summaryrefslogtreecommitdiffstats
path: root/third_party
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/src/tests/non262/Temporal/PlainDate/shell.js (renamed from third_party/rust/cssparser/docs/.nojekyll)0
-rw-r--r--third_party/aom/aom/aom_image.h36
-rw-r--r--third_party/aom/aom/src/aom_image.c43
-rw-r--r--third_party/aom/aom_dsp/aom_dsp.cmake3
-rwxr-xr-xthird_party/aom/aom_dsp/aom_dsp_rtcd_defs.pl2
-rw-r--r--third_party/aom/aom_dsp/arm/aom_convolve8_neon.c401
-rw-r--r--third_party/aom/aom_dsp/arm/aom_convolve8_neon_dotprod.c428
-rw-r--r--third_party/aom/aom_dsp/arm/aom_convolve8_neon_i8mm.c334
-rw-r--r--third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.c104
-rw-r--r--third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.h127
-rw-r--r--third_party/aom/aom_dsp/flow_estimation/arm/disflow_sve.c268
-rw-r--r--third_party/aom/aom_dsp/pyramid.c31
-rw-r--r--third_party/aom/aom_dsp/x86/synonyms.h1
-rw-r--r--third_party/aom/aom_util/aom_pthread.h1
-rw-r--r--third_party/aom/aom_util/aom_thread.h2
-rw-r--r--third_party/aom/av1/av1.cmake2
-rw-r--r--third_party/aom/av1/av1_cx_iface.c1
-rw-r--r--third_party/aom/av1/common/arm/compound_convolve_neon_dotprod.c55
-rw-r--r--third_party/aom/av1/common/arm/convolve_neon_dotprod.c49
-rw-r--r--third_party/aom/av1/common/av1_rtcd_defs.pl7
-rw-r--r--third_party/aom/av1/common/resize.c58
-rw-r--r--third_party/aom/av1/common/resize.h10
-rw-r--r--third_party/aom/av1/common/x86/resize_avx2.c411
-rw-r--r--third_party/aom/av1/encoder/arm/neon/highbd_pickrst_neon.c5
-rw-r--r--third_party/aom/av1/encoder/arm/neon/pickrst_sve.c590
-rw-r--r--third_party/aom/av1/encoder/enc_enums.h4
-rw-r--r--third_party/aom/av1/encoder/encodeframe.c4
-rw-r--r--third_party/aom/av1/encoder/encoder.h2
-rw-r--r--third_party/aom/av1/encoder/ethread.c7
-rw-r--r--third_party/aom/av1/encoder/global_motion.h7
-rw-r--r--third_party/aom/av1/encoder/nonrd_pickmode.c34
-rw-r--r--third_party/aom/av1/encoder/partition_search.c20
-rw-r--r--third_party/aom/av1/encoder/picklpf.c2
-rw-r--r--third_party/aom/av1/encoder/pickrst.c21
-rw-r--r--third_party/aom/av1/encoder/speed_features.c2
-rw-r--r--third_party/aom/av1/encoder/tune_vmaf.c4
-rw-r--r--third_party/aom/av1/encoder/x86/pickrst_avx2.c12
-rw-r--r--third_party/aom/av1/encoder/x86/pickrst_sse4.c18
-rw-r--r--third_party/aom/test/aom_image_test.cc65
-rw-r--r--third_party/aom/test/disflow_test.cc5
-rw-r--r--third_party/aom/test/ethread_test.cc5
-rw-r--r--third_party/aom/test/frame_resize_test.cc157
-rw-r--r--third_party/aom/test/test.cmake1
-rw-r--r--third_party/aom/test/wiener_test.cc61
-rw-r--r--third_party/dav1d/meson.build2
-rw-r--r--third_party/dav1d/meson_options.txt5
-rw-r--r--third_party/dav1d/src/arm/64/mc.S4
-rw-r--r--third_party/dav1d/src/arm/64/mc_dotprod.S1413
-rw-r--r--third_party/dav1d/src/arm/64/msac.S21
-rw-r--r--third_party/dav1d/src/arm/itx.h63
-rw-r--r--third_party/dav1d/src/arm/mc.h85
-rw-r--r--third_party/dav1d/src/cdf.c1378
-rw-r--r--third_party/dav1d/src/cdf.h48
-rw-r--r--third_party/dav1d/src/decode.c95
-rw-r--r--third_party/dav1d/src/internal.h9
-rw-r--r--third_party/dav1d/src/itx.h63
-rw-r--r--third_party/dav1d/src/lf_mask.c6
-rw-r--r--third_party/dav1d/src/meson.build1
-rw-r--r--third_party/dav1d/src/refmvs.c4
-rw-r--r--third_party/dav1d/src/riscv/itx.h63
-rw-r--r--third_party/dav1d/src/x86/ipred_avx2.asm3
-rw-r--r--third_party/dav1d/src/x86/itx.h64
-rw-r--r--third_party/dav1d/src/x86/mc16_avx2.asm1378
-rw-r--r--third_party/dav1d/src/x86/mc_avx2.asm1471
-rw-r--r--third_party/dav1d/src/x86/mc_avx512.asm2953
-rw-r--r--third_party/dav1d/tests/meson.build2
-rw-r--r--third_party/gemmology/gemmology.h9
-rw-r--r--third_party/gemmology/moz.yaml4
-rw-r--r--third_party/jpeg-xl/AUTHORS2
-rw-r--r--third_party/jpeg-xl/CMakeLists.txt12
-rw-r--r--third_party/jpeg-xl/examples/decode_progressive.cc8
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/apng.cc1226
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/apng.h3
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/color_description.cc38
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/decode.cc9
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/decode.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/gif.cc1
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jpg.cc3
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jxl.cc4
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/pnm.cc10
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/encode.cc8
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/encode.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpegli.cc4
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpg.cc7
-rw-r--r--third_party/jpeg-xl/lib/extras/jpegli_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/metrics.cc1
-rw-r--r--third_party/jpeg-xl/lib/extras/packed_image_convert.cc1
-rw-r--r--third_party/jpeg-xl/lib/include/jxl/color_encoding.h2
-rw-r--r--third_party/jpeg-xl/lib/jpegli/color_transform.cc316
-rw-r--r--third_party/jpeg-xl/lib/jpegli/common.h7
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode.cc49
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode.h1
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_api_test.cc24
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_internal.h4
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_marker.cc6
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode.cc40
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode.h1
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode_api_test.cc47
-rw-r--r--third_party/jpeg-xl/lib/jpegli/error_handling_test.cc22
-rw-r--r--third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc14
-rw-r--r--third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc7
-rw-r--r--third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc12
-rw-r--r--third_party/jpeg-xl/lib/jpegli/source_manager_test.cc3
-rw-r--r--third_party/jpeg-xl/lib/jpegli/streaming_test.cc10
-rw-r--r--third_party/jpeg-xl/lib/jpegli/test_utils.cc63
-rw-r--r--third_party/jpeg-xl/lib/jpegli/test_utils.h28
-rw-r--r--third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/ac_context.h11
-rw-r--r--third_party/jpeg-xl/lib/jxl/ac_strategy.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc8
-rw-r--r--third_party/jpeg-xl/lib/jxl/ans_common.h11
-rw-r--r--third_party/jpeg-xl/lib/jxl/ans_test.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/compiler_specific.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/exif.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/include_jpeglib.h20
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/matrix_ops.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/rect.h194
-rw-r--r--third_party/jpeg-xl/lib/jxl/base/span.h7
-rw-r--r--third_party/jpeg-xl/lib/jxl/bit_reader_test.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/bits_test.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/blending.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/blending.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc10
-rw-r--r--third_party/jpeg-xl/lib/jxl/cache_aligned.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/chroma_from_luma.h7
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h16
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/opsin_params.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/coeff_order.h17
-rw-r--r--third_party/jpeg-xl/lib/jxl/coeff_order_fwd.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/color_encoding_internal.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/color_management_test.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/compressed_dc.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/compressed_dc.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve-inl.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_separable5.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_slow.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/convolve_test.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/dct_for_test.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/dct_util.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_ans.h7
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_frame.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_group.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_group_border.cc7
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_group_border.h9
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_modular.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_modular.h11
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_noise.cc13
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_noise.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_transforms-inl.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_xyb.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/dec_xyb.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/decode_test.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_cache.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_cache.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_cluster.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_coeff_order.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_comparator.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_debug_image.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_debug_image.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_detect_dots.h7
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc12
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h11
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_fields.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_frame.cc22
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_gaborish.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_gaborish.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_group.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_group.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_heuristics.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_heuristics.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_image_bundle.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_modular.cc9
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_modular.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_photon_noise.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_quant_weights.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/enc_xyb.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/encode_internal.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/encode_test.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/epf.cc18
-rw-r--r--third_party/jpeg-xl/lib/jxl/epf.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/fake_parallel_runner_testonly.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/fields.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/fields.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/fields_test.cc11
-rw-r--r--third_party/jpeg-xl/lib/jxl/frame_dimensions.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/frame_header.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/icc_codec.h2
-rw-r--r--third_party/jpeg-xl/lib/jxl/image.h184
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_bundle.h5
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_metadata.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_ops.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_ops_test.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/image_test_utils.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/jxl_test.cc78
-rw-r--r--third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc7
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h10
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/options.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/palette.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/modular/transform/transform.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/opsin_image_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/passes_test.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/preview_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/quant_weights.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/quant_weights_test.cc7
-rw-r--r--third_party/jpeg-xl/lib/jxl/quantizer.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/quantizer.h14
-rw-r--r--third_party/jpeg-xl/lib/jxl/quantizer_test.cc8
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc7
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h9
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc4
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h12
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc6
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h7
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.h11
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc8
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h6
-rw-r--r--third_party/jpeg-xl/lib/jxl/roundtrip_test.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/sanitizers.h8
-rw-r--r--third_party/jpeg-xl/lib/jxl/speed_tier_test.cc2
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines.h1
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines_gbench.cc5
-rw-r--r--third_party/jpeg-xl/lib/jxl/splines_test.cc1
-rw-r--r--third_party/jpeg-xl/lib/jxl/test_image.cc3
-rw-r--r--third_party/jpeg-xl/lib/jxl/test_image.h3
-rw-r--r--third_party/jpeg-xl/lib/jxl/test_utils.h12
-rw-r--r--third_party/jpeg-xl/lib/jxl/xorshift128plus-inl.h4
-rw-r--r--third_party/jpeg-xl/lib/jxl_extras.cmake2
-rw-r--r--third_party/jpeg-xl/lib/jxl_lists.bzl2
-rw-r--r--third_party/jpeg-xl/lib/jxl_lists.cmake2
-rw-r--r--third_party/jpeg-xl/lib/jxl_tests.cmake2
-rw-r--r--third_party/jpeg-xl/lib/threads/thread_parallel_runner_test.cc3
-rw-r--r--third_party/libwebrtc/AUTHORS1
-rw-r--r--third_party/libwebrtc/DEPS120
-rw-r--r--third_party/libwebrtc/README.moz-ff-commit510
-rw-r--r--third_party/libwebrtc/README.mozilla340
-rw-r--r--third_party/libwebrtc/api/BUILD.gn25
-rw-r--r--third_party/libwebrtc/api/audio_codecs/BUILD.gn1
-rw-r--r--third_party/libwebrtc/api/audio_codecs/audio_encoder.h15
-rw-r--r--third_party/libwebrtc/api/candidate.cc32
-rw-r--r--third_party/libwebrtc/api/candidate.h22
-rw-r--r--third_party/libwebrtc/api/candidate_unittest.cc56
-rw-r--r--third_party/libwebrtc/api/crypto_params.h43
-rw-r--r--third_party/libwebrtc/api/frame_transformer_interface.h6
-rw-r--r--third_party/libwebrtc/api/neteq/neteq.cc3
-rw-r--r--third_party/libwebrtc/api/neteq/neteq.h31
-rw-r--r--third_party/libwebrtc/api/peer_connection_interface.h17
-rw-r--r--third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc3
-rw-r--r--third_party/libwebrtc/api/stats/attribute.h54
-rw-r--r--third_party/libwebrtc/api/stats/rtc_stats.h16
-rw-r--r--third_party/libwebrtc/api/stats/rtc_stats_member.h185
-rw-r--r--third_party/libwebrtc/api/stats/rtcstats_objects.h417
-rw-r--r--third_party/libwebrtc/api/test/mock_frame_transformer.h (renamed from third_party/libwebrtc/test/mock_frame_transformer.h)6
-rw-r--r--third_party/libwebrtc/api/test/mock_peerconnectioninterface.h4
-rw-r--r--third_party/libwebrtc/api/test/mock_video_decoder_factory.h13
-rw-r--r--third_party/libwebrtc/api/test/pclf/BUILD.gn2
-rw-r--r--third_party/libwebrtc/api/test/video/BUILD.gn1
-rw-r--r--third_party/libwebrtc/api/test/video/function_video_decoder_factory.h19
-rw-r--r--third_party/libwebrtc/api/transport/BUILD.gn6
-rw-r--r--third_party/libwebrtc/api/transport/bandwidth_estimation_settings.h27
-rw-r--r--third_party/libwebrtc/api/transport/bandwidth_estimation_settings_gn/moz.build198
-rw-r--r--third_party/libwebrtc/api/video_codecs/BUILD.gn5
-rw-r--r--third_party/libwebrtc/api/video_codecs/av1_profile.cc6
-rw-r--r--third_party/libwebrtc/api/video_codecs/av1_profile.h3
-rw-r--r--third_party/libwebrtc/api/video_codecs/sdp_video_format.cc42
-rw-r--r--third_party/libwebrtc/api/video_codecs/test/BUILD.gn3
-rw-r--r--third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc15
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_codec.cc30
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_codec.h4
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build1
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_decoder_factory.cc45
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_decoder_factory.h31
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h2
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc23
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h8
-rw-r--r--third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc18
-rw-r--r--third_party/libwebrtc/audio/BUILD.gn6
-rw-r--r--third_party/libwebrtc/audio/audio_send_stream.cc118
-rw-r--r--third_party/libwebrtc/audio/audio_send_stream.h28
-rw-r--r--third_party/libwebrtc/audio/audio_send_stream_unittest.cc71
-rw-r--r--third_party/libwebrtc/audio/channel_receive.cc7
-rw-r--r--third_party/libwebrtc/audio/channel_receive_frame_transformer_delegate_unittest.cc4
-rw-r--r--third_party/libwebrtc/audio/channel_receive_unittest.cc2
-rw-r--r--third_party/libwebrtc/audio/channel_send_frame_transformer_delegate.cc14
-rw-r--r--third_party/libwebrtc/audio/channel_send_frame_transformer_delegate_unittest.cc10
-rw-r--r--third_party/libwebrtc/audio/channel_send_unittest.cc2
-rw-r--r--third_party/libwebrtc/call/BUILD.gn3
-rw-r--r--third_party/libwebrtc/call/rtp_transport_controller_send.cc75
-rw-r--r--third_party/libwebrtc/call/rtp_transport_controller_send.h6
-rw-r--r--third_party/libwebrtc/call/rtp_transport_controller_send_interface.h11
-rw-r--r--third_party/libwebrtc/call/rtp_video_sender.cc88
-rw-r--r--third_party/libwebrtc/call/rtp_video_sender.h9
-rw-r--r--third_party/libwebrtc/call/rtp_video_sender_interface.h8
-rw-r--r--third_party/libwebrtc/call/rtp_video_sender_unittest.cc81
-rw-r--r--third_party/libwebrtc/call/test/mock_rtp_transport_controller_send.h9
-rw-r--r--third_party/libwebrtc/call/version.cc2
-rw-r--r--third_party/libwebrtc/call/video_send_stream.h19
-rw-r--r--third_party/libwebrtc/common_audio/wav_file_unittest.cc9
-rw-r--r--third_party/libwebrtc/common_video/h265/h265_bitstream_parser.cc3
-rw-r--r--third_party/libwebrtc/common_video/h265/h265_common.h10
-rw-r--r--third_party/libwebrtc/examples/BUILD.gn5
-rwxr-xr-xthird_party/libwebrtc/experiments/field_trials.py15
-rw-r--r--third_party/libwebrtc/infra/specs/client.webrtc.json620
-rw-r--r--third_party/libwebrtc/infra/specs/internal.client.webrtc.json120
-rw-r--r--third_party/libwebrtc/infra/specs/mixins.pyl21
-rw-r--r--third_party/libwebrtc/infra/specs/mixins_webrtc.pyl4
-rw-r--r--third_party/libwebrtc/infra/specs/test_suites.pyl2
-rw-r--r--third_party/libwebrtc/infra/specs/tryserver.webrtc.json708
-rw-r--r--third_party/libwebrtc/infra/specs/variants.pyl8
-rw-r--r--third_party/libwebrtc/infra/specs/waterfalls.pyl32
-rw-r--r--third_party/libwebrtc/logging/BUILD.gn6
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc11
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc37
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h10
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc177
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc8
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h15
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/ice_logger.cc3
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_impl.cc2
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.cc82
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.h9
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc56
-rw-r--r--third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h10
-rw-r--r--third_party/libwebrtc/media/BUILD.gn3
-rw-r--r--third_party/libwebrtc/media/base/codec_unittest.cc10
-rw-r--r--third_party/libwebrtc/media/base/media_constants.cc6
-rw-r--r--third_party/libwebrtc/media/base/media_constants.h6
-rw-r--r--third_party/libwebrtc/media/engine/fake_webrtc_call.cc11
-rw-r--r--third_party/libwebrtc/media/engine/fake_webrtc_call.h1
-rw-r--r--third_party/libwebrtc/media/engine/internal_decoder_factory.cc7
-rw-r--r--third_party/libwebrtc/media/engine/internal_decoder_factory_unittest.cc2
-rw-r--r--third_party/libwebrtc/media/engine/multiplex_codec_factory.cc17
-rw-r--r--third_party/libwebrtc/media/engine/multiplex_codec_factory.h5
-rw-r--r--third_party/libwebrtc/media/engine/multiplex_codec_factory_unittest.cc13
-rw-r--r--third_party/libwebrtc/media/engine/simulcast_encoder_adapter.cc16
-rw-r--r--third_party/libwebrtc/media/engine/webrtc_video_engine.cc41
-rw-r--r--third_party/libwebrtc/media/engine/webrtc_video_engine.h7
-rw-r--r--third_party/libwebrtc/media/engine/webrtc_video_engine_unittest.cc140
-rw-r--r--third_party/libwebrtc/media/engine/webrtc_voice_engine.cc4
-rw-r--r--third_party/libwebrtc/modules/audio_coding/BUILD.gn3
-rw-r--r--third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver.cc6
-rw-r--r--third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc59
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc10
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h4
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc5
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h2
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc23
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h3
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc5
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h2
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/background_noise.cc29
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/background_noise.h4
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/decision_logic.cc14
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/decision_logic_unittest.cc13
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/mock/mock_packet_arrival_history.h9
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc140
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.h15
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/neteq_unittest.cc9
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.cc131
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.h79
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history_unittest.cc50
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.cc90
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.h71
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad_unittest.cc25
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.cc2
-rw-r--r--third_party/libwebrtc/modules/audio_coding/neteq_gn/moz.build1
-rw-r--r--third_party/libwebrtc/modules/audio_device/include/test_audio_device_unittest.cc20
-rw-r--r--third_party/libwebrtc/modules/audio_processing/agc2/input_volume_controller.h2
-rw-r--r--third_party/libwebrtc/modules/audio_processing/audio_processing_impl.cc2
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc3
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc11
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h2
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc36
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc31
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h3
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller_unittest.cc36
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc8
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h1
-rw-r--r--third_party/libwebrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc10
-rw-r--r--third_party/libwebrtc/modules/pacing/bitrate_prober.cc32
-rw-r--r--third_party/libwebrtc/modules/pacing/bitrate_prober.h6
-rw-r--r--third_party/libwebrtc/modules/pacing/pacing_controller.cc4
-rw-r--r--third_party/libwebrtc/modules/pacing/pacing_controller.h3
-rw-r--r--third_party/libwebrtc/modules/pacing/pacing_controller_unittest.cc41
-rw-r--r--third_party/libwebrtc/modules/pacing/packet_router.cc10
-rw-r--r--third_party/libwebrtc/modules/pacing/packet_router.h2
-rw-r--r--third_party/libwebrtc/modules/pacing/packet_router_unittest.cc25
-rw-r--r--third_party/libwebrtc/modules/pacing/task_queue_paced_sender.cc5
-rw-r--r--third_party/libwebrtc/modules/pacing/task_queue_paced_sender.h3
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/BUILD.gn12
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc8
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/frame_transformer_factory_unittest.cc2
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packet_h265_common.h54
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265.cc58
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265_unittest.cc91
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate_unittest.cc2
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc2
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc2
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc244
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h28
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265_unittest.cc400
-rw-r--r--third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc46
-rw-r--r--third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.h8
-rw-r--r--third_party/libwebrtc/modules/video_coding/BUILD.gn26
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder.cc18
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc25
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc1
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h5
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/multiplex/multiplex_decoder_adapter.cc7
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/multiplex/test/multiplex_adapter_unittest.cc12
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc20
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc8
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc6
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp8/include/vp8.h5
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc30
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.h6
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_simulcast_test.cc4
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc3
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc48
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h8
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config.cc3
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config_unittest.cc20
-rw-r--r--third_party/libwebrtc/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc109
-rw-r--r--third_party/libwebrtc/modules/video_coding/h264_packet_buffer.cc287
-rw-r--r--third_party/libwebrtc/modules/video_coding/h264_packet_buffer.h56
-rw-r--r--third_party/libwebrtc/modules/video_coding/h264_packet_buffer_unittest.cc778
-rw-r--r--third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.cc337
-rw-r--r--third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.h57
-rw-r--r--third_party/libwebrtc/modules/video_coding/h26x_packet_buffer_unittest.cc1058
-rw-r--r--third_party/libwebrtc/modules/video_coding/include/video_error_codes.h4
-rw-r--r--third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.cc46
-rw-r--r--third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.h22
-rw-r--r--third_party/libwebrtc/modules/video_coding/utility/simulcast_test_fixture_impl.cc5
-rw-r--r--third_party/libwebrtc/modules/video_coding/video_codec_initializer_unittest.cc21
-rw-r--r--third_party/libwebrtc/modules/video_coding/video_codec_interface_gn/moz.build1
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0001.patch14
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0012.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0013.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0021.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0023.patch6
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0030.patch84
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0032.patch11
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0033.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0034.patch26
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0042.patch8
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0044.patch6
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0050.patch6
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0052.patch12
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0054.patch2
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0059.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0061.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0064.patch2
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0066.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0068.patch6
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0069.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0070.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0071.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0075.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0076.patch2
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0081.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0085.patch4
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0086.patch2
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0091.patch115
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0092.patch54
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0093.patch62
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0094.patch55
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0095.patch44
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0096.patch35385
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0097.patch35372
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0098.patch78
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0099.patch88
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0100.patch145
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0101.patch212
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0102.patch134
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0103.patch101
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0104.patch80
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0105.patch136
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0106.patch301
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0107.patch55
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0108.patch27
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0109.patch243
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0110.patch207
-rw-r--r--third_party/libwebrtc/moz-patch-stack/541f202354.no-op-cherry-pick-msg1
-rw-r--r--third_party/libwebrtc/moz-patch-stack/74a4038ead.no-op-cherry-pick-msg1
-rw-r--r--third_party/libwebrtc/moz-patch-stack/958c9ac546.no-op-cherry-pick-msg1
-rw-r--r--third_party/libwebrtc/moz-patch-stack/de3c726121.no-op-cherry-pick-msg1
-rw-r--r--third_party/libwebrtc/moz.build1
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.cc28
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.h16
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter_test.cc19
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc4
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc26
-rw-r--r--third_party/libwebrtc/net/dcsctp/public/dcsctp_options.h15
-rw-r--r--third_party/libwebrtc/net/dcsctp/public/types.h21
-rw-r--r--third_party/libwebrtc/net/dcsctp/socket/capabilities.h2
-rw-r--r--third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket.cc25
-rw-r--r--third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket_test.cc36
-rw-r--r--third_party/libwebrtc/net/dcsctp/socket/heartbeat_handler_test.cc3
-rw-r--r--third_party/libwebrtc/p2p/BUILD.gn1029
-rw-r--r--third_party/libwebrtc/p2p/base/basic_ice_controller.cc4
-rw-r--r--third_party/libwebrtc/p2p/base/basic_ice_controller.h1
-rw-r--r--third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc6
-rw-r--r--third_party/libwebrtc/p2p/base/candidate_pair_interface.h12
-rw-r--r--third_party/libwebrtc/p2p/base/connection.cc54
-rw-r--r--third_party/libwebrtc/p2p/base/connection.h44
-rw-r--r--third_party/libwebrtc/p2p/base/fake_port_allocator.h5
-rw-r--r--third_party/libwebrtc/p2p/base/p2p_constants.h15
-rw-r--r--third_party/libwebrtc/p2p/base/p2p_transport_channel.cc13
-rw-r--r--third_party/libwebrtc/p2p/base/p2p_transport_channel.h6
-rw-r--r--third_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc283
-rw-r--r--third_party/libwebrtc/p2p/base/port.cc39
-rw-r--r--third_party/libwebrtc/p2p/base/port.h81
-rw-r--r--third_party/libwebrtc/p2p/base/port_allocator.cc16
-rw-r--r--third_party/libwebrtc/p2p/base/port_allocator.h20
-rw-r--r--third_party/libwebrtc/p2p/base/port_allocator_unittest.cc5
-rw-r--r--third_party/libwebrtc/p2p/base/port_interface.h75
-rw-r--r--third_party/libwebrtc/p2p/base/port_unittest.cc11
-rw-r--r--third_party/libwebrtc/p2p/base/regathering_controller_unittest.cc2
-rw-r--r--third_party/libwebrtc/p2p/base/stun_port_unittest.cc2
-rw-r--r--third_party/libwebrtc/p2p/base/tcp_port.cc3
-rw-r--r--third_party/libwebrtc/p2p/base/transport_description.h11
-rw-r--r--third_party/libwebrtc/p2p/base/transport_description_factory.cc92
-rw-r--r--third_party/libwebrtc/p2p/base/transport_description_factory.h15
-rw-r--r--third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc112
-rw-r--r--third_party/libwebrtc/p2p/base/turn_port.cc1
-rw-r--r--third_party/libwebrtc/p2p/base/turn_port.h3
-rw-r--r--third_party/libwebrtc/p2p/client/basic_port_allocator.cc8
-rw-r--r--third_party/libwebrtc/p2p/client/basic_port_allocator_unittest.cc48
-rw-r--r--third_party/libwebrtc/pc/BUILD.gn154
-rw-r--r--third_party/libwebrtc/pc/dtls_srtp_transport.h1
-rw-r--r--third_party/libwebrtc/pc/jsep_transport.cc75
-rw-r--r--third_party/libwebrtc/pc/jsep_transport.h10
-rw-r--r--third_party/libwebrtc/pc/jsep_transport_controller.cc20
-rw-r--r--third_party/libwebrtc/pc/jsep_transport_controller.h2
-rw-r--r--third_party/libwebrtc/pc/jsep_transport_unittest.cc171
-rw-r--r--third_party/libwebrtc/pc/media_session.cc428
-rw-r--r--third_party/libwebrtc/pc/media_session.h5
-rw-r--r--third_party/libwebrtc/pc/media_session_unittest.cc482
-rw-r--r--third_party/libwebrtc/pc/peer_connection.cc100
-rw-r--r--third_party/libwebrtc/pc/peer_connection.h2
-rw-r--r--third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc284
-rw-r--r--third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc89
-rw-r--r--third_party/libwebrtc/pc/peer_connection_ice_unittest.cc4
-rw-r--r--third_party/libwebrtc/pc/peer_connection_integrationtest.cc34
-rw-r--r--third_party/libwebrtc/pc/peer_connection_interface_unittest.cc49
-rw-r--r--third_party/libwebrtc/pc/peer_connection_proxy.h4
-rw-r--r--third_party/libwebrtc/pc/rtc_stats_collector.cc26
-rw-r--r--third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc5
-rw-r--r--third_party/libwebrtc/pc/rtc_stats_integrationtest.cc17
-rw-r--r--third_party/libwebrtc/pc/rtc_stats_traversal.cc3
-rw-r--r--third_party/libwebrtc/pc/rtp_receiver.cc5
-rw-r--r--third_party/libwebrtc/pc/rtp_transceiver.cc29
-rw-r--r--third_party/libwebrtc/pc/rtp_transceiver_unittest.cc75
-rw-r--r--third_party/libwebrtc/pc/sdp_offer_answer.cc25
-rw-r--r--third_party/libwebrtc/pc/session_description.h9
-rw-r--r--third_party/libwebrtc/pc/srtp_filter.cc280
-rw-r--r--third_party/libwebrtc/pc/srtp_filter.h147
-rw-r--r--third_party/libwebrtc/pc/srtp_filter_unittest.cc472
-rw-r--r--third_party/libwebrtc/pc/srtp_transport.h3
-rw-r--r--third_party/libwebrtc/pc/test/fake_peer_connection_base.h3
-rw-r--r--third_party/libwebrtc/pc/test/mock_peer_connection_internal.h4
-rw-r--r--third_party/libwebrtc/pc/test/svc_e2e_tests.cc3
-rw-r--r--third_party/libwebrtc/pc/used_ids.h11
-rw-r--r--third_party/libwebrtc/pc/used_ids_unittest.cc9
-rw-r--r--third_party/libwebrtc/pc/webrtc_sdp.cc95
-rw-r--r--third_party/libwebrtc/pc/webrtc_sdp_unittest.cc313
-rw-r--r--third_party/libwebrtc/pc/webrtc_session_description_factory.cc65
-rw-r--r--third_party/libwebrtc/pc/webrtc_session_description_factory.h7
-rw-r--r--third_party/libwebrtc/rtc_base/BUILD.gn5
-rw-r--r--third_party/libwebrtc/rtc_base/ip_address.h4
-rw-r--r--third_party/libwebrtc/rtc_base/nat_server.cc16
-rw-r--r--third_party/libwebrtc/rtc_base/nat_socket_factory.cc58
-rw-r--r--third_party/libwebrtc/rtc_base/nat_socket_factory.h6
-rw-r--r--third_party/libwebrtc/rtc_base/nat_unittest.cc10
-rw-r--r--third_party/libwebrtc/rtc_base/physical_socket_server.cc25
-rw-r--r--third_party/libwebrtc/rtc_base/physical_socket_server.h2
-rw-r--r--third_party/libwebrtc/rtc_base/proxy_server.cc4
-rw-r--r--third_party/libwebrtc/rtc_base/proxy_server.h16
-rw-r--r--third_party/libwebrtc/rtc_base/proxy_unittest.cc68
-rw-r--r--third_party/libwebrtc/rtc_base/server_socket_adapters.cc131
-rw-r--r--third_party/libwebrtc/rtc_base/server_socket_adapters.h34
-rw-r--r--third_party/libwebrtc/rtc_base/socket.h11
-rw-r--r--third_party/libwebrtc/rtc_base/socket_adapters.cc194
-rw-r--r--third_party/libwebrtc/rtc_base/socket_adapters.h36
-rw-r--r--third_party/libwebrtc/rtc_base/socket_unittest.cc14
-rw-r--r--third_party/libwebrtc/rtc_base/system/file_wrapper_unittest.cc3
-rw-r--r--third_party/libwebrtc/rtc_tools/network_tester/BUILD.gn1
-rw-r--r--third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/converter.cc8
-rw-r--r--third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer.cc32
-rw-r--r--third_party/libwebrtc/sdk/BUILD.gn15
-rw-r--r--third_party/libwebrtc/sdk/android/api/org/webrtc/Dav1dDecoder.java2
-rw-r--r--third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp8Decoder.java6
-rw-r--r--third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp9Decoder.java2
-rw-r--r--third_party/libwebrtc/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java14
-rw-r--r--third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoder.java6
-rw-r--r--third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoderFallback.java7
-rw-r--r--third_party/libwebrtc/sdk/android/api/org/webrtc/WrappedNativeVideoDecoder.java2
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h13
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm29
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h32
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.h31
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.mm60
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h33
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.h58
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm116
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability+Private.h34
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h33
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.mm56
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.h7
-rw-r--r--third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm11
-rw-r--r--third_party/libwebrtc/sdk/objc/unittests/RTCPeerConnectionFactory_xctest.m193
-rw-r--r--third_party/libwebrtc/stats/BUILD.gn4
-rw-r--r--third_party/libwebrtc/stats/attribute.cc19
-rw-r--r--third_party/libwebrtc/stats/rtc_stats_member.cc62
-rw-r--r--third_party/libwebrtc/stats/rtc_stats_report_unittest.cc7
-rw-r--r--third_party/libwebrtc/stats/rtc_stats_unittest.cc101
-rw-r--r--third_party/libwebrtc/stats/test/rtc_test_stats.h33
-rw-r--r--third_party/libwebrtc/test/BUILD.gn26
-rw-r--r--third_party/libwebrtc/test/call_test.cc4
-rw-r--r--third_party/libwebrtc/test/fuzzers/BUILD.gn6
-rw-r--r--third_party/libwebrtc/test/fuzzers/h265_depacketizer_fuzzer.cc19
-rw-r--r--third_party/libwebrtc/test/fuzzers/neteq_signal_fuzzer.cc1
-rw-r--r--third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc150
-rw-r--r--third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc146
-rw-r--r--third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc146
-rw-r--r--third_party/libwebrtc/test/mock_audio_encoder.h4
-rw-r--r--third_party/libwebrtc/test/mock_transformable_frame.h41
-rw-r--r--third_party/libwebrtc/test/network/BUILD.gn3
-rw-r--r--third_party/libwebrtc/test/pc/e2e/BUILD.gn2
-rw-r--r--third_party/libwebrtc/test/pc/e2e/analyzer/video/BUILD.gn1
-rw-r--r--third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.cc6
-rw-r--r--third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h5
-rw-r--r--third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc10
-rw-r--r--third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.h2
-rw-r--r--third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc5
-rw-r--r--third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc10
-rw-r--r--third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.h3
-rw-r--r--third_party/libwebrtc/test/peer_scenario/BUILD.gn2
-rw-r--r--third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc12
-rw-r--r--third_party/libwebrtc/test/peer_scenario/peer_scenario_client.h1
-rw-r--r--third_party/libwebrtc/test/peer_scenario/signaling_route.cc39
-rw-r--r--third_party/libwebrtc/test/peer_scenario/signaling_route.h17
-rw-r--r--third_party/libwebrtc/test/peer_scenario/tests/bwe_ramp_up_test.cc150
-rw-r--r--third_party/libwebrtc/test/peer_scenario/tests/unsignaled_stream_test.cc1
-rw-r--r--third_party/libwebrtc/test/scenario/video_stream.cc4
-rw-r--r--third_party/libwebrtc/test/testsupport/file_utils.cc17
-rw-r--r--third_party/libwebrtc/test/testsupport/file_utils.h5
-rw-r--r--third_party/libwebrtc/test/testsupport/file_utils_unittest.cc38
-rw-r--r--third_party/libwebrtc/test/testsupport/test_artifacts.cc9
-rw-r--r--third_party/libwebrtc/test/video_codec_tester.cc177
-rw-r--r--third_party/libwebrtc/test/video_codec_tester.h2
-rw-r--r--third_party/libwebrtc/test/video_codec_tester_unittest.cc195
-rw-r--r--third_party/libwebrtc/video/BUILD.gn3
-rw-r--r--third_party/libwebrtc/video/end_to_end_tests/codec_tests.cc12
-rw-r--r--third_party/libwebrtc/video/end_to_end_tests/multi_codec_receive_tests.cc3
-rw-r--r--third_party/libwebrtc/video/rtp_video_stream_receiver2.cc21
-rw-r--r--third_party/libwebrtc/video/rtp_video_stream_receiver2_unittest.cc2
-rw-r--r--third_party/libwebrtc/video/video_quality_test.cc12
-rw-r--r--third_party/libwebrtc/video/video_quality_test.h2
-rw-r--r--third_party/libwebrtc/video/video_receive_stream2.cc2
-rw-r--r--third_party/libwebrtc/video/video_receive_stream2_unittest.cc14
-rw-r--r--third_party/libwebrtc/video/video_send_stream_impl.cc70
-rw-r--r--third_party/libwebrtc/video/video_send_stream_impl.h5
-rw-r--r--third_party/libwebrtc/video/video_send_stream_impl_unittest.cc250
-rw-r--r--third_party/libwebrtc/video/video_stream_encoder.cc55
-rw-r--r--third_party/moz.build2
-rw-r--r--third_party/perfetto/LICENSE189
-rw-r--r--third_party/perfetto/moz.build19
-rw-r--r--third_party/perfetto/moz.yaml44
-rw-r--r--third_party/perfetto/moz_attributes.patch31
-rw-r--r--third_party/perfetto/sdk/perfetto.cc64804
-rw-r--r--third_party/perfetto/sdk/perfetto.h164605
-rw-r--r--third_party/python/glean_parser/glean_parser-13.0.1.dist-info/METADATA790
-rw-r--r--third_party/python/glean_parser/glean_parser-13.0.1.dist-info/RECORD48
-rw-r--r--third_party/python/glean_parser/glean_parser-14.0.1.dist-info/AUTHORS.md (renamed from third_party/python/glean_parser/glean_parser-13.0.1.dist-info/AUTHORS.md)0
-rw-r--r--third_party/python/glean_parser/glean_parser-14.0.1.dist-info/LICENSE (renamed from third_party/python/glean_parser/glean_parser-13.0.1.dist-info/LICENSE)0
-rw-r--r--third_party/python/glean_parser/glean_parser-14.0.1.dist-info/METADATA799
-rw-r--r--third_party/python/glean_parser/glean_parser-14.0.1.dist-info/RECORD48
-rw-r--r--third_party/python/glean_parser/glean_parser-14.0.1.dist-info/WHEEL (renamed from third_party/python/glean_parser/glean_parser-13.0.1.dist-info/WHEEL)0
-rw-r--r--third_party/python/glean_parser/glean_parser-14.0.1.dist-info/entry_points.txt (renamed from third_party/python/glean_parser/glean_parser-13.0.1.dist-info/entry_points.txt)0
-rw-r--r--third_party/python/glean_parser/glean_parser-14.0.1.dist-info/top_level.txt (renamed from third_party/python/glean_parser/glean_parser-13.0.1.dist-info/top_level.txt)0
-rw-r--r--third_party/python/glean_parser/glean_parser/javascript_server.py16
-rw-r--r--third_party/python/glean_parser/glean_parser/kotlin.py25
-rw-r--r--third_party/python/glean_parser/glean_parser/parser.py24
-rw-r--r--third_party/python/glean_parser/glean_parser/pings.py6
-rw-r--r--third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml22
-rw-r--r--third_party/python/glean_parser/glean_parser/swift.py23
-rw-r--r--third_party/python/glean_parser/glean_parser/templates/javascript_server.jinja254
-rw-r--r--third_party/python/glean_parser/glean_parser/templates/kotlin.jinja266
-rw-r--r--third_party/python/glean_parser/glean_parser/templates/rust.jinja22
-rw-r--r--third_party/python/glean_parser/glean_parser/templates/swift.jinja249
-rw-r--r--third_party/python/glean_parser/glean_parser/util.py2
-rw-r--r--third_party/python/poetry.lock15
-rw-r--r--third_party/python/requirements.in4
-rw-r--r--third_party/python/requirements.txt13
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/METADATA28
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/RECORD80
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/WHEEL5
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/LICENSE (renamed from third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/LICENSE)0
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/METADATA123
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/RECORD79
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/WHEEL5
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/entry_points.txt (renamed from third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/entry_points.txt)0
-rw-r--r--third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/top_level.txt (renamed from third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/top_level.txt)0
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/__init__.py2
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/actions/add_new_jobs.py2
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel.py4
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel_all.py4
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/actions/rebuild_cached_tasks.py2
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/actions/registry.py34
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/actions/retrigger.py26
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/actions/util.py15
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/config.py20
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/create.py2
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/decision.py23
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/docker.py48
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/files_changed.py91
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/generator.py8
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/loader/default.py4
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/main.py83
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/morph.py1
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/optimize/base.py12
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/optimize/strategies.py16
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/parameters.py5
-rwxr-xr-xthird_party/python/taskcluster_taskgraph/taskgraph/run-task/run-task14
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/target_tasks.py8
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/__init__.py3
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/base.py2
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/code_review.py10
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/docker_image.py16
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/fetch.py65
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/from_deps.py21
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/__init__.py453
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/common.py171
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/__init__.py451
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/common.py165
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/index_search.py (renamed from third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/index_search.py)8
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/run_task.py (renamed from third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/run_task.py)36
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/toolchain.py (renamed from third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/toolchain.py)38
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/task.py61
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/transforms/task_context.py10
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/archive.py52
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/cached_tasks.py45
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/decision.py79
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/docker.py21
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/hash.py11
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/keyed_by.py16
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/memoize.py35
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/parameterization.py21
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/schema.py12
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/set_name.py34
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/shell.py2
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/taskcluster.py71
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/time.py4
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/treeherder.py15
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/vcs.py36
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/verify.py27
-rw-r--r--third_party/python/taskcluster_taskgraph/taskgraph/util/yaml.py5
-rw-r--r--third_party/rust/ahash/.cargo-checksum.json2
-rw-r--r--third_party/rust/ahash/Cargo.toml74
-rw-r--r--third_party/rust/ahash/LICENSE-MIT2
-rw-r--r--third_party/rust/ahash/README.md19
-rw-r--r--third_party/rust/ahash/build.rs31
-rw-r--r--third_party/rust/ahash/src/aes_hash.rs65
-rw-r--r--third_party/rust/ahash/src/convert.rs11
-rw-r--r--third_party/rust/ahash/src/fallback_hash.rs51
-rw-r--r--third_party/rust/ahash/src/hash_map.rs150
-rw-r--r--third_party/rust/ahash/src/hash_quality_test.rs95
-rw-r--r--third_party/rust/ahash/src/hash_set.rs65
-rw-r--r--third_party/rust/ahash/src/lib.rs243
-rw-r--r--third_party/rust/ahash/src/operations.rs98
-rw-r--r--third_party/rust/ahash/src/random_state.rs511
-rw-r--r--third_party/rust/ahash/src/specialize.rs23
-rw-r--r--third_party/rust/ahash/tests/bench.rs205
-rw-r--r--third_party/rust/ahash/tests/map_tests.rs115
-rw-r--r--third_party/rust/ahash/tests/nopanic.rs35
-rw-r--r--third_party/rust/any_all_workaround/.cargo-checksum.json1
-rw-r--r--third_party/rust/any_all_workaround/Cargo.toml28
-rw-r--r--third_party/rust/any_all_workaround/LICENSE-APACHE (renamed from third_party/rust/packed_simd/LICENSE-APACHE)0
-rw-r--r--third_party/rust/any_all_workaround/LICENSE-MIT (renamed from third_party/rust/packed_simd/LICENSE-MIT)0
-rw-r--r--third_party/rust/any_all_workaround/LICENSE-MIT-QCMS21
-rw-r--r--third_party/rust/any_all_workaround/README.md13
-rw-r--r--third_party/rust/any_all_workaround/build.rs7
-rw-r--r--third_party/rust/any_all_workaround/src/lib.rs110
-rw-r--r--third_party/rust/audio-mixer/.cargo-checksum.json2
-rw-r--r--third_party/rust/audio-mixer/Cargo.lock207
-rw-r--r--third_party/rust/audio-mixer/Cargo.toml2
-rw-r--r--third_party/rust/audio-mixer/src/channel.rs4
-rw-r--r--third_party/rust/audio-mixer/src/coefficient.rs239
-rw-r--r--third_party/rust/bindgen/clang.rs2
-rw-r--r--third_party/rust/bitflags/.cargo-checksum.json2
-rw-r--r--third_party/rust/bitflags/CHANGELOG.md26
-rw-r--r--third_party/rust/bitflags/Cargo.lock165
-rw-r--r--third_party/rust/bitflags/Cargo.toml6
-rw-r--r--third_party/rust/bitflags/README.md2
-rw-r--r--third_party/rust/bitflags/src/external.rs24
-rw-r--r--third_party/rust/bitflags/src/internal.rs10
-rw-r--r--third_party/rust/bitflags/src/lib.rs46
-rw-r--r--third_party/rust/bitflags/src/parser.rs85
-rw-r--r--third_party/rust/bitflags/src/public.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/all.rs23
-rw-r--r--third_party/rust/bitflags/src/tests/bits.rs36
-rw-r--r--third_party/rust/bitflags/src/tests/complement.rs53
-rw-r--r--third_party/rust/bitflags/src/tests/contains.rs108
-rw-r--r--third_party/rust/bitflags/src/tests/difference.rs92
-rw-r--r--third_party/rust/bitflags/src/tests/empty.rs23
-rw-r--r--third_party/rust/bitflags/src/tests/eq.rs10
-rw-r--r--third_party/rust/bitflags/src/tests/extend.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/flags.rs46
-rw-r--r--third_party/rust/bitflags/src/tests/fmt.rs97
-rw-r--r--third_party/rust/bitflags/src/tests/from_bits.rs45
-rw-r--r--third_party/rust/bitflags/src/tests/from_bits_retain.rs38
-rw-r--r--third_party/rust/bitflags/src/tests/from_bits_truncate.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/from_name.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/insert.rs91
-rw-r--r--third_party/rust/bitflags/src/tests/intersection.rs79
-rw-r--r--third_party/rust/bitflags/src/tests/intersects.rs91
-rw-r--r--third_party/rust/bitflags/src/tests/is_all.rs32
-rw-r--r--third_party/rust/bitflags/src/tests/is_empty.rs31
-rw-r--r--third_party/rust/bitflags/src/tests/iter.rs209
-rw-r--r--third_party/rust/bitflags/src/tests/parser.rs332
-rw-r--r--third_party/rust/bitflags/src/tests/remove.rs100
-rw-r--r--third_party/rust/bitflags/src/tests/symmetric_difference.rs110
-rw-r--r--third_party/rust/bitflags/src/tests/union.rs71
-rw-r--r--third_party/rust/bitflags/src/traits.rs1
-rw-r--r--third_party/rust/byteorder/.cargo-checksum.json2
-rw-r--r--third_party/rust/byteorder/CHANGELOG.md4
-rw-r--r--third_party/rust/byteorder/Cargo.toml31
-rw-r--r--third_party/rust/byteorder/README.md16
-rw-r--r--third_party/rust/byteorder/benches/bench.rs2
-rw-r--r--third_party/rust/byteorder/src/lib.rs231
-rw-r--r--third_party/rust/core-foundation-sys/.cargo-checksum.json2
-rw-r--r--third_party/rust/core-foundation-sys/Cargo.toml19
-rw-r--r--third_party/rust/core-foundation-sys/build.rs14
-rw-r--r--third_party/rust/core-foundation-sys/src/array.rs119
-rw-r--r--third_party/rust/core-foundation-sys/src/attributed_string.rs99
-rw-r--r--third_party/rust/core-foundation-sys/src/bag.rs101
-rw-r--r--third_party/rust/core-foundation-sys/src/base.rs88
-rw-r--r--third_party/rust/core-foundation-sys/src/binary_heap.rs83
-rw-r--r--third_party/rust/core-foundation-sys/src/bit_vector.rs74
-rw-r--r--third_party/rust/core-foundation-sys/src/bundle.rs215
-rw-r--r--third_party/rust/core-foundation-sys/src/calendar.rs128
-rw-r--r--third_party/rust/core-foundation-sys/src/characterset.rs102
-rw-r--r--third_party/rust/core-foundation-sys/src/data.rs59
-rw-r--r--third_party/rust/core-foundation-sys/src/date.rs10
-rw-r--r--third_party/rust/core-foundation-sys/src/date_formatter.rs147
-rw-r--r--third_party/rust/core-foundation-sys/src/dictionary.rs124
-rw-r--r--third_party/rust/core-foundation-sys/src/error.rs38
-rw-r--r--third_party/rust/core-foundation-sys/src/file_security.rs71
-rw-r--r--third_party/rust/core-foundation-sys/src/filedescriptor.rs56
-rw-r--r--third_party/rust/core-foundation-sys/src/lib.rs48
-rw-r--r--third_party/rust/core-foundation-sys/src/locale.rs146
-rw-r--r--third_party/rust/core-foundation-sys/src/mach_port.rs63
-rw-r--r--third_party/rust/core-foundation-sys/src/messageport.rs123
-rw-r--r--third_party/rust/core-foundation-sys/src/notification_center.rs89
-rw-r--r--third_party/rust/core-foundation-sys/src/number.rs74
-rw-r--r--third_party/rust/core-foundation-sys/src/number_formatter.rs163
-rw-r--r--third_party/rust/core-foundation-sys/src/plugin.rs99
-rw-r--r--third_party/rust/core-foundation-sys/src/preferences.rs103
-rw-r--r--third_party/rust/core-foundation-sys/src/propertylist.rs102
-rw-r--r--third_party/rust/core-foundation-sys/src/runloop.rs220
-rw-r--r--third_party/rust/core-foundation-sys/src/set.rs64
-rw-r--r--third_party/rust/core-foundation-sys/src/socket.rs188
-rw-r--r--third_party/rust/core-foundation-sys/src/stream.rs281
-rw-r--r--third_party/rust/core-foundation-sys/src/string.rs757
-rw-r--r--third_party/rust/core-foundation-sys/src/string_tokenizer.rs91
-rw-r--r--third_party/rust/core-foundation-sys/src/timezone.rs76
-rw-r--r--third_party/rust/core-foundation-sys/src/tree.rs74
-rw-r--r--third_party/rust/core-foundation-sys/src/url.rs468
-rw-r--r--third_party/rust/core-foundation-sys/src/url_enumerator.rs62
-rw-r--r--third_party/rust/core-foundation-sys/src/user_notification.rs138
-rw-r--r--third_party/rust/core-foundation-sys/src/uuid.rs74
-rw-r--r--third_party/rust/core-foundation-sys/src/xml_node.rs147
-rw-r--r--third_party/rust/core-foundation-sys/src/xml_parser.rs174
-rw-r--r--third_party/rust/core-foundation/.cargo-checksum.json2
-rw-r--r--third_party/rust/core-foundation/Cargo.toml19
-rw-r--r--third_party/rust/core-foundation/src/array.rs97
-rw-r--r--third_party/rust/core-foundation/src/attributed_string.rs51
-rw-r--r--third_party/rust/core-foundation/src/base.rs84
-rw-r--r--third_party/rust/core-foundation/src/boolean.rs17
-rw-r--r--third_party/rust/core-foundation/src/bundle.rs65
-rw-r--r--third_party/rust/core-foundation/src/characterset.rs4
-rw-r--r--third_party/rust/core-foundation/src/data.rs53
-rw-r--r--third_party/rust/core-foundation/src/date.rs25
-rw-r--r--third_party/rust/core-foundation/src/dictionary.rs204
-rw-r--r--third_party/rust/core-foundation/src/error.rs15
-rw-r--r--third_party/rust/core-foundation/src/filedescriptor.rs90
-rw-r--r--third_party/rust/core-foundation/src/lib.rs24
-rw-r--r--third_party/rust/core-foundation/src/mach_port.rs13
-rw-r--r--third_party/rust/core-foundation/src/number.rs54
-rw-r--r--third_party/rust/core-foundation/src/propertylist.rs109
-rw-r--r--third_party/rust/core-foundation/src/runloop.rs128
-rw-r--r--third_party/rust/core-foundation/src/set.rs32
-rw-r--r--third_party/rust/core-foundation/src/string.rs100
-rw-r--r--third_party/rust/core-foundation/src/timezone.rs25
-rw-r--r--third_party/rust/core-foundation/src/url.rs75
-rw-r--r--third_party/rust/core-foundation/src/uuid.rs32
-rw-r--r--third_party/rust/core-graphics-types/.cargo-checksum.json2
-rw-r--r--third_party/rust/core-graphics-types/Cargo.toml10
-rw-r--r--third_party/rust/core-graphics-types/LICENSE-APACHE201
-rw-r--r--third_party/rust/core-graphics-types/LICENSE-MIT25
-rw-r--r--third_party/rust/core-graphics-types/src/base.rs4
-rw-r--r--third_party/rust/core-graphics-types/src/geometry.rs67
-rw-r--r--third_party/rust/core-graphics-types/src/lib.rs2
-rw-r--r--third_party/rust/cssparser-macros/.cargo-checksum.json2
-rw-r--r--third_party/rust/cssparser-macros/Cargo.toml4
-rw-r--r--third_party/rust/cssparser/.cargo-checksum.json2
-rw-r--r--third_party/rust/cssparser/.github/workflows/main.yml78
-rw-r--r--third_party/rust/cssparser/Cargo.toml41
-rw-r--r--third_party/rust/cssparser/README.md4
-rw-r--r--third_party/rust/cssparser/src/color.rs63
-rw-r--r--third_party/rust/cssparser/src/cow_rc_str.rs6
-rw-r--r--third_party/rust/cssparser/src/macros.rs4
-rw-r--r--third_party/rust/cssparser/src/nth.rs18
-rw-r--r--third_party/rust/cssparser/src/parser.rs56
-rw-r--r--third_party/rust/cssparser/src/rules_and_declarations.rs87
-rw-r--r--third_party/rust/cssparser/src/serializer.rs36
-rw-r--r--third_party/rust/cssparser/src/tests.rs74
-rw-r--r--third_party/rust/cssparser/src/tokenizer.rs86
-rw-r--r--third_party/rust/cssparser/src/unicode_range.rs20
-rw-r--r--third_party/rust/cubeb-coreaudio/.cargo-checksum.json2
-rw-r--r--third_party/rust/cubeb-coreaudio/Cargo.toml5
-rw-r--r--third_party/rust/cubeb-coreaudio/src/backend/mixer.rs53
-rw-r--r--third_party/rust/cubeb-coreaudio/src/backend/mod.rs172
-rw-r--r--third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs3
-rw-r--r--third_party/rust/d3d12/.cargo-checksum.json2
-rw-r--r--third_party/rust/d3d12/Cargo.toml2
-rw-r--r--third_party/rust/encoding_rs/.cargo-checksum.json2
-rw-r--r--third_party/rust/encoding_rs/Cargo.toml19
-rw-r--r--third_party/rust/encoding_rs/README.md34
-rw-r--r--third_party/rust/encoding_rs/src/ascii.rs388
-rw-r--r--third_party/rust/encoding_rs/src/handles.rs36
-rw-r--r--third_party/rust/encoding_rs/src/lib.rs13
-rw-r--r--third_party/rust/encoding_rs/src/mem.rs18
-rw-r--r--third_party/rust/encoding_rs/src/simd_funcs.rs146
-rw-r--r--third_party/rust/encoding_rs/src/single_byte.rs64
-rw-r--r--third_party/rust/encoding_rs/src/x_user_defined.rs10
-rw-r--r--third_party/rust/equivalent/.cargo-checksum.json1
-rw-r--r--third_party/rust/equivalent/Cargo.toml27
-rw-r--r--third_party/rust/equivalent/LICENSE-APACHE201
-rw-r--r--third_party/rust/equivalent/LICENSE-MIT25
-rw-r--r--third_party/rust/equivalent/README.md25
-rw-r--r--third_party/rust/equivalent/src/lib.rs113
-rw-r--r--third_party/rust/fallible_collections/.cargo-checksum.json2
-rw-r--r--third_party/rust/fallible_collections/Cargo.toml7
-rw-r--r--third_party/rust/fallible_collections/README.md3
-rw-r--r--third_party/rust/fallible_collections/src/arc.rs35
-rw-r--r--third_party/rust/fallible_collections/src/boxed.rs15
-rw-r--r--third_party/rust/fallible_collections/src/btree/node.rs29
-rw-r--r--third_party/rust/fallible_collections/src/lib.rs24
-rw-r--r--third_party/rust/fallible_collections/src/try_reserve_error.rs19
-rw-r--r--third_party/rust/fallible_collections/src/vec.rs4
-rw-r--r--third_party/rust/getrandom/.cargo-checksum.json2
-rw-r--r--third_party/rust/getrandom/CHANGELOG.md39
-rw-r--r--third_party/rust/getrandom/Cargo.toml3
-rw-r--r--third_party/rust/getrandom/LICENSE-MIT2
-rw-r--r--third_party/rust/getrandom/README.md23
-rw-r--r--third_party/rust/getrandom/src/3ds.rs8
-rw-r--r--third_party/rust/getrandom/src/apple-other.rs27
-rw-r--r--third_party/rust/getrandom/src/bsd_arandom.rs8
-rw-r--r--third_party/rust/getrandom/src/custom.rs9
-rw-r--r--third_party/rust/getrandom/src/dragonfly.rs8
-rw-r--r--third_party/rust/getrandom/src/error.rs14
-rw-r--r--third_party/rust/getrandom/src/error_impls.rs9
-rw-r--r--third_party/rust/getrandom/src/espidf.rs8
-rw-r--r--third_party/rust/getrandom/src/fuchsia.rs8
-rw-r--r--third_party/rust/getrandom/src/hermit.rs24
-rw-r--r--third_party/rust/getrandom/src/hurd.rs8
-rw-r--r--third_party/rust/getrandom/src/js.rs8
-rw-r--r--third_party/rust/getrandom/src/lazy.rs56
-rw-r--r--third_party/rust/getrandom/src/lib.rs96
-rw-r--r--third_party/rust/getrandom/src/linux_android.rs47
-rw-r--r--third_party/rust/getrandom/src/linux_android_with_fallback.rs33
-rw-r--r--third_party/rust/getrandom/src/macos.rs40
-rw-r--r--third_party/rust/getrandom/src/openbsd.rs8
-rw-r--r--third_party/rust/getrandom/src/rdrand.rs13
-rw-r--r--third_party/rust/getrandom/src/solaris_illumos.rs8
-rw-r--r--third_party/rust/getrandom/src/solid.rs8
-rw-r--r--third_party/rust/getrandom/src/use_file.rs21
-rw-r--r--third_party/rust/getrandom/src/util.rs68
-rw-r--r--third_party/rust/getrandom/src/util_libc.rs41
-rw-r--r--third_party/rust/getrandom/src/vita.rs8
-rw-r--r--third_party/rust/getrandom/src/vxworks.rs8
-rw-r--r--third_party/rust/getrandom/src/wasi.rs8
-rw-r--r--third_party/rust/getrandom/src/windows.rs9
-rw-r--r--third_party/rust/getrandom/tests/rdrand.rs2
-rw-r--r--third_party/rust/glean-core/.cargo-checksum.json2
-rw-r--r--third_party/rust/glean-core/Cargo.toml4
-rw-r--r--third_party/rust/glean-core/src/common_metric_data.rs5
-rw-r--r--third_party/rust/glean-core/src/core/mod.rs29
-rw-r--r--third_party/rust/glean-core/src/database/mod.rs65
-rw-r--r--third_party/rust/glean-core/src/glean.udl22
-rw-r--r--third_party/rust/glean-core/src/internal_pings.rs17
-rw-r--r--third_party/rust/glean-core/src/lib.rs42
-rw-r--r--third_party/rust/glean-core/src/lib_unit_tests.rs118
-rw-r--r--third_party/rust/glean-core/src/metrics/metrics_enabled_config.rs46
-rw-r--r--third_party/rust/glean-core/src/metrics/mod.rs21
-rw-r--r--third_party/rust/glean-core/src/metrics/object.rs29
-rw-r--r--third_party/rust/glean-core/src/metrics/ping.rs74
-rw-r--r--third_party/rust/glean-core/src/metrics/remote_settings_config.rs52
-rw-r--r--third_party/rust/glean-core/src/ping/mod.rs3
-rw-r--r--third_party/rust/glean-core/src/upload/directory.rs6
-rw-r--r--third_party/rust/glean-core/src/upload/mod.rs24
-rw-r--r--third_party/rust/glean-core/tests/event.rs4
-rw-r--r--third_party/rust/glean-core/tests/ping.rs46
-rw-r--r--third_party/rust/glean-core/tests/ping_maker.rs23
-rw-r--r--third_party/rust/glean/.cargo-checksum.json2
-rw-r--r--third_party/rust/glean/Cargo.toml4
-rw-r--r--third_party/rust/glean/src/lib.rs10
-rw-r--r--third_party/rust/glean/src/private/ping.rs11
-rw-r--r--third_party/rust/glean/src/test.rs29
-rw-r--r--third_party/rust/glean/tests/init_fails.rs5
-rw-r--r--third_party/rust/glean/tests/never_init.rs5
-rw-r--r--third_party/rust/glean/tests/no_time_to_init.rs5
-rw-r--r--third_party/rust/glean/tests/schema.rs3
-rw-r--r--third_party/rust/glean/tests/simple.rs5
-rwxr-xr-xthird_party/rust/glean/tests/test-shutdown-blocking.sh2
-rwxr-xr-xthird_party/rust/glean/tests/test-thread-crashing.sh2
-rw-r--r--third_party/rust/glean/tests/upload_timing.rs5
-rw-r--r--third_party/rust/gpu-descriptor-types/.cargo-checksum.json2
-rw-r--r--third_party/rust/gpu-descriptor-types/Cargo.toml23
-rw-r--r--third_party/rust/gpu-descriptor-types/src/device.rs128
-rw-r--r--third_party/rust/gpu-descriptor-types/src/lib.rs12
-rw-r--r--third_party/rust/gpu-descriptor-types/src/types.rs86
-rw-r--r--third_party/rust/gpu-descriptor/.cargo-checksum.json2
-rw-r--r--third_party/rust/gpu-descriptor/Cargo.toml14
-rw-r--r--third_party/rust/gpu-descriptor/src/allocator.rs38
-rw-r--r--third_party/rust/hashbrown/.cargo-checksum.json2
-rw-r--r--third_party/rust/hashbrown/CHANGELOG.md166
-rw-r--r--third_party/rust/hashbrown/Cargo.toml40
-rw-r--r--third_party/rust/hashbrown/README.md77
-rw-r--r--third_party/rust/hashbrown/benches/bench.rs2
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/mod.rs2
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rayon/map.rs47
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rayon/mod.rs1
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rayon/raw.rs23
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rayon/set.rs34
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rayon/table.rs252
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_map.rs125
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_set.rs123
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/rkyv/mod.rs2
-rw-r--r--third_party/rust/hashbrown/src/external_trait_impls/serde.rs63
-rw-r--r--third_party/rust/hashbrown/src/lib.rs78
-rw-r--r--third_party/rust/hashbrown/src/macros.rs2
-rw-r--r--third_party/rust/hashbrown/src/map.rs1324
-rw-r--r--third_party/rust/hashbrown/src/raw/alloc.rs57
-rw-r--r--third_party/rust/hashbrown/src/raw/bitmask.rs99
-rw-r--r--third_party/rust/hashbrown/src/raw/generic.rs59
-rw-r--r--third_party/rust/hashbrown/src/raw/mod.rs3301
-rw-r--r--third_party/rust/hashbrown/src/raw/neon.rs124
-rw-r--r--third_party/rust/hashbrown/src/raw/sse2.rs31
-rw-r--r--third_party/rust/hashbrown/src/rustc_entry.rs32
-rw-r--r--third_party/rust/hashbrown/src/scopeguard.rs14
-rw-r--r--third_party/rust/hashbrown/src/set.rs516
-rw-r--r--third_party/rust/hashbrown/src/table.rs2070
-rw-r--r--third_party/rust/hashbrown/tests/equivalent_trait.rs53
-rw-r--r--third_party/rust/hashbrown/tests/raw.rs11
-rw-r--r--third_party/rust/hashbrown/tests/rayon.rs4
-rw-r--r--third_party/rust/hashbrown/tests/set.rs2
-rw-r--r--third_party/rust/hashlink/.cargo-checksum.json2
-rw-r--r--third_party/rust/hashlink/CHANGELOG.md3
-rw-r--r--third_party/rust/hashlink/Cargo.toml8
-rw-r--r--third_party/rust/hashlink/tests/serde.rs10
-rw-r--r--third_party/rust/indexmap/.cargo-checksum.json2
-rw-r--r--third_party/rust/indexmap/Cargo.toml47
-rw-r--r--third_party/rust/indexmap/README.md10
-rw-r--r--third_party/rust/indexmap/RELEASES.md618
-rw-r--r--third_party/rust/indexmap/build.rs8
-rw-r--r--third_party/rust/indexmap/src/arbitrary.rs2
-rw-r--r--third_party/rust/indexmap/src/borsh.rs122
-rw-r--r--third_party/rust/indexmap/src/equivalent.rs27
-rw-r--r--third_party/rust/indexmap/src/lib.rs132
-rw-r--r--third_party/rust/indexmap/src/macros.rs36
-rw-r--r--third_party/rust/indexmap/src/map.rs1410
-rw-r--r--third_party/rust/indexmap/src/map/core.rs460
-rw-r--r--third_party/rust/indexmap/src/map/core/entry.rs481
-rw-r--r--third_party/rust/indexmap/src/map/core/raw.rs174
-rw-r--r--third_party/rust/indexmap/src/map/core/raw_entry_v1.rs652
-rw-r--r--third_party/rust/indexmap/src/map/iter.rs713
-rw-r--r--third_party/rust/indexmap/src/map/mutable.rs87
-rw-r--r--third_party/rust/indexmap/src/map/serde_seq.rs138
-rw-r--r--third_party/rust/indexmap/src/map/slice.rs539
-rw-r--r--third_party/rust/indexmap/src/map/tests.rs727
-rw-r--r--third_party/rust/indexmap/src/mutable_keys.rs75
-rw-r--r--third_party/rust/indexmap/src/rayon/map.rs184
-rw-r--r--third_party/rust/indexmap/src/rayon/mod.rs2
-rw-r--r--third_party/rust/indexmap/src/rayon/set.rs111
-rw-r--r--third_party/rust/indexmap/src/serde.rs43
-rw-r--r--third_party/rust/indexmap/src/serde_seq.rs112
-rw-r--r--third_party/rust/indexmap/src/set.rs1457
-rw-r--r--third_party/rust/indexmap/src/set/iter.rs626
-rw-r--r--third_party/rust/indexmap/src/set/mutable.rs86
-rw-r--r--third_party/rust/indexmap/src/set/slice.rs340
-rw-r--r--third_party/rust/indexmap/src/set/tests.rs723
-rw-r--r--third_party/rust/indexmap/src/util.rs22
-rw-r--r--third_party/rust/indexmap/tests/quick.rs198
-rw-r--r--third_party/rust/interrupt-support/.cargo-checksum.json2
-rw-r--r--third_party/rust/interrupt-support/Cargo.toml5
-rw-r--r--third_party/rust/interrupt-support/build.rs8
-rw-r--r--third_party/rust/interrupt-support/src/interrupt_support.udl5
-rw-r--r--third_party/rust/interrupt-support/src/shutdown.rs5
-rw-r--r--third_party/rust/interrupt-support/src/sql.rs7
-rw-r--r--third_party/rust/libc/.cargo-checksum.json2
-rw-r--r--third_party/rust/libc/Cargo.toml2
-rw-r--r--third_party/rust/libc/src/unix/linux_like/android/mod.rs33
-rw-r--r--third_party/rust/libc/src/unix/linux_like/linux/arch/generic/mod.rs6
-rw-r--r--third_party/rust/libc/src/unix/linux_like/linux/mod.rs2
-rw-r--r--third_party/rust/libc/src/unix/newlib/vita/mod.rs2
-rw-r--r--third_party/rust/libloading/.cargo-checksum.json2
-rw-r--r--third_party/rust/libloading/Cargo.toml16
-rw-r--r--third_party/rust/libloading/README.mkd7
-rw-r--r--third_party/rust/libloading/src/changelog.rs45
-rw-r--r--third_party/rust/libloading/src/error.rs8
-rw-r--r--third_party/rust/libloading/src/lib.rs8
-rw-r--r--third_party/rust/libloading/src/os/unix/consts.rs12
-rw-r--r--third_party/rust/libloading/src/os/unix/mod.rs186
-rw-r--r--third_party/rust/libloading/src/os/windows/mod.rs154
-rw-r--r--third_party/rust/libloading/tests/functions.rs20
-rw-r--r--third_party/rust/metal/.cargo-checksum.json2
-rw-r--r--third_party/rust/metal/Cargo.lock273
-rw-r--r--third_party/rust/metal/Cargo.toml7
-rw-r--r--third_party/rust/metal/README.md7
-rw-r--r--third_party/rust/metal/src/device.rs3
-rw-r--r--third_party/rust/metal/src/lib.rs8
-rw-r--r--third_party/rust/metal/src/library.rs9
-rw-r--r--third_party/rust/metal/src/mps.rs7
-rw-r--r--third_party/rust/metal/src/sync.rs4
-rw-r--r--third_party/rust/minidump-common/.cargo-checksum.json2
-rw-r--r--third_party/rust/minidump-common/Cargo.toml4
-rw-r--r--third_party/rust/minidump-common/src/errors/macos.rs25
-rw-r--r--third_party/rust/minidump-common/src/format.rs24
-rw-r--r--third_party/rust/minidump-writer/.cargo-checksum.json2
-rw-r--r--third_party/rust/minidump-writer/CHANGELOG.md40
-rw-r--r--third_party/rust/minidump-writer/Cargo.lock1757
-rw-r--r--third_party/rust/minidump-writer/Cargo.toml27
-rw-r--r--third_party/rust/minidump-writer/README.md26
-rw-r--r--third_party/rust/minidump-writer/deny.toml6
-rw-r--r--third_party/rust/minidump-writer/src/bin/test.rs26
-rw-r--r--third_party/rust/minidump-writer/src/linux/dso_debug.rs5
-rw-r--r--third_party/rust/minidump-writer/src/linux/maps_reader.rs147
-rw-r--r--third_party/rust/minidump-writer/src/linux/minidump_writer.rs38
-rw-r--r--third_party/rust/minidump-writer/src/linux/ptrace_dumper.rs81
-rw-r--r--third_party/rust/minidump-writer/src/linux/sections/mappings.rs21
-rw-r--r--third_party/rust/minidump-writer/src/linux/thread_info.rs22
-rw-r--r--third_party/rust/minidump-writer/src/mac/mach.rs3
-rw-r--r--third_party/rust/minidump-writer/src/mac/streams/exception.rs8
-rw-r--r--third_party/rust/minidump-writer/src/mac/streams/module_list.rs8
-rw-r--r--third_party/rust/minidump-writer/src/mac/streams/thread_names.rs4
-rw-r--r--third_party/rust/minidump-writer/src/windows/minidump_writer.rs14
-rw-r--r--third_party/rust/minidump-writer/tests/common/mod.rs67
-rw-r--r--third_party/rust/minidump-writer/tests/linux_minidump_writer.rs106
-rw-r--r--third_party/rust/minidump-writer/tests/ptrace_dumper.rs21
-rw-r--r--third_party/rust/naga/.cargo-checksum.json2
-rw-r--r--third_party/rust/naga/Cargo.toml9
-rw-r--r--third_party/rust/naga/src/arena.rs17
-rw-r--r--third_party/rust/naga/src/back/dot/mod.rs91
-rw-r--r--third_party/rust/naga/src/back/glsl/features.rs23
-rw-r--r--third_party/rust/naga/src/back/glsl/mod.rs148
-rw-r--r--third_party/rust/naga/src/back/hlsl/conv.rs5
-rw-r--r--third_party/rust/naga/src/back/hlsl/help.rs94
-rw-r--r--third_party/rust/naga/src/back/hlsl/mod.rs17
-rw-r--r--third_party/rust/naga/src/back/hlsl/writer.rs315
-rw-r--r--third_party/rust/naga/src/back/mod.rs17
-rw-r--r--third_party/rust/naga/src/back/msl/mod.rs27
-rw-r--r--third_party/rust/naga/src/back/msl/writer.rs192
-rw-r--r--third_party/rust/naga/src/back/pipeline_constants.rs957
-rw-r--r--third_party/rust/naga/src/back/spv/block.rs32
-rw-r--r--third_party/rust/naga/src/back/spv/helpers.rs53
-rw-r--r--third_party/rust/naga/src/back/spv/instructions.rs103
-rw-r--r--third_party/rust/naga/src/back/spv/mod.rs47
-rw-r--r--third_party/rust/naga/src/back/spv/subgroup.rs207
-rw-r--r--third_party/rust/naga/src/back/spv/writer.rs68
-rw-r--r--third_party/rust/naga/src/back/wgsl/writer.rs131
-rw-r--r--third_party/rust/naga/src/block.rs6
-rw-r--r--third_party/rust/naga/src/compact/expressions.rs27
-rw-r--r--third_party/rust/naga/src/compact/functions.rs6
-rw-r--r--third_party/rust/naga/src/compact/mod.rs49
-rw-r--r--third_party/rust/naga/src/compact/statements.rs67
-rw-r--r--third_party/rust/naga/src/error.rs74
-rw-r--r--third_party/rust/naga/src/front/glsl/context.rs48
-rw-r--r--third_party/rust/naga/src/front/glsl/error.rs18
-rw-r--r--third_party/rust/naga/src/front/glsl/functions.rs10
-rw-r--r--third_party/rust/naga/src/front/glsl/mod.rs4
-rw-r--r--third_party/rust/naga/src/front/glsl/parser.rs17
-rw-r--r--third_party/rust/naga/src/front/glsl/parser/declarations.rs9
-rw-r--r--third_party/rust/naga/src/front/glsl/parser/functions.rs9
-rw-r--r--third_party/rust/naga/src/front/glsl/parser_tests.rs22
-rw-r--r--third_party/rust/naga/src/front/glsl/types.rs17
-rw-r--r--third_party/rust/naga/src/front/glsl/variables.rs1
-rw-r--r--third_party/rust/naga/src/front/spv/convert.rs5
-rw-r--r--third_party/rust/naga/src/front/spv/error.rs10
-rw-r--r--third_party/rust/naga/src/front/spv/function.rs13
-rw-r--r--third_party/rust/naga/src/front/spv/image.rs13
-rw-r--r--third_party/rust/naga/src/front/spv/mod.rs455
-rw-r--r--third_party/rust/naga/src/front/spv/null.rs8
-rw-r--r--third_party/rust/naga/src/front/wgsl/error.rs29
-rw-r--r--third_party/rust/naga/src/front/wgsl/index.rs1
-rw-r--r--third_party/rust/naga/src/front/wgsl/lower/mod.rs414
-rw-r--r--third_party/rust/naga/src/front/wgsl/mod.rs11
-rw-r--r--third_party/rust/naga/src/front/wgsl/parse/ast.rs9
-rw-r--r--third_party/rust/naga/src/front/wgsl/parse/conv.rs28
-rw-r--r--third_party/rust/naga/src/front/wgsl/parse/mod.rs106
-rw-r--r--third_party/rust/naga/src/front/wgsl/to_wgsl.rs3
-rw-r--r--third_party/rust/naga/src/lib.rs174
-rw-r--r--third_party/rust/naga/src/proc/constant_evaluator.rs589
-rw-r--r--third_party/rust/naga/src/proc/index.rs4
-rw-r--r--third_party/rust/naga/src/proc/mod.rs105
-rw-r--r--third_party/rust/naga/src/proc/terminator.rs3
-rw-r--r--third_party/rust/naga/src/proc/typifier.rs8
-rw-r--r--third_party/rust/naga/src/span.rs12
-rw-r--r--third_party/rust/naga/src/valid/analyzer.rs53
-rw-r--r--third_party/rust/naga/src/valid/expression.rs39
-rw-r--r--third_party/rust/naga/src/valid/function.rs268
-rw-r--r--third_party/rust/naga/src/valid/handles.rs91
-rw-r--r--third_party/rust/naga/src/valid/interface.rs48
-rw-r--r--third_party/rust/naga/src/valid/mod.rs228
-rw-r--r--third_party/rust/naga/src/valid/type.rs3
-rw-r--r--third_party/rust/neqo-common/.cargo-checksum.json2
-rw-r--r--third_party/rust/neqo-common/Cargo.toml13
-rw-r--r--third_party/rust/neqo-common/src/datagram.rs2
-rw-r--r--third_party/rust/neqo-common/src/fuzz.rs43
-rw-r--r--third_party/rust/neqo-common/src/lib.rs4
-rw-r--r--third_party/rust/neqo-common/src/tos.rs27
-rw-r--r--third_party/rust/neqo-crypto/.cargo-checksum.json2
-rw-r--r--third_party/rust/neqo-crypto/Cargo.toml5
-rw-r--r--third_party/rust/neqo-crypto/src/aead_null.rs2
-rw-r--r--third_party/rust/neqo-crypto/src/agentio.rs2
-rw-r--r--third_party/rust/neqo-crypto/src/constants.rs2
-rw-r--r--third_party/rust/neqo-crypto/src/p11.rs26
-rw-r--r--third_party/rust/neqo-http3/.cargo-checksum.json2
-rw-r--r--third_party/rust/neqo-http3/Cargo.toml6
-rw-r--r--third_party/rust/neqo-http3/src/buffered_send_stream.rs51
-rw-r--r--third_party/rust/neqo-http3/src/connection.rs20
-rw-r--r--third_party/rust/neqo-http3/src/connection_client.rs20
-rw-r--r--third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/negotiation.rs7
-rw-r--r--third_party/rust/neqo-http3/src/send_message.rs4
-rw-r--r--third_party/rust/neqo-http3/src/server.rs4
-rw-r--r--third_party/rust/neqo-http3/tests/httpconn.rs4
-rw-r--r--third_party/rust/neqo-qpack/.cargo-checksum.json2
-rw-r--r--third_party/rust/neqo-qpack/Cargo.toml6
-rw-r--r--third_party/rust/neqo-transport/.cargo-checksum.json2
-rw-r--r--third_party/rust/neqo-transport/Cargo.toml22
-rw-r--r--third_party/rust/neqo-transport/src/cc/classic_cc.rs105
-rw-r--r--third_party/rust/neqo-transport/src/cc/mod.rs3
-rw-r--r--third_party/rust/neqo-transport/src/cc/tests/cubic.rs34
-rw-r--r--third_party/rust/neqo-transport/src/cc/tests/new_reno.rs89
-rw-r--r--third_party/rust/neqo-transport/src/connection/mod.rs285
-rw-r--r--third_party/rust/neqo-transport/src/connection/state.rs39
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/cc.rs36
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/close.rs25
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/datagram.rs14
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/ecn.rs392
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/handshake.rs26
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/keys.rs10
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/migration.rs8
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/mod.rs31
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/stream.rs9
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/vn.rs8
-rw-r--r--third_party/rust/neqo-transport/src/ecn.rs225
-rw-r--r--third_party/rust/neqo-transport/src/events.rs4
-rw-r--r--third_party/rust/neqo-transport/src/frame.rs143
-rw-r--r--third_party/rust/neqo-transport/src/lib.rs27
-rw-r--r--third_party/rust/neqo-transport/src/packet/mod.rs1
-rw-r--r--third_party/rust/neqo-transport/src/path.rs77
-rw-r--r--third_party/rust/neqo-transport/src/qlog.rs73
-rw-r--r--third_party/rust/neqo-transport/src/recovery.rs52
-rw-r--r--third_party/rust/neqo-transport/src/send_stream.rs18
-rw-r--r--third_party/rust/neqo-transport/src/sender.rs5
-rw-r--r--third_party/rust/neqo-transport/src/server.rs7
-rw-r--r--third_party/rust/neqo-transport/src/tracking.rs47
-rw-r--r--third_party/rust/neqo-transport/tests/common/mod.rs108
-rw-r--r--third_party/rust/neqo-transport/tests/connection.rs41
-rw-r--r--third_party/rust/neqo-transport/tests/network.rs10
-rw-r--r--third_party/rust/neqo-transport/tests/retry.rs20
-rw-r--r--third_party/rust/neqo-transport/tests/server.rs93
-rw-r--r--third_party/rust/nix/.cargo-checksum.json2
-rw-r--r--third_party/rust/nix/CHANGELOG.md205
-rw-r--r--third_party/rust/nix/Cargo.toml16
-rw-r--r--third_party/rust/nix/README.md4
-rw-r--r--third_party/rust/nix/build.rs25
-rw-r--r--third_party/rust/nix/src/dir.rs27
-rw-r--r--third_party/rust/nix/src/env.rs7
-rw-r--r--third_party/rust/nix/src/errno.rs1114
-rw-r--r--third_party/rust/nix/src/fcntl.rs561
-rw-r--r--third_party/rust/nix/src/features.rs12
-rw-r--r--third_party/rust/nix/src/ifaddrs.rs38
-rw-r--r--third_party/rust/nix/src/kmod.rs4
-rw-r--r--third_party/rust/nix/src/lib.rs34
-rw-r--r--third_party/rust/nix/src/macros.rs8
-rw-r--r--third_party/rust/nix/src/mount/bsd.rs51
-rw-r--r--third_party/rust/nix/src/mount/linux.rs2
-rw-r--r--third_party/rust/nix/src/mount/mod.rs22
-rw-r--r--third_party/rust/nix/src/mqueue.rs15
-rw-r--r--third_party/rust/nix/src/net/if_.rs329
-rw-r--r--third_party/rust/nix/src/poll.rs61
-rw-r--r--third_party/rust/nix/src/poll_timeout.rs224
-rw-r--r--third_party/rust/nix/src/pty.rs15
-rw-r--r--third_party/rust/nix/src/sched.rs43
-rw-r--r--third_party/rust/nix/src/sys/aio.rs80
-rw-r--r--third_party/rust/nix/src/sys/epoll.rs25
-rw-r--r--third_party/rust/nix/src/sys/event.rs171
-rw-r--r--third_party/rust/nix/src/sys/eventfd.rs77
-rw-r--r--third_party/rust/nix/src/sys/fanotify.rs416
-rw-r--r--third_party/rust/nix/src/sys/inotify.rs16
-rw-r--r--third_party/rust/nix/src/sys/ioctl/bsd.rs4
-rw-r--r--third_party/rust/nix/src/sys/ioctl/linux.rs2
-rw-r--r--third_party/rust/nix/src/sys/ioctl/mod.rs112
-rw-r--r--third_party/rust/nix/src/sys/memfd.rs43
-rw-r--r--third_party/rust/nix/src/sys/mman.rs320
-rw-r--r--third_party/rust/nix/src/sys/mod.rs82
-rw-r--r--third_party/rust/nix/src/sys/personality.rs2
-rw-r--r--third_party/rust/nix/src/sys/prctl.rs23
-rw-r--r--third_party/rust/nix/src/sys/ptrace/bsd.rs42
-rw-r--r--third_party/rust/nix/src/sys/ptrace/linux.rs58
-rw-r--r--third_party/rust/nix/src/sys/ptrace/mod.rs20
-rw-r--r--third_party/rust/nix/src/sys/quota.rs6
-rw-r--r--third_party/rust/nix/src/sys/reboot.rs175
-rw-r--r--third_party/rust/nix/src/sys/resource.rs109
-rw-r--r--third_party/rust/nix/src/sys/select.rs267
-rw-r--r--third_party/rust/nix/src/sys/sendfile.rs116
-rw-r--r--third_party/rust/nix/src/sys/signal.rs461
-rw-r--r--third_party/rust/nix/src/sys/signalfd.rs66
-rw-r--r--third_party/rust/nix/src/sys/socket/addr.rs873
-rw-r--r--third_party/rust/nix/src/sys/socket/mod.rs943
-rw-r--r--third_party/rust/nix/src/sys/socket/sockopt.rs454
-rw-r--r--third_party/rust/nix/src/sys/stat.rs73
-rw-r--r--third_party/rust/nix/src/sys/statfs.rs363
-rw-r--r--third_party/rust/nix/src/sys/statvfs.rs48
-rw-r--r--third_party/rust/nix/src/sys/termios.rs570
-rw-r--r--third_party/rust/nix/src/sys/time.rs121
-rw-r--r--third_party/rust/nix/src/sys/timerfd.rs2
-rw-r--r--third_party/rust/nix/src/sys/uio.rs49
-rw-r--r--third_party/rust/nix/src/sys/utsname.rs23
-rw-r--r--third_party/rust/nix/src/sys/wait.rs58
-rw-r--r--third_party/rust/nix/src/time.rs236
-rw-r--r--third_party/rust/nix/src/unistd.rs1313
-rw-r--r--third_party/rust/nix/test/common/mod.rs10
-rw-r--r--third_party/rust/nix/test/sys/mod.rs54
-rw-r--r--third_party/rust/nix/test/sys/test_aio.rs66
-rw-r--r--third_party/rust/nix/test/sys/test_aio_drop.rs3
-rw-r--r--third_party/rust/nix/test/sys/test_event.rs41
-rw-r--r--third_party/rust/nix/test/sys/test_fanotify.rs149
-rw-r--r--third_party/rust/nix/test/sys/test_ioctl.rs33
-rw-r--r--third_party/rust/nix/test/sys/test_mman.rs55
-rw-r--r--third_party/rust/nix/test/sys/test_ptrace.rs12
-rw-r--r--third_party/rust/nix/test/sys/test_resource.rs43
-rw-r--r--third_party/rust/nix/test/sys/test_select.rs247
-rw-r--r--third_party/rust/nix/test/sys/test_signal.rs320
-rw-r--r--third_party/rust/nix/test/sys/test_signalfd.rs63
-rw-r--r--third_party/rust/nix/test/sys/test_socket.rs474
-rw-r--r--third_party/rust/nix/test/sys/test_sockopt.rs454
-rw-r--r--third_party/rust/nix/test/sys/test_statfs.rs99
-rw-r--r--third_party/rust/nix/test/sys/test_statvfs.rs13
-rw-r--r--third_party/rust/nix/test/sys/test_termios.rs13
-rw-r--r--third_party/rust/nix/test/sys/test_time.rs91
-rw-r--r--third_party/rust/nix/test/sys/test_timer.rs (renamed from third_party/rust/nix/test/test_timer.rs)0
-rw-r--r--third_party/rust/nix/test/sys/test_uio.rs36
-rw-r--r--third_party/rust/nix/test/sys/test_utsname.rs17
-rw-r--r--third_party/rust/nix/test/sys/test_wait.rs16
-rw-r--r--third_party/rust/nix/test/test.rs32
-rw-r--r--third_party/rust/nix/test/test_dir.rs4
-rw-r--r--third_party/rust/nix/test/test_errno.rs16
-rw-r--r--third_party/rust/nix/test/test_fcntl.rs182
-rw-r--r--third_party/rust/nix/test/test_mount.rs390
-rw-r--r--third_party/rust/nix/test/test_mq.rs20
-rw-r--r--third_party/rust/nix/test/test_net.rs8
-rw-r--r--third_party/rust/nix/test/test_poll.rs31
-rw-r--r--third_party/rust/nix/test/test_pty.rs24
-rw-r--r--third_party/rust/nix/test/test_resource.rs34
-rw-r--r--third_party/rust/nix/test/test_sendfile.rs90
-rw-r--r--third_party/rust/nix/test/test_stat.rs104
-rw-r--r--third_party/rust/nix/test/test_time.rs49
-rw-r--r--third_party/rust/nix/test/test_unistd.rs260
-rw-r--r--third_party/rust/objc_exception/.cargo-checksum.json1
-rw-r--r--third_party/rust/objc_exception/Cargo.toml25
-rw-r--r--third_party/rust/objc_exception/build.rs7
-rw-r--r--third_party/rust/objc_exception/extern/exception.m21
-rw-r--r--third_party/rust/objc_exception/src/lib.rs100
-rw-r--r--third_party/rust/owning_ref/.cargo-checksum.json1
-rw-r--r--third_party/rust/owning_ref/CHANGELOG.md8
-rw-r--r--third_party/rust/owning_ref/Cargo.toml24
-rw-r--r--third_party/rust/owning_ref/LICENSE21
-rw-r--r--third_party/rust/owning_ref/README.md64
-rw-r--r--third_party/rust/owning_ref/src/lib.rs2016
-rw-r--r--third_party/rust/packed_simd/.cargo-checksum.json1
-rw-r--r--third_party/rust/packed_simd/Cargo.toml83
-rw-r--r--third_party/rust/packed_simd/README.md144
-rw-r--r--third_party/rust/packed_simd/bors.toml3
-rw-r--r--third_party/rust/packed_simd/build.rs6
-rwxr-xr-xthird_party/rust/packed_simd/ci/all.sh71
-rw-r--r--third_party/rust/packed_simd/ci/android-install-ndk.sh21
-rw-r--r--third_party/rust/packed_simd/ci/android-install-sdk.sh60
-rw-r--r--third_party/rust/packed_simd/ci/android-sysimage.sh56
-rwxr-xr-xthird_party/rust/packed_simd/ci/benchmark.sh32
-rw-r--r--third_party/rust/packed_simd/ci/deploy_and_run_on_ios_simulator.rs176
-rw-r--r--third_party/rust/packed_simd/ci/docker/aarch64-linux-android/Dockerfile47
-rw-r--r--third_party/rust/packed_simd/ci/docker/aarch64-unknown-linux-gnu/Dockerfile14
-rw-r--r--third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabi/Dockerfile15
-rw-r--r--third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile13
-rw-r--r--third_party/rust/packed_simd/ci/docker/armv7-linux-androideabi/Dockerfile47
-rw-r--r--third_party/rust/packed_simd/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile13
-rw-r--r--third_party/rust/packed_simd/ci/docker/i586-unknown-linux-gnu/Dockerfile7
-rw-r--r--third_party/rust/packed_simd/ci/docker/i686-unknown-linux-gnu/Dockerfile7
-rw-r--r--third_party/rust/packed_simd/ci/docker/mips-unknown-linux-gnu/Dockerfile13
-rw-r--r--third_party/rust/packed_simd/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile10
-rw-r--r--third_party/rust/packed_simd/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile10
-rw-r--r--third_party/rust/packed_simd/ci/docker/mipsel-unknown-linux-musl/Dockerfile25
-rw-r--r--third_party/rust/packed_simd/ci/docker/powerpc-unknown-linux-gnu/Dockerfile13
-rw-r--r--third_party/rust/packed_simd/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile17
-rw-r--r--third_party/rust/packed_simd/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile11
-rw-r--r--third_party/rust/packed_simd/ci/docker/s390x-unknown-linux-gnu/Dockerfile20
-rw-r--r--third_party/rust/packed_simd/ci/docker/sparc64-unknown-linux-gnu/Dockerfile18
-rw-r--r--third_party/rust/packed_simd/ci/docker/thumbv7neon-linux-androideabi/Dockerfile47
-rw-r--r--third_party/rust/packed_simd/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile13
-rw-r--r--third_party/rust/packed_simd/ci/docker/wasm32-unknown-unknown/Dockerfile39
-rw-r--r--third_party/rust/packed_simd/ci/docker/x86_64-linux-android/Dockerfile31
-rw-r--r--third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile16
-rw-r--r--third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu/Dockerfile10
-rwxr-xr-xthird_party/rust/packed_simd/ci/dox.sh27
-rw-r--r--third_party/rust/packed_simd/ci/linux-s390x.sh18
-rw-r--r--third_party/rust/packed_simd/ci/linux-sparc64.sh17
-rw-r--r--third_party/rust/packed_simd/ci/lld-shim.rs11
-rwxr-xr-xthird_party/rust/packed_simd/ci/max_line_width.sh17
-rwxr-xr-xthird_party/rust/packed_simd/ci/run-docker.sh38
-rwxr-xr-xthird_party/rust/packed_simd/ci/run.sh99
-rw-r--r--third_party/rust/packed_simd/ci/run_examples.sh51
-rw-r--r--third_party/rust/packed_simd/ci/runtest-android.rs45
-rwxr-xr-xthird_party/rust/packed_simd/ci/setup_benchmarks.sh7
-rwxr-xr-xthird_party/rust/packed_simd/ci/test-runner-linux24
-rw-r--r--third_party/rust/packed_simd/contributing.md67
-rw-r--r--third_party/rust/packed_simd/perf-guide/book.toml12
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/SUMMARY.md21
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/ascii.css4
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/bound_checks.md22
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/float-math/approx.md8
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/float-math/fma.md6
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/float-math/fp.md3
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/float-math/svml.md7
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/introduction.md26
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/prof/linux.md107
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/prof/mca.md100
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/prof/profiling.md14
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/target-feature/attribute.md5
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/target-feature/features.md13
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/target-feature/inlining.md5
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/target-feature/practice.md31
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/target-feature/runtime.md5
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/target-feature/rustflags.md77
-rw-r--r--third_party/rust/packed_simd/perf-guide/src/vert-hor-ops.md76
-rw-r--r--third_party/rust/packed_simd/rust-toolchain1
-rw-r--r--third_party/rust/packed_simd/rustfmt.toml5
-rw-r--r--third_party/rust/packed_simd/src/api.rs309
-rw-r--r--third_party/rust/packed_simd/src/api/bit_manip.rs129
-rw-r--r--third_party/rust/packed_simd/src/api/bitmask.rs79
-rw-r--r--third_party/rust/packed_simd/src/api/cast.rs108
-rw-r--r--third_party/rust/packed_simd/src/api/cast/macros.rs82
-rw-r--r--third_party/rust/packed_simd/src/api/cast/v128.rs302
-rw-r--r--third_party/rust/packed_simd/src/api/cast/v16.rs68
-rw-r--r--third_party/rust/packed_simd/src/api/cast/v256.rs298
-rw-r--r--third_party/rust/packed_simd/src/api/cast/v32.rs132
-rw-r--r--third_party/rust/packed_simd/src/api/cast/v512.rs209
-rw-r--r--third_party/rust/packed_simd/src/api/cast/v64.rs208
-rw-r--r--third_party/rust/packed_simd/src/api/cmp.rs16
-rw-r--r--third_party/rust/packed_simd/src/api/cmp/eq.rs27
-rw-r--r--third_party/rust/packed_simd/src/api/cmp/ord.rs43
-rw-r--r--third_party/rust/packed_simd/src/api/cmp/partial_eq.rs65
-rw-r--r--third_party/rust/packed_simd/src/api/cmp/partial_ord.rs230
-rw-r--r--third_party/rust/packed_simd/src/api/cmp/vertical.rs114
-rw-r--r--third_party/rust/packed_simd/src/api/default.rs30
-rw-r--r--third_party/rust/packed_simd/src/api/fmt.rs12
-rw-r--r--third_party/rust/packed_simd/src/api/fmt/binary.rs54
-rw-r--r--third_party/rust/packed_simd/src/api/fmt/debug.rs60
-rw-r--r--third_party/rust/packed_simd/src/api/fmt/lower_hex.rs54
-rw-r--r--third_party/rust/packed_simd/src/api/fmt/octal.rs54
-rw-r--r--third_party/rust/packed_simd/src/api/fmt/upper_hex.rs54
-rw-r--r--third_party/rust/packed_simd/src/api/from.rs7
-rw-r--r--third_party/rust/packed_simd/src/api/from/from_array.rs124
-rw-r--r--third_party/rust/packed_simd/src/api/from/from_vector.rs67
-rw-r--r--third_party/rust/packed_simd/src/api/hash.rs49
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits.rs59
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/arch_specific.rs345
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/macros.rs74
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/v128.rs232
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/v16.rs9
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/v256.rs232
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/v32.rs13
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/v512.rs232
-rw-r--r--third_party/rust/packed_simd/src/api/into_bits/v64.rs18
-rw-r--r--third_party/rust/packed_simd/src/api/math.rs4
-rw-r--r--third_party/rust/packed_simd/src/api/math/float.rs64
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/abs.rs31
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/consts.rs74
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/cos.rs44
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/exp.rs33
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/ln.rs33
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/mul_add.rs44
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/mul_adde.rs48
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/powf.rs36
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/recpre.rs36
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/rsqrte.rs40
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/sin.rs50
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/sqrt.rs35
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/sqrte.rs44
-rw-r--r--third_party/rust/packed_simd/src/api/math/float/tanh.rs29
-rw-r--r--third_party/rust/packed_simd/src/api/minimal.rs6
-rw-r--r--third_party/rust/packed_simd/src/api/minimal/iuf.rs169
-rw-r--r--third_party/rust/packed_simd/src/api/minimal/mask.rs176
-rw-r--r--third_party/rust/packed_simd/src/api/minimal/ptr.rs1373
-rw-r--r--third_party/rust/packed_simd/src/api/ops.rs32
-rw-r--r--third_party/rust/packed_simd/src/api/ops/scalar_arithmetic.rs203
-rw-r--r--third_party/rust/packed_simd/src/api/ops/scalar_bitwise.rs162
-rw-r--r--third_party/rust/packed_simd/src/api/ops/scalar_mask_bitwise.rs140
-rw-r--r--third_party/rust/packed_simd/src/api/ops/scalar_shifts.rs106
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_arithmetic.rs148
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_bitwise.rs129
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_float_min_max.rs74
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_int_min_max.rs57
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_mask_bitwise.rs116
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_neg.rs43
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_rotates.rs92
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_shifts.rs106
-rw-r--r--third_party/rust/packed_simd/src/api/ptr.rs4
-rw-r--r--third_party/rust/packed_simd/src/api/ptr/gather_scatter.rs216
-rw-r--r--third_party/rust/packed_simd/src/api/reductions.rs12
-rw-r--r--third_party/rust/packed_simd/src/api/reductions/bitwise.rs151
-rw-r--r--third_party/rust/packed_simd/src/api/reductions/float_arithmetic.rs313
-rw-r--r--third_party/rust/packed_simd/src/api/reductions/integer_arithmetic.rs193
-rw-r--r--third_party/rust/packed_simd/src/api/reductions/mask.rs89
-rw-r--r--third_party/rust/packed_simd/src/api/reductions/min_max.rs360
-rw-r--r--third_party/rust/packed_simd/src/api/select.rs73
-rw-r--r--third_party/rust/packed_simd/src/api/shuffle.rs184
-rw-r--r--third_party/rust/packed_simd/src/api/shuffle1_dyn.rs159
-rw-r--r--third_party/rust/packed_simd/src/api/slice.rs7
-rw-r--r--third_party/rust/packed_simd/src/api/slice/from_slice.rs202
-rw-r--r--third_party/rust/packed_simd/src/api/slice/write_to_slice.rs196
-rw-r--r--third_party/rust/packed_simd/src/api/swap_bytes.rs192
-rw-r--r--third_party/rust/packed_simd/src/codegen.rs62
-rw-r--r--third_party/rust/packed_simd/src/codegen/bit_manip.rs347
-rw-r--r--third_party/rust/packed_simd/src/codegen/llvm.rs122
-rw-r--r--third_party/rust/packed_simd/src/codegen/math.rs3
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float.rs19
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/abs.rs103
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/cos.rs103
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/cos_pi.rs87
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/exp.rs112
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/ln.rs112
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/macros.rs470
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/mul_add.rs109
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/mul_adde.rs60
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/powf.rs112
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/sin.rs103
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/sin_cos_pi.rs188
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/sin_pi.rs87
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/sqrt.rs103
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/sqrte.rs67
-rw-r--r--third_party/rust/packed_simd/src/codegen/math/float/tanh.rs120
-rw-r--r--third_party/rust/packed_simd/src/codegen/pointer_sized_int.rs28
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions.rs1
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask.rs69
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/aarch64.rs81
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/arm.rs56
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/fallback.rs8
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/fallback_impl.rs237
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/x86.rs216
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx.rs95
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx2.rs35
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse.rs35
-rw-r--r--third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse2.rs68
-rw-r--r--third_party/rust/packed_simd/src/codegen/shuffle.rs150
-rw-r--r--third_party/rust/packed_simd/src/codegen/shuffle1_dyn.rs408
-rw-r--r--third_party/rust/packed_simd/src/codegen/swap_bytes.rs149
-rw-r--r--third_party/rust/packed_simd/src/codegen/v128.rs46
-rw-r--r--third_party/rust/packed_simd/src/codegen/v16.rs7
-rw-r--r--third_party/rust/packed_simd/src/codegen/v256.rs78
-rw-r--r--third_party/rust/packed_simd/src/codegen/v32.rs11
-rw-r--r--third_party/rust/packed_simd/src/codegen/v512.rs145
-rw-r--r--third_party/rust/packed_simd/src/codegen/v64.rs21
-rw-r--r--third_party/rust/packed_simd/src/codegen/vPtr.rs35
-rw-r--r--third_party/rust/packed_simd/src/codegen/vSize.rs16
-rw-r--r--third_party/rust/packed_simd/src/lib.rs348
-rw-r--r--third_party/rust/packed_simd/src/masks.rs126
-rw-r--r--third_party/rust/packed_simd/src/sealed.rs42
-rw-r--r--third_party/rust/packed_simd/src/testing.rs8
-rw-r--r--third_party/rust/packed_simd/src/testing/macros.rs44
-rw-r--r--third_party/rust/packed_simd/src/testing/utils.rs130
-rw-r--r--third_party/rust/packed_simd/src/v128.rs80
-rw-r--r--third_party/rust/packed_simd/src/v16.rs16
-rw-r--r--third_party/rust/packed_simd/src/v256.rs86
-rw-r--r--third_party/rust/packed_simd/src/v32.rs29
-rw-r--r--third_party/rust/packed_simd/src/v512.rs99
-rw-r--r--third_party/rust/packed_simd/src/v64.rs66
-rw-r--r--third_party/rust/packed_simd/src/vPtr.rs34
-rw-r--r--third_party/rust/packed_simd/src/vSize.rs53
-rw-r--r--third_party/rust/packed_simd/tests/endianness.rs268
-rw-r--r--third_party/rust/plist/Cargo.toml2
-rw-r--r--third_party/rust/plist/src/lib.rs2
-rw-r--r--third_party/rust/plist/src/stream/binary_writer.rs2
-rw-r--r--third_party/rust/prio/.cargo-checksum.json2
-rw-r--r--third_party/rust/prio/Cargo.toml66
-rw-r--r--third_party/rust/prio/README.md27
-rw-r--r--third_party/rust/prio/benches/cycle_counts.rs63
-rw-r--r--third_party/rust/prio/benches/speed_tests.rs127
-rwxr-xr-xthird_party/rust/prio/documentation/field_parameters.sage117
-rw-r--r--third_party/rust/prio/src/codec.rs210
-rw-r--r--third_party/rust/prio/src/dp.rs1
-rw-r--r--third_party/rust/prio/src/dp/distributions.rs22
-rw-r--r--third_party/rust/prio/src/fft.rs1
-rw-r--r--third_party/rust/prio/src/field.rs379
-rw-r--r--third_party/rust/prio/src/field/field255.rs31
-rw-r--r--third_party/rust/prio/src/flp.rs241
-rw-r--r--third_party/rust/prio/src/flp/types.rs460
-rw-r--r--third_party/rust/prio/src/flp/types/fixedpoint_l2.rs131
-rw-r--r--third_party/rust/prio/src/idpf.rs152
-rw-r--r--third_party/rust/prio/src/lib.rs7
-rw-r--r--third_party/rust/prio/src/polynomial.rs4
-rw-r--r--third_party/rust/prio/src/prng.rs71
-rw-r--r--third_party/rust/prio/src/topology/ping_pong.rs125
-rw-r--r--third_party/rust/prio/src/vdaf.rs437
-rw-r--r--third_party/rust/prio/src/vdaf/dummy.rs147
-rw-r--r--third_party/rust/prio/src/vdaf/poplar1.rs306
-rw-r--r--third_party/rust/prio/src/vdaf/prio2.rs30
-rw-r--r--third_party/rust/prio/src/vdaf/prio2/client.rs16
-rw-r--r--third_party/rust/prio/src/vdaf/prio2/server.rs50
-rw-r--r--third_party/rust/prio/src/vdaf/prio2/test_vector.rs32
-rw-r--r--third_party/rust/prio/src/vdaf/prio3.rs630
-rw-r--r--third_party/rust/prio/src/vdaf/prio3_test.rs162
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/IdpfPoplar_0.json52
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_0.json56
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_1.json64
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_2.json64
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_3.json76
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_0.json39
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_1.json45
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_0.json52
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_1.json89
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_0.json194
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_1.json146
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_0.json40
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_1.json46
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/XofFixedKeyAes128.json8
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/07/XofShake128.json8
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/IdpfPoplar_0.json52
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_0.json56
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_1.json64
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_2.json64
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_3.json76
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_0.json39
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_1.json45
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_0.json52
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_1.json89
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_0.json194
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_1.json146
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_0.json40
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_1.json46
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/XofFixedKeyAes128.json8
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/08/XofTurboShake128.json8
-rw-r--r--third_party/rust/prio/src/vdaf/test_vec/XofHmacSha256Aes128.json8
-rw-r--r--third_party/rust/prio/src/vdaf/xof.rs148
-rw-r--r--third_party/rust/prio/src/vidpf.rs827
-rw-r--r--third_party/rust/prio/tests/discrete_gauss.rs25
-rw-r--r--third_party/rust/prio/tests/test_vectors/discrete_gauss_100.json92
-rw-r--r--third_party/rust/prio/tests/test_vectors/discrete_gauss_2.342.json54
-rw-r--r--third_party/rust/prio/tests/test_vectors/discrete_gauss_3.json62
-rw-r--r--third_party/rust/prio/tests/test_vectors/discrete_gauss_41293847.json98
-rw-r--r--third_party/rust/prio/tests/test_vectors/discrete_gauss_9.json80
-rw-r--r--third_party/rust/prio/tests/test_vectors/discrete_gauss_9999999999999999999999.json98
-rw-r--r--third_party/rust/qlog/.cargo-checksum.json2
-rw-r--r--third_party/rust/qlog/Cargo.toml2
-rw-r--r--third_party/rust/qlog/src/events/mod.rs3
-rw-r--r--third_party/rust/qlog/src/events/quic.rs21
-rw-r--r--third_party/rust/qlog/src/lib.rs28
-rw-r--r--third_party/rust/relevancy/.cargo-checksum.json2
-rw-r--r--third_party/rust/relevancy/Cargo.toml13
-rw-r--r--third_party/rust/relevancy/src/db.rs68
-rw-r--r--third_party/rust/relevancy/src/error.rs15
-rw-r--r--third_party/rust/relevancy/src/ingest.rs394
-rw-r--r--third_party/rust/relevancy/src/interest.rs152
-rw-r--r--third_party/rust/relevancy/src/lib.rs80
-rw-r--r--third_party/rust/relevancy/src/populate_interests.rs157
-rw-r--r--third_party/rust/relevancy/src/relevancy.udl17
-rw-r--r--third_party/rust/relevancy/src/rs.rs60
-rw-r--r--third_party/rust/relevancy/src/url_hash.rs15
-rw-r--r--third_party/rust/relevancy/test-databin192 -> 188 bytes
-rw-r--r--third_party/rust/remote_settings/.cargo-checksum.json2
-rw-r--r--third_party/rust/remote_settings/src/client.rs89
-rw-r--r--third_party/rust/remote_settings/src/config.rs30
-rw-r--r--third_party/rust/remote_settings/src/error.rs2
-rw-r--r--third_party/rust/remote_settings/src/lib.rs17
-rw-r--r--third_party/rust/remote_settings/src/remote_settings.udl10
-rw-r--r--third_party/rust/serde/.cargo-checksum.json2
-rw-r--r--third_party/rust/serde/Cargo.toml4
-rw-r--r--third_party/rust/serde/build.rs6
-rw-r--r--third_party/rust/serde/src/de/impls.rs119
-rw-r--r--third_party/rust/serde/src/de/mod.rs8
-rw-r--r--third_party/rust/serde/src/lib.rs5
-rw-r--r--third_party/rust/serde/src/private/de.rs7
-rw-r--r--third_party/rust/serde/src/private/doc.rs5
-rw-r--r--third_party/rust/serde/src/private/ser.rs132
-rw-r--r--third_party/rust/serde/src/ser/fmt.rs16
-rw-r--r--third_party/rust/serde/src/ser/impls.rs51
-rw-r--r--third_party/rust/serde/src/ser/impossible.rs32
-rw-r--r--third_party/rust/serde/src/ser/mod.rs79
-rw-r--r--third_party/rust/serde_derive/.cargo-checksum.json2
-rw-r--r--third_party/rust/serde_derive/Cargo.toml3
-rw-r--r--third_party/rust/serde_derive/src/lib.rs2
-rw-r--r--third_party/rust/serde_derive/src/ser.rs4
-rw-r--r--third_party/rust/serde_json/.cargo-checksum.json2
-rw-r--r--third_party/rust/serde_json/Cargo.toml33
-rw-r--r--third_party/rust/serde_json/README.md2
-rw-r--r--third_party/rust/serde_json/build.rs39
-rw-r--r--third_party/rust/serde_json/src/de.rs295
-rw-r--r--third_party/rust/serde_json/src/error.rs128
-rw-r--r--third_party/rust/serde_json/src/features_check/error.rs1
-rw-r--r--third_party/rust/serde_json/src/features_check/mod.rs13
-rw-r--r--third_party/rust/serde_json/src/io/core.rs2
-rw-r--r--third_party/rust/serde_json/src/lexical/algorithm.rs5
-rw-r--r--third_party/rust/serde_json/src/lexical/bignum.rs1
-rw-r--r--third_party/rust/serde_json/src/lexical/digit.rs5
-rw-r--r--third_party/rust/serde_json/src/lexical/errors.rs3
-rw-r--r--third_party/rust/serde_json/src/lexical/exponent.rs4
-rw-r--r--third_party/rust/serde_json/src/lexical/large_powers32.rs2
-rw-r--r--third_party/rust/serde_json/src/lexical/large_powers64.rs2
-rw-r--r--third_party/rust/serde_json/src/lexical/math.rs4
-rw-r--r--third_party/rust/serde_json/src/lexical/num.rs13
-rw-r--r--third_party/rust/serde_json/src/lexical/rounding.rs2
-rw-r--r--third_party/rust/serde_json/src/lib.rs35
-rw-r--r--third_party/rust/serde_json/src/macros.rs3
-rw-r--r--third_party/rust/serde_json/src/map.rs131
-rw-r--r--third_party/rust/serde_json/src/number.rs76
-rw-r--r--third_party/rust/serde_json/src/raw.rs270
-rw-r--r--third_party/rust/serde_json/src/read.rs6
-rw-r--r--third_party/rust/serde_json/src/ser.rs122
-rw-r--r--third_party/rust/serde_json/src/value/de.rs94
-rw-r--r--third_party/rust/serde_json/src/value/from.rs37
-rw-r--r--third_party/rust/serde_json/src/value/index.rs2
-rw-r--r--third_party/rust/serde_json/src/value/mod.rs30
-rw-r--r--third_party/rust/serde_json/src/value/partial_eq.rs14
-rw-r--r--third_party/rust/serde_json/src/value/ser.rs41
-rw-r--r--third_party/rust/serde_json/tests/lexical.rs6
-rw-r--r--third_party/rust/serde_json/tests/lexical/exponent.rs34
-rw-r--r--third_party/rust/serde_json/tests/lexical/parse.rs2
-rw-r--r--third_party/rust/serde_json/tests/map.rs1
-rw-r--r--third_party/rust/serde_json/tests/regression/issue1004.rs12
-rw-r--r--third_party/rust/serde_json/tests/regression/issue520.rs2
-rw-r--r--third_party/rust/serde_json/tests/regression/issue795.rs5
-rw-r--r--third_party/rust/serde_json/tests/regression/issue845.rs2
-rw-r--r--third_party/rust/serde_json/tests/test.rs245
-rw-r--r--third_party/rust/serde_json/tests/ui/parse_key.stderr2
-rw-r--r--third_party/rust/sfv/.cargo-checksum.json2
-rw-r--r--third_party/rust/sfv/Cargo.toml4
-rw-r--r--third_party/rust/sql-support/.cargo-checksum.json2
-rw-r--r--third_party/rust/sql-support/Cargo.toml1
-rw-r--r--third_party/rust/sql-support/src/lazy.rs151
-rw-r--r--third_party/rust/sql-support/src/lib.rs10
-rw-r--r--third_party/rust/sql-support/src/open_database.rs204
-rw-r--r--third_party/rust/suggest/.cargo-checksum.json2
-rw-r--r--third_party/rust/suggest/src/benchmarks/client.rs1
-rw-r--r--third_party/rust/suggest/src/db.rs6
-rw-r--r--third_party/rust/suggest/src/lib.rs2
-rw-r--r--third_party/rust/suggest/src/schema.rs454
-rw-r--r--third_party/rust/suggest/src/store.rs216
-rw-r--r--third_party/rust/suggest/src/suggest.udl15
-rw-r--r--third_party/rust/thiserror-impl/.cargo-checksum.json2
-rw-r--r--third_party/rust/thiserror-impl/Cargo.toml2
-rw-r--r--third_party/rust/thiserror-impl/src/ast.rs2
-rw-r--r--third_party/rust/thiserror-impl/src/attr.rs15
-rw-r--r--third_party/rust/thiserror-impl/src/expand.rs4
-rw-r--r--third_party/rust/thiserror/.cargo-checksum.json2
-rw-r--r--third_party/rust/thiserror/Cargo.toml4
-rw-r--r--third_party/rust/thiserror/build.rs20
-rw-r--r--third_party/rust/thiserror/src/lib.rs2
-rw-r--r--third_party/rust/thiserror/tests/test_lints.rs2
-rw-r--r--third_party/rust/uniffi-example-arithmetic/.cargo-checksum.json1
-rw-r--r--third_party/rust/uniffi-example-arithmetic/Cargo.toml42
-rw-r--r--third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.py37
-rw-r--r--third_party/rust/uniffi-example-geometry/.cargo-checksum.json1
-rw-r--r--third_party/rust/uniffi-example-geometry/Cargo.toml39
-rw-r--r--third_party/rust/uniffi-example-rondpoint/.cargo-checksum.json1
-rw-r--r--third_party/rust/uniffi-example-rondpoint/Cargo.toml39
-rw-r--r--third_party/rust/uniffi-example-sprites/.cargo-checksum.json1
-rw-r--r--third_party/rust/uniffi-example-sprites/Cargo.toml39
-rw-r--r--third_party/rust/uniffi-example-todolist/.cargo-checksum.json1
-rw-r--r--third_party/rust/uniffi-example-todolist/Cargo.toml43
-rw-r--r--third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.py44
-rw-r--r--third_party/rust/wasm-encoder/.cargo-checksum.json2
-rw-r--r--third_party/rust/wasm-encoder/Cargo.toml4
-rw-r--r--third_party/rust/wasm-encoder/src/component/types.rs16
-rw-r--r--third_party/rust/wasm-encoder/src/core/code.rs60
-rw-r--r--third_party/rust/wasm-encoder/src/core/data.rs1
-rw-r--r--third_party/rust/wasm-encoder/src/core/globals.rs13
-rw-r--r--third_party/rust/wasm-encoder/src/core/imports.rs1
-rw-r--r--third_party/rust/wasm-encoder/src/core/memories.rs25
-rw-r--r--third_party/rust/wasm-encoder/src/core/types.rs15
-rw-r--r--third_party/rust/wasm-smith/.cargo-checksum.json2
-rw-r--r--third_party/rust/wasm-smith/Cargo.toml10
-rw-r--r--third_party/rust/wasm-smith/src/component.rs17
-rw-r--r--third_party/rust/wasm-smith/src/config.rs9
-rw-r--r--third_party/rust/wasm-smith/src/core.rs202
-rw-r--r--third_party/rust/wasm-smith/src/core/code_builder.rs77
-rw-r--r--third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs10
-rw-r--r--third_party/rust/wasm-smith/src/core/terminate.rs1
-rw-r--r--third_party/rust/wasm-smith/src/lib.rs6
-rw-r--r--third_party/rust/wasm-smith/tests/common/mod.rs52
-rw-r--r--third_party/rust/wasm-smith/tests/component.rs8
-rw-r--r--third_party/rust/wasm-smith/tests/core.rs55
-rw-r--r--third_party/rust/wasm-smith/tests/exports.rs32
-rw-r--r--third_party/rust/wast/.cargo-checksum.json2
-rw-r--r--third_party/rust/wast/Cargo.toml8
-rw-r--r--third_party/rust/wast/src/component/binary.rs30
-rw-r--r--third_party/rust/wast/src/component/resolve.rs3
-rw-r--r--third_party/rust/wast/src/component/types.rs16
-rw-r--r--third_party/rust/wast/src/component/wast.rs10
-rw-r--r--third_party/rust/wast/src/core/binary.rs84
-rw-r--r--third_party/rust/wast/src/core/expr.rs158
-rw-r--r--third_party/rust/wast/src/core/memory.rs11
-rw-r--r--third_party/rust/wast/src/core/resolve/deinline_import_export.rs6
-rw-r--r--third_party/rust/wast/src/core/resolve/names.rs28
-rw-r--r--third_party/rust/wast/src/core/resolve/types.rs4
-rw-r--r--third_party/rust/wast/src/core/types.rs78
-rw-r--r--third_party/rust/wast/src/core/wast.rs18
-rw-r--r--third_party/rust/wast/src/lib.rs5
-rw-r--r--third_party/rust/wast/src/token.rs20
-rw-r--r--third_party/rust/wast/src/wast.rs75
-rw-r--r--third_party/rust/wast/src/wat.rs8
-rw-r--r--third_party/rust/wast/tests/parse-fail.rs42
-rw-r--r--third_party/rust/wgpu-core/.cargo-checksum.json2
-rw-r--r--third_party/rust/wgpu-core/Cargo.toml10
-rw-r--r--third_party/rust/wgpu-core/src/any_surface.rs95
-rw-r--r--third_party/rust/wgpu-core/src/binding_model.rs2
-rw-r--r--third_party/rust/wgpu-core/src/command/allocator.rs67
-rw-r--r--third_party/rust/wgpu-core/src/command/bundle.rs21
-rw-r--r--third_party/rust/wgpu-core/src/command/clear.rs9
-rw-r--r--third_party/rust/wgpu-core/src/command/compute.rs318
-rw-r--r--third_party/rust/wgpu-core/src/command/compute_command.rs322
-rw-r--r--third_party/rust/wgpu-core/src/command/mod.rs249
-rw-r--r--third_party/rust/wgpu-core/src/command/query.rs11
-rw-r--r--third_party/rust/wgpu-core/src/command/render.rs168
-rw-r--r--third_party/rust/wgpu-core/src/command/transfer.rs35
-rw-r--r--third_party/rust/wgpu-core/src/device/any_device.rs2
-rw-r--r--third_party/rust/wgpu-core/src/device/bgl.rs2
-rw-r--r--third_party/rust/wgpu-core/src/device/global.rs77
-rw-r--r--third_party/rust/wgpu-core/src/device/life.rs123
-rw-r--r--third_party/rust/wgpu-core/src/device/mod.rs37
-rw-r--r--third_party/rust/wgpu-core/src/device/queue.rs169
-rw-r--r--third_party/rust/wgpu-core/src/device/resource.rs544
-rw-r--r--third_party/rust/wgpu-core/src/global.rs10
-rw-r--r--third_party/rust/wgpu-core/src/hal_api.rs20
-rw-r--r--third_party/rust/wgpu-core/src/hub.rs36
-rw-r--r--third_party/rust/wgpu-core/src/id.rs47
-rw-r--r--third_party/rust/wgpu-core/src/identity.rs40
-rw-r--r--third_party/rust/wgpu-core/src/instance.rs357
-rw-r--r--third_party/rust/wgpu-core/src/lib.rs4
-rw-r--r--third_party/rust/wgpu-core/src/lock/mod.rs41
-rw-r--r--third_party/rust/wgpu-core/src/lock/rank.rs170
-rw-r--r--third_party/rust/wgpu-core/src/lock/ranked.rs397
-rw-r--r--third_party/rust/wgpu-core/src/lock/vanilla.rs121
-rw-r--r--third_party/rust/wgpu-core/src/pipeline.rs102
-rw-r--r--third_party/rust/wgpu-core/src/pool.rs12
-rw-r--r--third_party/rust/wgpu-core/src/present.rs30
-rw-r--r--third_party/rust/wgpu-core/src/registry.rs89
-rw-r--r--third_party/rust/wgpu-core/src/resource.rs74
-rw-r--r--third_party/rust/wgpu-core/src/snatch.rs88
-rw-r--r--third_party/rust/wgpu-core/src/storage.rs5
-rw-r--r--third_party/rust/wgpu-core/src/track/buffer.rs24
-rw-r--r--third_party/rust/wgpu-core/src/track/metadata.rs10
-rw-r--r--third_party/rust/wgpu-core/src/track/mod.rs45
-rw-r--r--third_party/rust/wgpu-core/src/track/stateless.rs22
-rw-r--r--third_party/rust/wgpu-core/src/track/texture.rs4
-rw-r--r--third_party/rust/wgpu-core/src/validation.rs3
-rw-r--r--third_party/rust/wgpu-hal/.cargo-checksum.json2
-rw-r--r--third_party/rust/wgpu-hal/Cargo.toml19
-rw-r--r--third_party/rust/wgpu-hal/README.md129
-rw-r--r--third_party/rust/wgpu-hal/examples/halmark/main.rs6
-rw-r--r--third_party/rust/wgpu-hal/examples/ray-traced-triangle/main.rs2
-rw-r--r--third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs1
-rw-r--r--third_party/rust/wgpu-hal/src/dx12/adapter.rs99
-rw-r--r--third_party/rust/wgpu-hal/src/dx12/conv.rs2
-rw-r--r--third_party/rust/wgpu-hal/src/dx12/device.rs33
-rw-r--r--third_party/rust/wgpu-hal/src/dx12/mod.rs3
-rw-r--r--third_party/rust/wgpu-hal/src/dx12/types.rs22
-rw-r--r--third_party/rust/wgpu-hal/src/gles/adapter.rs33
-rw-r--r--third_party/rust/wgpu-hal/src/gles/conv.rs1
-rw-r--r--third_party/rust/wgpu-hal/src/gles/device.rs37
-rw-r--r--third_party/rust/wgpu-hal/src/gles/egl.rs74
-rw-r--r--third_party/rust/wgpu-hal/src/gles/mod.rs1
-rw-r--r--third_party/rust/wgpu-hal/src/gles/queue.rs71
-rw-r--r--third_party/rust/wgpu-hal/src/gles/wgl.rs2
-rw-r--r--third_party/rust/wgpu-hal/src/lib.rs346
-rw-r--r--third_party/rust/wgpu-hal/src/metal/adapter.rs22
-rw-r--r--third_party/rust/wgpu-hal/src/metal/conv.rs1
-rw-r--r--third_party/rust/wgpu-hal/src/metal/device.rs24
-rw-r--r--third_party/rust/wgpu-hal/src/metal/mod.rs12
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/adapter.rs123
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/command.rs5
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/conv.rs1
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/device.rs30
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/mod.rs109
-rw-r--r--third_party/rust/wgpu-types/.cargo-checksum.json2
-rw-r--r--third_party/rust/wgpu-types/Cargo.toml4
-rw-r--r--third_party/rust/wgpu-types/src/lib.rs100
-rw-r--r--third_party/rust/zerocopy-derive/.cargo-checksum.json1
-rw-r--r--third_party/rust/zerocopy-derive/Cargo.toml44
-rw-r--r--third_party/rust/zerocopy-derive/LICENSE-APACHE202
-rw-r--r--third_party/rust/zerocopy-derive/LICENSE-BSD24
-rw-r--r--third_party/rust/zerocopy-derive/LICENSE-MIT26
-rw-r--r--third_party/rust/zerocopy-derive/src/ext.rs53
-rw-r--r--third_party/rust/zerocopy-derive/src/lib.rs882
-rw-r--r--third_party/rust/zerocopy-derive/src/repr.rs311
-rw-r--r--third_party/rust/zerocopy-derive/tests/enum_as_bytes.rs101
-rw-r--r--third_party/rust/zerocopy-derive/tests/enum_from_zeroes.rs35
-rw-r--r--third_party/rust/zerocopy-derive/tests/enum_known_layout.rs46
-rw-r--r--third_party/rust/zerocopy-derive/tests/enum_unaligned.rs47
-rw-r--r--third_party/rust/zerocopy-derive/tests/hygiene.rs43
-rw-r--r--third_party/rust/zerocopy-derive/tests/paths_and_modules.rs38
-rw-r--r--third_party/rust/zerocopy-derive/tests/priv_in_pub.rs24
-rw-r--r--third_party/rust/zerocopy-derive/tests/struct_as_bytes.rs161
-rw-r--r--third_party/rust/zerocopy-derive/tests/struct_from_bytes.rs79
-rw-r--r--third_party/rust/zerocopy-derive/tests/struct_from_zeroes.rs77
-rw-r--r--third_party/rust/zerocopy-derive/tests/struct_known_layout.rs65
-rw-r--r--third_party/rust/zerocopy-derive/tests/struct_unaligned.rs100
-rw-r--r--third_party/rust/zerocopy-derive/tests/trybuild.rs19
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.rs40
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr71
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/enum.rs194
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/enum.stderr199
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs272
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr11
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs75
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr74
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs61
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr104
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/struct.rs99
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/struct.stderr113
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/union.rs73
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-msrv/union.stderr42
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.rs40
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr111
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/enum.rs194
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/enum.stderr201
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs272
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr11
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs75
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr150
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs61
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr104
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/struct.rs99
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/struct.stderr143
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/union.rs73
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-nightly/union.stderr48
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.rs40
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.stderr111
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/enum.rs194
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/enum.stderr201
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs272
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr11
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.rs75
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr144
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs61
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr104
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/struct.rs99
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/struct.stderr131
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/union.rs73
-rw-r--r--third_party/rust/zerocopy-derive/tests/ui-stable/union.stderr41
-rw-r--r--third_party/rust/zerocopy-derive/tests/union_as_bytes.rs75
-rw-r--r--third_party/rust/zerocopy-derive/tests/union_from_bytes.rs72
-rw-r--r--third_party/rust/zerocopy-derive/tests/union_from_zeroes.rs72
-rw-r--r--third_party/rust/zerocopy-derive/tests/union_known_layout.rs65
-rw-r--r--third_party/rust/zerocopy-derive/tests/union_unaligned.rs77
-rw-r--r--third_party/rust/zerocopy-derive/tests/util.rs20
-rw-r--r--third_party/rust/zerocopy/.cargo-checksum.json1
-rw-r--r--third_party/rust/zerocopy/CONTRIBUTING.md215
-rw-r--r--third_party/rust/zerocopy/Cargo.toml87
-rw-r--r--third_party/rust/zerocopy/INTERNAL.md44
-rw-r--r--third_party/rust/zerocopy/LICENSE-APACHE202
-rw-r--r--third_party/rust/zerocopy/LICENSE-BSD24
-rw-r--r--third_party/rust/zerocopy/LICENSE-MIT26
-rw-r--r--third_party/rust/zerocopy/POLICIES.md103
-rw-r--r--third_party/rust/zerocopy/README.md154
-rwxr-xr-xthird_party/rust/zerocopy/cargo.sh120
-rw-r--r--third_party/rust/zerocopy/clippy.toml10
-rwxr-xr-xthird_party/rust/zerocopy/generate-readme.sh50
-rw-r--r--third_party/rust/zerocopy/rustfmt.toml19
-rw-r--r--third_party/rust/zerocopy/src/byteorder.rs1075
-rw-r--r--third_party/rust/zerocopy/src/lib.rs8256
-rw-r--r--third_party/rust/zerocopy/src/macro_util.rs670
-rw-r--r--third_party/rust/zerocopy/src/macros.rs417
-rw-r--r--third_party/rust/zerocopy/src/post_monomorphization_compile_fail_tests.rs118
-rw-r--r--third_party/rust/zerocopy/src/third_party/rust/LICENSE-APACHE176
-rw-r--r--third_party/rust/zerocopy/src/third_party/rust/LICENSE-MIT23
-rw-r--r--third_party/rust/zerocopy/src/third_party/rust/README.fuchsia7
-rw-r--r--third_party/rust/zerocopy/src/third_party/rust/layout.rs45
-rw-r--r--third_party/rust/zerocopy/src/util.rs808
-rw-r--r--third_party/rust/zerocopy/src/wrappers.rs503
-rw-r--r--third_party/rust/zerocopy/testdata/include_value/data1
-rw-r--r--third_party/rust/zerocopy/tests/trybuild.rs41
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.rs11
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs29
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr127
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/max-align.rs99
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/max-align.stderr5
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.stderr36
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.rs20
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.stderr41
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr39
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr108
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs15
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.stderr36
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.stderr36
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.stderr237
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.stderr10
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr11
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs16
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr198
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs20
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr37
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr29
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr29
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr94
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs15
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr42
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.stderr195
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs16
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr170
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs12
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.rs11
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs29
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr107
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/max-align.rs99
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/max-align.stderr5
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.rs20
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.stderr42
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr39
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr86
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs15
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr15
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.stderr231
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.stderr10
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr11
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr15
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.stderr48
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr48
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs16
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr158
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs20
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr30
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr29
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr29
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr69
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs15
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr45
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.stderr183
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr15
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.stderr48
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs16
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr127
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.stderr48
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs12
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.rs11
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs29
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr107
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/max-align.rs99
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/max-align.stderr5
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.rs20
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.stderr41
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr39
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr106
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs15
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr15
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr288
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.stderr10
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr11
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr15
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.stderr48
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs24
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr48
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs16
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr195
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs20
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr30
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr29
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr29
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr25
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr89
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs15
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr12
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr45
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr240
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.stderr19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs17
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr15
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.stderr48
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs16
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr164
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.rs19
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.stderr9
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.rs18
-rw-r--r--third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.stderr48
-rw-r--r--third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp2
-rw-r--r--third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_memory.hpp38
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_avx.hpp38
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_avx2.hpp20
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_avx512bw.hpp16
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_avx512f.hpp48
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_emulated.hpp757
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_isa.hpp4
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_neon.hpp8
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_neon64.hpp70
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_rvv.hpp12
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_scalar.hpp114
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_sse2.hpp97
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_sse4_1.hpp14
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_ssse3.hpp16
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_sve.hpp12
-rw-r--r--third_party/xsimd/include/xsimd/arch/xsimd_wasm.hpp32
-rw-r--r--third_party/xsimd/include/xsimd/types/xsimd_all_registers.hpp4
-rw-r--r--third_party/xsimd/include/xsimd/types/xsimd_api.hpp29
-rw-r--r--third_party/xsimd/include/xsimd/types/xsimd_batch_constant.hpp122
-rw-r--r--third_party/xsimd/include/xsimd/types/xsimd_emulated_register.hpp80
-rw-r--r--third_party/xsimd/moz.yaml4
-rw-r--r--third_party/zstd/moz.build1
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/build.rs (renamed from third_party/rust/uniffi-example-arithmetic/build.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/src/arithmetic.udl (renamed from third_party/rust/uniffi-example-arithmetic/src/arithmetic.udl)0
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/src/lib.rs (renamed from third_party/rust/uniffi-example-arithmetic/src/lib.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.kts (renamed from third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.kts)0
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.rb (renamed from third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.rb)0
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.swift (renamed from third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.swift)0
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/tests/test_generated_bindings.rs (renamed from third_party/rust/uniffi-example-arithmetic/tests/test_generated_bindings.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/arithmetic/uniffi.toml (renamed from third_party/rust/uniffi-example-arithmetic/uniffi.toml)0
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/build.rs (renamed from third_party/rust/uniffi-example-geometry/build.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/src/geometry.udl (renamed from third_party/rust/uniffi-example-geometry/src/geometry.udl)0
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/src/lib.rs (renamed from third_party/rust/uniffi-example-geometry/src/lib.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.kts (renamed from third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.kts)0
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.py (renamed from third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.py)2
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.rb (renamed from third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.rb)0
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.swift (renamed from third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.swift)0
-rw-r--r--toolkit/components/uniffi-fixtures/geometry/tests/test_generated_bindings.rs (renamed from third_party/rust/uniffi-example-geometry/tests/test_generated_bindings.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/build.rs (renamed from third_party/rust/uniffi-example-rondpoint/build.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/src/lib.rs (renamed from third_party/rust/uniffi-example-rondpoint/src/lib.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/src/rondpoint.udl (renamed from third_party/rust/uniffi-example-rondpoint/src/rondpoint.udl)0
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.kts (renamed from third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.kts)0
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.py (renamed from third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.py)75
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.rb (renamed from third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.rb)0
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift (renamed from third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.swift)0
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/tests/test_generated_bindings.rs (renamed from third_party/rust/uniffi-example-rondpoint/tests/test_generated_bindings.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/build.rs (renamed from third_party/rust/uniffi-example-sprites/build.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/src/lib.rs (renamed from third_party/rust/uniffi-example-sprites/src/lib.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/src/sprites.udl (renamed from third_party/rust/uniffi-example-sprites/src/sprites.udl)0
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.kts (renamed from third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.kts)0
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.py (renamed from third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.py)3
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.rb (renamed from third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.rb)0
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.swift (renamed from third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.swift)0
-rw-r--r--toolkit/components/uniffi-fixtures/sprites/tests/test_generated_bindings.rs (renamed from third_party/rust/uniffi-example-sprites/tests/test_generated_bindings.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/todolist/build.rs (renamed from third_party/rust/uniffi-example-todolist/build.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/todolist/src/lib.rs (renamed from third_party/rust/uniffi-example-todolist/src/lib.rs)0
-rw-r--r--toolkit/components/uniffi-fixtures/todolist/src/todolist.udl (renamed from third_party/rust/uniffi-example-todolist/src/todolist.udl)0
-rw-r--r--toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.kts (renamed from third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.kts)0
-rw-r--r--toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.rb (renamed from third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.rb)0
-rw-r--r--toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.swift (renamed from third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.swift)0
-rw-r--r--toolkit/components/uniffi-fixtures/todolist/tests/test_generated_bindings.rs (renamed from third_party/rust/uniffi-example-todolist/tests/test_generated_bindings.rs)0
2358 files changed, 376490 insertions, 96621 deletions
diff --git a/third_party/rust/cssparser/docs/.nojekyll b/js/src/tests/non262/Temporal/PlainDate/shell.js
index e69de29bb2..e69de29bb2 100644
--- a/third_party/rust/cssparser/docs/.nojekyll
+++ b/js/src/tests/non262/Temporal/PlainDate/shell.js
diff --git a/third_party/aom/aom/aom_image.h b/third_party/aom/aom/aom_image.h
index d5f0c087e6..68fb312222 100644
--- a/third_party/aom/aom/aom_image.h
+++ b/third_party/aom/aom/aom_image.h
@@ -103,7 +103,8 @@ typedef enum aom_transfer_characteristics {
AOM_CICP_TC_SMPTE_428 = 17, /**< SMPTE ST 428 */
AOM_CICP_TC_HLG = 18, /**< BT.2100 HLG, ARIB STD-B67 */
AOM_CICP_TC_RESERVED_19 = 19 /**< For future use (values 19-255) */
-} aom_transfer_characteristics_t; /**< alias for enum aom_transfer_function */
+} aom_transfer_characteristics_t; /**< alias for enum
+ aom_transfer_characteristics */
/*!\brief List of supported matrix coefficients */
typedef enum aom_matrix_coefficients {
@@ -125,7 +126,7 @@ typedef enum aom_matrix_coefficients {
AOM_CICP_MC_CHROMAT_CL = 13, /**< Chromaticity-derived constant luminance */
AOM_CICP_MC_ICTCP = 14, /**< BT.2100 ICtCp */
AOM_CICP_MC_RESERVED_15 = 15 /**< For future use (values 15-255) */
-} aom_matrix_coefficients_t;
+} aom_matrix_coefficients_t; /**< alias for enum aom_matrix_coefficients */
/*!\brief List of supported color range */
typedef enum aom_color_range {
@@ -144,7 +145,8 @@ typedef enum aom_chroma_sample_position {
/**< sample, between two vertical samples */
AOM_CSP_COLOCATED = 2, /**< Co-located with luma(0, 0) sample */
AOM_CSP_RESERVED = 3 /**< Reserved value */
-} aom_chroma_sample_position_t; /**< alias for enum aom_transfer_function */
+} aom_chroma_sample_position_t; /**< alias for enum aom_chroma_sample_position
+ */
/*!\brief List of insert flags for Metadata
*
@@ -244,10 +246,13 @@ typedef struct aom_image {
* is NULL, the storage for the descriptor will be
* allocated on the heap.
* \param[in] fmt Format for the image
- * \param[in] d_w Width of the image
- * \param[in] d_h Height of the image
+ * \param[in] d_w Width of the image. Must not exceed 0x08000000
+ * (2^27).
+ * \param[in] d_h Height of the image. Must not exceed 0x08000000
+ * (2^27).
* \param[in] align Alignment, in bytes, of the image buffer and
- * each row in the image (stride).
+ * each row in the image (stride). Must not exceed
+ * 65536.
*
* \return Returns a pointer to the initialized image descriptor. If the img
* parameter is non-null, the value of the img parameter will be
@@ -267,10 +272,12 @@ aom_image_t *aom_img_alloc(aom_image_t *img, aom_img_fmt_t fmt,
* is NULL, the storage for the descriptor will be
* allocated on the heap.
* \param[in] fmt Format for the image
- * \param[in] d_w Width of the image
- * \param[in] d_h Height of the image
+ * \param[in] d_w Width of the image. Must not exceed 0x08000000
+ * (2^27).
+ * \param[in] d_h Height of the image. Must not exceed 0x08000000
+ * (2^27).
* \param[in] align Alignment, in bytes, of each row in the image
- * (stride).
+ * (stride). Must not exceed 65536.
* \param[in] img_data Storage to use for the image
*
* \return Returns a pointer to the initialized image descriptor. If the img
@@ -291,12 +298,17 @@ aom_image_t *aom_img_wrap(aom_image_t *img, aom_img_fmt_t fmt, unsigned int d_w,
* is NULL, the storage for the descriptor will be
* allocated on the heap.
* \param[in] fmt Format for the image
- * \param[in] d_w Width of the image
- * \param[in] d_h Height of the image
+ * \param[in] d_w Width of the image. Must not exceed 0x08000000
+ * (2^27).
+ * \param[in] d_h Height of the image. Must not exceed 0x08000000
+ * (2^27).
* \param[in] align Alignment, in bytes, of the image buffer and
- * each row in the image (stride).
+ * each row in the image (stride). Must not exceed
+ * 65536.
* \param[in] size_align Alignment, in pixels, of the image width and height.
+ * Must not exceed 65536.
* \param[in] border A border that is padded on four sides of the image.
+ * Must not exceed 65536.
*
* \return Returns a pointer to the initialized image descriptor. If the img
* parameter is non-null, the value of the img parameter will be
diff --git a/third_party/aom/aom/src/aom_image.c b/third_party/aom/aom/src/aom_image.c
index 3b1c33d056..1d3b7df245 100644
--- a/third_party/aom/aom/src/aom_image.c
+++ b/third_party/aom/aom/src/aom_image.c
@@ -9,6 +9,7 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
+#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -36,13 +37,20 @@ static aom_image_t *img_alloc_helper(
/* NOTE: In this function, bit_depth is either 8 or 16 (if
* AOM_IMG_FMT_HIGHBITDEPTH is set), never 10 or 12.
*/
- unsigned int h, w, s, xcs, ycs, bps, bit_depth;
- unsigned int stride_in_bytes;
+ unsigned int xcs, ycs, bps, bit_depth;
if (img != NULL) memset(img, 0, sizeof(aom_image_t));
if (fmt == AOM_IMG_FMT_NONE) goto fail;
+ /* Impose maximum values on input parameters so that this function can
+ * perform arithmetic operations without worrying about overflows.
+ */
+ if (d_w > 0x08000000 || d_h > 0x08000000 || buf_align > 65536 ||
+ stride_align > 65536 || size_align > 65536 || border > 65536) {
+ goto fail;
+ }
+
/* Treat align==0 like align==1 */
if (!buf_align) buf_align = 1;
@@ -105,12 +113,17 @@ static aom_image_t *img_alloc_helper(
}
/* Calculate storage sizes given the chroma subsampling */
- w = align_image_dimension(d_w, xcs, size_align);
- h = align_image_dimension(d_h, ycs, size_align);
-
- s = (fmt & AOM_IMG_FMT_PLANAR) ? w : bps * w / bit_depth;
- s = (s + 2 * border + stride_align - 1) & ~(stride_align - 1);
- stride_in_bytes = s * bit_depth / 8;
+ const unsigned int w = align_image_dimension(d_w, xcs, size_align);
+ assert(d_w <= w);
+ const unsigned int h = align_image_dimension(d_h, ycs, size_align);
+ assert(d_h <= h);
+
+ uint64_t s = (uint64_t)w + 2 * border;
+ s = (fmt & AOM_IMG_FMT_PLANAR) ? s : s * bps / bit_depth;
+ s = s * bit_depth / 8;
+ s = (s + stride_align - 1) & ~((uint64_t)stride_align - 1);
+ if (s > INT_MAX) goto fail;
+ const int stride_in_bytes = (int)s;
/* Allocate the new image */
if (!img) {
@@ -232,7 +245,7 @@ int aom_img_set_rect(aom_image_t *img, unsigned int x, unsigned int y,
img->planes[AOM_PLANE_Y] =
data + x * bytes_per_sample + y * img->stride[AOM_PLANE_Y];
- data += (img->h + 2 * border) * img->stride[AOM_PLANE_Y];
+ data += ((size_t)img->h + 2 * border) * img->stride[AOM_PLANE_Y];
unsigned int uv_border_h = border >> img->y_chroma_shift;
unsigned int uv_x = x >> img->x_chroma_shift;
@@ -244,14 +257,14 @@ int aom_img_set_rect(aom_image_t *img, unsigned int x, unsigned int y,
} else if (!(img->fmt & AOM_IMG_FMT_UV_FLIP)) {
img->planes[AOM_PLANE_U] =
data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_U];
- data += ((img->h >> img->y_chroma_shift) + 2 * uv_border_h) *
+ data += ((size_t)(img->h >> img->y_chroma_shift) + 2 * uv_border_h) *
img->stride[AOM_PLANE_U];
img->planes[AOM_PLANE_V] =
data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_V];
} else {
img->planes[AOM_PLANE_V] =
data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_V];
- data += ((img->h >> img->y_chroma_shift) + 2 * uv_border_h) *
+ data += ((size_t)(img->h >> img->y_chroma_shift) + 2 * uv_border_h) *
img->stride[AOM_PLANE_V];
img->planes[AOM_PLANE_U] =
data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_U];
@@ -291,15 +304,15 @@ void aom_img_free(aom_image_t *img) {
}
int aom_img_plane_width(const aom_image_t *img, int plane) {
- if (plane > 0 && img->x_chroma_shift > 0)
- return (img->d_w + 1) >> img->x_chroma_shift;
+ if (plane > 0)
+ return (img->d_w + img->x_chroma_shift) >> img->x_chroma_shift;
else
return img->d_w;
}
int aom_img_plane_height(const aom_image_t *img, int plane) {
- if (plane > 0 && img->y_chroma_shift > 0)
- return (img->d_h + 1) >> img->y_chroma_shift;
+ if (plane > 0)
+ return (img->d_h + img->y_chroma_shift) >> img->y_chroma_shift;
else
return img->d_h;
}
diff --git a/third_party/aom/aom_dsp/aom_dsp.cmake b/third_party/aom/aom_dsp/aom_dsp.cmake
index de987cbd23..27099d36b2 100644
--- a/third_party/aom/aom_dsp/aom_dsp.cmake
+++ b/third_party/aom/aom_dsp/aom_dsp.cmake
@@ -205,6 +205,9 @@ if(CONFIG_AV1_ENCODER)
list(APPEND AOM_DSP_ENCODER_INTRIN_NEON
"${AOM_ROOT}/aom_dsp/flow_estimation/arm/disflow_neon.c")
+
+ list(APPEND AOM_DSP_ENCODER_INTRIN_SVE
+ "${AOM_ROOT}/aom_dsp/flow_estimation/arm/disflow_sve.c")
endif()
list(APPEND AOM_DSP_ENCODER_ASM_SSE2 "${AOM_ROOT}/aom_dsp/x86/sad4d_sse2.asm"
diff --git a/third_party/aom/aom_dsp/aom_dsp_rtcd_defs.pl b/third_party/aom/aom_dsp/aom_dsp_rtcd_defs.pl
index 7e746e9cb9..b75bdc5a19 100755
--- a/third_party/aom/aom_dsp/aom_dsp_rtcd_defs.pl
+++ b/third_party/aom/aom_dsp/aom_dsp_rtcd_defs.pl
@@ -1799,7 +1799,7 @@ if (aom_config("CONFIG_AV1_ENCODER") eq "yes") {
specialize qw/aom_compute_correlation sse4_1 avx2/;
add_proto qw/void aom_compute_flow_at_point/, "const uint8_t *src, const uint8_t *ref, int x, int y, int width, int height, int stride, double *u, double *v";
- specialize qw/aom_compute_flow_at_point sse4_1 avx2 neon/;
+ specialize qw/aom_compute_flow_at_point sse4_1 avx2 neon sve/;
}
} # CONFIG_AV1_ENCODER
diff --git a/third_party/aom/aom_dsp/arm/aom_convolve8_neon.c b/third_party/aom/aom_dsp/arm/aom_convolve8_neon.c
index 7441108b01..6a177b2e6b 100644
--- a/third_party/aom/aom_dsp/arm/aom_convolve8_neon.c
+++ b/third_party/aom/aom_dsp/arm/aom_convolve8_neon.c
@@ -20,6 +20,7 @@
#include "aom/aom_integer.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_dsp/aom_filter.h"
+#include "aom_dsp/arm/aom_filter.h"
#include "aom_dsp/arm/mem_neon.h"
#include "aom_dsp/arm/transpose_neon.h"
#include "aom_ports/mem.h"
@@ -31,14 +32,14 @@ static INLINE int16x4_t convolve8_4(const int16x4_t s0, const int16x4_t s1,
const int16x8_t filter) {
const int16x4_t filter_lo = vget_low_s16(filter);
const int16x4_t filter_hi = vget_high_s16(filter);
- int16x4_t sum;
- sum = vmul_lane_s16(s0, filter_lo, 0);
+ int16x4_t sum = vmul_lane_s16(s0, filter_lo, 0);
sum = vmla_lane_s16(sum, s1, filter_lo, 1);
sum = vmla_lane_s16(sum, s2, filter_lo, 2);
sum = vmla_lane_s16(sum, s5, filter_hi, 1);
sum = vmla_lane_s16(sum, s6, filter_hi, 2);
sum = vmla_lane_s16(sum, s7, filter_hi, 3);
+
sum = vqadd_s16(sum, vmul_lane_s16(s3, filter_lo, 3));
sum = vqadd_s16(sum, vmul_lane_s16(s4, filter_hi, 0));
return sum;
@@ -51,65 +52,56 @@ static INLINE uint8x8_t convolve8_8(const int16x8_t s0, const int16x8_t s1,
const int16x8_t filter) {
const int16x4_t filter_lo = vget_low_s16(filter);
const int16x4_t filter_hi = vget_high_s16(filter);
- int16x8_t sum;
- sum = vmulq_lane_s16(s0, filter_lo, 0);
+ int16x8_t sum = vmulq_lane_s16(s0, filter_lo, 0);
sum = vmlaq_lane_s16(sum, s1, filter_lo, 1);
sum = vmlaq_lane_s16(sum, s2, filter_lo, 2);
sum = vmlaq_lane_s16(sum, s5, filter_hi, 1);
sum = vmlaq_lane_s16(sum, s6, filter_hi, 2);
sum = vmlaq_lane_s16(sum, s7, filter_hi, 3);
+
sum = vqaddq_s16(sum, vmulq_lane_s16(s3, filter_lo, 3));
sum = vqaddq_s16(sum, vmulq_lane_s16(s4, filter_hi, 0));
return vqrshrun_n_s16(sum, FILTER_BITS);
}
-void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
- uint8_t *dst, ptrdiff_t dst_stride,
- const int16_t *filter_x, int x_step_q4,
- const int16_t *filter_y, int y_step_q4, int w,
- int h) {
+static INLINE void convolve8_horiz_8tap_neon(const uint8_t *src,
+ ptrdiff_t src_stride, uint8_t *dst,
+ ptrdiff_t dst_stride,
+ const int16_t *filter_x, int w,
+ int h) {
const int16x8_t filter = vld1q_s16(filter_x);
- assert((intptr_t)dst % 4 == 0);
- assert(dst_stride % 4 == 0);
-
- (void)x_step_q4;
- (void)filter_y;
- (void)y_step_q4;
-
- src -= ((SUBPEL_TAPS / 2) - 1);
-
if (h == 4) {
- uint8x8_t t0, t1, t2, t3, d01, d23;
- int16x4_t s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, d0, d1, d2, d3;
-
+ uint8x8_t t0, t1, t2, t3;
load_u8_8x4(src, src_stride, &t0, &t1, &t2, &t3);
transpose_elems_inplace_u8_8x4(&t0, &t1, &t2, &t3);
- s0 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
- s1 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
- s2 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
- s3 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
- s4 = vget_high_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
- s5 = vget_high_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
- s6 = vget_high_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
+
+ int16x4_t s0 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
+ int16x4_t s1 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
+ int16x4_t s2 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
+ int16x4_t s3 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
+ int16x4_t s4 = vget_high_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
+ int16x4_t s5 = vget_high_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
+ int16x4_t s6 = vget_high_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
src += 7;
do {
load_u8_8x4(src, src_stride, &t0, &t1, &t2, &t3);
transpose_elems_inplace_u8_8x4(&t0, &t1, &t2, &t3);
- s7 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
- s8 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
- s9 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
- s10 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
-
- d0 = convolve8_4(s0, s1, s2, s3, s4, s5, s6, s7, filter);
- d1 = convolve8_4(s1, s2, s3, s4, s5, s6, s7, s8, filter);
- d2 = convolve8_4(s2, s3, s4, s5, s6, s7, s8, s9, filter);
- d3 = convolve8_4(s3, s4, s5, s6, s7, s8, s9, s10, filter);
- d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
- d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
+
+ int16x4_t s7 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
+ int16x4_t s8 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
+ int16x4_t s9 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
+ int16x4_t s10 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
+
+ int16x4_t d0 = convolve8_4(s0, s1, s2, s3, s4, s5, s6, s7, filter);
+ int16x4_t d1 = convolve8_4(s1, s2, s3, s4, s5, s6, s7, s8, filter);
+ int16x4_t d2 = convolve8_4(s2, s3, s4, s5, s6, s7, s8, s9, filter);
+ int16x4_t d3 = convolve8_4(s3, s4, s5, s6, s7, s8, s9, s10, filter);
+ uint8x8_t d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
+ uint8x8_t d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
transpose_elems_inplace_u8_4x4(&d01, &d23);
@@ -123,39 +115,40 @@ void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
s4 = s8;
s5 = s9;
s6 = s10;
+
src += 4;
dst += 4;
w -= 4;
} while (w != 0);
} else {
- uint8x8_t t0, t1, t2, t3, t4, t5, t6, t7, d0, d1, d2, d3;
- int16x8_t s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10;
-
if (w == 4) {
do {
+ uint8x8_t t0, t1, t2, t3, t4, t5, t6, t7;
load_u8_8x8(src, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7);
transpose_elems_inplace_u8_8x8(&t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7);
- s0 = vreinterpretq_s16_u16(vmovl_u8(t0));
- s1 = vreinterpretq_s16_u16(vmovl_u8(t1));
- s2 = vreinterpretq_s16_u16(vmovl_u8(t2));
- s3 = vreinterpretq_s16_u16(vmovl_u8(t3));
- s4 = vreinterpretq_s16_u16(vmovl_u8(t4));
- s5 = vreinterpretq_s16_u16(vmovl_u8(t5));
- s6 = vreinterpretq_s16_u16(vmovl_u8(t6));
+
+ int16x8_t s0 = vreinterpretq_s16_u16(vmovl_u8(t0));
+ int16x8_t s1 = vreinterpretq_s16_u16(vmovl_u8(t1));
+ int16x8_t s2 = vreinterpretq_s16_u16(vmovl_u8(t2));
+ int16x8_t s3 = vreinterpretq_s16_u16(vmovl_u8(t3));
+ int16x8_t s4 = vreinterpretq_s16_u16(vmovl_u8(t4));
+ int16x8_t s5 = vreinterpretq_s16_u16(vmovl_u8(t5));
+ int16x8_t s6 = vreinterpretq_s16_u16(vmovl_u8(t6));
load_u8_8x8(src + 7, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6,
&t7);
transpose_elems_u8_4x8(t0, t1, t2, t3, t4, t5, t6, t7, &t0, &t1, &t2,
&t3);
- s7 = vreinterpretq_s16_u16(vmovl_u8(t0));
- s8 = vreinterpretq_s16_u16(vmovl_u8(t1));
- s9 = vreinterpretq_s16_u16(vmovl_u8(t2));
- s10 = vreinterpretq_s16_u16(vmovl_u8(t3));
- d0 = convolve8_8(s0, s1, s2, s3, s4, s5, s6, s7, filter);
- d1 = convolve8_8(s1, s2, s3, s4, s5, s6, s7, s8, filter);
- d2 = convolve8_8(s2, s3, s4, s5, s6, s7, s8, s9, filter);
- d3 = convolve8_8(s3, s4, s5, s6, s7, s8, s9, s10, filter);
+ int16x8_t s7 = vreinterpretq_s16_u16(vmovl_u8(t0));
+ int16x8_t s8 = vreinterpretq_s16_u16(vmovl_u8(t1));
+ int16x8_t s9 = vreinterpretq_s16_u16(vmovl_u8(t2));
+ int16x8_t s10 = vreinterpretq_s16_u16(vmovl_u8(t3));
+
+ uint8x8_t d0 = convolve8_8(s0, s1, s2, s3, s4, s5, s6, s7, filter);
+ uint8x8_t d1 = convolve8_8(s1, s2, s3, s4, s5, s6, s7, s8, filter);
+ uint8x8_t d2 = convolve8_8(s2, s3, s4, s5, s6, s7, s8, s9, filter);
+ uint8x8_t d3 = convolve8_8(s3, s4, s5, s6, s7, s8, s9, s10, filter);
transpose_elems_inplace_u8_8x4(&d0, &d1, &d2, &d3);
@@ -169,48 +162,49 @@ void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
h -= 8;
} while (h > 0);
} else {
- uint8x8_t d4, d5, d6, d7;
- int16x8_t s11, s12, s13, s14;
- int width;
- const uint8_t *s;
- uint8_t *d;
-
do {
- load_u8_8x8(src, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7);
+ int width = w;
+ const uint8_t *s = src;
+ uint8_t *d = dst;
+
+ uint8x8_t t0, t1, t2, t3, t4, t5, t6, t7;
+ load_u8_8x8(s, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7);
transpose_elems_inplace_u8_8x8(&t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7);
- s0 = vreinterpretq_s16_u16(vmovl_u8(t0));
- s1 = vreinterpretq_s16_u16(vmovl_u8(t1));
- s2 = vreinterpretq_s16_u16(vmovl_u8(t2));
- s3 = vreinterpretq_s16_u16(vmovl_u8(t3));
- s4 = vreinterpretq_s16_u16(vmovl_u8(t4));
- s5 = vreinterpretq_s16_u16(vmovl_u8(t5));
- s6 = vreinterpretq_s16_u16(vmovl_u8(t6));
-
- width = w;
- s = src + 7;
- d = dst;
+
+ int16x8_t s0 = vreinterpretq_s16_u16(vmovl_u8(t0));
+ int16x8_t s1 = vreinterpretq_s16_u16(vmovl_u8(t1));
+ int16x8_t s2 = vreinterpretq_s16_u16(vmovl_u8(t2));
+ int16x8_t s3 = vreinterpretq_s16_u16(vmovl_u8(t3));
+ int16x8_t s4 = vreinterpretq_s16_u16(vmovl_u8(t4));
+ int16x8_t s5 = vreinterpretq_s16_u16(vmovl_u8(t5));
+ int16x8_t s6 = vreinterpretq_s16_u16(vmovl_u8(t6));
+
+ s += 7;
do {
load_u8_8x8(s, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7);
transpose_elems_inplace_u8_8x8(&t0, &t1, &t2, &t3, &t4, &t5, &t6,
&t7);
- s7 = vreinterpretq_s16_u16(vmovl_u8(t0));
- s8 = vreinterpretq_s16_u16(vmovl_u8(t1));
- s9 = vreinterpretq_s16_u16(vmovl_u8(t2));
- s10 = vreinterpretq_s16_u16(vmovl_u8(t3));
- s11 = vreinterpretq_s16_u16(vmovl_u8(t4));
- s12 = vreinterpretq_s16_u16(vmovl_u8(t5));
- s13 = vreinterpretq_s16_u16(vmovl_u8(t6));
- s14 = vreinterpretq_s16_u16(vmovl_u8(t7));
-
- d0 = convolve8_8(s0, s1, s2, s3, s4, s5, s6, s7, filter);
- d1 = convolve8_8(s1, s2, s3, s4, s5, s6, s7, s8, filter);
- d2 = convolve8_8(s2, s3, s4, s5, s6, s7, s8, s9, filter);
- d3 = convolve8_8(s3, s4, s5, s6, s7, s8, s9, s10, filter);
- d4 = convolve8_8(s4, s5, s6, s7, s8, s9, s10, s11, filter);
- d5 = convolve8_8(s5, s6, s7, s8, s9, s10, s11, s12, filter);
- d6 = convolve8_8(s6, s7, s8, s9, s10, s11, s12, s13, filter);
- d7 = convolve8_8(s7, s8, s9, s10, s11, s12, s13, s14, filter);
+
+ int16x8_t s7 = vreinterpretq_s16_u16(vmovl_u8(t0));
+ int16x8_t s8 = vreinterpretq_s16_u16(vmovl_u8(t1));
+ int16x8_t s9 = vreinterpretq_s16_u16(vmovl_u8(t2));
+ int16x8_t s10 = vreinterpretq_s16_u16(vmovl_u8(t3));
+ int16x8_t s11 = vreinterpretq_s16_u16(vmovl_u8(t4));
+ int16x8_t s12 = vreinterpretq_s16_u16(vmovl_u8(t5));
+ int16x8_t s13 = vreinterpretq_s16_u16(vmovl_u8(t6));
+ int16x8_t s14 = vreinterpretq_s16_u16(vmovl_u8(t7));
+
+ uint8x8_t d0 = convolve8_8(s0, s1, s2, s3, s4, s5, s6, s7, filter);
+ uint8x8_t d1 = convolve8_8(s1, s2, s3, s4, s5, s6, s7, s8, filter);
+ uint8x8_t d2 = convolve8_8(s2, s3, s4, s5, s6, s7, s8, s9, filter);
+ uint8x8_t d3 = convolve8_8(s3, s4, s5, s6, s7, s8, s9, s10, filter);
+ uint8x8_t d4 = convolve8_8(s4, s5, s6, s7, s8, s9, s10, s11, filter);
+ uint8x8_t d5 = convolve8_8(s5, s6, s7, s8, s9, s10, s11, s12, filter);
+ uint8x8_t d6 =
+ convolve8_8(s6, s7, s8, s9, s10, s11, s12, s13, filter);
+ uint8x8_t d7 =
+ convolve8_8(s7, s8, s9, s10, s11, s12, s13, s14, filter);
transpose_elems_inplace_u8_8x8(&d0, &d1, &d2, &d3, &d4, &d5, &d6,
&d7);
@@ -224,6 +218,7 @@ void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
s4 = s12;
s5 = s13;
s6 = s14;
+
s += 8;
d += 8;
width -= 8;
@@ -236,6 +231,137 @@ void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
}
}
+static INLINE int16x4_t convolve4_4(const int16x4_t s0, const int16x4_t s1,
+ const int16x4_t s2, const int16x4_t s3,
+ const int16x4_t filter) {
+ int16x4_t sum = vmul_lane_s16(s0, filter, 0);
+ sum = vmla_lane_s16(sum, s1, filter, 1);
+ sum = vmla_lane_s16(sum, s2, filter, 2);
+ sum = vmla_lane_s16(sum, s3, filter, 3);
+
+ return sum;
+}
+
+static INLINE uint8x8_t convolve4_8(const int16x8_t s0, const int16x8_t s1,
+ const int16x8_t s2, const int16x8_t s3,
+ const int16x4_t filter) {
+ int16x8_t sum = vmulq_lane_s16(s0, filter, 0);
+ sum = vmlaq_lane_s16(sum, s1, filter, 1);
+ sum = vmlaq_lane_s16(sum, s2, filter, 2);
+ sum = vmlaq_lane_s16(sum, s3, filter, 3);
+
+ // We halved the filter values so -1 from right shift.
+ return vqrshrun_n_s16(sum, FILTER_BITS - 1);
+}
+
+static INLINE void convolve8_horiz_4tap_neon(const uint8_t *src,
+ ptrdiff_t src_stride, uint8_t *dst,
+ ptrdiff_t dst_stride,
+ const int16_t *filter_x, int w,
+ int h) {
+ // All filter values are even, halve to reduce intermediate precision
+ // requirements.
+ const int16x4_t filter = vshr_n_s16(vld1_s16(filter_x + 2), 1);
+
+ if (w == 4) {
+ do {
+ int16x8_t t0 =
+ vreinterpretq_s16_u16(vmovl_u8(vld1_u8(src + 0 * src_stride)));
+ int16x8_t t1 =
+ vreinterpretq_s16_u16(vmovl_u8(vld1_u8(src + 1 * src_stride)));
+
+ int16x4_t s0[4], s1[4];
+ s0[0] = vget_low_s16(t0);
+ s0[1] = vget_low_s16(vextq_s16(t0, t0, 1));
+ s0[2] = vget_low_s16(vextq_s16(t0, t0, 2));
+ s0[3] = vget_low_s16(vextq_s16(t0, t0, 3));
+
+ s1[0] = vget_low_s16(t1);
+ s1[1] = vget_low_s16(vextq_s16(t1, t1, 1));
+ s1[2] = vget_low_s16(vextq_s16(t1, t1, 2));
+ s1[3] = vget_low_s16(vextq_s16(t1, t1, 3));
+
+ int16x4_t d0 = convolve4_4(s0[0], s0[1], s0[2], s0[3], filter);
+ int16x4_t d1 = convolve4_4(s1[0], s1[1], s1[2], s1[3], filter);
+ // We halved the filter values so -1 from right shift.
+ uint8x8_t d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS - 1);
+
+ store_u8x4_strided_x2(dst + 0 * dst_stride, dst_stride, d01);
+
+ src += 2 * src_stride;
+ dst += 2 * dst_stride;
+ h -= 2;
+ } while (h > 0);
+ } else {
+ do {
+ int width = w;
+ const uint8_t *s = src;
+ uint8_t *d = dst;
+
+ int16x8_t t0 =
+ vreinterpretq_s16_u16(vmovl_u8(vld1_u8(s + 0 * src_stride)));
+ int16x8_t t1 =
+ vreinterpretq_s16_u16(vmovl_u8(vld1_u8(s + 1 * src_stride)));
+
+ s += 8;
+ do {
+ int16x8_t t2 =
+ vreinterpretq_s16_u16(vmovl_u8(vld1_u8(s + 0 * src_stride)));
+ int16x8_t t3 =
+ vreinterpretq_s16_u16(vmovl_u8(vld1_u8(s + 1 * src_stride)));
+
+ int16x8_t s0[4], s1[4];
+ s0[0] = t0;
+ s0[1] = vextq_s16(t0, t2, 1);
+ s0[2] = vextq_s16(t0, t2, 2);
+ s0[3] = vextq_s16(t0, t2, 3);
+
+ s1[0] = t1;
+ s1[1] = vextq_s16(t1, t3, 1);
+ s1[2] = vextq_s16(t1, t3, 2);
+ s1[3] = vextq_s16(t1, t3, 3);
+
+ uint8x8_t d0 = convolve4_8(s0[0], s0[1], s0[2], s0[3], filter);
+ uint8x8_t d1 = convolve4_8(s1[0], s1[1], s1[2], s1[3], filter);
+
+ store_u8_8x2(d, dst_stride, d0, d1);
+
+ t0 = t2;
+ t1 = t3;
+
+ s += 8;
+ d += 8;
+ width -= 8;
+ } while (width != 0);
+ src += 2 * src_stride;
+ dst += 2 * dst_stride;
+ h -= 2;
+ } while (h > 0);
+ }
+}
+
+void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
+ uint8_t *dst, ptrdiff_t dst_stride,
+ const int16_t *filter_x, int x_step_q4,
+ const int16_t *filter_y, int y_step_q4, int w,
+ int h) {
+ assert((intptr_t)dst % 4 == 0);
+ assert(dst_stride % 4 == 0);
+
+ (void)x_step_q4;
+ (void)filter_y;
+ (void)y_step_q4;
+
+ src -= ((SUBPEL_TAPS / 2) - 1);
+
+ if (get_filter_taps_convolve8(filter_x) <= 4) {
+ convolve8_horiz_4tap_neon(src + 2, src_stride, dst, dst_stride, filter_x, w,
+ h);
+ } else {
+ convolve8_horiz_8tap_neon(src, src_stride, dst, dst_stride, filter_x, w, h);
+ }
+}
+
void aom_convolve8_vert_neon(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x, int x_step_q4,
@@ -253,33 +379,33 @@ void aom_convolve8_vert_neon(const uint8_t *src, ptrdiff_t src_stride,
src -= ((SUBPEL_TAPS / 2) - 1) * src_stride;
if (w == 4) {
- uint8x8_t t0, t1, t2, t3, t4, t5, t6, d01, d23;
- int16x4_t s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, d0, d1, d2, d3;
-
+ uint8x8_t t0, t1, t2, t3, t4, t5, t6;
load_u8_8x7(src, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6);
- s0 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
- s1 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
- s2 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
- s3 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
- s4 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t4)));
- s5 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t5)));
- s6 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t6)));
+
+ int16x4_t s0 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
+ int16x4_t s1 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
+ int16x4_t s2 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
+ int16x4_t s3 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
+ int16x4_t s4 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t4)));
+ int16x4_t s5 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t5)));
+ int16x4_t s6 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t6)));
src += 7 * src_stride;
do {
load_u8_8x4(src, src_stride, &t0, &t1, &t2, &t3);
- s7 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
- s8 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
- s9 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
- s10 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
-
- d0 = convolve8_4(s0, s1, s2, s3, s4, s5, s6, s7, filter);
- d1 = convolve8_4(s1, s2, s3, s4, s5, s6, s7, s8, filter);
- d2 = convolve8_4(s2, s3, s4, s5, s6, s7, s8, s9, filter);
- d3 = convolve8_4(s3, s4, s5, s6, s7, s8, s9, s10, filter);
- d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
- d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
+
+ int16x4_t s7 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t0)));
+ int16x4_t s8 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t1)));
+ int16x4_t s9 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t2)));
+ int16x4_t s10 = vget_low_s16(vreinterpretq_s16_u16(vmovl_u8(t3)));
+
+ int16x4_t d0 = convolve8_4(s0, s1, s2, s3, s4, s5, s6, s7, filter);
+ int16x4_t d1 = convolve8_4(s1, s2, s3, s4, s5, s6, s7, s8, filter);
+ int16x4_t d2 = convolve8_4(s2, s3, s4, s5, s6, s7, s8, s9, filter);
+ int16x4_t d3 = convolve8_4(s3, s4, s5, s6, s7, s8, s9, s10, filter);
+ uint8x8_t d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
+ uint8x8_t d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
store_u8x4_strided_x2(dst + 0 * dst_stride, dst_stride, d01);
store_u8x4_strided_x2(dst + 2 * dst_stride, dst_stride, d23);
@@ -291,42 +417,40 @@ void aom_convolve8_vert_neon(const uint8_t *src, ptrdiff_t src_stride,
s4 = s8;
s5 = s9;
s6 = s10;
+
src += 4 * src_stride;
dst += 4 * dst_stride;
h -= 4;
} while (h != 0);
} else {
- uint8x8_t t0, t1, t2, t3, t4, t5, t6, d0, d1, d2, d3;
- int16x8_t s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10;
- int height;
- const uint8_t *s;
- uint8_t *d;
-
do {
+ uint8x8_t t0, t1, t2, t3, t4, t5, t6;
load_u8_8x7(src, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6);
- s0 = vreinterpretq_s16_u16(vmovl_u8(t0));
- s1 = vreinterpretq_s16_u16(vmovl_u8(t1));
- s2 = vreinterpretq_s16_u16(vmovl_u8(t2));
- s3 = vreinterpretq_s16_u16(vmovl_u8(t3));
- s4 = vreinterpretq_s16_u16(vmovl_u8(t4));
- s5 = vreinterpretq_s16_u16(vmovl_u8(t5));
- s6 = vreinterpretq_s16_u16(vmovl_u8(t6));
-
- height = h;
- s = src + 7 * src_stride;
- d = dst;
+
+ int16x8_t s0 = vreinterpretq_s16_u16(vmovl_u8(t0));
+ int16x8_t s1 = vreinterpretq_s16_u16(vmovl_u8(t1));
+ int16x8_t s2 = vreinterpretq_s16_u16(vmovl_u8(t2));
+ int16x8_t s3 = vreinterpretq_s16_u16(vmovl_u8(t3));
+ int16x8_t s4 = vreinterpretq_s16_u16(vmovl_u8(t4));
+ int16x8_t s5 = vreinterpretq_s16_u16(vmovl_u8(t5));
+ int16x8_t s6 = vreinterpretq_s16_u16(vmovl_u8(t6));
+
+ int height = h;
+ const uint8_t *s = src + 7 * src_stride;
+ uint8_t *d = dst;
do {
load_u8_8x4(s, src_stride, &t0, &t1, &t2, &t3);
- s7 = vreinterpretq_s16_u16(vmovl_u8(t0));
- s8 = vreinterpretq_s16_u16(vmovl_u8(t1));
- s9 = vreinterpretq_s16_u16(vmovl_u8(t2));
- s10 = vreinterpretq_s16_u16(vmovl_u8(t3));
- d0 = convolve8_8(s0, s1, s2, s3, s4, s5, s6, s7, filter);
- d1 = convolve8_8(s1, s2, s3, s4, s5, s6, s7, s8, filter);
- d2 = convolve8_8(s2, s3, s4, s5, s6, s7, s8, s9, filter);
- d3 = convolve8_8(s3, s4, s5, s6, s7, s8, s9, s10, filter);
+ int16x8_t s7 = vreinterpretq_s16_u16(vmovl_u8(t0));
+ int16x8_t s8 = vreinterpretq_s16_u16(vmovl_u8(t1));
+ int16x8_t s9 = vreinterpretq_s16_u16(vmovl_u8(t2));
+ int16x8_t s10 = vreinterpretq_s16_u16(vmovl_u8(t3));
+
+ uint8x8_t d0 = convolve8_8(s0, s1, s2, s3, s4, s5, s6, s7, filter);
+ uint8x8_t d1 = convolve8_8(s1, s2, s3, s4, s5, s6, s7, s8, filter);
+ uint8x8_t d2 = convolve8_8(s2, s3, s4, s5, s6, s7, s8, s9, filter);
+ uint8x8_t d3 = convolve8_8(s3, s4, s5, s6, s7, s8, s9, s10, filter);
store_u8_8x4(d, dst_stride, d0, d1, d2, d3);
@@ -337,6 +461,7 @@ void aom_convolve8_vert_neon(const uint8_t *src, ptrdiff_t src_stride,
s4 = s8;
s5 = s9;
s6 = s10;
+
s += 4 * src_stride;
d += 4 * dst_stride;
height -= 4;
diff --git a/third_party/aom/aom_dsp/arm/aom_convolve8_neon_dotprod.c b/third_party/aom/aom_dsp/arm/aom_convolve8_neon_dotprod.c
index c82125ba17..120c479798 100644
--- a/third_party/aom/aom_dsp/arm/aom_convolve8_neon_dotprod.c
+++ b/third_party/aom/aom_dsp/arm/aom_convolve8_neon_dotprod.c
@@ -24,81 +24,72 @@
#include "aom_dsp/arm/transpose_neon.h"
#include "aom_ports/mem.h"
-DECLARE_ALIGNED(16, static const uint8_t, dot_prod_permute_tbl[48]) = {
+// Filter values always sum to 128.
+#define FILTER_WEIGHT 128
+
+DECLARE_ALIGNED(16, static const uint8_t, kDotProdPermuteTbl[48]) = {
0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6,
4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10,
8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
};
-DECLARE_ALIGNED(16, static const uint8_t, dot_prod_tran_concat_tbl[32]) = {
- 0, 8, 16, 24, 1, 9, 17, 25, 2, 10, 18, 26, 3, 11, 19, 27,
- 4, 12, 20, 28, 5, 13, 21, 29, 6, 14, 22, 30, 7, 15, 23, 31
-};
-
-DECLARE_ALIGNED(16, static const uint8_t, dot_prod_merge_block_tbl[48]) = {
- /* Shift left and insert new last column in transposed 4x4 block. */
+DECLARE_ALIGNED(16, static const uint8_t, kDotProdMergeBlockTbl[48]) = {
+ // Shift left and insert new last column in transposed 4x4 block.
1, 2, 3, 16, 5, 6, 7, 20, 9, 10, 11, 24, 13, 14, 15, 28,
- /* Shift left and insert two new columns in transposed 4x4 block. */
+ // Shift left and insert two new columns in transposed 4x4 block.
2, 3, 16, 17, 6, 7, 20, 21, 10, 11, 24, 25, 14, 15, 28, 29,
- /* Shift left and insert three new columns in transposed 4x4 block. */
+ // Shift left and insert three new columns in transposed 4x4 block.
3, 16, 17, 18, 7, 20, 21, 22, 11, 24, 25, 26, 15, 28, 29, 30
};
-static INLINE int16x4_t convolve8_4_sdot(uint8x16_t samples,
- const int8x8_t filter,
- const int32x4_t correction,
- const uint8x16_t range_limit,
- const uint8x16x2_t permute_tbl) {
- int8x16_t clamped_samples, permuted_samples[2];
- int32x4_t sum;
-
- /* Clamp sample range to [-128, 127] for 8-bit signed dot product. */
- clamped_samples = vreinterpretq_s8_u8(vsubq_u8(samples, range_limit));
-
- /* Permute samples ready for dot product. */
- /* { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 } */
- permuted_samples[0] = vqtbl1q_s8(clamped_samples, permute_tbl.val[0]);
- /* { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 } */
- permuted_samples[1] = vqtbl1q_s8(clamped_samples, permute_tbl.val[1]);
-
- /* Accumulate dot product into 'correction' to account for range clamp. */
- sum = vdotq_lane_s32(correction, permuted_samples[0], filter, 0);
- sum = vdotq_lane_s32(sum, permuted_samples[1], filter, 1);
-
- /* Further narrowing and packing is performed by the caller. */
+static INLINE int16x4_t convolve8_4_h(const uint8x16_t samples,
+ const int8x8_t filters,
+ const uint8x16x2_t permute_tbl) {
+ // Transform sample range to [-128, 127] for 8-bit signed dot product.
+ int8x16_t samples_128 =
+ vreinterpretq_s8_u8(vsubq_u8(samples, vdupq_n_u8(128)));
+
+ // Permute samples ready for dot product.
+ // { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 }
+ // { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 }
+ int8x16_t perm_samples[2] = { vqtbl1q_s8(samples_128, permute_tbl.val[0]),
+ vqtbl1q_s8(samples_128, permute_tbl.val[1]) };
+
+ // Accumulate into 128 * FILTER_WEIGHT to account for range transform.
+ int32x4_t acc = vdupq_n_s32(128 * FILTER_WEIGHT);
+ int32x4_t sum = vdotq_lane_s32(acc, perm_samples[0], filters, 0);
+ sum = vdotq_lane_s32(sum, perm_samples[1], filters, 1);
+
+ // Further narrowing and packing is performed by the caller.
return vqmovn_s32(sum);
}
-static INLINE uint8x8_t convolve8_8_sdot(uint8x16_t samples,
- const int8x8_t filter,
- const int32x4_t correction,
- const uint8x16_t range_limit,
- const uint8x16x3_t permute_tbl) {
- int8x16_t clamped_samples, permuted_samples[3];
- int32x4_t sum0, sum1;
- int16x8_t sum;
-
- /* Clamp sample range to [-128, 127] for 8-bit signed dot product. */
- clamped_samples = vreinterpretq_s8_u8(vsubq_u8(samples, range_limit));
-
- /* Permute samples ready for dot product. */
- /* { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 } */
- permuted_samples[0] = vqtbl1q_s8(clamped_samples, permute_tbl.val[0]);
- /* { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 } */
- permuted_samples[1] = vqtbl1q_s8(clamped_samples, permute_tbl.val[1]);
- /* { 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 } */
- permuted_samples[2] = vqtbl1q_s8(clamped_samples, permute_tbl.val[2]);
-
- /* Accumulate dot product into 'correction' to account for range clamp. */
- /* First 4 output values. */
- sum0 = vdotq_lane_s32(correction, permuted_samples[0], filter, 0);
- sum0 = vdotq_lane_s32(sum0, permuted_samples[1], filter, 1);
- /* Second 4 output values. */
- sum1 = vdotq_lane_s32(correction, permuted_samples[1], filter, 0);
- sum1 = vdotq_lane_s32(sum1, permuted_samples[2], filter, 1);
-
- /* Narrow and re-pack. */
- sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
+static INLINE uint8x8_t convolve8_8_h(const uint8x16_t samples,
+ const int8x8_t filters,
+ const uint8x16x3_t permute_tbl) {
+ // Transform sample range to [-128, 127] for 8-bit signed dot product.
+ int8x16_t samples_128 =
+ vreinterpretq_s8_u8(vsubq_u8(samples, vdupq_n_u8(128)));
+
+ // Permute samples ready for dot product.
+ // { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 }
+ // { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 }
+ // { 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 }
+ int8x16_t perm_samples[3] = { vqtbl1q_s8(samples_128, permute_tbl.val[0]),
+ vqtbl1q_s8(samples_128, permute_tbl.val[1]),
+ vqtbl1q_s8(samples_128, permute_tbl.val[2]) };
+
+ // Accumulate into 128 * FILTER_WEIGHT to account for range transform.
+ int32x4_t acc = vdupq_n_s32(128 * FILTER_WEIGHT);
+ // First 4 output values.
+ int32x4_t sum0 = vdotq_lane_s32(acc, perm_samples[0], filters, 0);
+ sum0 = vdotq_lane_s32(sum0, perm_samples[1], filters, 1);
+ // Second 4 output values.
+ int32x4_t sum1 = vdotq_lane_s32(acc, perm_samples[1], filters, 0);
+ sum1 = vdotq_lane_s32(sum1, perm_samples[2], filters, 1);
+
+ // Narrow and re-pack.
+ int16x8_t sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
return vqrshrun_n_s16(sum, FILTER_BITS);
}
@@ -108,10 +99,6 @@ void aom_convolve8_horiz_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
const int8x8_t filter = vmovn_s16(vld1q_s16(filter_x));
- const int16x8_t correct_tmp = vmulq_n_s16(vld1q_s16(filter_x), 128);
- const int32x4_t correction = vdupq_n_s32((int32_t)vaddvq_s16(correct_tmp));
- const uint8x16_t range_limit = vdupq_n_u8(128);
- uint8x16_t s0, s1, s2, s3;
assert((intptr_t)dst % 4 == 0);
assert(dst_stride % 4 == 0);
@@ -123,19 +110,17 @@ void aom_convolve8_horiz_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
src -= ((SUBPEL_TAPS / 2) - 1);
if (w == 4) {
- const uint8x16x2_t perm_tbl = vld1q_u8_x2(dot_prod_permute_tbl);
+ const uint8x16x2_t perm_tbl = vld1q_u8_x2(kDotProdPermuteTbl);
do {
- int16x4_t t0, t1, t2, t3;
- uint8x8_t d01, d23;
-
+ uint8x16_t s0, s1, s2, s3;
load_u8_16x4(src, src_stride, &s0, &s1, &s2, &s3);
- t0 = convolve8_4_sdot(s0, filter, correction, range_limit, perm_tbl);
- t1 = convolve8_4_sdot(s1, filter, correction, range_limit, perm_tbl);
- t2 = convolve8_4_sdot(s2, filter, correction, range_limit, perm_tbl);
- t3 = convolve8_4_sdot(s3, filter, correction, range_limit, perm_tbl);
- d01 = vqrshrun_n_s16(vcombine_s16(t0, t1), FILTER_BITS);
- d23 = vqrshrun_n_s16(vcombine_s16(t2, t3), FILTER_BITS);
+ int16x4_t d0 = convolve8_4_h(s0, filter, perm_tbl);
+ int16x4_t d1 = convolve8_4_h(s1, filter, perm_tbl);
+ int16x4_t d2 = convolve8_4_h(s2, filter, perm_tbl);
+ int16x4_t d3 = convolve8_4_h(s3, filter, perm_tbl);
+ uint8x8_t d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
+ uint8x8_t d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
store_u8x4_strided_x2(dst + 0 * dst_stride, dst_stride, d01);
store_u8x4_strided_x2(dst + 2 * dst_stride, dst_stride, d23);
@@ -145,23 +130,20 @@ void aom_convolve8_horiz_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
h -= 4;
} while (h > 0);
} else {
- const uint8x16x3_t perm_tbl = vld1q_u8_x3(dot_prod_permute_tbl);
- const uint8_t *s;
- uint8_t *d;
- int width;
- uint8x8_t d0, d1, d2, d3;
+ const uint8x16x3_t perm_tbl = vld1q_u8_x3(kDotProdPermuteTbl);
do {
- width = w;
- s = src;
- d = dst;
+ int width = w;
+ const uint8_t *s = src;
+ uint8_t *d = dst;
do {
+ uint8x16_t s0, s1, s2, s3;
load_u8_16x4(s, src_stride, &s0, &s1, &s2, &s3);
- d0 = convolve8_8_sdot(s0, filter, correction, range_limit, perm_tbl);
- d1 = convolve8_8_sdot(s1, filter, correction, range_limit, perm_tbl);
- d2 = convolve8_8_sdot(s2, filter, correction, range_limit, perm_tbl);
- d3 = convolve8_8_sdot(s3, filter, correction, range_limit, perm_tbl);
+ uint8x8_t d0 = convolve8_8_h(s0, filter, perm_tbl);
+ uint8x8_t d1 = convolve8_8_h(s1, filter, perm_tbl);
+ uint8x8_t d2 = convolve8_8_h(s2, filter, perm_tbl);
+ uint8x8_t d3 = convolve8_8_h(s3, filter, perm_tbl);
store_u8_8x4(d, dst_stride, d0, d1, d2, d3);
@@ -177,83 +159,88 @@ void aom_convolve8_horiz_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
}
static INLINE void transpose_concat_4x4(int8x8_t a0, int8x8_t a1, int8x8_t a2,
- int8x8_t a3, int8x16_t *b,
- const uint8x16_t permute_tbl) {
- /* Transpose 8-bit elements and concatenate result rows as follows:
- * a0: 00, 01, 02, 03, XX, XX, XX, XX
- * a1: 10, 11, 12, 13, XX, XX, XX, XX
- * a2: 20, 21, 22, 23, XX, XX, XX, XX
- * a3: 30, 31, 32, 33, XX, XX, XX, XX
- *
- * b: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
- *
- * The 'permute_tbl' is always 'dot_prod_tran_concat_tbl' above. Passing it
- * as an argument is preferable to loading it directly from memory as this
- * inline helper is called many times from the same parent function.
- */
-
- int8x16x2_t samples = { { vcombine_s8(a0, a1), vcombine_s8(a2, a3) } };
- *b = vqtbl2q_s8(samples, permute_tbl);
+ int8x8_t a3, int8x16_t *b) {
+ // Transpose 8-bit elements and concatenate result rows as follows:
+ // a0: 00, 01, 02, 03, XX, XX, XX, XX
+ // a1: 10, 11, 12, 13, XX, XX, XX, XX
+ // a2: 20, 21, 22, 23, XX, XX, XX, XX
+ // a3: 30, 31, 32, 33, XX, XX, XX, XX
+ //
+ // b: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
+
+ int8x16_t a0q = vcombine_s8(a0, vdup_n_s8(0));
+ int8x16_t a1q = vcombine_s8(a1, vdup_n_s8(0));
+ int8x16_t a2q = vcombine_s8(a2, vdup_n_s8(0));
+ int8x16_t a3q = vcombine_s8(a3, vdup_n_s8(0));
+
+ int8x16_t a01 = vzipq_s8(a0q, a1q).val[0];
+ int8x16_t a23 = vzipq_s8(a2q, a3q).val[0];
+
+ int16x8_t a0123 =
+ vzipq_s16(vreinterpretq_s16_s8(a01), vreinterpretq_s16_s8(a23)).val[0];
+
+ *b = vreinterpretq_s8_s16(a0123);
}
static INLINE void transpose_concat_8x4(int8x8_t a0, int8x8_t a1, int8x8_t a2,
int8x8_t a3, int8x16_t *b0,
- int8x16_t *b1,
- const uint8x16x2_t permute_tbl) {
- /* Transpose 8-bit elements and concatenate result rows as follows:
- * a0: 00, 01, 02, 03, 04, 05, 06, 07
- * a1: 10, 11, 12, 13, 14, 15, 16, 17
- * a2: 20, 21, 22, 23, 24, 25, 26, 27
- * a3: 30, 31, 32, 33, 34, 35, 36, 37
- *
- * b0: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
- * b1: 04, 14, 24, 34, 05, 15, 25, 35, 06, 16, 26, 36, 07, 17, 27, 37
- *
- * The 'permute_tbl' is always 'dot_prod_tran_concat_tbl' above. Passing it
- * as an argument is preferable to loading it directly from memory as this
- * inline helper is called many times from the same parent function.
- */
-
- int8x16x2_t samples = { { vcombine_s8(a0, a1), vcombine_s8(a2, a3) } };
- *b0 = vqtbl2q_s8(samples, permute_tbl.val[0]);
- *b1 = vqtbl2q_s8(samples, permute_tbl.val[1]);
+ int8x16_t *b1) {
+ // Transpose 8-bit elements and concatenate result rows as follows:
+ // a0: 00, 01, 02, 03, 04, 05, 06, 07
+ // a1: 10, 11, 12, 13, 14, 15, 16, 17
+ // a2: 20, 21, 22, 23, 24, 25, 26, 27
+ // a3: 30, 31, 32, 33, 34, 35, 36, 37
+ //
+ // b0: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
+ // b1: 04, 14, 24, 34, 05, 15, 25, 35, 06, 16, 26, 36, 07, 17, 27, 37
+
+ int8x16_t a0q = vcombine_s8(a0, vdup_n_s8(0));
+ int8x16_t a1q = vcombine_s8(a1, vdup_n_s8(0));
+ int8x16_t a2q = vcombine_s8(a2, vdup_n_s8(0));
+ int8x16_t a3q = vcombine_s8(a3, vdup_n_s8(0));
+
+ int8x16_t a01 = vzipq_s8(a0q, a1q).val[0];
+ int8x16_t a23 = vzipq_s8(a2q, a3q).val[0];
+
+ int16x8x2_t a0123 =
+ vzipq_s16(vreinterpretq_s16_s8(a01), vreinterpretq_s16_s8(a23));
+
+ *b0 = vreinterpretq_s8_s16(a0123.val[0]);
+ *b1 = vreinterpretq_s8_s16(a0123.val[1]);
}
-static INLINE int16x4_t convolve8_4_sdot_partial(const int8x16_t samples_lo,
- const int8x16_t samples_hi,
- const int32x4_t correction,
- const int8x8_t filter) {
- /* Sample range-clamping and permutation are performed by the caller. */
- int32x4_t sum;
+static INLINE int16x4_t convolve8_4_v(const int8x16_t samples_lo,
+ const int8x16_t samples_hi,
+ const int8x8_t filters) {
+ // The sample range transform and permutation are performed by the caller.
- /* Accumulate dot product into 'correction' to account for range clamp. */
- sum = vdotq_lane_s32(correction, samples_lo, filter, 0);
- sum = vdotq_lane_s32(sum, samples_hi, filter, 1);
+ // Accumulate into 128 * FILTER_WEIGHT to account for range transform.
+ int32x4_t acc = vdupq_n_s32(128 * FILTER_WEIGHT);
+ int32x4_t sum = vdotq_lane_s32(acc, samples_lo, filters, 0);
+ sum = vdotq_lane_s32(sum, samples_hi, filters, 1);
- /* Further narrowing and packing is performed by the caller. */
+ // Further narrowing and packing is performed by the caller.
return vqmovn_s32(sum);
}
-static INLINE uint8x8_t convolve8_8_sdot_partial(const int8x16_t samples0_lo,
- const int8x16_t samples0_hi,
- const int8x16_t samples1_lo,
- const int8x16_t samples1_hi,
- const int32x4_t correction,
- const int8x8_t filter) {
- /* Sample range-clamping and permutation are performed by the caller. */
- int32x4_t sum0, sum1;
- int16x8_t sum;
-
- /* Accumulate dot product into 'correction' to account for range clamp. */
- /* First 4 output values. */
- sum0 = vdotq_lane_s32(correction, samples0_lo, filter, 0);
- sum0 = vdotq_lane_s32(sum0, samples0_hi, filter, 1);
- /* Second 4 output values. */
- sum1 = vdotq_lane_s32(correction, samples1_lo, filter, 0);
- sum1 = vdotq_lane_s32(sum1, samples1_hi, filter, 1);
-
- /* Narrow and re-pack. */
- sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
+static INLINE uint8x8_t convolve8_8_v(const int8x16_t samples0_lo,
+ const int8x16_t samples0_hi,
+ const int8x16_t samples1_lo,
+ const int8x16_t samples1_hi,
+ const int8x8_t filters) {
+ // The sample range transform and permutation are performed by the caller.
+
+ // Accumulate into 128 * FILTER_WEIGHT to account for range transform.
+ int32x4_t acc = vdupq_n_s32(128 * FILTER_WEIGHT);
+ // First 4 output values.
+ int32x4_t sum0 = vdotq_lane_s32(acc, samples0_lo, filters, 0);
+ sum0 = vdotq_lane_s32(sum0, samples0_hi, filters, 1);
+ // Second 4 output values.
+ int32x4_t sum1 = vdotq_lane_s32(acc, samples1_lo, filters, 0);
+ sum1 = vdotq_lane_s32(sum1, samples1_hi, filters, 1);
+
+ // Narrow and re-pack.
+ int16x8_t sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
return vqrshrun_n_s16(sum, FILTER_BITS);
}
@@ -263,10 +250,7 @@ void aom_convolve8_vert_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
const int8x8_t filter = vmovn_s16(vld1q_s16(filter_y));
- const int16x8_t correct_tmp = vmulq_n_s16(vld1q_s16(filter_y), 128);
- const int32x4_t correction = vdupq_n_s32((int32_t)vaddvq_s16(correct_tmp));
- const uint8x8_t range_limit = vdup_n_u8(128);
- const uint8x16x3_t merge_block_tbl = vld1q_u8_x3(dot_prod_merge_block_tbl);
+ const uint8x16x3_t merge_block_tbl = vld1q_u8_x3(kDotProdMergeBlockTbl);
int8x16x2_t samples_LUT;
assert((intptr_t)dst % 4 == 0);
@@ -279,62 +263,58 @@ void aom_convolve8_vert_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
src -= ((SUBPEL_TAPS / 2) - 1) * src_stride;
if (w == 4) {
- const uint8x16_t tran_concat_tbl = vld1q_u8(dot_prod_tran_concat_tbl);
-
uint8x8_t t0, t1, t2, t3, t4, t5, t6;
load_u8_8x7(src, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6);
src += 7 * src_stride;
- /* Clamp sample range to [-128, 127] for 8-bit signed dot product. */
- int8x8_t s0 = vreinterpret_s8_u8(vsub_u8(t0, range_limit));
- int8x8_t s1 = vreinterpret_s8_u8(vsub_u8(t1, range_limit));
- int8x8_t s2 = vreinterpret_s8_u8(vsub_u8(t2, range_limit));
- int8x8_t s3 = vreinterpret_s8_u8(vsub_u8(t3, range_limit));
- int8x8_t s4 = vreinterpret_s8_u8(vsub_u8(t4, range_limit));
- int8x8_t s5 = vreinterpret_s8_u8(vsub_u8(t5, range_limit));
- int8x8_t s6 = vreinterpret_s8_u8(vsub_u8(t6, range_limit));
-
- /* This operation combines a conventional transpose and the sample permute
- * (see horizontal case) required before computing the dot product.
- */
+ // Clamp sample range to [-128, 127] for 8-bit signed dot product.
+ int8x8_t s0 = vreinterpret_s8_u8(vsub_u8(t0, vdup_n_u8(128)));
+ int8x8_t s1 = vreinterpret_s8_u8(vsub_u8(t1, vdup_n_u8(128)));
+ int8x8_t s2 = vreinterpret_s8_u8(vsub_u8(t2, vdup_n_u8(128)));
+ int8x8_t s3 = vreinterpret_s8_u8(vsub_u8(t3, vdup_n_u8(128)));
+ int8x8_t s4 = vreinterpret_s8_u8(vsub_u8(t4, vdup_n_u8(128)));
+ int8x8_t s5 = vreinterpret_s8_u8(vsub_u8(t5, vdup_n_u8(128)));
+ int8x8_t s6 = vreinterpret_s8_u8(vsub_u8(t6, vdup_n_u8(128)));
+
+ // This operation combines a conventional transpose and the sample permute
+ // (see horizontal case) required before computing the dot product.
int8x16_t s0123, s1234, s2345, s3456;
- transpose_concat_4x4(s0, s1, s2, s3, &s0123, tran_concat_tbl);
- transpose_concat_4x4(s1, s2, s3, s4, &s1234, tran_concat_tbl);
- transpose_concat_4x4(s2, s3, s4, s5, &s2345, tran_concat_tbl);
- transpose_concat_4x4(s3, s4, s5, s6, &s3456, tran_concat_tbl);
+ transpose_concat_4x4(s0, s1, s2, s3, &s0123);
+ transpose_concat_4x4(s1, s2, s3, s4, &s1234);
+ transpose_concat_4x4(s2, s3, s4, s5, &s2345);
+ transpose_concat_4x4(s3, s4, s5, s6, &s3456);
do {
uint8x8_t t7, t8, t9, t10;
load_u8_8x4(src, src_stride, &t7, &t8, &t9, &t10);
- int8x8_t s7 = vreinterpret_s8_u8(vsub_u8(t7, range_limit));
- int8x8_t s8 = vreinterpret_s8_u8(vsub_u8(t8, range_limit));
- int8x8_t s9 = vreinterpret_s8_u8(vsub_u8(t9, range_limit));
- int8x8_t s10 = vreinterpret_s8_u8(vsub_u8(t10, range_limit));
+ int8x8_t s7 = vreinterpret_s8_u8(vsub_u8(t7, vdup_n_u8(128)));
+ int8x8_t s8 = vreinterpret_s8_u8(vsub_u8(t8, vdup_n_u8(128)));
+ int8x8_t s9 = vreinterpret_s8_u8(vsub_u8(t9, vdup_n_u8(128)));
+ int8x8_t s10 = vreinterpret_s8_u8(vsub_u8(t10, vdup_n_u8(128)));
int8x16_t s4567, s5678, s6789, s78910;
- transpose_concat_4x4(s7, s8, s9, s10, &s78910, tran_concat_tbl);
+ transpose_concat_4x4(s7, s8, s9, s10, &s78910);
- /* Merge new data into block from previous iteration. */
+ // Merge new data into block from previous iteration.
samples_LUT.val[0] = s3456;
samples_LUT.val[1] = s78910;
s4567 = vqtbl2q_s8(samples_LUT, merge_block_tbl.val[0]);
s5678 = vqtbl2q_s8(samples_LUT, merge_block_tbl.val[1]);
s6789 = vqtbl2q_s8(samples_LUT, merge_block_tbl.val[2]);
- int16x4_t d0 = convolve8_4_sdot_partial(s0123, s4567, correction, filter);
- int16x4_t d1 = convolve8_4_sdot_partial(s1234, s5678, correction, filter);
- int16x4_t d2 = convolve8_4_sdot_partial(s2345, s6789, correction, filter);
- int16x4_t d3 =
- convolve8_4_sdot_partial(s3456, s78910, correction, filter);
+ int16x4_t d0 = convolve8_4_v(s0123, s4567, filter);
+ int16x4_t d1 = convolve8_4_v(s1234, s5678, filter);
+ int16x4_t d2 = convolve8_4_v(s2345, s6789, filter);
+ int16x4_t d3 = convolve8_4_v(s3456, s78910, filter);
uint8x8_t d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
uint8x8_t d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
store_u8x4_strided_x2(dst + 0 * dst_stride, dst_stride, d01);
store_u8x4_strided_x2(dst + 2 * dst_stride, dst_stride, d23);
- /* Prepare block for next iteration - re-using as much as possible. */
- /* Shuffle everything up four rows. */
+ // Prepare block for next iteration - re-using as much as possible.
+ // Shuffle everything up four rows.
s0123 = s4567;
s1234 = s5678;
s2345 = s6789;
@@ -345,8 +325,6 @@ void aom_convolve8_vert_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
h -= 4;
} while (h != 0);
} else {
- const uint8x16x2_t tran_concat_tbl = vld1q_u8_x2(dot_prod_tran_concat_tbl);
-
do {
int height = h;
const uint8_t *s = src;
@@ -356,44 +334,38 @@ void aom_convolve8_vert_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
load_u8_8x7(s, src_stride, &t0, &t1, &t2, &t3, &t4, &t5, &t6);
s += 7 * src_stride;
- /* Clamp sample range to [-128, 127] for 8-bit signed dot product. */
- int8x8_t s0 = vreinterpret_s8_u8(vsub_u8(t0, range_limit));
- int8x8_t s1 = vreinterpret_s8_u8(vsub_u8(t1, range_limit));
- int8x8_t s2 = vreinterpret_s8_u8(vsub_u8(t2, range_limit));
- int8x8_t s3 = vreinterpret_s8_u8(vsub_u8(t3, range_limit));
- int8x8_t s4 = vreinterpret_s8_u8(vsub_u8(t4, range_limit));
- int8x8_t s5 = vreinterpret_s8_u8(vsub_u8(t5, range_limit));
- int8x8_t s6 = vreinterpret_s8_u8(vsub_u8(t6, range_limit));
-
- /* This operation combines a conventional transpose and the sample permute
- * (see horizontal case) required before computing the dot product.
- */
+ // Clamp sample range to [-128, 127] for 8-bit signed dot product.
+ int8x8_t s0 = vreinterpret_s8_u8(vsub_u8(t0, vdup_n_u8(128)));
+ int8x8_t s1 = vreinterpret_s8_u8(vsub_u8(t1, vdup_n_u8(128)));
+ int8x8_t s2 = vreinterpret_s8_u8(vsub_u8(t2, vdup_n_u8(128)));
+ int8x8_t s3 = vreinterpret_s8_u8(vsub_u8(t3, vdup_n_u8(128)));
+ int8x8_t s4 = vreinterpret_s8_u8(vsub_u8(t4, vdup_n_u8(128)));
+ int8x8_t s5 = vreinterpret_s8_u8(vsub_u8(t5, vdup_n_u8(128)));
+ int8x8_t s6 = vreinterpret_s8_u8(vsub_u8(t6, vdup_n_u8(128)));
+
+ // This operation combines a conventional transpose and the sample permute
+ // (see horizontal case) required before computing the dot product.
int8x16_t s0123_lo, s0123_hi, s1234_lo, s1234_hi, s2345_lo, s2345_hi,
s3456_lo, s3456_hi;
- transpose_concat_8x4(s0, s1, s2, s3, &s0123_lo, &s0123_hi,
- tran_concat_tbl);
- transpose_concat_8x4(s1, s2, s3, s4, &s1234_lo, &s1234_hi,
- tran_concat_tbl);
- transpose_concat_8x4(s2, s3, s4, s5, &s2345_lo, &s2345_hi,
- tran_concat_tbl);
- transpose_concat_8x4(s3, s4, s5, s6, &s3456_lo, &s3456_hi,
- tran_concat_tbl);
+ transpose_concat_8x4(s0, s1, s2, s3, &s0123_lo, &s0123_hi);
+ transpose_concat_8x4(s1, s2, s3, s4, &s1234_lo, &s1234_hi);
+ transpose_concat_8x4(s2, s3, s4, s5, &s2345_lo, &s2345_hi);
+ transpose_concat_8x4(s3, s4, s5, s6, &s3456_lo, &s3456_hi);
do {
uint8x8_t t7, t8, t9, t10;
load_u8_8x4(s, src_stride, &t7, &t8, &t9, &t10);
- int8x8_t s7 = vreinterpret_s8_u8(vsub_u8(t7, range_limit));
- int8x8_t s8 = vreinterpret_s8_u8(vsub_u8(t8, range_limit));
- int8x8_t s9 = vreinterpret_s8_u8(vsub_u8(t9, range_limit));
- int8x8_t s10 = vreinterpret_s8_u8(vsub_u8(t10, range_limit));
+ int8x8_t s7 = vreinterpret_s8_u8(vsub_u8(t7, vdup_n_u8(128)));
+ int8x8_t s8 = vreinterpret_s8_u8(vsub_u8(t8, vdup_n_u8(128)));
+ int8x8_t s9 = vreinterpret_s8_u8(vsub_u8(t9, vdup_n_u8(128)));
+ int8x8_t s10 = vreinterpret_s8_u8(vsub_u8(t10, vdup_n_u8(128)));
int8x16_t s4567_lo, s4567_hi, s5678_lo, s5678_hi, s6789_lo, s6789_hi,
s78910_lo, s78910_hi;
- transpose_concat_8x4(s7, s8, s9, s10, &s78910_lo, &s78910_hi,
- tran_concat_tbl);
+ transpose_concat_8x4(s7, s8, s9, s10, &s78910_lo, &s78910_hi);
- /* Merge new data into block from previous iteration. */
+ // Merge new data into block from previous iteration.
samples_LUT.val[0] = s3456_lo;
samples_LUT.val[1] = s78910_lo;
s4567_lo = vqtbl2q_s8(samples_LUT, merge_block_tbl.val[0]);
@@ -406,19 +378,19 @@ void aom_convolve8_vert_neon_dotprod(const uint8_t *src, ptrdiff_t src_stride,
s5678_hi = vqtbl2q_s8(samples_LUT, merge_block_tbl.val[1]);
s6789_hi = vqtbl2q_s8(samples_LUT, merge_block_tbl.val[2]);
- uint8x8_t d0 = convolve8_8_sdot_partial(s0123_lo, s4567_lo, s0123_hi,
- s4567_hi, correction, filter);
- uint8x8_t d1 = convolve8_8_sdot_partial(s1234_lo, s5678_lo, s1234_hi,
- s5678_hi, correction, filter);
- uint8x8_t d2 = convolve8_8_sdot_partial(s2345_lo, s6789_lo, s2345_hi,
- s6789_hi, correction, filter);
- uint8x8_t d3 = convolve8_8_sdot_partial(s3456_lo, s78910_lo, s3456_hi,
- s78910_hi, correction, filter);
+ uint8x8_t d0 =
+ convolve8_8_v(s0123_lo, s4567_lo, s0123_hi, s4567_hi, filter);
+ uint8x8_t d1 =
+ convolve8_8_v(s1234_lo, s5678_lo, s1234_hi, s5678_hi, filter);
+ uint8x8_t d2 =
+ convolve8_8_v(s2345_lo, s6789_lo, s2345_hi, s6789_hi, filter);
+ uint8x8_t d3 =
+ convolve8_8_v(s3456_lo, s78910_lo, s3456_hi, s78910_hi, filter);
store_u8_8x4(d, dst_stride, d0, d1, d2, d3);
- /* Prepare block for next iteration - re-using as much as possible. */
- /* Shuffle everything up four rows. */
+ // Prepare block for next iteration - re-using as much as possible.
+ // Shuffle everything up four rows.
s0123_lo = s4567_lo;
s0123_hi = s4567_hi;
s1234_lo = s5678_lo;
diff --git a/third_party/aom/aom_dsp/arm/aom_convolve8_neon_i8mm.c b/third_party/aom/aom_dsp/arm/aom_convolve8_neon_i8mm.c
index df6e4d2ab5..68e031461d 100644
--- a/third_party/aom/aom_dsp/arm/aom_convolve8_neon_i8mm.c
+++ b/third_party/aom/aom_dsp/arm/aom_convolve8_neon_i8mm.c
@@ -23,69 +23,60 @@
#include "aom_dsp/arm/transpose_neon.h"
#include "aom_ports/mem.h"
-DECLARE_ALIGNED(16, static const uint8_t, dot_prod_permute_tbl[48]) = {
+DECLARE_ALIGNED(16, static const uint8_t, kDotProdPermuteTbl[48]) = {
0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6,
4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10,
8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
};
-DECLARE_ALIGNED(16, static const uint8_t, dot_prod_tran_concat_tbl[32]) = {
- 0, 8, 16, 24, 1, 9, 17, 25, 2, 10, 18, 26, 3, 11, 19, 27,
- 4, 12, 20, 28, 5, 13, 21, 29, 6, 14, 22, 30, 7, 15, 23, 31
-};
-
-DECLARE_ALIGNED(16, static const uint8_t, dot_prod_merge_block_tbl[48]) = {
- /* Shift left and insert new last column in transposed 4x4 block. */
+DECLARE_ALIGNED(16, static const uint8_t, kDotProdMergeBlockTbl[48]) = {
+ // Shift left and insert new last column in transposed 4x4 block.
1, 2, 3, 16, 5, 6, 7, 20, 9, 10, 11, 24, 13, 14, 15, 28,
- /* Shift left and insert two new columns in transposed 4x4 block. */
+ // Shift left and insert two new columns in transposed 4x4 block.
2, 3, 16, 17, 6, 7, 20, 21, 10, 11, 24, 25, 14, 15, 28, 29,
- /* Shift left and insert three new columns in transposed 4x4 block. */
+ // Shift left and insert three new columns in transposed 4x4 block.
3, 16, 17, 18, 7, 20, 21, 22, 11, 24, 25, 26, 15, 28, 29, 30
};
-static INLINE int16x4_t convolve8_4_usdot(const uint8x16_t samples,
- const int8x8_t filter,
- const uint8x16x2_t permute_tbl) {
- uint8x16_t permuted_samples[2];
- int32x4_t sum;
-
- /* Permute samples ready for dot product. */
- /* { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 } */
- permuted_samples[0] = vqtbl1q_u8(samples, permute_tbl.val[0]);
- /* { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 } */
- permuted_samples[1] = vqtbl1q_u8(samples, permute_tbl.val[1]);
+static INLINE int16x4_t convolve8_4_h(const uint8x16_t samples,
+ const int8x8_t filters,
+ const uint8x16x2_t permute_tbl) {
+ // Permute samples ready for dot product.
+ // { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 }
+ // { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 }
+ uint8x16_t permuted_samples[2] = { vqtbl1q_u8(samples, permute_tbl.val[0]),
+ vqtbl1q_u8(samples, permute_tbl.val[1]) };
- sum = vusdotq_lane_s32(vdupq_n_s32(0), permuted_samples[0], filter, 0);
- sum = vusdotq_lane_s32(sum, permuted_samples[1], filter, 1);
+ int32x4_t sum =
+ vusdotq_lane_s32(vdupq_n_s32(0), permuted_samples[0], filters, 0);
+ sum = vusdotq_lane_s32(sum, permuted_samples[1], filters, 1);
- /* Further narrowing and packing is performed by the caller. */
+ // Further narrowing and packing is performed by the caller.
return vqmovn_s32(sum);
}
-static INLINE uint8x8_t convolve8_8_usdot(const uint8x16_t samples,
- const int8x8_t filter,
- const uint8x16x3_t permute_tbl) {
- uint8x16_t permuted_samples[3];
- int32x4_t sum0, sum1;
- int16x8_t sum;
-
- /* Permute samples ready for dot product. */
- /* { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 } */
- permuted_samples[0] = vqtbl1q_u8(samples, permute_tbl.val[0]);
- /* { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 } */
- permuted_samples[1] = vqtbl1q_u8(samples, permute_tbl.val[1]);
- /* { 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 } */
- permuted_samples[2] = vqtbl1q_u8(samples, permute_tbl.val[2]);
-
- /* First 4 output values. */
- sum0 = vusdotq_lane_s32(vdupq_n_s32(0), permuted_samples[0], filter, 0);
- sum0 = vusdotq_lane_s32(sum0, permuted_samples[1], filter, 1);
- /* Second 4 output values. */
- sum1 = vusdotq_lane_s32(vdupq_n_s32(0), permuted_samples[1], filter, 0);
- sum1 = vusdotq_lane_s32(sum1, permuted_samples[2], filter, 1);
-
- /* Narrow and re-pack. */
- sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
+static INLINE uint8x8_t convolve8_8_h(const uint8x16_t samples,
+ const int8x8_t filters,
+ const uint8x16x3_t permute_tbl) {
+ // Permute samples ready for dot product.
+ // { 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 }
+ // { 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 }
+ // { 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 }
+ uint8x16_t permuted_samples[3] = { vqtbl1q_u8(samples, permute_tbl.val[0]),
+ vqtbl1q_u8(samples, permute_tbl.val[1]),
+ vqtbl1q_u8(samples, permute_tbl.val[2]) };
+
+ // First 4 output values.
+ int32x4_t sum0 =
+ vusdotq_lane_s32(vdupq_n_s32(0), permuted_samples[0], filters, 0);
+ sum0 = vusdotq_lane_s32(sum0, permuted_samples[1], filters, 1);
+ // Second 4 output values.
+ int32x4_t sum1 =
+ vusdotq_lane_s32(vdupq_n_s32(0), permuted_samples[1], filters, 0);
+ sum1 = vusdotq_lane_s32(sum1, permuted_samples[2], filters, 1);
+
+ // Narrow and re-pack.
+ int16x8_t sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
return vqrshrun_n_s16(sum, FILTER_BITS);
}
@@ -95,7 +86,6 @@ void aom_convolve8_horiz_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
const int16_t *filter_y, int y_step_q4,
int w, int h) {
const int8x8_t filter = vmovn_s16(vld1q_s16(filter_x));
- uint8x16_t s0, s1, s2, s3;
assert((intptr_t)dst % 4 == 0);
assert(dst_stride % 4 == 0);
@@ -107,19 +97,17 @@ void aom_convolve8_horiz_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
src -= ((SUBPEL_TAPS / 2) - 1);
if (w == 4) {
- const uint8x16x2_t perm_tbl = vld1q_u8_x2(dot_prod_permute_tbl);
+ const uint8x16x2_t perm_tbl = vld1q_u8_x2(kDotProdPermuteTbl);
do {
- int16x4_t t0, t1, t2, t3;
- uint8x8_t d01, d23;
-
+ uint8x16_t s0, s1, s2, s3;
load_u8_16x4(src, src_stride, &s0, &s1, &s2, &s3);
- t0 = convolve8_4_usdot(s0, filter, perm_tbl);
- t1 = convolve8_4_usdot(s1, filter, perm_tbl);
- t2 = convolve8_4_usdot(s2, filter, perm_tbl);
- t3 = convolve8_4_usdot(s3, filter, perm_tbl);
- d01 = vqrshrun_n_s16(vcombine_s16(t0, t1), FILTER_BITS);
- d23 = vqrshrun_n_s16(vcombine_s16(t2, t3), FILTER_BITS);
+ int16x4_t d0 = convolve8_4_h(s0, filter, perm_tbl);
+ int16x4_t d1 = convolve8_4_h(s1, filter, perm_tbl);
+ int16x4_t d2 = convolve8_4_h(s2, filter, perm_tbl);
+ int16x4_t d3 = convolve8_4_h(s3, filter, perm_tbl);
+ uint8x8_t d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
+ uint8x8_t d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
store_u8x4_strided_x2(dst + 0 * dst_stride, dst_stride, d01);
store_u8x4_strided_x2(dst + 2 * dst_stride, dst_stride, d23);
@@ -129,23 +117,20 @@ void aom_convolve8_horiz_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
h -= 4;
} while (h > 0);
} else {
- const uint8x16x3_t perm_tbl = vld1q_u8_x3(dot_prod_permute_tbl);
- const uint8_t *s;
- uint8_t *d;
- int width;
- uint8x8_t d0, d1, d2, d3;
+ const uint8x16x3_t perm_tbl = vld1q_u8_x3(kDotProdPermuteTbl);
do {
- width = w;
- s = src;
- d = dst;
+ int width = w;
+ const uint8_t *s = src;
+ uint8_t *d = dst;
do {
+ uint8x16_t s0, s1, s2, s3;
load_u8_16x4(s, src_stride, &s0, &s1, &s2, &s3);
- d0 = convolve8_8_usdot(s0, filter, perm_tbl);
- d1 = convolve8_8_usdot(s1, filter, perm_tbl);
- d2 = convolve8_8_usdot(s2, filter, perm_tbl);
- d3 = convolve8_8_usdot(s3, filter, perm_tbl);
+ uint8x8_t d0 = convolve8_8_h(s0, filter, perm_tbl);
+ uint8x8_t d1 = convolve8_8_h(s1, filter, perm_tbl);
+ uint8x8_t d2 = convolve8_8_h(s2, filter, perm_tbl);
+ uint8x8_t d3 = convolve8_8_h(s3, filter, perm_tbl);
store_u8_8x4(d, dst_stride, d0, d1, d2, d3);
@@ -162,79 +147,83 @@ void aom_convolve8_horiz_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
static INLINE void transpose_concat_4x4(uint8x8_t a0, uint8x8_t a1,
uint8x8_t a2, uint8x8_t a3,
- uint8x16_t *b,
- const uint8x16_t permute_tbl) {
- /* Transpose 8-bit elements and concatenate result rows as follows:
- * a0: 00, 01, 02, 03, XX, XX, XX, XX
- * a1: 10, 11, 12, 13, XX, XX, XX, XX
- * a2: 20, 21, 22, 23, XX, XX, XX, XX
- * a3: 30, 31, 32, 33, XX, XX, XX, XX
- *
- * b: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
- *
- * The 'permute_tbl' is always 'dot_prod_tran_concat_tbl' above. Passing it
- * as an argument is preferable to loading it directly from memory as this
- * inline helper is called many times from the same parent function.
- */
-
- uint8x16x2_t samples = { { vcombine_u8(a0, a1), vcombine_u8(a2, a3) } };
- *b = vqtbl2q_u8(samples, permute_tbl);
+ uint8x16_t *b) {
+ // Transpose 8-bit elements and concatenate result rows as follows:
+ // a0: 00, 01, 02, 03, XX, XX, XX, XX
+ // a1: 10, 11, 12, 13, XX, XX, XX, XX
+ // a2: 20, 21, 22, 23, XX, XX, XX, XX
+ // a3: 30, 31, 32, 33, XX, XX, XX, XX
+ //
+ // b: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
+
+ uint8x16_t a0q = vcombine_u8(a0, vdup_n_u8(0));
+ uint8x16_t a1q = vcombine_u8(a1, vdup_n_u8(0));
+ uint8x16_t a2q = vcombine_u8(a2, vdup_n_u8(0));
+ uint8x16_t a3q = vcombine_u8(a3, vdup_n_u8(0));
+
+ uint8x16_t a01 = vzipq_u8(a0q, a1q).val[0];
+ uint8x16_t a23 = vzipq_u8(a2q, a3q).val[0];
+
+ uint16x8_t a0123 =
+ vzipq_u16(vreinterpretq_u16_u8(a01), vreinterpretq_u16_u8(a23)).val[0];
+
+ *b = vreinterpretq_u8_u16(a0123);
}
static INLINE void transpose_concat_8x4(uint8x8_t a0, uint8x8_t a1,
uint8x8_t a2, uint8x8_t a3,
- uint8x16_t *b0, uint8x16_t *b1,
- const uint8x16x2_t permute_tbl) {
- /* Transpose 8-bit elements and concatenate result rows as follows:
- * a0: 00, 01, 02, 03, 04, 05, 06, 07
- * a1: 10, 11, 12, 13, 14, 15, 16, 17
- * a2: 20, 21, 22, 23, 24, 25, 26, 27
- * a3: 30, 31, 32, 33, 34, 35, 36, 37
- *
- * b0: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
- * b1: 04, 14, 24, 34, 05, 15, 25, 35, 06, 16, 26, 36, 07, 17, 27, 37
- *
- * The 'permute_tbl' is always 'dot_prod_tran_concat_tbl' above. Passing it
- * as an argument is preferable to loading it directly from memory as this
- * inline helper is called many times from the same parent function.
- */
-
- uint8x16x2_t samples = { { vcombine_u8(a0, a1), vcombine_u8(a2, a3) } };
- *b0 = vqtbl2q_u8(samples, permute_tbl.val[0]);
- *b1 = vqtbl2q_u8(samples, permute_tbl.val[1]);
+ uint8x16_t *b0, uint8x16_t *b1) {
+ // Transpose 8-bit elements and concatenate result rows as follows:
+ // a0: 00, 01, 02, 03, 04, 05, 06, 07
+ // a1: 10, 11, 12, 13, 14, 15, 16, 17
+ // a2: 20, 21, 22, 23, 24, 25, 26, 27
+ // a3: 30, 31, 32, 33, 34, 35, 36, 37
+ //
+ // b0: 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33
+ // b1: 04, 14, 24, 34, 05, 15, 25, 35, 06, 16, 26, 36, 07, 17, 27, 37
+
+ uint8x16_t a0q = vcombine_u8(a0, vdup_n_u8(0));
+ uint8x16_t a1q = vcombine_u8(a1, vdup_n_u8(0));
+ uint8x16_t a2q = vcombine_u8(a2, vdup_n_u8(0));
+ uint8x16_t a3q = vcombine_u8(a3, vdup_n_u8(0));
+
+ uint8x16_t a01 = vzipq_u8(a0q, a1q).val[0];
+ uint8x16_t a23 = vzipq_u8(a2q, a3q).val[0];
+
+ uint16x8x2_t a0123 =
+ vzipq_u16(vreinterpretq_u16_u8(a01), vreinterpretq_u16_u8(a23));
+
+ *b0 = vreinterpretq_u8_u16(a0123.val[0]);
+ *b1 = vreinterpretq_u8_u16(a0123.val[1]);
}
-static INLINE int16x4_t convolve8_4_usdot_partial(const uint8x16_t samples_lo,
- const uint8x16_t samples_hi,
- const int8x8_t filter) {
- /* Sample permutation is performed by the caller. */
- int32x4_t sum;
-
- sum = vusdotq_lane_s32(vdupq_n_s32(0), samples_lo, filter, 0);
- sum = vusdotq_lane_s32(sum, samples_hi, filter, 1);
+static INLINE int16x4_t convolve8_4_v(const uint8x16_t samples_lo,
+ const uint8x16_t samples_hi,
+ const int8x8_t filters) {
+ // Sample permutation is performed by the caller.
+ int32x4_t sum = vusdotq_lane_s32(vdupq_n_s32(0), samples_lo, filters, 0);
+ sum = vusdotq_lane_s32(sum, samples_hi, filters, 1);
- /* Further narrowing and packing is performed by the caller. */
+ // Further narrowing and packing is performed by the caller.
return vqmovn_s32(sum);
}
-static INLINE uint8x8_t convolve8_8_usdot_partial(const uint8x16_t samples0_lo,
- const uint8x16_t samples0_hi,
- const uint8x16_t samples1_lo,
- const uint8x16_t samples1_hi,
- const int8x8_t filter) {
- /* Sample permutation is performed by the caller. */
- int32x4_t sum0, sum1;
- int16x8_t sum;
-
- /* First 4 output values. */
- sum0 = vusdotq_lane_s32(vdupq_n_s32(0), samples0_lo, filter, 0);
- sum0 = vusdotq_lane_s32(sum0, samples0_hi, filter, 1);
- /* Second 4 output values. */
- sum1 = vusdotq_lane_s32(vdupq_n_s32(0), samples1_lo, filter, 0);
- sum1 = vusdotq_lane_s32(sum1, samples1_hi, filter, 1);
-
- /* Narrow and re-pack. */
- sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
+static INLINE uint8x8_t convolve8_8_v(const uint8x16_t samples0_lo,
+ const uint8x16_t samples0_hi,
+ const uint8x16_t samples1_lo,
+ const uint8x16_t samples1_hi,
+ const int8x8_t filters) {
+ // Sample permutation is performed by the caller.
+
+ // First 4 output values.
+ int32x4_t sum0 = vusdotq_lane_s32(vdupq_n_s32(0), samples0_lo, filters, 0);
+ sum0 = vusdotq_lane_s32(sum0, samples0_hi, filters, 1);
+ // Second 4 output values.
+ int32x4_t sum1 = vusdotq_lane_s32(vdupq_n_s32(0), samples1_lo, filters, 0);
+ sum1 = vusdotq_lane_s32(sum1, samples1_hi, filters, 1);
+
+ // Narrow and re-pack.
+ int16x8_t sum = vcombine_s16(vqmovn_s32(sum0), vqmovn_s32(sum1));
return vqrshrun_n_s16(sum, FILTER_BITS);
}
@@ -244,7 +233,7 @@ void aom_convolve8_vert_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
const int16_t *filter_y, int y_step_q4, int w,
int h) {
const int8x8_t filter = vmovn_s16(vld1q_s16(filter_y));
- const uint8x16x3_t merge_block_tbl = vld1q_u8_x3(dot_prod_merge_block_tbl);
+ const uint8x16x3_t merge_block_tbl = vld1q_u8_x3(kDotProdMergeBlockTbl);
uint8x16x2_t samples_LUT;
assert((intptr_t)dst % 4 == 0);
@@ -257,47 +246,44 @@ void aom_convolve8_vert_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
src -= ((SUBPEL_TAPS / 2) - 1) * src_stride;
if (w == 4) {
- const uint8x16_t tran_concat_tbl = vld1q_u8(dot_prod_tran_concat_tbl);
-
uint8x8_t s0, s1, s2, s3, s4, s5, s6;
load_u8_8x7(src, src_stride, &s0, &s1, &s2, &s3, &s4, &s5, &s6);
src += 7 * src_stride;
- /* This operation combines a conventional transpose and the sample permute
- * (see horizontal case) required before computing the dot product.
- */
+ // This operation combines a conventional transpose and the sample permute
+ // (see horizontal case) required before computing the dot product.
uint8x16_t s0123, s1234, s2345, s3456;
- transpose_concat_4x4(s0, s1, s2, s3, &s0123, tran_concat_tbl);
- transpose_concat_4x4(s1, s2, s3, s4, &s1234, tran_concat_tbl);
- transpose_concat_4x4(s2, s3, s4, s5, &s2345, tran_concat_tbl);
- transpose_concat_4x4(s3, s4, s5, s6, &s3456, tran_concat_tbl);
+ transpose_concat_4x4(s0, s1, s2, s3, &s0123);
+ transpose_concat_4x4(s1, s2, s3, s4, &s1234);
+ transpose_concat_4x4(s2, s3, s4, s5, &s2345);
+ transpose_concat_4x4(s3, s4, s5, s6, &s3456);
do {
uint8x8_t s7, s8, s9, s10;
load_u8_8x4(src, src_stride, &s7, &s8, &s9, &s10);
uint8x16_t s4567, s5678, s6789, s78910;
- transpose_concat_4x4(s7, s8, s9, s10, &s78910, tran_concat_tbl);
+ transpose_concat_4x4(s7, s8, s9, s10, &s78910);
- /* Merge new data into block from previous iteration. */
+ // Merge new data into block from previous iteration.
samples_LUT.val[0] = s3456;
samples_LUT.val[1] = s78910;
s4567 = vqtbl2q_u8(samples_LUT, merge_block_tbl.val[0]);
s5678 = vqtbl2q_u8(samples_LUT, merge_block_tbl.val[1]);
s6789 = vqtbl2q_u8(samples_LUT, merge_block_tbl.val[2]);
- int16x4_t d0 = convolve8_4_usdot_partial(s0123, s4567, filter);
- int16x4_t d1 = convolve8_4_usdot_partial(s1234, s5678, filter);
- int16x4_t d2 = convolve8_4_usdot_partial(s2345, s6789, filter);
- int16x4_t d3 = convolve8_4_usdot_partial(s3456, s78910, filter);
+ int16x4_t d0 = convolve8_4_v(s0123, s4567, filter);
+ int16x4_t d1 = convolve8_4_v(s1234, s5678, filter);
+ int16x4_t d2 = convolve8_4_v(s2345, s6789, filter);
+ int16x4_t d3 = convolve8_4_v(s3456, s78910, filter);
uint8x8_t d01 = vqrshrun_n_s16(vcombine_s16(d0, d1), FILTER_BITS);
uint8x8_t d23 = vqrshrun_n_s16(vcombine_s16(d2, d3), FILTER_BITS);
store_u8x4_strided_x2(dst + 0 * dst_stride, dst_stride, d01);
store_u8x4_strided_x2(dst + 2 * dst_stride, dst_stride, d23);
- /* Prepare block for next iteration - re-using as much as possible. */
- /* Shuffle everything up four rows. */
+ // Prepare block for next iteration - re-using as much as possible.
+ // Shuffle everything up four rows.
s0123 = s4567;
s1234 = s5678;
s2345 = s6789;
@@ -308,8 +294,6 @@ void aom_convolve8_vert_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
h -= 4;
} while (h != 0);
} else {
- const uint8x16x2_t tran_concat_tbl = vld1q_u8_x2(dot_prod_tran_concat_tbl);
-
do {
int height = h;
const uint8_t *s = src;
@@ -319,19 +303,14 @@ void aom_convolve8_vert_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
load_u8_8x7(s, src_stride, &s0, &s1, &s2, &s3, &s4, &s5, &s6);
s += 7 * src_stride;
- /* This operation combines a conventional transpose and the sample permute
- * (see horizontal case) required before computing the dot product.
- */
+ // This operation combines a conventional transpose and the sample permute
+ // (see horizontal case) required before computing the dot product.
uint8x16_t s0123_lo, s0123_hi, s1234_lo, s1234_hi, s2345_lo, s2345_hi,
s3456_lo, s3456_hi;
- transpose_concat_8x4(s0, s1, s2, s3, &s0123_lo, &s0123_hi,
- tran_concat_tbl);
- transpose_concat_8x4(s1, s2, s3, s4, &s1234_lo, &s1234_hi,
- tran_concat_tbl);
- transpose_concat_8x4(s2, s3, s4, s5, &s2345_lo, &s2345_hi,
- tran_concat_tbl);
- transpose_concat_8x4(s3, s4, s5, s6, &s3456_lo, &s3456_hi,
- tran_concat_tbl);
+ transpose_concat_8x4(s0, s1, s2, s3, &s0123_lo, &s0123_hi);
+ transpose_concat_8x4(s1, s2, s3, s4, &s1234_lo, &s1234_hi);
+ transpose_concat_8x4(s2, s3, s4, s5, &s2345_lo, &s2345_hi);
+ transpose_concat_8x4(s3, s4, s5, s6, &s3456_lo, &s3456_hi);
do {
uint8x8_t s7, s8, s9, s10;
@@ -339,10 +318,9 @@ void aom_convolve8_vert_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
uint8x16_t s4567_lo, s4567_hi, s5678_lo, s5678_hi, s6789_lo, s6789_hi,
s78910_lo, s78910_hi;
- transpose_concat_8x4(s7, s8, s9, s10, &s78910_lo, &s78910_hi,
- tran_concat_tbl);
+ transpose_concat_8x4(s7, s8, s9, s10, &s78910_lo, &s78910_hi);
- /* Merge new data into block from previous iteration. */
+ // Merge new data into block from previous iteration.
samples_LUT.val[0] = s3456_lo;
samples_LUT.val[1] = s78910_lo;
s4567_lo = vqtbl2q_u8(samples_LUT, merge_block_tbl.val[0]);
@@ -355,19 +333,19 @@ void aom_convolve8_vert_neon_i8mm(const uint8_t *src, ptrdiff_t src_stride,
s5678_hi = vqtbl2q_u8(samples_LUT, merge_block_tbl.val[1]);
s6789_hi = vqtbl2q_u8(samples_LUT, merge_block_tbl.val[2]);
- uint8x8_t d0 = convolve8_8_usdot_partial(s0123_lo, s4567_lo, s0123_hi,
- s4567_hi, filter);
- uint8x8_t d1 = convolve8_8_usdot_partial(s1234_lo, s5678_lo, s1234_hi,
- s5678_hi, filter);
- uint8x8_t d2 = convolve8_8_usdot_partial(s2345_lo, s6789_lo, s2345_hi,
- s6789_hi, filter);
- uint8x8_t d3 = convolve8_8_usdot_partial(s3456_lo, s78910_lo, s3456_hi,
- s78910_hi, filter);
+ uint8x8_t d0 =
+ convolve8_8_v(s0123_lo, s4567_lo, s0123_hi, s4567_hi, filter);
+ uint8x8_t d1 =
+ convolve8_8_v(s1234_lo, s5678_lo, s1234_hi, s5678_hi, filter);
+ uint8x8_t d2 =
+ convolve8_8_v(s2345_lo, s6789_lo, s2345_hi, s6789_hi, filter);
+ uint8x8_t d3 =
+ convolve8_8_v(s3456_lo, s78910_lo, s3456_hi, s78910_hi, filter);
store_u8_8x4(d, dst_stride, d0, d1, d2, d3);
- /* Prepare block for next iteration - re-using as much as possible. */
- /* Shuffle everything up four rows. */
+ // Prepare block for next iteration - re-using as much as possible.
+ // Shuffle everything up four rows.
s0123_lo = s4567_lo;
s0123_hi = s4567_hi;
s1234_lo = s5678_lo;
diff --git a/third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.c b/third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.c
index 62729133e3..5758d2887f 100644
--- a/third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.c
+++ b/third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.c
@@ -16,36 +16,10 @@
#include "aom_dsp/arm/mem_neon.h"
#include "aom_dsp/arm/sum_neon.h"
+#include "aom_dsp/flow_estimation/arm/disflow_neon.h"
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
-static INLINE void get_cubic_kernel_dbl(double x, double kernel[4]) {
- // Check that the fractional position is in range.
- //
- // Note: x is calculated from, e.g., `u_frac = u - floor(u)`.
- // Mathematically, this implies that 0 <= x < 1. However, in practice it is
- // possible to have x == 1 due to floating point rounding. This is fine,
- // and we still interpolate correctly if we allow x = 1.
- assert(0 <= x && x <= 1);
-
- double x2 = x * x;
- double x3 = x2 * x;
- kernel[0] = -0.5 * x + x2 - 0.5 * x3;
- kernel[1] = 1.0 - 2.5 * x2 + 1.5 * x3;
- kernel[2] = 0.5 * x + 2.0 * x2 - 1.5 * x3;
- kernel[3] = -0.5 * x2 + 0.5 * x3;
-}
-
-static INLINE void get_cubic_kernel_int(double x, int kernel[4]) {
- double kernel_dbl[4];
- get_cubic_kernel_dbl(x, kernel_dbl);
-
- kernel[0] = (int)rint(kernel_dbl[0] * (1 << DISFLOW_INTERP_BITS));
- kernel[1] = (int)rint(kernel_dbl[1] * (1 << DISFLOW_INTERP_BITS));
- kernel[2] = (int)rint(kernel_dbl[2] * (1 << DISFLOW_INTERP_BITS));
- kernel[3] = (int)rint(kernel_dbl[3] * (1 << DISFLOW_INTERP_BITS));
-}
-
// Compare two regions of width x height pixels, one rooted at position
// (x, y) in src and the other at (x + u, y + v) in ref.
// This function returns the sum of squared pixel differences between
@@ -157,82 +131,6 @@ static INLINE void compute_flow_error(const uint8_t *src, const uint8_t *ref,
}
}
-static INLINE void sobel_filter_x(const uint8_t *src, int src_stride,
- int16_t *dst, int dst_stride) {
- int16_t tmp[DISFLOW_PATCH_SIZE * (DISFLOW_PATCH_SIZE + 2)];
-
- // Horizontal filter, using kernel {1, 0, -1}.
- const uint8_t *src_start = src - 1 * src_stride - 1;
-
- for (int i = 0; i < DISFLOW_PATCH_SIZE + 2; i++) {
- uint8x16_t s = vld1q_u8(src_start + i * src_stride);
- uint8x8_t s0 = vget_low_u8(s);
- uint8x8_t s2 = vget_low_u8(vextq_u8(s, s, 2));
-
- // Given that the kernel is {1, 0, -1} the convolution is a simple
- // subtraction.
- int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(s0, s2));
-
- vst1q_s16(tmp + i * DISFLOW_PATCH_SIZE, diff);
- }
-
- // Vertical filter, using kernel {1, 2, 1}.
- // This kernel can be split into two 2-taps kernels of value {1, 1}.
- // That way we need only 3 add operations to perform the convolution, one of
- // which can be reused for the next line.
- int16x8_t s0 = vld1q_s16(tmp);
- int16x8_t s1 = vld1q_s16(tmp + DISFLOW_PATCH_SIZE);
- int16x8_t sum01 = vaddq_s16(s0, s1);
- for (int i = 0; i < DISFLOW_PATCH_SIZE; i++) {
- int16x8_t s2 = vld1q_s16(tmp + (i + 2) * DISFLOW_PATCH_SIZE);
-
- int16x8_t sum12 = vaddq_s16(s1, s2);
- int16x8_t sum = vaddq_s16(sum01, sum12);
-
- vst1q_s16(dst + i * dst_stride, sum);
-
- sum01 = sum12;
- s1 = s2;
- }
-}
-
-static INLINE void sobel_filter_y(const uint8_t *src, int src_stride,
- int16_t *dst, int dst_stride) {
- int16_t tmp[DISFLOW_PATCH_SIZE * (DISFLOW_PATCH_SIZE + 2)];
-
- // Horizontal filter, using kernel {1, 2, 1}.
- // This kernel can be split into two 2-taps kernels of value {1, 1}.
- // That way we need only 3 add operations to perform the convolution.
- const uint8_t *src_start = src - 1 * src_stride - 1;
-
- for (int i = 0; i < DISFLOW_PATCH_SIZE + 2; i++) {
- uint8x16_t s = vld1q_u8(src_start + i * src_stride);
- uint8x8_t s0 = vget_low_u8(s);
- uint8x8_t s1 = vget_low_u8(vextq_u8(s, s, 1));
- uint8x8_t s2 = vget_low_u8(vextq_u8(s, s, 2));
-
- uint16x8_t sum01 = vaddl_u8(s0, s1);
- uint16x8_t sum12 = vaddl_u8(s1, s2);
- uint16x8_t sum = vaddq_u16(sum01, sum12);
-
- vst1q_s16(tmp + i * DISFLOW_PATCH_SIZE, vreinterpretq_s16_u16(sum));
- }
-
- // Vertical filter, using kernel {1, 0, -1}.
- // Load the whole block at once to avoid redundant loads during convolution.
- int16x8_t t[10];
- load_s16_8x10(tmp, DISFLOW_PATCH_SIZE, &t[0], &t[1], &t[2], &t[3], &t[4],
- &t[5], &t[6], &t[7], &t[8], &t[9]);
-
- for (int i = 0; i < DISFLOW_PATCH_SIZE; i++) {
- // Given that the kernel is {1, 0, -1} the convolution is a simple
- // subtraction.
- int16x8_t diff = vsubq_s16(t[i], t[i + 2]);
-
- vst1q_s16(dst + i * dst_stride, diff);
- }
-}
-
// Computes the components of the system of equations used to solve for
// a flow vector.
//
diff --git a/third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.h b/third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.h
new file mode 100644
index 0000000000..d991a13460
--- /dev/null
+++ b/third_party/aom/aom_dsp/flow_estimation/arm/disflow_neon.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#ifndef AOM_AOM_DSP_FLOW_ESTIMATION_ARM_DISFLOW_NEON_H_
+#define AOM_AOM_DSP_FLOW_ESTIMATION_ARM_DISFLOW_NEON_H_
+
+#include "aom_dsp/flow_estimation/disflow.h"
+
+#include <arm_neon.h>
+#include <math.h>
+
+#include "aom_dsp/arm/mem_neon.h"
+#include "config/aom_config.h"
+#include "config/aom_dsp_rtcd.h"
+
+static INLINE void get_cubic_kernel_dbl(double x, double kernel[4]) {
+ // Check that the fractional position is in range.
+ //
+ // Note: x is calculated from, e.g., `u_frac = u - floor(u)`.
+ // Mathematically, this implies that 0 <= x < 1. However, in practice it is
+ // possible to have x == 1 due to floating point rounding. This is fine,
+ // and we still interpolate correctly if we allow x = 1.
+ assert(0 <= x && x <= 1);
+
+ double x2 = x * x;
+ double x3 = x2 * x;
+ kernel[0] = -0.5 * x + x2 - 0.5 * x3;
+ kernel[1] = 1.0 - 2.5 * x2 + 1.5 * x3;
+ kernel[2] = 0.5 * x + 2.0 * x2 - 1.5 * x3;
+ kernel[3] = -0.5 * x2 + 0.5 * x3;
+}
+
+static INLINE void get_cubic_kernel_int(double x, int kernel[4]) {
+ double kernel_dbl[4];
+ get_cubic_kernel_dbl(x, kernel_dbl);
+
+ kernel[0] = (int)rint(kernel_dbl[0] * (1 << DISFLOW_INTERP_BITS));
+ kernel[1] = (int)rint(kernel_dbl[1] * (1 << DISFLOW_INTERP_BITS));
+ kernel[2] = (int)rint(kernel_dbl[2] * (1 << DISFLOW_INTERP_BITS));
+ kernel[3] = (int)rint(kernel_dbl[3] * (1 << DISFLOW_INTERP_BITS));
+}
+
+static INLINE void sobel_filter_x(const uint8_t *src, int src_stride,
+ int16_t *dst, int dst_stride) {
+ int16_t tmp[DISFLOW_PATCH_SIZE * (DISFLOW_PATCH_SIZE + 2)];
+
+ // Horizontal filter, using kernel {1, 0, -1}.
+ const uint8_t *src_start = src - 1 * src_stride - 1;
+
+ for (int i = 0; i < DISFLOW_PATCH_SIZE + 2; i++) {
+ uint8x16_t s = vld1q_u8(src_start + i * src_stride);
+ uint8x8_t s0 = vget_low_u8(s);
+ uint8x8_t s2 = vget_low_u8(vextq_u8(s, s, 2));
+
+ // Given that the kernel is {1, 0, -1} the convolution is a simple
+ // subtraction.
+ int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(s0, s2));
+
+ vst1q_s16(tmp + i * DISFLOW_PATCH_SIZE, diff);
+ }
+
+ // Vertical filter, using kernel {1, 2, 1}.
+ // This kernel can be split into two 2-taps kernels of value {1, 1}.
+ // That way we need only 3 add operations to perform the convolution, one of
+ // which can be reused for the next line.
+ int16x8_t s0 = vld1q_s16(tmp);
+ int16x8_t s1 = vld1q_s16(tmp + DISFLOW_PATCH_SIZE);
+ int16x8_t sum01 = vaddq_s16(s0, s1);
+ for (int i = 0; i < DISFLOW_PATCH_SIZE; i++) {
+ int16x8_t s2 = vld1q_s16(tmp + (i + 2) * DISFLOW_PATCH_SIZE);
+
+ int16x8_t sum12 = vaddq_s16(s1, s2);
+ int16x8_t sum = vaddq_s16(sum01, sum12);
+
+ vst1q_s16(dst + i * dst_stride, sum);
+
+ sum01 = sum12;
+ s1 = s2;
+ }
+}
+
+static INLINE void sobel_filter_y(const uint8_t *src, int src_stride,
+ int16_t *dst, int dst_stride) {
+ int16_t tmp[DISFLOW_PATCH_SIZE * (DISFLOW_PATCH_SIZE + 2)];
+
+ // Horizontal filter, using kernel {1, 2, 1}.
+ // This kernel can be split into two 2-taps kernels of value {1, 1}.
+ // That way we need only 3 add operations to perform the convolution.
+ const uint8_t *src_start = src - 1 * src_stride - 1;
+
+ for (int i = 0; i < DISFLOW_PATCH_SIZE + 2; i++) {
+ uint8x16_t s = vld1q_u8(src_start + i * src_stride);
+ uint8x8_t s0 = vget_low_u8(s);
+ uint8x8_t s1 = vget_low_u8(vextq_u8(s, s, 1));
+ uint8x8_t s2 = vget_low_u8(vextq_u8(s, s, 2));
+
+ uint16x8_t sum01 = vaddl_u8(s0, s1);
+ uint16x8_t sum12 = vaddl_u8(s1, s2);
+ uint16x8_t sum = vaddq_u16(sum01, sum12);
+
+ vst1q_s16(tmp + i * DISFLOW_PATCH_SIZE, vreinterpretq_s16_u16(sum));
+ }
+
+ // Vertical filter, using kernel {1, 0, -1}.
+ // Load the whole block at once to avoid redundant loads during convolution.
+ int16x8_t t[10];
+ load_s16_8x10(tmp, DISFLOW_PATCH_SIZE, &t[0], &t[1], &t[2], &t[3], &t[4],
+ &t[5], &t[6], &t[7], &t[8], &t[9]);
+
+ for (int i = 0; i < DISFLOW_PATCH_SIZE; i++) {
+ // Given that the kernel is {1, 0, -1} the convolution is a simple
+ // subtraction.
+ int16x8_t diff = vsubq_s16(t[i], t[i + 2]);
+
+ vst1q_s16(dst + i * dst_stride, diff);
+ }
+}
+
+#endif // AOM_AOM_DSP_FLOW_ESTIMATION_ARM_DISFLOW_NEON_H_
diff --git a/third_party/aom/aom_dsp/flow_estimation/arm/disflow_sve.c b/third_party/aom/aom_dsp/flow_estimation/arm/disflow_sve.c
new file mode 100644
index 0000000000..7b01e90d12
--- /dev/null
+++ b/third_party/aom/aom_dsp/flow_estimation/arm/disflow_sve.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2024, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#include "aom_dsp/flow_estimation/disflow.h"
+
+#include <arm_neon.h>
+#include <arm_sve.h>
+#include <math.h>
+
+#include "aom_dsp/arm/aom_neon_sve_bridge.h"
+#include "aom_dsp/arm/mem_neon.h"
+#include "aom_dsp/arm/sum_neon.h"
+#include "aom_dsp/flow_estimation/arm/disflow_neon.h"
+#include "config/aom_config.h"
+#include "config/aom_dsp_rtcd.h"
+
+DECLARE_ALIGNED(16, static const uint16_t, kDeinterleaveTbl[8]) = {
+ 0, 2, 4, 6, 1, 3, 5, 7,
+};
+
+// Compare two regions of width x height pixels, one rooted at position
+// (x, y) in src and the other at (x + u, y + v) in ref.
+// This function returns the sum of squared pixel differences between
+// the two regions.
+static INLINE void compute_flow_error(const uint8_t *src, const uint8_t *ref,
+ int width, int height, int stride, int x,
+ int y, double u, double v, int16_t *dt) {
+ // Split offset into integer and fractional parts, and compute cubic
+ // interpolation kernels
+ const int u_int = (int)floor(u);
+ const int v_int = (int)floor(v);
+ const double u_frac = u - floor(u);
+ const double v_frac = v - floor(v);
+
+ int h_kernel[4];
+ int v_kernel[4];
+ get_cubic_kernel_int(u_frac, h_kernel);
+ get_cubic_kernel_int(v_frac, v_kernel);
+
+ int16_t tmp_[DISFLOW_PATCH_SIZE * (DISFLOW_PATCH_SIZE + 3)];
+
+ // Clamp coordinates so that all pixels we fetch will remain within the
+ // allocated border region, but allow them to go far enough out that
+ // the border pixels' values do not change.
+ // Since we are calculating an 8x8 block, the bottom-right pixel
+ // in the block has coordinates (x0 + 7, y0 + 7). Then, the cubic
+ // interpolation has 4 taps, meaning that the output of pixel
+ // (x_w, y_w) depends on the pixels in the range
+ // ([x_w - 1, x_w + 2], [y_w - 1, y_w + 2]).
+ //
+ // Thus the most extreme coordinates which will be fetched are
+ // (x0 - 1, y0 - 1) and (x0 + 9, y0 + 9).
+ const int x0 = clamp(x + u_int, -9, width);
+ const int y0 = clamp(y + v_int, -9, height);
+
+ // Horizontal convolution.
+ const uint8_t *ref_start = ref + (y0 - 1) * stride + (x0 - 1);
+ const int16x4_t h_kernel_s16 = vmovn_s32(vld1q_s32(h_kernel));
+ const int16x8_t h_filter = vcombine_s16(h_kernel_s16, vdup_n_s16(0));
+ const uint16x8_t idx = vld1q_u16(kDeinterleaveTbl);
+
+ for (int i = 0; i < DISFLOW_PATCH_SIZE + 3; ++i) {
+ svuint16_t r0 = svld1ub_u16(svptrue_b16(), ref_start + i * stride + 0);
+ svuint16_t r1 = svld1ub_u16(svptrue_b16(), ref_start + i * stride + 1);
+ svuint16_t r2 = svld1ub_u16(svptrue_b16(), ref_start + i * stride + 2);
+ svuint16_t r3 = svld1ub_u16(svptrue_b16(), ref_start + i * stride + 3);
+
+ int16x8_t s0 = vreinterpretq_s16_u16(svget_neonq_u16(r0));
+ int16x8_t s1 = vreinterpretq_s16_u16(svget_neonq_u16(r1));
+ int16x8_t s2 = vreinterpretq_s16_u16(svget_neonq_u16(r2));
+ int16x8_t s3 = vreinterpretq_s16_u16(svget_neonq_u16(r3));
+
+ int64x2_t sum04 = aom_svdot_lane_s16(vdupq_n_s64(0), s0, h_filter, 0);
+ int64x2_t sum15 = aom_svdot_lane_s16(vdupq_n_s64(0), s1, h_filter, 0);
+ int64x2_t sum26 = aom_svdot_lane_s16(vdupq_n_s64(0), s2, h_filter, 0);
+ int64x2_t sum37 = aom_svdot_lane_s16(vdupq_n_s64(0), s3, h_filter, 0);
+
+ int32x4_t res0 = vcombine_s32(vmovn_s64(sum04), vmovn_s64(sum15));
+ int32x4_t res1 = vcombine_s32(vmovn_s64(sum26), vmovn_s64(sum37));
+
+ // 6 is the maximum allowable number of extra bits which will avoid
+ // the intermediate values overflowing an int16_t. The most extreme
+ // intermediate value occurs when:
+ // * The input pixels are [0, 255, 255, 0]
+ // * u_frac = 0.5
+ // In this case, the un-scaled output is 255 * 1.125 = 286.875.
+ // As an integer with 6 fractional bits, that is 18360, which fits
+ // in an int16_t. But with 7 fractional bits it would be 36720,
+ // which is too large.
+ int16x8_t res = vcombine_s16(vrshrn_n_s32(res0, DISFLOW_INTERP_BITS - 6),
+ vrshrn_n_s32(res1, DISFLOW_INTERP_BITS - 6));
+
+ res = aom_tbl_s16(res, idx);
+
+ vst1q_s16(tmp_ + i * DISFLOW_PATCH_SIZE, res);
+ }
+
+ // Vertical convolution.
+ int16x4_t v_filter = vmovn_s32(vld1q_s32(v_kernel));
+ int16_t *tmp_start = tmp_ + DISFLOW_PATCH_SIZE;
+
+ for (int i = 0; i < DISFLOW_PATCH_SIZE; ++i) {
+ int16x8_t t0 = vld1q_s16(tmp_start + (i - 1) * DISFLOW_PATCH_SIZE);
+ int16x8_t t1 = vld1q_s16(tmp_start + i * DISFLOW_PATCH_SIZE);
+ int16x8_t t2 = vld1q_s16(tmp_start + (i + 1) * DISFLOW_PATCH_SIZE);
+ int16x8_t t3 = vld1q_s16(tmp_start + (i + 2) * DISFLOW_PATCH_SIZE);
+
+ int32x4_t sum_lo = vmull_lane_s16(vget_low_s16(t0), v_filter, 0);
+ sum_lo = vmlal_lane_s16(sum_lo, vget_low_s16(t1), v_filter, 1);
+ sum_lo = vmlal_lane_s16(sum_lo, vget_low_s16(t2), v_filter, 2);
+ sum_lo = vmlal_lane_s16(sum_lo, vget_low_s16(t3), v_filter, 3);
+
+ int32x4_t sum_hi = vmull_lane_s16(vget_high_s16(t0), v_filter, 0);
+ sum_hi = vmlal_lane_s16(sum_hi, vget_high_s16(t1), v_filter, 1);
+ sum_hi = vmlal_lane_s16(sum_hi, vget_high_s16(t2), v_filter, 2);
+ sum_hi = vmlal_lane_s16(sum_hi, vget_high_s16(t3), v_filter, 3);
+
+ uint8x8_t s = vld1_u8(src + (i + y) * stride + x);
+ int16x8_t s_s16 = vreinterpretq_s16_u16(vshll_n_u8(s, 3));
+
+ // This time, we have to round off the 6 extra bits which were kept
+ // earlier, but we also want to keep DISFLOW_DERIV_SCALE_LOG2 extra bits
+ // of precision to match the scale of the dx and dy arrays.
+ sum_lo = vrshrq_n_s32(sum_lo,
+ DISFLOW_INTERP_BITS + 6 - DISFLOW_DERIV_SCALE_LOG2);
+ sum_hi = vrshrq_n_s32(sum_hi,
+ DISFLOW_INTERP_BITS + 6 - DISFLOW_DERIV_SCALE_LOG2);
+ int32x4_t err_lo = vsubw_s16(sum_lo, vget_low_s16(s_s16));
+ int32x4_t err_hi = vsubw_s16(sum_hi, vget_high_s16(s_s16));
+ vst1q_s16(dt + i * DISFLOW_PATCH_SIZE,
+ vcombine_s16(vmovn_s32(err_lo), vmovn_s32(err_hi)));
+ }
+}
+
+// Computes the components of the system of equations used to solve for
+// a flow vector.
+//
+// The flow equations are a least-squares system, derived as follows:
+//
+// For each pixel in the patch, we calculate the current error `dt`,
+// and the x and y gradients `dx` and `dy` of the source patch.
+// This means that, to first order, the squared error for this pixel is
+//
+// (dt + u * dx + v * dy)^2
+//
+// where (u, v) are the incremental changes to the flow vector.
+//
+// We then want to find the values of u and v which minimize the sum
+// of the squared error across all pixels. Conveniently, this fits exactly
+// into the form of a least squares problem, with one equation
+//
+// u * dx + v * dy = -dt
+//
+// for each pixel.
+//
+// Summing across all pixels in a square window of size DISFLOW_PATCH_SIZE,
+// and absorbing the - sign elsewhere, this results in the least squares system
+//
+// M = |sum(dx * dx) sum(dx * dy)|
+// |sum(dx * dy) sum(dy * dy)|
+//
+// b = |sum(dx * dt)|
+// |sum(dy * dt)|
+static INLINE void compute_flow_matrix(const int16_t *dx, int dx_stride,
+ const int16_t *dy, int dy_stride,
+ double *M_inv) {
+ int64x2_t sum[3] = { vdupq_n_s64(0), vdupq_n_s64(0), vdupq_n_s64(0) };
+
+ for (int i = 0; i < DISFLOW_PATCH_SIZE; i++) {
+ int16x8_t x = vld1q_s16(dx + i * dx_stride);
+ int16x8_t y = vld1q_s16(dy + i * dy_stride);
+
+ sum[0] = aom_sdotq_s16(sum[0], x, x);
+ sum[1] = aom_sdotq_s16(sum[1], x, y);
+ sum[2] = aom_sdotq_s16(sum[2], y, y);
+ }
+
+ sum[0] = vpaddq_s64(sum[0], sum[1]);
+ sum[2] = vpaddq_s64(sum[1], sum[2]);
+ int32x4_t res = vcombine_s32(vmovn_s64(sum[0]), vmovn_s64(sum[2]));
+
+ // Apply regularization
+ // We follow the standard regularization method of adding `k * I` before
+ // inverting. This ensures that the matrix will be invertible.
+ //
+ // Setting the regularization strength k to 1 seems to work well here, as
+ // typical values coming from the other equations are very large (1e5 to
+ // 1e6, with an upper limit of around 6e7, at the time of writing).
+ // It also preserves the property that all matrix values are whole numbers,
+ // which is convenient for integerized SIMD implementation.
+
+ double M0 = (double)vgetq_lane_s32(res, 0) + 1;
+ double M1 = (double)vgetq_lane_s32(res, 1);
+ double M2 = (double)vgetq_lane_s32(res, 2);
+ double M3 = (double)vgetq_lane_s32(res, 3) + 1;
+
+ // Invert matrix M.
+ double det = (M0 * M3) - (M1 * M2);
+ assert(det >= 1);
+ const double det_inv = 1 / det;
+
+ M_inv[0] = M3 * det_inv;
+ M_inv[1] = -M1 * det_inv;
+ M_inv[2] = -M2 * det_inv;
+ M_inv[3] = M0 * det_inv;
+}
+
+static INLINE void compute_flow_vector(const int16_t *dx, int dx_stride,
+ const int16_t *dy, int dy_stride,
+ const int16_t *dt, int dt_stride,
+ int *b) {
+ int64x2_t b_s64[2] = { vdupq_n_s64(0), vdupq_n_s64(0) };
+
+ for (int i = 0; i < DISFLOW_PATCH_SIZE; i++) {
+ int16x8_t dx16 = vld1q_s16(dx + i * dx_stride);
+ int16x8_t dy16 = vld1q_s16(dy + i * dy_stride);
+ int16x8_t dt16 = vld1q_s16(dt + i * dt_stride);
+
+ b_s64[0] = aom_sdotq_s16(b_s64[0], dx16, dt16);
+ b_s64[1] = aom_sdotq_s16(b_s64[1], dy16, dt16);
+ }
+
+ b_s64[0] = vpaddq_s64(b_s64[0], b_s64[1]);
+ vst1_s32(b, vmovn_s64(b_s64[0]));
+}
+
+void aom_compute_flow_at_point_sve(const uint8_t *src, const uint8_t *ref,
+ int x, int y, int width, int height,
+ int stride, double *u, double *v) {
+ double M_inv[4];
+ int b[2];
+ int16_t dt[DISFLOW_PATCH_SIZE * DISFLOW_PATCH_SIZE];
+ int16_t dx[DISFLOW_PATCH_SIZE * DISFLOW_PATCH_SIZE];
+ int16_t dy[DISFLOW_PATCH_SIZE * DISFLOW_PATCH_SIZE];
+
+ // Compute gradients within this patch
+ const uint8_t *src_patch = &src[y * stride + x];
+ sobel_filter_x(src_patch, stride, dx, DISFLOW_PATCH_SIZE);
+ sobel_filter_y(src_patch, stride, dy, DISFLOW_PATCH_SIZE);
+
+ compute_flow_matrix(dx, DISFLOW_PATCH_SIZE, dy, DISFLOW_PATCH_SIZE, M_inv);
+
+ for (int itr = 0; itr < DISFLOW_MAX_ITR; itr++) {
+ compute_flow_error(src, ref, width, height, stride, x, y, *u, *v, dt);
+ compute_flow_vector(dx, DISFLOW_PATCH_SIZE, dy, DISFLOW_PATCH_SIZE, dt,
+ DISFLOW_PATCH_SIZE, b);
+
+ // Solve flow equations to find a better estimate for the flow vector
+ // at this point
+ const double step_u = M_inv[0] * b[0] + M_inv[1] * b[1];
+ const double step_v = M_inv[2] * b[0] + M_inv[3] * b[1];
+ *u += fclamp(step_u * DISFLOW_STEP_SIZE, -2, 2);
+ *v += fclamp(step_v * DISFLOW_STEP_SIZE, -2, 2);
+
+ if (fabs(step_u) + fabs(step_v) < DISFLOW_STEP_SIZE_THRESOLD) {
+ // Stop iteration when we're close to convergence
+ break;
+ }
+ }
+}
diff --git a/third_party/aom/aom_dsp/pyramid.c b/third_party/aom/aom_dsp/pyramid.c
index 5de001dbd5..05ddbb2f5f 100644
--- a/third_party/aom/aom_dsp/pyramid.c
+++ b/third_party/aom/aom_dsp/pyramid.c
@@ -305,6 +305,7 @@ static INLINE int fill_pyramid(const YV12_BUFFER_CONFIG *frame, int bit_depth,
// Fill in the remaining levels through progressive downsampling
for (int level = already_filled_levels; level < n_levels; ++level) {
+ bool mem_status = false;
PyramidLayer *prev_layer = &frame_pyr->layers[level - 1];
uint8_t *prev_buffer = prev_layer->buffer;
int prev_stride = prev_layer->stride;
@@ -315,6 +316,11 @@ static INLINE int fill_pyramid(const YV12_BUFFER_CONFIG *frame, int bit_depth,
int this_height = this_layer->height;
int this_stride = this_layer->stride;
+ // The width and height of the previous layer that needs to be considered to
+ // derive the current layer frame.
+ const int input_layer_width = this_width << 1;
+ const int input_layer_height = this_height << 1;
+
// Compute the this pyramid level by downsampling the current level.
//
// We downsample by a factor of exactly 2, clipping the rightmost and
@@ -329,13 +335,30 @@ static INLINE int fill_pyramid(const YV12_BUFFER_CONFIG *frame, int bit_depth,
// 2) Up/downsampling by a factor of 2 can be implemented much more
// efficiently than up/downsampling by a generic ratio.
// TODO(rachelbarker): Use optimized downsample-by-2 function
- if (!av1_resize_plane(prev_buffer, this_height << 1, this_width << 1,
- prev_stride, this_buffer, this_height, this_width,
- this_stride)) {
- // If we can't allocate memory, we'll have to terminate early
+
+ // SIMD support has been added specifically for cases where the downsample
+ // factor is exactly 2. In such instances, horizontal and vertical resizing
+ // is performed utilizing the down2_symeven() function, which considers the
+ // even dimensions of the input layer.
+ if (should_resize_by_half(input_layer_height, input_layer_width,
+ this_height, this_width)) {
+ assert(input_layer_height % 2 == 0 && input_layer_width % 2 == 0 &&
+ "Input width or height cannot be odd.");
+ mem_status = av1_resize_plane_to_half(
+ prev_buffer, input_layer_height, input_layer_width, prev_stride,
+ this_buffer, this_height, this_width, this_stride);
+ } else {
+ mem_status = av1_resize_plane(prev_buffer, input_layer_height,
+ input_layer_width, prev_stride, this_buffer,
+ this_height, this_width, this_stride);
+ }
+
+ // Terminate early in cases of memory allocation failure.
+ if (!mem_status) {
frame_pyr->filled_levels = n_levels;
return -1;
}
+
fill_border(this_buffer, this_width, this_height, this_stride);
}
diff --git a/third_party/aom/aom_dsp/x86/synonyms.h b/third_party/aom/aom_dsp/x86/synonyms.h
index 74318de2e5..f9bc9ac733 100644
--- a/third_party/aom/aom_dsp/x86/synonyms.h
+++ b/third_party/aom/aom_dsp/x86/synonyms.h
@@ -46,7 +46,6 @@ static INLINE __m128i xx_loadu_128(const void *a) {
return _mm_loadu_si128((const __m128i *)a);
}
-
// _mm_loadu_si64 has been introduced in GCC 9, reimplement the function
// manually on older compilers.
#if !defined(__clang__) && __GNUC_MAJOR__ < 9
diff --git a/third_party/aom/aom_util/aom_pthread.h b/third_party/aom/aom_util/aom_pthread.h
index 99deeb292a..e755487ae3 100644
--- a/third_party/aom/aom_util/aom_pthread.h
+++ b/third_party/aom/aom_util/aom_pthread.h
@@ -28,6 +28,7 @@ extern "C" {
#define NOMINMAX
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
+#include <errno.h> // NOLINT
#include <process.h> // NOLINT
#include <stddef.h> // NOLINT
#include <windows.h> // NOLINT
diff --git a/third_party/aom/aom_util/aom_thread.h b/third_party/aom/aom_util/aom_thread.h
index 92e162f121..80ed314752 100644
--- a/third_party/aom/aom_util/aom_thread.h
+++ b/third_party/aom/aom_util/aom_thread.h
@@ -21,8 +21,6 @@
extern "C" {
#endif
-#define MAX_NUM_THREADS 64
-
// State of the worker thread object
typedef enum {
AVX_WORKER_STATUS_NOT_OK = 0, // object is unusable
diff --git a/third_party/aom/av1/av1.cmake b/third_party/aom/av1/av1.cmake
index 32645f6065..b6cf974aa7 100644
--- a/third_party/aom/av1/av1.cmake
+++ b/third_party/aom/av1/av1.cmake
@@ -302,6 +302,7 @@ list(APPEND AOM_AV1_COMMON_INTRIN_AVX2
"${AOM_ROOT}/av1/common/x86/highbd_inv_txfm_avx2.c"
"${AOM_ROOT}/av1/common/x86/jnt_convolve_avx2.c"
"${AOM_ROOT}/av1/common/x86/reconinter_avx2.c"
+ "${AOM_ROOT}/av1/common/x86/resize_avx2.c"
"${AOM_ROOT}/av1/common/x86/selfguided_avx2.c"
"${AOM_ROOT}/av1/common/x86/warp_plane_avx2.c"
"${AOM_ROOT}/av1/common/x86/wiener_convolve_avx2.c")
@@ -375,6 +376,7 @@ list(APPEND AOM_AV1_ENCODER_INTRIN_NEON_DOTPROD
list(APPEND AOM_AV1_ENCODER_INTRIN_SVE
"${AOM_ROOT}/av1/encoder/arm/neon/av1_error_sve.c"
+ "${AOM_ROOT}/av1/encoder/arm/neon/pickrst_sve.c"
"${AOM_ROOT}/av1/encoder/arm/neon/wedge_utils_sve.c")
list(APPEND AOM_AV1_ENCODER_INTRIN_ARM_CRC32
diff --git a/third_party/aom/av1/av1_cx_iface.c b/third_party/aom/av1/av1_cx_iface.c
index 2b6b1504e6..39c03c9ecb 100644
--- a/third_party/aom/av1/av1_cx_iface.c
+++ b/third_party/aom/av1/av1_cx_iface.c
@@ -32,6 +32,7 @@
#include "av1/common/enums.h"
#include "av1/common/scale.h"
#include "av1/encoder/bitstream.h"
+#include "av1/encoder/enc_enums.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/encoder_alloc.h"
#include "av1/encoder/encoder_utils.h"
diff --git a/third_party/aom/av1/common/arm/compound_convolve_neon_dotprod.c b/third_party/aom/av1/common/arm/compound_convolve_neon_dotprod.c
index 3aeffbb0e6..40befdf44e 100644
--- a/third_party/aom/av1/common/arm/compound_convolve_neon_dotprod.c
+++ b/third_party/aom/av1/common/arm/compound_convolve_neon_dotprod.c
@@ -80,17 +80,15 @@ static INLINE void dist_wtd_convolve_2d_horiz_neon_dotprod(
const uint8_t *src, int src_stride, int16_t *im_block, const int im_stride,
const int16_t *x_filter_ptr, const int im_h, int w) {
const int bd = 8;
- const int32_t horiz_const = (1 << (bd + FILTER_BITS - 2));
// Dot product constants and other shims.
const int16x8_t x_filter_s16 = vld1q_s16(x_filter_ptr);
- const int32_t correction_s32 =
- vaddlvq_s16(vshlq_n_s16(x_filter_s16, FILTER_BITS - 1));
- // Fold horiz_const into the dot-product filter correction constant. The
- // additional shim of 1 << ((ROUND0_BITS - 1) - 1) enables us to use non-
- // rounding shifts - which are generally faster than rounding shifts on
- // modern CPUs. (The extra -1 is needed because we halved the filter values.)
- const int32x4_t correction = vdupq_n_s32(correction_s32 + horiz_const +
- (1 << ((ROUND0_BITS - 1) - 1)));
+ // This shim of 1 << (ROUND0_BITS - 1) enables us to use non-rounding shifts
+ // - which are generally faster than rounding shifts on modern CPUs.
+ const int32_t horiz_const =
+ ((1 << (bd + FILTER_BITS - 1)) + (1 << (ROUND0_BITS - 1)));
+ // Halve the total because we will halve the filter values.
+ const int32x4_t correction =
+ vdupq_n_s32(((128 << FILTER_BITS) + horiz_const) / 2);
const uint8x16_t range_limit = vdupq_n_u8(128);
const uint8_t *src_ptr = src;
@@ -334,15 +332,14 @@ static INLINE void dist_wtd_convolve_x_dist_wtd_avg_neon_dotprod(
// Dot-product constants and other shims.
const uint8x16_t range_limit = vdupq_n_u8(128);
- const int32_t correction_s32 =
- vaddlvq_s16(vshlq_n_s16(x_filter_s16, FILTER_BITS - 1));
// Fold round_offset into the dot-product filter correction constant. The
- // additional shim of 1 << ((ROUND0_BITS - 1) - 1) enables us to use non-
- // rounding shifts - which are generally faster than rounding shifts on
- // modern CPUs. (The extra -1 is needed because we halved the filter values.)
+ // additional shim of 1 << (ROUND0_BITS - 1) enables us to use non-rounding
+ // shifts - which are generally faster than rounding shifts on modern CPUs.
+ // Halve the total because we will halve the filter values.
int32x4_t correction =
- vdupq_n_s32(correction_s32 + (round_offset << (ROUND0_BITS - 1)) +
- (1 << ((ROUND0_BITS - 1) - 1)));
+ vdupq_n_s32(((128 << FILTER_BITS) + (round_offset << ROUND0_BITS) +
+ (1 << (ROUND0_BITS - 1))) /
+ 2);
const int horiz_offset = filter_params_x->taps / 2 - 1;
const uint8_t *src_ptr = src - horiz_offset;
@@ -455,15 +452,14 @@ static INLINE void dist_wtd_convolve_x_avg_neon_dotprod(
// Dot-product constants and other shims.
const uint8x16_t range_limit = vdupq_n_u8(128);
- const int32_t correction_s32 =
- vaddlvq_s16(vshlq_n_s16(x_filter_s16, FILTER_BITS - 1));
// Fold round_offset into the dot-product filter correction constant. The
- // additional shim of 1 << ((ROUND0_BITS - 1) - 1) enables us to use non-
- // rounding shifts - which are generally faster than rounding shifts on
- // modern CPUs. (The extra -1 is needed because we halved the filter values.)
+ // additional shim of 1 << (ROUND0_BITS - 1) enables us to use non-rounding
+ // shifts - which are generally faster than rounding shifts on modern CPUs.
+ // Halve the total because we will halve the filter values.
int32x4_t correction =
- vdupq_n_s32(correction_s32 + (round_offset << (ROUND0_BITS - 1)) +
- (1 << ((ROUND0_BITS - 1) - 1)));
+ vdupq_n_s32(((128 << FILTER_BITS) + (round_offset << ROUND0_BITS) +
+ (1 << (ROUND0_BITS - 1))) /
+ 2);
const int horiz_offset = filter_params_x->taps / 2 - 1;
const uint8_t *src_ptr = src - horiz_offset;
@@ -574,15 +570,14 @@ static INLINE void dist_wtd_convolve_x_neon_dotprod(
// Dot-product constants and other shims.
const uint8x16_t range_limit = vdupq_n_u8(128);
- const int32_t correction_s32 =
- vaddlvq_s16(vshlq_n_s16(x_filter_s16, FILTER_BITS - 1));
// Fold round_offset into the dot-product filter correction constant. The
- // additional shim of 1 << ((ROUND0_BITS - 1) - 1) enables us to use non-
- // rounding shifts - which are generally faster than rounding shifts on
- // modern CPUs. (The extra -1 is needed because we halved the filter values.)
+ // additional shim of 1 << (ROUND0_BITS - 1) enables us to use non-rounding
+ // shifts - which are generally faster than rounding shifts on modern CPUs.
+ // Halve the total because we will halve the vilter values.
int32x4_t correction =
- vdupq_n_s32(correction_s32 + (round_offset << (ROUND0_BITS - 1)) +
- (1 << ((ROUND0_BITS - 1) - 1)));
+ vdupq_n_s32(((128 << FILTER_BITS) + (round_offset << ROUND0_BITS) +
+ (1 << (ROUND0_BITS - 1))) /
+ 2);
const int horiz_offset = filter_params_x->taps / 2 - 1;
const uint8_t *src_ptr = src - horiz_offset;
diff --git a/third_party/aom/av1/common/arm/convolve_neon_dotprod.c b/third_party/aom/av1/common/arm/convolve_neon_dotprod.c
index c29229eb09..132da2442b 100644
--- a/third_party/aom/av1/common/arm/convolve_neon_dotprod.c
+++ b/third_party/aom/av1/common/arm/convolve_neon_dotprod.c
@@ -102,14 +102,12 @@ static INLINE void convolve_x_sr_12tap_neon_dotprod(
const int8x16_t filter =
vcombine_s8(vmovn_s16(filter_0_7), vmovn_s16(filter_8_15));
- const int32_t correction_s32 =
- vaddvq_s32(vaddq_s32(vpaddlq_s16(vshlq_n_s16(filter_0_7, FILTER_BITS)),
- vpaddlq_s16(vshlq_n_s16(filter_8_15, FILTER_BITS))));
- // A shim of 1 << (ROUND0_BITS - 1) enables us to use a single rounding right
- // shift by FILTER_BITS - instead of a first rounding right shift by
+ // Adding a shim of 1 << (ROUND0_BITS - 1) enables us to use a single rounding
+ // right shift by FILTER_BITS - instead of a first rounding right shift by
// ROUND0_BITS, followed by second rounding right shift by FILTER_BITS -
// ROUND0_BITS.
- int32x4_t correction = vdupq_n_s32(correction_s32 + (1 << (ROUND0_BITS - 1)));
+ int32x4_t correction =
+ vdupq_n_s32((128 << FILTER_BITS) + (1 << (ROUND0_BITS - 1)));
const uint8x16_t range_limit = vdupq_n_u8(128);
const uint8x16x3_t permute_tbl = vld1q_u8_x3(dot_prod_permute_tbl);
@@ -274,16 +272,13 @@ void av1_convolve_x_sr_neon_dotprod(const uint8_t *src, int src_stride,
}
const int16x8_t x_filter_s16 = vld1q_s16(x_filter_ptr);
- // Dot product constants.
- const int32_t correction_s32 =
- vaddlvq_s16(vshlq_n_s16(x_filter_s16, FILTER_BITS - 1));
- // This shim of (1 << ((ROUND0_BITS - 1) - 1) enables us to use a single
- // rounding right shift by FILTER_BITS - instead of a first rounding right
- // shift by ROUND0_BITS, followed by second rounding right shift by
- // FILTER_BITS - ROUND0_BITS.
- // The outermost -1 is needed because we will halve the filter values.
+ // Dot product constants:
+ // Adding a shim of 1 << (ROUND0_BITS - 1) enables us to use a single rounding
+ // right shift by FILTER_BITS - instead of a first rounding right shift by
+ // ROUND0_BITS, followed by second rounding right shift by FILTER_BITS -
+ // ROUND0_BITS. Halve the total because we will halve the filter values.
const int32x4_t correction =
- vdupq_n_s32(correction_s32 + (1 << ((ROUND0_BITS - 1) - 1)));
+ vdupq_n_s32(((128 << FILTER_BITS) + (1 << ((ROUND0_BITS - 1)))) / 2);
const uint8x16_t range_limit = vdupq_n_u8(128);
if (w <= 4) {
@@ -465,16 +460,13 @@ static INLINE void convolve_2d_sr_horiz_12tap_neon_dotprod(
const int8x16_t x_filter = vcombine_s8(vmovn_s16(x_filter_s16.val[0]),
vmovn_s16(x_filter_s16.val[1]));
- // This shim of 1 << (ROUND0_BITS - 1) enables us to use non-rounding shifts
- // - which are generally faster than rounding shifts on modern CPUs.
+ // Adding a shim of 1 << (ROUND0_BITS - 1) enables us to use non-rounding
+ // shifts - which are generally faster than rounding shifts on modern CPUs.
const int32_t horiz_const =
((1 << (bd + FILTER_BITS - 1)) + (1 << (ROUND0_BITS - 1)));
// Dot product constants.
- const int32x4_t correct_tmp =
- vaddq_s32(vpaddlq_s16(vshlq_n_s16(x_filter_s16.val[0], 7)),
- vpaddlq_s16(vshlq_n_s16(x_filter_s16.val[1], 7)));
const int32x4_t correction =
- vdupq_n_s32(vaddvq_s32(correct_tmp) + horiz_const);
+ vdupq_n_s32((128 << FILTER_BITS) + horiz_const);
const uint8x16_t range_limit = vdupq_n_u8(128);
const uint8x16x3_t permute_tbl = vld1q_u8_x3(dot_prod_permute_tbl);
@@ -621,16 +613,15 @@ static INLINE void convolve_2d_sr_horiz_neon_dotprod(
const uint8_t *src, int src_stride, int16_t *im_block, int im_stride, int w,
int im_h, const int16_t *x_filter_ptr) {
const int bd = 8;
- // This shim of 1 << ((ROUND0_BITS - 1) - 1) enables us to use non-rounding
- // shifts - which are generally faster than rounding shifts on modern CPUs.
- // The outermost -1 is needed because we halved the filter values.
- const int32_t horiz_const =
- ((1 << (bd + FILTER_BITS - 2)) + (1 << ((ROUND0_BITS - 1) - 1)));
// Dot product constants.
const int16x8_t x_filter_s16 = vld1q_s16(x_filter_ptr);
- const int32_t correction_s32 =
- vaddlvq_s16(vshlq_n_s16(x_filter_s16, FILTER_BITS - 1));
- const int32x4_t correction = vdupq_n_s32(correction_s32 + horiz_const);
+ // Adding a shim of 1 << (ROUND0_BITS - 1) enables us to use non-rounding
+ // shifts - which are generally faster than rounding shifts on modern CPUs.
+ const int32_t horiz_const =
+ ((1 << (bd + FILTER_BITS - 1)) + (1 << (ROUND0_BITS - 1)));
+ // Halve the total because we will halve the filter values.
+ const int32x4_t correction =
+ vdupq_n_s32(((128 << FILTER_BITS) + horiz_const) / 2);
const uint8x16_t range_limit = vdupq_n_u8(128);
const uint8_t *src_ptr = src;
diff --git a/third_party/aom/av1/common/av1_rtcd_defs.pl b/third_party/aom/av1/common/av1_rtcd_defs.pl
index c0831330d1..6a0043c761 100644
--- a/third_party/aom/av1/common/av1_rtcd_defs.pl
+++ b/third_party/aom/av1/common/av1_rtcd_defs.pl
@@ -458,7 +458,7 @@ if (aom_config("CONFIG_AV1_ENCODER") eq "yes") {
if (aom_config("CONFIG_REALTIME_ONLY") ne "yes") {
add_proto qw/void av1_compute_stats/, "int wiener_win, const uint8_t *dgd8, const uint8_t *src8, int16_t *dgd_avg, int16_t *src_avg, int h_start, int h_end, int v_start, int v_end, int dgd_stride, int src_stride, int64_t *M, int64_t *H, int use_downsampled_wiener_stats";
- specialize qw/av1_compute_stats sse4_1 avx2 neon/;
+ specialize qw/av1_compute_stats sse4_1 avx2 neon sve/;
add_proto qw/void av1_calc_proj_params/, "const uint8_t *src8, int width, int height, int src_stride, const uint8_t *dat8, int dat_stride, int32_t *flt0, int flt0_stride, int32_t *flt1, int flt1_stride, int64_t H[2][2], int64_t C[2], const sgr_params_type *params";
specialize qw/av1_calc_proj_params sse4_1 avx2 neon/;
add_proto qw/int64_t av1_lowbd_pixel_proj_error/, "const uint8_t *src8, int width, int height, int src_stride, const uint8_t *dat8, int dat_stride, int32_t *flt0, int flt0_stride, int32_t *flt1, int flt1_stride, int xq[2], const sgr_params_type *params";
@@ -469,7 +469,7 @@ if (aom_config("CONFIG_AV1_ENCODER") eq "yes") {
specialize qw/av1_calc_proj_params_high_bd sse4_1 avx2 neon/;
add_proto qw/int64_t av1_highbd_pixel_proj_error/, "const uint8_t *src8, int width, int height, int src_stride, const uint8_t *dat8, int dat_stride, int32_t *flt0, int flt0_stride, int32_t *flt1, int flt1_stride, int xq[2], const sgr_params_type *params";
specialize qw/av1_highbd_pixel_proj_error sse4_1 avx2 neon/;
- add_proto qw/void av1_compute_stats_highbd/, "int wiener_win, const uint8_t *dgd8, const uint8_t *src8, int h_start, int h_end, int v_start, int v_end, int dgd_stride, int src_stride, int64_t *M, int64_t *H, aom_bit_depth_t bit_depth";
+ add_proto qw/void av1_compute_stats_highbd/, "int wiener_win, const uint8_t *dgd8, const uint8_t *src8, int16_t *dgd_avg, int16_t *src_avg, int h_start, int h_end, int v_start, int v_end, int dgd_stride, int src_stride, int64_t *M, int64_t *H, aom_bit_depth_t bit_depth";
specialize qw/av1_compute_stats_highbd sse4_1 avx2 neon/;
}
}
@@ -554,6 +554,9 @@ if (aom_config("CONFIG_AV1_HIGHBITDEPTH") eq "yes") {
specialize qw/av1_highbd_warp_affine sse4_1 avx2 neon sve/;
}
+add_proto qw/bool resize_vert_dir/, "uint8_t *intbuf, uint8_t *output, int out_stride, int height, int height2, int width2, int start_col";
+specialize qw/resize_vert_dir avx2/;
+
add_proto qw/void av1_warp_affine/, "const int32_t *mat, const uint8_t *ref, int width, int height, int stride, uint8_t *pred, int p_col, int p_row, int p_width, int p_height, int p_stride, int subsampling_x, int subsampling_y, ConvolveParams *conv_params, int16_t alpha, int16_t beta, int16_t gamma, int16_t delta";
specialize qw/av1_warp_affine sse4_1 avx2 neon neon_i8mm sve/;
diff --git a/third_party/aom/av1/common/resize.c b/third_party/aom/av1/common/resize.c
index 441323ab1f..2b48b9fff4 100644
--- a/third_party/aom/av1/common/resize.c
+++ b/third_party/aom/av1/common/resize.c
@@ -18,6 +18,7 @@
#include <string.h>
#include "config/aom_config.h"
+#include "config/av1_rtcd.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_dsp/flow_estimation/corner_detect.h"
@@ -216,10 +217,6 @@ const int16_t av1_resize_filter_normative[(
// Filters for interpolation (full-band) - no filtering for integer pixels
#define filteredinterp_filters1000 av1_resize_filter_normative
-// Filters for factor of 2 downsampling.
-static const int16_t av1_down2_symeven_half_filter[] = { 56, 12, -3, -1 };
-static const int16_t av1_down2_symodd_half_filter[] = { 64, 35, 0, -3 };
-
static const InterpKernel *choose_interp_filter(int in_length, int out_length) {
int out_length16 = out_length * 16;
if (out_length16 >= in_length * 16)
@@ -524,6 +521,59 @@ static void fill_arr_to_col(uint8_t *img, int stride, int len, uint8_t *arr) {
}
}
+bool resize_vert_dir_c(uint8_t *intbuf, uint8_t *output, int out_stride,
+ int height, int height2, int width2, int start_col) {
+ bool mem_status = true;
+ uint8_t *arrbuf = (uint8_t *)aom_malloc(sizeof(*arrbuf) * height);
+ uint8_t *arrbuf2 = (uint8_t *)aom_malloc(sizeof(*arrbuf2) * height2);
+ if (arrbuf == NULL || arrbuf2 == NULL) {
+ mem_status = false;
+ goto Error;
+ }
+
+ for (int i = start_col; i < width2; ++i) {
+ fill_col_to_arr(intbuf + i, width2, height, arrbuf);
+ down2_symeven(arrbuf, height, arrbuf2);
+ fill_arr_to_col(output + i, out_stride, height2, arrbuf2);
+ }
+
+Error:
+ aom_free(arrbuf);
+ aom_free(arrbuf2);
+ return mem_status;
+}
+
+void resize_horz_dir(const uint8_t *const input, int in_stride, uint8_t *intbuf,
+ int height, int filtered_length, int width2) {
+ for (int i = 0; i < height; ++i)
+ down2_symeven(input + in_stride * i, filtered_length, intbuf + width2 * i);
+}
+
+bool av1_resize_plane_to_half(const uint8_t *const input, int height, int width,
+ int in_stride, uint8_t *output, int height2,
+ int width2, int out_stride) {
+ uint8_t *intbuf = (uint8_t *)aom_malloc(sizeof(*intbuf) * width2 * height);
+ if (intbuf == NULL) {
+ return false;
+ }
+
+ // Resize in the horizontal direction
+ resize_horz_dir(input, in_stride, intbuf, height, width, width2);
+ // Resize in the vertical direction
+ bool mem_status = resize_vert_dir(intbuf, output, out_stride, height, height2,
+ width2, 0 /*start_col*/);
+ aom_free(intbuf);
+ return mem_status;
+}
+
+// Check if both the output width and height are half of input width and
+// height respectively.
+bool should_resize_by_half(int height, int width, int height2, int width2) {
+ const bool is_width_by_2 = get_down2_length(width, 1) == width2;
+ const bool is_height_by_2 = get_down2_length(height, 1) == height2;
+ return (is_width_by_2 && is_height_by_2);
+}
+
bool av1_resize_plane(const uint8_t *input, int height, int width,
int in_stride, uint8_t *output, int height2, int width2,
int out_stride) {
diff --git a/third_party/aom/av1/common/resize.h b/third_party/aom/av1/common/resize.h
index d573a538bf..de71f5d539 100644
--- a/third_party/aom/av1/common/resize.h
+++ b/third_party/aom/av1/common/resize.h
@@ -20,6 +20,10 @@
extern "C" {
#endif
+// Filters for factor of 2 downsampling.
+static const int16_t av1_down2_symeven_half_filter[] = { 56, 12, -3, -1 };
+static const int16_t av1_down2_symodd_half_filter[] = { 64, 35, 0, -3 };
+
bool av1_resize_plane(const uint8_t *input, int height, int width,
int in_stride, uint8_t *output, int height2, int width2,
int out_stride);
@@ -93,6 +97,12 @@ void av1_calculate_unscaled_superres_size(int *width, int *height, int denom);
void av1_superres_upscale(AV1_COMMON *cm, BufferPool *const pool,
bool alloc_pyramid);
+bool av1_resize_plane_to_half(const uint8_t *const input, int height, int width,
+ int in_stride, uint8_t *output, int height2,
+ int width2, int out_stride);
+
+bool should_resize_by_half(int height, int width, int height2, int width2);
+
// Returns 1 if a superres upscaled frame is scaled and 0 otherwise.
static INLINE int av1_superres_scaled(const AV1_COMMON *cm) {
// Note: for some corner cases (e.g. cm->width of 1), there may be no scaling
diff --git a/third_party/aom/av1/common/x86/resize_avx2.c b/third_party/aom/av1/common/x86/resize_avx2.c
new file mode 100644
index 0000000000..c44edb88d9
--- /dev/null
+++ b/third_party/aom/av1/common/x86/resize_avx2.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2024, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+#include <immintrin.h>
+#include <string.h>
+
+#include "config/av1_rtcd.h"
+
+#include "av1/common/resize.h"
+
+#include "aom_dsp/x86/synonyms.h"
+
+#define CAST_HI(x) _mm256_castsi128_si256(x)
+#define CAST_LOW(x) _mm256_castsi256_si128(x)
+
+#define PROCESS_RESIZE_Y_WD16 \
+ const int idx1 = AOMMIN(height - 1, i + 5); \
+ const int idx2 = AOMMIN(height - 1, i + 6); \
+ l6 = l10; \
+ l7 = l11; \
+ l8 = _mm_loadu_si128((__m128i *)(data + idx1 * stride)); \
+ l9 = _mm_loadu_si128((__m128i *)(data + idx2 * stride)); \
+ \
+ /* g0... g15 | i0... i15 */ \
+ const __m256i s68 = \
+ _mm256_permute2x128_si256(CAST_HI(l6), CAST_HI(l8), 0x20); \
+ /* h0... h15 | j0... j15 */ \
+ const __m256i s79 = \
+ _mm256_permute2x128_si256(CAST_HI(l7), CAST_HI(l9), 0x20); \
+ \
+ /* g0h0... g7g7 | i0j0... i7j */ \
+ s[3] = _mm256_unpacklo_epi8(s68, s79); \
+ /* g8h8... g15g15 | i8j8... i15j15 */ \
+ s[8] = _mm256_unpackhi_epi8(s68, s79); \
+ \
+ __m256i res_out[2] = { 0 }; \
+ resize_y_convolve(s, coeffs_y, res_out); \
+ \
+ /* r00... r07 */ \
+ __m256i res_a_round_1 = _mm256_add_epi32(res_out[0], round_const_bits); \
+ /* r20... r27 */ \
+ __m256i res_a_round_2 = _mm256_add_epi32(res_out[1], round_const_bits); \
+ \
+ res_a_round_1 = _mm256_sra_epi32(res_a_round_1, round_shift_bits); \
+ res_a_round_2 = _mm256_sra_epi32(res_a_round_2, round_shift_bits); \
+ \
+ __m256i res_out_b[2] = { 0 }; \
+ resize_y_convolve(s + 5, coeffs_y, res_out_b); \
+ \
+ /* r08... r015 */ \
+ __m256i res_b_round_1 = _mm256_add_epi32(res_out_b[0], round_const_bits); \
+ /* r28... r215 */ \
+ __m256i res_b_round_2 = _mm256_add_epi32(res_out_b[1], round_const_bits); \
+ res_b_round_1 = _mm256_sra_epi32(res_b_round_1, round_shift_bits); \
+ res_b_round_2 = _mm256_sra_epi32(res_b_round_2, round_shift_bits); \
+ \
+ /* r00... r03 r20... r23 | r04... r07 r24... r27 */ \
+ __m256i res_8bit0 = _mm256_packus_epi32(res_a_round_1, res_a_round_2); \
+ /* r08... r012 r28... r212 | r013... r015 r213... r215 */ \
+ __m256i res_8bit1 = _mm256_packus_epi32(res_b_round_1, res_b_round_2); \
+ /* r00... r07 | r20... r27 */ \
+ res_8bit0 = _mm256_permute4x64_epi64(res_8bit0, 0xd8); \
+ /* r08... r015 | r28... r215 */ \
+ res_8bit1 = _mm256_permute4x64_epi64(res_8bit1, 0xd8); \
+ /* r00... r015 | r20... r215 */ \
+ res_8bit1 = _mm256_packus_epi16(res_8bit0, res_8bit1); \
+ res_8bit0 = _mm256_min_epu8(res_8bit1, clip_pixel); \
+ res_8bit0 = _mm256_max_epu8(res_8bit0, zero);
+
+#define PROCESS_RESIZE_Y_WD8 \
+ const int idx1 = AOMMIN(height - 1, i + 5); \
+ const int idx2 = AOMMIN(height - 1, i + 6); \
+ l6 = l10; \
+ l7 = l11; \
+ l8 = _mm_loadl_epi64((__m128i *)(data + idx1 * stride)); \
+ l9 = _mm_loadl_epi64((__m128i *)(data + idx2 * stride)); \
+ \
+ /* g0h0... g7h7 */ \
+ s67 = _mm_unpacklo_epi8(l6, l7); \
+ /* i0j0...i7j7 */ \
+ __m128i s89 = _mm_unpacklo_epi8(l8, l9); \
+ \
+ /* g0h0...g7g7 | i0j0...i7j7 */ \
+ s[3] = _mm256_permute2x128_si256(CAST_HI(s67), CAST_HI(s89), 0x20); \
+ \
+ __m256i res_out[2] = { 0 }; \
+ resize_y_convolve(s, coeffs_y, res_out); \
+ \
+ /* r00... r07 */ \
+ __m256i res_a_round_1 = _mm256_add_epi32(res_out[0], round_const_bits); \
+ /* r20...r27 */ \
+ __m256i res_a_round_2 = _mm256_add_epi32(res_out[1], round_const_bits); \
+ res_a_round_1 = _mm256_sra_epi32(res_a_round_1, round_shift_bits); \
+ res_a_round_2 = _mm256_sra_epi32(res_a_round_2, round_shift_bits); \
+ \
+ /* r00...r03 r20...r23 | r04...r07 r24...r27 */ \
+ res_a_round_1 = _mm256_packus_epi32(res_a_round_1, res_a_round_2); \
+ /* r00...r07 | r20...r27 */ \
+ res_a_round_1 = _mm256_permute4x64_epi64(res_a_round_1, 0xd8); \
+ res_a_round_1 = _mm256_packus_epi16(res_a_round_1, res_a_round_1); \
+ res_a_round_1 = _mm256_min_epu8(res_a_round_1, clip_pixel); \
+ res_a_round_1 = _mm256_max_epu8(res_a_round_1, zero);
+
+static INLINE void resize_y_convolve(const __m256i *const s,
+ const __m256i *const coeffs,
+ __m256i *res_out) {
+ const __m256i res_0 = _mm256_maddubs_epi16(s[0], coeffs[0]);
+ const __m256i res_1 = _mm256_maddubs_epi16(s[1], coeffs[1]);
+ const __m256i res_2 = _mm256_maddubs_epi16(s[2], coeffs[2]);
+ const __m256i res_3 = _mm256_maddubs_epi16(s[3], coeffs[3]);
+
+ const __m256i dst_0 = _mm256_add_epi16(res_0, res_1);
+ const __m256i dst_1 = _mm256_add_epi16(res_2, res_3);
+ // The sum of convolve operation crosses signed 16bit. Hence, the addition
+ // should happen in 32bit.
+ const __m256i dst_00 = _mm256_cvtepi16_epi32(CAST_LOW(dst_0));
+ const __m256i dst_01 =
+ _mm256_cvtepi16_epi32(_mm256_extracti128_si256(dst_0, 1));
+ const __m256i dst_10 = _mm256_cvtepi16_epi32(CAST_LOW(dst_1));
+ const __m256i dst_11 =
+ _mm256_cvtepi16_epi32(_mm256_extracti128_si256(dst_1, 1));
+
+ res_out[0] = _mm256_add_epi32(dst_00, dst_10);
+ res_out[1] = _mm256_add_epi32(dst_01, dst_11);
+}
+
+static INLINE void prepare_filter_coeffs(const int16_t *filter,
+ __m256i *const coeffs /* [4] */) {
+ // f0 f1 f2 f3 x x x x
+ const __m128i sym_even_filter = _mm_loadl_epi64((__m128i *)filter);
+ // f0 f1 f2 f3 f0 f1 f2 f3
+ const __m128i tmp0 = _mm_shuffle_epi32(sym_even_filter, 0x44);
+ // f0 f1 f2 f3 f1 f0 f3 f2
+ const __m128i tmp1 = _mm_shufflehi_epi16(tmp0, 0xb1);
+
+ const __m128i filter_8bit = _mm_packs_epi16(tmp1, tmp1);
+
+ // f0 f1 f0 f1 ..
+ coeffs[2] = _mm256_broadcastw_epi16(filter_8bit);
+ // f2 f3 f2 f3 ..
+ coeffs[3] = _mm256_broadcastw_epi16(_mm_bsrli_si128(filter_8bit, 2));
+ // f3 f2 f3 f2 ..
+ coeffs[0] = _mm256_broadcastw_epi16(_mm_bsrli_si128(filter_8bit, 6));
+ // f1 f0 f1 f0 ..
+ coeffs[1] = _mm256_broadcastw_epi16(_mm_bsrli_si128(filter_8bit, 4));
+}
+
+bool resize_vert_dir_avx2(uint8_t *intbuf, uint8_t *output, int out_stride,
+ int height, int height2, int stride, int start_col) {
+ assert(start_col <= stride);
+ // For the GM tool, the input layer height or width is assured to be an even
+ // number. Hence the function 'down2_symodd()' is not invoked and SIMD
+ // optimization of the same is not implemented.
+ // When the input height is less than 8 and even, the potential input
+ // heights are limited to 2, 4, or 6. These scenarios require seperate
+ // handling due to padding requirements. Invoking the C function here will
+ // eliminate the need for conditional statements within the subsequent SIMD
+ // code to manage these cases.
+ if (height & 1 || height < 8) {
+ return resize_vert_dir_c(intbuf, output, out_stride, height, height2,
+ stride, start_col);
+ }
+
+ __m256i s[10], coeffs_y[4];
+ const int bits = FILTER_BITS;
+
+ const __m128i round_shift_bits = _mm_cvtsi32_si128(bits);
+ const __m256i round_const_bits = _mm256_set1_epi32((1 << bits) >> 1);
+ const uint8_t max_pixel = 255;
+ const __m256i clip_pixel = _mm256_set1_epi8(max_pixel);
+ const __m256i zero = _mm256_setzero_si256();
+
+ prepare_filter_coeffs(av1_down2_symeven_half_filter, coeffs_y);
+
+ const int num_col16 = stride / 16;
+ int remain_col = stride % 16;
+ // The core vertical SIMD processes 4 input rows simultaneously to generate
+ // output corresponding to 2 rows. To streamline the core loop and eliminate
+ // the need for conditional checks, the remaining rows (4 or 6) are processed
+ // separately.
+ const int remain_row = (height % 4 == 0) ? 4 : 6;
+
+ for (int j = start_col; j < stride - remain_col; j += 16) {
+ const uint8_t *data = &intbuf[j];
+ const __m128i l3 = _mm_loadu_si128((__m128i *)(data + 0 * stride));
+ // Padding top 3 rows with the last available row at the top.
+ const __m128i l0 = l3;
+ const __m128i l1 = l3;
+ const __m128i l2 = l3;
+ const __m128i l4 = _mm_loadu_si128((__m128i *)(data + 1 * stride));
+
+ __m128i l6, l7, l8, l9;
+ __m128i l5 = _mm_loadu_si128((__m128i *)(data + 2 * stride));
+ __m128i l10 = _mm_loadu_si128((__m128i *)(data + 3 * stride));
+ __m128i l11 = _mm_loadu_si128((__m128i *)(data + 4 * stride));
+
+ // a0...a15 | c0...c15
+ const __m256i s02 =
+ _mm256_permute2x128_si256(CAST_HI(l0), CAST_HI(l2), 0x20);
+ // b0...b15 | d0...d15
+ const __m256i s13 =
+ _mm256_permute2x128_si256(CAST_HI(l1), CAST_HI(l3), 0x20);
+ // c0...c15 | e0...e15
+ const __m256i s24 =
+ _mm256_permute2x128_si256(CAST_HI(l2), CAST_HI(l4), 0x20);
+ // d0...d15 | f0...f15
+ const __m256i s35 =
+ _mm256_permute2x128_si256(CAST_HI(l3), CAST_HI(l5), 0x20);
+ // e0...e15 | g0...g15
+ const __m256i s46 =
+ _mm256_permute2x128_si256(CAST_HI(l4), CAST_HI(l10), 0x20);
+ // f0...f15 | h0...h15
+ const __m256i s57 =
+ _mm256_permute2x128_si256(CAST_HI(l5), CAST_HI(l11), 0x20);
+
+ // a0b0...a7b7 | c0d0...c7d7
+ s[0] = _mm256_unpacklo_epi8(s02, s13);
+ // c0d0...c7d7 | e0f0...e7f7
+ s[1] = _mm256_unpacklo_epi8(s24, s35);
+ // e0f0...e7f7 | g0h0...g7h7
+ s[2] = _mm256_unpacklo_epi8(s46, s57);
+
+ // a8b8...a15b15 | c8d8...c15d15
+ s[5] = _mm256_unpackhi_epi8(s02, s13);
+ // c8d8...c15d15 | e8f8...e15f15
+ s[6] = _mm256_unpackhi_epi8(s24, s35);
+ // e8f8...e15f15 | g8h8...g15h15
+ s[7] = _mm256_unpackhi_epi8(s46, s57);
+
+ // height to be processed here
+ const int process_ht = height - remain_row;
+ for (int i = 0; i < process_ht; i += 4) {
+ PROCESS_RESIZE_Y_WD16
+
+ _mm_storeu_si128((__m128i *)&output[(i / 2) * out_stride + j],
+ CAST_LOW(res_8bit0));
+
+ _mm_storeu_si128(
+ (__m128i *)&output[(i / 2) * out_stride + j + out_stride],
+ _mm256_extracti128_si256(res_8bit0, 1));
+
+ // Load the required data for processing of next 4 input rows.
+ const int idx7 = AOMMIN(height - 1, i + 7);
+ const int idx8 = AOMMIN(height - 1, i + 8);
+ l10 = _mm_loadu_si128((__m128i *)(data + idx7 * stride));
+ l11 = _mm_loadu_si128((__m128i *)(data + idx8 * stride));
+
+ const __m256i s810 =
+ _mm256_permute2x128_si256(CAST_HI(l8), CAST_HI(l10), 0x20);
+ const __m256i s911 =
+ _mm256_permute2x128_si256(CAST_HI(l9), CAST_HI(l11), 0x20);
+ // i0j0... i7j7 | k0l0... k7l7
+ s[4] = _mm256_unpacklo_epi8(s810, s911);
+ // i8j8... i15j15 | k8l8... k15l15
+ s[9] = _mm256_unpackhi_epi8(s810, s911);
+
+ s[0] = s[2];
+ s[1] = s[3];
+ s[2] = s[4];
+
+ s[5] = s[7];
+ s[6] = s[8];
+ s[7] = s[9];
+ }
+
+ // Process the remaining last 4 or 6 rows here.
+ int i = process_ht;
+ while (i < height - 1) {
+ PROCESS_RESIZE_Y_WD16
+
+ _mm_storeu_si128((__m128i *)&output[(i / 2) * out_stride + j],
+ CAST_LOW(res_8bit0));
+ i += 2;
+
+ const int is_store_valid = (i < height - 1);
+ if (is_store_valid)
+ _mm_storeu_si128((__m128i *)&output[(i / 2) * out_stride + j],
+ _mm256_extracti128_si256(res_8bit0, 1));
+ i += 2;
+
+ // Check if there is any remaining height to process. If so, perform the
+ // necessary data loading for processing the next row.
+ if (i < height - 1) {
+ l10 = l11 = l9;
+ const __m256i s810 =
+ _mm256_permute2x128_si256(CAST_HI(l8), CAST_HI(l10), 0x20);
+ const __m256i s911 =
+ _mm256_permute2x128_si256(CAST_HI(l9), CAST_HI(l11), 0x20);
+ // i0j0... i7j7 | k0l0... k7l7
+ s[4] = _mm256_unpacklo_epi8(s810, s911);
+ // i8j8... i15j15 | k8l8... k15l15
+ s[9] = _mm256_unpackhi_epi8(s810, s911);
+
+ s[0] = s[2];
+ s[1] = s[3];
+ s[2] = s[4];
+
+ s[5] = s[7];
+ s[6] = s[8];
+ s[7] = s[9];
+ }
+ }
+ }
+
+ if (remain_col > 7) {
+ const int processed_wd = num_col16 * 16;
+ remain_col = stride % 8;
+
+ const uint8_t *data = &intbuf[processed_wd];
+
+ const __m128i l3 = _mm_loadl_epi64((__m128i *)(data + 0 * stride));
+ // Padding top 3 rows with available top-most row.
+ const __m128i l0 = l3;
+ const __m128i l1 = l3;
+ const __m128i l2 = l3;
+ const __m128i l4 = _mm_loadl_epi64((__m128i *)(data + 1 * stride));
+
+ __m128i l6, l7, l8, l9;
+ __m128i l5 = _mm_loadl_epi64((__m128i *)(data + 2 * stride));
+ __m128i l10 = _mm_loadl_epi64((__m128i *)(data + 3 * stride));
+ __m128i l11 = _mm_loadl_epi64((__m128i *)(data + 4 * stride));
+
+ // a0b0...a7b7
+ const __m128i s01 = _mm_unpacklo_epi8(l0, l1);
+ // c0d0...c7d7
+ const __m128i s23 = _mm_unpacklo_epi8(l2, l3);
+ // e0f0...e7f7
+ const __m128i s45 = _mm_unpacklo_epi8(l4, l5);
+ // g0h0...g7h7
+ __m128i s67 = _mm_unpacklo_epi8(l10, l11);
+
+ // a0b0...a7b7 | c0d0...c7d7
+ s[0] = _mm256_permute2x128_si256(CAST_HI(s01), CAST_HI(s23), 0x20);
+ // c0d0...c7d7 | e0f0...e7f7
+ s[1] = _mm256_permute2x128_si256(CAST_HI(s23), CAST_HI(s45), 0x20);
+ // e0f0...e7f7 | g0h0...g7h7
+ s[2] = _mm256_permute2x128_si256(CAST_HI(s45), CAST_HI(s67), 0x20);
+
+ // height to be processed here
+ const int process_ht = height - remain_row;
+ for (int i = 0; i < process_ht; i += 4) {
+ PROCESS_RESIZE_Y_WD8
+
+ _mm_storel_epi64((__m128i *)&output[(i / 2) * out_stride + processed_wd],
+ CAST_LOW(res_a_round_1));
+
+ _mm_storel_epi64(
+ (__m128i *)&output[(i / 2) * out_stride + processed_wd + out_stride],
+ _mm256_extracti128_si256(res_a_round_1, 1));
+
+ const int idx7 = AOMMIN(height - 1, i + 7);
+ const int idx8 = AOMMIN(height - 1, i + 8);
+ l10 = _mm_loadl_epi64((__m128i *)(data + idx7 * stride));
+ l11 = _mm_loadl_epi64((__m128i *)(data + idx8 * stride));
+
+ // k0l0... k7l7
+ const __m128i s10s11 = _mm_unpacklo_epi8(l10, l11);
+ // i0j0... i7j7 | k0l0... k7l7
+ s[4] = _mm256_permute2x128_si256(CAST_HI(s89), CAST_HI(s10s11), 0x20);
+
+ s[0] = s[2];
+ s[1] = s[3];
+ s[2] = s[4];
+ }
+
+ // Process the remaining last 4 or 6 rows here.
+ int i = process_ht;
+ while (i < height - 1) {
+ PROCESS_RESIZE_Y_WD8
+
+ _mm_storel_epi64((__m128i *)&output[(i / 2) * out_stride + processed_wd],
+ CAST_LOW(res_a_round_1));
+
+ i += 2;
+
+ const int is_store_valid = (i < height - 1);
+ if (is_store_valid)
+ _mm_storel_epi64(
+ (__m128i *)&output[(i / 2) * out_stride + processed_wd],
+ _mm256_extracti128_si256(res_a_round_1, 1));
+ i += 2;
+
+ // Check rows are still remaining for processing. If yes do the required
+ // load of data for the next iteration.
+ if (i < height - 1) {
+ l10 = l11 = l9;
+ // k0l0... k7l7
+ const __m128i s10s11 = _mm_unpacklo_epi8(l10, l11);
+ // i0j0... i7j7 | k0l0... k7l7
+ s[4] = _mm256_permute2x128_si256(CAST_HI(s89), CAST_HI(s10s11), 0x20);
+
+ s[0] = s[2];
+ s[1] = s[3];
+ s[2] = s[4];
+ }
+ }
+ }
+
+ if (remain_col)
+ return resize_vert_dir_c(intbuf, output, out_stride, height, height2,
+ stride, stride - remain_col);
+
+ return true;
+}
diff --git a/third_party/aom/av1/encoder/arm/neon/highbd_pickrst_neon.c b/third_party/aom/av1/encoder/arm/neon/highbd_pickrst_neon.c
index 47b5f5cfb7..8b0d3bcc7e 100644
--- a/third_party/aom/av1/encoder/arm/neon/highbd_pickrst_neon.c
+++ b/third_party/aom/av1/encoder/arm/neon/highbd_pickrst_neon.c
@@ -1008,10 +1008,13 @@ static uint16_t highbd_find_average_neon(const uint16_t *src, int src_stride,
}
void av1_compute_stats_highbd_neon(int wiener_win, const uint8_t *dgd8,
- const uint8_t *src8, int h_start, int h_end,
+ const uint8_t *src8, int16_t *dgd_avg,
+ int16_t *src_avg, int h_start, int h_end,
int v_start, int v_end, int dgd_stride,
int src_stride, int64_t *M, int64_t *H,
aom_bit_depth_t bit_depth) {
+ (void)dgd_avg;
+ (void)src_avg;
assert(wiener_win == WIENER_WIN || wiener_win == WIENER_WIN_REDUCED);
const int wiener_halfwin = wiener_win >> 1;
diff --git a/third_party/aom/av1/encoder/arm/neon/pickrst_sve.c b/third_party/aom/av1/encoder/arm/neon/pickrst_sve.c
new file mode 100644
index 0000000000..a519ecc5f5
--- /dev/null
+++ b/third_party/aom/av1/encoder/arm/neon/pickrst_sve.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2024, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#include <arm_neon.h>
+#include <arm_sve.h>
+#include <string.h>
+
+#include "config/aom_config.h"
+#include "config/av1_rtcd.h"
+
+#include "aom_dsp/arm/aom_neon_sve_bridge.h"
+#include "aom_dsp/arm/mem_neon.h"
+#include "aom_dsp/arm/sum_neon.h"
+#include "aom_dsp/arm/transpose_neon.h"
+#include "av1/common/restoration.h"
+#include "av1/encoder/pickrst.h"
+
+static INLINE uint8_t find_average_sve(const uint8_t *src, int src_stride,
+ int width, int height) {
+ uint32x4_t avg_u32 = vdupq_n_u32(0);
+ uint8x16_t ones = vdupq_n_u8(1);
+
+ // Use a predicate to compute the last columns.
+ svbool_t pattern = svwhilelt_b8_u32(0, width % 16);
+
+ int h = height;
+ do {
+ int j = width;
+ const uint8_t *src_ptr = src;
+ while (j >= 16) {
+ uint8x16_t s = vld1q_u8(src_ptr);
+ avg_u32 = vdotq_u32(avg_u32, s, ones);
+
+ j -= 16;
+ src_ptr += 16;
+ }
+ uint8x16_t s_end = svget_neonq_u8(svld1_u8(pattern, src_ptr));
+ avg_u32 = vdotq_u32(avg_u32, s_end, ones);
+
+ src += src_stride;
+ } while (--h != 0);
+ return (uint8_t)(vaddlvq_u32(avg_u32) / (width * height));
+}
+
+static INLINE void compute_sub_avg(const uint8_t *buf, int buf_stride, int avg,
+ int16_t *buf_avg, int buf_avg_stride,
+ int width, int height,
+ int downsample_factor) {
+ uint8x8_t avg_u8 = vdup_n_u8(avg);
+
+ // Use a predicate to compute the last columns.
+ svbool_t pattern = svwhilelt_b8_u32(0, width % 8);
+
+ uint8x8_t avg_end = vget_low_u8(svget_neonq_u8(svdup_n_u8_z(pattern, avg)));
+
+ do {
+ int j = width;
+ const uint8_t *buf_ptr = buf;
+ int16_t *buf_avg_ptr = buf_avg;
+ while (j >= 8) {
+ uint8x8_t d = vld1_u8(buf_ptr);
+ vst1q_s16(buf_avg_ptr, vreinterpretq_s16_u16(vsubl_u8(d, avg_u8)));
+
+ j -= 8;
+ buf_ptr += 8;
+ buf_avg_ptr += 8;
+ }
+ uint8x8_t d_end = vget_low_u8(svget_neonq_u8(svld1_u8(pattern, buf_ptr)));
+ vst1q_s16(buf_avg_ptr, vreinterpretq_s16_u16(vsubl_u8(d_end, avg_end)));
+
+ buf += buf_stride;
+ buf_avg += buf_avg_stride;
+ height -= downsample_factor;
+ } while (height > 0);
+}
+
+static INLINE void copy_upper_triangle(int64_t *H, int64_t *H_tmp,
+ const int wiener_win2, const int scale) {
+ for (int i = 0; i < wiener_win2 - 2; i = i + 2) {
+ // Transpose the first 2x2 square. It needs a special case as the element
+ // of the bottom left is on the diagonal.
+ int64x2_t row0 = vld1q_s64(H_tmp + i * wiener_win2 + i + 1);
+ int64x2_t row1 = vld1q_s64(H_tmp + (i + 1) * wiener_win2 + i + 1);
+
+ int64x2_t tr_row = aom_vtrn2q_s64(row0, row1);
+
+ vst1_s64(H_tmp + (i + 1) * wiener_win2 + i, vget_low_s64(row0));
+ vst1q_s64(H_tmp + (i + 2) * wiener_win2 + i, tr_row);
+
+ // Transpose and store all the remaining 2x2 squares of the line.
+ for (int j = i + 3; j < wiener_win2; j = j + 2) {
+ row0 = vld1q_s64(H_tmp + i * wiener_win2 + j);
+ row1 = vld1q_s64(H_tmp + (i + 1) * wiener_win2 + j);
+
+ int64x2_t tr_row0 = aom_vtrn1q_s64(row0, row1);
+ int64x2_t tr_row1 = aom_vtrn2q_s64(row0, row1);
+
+ vst1q_s64(H_tmp + j * wiener_win2 + i, tr_row0);
+ vst1q_s64(H_tmp + (j + 1) * wiener_win2 + i, tr_row1);
+ }
+ }
+ for (int i = 0; i < wiener_win2 * wiener_win2; i++) {
+ H[i] += H_tmp[i] * scale;
+ }
+}
+
+// Transpose the matrix that has just been computed and accumulate it in M.
+static INLINE void acc_transpose_M(int64_t *M, const int64_t *M_trn,
+ const int wiener_win, int scale) {
+ for (int i = 0; i < wiener_win; ++i) {
+ for (int j = 0; j < wiener_win; ++j) {
+ int tr_idx = j * wiener_win + i;
+ *M++ += (int64_t)(M_trn[tr_idx] * scale);
+ }
+ }
+}
+
+// Swap each half of the dgd vectors so that we can accumulate the result of
+// the dot-products directly in the destination matrix.
+static INLINE int16x8x2_t transpose_dgd(int16x8_t dgd0, int16x8_t dgd1) {
+ int16x8_t dgd_trn0 = vreinterpretq_s16_s64(
+ vzip1q_s64(vreinterpretq_s64_s16(dgd0), vreinterpretq_s64_s16(dgd1)));
+ int16x8_t dgd_trn1 = vreinterpretq_s16_s64(
+ vzip2q_s64(vreinterpretq_s64_s16(dgd0), vreinterpretq_s64_s16(dgd1)));
+
+ return (struct int16x8x2_t){ dgd_trn0, dgd_trn1 };
+}
+
+static INLINE void compute_M_one_row_win5(int16x8_t src, int16x8_t dgd[5],
+ int64_t *M, int row) {
+ const int wiener_win = 5;
+
+ int64x2_t m01 = vld1q_s64(M + row * wiener_win + 0);
+ int16x8x2_t dgd01 = transpose_dgd(dgd[0], dgd[1]);
+
+ int64x2_t cross_corr01 = aom_svdot_lane_s16(m01, dgd01.val[0], src, 0);
+ cross_corr01 = aom_svdot_lane_s16(cross_corr01, dgd01.val[1], src, 1);
+ vst1q_s64(M + row * wiener_win + 0, cross_corr01);
+
+ int64x2_t m23 = vld1q_s64(M + row * wiener_win + 2);
+ int16x8x2_t dgd23 = transpose_dgd(dgd[2], dgd[3]);
+
+ int64x2_t cross_corr23 = aom_svdot_lane_s16(m23, dgd23.val[0], src, 0);
+ cross_corr23 = aom_svdot_lane_s16(cross_corr23, dgd23.val[1], src, 1);
+ vst1q_s64(M + row * wiener_win + 2, cross_corr23);
+
+ int64x2_t m4 = aom_sdotq_s16(vdupq_n_s64(0), src, dgd[4]);
+ M[row * wiener_win + 4] += vaddvq_s64(m4);
+}
+
+static INLINE void compute_M_one_row_win7(int16x8_t src, int16x8_t dgd[7],
+ int64_t *M, int row) {
+ const int wiener_win = 7;
+
+ int64x2_t m01 = vld1q_s64(M + row * wiener_win + 0);
+ int16x8x2_t dgd01 = transpose_dgd(dgd[0], dgd[1]);
+
+ int64x2_t cross_corr01 = aom_svdot_lane_s16(m01, dgd01.val[0], src, 0);
+ cross_corr01 = aom_svdot_lane_s16(cross_corr01, dgd01.val[1], src, 1);
+ vst1q_s64(M + row * wiener_win + 0, cross_corr01);
+
+ int64x2_t m23 = vld1q_s64(M + row * wiener_win + 2);
+ int16x8x2_t dgd23 = transpose_dgd(dgd[2], dgd[3]);
+
+ int64x2_t cross_corr23 = aom_svdot_lane_s16(m23, dgd23.val[0], src, 0);
+ cross_corr23 = aom_svdot_lane_s16(cross_corr23, dgd23.val[1], src, 1);
+ vst1q_s64(M + row * wiener_win + 2, cross_corr23);
+
+ int64x2_t m45 = vld1q_s64(M + row * wiener_win + 4);
+ int16x8x2_t dgd45 = transpose_dgd(dgd[4], dgd[5]);
+
+ int64x2_t cross_corr45 = aom_svdot_lane_s16(m45, dgd45.val[0], src, 0);
+ cross_corr45 = aom_svdot_lane_s16(cross_corr45, dgd45.val[1], src, 1);
+ vst1q_s64(M + row * wiener_win + 4, cross_corr45);
+
+ int64x2_t m6 = aom_sdotq_s16(vdupq_n_s64(0), src, dgd[6]);
+ M[row * wiener_win + 6] += vaddvq_s64(m6);
+}
+
+static INLINE void compute_H_one_col(int16x8_t *dgd, int col, int64_t *H,
+ const int wiener_win,
+ const int wiener_win2) {
+ for (int row0 = 0; row0 < wiener_win; row0++) {
+ for (int row1 = row0; row1 < wiener_win; row1++) {
+ int auto_cov_idx =
+ (col * wiener_win + row0) * wiener_win2 + (col * wiener_win) + row1;
+
+ int64x2_t auto_cov = aom_sdotq_s16(vdupq_n_s64(0), dgd[row0], dgd[row1]);
+ H[auto_cov_idx] += vaddvq_s64(auto_cov);
+ }
+ }
+}
+
+static INLINE void compute_H_two_rows_win5(int16x8_t *dgd0, int16x8_t *dgd1,
+ int row0, int row1, int64_t *H) {
+ for (int col0 = 0; col0 < 5; col0++) {
+ int auto_cov_idx = (row0 * 5 + col0) * 25 + (row1 * 5);
+
+ int64x2_t h01 = vld1q_s64(H + auto_cov_idx);
+ int16x8x2_t dgd01 = transpose_dgd(dgd1[0], dgd1[1]);
+
+ int64x2_t auto_cov01 = aom_svdot_lane_s16(h01, dgd01.val[0], dgd0[col0], 0);
+ auto_cov01 = aom_svdot_lane_s16(auto_cov01, dgd01.val[1], dgd0[col0], 1);
+ vst1q_s64(H + auto_cov_idx, auto_cov01);
+
+ int64x2_t h23 = vld1q_s64(H + auto_cov_idx + 2);
+ int16x8x2_t dgd23 = transpose_dgd(dgd1[2], dgd1[3]);
+
+ int64x2_t auto_cov23 = aom_svdot_lane_s16(h23, dgd23.val[0], dgd0[col0], 0);
+ auto_cov23 = aom_svdot_lane_s16(auto_cov23, dgd23.val[1], dgd0[col0], 1);
+ vst1q_s64(H + auto_cov_idx + 2, auto_cov23);
+
+ int64x2_t auto_cov4 = aom_sdotq_s16(vdupq_n_s64(0), dgd0[col0], dgd1[4]);
+ H[auto_cov_idx + 4] += vaddvq_s64(auto_cov4);
+ }
+}
+
+static INLINE void compute_H_two_rows_win7(int16x8_t *dgd0, int16x8_t *dgd1,
+ int row0, int row1, int64_t *H) {
+ for (int col0 = 0; col0 < 7; col0++) {
+ int auto_cov_idx = (row0 * 7 + col0) * 49 + (row1 * 7);
+
+ int64x2_t h01 = vld1q_s64(H + auto_cov_idx);
+ int16x8x2_t dgd01 = transpose_dgd(dgd1[0], dgd1[1]);
+
+ int64x2_t auto_cov01 = aom_svdot_lane_s16(h01, dgd01.val[0], dgd0[col0], 0);
+ auto_cov01 = aom_svdot_lane_s16(auto_cov01, dgd01.val[1], dgd0[col0], 1);
+ vst1q_s64(H + auto_cov_idx, auto_cov01);
+
+ int64x2_t h23 = vld1q_s64(H + auto_cov_idx + 2);
+ int16x8x2_t dgd23 = transpose_dgd(dgd1[2], dgd1[3]);
+
+ int64x2_t auto_cov23 = aom_svdot_lane_s16(h23, dgd23.val[0], dgd0[col0], 0);
+ auto_cov23 = aom_svdot_lane_s16(auto_cov23, dgd23.val[1], dgd0[col0], 1);
+ vst1q_s64(H + auto_cov_idx + 2, auto_cov23);
+
+ int64x2_t h45 = vld1q_s64(H + auto_cov_idx + 4);
+ int16x8x2_t dgd45 = transpose_dgd(dgd1[4], dgd1[5]);
+
+ int64x2_t auto_cov45 = aom_svdot_lane_s16(h45, dgd45.val[0], dgd0[col0], 0);
+ auto_cov45 = aom_svdot_lane_s16(auto_cov45, dgd45.val[1], dgd0[col0], 1);
+ vst1q_s64(H + auto_cov_idx + 4, auto_cov45);
+
+ int64x2_t auto_cov6 = aom_sdotq_s16(vdupq_n_s64(0), dgd0[col0], dgd1[6]);
+ H[auto_cov_idx + 6] += vaddvq_s64(auto_cov6);
+ }
+}
+
+// This function computes two matrices: the cross-correlation between the src
+// buffer and dgd buffer (M), and the auto-covariance of the dgd buffer (H).
+//
+// M is of size 7 * 7. It needs to be filled such that multiplying one element
+// from src with each element of a row of the wiener window will fill one
+// column of M. However this is not very convenient in terms of memory
+// accesses, as it means we do contiguous loads of dgd but strided stores to M.
+// As a result, we use an intermediate matrix M_trn which is instead filled
+// such that one row of the wiener window gives one row of M_trn. Once fully
+// computed, M_trn is then transposed to return M.
+//
+// H is of size 49 * 49. It is filled by multiplying every pair of elements of
+// the wiener window together. Since it is a symmetric matrix, we only compute
+// the upper triangle, and then copy it down to the lower one. Here we fill it
+// by taking each different pair of columns, and multiplying all the elements of
+// the first one with all the elements of the second one, with a special case
+// when multiplying a column by itself.
+static INLINE void compute_stats_win7_sve(int16_t *dgd_avg, int dgd_avg_stride,
+ int16_t *src_avg, int src_avg_stride,
+ int width, int height, int64_t *M,
+ int64_t *H, int downsample_factor) {
+ const int wiener_win = 7;
+ const int wiener_win2 = wiener_win * wiener_win;
+
+ // Use a predicate to compute the last columns of the block for H.
+ svbool_t pattern = svwhilelt_b16_u32(0, width % 8);
+
+ // Use intermediate matrices for H and M to perform the computation, they
+ // will be accumulated into the original H and M at the end.
+ int64_t M_trn[49];
+ memset(M_trn, 0, sizeof(M_trn));
+
+ int64_t H_tmp[49 * 49];
+ memset(H_tmp, 0, sizeof(H_tmp));
+
+ do {
+ // Cross-correlation (M).
+ for (int row = 0; row < wiener_win; row++) {
+ int j = 0;
+ while (j < width) {
+ int16x8_t dgd[7];
+ load_s16_8x7(dgd_avg + row * dgd_avg_stride + j, 1, &dgd[0], &dgd[1],
+ &dgd[2], &dgd[3], &dgd[4], &dgd[5], &dgd[6]);
+ int16x8_t s = vld1q_s16(src_avg + j);
+
+ // Compute all the elements of one row of M.
+ compute_M_one_row_win7(s, dgd, M_trn, row);
+
+ j += 8;
+ }
+ }
+
+ // Auto-covariance (H).
+ int j = 0;
+ while (j <= width - 8) {
+ for (int col0 = 0; col0 < wiener_win; col0++) {
+ int16x8_t dgd0[7];
+ load_s16_8x7(dgd_avg + j + col0, dgd_avg_stride, &dgd0[0], &dgd0[1],
+ &dgd0[2], &dgd0[3], &dgd0[4], &dgd0[5], &dgd0[6]);
+
+ // Perform computation of the first column with itself (28 elements).
+ // For the first column this will fill the upper triangle of the 7x7
+ // matrix at the top left of the H matrix. For the next columns this
+ // will fill the upper triangle of the other 7x7 matrices around H's
+ // diagonal.
+ compute_H_one_col(dgd0, col0, H_tmp, wiener_win, wiener_win2);
+
+ // All computation next to the matrix diagonal has already been done.
+ for (int col1 = col0 + 1; col1 < wiener_win; col1++) {
+ // Load second column and scale based on downsampling factor.
+ int16x8_t dgd1[7];
+ load_s16_8x7(dgd_avg + j + col1, dgd_avg_stride, &dgd1[0], &dgd1[1],
+ &dgd1[2], &dgd1[3], &dgd1[4], &dgd1[5], &dgd1[6]);
+
+ // Compute all elements from the combination of both columns (49
+ // elements).
+ compute_H_two_rows_win7(dgd0, dgd1, col0, col1, H_tmp);
+ }
+ }
+ j += 8;
+ }
+
+ if (j < width) {
+ // Process remaining columns using a predicate to discard excess elements.
+ for (int col0 = 0; col0 < wiener_win; col0++) {
+ // Load first column.
+ int16x8_t dgd0[7];
+ dgd0[0] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 0 * dgd_avg_stride + j + col0));
+ dgd0[1] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 1 * dgd_avg_stride + j + col0));
+ dgd0[2] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 2 * dgd_avg_stride + j + col0));
+ dgd0[3] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 3 * dgd_avg_stride + j + col0));
+ dgd0[4] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 4 * dgd_avg_stride + j + col0));
+ dgd0[5] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 5 * dgd_avg_stride + j + col0));
+ dgd0[6] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 6 * dgd_avg_stride + j + col0));
+
+ // Perform computation of the first column with itself (28 elements).
+ // For the first column this will fill the upper triangle of the 7x7
+ // matrix at the top left of the H matrix. For the next columns this
+ // will fill the upper triangle of the other 7x7 matrices around H's
+ // diagonal.
+ compute_H_one_col(dgd0, col0, H_tmp, wiener_win, wiener_win2);
+
+ // All computation next to the matrix diagonal has already been done.
+ for (int col1 = col0 + 1; col1 < wiener_win; col1++) {
+ // Load second column and scale based on downsampling factor.
+ int16x8_t dgd1[7];
+ load_s16_8x7(dgd_avg + j + col1, dgd_avg_stride, &dgd1[0], &dgd1[1],
+ &dgd1[2], &dgd1[3], &dgd1[4], &dgd1[5], &dgd1[6]);
+
+ // Compute all elements from the combination of both columns (49
+ // elements).
+ compute_H_two_rows_win7(dgd0, dgd1, col0, col1, H_tmp);
+ }
+ }
+ }
+ dgd_avg += downsample_factor * dgd_avg_stride;
+ src_avg += src_avg_stride;
+ } while (--height != 0);
+
+ // Transpose M_trn.
+ acc_transpose_M(M, M_trn, 7, downsample_factor);
+
+ // Copy upper triangle of H in the lower one.
+ copy_upper_triangle(H, H_tmp, wiener_win2, downsample_factor);
+}
+
+// This function computes two matrices: the cross-correlation between the src
+// buffer and dgd buffer (M), and the auto-covariance of the dgd buffer (H).
+//
+// M is of size 5 * 5. It needs to be filled such that multiplying one element
+// from src with each element of a row of the wiener window will fill one
+// column of M. However this is not very convenient in terms of memory
+// accesses, as it means we do contiguous loads of dgd but strided stores to M.
+// As a result, we use an intermediate matrix M_trn which is instead filled
+// such that one row of the wiener window gives one row of M_trn. Once fully
+// computed, M_trn is then transposed to return M.
+//
+// H is of size 25 * 25. It is filled by multiplying every pair of elements of
+// the wiener window together. Since it is a symmetric matrix, we only compute
+// the upper triangle, and then copy it down to the lower one. Here we fill it
+// by taking each different pair of columns, and multiplying all the elements of
+// the first one with all the elements of the second one, with a special case
+// when multiplying a column by itself.
+static INLINE void compute_stats_win5_sve(int16_t *dgd_avg, int dgd_avg_stride,
+ int16_t *src_avg, int src_avg_stride,
+ int width, int height, int64_t *M,
+ int64_t *H, int downsample_factor) {
+ const int wiener_win = 5;
+ const int wiener_win2 = wiener_win * wiener_win;
+
+ // Use a predicate to compute the last columns of the block for H.
+ svbool_t pattern = svwhilelt_b16_u32(0, width % 8);
+
+ // Use intermediate matrices for H and M to perform the computation, they
+ // will be accumulated into the original H and M at the end.
+ int64_t M_trn[25];
+ memset(M_trn, 0, sizeof(M_trn));
+
+ int64_t H_tmp[25 * 25];
+ memset(H_tmp, 0, sizeof(H_tmp));
+
+ do {
+ // Cross-correlation (M).
+ for (int row = 0; row < wiener_win; row++) {
+ int j = 0;
+ while (j < width) {
+ int16x8_t dgd[5];
+ load_s16_8x5(dgd_avg + row * dgd_avg_stride + j, 1, &dgd[0], &dgd[1],
+ &dgd[2], &dgd[3], &dgd[4]);
+ int16x8_t s = vld1q_s16(src_avg + j);
+
+ // Compute all the elements of one row of M.
+ compute_M_one_row_win5(s, dgd, M_trn, row);
+
+ j += 8;
+ }
+ }
+
+ // Auto-covariance (H).
+ int j = 0;
+ while (j <= width - 8) {
+ for (int col0 = 0; col0 < wiener_win; col0++) {
+ // Load first column.
+ int16x8_t dgd0[5];
+ load_s16_8x5(dgd_avg + j + col0, dgd_avg_stride, &dgd0[0], &dgd0[1],
+ &dgd0[2], &dgd0[3], &dgd0[4]);
+
+ // Perform computation of the first column with itself (15 elements).
+ // For the first column this will fill the upper triangle of the 5x5
+ // matrix at the top left of the H matrix. For the next columns this
+ // will fill the upper triangle of the other 5x5 matrices around H's
+ // diagonal.
+ compute_H_one_col(dgd0, col0, H_tmp, wiener_win, wiener_win2);
+
+ // All computation next to the matrix diagonal has already been done.
+ for (int col1 = col0 + 1; col1 < wiener_win; col1++) {
+ // Load second column and scale based on downsampling factor.
+ int16x8_t dgd1[5];
+ load_s16_8x5(dgd_avg + j + col1, dgd_avg_stride, &dgd1[0], &dgd1[1],
+ &dgd1[2], &dgd1[3], &dgd1[4]);
+
+ // Compute all elements from the combination of both columns (25
+ // elements).
+ compute_H_two_rows_win5(dgd0, dgd1, col0, col1, H_tmp);
+ }
+ }
+ j += 8;
+ }
+
+ // Process remaining columns using a predicate to discard excess elements.
+ if (j < width) {
+ for (int col0 = 0; col0 < wiener_win; col0++) {
+ int16x8_t dgd0[5];
+ dgd0[0] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 0 * dgd_avg_stride + j + col0));
+ dgd0[1] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 1 * dgd_avg_stride + j + col0));
+ dgd0[2] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 2 * dgd_avg_stride + j + col0));
+ dgd0[3] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 3 * dgd_avg_stride + j + col0));
+ dgd0[4] = svget_neonq_s16(
+ svld1_s16(pattern, dgd_avg + 4 * dgd_avg_stride + j + col0));
+
+ // Perform computation of the first column with itself (15 elements).
+ // For the first column this will fill the upper triangle of the 5x5
+ // matrix at the top left of the H matrix. For the next columns this
+ // will fill the upper triangle of the other 5x5 matrices around H's
+ // diagonal.
+ compute_H_one_col(dgd0, col0, H_tmp, wiener_win, wiener_win2);
+
+ // All computation next to the matrix diagonal has already been done.
+ for (int col1 = col0 + 1; col1 < wiener_win; col1++) {
+ // Load second column and scale based on downsampling factor.
+ int16x8_t dgd1[5];
+ load_s16_8x5(dgd_avg + j + col1, dgd_avg_stride, &dgd1[0], &dgd1[1],
+ &dgd1[2], &dgd1[3], &dgd1[4]);
+
+ // Compute all elements from the combination of both columns (25
+ // elements).
+ compute_H_two_rows_win5(dgd0, dgd1, col0, col1, H_tmp);
+ }
+ }
+ }
+ dgd_avg += downsample_factor * dgd_avg_stride;
+ src_avg += src_avg_stride;
+ } while (--height != 0);
+
+ // Transpose M_trn.
+ acc_transpose_M(M, M_trn, 5, downsample_factor);
+
+ // Copy upper triangle of H in the lower one.
+ copy_upper_triangle(H, H_tmp, wiener_win2, downsample_factor);
+}
+
+void av1_compute_stats_sve(int wiener_win, const uint8_t *dgd,
+ const uint8_t *src, int16_t *dgd_avg,
+ int16_t *src_avg, int h_start, int h_end,
+ int v_start, int v_end, int dgd_stride,
+ int src_stride, int64_t *M, int64_t *H,
+ int use_downsampled_wiener_stats) {
+ assert(wiener_win == WIENER_WIN || wiener_win == WIENER_WIN_CHROMA);
+
+ const int wiener_win2 = wiener_win * wiener_win;
+ const int wiener_halfwin = wiener_win >> 1;
+ const int32_t width = h_end - h_start;
+ const int32_t height = v_end - v_start;
+ const uint8_t *dgd_start = &dgd[v_start * dgd_stride + h_start];
+ memset(H, 0, sizeof(*H) * wiener_win2 * wiener_win2);
+ memset(M, 0, sizeof(*M) * wiener_win * wiener_win);
+
+ const uint8_t avg = find_average_sve(dgd_start, dgd_stride, width, height);
+ const int downsample_factor =
+ use_downsampled_wiener_stats ? WIENER_STATS_DOWNSAMPLE_FACTOR : 1;
+
+ // dgd_avg and src_avg have been memset to zero before calling this
+ // function, so round up the stride to the next multiple of 8 so that we
+ // don't have to worry about a tail loop when computing M.
+ const int dgd_avg_stride = ((width + 2 * wiener_halfwin) & ~7) + 8;
+ const int src_avg_stride = (width & ~7) + 8;
+
+ // Compute (dgd - avg) and store it in dgd_avg.
+ // The wiener window will slide along the dgd frame, centered on each pixel.
+ // For the top left pixel and all the pixels on the side of the frame this
+ // means half of the window will be outside of the frame. As such the actual
+ // buffer that we need to subtract the avg from will be 2 * wiener_halfwin
+ // wider and 2 * wiener_halfwin higher than the original dgd buffer.
+ const int vert_offset = v_start - wiener_halfwin;
+ const int horiz_offset = h_start - wiener_halfwin;
+ const uint8_t *dgd_win = dgd + horiz_offset + vert_offset * dgd_stride;
+ compute_sub_avg(dgd_win, dgd_stride, avg, dgd_avg, dgd_avg_stride,
+ width + 2 * wiener_halfwin, height + 2 * wiener_halfwin, 1);
+
+ // Compute (src - avg), downsample if necessary and store in src-avg.
+ const uint8_t *src_start = src + h_start + v_start * src_stride;
+ compute_sub_avg(src_start, src_stride * downsample_factor, avg, src_avg,
+ src_avg_stride, width, height, downsample_factor);
+
+ const int downsample_height = height / downsample_factor;
+
+ // Since the height is not necessarily a multiple of the downsample factor,
+ // the last line of src will be scaled according to how many rows remain.
+ const int downsample_remainder = height % downsample_factor;
+
+ if (wiener_win == WIENER_WIN) {
+ compute_stats_win7_sve(dgd_avg, dgd_avg_stride, src_avg, src_avg_stride,
+ width, downsample_height, M, H, downsample_factor);
+ } else {
+ compute_stats_win5_sve(dgd_avg, dgd_avg_stride, src_avg, src_avg_stride,
+ width, downsample_height, M, H, downsample_factor);
+ }
+
+ if (downsample_remainder > 0) {
+ const int remainder_offset = height - downsample_remainder;
+ if (wiener_win == WIENER_WIN) {
+ compute_stats_win7_sve(
+ dgd_avg + remainder_offset * dgd_avg_stride, dgd_avg_stride,
+ src_avg + downsample_height * src_avg_stride, src_avg_stride, width,
+ 1, M, H, downsample_remainder);
+ } else {
+ compute_stats_win5_sve(
+ dgd_avg + remainder_offset * dgd_avg_stride, dgd_avg_stride,
+ src_avg + downsample_height * src_avg_stride, src_avg_stride, width,
+ 1, M, H, downsample_remainder);
+ }
+ }
+}
diff --git a/third_party/aom/av1/encoder/enc_enums.h b/third_party/aom/av1/encoder/enc_enums.h
index 20cefa16a5..0a8b0f258a 100644
--- a/third_party/aom/av1/encoder/enc_enums.h
+++ b/third_party/aom/av1/encoder/enc_enums.h
@@ -12,10 +12,14 @@
#ifndef AOM_AV1_ENCODER_ENC_ENUMS_H_
#define AOM_AV1_ENCODER_ENC_ENUMS_H_
+#include "aom_ports/mem.h"
+
#ifdef __cplusplus
extern "C" {
#endif
+#define MAX_NUM_THREADS 64
+
// This enumerator type needs to be kept aligned with the mode order in
// const MODE_DEFINITION av1_mode_defs[MAX_MODES] used in the rd code.
enum {
diff --git a/third_party/aom/av1/encoder/encodeframe.c b/third_party/aom/av1/encoder/encodeframe.c
index a9214f77c2..07382eb6cc 100644
--- a/third_party/aom/av1/encoder/encodeframe.c
+++ b/third_party/aom/av1/encoder/encodeframe.c
@@ -537,7 +537,9 @@ static AOM_INLINE void encode_nonrd_sb(AV1_COMP *cpi, ThreadData *td,
// Set the partition
if (sf->part_sf.partition_search_type == FIXED_PARTITION || seg_skip ||
(sf->rt_sf.use_fast_fixed_part && x->sb_force_fixed_part == 1 &&
- !frame_is_intra_only(cm))) {
+ (!frame_is_intra_only(cm) &&
+ (!cpi->ppi->use_svc ||
+ !cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)))) {
// set a fixed-size partition
av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
BLOCK_SIZE bsize_select = sf->part_sf.fixed_partition_size;
diff --git a/third_party/aom/av1/encoder/encoder.h b/third_party/aom/av1/encoder/encoder.h
index 4de5d426ce..a919bd906a 100644
--- a/third_party/aom/av1/encoder/encoder.h
+++ b/third_party/aom/av1/encoder/encoder.h
@@ -37,6 +37,7 @@
#include "av1/encoder/av1_quantize.h"
#include "av1/encoder/block.h"
#include "av1/encoder/context_tree.h"
+#include "av1/encoder/enc_enums.h"
#include "av1/encoder/encodemb.h"
#include "av1/encoder/external_partition.h"
#include "av1/encoder/firstpass.h"
@@ -74,7 +75,6 @@
#endif
#include "aom/internal/aom_codec_internal.h"
-#include "aom_util/aom_thread.h"
#ifdef __cplusplus
extern "C" {
diff --git a/third_party/aom/av1/encoder/ethread.c b/third_party/aom/av1/encoder/ethread.c
index 755535ba51..1d0092a5ed 100644
--- a/third_party/aom/av1/encoder/ethread.c
+++ b/third_party/aom/av1/encoder/ethread.c
@@ -19,6 +19,7 @@
#include "av1/encoder/allintra_vis.h"
#include "av1/encoder/bitstream.h"
+#include "av1/encoder/enc_enums.h"
#include "av1/encoder/encodeframe.h"
#include "av1/encoder/encodeframe_utils.h"
#include "av1/encoder/encoder.h"
@@ -2520,7 +2521,7 @@ void av1_tf_do_filtering_mt(AV1_COMP *cpi) {
static AOM_INLINE int get_next_gm_job(AV1_COMP *cpi, int *frame_idx,
int cur_dir) {
GlobalMotionInfo *gm_info = &cpi->gm_info;
- JobInfo *job_info = &cpi->mt_info.gm_sync.job_info;
+ GlobalMotionJobInfo *job_info = &cpi->mt_info.gm_sync.job_info;
int total_refs = gm_info->num_ref_frames[cur_dir];
int8_t cur_frame_to_process = job_info->next_frame_to_process[cur_dir];
@@ -2551,7 +2552,7 @@ static int gm_mt_worker_hook(void *arg1, void *unused) {
AV1_COMP *cpi = thread_data->cpi;
GlobalMotionInfo *gm_info = &cpi->gm_info;
AV1GlobalMotionSync *gm_sync = &cpi->mt_info.gm_sync;
- JobInfo *job_info = &gm_sync->job_info;
+ GlobalMotionJobInfo *job_info = &gm_sync->job_info;
int thread_id = thread_data->thread_id;
GlobalMotionData *gm_thread_data = &thread_data->td->gm_data;
#if CONFIG_MULTITHREAD
@@ -2689,7 +2690,7 @@ static AOM_INLINE void gm_dealloc_thread_data(AV1_COMP *cpi, int num_workers) {
// Implements multi-threading for global motion.
void av1_global_motion_estimation_mt(AV1_COMP *cpi) {
- JobInfo *job_info = &cpi->mt_info.gm_sync.job_info;
+ GlobalMotionJobInfo *job_info = &cpi->mt_info.gm_sync.job_info;
av1_zero(*job_info);
diff --git a/third_party/aom/av1/encoder/global_motion.h b/third_party/aom/av1/encoder/global_motion.h
index de46a0e1f2..2645f93e3c 100644
--- a/third_party/aom/av1/encoder/global_motion.h
+++ b/third_party/aom/av1/encoder/global_motion.h
@@ -14,9 +14,8 @@
#include "aom/aom_integer.h"
#include "aom_dsp/flow_estimation/flow_estimation.h"
-#include "aom_scale/yv12config.h"
#include "aom_util/aom_pthread.h"
-#include "aom_util/aom_thread.h"
+#include "av1/encoder/enc_enums.h"
#ifdef __cplusplus
extern "C" {
@@ -58,11 +57,11 @@ typedef struct {
// next_frame_to_process[i] will hold the count of next reference frame to be
// processed in the direction 'i'.
int8_t next_frame_to_process[MAX_DIRECTIONS];
-} JobInfo;
+} GlobalMotionJobInfo;
typedef struct {
// Data related to assigning jobs for global motion multi-threading.
- JobInfo job_info;
+ GlobalMotionJobInfo job_info;
#if CONFIG_MULTITHREAD
// Mutex lock used while dispatching jobs.
diff --git a/third_party/aom/av1/encoder/nonrd_pickmode.c b/third_party/aom/av1/encoder/nonrd_pickmode.c
index 57c74f66d5..08ecb8495a 100644
--- a/third_party/aom/av1/encoder/nonrd_pickmode.c
+++ b/third_party/aom/av1/encoder/nonrd_pickmode.c
@@ -1886,14 +1886,17 @@ static AOM_INLINE int skip_mode_by_low_temp(
static AOM_INLINE int skip_mode_by_bsize_and_ref_frame(
PREDICTION_MODE mode, MV_REFERENCE_FRAME ref_frame, BLOCK_SIZE bsize,
- int extra_prune, unsigned int sse_zeromv_norm, int more_prune) {
+ int extra_prune, unsigned int sse_zeromv_norm, int more_prune,
+ int skip_nearmv) {
const unsigned int thresh_skip_golden = 500;
if (ref_frame != LAST_FRAME && sse_zeromv_norm < thresh_skip_golden &&
mode == NEWMV)
return 1;
- if (bsize == BLOCK_128X128 && mode == NEWMV) return 1;
+ if ((bsize == BLOCK_128X128 && mode == NEWMV) ||
+ (skip_nearmv && mode == NEARMV))
+ return 1;
// Skip testing non-LAST if this flag is set.
if (extra_prune) {
@@ -2361,6 +2364,18 @@ static AOM_FORCE_INLINE bool skip_inter_mode_nonrd(
(*this_mode != GLOBALMV || *ref_frame != LAST_FRAME))
return true;
+ // Skip the mode if use reference frame mask flag is not set.
+ if (!search_state->use_ref_frame_mask[*ref_frame]) return true;
+
+ // Skip mode for some modes and reference frames when
+ // force_zeromv_skip_for_blk flag is true.
+ if (x->force_zeromv_skip_for_blk &&
+ ((!(*this_mode == NEARESTMV &&
+ search_state->frame_mv[*this_mode][*ref_frame].as_int == 0) &&
+ *this_mode != GLOBALMV) ||
+ *ref_frame != LAST_FRAME))
+ return true;
+
if (x->sb_me_block && *ref_frame == LAST_FRAME) {
// We want to make sure to test the superblock MV:
// so don't skip (return false) for NEAREST_LAST or NEAR_LAST if they
@@ -2400,18 +2415,6 @@ static AOM_FORCE_INLINE bool skip_inter_mode_nonrd(
mi->ref_frame[0] = *ref_frame;
mi->ref_frame[1] = *ref_frame2;
- // Skip the mode if use reference frame mask flag is not set.
- if (!search_state->use_ref_frame_mask[*ref_frame]) return true;
-
- // Skip mode for some modes and reference frames when
- // force_zeromv_skip_for_blk flag is true.
- if (x->force_zeromv_skip_for_blk &&
- ((!(*this_mode == NEARESTMV &&
- search_state->frame_mv[*this_mode][*ref_frame].as_int == 0) &&
- *this_mode != GLOBALMV) ||
- *ref_frame != LAST_FRAME))
- return true;
-
// Skip compound mode based on variance of previously evaluated single
// reference modes.
if (rt_sf->prune_compoundmode_with_singlemode_var && !*is_single_pred &&
@@ -2478,7 +2481,8 @@ static AOM_FORCE_INLINE bool skip_inter_mode_nonrd(
// properties.
if (skip_mode_by_bsize_and_ref_frame(
*this_mode, *ref_frame, bsize, x->nonrd_prune_ref_frame_search,
- sse_zeromv_norm, rt_sf->nonrd_aggressive_skip))
+ sse_zeromv_norm, rt_sf->nonrd_aggressive_skip,
+ rt_sf->increase_source_sad_thresh))
return true;
// Skip mode based on low temporal variance and souce sad.
diff --git a/third_party/aom/av1/encoder/partition_search.c b/third_party/aom/av1/encoder/partition_search.c
index 61d49a23f2..30ea7d9140 100644
--- a/third_party/aom/av1/encoder/partition_search.c
+++ b/third_party/aom/av1/encoder/partition_search.c
@@ -2323,8 +2323,9 @@ static void pick_sb_modes_nonrd(AV1_COMP *const cpi, TileDataEnc *tile_data,
}
if (cpi->sf.rt_sf.skip_cdef_sb) {
// cdef_strength is initialized to 1 which means skip_cdef, and is updated
- // here. Check to see is skipping cdef is allowed.
- // Always allow cdef_skip for seg_skip = 1.
+ // here. Check to see is skipping cdef is allowed. Never skip on slide/scene
+ // change, near a key frame, or when color sensitivity is set. Always allow
+ // cdef_skip for seg_skip = 1.
const int allow_cdef_skipping =
seg_skip ||
(cpi->rc.frames_since_key > 10 && !cpi->rc.high_source_sad &&
@@ -2338,8 +2339,16 @@ static void pick_sb_modes_nonrd(AV1_COMP *const cpi, TileDataEnc *tile_data,
MB_MODE_INFO **mi_sb =
cm->mi_params.mi_grid_base +
get_mi_grid_idx(&cm->mi_params, mi_row_sb, mi_col_sb);
- // Do not skip if intra or new mv is picked, or color sensitivity is set.
- // Never skip on slide/scene change.
+ const int is_720p_or_larger = AOMMIN(cm->width, cm->height) >= 720;
+ unsigned int thresh_spatial_var =
+ (cpi->oxcf.speed >= 11 && !is_720p_or_larger &&
+ cpi->oxcf.tune_cfg.content != AOM_CONTENT_SCREEN)
+ ? 400
+ : UINT_MAX;
+ // For skip_cdef_sb = 1: do not skip if allow_cdef_skipping is false or
+ // intra or new mv is picked, with possible conidition on spatial variance.
+ // For skip_cdef_sb >= 2: more aggressive mode to always skip unless
+ // allow_cdef_skipping is false and source_variance is non-zero.
if (cpi->sf.rt_sf.skip_cdef_sb >= 2) {
mi_sb[0]->cdef_strength =
mi_sb[0]->cdef_strength &&
@@ -2347,7 +2356,8 @@ static void pick_sb_modes_nonrd(AV1_COMP *const cpi, TileDataEnc *tile_data,
} else {
mi_sb[0]->cdef_strength =
mi_sb[0]->cdef_strength && allow_cdef_skipping &&
- !(mbmi->mode < INTRA_MODES || mbmi->mode == NEWMV);
+ !(x->source_variance < thresh_spatial_var &&
+ (mbmi->mode < INTRA_MODES || mbmi->mode == NEWMV));
}
// Store in the pickmode context.
ctx->mic.cdef_strength = mi_sb[0]->cdef_strength;
diff --git a/third_party/aom/av1/encoder/picklpf.c b/third_party/aom/av1/encoder/picklpf.c
index a504535028..ce0357163d 100644
--- a/third_party/aom/av1/encoder/picklpf.c
+++ b/third_party/aom/av1/encoder/picklpf.c
@@ -257,6 +257,8 @@ void av1_pick_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
inter_frame_multiplier = inter_frame_multiplier << 1;
else if (cpi->rc.frame_source_sad > 50000)
inter_frame_multiplier = 3 * (inter_frame_multiplier >> 1);
+ } else if (cpi->sf.rt_sf.use_fast_fixed_part) {
+ inter_frame_multiplier = inter_frame_multiplier << 1;
}
// These values were determined by linear fitting the result of the
// searched level for 8 bit depth:
diff --git a/third_party/aom/av1/encoder/pickrst.c b/third_party/aom/av1/encoder/pickrst.c
index b0d0d0bb78..a431c4dada 100644
--- a/third_party/aom/av1/encoder/pickrst.c
+++ b/third_party/aom/av1/encoder/pickrst.c
@@ -1044,10 +1044,13 @@ void av1_compute_stats_c(int wiener_win, const uint8_t *dgd, const uint8_t *src,
#if CONFIG_AV1_HIGHBITDEPTH
void av1_compute_stats_highbd_c(int wiener_win, const uint8_t *dgd8,
- const uint8_t *src8, int h_start, int h_end,
+ const uint8_t *src8, int16_t *dgd_avg,
+ int16_t *src_avg, int h_start, int h_end,
int v_start, int v_end, int dgd_stride,
int src_stride, int64_t *M, int64_t *H,
aom_bit_depth_t bit_depth) {
+ (void)dgd_avg;
+ (void)src_avg;
int i, j, k, l;
int32_t Y[WIENER_WIN2];
const int wiener_win2 = wiener_win * wiener_win;
@@ -1659,9 +1662,10 @@ static AOM_INLINE void search_wiener(
// functions. Optimize intrinsics of HBD design similar to LBD (i.e.,
// pre-calculate d and s buffers and avoid most of the C operations).
av1_compute_stats_highbd(reduced_wiener_win, rsc->dgd_buffer,
- rsc->src_buffer, limits->h_start, limits->h_end,
- limits->v_start, limits->v_end, rsc->dgd_stride,
- rsc->src_stride, M, H, cm->seq_params->bit_depth);
+ rsc->src_buffer, rsc->dgd_avg, rsc->src_avg,
+ limits->h_start, limits->h_end, limits->v_start,
+ limits->v_end, rsc->dgd_stride, rsc->src_stride, M,
+ H, cm->seq_params->bit_depth);
} else {
av1_compute_stats(reduced_wiener_win, rsc->dgd_buffer, rsc->src_buffer,
rsc->dgd_avg, rsc->src_avg, limits->h_start,
@@ -2081,10 +2085,9 @@ void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi) {
// and height aligned to multiple of 16 is considered for intrinsic purpose.
rsc.dgd_avg = NULL;
rsc.src_avg = NULL;
-#if HAVE_AVX2 || HAVE_NEON
- // The buffers allocated below are used during Wiener filter processing of low
- // bitdepth path. Hence, allocate the same when Wiener filter is enabled in
- // low bitdepth path.
+#if HAVE_AVX2
+ // The buffers allocated below are used during Wiener filter processing.
+ // Hence, allocate the same when Wiener filter is enabled.
if (!cpi->sf.lpf_sf.disable_wiener_filter && !highbd) {
const int buf_size = sizeof(*cpi->pick_lr_ctxt.dgd_avg) * 6 *
RESTORATION_UNITSIZE_MAX * RESTORATION_UNITSIZE_MAX;
@@ -2221,7 +2224,7 @@ void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi) {
best_luma_unit_size);
}
-#if HAVE_AVX || HAVE_NEON
+#if HAVE_AVX2
if (!cpi->sf.lpf_sf.disable_wiener_filter && !highbd) {
aom_free(cpi->pick_lr_ctxt.dgd_avg);
cpi->pick_lr_ctxt.dgd_avg = NULL;
diff --git a/third_party/aom/av1/encoder/speed_features.c b/third_party/aom/av1/encoder/speed_features.c
index 256b6fc9eb..9a00042520 100644
--- a/third_party/aom/av1/encoder/speed_features.c
+++ b/third_party/aom/av1/encoder/speed_features.c
@@ -1461,7 +1461,7 @@ static void set_rt_speed_feature_framesize_dependent(const AV1_COMP *const cpi,
// for resolutions below 720p.
if (speed >= 11 && !is_720p_or_larger &&
cpi->oxcf.tune_cfg.content != AOM_CONTENT_SCREEN) {
- sf->rt_sf.skip_cdef_sb = 2;
+ sf->rt_sf.skip_cdef_sb = 1;
sf->rt_sf.force_only_last_ref = 1;
sf->rt_sf.selective_cdf_update = 1;
sf->rt_sf.use_nonrd_filter_search = 0;
diff --git a/third_party/aom/av1/encoder/tune_vmaf.c b/third_party/aom/av1/encoder/tune_vmaf.c
index 91db3db726..fdb7c77ebc 100644
--- a/third_party/aom/av1/encoder/tune_vmaf.c
+++ b/third_party/aom/av1/encoder/tune_vmaf.c
@@ -247,7 +247,9 @@ static AOM_INLINE void unsharp(const AV1_COMP *const cpi,
// 8-tap Gaussian convolution filter with sigma = 1.0, sums to 128,
// all co-efficients must be even.
-DECLARE_ALIGNED(16, static const int16_t, gauss_filter[8]) = { 0, 8, 30, 52,
+// The array is of size 9 to allow passing gauss_filter + 1 to
+// _mm_loadu_si128() in prepare_coeffs_6t().
+DECLARE_ALIGNED(16, static const int16_t, gauss_filter[9]) = { 0, 8, 30, 52,
30, 8, 0, 0 };
static AOM_INLINE void gaussian_blur(const int bit_depth,
const YV12_BUFFER_CONFIG *source,
diff --git a/third_party/aom/av1/encoder/x86/pickrst_avx2.c b/third_party/aom/av1/encoder/x86/pickrst_avx2.c
index 6658ed39a8..1f76576c9e 100644
--- a/third_party/aom/av1/encoder/x86/pickrst_avx2.c
+++ b/third_party/aom/av1/encoder/x86/pickrst_avx2.c
@@ -345,21 +345,27 @@ static INLINE void compute_stats_highbd_win5_opt_avx2(
}
void av1_compute_stats_highbd_avx2(int wiener_win, const uint8_t *dgd8,
- const uint8_t *src8, int h_start, int h_end,
+ const uint8_t *src8, int16_t *dgd_avg,
+ int16_t *src_avg, int h_start, int h_end,
int v_start, int v_end, int dgd_stride,
int src_stride, int64_t *M, int64_t *H,
aom_bit_depth_t bit_depth) {
if (wiener_win == WIENER_WIN) {
+ (void)dgd_avg;
+ (void)src_avg;
compute_stats_highbd_win7_opt_avx2(dgd8, src8, h_start, h_end, v_start,
v_end, dgd_stride, src_stride, M, H,
bit_depth);
} else if (wiener_win == WIENER_WIN_CHROMA) {
+ (void)dgd_avg;
+ (void)src_avg;
compute_stats_highbd_win5_opt_avx2(dgd8, src8, h_start, h_end, v_start,
v_end, dgd_stride, src_stride, M, H,
bit_depth);
} else {
- av1_compute_stats_highbd_c(wiener_win, dgd8, src8, h_start, h_end, v_start,
- v_end, dgd_stride, src_stride, M, H, bit_depth);
+ av1_compute_stats_highbd_c(wiener_win, dgd8, src8, dgd_avg, src_avg,
+ h_start, h_end, v_start, v_end, dgd_stride,
+ src_stride, M, H, bit_depth);
}
}
#endif // CONFIG_AV1_HIGHBITDEPTH
diff --git a/third_party/aom/av1/encoder/x86/pickrst_sse4.c b/third_party/aom/av1/encoder/x86/pickrst_sse4.c
index 50db305802..3617d33fef 100644
--- a/third_party/aom/av1/encoder/x86/pickrst_sse4.c
+++ b/third_party/aom/av1/encoder/x86/pickrst_sse4.c
@@ -524,21 +524,27 @@ static INLINE void compute_stats_highbd_win5_opt_sse4_1(
}
void av1_compute_stats_highbd_sse4_1(int wiener_win, const uint8_t *dgd8,
- const uint8_t *src8, int h_start,
- int h_end, int v_start, int v_end,
- int dgd_stride, int src_stride, int64_t *M,
- int64_t *H, aom_bit_depth_t bit_depth) {
+ const uint8_t *src8, int16_t *dgd_avg,
+ int16_t *src_avg, int h_start, int h_end,
+ int v_start, int v_end, int dgd_stride,
+ int src_stride, int64_t *M, int64_t *H,
+ aom_bit_depth_t bit_depth) {
if (wiener_win == WIENER_WIN) {
+ (void)dgd_avg;
+ (void)src_avg;
compute_stats_highbd_win7_opt_sse4_1(dgd8, src8, h_start, h_end, v_start,
v_end, dgd_stride, src_stride, M, H,
bit_depth);
} else if (wiener_win == WIENER_WIN_CHROMA) {
+ (void)dgd_avg;
+ (void)src_avg;
compute_stats_highbd_win5_opt_sse4_1(dgd8, src8, h_start, h_end, v_start,
v_end, dgd_stride, src_stride, M, H,
bit_depth);
} else {
- av1_compute_stats_highbd_c(wiener_win, dgd8, src8, h_start, h_end, v_start,
- v_end, dgd_stride, src_stride, M, H, bit_depth);
+ av1_compute_stats_highbd_c(wiener_win, dgd8, src8, dgd_avg, src_avg,
+ h_start, h_end, v_start, v_end, dgd_stride,
+ src_stride, M, H, bit_depth);
}
}
#endif // CONFIG_AV1_HIGHBITDEPTH
diff --git a/third_party/aom/test/aom_image_test.cc b/third_party/aom/test/aom_image_test.cc
index 03f4373f35..0dfb912215 100644
--- a/third_party/aom/test/aom_image_test.cc
+++ b/third_party/aom/test/aom_image_test.cc
@@ -9,6 +9,8 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
+#include <climits>
+
#include "aom/aom_image.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
@@ -70,3 +72,66 @@ TEST(AomImageTest, AomImgAllocNv12) {
EXPECT_EQ(img.planes[AOM_PLANE_V], nullptr);
aom_img_free(&img);
}
+
+TEST(AomImageTest, AomImgAllocHugeWidth) {
+ // The stride (0x80000000 * 2) would overflow unsigned int.
+ aom_image_t *image =
+ aom_img_alloc(nullptr, AOM_IMG_FMT_I42016, 0x80000000, 1, 1);
+ ASSERT_EQ(image, nullptr);
+
+ // The stride (0x80000000) would overflow int.
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 0x80000000, 1, 1);
+ ASSERT_EQ(image, nullptr);
+
+ // The aligned width (UINT_MAX + 1) would overflow unsigned int.
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, UINT_MAX, 1, 1);
+ ASSERT_EQ(image, nullptr);
+
+ image = aom_img_alloc_with_border(nullptr, AOM_IMG_FMT_I422, 1, INT_MAX, 1,
+ 0x40000000, 0);
+ if (image) {
+ uint16_t *y_plane =
+ reinterpret_cast<uint16_t *>(image->planes[AOM_PLANE_Y]);
+ y_plane[0] = 0;
+ y_plane[image->d_w - 1] = 0;
+ aom_img_free(image);
+ }
+
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 0x7ffffffe, 1, 1);
+ if (image) {
+ aom_img_free(image);
+ }
+
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 285245883, 64, 1);
+ if (image) {
+ aom_img_free(image);
+ }
+
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_NV12, 285245883, 64, 1);
+ if (image) {
+ aom_img_free(image);
+ }
+
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_YV12, 285245883, 64, 1);
+ if (image) {
+ aom_img_free(image);
+ }
+
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_I42016, 65536, 2, 1);
+ if (image) {
+ uint16_t *y_plane =
+ reinterpret_cast<uint16_t *>(image->planes[AOM_PLANE_Y]);
+ y_plane[0] = 0;
+ y_plane[image->d_w - 1] = 0;
+ aom_img_free(image);
+ }
+
+ image = aom_img_alloc(nullptr, AOM_IMG_FMT_I42016, 285245883, 2, 1);
+ if (image) {
+ uint16_t *y_plane =
+ reinterpret_cast<uint16_t *>(image->planes[AOM_PLANE_Y]);
+ y_plane[0] = 0;
+ y_plane[image->d_w - 1] = 0;
+ aom_img_free(image);
+ }
+}
diff --git a/third_party/aom/test/disflow_test.cc b/third_party/aom/test/disflow_test.cc
index 4f004480e2..bee9e1261c 100644
--- a/third_party/aom/test/disflow_test.cc
+++ b/third_party/aom/test/disflow_test.cc
@@ -124,4 +124,9 @@ INSTANTIATE_TEST_SUITE_P(NEON, ComputeFlowTest,
::testing::Values(aom_compute_flow_at_point_neon));
#endif
+#if HAVE_SVE
+INSTANTIATE_TEST_SUITE_P(SVE, ComputeFlowTest,
+ ::testing::Values(aom_compute_flow_at_point_sve));
+#endif
+
} // namespace
diff --git a/third_party/aom/test/ethread_test.cc b/third_party/aom/test/ethread_test.cc
index ce45394eb8..415f5de269 100644
--- a/third_party/aom/test/ethread_test.cc
+++ b/third_party/aom/test/ethread_test.cc
@@ -18,6 +18,7 @@
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "test/yuv_video_source.h"
+#include "av1/encoder/enc_enums.h"
#include "av1/encoder/firstpass.h"
namespace {
@@ -411,9 +412,7 @@ class AVxEncoderThreadTest
const std::vector<size_t> ref_size_enc,
const std::vector<std::string> ref_md5_enc,
const std::vector<std::string> ref_md5_dec) {
- // This value should be kept the same as MAX_NUM_THREADS
- // in aom_thread.h
- cfg_.g_threads = 64;
+ cfg_.g_threads = MAX_NUM_THREADS;
ASSERT_NO_FATAL_FAILURE(RunLoop(video));
std::vector<size_t> multi_thr_max_row_mt_size_enc;
std::vector<std::string> multi_thr_max_row_mt_md5_enc;
diff --git a/third_party/aom/test/frame_resize_test.cc b/third_party/aom/test/frame_resize_test.cc
new file mode 100644
index 0000000000..8891304192
--- /dev/null
+++ b/third_party/aom/test/frame_resize_test.cc
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#include "config/av1_rtcd.h"
+#include "test/acm_random.h"
+#include "test/util.h"
+#include "aom_ports/aom_timer.h"
+#include "aom_ports/bitops.h"
+#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
+
+namespace {
+
+using ::testing::Combine;
+using ::testing::Values;
+using ::testing::ValuesIn;
+
+using std::make_tuple;
+using std::tuple;
+
+const int kIters = 1000;
+
+typedef tuple<int, int> FrameDimension;
+
+// Resolutions (width x height) to be tested for resizing.
+const FrameDimension kFrameDim[] = {
+ make_tuple(3840, 2160), make_tuple(2560, 1440), make_tuple(1920, 1080),
+ make_tuple(1280, 720), make_tuple(640, 480), make_tuple(640, 360),
+ make_tuple(256, 256),
+};
+
+// Check that two 8-bit output buffers are identical.
+void AssertOutputBufferEq(const uint8_t *p1, const uint8_t *p2, int width,
+ int height) {
+ ASSERT_TRUE(p1 != p2) << "Buffers must be at different memory locations";
+ for (int j = 0; j < height; ++j) {
+ if (memcmp(p1, p2, sizeof(*p1) * width) == 0) {
+ p1 += width;
+ p2 += width;
+ continue;
+ }
+ for (int i = 0; i < width; ++i) {
+ ASSERT_EQ(p1[i], p2[i])
+ << width << "x" << height << " Pixel mismatch at (" << i << ", " << j
+ << ")";
+ }
+ }
+}
+
+typedef bool (*LowBDResizeFunc)(uint8_t *intbuf, uint8_t *output,
+ int out_stride, int height, int height2,
+ int stride, int start_wd);
+// Test parameter list:
+// <tst_fun, dims>
+typedef tuple<LowBDResizeFunc, FrameDimension> ResizeTestParams;
+
+class AV1ResizeYTest : public ::testing::TestWithParam<ResizeTestParams> {
+ public:
+ void SetUp() {
+ test_fun_ = GET_PARAM(0);
+ frame_dim_ = GET_PARAM(1);
+ width_ = std::get<0>(frame_dim_);
+ height_ = std::get<1>(frame_dim_);
+ const int msb = get_msb(AOMMIN(width_, height_));
+ n_levels_ = AOMMAX(msb - MIN_PYRAMID_SIZE_LOG2, 1);
+
+ src_ = (uint8_t *)aom_malloc((width_ / 2) * height_ * sizeof(*src_));
+ ref_dest_ =
+ (uint8_t *)aom_calloc((width_ * height_) / 4, sizeof(*ref_dest_));
+ test_dest_ =
+ (uint8_t *)aom_calloc((width_ * height_) / 4, sizeof(*test_dest_));
+ }
+
+ void RunTest() {
+ int width2 = width_, height2 = height_;
+
+ for (int i = 0; i < (width_ / 2) * height_; i++) src_[i] = rng_.Rand8();
+ for (int level = 1; level < n_levels_; level++) {
+ width2 = (width_ >> level);
+ height2 = (height_ >> level);
+ resize_vert_dir_c(src_, ref_dest_, width2, height2 << 1, height2, width2,
+ 0);
+ test_fun_(src_, test_dest_, width2, height2 << 1, height2, width2, 0);
+
+ AssertOutputBufferEq(ref_dest_, test_dest_, width2, height2);
+ }
+ }
+
+ void SpeedTest() {
+ int width2 = width_, height2 = height_;
+
+ for (int i = 0; i < (width_ / 2) * height_; i++) src_[i] = rng_.Rand8();
+ for (int level = 1; level < n_levels_; level++) {
+ width2 = (width_ >> level);
+ height2 = (height_ >> level);
+ aom_usec_timer ref_timer;
+ aom_usec_timer_start(&ref_timer);
+ for (int j = 0; j < kIters; j++) {
+ resize_vert_dir_c(src_, ref_dest_, width2, height2 << 1, height2,
+ width2, 0);
+ }
+ aom_usec_timer_mark(&ref_timer);
+ const int64_t ref_time = aom_usec_timer_elapsed(&ref_timer);
+
+ aom_usec_timer tst_timer;
+ aom_usec_timer_start(&tst_timer);
+ for (int j = 0; j < kIters; j++) {
+ test_fun_(src_, test_dest_, width2, height2 << 1, height2, width2, 0);
+ }
+ aom_usec_timer_mark(&tst_timer);
+ const int64_t tst_time = aom_usec_timer_elapsed(&tst_timer);
+
+ std::cout << "level: " << level << " [" << width2 << " x " << height2
+ << "] C time = " << ref_time << " , SIMD time = " << tst_time
+ << " scaling=" << float(1.00) * ref_time / tst_time << "x \n";
+ }
+ }
+
+ void TearDown() {
+ aom_free(src_);
+ aom_free(ref_dest_);
+ aom_free(test_dest_);
+ }
+
+ private:
+ LowBDResizeFunc test_fun_;
+ FrameDimension frame_dim_;
+ int width_;
+ int height_;
+ int n_levels_;
+ uint8_t *src_;
+ uint8_t *ref_dest_;
+ uint8_t *test_dest_;
+ libaom_test::ACMRandom rng_;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1ResizeYTest);
+
+TEST_P(AV1ResizeYTest, RunTest) { RunTest(); }
+
+TEST_P(AV1ResizeYTest, DISABLED_SpeedTest) { SpeedTest(); }
+
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, AV1ResizeYTest,
+ ::testing::Combine(::testing::Values(resize_vert_dir_avx2),
+ ::testing::ValuesIn(kFrameDim)));
+#endif
+
+} // namespace
diff --git a/third_party/aom/test/test.cmake b/third_party/aom/test/test.cmake
index e2f5da570d..2631c9fb39 100644
--- a/third_party/aom/test/test.cmake
+++ b/third_party/aom/test/test.cmake
@@ -209,6 +209,7 @@ if(NOT BUILD_SHARED_LIBS)
"${AOM_ROOT}/test/fdct4x4_test.cc"
"${AOM_ROOT}/test/fft_test.cc"
"${AOM_ROOT}/test/firstpass_test.cc"
+ "${AOM_ROOT}/test/frame_resize_test.cc"
"${AOM_ROOT}/test/fwht4x4_test.cc"
"${AOM_ROOT}/test/hadamard_test.cc"
"${AOM_ROOT}/test/horver_correlation_test.cc"
diff --git a/third_party/aom/test/wiener_test.cc b/third_party/aom/test/wiener_test.cc
index b995c84d8f..c38e10e3c2 100644
--- a/third_party/aom/test/wiener_test.cc
+++ b/third_party/aom/test/wiener_test.cc
@@ -397,6 +397,12 @@ INSTANTIATE_TEST_SUITE_P(NEON, WienerTest,
::testing::Values(av1_compute_stats_neon));
#endif // HAVE_NEON
+#if HAVE_SVE
+
+INSTANTIATE_TEST_SUITE_P(SVE, WienerTest,
+ ::testing::Values(av1_compute_stats_sve));
+#endif // HAVE_SVE
+
} // namespace wiener_lowbd
#if CONFIG_AV1_HIGHBITDEPTH
@@ -514,25 +520,27 @@ static void compute_stats_highbd_win_opt_c(int wiener_win, const uint8_t *dgd8,
}
void compute_stats_highbd_opt_c(int wiener_win, const uint8_t *dgd,
- const uint8_t *src, int h_start, int h_end,
- int v_start, int v_end, int dgd_stride,
- int src_stride, int64_t *M, int64_t *H,
- aom_bit_depth_t bit_depth) {
+ const uint8_t *src, int16_t *d, int16_t *s,
+ int h_start, int h_end, int v_start, int v_end,
+ int dgd_stride, int src_stride, int64_t *M,
+ int64_t *H, aom_bit_depth_t bit_depth) {
if (wiener_win == WIENER_WIN || wiener_win == WIENER_WIN_CHROMA) {
compute_stats_highbd_win_opt_c(wiener_win, dgd, src, h_start, h_end,
v_start, v_end, dgd_stride, src_stride, M, H,
bit_depth);
} else {
- av1_compute_stats_highbd_c(wiener_win, dgd, src, h_start, h_end, v_start,
- v_end, dgd_stride, src_stride, M, H, bit_depth);
+ av1_compute_stats_highbd_c(wiener_win, dgd, src, d, s, h_start, h_end,
+ v_start, v_end, dgd_stride, src_stride, M, H,
+ bit_depth);
}
}
static const int kIterations = 100;
typedef void (*compute_stats_Func)(int wiener_win, const uint8_t *dgd,
- const uint8_t *src, int h_start, int h_end,
- int v_start, int v_end, int dgd_stride,
- int src_stride, int64_t *M, int64_t *H,
+ const uint8_t *src, int16_t *d, int16_t *s,
+ int h_start, int h_end, int v_start,
+ int v_end, int dgd_stride, int src_stride,
+ int64_t *M, int64_t *H,
aom_bit_depth_t bit_depth);
typedef std::tuple<const compute_stats_Func> WienerTestParam;
@@ -546,11 +554,17 @@ class WienerTestHighbd : public ::testing::TestWithParam<WienerTestParam> {
dgd_buf = (uint16_t *)aom_memalign(
32, MAX_DATA_BLOCK * MAX_DATA_BLOCK * sizeof(*dgd_buf));
ASSERT_NE(dgd_buf, nullptr);
+ const size_t buf_size =
+ sizeof(*buf) * 6 * RESTORATION_UNITSIZE_MAX * RESTORATION_UNITSIZE_MAX;
+ buf = (int16_t *)aom_memalign(32, buf_size);
+ ASSERT_NE(buf, nullptr);
+ memset(buf, 0, buf_size);
target_func_ = GET_PARAM(0);
}
void TearDown() override {
aom_free(src_buf);
aom_free(dgd_buf);
+ aom_free(buf);
}
void RunWienerTest(const int32_t wiener_win, int32_t run_times,
aom_bit_depth_t bit_depth);
@@ -562,6 +576,7 @@ class WienerTestHighbd : public ::testing::TestWithParam<WienerTestParam> {
libaom_test::ACMRandom rng_;
uint16_t *src_buf;
uint16_t *dgd_buf;
+ int16_t *buf;
};
void WienerTestHighbd::RunWienerTest(const int32_t wiener_win,
@@ -589,6 +604,9 @@ void WienerTestHighbd::RunWienerTest(const int32_t wiener_win,
const int dgd_stride = h_end;
const int src_stride = MAX_DATA_BLOCK;
const int iters = run_times == 1 ? kIterations : 2;
+ int16_t *dgd_avg = buf;
+ int16_t *src_avg =
+ buf + (3 * RESTORATION_UNITSIZE_MAX * RESTORATION_UNITSIZE_MAX);
for (int iter = 0; iter < iters && !HasFatalFailure(); ++iter) {
for (int i = 0; i < MAX_DATA_BLOCK * MAX_DATA_BLOCK; ++i) {
dgd_buf[i] = rng_.Rand16() % (1 << bit_depth);
@@ -601,16 +619,17 @@ void WienerTestHighbd::RunWienerTest(const int32_t wiener_win,
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < run_times; ++i) {
- av1_compute_stats_highbd_c(wiener_win, dgd8, src8, h_start, h_end,
- v_start, v_end, dgd_stride, src_stride, M_ref,
- H_ref, bit_depth);
+ av1_compute_stats_highbd_c(wiener_win, dgd8, src8, dgd_avg, src_avg,
+ h_start, h_end, v_start, v_end, dgd_stride,
+ src_stride, M_ref, H_ref, bit_depth);
}
aom_usec_timer_mark(&timer);
const double time1 = static_cast<double>(aom_usec_timer_elapsed(&timer));
aom_usec_timer_start(&timer);
for (int i = 0; i < run_times; ++i) {
- target_func_(wiener_win, dgd8, src8, h_start, h_end, v_start, v_end,
- dgd_stride, src_stride, M_test, H_test, bit_depth);
+ target_func_(wiener_win, dgd8, src8, dgd_avg, src_avg, h_start, h_end,
+ v_start, v_end, dgd_stride, src_stride, M_test, H_test,
+ bit_depth);
}
aom_usec_timer_mark(&timer);
const double time2 = static_cast<double>(aom_usec_timer_elapsed(&timer));
@@ -657,6 +676,9 @@ void WienerTestHighbd::RunWienerTest_ExtremeValues(const int32_t wiener_win,
const int dgd_stride = h_end;
const int src_stride = MAX_DATA_BLOCK;
const int iters = 1;
+ int16_t *dgd_avg = buf;
+ int16_t *src_avg =
+ buf + (3 * RESTORATION_UNITSIZE_MAX * RESTORATION_UNITSIZE_MAX);
for (int iter = 0; iter < iters && !HasFatalFailure(); ++iter) {
// Fill with alternating extreme values to maximize difference with
// the average.
@@ -668,12 +690,13 @@ void WienerTestHighbd::RunWienerTest_ExtremeValues(const int32_t wiener_win,
dgd_buf + wiener_halfwin * MAX_DATA_BLOCK + wiener_halfwin);
const uint8_t *src8 = CONVERT_TO_BYTEPTR(src_buf);
- av1_compute_stats_highbd_c(wiener_win, dgd8, src8, h_start, h_end, v_start,
- v_end, dgd_stride, src_stride, M_ref, H_ref,
- bit_depth);
+ av1_compute_stats_highbd_c(wiener_win, dgd8, src8, dgd_avg, src_avg,
+ h_start, h_end, v_start, v_end, dgd_stride,
+ src_stride, M_ref, H_ref, bit_depth);
- target_func_(wiener_win, dgd8, src8, h_start, h_end, v_start, v_end,
- dgd_stride, src_stride, M_test, H_test, bit_depth);
+ target_func_(wiener_win, dgd8, src8, dgd_avg, src_avg, h_start, h_end,
+ v_start, v_end, dgd_stride, src_stride, M_test, H_test,
+ bit_depth);
int failed = 0;
for (int i = 0; i < wiener_win2; ++i) {
diff --git a/third_party/dav1d/meson.build b/third_party/dav1d/meson.build
index e371415d53..a2637ed797 100644
--- a/third_party/dav1d/meson.build
+++ b/third_party/dav1d/meson.build
@@ -81,6 +81,8 @@ cdata.set10('TRIM_DSP_FUNCTIONS', get_option('trim_dsp') == 'true' or
# Logging option
cdata.set10('CONFIG_LOG', get_option('logging'))
+cdata.set10('CONFIG_MACOS_KPERF', get_option('macos_kperf'))
+
#
# OS/Compiler checks and defines
#
diff --git a/third_party/dav1d/meson_options.txt b/third_party/dav1d/meson_options.txt
index c04deffd73..b0b45b474d 100644
--- a/third_party/dav1d/meson_options.txt
+++ b/third_party/dav1d/meson_options.txt
@@ -68,3 +68,8 @@ option('trim_dsp',
choices: ['true', 'false', 'if-release'],
value: 'if-release',
description: 'Eliminate redundant DSP functions where possible')
+
+option('macos_kperf',
+ type: 'boolean',
+ value: false,
+ description: 'Use the private macOS kperf API for benchmarking')
diff --git a/third_party/dav1d/src/arm/64/mc.S b/third_party/dav1d/src/arm/64/mc.S
index 3df0393c3a..5b493be82d 100644
--- a/third_party/dav1d/src/arm/64/mc.S
+++ b/third_party/dav1d/src/arm/64/mc.S
@@ -837,7 +837,7 @@ endfunc
// This has got the same signature as the put_8tap functions,
// and assumes that x8 is set to (clz(w)-24).
-function put_neon
+function put_neon, export=1
adr x9, L(put_tbl)
ldrh w8, [x9, x8, lsl #1]
sub x9, x9, w8, uxtw
@@ -939,7 +939,7 @@ endfunc
// This has got the same signature as the prep_8tap functions,
// and assumes that x8 is set to (clz(w)-24), and x7 to w*2.
-function prep_neon
+function prep_neon, export=1
adr x9, L(prep_tbl)
ldrh w8, [x9, x8, lsl #1]
sub x9, x9, w8, uxtw
diff --git a/third_party/dav1d/src/arm/64/mc_dotprod.S b/third_party/dav1d/src/arm/64/mc_dotprod.S
new file mode 100644
index 0000000000..fcf04ee4d0
--- /dev/null
+++ b/third_party/dav1d/src/arm/64/mc_dotprod.S
@@ -0,0 +1,1413 @@
+/*
+ * Copyright © 2024, VideoLAN and dav1d authors
+ * Copyright © 2024, Janne Grunau
+ * Copyright © 2024, Martin Storsjo
+ * Copyright © 2024, Arm Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "src/arm/asm.S"
+#include "util.S"
+
+
+#if HAVE_DOTPROD
+ENABLE_DOTPROD
+
+// No spaces in these expressions, due to gas-preprocessor. It is translated by
+// -1 to save the negative offset at getting the address of `mc_subpel_filters`.
+#define REGULAR1 (((0*15-1)<<7)|(3*15-1))
+#define SMOOTH1 (((1*15-1)<<7)|(4*15-1))
+#define SHARP1 (((2*15-1)<<7)|(3*15-1))
+
+#define FUNC_ALIGN 2
+#define JUMP_ALIGN 2
+#define LOOP_ALIGN 2
+
+
+// Lookup table used to help conversion of shifted 32-bit values to 8-bit.
+ .align 4
+L(hv_tbl_neon_dotprod):
+ .byte 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30
+
+// Shuffle indices to permute horizontal samples in preparation for input to
+// SDOT instructions. The 8-tap horizontal convolution uses sample indices in the
+// interval of [-3, 4] relative to the current sample position. We load samples
+// from index value -4 to keep loads word aligned, so the shuffle bytes are
+// translated by 1 to handle this.
+ .align 4
+L(h_tbl_neon_dotprod):
+ .byte 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7
+ .byte 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10, 8, 9, 10, 11
+ .byte 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14, 12, 13, 14, 15
+ .byte 13, 14, 15, 16, 14, 15, 16, 17, 15, 16, 17, 18, 16, 17, 18, 19
+
+// Vertical convolutions are also using SDOT instructions, where a 128-bit
+// register contains a transposed 4x4 matrix of values. Subsequent iterations of
+// the vertical convolution can reuse the 3x4 sub-matrix from the previous loop
+// iteration. These shuffle indices shift and merge this 4x4 matrix with the
+// values of a new line.
+ .align 4
+L(v_tbl_neon_dotprod):
+ .byte 1, 2, 3, 16, 5, 6, 7, 20, 9, 10, 11, 24, 13, 14, 15, 28
+ .byte 1, 2, 3, 16, 5, 6, 7, 17, 9, 10, 11, 18, 13, 14, 15, 19
+ .byte 1, 2, 3, 20, 5, 6, 7, 21, 9, 10, 11, 22, 13, 14, 15, 23
+ .byte 1, 2, 3, 24, 5, 6, 7, 25, 9, 10, 11, 26, 13, 14, 15, 27
+ .byte 1, 2, 3, 28, 5, 6, 7, 29, 9, 10, 11, 30, 13, 14, 15, 31
+
+
+.macro make_8tap_fn op, type, type_h, type_v, isa, jump=1
+function \op\()_8tap_\type\()_8bpc_\isa, export=1, align=FUNC_ALIGN
+ mov x9, \type_h
+ mov x10, \type_v
+ .if \jump
+ b \op\()_8tap_\isa
+ .endif
+endfunc
+.endm
+
+.macro filter_8tap_fn type, isa, dst, d_strd, src, s_strd, w, h, mx, my, xmx, xmy, ldst, lsrc, wd_strd
+make_8tap_fn \type, sharp, SHARP1, SHARP1, \isa
+make_8tap_fn \type, sharp_smooth, SHARP1, SMOOTH1, \isa
+make_8tap_fn \type, sharp_regular, SHARP1, REGULAR1, \isa
+make_8tap_fn \type, smooth_sharp, SMOOTH1, SHARP1, \isa
+make_8tap_fn \type, smooth, SMOOTH1, SMOOTH1, \isa
+make_8tap_fn \type, smooth_regular, SMOOTH1, REGULAR1, \isa
+make_8tap_fn \type, regular_sharp, REGULAR1, SHARP1, \isa
+make_8tap_fn \type, regular_smooth, REGULAR1, SMOOTH1, \isa
+make_8tap_fn \type, regular, REGULAR1, REGULAR1, \isa, jump=0
+
+function \type\()_8tap_\isa, align=FUNC_ALIGN
+ clz w8, \w
+ mov w11, #0x4081 // (1 << 14) | (1 << 7) | (1 << 0)
+ sub w8, w8, #24 // for jump tables
+ movrel x12, X(mc_subpel_filters)
+ cbnz \mx, L(\type\()_8tap_h_hv_\isa)
+ cbnz \my, L(\type\()_8tap_v_\isa)
+.ifc \type, prep
+ add \wd_strd, \w, \w // prep_neon needs w * 2 as stride
+.endif
+ b X(\type\()_neon)
+
+ .align JUMP_ALIGN
+L(\type\()_8tap_v_\isa):
+ madd \my, \my, w11, w10
+.ifc \type, prep
+ mov w8, 0x2002 // FILTER_WEIGHT * 128 + rounding
+.endif
+ sub \src, \src, \s_strd
+ ldr q6, L(v_tbl_neon_dotprod)
+.ifc \type, prep
+ dup v4.4s, w8
+.endif
+ ubfx w11, \my, #7, #7
+ and \my, \my, #0x7F
+ ldr q28, L(v_tbl_neon_dotprod) + 16
+ cmp \h, #4
+ csel \my, \my, w11, le
+ sub \src, \src, \s_strd, lsl #1 // src - src_stride * 3
+ ldr q29, L(v_tbl_neon_dotprod) + 32
+ add \xmy, x12, \xmy, lsl #3 // subpel V filter address
+ movi v5.16b, #128
+ ldr d7, [\xmy]
+ cmp \w, #8
+ b.eq 80f
+ b.lt 40f
+
+ // .align JUMP_ALIGN // fallthrough
+160: // V - 16xN+
+ ldr q30, L(v_tbl_neon_dotprod) + 48
+ ldr q31, L(v_tbl_neon_dotprod) + 64
+.ifc \type, prep
+ add \wd_strd, \w, \w
+.endif
+ .align LOOP_ALIGN
+161:
+ mov \lsrc, \src
+ mov \ldst, \dst
+ sub w8, \h, #1
+
+ ldr q16, [\lsrc]
+ ldr q17, [\lsrc, \s_strd]
+ add \lsrc, \lsrc, \s_strd, lsl #1
+ ldr q18, [\lsrc]
+ ldr q19, [\lsrc, \s_strd]
+ add \lsrc, \lsrc, \s_strd, lsl #1
+
+ zip1 v0.16b, v16.16b, v17.16b
+ zip2 v1.16b, v16.16b, v17.16b
+ zip1 v2.16b, v18.16b, v19.16b
+ zip2 v3.16b, v18.16b, v19.16b
+
+ ldr q20, [\lsrc]
+ ldr q21, [\lsrc, \s_strd]
+ add \lsrc, \lsrc, \s_strd, lsl #1
+ ldr q22, [\lsrc]
+ ldr q23, [\lsrc, \s_strd]
+ add \lsrc, \lsrc, \s_strd, lsl #1
+
+ zip1 v18.16b, v20.16b, v21.16b
+ zip2 v21.16b, v20.16b, v21.16b
+ zip1 v24.16b, v22.16b, v23.16b
+ zip2 v27.16b, v22.16b, v23.16b
+
+ zip1 v16.8h, v0.8h, v2.8h
+ zip2 v19.8h, v0.8h, v2.8h
+ zip1 v22.8h, v1.8h, v3.8h
+ zip2 v25.8h, v1.8h, v3.8h
+
+ zip1 v17.8h, v18.8h, v24.8h
+ zip2 v20.8h, v18.8h, v24.8h
+ zip1 v23.8h, v21.8h, v27.8h
+ zip2 v26.8h, v21.8h, v27.8h
+
+ sub v16.16b, v16.16b, v5.16b
+ sub v19.16b, v19.16b, v5.16b
+ sub v22.16b, v22.16b, v5.16b
+ sub v25.16b, v25.16b, v5.16b
+
+ sub v17.16b, v17.16b, v5.16b
+ sub v20.16b, v20.16b, v5.16b
+ sub v23.16b, v23.16b, v5.16b
+ sub v26.16b, v26.16b, v5.16b
+
+ .align LOOP_ALIGN
+16:
+ ldr q27, [\lsrc]
+ add \lsrc, \lsrc, \s_strd
+.ifc \type, prep
+ mov v0.16b, v4.16b
+ mov v1.16b, v4.16b
+ mov v2.16b, v4.16b
+ mov v3.16b, v4.16b
+.else
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+ movi v2.4s, #32, lsl 8
+ movi v3.4s, #32, lsl 8
+.endif
+ sub v18.16b, v27.16b, v5.16b
+ sub v21.16b, v27.16b, v5.16b
+ sub v24.16b, v27.16b, v5.16b
+ sub v27.16b, v27.16b, v5.16b
+
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v2.4s, v22.16b, v7.4b[0]
+ sdot v3.4s, v25.16b, v7.4b[0]
+
+ tbl v16.16b, {v16.16b, v17.16b}, v6.16b
+ tbl v19.16b, {v19.16b, v20.16b}, v6.16b
+ tbl v22.16b, {v22.16b, v23.16b}, v6.16b
+ tbl v25.16b, {v25.16b, v26.16b}, v6.16b
+
+ sdot v0.4s, v17.16b, v7.4b[1]
+ sdot v1.4s, v20.16b, v7.4b[1]
+ sdot v2.4s, v23.16b, v7.4b[1]
+ sdot v3.4s, v26.16b, v7.4b[1]
+
+ tbl v17.16b, {v17.16b, v18.16b}, v28.16b
+ tbl v20.16b, {v20.16b, v21.16b}, v29.16b
+ tbl v23.16b, {v23.16b, v24.16b}, v30.16b
+ tbl v26.16b, {v26.16b, v27.16b}, v31.16b
+
+ subs w8, w8, #1
+ uzp1 v0.8h, v0.8h, v1.8h
+ uzp1 v2.8h, v2.8h, v3.8h
+.ifc \type, prep
+ sshr v0.8h, v0.8h, #2
+ sshr v1.8h, v2.8h, #2
+ st1 {v0.8h, v1.8h}, [\ldst], \d_strd
+.else
+ sqrshrun v0.8b, v0.8h, #6
+ sqrshrun2 v0.16b, v2.8h, #6
+ st1 {v0.16b}, [\ldst], \d_strd
+.endif
+ b.gt 16b
+
+.ifc \type, prep
+ mov v0.16b, v4.16b
+ mov v1.16b, v4.16b
+ mov v2.16b, v4.16b
+ mov v3.16b, v4.16b
+.else
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+ movi v2.4s, #32, lsl 8
+ movi v3.4s, #32, lsl 8
+.endif
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v2.4s, v22.16b, v7.4b[0]
+ sdot v3.4s, v25.16b, v7.4b[0]
+
+ sdot v0.4s, v17.16b, v7.4b[1]
+ sdot v1.4s, v20.16b, v7.4b[1]
+ sdot v2.4s, v23.16b, v7.4b[1]
+ sdot v3.4s, v26.16b, v7.4b[1]
+
+ subs \w, \w, #16
+ uzp1 v0.8h, v0.8h, v1.8h
+ uzp1 v2.8h, v2.8h, v3.8h
+.ifc \type, prep
+ sshr v0.8h, v0.8h, #2
+ sshr v1.8h, v2.8h, #2
+ stp q0, q1, [\ldst]
+ add \dst, \dst, #32
+.else
+ sqrshrun v0.8b, v0.8h, #6
+ sqrshrun2 v0.16b, v2.8h, #6
+ str q0, [\ldst]
+ add \dst, \dst, #16
+.endif
+ add \src, \src, #16
+ b.gt 161b
+ ret
+
+ .align JUMP_ALIGN
+80: // V - 8xN
+ ldr d16, [\src]
+ ldr d17, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ ldr d18, [\src]
+ ldr d19, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+
+ ldr d20, [\src]
+ ldr d21, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ ldr d22, [\src]
+ ldr d23, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ subs \h, \h, #2 // for prep: sub is enough
+
+ zip1 v0.16b, v16.16b, v17.16b
+ zip1 v2.16b, v18.16b, v19.16b
+ zip1 v18.16b, v20.16b, v21.16b
+ zip1 v24.16b, v22.16b, v23.16b
+
+ zip1 v16.8h, v0.8h, v2.8h
+ zip2 v19.8h, v0.8h, v2.8h
+ zip1 v17.8h, v18.8h, v24.8h
+ zip2 v20.8h, v18.8h, v24.8h
+
+ sub v16.16b, v16.16b, v5.16b
+ sub v19.16b, v19.16b, v5.16b
+ sub v17.16b, v17.16b, v5.16b
+ sub v20.16b, v20.16b, v5.16b
+.ifc \type, put
+ b.eq 82f
+.endif
+
+ .align LOOP_ALIGN
+8:
+ ldr d21, [\src]
+ ldr d27, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+.ifc \type, prep
+ mov v0.16b, v4.16b
+ mov v1.16b, v4.16b
+ mov v2.16b, v4.16b
+ mov v3.16b, v4.16b
+.else
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+ movi v2.4s, #32, lsl 8
+ movi v3.4s, #32, lsl 8
+.endif
+ sub v18.16b, v21.16b, v5.16b
+ sub v21.16b, v21.16b, v5.16b
+ sub v24.16b, v27.16b, v5.16b
+ sub v27.16b, v27.16b, v5.16b
+
+ tbl v22.16b, {v16.16b, v17.16b}, v6.16b
+ tbl v25.16b, {v19.16b, v20.16b}, v6.16b
+ tbl v23.16b, {v17.16b, v18.16b}, v28.16b
+ tbl v26.16b, {v20.16b, v21.16b}, v29.16b
+
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v0.4s, v17.16b, v7.4b[1]
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v1.4s, v20.16b, v7.4b[1]
+
+ tbl v16.16b, {v22.16b, v23.16b}, v6.16b
+ tbl v19.16b, {v25.16b, v26.16b}, v6.16b
+ tbl v17.16b, {v23.16b, v24.16b}, v28.16b
+ tbl v20.16b, {v26.16b, v27.16b}, v29.16b
+
+ sdot v2.4s, v22.16b, v7.4b[0]
+ sdot v2.4s, v23.16b, v7.4b[1]
+ sdot v3.4s, v25.16b, v7.4b[0]
+ sdot v3.4s, v26.16b, v7.4b[1]
+
+ subs \h, \h, #2
+ uzp1 v0.8h, v0.8h, v1.8h
+ uzp1 v2.8h, v2.8h, v3.8h
+.ifc \type, prep
+ sshr v0.8h, v0.8h, #2
+ sshr v1.8h, v2.8h, #2
+ stp q0, q1, [\dst], #32
+.else
+ sqrshrun v0.8b, v0.8h, #6
+ sqrshrun v1.8b, v2.8h, #6
+ str d0, [\dst]
+ str d1, [\dst, \d_strd]
+ add \dst, \dst, \d_strd, lsl #1
+.endif
+ b.gt 8b
+
+.ifc \type, put
+ .align JUMP_ALIGN
+82:
+ ldr d21, [\src]
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+ movi v2.4s, #32, lsl 8
+ movi v3.4s, #32, lsl 8
+.else
+ ldr d21, [\src]
+ mov v0.16b, v4.16b
+ mov v1.16b, v4.16b
+ mov v2.16b, v4.16b
+ mov v3.16b, v4.16b
+.endif
+ sub v18.16b, v21.16b, v5.16b
+ sub v21.16b, v21.16b, v5.16b
+
+ tbl v22.16b, {v16.16b, v17.16b}, v6.16b
+ tbl v25.16b, {v19.16b, v20.16b}, v6.16b
+ tbl v23.16b, {v17.16b, v18.16b}, v28.16b
+ tbl v26.16b, {v20.16b, v21.16b}, v29.16b
+
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v0.4s, v17.16b, v7.4b[1]
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v1.4s, v20.16b, v7.4b[1]
+
+ sdot v2.4s, v22.16b, v7.4b[0]
+ sdot v2.4s, v23.16b, v7.4b[1]
+ sdot v3.4s, v25.16b, v7.4b[0]
+ sdot v3.4s, v26.16b, v7.4b[1]
+
+ uzp1 v0.8h, v0.8h, v1.8h
+ uzp1 v2.8h, v2.8h, v3.8h
+.ifc \type, prep
+ sshr v0.8h, v0.8h, #2
+ sshr v1.8h, v2.8h, #2
+ stp q0, q1, [\dst]
+.else
+ sqrshrun v0.8b, v0.8h, #6
+ sqrshrun v1.8b, v2.8h, #6
+ str d0, [\dst]
+ str d1, [\dst, \d_strd]
+.endif
+ ret
+
+ .align JUMP_ALIGN
+40: // V - 4xN or 2xN (put only)
+.ifc \type, put
+ cmp \w, #2
+ b.eq 20f
+.endif
+ ldr s16, [\src]
+ ldr s17, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ ldr s18, [\src]
+ ldr s19, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+
+ ldr s20, [\src]
+ ldr s21, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ ldr s22, [\src]
+ ldr s23, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ subs \h, \h, #2 // for prep: sub is enough
+
+ zip1 v0.8b, v16.8b, v17.8b
+ zip1 v2.8b, v18.8b, v19.8b
+ zip1 v18.8b, v20.8b, v21.8b
+ zip1 v24.8b, v22.8b, v23.8b
+
+ zip1 v16.8h, v0.8h, v2.8h
+ zip1 v17.8h, v18.8h, v24.8h
+
+ sub v16.16b, v16.16b, v5.16b
+ sub v17.16b, v17.16b, v5.16b
+.ifc \type, put
+ b.eq 42f
+.endif
+
+ .align LOOP_ALIGN
+4:
+ ldr s18, [\src]
+ ldr s21, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+.ifc \type, prep
+ mov v0.16b, v4.16b
+ mov v1.16b, v4.16b
+.else
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+.endif
+ sub v18.16b, v18.16b, v5.16b
+ sub v21.16b, v21.16b, v5.16b
+
+ tbl v19.16b, {v16.16b, v17.16b}, v6.16b
+ tbl v20.16b, {v17.16b, v18.16b}, v28.16b
+
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v0.4s, v17.16b, v7.4b[1]
+
+ tbl v16.16b, {v19.16b, v20.16b}, v6.16b
+ tbl v17.16b, {v20.16b, v21.16b}, v28.16b
+
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v1.4s, v20.16b, v7.4b[1]
+.ifc \type, prep
+ subs \h, \h, #2
+ shrn v0.4h, v0.4s, #2
+ shrn2 v0.8h, v1.4s, #2
+ str q0, [\dst], #16
+.else
+ uzp1 v0.8h, v0.8h, v1.8h
+ sqrshrun v0.8b, v0.8h, #6
+ subs \h, \h, #2
+ fmov x8, d0
+ lsr x9, x8, #32
+ str w8, [\dst]
+ str w9, [\dst, \d_strd]
+ add \dst, \dst, \d_strd, lsl #1
+.endif
+ b.gt 4b
+
+.ifc \type, put
+ .align JUMP_ALIGN
+42:
+ ldr s18, [\src]
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+.else
+ ldr s18, [\src]
+ mov v0.16b, v4.16b
+ mov v1.16b, v4.16b
+.endif
+ sub v18.16b, v18.16b, v5.16b
+
+ tbl v19.16b, {v16.16b, v17.16b}, v6.16b
+ tbl v20.16b, {v17.16b, v18.16b}, v28.16b
+
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v0.4s, v17.16b, v7.4b[1]
+
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v1.4s, v20.16b, v7.4b[1]
+.ifc \type, prep
+ shrn v0.4h, v0.4s, #2
+ shrn2 v0.8h, v1.4s, #2
+ str q0, [\dst]
+ ret
+.else
+ uzp1 v0.8h, v0.8h, v1.8h
+ sqrshrun v0.8b, v0.8h, #6
+ fmov x8, d0
+ lsr x9, x8, #32
+ str w8, [\dst]
+ str w9, [\dst, \d_strd]
+ ret
+
+ .align JUMP_ALIGN
+20: // V - 2xN
+ ldr h16, [\src]
+ ldr h17, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ ldr h18, [\src]
+ ldr h19, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+
+ ldr h20, [\src]
+ ldr h21, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ ldr h22, [\src]
+ ldr h23, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+ subs \h, \h, #2
+
+ zip1 v0.8b, v16.8b, v17.8b
+ zip1 v2.8b, v18.8b, v19.8b
+ zip1 v18.8b, v20.8b, v21.8b
+ zip1 v24.8b, v22.8b, v23.8b
+
+ zip1 v16.4h, v0.4h, v2.4h
+ zip1 v17.4h, v18.4h, v24.4h
+
+ sub v16.8b, v16.8b, v5.8b
+ sub v17.8b, v17.8b, v5.8b
+
+ b.eq 22f
+
+ .align LOOP_ALIGN
+2:
+ ldr h18, [\src]
+ ldr h21, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+
+ sub v18.8b, v18.8b, v5.8b
+ sub v21.8b, v21.8b, v5.8b
+
+ tbl v19.16b, {v16.16b, v17.16b}, v6.16b
+ tbl v20.16b, {v17.16b, v18.16b}, v28.16b
+
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v0.4s, v17.16b, v7.4b[1]
+
+ tbl v16.16b, {v19.16b, v20.16b}, v6.16b
+ tbl v17.16b, {v20.16b, v21.16b}, v28.16b
+
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v1.4s, v20.16b, v7.4b[1]
+
+ uzp1 v0.8h, v0.8h, v1.8h
+ sqrshrun v0.8b, v0.8h, #6
+
+ subs \h, \h, #2
+ fmov x8, d0
+ lsr x9, x8, #32
+ strh w8, [\dst]
+ strh w9, [\dst, \d_strd]
+ add \dst, \dst, \d_strd, lsl #1
+ b.gt 2b
+
+ .align JUMP_ALIGN
+22:
+ ldr h18, [\src]
+
+ movi v0.4s, #32, lsl 8 // 64 * 128, bias for SDOT
+ movi v1.4s, #32, lsl 8
+
+ sub v18.8b, v18.8b, v5.8b
+
+ tbl v19.16b, {v16.16b, v17.16b}, v6.16b
+ tbl v20.16b, {v17.16b, v18.16b}, v28.16b
+
+ sdot v0.4s, v16.16b, v7.4b[0]
+ sdot v0.4s, v17.16b, v7.4b[1]
+
+ sdot v1.4s, v19.16b, v7.4b[0]
+ sdot v1.4s, v20.16b, v7.4b[1]
+
+ uzp1 v0.8h, v0.8h, v1.8h
+ sqrshrun v0.8b, v0.8h, #6
+
+ fmov x8, d0
+ lsr x9, x8, #32
+ strh w8, [\dst]
+ strh w9, [\dst, \d_strd]
+ ret
+.endif
+
+ .align JUMP_ALIGN
+L(\type\()_8tap_h_hv_\isa):
+ madd \mx, \mx, w11, w9
+ madd w14, \my, w11, w10 // for HV
+ ldr q28, L(h_tbl_neon_dotprod)
+ mov w13, 0x2002 // FILTER_WEIGHT * 128 + rounding
+ sub \src, \src, #4 // src - 4
+ dup v27.4s, w13
+ ubfx w9, \mx, #7, #7
+ and \mx, \mx, #0x7F
+ ubfx w11, w14, #7, #7 // for HV
+ and w14, w14, #0x7F // for HV
+ cmp \w, #4
+ csel \mx, \mx, w9, le
+ add \xmx, x12, \xmx, lsl #3 // subpel H filter address
+ movi v24.16b, #128
+ cbz \my, L(\type\()_8tap_h_\isa)
+
+ // HV cases
+ cmp \h, #4
+ csel w14, w14, w11, le
+ sub \src, \src, \s_strd, lsl #1 // src - src_stride * 2 - 4
+ add \xmy, x12, x14, lsl #3 // subpel V filter address
+ mov x15, x30
+ ldr d7, [\xmy]
+.ifc \type, put
+ ldr q25, L(hv_tbl_neon_dotprod)
+.endif
+ sxtl v7.8h, v7.8b
+ cmp w10, SHARP1
+ b.ne L(\type\()_6tap_hv_\isa) // vertical != SHARP1
+
+ // HV 8-tap cases
+ sub \src, \src, \s_strd // src - src_stride * 3 - 4
+ cmp \w, #4
+ b.eq 40f
+.ifc \type, put
+ b.lt 20f
+.endif
+
+ // .align JUMP_ALIGN // fallthrough
+80: // HV8 - 8xN+
+ ldr q29, L(h_tbl_neon_dotprod) + 16
+ ldr q30, L(h_tbl_neon_dotprod) + 32
+ ldr d26, [\xmx]
+.ifc \type, prep
+ add \wd_strd, \w, \w
+.endif
+
+ .align LOOP_ALIGN
+81:
+ mov \lsrc, \src
+ mov \ldst, \dst
+ mov w8, \h
+
+ bl L(\type\()_hv_filter8_\isa)
+ mov v16.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v17.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v18.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v19.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v20.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v21.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+
+ .align LOOP_ALIGN
+8:
+ ldr q23, [\lsrc]
+ add \lsrc, \lsrc, \s_strd
+
+ smull v0.4s, v16.4h, v7.h[0]
+ smull2 v1.4s, v16.8h, v7.h[0]
+ mov v16.16b, v17.16b
+
+ sub v23.16b, v23.16b, v24.16b
+
+ mov v5.16b, v27.16b
+ mov v6.16b, v27.16b
+
+ smlal v0.4s, v17.4h, v7.h[1]
+ smlal2 v1.4s, v17.8h, v7.h[1]
+ mov v17.16b, v18.16b
+
+ tbl v2.16b, {v23.16b}, v28.16b
+ tbl v3.16b, {v23.16b}, v29.16b
+ tbl v4.16b, {v23.16b}, v30.16b
+
+ smlal v0.4s, v18.4h, v7.h[2]
+ smlal2 v1.4s, v18.8h, v7.h[2]
+ mov v18.16b, v19.16b
+
+ sdot v5.4s, v2.16b, v26.4b[0]
+ sdot v6.4s, v3.16b, v26.4b[0]
+
+ smlal v0.4s, v19.4h, v7.h[3]
+ smlal2 v1.4s, v19.8h, v7.h[3]
+ mov v19.16b, v20.16b
+
+ sdot v5.4s, v3.16b, v26.4b[1]
+ sdot v6.4s, v4.16b, v26.4b[1]
+
+ smlal v0.4s, v20.4h, v7.h[4]
+ smlal2 v1.4s, v20.8h, v7.h[4]
+ mov v20.16b, v21.16b
+
+ smlal v0.4s, v21.4h, v7.h[5]
+ smlal2 v1.4s, v21.8h, v7.h[5]
+.ifc \type, prep
+ uzp1 v23.8h, v5.8h, v6.8h
+.endif
+ mov v21.16b, v22.16b
+
+ smlal v0.4s, v22.4h, v7.h[6]
+ smlal2 v1.4s, v22.8h, v7.h[6]
+.ifc \type, prep
+ sshr v22.8h, v23.8h, #2
+ smlal v0.4s, v22.4h, v7.h[7]
+ smlal2 v1.4s, v22.8h, v7.h[7]
+ rshrn v0.4h, v0.4s, #6
+ rshrn2 v0.8h, v1.4s, #6
+ subs w8, w8, #1
+ st1 {v0.8h}, [\ldst], \d_strd
+ b.gt 8b
+ add \dst, \dst, #16
+.else
+ shrn v22.4h, v5.4s, #2
+ shrn2 v22.8h, v6.4s, #2
+ smlal v0.4s, v22.4h, v7.h[7]
+ smlal2 v1.4s, v22.8h, v7.h[7]
+ tbl v0.16b, {v0.16b, v1.16b}, v25.16b
+ subs w8, w8, #1
+ sqrshrun v0.8b, v0.8h, #2
+ st1 {v0.8b}, [\ldst], \d_strd
+ b.gt 8b
+ add \dst, \dst, #8
+.endif
+ add \src, \src, #8
+ subs \w, \w, #8
+ b.gt 81b
+ ret x15
+
+ .align JUMP_ALIGN
+40: // HV8 - 4xN
+ ldr s26, [\xmx, #2]
+ add \src, \src, #2
+
+ bl L(\type\()_hv_filter4_\isa)
+ mov v16.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v17.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v18.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v19.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v20.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v21.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+
+ .align LOOP_ALIGN
+4:
+ ld1 {v4.8b}, [\src], \s_strd
+
+ smull v0.4s, v16.4h, v7.h[0]
+ smlal v0.4s, v17.4h, v7.h[1]
+ mov v16.16b, v17.16b
+ mov v17.16b, v18.16b
+ sub v4.16b, v4.16b, v24.16b
+
+ smlal v0.4s, v18.4h, v7.h[2]
+ smlal v0.4s, v19.4h, v7.h[3]
+ tbl v2.16b, {v4.16b}, v28.16b
+ mov v5.16b, v27.16b
+
+ mov v18.16b, v19.16b
+ mov v19.16b, v20.16b
+
+ smlal v0.4s, v20.4h, v7.h[4]
+ smlal v0.4s, v21.4h, v7.h[5]
+
+ sdot v5.4s, v2.16b, v26.4b[0]
+ mov v20.16b, v21.16b
+ mov v21.16b, v22.16b
+.ifc \type, put
+ subs \h, \h, #1
+.endif
+ smlal v0.4s, v22.4h, v7.h[6]
+ shrn v22.4h, v5.4s, #2
+
+ smlal v0.4s, v22.4h, v7.h[7]
+.ifc \type, prep
+ rshrn v0.4h, v0.4s, #6
+ str d0, [\dst], #8
+ subs \h, \h, #1
+.else
+ tbl v0.16b, {v0.16b, v1.16b}, v25.16b
+ sqrshrun v0.8b, v0.8h, #2
+ str s0, [\dst]
+ add \dst, \dst, \d_strd
+.endif
+ b.gt 4b
+ ret x15
+
+.ifc \type, put
+ .align JUMP_ALIGN
+20: // HV8 - 2xN
+ ldr s26, [\xmx, #2]
+ add \src, \src, #2
+
+ bl L(\type\()_hv_filter4_\isa)
+ mov v16.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v17.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v18.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v19.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v20.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v21.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+
+ .align LOOP_ALIGN
+2:
+ ld1 {v4.8b}, [\src], \s_strd
+
+ smull v0.4s, v16.4h, v7.h[0]
+ smlal v0.4s, v17.4h, v7.h[1]
+ mov v16.16b, v17.16b
+ mov v17.16b, v18.16b
+ sub v4.16b, v4.16b, v24.16b
+
+ smlal v0.4s, v18.4h, v7.h[2]
+ smlal v0.4s, v19.4h, v7.h[3]
+ tbl v2.16b, {v4.16b}, v28.16b
+ mov v5.16b, v27.16b
+
+ mov v18.16b, v19.16b
+ mov v19.16b, v20.16b
+
+ smlal v0.4s, v20.4h, v7.h[4]
+ smlal v0.4s, v21.4h, v7.h[5]
+
+ sdot v5.4s, v2.16b, v26.4b[0]
+ mov v20.16b, v21.16b
+ mov v21.16b, v22.16b
+
+ subs \h, \h, #1
+ smlal v0.4s, v22.4h, v7.h[6]
+ shrn v22.4h, v5.4s, #2
+
+ smlal v0.4s, v22.4h, v7.h[7]
+ tbl v0.16b, {v0.16b, v1.16b}, v25.16b
+ sqrshrun v0.8b, v0.8h, #2
+
+ str h0, [\dst]
+ add \dst, \dst, \d_strd
+ b.gt 2b
+ ret x15
+.endif
+
+ .align JUMP_ALIGN
+L(\type\()_6tap_hv_\isa):
+ cmp \w, #4
+ b.eq 40f
+.ifc \type, put
+ b.lt 20f
+.endif
+
+ // .align JUMP_ALIGN // fallthrough
+80: // HV6 - 8xN+
+ ldr q29, L(h_tbl_neon_dotprod) + 16
+ ldr q30, L(h_tbl_neon_dotprod) + 32
+ ldr d26, [\xmx]
+.ifc \type, prep
+ add \wd_strd, \w, \w
+.endif
+
+ .align LOOP_ALIGN
+81:
+ mov \lsrc, \src
+ mov \ldst, \dst
+ mov w8, \h
+
+ bl L(\type\()_hv_filter8_\isa)
+ mov v16.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v17.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v18.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v19.16b, v22.16b
+ bl L(\type\()_hv_filter8_\isa)
+ mov v20.16b, v22.16b
+
+ .align LOOP_ALIGN
+8:
+ ldr q23, [\xmy]
+ add \xmy, \xmy, \s_strd
+
+ smull v0.4s, v16.4h, v7.h[1]
+ smull2 v1.4s, v16.8h, v7.h[1]
+ sub v23.16b, v23.16b, v24.16b
+ mov v16.16b, v17.16b
+
+ mov v5.16b, v27.16b
+ mov v6.16b, v27.16b
+
+ tbl v2.16b, {v23.16b}, v28.16b
+ tbl v3.16b, {v23.16b}, v29.16b
+
+ smlal v0.4s, v17.4h, v7.h[2]
+ smlal2 v1.4s, v17.8h, v7.h[2]
+ tbl v4.16b, {v23.16b}, v30.16b
+ mov v17.16b, v18.16b
+
+ sdot v5.4s, v2.16b, v26.4b[0]
+ sdot v6.4s, v3.16b, v26.4b[0]
+ smlal v0.4s, v18.4h, v7.h[3]
+ smlal2 v1.4s, v18.8h, v7.h[3]
+ mov v18.16b, v19.16b
+
+ sdot v5.4s, v3.16b, v26.4b[1]
+ sdot v6.4s, v4.16b, v26.4b[1]
+ smlal v0.4s, v19.4h, v7.h[4]
+ smlal2 v1.4s, v19.8h, v7.h[4]
+ mov v19.16b, v20.16b
+ uzp1 v23.8h, v5.8h, v6.8h
+
+ smlal v0.4s, v20.4h, v7.h[5]
+ smlal2 v1.4s, v20.8h, v7.h[5]
+ sshr v20.8h, v23.8h, #2
+.ifc \type, prep
+ smlal v0.4s, v20.4h, v7.h[6]
+ smlal2 v1.4s, v20.8h, v7.h[6]
+ rshrn v0.4h, v0.4s, #6
+ rshrn2 v0.8h, v1.4s, #6
+ st1 {v0.8h}, [\ldst], \d_strd
+ subs w8, w8, #1
+ b.gt 8b
+ add \dst, \dst, #16
+.else
+ subs w8, w8, #1
+ smlal v0.4s, v20.4h, v7.h[6]
+ smlal2 v1.4s, v20.8h, v7.h[6]
+ tbl v0.16b, {v0.16b, v1.16b}, v25.16b
+ sqrshrun v0.8b, v0.8h, #2
+ st1 {v0.8b}, [\ldst], \d_strd
+ b.gt 8b
+ add \dst, \dst, #8
+.endif
+ add \src, \src, #8
+ subs \w, \w, #8
+ b.gt 81b
+ ret x15
+
+ .align FUNC_ALIGN
+L(\type\()_hv_filter8_\isa):
+ ldr q4, [\lsrc]
+ add \lsrc, \lsrc, \s_strd
+ sub v4.16b, v4.16b, v24.16b
+ mov v22.16b, v27.16b
+ mov v23.16b, v27.16b
+ tbl v2.16b, {v4.16b}, v28.16b
+ tbl v3.16b, {v4.16b}, v29.16b
+ tbl v4.16b, {v4.16b}, v30.16b
+ sdot v22.4s, v2.16b, v26.4b[0]
+ sdot v22.4s, v3.16b, v26.4b[1]
+ sdot v23.4s, v3.16b, v26.4b[0]
+ sdot v23.4s, v4.16b, v26.4b[1]
+ shrn v22.4h, v22.4s, #2
+ shrn2 v22.8h, v23.4s, #2
+ ret
+
+ .align FUNC_ALIGN
+L(\type\()_hv_filter4_\isa):
+ mov v22.16b, v27.16b
+ ld1 {v4.8b}, [\src], \s_strd
+ sub v4.16b, v4.16b, v24.16b
+ tbl v2.16b, {v4.16b}, v28.16b
+ sdot v22.4s, v2.16b, v26.4b[0]
+ shrn v22.4h, v22.4s, #2
+ ret
+
+ .align JUMP_ALIGN
+40: // HV6 - 4xN
+ ldr s26, [\xmx, #2]
+ add \src, \src, #2
+
+ bl L(\type\()_hv_filter4_\isa)
+ mov v16.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v17.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v18.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v19.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v20.16b, v22.16b
+
+ .align LOOP_ALIGN
+4:
+ ld1 {v4.8b}, [\src], \s_strd
+
+ smull v0.4s, v16.4h, v7.h[1]
+ smlal v0.4s, v17.4h, v7.h[2]
+ sub v4.16b, v4.16b, v24.16b
+ mov v16.16b, v17.16b
+ mov v17.16b, v18.16b
+
+ smlal v0.4s, v18.4h, v7.h[3]
+ smlal v0.4s, v19.4h, v7.h[4]
+ tbl v2.16b, {v4.16b}, v28.16b
+ mov v5.16b, v27.16b
+
+ mov v18.16b, v19.16b
+ mov v19.16b, v20.16b
+ sdot v5.4s, v2.16b, v26.4b[0]
+
+ smlal v0.4s, v20.4h, v7.h[5]
+ shrn v20.4h, v5.4s, #2
+.ifc \type, prep
+ smlal v0.4s, v20.4h, v7.h[6]
+ rshrn v0.4h, v0.4s, #6
+ str d0, [\dst], #8
+ subs \h, \h, #1
+.else
+ subs \h, \h, #1
+ smlal v0.4s, v20.4h, v7.h[6]
+ tbl v0.16b, {v0.16b}, v25.16b
+ sqrshrun v0.8b, v0.8h, #2
+ str s0, [\dst]
+ add \dst, \dst, \d_strd
+.endif
+ b.gt 4b
+ ret x15
+
+.ifc \type, put
+ .align JUMP_ALIGN
+20: // HV6 - 2xN
+ ldr s26, [\xmx, #2]
+ add \src, \src, #2
+
+ bl L(\type\()_hv_filter4_\isa)
+ mov v16.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v17.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v18.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v19.16b, v22.16b
+ bl L(\type\()_hv_filter4_\isa)
+ mov v20.16b, v22.16b
+
+ .align LOOP_ALIGN
+2:
+ ld1 {v4.8b}, [\src], \s_strd
+
+ smull v0.4s, v16.4h, v7.h[1]
+ smlal v0.4s, v17.4h, v7.h[2]
+ sub v4.16b, v4.16b, v24.16b
+ mov v16.16b, v17.16b
+ mov v17.16b, v18.16b
+
+ smlal v0.4s, v18.4h, v7.h[3]
+ smlal v0.4s, v19.4h, v7.h[4]
+ tbl v2.16b, {v4.16b}, v28.16b
+ mov v5.16b, v27.16b
+
+ mov v18.16b, v19.16b
+ mov v19.16b, v20.16b
+ sdot v5.4s, v2.16b, v26.4b[0]
+
+ smlal v0.4s, v20.4h, v7.h[5]
+ shrn v20.4h, v5.4s, #2
+
+ subs \h, \h, #1
+ smlal v0.4s, v20.4h, v7.h[6]
+
+ tbl v0.16b, {v0.16b}, v25.16b
+ sqrshrun v0.8b, v0.8h, #2
+
+ str h0, [\dst]
+ add \dst, \dst, \d_strd
+ b.gt 2b
+ ret x15
+.endif
+
+ .align JUMP_ALIGN
+L(\type\()_8tap_h_\isa):
+ adr x9, L(\type\()_8tap_h_\isa\()_tbl)
+ ldrh w8, [x9, x8, lsl #1]
+.ifc \type, put
+ mov w10, #0x2022 // 64 * 128 + 34, bias and rounding for SDOT
+ dup v27.4s, w10
+.endif
+ sub x9, x9, x8
+ br x9
+
+.ifc \type, put
+ .align JUMP_ALIGN
+20: // H - 2xN
+ AARCH64_VALID_JUMP_TARGET
+ add \src, \src, #2
+ ldr s6, [\xmx, #2]
+
+ .align LOOP_ALIGN
+2:
+ ldr d0, [\src]
+ ldr d1, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+
+ sub v0.8b, v0.8b, v24.8b
+ sub v1.8b, v1.8b, v24.8b
+
+ mov v4.16b, v27.16b
+ mov v5.16b, v27.16b
+
+ tbl v2.16b, {v0.16b}, v28.16b
+ tbl v3.16b, {v1.16b}, v28.16b
+
+ sdot v4.4s, v2.16b, v6.4b[0]
+ sdot v5.4s, v3.16b, v6.4b[0]
+
+ uzp1 v4.8h, v4.8h, v5.8h
+ sqshrun v4.8b, v4.8h, #6
+
+ subs \h, \h, #2
+ fmov x8, d4
+ lsr x9, x8, #32
+ strh w8, [\dst]
+ strh w9, [\dst, \d_strd]
+ add \dst, \dst, \d_strd, lsl #1
+ b.gt 2b
+ ret
+
+.endif
+
+ .align JUMP_ALIGN
+40: // H - 4xN
+ AARCH64_VALID_JUMP_TARGET
+ add \src, \src, #2
+ ldr s26, [\xmx, #2]
+
+ .align LOOP_ALIGN
+4:
+ ldr d0, [\src]
+ ldr d1, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+
+ sub v0.8b, v0.8b, v24.8b
+ sub v1.8b, v1.8b, v24.8b
+
+ mov v4.16b, v27.16b
+ mov v5.16b, v27.16b
+
+ tbl v2.16b, {v0.16b}, v28.16b
+ tbl v3.16b, {v1.16b}, v28.16b
+
+ sdot v4.4s, v2.16b, v26.4b[0]
+ sdot v5.4s, v3.16b, v26.4b[0]
+.ifc \type, prep
+ subs \h, \h, #2
+ shrn v4.4h, v4.4s, #2
+ shrn2 v4.8h, v5.4s, #2
+ str q4, [\dst], #16
+.else
+ uzp1 v4.8h, v4.8h, v5.8h
+ sqshrun v4.8b, v4.8h, #6
+ subs \h, \h, #2
+ fmov x8, d4
+ lsr x9, x8, #32
+ str w8, [\dst]
+ str w9, [\dst, \d_strd]
+ add \dst, \dst, \d_strd, lsl #1
+.endif
+ b.gt 4b
+ ret
+
+ .align JUMP_ALIGN
+80: // H - 8xN
+ AARCH64_VALID_JUMP_TARGET
+ ldr q29, L(h_tbl_neon_dotprod) + 16
+ ldr q30, L(h_tbl_neon_dotprod) + 32
+ ldr d26, [\xmx]
+
+ .align LOOP_ALIGN
+8:
+ ldr q0, [\src]
+ ldr q16, [\src, \s_strd]
+ add \src, \src, \s_strd, lsl #1
+
+ sub v0.16b, v0.16b, v24.16b
+ sub v16.16b, v16.16b, v24.16b
+
+ mov v4.16b, v27.16b
+ mov v5.16b, v27.16b
+ mov v20.16b, v27.16b
+ mov v21.16b, v27.16b
+
+ tbl v1.16b, {v0.16b}, v28.16b
+ tbl v2.16b, {v0.16b}, v29.16b
+ tbl v3.16b, {v0.16b}, v30.16b
+ tbl v17.16b, {v16.16b}, v28.16b
+ tbl v18.16b, {v16.16b}, v29.16b
+ tbl v19.16b, {v16.16b}, v30.16b
+
+ sdot v4.4s, v1.16b, v26.4b[0]
+ sdot v5.4s, v2.16b, v26.4b[0]
+ sdot v20.4s, v17.16b, v26.4b[0]
+ sdot v21.4s, v18.16b, v26.4b[0]
+ sdot v4.4s, v2.16b, v26.4b[1]
+ sdot v5.4s, v3.16b, v26.4b[1]
+ sdot v20.4s, v18.16b, v26.4b[1]
+ sdot v21.4s, v19.16b, v26.4b[1]
+
+ uzp1 v4.8h, v4.8h, v5.8h
+ uzp1 v20.8h, v20.8h, v21.8h
+.ifc \type, prep
+ sshr v4.8h, v4.8h, #2
+ sshr v20.8h, v20.8h, #2
+ subs \h, \h, #2
+ stp q4, q20, [\dst], #32
+.else
+ sqshrun v4.8b, v4.8h, #6
+ sqshrun v20.8b, v20.8h, #6
+ subs \h, \h, #2
+ str d4, [\dst]
+ str d20, [\dst, \d_strd]
+ add \dst, \dst, \d_strd, lsl #1
+.endif
+ b.gt 8b
+ ret
+
+ .align JUMP_ALIGN
+160: // H - 16xN
+ AARCH64_VALID_JUMP_TARGET
+ ldr q29, L(h_tbl_neon_dotprod) + 16
+ ldr q30, L(h_tbl_neon_dotprod) + 32
+ ldr q31, L(h_tbl_neon_dotprod) + 48
+ ldr d26, [\xmx]
+
+ .align LOOP_ALIGN
+16:
+ ldp q16, q17, [\src]
+ add \src, \src, \s_strd
+
+ sub v16.16b, v16.16b, v24.16b
+ sub v17.16b, v17.16b, v24.16b
+
+ mov v6.16b, v27.16b
+ mov v7.16b, v27.16b
+ mov v22.16b, v27.16b
+ mov v23.16b, v27.16b
+
+ tbl v0.16b, {v16.16b}, v28.16b
+ tbl v1.16b, {v16.16b}, v29.16b
+ tbl v2.16b, {v16.16b}, v30.16b
+ tbl v3.16b, {v16.16b, v17.16b}, v31.16b
+ tbl v4.16b, {v17.16b}, v28.16b
+
+ sdot v6.4s, v0.16b, v26.4b[0]
+ sdot v7.4s, v1.16b, v26.4b[0]
+ sdot v22.4s, v2.16b, v26.4b[0]
+ sdot v23.4s, v3.16b, v26.4b[0]
+ sdot v6.4s, v1.16b, v26.4b[1]
+ sdot v7.4s, v2.16b, v26.4b[1]
+ sdot v22.4s, v3.16b, v26.4b[1]
+ sdot v23.4s, v4.16b, v26.4b[1]
+
+ uzp1 v6.8h, v6.8h, v7.8h
+ uzp1 v22.8h, v22.8h, v23.8h
+.ifc \type, prep
+ sshr v6.8h, v6.8h, #2
+ sshr v22.8h, v22.8h, #2
+ subs \h, \h, #1
+ stp q6, q22, [\dst], #32
+.else
+ sqshrun v6.8b, v6.8h, #6
+ sqshrun2 v6.16b, v22.8h, #6
+ subs \h, \h, #1
+ str q6, [\dst]
+ add \dst, \dst, \d_strd
+.endif
+ b.gt 16b
+ ret
+
+ .align JUMP_ALIGN
+320: // H - 32xN+
+640:
+1280:
+ AARCH64_VALID_JUMP_TARGET
+ ldr q29, L(h_tbl_neon_dotprod) + 16
+ ldr q30, L(h_tbl_neon_dotprod) + 32
+ ldr q31, L(h_tbl_neon_dotprod) + 48
+ ldr d26, [\xmx]
+.ifc \type, put
+ sub \d_strd, \d_strd, \w, uxtw
+.endif
+ sub \s_strd, \s_strd, \w, uxtw
+ mov w8, \w
+
+ .align LOOP_ALIGN
+32:
+ ldp q16, q17, [\src], #16
+
+ sub v16.16b, v16.16b, v24.16b
+ sub v17.16b, v17.16b, v24.16b
+
+ mov v6.16b, v27.16b
+ mov v7.16b, v27.16b
+ mov v22.16b, v27.16b
+ mov v23.16b, v27.16b
+
+ tbl v0.16b, {v16.16b}, v28.16b
+ tbl v1.16b, {v16.16b}, v29.16b
+ tbl v2.16b, {v16.16b}, v30.16b
+ tbl v3.16b, {v16.16b, v17.16b}, v31.16b
+ tbl v4.16b, {v17.16b}, v28.16b
+
+ sdot v6.4s, v0.16b, v26.4b[0]
+ sdot v7.4s, v1.16b, v26.4b[0]
+ sdot v22.4s, v2.16b, v26.4b[0]
+ sdot v23.4s, v3.16b, v26.4b[0]
+ sdot v6.4s, v1.16b, v26.4b[1]
+ sdot v7.4s, v2.16b, v26.4b[1]
+ sdot v22.4s, v3.16b, v26.4b[1]
+ sdot v23.4s, v4.16b, v26.4b[1]
+
+ uzp1 v6.8h, v6.8h, v7.8h
+ uzp1 v22.8h, v22.8h, v23.8h
+.ifc \type, prep
+ sshr v6.8h, v6.8h, #2
+ sshr v22.8h, v22.8h, #2
+ subs w8, w8, #16
+ stp q6, q22, [\dst], #32
+.else
+ sqshrun v6.8b, v6.8h, #6
+ sqshrun2 v6.16b, v22.8h, #6
+ subs w8, w8, #16
+ str q6, [\dst], #16
+.endif
+ b.gt 32b
+
+ add \src, \src, \s_strd
+.ifc \type, put
+ add \dst, \dst, \d_strd
+.endif
+ mov w8, \w
+ subs \h, \h, #1
+ b.gt 32b
+ ret
+
+L(\type\()_8tap_h_\isa\()_tbl):
+ .hword (L(\type\()_8tap_h_\isa\()_tbl) - 1280b)
+ .hword (L(\type\()_8tap_h_\isa\()_tbl) - 640b)
+ .hword (L(\type\()_8tap_h_\isa\()_tbl) - 320b)
+ .hword (L(\type\()_8tap_h_\isa\()_tbl) - 160b)
+ .hword (L(\type\()_8tap_h_\isa\()_tbl) - 80b)
+ .hword (L(\type\()_8tap_h_\isa\()_tbl) - 40b)
+.ifc \type, put
+ .hword (L(\type\()_8tap_h_\isa\()_tbl) - 20b)
+.endif
+endfunc
+.endm
+
+// dst(x0), d_strd(x7), src(x1), s_strd(x2), w(w3), h(w4), mx(w5), my(w6)
+// xmx(x5), xmy(x6), ldst(x5), lsrc(x6), wd_strd(w7)
+filter_8tap_fn prep, neon_dotprod, x0, x7, x1, x2, w3, w4, w5, w6, x5, x6, x5, x6, w7
+
+// dst(x0) d_strd(x1) src(x2) s_strd(x3) w(w4) h(w5) mx(w6) my(w7)
+// xmx(x6), xmy(x7), ldst(x6), lsrc(x7), wd_strd(w1)
+filter_8tap_fn put, neon_dotprod, x0, x1, x2, x3, w4, w5, w6, w7, x6, x7, x6, x7, w1
+
+DISABLE_DOTPROD
+#endif // HAVE_DOTPROD
diff --git a/third_party/dav1d/src/arm/64/msac.S b/third_party/dav1d/src/arm/64/msac.S
index 7bef9243fb..9033072a82 100644
--- a/third_party/dav1d/src/arm/64/msac.S
+++ b/third_party/dav1d/src/arm/64/msac.S
@@ -288,10 +288,8 @@ function msac_decode_hi_tok_neon, export=1
mvni v30.4h, #0x3f // 0xffc0
ldrh w9, [x1, #6] // count = cdf[n_symbols]
ld1r {v3.4h}, [x16] // rng
- movrel x16, bits
ld1 {v29.4h}, [x17] // EC_MIN_PROB * (n_symbols - ret)
add x17, x0, #DIF + 6
- ld1 {v16.8h}, [x16]
mov w13, #-24
and v17.8b, v0.8b, v30.8b // cdf & 0xffc0
ldr w10, [x0, #ALLOW_UPDATE_CDF]
@@ -305,30 +303,27 @@ function msac_decode_hi_tok_neon, export=1
add v4.4h, v17.4h, v29.4h // v = cdf + EC_MIN_PROB * (n_symbols - ret)
add v4.4h, v6.4h, v4.4h // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret)
str h3, [sp, #14] // store original u = s->rng
- cmhs v2.8h, v1.8h, v4.8h // c >= v
+ cmhs v2.4h, v1.4h, v4.4h // c >= v
str q4, [sp, #16] // store v values to allow indexed access
- and v6.16b, v2.16b, v16.16b // One bit per halfword set in the mask
- addv h6, v6.8h // Aggregate mask bits
- umov w3, v6.h[0]
+ addv h6, v2.4h // -4 + ret
add w13, w13, #5
- rbit w3, w3
+ smov w15, v6.h[0]
add x8, sp, #16
- clz w15, w3 // ret
+ add w15, w15, #4 // ret
cbz w10, 2f
// update_cdf
- movi v5.8b, #0xff
+ sub v5.4h, v0.4h, v2.4h // cdf[i] + (i >= val ? 1 : 0)
mov w4, #-5
- urhadd v4.4h, v5.4h, v2.4h // i >= val ? -1 : 32768
+ orr v2.4h, #0x80, lsl #8 // i >= val ? -1 : 32768
sub w4, w4, w9, lsr #4 // -((count >> 4) + 5)
- sub v4.4h, v4.4h, v0.4h // (32768 - cdf[i]) or (-1 - cdf[i])
+ sub v4.4h, v2.4h, v0.4h // (32768 - cdf[i]) or (-1 - cdf[i])
dup v6.4h, w4 // -rate
sub w9, w9, w9, lsr #5 // count - (count == 32)
- sub v0.4h, v0.4h, v2.4h // cdf + (i >= val ? 1 : 0)
sshl v4.4h, v4.4h, v6.4h // ({32768,-1} - cdf[i]) >> rate
add w9, w9, #1 // count + (count < 32)
- add v0.4h, v0.4h, v4.4h // cdf + (32768 - cdf[i]) >> rate
+ add v0.4h, v5.4h, v4.4h // cdf[i] + (32768 - cdf[i]) >> rate
st1 {v0.4h}, [x1]
and v17.8b, v0.8b, v30.8b // cdf & 0xffc0
strh w9, [x1, #6]
diff --git a/third_party/dav1d/src/arm/itx.h b/third_party/dav1d/src/arm/itx.h
index 17234e027a..2a58a31322 100644
--- a/third_party/dav1d/src/arm/itx.h
+++ b/third_party/dav1d/src/arm/itx.h
@@ -28,34 +28,6 @@
#include "src/cpu.h"
#include "src/itx.h"
-#define decl_itx2_fns(w, h, opt) \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_identity_##w##x##h, opt))
-
-#define decl_itx12_fns(w, h, opt) \
-decl_itx2_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_dct_##w##x##h, opt))
-
-#define decl_itx16_fns(w, h, opt) \
-decl_itx12_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_flipadst_##w##x##h, opt))
-
-#define decl_itx17_fns(w, h, opt) \
-decl_itx16_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_wht_wht_##w##x##h, opt))
-
decl_itx17_fns( 4, 4, neon);
decl_itx16_fns( 4, 8, neon);
decl_itx16_fns( 4, 16, neon);
@@ -78,41 +50,6 @@ decl_itx_fn(BF(dav1d_inv_txfm_add_dct_dct_64x32, neon));
decl_itx_fn(BF(dav1d_inv_txfm_add_dct_dct_64x64, neon));
static ALWAYS_INLINE void itx_dsp_init_arm(Dav1dInvTxfmDSPContext *const c, int bpc) {
-#define assign_itx_fn(pfx, w, h, type, type_enum, ext) \
- c->itxfm_add[pfx##TX_##w##X##h][type_enum] = \
- BF(dav1d_inv_txfm_add_##type##_##w##x##h, ext)
-
-#define assign_itx1_fn(pfx, w, h, ext) \
- assign_itx_fn(pfx, w, h, dct_dct, DCT_DCT, ext)
-
-#define assign_itx2_fn(pfx, w, h, ext) \
- assign_itx1_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, identity_identity, IDTX, ext)
-
-#define assign_itx12_fn(pfx, w, h, ext) \
- assign_itx2_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, dct_adst, ADST_DCT, ext); \
- assign_itx_fn(pfx, w, h, dct_flipadst, FLIPADST_DCT, ext); \
- assign_itx_fn(pfx, w, h, dct_identity, H_DCT, ext); \
- assign_itx_fn(pfx, w, h, adst_dct, DCT_ADST, ext); \
- assign_itx_fn(pfx, w, h, adst_adst, ADST_ADST, ext); \
- assign_itx_fn(pfx, w, h, adst_flipadst, FLIPADST_ADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_dct, DCT_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_adst, ADST_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_flipadst, FLIPADST_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, identity_dct, V_DCT, ext)
-
-#define assign_itx16_fn(pfx, w, h, ext) \
- assign_itx12_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, adst_identity, H_ADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_identity, H_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, identity_adst, V_ADST, ext); \
- assign_itx_fn(pfx, w, h, identity_flipadst, V_FLIPADST, ext)
-
-#define assign_itx17_fn(pfx, w, h, ext) \
- assign_itx16_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, wht_wht, WHT_WHT, ext)
-
const unsigned flags = dav1d_get_cpu_flags();
if (!(flags & DAV1D_ARM_CPU_FLAG_NEON)) return;
diff --git a/third_party/dav1d/src/arm/mc.h b/third_party/dav1d/src/arm/mc.h
index 06cd533a9b..7e57fd37cb 100644
--- a/third_party/dav1d/src/arm/mc.h
+++ b/third_party/dav1d/src/arm/mc.h
@@ -30,26 +30,40 @@
#include "src/mc.h"
#include "src/cpu.h"
-decl_mc_fn(BF(dav1d_put_8tap_regular, neon));
-decl_mc_fn(BF(dav1d_put_8tap_regular_smooth, neon));
-decl_mc_fn(BF(dav1d_put_8tap_regular_sharp, neon));
-decl_mc_fn(BF(dav1d_put_8tap_smooth, neon));
-decl_mc_fn(BF(dav1d_put_8tap_smooth_regular, neon));
-decl_mc_fn(BF(dav1d_put_8tap_smooth_sharp, neon));
-decl_mc_fn(BF(dav1d_put_8tap_sharp, neon));
-decl_mc_fn(BF(dav1d_put_8tap_sharp_regular, neon));
-decl_mc_fn(BF(dav1d_put_8tap_sharp_smooth, neon));
-decl_mc_fn(BF(dav1d_put_bilin, neon));
+#define decl_8tap_gen(decl_name, fn_name, opt) \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_regular, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_regular_smooth, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_regular_sharp, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_smooth_regular, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_smooth, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_smooth_sharp, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_sharp_regular, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_sharp_smooth, opt)); \
+ decl_##decl_name##_fn(BF(dav1d_##fn_name##_8tap_sharp, opt))
+
+#define decl_8tap_fns(opt) \
+ decl_8tap_gen(mc, put, opt); \
+ decl_8tap_gen(mct, prep, opt)
+
+#define init_8tap_gen(name, opt) \
+ init_##name##_fn(FILTER_2D_8TAP_REGULAR, 8tap_regular, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_REGULAR_SMOOTH, 8tap_regular_smooth, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_REGULAR_SHARP, 8tap_regular_sharp, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_SMOOTH_REGULAR, 8tap_smooth_regular, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_SMOOTH, 8tap_smooth, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_SMOOTH_SHARP, 8tap_smooth_sharp, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_SHARP_REGULAR, 8tap_sharp_regular, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_SHARP_SMOOTH, 8tap_sharp_smooth, opt); \
+ init_##name##_fn(FILTER_2D_8TAP_SHARP, 8tap_sharp, opt)
+
+#define init_8tap_fns(opt) \
+ init_8tap_gen(mc, opt); \
+ init_8tap_gen(mct, opt)
+
+decl_8tap_fns(neon);
+decl_8tap_fns(neon_dotprod);
-decl_mct_fn(BF(dav1d_prep_8tap_regular, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_regular_smooth, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_regular_sharp, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_smooth, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_smooth_regular, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_smooth_sharp, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_sharp, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_sharp_regular, neon));
-decl_mct_fn(BF(dav1d_prep_8tap_sharp_smooth, neon));
+decl_mc_fn(BF(dav1d_put_bilin, neon));
decl_mct_fn(BF(dav1d_prep_bilin, neon));
decl_avg_fn(BF(dav1d_avg, neon));
@@ -77,27 +91,10 @@ static ALWAYS_INLINE void mc_dsp_init_arm(Dav1dMCDSPContext *const c) {
if (!(flags & DAV1D_ARM_CPU_FLAG_NEON)) return;
- init_mc_fn (FILTER_2D_8TAP_REGULAR, 8tap_regular, neon);
- init_mc_fn (FILTER_2D_8TAP_REGULAR_SMOOTH, 8tap_regular_smooth, neon);
- init_mc_fn (FILTER_2D_8TAP_REGULAR_SHARP, 8tap_regular_sharp, neon);
- init_mc_fn (FILTER_2D_8TAP_SMOOTH_REGULAR, 8tap_smooth_regular, neon);
- init_mc_fn (FILTER_2D_8TAP_SMOOTH, 8tap_smooth, neon);
- init_mc_fn (FILTER_2D_8TAP_SMOOTH_SHARP, 8tap_smooth_sharp, neon);
- init_mc_fn (FILTER_2D_8TAP_SHARP_REGULAR, 8tap_sharp_regular, neon);
- init_mc_fn (FILTER_2D_8TAP_SHARP_SMOOTH, 8tap_sharp_smooth, neon);
- init_mc_fn (FILTER_2D_8TAP_SHARP, 8tap_sharp, neon);
- init_mc_fn (FILTER_2D_BILINEAR, bilin, neon);
-
- init_mct_fn(FILTER_2D_8TAP_REGULAR, 8tap_regular, neon);
- init_mct_fn(FILTER_2D_8TAP_REGULAR_SMOOTH, 8tap_regular_smooth, neon);
- init_mct_fn(FILTER_2D_8TAP_REGULAR_SHARP, 8tap_regular_sharp, neon);
- init_mct_fn(FILTER_2D_8TAP_SMOOTH_REGULAR, 8tap_smooth_regular, neon);
- init_mct_fn(FILTER_2D_8TAP_SMOOTH, 8tap_smooth, neon);
- init_mct_fn(FILTER_2D_8TAP_SMOOTH_SHARP, 8tap_smooth_sharp, neon);
- init_mct_fn(FILTER_2D_8TAP_SHARP_REGULAR, 8tap_sharp_regular, neon);
- init_mct_fn(FILTER_2D_8TAP_SHARP_SMOOTH, 8tap_sharp_smooth, neon);
- init_mct_fn(FILTER_2D_8TAP_SHARP, 8tap_sharp, neon);
- init_mct_fn(FILTER_2D_BILINEAR, bilin, neon);
+ init_8tap_fns(neon);
+
+ init_mc_fn (FILTER_2D_BILINEAR, bilin, neon);
+ init_mct_fn(FILTER_2D_BILINEAR, bilin, neon);
c->avg = BF(dav1d_avg, neon);
c->w_avg = BF(dav1d_w_avg, neon);
@@ -111,4 +108,12 @@ static ALWAYS_INLINE void mc_dsp_init_arm(Dav1dMCDSPContext *const c) {
c->warp8x8 = BF(dav1d_warp_affine_8x8, neon);
c->warp8x8t = BF(dav1d_warp_affine_8x8t, neon);
c->emu_edge = BF(dav1d_emu_edge, neon);
+
+#if ARCH_AARCH64
+#if HAVE_DOTPROD && BITDEPTH == 8
+ if (!(flags & DAV1D_ARM_CPU_FLAG_DOTPROD)) return;
+
+ init_8tap_fns(neon_dotprod);
+#endif // HAVE_DOTPROD && BITDEPTH == 8
+#endif // ARCH_AARCH64
}
diff --git a/third_party/dav1d/src/cdf.c b/third_party/dav1d/src/cdf.c
index e0f2132e00..d9721dad46 100644
--- a/third_party/dav1d/src/cdf.c
+++ b/third_party/dav1d/src/cdf.c
@@ -65,631 +65,638 @@
#define CDF15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \
CDF1(a), CDF14(b,c,d,e,f,g,h,i,j,k,l,m,n,o)
-static const CdfModeContext av1_default_cdf = {
- .y_mode = {
- { CDF12(22801, 23489, 24293, 24756, 25601, 26123,
- 26606, 27418, 27945, 29228, 29685, 30349) },
- { CDF12(18673, 19845, 22631, 23318, 23950, 24649,
- 25527, 27364, 28152, 29701, 29984, 30852) },
- { CDF12(19770, 20979, 23396, 23939, 24241, 24654,
- 25136, 27073, 27830, 29360, 29730, 30659) },
- { CDF12(20155, 21301, 22838, 23178, 23261, 23533,
- 23703, 24804, 25352, 26575, 27016, 28049) },
- }, .use_filter_intra = {
- [BS_4x4] = { CDF1( 4621) },
- [BS_4x8] = { CDF1( 6743) },
- [BS_8x4] = { CDF1( 5893) },
- [BS_8x8] = { CDF1( 7866) },
- [BS_8x16] = { CDF1(12551) },
- [BS_16x8] = { CDF1( 9394) },
- [BS_16x16] = { CDF1(12408) },
- [BS_16x32] = { CDF1(14301) },
- [BS_32x16] = { CDF1(12756) },
- [BS_32x32] = { CDF1(22343) },
- [BS_32x64] = { CDF1(16384) },
- [BS_64x32] = { CDF1(16384) },
- [BS_64x64] = { CDF1(16384) },
- [BS_64x128] = { CDF1(16384) },
- [BS_128x64] = { CDF1(16384) },
- [BS_128x128] = { CDF1(16384) },
- [BS_4x16] = { CDF1(12770) },
- [BS_16x4] = { CDF1(10368) },
- [BS_8x32] = { CDF1(20229) },
- [BS_32x8] = { CDF1(18101) },
- [BS_16x64] = { CDF1(16384) },
- [BS_64x16] = { CDF1(16384) },
- }, .filter_intra = {
- CDF4(8949, 12776, 17211, 29558),
- }, .uv_mode = {
- {
- { CDF12(22631, 24152, 25378, 25661, 25986, 26520,
- 27055, 27923, 28244, 30059, 30941, 31961) },
- { CDF12( 9513, 26881, 26973, 27046, 27118, 27664,
- 27739, 27824, 28359, 29505, 29800, 31796) },
- { CDF12( 9845, 9915, 28663, 28704, 28757, 28780,
- 29198, 29822, 29854, 30764, 31777, 32029) },
- { CDF12(13639, 13897, 14171, 25331, 25606, 25727,
- 25953, 27148, 28577, 30612, 31355, 32493) },
- { CDF12( 9764, 9835, 9930, 9954, 25386, 27053,
- 27958, 28148, 28243, 31101, 31744, 32363) },
- { CDF12(11825, 13589, 13677, 13720, 15048, 29213,
- 29301, 29458, 29711, 31161, 31441, 32550) },
- { CDF12(14175, 14399, 16608, 16821, 17718, 17775,
- 28551, 30200, 30245, 31837, 32342, 32667) },
- { CDF12(12885, 13038, 14978, 15590, 15673, 15748,
- 16176, 29128, 29267, 30643, 31961, 32461) },
- { CDF12(12026, 13661, 13874, 15305, 15490, 15726,
- 15995, 16273, 28443, 30388, 30767, 32416) },
- { CDF12(19052, 19840, 20579, 20916, 21150, 21467,
- 21885, 22719, 23174, 28861, 30379, 32175) },
- { CDF12(18627, 19649, 20974, 21219, 21492, 21816,
- 22199, 23119, 23527, 27053, 31397, 32148) },
- { CDF12(17026, 19004, 19997, 20339, 20586, 21103,
- 21349, 21907, 22482, 25896, 26541, 31819) },
- { CDF12(12124, 13759, 14959, 14992, 15007, 15051,
- 15078, 15166, 15255, 15753, 16039, 16606) },
- }, {
- { CDF13(10407, 11208, 12900, 13181, 13823, 14175, 14899,
- 15656, 15986, 20086, 20995, 22455, 24212) },
- { CDF13( 4532, 19780, 20057, 20215, 20428, 21071, 21199,
- 21451, 22099, 24228, 24693, 27032, 29472) },
- { CDF13( 5273, 5379, 20177, 20270, 20385, 20439, 20949,
- 21695, 21774, 23138, 24256, 24703, 26679) },
- { CDF13( 6740, 7167, 7662, 14152, 14536, 14785, 15034,
- 16741, 18371, 21520, 22206, 23389, 24182) },
- { CDF13( 4987, 5368, 5928, 6068, 19114, 20315, 21857,
- 22253, 22411, 24911, 25380, 26027, 26376) },
- { CDF13( 5370, 6889, 7247, 7393, 9498, 21114, 21402,
- 21753, 21981, 24780, 25386, 26517, 27176) },
- { CDF13( 4816, 4961, 7204, 7326, 8765, 8930, 20169,
- 20682, 20803, 23188, 23763, 24455, 24940) },
- { CDF13( 6608, 6740, 8529, 9049, 9257, 9356, 9735,
- 18827, 19059, 22336, 23204, 23964, 24793) },
- { CDF13( 5998, 7419, 7781, 8933, 9255, 9549, 9753,
- 10417, 18898, 22494, 23139, 24764, 25989) },
- { CDF13(10660, 11298, 12550, 12957, 13322, 13624, 14040,
- 15004, 15534, 20714, 21789, 23443, 24861) },
- { CDF13(10522, 11530, 12552, 12963, 13378, 13779, 14245,
- 15235, 15902, 20102, 22696, 23774, 25838) },
- { CDF13(10099, 10691, 12639, 13049, 13386, 13665, 14125,
- 15163, 15636, 19676, 20474, 23519, 25208) },
- { CDF13( 3144, 5087, 7382, 7504, 7593, 7690, 7801,
- 8064, 8232, 9248, 9875, 10521, 29048) },
- },
- }, .angle_delta = {
- { CDF6( 2180, 5032, 7567, 22776, 26989, 30217) },
- { CDF6( 2301, 5608, 8801, 23487, 26974, 30330) },
- { CDF6( 3780, 11018, 13699, 19354, 23083, 31286) },
- { CDF6( 4581, 11226, 15147, 17138, 21834, 28397) },
- { CDF6( 1737, 10927, 14509, 19588, 22745, 28823) },
- { CDF6( 2664, 10176, 12485, 17650, 21600, 30495) },
- { CDF6( 2240, 11096, 15453, 20341, 22561, 28917) },
- { CDF6( 3605, 10428, 12459, 17676, 21244, 30655) },
- }, .filter = {
- {
- { CDF2(31935, 32720) }, { CDF2( 5568, 32719) },
- { CDF2( 422, 2938) }, { CDF2(28244, 32608) },
- { CDF2(31206, 31953) }, { CDF2( 4862, 32121) },
- { CDF2( 770, 1152) }, { CDF2(20889, 25637) },
- }, {
- { CDF2(31910, 32724) }, { CDF2( 4120, 32712) },
- { CDF2( 305, 2247) }, { CDF2(27403, 32636) },
- { CDF2(31022, 32009) }, { CDF2( 2963, 32093) },
- { CDF2( 601, 943) }, { CDF2(14969, 21398) },
- },
- }, .newmv_mode = {
- { CDF1(24035) }, { CDF1(16630) }, { CDF1(15339) },
- { CDF1( 8386) }, { CDF1(12222) }, { CDF1( 4676) },
- }, .globalmv_mode = {
- { CDF1( 2175) }, { CDF1( 1054) },
- }, .refmv_mode = {
- { CDF1(23974) }, { CDF1(24188) }, { CDF1(17848) },
- { CDF1(28622) }, { CDF1(24312) }, { CDF1(19923) },
- }, .drl_bit = {
- { CDF1(13104) }, { CDF1(24560) }, { CDF1(18945) },
- }, .comp_inter_mode = {
- { CDF7( 7760, 13823, 15808, 17641, 19156, 20666, 26891) },
- { CDF7(10730, 19452, 21145, 22749, 24039, 25131, 28724) },
- { CDF7(10664, 20221, 21588, 22906, 24295, 25387, 28436) },
- { CDF7(13298, 16984, 20471, 24182, 25067, 25736, 26422) },
- { CDF7(18904, 23325, 25242, 27432, 27898, 28258, 30758) },
- { CDF7(10725, 17454, 20124, 22820, 24195, 25168, 26046) },
- { CDF7(17125, 24273, 25814, 27492, 28214, 28704, 30592) },
- { CDF7(13046, 23214, 24505, 25942, 27435, 28442, 29330) },
- }, .intra = {
- { CDF1( 806) }, { CDF1(16662) }, { CDF1(20186) },
- { CDF1(26538) },
- }, .comp = {
- { CDF1(26828) }, { CDF1(24035) }, { CDF1(12031) },
- { CDF1(10640) }, { CDF1( 2901) },
- }, .comp_dir = {
- { CDF1( 1198) }, { CDF1( 2070) }, { CDF1( 9166) },
- { CDF1( 7499) }, { CDF1(22475) },
- }, .jnt_comp = {
- { CDF1(18244) }, { CDF1(12865) }, { CDF1( 7053) },
- { CDF1(13259) }, { CDF1( 9334) }, { CDF1( 4644) },
- }, .mask_comp = {
- { CDF1(26607) }, { CDF1(22891) }, { CDF1(18840) },
- { CDF1(24594) }, { CDF1(19934) }, { CDF1(22674) },
- }, .wedge_comp = {
- { CDF1(23431) }, { CDF1(13171) }, { CDF1(11470) },
- { CDF1( 9770) }, { CDF1( 9100) }, { CDF1( 8233) },
- { CDF1( 6172) }, { CDF1(11820) }, { CDF1( 7701) },
- }, .wedge_idx = {
- { CDF15( 2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094,
- 20359, 22362, 24127, 25702, 27752, 29450, 31171) },
- { CDF15( 806, 3266, 6005, 6738, 7218, 7367, 7771, 14588,
- 16323, 17367, 18452, 19422, 22839, 26127, 29629) },
- { CDF15( 2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357,
- 17939, 21332, 24520, 27470, 29456, 30529, 31656) },
- { CDF15( 1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144,
- 19163, 20961, 22884, 24471, 26719, 28714, 30877) },
- { CDF15( 1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624,
- 15369, 16730, 18114, 19313, 22521, 26012, 29550) },
- { CDF15( 2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124,
- 17270, 20533, 23434, 25972, 27944, 29570, 31416) },
- { CDF15( 1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944,
- 20638, 22038, 23963, 25311, 26988, 28766, 31012) },
- { CDF15( 154, 987, 1925, 2051, 2088, 2111, 2151, 23033,
- 23703, 24284, 24985, 25684, 27259, 28883, 30911) },
- { CDF15( 1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016,
- 22935, 25057, 27251, 29173, 30089, 30960, 31933) },
- }, .interintra = {
- { CDF1(16384) }, { CDF1(26887) }, { CDF1(27597) },
- { CDF1(30237) },
- }, .interintra_mode = {
- { CDF3(8192, 16384, 24576) },
- { CDF3(1875, 11082, 27332) },
- { CDF3(2473, 9996, 26388) },
- { CDF3(4238, 11537, 25926) },
- }, .interintra_wedge = {
- { CDF1(20036) }, { CDF1(24957) }, { CDF1(26704) },
- { CDF1(27530) }, { CDF1(29564) }, { CDF1(29444) },
- { CDF1(26872) },
- }, .ref = {
- { { CDF1( 4897) }, { CDF1(16973) }, { CDF1(29744) } },
- { { CDF1( 1555) }, { CDF1(16751) }, { CDF1(30279) } },
- { { CDF1( 4236) }, { CDF1(19647) }, { CDF1(31194) } },
- { { CDF1( 8650) }, { CDF1(24773) }, { CDF1(31895) } },
- { { CDF1( 904) }, { CDF1(11014) }, { CDF1(26875) } },
- { { CDF1( 1444) }, { CDF1(15087) }, { CDF1(30304) } },
- }, .comp_fwd_ref = {
- { { CDF1( 4946) }, { CDF1(19891) }, { CDF1(30731) } },
- { { CDF1( 9468) }, { CDF1(22441) }, { CDF1(31059) } },
- { { CDF1( 1503) }, { CDF1(15160) }, { CDF1(27544) } },
- }, .comp_bwd_ref = {
- { { CDF1( 2235) }, { CDF1(17182) }, { CDF1(30606) } },
- { { CDF1( 1423) }, { CDF1(15175) }, { CDF1(30489) } },
- }, .comp_uni_ref = {
- { { CDF1( 5284) }, { CDF1(23152) }, { CDF1(31774) } },
- { { CDF1( 3865) }, { CDF1(14173) }, { CDF1(25120) } },
- { { CDF1( 3128) }, { CDF1(15270) }, { CDF1(26710) } },
- }, .txsz = {
- {
- { CDF1(19968) }, { CDF1(19968) }, { CDF1(24320) },
- }, {
- { CDF2(12272, 30172) }, { CDF2(12272, 30172) },
- { CDF2(18677, 30848) },
- }, {
- { CDF2(12986, 15180) }, { CDF2(12986, 15180) },
- { CDF2(24302, 25602) },
- }, {
- { CDF2( 5782, 11475) }, { CDF2( 5782, 11475) },
- { CDF2(16803, 22759) },
- },
- }, .txpart = {
- { { CDF1(28581) }, { CDF1(23846) }, { CDF1(20847) } },
- { { CDF1(24315) }, { CDF1(18196) }, { CDF1(12133) } },
- { { CDF1(18791) }, { CDF1(10887) }, { CDF1(11005) } },
- { { CDF1(27179) }, { CDF1(20004) }, { CDF1(11281) } },
- { { CDF1(26549) }, { CDF1(19308) }, { CDF1(14224) } },
- { { CDF1(28015) }, { CDF1(21546) }, { CDF1(14400) } },
- { { CDF1(28165) }, { CDF1(22401) }, { CDF1(16088) } },
- }, .txtp_inter1 = {
- { CDF15( 4458, 5560, 7695, 9709, 13330, 14789, 17537, 20266,
- 21504, 22848, 23934, 25474, 27727, 28915, 30631) },
- { CDF15( 1645, 2573, 4778, 5711, 7807, 8622, 10522, 15357,
- 17674, 20408, 22517, 25010, 27116, 28856, 30749) },
- }, .txtp_inter2 = {
- CDF11( 770, 2421, 5225, 12907, 15819, 18927,
- 21561, 24089, 26595, 28526, 30529)
- }, .txtp_inter3 = {
- { CDF1(16384) }, { CDF1( 4167) }, { CDF1( 1998) }, { CDF1( 748) },
- }, .txtp_intra1 = {
- {
- { CDF6( 1535, 8035, 9461, 12751, 23467, 27825) },
- { CDF6( 564, 3335, 9709, 10870, 18143, 28094) },
- { CDF6( 672, 3247, 3676, 11982, 19415, 23127) },
- { CDF6( 5279, 13885, 15487, 18044, 23527, 30252) },
- { CDF6( 4423, 6074, 7985, 10416, 25693, 29298) },
- { CDF6( 1486, 4241, 9460, 10662, 16456, 27694) },
- { CDF6( 439, 2838, 3522, 6737, 18058, 23754) },
- { CDF6( 1190, 4233, 4855, 11670, 20281, 24377) },
- { CDF6( 1045, 4312, 8647, 10159, 18644, 29335) },
- { CDF6( 202, 3734, 4747, 7298, 17127, 24016) },
- { CDF6( 447, 4312, 6819, 8884, 16010, 23858) },
- { CDF6( 277, 4369, 5255, 8905, 16465, 22271) },
- { CDF6( 3409, 5436, 10599, 15599, 19687, 24040) },
- }, {
- { CDF6( 1870, 13742, 14530, 16498, 23770, 27698) },
- { CDF6( 326, 8796, 14632, 15079, 19272, 27486) },
- { CDF6( 484, 7576, 7712, 14443, 19159, 22591) },
- { CDF6( 1126, 15340, 15895, 17023, 20896, 30279) },
- { CDF6( 655, 4854, 5249, 5913, 22099, 27138) },
- { CDF6( 1299, 6458, 8885, 9290, 14851, 25497) },
- { CDF6( 311, 5295, 5552, 6885, 16107, 22672) },
- { CDF6( 883, 8059, 8270, 11258, 17289, 21549) },
- { CDF6( 741, 7580, 9318, 10345, 16688, 29046) },
- { CDF6( 110, 7406, 7915, 9195, 16041, 23329) },
- { CDF6( 363, 7974, 9357, 10673, 15629, 24474) },
- { CDF6( 153, 7647, 8112, 9936, 15307, 19996) },
- { CDF6( 3511, 6332, 11165, 15335, 19323, 23594) },
- },
- }, .txtp_intra2 = {
- {
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- }, {
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- { CDF4( 6554, 13107, 19661, 26214) },
- }, {
- { CDF4( 1127, 12814, 22772, 27483) },
- { CDF4( 145, 6761, 11980, 26667) },
- { CDF4( 362, 5887, 11678, 16725) },
- { CDF4( 385, 15213, 18587, 30693) },
- { CDF4( 25, 2914, 23134, 27903) },
- { CDF4( 60, 4470, 11749, 23991) },
- { CDF4( 37, 3332, 14511, 21448) },
- { CDF4( 157, 6320, 13036, 17439) },
- { CDF4( 119, 6719, 12906, 29396) },
- { CDF4( 47, 5537, 12576, 21499) },
- { CDF4( 269, 6076, 11258, 23115) },
- { CDF4( 83, 5615, 12001, 17228) },
- { CDF4( 1968, 5556, 12023, 18547) },
- },
- }, .skip = {
- { CDF1(31671) }, { CDF1(16515) }, { CDF1( 4576) },
- }, .skip_mode = {
- { CDF1(32621) }, { CDF1(20708) }, { CDF1( 8127) },
- }, .partition = {
- {
- // 128x128 -> 64x64
- { CDF7(27899, 28219, 28529, 32484, 32539, 32619, 32639) },
- { CDF7( 6607, 6990, 8268, 32060, 32219, 32338, 32371) },
- { CDF7( 5429, 6676, 7122, 32027, 32227, 32531, 32582) },
- { CDF7( 711, 966, 1172, 32448, 32538, 32617, 32664) },
- }, {
- // 64x64 -> 32x32
- { CDF9(20137, 21547, 23078, 29566, 29837,
- 30261, 30524, 30892, 31724) },
- { CDF9( 6732, 7490, 9497, 27944, 28250,
- 28515, 28969, 29630, 30104) },
- { CDF9( 5945, 7663, 8348, 28683, 29117,
- 29749, 30064, 30298, 32238) },
- { CDF9( 870, 1212, 1487, 31198, 31394,
- 31574, 31743, 31881, 32332) },
- }, {
- // 32x32 -> 16x16
- { CDF9(18462, 20920, 23124, 27647, 28227,
- 29049, 29519, 30178, 31544) },
- { CDF9( 7689, 9060, 12056, 24992, 25660,
- 26182, 26951, 28041, 29052) },
- { CDF9( 6015, 9009, 10062, 24544, 25409,
- 26545, 27071, 27526, 32047) },
- { CDF9( 1394, 2208, 2796, 28614, 29061,
- 29466, 29840, 30185, 31899) },
- }, {
- // 16x16 -> 8x8
- { CDF9(15597, 20929, 24571, 26706, 27664,
- 28821, 29601, 30571, 31902) },
- { CDF9( 7925, 11043, 16785, 22470, 23971,
- 25043, 26651, 28701, 29834) },
- { CDF9( 5414, 13269, 15111, 20488, 22360,
- 24500, 25537, 26336, 32117) },
- { CDF9( 2662, 6362, 8614, 20860, 23053,
- 24778, 26436, 27829, 31171) },
- }, {
- // 8x8 -> 4x4 only supports the four legacy partition types
- { CDF3(19132, 25510, 30392) },
- { CDF3(13928, 19855, 28540) },
- { CDF3(12522, 23679, 28629) },
- { CDF3( 9896, 18783, 25853) },
- },
- }, .seg_pred = {
- { CDF1(16384) }, { CDF1(16384) }, { CDF1(16384) },
- }, .seg_id = {
- { CDF7( 5622, 7893, 16093, 18233, 27809, 28373, 32533) },
- { CDF7(14274, 18230, 22557, 24935, 29980, 30851, 32344) },
- { CDF7(27527, 28487, 28723, 28890, 32397, 32647, 32679) },
- }, .cfl_sign = {
- CDF7( 1418, 2123, 13340, 18405, 26972, 28343, 32294)
- }, .cfl_alpha = {
- { CDF15( 7637, 20719, 31401, 32481, 32657, 32688, 32692, 32696,
- 32700, 32704, 32708, 32712, 32716, 32720, 32724) },
- { CDF15(14365, 23603, 28135, 31168, 32167, 32395, 32487, 32573,
- 32620, 32647, 32668, 32672, 32676, 32680, 32684) },
- { CDF15(11532, 22380, 28445, 31360, 32349, 32523, 32584, 32649,
- 32673, 32677, 32681, 32685, 32689, 32693, 32697) },
- { CDF15(26990, 31402, 32282, 32571, 32692, 32696, 32700, 32704,
- 32708, 32712, 32716, 32720, 32724, 32728, 32732) },
- { CDF15(17248, 26058, 28904, 30608, 31305, 31877, 32126, 32321,
- 32394, 32464, 32516, 32560, 32576, 32593, 32622) },
- { CDF15(14738, 21678, 25779, 27901, 29024, 30302, 30980, 31843,
- 32144, 32413, 32520, 32594, 32622, 32656, 32660) },
- }, .restore_wiener = {
- CDF1(11570)
- }, .restore_sgrproj = {
- CDF1(16855)
- }, .restore_switchable = {
- CDF2( 9413, 22581)
- }, .delta_q = {
- CDF3(28160, 32120, 32677)
- }, .delta_lf = {
- { CDF3(28160, 32120, 32677) },
- { CDF3(28160, 32120, 32677) },
- { CDF3(28160, 32120, 32677) },
- { CDF3(28160, 32120, 32677) },
- { CDF3(28160, 32120, 32677) },
- }, .motion_mode = {
- [BS_8x8] = { CDF2( 7651, 24760) },
- [BS_8x16] = { CDF2( 4738, 24765) },
- [BS_8x32] = { CDF2(28799, 31390) },
- [BS_16x8] = { CDF2( 5391, 25528) },
- [BS_16x16] = { CDF2(19419, 26810) },
- [BS_16x32] = { CDF2( 5123, 23606) },
- [BS_16x64] = { CDF2(28973, 31594) },
- [BS_32x8] = { CDF2(26431, 30774) },
- [BS_32x16] = { CDF2(11606, 24308) },
- [BS_32x32] = { CDF2(26260, 29116) },
- [BS_32x64] = { CDF2(20360, 28062) },
- [BS_64x16] = { CDF2(29742, 31203) },
- [BS_64x32] = { CDF2(21679, 26830) },
- [BS_64x64] = { CDF2(29516, 30701) },
- [BS_64x128] = { CDF2(28898, 30397) },
- [BS_128x64] = { CDF2(30878, 31335) },
- [BS_128x128] = { CDF2(32507, 32558) },
- }, .obmc = {
- [BS_8x8] = { CDF1(10437) },
- [BS_8x16] = { CDF1( 9371) },
- [BS_8x32] = { CDF1(23664) },
- [BS_16x8] = { CDF1( 9301) },
- [BS_16x16] = { CDF1(17432) },
- [BS_16x32] = { CDF1(14423) },
- [BS_16x64] = { CDF1(24008) },
- [BS_32x8] = { CDF1(20901) },
- [BS_32x16] = { CDF1(15142) },
- [BS_32x32] = { CDF1(25817) },
- [BS_32x64] = { CDF1(22823) },
- [BS_64x16] = { CDF1(26879) },
- [BS_64x32] = { CDF1(22083) },
- [BS_64x64] = { CDF1(30128) },
- [BS_64x128] = { CDF1(31014) },
- [BS_128x64] = { CDF1(31560) },
- [BS_128x128] = { CDF1(32638) },
- }, .pal_y = {
- { { CDF1(31676) }, { CDF1( 3419) }, { CDF1( 1261) } },
- { { CDF1(31912) }, { CDF1( 2859) }, { CDF1( 980) } },
- { { CDF1(31823) }, { CDF1( 3400) }, { CDF1( 781) } },
- { { CDF1(32030) }, { CDF1( 3561) }, { CDF1( 904) } },
- { { CDF1(32309) }, { CDF1( 7337) }, { CDF1( 1462) } },
- { { CDF1(32265) }, { CDF1( 4015) }, { CDF1( 1521) } },
- { { CDF1(32450) }, { CDF1( 7946) }, { CDF1( 129) } },
- }, .pal_sz = {
- {
- { CDF6( 7952, 13000, 18149, 21478, 25527, 29241) },
- { CDF6( 7139, 11421, 16195, 19544, 23666, 28073) },
- { CDF6( 7788, 12741, 17325, 20500, 24315, 28530) },
- { CDF6( 8271, 14064, 18246, 21564, 25071, 28533) },
- { CDF6(12725, 19180, 21863, 24839, 27535, 30120) },
- { CDF6( 9711, 14888, 16923, 21052, 25661, 27875) },
- { CDF6(14940, 20797, 21678, 24186, 27033, 28999) },
- }, {
- { CDF6( 8713, 19979, 27128, 29609, 31331, 32272) },
- { CDF6( 5839, 15573, 23581, 26947, 29848, 31700) },
- { CDF6( 4426, 11260, 17999, 21483, 25863, 29430) },
- { CDF6( 3228, 9464, 14993, 18089, 22523, 27420) },
- { CDF6( 3768, 8886, 13091, 17852, 22495, 27207) },
- { CDF6( 2464, 8451, 12861, 21632, 25525, 28555) },
- { CDF6( 1269, 5435, 10433, 18963, 21700, 25865) },
- },
- }, .pal_uv = {
- { CDF1(32461) }, { CDF1(21488) },
- }, .color_map = {
- { /* y */
+typedef struct CdfDefaultContext {
+ CdfModeContext m;
+ struct {
+ CdfMvComponent comp;
+ ALIGN(uint16_t joint[N_MV_JOINTS], 8);
+ } mv;
+ ALIGN(uint16_t kfym[5][5][N_INTRA_PRED_MODES + 3], 32);
+} CdfDefaultContext;
+
+static const CdfDefaultContext default_cdf = {
+ .m = {
+ .y_mode = {
+ { CDF12(22801, 23489, 24293, 24756, 25601, 26123,
+ 26606, 27418, 27945, 29228, 29685, 30349) },
+ { CDF12(18673, 19845, 22631, 23318, 23950, 24649,
+ 25527, 27364, 28152, 29701, 29984, 30852) },
+ { CDF12(19770, 20979, 23396, 23939, 24241, 24654,
+ 25136, 27073, 27830, 29360, 29730, 30659) },
+ { CDF12(20155, 21301, 22838, 23178, 23261, 23533,
+ 23703, 24804, 25352, 26575, 27016, 28049) },
+ }, .use_filter_intra = {
+ [BS_4x4] = { CDF1( 4621) },
+ [BS_4x8] = { CDF1( 6743) },
+ [BS_8x4] = { CDF1( 5893) },
+ [BS_8x8] = { CDF1( 7866) },
+ [BS_8x16] = { CDF1(12551) },
+ [BS_16x8] = { CDF1( 9394) },
+ [BS_16x16] = { CDF1(12408) },
+ [BS_16x32] = { CDF1(14301) },
+ [BS_32x16] = { CDF1(12756) },
+ [BS_32x32] = { CDF1(22343) },
+ [BS_32x64] = { CDF1(16384) },
+ [BS_64x32] = { CDF1(16384) },
+ [BS_64x64] = { CDF1(16384) },
+ [BS_64x128] = { CDF1(16384) },
+ [BS_128x64] = { CDF1(16384) },
+ [BS_128x128] = { CDF1(16384) },
+ [BS_4x16] = { CDF1(12770) },
+ [BS_16x4] = { CDF1(10368) },
+ [BS_8x32] = { CDF1(20229) },
+ [BS_32x8] = { CDF1(18101) },
+ [BS_16x64] = { CDF1(16384) },
+ [BS_64x16] = { CDF1(16384) },
+ }, .filter_intra = {
+ CDF4(8949, 12776, 17211, 29558),
+ }, .uv_mode = {
{
- { CDF1(28710) }, { CDF1(16384) }, { CDF1(10553) },
- { CDF1(27036) }, { CDF1(31603) },
+ { CDF12(22631, 24152, 25378, 25661, 25986, 26520,
+ 27055, 27923, 28244, 30059, 30941, 31961) },
+ { CDF12( 9513, 26881, 26973, 27046, 27118, 27664,
+ 27739, 27824, 28359, 29505, 29800, 31796) },
+ { CDF12( 9845, 9915, 28663, 28704, 28757, 28780,
+ 29198, 29822, 29854, 30764, 31777, 32029) },
+ { CDF12(13639, 13897, 14171, 25331, 25606, 25727,
+ 25953, 27148, 28577, 30612, 31355, 32493) },
+ { CDF12( 9764, 9835, 9930, 9954, 25386, 27053,
+ 27958, 28148, 28243, 31101, 31744, 32363) },
+ { CDF12(11825, 13589, 13677, 13720, 15048, 29213,
+ 29301, 29458, 29711, 31161, 31441, 32550) },
+ { CDF12(14175, 14399, 16608, 16821, 17718, 17775,
+ 28551, 30200, 30245, 31837, 32342, 32667) },
+ { CDF12(12885, 13038, 14978, 15590, 15673, 15748,
+ 16176, 29128, 29267, 30643, 31961, 32461) },
+ { CDF12(12026, 13661, 13874, 15305, 15490, 15726,
+ 15995, 16273, 28443, 30388, 30767, 32416) },
+ { CDF12(19052, 19840, 20579, 20916, 21150, 21467,
+ 21885, 22719, 23174, 28861, 30379, 32175) },
+ { CDF12(18627, 19649, 20974, 21219, 21492, 21816,
+ 22199, 23119, 23527, 27053, 31397, 32148) },
+ { CDF12(17026, 19004, 19997, 20339, 20586, 21103,
+ 21349, 21907, 22482, 25896, 26541, 31819) },
+ { CDF12(12124, 13759, 14959, 14992, 15007, 15051,
+ 15078, 15166, 15255, 15753, 16039, 16606) },
}, {
- { CDF2(27877, 30490) }, { CDF2(11532, 25697) },
- { CDF2( 6544, 30234) }, { CDF2(23018, 28072) },
- { CDF2(31915, 32385) },
+ { CDF13(10407, 11208, 12900, 13181, 13823, 14175, 14899,
+ 15656, 15986, 20086, 20995, 22455, 24212) },
+ { CDF13( 4532, 19780, 20057, 20215, 20428, 21071, 21199,
+ 21451, 22099, 24228, 24693, 27032, 29472) },
+ { CDF13( 5273, 5379, 20177, 20270, 20385, 20439, 20949,
+ 21695, 21774, 23138, 24256, 24703, 26679) },
+ { CDF13( 6740, 7167, 7662, 14152, 14536, 14785, 15034,
+ 16741, 18371, 21520, 22206, 23389, 24182) },
+ { CDF13( 4987, 5368, 5928, 6068, 19114, 20315, 21857,
+ 22253, 22411, 24911, 25380, 26027, 26376) },
+ { CDF13( 5370, 6889, 7247, 7393, 9498, 21114, 21402,
+ 21753, 21981, 24780, 25386, 26517, 27176) },
+ { CDF13( 4816, 4961, 7204, 7326, 8765, 8930, 20169,
+ 20682, 20803, 23188, 23763, 24455, 24940) },
+ { CDF13( 6608, 6740, 8529, 9049, 9257, 9356, 9735,
+ 18827, 19059, 22336, 23204, 23964, 24793) },
+ { CDF13( 5998, 7419, 7781, 8933, 9255, 9549, 9753,
+ 10417, 18898, 22494, 23139, 24764, 25989) },
+ { CDF13(10660, 11298, 12550, 12957, 13322, 13624, 14040,
+ 15004, 15534, 20714, 21789, 23443, 24861) },
+ { CDF13(10522, 11530, 12552, 12963, 13378, 13779, 14245,
+ 15235, 15902, 20102, 22696, 23774, 25838) },
+ { CDF13(10099, 10691, 12639, 13049, 13386, 13665, 14125,
+ 15163, 15636, 19676, 20474, 23519, 25208) },
+ { CDF13( 3144, 5087, 7382, 7504, 7593, 7690, 7801,
+ 8064, 8232, 9248, 9875, 10521, 29048) },
+ },
+ }, .angle_delta = {
+ { CDF6( 2180, 5032, 7567, 22776, 26989, 30217) },
+ { CDF6( 2301, 5608, 8801, 23487, 26974, 30330) },
+ { CDF6( 3780, 11018, 13699, 19354, 23083, 31286) },
+ { CDF6( 4581, 11226, 15147, 17138, 21834, 28397) },
+ { CDF6( 1737, 10927, 14509, 19588, 22745, 28823) },
+ { CDF6( 2664, 10176, 12485, 17650, 21600, 30495) },
+ { CDF6( 2240, 11096, 15453, 20341, 22561, 28917) },
+ { CDF6( 3605, 10428, 12459, 17676, 21244, 30655) },
+ }, .filter = {
+ {
+ { CDF2(31935, 32720) }, { CDF2( 5568, 32719) },
+ { CDF2( 422, 2938) }, { CDF2(28244, 32608) },
+ { CDF2(31206, 31953) }, { CDF2( 4862, 32121) },
+ { CDF2( 770, 1152) }, { CDF2(20889, 25637) },
}, {
- { CDF3(25572, 28046, 30045) },
- { CDF3( 9478, 21590, 27256) },
- { CDF3( 7248, 26837, 29824) },
- { CDF3(19167, 24486, 28349) },
- { CDF3(31400, 31825, 32250) },
+ { CDF2(31910, 32724) }, { CDF2( 4120, 32712) },
+ { CDF2( 305, 2247) }, { CDF2(27403, 32636) },
+ { CDF2(31022, 32009) }, { CDF2( 2963, 32093) },
+ { CDF2( 601, 943) }, { CDF2(14969, 21398) },
+ },
+ }, .newmv_mode = {
+ { CDF1(24035) }, { CDF1(16630) }, { CDF1(15339) },
+ { CDF1( 8386) }, { CDF1(12222) }, { CDF1( 4676) },
+ }, .globalmv_mode = {
+ { CDF1( 2175) }, { CDF1( 1054) },
+ }, .refmv_mode = {
+ { CDF1(23974) }, { CDF1(24188) }, { CDF1(17848) },
+ { CDF1(28622) }, { CDF1(24312) }, { CDF1(19923) },
+ }, .drl_bit = {
+ { CDF1(13104) }, { CDF1(24560) }, { CDF1(18945) },
+ }, .comp_inter_mode = {
+ { CDF7( 7760, 13823, 15808, 17641, 19156, 20666, 26891) },
+ { CDF7(10730, 19452, 21145, 22749, 24039, 25131, 28724) },
+ { CDF7(10664, 20221, 21588, 22906, 24295, 25387, 28436) },
+ { CDF7(13298, 16984, 20471, 24182, 25067, 25736, 26422) },
+ { CDF7(18904, 23325, 25242, 27432, 27898, 28258, 30758) },
+ { CDF7(10725, 17454, 20124, 22820, 24195, 25168, 26046) },
+ { CDF7(17125, 24273, 25814, 27492, 28214, 28704, 30592) },
+ { CDF7(13046, 23214, 24505, 25942, 27435, 28442, 29330) },
+ }, .intra = {
+ { CDF1( 806) }, { CDF1(16662) }, { CDF1(20186) },
+ { CDF1(26538) },
+ }, .comp = {
+ { CDF1(26828) }, { CDF1(24035) }, { CDF1(12031) },
+ { CDF1(10640) }, { CDF1( 2901) },
+ }, .comp_dir = {
+ { CDF1( 1198) }, { CDF1( 2070) }, { CDF1( 9166) },
+ { CDF1( 7499) }, { CDF1(22475) },
+ }, .jnt_comp = {
+ { CDF1(18244) }, { CDF1(12865) }, { CDF1( 7053) },
+ { CDF1(13259) }, { CDF1( 9334) }, { CDF1( 4644) },
+ }, .mask_comp = {
+ { CDF1(26607) }, { CDF1(22891) }, { CDF1(18840) },
+ { CDF1(24594) }, { CDF1(19934) }, { CDF1(22674) },
+ }, .wedge_comp = {
+ { CDF1(23431) }, { CDF1(13171) }, { CDF1(11470) },
+ { CDF1( 9770) }, { CDF1( 9100) }, { CDF1( 8233) },
+ { CDF1( 6172) }, { CDF1(11820) }, { CDF1( 7701) },
+ }, .wedge_idx = {
+ { CDF15( 2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094,
+ 20359, 22362, 24127, 25702, 27752, 29450, 31171) },
+ { CDF15( 806, 3266, 6005, 6738, 7218, 7367, 7771, 14588,
+ 16323, 17367, 18452, 19422, 22839, 26127, 29629) },
+ { CDF15( 2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357,
+ 17939, 21332, 24520, 27470, 29456, 30529, 31656) },
+ { CDF15( 1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144,
+ 19163, 20961, 22884, 24471, 26719, 28714, 30877) },
+ { CDF15( 1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624,
+ 15369, 16730, 18114, 19313, 22521, 26012, 29550) },
+ { CDF15( 2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124,
+ 17270, 20533, 23434, 25972, 27944, 29570, 31416) },
+ { CDF15( 1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944,
+ 20638, 22038, 23963, 25311, 26988, 28766, 31012) },
+ { CDF15( 154, 987, 1925, 2051, 2088, 2111, 2151, 23033,
+ 23703, 24284, 24985, 25684, 27259, 28883, 30911) },
+ { CDF15( 1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016,
+ 22935, 25057, 27251, 29173, 30089, 30960, 31933) },
+ }, .interintra = {
+ { CDF1(16384) }, { CDF1(26887) }, { CDF1(27597) },
+ { CDF1(30237) },
+ }, .interintra_mode = {
+ { CDF3(8192, 16384, 24576) },
+ { CDF3(1875, 11082, 27332) },
+ { CDF3(2473, 9996, 26388) },
+ { CDF3(4238, 11537, 25926) },
+ }, .interintra_wedge = {
+ { CDF1(20036) }, { CDF1(24957) }, { CDF1(26704) },
+ { CDF1(27530) }, { CDF1(29564) }, { CDF1(29444) },
+ { CDF1(26872) },
+ }, .ref = {
+ { { CDF1( 4897) }, { CDF1(16973) }, { CDF1(29744) } },
+ { { CDF1( 1555) }, { CDF1(16751) }, { CDF1(30279) } },
+ { { CDF1( 4236) }, { CDF1(19647) }, { CDF1(31194) } },
+ { { CDF1( 8650) }, { CDF1(24773) }, { CDF1(31895) } },
+ { { CDF1( 904) }, { CDF1(11014) }, { CDF1(26875) } },
+ { { CDF1( 1444) }, { CDF1(15087) }, { CDF1(30304) } },
+ }, .comp_fwd_ref = {
+ { { CDF1( 4946) }, { CDF1(19891) }, { CDF1(30731) } },
+ { { CDF1( 9468) }, { CDF1(22441) }, { CDF1(31059) } },
+ { { CDF1( 1503) }, { CDF1(15160) }, { CDF1(27544) } },
+ }, .comp_bwd_ref = {
+ { { CDF1( 2235) }, { CDF1(17182) }, { CDF1(30606) } },
+ { { CDF1( 1423) }, { CDF1(15175) }, { CDF1(30489) } },
+ }, .comp_uni_ref = {
+ { { CDF1( 5284) }, { CDF1(23152) }, { CDF1(31774) } },
+ { { CDF1( 3865) }, { CDF1(14173) }, { CDF1(25120) } },
+ { { CDF1( 3128) }, { CDF1(15270) }, { CDF1(26710) } },
+ }, .txsz = {
+ {
+ { CDF1(19968) }, { CDF1(19968) }, { CDF1(24320) },
}, {
- { CDF4(24779, 26955, 28576, 30282) },
- { CDF4( 8669, 20364, 24073, 28093) },
- { CDF4( 4255, 27565, 29377, 31067) },
- { CDF4(19864, 23674, 26716, 29530) },
- { CDF4(31646, 31893, 32147, 32426) },
+ { CDF2(12272, 30172) }, { CDF2(12272, 30172) },
+ { CDF2(18677, 30848) },
}, {
- { CDF5(23132, 25407, 26970, 28435, 30073) },
- { CDF5( 7443, 17242, 20717, 24762, 27982) },
- { CDF5( 6300, 24862, 26944, 28784, 30671) },
- { CDF5(18916, 22895, 25267, 27435, 29652) },
- { CDF5(31270, 31550, 31808, 32059, 32353) },
+ { CDF2(12986, 15180) }, { CDF2(12986, 15180) },
+ { CDF2(24302, 25602) },
}, {
- { CDF6(23105, 25199, 26464, 27684, 28931, 30318) },
- { CDF6( 6950, 15447, 18952, 22681, 25567, 28563) },
- { CDF6( 7560, 23474, 25490, 27203, 28921, 30708) },
- { CDF6(18544, 22373, 24457, 26195, 28119, 30045) },
- { CDF6(31198, 31451, 31670, 31882, 32123, 32391) },
+ { CDF2( 5782, 11475) }, { CDF2( 5782, 11475) },
+ { CDF2(16803, 22759) },
+ },
+ }, .txpart = {
+ { { CDF1(28581) }, { CDF1(23846) }, { CDF1(20847) } },
+ { { CDF1(24315) }, { CDF1(18196) }, { CDF1(12133) } },
+ { { CDF1(18791) }, { CDF1(10887) }, { CDF1(11005) } },
+ { { CDF1(27179) }, { CDF1(20004) }, { CDF1(11281) } },
+ { { CDF1(26549) }, { CDF1(19308) }, { CDF1(14224) } },
+ { { CDF1(28015) }, { CDF1(21546) }, { CDF1(14400) } },
+ { { CDF1(28165) }, { CDF1(22401) }, { CDF1(16088) } },
+ }, .txtp_inter1 = {
+ { CDF15( 4458, 5560, 7695, 9709, 13330, 14789, 17537, 20266,
+ 21504, 22848, 23934, 25474, 27727, 28915, 30631) },
+ { CDF15( 1645, 2573, 4778, 5711, 7807, 8622, 10522, 15357,
+ 17674, 20408, 22517, 25010, 27116, 28856, 30749) },
+ }, .txtp_inter2 = {
+ CDF11( 770, 2421, 5225, 12907, 15819, 18927,
+ 21561, 24089, 26595, 28526, 30529)
+ }, .txtp_inter3 = {
+ { CDF1(16384) }, { CDF1( 4167) }, { CDF1( 1998) }, { CDF1( 748) },
+ }, .txtp_intra1 = {
+ {
+ { CDF6( 1535, 8035, 9461, 12751, 23467, 27825) },
+ { CDF6( 564, 3335, 9709, 10870, 18143, 28094) },
+ { CDF6( 672, 3247, 3676, 11982, 19415, 23127) },
+ { CDF6( 5279, 13885, 15487, 18044, 23527, 30252) },
+ { CDF6( 4423, 6074, 7985, 10416, 25693, 29298) },
+ { CDF6( 1486, 4241, 9460, 10662, 16456, 27694) },
+ { CDF6( 439, 2838, 3522, 6737, 18058, 23754) },
+ { CDF6( 1190, 4233, 4855, 11670, 20281, 24377) },
+ { CDF6( 1045, 4312, 8647, 10159, 18644, 29335) },
+ { CDF6( 202, 3734, 4747, 7298, 17127, 24016) },
+ { CDF6( 447, 4312, 6819, 8884, 16010, 23858) },
+ { CDF6( 277, 4369, 5255, 8905, 16465, 22271) },
+ { CDF6( 3409, 5436, 10599, 15599, 19687, 24040) },
}, {
- { CDF7(21689, 23883, 25163, 26352, 27506, 28827, 30195) },
- { CDF7( 6892, 15385, 17840, 21606, 24287, 26753, 29204) },
- { CDF7( 5651, 23182, 25042, 26518, 27982, 29392, 30900) },
- { CDF7(19349, 22578, 24418, 25994, 27524, 29031, 30448) },
- { CDF7(31028, 31270, 31504, 31705, 31927, 32153, 32392) },
+ { CDF6( 1870, 13742, 14530, 16498, 23770, 27698) },
+ { CDF6( 326, 8796, 14632, 15079, 19272, 27486) },
+ { CDF6( 484, 7576, 7712, 14443, 19159, 22591) },
+ { CDF6( 1126, 15340, 15895, 17023, 20896, 30279) },
+ { CDF6( 655, 4854, 5249, 5913, 22099, 27138) },
+ { CDF6( 1299, 6458, 8885, 9290, 14851, 25497) },
+ { CDF6( 311, 5295, 5552, 6885, 16107, 22672) },
+ { CDF6( 883, 8059, 8270, 11258, 17289, 21549) },
+ { CDF6( 741, 7580, 9318, 10345, 16688, 29046) },
+ { CDF6( 110, 7406, 7915, 9195, 16041, 23329) },
+ { CDF6( 363, 7974, 9357, 10673, 15629, 24474) },
+ { CDF6( 153, 7647, 8112, 9936, 15307, 19996) },
+ { CDF6( 3511, 6332, 11165, 15335, 19323, 23594) },
},
- }, { /* uv */
+ }, .txtp_intra2 = {
{
- { CDF1(29089) }, { CDF1(16384) }, { CDF1( 8713) },
- { CDF1(29257) }, { CDF1(31610) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ }, {
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
+ { CDF4( 6554, 13107, 19661, 26214) },
}, {
- { CDF2(25257, 29145) }, { CDF2(12287, 27293) },
- { CDF2( 7033, 27960) }, { CDF2(20145, 25405) },
- { CDF2(30608, 31639) },
+ { CDF4( 1127, 12814, 22772, 27483) },
+ { CDF4( 145, 6761, 11980, 26667) },
+ { CDF4( 362, 5887, 11678, 16725) },
+ { CDF4( 385, 15213, 18587, 30693) },
+ { CDF4( 25, 2914, 23134, 27903) },
+ { CDF4( 60, 4470, 11749, 23991) },
+ { CDF4( 37, 3332, 14511, 21448) },
+ { CDF4( 157, 6320, 13036, 17439) },
+ { CDF4( 119, 6719, 12906, 29396) },
+ { CDF4( 47, 5537, 12576, 21499) },
+ { CDF4( 269, 6076, 11258, 23115) },
+ { CDF4( 83, 5615, 12001, 17228) },
+ { CDF4( 1968, 5556, 12023, 18547) },
+ },
+ }, .skip = {
+ { CDF1(31671) }, { CDF1(16515) }, { CDF1( 4576) },
+ }, .skip_mode = {
+ { CDF1(32621) }, { CDF1(20708) }, { CDF1( 8127) },
+ }, .partition = {
+ {
+ // 128x128 -> 64x64
+ { CDF7(27899, 28219, 28529, 32484, 32539, 32619, 32639) },
+ { CDF7( 6607, 6990, 8268, 32060, 32219, 32338, 32371) },
+ { CDF7( 5429, 6676, 7122, 32027, 32227, 32531, 32582) },
+ { CDF7( 711, 966, 1172, 32448, 32538, 32617, 32664) },
}, {
- { CDF3(24210, 27175, 29903) },
- { CDF3( 9888, 22386, 27214) },
- { CDF3( 5901, 26053, 29293) },
- { CDF3(18318, 22152, 28333) },
- { CDF3(30459, 31136, 31926) },
+ // 64x64 -> 32x32
+ { CDF9(20137, 21547, 23078, 29566, 29837,
+ 30261, 30524, 30892, 31724) },
+ { CDF9( 6732, 7490, 9497, 27944, 28250,
+ 28515, 28969, 29630, 30104) },
+ { CDF9( 5945, 7663, 8348, 28683, 29117,
+ 29749, 30064, 30298, 32238) },
+ { CDF9( 870, 1212, 1487, 31198, 31394,
+ 31574, 31743, 31881, 32332) },
}, {
- { CDF4(22980, 25479, 27781, 29986) },
- { CDF4( 8413, 21408, 24859, 28874) },
- { CDF4( 2257, 29449, 30594, 31598) },
- { CDF4(19189, 21202, 25915, 28620) },
- { CDF4(31844, 32044, 32281, 32518) },
+ // 32x32 -> 16x16
+ { CDF9(18462, 20920, 23124, 27647, 28227,
+ 29049, 29519, 30178, 31544) },
+ { CDF9( 7689, 9060, 12056, 24992, 25660,
+ 26182, 26951, 28041, 29052) },
+ { CDF9( 6015, 9009, 10062, 24544, 25409,
+ 26545, 27071, 27526, 32047) },
+ { CDF9( 1394, 2208, 2796, 28614, 29061,
+ 29466, 29840, 30185, 31899) },
}, {
- { CDF5(22217, 24567, 26637, 28683, 30548) },
- { CDF5( 7307, 16406, 19636, 24632, 28424) },
- { CDF5( 4441, 25064, 26879, 28942, 30919) },
- { CDF5(17210, 20528, 23319, 26750, 29582) },
- { CDF5(30674, 30953, 31396, 31735, 32207) },
+ // 16x16 -> 8x8
+ { CDF9(15597, 20929, 24571, 26706, 27664,
+ 28821, 29601, 30571, 31902) },
+ { CDF9( 7925, 11043, 16785, 22470, 23971,
+ 25043, 26651, 28701, 29834) },
+ { CDF9( 5414, 13269, 15111, 20488, 22360,
+ 24500, 25537, 26336, 32117) },
+ { CDF9( 2662, 6362, 8614, 20860, 23053,
+ 24778, 26436, 27829, 31171) },
}, {
- { CDF6(21239, 23168, 25044, 26962, 28705, 30506) },
- { CDF6( 6545, 15012, 18004, 21817, 25503, 28701) },
- { CDF6( 3448, 26295, 27437, 28704, 30126, 31442) },
- { CDF6(15889, 18323, 21704, 24698, 26976, 29690) },
- { CDF6(30988, 31204, 31479, 31734, 31983, 32325) },
+ // 8x8 -> 4x4 only supports the four legacy partition types
+ { CDF3(19132, 25510, 30392) },
+ { CDF3(13928, 19855, 28540) },
+ { CDF3(12522, 23679, 28629) },
+ { CDF3( 9896, 18783, 25853) },
+ },
+ }, .seg_pred = {
+ { CDF1(16384) }, { CDF1(16384) }, { CDF1(16384) },
+ }, .seg_id = {
+ { CDF7( 5622, 7893, 16093, 18233, 27809, 28373, 32533) },
+ { CDF7(14274, 18230, 22557, 24935, 29980, 30851, 32344) },
+ { CDF7(27527, 28487, 28723, 28890, 32397, 32647, 32679) },
+ }, .cfl_sign = {
+ CDF7( 1418, 2123, 13340, 18405, 26972, 28343, 32294)
+ }, .cfl_alpha = {
+ { CDF15( 7637, 20719, 31401, 32481, 32657, 32688, 32692, 32696,
+ 32700, 32704, 32708, 32712, 32716, 32720, 32724) },
+ { CDF15(14365, 23603, 28135, 31168, 32167, 32395, 32487, 32573,
+ 32620, 32647, 32668, 32672, 32676, 32680, 32684) },
+ { CDF15(11532, 22380, 28445, 31360, 32349, 32523, 32584, 32649,
+ 32673, 32677, 32681, 32685, 32689, 32693, 32697) },
+ { CDF15(26990, 31402, 32282, 32571, 32692, 32696, 32700, 32704,
+ 32708, 32712, 32716, 32720, 32724, 32728, 32732) },
+ { CDF15(17248, 26058, 28904, 30608, 31305, 31877, 32126, 32321,
+ 32394, 32464, 32516, 32560, 32576, 32593, 32622) },
+ { CDF15(14738, 21678, 25779, 27901, 29024, 30302, 30980, 31843,
+ 32144, 32413, 32520, 32594, 32622, 32656, 32660) },
+ }, .restore_wiener = {
+ CDF1(11570)
+ }, .restore_sgrproj = {
+ CDF1(16855)
+ }, .restore_switchable = {
+ CDF2( 9413, 22581)
+ }, .delta_q = {
+ CDF3(28160, 32120, 32677)
+ }, .delta_lf = {
+ { CDF3(28160, 32120, 32677) },
+ { CDF3(28160, 32120, 32677) },
+ { CDF3(28160, 32120, 32677) },
+ { CDF3(28160, 32120, 32677) },
+ { CDF3(28160, 32120, 32677) },
+ }, .motion_mode = {
+ [BS_8x8] = { CDF2( 7651, 24760) },
+ [BS_8x16] = { CDF2( 4738, 24765) },
+ [BS_8x32] = { CDF2(28799, 31390) },
+ [BS_16x8] = { CDF2( 5391, 25528) },
+ [BS_16x16] = { CDF2(19419, 26810) },
+ [BS_16x32] = { CDF2( 5123, 23606) },
+ [BS_16x64] = { CDF2(28973, 31594) },
+ [BS_32x8] = { CDF2(26431, 30774) },
+ [BS_32x16] = { CDF2(11606, 24308) },
+ [BS_32x32] = { CDF2(26260, 29116) },
+ [BS_32x64] = { CDF2(20360, 28062) },
+ [BS_64x16] = { CDF2(29742, 31203) },
+ [BS_64x32] = { CDF2(21679, 26830) },
+ [BS_64x64] = { CDF2(29516, 30701) },
+ [BS_64x128] = { CDF2(28898, 30397) },
+ [BS_128x64] = { CDF2(30878, 31335) },
+ [BS_128x128] = { CDF2(32507, 32558) },
+ }, .obmc = {
+ [BS_8x8] = { CDF1(10437) },
+ [BS_8x16] = { CDF1( 9371) },
+ [BS_8x32] = { CDF1(23664) },
+ [BS_16x8] = { CDF1( 9301) },
+ [BS_16x16] = { CDF1(17432) },
+ [BS_16x32] = { CDF1(14423) },
+ [BS_16x64] = { CDF1(24008) },
+ [BS_32x8] = { CDF1(20901) },
+ [BS_32x16] = { CDF1(15142) },
+ [BS_32x32] = { CDF1(25817) },
+ [BS_32x64] = { CDF1(22823) },
+ [BS_64x16] = { CDF1(26879) },
+ [BS_64x32] = { CDF1(22083) },
+ [BS_64x64] = { CDF1(30128) },
+ [BS_64x128] = { CDF1(31014) },
+ [BS_128x64] = { CDF1(31560) },
+ [BS_128x128] = { CDF1(32638) },
+ }, .pal_y = {
+ { { CDF1(31676) }, { CDF1( 3419) }, { CDF1( 1261) } },
+ { { CDF1(31912) }, { CDF1( 2859) }, { CDF1( 980) } },
+ { { CDF1(31823) }, { CDF1( 3400) }, { CDF1( 781) } },
+ { { CDF1(32030) }, { CDF1( 3561) }, { CDF1( 904) } },
+ { { CDF1(32309) }, { CDF1( 7337) }, { CDF1( 1462) } },
+ { { CDF1(32265) }, { CDF1( 4015) }, { CDF1( 1521) } },
+ { { CDF1(32450) }, { CDF1( 7946) }, { CDF1( 129) } },
+ }, .pal_sz = {
+ {
+ { CDF6( 7952, 13000, 18149, 21478, 25527, 29241) },
+ { CDF6( 7139, 11421, 16195, 19544, 23666, 28073) },
+ { CDF6( 7788, 12741, 17325, 20500, 24315, 28530) },
+ { CDF6( 8271, 14064, 18246, 21564, 25071, 28533) },
+ { CDF6(12725, 19180, 21863, 24839, 27535, 30120) },
+ { CDF6( 9711, 14888, 16923, 21052, 25661, 27875) },
+ { CDF6(14940, 20797, 21678, 24186, 27033, 28999) },
}, {
- { CDF7(21442, 23288, 24758, 26246, 27649, 28980, 30563) },
- { CDF7( 5863, 14933, 17552, 20668, 23683, 26411, 29273) },
- { CDF7( 3415, 25810, 26877, 27990, 29223, 30394, 31618) },
- { CDF7(17965, 20084, 22232, 23974, 26274, 28402, 30390) },
- { CDF7(31190, 31329, 31516, 31679, 31825, 32026, 32322) },
+ { CDF6( 8713, 19979, 27128, 29609, 31331, 32272) },
+ { CDF6( 5839, 15573, 23581, 26947, 29848, 31700) },
+ { CDF6( 4426, 11260, 17999, 21483, 25863, 29430) },
+ { CDF6( 3228, 9464, 14993, 18089, 22523, 27420) },
+ { CDF6( 3768, 8886, 13091, 17852, 22495, 27207) },
+ { CDF6( 2464, 8451, 12861, 21632, 25525, 28555) },
+ { CDF6( 1269, 5435, 10433, 18963, 21700, 25865) },
+ },
+ }, .pal_uv = {
+ { CDF1(32461) }, { CDF1(21488) },
+ }, .color_map = {
+ { /* y */
+ {
+ { CDF1(28710) }, { CDF1(16384) }, { CDF1(10553) },
+ { CDF1(27036) }, { CDF1(31603) },
+ }, {
+ { CDF2(27877, 30490) }, { CDF2(11532, 25697) },
+ { CDF2( 6544, 30234) }, { CDF2(23018, 28072) },
+ { CDF2(31915, 32385) },
+ }, {
+ { CDF3(25572, 28046, 30045) },
+ { CDF3( 9478, 21590, 27256) },
+ { CDF3( 7248, 26837, 29824) },
+ { CDF3(19167, 24486, 28349) },
+ { CDF3(31400, 31825, 32250) },
+ }, {
+ { CDF4(24779, 26955, 28576, 30282) },
+ { CDF4( 8669, 20364, 24073, 28093) },
+ { CDF4( 4255, 27565, 29377, 31067) },
+ { CDF4(19864, 23674, 26716, 29530) },
+ { CDF4(31646, 31893, 32147, 32426) },
+ }, {
+ { CDF5(23132, 25407, 26970, 28435, 30073) },
+ { CDF5( 7443, 17242, 20717, 24762, 27982) },
+ { CDF5( 6300, 24862, 26944, 28784, 30671) },
+ { CDF5(18916, 22895, 25267, 27435, 29652) },
+ { CDF5(31270, 31550, 31808, 32059, 32353) },
+ }, {
+ { CDF6(23105, 25199, 26464, 27684, 28931, 30318) },
+ { CDF6( 6950, 15447, 18952, 22681, 25567, 28563) },
+ { CDF6( 7560, 23474, 25490, 27203, 28921, 30708) },
+ { CDF6(18544, 22373, 24457, 26195, 28119, 30045) },
+ { CDF6(31198, 31451, 31670, 31882, 32123, 32391) },
+ }, {
+ { CDF7(21689, 23883, 25163, 26352, 27506, 28827, 30195) },
+ { CDF7( 6892, 15385, 17840, 21606, 24287, 26753, 29204) },
+ { CDF7( 5651, 23182, 25042, 26518, 27982, 29392, 30900) },
+ { CDF7(19349, 22578, 24418, 25994, 27524, 29031, 30448) },
+ { CDF7(31028, 31270, 31504, 31705, 31927, 32153, 32392) },
+ },
+ }, { /* uv */
+ {
+ { CDF1(29089) }, { CDF1(16384) }, { CDF1( 8713) },
+ { CDF1(29257) }, { CDF1(31610) },
+ }, {
+ { CDF2(25257, 29145) }, { CDF2(12287, 27293) },
+ { CDF2( 7033, 27960) }, { CDF2(20145, 25405) },
+ { CDF2(30608, 31639) },
+ }, {
+ { CDF3(24210, 27175, 29903) },
+ { CDF3( 9888, 22386, 27214) },
+ { CDF3( 5901, 26053, 29293) },
+ { CDF3(18318, 22152, 28333) },
+ { CDF3(30459, 31136, 31926) },
+ }, {
+ { CDF4(22980, 25479, 27781, 29986) },
+ { CDF4( 8413, 21408, 24859, 28874) },
+ { CDF4( 2257, 29449, 30594, 31598) },
+ { CDF4(19189, 21202, 25915, 28620) },
+ { CDF4(31844, 32044, 32281, 32518) },
+ }, {
+ { CDF5(22217, 24567, 26637, 28683, 30548) },
+ { CDF5( 7307, 16406, 19636, 24632, 28424) },
+ { CDF5( 4441, 25064, 26879, 28942, 30919) },
+ { CDF5(17210, 20528, 23319, 26750, 29582) },
+ { CDF5(30674, 30953, 31396, 31735, 32207) },
+ }, {
+ { CDF6(21239, 23168, 25044, 26962, 28705, 30506) },
+ { CDF6( 6545, 15012, 18004, 21817, 25503, 28701) },
+ { CDF6( 3448, 26295, 27437, 28704, 30126, 31442) },
+ { CDF6(15889, 18323, 21704, 24698, 26976, 29690) },
+ { CDF6(30988, 31204, 31479, 31734, 31983, 32325) },
+ }, {
+ { CDF7(21442, 23288, 24758, 26246, 27649, 28980, 30563) },
+ { CDF7( 5863, 14933, 17552, 20668, 23683, 26411, 29273) },
+ { CDF7( 3415, 25810, 26877, 27990, 29223, 30394, 31618) },
+ { CDF7(17965, 20084, 22232, 23974, 26274, 28402, 30390) },
+ { CDF7(31190, 31329, 31516, 31679, 31825, 32026, 32322) },
+ },
},
+ }, .intrabc = {
+ CDF1(30531)
+ },
+ }, .mv = {
+ .comp = {
+ .classes = {
+ CDF10(28672, 30976, 31858, 32320, 32551,
+ 32656, 32740, 32757, 32762, 32767)
+ }, .class0 = {
+ CDF1(27648)
+ }, .classN = {
+ { CDF1(17408) }, { CDF1(17920) }, { CDF1(18944) },
+ { CDF1(20480) }, { CDF1(22528) }, { CDF1(24576) },
+ { CDF1(28672) }, { CDF1(29952) }, { CDF1(29952) },
+ { CDF1(30720) },
+ }, .class0_fp = {
+ { CDF3(16384, 24576, 26624) },
+ { CDF3(12288, 21248, 24128) },
+ }, .classN_fp = {
+ CDF3( 8192, 17408, 21248)
+ }, .class0_hp = {
+ CDF1(20480)
+ }, .classN_hp = {
+ CDF1(16384)
+ }, .sign = {
+ CDF1(16384)
+ },
+ }, .joint = {
+ CDF3( 4096, 11264, 19328)
+ },
+ }, .kfym = {
+ {
+ { CDF12(15588, 17027, 19338, 20218, 20682, 21110,
+ 21825, 23244, 24189, 28165, 29093, 30466) },
+ { CDF12(12016, 18066, 19516, 20303, 20719, 21444,
+ 21888, 23032, 24434, 28658, 30172, 31409) },
+ { CDF12(10052, 10771, 22296, 22788, 23055, 23239,
+ 24133, 25620, 26160, 29336, 29929, 31567) },
+ { CDF12(14091, 15406, 16442, 18808, 19136, 19546,
+ 19998, 22096, 24746, 29585, 30958, 32462) },
+ { CDF12(12122, 13265, 15603, 16501, 18609, 20033,
+ 22391, 25583, 26437, 30261, 31073, 32475) },
+ }, {
+ { CDF12(10023, 19585, 20848, 21440, 21832, 22760,
+ 23089, 24023, 25381, 29014, 30482, 31436) },
+ { CDF12( 5983, 24099, 24560, 24886, 25066, 25795,
+ 25913, 26423, 27610, 29905, 31276, 31794) },
+ { CDF12( 7444, 12781, 20177, 20728, 21077, 21607,
+ 22170, 23405, 24469, 27915, 29090, 30492) },
+ { CDF12( 8537, 14689, 15432, 17087, 17408, 18172,
+ 18408, 19825, 24649, 29153, 31096, 32210) },
+ { CDF12( 7543, 14231, 15496, 16195, 17905, 20717,
+ 21984, 24516, 26001, 29675, 30981, 31994) },
+ }, {
+ { CDF12(12613, 13591, 21383, 22004, 22312, 22577,
+ 23401, 25055, 25729, 29538, 30305, 32077) },
+ { CDF12( 9687, 13470, 18506, 19230, 19604, 20147,
+ 20695, 22062, 23219, 27743, 29211, 30907) },
+ { CDF12( 6183, 6505, 26024, 26252, 26366, 26434,
+ 27082, 28354, 28555, 30467, 30794, 32086) },
+ { CDF12(10718, 11734, 14954, 17224, 17565, 17924,
+ 18561, 21523, 23878, 28975, 30287, 32252) },
+ { CDF12( 9194, 9858, 16501, 17263, 18424, 19171,
+ 21563, 25961, 26561, 30072, 30737, 32463) },
+ }, {
+ { CDF12(12602, 14399, 15488, 18381, 18778, 19315,
+ 19724, 21419, 25060, 29696, 30917, 32409) },
+ { CDF12( 8203, 13821, 14524, 17105, 17439, 18131,
+ 18404, 19468, 25225, 29485, 31158, 32342) },
+ { CDF12( 8451, 9731, 15004, 17643, 18012, 18425,
+ 19070, 21538, 24605, 29118, 30078, 32018) },
+ { CDF12( 7714, 9048, 9516, 16667, 16817, 16994,
+ 17153, 18767, 26743, 30389, 31536, 32528) },
+ { CDF12( 8843, 10280, 11496, 15317, 16652, 17943,
+ 19108, 22718, 25769, 29953, 30983, 32485) },
+ }, {
+ { CDF12(12578, 13671, 15979, 16834, 19075, 20913,
+ 22989, 25449, 26219, 30214, 31150, 32477) },
+ { CDF12( 9563, 13626, 15080, 15892, 17756, 20863,
+ 22207, 24236, 25380, 29653, 31143, 32277) },
+ { CDF12( 8356, 8901, 17616, 18256, 19350, 20106,
+ 22598, 25947, 26466, 29900, 30523, 32261) },
+ { CDF12(10835, 11815, 13124, 16042, 17018, 18039,
+ 18947, 22753, 24615, 29489, 30883, 32482) },
+ { CDF12( 7618, 8288, 9859, 10509, 15386, 18657,
+ 22903, 28776, 29180, 31355, 31802, 32593) },
},
- }, .intrabc = {
- CDF1(30531)
- },
-};
-
-static const CdfMvComponent default_mv_component_cdf = {
- .classes = {
- CDF10(28672, 30976, 31858, 32320, 32551,
- 32656, 32740, 32757, 32762, 32767)
- }, .class0 = {
- CDF1(27648)
- }, .classN = {
- { CDF1(17408) }, { CDF1(17920) }, { CDF1(18944) },
- { CDF1(20480) }, { CDF1(22528) }, { CDF1(24576) },
- { CDF1(28672) }, { CDF1(29952) }, { CDF1(29952) },
- { CDF1(30720) },
- }, .class0_fp = {
- { CDF3(16384, 24576, 26624) },
- { CDF3(12288, 21248, 24128) },
- }, .classN_fp = {
- CDF3( 8192, 17408, 21248)
- }, .class0_hp = {
- CDF1(20480)
- }, .classN_hp = {
- CDF1(16384)
- }, .sign = {
- CDF1(16384)
- },
-};
-
-static const uint16_t ALIGN(default_mv_joint_cdf[N_MV_JOINTS], 8) = {
- CDF3( 4096, 11264, 19328)
-};
-
-static const uint16_t ALIGN(default_kf_y_mode_cdf[5][5][N_INTRA_PRED_MODES + 3], 32) = {
- {
- { CDF12(15588, 17027, 19338, 20218, 20682, 21110,
- 21825, 23244, 24189, 28165, 29093, 30466) },
- { CDF12(12016, 18066, 19516, 20303, 20719, 21444,
- 21888, 23032, 24434, 28658, 30172, 31409) },
- { CDF12(10052, 10771, 22296, 22788, 23055, 23239,
- 24133, 25620, 26160, 29336, 29929, 31567) },
- { CDF12(14091, 15406, 16442, 18808, 19136, 19546,
- 19998, 22096, 24746, 29585, 30958, 32462) },
- { CDF12(12122, 13265, 15603, 16501, 18609, 20033,
- 22391, 25583, 26437, 30261, 31073, 32475) },
- }, {
- { CDF12(10023, 19585, 20848, 21440, 21832, 22760,
- 23089, 24023, 25381, 29014, 30482, 31436) },
- { CDF12( 5983, 24099, 24560, 24886, 25066, 25795,
- 25913, 26423, 27610, 29905, 31276, 31794) },
- { CDF12( 7444, 12781, 20177, 20728, 21077, 21607,
- 22170, 23405, 24469, 27915, 29090, 30492) },
- { CDF12( 8537, 14689, 15432, 17087, 17408, 18172,
- 18408, 19825, 24649, 29153, 31096, 32210) },
- { CDF12( 7543, 14231, 15496, 16195, 17905, 20717,
- 21984, 24516, 26001, 29675, 30981, 31994) },
- }, {
- { CDF12(12613, 13591, 21383, 22004, 22312, 22577,
- 23401, 25055, 25729, 29538, 30305, 32077) },
- { CDF12( 9687, 13470, 18506, 19230, 19604, 20147,
- 20695, 22062, 23219, 27743, 29211, 30907) },
- { CDF12( 6183, 6505, 26024, 26252, 26366, 26434,
- 27082, 28354, 28555, 30467, 30794, 32086) },
- { CDF12(10718, 11734, 14954, 17224, 17565, 17924,
- 18561, 21523, 23878, 28975, 30287, 32252) },
- { CDF12( 9194, 9858, 16501, 17263, 18424, 19171,
- 21563, 25961, 26561, 30072, 30737, 32463) },
- }, {
- { CDF12(12602, 14399, 15488, 18381, 18778, 19315,
- 19724, 21419, 25060, 29696, 30917, 32409) },
- { CDF12( 8203, 13821, 14524, 17105, 17439, 18131,
- 18404, 19468, 25225, 29485, 31158, 32342) },
- { CDF12( 8451, 9731, 15004, 17643, 18012, 18425,
- 19070, 21538, 24605, 29118, 30078, 32018) },
- { CDF12( 7714, 9048, 9516, 16667, 16817, 16994,
- 17153, 18767, 26743, 30389, 31536, 32528) },
- { CDF12( 8843, 10280, 11496, 15317, 16652, 17943,
- 19108, 22718, 25769, 29953, 30983, 32485) },
- }, {
- { CDF12(12578, 13671, 15979, 16834, 19075, 20913,
- 22989, 25449, 26219, 30214, 31150, 32477) },
- { CDF12( 9563, 13626, 15080, 15892, 17756, 20863,
- 22207, 24236, 25380, 29653, 31143, 32277) },
- { CDF12( 8356, 8901, 17616, 18256, 19350, 20106,
- 22598, 25947, 26466, 29900, 30523, 32261) },
- { CDF12(10835, 11815, 13124, 16042, 17018, 18039,
- 18947, 22753, 24615, 29489, 30883, 32482) },
- { CDF12( 7618, 8288, 9859, 10509, 15386, 18657,
- 22903, 28776, 29180, 31355, 31802, 32593) },
},
};
-static const CdfCoefContext av1_default_coef_cdf[4] = {
+static const CdfCoefContext default_coef_cdf[4] = {
[0] = {
.skip = {
{
@@ -3951,10 +3958,8 @@ void dav1d_cdf_thread_update(const Dav1dFrameHeader *const hdr,
{
#define update_cdf_1d(n1d, name) \
do { \
- memcpy(dst->name, src->name, sizeof(dst->name)); \
dst->name[n1d] = 0; \
} while (0)
-
#define update_cdf_2d(n1d, n2d, name) \
for (int j = 0; j < (n1d); j++) update_cdf_1d(n2d, name[j])
#define update_cdf_3d(n1d, n2d, n3d, name) \
@@ -3962,29 +3967,8 @@ void dav1d_cdf_thread_update(const Dav1dFrameHeader *const hdr,
#define update_cdf_4d(n1d, n2d, n3d, n4d, name) \
for (int l = 0; l < (n1d); l++) update_cdf_3d(n2d, n3d, n4d, name[l])
-#define update_bit_0d(name) \
- do { \
- dst->name[0] = src->name[0]; \
- dst->name[1] = 0; \
- } while (0)
-
-#define update_bit_1d(n1d, name) \
- for (int i = 0; i < (n1d); i++) update_bit_0d(name[i])
-#define update_bit_2d(n1d, n2d, name) \
- for (int j = 0; j < (n1d); j++) update_bit_1d(n2d, name[j])
-#define update_bit_3d(n1d, n2d, n3d, name) \
- for (int k = 0; k < (n1d); k++) update_bit_2d(n2d, n3d, name[k])
+ memcpy(dst, src, offsetof(CdfContext, m.intrabc));
- update_bit_1d(N_BS_SIZES, m.use_filter_intra);
- update_cdf_1d(4, m.filter_intra);
- update_cdf_3d(2, N_INTRA_PRED_MODES, N_UV_INTRA_PRED_MODES - 1 - !k, m.uv_mode);
- update_cdf_2d(8, 6, m.angle_delta);
- update_cdf_3d(N_TX_SIZES - 1, 3, imin(k + 1, 2), m.txsz);
- update_cdf_3d(2, N_INTRA_PRED_MODES, 6, m.txtp_intra1);
- update_cdf_3d(3, N_INTRA_PRED_MODES, 4, m.txtp_intra2);
- update_bit_1d(3, m.skip);
- update_cdf_3d(N_BL_LEVELS, 4, dav1d_partition_type_count[k], m.partition);
- update_bit_2d(N_TX_SIZES, 13, coef.skip);
update_cdf_3d(2, 2, 4, coef.eob_bin_16);
update_cdf_3d(2, 2, 5, coef.eob_bin_32);
update_cdf_3d(2, 2, 6, coef.eob_bin_64);
@@ -3992,106 +3976,104 @@ void dav1d_cdf_thread_update(const Dav1dFrameHeader *const hdr,
update_cdf_3d(2, 2, 8, coef.eob_bin_256);
update_cdf_2d(2, 9, coef.eob_bin_512);
update_cdf_2d(2, 10, coef.eob_bin_1024);
- update_bit_3d(N_TX_SIZES, 2, 11 /*22*/, coef.eob_hi_bit);
update_cdf_4d(N_TX_SIZES, 2, 4, 2, coef.eob_base_tok);
update_cdf_4d(N_TX_SIZES, 2, 41 /*42*/, 3, coef.base_tok);
- update_bit_2d(2, 3, coef.dc_sign);
update_cdf_4d(4, 2, 21, 3, coef.br_tok);
- update_cdf_2d(3, DAV1D_MAX_SEGMENTS - 1, m.seg_id);
- update_cdf_1d(7, m.cfl_sign);
+ update_cdf_4d(N_TX_SIZES, 2, 11 /*22*/, 1, coef.eob_hi_bit);
+ update_cdf_3d(N_TX_SIZES, 13, 1, coef.skip);
+ update_cdf_3d(2, 3, 1, coef.dc_sign);
+
+ update_cdf_3d(2, N_INTRA_PRED_MODES, N_UV_INTRA_PRED_MODES - 1 - !k, m.uv_mode);
+ update_cdf_2d(4, N_PARTITIONS - 3, m.partition[BL_128X128]);
+ for (int k = BL_64X64; k < BL_8X8; k++)
+ update_cdf_2d(4, N_PARTITIONS - 1, m.partition[k]);
+ update_cdf_2d(4, N_SUB8X8_PARTITIONS - 1, m.partition[BL_8X8]);
update_cdf_2d(6, 15, m.cfl_alpha);
- update_bit_0d(m.restore_wiener);
- update_bit_0d(m.restore_sgrproj);
- update_cdf_1d(2, m.restore_switchable);
- update_cdf_1d(3, m.delta_q);
- update_cdf_2d(5, 3, m.delta_lf);
- update_bit_2d(7, 3, m.pal_y);
- update_bit_1d(2, m.pal_uv);
- update_cdf_3d(2, 7, 6, m.pal_sz);
- update_cdf_4d(2, 7, 5, k + 1, m.color_map);
- update_bit_2d(7, 3, m.txpart);
update_cdf_2d(2, 15, m.txtp_inter1);
update_cdf_1d(11, m.txtp_inter2);
- update_bit_1d(4, m.txtp_inter3);
-
- if (IS_KEY_OR_INTRA(hdr)) {
- update_bit_0d(m.intrabc);
+ update_cdf_3d(2, N_INTRA_PRED_MODES, 6, m.txtp_intra1);
+ update_cdf_3d(3, N_INTRA_PRED_MODES, 4, m.txtp_intra2);
+ update_cdf_1d(7, m.cfl_sign);
+ update_cdf_2d(8, 6, m.angle_delta);
+ update_cdf_1d(4, m.filter_intra);
+ update_cdf_2d(3, DAV1D_MAX_SEGMENTS - 1, m.seg_id);
+ update_cdf_3d(2, 7, 6, m.pal_sz);
+ update_cdf_4d(2, 7, 5, k + 1, m.color_map);
+ update_cdf_3d(N_TX_SIZES - 1, 3, imin(k + 1, 2), m.txsz);
+ update_cdf_1d(3, m.delta_q);
+ update_cdf_2d(5, 3, m.delta_lf);
+ update_cdf_1d(2, m.restore_switchable);
+ update_cdf_1d(1, m.restore_wiener);
+ update_cdf_1d(1, m.restore_sgrproj);
+ update_cdf_2d(4, 1, m.txtp_inter3);
+ update_cdf_2d(N_BS_SIZES, 1, m.use_filter_intra);
+ update_cdf_3d(7, 3, 1, m.txpart);
+ update_cdf_2d(3, 1, m.skip);
+ update_cdf_3d(7, 3, 1, m.pal_y);
+ update_cdf_2d(2, 1, m.pal_uv);
- update_cdf_1d(N_MV_JOINTS - 1, dmv.joint);
- for (int k = 0; k < 2; k++) {
- update_cdf_1d(10, dmv.comp[k].classes);
- update_bit_0d(dmv.comp[k].class0);
- update_bit_1d(10, dmv.comp[k].classN);
- update_bit_0d(dmv.comp[k].sign);
- }
+ if (IS_KEY_OR_INTRA(hdr))
return;
- }
- update_bit_1d(3, m.skip_mode);
+ memcpy(dst->m.y_mode, src->m.y_mode,
+ offsetof(CdfContext, kfym) - offsetof(CdfContext, m.y_mode));
+
update_cdf_2d(4, N_INTRA_PRED_MODES - 1, m.y_mode);
- update_cdf_3d(2, 8, DAV1D_N_SWITCHABLE_FILTERS - 1, m.filter);
- update_bit_1d(6, m.newmv_mode);
- update_bit_1d(2, m.globalmv_mode);
- update_bit_1d(6, m.refmv_mode);
- update_bit_1d(3, m.drl_bit);
- update_cdf_2d(8, N_COMP_INTER_PRED_MODES - 1, m.comp_inter_mode);
- update_bit_1d(4, m.intra);
- update_bit_1d(5, m.comp);
- update_bit_1d(5, m.comp_dir);
- update_bit_1d(6, m.jnt_comp);
- update_bit_1d(6, m.mask_comp);
- update_bit_1d(9, m.wedge_comp);
update_cdf_2d(9, 15, m.wedge_idx);
- update_bit_2d(6, 3, m.ref);
- update_bit_2d(3, 3, m.comp_fwd_ref);
- update_bit_2d(2, 3, m.comp_bwd_ref);
- update_bit_2d(3, 3, m.comp_uni_ref);
- update_bit_1d(3, m.seg_pred);
- update_bit_1d(4, m.interintra);
- update_bit_1d(7, m.interintra_wedge);
+ update_cdf_2d(8, N_COMP_INTER_PRED_MODES - 1, m.comp_inter_mode);
+ update_cdf_3d(2, 8, DAV1D_N_SWITCHABLE_FILTERS - 1, m.filter);
update_cdf_2d(4, 3, m.interintra_mode);
update_cdf_2d(N_BS_SIZES, 2, m.motion_mode);
- update_bit_1d(N_BS_SIZES, m.obmc);
+ update_cdf_2d(3, 1, m.skip_mode);
+ update_cdf_2d(6, 1, m.newmv_mode);
+ update_cdf_2d(2, 1, m.globalmv_mode);
+ update_cdf_2d(6, 1, m.refmv_mode);
+ update_cdf_2d(3, 1, m.drl_bit);
+ update_cdf_2d(4, 1, m.intra);
+ update_cdf_2d(5, 1, m.comp);
+ update_cdf_2d(5, 1, m.comp_dir);
+ update_cdf_2d(6, 1, m.jnt_comp);
+ update_cdf_2d(6, 1, m.mask_comp);
+ update_cdf_2d(9, 1, m.wedge_comp);
+ update_cdf_3d(6, 3, 1, m.ref);
+ update_cdf_3d(3, 3, 1, m.comp_fwd_ref);
+ update_cdf_3d(2, 3, 1, m.comp_bwd_ref);
+ update_cdf_3d(3, 3, 1, m.comp_uni_ref);
+ update_cdf_2d(3, 1, m.seg_pred);
+ update_cdf_2d(4, 1, m.interintra);
+ update_cdf_2d(7, 1, m.interintra_wedge);
+ update_cdf_2d(N_BS_SIZES, 1, m.obmc);
- update_cdf_1d(N_MV_JOINTS - 1, mv.joint);
for (int k = 0; k < 2; k++) {
update_cdf_1d(10, mv.comp[k].classes);
- update_bit_0d(mv.comp[k].class0);
- update_bit_1d(10, mv.comp[k].classN);
+ update_cdf_1d(1, mv.comp[k].sign);
+ update_cdf_1d(1, mv.comp[k].class0);
update_cdf_2d(2, 3, mv.comp[k].class0_fp);
+ update_cdf_1d(1, mv.comp[k].class0_hp);
+ update_cdf_2d(10, 1, mv.comp[k].classN);
update_cdf_1d(3, mv.comp[k].classN_fp);
- update_bit_0d(mv.comp[k].class0_hp);
- update_bit_0d(mv.comp[k].classN_hp);
- update_bit_0d(mv.comp[k].sign);
+ update_cdf_1d(1, mv.comp[k].classN_hp);
}
+ update_cdf_1d(N_MV_JOINTS - 1, mv.joint);
}
/*
* CDF threading wrappers.
*/
-static inline int get_qcat_idx(const int q) {
- if (q <= 20) return 0;
- if (q <= 60) return 1;
- if (q <= 120) return 2;
- return 3;
-}
-
-void dav1d_cdf_thread_init_static(CdfThreadContext *const cdf, const int qidx) {
+void dav1d_cdf_thread_init_static(CdfThreadContext *const cdf, const unsigned qidx) {
cdf->ref = NULL;
- cdf->data.qcat = get_qcat_idx(qidx);
+ cdf->data.qcat = (qidx > 20) + (qidx > 60) + (qidx > 120);
}
void dav1d_cdf_thread_copy(CdfContext *const dst, const CdfThreadContext *const src) {
if (src->ref) {
memcpy(dst, src->data.cdf, sizeof(*dst));
} else {
- dst->m = av1_default_cdf;
- memcpy(dst->kfym, default_kf_y_mode_cdf, sizeof(default_kf_y_mode_cdf));
- dst->coef = av1_default_coef_cdf[src->data.qcat];
- memcpy(dst->mv.joint, default_mv_joint_cdf, sizeof(default_mv_joint_cdf));
- memcpy(dst->dmv.joint, default_mv_joint_cdf, sizeof(default_mv_joint_cdf));
- dst->mv.comp[0] = dst->mv.comp[1] = dst->dmv.comp[0] = dst->dmv.comp[1] =
- default_mv_component_cdf;
+ dst->coef = default_coef_cdf[src->data.qcat];
+ memcpy(&dst->m, &default_cdf.m,
+ offsetof(CdfDefaultContext, mv.joint));
+ memcpy(&dst->mv.comp[1], &default_cdf.mv.comp,
+ sizeof(default_cdf) - offsetof(CdfDefaultContext, mv.comp));
}
}
diff --git a/third_party/dav1d/src/cdf.h b/third_party/dav1d/src/cdf.h
index 4b30474baa..c9b516dc72 100644
--- a/third_party/dav1d/src/cdf.h
+++ b/third_party/dav1d/src/cdf.h
@@ -34,12 +34,10 @@
#include "src/ref.h"
#include "src/thread_data.h"
-/* Buffers padded to [8] or [16] for SIMD where needed. */
+/* Buffers padded to [4]/[8]/[16] for SIMD where needed. */
typedef struct CdfModeContext {
- ALIGN(uint16_t y_mode[4][N_INTRA_PRED_MODES + 3], 32);
ALIGN(uint16_t uv_mode[2][N_INTRA_PRED_MODES][N_UV_INTRA_PRED_MODES + 2], 32);
- ALIGN(uint16_t wedge_idx[9][16], 32);
ALIGN(uint16_t partition[N_BL_LEVELS][4][N_PARTITIONS + 6], 32);
ALIGN(uint16_t cfl_alpha[6][16], 32);
ALIGN(uint16_t txtp_inter1[2][16], 32);
@@ -49,23 +47,33 @@ typedef struct CdfModeContext {
ALIGN(uint16_t cfl_sign[8], 16);
ALIGN(uint16_t angle_delta[8][8], 16);
ALIGN(uint16_t filter_intra[5 + 3], 16);
- ALIGN(uint16_t comp_inter_mode[8][N_COMP_INTER_PRED_MODES], 16);
ALIGN(uint16_t seg_id[3][DAV1D_MAX_SEGMENTS], 16);
ALIGN(uint16_t pal_sz[2][7][7 + 1], 16);
ALIGN(uint16_t color_map[2][7][5][8], 16);
- ALIGN(uint16_t filter[2][8][DAV1D_N_SWITCHABLE_FILTERS + 1], 8);
ALIGN(uint16_t txsz[N_TX_SIZES - 1][3][4], 8);
- ALIGN(uint16_t motion_mode[N_BS_SIZES][3 + 1], 8);
ALIGN(uint16_t delta_q[4], 8);
ALIGN(uint16_t delta_lf[5][4], 8);
- ALIGN(uint16_t interintra_mode[4][4], 8);
ALIGN(uint16_t restore_switchable[3 + 1], 8);
ALIGN(uint16_t restore_wiener[2], 4);
ALIGN(uint16_t restore_sgrproj[2], 4);
- ALIGN(uint16_t interintra[7][2], 4);
- ALIGN(uint16_t interintra_wedge[7][2], 4);
ALIGN(uint16_t txtp_inter3[4][2], 4);
ALIGN(uint16_t use_filter_intra[N_BS_SIZES][2], 4);
+ ALIGN(uint16_t txpart[7][3][2], 4);
+ ALIGN(uint16_t skip[3][2], 4);
+ ALIGN(uint16_t pal_y[7][3][2], 4);
+ ALIGN(uint16_t pal_uv[2][2], 4);
+
+ /* key/intra */
+ ALIGN(uint16_t intrabc[2], 4);
+
+ /* inter/switch */
+ ALIGN(uint16_t y_mode[4][N_INTRA_PRED_MODES + 3], 32);
+ ALIGN(uint16_t wedge_idx[9][16], 32);
+ ALIGN(uint16_t comp_inter_mode[8][N_COMP_INTER_PRED_MODES], 16);
+ ALIGN(uint16_t filter[2][8][DAV1D_N_SWITCHABLE_FILTERS + 1], 8);
+ ALIGN(uint16_t interintra_mode[4][4], 8);
+ ALIGN(uint16_t motion_mode[N_BS_SIZES][3 + 1], 8);
+ ALIGN(uint16_t skip_mode[3][2], 4);
ALIGN(uint16_t newmv_mode[6][2], 4);
ALIGN(uint16_t globalmv_mode[2][2], 4);
ALIGN(uint16_t refmv_mode[6][2], 4);
@@ -80,14 +88,10 @@ typedef struct CdfModeContext {
ALIGN(uint16_t comp_fwd_ref[3][3][2], 4);
ALIGN(uint16_t comp_bwd_ref[2][3][2], 4);
ALIGN(uint16_t comp_uni_ref[3][3][2], 4);
- ALIGN(uint16_t txpart[7][3][2], 4);
- ALIGN(uint16_t skip[3][2], 4);
- ALIGN(uint16_t skip_mode[3][2], 4);
ALIGN(uint16_t seg_pred[3][2], 4);
+ ALIGN(uint16_t interintra[7][2], 4);
+ ALIGN(uint16_t interintra_wedge[7][2], 4);
ALIGN(uint16_t obmc[N_BS_SIZES][2], 4);
- ALIGN(uint16_t pal_y[7][3][2], 4);
- ALIGN(uint16_t pal_uv[2][2], 4);
- ALIGN(uint16_t intrabc[2], 4);
} CdfModeContext;
typedef struct CdfCoefContext {
@@ -108,13 +112,13 @@ typedef struct CdfCoefContext {
typedef struct CdfMvComponent {
ALIGN(uint16_t classes[11 + 5], 32);
+ ALIGN(uint16_t sign[2], 4);
+ ALIGN(uint16_t class0[2], 4);
ALIGN(uint16_t class0_fp[2][4], 8);
- ALIGN(uint16_t classN_fp[4], 8);
ALIGN(uint16_t class0_hp[2], 4);
- ALIGN(uint16_t classN_hp[2], 4);
- ALIGN(uint16_t class0[2], 4);
ALIGN(uint16_t classN[10][2], 4);
- ALIGN(uint16_t sign[2], 4);
+ ALIGN(uint16_t classN_fp[4], 8);
+ ALIGN(uint16_t classN_hp[2], 4);
} CdfMvComponent;
typedef struct CdfMvContext {
@@ -123,10 +127,10 @@ typedef struct CdfMvContext {
} CdfMvContext;
typedef struct CdfContext {
+ CdfCoefContext coef;
CdfModeContext m;
+ CdfMvContext mv;
ALIGN(uint16_t kfym[5][5][N_INTRA_PRED_MODES + 3], 32);
- CdfCoefContext coef;
- CdfMvContext mv, dmv;
} CdfContext;
typedef struct CdfThreadContext {
@@ -138,7 +142,7 @@ typedef struct CdfThreadContext {
atomic_uint *progress;
} CdfThreadContext;
-void dav1d_cdf_thread_init_static(CdfThreadContext *cdf, int qidx);
+void dav1d_cdf_thread_init_static(CdfThreadContext *cdf, unsigned qidx);
int dav1d_cdf_thread_alloc(Dav1dContext *c, CdfThreadContext *cdf,
const int have_frame_mt);
void dav1d_cdf_thread_copy(CdfContext *dst, const CdfThreadContext *src);
diff --git a/third_party/dav1d/src/decode.c b/third_party/dav1d/src/decode.c
index eed9dfb756..7427c35592 100644
--- a/third_party/dav1d/src/decode.c
+++ b/third_party/dav1d/src/decode.c
@@ -73,42 +73,29 @@ static void init_quant_tables(const Dav1dSequenceHeader *const seq_hdr,
}
}
-static int read_mv_component_diff(Dav1dTaskContext *const t,
+static int read_mv_component_diff(MsacContext *const msac,
CdfMvComponent *const mv_comp,
- const int have_fp)
+ const int mv_prec)
{
- Dav1dTileState *const ts = t->ts;
- const Dav1dFrameContext *const f = t->f;
- const int have_hp = f->frame_hdr->hp;
- const int sign = dav1d_msac_decode_bool_adapt(&ts->msac, mv_comp->sign);
- const int cl = dav1d_msac_decode_symbol_adapt16(&ts->msac,
- mv_comp->classes, 10);
- int up, fp, hp;
+ const int sign = dav1d_msac_decode_bool_adapt(msac, mv_comp->sign);
+ const int cl = dav1d_msac_decode_symbol_adapt16(msac, mv_comp->classes, 10);
+ int up, fp = 3, hp = 1;
if (!cl) {
- up = dav1d_msac_decode_bool_adapt(&ts->msac, mv_comp->class0);
- if (have_fp) {
- fp = dav1d_msac_decode_symbol_adapt4(&ts->msac,
- mv_comp->class0_fp[up], 3);
- hp = have_hp ? dav1d_msac_decode_bool_adapt(&ts->msac,
- mv_comp->class0_hp) : 1;
- } else {
- fp = 3;
- hp = 1;
+ up = dav1d_msac_decode_bool_adapt(msac, mv_comp->class0);
+ if (mv_prec >= 0) { // !force_integer_mv
+ fp = dav1d_msac_decode_symbol_adapt4(msac, mv_comp->class0_fp[up], 3);
+ if (mv_prec > 0) // allow_high_precision_mv
+ hp = dav1d_msac_decode_bool_adapt(msac, mv_comp->class0_hp);
}
} else {
up = 1 << cl;
for (int n = 0; n < cl; n++)
- up |= dav1d_msac_decode_bool_adapt(&ts->msac,
- mv_comp->classN[n]) << n;
- if (have_fp) {
- fp = dav1d_msac_decode_symbol_adapt4(&ts->msac,
- mv_comp->classN_fp, 3);
- hp = have_hp ? dav1d_msac_decode_bool_adapt(&ts->msac,
- mv_comp->classN_hp) : 1;
- } else {
- fp = 3;
- hp = 1;
+ up |= dav1d_msac_decode_bool_adapt(msac, mv_comp->classN[n]) << n;
+ if (mv_prec >= 0) { // !force_integer_mv
+ fp = dav1d_msac_decode_symbol_adapt4(msac, mv_comp->classN_fp, 3);
+ if (mv_prec > 0) // allow_high_precision_mv
+ hp = dav1d_msac_decode_bool_adapt(msac, mv_comp->classN_hp);
}
}
@@ -117,25 +104,16 @@ static int read_mv_component_diff(Dav1dTaskContext *const t,
return sign ? -diff : diff;
}
-static void read_mv_residual(Dav1dTaskContext *const t, mv *const ref_mv,
- CdfMvContext *const mv_cdf, const int have_fp)
+static void read_mv_residual(Dav1dTileState *const ts, mv *const ref_mv,
+ const int mv_prec)
{
- switch (dav1d_msac_decode_symbol_adapt4(&t->ts->msac, t->ts->cdf.mv.joint,
- N_MV_JOINTS - 1))
- {
- case MV_JOINT_HV:
- ref_mv->y += read_mv_component_diff(t, &mv_cdf->comp[0], have_fp);
- ref_mv->x += read_mv_component_diff(t, &mv_cdf->comp[1], have_fp);
- break;
- case MV_JOINT_H:
- ref_mv->x += read_mv_component_diff(t, &mv_cdf->comp[1], have_fp);
- break;
- case MV_JOINT_V:
- ref_mv->y += read_mv_component_diff(t, &mv_cdf->comp[0], have_fp);
- break;
- default:
- break;
- }
+ MsacContext *const msac = &ts->msac;
+ const enum MVJoint mv_joint =
+ dav1d_msac_decode_symbol_adapt4(msac, ts->cdf.mv.joint, N_MV_JOINTS - 1);
+ if (mv_joint & MV_JOINT_V)
+ ref_mv->y += read_mv_component_diff(msac, &ts->cdf.mv.comp[0], mv_prec);
+ if (mv_joint & MV_JOINT_H)
+ ref_mv->x += read_mv_component_diff(msac, &ts->cdf.mv.comp[1], mv_prec);
}
static void read_tx_tree(Dav1dTaskContext *const t,
@@ -1001,8 +979,7 @@ static int decode_b(Dav1dTaskContext *const t,
const int have_delta_q = f->frame_hdr->delta.q.present &&
(bs != (f->seq_hdr->sb128 ? BS_128x128 : BS_64x64) || !b->skip);
- int8_t prev_delta_lf[4];
- memcpy(prev_delta_lf, ts->last_delta_lf, 4);
+ uint32_t prev_delta_lf = ts->last_delta_lf.u32;
if (have_delta_q) {
int delta_q = dav1d_msac_decode_symbol_adapt4(&ts->msac,
@@ -1038,8 +1015,8 @@ static int decode_b(Dav1dTaskContext *const t,
delta_lf = -delta_lf;
delta_lf *= 1 << f->frame_hdr->delta.lf.res_log2;
}
- ts->last_delta_lf[i] =
- iclip(ts->last_delta_lf[i] + delta_lf, -63, 63);
+ ts->last_delta_lf.i8[i] =
+ iclip(ts->last_delta_lf.i8[i] + delta_lf, -63, 63);
if (have_delta_q && DEBUG_BLOCK_INFO)
printf("Post-delta_lf[%d:%d]: r=%d\n", i, delta_lf,
ts->msac.rng);
@@ -1054,13 +1031,13 @@ static int decode_b(Dav1dTaskContext *const t,
init_quant_tables(f->seq_hdr, f->frame_hdr, ts->last_qidx, ts->dqmem);
ts->dq = ts->dqmem;
}
- if (!memcmp(ts->last_delta_lf, (int8_t[4]) { 0, 0, 0, 0 }, 4)) {
+ if (!ts->last_delta_lf.u32) {
// assign frame-wide lf values to this sb
ts->lflvl = f->lf.lvl;
- } else if (memcmp(ts->last_delta_lf, prev_delta_lf, 4)) {
+ } else if (ts->last_delta_lf.u32 != prev_delta_lf) {
// find sb-specific lf lvl parameters
- dav1d_calc_lf_values(ts->lflvlmem, f->frame_hdr, ts->last_delta_lf);
ts->lflvl = ts->lflvlmem;
+ dav1d_calc_lf_values(ts->lflvlmem, f->frame_hdr, ts->last_delta_lf.i8);
}
}
@@ -1324,7 +1301,7 @@ static int decode_b(Dav1dTaskContext *const t,
}
const union mv ref = b->mv[0];
- read_mv_residual(t, &b->mv[0], &ts->cdf.dmv, 0);
+ read_mv_residual(ts, &b->mv[0], -1);
// clip intrabc motion vector to decoded parts of current tile
int border_left = ts->tiling.col_start * 4;
@@ -1586,8 +1563,8 @@ static int decode_b(Dav1dTaskContext *const t,
break; \
case NEWMV: \
b->mv[idx] = mvstack[b->drl_idx].mv.mv[idx]; \
- read_mv_residual(t, &b->mv[idx], &ts->cdf.mv, \
- !f->frame_hdr->force_integer_mv); \
+ const int mv_prec = f->frame_hdr->hp - f->frame_hdr->force_integer_mv; \
+ read_mv_residual(ts, &b->mv[idx], mv_prec); \
break; \
}
has_subpel_filter = imin(bw4, bh4) == 1 ||
@@ -1775,8 +1752,8 @@ static int decode_b(Dav1dTaskContext *const t,
if (DEBUG_BLOCK_INFO)
printf("Post-intermode[%d,drl=%d]: r=%d\n",
b->inter_mode, b->drl_idx, ts->msac.rng);
- read_mv_residual(t, &b->mv[0], &ts->cdf.mv,
- !f->frame_hdr->force_integer_mv);
+ const int mv_prec = f->frame_hdr->hp - f->frame_hdr->force_integer_mv;
+ read_mv_residual(ts, &b->mv[0], mv_prec);
if (DEBUG_BLOCK_INFO)
printf("Post-residualmv[mv=y:%d,x:%d]: r=%d\n",
b->mv[0].y, b->mv[0].x, ts->msac.rng);
@@ -2495,7 +2472,7 @@ static void setup_tile(Dav1dTileState *const ts,
dav1d_cdf_thread_copy(&ts->cdf, &f->in_cdf);
ts->last_qidx = f->frame_hdr->quant.yac;
- memset(ts->last_delta_lf, 0, sizeof(ts->last_delta_lf));
+ ts->last_delta_lf.u32 = 0;
dav1d_msac_init(&ts->msac, data, sz, f->frame_hdr->disable_cdf_update);
diff --git a/third_party/dav1d/src/internal.h b/third_party/dav1d/src/internal.h
index 72f65607ed..96bf409c6c 100644
--- a/third_party/dav1d/src/internal.h
+++ b/third_party/dav1d/src/internal.h
@@ -303,8 +303,8 @@ struct Dav1dFrameContext {
int lr_buf_plane_sz[2]; /* (stride*sbh*4) << sb128 if n_tc > 1, else stride*4 */
int re_sz /* h */;
ALIGN(Av1FilterLUT lim_lut, 16);
+ ALIGN(uint8_t lvl[8 /* seg_id */][4 /* dir */][8 /* ref */][2 /* is_gmv */], 16);
int last_sharpness;
- uint8_t lvl[8 /* seg_id */][4 /* dir */][8 /* ref */][2 /* is_gmv */];
uint8_t *tx_lpf_right_edge[2];
uint8_t *cdef_line_buf, *lr_line_buf;
pixel *cdef_line[2 /* pre, post */][3 /* plane */];
@@ -376,8 +376,11 @@ struct Dav1dTileState {
const uint16_t (*dq)[3][2];
int last_qidx;
- int8_t last_delta_lf[4];
- uint8_t lflvlmem[8 /* seg_id */][4 /* dir */][8 /* ref */][2 /* is_gmv */];
+ union {
+ int8_t i8[4];
+ uint32_t u32;
+ } last_delta_lf;
+ ALIGN(uint8_t lflvlmem[8 /* seg_id */][4 /* dir */][8 /* ref */][2 /* is_gmv */], 16);
const uint8_t (*lflvl)[4][8][2];
Av1RestorationUnit *lr_ref[3];
diff --git a/third_party/dav1d/src/itx.h b/third_party/dav1d/src/itx.h
index d522079907..8ef4f4df48 100644
--- a/third_party/dav1d/src/itx.h
+++ b/third_party/dav1d/src/itx.h
@@ -39,10 +39,73 @@ void (name)(pixel *dst, ptrdiff_t dst_stride, coef *coeff, int eob \
HIGHBD_DECL_SUFFIX)
typedef decl_itx_fn(*itxfm_fn);
+#define decl_itx2_fns(w, h, opt) \
+decl_itx_fn(BF(dav1d_inv_txfm_add_dct_dct_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_identity_identity_##w##x##h, opt))
+
+#define decl_itx12_fns(w, h, opt) \
+decl_itx2_fns(w, h, opt); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_dct_adst_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_dct_flipadst_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_dct_identity_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_adst_dct_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_adst_adst_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_adst_flipadst_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_dct_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_adst_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_flipadst_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_identity_dct_##w##x##h, opt))
+
+#define decl_itx16_fns(w, h, opt) \
+decl_itx12_fns(w, h, opt); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_adst_identity_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_identity_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_identity_adst_##w##x##h, opt)); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_identity_flipadst_##w##x##h, opt))
+
+#define decl_itx17_fns(w, h, opt) \
+decl_itx16_fns(w, h, opt); \
+decl_itx_fn(BF(dav1d_inv_txfm_add_wht_wht_##w##x##h, opt))
+
typedef struct Dav1dInvTxfmDSPContext {
itxfm_fn itxfm_add[N_RECT_TX_SIZES][N_TX_TYPES_PLUS_LL];
} Dav1dInvTxfmDSPContext;
bitfn_decls(void dav1d_itx_dsp_init, Dav1dInvTxfmDSPContext *c, int bpc);
+#define assign_itx_fn(pfx, w, h, type, type_enum, ext) \
+ c->itxfm_add[pfx##TX_##w##X##h][type_enum] = \
+ BF(dav1d_inv_txfm_add_##type##_##w##x##h, ext)
+
+#define assign_itx1_fn(pfx, w, h, ext) \
+ assign_itx_fn(pfx, w, h, dct_dct, DCT_DCT, ext)
+
+#define assign_itx2_fn(pfx, w, h, ext) \
+ assign_itx1_fn(pfx, w, h, ext); \
+ assign_itx_fn(pfx, w, h, identity_identity, IDTX, ext)
+
+#define assign_itx12_fn(pfx, w, h, ext) \
+ assign_itx2_fn(pfx, w, h, ext); \
+ assign_itx_fn(pfx, w, h, dct_adst, ADST_DCT, ext); \
+ assign_itx_fn(pfx, w, h, dct_flipadst, FLIPADST_DCT, ext); \
+ assign_itx_fn(pfx, w, h, dct_identity, H_DCT, ext); \
+ assign_itx_fn(pfx, w, h, adst_dct, DCT_ADST, ext); \
+ assign_itx_fn(pfx, w, h, adst_adst, ADST_ADST, ext); \
+ assign_itx_fn(pfx, w, h, adst_flipadst, FLIPADST_ADST, ext); \
+ assign_itx_fn(pfx, w, h, flipadst_dct, DCT_FLIPADST, ext); \
+ assign_itx_fn(pfx, w, h, flipadst_adst, ADST_FLIPADST, ext); \
+ assign_itx_fn(pfx, w, h, flipadst_flipadst, FLIPADST_FLIPADST, ext); \
+ assign_itx_fn(pfx, w, h, identity_dct, V_DCT, ext)
+
+#define assign_itx16_fn(pfx, w, h, ext) \
+ assign_itx12_fn(pfx, w, h, ext); \
+ assign_itx_fn(pfx, w, h, adst_identity, H_ADST, ext); \
+ assign_itx_fn(pfx, w, h, flipadst_identity, H_FLIPADST, ext); \
+ assign_itx_fn(pfx, w, h, identity_adst, V_ADST, ext); \
+ assign_itx_fn(pfx, w, h, identity_flipadst, V_FLIPADST, ext)
+
+#define assign_itx17_fn(pfx, w, h, ext) \
+ assign_itx16_fn(pfx, w, h, ext); \
+ assign_itx_fn(pfx, w, h, wht_wht, WHT_WHT, ext)
+
#endif /* DAV1D_SRC_ITX_H */
diff --git a/third_party/dav1d/src/lf_mask.c b/third_party/dav1d/src/lf_mask.c
index 062ba67371..09a5c532c4 100644
--- a/third_party/dav1d/src/lf_mask.c
+++ b/third_party/dav1d/src/lf_mask.c
@@ -436,7 +436,7 @@ static void calc_lf_value(uint8_t (*const lflvl_values)[2],
const int base = iclip(iclip(base_lvl + lf_delta, 0, 63) + seg_delta, 0, 63);
if (!mr_delta) {
- memset(lflvl_values, base, 8 * 2);
+ memset(lflvl_values, base, sizeof(*lflvl_values) * 8);
} else {
const int sh = base >= 32;
lflvl_values[0][0] = lflvl_values[0][1] =
@@ -457,7 +457,7 @@ static inline void calc_lf_value_chroma(uint8_t (*const lflvl_values)[2],
const Dav1dLoopfilterModeRefDeltas *const mr_delta)
{
if (!base_lvl)
- memset(lflvl_values, 0, 8 * 2);
+ memset(lflvl_values, 0, sizeof(*lflvl_values) * 8);
else
calc_lf_value(lflvl_values, base_lvl, lf_delta, seg_delta, mr_delta);
}
@@ -469,7 +469,7 @@ void dav1d_calc_lf_values(uint8_t (*const lflvl_values)[4][8][2],
const int n_seg = hdr->segmentation.enabled ? 8 : 1;
if (!hdr->loopfilter.level_y[0] && !hdr->loopfilter.level_y[1]) {
- memset(lflvl_values, 0, 8 * 4 * 2 * n_seg);
+ memset(lflvl_values, 0, sizeof(*lflvl_values) * n_seg);
return;
}
diff --git a/third_party/dav1d/src/meson.build b/third_party/dav1d/src/meson.build
index dc4be5fd6f..cd19b70c38 100644
--- a/third_party/dav1d/src/meson.build
+++ b/third_party/dav1d/src/meson.build
@@ -106,6 +106,7 @@ if is_asm_enabled
'arm/64/loopfilter.S',
'arm/64/looprestoration.S',
'arm/64/mc.S',
+ 'arm/64/mc_dotprod.S',
)
endif
diff --git a/third_party/dav1d/src/refmvs.c b/third_party/dav1d/src/refmvs.c
index 200afebde7..1da024b630 100644
--- a/third_party/dav1d/src/refmvs.c
+++ b/third_party/dav1d/src/refmvs.c
@@ -817,7 +817,9 @@ int dav1d_refmvs_init_frame(refmvs_frame *const rf,
if (r_stride != rf->r_stride || n_tile_rows != rf->n_tile_rows) {
if (rf->r) dav1d_freep_aligned(&rf->r);
const int uses_2pass = n_tile_threads > 1 && n_frame_threads > 1;
- rf->r = dav1d_alloc_aligned(ALLOC_REFMVS, sizeof(*rf->r) * 35 * r_stride * n_tile_rows * (1 + uses_2pass), 64);
+ /* sizeof(refmvs_block) == 12 but it's accessed using 16-byte loads in asm,
+ * so add 4 bytes of padding to avoid buffer overreads. */
+ rf->r = dav1d_alloc_aligned(ALLOC_REFMVS, sizeof(*rf->r) * 35 * r_stride * n_tile_rows * (1 + uses_2pass) + 4, 64);
if (!rf->r) return DAV1D_ERR(ENOMEM);
rf->r_stride = r_stride;
}
diff --git a/third_party/dav1d/src/riscv/itx.h b/third_party/dav1d/src/riscv/itx.h
index d3f9a03a03..e11b138348 100644
--- a/third_party/dav1d/src/riscv/itx.h
+++ b/third_party/dav1d/src/riscv/itx.h
@@ -28,34 +28,6 @@
#include "src/cpu.h"
#include "src/itx.h"
-#define decl_itx2_fns(w, h, opt) \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_identity_##w##x##h, opt))
-
-#define decl_itx12_fns(w, h, opt) \
-decl_itx2_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_dct_##w##x##h, opt))
-
-#define decl_itx16_fns(w, h, opt) \
-decl_itx12_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_flipadst_##w##x##h, opt))
-
-#define decl_itx17_fns(w, h, opt) \
-decl_itx16_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_wht_wht_##w##x##h, opt))
-
#define decl_itx_fns(ext) \
decl_itx17_fns( 4, 4, ext); \
decl_itx16_fns( 4, 8, ext); \
@@ -70,41 +42,6 @@ decl_itx16_fns(16, 16, ext)
decl_itx_fns(rvv);
static ALWAYS_INLINE void itx_dsp_init_riscv(Dav1dInvTxfmDSPContext *const c, int const bpc) {
-#define assign_itx_fn(pfx, w, h, type, type_enum, ext) \
- c->itxfm_add[pfx##TX_##w##X##h][type_enum] = \
- BF(dav1d_inv_txfm_add_##type##_##w##x##h, ext)
-
-#define assign_itx1_fn(pfx, w, h, ext) \
- assign_itx_fn(pfx, w, h, dct_dct, DCT_DCT, ext)
-
-#define assign_itx2_fn(pfx, w, h, ext) \
- assign_itx1_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, identity_identity, IDTX, ext)
-
-#define assign_itx12_fn(pfx, w, h, ext) \
- assign_itx2_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, dct_adst, ADST_DCT, ext); \
- assign_itx_fn(pfx, w, h, dct_flipadst, FLIPADST_DCT, ext); \
- assign_itx_fn(pfx, w, h, dct_identity, H_DCT, ext); \
- assign_itx_fn(pfx, w, h, adst_dct, DCT_ADST, ext); \
- assign_itx_fn(pfx, w, h, adst_adst, ADST_ADST, ext); \
- assign_itx_fn(pfx, w, h, adst_flipadst, FLIPADST_ADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_dct, DCT_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_adst, ADST_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_flipadst, FLIPADST_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, identity_dct, V_DCT, ext)
-
-#define assign_itx16_fn(pfx, w, h, ext) \
- assign_itx12_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, adst_identity, H_ADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_identity, H_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, identity_adst, V_ADST, ext); \
- assign_itx_fn(pfx, w, h, identity_flipadst, V_FLIPADST, ext)
-
-#define assign_itx17_fn(pfx, w, h, ext) \
- assign_itx16_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, wht_wht, WHT_WHT, ext)
-
const unsigned flags = dav1d_get_cpu_flags();
if (!(flags & DAV1D_RISCV_CPU_FLAG_V)) return;
diff --git a/third_party/dav1d/src/x86/ipred_avx2.asm b/third_party/dav1d/src/x86/ipred_avx2.asm
index 35738e7c0b..2956ffaf29 100644
--- a/third_party/dav1d/src/x86/ipred_avx2.asm
+++ b/third_party/dav1d/src/x86/ipred_avx2.asm
@@ -66,7 +66,8 @@ z_filter_wh: db 7, 7, 11, 11, 15, 15, 19, 19, 19, 23, 23, 23, 31, 31, 31, 39
z_filter_k: db 0, 16, 0, 16, 0, 20, 0, 20, 8, 16, 8, 16
db 32, 16, 32, 16, 24, 20, 24, 20, 16, 16, 16, 16
db 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0
-z_filter_s: db 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7
+const \
+z_filter_s, db 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7
db 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15
db 15, 15, 15, 15, 15, 15, 15, 15 ; should be in one cache line
pb_128: times 4 db 128 ; those are just placed here for alignment.
diff --git a/third_party/dav1d/src/x86/itx.h b/third_party/dav1d/src/x86/itx.h
index 346fde7d90..23d7a73806 100644
--- a/third_party/dav1d/src/x86/itx.h
+++ b/third_party/dav1d/src/x86/itx.h
@@ -30,34 +30,6 @@
#define BF_BPC(x, bits, suffix) x##_##bits##bpc_##suffix
-#define decl_itx2_fns(w, h, opt) \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_identity_##w##x##h, opt))
-
-#define decl_itx12_fns(w, h, opt) \
-decl_itx2_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_dct_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_dct_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_flipadst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_dct_##w##x##h, opt))
-
-#define decl_itx16_fns(w, h, opt) \
-decl_itx12_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_adst_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_flipadst_identity_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_adst_##w##x##h, opt)); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_identity_flipadst_##w##x##h, opt))
-
-#define decl_itx17_fns(w, h, opt) \
-decl_itx16_fns(w, h, opt); \
-decl_itx_fn(BF(dav1d_inv_txfm_add_wht_wht_##w##x##h, opt))
-
#define decl_itx_fns(ext) \
decl_itx17_fns( 4, 4, ext); \
decl_itx16_fns( 4, 8, ext); \
@@ -136,42 +108,6 @@ decl_itx_fn(dav1d_inv_txfm_add_wht_wht_4x4_16bpc_avx2);
decl_itx_fn(BF(dav1d_inv_txfm_add_wht_wht_4x4, sse2));
static ALWAYS_INLINE void itx_dsp_init_x86(Dav1dInvTxfmDSPContext *const c, const int bpc) {
-#define assign_itx_fn(pfx, w, h, type, type_enum, ext) \
- c->itxfm_add[pfx##TX_##w##X##h][type_enum] = \
- BF(dav1d_inv_txfm_add_##type##_##w##x##h, ext)
-
-#define assign_itx1_fn(pfx, w, h, ext) \
- assign_itx_fn(pfx, w, h, dct_dct, DCT_DCT, ext)
-
-#define assign_itx2_fn(pfx, w, h, ext) \
- assign_itx1_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, identity_identity, IDTX, ext)
-
-#define assign_itx12_fn(pfx, w, h, ext) \
- assign_itx2_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, dct_adst, ADST_DCT, ext); \
- assign_itx_fn(pfx, w, h, dct_flipadst, FLIPADST_DCT, ext); \
- assign_itx_fn(pfx, w, h, dct_identity, H_DCT, ext); \
- assign_itx_fn(pfx, w, h, adst_dct, DCT_ADST, ext); \
- assign_itx_fn(pfx, w, h, adst_adst, ADST_ADST, ext); \
- assign_itx_fn(pfx, w, h, adst_flipadst, FLIPADST_ADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_dct, DCT_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_adst, ADST_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_flipadst, FLIPADST_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, identity_dct, V_DCT, ext)
-
-#define assign_itx16_fn(pfx, w, h, ext) \
- assign_itx12_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, adst_identity, H_ADST, ext); \
- assign_itx_fn(pfx, w, h, flipadst_identity, H_FLIPADST, ext); \
- assign_itx_fn(pfx, w, h, identity_adst, V_ADST, ext); \
- assign_itx_fn(pfx, w, h, identity_flipadst, V_FLIPADST, ext)
-
-#define assign_itx17_fn(pfx, w, h, ext) \
- assign_itx16_fn(pfx, w, h, ext); \
- assign_itx_fn(pfx, w, h, wht_wht, WHT_WHT, ext)
-
-
#define assign_itx_bpc_fn(pfx, w, h, type, type_enum, bpc, ext) \
c->itxfm_add[pfx##TX_##w##X##h][type_enum] = \
BF_BPC(dav1d_inv_txfm_add_##type##_##w##x##h, bpc, ext)
diff --git a/third_party/dav1d/src/x86/mc16_avx2.asm b/third_party/dav1d/src/x86/mc16_avx2.asm
index 42e2a5525e..6b4424946b 100644
--- a/third_party/dav1d/src/x86/mc16_avx2.asm
+++ b/third_party/dav1d/src/x86/mc16_avx2.asm
@@ -1222,7 +1222,7 @@ cglobal prep_bilin_16bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
%assign FILTER_SMOOTH (1*15 << 16) | 4*15
%assign FILTER_SHARP (2*15 << 16) | 3*15
-%macro FN 4 ; prefix, type, type_h, type_v
+%macro FN 4-5 ; prefix, type, type_h, type_v, jmp_to
cglobal %1_%2_16bpc
mov t0d, FILTER_%3
%ifidn %3, %4
@@ -1230,8 +1230,8 @@ cglobal %1_%2_16bpc
%else
mov t1d, FILTER_%4
%endif
-%ifnidn %2, regular ; skip the jump in the last filter
- jmp mangle(private_prefix %+ _%1_16bpc %+ SUFFIX)
+%if %0 == 5 ; skip the jump in the last filter
+ jmp mangle(private_prefix %+ _%5 %+ SUFFIX)
%endif
%endmacro
@@ -1242,22 +1242,17 @@ DECLARE_REG_TMP 7, 8
%endif
%define PUT_8TAP_FN FN put_8tap,
-PUT_8TAP_FN sharp, SHARP, SHARP
-PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH
-PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP
-PUT_8TAP_FN smooth, SMOOTH, SMOOTH
-PUT_8TAP_FN sharp_regular, SHARP, REGULAR
-PUT_8TAP_FN regular_sharp, REGULAR, SHARP
-PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR
-PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH
+PUT_8TAP_FN smooth, SMOOTH, SMOOTH, put_6tap_16bpc
+PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR, put_6tap_16bpc
+PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH, put_6tap_16bpc
PUT_8TAP_FN regular, REGULAR, REGULAR
-cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
+cglobal put_6tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
%define base r8-put_avx2
imul mxd, mxm, 0x010101
- add mxd, t0d ; 8tap_h, mx, 4tap_h
+ add mxd, t0d ; 6tap_h, mx, 4tap_h
imul myd, mym, 0x010101
- add myd, t1d ; 8tap_v, my, 4tap_v
+ add myd, t1d ; 6tap_v, my, 4tap_v
lea r8, [put_avx2]
movifnidn wd, wm
movifnidn hd, hm
@@ -1265,6 +1260,7 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
jnz .h
test myd, 0xf00
jnz .v
+.put:
tzcnt wd, wd
movzx wd, word [r8+wq*2+table_offset(put,)]
add wq, r8
@@ -1337,43 +1333,36 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
cmp wd, 4
je .h_w4
jl .h_w2
- WIN64_SPILL_XMM 13
+ WIN64_SPILL_XMM 11
shr mxd, 16
- sub srcq, 6
- vpbroadcastq m0, [base+subpel_filters+mxq*8]
- vbroadcasti128 m6, [subpel_h_shufA]
- vbroadcasti128 m7, [subpel_h_shufB]
+ sub srcq, 4
+ vpbroadcastq m0, [base+subpel_filters+1+mxq*8]
+ vbroadcasti128 m6, [base+subpel_h_shufA]
punpcklbw m0, m0
psraw m0, 8 ; sign-extend
- pshufd m8, m0, q0000
- pshufd m9, m0, q1111
- pshufd m10, m0, q2222
- pshufd m11, m0, q3333
- cmp wd, 8
- jg .h_w16
+ pshufd m7, m0, q0000
+ pshufd m8, m0, q1111
+ pshufd m9, m0, q2222
+ sub wd, 16
+ jge .h_w16
.h_w8:
-%macro PUT_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
- pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6
- pshufb m%1, m6 ; 0 1 1 2 2 3 3 4
- pmaddwd m%5, m9, m%4 ; abcd1
- pmaddwd m%1, m8 ; abcd0
- pshufb m%2, m7 ; 6 7 7 8 8 9 9 a
- shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8
- paddd m%5, m4
- paddd m%1, m%5
- pmaddwd m%5, m11, m%2 ; abcd3
- paddd m%1, m%5
- pmaddwd m%5, m10, m%4 ; abcd2
- pshufb m%3, m7 ; a b b c c d d e
- pmaddwd m%4, m8 ; efgh0
- paddd m%1, m%5
- pmaddwd m%5, m9, m%2 ; efgh1
- shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c
- pmaddwd m%3, m11 ; efgh3
- pmaddwd m%2, m10 ; efgh2
+%macro PUT_6TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
+ pshufb m%1, m6 ; 01 12 23 34
+ pshufb m%2, m6 ; 45 56 67 78
+ pmaddwd m%4, m7, m%1 ; a0
+ pshufb m%3, m6 ; 89 9a ab bc
+ pmaddwd m%5, m9, m%2 ; a2
+ shufpd m%1, m%2, 0x05 ; 23 34 45 56
+ paddd m%4, m%5 ; a0+a2
+ pmaddwd m%5, m7, m%2 ; b0
+ shufpd m%2, m%3, 0x05 ; 67 78 89 9a
+ pmaddwd m%3, m9 ; b2
+ pmaddwd m%1, m8 ; a1
+ pmaddwd m%2, m8 ; b1
+ paddd m%3, m%5 ; b0+b2
paddd m%4, m4
- paddd m%4, m%5
- paddd m%3, m%4
+ paddd m%3, m4
+ paddd m%1, m%4
paddd m%2, m%3
psrad m%1, 6
psrad m%2, 6
@@ -1384,9 +1373,9 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
vinserti128 m0, [srcq+ssq*1+ 0], 1
movu xm2, [srcq+ssq*0+16]
vinserti128 m2, [srcq+ssq*1+16], 1
- lea srcq, [srcq+ssq*2]
shufpd m1, m0, m2, 0x05
- PUT_8TAP_H 0, 1, 2, 3, 12
+ lea srcq, [srcq+ssq*2]
+ PUT_6TAP_H 0, 1, 2, 3, 10
mova [dstq+dsq*0], xm0
vextracti128 [dstq+dsq*1], m0, 1
lea dstq, [dstq+dsq*2]
@@ -1396,13 +1385,13 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
.h_w16:
mov r6d, wd
.h_w16_loop:
- movu m0, [srcq+r6*2-32]
- movu m1, [srcq+r6*2-24]
- movu m2, [srcq+r6*2-16]
- PUT_8TAP_H 0, 1, 2, 3, 12
- mova [dstq+r6*2-32], m0
+ movu m0, [srcq+r6*2+ 0]
+ movu m1, [srcq+r6*2+ 8]
+ movu m2, [srcq+r6*2+16]
+ PUT_6TAP_H 0, 1, 2, 3, 10
+ mova [dstq+r6*2], m0
sub r6d, 16
- jg .h_w16_loop
+ jge .h_w16_loop
add srcq, ssq
add dstq, dsq
dec hd
@@ -1411,10 +1400,449 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
.v:
movzx mxd, myb
shr myd, 16
- cmp hd, 4
- cmovle myd, mxd
+ cmp hd, 6
+ cmovs myd, mxd
+ vpbroadcastq m0, [base+subpel_filters+1+myq*8]
+ WIN64_SPILL_XMM 10, 12
+ vpbroadcastd m5, [pd_32]
+ vpbroadcastw m6, r8m
+ punpcklbw m0, m0
+ mov r6, ssq
+ psraw m0, 8 ; sign-extend
+ neg r6
+ pshufd m7, m0, q0000
+ pshufd m8, m0, q1111
+ pshufd m9, m0, q2222
+ cmp wd, 4
+ jg .v_w8
+ je .v_w4
+.v_w2:
+ movd xm2, [srcq+r6 *2]
+ pinsrd xm2, [srcq+r6 *1], 1
+ pinsrd xm2, [srcq+ssq*0], 2
+ pinsrd xm2, [srcq+ssq*1], 3 ; 0 1 2 3
+ lea srcq, [srcq+ssq*2]
+ movd xm0, [srcq+ssq*0]
+ palignr xm3, xm0, xm2, 4 ; 1 2 3 4
+ punpcklwd xm1, xm2, xm3 ; 01 12
+ punpckhwd xm2, xm3 ; 23 34
+.v_w2_loop:
+ movd xm3, [srcq+ssq*1]
+ pmaddwd xm4, xm7, xm1 ; a0 b0
+ mova xm1, xm2
+ pmaddwd xm2, xm8 ; a1 b1
+ lea srcq, [srcq+ssq*2]
+ paddd xm4, xm2
+ punpckldq xm2, xm0, xm3 ; 4 5
+ movd xm0, [srcq+ssq*0]
+ punpckldq xm3, xm0 ; 5 6
+ punpcklwd xm2, xm3 ; 45 56
+ pmaddwd xm3, xm9, xm2 ; a2 b2
+ paddd xm4, xm5
+ paddd xm4, xm3
+ psrad xm4, 6
+ packusdw xm4, xm4
+ pminsw xm4, xm6
+ movd [dstq+dsq*0], xm4
+ pextrd [dstq+dsq*1], xm4, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .v_w2_loop
+ RET
+.v_w4:
+ movq xm1, [srcq+r6 *2]
+ vpbroadcastq m3, [srcq+r6 *1]
+ vpbroadcastq m2, [srcq+ssq*0]
+ vpbroadcastq m4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vpbroadcastq m0, [srcq+ssq*0]
+ vpblendd m1, m3, 0x30
+ vpblendd m3, m2, 0x30
+ punpcklwd m1, m3 ; 01 12
+ vpblendd m2, m4, 0x30
+ vpblendd m4, m0, 0x30
+ punpcklwd m2, m4 ; 23 34
+.v_w4_loop:
+ vpbroadcastq m3, [srcq+ssq*1]
+ pmaddwd m4, m7, m1 ; a0 b0
+ mova m1, m2
+ pmaddwd m2, m8 ; a1 b1
+ lea srcq, [srcq+ssq*2]
+ paddd m4, m2
+ vpblendd m2, m0, m3, 0x30
+ vpbroadcastq m0, [srcq+ssq*0]
+ vpblendd m3, m0, 0x30
+ punpcklwd m2, m3 ; 45 56
+ pmaddwd m3, m9, m2 ; a2 b2
+ paddd m4, m5
+ paddd m4, m3
+ psrad m4, 6
+ vextracti128 xm3, m4, 1
+ packusdw xm4, xm3
+ pminsw xm4, xm6
+ movq [dstq+dsq*0], xm4
+ movhps [dstq+dsq*1], xm4
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .v_w4_loop
+ RET
+.v_w8:
+ shl wd, 5
+ WIN64_PUSH_XMM 12
+ lea wd, [hq+wq-256]
+.v_w8_loop0:
+ vbroadcasti128 m3, [srcq+r6 *2]
+ vbroadcasti128 m4, [srcq+r6 *1]
+ lea r7, [srcq+ssq*2]
+ vbroadcasti128 m0, [srcq+ssq*0]
+ vbroadcasti128 m1, [srcq+ssq*1]
+ mov r8, dstq
+ vbroadcasti128 m2, [r7+ssq*0]
+ shufpd m3, m0, 0x0c
+ shufpd m4, m1, 0x0c
+ punpcklwd m1, m3, m4 ; 01
+ punpckhwd m3, m4 ; 23
+ shufpd m0, m2, 0x0c
+ punpcklwd m2, m4, m0 ; 12
+ punpckhwd m4, m0 ; 34
+.v_w8_loop:
+ vbroadcasti128 m5, [r7+ssq*1]
+ pmaddwd m10, m7, m1 ; a0
+ lea r7, [r7+ssq*2]
+ pmaddwd m11, m7, m2 ; b0
+ mova m1, m3
+ pmaddwd m3, m8 ; a1
+ mova m2, m4
+ pmaddwd m4, m8 ; b1
+ paddd m10, m3
+ vbroadcasti128 m3, [r7+ssq*0]
+ paddd m11, m4
+ shufpd m4, m0, m5, 0x0d
+ shufpd m0, m5, m3, 0x0c
+ punpcklwd m3, m4, m0 ; 45
+ punpckhwd m4, m0 ; 56
+ pmaddwd m5, m9, m3 ; a2
+ paddd m10, m5
+ pmaddwd m5, m9, m4 ; b2
+ paddd m5, m11
+ psrad m10, 5
+ psrad m5, 5
+ packusdw m10, m5
+ pxor m5, m5
+ pavgw m5, m10
+ pminsw m5, m6
+ vpermq m5, m5, q3120
+ mova [r8+dsq*0], xm5
+ vextracti128 [r8+dsq*1], m5, 1
+ lea r8, [r8+dsq*2]
+ sub hd, 2
+ jg .v_w8_loop
+ add srcq, 16
+ add dstq, 16
+ movzx hd, wb
+ sub wd, 1<<8
+ jg .v_w8_loop0
+ RET
+.hv:
+ WIN64_SPILL_XMM 12, 16
+ vpbroadcastd m10, [pd_512]
+ vpbroadcastw m11, r8m
+ cmp wd, 4
+ jg .hv_w8
+ movzx mxd, mxb
+ vpbroadcastd m0, [base+subpel_filters+mxq*8+2]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ vpbroadcastq m1, [base+subpel_filters+1+myq*8]
+ mov r6, ssq
+ sub srcq, 2
+ neg r6
+ pxor m6, m6
+ punpcklbw m6, m0
+ punpcklbw m1, m1
+ psraw m1, 8 ; sign-extend
+ test dword r8m, 0x800
+ jz .hv_10bit
+ psraw m6, 2
+ psllw m1, 2
+.hv_10bit:
+ pshufd m7, m1, q0000
+ pshufd m8, m1, q1111
+ pshufd m9, m1, q2222
+ cmp wd, 4
+ je .hv_w4
+ vbroadcasti128 m5, [subpel_h_shuf2]
+ vbroadcasti128 m0, [srcq+ssq*0]
+ vinserti128 m2, m0, [srcq+r6*2], 1 ; 2 0
+ movu xm1, [srcq+ssq*1]
+ vinserti128 m1, [srcq+r6 *1], 1 ; 3 1
+ lea srcq, [srcq+ssq*2]
+ vinserti128 m0, [srcq+ssq*0], 0 ; 4 2
+ REPX {pshufb x, m5}, m2, m1, m0
+ REPX {pmaddwd x, m6}, m2, m1, m0
+ phaddd m2, m1
+ phaddd m1, m0
+ paddd m2, m10
+ paddd m1, m10
+ psrad m2, 10
+ psrad m1, 10
+ packssdw m2, m1 ; 2 3 3 4 0 1 1 2
+ punpckhqdq m0, m2, m2
+ punpcklwd m2, m0 ; 23 34
+ vextracti128 xm1, m2, 1 ; 01 12
+.hv_w2_loop:
+ movu xm3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ movu xm4, [srcq+ssq*0]
+ pshufb xm3, xm5
+ pshufb xm4, xm5
+ pmaddwd xm3, xm6
+ pmaddwd xm4, xm6
+ phaddd xm3, xm4
+ pmaddwd xm4, xm7, xm1 ; a0 b0
+ mova xm1, xm2
+ pmaddwd xm2, xm8 ; a1 b1
+ paddd xm4, xm2
+ paddd xm3, xm10
+ psrad xm3, 10
+ packssdw xm3, xm3
+ palignr xm2, xm3, xm0, 12
+ mova xm0, xm3
+ punpcklwd xm2, xm0 ; 45 56
+ pmaddwd xm3, xm9, xm2 ; a2 b2
+ paddd xm4, xm10
+ paddd xm4, xm3
+ psrad xm4, 10
+ packusdw xm4, xm4
+ pminsw xm4, xm11
+ movd [dstq+dsq*0], xm4
+ pextrd [dstq+dsq*1], xm4, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .hv_w2_loop
+ RET
+.hv_w4:
+ WIN64_PUSH_XMM 14
+ vbroadcasti128 m12, [subpel_h_shufA]
+ pshufd m5, m6, q0000
+ vbroadcasti128 m13, [subpel_h_shufB]
+ pshufd m6, m6, q1111
+ movu xm2, [srcq+r6 *2]
+ vinserti128 m2, [srcq+r6 *1], 1 ; 0 1
+ movu xm0, [srcq+ssq*0]
+ vinserti128 m0, [srcq+ssq*1], 1 ; 2 3
+ lea srcq, [srcq+ssq*2]
+ movu xm3, [srcq+ssq*0] ; 4
+ pshufb m1, m2, m12
+ pmaddwd m1, m5
+ pshufb m2, m13
+ pmaddwd m2, m6
+ pshufb m4, m0, m12
+ pmaddwd m4, m5
+ pshufb m0, m13
+ pmaddwd m0, m6
+ paddd m2, m1
+ pshufb xm1, xm3, xm12
+ pmaddwd xm1, xm5
+ pshufb xm3, xm13
+ pmaddwd xm3, xm6
+ paddd m0, m4
+ paddd m2, m10
+ paddd xm1, xm10
+ paddd m0, m10
+ paddd xm3, xm1
+ REPX {psrad x, 10}, m2, m0, xm3
+ packssdw m2, m0 ; 0 2 1 3
+ packssdw xm0, xm3 ; 2 4
+ vperm2i128 m0, m2, 0x03
+ punpcklwd m1, m2, m0 ; 01 12
+ punpckhwd m2, m0 ; 23 34
+.hv_w4_loop:
+ movu xm3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vinserti128 m3, [srcq+ssq*0], 1
+ pmaddwd m4, m7, m1 ; a0 b0
+ mova m1, m2
+ pmaddwd m2, m8 ; a1 b1
+ paddd m4, m2
+ pshufb m2, m3, m12
+ pmaddwd m2, m5
+ pshufb m3, m13
+ pmaddwd m3, m6
+ paddd m2, m10
+ paddd m3, m2
+ psrad m3, 10
+ packssdw m3, m3 ; 5 5 6 6
+ vperm2i128 m2, m0, m3, 0x21
+ mova m0, m3
+ punpckhwd m2, m3 ; 45 56
+ pmaddwd m3, m9, m2 ; a2 b2
+ paddd m4, m10
+ paddd m4, m3
+ psrad m4, 10
+ vextracti128 xm3, m4, 1
+ packusdw xm4, xm3
+ pminsw xm4, xm11
+ movq [dstq+dsq*0], xm4
+ movhps [dstq+dsq*1], xm4
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .hv_w4_loop
+ RET
+.hv_w8:
+ WIN64_PUSH_XMM 16, 12
+ shr mxd, 16
+ vbroadcasti128 m12, [subpel_h_shufA]
+ vpbroadcastq m2, [base+subpel_filters+1+mxq*8]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ pmovsxbw xm1, [base+subpel_filters+1+myq*8]
+ shl wd, 5
+ mov r6, ssq
+ sub srcq, 4
+ pxor m0, m0
+ neg r6
+ punpcklbw m0, m2
+ lea wd, [hq+wq-256]
+ test dword r8m, 0x800
+ jz .hv_w8_10bit
+ psraw m0, 2
+ psllw xm1, 2
+.hv_w8_10bit:
+ pshufd m7, m0, q0000
+ pshufd m8, m0, q1111
+%if WIN64
+ %define v_mul (rsp+stack_offset+40) ; r4m
+%else
+ %define v_mul (rsp+stack_offset+ 8) ; r6m
+%endif
+ mova [v_mul], xm1
+ pshufd m9, m0, q2222
+.hv_w8_loop0:
+ vbroadcasti128 m0, [srcq+ssq*0+ 0]
+ vinserti128 m3, m0, [srcq+r6*2+ 0], 0
+ lea r7, [srcq+ssq*2]
+ vbroadcasti128 m2, [srcq+ssq*0+16]
+ vinserti128 m1, m2, [srcq+r6*2+16], 0
+ mov r8, dstq
+ vinserti128 m0, [r7 +ssq*0+ 0], 1
+ vinserti128 m2, [r7 +ssq*0+16], 1
+ shufpd m4, m3, m1, 0x05
+%macro PUT_6TAP_HV_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
+ pshufb m%1, m12 ; 01 12 23 34
+ pshufb m%2, m12 ; 45 56 67 78
+ pmaddwd m%4, m7, m%1 ; a0
+ pshufb m%3, m12 ; 89 9a ab bc
+ pmaddwd m%5, m9, m%2 ; a2
+ shufpd m%1, m%2, 0x05 ; 23 34 45 56
+ paddd m%4, m%5 ; a0+a2
+ pmaddwd m%5, m7, m%2 ; b0
+ shufpd m%2, m%3, 0x05 ; 67 78 89 9a
+ pmaddwd m%3, m9 ; b2
+ pmaddwd m%1, m8 ; a1
+ pmaddwd m%2, m8 ; b1
+ paddd m%3, m%5 ; b0+b2
+ paddd m%4, m10
+ paddd m%3, m10
+ paddd m%1, m%4
+ paddd m%2, m%3
+ psrad m%1, 10
+ psrad m%2, 10
+ packssdw m%1, m%2
+%endmacro
+ PUT_6TAP_HV_H 3, 4, 1, 5, 6 ; 0 2
+ movu xm4, [srcq+r6 *1+ 0]
+ vinserti128 m4, [srcq+ssq*1+ 0], 1
+ shufpd m1, m0, m2, 0x05
+ PUT_6TAP_HV_H 0, 1, 2, 5, 6 ; 2 4
+ movu xm2, [srcq+r6 *1+16]
+ vinserti128 m2, [srcq+ssq*1+16], 1
+ shufpd m1, m4, m2, 0x05
+ PUT_6TAP_HV_H 4, 1, 2, 5, 6 ; 1 3
+ vpermq m3, m3, q3120
+ vpermq m4, m4, q3120
+ vpermq m0, m0, q3120
+ punpcklwd m1, m3, m4 ; 01
+ punpckhwd m3, m4 ; 23
+ punpcklwd m2, m4, m0 ; 12
+ punpckhwd m4, m0 ; 34
+.hv_w8_loop:
+ vpbroadcastd m15, [v_mul+4*0]
+ vpbroadcastd m13, [v_mul+4*1]
+ movu xm5, [r7+ssq*1+ 0]
+ movu xm6, [r7+ssq*1+16]
+ lea r7, [r7+ssq*2]
+ pmaddwd m14, m15, m1 ; a0
+ pmaddwd m15, m2 ; b0
+ vinserti128 m5, [r7+ssq*0+ 0], 1
+ vinserti128 m6, [r7+ssq*0+16], 1
+ mova m1, m3
+ pmaddwd m3, m13 ; a1
+ mova m2, m4
+ pmaddwd m4, m13 ; b1
+ paddd m14, m3
+ shufpd m3, m5, m6, 0x05
+ paddd m15, m4
+ PUT_6TAP_HV_H 5, 3, 6, 4, 13 ; 5 6
+ vpbroadcastd m6, [v_mul+4*2]
+ vpermq m5, m5, q3120
+ shufpd m4, m0, m5, 0x05
+ mova m0, m5
+ punpcklwd m3, m4, m5 ; 45
+ punpckhwd m4, m5 ; 56
+ pmaddwd m5, m6, m3 ; a2
+ pmaddwd m6, m4 ; b2
+ paddd m14, m10
+ paddd m15, m10
+ paddd m5, m14
+ paddd m6, m15
+ psrad m5, 10
+ psrad m6, 10
+ packusdw m5, m6
+ pminsw m5, m11
+ vpermq m5, m5, q3120
+ mova [r8+dsq*0], xm5
+ vextracti128 [r8+dsq*1], m5, 1
+ lea r8, [r8+dsq*2]
+ sub hd, 2
+ jg .hv_w8_loop
+ add srcq, 16
+ add dstq, 16
+ movzx hd, wb
+ sub wd, 1<<8
+ jg .hv_w8_loop0
+ RET
+
+PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP, put_8tap_16bpc
+PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH, put_8tap_16bpc
+PUT_8TAP_FN regular_sharp, REGULAR, SHARP, put_8tap_16bpc
+PUT_8TAP_FN sharp_regular, SHARP, REGULAR, put_8tap_16bpc
+PUT_8TAP_FN sharp, SHARP, SHARP
+
+cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
+%define base r8-put_avx2
+ imul mxd, mxm, 0x010101
+ add mxd, t0d ; 8tap_h, mx, 4tap_h
+ imul myd, mym, 0x010101
+ add myd, t1d ; 8tap_v, my, 4tap_v
+ lea r8, [put_avx2]
+ movifnidn wd, wm
+ movifnidn hd, hm
+ test mxd, 0xf00
+ jnz .h
+ test myd, 0xf00
+ jz mangle(private_prefix %+ _put_6tap_16bpc_avx2).put
+.v:
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
vpbroadcastq m0, [base+subpel_filters+myq*8]
- WIN64_SPILL_XMM 15
+ WIN64_SPILL_XMM 12, 15
vpbroadcastd m6, [pd_32]
vpbroadcastw m7, r8m
lea r6, [ssq*3]
@@ -1518,19 +1946,19 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
RET
.v_w8:
shl wd, 5
- mov r7, srcq
- mov r8, dstq
+ WIN64_PUSH_XMM 15
lea wd, [hq+wq-256]
.v_w8_loop0:
vbroadcasti128 m4, [srcq+ssq*0]
vbroadcasti128 m5, [srcq+ssq*1]
+ lea r7, [srcq+ssq*4]
vbroadcasti128 m0, [srcq+r6 ]
vbroadcasti128 m6, [srcq+ssq*2]
- lea srcq, [srcq+ssq*4]
- vbroadcasti128 m1, [srcq+ssq*0]
- vbroadcasti128 m2, [srcq+ssq*1]
- vbroadcasti128 m3, [srcq+ssq*2]
- add srcq, r6
+ mov r8, dstq
+ vbroadcasti128 m1, [r7+ssq*0]
+ vbroadcasti128 m2, [r7+ssq*1]
+ vbroadcasti128 m3, [r7+ssq*2]
+ add r7, r6
shufpd m4, m0, 0x0c
shufpd m5, m1, 0x0c
punpcklwd m1, m4, m5 ; 01
@@ -1542,7 +1970,7 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
punpcklwd m3, m6, m0 ; 23
punpckhwd m6, m0 ; 56
.v_w8_loop:
- vbroadcasti128 m14, [srcq+ssq*0]
+ vbroadcasti128 m14, [r7+ssq*0]
pmaddwd m12, m8, m1 ; a0
pmaddwd m13, m8, m2 ; b0
mova m1, m3
@@ -1556,8 +1984,8 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
pmaddwd m5, m10 ; a2
pmaddwd m6, m10 ; b2
paddd m12, m5
- vbroadcasti128 m5, [srcq+ssq*1]
- lea srcq, [srcq+ssq*2]
+ vbroadcasti128 m5, [r7+ssq*1]
+ lea r7, [r7+ssq*2]
paddd m13, m6
shufpd m6, m0, m14, 0x0d
shufpd m0, m14, m5, 0x0c
@@ -1574,19 +2002,99 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
pavgw m12, m13
pminsw m12, m7
vpermq m12, m12, q3120
- mova [dstq+dsq*0], xm12
- vextracti128 [dstq+dsq*1], m12, 1
- lea dstq, [dstq+dsq*2]
+ mova [r8+dsq*0], xm12
+ vextracti128 [r8+dsq*1], m12, 1
+ lea r8, [r8+dsq*2]
sub hd, 2
jg .v_w8_loop
- add r7, 16
- add r8, 16
+ add srcq, 16
+ add dstq, 16
movzx hd, wb
- mov srcq, r7
- mov dstq, r8
sub wd, 1<<8
jg .v_w8_loop0
RET
+.h:
+ RESET_STACK_STATE
+ test myd, 0xf00
+ jnz .hv
+ mov r7d, r8m
+ vpbroadcastw m5, r8m
+ shr r7d, 11
+ vpbroadcastd m4, [base+put_8tap_h_rnd+r7*4]
+ cmp wd, 4
+ jl mangle(private_prefix %+ _put_6tap_16bpc_avx2).h_w2
+ je mangle(private_prefix %+ _put_6tap_16bpc_avx2).h_w4
+ WIN64_SPILL_XMM 13
+ shr mxd, 16
+ sub srcq, 6
+ vpbroadcastq m0, [base+subpel_filters+mxq*8]
+ vbroadcasti128 m6, [subpel_h_shufA]
+ vbroadcasti128 m7, [subpel_h_shufB]
+ punpcklbw m0, m0
+ psraw m0, 8 ; sign-extend
+ pshufd m8, m0, q0000
+ pshufd m9, m0, q1111
+ pshufd m10, m0, q2222
+ pshufd m11, m0, q3333
+ sub wd, 16
+ jge .h_w16
+.h_w8:
+%macro PUT_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
+ pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6
+ pshufb m%1, m6 ; 0 1 1 2 2 3 3 4
+ pmaddwd m%5, m9, m%4 ; abcd1
+ pmaddwd m%1, m8 ; abcd0
+ pshufb m%2, m7 ; 6 7 7 8 8 9 9 a
+ shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8
+ paddd m%5, m4
+ paddd m%1, m%5
+ pmaddwd m%5, m11, m%2 ; abcd3
+ paddd m%1, m%5
+ pmaddwd m%5, m10, m%4 ; abcd2
+ pshufb m%3, m7 ; a b b c c d d e
+ pmaddwd m%4, m8 ; efgh0
+ paddd m%1, m%5
+ pmaddwd m%5, m9, m%2 ; efgh1
+ shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c
+ pmaddwd m%3, m11 ; efgh3
+ pmaddwd m%2, m10 ; efgh2
+ paddd m%4, m4
+ paddd m%4, m%5
+ paddd m%3, m%4
+ paddd m%2, m%3
+ psrad m%1, 6
+ psrad m%2, 6
+ packusdw m%1, m%2
+ pminsw m%1, m5
+%endmacro
+ movu xm0, [srcq+ssq*0+ 0]
+ vinserti128 m0, [srcq+ssq*1+ 0], 1
+ movu xm2, [srcq+ssq*0+16]
+ vinserti128 m2, [srcq+ssq*1+16], 1
+ lea srcq, [srcq+ssq*2]
+ shufpd m1, m0, m2, 0x05
+ PUT_8TAP_H 0, 1, 2, 3, 12
+ mova [dstq+dsq*0], xm0
+ vextracti128 [dstq+dsq*1], m0, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w8
+ RET
+.h_w16:
+ mov r6d, wd
+.h_w16_loop:
+ movu m0, [srcq+r6*2+ 0]
+ movu m1, [srcq+r6*2+ 8]
+ movu m2, [srcq+r6*2+16]
+ PUT_8TAP_H 0, 1, 2, 3, 12
+ mova [dstq+r6*2], m0
+ sub r6d, 16
+ jge .h_w16_loop
+ add srcq, ssq
+ add dstq, dsq
+ dec hd
+ jg .h_w16
+ RET
.hv:
WIN64_SPILL_XMM 16
vpbroadcastw m15, r8m
@@ -1596,8 +2104,8 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
vpbroadcastd m0, [base+subpel_filters+mxq*8+2]
movzx mxd, myb
shr myd, 16
- cmp hd, 4
- cmovle myd, mxd
+ cmp hd, 6
+ cmovs myd, mxd
vpbroadcastq m1, [base+subpel_filters+myq*8]
vpbroadcastd m6, [pd_512]
lea r6, [ssq*3]
@@ -1773,17 +2281,15 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
vpbroadcastq m2, [base+subpel_filters+mxq*8]
movzx mxd, myb
shr myd, 16
- cmp hd, 4
- cmovle myd, mxd
+ cmp hd, 6
+ cmovs myd, mxd
pmovsxbw xm1, [base+subpel_filters+myq*8]
shl wd, 5
lea r6, [ssq*3]
sub srcq, 6
- sub srcq, r6
pxor m0, m0
+ sub srcq, r6
punpcklbw m0, m2
- mov r7, srcq
- mov r8, dstq
lea wd, [hq+wq-256]
test dword r8m, 0x800
jz .hv_w8_10bit
@@ -1792,14 +2298,9 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
.hv_w8_10bit:
pshufd m11, m0, q0000
pshufd m12, m0, q1111
+ mova [v_mul], xm1
pshufd m13, m0, q2222
pshufd m14, m0, q3333
-%if WIN64
- %define v_mul (rsp+stack_offset+40) ; r4m
-%else
- %define v_mul (rsp-24) ; red zone
-%endif
- mova [v_mul], xm1
.hv_w8_loop0:
%macro PUT_8TAP_HV_H 3 ; dst/src+0, src+8, src+16
pshufb m2, m%1, m9 ; 2 3 3 4 4 5 5 6
@@ -1830,14 +2331,16 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
%endmacro
movu xm4, [srcq+r6 *1+ 0]
vbroadcasti128 m8, [subpel_h_shufA]
+ lea r7, [srcq+ssq*4]
movu xm6, [srcq+r6 *1+ 8]
vbroadcasti128 m9, [subpel_h_shufB]
+ mov r8, dstq
movu xm0, [srcq+r6 *1+16]
vpbroadcastd m10, [pd_512]
movu xm5, [srcq+ssq*0+ 0]
- vinserti128 m5, [srcq+ssq*4+ 0], 1
+ vinserti128 m5, [r7 +ssq*0+ 0], 1
movu xm1, [srcq+ssq*0+16]
- vinserti128 m1, [srcq+ssq*4+16], 1
+ vinserti128 m1, [r7 +ssq*0+16], 1
shufpd m7, m5, m1, 0x05
INIT_XMM avx2
PUT_8TAP_HV_H 4, 6, 0 ; 3
@@ -1851,10 +2354,9 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
PUT_8TAP_HV_H 0, 7, 1 ; 2 6
movu xm6, [srcq+ssq*1+ 0]
movu xm1, [srcq+ssq*1+16]
- lea srcq, [srcq+ssq*4]
- vinserti128 m6, [srcq+ssq*1+ 0], 1
- vinserti128 m1, [srcq+ssq*1+16], 1
- add srcq, r6
+ vinserti128 m6, [r7 +ssq*1+ 0], 1
+ vinserti128 m1, [r7 +ssq*1+16], 1
+ add r7, r6
shufpd m7, m6, m1, 0x05
PUT_8TAP_HV_H 6, 7, 1 ; 1 5
vpermq m4, m4, q1100
@@ -1885,13 +2387,13 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
pmaddwd m6, m10 ; b2
paddd m8, m5
paddd m9, m6
- movu xm5, [srcq+ssq*0]
- vinserti128 m5, [srcq+ssq*1], 1
+ movu xm5, [r7+ssq*0]
+ vinserti128 m5, [r7+ssq*1], 1
vbroadcasti128 m7, [subpel_h_shufA]
vbroadcasti128 m10, [subpel_h_shufB]
- movu xm6, [srcq+ssq*0+16]
- vinserti128 m6, [srcq+ssq*1+16], 1
- vextracti128 [dstq], m0, 1
+ movu xm6, [r7+ssq*0+16]
+ vinserti128 m6, [r7+ssq*1+16], 1
+ vextracti128 [r8], m0, 1
pshufb m0, m5, m7 ; 01
pshufb m5, m10 ; 23
pmaddwd m0, m11
@@ -1902,9 +2404,9 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
pmaddwd m5, m13
pmaddwd m6, m14
paddd m6, m5
- movu xm5, [srcq+ssq*0+8]
- vinserti128 m5, [srcq+ssq*1+8], 1
- lea srcq, [srcq+ssq*2]
+ movu xm5, [r7+ssq*0+8]
+ vinserti128 m5, [r7+ssq*1+8], 1
+ lea r7, [r7+ssq*2]
pshufb m7, m5, m7
pshufb m5, m10
pmaddwd m10, m13, m7
@@ -1916,7 +2418,7 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
pmaddwd m5, m12
paddd m0, m7
paddd m5, m6
- vbroadcasti128 m6, [dstq]
+ vbroadcasti128 m6, [r8]
paddd m8, m10
paddd m9, m10
paddd m0, m10
@@ -1938,16 +2440,14 @@ cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my
packusdw m7, m9
pminsw m7, m15
vpermq m7, m7, q3120
- mova [dstq+dsq*0], xm7
- vextracti128 [dstq+dsq*1], m7, 1
- lea dstq, [dstq+dsq*2]
+ mova [r8+dsq*0], xm7
+ vextracti128 [r8+dsq*1], m7, 1
+ lea r8, [r8+dsq*2]
sub hd, 2
jg .hv_w8_loop
- add r7, 16
- add r8, 16
+ add srcq, 16
+ add dstq, 16
movzx hd, wb
- mov srcq, r7
- mov dstq, r8
sub wd, 1<<8
jg .hv_w8_loop0
RET
@@ -1959,28 +2459,24 @@ DECLARE_REG_TMP 6, 7
%endif
%define PREP_8TAP_FN FN prep_8tap,
-PREP_8TAP_FN sharp, SHARP, SHARP
-PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH
-PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP
-PREP_8TAP_FN smooth, SMOOTH, SMOOTH
-PREP_8TAP_FN sharp_regular, SHARP, REGULAR
-PREP_8TAP_FN regular_sharp, REGULAR, SHARP
-PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR
-PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH
+PREP_8TAP_FN smooth, SMOOTH, SMOOTH, prep_6tap_16bpc
+PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR, prep_6tap_16bpc
+PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH, prep_6tap_16bpc
PREP_8TAP_FN regular, REGULAR, REGULAR
-cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
+cglobal prep_6tap_16bpc, 4, 8, 0, tmp, src, ss, w, h, mx, my
%define base r7-prep_avx2
imul mxd, mxm, 0x010101
- add mxd, t0d ; 8tap_h, mx, 4tap_h
+ add mxd, t0d ; 6tap_h, mx, 4tap_h
imul myd, mym, 0x010101
- add myd, t1d ; 8tap_v, my, 4tap_v
+ add myd, t1d ; 6tap_v, my, 4tap_v
lea r7, [prep_avx2]
movifnidn hd, hm
test mxd, 0xf00
jnz .h
test myd, 0xf00
jnz .v
+.prep:
tzcnt wd, wd
mov r6d, r7m ; bitdepth_max
movzx wd, word [r7+wq*2+table_offset(prep,)]
@@ -1988,7 +2484,7 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
shr r6d, 11
add wq, r7
vpbroadcastd m4, [base+prep_mul+r6*4]
- lea r6, [strideq*3]
+ lea r6, [ssq*3]
%if WIN64
pop r7
%endif
@@ -1998,6 +2494,7 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
sub srcq, 2
pmovsxbw xm0, [base+subpel_filters+mxq*8]
vbroadcasti128 m3, [subpel_h_shufA]
+ lea r6, [ssq*3]
vbroadcasti128 m4, [subpel_h_shufB]
WIN64_SPILL_XMM 8
pshufd xm0, xm0, q2211
@@ -2008,11 +2505,11 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
vpbroadcastq m6, xm0
vpermq m7, m0, q1111
.h_w4_loop:
- movu xm1, [srcq+strideq*0]
- vinserti128 m1, [srcq+strideq*2], 1
- movu xm2, [srcq+strideq*1]
- vinserti128 m2, [srcq+r6 ], 1
- lea srcq, [srcq+strideq*4]
+ movu xm1, [srcq+ssq*0]
+ vinserti128 m1, [srcq+ssq*2], 1
+ movu xm2, [srcq+ssq*1]
+ vinserti128 m2, [srcq+r6 *1], 1
+ lea srcq, [srcq+ssq*4]
pshufb m0, m1, m3 ; 0 1 1 2 2 3 3 4
pshufb m1, m4 ; 2 3 3 4 4 5 5 6
pmaddwd m0, m6
@@ -2037,62 +2534,54 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
test myd, 0xf00
jnz .hv
vpbroadcastd m5, [prep_8tap_1d_rnd] ; 8 - (8192 << 4)
- lea r6, [strideq*3]
cmp wd, 4
je .h_w4
shr mxd, 16
- sub srcq, 6
- vpbroadcastq m0, [base+subpel_filters+mxq*8]
- WIN64_SPILL_XMM 12
+ sub srcq, 4
+ vpbroadcastq m0, [base+subpel_filters+1+mxq*8]
+ WIN64_SPILL_XMM 10
vbroadcasti128 m6, [subpel_h_shufA]
- vbroadcasti128 m7, [subpel_h_shufB]
punpcklbw m0, m0
psraw m0, 8 ; sign-extend
test dword r7m, 0x800
jnz .h_12bpc
psllw m0, 2
.h_12bpc:
- pshufd m8, m0, q0000
- pshufd m9, m0, q1111
- pshufd m10, m0, q2222
- pshufd m11, m0, q3333
+ pshufd m7, m0, q0000
+ pshufd m8, m0, q1111
+ pshufd m9, m0, q2222
cmp wd, 8
jg .h_w16
.h_w8:
-%macro PREP_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
- pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6
- pshufb m%1, m6 ; 0 1 1 2 2 3 3 4
- pmaddwd m%5, m9, m%4 ; abcd1
- pmaddwd m%1, m8 ; abcd0
- pshufb m%2, m7 ; 6 7 7 8 8 9 9 a
- shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8
- paddd m%5, m5
- paddd m%1, m%5
- pmaddwd m%5, m11, m%2 ; abcd3
- paddd m%1, m%5
- pmaddwd m%5, m10, m%4 ; abcd2
- pshufb m%3, m7 ; a b b c c d d e
- pmaddwd m%4, m8 ; efgh0
- paddd m%1, m%5
- pmaddwd m%5, m9, m%2 ; efgh1
- shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c
- pmaddwd m%3, m11 ; efgh3
- pmaddwd m%2, m10 ; efgh2
+ movu xm0, [srcq+ssq*0+ 0]
+ vinserti128 m0, [srcq+ssq*1+ 0], 1
+ movu xm2, [srcq+ssq*0+16]
+ vinserti128 m2, [srcq+ssq*1+16], 1
+ lea srcq, [srcq+ssq*2]
+ shufpd m1, m0, m2, 0x05
+%macro PREP_6TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
+ pshufb m%1, m6 ; 01 12 23 34
+ pshufb m%2, m6 ; 45 56 67 78
+ pmaddwd m%4, m7, m%1 ; a0
+ pshufb m%3, m6 ; 89 9a ab bc
+ pmaddwd m%5, m9, m%2 ; a2
+ shufpd m%1, m%2, 0x05 ; 23 34 45 56
+ paddd m%4, m%5 ; a0+a2
+ pmaddwd m%5, m7, m%2 ; b0
+ shufpd m%2, m%3, 0x05 ; 67 78 89 9a
+ pmaddwd m%3, m9 ; b2
+ pmaddwd m%1, m8 ; a1
+ pmaddwd m%2, m8 ; b1
+ paddd m%3, m%5 ; b0+b2
paddd m%4, m5
- paddd m%4, m%5
- paddd m%3, m%4
+ paddd m%3, m5
+ paddd m%1, m%4
paddd m%2, m%3
psrad m%1, 4
psrad m%2, 4
packssdw m%1, m%2
%endmacro
- movu xm0, [srcq+strideq*0+ 0]
- vinserti128 m0, [srcq+strideq*1+ 0], 1
- movu xm2, [srcq+strideq*0+16]
- vinserti128 m2, [srcq+strideq*1+16], 1
- lea srcq, [srcq+strideq*2]
- shufpd m1, m0, m2, 0x05
- PREP_8TAP_H 0, 1, 2, 3, 4
+ PREP_6TAP_H 0, 1, 2, 3, 4
mova [tmpq], m0
add tmpq, 32
sub hd, 2
@@ -2106,11 +2595,11 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
movu m0, [srcq+r6-32]
movu m1, [srcq+r6-24]
movu m2, [srcq+r6-16]
- PREP_8TAP_H 0, 1, 2, 3, 4
+ PREP_6TAP_H 0, 1, 2, 3, 4
mova [tmpq+r6-32], m0
sub r6d, 32
jg .h_w16_loop
- add srcq, strideq
+ add srcq, ssq
add tmpq, wq
dec hd
jg .h_w16_loop0
@@ -2119,13 +2608,368 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
movzx mxd, myb
shr myd, 16
cmp hd, 4
- cmovle myd, mxd
+ cmove myd, mxd
+ vpbroadcastq m0, [base+subpel_filters+1+myq*8]
+ WIN64_SPILL_XMM 9, 12
+ vpbroadcastd m5, [prep_8tap_1d_rnd]
+ mov r6, ssq
+ punpcklbw m0, m0
+ neg r6
+ psraw m0, 8 ; sign-extend
+ test dword r7m, 0x800
+ jnz .v_12bpc
+ psllw m0, 2
+.v_12bpc:
+ pshufd m6, m0, q0000
+ pshufd m7, m0, q1111
+ pshufd m8, m0, q2222
+ cmp wd, 4
+ jg .v_w8
+.v_w4:
+ movq xm1, [srcq+r6 *2]
+ vpbroadcastq m3, [srcq+r6 *1]
+ vpbroadcastq m2, [srcq+ssq*0]
+ vpbroadcastq m4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vpbroadcastq m0, [srcq+ssq*0]
+ vpblendd m1, m3, 0x30
+ vpblendd m3, m2, 0x30
+ punpcklwd m1, m3 ; 01 12
+ vpblendd m2, m4, 0x30
+ vpblendd m4, m0, 0x30
+ punpcklwd m2, m4 ; 23 34
+.v_w4_loop:
+ vpbroadcastq m3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddwd m4, m6, m1 ; a0 b0
+ mova m1, m2
+ pmaddwd m2, m7 ; a1 b1
+ paddd m4, m2
+ vpblendd m2, m0, m3, 0x30
+ vpbroadcastq m0, [srcq+ssq*0]
+ vpblendd m3, m0, 0x30
+ punpcklwd m2, m3 ; 45 56
+ pmaddwd m3, m8, m2 ; a2 b2
+ paddd m4, m5
+ paddd m4, m3
+ psrad m4, 4
+ vextracti128 xm3, m4, 1
+ packssdw xm4, xm3
+ mova [tmpq], xm4
+ add tmpq, 16
+ sub hd, 2
+ jg .v_w4_loop
+ RET
+.v_w8:
+ WIN64_PUSH_XMM 12
+%if WIN64
+ push r8
+%endif
+ mov r8d, wd
+ shl wd, 5
+ lea wd, [hq+wq-256]
+.v_w8_loop0:
+ vbroadcasti128 m3, [srcq+r6 *2]
+ vbroadcasti128 m4, [srcq+r6 *1]
+ lea r5, [srcq+ssq*2]
+ vbroadcasti128 m0, [srcq+ssq*0]
+ vbroadcasti128 m1, [srcq+ssq*1]
+ mov r7, tmpq
+ vbroadcasti128 m2, [r5+ssq*0]
+ shufpd m3, m0, 0x0c
+ shufpd m4, m1, 0x0c
+ punpcklwd m1, m3, m4 ; 01
+ punpckhwd m3, m4 ; 23
+ shufpd m0, m2, 0x0c
+ punpcklwd m2, m4, m0 ; 12
+ punpckhwd m4, m0 ; 34
+.v_w8_loop:
+ vbroadcasti128 m9, [r5+ssq*1]
+ pmaddwd m10, m6, m1 ; a0
+ lea r5, [r5+ssq*2]
+ pmaddwd m11, m6, m2 ; b0
+ mova m1, m3
+ pmaddwd m3, m7 ; a1
+ mova m2, m4
+ pmaddwd m4, m7 ; b1
+ paddd m10, m5
+ paddd m11, m5
+ paddd m10, m3
+ vbroadcasti128 m3, [r5+ssq*0]
+ paddd m11, m4
+ shufpd m4, m0, m9, 0x0d
+ shufpd m0, m9, m3, 0x0c
+ punpcklwd m3, m4, m0 ; 45
+ punpckhwd m4, m0 ; 56
+ pmaddwd m9, m8, m3 ; a2
+ paddd m10, m9
+ pmaddwd m9, m8, m4 ; b2
+ paddd m11, m9
+ psrad m10, 4
+ psrad m11, 4
+ packssdw m10, m11
+ vpermq m10, m10, q3120
+ mova [r7+r8*0], xm10
+ vextracti128 [r7+r8*2], m10, 1
+ lea r7, [r7+r8*4]
+ sub hd, 2
+ jg .v_w8_loop
+ add srcq, 16
+ add tmpq, 16
+ movzx hd, wb
+ sub wd, 1<<8
+ jg .v_w8_loop0
+%if WIN64
+ pop r8
+%endif
+ RET
+.hv:
+ WIN64_SPILL_XMM 13, 15
+ vpbroadcastd m7, [prep_8tap_2d_rnd]
+ vbroadcasti128 m8, [subpel_h_shufA]
+ cmp wd, 4
+ jg .hv_w8
+ movzx mxd, mxb
+ vpbroadcastd m0, [base+subpel_filters+mxq*8+2]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ vpbroadcastq m1, [base+subpel_filters+1+myq*8]
+ mov r6, ssq
+ sub srcq, 2
+ pxor m6, m6
+ neg r6
+ punpcklbw m6, m0
+ punpcklbw m1, m1
+ psraw m6, 4
+ psraw m1, 8
+ test dword r7m, 0x800
+ jz .hv_w4_10bit
+ psraw m6, 2
+.hv_w4_10bit:
+ pshufd m10, m1, q0000
+ pshufd m11, m1, q1111
+ pshufd m12, m1, q2222
+.hv_w4:
+ movu xm2, [srcq+r6 *2]
+ vinserti128 m2, [srcq+r6 *1], 1 ; 0 1
+ pshufd m5, m6, q0000
+ vbroadcasti128 m9, [base+subpel_h_shufB]
+ movu xm0, [srcq+ssq*0]
+ pshufd m6, m6, q1111
+ vinserti128 m0, [srcq+ssq*1], 1 ; 2 3
+ lea srcq, [srcq+ssq*2]
+ movu xm3, [srcq+ssq*0] ; 4
+ pshufb m1, m2, m8
+ pmaddwd m1, m5
+ pshufb m2, m9
+ pmaddwd m2, m6
+ pshufb m4, m0, m8
+ pmaddwd m4, m5
+ pshufb m0, m9
+ pmaddwd m0, m6
+ paddd m2, m1
+ pshufb xm1, xm3, xm8
+ pmaddwd xm1, xm5
+ pshufb xm3, xm9
+ pmaddwd xm3, xm6
+ paddd m0, m4
+ paddd m2, m7
+ paddd xm1, xm7
+ paddd m0, m7
+ paddd xm3, xm1
+ REPX {psrad x, 6}, m2, m0, xm3
+ packssdw m2, m0 ; 0 2 1 3
+ packssdw xm0, xm3 ; 2 4
+ vperm2i128 m0, m2, 0x03
+ punpcklwd m1, m2, m0 ; 01 12
+ punpckhwd m2, m0 ; 23 34
+.hv_w4_loop:
+ movu xm3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vinserti128 m3, [srcq+ssq*0], 1
+ pmaddwd m4, m10, m1 ; a0 b0
+ mova m1, m2
+ pmaddwd m2, m11 ; a1 b1
+ paddd m4, m2
+ pshufb m2, m3, m8
+ pmaddwd m2, m5
+ pshufb m3, m9
+ pmaddwd m3, m6
+ paddd m2, m7
+ paddd m3, m2
+ psrad m3, 6
+ packssdw m3, m3 ; 5 5 6 6
+ vperm2i128 m2, m0, m3, 0x21
+ mova m0, m3
+ punpckhwd m2, m3 ; 45 56
+ pmaddwd m3, m12, m2 ; a2 b2
+ paddd m4, m7
+ paddd m4, m3
+ psrad m4, 6
+ vextracti128 xm3, m4, 1
+ packssdw xm4, xm3
+ mova [tmpq], xm4
+ add tmpq, 16
+ sub hd, 2
+ jg .hv_w4_loop
+ RET
+.hv_w8:
+ shr mxd, 16
+ vpbroadcastq m2, [base+subpel_filters+1+mxq*8]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ pmovsxbw xm1, [base+subpel_filters+1+myq*8]
+ WIN64_PUSH_XMM 15
+%if WIN64
+ PUSH r8
+%endif
+ mov r8d, wd
+ shl wd, 5
+ mov r6, ssq
+ sub srcq, 4
+ neg r6
+ lea wd, [hq+wq-256]
+ pxor m0, m0
+ punpcklbw m0, m2
+ psraw m0, 4
+ test dword r7m, 0x800
+ jz .hv_w8_10bit
+ psraw m0, 2
+.hv_w8_10bit:
+ pshufd m10, m0, q0000
+ pshufd m11, m0, q1111
+ mova [v_mul], xm1
+ pshufd m12, m0, q2222
+.hv_w8_loop0:
+ vbroadcasti128 m0, [srcq+ssq*0+ 0]
+ vinserti128 m3, m0, [srcq+r6*2+ 0], 0
+ lea r5, [srcq+ssq*2]
+ vbroadcasti128 m2, [srcq+ssq*0+16]
+ vinserti128 m1, m2, [srcq+r6*2+16], 0
+ mov r7, tmpq
+ vinserti128 m0, [r5 +ssq*0+ 0], 1
+ vinserti128 m2, [r5 +ssq*0+16], 1
+ shufpd m4, m3, m1, 0x05
+%macro PREP_6TAP_HV_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
+ pshufb m%1, m8 ; 01 12 23 34
+ pshufb m%2, m8 ; 45 56 67 78
+ pmaddwd m%4, m10, m%1 ; a0
+ pshufb m%3, m8 ; 89 9a ab bc
+ pmaddwd m%5, m12, m%2 ; a2
+ shufpd m%1, m%2, 0x05 ; 23 34 45 56
+ paddd m%4, m%5 ; a0+a2
+ pmaddwd m%5, m10, m%2 ; b0
+ shufpd m%2, m%3, 0x05 ; 67 78 89 9a
+ pmaddwd m%3, m12 ; b2
+ pmaddwd m%1, m11 ; a1
+ pmaddwd m%2, m11 ; b1
+ paddd m%3, m%5 ; b0+b2
+ paddd m%4, m7
+ paddd m%3, m7
+ paddd m%1, m%4
+ paddd m%2, m%3
+ psrad m%1, 6
+ psrad m%2, 6
+ packssdw m%1, m%2
+%endmacro
+ PREP_6TAP_HV_H 3, 4, 1, 5, 6 ; 0 2
+ movu xm4, [srcq+r6 *1+ 0]
+ vinserti128 m4, [srcq+ssq*1+ 0], 1
+ shufpd m1, m0, m2, 0x05
+ PREP_6TAP_HV_H 0, 1, 2, 5, 6 ; 2 4
+ movu xm2, [srcq+r6 *1+16]
+ vinserti128 m2, [srcq+ssq*1+16], 1
+ shufpd m1, m4, m2, 0x05
+ PREP_6TAP_HV_H 4, 1, 2, 5, 6 ; 1 3
+ vpermq m3, m3, q3120
+ vpermq m4, m4, q3120
+ vpermq m0, m0, q3120
+ punpcklwd m1, m3, m4 ; 01
+ punpckhwd m3, m4 ; 23
+ punpcklwd m2, m4, m0 ; 12
+ punpckhwd m4, m0 ; 34
+.hv_w8_loop:
+ vpbroadcastd m14, [v_mul+4*0]
+ vpbroadcastd m9, [v_mul+4*1]
+ movu xm5, [r5+ssq*1+ 0]
+ movu xm6, [r5+ssq*1+16]
+ lea r5, [r5+ssq*2]
+ pmaddwd m13, m14, m1 ; a0
+ pmaddwd m14, m2 ; b0
+ vinserti128 m5, [r5+ssq*0+ 0], 1
+ vinserti128 m6, [r5+ssq*0+16], 1
+ mova m1, m3
+ pmaddwd m3, m9 ; a1
+ mova m2, m4
+ pmaddwd m4, m9 ; b1
+ paddd m13, m3
+ shufpd m3, m5, m6, 0x05
+ paddd m14, m4
+ PREP_6TAP_HV_H 5, 3, 6, 4, 9 ; 5 6
+ vpbroadcastd m6, [v_mul+4*2]
+ vpermq m5, m5, q3120
+ shufpd m4, m0, m5, 0x05
+ mova m0, m5
+ punpcklwd m3, m4, m5 ; 45
+ punpckhwd m4, m5 ; 56
+ pmaddwd m5, m6, m3 ; a2
+ pmaddwd m6, m4 ; b2
+ paddd m13, m7
+ paddd m14, m7
+ paddd m5, m13
+ paddd m6, m14
+ psrad m5, 6
+ psrad m6, 6
+ packssdw m5, m6
+ vpermq m5, m5, q3120
+ mova [r7+r8*0], xm5
+ vextracti128 [r7+r8*2], m5, 1
+ lea r7, [r7+r8*4]
+ sub hd, 2
+ jg .hv_w8_loop
+ add srcq, 16
+ add tmpq, 16
+ movzx hd, wb
+ sub wd, 1<<8
+ jg .hv_w8_loop0
+%if WIN64
+ POP r8
+%endif
+ RET
+
+PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP, prep_8tap_16bpc
+PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH, prep_8tap_16bpc
+PREP_8TAP_FN regular_sharp, REGULAR, SHARP, prep_8tap_16bpc
+PREP_8TAP_FN sharp_regular, SHARP, REGULAR, prep_8tap_16bpc
+PREP_8TAP_FN sharp, SHARP, SHARP
+
+cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
+%define base r7-prep_avx2
+ imul mxd, mxm, 0x010101
+ add mxd, t0d ; 8tap_h, mx, 4tap_h
+ imul myd, mym, 0x010101
+ add myd, t1d ; 8tap_v, my, 4tap_v
+ lea r7, [prep_avx2]
+ movifnidn hd, hm
+ test mxd, 0xf00
+ jnz .h
+ test myd, 0xf00
+ jz mangle(private_prefix %+ _prep_6tap_16bpc_avx2).prep
+.v:
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
vpbroadcastq m0, [base+subpel_filters+myq*8]
- WIN64_SPILL_XMM 15
+ WIN64_SPILL_XMM 12, 15
vpbroadcastd m7, [prep_8tap_1d_rnd]
lea r6, [strideq*3]
- sub srcq, r6
punpcklbw m0, m0
+ sub srcq, r6
psraw m0, 8 ; sign-extend
test dword r7m, 0x800
jnz .v_12bpc
@@ -2183,23 +3027,23 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
RET
.v_w8:
%if WIN64
+ WIN64_PUSH_XMM 15
push r8
%endif
mov r8d, wd
shl wd, 5
- mov r5, srcq
- mov r7, tmpq
lea wd, [hq+wq-256]
.v_w8_loop0:
vbroadcasti128 m4, [srcq+strideq*0]
vbroadcasti128 m5, [srcq+strideq*1]
+ lea r5, [srcq+strideq*4]
vbroadcasti128 m0, [srcq+r6 ]
vbroadcasti128 m6, [srcq+strideq*2]
- lea srcq, [srcq+strideq*4]
- vbroadcasti128 m1, [srcq+strideq*0]
- vbroadcasti128 m2, [srcq+strideq*1]
- vbroadcasti128 m3, [srcq+strideq*2]
- add srcq, r6
+ mov r7, tmpq
+ vbroadcasti128 m1, [r5+strideq*0]
+ vbroadcasti128 m2, [r5+strideq*1]
+ vbroadcasti128 m3, [r5+strideq*2]
+ add r5, r6
shufpd m4, m0, 0x0c
shufpd m5, m1, 0x0c
punpcklwd m1, m4, m5 ; 01
@@ -2211,7 +3055,7 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
punpcklwd m3, m6, m0 ; 23
punpckhwd m6, m0 ; 56
.v_w8_loop:
- vbroadcasti128 m14, [srcq+strideq*0]
+ vbroadcasti128 m14, [r5+strideq*0]
pmaddwd m12, m8, m1 ; a0
pmaddwd m13, m8, m2 ; b0
mova m1, m3
@@ -2227,8 +3071,8 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
pmaddwd m5, m10 ; a2
pmaddwd m6, m10 ; b2
paddd m12, m5
- vbroadcasti128 m5, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
+ vbroadcasti128 m5, [r5+strideq*1]
+ lea r5, [r5+strideq*2]
paddd m13, m6
shufpd m6, m0, m14, 0x0d
shufpd m0, m14, m5, 0x0c
@@ -2242,22 +3086,101 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
psrad m13, 4
packssdw m12, m13
vpermq m12, m12, q3120
- mova [tmpq+r8*0], xm12
- vextracti128 [tmpq+r8*2], m12, 1
- lea tmpq, [tmpq+r8*4]
+ mova [r7+r8*0], xm12
+ vextracti128 [r7+r8*2], m12, 1
+ lea r7, [r7+r8*4]
sub hd, 2
jg .v_w8_loop
- add r5, 16
- add r7, 16
+ add srcq, 16
+ add tmpq, 16
movzx hd, wb
- mov srcq, r5
- mov tmpq, r7
sub wd, 1<<8
jg .v_w8_loop0
%if WIN64
pop r8
%endif
RET
+.h:
+ test myd, 0xf00
+ jnz .hv
+ vpbroadcastd m5, [prep_8tap_1d_rnd] ; 8 - (8192 << 4)
+ cmp wd, 4
+ je mangle(private_prefix %+ _prep_6tap_16bpc_avx2).h_w4
+ shr mxd, 16
+ sub srcq, 6
+ vpbroadcastq m0, [base+subpel_filters+mxq*8]
+ WIN64_SPILL_XMM 12
+ vbroadcasti128 m6, [subpel_h_shufA]
+ vbroadcasti128 m7, [subpel_h_shufB]
+ punpcklbw m0, m0
+ psraw m0, 8 ; sign-extend
+ test dword r7m, 0x800
+ jnz .h_12bpc
+ psllw m0, 2
+.h_12bpc:
+ pshufd m8, m0, q0000
+ pshufd m9, m0, q1111
+ pshufd m10, m0, q2222
+ pshufd m11, m0, q3333
+ cmp wd, 8
+ jg .h_w16
+.h_w8:
+%macro PREP_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2]
+ pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6
+ pshufb m%1, m6 ; 0 1 1 2 2 3 3 4
+ pmaddwd m%5, m9, m%4 ; abcd1
+ pmaddwd m%1, m8 ; abcd0
+ pshufb m%2, m7 ; 6 7 7 8 8 9 9 a
+ shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8
+ paddd m%5, m5
+ paddd m%1, m%5
+ pmaddwd m%5, m11, m%2 ; abcd3
+ paddd m%1, m%5
+ pmaddwd m%5, m10, m%4 ; abcd2
+ pshufb m%3, m7 ; a b b c c d d e
+ pmaddwd m%4, m8 ; efgh0
+ paddd m%1, m%5
+ pmaddwd m%5, m9, m%2 ; efgh1
+ shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c
+ pmaddwd m%3, m11 ; efgh3
+ pmaddwd m%2, m10 ; efgh2
+ paddd m%4, m5
+ paddd m%4, m%5
+ paddd m%3, m%4
+ paddd m%2, m%3
+ psrad m%1, 4
+ psrad m%2, 4
+ packssdw m%1, m%2
+%endmacro
+ movu xm0, [srcq+strideq*0+ 0]
+ vinserti128 m0, [srcq+strideq*1+ 0], 1
+ movu xm2, [srcq+strideq*0+16]
+ vinserti128 m2, [srcq+strideq*1+16], 1
+ lea srcq, [srcq+strideq*2]
+ shufpd m1, m0, m2, 0x05
+ PREP_8TAP_H 0, 1, 2, 3, 4
+ mova [tmpq], m0
+ add tmpq, 32
+ sub hd, 2
+ jg .h_w8
+ RET
+.h_w16:
+ add wd, wd
+.h_w16_loop0:
+ mov r6d, wd
+.h_w16_loop:
+ movu m0, [srcq+r6-32]
+ movu m1, [srcq+r6-24]
+ movu m2, [srcq+r6-16]
+ PREP_8TAP_H 0, 1, 2, 3, 4
+ mova [tmpq+r6-32], m0
+ sub r6d, 32
+ jg .h_w16_loop
+ add srcq, strideq
+ add tmpq, wq
+ dec hd
+ jg .h_w16_loop0
+ RET
.hv:
WIN64_SPILL_XMM 16
vpbroadcastd m15, [prep_8tap_2d_rnd]
@@ -2268,12 +3191,12 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
movzx mxd, myb
shr myd, 16
cmp hd, 4
- cmovle myd, mxd
+ cmove myd, mxd
vpbroadcastq m1, [base+subpel_filters+myq*8]
lea r6, [strideq*3]
sub srcq, 2
- sub srcq, r6
pxor m7, m7
+ sub srcq, r6
punpcklbw m7, m0
punpcklbw m1, m1
psraw m7, 4
@@ -2375,7 +3298,7 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
movzx mxd, myb
shr myd, 16
cmp hd, 4
- cmovle myd, mxd
+ cmove myd, mxd
pmovsxbw xm1, [base+subpel_filters+myq*8]
%if WIN64
PUSH r8
@@ -2385,12 +3308,9 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
lea r6, [strideq*3]
sub srcq, 6
sub srcq, r6
- mov r5, srcq
- mov r7, tmpq
lea wd, [hq+wq-256]
pxor m0, m0
punpcklbw m0, m2
- mova [v_mul], xm1
psraw m0, 4
test dword r7m, 0x800
jz .hv_w8_10bit
@@ -2398,6 +3318,7 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
.hv_w8_10bit:
pshufd m11, m0, q0000
pshufd m12, m0, q1111
+ mova [v_mul], xm1
pshufd m13, m0, q2222
pshufd m14, m0, q3333
.hv_w8_loop0:
@@ -2430,13 +3351,15 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
%endmacro
movu xm4, [srcq+r6 + 0]
vbroadcasti128 m8, [subpel_h_shufA]
+ lea r5, [srcq+strideq*4]
movu xm6, [srcq+r6 + 8]
vbroadcasti128 m9, [subpel_h_shufB]
+ mov r7, tmpq
movu xm0, [srcq+r6 +16]
movu xm5, [srcq+strideq*0+ 0]
- vinserti128 m5, [srcq+strideq*4+ 0], 1
+ vinserti128 m5, [r5 +strideq*0+ 0], 1
movu xm1, [srcq+strideq*0+16]
- vinserti128 m1, [srcq+strideq*4+16], 1
+ vinserti128 m1, [r5 +strideq*0+16], 1
shufpd m7, m5, m1, 0x05
INIT_XMM avx2
PREP_8TAP_HV_H 4, 6, 0 ; 3
@@ -2450,10 +3373,9 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
PREP_8TAP_HV_H 0, 7, 1 ; 2 6
movu xm6, [srcq+strideq*1+ 0]
movu xm1, [srcq+strideq*1+16]
- lea srcq, [srcq+strideq*4]
- vinserti128 m6, [srcq+strideq*1+ 0], 1
- vinserti128 m1, [srcq+strideq*1+16], 1
- add srcq, r6
+ vinserti128 m6, [r5 +strideq*1+ 0], 1
+ vinserti128 m1, [r5 +strideq*1+16], 1
+ add r5, r6
shufpd m7, m6, m1, 0x05
PREP_8TAP_HV_H 6, 7, 1 ; 1 5
vpermq m4, m4, q1100
@@ -2486,13 +3408,13 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
pmaddwd m6, m10 ; b2
paddd m8, m5
paddd m9, m6
- movu xm5, [srcq+strideq*0]
- vinserti128 m5, [srcq+strideq*1], 1
+ movu xm5, [r5+strideq*0]
+ vinserti128 m5, [r5+strideq*1], 1
vbroadcasti128 m7, [subpel_h_shufA]
vbroadcasti128 m10, [subpel_h_shufB]
- movu xm6, [srcq+strideq*0+16]
- vinserti128 m6, [srcq+strideq*1+16], 1
- vextracti128 [tmpq], m0, 1
+ movu xm6, [r5+strideq*0+16]
+ vinserti128 m6, [r5+strideq*1+16], 1
+ vextracti128 [r7], m0, 1
pshufb m0, m5, m7 ; 01
pshufb m5, m10 ; 23
pmaddwd m0, m11
@@ -2505,9 +3427,9 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
pmaddwd m6, m14
paddd m5, m15
paddd m6, m5
- movu xm5, [srcq+strideq*0+8]
- vinserti128 m5, [srcq+strideq*1+8], 1
- lea srcq, [srcq+strideq*2]
+ movu xm5, [r5+strideq*0+8]
+ vinserti128 m5, [r5+strideq*1+8], 1
+ lea r5, [r5+strideq*2]
pshufb m7, m5, m7
pshufb m5, m10
pmaddwd m10, m13, m7
@@ -2518,7 +3440,7 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
pmaddwd m5, m12
paddd m0, m7
paddd m5, m6
- vbroadcasti128 m6, [tmpq]
+ vbroadcasti128 m6, [r7]
vpbroadcastd m10, [v_mul+4*3]
psrad m0, 6
psrad m5, 6
@@ -2535,16 +3457,14 @@ cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my
psrad m9, 6
packssdw m7, m9
vpermq m7, m7, q3120
- mova [tmpq+r8*0], xm7
- vextracti128 [tmpq+r8*2], m7, 1
- lea tmpq, [tmpq+r8*4]
+ mova [r7+r8*0], xm7
+ vextracti128 [r7+r8*2], m7, 1
+ lea r7, [r7+r8*4]
sub hd, 2
jg .hv_w8_loop
- add r5, 16
- add r7, 16
+ add srcq, 16
+ add tmpq, 16
movzx hd, wb
- mov srcq, r5
- mov tmpq, r7
sub wd, 1<<8
jg .hv_w8_loop0
%if WIN64
@@ -4223,14 +5143,14 @@ DECLARE_REG_TMP 6, 8
%define PUT_8TAP_SCALED_FN FN put_8tap_scaled,
BILIN_SCALED_FN put
-PUT_8TAP_SCALED_FN sharp, SHARP, SHARP
-PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH
-PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP
-PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH
-PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR
-PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP
-PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR
-PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH
+PUT_8TAP_SCALED_FN sharp, SHARP, SHARP, put_8tap_scaled_16bpc
+PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH, put_8tap_scaled_16bpc
+PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP, put_8tap_scaled_16bpc
+PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH, put_8tap_scaled_16bpc
+PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR, put_8tap_scaled_16bpc
+PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP, put_8tap_scaled_16bpc
+PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR, put_8tap_scaled_16bpc
+PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH, put_8tap_scaled_16bpc
PUT_8TAP_SCALED_FN regular, REGULAR, REGULAR
MC_8TAP_SCALED put
@@ -4242,14 +5162,14 @@ DECLARE_REG_TMP 6, 7
%define PREP_8TAP_SCALED_FN FN prep_8tap_scaled,
BILIN_SCALED_FN prep
-PREP_8TAP_SCALED_FN sharp, SHARP, SHARP
-PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH
-PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP
-PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH
-PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR
-PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP
-PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR
-PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH
+PREP_8TAP_SCALED_FN sharp, SHARP, SHARP, prep_8tap_scaled_16bpc
+PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH, prep_8tap_scaled_16bpc
+PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP, prep_8tap_scaled_16bpc
+PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH, prep_8tap_scaled_16bpc
+PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR, prep_8tap_scaled_16bpc
+PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP, prep_8tap_scaled_16bpc
+PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR, prep_8tap_scaled_16bpc
+PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH, prep_8tap_scaled_16bpc
PREP_8TAP_SCALED_FN regular, REGULAR, REGULAR
MC_8TAP_SCALED prep
diff --git a/third_party/dav1d/src/x86/mc_avx2.asm b/third_party/dav1d/src/x86/mc_avx2.asm
index 58e3cb5af1..df8bebb1cb 100644
--- a/third_party/dav1d/src/x86/mc_avx2.asm
+++ b/third_party/dav1d/src/x86/mc_avx2.asm
@@ -60,15 +60,14 @@ subpel_v_shuf4: db 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 1
subpel_s_shuf2: db 0, 1, 2, 3, 0, 1, 2, 3, 8, 9, 10, 11, 8, 9, 10, 11
subpel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15
bilin_h_shuf4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12
-bilin_h_shuf8: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
bilin_v_shuf4: db 4, 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7
deint_shuf4: db 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11
blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3
pb_8x0_8x8: db 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8
bdct_lb_dw: db 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12
wswap: db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13
-rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7
resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7
+rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7
wm_420_sign: dd 0x01020102, 0x01010101
wm_422_sign: dd 0x80808080, 0x7f7f7f7f
@@ -95,6 +94,7 @@ pq_0x40000000: dq 0x40000000
cextern mc_subpel_filters
cextern mc_warp_filter2
cextern resize_filter
+cextern z_filter_s
%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8)
@@ -184,7 +184,9 @@ BASE_JMP_TABLE put, avx2, 2, 4, 8, 16, 32, 64, 128
BASE_JMP_TABLE prep, avx2, 4, 8, 16, 32, 64, 128
HV_JMP_TABLE put, bilin, avx2, 7, 2, 4, 8, 16, 32, 64, 128
HV_JMP_TABLE prep, bilin, avx2, 7, 4, 8, 16, 32, 64, 128
+HV_JMP_TABLE put, 6tap, avx2, 3, 2, 4, 8, 16, 32, 64, 128
HV_JMP_TABLE put, 8tap, avx2, 3, 2, 4, 8, 16, 32, 64, 128
+HV_JMP_TABLE prep, 6tap, avx2, 1, 4, 8, 16, 32, 64, 128
HV_JMP_TABLE prep, 8tap, avx2, 1, 4, 8, 16, 32, 64, 128
SCALED_JMP_TABLE put_8tap_scaled, avx2, 2, 4, 8, 16, 32, 64, 128
SCALED_JMP_TABLE prep_8tap_scaled, avx2, 4, 8, 16, 32, 64, 128
@@ -298,7 +300,7 @@ INIT_YMM avx2
; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4
; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4
imul mxyd, 255
- vbroadcasti128 m4, [bilin_h_shuf8]
+ vbroadcasti128 m4, [z_filter_s+2]
add mxyd, 16
movd xm5, mxyd
mov mxyd, r7m ; my
@@ -900,7 +902,7 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
; 16 * src[x] + (mx * (src[x + 1] - src[x]))
; = (16 - mx) * src[x] + mx * src[x + 1]
imul mxyd, 255
- vbroadcasti128 m4, [bilin_h_shuf8]
+ vbroadcasti128 m4, [z_filter_s+2]
add mxyd, 16
movd xm5, mxyd
mov mxyd, r6m ; my
@@ -1436,7 +1438,7 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
%assign FILTER_SMOOTH (1*15 << 16) | 4*15
%assign FILTER_SHARP (2*15 << 16) | 3*15
-%macro FN 4 ; fn, type, type_h, type_v
+%macro FN 4-5 ; fn, type, type_h, type_v, jmp_to
cglobal %1_%2_8bpc
mov t0d, FILTER_%3
%ifidn %3, %4
@@ -1444,8 +1446,8 @@ cglobal %1_%2_8bpc
%else
mov t1d, FILTER_%4
%endif
-%ifnidn %2, regular ; skip the jump in the last filter
- jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX)
+%if %0 == 5 ; skip the jump in the last filter
+ jmp mangle(private_prefix %+ _%5 %+ SUFFIX)
%endif
%endmacro
@@ -1456,28 +1458,24 @@ DECLARE_REG_TMP 7, 8
%endif
%define PUT_8TAP_FN FN put_8tap,
-PUT_8TAP_FN sharp, SHARP, SHARP
-PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH
-PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP
-PUT_8TAP_FN smooth, SMOOTH, SMOOTH
-PUT_8TAP_FN sharp_regular, SHARP, REGULAR
-PUT_8TAP_FN regular_sharp, REGULAR, SHARP
-PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR
-PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH
+PUT_8TAP_FN smooth, SMOOTH, SMOOTH, put_6tap_8bpc
+PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR, put_6tap_8bpc
+PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH, put_6tap_8bpc
PUT_8TAP_FN regular, REGULAR, REGULAR
-cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
+cglobal put_6tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ns
imul mxd, mxm, 0x010101
- add mxd, t0d ; 8tap_h, mx, 4tap_h
+ add mxd, t0d ; 6tap_h, mx, 4tap_h
imul myd, mym, 0x010101
- add myd, t1d ; 8tap_v, my, 4tap_v
+ add myd, t1d ; 6tap_v, my, 4tap_v
lea r8, [put_avx2]
- movsxd wq, wm
+ mov wd, wm
movifnidn hd, hm
test mxd, 0xf00
jnz .h
test myd, 0xf00
jnz .v
+.put:
tzcnt wd, wd
movzx wd, word [r8+wq*2+table_offset(put,)]
add wq, r8
@@ -1487,36 +1485,18 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
pop r8
%endif
jmp wq
-.h:
- test myd, 0xf00
- jnz .hv
- vpbroadcastd m5, [pw_34] ; 2 + (8 << 2)
- WIN64_SPILL_XMM 11
- cmp wd, 4
- jl .h_w2
- vbroadcasti128 m6, [subpel_h_shufA]
- je .h_w4
- tzcnt wd, wd
- vbroadcasti128 m7, [subpel_h_shufB]
- vbroadcasti128 m8, [subpel_h_shufC]
- shr mxd, 16
- sub srcq, 3
- movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)]
- vpbroadcastd m9, [r8+mxq*8+subpel_filters-put_avx2+0]
- vpbroadcastd m10, [r8+mxq*8+subpel_filters-put_avx2+4]
- add wq, r8
- jmp wq
.h_w2:
movzx mxd, mxb
- dec srcq
- mova xm4, [subpel_h_shuf4]
- vpbroadcastd xm3, [r8+mxq*8+subpel_filters-put_avx2+2]
+ lea srcq, [srcq-1]
+ vpbroadcastd xm4, [r8+mxq*8+subpel_filters-put_avx2+2]
+ je .h_w4
+ mova xm3, [subpel_h_shuf4]
.h_w2_loop:
movq xm0, [srcq+ssq*0]
movhps xm0, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- pshufb xm0, xm4
- pmaddubsw xm0, xm3
+ pshufb xm0, xm3
+ pmaddubsw xm0, xm4
phaddw xm0, xm0
paddw xm0, xm5
psraw xm0, 6
@@ -1528,17 +1508,15 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
jg .h_w2_loop
RET
.h_w4:
- movzx mxd, mxb
- dec srcq
- vpbroadcastd xm3, [r8+mxq*8+subpel_filters-put_avx2+2]
+ mova xm3, [subpel_h_shufA]
.h_w4_loop:
movq xm0, [srcq+ssq*0]
movq xm1, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- pshufb xm0, xm6
- pshufb xm1, xm6
- pmaddubsw xm0, xm3
- pmaddubsw xm1, xm3
+ pshufb xm0, xm3
+ pshufb xm1, xm3
+ pmaddubsw xm0, xm4
+ pmaddubsw xm1, xm4
phaddw xm0, xm1
paddw xm0, xm5
psraw xm0, 6
@@ -1549,25 +1527,43 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
sub hd, 2
jg .h_w4_loop
RET
+.h:
+ test myd, 0xf00
+ jnz .hv
+ vpbroadcastd m5, [pw_34] ; 2 + (8 << 2)
+ cmp wd, 4
+ jle .h_w2
+ WIN64_SPILL_XMM 11
+ tzcnt wd, wd
+ vbroadcasti128 m4, [z_filter_s+ 2] ; 01
+ shr mxd, 16
+ vbroadcasti128 m6, [z_filter_s+ 6] ; 23
+ sub srcq, 2
+ vbroadcasti128 m7, [z_filter_s+10] ; 45
+ lea mxq, [r8+mxq*8+subpel_filters+1-put_avx2]
+ movzx wd, word [r8+wq*2+table_offset(put, _6tap_h)]
+ vpbroadcastw m8, [mxq+0]
+ vpbroadcastw m9, [mxq+2]
+ add wq, r8
+ vpbroadcastw m10, [mxq+4]
+ jmp wq
.h_w8:
-%macro PUT_8TAP_H 4 ; dst/src, tmp[1-3]
- pshufb m%2, m%1, m7
- pshufb m%3, m%1, m8
- pshufb m%1, m6
- pmaddubsw m%4, m%2, m9
- pmaddubsw m%2, m10
- pmaddubsw m%3, m10
- pmaddubsw m%1, m9
- paddw m%3, m%4
+%macro PUT_6TAP_H 3 ; dst/src, tmp[1-2]
+ pshufb m%2, m%1, m4
+ pmaddubsw m%2, m8
+ pshufb m%3, m%1, m6
+ pmaddubsw m%3, m9
+ pshufb m%1, m7
+ pmaddubsw m%1, m10
+ paddw m%2, m5
+ paddw m%1, m%3
paddw m%1, m%2
- phaddw m%1, m%3
- paddw m%1, m5
psraw m%1, 6
%endmacro
movu xm0, [srcq+ssq*0]
vinserti128 m0, [srcq+ssq*1], 1
lea srcq, [srcq+ssq*2]
- PUT_8TAP_H 0, 1, 2, 3
+ PUT_6TAP_H 0, 1, 2
vextracti128 xm1, m0, 1
packuswb xm0, xm1
movq [dstq+dsq*0], xm0
@@ -1581,9 +1577,9 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vinserti128 m0, [srcq+ssq*1+8*0], 1
movu xm1, [srcq+ssq*0+8*1]
vinserti128 m1, [srcq+ssq*1+8*1], 1
- PUT_8TAP_H 0, 2, 3, 4
+ PUT_6TAP_H 0, 2, 3
lea srcq, [srcq+ssq*2]
- PUT_8TAP_H 1, 2, 3, 4
+ PUT_6TAP_H 1, 2, 3
packuswb m0, m1
mova [dstq+dsq*0], xm0
vextracti128 [dstq+dsq*1], m0, 1
@@ -1606,8 +1602,8 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
.h_loop:
movu m0, [srcq+r6+8*0]
movu m1, [srcq+r6+8*1]
- PUT_8TAP_H 0, 2, 3, 4
- PUT_8TAP_H 1, 2, 3, 4
+ PUT_6TAP_H 0, 2, 3
+ PUT_6TAP_H 1, 2, 3
packuswb m0, m1
mova [dstq+r6], m0
add r6, 32
@@ -1619,7 +1615,421 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
jg .h_loop
RET
.v:
- WIN64_SPILL_XMM 16
+ WIN64_SPILL_XMM 9, 12
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ tzcnt r6d, wd
+ movzx r6d, word [r8+r6*2+table_offset(put, _6tap_v)]
+ vpbroadcastd m8, [pw_512]
+ lea myq, [r8+myq*8+subpel_filters+1-put_avx2]
+ vpbroadcastw m5, [myq+0]
+ vpbroadcastw m6, [myq+2]
+ vpbroadcastw m7, [myq+4]
+ add r6, r8
+ mov nsq, ssq
+ neg nsq
+ jmp r6
+.v_w2:
+ movd xm2, [srcq+nsq*2]
+ pinsrw xm2, [srcq+nsq*1], 2
+ pinsrw xm2, [srcq+ssq*0], 4
+ pinsrw xm2, [srcq+ssq*1], 6 ; 0 1 2 3
+ lea srcq, [srcq+ssq*2]
+ vpbroadcastd xm0, [srcq+ssq*0]
+ palignr xm3, xm0, xm2, 4 ; 1 2 3 4
+ punpcklbw xm1, xm2, xm3 ; 01 12
+ punpckhbw xm2, xm3 ; 23 34
+.v_w2_loop:
+ vpbroadcastd xm4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw xm3, xm1, xm5 ; a0 b0
+ mova xm1, xm2
+ pmaddubsw xm2, xm6 ; a1 b1
+ paddw xm3, xm2
+ vpblendd xm2, xm0, xm4, 0x02 ; 4 5
+ vpbroadcastd xm0, [srcq+ssq*0]
+ vpblendd xm4, xm0, 0x02 ; 5 6
+ punpcklbw xm2, xm4 ; 67 78
+ pmaddubsw xm4, xm2, xm7 ; a3 b3
+ paddw xm3, xm4
+ pmulhrsw xm3, xm8
+ packuswb xm3, xm3
+ pextrw [dstq+dsq*0], xm3, 0
+ pextrw [dstq+dsq*1], xm3, 2
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .v_w2_loop
+ RET
+.v_w4:
+ movd xm2, [srcq+nsq*2]
+ pinsrd xm2, [srcq+nsq*1], 1
+ pinsrd xm2, [srcq+ssq*0], 2
+ pinsrd xm2, [srcq+ssq*1], 3 ; 0 1 2 3
+ lea srcq, [srcq+ssq*2]
+ vpbroadcastd xm0, [srcq+ssq*0]
+ palignr xm3, xm0, xm2, 4 ; 1 2 3 4
+ punpcklbw xm1, xm2, xm3 ; 01 12
+ punpckhbw xm2, xm3 ; 23 34
+.v_w4_loop:
+ vpbroadcastd xm4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw xm3, xm1, xm5 ; a0 b0
+ mova xm1, xm2
+ pmaddubsw xm2, xm6 ; a1 b1
+ paddw xm3, xm2
+ vpblendd xm2, xm0, xm4, 0x02 ; 4 5
+ vpbroadcastd xm0, [srcq+ssq*0]
+ vpblendd xm4, xm0, 0x02 ; 5 6
+ punpcklbw xm2, xm4 ; 45 56
+ pmaddubsw xm4, xm2, xm7 ; a2 b2
+ paddw xm3, xm4
+ pmulhrsw xm3, xm8
+ packuswb xm3, xm3
+ movd [dstq+dsq*0], xm3
+ pextrd [dstq+dsq*1], xm3, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .v_w4_loop
+ RET
+.v_w8:
+ movq xm1, [srcq+nsq*2]
+ vpbroadcastq m3, [srcq+nsq*1]
+ vpbroadcastq m2, [srcq+ssq*0]
+ vpbroadcastq m4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vpbroadcastq m0, [srcq+ssq*0]
+ vpblendd m1, m3, 0x30
+ vpblendd m3, m2, 0x30
+ punpcklbw m1, m3 ; 01 12
+ vpblendd m2, m4, 0x30
+ vpblendd m4, m0, 0x30
+ punpcklbw m2, m4 ; 23 34
+.v_w8_loop:
+ vpbroadcastq m4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw m3, m1, m5 ; a0 b0
+ mova m1, m2
+ pmaddubsw m2, m6 ; a1 b1
+ paddw m3, m2
+ vpblendd m2, m0, m4, 0x30
+ vpbroadcastq m0, [srcq+ssq*0]
+ vpblendd m4, m0, 0x30
+ punpcklbw m2, m4 ; 45 56
+ pmaddubsw m4, m2, m7 ; a2 b2
+ paddw m3, m4
+ pmulhrsw m3, m8
+ vextracti128 xm4, m3, 1
+ packuswb xm3, xm4
+ movq [dstq+dsq*0], xm3
+ movhps [dstq+dsq*1], xm3
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .v_w8_loop
+ RET
+.v_w16:
+.v_w32:
+.v_w64:
+.v_w128:
+ lea r6d, [wq*8-128]
+ WIN64_PUSH_XMM 12
+ lea r6d, [hq+r6*2]
+.v_w16_loop0:
+ vbroadcasti128 m3, [srcq+nsq*2]
+ vbroadcasti128 m4, [srcq+nsq*1]
+ lea r4, [srcq+ssq*2]
+ vbroadcasti128 m0, [srcq+ssq*0]
+ vbroadcasti128 m1, [srcq+ssq*1]
+ mov r7, dstq
+ vbroadcasti128 m2, [r4+ssq*0]
+ shufpd m3, m0, 0x0c
+ shufpd m4, m1, 0x0c
+ punpcklbw m1, m3, m4 ; 01
+ punpckhbw m3, m4 ; 23
+ shufpd m0, m2, 0x0c
+ punpcklbw m2, m4, m0 ; 12
+ punpckhbw m4, m0 ; 34
+.v_w16_loop:
+ vbroadcasti128 m9, [r4+ssq*1]
+ pmaddubsw m10, m1, m5 ; a0
+ lea r4, [r4+ssq*2]
+ pmaddubsw m11, m2, m5 ; b0
+ mova m1, m3
+ pmaddubsw m3, m6 ; a1
+ mova m2, m4
+ pmaddubsw m4, m6 ; b1
+ paddw m10, m3
+ vbroadcasti128 m3, [r4+ssq*0]
+ paddw m11, m4
+ shufpd m4, m0, m9, 0x0d
+ shufpd m0, m9, m3, 0x0c
+ punpcklbw m3, m4, m0 ; 45
+ punpckhbw m4, m0 ; 56
+ pmaddubsw m9, m3, m7 ; a2
+ paddw m10, m9
+ pmaddubsw m9, m4, m7 ; b2
+ paddw m11, m9
+ pmulhrsw m10, m8
+ pmulhrsw m11, m8
+ packuswb m10, m11
+ vpermq m10, m10, q3120
+ mova [r7+dsq*0], xm10
+ vextracti128 [r7+dsq*1], m10, 1
+ lea r7, [r7+dsq*2]
+ sub hd, 2
+ jg .v_w16_loop
+ add srcq, 16
+ add dstq, 16
+ movzx hd, r6b
+ sub r6d, 1<<8
+ jg .v_w16_loop0
+ RET
+.hv:
+ WIN64_SPILL_XMM 12, 16
+ cmp wd, 4
+ jg .hv_w8
+ movzx mxd, mxb
+ dec srcq
+ vpbroadcastd m6, [r8+mxq*8+subpel_filters-put_avx2+2]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ vpbroadcastq m0, [r8+myq*8+subpel_filters+1-put_avx2]
+ vpbroadcastd m7, [pw_8192]
+ punpcklbw m0, m0
+ vpbroadcastd m8, [pd_512]
+ psraw m0, 8 ; sign-extend
+ mov nsq, ssq
+ pshufd m9, m0, q0000
+ neg nsq
+ pshufd m10, m0, q1111
+ pshufd m11, m0, q2222
+ cmp wd, 4
+ je .hv_w4
+ vbroadcasti128 m5, [subpel_h_shuf4]
+ movq xm2, [srcq+nsq*2]
+ movhps xm2, [srcq+nsq*1]
+ movq xm0, [srcq+ssq*0]
+ movhps xm0, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vpbroadcastq m1, [srcq+ssq*0]
+ vpblendd m2, m1, 0x30
+ pshufb m2, m5
+ pshufb xm0, xm5
+ pmaddubsw m2, m6
+ pmaddubsw xm0, xm6
+ phaddw m2, m0
+ pmulhrsw m2, m7
+ vextracti128 xm0, m2, 1
+ palignr xm0, xm2, 4
+ punpcklwd xm1, xm2, xm0 ; 01 12
+ punpckhwd xm2, xm0 ; 23 34
+.hv_w2_loop:
+ movq xm4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ movhps xm4, [srcq+ssq*0]
+ pshufb xm4, xm5
+ pmaddubsw xm4, xm6
+ pmaddwd xm3, xm9, xm1 ; a0 b0
+ mova xm1, xm2
+ pmaddwd xm2, xm10 ; a1 b1
+ phaddw xm4, xm4
+ paddd xm3, xm2
+ pmulhrsw xm4, xm7
+ palignr xm2, xm4, xm0, 12
+ mova xm0, xm4
+ punpcklwd xm2, xm4 ; 45 56
+ pmaddwd xm4, xm11, xm2 ; a2 b2
+ paddd xm3, xm8
+ paddd xm3, xm4
+ psrad xm3, 10
+ packssdw xm3, xm3
+ packuswb xm3, xm3
+ pextrw [dstq+dsq*0], xm3, 0
+ pextrw [dstq+dsq*1], xm3, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .hv_w2_loop
+ RET
+.hv_w4:
+ mova m5, [subpel_h_shuf4]
+ vpbroadcastq m2, [srcq+nsq*2]
+ vpbroadcastq m4, [srcq+nsq*1]
+ vpbroadcastq m1, [srcq+ssq*0]
+ vpbroadcastq m3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vpbroadcastq m0, [srcq+ssq*0]
+ vpblendd m2, m4, 0xcc ; 0 1
+ vpblendd m1, m3, 0xcc ; 2 3
+ pshufb m2, m5
+ pshufb m1, m5
+ pshufb m0, m5
+ pmaddubsw m2, m6
+ pmaddubsw m1, m6
+ pmaddubsw m0, m6
+ phaddw m2, m1
+ phaddw m0, m0
+ pmulhrsw m2, m7
+ pmulhrsw m0, m7
+ palignr m3, m0, m2, 4
+ punpcklwd m1, m2, m3 ; 01 12
+ punpckhwd m2, m3 ; 23 34
+.hv_w4_loop:
+ vpbroadcastq m4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddwd m3, m9, m1 ; a0 b0
+ mova m1, m2
+ pmaddwd m2, m10 ; a1 b1
+ paddd m3, m2
+ vpbroadcastq m2, [srcq+ssq*0]
+ vpblendd m4, m2, 0xcc ; 5 6
+ pshufb m4, m5
+ pmaddubsw m4, m6
+ phaddw m4, m4
+ pmulhrsw m4, m7
+ palignr m2, m4, m0, 12
+ mova m0, m4
+ punpcklwd m2, m4 ; 45 56
+ pmaddwd m4, m11, m2 ; a2 b2
+ paddd m3, m8
+ paddd m3, m4
+ psrad m3, 10
+ vextracti128 xm4, m3, 1
+ packssdw xm3, xm4
+ packuswb xm3, xm3
+ pshuflw xm3, xm3, q3120
+ movd [dstq+dsq*0], xm3
+ pextrd [dstq+dsq*1], xm3, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .hv_w4_loop
+ RET
+.hv_w8:
+ shr mxd, 16
+ sub srcq, 2
+ lea mxq, [r8+mxq*8+subpel_filters+1-put_avx2]
+ WIN64_PUSH_XMM 16
+ vpbroadcastw m10, [mxq+0]
+ vpbroadcastw m11, [mxq+2]
+ vpbroadcastw m12, [mxq+4]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ vpbroadcastq m0, [r8+myq*8+subpel_filters+1-put_avx2]
+ lea r6d, [wq*8-64]
+ vbroadcasti128 m8, [z_filter_s+ 6]
+ punpcklbw m0, m0
+ vbroadcasti128 m9, [z_filter_s+10]
+ psraw m0, 8 ; sign-extend
+ mov nsq, ssq
+ pshufd m13, m0, q0000
+ neg nsq
+ pshufd m14, m0, q1111
+ lea r6d, [hq+r6*4]
+ pshufd m15, m0, q2222
+.hv_w8_loop0:
+ vbroadcasti128 m7, [z_filter_s+2]
+ movu xm3, [srcq+nsq*2]
+ lea r4, [srcq+ssq*2]
+ movu xm4, [srcq+nsq*1]
+ vbroadcasti128 m0, [srcq+ssq*0]
+ mov r7, dstq
+ vinserti128 m4, [srcq+ssq*1], 1 ; 1 3
+ vpblendd m3, m0, 0xf0 ; 0 2
+ vinserti128 m0, [r4+ssq*0], 1 ; 2 4
+ vpbroadcastd m5, [pw_8192]
+%macro HV_H_6TAP_W8 6 ; src/dst, tmp[1-2], shuf[1-3]
+ pshufb %2, %1, %4
+ pmaddubsw %2, m10
+ pshufb %3, %1, %5
+ pmaddubsw %3, m11
+ pshufb %1, %6
+ pmaddubsw %1, m12
+ paddw %2, %3
+ paddw %1, %2
+%endmacro
+ HV_H_6TAP_W8 m3, m1, m2, m7, m8, m9
+ HV_H_6TAP_W8 m4, m1, m2, m7, m8, m9
+ HV_H_6TAP_W8 m0, m1, m2, m7, m8, m9
+ vpermq m3, m3, q3120
+ vpermq m4, m4, q3120
+ vpermq m0, m0, q3120
+ pmulhrsw m3, m5
+ pmulhrsw m4, m5
+ pmulhrsw m0, m5
+ punpcklwd m1, m3, m4 ; 01
+ punpckhwd m3, m4 ; 23
+ punpcklwd m2, m4, m0 ; 12
+ punpckhwd m4, m0 ; 34
+.hv_w8_loop:
+ movu xm7, [r4+ssq*1]
+ lea r4, [r4+ssq*2]
+ vinserti128 m7, [r4+ssq*0], 1 ; 5 6
+ pmaddwd m5, m13, m1 ; a0
+ mova m1, m3
+ pmaddwd m6, m13, m2 ; b0
+ mova m2, m4
+ pmaddwd m3, m14 ; a1
+ pmaddwd m4, m14 ; b1
+ paddd m5, m3
+ vbroadcasti128 m3, [z_filter_s+2]
+ paddd m6, m4
+ HV_H_6TAP_W8 m7, m3, m4, m3, m8, m9
+ vpbroadcastd m3, [pw_8192]
+ vpbroadcastd m4, [pd_512]
+ pmulhrsw m7, m3
+ paddd m5, m4
+ paddd m6, m4
+ mova m4, m0
+ vpermq m0, m7, q3120
+ shufpd m4, m0, 0x05
+ punpcklwd m3, m4, m0 ; 45
+ pmaddwd m7, m15, m3 ; a2
+ punpckhwd m4, m0 ; 67
+ paddd m5, m7
+ pmaddwd m7, m15, m4 ; b2
+ paddd m6, m7
+ psrad m5, 10
+ psrad m6, 10
+ packssdw m5, m6
+ vextracti128 xm6, m5, 1
+ packuswb xm5, xm6
+ pshufd xm5, xm5, q3120
+ movq [r7+dsq*0], xm5
+ movhps [r7+dsq*1], xm5
+ lea r7, [r7+dsq*2]
+ sub hd, 2
+ jg .hv_w8_loop
+ add srcq, 8
+ add dstq, 8
+ movzx hd, r6b
+ sub r6d, 1<<8
+ jg .hv_w8_loop0
+ RET
+
+PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP, put_8tap_8bpc
+PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH, put_8tap_8bpc
+PUT_8TAP_FN regular_sharp, REGULAR, SHARP, put_8tap_8bpc
+PUT_8TAP_FN sharp_regular, SHARP, REGULAR, put_8tap_8bpc
+PUT_8TAP_FN sharp, SHARP, SHARP
+
+cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
+ imul mxd, mxm, 0x010101
+ add mxd, t0d ; 8tap_h, mx, 4tap_h
+ imul myd, mym, 0x010101
+ add myd, t1d ; 8tap_v, my, 4tap_v
+ lea r8, [put_avx2]
+ movsxd wq, wm
+ movifnidn hd, hm
+ test mxd, 0xf00
+ jnz .h
+ test myd, 0xf00
+ jz mangle(private_prefix %+ _put_6tap_8bpc_avx2).put
+.v:
+ WIN64_SPILL_XMM 12, 15
movzx mxd, myb
shr myd, 16
cmp hd, 6
@@ -1765,19 +2175,19 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
.v_w64:
.v_w128:
lea r6d, [wq*8-128]
- mov r4, srcq
- mov r7, dstq
+ WIN64_PUSH_XMM 15
lea r6d, [hq+r6*2]
.v_w16_loop0:
vbroadcasti128 m4, [srcq+ssq*0]
vbroadcasti128 m5, [srcq+ssq*1]
+ lea r4, [srcq+ss3q]
vbroadcasti128 m6, [srcq+ssq*2]
- add srcq, ss3q
- vbroadcasti128 m0, [srcq+ssq*0]
- vbroadcasti128 m1, [srcq+ssq*1]
- vbroadcasti128 m2, [srcq+ssq*2]
- add srcq, ss3q
- vbroadcasti128 m3, [srcq+ssq*0]
+ vbroadcasti128 m0, [r4+ssq*0]
+ mov r7, dstq
+ vbroadcasti128 m1, [r4+ssq*1]
+ vbroadcasti128 m2, [r4+ssq*2]
+ add r4, ss3q
+ vbroadcasti128 m3, [r4+ssq*0]
shufpd m4, m0, 0x0c
shufpd m5, m1, 0x0c
punpcklbw m1, m4, m5 ; 01
@@ -1789,50 +2199,137 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
punpcklbw m3, m6, m0 ; 23
punpckhbw m6, m0 ; 56
.v_w16_loop:
- vbroadcasti128 m12, [srcq+ssq*1]
- lea srcq, [srcq+ssq*2]
- vbroadcasti128 m13, [srcq+ssq*0]
- pmaddubsw m14, m1, m8 ; a0
- pmaddubsw m15, m2, m8 ; b0
+ vbroadcasti128 m12, [r4+ssq*1]
+ lea r4, [r4+ssq*2]
+ pmaddubsw m13, m1, m8 ; a0
+ pmaddubsw m14, m2, m8 ; b0
mova m1, m3
mova m2, m4
pmaddubsw m3, m9 ; a1
pmaddubsw m4, m9 ; b1
- paddw m14, m3
- paddw m15, m4
+ paddw m13, m3
+ paddw m14, m4
mova m3, m5
mova m4, m6
pmaddubsw m5, m10 ; a2
pmaddubsw m6, m10 ; b2
- paddw m14, m5
- paddw m15, m6
+ paddw m13, m5
+ vbroadcasti128 m5, [r4+ssq*0]
+ paddw m14, m6
shufpd m6, m0, m12, 0x0d
- shufpd m0, m12, m13, 0x0c
+ shufpd m0, m12, m5, 0x0c
punpcklbw m5, m6, m0 ; 67
punpckhbw m6, m0 ; 78
pmaddubsw m12, m5, m11 ; a3
- pmaddubsw m13, m6, m11 ; b3
+ paddw m13, m12
+ pmaddubsw m12, m6, m11 ; b3
paddw m14, m12
- paddw m15, m13
+ pmulhrsw m13, m7
pmulhrsw m14, m7
- pmulhrsw m15, m7
- packuswb m14, m15
- vpermq m14, m14, q3120
- mova [dstq+dsq*0], xm14
- vextracti128 [dstq+dsq*1], m14, 1
- lea dstq, [dstq+dsq*2]
+ packuswb m13, m14
+ vpermq m13, m13, q3120
+ mova [r7+dsq*0], xm13
+ vextracti128 [r7+dsq*1], m13, 1
+ lea r7, [r7+dsq*2]
sub hd, 2
jg .v_w16_loop
- add r4, 16
- add r7, 16
+ add srcq, 16
+ add dstq, 16
movzx hd, r6b
- mov srcq, r4
- mov dstq, r7
sub r6d, 1<<8
jg .v_w16_loop0
RET
+.h:
+.h_w2:
+.h_w4:
+ test myd, 0xf00
+ jnz .hv
+ vpbroadcastd m5, [pw_34] ; 2 + (8 << 2)
+ cmp wd, 4
+ jle mangle(private_prefix %+ _put_6tap_8bpc_avx2).h_w2
+ WIN64_SPILL_XMM 11
+ tzcnt wd, wd
+ vbroadcasti128 m6, [subpel_h_shufA]
+ shr mxd, 16
+ vbroadcasti128 m7, [subpel_h_shufB]
+ sub srcq, 3
+ vbroadcasti128 m8, [subpel_h_shufC]
+ movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)]
+ vpbroadcastd m9, [r8+mxq*8+subpel_filters-put_avx2+0]
+ vpbroadcastd m10, [r8+mxq*8+subpel_filters-put_avx2+4]
+ add wq, r8
+ jmp wq
+.h_w8:
+%macro PUT_8TAP_H 4 ; dst/src, tmp[1-3]
+ pshufb m%2, m%1, m7
+ pshufb m%3, m%1, m8
+ pshufb m%1, m6
+ pmaddubsw m%4, m%2, m9
+ pmaddubsw m%2, m10
+ pmaddubsw m%3, m10
+ pmaddubsw m%1, m9
+ paddw m%3, m%4
+ paddw m%1, m%2
+ phaddw m%1, m%3
+ paddw m%1, m5
+ psraw m%1, 6
+%endmacro
+ movu xm0, [srcq+ssq*0]
+ vinserti128 m0, [srcq+ssq*1], 1
+ lea srcq, [srcq+ssq*2]
+ PUT_8TAP_H 0, 1, 2, 3
+ vextracti128 xm1, m0, 1
+ packuswb xm0, xm1
+ movq [dstq+dsq*0], xm0
+ movhps [dstq+dsq*1], xm0
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w8
+ RET
+.h_w16:
+ movu xm0, [srcq+ssq*0+8*0]
+ vinserti128 m0, [srcq+ssq*1+8*0], 1
+ movu xm1, [srcq+ssq*0+8*1]
+ vinserti128 m1, [srcq+ssq*1+8*1], 1
+ PUT_8TAP_H 0, 2, 3, 4
+ lea srcq, [srcq+ssq*2]
+ PUT_8TAP_H 1, 2, 3, 4
+ packuswb m0, m1
+ mova [dstq+dsq*0], xm0
+ vextracti128 [dstq+dsq*1], m0, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w16
+ RET
+.h_w32:
+ xor r6d, r6d
+ jmp .h_start
+.h_w64:
+ mov r6, -32*1
+ jmp .h_start
+.h_w128:
+ mov r6, -32*3
+.h_start:
+ sub srcq, r6
+ sub dstq, r6
+ mov r4, r6
+.h_loop:
+ movu m0, [srcq+r6+8*0]
+ movu m1, [srcq+r6+8*1]
+ PUT_8TAP_H 0, 2, 3, 4
+ PUT_8TAP_H 1, 2, 3, 4
+ packuswb m0, m1
+ mova [dstq+r6], m0
+ add r6, 32
+ jle .h_loop
+ add srcq, ssq
+ add dstq, dsq
+ mov r6, r4
+ dec hd
+ jg .h_loop
+ RET
.hv:
- WIN64_SPILL_XMM 16
+ WIN64_SPILL_XMM 14, 16
cmp wd, 4
jg .hv_w8
movzx mxd, mxb
@@ -1975,6 +2472,7 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
jg .hv_w4_loop
RET
.hv_w8:
+ WIN64_PUSH_XMM 16
shr mxd, 16
sub srcq, 3
vpbroadcastd m10, [r8+mxq*8+subpel_filters-put_avx2+0]
@@ -1993,24 +2491,23 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
pshufd m14, m0, q2222
pshufd m15, m0, q3333
lea r6d, [wq*8-64]
- mov r4, srcq
- mov r7, dstq
lea r6d, [hq+r6*4]
.hv_w8_loop0:
vbroadcasti128 m7, [subpel_h_shufA]
movu xm4, [srcq+ssq*0]
+ lea r4, [srcq+ss3q]
vbroadcasti128 m8, [subpel_h_shufB]
movu xm5, [srcq+ssq*1]
+ mov r7, dstq
vbroadcasti128 m9, [subpel_h_shufC]
movu xm6, [srcq+ssq*2]
- add srcq, ss3q
- vbroadcasti128 m0, [srcq+ssq*0]
- vpblendd m4, m0, 0xf0 ; 0 3
- vinserti128 m5, [srcq+ssq*1], 1 ; 1 4
- vinserti128 m6, [srcq+ssq*2], 1 ; 2 5
- add srcq, ss3q
- vinserti128 m0, [srcq+ssq*0], 1 ; 3 6
-%macro HV_H_W8 4-7 ; src/dst, tmp[1-3], shuf[1-3]
+ vbroadcasti128 m0, [r4+ssq*0]
+ vpblendd m4, m0, 0xf0 ; 0 3
+ vinserti128 m5, [r4+ssq*1], 1 ; 1 4
+ vinserti128 m6, [r4+ssq*2], 1 ; 2 5
+ add r4, ss3q
+ vinserti128 m0, [r4+ssq*0], 1 ; 3 6
+%macro HV_H_8TAP_W8 4-7 ; src/dst, tmp[1-3], shuf[1-3]
pshufb %3, %1, %6
pshufb %4, %1, %7
pshufb %1, %5
@@ -2022,10 +2519,10 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
paddw %1, %3
phaddw %1, %2
%endmacro
- HV_H_W8 m4, m1, m2, m3, m7, m8, m9
- HV_H_W8 m5, m1, m2, m3, m7, m8, m9
- HV_H_W8 m6, m1, m2, m3, m7, m8, m9
- HV_H_W8 m0, m1, m2, m3, m7, m8, m9
+ HV_H_8TAP_W8 m4, m1, m2, m3, m7, m8, m9
+ HV_H_8TAP_W8 m5, m1, m2, m3, m7, m8, m9
+ HV_H_8TAP_W8 m6, m1, m2, m3, m7, m8, m9
+ HV_H_8TAP_W8 m0, m1, m2, m3, m7, m8, m9
vpbroadcastd m7, [pw_8192]
vpermq m4, m4, q3120
vpermq m5, m5, q3120
@@ -2043,9 +2540,9 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
punpckhwd m6, m7 ; 56
.hv_w8_loop:
vextracti128 r6m, m0, 1 ; not enough registers
- movu xm0, [srcq+ssq*1]
- lea srcq, [srcq+ssq*2]
- vinserti128 m0, [srcq+ssq*0], 1 ; 7 8
+ movu xm0, [r4+ssq*1]
+ lea r4, [r4+ssq*2]
+ vinserti128 m0, [r4+ssq*0], 1 ; 7 8
pmaddwd m8, m1, m12 ; a0
pmaddwd m9, m2, m12 ; b0
mova m1, m3
@@ -2063,15 +2560,15 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vbroadcasti128 m6, [subpel_h_shufB]
vbroadcasti128 m7, [subpel_h_shufC]
vbroadcasti128 m5, [subpel_h_shufA]
- HV_H_W8 m0, m5, m6, m7, m5, m6, m7
+ HV_H_8TAP_W8 m0, m5, m6, m7, m5, m6, m7
vpbroadcastd m5, [pw_8192]
vpbroadcastd m7, [pd_512]
vbroadcasti128 m6, r6m
pmulhrsw m0, m5
paddd m8, m7
paddd m9, m7
- vpermq m7, m0, q3120 ; 7 8
- shufpd m6, m6, m7, 0x04 ; 6 7
+ vpermq m7, m0, q3120 ; 7 8
+ shufpd m6, m7, 0x04 ; 6 7
punpcklwd m5, m6, m7 ; 67
punpckhwd m6, m7 ; 78
pmaddwd m7, m5, m15 ; a3
@@ -2084,34 +2581,18 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vextracti128 xm7, m8, 1
packuswb xm8, xm7
pshufd xm7, xm8, q3120
- movq [dstq+dsq*0], xm7
- movhps [dstq+dsq*1], xm7
- lea dstq, [dstq+dsq*2]
+ movq [r7+dsq*0], xm7
+ movhps [r7+dsq*1], xm7
+ lea r7, [r7+dsq*2]
sub hd, 2
jg .hv_w8_loop
- add r4, 8
- add r7, 8
+ add srcq, 8
+ add dstq, 8
movzx hd, r6b
- mov srcq, r4
- mov dstq, r7
sub r6d, 1<<8
jg .hv_w8_loop0
RET
-%macro PREP_8TAP_H 0
- pshufb m1, m0, m5
- pshufb m2, m0, m6
- pshufb m3, m0, m7
- pmaddubsw m1, m8
- pmaddubsw m0, m2, m8
- pmaddubsw m2, m9
- pmaddubsw m3, m9
- paddw m1, m2
- paddw m0, m3
- phaddw m0, m1, m0
- pmulhrsw m0, m4
-%endmacro
-
%if WIN64
DECLARE_REG_TMP 6, 4
%else
@@ -2119,71 +2600,197 @@ DECLARE_REG_TMP 6, 7
%endif
%define PREP_8TAP_FN FN prep_8tap,
-PREP_8TAP_FN sharp, SHARP, SHARP
-PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH
-PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP
-PREP_8TAP_FN smooth, SMOOTH, SMOOTH
-PREP_8TAP_FN sharp_regular, SHARP, REGULAR
-PREP_8TAP_FN regular_sharp, REGULAR, SHARP
-PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR
-PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH
+PREP_8TAP_FN smooth, SMOOTH, SMOOTH, prep_6tap_8bpc
+PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR, prep_6tap_8bpc
+PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH, prep_6tap_8bpc
PREP_8TAP_FN regular, REGULAR, REGULAR
-cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
+cglobal prep_6tap_8bpc, 3, 8, 0, tmp, src, ss, w, h, mx, my, ns
imul mxd, mxm, 0x010101
- add mxd, t0d ; 8tap_h, mx, 4tap_h
+ add mxd, t0d ; 6tap_h, mx, 4tap_h
imul myd, mym, 0x010101
- add myd, t1d ; 8tap_v, my, 4tap_v
+ add myd, t1d ; 6tap_v, my, 4tap_v
lea r7, [prep%+SUFFIX]
- movsxd wq, wm
+ mov wd, wm
movifnidn hd, hm
test mxd, 0xf00
jnz .h
test myd, 0xf00
jnz .v
+.prep:
tzcnt wd, wd
movzx wd, word [r7+wq*2+table_offset(prep,)]
add wq, r7
- lea r6, [strideq*3]
+ lea r6, [ssq*3]
%if WIN64
pop r7
%endif
jmp wq
-.h:
- test myd, 0xf00
- jnz .hv
- vpbroadcastd m4, [pw_8192]
- vbroadcasti128 m5, [subpel_h_shufA]
- WIN64_SPILL_XMM 10
- cmp wd, 4
- je .h_w4
- tzcnt wd, wd
- vbroadcasti128 m6, [subpel_h_shufB]
- vbroadcasti128 m7, [subpel_h_shufC]
- shr mxd, 16
- sub srcq, 3
- movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)]
- vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep%+SUFFIX+0]
- vpbroadcastd m9, [r7+mxq*8+subpel_filters-prep%+SUFFIX+4]
- add wq, r7
- jmp wq
+.v:
+ WIN64_SPILL_XMM 10, 12
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ lea myq, [r7+myq*8+subpel_filters+1-prep%+SUFFIX]
+ vpbroadcastd m9, [pw_8192]
+ vpbroadcastw m6, [myq+0]
+ mov nsq, ssq
+ vpbroadcastw m7, [myq+2]
+ neg nsq
+ vpbroadcastw m8, [myq+4]
+ cmp wd, 8
+ jg .v_w16
+ je .v_w8
+.v_w4:
+ movd xm2, [srcq+nsq*2]
+ pinsrd xm2, [srcq+nsq*1], 1
+ vpbroadcastd m1, [srcq+ssq*0]
+ vpbroadcastd m3, [srcq+ssq*1]
+ vpbroadcastd m0, [srcq+ssq*2]
+ vbroadcasti128 m5, [deint_shuf4]
+ vpblendd m1, m2, 0xeb
+ punpcklqdq m3, m0
+ vpblendd m1, m3, 0x60 ; 0 1 2 _ 2 3 4 _
+ pshufb m1, m5 ; 01 12 23 34
+.v_w4_loop:
+ lea srcq, [srcq+ssq*4]
+ pinsrd xm0, [srcq+nsq*1], 1
+ vpbroadcastd m2, [srcq+ssq*0]
+ vpbroadcastd m3, [srcq+ssq*1]
+ vpblendd m2, m0, 0xeb
+ vpbroadcastd m0, [srcq+ssq*2]
+ punpcklqdq m3, m0
+ vpblendd m2, m3, 0x60 ; 4 5 6 _ 6 7 8 _
+ pshufb m2, m5 ; 45 56 67 78
+ pmaddubsw m3, m1, m6 ; a0 b0 c0 d0
+ vperm2i128 m1, m2, 0x21 ; 23 34 45 56
+ pmaddubsw m4, m2, m8 ; a2 b2 c2 d2
+ pmaddubsw m1, m7 ; a1 b1 c1 d1
+ paddw m3, m4
+ paddw m3, m1
+ pmulhrsw m3, m9
+ mova m1, m2
+ mova [tmpq], m3
+ add tmpq, 32
+ sub hd, 4
+ jg .v_w4_loop
+ RET
+.v_w8:
+ movq xm1, [srcq+nsq*2]
+ vpbroadcastq m3, [srcq+nsq*1]
+ vpbroadcastq m2, [srcq+ssq*0]
+ vpbroadcastq m4, [srcq+ssq*1]
+ vpbroadcastq m0, [srcq+ssq*2]
+ vpblendd m1, m3, 0x30
+ vpblendd m3, m2, 0x30
+ punpcklbw m1, m3 ; 01 12
+ vpblendd m2, m4, 0x30
+ vpblendd m4, m0, 0x30
+ punpcklbw m2, m4 ; 23 34
+.v_w8_loop:
+ lea srcq, [srcq+ssq*4]
+ pmaddubsw m1, m6 ; a0
+ vpbroadcastq m3, [srcq+nsq*1]
+ pmaddubsw m4, m2, m7 ; a1
+ pmaddubsw m5, m2, m6 ; b0
+ vpbroadcastq m2, [srcq+ssq*0]
+ vpblendd m0, m3, 0x30
+ vpblendd m3, m2, 0x30
+ paddw m4, m1
+ punpcklbw m1, m0, m3 ; 45 56
+ vpbroadcastq m3, [srcq+ssq*1]
+ vpbroadcastq m0, [srcq+ssq*2]
+ vpblendd m2, m3, 0x30
+ vpblendd m3, m0, 0x30
+ punpcklbw m2, m3 ; 67 78
+ pmaddubsw m3, m1, m7 ; b1
+ paddw m5, m3
+ pmaddubsw m3, m1, m8 ; a2
+ paddw m4, m3
+ pmaddubsw m3, m2, m8 ; b2
+ paddw m5, m3
+ pmulhrsw m4, m9
+ pmulhrsw m5, m9
+ mova [tmpq+32*0], m4
+ mova [tmpq+32*1], m5
+ add tmpq, 32*2
+ sub hd, 4
+ jg .v_w8_loop
+ RET
+.v_w16:
+ lea r6d, [wq*2-32]
+ lea srcq, [srcq+nsq*2]
+ WIN64_PUSH_XMM 12
+ lea r6d, [hq+r6*8]
+.v_w16_loop0:
+ vbroadcasti128 m3, [srcq+ssq*0]
+ lea r5, [srcq+ssq*2]
+ vbroadcasti128 m4, [srcq+ssq*1]
+ mov r7, tmpq
+ vbroadcasti128 m0, [r5+ssq*0]
+ vbroadcasti128 m1, [r5+ssq*1]
+ lea r5, [r5+ssq*2]
+ vbroadcasti128 m2, [r5+ssq*0]
+ shufpd m3, m0, 0x0c
+ shufpd m4, m1, 0x0c
+ punpcklbw m1, m3, m4 ; 01
+ punpckhbw m3, m4 ; 23
+ shufpd m0, m2, 0x0c
+ punpcklbw m2, m4, m0 ; 12
+ punpckhbw m4, m0 ; 34
+.v_w16_loop:
+ vbroadcasti128 m5, [r5+ssq*1]
+ pmaddubsw m10, m1, m6 ; a0
+ lea r5, [r5+ssq*2]
+ pmaddubsw m11, m2, m6 ; b0
+ mova m1, m3
+ pmaddubsw m3, m7 ; a1
+ mova m2, m4
+ pmaddubsw m4, m7 ; b1
+ paddw m10, m3
+ vbroadcasti128 m3, [r5+ssq*0]
+ paddw m11, m4
+ shufpd m4, m0, m5, 0x0d
+ shufpd m0, m5, m3, 0x0c
+ punpcklbw m3, m4, m0 ; 45
+ punpckhbw m4, m0 ; 56
+ pmaddubsw m5, m3, m8 ; a2
+ paddw m10, m5
+ pmaddubsw m5, m4, m8 ; b2
+ paddw m11, m5
+ pmulhrsw m10, m9
+ pmulhrsw m11, m9
+ mova [r7+wq*0], m10
+ mova [r7+wq*2], m11
+ lea r7, [r7+wq*4]
+ sub hd, 2
+ jg .v_w16_loop
+ add srcq, 16
+ add tmpq, 32
+ movzx hd, r6b
+ sub r6d, 1<<8
+ jg .v_w16_loop0
+ RET
.h_w4:
+ RESET_STACK_STATE
movzx mxd, mxb
+ vbroadcasti128 m3, [subpel_h_shufA]
dec srcq
- vpbroadcastd m6, [r7+mxq*8+subpel_filters-prep%+SUFFIX+2]
- lea stride3q, [strideq*3]
+ vpbroadcastd m5, [r7+mxq*8+subpel_filters-prep%+SUFFIX+2]
+ lea r3, [ssq*3]
.h_w4_loop:
- movq xm0, [srcq+strideq*0]
- vpbroadcastq m2, [srcq+strideq*2]
- movq xm1, [srcq+strideq*1]
- vpblendd m0, m2, 0xf0
- vpbroadcastq m2, [srcq+stride3q ]
- lea srcq, [srcq+strideq*4]
- vpblendd m1, m2, 0xf0
- pshufb m0, m5
- pshufb m1, m5
- pmaddubsw m0, m6
- pmaddubsw m1, m6
+ movq xm0, [srcq+ssq*0]
+ vpbroadcastq m2, [srcq+ssq*2]
+ movq xm1, [srcq+ssq*1]
+ vpblendd m0, m2, 0x30
+ vpbroadcastq m2, [srcq+r3 ]
+ lea srcq, [srcq+ssq*4]
+ vpblendd m1, m2, 0x30
+ pshufb m0, m3
+ pshufb m1, m3
+ pmaddubsw m0, m5
+ pmaddubsw m1, m5
phaddw m0, m1
pmulhrsw m0, m4
mova [tmpq], m0
@@ -2191,25 +2798,56 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
sub hd, 4
jg .h_w4_loop
RET
+.h:
+ test myd, 0xf00
+ jnz .hv
+ vpbroadcastd m4, [pw_8192]
+ cmp wd, 4
+ je .h_w4
+ WIN64_SPILL_XMM 10
+ tzcnt wd, wd
+ vbroadcasti128 m3, [z_filter_s+ 2]
+ shr mxd, 16
+ vbroadcasti128 m5, [z_filter_s+ 6]
+ sub srcq, 2
+ vbroadcasti128 m6, [z_filter_s+10]
+ lea mxq, [r7+mxq*8+subpel_filters+1-prep%+SUFFIX]
+ movzx wd, word [r7+wq*2+table_offset(prep, _6tap_h)]
+ vpbroadcastw m7, [mxq+0]
+ vpbroadcastw m8, [mxq+2]
+ add wq, r7
+ vpbroadcastw m9, [mxq+4]
+ jmp wq
.h_w8:
- movu xm0, [srcq+strideq*0]
- vinserti128 m0, [srcq+strideq*1], 1
- lea srcq, [srcq+strideq*2]
- PREP_8TAP_H
+ movu xm0, [srcq+ssq*0]
+ vinserti128 m0, [srcq+ssq*1], 1
+ lea srcq, [srcq+ssq*2]
+%macro PREP_6TAP_H 0
+ pshufb m1, m0, m3
+ pmaddubsw m1, m7
+ pshufb m2, m0, m5
+ pmaddubsw m2, m8
+ pshufb m0, m6
+ pmaddubsw m0, m9
+ paddw m1, m2
+ paddw m0, m1
+ pmulhrsw m0, m4
+%endmacro
+ PREP_6TAP_H
mova [tmpq], m0
add tmpq, 32
sub hd, 2
jg .h_w8
RET
.h_w16:
- movu xm0, [srcq+strideq*0+8*0]
- vinserti128 m0, [srcq+strideq*0+8*1], 1
- PREP_8TAP_H
+ movu xm0, [srcq+ssq*0+8*0]
+ vinserti128 m0, [srcq+ssq*0+8*1], 1
+ PREP_6TAP_H
mova [tmpq+32*0], m0
- movu xm0, [srcq+strideq*1+8*0]
- vinserti128 m0, [srcq+strideq*1+8*1], 1
- lea srcq, [srcq+strideq*2]
- PREP_8TAP_H
+ movu xm0, [srcq+ssq*1+8*0]
+ vinserti128 m0, [srcq+ssq*1+8*1], 1
+ lea srcq, [srcq+ssq*2]
+ PREP_6TAP_H
mova [tmpq+32*1], m0
add tmpq, 32*2
sub hd, 2
@@ -2229,27 +2867,219 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
.h_loop:
movu xm0, [srcq+r6+8*0]
vinserti128 m0, [srcq+r6+8*1], 1
- PREP_8TAP_H
+ PREP_6TAP_H
mova [tmpq+32*0], m0
movu xm0, [srcq+r6+8*2]
vinserti128 m0, [srcq+r6+8*3], 1
- PREP_8TAP_H
+ PREP_6TAP_H
mova [tmpq+32*1], m0
add tmpq, 32*2
add r6, 32
jle .h_loop
- add srcq, strideq
+ add srcq, ssq
mov r6, r5
dec hd
jg .h_loop
RET
+.hv:
+ WIN64_SPILL_XMM 14, 16
+ cmp wd, 4
+ jne .hv_w8
+.hv_w4:
+ movzx mxd, mxb
+ dec srcq
+ vpbroadcastd m7, [r7+mxq*8+subpel_filters-prep%+SUFFIX+2]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ mova m6, [subpel_h_shuf4]
+ vpbroadcastq m0, [r7+myq*8+subpel_filters+1-prep%+SUFFIX]
+ mov nsq, ssq
+ pmovzxbd m13, [deint_shuf4]
+ neg nsq
+ vpbroadcastd m8, [pw_8192]
+ vpbroadcastd m9, [pd_32]
+ punpcklbw m0, m0
+ vpbroadcastq m2, [srcq+nsq*2]
+ psraw m0, 8 ; sign-extend
+ vpbroadcastq m4, [srcq+nsq*1]
+ pshufd m10, m0, q0000
+ vpbroadcastq m1, [srcq+ssq*0]
+ pshufd m11, m0, q1111
+ vpbroadcastq m3, [srcq+ssq*1]
+ pshufd m12, m0, q2222
+ vpbroadcastq m0, [srcq+ssq*2]
+ vpblendd m2, m4, 0xcc ; 0 1
+ vpblendd m1, m3, 0xcc ; 2 3
+ pshufb m2, m6
+ pshufb m1, m6
+ pshufb m0, m6
+ pmaddubsw m2, m7
+ pmaddubsw m1, m7
+ pmaddubsw m0, m7
+ phaddw m2, m1 ; 0 1 2 3
+ phaddw m0, m0 ; 4
+ pmulhrsw m2, m8
+ pmulhrsw m0, m8
+ palignr m0, m2, 4
+ punpcklwd m1, m2, m0 ; 01 12
+ punpckhwd m2, m0 ; 23 34
+.hv_w4_loop:
+ pmaddwd m4, m10, m1 ; a0 b0
+ lea srcq, [srcq+ssq*4]
+ pmaddwd m5, m2, m10 ; c0 d0
+ vpbroadcastq m1, [srcq+nsq*1]
+ pmaddwd m2, m11 ; a1 b1
+ vpbroadcastq m3, [srcq+ssq*0]
+ paddd m4, m2
+ vpbroadcastq m2, [srcq+ssq*1]
+ vpblendd m1, m3, 0xcc ; 5 6
+ vpbroadcastq m3, [srcq+ssq*2]
+ vpblendd m2, m3, 0xcc ; 7 8
+ pshufb m1, m6
+ pshufb m2, m6
+ pmaddubsw m1, m7
+ pmaddubsw m2, m7
+ phaddw m1, m2 ; 5 6 7 8
+ pmulhrsw m1, m8
+ paddd m5, m9
+ paddd m4, m9
+ palignr m2, m1, m0, 12
+ mova m0, m1
+ punpcklwd m1, m2, m0 ; 45 56
+ punpckhwd m2, m0 ; 67 78
+ pmaddwd m3, m11, m1 ; c1 d1
+ paddd m5, m3
+ pmaddwd m3, m12, m1 ; a2 b2
+ paddd m4, m3
+ pmaddwd m3, m12, m2 ; c2 d2
+ paddd m5, m3
+ psrad m4, 6
+ psrad m5, 6
+ packssdw m4, m5
+ vpermd m4, m13, m4
+ mova [tmpq], m4
+ add tmpq, 32
+ sub hd, 4
+ jg .hv_w4_loop
+ RET
+.hv_w8:
+ shr mxd, 16
+ lea mxq, [r7+mxq*8+subpel_filters+1-prep_avx2]
+ WIN64_PUSH_XMM 16
+ vpbroadcastw m10, [mxq+0]
+ vpbroadcastw m11, [mxq+2]
+ vpbroadcastw m12, [mxq+4]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ vpbroadcastq m0, [r7+myq*8+subpel_filters+1-prep_avx2]
+ lea r7, [ssq*2+2]
+ vbroadcasti128 m8, [z_filter_s+ 6]
+ punpcklbw m0, m0
+ vbroadcasti128 m9, [z_filter_s+10]
+ psraw m0, 8 ; sign-extend
+ lea r6d, [wq*8-64]
+ pshufd m13, m0, q0000
+ sub srcq, r7
+ pshufd m14, m0, q1111
+ lea r6d, [hq+r6*4]
+ pshufd m15, m0, q2222
+.hv_w8_loop0:
+ vbroadcasti128 m7, [z_filter_s+2]
+ movu xm3, [srcq+ssq*0]
+ lea r5, [srcq+ssq*2]
+ movu xm4, [srcq+ssq*1]
+ vbroadcasti128 m0, [r5+ssq*0]
+ mov r7, tmpq
+ vinserti128 m4, [r5+ssq*1], 1 ; 1 3
+ lea r5, [r5+ssq*2]
+ vpblendd m3, m0, 0xf0 ; 0 2
+ vinserti128 m0, [r5+ssq*0], 1 ; 2 4
+ vpbroadcastd m5, [pw_8192]
+ HV_H_6TAP_W8 m3, m1, m2, m7, m8, m9
+ HV_H_6TAP_W8 m4, m1, m2, m7, m8, m9
+ HV_H_6TAP_W8 m0, m1, m2, m7, m8, m9
+ vpermq m3, m3, q3120
+ vpermq m4, m4, q3120
+ vpermq m0, m0, q3120
+ pmulhrsw m3, m5
+ pmulhrsw m4, m5
+ pmulhrsw m0, m5
+ punpcklwd m1, m3, m4 ; 01
+ punpckhwd m3, m4 ; 23
+ punpcklwd m2, m4, m0 ; 12
+ punpckhwd m4, m0 ; 34
+.hv_w8_loop:
+ movu xm7, [r5+ssq*1]
+ lea r5, [r5+ssq*2]
+ vinserti128 m7, [r5+ssq*0], 1 ; 5 6
+ pmaddwd m5, m13, m1 ; a0
+ mova m1, m3
+ pmaddwd m6, m13, m2 ; b0
+ mova m2, m4
+ pmaddwd m3, m14 ; a1
+ pmaddwd m4, m14 ; b1
+ paddd m5, m3
+ vbroadcasti128 m3, [z_filter_s+2]
+ paddd m6, m4
+ HV_H_6TAP_W8 m7, m3, m4, m3, m8, m9
+ vpbroadcastd m3, [pw_8192]
+ vpbroadcastd m4, [pd_32]
+ pmulhrsw m7, m3
+ paddd m5, m4
+ paddd m6, m4
+ mova m4, m0
+ vpermq m0, m7, q3120
+ shufpd m4, m0, 0x05
+ punpcklwd m3, m4, m0 ; 45
+ pmaddwd m7, m15, m3 ; a2
+ punpckhwd m4, m0 ; 67
+ paddd m5, m7
+ pmaddwd m7, m15, m4 ; b2
+ paddd m6, m7
+ psrad m5, 6
+ psrad m6, 6
+ packssdw m5, m6
+ vpermq m5, m5, q3120
+ mova [r7+wq*0], xm5
+ vextracti128 [r7+wq*2], m5, 1
+ lea r7, [r7+wq*4]
+ sub hd, 2
+ jg .hv_w8_loop
+ add srcq, 8
+ add tmpq, 16
+ movzx hd, r6b
+ sub r6d, 1<<8
+ jg .hv_w8_loop0
+ RET
+
+PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP, prep_8tap_8bpc
+PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH, prep_8tap_8bpc
+PREP_8TAP_FN regular_sharp, REGULAR, SHARP, prep_8tap_8bpc
+PREP_8TAP_FN sharp_regular, SHARP, REGULAR, prep_8tap_8bpc
+PREP_8TAP_FN sharp, SHARP, SHARP
+
+cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
+ imul mxd, mxm, 0x010101
+ add mxd, t0d ; 8tap_h, mx, 4tap_h
+ imul myd, mym, 0x010101
+ add myd, t1d ; 8tap_v, my, 4tap_v
+ lea r7, [prep%+SUFFIX]
+ mov wd, wm
+ movifnidn hd, hm
+ test mxd, 0xf00
+ jnz .h
+ test myd, 0xf00
+ jz mangle(private_prefix %+ _prep_6tap_8bpc_avx2).prep
.v:
- WIN64_SPILL_XMM 16
+ WIN64_SPILL_XMM 12, 15
movzx mxd, myb ; Select 4-tap/8-tap filter multipliers.
shr myd, 16 ; Note that the code is 8-tap only, having
cmp hd, 4 ; a separate 4-tap code path for (4|8|16)x4
cmove myd, mxd ; had a negligible effect on performance.
- ; TODO: Would a 6-tap code path be worth it?
lea myq, [r7+myq*8+subpel_filters-prep%+SUFFIX]
lea stride3q, [strideq*3]
sub srcq, stride3q
@@ -2359,72 +3189,154 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
jg .v_w8_loop
RET
.v_w16:
- add wd, wd
- mov r5, srcq
- mov r7, tmpq
- lea r6d, [hq+wq*8-256]
+ lea r6d, [wq*2-32]
+ WIN64_PUSH_XMM 15
+ lea r6d, [hq+r6*8]
.v_w16_loop0:
vbroadcasti128 m4, [srcq+strideq*0]
vbroadcasti128 m5, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vbroadcasti128 m0, [srcq+strideq*1]
- vbroadcasti128 m6, [srcq+strideq*0]
- lea srcq, [srcq+strideq*2]
- vbroadcasti128 m1, [srcq+strideq*0]
- vbroadcasti128 m2, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vbroadcasti128 m3, [srcq+strideq*0]
- shufpd m4, m4, m0, 0x0c
- shufpd m5, m5, m1, 0x0c
+ lea r5, [srcq+strideq*2]
+ vbroadcasti128 m0, [r5+strideq*1]
+ vbroadcasti128 m6, [r5+strideq*0]
+ lea r5, [r5+strideq*2]
+ vbroadcasti128 m1, [r5+strideq*0]
+ vbroadcasti128 m2, [r5+strideq*1]
+ lea r5, [r5+strideq*2]
+ vbroadcasti128 m3, [r5+strideq*0]
+ mov r7, tmpq
+ shufpd m4, m0, 0x0c
+ shufpd m5, m1, 0x0c
punpcklbw m1, m4, m5 ; 01
punpckhbw m4, m5 ; 34
- shufpd m6, m6, m2, 0x0c
+ shufpd m6, m2, 0x0c
punpcklbw m2, m5, m6 ; 12
punpckhbw m5, m6 ; 45
- shufpd m0, m0, m3, 0x0c
+ shufpd m0, m3, 0x0c
punpcklbw m3, m6, m0 ; 23
punpckhbw m6, m0 ; 56
.v_w16_loop:
- vbroadcasti128 m12, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vbroadcasti128 m13, [srcq+strideq*0]
- pmaddubsw m14, m1, m8 ; a0
- pmaddubsw m15, m2, m8 ; b0
+ vbroadcasti128 m12, [r5+strideq*1]
+ lea r5, [r5+strideq*2]
+ pmaddubsw m13, m1, m8 ; a0
+ pmaddubsw m14, m2, m8 ; b0
mova m1, m3
mova m2, m4
pmaddubsw m3, m9 ; a1
pmaddubsw m4, m9 ; b1
- paddw m14, m3
- paddw m15, m4
+ paddw m13, m3
+ paddw m14, m4
mova m3, m5
mova m4, m6
pmaddubsw m5, m10 ; a2
pmaddubsw m6, m10 ; b2
- paddw m14, m5
- paddw m15, m6
+ paddw m13, m5
+ vbroadcasti128 m5, [r5+strideq*0]
+ paddw m14, m6
shufpd m6, m0, m12, 0x0d
- shufpd m0, m12, m13, 0x0c
+ shufpd m0, m12, m5, 0x0c
punpcklbw m5, m6, m0 ; 67
punpckhbw m6, m0 ; 78
pmaddubsw m12, m5, m11 ; a3
- pmaddubsw m13, m6, m11 ; b3
+ paddw m13, m12
+ pmaddubsw m12, m6, m11 ; b3
paddw m14, m12
- paddw m15, m13
+ pmulhrsw m13, m7
pmulhrsw m14, m7
- pmulhrsw m15, m7
- mova [tmpq+wq*0], m14
- mova [tmpq+wq*1], m15
- lea tmpq, [tmpq+wq*2]
+ mova [r7+wq*0], m13
+ mova [r7+wq*2], m14
+ lea r7, [r7+wq*4]
sub hd, 2
jg .v_w16_loop
- add r5, 16
- add r7, 32
+ add srcq, 16
+ add tmpq, 32
movzx hd, r6b
- mov srcq, r5
- mov tmpq, r7
sub r6d, 1<<8
jg .v_w16_loop0
RET
+.h:
+.h_w4:
+ test myd, 0xf00
+ jnz .hv
+ vpbroadcastd m4, [pw_8192]
+ cmp wd, 4
+ je mangle(private_prefix %+ _prep_6tap_8bpc_avx2).h_w4
+ WIN64_SPILL_XMM 10
+ vbroadcasti128 m5, [subpel_h_shufA]
+ tzcnt wd, wd
+ vbroadcasti128 m6, [subpel_h_shufB]
+ vbroadcasti128 m7, [subpel_h_shufC]
+ shr mxd, 16
+ sub srcq, 3
+ movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)]
+ vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep%+SUFFIX+0]
+ vpbroadcastd m9, [r7+mxq*8+subpel_filters-prep%+SUFFIX+4]
+ add wq, r7
+ jmp wq
+.h_w8:
+ movu xm0, [srcq+strideq*0]
+ vinserti128 m0, [srcq+strideq*1], 1
+ lea srcq, [srcq+strideq*2]
+%macro PREP_8TAP_H 0
+ pshufb m1, m0, m5
+ pshufb m2, m0, m6
+ pshufb m3, m0, m7
+ pmaddubsw m1, m8
+ pmaddubsw m0, m2, m8
+ pmaddubsw m2, m9
+ pmaddubsw m3, m9
+ paddw m1, m2
+ paddw m0, m3
+ phaddw m0, m1, m0
+ pmulhrsw m0, m4
+%endmacro
+ PREP_8TAP_H
+ mova [tmpq], m0
+ add tmpq, 32
+ sub hd, 2
+ jg .h_w8
+ RET
+.h_w16:
+ movu xm0, [srcq+strideq*0+8*0]
+ vinserti128 m0, [srcq+strideq*0+8*1], 1
+ PREP_8TAP_H
+ mova [tmpq+32*0], m0
+ movu xm0, [srcq+strideq*1+8*0]
+ vinserti128 m0, [srcq+strideq*1+8*1], 1
+ lea srcq, [srcq+strideq*2]
+ PREP_8TAP_H
+ mova [tmpq+32*1], m0
+ add tmpq, 32*2
+ sub hd, 2
+ jg .h_w16
+ RET
+.h_w32:
+ xor r6d, r6d
+ jmp .h_start
+.h_w64:
+ mov r6, -32*1
+ jmp .h_start
+.h_w128:
+ mov r6, -32*3
+.h_start:
+ sub srcq, r6
+ mov r5, r6
+.h_loop:
+ movu xm0, [srcq+r6+8*0]
+ vinserti128 m0, [srcq+r6+8*1], 1
+ PREP_8TAP_H
+ mova [tmpq+32*0], m0
+ movu xm0, [srcq+r6+8*2]
+ vinserti128 m0, [srcq+r6+8*3], 1
+ PREP_8TAP_H
+ mova [tmpq+32*1], m0
+ add tmpq, 32*2
+ add r6, 32
+ jle .h_loop
+ add srcq, strideq
+ mov r6, r5
+ dec hd
+ jg .h_loop
+ RET
.hv:
WIN64_SPILL_XMM 16
cmp wd, 4
@@ -2542,28 +3454,27 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
RET
.hv_w8:
lea r6d, [wq*8-64]
- mov r5, srcq
- mov r7, tmpq
lea r6d, [hq+r6*4]
.hv_w8_loop0:
vbroadcasti128 m7, [subpel_h_shufA]
movu xm4, [srcq+strideq*0]
+ lea r5, [srcq+strideq*2]
vbroadcasti128 m8, [subpel_h_shufB]
movu xm5, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
+ mov r7, tmpq
vbroadcasti128 m9, [subpel_h_shufC]
- movu xm6, [srcq+strideq*0]
- vbroadcasti128 m0, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vpblendd m4, m0, 0xf0 ; 0 3
- vinserti128 m5, [srcq+strideq*0], 1 ; 1 4
- vinserti128 m6, [srcq+strideq*1], 1 ; 2 5
- lea srcq, [srcq+strideq*2]
- vinserti128 m0, [srcq+strideq*0], 1 ; 3 6
- HV_H_W8 m4, m1, m2, m3, m7, m8, m9
- HV_H_W8 m5, m1, m2, m3, m7, m8, m9
- HV_H_W8 m6, m1, m2, m3, m7, m8, m9
- HV_H_W8 m0, m1, m2, m3, m7, m8, m9
+ movu xm6, [r5+strideq*0]
+ vbroadcasti128 m0, [r5+strideq*1]
+ lea r5, [r5+strideq*2]
+ vpblendd m4, m0, 0xf0 ; 0 3
+ vinserti128 m5, [r5+strideq*0], 1 ; 1 4
+ vinserti128 m6, [r5+strideq*1], 1 ; 2 5
+ lea r5, [r5+strideq*2]
+ vinserti128 m0, [r5+strideq*0], 1 ; 3 6
+ HV_H_8TAP_W8 m4, m1, m2, m3, m7, m8, m9
+ HV_H_8TAP_W8 m5, m1, m2, m3, m7, m8, m9
+ HV_H_8TAP_W8 m6, m1, m2, m3, m7, m8, m9
+ HV_H_8TAP_W8 m0, m1, m2, m3, m7, m8, m9
vpbroadcastd m7, [pw_8192]
vpermq m4, m4, q3120
vpermq m5, m5, q3120
@@ -2580,10 +3491,10 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
punpcklwd m3, m6, m7 ; 23
punpckhwd m6, m7 ; 56
.hv_w8_loop:
- vextracti128 [tmpq], m0, 1 ; not enough registers
- movu xm0, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vinserti128 m0, [srcq+strideq*0], 1 ; 7 8
+ vextracti128 [r7], m0, 1 ; not enough registers
+ movu xm0, [r5+strideq*1]
+ lea r5, [r5+strideq*2]
+ vinserti128 m0, [r5+strideq*0], 1 ; 7 8
pmaddwd m8, m1, m12 ; a0
pmaddwd m9, m2, m12 ; b0
mova m1, m3
@@ -2601,15 +3512,15 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
vbroadcasti128 m6, [subpel_h_shufB]
vbroadcasti128 m7, [subpel_h_shufC]
vbroadcasti128 m5, [subpel_h_shufA]
- HV_H_W8 m0, m5, m6, m7, m5, m6, m7
+ HV_H_8TAP_W8 m0, m5, m6, m7, m5, m6, m7
vpbroadcastd m5, [pw_8192]
vpbroadcastd m7, [pd_32]
- vbroadcasti128 m6, [tmpq]
+ vbroadcasti128 m6, [r7]
pmulhrsw m0, m5
paddd m8, m7
paddd m9, m7
- vpermq m7, m0, q3120 ; 7 8
- shufpd m6, m6, m7, 0x04 ; 6 7
+ vpermq m7, m0, q3120 ; 7 8
+ shufpd m6, m7, 0x04 ; 6 7
punpcklwd m5, m6, m7 ; 67
punpckhwd m6, m7 ; 78
pmaddwd m7, m5, m15 ; a3
@@ -2620,16 +3531,14 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
psrad m7, 6
packssdw m8, m7
vpermq m7, m8, q3120
- mova [tmpq+wq*0], xm7
- vextracti128 [tmpq+wq*2], m7, 1
- lea tmpq, [tmpq+wq*4]
+ mova [r7+wq*0], xm7
+ vextracti128 [r7+wq*2], m7, 1
+ lea r7, [r7+wq*4]
sub hd, 2
jg .hv_w8_loop
- add r5, 8
- add r7, 16
+ add srcq, 8
+ add tmpq, 16
movzx hd, r6b
- mov srcq, r5
- mov tmpq, r7
sub r6d, 1<<8
jg .hv_w8_loop0
RET
@@ -4008,14 +4917,14 @@ DECLARE_REG_TMP 6, 8
%define PREP_8TAP_SCALED_FN FN prep_8tap_scaled,
BILIN_SCALED_FN put
-PUT_8TAP_SCALED_FN sharp, SHARP, SHARP
-PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH
-PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP
-PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH
-PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR
-PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP
-PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR
-PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH
+PUT_8TAP_SCALED_FN sharp, SHARP, SHARP, put_8tap_scaled_8bpc
+PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH, put_8tap_scaled_8bpc
+PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP, put_8tap_scaled_8bpc
+PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH, put_8tap_scaled_8bpc
+PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR, put_8tap_scaled_8bpc
+PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP, put_8tap_scaled_8bpc
+PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR, put_8tap_scaled_8bpc
+PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH, put_8tap_scaled_8bpc
PUT_8TAP_SCALED_FN regular, REGULAR, REGULAR
MC_8TAP_SCALED put
@@ -4026,14 +4935,14 @@ DECLARE_REG_TMP 6, 7
%endif
BILIN_SCALED_FN prep
-PREP_8TAP_SCALED_FN sharp, SHARP, SHARP
-PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH
-PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP
-PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH
-PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR
-PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP
-PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR
-PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH
+PREP_8TAP_SCALED_FN sharp, SHARP, SHARP, prep_8tap_scaled_8bpc
+PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH, prep_8tap_scaled_8bpc
+PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP, prep_8tap_scaled_8bpc
+PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH, prep_8tap_scaled_8bpc
+PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR, prep_8tap_scaled_8bpc
+PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP, prep_8tap_scaled_8bpc
+PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR, prep_8tap_scaled_8bpc
+PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH, prep_8tap_scaled_8bpc
PREP_8TAP_SCALED_FN regular, REGULAR, REGULAR
MC_8TAP_SCALED prep
diff --git a/third_party/dav1d/src/x86/mc_avx512.asm b/third_party/dav1d/src/x86/mc_avx512.asm
index f9043f1ad3..50e670ec25 100644
--- a/third_party/dav1d/src/x86/mc_avx512.asm
+++ b/third_party/dav1d/src/x86/mc_avx512.asm
@@ -89,55 +89,47 @@ wm_444_mask: db 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 3
db 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63
db 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
db 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62
-bilin_h_perm16: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7
- db 9, 8, 10, 9, 11, 10, 12, 11, 13, 12, 14, 13, 15, 14, 16, 15
- db 33, 32, 34, 33, 35, 34, 36, 35, 37, 36, 38, 37, 39, 38, 40, 39
- db 41, 40, 42, 41, 43, 42, 44, 43, 45, 44, 46, 45, 47, 46, 48, 47
-bilin_h_perm32: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7
- db 9, 8, 10, 9, 11, 10, 12, 11, 13, 12, 14, 13, 15, 14, 16, 15
- db 17, 16, 18, 17, 19, 18, 20, 19, 21, 20, 22, 21, 23, 22, 24, 23
- db 25, 24, 26, 25, 27, 26, 28, 27, 29, 28, 30, 29, 31, 30, 32, 31
-bilin_v_perm8: db 16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7
- db 80, 16, 81, 17, 82, 18, 83, 19, 84, 20, 85, 21, 86, 22, 87, 23
- db 32, 80, 33, 81, 34, 82, 35, 83, 36, 84, 37, 85, 38, 86, 39, 87
- db 64, 32, 65, 33, 66, 34, 67, 35, 68, 36, 69, 37, 70, 38, 71, 39
-bilin_v_perm16: db 16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7
- db 24, 8, 25, 9, 26, 10, 27, 11, 28, 12, 29, 13, 30, 14, 31, 15
- db 64, 16, 65, 17, 66, 18, 67, 19, 68, 20, 69, 21, 70, 22, 71, 23
- db 72, 24, 73, 25, 74, 26, 75, 27, 76, 28, 77, 29, 78, 30, 79, 31
-bilin_v_perm32: db 64, 0, 65, 1, 66, 2, 67, 3, 68, 4, 69, 5, 70, 6, 71, 7
- db 72, 8, 73, 9, 74, 10, 75, 11, 76, 12, 77, 13, 78, 14, 79, 15
- db 80, 16, 81, 17, 82, 18, 83, 19, 84, 20, 85, 21, 86, 22, 87, 23
- db 88, 24, 89, 25, 90, 26, 91, 27, 92, 28, 93, 29, 94, 30, 95, 31
-bilin_v_perm64: dq 0, 4, 1, 5, 2, 6, 3, 7
-spel_h_perm16a: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6
+bilin_h_perm16: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
+ db 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16
+ db 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40
+ db 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48
+bilin_h_perm32: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
+ db 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16
+ db 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24
+ db 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32
+bilin_v_perm8: db 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23
+ db 16, 80, 17, 81, 18, 82, 19, 83, 20, 84, 21, 85, 22, 86, 23, 87
+ db 80, 32, 81, 33, 82, 34, 83, 35, 84, 36, 85, 37, 86, 38, 87, 39
+ db 32, 64, 33, 65, 34, 66, 35, 67, 36, 68, 37, 69, 38, 70, 39, 71
+bilin_v_perm16: db 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23
+ db 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31
+ db 16, 64, 17, 65, 18, 66, 19, 67, 20, 68, 21, 69, 22, 70, 23, 71
+ db 24, 72, 25, 73, 26, 74, 27, 75, 28, 76, 29, 77, 30, 78, 31, 79
+bilin_v_perm32: db 0, 64, 1, 65, 2, 66, 3, 67, 4, 68, 5, 69, 6, 70, 7, 71
+ db 8, 72, 9, 73, 10, 74, 11, 75, 12, 76, 13, 77, 14, 78, 15, 79
+ db 16, 80, 17, 81, 18, 82, 19, 83, 20, 84, 21, 85, 22, 86, 23, 87
+ db 24, 88, 25, 89, 26, 90, 27, 91, 28, 92, 29, 93, 30, 94, 31, 95
+bilin_v_perm64: dd 0, 0, 4, 8, 1, 1, 5, 9, 2, 2, 6, 10, 3, 3, 7, 11
+spel_h_perm16: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6
db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
db 32, 33, 34, 35, 33, 34, 35, 36, 34, 35, 36, 37, 35, 36, 37, 38
db 40, 41, 42, 43, 41, 42, 43, 44, 42, 43, 44, 45, 43, 44, 45, 46
-spel_h_perm16b: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10
- db 12, 13, 14, 15, 13, 14, 15, 16, 14, 15, 16, 17, 15, 16, 17, 18
- db 36, 37, 38, 39, 37, 38, 39, 40, 38, 39, 40, 41, 39, 40, 41, 42
- db 44, 45, 46, 47, 45, 46, 47, 48, 46, 47, 48, 49, 47, 48, 49, 50
-spel_h_perm16c: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
- db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22
- db 40, 41, 42, 43, 41, 42, 43, 44, 42, 43, 44, 45, 43, 44, 45, 46
- db 48, 49, 50, 51, 49, 50, 51, 52, 50, 51, 52, 53, 51, 52, 53, 54
-spel_h_perm32a: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6
+spel_h_perm32: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6
db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22
db 24, 25, 26, 27, 25, 26, 27, 28, 26, 27, 28, 29, 27, 28, 29, 30
-spel_h_perm32b: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10
- db 12, 13, 14, 15, 13, 14, 15, 16, 14, 15, 16, 17, 15, 16, 17, 18
- db 20, 21, 22, 23, 21, 22, 23, 24, 22, 23, 24, 25, 23, 24, 25, 26
- db 28, 29, 30, 31, 29, 30, 31, 32, 30, 31, 32, 33, 31, 32, 33, 34
-spel_h_perm32c: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
- db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22
- db 24, 25, 26, 27, 25, 26, 27, 28, 26, 27, 28, 29, 27, 28, 29, 30
- db 32, 33, 34, 35, 33, 34, 35, 36, 34, 35, 36, 37, 35, 36, 37, 38
-spel_v_perm16: db 32, 0, 33, 1, 34, 2, 35, 3, 36, 4, 37, 5, 38, 6, 39, 7
+spel_v_perm8: db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
+ db 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 14, 22, 15, 23
+ db 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31
+ db 24, 32, 25, 33, 26, 34, 27, 35, 28, 36, 29, 37, 30, 38, 31, 39
+spel_v_perm16a: db 32, 0, 33, 1, 34, 2, 35, 3, 36, 4, 37, 5, 38, 6, 39, 7
db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
db 40, 16, 41, 17, 42, 18, 43, 19, 44, 20, 45, 21, 46, 22, 47, 23
db 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31
+spel_v_perm16b: db 32, 0, 33, 1, 34, 2, 35, 3, 36, 4, 37, 5, 38, 6, 39, 7
+ db 40, 16, 41, 17, 42, 18, 43, 19, 44, 20, 45, 21, 46, 22, 47, 23
+ db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
+ db 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31
spel_v_perm32: db 0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39
db 8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47
db 16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55
@@ -154,34 +146,20 @@ spel_hv_perm8a: db 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 2
db 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31
db 16, 17, 32, 33, 18, 19, 34, 35, 20, 21, 36, 37, 22, 23, 38, 39
db 24, 25, 40, 41, 26, 27, 42, 43, 28, 29, 44, 45, 30, 31, 46, 47
-spel_hv_perm8b: db 32, 33, 48, 49, 34, 35, 50, 51, 36, 37, 52, 53, 38, 39, 54, 55
- db 40, 41, 56, 57, 42, 43, 58, 59, 44, 45, 60, 61, 46, 47, 62, 63
- db 48, 49, 64, 65, 50, 51, 66, 67, 52, 53, 68, 69, 54, 55, 70, 71
- db 56, 57, 72, 73, 58, 59, 74, 75, 60, 61, 76, 77, 62, 63, 78, 79
-spel_hv_perm8c: db 34, 35, 0, 1, 38, 39, 4, 5, 42, 43, 8, 9, 46, 47, 12, 13
+spel_hv_perm8b: db 34, 35, 0, 1, 38, 39, 4, 5, 42, 43, 8, 9, 46, 47, 12, 13
db 50, 51, 16, 17, 54, 55, 20, 21, 58, 59, 24, 25, 62, 63, 28, 29
db 0, 1, 32, 33, 4, 5, 36, 37, 8, 9, 40, 41, 12, 13, 44, 45
db 16, 17, 48, 49, 20, 21, 52, 53, 24, 25, 56, 57, 28, 29, 60, 61
-spel_hv_end16: db 1, 3, 17, 19, 5, 7, 21, 23, 33, 35, 49, 51, 37, 39, 53, 55
- db 9, 11, 25, 27, 13, 15, 29, 31, 41, 43, 57, 59, 45, 47, 61, 63
spel_hv_perm16a:db 0, 1, 2, 3, 32, 33, 34, 35, 1, 2, 3, 4, 33, 34, 35, 36
db 2, 3, 4, 5, 34, 35, 36, 37, 3, 4, 5, 6, 35, 36, 37, 38
-spel_hv_perm16c:db 8, 9, 10, 11, 40, 41, 42, 43, 9, 10, 11, 12, 41, 42, 43, 44
+ db 8, 9, 10, 11, 40, 41, 42, 43, 9, 10, 11, 12, 41, 42, 43, 44
db 10, 11, 12, 13, 42, 43, 44, 45, 11, 12, 13, 14, 43, 44, 45, 46
- db 16, 17, 18, 19, 48, 49, 50, 51, 17, 18, 19, 20, 49, 50, 51, 52
- db 18, 19, 20, 21, 50, 51, 52, 53, 19, 20, 21, 22, 51, 52, 53, 54
-spel_hv_perm16b:db 4, 5, 6, 7, 36, 37, 38, 39, 5, 6, 7, 8, 37, 38, 39, 40
- db 6, 7, 8, 9, 38, 39, 40, 41, 7, 8, 9, 10, 39, 40, 41, 42
- db 12, 13, 14, 15, 44, 45, 46, 47, 13, 14, 15, 16, 45, 46, 47, 48
- db 14, 15, 16, 17, 46, 47, 48, 49, 15, 16, 17, 18, 47, 48, 49, 50
-spel_hv_perm16d:db 0, 1, 2, 3, 1, 2, 3, 4, 4, 5, 6, 7, 5, 6, 7, 8
+spel_hv_perm16b:db 0, 1, 2, 3, 1, 2, 3, 4, 4, 5, 6, 7, 5, 6, 7, 8
db 2, 3, 4, 5, 3, 4, 5, 6, 6, 7, 8, 9, 7, 8, 9, 10
db 8, 9, 10, 11, 9, 10, 11, 12, 12, 13, 14, 15, 13, 14, 15, 16
db 10, 11, 12, 13, 11, 12, 13, 14, 14, 15, 16, 17, 15, 16, 17, 18
-spel_hv_perm16e:db 4, 5, 6, 7, 5, 6, 7, 8, 8, 9, 10, 11, 9, 10, 11, 12
- db 6, 7, 8, 9, 7, 8, 9, 10, 10, 11, 12, 13, 11, 12, 13, 14
- db 12, 13, 14, 15, 13, 14, 15, 16, 16, 17, 18, 19, 17, 18, 19, 20
- db 14, 15, 16, 17, 15, 16, 17, 18, 18, 19, 20, 21, 19, 20, 21, 22
+spel_hv_end16: db 1, 3, 17, 19, 5, 7, 21, 23, 33, 35, 49, 51, 37, 39, 53, 55
+ db 9, 11, 25, 27, 13, 15, 29, 31, 41, 43, 57, 59, 45, 47, 61, 63
spel_hv_end: db 1, 3, 5, 7, 17, 19, 21, 23, 33, 35, 37, 39, 49, 51, 53, 55
deint_shuf4: db 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11
subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 12
@@ -189,15 +167,14 @@ subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 1
subpel_h_shufA: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6
subpel_h_shufB: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10
subpel_h_shufC: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
-bilin_h_shuf4: db 1, 0, 2, 1, 3, 2, 4, 3, 9, 8, 10, 9, 11, 10, 12, 11
-bilin_h_shuf8: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7
-bilin_v_shuf4: db 4, 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7
+bilin_h_shuf4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12
+bilin_v_shuf4: db 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11
blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3
rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7
resize_permA: dd 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
resize_permB: dd 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31
resize_permC: dd 0, 4, 8, 12
+resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7
pb_02461357: db 0, 2, 4, 6, 1, 3, 5, 7
wm_420_perm64: dq 0xfedcba9876543210
@@ -205,6 +182,8 @@ wm_sign: dd 0x40804080, 0xc0c0c0c0, 0x40404040
pb_8x0_8x8: times 8 db 0
times 8 db 8
+pb_4: times 4 db 4
+pb_32: times 4 db 32
pb_127: times 4 db 127
pw_m128 times 2 dw -128
pw_m256: times 2 dw -256
@@ -216,7 +195,6 @@ pd_32: dd 32
pd_34: dd 34
pd_63: dd 63
pd_512: dd 512
-pd_32768: dd 32768
%define pb_m64 (wm_sign+4)
%define pb_64 (wm_sign+8)
@@ -289,8 +267,10 @@ BASE_JMP_TABLE put, avx512icl, 2, 4, 8, 16, 32, 64, 128
BASE_JMP_TABLE prep, avx512icl, 4, 8, 16, 32, 64, 128
HV_JMP_TABLE put, bilin, avx512icl, 7, 2, 4, 8, 16, 32, 64, 128
HV_JMP_TABLE prep, bilin, avx512icl, 7, 4, 8, 16, 32, 64, 128
+HV_JMP_TABLE put, 6tap, avx512icl, 2, 2, 4, 8, 16, 32, 64, 128
HV_JMP_TABLE put, 8tap, avx512icl, 3, 2, 4, 8, 16, 32, 64, 128
-HV_JMP_TABLE prep, 8tap, avx512icl, 7, 4, 8, 16, 32, 64, 128
+HV_JMP_TABLE prep, 6tap, avx512icl, 2, 4, 8, 16, 32, 64, 128
+HV_JMP_TABLE prep, 8tap, avx512icl, 3, 4, 8, 16, 32, 64, 128
BIDIR_JMP_TABLE avg, avx512icl, 4, 8, 16, 32, 64, 128
BIDIR_JMP_TABLE w_avg, avx512icl, 4, 8, 16, 32, 64, 128
BIDIR_JMP_TABLE mask, avx512icl, 4, 8, 16, 32, 64, 128
@@ -401,9 +381,9 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
.h:
; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4
; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4
- imul mxyd, 0xff01
- vbroadcasti128 m4, [bilin_h_shuf8]
- add mxyd, 16 << 8
+ imul mxyd, 255
+ vbroadcasti128 m4, [bilin_h_perm16]
+ add mxyd, 16
vpbroadcastw m5, mxyd
mov mxyd, r7m ; my
test mxyd, mxyd
@@ -526,9 +506,9 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
RET
.v:
movzx wd, word [r7+wq*2+table_offset(put, _bilin_v)]
- imul mxyd, 0xff01
+ imul mxyd, 255
vpbroadcastd m5, [pw_2048]
- add mxyd, 16 << 8
+ add mxyd, 16
add wq, r7
vpbroadcastw m4, mxyd
jmp wq
@@ -539,7 +519,7 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
lea srcq, [srcq+ssq*2]
pinsrw xmm0, xmm1, [srcq+ssq*0], 0 ; 2 1
pshuflw xmm1, xmm1, q2301 ; 1 0
- punpcklbw xmm1, xmm0, xmm1
+ punpcklbw xmm1, xmm0
pmaddubsw xmm1, xm4
pmulhrsw xmm1, xm5
packuswb xmm1, xmm1
@@ -552,11 +532,11 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
.v_w4:
movd xmm0, [srcq+ssq*0]
.v_w4_loop:
- vpbroadcastd xmm1, [srcq+ssq*1]
+ vpbroadcastd xmm2, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- vpblendd xmm2, xmm1, xmm0, 0x01 ; 0 1
+ vpblendd xmm1, xmm2, xmm0, 0x01 ; 0 1
vpbroadcastd xmm0, [srcq+ssq*0]
- vpblendd xmm1, xmm0, 0x02 ; 1 2
+ vpblendd xmm2, xmm0, 0x02 ; 1 2
punpcklbw xmm1, xmm2
pmaddubsw xmm1, xm4
pmulhrsw xmm1, xm5
@@ -570,11 +550,11 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
.v_w8:
movq xmm0, [srcq+ssq*0]
.v_w8_loop:
- movq xmm3, [srcq+ssq*1]
+ movq xmm2, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- punpcklbw xmm1, xmm3, xmm0
+ punpcklbw xmm1, xmm0, xmm2
movq xmm0, [srcq+ssq*0]
- punpcklbw xmm2, xmm0, xmm3
+ punpcklbw xmm2, xmm0
pmaddubsw xmm1, xm4
pmaddubsw xmm2, xm4
pmulhrsw xmm1, xm5
@@ -589,11 +569,11 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
.v_w16:
movu xmm0, [srcq+ssq*0]
.v_w16_loop:
- vbroadcasti128 ymm2, [srcq+ssq*1]
+ vbroadcasti128 ymm3, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- vpblendd ymm3, ymm2, ymm0, 0x0f ; 0 1
+ vpblendd ymm2, ymm3, ymm0, 0x0f ; 0 1
vbroadcasti128 ymm0, [srcq+ssq*0]
- vpblendd ymm2, ymm2, ymm0, 0xf0 ; 1 2
+ vpblendd ymm3, ymm0, 0xf0 ; 1 2
punpcklbw ymm1, ymm2, ymm3
punpckhbw ymm2, ymm3
pmaddubsw ymm1, ym4
@@ -612,11 +592,11 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
movu ym0, [srcq+ssq*0]
kxnorb k1, k1, k1
.v_w32_loop:
- vbroadcasti32x8 m2, [srcq+ssq*1]
+ vbroadcasti32x8 m3, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- vpblendmd m3{k1}, m2, m0 ; 0 1
+ vpblendmd m2{k1}, m3, m0 ; 0 1
vbroadcasti32x8 m0, [srcq+ssq*0]
- vpblendmd m2{k1}, m0, m2 ; 1 2
+ vpblendmd m3{k1}, m0, m3 ; 1 2
punpcklbw m1, m2, m3
punpckhbw m2, m3
pmaddubsw m1, m4
@@ -635,18 +615,18 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
.v_w64_loop:
movu m3, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- punpcklbw m1, m3, m0
- punpckhbw m6, m3, m0
+ punpcklbw m1, m0, m3
+ punpckhbw m6, m0, m3
movu m0, [srcq+ssq*0]
pmaddubsw m1, m4
pmaddubsw m6, m4
- punpcklbw m2, m0, m3
- punpckhbw m7, m0, m3
+ punpcklbw m2, m3, m0
+ punpckhbw m3, m0
pmaddubsw m2, m4
- pmaddubsw m7, m4
- REPX {pmulhrsw x, m5}, m1, m6, m2, m7
+ pmaddubsw m3, m4
+ REPX {pmulhrsw x, m5}, m1, m6, m2, m3
packuswb m1, m6
- packuswb m2, m7
+ packuswb m2, m3
mova [dstq+dsq*0], m1
mova [dstq+dsq*1], m2
lea dstq, [dstq+dsq*2]
@@ -660,13 +640,13 @@ cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy
add srcq, ssq
movu m2, [srcq+64*0]
movu m3, [srcq+64*1]
- punpcklbw m6, m2, m0
+ punpcklbw m6, m0, m2
pmaddubsw m6, m4
- punpckhbw m0, m2, m0
+ punpckhbw m0, m2
pmaddubsw m0, m4
- punpcklbw m7, m3, m1
+ punpcklbw m7, m1, m3
pmaddubsw m7, m4
- punpckhbw m1, m3, m1
+ punpckhbw m1, m3
pmaddubsw m1, m4
REPX {pmulhrsw x, m5}, m6, m0, m7, m1
packuswb m6, m0
@@ -1005,8 +985,8 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
.h:
; 16 * src[x] + (mx * (src[x + 1] - src[x]))
; = (16 - mx) * src[x] + mx * src[x + 1]
- imul mxyd, 0xff01
- add mxyd, 16 << 8
+ imul mxyd, 255
+ add mxyd, 16
vpbroadcastw m5, mxyd
mov mxyd, r6m ; my
test mxyd, mxyd
@@ -1032,7 +1012,7 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
jg .h_w4_loop
RET
.h_w8:
- vbroadcasti32x4 m4, [bilin_h_shuf8]
+ vbroadcasti32x4 m4, [bilin_h_perm16]
.h_w8_loop:
movu xmm0, [srcq+strideq*0]
vinserti32x4 ym0, ymm0, [srcq+strideq*1], 1
@@ -1127,8 +1107,8 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
.v:
WIN64_SPILL_XMM 7
movzx wd, word [t2+wq*2+table_offset(prep, _bilin_v)]
- imul mxyd, 0xff01
- add mxyd, 16 << 8
+ imul mxyd, 255
+ add mxyd, 16
add wq, t2
lea stride3q, [strideq*3]
vpbroadcastw m6, mxyd
@@ -1218,11 +1198,11 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
.v_w64_loop:
vpermq m1, m5, [srcq+strideq*1]
lea srcq, [srcq+strideq*2]
- punpcklbw m4, m1, m0
- punpckhbw m2, m1, m0
+ punpcklbw m4, m0, m1
+ punpckhbw m2, m0, m1
vpermq m0, m5, [srcq+strideq*0]
- punpcklbw m3, m0, m1
- punpckhbw m1, m0, m1
+ punpcklbw m3, m1, m0
+ punpckhbw m1, m0
pmaddubsw m4, m6
pmaddubsw m2, m6
pmaddubsw m3, m6
@@ -1243,28 +1223,28 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
vpermq m2, m5, [srcq+strideq*1+ 0]
vpermq m3, m5, [srcq+strideq*1+64]
lea srcq, [srcq+strideq*2]
- punpcklbw m4, m2, m0
- punpckhbw m0, m2, m0
+ punpcklbw m4, m0, m2
+ punpckhbw m0, m2
pmaddubsw m4, m6
pmaddubsw m0, m6
mova [tmpq+64*0], m4
mova [tmpq+64*1], m0
- punpcklbw m4, m3, m1
- punpckhbw m1, m3, m1
+ punpcklbw m4, m1, m3
+ punpckhbw m1, m3
pmaddubsw m4, m6
pmaddubsw m1, m6
mova [tmpq+64*2], m4
mova [tmpq+64*3], m1
vpermq m0, m5, [srcq+strideq*0+ 0]
vpermq m1, m5, [srcq+strideq*0+64]
- punpcklbw m4, m0, m2
- punpckhbw m2, m0, m2
+ punpcklbw m4, m2, m0
+ punpckhbw m2, m0
pmaddubsw m4, m6
pmaddubsw m2, m6
mova [tmpq+64*4], m4
mova [tmpq+64*5], m2
- punpcklbw m4, m1, m3
- punpckhbw m3, m1, m3
+ punpcklbw m4, m3, m1
+ punpckhbw m3, m1
pmaddubsw m4, m6
pmaddubsw m3, m6
mova [tmpq+64*6], m4
@@ -1308,7 +1288,7 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
jg .hv_w4_loop
RET
.hv_w8:
- vbroadcasti32x4 m4, [bilin_h_shuf8]
+ vbroadcasti32x4 m4, [bilin_h_perm16]
vbroadcasti32x4 m0, [srcq+strideq*0]
pshufb m0, m4
pmaddubsw m0, m5
@@ -1448,7 +1428,7 @@ cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3
%assign FILTER_SMOOTH (1*15 << 16) | 4*15
%assign FILTER_SHARP (2*15 << 16) | 3*15
-%macro FN 4 ; fn, type, type_h, type_v
+%macro FN 4-5 ; fn, type, type_h, type_v, jmp_to
cglobal %1_%2_8bpc
mov t0d, FILTER_%3
%ifidn %3, %4
@@ -1456,8 +1436,8 @@ cglobal %1_%2_8bpc
%else
mov t1d, FILTER_%4
%endif
-%ifnidn %2, regular ; skip the jump in the last filter
- jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX)
+%if %0 == 5 ; skip the jump in the last filter
+ jmp mangle(private_prefix %+ _%5 %+ SUFFIX)
%endif
%endmacro
@@ -1489,24 +1469,22 @@ DECLARE_REG_TMP 4, 5
DECLARE_REG_TMP 7, 8
%endif
+; Due to the use of vpdpbusd (which does 4 pixels per instruction) in
+; the horizontal filter, 6-tap is only used for the vertical filter.
%define PUT_8TAP_FN FN put_8tap,
-
-PUT_8TAP_FN sharp, SHARP, SHARP
-PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH
-PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP
-PUT_8TAP_FN smooth, SMOOTH, SMOOTH
-PUT_8TAP_FN sharp_regular, SHARP, REGULAR
-PUT_8TAP_FN regular_sharp, REGULAR, SHARP
-PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR
-PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH
+PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH, put_6tap_8bpc
+PUT_8TAP_FN sharp_regular, SHARP, REGULAR, put_6tap_8bpc
+PUT_8TAP_FN smooth, SMOOTH, SMOOTH, put_6tap_8bpc
+PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR, put_6tap_8bpc
+PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH, put_6tap_8bpc
PUT_8TAP_FN regular, REGULAR, REGULAR
-cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
+cglobal put_6tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ns
%define base r8-put_avx512icl
imul mxd, mxm, 0x010101
- add mxd, t0d ; 8tap_h, mx, 4tap_h
+ add mxd, t0d ; 6tap_h, mx, 4tap_h
imul myd, mym, 0x010101
- add myd, t1d ; 8tap_v, my, 4tap_v
+ add myd, t1d ; 6tap_v, my, 4tap_v
lea r8, [put_avx512icl]
movsxd wq, wm
movifnidn hd, hm
@@ -1514,6 +1492,7 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
jnz .h
test myd, 0xf00
jnz .v
+.put:
tzcnt wd, wd
movzx wd, word [r8+wq*2+table_offset(put,)]
add wq, r8
@@ -1523,158 +1502,577 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
pop r8
%endif
jmp wq
-.h:
- test myd, 0xf00
- jnz .hv
- vpbroadcastd m5, [pd_34] ; 2 + (8 << 2)
- WIN64_SPILL_XMM 11
- cmp wd, 4
- jl .h_w2
- vbroadcasti128 m6, [subpel_h_shufA]
- je .h_w4
- tzcnt wd, wd
- vbroadcasti128 m7, [subpel_h_shufB]
- vbroadcasti128 m8, [subpel_h_shufC]
- shr mxd, 16
- sub srcq, 3
- movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)]
- vpbroadcastd m9, [base+mxq*8+subpel_filters+0]
- vpbroadcastd m10, [base+mxq*8+subpel_filters+4]
- add wq, r8
- jmp wq
-.h_w2:
- movzx mxd, mxb
- dec srcq
- mova xmm4, [subpel_h_shuf4]
- vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2]
-.h_w2_loop:
- movq xmm0, [srcq+ssq*0]
- movhps xmm0, [srcq+ssq*1]
+.v:
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ tzcnt r6d, wd
+ movzx r6d, word [r8+r6*2+table_offset(put, _6tap_v)]
+ vpbroadcastd m6, [pw_512]
+ lea myq, [base+subpel_filters+1+myq*8]
+ vpbroadcastw m7, [myq+0]
+ add r6, r8
+ vpbroadcastw m8, [myq+2]
+ mov nsq, ssq
+ vpbroadcastw m9, [myq+4]
+ neg nsq
+ jmp r6
+.v_w2:
+ movd xmm2, [srcq+nsq*2]
+ pinsrw xmm2, [srcq+nsq*1], 2
+ pinsrw xmm2, [srcq+ssq*0], 4
+ pinsrw xmm2, [srcq+ssq*1], 6 ; 0 1 2 3
lea srcq, [srcq+ssq*2]
- pshufb xmm0, xmm4
- mova xmm1, xm5
- vpdpbusd xmm1, xmm0, xmm3
- packssdw xmm0, xmm1, xmm1
- psraw xmm0, 6
- packuswb xmm0, xm0
- pextrw [dstq+dsq*0], xmm0, 0
- pextrw [dstq+dsq*1], xmm0, 1
+ vpbroadcastd xmm0, [srcq+ssq*0]
+ palignr xmm3, xmm0, xmm2, 4 ; 1 2 3 4
+ punpcklbw xmm1, xmm2, xmm3 ; 01 12
+ punpckhbw xmm2, xmm3 ; 23 34
+.v_w2_loop:
+ vpbroadcastd xmm4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw xmm3, xmm1, xm7 ; a0 b0
+ mova xmm1, xmm2
+ pmaddubsw xmm2, xm8 ; a1 b1
+ paddw xmm3, xmm2
+ vpblendd xmm2, xmm0, xmm4, 0x02 ; 4 5
+ vpbroadcastd xmm0, [srcq+ssq*0]
+ vpblendd xmm4, xmm0, 0x02 ; 5 6
+ punpcklbw xmm2, xmm4 ; 67 78
+ pmaddubsw xmm4, xmm2, xm9 ; a3 b3
+ paddw xmm3, xmm4
+ pmulhrsw xmm3, xm6
+ packuswb xmm3, xmm3
+ pextrw [dstq+dsq*0], xmm3, 0
+ pextrw [dstq+dsq*1], xmm3, 2
lea dstq, [dstq+dsq*2]
sub hd, 2
- jg .h_w2_loop
+ jg .v_w2_loop
RET
-.h_w4:
- movzx mxd, mxb
- dec srcq
- vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2]
-.h_w4_loop:
- movq xmm0, [srcq+ssq*0]
- movq xmm1, [srcq+ssq*1]
+.v_w4:
+ movd xmm2, [srcq+nsq*2]
+ pinsrd xmm2, [srcq+nsq*1], 1
+ pinsrd xmm2, [srcq+ssq*0], 2
+ pinsrd xmm2, [srcq+ssq*1], 3 ; 0 1 2 3
lea srcq, [srcq+ssq*2]
- pshufb xmm0, xm6
- pshufb xmm1, xm6
- mova xmm2, xm5
- vpdpbusd xmm2, xmm0, xmm3
- mova xmm0, xm5
- vpdpbusd xmm0, xmm1, xmm3
- packssdw xmm0, xmm2, xmm0
- psraw xmm0, 6
- packuswb xmm0, xmm0
- movd [dstq+dsq*0], xmm0
- pextrd [dstq+dsq*1], xmm0, 1
+ vpbroadcastd xmm0, [srcq+ssq*0]
+ palignr xmm3, xmm0, xmm2, 4 ; 1 2 3 4
+ punpcklbw xmm1, xmm2, xmm3 ; 01 12
+ punpckhbw xmm2, xmm3 ; 23 34
+.v_w4_loop:
+ vpbroadcastd xmm4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw xmm3, xmm1, xm7 ; a0 b0
+ mova xmm1, xmm2
+ pmaddubsw xmm2, xm8 ; a1 b1
+ paddw xmm3, xmm2
+ vpblendd xmm2, xmm0, xmm4, 0x02 ; 4 5
+ vpbroadcastd xmm0, [srcq+ssq*0]
+ vpblendd xmm4, xmm0, 0x02 ; 5 6
+ punpcklbw xmm2, xmm4 ; 45 56
+ pmaddubsw xmm4, xmm2, xm9 ; a2 b2
+ paddw xmm3, xmm4
+ pmulhrsw xmm3, xm6
+ packuswb xmm3, xmm3
+ movd [dstq+dsq*0], xmm3
+ pextrd [dstq+dsq*1], xmm3, 1
lea dstq, [dstq+dsq*2]
sub hd, 2
- jg .h_w4_loop
+ jg .v_w4_loop
RET
-.h_w8:
- movu xm0, [srcq+ssq*0]
- vinserti32x4 ym0, [srcq+ssq*1], 1
+.v_w8:
+ movq xmm1, [srcq+nsq*2]
+ vpbroadcastq ymm3, [srcq+nsq*1]
+ vpbroadcastq ymm2, [srcq+ssq*0]
+ vpbroadcastq ymm4, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- WRAP_YMM PUT_8TAP_H 0, 1, 2, 3
- vpmovuswb xm0, ym0
- movq [dstq+dsq*0], xm0
- movhps [dstq+dsq*1], xm0
+ vpbroadcastq ymm0, [srcq+ssq*0]
+ vpblendd ymm1, ymm3, 0x30
+ vpblendd ymm3, ymm2, 0x30
+ punpcklbw ymm1, ymm3 ; 01 12
+ vpblendd ymm2, ymm4, 0x30
+ vpblendd ymm4, ymm0, 0x30
+ punpcklbw ymm2, ymm4 ; 23 34
+.v_w8_loop:
+ vpbroadcastq ymm4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw ymm3, ymm1, ym7 ; a0 b0
+ mova ymm1, ymm2
+ pmaddubsw ymm2, ym8 ; a1 b1
+ paddw ymm3, ymm2
+ vpblendd ymm2, ymm0, ymm4, 0x30
+ vpbroadcastq ymm0, [srcq+ssq*0]
+ vpblendd ymm4, ymm0, 0x30
+ punpcklbw ymm2, ymm4 ; 45 56
+ pmaddubsw ymm4, ymm2, ym9 ; a2 b2
+ paddw ymm3, ymm4
+ pmulhrsw ymm3, ym6
+ vextracti128 xmm4, ymm3, 1
+ packuswb xmm3, xmm4
+ movq [dstq+dsq*0], xmm3
+ movhps [dstq+dsq*1], xmm3
lea dstq, [dstq+dsq*2]
sub hd, 2
- jg .h_w8
+ jg .v_w8_loop
+ vzeroupper
RET
-.h_w16:
- mova m6, [spel_h_perm16a]
- mova m7, [spel_h_perm16b]
- mova m8, [spel_h_perm16c]
-.h_w16_loop:
- movu ym0, [srcq+ssq*0]
+.v_w16:
+ mova m5, [spel_v_perm16a]
+ vbroadcasti32x4 m1, [srcq+nsq*2]
+ vbroadcasti32x4 ym3, [srcq+nsq*1]
+ mov r6d, 0x0f
+ vbroadcasti32x4 m2, [srcq+ssq*0]
+ kmovb k1, r6d
+ vbroadcasti32x4 ym4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vbroadcasti32x4 m0, [srcq+ssq*0]
+ vshufpd m1{k1}, m3, m2, 0xcc
+ vshufpd m2{k1}, m4, m0, 0xcc
+ vpermb m1, m5, m1 ; 01 12
+ vpermb m2, m5, m2 ; 23 34
+.v_w16_loop:
+ vbroadcasti32x4 ym4, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw m3, m1, m7 ; a0 b0
+ mova m1, m2
+ pmaddubsw m2, m8 ; a1 b1
+ paddw m3, m2
+ mova m2, m0
+ vbroadcasti32x4 m0, [srcq+ssq*0]
+ vshufpd m2{k1}, m4, m0, 0xcc
+ vpermb m2, m5, m2 ; 45 56
+ pmaddubsw m4, m2, m9 ; a2 b2
+ paddw m3, m4
+ pmulhrsw m3, m6
+ vextracti32x8 ym4, m3, 1
+ packuswb ym3, ym4
+ mova [dstq+dsq*0], xm3
+ vextracti32x4 [dstq+dsq*1], ym3, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .v_w16_loop
+ RET
+.v_w32:
+ mova m10, [spel_v_perm32]
+ pmovzxbq m5, [pb_02461357]
+ vpshrdw m11, m10, m10, 8
+ movu ym0, [srcq+nsq*2]
+ vinserti32x8 m0, [srcq+nsq*1], 1
+ vpermb m1, m10, m0 ; 01
+ vinserti32x8 m0, [srcq+ssq*0], 0
+ vpermb m2, m11, m0 ; 12
vinserti32x8 m0, [srcq+ssq*1], 1
lea srcq, [srcq+ssq*2]
- PUT_8TAP_H 0, 1, 2, 3, 1
- vpmovuswb ym0, m0
- mova [dstq+dsq*0], xm0
- vextracti128 [dstq+dsq*1], ym0, 1
+ vpermb m3, m10, m0 ; 23
+ vinserti32x8 m0, [srcq+ssq*0], 0
+ vpermb m4, m11, m0 ; 34
+.v_w32_loop:
+ vinserti32x8 m0, [srcq+ssq*1], 1
+ lea srcq, [srcq+ssq*2]
+ pmaddubsw m12, m1, m7
+ mova m1, m3
+ pmaddubsw m13, m2, m7
+ mova m2, m4
+ pmaddubsw m14, m3, m8
+ vpermb m3, m10, m0 ; 45
+ vinserti32x8 m0, [srcq+ssq*0], 0
+ pmaddubsw m15, m4, m8
+ vpermb m4, m11, m0 ; 56
+ paddw m12, m14
+ pmaddubsw m14, m3, m9
+ paddw m13, m15
+ pmaddubsw m15, m4, m9
+ paddw m12, m14
+ paddw m13, m15
+ pmulhrsw m12, m6
+ pmulhrsw m13, m6
+ packuswb m12, m13
+ vpermq m12, m5, m12
+ mova [dstq+dsq*0], ym12
+ vextracti32x8 [dstq+dsq*1], m12, 1
lea dstq, [dstq+dsq*2]
sub hd, 2
- jg .h_w16_loop
+ jg .v_w32_loop
RET
-.h_w32:
- movu ym0, [srcq+ssq*0+8*0]
- vinserti32x8 m0, [srcq+ssq*1+8*0], 1
- movu ym1, [srcq+ssq*0+8*1]
- vinserti32x8 m1, [srcq+ssq*1+8*1], 1
+.v_w64:
+.v_w128:
+ lea r6d, [hq+wq*4-256]
+.v_loop0:
+ movu m2, [srcq+nsq*2]
+ movu m4, [srcq+nsq*1]
+ lea r4, [srcq+ssq*2]
+ movu m11, [srcq+ssq*0]
+ movu m13, [srcq+ssq*1]
+ mov r7, dstq
+ movu m0, [r4 +ssq*0]
+ punpcklbw m1, m2, m4 ; 01l
+ punpckhbw m2, m4 ; 01h
+ punpcklbw m3, m4, m11 ; 12l
+ punpckhbw m4, m11 ; 12h
+ punpcklbw m10, m11, m13 ; 23l
+ punpckhbw m11, m13 ; 23h
+ punpcklbw m12, m13, m0 ; 34l
+ punpckhbw m13, m0 ; 34h
+.v_loop:
+ movu m5, [r4+ssq*1]
+ pmaddubsw m14, m1, m7 ; a0l
+ mova m1, m10
+ pmaddubsw m10, m8 ; a1l
+ lea r4, [r4+ssq*2]
+ pmaddubsw m15, m2, m7 ; a0h
+ mova m2, m11
+ pmaddubsw m11, m8 ; a1h
+ paddw m14, m10
+ punpcklbw m10, m0, m5 ; 45l
+ paddw m15, m11
+ punpckhbw m11, m0, m5 ; 45h
+ pmaddubsw m0, m10, m9 ; a2l
+ paddw m14, m0
+ pmaddubsw m0, m11, m9 ; a2h
+ paddw m15, m0
+ movu m0, [r4+ssq*0]
+ pmulhrsw m14, m6
+ pmulhrsw m15, m6
+ packuswb m14, m15
+ pmaddubsw m15, m3, m7 ; b0l
+ mova m3, m12
+ pmaddubsw m12, m8 ; b1l
+ mova [r7+dsq*0], m14
+ pmaddubsw m14, m4, m7 ; b0h
+ mova m4, m13
+ pmaddubsw m13, m8 ; b1h
+ paddw m15, m12
+ punpcklbw m12, m5, m0 ; 56l
+ paddw m14, m13
+ punpckhbw m13, m5, m0 ; 56h
+ pmaddubsw m5, m12, m9 ; b2l
+ paddw m15, m5
+ pmaddubsw m5, m13, m9 ; b2h
+ paddw m14, m5
+ pmulhrsw m15, m6
+ pmulhrsw m14, m6
+ packuswb m15, m14
+ mova [r7+dsq*1], m15
+ lea r7, [r7+dsq*2]
+ sub hd, 2
+ jg .v_loop
+ add srcq, 64
+ add dstq, 64
+ movzx hd, r6b
+ sub r6d, 256
+ jg .v_loop0
+ RET
+.h:
+ test myd, 0xf00
+ jz mangle(private_prefix %+ _put_8tap_8bpc_avx512icl).h2
+.hv:
+ vpbroadcastd m9, [pd_34]
+ mova xm10, [spel_hv_end]
+ pxor xm0, xm0
+ cmp wd, 4
+ jg .hv_w8
+ movzx mxd, mxb
+ dec srcq
+ vpbroadcastd m7, [base+subpel_filters+mxq*8+2]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ vpbroadcastq ym1, [base+subpel_filters+1+myq*8]
+ mov nsq, ssq
+ punpcklbw ym0, ym1
+ neg nsq
+ psraw ym0, 2 ; << 6
+ pshufd ym11, ym0, q0000
+ pshufd ym12, ym0, q1111
+ pshufd ym13, ym0, q2222
+ cmp wd, 4
+ je .hv_w4
+ vbroadcasti128 ym5, [subpel_h_shuf4]
+ movq xmm0, [srcq+nsq*2]
+ movhps xmm0, [srcq+nsq*1]
+ movq xmm2, [srcq+ssq*0]
+ movhps xmm2, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
- PUT_8TAP_H 0, 2, 3, 4
- PUT_8TAP_H 1, 4, 3, 2
- packuswb m0, m1
- mova [dstq+dsq*0], ym0
- vextracti32x8 [dstq+dsq*1], m0, 1
+ vpbroadcastq ymm1, [srcq+ssq*0]
+ vpblendd ymm0, ymm1, 0x30
+ pshufb xmm2, xm5 ; 2 3
+ pshufb ymm0, ym5 ; 0 1 4
+ mova xmm1, xm9
+ vpdpbusd xmm1, xmm2, xm7
+ mova ymm2, ym9
+ vpdpbusd ymm2, ymm0, ym7
+ packssdw ymm2, ymm1
+ psraw ymm2, 2
+ vextracti128 xmm0, ymm2, 1
+ vzeroupper
+ palignr xmm0, xmm2, 4
+ punpcklwd xmm1, xmm2, xmm0 ; 01 12
+ punpckhwd xmm2, xmm0 ; 23 34
+.hv_w2_loop:
+ movq xmm3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ movhps xmm3, [srcq+ssq*0]
+ pmaddwd xmm4, xmm1, xm11 ; a0 b0
+ mova xmm1, xmm2
+ vpdpwssd xmm4, xmm2, xm12 ; a1 b1
+ pshufb xmm3, xm5
+ mova xmm2, xm9
+ vpdpbusd xmm2, xmm3, xm7
+ packssdw xmm3, xmm2, xmm2
+ psraw xmm3, 2
+ palignr xmm2, xmm3, xmm0, 12
+ mova xmm0, xmm3
+ punpcklwd xmm2, xmm3 ; 45 56
+ vpdpwssd xmm4, xmm2, xm13 ; a2 b2
+ packuswb xmm4, xmm4
+ pshufb xmm4, xm10
+ pextrw [dstq+dsq*0], xmm4, 0
+ pextrw [dstq+dsq*1], xmm4, 1
lea dstq, [dstq+dsq*2]
sub hd, 2
- jg .h_w32
+ jg .hv_w2_loop
RET
-.h_w64:
- movu m0, [srcq+8*0]
- movu m1, [srcq+8*1]
- add srcq, ssq
- PUT_8TAP_H 0, 2, 3, 4
- PUT_8TAP_H 1, 4, 3, 2
- packuswb m0, m1
- mova [dstq], m0
- add dstq, dsq
- dec hd
- jg .h_w64
+.hv_w4:
+ movq xm2, [srcq+nsq*2]
+ vpbroadcastq ym1, [srcq+nsq*1]
+ vinserti32x4 ym2, [srcq+ssq*0], 1
+ vinserti32x4 m1, [srcq+ssq*1], 2 ; _ 1 3
+ lea srcq, [srcq+ssq*2]
+ vbroadcasti32x4 m5, [subpel_h_shufA]
+ vinserti32x4 m2, [srcq+ssq*0], 2 ; 0 2 4
+ pshufb m1, m5
+ mova m0, m9
+ pshufb m2, m5
+ mova m3, m9
+ vpdpbusd m0, m1, m7
+ mova ym1, [spel_hv_perm4a]
+ vpdpbusd m3, m2, m7
+ mova ym2, [spel_hv_perm4b]
+ mov r6d, 0x5555
+ mova ym6, [spel_hv_perm4d]
+ packssdw m0, m3
+ kmovw k1, r6d
+ psraw m0, 2 ; _ 0 1 2 3 4 5 6
+ vpermb ym1, ym1, ym0 ; 01 12
+ vpermb m2, m2, m0 ; 23 34
+.hv_w4_loop:
+ movq xm3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vinserti32x4 ym3, [srcq+ssq*0], 1
+ pmaddwd ym4, ym1, ym11 ; a0 b0
+ mova ym1, ym2
+ pshufb ym3, ym5
+ mova ym0, ym9
+ vpdpbusd ym0, ym3, ym7
+ vpdpwssd ym4, ym2, ym12 ; a1 b1
+ vpsraw ym2{k1}, ym0, 2 ; 5 6
+ vpermb ym2, ym6, ym2 ; 45 56
+ vpdpwssd ym4, ym2, ym13 ; a2 b2
+ packuswb ym4, ym4
+ vpermb ym4, ym10, ym4
+ movd [dstq+dsq*0], xm4
+ pextrd [dstq+dsq*1], xm4, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .hv_w4_loop
RET
-.h_w128:
- movu m0, [srcq+8*0]
- movu m2, [srcq+8*1]
- movu m1, [srcq+8*8]
- movu m3, [srcq+8*9]
- add srcq, ssq
- PUT_8TAP_H 0, 4, 11, 12
- PUT_8TAP_H 2, 12, 11, 4
- PUT_8TAP_H 1, 4, 11, 12
- PUT_8TAP_H 3, 12, 11, 4
- packuswb m0, m2
- packuswb m1, m3
- mova [dstq+64*0], m0
- mova [dstq+64*1], m1
- add dstq, dsq
- dec hd
- jg .h_w128
+.hv_w8:
+ shr mxd, 16
+ sub srcq, 3
+ vpbroadcastd m11, [base+subpel_filters+mxq*8+0]
+ vpbroadcastd m12, [base+subpel_filters+mxq*8+4]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 6
+ cmovs myd, mxd
+ vpbroadcastq m1, [base+subpel_filters+1+myq*8]
+ mov nsq, ssq
+ punpcklbw m0, m1
+ neg nsq
+ psraw m0, 2 ; << 6
+ pshufd m13, m0, q0000
+ pshufd m14, m0, q1111
+ pshufd m15, m0, q2222
+ cmp wd, 8
+ jne .hv_w16
+ movu xm0, [srcq+nsq*2]
+ vinserti32x4 ym0, [srcq+nsq*1], 1
+ vbroadcasti32x4 m1, [subpel_h_shufA]
+ vinserti32x4 m0, [srcq+ssq*0], 2
+ vbroadcasti32x4 m4, [subpel_h_shufB]
+ vinserti32x4 m0, [srcq+ssq*1], 3
+ lea srcq, [srcq+ssq*2]
+ vbroadcasti32x4 m7, [subpel_h_shufC]
+ vbroadcasti32x4 ym5, [srcq+ssq*0]
+ vbroadcasti32x8 m6, [subpel_h_shufA]
+ pshufb m1, m0, m1 ; 0 1 2 3 0123
+ mova m2, m9
+ vpdpbusd m2, m1, m11
+ pshufb m4, m0, m4 ; 0 1 2 3 4567
+ mova m1, m9
+ vpdpbusd m1, m4, m11
+ pshufb m0, m7 ; 0 1 2 3 89ab
+ pshufb ym7, ym5, ym6 ; 4 0123 4567
+ mova ym3, ym9
+ vpdpbusd ym3, ym7, ym11
+ vbroadcasti32x8 m7, [subpel_h_shufB]
+ vpdpbusd m2, m4, m12
+ mova m4, [spel_hv_perm8a]
+ pshufb ym5, ym7 ; 4 4567 89ab
+ vpdpbusd m1, m0, m12
+ vpaddd m0, m4, [pb_32] {1to16}
+ vpdpbusd ym3, ym5, ym12
+ mova m5, [spel_hv_perm8b]
+ mov r6, 0x55555555ff00
+ packssdw m2, m1
+ vpmovsdw xm3, ym3
+ kmovq k1, r6
+ psraw m2, 2 ; 0 1 2 3
+ psraw xm3, 2 ; 4
+ vpermb m1, m4, m2 ; 01 12
+ kshiftrq k2, k1, 16
+ vpermt2b m2, m0, m3 ; 23 34
+.hv_w8_loop:
+ vbroadcasti32x4 ym3, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ vbroadcasti32x4 m3{k1}, [srcq+ssq*0]
+ pmaddwd m0, m1, m13 ; a0 b0
+ pshufb m1, m3, m6 ; 5 6 0123 4567
+ mova m4, m9
+ vpdpbusd m4, m1, m11
+ pshufb m3, m7 ; 5 6 4567 89ab
+ vpdpwssd m0, m2, m14 ; a1 b1
+ mova m1, m2
+ vpdpbusd m4, m3, m12
+ psraw m2{k2}, m4, 2 ; 53 64
+ vpermb m2, m5, m2 ; 45 56
+ vpdpwssd m0, m2, m15 ; a2 b2
+ packuswb m0, m0
+ vpermb m0, m10, m0
+ movq [dstq+dsq*0], xm0
+ movhps [dstq+dsq*1], xm0
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .hv_w8_loop
+ RET
+.hv_w16:
+ movu m19, [spel_hv_perm16a]
+ vpbroadcastd m7, [pb_4]
+ lea r6d, [wq*2-32]
+ mova m6, [spel_hv_perm16b]
+ paddb m20, m7, m19
+ lea r6d, [hq+r6*8]
+ paddb m21, m7, m20
+ mova ym10, [spel_hv_end16]
+ paddb m7, m6
+.hv_w16_loop0:
+ movu ym16, [srcq+nsq*2]
+ vinserti32x8 m16, [srcq+nsq*1], 1
+ lea r4, [srcq+ssq*2]
+ movu ym17, [srcq+ssq*0]
+ vinserti32x8 m17, [srcq+ssq*1], 1
+ mov r7, dstq
+ movu ym18, [r4 +ssq*0]
+ vpermb m2, m19, m16 ; 0 1 0123 89ab
+ mova m1, m9
+ vpermb m3, m21, m16 ; 0 1 89ab ghij
+ vpdpbusd m1, m2, m11
+ mova m2, m9
+ vpermb m4, m19, m17 ; 2 3 0123 89ab
+ vpdpbusd m2, m3, m12
+ mova m3, m9
+ vpermb m5, m21, m17 ; 2 3 89ab ghij
+ vpdpbusd m3, m4, m11
+ mova m4, m9
+ vpermb m0, m6, m18 ; 4 0145 2367 89cd abef
+ vpdpbusd m4, m5, m12
+ mova m5, m9
+ vpermb m16, m20, m16 ; 0 1 4567 cdef
+ vpdpbusd m5, m0, m11
+ vpermb m17, m20, m17 ; 2 3 4567 cdef
+ vpdpbusd m1, m16, m12
+ vpermb m18, m7, m18 ; 4 4589 67ab cdgh efij
+ vpdpbusd m2, m16, m11
+ vpdpbusd m3, m17, m12
+ vpdpbusd m4, m17, m11
+ vpdpbusd m5, m18, m12
+ packssdw m1, m2 ; 01
+ packssdw m3, m4 ; 23
+ REPX {psraw x, 2}, m1, m3, m5
+ vpshrdd m2, m1, m3, 16 ; 12
+ vpshrdd m4, m3, m5, 16 ; 34
+.hv_w16_loop:
+ movu ym18, [r4+ssq*1]
+ lea r4, [r4+ssq*2]
+ vinserti32x8 m18, [r4+ssq*0], 1
+ pmaddwd m16, m1, m13 ; a0
+ vpermb m1, m19, m18 ; 5 6 0123 89ab
+ pmaddwd m17, m2, m13 ; b0
+ vpermb m2, m20, m18 ; 5 6 4567 cdef
+ mova m0, m9
+ vpdpbusd m0, m1, m11
+ vpermb m18, m21, m18
+ mova m1, m9
+ vpdpbusd m1, m2, m11
+ vpdpwssd m16, m3, m14 ; a1
+ vpdpwssd m17, m4, m14 ; b1
+ vpdpbusd m0, m2, m12
+ mova m2, m4
+ vpdpbusd m1, m18, m12
+ packssdw m0, m1
+ mova m1, m3
+ psraw m4, m0, 2 ; 5 6
+ vpshrdd m3, m2, m4, 16 ; 4 5
+ vpdpwssd m17, m4, m15 ; b2
+ vpdpwssd m16, m3, m15 ; a2
+ packuswb m16, m17
+ vpermb m16, m10, m16
+ mova [r7+dsq*0], xm16
+ vextracti128 [r7+dsq*1], ym16, 1
+ lea r7, [r7+dsq*2]
+ sub hd, 2
+ jg .hv_w16_loop
+ add srcq, 16
+ add dstq, 16
+ movzx hd, r6b
+ sub r6d, 1<<8
+ jg .hv_w16_loop0
+ vzeroupper
RET
+
+PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP, put_8tap_8bpc
+PUT_8TAP_FN regular_sharp, REGULAR, SHARP, put_8tap_8bpc
+PUT_8TAP_FN sharp, SHARP, SHARP
+
+cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
+ imul mxd, mxm, 0x010101
+ add mxd, t0d ; 8tap_h, mx, 4tap_h
+ imul myd, mym, 0x010101
+ add myd, t1d ; 8tap_v, my, 4tap_v
+ lea r8, [put_avx512icl]
+ movsxd wq, wm
+ movifnidn hd, hm
+ test mxd, 0xf00
+ jnz .h
+ test myd, 0xf00
+ jz mangle(private_prefix %+ _put_6tap_8bpc_avx512icl).put
.v:
movzx mxd, myb
shr myd, 16
cmp hd, 6
cmovs myd, mxd
tzcnt r6d, wd
+ lea myq, [base+subpel_filters+myq*8]
movzx r6d, word [r8+r6*2+table_offset(put, _8tap_v)]
vpbroadcastd m7, [pw_512]
- lea myq, [base+subpel_filters+myq*8]
vpbroadcastw m8, [myq+0]
- vpbroadcastw m9, [myq+2]
- vpbroadcastw m10, [myq+4]
- vpbroadcastw m11, [myq+6]
add r6, r8
+ vpbroadcastw m9, [myq+2]
lea ss3q, [ssq*3]
+ vpbroadcastw m10, [myq+4]
sub srcq, ss3q
+ vpbroadcastw m11, [myq+6]
jmp r6
.v_w2:
movd xmm2, [srcq+ssq*0]
@@ -1802,7 +2200,7 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vzeroupper
RET
.v_w16:
- mova m12, [spel_v_perm16]
+ mova m12, [spel_v_perm16a]
vbroadcasti32x4 m1, [srcq+ssq*0]
vbroadcasti32x4 ym4, [srcq+ssq*1]
mov r6d, 0x0f
@@ -1990,7 +2388,146 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
jg .v_loop0
vzeroupper
RET
+.h:
+ test myd, 0xf00
+ jnz .hv
+.h2:
+ vpbroadcastd m5, [pd_34] ; 2 + (8 << 2)
+ cmp wd, 4
+ jl .h_w2
+ vbroadcasti128 m6, [subpel_h_shufA]
+ je .h_w4
+ tzcnt wd, wd
+ vbroadcasti128 m7, [subpel_h_shufB]
+ vbroadcasti128 m8, [subpel_h_shufC]
+ shr mxd, 16
+ sub srcq, 3
+ movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)]
+ vpbroadcastd m9, [base+mxq*8+subpel_filters+0]
+ vpbroadcastd m10, [base+mxq*8+subpel_filters+4]
+ add wq, r8
+ jmp wq
+.h_w2:
+ movzx mxd, mxb
+ dec srcq
+ mova xmm4, [subpel_h_shuf4]
+ vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2]
+.h_w2_loop:
+ movq xmm0, [srcq+ssq*0]
+ movhps xmm0, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pshufb xmm0, xmm4
+ mova xmm1, xm5
+ vpdpbusd xmm1, xmm0, xmm3
+ packssdw xmm0, xmm1, xmm1
+ psraw xmm0, 6
+ packuswb xmm0, xm0
+ pextrw [dstq+dsq*0], xmm0, 0
+ pextrw [dstq+dsq*1], xmm0, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w2_loop
+ RET
+.h_w4:
+ movzx mxd, mxb
+ dec srcq
+ vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2]
+.h_w4_loop:
+ movq xmm0, [srcq+ssq*0]
+ movq xmm1, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ pshufb xmm0, xm6
+ pshufb xmm1, xm6
+ mova xmm2, xm5
+ vpdpbusd xmm2, xmm0, xmm3
+ mova xmm0, xm5
+ vpdpbusd xmm0, xmm1, xmm3
+ packssdw xmm0, xmm2, xmm0
+ psraw xmm0, 6
+ packuswb xmm0, xmm0
+ movd [dstq+dsq*0], xmm0
+ pextrd [dstq+dsq*1], xmm0, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w4_loop
+ RET
+.h_w8:
+ movu xm0, [srcq+ssq*0]
+ vinserti32x4 ym0, [srcq+ssq*1], 1
+ lea srcq, [srcq+ssq*2]
+ WRAP_YMM PUT_8TAP_H 0, 1, 2, 3
+ vpmovuswb xm0, ym0
+ movq [dstq+dsq*0], xm0
+ movhps [dstq+dsq*1], xm0
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w8
+ RET
+.h_w16:
+ mova m6, [spel_h_perm16]
+ vpbroadcastd m8, [pb_4]
+ paddb m7, m8, m6
+ paddb m8, m7
+.h_w16_loop:
+ movu ym0, [srcq+ssq*0]
+ vinserti32x8 m0, [srcq+ssq*1], 1
+ lea srcq, [srcq+ssq*2]
+ PUT_8TAP_H 0, 1, 2, 3, 1
+ vpmovuswb ym0, m0
+ mova [dstq+dsq*0], xm0
+ vextracti128 [dstq+dsq*1], ym0, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w16_loop
+ RET
+.h_w32:
+ movu ym0, [srcq+ssq*0+8*0]
+ vinserti32x8 m0, [srcq+ssq*1+8*0], 1
+ movu ym1, [srcq+ssq*0+8*1]
+ vinserti32x8 m1, [srcq+ssq*1+8*1], 1
+ lea srcq, [srcq+ssq*2]
+ PUT_8TAP_H 0, 2, 3, 4
+ PUT_8TAP_H 1, 4, 3, 2
+ packuswb m0, m1
+ mova [dstq+dsq*0], ym0
+ vextracti32x8 [dstq+dsq*1], m0, 1
+ lea dstq, [dstq+dsq*2]
+ sub hd, 2
+ jg .h_w32
+ RET
+.h_w64:
+ movu m0, [srcq+8*0]
+ movu m1, [srcq+8*1]
+ add srcq, ssq
+ PUT_8TAP_H 0, 2, 3, 4
+ PUT_8TAP_H 1, 4, 3, 2
+ packuswb m0, m1
+ mova [dstq], m0
+ add dstq, dsq
+ dec hd
+ jg .h_w64
+ RET
+.h_w128:
+ movu m0, [srcq+8*0]
+ movu m2, [srcq+8*1]
+ movu m1, [srcq+8*8]
+ movu m3, [srcq+8*9]
+ add srcq, ssq
+ PUT_8TAP_H 0, 4, 11, 12
+ PUT_8TAP_H 2, 12, 11, 4
+ PUT_8TAP_H 1, 4, 11, 12
+ PUT_8TAP_H 3, 12, 11, 4
+ packuswb m0, m2
+ packuswb m1, m3
+ mova [dstq+64*0], m0
+ mova [dstq+64*1], m1
+ add dstq, dsq
+ dec hd
+ jg .h_w128
+ RET
.hv:
+ vpbroadcastd m9, [pd_34]
+ pxor xm0, xm0
cmp wd, 4
jg .hv_w8
movzx mxd, mxb
@@ -2000,12 +2537,10 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
shr myd, 16
cmp hd, 6
cmovs myd, mxd
- vpbroadcastd m8, [pd_2]
- vpbroadcastq ym0, [base+subpel_filters+myq*8]
+ vpbroadcastq ym1, [base+subpel_filters+myq*8]
lea ss3q, [ssq*3]
- vpbroadcastd ym9, [pd_32768]
mov r6, srcq
- punpcklbw ym0, ym8, ym0
+ punpcklbw ym0, ym1
sub r6, ss3q
psraw ym0, 2 ; << 6
mova xm14, [spel_hv_end]
@@ -2029,9 +2564,9 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vpblendd ymm2, ymm4, 0xc0 ; 0 1 4 5
pshufb ymm2, ym6
pshufb ymm0, ym6
- mova ymm1, ym8
+ mova ymm1, ym9
vpdpbusd ymm1, ymm2, ym7
- mova ymm2, ym8
+ mova ymm2, ym9
vpdpbusd ymm2, ymm0, ym7
packssdw ymm2, ymm1, ymm2
psraw ymm2, 2
@@ -2045,14 +2580,13 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
movq xmm4, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
movhps xmm4, [srcq+ssq*0]
- mova xmm5, xm9
- vpdpwssd xmm5, xmm1, xm10 ; a0 b0
+ pmaddwd xmm5, xmm1, xm10 ; a0 b0
mova xmm1, xmm2
vpdpwssd xmm5, xmm2, xm11 ; a1 b1
pshufb xmm4, xm6
mova xmm2, xmm3
vpdpwssd xmm5, xmm3, xm12 ; a2 b2
- mova xmm3, xm8
+ mova xmm3, xm9
vpdpbusd xmm3, xmm4, xm7
packssdw xmm4, xmm3, xmm3
psraw xmm4, 2
@@ -2081,9 +2615,9 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vinserti32x4 m1, [srcq+ssq*0], 3 ; 0 2 4 6
pshufb m2, m6
pshufb m1, m6
- mova m0, m8
+ mova m0, m9
vpdpbusd m0, m2, m7
- mova m4, m8
+ mova m4, m9
vpdpbusd m4, m1, m7
mova ym1, [spel_hv_perm4a]
mova ym2, [spel_hv_perm4b]
@@ -2100,11 +2634,10 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
movq xmm4, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
vinserti32x4 ym4, ymm4, [srcq+ssq*0], 1
- mova ym5, ym9
- vpdpwssd ym5, ym1, ym10 ; a0 b0
+ pmaddwd ym5, ym1, ym10 ; a0 b0
mova ym1, ym2
pshufb ym4, ym6
- mova ym0, ym8
+ mova ym0, ym9
vpdpbusd ym0, ym4, ym7
vpdpwssd ym5, ym2, ym11 ; a1 b1
mova ym2, ym3
@@ -2129,10 +2662,8 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
shr myd, 16
cmp hd, 6
cmovs myd, mxd
- vpbroadcastd m8, [pd_2]
- vpbroadcastq m0, [base+subpel_filters+myq*8]
- vpbroadcastd m9, [pd_32768]
- punpcklbw m0, m8, m0
+ vpbroadcastq m1, [base+subpel_filters+myq*8]
+ punpcklbw m0, m1
lea ss3q, [ssq*3]
psraw m0, 2 ; << 6
pshufd m12, m0, q0000
@@ -2153,31 +2684,31 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vbroadcasti32x4 m4, [subpel_h_shufA]
vinserti32x4 m0, zmm2, [srcq+ssq*0], 2 ; 4 5 6 _
vbroadcasti32x4 m7, [subpel_h_shufB]
- vbroadcasti32x4 m17, [subpel_h_shufC]
+ vbroadcasti32x4 m8, [subpel_h_shufC]
pshufb m1, m6, m4 ; 0 1 2 3 0123
- mova m2, m8
+ mova m2, m9
vpdpbusd m2, m1, m10
pshufb m5, m6, m7 ; 0 1 2 3 4567
- mova m1, m8
+ mova m1, m9
vpdpbusd m1, m5, m10
pshufb m4, m0, m4 ; 4 5 6 _ 0123
- mova m3, m8
+ mova m3, m9
vpdpbusd m3, m4, m10
pshufb m7, m0, m7 ; 4 5 6 _ 4567
- mova m4, m8
+ mova m4, m9
vpdpbusd m4, m7, m10
- pshufb m6, m17
+ pshufb m6, m8
vpdpbusd m2, m5, m11
vpdpbusd m1, m6, m11
- pshufb m6, m0, m17
+ pshufb m6, m0, m8
vpdpbusd m3, m7, m11
vpdpbusd m4, m6, m11
mova m5, [spel_hv_perm8a]
- mova m0, [spel_hv_perm8b]
+ vpaddd m0, m5, [pb_32] {1to16}
mov r6, 0x55555555ff00
packssdw m2, m1
packssdw m3, m4
- mova m18, [spel_hv_perm8c]
+ mova m8, [spel_hv_perm8b]
psraw m2, 2 ; 0 1 2 3
psraw m3, 2 ; 4 5 6 _
vpermb m1, m5, m2 ; 01 12
@@ -2192,10 +2723,9 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vbroadcasti32x4 ym4, [srcq+ssq*1]
lea srcq, [srcq+ssq*2]
vbroadcasti32x4 m4{k1}, [srcq+ssq*0]
- mova m0, m9
- vpdpwssd m0, m1, m12 ; a0 b0
+ pmaddwd m0, m1, m12 ; a0 b0
pshufb m1, m4, m6 ; 7 8 0123 4567
- mova m5, m8
+ mova m5, m9
vpdpbusd m5, m1, m10
pshufb m4, m7 ; 7 8 4567 89ab
vpdpwssd m0, m2, m13 ; a1 b1
@@ -2204,7 +2734,7 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
mova m2, m3
vpdpwssd m0, m3, m14 ; a2 b2
psraw m3{k2}, m5, 2 ; 75 86
- vpermb m3, m18, m3 ; 67 78
+ vpermb m3, m8, m3 ; 67 78
vpdpwssd m0, m3, m15 ; a3 b3
packuswb m0, m0
vpermb zmm1, m16, m0
@@ -2216,111 +2746,652 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
vzeroupper
RET
.hv_w16:
- movu m7, [spel_hv_perm16a]
+ WIN64_SPILL_XMM 23
+ movu m22, [spel_hv_perm16a]
sub srcq, ss3q
- mova m20, [spel_hv_perm16b]
+ vpbroadcastd m8, [pb_4]
lea r6d, [wq*2-32]
- mova m21, [spel_hv_perm16c]
- mov r4, srcq
- mov r7, dstq
+ mova m7, [spel_hv_perm16b]
+ paddb m20, m8, m22
mova ym16, [spel_hv_end16]
+ paddb m21, m8, m20
lea r6d, [hq+r6*8]
+ paddb m8, m7
.hv_w16_loop0:
movu ym17, [srcq+ssq*0]
vinserti32x8 m17, [srcq+ssq*1], 1 ; 0 1
+ lea r4, [srcq+ss3q]
movu ym18, [srcq+ssq*2]
- add srcq, ss3q
- vinserti32x8 m18, [srcq+ssq*0], 1 ; 2 3
- movu ym19, [srcq+ssq*1]
- vinserti32x8 m19, [srcq+ssq*2], 1 ; 4 5
- add srcq, ss3q
- vpermb m2, m7, m17 ; 0 1 0123 89ab
- vpermb m0, m20, m17 ; 0 1 4567 cdef
- vpermb m4, m7, m18 ; 2 3 0123 89ab
- mova m1, m8
+ vinserti32x8 m18, [r4 +ssq*0], 1 ; 2 3
+ mov r7, dstq
+ movu ym19, [r4 +ssq*1]
+ vinserti32x8 m19, [r4 +ssq*2], 1 ; 4 5
+ add r4, ss3q
+ vpermb m2, m22, m17 ; 0 1 0123 89ab
+ mova m1, m9
+ vpermb m3, m21, m17 ; 0 1 89ab ghij
vpdpbusd m1, m2, m10
- vpermb m5, m20, m18 ; 2 3 4567 cdef
- mova m2, m8
- vpdpbusd m2, m0, m10
- vpermb m17, m21, m17 ; 0 1 89ab ghij
- mova m3, m8
+ mova m2, m9
+ vpermb m4, m22, m18 ; 2 3 0123 89ab
+ vpdpbusd m2, m3, m11
+ mova m3, m9
+ vpermb m5, m21, m18 ; 2 3 89ab ghij
vpdpbusd m3, m4, m10
- vpermb m6, m7, m19 ; 4 5 0123 89ab
- mova m4, m8
- vpdpbusd m4, m5, m10
- vpermb m18, m21, m18 ; 2 3 89ab ghij
- vpdpbusd m1, m0, m11
- movu ym0, [srcq+ssq*0] ; 6
- vpdpbusd m2, m17, m11
- vpermb m17, m20, m19 ; 4 5 4567 cdef
- vpdpbusd m3, m5, m11
- mova m5, m8
+ mova m4, m9
+ vpermb m6, m22, m19 ; 4 5 0123 89ab
+ vpdpbusd m4, m5, m11
+ mova m5, m9
+ vpermb m17, m20, m17 ; 0 1 4567 cdef
vpdpbusd m5, m6, m10
- mova m6, m8
- vpdpbusd m6, m17, m10
- vpdpbusd m4, m18, m11
- mova m18, [spel_hv_perm16d]
- vpermb m18, m18, m0 ; 6 0145 2367 89cd abef
- vpdpbusd m5, m17, m11
- vpermb m19, m21, m19 ; 4 5 89ab ghij
- mova m17, m8
- vpdpbusd m17, m18, m10
- mova m18, [spel_hv_perm16e]
- vpermb m0, m18, m0 ; 6 4589 67ab cdgh efij
- packssdw m1, m2 ; 01
- vpdpbusd m6, m19, m11
- packssdw m3, m4 ; 23
- vpdpbusd m17, m0, m11
- psraw m1, 2
- packssdw m5, m6 ; 45
- psraw m3, 2
+ mova m6, m9
+ vpermb m0, m21, m19 ; 4 5 89ab ghij
+ vpdpbusd m1, m17, m11
+ vpdpbusd m2, m17, m10
+ movu ym17, [r4+ssq*0] ; 6
+ vpermb m18, m20, m18 ; 2 3 4567 cdef
+ vpdpbusd m6, m0, m11
+ vpermb m0, m7, m17 ; 6 0145 2367 89cd abef
+ vpdpbusd m3, m18, m11
+ vpermb m19, m20, m19 ; 4 5 4567 cdef
+ vpdpbusd m4, m18, m10
+ mova m18, m9
+ vpermb m17, m8, m17 ; 6 4589 67ab cdgh efij
+ vpdpbusd m18, m0, m10
+ packssdw m1, m2
+ vpdpbusd m5, m19, m11
+ vpdpbusd m6, m19, m10
+ packssdw m3, m4
+ vpdpbusd m18, m17, m11
+ psraw m1, 2 ; 01
+ psraw m3, 2 ; 23
+ packssdw m5, m6
vpshrdd m2, m1, m3, 16 ; 12
- psraw m5, 2
+ psraw m5, 2 ; 45
vpshrdd m4, m3, m5, 16 ; 34
- psraw m17, 2
- vpshrdd m6, m5, m17, 16 ; 56
+ psraw m18, 2
+ vpshrdd m6, m5, m18, 16 ; 56
.hv_w16_loop:
- movu ym18, [srcq+ssq*1]
- lea srcq, [srcq+ssq*2]
- vinserti32x8 m18, [srcq+ssq*0], 1
+ movu ym19, [r4+ssq*1]
+ lea r4, [r4+ssq*2]
+ vinserti32x8 m19, [r4+ssq*0], 1
+ pmaddwd m17, m1, m12 ; a0
+ vpermb m1, m22, m19 ; 7 8 0123 89ab
+ pmaddwd m18, m2, m12 ; b0
mova m0, m9
- vpdpwssd m0, m1, m12 ; a0
- vpermb m1, m7, m18 ; 7 8 0123 89ab
- mova m17, m9
- vpdpwssd m17, m2, m12 ; b0
- vpermb m2, m20, m18 ; 7 8 4567 cdef
- mova m19, m8
- vpdpbusd m19, m1, m10
- vpermb m18, m21, m18
- mova m1, m8
- vpdpbusd m1, m2, m10
- vpdpwssd m0, m3, m13 ; a1
- vpdpwssd m17, m4, m13 ; b1
- vpdpbusd m19, m2, m11
+ vpermb m2, m21, m19 ; 7 8 89ab ghij
+ vpdpbusd m0, m1, m10
+ mova m1, m9
+ vpermb m19, m20, m19 ; 7 8 4567 cdef
+ vpdpbusd m1, m2, m11
mova m2, m4
- vpdpbusd m1, m18, m11
+ vpdpwssd m17, m3, m13 ; a1
+ vpdpwssd m18, m4, m13 ; b1
mova m4, m6
- vpdpwssd m0, m5, m14 ; a2
- vpdpwssd m17, m6, m14 ; b2
- packssdw m19, m1
+ vpdpbusd m0, m19, m11
+ vpdpbusd m1, m19, m10
+ vpdpwssd m17, m5, m14 ; a2
+ vpdpwssd m18, m6, m14 ; b2
+ packssdw m0, m1
mova m1, m3
+ psraw m6, m0, 2 ; 78
mova m3, m5
- psraw m6, m19, 2 ; 7 8
- vpshrdd m5, m4, m6, 16 ; 6 7
- vpdpwssd m17, m6, m15 ; b3
- vpdpwssd m0, m5, m15 ; a3
- packuswb m0, m17
- vpermb zmm1, m16, m0
- mova [dstq+dsq*0], xmm1
- vextracti128 [dstq+dsq*1], ymm1, 1
- lea dstq, [dstq+dsq*2]
+ vpshrdd m5, m4, m6, 16 ; 67
+ vpdpwssd m18, m6, m15 ; b3
+ vpdpwssd m17, m5, m15 ; a3
+ packuswb m17, m18
+ vpermb m17, m16, m17
+ mova [r7+dsq*0], xm17
+ vextracti128 [r7+dsq*1], ym17, 1
+ lea r7, [r7+dsq*2]
sub hd, 2
jg .hv_w16_loop
- add r4, 16
- add r7, 16
+ add srcq, 16
+ add dstq, 16
+ movzx hd, r6b
+ sub r6d, 1<<8
+ jg .hv_w16_loop0
+ RET
+
+%if WIN64
+DECLARE_REG_TMP 6, 4
+%else
+DECLARE_REG_TMP 6, 7
+%endif
+
+%define PREP_8TAP_FN FN prep_8tap,
+PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH, prep_6tap_8bpc
+PREP_8TAP_FN sharp_regular, SHARP, REGULAR, prep_6tap_8bpc
+PREP_8TAP_FN smooth, SMOOTH, SMOOTH, prep_6tap_8bpc
+PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR, prep_6tap_8bpc
+PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH, prep_6tap_8bpc
+PREP_8TAP_FN regular, REGULAR, REGULAR
+
+cglobal prep_6tap_8bpc, 4, 8, 0, tmp, src, ss, w, h, mx, my, ss3
+%define base r7-prep_avx512icl
+ imul mxd, mxm, 0x010101
+ add mxd, t0d ; 6tap_h, mx, 4tap_h
+ imul myd, mym, 0x010101
+ add myd, t1d ; 6tap_v, my, 4tap_v
+ lea r7, [prep_avx512icl]
+ movifnidn hd, hm
+ test mxd, 0xf00
+ jnz .h
+ test myd, 0xf00
+ jnz .v
+.prep:
+ tzcnt wd, wd
+ movzx wd, word [r7+wq*2+table_offset(prep,)]
+ add wq, r7
+ lea r6, [ssq*3]
+%if WIN64
+ pop r7
+%endif
+ jmp wq
+.v:
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ tzcnt r5d, wd
+ lea myq, [base+subpel_filters+1+myq*8]
+ movzx r5d, word [r7+r5*2+table_offset(prep, _6tap_v)]
+ vpbroadcastd m7, [pw_8192]
+ sub srcq, ssq
+ vpbroadcastw m8, [myq+0]
+ add r5, r7
+ vpbroadcastw m9, [myq+2]
+ lea ss3q, [ssq*3]
+ vpbroadcastw m10, [myq+4]
+ sub srcq, ssq
+ jmp r5
+.v_w4:
+ movd xmm2, [srcq+ssq*0]
+ pinsrd xmm2, [srcq+ssq*1], 1
+ vpbroadcastd ymm1, [srcq+ssq*2]
+ add srcq, ss3q
+ vpbroadcastd ymm3, [srcq+ssq*0]
+ vpbroadcastd ymm0, [srcq+ssq*1]
+ vbroadcasti128 ymm5, [deint_shuf4]
+ vpblendd ymm1, ymm2, 0xeb
+ punpcklqdq ymm3, ymm0
+ vpblendd ymm1, ymm3, 0x60 ; 0 1 2 _ 2 3 4 _
+ pshufb ymm1, ymm5 ; 01 12 23 34
+.v_w4_loop:
+ pinsrd xmm0, [srcq+ssq*2], 1
+ vpbroadcastd ymm2, [srcq+ss3q ]
+ lea srcq, [srcq+ssq*4]
+ vpbroadcastd ymm3, [srcq+ssq*0]
+ vpblendd ymm2, ymm0, 0xeb
+ vpbroadcastd ymm0, [srcq+ssq*1]
+ punpcklqdq ymm3, ymm0
+ vpblendd ymm2, ymm3, 0x60 ; 4 5 6 _ 6 7 8 _
+ pshufb ymm2, ymm5 ; 45 56 67 78
+ pmaddubsw ymm3, ymm1, ym8 ; a0 b0 c0 d0
+ vperm2i128 ymm1, ymm2, 0x21 ; 23 34 45 56
+ pmaddubsw ymm4, ymm2, ym10 ; a2 b2 c2 d2
+ pmaddubsw ymm1, ym9 ; a1 b1 c1 d1
+ paddw ymm3, ymm4
+ paddw ymm3, ymm1
+ pmulhrsw ymm3, ym7
+ mova ymm1, ymm2
+ mova [tmpq], ymm3
+ add tmpq, 32
+ sub hd, 4
+ jg .v_w4_loop
+ vzeroupper
+ RET
+.v_w8:
+ mova m6, [spel_v_perm8]
+ movq xm1, [srcq+ssq*0]
+ mov r6d, 0x3e
+ movq xm2, [srcq+ssq*1]
+ kmovb k1, r6d
+ vpbroadcastq ym3, [srcq+ssq*2]
+ add srcq, ss3q
+ vpunpcklqdq ym2, [srcq+ssq*0] {1to4}
+ vpunpcklqdq m1{k1}, m3, [srcq+ssq*1] {1to8}
+ movq xm0, [srcq+ssq*1]
+ kshiftlb k2, k1, 2
+ shufpd m1, m2, 0x18 ; 0 1 2 3 4
+ vpermb m1, m6, m1 ; 01 12 23 34
+.v_w8_loop:
+ vpbroadcastq ym3, [srcq+ss3q ]
+ vpunpcklqdq ym0{k1}, ym3, [srcq+ssq*2] {1to4}
+ lea srcq, [srcq+ssq*4]
+ vpbroadcastq m3, [srcq+ssq*1]
+ vpunpcklqdq m0{k2}, m3, [srcq+ssq*0] {1to8}
+ pmaddubsw m4, m1, m8 ; a0 b0 c0 d0
+ vpermb m2, m6, m0 ; 45 56 67 78
+ mova xm0, xm3
+ vshufi32x4 m1, m2, q1032 ; 23 34 45 56
+ pmaddubsw m3, m2, m10 ; a3 b3 c3 d3
+ pmaddubsw m5, m1, m9 ; a2 b2 c2 d2
+ mova m1, m2
+ paddw m4, m3
+ paddw m4, m5
+ pmulhrsw m4, m7
+ mova [tmpq], m4
+ add tmpq, 64
+ sub hd, 4
+ jg .v_w8_loop
+ RET
+.v_w16:
+ mova m11, [spel_v_perm16b]
+ vbroadcasti32x4 m1, [srcq+ssq*0]
+ mov r6d, 0x0f
+ vbroadcasti32x4 ym3, [srcq+ssq*1]
+ vbroadcasti32x4 m2, [srcq+ssq*2]
+ kmovb k1, r6d
+ add srcq, ss3q
+ vbroadcasti32x4 ym4, [srcq+ssq*0]
+ vbroadcasti32x4 m0, [srcq+ssq*1]
+ vshufpd m1{k1}, m3, m2, 0xcc
+ vshufpd m2{k1}, m4, m0, 0xcc
+ vpermb m1, m11, m1 ; 01 12
+ vpermb m2, m11, m2 ; 23 34
+.v_w16_loop:
+ pmaddubsw m3, m1, m8 ; a0 b0
+ pmaddubsw m5, m2, m9 ; a1 b1
+ vbroadcasti32x4 ym6, [srcq+ssq*2]
+ pmaddubsw m4, m2, m8 ; c0 d0
+ vbroadcasti32x4 m2, [srcq+ss3q ]
+ lea srcq, [srcq+ssq*4]
+ vshufpd m0{k1}, m6, m2, 0xcc
+ vbroadcasti32x4 ym6, [srcq+ssq*0]
+ vpermb m1, m11, m0 ; 45 56
+ vbroadcasti32x4 m0, [srcq+ssq*1]
+ vshufpd m2{k1}, m6, m0, 0xcc
+ pmaddubsw m6, m1, m9 ; c1 d1
+ vpermb m2, m11, m2 ; 67 78
+ paddw m3, m5
+ pmaddubsw m5, m1, m10 ; a2 b2
+ paddw m4, m6
+ pmaddubsw m6, m2, m10 ; c2 d2
+ paddw m3, m5
+ paddw m4, m6
+ pmulhrsw m3, m7
+ pmulhrsw m4, m7
+ mova [tmpq+ 0], m3
+ mova [tmpq+64], m4
+ add tmpq, 64*2
+ sub hd, 4
+ jg .v_w16_loop
+ RET
+.v_w32:
+ movshdup m6, [bilin_v_perm64]
+ movu ym16, [srcq+ssq*0]
+ movu ym17, [srcq+ssq*1]
+ movu ym18, [srcq+ssq*2]
+ add srcq, ss3q
+ movu ym19, [srcq+ssq*0]
+ add srcq, ssq
+ movu ym20, [srcq+ssq*0]
+ vpermt2q m16, m6, m18 ; 0 2
+ vpermt2q m17, m6, m19 ; 1 3
+ vpermt2q m18, m6, m20 ; 2 4
+ punpcklbw m0, m16, m17 ; 01
+ punpcklbw m1, m17, m18 ; 12
+ punpckhbw m2, m16, m17 ; 23
+ punpckhbw m3, m17, m18 ; 34
+.v_w32_loop:
+ movu ym16, [srcq+ssq*1]
+ lea srcq, [srcq+ssq*2]
+ movu ym17, [srcq+ssq*0]
+ pmaddubsw m4, m0, m8 ; a0
+ mova m0, m2
+ pmaddubsw m2, m9 ; a1
+ vpermt2q m16, m6, m17 ; 5 6
+ pmaddubsw m5, m1, m8 ; b0
+ mova m1, m3
+ pmaddubsw m3, m9 ; b1
+ shufpd m18, m16, 0x55 ; 4 5
+ paddw m4, m2
+ punpcklbw m2, m18, m16 ; 45
+ paddw m5, m3
+ punpckhbw m3, m18, m16 ; 56
+ mova m18, m16
+ pmaddubsw m16, m2, m10 ; a2
+ pmaddubsw m17, m3, m10 ; b2
+ paddw m4, m16
+ paddw m5, m17
+ pmulhrsw m4, m7
+ pmulhrsw m5, m7
+ mova [tmpq+ 0], m4
+ mova [tmpq+64], m5
+ add tmpq, 64*2
+ sub hd, 2
+ jg .v_w32_loop
+ vzeroupper
+ RET
+.v_w64:
+.v_w128:
+ mova m6, [bilin_v_perm64]
+ add wd, wd
+ lea r6d, [hq+wq]
+.v_loop0:
+ vpermq m12, m6, [srcq+ssq*0]
+ vpermq m13, m6, [srcq+ssq*1]
+ lea r5, [srcq+ssq*2]
+ vpermq m14, m6, [r5 +ssq*0]
+ vpermq m15, m6, [r5 +ssq*1]
+ lea r5, [r5+ssq*2]
+ vpermq m16, m6, [r5 +ssq*0]
+ mov r7, tmpq
+ punpcklbw m0, m12, m13 ; 01
+ punpckhbw m12, m13
+ punpcklbw m1, m13, m14 ; 12
+ punpckhbw m13, m14
+ punpcklbw m2, m14, m15 ; 23
+ punpckhbw m14, m15
+ punpcklbw m3, m15, m16 ; 34
+ punpckhbw m15, m16
+.v_loop:
+ pmaddubsw m17, m0, m8 ; a0
+ vpermq m5, m6, [r5+ssq*1]
+ pmaddubsw m18, m12, m8
+ mova m0, m2
+ pmaddubsw m2, m9 ; a1
+ mova m12, m14
+ pmaddubsw m14, m9
+ lea r5, [r5+ssq*2]
+ pmaddubsw m19, m1, m8 ; b0
+ pmaddubsw m20, m13, m8
+ mova m1, m3
+ pmaddubsw m3, m9 ; b1
+ mova m13, m15
+ pmaddubsw m15, m9
+ paddw m17, m2
+ punpcklbw m2, m16, m5 ; 67
+ paddw m18, m14
+ punpckhbw m14, m16, m5
+ vpermq m16, m6, [r5+ssq*0]
+ paddw m19, m3
+ pmaddubsw m3, m2, m10 ; a3
+ paddw m20, m15
+ pmaddubsw m15, m14, m10
+ paddw m17, m3
+ punpcklbw m3, m5, m16 ; 78
+ pmaddubsw m4, m3, m10 ; b3
+ paddw m18, m15
+ punpckhbw m15, m5, m16
+ pmaddubsw m5, m15, m10
+ paddw m19, m4
+ paddw m20, m5
+ REPX {pmulhrsw x, m7}, m17, m18, m19, m20
+ mova [r7+wq*0+ 0], m17
+ mova [r7+wq*0+64], m18
+ mova [r7+wq*1+ 0], m19
+ mova [r7+wq*1+64], m20
+ lea r7, [r7+wq*2]
+ sub hd, 2
+ jg .v_loop
+ add srcq, 64
+ add tmpq, 128
+ movzx hd, r6b
+ sub r6d, 1<<8
+ jg .v_loop0
+ vzeroupper
+ RET
+.h:
+ test myd, 0xf00
+ jz mangle(private_prefix %+ _prep_8tap_8bpc_avx512icl).h2
+.hv:
+ vpbroadcastd m8, [pd_2]
+ vpbroadcastd m9, [pd_32]
+ cmp wd, 4
+ jg .hv_w8
+ movzx mxd, mxb
+ vpbroadcastd m11, [base+subpel_filters+mxq*8+2]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ vpbroadcastq m3, [base+subpel_filters+1+myq*8]
+ vbroadcasti128 m10, [subpel_h_shufA]
+ lea r6, [ssq*2+1]
+ mov r3d, 0x30
+ sub srcq, r6
+ kmovb k1, r3d
+ vpbroadcastq ym2, [srcq+ssq*0]
+ lea ss3q, [ssq*3]
+ vpbroadcastq m1, [srcq+ssq*1]
+ kaddb k2, k1, k1
+ vpbroadcastq m2{k1}, [srcq+ssq*2]
+ add srcq, ss3q
+ vpbroadcastq m1{k2}, [srcq+ssq*0] ; _ _ 1 3
+ punpcklbw m3, m3
+ vpbroadcastq m2{k2}, [srcq+ssq*1] ; _ 0 2 4
+ psraw m3, 8 ; sign-extend
+ mova m6, [spel_hv_perm4a]
+ kshiftrb k1, k1, 2
+ movu m7, [spel_hv_perm4b]
+ pshufb m1, m10
+ mova m0, m8
+ vpdpbusd m0, m1, m11
+ pshufb m2, m10
+ mova m1, m8
+ vpdpbusd m1, m2, m11
+ pshufd m12, m3, q0000
+ pshufd m13, m3, q1111
+ pshufd m14, m3, q2222
+ packssdw m0, m1 ; _ _ _ 0 1 2 3 4
+ psraw m0, 2
+ vpermb m1, m7, m0 ; 01 12 23 34
+.hv_w4_loop:
+ movq xm3, [srcq+ssq*2]
+ movq xm4, [srcq+ss3q ]
+ lea srcq, [srcq+ssq*4]
+ vpbroadcastq ym3{k1}, [srcq+ssq*0] ; 5 7
+ vpbroadcastq ym4{k1}, [srcq+ssq*1] ; 6 8
+ pshufb ym3, ym10
+ mova ym2, ym8
+ vpdpbusd ym2, ym3, ym11
+ pshufb ym4, ym10
+ mova ym3, ym8
+ vpdpbusd ym3, ym4, ym11
+ mova m4, m9
+ vpdpwssd m4, m1, m12 ; a0 b0 c0 d0
+ packssdw ym2, ym3 ; 5 6 7 8
+ psraw ym2, 2
+ vshufi32x4 m0, m2, q1032 ; _ 2 3 4 5 6 7 8
+ vpermb m2, m6, m0 ; 23 34 45 56
+ vpermb m1, m7, m0 ; 45 56 67 78
+ vpdpwssd m4, m2, m13 ; a1 b1 c1 d1
+ vpdpwssd m4, m1, m14 ; a2 b2 c2 d2
+ psrad m4, 6
+ vpmovdw [tmpq], m4
+ add tmpq, 32
+ sub hd, 4
+ jg .hv_w4_loop
+ RET
+.hv_w8:
+ shr mxd, 16
+ vpbroadcastd m10, [base+subpel_filters+mxq*8+0]
+ vpbroadcastd m11, [base+subpel_filters+mxq*8+4]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ vpbroadcastq m0, [base+subpel_filters+1+myq*8]
+ lea r6, [ssq*2+3]
+ punpcklbw m0, m0
+ sub srcq, r6
+ psraw m0, 8 ; sign-extend
+ lea ss3q, [ssq*3]
+ pshufd m12, m0, q0000
+ pshufd m13, m0, q1111
+ pshufd m14, m0, q2222
+ cmp wd, 8
+ jg .hv_w16
+ movu xm16, [srcq+ssq*0]
+ vbroadcasti32x4 m19, [subpel_h_shufA]
+ vinserti128 ym16, [srcq+ssq*1], 1
+ vbroadcasti32x4 m21, [subpel_h_shufC]
+ vinserti32x4 m16, [srcq+ssq*2], 2
+ add srcq, ss3q
+ vinserti32x4 m16, [srcq+ssq*0], 3
+ movu xm17, [srcq+ssq*1]
+ vbroadcasti32x4 m20, [subpel_h_shufB]
+ pshufb m3, m16, m19 ; 0 1 2 3 0123
+ mova m2, m8
+ pshufb m0, m16, m21 ; 0 1 2 3 89ab
+ vpdpbusd m2, m3, m10
+ mova m3, m8
+ pshufb xm1, xm17, xm19 ; 3 4 5 6 0123
+ vpdpbusd m3, m0, m11
+ mova xm0, xm8
+ pshufb xm18, xm17, xm21 ; 3 4 5 6 89ab
+ vpdpbusd xm0, xm1, xm10
+ mova xm1, xm8
+ pshufb m16, m20 ; 0 1 2 3 4567
+ vpdpbusd xm1, xm18, xm11
+ pshufb xm17, xm20 ; 3 4 5 6 4567
+ vpdpbusd m2, m16, m11
+ vpdpbusd m3, m16, m10
+ vpdpbusd xm0, xm17, xm11
+ vpdpbusd xm1, xm17, xm10
+ packssdw m2, m3
+ packssdw xm0, xm1
+ psraw m2, 2 ; 0 1 2 3
+ psraw xm0, 2 ; 4
+ valignq m0, m2, 2 ; 1 2 3 4
+ punpcklwd m1, m2, m0 ; 01 12 23 34
+ punpckhwd m2, m0
+.hv_w8_loop:
+ movu xm16, [srcq+ssq*2]
+ vinserti128 ym16, [srcq+ss3q ], 1
+ lea srcq, [srcq+ssq*4]
+ vinserti32x4 m16, [srcq+ssq*0], 2
+ vinserti32x4 m16, [srcq+ssq*1], 3
+ pshufb m6, m16, m19 ; 5 6 7 8 0123
+ mova m5, m8
+ pshufb m3, m16, m21 ; 5 6 7 8 89ab
+ vpdpbusd m5, m6, m10
+ mova m6, m8
+ pshufb m16, m20 ; 5 6 7 8 4567
+ vpdpbusd m6, m3, m11
+ mova m3, m9
+ vpdpwssd m3, m1, m12 ; a0 b0 c0 d0
+ mova m4, m9
+ vpdpwssd m4, m2, m12
+ vpdpbusd m5, m16, m11
+ vpdpbusd m6, m16, m10
+ mova m16, m1
+ packssdw m5, m6
+ mova m6, m2
+ psraw m5, 2 ; 5 6 7 8
+ valignq m2, m5, m0, 6 ; 4 5 6 7
+ mova m0, m5
+ punpcklwd m1, m2, m5 ; 45 56 67 78
+ punpckhwd m2, m5
+ vpdpwssd m3, m1, m14 ; a2 b2 c2 d2
+ vpdpwssd m4, m2, m14
+ vshufi32x4 m16, m1, q1032 ; 23 34 45 56
+ vshufi32x4 m6, m2, q1032
+ vpdpwssd m3, m16, m13 ; a1 b1 c1 d1
+ vpdpwssd m4, m6, m13
+ psrad m3, 6
+ psrad m4, 6
+ packssdw m3, m4
+ mova [tmpq], m3
+ add tmpq, 64
+ sub hd, 4
+ jg .hv_w8_loop
+ vzeroupper
+ RET
+.hv_w16:
+ mova m16, [spel_h_perm16]
+ vpbroadcastd m18, [pb_4]
+ add wd, wd
+ paddb m17, m18, m16
+ lea r6d, [hq+wq*8-256]
+ paddb m18, m17
+.hv_w16_loop0:
+ movu ym19, [srcq+ssq*0]
+ vinserti32x8 m19, [srcq+ssq*1], 1
+ lea r5, [srcq+ssq*2]
+ movu ym20, [r5 +ssq*0]
+ vinserti32x8 m20, [r5 +ssq*1], 1
+ lea r5, [r5 +ssq*2]
+ movu ym21, [r5 +ssq*0]
+ mov r7, tmpq
+ vpermb m3, m16, m19 ; 0 1 0123 89ab
+ mova m2, m8
+ vpermb m4, m18, m19 ; 0 1 89ab ghij
+ vpdpbusd m2, m3, m10
+ mova m3, m8
+ vpermb m5, m16, m20 ; 2 3 0123 89ab
+ vpdpbusd m3, m4, m11
+ mova m4, m8
+ vpermb m0, m18, m20 ; 2 3 89ab ghij
+ vpdpbusd m4, m5, m10
+ mova m5, m8
+ vpermb ym1, ym16, ym21 ; 4 0123 89ab
+ vpdpbusd m5, m0, m11
+ mova ym0, ym8
+ vpermb ym6, ym18, ym21 ; 4 89ab ghij
+ vpdpbusd ym0, ym1, ym10
+ mova ym1, ym8
+ vpermb m19, m17, m19 ; 0 1 4567 cdef
+ vpdpbusd ym1, ym6, ym11
+ vpermb m20, m17, m20 ; 2 3 4567 cdef
+ vpdpbusd m2, m19, m11
+ vpdpbusd m3, m19, m10
+ vpermb ym21, ym17, ym21 ; 4 4567 cdef
+ vpdpbusd m4, m20, m11
+ vpdpbusd m5, m20, m10
+ vpdpbusd ym0, ym21, ym11
+ vpdpbusd ym1, ym21, ym10
+ packssdw m2, m3 ; 0 1
+ packssdw m4, m5 ; 2 3
+ packssdw ym0, ym1 ; 4
+ REPX {psraw x, 2}, m2, m4, ym0
+ vshufi32x4 m3, m2, m4, q1032 ; 1 2
+ vshufi32x4 m0, m4, m0, q1032 ; 3 4
+ punpcklwd m1, m2, m3 ; 01 12
+ punpckhwd m2, m3
+ punpcklwd m3, m4, m0 ; 23 34
+ punpckhwd m4, m0
+.hv_w16_loop:
+ movu ym19, [r5+ssq*1]
+ lea r5, [r5+ssq*2]
+ vinserti32x8 m19, [r5+ssq*0], 1
+ vpermb m6, m16, m19 ; 5 6 0123 89ab
+ mova m5, m8
+ vpermb m20, m18, m19 ; 5 6 89ab ghij
+ vpdpbusd m5, m6, m10
+ mova m6, m8
+ vpermb m19, m17, m19 ; 5 6 4567 cdef
+ vpdpbusd m6, m20, m11
+ mova m20, m9
+ vpdpwssd m20, m1, m12 ; a0 b0
+ mova m21, m9
+ vpdpwssd m21, m2, m12
+ vpdpbusd m5, m19, m11
+ vpdpbusd m6, m19, m10
+ vpdpwssd m20, m3, m13 ; a1 b1
+ vpdpwssd m21, m4, m13
+ packssdw m5, m6
+ mova m1, m3
+ psraw m5, 2 ; 5 6
+ mova m2, m4
+ vshufi32x4 m4, m0, m5, q1032 ; 4 5
+ mova m0, m5
+ punpcklwd m3, m4, m0 ; 45 56
+ punpckhwd m4, m0
+ vpdpwssd m20, m3, m14 ; a2 b2
+ vpdpwssd m21, m4, m14
+ psrad m20, 6
+ psrad m21, 6
+ packssdw m20, m21
+ mova [r7+wq*0], ym20
+ vextracti32x8 [r7+wq*1], m20, 1
+ lea r7, [r7+wq*2]
+ sub hd, 2
+ jg .hv_w16_loop
+ add srcq, 16
+ add tmpq, 32
movzx hd, r6b
- mov srcq, r4
- mov dstq, r7
sub r6d, 1<<8
jg .hv_w16_loop0
vzeroupper
@@ -2353,183 +3424,38 @@ cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3
mova [tmpq+64*1], m1
%endmacro
-%if WIN64
-DECLARE_REG_TMP 6, 4
-%else
-DECLARE_REG_TMP 6, 7
-%endif
-
-%define PREP_8TAP_FN FN prep_8tap,
-
+PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP, prep_8tap_8bpc
+PREP_8TAP_FN regular_sharp, REGULAR, SHARP, prep_8tap_8bpc
PREP_8TAP_FN sharp, SHARP, SHARP
-PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH
-PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP
-PREP_8TAP_FN smooth, SMOOTH, SMOOTH
-PREP_8TAP_FN sharp_regular, SHARP, REGULAR
-PREP_8TAP_FN regular_sharp, REGULAR, SHARP
-PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR
-PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH
-PREP_8TAP_FN regular, REGULAR, REGULAR
-cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
+cglobal prep_8tap_8bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my, stride3
imul mxd, mxm, 0x010101
add mxd, t0d ; 8tap_h, mx, 4tap_h
imul myd, mym, 0x010101
add myd, t1d ; 8tap_v, my, 4tap_v
lea r7, [prep_avx512icl]
- movsxd wq, wm
movifnidn hd, hm
test mxd, 0xf00
jnz .h
test myd, 0xf00
- jnz .v
- tzcnt wd, wd
- movzx wd, word [r7+wq*2+table_offset(prep,)]
- add wq, r7
- lea r6, [strideq*3]
-%if WIN64
- pop r7
-%endif
- jmp wq
-.h:
- test myd, 0xf00
- jnz .hv
- vpbroadcastd m4, [pd_2]
- WIN64_SPILL_XMM 10
- cmp wd, 4
- je .h_w4
- tzcnt wd, wd
- shr mxd, 16
- sub srcq, 3
- movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)]
- vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep_avx512icl+0]
- vpbroadcastd m9, [r7+mxq*8+subpel_filters-prep_avx512icl+4]
- add wq, r7
- jmp wq
-.h_w4:
- movzx mxd, mxb
- vbroadcasti128 ym5, [subpel_h_shufA]
- mov r3d, 0x4
- dec srcq
- vpbroadcastd ym6, [r7+mxq*8+subpel_filters-prep_avx512icl+2]
- kmovb k1, r3d
- lea stride3q, [strideq*3]
-.h_w4_loop:
- movq xm2, [srcq+strideq*0]
- movq xm3, [srcq+strideq*1]
- vpbroadcastq ym2{k1}, [srcq+strideq*2]
- vpbroadcastq ym3{k1}, [srcq+stride3q ]
- lea srcq, [srcq+strideq*4]
- pshufb ym2, ym5
- pshufb ym3, ym5
- mova ym0, ym4
- vpdpbusd ym0, ym2, ym6
- mova ym1, ym4
- vpdpbusd ym1, ym3, ym6
- packssdw ym0, ym1
- psraw ym0, 2
- mova [tmpq], ym0
- add tmpq, 32
- sub hd, 4
- jg .h_w4_loop
- RET
-.h_w8:
- vbroadcasti128 m5, [subpel_h_shufA]
- vbroadcasti128 m6, [subpel_h_shufB]
- vbroadcasti128 m7, [subpel_h_shufC]
- lea stride3q, [strideq*3]
-.h_w8_loop:
- movu xmm3, [srcq+strideq*0]
- vinserti128 ym3, ymm3, [srcq+strideq*1], 1
- vinserti128 m3, [srcq+strideq*2], 2
- vinserti128 m3, [srcq+stride3q ], 3
- lea srcq, [srcq+strideq*4]
- pshufb m1, m3, m5
- pshufb m2, m3, m6
- mova m0, m4
- vpdpbusd m0, m1, m8
- mova m1, m4
- vpdpbusd m1, m2, m8
- pshufb m3, m7
- vpdpbusd m0, m2, m9
- vpdpbusd m1, m3, m9
- packssdw m0, m1
- psraw m0, 2
- mova [tmpq], m0
- add tmpq, 64
- sub hd, 4
- jg .h_w8_loop
- RET
-.h_w16:
- mova m5, [spel_h_perm16a]
- mova m6, [spel_h_perm16b]
- mova m7, [spel_h_perm16c]
- lea stride3q, [strideq*3]
-.h_w16_loop:
- movu ym0, [srcq+strideq*0]
- movu ym1, [srcq+strideq*2]
- vinserti32x8 m0, [srcq+strideq*1], 1
- vinserti32x8 m1, [srcq+stride3q ], 1
- lea srcq, [srcq+strideq*4]
- PREP_8TAP_H
- add tmpq, 64*2
- sub hd, 4
- jg .h_w16_loop
- RET
-.h_w32:
- mova m5, [spel_h_perm32a]
- mova m6, [spel_h_perm32b]
- mova m7, [spel_h_perm32c]
-.h_w32_loop:
- movu m0, [srcq+strideq*0]
- movu m1, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- PREP_8TAP_H
- add tmpq, 64*2
- sub hd, 2
- jg .h_w32_loop
- RET
-.h_w64:
- xor r6d, r6d
- jmp .h_start
-.h_w128:
- mov r6, -64*1
-.h_start:
- mova m5, [spel_h_perm32a]
- mova m6, [spel_h_perm32b]
- mova m7, [spel_h_perm32c]
- sub srcq, r6
- mov r5, r6
-.h_loop:
- movu m0, [srcq+r6+32*0]
- movu m1, [srcq+r6+32*1]
- PREP_8TAP_H
- add tmpq, 64*2
- add r6, 64
- jle .h_loop
- add srcq, strideq
- mov r6, r5
- dec hd
- jg .h_loop
- RET
+ jz mangle(private_prefix %+ _prep_6tap_8bpc_avx512icl).prep
.v:
movzx mxd, myb ; Select 4-tap/8-tap filter multipliers.
shr myd, 16 ; Note that the code is 8-tap only, having
- tzcnt wd, wd
cmp hd, 4 ; a separate 4-tap code path for (4|8|16)x4
cmove myd, mxd ; had a negligible effect on performance.
- ; TODO: Would a 6-tap code path be worth it?
- lea myq, [r7+myq*8+subpel_filters-prep_avx512icl]
- movzx wd, word [r7+wq*2+table_offset(prep, _8tap_v)]
- add wq, r7
- lea stride3q, [strideq*3]
- sub srcq, stride3q
+ tzcnt r5d, wd
+ lea myq, [base+subpel_filters+myq*8]
+ movzx r5d, word [r7+r5*2+table_offset(prep, _8tap_v)]
vpbroadcastd m7, [pw_8192]
vpbroadcastw m8, [myq+0]
+ add r5, r7
vpbroadcastw m9, [myq+2]
+ lea stride3q, [strideq*3]
vpbroadcastw m10, [myq+4]
+ sub srcq, stride3q
vpbroadcastw m11, [myq+6]
- jmp wq
+ jmp r5
.v_w4:
movd xmm0, [srcq+strideq*0]
vpbroadcastd ymm1, [srcq+strideq*2]
@@ -2576,172 +3502,146 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
vzeroupper
RET
.v_w8:
- mov r3d, 0xf044
- kmovw k1, r3d
- kshiftrw k2, k1, 8
- movq xm0, [srcq+strideq*0]
- vpbroadcastq ym1, [srcq+strideq*1]
- vpbroadcastq m2, [srcq+strideq*2]
- vpbroadcastq m3, [srcq+stride3q ]
+ mova m6, [spel_v_perm8]
+ movq xm1, [srcq+strideq*0]
+ mov r6d, 0x3e
+ movq xm2, [srcq+strideq*1]
+ vpbroadcastq ym3, [srcq+strideq*2]
+ kmovb k1, r6d
+ vpbroadcastq ym4, [srcq+stride3q ]
lea srcq, [srcq+strideq*4]
- vpbroadcastq m4, [srcq+strideq*0]
- vpbroadcastq m5, [srcq+strideq*1]
- vpbroadcastq m6, [srcq+strideq*2]
- vmovdqa64 ym0{k1}, ym1
- vmovdqa64 ym1{k1}, ym2
- vmovdqa64 m2{k1}, m3
- vmovdqa64 m3{k1}, m4
- vmovdqa64 m4{k1}, m5
- vmovdqa64 m5{k1}, m6
- punpcklbw ym0, ym1 ; 01 12 __ __
- punpcklbw m2, m3 ; 23 34 23 34
- punpcklbw m4, m5 ; 45 56 45 56
- vmovdqa64 m0{k2}, m2 ; 01 12 23 34
- vmovdqa64 m2{k2}, m4 ; 23 34 45 56
+ vpunpcklqdq m1{k1}, m3, [srcq+strideq*0] {1to8}
+ vpunpcklqdq m2{k1}, m4, [srcq+strideq*1] {1to8}
+ movq xm0, [srcq+strideq*2]
+ kshiftlb k2, k1, 2
+ shufpd m1, m2, 0x30 ; 0 1 2 3 4 5
+ vshufi32x4 m2, m1, m0, q0021 ; 2 3 4 5 6 _
+ vpermb m1, m6, m1 ; 01 12 23 34
+ vpermb m2, m6, m2 ; 23 34 45 56
.v_w8_loop:
- vpbroadcastq m1, [srcq+stride3q ]
+ vpbroadcastq ym3, [srcq+strideq*4]
+ vpunpcklqdq ym0{k1}, ym3, [srcq+stride3q] {1to4}
lea srcq, [srcq+strideq*4]
- vpbroadcastq m3, [srcq+strideq*0]
- vpbroadcastq m5, [srcq+strideq*1]
- pmaddubsw m14, m0, m8
- pmaddubsw m15, m2, m9
- vpblendmq m0{k1}, m6, m1
- vpblendmq m2{k1}, m1, m3
- vpbroadcastq m6, [srcq+strideq*2]
- paddw m14, m15
- punpcklbw m2, m0, m2 ; 67 78 67 78
- vpblendmq m12{k1}, m3, m5
- vpblendmq m13{k1}, m5, m6
- vpblendmq m0{k2}, m4, m2 ; 45 56 67 78
- punpcklbw m4, m12, m13 ; 89 9a 89 9a
- vmovdqa64 m2{k2}, m4 ; 67 78 89 9a
- pmaddubsw m12, m0, m10
- pmaddubsw m13, m2, m11
- paddw m14, m12
- paddw m14, m13
- pmulhrsw m14, m7
- mova [tmpq], m14
+ vpbroadcastq m3, [srcq+strideq*2]
+ vpunpcklqdq m0{k2}, m3, [srcq+strideq*1] {1to8}
+ pmaddubsw m4, m1, m8 ; a0 b0 c0 d0
+ mova m1, m2
+ pmaddubsw m5, m2, m9 ; a1 b1 c1 d1
+ vpermb m2, m6, m0 ; 67 78 89 9a
+ mova xm0, xm3
+ vshufi32x4 m1, m2, q1032 ; 45 56 67 78
+ pmaddubsw m3, m2, m11 ; a3 b3 c3 d3
+ paddw m4, m5
+ pmaddubsw m5, m1, m10 ; a2 b2 c2 d2
+ paddw m4, m3
+ paddw m4, m5
+ pmulhrsw m4, m7
+ mova [tmpq], m4
add tmpq, 64
sub hd, 4
jg .v_w8_loop
RET
.v_w16:
- mov r3d, 0xf0
- kmovb k1, r3d
- vbroadcasti128 m0, [srcq+strideq*0]
- vbroadcasti128 m1, [srcq+strideq*1]
- vbroadcasti128 m2, [srcq+strideq*2]
- vbroadcasti128 m3, [srcq+stride3q ]
+ mova m12, [spel_v_perm16b]
+ vbroadcasti32x4 m1, [srcq+strideq*0]
+ mov r6d, 0x0f
+ vbroadcasti32x4 ym4, [srcq+strideq*1]
+ vbroadcasti32x4 m2, [srcq+strideq*2]
+ kmovb k1, r6d
+ vbroadcasti32x4 ym5, [srcq+stride3q ]
lea srcq, [srcq+strideq*4]
- vbroadcasti128 m4, [srcq+strideq*0]
- vbroadcasti128 m5, [srcq+strideq*1]
- vbroadcasti128 m6, [srcq+strideq*2]
- vmovdqa64 m0{k1}, m1
- vmovdqa64 m1{k1}, m2
- vmovdqa64 m2{k1}, m3
- vmovdqa64 m3{k1}, m4
- vmovdqa64 m4{k1}, m5
- vmovdqa64 m5{k1}, m6
- shufpd m0, m2, 0xcc ; 0a_2a 0b_2b 1a_3a 1b_3b
- shufpd m1, m3, 0xcc ; 1a_3a 1b_3b 2a_4a 2b_4b
- shufpd m4, m4, 0x44 ; 4a_-- 4b_-- 5a_-- 5b_--
- shufpd m5, m5, 0x44 ; 5a_-- 5b_-- 6a_-- 6b_--
- punpckhbw m2, m0, m1 ; 23a 23b 34a 34b
- punpcklbw m0, m1 ; 01a 01b 12a 12b
- punpcklbw m4, m5 ; 45a 45b 56a 56b
+ vbroadcasti32x4 m3, [srcq+strideq*0]
+ vbroadcasti32x4 ym6, [srcq+strideq*1]
+ vbroadcasti32x4 m0, [srcq+strideq*2]
+ vshufpd m1{k1}, m4, m2, 0xcc
+ vshufpd m2{k1}, m5, m3, 0xcc
+ vshufpd m3{k1}, m6, m0, 0xcc
+ vpermb m1, m12, m1 ; 01 12
+ vpermb m2, m12, m2 ; 23 34
+ vpermb m3, m12, m3 ; 45 56
.v_w16_loop:
- vbroadcasti128 m3, [srcq+stride3q ]
+ pmaddubsw m4, m1, m8 ; a0 b0
+ mova m1, m3
+ pmaddubsw m13, m2, m9 ; a1 b1
+ vbroadcasti32x4 ym6, [srcq+stride3q ]
+ pmaddubsw m5, m2, m8 ; c0 d0
lea srcq, [srcq+strideq*4]
- vbroadcasti128 m5, [srcq+strideq*0]
- vpblendmq m1{k1}, m6, m3
- vmovdqa64 m3{k1}, m5
- pmaddubsw m12, m0, m8
- pmaddubsw m13, m2, m8
- pmaddubsw m14, m2, m9
- pmaddubsw m15, m4, m9
- pmaddubsw m0, m4, m10
- vbroadcasti128 m2, [srcq+strideq*1]
- vbroadcasti128 m6, [srcq+strideq*2]
- paddw m12, m14
- paddw m13, m15
- paddw m12, m0
- vmovdqa64 m5{k1}, m2
- vmovdqa64 m2{k1}, m6
- mova m0, m4
- shufpd m1, m5, 0xcc ; 6a_8a 6b_8b 7a_9a 7b_9b
- shufpd m3, m2, 0xcc ; 7a_9a 7b_9b 8a_Aa 8b_Ab
- punpcklbw m2, m1, m3 ; 67a 67b 78a 78b
- punpckhbw m4, m1, m3 ; 89a 89b 9Aa 9Ab
- pmaddubsw m14, m2, m10
- pmaddubsw m15, m2, m11
- paddw m13, m14
- paddw m12, m15
- pmaddubsw m14, m4, m11
- paddw m13, m14
- pmulhrsw m12, m7
- pmulhrsw m13, m7
- mova [tmpq+ 0], m12
- mova [tmpq+64], m13
+ pmaddubsw m14, m3, m9 ; c1 d1
+ vbroadcasti32x4 m3, [srcq+strideq*0]
+ vshufpd m0{k1}, m6, m3, 0xcc
+ vbroadcasti32x4 ym6, [srcq+strideq*1]
+ vpermb m2, m12, m0 ; 67 78
+ vbroadcasti32x4 m0, [srcq+strideq*2]
+ vshufpd m3{k1}, m6, m0, 0xcc
+ paddw m4, m13
+ pmaddubsw m13, m1, m10 ; a2 b2
+ vpermb m3, m12, m3 ; 89 9a
+ paddw m5, m14
+ pmaddubsw m14, m2, m10 ; c2 d2
+ pmaddubsw m15, m2, m11 ; a3 b3
+ pmaddubsw m6, m3, m11 ; c3 d3
+ paddw m4, m13
+ paddw m5, m14
+ paddw m4, m15
+ paddw m5, m6
+ pmulhrsw m4, m7
+ pmulhrsw m5, m7
+ mova [tmpq+ 0], m4
+ mova [tmpq+64], m5
add tmpq, 64*2
sub hd, 4
jg .v_w16_loop
RET
.v_w32:
- mova m18, [bilin_v_perm64]
- movu ym0, [srcq+strideq*0]
- movu ym1, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- movu ym2, [srcq+strideq*0]
- movu ym3, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- movu ym4, [srcq+strideq*0]
- movu ym5, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- movu ym6, [srcq+strideq*0]
- vpermq m0, m18, m0
- vpermq m1, m18, m1
- vpermq m2, m18, m2
- vpermq m3, m18, m3
- vpermq m4, m18, m4
- vpermq m5, m18, m5
- vpermq m6, m18, m6
- punpcklbw m0, m1
- punpcklbw m1, m2
- punpcklbw m2, m3
- punpcklbw m3, m4
- punpcklbw m4, m5
- punpcklbw m5, m6
+ movshdup m21, [bilin_v_perm64]
+ movu ym16, [srcq+strideq*0]
+ movu ym17, [srcq+strideq*1]
+ movu ym18, [srcq+strideq*2]
+ add srcq, stride3q
+ movu ym19, [srcq+strideq*0]
+ vpermt2q m16, m21, m19 ; 0 3
+ movu ym20, [srcq+strideq*1]
+ vpermt2q m17, m21, m20 ; 1 4
+ movu ym20, [srcq+strideq*2]
+ add srcq, stride3q
+ vpermt2q m18, m21, m20 ; 2 5
+ movu ym20, [srcq+strideq*0]
+ vpermt2q m19, m21, m20 ; 3 6
+ punpcklbw m0, m16, m17 ; 01
+ punpcklbw m1, m17, m18 ; 12
+ punpcklbw m2, m18, m19 ; 23
+ punpckhbw m3, m16, m17 ; 34
+ punpckhbw m4, m17, m18 ; 45
+ punpckhbw m5, m18, m19 ; 56
.v_w32_loop:
- movu ym12, [srcq+strideq*1]
+ movu ym16, [srcq+strideq*1]
lea srcq, [srcq+strideq*2]
- movu ym13, [srcq+strideq*0]
+ movu ym17, [srcq+strideq*0]
pmaddubsw m14, m0, m8
- pmaddubsw m16, m2, m9
- pmaddubsw m15, m1, m8
- pmaddubsw m17, m3, m9
mova m0, m2
+ pmaddubsw m15, m1, m8
mova m1, m3
- vpermq m12, m18, m12
- vpermq m13, m18, m13
- paddw m14, m16
- paddw m15, m17
- pmaddubsw m16, m4, m10
- pmaddubsw m17, m5, m10
- punpcklbw m6, m12
- punpcklbw m12, m13
+ pmaddubsw m2, m9
+ vpermt2q m16, m21, m17 ; 7 8
+ pmaddubsw m3, m9
+ pmaddubsw m12, m4, m10
+ pmaddubsw m13, m5, m10
+ shufpd m19, m16, 0x55 ; 6 7
+ paddw m14, m2
mova m2, m4
+ punpcklbw m4, m19, m16 ; 67
+ paddw m15, m3
mova m3, m5
- paddw m14, m16
- paddw m15, m17
- pmaddubsw m16, m6, m11
- pmaddubsw m17, m12, m11
- mova m4, m6
- mova m5, m12
- paddw m14, m16
- paddw m15, m17
+ punpckhbw m5, m19, m16 ; 78
+ paddw m14, m12
+ paddw m15, m13
+ pmaddubsw m12, m4, m11
+ pmaddubsw m13, m5, m11
+ mova m19, m16
+ paddw m14, m12
+ paddw m15, m13
pmulhrsw m14, m7
pmulhrsw m15, m7
- mova m6, m13
mova [tmpq+ 0], m14
mova [tmpq+64], m15
add tmpq, 64*2
@@ -2750,154 +3650,241 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
vzeroupper
RET
.v_w64:
- mov wd, 64
- jmp .v_start
.v_w128:
- mov wd, 128
-.v_start:
- WIN64_SPILL_XMM 27
- mova m26, [bilin_v_perm64]
- lea r6d, [hq+wq*2]
- mov r5, srcq
- mov r7, tmpq
+ WIN64_SPILL_XMM 24
+ mova m23, [bilin_v_perm64]
+ add wd, wd
+ lea r6d, [hq+wq]
.v_loop0:
- vpermq m0, m26, [srcq+strideq*0]
- vpermq m1, m26, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vpermq m2, m26, [srcq+strideq*0]
- vpermq m3, m26, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vpermq m4, m26, [srcq+strideq*0]
- vpermq m5, m26, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vpermq m6, m26, [srcq+strideq*0]
- punpckhbw m12, m0, m1
- punpcklbw m0, m1
- punpckhbw m13, m1, m2
- punpcklbw m1, m2
- punpckhbw m14, m2, m3
- punpcklbw m2, m3
- punpckhbw m15, m3, m4
- punpcklbw m3, m4
- punpckhbw m16, m4, m5
- punpcklbw m4, m5
- punpckhbw m17, m5, m6
- punpcklbw m5, m6
+ vpermq m12, m23, [srcq+strideq*0]
+ vpermq m13, m23, [srcq+strideq*1]
+ lea r5, [srcq+strideq*2]
+ vpermq m14, m23, [r5 +strideq*0]
+ vpermq m15, m23, [r5 +strideq*1]
+ lea r5, [r5+strideq*2]
+ vpermq m16, m23, [r5 +strideq*0]
+ vpermq m17, m23, [r5 +strideq*1]
+ lea r5, [r5+strideq*2]
+ vpermq m18, m23, [r5 +strideq*0]
+ mov r7, tmpq
+ punpcklbw m0, m12, m13 ; 01
+ punpckhbw m12, m13
+ punpcklbw m1, m13, m14 ; 12
+ punpckhbw m13, m14
+ punpcklbw m2, m14, m15 ; 23
+ punpckhbw m14, m15
+ punpcklbw m3, m15, m16 ; 34
+ punpckhbw m15, m16
+ punpcklbw m4, m16, m17 ; 45
+ punpckhbw m16, m17
+ punpcklbw m5, m17, m18 ; 56
+ punpckhbw m17, m18
.v_loop:
- vpermq m18, m26, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vpermq m19, m26, [srcq+strideq*0]
- pmaddubsw m20, m0, m8
- pmaddubsw m21, m12, m8
- pmaddubsw m22, m1, m8
- pmaddubsw m23, m13, m8
+ pmaddubsw m19, m0, m8 ; a0
+ vpermq m6, m23, [r5+strideq*1]
+ pmaddubsw m20, m12, m8
mova m0, m2
+ pmaddubsw m2, m9 ; a1
mova m12, m14
+ pmaddubsw m14, m9
+ lea r5, [r5+strideq*2]
+ pmaddubsw m21, m1, m8 ; b0
+ pmaddubsw m22, m13, m8
mova m1, m3
+ pmaddubsw m3, m9 ; b1
mova m13, m15
- pmaddubsw m2, m9
- pmaddubsw m14, m9
- pmaddubsw m3, m9
pmaddubsw m15, m9
- punpckhbw m24, m6, m18
- punpcklbw m6, m18
- paddw m20, m2
- paddw m21, m14
- paddw m22, m3
- paddw m23, m15
+ paddw m19, m2
mova m2, m4
+ pmaddubsw m4, m10 ; a2
+ paddw m20, m14
mova m14, m16
+ pmaddubsw m16, m10
+ paddw m21, m3
mova m3, m5
+ pmaddubsw m5, m10 ; b2
+ paddw m22, m15
mova m15, m17
- pmaddubsw m4, m10
- pmaddubsw m16, m10
- pmaddubsw m5, m10
pmaddubsw m17, m10
- punpckhbw m25, m18, m19
- punpcklbw m18, m19
- paddw m20, m4
- paddw m21, m16
- paddw m22, m5
- paddw m23, m17
- mova m4, m6
- mova m16, m24
- mova m5, m18
- mova m17, m25
- pmaddubsw m6, m11
- pmaddubsw m24, m11
- pmaddubsw m18, m11
- pmaddubsw m25, m11
- paddw m20, m6
- paddw m21, m24
- paddw m22, m18
- paddw m23, m25
- pmulhrsw m20, m7
- pmulhrsw m21, m7
- pmulhrsw m22, m7
- pmulhrsw m23, m7
- mova m6, m19
- mova [tmpq+wq*0+ 0], m20
- mova [tmpq+wq*0+64], m21
- mova [tmpq+wq*2+ 0], m22
- mova [tmpq+wq*2+64], m23
- lea tmpq, [tmpq+wq*4]
+ paddw m19, m4
+ punpcklbw m4, m18, m6 ; 67
+ paddw m20, m16
+ punpckhbw m16, m18, m6
+ vpermq m18, m23, [r5+strideq*0]
+ paddw m21, m5
+ pmaddubsw m5, m4, m11 ; a3
+ paddw m22, m17
+ pmaddubsw m17, m16, m11
+ paddw m19, m5
+ punpcklbw m5, m6, m18 ; 78
+ paddw m20, m17
+ punpckhbw m17, m6, m18
+ pmaddubsw m6, m5, m11 ; b3
+ paddw m21, m6
+ pmaddubsw m6, m17, m11
+ paddw m22, m6
+ REPX {pmulhrsw x, m7}, m19, m20, m21, m22
+ mova [r7+wq*0+ 0], m19
+ mova [r7+wq*0+64], m20
+ mova [r7+wq*1+ 0], m21
+ mova [r7+wq*1+64], m22
+ lea r7, [r7+wq*2]
sub hd, 2
jg .v_loop
- add r5, 64
- add r7, 128
+ add srcq, 64
+ add tmpq, 128
movzx hd, r6b
- mov srcq, r5
- mov tmpq, r7
sub r6d, 1<<8
jg .v_loop0
RET
-.hv:
- WIN64_SPILL_XMM 16
+.h:
+ RESET_STACK_STATE
+ test myd, 0xf00
+ jnz .hv
+.h2:
+ vpbroadcastd m4, [pd_2]
cmp wd, 4
- je .hv_w4
+ je .h_w4
+ tzcnt wd, wd
shr mxd, 16
sub srcq, 3
- vpbroadcastd m10, [r7+mxq*8+subpel_filters-prep_avx512icl+0]
- vpbroadcastd m11, [r7+mxq*8+subpel_filters-prep_avx512icl+4]
- movzx mxd, myb
- shr myd, 16
- cmp hd, 4
- cmove myd, mxd
- tzcnt wd, wd
- vpbroadcastd m8, [pd_2]
- movzx wd, word [r7+wq*2+table_offset(prep, _8tap_hv)]
- vpbroadcastd m9, [pd_32]
+ movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)]
+ vpbroadcastd m8, [base+subpel_filters+mxq*8+0]
+ vpbroadcastd m9, [base+subpel_filters+mxq*8+4]
add wq, r7
- vpbroadcastq m0, [r7+myq*8+subpel_filters-prep_avx512icl]
- lea stride3q, [strideq*3]
- sub srcq, stride3q
- punpcklbw m0, m0
- psraw m0, 8 ; sign-extend
- pshufd m12, m0, q0000
- pshufd m13, m0, q1111
- pshufd m14, m0, q2222
- pshufd m15, m0, q3333
jmp wq
-.hv_w4:
+.h_w4:
+ movzx mxd, mxb
+ vbroadcasti128 ym5, [subpel_h_shufA]
+ mov r3d, 0x4
+ dec srcq
+ vpbroadcastd ym6, [base+subpel_filters+mxq*8+2]
+ kmovb k1, r3d
+ lea stride3q, [strideq*3]
+.h_w4_loop:
+ movq xm2, [srcq+strideq*0]
+ movq xm3, [srcq+strideq*1]
+ vpbroadcastq ym2{k1}, [srcq+strideq*2]
+ vpbroadcastq ym3{k1}, [srcq+stride3q ]
+ lea srcq, [srcq+strideq*4]
+ pshufb ym2, ym5
+ pshufb ym3, ym5
+ mova ym0, ym4
+ vpdpbusd ym0, ym2, ym6
+ mova ym1, ym4
+ vpdpbusd ym1, ym3, ym6
+ packssdw ym0, ym1
+ psraw ym0, 2
+ mova [tmpq], ym0
+ add tmpq, 32
+ sub hd, 4
+ jg .h_w4_loop
+ RET
+.h_w8:
+ vbroadcasti128 m5, [subpel_h_shufA]
+ vbroadcasti128 m6, [subpel_h_shufB]
+ vbroadcasti128 m7, [subpel_h_shufC]
+ lea stride3q, [strideq*3]
+.h_w8_loop:
+ movu xmm3, [srcq+strideq*0]
+ vinserti128 ym3, ymm3, [srcq+strideq*1], 1
+ vinserti128 m3, [srcq+strideq*2], 2
+ vinserti128 m3, [srcq+stride3q ], 3
+ lea srcq, [srcq+strideq*4]
+ pshufb m1, m3, m5
+ pshufb m2, m3, m6
+ mova m0, m4
+ vpdpbusd m0, m1, m8
+ mova m1, m4
+ vpdpbusd m1, m2, m8
+ pshufb m3, m7
+ vpdpbusd m0, m2, m9
+ vpdpbusd m1, m3, m9
+ packssdw m0, m1
+ psraw m0, 2
+ mova [tmpq], m0
+ add tmpq, 64
+ sub hd, 4
+ jg .h_w8_loop
+ RET
+.h_w16:
+ mova m5, [spel_h_perm16]
+ vpbroadcastd m7, [pb_4]
+ lea stride3q, [strideq*3]
+ paddb m6, m7, m5
+ paddb m7, m6
+.h_w16_loop:
+ movu ym0, [srcq+strideq*0]
+ movu ym1, [srcq+strideq*2]
+ vinserti32x8 m0, [srcq+strideq*1], 1
+ vinserti32x8 m1, [srcq+stride3q ], 1
+ lea srcq, [srcq+strideq*4]
+ PREP_8TAP_H
+ add tmpq, 64*2
+ sub hd, 4
+ jg .h_w16_loop
+ RET
+.h_w32:
+ mova m5, [spel_h_perm32]
+ vpbroadcastd m7, [pb_4]
+ paddb m6, m7, m5
+ paddb m7, m6
+.h_w32_loop:
+ movu m0, [srcq+strideq*0]
+ movu m1, [srcq+strideq*1]
+ lea srcq, [srcq+strideq*2]
+ PREP_8TAP_H
+ add tmpq, 64*2
+ sub hd, 2
+ jg .h_w32_loop
+ RET
+.h_w64:
+ xor r6d, r6d
+ jmp .h_start
+.h_w128:
+ mov r6, -64*1
+.h_start:
+ mova m5, [spel_h_perm32]
+ vpbroadcastd m7, [pb_4]
+ sub srcq, r6
+ paddb m6, m7, m5
+ paddb m7, m6
+.h_loop0:
+ mov r5, r6
+.h_loop:
+ movu m0, [srcq+r5+32*0]
+ movu m1, [srcq+r5+32*1]
+ PREP_8TAP_H
+ add tmpq, 64*2
+ add r5, 64
+ jle .h_loop
+ add srcq, strideq
+ dec hd
+ jg .h_loop0
+ RET
+.hv:
+ RESET_STACK_STATE
+ vpbroadcastd m8, [pd_2]
+ vpbroadcastd m9, [pd_32]
+ cmp wd, 4
+ jg .hv_w8
movzx mxd, mxb
dec srcq
- vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep_avx512icl+2]
+ vpbroadcastd m11, [base+subpel_filters+mxq*8+2]
movzx mxd, myb
shr myd, 16
cmp hd, 4
cmove myd, mxd
- vpbroadcastq m0, [r7+myq*8+subpel_filters-prep_avx512icl]
+ vpbroadcastq m0, [base+subpel_filters+myq*8]
lea stride3q, [strideq*3]
sub srcq, stride3q
mov r3d, 0x04
kmovb k1, r3d
kshiftlb k2, k1, 2
kshiftlb k3, k1, 4
- vpbroadcastd m10, [pd_2]
- vbroadcasti128 m16, [subpel_h_shufA]
+ vbroadcasti128 m10, [subpel_h_shufA]
punpcklbw m0, m0
psraw m0, 8 ; sign-extend
- vpbroadcastd m11, [pd_32]
pshufd m12, m0, q0000
pshufd m13, m0, q1111
pshufd m14, m0, q2222
@@ -2910,263 +3897,265 @@ cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3
vpbroadcastq m3{k2}, [srcq+strideq*0]
vpbroadcastq m2{k3}, [srcq+strideq*1]
vpbroadcastq m3{k3}, [srcq+strideq*2]
- mova m17, [spel_hv_perm4a]
- movu m18, [spel_hv_perm4b]
- mova m0, m10
- mova m1, m10
- pshufb m2, m16
- pshufb m3, m16
- vpdpbusd m0, m2, m8
- vpdpbusd m1, m3, m8
+ mova m6, [spel_hv_perm4a]
+ movu m7, [spel_hv_perm4b]
+ mova m0, m8
+ mova m1, m8
+ pshufb m2, m10
+ pshufb m3, m10
+ vpdpbusd m0, m2, m11
+ vpdpbusd m1, m3, m11
packssdw m0, m1 ; _ 0 1 2 3 4 5 6
psraw m0, 2
- vpermb m1, m17, m0 ; 01 12 23 34
- vpermb m2, m18, m0 ; 23 34 45 56
+ vpermb m1, m6, m0 ; 01 12 23 34
+ vpermb m2, m7, m0 ; 23 34 45 56
.hv_w4_loop:
movq xm3, [srcq+stride3q ]
lea srcq, [srcq+strideq*4]
movq xm4, [srcq+strideq*0]
vpbroadcastq ym3{k1}, [srcq+strideq*1]
vpbroadcastq ym4{k1}, [srcq+strideq*2]
- mova ym5, ym10
- mova ym6, ym10
- pshufb ym3, ym16
- pshufb ym4, ym16
- vpdpbusd ym5, ym3, ym8
- vpdpbusd ym6, ym4, ym8
- mova m7, m11
- packssdw ym5, ym6 ; 7 8 9 a _ _ _ _
- psraw ym5, 2
- valignq m0, m5, m0, 4 ; _ 4 5 6 7 8 9 a
- vpdpwssd m7, m1, m12
- vpdpwssd m7, m2, m13
- vpermb m1, m17, m0 ; 45 56 67 78
- vpermb m2, m18, m0 ; 67 78 89 9a
- vpdpwssd m7, m1, m14
- vpdpwssd m7, m2, m15
- psrad m7, 6
- vpmovdw [tmpq], m7
+ mova m5, m9
+ pshufb ym3, ym10
+ vpdpwssd m5, m1, m12 ; a0 b0 c0 d0
+ mova ym1, ym8
+ pshufb ym4, ym10
+ vpdpbusd ym1, ym3, ym11
+ mova ym3, ym8
+ vpdpbusd ym3, ym4, ym11
+ vpdpwssd m5, m2, m13 ; a1 b1 c1 d1
+ packssdw ym1, ym3 ; 7 8 9 a
+ psraw ym1, 2
+ vshufi32x4 m0, m1, q1032 ; _ 4 5 6 7 8 9 a
+ vpermb m1, m6, m0 ; 45 56 67 78
+ vpermb m2, m7, m0 ; 67 78 89 9a
+ vpdpwssd m5, m1, m14 ; a2 b2 c2 d2
+ vpdpwssd m5, m2, m15 ; a3 b3 c3 d3
+ psrad m5, 6
+ vpmovdw [tmpq], m5
add tmpq, 32
sub hd, 4
jg .hv_w4_loop
- vzeroupper
RET
.hv_w8:
- WIN64_SPILL_XMM 24
- vbroadcasti128 m16, [subpel_h_shufA]
- vbroadcasti128 m17, [subpel_h_shufB]
- vbroadcasti128 m18, [subpel_h_shufC]
- vinserti128 ym0, [srcq+strideq*0], 1
- vinserti128 m0, [srcq+strideq*1], 2
- vinserti128 m0, [srcq+strideq*2], 3
- movu xm1, [srcq+stride3q ]
+ shr mxd, 16
+ sub srcq, 3
+ vpbroadcastd m10, [base+subpel_filters+mxq*8+0]
+ vpbroadcastd m11, [base+subpel_filters+mxq*8+4]
+ movzx mxd, myb
+ shr myd, 16
+ cmp hd, 4
+ cmove myd, mxd
+ vpbroadcastq m0, [base+subpel_filters+myq*8]
+ lea stride3q, [strideq*3]
+ sub srcq, stride3q
+ punpcklbw m0, m0
+ psraw m0, 8 ; sign-extend
+ pshufd m12, m0, q0000
+ pshufd m13, m0, q1111
+ pshufd m14, m0, q2222
+ pshufd m15, m0, q3333
+ cmp wd, 8
+ jg .hv_w16
+ vbroadcasti32x4 m17, [srcq+stride3q ]
+ vinserti32x4 m16, m17, [srcq+strideq*0], 0
+ vbroadcasti32x4 m19, [subpel_h_shufA]
+ vinserti32x4 m16, [srcq+strideq*1], 1
+ vbroadcasti32x4 m21, [subpel_h_shufC]
+ vinserti32x4 m16, [srcq+strideq*2], 2
lea srcq, [srcq+strideq*4]
- vinserti128 ym1, [srcq+strideq*0], 1
- vinserti128 m1, [srcq+strideq*1], 2
- vinserti128 m1, [srcq+strideq*2], 3
+ vinserti128 ym17, [srcq+strideq*0], 1
+ vbroadcasti32x4 m20, [subpel_h_shufB]
+ vinserti32x4 m17, [srcq+strideq*1], 2
+ vinserti32x4 m17, [srcq+strideq*2], 3
+ pshufb m3, m16, m19 ; 0 1 2 3 0123
mova m2, m8
- mova m4, m8
+ pshufb m0, m16, m21 ; 0 1 2 3 89ab
+ vpdpbusd m2, m3, m10
mova m3, m8
- mova m5, m8
- pshufb m20, m0, m16
- pshufb m21, m0, m17
- pshufb m22, m0, m18
- pshufb m23, m1, m16
- pshufb m6, m1, m17
- pshufb m7, m1, m18
- vpdpbusd m2, m20, m10
- vpdpbusd m4, m21, m10
- vpdpbusd m2, m21, m11
- vpdpbusd m4, m22, m11
- vpdpbusd m3, m23, m10
- vpdpbusd m5, m6, m10
- vpdpbusd m3, m6, m11
- vpdpbusd m5, m7, m11
- packssdw m2, m4
- packssdw m3, m5
- psraw m2, 2 ; _ 0 1 2
- psraw m3, 2 ; 3 4 5 6
- valignq m0, m3, m2, 2 ; 0 1 2 3
- valignq m1, m3, m2, 4 ; 1 2 3 4
- valignq m2, m3, m2, 6 ; 2 3 4 5
- punpcklwd m4, m0, m1 ; 01a 12a 23a 34a
- punpckhwd m5, m0, m1 ; 01b 12b 23b 34b
- punpcklwd m6, m2, m3 ; 23a 34a 45a 56a
- punpckhwd m7, m2, m3 ; 23b 34b 45b 56b
+ pshufb m1, m17, m19 ; 3 4 5 6 0123
+ vpdpbusd m3, m0, m11
+ mova m0, m8
+ pshufb m4, m17, m21 ; 3 4 5 6 89ab
+ vpdpbusd m0, m1, m10
+ mova m1, m8
+ pshufb m16, m20 ; 0 1 2 3 4567
+ vpdpbusd m1, m4, m11
+ pshufb m17, m20 ; 3 4 5 6 4567
+ vpdpbusd m2, m16, m11
+ vpdpbusd m3, m16, m10
+ vpdpbusd m0, m17, m11
+ vpdpbusd m1, m17, m10
+ packssdw m2, m3
+ packssdw m0, m1
+ psraw m2, 2 ; 0 1 2 3
+ psraw m0, 2 ; 3 4 5 6
+ vshufi32x4 m4, m2, m0, q2132 ; 2 3 4 5
+ vshufi32x4 m5, m2, m0, q1021 ; 1 2 3 4
+ punpcklwd m3, m4, m0 ; 23 34 45 56
+ punpckhwd m4, m0
+ punpcklwd m1, m2, m5 ; 01 12 23 34
+ punpckhwd m2, m5
.hv_w8_loop:
- movu xm19, [srcq+stride3q ]
+ movu xm18, [srcq+stride3q ]
lea srcq, [srcq+strideq*4]
- vinserti128 ym19, [srcq+strideq*0], 1
- vinserti128 m19, [srcq+strideq*1], 2
- vinserti128 m19, [srcq+strideq*2], 3
- mova m20, m9
- mova m21, m9
- mova m22, m8
- mova m23, m8
- vpdpwssd m20, m4, m12
- vpdpwssd m21, m5, m12
- vpdpwssd m20, m6, m13
- vpdpwssd m21, m7, m13
- pshufb m0, m19, m16
- pshufb m1, m19, m17
- pshufb m2, m19, m18
- vpdpbusd m22, m0, m10
- vpdpbusd m23, m1, m10
- vpdpbusd m22, m1, m11
- vpdpbusd m23, m2, m11
- packssdw m22, m23
- psraw m22, 2 ; 7 8 9 A
- valignq m0, m22, m3, 2 ; 4 5 6 7
- valignq m1, m22, m3, 4 ; 5 6 7 8
- valignq m2, m22, m3, 6 ; 6 7 8 9
- mova m3, m22
- punpcklwd m4, m0, m1 ; 45a 56a 67a 78a
- punpckhwd m5, m0, m1 ; 45b 56b 67b 78b
- punpcklwd m6, m2, m3 ; 67a 78a 89a 9Aa
- punpckhwd m7, m2, m3 ; 67b 78b 89b 9Ab
- vpdpwssd m20, m4, m14
- vpdpwssd m21, m5, m14
- vpdpwssd m20, m6, m15
- vpdpwssd m21, m7, m15
- psrad m20, 6
- psrad m21, 6
- packssdw m20, m21
- mova [tmpq], m20
+ vinserti128 ym18, [srcq+strideq*0], 1
+ vinserti32x4 m18, [srcq+strideq*1], 2
+ vinserti32x4 m18, [srcq+strideq*2], 3
+ pshufb m17, m18, m19 ; 7 8 9 a 0123
+ mova m16, m8
+ pshufb m5, m18, m21 ; 7 8 9 a 89ab
+ vpdpbusd m16, m17, m10
+ mova m17, m8
+ pshufb m18, m20 ; 7 8 9 a 4567
+ vpdpbusd m17, m5, m11
+ mova m5, m9
+ vpdpwssd m5, m3, m13 ; a1 b1 c1 d1
+ mova m6, m9
+ vpdpwssd m6, m4, m13
+ vpdpbusd m16, m18, m11
+ vpdpbusd m17, m18, m10
+ vpdpwssd m5, m1, m12 ; a0 b0 c0 d0
+ mova m1, m3
+ vpdpwssd m6, m2, m12
+ mova m2, m4
+ packssdw m16, m17
+ psraw m16, 2 ; 7 8 9 a
+ valignq m4, m16, m0, 6 ; 6 7 8 9
+ mova m0, m16
+ punpcklwd m3, m4, m16 ; 67 78 89 9a
+ punpckhwd m4, m16
+ vpdpwssd m5, m3, m15 ; a3 b3 c3 d3
+ vpdpwssd m6, m4, m15
+ vshufi32x4 m1, m3, q1032 ; 45 56 67 78
+ vshufi32x4 m2, m4, q1032
+ vpdpwssd m5, m1, m14 ; a2 b2 c2 d2
+ vpdpwssd m6, m2, m14
+ psrad m5, 6
+ psrad m6, 6
+ packssdw m5, m6
+ mova [tmpq], m5
add tmpq, 64
sub hd, 4
jg .hv_w8_loop
+ vzeroupper
RET
.hv_w16:
- mov wd, 16*2
- jmp .hv_start
-.hv_w32:
- mov wd, 32*2
- jmp .hv_start
-.hv_w64:
- mov wd, 64*2
- jmp .hv_start
-.hv_w128:
- mov wd, 128*2
-.hv_start:
- WIN64_SPILL_XMM 31
- mova m16, [spel_h_perm16a]
- mova m17, [spel_h_perm16b]
- mova m18, [spel_h_perm16c]
+ WIN64_SPILL_XMM 23
+ mova m16, [spel_h_perm16]
+ vpbroadcastd m18, [pb_4]
+ add wd, wd
+ paddb m17, m18, m16
lea r6d, [hq+wq*8-256]
- mov r5, srcq
+ paddb m18, m17
+.hv_w16_loop0:
+ movu ym19, [srcq+strideq*0]
+ vinserti32x8 m19, [srcq+strideq*1], 1
+ lea r5, [srcq+strideq*2]
+ movu ym20, [r5 +strideq*0]
+ vinserti32x8 m20, [r5 +strideq*1], 1
+ lea r5, [r5 +strideq*2]
+ movu ym21, [r5 +strideq*0]
+ vinserti32x8 m21, [r5 +strideq*1], 1
+ lea r5, [r5 +strideq*2]
+ movu ym22, [r5 +strideq*0]
mov r7, tmpq
-.hv_loop0:
- movu ym0, [srcq+strideq*0]
- vinserti32x8 m0, [srcq+strideq*1], 1
- lea srcq, [srcq+strideq*2]
- movu ym1, [srcq+strideq*0]
- vinserti32x8 m1, [srcq+strideq*1], 1
- lea srcq, [srcq+strideq*2]
- movu ym2, [srcq+strideq*0]
- vinserti32x8 m2, [srcq+strideq*1], 1
- lea srcq, [srcq+strideq*2]
- movu ym3, [srcq+strideq*0]
+ vpermb m3, m16, m19 ; 0 1 0123 89ab
+ mova m2, m8
+ vpermb m4, m18, m19 ; 0 1 89ab ghij
+ vpdpbusd m2, m3, m10
+ mova m3, m8
+ vpermb m5, m16, m20 ; 2 3 0123 89ab
+ vpdpbusd m3, m4, m11
mova m4, m8
+ vpermb m6, m18, m20 ; 2 3 89ab ghij
+ vpdpbusd m4, m5, m10
mova m5, m8
+ vpermb m7, m16, m21 ; 4 5 0123 89ab
+ vpdpbusd m5, m6, m11
mova m6, m8
+ vpermb m0, m18, m21 ; 4 5 89ab ghij
+ vpdpbusd m6, m7, m10
mova m7, m8
- vpermb m19, m16, m0
- vpermb m20, m17, m0
- vpermb m21, m18, m0
- vpermb m22, m16, m1
- vpermb m23, m17, m1
- vpermb m24, m18, m1
- vpermb m25, m16, m2
- vpermb m26, m17, m2
- vpermb m27, m18, m2
- vpermb ym28, ym16, ym3
- vpermb ym29, ym17, ym3
- vpermb ym30, ym18, ym3
- mova m0, m8
- mova m1, m8
- mova ym2, ym8
- mova ym3, ym8
- vpdpbusd m4, m19, m10
- vpdpbusd m5, m20, m10
- vpdpbusd m6, m22, m10
- vpdpbusd m7, m23, m10
- vpdpbusd m0, m25, m10
- vpdpbusd m1, m26, m10
- vpdpbusd ym2, ym28, ym10
- vpdpbusd ym3, ym29, ym10
+ vpermb ym1, ym16, ym22 ; 6 0123 89ab
+ vpdpbusd m7, m0, m11
+ mova ym0, ym8
+ vpermb m19, m17, m19 ; 0 1 4567 cdef
+ vpdpbusd ym0, ym1, ym10
+ vpermb ym1, ym18, ym22 ; 6 89ab ghij
+ vpdpbusd m2, m19, m11
+ vpdpbusd m3, m19, m10
+ mova ym19, ym8
+ vpermb m20, m17, m20 ; 2 3 4567 cdef
+ vpdpbusd ym19, ym1, ym11
+ vpermb m21, m17, m21 ; 4 5 4567 cdef
vpdpbusd m4, m20, m11
- vpdpbusd m5, m21, m11
- vpdpbusd m6, m23, m11
- vpdpbusd m7, m24, m11
- vpdpbusd m0, m26, m11
- vpdpbusd m1, m27, m11
- vpdpbusd ym2, ym29, ym11
- vpdpbusd ym3, ym30, ym11
- packssdw m4, m5
- packssdw m6, m7
- packssdw m0, m1
- packssdw ym2, ym3
- psraw m4, 2 ; 0a 0b 1a 1b
- psraw m6, 2 ; 2a 2b 3a 3b
- psraw m0, 2 ; 4a 4b 5a 5b
- psraw ym2, 2 ; 6a 6b __ __
- vshufi32x4 m5, m4, m6, q1032 ; 1a 1b 2a 2b
- vshufi32x4 m7, m6, m0, q1032 ; 3a 3b 4a 4b
- vshufi32x4 m1, m0, m2, q1032 ; 5a 5b 6a 6b
- punpcklwd m2, m4, m5 ; 01a 01c 12a 12c
- punpckhwd m3, m4, m5 ; 01b 01d 12b 12d
- punpcklwd m4, m6, m7 ; 23a 23c 34a 34c
- punpckhwd m5, m6, m7 ; 23b 23d 34b 34d
- punpcklwd m6, m0, m1 ; 45a 45c 56a 56c
- punpckhwd m7, m0, m1 ; 45b 45d 56b 56d
-.hv_loop:
- movu ym19, [srcq+strideq*1]
- lea srcq, [srcq+strideq*2]
- vinserti32x8 m19, [srcq+strideq*0], 1
+ vpdpbusd m5, m20, m10
+ vpermb ym22, ym17, ym22 ; 6 4567 cdef
+ vpdpbusd m6, m21, m11
+ vpdpbusd m7, m21, m10
+ packssdw m2, m3 ; 0 1
+ vpdpbusd ym0, ym22, ym11
+ packssdw m4, m5 ; 2 3
+ vpdpbusd ym19, ym22, ym10
+ packssdw m6, m7 ; 4 5
+ packssdw ym0, ym19 ; 6
+ REPX {psraw x, 2}, m2, m4, m6, ym0
+ vshufi32x4 m3, m2, m4, q1032 ; 1 2
+ vshufi32x4 m5, m4, m6, q1032 ; 3 4
+ vshufi32x4 m0, m6, m0, q1032 ; 5 6
+ punpcklwd m1, m2, m3 ; 01 12
+ punpckhwd m2, m3
+ punpcklwd m3, m4, m5 ; 23 34
+ punpckhwd m4, m5
+ punpcklwd m5, m6, m0 ; 45 56
+ punpckhwd m6, m0
+.hv_w16_loop:
+ movu ym19, [r5+strideq*1]
+ lea r5, [r5+strideq*2]
+ vinserti32x8 m19, [r5+strideq*0], 1
mova m20, m9
+ vpdpwssd m20, m1, m12 ; a0
+ vpermb m1, m16, m19
mova m21, m9
+ vpdpwssd m21, m2, m12 ; b0
+ vpermb m2, m17, m19
mova m22, m8
- mova m23, m8
- vpdpwssd m20, m2, m12
- vpdpwssd m21, m3, m12
- vpdpwssd m20, m4, m13
- vpdpwssd m21, m5, m13
- vpermb m24, m16, m19
- vpermb m25, m17, m19
- vpermb m26, m18, m19
- vpdpbusd m22, m24, m10
- vpdpbusd m23, m25, m10
- vpdpbusd m22, m25, m11
- vpdpbusd m23, m26, m11
- packssdw m22, m23
- psraw m22, 2 ; 7a 7b 8a 8b
- vshufi32x4 m0, m1, m22, q1032 ; 6a 6b 7a 7b
+ vpdpbusd m22, m1, m10
+ mova m1, m8
+ vpermb m19, m18, m19
+ vpdpbusd m1, m2, m10
+ vpdpwssd m20, m3, m13 ; a1
+ vpdpwssd m21, m4, m13 ; b1
+ vpdpbusd m22, m2, m11
mova m2, m4
- mova m3, m5
- mova m1, m22
+ vpdpbusd m1, m19, m11
mova m4, m6
- mova m5, m7
- punpcklwd m6, m0, m1 ; 67a 67c 78a 78c
- punpckhwd m7, m0, m1 ; 67b 67d 78b 78d
- vpdpwssd m20, m4, m14
- vpdpwssd m21, m5, m14
- vpdpwssd m20, m6, m15
- vpdpwssd m21, m7, m15
+ vpdpwssd m20, m5, m14 ; a2
+ vpdpwssd m21, m6, m14 ; b2
+ packssdw m22, m1
+ mova m1, m3
+ psraw m22, 2 ; 7 8
+ mova m3, m5
+ vshufi32x4 m6, m0, m22, q1032 ; 6 7
+ mova m0, m22
+ punpcklwd m5, m6, m0 ; 67 78
+ punpckhwd m6, m0
+ vpdpwssd m20, m5, m15 ; a3
+ vpdpwssd m21, m6, m15 ; b3
psrad m20, 6
psrad m21, 6
packssdw m20, m21
- mova [tmpq+wq*0], ym20
- vextracti32x8 [tmpq+wq*1], m20, 1
- lea tmpq, [tmpq+wq*2]
+ mova [r7+wq*0], ym20
+ vextracti32x8 [r7+wq*1], m20, 1
+ lea r7, [r7+wq*2]
sub hd, 2
- jg .hv_loop
- add r5, 16
- add r7, 32
+ jg .hv_w16_loop
+ add srcq, 16
+ add tmpq, 32
movzx hd, r6b
- mov srcq, r5
- mov tmpq, r7
sub r6d, 1<<8
- jg .hv_loop0
+ jg .hv_w16_loop0
RET
cglobal warp_affine_8x8t_8bpc, 4, 7, 22, tmp, ts
diff --git a/third_party/dav1d/tests/meson.build b/third_party/dav1d/tests/meson.build
index 11db0a56e9..38a591b5b4 100644
--- a/third_party/dav1d/tests/meson.build
+++ b/third_party/dav1d/tests/meson.build
@@ -100,7 +100,7 @@ if is_asm_enabled
],
)
- test('checkasm', checkasm, suite: 'checkasm', timeout: 180, is_parallel: false)
+ test('checkasm', checkasm, suite: 'checkasm', timeout: 180)
benchmark('checkasm', checkasm, suite: 'checkasm', timeout: 3600, args: '--bench')
endif
diff --git a/third_party/gemmology/gemmology.h b/third_party/gemmology/gemmology.h
index eb5ebed3b4..21004d2709 100644
--- a/third_party/gemmology/gemmology.h
+++ b/third_party/gemmology/gemmology.h
@@ -786,7 +786,6 @@ public:
using batch8 = xsimd::batch<int8_t, Arch>;
using batch16 = xsimd::batch<int16_t, Arch>;
using batch32 = xsimd::batch<int32_t, Arch>;
- using ubatch32 = xsimd::batch<uint32_t, Arch>;
// Put higher rows in the second half of the register. These will jumble
// around in the same way then conveniently land in the right place.
@@ -814,7 +813,7 @@ public:
return xsimd::bitwise_cast<int8_t>(
xsimd::swizzle(xsimd::bitwise_cast<int32_t>(packed),
- xsimd::make_batch_constant<ubatch32, Tiler<Arch>>()));
+ xsimd::make_batch_constant<uint32_t, Arch, Tiler<Arch>>()));
} else if constexpr (batchf32::size == 8)
return Tile(quant_mult, input, input + 2 * cols, input + 16 * cols,
input + 18 * cols);
@@ -833,7 +832,6 @@ public:
using batch8 = xsimd::batch<int8_t, Arch>;
using batch16 = xsimd::batch<int16_t, Arch>;
using batch32 = xsimd::batch<int32_t, Arch>;
- using ubatch32 = xsimd::batch<uint32_t, Arch>;
const batch8 neg127(-127);
// Grab 4 registers at a time in 32-bit format.
@@ -857,7 +855,7 @@ public:
// and the values are only used for GEMM.
return xsimd::bitwise_cast<int8_t>(
xsimd::swizzle(xsimd::bitwise_cast<int32_t>(packed),
- xsimd::make_batch_constant<ubatch32, Tiler<Arch>>()));
+ xsimd::make_batch_constant<uint32_t, Arch, Tiler<Arch>>()));
}
private:
@@ -869,7 +867,6 @@ private:
using batch8 = xsimd::batch<int8_t, Arch>;
using batch16 = xsimd::batch<int16_t, Arch>;
using batch32 = xsimd::batch<int32_t, Arch>;
- using ubatch32 = xsimd::batch<uint32_t, Arch>;
const batch8 neg127 = -127;
const batch8 pos127 = +127;
@@ -894,7 +891,7 @@ private:
// and the values are only used for GEMM.
return xsimd::bitwise_cast<uint8_t>(
xsimd::swizzle(xsimd::bitwise_cast<int32_t>(packed),
- xsimd::make_batch_constant<ubatch32, Tiler<Arch>>()));
+ xsimd::make_batch_constant<uint32_t, Arch, Tiler<Arch>>()));
}
};
diff --git a/third_party/gemmology/moz.yaml b/third_party/gemmology/moz.yaml
index 749227e2ee..bb99db1a39 100644
--- a/third_party/gemmology/moz.yaml
+++ b/third_party/gemmology/moz.yaml
@@ -10,8 +10,8 @@ origin:
url: https://github.com/mozilla/gemmology
- release: dbcd029c3bc6e183355ea597216d379677ff9b19 (2024-02-20T12:36:14Z).
- revision: dbcd029c3bc6e183355ea597216d379677ff9b19
+ release: a37d922a88ded67a0b741f16390821000fde99ee (2024-04-17T11:18:45Z).
+ revision: a37d922a88ded67a0b741f16390821000fde99ee
license: MIT
diff --git a/third_party/jpeg-xl/AUTHORS b/third_party/jpeg-xl/AUTHORS
index ed6d72db66..3f3675858d 100644
--- a/third_party/jpeg-xl/AUTHORS
+++ b/third_party/jpeg-xl/AUTHORS
@@ -39,6 +39,7 @@ Alistair Barrow
Andrius Lukas Narbutas <andrius4669@gmail.com>
Aous Naman <aous@unsw.edu.au>
Artem Selishchev
+Aryan Pingle <realaryanpingle@gmail.com>
Biswapriyo Nath <nathbappai@gmail.com>
CanadianBaconBoi <beamconnor@gmail.com>
Damiano Albani <damiano.albani@gmail.com>
@@ -53,6 +54,7 @@ Dong Xu <xdong181@gmail.com>
estrogently <41487185+estrogently@users.noreply.github.com>
Even Rouault <even.rouault@spatialys.com>
Fred Brennan <copypaste@kittens.ph>
+Gerhard Huber <support@pl32.com>
gi-man
Gilles Devillers (GilDev) <gildev@gmail.com>
Heiko Becker <heirecka@exherbo.org>
diff --git a/third_party/jpeg-xl/CMakeLists.txt b/third_party/jpeg-xl/CMakeLists.txt
index 9b74537f1c..ea8ccc43ba 100644
--- a/third_party/jpeg-xl/CMakeLists.txt
+++ b/third_party/jpeg-xl/CMakeLists.txt
@@ -160,7 +160,7 @@ set(JPEGXL_ENABLE_AVX512_SPR false CACHE BOOL
"Build with AVX-512FP16 support (faster on CPUs that support it, but larger binary size).")
set(JPEGXL_ENABLE_AVX512_ZEN4 false CACHE BOOL
"Build with Zen4-optimized AVX512 support (faster on CPUs that support it, but larger binary size).")
-set(JPEGXL_ENABLE_WASM_TRHEADS true CACHE BOOL
+set(JPEGXL_ENABLE_WASM_THREADS true CACHE BOOL
"Builds WASM modules with threads support")
# Force system dependencies.
@@ -211,10 +211,12 @@ if(JPEGXL_STATIC)
# Clang developers say that in case to use "static" we have to build stdlib
# ourselves; for real use case we don't care about stdlib, as it is "granted",
# so just linking all other libraries is fine.
- if (NOT MSVC AND NOT APPLE)
+ if (NOT MSVC)
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -static")
+ endif()
+ if ((NOT WIN32 AND NOT APPLE) OR CYGWIN OR MINGW)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
- set(CMAKE_EXE_LINKER_FLAGS
- "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -static-libgcc -static-libstdc++")
endif()
endif() # JPEGXL_STATIC
@@ -265,7 +267,7 @@ if(JPEGXL_STATIC)
endif()
endif() # JPEGXL_STATIC
-if (EMSCRIPTEN AND JPEGXL_ENABLE_WASM_TRHEADS)
+if (EMSCRIPTEN AND JPEGXL_ENABLE_WASM_THREADS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
diff --git a/third_party/jpeg-xl/examples/decode_progressive.cc b/third_party/jpeg-xl/examples/decode_progressive.cc
index 2cdc175e8a..7a3a9aa33b 100644
--- a/third_party/jpeg-xl/examples/decode_progressive.cc
+++ b/third_party/jpeg-xl/examples/decode_progressive.cc
@@ -10,16 +10,16 @@
#define __STDC_FORMAT_MACROS
#endif
-#include <inttypes.h>
#include <jxl/decode.h>
#include <jxl/decode_cxx.h>
#include <jxl/resizable_parallel_runner.h>
#include <jxl/resizable_parallel_runner_cxx.h>
#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
+#include <cinttypes> // PRIu64
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
#include <vector>
bool WritePAM(const char* filename, const uint8_t* buffer, size_t w, size_t h) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/apng.cc b/third_party/jpeg-xl/lib/extras/dec/apng.cc
index c607a71d08..824a6f47ee 100644
--- a/third_party/jpeg-xl/lib/extras/dec/apng.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/apng.cc
@@ -38,8 +38,10 @@
#include <jxl/codestream_header.h>
#include <jxl/encode.h>
-#include <string.h>
+#include <array>
+#include <cstdint>
+#include <cstring>
#include <string>
#include <utility>
#include <vector>
@@ -49,8 +51,7 @@
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/printf_macros.h"
-#include "lib/jxl/base/scope_guard.h"
-#include "lib/jxl/sanitizers.h"
+#include "lib/jxl/base/span.h"
#if JPEGXL_ENABLE_APNG
#include "png.h" /* original (unpatched) libpng is ok */
#endif
@@ -58,39 +59,49 @@
namespace jxl {
namespace extras {
-#if JPEGXL_ENABLE_APNG
+#if !JPEGXL_ENABLE_APNG
+
+bool CanDecodeAPNG() { return false; }
+Status DecodeImageAPNG(const Span<const uint8_t> bytes,
+ const ColorHints& color_hints, PackedPixelFile* ppf,
+ const SizeConstraints* constraints) {
+ return false;
+}
+
+#else // JPEGXL_ENABLE_APNG
+
namespace {
-constexpr unsigned char kExifSignature[6] = {0x45, 0x78, 0x69,
- 0x66, 0x00, 0x00};
+constexpr uint8_t kExifSignature[6] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
/* hIST chunk tail is not proccesed properly; skip this chunk completely;
see https://github.com/glennrp/libpng/pull/413 */
-const png_byte kIgnoredPngChunks[] = {
- 104, 73, 83, 84, '\0' /* hIST */
-};
+const uint8_t kIgnoredPngChunks[] = {'h', 'I', 'S', 'T', '\0'};
// Returns floating-point value from the PNG encoding (times 10^5).
double F64FromU32(const uint32_t x) { return static_cast<int32_t>(x) * 1E-5; }
-Status DecodeSRGB(const unsigned char* payload, const size_t payload_size,
- JxlColorEncoding* color_encoding) {
- if (payload_size != 1) return JXL_FAILURE("Wrong sRGB size");
+/** Extract information from 'sRGB' chunk. */
+Status DecodeSrgbChunk(const Bytes payload, JxlColorEncoding* color_encoding) {
+ if (payload.size() != 1) return JXL_FAILURE("Wrong sRGB size");
+ uint8_t ri = payload[0];
// (PNG uses the same values as ICC.)
- if (payload[0] >= 4) return JXL_FAILURE("Invalid Rendering Intent");
+ if (ri >= 4) return JXL_FAILURE("Invalid Rendering Intent");
color_encoding->white_point = JXL_WHITE_POINT_D65;
color_encoding->primaries = JXL_PRIMARIES_SRGB;
color_encoding->transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
- color_encoding->rendering_intent =
- static_cast<JxlRenderingIntent>(payload[0]);
+ color_encoding->rendering_intent = static_cast<JxlRenderingIntent>(ri);
return true;
}
-// If the cICP profile is not fully supported, return false and leave
-// color_encoding unmodified.
-Status DecodeCICP(const unsigned char* payload, const size_t payload_size,
- JxlColorEncoding* color_encoding) {
- if (payload_size != 4) return JXL_FAILURE("Wrong cICP size");
+/**
+ * Extract information from 'cICP' chunk.
+ *
+ * If the cICP profile is not fully supported, return `false` and leave
+ * `color_encoding` unmodified.
+ */
+Status DecodeCicpChunk(const Bytes payload, JxlColorEncoding* color_encoding) {
+ if (payload.size() != 4) return JXL_FAILURE("Wrong cICP size");
JxlColorEncoding color_enc = *color_encoding;
// From https://www.itu.int/rec/T-REC-H.273-202107-I/en
@@ -217,257 +228,279 @@ Status DecodeCICP(const unsigned char* payload, const size_t payload_size,
return true;
}
-Status DecodeGAMA(const unsigned char* payload, const size_t payload_size,
- JxlColorEncoding* color_encoding) {
- if (payload_size != 4) return JXL_FAILURE("Wrong gAMA size");
+/** Extract information from 'gAMA' chunk. */
+Status DecodeGamaChunk(Bytes payload, JxlColorEncoding* color_encoding) {
+ if (payload.size() != 4) return JXL_FAILURE("Wrong gAMA size");
color_encoding->transfer_function = JXL_TRANSFER_FUNCTION_GAMMA;
- color_encoding->gamma = F64FromU32(LoadBE32(payload));
+ color_encoding->gamma = F64FromU32(LoadBE32(payload.data()));
return true;
}
-Status DecodeCHRM(const unsigned char* payload, const size_t payload_size,
- JxlColorEncoding* color_encoding) {
- if (payload_size != 32) return JXL_FAILURE("Wrong cHRM size");
-
+/** Extract information from 'cHTM' chunk. */
+Status DecodeChrmChunk(Bytes payload, JxlColorEncoding* color_encoding) {
+ if (payload.size() != 32) return JXL_FAILURE("Wrong cHRM size");
+ const uint8_t* data = payload.data();
color_encoding->white_point = JXL_WHITE_POINT_CUSTOM;
- color_encoding->white_point_xy[0] = F64FromU32(LoadBE32(payload + 0));
- color_encoding->white_point_xy[1] = F64FromU32(LoadBE32(payload + 4));
+ color_encoding->white_point_xy[0] = F64FromU32(LoadBE32(data + 0));
+ color_encoding->white_point_xy[1] = F64FromU32(LoadBE32(data + 4));
color_encoding->primaries = JXL_PRIMARIES_CUSTOM;
- color_encoding->primaries_red_xy[0] = F64FromU32(LoadBE32(payload + 8));
- color_encoding->primaries_red_xy[1] = F64FromU32(LoadBE32(payload + 12));
- color_encoding->primaries_green_xy[0] = F64FromU32(LoadBE32(payload + 16));
- color_encoding->primaries_green_xy[1] = F64FromU32(LoadBE32(payload + 20));
- color_encoding->primaries_blue_xy[0] = F64FromU32(LoadBE32(payload + 24));
- color_encoding->primaries_blue_xy[1] = F64FromU32(LoadBE32(payload + 28));
+ color_encoding->primaries_red_xy[0] = F64FromU32(LoadBE32(data + 8));
+ color_encoding->primaries_red_xy[1] = F64FromU32(LoadBE32(data + 12));
+ color_encoding->primaries_green_xy[0] = F64FromU32(LoadBE32(data + 16));
+ color_encoding->primaries_green_xy[1] = F64FromU32(LoadBE32(data + 20));
+ color_encoding->primaries_blue_xy[0] = F64FromU32(LoadBE32(data + 24));
+ color_encoding->primaries_blue_xy[1] = F64FromU32(LoadBE32(data + 28));
return true;
}
-// Retrieves XMP and EXIF/IPTC from itext and text.
-class BlobsReaderPNG {
- public:
- static Status Decode(const png_text_struct& info, PackedMetadata* metadata) {
- // We trust these are properly null-terminated by libpng.
- const char* key = info.key;
- const char* value = info.text;
- if (strstr(key, "XML:com.adobe.xmp")) {
- metadata->xmp.resize(strlen(value)); // safe, see above
- memcpy(metadata->xmp.data(), value, metadata->xmp.size());
- }
-
- std::string type;
- std::vector<uint8_t> bytes;
-
- // Handle text chunks annotated with key "Raw profile type ####", with
- // #### a type, which may contain metadata.
- const char* kKey = "Raw profile type ";
- if (strncmp(key, kKey, strlen(kKey)) != 0) return false;
+/** Returns false if invalid. */
+JXL_INLINE Status DecodeHexNibble(const char c, uint32_t* JXL_RESTRICT nibble) {
+ if ('a' <= c && c <= 'f') {
+ *nibble = 10 + c - 'a';
+ } else if ('0' <= c && c <= '9') {
+ *nibble = c - '0';
+ } else {
+ *nibble = 0;
+ return JXL_FAILURE("Invalid metadata nibble");
+ }
+ JXL_ASSERT(*nibble < 16);
+ return true;
+}
- if (!MaybeDecodeBase16(key, value, &type, &bytes)) {
- JXL_WARNING("Couldn't parse 'Raw format type' text chunk");
- return false;
- }
- if (type == "exif") {
- // Remove "Exif\0\0" prefix if present
- if (bytes.size() >= sizeof kExifSignature &&
- memcmp(bytes.data(), kExifSignature, sizeof kExifSignature) == 0) {
- bytes.erase(bytes.begin(), bytes.begin() + sizeof kExifSignature);
- }
- if (!metadata->exif.empty()) {
- JXL_WARNING("overwriting EXIF (%" PRIuS " bytes) with base16 (%" PRIuS
- " bytes)",
- metadata->exif.size(), bytes.size());
- }
- metadata->exif = std::move(bytes);
- } else if (type == "iptc") {
- // TODO(jon): Deal with IPTC in some way
- } else if (type == "8bim") {
- // TODO(jon): Deal with 8bim in some way
- } else if (type == "xmp") {
- if (!metadata->xmp.empty()) {
- JXL_WARNING("overwriting XMP (%" PRIuS " bytes) with base16 (%" PRIuS
- " bytes)",
- metadata->xmp.size(), bytes.size());
+/** Returns false if invalid. */
+JXL_INLINE Status DecodeDecimal(const char** pos, const char* end,
+ uint32_t* JXL_RESTRICT value) {
+ size_t len = 0;
+ *value = 0;
+ while (*pos < end) {
+ char next = **pos;
+ if (next >= '0' && next <= '9') {
+ *value = (*value * 10) + static_cast<uint32_t>(next - '0');
+ len++;
+ if (len > 8) {
+ break;
}
- metadata->xmp = std::move(bytes);
} else {
- JXL_WARNING("Unknown type in 'Raw format type' text chunk: %s: %" PRIuS
- " bytes",
- type.c_str(), bytes.size());
+ // Do not consume terminator (non-decimal digit).
+ break;
}
- return true;
+ (*pos)++;
+ }
+ if (len == 0 || len > 8) {
+ return JXL_FAILURE("Failed to parse decimal");
}
+ return true;
+}
- private:
- // Returns false if invalid.
- static JXL_INLINE Status DecodeNibble(const char c,
- uint32_t* JXL_RESTRICT nibble) {
- if ('a' <= c && c <= 'f') {
- *nibble = 10 + c - 'a';
- } else if ('0' <= c && c <= '9') {
- *nibble = c - '0';
- } else {
- *nibble = 0;
- return JXL_FAILURE("Invalid metadata nibble");
+/**
+ * Parses a PNG text chunk with key of the form "Raw profile type ####", with
+ * #### a type.
+ *
+ * Returns whether it could successfully parse the content.
+ * We trust key and encoded are null-terminated because they come from
+ * libpng.
+ */
+Status MaybeDecodeBase16(const char* key, const char* encoded,
+ std::string* type, std::vector<uint8_t>* bytes) {
+ const char* encoded_end = encoded + strlen(encoded);
+
+ const char* kKey = "Raw profile type ";
+ if (strncmp(key, kKey, strlen(kKey)) != 0) return false;
+ *type = key + strlen(kKey);
+ const size_t kMaxTypeLen = 20;
+ if (type->length() > kMaxTypeLen) return false; // Type too long
+
+ // Header: freeform string and number of bytes
+ // Expected format is:
+ // \n
+ // profile name/description\n
+ // 40\n (the number of bytes after hex-decoding)
+ // 01234566789abcdef....\n (72 bytes per line max).
+ // 012345667\n (last line)
+ const char* pos = encoded;
+
+ if (*(pos++) != '\n') return false;
+ while (pos < encoded_end && *pos != '\n') {
+ pos++;
+ }
+ if (pos == encoded_end) return false;
+ // We parsed so far a \n, some number of non \n characters and are now
+ // pointing at a \n.
+ if (*(pos++) != '\n') return false;
+ // Skip leading spaces
+ while (pos < encoded_end && *pos == ' ') {
+ pos++;
+ }
+ uint32_t bytes_to_decode = 0;
+ JXL_RETURN_IF_ERROR(DecodeDecimal(&pos, encoded_end, &bytes_to_decode));
+
+ // We need 2*bytes for the hex values plus 1 byte every 36 values,
+ // plus terminal \n for length.
+ size_t tail = static_cast<size_t>(encoded_end - pos);
+ bool ok = ((tail / 2) >= bytes_to_decode);
+ if (ok) tail -= 2 * static_cast<size_t>(bytes_to_decode);
+ ok = ok && (tail == 1 + DivCeil(bytes_to_decode, 36));
+ if (!ok) {
+ return JXL_FAILURE("Not enough bytes to parse %d bytes in hex",
+ bytes_to_decode);
+ }
+ JXL_ASSERT(bytes->empty());
+ bytes->reserve(bytes_to_decode);
+
+ // Encoding: base16 with newline after 72 chars.
+ // pos points to the \n before the first line of hex values.
+ for (size_t i = 0; i < bytes_to_decode; ++i) {
+ if (i % 36 == 0) {
+ if (pos + 1 >= encoded_end) return false; // Truncated base16 1
+ if (*pos != '\n') return false; // Expected newline
+ ++pos;
}
- JXL_ASSERT(*nibble < 16);
- return true;
+
+ if (pos + 2 >= encoded_end) return false; // Truncated base16 2;
+ uint32_t nibble0;
+ uint32_t nibble1;
+ JXL_RETURN_IF_ERROR(DecodeHexNibble(pos[0], &nibble0));
+ JXL_RETURN_IF_ERROR(DecodeHexNibble(pos[1], &nibble1));
+ bytes->push_back(static_cast<uint8_t>((nibble0 << 4) + nibble1));
+ pos += 2;
}
+ if (pos + 1 != encoded_end) return false; // Too many encoded bytes
+ if (pos[0] != '\n') return false; // Incorrect metadata terminator
+ return true;
+}
- // Returns false if invalid.
- static JXL_INLINE Status DecodeDecimal(const char** pos, const char* end,
- uint32_t* JXL_RESTRICT value) {
- size_t len = 0;
- *value = 0;
- while (*pos < end) {
- char next = **pos;
- if (next >= '0' && next <= '9') {
- *value = (*value * 10) + static_cast<uint32_t>(next - '0');
- len++;
- if (len > 8) {
- break;
- }
- } else {
- // Do not consume terminator (non-decimal digit).
- break;
- }
- (*pos)++;
- }
- if (len == 0 || len > 8) {
- return JXL_FAILURE("Failed to parse decimal");
- }
- return true;
+/** Retrieves XMP and EXIF/IPTC from itext and text. */
+Status DecodeBlob(const png_text_struct& info, PackedMetadata* metadata) {
+ // We trust these are properly null-terminated by libpng.
+ const char* key = info.key;
+ const char* value = info.text;
+ if (strstr(key, "XML:com.adobe.xmp")) {
+ metadata->xmp.resize(strlen(value)); // safe, see above
+ memcpy(metadata->xmp.data(), value, metadata->xmp.size());
}
- // Parses a PNG text chunk with key of the form "Raw profile type ####", with
- // #### a type.
- // Returns whether it could successfully parse the content.
- // We trust key and encoded are null-terminated because they come from
- // libpng.
- static Status MaybeDecodeBase16(const char* key, const char* encoded,
- std::string* type,
- std::vector<uint8_t>* bytes) {
- const char* encoded_end = encoded + strlen(encoded);
-
- const char* kKey = "Raw profile type ";
- if (strncmp(key, kKey, strlen(kKey)) != 0) return false;
- *type = key + strlen(kKey);
- const size_t kMaxTypeLen = 20;
- if (type->length() > kMaxTypeLen) return false; // Type too long
-
- // Header: freeform string and number of bytes
- // Expected format is:
- // \n
- // profile name/description\n
- // 40\n (the number of bytes after hex-decoding)
- // 01234566789abcdef....\n (72 bytes per line max).
- // 012345667\n (last line)
- const char* pos = encoded;
-
- if (*(pos++) != '\n') return false;
- while (pos < encoded_end && *pos != '\n') {
- pos++;
- }
- if (pos == encoded_end) return false;
- // We parsed so far a \n, some number of non \n characters and are now
- // pointing at a \n.
- if (*(pos++) != '\n') return false;
- // Skip leading spaces
- while (pos < encoded_end && *pos == ' ') {
- pos++;
+ std::string type;
+ std::vector<uint8_t> bytes;
+
+ // Handle text chunks annotated with key "Raw profile type ####", with
+ // #### a type, which may contain metadata.
+ const char* kKey = "Raw profile type ";
+ if (strncmp(key, kKey, strlen(kKey)) != 0) return false;
+
+ if (!MaybeDecodeBase16(key, value, &type, &bytes)) {
+ JXL_WARNING("Couldn't parse 'Raw format type' text chunk");
+ return false;
+ }
+ if (type == "exif") {
+ // Remove "Exif\0\0" prefix if present
+ if (bytes.size() >= sizeof kExifSignature &&
+ memcmp(bytes.data(), kExifSignature, sizeof kExifSignature) == 0) {
+ bytes.erase(bytes.begin(), bytes.begin() + sizeof kExifSignature);
}
- uint32_t bytes_to_decode = 0;
- JXL_RETURN_IF_ERROR(DecodeDecimal(&pos, encoded_end, &bytes_to_decode));
-
- // We need 2*bytes for the hex values plus 1 byte every 36 values,
- // plus terminal \n for length.
- size_t tail = static_cast<size_t>(encoded_end - pos);
- bool ok = ((tail / 2) >= bytes_to_decode);
- if (ok) tail -= 2 * static_cast<size_t>(bytes_to_decode);
- ok = ok && (tail == 1 + DivCeil(bytes_to_decode, 36));
- if (!ok) {
- return JXL_FAILURE("Not enough bytes to parse %d bytes in hex",
- bytes_to_decode);
+ if (!metadata->exif.empty()) {
+ JXL_WARNING("overwriting EXIF (%" PRIuS " bytes) with base16 (%" PRIuS
+ " bytes)",
+ metadata->exif.size(), bytes.size());
}
- JXL_ASSERT(bytes->empty());
- bytes->reserve(bytes_to_decode);
-
- // Encoding: base16 with newline after 72 chars.
- // pos points to the \n before the first line of hex values.
- for (size_t i = 0; i < bytes_to_decode; ++i) {
- if (i % 36 == 0) {
- if (pos + 1 >= encoded_end) return false; // Truncated base16 1
- if (*pos != '\n') return false; // Expected newline
- ++pos;
- }
-
- if (pos + 2 >= encoded_end) return false; // Truncated base16 2;
- uint32_t nibble0;
- uint32_t nibble1;
- JXL_RETURN_IF_ERROR(DecodeNibble(pos[0], &nibble0));
- JXL_RETURN_IF_ERROR(DecodeNibble(pos[1], &nibble1));
- bytes->push_back(static_cast<uint8_t>((nibble0 << 4) + nibble1));
- pos += 2;
+ metadata->exif = std::move(bytes);
+ } else if (type == "iptc") {
+ // TODO(jon): Deal with IPTC in some way
+ } else if (type == "8bim") {
+ // TODO(jon): Deal with 8bim in some way
+ } else if (type == "xmp") {
+ if (!metadata->xmp.empty()) {
+ JXL_WARNING("overwriting XMP (%" PRIuS " bytes) with base16 (%" PRIuS
+ " bytes)",
+ metadata->xmp.size(), bytes.size());
}
- if (pos + 1 != encoded_end) return false; // Too many encoded bytes
- if (pos[0] != '\n') return false; // Incorrect metadata terminator
- return true;
+ metadata->xmp = std::move(bytes);
+ } else {
+ JXL_WARNING("Unknown type in 'Raw format type' text chunk: %s: %" PRIuS
+ " bytes",
+ type.c_str(), bytes.size());
}
-};
+ return true;
+}
constexpr bool isAbc(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
-constexpr uint32_t kId_IHDR = 0x52444849;
-constexpr uint32_t kId_acTL = 0x4C546361;
-constexpr uint32_t kId_fcTL = 0x4C546366;
-constexpr uint32_t kId_IDAT = 0x54414449;
-constexpr uint32_t kId_fdAT = 0x54416466;
-constexpr uint32_t kId_IEND = 0x444E4549;
-constexpr uint32_t kId_cICP = 0x50434963;
-constexpr uint32_t kId_iCCP = 0x50434369;
-constexpr uint32_t kId_sRGB = 0x42475273;
-constexpr uint32_t kId_gAMA = 0x414D4167;
-constexpr uint32_t kId_cHRM = 0x4D524863;
-constexpr uint32_t kId_eXIf = 0x66495865;
-
-struct APNGFrame {
- APNGFrame() : pixels(nullptr, free) {}
- std::unique_ptr<void, decltype(free)*> pixels;
+/** Wrap 4-char tag name into ID. */
+constexpr uint32_t MakeTag(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
+ return a | (b << 8) | (c << 16) | (d << 24);
+}
+
+/** Reusable image data container. */
+struct Pixels {
+ // Use array instead of vector to avoid memory initialization.
+ std::unique_ptr<uint8_t[]> pixels;
size_t pixels_size = 0;
std::vector<uint8_t*> rows;
- unsigned int w, h, delay_num, delay_den;
- Status Resize(size_t new_size) {
+
+ Status Resize(size_t row_bytes, size_t num_rows) {
+ size_t new_size = row_bytes * num_rows; // it is assumed size is sane
if (new_size > pixels_size) {
- pixels.reset(malloc(new_size));
+ pixels.reset(new uint8_t[new_size]);
if (!pixels) {
// TODO(szabadka): use specialized OOM error code
return JXL_FAILURE("Failed to allocate memory for image buffer");
}
pixels_size = new_size;
}
+ rows.resize(num_rows);
+ for (size_t y = 0; y < num_rows; y++) {
+ rows[y] = pixels.get() + y * row_bytes;
+ }
return true;
}
};
+/**
+ * Helper that chunks in-memory input.
+ */
struct Reader {
- const uint8_t* next;
- const uint8_t* last;
- bool Read(void* data, size_t len) {
- size_t cap = last - next;
+ explicit Reader(Span<const uint8_t> data) : data_(data) {}
+
+ const Span<const uint8_t> data_;
+ size_t offset_ = 0;
+
+ Bytes Peek(size_t len) const {
+ size_t cap = data_.size() - offset_;
size_t to_copy = std::min(cap, len);
- memcpy(data, next, to_copy);
- next += to_copy;
- return (len == to_copy);
+ return {data_.data() + offset_, to_copy};
}
- bool Eof() const { return next == last; }
-};
-const uint32_t cMaxPNGSize = 1000000UL;
-const size_t kMaxPNGChunkSize = 1lu << 30; // 1 GB
+ Bytes Read(size_t len) {
+ Bytes result = Peek(len);
+ offset_ += result.size();
+ return result;
+ }
-void info_fn(png_structp png_ptr, png_infop info_ptr) {
+ /* Returns empty Span on errror. */
+ Bytes ReadChunk() {
+ Bytes len = Peek(4);
+ if (len.size() != 4) {
+ return Bytes();
+ }
+ const auto size = png_get_uint_32(len.data());
+ // NB: specification allows 2^31 - 1
+ constexpr size_t kMaxPNGChunkSize = 1u << 30; // 1 GB
+ // Check first, to avoid overflow.
+ if (size > kMaxPNGChunkSize) {
+ JXL_WARNING("APNG chunk size is too big");
+ return Bytes();
+ }
+ size_t full_size = size + 12; // size does not include itself, tag and CRC.
+ Bytes result = Read(full_size);
+ return (result.size() == full_size) ? result : Bytes();
+ }
+
+ bool Eof() const { return offset_ == data_.size(); }
+};
+
+void ProgressiveRead_OnInfo(png_structp png_ptr, png_infop info_ptr) {
png_set_expand(png_ptr);
png_set_palette_to_rgb(png_ptr);
png_set_tRNS_to_alpha(png_ptr);
@@ -475,432 +508,437 @@ void info_fn(png_structp png_ptr, png_infop info_ptr) {
png_read_update_info(png_ptr, info_ptr);
}
-void row_fn(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num,
- int pass) {
- APNGFrame* frame =
- reinterpret_cast<APNGFrame*>(png_get_progressive_ptr(png_ptr));
+void ProgressiveRead_OnRow(png_structp png_ptr, png_bytep new_row,
+ png_uint_32 row_num, int pass) {
+ Pixels* frame = reinterpret_cast<Pixels*>(png_get_progressive_ptr(png_ptr));
JXL_CHECK(frame);
JXL_CHECK(row_num < frame->rows.size());
JXL_CHECK(frame->rows[row_num] < frame->rows[0] + frame->pixels_size);
png_progressive_combine_row(png_ptr, frame->rows[row_num], new_row);
}
-inline unsigned int read_chunk(Reader* r, std::vector<uint8_t>* pChunk) {
- unsigned char len[4];
- if (r->Read(&len, 4)) {
- const auto size = png_get_uint_32(len);
- // Check first, to avoid overflow.
- if (size > kMaxPNGChunkSize) {
- JXL_WARNING("APNG chunk size is too big");
- return 0;
- }
- pChunk->resize(size + 12);
- memcpy(pChunk->data(), len, 4);
- if (r->Read(pChunk->data() + 4, pChunk->size() - 4)) {
- return LoadLE32(pChunk->data() + 4);
- }
+// Holds intermediate state during parsing APNG file.
+struct Context {
+ ~Context() {
+ // Make sure png memory is released in any case.
+ ResetPngDecoder();
}
- return 0;
-}
-
-int processing_start(png_structp& png_ptr, png_infop& info_ptr, void* frame_ptr,
- bool hasInfo, std::vector<uint8_t>& chunkIHDR,
- std::vector<std::vector<uint8_t>>& chunksInfo) {
- unsigned char header[8] = {137, 80, 78, 71, 13, 10, 26, 10};
- // Cleanup prior decoder, if any.
- png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
- // Just in case. Not all versions on libpng wipe-out the pointers.
- png_ptr = nullptr;
- info_ptr = nullptr;
+ bool CreatePngDecoder() {
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
+ nullptr);
+ info_ptr = png_create_info_struct(png_ptr);
+ return (png_ptr != nullptr && info_ptr != nullptr);
+ }
- png_ptr =
- png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
- info_ptr = png_create_info_struct(png_ptr);
- if (!png_ptr || !info_ptr) return 1;
+ /**
+ * Initialize PNG decoder.
+ *
+ * TODO(eustas): add details
+ */
+ bool InitPngDecoder(bool hasInfo, std::vector<Bytes>& chunksInfo) {
+ ResetPngDecoder();
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
+ nullptr);
+ info_ptr = png_create_info_struct(png_ptr);
+ if (png_ptr == nullptr || info_ptr == nullptr) {
+ return false;
+ }
- if (setjmp(png_jmpbuf(png_ptr))) {
- return 1;
- }
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ return false;
+ }
- png_set_keep_unknown_chunks(png_ptr, 1, kIgnoredPngChunks,
- static_cast<int>(sizeof(kIgnoredPngChunks) / 5));
+ png_set_keep_unknown_chunks(
+ png_ptr, 1, kIgnoredPngChunks,
+ static_cast<int>(sizeof(kIgnoredPngChunks) / 5));
- png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
- png_set_progressive_read_fn(png_ptr, frame_ptr, info_fn, row_fn, nullptr);
+ png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
+ png_set_progressive_read_fn(png_ptr, static_cast<void*>(&frameRaw),
+ ProgressiveRead_OnInfo, ProgressiveRead_OnRow,
+ nullptr);
- png_process_data(png_ptr, info_ptr, header, 8);
- png_process_data(png_ptr, info_ptr, chunkIHDR.data(), chunkIHDR.size());
+ std::array<uint8_t, 8> header = {137, 80, 78, 71, 13, 10, 26, 10};
+ png_process_data(png_ptr, info_ptr, header.data(), header.size());
+ png_process_data(png_ptr, info_ptr, ihdr.data(), ihdr.size());
- if (hasInfo) {
- for (auto& chunk : chunksInfo) {
- png_process_data(png_ptr, info_ptr, chunk.data(), chunk.size());
+ if (hasInfo) {
+ for (auto& chunk : chunksInfo) {
+ png_process_data(png_ptr, info_ptr, const_cast<uint8_t*>(chunk.data()),
+ chunk.size());
+ }
}
+ return true;
}
- return 0;
-}
-int processing_data(png_structp png_ptr, png_infop info_ptr, unsigned char* p,
- unsigned int size) {
- if (!png_ptr || !info_ptr) return 1;
+ /**
+ * Pass chunk to PNG decoder.
+ */
+ bool FeedChunks(const Bytes& chunk1, const Bytes& chunk2 = Bytes()) {
+ // TODO(eustas): turn to DCHECK
+ if (!png_ptr || !info_ptr) return false;
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ return false;
+ }
- if (setjmp(png_jmpbuf(png_ptr))) {
- return 1;
+ for (const auto& chunk : {chunk1, chunk2}) {
+ if (!chunk.empty()) {
+ png_process_data(png_ptr, info_ptr, const_cast<uint8_t*>(chunk.data()),
+ chunk.size());
+ }
+ }
+ return true;
}
- png_process_data(png_ptr, info_ptr, p, size);
- return 0;
-}
+ bool FinalizeStream(PackedMetadata* metadata) {
+ // TODO(eustas): turn to DCHECK
+ if (!png_ptr || !info_ptr) return false;
-int processing_finish(png_structp png_ptr, png_infop info_ptr,
- PackedMetadata* metadata) {
- unsigned char footer[12] = {0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130};
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ return false;
+ }
- if (!png_ptr || !info_ptr) return 1;
+ const std::array<uint8_t, 12> kFooter = {0, 0, 0, 0, 73, 69,
+ 78, 68, 174, 66, 96, 130};
+ png_process_data(png_ptr, info_ptr, const_cast<uint8_t*>(kFooter.data()),
+ kFooter.size());
+ // before destroying: check if we encountered any metadata chunks
+ png_textp text_ptr;
+ int num_text;
+ png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
+ for (int i = 0; i < num_text; i++) {
+ Status result = DecodeBlob(text_ptr[i], metadata);
+ // Ignore unknown / malformed blob.
+ (void)result;
+ }
- if (setjmp(png_jmpbuf(png_ptr))) {
- return 1;
+ return true;
}
- png_process_data(png_ptr, info_ptr, footer, 12);
- // before destroying: check if we encountered any metadata chunks
- png_textp text_ptr;
- int num_text;
- png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
- for (int i = 0; i < num_text; i++) {
- (void)BlobsReaderPNG::Decode(text_ptr[i], metadata);
+ void ResetPngDecoder() {
+ png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
+ // Just in case. Not all versions on libpng wipe-out the pointers.
+ png_ptr = nullptr;
+ info_ptr = nullptr;
}
- return 0;
-}
+ std::vector<uint8_t> ihdr; // (modified) copy of file IHDR chunk
+ png_structp png_ptr = nullptr;
+ png_infop info_ptr = nullptr;
+ Pixels frameRaw = {};
+};
+
+constexpr uint32_t kMaxPNGSize = 1000000UL;
+
+struct FrameInfo {
+ PackedImage data;
+ uint32_t duration;
+ size_t x0, xsize;
+ size_t y0, ysize;
+ uint32_t dispose_op;
+ uint32_t blend_op;
+};
} // namespace
-#endif
-bool CanDecodeAPNG() {
-#if JPEGXL_ENABLE_APNG
- return true;
-#else
- return false;
-#endif
-}
+bool CanDecodeAPNG() { return true; }
Status DecodeImageAPNG(const Span<const uint8_t> bytes,
const ColorHints& color_hints, PackedPixelFile* ppf,
const SizeConstraints* constraints) {
-#if JPEGXL_ENABLE_APNG
- Reader r;
- unsigned char sig[8];
- png_structp png_ptr = nullptr;
- png_infop info_ptr = nullptr;
- std::vector<uint8_t> chunk;
- std::vector<uint8_t> chunkIHDR;
- std::vector<std::vector<uint8_t>> chunksInfo;
- bool isAnimated = false;
- bool hasInfo = false;
- bool seenFctl = false;
- APNGFrame frameRaw = {};
- uint32_t num_channels;
- JxlPixelFormat format = {};
- unsigned int bytes_per_pixel = 0;
-
- struct FrameInfo {
- PackedImage data;
- uint32_t duration;
- size_t x0, xsize;
- size_t y0, ysize;
- uint32_t dispose_op;
- uint32_t blend_op;
- };
-
- std::vector<FrameInfo> frames;
+ // Initialize output (default settings in case e.g. only gAMA is given).
+ ppf->frames.clear();
+ ppf->info.exponent_bits_per_sample = 0;
+ ppf->info.alpha_exponent_bits = 0;
+ ppf->info.orientation = JXL_ORIENT_IDENTITY;
+ ppf->color_encoding.color_space = JXL_COLOR_SPACE_RGB;
+ ppf->color_encoding.white_point = JXL_WHITE_POINT_D65;
+ ppf->color_encoding.primaries = JXL_PRIMARIES_SRGB;
+ ppf->color_encoding.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
+ ppf->color_encoding.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
- // Make sure png memory is released in any case.
- auto scope_guard = MakeScopeGuard([&]() {
- png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
- // Just in case. Not all versions on libpng wipe-out the pointers.
- png_ptr = nullptr;
- info_ptr = nullptr;
- });
+ Reader input(bytes);
- r = {bytes.data(), bytes.data() + bytes.size()};
// Not a PNG => not an error
unsigned char png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
- if (!r.Read(sig, 8) || memcmp(sig, png_signature, 8) != 0) {
+ Bytes sig = input.Read(8);
+ if (sig.size() != 8 || memcmp(sig.data(), png_signature, 8) != 0) {
return false;
}
- unsigned int id = read_chunk(&r, &chunkIHDR);
- ppf->info.exponent_bits_per_sample = 0;
- ppf->info.alpha_exponent_bits = 0;
- ppf->info.orientation = JXL_ORIENT_IDENTITY;
+ Bytes chunk_ihdr = input.ReadChunk();
+ if (chunk_ihdr.empty()) {
+ return false;
+ }
+ uint32_t id = LoadLE32(chunk_ihdr.data() + 4);
+ if (id != MakeTag('I', 'H', 'D', 'R') || chunk_ihdr.size() != 25) {
+ return false;
+ }
+ const uint32_t w = png_get_uint_32(chunk_ihdr.data() + 8);
+ const uint32_t h = png_get_uint_32(chunk_ihdr.data() + 12);
+ if (w > kMaxPNGSize || h > kMaxPNGSize) {
+ return false;
+ }
- ppf->frames.clear();
+ Context ctx;
+ ctx.ihdr = chunk_ihdr.Copy();
+
+ std::vector<Bytes> chunksInfo;
+ if (!ctx.InitPngDecoder(false, chunksInfo)) {
+ return false;
+ }
+ bool isAnimated = false;
+ bool hasInfo = false;
+ uint32_t num_channels;
+ JxlPixelFormat format = {};
+ unsigned int bytes_per_pixel = 0;
+ std::vector<FrameInfo> frames;
bool have_color = false;
bool have_cicp = false;
bool have_iccp = false;
bool have_srgb = false;
- bool errorstate = true;
- if (id == kId_IHDR && chunkIHDR.size() == 25) {
- uint32_t x0 = 0;
- uint32_t y0 = 0;
- uint32_t delay_num = 1;
- uint32_t delay_den = 10;
- uint32_t dop = 0;
- uint32_t bop = 0;
-
- uint32_t w = png_get_uint_32(chunkIHDR.data() + 8);
- uint32_t h = png_get_uint_32(chunkIHDR.data() + 12);
- uint32_t w0 = w;
- uint32_t h0 = h;
- if (w > cMaxPNGSize || h > cMaxPNGSize) {
+ uint32_t x0 = 0;
+ uint32_t y0 = 0;
+ uint32_t delay_num = 1;
+ uint32_t delay_den = 10;
+ uint32_t dop = 0;
+ uint32_t bop = 0;
+ uint32_t w0 = w;
+ uint32_t h0 = h;
+
+ while (!input.Eof()) {
+ Bytes chunk = input.ReadChunk();
+ if (chunk.empty()) {
return false;
}
-
- // default settings in case e.g. only gAMA is given
- ppf->color_encoding.color_space = JXL_COLOR_SPACE_RGB;
- ppf->color_encoding.white_point = JXL_WHITE_POINT_D65;
- ppf->color_encoding.primaries = JXL_PRIMARIES_SRGB;
- ppf->color_encoding.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
- ppf->color_encoding.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
-
- if (!processing_start(png_ptr, info_ptr, static_cast<void*>(&frameRaw),
- hasInfo, chunkIHDR, chunksInfo)) {
- while (!r.Eof()) {
- id = read_chunk(&r, &chunk);
- if (!id) break;
- seenFctl |= (id == kId_fcTL);
-
- if (id == kId_acTL && !hasInfo && !isAnimated) {
- isAnimated = true;
- ppf->info.have_animation = JXL_TRUE;
- ppf->info.animation.tps_numerator = 1000;
- ppf->info.animation.tps_denominator = 1;
- } else if (id == kId_IEND ||
- (id == kId_fcTL && (!hasInfo || isAnimated))) {
- if (hasInfo) {
- if (!processing_finish(png_ptr, info_ptr, &ppf->metadata)) {
- // Allocates the frame buffer.
- uint32_t duration = delay_num * 1000 / delay_den;
- JXL_ASSIGN_OR_RETURN(PackedImage image,
- PackedImage::Create(w0, h0, format));
- frames.push_back(FrameInfo{std::move(image), duration, x0, w0, y0,
- h0, dop, bop});
- auto& frame = frames.back().data;
- for (size_t y = 0; y < h0; ++y) {
- memcpy(static_cast<uint8_t*>(frame.pixels()) + frame.stride * y,
- frameRaw.rows[y], bytes_per_pixel * w0);
- }
- } else {
- break;
- }
+ id = LoadLE32(chunk.data() + 4);
+
+ if (id == MakeTag('a', 'c', 'T', 'L') && !hasInfo && !isAnimated) {
+ isAnimated = true;
+ ppf->info.have_animation = JXL_TRUE;
+ ppf->info.animation.tps_numerator = 1000;
+ ppf->info.animation.tps_denominator = 1;
+ } else if (id == MakeTag('I', 'E', 'N', 'D') ||
+ (id == MakeTag('f', 'c', 'T', 'L') &&
+ (!hasInfo || isAnimated))) {
+ if (hasInfo) {
+ if (ctx.FinalizeStream(&ppf->metadata)) {
+ // Allocates the frame buffer.
+ uint32_t duration = delay_num * 1000 / delay_den;
+ JXL_ASSIGN_OR_RETURN(PackedImage image,
+ PackedImage::Create(w0, h0, format));
+ frames.push_back(
+ FrameInfo{std::move(image), duration, x0, w0, y0, h0, dop, bop});
+ auto& frame = frames.back().data;
+ for (size_t y = 0; y < h0; ++y) {
+ // TODO(eustas): ensure multiplication is safe
+ memcpy(static_cast<uint8_t*>(frame.pixels()) + frame.stride * y,
+ ctx.frameRaw.rows[y], bytes_per_pixel * w0);
}
+ } else {
+ return false;
+ }
+ }
- if (id == kId_IEND) {
- errorstate = false;
- break;
- }
- if (chunk.size() < 34) {
- return JXL_FAILURE("Received a chunk that is too small (%" PRIuS
- "B)",
- chunk.size());
- }
- // At this point the old frame is done. Let's start a new one.
- w0 = png_get_uint_32(chunk.data() + 12);
- h0 = png_get_uint_32(chunk.data() + 16);
- x0 = png_get_uint_32(chunk.data() + 20);
- y0 = png_get_uint_32(chunk.data() + 24);
- delay_num = png_get_uint_16(chunk.data() + 28);
- delay_den = png_get_uint_16(chunk.data() + 30);
- dop = chunk[32];
- bop = chunk[33];
-
- if (!delay_den) delay_den = 100;
-
- if (w0 > cMaxPNGSize || h0 > cMaxPNGSize || x0 > cMaxPNGSize ||
- y0 > cMaxPNGSize || x0 + w0 > w || y0 + h0 > h || dop > 2 ||
- bop > 1) {
- break;
- }
+ if (id == MakeTag('I', 'E', 'N', 'D')) {
+ break;
+ }
+ if (chunk.size() < 34) {
+ return JXL_FAILURE("Received a chunk that is too small (%" PRIuS "B)",
+ chunk.size());
+ }
+ // At this point the old frame is done. Let's start a new one.
+ w0 = png_get_uint_32(chunk.data() + 12);
+ h0 = png_get_uint_32(chunk.data() + 16);
+ x0 = png_get_uint_32(chunk.data() + 20);
+ y0 = png_get_uint_32(chunk.data() + 24);
+ delay_num = png_get_uint_16(chunk.data() + 28);
+ delay_den = png_get_uint_16(chunk.data() + 30);
+ dop = chunk[32];
+ bop = chunk[33];
+
+ if (!delay_den) delay_den = 100;
+
+ if (w0 > kMaxPNGSize || h0 > kMaxPNGSize || x0 > kMaxPNGSize ||
+ y0 > kMaxPNGSize || x0 + w0 > w || y0 + h0 > h || dop > 2 ||
+ bop > 1) {
+ return false;
+ }
- if (hasInfo) {
- memcpy(chunkIHDR.data() + 8, chunk.data() + 12, 8);
- if (processing_start(png_ptr, info_ptr,
- static_cast<void*>(&frameRaw), hasInfo,
- chunkIHDR, chunksInfo)) {
- break;
- }
- }
- } else if (id == kId_IDAT) {
- // First IDAT chunk means we now have all header info
- if (seenFctl) {
- // `fcTL` chunk must appear after all `IDAT` chunks
- return JXL_FAILURE("IDAT chunk after fcTL chunk");
- }
- hasInfo = true;
- JXL_CHECK(w == png_get_image_width(png_ptr, info_ptr));
- JXL_CHECK(h == png_get_image_height(png_ptr, info_ptr));
- int colortype = png_get_color_type(png_ptr, info_ptr);
- int png_bit_depth = png_get_bit_depth(png_ptr, info_ptr);
- ppf->info.bits_per_sample = png_bit_depth;
- png_color_8p sigbits = nullptr;
- png_get_sBIT(png_ptr, info_ptr, &sigbits);
- if (colortype & 1) {
- // palette will actually be 8-bit regardless of the index bitdepth
- ppf->info.bits_per_sample = 8;
- }
- if (colortype & 2) {
- ppf->info.num_color_channels = 3;
- ppf->color_encoding.color_space = JXL_COLOR_SPACE_RGB;
- if (sigbits && sigbits->red == sigbits->green &&
- sigbits->green == sigbits->blue) {
- ppf->info.bits_per_sample = sigbits->red;
- } else if (sigbits) {
- int maxbps = std::max(sigbits->red,
- std::max(sigbits->green, sigbits->blue));
- JXL_WARNING(
- "sBIT chunk: bit depths for R, G, and B are not the same (%i "
- "%i %i), while in JPEG XL they have to be the same. Setting "
- "RGB bit depth to %i.",
- sigbits->red, sigbits->green, sigbits->blue, maxbps);
- ppf->info.bits_per_sample = maxbps;
- }
- } else {
- ppf->info.num_color_channels = 1;
- ppf->color_encoding.color_space = JXL_COLOR_SPACE_GRAY;
- if (sigbits) ppf->info.bits_per_sample = sigbits->gray;
- }
- if (colortype & 4 ||
- png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- ppf->info.alpha_bits = ppf->info.bits_per_sample;
- if (sigbits && sigbits->alpha != ppf->info.bits_per_sample) {
- JXL_WARNING(
- "sBIT chunk: bit depths for RGBA are inconsistent "
- "(%i %i %i %i). Setting A bitdepth to %i.",
- sigbits->red, sigbits->green, sigbits->blue, sigbits->alpha,
- ppf->info.bits_per_sample);
- }
- } else {
- ppf->info.alpha_bits = 0;
- }
- ppf->color_encoding.color_space =
- (ppf->info.num_color_channels == 1 ? JXL_COLOR_SPACE_GRAY
- : JXL_COLOR_SPACE_RGB);
- ppf->info.xsize = w;
- ppf->info.ysize = h;
- JXL_RETURN_IF_ERROR(VerifyDimensions(constraints, w, h));
- num_channels =
- ppf->info.num_color_channels + (ppf->info.alpha_bits ? 1 : 0);
- format = {
- /*num_channels=*/num_channels,
- /*data_type=*/ppf->info.bits_per_sample > 8 ? JXL_TYPE_UINT16
- : JXL_TYPE_UINT8,
- /*endianness=*/JXL_BIG_ENDIAN,
- /*align=*/0,
- };
- if (png_bit_depth > 8 && format.data_type == JXL_TYPE_UINT8) {
- png_set_strip_16(png_ptr);
- }
- bytes_per_pixel =
- num_channels * (format.data_type == JXL_TYPE_UINT16 ? 2 : 1);
- size_t rowbytes = w * bytes_per_pixel;
- if (h > std::numeric_limits<size_t>::max() / rowbytes) {
- return JXL_FAILURE("Image too big.");
- }
- size_t imagesize = h * rowbytes;
- JXL_RETURN_IF_ERROR(frameRaw.Resize(imagesize));
- frameRaw.rows.resize(h);
- for (size_t j = 0; j < h; j++) {
- frameRaw.rows[j] =
- reinterpret_cast<uint8_t*>(frameRaw.pixels.get()) +
- j * rowbytes;
- }
+ if (hasInfo) {
+ // Copy dimensions.
+ memcpy(ctx.ihdr.data() + 8, chunk.data() + 12, 8);
+ if (!ctx.InitPngDecoder(hasInfo, chunksInfo)) {
+ return false;
+ }
+ }
+ } else if (id == MakeTag('I', 'D', 'A', 'T')) {
+ // First IDAT chunk means we now have all header info
+ hasInfo = true;
+ JXL_CHECK(w == png_get_image_width(ctx.png_ptr, ctx.info_ptr));
+ JXL_CHECK(h == png_get_image_height(ctx.png_ptr, ctx.info_ptr));
+ int colortype = png_get_color_type(ctx.png_ptr, ctx.info_ptr);
+ int png_bit_depth = png_get_bit_depth(ctx.png_ptr, ctx.info_ptr);
+ ppf->info.bits_per_sample = png_bit_depth;
+ png_color_8p sigbits = nullptr;
+ png_get_sBIT(ctx.png_ptr, ctx.info_ptr, &sigbits);
+ if (colortype & 1) {
+ // palette will actually be 8-bit regardless of the index bitdepth
+ ppf->info.bits_per_sample = 8;
+ }
+ if (colortype & 2) {
+ ppf->info.num_color_channels = 3;
+ ppf->color_encoding.color_space = JXL_COLOR_SPACE_RGB;
+ if (sigbits && sigbits->red == sigbits->green &&
+ sigbits->green == sigbits->blue) {
+ ppf->info.bits_per_sample = sigbits->red;
+ } else if (sigbits) {
+ int maxbps =
+ std::max(sigbits->red, std::max(sigbits->green, sigbits->blue));
+ JXL_WARNING(
+ "sBIT chunk: bit depths for R, G, and B are not the same (%i "
+ "%i %i), while in JPEG XL they have to be the same. Setting "
+ "RGB bit depth to %i.",
+ sigbits->red, sigbits->green, sigbits->blue, maxbps);
+ ppf->info.bits_per_sample = maxbps;
+ }
+ } else {
+ ppf->info.num_color_channels = 1;
+ ppf->color_encoding.color_space = JXL_COLOR_SPACE_GRAY;
+ if (sigbits) ppf->info.bits_per_sample = sigbits->gray;
+ }
+ if (colortype & 4 ||
+ png_get_valid(ctx.png_ptr, ctx.info_ptr, PNG_INFO_tRNS)) {
+ ppf->info.alpha_bits = ppf->info.bits_per_sample;
+ if (sigbits && sigbits->alpha != ppf->info.bits_per_sample) {
+ JXL_WARNING(
+ "sBIT chunk: bit depths for RGBA are inconsistent "
+ "(%i %i %i %i). Setting A bitdepth to %i.",
+ sigbits->red, sigbits->green, sigbits->blue, sigbits->alpha,
+ ppf->info.bits_per_sample);
+ }
+ } else {
+ ppf->info.alpha_bits = 0;
+ }
+ ppf->color_encoding.color_space =
+ (ppf->info.num_color_channels == 1 ? JXL_COLOR_SPACE_GRAY
+ : JXL_COLOR_SPACE_RGB);
+ ppf->info.xsize = w;
+ ppf->info.ysize = h;
+ JXL_RETURN_IF_ERROR(VerifyDimensions(constraints, w, h));
+ num_channels =
+ ppf->info.num_color_channels + (ppf->info.alpha_bits ? 1 : 0);
+ format = {
+ /*num_channels=*/num_channels,
+ /*data_type=*/ppf->info.bits_per_sample > 8 ? JXL_TYPE_UINT16
+ : JXL_TYPE_UINT8,
+ /*endianness=*/JXL_BIG_ENDIAN,
+ /*align=*/0,
+ };
+ if (png_bit_depth > 8 && format.data_type == JXL_TYPE_UINT8) {
+ png_set_strip_16(ctx.png_ptr);
+ }
+ bytes_per_pixel =
+ num_channels * (format.data_type == JXL_TYPE_UINT16 ? 2 : 1);
+ // TODO(eustas): ensure multiplication is safe
+ size_t rowbytes = w * bytes_per_pixel;
+ if (h > std::numeric_limits<size_t>::max() / rowbytes) {
+ return JXL_FAILURE("Image too big.");
+ }
+ JXL_RETURN_IF_ERROR(ctx.frameRaw.Resize(rowbytes, h));
- if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) {
- break;
- }
- } else if (id == kId_fdAT && isAnimated) {
- if (!hasInfo) {
- return JXL_FAILURE("fDAT chunk before iDAT");
- }
- png_save_uint_32(chunk.data() + 4, chunk.size() - 16);
- memcpy(chunk.data() + 8, "IDAT", 4);
- if (processing_data(png_ptr, info_ptr, chunk.data() + 4,
- chunk.size() - 4)) {
- break;
- }
- } else if (id == kId_cICP) {
- // Color profile chunks: cICP has the highest priority, followed by
- // iCCP and sRGB (which shouldn't co-exist, but if they do, we use
- // iCCP), followed finally by gAMA and cHRM.
- if (DecodeCICP(chunk.data() + 8, chunk.size() - 12,
- &ppf->color_encoding)) {
- have_cicp = true;
- have_color = true;
- ppf->icc.clear();
- ppf->primary_color_representation =
- PackedPixelFile::kColorEncodingIsPrimary;
- }
- } else if (!have_cicp && id == kId_iCCP) {
- if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) {
- JXL_WARNING("Corrupt iCCP chunk");
- break;
- }
+ if (!ctx.FeedChunks(chunk)) {
+ return false;
+ }
+ } else if (id == MakeTag('f', 'd', 'A', 'T') && isAnimated) {
+ if (!hasInfo) {
+ return JXL_FAILURE("fdAT chunk before IDAT");
+ }
+ /* The 'fdAT' chunk has... the same structure as an 'IDAT' chunk,
+ * except preceded by a sequence number. */
+ size_t payload_size = chunk.size() - 12;
+ if (payload_size < 4) {
+ return JXL_FAILURE("Corrupted fdAT chunk");
+ }
+ // Turn 'fdAT' to 'IDAT' by cutting sequence number and replacing tag.
+ std::array<uint8_t, 8> preamble;
+ png_save_uint_32(preamble.data(), payload_size - 4);
+ memcpy(preamble.data() + 4, "IDAT", 4);
+ if (!ctx.FeedChunks(Bytes(preamble),
+ Bytes(chunk.data() + 12, chunk.size() - 12))) {
+ return false;
+ }
+ } else if (id == MakeTag('c', 'I', 'C', 'P')) {
+ // Color profile chunks: cICP has the highest priority, followed by
+ // iCCP and sRGB (which shouldn't co-exist, but if they do, we use
+ // iCCP), followed finally by gAMA and cHRM.
+ if (DecodeCicpChunk(Bytes(chunk.data() + 8, chunk.size() - 12),
+ &ppf->color_encoding)) {
+ have_cicp = true;
+ have_color = true;
+ ppf->icc.clear();
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
+ }
+ } else if (!have_cicp && id == MakeTag('i', 'C', 'C', 'P')) {
+ if (!ctx.FeedChunks(chunk)) {
+ JXL_WARNING("Corrupt iCCP chunk");
+ return false;
+ }
- // TODO(jon): catch special case of PQ and synthesize color encoding
- // in that case
- int compression_type;
- png_bytep profile;
- png_charp name;
- png_uint_32 proflen = 0;
- auto ok = png_get_iCCP(png_ptr, info_ptr, &name, &compression_type,
- &profile, &proflen);
- if (ok && proflen) {
- ppf->icc.assign(profile, profile + proflen);
- ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
- have_color = true;
- have_iccp = true;
- } else {
- // TODO(eustas): JXL_WARNING?
- }
- } else if (!have_cicp && !have_iccp && id == kId_sRGB) {
- JXL_RETURN_IF_ERROR(DecodeSRGB(chunk.data() + 8, chunk.size() - 12,
- &ppf->color_encoding));
- have_srgb = true;
- have_color = true;
- } else if (!have_cicp && !have_srgb && !have_iccp && id == kId_gAMA) {
- JXL_RETURN_IF_ERROR(DecodeGAMA(chunk.data() + 8, chunk.size() - 12,
- &ppf->color_encoding));
- have_color = true;
- } else if (!have_cicp && !have_srgb && !have_iccp && id == kId_cHRM) {
- JXL_RETURN_IF_ERROR(DecodeCHRM(chunk.data() + 8, chunk.size() - 12,
- &ppf->color_encoding));
- have_color = true;
- } else if (id == kId_eXIf) {
- ppf->metadata.exif.resize(chunk.size() - 12);
- memcpy(ppf->metadata.exif.data(), chunk.data() + 8,
- chunk.size() - 12);
- } else if (!isAbc(chunk[4]) || !isAbc(chunk[5]) || !isAbc(chunk[6]) ||
- !isAbc(chunk[7])) {
- break;
- } else {
- if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) {
- break;
- }
- if (!hasInfo) {
- chunksInfo.push_back(chunk);
- continue;
- }
- }
+ // TODO(jon): catch special case of PQ and synthesize color encoding
+ // in that case
+ int compression_type;
+ png_bytep profile;
+ png_charp name;
+ png_uint_32 proflen = 0;
+ auto ok = png_get_iCCP(ctx.png_ptr, ctx.info_ptr, &name,
+ &compression_type, &profile, &proflen);
+ if (ok && proflen) {
+ ppf->icc.assign(profile, profile + proflen);
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
+ have_color = true;
+ have_iccp = true;
+ } else {
+ // TODO(eustas): JXL_WARNING?
+ }
+ } else if (!have_cicp && !have_iccp && id == MakeTag('s', 'R', 'G', 'B')) {
+ JXL_RETURN_IF_ERROR(DecodeSrgbChunk(
+ Bytes(chunk.data() + 8, chunk.size() - 12), &ppf->color_encoding));
+ have_srgb = true;
+ have_color = true;
+ } else if (!have_cicp && !have_srgb && !have_iccp &&
+ id == MakeTag('g', 'A', 'M', 'A')) {
+ JXL_RETURN_IF_ERROR(DecodeGamaChunk(
+ Bytes(chunk.data() + 8, chunk.size() - 12), &ppf->color_encoding));
+ have_color = true;
+ } else if (!have_cicp && !have_srgb && !have_iccp &&
+ id == MakeTag('c', 'H', 'R', 'M')) {
+ JXL_RETURN_IF_ERROR(DecodeChrmChunk(
+ Bytes(chunk.data() + 8, chunk.size() - 12), &ppf->color_encoding));
+ have_color = true;
+ } else if (id == MakeTag('e', 'X', 'I', 'f')) {
+ ppf->metadata.exif.resize(chunk.size() - 12);
+ memcpy(ppf->metadata.exif.data(), chunk.data() + 8, chunk.size() - 12);
+ } else if (!isAbc(chunk[4]) || !isAbc(chunk[5]) || !isAbc(chunk[6]) ||
+ !isAbc(chunk[7])) {
+ return false;
+ } else {
+ if (!ctx.FeedChunks(chunk)) {
+ return false;
+ }
+ if (!hasInfo) {
+ chunksInfo.push_back(chunk);
+ continue;
}
}
-
- JXL_RETURN_IF_ERROR(ApplyColorHints(
- color_hints, have_color, ppf->info.num_color_channels == 1, ppf));
}
- if (errorstate) return false;
+ JXL_RETURN_IF_ERROR(ApplyColorHints(color_hints, have_color,
+ ppf->info.num_color_channels == 1, ppf));
bool has_nontrivial_background = false;
bool previous_frame_should_be_cleared = false;
@@ -1014,14 +1052,14 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
previous_frame_should_be_cleared =
has_nontrivial_background && frame.dispose_op == DISPOSE_OP_BACKGROUND;
}
+
if (ppf->frames.empty()) return JXL_FAILURE("No frames decoded");
ppf->frames.back().frame_info.is_last = JXL_TRUE;
return true;
-#else
- return false;
-#endif
}
+#endif // JPEGXL_ENABLE_APNG
+
} // namespace extras
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/extras/dec/apng.h b/third_party/jpeg-xl/lib/extras/dec/apng.h
index d91364b1e6..7ebc2ee7c8 100644
--- a/third_party/jpeg-xl/lib/extras/dec/apng.h
+++ b/third_party/jpeg-xl/lib/extras/dec/apng.h
@@ -8,11 +8,10 @@
// Decodes APNG images in memory.
-#include <stdint.h>
+#include <cstdint>
#include "lib/extras/dec/color_hints.h"
#include "lib/extras/packed_image.h"
-#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
diff --git a/third_party/jpeg-xl/lib/extras/dec/color_description.cc b/third_party/jpeg-xl/lib/extras/dec/color_description.cc
index bf229632d0..87fff6e54a 100644
--- a/third_party/jpeg-xl/lib/extras/dec/color_description.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/color_description.cc
@@ -203,12 +203,38 @@ Status ParseTransferFunction(Tokenizer* tokenizer, JxlColorEncoding* c) {
Status ParseDescription(const std::string& description, JxlColorEncoding* c) {
*c = {};
- Tokenizer tokenizer(&description, '_');
- JXL_RETURN_IF_ERROR(ParseColorSpace(&tokenizer, c));
- JXL_RETURN_IF_ERROR(ParseWhitePoint(&tokenizer, c));
- JXL_RETURN_IF_ERROR(ParsePrimaries(&tokenizer, c));
- JXL_RETURN_IF_ERROR(ParseRenderingIntent(&tokenizer, c));
- JXL_RETURN_IF_ERROR(ParseTransferFunction(&tokenizer, c));
+ if (description == "sRGB") {
+ c->color_space = JXL_COLOR_SPACE_RGB;
+ c->white_point = JXL_WHITE_POINT_D65;
+ c->primaries = JXL_PRIMARIES_SRGB;
+ c->transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
+ c->rendering_intent = JXL_RENDERING_INTENT_PERCEPTUAL;
+ } else if (description == "DisplayP3") {
+ c->color_space = JXL_COLOR_SPACE_RGB;
+ c->white_point = JXL_WHITE_POINT_D65;
+ c->primaries = JXL_PRIMARIES_P3;
+ c->transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
+ c->rendering_intent = JXL_RENDERING_INTENT_PERCEPTUAL;
+ } else if (description == "Rec2100PQ") {
+ c->color_space = JXL_COLOR_SPACE_RGB;
+ c->white_point = JXL_WHITE_POINT_D65;
+ c->primaries = JXL_PRIMARIES_2100;
+ c->transfer_function = JXL_TRANSFER_FUNCTION_PQ;
+ c->rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
+ } else if (description == "Rec2100HLG") {
+ c->color_space = JXL_COLOR_SPACE_RGB;
+ c->white_point = JXL_WHITE_POINT_D65;
+ c->primaries = JXL_PRIMARIES_2100;
+ c->transfer_function = JXL_TRANSFER_FUNCTION_HLG;
+ c->rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
+ } else {
+ Tokenizer tokenizer(&description, '_');
+ JXL_RETURN_IF_ERROR(ParseColorSpace(&tokenizer, c));
+ JXL_RETURN_IF_ERROR(ParseWhitePoint(&tokenizer, c));
+ JXL_RETURN_IF_ERROR(ParsePrimaries(&tokenizer, c));
+ JXL_RETURN_IF_ERROR(ParseRenderingIntent(&tokenizer, c));
+ JXL_RETURN_IF_ERROR(ParseTransferFunction(&tokenizer, c));
+ }
return true;
}
diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.cc b/third_party/jpeg-xl/lib/extras/dec/decode.cc
index 3546cb65c0..2581d53f63 100644
--- a/third_party/jpeg-xl/lib/extras/dec/decode.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/decode.cc
@@ -91,6 +91,15 @@ bool CanDecode(Codec codec) {
}
}
+std::string ListOfDecodeCodecs() {
+ std::string list_of_codecs("JXL, PPM, PNM, PFM, PAM, PGX");
+ if (CanDecode(Codec::kPNG)) list_of_codecs.append(", PNG, APNG");
+ if (CanDecode(Codec::kGIF)) list_of_codecs.append(", GIF");
+ if (CanDecode(Codec::kJPG)) list_of_codecs.append(", JPEG");
+ if (CanDecode(Codec::kEXR)) list_of_codecs.append(", EXR");
+ return list_of_codecs;
+}
+
Status DecodeBytes(const Span<const uint8_t> bytes,
const ColorHints& color_hints, extras::PackedPixelFile* ppf,
const SizeConstraints* constraints, Codec* orig_codec) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.h b/third_party/jpeg-xl/lib/extras/dec/decode.h
index 1a90f4c6a3..26dc1409df 100644
--- a/third_party/jpeg-xl/lib/extras/dec/decode.h
+++ b/third_party/jpeg-xl/lib/extras/dec/decode.h
@@ -38,6 +38,8 @@ enum class Codec : uint32_t {
bool CanDecode(Codec codec);
+std::string ListOfDecodeCodecs();
+
// If and only if extension is ".pfm", *bits_per_sample is updated to 32 so
// that Encode() would encode to PFM instead of PPM.
Codec CodecFromPath(const std::string& path,
diff --git a/third_party/jpeg-xl/lib/extras/dec/gif.cc b/third_party/jpeg-xl/lib/extras/dec/gif.cc
index 3f89d460b8..243d8b5103 100644
--- a/third_party/jpeg-xl/lib/extras/dec/gif.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/gif.cc
@@ -17,6 +17,7 @@
#include "lib/extras/size_constraints.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/sanitizers.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/extras/dec/jpg.cc b/third_party/jpeg-xl/lib/extras/dec/jpg.cc
index 4a3e0d3b21..a65b46b4c8 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jpg.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jpg.cc
@@ -6,8 +6,7 @@
#include "lib/extras/dec/jpg.h"
#if JPEGXL_ENABLE_JPEG
-#include <jpeglib.h>
-#include <setjmp.h>
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#endif
#include <stdint.h>
diff --git a/third_party/jpeg-xl/lib/extras/dec/jxl.cc b/third_party/jpeg-xl/lib/extras/dec/jxl.cc
index 5b7fa03f02..e2534fa745 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jxl.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jxl.cc
@@ -10,7 +10,7 @@
#include <jxl/decode_cxx.h>
#include <jxl/types.h>
-#include <cinttypes>
+#include <cinttypes> // PRIu32
#include "lib/extras/common.h"
#include "lib/extras/dec/color_description.h"
@@ -211,7 +211,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
uint32_t progression_index = 0;
- bool codestream_done = accepted_formats.empty();
+ bool codestream_done = jpeg_bytes == nullptr && accepted_formats.empty();
BoxProcessor boxes(dec);
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec);
diff --git a/third_party/jpeg-xl/lib/extras/dec/pnm.cc b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
index e64d7e95f9..b3f9cd1206 100644
--- a/third_party/jpeg-xl/lib/extras/dec/pnm.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
@@ -5,17 +5,17 @@
#include "lib/extras/dec/pnm.h"
-#include <stdlib.h>
-#include <string.h>
+#include <jxl/encode.h>
#include <cmath>
+#include <cstddef>
#include <cstdint>
-#include <mutex>
+#include <cstdlib>
+#include <cstring>
-#include "jxl/encode.h"
#include "lib/extras/size_constraints.h"
#include "lib/jxl/base/bits.h"
-#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/extras/enc/encode.cc b/third_party/jpeg-xl/lib/extras/enc/encode.cc
index c5e22d8c7e..71be78e36c 100644
--- a/third_party/jpeg-xl/lib/extras/enc/encode.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/encode.cc
@@ -134,5 +134,13 @@ std::unique_ptr<Encoder> Encoder::FromExtension(std::string extension) {
return nullptr;
}
+std::string ListOfEncodeCodecs() {
+ std::string list_of_codecs("PPM, PNM, PFM, PAM, PGX");
+ if (GetAPNGEncoder()) list_of_codecs.append(", PNG, APNG");
+ if (GetJPEGEncoder()) list_of_codecs.append(", JPEG");
+ if (GetEXREncoder()) list_of_codecs.append(", EXR");
+ return list_of_codecs;
+}
+
} // namespace extras
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/extras/enc/encode.h b/third_party/jpeg-xl/lib/extras/enc/encode.h
index 2502d9976b..a71f3b220f 100644
--- a/third_party/jpeg-xl/lib/extras/enc/encode.h
+++ b/third_party/jpeg-xl/lib/extras/enc/encode.h
@@ -82,6 +82,8 @@ class Encoder {
std::unordered_map<std::string, std::string> options_;
};
+std::string ListOfEncodeCodecs();
+
} // namespace extras
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
index cb473a1290..9735cd8cb9 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
@@ -454,6 +454,10 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
cinfo.comp_info[i].h_samp_factor = 1;
cinfo.comp_info[i].v_samp_factor = 1;
}
+ } else if (!jpeg_settings.xyb) {
+ // Default is no chroma subsampling.
+ cinfo.comp_info[0].h_samp_factor = 1;
+ cinfo.comp_info[0].v_samp_factor = 1;
}
jpegli_enable_adaptive_quantization(
&cinfo, TO_JXL_BOOL(jpeg_settings.use_adaptive_quantization));
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpg.cc b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
index 0095ac9294..a2ef4a9fc4 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpg.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
@@ -6,18 +6,15 @@
#include "lib/extras/enc/jpg.h"
#if JPEGXL_ENABLE_JPEG
-#include <jpeglib.h>
-#include <setjmp.h>
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#endif
-#include <stdint.h>
#include <algorithm>
#include <array>
#include <cmath>
+#include <cstdint>
#include <fstream>
-#include <iterator>
#include <memory>
-#include <numeric>
#include <sstream>
#include <utility>
#include <vector>
diff --git a/third_party/jpeg-xl/lib/extras/jpegli_test.cc b/third_party/jpeg-xl/lib/extras/jpegli_test.cc
index 3049049a64..96b546755c 100644
--- a/third_party/jpeg-xl/lib/extras/jpegli_test.cc
+++ b/third_party/jpeg-xl/lib/extras/jpegli_test.cc
@@ -255,7 +255,7 @@ TEST(JpegliTest, JpegliHDRRoundtripTest) {
std::string testimage = "jxl/hdr_room.png";
PackedPixelFile ppf_in;
ASSERT_TRUE(ReadTestImage(testimage, &ppf_in));
- EXPECT_EQ("RGB_D65_202_Rel_HLG", Description(ppf_in.color_encoding));
+ EXPECT_EQ("Rec2100HLG", Description(ppf_in.color_encoding));
EXPECT_EQ(16, ppf_in.info.bits_per_sample);
std::vector<uint8_t> compressed;
diff --git a/third_party/jpeg-xl/lib/extras/metrics.cc b/third_party/jpeg-xl/lib/extras/metrics.cc
index 4259d3c375..f70ab0a61d 100644
--- a/third_party/jpeg-xl/lib/extras/metrics.cc
+++ b/third_party/jpeg-xl/lib/extras/metrics.cc
@@ -16,6 +16,7 @@
#include <hwy/highway.h>
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
HWY_BEFORE_NAMESPACE();
diff --git a/third_party/jpeg-xl/lib/extras/packed_image_convert.cc b/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
index 2ad001bf09..7e4b592fc4 100644
--- a/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
+++ b/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
@@ -11,6 +11,7 @@
#include <cstdint>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_external_image.h"
diff --git a/third_party/jpeg-xl/lib/include/jxl/color_encoding.h b/third_party/jpeg-xl/lib/include/jxl/color_encoding.h
index e6325dcb30..f5de188223 100644
--- a/third_party/jpeg-xl/lib/include/jxl/color_encoding.h
+++ b/third_party/jpeg-xl/lib/include/jxl/color_encoding.h
@@ -14,8 +14,6 @@
#ifndef JXL_COLOR_ENCODING_H_
#define JXL_COLOR_ENCODING_H_
-#include <stdint.h>
-
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
diff --git a/third_party/jpeg-xl/lib/jpegli/color_transform.cc b/third_party/jpeg-xl/lib/jpegli/color_transform.cc
index 60a0dc83bb..ec906bedce 100644
--- a/third_party/jpeg-xl/lib/jpegli/color_transform.cc
+++ b/third_party/jpeg-xl/lib/jpegli/color_transform.cc
@@ -26,11 +26,16 @@ using hwy::HWY_NAMESPACE::Mul;
using hwy::HWY_NAMESPACE::MulAdd;
using hwy::HWY_NAMESPACE::Sub;
-void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
+template <int kRed, int kGreen, int kBlue, int kAlpha>
+void YCbCrToExtRGB(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
- float* JXL_RESTRICT row0 = row[0];
- float* JXL_RESTRICT row1 = row[1];
- float* JXL_RESTRICT row2 = row[2];
+ const float* row_y = row[0];
+ const float* row_cb = row[1];
+ const float* row_cr = row[2];
+ float* row_r = row[kRed];
+ float* row_g = row[kGreen];
+ float* row_b = row[kBlue];
+ float* row_a = row[kAlpha];
// Full-range BT.601 as defined by JFIF Clause 7:
// https://www.itu.int/rec/T-REC-T.871-201105-I/en
@@ -38,20 +43,48 @@ void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
const auto cgcb = Set(df, -0.114f * 1.772f / 0.587f);
const auto cgcr = Set(df, -0.299f * 1.402f / 0.587f);
const auto cbcb = Set(df, 1.772f);
+ const auto alpha_opaque = Set(df, 127.0f / 255.0f);
for (size_t x = 0; x < xsize; x += Lanes(df)) {
- const auto y_vec = Load(df, row0 + x);
- const auto cb_vec = Load(df, row1 + x);
- const auto cr_vec = Load(df, row2 + x);
+ const auto y_vec = Load(df, row_y + x);
+ const auto cb_vec = Load(df, row_cb + x);
+ const auto cr_vec = Load(df, row_cr + x);
const auto r_vec = MulAdd(crcr, cr_vec, y_vec);
const auto g_vec = MulAdd(cgcr, cr_vec, MulAdd(cgcb, cb_vec, y_vec));
const auto b_vec = MulAdd(cbcb, cb_vec, y_vec);
- Store(r_vec, df, row0 + x);
- Store(g_vec, df, row1 + x);
- Store(b_vec, df, row2 + x);
+ Store(r_vec, df, row_r + x);
+ Store(g_vec, df, row_g + x);
+ Store(b_vec, df, row_b + x);
+ if (kAlpha >= 0) {
+ Store(alpha_opaque, df, row_a + x);
+ }
}
}
+void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<0, 1, 2, -1>(row, xsize);
+}
+
+void YCbCrToBGR(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<2, 1, 0, -1>(row, xsize);
+}
+
+void YCbCrToRGBA(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<0, 1, 2, 3>(row, xsize);
+}
+
+void YCbCrToBGRA(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<2, 1, 0, 3>(row, xsize);
+}
+
+void YCbCrToARGB(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<1, 2, 3, 0>(row, xsize);
+}
+
+void YCbCrToABGR(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<3, 2, 1, 0>(row, xsize);
+}
+
void YCCKToCMYK(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
@@ -66,11 +99,15 @@ void YCCKToCMYK(float* row[kMaxComponents], size_t xsize) {
}
}
-void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
+template <int kRed, int kGreen, int kBlue>
+void ExtRGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
- float* JXL_RESTRICT row0 = row[0];
- float* JXL_RESTRICT row1 = row[1];
- float* JXL_RESTRICT row2 = row[2];
+ const float* row_r = row[kRed];
+ const float* row_g = row[kGreen];
+ const float* row_b = row[kBlue];
+ float* row_y = row[0];
+ float* row_cb = row[1];
+ float* row_cr = row[2];
// Full-range BT.601 as defined by JFIF Clause 7:
// https://www.itu.int/rec/T-REC-T.871-201105-I/en
const auto c128 = Set(df, 128.0f);
@@ -85,9 +122,9 @@ void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const auto kNormB = Div(Set(df, 1.0f), (Add(kR, Add(kG, kAmpB))));
for (size_t x = 0; x < xsize; x += Lanes(df)) {
- const auto r = Load(df, row0 + x);
- const auto g = Load(df, row1 + x);
- const auto b = Load(df, row2 + x);
+ const auto r = Load(df, row_r + x);
+ const auto g = Load(df, row_g + x);
+ const auto b = Load(df, row_b + x);
const auto r_base = Mul(r, kR);
const auto r_diff = Mul(r, kDiffR);
const auto g_base = Mul(g, kG);
@@ -96,12 +133,28 @@ void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const auto y_base = Add(r_base, Add(g_base, b_base));
const auto cb_vec = MulAdd(Sub(b_diff, y_base), kNormB, c128);
const auto cr_vec = MulAdd(Sub(r_diff, y_base), kNormR, c128);
- Store(y_base, df, row0 + x);
- Store(cb_vec, df, row1 + x);
- Store(cr_vec, df, row2 + x);
+ Store(y_base, df, row_y + x);
+ Store(cb_vec, df, row_cb + x);
+ Store(cr_vec, df, row_cr + x);
}
}
+void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<0, 1, 2>(row, xsize);
+}
+
+void BGRToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<2, 1, 0>(row, xsize);
+}
+
+void ARGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<1, 2, 3>(row, xsize);
+}
+
+void ABGRToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<3, 2, 1>(row, xsize);
+}
+
void CMYKToYCCK(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
@@ -127,7 +180,15 @@ namespace jpegli {
HWY_EXPORT(CMYKToYCCK);
HWY_EXPORT(YCCKToCMYK);
HWY_EXPORT(YCbCrToRGB);
+HWY_EXPORT(YCbCrToBGR);
+HWY_EXPORT(YCbCrToRGBA);
+HWY_EXPORT(YCbCrToBGRA);
+HWY_EXPORT(YCbCrToARGB);
+HWY_EXPORT(YCbCrToABGR);
HWY_EXPORT(RGBToYCbCr);
+HWY_EXPORT(BGRToYCbCr);
+HWY_EXPORT(ARGBToYCbCr);
+HWY_EXPORT(ABGRToYCbCr);
bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
switch (colorspace) {
@@ -164,16 +225,73 @@ bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
void NullTransform(float* row[kMaxComponents], size_t len) {}
+void FillAlpha(float* row, size_t len) {
+ static const float kAlpha = 127.0f / 255.0f;
+ for (size_t i = 0; i < len; ++i) {
+ row[i] = kAlpha;
+ }
+}
+
+// Works for BGR as well.
void GrayscaleToRGB(float* row[kMaxComponents], size_t len) {
memcpy(row[1], row[0], len * sizeof(row[1][0]));
memcpy(row[2], row[0], len * sizeof(row[2][0]));
}
+// Works for BGRA as well.
+void GrayscaleToRGBA(float* row[kMaxComponents], size_t len) {
+ memcpy(row[1], row[0], len * sizeof(row[1][0]));
+ memcpy(row[2], row[0], len * sizeof(row[2][0]));
+ FillAlpha(row[3], len);
+}
+
+// Works for ABGR as well.
+void GrayscaleToARGB(float* row[kMaxComponents], size_t len) {
+ memcpy(row[1], row[0], len * sizeof(row[1][0]));
+ memcpy(row[2], row[0], len * sizeof(row[2][0]));
+ memcpy(row[3], row[0], len * sizeof(row[1][0]));
+ FillAlpha(row[0], len);
+}
+
void GrayscaleToYCbCr(float* row[kMaxComponents], size_t len) {
memset(row[1], 0, len * sizeof(row[1][0]));
memset(row[2], 0, len * sizeof(row[2][0]));
}
+void RGBToBGR(float* row[kMaxComponents], size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ std::swap(row[0][i], row[2][i]);
+ }
+}
+
+void RGBToRGBA(float* row[kMaxComponents], size_t len) {
+ FillAlpha(row[3], len);
+}
+
+void RGBToBGRA(float* row[kMaxComponents], size_t len) {
+ static const float kAlpha = 127.0f / 255.0f;
+ for (size_t i = 0; i < len; ++i) {
+ std::swap(row[0][i], row[2][i]);
+ row[3][i] = kAlpha;
+ }
+}
+
+void RGBToARGB(float* row[kMaxComponents], size_t len) {
+ memcpy(row[3], row[2], len * sizeof(row[1][0]));
+ memcpy(row[2], row[1], len * sizeof(row[2][0]));
+ memcpy(row[1], row[0], len * sizeof(row[1][0]));
+ FillAlpha(row[0], len);
+}
+
+void RGBToABGR(float* row[kMaxComponents], size_t len) {
+ static const float kAlpha = 127.0f / 255.0f;
+ for (size_t i = 0; i < len; ++i) {
+ std::swap(row[1][i], row[2][i]);
+ row[3][i] = row[0][i];
+ row[0][i] = kAlpha;
+ }
+}
+
void ChooseColorTransform(j_compress_ptr cinfo) {
jpeg_comp_master* m = cinfo->master;
if (!CheckColorSpaceComponents(cinfo->input_components,
@@ -226,6 +344,43 @@ void ChooseColorTransform(j_compress_ptr cinfo) {
}
}
+ if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
+ cinfo->jpeg_color_space == JCS_YCbCr) {
+ switch (cinfo->in_color_space) {
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_RGBX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ break;
+ case JCS_EXT_BGR:
+ case JCS_EXT_BGRX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(BGRToYCbCr);
+ break;
+ case JCS_EXT_XRGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ARGBToYCbCr);
+ break;
+ case JCS_EXT_XBGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ABGRToYCbCr);
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ break;
+ case JCS_EXT_BGRA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(BGRToYCbCr);
+ break;
+ case JCS_EXT_ARGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ARGBToYCbCr);
+ break;
+ case JCS_EXT_ABGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ABGRToYCbCr);
+ break;
+#endif
+ default:; // Nothing to do.
+ }
+ }
+
if (m->color_transform == nullptr) {
// TODO(szabadka) Support more color transforms.
JPEGLI_ERROR("Unsupported color transform %d -> %d", cinfo->in_color_space,
@@ -257,18 +412,123 @@ void ChooseColorTransform(j_decompress_ptr cinfo) {
m->color_transform = nullptr;
if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
- if (cinfo->out_color_space == JCS_RGB) {
- m->color_transform = GrayscaleToRGB;
+ switch (cinfo->out_color_space) {
+ case JCS_RGB:
+ m->color_transform = GrayscaleToRGB;
+ break;
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_BGR:
+ m->color_transform = GrayscaleToRGB;
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_BGRX:
+ m->color_transform = GrayscaleToRGBA;
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_XBGR:
+ m->color_transform = GrayscaleToARGB;
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ case JCS_EXT_BGRA:
+ m->color_transform = GrayscaleToRGBA;
+ break;
+ case JCS_EXT_ARGB:
+ case JCS_EXT_ABGR:
+ m->color_transform = GrayscaleToARGB;
+ break;
+#endif
+ default:
+ m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_RGB) {
- if (cinfo->out_color_space == JCS_GRAYSCALE) {
- m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ break;
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ m->color_transform = NullTransform;
+ break;
+ case JCS_EXT_BGR:
+ m->color_transform = RGBToBGR;
+ break;
+ case JCS_EXT_RGBX:
+ m->color_transform = RGBToRGBA;
+ break;
+ case JCS_EXT_BGRX:
+ m->color_transform = RGBToBGRA;
+ break;
+ case JCS_EXT_XRGB:
+ m->color_transform = RGBToARGB;
+ break;
+ case JCS_EXT_XBGR:
+ m->color_transform = RGBToABGR;
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ m->color_transform = RGBToRGBA;
+ break;
+ case JCS_EXT_BGRA:
+ m->color_transform = RGBToBGRA;
+ break;
+ case JCS_EXT_ARGB:
+ m->color_transform = RGBToARGB;
+ break;
+ case JCS_EXT_ABGR:
+ m->color_transform = RGBToABGR;
+ break;
+#endif
+ default:
+ m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_YCbCr) {
- if (cinfo->out_color_space == JCS_RGB) {
- m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
- } else if (cinfo->out_color_space == JCS_GRAYSCALE) {
- m->color_transform = NullTransform;
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ m->color_transform = NullTransform;
+ break;
+ case JCS_RGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
+ break;
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
+ break;
+ case JCS_EXT_BGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGR);
+ break;
+ case JCS_EXT_RGBX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGBA);
+ break;
+ case JCS_EXT_BGRX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGRA);
+ break;
+ case JCS_EXT_XRGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToARGB);
+ break;
+ case JCS_EXT_XBGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToABGR);
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGBA);
+ break;
+ case JCS_EXT_BGRA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGRA);
+ break;
+ case JCS_EXT_ARGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToARGB);
+ break;
+ case JCS_EXT_ABGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToABGR);
+ break;
+#endif
+ default:
+ m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_YCCK) {
if (cinfo->out_color_space == JCS_CMYK) {
diff --git a/third_party/jpeg-xl/lib/jpegli/common.h b/third_party/jpeg-xl/lib/jpegli/common.h
index 42487f2b89..514483afef 100644
--- a/third_party/jpeg-xl/lib/jpegli/common.h
+++ b/third_party/jpeg-xl/lib/jpegli/common.h
@@ -20,12 +20,7 @@
#ifndef LIB_JPEGLI_COMMON_H_
#define LIB_JPEGLI_COMMON_H_
-/* clang-format off */
-#include <stdio.h>
-#include <jpeglib.h>
-/* clang-format on */
-
-#include "lib/jpegli/types.h"
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
diff --git a/third_party/jpeg-xl/lib/jpegli/decode.cc b/third_party/jpeg-xl/lib/jpegli/decode.cc
index 9fdf68dd18..d967b787d3 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode.cc
@@ -54,6 +54,7 @@ void InitializeImage(j_decompress_ptr cinfo) {
m->found_soi_ = false;
m->found_dri_ = false;
m->found_sof_ = false;
+ m->found_sos_ = false;
m->found_eoi_ = false;
m->icc_index_ = 0;
m->icc_total_ = 0;
@@ -243,10 +244,14 @@ void PrepareForScan(j_decompress_ptr cinfo) {
// Copy quantization tables into comp_info.
for (int i = 0; i < cinfo->comps_in_scan; ++i) {
jpeg_component_info* comp = cinfo->cur_comp_info[i];
+ int quant_tbl_idx = comp->quant_tbl_no;
+ JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[quant_tbl_idx];
+ if (!quant_table) {
+ JPEGLI_ERROR("Quantization table with index %d not found", quant_tbl_idx);
+ }
if (comp->quant_table == nullptr) {
comp->quant_table = Allocate<JQUANT_TBL>(cinfo, 1, JPOOL_IMAGE);
- memcpy(comp->quant_table, cinfo->quant_tbl_ptrs[comp->quant_tbl_no],
- sizeof(JQUANT_TBL));
+ memcpy(comp->quant_table, quant_table, sizeof(JQUANT_TBL));
}
}
if (cinfo->comps_in_scan == 1) {
@@ -723,16 +728,36 @@ void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
}
}
}
- if (cinfo->out_color_space == JCS_GRAYSCALE) {
- cinfo->out_color_components = 1;
- } else if (cinfo->out_color_space == JCS_RGB ||
- cinfo->out_color_space == JCS_YCbCr) {
- cinfo->out_color_components = 3;
- } else if (cinfo->out_color_space == JCS_CMYK ||
- cinfo->out_color_space == JCS_YCCK) {
- cinfo->out_color_components = 4;
- } else {
- cinfo->out_color_components = cinfo->num_components;
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ break;
+ case JCS_RGB:
+ case JCS_YCbCr:
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_BGR:
+#endif
+ cinfo->out_color_components = 3;
+ break;
+ case JCS_CMYK:
+ case JCS_YCCK:
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGBX:
+ case JCS_EXT_BGRX:
+ case JCS_EXT_XBGR:
+ case JCS_EXT_XRGB:
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ case JCS_EXT_BGRA:
+ case JCS_EXT_ABGR:
+ case JCS_EXT_ARGB:
+#endif
+ cinfo->out_color_components = 4;
+ break;
+ default:
+ cinfo->out_color_components = cinfo->num_components;
}
cinfo->output_components =
cinfo->quantize_colors ? 1 : cinfo->out_color_components;
diff --git a/third_party/jpeg-xl/lib/jpegli/decode.h b/third_party/jpeg-xl/lib/jpegli/decode.h
index f5b099eda3..668d630586 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode.h
+++ b/third_party/jpeg-xl/lib/jpegli/decode.h
@@ -21,6 +21,7 @@
#define LIB_JPEGLI_DECODE_H_
#include "lib/jpegli/common.h"
+#include "lib/jpegli/types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
index 3ecd479951..c429f0f810 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
@@ -3,17 +3,27 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <jxl/types.h>
+
+#include <algorithm>
#include <cstdint>
#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
#include <vector>
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/base/byte_order.h"
+#include "lib/jpegli/types.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
@@ -894,7 +904,9 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
all_tests.push_back(config);
}
// Tests for color transforms.
- for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_GRAYSCALE}) {
+ for (J_COLOR_SPACE out_color_space :
+ {JCS_RGB, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR, JCS_EXT_RGBA,
+ JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
TestConfig config;
config.input.xsize = config.input.ysize = 256;
config.input.color_space = JCS_GRAYSCALE;
@@ -903,7 +915,9 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
all_tests.push_back(config);
}
for (J_COLOR_SPACE jpeg_color_space : {JCS_RGB, JCS_YCbCr}) {
- for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
+ for (J_COLOR_SPACE out_color_space :
+ {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR,
+ JCS_EXT_RGBA, JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
if (jpeg_color_space == JCS_RGB && out_color_space == JCS_YCbCr) continue;
TestConfig config;
config.input.xsize = config.input.ysize = 256;
@@ -1108,6 +1122,8 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
TestConfig config;
config.input.xsize = xsize;
config.input.ysize = ysize;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
}
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_internal.h b/third_party/jpeg-xl/lib/jpegli/decode_internal.h
index 37dfcc4526..8455fae392 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_internal.h
+++ b/third_party/jpeg-xl/lib/jpegli/decode_internal.h
@@ -6,14 +6,15 @@
#ifndef LIB_JPEGLI_DECODE_INTERNAL_H_
#define LIB_JPEGLI_DECODE_INTERNAL_H_
-#include <stdint.h>
#include <sys/types.h>
+#include <cstdint>
#include <vector>
#include "lib/jpegli/common.h"
#include "lib/jpegli/common_internal.h"
#include "lib/jpegli/huffman.h"
+#include "lib/jpegli/types.h"
namespace jpegli {
@@ -58,6 +59,7 @@ struct jpeg_decomp_master {
bool found_soi_;
bool found_dri_;
bool found_sof_;
+ bool found_sos_;
bool found_eoi_;
// Whether this jpeg has multiple scans (progressive or non-interleaved
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_marker.cc b/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
index a9ed4df329..2621ed0867 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
@@ -103,9 +103,6 @@ void ProcessSOF(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
int quant_tbl_idx = ReadUint8(data, &pos);
JPEG_VERIFY_INPUT(quant_tbl_idx, 0, NUM_QUANT_TBLS - 1);
comp->quant_tbl_no = quant_tbl_idx;
- if (cinfo->quant_tbl_ptrs[quant_tbl_idx] == nullptr) {
- JPEGLI_ERROR("Quantization table with index %u not found", quant_tbl_idx);
- }
comp->quant_table = nullptr; // will be allocated after SOS marker
}
JPEG_VERIFY_MARKER_END();
@@ -168,6 +165,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
if (!m->found_sof_) {
JPEGLI_ERROR("Unexpected SOS marker.");
}
+ m->found_sos_ = true;
size_t pos = 2;
JPEG_VERIFY_LEN(1);
cinfo->comps_in_scan = ReadUint8(data, &pos);
@@ -337,7 +335,7 @@ void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
void ProcessDQT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
jpeg_decomp_master* m = cinfo->master;
- if (m->found_sof_) {
+ if (m->found_sos_) {
JPEGLI_ERROR("Updating quant tables between scans is not supported.");
}
size_t pos = 2;
diff --git a/third_party/jpeg-xl/lib/jpegli/encode.cc b/third_party/jpeg-xl/lib/jpegli/encode.cc
index 5326f2cb0f..6cfd54ad30 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode.cc
+++ b/third_party/jpeg-xl/lib/jpegli/encode.cc
@@ -283,15 +283,15 @@ void ProcessCompressionParams(j_compress_ptr cinfo) {
JPEGLI_ERROR("Invalid sampling factor %d x %d", comp->h_samp_factor,
comp->v_samp_factor);
}
+ if (cinfo->num_components == 1) {
+ // Force samp factors to 1x1 for single-component images.
+ comp->h_samp_factor = comp->v_samp_factor = 1;
+ }
cinfo->max_h_samp_factor =
std::max(comp->h_samp_factor, cinfo->max_h_samp_factor);
cinfo->max_v_samp_factor =
std::max(comp->v_samp_factor, cinfo->max_v_samp_factor);
}
- if (cinfo->num_components == 1 &&
- (cinfo->max_h_samp_factor != 1 || cinfo->max_v_samp_factor != 1)) {
- JPEGLI_ERROR("Sampling is not supported for simgle component image.");
- }
size_t iMCU_width = DCTSIZE * cinfo->max_h_samp_factor;
size_t iMCU_height = DCTSIZE * cinfo->max_v_samp_factor;
size_t total_iMCU_cols = DivCeil(cinfo->image_width, iMCU_width);
@@ -713,18 +713,31 @@ void jpegli_set_defaults(j_compress_ptr cinfo) {
void jpegli_default_colorspace(j_compress_ptr cinfo) {
CheckState(cinfo, jpegli::kEncStart);
+ if (cinfo->in_color_space == JCS_RGB && cinfo->master->xyb_mode) {
+ jpegli_set_colorspace(cinfo, JCS_RGB);
+ return;
+ }
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
jpegli_set_colorspace(cinfo, JCS_GRAYSCALE);
break;
- case JCS_RGB: {
- if (cinfo->master->xyb_mode) {
- jpegli_set_colorspace(cinfo, JCS_RGB);
- } else {
- jpegli_set_colorspace(cinfo, JCS_YCbCr);
- }
+ case JCS_RGB:
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_BGR:
+ case JCS_EXT_RGBX:
+ case JCS_EXT_BGRX:
+ case JCS_EXT_XRGB:
+ case JCS_EXT_XBGR:
+#endif
+#if JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ case JCS_EXT_BGRA:
+ case JCS_EXT_ARGB:
+ case JCS_EXT_ABGR:
+#endif
+ jpegli_set_colorspace(cinfo, JCS_YCbCr);
break;
- }
case JCS_YCbCr:
jpegli_set_colorspace(cinfo, JCS_YCbCr);
break;
@@ -806,6 +819,11 @@ void jpegli_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace) {
cinfo->comp_info[2].quant_tbl_no = 1;
cinfo->comp_info[1].dc_tbl_no = cinfo->comp_info[1].ac_tbl_no = 1;
cinfo->comp_info[2].dc_tbl_no = cinfo->comp_info[2].ac_tbl_no = 1;
+ // Use chroma subsampling by default
+ cinfo->comp_info[0].h_samp_factor = cinfo->comp_info[0].v_samp_factor = 2;
+ if (colorspace == JCS_YCCK) {
+ cinfo->comp_info[3].h_samp_factor = cinfo->comp_info[3].v_samp_factor = 2;
+ }
}
}
diff --git a/third_party/jpeg-xl/lib/jpegli/encode.h b/third_party/jpeg-xl/lib/jpegli/encode.h
index ed34838450..33de674471 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode.h
+++ b/third_party/jpeg-xl/lib/jpegli/encode.h
@@ -21,6 +21,7 @@
#define LIB_JPEGLI_ENCODE_H_
#include "lib/jpegli/common.h"
+#include "lib/jpegli/types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
diff --git a/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
index 2978b3f35d..81b1b25bef 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
@@ -4,14 +4,23 @@
// license that can be found in the LICENSE file.
#include <algorithm>
-#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
#include <vector>
#include "lib/jpegli/encode.h"
-#include "lib/jpegli/error.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/sanitizers.h"
+#include "lib/jpegli/types.h"
+#include "lib/jxl/base/status.h"
namespace jpegli {
namespace {
@@ -372,6 +381,8 @@ std::vector<TestConfig> GenerateTests() {
{
TestConfig config;
config.jparams.quality = 100;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 6.6;
config.max_dist = 0.6;
all_tests.push_back(config);
@@ -510,17 +521,23 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.libjpeg_mode = true;
config.max_bpp = 2.1;
config.max_dist = 1.7;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
- for (J_COLOR_SPACE in_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
+ for (J_COLOR_SPACE in_color_space :
+ {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR,
+ JCS_EXT_RGBA, JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
for (J_COLOR_SPACE jpeg_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
- if (jpeg_color_space == JCS_RGB && in_color_space == JCS_YCbCr) continue;
+ if (jpeg_color_space == JCS_RGB && in_color_space >= JCS_YCbCr) continue;
TestConfig config;
config.input.xsize = config.input.ysize = 256;
config.input.color_space = in_color_space;
config.jparams.set_jpeg_colorspace = true;
config.jparams.jpeg_color_space = jpeg_color_space;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = jpeg_color_space == JCS_RGB ? 4.5 : 1.85;
config.max_dist = jpeg_color_space == JCS_RGB ? 1.4 : 2.05;
all_tests.push_back(config);
@@ -536,6 +553,8 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.set_jpeg_colorspace = true;
config.jparams.jpeg_color_space = jpeg_color_space;
}
+ config.jparams.h_sampling = {1, 1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1, 1};
config.max_bpp = jpeg_color_space == JCS_CMYK ? 4.0 : 3.6;
config.max_dist = jpeg_color_space == JCS_CMYK ? 1.2 : 1.5;
all_tests.push_back(config);
@@ -546,6 +565,8 @@ std::vector<TestConfig> GenerateTests() {
config.input.color_space = JCS_YCbCr;
config.max_bpp = 1.6;
config.max_dist = 1.35;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
for (bool xyb : {false, true}) {
@@ -596,6 +617,8 @@ std::vector<TestConfig> GenerateTests() {
table.add_raw = add_raw;
table.Generate();
config.jparams.optimize_coding = 1;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.jparams.quant_tables.push_back(table);
config.jparams.quant_indexes = {0, 0, 0};
float q = (type == 0 ? 16 : type) * scale * 0.01f;
@@ -614,6 +637,8 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 2.25;
config.max_dist = 2.8;
all_tests.push_back(config);
@@ -626,6 +651,8 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
CustomQuantTable table;
table.slot_idx = slot_idx;
table.Generate();
@@ -643,6 +670,10 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.xyb_mode = xyb;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
+ if (!xyb) {
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
+ }
{
CustomQuantTable table;
table.slot_idx = 0;
@@ -667,6 +698,10 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.xyb_mode = xyb;
config.jparams.quant_indexes = {0, 1, 2};
+ if (!xyb) {
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
+ }
{
CustomQuantTable table;
table.slot_idx = 0;
@@ -738,6 +773,8 @@ std::vector<TestConfig> GenerateTests() {
}
config.jparams.progressive_mode = 0;
config.jparams.optimize_coding = 0;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 1.85;
config.max_dist = 2.05;
if (input_mode == COEFFICIENTS) {
diff --git a/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc b/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
index bcd7355124..582c6b170b 100644
--- a/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
@@ -3,12 +3,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+
+#include "lib/jpegli/common.h"
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
-#include "lib/jpegli/error.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/sanitizers.h"
+#include "lib/jxl/base/status.h"
namespace jpegli {
namespace {
@@ -996,6 +1004,9 @@ TEST(EncoderErrorHandlingTest, AddOnTableNoStringParam) {
const uint8_t kCompressed0[] = {
// SOI
0xff, 0xd8, //
+ // SOF
+ 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, //
+ 0x01, 0x11, 0x00, //
// DQT
0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x03, 0x02, //
0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05, //
@@ -1004,9 +1015,6 @@ const uint8_t kCompressed0[] = {
0x0e, 0x12, 0x10, 0x0d, 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, //
0x16, 0x10, 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0c, 0x0f, //
0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, 0x14, //
- // SOF
- 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, //
- 0x01, 0x11, 0x00, //
// DHT
0xff, 0xc4, 0x00, 0xd2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, //
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
@@ -1039,8 +1047,8 @@ const uint8_t kCompressed0[] = {
};
const size_t kLen0 = sizeof(kCompressed0);
-const size_t kDQTOffset = 2;
-const size_t kSOFOffset = 71;
+const size_t kSOFOffset = 2;
+const size_t kDQTOffset = 15;
const size_t kDHTOffset = 84;
const size_t kSOSOffset = 296;
diff --git a/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc b/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
index 6546b7b087..dc5aee2fc5 100644
--- a/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
@@ -3,16 +3,24 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include <cmath>
+#include <jxl/types.h>
+
+#include <algorithm>
+#include <cstddef>
#include <cstdint>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
#include <vector>
#include "lib/jpegli/decode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
diff --git a/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc b/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
index 020adf5e9e..d34ec7e999 100644
--- a/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
+++ b/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
@@ -5,12 +5,7 @@
#include "lib/jpegli/libjpeg_test_util.h"
-/* clang-format off */
-#include <stdio.h>
-#include <jpeglib.h>
-#include <setjmp.h>
-/* clang-format on */
-
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#include "lib/jxl/sanitizers.h"
namespace jpegli {
diff --git a/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc b/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
index 3cb2fd3ee4..44d63fdcbb 100644
--- a/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
@@ -3,7 +3,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
@@ -130,6 +141,7 @@ TEST_P(OutputSuspensionTestParam, RawData) {
cinfo.input_components = input.components;
cinfo.in_color_space = JCS_YCbCr;
jpegli_set_defaults(&cinfo);
+ cinfo.comp_info[0].h_samp_factor = config.jparams.h_sampling[0];
cinfo.comp_info[0].v_samp_factor = config.jparams.v_sampling[0];
jpegli_set_progressive_level(&cinfo, 0);
cinfo.optimize_coding = FALSE;
diff --git a/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc b/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
index a513b7063b..2d49ac16ba 100644
--- a/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
@@ -3,14 +3,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include <cmath>
#include <cstdint>
#include <vector>
#include "lib/jpegli/decode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/base/status.h"
namespace jpegli {
namespace {
diff --git a/third_party/jpeg-xl/lib/jpegli/streaming_test.cc b/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
index 1f19dc2045..29a224385f 100644
--- a/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
@@ -3,8 +3,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
diff --git a/third_party/jpeg-xl/lib/jpegli/test_utils.cc b/third_party/jpeg-xl/lib/jpegli/test_utils.cc
index db5a30e8dc..5315c692a1 100644
--- a/third_party/jpeg-xl/lib/jpegli/test_utils.cc
+++ b/third_party/jpeg-xl/lib/jpegli/test_utils.cc
@@ -8,6 +8,7 @@
#include <cmath>
#include <cstdint>
#include <fstream>
+#include <sstream>
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
@@ -171,6 +172,18 @@ std::string ColorSpaceName(J_COLOR_SPACE colorspace) {
return "CMYK";
case JCS_YCCK:
return "YCCK";
+ case JCS_EXT_RGB:
+ return "EXT_RGB";
+ case JCS_EXT_BGR:
+ return "EXT_BGR";
+ case JCS_EXT_RGBA:
+ return "EXT_RGBA";
+ case JCS_EXT_BGRA:
+ return "EXT_BGRA";
+ case JCS_EXT_ARGB:
+ return "EXT_ARGB";
+ case JCS_EXT_ABGR:
+ return "EXT_ABGR";
default:
return "";
}
@@ -301,9 +314,12 @@ std::ostream& operator<<(std::ostream& os, const CompressParams& jparams) {
void SetNumChannels(J_COLOR_SPACE colorspace, size_t* channels) {
if (colorspace == JCS_GRAYSCALE) {
*channels = 1;
- } else if (colorspace == JCS_RGB || colorspace == JCS_YCbCr) {
+ } else if (colorspace == JCS_RGB || colorspace == JCS_YCbCr ||
+ colorspace == JCS_EXT_RGB || colorspace == JCS_EXT_BGR) {
*channels = 3;
- } else if (colorspace == JCS_CMYK || colorspace == JCS_YCCK) {
+ } else if (colorspace == JCS_CMYK || colorspace == JCS_YCCK ||
+ colorspace == JCS_EXT_RGBA || colorspace == JCS_EXT_BGRA ||
+ colorspace == JCS_EXT_ARGB || colorspace == JCS_EXT_ABGR) {
*channels = 4;
} else if (colorspace == JCS_UNKNOWN) {
JXL_CHECK(*channels <= 4);
@@ -330,7 +346,28 @@ void ConvertPixel(const uint8_t* input_rgb, uint8_t* out,
if (colorspace == JCS_GRAYSCALE) {
const float Y = 0.299f * r + 0.587f * g + 0.114f * b;
out8[0] = static_cast<uint8_t>(std::round(Y * kMul));
- } else if (colorspace == JCS_RGB || colorspace == JCS_UNKNOWN) {
+ } else if (colorspace == JCS_RGB || colorspace == JCS_EXT_RGB ||
+ colorspace == JCS_EXT_RGBA) {
+ out8[0] = input_rgb[0];
+ out8[1] = input_rgb[1];
+ out8[2] = input_rgb[2];
+ if (colorspace == JCS_EXT_RGBA) out8[3] = 255;
+ } else if (colorspace == JCS_EXT_BGR || colorspace == JCS_EXT_BGRA) {
+ out8[2] = input_rgb[0];
+ out8[1] = input_rgb[1];
+ out8[0] = input_rgb[2];
+ if (colorspace == JCS_EXT_BGRA) out8[3] = 255;
+ } else if (colorspace == JCS_EXT_ABGR) {
+ out8[0] = 255;
+ out8[3] = input_rgb[0];
+ out8[2] = input_rgb[1];
+ out8[1] = input_rgb[2];
+ } else if (colorspace == JCS_EXT_ARGB) {
+ out8[0] = 255;
+ out8[1] = input_rgb[0];
+ out8[2] = input_rgb[1];
+ out8[3] = input_rgb[2];
+ } else if (colorspace == JCS_UNKNOWN) {
for (size_t c = 0; c < num_channels; ++c) {
out8[c] = input_rgb[std::min<size_t>(2, c)];
}
@@ -390,9 +427,23 @@ void ConvertPixel(const uint8_t* input_rgb, uint8_t* out,
void ConvertToGrayscale(TestImage* img) {
if (img->color_space == JCS_GRAYSCALE) return;
JXL_CHECK(img->data_type == JPEGLI_TYPE_UINT8);
- for (size_t i = 0; i < img->pixels.size(); i += 3) {
- if (img->color_space == JCS_RGB) {
- ConvertPixel(&img->pixels[i], &img->pixels[i / 3], JCS_GRAYSCALE, 1);
+ bool rgb_pre_alpha =
+ img->color_space == JCS_EXT_ARGB || img->color_space == JCS_EXT_ABGR;
+ bool rgb_post_alpha =
+ img->color_space == JCS_EXT_RGBA || img->color_space == JCS_EXT_BGRA;
+ bool rgb_alpha = rgb_pre_alpha || rgb_post_alpha;
+ bool is_rgb = img->color_space == JCS_RGB ||
+ img->color_space == JCS_EXT_RGB ||
+ img->color_space == JCS_EXT_BGR || rgb_alpha;
+ bool switch_br = img->color_space == JCS_EXT_BGR ||
+ img->color_space == JCS_EXT_ABGR ||
+ img->color_space == JCS_EXT_BGRA;
+ size_t stride = rgb_alpha ? 4 : 3;
+ size_t offset = rgb_pre_alpha ? 1 : 0;
+ for (size_t i = offset; i < img->pixels.size(); i += stride) {
+ if (is_rgb) {
+ if (switch_br) std::swap(img->pixels[i], img->pixels[i + 2]);
+ ConvertPixel(&img->pixels[i], &img->pixels[i / stride], JCS_GRAYSCALE, 1);
} else if (img->color_space == JCS_YCbCr) {
img->pixels[i / 3] = img->pixels[i];
}
diff --git a/third_party/jpeg-xl/lib/jpegli/test_utils.h b/third_party/jpeg-xl/lib/jpegli/test_utils.h
index 132cfd042a..22c620c46c 100644
--- a/third_party/jpeg-xl/lib/jpegli/test_utils.h
+++ b/third_party/jpeg-xl/lib/jpegli/test_utils.h
@@ -6,22 +6,15 @@
#ifndef LIB_JPEGLI_TEST_UTILS_H_
#define LIB_JPEGLI_TEST_UTILS_H_
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
+#include <cstddef>
+#include <cstdint>
#include <string>
#include <vector>
-/* clang-format off */
-#include <stdio.h>
-#include <jpeglib.h>
-#include <setjmp.h>
-/* clang-format on */
-
-#include "lib/jpegli/common.h"
-#include "lib/jpegli/libjpeg_test_util.h"
#include "lib/jpegli/test_params.h"
+#include "lib/jpegli/types.h"
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
namespace jpegli {
@@ -127,4 +120,15 @@ void VerifyOutputImage(const TestImage& input, const TestImage& output,
} // namespace jpegli
+#if !defined(FUZZ_TEST)
+struct FuzzTestSink {
+ template <typename F>
+ FuzzTestSink WithSeeds(F) {
+ return *this;
+ }
+};
+#define FUZZ_TEST(A, B) \
+ const JXL_MAYBE_UNUSED FuzzTestSink unused##A##B = FuzzTestSink()
+#endif
+
#endif // LIB_JPEGLI_TEST_UTILS_H_
diff --git a/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
index 13c81a1119..413d5ae996 100644
--- a/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
@@ -3,10 +3,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
#include <vector>
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
#include "lib/jxl/base/status.h"
diff --git a/third_party/jpeg-xl/lib/jxl/ac_context.h b/third_party/jpeg-xl/lib/jxl/ac_context.h
index a2b9e046d1..6529a9bb88 100644
--- a/third_party/jpeg-xl/lib/jxl/ac_context.h
+++ b/third_party/jpeg-xl/lib/jxl/ac_context.h
@@ -62,7 +62,8 @@ static JXL_INLINE size_t ZeroDensityContext(size_t nonzeros_left, size_t k,
size_t covered_blocks,
size_t log2_covered_blocks,
size_t prev) {
- JXL_DASSERT((1u << log2_covered_blocks) == covered_blocks);
+ JXL_DASSERT((static_cast<size_t>(1) << log2_covered_blocks) ==
+ covered_blocks);
nonzeros_left = (nonzeros_left + covered_blocks - 1) >> log2_covered_blocks;
k >>= log2_covered_blocks;
JXL_DASSERT(k > 0);
@@ -109,7 +110,8 @@ struct BlockCtxMap {
// Non-zero context is based on number of non-zeros and block context.
// For better clustering, contexts with same number of non-zeros are grouped.
constexpr uint32_t ZeroDensityContextsOffset(uint32_t block_ctx) const {
- return num_ctxs * kNonZeroBuckets + kZeroDensityContextCount * block_ctx;
+ return static_cast<uint32_t>(num_ctxs * kNonZeroBuckets +
+ kZeroDensityContextCount * block_ctx);
}
// Context map for AC coefficients consists of 2 blocks:
@@ -121,7 +123,8 @@ struct BlockCtxMap {
// number of non-zeros left and
// index in scan order
constexpr uint32_t NumACContexts() const {
- return num_ctxs * (kNonZeroBuckets + kZeroDensityContextCount);
+ return static_cast<uint32_t>(num_ctxs *
+ (kNonZeroBuckets + kZeroDensityContextCount));
}
// Non-zero context is based on number of non-zeros and block context.
@@ -134,7 +137,7 @@ struct BlockCtxMap {
} else {
ctx = 4 + non_zeros / 2;
}
- return ctx * num_ctxs + block_ctx;
+ return static_cast<uint32_t>(ctx * num_ctxs + block_ctx);
}
BlockCtxMap() {
diff --git a/third_party/jpeg-xl/lib/jxl/ac_strategy.h b/third_party/jpeg-xl/lib/jxl/ac_strategy.h
index 9e5917ff1b..fd40b0ced8 100644
--- a/third_party/jpeg-xl/lib/jxl/ac_strategy.h
+++ b/third_party/jpeg-xl/lib/jxl/ac_strategy.h
@@ -11,9 +11,12 @@
#include <hwy/base.h> // kMaxVectorSize
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/coeff_order_fwd.h"
#include "lib/jxl/frame_dimensions.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/image_ops.h"
// Defines the different kinds of transforms, and heuristics to choose between
diff --git a/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc b/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc
index b1d9103466..dc25c89898 100644
--- a/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/ac_strategy_test.cc
@@ -5,16 +5,14 @@
#include "lib/jxl/ac_strategy.h"
-#include <string.h>
-
-#include <cmath>
+#include <algorithm>
+#include <cstring>
#include <hwy/aligned_allocator.h>
#include <hwy/base.h> // HWY_ALIGN_MAX
#include <hwy/tests/hwy_gtest.h>
-#include <utility>
#include "lib/jxl/base/random.h"
-#include "lib/jxl/dct_scales.h"
+#include "lib/jxl/coeff_order_fwd.h"
#include "lib/jxl/dec_transforms_testonly.h"
#include "lib/jxl/enc_transforms.h"
#include "lib/jxl/simd_util.h"
diff --git a/third_party/jpeg-xl/lib/jxl/ans_common.h b/third_party/jpeg-xl/lib/jxl/ans_common.h
index 44b8e3fba1..8236bb20ec 100644
--- a/third_party/jpeg-xl/lib/jxl/ans_common.h
+++ b/third_party/jpeg-xl/lib/jxl/ans_common.h
@@ -6,23 +6,24 @@
#ifndef LIB_JXL_ANS_COMMON_H_
#define LIB_JXL_ANS_COMMON_H_
-#include <stdint.h>
-
#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <hwy/base.h>
#include <hwy/cache_control.h> // Prefetch
#include <vector>
#include "lib/jxl/ans_params.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/status.h"
namespace jxl {
// Returns the precision (number of bits) that should be used to store
// a histogram count such that Log2Floor(count) == logcount.
-static JXL_INLINE uint32_t GetPopulationCountPrecision(uint32_t logcount,
- uint32_t shift) {
+static JXL_MAYBE_UNUSED JXL_INLINE uint32_t
+GetPopulationCountPrecision(uint32_t logcount, uint32_t shift) {
int32_t r = std::min<int>(
logcount, static_cast<int>(shift) -
static_cast<int>((ANS_LOG_TAB_SIZE - logcount) >> 1));
diff --git a/third_party/jpeg-xl/lib/jxl/ans_test.cc b/third_party/jpeg-xl/lib/jxl/ans_test.cc
index 5d6a5ef090..83a2e732f8 100644
--- a/third_party/jpeg-xl/lib/jxl/ans_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/ans_test.cc
@@ -10,11 +10,10 @@
#include "lib/jxl/ans_params.h"
#include "lib/jxl/base/random.h"
-#include "lib/jxl/base/span.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_ans.h"
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_ans.h"
-#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/testing.h"
diff --git a/third_party/jpeg-xl/lib/jxl/base/compiler_specific.h b/third_party/jpeg-xl/lib/jxl/base/compiler_specific.h
index 702ff8e058..52f88c50f8 100644
--- a/third_party/jpeg-xl/lib/jxl/base/compiler_specific.h
+++ b/third_party/jpeg-xl/lib/jxl/base/compiler_specific.h
@@ -8,7 +8,6 @@
// Macros for compiler version + nonstandard keywords, e.g. __builtin_expect.
-#include <stdint.h>
#include <sys/types.h>
#include "lib/jxl/base/sanitizer_definitions.h"
@@ -97,6 +96,11 @@
#define JXL_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
#endif
+#if JXL_COMPILER_MSVC
+#include <stdint.h>
+using ssize_t = intptr_t;
+#endif
+
// Returns a void* pointer which the compiler then assumes is N-byte aligned.
// Example: float* JXL_RESTRICT aligned = (float*)JXL_ASSUME_ALIGNED(in, 32);
//
@@ -150,8 +154,4 @@
#define JXL_FORMAT(idx_fmt, idx_arg)
#endif
-#if JXL_COMPILER_MSVC
-using ssize_t = intptr_t;
-#endif
-
#endif // LIB_JXL_BASE_COMPILER_SPECIFIC_H_
diff --git a/third_party/jpeg-xl/lib/jxl/base/exif.h b/third_party/jpeg-xl/lib/jxl/base/exif.h
index a3574a16ff..acaa1a1ce4 100644
--- a/third_party/jpeg-xl/lib/jxl/base/exif.h
+++ b/third_party/jpeg-xl/lib/jxl/base/exif.h
@@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#ifndef LIB_JXL_EXIF_H_
-#define LIB_JXL_EXIF_H_
+#ifndef LIB_JXL_BASE_EXIF_H_
+#define LIB_JXL_BASE_EXIF_H_
// Basic parsing of Exif (just enough for the render-impacting things
// like orientation)
@@ -87,4 +87,4 @@ JXL_INLINE void InterpretExif(const std::vector<uint8_t>& exif,
} // namespace jxl
-#endif // LIB_JXL_EXIF_H_
+#endif // LIB_JXL_BASE_EXIF_H_
diff --git a/third_party/jpeg-xl/lib/jxl/base/include_jpeglib.h b/third_party/jpeg-xl/lib/jxl/base/include_jpeglib.h
new file mode 100644
index 0000000000..f72d13d04b
--- /dev/null
+++ b/third_party/jpeg-xl/lib/jxl/base/include_jpeglib.h
@@ -0,0 +1,20 @@
+// Copyright (c) the JPEG XL Project Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef LIB_JXL_BASE_INCLUDE_JPEGLIB_H_
+#define LIB_JXL_BASE_INCLUDE_JPEGLIB_H_
+
+// Using this header ensures that includes go in the right order,
+// not alphabetically sorted.
+
+// NOLINTBEGIN
+/* clang-format off */
+#include <stdio.h> // IWYU pragma: keep
+#include <jpeglib.h> // IWYU pragma: keep
+#include <setjmp.h> // IWYU pragma: keep
+/* clang-format on */
+// NOLINTEND
+
+#endif // LIB_JXL_BASE_INCLUDE_JPEGLIB_H_
diff --git a/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h b/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h
index cde6a64b1e..e1f8753932 100644
--- a/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h
+++ b/third_party/jpeg-xl/lib/jxl/base/matrix_ops.h
@@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#ifndef LIB_JXL_MATRIX_OPS_H_
-#define LIB_JXL_MATRIX_OPS_H_
+#ifndef LIB_JXL_BASE_MATRIX_OPS_H_
+#define LIB_JXL_BASE_MATRIX_OPS_H_
// 3x3 matrix operations.
@@ -83,4 +83,4 @@ Status Inv3x3Matrix(Matrix& matrix) {
} // namespace jxl
-#endif // LIB_JXL_MATRIX_OPS_H_
+#endif // LIB_JXL_BASE_MATRIX_OPS_H_
diff --git a/third_party/jpeg-xl/lib/jxl/base/rect.h b/third_party/jpeg-xl/lib/jxl/base/rect.h
new file mode 100644
index 0000000000..666c3d73ec
--- /dev/null
+++ b/third_party/jpeg-xl/lib/jxl/base/rect.h
@@ -0,0 +1,194 @@
+// Copyright (c) the JPEG XL Project Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef LIB_JXL_BASE_RECT_H_
+#define LIB_JXL_BASE_RECT_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <sstream>
+#include <string>
+#include <utility> // std::move
+
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/status.h"
+
+namespace jxl {
+
+// Rectangular region in image(s). Factoring this out of Image instead of
+// shifting the pointer by x0/y0 allows this to apply to multiple images with
+// different resolutions (e.g. color transform and quantization field).
+// Can compare using SameSize(rect1, rect2).
+template <typename T>
+class RectT {
+ public:
+ // Most windows are xsize_max * ysize_max, except those on the borders where
+ // begin + size_max > end.
+ constexpr RectT(T xbegin, T ybegin, size_t xsize_max, size_t ysize_max,
+ T xend, T yend)
+ : x0_(xbegin),
+ y0_(ybegin),
+ xsize_(ClampedSize(xbegin, xsize_max, xend)),
+ ysize_(ClampedSize(ybegin, ysize_max, yend)) {}
+
+ // Construct with origin and known size (typically from another Rect).
+ constexpr RectT(T xbegin, T ybegin, size_t xsize, size_t ysize)
+ : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {}
+
+ // Construct a rect that covers a whole image/plane/ImageBundle etc.
+ template <typename ImageT>
+ explicit RectT(const ImageT& image)
+ : RectT(0, 0, image.xsize(), image.ysize()) {}
+
+ RectT() : RectT(0, 0, 0, 0) {}
+
+ RectT(const RectT&) = default;
+ RectT& operator=(const RectT&) = default;
+
+ // Construct a subrect that resides in an image/plane/ImageBundle etc.
+ template <typename ImageT>
+ RectT Crop(const ImageT& image) const {
+ return Intersection(RectT(image));
+ }
+
+ // Construct a subrect that resides in the [0, ysize) x [0, xsize) region of
+ // the current rect.
+ RectT Crop(size_t area_xsize, size_t area_ysize) const {
+ return Intersection(RectT(0, 0, area_xsize, area_ysize));
+ }
+
+ // Returns a rect that only contains `num` lines with offset `y` from `y0()`.
+ RectT Lines(size_t y, size_t num) const {
+ JXL_DASSERT(y + num <= ysize_);
+ return RectT(x0_, y0_ + y, xsize_, num);
+ }
+
+ RectT Line(size_t y) const { return Lines(y, 1); }
+
+ JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const {
+ return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_,
+ ysize_, std::min(x1(), other.x1()),
+ std::min(y1(), other.y1()));
+ }
+
+ JXL_MUST_USE_RESULT RectT Translate(int64_t x_offset,
+ int64_t y_offset) const {
+ return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_);
+ }
+
+ template <template <class> class P, typename V>
+ V* Row(P<V>* image, size_t y) const {
+ JXL_DASSERT(y + y0_ >= 0);
+ return image->Row(y + y0_) + x0_;
+ }
+
+ template <template <class> class P, typename V>
+ const V* Row(const P<V>* image, size_t y) const {
+ JXL_DASSERT(y + y0_ >= 0);
+ return image->Row(y + y0_) + x0_;
+ }
+
+ template <template <class> class MP, typename V>
+ V* PlaneRow(MP<V>* image, const size_t c, size_t y) const {
+ JXL_DASSERT(y + y0_ >= 0);
+ return image->PlaneRow(c, y + y0_) + x0_;
+ }
+
+ template <template <class> class P, typename V>
+ const V* ConstRow(const P<V>& image, size_t y) const {
+ JXL_DASSERT(y + y0_ >= 0);
+ return image.ConstRow(y + y0_) + x0_;
+ }
+
+ template <template <class> class MP, typename V>
+ const V* ConstPlaneRow(const MP<V>& image, size_t c, size_t y) const {
+ JXL_DASSERT(y + y0_ >= 0);
+ return image.ConstPlaneRow(c, y + y0_) + x0_;
+ }
+
+ bool IsInside(const RectT& other) const {
+ return x0_ >= other.x0() && x1() <= other.x1() && y0_ >= other.y0() &&
+ y1() <= other.y1();
+ }
+
+ // Returns true if this Rect fully resides in the given image. ImageT could be
+ // Plane<T> or Image3<T>; however if ImageT is Rect, results are nonsensical.
+ template <class ImageT>
+ bool IsInside(const ImageT& image) const {
+ return IsInside(RectT(image));
+ }
+
+ T x0() const { return x0_; }
+ T y0() const { return y0_; }
+ size_t xsize() const { return xsize_; }
+ size_t ysize() const { return ysize_; }
+ T x1() const { return x0_ + xsize_; }
+ T y1() const { return y0_ + ysize_; }
+
+ RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const {
+ return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx,
+ ysize_ << shifty);
+ }
+ RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); }
+
+ // Requires x0(), y0() to be multiples of 1<<shiftx, 1<<shifty.
+ RectT<T> CeilShiftRight(size_t shiftx, size_t shifty) const {
+ JXL_ASSERT(x0_ % (1 << shiftx) == 0);
+ JXL_ASSERT(y0_ % (1 << shifty) == 0);
+ return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty),
+ DivCeil(xsize_, T{1} << shiftx),
+ DivCeil(ysize_, T{1} << shifty));
+ }
+ RectT<T> CeilShiftRight(std::pair<size_t, size_t> shift) const {
+ return CeilShiftRight(shift.first, shift.second);
+ }
+ RectT<T> CeilShiftRight(size_t shift) const {
+ return CeilShiftRight(shift, shift);
+ }
+
+ RectT<T> Extend(T border, RectT<T> parent) const {
+ T new_x0 = x0() > parent.x0() + border ? x0() - border : parent.x0();
+ T new_y0 = y0() > parent.y0() + border ? y0() - border : parent.y0();
+ T new_x1 = x1() + border > parent.x1() ? parent.x1() : x1() + border;
+ T new_y1 = y1() + border > parent.y1() ? parent.y1() : y1() + border;
+ return RectT<T>(new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
+ }
+
+ template <typename U>
+ RectT<U> As() const {
+ return RectT<U>(static_cast<U>(x0_), static_cast<U>(y0_),
+ static_cast<U>(xsize_), static_cast<U>(ysize_));
+ }
+
+ private:
+ // Returns size_max, or whatever is left in [begin, end).
+ static constexpr size_t ClampedSize(T begin, size_t size_max, T end) {
+ return (static_cast<T>(begin + size_max) <= end)
+ ? size_max
+ : (end > begin ? end - begin : 0);
+ }
+
+ T x0_;
+ T y0_;
+
+ size_t xsize_;
+ size_t ysize_;
+};
+
+template <typename T>
+std::string Description(RectT<T> r) {
+ std::ostringstream os;
+ os << "[" << r.x0() << ".." << r.x1() << ")x"
+ << "[" << r.y0() << ".." << r.y1() << ")";
+ return os.str();
+}
+
+using Rect = RectT<size_t>;
+
+} // namespace jxl
+
+#endif // LIB_JXL_BASE_RECT_H_
diff --git a/third_party/jpeg-xl/lib/jxl/base/span.h b/third_party/jpeg-xl/lib/jxl/base/span.h
index ba09d62316..7515b7b1ef 100644
--- a/third_party/jpeg-xl/lib/jxl/base/span.h
+++ b/third_party/jpeg-xl/lib/jxl/base/span.h
@@ -11,6 +11,7 @@
#include <cstddef>
#include <cstdint>
+#include <type_traits>
#include <vector>
#include "lib/jxl/base/status.h"
@@ -41,6 +42,8 @@ class Span {
"Incompatible type of source.");
}
+ using NCT = typename std::remove_const<T>::type;
+
constexpr T* data() const noexcept { return ptr_; }
constexpr size_t size() const noexcept { return len_; }
@@ -62,12 +65,12 @@ class Span {
len_ -= n;
}
- // NCT == non-const-T; compiler will complain if NCT is not compatible with T.
- template <typename NCT>
void AppendTo(std::vector<NCT>& dst) const {
dst.insert(dst.end(), begin(), end());
}
+ std::vector<NCT> Copy() const { return std::vector<NCT>(begin(), end()); }
+
private:
T* ptr_;
size_t len_;
diff --git a/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc b/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc
index 802da855fa..b2d5773d15 100644
--- a/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/bit_reader_test.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <array>
+#include <utility>
#include <vector>
#include "lib/jxl/base/common.h"
diff --git a/third_party/jpeg-xl/lib/jxl/bits_test.cc b/third_party/jpeg-xl/lib/jxl/bits_test.cc
index 45db8c0d6e..8340db5a38 100644
--- a/third_party/jpeg-xl/lib/jxl/bits_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/bits_test.cc
@@ -5,6 +5,9 @@
#include "lib/jxl/base/bits.h"
+#include <cstddef>
+#include <cstdint>
+
#include "lib/jxl/testing.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/blending.cc b/third_party/jpeg-xl/lib/jxl/blending.cc
index 7575ec6e4a..0e26980816 100644
--- a/third_party/jpeg-xl/lib/jxl/blending.cc
+++ b/third_party/jpeg-xl/lib/jxl/blending.cc
@@ -5,7 +5,16 @@
#include "lib/jxl/blending.h"
+#include <cstddef>
+#include <cstring>
+#include <vector>
+
#include "lib/jxl/alpha.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/dec_patch_dictionary.h"
+#include "lib/jxl/frame_header.h"
+#include "lib/jxl/image.h"
+#include "lib/jxl/image_metadata.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/blending.h b/third_party/jpeg-xl/lib/jxl/blending.h
index 94bead8dd6..6ed862ac1c 100644
--- a/third_party/jpeg-xl/lib/jxl/blending.h
+++ b/third_party/jpeg-xl/lib/jxl/blending.h
@@ -6,8 +6,10 @@
#ifndef LIB_JXL_BLENDING_H_
#define LIB_JXL_BLENDING_H_
+#include <cstddef>
#include <vector>
+#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_patch_dictionary.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image_metadata.h"
diff --git a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc
index 2e06d79eba..4e49f18df8 100644
--- a/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc
+++ b/third_party/jpeg-xl/lib/jxl/butteraugli/butteraugli.cc
@@ -22,13 +22,12 @@
#include "lib/jxl/butteraugli/butteraugli.h"
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
#include <algorithm>
#include <cmath>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <memory>
#include <vector>
@@ -40,6 +39,7 @@
#include "lib/jxl/base/fast_math-inl.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/convolve.h"
#include "lib/jxl/image_ops.h"
diff --git a/third_party/jpeg-xl/lib/jxl/cache_aligned.h b/third_party/jpeg-xl/lib/jxl/cache_aligned.h
index 8480471e5c..c9cac17339 100644
--- a/third_party/jpeg-xl/lib/jxl/cache_aligned.h
+++ b/third_party/jpeg-xl/lib/jxl/cache_aligned.h
@@ -13,8 +13,6 @@
#include <memory>
-#include "lib/jxl/base/compiler_specific.h"
-
namespace jxl {
// Functions that depend on the cache line size.
diff --git a/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h b/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h
index 1f2353d9af..090d95165c 100644
--- a/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h
+++ b/third_party/jpeg-xl/lib/jxl/chroma_from_luma.h
@@ -9,11 +9,12 @@
// Chroma-from-luma, computed using heuristics to determine the best linear
// model for the X and B channels from the Y channel.
-#include <stddef.h>
-#include <stdint.h>
-
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
#include <limits>
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/dec_bit_reader.h"
diff --git a/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h b/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h
index a787bd11d8..69a5dc434e 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/jxl_cms_internal.h
@@ -405,7 +405,7 @@ static Status WriteICCS15Fixed16(float value, size_t pos,
// Even the first value works well,...
bool ok = (-32767.995f <= value) && (value <= 32767.995f);
if (!ok) return JXL_FAILURE("ICC value is out of range / NaN");
- int32_t i = value * 65536.0f + 0.5f;
+ int32_t i = static_cast<int32_t>(std::lround(value * 65536.0f));
// Use two's complement
uint32_t u = static_cast<uint32_t>(i);
WriteICCUint32(u, pos, icc);
@@ -849,6 +849,20 @@ static std::string ToString(JxlRenderingIntent rendering_intent) {
}
static std::string ColorEncodingDescriptionImpl(const JxlColorEncoding& c) {
+ if (c.color_space == JXL_COLOR_SPACE_RGB &&
+ c.white_point == JXL_WHITE_POINT_D65) {
+ if (c.rendering_intent == JXL_RENDERING_INTENT_PERCEPTUAL &&
+ c.transfer_function == JXL_TRANSFER_FUNCTION_SRGB) {
+ if (c.primaries == JXL_PRIMARIES_SRGB) return "sRGB";
+ if (c.primaries == JXL_PRIMARIES_P3) return "DisplayP3";
+ }
+ if (c.rendering_intent == JXL_RENDERING_INTENT_RELATIVE &&
+ c.primaries == JXL_PRIMARIES_2100) {
+ if (c.transfer_function == JXL_TRANSFER_FUNCTION_PQ) return "Rec2100PQ";
+ if (c.transfer_function == JXL_TRANSFER_FUNCTION_HLG) return "Rec2100HLG";
+ }
+ }
+
std::string d = ToString(c.color_space);
bool explicit_wp_tf = (c.color_space != JXL_COLOR_SPACE_XYB);
diff --git a/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h b/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h
index 69dcd0b512..0af852c745 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/opsin_params.h
@@ -6,6 +6,9 @@
#ifndef LIB_JXL_CMS_OPSIN_PARAMS_H_
#define LIB_JXL_CMS_OPSIN_PARAMS_H_
+#include <array>
+#include <cstddef>
+
#include "lib/jxl/base/matrix_ops.h"
// Constants that define the XYB color space.
diff --git a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h
index 1f85dcca41..c1f43f4d31 100644
--- a/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h
+++ b/third_party/jpeg-xl/lib/jxl/cms/tone_mapping.h
@@ -8,6 +8,7 @@
#include <algorithm>
#include <cmath>
+#include <cstddef>
#include <utility>
#include "lib/jxl/base/common.h"
diff --git a/third_party/jpeg-xl/lib/jxl/coeff_order.h b/third_party/jpeg-xl/lib/jxl/coeff_order.h
index 79c0c976c9..395e296642 100644
--- a/third_party/jpeg-xl/lib/jxl/coeff_order.h
+++ b/third_party/jpeg-xl/lib/jxl/coeff_order.h
@@ -6,11 +6,11 @@
#ifndef LIB_JXL_COEFF_ORDER_H_
#define LIB_JXL_COEFF_ORDER_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <array>
+#include <cstddef>
+#include <cstdint>
#include "lib/jxl/ac_strategy.h"
-#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/coeff_order_fwd.h"
@@ -24,11 +24,12 @@ class BitReader;
static constexpr size_t kCoeffOrderLimit = 6156;
-static constexpr std::array<size_t, 3 * kNumOrders + 1> kCoeffOrderOffset = {
- 0, 1, 2, 3, 4, 5, 6, 10, 14, 18,
- 34, 50, 66, 68, 70, 72, 76, 80, 84, 92,
- 100, 108, 172, 236, 300, 332, 364, 396, 652, 908,
- 1164, 1292, 1420, 1548, 2572, 3596, 4620, 5132, 5644, kCoeffOrderLimit};
+static constexpr std::array<size_t, 3 * kNumOrders + 1> JXL_MAYBE_UNUSED
+ kCoeffOrderOffset = {
+ 0, 1, 2, 3, 4, 5, 6, 10, 14, 18,
+ 34, 50, 66, 68, 70, 72, 76, 80, 84, 92,
+ 100, 108, 172, 236, 300, 332, 364, 396, 652, 908,
+ 1164, 1292, 1420, 1548, 2572, 3596, 4620, 5132, 5644, kCoeffOrderLimit};
// TODO(eustas): rollback to constexpr once modern C++ becomes reuired.
#define CoeffOrderOffset(O, C) \
diff --git a/third_party/jpeg-xl/lib/jxl/coeff_order_fwd.h b/third_party/jpeg-xl/lib/jxl/coeff_order_fwd.h
index 26306575c1..e5e72a4913 100644
--- a/third_party/jpeg-xl/lib/jxl/coeff_order_fwd.h
+++ b/third_party/jpeg-xl/lib/jxl/coeff_order_fwd.h
@@ -8,8 +8,8 @@
// Breaks circular dependency between ac_strategy and coeff_order.
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
#include "lib/jxl/base/compiler_specific.h"
diff --git a/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h b/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h
index 61e4628dbd..afcd5a4c1c 100644
--- a/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h
+++ b/third_party/jpeg-xl/lib/jxl/color_encoding_internal.h
@@ -10,6 +10,7 @@
#include <jxl/cms_interface.h>
#include <jxl/color_encoding.h>
+#include <jxl/types.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/third_party/jpeg-xl/lib/jxl/color_management_test.cc b/third_party/jpeg-xl/lib/jxl/color_management_test.cc
index 77cbe56926..b6a45b0a85 100644
--- a/third_party/jpeg-xl/lib/jxl/color_management_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/color_management_test.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <algorithm>
+#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdio>
@@ -20,6 +21,7 @@
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/span.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/color_encoding_cms.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/color_encoding_internal.h"
@@ -417,7 +419,7 @@ TEST_F(ColorManagementTest, XYBProfile) {
}
}
}
- static float kMaxError[3] = {9e-4, 4e-4, 5e-4};
+ static float kMaxError[3] = {8.7e-4, 4.4e-4, 5.2e-4};
printf("Maximum errors:\n");
for (size_t c = 0; c < 3; ++c) {
debug_print_color(max_err_i[c]);
diff --git a/third_party/jpeg-xl/lib/jxl/compressed_dc.cc b/third_party/jpeg-xl/lib/jxl/compressed_dc.cc
index 250be9e9a6..ec78afbd41 100644
--- a/third_party/jpeg-xl/lib/jxl/compressed_dc.cc
+++ b/third_party/jpeg-xl/lib/jxl/compressed_dc.cc
@@ -20,6 +20,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
HWY_BEFORE_NAMESPACE();
diff --git a/third_party/jpeg-xl/lib/jxl/compressed_dc.h b/third_party/jpeg-xl/lib/jxl/compressed_dc.h
index 30259ebd56..d8846a8f04 100644
--- a/third_party/jpeg-xl/lib/jxl/compressed_dc.h
+++ b/third_party/jpeg-xl/lib/jxl/compressed_dc.h
@@ -6,11 +6,10 @@
#ifndef LIB_JXL_COMPRESSED_DC_H_
#define LIB_JXL_COMPRESSED_DC_H_
-#include <stddef.h>
-#include <stdint.h>
-
#include "lib/jxl/ac_context.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
#include "lib/jxl/modular/modular_image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/convolve-inl.h b/third_party/jpeg-xl/lib/jxl/convolve-inl.h
index 949fd8ad67..3efd8f6335 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/convolve-inl.h
@@ -12,6 +12,8 @@
#include <hwy/highway.h>
+#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image_ops.h"
diff --git a/third_party/jpeg-xl/lib/jxl/convolve.h b/third_party/jpeg-xl/lib/jxl/convolve.h
index 5231ae2640..da7cab6ffb 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve.h
+++ b/third_party/jpeg-xl/lib/jxl/convolve.h
@@ -12,6 +12,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/image.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc b/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc
index ae618b9990..d6b388698c 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_separable5.cc
@@ -10,6 +10,7 @@
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/convolve-inl.h"
HWY_BEFORE_NAMESPACE();
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_slow.cc b/third_party/jpeg-xl/lib/jxl/convolve_slow.cc
index 655e040885..aa4c07f60b 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_slow.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_slow.cc
@@ -3,9 +3,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "lib/jxl/convolve.h"
-
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/convolve-inl.h"
+#include "lib/jxl/convolve.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc b/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc
index 618ad03a86..012a9be97e 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_symmetric3.cc
@@ -10,6 +10,7 @@
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/convolve-inl.h"
HWY_BEFORE_NAMESPACE();
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc b/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc
index 7ed384894e..4c8451f847 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_symmetric5.cc
@@ -11,6 +11,7 @@
#include <hwy/highway.h>
#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/convolve-inl.h"
HWY_BEFORE_NAMESPACE();
diff --git a/third_party/jpeg-xl/lib/jxl/convolve_test.cc b/third_party/jpeg-xl/lib/jxl/convolve_test.cc
index 084398c5e1..5ba36b33fe 100644
--- a/third_party/jpeg-xl/lib/jxl/convolve_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/convolve_test.cc
@@ -8,6 +8,8 @@
#include <jxl/types.h>
#include <time.h>
+#include <cinttypes> // PRIx64
+
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/convolve_test.cc"
#include <hwy/foreach_target.h>
@@ -20,6 +22,7 @@
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/random.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/image_ops.h"
#include "lib/jxl/image_test_utils.h"
#include "lib/jxl/test_utils.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dct_for_test.h b/third_party/jpeg-xl/lib/jxl/dct_for_test.h
index b0cbffacad..29c189261d 100644
--- a/third_party/jpeg-xl/lib/jxl/dct_for_test.h
+++ b/third_party/jpeg-xl/lib/jxl/dct_for_test.h
@@ -8,9 +8,8 @@
// Unoptimized DCT only for use in tests.
-#include <string.h> // memcpy
-
#include <cmath>
+#include <cstring> // memcpy
#include <vector>
#include "lib/jxl/base/common.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dct_util.h b/third_party/jpeg-xl/lib/jxl/dct_util.h
index 90a02658af..077c17bd77 100644
--- a/third_party/jpeg-xl/lib/jxl/dct_util.h
+++ b/third_party/jpeg-xl/lib/jxl/dct_util.h
@@ -6,9 +6,10 @@
#ifndef LIB_JXL_DCT_UTIL_H_
#define LIB_JXL_DCT_UTIL_H_
-#include <stddef.h>
-
+#include <cstddef>
+#include <cstdint>
#include <memory>
+#include <type_traits>
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/status.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_ans.h b/third_party/jpeg-xl/lib/jxl/dec_ans.h
index cbff1deebe..dc56df1216 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_ans.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_ans.h
@@ -10,17 +10,18 @@
// decoding table from them.
#include <jxl/types.h>
-#include <stddef.h>
-#include <stdint.h>
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
#include <cstring>
#include <vector>
#include "lib/jxl/ans_common.h"
#include "lib/jxl/ans_params.h"
#include "lib/jxl/base/bits.h"
-#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/cache_aligned.h"
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/dec_huffman.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_frame.cc b/third_party/jpeg-xl/lib/jxl/dec_frame.cc
index a2a82ad1fb..ab51c1841f 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_frame.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_frame.cc
@@ -23,6 +23,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/coeff_order.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_group.cc b/third_party/jpeg-xl/lib/jxl/dec_group.cc
index 7dc4772eba..d1b03969c8 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_group.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_group.cc
@@ -5,10 +5,9 @@
#include "lib/jxl/dec_group.h"
-#include <stdint.h>
-#include <string.h>
-
#include <algorithm>
+#include <cstdint>
+#include <cstring>
#include <memory>
#include <utility>
@@ -24,6 +23,7 @@
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/coeff_order.h"
#include "lib/jxl/common.h" // kMaxNumPasses
diff --git a/third_party/jpeg-xl/lib/jxl/dec_group_border.cc b/third_party/jpeg-xl/lib/jxl/dec_group_border.cc
index 4bee3ae6ef..0f55a4053f 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_group_border.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_group_border.cc
@@ -6,6 +6,13 @@
#include "lib/jxl/dec_group_border.h"
#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/frame_dimensions.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/dec_group_border.h b/third_party/jpeg-xl/lib/jxl/dec_group_border.h
index cb3ecbefae..829f513d16 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_group_border.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_group_border.h
@@ -6,14 +6,13 @@
#ifndef LIB_JXL_DEC_GROUP_BORDER_H_
#define LIB_JXL_DEC_GROUP_BORDER_H_
-#include <stddef.h>
-
#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
-#include "lib/jxl/base/arch_macros.h"
-#include "lib/jxl/base/status.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/frame_dimensions.h"
-#include "lib/jxl/image.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/dec_modular.cc b/third_party/jpeg-xl/lib/jxl/dec_modular.cc
index 80cc9d1360..049d6e4f91 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_modular.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_modular.cc
@@ -5,9 +5,8 @@
#include "lib/jxl/dec_modular.h"
-#include <stdint.h>
-
#include <atomic>
+#include <cstdint>
#include <vector>
#include "lib/jxl/frame_header.h"
@@ -19,6 +18,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/compressed_dc.h"
#include "lib/jxl/epf.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_modular.h b/third_party/jpeg-xl/lib/jxl/dec_modular.h
index 23caad0c16..70eab8af89 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_modular.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_modular.h
@@ -6,18 +6,23 @@
#ifndef LIB_JXL_DEC_MODULAR_H_
#define LIB_JXL_DEC_MODULAR_H_
-#include <stddef.h>
-
+#include <cstddef>
+#include <cstdint>
#include <string>
+#include <vector>
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/dec_cache.h"
+#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/frame_header.h"
-#include "lib/jxl/image.h"
+#include "lib/jxl/modular/encoding/dec_ma.h"
#include "lib/jxl/modular/encoding/encoding.h"
#include "lib/jxl/modular/modular_image.h"
+#include "lib/jxl/quant_weights.h"
+#include "lib/jxl/render_pipeline/render_pipeline.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/dec_noise.cc b/third_party/jpeg-xl/lib/jxl/dec_noise.cc
index 24f0136490..ed5668f26b 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_noise.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_noise.cc
@@ -5,11 +5,8 @@
#include "lib/jxl/dec_noise.h"
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <algorithm>
-#include <numeric>
+#include <cstdint>
+#include <cstdlib>
#include <utility>
#undef HWY_TARGET_INCLUDE
@@ -18,10 +15,10 @@
#include <hwy/highway.h>
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/chroma_from_luma.h"
-#include "lib/jxl/image_ops.h"
-#include "lib/jxl/sanitizers.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/xorshift128plus-inl.h"
+
HWY_BEFORE_NAMESPACE();
namespace jxl {
namespace HWY_NAMESPACE {
diff --git a/third_party/jpeg-xl/lib/jxl/dec_noise.h b/third_party/jpeg-xl/lib/jxl/dec_noise.h
index ac05866470..39a3a8b8e3 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_noise.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_noise.h
@@ -8,11 +8,11 @@
// Noise synthesis. Currently disabled.
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <utility>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/image.h"
#include "lib/jxl/noise.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h b/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h
index 72dca8f057..ad0f5d6a04 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_patch_dictionary.h
@@ -8,10 +8,12 @@
// Chooses reference patches, and avoids encoding them once per occurrence.
-#include <stddef.h>
-#include <string.h>
#include <sys/types.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <utility>
#include <vector>
#include "lib/jxl/base/status.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_transforms-inl.h b/third_party/jpeg-xl/lib/jxl/dec_transforms-inl.h
index 9c90550625..51b0c80727 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_transforms-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_transforms-inl.h
@@ -10,12 +10,10 @@
#define LIB_JXL_DEC_TRANSFORMS_INL_H_
#endif
-#include <stddef.h>
-
+#include <cstddef>
#include <hwy/highway.h>
#include "lib/jxl/ac_strategy.h"
-#include "lib/jxl/coeff_order_fwd.h"
#include "lib/jxl/dct-inl.h"
#include "lib/jxl/dct_scales.h"
HWY_BEFORE_NAMESPACE();
diff --git a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc
index 6451c41f6d..294d10f504 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.cc
@@ -10,7 +10,6 @@
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
-#include "lib/jxl/dct_scales.h"
#include "lib/jxl/dec_transforms-inl.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h
index 2cbf6bd5f6..b7f3e8825d 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_transforms_testonly.h
@@ -8,8 +8,7 @@
// Facade for (non-inlined) inverse integral transforms.
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/compiler_specific.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_xyb.cc b/third_party/jpeg-xl/lib/jxl/dec_xyb.cc
index a719b3eb8c..009c078fae 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_xyb.cc
+++ b/third_party/jpeg-xl/lib/jxl/dec_xyb.cc
@@ -5,7 +5,7 @@
#include "lib/jxl/dec_xyb.h"
-#include <string.h>
+#include <cstring>
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/dec_xyb.cc"
@@ -14,13 +14,12 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/matrix_ops.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/jxl_cms_internal.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/color_encoding_internal.h"
-#include "lib/jxl/dec_group_border.h"
#include "lib/jxl/dec_xyb-inl.h"
-#include "lib/jxl/fields.h"
#include "lib/jxl/image.h"
#include "lib/jxl/opsin_params.h"
#include "lib/jxl/quantizer.h"
diff --git a/third_party/jpeg-xl/lib/jxl/dec_xyb.h b/third_party/jpeg-xl/lib/jxl/dec_xyb.h
index 65317f2f54..13692456f8 100644
--- a/third_party/jpeg-xl/lib/jxl/dec_xyb.h
+++ b/third_party/jpeg-xl/lib/jxl/dec_xyb.h
@@ -15,6 +15,8 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/matrix_ops.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/decode_test.cc b/third_party/jpeg-xl/lib/jxl/decode_test.cc
index 99b5871ccd..bf6723016f 100644
--- a/third_party/jpeg-xl/lib/jxl/decode_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/decode_test.cc
@@ -1701,7 +1701,7 @@ TEST(DecodeTest, PixelTestWithICCProfileLossy) {
EXPECT_SLIGHTLY_BELOW(
ButteraugliDistance(io0.frames, io1.frames, ba, *JxlGetDefaultCms(),
/*distmap=*/nullptr, nullptr),
- 0.56f);
+ 0.58f);
JxlDecoderDestroy(dec);
}
@@ -2151,7 +2151,7 @@ TEST(DecodeTest, PixelTestOpaqueSrgbLossyNoise) {
EXPECT_SLIGHTLY_BELOW(
ButteraugliDistance(io0.frames, io1.frames, ba, *JxlGetDefaultCms(),
/*distmap=*/nullptr, nullptr),
- 1.3f);
+ 1.9f);
JxlDecoderDestroy(dec);
}
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc
index 4aafd7a5e5..0be7cdb882 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.cc
@@ -5,12 +5,11 @@
#include "lib/jxl/enc_ac_strategy.h"
-#include <stdint.h>
-#include <string.h>
-
#include <algorithm>
#include <cmath>
+#include <cstdint>
#include <cstdio>
+#include <cstring>
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/enc_ac_strategy.cc"
@@ -21,6 +20,7 @@
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/fast_math-inl.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_transforms-inl.h"
#include "lib/jxl/enc_aux_out.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h
index 31eb73c6a0..05103e78ab 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_ac_strategy.h
@@ -7,9 +7,12 @@
#define LIB_JXL_ENC_AC_STRATEGY_H_
#include <cstddef>
+#include <cstdint>
+#include <hwy/aligned_allocator.h>
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/enc_cache.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc
index 4c2ddba95b..fa0570d937 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.cc
@@ -24,6 +24,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/fast_math-inl.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/butteraugli/butteraugli.h"
#include "lib/jxl/cms/opsin_params.h"
@@ -765,7 +766,7 @@ StatusOr<ImageF> TileDistMap(const ImageF& distmap, int tile_size, int margin,
const float kDcQuantPow = 0.83f;
const float kDcQuant = 1.095924047623553f;
-const float kAcQuant = 0.7381485255235064f;
+const float kAcQuant = 0.725f;
// Computes the decoded image for a given set of compression parameters.
StatusOr<ImageBundle> RoundtripImage(const FrameHeader& frame_header,
diff --git a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h
index 26ed3f26ca..30849dba4e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_adaptive_quantization.h
@@ -7,10 +7,11 @@
#define LIB_JXL_ENC_ADAPTIVE_QUANTIZATION_H_
#include <jxl/cms_interface.h>
-#include <stddef.h>
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/enc_cache.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc
index 4f1d2dadb5..c323dc68bb 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.cc
@@ -5,10 +5,9 @@
#include "lib/jxl/enc_ar_control_field.h"
-#include <stdint.h>
-#include <stdlib.h>
-
#include <algorithm>
+#include <cstdint>
+#include <cstdlib>
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/enc_ar_control_field.cc"
@@ -17,6 +16,7 @@
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h
index f3c5a97a1b..fef5a51d05 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_ar_control_field.h
@@ -6,11 +6,12 @@
#ifndef LIB_JXL_ENC_AR_CONTROL_FIELD_H_
#define LIB_JXL_ENC_AR_CONTROL_FIELD_H_
-#include <stddef.h>
-
+#include <cstddef>
#include <vector>
#include "lib/jxl/ac_strategy.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_cache.cc b/third_party/jpeg-xl/lib/jxl/enc_cache.cc
index 200ec83b65..91d0046c29 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_cache.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_cache.cc
@@ -5,13 +5,13 @@
#include "lib/jxl/enc_cache.h"
-#include <stddef.h>
-#include <stdint.h>
-
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_cache.h b/third_party/jpeg-xl/lib/jxl/enc_cache.h
index 43ee7bc9c8..76b7e3ddae 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_cache.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_cache.h
@@ -7,13 +7,14 @@
#define LIB_JXL_ENC_CACHE_H_
#include <jxl/cms_interface.h>
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <vector>
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dct_util.h"
#include "lib/jxl/enc_ans.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc
index 4039da2858..d45899936b 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.cc
@@ -5,11 +5,10 @@
#include "lib/jxl/enc_chroma_from_luma.h"
-#include <float.h>
-#include <stdlib.h>
-
#include <algorithm>
+#include <cfloat>
#include <cmath>
+#include <cstdlib>
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/enc_chroma_from_luma.cc"
@@ -18,6 +17,7 @@
#include <hwy/highway.h>
#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/dec_transforms-inl.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h
index c6481a0ec9..514202bf8b 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_chroma_from_luma.h
@@ -13,6 +13,8 @@
#include <hwy/aligned_allocator.h>
#include "lib/jxl/ac_strategy.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_cluster.h b/third_party/jpeg-xl/lib/jxl/enc_cluster.h
index 7ddc003cf2..3b157c9c9d 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_cluster.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_cluster.h
@@ -8,13 +8,11 @@
#ifndef LIB_JXL_ENC_CLUSTER_H_
#define LIB_JXL_ENC_CLUSTER_H_
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
#include <vector>
-#include "lib/jxl/ans_params.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/enc_ans_params.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc b/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc
index 49129f5d9e..abe404ce9e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_coeff_order.cc
@@ -3,13 +3,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include <stdint.h>
-
#include <algorithm>
#include <cmath>
+#include <cstdint>
#include <hwy/aligned_allocator.h>
#include <vector>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/coeff_order.h"
#include "lib/jxl/coeff_order_fwd.h"
#include "lib/jxl/dct_util.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_coeff_order.h b/third_party/jpeg-xl/lib/jxl/enc_coeff_order.h
index 25e0f17a8d..65f497e882 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_coeff_order.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_coeff_order.h
@@ -6,18 +6,16 @@
#ifndef LIB_JXL_ENC_COEFF_ORDER_H_
#define LIB_JXL_ENC_COEFF_ORDER_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/status.h"
-#include "lib/jxl/coeff_order.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/coeff_order_fwd.h"
+#include "lib/jxl/common.h"
#include "lib/jxl/dct_util.h"
-#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_bit_writer.h"
-#include "lib/jxl/enc_params.h"
#include "lib/jxl/frame_dimensions.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_comparator.h b/third_party/jpeg-xl/lib/jxl/enc_comparator.h
index ee62ab6f28..6ae6913abe 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_comparator.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_comparator.h
@@ -6,6 +6,8 @@
#ifndef LIB_JXL_ENC_COMPARATOR_H_
#define LIB_JXL_ENC_COMPARATOR_H_
+#include <jxl/cms_interface.h>
+
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc b/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc
index d67ab7db46..6b4d115e7f 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_debug_image.cc
@@ -5,9 +5,10 @@
#include "lib/jxl/enc_debug_image.h"
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_external_image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_debug_image.h b/third_party/jpeg-xl/lib/jxl/enc_debug_image.h
index 428293f8bc..98d27e705c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_debug_image.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_debug_image.h
@@ -8,9 +8,9 @@
// Optional output images for debugging.
-#include <stddef.h>
-#include <stdint.h>
+#include <cstdint>
+#include "lib/jxl/base/status.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc
index 94e6fefb61..81dd2f2b67 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.cc
@@ -5,11 +5,10 @@
#include "lib/jxl/enc_detect_dots.h"
-#include <stdint.h>
-
#include <algorithm>
#include <array>
#include <cmath>
+#include <cstdint>
#include <cstdio>
#include <utility>
#include <vector>
@@ -23,6 +22,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/convolve.h"
#include "lib/jxl/enc_linalg.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h
index 59def59f8f..91174463f7 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_detect_dots.h
@@ -7,13 +7,14 @@
#ifndef LIB_JXL_ENC_DETECT_DOTS_H_
#define LIB_JXL_ENC_DETECT_DOTS_H_
-#include <stddef.h>
-#include <stdint.h>
-
#include <array>
+#include <cstddef>
+#include <cstdint>
#include <vector>
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/enc_patch_dictionary.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc
index 7d76ba9002..bf9c15ef4e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.cc
@@ -5,12 +5,12 @@
#include "lib/jxl/enc_dot_dictionary.h"
-#include <stddef.h>
-#include <string.h>
-
#include <array>
+#include <cstddef>
+#include <cstring>
#include "lib/jxl/base/override.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/enc_detect_dots.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h
index d348fb73b8..cd7691e202 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_dot_dictionary.h
@@ -9,10 +9,10 @@
// Dots are stored in a dictionary to avoid storing similar dots multiple
// times.
-#include <stddef.h>
-
#include <vector>
+#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/enc_params.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc
index b71bb07bc9..461713058c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.cc
@@ -5,11 +5,8 @@
#include "lib/jxl/enc_entropy_coder.h"
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <utility>
+#include <cstddef>
+#include <cstdint>
#include <vector>
#undef HWY_TARGET_INCLUDE
@@ -24,13 +21,8 @@
#include "lib/jxl/base/status.h"
#include "lib/jxl/coeff_order.h"
#include "lib/jxl/coeff_order_fwd.h"
-#include "lib/jxl/dec_ans.h"
-#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/dec_context_map.h"
#include "lib/jxl/entropy_coder.h"
-#include "lib/jxl/epf.h"
#include "lib/jxl/image.h"
-#include "lib/jxl/image_ops.h"
#include "lib/jxl/pack_signed.h"
HWY_BEFORE_NAMESPACE();
diff --git a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h
index 6df3e8e770..2321a1d831 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_entropy_coder.h
@@ -6,20 +6,17 @@
#ifndef LIB_JXL_ENC_ENTROPY_CODER_H_
#define LIB_JXL_ENC_ENTROPY_CODER_H_
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/types.h>
-#include <memory>
-#include <utility>
+#include <cstdint>
#include <vector>
#include "lib/jxl/ac_context.h" // BlockCtxMap
#include "lib/jxl/ac_strategy.h"
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/coeff_order_fwd.h"
#include "lib/jxl/enc_ans.h"
-#include "lib/jxl/field_encodings.h"
#include "lib/jxl/frame_header.h" // YCbCrChromaSubsampling
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc b/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc
index 1797139428..a5884301b6 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_fast_lossless.cc
@@ -3612,7 +3612,8 @@ bool detect_palette(const unsigned char* r, size_t width,
size_t x = 0;
bool collided = false;
// this is just an unrolling of the next loop
- for (; x + 7 < width; x += 8) {
+ size_t look_ahead = 7 + ((nb_chans == 1) ? 3 : ((nb_chans < 4) ? 1 : 0));
+ for (; x + look_ahead < width; x += 8) {
uint32_t p[8] = {}, index[8];
for (int i = 0; i < 8; i++) memcpy(&p[i], r + (x + i) * nb_chans, 4);
for (int i = 0; i < 8; i++) p[i] &= ((1llu << (8 * nb_chans)) - 1);
diff --git a/third_party/jpeg-xl/lib/jxl/enc_fields.cc b/third_party/jpeg-xl/lib/jxl/enc_fields.cc
index fa513297fd..e1bf9d2ad8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_fields.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_fields.cc
@@ -5,7 +5,7 @@
#include "lib/jxl/enc_fields.h"
-#include <cinttypes>
+#include <cinttypes> // PRIu64
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/fields.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_frame.cc b/third_party/jpeg-xl/lib/jxl/enc_frame.cc
index 2a3389921b..ec0af1e8e5 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_frame.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_frame.cc
@@ -5,13 +5,12 @@
#include "lib/jxl/enc_frame.h"
-#include <stddef.h>
-#include <stdint.h>
-
#include <algorithm>
#include <array>
#include <atomic>
#include <cmath>
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <numeric>
#include <utility>
@@ -25,6 +24,7 @@
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/override.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/coeff_order.h"
@@ -583,10 +583,13 @@ struct PixelStatsForChromacityAdjustment {
CalcExposedBlue(&opsin->Plane(1), &opsin->Plane(2), rect);
}
int HowMuchIsXChannelPixelized() const {
- if (dx >= 0.03) {
+ if (dx >= 0.026) {
+ return 3;
+ }
+ if (dx >= 0.022) {
return 2;
}
- if (dx >= 0.017) {
+ if (dx >= 0.015) {
return 1;
}
return 0;
@@ -614,18 +617,13 @@ void ComputeChromacityAdjustments(const CompressParams& cparams,
return;
}
// 1) Distance based approach for chromacity adjustment:
- float x_qm_scale_steps[4] = {1.25f, 7.0f, 15.0f, 24.0f};
- frame_header->x_qm_scale = 2;
+ float x_qm_scale_steps[3] = {2.5f, 5.5f, 9.5f};
+ frame_header->x_qm_scale = 3;
for (float x_qm_scale_step : x_qm_scale_steps) {
if (cparams.original_butteraugli_distance > x_qm_scale_step) {
frame_header->x_qm_scale++;
}
}
- if (cparams.butteraugli_distance < 0.299f) {
- // Favor chromacity preservation for making images appear more
- // faithful to original even with extreme (5-10x) zooming.
- frame_header->x_qm_scale++;
- }
// 2) Pixel-based approach for chromacity adjustment:
// look at the individual pixels and make a guess how difficult
// the image would be based on the worst case pixel.
diff --git a/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc b/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc
index 7467a4d669..ba1181e285 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_gaborish.cc
@@ -5,12 +5,13 @@
#include "lib/jxl/enc_gaborish.h"
-#include <stddef.h>
-
#include <hwy/base.h>
+#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/convolve.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/image_ops.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_gaborish.h b/third_party/jpeg-xl/lib/jxl/enc_gaborish.h
index 041edcec96..ce1c211ffa 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_gaborish.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_gaborish.h
@@ -9,6 +9,7 @@
// Linear smoothing (3x3 convolution) for deblocking without too much blur.
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc b/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc
index 0d173c5eb8..074c547287 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_gaborish_test.cc
@@ -11,6 +11,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/convolve.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_group.cc b/third_party/jpeg-xl/lib/jxl/enc_group.cc
index 2b60643e7c..6e4e05335a 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_group.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_group.cc
@@ -6,7 +6,6 @@
#include "lib/jxl/enc_group.h"
#include <hwy/aligned_allocator.h>
-#include <utility>
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/enc_group.cc"
@@ -16,6 +15,7 @@
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/common.h" // kMaxNumPasses
#include "lib/jxl/dct_util.h"
#include "lib/jxl/dec_transforms-inl.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_group.h b/third_party/jpeg-xl/lib/jxl/enc_group.h
index 78484c2e9b..c9c4b77a5b 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_group.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_group.h
@@ -6,8 +6,9 @@
#ifndef LIB_JXL_ENC_GROUP_H_
#define LIB_JXL_ENC_GROUP_H_
-#include <stddef.h>
+#include <cstddef>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc b/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc
index 685558ac7c..152468255f 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_heuristics.cc
@@ -6,10 +6,10 @@
#include "lib/jxl/enc_heuristics.h"
#include <jxl/cms_interface.h>
-#include <stddef.h>
-#include <stdint.h>
#include <algorithm>
+#include <cstddef>
+#include <cstdint>
#include <cstdlib>
#include <limits>
#include <memory>
@@ -24,6 +24,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/override.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/butteraugli/butteraugli.h"
#include "lib/jxl/chroma_from_luma.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_heuristics.h b/third_party/jpeg-xl/lib/jxl/enc_heuristics.h
index 0dd93e4288..75a196748c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_heuristics.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_heuristics.h
@@ -9,9 +9,9 @@
// Hook for custom encoder heuristics (VarDCT only for now).
#include <jxl/cms_interface.h>
-#include <stddef.h>
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc b/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc
index 044f763363..db3c497cde 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_image_bundle.cc
@@ -10,6 +10,7 @@
#include <atomic>
#include <utility>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/image_bundle.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_image_bundle.h b/third_party/jpeg-xl/lib/jxl/enc_image_bundle.h
index 38536c8c7a..c1180a6da8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_image_bundle.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_image_bundle.h
@@ -9,6 +9,7 @@
#include <jxl/cms_interface.h>
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc b/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc
index c02f009ca7..1056c4f06c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_linalg_test.cc
@@ -5,6 +5,8 @@
#include "lib/jxl/enc_linalg.h"
+#include <cstddef>
+
#include "lib/jxl/base/random.h"
#include "lib/jxl/testing.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_modular.cc b/third_party/jpeg-xl/lib/jxl/enc_modular.cc
index 35fac3c827..25464737b8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_modular.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_modular.cc
@@ -5,11 +5,9 @@
#include "lib/jxl/enc_modular.h"
-#include <stddef.h>
-#include <stdint.h>
-
#include <array>
#include <atomic>
+#include <cstddef>
#include <cstdint>
#include <limits>
#include <utility>
@@ -17,6 +15,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/compressed_dc.h"
#include "lib/jxl/dec_ans.h"
@@ -998,7 +997,9 @@ Status ModularFrameEncoder::ComputeEncodingData(
pool, 0, stream_params_.size(), ThreadPool::NoInit,
[&](const uint32_t i, size_t /* thread */) {
size_t stream = stream_params_[i].id.ID(frame_dim_);
- stream_options_[stream] = stream_options_[0];
+ if (stream != 0) {
+ stream_options_[stream] = stream_options_[0];
+ }
JXL_CHECK(PrepareStreamParams(
stream_params_[i].rect, cparams_, stream_params_[i].minShift,
stream_params_[i].maxShift, stream_params_[i].id, do_color,
diff --git a/third_party/jpeg-xl/lib/jxl/enc_modular.h b/third_party/jpeg-xl/lib/jxl/enc_modular.h
index c7a8421982..cac6483a00 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_modular.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_modular.h
@@ -14,6 +14,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_modular.h"
#include "lib/jxl/enc_ans.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc b/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc
index 9184765be2..4270116ee8 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_optimize_test.cc
@@ -5,6 +5,10 @@
#include "lib/jxl/enc_optimize.h"
+#include <cmath>
+#include <cstddef>
+#include <vector>
+
#include "lib/jxl/testing.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc
index 6fc5f7f49e..2586692c4e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.cc
@@ -6,12 +6,12 @@
#include "lib/jxl/enc_patch_dictionary.h"
#include <jxl/types.h>
-#include <stdint.h>
-#include <stdlib.h>
#include <sys/types.h>
#include <algorithm>
#include <atomic>
+#include <cstdint>
+#include <cstdlib>
#include <utility>
#include <vector>
@@ -20,6 +20,7 @@
#include "lib/jxl/base/override.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/random.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_cache.h"
#include "lib/jxl/dec_frame.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h
index ac236d7f17..ba2e3ba6b2 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_patch_dictionary.h
@@ -8,12 +8,16 @@
// Chooses reference patches, and avoids encoding them once per occurrence.
-#include <stddef.h>
-#include <string.h>
+#include <jxl/cms_interface.h>
#include <sys/types.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <utility>
#include <vector>
+#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_patch_dictionary.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_photon_noise.h b/third_party/jpeg-xl/lib/jxl/enc_photon_noise.h
index f43e14d560..d3c6d843af 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_photon_noise.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_photon_noise.h
@@ -6,8 +6,8 @@
#ifndef LIB_JXL_ENC_PHOTON_NOISE_H_
#define LIB_JXL_ENC_PHOTON_NOISE_H_
-#include "lib/jxl/dec_xyb.h"
-#include "lib/jxl/image.h"
+#include <cstddef>
+
#include "lib/jxl/noise.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc b/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc
index 2e10dd5457..db172fb699 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_photon_noise_test.cc
@@ -5,7 +5,6 @@
#include "lib/jxl/enc_photon_noise.h"
-#include "lib/jxl/base/common.h"
#include "lib/jxl/noise.h"
#include "lib/jxl/testing.h"
diff --git a/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h b/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h
index 82d8278b72..897ace6c7e 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h
+++ b/third_party/jpeg-xl/lib/jxl/enc_quant_weights.h
@@ -7,7 +7,9 @@
#define LIB_JXL_ENC_QUANT_WEIGHTS_H_
#include <cstddef>
+#include <vector>
+#include "lib/jxl/base/status.h"
#include "lib/jxl/quant_weights.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/enc_xyb.cc b/third_party/jpeg-xl/lib/jxl/enc_xyb.cc
index 9fc68d8474..89bb4de37c 100644
--- a/third_party/jpeg-xl/lib/jxl/enc_xyb.cc
+++ b/third_party/jpeg-xl/lib/jxl/enc_xyb.cc
@@ -17,6 +17,7 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/fast_math-inl.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/cms/transfer_functions-inl.h"
diff --git a/third_party/jpeg-xl/lib/jxl/encode_internal.h b/third_party/jpeg-xl/lib/jxl/encode_internal.h
index 001df5fed5..8030c8314a 100644
--- a/third_party/jpeg-xl/lib/jxl/encode_internal.h
+++ b/third_party/jpeg-xl/lib/jxl/encode_internal.h
@@ -214,7 +214,7 @@ class JxlEncoderChunkedFrameAdapter {
}
// TODO(szabadka) Move instead of copy.
- void SetJPEGData(const jpeg::JPEGData jpeg_data) {
+ void SetJPEGData(const jpeg::JPEGData& jpeg_data) {
jpeg_data_ = jpeg_data;
has_jpeg_data_ = true;
}
diff --git a/third_party/jpeg-xl/lib/jxl/encode_test.cc b/third_party/jpeg-xl/lib/jxl/encode_test.cc
index 0aef5f8aff..7400b237de 100644
--- a/third_party/jpeg-xl/lib/jxl/encode_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/encode_test.cc
@@ -233,7 +233,7 @@ void VerifyFrameEncoding(size_t xsize, size_t ysize, JxlEncoder* enc,
static constexpr double kMaxButteraugli =
#if JXL_HIGH_PRECISION
- 1.84;
+ 3.2;
#else
8.7;
#endif
@@ -461,7 +461,7 @@ TEST(EncodeTest, FrameSettingsTest) {
JxlEncoderFrameSettings* frame_settings =
JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
EXPECT_EQ(JXL_ENC_SUCCESS, JxlEncoderSetFrameDistance(frame_settings, 0.5));
- VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3130, false);
+ VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3200, false);
EXPECT_EQ(0.5, enc->last_used_cparams.butteraugli_distance);
}
@@ -1888,7 +1888,7 @@ TEST_P(EncoderStreamingTest, OutputCallback) {
p.color_includes_alpha(), p.is_lossless());
std::vector<uint8_t> compressed = std::vector<uint8_t>(64);
- // without sreaming
+ // without streaming
{
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
ASSERT_NE(nullptr, enc.get());
diff --git a/third_party/jpeg-xl/lib/jxl/epf.cc b/third_party/jpeg-xl/lib/jxl/epf.cc
index 78ef38bfd5..042aa8c591 100644
--- a/third_party/jpeg-xl/lib/jxl/epf.cc
+++ b/third_party/jpeg-xl/lib/jxl/epf.cc
@@ -7,27 +7,17 @@
#include "lib/jxl/epf.h"
-#include <math.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
#include <algorithm>
-#include <atomic>
-#include <numeric> // std::accumulate
-#include <vector>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/convolve.h"
#include "lib/jxl/dec_cache.h"
-#include "lib/jxl/image.h"
-#include "lib/jxl/image_bundle.h"
-#include "lib/jxl/image_ops.h"
#include "lib/jxl/loop_filter.h"
-#include "lib/jxl/quant_weights.h"
#include "lib/jxl/quantizer.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/epf.h b/third_party/jpeg-xl/lib/jxl/epf.h
index 808dde10dc..e372deaa6b 100644
--- a/third_party/jpeg-xl/lib/jxl/epf.h
+++ b/third_party/jpeg-xl/lib/jxl/epf.h
@@ -8,8 +8,8 @@
// Fast SIMD "in-loop" edge preserving filter (adaptive, nonlinear).
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/dec_cache.h"
-#include "lib/jxl/image.h"
#include "lib/jxl/loop_filter.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/fake_parallel_runner_testonly.h b/third_party/jpeg-xl/lib/jxl/fake_parallel_runner_testonly.h
index 508d808cc5..4ca422e9a4 100644
--- a/third_party/jpeg-xl/lib/jxl/fake_parallel_runner_testonly.h
+++ b/third_party/jpeg-xl/lib/jxl/fake_parallel_runner_testonly.h
@@ -7,8 +7,8 @@
#define LIB_JXL_FAKE_PARALLEL_RUNNER_TESTONLY_H_
#include <jxl/parallel_runner.h>
-#include <stdint.h>
+#include <cstdint>
#include <vector>
#include "lib/jxl/base/compiler_specific.h"
diff --git a/third_party/jpeg-xl/lib/jxl/fields.cc b/third_party/jpeg-xl/lib/jxl/fields.cc
index 6bb5eae25d..e11166877b 100644
--- a/third_party/jpeg-xl/lib/jxl/fields.cc
+++ b/third_party/jpeg-xl/lib/jxl/fields.cc
@@ -6,7 +6,7 @@
#include "lib/jxl/fields.h"
#include <algorithm>
-#include <cinttypes>
+#include <cinttypes> // PRIu64
#include <cmath>
#include <cstddef>
#include <hwy/base.h>
diff --git a/third_party/jpeg-xl/lib/jxl/fields.h b/third_party/jpeg-xl/lib/jxl/fields.h
index a8d8d8671a..cb9554213a 100644
--- a/third_party/jpeg-xl/lib/jxl/fields.h
+++ b/third_party/jpeg-xl/lib/jxl/fields.h
@@ -8,14 +8,11 @@
// Forward/backward-compatible 'bundles' with auto-serialized 'fields'.
-#include <cmath> // abs
-#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
-#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_bit_reader.h"
diff --git a/third_party/jpeg-xl/lib/jxl/fields_test.cc b/third_party/jpeg-xl/lib/jxl/fields_test.cc
index 0584458d07..5af68d2d5f 100644
--- a/third_party/jpeg-xl/lib/jxl/fields_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/fields_test.cc
@@ -5,18 +5,21 @@
#include "lib/jxl/fields.h"
-#include <stddef.h>
-#include <stdint.h>
-
#include <array>
-#include <utility>
+#include <cstddef>
+#include <cstdint>
#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/span.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_fields.h"
+#include "lib/jxl/field_encodings.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/headers.h"
+#include "lib/jxl/image_metadata.h"
#include "lib/jxl/testing.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/frame_dimensions.h b/third_party/jpeg-xl/lib/jxl/frame_dimensions.h
index 8440a95463..f7493f88b2 100644
--- a/third_party/jpeg-xl/lib/jxl/frame_dimensions.h
+++ b/third_party/jpeg-xl/lib/jxl/frame_dimensions.h
@@ -11,7 +11,7 @@
#include <cstddef>
#include "lib/jxl/base/common.h"
-#include "lib/jxl/image.h"
+#include "lib/jxl/base/rect.h"
namespace jxl {
// Some enums and typedefs used by more than one header file.
diff --git a/third_party/jpeg-xl/lib/jxl/frame_header.h b/third_party/jpeg-xl/lib/jxl/frame_header.h
index 30c62d5f27..68c4684a58 100644
--- a/third_party/jpeg-xl/lib/jxl/frame_header.h
+++ b/third_party/jpeg-xl/lib/jxl/frame_header.h
@@ -9,18 +9,20 @@
// Frame header with backward and forward-compatible extension capability and
// compressed integer fields.
-#include <stddef.h>
-#include <stdint.h>
-
#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <cstdint>
#include <string>
+#include <vector>
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/override.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/coeff_order_fwd.h"
#include "lib/jxl/common.h" // kMaxNumPasses
#include "lib/jxl/dec_bit_reader.h"
+#include "lib/jxl/field_encodings.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/image_metadata.h"
diff --git a/third_party/jpeg-xl/lib/jxl/icc_codec.h b/third_party/jpeg-xl/lib/jxl/icc_codec.h
index 3b0b0c041b..e57018b4c3 100644
--- a/third_party/jpeg-xl/lib/jxl/icc_codec.h
+++ b/third_party/jpeg-xl/lib/jxl/icc_codec.h
@@ -10,8 +10,8 @@
#include <cstddef>
#include <cstdint>
+#include <vector>
-#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_ans.h"
#include "lib/jxl/dec_bit_reader.h"
diff --git a/third_party/jpeg-xl/lib/jxl/image.h b/third_party/jpeg-xl/lib/jxl/image.h
index be97b929e3..347e070336 100644
--- a/third_party/jpeg-xl/lib/jxl/image.h
+++ b/third_party/jpeg-xl/lib/jxl/image.h
@@ -10,16 +10,13 @@
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
defined(THREAD_SANITIZER)
-#include <inttypes.h>
+#include <cinttypes> // PRIu64
#endif
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
#include <algorithm>
-#include <sstream>
-#include <string>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
#include <utility> // std::move
#include "lib/jxl/base/compiler_specific.h"
@@ -184,179 +181,6 @@ using ImageI = Plane<int32_t>;
using ImageF = Plane<float>;
using ImageD = Plane<double>;
-template <typename T>
-class Image3;
-
-// Rectangular region in image(s). Factoring this out of Image instead of
-// shifting the pointer by x0/y0 allows this to apply to multiple images with
-// different resolutions (e.g. color transform and quantization field).
-// Can compare using SameSize(rect1, rect2).
-template <typename T>
-class RectT {
- public:
- // Most windows are xsize_max * ysize_max, except those on the borders where
- // begin + size_max > end.
- constexpr RectT(T xbegin, T ybegin, size_t xsize_max, size_t ysize_max,
- T xend, T yend)
- : x0_(xbegin),
- y0_(ybegin),
- xsize_(ClampedSize(xbegin, xsize_max, xend)),
- ysize_(ClampedSize(ybegin, ysize_max, yend)) {}
-
- // Construct with origin and known size (typically from another Rect).
- constexpr RectT(T xbegin, T ybegin, size_t xsize, size_t ysize)
- : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {}
-
- // Construct a rect that covers a whole image/plane/ImageBundle etc.
- template <typename ImageT>
- explicit RectT(const ImageT& image)
- : RectT(0, 0, image.xsize(), image.ysize()) {}
-
- RectT() : RectT(0, 0, 0, 0) {}
-
- RectT(const RectT&) = default;
- RectT& operator=(const RectT&) = default;
-
- // Construct a subrect that resides in an image/plane/ImageBundle etc.
- template <typename ImageT>
- RectT Crop(const ImageT& image) const {
- return Intersection(RectT(image));
- }
-
- // Construct a subrect that resides in the [0, ysize) x [0, xsize) region of
- // the current rect.
- RectT Crop(size_t area_xsize, size_t area_ysize) const {
- return Intersection(RectT(0, 0, area_xsize, area_ysize));
- }
-
- // Returns a rect that only contains `num` lines with offset `y` from `y0()`.
- RectT Lines(size_t y, size_t num) const {
- JXL_DASSERT(y + num <= ysize_);
- return RectT(x0_, y0_ + y, xsize_, num);
- }
-
- RectT Line(size_t y) const { return Lines(y, 1); }
-
- JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const {
- return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_,
- ysize_, std::min(x1(), other.x1()),
- std::min(y1(), other.y1()));
- }
-
- JXL_MUST_USE_RESULT RectT Translate(int64_t x_offset,
- int64_t y_offset) const {
- return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_);
- }
-
- template <typename V>
- V* Row(Plane<V>* image, size_t y) const {
- JXL_DASSERT(y + y0_ >= 0);
- return image->Row(y + y0_) + x0_;
- }
-
- template <typename V>
- const V* Row(const Plane<V>* image, size_t y) const {
- JXL_DASSERT(y + y0_ >= 0);
- return image->Row(y + y0_) + x0_;
- }
-
- template <typename V>
- V* PlaneRow(Image3<V>* image, const size_t c, size_t y) const {
- JXL_DASSERT(y + y0_ >= 0);
- return image->PlaneRow(c, y + y0_) + x0_;
- }
-
- template <typename V>
- const V* ConstRow(const Plane<V>& image, size_t y) const {
- JXL_DASSERT(y + y0_ >= 0);
- return image.ConstRow(y + y0_) + x0_;
- }
-
- template <typename V>
- const V* ConstPlaneRow(const Image3<V>& image, size_t c, size_t y) const {
- JXL_DASSERT(y + y0_ >= 0);
- return image.ConstPlaneRow(c, y + y0_) + x0_;
- }
-
- bool IsInside(const RectT& other) const {
- return x0_ >= other.x0() && x1() <= other.x1() && y0_ >= other.y0() &&
- y1() <= other.y1();
- }
-
- // Returns true if this Rect fully resides in the given image. ImageT could be
- // Plane<T> or Image3<T>; however if ImageT is Rect, results are nonsensical.
- template <class ImageT>
- bool IsInside(const ImageT& image) const {
- return IsInside(RectT(image));
- }
-
- T x0() const { return x0_; }
- T y0() const { return y0_; }
- size_t xsize() const { return xsize_; }
- size_t ysize() const { return ysize_; }
- T x1() const { return x0_ + xsize_; }
- T y1() const { return y0_ + ysize_; }
-
- RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const {
- return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx,
- ysize_ << shifty);
- }
- RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); }
-
- // Requires x0(), y0() to be multiples of 1<<shiftx, 1<<shifty.
- RectT<T> CeilShiftRight(size_t shiftx, size_t shifty) const {
- JXL_ASSERT(x0_ % (1 << shiftx) == 0);
- JXL_ASSERT(y0_ % (1 << shifty) == 0);
- return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty),
- DivCeil(xsize_, T{1} << shiftx),
- DivCeil(ysize_, T{1} << shifty));
- }
- RectT<T> CeilShiftRight(std::pair<size_t, size_t> shift) const {
- return CeilShiftRight(shift.first, shift.second);
- }
- RectT<T> CeilShiftRight(size_t shift) const {
- return CeilShiftRight(shift, shift);
- }
-
- RectT<T> Extend(T border, RectT<T> parent) const {
- T new_x0 = x0() > parent.x0() + border ? x0() - border : parent.x0();
- T new_y0 = y0() > parent.y0() + border ? y0() - border : parent.y0();
- T new_x1 = x1() + border > parent.x1() ? parent.x1() : x1() + border;
- T new_y1 = y1() + border > parent.y1() ? parent.y1() : y1() + border;
- return RectT<T>(new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
- }
-
- template <typename U>
- RectT<U> As() const {
- return RectT<U>(static_cast<U>(x0_), static_cast<U>(y0_),
- static_cast<U>(xsize_), static_cast<U>(ysize_));
- }
-
- private:
- // Returns size_max, or whatever is left in [begin, end).
- static constexpr size_t ClampedSize(T begin, size_t size_max, T end) {
- return (static_cast<T>(begin + size_max) <= end)
- ? size_max
- : (end > begin ? end - begin : 0);
- }
-
- T x0_;
- T y0_;
-
- size_t xsize_;
- size_t ysize_;
-};
-
-template <typename T>
-std::string Description(RectT<T> r) {
- std::ostringstream os;
- os << "[" << r.x0() << ".." << r.x1() << ")x"
- << "[" << r.y0() << ".." << r.y1() << ")";
- return os.str();
-}
-
-using Rect = RectT<size_t>;
-
// Currently, we abuse Image to either refer to an image that owns its storage
// or one that doesn't. In similar vein, we abuse Image* function parameters to
// either mean "assign to me" or "fill the provided image with data".
diff --git a/third_party/jpeg-xl/lib/jxl/image_bundle.h b/third_party/jpeg-xl/lib/jxl/image_bundle.h
index c8a76a9f59..00f1eb81bd 100644
--- a/third_party/jpeg-xl/lib/jxl/image_bundle.h
+++ b/third_party/jpeg-xl/lib/jxl/image_bundle.h
@@ -9,9 +9,9 @@
// The main image or frame consists of a bundle of associated images.
#include <jxl/cms_interface.h>
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <string>
#include <utility>
@@ -19,6 +19,7 @@
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/common.h" // JPEGXL_ENABLE_TRANSCODE_JPEG
diff --git a/third_party/jpeg-xl/lib/jxl/image_metadata.h b/third_party/jpeg-xl/lib/jxl/image_metadata.h
index 2b647cfa30..37b5aedcfa 100644
--- a/third_party/jpeg-xl/lib/jxl/image_metadata.h
+++ b/third_party/jpeg-xl/lib/jxl/image_metadata.h
@@ -17,6 +17,7 @@
#include <vector>
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/matrix_ops.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_bit_reader.h"
diff --git a/third_party/jpeg-xl/lib/jxl/image_ops.h b/third_party/jpeg-xl/lib/jxl/image_ops.h
index 84cf7dad76..bee4eb56bd 100644
--- a/third_party/jpeg-xl/lib/jxl/image_ops.h
+++ b/third_party/jpeg-xl/lib/jxl/image_ops.h
@@ -14,6 +14,7 @@
#include <limits>
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/image_ops_test.cc b/third_party/jpeg-xl/lib/jxl/image_ops_test.cc
index 6b308baab4..0d16864282 100644
--- a/third_party/jpeg-xl/lib/jxl/image_ops_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/image_ops_test.cc
@@ -5,14 +5,14 @@
#include "lib/jxl/image_ops.h"
-#include <stdint.h>
-#include <stdlib.h>
-
+#include <cstdint>
+#include <cstdlib>
#include <cstring>
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/random.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/cache_aligned.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/image_test_utils.h b/third_party/jpeg-xl/lib/jxl/image_test_utils.h
index 7bb146866e..0b8b79a7dd 100644
--- a/third_party/jpeg-xl/lib/jxl/image_test_utils.h
+++ b/third_party/jpeg-xl/lib/jxl/image_test_utils.h
@@ -6,17 +6,15 @@
#ifndef LIB_JXL_IMAGE_TEST_UTILS_H_
#define LIB_JXL_IMAGE_TEST_UTILS_H_
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdint.h>
-
#include <cmath>
+#include <cstddef>
+#include <cstdint>
#include <limits>
#include <sstream>
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/random.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/image.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc
index d7c6c2ad78..d4a5e1d577 100644
--- a/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc
+++ b/third_party/jpeg-xl/lib/jxl/jpeg/enc_jpeg_data.cc
@@ -88,7 +88,7 @@ Status DetectBlobs(jpeg::JPEGData& jpeg_data) {
// Something is wrong with this marker; does not care.
continue;
}
- if (!have_exif && payload.size() >= sizeof kExifTag &&
+ if (!have_exif && payload.size() > sizeof kExifTag &&
!memcmp(payload.data(), kExifTag, sizeof kExifTag)) {
jpeg_data.app_marker_type[i] = AppMarkerType::kExif;
have_exif = true;
diff --git a/third_party/jpeg-xl/lib/jxl/jxl_test.cc b/third_party/jpeg-xl/lib/jxl/jxl_test.cc
index cf9857f462..be43d5a237 100644
--- a/third_party/jpeg-xl/lib/jxl/jxl_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/jxl_test.cc
@@ -120,7 +120,7 @@ TEST(JxlTest, RoundtripSmallD1) {
{
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 916, 40);
- EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.888);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.92);
}
// With a lower intensity target than the default, the bitrate should be
@@ -179,7 +179,7 @@ TEST(JxlTest, RoundtripResample2MT) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 203300,
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 206917,
2000);
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 340);
}
@@ -201,7 +201,7 @@ TEST(JxlTest, RoundtripOutOfOrderProcessing) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_EPF, 3);
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 27444, 400);
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 26933, 400);
EXPECT_LE(ButteraugliDistance(t.ppf(), ppf_out), 1.35);
}
@@ -221,7 +221,7 @@ TEST(JxlTest, RoundtripOutOfOrderProcessingBorder) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_RESAMPLING, 2);
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 10065, 200);
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 9747, 200);
EXPECT_LE(ButteraugliDistance(t.ppf(), ppf_out), 2.9);
}
@@ -236,7 +236,7 @@ TEST(JxlTest, RoundtripResample4) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_RESAMPLING, 4);
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 5758, 100);
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 5888, 100);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 22);
}
@@ -296,7 +296,7 @@ TEST(JxlTest, RoundtripMultiGroup) {
auto run_kitten = std::async(std::launch::async, test, SpeedTier::kKitten,
1.0f, 63624u, 8.5);
auto run_wombat = std::async(std::launch::async, test, SpeedTier::kWombat,
- 2.0f, 39620u, 15.5);
+ 2.0f, 38536u, 15.7);
}
TEST(JxlTest, RoundtripRGBToGrayscale) {
@@ -505,7 +505,7 @@ TEST(JxlTest, RoundtripSmallNL) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 916, 45);
- EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.82);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.92);
}
TEST(JxlTest, RoundtripNoGaborishNoAR) {
@@ -539,7 +539,7 @@ TEST(JxlTest, RoundtripSmallNoGaborish) {
PackedPixelFile ppf_out;
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 1006, 20);
- EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.1);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.2);
}
TEST(JxlTest, RoundtripSmallPatchesAlpha) {
@@ -895,7 +895,7 @@ TEST(JxlTest, RoundtripAlphaPremultiplied) {
ButteraugliDistance(io_nopremul.frames, io2.frames,
ButteraugliParams(), *JxlGetDefaultCms(),
/*distmap=*/nullptr),
- 1.0);
+ 1.1);
}
}
}
@@ -936,7 +936,7 @@ TEST(JxlTest, RoundtripAlphaResamplingOnlyAlpha) {
cparams.AddOption(JXL_ENC_FRAME_SETTING_EXTRA_CHANNEL_RESAMPLING, 2);
PackedPixelFile ppf_out;
- EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 32000, 1000);
+ EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 33179, 1000);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.52);
}
@@ -1316,8 +1316,13 @@ size_t RoundtripJpeg(const std::vector<uint8_t>& jpeg_in, ThreadPool* pool) {
&compressed));
jxl::JXLDecompressParams dparams;
- test::DefaultAcceptedFormats(dparams);
test::SetThreadParallelRunner(dparams, pool);
+ {
+ std::vector<uint8_t> out;
+ jxl::PackedPixelFile ppf;
+ EXPECT_FALSE(DecodeImageJXL(compressed.data(), compressed.size() - 1,
+ dparams, nullptr, &ppf, &out));
+ }
std::vector<uint8_t> out;
jxl::PackedPixelFile ppf;
EXPECT_TRUE(DecodeImageJXL(compressed.data(), compressed.size(), dparams,
@@ -1504,6 +1509,57 @@ JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionMetadata) {
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 1334u, 100);
}
+JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionEmptyExif) {
+ ThreadPoolForTests pool(8);
+ const std::vector<uint8_t> orig = {
+ // SOI
+ 0xff, 0xd8, //
+ // APP1
+ 0xff, 0xe1, 0x00, 0x08, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, //
+ // DQT
+ 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x03, 0x02, //
+ 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05, //
+ 0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0a, 0x07, 0x07, 0x06, //
+ 0x08, 0x0c, 0x0a, 0x0c, 0x0c, 0x0b, 0x0a, 0x0b, 0x0b, 0x0d, //
+ 0x0e, 0x12, 0x10, 0x0d, 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, //
+ 0x16, 0x10, 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0c, 0x0f, //
+ 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, 0x14, //
+ // SOF
+ 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, //
+ 0x01, 0x11, 0x00, //
+ // DHT
+ 0xff, 0xc4, 0x00, 0xd2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, //
+ 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
+ 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, //
+ 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, //
+ 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, //
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, //
+ 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, //
+ 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, //
+ 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, //
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, //
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, //
+ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, //
+ 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, //
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, //
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, //
+ 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, //
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, //
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, //
+ 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, //
+ 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, //
+ 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, //
+ 0xf9, 0xfa, //
+ // SOS
+ 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, //
+ // entropy coded data
+ 0xfc, 0xaa, 0xaf, //
+ // EOI
+ 0xff, 0xd9, //
+ };
+ EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 466u, 100);
+}
+
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionRestarts) {
ThreadPoolForTests pool(8);
const std::vector<uint8_t> orig =
diff --git a/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc b/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc
index c7752d8cfc..ba4651430f 100644
--- a/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/lehmer_code_test.cc
@@ -5,16 +5,15 @@
#include "lib/jxl/lehmer_code.h"
-#include <stdint.h>
-#include <string.h>
-
-#include <algorithm>
+#include <cstdint>
+#include <cstring>
#include <numeric>
#include <vector>
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/random.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/test_utils.h"
#include "lib/jxl/testing.h"
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h b/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h
index df54a9425e..0a71bec24f 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h
@@ -6,9 +6,17 @@
#ifndef LIB_JXL_MODULAR_ENCODING_CONTEXT_PREDICT_H_
#define LIB_JXL_MODULAR_ENCODING_CONTEXT_PREDICT_H_
-#include <utility>
+#include <algorithm>
+#include <array>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
#include <vector>
+#include "lib/jxl/base/bits.h"
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/field_encodings.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/image_ops.h"
#include "lib/jxl/modular/modular_image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc
index f863823629..04f8812750 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc
@@ -5,8 +5,7 @@
#include "lib/jxl/modular/encoding/enc_debug_tree.h"
-#include <cinttypes>
-#include <cstdint>
+#include <cinttypes> // PRId64
#include <cstdlib>
#include "lib/jxl/base/os_macros.h"
diff --git a/third_party/jpeg-xl/lib/jxl/modular/options.h b/third_party/jpeg-xl/lib/jxl/modular/options.h
index 6613b513de..5b08236ff2 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/options.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/options.h
@@ -6,9 +6,9 @@
#ifndef LIB_JXL_MODULAR_OPTIONS_H_
#define LIB_JXL_MODULAR_OPTIONS_H_
-#include <stdint.h>
-
#include <array>
+#include <cstddef>
+#include <cstdint>
#include <vector>
#include "lib/jxl/enc_ans_params.h"
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc
index 7f9399d3c4..86d161e891 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc
@@ -170,6 +170,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
size_t w = input.channel[begin_c].w;
size_t h = input.channel[begin_c].h;
+ if (input.bitdepth >= 32) return false;
if (!lossy && nb_colors < 2) return false;
if (!lossy && nb == 1) {
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc
index 1ab499ccf6..7726fd8ff3 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc
@@ -5,6 +5,10 @@
#include "lib/jxl/modular/transform/palette.h"
+#include <atomic>
+
+#include "lib/jxl/modular/transform/transform.h" // CheckEqualChannels
+
namespace jxl {
Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors,
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h
index 2a9e5c71f4..ee51d4c556 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h
@@ -6,13 +6,17 @@
#ifndef LIB_JXL_MODULAR_TRANSFORM_PALETTE_H_
#define LIB_JXL_MODULAR_TRANSFORM_PALETTE_H_
-#include <atomic>
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/modular/encoding/context_predict.h"
#include "lib/jxl/modular/modular_image.h"
-#include "lib/jxl/modular/transform/transform.h" // CheckEqualChannels
+#include "lib/jxl/modular/options.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h
index f0333da6fd..f56d6dd7e9 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h
@@ -23,9 +23,11 @@
// wavelet transform", IEEE Transactions on Image Processing, vol. 1, no. 2, pp.
// 205-220, April 1992, doi: 10.1109/83.136597.
-#include <stdlib.h>
+#include <cstdlib>
+#include <vector>
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/modular/modular_image.h"
#include "lib/jxl/modular/transform/transform.h"
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc
index a609cfb3fb..05a18215d1 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.cc
@@ -5,7 +5,7 @@
#include "lib/jxl/modular/transform/transform.h"
-#include <cinttypes>
+#include <cinttypes> // PRIu32
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/fields.h"
diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h
index 70c383834a..cb46d0888f 100644
--- a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h
+++ b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h
@@ -6,13 +6,17 @@
#ifndef LIB_JXL_MODULAR_TRANSFORM_TRANSFORM_H_
#define LIB_JXL_MODULAR_TRANSFORM_TRANSFORM_H_
+#include <cstddef>
#include <cstdint>
-#include <string>
#include <vector>
+#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/field_encodings.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/modular/encoding/context_predict.h"
+#include "lib/jxl/modular/modular_image.h"
#include "lib/jxl/modular/options.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc b/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc
index b8ea839b9e..dff257f9bc 100644
--- a/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/opsin_image_test.cc
@@ -10,6 +10,8 @@
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/matrix_ops.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/cms/opsin_params.h"
#include "lib/jxl/dec_xyb.h"
#include "lib/jxl/enc_xyb.h"
diff --git a/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc b/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc
index b8f9aa13df..4407658ddf 100644
--- a/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/opsin_inverse_test.cc
@@ -8,6 +8,8 @@
#include <utility>
#include "lib/jxl/base/data_parallel.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/codec_in_out.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_xyb.h"
diff --git a/third_party/jpeg-xl/lib/jxl/passes_test.cc b/third_party/jpeg-xl/lib/jxl/passes_test.cc
index e7a7547a0c..a525987018 100644
--- a/third_party/jpeg-xl/lib/jxl/passes_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/passes_test.cc
@@ -4,8 +4,8 @@
// license that can be found in the LICENSE file.
#include <jxl/cms.h>
-#include <stddef.h>
+#include <cstddef>
#include <cstdint>
#include <future>
#include <string>
@@ -16,6 +16,7 @@
#include "lib/extras/dec/jxl.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/override.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/image.h"
@@ -51,7 +52,7 @@ TEST(PassesTest, RoundtripSmallPasses) {
ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
*JxlGetDefaultCms(),
/*distmap=*/nullptr),
- 0.8222);
+ 1.0);
}
TEST(PassesTest, RoundtripUnalignedPasses) {
diff --git a/third_party/jpeg-xl/lib/jxl/preview_test.cc b/third_party/jpeg-xl/lib/jxl/preview_test.cc
index c482db9fd8..fab8943e10 100644
--- a/third_party/jpeg-xl/lib/jxl/preview_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/preview_test.cc
@@ -12,7 +12,9 @@
#include "lib/extras/codec.h"
#include "lib/jxl/base/span.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/codec_in_out.h"
+#include "lib/jxl/common.h"
#include "lib/jxl/enc_params.h"
#include "lib/jxl/headers.h"
#include "lib/jxl/image_bundle.h"
diff --git a/third_party/jpeg-xl/lib/jxl/quant_weights.h b/third_party/jpeg-xl/lib/jxl/quant_weights.h
index 0fa23ffddb..8192f71443 100644
--- a/third_party/jpeg-xl/lib/jxl/quant_weights.h
+++ b/third_party/jpeg-xl/lib/jxl/quant_weights.h
@@ -11,16 +11,14 @@
#include <array>
#include <hwy/aligned_allocator.h>
-#include <utility>
#include <vector>
#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
-#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_bit_reader.h"
-#include "lib/jxl/image.h"
+#include "lib/jxl/frame_dimensions.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc b/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc
index 776a1c776d..61c812d620 100644
--- a/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/quant_weights_test.cc
@@ -10,14 +10,21 @@
#include <cmath>
#include <hwy/base.h> // HWY_ALIGN_MAX
#include <hwy/tests/hwy_gtest.h>
+#include <iterator>
#include <numeric>
+#include <vector>
+#include "lib/jxl/ac_strategy.h"
#include "lib/jxl/base/random.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/dct_for_test.h"
#include "lib/jxl/dec_transforms_testonly.h"
#include "lib/jxl/enc_modular.h"
+#include "lib/jxl/enc_params.h"
#include "lib/jxl/enc_quant_weights.h"
#include "lib/jxl/enc_transforms.h"
+#include "lib/jxl/frame_header.h"
+#include "lib/jxl/image_metadata.h"
#include "lib/jxl/testing.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/quantizer.cc b/third_party/jpeg-xl/lib/jxl/quantizer.cc
index b9ea43e0d6..f63c6a589d 100644
--- a/third_party/jpeg-xl/lib/jxl/quantizer.cc
+++ b/third_party/jpeg-xl/lib/jxl/quantizer.cc
@@ -5,11 +5,11 @@
#include "lib/jxl/quantizer.h"
-#include <string.h>
-
#include <algorithm>
+#include <cstring>
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/field_encodings.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/quantizer.h b/third_party/jpeg-xl/lib/jxl/quantizer.h
index 602d12bdfa..b61c8acde6 100644
--- a/third_party/jpeg-xl/lib/jxl/quantizer.h
+++ b/third_party/jpeg-xl/lib/jxl/quantizer.h
@@ -6,21 +6,17 @@
#ifndef LIB_JXL_QUANTIZER_H_
#define LIB_JXL_QUANTIZER_H_
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-
#include <algorithm>
#include <cmath>
-#include <utility>
-#include <vector>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
-#include "lib/jxl/ac_strategy.h"
-#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/dct_util.h"
#include "lib/jxl/dec_bit_reader.h"
+#include "lib/jxl/field_encodings.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/image.h"
#include "lib/jxl/quant_weights.h"
diff --git a/third_party/jpeg-xl/lib/jxl/quantizer_test.cc b/third_party/jpeg-xl/lib/jxl/quantizer_test.cc
index eeaac9ba53..5b965b78ca 100644
--- a/third_party/jpeg-xl/lib/jxl/quantizer_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/quantizer_test.cc
@@ -5,9 +5,17 @@
#include "lib/jxl/quantizer.h"
+#include <cstddef>
+#include <cstdint>
+
+#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_bit_reader.h"
+#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/enc_fields.h"
+#include "lib/jxl/fields.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/image_test_utils.h"
+#include "lib/jxl/quant_weights.h"
#include "lib/jxl/testing.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc
index 27718e6413..f95237dea5 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.cc
@@ -6,9 +6,16 @@
#include "lib/jxl/render_pipeline/low_memory_render_pipeline.h"
#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+#include <vector>
#include "lib/jxl/base/arch_macros.h"
+#include "lib/jxl/base/common.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/image_ops.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h
index f0b21d3dca..5f88a34b5e 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/low_memory_render_pipeline.h
@@ -6,9 +6,16 @@
#ifndef LIB_JXL_RENDER_PIPELINE_LOW_MEMORY_RENDER_PIPELINE_H_
#define LIB_JXL_RENDER_PIPELINE_LOW_MEMORY_RENDER_PIPELINE_H_
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+#include <vector>
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_group_border.h"
+#include "lib/jxl/frame_header.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/render_pipeline/render_pipeline.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc
index 09e3dbab76..ed27a2efa0 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.cc
@@ -5,6 +5,10 @@
#include "lib/jxl/render_pipeline/render_pipeline.h"
+#include <memory>
+#include <utility>
+
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/render_pipeline/low_memory_render_pipeline.h"
#include "lib/jxl/render_pipeline/simple_render_pipeline.h"
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h
index c61420be4b..fa7a1e58c4 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline.h
@@ -6,8 +6,16 @@
#ifndef LIB_JXL_RENDER_PIPELINE_RENDER_PIPELINE_H_
#define LIB_JXL_RENDER_PIPELINE_RENDER_PIPELINE_H_
-#include <stdint.h>
-
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/frame_dimensions.h"
#include "lib/jxl/image.h"
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h
index d054027ba7..3c9b83addd 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_stage.h
@@ -6,7 +6,9 @@
#ifndef LIB_JXL_RENDER_PIPELINE_RENDER_PIPELINE_STAGE_H_
#define LIB_JXL_RENDER_PIPELINE_RENDER_PIPELINE_STAGE_H_
-#include <stdint.h>
+#include <cstddef>
+#include <utility>
+#include <vector>
#include "lib/jxl/base/arch_macros.h"
#include "lib/jxl/base/status.h"
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc
index e9cb913983..f5d7635206 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/render_pipeline_test.cc
@@ -247,7 +247,7 @@ TEST_P(RenderPipelineTestParam, PipelineTest) {
ASSERT_EQ(io_default.frames.size(), io_slow_pipeline.frames.size());
for (size_t i = 0; i < io_default.frames.size(); i++) {
#if JXL_HIGH_PRECISION
- constexpr float kMaxError = 5e-5;
+ constexpr float kMaxError = 2e-4;
#else
constexpr float kMaxError = 5e-4;
#endif
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc
index 77ddb3d430..88cc04ed0c 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.cc
@@ -5,8 +5,14 @@
#include "lib/jxl/render_pipeline/simple_render_pipeline.h"
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
#include <hwy/base.h>
+#include <utility>
+#include <vector>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image_ops.h"
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h
index 1240b9fa46..4fd81755f3 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/simple_render_pipeline.h
@@ -6,8 +6,13 @@
#ifndef LIB_JXL_RENDER_PIPELINE_SIMPLE_RENDER_PIPELINE_H_
#define LIB_JXL_RENDER_PIPELINE_SIMPLE_RENDER_PIPELINE_H_
-#include <stdint.h>
+#include <cstddef>
+#include <utility>
+#include <vector>
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/render_pipeline/render_pipeline.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.h
index bd7797f991..ebdc9be992 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_noise.h
@@ -5,15 +5,12 @@
#ifndef LIB_JXL_RENDER_PIPELINE_STAGE_NOISE_H_
#define LIB_JXL_RENDER_PIPELINE_STAGE_NOISE_H_
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <algorithm>
-#include <utility>
-#include <vector>
+#include <cstddef>
+#include <memory>
-#include "lib/jxl/dec_noise.h"
+#include "lib/jxl/chroma_from_luma.h"
+#include "lib/jxl/noise.h"
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc
index 92a13090a7..9473ff3dbe 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_splines.cc
@@ -5,11 +5,19 @@
#include "lib/jxl/render_pipeline/stage_splines.h"
+#include <cstddef>
+#include <memory>
+
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "lib/jxl/render_pipeline/stage_splines.cc"
#include <hwy/foreach_target.h>
#include <hwy/highway.h>
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/base/status.h"
+#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
+#include "lib/jxl/splines.h"
+
HWY_BEFORE_NAMESPACE();
namespace jxl {
namespace HWY_NAMESPACE {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h
index ba2c51ee97..32e5fba932 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_write.h
@@ -6,11 +6,15 @@
#ifndef LIB_JXL_RENDER_PIPELINE_STAGE_WRITE_H_
#define LIB_JXL_RENDER_PIPELINE_STAGE_WRITE_H_
-#include <functional>
+#include <cstddef>
+#include <memory>
+#include <vector>
#include "lib/jxl/dec_cache.h"
#include "lib/jxl/dec_xyb.h"
+#include "lib/jxl/image.h"
#include "lib/jxl/image_bundle.h"
+#include "lib/jxl/image_metadata.h"
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h b/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h
index c2c25c46c3..54d40671d6 100644
--- a/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h
+++ b/third_party/jpeg-xl/lib/jxl/render_pipeline/test_render_pipeline_stages.h
@@ -3,9 +3,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
+#include <cmath>
+#include <cstdint>
+#include <cstdio>
#include "lib/jxl/base/status.h"
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
diff --git a/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc b/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc
index 07e43e4ddf..fa23956995 100644
--- a/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/roundtrip_test.cc
@@ -23,6 +23,7 @@
#include "lib/extras/codec.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/span.h"
+#include "lib/jxl/base/status.h"
#include "lib/jxl/butteraugli/butteraugli.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_bit_reader.h"
@@ -432,7 +433,7 @@ void VerifyRoundtripCompression(
float butteraugli_score = ButteraugliDistance(
original_io.frames, decoded_io.frames, ba, *JxlGetDefaultCms(),
/*distmap=*/nullptr, nullptr);
- float target_score = 1.3f;
+ float target_score = 1.4f;
// upsampling mode 1 (unlike default and NN) does not downscale back to the
// already downsampled image
if (upsampling_mode == 1 && resampling >= 4 && already_downsampled)
diff --git a/third_party/jpeg-xl/lib/jxl/sanitizers.h b/third_party/jpeg-xl/lib/jxl/sanitizers.h
index bb133e9203..e05f79737b 100644
--- a/third_party/jpeg-xl/lib/jxl/sanitizers.h
+++ b/third_party/jpeg-xl/lib/jxl/sanitizers.h
@@ -6,20 +6,20 @@
#ifndef LIB_JXL_SANITIZERS_H_
#define LIB_JXL_SANITIZERS_H_
-#include <stddef.h>
+#include <cstddef>
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/sanitizer_definitions.h"
#include "lib/jxl/image.h"
#if JXL_MEMORY_SANITIZER
-#include <inttypes.h>
-#include <stdio.h>
-
#include <algorithm>
+#include <cinttypes> // PRId64
+#include <cstdio>
#include <string>
#include <vector>
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "sanitizer/msan_interface.h"
#endif
diff --git a/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc b/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc
index 8783faec8f..aefbbc559e 100644
--- a/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/speed_tier_test.cc
@@ -15,7 +15,7 @@
#include "lib/extras/dec/jxl.h"
#include "lib/extras/enc/jxl.h"
-#include "lib/jxl/enc_params.h"
+#include "lib/jxl/common.h"
#include "lib/jxl/test_image.h"
#include "lib/jxl/test_utils.h"
#include "lib/jxl/testing.h"
diff --git a/third_party/jpeg-xl/lib/jxl/splines.cc b/third_party/jpeg-xl/lib/jxl/splines.cc
index 2df2160d76..fd68c15493 100644
--- a/third_party/jpeg-xl/lib/jxl/splines.cc
+++ b/third_party/jpeg-xl/lib/jxl/splines.cc
@@ -6,12 +6,13 @@
#include "lib/jxl/splines.h"
#include <algorithm>
-#include <cinttypes>
+#include <cinttypes> // PRIu64
#include <cmath>
#include <limits>
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/common.h" // JXL_HIGH_PRECISION
diff --git a/third_party/jpeg-xl/lib/jxl/splines.h b/third_party/jpeg-xl/lib/jxl/splines.h
index af51ec937e..b292d6952b 100644
--- a/third_party/jpeg-xl/lib/jxl/splines.h
+++ b/third_party/jpeg-xl/lib/jxl/splines.h
@@ -14,6 +14,7 @@
#include <vector>
#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/image.h"
diff --git a/third_party/jpeg-xl/lib/jxl/splines_gbench.cc b/third_party/jpeg-xl/lib/jxl/splines_gbench.cc
index 903c5b6328..95f890e3ce 100644
--- a/third_party/jpeg-xl/lib/jxl/splines_gbench.cc
+++ b/third_party/jpeg-xl/lib/jxl/splines_gbench.cc
@@ -3,9 +3,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include <array>
+#include <cstddef>
+#include <vector>
#include "benchmark/benchmark.h"
+#include "lib/jxl/base/rect.h"
+#include "lib/jxl/chroma_from_luma.h"
#include "lib/jxl/image_ops.h"
#include "lib/jxl/splines.h"
diff --git a/third_party/jpeg-xl/lib/jxl/splines_test.cc b/third_party/jpeg-xl/lib/jxl/splines_test.cc
index 83cc524234..56f2344b4a 100644
--- a/third_party/jpeg-xl/lib/jxl/splines_test.cc
+++ b/third_party/jpeg-xl/lib/jxl/splines_test.cc
@@ -18,6 +18,7 @@
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/chroma_from_luma.h"
diff --git a/third_party/jpeg-xl/lib/jxl/test_image.cc b/third_party/jpeg-xl/lib/jxl/test_image.cc
index d2e17c6ab0..eab5ccca14 100644
--- a/third_party/jpeg-xl/lib/jxl/test_image.cc
+++ b/third_party/jpeg-xl/lib/jxl/test_image.cc
@@ -8,8 +8,11 @@
#include <jxl/encode.h>
#include <algorithm>
+#include <cstddef>
+#include <cstdint>
#include <cstring>
#include <utility>
+#include <vector>
#include "lib/extras/dec/color_description.h"
#include "lib/extras/dec/color_hints.h"
diff --git a/third_party/jpeg-xl/lib/jxl/test_image.h b/third_party/jpeg-xl/lib/jxl/test_image.h
index 13d0806ec8..ae62047052 100644
--- a/third_party/jpeg-xl/lib/jxl/test_image.h
+++ b/third_party/jpeg-xl/lib/jxl/test_image.h
@@ -8,14 +8,13 @@
#include <jxl/codestream_header.h>
#include <jxl/types.h>
-#include <stddef.h>
+#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "lib/extras/packed_image.h"
-#include "lib/jxl/base/span.h"
namespace jxl {
namespace test {
diff --git a/third_party/jpeg-xl/lib/jxl/test_utils.h b/third_party/jpeg-xl/lib/jxl/test_utils.h
index dc50490174..0d0d8004c1 100644
--- a/third_party/jpeg-xl/lib/jxl/test_utils.h
+++ b/third_party/jpeg-xl/lib/jxl/test_utils.h
@@ -21,6 +21,7 @@
#include "lib/extras/dec/jxl.h"
#include "lib/extras/enc/jxl.h"
#include "lib/extras/packed_image.h"
+#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
@@ -210,4 +211,15 @@ bool operator!=(const jxl::Bytes& a, const jxl::Bytes& b);
} // namespace jxl
+#if !defined(FUZZ_TEST)
+struct FuzzTestSink {
+ template <typename F>
+ FuzzTestSink WithSeeds(F) {
+ return *this;
+ }
+};
+#define FUZZ_TEST(A, B) \
+ const JXL_MAYBE_UNUSED FuzzTestSink unused##A##B = FuzzTestSink()
+#endif
+
#endif // LIB_JXL_TEST_UTILS_H_
diff --git a/third_party/jpeg-xl/lib/jxl/xorshift128plus-inl.h b/third_party/jpeg-xl/lib/jxl/xorshift128plus-inl.h
index a473d591f2..f7967655df 100644
--- a/third_party/jpeg-xl/lib/jxl/xorshift128plus-inl.h
+++ b/third_party/jpeg-xl/lib/jxl/xorshift128plus-inl.h
@@ -12,8 +12,8 @@
#define LIB_JXL_XORSHIFT128PLUS_INL_H_
#endif
-#include <stddef.h>
-
+#include <cstddef>
+#include <cstdint>
#include <hwy/highway.h>
HWY_BEFORE_NAMESPACE();
namespace jxl {
diff --git a/third_party/jpeg-xl/lib/jxl_extras.cmake b/third_party/jpeg-xl/lib/jxl_extras.cmake
index 747c07eb9c..3a45d9c971 100644
--- a/third_party/jpeg-xl/lib/jxl_extras.cmake
+++ b/third_party/jpeg-xl/lib/jxl_extras.cmake
@@ -151,7 +151,7 @@ endif()
### Library that does not depend on internal parts of jxl library.
### Used by cjxl and djxl binaries.
-add_library(jxl_extras_codec
+add_library(jxl_extras_codec STATIC
$<TARGET_OBJECTS:jxl_extras_core-obj>
)
target_link_libraries(jxl_extras_codec PRIVATE
diff --git a/third_party/jpeg-xl/lib/jxl_lists.bzl b/third_party/jpeg-xl/lib/jxl_lists.bzl
index a66706aa83..41f97e4347 100644
--- a/third_party/jpeg-xl/lib/jxl_lists.bzl
+++ b/third_party/jpeg-xl/lib/jxl_lists.bzl
@@ -20,12 +20,14 @@ libjxl_base_sources = [
"jxl/base/fast_math-inl.h",
"jxl/base/float.h",
"jxl/base/iaca.h",
+ "jxl/base/include_jpeglib.h",
"jxl/base/matrix_ops.h",
"jxl/base/os_macros.h",
"jxl/base/override.h",
"jxl/base/printf_macros.h",
"jxl/base/random.h",
"jxl/base/rational_polynomial-inl.h",
+ "jxl/base/rect.h",
"jxl/base/sanitizer_definitions.h",
"jxl/base/scope_guard.h",
"jxl/base/span.h",
diff --git a/third_party/jpeg-xl/lib/jxl_lists.cmake b/third_party/jpeg-xl/lib/jxl_lists.cmake
index d1a56f9ca8..f7e36692df 100644
--- a/third_party/jpeg-xl/lib/jxl_lists.cmake
+++ b/third_party/jpeg-xl/lib/jxl_lists.cmake
@@ -17,12 +17,14 @@ set(JPEGXL_INTERNAL_BASE_SOURCES
jxl/base/fast_math-inl.h
jxl/base/float.h
jxl/base/iaca.h
+ jxl/base/include_jpeglib.h
jxl/base/matrix_ops.h
jxl/base/os_macros.h
jxl/base/override.h
jxl/base/printf_macros.h
jxl/base/random.h
jxl/base/rational_polynomial-inl.h
+ jxl/base/rect.h
jxl/base/sanitizer_definitions.h
jxl/base/scope_guard.h
jxl/base/span.h
diff --git a/third_party/jpeg-xl/lib/jxl_tests.cmake b/third_party/jpeg-xl/lib/jxl_tests.cmake
index 64f807cb82..5613dffdde 100644
--- a/third_party/jpeg-xl/lib/jxl_tests.cmake
+++ b/third_party/jpeg-xl/lib/jxl_tests.cmake
@@ -46,7 +46,7 @@ if (EMSCRIPTEN)
-s EXIT_RUNTIME=1 \
-s NODERAWFS=1 \
")
- if (JPEGXL_ENABLE_WASM_TRHEADS)
+ if (JPEGXL_ENABLE_WASM_THREADS)
set(JXL_WASM_TEST_LINK_FLAGS "${JXL_WASM_TEST_LINK_FLAGS} \
-s PROXY_TO_PTHREAD \
-s USE_PTHREADS=1 \
diff --git a/third_party/jpeg-xl/lib/threads/thread_parallel_runner_test.cc b/third_party/jpeg-xl/lib/threads/thread_parallel_runner_test.cc
index 0762b3299b..effe5d5feb 100644
--- a/third_party/jpeg-xl/lib/threads/thread_parallel_runner_test.cc
+++ b/third_party/jpeg-xl/lib/threads/thread_parallel_runner_test.cc
@@ -3,7 +3,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <algorithm>
#include <atomic>
+#include <cstdint>
+#include <vector>
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/test_utils.h"
diff --git a/third_party/libwebrtc/AUTHORS b/third_party/libwebrtc/AUTHORS
index 6e922401d0..c0c40930d6 100644
--- a/third_party/libwebrtc/AUTHORS
+++ b/third_party/libwebrtc/AUTHORS
@@ -65,6 +65,7 @@ Jie Mao <maojie0924@gmail.com>
Jiwon Kim <jwkim0000@gmail.com>
Johnny Wong <hellojinqiang@gmail.com>
Jose Antonio Olivera Ortega <josea.olivera@gmail.com>
+Karim Hammache <karim@karhm.com>
Keiichi Enomoto <enm10k@gmail.com>
Kiran Thind <kiran.thind@gmail.com>
Korniltsev Anatoly <korniltsev.anatoly@gmail.com>
diff --git a/third_party/libwebrtc/DEPS b/third_party/libwebrtc/DEPS
index 9f5cd9fd1f..84e12c12aa 100644
--- a/third_party/libwebrtc/DEPS
+++ b/third_party/libwebrtc/DEPS
@@ -10,7 +10,7 @@ vars = {
# chromium waterfalls. More info at: crbug.com/570091.
'checkout_configuration': 'default',
'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"',
- 'chromium_revision': 'e1fb84c37d20b7b85bfdd24e4ab19967ce1b77df',
+ 'chromium_revision': 'a4279f28422a0b59acdc9fcfe7233d9f0e3b2dc6',
# Fetch the prebuilt binaries for llvm-cov and llvm-profdata. Needed to
# process the raw profiles produced by instrumented targets (built with
@@ -25,7 +25,7 @@ vars = {
# By default, download the fuchsia sdk from the public sdk directory.
'fuchsia_sdk_cipd_prefix': 'fuchsia/sdk/core/',
- 'fuchsia_version': 'version:17.20240120.1.1',
+ 'fuchsia_version': 'version:18.20240207.3.1',
# By default, download the fuchsia images from the fuchsia GCS bucket.
'fuchsia_images_bucket': 'fuchsia',
'checkout_fuchsia': False,
@@ -40,7 +40,7 @@ vars = {
# RBE instance to use for running remote builds
'rbe_instance': 'projects/rbe-webrtc-developer/instances/default_instance',
# reclient CIPD package version
- 'reclient_version': 're_client_version:0.126.0.4aaef37-gomaip',
+ 'reclient_version': 're_client_version:0.131.1.784ddbb-gomaip',
# ninja CIPD package version
# https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja
@@ -50,30 +50,30 @@ vars = {
deps = {
# TODO(kjellander): Move this to be Android-only.
'src/base':
- 'https://chromium.googlesource.com/chromium/src/base@36ecc8e397422620def3bb19a7ba392810ca2442',
+ 'https://chromium.googlesource.com/chromium/src/base@fd5eca261fa03e22f053a0eaa5b010ca01c6fe51',
'src/build':
- 'https://chromium.googlesource.com/chromium/src/build@28cd6ea727d171ec990e6174308451d4178d7f8e',
+ 'https://chromium.googlesource.com/chromium/src/build@a3566ffdee8a4dda521d05c378d915427d049292',
'src/buildtools':
- 'https://chromium.googlesource.com/chromium/src/buildtools@aadc2aa5f7382cdb5bc8e9309971356cf7722773',
+ 'https://chromium.googlesource.com/chromium/src/buildtools@f35a7d885ace0b7dd8e8ac2376ca759d3905f4dc',
# Gradle 6.6.1. Used for testing Android Studio project generation for WebRTC.
'src/examples/androidtests/third_party/gradle': {
'url': 'https://chromium.googlesource.com/external/github.com/gradle/gradle.git@f2d1fb54a951d8b11d25748e4711bec8d128d7e3',
'condition': 'checkout_android',
},
'src/ios': {
- 'url': 'https://chromium.googlesource.com/chromium/src/ios@e18cc47f9334d9dcf911c724467795542a472b51',
+ 'url': 'https://chromium.googlesource.com/chromium/src/ios@37d33be47e19e2d4450fcb9cdf6d3213d8e4ef89',
'condition': 'checkout_ios',
},
'src/testing':
- 'https://chromium.googlesource.com/chromium/src/testing@450bfd79ee0369ac1a5465a12820b5d94a5956be',
+ 'https://chromium.googlesource.com/chromium/src/testing@a7e90605df75793b837bea0d56815344e28fe071',
'src/third_party':
- 'https://chromium.googlesource.com/chromium/src/third_party@692fab5c0074bc6fa486dce1a4aa7b2cc5609928',
+ 'https://chromium.googlesource.com/chromium/src/third_party@121de111a913373d1ac15e4605da24fd22b21bcf',
'src/buildtools/linux64': {
'packages': [
{
'package': 'gn/gn/linux-${{arch}}',
- 'version': 'git_revision:f99e015ac35f689cfdbf46e4eb174e5d2da78d8e',
+ 'version': 'git_revision:a2e2717ea670249a34b0de4b3e54f268d320bdfa',
}
],
'dep_type': 'cipd',
@@ -83,7 +83,7 @@ deps = {
'packages': [
{
'package': 'gn/gn/mac-${{arch}}',
- 'version': 'git_revision:f99e015ac35f689cfdbf46e4eb174e5d2da78d8e',
+ 'version': 'git_revision:a2e2717ea670249a34b0de4b3e54f268d320bdfa',
}
],
'dep_type': 'cipd',
@@ -93,7 +93,7 @@ deps = {
'packages': [
{
'package': 'gn/gn/windows-amd64',
- 'version': 'git_revision:f99e015ac35f689cfdbf46e4eb174e5d2da78d8e',
+ 'version': 'git_revision:a2e2717ea670249a34b0de4b3e54f268d320bdfa',
}
],
'dep_type': 'cipd',
@@ -115,11 +115,11 @@ deps = {
'src/third_party/clang-format/script':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/clang/tools/clang-format.git@e5337933f2951cacd3aeacd238ce4578163ca0b9',
'src/third_party/libc++/src':
- 'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxx.git@28aa23ffb4c7344914a5b4ac7169f12e5a12333f',
+ 'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxx.git@9d119c1f4a097b7d27210874f4eba3fc91a83a4e',
'src/third_party/libc++abi/src':
- 'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxxabi.git@ea028d4d2b8a901f6302f5371c68a24480766e2b',
+ 'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxxabi.git@a7b3d968a3a923886fea64b424bd770e69dc4ea4',
'src/third_party/libunwind/src':
- 'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libunwind.git@f400fdb561d4416b59b8f8a33d8ec8b79da60495',
+ 'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libunwind.git@8bad7bd6ec30f94bce82f7cb5b58ecbd6ce02996',
'src/third_party/ninja': {
'packages': [
@@ -155,7 +155,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/aapt2',
- 'version': 'y1G4s2RWI63L9ZLgzS3RzFdWdeblpCmYyAUzMphcQawC',
+ 'version': 'G1S0vNnfv3f8FD-9mH5RFSUiK-mnSwri_IdiVQKwLP0C',
},
],
'condition': 'checkout_android',
@@ -185,11 +185,11 @@ deps = {
},
'src/third_party/boringssl/src':
- 'https://boringssl.googlesource.com/boringssl.git@414f69504d30d0848b69f6453ea7fb5e88004cb4',
+ 'https://boringssl.googlesource.com/boringssl.git@10a2132f50aaf7d49db7e258666f447b821588d9',
'src/third_party/breakpad/breakpad':
- 'https://chromium.googlesource.com/breakpad/breakpad.git@62ecd463583d09eb7d15b1d410055f30b2c7bcb4',
+ 'https://chromium.googlesource.com/breakpad/breakpad.git@6551ac3632eb7236642366f70a2eb865b87a3329',
'src/third_party/catapult':
- 'https://chromium.googlesource.com/catapult.git@3e413d7b62c09fda8713146714ba2146a0369d86',
+ 'https://chromium.googlesource.com/catapult.git@c712e9cc34286f512da4300ede35957ea7c138a6',
'src/third_party/ced/src': {
'url': 'https://chromium.googlesource.com/external/github.com/google/compact_enc_det.git@ba412eaaacd3186085babcd901679a48863c7dd5',
},
@@ -202,9 +202,9 @@ deps = {
'src/third_party/crc32c/src':
'https://chromium.googlesource.com/external/github.com/google/crc32c.git@fa5ade41ee480003d9c5af6f43567ba22e4e17e6',
'src/third_party/depot_tools':
- 'https://chromium.googlesource.com/chromium/tools/depot_tools.git@46cb7d0aca592cd20ddc2f6cb16ee386b2abbf0d',
+ 'https://chromium.googlesource.com/chromium/tools/depot_tools.git@f76550541c751f956ef9287f2695a6c8a74bf709',
'src/third_party/ffmpeg':
- 'https://chromium.googlesource.com/chromium/third_party/ffmpeg.git@17525de887d54b970ffdd421a0879c1db1952307',
+ 'https://chromium.googlesource.com/chromium/third_party/ffmpeg.git@7c1b0b524c639beeb25363b1d0809ebe5c6efe5e',
'src/third_party/flatbuffers/src':
'https://chromium.googlesource.com/external/github.com/google/flatbuffers.git@bcb9ef187628fe07514e57756d05e6a6296f7dc5',
'src/third_party/grpc/src': {
@@ -212,11 +212,11 @@ deps = {
},
# Used for embedded builds. CrOS & Linux use the system version.
'src/third_party/fontconfig/src': {
- 'url': 'https://chromium.googlesource.com/external/fontconfig.git@2fb3419a92156569bc1ec707401258c922cd0d99',
+ 'url': 'https://chromium.googlesource.com/external/fontconfig.git@14d466b30a8ab4a9d789977ed94f2c30e7209267',
'condition': 'checkout_linux',
},
'src/third_party/freetype/src':
- 'https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@57617782464411201ce7bbc93b086c1b4d7d84a5',
+ 'https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@47574f7ea445c8bb751da0fa716424c9c29a6807',
'src/third_party/harfbuzz-ng/src':
'https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@155015f4bec434ecc2f94621665844218f05ce51',
'src/third_party/google_benchmark/src': {
@@ -267,7 +267,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/kotlin_stdlib',
- 'version': '7f5xFu_YQrbg_vacQ5mMcUFIkMPpvM_mQ8QERRKYBvUC',
+ 'version': '-uFeIws_FQzyqmgZlGL37ooRLAD8mwClD33O8rZwnTsC',
},
],
'condition': 'checkout_android',
@@ -288,7 +288,7 @@ deps = {
'src/third_party/libFuzzer/src':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/compiler-rt/lib/fuzzer.git@758bd21f103a501b362b1ca46fa8fcb692eaa303',
'src/third_party/fuzztest/src':
- 'https://chromium.googlesource.com/external/github.com/google/fuzztest.git@12e7428ab0847b1d1dc6c4b89203adfd1f16a1ad',
+ 'https://chromium.googlesource.com/external/github.com/google/fuzztest.git@61d95200e7ece7d121cab26f0c39fbf392e6566e',
'src/third_party/libjpeg_turbo':
'https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@9b894306ec3b28cea46e84c32b56773a98c483da',
'src/third_party/libsrtp':
@@ -296,17 +296,17 @@ deps = {
'src/third_party/dav1d/libdav1d':
'https://chromium.googlesource.com/external/github.com/videolan/dav1d.git@47107e384bd1dc25674acf04d000a8cdc6195234',
'src/third_party/libaom/source/libaom':
- 'https://aomedia.googlesource.com/aom.git@646f28605eed1076d784451faa05a4e91e46ff6e',
+ 'https://aomedia.googlesource.com/aom.git@0cee19cfc8b69661a4c808624d36def44450f14e',
'src/third_party/libunwindstack': {
- 'url': 'https://chromium.googlesource.com/chromium/src/third_party/libunwindstack.git@4dbfa0e8c844c8e243b297bc185e54a99ff94f9e',
+ 'url': 'https://chromium.googlesource.com/chromium/src/third_party/libunwindstack.git@a3bb4cd02e0e984a235069f812cbef2b37c389e5',
'condition': 'checkout_android',
},
'src/third_party/perfetto':
- 'https://android.googlesource.com/platform/external/perfetto.git@d6af17fef257af28ee2417216ef87d5c5b743a1b',
+ 'https://android.googlesource.com/platform/external/perfetto.git@e01c38d714f4d55c7ef67aa9414c69479b051b38',
'src/third_party/libvpx/source/libvpx':
- 'https://chromium.googlesource.com/webm/libvpx.git@b95d17572629c676bdcfd535fb3990b9f6f8fb11',
+ 'https://chromium.googlesource.com/webm/libvpx.git@96b64eaac5adbac59e43e34d87af3ba0fb06bca6',
'src/third_party/libyuv':
- 'https://chromium.googlesource.com/libyuv/libyuv.git@04821d1e7d60845525e8db55c7bcd41ef5be9406',
+ 'https://chromium.googlesource.com/libyuv/libyuv.git@2f2c04c1576534a7df953c2dc7c7ccf30beacd89',
'src/third_party/lss': {
'url': 'https://chromium.googlesource.com/linux-syscall-support.git@ce877209e11aa69dcfffbd53ef90ea1d07136521',
'condition': 'checkout_android or checkout_linux',
@@ -325,13 +325,13 @@ deps = {
'https://chromium.googlesource.com/external/github.com/cisco/openh264@09a4f3ec842a8932341b195c5b01e141c8a16eb7',
'src/third_party/re2/src':
- 'https://chromium.googlesource.com/external/github.com/google/re2.git@826ad10e58a042faf57d7c329b0fd0a04b797e0b',
+ 'https://chromium.googlesource.com/external/github.com/google/re2.git@ab7c5918b418428ed17dbe564e0d8402bd7d743d',
'src/third_party/r8': {
'packages': [
{
'package': 'chromium/third_party/r8',
- 'version': 'K1NPmXz0aZCAGGtC5UESEmqwT5-x6QNNb0Jo0umsez4C',
+ 'version': 'tp4vVuXzmyHJxDFlwxDb7RYZLLEufc3EnGTyOTCTNkgC',
},
],
'condition': 'checkout_android',
@@ -355,7 +355,7 @@ deps = {
'condition': 'checkout_android',
},
'src/tools':
- 'https://chromium.googlesource.com/chromium/src/tools@51d5368f2225c34a47d1be4feafebba3b6d19579',
+ 'https://chromium.googlesource.com/chromium/src/tools@2b9f1d699f313c182606ca27cdc220d9c4034577',
'src/third_party/accessibility_test_framework': {
'packages': [
@@ -379,6 +379,17 @@ deps = {
'dep_type': 'cipd',
},
+ 'src/third_party/google-java-format': {
+ 'packages': [
+ {
+ 'package': 'chromium/third_party/google-java-format',
+ 'version': 'AQn4F5NfPAs_GKX-z3OW_Q7-yJ9N6tPrDnmnDScjkTEC',
+ },
+ ],
+ 'condition': 'checkout_android or checkout_linux',
+ 'dep_type': 'cipd',
+ },
+
'src/third_party/hamcrest': {
'packages': [
{
@@ -405,7 +416,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/androidx',
- 'version': 'BW2v6j8vjcVQrdX9fXmf686JtkLjxn-KCWhAE1XT_n4C',
+ 'version': 'W2mpTbVe6yo3_GJiaoEVjCGnpicqsSrxcRMEADDJzMMC',
},
],
'condition': 'checkout_android',
@@ -416,7 +427,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/manifest_merger',
- 'version': 'tFbjqslkduDT_-y8WEZlsl9iulzcm3mgienslcU71poC',
+ 'version': 'DEhOvoBwWVbV8XAI9NG-tn5g27KeMh2pXa44mY4dY10C',
},
],
'condition': 'checkout_android',
@@ -498,7 +509,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/turbine',
- 'version': 'ABguU2WKErRBdXX1LMt0zqZListLS_05X0Rp_V7pwAYC',
+ 'version': 's-hdujub30RR2mH9Qf7pHv6h9uNGEiYVs6W1VXWeEe8C',
},
],
'condition': 'checkout_android',
@@ -509,11 +520,11 @@ deps = {
'packages': [
{
'package': 'infra/tools/luci/isolate/${{platform}}',
- 'version': 'git_revision:0d11be367258bfe14a13ff1afcf43a0bc6aedb45',
+ 'version': 'git_revision:c7b026b3a6a1f877ce46a90c5f761b10e5149891',
},
{
'package': 'infra/tools/luci/swarming/${{platform}}',
- 'version': 'git_revision:0d11be367258bfe14a13ff1afcf43a0bc6aedb45',
+ 'version': 'git_revision:c7b026b3a6a1f877ce46a90c5f761b10e5149891',
},
],
'dep_type': 'cipd',
@@ -1868,6 +1879,28 @@ deps = {
'dep_type': 'cipd',
},
+ 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime': {
+ 'packages': [
+ {
+ 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime',
+ 'version': 'version:2@1.9.22.cr1',
+ },
+ ],
+ 'condition': 'checkout_android',
+ 'dep_type': 'cipd',
+ },
+
+ 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime': {
+ 'packages': [
+ {
+ 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime',
+ 'version': 'version:2@1.9.22.cr1',
+ },
+ ],
+ 'condition': 'checkout_android',
+ 'dep_type': 'cipd',
+ },
+
'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7': {
'packages': [
{
@@ -1890,6 +1923,17 @@ deps = {
'dep_type': 'cipd',
},
+ 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm': {
+ 'packages': [
+ {
+ 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm',
+ 'version': 'version:2@0.23.2.cr1',
+ },
+ ],
+ 'condition': 'checkout_android',
+ 'dep_type': 'cipd',
+ },
+
'src/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android': {
'packages': [
{
diff --git a/third_party/libwebrtc/README.moz-ff-commit b/third_party/libwebrtc/README.moz-ff-commit
index 92e573e293..d099892121 100644
--- a/third_party/libwebrtc/README.moz-ff-commit
+++ b/third_party/libwebrtc/README.moz-ff-commit
@@ -28536,3 +28536,513 @@ be2786cd23
# MOZ_LIBWEBRTC_SRC=/Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
# base of lastest vendoring
6b419a0536
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+25b29829dd
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+eb76f193f3
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+340d6c0236
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c708c00f95
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1b61c7161e
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+44e4453067
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+5372bcec52
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+a8375bb973
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+b7e8a10fe4
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c13a7f9a00
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+de3c726121
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c3624d02d0
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+cc70a6d174
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+e3a4bdb46f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+a310d78662
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+ac58a334f7
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+0817380a56
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+7f8470aeee
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+6a3bbefd58
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+523eff622e
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+d213dd5517
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9a953b28f9
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9c166e064f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+979b6d62a8
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1dccfeb395
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9c6874607a
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+698b4e7087
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+0c4165e667
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+89db1c5827
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+98db63cfb6
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+6adf2243b5
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+f43e8ebab9
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+7aa797244d
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+62cee88e4b
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+68e85b8d0d
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+05a6f3b425
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+765024e67b
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+59f3b35013
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+056782c4b5
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+cc83e32cdb
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c6675ed967
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+365cf14407
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+958c9ac546
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c4dd03dfcb
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+3cbe63eac1
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+7cb4ce0079
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c0741e9f12
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+14b016fbf9
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9b7f3649af
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+26ad5b82ce
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1d3e286c7f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+4860148c51
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+27a452da21
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+657b65fa18
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+d071dc1725
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+2c169aef97
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+89cf26f1e0
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c1cc6a36b2
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+b5f2b17fd8
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+53e41a2bc6
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+687ef0a136
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9d653660e9
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+f19c7caeb5
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+8c371f2a9b
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+707296a068
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+2212f86b5a
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+bda5cc63ce
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+35fe95802d
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+f6ae657b07
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+ff616269f8
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+0358a2c7a5
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+5b90b963de
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+5ff04d1b60
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1df269099f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+57a1232d75
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+559e854da4
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1188d0849f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+26540f6071
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+310c9d4cbe
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+8bb54c1c42
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+0a92fe8b61
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+f0895f7733
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+72fdb65330
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+5c7bc9fa02
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+6de9d6add0
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9d9b3a3553
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+3bddaed569
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+4eb72a0867
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+2425c8ddea
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+22b6564d77
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+39ac25d6ec
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+aaa123debb
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+dc769ae509
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+fe6178ef7d
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+76817070d3
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+5e04753e7a
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+74e7ac59b0
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+68831d28c7
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+3e613c2590
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+cea1c0b9a9
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+974044efca
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+6432970fe9
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9183fcdc53
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+955839cf5a
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+bc2593ebc6
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1d35f76e42
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+dcd1ce2325
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+5ba4f2ab58
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+15062c8739
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+61b1f53a4c
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+3f3f991c03
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9d4961e596
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+d49058e702
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+951372774b
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+32f2a30e5e
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+25cdac7d7e
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+541f202354
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+52fec7d3e9
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+407367d053
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1b5f47f2d3
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+24ad911210
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+cd81d55fec
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1cce1d7ddc
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+e3fb8122aa
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+521b8632b6
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+9a75ae1255
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+764b8ae655
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+e28e60c740
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1e7a6f3b6a
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+e5cd905b9e
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+14d7d2d845
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+d99fb2f6ff
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+495e23e60f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+94c3328b61
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+2bd4129e91
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+7a6a8ebf23
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+050ffefd85
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+7fc9535d8b
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+23c32da48a
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+414c94290a
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+3e9e4e7c9c
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+4efc830e53
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+a2655449ee
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+f7b22c66ff
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+b158537a4f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+611f21d0d4
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+6a8236617d
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+45242adc4c
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+2eee89e904
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+ce1271af8f
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+46364195d3
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+7e0bd7aaaf
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+62cbdcea05
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+6596134fad
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+1b52d5641e
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+85b405b798
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+8bfc3e99a6
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+54d9cd002c
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+052bc3af92
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+600503ae26
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+0ba663c245
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c49da7a58b
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+2bfb5db548
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+d99da2c5f8
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+a75459d122
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+bde80e3c0e
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+0355f455a4
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+c026167f59
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+45e49ef537
+# MOZ_LIBWEBRTC_SRC=/Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
+# base of lastest vendoring
+41b1493ddb
diff --git a/third_party/libwebrtc/README.mozilla b/third_party/libwebrtc/README.mozilla
index 5c7f6efb78..f1b272f77f 100644
--- a/third_party/libwebrtc/README.mozilla
+++ b/third_party/libwebrtc/README.mozilla
@@ -19048,3 +19048,343 @@ libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc co
libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-03-16T18:53:57.098291.
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-03-16T18:55:14.637807.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T18:57:03.025915.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T18:58:21.664126.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T18:59:41.799938.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:01:05.779869.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:33:19.100723.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:35:17.344199.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:36:36.336625.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:38:36.947117.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:39:53.400612.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:41:10.322109.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:42:28.021389.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:43:51.241448.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:45:12.410693.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:46:34.942042.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:47:52.228855.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:49:54.179011.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:51:49.226149.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:53:20.059128.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:54:40.193725.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:56:07.109459.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:57:28.027654.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T19:59:36.032228.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:01:42.092961.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:30:41.783887.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:32:22.780075.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:33:46.240912.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:35:59.143300.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:37:23.341469.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:38:47.571822.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:40:08.247186.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:41:40.949224.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:43:18.024698.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:45:32.507851.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:47:22.725467.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:49:20.250713.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:50:53.283376.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:52:14.005210.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:53:35.306273.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:55:05.673775.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:57:07.926494.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T20:58:36.253947.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T21:00:09.599294.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T21:01:44.296536.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T21:03:18.020690.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T21:59:07.213391.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:00:38.941544.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:02:02.813982.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:03:36.002921.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:05:46.926634.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:07:10.970910.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:08:27.030498.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:09:41.787720.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:10:57.153455.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:12:10.878834.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:13:28.071804.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:15:24.062388.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:16:42.986457.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:18:12.681300.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T22:36:33.250348.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:09:04.392191.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:10:18.649463.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:26:33.855380.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:27:48.882496.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:45:24.755554.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:46:40.000033.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:48:01.008085.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:49:17.546707.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:50:30.883376.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:51:51.495220.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-03T23:53:06.900046.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T00:06:21.977348.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T00:07:37.630480.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T00:24:38.990621.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T00:43:38.927753.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T00:44:53.748364.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T01:01:11.349330.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T01:02:31.237022.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T01:19:04.752570.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T01:20:20.378573.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T01:37:30.245727.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T01:54:55.998080.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T02:13:09.257237.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T02:14:25.019460.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T02:31:17.186888.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T02:47:51.997147.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T03:04:30.059077.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T03:22:00.978944.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T03:39:56.828125.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T03:58:23.990648.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T04:02:07.098300.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T04:36:27.231099.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:40:46.539958.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:50:12.952189.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:51:30.186430.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:52:50.052759.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:54:08.848343.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:55:26.182165.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:56:44.382662.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:58:04.520451.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T06:59:23.753554.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:00:39.929808.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:02:54.267570.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:04:31.735805.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:06:06.642405.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:07:39.335516.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:09:07.549126.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:10:34.857747.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:12:01.650318.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:14:22.731124.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:15:53.328195.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:18:22.399329.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:19:57.623992.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:21:26.412052.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:22:51.598040.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:24:17.917164.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:26:37.356373.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T07:28:10.748849.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:11:56.104814.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:13:22.841548.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:14:50.848630.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:16:55.122455.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:18:20.115351.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:19:41.005812.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:21:06.953358.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:22:27.309802.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:23:46.030200.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:25:07.227063.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:26:29.499553.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:27:49.704542.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:29:20.877927.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:30:41.690934.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:32:05.086813.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:33:28.264737.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:34:52.038397.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:37:01.663272.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:39:07.783362.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:40:28.989852.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:41:54.742373.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:43:19.163364.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T08:44:44.144100.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:31:48.802623.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:33:09.285864.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:35:24.601913.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:36:40.617099.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:38:53.271014.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:41:09.999876.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:42:26.325351.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:43:51.200876.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:45:11.848093.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:46:25.191980.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:47:46.232795.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:49:59.647433.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:52:13.597185.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:53:36.033999.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:54:57.387871.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:56:15.101548.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:57:29.044531.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:58:41.095787.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T11:59:55.678531.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:01:21.950431.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:02:36.208538.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:03:57.200737.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:05:17.055053.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:06:40.182816.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:08:44.989126.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:09:59.151311.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:11:16.117006.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:12:29.071526.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:13:47.742363.
+# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
+libwebrtc updated from /Users/apehrson/Dev/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-04-04T12:15:04.987435.
diff --git a/third_party/libwebrtc/api/BUILD.gn b/third_party/libwebrtc/api/BUILD.gn
index 1628660c3c..4549c02b7a 100644
--- a/third_party/libwebrtc/api/BUILD.gn
+++ b/third_party/libwebrtc/api/BUILD.gn
@@ -301,7 +301,6 @@ if (!build_with_mozilla) {
visibility = [ "*" ]
cflags = []
sources = [
- "crypto_params.h",
"data_channel_interface.cc",
"data_channel_interface.h",
"jsep.cc",
@@ -361,6 +360,8 @@ if (!build_with_mozilla) {
":sequence_checker",
":turn_customizer",
"../call:rtp_interfaces",
+ "../p2p:connection",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
"../pc:media_factory",
"../rtc_base:copy_on_write_buffer",
@@ -380,6 +381,7 @@ if (!build_with_mozilla) {
"neteq:neteq_api",
"rtc_event_log",
"task_queue",
+ "transport:bandwidth_estimation_settings",
"transport:bitrate_settings",
"transport:enums",
"transport:network_control",
@@ -806,7 +808,6 @@ rtc_source_set("rtc_stats_api") {
"stats/attribute.h",
"stats/rtc_stats.h",
"stats/rtc_stats_collector_callback.h",
- "stats/rtc_stats_member.h",
"stats/rtc_stats_report.h",
"stats/rtcstats_objects.h",
]
@@ -969,6 +970,11 @@ rtc_library("ice_transport_factory") {
":make_ref_counted",
":packet_socket_factory",
":scoped_refptr",
+ "../p2p:connection",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:p2p_transport_channel",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
"../rtc_base:threading",
"../rtc_base/system:rtc_export",
@@ -1181,6 +1187,16 @@ if (rtc_include_tests) {
]
}
+ rtc_library("mock_frame_transformer") {
+ visibility = [ "*" ]
+ testonly = true
+ sources = [ "test/mock_frame_transformer.h" ]
+ deps = [
+ ":frame_transformer_interface",
+ "../test:test_support",
+ ]
+ }
+
rtc_library("mock_encoder_selector") {
visibility = [ "*" ]
testonly = true
@@ -1379,6 +1395,7 @@ if (rtc_include_tests) {
deps = [
"../api/video_codecs:video_codecs_api",
"../test:test_support",
+ "environment",
]
}
@@ -1447,6 +1464,7 @@ if (rtc_include_tests) {
sources = [
"array_view_unittest.cc",
+ "candidate_unittest.cc",
"field_trials_unittest.cc",
"function_view_unittest.cc",
"rtc_error_unittest.cc",
@@ -1462,6 +1480,7 @@ if (rtc_include_tests) {
deps = [
":array_view",
+ ":candidate",
":create_time_controller",
":field_trials",
":field_trials_view",
@@ -1475,12 +1494,14 @@ if (rtc_include_tests) {
":scoped_refptr",
":sequence_checker",
":time_controller",
+ "../p2p:rtc_p2p",
"../rtc_base:buffer",
"../rtc_base:checks",
"../rtc_base:gunit_helpers",
"../rtc_base:platform_thread",
"../rtc_base:rtc_event",
"../rtc_base:rtc_task_queue",
+ "../rtc_base:ssl",
"../rtc_base:task_queue_for_test",
"../rtc_base/containers:flat_set",
"../rtc_base/task_utils:repeating_task",
diff --git a/third_party/libwebrtc/api/audio_codecs/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/BUILD.gn
index 2719942488..fc02b2d834 100644
--- a/third_party/libwebrtc/api/audio_codecs/BUILD.gn
+++ b/third_party/libwebrtc/api/audio_codecs/BUILD.gn
@@ -42,6 +42,7 @@ rtc_library("audio_codecs_api") {
"../../rtc_base:refcount",
"../../rtc_base:sanitizer",
"../../rtc_base/system:rtc_export",
+ "../units:data_rate",
"../units:time_delta",
]
absl_deps = [
diff --git a/third_party/libwebrtc/api/audio_codecs/audio_encoder.h b/third_party/libwebrtc/api/audio_codecs/audio_encoder.h
index 7f5a34214f..7b5ee7a866 100644
--- a/third_party/libwebrtc/api/audio_codecs/audio_encoder.h
+++ b/third_party/libwebrtc/api/audio_codecs/audio_encoder.h
@@ -20,6 +20,7 @@
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/call/bitrate_allocation.h"
+#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "rtc_base/buffer.h"
@@ -240,12 +241,20 @@ class AudioEncoder {
// Get statistics related to audio network adaptation.
virtual ANAStats GetANAStats() const;
- // The range of frame lengths that are supported or nullopt if there's no sch
- // information. This is used to calculated the full bitrate range, including
- // overhead.
+ // The range of frame lengths that are supported or nullopt if there's no such
+ // information. This is used together with the bitrate range to calculate the
+ // full bitrate range, including overhead.
virtual absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
const = 0;
+ // The range of payload bitrates that are supported. This is used together
+ // with the frame length range to calculate the full bitrate range, including
+ // overhead.
+ virtual absl::optional<std::pair<DataRate, DataRate>> GetBitrateRange()
+ const {
+ return absl::nullopt;
+ }
+
// The maximum number of audio channels supported by WebRTC encoders.
static constexpr int kMaxNumberOfChannels = 24;
diff --git a/third_party/libwebrtc/api/candidate.cc b/third_party/libwebrtc/api/candidate.cc
index 865f8e5787..7718f94076 100644
--- a/third_party/libwebrtc/api/candidate.cc
+++ b/third_party/libwebrtc/api/candidate.cc
@@ -10,6 +10,7 @@
#include "api/candidate.h"
+#include "absl/base/attributes.h"
#include "rtc_base/helpers.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/logging.h"
@@ -17,15 +18,16 @@
namespace cricket {
-const char LOCAL_PORT_TYPE[] = "local";
-const char STUN_PORT_TYPE[] = "stun";
-const char PRFLX_PORT_TYPE[] = "prflx";
-const char RELAY_PORT_TYPE[] = "relay";
+ABSL_CONST_INIT const absl::string_view LOCAL_PORT_TYPE = "local";
+ABSL_CONST_INIT const absl::string_view STUN_PORT_TYPE = "stun";
+ABSL_CONST_INIT const absl::string_view PRFLX_PORT_TYPE = "prflx";
+ABSL_CONST_INIT const absl::string_view RELAY_PORT_TYPE = "relay";
Candidate::Candidate()
: id_(rtc::CreateRandomString(8)),
component_(0),
priority_(0),
+ type_(LOCAL_PORT_TYPE),
network_type_(rtc::ADAPTER_TYPE_UNKNOWN),
underlying_type_for_vpn_(rtc::ADAPTER_TYPE_UNKNOWN),
generation_(0),
@@ -62,6 +64,10 @@ Candidate::Candidate(const Candidate&) = default;
Candidate::~Candidate() = default;
+void Candidate::generate_id() {
+ id_ = rtc::CreateRandomString(8);
+}
+
bool Candidate::is_local() const {
return type_ == LOCAL_PORT_TYPE;
}
@@ -75,6 +81,17 @@ bool Candidate::is_relay() const {
return type_ == RELAY_PORT_TYPE;
}
+absl::string_view Candidate::type_name() const {
+ // The LOCAL_PORT_TYPE and STUN_PORT_TYPE constants are not the standard type
+ // names, so check for those specifically. For other types, `type_` will have
+ // the correct name.
+ if (is_local())
+ return "host";
+ if (is_stun())
+ return "srflx";
+ return type_;
+}
+
bool Candidate::IsEquivalent(const Candidate& c) const {
// We ignore the network name, since that is just debug information, and
// the priority and the network cost, since they should be the same if the
@@ -99,9 +116,10 @@ std::string Candidate::ToStringInternal(bool sensitive) const {
std::string related_address = sensitive ? related_address_.ToSensitiveString()
: related_address_.ToString();
ost << "Cand[" << transport_name_ << ":" << foundation_ << ":" << component_
- << ":" << protocol_ << ":" << priority_ << ":" << address << ":" << type_
- << ":" << related_address << ":" << username_ << ":" << password_ << ":"
- << network_id_ << ":" << network_cost_ << ":" << generation_ << "]";
+ << ":" << protocol_ << ":" << priority_ << ":" << address << ":"
+ << type_name() << ":" << related_address << ":" << username_ << ":"
+ << password_ << ":" << network_id_ << ":" << network_cost_ << ":"
+ << generation_ << "]";
return ost.Release();
}
diff --git a/third_party/libwebrtc/api/candidate.h b/third_party/libwebrtc/api/candidate.h
index d48f4fc559..0aa75aa192 100644
--- a/third_party/libwebrtc/api/candidate.h
+++ b/third_party/libwebrtc/api/candidate.h
@@ -24,14 +24,18 @@
#include "rtc_base/socket_address.h"
#include "rtc_base/system/rtc_export.h"
+namespace webrtc {
+enum class IceCandidateType : int { kHost, kSrflx, kPrflx, kRelay };
+} // namespace webrtc
+
namespace cricket {
// TODO(tommi): These are temporarily here, moved from `port.h` and will
// eventually be removed once we use enums instead of strings for these values.
-RTC_EXPORT extern const char LOCAL_PORT_TYPE[];
-RTC_EXPORT extern const char STUN_PORT_TYPE[];
-RTC_EXPORT extern const char PRFLX_PORT_TYPE[];
-RTC_EXPORT extern const char RELAY_PORT_TYPE[];
+RTC_EXPORT extern const absl::string_view LOCAL_PORT_TYPE;
+RTC_EXPORT extern const absl::string_view STUN_PORT_TYPE;
+RTC_EXPORT extern const absl::string_view PRFLX_PORT_TYPE;
+RTC_EXPORT extern const absl::string_view RELAY_PORT_TYPE;
// TURN servers are limited to 32 in accordance with
// https://w3c.github.io/webrtc-pc/#dom-rtcconfiguration-iceservers
@@ -59,8 +63,12 @@ class RTC_EXPORT Candidate {
Candidate(const Candidate&);
~Candidate();
+ // 8 character long randomized ID string for logging purposes.
const std::string& id() const { return id_; }
- void set_id(absl::string_view id) { Assign(id_, id); }
+ // Generates a new, 8 character long, id.
+ void generate_id();
+ // TODO(tommi): Callers should use generate_id(). Remove.
+ [[deprecated]] void set_id(absl::string_view id) { Assign(id_, id); }
int component() const { return component_; }
void set_component(int component) { component_ = component; }
@@ -89,6 +97,10 @@ class RTC_EXPORT Candidate {
const std::string& type() const { return type_; }
+ // Returns the name of the candidate type as specified in
+ // https://datatracker.ietf.org/doc/html/rfc5245#section-15.1
+ absl::string_view type_name() const;
+
// Setting the type requires a constant string (e.g.
// cricket::LOCAL_PORT_TYPE). The type should really be an enum rather than a
// string, but until we make that change the lifetime attribute helps us lock
diff --git a/third_party/libwebrtc/api/candidate_unittest.cc b/third_party/libwebrtc/api/candidate_unittest.cc
new file mode 100644
index 0000000000..e52d448e72
--- /dev/null
+++ b/third_party/libwebrtc/api/candidate_unittest.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2024 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/candidate.h"
+
+#include <string>
+
+#include "p2p/base/p2p_constants.h"
+#include "rtc_base/gunit.h"
+
+namespace cricket {
+
+TEST(CandidateTest, Id) {
+ Candidate c;
+ EXPECT_EQ(c.id().size(), 8u);
+ std::string current_id = c.id();
+ // Generate a new ID.
+ c.generate_id();
+ EXPECT_EQ(c.id().size(), 8u);
+ EXPECT_NE(current_id, c.id());
+}
+
+TEST(CandidateTest, Component) {
+ Candidate c;
+ EXPECT_EQ(c.component(), 0);
+ c.set_component(ICE_CANDIDATE_COMPONENT_DEFAULT);
+ EXPECT_EQ(c.component(), ICE_CANDIDATE_COMPONENT_DEFAULT);
+}
+
+TEST(CandidateTest, TypeName) {
+ Candidate c;
+ // The `type_name()` property defaults to "host".
+ EXPECT_EQ(c.type_name(), "host");
+ EXPECT_EQ(c.type(), LOCAL_PORT_TYPE);
+
+ c.set_type(STUN_PORT_TYPE);
+ EXPECT_EQ(c.type_name(), "srflx");
+ EXPECT_EQ(c.type(), STUN_PORT_TYPE);
+
+ c.set_type(PRFLX_PORT_TYPE);
+ EXPECT_EQ(c.type_name(), "prflx");
+ EXPECT_EQ(c.type(), PRFLX_PORT_TYPE);
+
+ c.set_type(RELAY_PORT_TYPE);
+ EXPECT_EQ(c.type_name(), "relay");
+ EXPECT_EQ(c.type(), RELAY_PORT_TYPE);
+}
+
+} // namespace cricket
diff --git a/third_party/libwebrtc/api/crypto_params.h b/third_party/libwebrtc/api/crypto_params.h
deleted file mode 100644
index 34906ea0ef..0000000000
--- a/third_party/libwebrtc/api/crypto_params.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef API_CRYPTO_PARAMS_H_
-#define API_CRYPTO_PARAMS_H_
-
-#include <string>
-
-#include "absl/strings/string_view.h"
-
-namespace cricket {
-
-// Parameters for SRTP negotiation, as described in RFC 4568.
-// TODO(benwright) - Rename to SrtpCryptoParams as these only apply to SRTP and
-// not generic crypto parameters for WebRTC.
-struct CryptoParams {
- CryptoParams() : tag(0) {}
- CryptoParams(int t,
- absl::string_view cs,
- absl::string_view kp,
- absl::string_view sp)
- : tag(t), crypto_suite(cs), key_params(kp), session_params(sp) {}
-
- bool Matches(const CryptoParams& params) const {
- return (tag == params.tag && crypto_suite == params.crypto_suite);
- }
-
- int tag;
- std::string crypto_suite;
- std::string key_params;
- std::string session_params;
-};
-
-} // namespace cricket
-
-#endif // API_CRYPTO_PARAMS_H_
diff --git a/third_party/libwebrtc/api/frame_transformer_interface.h b/third_party/libwebrtc/api/frame_transformer_interface.h
index afa79b92ea..4869ad6909 100644
--- a/third_party/libwebrtc/api/frame_transformer_interface.h
+++ b/third_party/libwebrtc/api/frame_transformer_interface.h
@@ -74,11 +74,7 @@ class TransformableAudioFrameInterface : public TransformableFrameInterface {
virtual rtc::ArrayView<const uint32_t> GetContributingSources() const = 0;
- // TODO(crbug.com/1453226): Change this to pure virtual after it
- // is implemented everywhere.
- virtual const absl::optional<uint16_t> SequenceNumber() const {
- return absl::nullopt;
- }
+ virtual const absl::optional<uint16_t> SequenceNumber() const = 0;
virtual absl::optional<uint64_t> AbsoluteCaptureTimestamp() const = 0;
diff --git a/third_party/libwebrtc/api/neteq/neteq.cc b/third_party/libwebrtc/api/neteq/neteq.cc
index 155ddf2cf3..d237def23a 100644
--- a/third_party/libwebrtc/api/neteq/neteq.cc
+++ b/third_party/libwebrtc/api/neteq/neteq.cc
@@ -24,8 +24,7 @@ NetEq::Config& NetEq::Config::operator=(Config&&) = default;
std::string NetEq::Config::ToString() const {
char buf[1024];
rtc::SimpleStringBuilder ss(buf);
- ss << "sample_rate_hz=" << sample_rate_hz << ", enable_post_decode_vad="
- << (enable_post_decode_vad ? "true" : "false")
+ ss << "sample_rate_hz=" << sample_rate_hz
<< ", max_packets_in_buffer=" << max_packets_in_buffer
<< ", min_delay_ms=" << min_delay_ms << ", enable_fast_accelerate="
<< (enable_fast_accelerate ? "true" : "false")
diff --git a/third_party/libwebrtc/api/neteq/neteq.h b/third_party/libwebrtc/api/neteq/neteq.h
index 43e0e09784..3dfe662741 100644
--- a/third_party/libwebrtc/api/neteq/neteq.h
+++ b/third_party/libwebrtc/api/neteq/neteq.h
@@ -130,7 +130,6 @@ class NetEq {
std::string ToString() const;
int sample_rate_hz = 48000; // Initial value. Will change with input data.
- bool enable_post_decode_vad = false;
size_t max_packets_in_buffer = 200;
int max_delay_ms = 0;
int min_delay_ms = 0;
@@ -197,18 +196,17 @@ class NetEq {
// Instructs NetEq to deliver 10 ms of audio data. The data is written to
// `audio_frame`. All data in `audio_frame` is wiped; `data_`, `speech_type_`,
- // `num_channels_`, `sample_rate_hz_`, `samples_per_channel_`, and
- // `vad_activity_` are updated upon success. If an error is returned, some
- // fields may not have been updated, or may contain inconsistent values.
- // If muted state is enabled (through Config::enable_muted_state), `muted`
- // may be set to true after a prolonged expand period. When this happens, the
- // `data_` in `audio_frame` is not written, but should be interpreted as being
- // all zeros. For testing purposes, an override can be supplied in the
- // `action_override` argument, which will cause NetEq to take this action
- // next, instead of the action it would normally choose. An optional output
- // argument for fetching the current sample rate can be provided, which
- // will return the same value as last_output_sample_rate_hz() but will avoid
- // additional synchronization.
+ // `num_channels_`, `sample_rate_hz_` and `samples_per_channel_` are updated
+ // upon success. If an error is returned, some fields may not have been
+ // updated, or may contain inconsistent values. If muted state is enabled
+ // (through Config::enable_muted_state), `muted` may be set to true after a
+ // prolonged expand period. When this happens, the `data_` in `audio_frame`
+ // is not written, but should be interpreted as being all zeros. For testing
+ // purposes, an override can be supplied in the `action_override` argument,
+ // which will cause NetEq to take this action next, instead of the action it
+ // would normally choose. An optional output argument for fetching the current
+ // sample rate can be provided, which will return the same value as
+ // last_output_sample_rate_hz() but will avoid additional synchronization.
// Returns kOK on success, or kFail in case of an error.
virtual int GetAudio(
AudioFrame* audio_frame,
@@ -278,13 +276,6 @@ class NetEq {
// statistics are never reset.
virtual NetEqOperationsAndState GetOperationsAndState() const = 0;
- // Enables post-decode VAD. When enabled, GetAudio() will return
- // kOutputVADPassive when the signal contains no speech.
- virtual void EnableVad() = 0;
-
- // Disables post-decode VAD.
- virtual void DisableVad() = 0;
-
// Returns the RTP timestamp for the last sample delivered by GetAudio().
// The return value will be empty if no valid timestamp is available.
virtual absl::optional<uint32_t> GetPlayoutTimestamp() const = 0;
diff --git a/third_party/libwebrtc/api/peer_connection_interface.h b/third_party/libwebrtc/api/peer_connection_interface.h
index 3c225eb28a..38699ec98a 100644
--- a/third_party/libwebrtc/api/peer_connection_interface.h
+++ b/third_party/libwebrtc/api/peer_connection_interface.h
@@ -112,6 +112,7 @@
#include "api/set_remote_description_observer_interface.h"
#include "api/stats/rtc_stats_collector_callback.h"
#include "api/task_queue/task_queue_factory.h"
+#include "api/transport/bandwidth_estimation_settings.h"
#include "api/transport/bitrate_settings.h"
#include "api/transport/enums.h"
#include "api/transport/network_control.h"
@@ -451,15 +452,6 @@ class RTC_EXPORT PeerConnectionInterface : public webrtc::RefCountInterface {
// when switching from a static scene to one with motion.
absl::optional<int> screencast_min_bitrate;
-#if defined(WEBRTC_FUCHSIA)
- // TODO(bugs.webrtc.org/11066): Remove entirely once Fuchsia does not use.
- // TODO(bugs.webrtc.org/9891) - Move to crypto_options
- // Can be used to disable DTLS-SRTP. This should never be done, but can be
- // useful for testing purposes, for example in setting up a loopback call
- // with a single PeerConnection.
- absl::optional<bool> enable_dtls_srtp;
-#endif
-
/////////////////////////////////////////////////
// The below fields are not part of the standard.
/////////////////////////////////////////////////
@@ -1142,6 +1134,13 @@ class RTC_EXPORT PeerConnectionInterface : public webrtc::RefCountInterface {
// to the provided value.
virtual RTCError SetBitrate(const BitrateSettings& bitrate) = 0;
+ // Allows an application to reconfigure bandwidth estimation.
+ // The method can be called both before and after estimation has started.
+ // Estimation starts when the first RTP packet is sent.
+ // Estimation will be restarted if already started.
+ virtual void ReconfigureBandwidthEstimation(
+ const BandwidthEstimationSettings& settings) {}
+
// Enable/disable playout of received audio streams. Enabled by default. Note
// that even if playout is enabled, streams will only be played out if the
// appropriate SDP is also applied. Setting `playout` to false will stop
diff --git a/third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc b/third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc
index 0aff57fbbc..d2f1e1c6b5 100644
--- a/third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc
+++ b/third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc
@@ -34,7 +34,8 @@ class RtcEventLogOutputFileTest : public ::testing::Test {
protected:
std::string GetOutputFilePath() const {
auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
- return test::OutputPath() + test_info->test_case_name() + test_info->name();
+ return test::OutputPathWithRandomDirectory() + test_info->test_case_name() +
+ test_info->name();
}
std::string GetOutputFileContents() const {
diff --git a/third_party/libwebrtc/api/stats/attribute.h b/third_party/libwebrtc/api/stats/attribute.h
index 09211f469c..36500db999 100644
--- a/third_party/libwebrtc/api/stats/attribute.h
+++ b/third_party/libwebrtc/api/stats/attribute.h
@@ -16,37 +16,38 @@
#include <string>
#include <vector>
+#include "absl/types/optional.h"
#include "absl/types/variant.h"
-#include "api/stats/rtc_stats_member.h"
+#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
-// A light-weight wrapper of an RTCStats attribute (an individual metric).
+// A light-weight wrapper of an RTCStats attribute, i.e. an individual metric of
+// type absl::optional<T>.
class RTC_EXPORT Attribute {
public:
- // TODO(https://crbug.com/webrtc/15164): Replace uses of RTCStatsMember<T>
- // with absl::optional<T> and update these pointer types.
- typedef absl::variant<const RTCStatsMember<bool>*,
- const RTCStatsMember<int32_t>*,
- const RTCStatsMember<uint32_t>*,
- const RTCStatsMember<int64_t>*,
- const RTCStatsMember<uint64_t>*,
- const RTCStatsMember<double>*,
- const RTCStatsMember<std::string>*,
- const RTCStatsMember<std::vector<bool>>*,
- const RTCStatsMember<std::vector<int32_t>>*,
- const RTCStatsMember<std::vector<uint32_t>>*,
- const RTCStatsMember<std::vector<int64_t>>*,
- const RTCStatsMember<std::vector<uint64_t>>*,
- const RTCStatsMember<std::vector<double>>*,
- const RTCStatsMember<std::vector<std::string>>*,
- const RTCStatsMember<std::map<std::string, uint64_t>>*,
- const RTCStatsMember<std::map<std::string, double>>*>
+ // All supported attribute types.
+ typedef absl::variant<const absl::optional<bool>*,
+ const absl::optional<int32_t>*,
+ const absl::optional<uint32_t>*,
+ const absl::optional<int64_t>*,
+ const absl::optional<uint64_t>*,
+ const absl::optional<double>*,
+ const absl::optional<std::string>*,
+ const absl::optional<std::vector<bool>>*,
+ const absl::optional<std::vector<int32_t>>*,
+ const absl::optional<std::vector<uint32_t>>*,
+ const absl::optional<std::vector<int64_t>>*,
+ const absl::optional<std::vector<uint64_t>>*,
+ const absl::optional<std::vector<double>>*,
+ const absl::optional<std::vector<std::string>>*,
+ const absl::optional<std::map<std::string, uint64_t>>*,
+ const absl::optional<std::map<std::string, double>>*>
StatVariant;
template <typename T>
- explicit Attribute(const char* name, const RTCStatsMember<T>* attribute)
+ Attribute(const char* name, const absl::optional<T>* attribute)
: name_(name), attribute_(attribute) {}
const char* name() const;
@@ -55,21 +56,18 @@ class RTC_EXPORT Attribute {
bool has_value() const;
template <typename T>
bool holds_alternative() const {
- return absl::holds_alternative<const RTCStatsMember<T>*>(attribute_);
+ return absl::holds_alternative<const absl::optional<T>*>(attribute_);
}
template <typename T>
- absl::optional<T> as_optional() const {
+ const absl::optional<T>& as_optional() const {
RTC_CHECK(holds_alternative<T>());
- if (!has_value()) {
- return absl::nullopt;
- }
- return absl::optional<T>(get<T>());
+ return *absl::get<const absl::optional<T>*>(attribute_);
}
template <typename T>
const T& get() const {
RTC_CHECK(holds_alternative<T>());
RTC_CHECK(has_value());
- return absl::get<const RTCStatsMember<T>*>(attribute_)->value();
+ return absl::get<const absl::optional<T>*>(attribute_)->value();
}
bool is_sequence() const;
diff --git a/third_party/libwebrtc/api/stats/rtc_stats.h b/third_party/libwebrtc/api/stats/rtc_stats.h
index edd293f5c9..74e7fc4d8e 100644
--- a/third_party/libwebrtc/api/stats/rtc_stats.h
+++ b/third_party/libwebrtc/api/stats/rtc_stats.h
@@ -20,8 +20,8 @@
#include <utility>
#include <vector>
+#include "absl/types/optional.h"
#include "api/stats/attribute.h"
-#include "api/stats/rtc_stats_member.h"
#include "api/units/timestamp.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
@@ -39,8 +39,8 @@ namespace webrtc {
// Use the `WEBRTC_RTCSTATS_IMPL` macro when implementing subclasses, see macro
// for details.
//
-// Derived classes list their dictionary attributes (RTCStatsMember<T> to soon
-// be replaced by absl::optional<T>) as public fields, allowing the following:
+// Derived classes list their dictionary attributes, absl::optional<T>, as
+// public fields, allowing the following:
//
// RTCFooStats foo("fooId", Timestamp::Micros(GetCurrentTime()));
// foo.bar = 42;
@@ -52,7 +52,7 @@ namespace webrtc {
// iteration:
//
// for (const auto& attribute : foo.Attributes()) {
-// printf("%s = %s\n", attribute.name(), attribute.ValueToString().c_str());
+// printf("%s = %s\n", attribute.name(), attribute.ToString().c_str());
// }
class RTC_EXPORT RTCStats {
public:
@@ -73,12 +73,12 @@ class RTC_EXPORT RTCStats {
// metrics as viewed via the Attribute wrapper.
std::vector<Attribute> Attributes() const;
template <typename T>
- Attribute GetAttribute(const RTCStatsMember<T>& stat) const {
+ Attribute GetAttribute(const absl::optional<T>& stat) const {
for (const auto& attribute : Attributes()) {
if (!attribute.holds_alternative<T>()) {
continue;
}
- if (absl::get<const RTCStatsMember<T>*>(attribute.as_variant()) ==
+ if (absl::get<const absl::optional<T>*>(attribute.as_variant()) ==
&stat) {
return attribute;
}
@@ -136,8 +136,8 @@ class RTC_EXPORT RTCStats {
//
// RTCFooStats(const std::string& id, Timestamp timestamp);
//
-// RTCStatsMember<int32_t> foo;
-// RTCStatsMember<int32_t> bar;
+// absl::optional<int32_t> foo;
+// absl::optional<int32_t> bar;
// };
//
// rtcfoostats.cc:
diff --git a/third_party/libwebrtc/api/stats/rtc_stats_member.h b/third_party/libwebrtc/api/stats/rtc_stats_member.h
deleted file mode 100644
index 9039569ede..0000000000
--- a/third_party/libwebrtc/api/stats/rtc_stats_member.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2023 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef API_STATS_RTC_STATS_MEMBER_H_
-#define API_STATS_RTC_STATS_MEMBER_H_
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "absl/types/optional.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/system/rtc_export.h"
-#include "rtc_base/system/rtc_export_template.h"
-
-namespace webrtc {
-
-// Interface for `RTCStats` members, which have a name and a value of a type
-// defined in a subclass. Only the types listed in `Type` are supported, these
-// are implemented by `RTCStatsMember<T>`. The value of a member may be
-// undefined, the value can only be read if `is_defined`.
-class RTCStatsMemberInterface {
- public:
- // Member value types.
- enum Type {
- kBool, // bool
- kInt32, // int32_t
- kUint32, // uint32_t
- kInt64, // int64_t
- kUint64, // uint64_t
- kDouble, // double
- kString, // std::string
-
- kSequenceBool, // std::vector<bool>
- kSequenceInt32, // std::vector<int32_t>
- kSequenceUint32, // std::vector<uint32_t>
- kSequenceInt64, // std::vector<int64_t>
- kSequenceUint64, // std::vector<uint64_t>
- kSequenceDouble, // std::vector<double>
- kSequenceString, // std::vector<std::string>
-
- kMapStringUint64, // std::map<std::string, uint64_t>
- kMapStringDouble, // std::map<std::string, double>
- };
-
- virtual ~RTCStatsMemberInterface() {}
-
- virtual Type type() const = 0;
- virtual bool is_sequence() const = 0;
- virtual bool is_string() const = 0;
- virtual bool has_value() const = 0;
- // Type and value comparator. The names are not compared. These operators are
- // exposed for testing.
- bool operator==(const RTCStatsMemberInterface& other) const {
- return IsEqual(other);
- }
- bool operator!=(const RTCStatsMemberInterface& other) const {
- return !(*this == other);
- }
-
- virtual const RTCStatsMemberInterface* member_ptr() const { return this; }
- template <typename T>
- const T& cast_to() const {
- RTC_DCHECK_EQ(type(), T::StaticType());
- return static_cast<const T&>(*member_ptr());
- }
-
- protected:
- virtual bool IsEqual(const RTCStatsMemberInterface& other) const = 0;
-};
-
-// Template implementation of `RTCStatsMemberInterface`.
-// The supported types are the ones described by
-// `RTCStatsMemberInterface::Type`.
-template <typename T>
-class RTCStatsMember : public RTCStatsMemberInterface {
- public:
- RTCStatsMember() {}
- explicit RTCStatsMember(const T& value) : value_(value) {}
-
- static Type StaticType();
- Type type() const override { return StaticType(); }
- bool is_sequence() const override;
- bool is_string() const override;
-
- template <typename U>
- inline T value_or(U default_value) const {
- return value_.value_or(default_value);
- }
- // TODO(https://crbug.com/webrtc/15164): Migrate to value_or() and delete.
- template <typename U>
- inline T ValueOrDefault(U default_value) const {
- return value_or(default_value);
- }
-
- // Assignment operators.
- T& operator=(const T& value) {
- value_ = value;
- return value_.value();
- }
- T& operator=(const T&& value) {
- value_ = std::move(value);
- return value_.value();
- }
-
- // Getter methods that look the same as absl::optional<T>. Please prefer these
- // in order to unblock replacing RTCStatsMember<T> with absl::optional<T> in
- // the future (https://crbug.com/webrtc/15164).
- bool has_value() const override { return value_.has_value(); }
- const T& value() const { return value_.value(); }
- T& value() { return value_.value(); }
- T& operator*() {
- RTC_DCHECK(value_);
- return *value_;
- }
- const T& operator*() const {
- RTC_DCHECK(value_);
- return *value_;
- }
- T* operator->() {
- RTC_DCHECK(value_);
- return &(*value_);
- }
- const T* operator->() const {
- RTC_DCHECK(value_);
- return &(*value_);
- }
-
- bool IsEqual(const RTCStatsMemberInterface& other) const override {
- if (type() != other.type())
- return false;
- const RTCStatsMember<T>& other_t =
- static_cast<const RTCStatsMember<T>&>(other);
- return value_ == other_t.value_;
- }
-
- private:
- absl::optional<T> value_;
-};
-
-namespace rtc_stats_internal {
-
-typedef std::map<std::string, uint64_t> MapStringUint64;
-typedef std::map<std::string, double> MapStringDouble;
-
-} // namespace rtc_stats_internal
-
-#define WEBRTC_DECLARE_RTCSTATSMEMBER(T) \
- template <> \
- RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \
- template <> \
- RTC_EXPORT bool RTCStatsMember<T>::is_sequence() const; \
- template <> \
- RTC_EXPORT bool RTCStatsMember<T>::is_string() const; \
- extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) \
- RTCStatsMember<T>
-
-WEBRTC_DECLARE_RTCSTATSMEMBER(bool);
-WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(uint32_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(int64_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(uint64_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(double);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::string);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<bool>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int32_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint32_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int64_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint64_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<double>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<std::string>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64);
-WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble);
-
-} // namespace webrtc
-
-#endif // API_STATS_RTC_STATS_MEMBER_H_
diff --git a/third_party/libwebrtc/api/stats/rtcstats_objects.h b/third_party/libwebrtc/api/stats/rtcstats_objects.h
index 351c2cbefe..9f51f56cc5 100644
--- a/third_party/libwebrtc/api/stats/rtcstats_objects.h
+++ b/third_party/libwebrtc/api/stats/rtcstats_objects.h
@@ -18,6 +18,7 @@
#include <string>
#include <vector>
+#include "absl/types/optional.h"
#include "api/stats/rtc_stats.h"
#include "rtc_base/system/rtc_export.h"
@@ -30,10 +31,10 @@ class RTC_EXPORT RTCCertificateStats final : public RTCStats {
RTCCertificateStats(std::string id, Timestamp timestamp);
~RTCCertificateStats() override;
- RTCStatsMember<std::string> fingerprint;
- RTCStatsMember<std::string> fingerprint_algorithm;
- RTCStatsMember<std::string> base64_certificate;
- RTCStatsMember<std::string> issuer_certificate_id;
+ absl::optional<std::string> fingerprint;
+ absl::optional<std::string> fingerprint_algorithm;
+ absl::optional<std::string> base64_certificate;
+ absl::optional<std::string> issuer_certificate_id;
};
// https://w3c.github.io/webrtc-stats/#codec-dict*
@@ -43,12 +44,12 @@ class RTC_EXPORT RTCCodecStats final : public RTCStats {
RTCCodecStats(std::string id, Timestamp timestamp);
~RTCCodecStats() override;
- RTCStatsMember<std::string> transport_id;
- RTCStatsMember<uint32_t> payload_type;
- RTCStatsMember<std::string> mime_type;
- RTCStatsMember<uint32_t> clock_rate;
- RTCStatsMember<uint32_t> channels;
- RTCStatsMember<std::string> sdp_fmtp_line;
+ absl::optional<std::string> transport_id;
+ absl::optional<uint32_t> payload_type;
+ absl::optional<std::string> mime_type;
+ absl::optional<uint32_t> clock_rate;
+ absl::optional<uint32_t> channels;
+ absl::optional<std::string> sdp_fmtp_line;
};
// https://w3c.github.io/webrtc-stats/#dcstats-dict*
@@ -58,14 +59,14 @@ class RTC_EXPORT RTCDataChannelStats final : public RTCStats {
RTCDataChannelStats(std::string id, Timestamp timestamp);
~RTCDataChannelStats() override;
- RTCStatsMember<std::string> label;
- RTCStatsMember<std::string> protocol;
- RTCStatsMember<int32_t> data_channel_identifier;
- RTCStatsMember<std::string> state;
- RTCStatsMember<uint32_t> messages_sent;
- RTCStatsMember<uint64_t> bytes_sent;
- RTCStatsMember<uint32_t> messages_received;
- RTCStatsMember<uint64_t> bytes_received;
+ absl::optional<std::string> label;
+ absl::optional<std::string> protocol;
+ absl::optional<int32_t> data_channel_identifier;
+ absl::optional<std::string> state;
+ absl::optional<uint32_t> messages_sent;
+ absl::optional<uint64_t> bytes_sent;
+ absl::optional<uint32_t> messages_received;
+ absl::optional<uint64_t> bytes_received;
};
// https://w3c.github.io/webrtc-stats/#candidatepair-dict*
@@ -75,35 +76,35 @@ class RTC_EXPORT RTCIceCandidatePairStats final : public RTCStats {
RTCIceCandidatePairStats(std::string id, Timestamp timestamp);
~RTCIceCandidatePairStats() override;
- RTCStatsMember<std::string> transport_id;
- RTCStatsMember<std::string> local_candidate_id;
- RTCStatsMember<std::string> remote_candidate_id;
- RTCStatsMember<std::string> state;
+ absl::optional<std::string> transport_id;
+ absl::optional<std::string> local_candidate_id;
+ absl::optional<std::string> remote_candidate_id;
+ absl::optional<std::string> state;
// Obsolete: priority
- RTCStatsMember<uint64_t> priority;
- RTCStatsMember<bool> nominated;
+ absl::optional<uint64_t> priority;
+ absl::optional<bool> nominated;
// `writable` does not exist in the spec and old comments suggest it used to
// exist but was incorrectly implemented.
// TODO(https://crbug.com/webrtc/14171): Standardize and/or modify
// implementation.
- RTCStatsMember<bool> writable;
- RTCStatsMember<uint64_t> packets_sent;
- RTCStatsMember<uint64_t> packets_received;
- RTCStatsMember<uint64_t> bytes_sent;
- RTCStatsMember<uint64_t> bytes_received;
- RTCStatsMember<double> total_round_trip_time;
- RTCStatsMember<double> current_round_trip_time;
- RTCStatsMember<double> available_outgoing_bitrate;
- RTCStatsMember<double> available_incoming_bitrate;
- RTCStatsMember<uint64_t> requests_received;
- RTCStatsMember<uint64_t> requests_sent;
- RTCStatsMember<uint64_t> responses_received;
- RTCStatsMember<uint64_t> responses_sent;
- RTCStatsMember<uint64_t> consent_requests_sent;
- RTCStatsMember<uint64_t> packets_discarded_on_send;
- RTCStatsMember<uint64_t> bytes_discarded_on_send;
- RTCStatsMember<double> last_packet_received_timestamp;
- RTCStatsMember<double> last_packet_sent_timestamp;
+ absl::optional<bool> writable;
+ absl::optional<uint64_t> packets_sent;
+ absl::optional<uint64_t> packets_received;
+ absl::optional<uint64_t> bytes_sent;
+ absl::optional<uint64_t> bytes_received;
+ absl::optional<double> total_round_trip_time;
+ absl::optional<double> current_round_trip_time;
+ absl::optional<double> available_outgoing_bitrate;
+ absl::optional<double> available_incoming_bitrate;
+ absl::optional<uint64_t> requests_received;
+ absl::optional<uint64_t> requests_sent;
+ absl::optional<uint64_t> responses_received;
+ absl::optional<uint64_t> responses_sent;
+ absl::optional<uint64_t> consent_requests_sent;
+ absl::optional<uint64_t> packets_discarded_on_send;
+ absl::optional<uint64_t> bytes_discarded_on_send;
+ absl::optional<double> last_packet_received_timestamp;
+ absl::optional<double> last_packet_sent_timestamp;
};
// https://w3c.github.io/webrtc-stats/#icecandidate-dict*
@@ -112,28 +113,28 @@ class RTC_EXPORT RTCIceCandidateStats : public RTCStats {
WEBRTC_RTCSTATS_DECL();
~RTCIceCandidateStats() override;
- RTCStatsMember<std::string> transport_id;
+ absl::optional<std::string> transport_id;
// Obsolete: is_remote
- RTCStatsMember<bool> is_remote;
- RTCStatsMember<std::string> network_type;
- RTCStatsMember<std::string> ip;
- RTCStatsMember<std::string> address;
- RTCStatsMember<int32_t> port;
- RTCStatsMember<std::string> protocol;
- RTCStatsMember<std::string> relay_protocol;
- RTCStatsMember<std::string> candidate_type;
- RTCStatsMember<int32_t> priority;
- RTCStatsMember<std::string> url;
- RTCStatsMember<std::string> foundation;
- RTCStatsMember<std::string> related_address;
- RTCStatsMember<int32_t> related_port;
- RTCStatsMember<std::string> username_fragment;
- RTCStatsMember<std::string> tcp_type;
+ absl::optional<bool> is_remote;
+ absl::optional<std::string> network_type;
+ absl::optional<std::string> ip;
+ absl::optional<std::string> address;
+ absl::optional<int32_t> port;
+ absl::optional<std::string> protocol;
+ absl::optional<std::string> relay_protocol;
+ absl::optional<std::string> candidate_type;
+ absl::optional<int32_t> priority;
+ absl::optional<std::string> url;
+ absl::optional<std::string> foundation;
+ absl::optional<std::string> related_address;
+ absl::optional<int32_t> related_port;
+ absl::optional<std::string> username_fragment;
+ absl::optional<std::string> tcp_type;
// The following metrics are NOT exposed to JavaScript. We should consider
// standardizing or removing them.
- RTCStatsMember<bool> vpn;
- RTCStatsMember<std::string> network_adapter_type;
+ absl::optional<bool> vpn;
+ absl::optional<std::string> network_adapter_type;
protected:
RTCIceCandidateStats(std::string id, Timestamp timestamp, bool is_remote);
@@ -168,8 +169,8 @@ class RTC_EXPORT RTCPeerConnectionStats final : public RTCStats {
RTCPeerConnectionStats(std::string id, Timestamp timestamp);
~RTCPeerConnectionStats() override;
- RTCStatsMember<uint32_t> data_channels_opened;
- RTCStatsMember<uint32_t> data_channels_closed;
+ absl::optional<uint32_t> data_channels_opened;
+ absl::optional<uint32_t> data_channels_closed;
};
// https://w3c.github.io/webrtc-stats/#streamstats-dict*
@@ -178,10 +179,10 @@ class RTC_EXPORT RTCRtpStreamStats : public RTCStats {
WEBRTC_RTCSTATS_DECL();
~RTCRtpStreamStats() override;
- RTCStatsMember<uint32_t> ssrc;
- RTCStatsMember<std::string> kind;
- RTCStatsMember<std::string> transport_id;
- RTCStatsMember<std::string> codec_id;
+ absl::optional<uint32_t> ssrc;
+ absl::optional<std::string> kind;
+ absl::optional<std::string> transport_id;
+ absl::optional<std::string> codec_id;
protected:
RTCRtpStreamStats(std::string id, Timestamp timestamp);
@@ -193,8 +194,8 @@ class RTC_EXPORT RTCReceivedRtpStreamStats : public RTCRtpStreamStats {
WEBRTC_RTCSTATS_DECL();
~RTCReceivedRtpStreamStats() override;
- RTCStatsMember<double> jitter;
- RTCStatsMember<int32_t> packets_lost; // Signed per RFC 3550
+ absl::optional<double> jitter;
+ absl::optional<int32_t> packets_lost; // Signed per RFC 3550
protected:
RTCReceivedRtpStreamStats(std::string id, Timestamp timestamp);
@@ -206,8 +207,8 @@ class RTC_EXPORT RTCSentRtpStreamStats : public RTCRtpStreamStats {
WEBRTC_RTCSTATS_DECL();
~RTCSentRtpStreamStats() override;
- RTCStatsMember<uint64_t> packets_sent;
- RTCStatsMember<uint64_t> bytes_sent;
+ absl::optional<uint64_t> packets_sent;
+ absl::optional<uint64_t> bytes_sent;
protected:
RTCSentRtpStreamStats(std::string id, Timestamp timestamp);
@@ -221,51 +222,51 @@ class RTC_EXPORT RTCInboundRtpStreamStats final
RTCInboundRtpStreamStats(std::string id, Timestamp timestamp);
~RTCInboundRtpStreamStats() override;
- RTCStatsMember<std::string> playout_id;
- RTCStatsMember<std::string> track_identifier;
- RTCStatsMember<std::string> mid;
- RTCStatsMember<std::string> remote_id;
- RTCStatsMember<uint32_t> packets_received;
- RTCStatsMember<uint64_t> packets_discarded;
- RTCStatsMember<uint64_t> fec_packets_received;
- RTCStatsMember<uint64_t> fec_bytes_received;
- RTCStatsMember<uint64_t> fec_packets_discarded;
+ absl::optional<std::string> playout_id;
+ absl::optional<std::string> track_identifier;
+ absl::optional<std::string> mid;
+ absl::optional<std::string> remote_id;
+ absl::optional<uint32_t> packets_received;
+ absl::optional<uint64_t> packets_discarded;
+ absl::optional<uint64_t> fec_packets_received;
+ absl::optional<uint64_t> fec_bytes_received;
+ absl::optional<uint64_t> fec_packets_discarded;
// Inbound FEC SSRC. Only present if a mechanism like FlexFEC is negotiated.
- RTCStatsMember<uint32_t> fec_ssrc;
- RTCStatsMember<uint64_t> bytes_received;
- RTCStatsMember<uint64_t> header_bytes_received;
+ absl::optional<uint32_t> fec_ssrc;
+ absl::optional<uint64_t> bytes_received;
+ absl::optional<uint64_t> header_bytes_received;
// Inbound RTX stats. Only defined when RTX is used and it is therefore
// possible to distinguish retransmissions.
- RTCStatsMember<uint64_t> retransmitted_packets_received;
- RTCStatsMember<uint64_t> retransmitted_bytes_received;
- RTCStatsMember<uint32_t> rtx_ssrc;
-
- RTCStatsMember<double> last_packet_received_timestamp;
- RTCStatsMember<double> jitter_buffer_delay;
- RTCStatsMember<double> jitter_buffer_target_delay;
- RTCStatsMember<double> jitter_buffer_minimum_delay;
- RTCStatsMember<uint64_t> jitter_buffer_emitted_count;
- RTCStatsMember<uint64_t> total_samples_received;
- RTCStatsMember<uint64_t> concealed_samples;
- RTCStatsMember<uint64_t> silent_concealed_samples;
- RTCStatsMember<uint64_t> concealment_events;
- RTCStatsMember<uint64_t> inserted_samples_for_deceleration;
- RTCStatsMember<uint64_t> removed_samples_for_acceleration;
- RTCStatsMember<double> audio_level;
- RTCStatsMember<double> total_audio_energy;
- RTCStatsMember<double> total_samples_duration;
+ absl::optional<uint64_t> retransmitted_packets_received;
+ absl::optional<uint64_t> retransmitted_bytes_received;
+ absl::optional<uint32_t> rtx_ssrc;
+
+ absl::optional<double> last_packet_received_timestamp;
+ absl::optional<double> jitter_buffer_delay;
+ absl::optional<double> jitter_buffer_target_delay;
+ absl::optional<double> jitter_buffer_minimum_delay;
+ absl::optional<uint64_t> jitter_buffer_emitted_count;
+ absl::optional<uint64_t> total_samples_received;
+ absl::optional<uint64_t> concealed_samples;
+ absl::optional<uint64_t> silent_concealed_samples;
+ absl::optional<uint64_t> concealment_events;
+ absl::optional<uint64_t> inserted_samples_for_deceleration;
+ absl::optional<uint64_t> removed_samples_for_acceleration;
+ absl::optional<double> audio_level;
+ absl::optional<double> total_audio_energy;
+ absl::optional<double> total_samples_duration;
// Stats below are only implemented or defined for video.
- RTCStatsMember<uint32_t> frames_received;
- RTCStatsMember<uint32_t> frame_width;
- RTCStatsMember<uint32_t> frame_height;
- RTCStatsMember<double> frames_per_second;
- RTCStatsMember<uint32_t> frames_decoded;
- RTCStatsMember<uint32_t> key_frames_decoded;
- RTCStatsMember<uint32_t> frames_dropped;
- RTCStatsMember<double> total_decode_time;
- RTCStatsMember<double> total_processing_delay;
- RTCStatsMember<double> total_assembly_time;
- RTCStatsMember<uint32_t> frames_assembled_from_multiple_packets;
+ absl::optional<uint32_t> frames_received;
+ absl::optional<uint32_t> frame_width;
+ absl::optional<uint32_t> frame_height;
+ absl::optional<double> frames_per_second;
+ absl::optional<uint32_t> frames_decoded;
+ absl::optional<uint32_t> key_frames_decoded;
+ absl::optional<uint32_t> frames_dropped;
+ absl::optional<double> total_decode_time;
+ absl::optional<double> total_processing_delay;
+ absl::optional<double> total_assembly_time;
+ absl::optional<uint32_t> frames_assembled_from_multiple_packets;
// TODO(https://crbug.com/webrtc/15600): Implement framesRendered, which is
// incremented at the same time that totalInterFrameDelay and
// totalSquaredInterFrameDelay is incremented. (Dividing inter-frame delay by
@@ -277,43 +278,43 @@ class RTC_EXPORT RTCInboundRtpStreamStats final
// at delivery to sink, not at actual render time. When we have an actual
// frame rendered callback, move the calculating of these metrics to there in
// order to make them more accurate.
- RTCStatsMember<double> total_inter_frame_delay;
- RTCStatsMember<double> total_squared_inter_frame_delay;
- RTCStatsMember<uint32_t> pause_count;
- RTCStatsMember<double> total_pauses_duration;
- RTCStatsMember<uint32_t> freeze_count;
- RTCStatsMember<double> total_freezes_duration;
+ absl::optional<double> total_inter_frame_delay;
+ absl::optional<double> total_squared_inter_frame_delay;
+ absl::optional<uint32_t> pause_count;
+ absl::optional<double> total_pauses_duration;
+ absl::optional<uint32_t> freeze_count;
+ absl::optional<double> total_freezes_duration;
// https://w3c.github.io/webrtc-provisional-stats/#dom-rtcinboundrtpstreamstats-contenttype
- RTCStatsMember<std::string> content_type;
+ absl::optional<std::string> content_type;
// Only populated if audio/video sync is enabled.
// TODO(https://crbug.com/webrtc/14177): Expose even if A/V sync is off?
- RTCStatsMember<double> estimated_playout_timestamp;
+ absl::optional<double> estimated_playout_timestamp;
// Only defined for video.
// In JavaScript, this is only exposed if HW exposure is allowed.
- RTCStatsMember<std::string> decoder_implementation;
+ absl::optional<std::string> decoder_implementation;
// FIR and PLI counts are only defined for |kind == "video"|.
- RTCStatsMember<uint32_t> fir_count;
- RTCStatsMember<uint32_t> pli_count;
- RTCStatsMember<uint32_t> nack_count;
- RTCStatsMember<uint64_t> qp_sum;
+ absl::optional<uint32_t> fir_count;
+ absl::optional<uint32_t> pli_count;
+ absl::optional<uint32_t> nack_count;
+ absl::optional<uint64_t> qp_sum;
// This is a remnant of the legacy getStats() API. When the "video-timing"
// header extension is used,
// https://webrtc.github.io/webrtc-org/experiments/rtp-hdrext/video-timing/,
// `googTimingFrameInfo` is exposed with the value of
// TimingFrameInfo::ToString().
// TODO(https://crbug.com/webrtc/14586): Unship or standardize this metric.
- RTCStatsMember<std::string> goog_timing_frame_info;
+ absl::optional<std::string> goog_timing_frame_info;
// In JavaScript, this is only exposed if HW exposure is allowed.
- RTCStatsMember<bool> power_efficient_decoder;
+ absl::optional<bool> power_efficient_decoder;
// The following metrics are NOT exposed to JavaScript. We should consider
// standardizing or removing them.
- RTCStatsMember<uint64_t> jitter_buffer_flushes;
- RTCStatsMember<uint64_t> delayed_packet_outage_samples;
- RTCStatsMember<double> relative_packet_arrival_delay;
- RTCStatsMember<uint32_t> interruption_count;
- RTCStatsMember<double> total_interruption_duration;
- RTCStatsMember<double> min_playout_delay;
+ absl::optional<uint64_t> jitter_buffer_flushes;
+ absl::optional<uint64_t> delayed_packet_outage_samples;
+ absl::optional<double> relative_packet_arrival_delay;
+ absl::optional<uint32_t> interruption_count;
+ absl::optional<double> total_interruption_duration;
+ absl::optional<double> min_playout_delay;
};
// https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict*
@@ -324,46 +325,46 @@ class RTC_EXPORT RTCOutboundRtpStreamStats final
RTCOutboundRtpStreamStats(std::string id, Timestamp timestamp);
~RTCOutboundRtpStreamStats() override;
- RTCStatsMember<std::string> media_source_id;
- RTCStatsMember<std::string> remote_id;
- RTCStatsMember<std::string> mid;
- RTCStatsMember<std::string> rid;
- RTCStatsMember<uint64_t> retransmitted_packets_sent;
- RTCStatsMember<uint64_t> header_bytes_sent;
- RTCStatsMember<uint64_t> retransmitted_bytes_sent;
- RTCStatsMember<double> target_bitrate;
- RTCStatsMember<uint32_t> frames_encoded;
- RTCStatsMember<uint32_t> key_frames_encoded;
- RTCStatsMember<double> total_encode_time;
- RTCStatsMember<uint64_t> total_encoded_bytes_target;
- RTCStatsMember<uint32_t> frame_width;
- RTCStatsMember<uint32_t> frame_height;
- RTCStatsMember<double> frames_per_second;
- RTCStatsMember<uint32_t> frames_sent;
- RTCStatsMember<uint32_t> huge_frames_sent;
- RTCStatsMember<double> total_packet_send_delay;
- RTCStatsMember<std::string> quality_limitation_reason;
- RTCStatsMember<std::map<std::string, double>> quality_limitation_durations;
+ absl::optional<std::string> media_source_id;
+ absl::optional<std::string> remote_id;
+ absl::optional<std::string> mid;
+ absl::optional<std::string> rid;
+ absl::optional<uint64_t> retransmitted_packets_sent;
+ absl::optional<uint64_t> header_bytes_sent;
+ absl::optional<uint64_t> retransmitted_bytes_sent;
+ absl::optional<double> target_bitrate;
+ absl::optional<uint32_t> frames_encoded;
+ absl::optional<uint32_t> key_frames_encoded;
+ absl::optional<double> total_encode_time;
+ absl::optional<uint64_t> total_encoded_bytes_target;
+ absl::optional<uint32_t> frame_width;
+ absl::optional<uint32_t> frame_height;
+ absl::optional<double> frames_per_second;
+ absl::optional<uint32_t> frames_sent;
+ absl::optional<uint32_t> huge_frames_sent;
+ absl::optional<double> total_packet_send_delay;
+ absl::optional<std::string> quality_limitation_reason;
+ absl::optional<std::map<std::string, double>> quality_limitation_durations;
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges
- RTCStatsMember<uint32_t> quality_limitation_resolution_changes;
+ absl::optional<uint32_t> quality_limitation_resolution_changes;
// https://w3c.github.io/webrtc-provisional-stats/#dom-rtcoutboundrtpstreamstats-contenttype
- RTCStatsMember<std::string> content_type;
+ absl::optional<std::string> content_type;
// In JavaScript, this is only exposed if HW exposure is allowed.
// Only implemented for video.
// TODO(https://crbug.com/webrtc/14178): Implement for audio as well.
- RTCStatsMember<std::string> encoder_implementation;
+ absl::optional<std::string> encoder_implementation;
// FIR and PLI counts are only defined for |kind == "video"|.
- RTCStatsMember<uint32_t> fir_count;
- RTCStatsMember<uint32_t> pli_count;
- RTCStatsMember<uint32_t> nack_count;
- RTCStatsMember<uint64_t> qp_sum;
- RTCStatsMember<bool> active;
+ absl::optional<uint32_t> fir_count;
+ absl::optional<uint32_t> pli_count;
+ absl::optional<uint32_t> nack_count;
+ absl::optional<uint64_t> qp_sum;
+ absl::optional<bool> active;
// In JavaScript, this is only exposed if HW exposure is allowed.
- RTCStatsMember<bool> power_efficient_encoder;
- RTCStatsMember<std::string> scalability_mode;
+ absl::optional<bool> power_efficient_encoder;
+ absl::optional<std::string> scalability_mode;
// RTX ssrc. Only present if RTX is negotiated.
- RTCStatsMember<uint32_t> rtx_ssrc;
+ absl::optional<uint32_t> rtx_ssrc;
};
// https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
@@ -374,11 +375,11 @@ class RTC_EXPORT RTCRemoteInboundRtpStreamStats final
RTCRemoteInboundRtpStreamStats(std::string id, Timestamp timestamp);
~RTCRemoteInboundRtpStreamStats() override;
- RTCStatsMember<std::string> local_id;
- RTCStatsMember<double> round_trip_time;
- RTCStatsMember<double> fraction_lost;
- RTCStatsMember<double> total_round_trip_time;
- RTCStatsMember<int32_t> round_trip_time_measurements;
+ absl::optional<std::string> local_id;
+ absl::optional<double> round_trip_time;
+ absl::optional<double> fraction_lost;
+ absl::optional<double> total_round_trip_time;
+ absl::optional<int32_t> round_trip_time_measurements;
};
// https://w3c.github.io/webrtc-stats/#remoteoutboundrtpstats-dict*
@@ -389,12 +390,12 @@ class RTC_EXPORT RTCRemoteOutboundRtpStreamStats final
RTCRemoteOutboundRtpStreamStats(std::string id, Timestamp timestamp);
~RTCRemoteOutboundRtpStreamStats() override;
- RTCStatsMember<std::string> local_id;
- RTCStatsMember<double> remote_timestamp;
- RTCStatsMember<uint64_t> reports_sent;
- RTCStatsMember<double> round_trip_time;
- RTCStatsMember<uint64_t> round_trip_time_measurements;
- RTCStatsMember<double> total_round_trip_time;
+ absl::optional<std::string> local_id;
+ absl::optional<double> remote_timestamp;
+ absl::optional<uint64_t> reports_sent;
+ absl::optional<double> round_trip_time;
+ absl::optional<uint64_t> round_trip_time_measurements;
+ absl::optional<double> total_round_trip_time;
};
// https://w3c.github.io/webrtc-stats/#dom-rtcmediasourcestats
@@ -403,8 +404,8 @@ class RTC_EXPORT RTCMediaSourceStats : public RTCStats {
WEBRTC_RTCSTATS_DECL();
~RTCMediaSourceStats() override;
- RTCStatsMember<std::string> track_identifier;
- RTCStatsMember<std::string> kind;
+ absl::optional<std::string> track_identifier;
+ absl::optional<std::string> kind;
protected:
RTCMediaSourceStats(std::string id, Timestamp timestamp);
@@ -417,11 +418,11 @@ class RTC_EXPORT RTCAudioSourceStats final : public RTCMediaSourceStats {
RTCAudioSourceStats(std::string id, Timestamp timestamp);
~RTCAudioSourceStats() override;
- RTCStatsMember<double> audio_level;
- RTCStatsMember<double> total_audio_energy;
- RTCStatsMember<double> total_samples_duration;
- RTCStatsMember<double> echo_return_loss;
- RTCStatsMember<double> echo_return_loss_enhancement;
+ absl::optional<double> audio_level;
+ absl::optional<double> total_audio_energy;
+ absl::optional<double> total_samples_duration;
+ absl::optional<double> echo_return_loss;
+ absl::optional<double> echo_return_loss_enhancement;
};
// https://w3c.github.io/webrtc-stats/#dom-rtcvideosourcestats
@@ -431,10 +432,10 @@ class RTC_EXPORT RTCVideoSourceStats final : public RTCMediaSourceStats {
RTCVideoSourceStats(std::string id, Timestamp timestamp);
~RTCVideoSourceStats() override;
- RTCStatsMember<uint32_t> width;
- RTCStatsMember<uint32_t> height;
- RTCStatsMember<uint32_t> frames;
- RTCStatsMember<double> frames_per_second;
+ absl::optional<uint32_t> width;
+ absl::optional<uint32_t> height;
+ absl::optional<uint32_t> frames;
+ absl::optional<double> frames_per_second;
};
// https://w3c.github.io/webrtc-stats/#transportstats-dict*
@@ -444,23 +445,23 @@ class RTC_EXPORT RTCTransportStats final : public RTCStats {
RTCTransportStats(std::string id, Timestamp timestamp);
~RTCTransportStats() override;
- RTCStatsMember<uint64_t> bytes_sent;
- RTCStatsMember<uint64_t> packets_sent;
- RTCStatsMember<uint64_t> bytes_received;
- RTCStatsMember<uint64_t> packets_received;
- RTCStatsMember<std::string> rtcp_transport_stats_id;
- RTCStatsMember<std::string> dtls_state;
- RTCStatsMember<std::string> selected_candidate_pair_id;
- RTCStatsMember<std::string> local_certificate_id;
- RTCStatsMember<std::string> remote_certificate_id;
- RTCStatsMember<std::string> tls_version;
- RTCStatsMember<std::string> dtls_cipher;
- RTCStatsMember<std::string> dtls_role;
- RTCStatsMember<std::string> srtp_cipher;
- RTCStatsMember<uint32_t> selected_candidate_pair_changes;
- RTCStatsMember<std::string> ice_role;
- RTCStatsMember<std::string> ice_local_username_fragment;
- RTCStatsMember<std::string> ice_state;
+ absl::optional<uint64_t> bytes_sent;
+ absl::optional<uint64_t> packets_sent;
+ absl::optional<uint64_t> bytes_received;
+ absl::optional<uint64_t> packets_received;
+ absl::optional<std::string> rtcp_transport_stats_id;
+ absl::optional<std::string> dtls_state;
+ absl::optional<std::string> selected_candidate_pair_id;
+ absl::optional<std::string> local_certificate_id;
+ absl::optional<std::string> remote_certificate_id;
+ absl::optional<std::string> tls_version;
+ absl::optional<std::string> dtls_cipher;
+ absl::optional<std::string> dtls_role;
+ absl::optional<std::string> srtp_cipher;
+ absl::optional<uint32_t> selected_candidate_pair_changes;
+ absl::optional<std::string> ice_role;
+ absl::optional<std::string> ice_local_username_fragment;
+ absl::optional<std::string> ice_state;
};
// https://w3c.github.io/webrtc-stats/#playoutstats-dict*
@@ -470,12 +471,12 @@ class RTC_EXPORT RTCAudioPlayoutStats final : public RTCStats {
RTCAudioPlayoutStats(const std::string& id, Timestamp timestamp);
~RTCAudioPlayoutStats() override;
- RTCStatsMember<std::string> kind;
- RTCStatsMember<double> synthesized_samples_duration;
- RTCStatsMember<uint64_t> synthesized_samples_events;
- RTCStatsMember<double> total_samples_duration;
- RTCStatsMember<double> total_playout_delay;
- RTCStatsMember<uint64_t> total_samples_count;
+ absl::optional<std::string> kind;
+ absl::optional<double> synthesized_samples_duration;
+ absl::optional<uint64_t> synthesized_samples_events;
+ absl::optional<double> total_samples_duration;
+ absl::optional<double> total_playout_delay;
+ absl::optional<uint64_t> total_samples_count;
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/test/mock_frame_transformer.h b/third_party/libwebrtc/api/test/mock_frame_transformer.h
index 617cda8a43..8f438bdf9e 100644
--- a/third_party/libwebrtc/test/mock_frame_transformer.h
+++ b/third_party/libwebrtc/api/test/mock_frame_transformer.h
@@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#ifndef TEST_MOCK_FRAME_TRANSFORMER_H_
-#define TEST_MOCK_FRAME_TRANSFORMER_H_
+#ifndef API_TEST_MOCK_FRAME_TRANSFORMER_H_
+#define API_TEST_MOCK_FRAME_TRANSFORMER_H_
#include <memory>
#include <vector>
@@ -42,4 +42,4 @@ class MockFrameTransformer : public FrameTransformerInterface {
} // namespace webrtc
-#endif // TEST_MOCK_FRAME_TRANSFORMER_H_
+#endif // API_TEST_MOCK_FRAME_TRANSFORMER_H_
diff --git a/third_party/libwebrtc/api/test/mock_peerconnectioninterface.h b/third_party/libwebrtc/api/test/mock_peerconnectioninterface.h
index ccc6ce46b1..22a77d7dfe 100644
--- a/third_party/libwebrtc/api/test/mock_peerconnectioninterface.h
+++ b/third_party/libwebrtc/api/test/mock_peerconnectioninterface.h
@@ -177,6 +177,10 @@ class MockPeerConnectionInterface : public webrtc::PeerConnectionInterface {
(const std::vector<cricket::Candidate>&),
(override));
MOCK_METHOD(RTCError, SetBitrate, (const BitrateSettings&), (override));
+ MOCK_METHOD(void,
+ ReconfigureBandwidthEstimation,
+ (const BandwidthEstimationSettings&),
+ (override));
MOCK_METHOD(void, SetAudioPlayout, (bool), (override));
MOCK_METHOD(void, SetAudioRecording, (bool), (override));
MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>,
diff --git a/third_party/libwebrtc/api/test/mock_video_decoder_factory.h b/third_party/libwebrtc/api/test/mock_video_decoder_factory.h
index 6150d9f8b5..48d96ea58b 100644
--- a/third_party/libwebrtc/api/test/mock_video_decoder_factory.h
+++ b/third_party/libwebrtc/api/test/mock_video_decoder_factory.h
@@ -14,6 +14,7 @@
#include <memory>
#include <vector>
+#include "api/environment/environment.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_decoder_factory.h"
@@ -21,17 +22,21 @@
namespace webrtc {
-class MockVideoDecoderFactory : public webrtc::VideoDecoderFactory {
+class MockVideoDecoderFactory : public VideoDecoderFactory {
public:
~MockVideoDecoderFactory() override { Die(); }
- MOCK_METHOD(std::vector<webrtc::SdpVideoFormat>,
+ MOCK_METHOD(std::vector<SdpVideoFormat>,
GetSupportedFormats,
(),
(const, override));
- MOCK_METHOD(std::unique_ptr<webrtc::VideoDecoder>,
+ MOCK_METHOD(std::unique_ptr<VideoDecoder>,
+ Create,
+ (const Environment&, const SdpVideoFormat&),
+ (override));
+ MOCK_METHOD(std::unique_ptr<VideoDecoder>,
CreateVideoDecoder,
- (const webrtc::SdpVideoFormat&),
+ (const SdpVideoFormat&),
(override));
MOCK_METHOD(void, Die, ());
};
diff --git a/third_party/libwebrtc/api/test/pclf/BUILD.gn b/third_party/libwebrtc/api/test/pclf/BUILD.gn
index 4f62984e83..68f1688556 100644
--- a/third_party/libwebrtc/api/test/pclf/BUILD.gn
+++ b/third_party/libwebrtc/api/test/pclf/BUILD.gn
@@ -74,6 +74,8 @@ rtc_library("media_quality_test_params") {
"../../../api/transport:network_control",
"../../../api/video_codecs:video_codecs_api",
"../../../modules/audio_processing:api",
+ "../../../p2p:connection",
+ "../../../p2p:port_allocator",
"../../../p2p:rtc_p2p",
"../../../rtc_base:network",
"../../../rtc_base:rtc_certificate_generator",
diff --git a/third_party/libwebrtc/api/test/video/BUILD.gn b/third_party/libwebrtc/api/test/video/BUILD.gn
index 0eae85aef3..cf6dd599c9 100644
--- a/third_party/libwebrtc/api/test/video/BUILD.gn
+++ b/third_party/libwebrtc/api/test/video/BUILD.gn
@@ -18,6 +18,7 @@ rtc_library("function_video_factory") {
deps = [
"../../../rtc_base:checks",
+ "../../environment",
"../../video_codecs:video_codecs_api",
]
}
diff --git a/third_party/libwebrtc/api/test/video/function_video_decoder_factory.h b/third_party/libwebrtc/api/test/video/function_video_decoder_factory.h
index 2145c71bff..2f2eeb5886 100644
--- a/third_party/libwebrtc/api/test/video/function_video_decoder_factory.h
+++ b/third_party/libwebrtc/api/test/video/function_video_decoder_factory.h
@@ -16,6 +16,7 @@
#include <utility>
#include <vector>
+#include "api/environment/environment.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_decoder_factory.h"
@@ -29,17 +30,20 @@ class FunctionVideoDecoderFactory final : public VideoDecoderFactory {
public:
explicit FunctionVideoDecoderFactory(
std::function<std::unique_ptr<VideoDecoder>()> create)
- : create_([create = std::move(create)](const SdpVideoFormat&) {
+ : create_([create = std::move(create)](const Environment&,
+ const SdpVideoFormat&) {
return create();
}) {}
explicit FunctionVideoDecoderFactory(
- std::function<std::unique_ptr<VideoDecoder>(const SdpVideoFormat&)>
+ std::function<std::unique_ptr<VideoDecoder>(const Environment&,
+ const SdpVideoFormat&)>
create)
: create_(std::move(create)) {}
FunctionVideoDecoderFactory(
std::function<std::unique_ptr<VideoDecoder>()> create,
std::vector<SdpVideoFormat> sdp_video_formats)
- : create_([create = std::move(create)](const SdpVideoFormat&) {
+ : create_([create = std::move(create)](const Environment&,
+ const SdpVideoFormat&) {
return create();
}),
sdp_video_formats_(std::move(sdp_video_formats)) {}
@@ -48,13 +52,14 @@ class FunctionVideoDecoderFactory final : public VideoDecoderFactory {
return sdp_video_formats_;
}
- std::unique_ptr<VideoDecoder> CreateVideoDecoder(
- const SdpVideoFormat& format) override {
- return create_(format);
+ std::unique_ptr<VideoDecoder> Create(const Environment& env,
+ const SdpVideoFormat& format) override {
+ return create_(env, format);
}
private:
- const std::function<std::unique_ptr<VideoDecoder>(const SdpVideoFormat&)>
+ const std::function<std::unique_ptr<VideoDecoder>(const Environment& env,
+ const SdpVideoFormat&)>
create_;
const std::vector<SdpVideoFormat> sdp_video_formats_;
};
diff --git a/third_party/libwebrtc/api/transport/BUILD.gn b/third_party/libwebrtc/api/transport/BUILD.gn
index c0209bf0d0..21559815ca 100644
--- a/third_party/libwebrtc/api/transport/BUILD.gn
+++ b/third_party/libwebrtc/api/transport/BUILD.gn
@@ -18,6 +18,12 @@ rtc_library("bitrate_settings") {
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
+rtc_library("bandwidth_estimation_settings") {
+ visibility = [ "*" ]
+ sources = [ "bandwidth_estimation_settings.h" ]
+ deps = [ "../../rtc_base/system:rtc_export" ]
+}
+
rtc_source_set("enums") {
visibility = [ "*" ]
sources = [ "enums.h" ]
diff --git a/third_party/libwebrtc/api/transport/bandwidth_estimation_settings.h b/third_party/libwebrtc/api/transport/bandwidth_estimation_settings.h
new file mode 100644
index 0000000000..7ae8cc9ef8
--- /dev/null
+++ b/third_party/libwebrtc/api/transport/bandwidth_estimation_settings.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_TRANSPORT_BANDWIDTH_ESTIMATION_SETTINGS_H_
+#define API_TRANSPORT_BANDWIDTH_ESTIMATION_SETTINGS_H_
+
+#include "rtc_base/system/rtc_export.h"
+namespace webrtc {
+// Configuration settings affecting bandwidth estimation.
+// These settings can be set and changed by an application.
+struct RTC_EXPORT BandwidthEstimationSettings {
+ // A bandwith estimation probe may be sent using a RtpTransceiver with
+ // direction SendOnly or SendRecv that supports RTX. The probe can be sent
+ // without first sending media packets in which case Rtp padding packets are
+ // used.
+ bool allow_probe_without_media = false;
+};
+
+} // namespace webrtc
+#endif // API_TRANSPORT_BANDWIDTH_ESTIMATION_SETTINGS_H_
diff --git a/third_party/libwebrtc/api/transport/bandwidth_estimation_settings_gn/moz.build b/third_party/libwebrtc/api/transport/bandwidth_estimation_settings_gn/moz.build
new file mode 100644
index 0000000000..10e3f8f835
--- /dev/null
+++ b/third_party/libwebrtc/api/transport/bandwidth_estimation_settings_gn/moz.build
@@ -0,0 +1,198 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+ ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ###
+ ### DO NOT edit it by hand. ###
+
+COMPILE_FLAGS["OS_INCLUDES"] = []
+AllowCompilerWarnings()
+
+DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1"
+DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True
+DEFINES["RTC_ENABLE_VP9"] = True
+DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0"
+DEFINES["WEBRTC_LIBRARY_IMPL"] = True
+DEFINES["WEBRTC_MOZILLA_BUILD"] = True
+DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0"
+DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0"
+
+FINAL_LIBRARY = "webrtc"
+
+
+LOCAL_INCLUDES += [
+ "!/ipc/ipdl/_ipdlheaders",
+ "!/third_party/libwebrtc/gen",
+ "/ipc/chromium/src",
+ "/third_party/libwebrtc/",
+ "/third_party/libwebrtc/third_party/abseil-cpp/",
+ "/tools/profiler/public"
+]
+
+if not CONFIG["MOZ_DEBUG"]:
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0"
+ DEFINES["NDEBUG"] = True
+ DEFINES["NVALGRIND"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1":
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1"
+
+if CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["ANDROID"] = True
+ DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1"
+ DEFINES["HAVE_SYS_UIO_H"] = True
+ DEFINES["WEBRTC_ANDROID"] = True
+ DEFINES["WEBRTC_ANDROID_OPENSLES"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_GNU_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["WEBRTC_MAC"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True
+ DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0"
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_NSS_CERTS"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_UDEV"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_X11"] = "1"
+ DEFINES["WEBRTC_BSD"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True
+ DEFINES["NOMINMAX"] = True
+ DEFINES["NTDDI_VERSION"] = "0x0A000000"
+ DEFINES["PSAPI_VERSION"] = "2"
+ DEFINES["RTC_ENABLE_WIN_WGC"] = True
+ DEFINES["UNICODE"] = True
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["WEBRTC_WIN"] = True
+ DEFINES["WIN32"] = True
+ DEFINES["WIN32_LEAN_AND_MEAN"] = True
+ DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP"
+ DEFINES["WINVER"] = "0x0A00"
+ DEFINES["_ATL_NO_OPENGL"] = True
+ DEFINES["_CRT_RAND_S"] = True
+ DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True
+ DEFINES["_HAS_EXCEPTIONS"] = "0"
+ DEFINES["_HAS_NODISCARD"] = True
+ DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_SECURE_ATL"] = True
+ DEFINES["_UNICODE"] = True
+ DEFINES["_WIN32_WINNT"] = "0x0A00"
+ DEFINES["_WINDOWS"] = True
+ DEFINES["__STD_C"] = True
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "x86_64":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0"
+
+if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_X11"] = "1"
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+Library("bandwidth_estimation_settings_gn")
diff --git a/third_party/libwebrtc/api/video_codecs/BUILD.gn b/third_party/libwebrtc/api/video_codecs/BUILD.gn
index 3865f4fee7..9f7022ca67 100644
--- a/third_party/libwebrtc/api/video_codecs/BUILD.gn
+++ b/third_party/libwebrtc/api/video_codecs/BUILD.gn
@@ -58,6 +58,7 @@ rtc_library("video_codecs_api") {
"video_codec.h",
"video_decoder.cc",
"video_decoder.h",
+ "video_decoder_factory.cc",
"video_decoder_factory.h",
"video_encoder.cc",
"video_encoder.h",
@@ -84,6 +85,7 @@ rtc_library("video_codecs_api") {
"..:scoped_refptr",
"../../api:array_view",
"../../api:rtp_parameters",
+ "../../media:media_constants",
"../../modules/video_coding:codec_globals_headers",
"../../rtc_base:checks",
"../../rtc_base:logging",
@@ -91,6 +93,7 @@ rtc_library("video_codecs_api") {
"../../rtc_base:refcount",
"../../rtc_base:stringutils",
"../../rtc_base/system:rtc_export",
+ "../environment",
"../units:data_rate",
"../video:encoded_image",
"../video:render_resolution",
@@ -302,6 +305,8 @@ rtc_library("rtc_software_fallback_wrappers") {
deps = [
":video_codecs_api",
"..:fec_controller_api",
+ "../../api:field_trials_view",
+ "../../api/environment",
"../../api/transport:field_trial_based_config",
"../../api/video:video_frame",
"../../media:rtc_media_base",
diff --git a/third_party/libwebrtc/api/video_codecs/av1_profile.cc b/third_party/libwebrtc/api/video_codecs/av1_profile.cc
index 59d7b13e51..1a953a0c53 100644
--- a/third_party/libwebrtc/api/video_codecs/av1_profile.cc
+++ b/third_party/libwebrtc/api/video_codecs/av1_profile.cc
@@ -13,13 +13,11 @@
#include <map>
#include <utility>
+#include "media/base/media_constants.h"
#include "rtc_base/string_to_number.h"
namespace webrtc {
-// Parameter name in the format parameter map for AV1 video.
-const char kAV1FmtpProfile[] = "profile";
-
absl::string_view AV1ProfileToString(AV1Profile profile) {
switch (profile) {
case AV1Profile::kProfile0:
@@ -51,7 +49,7 @@ absl::optional<AV1Profile> StringToAV1Profile(absl::string_view str) {
absl::optional<AV1Profile> ParseSdpForAV1Profile(
const CodecParameterMap& params) {
- const auto profile_it = params.find(kAV1FmtpProfile);
+ const auto profile_it = params.find(cricket::kAv1FmtpProfile);
if (profile_it == params.end())
return AV1Profile::kProfile0;
const std::string& profile_str = profile_it->second;
diff --git a/third_party/libwebrtc/api/video_codecs/av1_profile.h b/third_party/libwebrtc/api/video_codecs/av1_profile.h
index bc9767631c..4651d93ef4 100644
--- a/third_party/libwebrtc/api/video_codecs/av1_profile.h
+++ b/third_party/libwebrtc/api/video_codecs/av1_profile.h
@@ -20,9 +20,6 @@
namespace webrtc {
-// Profile information for AV1 video.
-extern RTC_EXPORT const char kAV1FmtpProfile[];
-
// Profiles can be found at:
// https://aomedia.org/av1/specification/annex-a/#profiles
// The enum values match the number specified in the SDP.
diff --git a/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc b/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc
index 0f313e84a9..5abde8fbb0 100644
--- a/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc
+++ b/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc
@@ -20,6 +20,7 @@
#endif
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/vp9_profile.h"
+#include "media/base/media_constants.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
@@ -28,15 +29,21 @@ namespace webrtc {
namespace {
-std::string H264GetPacketizationModeOrDefault(const CodecParameterMap& params) {
- constexpr char kH264FmtpPacketizationMode[] = "packetization-mode";
- const auto it = params.find(kH264FmtpPacketizationMode);
+std::string GetFmtpParameterOrDefault(const CodecParameterMap& params,
+ const std::string& name,
+ const std::string& default_value) {
+ const auto it = params.find(name);
if (it != params.end()) {
return it->second;
}
+ return default_value;
+}
+
+std::string H264GetPacketizationModeOrDefault(const CodecParameterMap& params) {
// If packetization-mode is not present, default to "0".
// https://tools.ietf.org/html/rfc6184#section-6.2
- return "0";
+ return GetFmtpParameterOrDefault(params, cricket::kH264FmtpPacketizationMode,
+ "0");
}
bool H264IsSamePacketizationMode(const CodecParameterMap& left,
@@ -45,6 +52,28 @@ bool H264IsSamePacketizationMode(const CodecParameterMap& left,
H264GetPacketizationModeOrDefault(right);
}
+std::string AV1GetTierOrDefault(const CodecParameterMap& params) {
+ // If the parameter is not present, the tier MUST be inferred to be 0.
+ // https://aomediacodec.github.io/av1-rtp-spec/#72-sdp-parameters
+ return GetFmtpParameterOrDefault(params, cricket::kAv1FmtpTier, "0");
+}
+
+bool AV1IsSameTier(const CodecParameterMap& left,
+ const CodecParameterMap& right) {
+ return AV1GetTierOrDefault(left) == AV1GetTierOrDefault(right);
+}
+
+std::string AV1GetLevelIdxOrDefault(const CodecParameterMap& params) {
+ // If the parameter is not present, it MUST be inferred to be 5 (level 3.1).
+ // https://aomediacodec.github.io/av1-rtp-spec/#72-sdp-parameters
+ return GetFmtpParameterOrDefault(params, cricket::kAv1FmtpLevelIdx, "5");
+}
+
+bool AV1IsSameLevelIdx(const CodecParameterMap& left,
+ const CodecParameterMap& right) {
+ return AV1GetLevelIdxOrDefault(left) == AV1GetLevelIdxOrDefault(right);
+}
+
// Some (video) codecs are actually families of codecs and rely on parameters
// to distinguish different incompatible family members.
bool IsSameCodecSpecific(const SdpVideoFormat& format1,
@@ -62,7 +91,9 @@ bool IsSameCodecSpecific(const SdpVideoFormat& format1,
case kVideoCodecVP9:
return VP9IsSameProfile(format1.parameters, format2.parameters);
case kVideoCodecAV1:
- return AV1IsSameProfile(format1.parameters, format2.parameters);
+ return AV1IsSameProfile(format1.parameters, format2.parameters) &&
+ AV1IsSameTier(format1.parameters, format2.parameters) &&
+ AV1IsSameLevelIdx(format1.parameters, format2.parameters);
#ifdef RTC_ENABLE_H265
case kVideoCodecH265:
return H265IsSameProfileTierLevel(format1.parameters, format2.parameters);
@@ -71,6 +102,7 @@ bool IsSameCodecSpecific(const SdpVideoFormat& format1,
return true;
}
}
+
} // namespace
SdpVideoFormat::SdpVideoFormat(const std::string& name) : name(name) {}
diff --git a/third_party/libwebrtc/api/video_codecs/test/BUILD.gn b/third_party/libwebrtc/api/video_codecs/test/BUILD.gn
index 7bfe86e9f4..be897ae124 100644
--- a/third_party/libwebrtc/api/video_codecs/test/BUILD.gn
+++ b/third_party/libwebrtc/api/video_codecs/test/BUILD.gn
@@ -39,10 +39,13 @@ if (rtc_include_tests) {
"../../../modules/video_coding:webrtc_vp8",
"../../../rtc_base:checks",
"../../../rtc_base:rtc_base_tests_utils",
+ "../../../test:explicit_key_value_config",
"../../../test:fake_video_codecs",
"../../../test:field_trial",
"../../../test:test_support",
"../../../test:video_test_common",
+ "../../environment",
+ "../../environment:environment_factory",
"../../video:encoded_image",
"../../video:video_bitrate_allocation",
"../../video:video_frame",
diff --git a/third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc b/third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc
index 97be6250db..bd837605b0 100644
--- a/third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc
+++ b/third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc
@@ -13,6 +13,8 @@
#include <stdint.h>
#include "absl/types/optional.h"
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/video/encoded_image.h"
#include "api/video/video_frame.h"
#include "api/video_codecs/video_decoder.h"
@@ -20,7 +22,7 @@
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "rtc_base/checks.h"
-#include "test/field_trial.h"
+#include "test/explicit_key_value_config.h"
#include "test/gtest.h"
namespace webrtc {
@@ -31,10 +33,12 @@ class VideoDecoderSoftwareFallbackWrapperTest : public ::testing::Test {
: VideoDecoderSoftwareFallbackWrapperTest("") {}
explicit VideoDecoderSoftwareFallbackWrapperTest(
const std::string& field_trials)
- : override_field_trials_(field_trials),
+ : field_trials_(field_trials),
+ env_(CreateEnvironment(&field_trials_)),
fake_decoder_(new CountingFakeDecoder()),
fallback_wrapper_(CreateVideoDecoderSoftwareFallbackWrapper(
- std::unique_ptr<VideoDecoder>(VP8Decoder::Create()),
+ env_,
+ CreateVp8Decoder(env_),
std::unique_ptr<VideoDecoder>(fake_decoder_))) {}
class CountingFakeDecoder : public VideoDecoder {
@@ -71,7 +75,8 @@ class VideoDecoderSoftwareFallbackWrapperTest : public ::testing::Test {
int release_count_ = 0;
int reset_count_ = 0;
};
- test::ScopedFieldTrials override_field_trials_;
+ test::ExplicitKeyValueConfig field_trials_;
+ const Environment env_;
// `fake_decoder_` is owned and released by `fallback_wrapper_`.
CountingFakeDecoder* fake_decoder_;
std::unique_ptr<VideoDecoder> fallback_wrapper_;
@@ -275,7 +280,7 @@ class ForcedSoftwareDecoderFallbackTest
fake_decoder_ = new CountingFakeDecoder();
sw_fallback_decoder_ = new CountingFakeDecoder();
fallback_wrapper_ = CreateVideoDecoderSoftwareFallbackWrapper(
- std::unique_ptr<VideoDecoder>(sw_fallback_decoder_),
+ env_, std::unique_ptr<VideoDecoder>(sw_fallback_decoder_),
std::unique_ptr<VideoDecoder>(fake_decoder_));
}
diff --git a/third_party/libwebrtc/api/video_codecs/video_codec.cc b/third_party/libwebrtc/api/video_codecs/video_codec.cc
index 39a345d699..82c9bfc8ea 100644
--- a/third_party/libwebrtc/api/video_codecs/video_codec.cc
+++ b/third_party/libwebrtc/api/video_codecs/video_codec.cc
@@ -16,6 +16,7 @@
#include "absl/strings/match.h"
#include "rtc_base/checks.h"
+#include "rtc_base/strings/string_builder.h"
namespace webrtc {
namespace {
@@ -73,6 +74,35 @@ VideoCodec::VideoCodec()
codec_specific_(),
complexity_(VideoCodecComplexity::kComplexityNormal) {}
+std::string VideoCodec::ToString() const {
+ char string_buf[2048];
+ rtc::SimpleStringBuilder ss(string_buf);
+
+ ss << "VideoCodec {" << "type: " << CodecTypeToPayloadString(codecType)
+ << ", mode: "
+ << (mode == VideoCodecMode::kRealtimeVideo ? "RealtimeVideo"
+ : "Screensharing");
+ if (IsSinglecast()) {
+ absl::optional<ScalabilityMode> scalability_mode = GetScalabilityMode();
+ if (scalability_mode.has_value()) {
+ ss << ", Singlecast: {" << width << "x" << height << " "
+ << ScalabilityModeToString(*scalability_mode)
+ << (active ? ", active" : ", inactive") << "}";
+ }
+ } else {
+ ss << ", Simulcast: {";
+ for (size_t i = 0; i < numberOfSimulcastStreams; ++i) {
+ const SimulcastStream stream = simulcastStream[i];
+ ss << "[" << stream.width << "x" << stream.height << " "
+ << ScalabilityModeToString(stream.GetScalabilityMode())
+ << (stream.active ? ", active" : ", inactive") << "]";
+ }
+ ss << "}";
+ }
+ ss << "}";
+ return ss.str();
+}
+
VideoCodecVP8* VideoCodec::VP8() {
RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
return &codec_specific_.VP8;
diff --git a/third_party/libwebrtc/api/video_codecs/video_codec.h b/third_party/libwebrtc/api/video_codecs/video_codec.h
index a596af1528..e48ffd4b5f 100644
--- a/third_party/libwebrtc/api/video_codecs/video_codec.h
+++ b/third_party/libwebrtc/api/video_codecs/video_codec.h
@@ -141,6 +141,9 @@ class RTC_EXPORT VideoCodec {
bool GetFrameDropEnabled() const;
void SetFrameDropEnabled(bool enabled);
+ bool IsSinglecast() const { return numberOfSimulcastStreams <= 1; }
+ bool IsSimulcast() const { return !IsSinglecast(); }
+
// Public variables. TODO(hta): Make them private with accessors.
VideoCodecType codecType;
@@ -193,6 +196,7 @@ class RTC_EXPORT VideoCodec {
bool operator==(const VideoCodec& other) const = delete;
bool operator!=(const VideoCodec& other) const = delete;
+ std::string ToString() const;
// Accessors for codec specific information.
// There is a const version of each that returns a reference,
diff --git a/third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build b/third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build
index c6c127e5b6..13a1c027cf 100644
--- a/third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build
+++ b/third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build
@@ -38,6 +38,7 @@ UNIFIED_SOURCES += [
"/third_party/libwebrtc/api/video_codecs/spatial_layer.cc",
"/third_party/libwebrtc/api/video_codecs/video_codec.cc",
"/third_party/libwebrtc/api/video_codecs/video_decoder.cc",
+ "/third_party/libwebrtc/api/video_codecs/video_decoder_factory.cc",
"/third_party/libwebrtc/api/video_codecs/video_encoder.cc",
"/third_party/libwebrtc/api/video_codecs/vp8_frame_config.cc",
"/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.cc",
diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory.cc b/third_party/libwebrtc/api/video_codecs/video_decoder_factory.cc
new file mode 100644
index 0000000000..60fe92bf38
--- /dev/null
+++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory.cc
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/video_codecs/video_decoder_factory.h"
+
+#include <memory>
+
+#include "api/video_codecs/sdp_video_format.h"
+#include "api/video_codecs/video_decoder.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+VideoDecoderFactory::CodecSupport VideoDecoderFactory::QueryCodecSupport(
+ const SdpVideoFormat& format,
+ bool reference_scaling) const {
+ // Default implementation, query for supported formats and check if the
+ // specified format is supported. Returns false if `reference_scaling` is
+ // true.
+ return {.is_supported = !reference_scaling &&
+ format.IsCodecInList(GetSupportedFormats())};
+}
+
+std::unique_ptr<VideoDecoder> VideoDecoderFactory::Create(
+ const Environment& env,
+ const SdpVideoFormat& format) {
+ return CreateVideoDecoder(format);
+}
+
+std::unique_ptr<VideoDecoder> VideoDecoderFactory::CreateVideoDecoder(
+ const SdpVideoFormat& format) {
+ // Newer code shouldn't call this function,
+ // Older code should implement it in derived classes.
+ RTC_CHECK_NOTREACHED();
+ return nullptr;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory.h
index 7e1d2ee883..6048cb27fb 100644
--- a/third_party/libwebrtc/api/video_codecs/video_decoder_factory.h
+++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory.h
@@ -12,17 +12,15 @@
#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_H_
#include <memory>
-#include <string>
#include <vector>
-#include "absl/types/optional.h"
+#include "api/environment/environment.h"
#include "api/video_codecs/sdp_video_format.h"
+#include "api/video_codecs/video_decoder.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
-class VideoDecoder;
-
// A factory that creates VideoDecoders.
// NOTE: This class is still under development and may change without notice.
class RTC_EXPORT VideoDecoderFactory {
@@ -32,6 +30,8 @@ class RTC_EXPORT VideoDecoderFactory {
bool is_power_efficient = false;
};
+ virtual ~VideoDecoderFactory() = default;
+
// Returns a list of supported video formats in order of preference, to use
// for signaling etc.
virtual std::vector<SdpVideoFormat> GetSupportedFormats() const = 0;
@@ -47,21 +47,18 @@ class RTC_EXPORT VideoDecoderFactory {
// different scalabilty modes. NOTE: QueryCodecSupport is currently an
// experimental feature that is subject to change without notice.
virtual CodecSupport QueryCodecSupport(const SdpVideoFormat& format,
- bool reference_scaling) const {
- // Default implementation, query for supported formats and check if the
- // specified format is supported. Returns false if `reference_scaling` is
- // true.
- CodecSupport codec_support;
- codec_support.is_supported =
- !reference_scaling && format.IsCodecInList(GetSupportedFormats());
- return codec_support;
- }
+ bool reference_scaling) const;
- // Creates a VideoDecoder for the specified format.
- virtual std::unique_ptr<VideoDecoder> CreateVideoDecoder(
- const SdpVideoFormat& format) = 0;
+ // Creates a VideoDecoder for the specified `format`.
+ // TODO: bugs.webrtc.org/15791 - Make pure virtual when implemented in all
+ // derived classes.
+ virtual std::unique_ptr<VideoDecoder> Create(const Environment& env,
+ const SdpVideoFormat& format);
- virtual ~VideoDecoderFactory() {}
+ // TODO: bugs.webrtc.org/15791 - Make private or delete when all callers are
+ // migrated to `Create`.
+ virtual std::unique_ptr<VideoDecoder> CreateVideoDecoder(
+ const SdpVideoFormat& format);
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h
index bffbdc43d3..f38d46994b 100644
--- a/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h
+++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h
@@ -23,7 +23,7 @@ struct Dav1dDecoderTemplateAdapter {
static std::vector<SdpVideoFormat> SupportedFormats() {
return {SdpVideoFormat("AV1"),
SdpVideoFormat(
- "AV1", {{kAV1FmtpProfile,
+ "AV1", {{"profile",
AV1ProfileToString(AV1Profile::kProfile1).data()}})};
}
diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc
index 2af4d39b3a..623888b9e2 100644
--- a/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc
+++ b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc
@@ -16,6 +16,7 @@
#include <string>
#include <utility>
+#include "api/field_trials_view.h"
#include "api/video/encoded_image.h"
#include "api/video_codecs/video_decoder.h"
#include "modules/video_coding/include/video_error_codes.h"
@@ -35,7 +36,8 @@ class VideoDecoderSoftwareFallbackWrapper final : public VideoDecoder {
public:
VideoDecoderSoftwareFallbackWrapper(
std::unique_ptr<VideoDecoder> sw_fallback_decoder,
- std::unique_ptr<VideoDecoder> hw_decoder);
+ std::unique_ptr<VideoDecoder> hw_decoder,
+ bool force_sw_decoder_fallback);
~VideoDecoderSoftwareFallbackWrapper() override;
bool Configure(const Settings& settings) override;
@@ -67,6 +69,7 @@ class VideoDecoderSoftwareFallbackWrapper final : public VideoDecoder {
} decoder_type_;
std::unique_ptr<VideoDecoder> hw_decoder_;
+ const bool force_sw_decoder_fallback_;
Settings decoder_settings_;
const std::unique_ptr<VideoDecoder> fallback_decoder_;
const std::string fallback_implementation_name_;
@@ -77,9 +80,11 @@ class VideoDecoderSoftwareFallbackWrapper final : public VideoDecoder {
VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper(
std::unique_ptr<VideoDecoder> sw_fallback_decoder,
- std::unique_ptr<VideoDecoder> hw_decoder)
+ std::unique_ptr<VideoDecoder> hw_decoder,
+ bool force_sw_decoder_fallback)
: decoder_type_(DecoderType::kNone),
hw_decoder_(std::move(hw_decoder)),
+ force_sw_decoder_fallback_(force_sw_decoder_fallback),
fallback_decoder_(std::move(sw_fallback_decoder)),
fallback_implementation_name_(
fallback_decoder_->GetDecoderInfo().implementation_name +
@@ -94,7 +99,7 @@ VideoDecoderSoftwareFallbackWrapper::~VideoDecoderSoftwareFallbackWrapper() =
bool VideoDecoderSoftwareFallbackWrapper::Configure(const Settings& settings) {
decoder_settings_ = settings;
- if (webrtc::field_trial::IsEnabled("WebRTC-Video-ForcedSwDecoderFallback")) {
+ if (force_sw_decoder_fallback_) {
RTC_LOG(LS_INFO) << "Forced software decoder fallback enabled.";
RTC_DCHECK(decoder_type_ == DecoderType::kNone);
return InitFallbackDecoder();
@@ -276,10 +281,20 @@ VideoDecoder& VideoDecoderSoftwareFallbackWrapper::active_decoder() const {
} // namespace
std::unique_ptr<VideoDecoder> CreateVideoDecoderSoftwareFallbackWrapper(
+ const Environment& env,
std::unique_ptr<VideoDecoder> sw_fallback_decoder,
std::unique_ptr<VideoDecoder> hw_decoder) {
return std::make_unique<VideoDecoderSoftwareFallbackWrapper>(
- std::move(sw_fallback_decoder), std::move(hw_decoder));
+ std::move(sw_fallback_decoder), std::move(hw_decoder),
+ env.field_trials().IsEnabled("WebRTC-Video-ForcedSwDecoderFallback"));
+}
+
+std::unique_ptr<VideoDecoder> CreateVideoDecoderSoftwareFallbackWrapper(
+ std::unique_ptr<VideoDecoder> sw_fallback_decoder,
+ std::unique_ptr<VideoDecoder> hw_decoder) {
+ return std::make_unique<VideoDecoderSoftwareFallbackWrapper>(
+ std::move(sw_fallback_decoder), std::move(hw_decoder),
+ webrtc::field_trial::IsEnabled("WebRTC-Video-ForcedSwDecoderFallback"));
}
} // namespace webrtc
diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h
index 3f44e02b26..4fbc9a0048 100644
--- a/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h
+++ b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h
@@ -13,6 +13,7 @@
#include <memory>
+#include "api/environment/environment.h"
#include "api/video_codecs/video_decoder.h"
#include "rtc_base/system/rtc_export.h"
@@ -23,6 +24,13 @@ namespace webrtc {
// hardware restrictions, such as max resolution.
RTC_EXPORT std::unique_ptr<VideoDecoder>
CreateVideoDecoderSoftwareFallbackWrapper(
+ const Environment& env,
+ std::unique_ptr<VideoDecoder> sw_fallback_decoder,
+ std::unique_ptr<VideoDecoder> hw_decoder);
+
+// TODO: bugs.webrtc.org/15791 - Deprecated, remove when not used by chromium.
+RTC_EXPORT std::unique_ptr<VideoDecoder>
+CreateVideoDecoderSoftwareFallbackWrapper(
std::unique_ptr<VideoDecoder> sw_fallback_decoder,
std::unique_ptr<VideoDecoder> hw_decoder);
diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc b/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc
index d35c9f9950..e50b5086e8 100644
--- a/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc
+++ b/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc
@@ -28,6 +28,7 @@
#include "api/video_codecs/video_encoder.h"
#include "media/base/video_common.h"
#include "modules/video_coding/include/video_error_codes.h"
+#include "modules/video_coding/include/video_error_codes_utils.h"
#include "modules/video_coding/utility/simulcast_utility.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/field_trial_parser.h"
@@ -264,14 +265,17 @@ void VideoEncoderSoftwareFallbackWrapper::PrimeEncoder(
}
bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder(bool is_forced) {
- RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding.";
+ RTC_LOG(LS_WARNING) << "[VESFW] " << __func__
+ << "(is_forced=" << (is_forced ? "true" : "false") << ")";
RTC_DCHECK(encoder_settings_.has_value());
const int ret = fallback_encoder_->InitEncode(&codec_settings_,
encoder_settings_.value());
if (ret != WEBRTC_VIDEO_CODEC_OK) {
- RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback.";
+ RTC_LOG(LS_ERROR)
+ << "[VESFW] software-encoder fallback initialization failed with"
+ << " error code: " << WebRtcVideoCodecErrorToString(ret);
fallback_encoder_->Release();
return false;
}
@@ -305,6 +309,12 @@ void VideoEncoderSoftwareFallbackWrapper::SetFecControllerOverride(
int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
const VideoCodec* codec_settings,
const VideoEncoder::Settings& settings) {
+ RTC_LOG(LS_INFO) << "[VESFW] " << __func__
+ << "(codec=" << codec_settings->ToString()
+ << ", settings={number_of_cores: "
+ << settings.number_of_cores
+ << ", max_payload_size: " << settings.max_payload_size
+ << "})";
// Store settings, in case we need to dynamically switch to the fallback
// encoder after a failed Encode call.
codec_settings_ = *codec_settings;
@@ -327,6 +337,8 @@ int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
PrimeEncoder(current_encoder());
return ret;
}
+ RTC_LOG(LS_WARNING) << "[VESFW] Hardware encoder initialization failed with"
+ << " error code: " << WebRtcVideoCodecErrorToString(ret);
// Try to instantiate software codec.
if (InitFallbackEncoder(/*is_forced=*/false)) {
@@ -335,6 +347,8 @@ int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
}
// Software encoder failed too, use original return code.
+ RTC_LOG(LS_WARNING)
+ << "[VESFW] Software fallback encoder initialization also failed.";
encoder_state_ = EncoderState::kUninitialized;
return ret;
}
diff --git a/third_party/libwebrtc/audio/BUILD.gn b/third_party/libwebrtc/audio/BUILD.gn
index 7ece107407..8679790903 100644
--- a/third_party/libwebrtc/audio/BUILD.gn
+++ b/third_party/libwebrtc/audio/BUILD.gn
@@ -167,6 +167,8 @@ if (rtc_include_tests) {
"../api:mock_audio_mixer",
"../api:mock_frame_decryptor",
"../api:mock_frame_encryptor",
+ "../api:mock_frame_transformer",
+ "../api:mock_transformable_audio_frame",
"../api:scoped_refptr",
"../api/audio:audio_frame_api",
"../api/audio_codecs:audio_codecs_api",
@@ -210,8 +212,6 @@ if (rtc_include_tests) {
"../system_wrappers",
"../test:audio_codec_mocks",
"../test:field_trial",
- "../test:mock_frame_transformer",
- "../test:mock_transformable_frame",
"../test:mock_transport",
"../test:rtp_test_utils",
"../test:run_loop",
@@ -234,6 +234,7 @@ if (rtc_include_tests) {
sources = [ "channel_receive_unittest.cc" ]
deps = [
":audio",
+ "../api:mock_frame_transformer",
"../api/audio_codecs:builtin_audio_decoder_factory",
"../api/crypto:frame_decryptor_interface",
"../api/task_queue:default_task_queue_factory",
@@ -245,7 +246,6 @@ if (rtc_include_tests) {
"../rtc_base:logging",
"../rtc_base:threading",
"../test:audio_codec_mocks",
- "../test:mock_frame_transformer",
"../test:mock_transport",
"../test:test_support",
"../test/time_controller",
diff --git a/third_party/libwebrtc/audio/audio_send_stream.cc b/third_party/libwebrtc/audio/audio_send_stream.cc
index 8dc78b18fa..64bc15ab4e 100644
--- a/third_party/libwebrtc/audio/audio_send_stream.cc
+++ b/third_party/libwebrtc/audio/audio_send_stream.cc
@@ -157,6 +157,8 @@ AudioSendStream::AudioSendStream(
event_log_(event_log),
use_legacy_overhead_calculation_(
field_trials_.IsEnabled("WebRTC-Audio-LegacyOverhead")),
+ enable_priority_bitrate_(
+ !field_trials_.IsDisabled("WebRTC-Audio-PriorityBitrate")),
bitrate_allocator_(bitrate_allocator),
rtp_transport_(rtp_transport),
rtp_rtcp_module_(channel_send_->GetRtpRtcp()),
@@ -171,7 +173,6 @@ AudioSendStream::AudioSendStream(
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
ConfigureStream(config, true, nullptr);
- UpdateCachedTargetAudioBitrateConstraints();
}
AudioSendStream::~AudioSendStream() {
@@ -324,10 +325,7 @@ void AudioSendStream::ConfigureStream(
}
// Set currently known overhead (used in ANA, opus only).
- {
- MutexLock lock(&overhead_per_packet_lock_);
- UpdateOverheadForEncoder();
- }
+ UpdateOverheadPerPacket();
channel_send_->CallEncoder([this](AudioEncoder* encoder) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
@@ -335,7 +333,7 @@ void AudioSendStream::ConfigureStream(
return;
}
frame_length_range_ = encoder->GetFrameLengthRange();
- UpdateCachedTargetAudioBitrateConstraints();
+ bitrate_range_ = encoder->GetBitrateRange();
});
if (sending_) {
@@ -343,9 +341,6 @@ void AudioSendStream::ConfigureStream(
}
config_ = new_config;
- if (!first_time) {
- UpdateCachedTargetAudioBitrateConstraints();
- }
webrtc::InvokeSetParametersCallback(callback, webrtc::RTCError::OK());
}
@@ -489,30 +484,23 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats(
void AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
channel_send_->ReceivedRTCPPacket(packet, length);
-
- {
- // Poll if overhead has changed, which it can do if ack triggers us to stop
- // sending mid/rid.
- MutexLock lock(&overhead_per_packet_lock_);
- UpdateOverheadForEncoder();
- }
- UpdateCachedTargetAudioBitrateConstraints();
+ // Poll if overhead has changed, which it can do if ack triggers us to stop
+ // sending mid/rid.
+ UpdateOverheadPerPacket();
}
uint32_t AudioSendStream::OnBitrateUpdated(BitrateAllocationUpdate update) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
-
// Pick a target bitrate between the constraints. Overrules the allocator if
// it 1) allocated a bitrate of zero to disable the stream or 2) allocated a
// higher than max to allow for e.g. extra FEC.
- RTC_DCHECK(cached_constraints_.has_value());
- update.target_bitrate.Clamp(cached_constraints_->min,
- cached_constraints_->max);
- update.stable_target_bitrate.Clamp(cached_constraints_->min,
- cached_constraints_->max);
-
+ absl::optional<TargetAudioBitrateConstraints> constraints =
+ GetMinMaxBitrateConstraints();
+ if (constraints) {
+ update.target_bitrate.Clamp(constraints->min, constraints->max);
+ update.stable_target_bitrate.Clamp(constraints->min, constraints->max);
+ }
channel_send_->OnBitrateAllocation(update);
-
// The amount of audio protection is not exposed by the encoder, hence
// always returning 0.
return 0;
@@ -521,41 +509,30 @@ uint32_t AudioSendStream::OnBitrateUpdated(BitrateAllocationUpdate update) {
void AudioSendStream::SetTransportOverhead(
int transport_overhead_per_packet_bytes) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
- {
- MutexLock lock(&overhead_per_packet_lock_);
- transport_overhead_per_packet_bytes_ = transport_overhead_per_packet_bytes;
- UpdateOverheadForEncoder();
- }
- UpdateCachedTargetAudioBitrateConstraints();
+ transport_overhead_per_packet_bytes_ = transport_overhead_per_packet_bytes;
+ UpdateOverheadPerPacket();
}
-void AudioSendStream::UpdateOverheadForEncoder() {
+void AudioSendStream::UpdateOverheadPerPacket() {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
- size_t overhead_per_packet_bytes = GetPerPacketOverheadBytes();
+ size_t overhead_per_packet_bytes =
+ transport_overhead_per_packet_bytes_ +
+ rtp_rtcp_module_->ExpectedPerPacketOverhead();
if (overhead_per_packet_ == overhead_per_packet_bytes) {
return;
}
overhead_per_packet_ = overhead_per_packet_bytes;
-
channel_send_->CallEncoder([&](AudioEncoder* encoder) {
encoder->OnReceivedOverhead(overhead_per_packet_bytes);
});
- if (total_packet_overhead_bytes_ != overhead_per_packet_bytes) {
- total_packet_overhead_bytes_ = overhead_per_packet_bytes;
- if (registered_with_allocator_) {
- ConfigureBitrateObserver();
- }
+ if (registered_with_allocator_) {
+ ConfigureBitrateObserver();
}
}
size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
- MutexLock lock(&overhead_per_packet_lock_);
- return GetPerPacketOverheadBytes();
-}
-
-size_t AudioSendStream::GetPerPacketOverheadBytes() const {
- return transport_overhead_per_packet_bytes_ +
- rtp_rtcp_module_->ExpectedPerPacketOverhead();
+ RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+ return overhead_per_packet_;
}
RtpState AudioSendStream::GetRtpState() const {
@@ -649,13 +626,9 @@ bool AudioSendStream::SetupSendCodec(const Config& new_config) {
}
// Set currently known overhead (used in ANA, opus only).
- // If overhead changes later, it will be updated in UpdateOverheadForEncoder.
- {
- MutexLock lock(&overhead_per_packet_lock_);
- size_t overhead = GetPerPacketOverheadBytes();
- if (overhead > 0) {
- encoder->OnReceivedOverhead(overhead);
- }
+ // If overhead changes later, it will be updated in UpdateOverheadPerPacket.
+ if (overhead_per_packet_ > 0) {
+ encoder->OnReceivedOverhead(overhead_per_packet_);
}
StoreEncoderProperties(encoder->SampleRateHz(), encoder->NumChannels());
@@ -717,18 +690,14 @@ void AudioSendStream::ReconfigureANA(const Config& new_config) {
return;
}
if (new_config.audio_network_adaptor_config) {
- // This lock needs to be acquired before CallEncoder, since it aquires
- // another lock and we need to maintain the same order at all call sites to
- // avoid deadlock.
- MutexLock lock(&overhead_per_packet_lock_);
- size_t overhead = GetPerPacketOverheadBytes();
channel_send_->CallEncoder([&](AudioEncoder* encoder) {
+ RTC_DCHECK_RUN_ON(&worker_thread_checker_);
if (encoder->EnableAudioNetworkAdaptor(
*new_config.audio_network_adaptor_config, event_log_)) {
RTC_LOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
<< new_config.rtp.ssrc;
- if (overhead > 0) {
- encoder->OnReceivedOverhead(overhead);
+ if (overhead_per_packet_ > 0) {
+ encoder->OnReceivedOverhead(overhead_per_packet_);
}
} else {
RTC_LOG(LS_INFO) << "Failed to enable Audio network adaptor on SSRC "
@@ -833,8 +802,7 @@ void AudioSendStream::ConfigureBitrateObserver() {
priority_bitrate += max_overhead;
} else {
RTC_DCHECK(frame_length_range_);
- const DataSize overhead_per_packet =
- DataSize::Bytes(total_packet_overhead_bytes_);
+ const DataSize overhead_per_packet = DataSize::Bytes(overhead_per_packet_);
DataRate min_overhead = overhead_per_packet / frame_length_range_->second;
priority_bitrate += min_overhead;
}
@@ -843,6 +811,10 @@ void AudioSendStream::ConfigureBitrateObserver() {
priority_bitrate = *allocation_settings_.priority_bitrate_raw;
}
+ if (!enable_priority_bitrate_) {
+ priority_bitrate = DataRate::BitsPerSec(0);
+ }
+
bitrate_allocator_->AddObserver(
this,
MediaStreamAllocationConfig{
@@ -878,6 +850,12 @@ AudioSendStream::GetMinMaxBitrateConstraints() const {
if (allocation_settings_.max_bitrate)
constraints.max = *allocation_settings_.max_bitrate;
+ // Use encoder defined bitrate range if available.
+ if (bitrate_range_) {
+ constraints.min = bitrate_range_->first;
+ constraints.max = bitrate_range_->second;
+ }
+
RTC_DCHECK_GE(constraints.min, DataRate::Zero());
RTC_DCHECK_GE(constraints.max, DataRate::Zero());
if (constraints.max < constraints.min) {
@@ -898,10 +876,9 @@ AudioSendStream::GetMinMaxBitrateConstraints() const {
RTC_LOG(LS_WARNING) << "frame_length_range_ is not set";
return absl::nullopt;
}
- const DataSize kOverheadPerPacket =
- DataSize::Bytes(total_packet_overhead_bytes_);
- constraints.min += kOverheadPerPacket / frame_length_range_->second;
- constraints.max += kOverheadPerPacket / frame_length_range_->first;
+ const DataSize overhead_per_packet = DataSize::Bytes(overhead_per_packet_);
+ constraints.min += overhead_per_packet / frame_length_range_->second;
+ constraints.max += overhead_per_packet / frame_length_range_->first;
}
return constraints;
}
@@ -911,14 +888,5 @@ void AudioSendStream::RegisterCngPayloadType(int payload_type,
channel_send_->RegisterCngPayloadType(payload_type, clockrate_hz);
}
-void AudioSendStream::UpdateCachedTargetAudioBitrateConstraints() {
- absl::optional<AudioSendStream::TargetAudioBitrateConstraints>
- new_constraints = GetMinMaxBitrateConstraints();
- if (!new_constraints.has_value()) {
- return;
- }
- cached_constraints_ = new_constraints;
-}
-
} // namespace internal
} // namespace webrtc
diff --git a/third_party/libwebrtc/audio/audio_send_stream.h b/third_party/libwebrtc/audio/audio_send_stream.h
index 09fd712d40..a37c8fd452 100644
--- a/third_party/libwebrtc/audio/audio_send_stream.h
+++ b/third_party/libwebrtc/audio/audio_send_stream.h
@@ -110,8 +110,7 @@ class AudioSendStream final : public webrtc::AudioSendStream,
const voe::ChannelSendInterface* GetChannel() const;
// Returns combined per-packet overhead.
- size_t TestOnlyGetPerPacketOverheadBytes() const
- RTC_LOCKS_EXCLUDED(overhead_per_packet_lock_);
+ size_t TestOnlyGetPerPacketOverheadBytes() const;
private:
class TimedTransport;
@@ -152,19 +151,11 @@ class AudioSendStream final : public webrtc::AudioSendStream,
// Sets per-packet overhead on encoded (for ANA) based on current known values
// of transport and packetization overheads.
- void UpdateOverheadForEncoder()
- RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
-
- // Returns combined per-packet overhead.
- size_t GetPerPacketOverheadBytes() const
- RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
+ void UpdateOverheadPerPacket();
void RegisterCngPayloadType(int payload_type, int clockrate_hz)
RTC_RUN_ON(worker_thread_checker_);
- void UpdateCachedTargetAudioBitrateConstraints()
- RTC_RUN_ON(worker_thread_checker_);
-
Clock* clock_;
const FieldTrialsView& field_trials_;
@@ -182,6 +173,7 @@ class AudioSendStream final : public webrtc::AudioSendStream,
const std::unique_ptr<voe::ChannelSendInterface> channel_send_;
RtcEventLog* const event_log_;
const bool use_legacy_overhead_calculation_;
+ const bool enable_priority_bitrate_;
int encoder_sample_rate_hz_ RTC_GUARDED_BY(worker_thread_checker_) = 0;
size_t encoder_num_channels_ RTC_GUARDED_BY(worker_thread_checker_) = 0;
@@ -193,9 +185,6 @@ class AudioSendStream final : public webrtc::AudioSendStream,
BitrateAllocatorInterface* const bitrate_allocator_
RTC_GUARDED_BY(worker_thread_checker_);
- absl::optional<AudioSendStream::TargetAudioBitrateConstraints>
- cached_constraints_ RTC_GUARDED_BY(worker_thread_checker_) =
- absl::nullopt;
RtpTransportControllerSendInterface* const rtp_transport_;
RtpRtcpInterface* const rtp_rtcp_module_;
@@ -217,19 +206,18 @@ class AudioSendStream final : public webrtc::AudioSendStream,
const std::vector<RtpExtension>& extensions);
static int TransportSeqNumId(const Config& config);
- mutable Mutex overhead_per_packet_lock_;
- size_t overhead_per_packet_ RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
-
// Current transport overhead (ICE, TURN, etc.)
size_t transport_overhead_per_packet_bytes_
- RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
+ RTC_GUARDED_BY(worker_thread_checker_) = 0;
+ // Total overhead, including transport and RTP headers.
+ size_t overhead_per_packet_ RTC_GUARDED_BY(worker_thread_checker_) = 0;
bool registered_with_allocator_ RTC_GUARDED_BY(worker_thread_checker_) =
false;
- size_t total_packet_overhead_bytes_ RTC_GUARDED_BY(worker_thread_checker_) =
- 0;
absl::optional<std::pair<TimeDelta, TimeDelta>> frame_length_range_
RTC_GUARDED_BY(worker_thread_checker_);
+ absl::optional<std::pair<DataRate, DataRate>> bitrate_range_
+ RTC_GUARDED_BY(worker_thread_checker_);
};
} // namespace internal
} // namespace webrtc
diff --git a/third_party/libwebrtc/audio/audio_send_stream_unittest.cc b/third_party/libwebrtc/audio/audio_send_stream_unittest.cc
index c854f734b5..60d87eb080 100644
--- a/third_party/libwebrtc/audio/audio_send_stream_unittest.cc
+++ b/third_party/libwebrtc/audio/audio_send_stream_unittest.cc
@@ -21,6 +21,7 @@
#include "audio/audio_state.h"
#include "audio/conversion.h"
#include "audio/mock_voe_channel_proxy.h"
+#include "call/test/mock_bitrate_allocator.h"
#include "call/test/mock_rtp_transport_controller_send.h"
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "modules/audio_device/include/mock_audio_device.h"
@@ -155,7 +156,6 @@ struct ConfigHelper {
use_null_audio_processing
? nullptr
: rtc::make_ref_counted<NiceMock<MockAudioProcessing>>()),
- bitrate_allocator_(&limit_observer_),
audio_encoder_(nullptr) {
using ::testing::Invoke;
@@ -203,6 +203,7 @@ struct ConfigHelper {
MockRtpRtcpInterface* rtp_rtcp() { return &rtp_rtcp_; }
MockChannelSend* channel_send() { return channel_send_; }
RtpTransportControllerSendInterface* transport() { return &rtp_transport_; }
+ MockBitrateAllocator* bitrate_allocator() { return &bitrate_allocator_; }
static void AddBweToConfig(AudioSendStream::Config* config) {
config->rtp.extensions.push_back(RtpExtension(
@@ -328,7 +329,7 @@ struct ConfigHelper {
::testing::NiceMock<MockRtpTransportControllerSend> rtp_transport_;
::testing::NiceMock<MockRtpRtcpInterface> rtp_rtcp_;
::testing::NiceMock<MockLimitObserver> limit_observer_;
- BitrateAllocator bitrate_allocator_;
+ ::testing::NiceMock<MockBitrateAllocator> bitrate_allocator_;
std::unique_ptr<AudioEncoder> audio_encoder_;
};
@@ -560,8 +561,7 @@ TEST(AudioSendStreamTest, AudioNetworkAdaptorReceivesOverhead) {
InSequence s;
EXPECT_CALL(
*mock_encoder,
- OnReceivedOverhead(Eq(kOverheadPerPacket.bytes<size_t>())))
- .Times(2);
+ OnReceivedOverhead(Eq(kOverheadPerPacket.bytes<size_t>())));
EXPECT_CALL(*mock_encoder,
EnableAudioNetworkAdaptor(StrEq(kAnaConfigString), _))
.WillOnce(Return(true));
@@ -847,7 +847,6 @@ TEST(AudioSendStreamTest, AudioOverheadChanged) {
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
.WillRepeatedly(Return(audio_overhead_per_packet_bytes));
auto send_stream = helper.CreateAudioSendStream();
- auto new_config = helper.config();
BitrateAllocationUpdate update;
update.target_bitrate =
@@ -861,6 +860,8 @@ TEST(AudioSendStreamTest, AudioOverheadChanged) {
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
.WillRepeatedly(Return(audio_overhead_per_packet_bytes + 20));
+ // RTP overhead can only change in response to RTCP or configuration change.
+ send_stream->Reconfigure(helper.config(), nullptr);
EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
send_stream->OnBitrateUpdated(update);
@@ -924,5 +925,65 @@ TEST(AudioSendStreamTest, ReconfigureWithFrameEncryptor) {
send_stream->Reconfigure(new_config, nullptr);
}
}
+
+TEST(AudioSendStreamTest, DefaultsHonorsPriorityBitrate) {
+ ConfigHelper helper(true, true, true);
+ ScopedKeyValueConfig field_trials(helper.field_trials,
+ "WebRTC-Audio-Allocation/prio_rate:20/");
+ auto send_stream = helper.CreateAudioSendStream();
+ EXPECT_CALL(*helper.bitrate_allocator(), AddObserver(send_stream.get(), _))
+ .WillOnce(Invoke(
+ [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
+ EXPECT_EQ(config.priority_bitrate_bps, 20000);
+ }));
+ EXPECT_CALL(*helper.channel_send(), StartSend());
+ send_stream->Start();
+ EXPECT_CALL(*helper.channel_send(), StopSend());
+ send_stream->Stop();
+}
+
+TEST(AudioSendStreamTest, OverridesPriorityBitrate) {
+ ConfigHelper helper(true, true, true);
+ ScopedKeyValueConfig field_trials(helper.field_trials,
+ "WebRTC-Audio-Allocation/prio_rate:20/"
+ "WebRTC-Audio-PriorityBitrate/Disabled/");
+ auto send_stream = helper.CreateAudioSendStream();
+ EXPECT_CALL(*helper.bitrate_allocator(), AddObserver(send_stream.get(), _))
+ .WillOnce(Invoke(
+ [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
+ EXPECT_EQ(config.priority_bitrate_bps, 0);
+ }));
+ EXPECT_CALL(*helper.channel_send(), StartSend());
+ send_stream->Start();
+ EXPECT_CALL(*helper.channel_send(), StopSend());
+ send_stream->Stop();
+}
+
+TEST(AudioSendStreamTest, UseEncoderBitrateRange) {
+ ConfigHelper helper(true, true, true);
+ std::pair<DataRate, DataRate> bitrate_range{DataRate::BitsPerSec(5000),
+ DataRate::BitsPerSec(10000)};
+ EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
+ .WillOnce(Invoke([&](int payload_type, const SdpAudioFormat& format,
+ absl::optional<AudioCodecPairId> codec_pair_id,
+ std::unique_ptr<AudioEncoder>* return_value) {
+ auto mock_encoder = SetupAudioEncoderMock(payload_type, format);
+ EXPECT_CALL(*mock_encoder, GetBitrateRange())
+ .WillRepeatedly(Return(bitrate_range));
+ *return_value = std::move(mock_encoder);
+ }));
+ auto send_stream = helper.CreateAudioSendStream();
+ EXPECT_CALL(*helper.bitrate_allocator(), AddObserver(send_stream.get(), _))
+ .WillOnce(Invoke(
+ [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
+ EXPECT_EQ(config.min_bitrate_bps, bitrate_range.first.bps());
+ EXPECT_EQ(config.max_bitrate_bps, bitrate_range.second.bps());
+ }));
+ EXPECT_CALL(*helper.channel_send(), StartSend());
+ send_stream->Start();
+ EXPECT_CALL(*helper.channel_send(), StopSend());
+ send_stream->Stop();
+}
+
} // namespace test
} // namespace webrtc
diff --git a/third_party/libwebrtc/audio/channel_receive.cc b/third_party/libwebrtc/audio/channel_receive.cc
index aff21fa72a..b743b550ba 100644
--- a/third_party/libwebrtc/audio/channel_receive.cc
+++ b/third_party/libwebrtc/audio/channel_receive.cc
@@ -571,13 +571,6 @@ ChannelReceive::ChannelReceive(
network_thread_checker_.Detach();
- acm_receiver_.ResetInitialDelay();
- acm_receiver_.SetMinimumDelay(0);
- acm_receiver_.SetMaximumDelay(0);
- acm_receiver_.FlushBuffers();
-
- _outputAudioLevel.ResetLevelFullRange();
-
rtp_receive_statistics_->EnableRetransmitDetection(remote_ssrc_, true);
RtpRtcpInterface::Configuration configuration;
configuration.clock = clock;
diff --git a/third_party/libwebrtc/audio/channel_receive_frame_transformer_delegate_unittest.cc b/third_party/libwebrtc/audio/channel_receive_frame_transformer_delegate_unittest.cc
index 8bdf217d5a..a206a09f99 100644
--- a/third_party/libwebrtc/audio/channel_receive_frame_transformer_delegate_unittest.cc
+++ b/third_party/libwebrtc/audio/channel_receive_frame_transformer_delegate_unittest.cc
@@ -13,11 +13,11 @@
#include <memory>
#include <utility>
+#include "api/test/mock_frame_transformer.h"
+#include "api/test/mock_transformable_audio_frame.h"
#include "audio/channel_send_frame_transformer_delegate.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
-#include "test/mock_transformable_frame.h"
namespace webrtc {
namespace {
diff --git a/third_party/libwebrtc/audio/channel_receive_unittest.cc b/third_party/libwebrtc/audio/channel_receive_unittest.cc
index aab8a95d8b..8ca1e9e32b 100644
--- a/third_party/libwebrtc/audio/channel_receive_unittest.cc
+++ b/third_party/libwebrtc/audio/channel_receive_unittest.cc
@@ -14,6 +14,7 @@
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/crypto/frame_decryptor_interface.h"
#include "api/task_queue/default_task_queue_factory.h"
+#include "api/test/mock_frame_transformer.h"
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/audio_device/include/mock_audio_device.h"
@@ -29,7 +30,6 @@
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/mock_audio_decoder_factory.h"
-#include "test/mock_frame_transformer.h"
#include "test/mock_transport.h"
#include "test/time_controller/simulated_time_controller.h"
diff --git a/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate.cc b/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate.cc
index ac32410aed..6d3c011862 100644
--- a/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate.cc
+++ b/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate.cc
@@ -58,7 +58,8 @@ class TransformableOutgoingAudioFrame
absl::optional<uint64_t> absolute_capture_timestamp_ms,
uint32_t ssrc,
std::vector<uint32_t> csrcs,
- const std::string& codec_mime_type)
+ const std::string& codec_mime_type,
+ absl::optional<uint16_t> sequence_number)
: frame_type_(frame_type),
payload_type_(payload_type),
rtp_timestamp_with_offset_(rtp_timestamp_with_offset),
@@ -66,7 +67,8 @@ class TransformableOutgoingAudioFrame
absolute_capture_timestamp_ms_(absolute_capture_timestamp_ms),
ssrc_(ssrc),
csrcs_(std::move(csrcs)),
- codec_mime_type_(codec_mime_type) {}
+ codec_mime_type_(codec_mime_type),
+ sequence_number_(sequence_number) {}
~TransformableOutgoingAudioFrame() override = default;
rtc::ArrayView<const uint8_t> GetData() const override { return payload_; }
void SetData(rtc::ArrayView<const uint8_t> data) override {
@@ -88,7 +90,7 @@ class TransformableOutgoingAudioFrame
}
const absl::optional<uint16_t> SequenceNumber() const override {
- return absl::nullopt;
+ return sequence_number_;
}
void SetRTPTimestamp(uint32_t rtp_timestamp_with_offset) override {
@@ -108,6 +110,7 @@ class TransformableOutgoingAudioFrame
uint32_t ssrc_;
std::vector<uint32_t> csrcs_;
std::string codec_mime_type_;
+ absl::optional<uint16_t> sequence_number_;
};
} // namespace
@@ -155,7 +158,8 @@ void ChannelSendFrameTransformerDelegate::Transform(
std::make_unique<TransformableOutgoingAudioFrame>(
frame_type, payload_type, rtp_timestamp, payload_data, payload_size,
absolute_capture_timestamp_ms, ssrc,
- /*csrcs=*/std::vector<uint32_t>(), codec_mimetype));
+ /*csrcs=*/std::vector<uint32_t>(), codec_mimetype,
+ /*sequence_number=*/absl::nullopt));
}
void ChannelSendFrameTransformerDelegate::OnTransformedFrame(
@@ -203,7 +207,7 @@ std::unique_ptr<TransformableAudioFrameInterface> CloneSenderAudioFrame(
original->GetPayloadType(), original->GetTimestamp(),
original->GetData().data(), original->GetData().size(),
original->AbsoluteCaptureTimestamp(), original->GetSsrc(),
- std::move(csrcs), original->GetMimeType());
+ std::move(csrcs), original->GetMimeType(), original->SequenceNumber());
}
} // namespace webrtc
diff --git a/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate_unittest.cc b/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate_unittest.cc
index 483a2cce78..5c025bb345 100644
--- a/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate_unittest.cc
+++ b/third_party/libwebrtc/audio/channel_send_frame_transformer_delegate_unittest.cc
@@ -15,11 +15,11 @@
#include <vector>
#include "absl/memory/memory.h"
+#include "api/test/mock_frame_transformer.h"
+#include "api/test/mock_transformable_audio_frame.h"
#include "rtc_base/task_queue_for_test.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
-#include "test/mock_transformable_frame.h"
namespace webrtc {
namespace {
@@ -59,7 +59,7 @@ class MockChannelSend {
};
std::unique_ptr<TransformableAudioFrameInterface> CreateMockReceiverFrame(
- std::vector<const uint32_t> csrcs) {
+ const std::vector<uint32_t>& csrcs) {
std::unique_ptr<MockTransformableAudioFrame> mock_frame =
std::make_unique<NiceMock<MockTransformableAudioFrame>>();
rtc::ArrayView<const uint8_t> payload(mock_data);
@@ -68,6 +68,7 @@ std::unique_ptr<TransformableAudioFrameInterface> CreateMockReceiverFrame(
ON_CALL(*mock_frame, GetDirection)
.WillByDefault(Return(TransformableFrameInterface::Direction::kReceiver));
ON_CALL(*mock_frame, GetContributingSources).WillByDefault(Return(csrcs));
+ ON_CALL(*mock_frame, SequenceNumber).WillByDefault(Return(987654321));
return mock_frame;
}
@@ -167,7 +168,7 @@ TEST(ChannelSendFrameTransformerDelegateTest,
delegate->Init();
ASSERT_TRUE(callback);
- std::vector<const uint32_t> csrcs = {123, 234, 345, 456};
+ const std::vector<uint32_t> csrcs = {123, 234, 345, 456};
EXPECT_CALL(mock_channel, SendFrame).Times(0);
EXPECT_CALL(mock_channel, SendFrame(_, 0, 0, ElementsAreArray(mock_data), _,
ElementsAreArray(csrcs)));
@@ -252,6 +253,7 @@ TEST(ChannelSendFrameTransformerDelegateTest, CloningReceiverFrameWithCsrcs) {
ASSERT_NE(frame->GetContributingSources().size(), 0u);
EXPECT_THAT(cloned_frame->GetContributingSources(),
ElementsAreArray(frame->GetContributingSources()));
+ EXPECT_EQ(cloned_frame->SequenceNumber(), frame->SequenceNumber());
}
} // namespace
diff --git a/third_party/libwebrtc/audio/channel_send_unittest.cc b/third_party/libwebrtc/audio/channel_send_unittest.cc
index c86dcefadc..77d8479519 100644
--- a/third_party/libwebrtc/audio/channel_send_unittest.cc
+++ b/third_party/libwebrtc/audio/channel_send_unittest.cc
@@ -17,12 +17,12 @@
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "api/scoped_refptr.h"
+#include "api/test/mock_frame_transformer.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "call/rtp_transport_controller_send.h"
#include "rtc_base/gunit.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
#include "test/mock_transport.h"
#include "test/scoped_key_value_config.h"
#include "test/time_controller/simulated_time_controller.h"
diff --git a/third_party/libwebrtc/call/BUILD.gn b/third_party/libwebrtc/call/BUILD.gn
index 50a8257631..985a3a4e04 100644
--- a/third_party/libwebrtc/call/BUILD.gn
+++ b/third_party/libwebrtc/call/BUILD.gn
@@ -121,6 +121,7 @@ rtc_library("rtp_interfaces") {
"../api/crypto:options",
"../api/environment",
"../api/rtc_event_log",
+ "../api/transport:bandwidth_estimation_settings",
"../api/transport:bitrate_settings",
"../api/transport:network_control",
"../api/units:time_delta",
@@ -495,6 +496,7 @@ if (rtc_include_tests) {
"../api:array_view",
"../api:create_frame_generator",
"../api:mock_audio_mixer",
+ "../api:mock_frame_transformer",
"../api:rtp_headers",
"../api:rtp_parameters",
"../api:transport_api",
@@ -539,7 +541,6 @@ if (rtc_include_tests) {
"../test:fake_video_codecs",
"../test:field_trial",
"../test:frame_generator_capturer",
- "../test:mock_frame_transformer",
"../test:mock_transport",
"../test:run_loop",
"../test:scoped_key_value_config",
diff --git a/third_party/libwebrtc/call/rtp_transport_controller_send.cc b/third_party/libwebrtc/call/rtp_transport_controller_send.cc
index 600d4e2620..32c4addfb9 100644
--- a/third_party/libwebrtc/call/rtp_transport_controller_send.cc
+++ b/third_party/libwebrtc/call/rtp_transport_controller_send.cc
@@ -159,6 +159,37 @@ void RtpTransportControllerSend::DestroyRtpVideoSender(
video_rtp_senders_.erase(it);
}
+void RtpTransportControllerSend::RegisterSendingRtpStream(
+ RtpRtcpInterface& rtp_module) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ // Allow pacer to send packets using this module.
+ packet_router_.AddSendRtpModule(&rtp_module,
+ /*remb_candidate=*/true);
+ pacer_.SetAllowProbeWithoutMediaPacket(
+ bwe_settings_.allow_probe_without_media &&
+ packet_router_.SupportsRtxPayloadPadding());
+}
+
+void RtpTransportControllerSend::DeRegisterSendingRtpStream(
+ RtpRtcpInterface& rtp_module) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ // Disabling media, remove from packet router map to reduce size and
+ // prevent any stray packets in the pacer from asynchronously arriving
+ // to a disabled module.
+ packet_router_.RemoveSendRtpModule(&rtp_module);
+ // Clear the pacer queue of any packets pertaining to this module.
+ pacer_.RemovePacketsForSsrc(rtp_module.SSRC());
+ if (rtp_module.RtxSsrc().has_value()) {
+ pacer_.RemovePacketsForSsrc(*rtp_module.RtxSsrc());
+ }
+ if (rtp_module.FlexfecSsrc().has_value()) {
+ pacer_.RemovePacketsForSsrc(*rtp_module.FlexfecSsrc());
+ }
+ pacer_.SetAllowProbeWithoutMediaPacket(
+ bwe_settings_.allow_probe_without_media &&
+ packet_router_.SupportsRtxPayloadPadding());
+}
+
void RtpTransportControllerSend::UpdateControlState() {
absl::optional<TargetTransferRate> update = control_handler_->GetUpdate();
if (!update)
@@ -224,6 +255,29 @@ RtpTransportControllerSend::GetStreamFeedbackProvider() {
return &feedback_demuxer_;
}
+void RtpTransportControllerSend::ReconfigureBandwidthEstimation(
+ const BandwidthEstimationSettings& settings) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ bwe_settings_ = settings;
+
+ if (controller_) {
+ // Recreate the controller and handler.
+ control_handler_ = nullptr;
+ controller_ = nullptr;
+ // The BWE controller is created when/if the network is available.
+ MaybeCreateControllers();
+ if (controller_) {
+ BitrateConstraints constraints = bitrate_configurator_.GetConfig();
+ UpdateBitrateConstraints(constraints);
+ UpdateStreamsConfig();
+ UpdateNetworkAvailability();
+ }
+ }
+ pacer_.SetAllowProbeWithoutMediaPacket(
+ bwe_settings_.allow_probe_without_media &&
+ packet_router_.SupportsRtxPayloadPadding());
+}
+
void RtpTransportControllerSend::RegisterTargetTransferRateObserver(
TargetTransferRateObserver* observer) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
@@ -325,9 +379,6 @@ void RtpTransportControllerSend::OnNetworkAvailability(bool network_available) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_LOG(LS_VERBOSE) << "SignalNetworkState "
<< (network_available ? "Up" : "Down");
- NetworkAvailability msg;
- msg.at_time = Timestamp::Millis(env_.clock().TimeInMilliseconds());
- msg.network_available = network_available;
network_available_ = network_available;
if (network_available) {
pacer_.Resume();
@@ -340,11 +391,7 @@ void RtpTransportControllerSend::OnNetworkAvailability(bool network_available) {
if (!controller_) {
MaybeCreateControllers();
}
- if (controller_) {
- control_handler_->SetNetworkAvailability(network_available);
- PostUpdates(controller_->OnNetworkAvailability(msg));
- UpdateControlState();
- }
+ UpdateNetworkAvailability();
for (auto& rtp_sender : video_rtp_senders_) {
rtp_sender->OnNetworkAvailability(network_available);
}
@@ -587,6 +634,18 @@ void RtpTransportControllerSend::MaybeCreateControllers() {
StartProcessPeriodicTasks();
}
+void RtpTransportControllerSend::UpdateNetworkAvailability() {
+ if (!controller_) {
+ return;
+ }
+ NetworkAvailability msg;
+ msg.at_time = Timestamp::Millis(env_.clock().TimeInMilliseconds());
+ msg.network_available = network_available_;
+ control_handler_->SetNetworkAvailability(network_available_);
+ PostUpdates(controller_->OnNetworkAvailability(msg));
+ UpdateControlState();
+}
+
void RtpTransportControllerSend::UpdateInitialConstraints(
TargetRateConstraints new_contraints) {
if (!new_contraints.starting_rate)
diff --git a/third_party/libwebrtc/call/rtp_transport_controller_send.h b/third_party/libwebrtc/call/rtp_transport_controller_send.h
index c0bca41a2b..4428336672 100644
--- a/third_party/libwebrtc/call/rtp_transport_controller_send.h
+++ b/third_party/libwebrtc/call/rtp_transport_controller_send.h
@@ -75,6 +75,8 @@ class RtpTransportControllerSend final
RtpVideoSenderInterface* rtp_video_sender) override;
// Implements RtpTransportControllerSendInterface
+ void RegisterSendingRtpStream(RtpRtcpInterface& rtp_module) override;
+ void DeRegisterSendingRtpStream(RtpRtcpInterface& rtp_module) override;
PacketRouter* packet_router() override;
NetworkStateEstimateObserver* network_state_estimate_observer() override;
@@ -82,6 +84,8 @@ class RtpTransportControllerSend final
RtpPacketSender* packet_sender() override;
void SetAllocatedSendBitrateLimits(BitrateAllocationLimits limits) override;
+ void ReconfigureBandwidthEstimation(
+ const BandwidthEstimationSettings& settings) override;
void SetPacingFactor(float pacing_factor) override;
void SetQueueTimeLimit(int limit_ms) override;
@@ -125,6 +129,7 @@ class RtpTransportControllerSend final
private:
void MaybeCreateControllers() RTC_RUN_ON(sequence_checker_);
+ void UpdateNetworkAvailability() RTC_RUN_ON(sequence_checker_);
void UpdateInitialConstraints(TargetRateConstraints new_contraints)
RTC_RUN_ON(sequence_checker_);
@@ -155,6 +160,7 @@ class RtpTransportControllerSend final
RtpBitrateConfigurator bitrate_configurator_;
std::map<std::string, rtc::NetworkRoute> network_routes_
RTC_GUARDED_BY(sequence_checker_);
+ BandwidthEstimationSettings bwe_settings_ RTC_GUARDED_BY(sequence_checker_);
bool pacer_started_ RTC_GUARDED_BY(sequence_checker_);
TaskQueuePacedSender pacer_;
diff --git a/third_party/libwebrtc/call/rtp_transport_controller_send_interface.h b/third_party/libwebrtc/call/rtp_transport_controller_send_interface.h
index 7edc135037..c4b1536bad 100644
--- a/third_party/libwebrtc/call/rtp_transport_controller_send_interface.h
+++ b/third_party/libwebrtc/call/rtp_transport_controller_send_interface.h
@@ -24,6 +24,7 @@
#include "api/fec_controller.h"
#include "api/frame_transformer_interface.h"
#include "api/rtc_event_log/rtc_event_log.h"
+#include "api/transport/bandwidth_estimation_settings.h"
#include "api/transport/bitrate_settings.h"
#include "api/units/timestamp.h"
#include "call/rtp_config.h"
@@ -47,6 +48,7 @@ class Transport;
class PacketRouter;
class RtpVideoSenderInterface;
class RtpPacketSender;
+class RtpRtcpInterface;
struct RtpSenderObservers {
RtcpRttStats* rtcp_rtt_stats;
@@ -108,6 +110,12 @@ class RtpTransportControllerSendInterface {
virtual void DestroyRtpVideoSender(
RtpVideoSenderInterface* rtp_video_sender) = 0;
+ // Register a specific RTP stream as sending. This means that the pacer and
+ // packet router can send packets using this RTP stream.
+ virtual void RegisterSendingRtpStream(RtpRtcpInterface& rtp_module) = 0;
+ // Pacer and PacketRouter stop using this RTP stream.
+ virtual void DeRegisterSendingRtpStream(RtpRtcpInterface& rtp_module) = 0;
+
virtual NetworkStateEstimateObserver* network_state_estimate_observer() = 0;
virtual TransportFeedbackObserver* transport_feedback_observer() = 0;
@@ -118,6 +126,9 @@ class RtpTransportControllerSendInterface {
virtual void SetAllocatedSendBitrateLimits(
BitrateAllocationLimits limits) = 0;
+ virtual void ReconfigureBandwidthEstimation(
+ const BandwidthEstimationSettings& settings) = 0;
+
virtual void SetPacingFactor(float pacing_factor) = 0;
virtual void SetQueueTimeLimit(int limit_ms) = 0;
diff --git a/third_party/libwebrtc/call/rtp_video_sender.cc b/third_party/libwebrtc/call/rtp_video_sender.cc
index 4d99c61bb4..ac5540a7f2 100644
--- a/third_party/libwebrtc/call/rtp_video_sender.cc
+++ b/third_party/libwebrtc/call/rtp_video_sender.cc
@@ -470,86 +470,42 @@ RtpVideoSender::RtpVideoSender(
}
RtpVideoSender::~RtpVideoSender() {
- // TODO(bugs.webrtc.org/13517): Remove once RtpVideoSender gets deleted on the
- // transport task queue.
- transport_checker_.Detach();
-
+ RTC_DCHECK_RUN_ON(&transport_checker_);
SetActiveModulesLocked(
- std::vector<bool>(rtp_streams_.size(), /*active=*/false));
-
- RTC_DCHECK(!registered_for_feedback_);
+ /*sending=*/false);
}
-void RtpVideoSender::Stop() {
+void RtpVideoSender::SetSending(bool enabled) {
RTC_DCHECK_RUN_ON(&transport_checker_);
MutexLock lock(&mutex_);
- if (!active_)
+ if (enabled == active_) {
return;
-
- const std::vector<bool> active_modules(rtp_streams_.size(), false);
- SetActiveModulesLocked(active_modules);
-}
-
-void RtpVideoSender::SetActiveModules(const std::vector<bool>& active_modules) {
- RTC_DCHECK_RUN_ON(&transport_checker_);
- MutexLock lock(&mutex_);
- return SetActiveModulesLocked(active_modules);
+ }
+ SetActiveModulesLocked(/*sending=*/enabled);
}
-void RtpVideoSender::SetActiveModulesLocked(
- const std::vector<bool>& active_modules) {
+void RtpVideoSender::SetActiveModulesLocked(bool sending) {
RTC_DCHECK_RUN_ON(&transport_checker_);
- RTC_CHECK_EQ(rtp_streams_.size(), active_modules.size());
- active_ = false;
- for (size_t i = 0; i < active_modules.size(); ++i) {
- if (active_modules[i]) {
- active_ = true;
- }
-
+ if (active_ == sending) {
+ return;
+ }
+ active_ = sending;
+ for (size_t i = 0; i < rtp_streams_.size(); ++i) {
RtpRtcpInterface& rtp_module = *rtp_streams_[i].rtp_rtcp;
- const bool was_active = rtp_module.Sending();
- const bool should_be_active = active_modules[i];
-
// Sends a kRtcpByeCode when going from true to false.
- rtp_module.SetSendingStatus(active_modules[i]);
-
- if (was_active && !should_be_active) {
- // Disabling media, remove from packet router map to reduce size and
- // prevent any stray packets in the pacer from asynchronously arriving
- // to a disabled module.
- transport_->packet_router()->RemoveSendRtpModule(&rtp_module);
-
- // Clear the pacer queue of any packets pertaining to this module.
- transport_->packet_sender()->RemovePacketsForSsrc(rtp_module.SSRC());
- if (rtp_module.RtxSsrc().has_value()) {
- transport_->packet_sender()->RemovePacketsForSsrc(
- *rtp_module.RtxSsrc());
- }
- if (rtp_module.FlexfecSsrc().has_value()) {
- transport_->packet_sender()->RemovePacketsForSsrc(
- *rtp_module.FlexfecSsrc());
- }
- }
-
- // If set to false this module won't send media.
- rtp_module.SetSendingMediaStatus(active_modules[i]);
-
- if (!was_active && should_be_active) {
- // Turning on media, register with packet router.
- transport_->packet_router()->AddSendRtpModule(&rtp_module,
- /*remb_candidate=*/true);
+ rtp_module.SetSendingStatus(sending);
+ rtp_module.SetSendingMediaStatus(sending);
+ if (sending) {
+ transport_->RegisterSendingRtpStream(rtp_module);
+ } else {
+ transport_->DeRegisterSendingRtpStream(rtp_module);
}
}
- if (!active_) {
- auto* feedback_provider = transport_->GetStreamFeedbackProvider();
- if (registered_for_feedback_) {
- feedback_provider->DeRegisterStreamFeedbackObserver(this);
- registered_for_feedback_ = false;
- }
- } else if (!registered_for_feedback_) {
- auto* feedback_provider = transport_->GetStreamFeedbackProvider();
+ auto* feedback_provider = transport_->GetStreamFeedbackProvider();
+ if (!sending) {
+ feedback_provider->DeRegisterStreamFeedbackObserver(this);
+ } else {
feedback_provider->RegisterStreamFeedbackObserver(rtp_config_.ssrcs, this);
- registered_for_feedback_ = true;
}
}
diff --git a/third_party/libwebrtc/call/rtp_video_sender.h b/third_party/libwebrtc/call/rtp_video_sender.h
index 10b0d19d05..957b46e560 100644
--- a/third_party/libwebrtc/call/rtp_video_sender.h
+++ b/third_party/libwebrtc/call/rtp_video_sender.h
@@ -95,11 +95,7 @@ class RtpVideoSender : public RtpVideoSenderInterface,
RtpVideoSender(const RtpVideoSender&) = delete;
RtpVideoSender& operator=(const RtpVideoSender&) = delete;
- // Sets the sending status of the rtp modules and appropriately sets the
- // payload router to active if any rtp modules are active.
- void SetActiveModules(const std::vector<bool>& active_modules)
- RTC_LOCKS_EXCLUDED(mutex_) override;
- void Stop() RTC_LOCKS_EXCLUDED(mutex_) override;
+ void SetSending(bool enabled) RTC_LOCKS_EXCLUDED(mutex_) override;
bool IsActive() RTC_LOCKS_EXCLUDED(mutex_) override;
void OnNetworkAvailability(bool network_available)
@@ -160,7 +156,7 @@ class RtpVideoSender : public RtpVideoSenderInterface,
private:
bool IsActiveLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
- void SetActiveModulesLocked(const std::vector<bool>& active_modules)
+ void SetActiveModulesLocked(bool sending)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void UpdateModuleSendingState() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void ConfigureProtection();
@@ -184,7 +180,6 @@ class RtpVideoSender : public RtpVideoSenderInterface,
// transport task queue.
mutable Mutex mutex_;
bool active_ RTC_GUARDED_BY(mutex_);
- bool registered_for_feedback_ RTC_GUARDED_BY(transport_checker_) = false;
const std::unique_ptr<FecController> fec_controller_;
bool fec_allowed_ RTC_GUARDED_BY(mutex_);
diff --git a/third_party/libwebrtc/call/rtp_video_sender_interface.h b/third_party/libwebrtc/call/rtp_video_sender_interface.h
index 3f2877155a..6bbcb7f46e 100644
--- a/third_party/libwebrtc/call/rtp_video_sender_interface.h
+++ b/third_party/libwebrtc/call/rtp_video_sender_interface.h
@@ -31,12 +31,8 @@ struct FecProtectionParams;
class RtpVideoSenderInterface : public EncodedImageCallback,
public FecControllerOverride {
public:
- // Sets the sending status of the rtp modules and appropriately sets the
- // RtpVideoSender to active if any rtp modules are active.
- // A module will only send packet if beeing active.
- virtual void SetActiveModules(const std::vector<bool>& active_modules) = 0;
- // Set the sending status of all rtp modules to inactive.
- virtual void Stop() = 0;
+ // Sets weather or not RTP packets is allowed to be sent on this sender.
+ virtual void SetSending(bool enabled) = 0;
virtual bool IsActive() = 0;
virtual void OnNetworkAvailability(bool network_available) = 0;
diff --git a/third_party/libwebrtc/call/rtp_video_sender_unittest.cc b/third_party/libwebrtc/call/rtp_video_sender_unittest.cc
index cf099afaa3..cd525f0d61 100644
--- a/third_party/libwebrtc/call/rtp_video_sender_unittest.cc
+++ b/third_party/libwebrtc/call/rtp_video_sender_unittest.cc
@@ -18,6 +18,7 @@
#include "absl/functional/any_invocable.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
+#include "api/test/mock_frame_transformer.h"
#include "call/rtp_transport_controller_send.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/byte_io.h"
@@ -29,7 +30,6 @@
#include "rtc_base/rate_limiter.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
#include "test/mock_transport.h"
#include "test/scenario/scenario.h"
#include "test/scoped_key_value_config.h"
@@ -180,17 +180,13 @@ class RtpVideoSenderTestFixture {
/*frame_transformer=*/nullptr,
field_trials) {}
- ~RtpVideoSenderTestFixture() { Stop(); }
+ ~RtpVideoSenderTestFixture() { SetSending(false); }
RtpVideoSender* router() { return router_.get(); }
MockTransport& transport() { return transport_; }
void AdvanceTime(TimeDelta delta) { time_controller_.AdvanceTime(delta); }
- void Stop() { router_->Stop(); }
-
- void SetActiveModules(const std::vector<bool>& active_modules) {
- router_->SetActiveModules(active_modules);
- }
+ void SetSending(bool sending) { router_->SetSending(sending); }
private:
test::ScopedKeyValueConfig field_trials_;
@@ -227,20 +223,20 @@ TEST(RtpVideoSenderTest, SendOnOneModule) {
EXPECT_NE(EncodedImageCallback::Result::OK,
test.router()->OnEncodedImage(encoded_image, nullptr).error);
- test.SetActiveModules({true});
+ test.SetSending(true);
EXPECT_EQ(EncodedImageCallback::Result::OK,
test.router()->OnEncodedImage(encoded_image, nullptr).error);
- test.SetActiveModules({false});
+ test.SetSending(false);
EXPECT_NE(EncodedImageCallback::Result::OK,
test.router()->OnEncodedImage(encoded_image, nullptr).error);
- test.SetActiveModules({true});
+ test.SetSending(true);
EXPECT_EQ(EncodedImageCallback::Result::OK,
test.router()->OnEncodedImage(encoded_image, nullptr).error);
}
-TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
+TEST(RtpVideoSenderTest, OnEncodedImageReturnOkWhenSendingTrue) {
constexpr uint8_t kPayload = 'a';
EncodedImage encoded_image_1;
encoded_image_1.SetRtpTimestamp(1);
@@ -254,7 +250,7 @@ TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
CodecSpecificInfo codec_info;
codec_info.codecType = kVideoCodecVP8;
- test.SetActiveModules({true, true});
+ test.SetSending(true);
EXPECT_EQ(EncodedImageCallback::Result::OK,
test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
@@ -262,20 +258,9 @@ TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
encoded_image_2.SetSimulcastIndex(1);
EXPECT_EQ(EncodedImageCallback::Result::OK,
test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
-
- // Inactive.
- test.Stop();
- EXPECT_NE(EncodedImageCallback::Result::OK,
- test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
- EXPECT_NE(EncodedImageCallback::Result::OK,
- test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
}
-// Tests how setting individual rtp modules to active affects the overall
-// behavior of the payload router. First sets one module to active and checks
-// that outgoing data can be sent on this module, and checks that no data can
-// be sent if both modules are inactive.
-TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
+TEST(RtpVideoSenderTest, OnEncodedImageReturnErrorCodeWhenSendingFalse) {
constexpr uint8_t kPayload = 'a';
EncodedImage encoded_image_1;
encoded_image_1.SetRtpTimestamp(1);
@@ -291,23 +276,15 @@ TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
CodecSpecificInfo codec_info;
codec_info.codecType = kVideoCodecVP8;
- // Only setting one stream to active will still set the payload router to
- // active and allow sending data on the active stream.
- std::vector<bool> active_modules({true, false});
- test.SetActiveModules(active_modules);
- EXPECT_EQ(EncodedImageCallback::Result::OK,
- test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
-
- // Setting both streams to inactive will turn the payload router to
+ // Setting rtp streams to inactive will turn the payload router to
// inactive.
- active_modules = {false, false};
- test.SetActiveModules(active_modules);
+ test.SetSending(false);
// An incoming encoded image will not ask the module to send outgoing data
// because the payload router is inactive.
EXPECT_NE(EncodedImageCallback::Result::OK,
test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
EXPECT_NE(EncodedImageCallback::Result::OK,
- test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
+ test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
}
TEST(RtpVideoSenderTest,
@@ -324,7 +301,7 @@ TEST(RtpVideoSenderTest,
codec_info.codecType = kVideoCodecVP8;
RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
kPayloadType, {});
- test.SetActiveModules({true, true});
+ test.SetSending(true);
// A layer is sent on both rtp streams.
test.router()->OnVideoLayersAllocationUpdated(
{.active_spatial_layers = {{.rtp_stream_index = 0},
@@ -347,7 +324,7 @@ TEST(RtpVideoSenderTest,
TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) {
RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
kPayloadType, {});
- test.SetActiveModules({true, true});
+ test.SetSending(true);
std::map<uint32_t, RtpPayloadState> initial_states =
test.router()->GetRtpPayloadStates();
@@ -372,7 +349,7 @@ TEST(RtpVideoSenderTest, CreateWithPreviousStates) {
RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
kPayloadType, states);
- test.SetActiveModules({true, true});
+ test.SetSending(true);
std::map<uint32_t, RtpPayloadState> initial_states =
test.router()->GetRtpPayloadStates();
@@ -412,7 +389,7 @@ TEST(RtpVideoSenderTest, FrameCountCallbacks) {
test.router()->OnEncodedImage(encoded_image, nullptr).error);
::testing::Mock::VerifyAndClearExpectations(&callback);
- test.SetActiveModules({true});
+ test.SetSending(true);
FrameCounts frame_counts;
EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
@@ -441,7 +418,7 @@ TEST(RtpVideoSenderTest, FrameCountCallbacks) {
TEST(RtpVideoSenderTest, DoesNotRetrasmitAckedPackets) {
RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
kPayloadType, {});
- test.SetActiveModules({true, true});
+ test.SetSending(true);
constexpr uint8_t kPayload = 'a';
EncodedImage encoded_image;
@@ -606,7 +583,7 @@ TEST(RtpVideoSenderTest, RetransmitsOnTransportWideLossInfo) {
TEST(RtpVideoSenderTest, EarlyRetransmits) {
RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
kPayloadType, {});
- test.SetActiveModules({true, true});
+ test.SetSending(true);
const uint8_t kPayload[1] = {'a'};
EncodedImage encoded_image;
@@ -701,7 +678,7 @@ TEST(RtpVideoSenderTest, EarlyRetransmits) {
TEST(RtpVideoSenderTest, SupportsDependencyDescriptor) {
RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
- test.SetActiveModules({true});
+ test.SetSending(true);
RtpHeaderExtensionMap extensions;
extensions.Register<RtpDependencyDescriptorExtension>(
@@ -773,7 +750,7 @@ TEST(RtpVideoSenderTest,
EXPECT_TRUE(sent_packets.emplace_back(&extensions).Parse(packet));
return true;
});
- test.SetActiveModules({true});
+ test.SetSending(true);
EncodedImage key_frame_image;
key_frame_image._frameType = VideoFrameType::kVideoFrameKey;
@@ -807,7 +784,7 @@ TEST(RtpVideoSenderTest,
TEST(RtpVideoSenderTest, SupportsDependencyDescriptorForVp9) {
RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
- test.SetActiveModules({true});
+ test.SetSending(true);
RtpHeaderExtensionMap extensions;
extensions.Register<RtpDependencyDescriptorExtension>(
@@ -863,7 +840,7 @@ TEST(RtpVideoSenderTest, SupportsDependencyDescriptorForVp9) {
TEST(RtpVideoSenderTest,
SupportsDependencyDescriptorForVp9NotProvidedByEncoder) {
RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
- test.SetActiveModules({true});
+ test.SetSending(true);
RtpHeaderExtensionMap extensions;
extensions.Register<RtpDependencyDescriptorExtension>(
@@ -918,7 +895,7 @@ TEST(RtpVideoSenderTest, GenerateDependecyDescriptorForGenericCodecs) {
test::ScopedKeyValueConfig field_trials(
"WebRTC-GenericCodecDependencyDescriptor/Enabled/");
RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {}, &field_trials);
- test.SetActiveModules({true});
+ test.SetSending(true);
RtpHeaderExtensionMap extensions;
extensions.Register<RtpDependencyDescriptorExtension>(
@@ -964,7 +941,7 @@ TEST(RtpVideoSenderTest, GenerateDependecyDescriptorForGenericCodecs) {
TEST(RtpVideoSenderTest, SupportsStoppingUsingDependencyDescriptor) {
RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
- test.SetActiveModules({true});
+ test.SetSending(true);
RtpHeaderExtensionMap extensions;
extensions.Register<RtpDependencyDescriptorExtension>(
@@ -1049,7 +1026,7 @@ TEST(RtpVideoSenderTest, OverheadIsSubtractedFromTargetBitrate) {
kRtpHeaderSizeBytes + kTransportPacketOverheadBytes;
RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {}, &field_trials);
test.router()->OnTransportOverheadChanged(kTransportPacketOverheadBytes);
- test.SetActiveModules({true});
+ test.SetSending(true);
{
test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(300000),
@@ -1076,7 +1053,7 @@ TEST(RtpVideoSenderTest, OverheadIsSubtractedFromTargetBitrate) {
TEST(RtpVideoSenderTest, ClearsPendingPacketsOnInactivation) {
RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
- test.SetActiveModules({true});
+ test.SetSending(true);
RtpHeaderExtensionMap extensions;
extensions.Register<RtpDependencyDescriptorExtension>(
@@ -1127,13 +1104,13 @@ TEST(RtpVideoSenderTest, ClearsPendingPacketsOnInactivation) {
// Disable the sending module and advance time slightly. No packets should be
// sent.
- test.SetActiveModules({false});
+ test.SetSending(false);
test.AdvanceTime(TimeDelta::Millis(20));
EXPECT_TRUE(sent_packets.empty());
// Reactive the send module - any packets should have been removed, so nothing
// should be transmitted.
- test.SetActiveModules({true});
+ test.SetSending(true);
test.AdvanceTime(TimeDelta::Millis(33));
EXPECT_TRUE(sent_packets.empty());
@@ -1156,7 +1133,7 @@ TEST(RtpVideoSenderTest, ClearsPendingPacketsOnInactivation) {
TEST(RtpVideoSenderTest, RetransmitsBaseLayerOnly) {
RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
kPayloadType, {});
- test.SetActiveModules({true, true});
+ test.SetSending(true);
test.router()->SetRetransmissionMode(kRetransmitBaseLayer);
constexpr uint8_t kPayload = 'a';
diff --git a/third_party/libwebrtc/call/test/mock_rtp_transport_controller_send.h b/third_party/libwebrtc/call/test/mock_rtp_transport_controller_send.h
index b24e5a59ec..63f686eb3c 100644
--- a/third_party/libwebrtc/call/test/mock_rtp_transport_controller_send.h
+++ b/third_party/libwebrtc/call/test/mock_rtp_transport_controller_send.h
@@ -50,6 +50,11 @@ class MockRtpTransportControllerSend
DestroyRtpVideoSender,
(RtpVideoSenderInterface*),
(override));
+ MOCK_METHOD(void, RegisterSendingRtpStream, (RtpRtcpInterface&), (override));
+ MOCK_METHOD(void,
+ DeRegisterSendingRtpStream,
+ (RtpRtcpInterface&),
+ (override));
MOCK_METHOD(PacketRouter*, packet_router, (), (override));
MOCK_METHOD(NetworkStateEstimateObserver*,
network_state_estimate_observer,
@@ -64,6 +69,10 @@ class MockRtpTransportControllerSend
SetAllocatedSendBitrateLimits,
(BitrateAllocationLimits),
(override));
+ MOCK_METHOD(void,
+ ReconfigureBandwidthEstimation,
+ (const BandwidthEstimationSettings&),
+ (override));
MOCK_METHOD(void, SetPacingFactor, (float), (override));
MOCK_METHOD(void, SetQueueTimeLimit, (int), (override));
MOCK_METHOD(StreamFeedbackProvider*,
diff --git a/third_party/libwebrtc/call/version.cc b/third_party/libwebrtc/call/version.cc
index 85fdf004ea..9b1f88ad87 100644
--- a/third_party/libwebrtc/call/version.cc
+++ b/third_party/libwebrtc/call/version.cc
@@ -13,7 +13,7 @@
namespace webrtc {
// The timestamp is always in UTC.
-const char* const kSourceTimestamp = "WebRTC source stamp 2024-01-21T04:12:31";
+const char* const kSourceTimestamp = "WebRTC source stamp 2024-02-18T04:06:34";
void LoadWebRTCVersionInRegister() {
// Using volatile to instruct the compiler to not optimize `p` away even
diff --git a/third_party/libwebrtc/call/video_send_stream.h b/third_party/libwebrtc/call/video_send_stream.h
index 2b4ea5b66a..ca900823c8 100644
--- a/third_party/libwebrtc/call/video_send_stream.h
+++ b/third_party/libwebrtc/call/video_send_stream.h
@@ -212,20 +212,8 @@ class VideoSendStream {
Config(const Config&);
};
- // Updates the sending state for all simulcast layers that the video send
- // stream owns. This can mean updating the activity one or for multiple
- // layers. The ordering of active layers is the order in which the
- // rtp modules are stored in the VideoSendStream.
- // Note: This starts stream activity if it is inactive and one of the layers
- // is active. This stops stream activity if it is active and all layers are
- // inactive.
- // `active_layers` should have the same size as the number of configured
- // simulcast layers or one if only one rtp stream is used.
- virtual void StartPerRtpStream(std::vector<bool> active_layers) = 0;
-
// Starts stream activity.
// When a stream is active, it can receive, process and deliver packets.
- // Prefer to use StartPerRtpStream.
virtual void Start() = 0;
// Stops stream activity.
@@ -234,11 +222,8 @@ class VideoSendStream {
// Accessor for determining if the stream is active. This is an inexpensive
// call that must be made on the same thread as `Start()` and `Stop()` methods
- // are called on and will return `true` iff activity has been started either
- // via `Start()` or `StartPerRtpStream()`. If activity is either
- // stopped or is in the process of being stopped as a result of a call to
- // either `Stop()` or `StartPerRtpStream()` where all layers were
- // deactivated, the return value will be `false`.
+ // are called on and will return `true` iff activity has been started
+ // via `Start()`.
virtual bool started() = 0;
// If the resource is overusing, the VideoSendStream will try to reduce
diff --git a/third_party/libwebrtc/common_audio/wav_file_unittest.cc b/third_party/libwebrtc/common_audio/wav_file_unittest.cc
index 97cecc345f..71e4fedf94 100644
--- a/third_party/libwebrtc/common_audio/wav_file_unittest.cc
+++ b/third_party/libwebrtc/common_audio/wav_file_unittest.cc
@@ -35,7 +35,8 @@ static const float kSamples[] = {0.0, 10.0, 4e4, -1e9};
// Write a tiny WAV file with the C++ interface and verify the result.
TEST(WavWriterTest, MAYBE_CPP) {
- const std::string outfile = test::OutputPath() + "wavtest1.wav";
+ const std::string outfile =
+ test::OutputPathWithRandomDirectory() + "wavtest1.wav";
static const size_t kNumSamples = 3;
{
WavWriter w(outfile, 14099, 1);
@@ -112,7 +113,8 @@ TEST(WavWriterTest, LargeFile) {
{WavFile::SampleFormat::kInt16, WavFile::SampleFormat::kFloat}) {
for (WavFile::SampleFormat read_format :
{WavFile::SampleFormat::kInt16, WavFile::SampleFormat::kFloat}) {
- std::string outfile = test::OutputPath() + "wavtest3.wav";
+ std::string outfile =
+ test::OutputPathWithRandomDirectory() + "wavtest3.wav";
float samples[kNumSamples];
for (size_t i = 0; i < kNumSamples; i += kNumChannels) {
// A nice periodic beeping sound.
@@ -177,7 +179,8 @@ TEST(WavWriterTest, LargeFile) {
// Write a tiny WAV file with the C++ interface then read-reset-read.
TEST(WavReaderTest, MAYBE_CPPReset) {
- const std::string outfile = test::OutputPath() + "wavtest4.wav";
+ const std::string outfile =
+ test::OutputPathWithRandomDirectory() + "wavtest4.wav";
static const size_t kNumSamples = 3;
{
WavWriter w(outfile, 14099, 1);
diff --git a/third_party/libwebrtc/common_video/h265/h265_bitstream_parser.cc b/third_party/libwebrtc/common_video/h265/h265_bitstream_parser.cc
index f270f228c1..9247d5d272 100644
--- a/third_party/libwebrtc/common_video/h265/h265_bitstream_parser.cc
+++ b/third_party/libwebrtc/common_video/h265/h265_bitstream_parser.cc
@@ -531,8 +531,7 @@ absl::optional<int> H265BitstreamParser::GetLastSliceQp() const {
if (!last_slice_qp_delta_ || !last_slice_pps_id_) {
return absl::nullopt;
}
- uint32_t pps_id = 0;
- const H265PpsParser::PpsState* pps = GetPPS(pps_id);
+ const H265PpsParser::PpsState* pps = GetPPS(last_slice_pps_id_.value());
if (!pps)
return absl::nullopt;
const int parsed_qp = 26 + pps->init_qp_minus26 + *last_slice_qp_delta_;
diff --git a/third_party/libwebrtc/common_video/h265/h265_common.h b/third_party/libwebrtc/common_video/h265/h265_common.h
index 643726f701..d32de7f059 100644
--- a/third_party/libwebrtc/common_video/h265/h265_common.h
+++ b/third_party/libwebrtc/common_video/h265/h265_common.h
@@ -55,11 +55,15 @@ enum NaluType : uint8_t {
kAud = 35,
kPrefixSei = 39,
kSuffixSei = 40,
+ // Aggregation packets, refer to section 4.4.2 in RFC 7798.
kAp = 48,
- kFu = 49
+ // Fragmentation units, refer to section 4.4.3 in RFC 7798.
+ kFu = 49,
+ // PACI packets, refer to section 4.4.4 in RFC 7798.
+ kPaci = 50
};
-// Slice type definition. See table 7-7 of the H265 spec
+// Slice type definition. See table 7-7 of the H.265 spec
enum SliceType : uint8_t { kB = 0, kP = 1, kI = 2 };
struct NaluIndex {
@@ -78,7 +82,7 @@ std::vector<NaluIndex> FindNaluIndices(const uint8_t* buffer,
// Get the NAL type from the header byte immediately following start sequence.
NaluType ParseNaluType(uint8_t data);
-// Methods for parsing and writing RBSP. See section 7.4.2 of the H265 spec.
+// Methods for parsing and writing RBSP. See section 7.4.2 of the H.265 spec.
//
// The following sequences are illegal, and need to be escaped when encoding:
// 00 00 00 -> 00 00 03 00
diff --git a/third_party/libwebrtc/examples/BUILD.gn b/third_party/libwebrtc/examples/BUILD.gn
index 4ace29bb7e..941d62c962 100644
--- a/third_party/libwebrtc/examples/BUILD.gn
+++ b/third_party/libwebrtc/examples/BUILD.gn
@@ -702,6 +702,8 @@ if (is_linux || is_chromeos || is_win) {
"../api/video_codecs:video_codecs_api",
"../media:media_channel",
"../media:rtc_media_base",
+ "../p2p:connection",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
"../pc:video_track_source",
"../rtc_base:async_dns_resolver",
@@ -808,7 +810,9 @@ if (is_linux || is_chromeos || is_win) {
sources = [ "turnserver/turnserver_main.cc" ]
deps = [
":read_auth_file",
+ "../p2p:basic_packet_socket_factory",
"../p2p:p2p_server_utils",
+ "../p2p:port_interface",
"../p2p:rtc_p2p",
"../pc:rtc_pc",
"../rtc_base:async_udp_socket",
@@ -949,6 +953,7 @@ if (!build_with_chromium) {
testonly = true
sources = [ "stunprober/main.cc" ]
deps = [
+ "../p2p:basic_packet_socket_factory",
"../p2p:libstunprober",
"../p2p:rtc_p2p",
"../rtc_base:checks",
diff --git a/third_party/libwebrtc/experiments/field_trials.py b/third_party/libwebrtc/experiments/field_trials.py
index 4aa9bcbe4b..0273f89057 100755
--- a/third_party/libwebrtc/experiments/field_trials.py
+++ b/third_party/libwebrtc/experiments/field_trials.py
@@ -47,9 +47,18 @@ ACTIVE_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([
FieldTrial('WebRTC-Audio-GainController2',
'webrtc:7494',
date(2024, 4, 1)),
+ FieldTrial('WebRTC-Audio-NetEqFecDelayAdaptation',
+ 'webrtc:13322',
+ date(2024, 4, 1)),
FieldTrial('WebRTC-Audio-OpusSetSignalVoiceWithDtx',
'webrtc:4559',
date(2024, 4, 1)),
+ FieldTrial('WebRTC-Audio-OpusGeneratePlc',
+ 'webrtc:13322',
+ date(2024, 4, 1)),
+ FieldTrial('WebRTC-Audio-PriorityBitrate',
+ 'webrtc:15769',
+ date(2024, 4, 1)),
FieldTrial('WebRTC-AV1-OverridePriorityBitrate',
'webrtc:15763',
date(2024, 4, 1)),
@@ -83,6 +92,12 @@ ACTIVE_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([
FieldTrial('WebRTC-LibaomAv1Encoder-DisableFrameDropping',
'webrtc:15225',
date(2024, 4, 1)),
+ FieldTrial('WebRTC-LibaomAv1Encoder-MaxConsecFrameDrop',
+ 'webrtc:15821',
+ date(2024, 4, 1)),
+ FieldTrial('WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig',
+ 'webrtc:15827',
+ date(2024, 9, 1)),
FieldTrial('WebRTC-Pacer-FastRetransmissions',
'chromium:1354491',
date(2024, 4, 1)),
diff --git a/third_party/libwebrtc/infra/specs/client.webrtc.json b/third_party/libwebrtc/infra/specs/client.webrtc.json
index 4d53f6de9d..c38b68b0d3 100644
--- a/third_party/libwebrtc/infra/specs/client.webrtc.json
+++ b/third_party/libwebrtc/infra/specs/client.webrtc.json
@@ -1864,7 +1864,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -1888,7 +1888,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -1912,7 +1912,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -1936,7 +1936,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -1960,7 +1960,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -1984,7 +1984,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -2008,7 +2008,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -2033,7 +2033,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -2057,7 +2057,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -2082,7 +2082,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -2106,7 +2106,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -2127,7 +2127,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -3865,7 +3865,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -3882,7 +3882,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -3899,7 +3899,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -3916,7 +3916,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -3933,7 +3933,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -3951,7 +3951,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -3969,7 +3969,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -3987,7 +3987,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -4004,7 +4004,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -4021,7 +4021,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -4038,7 +4038,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -4056,7 +4056,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -4073,7 +4073,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4091,7 +4091,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -4108,7 +4108,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -4125,7 +4125,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -4142,7 +4142,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4160,7 +4160,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -4177,7 +4177,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -4199,7 +4199,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -4216,7 +4216,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -4233,7 +4233,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -4250,7 +4250,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -4267,7 +4267,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -4285,7 +4285,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -4303,7 +4303,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4321,7 +4321,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -4338,7 +4338,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -4355,7 +4355,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -4372,7 +4372,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -4390,7 +4390,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -4407,7 +4407,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4425,7 +4425,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -4442,7 +4442,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -4459,7 +4459,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -4476,7 +4476,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4494,7 +4494,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -4511,7 +4511,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -4534,7 +4534,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -4551,7 +4551,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -4568,7 +4568,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -4585,7 +4585,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -4602,7 +4602,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -4620,7 +4620,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -4638,7 +4638,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4656,7 +4656,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -4673,7 +4673,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -4690,7 +4690,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -4707,7 +4707,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -4725,7 +4725,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "shared_screencast_stream_test",
@@ -4742,7 +4742,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -4759,7 +4759,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4777,7 +4777,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -4794,7 +4794,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -4811,7 +4811,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -4828,7 +4828,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -4846,7 +4846,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -4863,7 +4863,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -4885,7 +4885,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -4902,7 +4902,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -4919,7 +4919,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -4936,7 +4936,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -4953,7 +4953,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -4971,7 +4971,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -4989,7 +4989,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -5007,7 +5007,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -5024,7 +5024,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -5041,7 +5041,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -5058,7 +5058,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -5076,7 +5076,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "shared_screencast_stream_test",
@@ -5093,7 +5093,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -5110,7 +5110,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -5128,7 +5128,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -5145,7 +5145,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -5162,7 +5162,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -5179,7 +5179,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -5197,7 +5197,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -5214,7 +5214,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -7959,18 +7959,18 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "apprtcmobile_tests iPhone 14 17.0",
+ "name": "apprtcmobile_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -7989,19 +7989,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "apprtcmobile_tests",
"test_id_prefix": "ninja://examples:apprtcmobile_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -8014,7 +8014,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8038,7 +8038,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8063,7 +8063,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8087,7 +8087,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8106,17 +8106,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "audio_decoder_unittests iPhone 14 17.0",
+ "name": "audio_decoder_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -8135,19 +8135,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "audio_decoder_unittests",
"test_id_prefix": "ninja://modules/audio_coding:audio_decoder_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -8159,7 +8159,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8183,7 +8183,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8207,7 +8207,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8231,7 +8231,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8250,17 +8250,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "common_audio_unittests iPhone 14 17.0",
+ "name": "common_audio_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -8279,19 +8279,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "common_audio_unittests",
"test_id_prefix": "ninja://common_audio:common_audio_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -8303,7 +8303,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8327,7 +8327,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8351,7 +8351,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8375,7 +8375,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8394,17 +8394,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "common_video_unittests iPhone 14 17.0",
+ "name": "common_video_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -8423,19 +8423,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "common_video_unittests",
"test_id_prefix": "ninja://common_video:common_video_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -8447,7 +8447,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8471,7 +8471,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8495,7 +8495,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8519,7 +8519,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8538,17 +8538,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "dcsctp_unittests iPhone 14 17.0",
+ "name": "dcsctp_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -8567,19 +8567,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "dcsctp_unittests",
"test_id_prefix": "ninja://net/dcsctp:dcsctp_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -8591,7 +8591,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8615,7 +8615,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8639,7 +8639,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8663,7 +8663,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8682,17 +8682,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "modules_tests iPhone 14 17.0",
+ "name": "modules_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -8711,12 +8711,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -8724,7 +8724,7 @@
},
"test": "modules_tests",
"test_id_prefix": "ninja://modules:modules_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -8736,7 +8736,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8760,7 +8760,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8785,7 +8785,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8809,7 +8809,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8829,17 +8829,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "modules_unittests iPhone 14 17.0",
+ "name": "modules_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -8859,12 +8859,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -8872,7 +8872,7 @@
},
"test": "modules_unittests",
"test_id_prefix": "ninja://modules:modules_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -8884,7 +8884,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8909,7 +8909,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8934,7 +8934,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -8959,7 +8959,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -8979,17 +8979,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_media_unittests iPhone 14 17.0",
+ "name": "rtc_media_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -9008,19 +9008,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "rtc_media_unittests",
"test_id_prefix": "ninja://media:rtc_media_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -9032,7 +9032,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9056,7 +9056,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9080,7 +9080,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9104,7 +9104,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9123,17 +9123,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_pc_unittests iPhone 14 17.0",
+ "name": "rtc_pc_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -9152,19 +9152,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "rtc_pc_unittests",
"test_id_prefix": "ninja://pc:rtc_pc_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -9176,7 +9176,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9200,7 +9200,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9224,7 +9224,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9248,7 +9248,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9267,17 +9267,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_stats_unittests iPhone 14 17.0",
+ "name": "rtc_stats_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -9296,19 +9296,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "rtc_stats_unittests",
"test_id_prefix": "ninja://stats:rtc_stats_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -9320,7 +9320,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9344,7 +9344,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9368,7 +9368,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9392,7 +9392,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9411,17 +9411,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_unittests iPhone 14 17.0",
+ "name": "rtc_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -9440,12 +9440,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -9453,7 +9453,7 @@
},
"test": "rtc_unittests",
"test_id_prefix": "ninja://:rtc_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -9465,7 +9465,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9489,7 +9489,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9514,7 +9514,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9538,7 +9538,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9558,18 +9558,18 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "sdk_framework_unittests iPhone 14 17.0",
+ "name": "sdk_framework_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -9588,19 +9588,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "sdk_framework_unittests",
"test_id_prefix": "ninja://sdk:sdk_framework_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -9613,7 +9613,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9637,7 +9637,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9662,7 +9662,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9686,7 +9686,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9705,18 +9705,18 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "sdk_unittests iPhone 14 17.0",
+ "name": "sdk_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -9735,19 +9735,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "sdk_unittests",
"test_id_prefix": "ninja://sdk:sdk_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -9760,7 +9760,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9784,7 +9784,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9809,7 +9809,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9833,7 +9833,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9852,17 +9852,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "svc_tests iPhone 14 17.0",
+ "name": "svc_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -9882,12 +9882,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -9895,7 +9895,7 @@
},
"test": "svc_tests",
"test_id_prefix": "ninja://pc:svc_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -9907,7 +9907,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9932,7 +9932,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -9957,7 +9957,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -9982,7 +9982,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10002,17 +10002,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "system_wrappers_unittests iPhone 14 17.0",
+ "name": "system_wrappers_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -10031,19 +10031,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "system_wrappers_unittests",
"test_id_prefix": "ninja://system_wrappers:system_wrappers_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -10055,7 +10055,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10079,7 +10079,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10103,7 +10103,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10127,7 +10127,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10146,17 +10146,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "test_support_unittests iPhone 14 17.0",
+ "name": "test_support_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -10175,19 +10175,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "test_support_unittests",
"test_id_prefix": "ninja://test:test_support_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -10199,7 +10199,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10223,7 +10223,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10247,7 +10247,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10271,7 +10271,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10290,17 +10290,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "tools_unittests iPhone 14 17.0",
+ "name": "tools_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -10319,19 +10319,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "tools_unittests",
"test_id_prefix": "ninja://rtc_tools:tools_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -10343,7 +10343,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10367,7 +10367,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10391,7 +10391,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10415,7 +10415,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10434,17 +10434,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "video_engine_tests iPhone 14 17.0",
+ "name": "video_engine_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -10463,12 +10463,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -10476,7 +10476,7 @@
},
"test": "video_engine_tests",
"test_id_prefix": "ninja://:video_engine_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -10488,7 +10488,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10512,7 +10512,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10537,7 +10537,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10561,7 +10561,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10581,17 +10581,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "voip_unittests iPhone 14 17.0",
+ "name": "voip_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -10610,19 +10610,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "voip_unittests",
"test_id_prefix": "ninja://:voip_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -10634,7 +10634,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10658,7 +10658,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10682,7 +10682,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10706,7 +10706,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10725,17 +10725,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "webrtc_nonparallel_tests iPhone 14 17.0",
+ "name": "webrtc_nonparallel_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -10754,19 +10754,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "webrtc_nonparallel_tests",
"test_id_prefix": "ninja://:webrtc_nonparallel_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -10778,7 +10778,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10802,7 +10802,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -10826,7 +10826,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10850,7 +10850,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
diff --git a/third_party/libwebrtc/infra/specs/internal.client.webrtc.json b/third_party/libwebrtc/infra/specs/internal.client.webrtc.json
index b6dbd5c2c3..95d0caa8b2 100644
--- a/third_party/libwebrtc/infra/specs/internal.client.webrtc.json
+++ b/third_party/libwebrtc/infra/specs/internal.client.webrtc.json
@@ -7,7 +7,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -29,12 +29,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -47,7 +47,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -69,12 +69,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -88,7 +88,7 @@
"--readline-timeout=1200",
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -110,14 +110,14 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"hard_timeout": 7200,
"io_timeout": 7200,
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -131,7 +131,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -153,12 +153,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -172,7 +172,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -194,12 +194,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -212,7 +212,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -234,12 +234,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -252,7 +252,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -274,12 +274,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -292,7 +292,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -314,12 +314,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -332,7 +332,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -354,12 +354,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -372,7 +372,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -394,12 +394,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -472,7 +472,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -494,12 +494,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -512,7 +512,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -534,12 +534,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -553,7 +553,7 @@
"--readline-timeout=1200",
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -575,14 +575,14 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"hard_timeout": 7200,
"io_timeout": 7200,
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -596,7 +596,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -618,12 +618,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -637,7 +637,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -659,12 +659,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -677,7 +677,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -699,12 +699,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -717,7 +717,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -739,12 +739,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -757,7 +757,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -779,12 +779,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -797,7 +797,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -819,12 +819,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
@@ -837,7 +837,7 @@
"args": [
"--xctest",
"--xcode-build-version",
- "15a507",
+ "15c500b",
"--out-dir",
"${ISOLATED_OUTDIR}"
],
@@ -859,12 +859,12 @@
],
"dimensions": {
"device_status": "available",
- "os": "iOS-16.6",
+ "os": "iOS-16.7.1",
"pool": "chrome.tests"
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
}
],
diff --git a/third_party/libwebrtc/infra/specs/mixins.pyl b/third_party/libwebrtc/infra/specs/mixins.pyl
index 8520002df6..135621c3ea 100644
--- a/third_party/libwebrtc/infra/specs/mixins.pyl
+++ b/third_party/libwebrtc/infra/specs/mixins.pyl
@@ -58,10 +58,10 @@
'has_native_resultdb_integration': True
}
},
- 'ios-device-16.6': {
+ 'ios-device-16.7': {
'swarming': {
'dimensions': {
- 'os': 'iOS-16.6',
+ 'os': 'iOS-16.7.1',
'pool': 'chrome.tests',
'device_status': 'available'
}
@@ -94,11 +94,11 @@
}]
}
},
- 'ios_runtime_cache_17_0': {
+ 'ios_runtime_cache_17_4': {
'swarming': {
'named_caches': [{
- 'name': 'runtime_ios_17_0',
- 'path': 'Runtime-ios-17.0'
+ 'name': 'runtime_ios_17_4',
+ 'path': 'Runtime-ios-17.4'
}]
}
},
@@ -124,6 +124,13 @@
}
}
},
+ 'linux-jammy': {
+ 'swarming': {
+ 'dimensions': {
+ 'os': 'Ubuntu-22.04'
+ }
+ }
+ },
'mac-m1-cpu': {
'swarming': {
'dimensions': {
@@ -320,10 +327,10 @@
}
},
'xcode_15_main': {
- 'args': ['--xcode-build-version', '15a507'],
+ 'args': ['--xcode-build-version', '15c500b'],
'swarming': {
'named_caches': [{
- 'name': 'xcode_ios_15a507',
+ 'name': 'xcode_ios_15c500b',
'path': 'Xcode.app'
}]
}
diff --git a/third_party/libwebrtc/infra/specs/mixins_webrtc.pyl b/third_party/libwebrtc/infra/specs/mixins_webrtc.pyl
index cd83ad2d9b..6ef5b41ffa 100644
--- a/third_party/libwebrtc/infra/specs/mixins_webrtc.pyl
+++ b/third_party/libwebrtc/infra/specs/mixins_webrtc.pyl
@@ -38,10 +38,10 @@
'--test-arg=--undefok=test_launcher_summary_output'
],
},
- 'ios-device-16.6': {
+ 'ios-device-16.7': {
'swarming': {
'dimensions': {
- 'os': 'iOS-16.6',
+ 'os': 'iOS-16.7.1',
'pool': 'chrome.tests',
'device_status': 'available'
}
diff --git a/third_party/libwebrtc/infra/specs/test_suites.pyl b/third_party/libwebrtc/infra/specs/test_suites.pyl
index e6d98748c7..b292fc11fe 100644
--- a/third_party/libwebrtc/infra/specs/test_suites.pyl
+++ b/third_party/libwebrtc/infra/specs/test_suites.pyl
@@ -263,7 +263,7 @@
'variants': [
'SIM_IPHONE_X_15_5',
'SIM_IPHONE_X_16_4',
- 'SIM_IPHONE_14_17_0',
+ 'SIM_IPHONE_14_17_4',
],
},
},
diff --git a/third_party/libwebrtc/infra/specs/tryserver.webrtc.json b/third_party/libwebrtc/infra/specs/tryserver.webrtc.json
index 3ab538b02c..41af426aeb 100644
--- a/third_party/libwebrtc/infra/specs/tryserver.webrtc.json
+++ b/third_party/libwebrtc/infra/specs/tryserver.webrtc.json
@@ -2062,7 +2062,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -2086,7 +2086,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -2110,7 +2110,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -2134,7 +2134,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -2158,7 +2158,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -2182,7 +2182,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -2206,7 +2206,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -2231,7 +2231,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -2255,7 +2255,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -2280,7 +2280,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -2304,7 +2304,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -2321,18 +2321,18 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "apprtcmobile_tests iPhone 14 17.0",
+ "name": "apprtcmobile_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -2351,19 +2351,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "apprtcmobile_tests",
"test_id_prefix": "ninja://examples:apprtcmobile_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -2376,7 +2376,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2400,7 +2400,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2425,7 +2425,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2449,7 +2449,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2468,17 +2468,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "audio_decoder_unittests iPhone 14 17.0",
+ "name": "audio_decoder_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -2497,19 +2497,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "audio_decoder_unittests",
"test_id_prefix": "ninja://modules/audio_coding:audio_decoder_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -2521,7 +2521,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2545,7 +2545,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2569,7 +2569,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2593,7 +2593,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2612,17 +2612,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "common_audio_unittests iPhone 14 17.0",
+ "name": "common_audio_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -2641,19 +2641,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "common_audio_unittests",
"test_id_prefix": "ninja://common_audio:common_audio_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -2665,7 +2665,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2689,7 +2689,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2713,7 +2713,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2737,7 +2737,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2756,17 +2756,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "common_video_unittests iPhone 14 17.0",
+ "name": "common_video_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -2785,19 +2785,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "common_video_unittests",
"test_id_prefix": "ninja://common_video:common_video_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -2809,7 +2809,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2833,7 +2833,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2857,7 +2857,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2881,7 +2881,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -2900,17 +2900,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "dcsctp_unittests iPhone 14 17.0",
+ "name": "dcsctp_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -2929,19 +2929,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "dcsctp_unittests",
"test_id_prefix": "ninja://net/dcsctp:dcsctp_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -2953,7 +2953,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -2977,7 +2977,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3001,7 +3001,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3025,7 +3025,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3044,17 +3044,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "modules_tests iPhone 14 17.0",
+ "name": "modules_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -3073,12 +3073,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -3086,7 +3086,7 @@
},
"test": "modules_tests",
"test_id_prefix": "ninja://modules:modules_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -3098,7 +3098,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3122,7 +3122,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3147,7 +3147,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3171,7 +3171,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3191,17 +3191,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "modules_unittests iPhone 14 17.0",
+ "name": "modules_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -3221,12 +3221,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -3234,7 +3234,7 @@
},
"test": "modules_unittests",
"test_id_prefix": "ninja://modules:modules_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -3246,7 +3246,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3271,7 +3271,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3296,7 +3296,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3321,7 +3321,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3341,17 +3341,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_media_unittests iPhone 14 17.0",
+ "name": "rtc_media_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -3370,19 +3370,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "rtc_media_unittests",
"test_id_prefix": "ninja://media:rtc_media_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -3394,7 +3394,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3418,7 +3418,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3442,7 +3442,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3466,7 +3466,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3485,17 +3485,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_pc_unittests iPhone 14 17.0",
+ "name": "rtc_pc_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -3514,19 +3514,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "rtc_pc_unittests",
"test_id_prefix": "ninja://pc:rtc_pc_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -3538,7 +3538,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3562,7 +3562,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3586,7 +3586,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3610,7 +3610,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3629,17 +3629,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_stats_unittests iPhone 14 17.0",
+ "name": "rtc_stats_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -3658,19 +3658,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "rtc_stats_unittests",
"test_id_prefix": "ninja://stats:rtc_stats_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -3682,7 +3682,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3706,7 +3706,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3730,7 +3730,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3754,7 +3754,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3773,17 +3773,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "rtc_unittests iPhone 14 17.0",
+ "name": "rtc_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -3802,12 +3802,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -3815,7 +3815,7 @@
},
"test": "rtc_unittests",
"test_id_prefix": "ninja://:rtc_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -3827,7 +3827,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3851,7 +3851,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3876,7 +3876,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3900,7 +3900,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -3920,18 +3920,18 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "sdk_framework_unittests iPhone 14 17.0",
+ "name": "sdk_framework_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -3950,19 +3950,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "sdk_framework_unittests",
"test_id_prefix": "ninja://sdk:sdk_framework_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -3975,7 +3975,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3999,7 +3999,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4024,7 +4024,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4048,7 +4048,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4067,18 +4067,18 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "sdk_unittests iPhone 14 17.0",
+ "name": "sdk_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -4097,19 +4097,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "sdk_unittests",
"test_id_prefix": "ninja://sdk:sdk_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -4122,7 +4122,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4146,7 +4146,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4171,7 +4171,7 @@
"--xctest",
"--xcodebuild-sim-runner",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4195,7 +4195,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4214,17 +4214,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "svc_tests iPhone 14 17.0",
+ "name": "svc_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -4244,12 +4244,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -4257,7 +4257,7 @@
},
"test": "svc_tests",
"test_id_prefix": "ninja://pc:svc_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -4269,7 +4269,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4294,7 +4294,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4319,7 +4319,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4344,7 +4344,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4364,17 +4364,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "system_wrappers_unittests iPhone 14 17.0",
+ "name": "system_wrappers_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -4393,19 +4393,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "system_wrappers_unittests",
"test_id_prefix": "ninja://system_wrappers:system_wrappers_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -4417,7 +4417,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4441,7 +4441,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4465,7 +4465,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4489,7 +4489,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4508,17 +4508,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "test_support_unittests iPhone 14 17.0",
+ "name": "test_support_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -4537,19 +4537,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "test_support_unittests",
"test_id_prefix": "ninja://test:test_support_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -4561,7 +4561,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4585,7 +4585,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4609,7 +4609,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4633,7 +4633,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4652,17 +4652,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "tools_unittests iPhone 14 17.0",
+ "name": "tools_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -4681,19 +4681,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "tools_unittests",
"test_id_prefix": "ninja://rtc_tools:tools_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -4705,7 +4705,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4729,7 +4729,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4753,7 +4753,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4777,7 +4777,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4796,17 +4796,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "video_engine_tests iPhone 14 17.0",
+ "name": "video_engine_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -4825,12 +4825,12 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -4838,7 +4838,7 @@
},
"test": "video_engine_tests",
"test_id_prefix": "ninja://:video_engine_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -4850,7 +4850,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4874,7 +4874,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4899,7 +4899,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -4923,7 +4923,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -4943,17 +4943,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "voip_unittests iPhone 14 17.0",
+ "name": "voip_unittests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -4972,19 +4972,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "voip_unittests",
"test_id_prefix": "ninja://:voip_unittests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -4996,7 +4996,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5020,7 +5020,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -5044,7 +5044,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5068,7 +5068,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -5087,17 +5087,17 @@
"--platform",
"iPhone 14",
"--version",
- "17.0",
+ "17.4",
"--out-dir",
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
},
- "name": "webrtc_nonparallel_tests iPhone 14 17.0",
+ "name": "webrtc_nonparallel_tests iPhone 14 17.4",
"resultdb": {
"enable": true,
"has_native_resultdb_integration": true
@@ -5116,19 +5116,19 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
- "name": "runtime_ios_17_0",
- "path": "Runtime-ios-17.0"
+ "name": "runtime_ios_17_4",
+ "path": "Runtime-ios-17.4"
}
],
"service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
},
"test": "webrtc_nonparallel_tests",
"test_id_prefix": "ninja://:webrtc_nonparallel_tests/",
- "variant_id": "iPhone 14 17.0"
+ "variant_id": "iPhone 14 17.4"
},
{
"args": [
@@ -5140,7 +5140,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5164,7 +5164,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -5188,7 +5188,7 @@
"${ISOLATED_OUTDIR}",
"--xctest",
"--xcode-build-version",
- "15a507"
+ "15c500b"
],
"merge": {
"script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5212,7 +5212,7 @@
},
"named_caches": [
{
- "name": "xcode_ios_15a507",
+ "name": "xcode_ios_15c500b",
"path": "Xcode.app"
},
{
@@ -5598,7 +5598,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -5616,7 +5616,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -5634,7 +5634,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -5652,7 +5652,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -5670,7 +5670,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -5689,7 +5689,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -5708,7 +5708,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -5727,7 +5727,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -5745,7 +5745,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -5763,7 +5763,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -5781,7 +5781,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -5800,7 +5800,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "shared_screencast_stream_test",
@@ -5818,7 +5818,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -5836,7 +5836,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -5855,7 +5855,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -5873,7 +5873,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -5891,7 +5891,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -5915,7 +5915,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "video_codec_perf_tests",
@@ -5933,7 +5933,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -5952,7 +5952,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -5970,7 +5970,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -5994,7 +5994,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_perf_tests",
@@ -6015,7 +6015,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -6032,7 +6032,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -6049,7 +6049,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -6066,7 +6066,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -6083,7 +6083,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -6101,7 +6101,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -6119,7 +6119,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -6137,7 +6137,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -6154,7 +6154,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -6171,7 +6171,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -6188,7 +6188,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -6206,7 +6206,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "shared_screencast_stream_test",
@@ -6223,7 +6223,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -6240,7 +6240,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -6258,7 +6258,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -6275,7 +6275,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -6292,7 +6292,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -6309,7 +6309,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -6327,7 +6327,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -6344,7 +6344,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -6366,7 +6366,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -6383,7 +6383,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -6400,7 +6400,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -6417,7 +6417,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -6434,7 +6434,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -6452,7 +6452,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -6470,7 +6470,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -6488,7 +6488,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -6505,7 +6505,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -6522,7 +6522,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -6539,7 +6539,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -6557,7 +6557,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "shared_screencast_stream_test",
@@ -6574,7 +6574,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -6591,7 +6591,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -6609,7 +6609,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -6626,7 +6626,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -6643,7 +6643,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -6660,7 +6660,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -6678,7 +6678,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -6695,7 +6695,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -6716,7 +6716,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -7071,7 +7071,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -7088,7 +7088,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -7105,7 +7105,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -7122,7 +7122,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -7139,7 +7139,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -7157,7 +7157,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -7175,7 +7175,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -7193,7 +7193,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -7210,7 +7210,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -7227,7 +7227,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -7244,7 +7244,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -7262,7 +7262,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "shared_screencast_stream_test",
@@ -7279,7 +7279,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -7296,7 +7296,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -7314,7 +7314,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -7331,7 +7331,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -7348,7 +7348,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -7371,7 +7371,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "video_codec_perf_tests",
@@ -7388,7 +7388,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -7406,7 +7406,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -7423,7 +7423,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -7446,7 +7446,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_perf_tests",
@@ -8500,7 +8500,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -8517,7 +8517,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -8534,7 +8534,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -8551,7 +8551,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -8568,7 +8568,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -8586,7 +8586,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -8604,7 +8604,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -8622,7 +8622,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -8639,7 +8639,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -8656,7 +8656,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -8673,7 +8673,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -8691,7 +8691,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -8708,7 +8708,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -8726,7 +8726,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -8743,7 +8743,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -8760,7 +8760,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -8777,7 +8777,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -8795,7 +8795,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -8812,7 +8812,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
@@ -8833,7 +8833,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "audio_decoder_unittests",
@@ -8850,7 +8850,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_audio_unittests",
@@ -8867,7 +8867,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "common_video_unittests",
@@ -8884,7 +8884,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "dcsctp_unittests",
@@ -8901,7 +8901,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 2
},
@@ -8919,7 +8919,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -8937,7 +8937,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -8955,7 +8955,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_media_unittests",
@@ -8972,7 +8972,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_pc_unittests",
@@ -8989,7 +8989,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "rtc_stats_unittests",
@@ -9006,7 +9006,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 6
},
@@ -9024,7 +9024,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "slow_peer_connection_unittests",
@@ -9041,7 +9041,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -9059,7 +9059,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "system_wrappers_unittests",
@@ -9076,7 +9076,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "test_support_unittests",
@@ -9093,7 +9093,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "tools_unittests",
@@ -9110,7 +9110,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
},
"shards": 4
},
@@ -9128,7 +9128,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "voip_unittests",
@@ -9145,7 +9145,7 @@
"swarming": {
"dimensions": {
"cpu": "x86-64",
- "os": "Ubuntu-20.04"
+ "os": "Ubuntu-22.04"
}
},
"test": "webrtc_nonparallel_tests",
diff --git a/third_party/libwebrtc/infra/specs/variants.pyl b/third_party/libwebrtc/infra/specs/variants.pyl
index c97bdc5468..690829c2b1 100644
--- a/third_party/libwebrtc/infra/specs/variants.pyl
+++ b/third_party/libwebrtc/infra/specs/variants.pyl
@@ -27,14 +27,14 @@
'identifier': 'iPhone X 16.4',
'mixins': ['xcode_15_main', 'ios_runtime_cache_16_4'],
},
- 'SIM_IPHONE_14_17_0': {
+ 'SIM_IPHONE_14_17_4': {
'args': [
'--platform',
'iPhone 14',
'--version',
- '17.0',
+ '17.4',
],
- 'identifier': 'iPhone 14 17.0',
- 'mixins': ['xcode_15_main', 'ios_runtime_cache_17_0'],
+ 'identifier': 'iPhone 14 17.4',
+ 'mixins': ['xcode_15_main', 'ios_runtime_cache_17_4'],
},
}
diff --git a/third_party/libwebrtc/infra/specs/waterfalls.pyl b/third_party/libwebrtc/infra/specs/waterfalls.pyl
index 3521a9fee3..3459541a96 100644
--- a/third_party/libwebrtc/infra/specs/waterfalls.pyl
+++ b/third_party/libwebrtc/infra/specs/waterfalls.pyl
@@ -70,7 +70,7 @@
'os_type':
'linux',
'mixins': [
- 'linux-focal', 'x86-64', 'fuchsia-gtest-output',
+ 'linux-jammy', 'x86-64', 'fuchsia-gtest-output',
'resultdb-gtest-json-format'
],
'test_suites': {
@@ -79,7 +79,7 @@
},
'Linux (more configs)': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'more_configs_tests',
},
@@ -127,7 +127,7 @@
},
'Linux32 Debug': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
@@ -135,7 +135,7 @@
'Linux32 Debug (ARM)': {},
'Linux32 Release': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
@@ -144,7 +144,7 @@
'Linux64 Builder': {},
'Linux64 Debug': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'linux_tests',
},
@@ -152,7 +152,7 @@
'Linux64 Debug (ARM)': {},
'Linux64 Release': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'linux_tests',
},
@@ -322,7 +322,7 @@
'machines': {
'iOS64 Debug': {
'mixins': [
- 'ios-device-16.6', 'webrtc-xctest', 'chrome-tester-service-account',
+ 'ios-device-16.7', 'webrtc-xctest', 'chrome-tester-service-account',
'xcode_15_main', 'mac_toolchain', 'has_native_resultdb_integration',
'out_dir_arg'
],
@@ -345,7 +345,7 @@
},
'iOS64 Release': {
'mixins': [
- 'ios-device-16.6', 'webrtc-xctest', 'chrome-tester-service-account',
+ 'ios-device-16.7', 'webrtc-xctest', 'chrome-tester-service-account',
'xcode_15_main', 'mac_toolchain', 'has_native_resultdb_integration',
'out_dir_arg'
],
@@ -420,7 +420,7 @@
'os_type':
'linux',
'mixins': [
- 'linux-focal', 'x86-64', 'fuchsia-gtest-output',
+ 'linux-jammy', 'x86-64', 'fuchsia-gtest-output',
'resultdb-gtest-json-format'
],
'test_suites': {
@@ -455,7 +455,7 @@
'os_type':
'linux',
'mixins': [
- 'linux-focal', 'x86-64', 'resultdb-json-format',
+ 'linux-jammy', 'x86-64', 'resultdb-json-format',
'isolate_profile_data'
],
'test_suites': {
@@ -464,7 +464,7 @@
},
'linux_dbg': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'linux_tests',
},
@@ -472,14 +472,14 @@
'linux_libfuzzer_rel': {},
'linux_memcheck': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'linux_tests',
},
},
'linux_more_configs': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'more_configs_tests',
},
@@ -496,7 +496,7 @@
},
'linux_rel': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'linux_desktop_tests_tryserver',
},
@@ -527,14 +527,14 @@
},
'linux_x86_dbg': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
},
'linux_x86_rel': {
'os_type': 'linux',
- 'mixins': ['linux-focal', 'x86-64', 'resultdb-json-format'],
+ 'mixins': ['linux-jammy', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
diff --git a/third_party/libwebrtc/logging/BUILD.gn b/third_party/libwebrtc/logging/BUILD.gn
index 91890553a3..117d5c4a3c 100644
--- a/third_party/libwebrtc/logging/BUILD.gn
+++ b/third_party/libwebrtc/logging/BUILD.gn
@@ -353,6 +353,7 @@ rtc_library("rtc_event_log_impl_encoder") {
deps = [
":rtc_event_number_encodings",
+ "../api:field_trials_view",
"../api:rtp_headers",
"../api:rtp_parameters",
"../api/transport:network_control",
@@ -362,7 +363,6 @@ rtc_library("rtc_event_log_impl_encoder") {
"../rtc_base:checks",
"../rtc_base:logging",
"../rtc_base:safe_conversions",
- "../system_wrappers:field_trial",
]
absl_deps = [
"//third_party/abseil-cpp/absl/memory",
@@ -609,6 +609,7 @@ if (rtc_enable_protobuf) {
":rtc_event_video",
":rtc_stream_config",
"../api:array_view",
+ "../api:field_trials_view",
"../api:network_state_predictor_api",
"../api:rtc_event_log_output_file",
"../api:rtp_headers",
@@ -630,9 +631,7 @@ if (rtc_enable_protobuf) {
"../rtc_base:rtc_base_tests_utils",
"../rtc_base:timeutils",
"../system_wrappers",
- "../system_wrappers:field_trial",
"../test:explicit_key_value_config",
- "../test:field_trial",
"../test:fileutils",
"../test:test_support",
"../test/logging:log_writer",
@@ -689,6 +688,7 @@ rtc_library("ice_log") {
deps = [
":rtc_event_field",
+ "../api:candidate",
"../api:dtls_transport_interface",
"../api:libjingle_logging_api",
"../api/rtc_event_log",
diff --git a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
index 2c1444af07..83c5441138 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
@@ -131,21 +131,15 @@ ConvertIceCandidatePairConfigType(IceCandidatePairConfigType type) {
rtclog::IceCandidatePairConfig::IceCandidateType ConvertIceCandidateType(
IceCandidateType type) {
switch (type) {
- case IceCandidateType::kUnknown:
- return rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
- case IceCandidateType::kLocal:
+ case IceCandidateType::kHost:
return rtclog::IceCandidatePairConfig::LOCAL;
- case IceCandidateType::kStun:
+ case IceCandidateType::kSrflx:
return rtclog::IceCandidatePairConfig::STUN;
case IceCandidateType::kPrflx:
return rtclog::IceCandidatePairConfig::PRFLX;
case IceCandidateType::kRelay:
return rtclog::IceCandidatePairConfig::RELAY;
- case IceCandidateType::kNumValues:
- RTC_DCHECK_NOTREACHED();
}
- RTC_DCHECK_NOTREACHED();
- return rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
}
rtclog::IceCandidatePairConfig::Protocol ConvertIceCandidatePairProtocol(
@@ -202,6 +196,7 @@ rtclog::IceCandidatePairConfig::NetworkType ConvertIceCandidateNetworkType(
return rtclog::IceCandidatePairConfig::CELLULAR;
case IceCandidateNetworkType::kNumValues:
RTC_DCHECK_NOTREACHED();
+ break;
}
RTC_DCHECK_NOTREACHED();
return rtclog::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
diff --git a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
index 01bd89718d..7018f71e1b 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
@@ -10,8 +10,11 @@
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h"
+#include <type_traits>
+
#include "absl/types/optional.h"
#include "api/array_view.h"
+#include "api/field_trials_view.h"
#include "api/network_state_predictor.h"
#include "logging/rtc_event_log/dependency_descriptor_encoder_decoder.h"
#include "logging/rtc_event_log/encoder/blob_encoding.h"
@@ -62,7 +65,6 @@
#include "modules/rtp_rtcp/source/rtp_packet.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
-#include "system_wrappers/include/field_trial.h"
// *.pb.h files are generated at build-time by the protobuf compiler.
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
@@ -198,18 +200,14 @@ ConvertToProtoFormat(IceCandidatePairConfigType type) {
rtclog2::IceCandidatePairConfig::IceCandidateType ConvertToProtoFormat(
IceCandidateType type) {
switch (type) {
- case IceCandidateType::kUnknown:
- return rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
- case IceCandidateType::kLocal:
+ case IceCandidateType::kHost:
return rtclog2::IceCandidatePairConfig::LOCAL;
- case IceCandidateType::kStun:
+ case IceCandidateType::kSrflx:
return rtclog2::IceCandidatePairConfig::STUN;
case IceCandidateType::kPrflx:
return rtclog2::IceCandidatePairConfig::PRFLX;
case IceCandidateType::kRelay:
return rtclog2::IceCandidatePairConfig::RELAY;
- case IceCandidateType::kNumValues:
- RTC_DCHECK_NOTREACHED();
}
RTC_DCHECK_NOTREACHED();
return rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
@@ -385,10 +383,12 @@ void EncodeRtcpPacket(rtc::ArrayView<const EventType*> batch,
}
proto_batch->set_raw_packet_blobs(EncodeBlobs(scrubed_packets));
}
+} // namespace
-template <typename EventType, typename ProtoType>
-void EncodeRtpPacket(const std::vector<const EventType*>& batch,
- ProtoType* proto_batch) {
+template <typename Batch, typename ProtoType>
+void RtcEventLogEncoderNewFormat::EncodeRtpPacket(const Batch& batch,
+ ProtoType* proto_batch) {
+ using EventType = std::remove_pointer_t<typename Batch::value_type>;
if (batch.empty()) {
return;
}
@@ -463,8 +463,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
{
// TODO(webrtc:14975) Remove this kill switch after DD in RTC event log has
// been rolled out.
- if (!webrtc::field_trial::IsDisabled(
- "WebRTC-RtcEventLogEncodeDependencyDescriptor")) {
+ if (encode_dependency_descriptor_) {
std::vector<rtc::ArrayView<const uint8_t>> raw_dds(batch.size());
bool has_dd = false;
for (size_t i = 0; i < batch.size(); ++i) {
@@ -678,15 +677,13 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
proto_batch->set_voice_activity_deltas(encoded_deltas);
}
}
-} // namespace
-RtcEventLogEncoderNewFormat::RtcEventLogEncoderNewFormat() {
- encode_neteq_set_minimum_delay_kill_switch_ = false;
- if (webrtc::field_trial::IsEnabled(
- "WebRTC-RtcEventLogEncodeNetEqSetMinimumDelayKillSwitch")) {
- encode_neteq_set_minimum_delay_kill_switch_ = true;
- }
-}
+RtcEventLogEncoderNewFormat::RtcEventLogEncoderNewFormat(
+ const FieldTrialsView& field_trials)
+ : encode_neteq_set_minimum_delay_kill_switch_(field_trials.IsEnabled(
+ "WebRTC-RtcEventLogEncodeNetEqSetMinimumDelayKillSwitch")),
+ encode_dependency_descriptor_(!field_trials.IsDisabled(
+ "WebRTC-RtcEventLogEncodeDependencyDescriptor")) {}
std::string RtcEventLogEncoderNewFormat::EncodeLogStart(int64_t timestamp_us,
int64_t utc_time_us) {
diff --git a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
index 6747f41f07..6a657090dd 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
+++ b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
@@ -18,6 +18,7 @@
#include <vector>
#include "api/array_view.h"
+#include "api/field_trials_view.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder.h"
namespace webrtc {
@@ -59,7 +60,7 @@ class RtcEventGenericPacketSent;
class RtcEventLogEncoderNewFormat final : public RtcEventLogEncoder {
public:
- RtcEventLogEncoderNewFormat();
+ explicit RtcEventLogEncoderNewFormat(const FieldTrialsView& field_trials);
~RtcEventLogEncoderNewFormat() override = default;
std::string EncodeBatch(
@@ -71,8 +72,6 @@ class RtcEventLogEncoderNewFormat final : public RtcEventLogEncoder {
std::string EncodeLogEnd(int64_t timestamp_us) override;
private:
- bool encode_neteq_set_minimum_delay_kill_switch_ = false;
-
// Encoding entry-point for the various RtcEvent subclasses.
void EncodeAlrState(rtc::ArrayView<const RtcEventAlrState*> batch,
rtclog2::EventStream* event_stream);
@@ -157,6 +156,11 @@ class RtcEventLogEncoderNewFormat final : public RtcEventLogEncoder {
void EncodeVideoSendStreamConfig(
rtc::ArrayView<const RtcEventVideoSendStreamConfig*> batch,
rtclog2::EventStream* event_stream);
+ template <typename Batch, typename ProtoType>
+ void EncodeRtpPacket(const Batch& batch, ProtoType* proto_batch);
+
+ const bool encode_neteq_set_minimum_delay_kill_switch_;
+ const bool encode_dependency_descriptor_;
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
index 612f85bf61..72611db8ce 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
@@ -14,6 +14,7 @@
#include <string>
#include <tuple>
+#include "api/field_trials_view.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.h"
@@ -40,10 +41,13 @@
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "rtc_base/fake_clock.h"
#include "rtc_base/random.h"
-#include "test/field_trial.h"
+#include "test/explicit_key_value_config.h"
#include "test/gtest.h"
namespace webrtc {
+
+using test::ExplicitKeyValueConfig;
+
class RtcEventLogEncoderTest
: public ::testing::TestWithParam<
std::tuple<int, RtcEventLog::EncodingType, size_t, bool>> {
@@ -55,22 +59,26 @@ class RtcEventLogEncoderTest
event_count_(std::get<2>(GetParam())),
force_repeated_fields_(std::get<3>(GetParam())),
gen_(seed_ * 880001UL),
- verifier_(encoding_type_) {
+ verifier_(encoding_type_) {}
+ ~RtcEventLogEncoderTest() override = default;
+
+ std::unique_ptr<RtcEventLogEncoder> CreateEncoder(
+ const FieldTrialsView& field_trials = ExplicitKeyValueConfig("")) {
+ std::unique_ptr<RtcEventLogEncoder> encoder;
switch (encoding_type_) {
case RtcEventLog::EncodingType::Legacy:
- encoder_ = std::make_unique<RtcEventLogEncoderLegacy>();
+ encoder = std::make_unique<RtcEventLogEncoderLegacy>();
break;
case RtcEventLog::EncodingType::NewFormat:
- encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>();
+ encoder = std::make_unique<RtcEventLogEncoderNewFormat>(field_trials);
break;
case RtcEventLog::EncodingType::ProtoFree:
- encoder_ = std::make_unique<RtcEventLogEncoderV3>();
+ encoder = std::make_unique<RtcEventLogEncoderV3>();
break;
}
- encoded_ =
- encoder_->EncodeLogStart(rtc::TimeMillis(), rtc::TimeUTCMillis());
+ encoded_ = encoder->EncodeLogStart(rtc::TimeMillis(), rtc::TimeUTCMillis());
+ return encoder;
}
- ~RtcEventLogEncoderTest() override = default;
// ANA events have some optional fields, so we want to make sure that we get
// correct behavior both when all of the values are there, as well as when
@@ -89,10 +97,9 @@ class RtcEventLogEncoderTest
uint32_t ssrc);
template <typename EventType, typename ParsedType>
- void TestRtpPackets();
+ void TestRtpPackets(RtcEventLogEncoder& encoder);
std::deque<std::unique_ptr<RtcEvent>> history_;
- std::unique_ptr<RtcEventLogEncoder> encoder_;
ParsedRtcEventLog parsed_log_;
const uint64_t seed_;
Random prng_;
@@ -108,12 +115,13 @@ void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
const std::vector<std::unique_ptr<RtcEventAudioNetworkAdaptation>>&
events) {
ASSERT_TRUE(history_.empty()) << "Function should be called once per test.";
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
for (auto& event : events) {
history_.push_back(event->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& ana_configs = parsed_log_.audio_network_adaptation_events();
@@ -165,7 +173,7 @@ RtcEventLogEncoderTest::GetRtpPacketsBySsrc(const ParsedRtcEventLog* parsed_log,
}
template <typename EventType, typename ParsedType>
-void RtcEventLogEncoderTest::TestRtpPackets() {
+void RtcEventLogEncoderTest::TestRtpPackets(RtcEventLogEncoder& encoder) {
// SSRCs will be randomly assigned out of this small pool, significant only
// in that it also covers such edge cases as SSRC = 0 and SSRC = 0xffffffff.
// The pool is intentionally small, so as to produce collisions.
@@ -193,7 +201,7 @@ void RtcEventLogEncoderTest::TestRtpPackets() {
}
// Encode and parse.
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder.EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
// For each SSRC, make sure the RTP packets associated with it to have been
@@ -213,6 +221,7 @@ void RtcEventLogEncoderTest::TestRtpPackets() {
}
TEST_P(RtcEventLogEncoderTest, RtcEventAlrState) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventAlrState>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_) ? gen_.NewAlrState()
@@ -220,7 +229,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAlrState) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& alr_state_events = parsed_log_.alr_state_events();
@@ -234,6 +243,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRouteChange) {
if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventRouteChange>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_) ? gen_.NewRouteChange()
@@ -241,7 +251,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRouteChange) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& route_change_events = parsed_log_.route_change_events();
@@ -252,6 +262,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRouteChange) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventRemoteEstimate) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventRemoteEstimate>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -260,7 +271,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRemoteEstimate) {
history_.push_back(std::make_unique<RtcEventRemoteEstimate>(*events[i]));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& parsed_events = parsed_log_.remote_estimate_events();
@@ -395,6 +406,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationAll) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
// SSRCs will be randomly assigned out of this small pool, significant only
// in that it also covers such edge cases as SSRC = 0 and SSRC = 0xffffffff.
// The pool is intentionally small, so as to produce collisions.
@@ -414,7 +426,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
original_events_by_ssrc[ssrc].push_back(std::move(event));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& parsed_playout_events_by_ssrc =
@@ -443,6 +455,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventNetEqSetMinimumDelayDecoded) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
// SSRCs will be randomly assigned out of this small pool, significant only
// in that it also covers such edge cases as SSRC = 0 and SSRC = 0xffffffff.
// The pool is intentionally small, so as to produce collisions.
@@ -461,7 +474,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventNetEqSetMinimumDelayDecoded) {
original_events_by_ssrc[ssrc].push_back(std::move(event));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& parsed_neteq_set_minimum_delay_events_by_ssrc =
@@ -502,13 +515,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventNetEqSetMinimumDelayDecoded) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventAudioReceiveStreamConfig> event =
gen_.NewAudioReceiveStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& audio_recv_configs = parsed_log_.audio_recv_configs();
@@ -518,13 +532,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventAudioSendStreamConfig) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventAudioSendStreamConfig> event =
gen_.NewAudioSendStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& audio_send_configs = parsed_log_.audio_send_configs();
@@ -533,6 +548,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioSendStreamConfig) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventBweUpdateDelayBased>> events(
event_count_);
for (size_t i = 0; i < event_count_; ++i) {
@@ -542,7 +558,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_delay_updates = parsed_log_.bwe_delay_updates();
@@ -554,6 +570,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventBweUpdateLossBased>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -562,7 +579,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_loss_updates = parsed_log_.bwe_loss_updates();
@@ -577,6 +594,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketReceived) {
if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventGenericPacketReceived>> events(
event_count_);
for (size_t i = 0; i < event_count_; ++i) {
@@ -586,7 +604,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketReceived) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& packets_received = parsed_log_.generic_packets_received();
@@ -602,6 +620,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketSent) {
if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventGenericPacketSent>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -610,7 +629,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketSent) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& packets_sent = parsed_log_.generic_packets_sent();
@@ -625,6 +644,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericAcksReceived) {
if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventGenericAckReceived>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -633,7 +653,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericAcksReceived) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& decoded_events = parsed_log_.generic_acks_received();
@@ -645,6 +665,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericAcksReceived) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventDtlsTransportState) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventDtlsTransportState>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -653,7 +674,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventDtlsTransportState) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& dtls_transport_states = parsed_log_.dtls_transport_states();
@@ -670,6 +691,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventDtlsTransportState) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventDtlsWritableState) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventDtlsWritableState>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -678,7 +700,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventDtlsWritableState) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& dtls_writable_states = parsed_log_.dtls_writable_states();
@@ -696,6 +718,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventDtlsWritableState) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventFrameDecoded) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
// SSRCs will be randomly assigned out of this small pool, significant only
// in that it also covers such edge cases as SSRC = 0 and SSRC = 0xffffffff.
// The pool is intentionally small, so as to produce collisions.
@@ -715,7 +738,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventFrameDecoded) {
original_events_by_ssrc[ssrc].push_back(std::move(event));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
auto status = parsed_log_.ParseString(encoded_);
if (!status.ok())
RTC_LOG(LS_ERROR) << status.message();
@@ -751,11 +774,12 @@ TEST_P(RtcEventLogEncoderTest, RtcEventFrameDecoded) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePairConfig) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::unique_ptr<RtcEventIceCandidatePairConfig> event =
gen_.NewIceCandidatePairConfig();
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& ice_candidate_pair_configs =
parsed_log_.ice_candidate_pair_configs();
@@ -767,10 +791,11 @@ TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePairConfig) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePair) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::unique_ptr<RtcEventIceCandidatePair> event = gen_.NewIceCandidatePair();
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& ice_candidate_pair_events =
parsed_log_.ice_candidate_pair_events();
@@ -781,11 +806,12 @@ TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePair) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
const int64_t timestamp_ms = prng_.Rand(1'000'000'000);
const int64_t utc_time_ms = prng_.Rand(1'000'000'000);
// Overwrite the previously encoded LogStart event.
- encoded_ = encoder_->EncodeLogStart(timestamp_ms * 1000, utc_time_ms * 1000);
+ encoded_ = encoder->EncodeLogStart(timestamp_ms * 1000, utc_time_ms * 1000);
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& start_log_events = parsed_log_.start_log_events();
@@ -795,16 +821,17 @@ TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
const int64_t start_timestamp_ms = prng_.Rand(1'000'000'000);
const int64_t start_utc_time_ms = prng_.Rand(1'000'000'000);
// Overwrite the previously encoded LogStart event.
- encoded_ = encoder_->EncodeLogStart(start_timestamp_ms * 1000,
- start_utc_time_ms * 1000);
+ encoded_ = encoder->EncodeLogStart(start_timestamp_ms * 1000,
+ start_utc_time_ms * 1000);
const int64_t stop_timestamp_ms =
prng_.Rand(start_timestamp_ms, 2'000'000'000);
- encoded_ += encoder_->EncodeLogEnd(stop_timestamp_ms * 1000);
+ encoded_ += encoder->EncodeLogEnd(stop_timestamp_ms * 1000);
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& stop_log_events = parsed_log_.stop_log_events();
@@ -814,11 +841,12 @@ TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventProbeClusterCreated) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::unique_ptr<RtcEventProbeClusterCreated> event =
gen_.NewProbeClusterCreated();
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_probe_cluster_created_events =
parsed_log_.bwe_probe_cluster_created_events();
@@ -830,11 +858,12 @@ TEST_P(RtcEventLogEncoderTest, RtcEventProbeClusterCreated) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultFailure) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::unique_ptr<RtcEventProbeResultFailure> event =
gen_.NewProbeResultFailure();
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_probe_failure_events = parsed_log_.bwe_probe_failure_events();
@@ -845,11 +874,12 @@ TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultFailure) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultSuccess) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::unique_ptr<RtcEventProbeResultSuccess> event =
gen_.NewProbeResultSuccess();
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_probe_success_events = parsed_log_.bwe_probe_success_events();
@@ -864,6 +894,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
// As a work around, we're removing duplicates in the parser.
return;
}
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventRtcpPacketIncoming>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
@@ -873,7 +904,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& incoming_rtcp_packets = parsed_log_.incoming_rtcp_packets();
@@ -886,6 +917,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketOutgoing) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
std::vector<std::unique_ptr<RtcEventRtcpPacketOutgoing>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -894,7 +926,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketOutgoing) {
history_.push_back(events[i]->Copy());
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& outgoing_rtcp_packets = parsed_log_.outgoing_rtcp_packets();
@@ -914,6 +946,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpReceiverReport) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::ReceiverReport> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -931,7 +965,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpReceiverReport) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& receiver_reports = parsed_log_.receiver_reports(direction);
@@ -952,6 +986,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpSenderReport) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::SenderReport> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -969,7 +1005,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpSenderReport) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& sender_reports = parsed_log_.sender_reports(direction);
@@ -990,6 +1026,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpExtendedReports) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::ExtendedReports> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -1007,7 +1045,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpExtendedReports) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& extended_reports = parsed_log_.extended_reports(direction);
@@ -1028,6 +1066,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpFir) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Fir> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -1045,7 +1085,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpFir) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& firs = parsed_log_.firs(direction);
@@ -1065,6 +1105,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPli) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Pli> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -1082,7 +1124,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPli) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& plis = parsed_log_.plis(direction);
@@ -1102,6 +1144,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpBye) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Bye> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -1119,7 +1163,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpBye) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& byes = parsed_log_.byes(direction);
@@ -1139,6 +1183,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpNack) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Nack> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -1156,7 +1202,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpNack) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& nacks = parsed_log_.nacks(direction);
@@ -1176,6 +1222,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpRemb) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Remb> events(event_count_);
std::vector<int64_t> timestamps_ms(event_count_);
@@ -1193,7 +1241,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpRemb) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& rembs = parsed_log_.rembs(direction);
@@ -1213,6 +1261,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpTransportFeedback) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::TransportFeedback> events;
events.reserve(event_count_);
@@ -1231,7 +1281,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpTransportFeedback) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& transport_feedbacks =
@@ -1253,6 +1303,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpLossNotification) {
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::LossNotification> events;
events.reserve(event_count_);
@@ -1271,7 +1323,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpLossNotification) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& loss_notifications = parsed_log_.loss_notifications(direction);
@@ -1285,36 +1337,43 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpLossNotification) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketIncoming) {
- TestRtpPackets<RtcEventRtpPacketIncoming, LoggedRtpPacketIncoming>();
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+ TestRtpPackets<RtcEventRtpPacketIncoming, LoggedRtpPacketIncoming>(*encoder);
}
TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketOutgoing) {
- TestRtpPackets<RtcEventRtpPacketOutgoing, LoggedRtpPacketOutgoing>();
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+ TestRtpPackets<RtcEventRtpPacketOutgoing, LoggedRtpPacketOutgoing>(*encoder);
}
TEST_P(RtcEventLogEncoderTest,
RtcEventRtpPacketIncomingNoDependencyDescriptor) {
- test::ScopedFieldTrials no_dd(
+ ExplicitKeyValueConfig no_dd(
"WebRTC-RtcEventLogEncodeDependencyDescriptor/Disabled/");
- TestRtpPackets<RtcEventRtpPacketIncoming, LoggedRtpPacketIncoming>();
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder(no_dd);
+ verifier_.ExpectDependencyDescriptorExtensionIsSet(false);
+ TestRtpPackets<RtcEventRtpPacketIncoming, LoggedRtpPacketIncoming>(*encoder);
}
TEST_P(RtcEventLogEncoderTest,
RtcEventRtpPacketOutgoingNoDependencyDescriptor) {
- test::ScopedFieldTrials no_dd(
+ ExplicitKeyValueConfig no_dd(
"WebRTC-RtcEventLogEncodeDependencyDescriptor/Disabled/");
- TestRtpPackets<RtcEventRtpPacketOutgoing, LoggedRtpPacketOutgoing>();
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder(no_dd);
+ verifier_.ExpectDependencyDescriptorExtensionIsSet(false);
+ TestRtpPackets<RtcEventRtpPacketOutgoing, LoggedRtpPacketOutgoing>(*encoder);
}
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventVideoReceiveStreamConfig> event =
gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& video_recv_configs = parsed_log_.video_recv_configs();
@@ -1324,13 +1383,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventVideoSendStreamConfig) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventVideoSendStreamConfig> event =
gen_.NewVideoSendStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& video_send_configs = parsed_log_.video_send_configs();
@@ -1357,7 +1417,8 @@ class RtcEventLogEncoderSimpleTest
encoder_ = std::make_unique<RtcEventLogEncoderLegacy>();
break;
case RtcEventLog::EncodingType::NewFormat:
- encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>();
+ encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>(
+ ExplicitKeyValueConfig(""));
break;
case RtcEventLog::EncodingType::ProtoFree:
encoder_ = std::make_unique<RtcEventLogEncoderV3>();
diff --git a/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc b/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
index eb458c4640..59d76e7a03 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
@@ -14,12 +14,14 @@
namespace webrtc {
-IceCandidatePairDescription::IceCandidatePairDescription() {
- local_candidate_type = IceCandidateType::kUnknown;
+IceCandidatePairDescription::IceCandidatePairDescription(
+ IceCandidateType local_candidate_type,
+ IceCandidateType remote_candidate_type)
+ : local_candidate_type(local_candidate_type),
+ remote_candidate_type(remote_candidate_type) {
local_relay_protocol = IceCandidatePairProtocol::kUnknown;
local_network_type = IceCandidateNetworkType::kUnknown;
local_address_family = IceCandidatePairAddressFamily::kUnknown;
- remote_candidate_type = IceCandidateType::kUnknown;
remote_address_family = IceCandidatePairAddressFamily::kUnknown;
candidate_pair_protocol = IceCandidatePairProtocol::kUnknown;
}
diff --git a/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h b/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
index e72d999cff..8198659cb2 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
+++ b/third_party/libwebrtc/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
@@ -18,6 +18,7 @@
#include <vector>
#include "absl/strings/string_view.h"
+#include "api/candidate.h"
#include "api/rtc_event_log/rtc_event.h"
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
@@ -32,17 +33,6 @@ enum class IceCandidatePairConfigType {
kNumValues,
};
-// TODO(qingsi): Change the names of candidate types to "host", "srflx", "prflx"
-// and "relay" after the naming is spec-compliant in the signaling part
-enum class IceCandidateType {
- kUnknown,
- kLocal,
- kStun,
- kPrflx,
- kRelay,
- kNumValues,
-};
-
enum class IceCandidatePairProtocol {
kUnknown,
kUdp,
@@ -88,7 +78,8 @@ struct LoggedIceCandidatePairConfig {
class IceCandidatePairDescription {
public:
- IceCandidatePairDescription();
+ IceCandidatePairDescription(IceCandidateType local_candidate_type,
+ IceCandidateType remote_candidate_type);
explicit IceCandidatePairDescription(
const IceCandidatePairDescription& other);
diff --git a/third_party/libwebrtc/logging/rtc_event_log/ice_logger.cc b/third_party/libwebrtc/logging/rtc_event_log/ice_logger.cc
index 390deda953..daa7057439 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/ice_logger.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/ice_logger.cc
@@ -26,7 +26,8 @@ void IceEventLog::LogCandidatePairConfig(
if (event_log_ == nullptr) {
return;
}
- candidate_pair_desc_by_id_[candidate_pair_id] = candidate_pair_desc;
+
+ candidate_pair_desc_by_id_.emplace(candidate_pair_id, candidate_pair_desc);
event_log_->Log(std::make_unique<RtcEventIceCandidatePairConfig>(
type, candidate_pair_id, candidate_pair_desc));
}
diff --git a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_impl.cc b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_impl.cc
index 419afd330a..5cafe8a711 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_impl.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_impl.cc
@@ -39,7 +39,7 @@ std::unique_ptr<RtcEventLogEncoder> CreateEncoder(const Environment& env) {
return std::make_unique<RtcEventLogEncoderLegacy>();
} else {
RTC_DLOG(LS_INFO) << "Creating new format encoder for RTC event log.";
- return std::make_unique<RtcEventLogEncoderNewFormat>();
+ return std::make_unique<RtcEventLogEncoderNewFormat>(env.field_trials());
}
}
diff --git a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.cc b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.cc
index 37bb70a69b..d6469e1033 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -163,22 +163,29 @@ IceCandidatePairConfigType GetRuntimeIceCandidatePairConfigType(
return IceCandidatePairConfigType::kAdded;
}
-IceCandidateType GetRuntimeIceCandidateType(
- rtclog::IceCandidatePairConfig::IceCandidateType type) {
- switch (type) {
+// Converts a log type (proto based) to a matching `IceCandidateType` value
+// and checks for validity of the log type (since the enums aren't a perfect
+// match).
+bool GetRuntimeIceCandidateType(
+ rtclog::IceCandidatePairConfig::IceCandidateType log_type,
+ IceCandidateType& parsed_type) {
+ switch (log_type) {
case rtclog::IceCandidatePairConfig::LOCAL:
- return IceCandidateType::kLocal;
+ parsed_type = IceCandidateType::kHost;
+ break;
case rtclog::IceCandidatePairConfig::STUN:
- return IceCandidateType::kStun;
+ parsed_type = IceCandidateType::kSrflx;
+ break;
case rtclog::IceCandidatePairConfig::PRFLX:
- return IceCandidateType::kPrflx;
+ parsed_type = IceCandidateType::kPrflx;
+ break;
case rtclog::IceCandidatePairConfig::RELAY:
- return IceCandidateType::kRelay;
- case rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE:
- return IceCandidateType::kUnknown;
+ parsed_type = IceCandidateType::kRelay;
+ break;
+ default:
+ return false;
}
- RTC_DCHECK_NOTREACHED();
- return IceCandidateType::kUnknown;
+ return true;
}
IceCandidatePairProtocol GetRuntimeIceCandidatePairProtocol(
@@ -806,18 +813,39 @@ IceCandidateType GetRuntimeIceCandidateType(
rtclog2::IceCandidatePairConfig::IceCandidateType type) {
switch (type) {
case rtclog2::IceCandidatePairConfig::LOCAL:
- return IceCandidateType::kLocal;
+ return IceCandidateType::kHost;
case rtclog2::IceCandidatePairConfig::STUN:
- return IceCandidateType::kStun;
+ return IceCandidateType::kSrflx;
case rtclog2::IceCandidatePairConfig::PRFLX:
return IceCandidateType::kPrflx;
case rtclog2::IceCandidatePairConfig::RELAY:
return IceCandidateType::kRelay;
- case rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE:
- return IceCandidateType::kUnknown;
+ default:
+ RTC_DCHECK_NOTREACHED();
+ return IceCandidateType::kHost;
}
- RTC_DCHECK_NOTREACHED();
- return IceCandidateType::kUnknown;
+}
+
+bool GetRuntimeIceCandidateType(
+ rtclog2::IceCandidatePairConfig::IceCandidateType log_type,
+ IceCandidateType& parsed_type) {
+ switch (log_type) {
+ case rtclog2::IceCandidatePairConfig::LOCAL:
+ parsed_type = IceCandidateType::kHost;
+ break;
+ case rtclog2::IceCandidatePairConfig::STUN:
+ parsed_type = IceCandidateType::kSrflx;
+ break;
+ case rtclog2::IceCandidatePairConfig::PRFLX:
+ parsed_type = IceCandidateType::kPrflx;
+ break;
+ case rtclog2::IceCandidatePairConfig::RELAY:
+ parsed_type = IceCandidateType::kRelay;
+ break;
+ default:
+ return false;
+ }
+ return true;
}
IceCandidatePairProtocol GetRuntimeIceCandidatePairProtocol(
@@ -2142,8 +2170,8 @@ ParsedRtcEventLog::GetIceCandidatePairConfig(
RTC_PARSE_CHECK_OR_RETURN(config.has_candidate_pair_id());
res.candidate_pair_id = config.candidate_pair_id();
RTC_PARSE_CHECK_OR_RETURN(config.has_local_candidate_type());
- res.local_candidate_type =
- GetRuntimeIceCandidateType(config.local_candidate_type());
+ RTC_PARSE_CHECK_OR_RETURN(GetRuntimeIceCandidateType(
+ config.local_candidate_type(), res.local_candidate_type));
RTC_PARSE_CHECK_OR_RETURN(config.has_local_relay_protocol());
res.local_relay_protocol =
GetRuntimeIceCandidatePairProtocol(config.local_relay_protocol());
@@ -2154,8 +2182,8 @@ ParsedRtcEventLog::GetIceCandidatePairConfig(
res.local_address_family =
GetRuntimeIceCandidatePairAddressFamily(config.local_address_family());
RTC_PARSE_CHECK_OR_RETURN(config.has_remote_candidate_type());
- res.remote_candidate_type =
- GetRuntimeIceCandidateType(config.remote_candidate_type());
+ RTC_PARSE_CHECK_OR_RETURN(GetRuntimeIceCandidateType(
+ config.remote_candidate_type(), res.remote_candidate_type));
RTC_PARSE_CHECK_OR_RETURN(config.has_remote_address_family());
res.remote_address_family =
GetRuntimeIceCandidatePairAddressFamily(config.remote_address_family());
@@ -2242,13 +2270,13 @@ std::vector<InferredRouteChangeEvent> ParsedRtcEventLog::GetRouteChanges()
if (candidate.remote_address_family ==
IceCandidatePairAddressFamily::kIpv6)
route.send_overhead += kIpv6Overhead - kIpv4Overhead;
- if (candidate.remote_candidate_type != IceCandidateType::kLocal)
+ if (candidate.remote_candidate_type != IceCandidateType::kHost)
route.send_overhead += kStunOverhead;
route.return_overhead = kUdpOverhead + kSrtpOverhead + kIpv4Overhead;
if (candidate.remote_address_family ==
IceCandidatePairAddressFamily::kIpv6)
route.return_overhead += kIpv6Overhead - kIpv4Overhead;
- if (candidate.remote_candidate_type != IceCandidateType::kLocal)
+ if (candidate.remote_candidate_type != IceCandidateType::kHost)
route.return_overhead += kStunOverhead;
route_changes.push_back(route);
}
@@ -3498,8 +3526,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIceCandidatePairConfig(
RTC_PARSE_CHECK_OR_RETURN(proto.has_candidate_pair_id());
ice_config.candidate_pair_id = proto.candidate_pair_id();
RTC_PARSE_CHECK_OR_RETURN(proto.has_local_candidate_type());
- ice_config.local_candidate_type =
- GetRuntimeIceCandidateType(proto.local_candidate_type());
+ RTC_PARSE_CHECK_OR_RETURN(GetRuntimeIceCandidateType(
+ proto.local_candidate_type(), ice_config.local_candidate_type));
RTC_PARSE_CHECK_OR_RETURN(proto.has_local_relay_protocol());
ice_config.local_relay_protocol =
GetRuntimeIceCandidatePairProtocol(proto.local_relay_protocol());
@@ -3510,8 +3538,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIceCandidatePairConfig(
ice_config.local_address_family =
GetRuntimeIceCandidatePairAddressFamily(proto.local_address_family());
RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_candidate_type());
- ice_config.remote_candidate_type =
- GetRuntimeIceCandidateType(proto.remote_candidate_type());
+ RTC_PARSE_CHECK_OR_RETURN(GetRuntimeIceCandidateType(
+ proto.remote_candidate_type(), ice_config.remote_candidate_type));
RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_address_family());
ice_config.remote_address_family =
GetRuntimeIceCandidatePairAddressFamily(proto.remote_address_family());
diff --git a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.h b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.h
index def9f0ab35..c24e5e8186 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_parser.h
@@ -71,12 +71,15 @@ enum PacketDirection { kIncomingPacket = 0, kOutgoingPacket };
enum class LoggedMediaType : uint8_t { kUnknown, kAudio, kVideo };
struct LoggedPacketInfo {
+ static LoggedPacketInfo CreateEmptyForTesting() { return LoggedPacketInfo(); }
+
LoggedPacketInfo(const LoggedRtpPacket& rtp,
LoggedMediaType media_type,
bool rtx,
Timestamp capture_time);
LoggedPacketInfo(const LoggedPacketInfo&);
~LoggedPacketInfo();
+
int64_t log_time_ms() const { return log_packet_time.ms(); }
int64_t log_time_us() const { return log_packet_time.us(); }
uint32_t ssrc;
@@ -114,6 +117,12 @@ struct LoggedPacketInfo {
// time, and this is instead calculated as the difference in reported receive
// time between this packet and the last packet in the same feedback message.
TimeDelta feedback_hold_duration = TimeDelta::MinusInfinity();
+
+ private:
+ LoggedPacketInfo()
+ : capture_time(Timestamp::MinusInfinity()),
+ log_packet_time(Timestamp::MinusInfinity()),
+ reported_send_time(Timestamp::MinusInfinity()) {}
};
struct InferredRouteChangeEvent {
diff --git a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index aece4b5753..bd83586456 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -42,8 +42,8 @@
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/time_utils.h"
-#include "system_wrappers/include/field_trial.h"
#include "system_wrappers/include/ntp_time.h"
+#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
@@ -52,6 +52,9 @@ namespace test {
namespace {
+using ::testing::ElementsAreArray;
+using ::testing::IsEmpty;
+
struct ExtensionPair {
RTPExtensionType type;
const char* name;
@@ -217,10 +220,27 @@ EventGenerator::NewProbeResultSuccess() {
return std::make_unique<RtcEventProbeResultSuccess>(id, bitrate_bps);
}
+constexpr uint32_t CandidateTypeCount() {
+ // This switch statement only exists to catch changes to the IceCandidateType
+ // enumeration. If you get an error here, please update the switch statement
+ // and the return value.
+ IceCandidateType type = IceCandidateType::kHost;
+ switch (type) {
+ case IceCandidateType::kHost:
+ case IceCandidateType::kSrflx:
+ case IceCandidateType::kPrflx:
+ case IceCandidateType::kRelay:
+ break;
+ }
+ return 4u;
+}
+
std::unique_ptr<RtcEventIceCandidatePairConfig>
EventGenerator::NewIceCandidatePairConfig() {
- IceCandidateType local_candidate_type = static_cast<IceCandidateType>(
- prng_.Rand(static_cast<uint32_t>(IceCandidateType::kNumValues) - 1));
+ static_assert(static_cast<int>(IceCandidateType::kHost) == 0,
+ "Expect kLocal to be the first enum value, equal to 0");
+ IceCandidateType local_candidate_type =
+ static_cast<IceCandidateType>(prng_.Rand(CandidateTypeCount() - 1));
IceCandidateNetworkType local_network_type =
static_cast<IceCandidateNetworkType>(prng_.Rand(
static_cast<uint32_t>(IceCandidateNetworkType::kNumValues) - 1));
@@ -228,8 +248,8 @@ EventGenerator::NewIceCandidatePairConfig() {
static_cast<IceCandidatePairAddressFamily>(prng_.Rand(
static_cast<uint32_t>(IceCandidatePairAddressFamily::kNumValues) -
1));
- IceCandidateType remote_candidate_type = static_cast<IceCandidateType>(
- prng_.Rand(static_cast<uint32_t>(IceCandidateType::kNumValues) - 1));
+ IceCandidateType remote_candidate_type =
+ static_cast<IceCandidateType>(prng_.Rand(CandidateTypeCount() - 1));
IceCandidatePairAddressFamily remote_address_family =
static_cast<IceCandidatePairAddressFamily>(prng_.Rand(
static_cast<uint32_t>(IceCandidatePairAddressFamily::kNumValues) -
@@ -238,12 +258,10 @@ EventGenerator::NewIceCandidatePairConfig() {
static_cast<IceCandidatePairProtocol>(prng_.Rand(
static_cast<uint32_t>(IceCandidatePairProtocol::kNumValues) - 1));
- IceCandidatePairDescription desc;
- desc.local_candidate_type = local_candidate_type;
+ IceCandidatePairDescription desc(local_candidate_type, remote_candidate_type);
desc.local_relay_protocol = protocol_type;
desc.local_network_type = local_network_type;
desc.local_address_family = local_address_family;
- desc.remote_candidate_type = remote_candidate_type;
desc.remote_address_family = remote_address_family;
desc.candidate_pair_protocol = protocol_type;
@@ -1032,23 +1050,15 @@ void VerifyLoggedRtpHeader(const Event& original_header,
}
template <typename Event>
-void VerifyLoggedDependencyDescriptor(const Event& packet,
- const std::vector<uint8_t>& logged_dd) {
- if (webrtc::field_trial::IsDisabled(
- "WebRTC-RtcEventLogEncodeDependencyDescriptor")) {
- EXPECT_TRUE(logged_dd.empty());
- } else {
+void EventVerifier::VerifyLoggedDependencyDescriptor(
+ const Event& packet,
+ const std::vector<uint8_t>& logged_dd) const {
+ if (expect_dependency_descriptor_rtp_header_extension_is_set_) {
rtc::ArrayView<const uint8_t> original =
packet.template GetRawExtension<RtpDependencyDescriptorExtension>();
- EXPECT_EQ(logged_dd.size(), original.size());
- bool dd_is_same = true;
- for (size_t i = 0; i < logged_dd.size(); ++i) {
- dd_is_same = logged_dd[i] == original[i];
- if (!dd_is_same) {
- break;
- }
- }
- EXPECT_TRUE(dd_is_same);
+ EXPECT_THAT(logged_dd, ElementsAreArray(original));
+ } else {
+ EXPECT_THAT(logged_dd, IsEmpty());
}
}
diff --git a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h
index 950a622f8b..e0fd3b741b 100644
--- a/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h
+++ b/third_party/libwebrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h
@@ -160,6 +160,10 @@ class EventVerifier {
explicit EventVerifier(RtcEventLog::EncodingType encoding_type)
: encoding_type_(encoding_type) {}
+ void ExpectDependencyDescriptorExtensionIsSet(bool value) {
+ expect_dependency_descriptor_rtp_header_extension_is_set_ = value;
+ }
+
void VerifyLoggedAlrStateEvent(const RtcEventAlrState& original_event,
const LoggedAlrStateEvent& logged_event) const;
@@ -331,7 +335,13 @@ class EventVerifier {
void VerifyReportBlock(const rtcp::ReportBlock& original_report_block,
const rtcp::ReportBlock& logged_report_block);
+ template <typename Event>
+ void VerifyLoggedDependencyDescriptor(
+ const Event& packet,
+ const std::vector<uint8_t>& logged_dd) const;
+
RtcEventLog::EncodingType encoding_type_;
+ bool expect_dependency_descriptor_rtp_header_extension_is_set_ = true;
};
} // namespace test
diff --git a/third_party/libwebrtc/media/BUILD.gn b/third_party/libwebrtc/media/BUILD.gn
index 44638d562e..7a489f0c43 100644
--- a/third_party/libwebrtc/media/BUILD.gn
+++ b/third_party/libwebrtc/media/BUILD.gn
@@ -395,6 +395,7 @@ rtc_library("rtc_internal_video_codecs") {
":media_constants",
":rtc_media_base",
":rtc_simulcast_encoder_adapter",
+ "../api/environment",
"../api/video:encoded_image",
"../api/video:video_bitrate_allocation",
"../api/video:video_frame",
@@ -615,6 +616,7 @@ rtc_source_set("rtc_data_sctp_transport_internal") {
"../api:rtc_error",
"../api/transport:datagram_transport_interface",
"../media:rtc_media_base",
+ "../p2p:packet_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:copy_on_write_buffer",
"../rtc_base:threading",
@@ -639,6 +641,7 @@ if (rtc_build_dcsctp) {
"../net/dcsctp/public:types",
"../net/dcsctp/public:utils",
"../net/dcsctp/timer:task_queue_timeout",
+ "../p2p:packet_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:copy_on_write_buffer",
diff --git a/third_party/libwebrtc/media/base/codec_unittest.cc b/third_party/libwebrtc/media/base/codec_unittest.cc
index 4dc3b18c21..e1e69eb082 100644
--- a/third_party/libwebrtc/media/base/codec_unittest.cc
+++ b/third_party/libwebrtc/media/base/codec_unittest.cc
@@ -228,11 +228,11 @@ TEST(CodecTest, TestAV1CodecMatches) {
VideoCodec c_no_profile =
cricket::CreateVideoCodec(95, cricket::kAv1CodecName);
VideoCodec c_profile0 = cricket::CreateVideoCodec(95, cricket::kAv1CodecName);
- c_profile0.params[webrtc::kAV1FmtpProfile] = kProfile0;
+ c_profile0.params[cricket::kAv1FmtpProfile] = kProfile0;
VideoCodec c_profile1 = cricket::CreateVideoCodec(95, cricket::kAv1CodecName);
- c_profile1.params[webrtc::kAV1FmtpProfile] = kProfile1;
+ c_profile1.params[cricket::kAv1FmtpProfile] = kProfile1;
VideoCodec c_profile2 = cricket::CreateVideoCodec(95, cricket::kAv1CodecName);
- c_profile2.params[webrtc::kAV1FmtpProfile] = kProfile2;
+ c_profile2.params[cricket::kAv1FmtpProfile] = kProfile2;
// An AV1 entry with no profile specified should be treated as profile-0.
EXPECT_TRUE(c_profile0.Matches(c_no_profile));
@@ -248,7 +248,7 @@ TEST(CodecTest, TestAV1CodecMatches) {
// Two AV1 entries with profile 0 specified are treated as duplicates.
VideoCodec c_profile0_eq =
cricket::CreateVideoCodec(95, cricket::kAv1CodecName);
- c_profile0_eq.params[webrtc::kAV1FmtpProfile] = kProfile0;
+ c_profile0_eq.params[cricket::kAv1FmtpProfile] = kProfile0;
EXPECT_TRUE(c_profile0.Matches(c_profile0_eq));
}
@@ -256,7 +256,7 @@ TEST(CodecTest, TestAV1CodecMatches) {
// Two AV1 entries with profile 1 specified are treated as duplicates.
VideoCodec c_profile1_eq =
cricket::CreateVideoCodec(95, cricket::kAv1CodecName);
- c_profile1_eq.params[webrtc::kAV1FmtpProfile] = kProfile1;
+ c_profile1_eq.params[cricket::kAv1FmtpProfile] = kProfile1;
EXPECT_TRUE(c_profile1.Matches(c_profile1_eq));
}
diff --git a/third_party/libwebrtc/media/base/media_constants.cc b/third_party/libwebrtc/media/base/media_constants.cc
index 2af0295a5a..1a7561aa52 100644
--- a/third_party/libwebrtc/media/base/media_constants.cc
+++ b/third_party/libwebrtc/media/base/media_constants.cc
@@ -124,8 +124,14 @@ const char kH265FmtpProfileCompatibilityIndicator[] =
const char kH265FmtpInteropConstraints[] = "interop-constraints";
const char kH265FmtpTxMode[] = "tx-mode";
+// draft-ietf-payload-vp9
const char kVP9ProfileId[] = "profile-id";
+// https://aomediacodec.github.io/av1-rtp-spec/
+const char kAv1FmtpProfile[] = "profile";
+const char kAv1FmtpLevelIdx[] = "level-idx";
+const char kAv1FmtpTier[] = "tier";
+
const int kDefaultVideoMaxFramerate = 60;
// Max encode quantizer for VP8/9 and AV1 encoders assuming libvpx/libaom API
// range [0, 63]
diff --git a/third_party/libwebrtc/media/base/media_constants.h b/third_party/libwebrtc/media/base/media_constants.h
index 877cc7a296..d5af17eb2a 100644
--- a/third_party/libwebrtc/media/base/media_constants.h
+++ b/third_party/libwebrtc/media/base/media_constants.h
@@ -147,8 +147,14 @@ RTC_EXPORT extern const char kH265FmtpProfileCompatibilityIndicator[];
RTC_EXPORT extern const char kH265FmtpInteropConstraints[];
RTC_EXPORT extern const char kH265FmtpTxMode[];
+// draft-ietf-payload-vp9
extern const char kVP9ProfileId[];
+// https://aomediacodec.github.io/av1-rtp-spec/
+extern const char kAv1FmtpProfile[];
+extern const char kAv1FmtpLevelIdx[];
+extern const char kAv1FmtpTier[];
+
extern const int kDefaultVideoMaxFramerate;
extern const int kDefaultVideoMaxQpVpx;
extern const int kDefaultVideoMaxQpH26x;
diff --git a/third_party/libwebrtc/media/engine/fake_webrtc_call.cc b/third_party/libwebrtc/media/engine/fake_webrtc_call.cc
index 16e7169b21..2536c9dd85 100644
--- a/third_party/libwebrtc/media/engine/fake_webrtc_call.cc
+++ b/third_party/libwebrtc/media/engine/fake_webrtc_call.cc
@@ -339,17 +339,6 @@ void FakeVideoSendStream::ReconfigureVideoEncoder(
webrtc::InvokeSetParametersCallback(callback, webrtc::RTCError::OK());
}
-void FakeVideoSendStream::StartPerRtpStream(
- const std::vector<bool> active_layers) {
- sending_ = false;
- for (const bool active_layer : active_layers) {
- if (active_layer) {
- sending_ = true;
- break;
- }
- }
-}
-
void FakeVideoSendStream::Start() {
sending_ = true;
}
diff --git a/third_party/libwebrtc/media/engine/fake_webrtc_call.h b/third_party/libwebrtc/media/engine/fake_webrtc_call.h
index 3dd6bdf397..d67a7ee452 100644
--- a/third_party/libwebrtc/media/engine/fake_webrtc_call.h
+++ b/third_party/libwebrtc/media/engine/fake_webrtc_call.h
@@ -199,7 +199,6 @@ class FakeVideoSendStream final
void OnFrame(const webrtc::VideoFrame& frame) override;
// webrtc::VideoSendStream implementation.
- void StartPerRtpStream(std::vector<bool> active_layers) override;
void Start() override;
void Stop() override;
bool started() override { return IsSending(); }
diff --git a/third_party/libwebrtc/media/engine/internal_decoder_factory.cc b/third_party/libwebrtc/media/engine/internal_decoder_factory.cc
index 001c666313..139f49d420 100644
--- a/third_party/libwebrtc/media/engine/internal_decoder_factory.cc
+++ b/third_party/libwebrtc/media/engine/internal_decoder_factory.cc
@@ -52,9 +52,10 @@ std::vector<SdpVideoFormat> InternalDecoderFactory::GetSupportedFormats()
#if !defined(WEBRTC_MOZILLA_BUILD)
if (kDav1dIsIncluded) {
formats.push_back(SdpVideoFormat(cricket::kAv1CodecName));
- formats.push_back(SdpVideoFormat(
- cricket::kAv1CodecName,
- {{kAV1FmtpProfile, AV1ProfileToString(AV1Profile::kProfile1).data()}}));
+ formats.push_back(
+ SdpVideoFormat(cricket::kAv1CodecName,
+ {{cricket::kAv1FmtpProfile,
+ AV1ProfileToString(AV1Profile::kProfile1).data()}}));
}
#endif
diff --git a/third_party/libwebrtc/media/engine/internal_decoder_factory_unittest.cc b/third_party/libwebrtc/media/engine/internal_decoder_factory_unittest.cc
index 51d6a94dd6..e06b4c3d77 100644
--- a/third_party/libwebrtc/media/engine/internal_decoder_factory_unittest.cc
+++ b/third_party/libwebrtc/media/engine/internal_decoder_factory_unittest.cc
@@ -121,7 +121,7 @@ TEST(InternalDecoderFactoryTest, Av1Profile1_Dav1dDecoderTrialEnabled) {
InternalDecoderFactory factory;
std::unique_ptr<VideoDecoder> decoder = factory.CreateVideoDecoder(
SdpVideoFormat(cricket::kAv1CodecName,
- {{kAV1FmtpProfile,
+ {{cricket::kAv1FmtpProfile,
AV1ProfileToString(AV1Profile::kProfile1).data()}}));
EXPECT_EQ(static_cast<bool>(decoder), kDav1dIsIncluded);
}
diff --git a/third_party/libwebrtc/media/engine/multiplex_codec_factory.cc b/third_party/libwebrtc/media/engine/multiplex_codec_factory.cc
index 90df02a77e..cf17b46d7d 100644
--- a/third_party/libwebrtc/media/engine/multiplex_codec_factory.cc
+++ b/third_party/libwebrtc/media/engine/multiplex_codec_factory.cc
@@ -11,10 +11,12 @@
#include "media/engine/multiplex_codec_factory.h"
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include "absl/strings/match.h"
+#include "api/environment/environment.h"
#include "api/video_codecs/sdp_video_format.h"
#include "media/base/codec.h"
#include "media/base/media_constants.h"
@@ -95,20 +97,21 @@ std::vector<SdpVideoFormat> MultiplexDecoderFactory::GetSupportedFormats()
return augmented_formats;
}
-std::unique_ptr<VideoDecoder> MultiplexDecoderFactory::CreateVideoDecoder(
+std::unique_ptr<VideoDecoder> MultiplexDecoderFactory::Create(
+ const Environment& env,
const SdpVideoFormat& format) {
- if (!IsMultiplexCodec(cricket::CreateVideoCodec(format)))
- return factory_->CreateVideoDecoder(format);
- const auto& it =
- format.parameters.find(cricket::kCodecParamAssociatedCodecName);
+ if (!IsMultiplexCodec(cricket::CreateVideoCodec(format))) {
+ return factory_->Create(env, format);
+ }
+ auto it = format.parameters.find(cricket::kCodecParamAssociatedCodecName);
if (it == format.parameters.end()) {
RTC_LOG(LS_ERROR) << "No assicated codec for multiplex.";
return nullptr;
}
SdpVideoFormat associated_format = format;
associated_format.name = it->second;
- return std::unique_ptr<VideoDecoder>(new MultiplexDecoderAdapter(
- factory_.get(), associated_format, supports_augmenting_data_));
+ return std::make_unique<MultiplexDecoderAdapter>(
+ env, factory_.get(), associated_format, supports_augmenting_data_);
}
} // namespace webrtc
diff --git a/third_party/libwebrtc/media/engine/multiplex_codec_factory.h b/third_party/libwebrtc/media/engine/multiplex_codec_factory.h
index a4272a2eb2..164164f3ee 100644
--- a/third_party/libwebrtc/media/engine/multiplex_codec_factory.h
+++ b/third_party/libwebrtc/media/engine/multiplex_codec_factory.h
@@ -14,6 +14,7 @@
#include <memory>
#include <vector>
+#include "api/environment/environment.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_decoder_factory.h"
@@ -66,8 +67,8 @@ class RTC_EXPORT MultiplexDecoderFactory : public VideoDecoderFactory {
bool supports_augmenting_data = false);
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
- std::unique_ptr<VideoDecoder> CreateVideoDecoder(
- const SdpVideoFormat& format) override;
+ std::unique_ptr<VideoDecoder> Create(const Environment& env,
+ const SdpVideoFormat& format) override;
private:
std::unique_ptr<VideoDecoderFactory> factory_;
diff --git a/third_party/libwebrtc/media/engine/multiplex_codec_factory_unittest.cc b/third_party/libwebrtc/media/engine/multiplex_codec_factory_unittest.cc
index 1cde2f37d8..7f0a418d4d 100644
--- a/third_party/libwebrtc/media/engine/multiplex_codec_factory_unittest.cc
+++ b/third_party/libwebrtc/media/engine/multiplex_codec_factory_unittest.cc
@@ -10,8 +10,10 @@
#include "media/engine/multiplex_codec_factory.h"
+#include <memory>
#include <utility>
+#include "api/environment/environment_factory.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_encoder.h"
@@ -22,12 +24,13 @@
namespace webrtc {
-TEST(MultiplexDecoderFactory, CreateVideoDecoder) {
- std::unique_ptr<VideoDecoderFactory> internal_factory(
- new InternalDecoderFactory());
+TEST(MultiplexDecoderFactoryTest, CreateVideoDecoder) {
+ std::unique_ptr<VideoDecoderFactory> internal_factory =
+ std::make_unique<InternalDecoderFactory>();
MultiplexDecoderFactory factory(std::move(internal_factory));
- std::unique_ptr<VideoDecoder> decoder =
- factory.CreateVideoDecoder(SdpVideoFormat(
+ std::unique_ptr<VideoDecoder> decoder = factory.Create(
+ CreateEnvironment(),
+ SdpVideoFormat(
cricket::kMultiplexCodecName,
{{cricket::kCodecParamAssociatedCodecName, cricket::kVp9CodecName}}));
EXPECT_TRUE(decoder);
diff --git a/third_party/libwebrtc/media/engine/simulcast_encoder_adapter.cc b/third_party/libwebrtc/media/engine/simulcast_encoder_adapter.cc
index 4853e68996..642fe31e90 100644
--- a/third_party/libwebrtc/media/engine/simulcast_encoder_adapter.cc
+++ b/third_party/libwebrtc/media/engine/simulcast_encoder_adapter.cc
@@ -32,6 +32,7 @@
#include "media/base/media_constants.h"
#include "media/base/video_common.h"
#include "modules/video_coding/include/video_error_codes.h"
+#include "modules/video_coding/include/video_error_codes_utils.h"
#include "modules/video_coding/utility/simulcast_rate_allocator.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/rate_control_settings.h"
@@ -360,8 +361,14 @@ int SimulcastEncoderAdapter::InitEncode(
bool separate_encoders_needed =
!encoder_context->encoder().GetEncoderInfo().supports_simulcast ||
active_streams_count == 1;
+ RTC_LOG(LS_INFO) << "[SEA] InitEncode: total_streams_count: "
+ << total_streams_count_
+ << ", active_streams_count: " << active_streams_count
+ << ", separate_encoders_needed: "
+ << (separate_encoders_needed ? "true" : "false");
// Singlecast or simulcast with simulcast-capable underlaying encoder.
if (total_streams_count_ == 1 || !separate_encoders_needed) {
+ RTC_LOG(LS_INFO) << "[SEA] InitEncode: Single-encoder mode";
int ret = encoder_context->encoder().InitEncode(&codec_, settings);
if (ret >= 0) {
stream_contexts_.emplace_back(
@@ -377,7 +384,8 @@ int SimulcastEncoderAdapter::InitEncode(
encoder_context->Release();
if (total_streams_count_ == 1) {
- // Failed to initialize singlecast encoder.
+ RTC_LOG(LS_ERROR) << "[SEA] InitEncode: failed with error code: "
+ << WebRtcVideoCodecErrorToString(ret);
return ret;
}
}
@@ -405,10 +413,16 @@ int SimulcastEncoderAdapter::InitEncode(
/*is_lowest_quality_stream=*/stream_idx == lowest_quality_stream_idx,
/*is_highest_quality_stream=*/stream_idx == highest_quality_stream_idx);
+ RTC_LOG(LS_INFO) << "[SEA] Multi-encoder mode: initializing stream: "
+ << stream_idx << ", active: "
+ << (codec_.simulcastStream[stream_idx].active ? "true"
+ : "false");
int ret = encoder_context->encoder().InitEncode(&stream_codec, settings);
if (ret < 0) {
encoder_context.reset();
Release();
+ RTC_LOG(LS_ERROR) << "[SEA] InitEncode: failed with error code: "
+ << WebRtcVideoCodecErrorToString(ret);
return ret;
}
diff --git a/third_party/libwebrtc/media/engine/webrtc_video_engine.cc b/third_party/libwebrtc/media/engine/webrtc_video_engine.cc
index a5b46d3344..a313407f2d 100644
--- a/third_party/libwebrtc/media/engine/webrtc_video_engine.cc
+++ b/third_party/libwebrtc/media/engine/webrtc_video_engine.cc
@@ -811,6 +811,8 @@ std::vector<VideoCodec> WebRtcVideoEngine::recv_codecs(bool include_rtx) const {
std::vector<webrtc::RtpHeaderExtensionCapability>
WebRtcVideoEngine::GetRtpHeaderExtensions() const {
std::vector<webrtc::RtpHeaderExtensionCapability> result;
+ // id is *not* incremented for non-default extensions, UsedIds needs to
+ // resolve conflicts.
int id = 1;
for (const auto& uri :
{webrtc::RtpExtension::kTimestampOffsetUri,
@@ -825,27 +827,26 @@ WebRtcVideoEngine::GetRtpHeaderExtensions() const {
result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kSendRecv);
}
for (const auto& uri : {webrtc::RtpExtension::kAbsoluteCaptureTimeUri}) {
- result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kStopped);
+ result.emplace_back(uri, id, webrtc::RtpTransceiverDirection::kStopped);
}
- result.emplace_back(webrtc::RtpExtension::kGenericFrameDescriptorUri00, id++,
+ result.emplace_back(webrtc::RtpExtension::kGenericFrameDescriptorUri00, id,
IsEnabled(trials_, "WebRTC-GenericDescriptorAdvertised")
? webrtc::RtpTransceiverDirection::kSendRecv
: webrtc::RtpTransceiverDirection::kStopped);
result.emplace_back(
- webrtc::RtpExtension::kDependencyDescriptorUri, id++,
+ webrtc::RtpExtension::kDependencyDescriptorUri, id,
IsEnabled(trials_, "WebRTC-DependencyDescriptorAdvertised")
? webrtc::RtpTransceiverDirection::kSendRecv
: webrtc::RtpTransceiverDirection::kStopped);
-
result.emplace_back(
- webrtc::RtpExtension::kVideoLayersAllocationUri, id++,
+ webrtc::RtpExtension::kVideoLayersAllocationUri, id,
IsEnabled(trials_, "WebRTC-VideoLayersAllocationAdvertised")
? webrtc::RtpTransceiverDirection::kSendRecv
: webrtc::RtpTransceiverDirection::kStopped);
// VideoFrameTrackingId is a test-only extension.
if (IsEnabled(trials_, "WebRTC-VideoFrameTrackingIdAdvertised")) {
- result.emplace_back(webrtc::RtpExtension::kVideoFrameTrackingIdUri, id++,
+ result.emplace_back(webrtc::RtpExtension::kVideoFrameTrackingIdUri, id,
webrtc::RtpTransceiverDirection::kSendRecv);
}
return result;
@@ -2013,6 +2014,7 @@ WebRtcVideoSendChannel::WebRtcVideoSendStream::SetRtpParameters(
new_send_state = true;
}
}
+
rtp_parameters_ = new_parameters;
// Codecs are currently handled at the WebRtcVideoSendChannel level.
rtp_parameters_.codecs.clear();
@@ -2021,9 +2023,6 @@ WebRtcVideoSendChannel::WebRtcVideoSendStream::SetRtpParameters(
ReconfigureEncoder(std::move(callback));
callback = nullptr;
}
- if (new_send_state) {
- UpdateSendState();
- }
if (new_degradation_preference) {
if (source_ && stream_) {
stream_->SetSource(source_, GetDegradationPreference());
@@ -2082,27 +2081,9 @@ void WebRtcVideoSendChannel::WebRtcVideoSendStream::UpdateSendState() {
RTC_DCHECK_RUN_ON(&thread_checker_);
if (sending_) {
RTC_DCHECK(stream_ != nullptr);
- size_t num_layers = rtp_parameters_.encodings.size();
- if (parameters_.encoder_config.number_of_streams == 1) {
- // SVC is used. Only one simulcast layer is present.
- num_layers = 1;
- }
- std::vector<bool> active_layers(num_layers);
- for (size_t i = 0; i < num_layers; ++i) {
- active_layers[i] = IsLayerActive(rtp_parameters_.encodings[i]);
- }
- if (parameters_.encoder_config.number_of_streams == 1 &&
- rtp_parameters_.encodings.size() > 1) {
- // SVC is used.
- // The only present simulcast layer should be active if any of the
- // configured SVC layers is active.
- active_layers[0] =
- absl::c_any_of(rtp_parameters_.encodings,
- [](const auto& encoding) { return encoding.active; });
- }
- // This updates what simulcast layers are sending, and possibly starts
- // or stops the VideoSendStream.
- stream_->StartPerRtpStream(active_layers);
+ // This allows the the Stream to be used. Ie, DTLS is connected and the
+ // RtpTransceiver direction allows sending.
+ stream_->Start();
} else {
if (stream_ != nullptr) {
stream_->Stop();
diff --git a/third_party/libwebrtc/media/engine/webrtc_video_engine.h b/third_party/libwebrtc/media/engine/webrtc_video_engine.h
index e4b1b2765b..d370a5445b 100644
--- a/third_party/libwebrtc/media/engine/webrtc_video_engine.h
+++ b/third_party/libwebrtc/media/engine/webrtc_video_engine.h
@@ -250,10 +250,6 @@ class WebRtcVideoSendChannel : public MediaChannelUtil,
ADAPTREASON_BANDWIDTH = 2,
};
- // TODO(webrtc:14852): Update downstream projects to use
- // cricket::kDefaultVideoMaxQpVpx/H26x and remove.
- static constexpr int kDefaultQpMax = 56;
-
// Implements webrtc::EncoderSwitchRequestCallback.
void RequestEncoderFallback() override;
void RequestEncoderSwitch(const webrtc::SdpVideoFormat& format,
@@ -402,8 +398,7 @@ class WebRtcVideoSendChannel : public MediaChannelUtil,
const VideoCodec& codec) const;
void ReconfigureEncoder(webrtc::SetParametersCallback callback);
- // Calls Start or Stop according to whether or not `sending_` is true,
- // and whether or not the encoding in `rtp_parameters_` is active.
+ // Calls Start or Stop according to whether or not `sending_` is true.
void UpdateSendState();
webrtc::DegradationPreference GetDegradationPreference() const
diff --git a/third_party/libwebrtc/media/engine/webrtc_video_engine_unittest.cc b/third_party/libwebrtc/media/engine/webrtc_video_engine_unittest.cc
index 148223f497..4493c9c616 100644
--- a/third_party/libwebrtc/media/engine/webrtc_video_engine_unittest.cc
+++ b/third_party/libwebrtc/media/engine/webrtc_video_engine_unittest.cc
@@ -9078,105 +9078,6 @@ TEST_F(WebRtcVideoChannelTest, DefaultMinAndMaxBitratePropagatedToEncoder) {
stream->GetVideoStreams()[0].target_bitrate_bps);
}
-// Test that a stream will not be sending if its encoding is made inactive
-// through SetRtpSendParameters.
-TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersOneEncodingActive) {
- FakeVideoSendStream* stream = AddSendStream();
- EXPECT_TRUE(send_channel_->SetSend(true));
- EXPECT_TRUE(stream->IsSending());
-
- // Get current parameters and change "active" to false.
- webrtc::RtpParameters parameters =
- send_channel_->GetRtpSendParameters(last_ssrc_);
- ASSERT_EQ(1u, parameters.encodings.size());
- ASSERT_TRUE(parameters.encodings[0].active);
- parameters.encodings[0].active = false;
- EXPECT_TRUE(send_channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
- EXPECT_FALSE(stream->IsSending());
-
- // Now change it back to active and verify we resume sending.
- parameters.encodings[0].active = true;
- EXPECT_TRUE(send_channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
- EXPECT_TRUE(stream->IsSending());
-}
-
-// Tests that when active is updated for any simulcast layer then the send
-// stream's sending state will be updated and it will be reconfigured with the
-// new appropriate active simulcast streams.
-TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersMultipleEncodingsActive) {
- // Create the stream params with multiple ssrcs for simulcast.
- const size_t kNumSimulcastStreams = 3;
- std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
- StreamParams stream_params = CreateSimStreamParams("cname", ssrcs);
- FakeVideoSendStream* fake_video_send_stream = AddSendStream(stream_params);
- uint32_t primary_ssrc = stream_params.first_ssrc();
-
- // Using the FrameForwarder, we manually send a full size
- // frame. This allows us to test that ReconfigureEncoder is called
- // appropriately.
- webrtc::test::FrameForwarder frame_forwarder;
- VideoOptions options;
- EXPECT_TRUE(
- send_channel_->SetVideoSend(primary_ssrc, &options, &frame_forwarder));
- send_channel_->SetSend(true);
- frame_forwarder.IncomingCapturedFrame(frame_source_.GetFrame(
- 1920, 1080, webrtc::VideoRotation::kVideoRotation_0,
- rtc::kNumMicrosecsPerSec / 30));
-
- // Check that all encodings are initially active.
- webrtc::RtpParameters parameters =
- send_channel_->GetRtpSendParameters(primary_ssrc);
- EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
- EXPECT_TRUE(parameters.encodings[0].active);
- EXPECT_TRUE(parameters.encodings[1].active);
- EXPECT_TRUE(parameters.encodings[2].active);
- EXPECT_TRUE(fake_video_send_stream->IsSending());
-
- // Only turn on only the middle stream.
- parameters.encodings[0].active = false;
- parameters.encodings[1].active = true;
- parameters.encodings[2].active = false;
- EXPECT_TRUE(
- send_channel_->SetRtpSendParameters(primary_ssrc, parameters).ok());
- // Verify that the active fields are set on the VideoChannel.
- parameters = send_channel_->GetRtpSendParameters(primary_ssrc);
- EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
- EXPECT_FALSE(parameters.encodings[0].active);
- EXPECT_TRUE(parameters.encodings[1].active);
- EXPECT_FALSE(parameters.encodings[2].active);
- // Check that the VideoSendStream is updated appropriately. This means its
- // send state was updated and it was reconfigured.
- EXPECT_TRUE(fake_video_send_stream->IsSending());
- std::vector<webrtc::VideoStream> simulcast_streams =
- fake_video_send_stream->GetVideoStreams();
- EXPECT_EQ(kNumSimulcastStreams, simulcast_streams.size());
- EXPECT_FALSE(simulcast_streams[0].active);
- EXPECT_TRUE(simulcast_streams[1].active);
- EXPECT_FALSE(simulcast_streams[2].active);
-
- // Turn off all streams.
- parameters.encodings[0].active = false;
- parameters.encodings[1].active = false;
- parameters.encodings[2].active = false;
- EXPECT_TRUE(
- send_channel_->SetRtpSendParameters(primary_ssrc, parameters).ok());
- // Verify that the active fields are set on the VideoChannel.
- parameters = send_channel_->GetRtpSendParameters(primary_ssrc);
- EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
- EXPECT_FALSE(parameters.encodings[0].active);
- EXPECT_FALSE(parameters.encodings[1].active);
- EXPECT_FALSE(parameters.encodings[2].active);
- // Check that the VideoSendStream is off.
- EXPECT_FALSE(fake_video_send_stream->IsSending());
- simulcast_streams = fake_video_send_stream->GetVideoStreams();
- EXPECT_EQ(kNumSimulcastStreams, simulcast_streams.size());
- EXPECT_FALSE(simulcast_streams[0].active);
- EXPECT_FALSE(simulcast_streams[1].active);
- EXPECT_FALSE(simulcast_streams[2].active);
-
- EXPECT_TRUE(send_channel_->SetVideoSend(primary_ssrc, nullptr, nullptr));
-}
-
// Tests that when some streams are disactivated then the lowest
// stream min_bitrate would be reused for the first active stream.
TEST_F(WebRtcVideoChannelTest,
@@ -9232,47 +9133,6 @@ TEST_F(WebRtcVideoChannelTest,
EXPECT_TRUE(send_channel_->SetVideoSend(primary_ssrc, nullptr, nullptr));
}
-// Test that if a stream is reconfigured (due to a codec change or other
-// change) while its encoding is still inactive, it doesn't start sending.
-TEST_F(WebRtcVideoChannelTest,
- InactiveStreamDoesntStartSendingWhenReconfigured) {
- // Set an initial codec list, which will be modified later.
- cricket::VideoSenderParameters parameters1;
- parameters1.codecs.push_back(GetEngineCodec("VP8"));
- parameters1.codecs.push_back(GetEngineCodec("VP9"));
- EXPECT_TRUE(send_channel_->SetSenderParameters(parameters1));
-
- FakeVideoSendStream* stream = AddSendStream();
- EXPECT_TRUE(send_channel_->SetSend(true));
- EXPECT_TRUE(stream->IsSending());
-
- // Get current parameters and change "active" to false.
- webrtc::RtpParameters parameters =
- send_channel_->GetRtpSendParameters(last_ssrc_);
- ASSERT_EQ(1u, parameters.encodings.size());
- ASSERT_TRUE(parameters.encodings[0].active);
- parameters.encodings[0].active = false;
- EXPECT_EQ(1u, GetFakeSendStreams().size());
- EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
- EXPECT_TRUE(send_channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
- EXPECT_FALSE(stream->IsSending());
-
- // Reorder the codec list, causing the stream to be reconfigured.
- cricket::VideoSenderParameters parameters2;
- parameters2.codecs.push_back(GetEngineCodec("VP9"));
- parameters2.codecs.push_back(GetEngineCodec("VP8"));
- EXPECT_TRUE(send_channel_->SetSenderParameters(parameters2));
- auto new_streams = GetFakeSendStreams();
- // Assert that a new underlying stream was created due to the codec change.
- // Otherwise, this test isn't testing what it set out to test.
- EXPECT_EQ(1u, GetFakeSendStreams().size());
- EXPECT_EQ(2, fake_call_->GetNumCreatedSendStreams());
-
- // Verify that we still are not sending anything, due to the inactive
- // encoding.
- EXPECT_FALSE(new_streams[0]->IsSending());
-}
-
// Test that GetRtpSendParameters returns the currently configured codecs.
TEST_F(WebRtcVideoChannelTest, GetRtpSendParametersCodecs) {
AddSendStream();
diff --git a/third_party/libwebrtc/media/engine/webrtc_voice_engine.cc b/third_party/libwebrtc/media/engine/webrtc_voice_engine.cc
index fcc2703f98..23a1b1927c 100644
--- a/third_party/libwebrtc/media/engine/webrtc_voice_engine.cc
+++ b/third_party/libwebrtc/media/engine/webrtc_voice_engine.cc
@@ -643,6 +643,8 @@ std::vector<webrtc::RtpHeaderExtensionCapability>
WebRtcVoiceEngine::GetRtpHeaderExtensions() const {
RTC_DCHECK(signal_thread_checker_.IsCurrent());
std::vector<webrtc::RtpHeaderExtensionCapability> result;
+ // id is *not* incremented for non-default extensions, UsedIds needs to
+ // resolve conflicts.
int id = 1;
for (const auto& uri : {webrtc::RtpExtension::kAudioLevelUri,
webrtc::RtpExtension::kAbsSendTimeUri,
@@ -651,7 +653,7 @@ WebRtcVoiceEngine::GetRtpHeaderExtensions() const {
result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kSendRecv);
}
for (const auto& uri : {webrtc::RtpExtension::kAbsoluteCaptureTimeUri}) {
- result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kStopped);
+ result.emplace_back(uri, id, webrtc::RtpTransceiverDirection::kStopped);
}
return result;
}
diff --git a/third_party/libwebrtc/modules/audio_coding/BUILD.gn b/third_party/libwebrtc/modules/audio_coding/BUILD.gn
index ddd1fd2656..a49df7e7d2 100644
--- a/third_party/libwebrtc/modules/audio_coding/BUILD.gn
+++ b/third_party/libwebrtc/modules/audio_coding/BUILD.gn
@@ -689,8 +689,6 @@ rtc_library("neteq") {
"neteq/packet_arrival_history.h",
"neteq/packet_buffer.cc",
"neteq/packet_buffer.h",
- "neteq/post_decode_vad.cc",
- "neteq/post_decode_vad.h",
"neteq/preemptive_expand.cc",
"neteq/preemptive_expand.h",
"neteq/random_vector.cc",
@@ -1655,7 +1653,6 @@ if (rtc_include_tests) {
"neteq/normal_unittest.cc",
"neteq/packet_arrival_history_unittest.cc",
"neteq/packet_buffer_unittest.cc",
- "neteq/post_decode_vad_unittest.cc",
"neteq/random_vector_unittest.cc",
"neteq/red_payload_splitter_unittest.cc",
"neteq/reorder_optimizer_unittest.cc",
diff --git a/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver.cc b/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver.cc
index a5bf88e547..4deabdf7ff 100644
--- a/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver.cc
+++ b/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver.cc
@@ -50,11 +50,7 @@ std::unique_ptr<NetEq> CreateNetEq(
AcmReceiver::Config::Config(
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)
- : clock(*Clock::GetRealTimeClockRaw()), decoder_factory(decoder_factory) {
- // Post-decode VAD is disabled by default in NetEq, however, Audio
- // Conference Mixer relies on VAD decisions and fails without them.
- neteq_config.enable_post_decode_vad = true;
-}
+ : clock(*Clock::GetRealTimeClockRaw()), decoder_factory(decoder_factory) {}
AcmReceiver::Config::Config(const Config&) = default;
AcmReceiver::Config::~Config() = default;
diff --git a/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc b/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc
index cda6688157..8b35f4a621 100644
--- a/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc
+++ b/third_party/libwebrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc
@@ -190,9 +190,6 @@ class AcmReceiverTestFaxModeOldApi : public AcmReceiverTestOldApi {
const size_t output_channels = info.num_channels;
const size_t samples_per_ms = rtc::checked_cast<size_t>(
rtc::CheckedDivExact(output_sample_rate_hz, 1000));
- const AudioFrame::VADActivity expected_vad_activity =
- output_sample_rate_hz > 16000 ? AudioFrame::kVadActive
- : AudioFrame::kVadPassive;
// Expect the first output timestamp to be 5*fs/8000 samples before the
// first inserted timestamp (because of NetEq's look-ahead). (This value is
@@ -217,7 +214,6 @@ class AcmReceiverTestFaxModeOldApi : public AcmReceiverTestOldApi {
EXPECT_EQ(output_sample_rate_hz, frame.sample_rate_hz_);
EXPECT_EQ(output_channels, frame.num_channels_);
EXPECT_EQ(AudioFrame::kNormalSpeech, frame.speech_type_);
- EXPECT_EQ(expected_vad_activity, frame.vad_activity_);
EXPECT_FALSE(muted);
}
}
@@ -243,61 +239,6 @@ TEST_F(AcmReceiverTestFaxModeOldApi, MAYBE_VerifyAudioFrameOpus) {
}
#if defined(WEBRTC_ANDROID)
-#define MAYBE_PostdecodingVad DISABLED_PostdecodingVad
-#else
-#define MAYBE_PostdecodingVad PostdecodingVad
-#endif
-TEST_F(AcmReceiverTestOldApi, MAYBE_PostdecodingVad) {
- EXPECT_TRUE(config_.neteq_config.enable_post_decode_vad);
- constexpr int payload_type = 34;
- const SdpAudioFormat codec = {"L16", 16000, 1};
- const AudioCodecInfo info = SetEncoder(payload_type, codec);
- receiver_->SetCodecs({{payload_type, codec}});
- constexpr int kNumPackets = 5;
- AudioFrame frame;
- for (int n = 0; n < kNumPackets; ++n) {
- const int num_10ms_frames = InsertOnePacketOfSilence(info);
- for (int k = 0; k < num_10ms_frames; ++k) {
- bool muted;
- ASSERT_EQ(0, receiver_->GetAudio(info.sample_rate_hz, &frame, &muted));
- }
- }
- EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
-}
-
-class AcmReceiverTestPostDecodeVadPassiveOldApi : public AcmReceiverTestOldApi {
- protected:
- AcmReceiverTestPostDecodeVadPassiveOldApi() {
- config_.neteq_config.enable_post_decode_vad = false;
- }
-};
-
-#if defined(WEBRTC_ANDROID)
-#define MAYBE_PostdecodingVad DISABLED_PostdecodingVad
-#else
-#define MAYBE_PostdecodingVad PostdecodingVad
-#endif
-TEST_F(AcmReceiverTestPostDecodeVadPassiveOldApi, MAYBE_PostdecodingVad) {
- EXPECT_FALSE(config_.neteq_config.enable_post_decode_vad);
- constexpr int payload_type = 34;
- const SdpAudioFormat codec = {"L16", 16000, 1};
- const AudioCodecInfo info = SetEncoder(payload_type, codec);
- auto const value = encoder_factory_->QueryAudioEncoder(codec);
- ASSERT_TRUE(value.has_value());
- receiver_->SetCodecs({{payload_type, codec}});
- const int kNumPackets = 5;
- AudioFrame frame;
- for (int n = 0; n < kNumPackets; ++n) {
- const int num_10ms_frames = InsertOnePacketOfSilence(info);
- for (int k = 0; k < num_10ms_frames; ++k) {
- bool muted;
- ASSERT_EQ(0, receiver_->GetAudio(info.sample_rate_hz, &frame, &muted));
- }
- }
- EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
-}
-
-#if defined(WEBRTC_ANDROID)
#define MAYBE_LastAudioCodec DISABLED_LastAudioCodec
#else
#define MAYBE_LastAudioCodec LastAudioCodec
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc
index 46ac671b30..ff7e919d9b 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc
@@ -58,6 +58,11 @@ int AudioDecoderPcmU::PacketDuration(const uint8_t* encoded,
return static_cast<int>(encoded_len / Channels());
}
+int AudioDecoderPcmU::PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const {
+ return PacketDuration(encoded, encoded_len);
+}
+
void AudioDecoderPcmA::Reset() {}
std::vector<AudioDecoder::ParseResult> AudioDecoderPcmA::ParsePayload(
@@ -99,4 +104,9 @@ int AudioDecoderPcmA::PacketDuration(const uint8_t* encoded,
return static_cast<int>(encoded_len / Channels());
}
+int AudioDecoderPcmA::PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const {
+ return PacketDuration(encoded, encoded_len);
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
index 3fa42cba30..5531d6e7f0 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
@@ -35,6 +35,8 @@ class AudioDecoderPcmU final : public AudioDecoder {
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
uint32_t timestamp) override;
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const override;
int SampleRateHz() const override;
size_t Channels() const override;
@@ -62,6 +64,8 @@ class AudioDecoderPcmA final : public AudioDecoder {
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
uint32_t timestamp) override;
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const override;
int SampleRateHz() const override;
size_t Channels() const override;
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc
index e969ed1189..bca47cea13 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc
@@ -63,6 +63,11 @@ int AudioDecoderG722Impl::PacketDuration(const uint8_t* encoded,
return static_cast<int>(2 * encoded_len / Channels());
}
+int AudioDecoderG722Impl::PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const {
+ return PacketDuration(encoded, encoded_len);
+}
+
int AudioDecoderG722Impl::SampleRateHz() const {
return 16000;
}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h
index 5872fad5de..e7083c3fd6 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h
@@ -30,6 +30,8 @@ class AudioDecoderG722Impl final : public AudioDecoder {
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
uint32_t timestamp) override;
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const override;
int SampleRateHz() const override;
size_t Channels() const override;
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
index cff9685548..0f53409f48 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
@@ -17,12 +17,15 @@
#include "api/array_view.h"
#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
#include "rtc_base/checks.h"
+#include "system_wrappers/include/field_trial.h"
namespace webrtc {
AudioDecoderOpusImpl::AudioDecoderOpusImpl(size_t num_channels,
int sample_rate_hz)
- : channels_{num_channels}, sample_rate_hz_{sample_rate_hz} {
+ : channels_(num_channels),
+ sample_rate_hz_(sample_rate_hz),
+ generate_plc_(field_trial::IsEnabled("WebRTC-Audio-OpusGeneratePlc")) {
RTC_DCHECK(num_channels == 1 || num_channels == 2);
RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 48000);
const int error =
@@ -125,4 +128,22 @@ size_t AudioDecoderOpusImpl::Channels() const {
return channels_;
}
+void AudioDecoderOpusImpl::GeneratePlc(
+ size_t requested_samples_per_channel,
+ rtc::BufferT<int16_t>* concealment_audio) {
+ if (!generate_plc_) {
+ return;
+ }
+ int plc_size = WebRtcOpus_PlcDuration(dec_state_) * channels_;
+ concealment_audio->AppendData(plc_size, [&](rtc::ArrayView<int16_t> decoded) {
+ int16_t temp_type = 1;
+ int ret =
+ WebRtcOpus_Decode(dec_state_, nullptr, 0, decoded.data(), &temp_type);
+ if (ret < 0) {
+ return 0;
+ }
+ return ret;
+ });
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h
index e8fd0440bc..2dd62fd4ee 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h
@@ -40,6 +40,8 @@ class AudioDecoderOpusImpl final : public AudioDecoder {
bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override;
int SampleRateHz() const override;
size_t Channels() const override;
+ void GeneratePlc(size_t requested_samples_per_channel,
+ rtc::BufferT<int16_t>* concealment_audio) override;
protected:
int DecodeInternal(const uint8_t* encoded,
@@ -57,6 +59,7 @@ class AudioDecoderOpusImpl final : public AudioDecoder {
OpusDecInst* dec_state_;
const size_t channels_;
const int sample_rate_hz_;
+ const bool generate_plc_;
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
index 7761efe8b3..1e2b5db331 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
@@ -67,4 +67,9 @@ int AudioDecoderPcm16B::PacketDuration(const uint8_t* encoded,
return static_cast<int>(encoded_len / (2 * Channels()));
}
+int AudioDecoderPcm16B::PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const {
+ return PacketDuration(encoded, encoded_len);
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
index 6f50161d3f..c31cc5d0a2 100644
--- a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
@@ -32,6 +32,8 @@ class AudioDecoderPcm16B final : public AudioDecoder {
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
uint32_t timestamp) override;
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const override;
int SampleRateHz() const override;
size_t Channels() const override;
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.cc b/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.cc
index 2c95d3b390..0c33dba47a 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.cc
@@ -17,7 +17,6 @@
#include "common_audio/signal_processing/include/signal_processing_library.h"
#include "modules/audio_coding/neteq/audio_multi_vector.h"
#include "modules/audio_coding/neteq/cross_correlation.h"
-#include "modules/audio_coding/neteq/post_decode_vad.h"
namespace webrtc {
namespace {
@@ -44,17 +43,11 @@ void BackgroundNoise::Reset() {
}
}
-bool BackgroundNoise::Update(const AudioMultiVector& input,
- const PostDecodeVad& vad) {
+bool BackgroundNoise::Update(const AudioMultiVector& sync_buffer) {
bool filter_params_saved = false;
- if (vad.running() && vad.active_speech()) {
- // Do not update the background noise parameters if we know that the signal
- // is active speech.
- return filter_params_saved;
- }
int32_t auto_correlation[kMaxLpcOrder + 1];
- int16_t fiter_output[kMaxLpcOrder + kResidualLength];
+ int16_t filter_output[kMaxLpcOrder + kResidualLength];
int16_t reflection_coefficients[kMaxLpcOrder];
int16_t lpc_coefficients[kMaxLpcOrder + 1];
@@ -62,14 +55,13 @@ bool BackgroundNoise::Update(const AudioMultiVector& input,
ChannelParameters& parameters = channel_parameters_[channel_ix];
int16_t temp_signal_array[kVecLen + kMaxLpcOrder] = {0};
int16_t* temp_signal = &temp_signal_array[kMaxLpcOrder];
- RTC_DCHECK_GE(input.Size(), kVecLen);
- input[channel_ix].CopyTo(kVecLen, input.Size() - kVecLen, temp_signal);
+ RTC_DCHECK_GE(sync_buffer.Size(), kVecLen);
+ sync_buffer[channel_ix].CopyTo(kVecLen, sync_buffer.Size() - kVecLen,
+ temp_signal);
int32_t sample_energy =
CalculateAutoCorrelation(temp_signal, kVecLen, auto_correlation);
- if ((!vad.running() &&
- sample_energy < parameters.energy_update_threshold) ||
- (vad.running() && !vad.active_speech())) {
+ if (sample_energy < parameters.energy_update_threshold) {
// Generate LPC coefficients.
if (auto_correlation[0] <= 0) {
// Center value in auto-correlation is not positive. Do not update.
@@ -95,10 +87,10 @@ bool BackgroundNoise::Update(const AudioMultiVector& input,
// Generate the CNG gain factor by looking at the energy of the residual.
WebRtcSpl_FilterMAFastQ12(temp_signal + kVecLen - kResidualLength,
- fiter_output, lpc_coefficients,
+ filter_output, lpc_coefficients,
kMaxLpcOrder + 1, kResidualLength);
int32_t residual_energy = WebRtcSpl_DotProductWithScale(
- fiter_output, fiter_output, kResidualLength, 0);
+ filter_output, filter_output, kResidualLength, 0);
// Check spectral flatness.
// Comparing the residual variance with the input signal variance tells
@@ -117,9 +109,8 @@ bool BackgroundNoise::Update(const AudioMultiVector& input,
filter_params_saved = true;
}
} else {
- // Will only happen if post-decode VAD is disabled and `sample_energy` is
- // not low enough. Increase the threshold for update so that it increases
- // by a factor 4 in 4 seconds.
+ // Will only happen if `sample_energy` is not low enough. Increase the
+ // threshold for update so that it increases by a factor 4 in 4 seconds.
IncrementEnergyThreshold(channel_ix, sample_energy);
}
}
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.h b/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.h
index 8e6d5890a0..9ef0131c92 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.h
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/background_noise.h
@@ -39,9 +39,9 @@ class BackgroundNoise {
void Reset();
// Updates the parameter estimates based on the signal currently in the
- // `sync_buffer`, and on the latest decision in `vad` if it is running.
+ // `sync_buffer`.
// Returns true if the filter parameters are updated.
- bool Update(const AudioMultiVector& sync_buffer, const PostDecodeVad& vad);
+ bool Update(const AudioMultiVector& sync_buffer);
// Generates background noise given a random vector and writes the output to
// `buffer`.
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic.cc b/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic.cc
index 6648fd8709..f68c05767d 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic.cc
@@ -14,7 +14,6 @@
#include <cstdint>
#include <memory>
-#include <string>
#include "absl/types/optional.h"
#include "api/neteq/neteq.h"
@@ -22,7 +21,6 @@
#include "modules/audio_coding/neteq/packet_arrival_history.h"
#include "modules/audio_coding/neteq/packet_buffer.h"
#include "rtc_base/checks.h"
-#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/struct_parameters_parser.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
@@ -102,6 +100,7 @@ DecisionLogic::DecisionLogic(
packet_arrival_history_(packet_arrival_history
? std::move(packet_arrival_history)
: std::make_unique<PacketArrivalHistory>(
+ config.tick_timer,
config_.packet_history_size_ms)),
tick_timer_(config.tick_timer),
disallow_time_stretching_(!config.allow_time_stretching),
@@ -221,14 +220,14 @@ absl::optional<int> DecisionLogic::PacketArrived(
packet_length_samples_ = info.packet_length_samples;
delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz);
}
- int64_t time_now_ms = tick_timer_->ticks() * tick_timer_->ms_per_tick();
- packet_arrival_history_->Insert(info.main_timestamp, time_now_ms);
- if (packet_arrival_history_->size() < 2) {
+ bool inserted = packet_arrival_history_->Insert(info.main_timestamp,
+ info.packet_length_samples);
+ if (!inserted || packet_arrival_history_->size() < 2) {
// No meaningful delay estimate unless at least 2 packets have arrived.
return absl::nullopt;
}
int arrival_delay_ms =
- packet_arrival_history_->GetDelayMs(info.main_timestamp, time_now_ms);
+ packet_arrival_history_->GetDelayMs(info.main_timestamp);
bool reordered =
!packet_arrival_history_->IsNewestRtpTimestamp(info.main_timestamp);
delay_manager_->Update(arrival_delay_ms, reordered);
@@ -464,8 +463,7 @@ int DecisionLogic::GetPlayoutDelayMs(
NetEqController::NetEqStatus status) const {
uint32_t playout_timestamp =
status.target_timestamp - status.sync_buffer_samples;
- return packet_arrival_history_->GetDelayMs(
- playout_timestamp, tick_timer_->ticks() * tick_timer_->ms_per_tick());
+ return packet_arrival_history_->GetDelayMs(playout_timestamp);
}
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic_unittest.cc b/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic_unittest.cc
index 9e9902af50..4b306f2639 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic_unittest.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/decision_logic_unittest.cc
@@ -14,12 +14,10 @@
#include "api/neteq/neteq_controller.h"
#include "api/neteq/tick_timer.h"
-#include "modules/audio_coding/neteq/buffer_level_filter.h"
#include "modules/audio_coding/neteq/delay_manager.h"
#include "modules/audio_coding/neteq/mock/mock_buffer_level_filter.h"
#include "modules/audio_coding/neteq/mock/mock_delay_manager.h"
#include "modules/audio_coding/neteq/mock/mock_packet_arrival_history.h"
-#include "test/field_trial.h"
#include "test/gtest.h"
namespace webrtc {
@@ -64,7 +62,8 @@ class DecisionLogicTest : public ::testing::Test {
mock_delay_manager_ = delay_manager.get();
auto buffer_level_filter = std::make_unique<MockBufferLevelFilter>();
mock_buffer_level_filter_ = buffer_level_filter.get();
- auto packet_arrival_history = std::make_unique<MockPacketArrivalHistory>();
+ auto packet_arrival_history =
+ std::make_unique<MockPacketArrivalHistory>(&tick_timer_);
mock_packet_arrival_history_ = packet_arrival_history.get();
decision_logic_ = std::make_unique<DecisionLogic>(
config, std::move(delay_manager), std::move(buffer_level_filter),
@@ -82,7 +81,7 @@ class DecisionLogicTest : public ::testing::Test {
TEST_F(DecisionLogicTest, NormalOperation) {
EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
.WillRepeatedly(Return(100));
- EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_, _))
+ EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_))
.WillRepeatedly(Return(100));
EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs())
.WillRepeatedly(Return(0));
@@ -98,7 +97,7 @@ TEST_F(DecisionLogicTest, NormalOperation) {
TEST_F(DecisionLogicTest, Accelerate) {
EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
.WillRepeatedly(Return(100));
- EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_, _))
+ EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_))
.WillRepeatedly(Return(150));
EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs())
.WillRepeatedly(Return(0));
@@ -114,7 +113,7 @@ TEST_F(DecisionLogicTest, Accelerate) {
TEST_F(DecisionLogicTest, FastAccelerate) {
EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
.WillRepeatedly(Return(100));
- EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_, _))
+ EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_))
.WillRepeatedly(Return(500));
EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs())
.WillRepeatedly(Return(0));
@@ -130,7 +129,7 @@ TEST_F(DecisionLogicTest, FastAccelerate) {
TEST_F(DecisionLogicTest, PreemptiveExpand) {
EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
.WillRepeatedly(Return(100));
- EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_, _))
+ EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_))
.WillRepeatedly(Return(50));
EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs())
.WillRepeatedly(Return(0));
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/mock/mock_packet_arrival_history.h b/third_party/libwebrtc/modules/audio_coding/neteq/mock/mock_packet_arrival_history.h
index 1b2080cd94..d4217cf2f8 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/mock/mock_packet_arrival_history.h
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/mock/mock_packet_arrival_history.h
@@ -11,6 +11,7 @@
#ifndef MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_PACKET_ARRIVAL_HISTORY_H_
#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_PACKET_ARRIVAL_HISTORY_H_
+#include "api/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/packet_arrival_history.h"
#include "test/gmock.h"
@@ -18,12 +19,10 @@ namespace webrtc {
class MockPacketArrivalHistory : public PacketArrivalHistory {
public:
- MockPacketArrivalHistory() : PacketArrivalHistory(0) {}
+ MockPacketArrivalHistory(const TickTimer* tick_timer)
+ : PacketArrivalHistory(tick_timer, 0) {}
- MOCK_METHOD(int,
- GetDelayMs,
- (uint32_t rtp_timestamp, int64_t time_ms),
- (const override));
+ MOCK_METHOD(int, GetDelayMs, (uint32_t rtp_timestamp), (const override));
MOCK_METHOD(int, GetMaxDelayMs, (), (const override));
};
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc
index e5c8bf6c08..6a76096b49 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -20,6 +20,7 @@
#include <vector>
#include "api/audio_codecs/audio_decoder.h"
+#include "api/neteq/neteq_controller.h"
#include "api/neteq/tick_timer.h"
#include "common_audio/signal_processing/include/signal_processing_library.h"
#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
@@ -36,7 +37,6 @@
#include "modules/audio_coding/neteq/normal.h"
#include "modules/audio_coding/neteq/packet.h"
#include "modules/audio_coding/neteq/packet_buffer.h"
-#include "modules/audio_coding/neteq/post_decode_vad.h"
#include "modules/audio_coding/neteq/preemptive_expand.h"
#include "modules/audio_coding/neteq/red_payload_splitter.h"
#include "modules/audio_coding/neteq/statistics_calculator.h"
@@ -50,6 +50,7 @@
#include "rtc_base/strings/audio_format_to_string.h"
#include "rtc_base/trace_event.h"
#include "system_wrappers/include/clock.h"
+#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
@@ -70,49 +71,26 @@ std::unique_ptr<NetEqController> CreateNetEqController(
return controller_factory.CreateNetEqController(config);
}
-void SetAudioFrameActivityAndType(bool vad_enabled,
- NetEqImpl::OutputType type,
- AudioFrame::VADActivity last_vad_activity,
- AudioFrame* audio_frame) {
+AudioFrame::SpeechType ToSpeechType(NetEqImpl::OutputType type) {
switch (type) {
case NetEqImpl::OutputType::kNormalSpeech: {
- audio_frame->speech_type_ = AudioFrame::kNormalSpeech;
- audio_frame->vad_activity_ = AudioFrame::kVadActive;
- break;
- }
- case NetEqImpl::OutputType::kVadPassive: {
- // This should only be reached if the VAD is enabled.
- RTC_DCHECK(vad_enabled);
- audio_frame->speech_type_ = AudioFrame::kNormalSpeech;
- audio_frame->vad_activity_ = AudioFrame::kVadPassive;
- break;
+ return AudioFrame::kNormalSpeech;
}
case NetEqImpl::OutputType::kCNG: {
- audio_frame->speech_type_ = AudioFrame::kCNG;
- audio_frame->vad_activity_ = AudioFrame::kVadPassive;
- break;
+ return AudioFrame::kCNG;
}
case NetEqImpl::OutputType::kPLC: {
- audio_frame->speech_type_ = AudioFrame::kPLC;
- audio_frame->vad_activity_ = last_vad_activity;
- break;
+ return AudioFrame::kPLC;
}
case NetEqImpl::OutputType::kPLCCNG: {
- audio_frame->speech_type_ = AudioFrame::kPLCCNG;
- audio_frame->vad_activity_ = AudioFrame::kVadPassive;
- break;
+ return AudioFrame::kPLCCNG;
}
case NetEqImpl::OutputType::kCodecPLC: {
- audio_frame->speech_type_ = AudioFrame::kCodecPLC;
- audio_frame->vad_activity_ = last_vad_activity;
- break;
+ return AudioFrame::kCodecPLC;
}
default:
RTC_DCHECK_NOTREACHED();
- }
- if (!vad_enabled) {
- // Always set kVadUnknown when receive VAD is inactive.
- audio_frame->vad_activity_ = AudioFrame::kVadUnknown;
+ return AudioFrame::kUndefined;
}
}
@@ -169,11 +147,12 @@ NetEqImpl::NetEqImpl(const NetEq::Config& config,
packet_buffer_(std::move(deps.packet_buffer)),
red_payload_splitter_(std::move(deps.red_payload_splitter)),
timestamp_scaler_(std::move(deps.timestamp_scaler)),
- vad_(new PostDecodeVad()),
expand_factory_(std::move(deps.expand_factory)),
accelerate_factory_(std::move(deps.accelerate_factory)),
preemptive_expand_factory_(std::move(deps.preemptive_expand_factory)),
stats_(std::move(deps.stats)),
+ enable_fec_delay_adaptation_(
+ !field_trial::IsDisabled("WebRTC-Audio-NetEqFecDelayAdaptation")),
controller_(std::move(deps.neteq_controller)),
last_mode_(Mode::kNormal),
decoded_buffer_length_(kMaxFrameSize),
@@ -211,10 +190,6 @@ NetEqImpl::NetEqImpl(const NetEq::Config& config,
if (create_components) {
SetSampleRateAndChannels(fs, 1); // Default is 1 channel.
}
- RTC_DCHECK(!vad_->enabled());
- if (config.enable_post_decode_vad) {
- vad_->Enable();
- }
}
NetEqImpl::~NetEqImpl() = default;
@@ -252,9 +227,7 @@ int NetEqImpl::GetAudio(AudioFrame* audio_frame,
audio_frame->sample_rate_hz_,
rtc::dchecked_cast<int>(audio_frame->samples_per_channel_ * 100));
RTC_DCHECK_EQ(*muted, audio_frame->muted());
- SetAudioFrameActivityAndType(vad_->enabled(), LastOutputType(),
- last_vad_activity_, audio_frame);
- last_vad_activity_ = audio_frame->vad_activity_;
+ audio_frame->speech_type_ = ToSpeechType(LastOutputType());
last_output_sample_rate_hz_ = audio_frame->sample_rate_hz_;
RTC_DCHECK(last_output_sample_rate_hz_ == 8000 ||
last_output_sample_rate_hz_ == 16000 ||
@@ -398,18 +371,6 @@ NetEqOperationsAndState NetEqImpl::GetOperationsAndState() const {
return result;
}
-void NetEqImpl::EnableVad() {
- MutexLock lock(&mutex_);
- RTC_DCHECK(vad_.get());
- vad_->Enable();
-}
-
-void NetEqImpl::DisableVad() {
- MutexLock lock(&mutex_);
- RTC_DCHECK(vad_.get());
- vad_->Disable();
-}
-
absl::optional<uint32_t> NetEqImpl::GetPlayoutTimestamp() const {
MutexLock lock(&mutex_);
if (first_packet_ || last_mode_ == Mode::kRfc3389Cng ||
@@ -695,6 +656,7 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header,
packet_buffer_->Flush();
buffer_flush_occured = true;
}
+ NetEqController::PacketArrivedInfo info = ToPacketArrivedInfo(packet);
int return_val = packet_buffer_->InsertPacket(std::move(packet));
if (return_val == PacketBuffer::kFlushed) {
buffer_flush_occured = true;
@@ -702,6 +664,15 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header,
// An error occurred.
return kOtherError;
}
+ if (enable_fec_delay_adaptation_) {
+ info.buffer_flush = buffer_flush_occured;
+ const bool should_update_stats = !new_codec_ && !buffer_flush_occured;
+ auto relative_delay =
+ controller_->PacketArrived(fs_hz_, should_update_stats, info);
+ if (relative_delay) {
+ stats_->RelativePacketArrivalDelay(relative_delay.value());
+ }
+ }
}
if (buffer_flush_occured) {
@@ -752,24 +723,26 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header,
}
}
- const DecoderDatabase::DecoderInfo* dec_info =
- decoder_database_->GetDecoderInfo(main_payload_type);
- RTC_DCHECK(dec_info); // Already checked that the payload type is known.
-
- NetEqController::PacketArrivedInfo info;
- info.is_cng_or_dtmf = dec_info->IsComfortNoise() || dec_info->IsDtmf();
- info.packet_length_samples =
- number_of_primary_packets * decoder_frame_length_;
- info.main_timestamp = main_timestamp;
- info.main_sequence_number = main_sequence_number;
- info.is_dtx = is_dtx;
- info.buffer_flush = buffer_flush_occured;
-
- const bool should_update_stats = !new_codec_;
- auto relative_delay =
- controller_->PacketArrived(fs_hz_, should_update_stats, info);
- if (relative_delay) {
- stats_->RelativePacketArrivalDelay(relative_delay.value());
+ if (!enable_fec_delay_adaptation_) {
+ const DecoderDatabase::DecoderInfo* dec_info =
+ decoder_database_->GetDecoderInfo(main_payload_type);
+ RTC_DCHECK(dec_info); // Already checked that the payload type is known.
+
+ NetEqController::PacketArrivedInfo info;
+ info.is_cng_or_dtmf = dec_info->IsComfortNoise() || dec_info->IsDtmf();
+ info.packet_length_samples =
+ number_of_primary_packets * decoder_frame_length_;
+ info.main_timestamp = main_timestamp;
+ info.main_sequence_number = main_sequence_number;
+ info.is_dtx = is_dtx;
+ info.buffer_flush = buffer_flush_occured;
+
+ const bool should_update_stats = !new_codec_;
+ auto relative_delay =
+ controller_->PacketArrived(fs_hz_, should_update_stats, info);
+ if (relative_delay) {
+ stats_->RelativePacketArrivalDelay(relative_delay.value());
+ }
}
return 0;
}
@@ -858,11 +831,8 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
last_decoded_type_ = speech_type;
}
- RTC_DCHECK(vad_.get());
bool sid_frame_available =
(operation == Operation::kRfc3389Cng && !packet_list.empty());
- vad_->Update(decoded_buffer_.get(), static_cast<size_t>(length), speech_type,
- sid_frame_available, fs_hz_);
// This is the criterion that we did decode some data through the speech
// decoder, and the operation resulted in comfort noise.
@@ -1012,7 +982,7 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
(last_mode_ == Mode::kPreemptiveExpandFail) ||
(last_mode_ == Mode::kRfc3389Cng) ||
(last_mode_ == Mode::kCodecInternalCng)) {
- background_noise_->Update(*sync_buffer_, *vad_.get());
+ background_noise_->Update(*sync_buffer_);
}
if (operation == Operation::kDtmf) {
@@ -2088,10 +2058,6 @@ void NetEqImpl::SetSampleRateAndChannels(int fs_hz, size_t channels) {
if (cng_decoder)
cng_decoder->Reset();
- // Reinit post-decode VAD with new sample rate.
- RTC_DCHECK(vad_.get()); // Cannot be NULL here.
- vad_->Init();
-
// Delete algorithm buffer and create a new one.
algorithm_buffer_.reset(new AudioMultiVector(channels));
@@ -2132,7 +2098,6 @@ void NetEqImpl::SetSampleRateAndChannels(int fs_hz, size_t channels) {
}
NetEqImpl::OutputType NetEqImpl::LastOutputType() {
- RTC_DCHECK(vad_.get());
RTC_DCHECK(expand_.get());
if (last_mode_ == Mode::kCodecInternalCng ||
last_mode_ == Mode::kRfc3389Cng) {
@@ -2142,12 +2107,27 @@ NetEqImpl::OutputType NetEqImpl::LastOutputType() {
return OutputType::kPLCCNG;
} else if (last_mode_ == Mode::kExpand) {
return OutputType::kPLC;
- } else if (vad_->running() && !vad_->active_speech()) {
- return OutputType::kVadPassive;
} else if (last_mode_ == Mode::kCodecPlc) {
return OutputType::kCodecPLC;
} else {
return OutputType::kNormalSpeech;
}
}
+
+NetEqController::PacketArrivedInfo NetEqImpl::ToPacketArrivedInfo(
+ const Packet& packet) const {
+ const DecoderDatabase::DecoderInfo* dec_info =
+ decoder_database_->GetDecoderInfo(packet.payload_type);
+
+ NetEqController::PacketArrivedInfo info;
+ info.is_cng_or_dtmf =
+ dec_info && (dec_info->IsComfortNoise() || dec_info->IsDtmf());
+ info.packet_length_samples =
+ packet.frame ? packet.frame->Duration() : decoder_frame_length_;
+ info.main_timestamp = packet.timestamp;
+ info.main_sequence_number = packet.sequence_number;
+ info.is_dtx = packet.frame && packet.frame->IsDtxPacket();
+ return info;
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.h b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.h
index f8f2b06410..eed7645e7d 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.h
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.h
@@ -48,7 +48,6 @@ class Merge;
class NackTracker;
class Normal;
class RedPayloadSplitter;
-class PostDecodeVad;
class PreemptiveExpand;
class RandomVector;
class SyncBuffer;
@@ -171,13 +170,6 @@ class NetEqImpl : public webrtc::NetEq {
NetEqOperationsAndState GetOperationsAndState() const override;
- // Enables post-decode VAD. When enabled, GetAudio() will return
- // kOutputVADPassive when the signal contains no speech.
- void EnableVad() override;
-
- // Disables post-decode VAD.
- void DisableVad() override;
-
absl::optional<uint32_t> GetPlayoutTimestamp() const override;
int last_output_sample_rate_hz() const override;
@@ -342,6 +334,9 @@ class NetEqImpl : public webrtc::NetEq {
NetEqNetworkStatistics CurrentNetworkStatisticsInternal() const
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ NetEqController::PacketArrivedInfo ToPacketArrivedInfo(
+ const Packet& packet) const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
Clock* const clock_;
mutable Mutex mutex_;
@@ -356,13 +351,13 @@ class NetEqImpl : public webrtc::NetEq {
RTC_GUARDED_BY(mutex_);
const std::unique_ptr<TimestampScaler> timestamp_scaler_
RTC_GUARDED_BY(mutex_);
- const std::unique_ptr<PostDecodeVad> vad_ RTC_GUARDED_BY(mutex_);
const std::unique_ptr<ExpandFactory> expand_factory_ RTC_GUARDED_BY(mutex_);
const std::unique_ptr<AccelerateFactory> accelerate_factory_
RTC_GUARDED_BY(mutex_);
const std::unique_ptr<PreemptiveExpandFactory> preemptive_expand_factory_
RTC_GUARDED_BY(mutex_);
const std::unique_ptr<StatisticsCalculator> stats_ RTC_GUARDED_BY(mutex_);
+ const bool enable_fec_delay_adaptation_ RTC_GUARDED_BY(mutex_);
std::unique_ptr<BackgroundNoise> background_noise_ RTC_GUARDED_BY(mutex_);
std::unique_ptr<NetEqController> controller_ RTC_GUARDED_BY(mutex_);
@@ -397,8 +392,6 @@ class NetEqImpl : public webrtc::NetEq {
std::unique_ptr<NackTracker> nack_ RTC_GUARDED_BY(mutex_);
bool nack_enabled_ RTC_GUARDED_BY(mutex_);
const bool enable_muted_state_ RTC_GUARDED_BY(mutex_);
- AudioFrame::VADActivity last_vad_activity_ RTC_GUARDED_BY(mutex_) =
- AudioFrame::kVadPassive;
std::unique_ptr<TickTimer::Stopwatch> generated_noise_stopwatch_
RTC_GUARDED_BY(mutex_);
std::vector<RtpPacketInfo> last_decoded_packet_infos_ RTC_GUARDED_BY(mutex_);
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_unittest.cc b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_unittest.cc
index aec7e580ec..7104b7a6dc 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_unittest.cc
@@ -76,12 +76,13 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) {
webrtc::test::ResourcePath("audio_coding/neteq_opus", "rtp");
const std::string output_checksum =
- "2efdbea92c3fb2383c59f89d881efec9f94001d0|"
- "a6831b946b59913852ae3e53f99fa8f209bb23cd";
+ "434bdc4ec08546510ee903d001c8be1a01c44e24|"
+ "4336be0091e2faad7a194c16ee0a05e727325727|"
+ "cefd2de4adfa8f6a9b66a3639ad63c2f6779d0cd";
const std::string network_stats_checksum =
- "dfaf4399fd60293405290476ccf1c05c807c71a0|"
- "076662525572dba753b11578330bd491923f7f5e";
+ "5f2c8e3dff9cff55dd7a9f4167939de001566d95|"
+ "80ab17c17da030d4f2dfbf314ac44aacdadd7f0c";
DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
absl::GetFlag(FLAGS_gen_ref));
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.cc b/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.cc
index 2077383f76..a36c8a2b06 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.cc
@@ -11,95 +11,122 @@
#include "modules/audio_coding/neteq/packet_arrival_history.h"
#include <algorithm>
+#include <cstdint>
#include "api/neteq/tick_timer.h"
+#include "rtc_base/checks.h"
namespace webrtc {
-PacketArrivalHistory::PacketArrivalHistory(int window_size_ms)
- : window_size_ms_(window_size_ms) {}
+PacketArrivalHistory::PacketArrivalHistory(const TickTimer* tick_timer,
+ int window_size_ms)
+ : tick_timer_(tick_timer), window_size_ms_(window_size_ms) {}
-void PacketArrivalHistory::Insert(uint32_t rtp_timestamp,
- int64_t arrival_time_ms) {
- RTC_DCHECK(sample_rate_khz_ > 0);
- int64_t unwrapped_rtp_timestamp = timestamp_unwrapper_.Unwrap(rtp_timestamp);
- if (!newest_rtp_timestamp_ ||
- unwrapped_rtp_timestamp > *newest_rtp_timestamp_) {
- newest_rtp_timestamp_ = unwrapped_rtp_timestamp;
+bool PacketArrivalHistory::Insert(uint32_t rtp_timestamp,
+ int packet_length_samples) {
+ int64_t arrival_timestamp =
+ tick_timer_->ticks() * tick_timer_->ms_per_tick() * sample_rate_khz_;
+ PacketArrival packet(timestamp_unwrapper_.Unwrap(rtp_timestamp),
+ arrival_timestamp, packet_length_samples);
+ if (IsObsolete(packet)) {
+ return false;
}
- history_.emplace_back(unwrapped_rtp_timestamp / sample_rate_khz_,
- arrival_time_ms);
- MaybeUpdateCachedArrivals(history_.back());
- while (history_.front().rtp_timestamp_ms + window_size_ms_ <
- unwrapped_rtp_timestamp / sample_rate_khz_) {
- if (&history_.front() == min_packet_arrival_) {
- min_packet_arrival_ = nullptr;
- }
- if (&history_.front() == max_packet_arrival_) {
- max_packet_arrival_ = nullptr;
- }
- history_.pop_front();
+ if (Contains(packet)) {
+ return false;
+ }
+ history_.emplace(packet.rtp_timestamp, packet);
+ if (packet != history_.rbegin()->second) {
+ // Packet was reordered.
+ return true;
}
- if (!min_packet_arrival_ || !max_packet_arrival_) {
- for (const PacketArrival& packet : history_) {
- MaybeUpdateCachedArrivals(packet);
+ // Remove old packets.
+ while (IsObsolete(history_.begin()->second)) {
+ if (history_.begin()->second == min_packet_arrivals_.front()) {
+ min_packet_arrivals_.pop_front();
}
+ if (history_.begin()->second == max_packet_arrivals_.front()) {
+ max_packet_arrivals_.pop_front();
+ }
+ history_.erase(history_.begin());
}
-}
-
-void PacketArrivalHistory::MaybeUpdateCachedArrivals(
- const PacketArrival& packet_arrival) {
- if (!min_packet_arrival_ || packet_arrival <= *min_packet_arrival_) {
- min_packet_arrival_ = &packet_arrival;
+ // Ensure ordering constraints.
+ while (!min_packet_arrivals_.empty() &&
+ packet <= min_packet_arrivals_.back()) {
+ min_packet_arrivals_.pop_back();
}
- if (!max_packet_arrival_ || packet_arrival >= *max_packet_arrival_) {
- max_packet_arrival_ = &packet_arrival;
+ while (!max_packet_arrivals_.empty() &&
+ packet >= max_packet_arrivals_.back()) {
+ max_packet_arrivals_.pop_back();
}
+ min_packet_arrivals_.push_back(packet);
+ max_packet_arrivals_.push_back(packet);
+ return true;
}
void PacketArrivalHistory::Reset() {
history_.clear();
- min_packet_arrival_ = nullptr;
- max_packet_arrival_ = nullptr;
+ min_packet_arrivals_.clear();
+ max_packet_arrivals_.clear();
timestamp_unwrapper_.Reset();
- newest_rtp_timestamp_ = absl::nullopt;
}
-int PacketArrivalHistory::GetDelayMs(uint32_t rtp_timestamp,
- int64_t time_ms) const {
- RTC_DCHECK(sample_rate_khz_ > 0);
- int64_t unwrapped_rtp_timestamp_ms =
- timestamp_unwrapper_.PeekUnwrap(rtp_timestamp) / sample_rate_khz_;
- PacketArrival packet(unwrapped_rtp_timestamp_ms, time_ms);
+int PacketArrivalHistory::GetDelayMs(uint32_t rtp_timestamp) const {
+ int64_t unwrapped_rtp_timestamp =
+ timestamp_unwrapper_.PeekUnwrap(rtp_timestamp);
+ int64_t current_timestamp =
+ tick_timer_->ticks() * tick_timer_->ms_per_tick() * sample_rate_khz_;
+ PacketArrival packet(unwrapped_rtp_timestamp, current_timestamp,
+ /*duration_ms=*/0);
return GetPacketArrivalDelayMs(packet);
}
int PacketArrivalHistory::GetMaxDelayMs() const {
- if (!max_packet_arrival_) {
+ if (max_packet_arrivals_.empty()) {
return 0;
}
- return GetPacketArrivalDelayMs(*max_packet_arrival_);
+ return GetPacketArrivalDelayMs(max_packet_arrivals_.front());
}
bool PacketArrivalHistory::IsNewestRtpTimestamp(uint32_t rtp_timestamp) const {
- if (!newest_rtp_timestamp_) {
- return false;
+ if (history_.empty()) {
+ return true;
}
int64_t unwrapped_rtp_timestamp =
timestamp_unwrapper_.PeekUnwrap(rtp_timestamp);
- return unwrapped_rtp_timestamp == *newest_rtp_timestamp_;
+ return unwrapped_rtp_timestamp == history_.rbegin()->second.rtp_timestamp;
}
int PacketArrivalHistory::GetPacketArrivalDelayMs(
const PacketArrival& packet_arrival) const {
- if (!min_packet_arrival_) {
+ if (min_packet_arrivals_.empty()) {
return 0;
}
- return std::max(static_cast<int>(packet_arrival.arrival_time_ms -
- min_packet_arrival_->arrival_time_ms -
- (packet_arrival.rtp_timestamp_ms -
- min_packet_arrival_->rtp_timestamp_ms)),
- 0);
+ RTC_DCHECK_NE(sample_rate_khz_, 0);
+ // TODO(jakobi): Timestamps are first converted to millis for bit-exactness.
+ return std::max<int>(
+ packet_arrival.arrival_timestamp / sample_rate_khz_ -
+ min_packet_arrivals_.front().arrival_timestamp / sample_rate_khz_ -
+ (packet_arrival.rtp_timestamp / sample_rate_khz_ -
+ min_packet_arrivals_.front().rtp_timestamp / sample_rate_khz_),
+ 0);
+}
+
+bool PacketArrivalHistory::IsObsolete(
+ const PacketArrival& packet_arrival) const {
+ if (history_.empty()) {
+ return false;
+ }
+ return packet_arrival.rtp_timestamp + window_size_ms_ * sample_rate_khz_ <
+ history_.rbegin()->second.rtp_timestamp;
+}
+
+bool PacketArrivalHistory::Contains(const PacketArrival& packet_arrival) const {
+ auto it = history_.upper_bound(packet_arrival.rtp_timestamp);
+ if (it == history_.begin()) {
+ return false;
+ }
+ --it;
+ return it->second.contains(packet_arrival);
}
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.h b/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.h
index 722caf5688..3fa1ea1fa9 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.h
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.h
@@ -11,10 +11,11 @@
#ifndef MODULES_AUDIO_CODING_NETEQ_PACKET_ARRIVAL_HISTORY_H_
#define MODULES_AUDIO_CODING_NETEQ_PACKET_ARRIVAL_HISTORY_H_
+#include <cstddef>
#include <cstdint>
#include <deque>
+#include <map>
-#include "absl/types/optional.h"
#include "api/neteq/tick_timer.h"
#include "rtc_base/numerics/sequence_number_unwrapper.h"
@@ -25,19 +26,22 @@ namespace webrtc {
// pruned.
class PacketArrivalHistory {
public:
- explicit PacketArrivalHistory(int window_size_ms);
+ explicit PacketArrivalHistory(const TickTimer* tick_timer,
+ int window_size_ms);
virtual ~PacketArrivalHistory() = default;
- // Insert packet with `rtp_timestamp` and `arrival_time_ms` into the history.
- void Insert(uint32_t rtp_timestamp, int64_t arrival_time_ms);
+ // Insert packet with `rtp_timestamp` into the history. Returns true if the
+ // packet was inserted, false if the timestamp is too old or if the timestamp
+ // already exists.
+ bool Insert(uint32_t rtp_timestamp, int packet_length_samples);
- // The delay for `rtp_timestamp` at `time_ms` is calculated as
- // `(time_ms - p.arrival_time_ms) - (rtp_timestamp - p.rtp_timestamp)`
- // where `p` is chosen as the packet arrival in the history that maximizes the
- // delay.
- virtual int GetDelayMs(uint32_t rtp_timestamp, int64_t time_ms) const;
+ // The delay for `rtp_timestamp` at time `now` is calculated as
+ // `(now - p.arrival_timestamp) - (rtp_timestamp - p.rtp_timestamp)` where `p`
+ // is chosen as the packet arrival in the history that maximizes the delay.
+ virtual int GetDelayMs(uint32_t rtp_timestamp) const;
- // Get the maximum packet arrival delay observed in the history.
+ // Get the maximum packet arrival delay observed in the history, excluding
+ // reordered packets.
virtual int GetMaxDelayMs() const;
bool IsNewestRtpTimestamp(uint32_t rtp_timestamp) const;
@@ -52,30 +56,53 @@ class PacketArrivalHistory {
private:
struct PacketArrival {
- PacketArrival(int64_t rtp_timestamp_ms, int64_t arrival_time_ms)
- : rtp_timestamp_ms(rtp_timestamp_ms),
- arrival_time_ms(arrival_time_ms) {}
- int64_t rtp_timestamp_ms;
- int64_t arrival_time_ms;
+ PacketArrival(int64_t rtp_timestamp,
+ int64_t arrival_timestamp,
+ int length_samples)
+ : rtp_timestamp(rtp_timestamp),
+ arrival_timestamp(arrival_timestamp),
+ length_samples(length_samples) {}
+ PacketArrival() = default;
+ int64_t rtp_timestamp;
+ int64_t arrival_timestamp;
+ int length_samples;
+ bool operator==(const PacketArrival& other) const {
+ return rtp_timestamp == other.rtp_timestamp &&
+ arrival_timestamp == other.arrival_timestamp &&
+ length_samples == other.length_samples;
+ }
+ bool operator!=(const PacketArrival& other) const {
+ return !(*this == other);
+ }
bool operator<=(const PacketArrival& other) const {
- return arrival_time_ms - rtp_timestamp_ms <=
- other.arrival_time_ms - other.rtp_timestamp_ms;
+ return arrival_timestamp - rtp_timestamp <=
+ other.arrival_timestamp - other.rtp_timestamp;
}
bool operator>=(const PacketArrival& other) const {
- return arrival_time_ms - rtp_timestamp_ms >=
- other.arrival_time_ms - other.rtp_timestamp_ms;
+ return arrival_timestamp - rtp_timestamp >=
+ other.arrival_timestamp - other.rtp_timestamp;
+ }
+ bool contains(const PacketArrival& other) const {
+ return rtp_timestamp <= other.rtp_timestamp &&
+ rtp_timestamp + length_samples >=
+ other.rtp_timestamp + other.length_samples;
}
};
- std::deque<PacketArrival> history_;
int GetPacketArrivalDelayMs(const PacketArrival& packet_arrival) const;
- // Updates `min_packet_arrival_` and `max_packet_arrival_`.
- void MaybeUpdateCachedArrivals(const PacketArrival& packet);
- const PacketArrival* min_packet_arrival_ = nullptr;
- const PacketArrival* max_packet_arrival_ = nullptr;
+ // Checks if the packet is older than the window size.
+ bool IsObsolete(const PacketArrival& packet_arrival) const;
+ // Check if the packet exists or fully overlaps with a packet in the history.
+ bool Contains(const PacketArrival& packet_arrival) const;
+ const TickTimer* tick_timer_;
const int window_size_ms_;
- RtpTimestampUnwrapper timestamp_unwrapper_;
- absl::optional<int64_t> newest_rtp_timestamp_;
int sample_rate_khz_ = 0;
+ RtpTimestampUnwrapper timestamp_unwrapper_;
+ // Packet history ordered by rtp timestamp.
+ std::map<int64_t, PacketArrival> history_;
+ // Tracks min/max packet arrivals in `history_` in ascending/descending order.
+ // Reordered packets are excluded.
+ std::deque<PacketArrival> min_packet_arrivals_;
+ std::deque<PacketArrival> max_packet_arrivals_;
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history_unittest.cc b/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history_unittest.cc
index 539a318fe1..dd95fec0f7 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history_unittest.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history_unittest.cc
@@ -21,32 +21,36 @@ namespace {
constexpr int kFs = 8000;
constexpr int kFsKhz = kFs / 1000;
constexpr int kFrameSizeMs = 20;
+constexpr int kFrameSizeSamples = kFrameSizeMs * kFsKhz;
constexpr int kWindowSizeMs = 1000;
class PacketArrivalHistoryTest : public testing::Test {
public:
- PacketArrivalHistoryTest() : history_(kWindowSizeMs) {
+ PacketArrivalHistoryTest() : history_(&tick_timer_, kWindowSizeMs) {
history_.set_sample_rate(kFs);
}
- void IncrementTime(int delta_ms) { time_ms_ += delta_ms; }
+ void IncrementTime(int delta_ms) {
+ tick_timer_.Increment(delta_ms / tick_timer_.ms_per_tick());
+ }
int InsertPacketAndGetDelay(int timestamp_delta_ms) {
uint32_t timestamp = timestamp_ + timestamp_delta_ms * kFsKhz;
if (timestamp_delta_ms > 0) {
timestamp_ = timestamp;
}
- history_.Insert(timestamp, time_ms_);
+ EXPECT_TRUE(history_.Insert(timestamp, kFrameSizeSamples));
EXPECT_EQ(history_.IsNewestRtpTimestamp(timestamp),
timestamp_delta_ms >= 0);
- return history_.GetDelayMs(timestamp, time_ms_);
+ return history_.GetDelayMs(timestamp);
}
protected:
- int64_t time_ms_ = 0;
+ TickTimer tick_timer_;
PacketArrivalHistory history_;
uint32_t timestamp_ = 0x12345678;
};
TEST_F(PacketArrivalHistoryTest, RelativeArrivalDelay) {
+ // Insert first packet.
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
IncrementTime(kFrameSizeMs);
@@ -56,7 +60,7 @@ TEST_F(PacketArrivalHistoryTest, RelativeArrivalDelay) {
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
// Reordered packet.
- EXPECT_EQ(InsertPacketAndGetDelay(-2 * kFrameSizeMs), 60);
+ EXPECT_EQ(InsertPacketAndGetDelay(-3 * kFrameSizeMs), 80);
IncrementTime(2 * kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 40);
@@ -68,7 +72,7 @@ TEST_F(PacketArrivalHistoryTest, RelativeArrivalDelay) {
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
// Earlier packet is now more delayed due to the new reference packet.
- EXPECT_EQ(history_.GetMaxDelayMs(), 100);
+ EXPECT_EQ(history_.GetMaxDelayMs(), 80);
}
TEST_F(PacketArrivalHistoryTest, ReorderedPackets) {
@@ -86,7 +90,7 @@ TEST_F(PacketArrivalHistoryTest, ReorderedPackets) {
IncrementTime(4 * kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 60);
- EXPECT_EQ(history_.GetMaxDelayMs(), 80);
+ EXPECT_EQ(history_.GetMaxDelayMs(), 60);
}
TEST_F(PacketArrivalHistoryTest, MaxHistorySize) {
@@ -117,7 +121,7 @@ TEST_F(PacketArrivalHistoryTest, TimestampWraparound) {
// Insert another in-order packet after the wraparound.
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
- EXPECT_EQ(history_.GetMaxDelayMs(), 3 * kFrameSizeMs);
+ EXPECT_EQ(history_.GetMaxDelayMs(), kFrameSizeMs);
}
TEST_F(PacketArrivalHistoryTest, TimestampWraparoundBackwards) {
@@ -134,7 +138,33 @@ TEST_F(PacketArrivalHistoryTest, TimestampWraparoundBackwards) {
// Insert another in-order packet after the wraparound.
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
- EXPECT_EQ(history_.GetMaxDelayMs(), 3 * kFrameSizeMs);
+ EXPECT_EQ(history_.GetMaxDelayMs(), kFrameSizeMs);
+}
+
+TEST_F(PacketArrivalHistoryTest, OldPacketShouldNotBeInserted) {
+ // Insert first packet as reference.
+ EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
+ // Insert packet with timestamp older than the window size compared to the
+ // first packet.
+ EXPECT_FALSE(history_.Insert(timestamp_ - kWindowSizeMs * kFsKhz - 1,
+ kFrameSizeSamples));
+}
+
+TEST_F(PacketArrivalHistoryTest, DuplicatePacketShouldNotBeInserted) {
+ // Insert first packet as reference.
+ uint32_t first_timestamp = timestamp_;
+ EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
+ EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
+ // Same timestamp as the first packet.
+ EXPECT_FALSE(history_.Insert(first_timestamp, kFrameSizeSamples));
+}
+
+TEST_F(PacketArrivalHistoryTest, OverlappingPacketShouldNotBeInserted) {
+ // Insert first packet as reference.
+ EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
+ // 10 ms overlap with the previous packet.
+ EXPECT_FALSE(history_.Insert(timestamp_ + kFrameSizeSamples / 2,
+ kFrameSizeSamples / 2));
}
} // namespace
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.cc b/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.cc
deleted file mode 100644
index 9999d6764b..0000000000
--- a/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/audio_coding/neteq/post_decode_vad.h"
-
-namespace webrtc {
-
-PostDecodeVad::~PostDecodeVad() {
- if (vad_instance_)
- WebRtcVad_Free(vad_instance_);
-}
-
-void PostDecodeVad::Enable() {
- if (!vad_instance_) {
- // Create the instance.
- vad_instance_ = WebRtcVad_Create();
- if (vad_instance_ == nullptr) {
- // Failed to create instance.
- Disable();
- return;
- }
- }
- Init();
- enabled_ = true;
-}
-
-void PostDecodeVad::Disable() {
- enabled_ = false;
- running_ = false;
-}
-
-void PostDecodeVad::Init() {
- running_ = false;
- if (vad_instance_) {
- WebRtcVad_Init(vad_instance_);
- WebRtcVad_set_mode(vad_instance_, kVadMode);
- running_ = true;
- }
-}
-
-void PostDecodeVad::Update(int16_t* signal,
- size_t length,
- AudioDecoder::SpeechType speech_type,
- bool sid_frame,
- int fs_hz) {
- if (!vad_instance_ || !enabled_) {
- return;
- }
-
- if (speech_type == AudioDecoder::kComfortNoise || sid_frame ||
- fs_hz > 16000) {
- // TODO(hlundin): Remove restriction on fs_hz.
- running_ = false;
- active_speech_ = true;
- sid_interval_counter_ = 0;
- } else if (!running_) {
- ++sid_interval_counter_;
- }
-
- if (sid_interval_counter_ >= kVadAutoEnable) {
- Init();
- }
-
- if (length > 0 && running_) {
- size_t vad_sample_index = 0;
- active_speech_ = false;
- // Loop through frame sizes 30, 20, and 10 ms.
- for (int vad_frame_size_ms = 30; vad_frame_size_ms >= 10;
- vad_frame_size_ms -= 10) {
- size_t vad_frame_size_samples =
- static_cast<size_t>(vad_frame_size_ms * fs_hz / 1000);
- while (length - vad_sample_index >= vad_frame_size_samples) {
- int vad_return =
- WebRtcVad_Process(vad_instance_, fs_hz, &signal[vad_sample_index],
- vad_frame_size_samples);
- active_speech_ |= (vad_return == 1);
- vad_sample_index += vad_frame_size_samples;
- }
- }
- }
-}
-
-} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.h b/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.h
deleted file mode 100644
index 3bd91b9edb..0000000000
--- a/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef MODULES_AUDIO_CODING_NETEQ_POST_DECODE_VAD_H_
-#define MODULES_AUDIO_CODING_NETEQ_POST_DECODE_VAD_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "api/audio_codecs/audio_decoder.h"
-#include "common_audio/vad/include/webrtc_vad.h"
-
-namespace webrtc {
-
-class PostDecodeVad {
- public:
- PostDecodeVad()
- : enabled_(false),
- running_(false),
- active_speech_(true),
- sid_interval_counter_(0),
- vad_instance_(NULL) {}
-
- virtual ~PostDecodeVad();
-
- PostDecodeVad(const PostDecodeVad&) = delete;
- PostDecodeVad& operator=(const PostDecodeVad&) = delete;
-
- // Enables post-decode VAD.
- void Enable();
-
- // Disables post-decode VAD.
- void Disable();
-
- // Initializes post-decode VAD.
- void Init();
-
- // Updates post-decode VAD with the audio data in `signal` having `length`
- // samples. The data is of type `speech_type`, at the sample rate `fs_hz`.
- void Update(int16_t* signal,
- size_t length,
- AudioDecoder::SpeechType speech_type,
- bool sid_frame,
- int fs_hz);
-
- // Accessors.
- bool enabled() const { return enabled_; }
- bool running() const { return running_; }
- bool active_speech() const { return active_speech_; }
-
- private:
- static const int kVadMode = 0; // Sets aggressiveness to "Normal".
- // Number of Update() calls without CNG/SID before re-enabling VAD.
- static const int kVadAutoEnable = 3000;
-
- bool enabled_;
- bool running_;
- bool active_speech_;
- int sid_interval_counter_;
- ::VadInst* vad_instance_;
-};
-
-} // namespace webrtc
-#endif // MODULES_AUDIO_CODING_NETEQ_POST_DECODE_VAD_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad_unittest.cc b/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad_unittest.cc
deleted file mode 100644
index da3e4e864e..0000000000
--- a/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad_unittest.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-// Unit tests for PostDecodeVad class.
-
-#include "modules/audio_coding/neteq/post_decode_vad.h"
-
-#include "test/gtest.h"
-
-namespace webrtc {
-
-TEST(PostDecodeVad, CreateAndDestroy) {
- PostDecodeVad vad;
-}
-
-// TODO(hlundin): Write more tests.
-
-} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.cc b/third_party/libwebrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.cc
index 081bd9631f..f1a46cd2df 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.cc
+++ b/third_party/libwebrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.cc
@@ -107,7 +107,7 @@ void NetEqReplacementInput::ReplacePacket() {
next_hdr->timestamp - packet_->header.timestamp;
const bool opus_dtx = packet_->payload.size() <= 2;
if (next_hdr->sequenceNumber == packet_->header.sequenceNumber + 1 &&
- timestamp_diff <= 120 * 48 && !opus_dtx) {
+ timestamp_diff <= 120 * 48 && timestamp_diff > 0 && !opus_dtx) {
// Packets are in order and the timestamp diff is less than 5760 samples.
// Accept the timestamp diff as a valid frame size.
input_frame_size_timestamps = timestamp_diff;
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq_gn/moz.build b/third_party/libwebrtc/modules/audio_coding/neteq_gn/moz.build
index 834a8d1265..9b2996fa22 100644
--- a/third_party/libwebrtc/modules/audio_coding/neteq_gn/moz.build
+++ b/third_party/libwebrtc/modules/audio_coding/neteq_gn/moz.build
@@ -58,7 +58,6 @@ UNIFIED_SOURCES += [
"/third_party/libwebrtc/modules/audio_coding/neteq/packet.cc",
"/third_party/libwebrtc/modules/audio_coding/neteq/packet_arrival_history.cc",
"/third_party/libwebrtc/modules/audio_coding/neteq/packet_buffer.cc",
- "/third_party/libwebrtc/modules/audio_coding/neteq/post_decode_vad.cc",
"/third_party/libwebrtc/modules/audio_coding/neteq/preemptive_expand.cc",
"/third_party/libwebrtc/modules/audio_coding/neteq/random_vector.cc",
"/third_party/libwebrtc/modules/audio_coding/neteq/red_payload_splitter.cc",
diff --git a/third_party/libwebrtc/modules/audio_device/include/test_audio_device_unittest.cc b/third_party/libwebrtc/modules/audio_device/include/test_audio_device_unittest.cc
index 7a122ca84b..cca82977e8 100644
--- a/third_party/libwebrtc/modules/audio_device/include/test_audio_device_unittest.cc
+++ b/third_party/libwebrtc/modules/audio_device/include/test_audio_device_unittest.cc
@@ -39,9 +39,9 @@ void RunWavTest(const std::vector<int16_t>& input_samples,
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
- const std::string output_filename =
- test::OutputPath() + "BoundedWavFileWriterTest_" + test_info->name() +
- "_" + std::to_string(std::rand()) + ".wav";
+ const std::string output_filename = test::OutputPathWithRandomDirectory() +
+ "BoundedWavFileWriterTest_" +
+ test_info->name() + ".wav";
static const size_t kSamplesPerFrame = 8;
static const int kSampleRate = kSamplesPerFrame * 100;
@@ -136,9 +136,9 @@ TEST(WavFileReaderTest, RepeatedTrueWithSingleFrameFileReadTwice) {
static const rtc::BufferT<int16_t> kExpectedSamples(kInputSamples.data(),
kInputSamples.size());
- const std::string output_filename = test::OutputPath() +
+ const std::string output_filename = test::OutputPathWithRandomDirectory() +
"WavFileReaderTest_RepeatedTrue_" +
- std::to_string(std::rand()) + ".wav";
+ ".wav";
static const size_t kSamplesPerFrame = 8;
static const int kSampleRate = kSamplesPerFrame * 100;
@@ -175,9 +175,9 @@ void RunRawTestNoRepeat(const std::vector<int16_t>& input_samples,
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
- const std::string output_filename = test::OutputPath() + "RawFileTest_" +
- test_info->name() + "_" +
- std::to_string(std::rand()) + ".raw";
+ const std::string output_filename = test::OutputPathWithRandomDirectory() +
+ "RawFileTest_" + test_info->name() +
+ ".raw";
static const size_t kSamplesPerFrame = 8;
static const int kSampleRate = kSamplesPerFrame * 100;
@@ -281,8 +281,8 @@ TEST(RawFileWriterTest, Repeat) {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
- const std::string output_filename = test::OutputPath() + "RawFileTest_" +
- test_info->name() + "_" +
+ const std::string output_filename = test::OutputPathWithRandomDirectory() +
+ "RawFileTest_" + test_info->name() + "_" +
std::to_string(std::rand()) + ".raw";
static const size_t kSamplesPerFrame = 8;
diff --git a/third_party/libwebrtc/modules/audio_processing/agc2/input_volume_controller.h b/third_party/libwebrtc/modules/audio_processing/agc2/input_volume_controller.h
index 21405542dc..0bec7af450 100644
--- a/third_party/libwebrtc/modules/audio_processing/agc2/input_volume_controller.h
+++ b/third_party/libwebrtc/modules/audio_processing/agc2/input_volume_controller.h
@@ -50,7 +50,7 @@ class InputVolumeController final {
// Limited to values higher than 0.
int clipped_wait_frames = 300;
// Enables clipping prediction functionality.
- bool enable_clipping_predictor = false;
+ bool enable_clipping_predictor = true;
// Speech level target range (dBFS). If the speech level is in the range
// [`target_range_min_dbfs`, `target_range_max_dbfs`], no input volume
// adjustments are done based on the speech level. For speech levels below
diff --git a/third_party/libwebrtc/modules/audio_processing/audio_processing_impl.cc b/third_party/libwebrtc/modules/audio_processing/audio_processing_impl.cc
index 4ac074526c..5f6dd59d02 100644
--- a/third_party/libwebrtc/modules/audio_processing/audio_processing_impl.cc
+++ b/third_party/libwebrtc/modules/audio_processing/audio_processing_impl.cc
@@ -2382,7 +2382,7 @@ void AudioProcessingImpl::InitializeGainController2() {
!UseApmVadSubModule(config_, gain_controller2_experiment_params_);
submodules_.gain_controller2 = std::make_unique<GainController2>(
config_.gain_controller2, input_volume_controller_config,
- proc_fullband_sample_rate_hz(), num_proc_channels(), use_internal_vad);
+ proc_fullband_sample_rate_hz(), num_output_channels(), use_internal_vad);
submodules_.gain_controller2->SetCaptureOutputUsed(
capture_.capture_output_used);
}
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/third_party/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
index 94645dcc4a..d8a0ce9d64 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
@@ -720,7 +720,8 @@ PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const {
// Pacing rate is based on target rate before congestion window pushback,
// because we don't want to build queues in the pacer when pushback occurs.
DataRate pacing_rate = DataRate::Zero();
- if (pace_at_max_of_bwe_and_lower_link_capacity_ && estimate_) {
+ if (pace_at_max_of_bwe_and_lower_link_capacity_ && estimate_ &&
+ !bandwidth_estimation_->PaceAtLossBasedEstimate()) {
pacing_rate =
std::max({min_total_allocated_bitrate_, estimate_->link_capacity_lower,
last_loss_based_target_rate_}) *
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc b/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
index 8e1a3c4698..2f47ee0f18 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
@@ -499,6 +499,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
FieldTrialParameter<TimeDelta> padding_duration("PaddingDuration",
TimeDelta::Zero());
FieldTrialParameter<bool> bound_best_candidate("BoundBestCandidate", false);
+ FieldTrialParameter<bool> pace_at_loss_based_estimate(
+ "PaceAtLossBasedEstimate", false);
if (key_value_config) {
ParseFieldTrial({&enabled,
&bandwidth_rampup_upper_bound_factor,
@@ -538,7 +540,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
&hold_duration_factor,
&use_byte_loss_rate,
&padding_duration,
- &bound_best_candidate},
+ &bound_best_candidate,
+ &pace_at_loss_based_estimate},
key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2"));
}
@@ -604,6 +607,7 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
config->use_byte_loss_rate = use_byte_loss_rate.Get();
config->padding_duration = padding_duration.Get();
config->bound_best_candidate = bound_best_candidate.Get();
+ config->pace_at_loss_based_estimate = pace_at_loss_based_estimate.Get();
return config;
}
@@ -1199,4 +1203,9 @@ bool LossBasedBweV2::CanKeepIncreasingState(DataRate estimate) const {
last_padding_info_.padding_rate < estimate;
}
+bool LossBasedBweV2::PaceAtLossBasedEstimate() const {
+ return config_->pace_at_loss_based_estimate &&
+ loss_based_result_.state != LossBasedState::kDelayBasedEstimate;
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h b/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
index 9afbb11f1f..34c96c66d9 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
@@ -74,6 +74,7 @@ class LossBasedBweV2 {
rtc::ArrayView<const PacketResult> packet_results,
DataRate delay_based_estimate,
bool in_alr);
+ bool PaceAtLossBasedEstimate() const;
// For unit testing only.
void SetBandwidthEstimate(DataRate bandwidth_estimate);
@@ -124,6 +125,7 @@ class LossBasedBweV2 {
bool use_byte_loss_rate = false;
TimeDelta padding_duration = TimeDelta::Zero();
bool bound_best_candidate = false;
+ bool pace_at_loss_based_estimate = false;
};
struct Derivatives {
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc b/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
index 9b7ad03148..bb867f4fb0 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
@@ -1776,5 +1776,41 @@ TEST_F(LossBasedBweV2Test, UseByteLossRate) {
DataRate::KilobitsPerSec(150));
}
+TEST_F(LossBasedBweV2Test, PaceAtLossBasedEstimate) {
+ ExplicitKeyValueConfig key_value_config(ShortObservationConfig(
+ "PaceAtLossBasedEstimate:true,PaddingDuration:1000ms"));
+ LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
+ loss_based_bandwidth_estimator.SetBandwidthEstimate(
+ DataRate::KilobitsPerSec(1000));
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ CreatePacketResultsWithReceivedPackets(
+ /*first_packet_timestamp=*/Timestamp::Zero()),
+ /*delay_based_estimate=*/DataRate::KilobitsPerSec(1000),
+ /*in_alr=*/false);
+ EXPECT_EQ(loss_based_bandwidth_estimator.GetLossBasedResult().state,
+ LossBasedState::kDelayBasedEstimate);
+ EXPECT_FALSE(loss_based_bandwidth_estimator.PaceAtLossBasedEstimate());
+
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ CreatePacketResultsWith100pLossRate(
+ /*first_packet_timestamp=*/Timestamp::Zero() +
+ kObservationDurationLowerBound),
+ /*delay_based_estimate=*/DataRate::KilobitsPerSec(1000),
+ /*in_alr=*/false);
+ EXPECT_EQ(loss_based_bandwidth_estimator.GetLossBasedResult().state,
+ LossBasedState::kDecreasing);
+ EXPECT_TRUE(loss_based_bandwidth_estimator.PaceAtLossBasedEstimate());
+
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ CreatePacketResultsWithReceivedPackets(
+ /*first_packet_timestamp=*/Timestamp::Zero() +
+ kObservationDurationLowerBound * 2),
+ /*delay_based_estimate=*/DataRate::KilobitsPerSec(1000),
+ /*in_alr=*/false);
+ EXPECT_EQ(loss_based_bandwidth_estimator.GetLossBasedResult().state,
+ LossBasedState::kIncreaseUsingPadding);
+ EXPECT_TRUE(loss_based_bandwidth_estimator.PaceAtLossBasedEstimate());
+}
+
} // namespace
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc
index 32b1b93c0b..31727051a8 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc
@@ -105,8 +105,7 @@ ProbeControllerConfig::ProbeControllerConfig(
probe_on_max_allocated_bitrate_change("probe_max_allocation", true),
first_allocation_probe_scale("alloc_p1", 1),
second_allocation_probe_scale("alloc_p2", 2),
- allocation_allow_further_probing("alloc_probe_further", false),
- allocation_probe_max("alloc_probe_max", DataRate::PlusInfinity()),
+ allocation_probe_limit_by_current_scale("alloc_current_bwe_limit"),
min_probe_packets_sent("min_probe_packets_sent", 5),
min_probe_duration("min_probe_duration", TimeDelta::Millis(15)),
loss_limited_probe_scale("loss_limited_scale", 1.5),
@@ -118,7 +117,7 @@ ProbeControllerConfig::ProbeControllerConfig(
&further_exponential_probe_scale, &further_probe_threshold,
&alr_probing_interval, &alr_probe_scale,
&probe_on_max_allocated_bitrate_change, &first_allocation_probe_scale,
- &second_allocation_probe_scale, &allocation_allow_further_probing,
+ &second_allocation_probe_scale, &allocation_probe_limit_by_current_scale,
&min_probe_duration, &network_state_estimate_probing_interval,
&probe_if_estimate_lower_than_network_state_estimate_ratio,
&estimate_lower_than_network_state_estimate_probing_interval,
@@ -138,7 +137,7 @@ ProbeControllerConfig::ProbeControllerConfig(
key_value_config->Lookup("WebRTC-Bwe-AlrProbing"));
ParseFieldTrial(
{&first_allocation_probe_scale, &second_allocation_probe_scale,
- &allocation_allow_further_probing, &allocation_probe_max},
+ &allocation_probe_limit_by_current_scale},
key_value_config->Lookup("WebRTC-Bwe-AllocationProbing"));
ParseFieldTrial({&min_probe_packets_sent, &min_probe_duration},
key_value_config->Lookup("WebRTC-Bwe-ProbingBehavior"));
@@ -220,19 +219,31 @@ std::vector<ProbeClusterConfig> ProbeController::OnMaxTotalAllocatedBitrate(
DataRate first_probe_rate = max_total_allocated_bitrate *
config_.first_allocation_probe_scale.Value();
- DataRate probe_cap = config_.allocation_probe_max.Get();
- first_probe_rate = std::min(first_probe_rate, probe_cap);
+ DataRate current_bwe_limit =
+ !config_.allocation_probe_limit_by_current_scale
+ ? DataRate::PlusInfinity()
+ : estimated_bitrate_ *
+ config_.allocation_probe_limit_by_current_scale.Value();
+ bool limited_by_current_bwe = current_bwe_limit < first_probe_rate;
+ if (limited_by_current_bwe) {
+ first_probe_rate = current_bwe_limit;
+ }
+
std::vector<DataRate> probes = {first_probe_rate};
- if (config_.second_allocation_probe_scale) {
+ if (!limited_by_current_bwe && config_.second_allocation_probe_scale) {
DataRate second_probe_rate =
max_total_allocated_bitrate *
config_.second_allocation_probe_scale.Value();
- second_probe_rate = std::min(second_probe_rate, probe_cap);
+ limited_by_current_bwe = current_bwe_limit < second_probe_rate;
+ if (limited_by_current_bwe) {
+ second_probe_rate = current_bwe_limit;
+ }
if (second_probe_rate > first_probe_rate)
probes.push_back(second_probe_rate);
}
- return InitiateProbing(at_time, probes,
- config_.allocation_allow_further_probing.Get());
+ bool allow_further_probing = limited_by_current_bwe;
+
+ return InitiateProbing(at_time, probes, allow_further_probing);
}
max_total_allocated_bitrate_ = max_total_allocated_bitrate;
return std::vector<ProbeClusterConfig>();
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h b/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h
index feec81f2dc..25f02aee69 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h
@@ -64,8 +64,7 @@ struct ProbeControllerConfig {
FieldTrialParameter<bool> probe_on_max_allocated_bitrate_change;
FieldTrialOptional<double> first_allocation_probe_scale;
FieldTrialOptional<double> second_allocation_probe_scale;
- FieldTrialFlag allocation_allow_further_probing;
- FieldTrialParameter<DataRate> allocation_probe_max;
+ FieldTrialOptional<double> allocation_probe_limit_by_current_scale;
// The minimum number probing packets used.
FieldTrialParameter<int> min_probe_packets_sent;
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller_unittest.cc b/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller_unittest.cc
index 94025b30ea..6e34a2962d 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller_unittest.cc
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/probe_controller_unittest.cc
@@ -213,6 +213,42 @@ TEST(ProbeControllerTest, ProbesOnMaxAllocatedBitrateIncreaseOnlyWhenInAlr) {
EXPECT_TRUE(probes.empty());
}
+TEST(ProbeControllerTest, ProbesOnMaxAllocatedBitrateLimitedByCurrentBwe) {
+ ProbeControllerFixture fixture(
+ "WebRTC-Bwe-ProbingConfiguration/"
+ "alloc_current_bwe_limit:1.5/");
+ ASSERT_TRUE(kMaxBitrate > 1.5 * kStartBitrate);
+ std::unique_ptr<ProbeController> probe_controller =
+ fixture.CreateController();
+ ASSERT_THAT(
+ probe_controller->OnNetworkAvailability({.network_available = true}),
+ IsEmpty());
+ auto probes = probe_controller->SetBitrates(
+ kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
+ probes = probe_controller->SetEstimatedBitrate(
+ kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
+ fixture.CurrentTime());
+
+ // Wait long enough to time out exponential probing.
+ fixture.AdvanceTime(kExponentialProbingTimeout);
+ probes = probe_controller->Process(fixture.CurrentTime());
+ EXPECT_TRUE(probes.empty());
+
+ // Probe when in alr.
+ probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
+ probes = probe_controller->OnMaxTotalAllocatedBitrate(kMaxBitrate,
+ fixture.CurrentTime());
+ EXPECT_EQ(probes.size(), 1u);
+ EXPECT_EQ(probes.at(0).target_data_rate, 1.5 * kStartBitrate);
+
+ // Continue probing if probe succeeds.
+ probes = probe_controller->SetEstimatedBitrate(
+ 1.5 * kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
+ fixture.CurrentTime());
+ EXPECT_EQ(probes.size(), 1u);
+ EXPECT_GT(probes.at(0).target_data_rate, 1.5 * kStartBitrate);
+}
+
TEST(ProbeControllerTest, CanDisableProbingOnMaxTotalAllocatedBitrateIncrease) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc b/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc
index 211d86c95d..7b305f12f1 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc
@@ -700,8 +700,12 @@ bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV2Enabled() const {
bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV2ReadyForUse()
const {
- return LossBasedBandwidthEstimatorV2Enabled() &&
- loss_based_bandwidth_estimator_v2_->IsReady();
+ return loss_based_bandwidth_estimator_v2_->IsReady();
+}
+
+bool SendSideBandwidthEstimation::PaceAtLossBasedEstimate() const {
+ return LossBasedBandwidthEstimatorV2ReadyForUse() &&
+ loss_based_bandwidth_estimator_v2_->PaceAtLossBasedEstimate();
}
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h b/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h
index dd4d25a236..1d919af7b6 100644
--- a/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h
+++ b/third_party/libwebrtc/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h
@@ -129,6 +129,7 @@ class SendSideBandwidthEstimation {
BandwidthUsage delay_detector_state,
absl::optional<DataRate> probe_bitrate,
bool in_alr);
+ bool PaceAtLossBasedEstimate() const;
private:
friend class GoogCcStatePrinter;
diff --git a/third_party/libwebrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc b/third_party/libwebrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
index 9c64125b4e..ac028ce38b 100644
--- a/third_party/libwebrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
+++ b/third_party/libwebrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
@@ -112,9 +112,13 @@ bool DxgiOutputDuplicator::DuplicateOutput() {
memset(&desc_, 0, sizeof(desc_));
duplication_->GetDesc(&desc_);
- if (desc_.ModeDesc.Format != DXGI_FORMAT_B8G8R8A8_UNORM) {
- RTC_LOG(LS_ERROR) << "IDXGIDuplicateOutput does not use RGBA (8 bit) "
- << "format, which is required by downstream components, "
+
+ // DXGI_FORMAT_R16G16B16A16_FLOAT is returned for HDR monitor,
+ // DXGI_FORMAT_B8G8R8A8_UNORM for others.
+ if ((desc_.ModeDesc.Format != DXGI_FORMAT_B8G8R8A8_UNORM) &&
+ (desc_.ModeDesc.Format != DXGI_FORMAT_R16G16B16A16_FLOAT)) {
+ RTC_LOG(LS_ERROR) << "IDXGIDuplicateOutput does not use RGBA (8, 16 bit)"
+ << "which is required by downstream components"
<< "format is " << desc_.ModeDesc.Format;
return false;
}
diff --git a/third_party/libwebrtc/modules/pacing/bitrate_prober.cc b/third_party/libwebrtc/modules/pacing/bitrate_prober.cc
index e60a1e5283..17729b5775 100644
--- a/third_party/libwebrtc/modules/pacing/bitrate_prober.cc
+++ b/third_party/libwebrtc/modules/pacing/bitrate_prober.cc
@@ -52,6 +52,18 @@ void BitrateProber::SetEnabled(bool enable) {
}
}
+void BitrateProber::SetAllowProbeWithoutMediaPacket(bool allow) {
+ config_.allow_start_probing_immediately = allow;
+ MaybeSetActiveState(/*packet_size=*/DataSize::Zero());
+}
+
+void BitrateProber::MaybeSetActiveState(DataSize packet_size) {
+ if (ReadyToSetActiveState(packet_size)) {
+ next_probe_time_ = Timestamp::MinusInfinity();
+ probing_state_ = ProbingState::kActive;
+ }
+}
+
bool BitrateProber::ReadyToSetActiveState(DataSize packet_size) const {
if (clusters_.empty()) {
RTC_DCHECK(probing_state_ == ProbingState::kDisabled ||
@@ -63,19 +75,19 @@ bool BitrateProber::ReadyToSetActiveState(DataSize packet_size) const {
case ProbingState::kActive:
return false;
case ProbingState::kInactive:
- // If config_.min_packet_size > 0, a "large enough" packet must be sent
- // first, before a probe can be generated and sent. Otherwise, send the
- // probe asap.
+ if (config_.allow_start_probing_immediately) {
+ return true;
+ }
+ // If config_.min_packet_size > 0, a "large enough" packet must be
+ // sent first, before a probe can be generated and sent. Otherwise,
+ // send the probe asap.
return packet_size >=
std::min(RecommendedMinProbeSize(), config_.min_packet_size.Get());
}
}
void BitrateProber::OnIncomingPacket(DataSize packet_size) {
- if (ReadyToSetActiveState(packet_size)) {
- next_probe_time_ = Timestamp::MinusInfinity();
- probing_state_ = ProbingState::kActive;
- }
+ MaybeSetActiveState(packet_size);
}
void BitrateProber::CreateProbeCluster(
@@ -101,10 +113,8 @@ void BitrateProber::CreateProbeCluster(
cluster.pace_info.probe_cluster_id = cluster_config.id;
clusters_.push(cluster);
- if (ReadyToSetActiveState(/*packet_size=*/DataSize::Zero())) {
- next_probe_time_ = Timestamp::MinusInfinity();
- probing_state_ = ProbingState::kActive;
- }
+ MaybeSetActiveState(/*packet_size=*/DataSize::Zero());
+
RTC_DCHECK(probing_state_ == ProbingState::kActive ||
probing_state_ == ProbingState::kInactive);
diff --git a/third_party/libwebrtc/modules/pacing/bitrate_prober.h b/third_party/libwebrtc/modules/pacing/bitrate_prober.h
index 82aba6ee3a..821bbf32eb 100644
--- a/third_party/libwebrtc/modules/pacing/bitrate_prober.h
+++ b/third_party/libwebrtc/modules/pacing/bitrate_prober.h
@@ -38,6 +38,9 @@ struct BitrateProberConfig {
// This defines the max min packet size, meaning that on high bitrates
// a packet of at least this size is needed to trigger sending a probe.
FieldTrialParameter<DataSize> min_packet_size;
+
+ // If true, `min_packet_size` is ignored.
+ bool allow_start_probing_immediately = false;
};
// Note that this class isn't thread-safe by itself and therefore relies
@@ -48,6 +51,7 @@ class BitrateProber {
~BitrateProber() = default;
void SetEnabled(bool enable);
+ void SetAllowProbeWithoutMediaPacket(bool allow);
// Returns true if the prober is in a probing session, i.e., it currently
// wants packets to be sent out according to the time returned by
@@ -105,6 +109,8 @@ class BitrateProber {
};
Timestamp CalculateNextProbeTime(const ProbeCluster& cluster) const;
+
+ void MaybeSetActiveState(DataSize packet_size);
bool ReadyToSetActiveState(DataSize packet_size) const;
ProbingState probing_state_;
diff --git a/third_party/libwebrtc/modules/pacing/pacing_controller.cc b/third_party/libwebrtc/modules/pacing/pacing_controller.cc
index 41f97a37fb..a45c5d8f63 100644
--- a/third_party/libwebrtc/modules/pacing/pacing_controller.cc
+++ b/third_party/libwebrtc/modules/pacing/pacing_controller.cc
@@ -252,6 +252,10 @@ void PacingController::SetSendBurstInterval(TimeDelta burst_interval) {
send_burst_interval_ = burst_interval;
}
+void PacingController::SetAllowProbeWithoutMediaPacket(bool allow) {
+ prober_.SetAllowProbeWithoutMediaPacket(allow);
+}
+
TimeDelta PacingController::ExpectedQueueTime() const {
RTC_DCHECK_GT(adjusted_media_rate_, DataRate::Zero());
return QueueSizeData() / adjusted_media_rate_;
diff --git a/third_party/libwebrtc/modules/pacing/pacing_controller.h b/third_party/libwebrtc/modules/pacing/pacing_controller.h
index fe6ee737a9..bdf8bef392 100644
--- a/third_party/libwebrtc/modules/pacing/pacing_controller.h
+++ b/third_party/libwebrtc/modules/pacing/pacing_controller.h
@@ -160,6 +160,9 @@ class PacingController {
// 'burst_interval'.
void SetSendBurstInterval(TimeDelta burst_interval);
+ // A probe may be sent without first waing for a media packet.
+ void SetAllowProbeWithoutMediaPacket(bool allow);
+
// Returns the time when the oldest packet was queued.
Timestamp OldestPacketEnqueueTime() const;
diff --git a/third_party/libwebrtc/modules/pacing/pacing_controller_unittest.cc b/third_party/libwebrtc/modules/pacing/pacing_controller_unittest.cc
index 2c3a71b369..8a37292b95 100644
--- a/third_party/libwebrtc/modules/pacing/pacing_controller_unittest.cc
+++ b/third_party/libwebrtc/modules/pacing/pacing_controller_unittest.cc
@@ -1366,10 +1366,9 @@ TEST_F(PacingControllerTest, CanProbeWithPaddingBeforeFirstMediaPacket) {
const int kInitialBitrateBps = 300000;
PacingControllerProbing packet_sender;
- const test::ExplicitKeyValueConfig trials(
- "WebRTC-Bwe-ProbingBehavior/min_packet_size:0/");
auto pacer =
- std::make_unique<PacingController>(&clock_, &packet_sender, trials);
+ std::make_unique<PacingController>(&clock_, &packet_sender, trials_);
+ pacer->SetAllowProbeWithoutMediaPacket(true);
std::vector<ProbeClusterConfig> probe_clusters = {
{.at_time = clock_.CurrentTime(),
.target_data_rate = kFirstClusterRate,
@@ -1393,16 +1392,46 @@ TEST_F(PacingControllerTest, CanProbeWithPaddingBeforeFirstMediaPacket) {
EXPECT_GT(packet_sender.padding_packets_sent(), 5);
}
+TEST_F(PacingControllerTest, ProbeSentAfterSetAllowProbeWithoutMediaPacket) {
+ const int kInitialBitrateBps = 300000;
+
+ PacingControllerProbing packet_sender;
+ auto pacer =
+ std::make_unique<PacingController>(&clock_, &packet_sender, trials_);
+ std::vector<ProbeClusterConfig> probe_clusters = {
+ {.at_time = clock_.CurrentTime(),
+ .target_data_rate = kFirstClusterRate,
+ .target_duration = TimeDelta::Millis(15),
+ .target_probe_count = 5,
+ .id = 0}};
+ pacer->CreateProbeClusters(probe_clusters);
+
+ pacer->SetPacingRates(
+ DataRate::BitsPerSec(kInitialBitrateBps * kPaceMultiplier),
+ DataRate::Zero());
+
+ pacer->SetAllowProbeWithoutMediaPacket(true);
+
+ Timestamp start = clock_.CurrentTime();
+ Timestamp next_process = pacer->NextSendTime();
+ while (clock_.CurrentTime() < start + TimeDelta::Millis(100) &&
+ next_process.IsFinite()) {
+ AdvanceTimeUntil(next_process);
+ pacer->ProcessPackets();
+ next_process = pacer->NextSendTime();
+ }
+ EXPECT_GT(packet_sender.padding_packets_sent(), 5);
+}
+
TEST_F(PacingControllerTest, CanNotProbeWithPaddingIfGeneratePaddingFails) {
// const size_t kPacketSize = 1200;
const int kInitialBitrateBps = 300000;
PacingControllerProbing packet_sender;
packet_sender.SetCanGeneratePadding(false);
- const test::ExplicitKeyValueConfig trials(
- "WebRTC-Bwe-ProbingBehavior/min_packet_size:0/");
auto pacer =
- std::make_unique<PacingController>(&clock_, &packet_sender, trials);
+ std::make_unique<PacingController>(&clock_, &packet_sender, trials_);
+ pacer->SetAllowProbeWithoutMediaPacket(true);
std::vector<ProbeClusterConfig> probe_clusters = {
{.at_time = clock_.CurrentTime(),
.target_data_rate = kFirstClusterRate,
diff --git a/third_party/libwebrtc/modules/pacing/packet_router.cc b/third_party/libwebrtc/modules/pacing/packet_router.cc
index 4c986ad027..0ad64f212d 100644
--- a/third_party/libwebrtc/modules/pacing/packet_router.cc
+++ b/third_party/libwebrtc/modules/pacing/packet_router.cc
@@ -65,6 +65,16 @@ void PacketRouter::AddSendRtpModule(RtpRtcpInterface* rtp_module,
}
}
+bool PacketRouter::SupportsRtxPayloadPadding() const {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ for (RtpRtcpInterface* rtp_module : send_modules_list_) {
+ if (rtp_module->SupportsRtxPayloadPadding()) {
+ return true;
+ }
+ }
+ return false;
+}
+
void PacketRouter::AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module,
uint32_t ssrc) {
RTC_DCHECK_RUN_ON(&thread_checker_);
diff --git a/third_party/libwebrtc/modules/pacing/packet_router.h b/third_party/libwebrtc/modules/pacing/packet_router.h
index 61779f49e5..4c5747f7e3 100644
--- a/third_party/libwebrtc/modules/pacing/packet_router.h
+++ b/third_party/libwebrtc/modules/pacing/packet_router.h
@@ -50,6 +50,8 @@ class PacketRouter : public PacingController::PacketSender {
void AddSendRtpModule(RtpRtcpInterface* rtp_module, bool remb_candidate);
void RemoveSendRtpModule(RtpRtcpInterface* rtp_module);
+ bool SupportsRtxPayloadPadding() const;
+
void AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
bool remb_candidate);
void RemoveReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender);
diff --git a/third_party/libwebrtc/modules/pacing/packet_router_unittest.cc b/third_party/libwebrtc/modules/pacing/packet_router_unittest.cc
index af8534316c..b91c309eec 100644
--- a/third_party/libwebrtc/modules/pacing/packet_router_unittest.cc
+++ b/third_party/libwebrtc/modules/pacing/packet_router_unittest.cc
@@ -125,6 +125,31 @@ TEST_F(PacketRouterTest, GeneratePaddingPrioritizesRtx) {
packet_router_.RemoveSendRtpModule(&rtp_2);
}
+TEST_F(PacketRouterTest, SupportsRtxPayloadPaddingFalseIfNoRtxSendModule) {
+ EXPECT_FALSE(packet_router_.SupportsRtxPayloadPadding());
+
+ NiceMock<MockRtpRtcpInterface> none_rtx_module;
+ ON_CALL(none_rtx_module, SupportsRtxPayloadPadding())
+ .WillByDefault(Return(false));
+
+ packet_router_.AddSendRtpModule(&none_rtx_module, false);
+ EXPECT_FALSE(packet_router_.SupportsRtxPayloadPadding());
+
+ packet_router_.RemoveSendRtpModule(&none_rtx_module);
+ EXPECT_FALSE(packet_router_.SupportsRtxPayloadPadding());
+}
+
+TEST_F(PacketRouterTest, SupportsRtxPayloadPaddingTrueIfRtxSendModule) {
+ NiceMock<MockRtpRtcpInterface> rtx_module;
+ ON_CALL(rtx_module, SupportsRtxPayloadPadding()).WillByDefault(Return(true));
+
+ packet_router_.AddSendRtpModule(&rtx_module, false);
+ EXPECT_TRUE(packet_router_.SupportsRtxPayloadPadding());
+
+ packet_router_.RemoveSendRtpModule(&rtx_module);
+ EXPECT_FALSE(packet_router_.SupportsRtxPayloadPadding());
+}
+
TEST_F(PacketRouterTest, GeneratePaddingPrioritizesVideo) {
// Two RTP modules. Neither support RTX, both support padding,
// but the first one is for audio and second for video.
diff --git a/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.cc b/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.cc
index f7218e48a1..5559153251 100644
--- a/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.cc
+++ b/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.cc
@@ -52,6 +52,11 @@ void TaskQueuePacedSender::SetSendBurstInterval(TimeDelta burst_interval) {
pacing_controller_.SetSendBurstInterval(burst_interval);
}
+void TaskQueuePacedSender::SetAllowProbeWithoutMediaPacket(bool allow) {
+ RTC_DCHECK_RUN_ON(task_queue_);
+ pacing_controller_.SetAllowProbeWithoutMediaPacket(allow);
+}
+
void TaskQueuePacedSender::EnsureStarted() {
RTC_DCHECK_RUN_ON(task_queue_);
is_started_ = true;
diff --git a/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.h b/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.h
index e29acdf878..a1d2474ca1 100644
--- a/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.h
+++ b/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.h
@@ -60,6 +60,9 @@ class TaskQueuePacedSender : public RtpPacketPacer, public RtpPacketSender {
// 'burst_interval'.
void SetSendBurstInterval(TimeDelta burst_interval);
+ // A probe may be sent without first waing for a media packet.
+ void SetAllowProbeWithoutMediaPacket(bool allow);
+
// Ensure that necessary delayed tasks are scheduled.
void EnsureStarted();
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/BUILD.gn b/third_party/libwebrtc/modules/rtp_rtcp/BUILD.gn
index b471c2fa76..2c42e53d36 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/BUILD.gn
+++ b/third_party/libwebrtc/modules/rtp_rtcp/BUILD.gn
@@ -260,8 +260,11 @@ rtc_library("rtp_rtcp") {
if (rtc_use_h265) {
sources += [
+ "source/rtp_packet_h265_common.h",
"source/rtp_packetizer_h265.cc",
"source/rtp_packetizer_h265.h",
+ "source/video_rtp_depacketizer_h265.cc",
+ "source/video_rtp_depacketizer_h265.h",
]
}
@@ -632,7 +635,10 @@ if (rtc_include_tests) {
"source/video_rtp_depacketizer_vp9_unittest.cc",
]
if (rtc_use_h265) {
- sources += [ "source/rtp_packetizer_h265_unittest.cc" ]
+ sources += [
+ "source/rtp_packetizer_h265_unittest.cc",
+ "source/video_rtp_depacketizer_h265_unittest.cc",
+ ]
}
deps = [
@@ -652,6 +658,7 @@ if (rtc_include_tests) {
"../../api:frame_transformer_factory",
"../../api:make_ref_counted",
"../../api:mock_frame_encryptor",
+ "../../api:mock_frame_transformer",
"../../api:mock_transformable_video_frame",
"../../api:rtp_headers",
"../../api:rtp_packet_info",
@@ -698,7 +705,6 @@ if (rtc_include_tests) {
"../../rtc_base:timeutils",
"../../system_wrappers",
"../../test:explicit_key_value_config",
- "../../test:mock_frame_transformer",
"../../test:mock_transport",
"../../test:rtp_test_utils",
"../../test:run_loop",
@@ -720,13 +726,13 @@ if (rtc_include_tests) {
sources = [ "source/frame_transformer_factory_unittest.cc" ]
deps = [
"../../api:frame_transformer_factory",
+ "../../api:mock_frame_transformer",
"../../api:mock_transformable_audio_frame",
"../../api:mock_transformable_video_frame",
"../../api:transport_api",
"../../call:video_stream_api",
"../../modules/rtp_rtcp",
"../../rtc_base:rtc_event",
- "../../test:mock_frame_transformer",
"../../test:test_support",
"../../video",
]
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
index 95db212bef..598a86d4ad 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
@@ -19,6 +19,9 @@
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp8.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.h"
+#ifdef RTC_ENABLE_H265
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h"
+#endif
namespace webrtc {
@@ -34,8 +37,11 @@ std::unique_ptr<VideoRtpDepacketizer> CreateVideoRtpDepacketizer(
case kVideoCodecAV1:
return std::make_unique<VideoRtpDepacketizerAv1>();
case kVideoCodecH265:
- // TODO(bugs.webrtc.org/13485): Implement VideoRtpDepacketizerH265.
+#ifdef RTC_ENABLE_H265
+ return std::make_unique<VideoRtpDepacketizerH265>();
+#else
return nullptr;
+#endif
case kVideoCodecGeneric:
case kVideoCodecMultiplex:
return std::make_unique<VideoRtpDepacketizerGeneric>();
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/frame_transformer_factory_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/frame_transformer_factory_unittest.cc
index a61179e9d3..788052da39 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/source/frame_transformer_factory_unittest.cc
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/frame_transformer_factory_unittest.cc
@@ -17,6 +17,7 @@
#include "absl/memory/memory.h"
#include "api/call/transport.h"
+#include "api/test/mock_frame_transformer.h"
#include "api/test/mock_transformable_audio_frame.h"
#include "api/test/mock_transformable_video_frame.h"
#include "call/video_receive_stream.h"
@@ -24,7 +25,6 @@
#include "rtc_base/event.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
namespace webrtc {
namespace {
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packet_h265_common.h b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packet_h265_common.h
new file mode 100644
index 0000000000..8655a02001
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packet_h265_common.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H265_COMMON_H_
+#define MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H265_COMMON_H_
+
+#include <string>
+#include <vector>
+
+namespace webrtc {
+// The payload header consists of the same
+// fields (F, Type, LayerId and TID) as the NAL unit header. Refer to
+// section 4.4 in RFC 7798.
+constexpr size_t kH265PayloadHeaderSizeBytes = 2;
+// Unlike H.264, H.265 NAL header is 2-bytes.
+constexpr size_t kH265NalHeaderSizeBytes = 2;
+// H.265's FU is constructed of 2-byte payload header, 1-byte FU header and FU
+// payload.
+constexpr size_t kH265FuHeaderSizeBytes = 1;
+// The NALU size for H.265 RTP aggregated packet indicates the size of the NAL
+// unit is 2-bytes.
+constexpr size_t kH265LengthFieldSizeBytes = 2;
+constexpr size_t kH265ApHeaderSizeBytes =
+ kH265NalHeaderSizeBytes + kH265LengthFieldSizeBytes;
+
+// Bit masks for NAL headers.
+enum NalHdrMasks {
+ kH265FBit = 0x80,
+ kH265TypeMask = 0x7E,
+ kH265LayerIDHMask = 0x1,
+ kH265LayerIDLMask = 0xF8,
+ kH265TIDMask = 0x7,
+ kH265TypeMaskN = 0x81,
+ kH265TypeMaskInFuHeader = 0x3F
+};
+
+// Bit masks for FU headers.
+enum FuBitmasks {
+ kH265SBitMask = 0x80,
+ kH265EBitMask = 0x40,
+ kH265FuTypeBitMask = 0x3F
+};
+
+constexpr uint8_t kStartCode[] = {0, 0, 0, 1};
+
+} // namespace webrtc
+
+#endif // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H265_COMMON_H_
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265.cc
index 313680cc87..5f10120d81 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265.cc
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265.cc
@@ -16,42 +16,10 @@
#include "common_video/h264/h264_common.h"
#include "common_video/h265/h265_common.h"
#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_packet_h265_common.h"
#include "rtc_base/logging.h"
namespace webrtc {
-namespace {
-
-// The payload header consists of the same
-// fields (F, Type, LayerId and TID) as the NAL unit header. Refer to
-// section 4.2 in RFC 7798.
-constexpr size_t kH265PayloadHeaderSize = 2;
-// Unlike H.264, H265 NAL header is 2-bytes.
-constexpr size_t kH265NalHeaderSize = 2;
-// H265's FU is constructed of 2-byte payload header, 1-byte FU header and FU
-// payload.
-constexpr size_t kH265FuHeaderSize = 1;
-// The NALU size for H265 RTP aggregated packet indicates the size of the NAL
-// unit is 2-bytes.
-constexpr size_t kH265LengthFieldSize = 2;
-
-enum H265NalHdrMasks {
- kH265FBit = 0x80,
- kH265TypeMask = 0x7E,
- kH265LayerIDHMask = 0x1,
- kH265LayerIDLMask = 0xF8,
- kH265TIDMask = 0x7,
- kH265TypeMaskN = 0x81,
- kH265TypeMaskInFuHeader = 0x3F
-};
-
-// Bit masks for FU headers.
-enum H265FuBitmasks {
- kH265SBitMask = 0x80,
- kH265EBitMask = 0x40,
- kH265FuTypeBitMask = 0x3F
-};
-
-} // namespace
RtpPacketizerH265::RtpPacketizerH265(rtc::ArrayView<const uint8_t> payload,
PayloadSizeLimits limits)
@@ -112,7 +80,8 @@ bool RtpPacketizerH265::PacketizeFu(size_t fragment_index) {
// Refer to section 4.4.3 in RFC7798, each FU fragment will have a 2-bytes
// payload header and a one-byte FU header. DONL is not supported so ignore
// its size when calculating max_payload_len.
- limits.max_payload_len -= kH265FuHeaderSize + kH265PayloadHeaderSize;
+ limits.max_payload_len -=
+ kH265FuHeaderSizeBytes + kH265PayloadHeaderSizeBytes;
// Update single/first/last packet reductions unless it is single/first/last
// fragment.
@@ -135,8 +104,8 @@ bool RtpPacketizerH265::PacketizeFu(size_t fragment_index) {
}
// Strip out the original header.
- size_t payload_left = fragment.size() - kH265NalHeaderSize;
- int offset = kH265NalHeaderSize;
+ size_t payload_left = fragment.size() - kH265NalHeaderSizeBytes;
+ int offset = kH265NalHeaderSizeBytes;
std::vector<int> payload_sizes = SplitAboutEqually(payload_left, limits);
if (payload_sizes.empty()) {
@@ -198,12 +167,13 @@ int RtpPacketizerH265::PacketizeAp(size_t fragment_index) {
payload_size_left -= fragment.size();
payload_size_left -= fragment_headers_length;
- fragment_headers_length = kH265LengthFieldSize;
+ fragment_headers_length = kH265LengthFieldSizeBytes;
// If we are going to try to aggregate more fragments into this packet
// we need to add the AP NALU header and a length field for the first
// NALU of this packet.
if (aggregated_fragments == 0) {
- fragment_headers_length += kH265PayloadHeaderSize + kH265LengthFieldSize;
+ fragment_headers_length +=
+ kH265PayloadHeaderSizeBytes + kH265LengthFieldSizeBytes;
}
++aggregated_fragments;
@@ -248,7 +218,7 @@ bool RtpPacketizerH265::NextPacket(RtpPacketToSend* rtp_packet) {
void RtpPacketizerH265::NextAggregatePacket(RtpPacketToSend* rtp_packet) {
size_t payload_capacity = rtp_packet->FreeCapacity();
- RTC_CHECK_GE(payload_capacity, kH265PayloadHeaderSize);
+ RTC_CHECK_GE(payload_capacity, kH265PayloadHeaderSizeBytes);
uint8_t* buffer = rtp_packet->AllocatePayload(payload_capacity);
RTC_CHECK(buffer);
PacketUnit* packet = &packets_.front();
@@ -272,13 +242,13 @@ void RtpPacketizerH265::NextAggregatePacket(RtpPacketToSend* rtp_packet) {
buffer[0] = payload_hdr_h;
buffer[1] = payload_hdr_l;
- int index = kH265PayloadHeaderSize;
+ int index = kH265PayloadHeaderSizeBytes;
bool is_last_fragment = packet->last_fragment;
while (packet->aggregated) {
// Add NAL unit length field.
rtc::ArrayView<const uint8_t> fragment = packet->source_fragment;
ByteWriter<uint16_t>::WriteBigEndian(&buffer[index], fragment.size());
- index += kH265LengthFieldSize;
+ index += kH265LengthFieldSizeBytes;
// Add NAL unit.
memcpy(&buffer[index], fragment.data(), fragment.size());
index += fragment.size();
@@ -332,15 +302,15 @@ void RtpPacketizerH265::NextFragmentPacket(RtpPacketToSend* rtp_packet) {
(H265::NaluType::kFu << 1) | layer_id_h;
rtc::ArrayView<const uint8_t> fragment = packet->source_fragment;
uint8_t* buffer = rtp_packet->AllocatePayload(
- kH265FuHeaderSize + kH265PayloadHeaderSize + fragment.size());
+ kH265FuHeaderSizeBytes + kH265PayloadHeaderSizeBytes + fragment.size());
RTC_CHECK(buffer);
buffer[0] = payload_hdr_h;
buffer[1] = payload_hdr_l;
buffer[2] = fu_header;
// Do not support DONL for fragmentation units, DONL field is not present.
- memcpy(buffer + kH265FuHeaderSize + kH265PayloadHeaderSize, fragment.data(),
- fragment.size());
+ memcpy(buffer + kH265FuHeaderSizeBytes + kH265PayloadHeaderSizeBytes,
+ fragment.data(), fragment.size());
if (packet->last_fragment) {
input_fragments_.pop_front();
}
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265_unittest.cc
index cb1de334c0..8f739e8618 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265_unittest.cc
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_packetizer_h265_unittest.cc
@@ -15,6 +15,7 @@
#include "common_video/h265/h265_common.h"
#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_packet_h265_common.h"
#include "test/gmock.h"
#include "test/gtest.h"
@@ -29,18 +30,12 @@ using ::testing::IsEmpty;
using ::testing::SizeIs;
constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
-constexpr size_t kMaxPayloadSize = 1200;
-constexpr size_t kLengthFieldLength = 2;
+constexpr size_t kMaxPayloadSizeBytes = 1200;
+constexpr size_t kH265LengthFieldSizeBytes = 2;
constexpr RtpPacketizer::PayloadSizeLimits kNoLimits;
-constexpr size_t kNalHeaderSize = 2;
-constexpr size_t kFuHeaderSize = 3;
-
-constexpr uint8_t kNaluTypeMask = 0x7E;
-
-// Bit masks for FU headers.
-constexpr uint8_t kH265SBit = 0x80;
-constexpr uint8_t kH265EBit = 0x40;
+constexpr size_t kFuHeaderSizeBytes =
+ kH265FuHeaderSizeBytes + kH265PayloadHeaderSizeBytes;
// Creates Buffer that looks like nal unit of given size.
rtc::Buffer GenerateNalUnit(size_t size) {
@@ -127,8 +122,8 @@ TEST(RtpPacketizerH265Test, SingleNalu) {
TEST(RtpPacketizerH265Test, SingleNaluTwoPackets) {
RtpPacketizer::PayloadSizeLimits limits;
- limits.max_payload_len = kMaxPayloadSize;
- rtc::Buffer nalus[] = {GenerateNalUnit(kMaxPayloadSize),
+ limits.max_payload_len = kMaxPayloadSizeBytes;
+ rtc::Buffer nalus[] = {GenerateNalUnit(kMaxPayloadSizeBytes),
GenerateNalUnit(100)};
rtc::Buffer frame = CreateFrame(nalus);
@@ -205,27 +200,28 @@ TEST(RtpPacketizerH265Test, ApRespectsNoPacketReduction) {
ASSERT_THAT(packets, SizeIs(1));
auto payload = packets[0].payload();
int type = H265::ParseNaluType(payload[0]);
- EXPECT_EQ(payload.size(),
- kNalHeaderSize + 3 * kLengthFieldLength + 2 + 2 + 0x123);
+ EXPECT_EQ(payload.size(), kH265NalHeaderSizeBytes +
+ 3 * kH265LengthFieldSizeBytes + 2 + 2 + 0x123);
EXPECT_EQ(type, H265::NaluType::kAp);
- payload = payload.subview(kNalHeaderSize);
+ payload = payload.subview(kH265NalHeaderSizeBytes);
// 1st fragment.
- EXPECT_THAT(payload.subview(0, kLengthFieldLength),
+ EXPECT_THAT(payload.subview(0, kH265LengthFieldSizeBytes),
ElementsAre(0, 2)); // Size.
- EXPECT_THAT(payload.subview(kLengthFieldLength, 2),
+ EXPECT_THAT(payload.subview(kH265LengthFieldSizeBytes, 2),
ElementsAreArray(nalus[0]));
- payload = payload.subview(kLengthFieldLength + 2);
+ payload = payload.subview(kH265LengthFieldSizeBytes + 2);
// 2nd fragment.
- EXPECT_THAT(payload.subview(0, kLengthFieldLength),
+ EXPECT_THAT(payload.subview(0, kH265LengthFieldSizeBytes),
ElementsAre(0, 2)); // Size.
- EXPECT_THAT(payload.subview(kLengthFieldLength, 2),
+ EXPECT_THAT(payload.subview(kH265LengthFieldSizeBytes, 2),
ElementsAreArray(nalus[1]));
- payload = payload.subview(kLengthFieldLength + 2);
+ payload = payload.subview(kH265LengthFieldSizeBytes + 2);
// 3rd fragment.
- EXPECT_THAT(payload.subview(0, kLengthFieldLength),
+ EXPECT_THAT(payload.subview(0, kH265LengthFieldSizeBytes),
ElementsAre(0x1, 0x23)); // Size.
- EXPECT_THAT(payload.subview(kLengthFieldLength), ElementsAreArray(nalus[2]));
+ EXPECT_THAT(payload.subview(kH265LengthFieldSizeBytes),
+ ElementsAreArray(nalus[2]));
}
TEST(RtpPacketizerH265Test, ApRespectsFirstPacketReduction) {
@@ -284,7 +280,7 @@ TEST(RtpPacketizerH265Test, TooSmallForApHeaders) {
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 1000;
const size_t kLastFragmentSize =
- limits.max_payload_len - 3 * kLengthFieldLength - 4;
+ limits.max_payload_len - 3 * kH265LengthFieldSizeBytes - 4;
rtc::Buffer nalus[] = {GenerateNalUnit(/*size=*/2),
GenerateNalUnit(/*size=*/2),
GenerateNalUnit(/*size=*/kLastFragmentSize)};
@@ -326,7 +322,8 @@ TEST(RtpPacketizerH265Test, LastFragmentFitsInSingleButNotLastPacket) {
// Returns sizes of the payloads excluding FU headers.
std::vector<int> TestFu(size_t frame_payload_size,
const RtpPacketizer::PayloadSizeLimits& limits) {
- rtc::Buffer nalu[] = {GenerateNalUnit(kNalHeaderSize + frame_payload_size)};
+ rtc::Buffer nalu[] = {
+ GenerateNalUnit(kH265NalHeaderSizeBytes + frame_payload_size)};
rtc::Buffer frame = CreateFrame(nalu);
RtpPacketizerH265 packetizer(frame, limits);
@@ -338,18 +335,18 @@ std::vector<int> TestFu(size_t frame_payload_size,
for (const RtpPacketToSend& packet : packets) {
auto payload = packet.payload();
- EXPECT_GT(payload.size(), kFuHeaderSize);
+ EXPECT_GT(payload.size(), kFuHeaderSizeBytes);
// FU header is after the 2-bytes size PayloadHdr according to 4.4.3 in spec
fu_header.push_back(payload[2]);
- payload_sizes.push_back(payload.size() - kFuHeaderSize);
+ payload_sizes.push_back(payload.size() - kFuHeaderSizeBytes);
}
- EXPECT_TRUE(fu_header.front() & kH265SBit);
- EXPECT_TRUE(fu_header.back() & kH265EBit);
+ EXPECT_TRUE(fu_header.front() & kH265SBitMask);
+ EXPECT_TRUE(fu_header.back() & kH265EBitMask);
// Clear S and E bits before testing all are duplicating same original header.
- fu_header.front() &= ~kH265SBit;
- fu_header.back() &= ~kH265EBit;
- uint8_t nalu_type = (nalu[0][0] & kNaluTypeMask) >> 1;
+ fu_header.front() &= ~kH265SBitMask;
+ fu_header.back() &= ~kH265EBitMask;
+ uint8_t nalu_type = (nalu[0][0] & kH265TypeMask) >> 1;
EXPECT_THAT(fu_header, Each(Eq(nalu_type)));
return payload_sizes;
@@ -403,7 +400,7 @@ TEST(RtpPacketizerH265Test, FuBig) {
limits.max_payload_len = 1200;
// Generate 10 full sized packets, leave room for FU headers.
EXPECT_THAT(
- TestFu(10 * (1200 - kFuHeaderSize), limits),
+ TestFu(10 * (1200 - kFuHeaderSizeBytes), limits),
ElementsAre(1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197));
}
@@ -449,30 +446,30 @@ TEST_P(RtpPacketizerH265ParametrizedTest, MixedApFu) {
if (expected_packet.aggregated) {
int type = H265::ParseNaluType(packets[i].payload()[0]);
EXPECT_THAT(type, H265::NaluType::kAp);
- auto payload = packets[i].payload().subview(kNalHeaderSize);
+ auto payload = packets[i].payload().subview(kH265NalHeaderSizeBytes);
int offset = 0;
// Generated AP packet header and payload align
for (int j = expected_packet.nalu_index; j < expected_packet.nalu_number;
j++) {
- EXPECT_THAT(payload.subview(0, kLengthFieldLength),
+ EXPECT_THAT(payload.subview(0, kH265LengthFieldSizeBytes),
ElementsAre(0, nalus[j].size()));
- EXPECT_THAT(
- payload.subview(offset + kLengthFieldLength, nalus[j].size()),
- ElementsAreArray(nalus[j]));
- offset += kLengthFieldLength + nalus[j].size();
+ EXPECT_THAT(payload.subview(offset + kH265LengthFieldSizeBytes,
+ nalus[j].size()),
+ ElementsAreArray(nalus[j]));
+ offset += kH265LengthFieldSizeBytes + nalus[j].size();
}
} else {
uint8_t fu_header = 0;
- fu_header |= (expected_packet.first_fragment ? kH265SBit : 0);
- fu_header |= (expected_packet.last_fragment ? kH265EBit : 0);
+ fu_header |= (expected_packet.first_fragment ? kH265SBitMask : 0);
+ fu_header |= (expected_packet.last_fragment ? kH265EBitMask : 0);
fu_header |= H265::NaluType::kTrailR;
- EXPECT_THAT(packets[i].payload().subview(0, kFuHeaderSize),
+ EXPECT_THAT(packets[i].payload().subview(0, kFuHeaderSizeBytes),
ElementsAre(98, 2, fu_header));
- EXPECT_THAT(
- packets[i].payload().subview(kFuHeaderSize),
- ElementsAreArray(nalus[expected_packet.nalu_index].data() +
- kNalHeaderSize + expected_packet.start_offset,
- expected_packet.payload_size));
+ EXPECT_THAT(packets[i].payload().subview(kFuHeaderSizeBytes),
+ ElementsAreArray(nalus[expected_packet.nalu_index].data() +
+ kH265NalHeaderSizeBytes +
+ expected_packet.start_offset,
+ expected_packet.payload_size));
}
}
}
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate_unittest.cc
index 6790fc3a71..586836a90e 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate_unittest.cc
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate_unittest.cc
@@ -12,11 +12,11 @@
#include <utility>
+#include "api/test/mock_frame_transformer.h"
#include "api/test/mock_transformable_video_frame.h"
#include "rtc_base/event.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
#include "test/time_controller/simulated_time_controller.h"
namespace webrtc {
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
index 9641d617d9..112a2979fd 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
@@ -21,6 +21,7 @@
#include "api/task_queue/task_queue_base.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/test/mock_frame_encryptor.h"
+#include "api/test/mock_frame_transformer.h"
#include "api/transport/rtp/dependency_descriptor.h"
#include "api/units/timestamp.h"
#include "api/video/video_codec_constants.h"
@@ -46,7 +47,6 @@
#include "test/explicit_key_value_config.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
#include "test/time_controller/simulated_time_controller.h"
namespace webrtc {
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc
index cf3062610f..192e239535 100644
--- a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc
@@ -17,6 +17,7 @@
#include "absl/memory/memory.h"
#include "api/call/transport.h"
+#include "api/test/mock_frame_transformer.h"
#include "api/test/mock_transformable_video_frame.h"
#include "api/units/timestamp.h"
#include "call/video_receive_stream.h"
@@ -24,7 +25,6 @@
#include "rtc_base/event.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
namespace webrtc {
namespace {
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc
new file mode 100644
index 0000000000..b54df7c271
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "absl/base/macros.h"
+#include "absl/types/optional.h"
+#include "absl/types/variant.h"
+#include "api/video/video_codec_type.h"
+#include "common_video/h264/h264_common.h"
+#include "common_video/h265/h265_bitstream_parser.h"
+#include "common_video/h265/h265_common.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_packet_h265_common.h"
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace {
+
+bool ParseApStartOffsets(const uint8_t* nalu_ptr,
+ size_t length_remaining,
+ std::vector<size_t>* offsets) {
+ size_t offset = 0;
+ while (length_remaining > 0) {
+ // Buffer doesn't contain room for additional NALU length.
+ if (length_remaining < kH265LengthFieldSizeBytes)
+ return false;
+ // Read 16-bit NALU size defined in RFC7798 section 4.4.2.
+ uint16_t nalu_size = ByteReader<uint16_t>::ReadBigEndian(nalu_ptr);
+ nalu_ptr += kH265LengthFieldSizeBytes;
+ length_remaining -= kH265LengthFieldSizeBytes;
+ if (nalu_size > length_remaining)
+ return false;
+ nalu_ptr += nalu_size;
+ length_remaining -= nalu_size;
+
+ offsets->push_back(offset + kH265ApHeaderSizeBytes);
+ offset += kH265LengthFieldSizeBytes + nalu_size;
+ }
+ return true;
+}
+
+absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> ProcessApOrSingleNalu(
+ rtc::CopyOnWriteBuffer rtp_payload) {
+ // Skip the single NALU header (payload header), aggregated packet case will
+ // be checked later.
+ if (rtp_payload.size() <= kH265PayloadHeaderSizeBytes) {
+ RTC_LOG(LS_ERROR) << "Single NALU header truncated.";
+ return absl::nullopt;
+ }
+ const uint8_t* const payload_data = rtp_payload.cdata();
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload(
+ absl::in_place);
+ parsed_payload->video_header.width = 0;
+ parsed_payload->video_header.height = 0;
+ parsed_payload->video_header.codec = kVideoCodecH265;
+ parsed_payload->video_header.is_first_packet_in_frame = true;
+
+ const uint8_t* nalu_start = payload_data + kH265PayloadHeaderSizeBytes;
+ const size_t nalu_length = rtp_payload.size() - kH265PayloadHeaderSizeBytes;
+ uint8_t nal_type = (payload_data[0] & kH265TypeMask) >> 1;
+ std::vector<size_t> nalu_start_offsets;
+ rtc::CopyOnWriteBuffer video_payload;
+ if (nal_type == H265::NaluType::kAp) {
+ // Skip the aggregated packet header (Aggregated packet NAL type + length).
+ if (rtp_payload.size() <= kH265ApHeaderSizeBytes) {
+ RTC_LOG(LS_ERROR) << "Aggregated packet header truncated.";
+ return absl::nullopt;
+ }
+
+ if (!ParseApStartOffsets(nalu_start, nalu_length, &nalu_start_offsets)) {
+ RTC_LOG(LS_ERROR)
+ << "Aggregated packet with incorrect NALU packet lengths.";
+ return absl::nullopt;
+ }
+
+ nal_type = (payload_data[kH265ApHeaderSizeBytes] & kH265TypeMask) >> 1;
+ } else {
+ nalu_start_offsets.push_back(0);
+ }
+ parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameDelta;
+
+ nalu_start_offsets.push_back(rtp_payload.size() +
+ kH265LengthFieldSizeBytes); // End offset.
+ for (size_t i = 0; i < nalu_start_offsets.size() - 1; ++i) {
+ size_t start_offset = nalu_start_offsets[i];
+ // End offset is actually start offset for next unit, excluding length field
+ // so remove that from this units length.
+ size_t end_offset = nalu_start_offsets[i + 1] - kH265LengthFieldSizeBytes;
+ if (end_offset - start_offset < kH265NalHeaderSizeBytes) {
+ RTC_LOG(LS_ERROR) << "Aggregated packet too short";
+ return absl::nullopt;
+ }
+
+ // Insert start code before each NALU in aggregated packet.
+ video_payload.AppendData(kStartCode);
+ video_payload.AppendData(&payload_data[start_offset],
+ end_offset - start_offset);
+
+ uint8_t nalu_type = (payload_data[start_offset] & kH265TypeMask) >> 1;
+ start_offset += kH265NalHeaderSizeBytes;
+ switch (nalu_type) {
+ case H265::NaluType::kBlaWLp:
+ case H265::NaluType::kBlaWRadl:
+ case H265::NaluType::kBlaNLp:
+ case H265::NaluType::kIdrWRadl:
+ case H265::NaluType::kIdrNLp:
+ case H265::NaluType::kCra:
+ case H265::NaluType::kRsvIrapVcl23:
+ parsed_payload->video_header.frame_type =
+ VideoFrameType::kVideoFrameKey;
+ ABSL_FALLTHROUGH_INTENDED;
+ case H265::NaluType::kSps: {
+ // Copy any previous data first (likely just the first header).
+ std::unique_ptr<rtc::Buffer> output_buffer(new rtc::Buffer());
+ if (start_offset)
+ output_buffer->AppendData(payload_data, start_offset);
+
+ absl::optional<H265SpsParser::SpsState> sps = H265SpsParser::ParseSps(
+ &payload_data[start_offset], end_offset - start_offset);
+
+ if (sps) {
+ // TODO(bugs.webrtc.org/13485): Implement the size calculation taking
+ // VPS->vui_parameters.def_disp_win_xx_offset into account.
+ parsed_payload->video_header.width = sps->width;
+ parsed_payload->video_header.height = sps->height;
+ } else {
+ RTC_LOG(LS_WARNING) << "Failed to parse SPS from SPS slice.";
+ }
+ }
+ ABSL_FALLTHROUGH_INTENDED;
+ case H265::NaluType::kVps:
+ case H265::NaluType::kPps:
+ case H265::NaluType::kTrailN:
+ case H265::NaluType::kTrailR:
+ // Slices below don't contain SPS or PPS ids.
+ case H265::NaluType::kAud:
+ case H265::NaluType::kTsaN:
+ case H265::NaluType::kTsaR:
+ case H265::NaluType::kStsaN:
+ case H265::NaluType::kStsaR:
+ case H265::NaluType::kRadlN:
+ case H265::NaluType::kRadlR:
+ case H265::NaluType::kPrefixSei:
+ case H265::NaluType::kSuffixSei:
+ break;
+ case H265::NaluType::kAp:
+ case H265::NaluType::kFu:
+ case H265::NaluType::kPaci:
+ RTC_LOG(LS_WARNING) << "Unexpected AP, FU or PACI received.";
+ return absl::nullopt;
+ }
+ }
+ parsed_payload->video_payload = video_payload;
+ return parsed_payload;
+}
+
+absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> ParseFuNalu(
+ rtc::CopyOnWriteBuffer rtp_payload) {
+ if (rtp_payload.size() < kH265FuHeaderSizeBytes + kH265NalHeaderSizeBytes) {
+ RTC_LOG(LS_ERROR) << "FU NAL units truncated.";
+ return absl::nullopt;
+ }
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload(
+ absl::in_place);
+
+ uint8_t f = rtp_payload.cdata()[0] & kH265FBit;
+ uint8_t layer_id_h = rtp_payload.cdata()[0] & kH265LayerIDHMask;
+ uint8_t layer_id_l_unshifted = rtp_payload.cdata()[1] & kH265LayerIDLMask;
+ uint8_t tid = rtp_payload.cdata()[1] & kH265TIDMask;
+
+ uint8_t original_nal_type = rtp_payload.cdata()[2] & kH265TypeMaskInFuHeader;
+ bool first_fragment = rtp_payload.cdata()[2] & kH265SBitMask;
+ if (first_fragment) {
+ rtp_payload = rtp_payload.Slice(
+ kH265FuHeaderSizeBytes, rtp_payload.size() - kH265FuHeaderSizeBytes);
+ rtp_payload.MutableData()[0] = f | original_nal_type << 1 | layer_id_h;
+ rtp_payload.MutableData()[1] = layer_id_l_unshifted | tid;
+ rtc::CopyOnWriteBuffer video_payload;
+ // Insert start code before the first fragment in FU.
+ video_payload.AppendData(kStartCode);
+ video_payload.AppendData(rtp_payload);
+ parsed_payload->video_payload = video_payload;
+ } else {
+ parsed_payload->video_payload = rtp_payload.Slice(
+ kH265NalHeaderSizeBytes + kH265FuHeaderSizeBytes,
+ rtp_payload.size() - kH265NalHeaderSizeBytes - kH265FuHeaderSizeBytes);
+ }
+
+ if (original_nal_type == H265::NaluType::kIdrWRadl ||
+ original_nal_type == H265::NaluType::kIdrNLp ||
+ original_nal_type == H265::NaluType::kCra) {
+ parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameKey;
+ } else {
+ parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameDelta;
+ }
+ parsed_payload->video_header.width = 0;
+ parsed_payload->video_header.height = 0;
+ parsed_payload->video_header.codec = kVideoCodecH265;
+ parsed_payload->video_header.is_first_packet_in_frame = first_fragment;
+
+ return parsed_payload;
+}
+
+} // namespace
+
+absl::optional<VideoRtpDepacketizer::ParsedRtpPayload>
+VideoRtpDepacketizerH265::Parse(rtc::CopyOnWriteBuffer rtp_payload) {
+ if (rtp_payload.empty()) {
+ RTC_LOG(LS_ERROR) << "Empty payload.";
+ return absl::nullopt;
+ }
+
+ uint8_t nal_type = (rtp_payload.cdata()[0] & kH265TypeMask) >> 1;
+
+ if (nal_type == H265::NaluType::kFu) {
+ // Fragmented NAL units (FU).
+ return ParseFuNalu(std::move(rtp_payload));
+ } else if (nal_type == H265::NaluType::kPaci) {
+ // TODO(bugs.webrtc.org/13485): Implement PACI parse for H265
+ RTC_LOG(LS_ERROR) << "Not support type:" << nal_type;
+ return absl::nullopt;
+ } else {
+ // Single NAL unit packet or Aggregated packets (AP).
+ return ProcessApOrSingleNalu(std::move(rtp_payload));
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h
new file mode 100644
index 0000000000..ed5290d1cb
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_H265_H_
+#define MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_H265_H_
+
+#include "absl/types/optional.h"
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
+#include "rtc_base/copy_on_write_buffer.h"
+
+namespace webrtc {
+class VideoRtpDepacketizerH265 : public VideoRtpDepacketizer {
+ public:
+ ~VideoRtpDepacketizerH265() override = default;
+
+ absl::optional<ParsedRtpPayload> Parse(
+ rtc::CopyOnWriteBuffer rtp_payload) override;
+};
+} // namespace webrtc
+
+#endif // MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_H265_H_
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265_unittest.cc
new file mode 100644
index 0000000000..a630671a71
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_h265_unittest.cc
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h"
+
+#include <cstdint>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "common_video/h265/h265_common.h"
+#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_packet_h265_common.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::Each;
+using ::testing::ElementsAre;
+using ::testing::ElementsAreArray;
+using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::SizeIs;
+
+TEST(VideoRtpDepacketizerH265Test, SingleNalu) {
+ uint8_t packet[3] = {0x26, 0x02,
+ 0xFF}; // F=0, Type=19 (Idr), LayerId=0, TID=2.
+ uint8_t expected_packet[] = {0x00, 0x00, 0x00, 0x01, 0x26, 0x02, 0xff};
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+
+ VideoRtpDepacketizerH265 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_TRUE(parsed);
+
+ EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
+ parsed->video_payload.size()),
+ ElementsAreArray(expected_packet));
+ EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+ EXPECT_EQ(parsed->video_header.codec, kVideoCodecH265);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+}
+
+TEST(VideoRtpDepacketizerH265Test, SingleNaluSpsWithResolution) {
+ // SPS for a 1280x720 camera capture from ffmpeg on linux. Contains
+ // emulation bytes but no cropping. This buffer is generated
+ // with following command:
+ // 1) ffmpeg -i /dev/video0 -r 30 -c:v libx265 -s 1280x720 camera.h265
+ //
+ // 2) Open camera.h265 and find the SPS, generally everything between the
+ // second and third start codes (0 0 0 1 or 0 0 1). The first two bytes
+ // 0x42 and 0x02 shows the nal header of SPS.
+ uint8_t packet[] = {0x42, 0x02, 0x01, 0x04, 0x08, 0x00, 0x00, 0x03,
+ 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x5d, 0xb0, 0x02, 0x80, 0x80, 0x2d, 0x16, 0x59,
+ 0x59, 0xa4, 0x93, 0x2b, 0x80, 0x40, 0x00, 0x00,
+ 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82};
+ uint8_t expected_packet[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x42, 0x02, 0x01, 0x04, 0x08, 0x00, 0x00,
+ 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x5d, 0xb0,
+ 0x02, 0x80, 0x80, 0x2d, 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0x80,
+ 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82};
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+
+ VideoRtpDepacketizerH265 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_TRUE(parsed);
+
+ EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
+ parsed->video_payload.size()),
+ ElementsAreArray(expected_packet));
+ EXPECT_EQ(parsed->video_header.codec, kVideoCodecH265);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+ EXPECT_EQ(parsed->video_header.width, 1280u);
+ EXPECT_EQ(parsed->video_header.height, 720u);
+}
+
+TEST(VideoRtpDepacketizerH265Test, PaciPackets) {
+ uint8_t packet[2] = {0x64, 0x02}; // F=0, Type=50 (PACI), LayerId=0, TID=2.
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+
+ VideoRtpDepacketizerH265 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_FALSE(parsed);
+}
+
+TEST(VideoRtpDepacketizerH265Test, ApKey) {
+ uint8_t payload_header[] = {0x60, 0x02};
+ uint8_t vps_nalu_size[] = {0, 0x17};
+ uint8_t sps_nalu_size[] = {0, 0x27};
+ uint8_t pps_nalu_size[] = {0, 0x32};
+ uint8_t slice_nalu_size[] = {0, 0xa};
+ uint8_t start_code[] = {0x00, 0x00, 0x00, 0x01};
+ // VPS/SPS/PPS/IDR for a 1280x720 camera capture from ffmpeg on linux.
+ // Contains emulation bytes but no cropping. This buffer is generated with
+ // following command: 1) ffmpeg -i /dev/video0 -r 30 -c:v libx265 -s 1280x720
+ // camera.h265
+ //
+ // 2) Open camera.h265 and find:
+ // VPS - generally everything between the first and second start codes (0 0 0
+ // 1 or 0 0 1). The first two bytes 0x40 and 0x02 shows the nal header of VPS.
+ // SPS - generally everything between the
+ // second and third start codes (0 0 0 1 or 0 0 1). The first two bytes
+ // 0x42 and 0x02 shows the nal header of SPS.
+ // PPS - generally everything between the third and fourth start codes (0 0 0
+ // 1 or 0 0 1). The first two bytes 0x44 and 0x02 shows the nal header of PPS.
+ // IDR - Part of the keyframe bitstream (no need to show all the bytes for
+ // depacketizer testing). The first two bytes 0x26 and 0x02 shows the nal
+ // header of IDR frame.
+ uint8_t vps[] = {
+ 0x40, 0x02, 0x1c, 0x01, 0xff, 0xff, 0x04, 0x08, 0x00, 0x00, 0x03, 0x00,
+ 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 0x95, 0x98, 0x09,
+ };
+ uint8_t sps[] = {0x42, 0x02, 0x01, 0x04, 0x08, 0x00, 0x00, 0x03, 0x00, 0x9d,
+ 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x5d, 0xb0, 0x02, 0x80,
+ 0x80, 0x2d, 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0x80, 0x40,
+ 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82};
+ uint8_t pps[] = {0x44, 0x02, 0xa4, 0x04, 0x55, 0xa2, 0x6d, 0xce, 0xc0, 0xc3,
+ 0xed, 0x0b, 0xac, 0xbc, 0x00, 0xc4, 0x44, 0x2e, 0xf7, 0x55,
+ 0xfd, 0x05, 0x86, 0x92, 0x19, 0xdf, 0x58, 0xec, 0x38, 0x36,
+ 0xb7, 0x7c, 0x00, 0x15, 0x33, 0x78, 0x03, 0x67, 0x26, 0x0f,
+ 0x7b, 0x30, 0x1c, 0xd7, 0xd4, 0x3a, 0xec, 0xad, 0xef, 0x73};
+ uint8_t idr[] = {0x26, 0x02, 0xaf, 0x08, 0x4a, 0x31, 0x11, 0x15, 0xe5, 0xc0};
+
+ rtc::Buffer packet;
+ packet.AppendData(payload_header);
+ packet.AppendData(vps_nalu_size);
+ packet.AppendData(vps);
+ packet.AppendData(sps_nalu_size);
+ packet.AppendData(sps);
+ packet.AppendData(pps_nalu_size);
+ packet.AppendData(pps);
+ packet.AppendData(slice_nalu_size);
+ packet.AppendData(idr);
+
+ rtc::Buffer expected_packet;
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(vps);
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(sps);
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(pps);
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(idr);
+
+ // clang-format on
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+
+ VideoRtpDepacketizerH265 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_TRUE(parsed);
+
+ EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
+ parsed->video_payload.size()),
+ ElementsAreArray(expected_packet));
+ EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+ EXPECT_EQ(parsed->video_header.codec, kVideoCodecH265);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+}
+
+TEST(VideoRtpDepacketizerH265Test, ApNaluSpsWithResolution) {
+ uint8_t payload_header[] = {0x60, 0x02};
+ uint8_t vps_nalu_size[] = {0, 0x17};
+ uint8_t sps_nalu_size[] = {0, 0x27};
+ uint8_t pps_nalu_size[] = {0, 0x32};
+ uint8_t slice_nalu_size[] = {0, 0xa};
+ uint8_t start_code[] = {0x00, 0x00, 0x00, 0x01};
+ // The VPS/SPS/PPS/IDR bytes are generated using the same way as above case.
+ uint8_t vps[] = {
+ 0x40, 0x02, 0x1c, 0x01, 0xff, 0xff, 0x04, 0x08, 0x00, 0x00, 0x03, 0x00,
+ 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 0x95, 0x98, 0x09,
+ };
+ uint8_t sps[] = {0x42, 0x02, 0x01, 0x04, 0x08, 0x00, 0x00, 0x03, 0x00, 0x9d,
+ 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x5d, 0xb0, 0x02, 0x80,
+ 0x80, 0x2d, 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0x80, 0x40,
+ 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82};
+ uint8_t pps[] = {0x44, 0x02, 0xa4, 0x04, 0x55, 0xa2, 0x6d, 0xce, 0xc0, 0xc3,
+ 0xed, 0x0b, 0xac, 0xbc, 0x00, 0xc4, 0x44, 0x2e, 0xf7, 0x55,
+ 0xfd, 0x05, 0x86, 0x92, 0x19, 0xdf, 0x58, 0xec, 0x38, 0x36,
+ 0xb7, 0x7c, 0x00, 0x15, 0x33, 0x78, 0x03, 0x67, 0x26, 0x0f,
+ 0x7b, 0x30, 0x1c, 0xd7, 0xd4, 0x3a, 0xec, 0xad, 0xef, 0x73};
+ uint8_t idr[] = {0x26, 0x02, 0xaf, 0x08, 0x4a, 0x31, 0x11, 0x15, 0xe5, 0xc0};
+
+ rtc::Buffer packet;
+ packet.AppendData(payload_header);
+ packet.AppendData(vps_nalu_size);
+ packet.AppendData(vps);
+ packet.AppendData(sps_nalu_size);
+ packet.AppendData(sps);
+ packet.AppendData(pps_nalu_size);
+ packet.AppendData(pps);
+ packet.AppendData(slice_nalu_size);
+ packet.AppendData(idr);
+
+ rtc::Buffer expected_packet;
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(vps);
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(sps);
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(pps);
+ expected_packet.AppendData(start_code);
+ expected_packet.AppendData(idr);
+
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+
+ VideoRtpDepacketizerH265 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_TRUE(parsed);
+
+ EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
+ parsed->video_payload.size()),
+ ElementsAreArray(expected_packet));
+ EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+ EXPECT_EQ(parsed->video_header.codec, kVideoCodecH265);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+ EXPECT_EQ(parsed->video_header.width, 1280u);
+ EXPECT_EQ(parsed->video_header.height, 720u);
+}
+
+TEST(VideoRtpDepacketizerH265Test, EmptyApRejected) {
+ uint8_t lone_empty_packet[] = {0x60, 0x02, // F=0, Type=48 (kH265Ap).
+ 0x00, 0x00};
+ uint8_t leading_empty_packet[] = {0x60, 0x02, // F=0, Type=48 (kH265Ap).
+ 0x00, 0x00, 0x00, 0x05, 0x26,
+ 0x02, 0xFF, 0x00, 0x11}; // kIdrWRadl
+ uint8_t middle_empty_packet[] = {0x60, 0x02, // F=0, Type=48 (kH265Ap).
+ 0x00, 0x04, 0x26, 0x02, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x26, 0x02, 0xFF, 0x00, 0x11}; // kIdrWRadl
+ uint8_t trailing_empty_packet[] = {0x60, 0x02, // F=0, Type=48 (kH265Ap).
+ 0x00, 0x04, 0x26,
+ 0x02, 0xFF, 0x00, // kIdrWRadl
+ 0x00, 0x00};
+
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(lone_empty_packet)));
+ EXPECT_FALSE(
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(leading_empty_packet)));
+ EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(middle_empty_packet)));
+ EXPECT_FALSE(
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(trailing_empty_packet)));
+}
+
+TEST(VideoRtpDepacketizerH265Test, ApDelta) {
+ uint8_t packet[20] = {0x60, 0x02, // F=0, Type=48 (kH265Ap).
+ // Length, nal header, payload.
+ 0, 0x03, 0x02, 0x02, 0xFF, // TrailR
+ 0, 0x04, 0x02, 0x02, 0xFF, 0x00, // TrailR
+ 0, 0x05, 0x02, 0x02, 0xFF, 0x00, 0x11}; // TrailR
+ uint8_t expected_packet[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0xFF, // TrailR
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0xFF, 0x00, // TrailR
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0xFF, 0x00, 0x11}; // TrailR
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+
+ VideoRtpDepacketizerH265 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_TRUE(parsed);
+
+ EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
+ parsed->video_payload.size()),
+ ElementsAreArray(expected_packet));
+
+ EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameDelta);
+ EXPECT_EQ(parsed->video_header.codec, kVideoCodecH265);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+}
+
+TEST(VideoRtpDepacketizerH265Test, Fu) {
+ // clang-format off
+ uint8_t packet1[] = {
+ 0x62, 0x02, // F=0, Type=49 (kH265Fu).
+ 0x93, // FU header kH265SBitMask | H265::kIdrWRadl.
+ 0xaf, 0x08, 0x4a, 0x31, 0x11, 0x15, 0xe5, 0xc0 // Payload.
+ };
+ // clang-format on
+ // F=0, Type=19, (kIdrWRadl), tid=1, nalu header: 00100110 00000010, which is
+ // 0x26, 0x02
+ const uint8_t kExpected1[] = {0x00, 0x00, 0x00, 0x01, 0x26, 0x02, 0xaf,
+ 0x08, 0x4a, 0x31, 0x11, 0x15, 0xe5, 0xc0};
+
+ uint8_t packet2[] = {
+ 0x62, 0x02, // F=0, Type=49 (kH265Fu).
+ H265::kIdrWRadl, // FU header.
+ 0x02 // Payload.
+ };
+ const uint8_t kExpected2[] = {0x02};
+
+ uint8_t packet3[] = {
+ 0x62, 0x02, // F=0, Type=49 (kH265Fu).
+ 0x33, // FU header kH265EBitMask | H265::kIdrWRadl.
+ 0x03 // Payload.
+ };
+ const uint8_t kExpected3[] = {0x03};
+
+ VideoRtpDepacketizerH265 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed1 =
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(packet1));
+ ASSERT_TRUE(parsed1);
+ // We expect that the first packet is one byte shorter since the FU header
+ // has been replaced by the original nal header.
+ EXPECT_THAT(rtc::MakeArrayView(parsed1->video_payload.cdata(),
+ parsed1->video_payload.size()),
+ ElementsAreArray(kExpected1));
+ EXPECT_EQ(parsed1->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+ EXPECT_EQ(parsed1->video_header.codec, kVideoCodecH265);
+ EXPECT_TRUE(parsed1->video_header.is_first_packet_in_frame);
+
+ // Following packets will be 2 bytes shorter since they will only be appended
+ // onto the first packet.
+ auto parsed2 = depacketizer.Parse(rtc::CopyOnWriteBuffer(packet2));
+ EXPECT_THAT(rtc::MakeArrayView(parsed2->video_payload.cdata(),
+ parsed2->video_payload.size()),
+ ElementsAreArray(kExpected2));
+ EXPECT_FALSE(parsed2->video_header.is_first_packet_in_frame);
+ EXPECT_EQ(parsed2->video_header.codec, kVideoCodecH265);
+
+ auto parsed3 = depacketizer.Parse(rtc::CopyOnWriteBuffer(packet3));
+ EXPECT_THAT(rtc::MakeArrayView(parsed3->video_payload.cdata(),
+ parsed3->video_payload.size()),
+ ElementsAreArray(kExpected3));
+ EXPECT_FALSE(parsed3->video_header.is_first_packet_in_frame);
+ EXPECT_EQ(parsed3->video_header.codec, kVideoCodecH265);
+}
+
+TEST(VideoRtpDepacketizerH265Test, EmptyPayload) {
+ rtc::CopyOnWriteBuffer empty;
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_FALSE(depacketizer.Parse(empty));
+}
+
+TEST(VideoRtpDepacketizerH265Test, TruncatedFuNalu) {
+ const uint8_t kPayload[] = {0x62};
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
+}
+
+TEST(VideoRtpDepacketizerH265Test, TruncatedSingleApNalu) {
+ const uint8_t kPayload[] = {0xe0, 0x02, 0x40};
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
+}
+
+TEST(VideoRtpDepacketizerH265Test, ApPacketWithTruncatedNalUnits) {
+ const uint8_t kPayload[] = {0x60, 0x02, 0xED, 0xDF};
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
+}
+
+TEST(VideoRtpDepacketizerH265Test, TruncationJustAfterSingleApNalu) {
+ const uint8_t kPayload[] = {0x60, 0x02, 0x40, 0x40};
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
+}
+
+TEST(VideoRtpDepacketizerH265Test, ShortSpsPacket) {
+ const uint8_t kPayload[] = {0x40, 0x80, 0x00};
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_TRUE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
+}
+
+TEST(VideoRtpDepacketizerH265Test, InvalidNaluSizeApNalu) {
+ const uint8_t kPayload[] = {0x60, 0x02, // F=0, Type=48 (kH265Ap).
+ // Length, nal header, payload.
+ 0, 0xff, 0x02, 0x02, 0xFF, // TrailR
+ 0, 0x05, 0x02, 0x02, 0xFF, 0x00,
+ 0x11}; // TrailR;
+ VideoRtpDepacketizerH265 depacketizer;
+ EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
+}
+
+TEST(VideoRtpDepacketizerH265Test, SeiPacket) {
+ const uint8_t kPayload[] = {
+ 0x4e, 0x02, // F=0, Type=39 (kPrefixSei).
+ 0x03, 0x03, 0x03, 0x03 // Payload.
+ };
+ VideoRtpDepacketizerH265 depacketizer;
+ auto parsed = depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload));
+ ASSERT_TRUE(parsed);
+}
+
+} // namespace
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc b/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc
index 08d23f7f58..b6e7e79a2a 100644
--- a/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc
+++ b/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc
@@ -62,6 +62,7 @@ VideoCaptureModuleV4L2::VideoCaptureModuleV4L2()
_deviceId(-1),
_deviceFd(-1),
_buffersAllocatedByDevice(-1),
+ _streaming(false),
_captureStarted(false),
_pool(NULL) {}
@@ -110,6 +111,7 @@ int32_t VideoCaptureModuleV4L2::Init(const char* deviceUniqueIdUTF8) {
VideoCaptureModuleV4L2::~VideoCaptureModuleV4L2() {
RTC_DCHECK_RUN_ON(&api_checker_);
+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
StopCapture();
if (_deviceFd != -1)
@@ -128,6 +130,14 @@ int32_t VideoCaptureModuleV4L2::StartCapture(
}
}
+ {
+ // We don't want members above to be guarded by capture_checker_ as
+ // it's meant to be for members that are accessed on the API thread
+ // only when we are not capturing. The code above can be called many
+ // times while sharing instance of VideoCaptureV4L2 between websites
+ // and therefore it would not follow the requirements of this checker.
+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
+
// Set a baseline of configured parameters. It is updated here during
// configuration, then read from the capture thread.
configured_capability_ = capability;
@@ -289,18 +299,23 @@ int32_t VideoCaptureModuleV4L2::StartCapture(
_requestedCapability = capability;
_captureStarted = true;
+ _streaming = true;
// start capture thread;
- if (_captureThread.empty()) {
- quit_ = false;
- _captureThread = rtc::PlatformThread::SpawnJoinable(
- [self = scoped_refptr(this)] {
- while (self->CaptureProcess()) {
- }
- },
- "CaptureThread",
- rtc::ThreadAttributes().SetPriority(rtc::ThreadPriority::kHigh));
+ if (!_captureThread.empty()) {
+ return 0;
+ }
+
+ quit_ = false;
}
+
+ _captureThread = rtc::PlatformThread::SpawnJoinable(
+ [self = scoped_refptr(this)] {
+ while (self->CaptureProcess()) {
+ }
+ },
+ "CaptureThread",
+ rtc::ThreadAttributes().SetPriority(rtc::ThreadPriority::kHigh));
return 0;
}
@@ -316,9 +331,12 @@ int32_t VideoCaptureModuleV4L2::StopCapture() {
_captureThread.Finalize();
}
+ _captureStarted = false;
+
+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
MutexLock lock(&capture_lock_);
- if (_captureStarted) {
- _captureStarted = false;
+ if (_streaming) {
+ _streaming = false;
DeAllocateVideoBuffers();
close(_deviceFd);
@@ -333,6 +351,7 @@ int32_t VideoCaptureModuleV4L2::StopCapture() {
// critical section protected by the caller
bool VideoCaptureModuleV4L2::AllocateVideoBuffers() {
+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
struct v4l2_requestbuffers rbuffer;
memset(&rbuffer, 0, sizeof(v4l2_requestbuffers));
@@ -383,6 +402,7 @@ bool VideoCaptureModuleV4L2::AllocateVideoBuffers() {
}
bool VideoCaptureModuleV4L2::DeAllocateVideoBuffers() {
+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
// unmap buffers
for (int i = 0; i < _buffersAllocatedByDevice; i++)
munmap(_pool[i].start, _pool[i].length);
@@ -400,10 +420,12 @@ bool VideoCaptureModuleV4L2::DeAllocateVideoBuffers() {
}
bool VideoCaptureModuleV4L2::CaptureStarted() {
+ RTC_DCHECK_RUN_ON(&api_checker_);
return _captureStarted;
}
bool VideoCaptureModuleV4L2::CaptureProcess() {
+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
int retVal = 0;
struct pollfd rSet;
@@ -432,7 +454,7 @@ bool VideoCaptureModuleV4L2::CaptureProcess() {
return true;
}
- if (_captureStarted) {
+ if (_streaming) {
struct v4l2_buffer buf;
memset(&buf, 0, sizeof(struct v4l2_buffer));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
diff --git a/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.h b/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.h
index 61358d0325..9bc4ce8402 100644
--- a/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.h
+++ b/third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.h
@@ -45,11 +45,13 @@ class VideoCaptureModuleV4L2 : public VideoCaptureImpl {
Mutex capture_lock_ RTC_ACQUIRED_BEFORE(api_lock_);
bool quit_ RTC_GUARDED_BY(capture_lock_);
int32_t _deviceId RTC_GUARDED_BY(api_checker_);
- int32_t _deviceFd;
+ int32_t _deviceFd RTC_GUARDED_BY(capture_checker_);
int32_t _buffersAllocatedByDevice RTC_GUARDED_BY(capture_lock_);
- VideoCaptureCapability configured_capability_;
- bool _captureStarted;
+ VideoCaptureCapability configured_capability_
+ RTC_GUARDED_BY(capture_checker_);
+ bool _streaming RTC_GUARDED_BY(capture_checker_);
+ bool _captureStarted RTC_GUARDED_BY(api_checker_);
struct Buffer {
void* start;
size_t length;
diff --git a/third_party/libwebrtc/modules/video_coding/BUILD.gn b/third_party/libwebrtc/modules/video_coding/BUILD.gn
index 0457b818c3..db5b57dff4 100644
--- a/third_party/libwebrtc/modules/video_coding/BUILD.gn
+++ b/third_party/libwebrtc/modules/video_coding/BUILD.gn
@@ -124,10 +124,10 @@ rtc_library("packet_buffer") {
]
}
-rtc_library("h264_packet_buffer") {
+rtc_library("h26x_packet_buffer") {
sources = [
- "h264_packet_buffer.cc",
- "h264_packet_buffer.h",
+ "h26x_packet_buffer.cc",
+ "h26x_packet_buffer.h",
]
deps = [
":codec_globals_headers",
@@ -287,6 +287,8 @@ rtc_library("video_codec_interface") {
"include/video_codec_interface.h",
"include/video_coding_defines.h",
"include/video_error_codes.h",
+ "include/video_error_codes_utils.cc",
+ "include/video_error_codes_utils.h",
"video_coding_defines.cc",
]
deps = [
@@ -527,6 +529,7 @@ rtc_library("webrtc_multiplex") {
":video_coding_utility",
"../../api:fec_controller_api",
"../../api:scoped_refptr",
+ "../../api/environment",
"../../api/video:encoded_image",
"../../api/video:video_frame",
"../../api/video:video_rtp_headers",
@@ -583,7 +586,10 @@ rtc_library("webrtc_vp8") {
":webrtc_vp8_scalability",
":webrtc_vp8_temporal_layers",
"../../api:fec_controller_api",
+ "../../api:field_trials_view",
"../../api:scoped_refptr",
+ "../../api/environment",
+ "../../api/transport:field_trial_based_config",
"../../api/units:time_delta",
"../../api/units:timestamp",
"../../api/video:encoded_image",
@@ -820,6 +826,8 @@ if (rtc_include_tests) {
"../../api:mock_video_decoder",
"../../api:mock_video_encoder",
"../../api:simulcast_test_fixture_api",
+ "../../api/environment",
+ "../../api/environment:environment_factory",
"../../api/video:encoded_image",
"../../api/video:video_frame",
"../../api/video:video_rtp_headers",
@@ -932,6 +940,8 @@ if (rtc_include_tests) {
":webrtc_vp9_helpers",
"../../api:array_view",
"../../api:videocodec_test_fixture_api",
+ "../../api/environment",
+ "../../api/environment:environment_factory",
"../../api/test/metrics:global_metrics_logger_and_exporter",
"../../api/test/metrics:metric",
"../../api/test/video:function_video_factory",
@@ -999,6 +1009,8 @@ if (rtc_include_tests) {
deps = [
":video_codec_interface",
+ "../../api/environment",
+ "../../api/environment:environment_factory",
"../../api/test/metrics:global_metrics_logger_and_exporter",
"../../api/units:data_rate",
"../../api/units:frequency",
@@ -1008,6 +1020,8 @@ if (rtc_include_tests) {
"../../modules/video_coding/svc:scalability_mode_util",
"../../rtc_base:logging",
"../../rtc_base:stringutils",
+ "../../test:explicit_key_value_config",
+ "../../test:field_trial",
"../../test:fileutils",
"../../test:test_flags",
"../../test:test_main",
@@ -1077,6 +1091,8 @@ if (rtc_include_tests) {
"../../api:scoped_refptr",
"../../api:videocodec_test_fixture_api",
"../../api:videocodec_test_stats_api",
+ "../../api/environment",
+ "../../api/environment:environment_factory",
"../../api/test/metrics:global_metrics_logger_and_exporter",
"../../api/test/video:function_video_factory",
"../../api/video:encoded_image",
@@ -1152,9 +1168,9 @@ if (rtc_include_tests) {
"frame_dependencies_calculator_unittest.cc",
"frame_helpers_unittest.cc",
"generic_decoder_unittest.cc",
- "h264_packet_buffer_unittest.cc",
"h264_sprop_parameter_sets_unittest.cc",
"h264_sps_pps_tracker_unittest.cc",
+ "h26x_packet_buffer_unittest.cc",
"histogram_unittest.cc",
"loss_notification_controller_unittest.cc",
"nack_requester_unittest.cc",
@@ -1189,7 +1205,7 @@ if (rtc_include_tests) {
":encoded_frame",
":frame_dependencies_calculator",
":frame_helpers",
- ":h264_packet_buffer",
+ ":h26x_packet_buffer",
":nack_requester",
":packet_buffer",
":simulcast_test_fixture_impl",
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
index 4ff22bfe34..03bb367fe0 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
@@ -133,6 +133,7 @@ class LibaomAv1Encoder final : public VideoEncoder {
// TODO(webrtc:15225): Kill switch for disabling frame dropping. Remove it
// after frame dropping is fully rolled out.
bool disable_frame_dropping_;
+ int max_consec_frame_drop_;
};
int32_t VerifyCodecSettings(const VideoCodec& codec_settings) {
@@ -163,6 +164,14 @@ int32_t VerifyCodecSettings(const VideoCodec& codec_settings) {
return WEBRTC_VIDEO_CODEC_OK;
}
+int GetMaxConsecutiveFrameDrop(const FieldTrialsView& field_trials) {
+ webrtc::FieldTrialParameter<int> maxdrop("maxdrop", 0);
+ webrtc::ParseFieldTrial(
+ {&maxdrop},
+ field_trials.Lookup("WebRTC-LibaomAv1Encoder-MaxConsecFrameDrop"));
+ return maxdrop;
+}
+
LibaomAv1Encoder::LibaomAv1Encoder(
const absl::optional<LibaomAv1EncoderAuxConfig>& aux_config,
const FieldTrialsView& trials)
@@ -174,7 +183,8 @@ LibaomAv1Encoder::LibaomAv1Encoder(
timestamp_(0),
disable_frame_dropping_(absl::StartsWith(
trials.Lookup("WebRTC-LibaomAv1Encoder-DisableFrameDropping"),
- "Enabled")) {}
+ "Enabled")),
+ max_consec_frame_drop_(GetMaxConsecutiveFrameDrop(trials)) {}
LibaomAv1Encoder::~LibaomAv1Encoder() {
Release();
@@ -297,6 +307,12 @@ int LibaomAv1Encoder::InitEncode(const VideoCodec* codec_settings,
SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_PALETTE, 0);
}
+ if (codec_settings->mode == VideoCodecMode::kRealtimeVideo &&
+ encoder_settings_.GetFrameDropEnabled() && max_consec_frame_drop_ > 0) {
+ SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_MAX_CONSEC_FRAME_DROP_CBR,
+ max_consec_frame_drop_);
+ }
+
if (cfg_.g_threads == 8) {
// Values passed to AV1E_SET_TILE_ROWS and AV1E_SET_TILE_COLUMNS are log2()
// based.
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
index 04ee9162ba..127aadb275 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
@@ -188,6 +188,31 @@ TEST(LibaomAv1EncoderTest, CheckOddDimensionsWithSpatialLayers) {
ASSERT_THAT(encoded_frames, SizeIs(6));
}
+TEST(LibaomAv1EncoderTest, WithMaximumConsecutiveFrameDrop) {
+ test::ScopedFieldTrials field_trials(
+ "WebRTC-LibaomAv1Encoder-MaxConsecFrameDrop/maxdrop:2/");
+ VideoBitrateAllocation allocation;
+ allocation.SetBitrate(0, 0, 1000); // some very low bitrate
+ std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
+ VideoCodec codec_settings = DefaultCodecSettings();
+ codec_settings.SetFrameDropEnabled(true);
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1);
+ codec_settings.startBitrate = allocation.get_sum_kbps();
+ ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
+ WEBRTC_VIDEO_CODEC_OK);
+ encoder->SetRates(VideoEncoder::RateControlParameters(
+ allocation, codec_settings.maxFramerate));
+ EncodedVideoFrameProducer evfp(*encoder);
+ evfp.SetResolution(
+ RenderResolution{codec_settings.width, codec_settings.height});
+ // We should code the first frame, skip two, then code another frame.
+ std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
+ evfp.SetNumInputFrames(4).Encode();
+ ASSERT_THAT(encoded_frames, SizeIs(2));
+ // The 4 frames have default Rtp-timestamps of 1000, 4000, 7000, 10000.
+ ASSERT_THAT(encoded_frames[1].encoded_image.RtpTimestamp(), 10000);
+}
+
TEST(LibaomAv1EncoderTest, EncoderInfoWithoutResolutionBitrateLimits) {
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
EXPECT_TRUE(encoder->GetEncoderInfo().resolution_bitrate_limits.empty());
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
index d486c1d062..6a135e2bab 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
@@ -62,6 +62,7 @@ VideoCodec DefaultCodecSettings() {
codec_settings.height = kHeight;
codec_settings.maxFramerate = kFramerate;
codec_settings.maxBitrate = 1000;
+ codec_settings.startBitrate = 1;
codec_settings.qpMax = 63;
return codec_settings;
}
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h b/third_party/libwebrtc/modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h
index d58981e4b2..ed02f2d72b 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h
+++ b/third_party/libwebrtc/modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h
@@ -15,6 +15,7 @@
#include <memory>
#include <vector>
+#include "api/environment/environment.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_decoder_factory.h"
@@ -25,7 +26,8 @@ namespace webrtc {
class MultiplexDecoderAdapter : public VideoDecoder {
public:
// `factory` is not owned and expected to outlive this class.
- MultiplexDecoderAdapter(VideoDecoderFactory* factory,
+ MultiplexDecoderAdapter(const Environment& env,
+ VideoDecoderFactory* factory,
const SdpVideoFormat& associated_format,
bool supports_augmenting_data = false);
virtual ~MultiplexDecoderAdapter();
@@ -62,6 +64,7 @@ class MultiplexDecoderAdapter : public VideoDecoder {
std::unique_ptr<uint8_t[]> augmenting_data,
uint16_t augmenting_data_length);
+ const Environment env_;
VideoDecoderFactory* const factory_;
const SdpVideoFormat associated_format_;
std::vector<std::unique_ptr<VideoDecoder>> decoders_;
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/multiplex/multiplex_decoder_adapter.cc b/third_party/libwebrtc/modules/video_coding/codecs/multiplex/multiplex_decoder_adapter.cc
index 551a9490b0..7cebbe14d0 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/multiplex/multiplex_decoder_adapter.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/multiplex/multiplex_decoder_adapter.cc
@@ -10,6 +10,7 @@
#include "modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h"
+#include "api/environment/environment.h"
#include "api/video/encoded_image.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_frame_buffer.h"
@@ -93,10 +94,12 @@ struct MultiplexDecoderAdapter::AugmentingData {
};
MultiplexDecoderAdapter::MultiplexDecoderAdapter(
+ const Environment& env,
VideoDecoderFactory* factory,
const SdpVideoFormat& associated_format,
bool supports_augmenting_data)
- : factory_(factory),
+ : env_(env),
+ factory_(factory),
associated_format_(associated_format),
supports_augmenting_data_(supports_augmenting_data) {}
@@ -111,7 +114,7 @@ bool MultiplexDecoderAdapter::Configure(const Settings& settings) {
PayloadStringToCodecType(associated_format_.name));
for (size_t i = 0; i < kAlphaCodecStreams; ++i) {
std::unique_ptr<VideoDecoder> decoder =
- factory_->CreateVideoDecoder(associated_format_);
+ factory_->Create(env_, associated_format_);
if (!decoder->Configure(associated_settings)) {
return false;
}
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/multiplex/test/multiplex_adapter_unittest.cc b/third_party/libwebrtc/modules/video_coding/codecs/multiplex/test/multiplex_adapter_unittest.cc
index a2f36a306d..9c6300e368 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/multiplex/test/multiplex_adapter_unittest.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/multiplex/test/multiplex_adapter_unittest.cc
@@ -16,6 +16,8 @@
#include <vector>
#include "absl/types/optional.h"
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/scoped_refptr.h"
#include "api/test/mock_video_decoder_factory.h"
#include "api/test/mock_video_encoder_factory.h"
@@ -63,7 +65,8 @@ class TestMultiplexAdapter : public VideoCodecUnitTest,
protected:
std::unique_ptr<VideoDecoder> CreateDecoder() override {
return std::make_unique<MultiplexDecoderAdapter>(
- decoder_factory_.get(), SdpVideoFormat(kMultiplexAssociatedCodecName),
+ env_, decoder_factory_.get(),
+ SdpVideoFormat(kMultiplexAssociatedCodecName),
supports_augmenting_data_);
}
@@ -182,9 +185,9 @@ class TestMultiplexAdapter : public VideoCodecUnitTest,
EXPECT_CALL(*decoder_factory_, Die);
// The decoders/encoders will be owned by the caller of
// CreateVideoDecoder()/CreateVideoEncoder().
- EXPECT_CALL(*decoder_factory_, CreateVideoDecoder)
- .Times(2)
- .WillRepeatedly([] { return VP9Decoder::Create(); });
+ EXPECT_CALL(*decoder_factory_, Create).Times(2).WillRepeatedly([] {
+ return VP9Decoder::Create();
+ });
EXPECT_CALL(*encoder_factory_, Die);
EXPECT_CALL(*encoder_factory_, CreateVideoEncoder)
@@ -194,6 +197,7 @@ class TestMultiplexAdapter : public VideoCodecUnitTest,
VideoCodecUnitTest::SetUp();
}
+ const Environment env_ = CreateEnvironment();
const std::unique_ptr<webrtc::MockVideoDecoderFactory> decoder_factory_;
const std::unique_ptr<webrtc::MockVideoEncoderFactory> encoder_factory_;
const bool supports_augmenting_data_;
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc b/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc
index 2ab1106a59..0811685e33 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc
@@ -14,6 +14,8 @@
#include "absl/flags/flag.h"
#include "absl/functional/any_invocable.h"
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/test/metrics/global_metrics_logger_and_exporter.h"
#include "api/units/data_rate.h"
#include "api/units/frequency.h"
@@ -26,6 +28,8 @@
#include "modules/video_coding/svc/scalability_mode_util.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
+#include "test/explicit_key_value_config.h"
+#include "test/field_trial.h"
#include "test/gtest.h"
#include "test/test_flags.h"
#include "test/testsupport/file_utils.h"
@@ -58,6 +62,7 @@ ABSL_FLAG(double,
30.0,
"Encode target frame rate of the top temporal layer in fps.");
ABSL_FLAG(int, num_frames, 300, "Number of frames to encode and/or decode.");
+ABSL_FLAG(std::string, field_trials, "", "Field trials to apply.");
ABSL_FLAG(std::string, test_name, "", "Test name.");
ABSL_FLAG(bool, dump_decoder_input, false, "Dump decoder input.");
ABSL_FLAG(bool, dump_decoder_output, false, "Dump decoder output.");
@@ -178,6 +183,7 @@ std::string TestOutputPath() {
} // namespace
std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest(
+ const Environment& env,
std::string encoder_impl,
std::string decoder_impl,
const VideoInfo& video_info,
@@ -247,7 +253,7 @@ std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest(
}
return VideoCodecTester::RunEncodeDecodeTest(
- source_settings, encoder_factory.get(), decoder_factory.get(),
+ env, source_settings, encoder_factory.get(), decoder_factory.get(),
encoder_settings, decoder_settings, encoding_settings);
}
@@ -313,6 +319,7 @@ class SpatialQualityTest : public ::testing::TestWithParam<std::tuple<
};
TEST_P(SpatialQualityTest, SpatialQuality) {
+ const Environment env = CreateEnvironment();
auto [codec_type, codec_impl, video_info, coding_settings] = GetParam();
auto [width, height, framerate_fps, bitrate_kbps, expected_min_psnr] =
coding_settings;
@@ -324,8 +331,8 @@ TEST_P(SpatialQualityTest, SpatialQuality) {
codec_type, /*scalability_mode=*/"L1T1", width, height,
{bitrate_kbps}, framerate_fps, num_frames);
- std::unique_ptr<VideoCodecStats> stats =
- RunEncodeDecodeTest(codec_impl, codec_impl, video_info, frames_settings);
+ std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest(
+ env, codec_impl, codec_impl, video_info, frames_settings);
VideoCodecStats::Stream stream;
if (stats != nullptr) {
@@ -527,6 +534,11 @@ INSTANTIATE_TEST_SUITE_P(
FramerateAdaptationTest::TestParamsToString);
TEST(VideoCodecTest, DISABLED_EncodeDecode) {
+ ScopedFieldTrials field_trials(absl::GetFlag(FLAGS_field_trials));
+ const Environment env =
+ CreateEnvironment(std::make_unique<ExplicitKeyValueConfig>(
+ absl::GetFlag(FLAGS_field_trials)));
+
std::vector<std::string> bitrate_str = absl::GetFlag(FLAGS_bitrate_kbps);
std::vector<int> bitrate_kbps;
std::transform(bitrate_str.begin(), bitrate_str.end(),
@@ -544,7 +556,7 @@ TEST(VideoCodecTest, DISABLED_EncodeDecode) {
// logged test name (implies lossing history in the chromeperf dashboard).
// Sync with changes in Stream::LogMetrics (see TODOs there).
std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest(
- CodecNameToCodecImpl(absl::GetFlag(FLAGS_encoder)),
+ env, CodecNameToCodecImpl(absl::GetFlag(FLAGS_encoder)),
CodecNameToCodecImpl(absl::GetFlag(FLAGS_decoder)),
kRawVideos.at(absl::GetFlag(FLAGS_video_name)), frames_settings);
ASSERT_NE(nullptr, stats);
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc b/third_party/libwebrtc/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc
index 41f2304748..581750768d 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc
@@ -11,6 +11,8 @@
#include <memory>
#include <vector>
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_decoder_factory.h"
@@ -86,6 +88,8 @@ class VideoEncoderDecoderInstantiationTest
}
}
+ const Environment env_ = CreateEnvironment();
+
const SdpVideoFormat vp8_format_;
const SdpVideoFormat vp9_format_;
const SdpVideoFormat h264cbp_format_;
@@ -126,7 +130,7 @@ TEST_P(VideoEncoderDecoderInstantiationTest, DISABLED_InstantiateVp8Codecs) {
for (int i = 0; i < num_decoders_; ++i) {
std::unique_ptr<VideoDecoder> decoder =
- decoder_factory_->CreateVideoDecoder(vp8_format_);
+ decoder_factory_->Create(env_, vp8_format_);
ASSERT_THAT(decoder, NotNull());
EXPECT_TRUE(decoder->Configure(DecoderSettings(kVideoCodecVP8)));
decoders_.emplace_back(std::move(decoder));
@@ -144,7 +148,7 @@ TEST_P(VideoEncoderDecoderInstantiationTest,
for (int i = 0; i < num_decoders_; ++i) {
std::unique_ptr<VideoDecoder> decoder =
- decoder_factory_->CreateVideoDecoder(h264cbp_format_);
+ decoder_factory_->Create(env_, h264cbp_format_);
ASSERT_THAT(decoder, NotNull());
EXPECT_TRUE(decoder->Configure(DecoderSettings(kVideoCodecH264)));
decoders_.push_back(std::move(decoder));
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc b/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc
index 35355d4387..508ac384b0 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc
@@ -24,6 +24,8 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/test/metrics/global_metrics_logger_and_exporter.h"
#include "api/test/metrics/metric.h"
#include "api/transport/field_trial_based_config.h"
@@ -685,6 +687,8 @@ void VideoCodecTestFixtureImpl::VerifyVideoStatistic(
}
bool VideoCodecTestFixtureImpl::CreateEncoderAndDecoder() {
+ const Environment env = CreateEnvironment();
+
SdpVideoFormat encoder_format(CreateSdpVideoFormat(config_));
SdpVideoFormat decoder_format = encoder_format;
@@ -709,7 +713,7 @@ bool VideoCodecTestFixtureImpl::CreateEncoderAndDecoder() {
config_.NumberOfSimulcastStreams(), config_.NumberOfSpatialLayers());
for (size_t i = 0; i < num_simulcast_or_spatial_layers; ++i) {
std::unique_ptr<VideoDecoder> decoder =
- decoder_factory_->CreateVideoDecoder(decoder_format);
+ decoder_factory_->Create(env, decoder_format);
EXPECT_TRUE(decoder) << "Decoder not successfully created.";
if (decoder == nullptr) {
return false;
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp8/include/vp8.h b/third_party/libwebrtc/modules/video_coding/codecs/vp8/include/vp8.h
index 2fc647874f..45b7cee00a 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp8/include/vp8.h
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp8/include/vp8.h
@@ -14,6 +14,7 @@
#include <memory>
#include <vector>
+#include "api/environment/environment.h"
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/vp8_frame_buffer_controller.h"
#include "modules/video_coding/include/video_codec_interface.h"
@@ -40,11 +41,15 @@ class VP8Encoder {
static std::unique_ptr<VideoEncoder> Create(Settings settings);
};
+// TODO: bugs.webrtc.org/15791 - Deprecate and delete in favor of the
+// CreateVp8Decoder function.
class VP8Decoder {
public:
static std::unique_ptr<VideoDecoder> Create();
};
+std::unique_ptr<VideoDecoder> CreateVp8Decoder(const Environment& env);
+
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_VP8_H_
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc b/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
index 9b77388f10..4c06aca5ad 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
@@ -18,7 +18,10 @@
#include <string>
#include "absl/types/optional.h"
+#include "api/environment/environment.h"
+#include "api/field_trials_view.h"
#include "api/scoped_refptr.h"
+#include "api/transport/field_trial_based_config.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_frame.h"
#include "api/video/video_frame_buffer.h"
@@ -28,7 +31,6 @@
#include "rtc_base/checks.h"
#include "rtc_base/numerics/exp_filter.h"
#include "rtc_base/time_utils.h"
-#include "system_wrappers/include/field_trial.h"
#include "system_wrappers/include/metrics.h"
#include "third_party/libyuv/include/libyuv/convert.h"
#include "vpx/vp8.h"
@@ -59,9 +61,9 @@ absl::optional<LibvpxVp8Decoder::DeblockParams> DefaultDeblockParams() {
}
absl::optional<LibvpxVp8Decoder::DeblockParams>
-GetPostProcParamsFromFieldTrialGroup() {
- std::string group = webrtc::field_trial::FindFullName(
- kIsArm ? kVp8PostProcArmFieldTrial : kVp8PostProcFieldTrial);
+GetPostProcParamsFromFieldTrialGroup(const FieldTrialsView& field_trials) {
+ std::string group = field_trials.Lookup(kIsArm ? kVp8PostProcArmFieldTrial
+ : kVp8PostProcFieldTrial);
if (group.empty()) {
return DefaultDeblockParams();
}
@@ -89,6 +91,10 @@ std::unique_ptr<VideoDecoder> VP8Decoder::Create() {
return std::make_unique<LibvpxVp8Decoder>();
}
+std::unique_ptr<VideoDecoder> CreateVp8Decoder(const Environment& env) {
+ return std::make_unique<LibvpxVp8Decoder>(env);
+}
+
class LibvpxVp8Decoder::QpSmoother {
public:
QpSmoother() : last_sample_ms_(rtc::TimeMillis()), smoother_(kAlpha) {}
@@ -114,9 +120,14 @@ class LibvpxVp8Decoder::QpSmoother {
};
LibvpxVp8Decoder::LibvpxVp8Decoder()
- : use_postproc_(
- kIsArm ? webrtc::field_trial::IsEnabled(kVp8PostProcArmFieldTrial)
- : true),
+ : LibvpxVp8Decoder(FieldTrialBasedConfig()) {}
+
+LibvpxVp8Decoder::LibvpxVp8Decoder(const Environment& env)
+ : LibvpxVp8Decoder(env.field_trials()) {}
+
+LibvpxVp8Decoder::LibvpxVp8Decoder(const FieldTrialsView& field_trials)
+ : use_postproc_(kIsArm ? field_trials.IsEnabled(kVp8PostProcArmFieldTrial)
+ : true),
buffer_pool_(false, 300 /* max_number_of_buffers*/),
decode_complete_callback_(NULL),
inited_(false),
@@ -124,8 +135,9 @@ LibvpxVp8Decoder::LibvpxVp8Decoder()
last_frame_width_(0),
last_frame_height_(0),
key_frame_required_(true),
- deblock_params_(use_postproc_ ? GetPostProcParamsFromFieldTrialGroup()
- : absl::nullopt),
+ deblock_params_(use_postproc_
+ ? GetPostProcParamsFromFieldTrialGroup(field_trials)
+ : absl::nullopt),
qp_smoother_(use_postproc_ ? new QpSmoother() : nullptr) {}
LibvpxVp8Decoder::~LibvpxVp8Decoder() {
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.h b/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.h
index 74f4dc7c89..8ed8e7ca88 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.h
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.h
@@ -14,6 +14,8 @@
#include <memory>
#include "absl/types/optional.h"
+#include "api/environment/environment.h"
+#include "api/field_trials_view.h"
#include "api/video/encoded_image.h"
#include "api/video_codecs/video_decoder.h"
#include "common_video/include/video_frame_buffer_pool.h"
@@ -26,7 +28,10 @@ namespace webrtc {
class LibvpxVp8Decoder : public VideoDecoder {
public:
+ // TODO: bugs.webrtc.org/15791 - Delete default constructor when
+ // Environment is always propagated.
LibvpxVp8Decoder();
+ explicit LibvpxVp8Decoder(const Environment& env);
~LibvpxVp8Decoder() override;
bool Configure(const Settings& settings) override;
@@ -56,6 +61,7 @@ class LibvpxVp8Decoder : public VideoDecoder {
private:
class QpSmoother;
+ explicit LibvpxVp8Decoder(const FieldTrialsView& field_trials);
int ReturnFrame(const vpx_image_t* img,
uint32_t timeStamp,
int qp,
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_simulcast_test.cc b/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_simulcast_test.cc
index 4ca3de20d5..3f13066892 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_simulcast_test.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp8/libvpx_vp8_simulcast_test.cc
@@ -27,7 +27,9 @@ std::unique_ptr<SimulcastTestFixture> CreateSpecificSimulcastTestFixture() {
[]() { return VP8Encoder::Create(); });
std::unique_ptr<VideoDecoderFactory> decoder_factory =
std::make_unique<FunctionVideoDecoderFactory>(
- []() { return VP8Decoder::Create(); });
+ [](const Environment& env, const SdpVideoFormat& format) {
+ return CreateVp8Decoder(env);
+ });
return CreateSimulcastTestFixture(std::move(encoder_factory),
std::move(decoder_factory),
SdpVideoFormat("VP8"));
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc b/third_party/libwebrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
index a6f570f855..514d3d7e1d 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
@@ -13,6 +13,7 @@
#include <algorithm>
#include <memory>
+#include "api/environment/environment_factory.h"
#include "api/test/create_frame_generator.h"
#include "api/test/frame_generator_interface.h"
#include "api/test/mock_video_decoder.h"
@@ -70,7 +71,7 @@ class TestVp8Impl : public VideoCodecUnitTest {
}
std::unique_ptr<VideoDecoder> CreateDecoder() override {
- return VP8Decoder::Create();
+ return CreateVp8Decoder(CreateEnvironment());
}
void ModifyCodecSettings(VideoCodec* codec_settings) override {
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc b/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
index 5330eb7e8c..edbe781639 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
@@ -267,7 +267,8 @@ LibvpxVp9Encoder::LibvpxVp9Encoder(const cricket::VideoCodec& codec,
"Disabled")),
performance_flags_(ParsePerformanceFlagsFromTrials(trials)),
num_steady_state_frames_(0),
- config_changed_(true) {
+ config_changed_(true),
+ svc_frame_drop_config_(ParseSvcFrameDropConfig(trials)) {
codec_ = {};
memset(&svc_params_, 0, sizeof(vpx_svc_extra_cfg_t));
}
@@ -838,6 +839,8 @@ int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
// 1:2 scaling in each dimension.
svc_params_.scaling_factor_num[i] = scaling_factor_num;
svc_params_.scaling_factor_den[i] = 256;
+ if (inst->mode != VideoCodecMode::kScreensharing)
+ scaling_factor_num /= 2;
}
}
@@ -924,11 +927,24 @@ int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
svc_drop_frame_.framedrop_thresh[i] = config_->rc_dropframe_thresh;
}
} else {
- // Configure encoder to drop entire superframe whenever it needs to drop
- // a layer. This mode is preferred over per-layer dropping which causes
- // quality flickering and is not compatible with RTP non-flexible mode.
- svc_drop_frame_.framedrop_mode = FULL_SUPERFRAME_DROP;
- svc_drop_frame_.max_consec_drop = std::numeric_limits<int>::max();
+ if (svc_frame_drop_config_.enabled &&
+ svc_frame_drop_config_.layer_drop_mode == LAYER_DROP &&
+ is_flexible_mode_ && svc_controller_ &&
+ (inter_layer_pred_ == InterLayerPredMode::kOff ||
+ inter_layer_pred_ == InterLayerPredMode::kOnKeyPic)) {
+ // SVC controller is required since it properly accounts for dropped
+ // refs (unlike SetReferences(), which assumes full superframe drop).
+ svc_drop_frame_.framedrop_mode = LAYER_DROP;
+ } else {
+ // Configure encoder to drop entire superframe whenever it needs to drop
+ // a layer. This mode is preferred over per-layer dropping which causes
+ // quality flickering and is not compatible with RTP non-flexible mode.
+ svc_drop_frame_.framedrop_mode = FULL_SUPERFRAME_DROP;
+ }
+ svc_drop_frame_.max_consec_drop =
+ svc_frame_drop_config_.enabled
+ ? svc_frame_drop_config_.max_consec_drop
+ : std::numeric_limits<int>::max();
for (size_t i = 0; i < num_spatial_layers_; ++i) {
svc_drop_frame_.framedrop_thresh[i] = config_->rc_dropframe_thresh;
}
@@ -1960,6 +1976,26 @@ LibvpxVp9Encoder::ParseQualityScalerConfig(const FieldTrialsView& trials) {
return config;
}
+LibvpxVp9Encoder::SvcFrameDropConfig LibvpxVp9Encoder::ParseSvcFrameDropConfig(
+ const FieldTrialsView& trials) {
+ FieldTrialFlag enabled = FieldTrialFlag("Enabled");
+ FieldTrialParameter<int> layer_drop_mode("layer_drop_mode",
+ FULL_SUPERFRAME_DROP);
+ FieldTrialParameter<int> max_consec_drop("max_consec_drop",
+ std::numeric_limits<int>::max());
+ ParseFieldTrial({&enabled, &layer_drop_mode, &max_consec_drop},
+ trials.Lookup("WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig"));
+ SvcFrameDropConfig config;
+ config.enabled = enabled.Get();
+ config.layer_drop_mode = layer_drop_mode.Get();
+ config.max_consec_drop = max_consec_drop.Get();
+ RTC_LOG(LS_INFO) << "Libvpx VP9 encoder SVC frame drop config: "
+ << (config.enabled ? "enabled" : "disabled")
+ << " layer_drop_mode " << config.layer_drop_mode
+ << " max_consec_drop " << config.max_consec_drop;
+ return config;
+}
+
void LibvpxVp9Encoder::UpdatePerformanceFlags() {
flat_map<int, PerformanceFlags::ParameterSet> params_by_resolution;
if (codec_.GetVideoEncoderComplexity() ==
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h b/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
index 1953923f81..ea4e5810ac 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
@@ -240,6 +240,14 @@ class LibvpxVp9Encoder : public VP9Encoder {
bool config_changed_;
const LibvpxVp9EncoderInfoSettings encoder_info_override_;
+
+ const struct SvcFrameDropConfig {
+ bool enabled;
+ int layer_drop_mode; // SVC_LAYER_DROP_MODE
+ int max_consec_drop;
+ } svc_frame_drop_config_;
+ static SvcFrameDropConfig ParseSvcFrameDropConfig(
+ const FieldTrialsView& trials);
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config.cc b/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config.cc
index 7af8cab3cb..555af835a5 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config.cc
@@ -190,6 +190,9 @@ std::vector<SpatialLayer> GetVp9SvcConfig(VideoCodec& codec) {
codec.SetScalabilityMode(limited_scalability_mode);
}
+ codec.VP9()->interLayerPred =
+ ScalabilityModeToInterLayerPredMode(*scalability_mode);
+
absl::optional<ScalableVideoController::StreamLayersConfig> info =
ScalabilityStructureConfig(*scalability_mode);
if (!info.has_value()) {
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config_unittest.cc b/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config_unittest.cc
index 1b1abe0f6d..2515b1ce4b 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config_unittest.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp9/svc_config_unittest.cc
@@ -13,6 +13,7 @@
#include <cstddef>
#include <vector>
+#include "api/video_codecs/video_encoder.h"
#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
#include "test/gmock.h"
#include "test/gtest.h"
@@ -65,6 +66,25 @@ TEST(SvcConfig, NumSpatialLayersWithScalabilityMode) {
EXPECT_EQ(codec.GetScalabilityMode(), ScalabilityMode::kL3T3_KEY);
}
+TEST(SvcConfig, UpdatesInterLayerPredModeBasedOnScalabilityMode) {
+ VideoCodec codec;
+ codec.codecType = kVideoCodecVP9;
+ codec.width = 1280;
+ codec.height = 720;
+ codec.SetScalabilityMode(ScalabilityMode::kL3T3_KEY);
+
+ std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
+ EXPECT_EQ(codec.VP9()->interLayerPred, InterLayerPredMode::kOnKeyPic);
+
+ codec.SetScalabilityMode(ScalabilityMode::kL3T3);
+ spatial_layers = GetVp9SvcConfig(codec);
+ EXPECT_EQ(codec.VP9()->interLayerPred, InterLayerPredMode::kOn);
+
+ codec.SetScalabilityMode(ScalabilityMode::kS3T3);
+ spatial_layers = GetVp9SvcConfig(codec);
+ EXPECT_EQ(codec.VP9()->interLayerPred, InterLayerPredMode::kOff);
+}
+
TEST(SvcConfig, NumSpatialLayersLimitedWithScalabilityMode) {
VideoCodec codec;
codec.codecType = kVideoCodecVP9;
diff --git a/third_party/libwebrtc/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc b/third_party/libwebrtc/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
index 993fd245ad..50e9cf2369 100644
--- a/third_party/libwebrtc/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
+++ b/third_party/libwebrtc/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
@@ -2459,4 +2459,113 @@ TEST(Vp9SpeedSettingsTrialsTest, DefaultPerLayerFlagsWithSvc) {
}
}
+struct SvcFrameDropConfigTestParameters {
+ bool flexible_mode;
+ absl::optional<ScalabilityMode> scalability_mode;
+ std::string field_trial;
+ int expected_framedrop_mode;
+ int expected_max_consec_drop;
+};
+
+class TestVp9ImplSvcFrameDropConfig
+ : public ::testing::TestWithParam<SvcFrameDropConfigTestParameters> {};
+
+TEST_P(TestVp9ImplSvcFrameDropConfig, SvcFrameDropConfig) {
+ SvcFrameDropConfigTestParameters test_params = GetParam();
+ auto* const vpx = new NiceMock<MockLibvpxInterface>();
+ LibvpxVp9Encoder encoder(
+ cricket::CreateVideoCodec(cricket::kVp9CodecName),
+ absl::WrapUnique<LibvpxInterface>(vpx),
+ test::ExplicitKeyValueConfig(test_params.field_trial));
+
+ vpx_image_t img;
+ ON_CALL(*vpx, img_wrap).WillByDefault(GetWrapImageFunction(&img));
+
+ EXPECT_CALL(*vpx,
+ codec_control(_, VP9E_SET_SVC_FRAME_DROP_LAYER,
+ SafeMatcherCast<vpx_svc_frame_drop_t*>(AllOf(
+ Field(&vpx_svc_frame_drop_t::framedrop_mode,
+ test_params.expected_framedrop_mode),
+ Field(&vpx_svc_frame_drop_t::max_consec_drop,
+ test_params.expected_max_consec_drop)))));
+
+ VideoCodec settings = DefaultCodecSettings();
+ settings.VP9()->flexibleMode = test_params.flexible_mode;
+ if (test_params.scalability_mode.has_value()) {
+ settings.SetScalabilityMode(*test_params.scalability_mode);
+ }
+ settings.VP9()->numberOfSpatialLayers =
+ 3; // to execute SVC code paths even when scalability_mode is not set.
+
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder.InitEncode(&settings, kSettings));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ TestVp9ImplSvcFrameDropConfig,
+ ::testing::Values(
+ // Flexible mode is disabled. Layer drop is not allowed. Ignore
+ // layer_drop_mode from field trial.
+ SvcFrameDropConfigTestParameters{
+ .flexible_mode = false,
+ .scalability_mode = ScalabilityMode::kL3T3_KEY,
+ .field_trial = "WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig/"
+ "Enabled,layer_drop_mode:1,max_consec_drop:7/",
+ .expected_framedrop_mode = FULL_SUPERFRAME_DROP,
+ .expected_max_consec_drop = 7},
+ // Flexible mode is enabled but the field trial is not set. Use default
+ // settings.
+ SvcFrameDropConfigTestParameters{
+ .flexible_mode = true,
+ .scalability_mode = ScalabilityMode::kL3T3_KEY,
+ .field_trial = "",
+ .expected_framedrop_mode = FULL_SUPERFRAME_DROP,
+ .expected_max_consec_drop = std::numeric_limits<int>::max()},
+ // Flexible mode is enabled but the field trial is disabled. Use default
+ // settings.
+ SvcFrameDropConfigTestParameters{
+ .flexible_mode = true,
+ .scalability_mode = ScalabilityMode::kL3T3_KEY,
+ .field_trial = "WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig/"
+ "Disabled,layer_drop_mode:1,max_consec_drop:7/",
+ .expected_framedrop_mode = FULL_SUPERFRAME_DROP,
+ .expected_max_consec_drop = std::numeric_limits<int>::max()},
+ // Flexible mode is enabled, layer drop is enabled, KSVC. Apply config
+ // from field trial.
+ SvcFrameDropConfigTestParameters{
+ .flexible_mode = true,
+ .scalability_mode = ScalabilityMode::kL3T3_KEY,
+ .field_trial = "WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig/"
+ "Enabled,layer_drop_mode:1,max_consec_drop:7/",
+ .expected_framedrop_mode = LAYER_DROP,
+ .expected_max_consec_drop = 7},
+ // Flexible mode is enabled, layer drop is enabled, simulcast. Apply
+ // config from field trial.
+ SvcFrameDropConfigTestParameters{
+ .flexible_mode = true,
+ .scalability_mode = ScalabilityMode::kS3T3,
+ .field_trial = "WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig/"
+ "Enabled,layer_drop_mode:1,max_consec_drop:7/",
+ .expected_framedrop_mode = LAYER_DROP,
+ .expected_max_consec_drop = 7},
+ // Flexible mode is enabled, layer drop is enabled, full SVC. Apply
+ // config from field trial.
+ SvcFrameDropConfigTestParameters{
+ .flexible_mode = false,
+ .scalability_mode = ScalabilityMode::kL3T3,
+ .field_trial = "WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig/"
+ "Enabled,layer_drop_mode:1,max_consec_drop:7/",
+ .expected_framedrop_mode = FULL_SUPERFRAME_DROP,
+ .expected_max_consec_drop = 7},
+ // Flexible mode is enabled, layer-drop is enabled, scalability mode is
+ // not set (i.e., SVC controller is not enabled). Ignore layer_drop_mode
+ // from field trial.
+ SvcFrameDropConfigTestParameters{
+ .flexible_mode = true,
+ .scalability_mode = absl::nullopt,
+ .field_trial = "WebRTC-LibvpxVp9Encoder-SvcFrameDropConfig/"
+ "Enabled,layer_drop_mode:1,max_consec_drop:7/",
+ .expected_framedrop_mode = FULL_SUPERFRAME_DROP,
+ .expected_max_consec_drop = 7}));
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/h264_packet_buffer.cc b/third_party/libwebrtc/modules/video_coding/h264_packet_buffer.cc
deleted file mode 100644
index 6096665bda..0000000000
--- a/third_party/libwebrtc/modules/video_coding/h264_packet_buffer.cc
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/video_coding/h264_packet_buffer.h"
-
-#include <algorithm>
-#include <cstdint>
-#include <utility>
-#include <vector>
-
-#include "api/array_view.h"
-#include "api/rtp_packet_info.h"
-#include "api/video/video_frame_type.h"
-#include "common_video/h264/h264_common.h"
-#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
-#include "modules/rtp_rtcp/source/rtp_packet_received.h"
-#include "modules/rtp_rtcp/source/rtp_video_header.h"
-#include "modules/video_coding/codecs/h264/include/h264_globals.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/copy_on_write_buffer.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/sequence_number_util.h"
-
-namespace webrtc {
-namespace {
-int64_t EuclideanMod(int64_t n, int64_t div) {
- RTC_DCHECK_GT(div, 0);
- return (n %= div) < 0 ? n + div : n;
-}
-
-rtc::ArrayView<const NaluInfo> GetNaluInfos(
- const RTPVideoHeaderH264& h264_header) {
- if (h264_header.nalus_length > kMaxNalusPerPacket) {
- return {};
- }
-
- return rtc::MakeArrayView(h264_header.nalus, h264_header.nalus_length);
-}
-
-bool IsFirstPacketOfFragment(const RTPVideoHeaderH264& h264_header) {
- return h264_header.nalus_length > 0;
-}
-
-bool BeginningOfIdr(const H264PacketBuffer::Packet& packet) {
- const auto& h264_header =
- absl::get<RTPVideoHeaderH264>(packet.video_header.video_type_header);
- const bool contains_idr_nalu =
- absl::c_any_of(GetNaluInfos(h264_header), [](const auto& nalu_info) {
- return nalu_info.type == H264::NaluType::kIdr;
- });
- switch (h264_header.packetization_type) {
- case kH264StapA:
- case kH264SingleNalu: {
- return contains_idr_nalu;
- }
- case kH264FuA: {
- return contains_idr_nalu && IsFirstPacketOfFragment(h264_header);
- }
- }
-}
-
-bool HasSps(const H264PacketBuffer::Packet& packet) {
- auto& h264_header =
- absl::get<RTPVideoHeaderH264>(packet.video_header.video_type_header);
- return absl::c_any_of(GetNaluInfos(h264_header), [](const auto& nalu_info) {
- return nalu_info.type == H264::NaluType::kSps;
- });
-}
-
-// TODO(bugs.webrtc.org/13157): Update the H264 depacketizer so we don't have to
-// fiddle with the payload at this point.
-rtc::CopyOnWriteBuffer FixVideoPayload(rtc::ArrayView<const uint8_t> payload,
- const RTPVideoHeader& video_header) {
- constexpr uint8_t kStartCode[] = {0, 0, 0, 1};
-
- const auto& h264_header =
- absl::get<RTPVideoHeaderH264>(video_header.video_type_header);
-
- rtc::CopyOnWriteBuffer result;
- switch (h264_header.packetization_type) {
- case kH264StapA: {
- const uint8_t* payload_end = payload.data() + payload.size();
- const uint8_t* nalu_ptr = payload.data() + 1;
- while (nalu_ptr < payload_end - 1) {
- // The first two bytes describe the length of the segment, where a
- // segment is the nalu type plus nalu payload.
- uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
- nalu_ptr += 2;
-
- if (nalu_ptr + segment_length <= payload_end) {
- result.AppendData(kStartCode);
- result.AppendData(nalu_ptr, segment_length);
- }
- nalu_ptr += segment_length;
- }
- return result;
- }
-
- case kH264FuA: {
- if (IsFirstPacketOfFragment(h264_header)) {
- result.AppendData(kStartCode);
- }
- result.AppendData(payload);
- return result;
- }
-
- case kH264SingleNalu: {
- result.AppendData(kStartCode);
- result.AppendData(payload);
- return result;
- }
- }
-
- RTC_DCHECK_NOTREACHED();
- return result;
-}
-
-} // namespace
-
-H264PacketBuffer::H264PacketBuffer(bool idr_only_keyframes_allowed)
- : idr_only_keyframes_allowed_(idr_only_keyframes_allowed) {}
-
-H264PacketBuffer::InsertResult H264PacketBuffer::InsertPacket(
- std::unique_ptr<Packet> packet) {
- RTC_DCHECK(packet->video_header.codec == kVideoCodecH264);
-
- InsertResult result;
- if (!absl::holds_alternative<RTPVideoHeaderH264>(
- packet->video_header.video_type_header)) {
- return result;
- }
-
- int64_t unwrapped_seq_num = seq_num_unwrapper_.Unwrap(packet->seq_num);
- auto& packet_slot = GetPacket(unwrapped_seq_num);
- if (packet_slot != nullptr &&
- AheadOrAt(packet_slot->timestamp, packet->timestamp)) {
- // The incoming `packet` is old or a duplicate.
- return result;
- } else {
- packet_slot = std::move(packet);
- }
-
- result.packets = FindFrames(unwrapped_seq_num);
- return result;
-}
-
-std::unique_ptr<H264PacketBuffer::Packet>& H264PacketBuffer::GetPacket(
- int64_t unwrapped_seq_num) {
- return buffer_[EuclideanMod(unwrapped_seq_num, kBufferSize)];
-}
-
-bool H264PacketBuffer::BeginningOfStream(
- const H264PacketBuffer::Packet& packet) const {
- return HasSps(packet) ||
- (idr_only_keyframes_allowed_ && BeginningOfIdr(packet));
-}
-
-std::vector<std::unique_ptr<H264PacketBuffer::Packet>>
-H264PacketBuffer::FindFrames(int64_t unwrapped_seq_num) {
- std::vector<std::unique_ptr<Packet>> found_frames;
-
- Packet* packet = GetPacket(unwrapped_seq_num).get();
- RTC_CHECK(packet != nullptr);
-
- // Check if the packet is continuous or the beginning of a new coded video
- // sequence.
- if (unwrapped_seq_num - 1 != last_continuous_unwrapped_seq_num_) {
- if (unwrapped_seq_num <= last_continuous_unwrapped_seq_num_ ||
- !BeginningOfStream(*packet)) {
- return found_frames;
- }
-
- last_continuous_unwrapped_seq_num_ = unwrapped_seq_num;
- }
-
- for (int64_t seq_num = unwrapped_seq_num;
- seq_num < unwrapped_seq_num + kBufferSize;) {
- RTC_DCHECK_GE(seq_num, *last_continuous_unwrapped_seq_num_);
-
- // Packets that were never assembled into a completed frame will stay in
- // the 'buffer_'. Check that the `packet` sequence number match the expected
- // unwrapped sequence number.
- if (static_cast<uint16_t>(seq_num) != packet->seq_num) {
- return found_frames;
- }
-
- last_continuous_unwrapped_seq_num_ = seq_num;
- // Last packet of the frame, try to assemble the frame.
- if (packet->marker_bit) {
- uint32_t rtp_timestamp = packet->timestamp;
-
- // Iterate backwards to find where the frame starts.
- for (int64_t seq_num_start = seq_num;
- seq_num_start > seq_num - kBufferSize; --seq_num_start) {
- auto& prev_packet = GetPacket(seq_num_start - 1);
-
- if (prev_packet == nullptr || prev_packet->timestamp != rtp_timestamp) {
- if (MaybeAssembleFrame(seq_num_start, seq_num, found_frames)) {
- // Frame was assembled, continue to look for more frames.
- break;
- } else {
- // Frame was not assembled, no subsequent frame will be continuous.
- return found_frames;
- }
- }
- }
- }
-
- seq_num++;
- packet = GetPacket(seq_num).get();
- if (packet == nullptr) {
- return found_frames;
- }
- }
-
- return found_frames;
-}
-
-bool H264PacketBuffer::MaybeAssembleFrame(
- int64_t start_seq_num_unwrapped,
- int64_t end_sequence_number_unwrapped,
- std::vector<std::unique_ptr<Packet>>& frames) {
- bool has_sps = false;
- bool has_pps = false;
- bool has_idr = false;
-
- int width = -1;
- int height = -1;
-
- for (int64_t seq_num = start_seq_num_unwrapped;
- seq_num <= end_sequence_number_unwrapped; ++seq_num) {
- const auto& packet = GetPacket(seq_num);
- const auto& h264_header =
- absl::get<RTPVideoHeaderH264>(packet->video_header.video_type_header);
- for (const auto& nalu : GetNaluInfos(h264_header)) {
- has_idr |= nalu.type == H264::NaluType::kIdr;
- has_sps |= nalu.type == H264::NaluType::kSps;
- has_pps |= nalu.type == H264::NaluType::kPps;
- }
-
- width = std::max<int>(packet->video_header.width, width);
- height = std::max<int>(packet->video_header.height, height);
- }
-
- if (has_idr) {
- if (!idr_only_keyframes_allowed_ && (!has_sps || !has_pps)) {
- return false;
- }
- }
-
- for (int64_t seq_num = start_seq_num_unwrapped;
- seq_num <= end_sequence_number_unwrapped; ++seq_num) {
- auto& packet = GetPacket(seq_num);
-
- packet->video_header.is_first_packet_in_frame =
- (seq_num == start_seq_num_unwrapped);
- packet->video_header.is_last_packet_in_frame =
- (seq_num == end_sequence_number_unwrapped);
-
- if (packet->video_header.is_first_packet_in_frame) {
- if (width > 0 && height > 0) {
- packet->video_header.width = width;
- packet->video_header.height = height;
- }
-
- packet->video_header.frame_type = has_idr
- ? VideoFrameType::kVideoFrameKey
- : VideoFrameType::kVideoFrameDelta;
- }
-
- packet->video_payload =
- FixVideoPayload(packet->video_payload, packet->video_header);
-
- frames.push_back(std::move(packet));
- }
-
- return true;
-}
-
-} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/h264_packet_buffer.h b/third_party/libwebrtc/modules/video_coding/h264_packet_buffer.h
deleted file mode 100644
index a72c240e82..0000000000
--- a/third_party/libwebrtc/modules/video_coding/h264_packet_buffer.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef MODULES_VIDEO_CODING_H264_PACKET_BUFFER_H_
-#define MODULES_VIDEO_CODING_H264_PACKET_BUFFER_H_
-
-#include <array>
-#include <memory>
-#include <vector>
-
-#include "absl/base/attributes.h"
-#include "absl/types/optional.h"
-#include "modules/video_coding/packet_buffer.h"
-#include "rtc_base/numerics/sequence_number_unwrapper.h"
-
-namespace webrtc {
-
-class H264PacketBuffer {
- public:
- // The H264PacketBuffer does the same job as the PacketBuffer but for H264
- // only. To make it fit in with surronding code the PacketBuffer input/output
- // classes are used.
- using Packet = video_coding::PacketBuffer::Packet;
- using InsertResult = video_coding::PacketBuffer::InsertResult;
-
- explicit H264PacketBuffer(bool idr_only_keyframes_allowed);
-
- ABSL_MUST_USE_RESULT InsertResult
- InsertPacket(std::unique_ptr<Packet> packet);
-
- private:
- static constexpr int kBufferSize = 2048;
-
- std::unique_ptr<Packet>& GetPacket(int64_t unwrapped_seq_num);
- bool BeginningOfStream(const Packet& packet) const;
- std::vector<std::unique_ptr<Packet>> FindFrames(int64_t unwrapped_seq_num);
- bool MaybeAssembleFrame(int64_t start_seq_num_unwrapped,
- int64_t end_sequence_number_unwrapped,
- std::vector<std::unique_ptr<Packet>>& packets);
-
- const bool idr_only_keyframes_allowed_;
- std::array<std::unique_ptr<Packet>, kBufferSize> buffer_;
- absl::optional<int64_t> last_continuous_unwrapped_seq_num_;
- SeqNumUnwrapper<uint16_t> seq_num_unwrapper_;
-};
-
-} // namespace webrtc
-
-#endif // MODULES_VIDEO_CODING_H264_PACKET_BUFFER_H_
diff --git a/third_party/libwebrtc/modules/video_coding/h264_packet_buffer_unittest.cc b/third_party/libwebrtc/modules/video_coding/h264_packet_buffer_unittest.cc
deleted file mode 100644
index 4f2331da28..0000000000
--- a/third_party/libwebrtc/modules/video_coding/h264_packet_buffer_unittest.cc
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
- * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#include "modules/video_coding/h264_packet_buffer.h"
-
-#include <cstring>
-#include <limits>
-#include <ostream>
-#include <string>
-#include <utility>
-
-#include "api/array_view.h"
-#include "api/video/render_resolution.h"
-#include "common_video/h264/h264_common.h"
-#include "rtc_base/system/unused.h"
-#include "test/gmock.h"
-#include "test/gtest.h"
-
-namespace webrtc {
-namespace {
-
-using ::testing::ElementsAreArray;
-using ::testing::Eq;
-using ::testing::IsEmpty;
-using ::testing::SizeIs;
-
-using H264::NaluType::kAud;
-using H264::NaluType::kFuA;
-using H264::NaluType::kIdr;
-using H264::NaluType::kPps;
-using H264::NaluType::kSlice;
-using H264::NaluType::kSps;
-using H264::NaluType::kStapA;
-
-constexpr int kBufferSize = 2048;
-
-std::vector<uint8_t> StartCode() {
- return {0, 0, 0, 1};
-}
-
-NaluInfo MakeNaluInfo(uint8_t type) {
- NaluInfo res;
- res.type = type;
- res.sps_id = -1;
- res.pps_id = -1;
- return res;
-}
-
-class Packet {
- public:
- explicit Packet(H264PacketizationTypes type);
-
- Packet& Idr(std::vector<uint8_t> payload = {9, 9, 9});
- Packet& Slice(std::vector<uint8_t> payload = {9, 9, 9});
- Packet& Sps(std::vector<uint8_t> payload = {9, 9, 9});
- Packet& SpsWithResolution(RenderResolution resolution,
- std::vector<uint8_t> payload = {9, 9, 9});
- Packet& Pps(std::vector<uint8_t> payload = {9, 9, 9});
- Packet& Aud();
- Packet& Marker();
- Packet& AsFirstFragment();
- Packet& Time(uint32_t rtp_timestamp);
- Packet& SeqNum(uint16_t rtp_seq_num);
-
- std::unique_ptr<H264PacketBuffer::Packet> Build();
-
- private:
- rtc::CopyOnWriteBuffer BuildFuaPayload() const;
- rtc::CopyOnWriteBuffer BuildSingleNaluPayload() const;
- rtc::CopyOnWriteBuffer BuildStapAPayload() const;
-
- RTPVideoHeaderH264& H264Header() {
- return absl::get<RTPVideoHeaderH264>(video_header_.video_type_header);
- }
- const RTPVideoHeaderH264& H264Header() const {
- return absl::get<RTPVideoHeaderH264>(video_header_.video_type_header);
- }
-
- H264PacketizationTypes type_;
- RTPVideoHeader video_header_;
- bool first_fragment_ = false;
- bool marker_bit_ = false;
- uint32_t rtp_timestamp_ = 0;
- uint16_t rtp_seq_num_ = 0;
- std::vector<std::vector<uint8_t>> nalu_payloads_;
-};
-
-Packet::Packet(H264PacketizationTypes type) : type_(type) {
- video_header_.video_type_header.emplace<RTPVideoHeaderH264>();
-}
-
-Packet& Packet::Idr(std::vector<uint8_t> payload) {
- auto& h264_header = H264Header();
- h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kIdr);
- nalu_payloads_.push_back(std::move(payload));
- return *this;
-}
-
-Packet& Packet::Slice(std::vector<uint8_t> payload) {
- auto& h264_header = H264Header();
- h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSlice);
- nalu_payloads_.push_back(std::move(payload));
- return *this;
-}
-
-Packet& Packet::Sps(std::vector<uint8_t> payload) {
- auto& h264_header = H264Header();
- h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSps);
- nalu_payloads_.push_back(std::move(payload));
- return *this;
-}
-
-Packet& Packet::SpsWithResolution(RenderResolution resolution,
- std::vector<uint8_t> payload) {
- auto& h264_header = H264Header();
- h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSps);
- video_header_.width = resolution.Width();
- video_header_.height = resolution.Height();
- nalu_payloads_.push_back(std::move(payload));
- return *this;
-}
-
-Packet& Packet::Pps(std::vector<uint8_t> payload) {
- auto& h264_header = H264Header();
- h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kPps);
- nalu_payloads_.push_back(std::move(payload));
- return *this;
-}
-
-Packet& Packet::Aud() {
- auto& h264_header = H264Header();
- h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kAud);
- nalu_payloads_.push_back({});
- return *this;
-}
-
-Packet& Packet::Marker() {
- marker_bit_ = true;
- return *this;
-}
-
-Packet& Packet::AsFirstFragment() {
- first_fragment_ = true;
- return *this;
-}
-
-Packet& Packet::Time(uint32_t rtp_timestamp) {
- rtp_timestamp_ = rtp_timestamp;
- return *this;
-}
-
-Packet& Packet::SeqNum(uint16_t rtp_seq_num) {
- rtp_seq_num_ = rtp_seq_num;
- return *this;
-}
-
-std::unique_ptr<H264PacketBuffer::Packet> Packet::Build() {
- auto res = std::make_unique<H264PacketBuffer::Packet>();
-
- auto& h264_header = H264Header();
- switch (type_) {
- case kH264FuA: {
- RTC_CHECK_EQ(h264_header.nalus_length, 1);
- res->video_payload = BuildFuaPayload();
- break;
- }
- case kH264SingleNalu: {
- RTC_CHECK_EQ(h264_header.nalus_length, 1);
- res->video_payload = BuildSingleNaluPayload();
- break;
- }
- case kH264StapA: {
- RTC_CHECK_GT(h264_header.nalus_length, 1);
- RTC_CHECK_LE(h264_header.nalus_length, kMaxNalusPerPacket);
- res->video_payload = BuildStapAPayload();
- break;
- }
- }
-
- if (type_ == kH264FuA && !first_fragment_) {
- h264_header.nalus_length = 0;
- }
-
- h264_header.packetization_type = type_;
- res->marker_bit = marker_bit_;
- res->video_header = video_header_;
- res->timestamp = rtp_timestamp_;
- res->seq_num = rtp_seq_num_;
- res->video_header.codec = kVideoCodecH264;
-
- return res;
-}
-
-rtc::CopyOnWriteBuffer Packet::BuildFuaPayload() const {
- return rtc::CopyOnWriteBuffer(nalu_payloads_[0]);
-}
-
-rtc::CopyOnWriteBuffer Packet::BuildSingleNaluPayload() const {
- rtc::CopyOnWriteBuffer res;
- auto& h264_header = H264Header();
- res.AppendData(&h264_header.nalus[0].type, 1);
- res.AppendData(nalu_payloads_[0]);
- return res;
-}
-
-rtc::CopyOnWriteBuffer Packet::BuildStapAPayload() const {
- rtc::CopyOnWriteBuffer res;
-
- const uint8_t indicator = H264::NaluType::kStapA;
- res.AppendData(&indicator, 1);
-
- auto& h264_header = H264Header();
- for (size_t i = 0; i < h264_header.nalus_length; ++i) {
- // The two first bytes indicates the nalu segment size.
- uint8_t length_as_array[2] = {
- 0, static_cast<uint8_t>(nalu_payloads_[i].size() + 1)};
- res.AppendData(length_as_array);
-
- res.AppendData(&h264_header.nalus[i].type, 1);
- res.AppendData(nalu_payloads_[i]);
- }
- return res;
-}
-
-rtc::ArrayView<const uint8_t> PacketPayload(
- const std::unique_ptr<H264PacketBuffer::Packet>& packet) {
- return packet->video_payload;
-}
-
-std::vector<uint8_t> FlatVector(
- const std::vector<std::vector<uint8_t>>& elems) {
- std::vector<uint8_t> res;
- for (const auto& elem : elems) {
- res.insert(res.end(), elem.begin(), elem.end());
- }
- return res;
-}
-
-TEST(H264PacketBufferTest, IdrIsKeyframe) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/true);
-
- EXPECT_THAT(
- packet_buffer.InsertPacket(Packet(kH264SingleNalu).Idr().Marker().Build())
- .packets,
- SizeIs(1));
-}
-
-TEST(H264PacketBufferTest, IdrIsNotKeyframe) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(
- packet_buffer.InsertPacket(Packet(kH264SingleNalu).Idr().Marker().Build())
- .packets,
- IsEmpty());
-}
-
-TEST(H264PacketBufferTest, IdrIsKeyframeFuaRequiresFirstFragmet) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/true);
-
- // Not marked as the first fragment
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build())
- .packets,
- IsEmpty());
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(
- Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
- .packets,
- IsEmpty());
-
- // Marked as first fragment
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264FuA)
- .Idr()
- .SeqNum(2)
- .Time(1)
- .AsFirstFragment()
- .Build())
- .packets,
- IsEmpty());
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(
- Packet(kH264FuA).Idr().SeqNum(3).Time(1).Marker().Build())
- .packets,
- SizeIs(2));
-}
-
-TEST(H264PacketBufferTest, SpsPpsIdrIsKeyframeSingleNalus) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Pps().SeqNum(1).Time(0).Build()));
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(
- Packet(kH264SingleNalu).Idr().SeqNum(2).Time(0).Marker().Build())
- .packets,
- SizeIs(3));
-}
-
-TEST(H264PacketBufferTest, PpsIdrIsNotKeyframeSingleNalus) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Pps().SeqNum(0).Time(0).Build()));
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(
- Packet(kH264SingleNalu).Idr().SeqNum(1).Time(0).Marker().Build())
- .packets,
- IsEmpty());
-}
-
-TEST(H264PacketBufferTest, SpsIdrIsNotKeyframeSingleNalus) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(
- Packet(kH264SingleNalu).Idr().SeqNum(1).Time(0).Marker().Build())
- .packets,
- IsEmpty());
-}
-
-TEST(H264PacketBufferTest, SpsPpsIdrIsKeyframeStapA) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(0)
- .Time(0)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-}
-
-TEST(H264PacketBufferTest, PpsIdrIsNotKeyframeStapA) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(
- Packet(kH264StapA).Pps().Idr().SeqNum(0).Time(0).Marker().Build())
- .packets,
- IsEmpty());
-}
-
-TEST(H264PacketBufferTest, SpsIdrIsNotKeyframeStapA) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(
- Packet(kH264StapA).Sps().Idr().SeqNum(2).Time(2).Marker().Build())
- .packets,
- IsEmpty());
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(3)
- .Time(3)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-}
-
-TEST(H264PacketBufferTest, InsertingSpsPpsLastCompletesKeyframe) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Idr().SeqNum(2).Time(1).Marker().Build()));
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(
- Packet(kH264StapA).Sps().Pps().SeqNum(1).Time(1).Build())
- .packets,
- SizeIs(2));
-}
-
-TEST(H264PacketBufferTest, InsertingMidFuaCompletesFrame) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(0)
- .Time(0)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264FuA).Slice().SeqNum(1).Time(1).AsFirstFragment().Build()));
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264FuA).Slice().SeqNum(3).Time(1).Marker().Build()));
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(Packet(kH264FuA).Slice().SeqNum(2).Time(1).Build())
- .packets,
- SizeIs(3));
-}
-
-TEST(H264PacketBufferTest, SeqNumJumpDoesNotCompleteFrame) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(0)
- .Time(0)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(Packet(kH264FuA).Slice().SeqNum(1).Time(1).Build())
- .packets,
- IsEmpty());
-
- // Add `kBufferSize` to make the index of the sequence number wrap and end up
- // where the packet with sequence number 2 would have ended up.
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264FuA)
- .Slice()
- .SeqNum(2 + kBufferSize)
- .Time(3)
- .Marker()
- .Build())
- .packets,
- IsEmpty());
-}
-
-TEST(H264PacketBufferTest, OldFramesAreNotCompletedAfterBufferWrap) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264SingleNalu)
- .Slice()
- .SeqNum(1)
- .Time(1)
- .Marker()
- .Build())
- .packets,
- IsEmpty());
-
- // New keyframe, preceedes packet with sequence number 1 in the buffer.
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(kBufferSize)
- .Time(kBufferSize)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-}
-
-TEST(H264PacketBufferTest, OldPacketsDontBlockNewPackets) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(kBufferSize)
- .Time(kBufferSize)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-
- RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
- .Slice()
- .SeqNum(kBufferSize + 1)
- .Time(kBufferSize + 1)
- .AsFirstFragment()
- .Build()));
-
- RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
- .Slice()
- .SeqNum(kBufferSize + 3)
- .Time(kBufferSize + 1)
- .Marker()
- .Build()));
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build())
- .packets,
- IsEmpty());
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264FuA)
- .Slice()
- .SeqNum(kBufferSize + 2)
- .Time(kBufferSize + 1)
- .Build())
- .packets,
- SizeIs(3));
-}
-
-TEST(H264PacketBufferTest, OldPacketDoesntCompleteFrame) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(kBufferSize)
- .Time(kBufferSize)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264FuA)
- .Slice()
- .SeqNum(kBufferSize + 3)
- .Time(kBufferSize + 1)
- .Marker()
- .Build())
- .packets,
- IsEmpty());
-
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(
- Packet(kH264FuA).Slice().SeqNum(2).Time(2).Marker().Build())
- .packets,
- IsEmpty());
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264FuA)
- .Slice()
- .SeqNum(kBufferSize + 1)
- .Time(kBufferSize + 1)
- .AsFirstFragment()
- .Build())
- .packets,
- IsEmpty());
-}
-
-TEST(H264PacketBufferTest, FrameBoundariesAreSet) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- auto key = packet_buffer.InsertPacket(
- Packet(kH264StapA).Sps().Pps().Idr().SeqNum(1).Time(1).Marker().Build());
-
- ASSERT_THAT(key.packets, SizeIs(1));
- EXPECT_TRUE(key.packets[0]->video_header.is_first_packet_in_frame);
- EXPECT_TRUE(key.packets[0]->video_header.is_last_packet_in_frame);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build()));
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264FuA).Slice().SeqNum(3).Time(2).Build()));
- auto delta = packet_buffer.InsertPacket(
- Packet(kH264FuA).Slice().SeqNum(4).Time(2).Marker().Build());
-
- ASSERT_THAT(delta.packets, SizeIs(3));
- EXPECT_TRUE(delta.packets[0]->video_header.is_first_packet_in_frame);
- EXPECT_FALSE(delta.packets[0]->video_header.is_last_packet_in_frame);
-
- EXPECT_FALSE(delta.packets[1]->video_header.is_first_packet_in_frame);
- EXPECT_FALSE(delta.packets[1]->video_header.is_last_packet_in_frame);
-
- EXPECT_FALSE(delta.packets[2]->video_header.is_first_packet_in_frame);
- EXPECT_TRUE(delta.packets[2]->video_header.is_last_packet_in_frame);
-}
-
-TEST(H264PacketBufferTest, ResolutionSetOnFirstPacket) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
- auto res = packet_buffer.InsertPacket(Packet(kH264StapA)
- .SpsWithResolution({320, 240})
- .Pps()
- .Idr()
- .SeqNum(2)
- .Time(1)
- .Marker()
- .Build());
-
- ASSERT_THAT(res.packets, SizeIs(2));
- EXPECT_THAT(res.packets[0]->video_header.width, Eq(320));
- EXPECT_THAT(res.packets[0]->video_header.height, Eq(240));
-}
-
-TEST(H264PacketBufferTest, KeyframeAndDeltaFrameSetOnFirstPacket) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
- auto key = packet_buffer.InsertPacket(
- Packet(kH264StapA).Sps().Pps().Idr().SeqNum(2).Time(1).Marker().Build());
-
- auto delta = packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Slice().SeqNum(3).Time(2).Marker().Build());
-
- ASSERT_THAT(key.packets, SizeIs(2));
- EXPECT_THAT(key.packets[0]->video_header.frame_type,
- Eq(VideoFrameType::kVideoFrameKey));
- ASSERT_THAT(delta.packets, SizeIs(1));
- EXPECT_THAT(delta.packets[0]->video_header.frame_type,
- Eq(VideoFrameType::kVideoFrameDelta));
-}
-
-TEST(H264PacketBufferTest, RtpSeqNumWrap) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264StapA).Sps().Pps().SeqNum(0xffff).Time(0).Build()));
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build()));
- EXPECT_THAT(packet_buffer
- .InsertPacket(
- Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
- .packets,
- SizeIs(3));
-}
-
-TEST(H264PacketBufferTest, StapAFixedBitstream) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- auto packets = packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps({1, 2, 3})
- .Pps({4, 5, 6})
- .Idr({7, 8, 9})
- .SeqNum(0)
- .Time(0)
- .Marker()
- .Build())
- .packets;
-
- ASSERT_THAT(packets, SizeIs(1));
- EXPECT_THAT(PacketPayload(packets[0]),
- ElementsAreArray(FlatVector({StartCode(),
- {kSps, 1, 2, 3},
- StartCode(),
- {kPps, 4, 5, 6},
- StartCode(),
- {kIdr, 7, 8, 9}})));
-}
-
-TEST(H264PacketBufferTest, SingleNaluFixedBitstream) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Sps({1, 2, 3}).SeqNum(0).Time(0).Build()));
- RTC_UNUSED(packet_buffer.InsertPacket(
- Packet(kH264SingleNalu).Pps({4, 5, 6}).SeqNum(1).Time(0).Build()));
- auto packets = packet_buffer
- .InsertPacket(Packet(kH264SingleNalu)
- .Idr({7, 8, 9})
- .SeqNum(2)
- .Time(0)
- .Marker()
- .Build())
- .packets;
-
- ASSERT_THAT(packets, SizeIs(3));
- EXPECT_THAT(PacketPayload(packets[0]),
- ElementsAreArray(FlatVector({StartCode(), {kSps, 1, 2, 3}})));
- EXPECT_THAT(PacketPayload(packets[1]),
- ElementsAreArray(FlatVector({StartCode(), {kPps, 4, 5, 6}})));
- EXPECT_THAT(PacketPayload(packets[2]),
- ElementsAreArray(FlatVector({StartCode(), {kIdr, 7, 8, 9}})));
-}
-
-TEST(H264PacketBufferTest, StapaAndFuaFixedBitstream) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264StapA)
- .Sps({1, 2, 3})
- .Pps({4, 5, 6})
- .SeqNum(0)
- .Time(0)
- .Build()));
- RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
- .Idr({8, 8, 8})
- .SeqNum(1)
- .Time(0)
- .AsFirstFragment()
- .Build()));
- auto packets = packet_buffer
- .InsertPacket(Packet(kH264FuA)
- .Idr({9, 9, 9})
- .SeqNum(2)
- .Time(0)
- .Marker()
- .Build())
- .packets;
-
- ASSERT_THAT(packets, SizeIs(3));
- EXPECT_THAT(
- PacketPayload(packets[0]),
- ElementsAreArray(FlatVector(
- {StartCode(), {kSps, 1, 2, 3}, StartCode(), {kPps, 4, 5, 6}})));
- EXPECT_THAT(PacketPayload(packets[1]),
- ElementsAreArray(FlatVector({StartCode(), {8, 8, 8}})));
- // Third is a continuation of second, so only the payload is expected.
- EXPECT_THAT(PacketPayload(packets[2]),
- ElementsAreArray(FlatVector({{9, 9, 9}})));
-}
-
-TEST(H264PacketBufferTest, FullPacketBufferDoesNotBlockKeyframe) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- for (int i = 0; i < kBufferSize; ++i) {
- EXPECT_THAT(
- packet_buffer
- .InsertPacket(
- Packet(kH264SingleNalu).Slice().SeqNum(i).Time(0).Build())
- .packets,
- IsEmpty());
- }
-
- EXPECT_THAT(packet_buffer
- .InsertPacket(Packet(kH264StapA)
- .Sps()
- .Pps()
- .Idr()
- .SeqNum(kBufferSize)
- .Time(1)
- .Marker()
- .Build())
- .packets,
- SizeIs(1));
-}
-
-TEST(H264PacketBufferTest, TooManyNalusInPacket) {
- H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
-
- std::unique_ptr<H264PacketBuffer::Packet> packet(
- Packet(kH264StapA).Sps().Pps().Idr().SeqNum(1).Time(1).Marker().Build());
- auto& h264_header =
- absl::get<RTPVideoHeaderH264>(packet->video_header.video_type_header);
- h264_header.nalus_length = kMaxNalusPerPacket + 1;
-
- EXPECT_THAT(packet_buffer.InsertPacket(std::move(packet)).packets, IsEmpty());
-}
-
-} // namespace
-} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.cc b/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.cc
new file mode 100644
index 0000000000..bca2b5ce29
--- /dev/null
+++ b/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.cc
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_coding/h26x_packet_buffer.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+#include "api/array_view.h"
+#include "api/rtp_packet_info.h"
+#include "api/video/video_frame_type.h"
+#include "common_video/h264/h264_common.h"
+#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_video_header.h"
+#include "modules/video_coding/codecs/h264/include/h264_globals.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/sequence_number_util.h"
+#ifdef RTC_ENABLE_H265
+#include "common_video/h265/h265_common.h"
+#endif
+
+namespace webrtc {
+namespace {
+
+int64_t EuclideanMod(int64_t n, int64_t div) {
+ RTC_DCHECK_GT(div, 0);
+ return (n %= div) < 0 ? n + div : n;
+}
+
+rtc::ArrayView<const NaluInfo> GetNaluInfos(
+ const RTPVideoHeaderH264& h264_header) {
+ if (h264_header.nalus_length > kMaxNalusPerPacket) {
+ return {};
+ }
+
+ return rtc::MakeArrayView(h264_header.nalus, h264_header.nalus_length);
+}
+
+bool IsFirstPacketOfFragment(const RTPVideoHeaderH264& h264_header) {
+ return h264_header.nalus_length > 0;
+}
+
+bool BeginningOfIdr(const H26xPacketBuffer::Packet& packet) {
+ const auto& h264_header =
+ absl::get<RTPVideoHeaderH264>(packet.video_header.video_type_header);
+ const bool contains_idr_nalu =
+ absl::c_any_of(GetNaluInfos(h264_header), [](const auto& nalu_info) {
+ return nalu_info.type == H264::NaluType::kIdr;
+ });
+ switch (h264_header.packetization_type) {
+ case kH264StapA:
+ case kH264SingleNalu: {
+ return contains_idr_nalu;
+ }
+ case kH264FuA: {
+ return contains_idr_nalu && IsFirstPacketOfFragment(h264_header);
+ }
+ }
+}
+
+bool HasSps(const H26xPacketBuffer::Packet& packet) {
+ auto& h264_header =
+ absl::get<RTPVideoHeaderH264>(packet.video_header.video_type_header);
+ return absl::c_any_of(GetNaluInfos(h264_header), [](const auto& nalu_info) {
+ return nalu_info.type == H264::NaluType::kSps;
+ });
+}
+
+#ifdef RTC_ENABLE_H265
+bool HasVps(const H26xPacketBuffer::Packet& packet) {
+ std::vector<H265::NaluIndex> nalu_indices = H265::FindNaluIndices(
+ packet.video_payload.cdata(), packet.video_payload.size());
+ return absl::c_any_of((nalu_indices), [&packet](
+ const H265::NaluIndex& nalu_index) {
+ return H265::ParseNaluType(
+ packet.video_payload.cdata()[nalu_index.payload_start_offset]) ==
+ H265::NaluType::kVps;
+ });
+}
+#endif
+
+// TODO(bugs.webrtc.org/13157): Update the H264 depacketizer so we don't have to
+// fiddle with the payload at this point.
+rtc::CopyOnWriteBuffer FixH264VideoPayload(
+ rtc::ArrayView<const uint8_t> payload,
+ const RTPVideoHeader& video_header) {
+ constexpr uint8_t kStartCode[] = {0, 0, 0, 1};
+
+ const auto& h264_header =
+ absl::get<RTPVideoHeaderH264>(video_header.video_type_header);
+
+ rtc::CopyOnWriteBuffer result;
+ switch (h264_header.packetization_type) {
+ case kH264StapA: {
+ const uint8_t* payload_end = payload.data() + payload.size();
+ const uint8_t* nalu_ptr = payload.data() + 1;
+ while (nalu_ptr < payload_end - 1) {
+ // The first two bytes describe the length of the segment, where a
+ // segment is the nalu type plus nalu payload.
+ uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
+ nalu_ptr += 2;
+
+ if (nalu_ptr + segment_length <= payload_end) {
+ result.AppendData(kStartCode);
+ result.AppendData(nalu_ptr, segment_length);
+ }
+ nalu_ptr += segment_length;
+ }
+ return result;
+ }
+
+ case kH264FuA: {
+ if (IsFirstPacketOfFragment(h264_header)) {
+ result.AppendData(kStartCode);
+ }
+ result.AppendData(payload);
+ return result;
+ }
+
+ case kH264SingleNalu: {
+ result.AppendData(kStartCode);
+ result.AppendData(payload);
+ return result;
+ }
+ }
+
+ RTC_DCHECK_NOTREACHED();
+ return result;
+}
+
+} // namespace
+
+H26xPacketBuffer::H26xPacketBuffer(bool h264_idr_only_keyframes_allowed)
+ : h264_idr_only_keyframes_allowed_(h264_idr_only_keyframes_allowed) {}
+
+H26xPacketBuffer::InsertResult H26xPacketBuffer::InsertPacket(
+ std::unique_ptr<Packet> packet) {
+ RTC_DCHECK(packet->video_header.codec == kVideoCodecH264 ||
+ packet->video_header.codec == kVideoCodecH265);
+
+ InsertResult result;
+
+ int64_t unwrapped_seq_num = seq_num_unwrapper_.Unwrap(packet->seq_num);
+ auto& packet_slot = GetPacket(unwrapped_seq_num);
+ if (packet_slot != nullptr &&
+ AheadOrAt(packet_slot->timestamp, packet->timestamp)) {
+ // The incoming `packet` is old or a duplicate.
+ return result;
+ } else {
+ packet_slot = std::move(packet);
+ }
+
+ result.packets = FindFrames(unwrapped_seq_num);
+ return result;
+}
+
+std::unique_ptr<H26xPacketBuffer::Packet>& H26xPacketBuffer::GetPacket(
+ int64_t unwrapped_seq_num) {
+ return buffer_[EuclideanMod(unwrapped_seq_num, kBufferSize)];
+}
+
+bool H26xPacketBuffer::BeginningOfStream(
+ const H26xPacketBuffer::Packet& packet) const {
+ if (packet.codec() == kVideoCodecH264) {
+ return HasSps(packet) ||
+ (h264_idr_only_keyframes_allowed_ && BeginningOfIdr(packet));
+#ifdef RTC_ENABLE_H265
+ } else if (packet.codec() == kVideoCodecH265) {
+ return HasVps(packet);
+#endif
+ }
+ RTC_DCHECK_NOTREACHED();
+ return false;
+}
+
+std::vector<std::unique_ptr<H26xPacketBuffer::Packet>>
+H26xPacketBuffer::FindFrames(int64_t unwrapped_seq_num) {
+ std::vector<std::unique_ptr<Packet>> found_frames;
+
+ Packet* packet = GetPacket(unwrapped_seq_num).get();
+ RTC_CHECK(packet != nullptr);
+
+ // Check if the packet is continuous or the beginning of a new coded video
+ // sequence.
+ if (unwrapped_seq_num - 1 != last_continuous_unwrapped_seq_num_) {
+ if (unwrapped_seq_num <= last_continuous_unwrapped_seq_num_ ||
+ !BeginningOfStream(*packet)) {
+ return found_frames;
+ }
+
+ last_continuous_unwrapped_seq_num_ = unwrapped_seq_num;
+ }
+
+ for (int64_t seq_num = unwrapped_seq_num;
+ seq_num < unwrapped_seq_num + kBufferSize;) {
+ RTC_DCHECK_GE(seq_num, *last_continuous_unwrapped_seq_num_);
+
+ // Packets that were never assembled into a completed frame will stay in
+ // the 'buffer_'. Check that the `packet` sequence number match the expected
+ // unwrapped sequence number.
+ if (static_cast<uint16_t>(seq_num) != packet->seq_num) {
+ return found_frames;
+ }
+
+ last_continuous_unwrapped_seq_num_ = seq_num;
+ // Last packet of the frame, try to assemble the frame.
+ if (packet->marker_bit) {
+ uint32_t rtp_timestamp = packet->timestamp;
+
+ // Iterate backwards to find where the frame starts.
+ for (int64_t seq_num_start = seq_num;
+ seq_num_start > seq_num - kBufferSize; --seq_num_start) {
+ auto& prev_packet = GetPacket(seq_num_start - 1);
+
+ if (prev_packet == nullptr || prev_packet->timestamp != rtp_timestamp) {
+ if (MaybeAssembleFrame(seq_num_start, seq_num, found_frames)) {
+ // Frame was assembled, continue to look for more frames.
+ break;
+ } else {
+ // Frame was not assembled, no subsequent frame will be continuous.
+ return found_frames;
+ }
+ }
+ }
+ }
+
+ seq_num++;
+ packet = GetPacket(seq_num).get();
+ if (packet == nullptr) {
+ return found_frames;
+ }
+ }
+
+ return found_frames;
+}
+
+bool H26xPacketBuffer::MaybeAssembleFrame(
+ int64_t start_seq_num_unwrapped,
+ int64_t end_sequence_number_unwrapped,
+ std::vector<std::unique_ptr<Packet>>& frames) {
+#ifdef RTC_ENABLE_H265
+ bool has_vps = false;
+#endif
+ bool has_sps = false;
+ bool has_pps = false;
+ bool has_idr = false;
+ bool has_irap = false;
+
+ int width = -1;
+ int height = -1;
+
+ for (int64_t seq_num = start_seq_num_unwrapped;
+ seq_num <= end_sequence_number_unwrapped; ++seq_num) {
+ const auto& packet = GetPacket(seq_num);
+ if (packet->codec() == kVideoCodecH264) {
+ const auto& h264_header =
+ absl::get<RTPVideoHeaderH264>(packet->video_header.video_type_header);
+ for (const auto& nalu : GetNaluInfos(h264_header)) {
+ has_idr |= nalu.type == H264::NaluType::kIdr;
+ has_sps |= nalu.type == H264::NaluType::kSps;
+ has_pps |= nalu.type == H264::NaluType::kPps;
+ }
+ if (has_idr) {
+ if (!h264_idr_only_keyframes_allowed_ && (!has_sps || !has_pps)) {
+ return false;
+ }
+ }
+#ifdef RTC_ENABLE_H265
+ } else if (packet->codec() == kVideoCodecH265) {
+ std::vector<H265::NaluIndex> nalu_indices = H265::FindNaluIndices(
+ packet->video_payload.cdata(), packet->video_payload.size());
+ for (const auto& nalu_index : nalu_indices) {
+ uint8_t nalu_type = H265::ParseNaluType(
+ packet->video_payload.cdata()[nalu_index.payload_start_offset]);
+ has_irap |= (nalu_type >= H265::NaluType::kBlaWLp &&
+ nalu_type <= H265::NaluType::kRsvIrapVcl23);
+ has_vps |= nalu_type == H265::NaluType::kVps;
+ has_sps |= nalu_type == H265::NaluType::kSps;
+ has_pps |= nalu_type == H265::NaluType::kPps;
+ }
+ if (has_irap) {
+ if (!has_vps || !has_sps || !has_pps) {
+ return false;
+ }
+ }
+#endif // RTC_ENABLE_H265
+ }
+
+ width = std::max<int>(packet->video_header.width, width);
+ height = std::max<int>(packet->video_header.height, height);
+ }
+
+ for (int64_t seq_num = start_seq_num_unwrapped;
+ seq_num <= end_sequence_number_unwrapped; ++seq_num) {
+ auto& packet = GetPacket(seq_num);
+
+ packet->video_header.is_first_packet_in_frame =
+ (seq_num == start_seq_num_unwrapped);
+ packet->video_header.is_last_packet_in_frame =
+ (seq_num == end_sequence_number_unwrapped);
+
+ if (packet->video_header.is_first_packet_in_frame) {
+ if (width > 0 && height > 0) {
+ packet->video_header.width = width;
+ packet->video_header.height = height;
+ }
+
+ packet->video_header.frame_type = has_idr || has_irap
+ ? VideoFrameType::kVideoFrameKey
+ : VideoFrameType::kVideoFrameDelta;
+ }
+
+ // Start code is inserted by depacktizer for H.265.
+ if (packet->codec() == kVideoCodecH264) {
+ packet->video_payload =
+ FixH264VideoPayload(packet->video_payload, packet->video_header);
+ }
+
+ frames.push_back(std::move(packet));
+ }
+
+ return true;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.h b/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.h
new file mode 100644
index 0000000000..21601562c5
--- /dev/null
+++ b/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CODING_H26X_PACKET_BUFFER_H_
+#define MODULES_VIDEO_CODING_H26X_PACKET_BUFFER_H_
+
+#include <array>
+#include <memory>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/types/optional.h"
+#include "modules/video_coding/packet_buffer.h"
+#include "rtc_base/numerics/sequence_number_unwrapper.h"
+
+namespace webrtc {
+
+class H26xPacketBuffer {
+ public:
+ // The H26xPacketBuffer does the same job as the PacketBuffer but for H264 and
+ // H265 only. To make it fit in with surronding code the PacketBuffer
+ // input/output classes are used.
+ using Packet = video_coding::PacketBuffer::Packet;
+ using InsertResult = video_coding::PacketBuffer::InsertResult;
+
+ // |h264_idr_only_keyframes_allowed| is ignored if H.265 is used.
+ explicit H26xPacketBuffer(bool h264_idr_only_keyframes_allowed);
+
+ ABSL_MUST_USE_RESULT InsertResult
+ InsertPacket(std::unique_ptr<Packet> packet);
+
+ private:
+ static constexpr int kBufferSize = 2048;
+
+ std::unique_ptr<Packet>& GetPacket(int64_t unwrapped_seq_num);
+ bool BeginningOfStream(const Packet& packet) const;
+ std::vector<std::unique_ptr<Packet>> FindFrames(int64_t unwrapped_seq_num);
+ bool MaybeAssembleFrame(int64_t start_seq_num_unwrapped,
+ int64_t end_sequence_number_unwrapped,
+ std::vector<std::unique_ptr<Packet>>& packets);
+
+ const bool h264_idr_only_keyframes_allowed_;
+ std::array<std::unique_ptr<Packet>, kBufferSize> buffer_;
+ absl::optional<int64_t> last_continuous_unwrapped_seq_num_;
+ SeqNumUnwrapper<uint16_t> seq_num_unwrapper_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_VIDEO_CODING_H26X_PACKET_BUFFER_H_
diff --git a/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer_unittest.cc b/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer_unittest.cc
new file mode 100644
index 0000000000..ac5bcb735b
--- /dev/null
+++ b/third_party/libwebrtc/modules/video_coding/h26x_packet_buffer_unittest.cc
@@ -0,0 +1,1058 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/video_coding/h26x_packet_buffer.h"
+
+#include <cstring>
+#include <limits>
+#include <ostream>
+#include <string>
+#include <utility>
+
+#include "api/array_view.h"
+#include "api/video/render_resolution.h"
+#include "common_video/h264/h264_common.h"
+#include "rtc_base/system/unused.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#ifdef RTC_ENABLE_H265
+#include "common_video/h265/h265_common.h"
+#endif
+
+namespace webrtc {
+namespace {
+
+using ::testing::ElementsAreArray;
+using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::SizeIs;
+
+using H264::NaluType::kAud;
+using H264::NaluType::kFuA;
+using H264::NaluType::kIdr;
+using H264::NaluType::kPps;
+using H264::NaluType::kSlice;
+using H264::NaluType::kSps;
+using H264::NaluType::kStapA;
+
+constexpr int kBufferSize = 2048;
+
+std::vector<uint8_t> StartCode() {
+ return {0, 0, 0, 1};
+}
+
+NaluInfo MakeNaluInfo(uint8_t type) {
+ NaluInfo res;
+ res.type = type;
+ res.sps_id = -1;
+ res.pps_id = -1;
+ return res;
+}
+
+class H264Packet {
+ public:
+ explicit H264Packet(H264PacketizationTypes type);
+
+ H264Packet& Idr(std::vector<uint8_t> payload = {9, 9, 9});
+ H264Packet& Slice(std::vector<uint8_t> payload = {9, 9, 9});
+ H264Packet& Sps(std::vector<uint8_t> payload = {9, 9, 9});
+ H264Packet& SpsWithResolution(RenderResolution resolution,
+ std::vector<uint8_t> payload = {9, 9, 9});
+ H264Packet& Pps(std::vector<uint8_t> payload = {9, 9, 9});
+ H264Packet& Aud();
+ H264Packet& Marker();
+ H264Packet& AsFirstFragment();
+ H264Packet& Time(uint32_t rtp_timestamp);
+ H264Packet& SeqNum(uint16_t rtp_seq_num);
+
+ std::unique_ptr<H26xPacketBuffer::Packet> Build();
+
+ private:
+ rtc::CopyOnWriteBuffer BuildFuaPayload() const;
+ rtc::CopyOnWriteBuffer BuildSingleNaluPayload() const;
+ rtc::CopyOnWriteBuffer BuildStapAPayload() const;
+
+ RTPVideoHeaderH264& H264Header() {
+ return absl::get<RTPVideoHeaderH264>(video_header_.video_type_header);
+ }
+ const RTPVideoHeaderH264& H264Header() const {
+ return absl::get<RTPVideoHeaderH264>(video_header_.video_type_header);
+ }
+
+ H264PacketizationTypes type_;
+ RTPVideoHeader video_header_;
+ bool first_fragment_ = false;
+ bool marker_bit_ = false;
+ uint32_t rtp_timestamp_ = 0;
+ uint16_t rtp_seq_num_ = 0;
+ std::vector<std::vector<uint8_t>> nalu_payloads_;
+};
+
+H264Packet::H264Packet(H264PacketizationTypes type) : type_(type) {
+ video_header_.video_type_header.emplace<RTPVideoHeaderH264>();
+}
+
+H264Packet& H264Packet::Idr(std::vector<uint8_t> payload) {
+ auto& h264_header = H264Header();
+ h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kIdr);
+ nalu_payloads_.push_back(std::move(payload));
+ return *this;
+}
+
+H264Packet& H264Packet::Slice(std::vector<uint8_t> payload) {
+ auto& h264_header = H264Header();
+ h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSlice);
+ nalu_payloads_.push_back(std::move(payload));
+ return *this;
+}
+
+H264Packet& H264Packet::Sps(std::vector<uint8_t> payload) {
+ auto& h264_header = H264Header();
+ h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSps);
+ nalu_payloads_.push_back(std::move(payload));
+ return *this;
+}
+
+H264Packet& H264Packet::SpsWithResolution(RenderResolution resolution,
+ std::vector<uint8_t> payload) {
+ auto& h264_header = H264Header();
+ h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSps);
+ video_header_.width = resolution.Width();
+ video_header_.height = resolution.Height();
+ nalu_payloads_.push_back(std::move(payload));
+ return *this;
+}
+
+H264Packet& H264Packet::Pps(std::vector<uint8_t> payload) {
+ auto& h264_header = H264Header();
+ h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kPps);
+ nalu_payloads_.push_back(std::move(payload));
+ return *this;
+}
+
+H264Packet& H264Packet::Aud() {
+ auto& h264_header = H264Header();
+ h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kAud);
+ nalu_payloads_.push_back({});
+ return *this;
+}
+
+H264Packet& H264Packet::Marker() {
+ marker_bit_ = true;
+ return *this;
+}
+
+H264Packet& H264Packet::AsFirstFragment() {
+ first_fragment_ = true;
+ return *this;
+}
+
+H264Packet& H264Packet::Time(uint32_t rtp_timestamp) {
+ rtp_timestamp_ = rtp_timestamp;
+ return *this;
+}
+
+H264Packet& H264Packet::SeqNum(uint16_t rtp_seq_num) {
+ rtp_seq_num_ = rtp_seq_num;
+ return *this;
+}
+
+std::unique_ptr<H26xPacketBuffer::Packet> H264Packet::Build() {
+ auto res = std::make_unique<H26xPacketBuffer::Packet>();
+
+ auto& h264_header = H264Header();
+ switch (type_) {
+ case kH264FuA: {
+ RTC_CHECK_EQ(h264_header.nalus_length, 1);
+ res->video_payload = BuildFuaPayload();
+ break;
+ }
+ case kH264SingleNalu: {
+ RTC_CHECK_EQ(h264_header.nalus_length, 1);
+ res->video_payload = BuildSingleNaluPayload();
+ break;
+ }
+ case kH264StapA: {
+ RTC_CHECK_GT(h264_header.nalus_length, 1);
+ RTC_CHECK_LE(h264_header.nalus_length, kMaxNalusPerPacket);
+ res->video_payload = BuildStapAPayload();
+ break;
+ }
+ }
+
+ if (type_ == kH264FuA && !first_fragment_) {
+ h264_header.nalus_length = 0;
+ }
+
+ h264_header.packetization_type = type_;
+ res->marker_bit = marker_bit_;
+ res->video_header = video_header_;
+ res->timestamp = rtp_timestamp_;
+ res->seq_num = rtp_seq_num_;
+ res->video_header.codec = kVideoCodecH264;
+
+ return res;
+}
+
+rtc::CopyOnWriteBuffer H264Packet::BuildFuaPayload() const {
+ return rtc::CopyOnWriteBuffer(nalu_payloads_[0]);
+}
+
+rtc::CopyOnWriteBuffer H264Packet::BuildSingleNaluPayload() const {
+ rtc::CopyOnWriteBuffer res;
+ auto& h264_header = H264Header();
+ res.AppendData(&h264_header.nalus[0].type, 1);
+ res.AppendData(nalu_payloads_[0]);
+ return res;
+}
+
+rtc::CopyOnWriteBuffer H264Packet::BuildStapAPayload() const {
+ rtc::CopyOnWriteBuffer res;
+
+ const uint8_t indicator = H264::NaluType::kStapA;
+ res.AppendData(&indicator, 1);
+
+ auto& h264_header = H264Header();
+ for (size_t i = 0; i < h264_header.nalus_length; ++i) {
+ // The two first bytes indicates the nalu segment size.
+ uint8_t length_as_array[2] = {
+ 0, static_cast<uint8_t>(nalu_payloads_[i].size() + 1)};
+ res.AppendData(length_as_array);
+
+ res.AppendData(&h264_header.nalus[i].type, 1);
+ res.AppendData(nalu_payloads_[i]);
+ }
+ return res;
+}
+
+#ifdef RTC_ENABLE_H265
+class H265Packet {
+ public:
+ H265Packet() = default;
+
+ H265Packet& Idr(std::vector<uint8_t> payload = {9, 9, 9});
+ H265Packet& Slice(H265::NaluType type,
+ std::vector<uint8_t> payload = {9, 9, 9});
+ H265Packet& Vps(std::vector<uint8_t> payload = {9, 9, 9});
+ H265Packet& Sps(std::vector<uint8_t> payload = {9, 9, 9});
+ H265Packet& SpsWithResolution(RenderResolution resolution,
+ std::vector<uint8_t> payload = {9, 9, 9});
+ H265Packet& Pps(std::vector<uint8_t> payload = {9, 9, 9});
+ H265Packet& Aud();
+ H265Packet& Marker();
+ H265Packet& AsFirstFragment();
+ H265Packet& Time(uint32_t rtp_timestamp);
+ H265Packet& SeqNum(uint16_t rtp_seq_num);
+
+ std::unique_ptr<H26xPacketBuffer::Packet> Build();
+
+ private:
+ H265Packet& StartCode();
+
+ RTPVideoHeader video_header_;
+ bool first_fragment_ = false;
+ bool marker_bit_ = false;
+ uint32_t rtp_timestamp_ = 0;
+ uint16_t rtp_seq_num_ = 0;
+ std::vector<std::vector<uint8_t>> nalu_payloads_;
+};
+
+H265Packet& H265Packet::Idr(std::vector<uint8_t> payload) {
+ return Slice(H265::NaluType::kIdrNLp, std::move(payload));
+}
+
+H265Packet& H265Packet::Slice(H265::NaluType type,
+ std::vector<uint8_t> payload) {
+ StartCode();
+ // Nalu header. Assume layer ID is 0 and TID is 2.
+ nalu_payloads_.push_back({static_cast<uint8_t>(type << 1), 0x02});
+ nalu_payloads_.push_back(std::move(payload));
+ return *this;
+}
+
+H265Packet& H265Packet::Vps(std::vector<uint8_t> payload) {
+ return Slice(H265::NaluType::kVps, std::move(payload));
+}
+
+H265Packet& H265Packet::Sps(std::vector<uint8_t> payload) {
+ return Slice(H265::NaluType::kSps, std::move(payload));
+}
+
+H265Packet& H265Packet::SpsWithResolution(RenderResolution resolution,
+ std::vector<uint8_t> payload) {
+ video_header_.width = resolution.Width();
+ video_header_.height = resolution.Height();
+ return Sps(std::move(payload));
+}
+
+H265Packet& H265Packet::Pps(std::vector<uint8_t> payload) {
+ return Slice(H265::NaluType::kPps, std::move(payload));
+}
+
+H265Packet& H265Packet::Aud() {
+ return Slice(H265::NaluType::kAud, {});
+}
+
+H265Packet& H265Packet::Marker() {
+ marker_bit_ = true;
+ return *this;
+}
+
+H265Packet& H265Packet::StartCode() {
+ nalu_payloads_.push_back({0x00, 0x00, 0x00, 0x01});
+ return *this;
+}
+
+std::unique_ptr<H26xPacketBuffer::Packet> H265Packet::Build() {
+ auto res = std::make_unique<H26xPacketBuffer::Packet>();
+ res->marker_bit = marker_bit_;
+ res->video_header = video_header_;
+ res->timestamp = rtp_timestamp_;
+ res->seq_num = rtp_seq_num_;
+ res->video_header.codec = kVideoCodecH265;
+ res->video_payload = rtc::CopyOnWriteBuffer();
+ for (const auto& payload : nalu_payloads_) {
+ res->video_payload.AppendData(payload);
+ }
+
+ return res;
+}
+
+H265Packet& H265Packet::AsFirstFragment() {
+ first_fragment_ = true;
+ return *this;
+}
+
+H265Packet& H265Packet::Time(uint32_t rtp_timestamp) {
+ rtp_timestamp_ = rtp_timestamp;
+ return *this;
+}
+
+H265Packet& H265Packet::SeqNum(uint16_t rtp_seq_num) {
+ rtp_seq_num_ = rtp_seq_num;
+ return *this;
+}
+#endif
+
+rtc::ArrayView<const uint8_t> PacketPayload(
+ const std::unique_ptr<H26xPacketBuffer::Packet>& packet) {
+ return packet->video_payload;
+}
+
+std::vector<uint8_t> FlatVector(
+ const std::vector<std::vector<uint8_t>>& elems) {
+ std::vector<uint8_t> res;
+ for (const auto& elem : elems) {
+ res.insert(res.end(), elem.begin(), elem.end());
+ }
+ return res;
+}
+
+TEST(H26xPacketBufferTest, IdrIsKeyframe) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/true);
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(H264Packet(kH264SingleNalu).Idr().Marker().Build())
+ .packets,
+ SizeIs(1));
+}
+
+TEST(H26xPacketBufferTest, IdrIsNotKeyframe) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(H264Packet(kH264SingleNalu).Idr().Marker().Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, IdrIsKeyframeFuaRequiresFirstFragmet) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/true);
+
+ // Not marked as the first fragment
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(H264Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build())
+ .packets,
+ IsEmpty());
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(
+ H264Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
+ .packets,
+ IsEmpty());
+
+ // Marked as first fragment
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264FuA)
+ .Idr()
+ .SeqNum(2)
+ .Time(1)
+ .AsFirstFragment()
+ .Build())
+ .packets,
+ IsEmpty());
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(
+ H264Packet(kH264FuA).Idr().SeqNum(3).Time(1).Marker().Build())
+ .packets,
+ SizeIs(2));
+}
+
+TEST(H26xPacketBufferTest, SpsPpsIdrIsKeyframeSingleNalus) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Pps().SeqNum(1).Time(0).Build()));
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264SingleNalu)
+ .Idr()
+ .SeqNum(2)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(3));
+}
+
+TEST(H26xPacketBufferTest, PpsIdrIsNotKeyframeSingleNalus) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Pps().SeqNum(0).Time(0).Build()));
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264SingleNalu)
+ .Idr()
+ .SeqNum(1)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, SpsIdrIsNotKeyframeSingleNalus) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264SingleNalu)
+ .Idr()
+ .SeqNum(1)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, SpsPpsIdrIsKeyframeStapA) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(0)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+}
+
+TEST(H26xPacketBufferTest, PpsIdrIsNotKeyframeStapA) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Pps()
+ .Idr()
+ .SeqNum(0)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, SpsIdrIsNotKeyframeStapA) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Idr()
+ .SeqNum(2)
+ .Time(2)
+ .Marker()
+ .Build())
+ .packets,
+ IsEmpty());
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(3)
+ .Time(3)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+}
+
+TEST(H26xPacketBufferTest, InsertingSpsPpsLastCompletesKeyframe) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Idr().SeqNum(2).Time(1).Marker().Build()));
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(
+ H264Packet(kH264StapA).Sps().Pps().SeqNum(1).Time(1).Build())
+ .packets,
+ SizeIs(2));
+}
+
+TEST(H26xPacketBufferTest, InsertingMidFuaCompletesFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(0)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+
+ RTC_UNUSED(packet_buffer.InsertPacket(H264Packet(kH264FuA)
+ .Slice()
+ .SeqNum(1)
+ .Time(1)
+ .AsFirstFragment()
+ .Build()));
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264FuA).Slice().SeqNum(3).Time(1).Marker().Build()));
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(H264Packet(kH264FuA).Slice().SeqNum(2).Time(1).Build())
+ .packets,
+ SizeIs(3));
+}
+
+TEST(H26xPacketBufferTest, SeqNumJumpDoesNotCompleteFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(0)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(H264Packet(kH264FuA).Slice().SeqNum(1).Time(1).Build())
+ .packets,
+ IsEmpty());
+
+ // Add `kBufferSize` to make the index of the sequence number wrap and end up
+ // where the packet with sequence number 2 would have ended up.
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264FuA)
+ .Slice()
+ .SeqNum(2 + kBufferSize)
+ .Time(3)
+ .Marker()
+ .Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, OldFramesAreNotCompletedAfterBufferWrap) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264SingleNalu)
+ .Slice()
+ .SeqNum(1)
+ .Time(1)
+ .Marker()
+ .Build())
+ .packets,
+ IsEmpty());
+
+ // New keyframe, preceedes packet with sequence number 1 in the buffer.
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(kBufferSize)
+ .Time(kBufferSize)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+}
+
+TEST(H26xPacketBufferTest, OldPacketsDontBlockNewPackets) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(kBufferSize)
+ .Time(kBufferSize)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+
+ RTC_UNUSED(packet_buffer.InsertPacket(H264Packet(kH264FuA)
+ .Slice()
+ .SeqNum(kBufferSize + 1)
+ .Time(kBufferSize + 1)
+ .AsFirstFragment()
+ .Build()));
+
+ RTC_UNUSED(packet_buffer.InsertPacket(H264Packet(kH264FuA)
+ .Slice()
+ .SeqNum(kBufferSize + 3)
+ .Time(kBufferSize + 1)
+ .Marker()
+ .Build()));
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(H264Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build())
+ .packets,
+ IsEmpty());
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264FuA)
+ .Slice()
+ .SeqNum(kBufferSize + 2)
+ .Time(kBufferSize + 1)
+ .Build())
+ .packets,
+ SizeIs(3));
+}
+
+TEST(H26xPacketBufferTest, OldPacketDoesntCompleteFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(kBufferSize)
+ .Time(kBufferSize)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264FuA)
+ .Slice()
+ .SeqNum(kBufferSize + 3)
+ .Time(kBufferSize + 1)
+ .Marker()
+ .Build())
+ .packets,
+ IsEmpty());
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(
+ H264Packet(kH264FuA).Slice().SeqNum(2).Time(2).Marker().Build())
+ .packets,
+ IsEmpty());
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264FuA)
+ .Slice()
+ .SeqNum(kBufferSize + 1)
+ .Time(kBufferSize + 1)
+ .AsFirstFragment()
+ .Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, FrameBoundariesAreSet) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ auto key = packet_buffer.InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(1)
+ .Time(1)
+ .Marker()
+ .Build());
+
+ ASSERT_THAT(key.packets, SizeIs(1));
+ EXPECT_TRUE(key.packets[0]->video_header.is_first_packet_in_frame);
+ EXPECT_TRUE(key.packets[0]->video_header.is_last_packet_in_frame);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build()));
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264FuA).Slice().SeqNum(3).Time(2).Build()));
+ auto delta = packet_buffer.InsertPacket(
+ H264Packet(kH264FuA).Slice().SeqNum(4).Time(2).Marker().Build());
+
+ ASSERT_THAT(delta.packets, SizeIs(3));
+ EXPECT_TRUE(delta.packets[0]->video_header.is_first_packet_in_frame);
+ EXPECT_FALSE(delta.packets[0]->video_header.is_last_packet_in_frame);
+
+ EXPECT_FALSE(delta.packets[1]->video_header.is_first_packet_in_frame);
+ EXPECT_FALSE(delta.packets[1]->video_header.is_last_packet_in_frame);
+
+ EXPECT_FALSE(delta.packets[2]->video_header.is_first_packet_in_frame);
+ EXPECT_TRUE(delta.packets[2]->video_header.is_last_packet_in_frame);
+}
+
+TEST(H26xPacketBufferTest, ResolutionSetOnFirstPacket) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
+ auto res = packet_buffer.InsertPacket(H264Packet(kH264StapA)
+ .SpsWithResolution({320, 240})
+ .Pps()
+ .Idr()
+ .SeqNum(2)
+ .Time(1)
+ .Marker()
+ .Build());
+
+ ASSERT_THAT(res.packets, SizeIs(2));
+ EXPECT_THAT(res.packets[0]->video_header.width, Eq(320));
+ EXPECT_THAT(res.packets[0]->video_header.height, Eq(240));
+}
+
+TEST(H26xPacketBufferTest, KeyframeAndDeltaFrameSetOnFirstPacket) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
+ auto key = packet_buffer.InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(2)
+ .Time(1)
+ .Marker()
+ .Build());
+
+ auto delta = packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Slice().SeqNum(3).Time(2).Marker().Build());
+
+ ASSERT_THAT(key.packets, SizeIs(2));
+ EXPECT_THAT(key.packets[0]->video_header.frame_type,
+ Eq(VideoFrameType::kVideoFrameKey));
+ ASSERT_THAT(delta.packets, SizeIs(1));
+ EXPECT_THAT(delta.packets[0]->video_header.frame_type,
+ Eq(VideoFrameType::kVideoFrameDelta));
+}
+
+TEST(H26xPacketBufferTest, RtpSeqNumWrap) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264StapA).Sps().Pps().SeqNum(0xffff).Time(0).Build()));
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build()));
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(
+ H264Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
+ .packets,
+ SizeIs(3));
+}
+
+TEST(H26xPacketBufferTest, StapAFixedBitstream) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ auto packets = packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps({1, 2, 3})
+ .Pps({4, 5, 6})
+ .Idr({7, 8, 9})
+ .SeqNum(0)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets;
+
+ ASSERT_THAT(packets, SizeIs(1));
+ EXPECT_THAT(PacketPayload(packets[0]),
+ ElementsAreArray(FlatVector({StartCode(),
+ {kSps, 1, 2, 3},
+ StartCode(),
+ {kPps, 4, 5, 6},
+ StartCode(),
+ {kIdr, 7, 8, 9}})));
+}
+
+TEST(H26xPacketBufferTest, SingleNaluFixedBitstream) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Sps({1, 2, 3}).SeqNum(0).Time(0).Build()));
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H264Packet(kH264SingleNalu).Pps({4, 5, 6}).SeqNum(1).Time(0).Build()));
+ auto packets = packet_buffer
+ .InsertPacket(H264Packet(kH264SingleNalu)
+ .Idr({7, 8, 9})
+ .SeqNum(2)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets;
+
+ ASSERT_THAT(packets, SizeIs(3));
+ EXPECT_THAT(PacketPayload(packets[0]),
+ ElementsAreArray(FlatVector({StartCode(), {kSps, 1, 2, 3}})));
+ EXPECT_THAT(PacketPayload(packets[1]),
+ ElementsAreArray(FlatVector({StartCode(), {kPps, 4, 5, 6}})));
+ EXPECT_THAT(PacketPayload(packets[2]),
+ ElementsAreArray(FlatVector({StartCode(), {kIdr, 7, 8, 9}})));
+}
+
+TEST(H26xPacketBufferTest, StapaAndFuaFixedBitstream) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(H264Packet(kH264StapA)
+ .Sps({1, 2, 3})
+ .Pps({4, 5, 6})
+ .SeqNum(0)
+ .Time(0)
+ .Build()));
+ RTC_UNUSED(packet_buffer.InsertPacket(H264Packet(kH264FuA)
+ .Idr({8, 8, 8})
+ .SeqNum(1)
+ .Time(0)
+ .AsFirstFragment()
+ .Build()));
+ auto packets = packet_buffer
+ .InsertPacket(H264Packet(kH264FuA)
+ .Idr({9, 9, 9})
+ .SeqNum(2)
+ .Time(0)
+ .Marker()
+ .Build())
+ .packets;
+
+ ASSERT_THAT(packets, SizeIs(3));
+ EXPECT_THAT(
+ PacketPayload(packets[0]),
+ ElementsAreArray(FlatVector(
+ {StartCode(), {kSps, 1, 2, 3}, StartCode(), {kPps, 4, 5, 6}})));
+ EXPECT_THAT(PacketPayload(packets[1]),
+ ElementsAreArray(FlatVector({StartCode(), {8, 8, 8}})));
+ // Third is a continuation of second, so only the payload is expected.
+ EXPECT_THAT(PacketPayload(packets[2]),
+ ElementsAreArray(FlatVector({{9, 9, 9}})));
+}
+
+TEST(H26xPacketBufferTest, FullPacketBufferDoesNotBlockKeyframe) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ for (int i = 0; i < kBufferSize; ++i) {
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(
+ H264Packet(kH264SingleNalu).Slice().SeqNum(i).Time(0).Build())
+ .packets,
+ IsEmpty());
+ }
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(kBufferSize)
+ .Time(1)
+ .Marker()
+ .Build())
+ .packets,
+ SizeIs(1));
+}
+
+TEST(H26xPacketBufferTest, TooManyNalusInPacket) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ std::unique_ptr<H26xPacketBuffer::Packet> packet(H264Packet(kH264StapA)
+ .Sps()
+ .Pps()
+ .Idr()
+ .SeqNum(1)
+ .Time(1)
+ .Marker()
+ .Build());
+ auto& h264_header =
+ absl::get<RTPVideoHeaderH264>(packet->video_header.video_type_header);
+ h264_header.nalus_length = kMaxNalusPerPacket + 1;
+
+ EXPECT_THAT(packet_buffer.InsertPacket(std::move(packet)).packets, IsEmpty());
+}
+
+#ifdef RTC_ENABLE_H265
+TEST(H26xPacketBufferTest, H265VpsSpsPpsIdrIsKeyframe) {
+ H26xPacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(
+ packet_buffer
+ .InsertPacket(H265Packet().Vps().Sps().Pps().Idr().Marker().Build())
+ .packets,
+ SizeIs(1));
+}
+
+TEST(H26xPacketBufferTest, H265IrapIsNotKeyframe) {
+ std::vector<const H265::NaluType> irap_types = {
+ H265::NaluType::kBlaWLp, H265::NaluType::kBlaWRadl,
+ H265::NaluType::kBlaNLp, H265::NaluType::kIdrWRadl,
+ H265::NaluType::kIdrNLp, H265::NaluType::kCra,
+ H265::NaluType::kRsvIrapVcl23};
+ for (const H265::NaluType type : irap_types) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(
+ packet_buffer.InsertPacket(H265Packet().Slice(type).Marker().Build())
+ .packets,
+ IsEmpty());
+ }
+}
+
+TEST(H26xPacketBufferTest, H265IdrIsNotKeyFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(
+ packet_buffer.InsertPacket(H265Packet().Idr().Marker().Build()).packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, H265SpsPpsIdrIsNotKeyFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H265Packet().Sps().Pps().Idr().Marker().Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, H265VpsPpsIdrIsNotKeyFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H265Packet().Vps().Pps().Idr().Marker().Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, H265VpsSpsIdrIsNotKeyFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(H265Packet().Vps().Sps().Idr().Marker().Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, H265VpsIdrIsNotKeyFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(
+ packet_buffer.InsertPacket(H265Packet().Vps().Idr().Marker().Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, H265SpsIdrIsNotKeyFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(
+ packet_buffer.InsertPacket(H265Packet().Sps().Idr().Marker().Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, H265PpsIdrIsNotKeyFrame) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ EXPECT_THAT(
+ packet_buffer.InsertPacket(H265Packet().Pps().Idr().Marker().Build())
+ .packets,
+ IsEmpty());
+}
+
+TEST(H26xPacketBufferTest, H265ResolutionSetOnSpsPacket) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(
+ packet_buffer.InsertPacket(H265Packet().Aud().SeqNum(1).Time(1).Build()));
+ auto res = packet_buffer.InsertPacket(H265Packet()
+ .Vps()
+ .SpsWithResolution({320, 240})
+ .Pps()
+ .Idr()
+ .SeqNum(2)
+ .Time(1)
+ .Marker()
+ .Build());
+
+ ASSERT_THAT(res.packets, SizeIs(2));
+ EXPECT_THAT(res.packets[0]->video_header.width, Eq(320));
+ EXPECT_THAT(res.packets[0]->video_header.height, Eq(240));
+}
+
+TEST(H26xPacketBufferTest, H265InsertingVpsSpsPpsLastCompletesKeyframe) {
+ H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
+
+ RTC_UNUSED(packet_buffer.InsertPacket(
+ H265Packet().Idr().SeqNum(2).Time(1).Marker().Build()));
+
+ EXPECT_THAT(packet_buffer
+ .InsertPacket(
+ H265Packet().Vps().Sps().Pps().SeqNum(1).Time(1).Build())
+ .packets,
+ SizeIs(2));
+}
+#endif // RTC_ENABLE_H265
+
+} // namespace
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/include/video_error_codes.h b/third_party/libwebrtc/modules/video_coding/include/video_error_codes.h
index 17146ce205..d7d54f3989 100644
--- a/third_party/libwebrtc/modules/video_coding/include/video_error_codes.h
+++ b/third_party/libwebrtc/modules/video_coding/include/video_error_codes.h
@@ -11,10 +11,6 @@
#ifndef MODULES_VIDEO_CODING_INCLUDE_VIDEO_ERROR_CODES_H_
#define MODULES_VIDEO_CODING_INCLUDE_VIDEO_ERROR_CODES_H_
-// NOTE: in sync with video_coding_module_defines.h
-
-// Define return values
-
#define WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT 5
#define WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME 4
#define WEBRTC_VIDEO_CODEC_NO_OUTPUT 1
diff --git a/third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.cc b/third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.cc
new file mode 100644
index 0000000000..7e2c08d518
--- /dev/null
+++ b/third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_coding/include/video_error_codes_utils.h"
+
+#include "modules/video_coding/include/video_error_codes.h"
+
+namespace webrtc {
+
+const char* WebRtcVideoCodecErrorToString(int32_t error_code) {
+ switch (error_code) {
+ case WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT:
+ return "WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT";
+ case WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME:
+ return "WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME";
+ case WEBRTC_VIDEO_CODEC_NO_OUTPUT:
+ return "WEBRTC_VIDEO_CODEC_NO_OUTPUT";
+ case WEBRTC_VIDEO_CODEC_ERROR:
+ return "WEBRTC_VIDEO_CODEC_ERROR";
+ case WEBRTC_VIDEO_CODEC_MEMORY:
+ return "WEBRTC_VIDEO_CODEC_MEMORY";
+ case WEBRTC_VIDEO_CODEC_ERR_PARAMETER:
+ return "WEBRTC_VIDEO_CODEC_ERR_PARAMETER";
+ case WEBRTC_VIDEO_CODEC_TIMEOUT:
+ return "WEBRTC_VIDEO_CODEC_TIMEOUT";
+ case WEBRTC_VIDEO_CODEC_UNINITIALIZED:
+ return "WEBRTC_VIDEO_CODEC_UNINITIALIZED";
+ case WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE:
+ return "WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE";
+ case WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED:
+ return "WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED";
+ case WEBRTC_VIDEO_CODEC_ENCODER_FAILURE:
+ return "WEBRTC_VIDEO_CODEC_ENCODER_FAILURE";
+ default:
+ return "WEBRTC_VIDEO_CODEC_UNKNOWN";
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.h b/third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.h
new file mode 100644
index 0000000000..ae17e29636
--- /dev/null
+++ b/third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CODING_INCLUDE_VIDEO_ERROR_CODES_UTILS_H_
+#define MODULES_VIDEO_CODING_INCLUDE_VIDEO_ERROR_CODES_UTILS_H_
+
+#include <stdint.h>
+
+namespace webrtc {
+
+const char* WebRtcVideoCodecErrorToString(int32_t error_code);
+
+} // namespace webrtc
+
+#endif // MODULES_VIDEO_CODING_INCLUDE_VIDEO_ERROR_CODES_UTILS_H_
diff --git a/third_party/libwebrtc/modules/video_coding/utility/simulcast_test_fixture_impl.cc b/third_party/libwebrtc/modules/video_coding/utility/simulcast_test_fixture_impl.cc
index c6e51e8068..ac076fde71 100644
--- a/third_party/libwebrtc/modules/video_coding/utility/simulcast_test_fixture_impl.cc
+++ b/third_party/libwebrtc/modules/video_coding/utility/simulcast_test_fixture_impl.cc
@@ -15,6 +15,8 @@
#include <memory>
#include <vector>
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/video/encoded_image.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_encoder.h"
@@ -258,8 +260,9 @@ SimulcastTestFixtureImpl::SimulcastTestFixtureImpl(
std::unique_ptr<VideoDecoderFactory> decoder_factory,
SdpVideoFormat video_format)
: codec_type_(PayloadStringToCodecType(video_format.name)) {
+ Environment env = CreateEnvironment();
encoder_ = encoder_factory->CreateVideoEncoder(video_format);
- decoder_ = decoder_factory->CreateVideoDecoder(video_format);
+ decoder_ = decoder_factory->Create(env, video_format);
SetUpCodec((codec_type_ == kVideoCodecVP8 || codec_type_ == kVideoCodecH264)
? kDefaultTemporalLayerProfile
: kNoTemporalLayerProfile);
diff --git a/third_party/libwebrtc/modules/video_coding/video_codec_initializer_unittest.cc b/third_party/libwebrtc/modules/video_coding/video_codec_initializer_unittest.cc
index b0edab6004..60ef7aece0 100644
--- a/third_party/libwebrtc/modules/video_coding/video_codec_initializer_unittest.cc
+++ b/third_party/libwebrtc/modules/video_coding/video_codec_initializer_unittest.cc
@@ -631,4 +631,25 @@ TEST_F(VideoCodecInitializerTest, Vp9TwoSpatialLayersBitratesAreConsistent) {
codec.spatialLayers[0].maxBitrate);
}
+TEST_F(VideoCodecInitializerTest, UpdatesVp9SpecificFieldsWithScalabilityMode) {
+ VideoEncoderConfig config;
+ config.codec_type = VideoCodecType::kVideoCodecVP9;
+ std::vector<VideoStream> streams = {DefaultStream()};
+ streams[0].scalability_mode = ScalabilityMode::kL2T3_KEY;
+
+ VideoCodec codec;
+ EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
+
+ EXPECT_EQ(codec.VP9()->numberOfSpatialLayers, 2u);
+ EXPECT_EQ(codec.VP9()->numberOfTemporalLayers, 3u);
+ EXPECT_EQ(codec.VP9()->interLayerPred, InterLayerPredMode::kOnKeyPic);
+
+ streams[0].scalability_mode = ScalabilityMode::kS3T1;
+ EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
+
+ EXPECT_EQ(codec.VP9()->numberOfSpatialLayers, 3u);
+ EXPECT_EQ(codec.VP9()->numberOfTemporalLayers, 1u);
+ EXPECT_EQ(codec.VP9()->interLayerPred, InterLayerPredMode::kOff);
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/video_coding/video_codec_interface_gn/moz.build b/third_party/libwebrtc/modules/video_coding/video_codec_interface_gn/moz.build
index 141def9090..c0d139fc6d 100644
--- a/third_party/libwebrtc/modules/video_coding/video_codec_interface_gn/moz.build
+++ b/third_party/libwebrtc/modules/video_coding/video_codec_interface_gn/moz.build
@@ -32,6 +32,7 @@ LOCAL_INCLUDES += [
UNIFIED_SOURCES += [
"/third_party/libwebrtc/modules/video_coding/include/video_codec_interface.cc",
+ "/third_party/libwebrtc/modules/video_coding/include/video_error_codes_utils.cc",
"/third_party/libwebrtc/modules/video_coding/video_coding_defines.cc"
]
diff --git a/third_party/libwebrtc/moz-patch-stack/0001.patch b/third_party/libwebrtc/moz-patch-stack/0001.patch
index e238c8c130..677a54762d 100644
--- a/third_party/libwebrtc/moz-patch-stack/0001.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0001.patch
@@ -413,7 +413,7 @@ index 3ff4b58a2e..ad0f3c9396 100644
bool RtpExtension::IsSupportedForVideo(absl::string_view uri) {
diff --git a/call/BUILD.gn b/call/BUILD.gn
-index 32ebc2e9cf..41ed587950 100644
+index 613b2b94d2..7c24834f1d 100644
--- a/call/BUILD.gn
+++ b/call/BUILD.gn
@@ -20,6 +20,7 @@ rtc_library("call_interfaces") {
@@ -1454,7 +1454,7 @@ index 5ec1fd4a83..e46e050609 100644
int64_t _lastProcessFrameTimeNanos RTC_GUARDED_BY(capture_checker_);
diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
-index e26169fd3d..5330eb7e8c 100644
+index 20c29abc7c..edbe781639 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
@@ -256,6 +256,7 @@ LibvpxVp9Encoder::LibvpxVp9Encoder(const cricket::VideoCodec& codec,
@@ -1465,7 +1465,7 @@ index e26169fd3d..5330eb7e8c 100644
is_flexible_mode_(false),
variable_framerate_experiment_(ParseVariableFramerateConfig(trials)),
variable_framerate_controller_(
-@@ -579,6 +580,7 @@ int LibvpxVp9Encoder::InitEncode(const VideoCodec* inst,
+@@ -580,6 +581,7 @@ int LibvpxVp9Encoder::InitEncode(const VideoCodec* inst,
force_key_frame_ = true;
pics_since_key_ = 0;
@@ -1473,7 +1473,7 @@ index e26169fd3d..5330eb7e8c 100644
scalability_mode_ = inst->GetScalabilityMode();
if (scalability_mode_.has_value()) {
-@@ -1151,6 +1153,14 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
+@@ -1167,6 +1169,14 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
config_changed_ = false;
}
@@ -1488,7 +1488,7 @@ index e26169fd3d..5330eb7e8c 100644
RTC_DCHECK_EQ(input_image.width(), raw_->d_w);
RTC_DCHECK_EQ(input_image.height(), raw_->d_h);
-@@ -1273,6 +1283,48 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
+@@ -1289,6 +1299,48 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -1538,7 +1538,7 @@ index e26169fd3d..5330eb7e8c 100644
absl::optional<int>* spatial_idx,
absl::optional<int>* temporal_idx,
diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
-index 0474e7bc17..1953923f81 100644
+index 3ccaa5fa52..ea4e5810ac 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
@@ -67,6 +67,9 @@ class LibvpxVp9Encoder : public VP9Encoder {
@@ -1560,7 +1560,7 @@ index 0474e7bc17..1953923f81 100644
std::unique_ptr<ScalableVideoController> svc_controller_;
absl::optional<ScalabilityMode> scalability_mode_;
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
-index ac30d8708b..84dc1718b4 100644
+index 2cf9c11316..b5e15ac2da 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -463,6 +463,12 @@ rtc_library("logging") {
diff --git a/third_party/libwebrtc/moz-patch-stack/0012.patch b/third_party/libwebrtc/moz-patch-stack/0012.patch
index 9a7e0c365c..670ac10210 100644
--- a/third_party/libwebrtc/moz-patch-stack/0012.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0012.patch
@@ -102,7 +102,7 @@ index b8f8ae9f7a..382511daeb 100644
#include <endian.h>
#else
diff --git a/rtc_base/physical_socket_server.cc b/rtc_base/physical_socket_server.cc
-index b0af1c20ce..b13d1aa21b 100644
+index c3bc1814a1..01286d7150 100644
--- a/rtc_base/physical_socket_server.cc
+++ b/rtc_base/physical_socket_server.cc
@@ -73,7 +73,10 @@ typedef void* SockOptArg;
@@ -117,7 +117,7 @@ index b0af1c20ce..b13d1aa21b 100644
int64_t GetSocketRecvTimestamp(int socket) {
struct timeval tv_ioctl;
-@@ -641,7 +644,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
+@@ -666,7 +669,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
*slevel = IPPROTO_IP;
*sopt = IP_DONTFRAGMENT;
break;
diff --git a/third_party/libwebrtc/moz-patch-stack/0013.patch b/third_party/libwebrtc/moz-patch-stack/0013.patch
index 969a3807d3..9b6662effd 100644
--- a/third_party/libwebrtc/moz-patch-stack/0013.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0013.patch
@@ -15,10 +15,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2b079067648bfe0d0
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rtc_base/physical_socket_server.cc b/rtc_base/physical_socket_server.cc
-index b13d1aa21b..f0427b1081 100644
+index 01286d7150..bdea16668f 100644
--- a/rtc_base/physical_socket_server.cc
+++ b/rtc_base/physical_socket_server.cc
-@@ -1429,7 +1429,7 @@ bool PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) {
+@@ -1454,7 +1454,7 @@ bool PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) {
int fd = pdispatcher->GetDescriptor();
// "select"ing a file descriptor that is equal to or larger than
// FD_SETSIZE will result in undefined behavior.
diff --git a/third_party/libwebrtc/moz-patch-stack/0021.patch b/third_party/libwebrtc/moz-patch-stack/0021.patch
index 3dd0c298a1..fe4bbae082 100644
--- a/third_party/libwebrtc/moz-patch-stack/0021.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0021.patch
@@ -10,10 +10,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/1387b2c480b55ecca
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
-index 5afd105949..9b77388f10 100644
+index 3466080c83..4c06aca5ad 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
-@@ -46,7 +46,7 @@ const char kVp8PostProcArmFieldTrial[] = "WebRTC-VP8-Postproc-Config-Arm";
+@@ -48,7 +48,7 @@ const char kVp8PostProcArmFieldTrial[] = "WebRTC-VP8-Postproc-Config-Arm";
const char kVp8PostProcFieldTrial[] = "WebRTC-VP8-Postproc-Config";
#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || \
diff --git a/third_party/libwebrtc/moz-patch-stack/0023.patch b/third_party/libwebrtc/moz-patch-stack/0023.patch
index 43ee2f8941..6af712dfe3 100644
--- a/third_party/libwebrtc/moz-patch-stack/0023.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0023.patch
@@ -78,7 +78,7 @@ index 23a8f4f3f3..b2c206d775 100644
#include <string.h>
#include <sys/ioctl.h>
diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc
-index 7a70c2ff88..00cede01cb 100644
+index 377c1ec878..a2e362bb94 100644
--- a/modules/video_capture/linux/video_capture_v4l2.cc
+++ b/modules/video_capture/linux/video_capture_v4l2.cc
@@ -12,7 +12,7 @@
@@ -105,7 +105,7 @@ index 7a70c2ff88..00cede01cb 100644
#include <new>
#include <string>
-@@ -405,16 +413,13 @@ bool VideoCaptureModuleV4L2::CaptureProcess() {
+@@ -414,16 +422,13 @@ bool VideoCaptureModuleV4L2::CaptureProcess() {
RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
int retVal = 0;
@@ -127,7 +127,7 @@ index 7a70c2ff88..00cede01cb 100644
{
MutexLock lock(&capture_lock_);
-@@ -424,12 +429,12 @@ bool VideoCaptureModuleV4L2::CaptureProcess() {
+@@ -433,12 +438,12 @@ bool VideoCaptureModuleV4L2::CaptureProcess() {
}
if (retVal < 0 && errno != EINTR) { // continue if interrupted
diff --git a/third_party/libwebrtc/moz-patch-stack/0030.patch b/third_party/libwebrtc/moz-patch-stack/0030.patch
index 9e8bd7b2fd..b63cba6033 100644
--- a/third_party/libwebrtc/moz-patch-stack/0030.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0030.patch
@@ -206,7 +206,7 @@ index 571049f3e4..f393179bbb 100644
} else {
deps += [
diff --git a/api/BUILD.gn b/api/BUILD.gn
-index 6af4fa5517..1628660c3c 100644
+index 0c982a2ac6..4549c02b7a 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -40,6 +40,9 @@ rtc_source_set("enable_media") {
@@ -290,7 +290,7 @@ index 6af4fa5517..1628660c3c 100644
visibility = [ "*" ]
cflags = []
sources = [
-@@ -387,6 +414,7 @@ rtc_library("libjingle_peerconnection_api") {
+@@ -389,6 +416,7 @@ rtc_library("libjingle_peerconnection_api") {
"//third_party/abseil-cpp/absl/types:optional",
]
}
@@ -298,7 +298,7 @@ index 6af4fa5517..1628660c3c 100644
rtc_source_set("frame_transformer_interface") {
visibility = [ "*" ]
-@@ -560,6 +588,7 @@ rtc_source_set("peer_network_dependencies") {
+@@ -562,6 +590,7 @@ rtc_source_set("peer_network_dependencies") {
}
rtc_source_set("peer_connection_quality_test_fixture_api") {
@@ -306,7 +306,7 @@ index 6af4fa5517..1628660c3c 100644
visibility = [ "*" ]
testonly = true
sources = [ "test/peerconnection_quality_test_fixture.h" ]
-@@ -609,6 +638,7 @@ rtc_source_set("peer_connection_quality_test_fixture_api") {
+@@ -611,6 +640,7 @@ rtc_source_set("peer_connection_quality_test_fixture_api") {
"//third_party/abseil-cpp/absl/types:optional",
]
}
@@ -314,7 +314,7 @@ index 6af4fa5517..1628660c3c 100644
rtc_source_set("frame_generator_api") {
visibility = [ "*" ]
-@@ -728,6 +758,7 @@ rtc_library("create_frame_generator") {
+@@ -730,6 +760,7 @@ rtc_library("create_frame_generator") {
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
@@ -322,7 +322,7 @@ index 6af4fa5517..1628660c3c 100644
rtc_library("create_peer_connection_quality_test_frame_generator") {
visibility = [ "*" ]
testonly = true
-@@ -744,6 +775,7 @@ rtc_library("create_peer_connection_quality_test_frame_generator") {
+@@ -746,6 +777,7 @@ rtc_library("create_peer_connection_quality_test_frame_generator") {
]
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
@@ -330,7 +330,7 @@ index 6af4fa5517..1628660c3c 100644
rtc_source_set("libjingle_logging_api") {
visibility = [ "*" ]
-@@ -924,6 +956,7 @@ rtc_source_set("refcountedbase") {
+@@ -925,6 +957,7 @@ rtc_source_set("refcountedbase") {
]
}
@@ -338,7 +338,7 @@ index 6af4fa5517..1628660c3c 100644
rtc_library("ice_transport_factory") {
visibility = [ "*" ]
sources = [
-@@ -942,6 +975,7 @@ rtc_library("ice_transport_factory") {
+@@ -948,6 +981,7 @@ rtc_library("ice_transport_factory") {
"rtc_event_log:rtc_event_log",
]
}
@@ -450,10 +450,10 @@ index 1b9425d719..afdf47dfc9 100644
rtc_library("default_task_queue_factory") {
visibility = [ "*" ]
diff --git a/api/transport/BUILD.gn b/api/transport/BUILD.gn
-index 84a0968ee9..c0209bf0d0 100644
+index f7a27c5899..21559815ca 100644
--- a/api/transport/BUILD.gn
+++ b/api/transport/BUILD.gn
-@@ -91,6 +91,7 @@ rtc_source_set("sctp_transport_factory_interface") {
+@@ -97,6 +97,7 @@ rtc_source_set("sctp_transport_factory_interface") {
}
rtc_source_set("stun_types") {
@@ -461,7 +461,7 @@ index 84a0968ee9..c0209bf0d0 100644
visibility = [ "*" ]
sources = [
"stun.cc",
-@@ -111,6 +112,7 @@ rtc_source_set("stun_types") {
+@@ -117,6 +118,7 @@ rtc_source_set("stun_types") {
]
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
@@ -470,7 +470,7 @@ index 84a0968ee9..c0209bf0d0 100644
if (rtc_include_tests) {
rtc_source_set("test_feedback_generator_interface") {
diff --git a/call/BUILD.gn b/call/BUILD.gn
-index 41ed587950..cca88ea7bb 100644
+index 7c24834f1d..2c761bf001 100644
--- a/call/BUILD.gn
+++ b/call/BUILD.gn
@@ -44,7 +44,7 @@ rtc_library("call_interfaces") {
@@ -482,7 +482,7 @@ index 41ed587950..cca88ea7bb 100644
"../api:scoped_refptr",
"../api:transport_api",
"../api/adaptation:resource_adaptation_api",
-@@ -345,6 +345,16 @@ rtc_library("call") {
+@@ -346,6 +346,16 @@ rtc_library("call") {
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
@@ -499,7 +499,7 @@ index 41ed587950..cca88ea7bb 100644
}
rtc_source_set("receive_stream_interface") {
-@@ -372,7 +382,7 @@ rtc_library("video_stream_api") {
+@@ -373,7 +383,7 @@ rtc_library("video_stream_api") {
"../api:frame_transformer_interface",
"../api:rtp_headers",
"../api:rtp_parameters",
@@ -522,7 +522,7 @@ index 9c2fad652f..f9e49db574 100644
#include "call/audio_sender.h"
#include "call/rtp_config.h"
diff --git a/call/video_send_stream.h b/call/video_send_stream.h
-index c305d60bcc..2b4ea5b66a 100644
+index 2c3fe55f8d..ca900823c8 100644
--- a/call/video_send_stream.h
+++ b/call/video_send_stream.h
@@ -23,7 +23,7 @@
@@ -581,7 +581,7 @@ index 0000000000..f6ff7f218f
+ #endif
+#endif
diff --git a/media/BUILD.gn b/media/BUILD.gn
-index 2a9cbcbff4..44638d562e 100644
+index 2530e5ab4d..7a489f0c43 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -64,7 +64,7 @@ rtc_library("rtc_media_base") {
@@ -674,7 +674,7 @@ index 2a9cbcbff4..44638d562e 100644
rtc_library("rtc_simulcast_encoder_adapter") {
visibility = [ "*" ]
-@@ -399,6 +418,12 @@ rtc_library("rtc_internal_video_codecs") {
+@@ -400,6 +419,12 @@ rtc_library("rtc_internal_video_codecs") {
"../system_wrappers:field_trial",
"../test:fake_video_codecs",
]
@@ -687,7 +687,7 @@ index 2a9cbcbff4..44638d562e 100644
if (enable_libaom) {
defines += [ "RTC_USE_LIBAOM_AV1_ENCODER" ]
-@@ -424,6 +449,14 @@ rtc_library("rtc_internal_video_codecs") {
+@@ -425,6 +450,14 @@ rtc_library("rtc_internal_video_codecs") {
"engine/multiplex_codec_factory.cc",
"engine/multiplex_codec_factory.h",
]
@@ -742,7 +742,7 @@ index 1c08382969..ff69ea62dc 100644
using webrtc::FrameDecryptorInterface;
using webrtc::FrameEncryptorInterface;
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
-index 5de99efa45..ddd1fd2656 100644
+index 8b23955d5b..a49df7e7d2 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -553,7 +553,7 @@ rtc_library("webrtc_opus_wrapper") {
@@ -1032,7 +1032,7 @@ index b583814ebe..aabf545728 100644
"/config/external/nspr",
"/nsprpub/lib/ds",
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
-index 84dc1718b4..7372b539c4 100644
+index b5e15ac2da..deb124d3af 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -327,6 +327,7 @@ rtc_library("sample_counter") {
@@ -1061,7 +1061,7 @@ index 84dc1718b4..7372b539c4 100644
if (rtc_build_json) {
deps += [ "//third_party/jsoncpp" ]
} else {
-@@ -1227,6 +1231,7 @@ if (!build_with_chromium) {
+@@ -1228,6 +1232,7 @@ if (!build_with_chromium) {
}
rtc_library("network") {
@@ -1069,7 +1069,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"network.cc",
-@@ -1265,16 +1270,20 @@ rtc_library("network") {
+@@ -1266,16 +1271,20 @@ rtc_library("network") {
deps += [ ":win32" ]
}
}
@@ -1090,7 +1090,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"net_helper.cc",
-@@ -1283,8 +1292,10 @@ rtc_library("net_helper") {
+@@ -1284,8 +1293,10 @@ rtc_library("net_helper") {
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
deps = [ "system:rtc_export" ]
}
@@ -1101,7 +1101,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"socket_adapters.cc",
-@@ -1304,6 +1315,7 @@ rtc_library("socket_adapters") {
+@@ -1305,6 +1316,7 @@ rtc_library("socket_adapters") {
]
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
@@ -1109,7 +1109,7 @@ index 84dc1718b4..7372b539c4 100644
rtc_library("network_route") {
sources = [
-@@ -1318,6 +1330,7 @@ rtc_library("network_route") {
+@@ -1319,6 +1331,7 @@ rtc_library("network_route") {
}
rtc_library("async_tcp_socket") {
@@ -1117,7 +1117,7 @@ index 84dc1718b4..7372b539c4 100644
sources = [
"async_tcp_socket.cc",
"async_tcp_socket.h",
-@@ -1335,8 +1348,10 @@ rtc_library("async_tcp_socket") {
+@@ -1336,8 +1349,10 @@ rtc_library("async_tcp_socket") {
"network:sent_packet",
]
}
@@ -1128,7 +1128,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"async_udp_socket.cc",
-@@ -1360,8 +1375,10 @@ rtc_library("async_udp_socket") {
+@@ -1361,8 +1376,10 @@ rtc_library("async_udp_socket") {
]
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
@@ -1139,7 +1139,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"async_packet_socket.cc",
-@@ -1381,6 +1398,7 @@ rtc_library("async_packet_socket") {
+@@ -1382,6 +1399,7 @@ rtc_library("async_packet_socket") {
"third_party/sigslot",
]
}
@@ -1147,7 +1147,7 @@ index 84dc1718b4..7372b539c4 100644
if (rtc_include_tests) {
rtc_library("async_packet_socket_unittest") {
-@@ -1408,6 +1426,7 @@ rtc_library("dscp") {
+@@ -1409,6 +1427,7 @@ rtc_library("dscp") {
}
rtc_library("proxy_info") {
@@ -1155,7 +1155,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"proxy_info.cc",
-@@ -1418,6 +1437,7 @@ rtc_library("proxy_info") {
+@@ -1419,6 +1438,7 @@ rtc_library("proxy_info") {
":socket_address",
]
}
@@ -1163,7 +1163,7 @@ index 84dc1718b4..7372b539c4 100644
rtc_library("file_rotating_stream") {
sources = [
-@@ -1446,6 +1466,7 @@ rtc_library("data_rate_limiter") {
+@@ -1447,6 +1467,7 @@ rtc_library("data_rate_limiter") {
}
rtc_library("unique_id_generator") {
@@ -1171,7 +1171,7 @@ index 84dc1718b4..7372b539c4 100644
sources = [
"unique_id_generator.cc",
"unique_id_generator.h",
-@@ -1460,6 +1481,7 @@ rtc_library("unique_id_generator") {
+@@ -1461,6 +1482,7 @@ rtc_library("unique_id_generator") {
]
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
@@ -1179,7 +1179,7 @@ index 84dc1718b4..7372b539c4 100644
rtc_library("crc32") {
sources = [
-@@ -1487,6 +1509,7 @@ rtc_library("stream") {
+@@ -1488,6 +1510,7 @@ rtc_library("stream") {
}
rtc_library("rtc_certificate_generator") {
@@ -1187,7 +1187,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"rtc_certificate_generator.cc",
-@@ -1504,8 +1527,10 @@ rtc_library("rtc_certificate_generator") {
+@@ -1505,8 +1528,10 @@ rtc_library("rtc_certificate_generator") {
"//third_party/abseil-cpp/absl/types:optional",
]
}
@@ -1198,7 +1198,7 @@ index 84dc1718b4..7372b539c4 100644
visibility = [ "*" ]
sources = [
"helpers.cc",
-@@ -1606,6 +1631,7 @@ rtc_library("ssl") {
+@@ -1607,6 +1632,7 @@ rtc_library("ssl") {
deps += [ ":win32" ]
}
}
@@ -1206,7 +1206,7 @@ index 84dc1718b4..7372b539c4 100644
rtc_library("crypt_string") {
sources = [
-@@ -1615,6 +1641,7 @@ rtc_library("crypt_string") {
+@@ -1616,6 +1642,7 @@ rtc_library("crypt_string") {
}
rtc_library("http_common") {
@@ -1214,7 +1214,7 @@ index 84dc1718b4..7372b539c4 100644
sources = [
"http_common.cc",
"http_common.h",
-@@ -1631,6 +1658,7 @@ rtc_library("http_common") {
+@@ -1632,6 +1659,7 @@ rtc_library("http_common") {
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
@@ -1222,7 +1222,7 @@ index 84dc1718b4..7372b539c4 100644
rtc_source_set("gtest_prod") {
sources = [ "gtest_prod_util.h" ]
-@@ -2191,7 +2219,7 @@ if (rtc_include_tests) {
+@@ -2194,7 +2222,7 @@ if (rtc_include_tests) {
}
}
@@ -1245,7 +1245,7 @@ index 77f5139a2f..486b37590c 100644
deps += [
"..:logging",
diff --git a/test/BUILD.gn b/test/BUILD.gn
-index 2a37b78c7c..75d8d9f3a8 100644
+index ed5dc5173d..bf98ec7d3a 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -239,6 +239,7 @@ rtc_library("audio_test_common") {
@@ -1287,7 +1287,7 @@ index 2a37b78c7c..75d8d9f3a8 100644
sources += [ "testsupport/jpeg_frame_writer.cc" ]
} else {
sources += [ "testsupport/jpeg_frame_writer_ios.cc" ]
-@@ -1331,6 +1339,7 @@ if (!build_with_chromium) {
+@@ -1313,6 +1321,7 @@ if (!build_with_chromium) {
}
}
@@ -1295,7 +1295,7 @@ index 2a37b78c7c..75d8d9f3a8 100644
if (!build_with_chromium && is_android) {
rtc_android_library("native_test_java") {
testonly = true
-@@ -1344,6 +1353,7 @@ if (!build_with_chromium && is_android) {
+@@ -1326,6 +1335,7 @@ if (!build_with_chromium && is_android) {
]
}
}
@@ -1304,7 +1304,7 @@ index 2a37b78c7c..75d8d9f3a8 100644
rtc_library("call_config_utils") {
testonly = true
diff --git a/video/BUILD.gn b/video/BUILD.gn
-index 0891a31f7b..2d6d8ab10c 100644
+index e4e1f275f4..b97d4af5bb 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -17,7 +17,7 @@ rtc_library("video_stream_encoder_interface") {
diff --git a/third_party/libwebrtc/moz-patch-stack/0032.patch b/third_party/libwebrtc/moz-patch-stack/0032.patch
index 8ffa882737..210ce19212 100644
--- a/third_party/libwebrtc/moz-patch-stack/0032.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0032.patch
@@ -9,19 +9,20 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/ef548d7758c7de6e7
1 file changed, 2 insertions(+)
diff --git a/media/engine/internal_decoder_factory.cc b/media/engine/internal_decoder_factory.cc
-index e761fd60c8..001c666313 100644
+index e623aeb43a..139f49d420 100644
--- a/media/engine/internal_decoder_factory.cc
+++ b/media/engine/internal_decoder_factory.cc
-@@ -49,12 +49,14 @@ std::vector<SdpVideoFormat> InternalDecoderFactory::GetSupportedFormats()
+@@ -49,6 +49,7 @@ std::vector<SdpVideoFormat> InternalDecoderFactory::GetSupportedFormats()
for (const SdpVideoFormat& h264_format : SupportedH264DecoderCodecs())
formats.push_back(h264_format);
+#if !defined(WEBRTC_MOZILLA_BUILD)
if (kDav1dIsIncluded) {
formats.push_back(SdpVideoFormat(cricket::kAv1CodecName));
- formats.push_back(SdpVideoFormat(
- cricket::kAv1CodecName,
- {{kAV1FmtpProfile, AV1ProfileToString(AV1Profile::kProfile1).data()}}));
+ formats.push_back(
+@@ -56,6 +57,7 @@ std::vector<SdpVideoFormat> InternalDecoderFactory::GetSupportedFormats()
+ {{cricket::kAv1FmtpProfile,
+ AV1ProfileToString(AV1Profile::kProfile1).data()}}));
}
+#endif
diff --git a/third_party/libwebrtc/moz-patch-stack/0033.patch b/third_party/libwebrtc/moz-patch-stack/0033.patch
index 62695eeb23..745efd36a7 100644
--- a/third_party/libwebrtc/moz-patch-stack/0033.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0033.patch
@@ -15,10 +15,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/d380a43d59f4f7cbc
4 files changed, 35 insertions(+)
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
-index 3701eafd6f..8dc78b18fa 100644
+index 59b0ea5b5e..64bc15ab4e 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
-@@ -432,6 +432,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats(
+@@ -427,6 +427,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats(
stats.target_bitrate_bps = channel_send_->GetTargetBitrate();
webrtc::CallSendStatistics call_stats = channel_send_->GetRTCPStatistics();
diff --git a/third_party/libwebrtc/moz-patch-stack/0034.patch b/third_party/libwebrtc/moz-patch-stack/0034.patch
index 3dfd2e8007..78234690b8 100644
--- a/third_party/libwebrtc/moz-patch-stack/0034.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0034.patch
@@ -7,8 +7,8 @@ Differential Revision: https://phabricator.services.mozilla.com/D105774
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/7330681cf4de6d8dd868cc661cbdd6679bbc07b3
---
call/video_receive_stream.h | 3 +++
- video/rtp_video_stream_receiver2.cc | 3 +--
- 2 files changed, 4 insertions(+), 2 deletions(-)
+ video/rtp_video_stream_receiver2.cc | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h
index 95f1a47f4e..a1fc204e7c 100644
@@ -25,17 +25,15 @@ index 95f1a47f4e..a1fc204e7c 100644
// See LntfConfig for description.
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index badb942cd4..1f4cc5b6be 100644
+index 624f699b73..3ed4e5bb18 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
-@@ -296,9 +296,8 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
- frames_decryptable_(false),
- absolute_capture_time_interpolator_(clock) {
- packet_sequence_checker_.Detach();
-- constexpr bool remb_candidate = true;
- if (packet_router_)
-- packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(), remb_candidate);
-+ packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(), config_.rtp.remb);
-
- RTC_DCHECK(config_.rtp.rtcp_mode != RtcpMode::kOff)
- << "A stream should not be configured with RTCP disabled. This value is "
+@@ -1258,7 +1258,7 @@ void RtpVideoStreamReceiver2::StartReceive() {
+ // Change REMB candidate egibility.
+ packet_router_->RemoveReceiveRtpModule(rtp_rtcp_.get());
+ packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(),
+- /*remb_candidate=*/true);
++ /*remb_candidate=*/config_.rtp.remb);
+ }
+ receiving_ = true;
+ }
diff --git a/third_party/libwebrtc/moz-patch-stack/0042.patch b/third_party/libwebrtc/moz-patch-stack/0042.patch
index 7ffec6a12e..873e46f6d4 100644
--- a/third_party/libwebrtc/moz-patch-stack/0042.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0042.patch
@@ -43,7 +43,7 @@ index 415ad0640a..1e8cff5441 100644
} // namespace
diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc
-index 8367b00113..aff21fa72a 100644
+index 17cf859ed8..b743b550ba 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -105,7 +105,8 @@ class ChannelReceive : public ChannelReceiveInterface,
@@ -66,7 +66,7 @@ index 8367b00113..aff21fa72a 100644
: worker_thread_(TaskQueueBase::Current()),
event_log_(rtc_event_log),
rtp_receive_statistics_(ReceiveStatistics::Create(clock)),
-@@ -587,6 +589,7 @@ ChannelReceive::ChannelReceive(
+@@ -580,6 +582,7 @@ ChannelReceive::ChannelReceive(
configuration.local_media_ssrc = local_ssrc;
configuration.rtcp_packet_type_counter_observer = this;
configuration.non_sender_rtt_measurement = enable_non_sender_rtt;
@@ -74,7 +74,7 @@ index 8367b00113..aff21fa72a 100644
if (frame_transformer)
InitFrameTransformerDelegate(std::move(frame_transformer));
-@@ -1129,13 +1132,15 @@ std::unique_ptr<ChannelReceiveInterface> CreateChannelReceive(
+@@ -1122,13 +1125,15 @@ std::unique_ptr<ChannelReceiveInterface> CreateChannelReceive(
absl::optional<AudioCodecPairId> codec_pair_id,
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
const webrtc::CryptoOptions& crypto_options,
@@ -269,7 +269,7 @@ index 0bdd389795..2c56dccd2a 100644
TransportFeedbackObserver* transport_feedback_callback = nullptr;
VideoBitrateAllocationObserver* bitrate_allocation_observer = nullptr;
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index 1f4cc5b6be..9694f1d0c1 100644
+index 3ed4e5bb18..a3cfd903f4 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
@@ -83,7 +83,8 @@ std::unique_ptr<ModuleRtpRtcpImpl2> CreateRtpRtcpModule(
diff --git a/third_party/libwebrtc/moz-patch-stack/0044.patch b/third_party/libwebrtc/moz-patch-stack/0044.patch
index e38e7de18f..cec69da917 100644
--- a/third_party/libwebrtc/moz-patch-stack/0044.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0044.patch
@@ -15,10 +15,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/edac9d01a9ac7594f
3 files changed, 24 insertions(+)
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index 9694f1d0c1..79ce90794e 100644
+index a3cfd903f4..63642c5f2a 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
-@@ -1062,6 +1062,16 @@ absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
+@@ -1067,6 +1067,16 @@ absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
return absl::nullopt;
}
@@ -53,7 +53,7 @@ index d436aa38a7..4a93e53356 100644
// Implements RtpVideoFrameReceiver.
void ManageFrame(std::unique_ptr<RtpFrameObject> frame) override;
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
-index 9e095064ba..3d0534bf10 100644
+index 7d307c6d2c..03d3d7ce2f 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -568,6 +568,14 @@ VideoReceiveStreamInterface::Stats VideoReceiveStream2::GetStats() const {
diff --git a/third_party/libwebrtc/moz-patch-stack/0050.patch b/third_party/libwebrtc/moz-patch-stack/0050.patch
index a3c23bc40a..fb6ae300e3 100644
--- a/third_party/libwebrtc/moz-patch-stack/0050.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0050.patch
@@ -159,10 +159,10 @@ index 2c56dccd2a..f196d11b58 100644
// Within this list, the sender-source SSRC pair is unique and per-pair the
// ReportBlockData represents the latest Report Block that was received for
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index 79ce90794e..029e7a7405 100644
+index 63642c5f2a..fd24060335 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
-@@ -1067,9 +1067,10 @@ absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
+@@ -1072,9 +1072,10 @@ absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
// seem to be any support for these stats right now. So, we hack this in.
void RtpVideoStreamReceiver2::RemoteRTCPSenderInfo(
uint32_t* packet_count, uint32_t* octet_count,
@@ -190,7 +190,7 @@ index 4a93e53356..00b17a77bd 100644
private:
// Implements RtpVideoFrameReceiver.
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
-index 3d0534bf10..f135f42f3b 100644
+index 03d3d7ce2f..a658255208 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -574,7 +574,8 @@ VideoReceiveStreamInterface::Stats VideoReceiveStream2::GetStats() const {
diff --git a/third_party/libwebrtc/moz-patch-stack/0052.patch b/third_party/libwebrtc/moz-patch-stack/0052.patch
index 98c4d5dafd..b1fb3153dd 100644
--- a/third_party/libwebrtc/moz-patch-stack/0052.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0052.patch
@@ -55,18 +55,18 @@ index a511eda7bd..75a4a1cac0 100644
DegradedCall::~DegradedCall() {
RTC_DCHECK_RUN_ON(call_->worker_thread());
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
-index a77e472ec1..a5bf88e547 100644
+index 24a49024c8..4deabdf7ff 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -50,7 +50,7 @@ std::unique_ptr<NetEq> CreateNetEq(
AcmReceiver::Config::Config(
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)
-- : clock(*Clock::GetRealTimeClock()), decoder_factory(decoder_factory) {
-+ : clock(*Clock::GetRealTimeClockRaw()), decoder_factory(decoder_factory) {
- // Post-decode VAD is disabled by default in NetEq, however, Audio
- // Conference Mixer relies on VAD decisions and fails without them.
- neteq_config.enable_post_decode_vad = true;
+- : clock(*Clock::GetRealTimeClock()), decoder_factory(decoder_factory) {}
++ : clock(*Clock::GetRealTimeClockRaw()), decoder_factory(decoder_factory) {}
+
+ AcmReceiver::Config::Config(const Config&) = default;
+ AcmReceiver::Config::~Config() = default;
diff --git a/modules/rtp_rtcp/include/flexfec_receiver.h b/modules/rtp_rtcp/include/flexfec_receiver.h
index a869c8ad41..b6a33882d1 100644
--- a/modules/rtp_rtcp/include/flexfec_receiver.h
diff --git a/third_party/libwebrtc/moz-patch-stack/0054.patch b/third_party/libwebrtc/moz-patch-stack/0054.patch
index f07a706f54..197ae0dc4e 100644
--- a/third_party/libwebrtc/moz-patch-stack/0054.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0054.patch
@@ -14,7 +14,7 @@ Subject: Bug 1766646 - (fix) breakout Call::Stats and SharedModuleThread into
create mode 100644 call/call_basic_stats.h
diff --git a/call/BUILD.gn b/call/BUILD.gn
-index cca88ea7bb..50a8257631 100644
+index 2c761bf001..985a3a4e04 100644
--- a/call/BUILD.gn
+++ b/call/BUILD.gn
@@ -33,6 +33,12 @@ rtc_library("call_interfaces") {
diff --git a/third_party/libwebrtc/moz-patch-stack/0059.patch b/third_party/libwebrtc/moz-patch-stack/0059.patch
index 018d4ac255..1ae0f2a8d8 100644
--- a/third_party/libwebrtc/moz-patch-stack/0059.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0059.patch
@@ -8,10 +8,10 @@ Subject: Bug 1766646 - (fix-f137b75a4d) specify default constructor on
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
-index 95f821352a..8e1a3c4698 100644
+index 7deeb7ad64..2f47ee0f18 100644
--- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
+++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
-@@ -546,7 +546,7 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
+@@ -549,7 +549,7 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
if (!enabled.Get()) {
return config;
}
diff --git a/third_party/libwebrtc/moz-patch-stack/0061.patch b/third_party/libwebrtc/moz-patch-stack/0061.patch
index cc24d61d85..ce88d2599a 100644
--- a/third_party/libwebrtc/moz-patch-stack/0061.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0061.patch
@@ -10,10 +10,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2e4867d8cc9813869
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc
-index 00cede01cb..97cd9a70eb 100644
+index a2e362bb94..6d8a5e463f 100644
--- a/modules/video_capture/linux/video_capture_v4l2.cc
+++ b/modules/video_capture/linux/video_capture_v4l2.cc
-@@ -296,8 +296,8 @@ int32_t VideoCaptureModuleV4L2::StartCapture(
+@@ -303,8 +303,8 @@ int32_t VideoCaptureModuleV4L2::StartCapture(
if (_captureThread.empty()) {
quit_ = false;
_captureThread = rtc::PlatformThread::SpawnJoinable(
diff --git a/third_party/libwebrtc/moz-patch-stack/0064.patch b/third_party/libwebrtc/moz-patch-stack/0064.patch
index e379af2487..e1655d02f1 100644
--- a/third_party/libwebrtc/moz-patch-stack/0064.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0064.patch
@@ -29,7 +29,7 @@ index afdf47dfc9..b9bc81171f 100644
rtc_library("task_queue_test") {
visibility = [ "*" ]
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
-index 7372b539c4..57a9c11f01 100644
+index deb124d3af..eb88039d33 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -743,10 +743,14 @@ if (is_mac || is_ios) {
diff --git a/third_party/libwebrtc/moz-patch-stack/0066.patch b/third_party/libwebrtc/moz-patch-stack/0066.patch
index 01f4a41c95..6e27ca0b7d 100644
--- a/third_party/libwebrtc/moz-patch-stack/0066.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0066.patch
@@ -26,7 +26,7 @@ index f595a2951a..7feca08e60 100644
deps += [ "logging:rtc_event_log_proto" ]
}
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
-index e28bdcc5a2..586d4d1911 100644
+index a044c469e0..e973448f05 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -533,6 +533,7 @@ if (is_ios || is_mac) {
@@ -69,7 +69,7 @@ index e28bdcc5a2..586d4d1911 100644
rtc_library("videocodec_objc") {
visibility = [ "*" ]
configs += [ "..:no_global_constructors" ]
-@@ -1729,5 +1734,6 @@ if (is_ios || is_mac) {
+@@ -1744,5 +1749,6 @@ if (is_ios || is_mac) {
"VideoToolbox.framework",
]
}
diff --git a/third_party/libwebrtc/moz-patch-stack/0068.patch b/third_party/libwebrtc/moz-patch-stack/0068.patch
index 38bae4d1e8..1721274081 100644
--- a/third_party/libwebrtc/moz-patch-stack/0068.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0068.patch
@@ -215,7 +215,7 @@ index 8e4941f961..7bcfc7c057 100644
int current_delay_ms,
int target_delay_ms,
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index 029e7a7405..26bd60057d 100644
+index fd24060335..65e45e38f7 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
@@ -244,6 +244,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
@@ -234,7 +234,7 @@ index 029e7a7405..26bd60057d 100644
packet_buffer_(kPacketBufferStartSize,
PacketBufferMaxSize(field_trials_)),
reference_finder_(std::make_unique<RtpFrameReferenceFinder>()),
-@@ -1250,7 +1252,8 @@ void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
+@@ -1255,7 +1257,8 @@ void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
int64_t unwrapped_rtp_seq_num = rtp_seq_num_unwrapper_.Unwrap(seq_num);
packet_infos_.erase(packet_infos_.begin(),
packet_infos_.upper_bound(unwrapped_rtp_seq_num));
@@ -273,7 +273,7 @@ index 00b17a77bd..b942cb97a6 100644
RTC_GUARDED_BY(packet_sequence_checker_);
UniqueTimestampCounter frame_counter_
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
-index f135f42f3b..8675ab9979 100644
+index a658255208..ce65ec4186 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -209,6 +209,7 @@ VideoReceiveStream2::VideoReceiveStream2(
diff --git a/third_party/libwebrtc/moz-patch-stack/0069.patch b/third_party/libwebrtc/moz-patch-stack/0069.patch
index 54357d2957..3825a74c75 100644
--- a/third_party/libwebrtc/moz-patch-stack/0069.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0069.patch
@@ -30,10 +30,10 @@ index 8ef4d553ad..a0f19999d8 100644
void ReceiveStatisticsProxy::OnPreDecode(VideoCodecType codec_type, int qp) {
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index 26bd60057d..daf601c6cb 100644
+index 65e45e38f7..49b7d06419 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
-@@ -1253,7 +1253,9 @@ void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
+@@ -1258,7 +1258,9 @@ void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
packet_infos_.erase(packet_infos_.begin(),
packet_infos_.upper_bound(unwrapped_rtp_seq_num));
uint32_t num_packets_cleared = packet_buffer_.ClearTo(seq_num);
diff --git a/third_party/libwebrtc/moz-patch-stack/0070.patch b/third_party/libwebrtc/moz-patch-stack/0070.patch
index 842b9da193..7ffa16e0df 100644
--- a/third_party/libwebrtc/moz-patch-stack/0070.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0070.patch
@@ -166,7 +166,7 @@ index a0f19999d8..1764308c0a 100644
}
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index daf601c6cb..5e563d001c 100644
+index 49b7d06419..d9f7fcbe95 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
@@ -44,6 +44,7 @@
@@ -177,7 +177,7 @@ index daf601c6cb..5e563d001c 100644
#include "system_wrappers/include/metrics.h"
#include "system_wrappers/include/ntp_time.h"
-@@ -1254,6 +1255,9 @@ void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
+@@ -1259,6 +1260,9 @@ void RtpVideoStreamReceiver2::FrameDecoded(int64_t picture_id) {
packet_infos_.upper_bound(unwrapped_rtp_seq_num));
uint32_t num_packets_cleared = packet_buffer_.ClearTo(seq_num);
if (num_packets_cleared > 0) {
diff --git a/third_party/libwebrtc/moz-patch-stack/0071.patch b/third_party/libwebrtc/moz-patch-stack/0071.patch
index 5495f3d035..160ba45026 100644
--- a/third_party/libwebrtc/moz-patch-stack/0071.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0071.patch
@@ -9,10 +9,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/5b2a7894ef1cf096d
1 file changed, 6 insertions(+)
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index 5e563d001c..4df65659f9 100644
+index d9f7fcbe95..d13e4448b4 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
-@@ -740,6 +740,12 @@ void RtpVideoStreamReceiver2::OnRtpPacket(const RtpPacketReceived& packet) {
+@@ -744,6 +744,12 @@ void RtpVideoStreamReceiver2::OnRtpPacket(const RtpPacketReceived& packet) {
void RtpVideoStreamReceiver2::RequestKeyFrame() {
RTC_DCHECK_RUN_ON(&worker_task_checker_);
diff --git a/third_party/libwebrtc/moz-patch-stack/0075.patch b/third_party/libwebrtc/moz-patch-stack/0075.patch
index 8a4150b2aa..50162cc5f3 100644
--- a/third_party/libwebrtc/moz-patch-stack/0075.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0075.patch
@@ -17,10 +17,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/a3447f709befd84a2
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rtc_base/physical_socket_server.cc b/rtc_base/physical_socket_server.cc
-index f0427b1081..95ba130e91 100644
+index bdea16668f..a5fe32722b 100644
--- a/rtc_base/physical_socket_server.cc
+++ b/rtc_base/physical_socket_server.cc
-@@ -459,7 +459,7 @@ int PhysicalSocket::DoReadFromSocket(void* buffer,
+@@ -484,7 +484,7 @@ int PhysicalSocket::DoReadFromSocket(void* buffer,
int received = 0;
if (read_scm_timestamp_experiment_) {
iovec iov = {.iov_base = buffer, .iov_len = length};
diff --git a/third_party/libwebrtc/moz-patch-stack/0076.patch b/third_party/libwebrtc/moz-patch-stack/0076.patch
index d3aec3677e..2bbf854001 100644
--- a/third_party/libwebrtc/moz-patch-stack/0076.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0076.patch
@@ -9,7 +9,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/108046c7cbb21c6cf
1 file changed, 1 insertion(+)
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
-index 0104e0c486..4ac074526c 100644
+index 0d11e418e6..5f6dd59d02 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -452,6 +452,7 @@ AudioProcessingImpl::GetGainController2ExperimentParams() {
diff --git a/third_party/libwebrtc/moz-patch-stack/0081.patch b/third_party/libwebrtc/moz-patch-stack/0081.patch
index 2fbb974454..b09fbc799b 100644
--- a/third_party/libwebrtc/moz-patch-stack/0081.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0081.patch
@@ -10,10 +10,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/a7179d8d75313b6c9
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
-index 3730f6eecb..d74f440996 100644
+index 73cd7826f9..afefa0b33f 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
-@@ -1383,7 +1383,7 @@ void VideoStreamEncoder::ReconfigureEncoder() {
+@@ -1386,7 +1386,7 @@ void VideoStreamEncoder::ReconfigureEncoder() {
bool is_svc = false;
bool single_stream_or_non_first_inactive = true;
diff --git a/third_party/libwebrtc/moz-patch-stack/0085.patch b/third_party/libwebrtc/moz-patch-stack/0085.patch
index 0593b7ae45..aa8d5a9501 100644
--- a/third_party/libwebrtc/moz-patch-stack/0085.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0085.patch
@@ -52,10 +52,10 @@ index f08fc692dd..02f2e53923 100644
Clock* const clock_;
bool short_circuit_ RTC_GUARDED_BY(network_sequence_checker_) = false;
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
-index 4df65659f9..077f522d41 100644
+index d13e4448b4..ae78ef8eef 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
-@@ -341,7 +341,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
+@@ -345,7 +345,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
if (frame_transformer) {
frame_transformer_delegate_ =
rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
diff --git a/third_party/libwebrtc/moz-patch-stack/0086.patch b/third_party/libwebrtc/moz-patch-stack/0086.patch
index cb6695d69d..44752e008c 100644
--- a/third_party/libwebrtc/moz-patch-stack/0086.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0086.patch
@@ -18,7 +18,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2f1a0ba74bf71cfa0
6 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/api/frame_transformer_interface.h b/api/frame_transformer_interface.h
-index 5bbcffe28e..afa79b92ea 100644
+index 102ac33334..4869ad6909 100644
--- a/api/frame_transformer_interface.h
+++ b/api/frame_transformer_interface.h
@@ -60,6 +60,7 @@ class TransformableVideoFrameInterface : public TransformableFrameInterface {
diff --git a/third_party/libwebrtc/moz-patch-stack/0091.patch b/third_party/libwebrtc/moz-patch-stack/0091.patch
index 51b0c620b0..3fcbcd0f94 100644
--- a/third_party/libwebrtc/moz-patch-stack/0091.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0091.patch
@@ -1,91 +1,30 @@
-From: Dan Baker <dbaker@mozilla.com>
-Date: Mon, 2 Oct 2023 17:17:00 +0000
-Subject: Bug 1851693 - (fix-279a05475d) Revert addition of race checker which
- is causing tsan failurs until better fix is landed upstream.r=pehrsons
+From: Michael Froman <mfroman@mozilla.com>
+Date: Thu, 5 Oct 2023 14:21:00 +0000
+Subject: Bug 1857037 - pt1 - add shim gni files to limit BUILD.gn changes.
+ r=ng,webrtc-reviewers
-This merely reverses a race checker that is too strict for our use, maintaining the code we had before, so we can fix upstream in the meantime tracked with Bug 1856392.
-
-Differential Revision: https://phabricator.services.mozilla.com/D189396
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e626ce7279e6575e68d0e43de3dfd3ed59b00a75
+Differential Revision: https://phabricator.services.mozilla.com/D190104
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/a84d39db037cbe34aa19588b0d18335eb5e2d79b
---
- modules/video_capture/linux/video_capture_v4l2.cc | 7 -------
- modules/video_capture/linux/video_capture_v4l2.h | 7 +++----
- 2 files changed, 3 insertions(+), 11 deletions(-)
+ testing/libfuzzer/fuzzer_test.gni | 2 ++
+ testing/test.gni | 2 ++
+ 2 files changed, 4 insertions(+)
+ create mode 100644 testing/libfuzzer/fuzzer_test.gni
+ create mode 100644 testing/test.gni
-diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc
-index 97cd9a70eb..08d23f7f58 100644
---- a/modules/video_capture/linux/video_capture_v4l2.cc
-+++ b/modules/video_capture/linux/video_capture_v4l2.cc
-@@ -110,7 +110,6 @@ int32_t VideoCaptureModuleV4L2::Init(const char* deviceUniqueIdUTF8) {
-
- VideoCaptureModuleV4L2::~VideoCaptureModuleV4L2() {
- RTC_DCHECK_RUN_ON(&api_checker_);
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
-
- StopCapture();
- if (_deviceFd != -1)
-@@ -120,7 +119,6 @@ VideoCaptureModuleV4L2::~VideoCaptureModuleV4L2() {
- int32_t VideoCaptureModuleV4L2::StartCapture(
- const VideoCaptureCapability& capability) {
- RTC_DCHECK_RUN_ON(&api_checker_);
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
-
- if (_captureStarted) {
- if (capability == _requestedCapability) {
-@@ -318,7 +316,6 @@ int32_t VideoCaptureModuleV4L2::StopCapture() {
- _captureThread.Finalize();
- }
-
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- MutexLock lock(&capture_lock_);
- if (_captureStarted) {
- _captureStarted = false;
-@@ -336,7 +333,6 @@ int32_t VideoCaptureModuleV4L2::StopCapture() {
- // critical section protected by the caller
-
- bool VideoCaptureModuleV4L2::AllocateVideoBuffers() {
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- struct v4l2_requestbuffers rbuffer;
- memset(&rbuffer, 0, sizeof(v4l2_requestbuffers));
-
-@@ -387,7 +383,6 @@ bool VideoCaptureModuleV4L2::AllocateVideoBuffers() {
- }
-
- bool VideoCaptureModuleV4L2::DeAllocateVideoBuffers() {
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- // unmap buffers
- for (int i = 0; i < _buffersAllocatedByDevice; i++)
- munmap(_pool[i].start, _pool[i].length);
-@@ -405,12 +400,10 @@ bool VideoCaptureModuleV4L2::DeAllocateVideoBuffers() {
- }
-
- bool VideoCaptureModuleV4L2::CaptureStarted() {
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- return _captureStarted;
- }
-
- bool VideoCaptureModuleV4L2::CaptureProcess() {
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
-
- int retVal = 0;
- struct pollfd rSet;
-diff --git a/modules/video_capture/linux/video_capture_v4l2.h b/modules/video_capture/linux/video_capture_v4l2.h
-index 0191e41876..61358d0325 100644
---- a/modules/video_capture/linux/video_capture_v4l2.h
-+++ b/modules/video_capture/linux/video_capture_v4l2.h
-@@ -45,12 +45,11 @@ class VideoCaptureModuleV4L2 : public VideoCaptureImpl {
- Mutex capture_lock_ RTC_ACQUIRED_BEFORE(api_lock_);
- bool quit_ RTC_GUARDED_BY(capture_lock_);
- int32_t _deviceId RTC_GUARDED_BY(api_checker_);
-- int32_t _deviceFd RTC_GUARDED_BY(capture_checker_);
-+ int32_t _deviceFd;
-
- int32_t _buffersAllocatedByDevice RTC_GUARDED_BY(capture_lock_);
-- VideoCaptureCapability configured_capability_
-- RTC_GUARDED_BY(capture_checker_);
-- bool _captureStarted RTC_GUARDED_BY(capture_checker_);
-+ VideoCaptureCapability configured_capability_;
-+ bool _captureStarted;
- struct Buffer {
- void* start;
- size_t length;
+diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni
+new file mode 100644
+index 0000000000..8fdf3cdad2
+--- /dev/null
++++ b/testing/libfuzzer/fuzzer_test.gni
+@@ -0,0 +1,2 @@
++# "empty" file in place of importing new testing/libfuzzer
++# to allow BUILD.gn imports to succeed.
+diff --git a/testing/test.gni b/testing/test.gni
+new file mode 100644
+index 0000000000..f46fa82778
+--- /dev/null
++++ b/testing/test.gni
+@@ -0,0 +1,2 @@
++# "empty" file in place of importing new testing/test.gni
++# to allow BUILD.gn imports to succeed.
diff --git a/third_party/libwebrtc/moz-patch-stack/0092.patch b/third_party/libwebrtc/moz-patch-stack/0092.patch
index 3fcbcd0f94..b0cdd2d540 100644
--- a/third_party/libwebrtc/moz-patch-stack/0092.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0092.patch
@@ -1,30 +1,40 @@
From: Michael Froman <mfroman@mozilla.com>
-Date: Thu, 5 Oct 2023 14:21:00 +0000
-Subject: Bug 1857037 - pt1 - add shim gni files to limit BUILD.gn changes.
- r=ng,webrtc-reviewers
+Date: Tue, 14 Feb 2023 03:27:00 +0000
+Subject: Bug 1816173 - pt12 - add shim config for
+ third_party/libwebrtc/testing/{gmock|gtest} r=ng
-Differential Revision: https://phabricator.services.mozilla.com/D190104
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/a84d39db037cbe34aa19588b0d18335eb5e2d79b
+We don't vendor third_party/libwebrtc/third_party/gmock
+ third_party/libwebrtc/third_party/gtest, so:
+- add BUILD.gn to avoid scattered BUILD.gn changes
+
+Differential Revision: https://phabricator.services.mozilla.com/D169674
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/4ea9d2db79c42a144235e45c47c71adf1dd01fdc
---
- testing/libfuzzer/fuzzer_test.gni | 2 ++
- testing/test.gni | 2 ++
- 2 files changed, 4 insertions(+)
- create mode 100644 testing/libfuzzer/fuzzer_test.gni
- create mode 100644 testing/test.gni
+ testing/gmock/BUILD.gn | 5 +++++
+ testing/gtest/BUILD.gn | 5 +++++
+ 2 files changed, 10 insertions(+)
+ create mode 100644 testing/gmock/BUILD.gn
+ create mode 100644 testing/gtest/BUILD.gn
-diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni
+diff --git a/testing/gmock/BUILD.gn b/testing/gmock/BUILD.gn
new file mode 100644
-index 0000000000..8fdf3cdad2
+index 0000000000..a2a1efdea9
--- /dev/null
-+++ b/testing/libfuzzer/fuzzer_test.gni
-@@ -0,0 +1,2 @@
-+# "empty" file in place of importing new testing/libfuzzer
-+# to allow BUILD.gn imports to succeed.
-diff --git a/testing/test.gni b/testing/test.gni
++++ b/testing/gmock/BUILD.gn
+@@ -0,0 +1,5 @@
++import("//third_party/libaom/options.gni")
++import("../../webrtc.gni")
++
++rtc_library("gmock") {
++}
+diff --git a/testing/gtest/BUILD.gn b/testing/gtest/BUILD.gn
new file mode 100644
-index 0000000000..f46fa82778
+index 0000000000..c9c2703c37
--- /dev/null
-+++ b/testing/test.gni
-@@ -0,0 +1,2 @@
-+# "empty" file in place of importing new testing/test.gni
-+# to allow BUILD.gn imports to succeed.
++++ b/testing/gtest/BUILD.gn
+@@ -0,0 +1,5 @@
++import("//third_party/libaom/options.gni")
++import("../../webrtc.gni")
++
++rtc_library("gtest") {
++}
diff --git a/third_party/libwebrtc/moz-patch-stack/0093.patch b/third_party/libwebrtc/moz-patch-stack/0093.patch
index b0cdd2d540..36e7778d1a 100644
--- a/third_party/libwebrtc/moz-patch-stack/0093.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0093.patch
@@ -1,40 +1,28 @@
-From: Michael Froman <mfroman@mozilla.com>
-Date: Tue, 14 Feb 2023 03:27:00 +0000
-Subject: Bug 1816173 - pt12 - add shim config for
- third_party/libwebrtc/testing/{gmock|gtest} r=ng
+From: Andreas Pehrson <apehrson@mozilla.com>
+Date: Wed, 18 Oct 2023 17:25:00 +0000
+Subject: Bug 1857862 - (fix-32a8169a65) Don't call non-constexpr
+ RTC_CHECK_NOTREACHED from constexpr VideoFrameTypeToString under gcc-8.
+ r=webrtc-reviewers,mjf
-We don't vendor third_party/libwebrtc/third_party/gmock
- third_party/libwebrtc/third_party/gtest, so:
-- add BUILD.gn to avoid scattered BUILD.gn changes
-
-Differential Revision: https://phabricator.services.mozilla.com/D169674
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/4ea9d2db79c42a144235e45c47c71adf1dd01fdc
+Differential Revision: https://phabricator.services.mozilla.com/D191308
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/8a4449ba24fa3192b44863ed8ba96f6f94a6e88d
---
- testing/gmock/BUILD.gn | 5 +++++
- testing/gtest/BUILD.gn | 5 +++++
- 2 files changed, 10 insertions(+)
- create mode 100644 testing/gmock/BUILD.gn
- create mode 100644 testing/gtest/BUILD.gn
+ api/video/video_frame_type.h | 4 ++++
+ 1 file changed, 4 insertions(+)
-diff --git a/testing/gmock/BUILD.gn b/testing/gmock/BUILD.gn
-new file mode 100644
-index 0000000000..a2a1efdea9
---- /dev/null
-+++ b/testing/gmock/BUILD.gn
-@@ -0,0 +1,5 @@
-+import("//third_party/libaom/options.gni")
-+import("../../webrtc.gni")
-+
-+rtc_library("gmock") {
-+}
-diff --git a/testing/gtest/BUILD.gn b/testing/gtest/BUILD.gn
-new file mode 100644
-index 0000000000..c9c2703c37
---- /dev/null
-+++ b/testing/gtest/BUILD.gn
-@@ -0,0 +1,5 @@
-+import("//third_party/libaom/options.gni")
-+import("../../webrtc.gni")
-+
-+rtc_library("gtest") {
-+}
+diff --git a/api/video/video_frame_type.h b/api/video/video_frame_type.h
+index 9079829ff8..3665a80cd8 100644
+--- a/api/video/video_frame_type.h
++++ b/api/video/video_frame_type.h
+@@ -34,7 +34,11 @@ inline constexpr absl::string_view VideoFrameTypeToString(
+ case VideoFrameType::kVideoFrameDelta:
+ return "delta";
+ }
++// Mozilla:
++// gcc-8 complains about a constexpr function calling a non-constexpr ditto.
++#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 9)
+ RTC_CHECK_NOTREACHED();
++#endif
+ return "";
+ }
+
diff --git a/third_party/libwebrtc/moz-patch-stack/0094.patch b/third_party/libwebrtc/moz-patch-stack/0094.patch
index 36e7778d1a..3b8608fa76 100644
--- a/third_party/libwebrtc/moz-patch-stack/0094.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0094.patch
@@ -1,28 +1,41 @@
From: Andreas Pehrson <apehrson@mozilla.com>
-Date: Wed, 18 Oct 2023 17:25:00 +0000
-Subject: Bug 1857862 - (fix-32a8169a65) Don't call non-constexpr
- RTC_CHECK_NOTREACHED from constexpr VideoFrameTypeToString under gcc-8.
- r=webrtc-reviewers,mjf
+Date: Wed, 18 Oct 2023 17:21:00 +0000
+Subject: Bug 1859786 - Fix lock annotation warning in Mozilla-specific edit on
+ top of video_capture_impl.cc. r=webrtc-reviewers,mjf
-Differential Revision: https://phabricator.services.mozilla.com/D191308
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/8a4449ba24fa3192b44863ed8ba96f6f94a6e88d
+The annotations were added in M116:
+https://hg.mozilla.org/mozilla-central/rev/9cd372df013948ad822ae936752d725d77474fb5
+
+Note that this was never unsafe, since _dataCallbacks is only written on the
+same thread that we are patching here. This patch however, adds helpful static
+analysis.
+
+Differential Revision: https://phabricator.services.mozilla.com/D191301
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/56ff441b644400f09d2d0453dbd8991ea25db7b1
---
- api/video/video_frame_type.h | 4 ++++
- 1 file changed, 4 insertions(+)
+ modules/video_capture/video_capture_impl.cc | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
-diff --git a/api/video/video_frame_type.h b/api/video/video_frame_type.h
-index 9079829ff8..3665a80cd8 100644
---- a/api/video/video_frame_type.h
-+++ b/api/video/video_frame_type.h
-@@ -34,7 +34,11 @@ inline constexpr absl::string_view VideoFrameTypeToString(
- case VideoFrameType::kVideoFrameDelta:
- return "delta";
+diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
+index 02404697ad..1bddaf824d 100644
+--- a/modules/video_capture/video_capture_impl.cc
++++ b/modules/video_capture/video_capture_impl.cc
+@@ -119,11 +119,14 @@ void VideoCaptureImpl::DeRegisterCaptureDataCallback(
+ }
+
+ int32_t VideoCaptureImpl::StopCaptureIfAllClientsClose() {
+- if (_dataCallBacks.empty()) {
+- return StopCapture();
+- } else {
+- return 0;
++ RTC_DCHECK_RUN_ON(&api_checker_);
++ {
++ MutexLock lock(&api_lock_);
++ if (!_dataCallBacks.empty()) {
++ return 0;
++ }
}
-+// Mozilla:
-+// gcc-8 complains about a constexpr function calling a non-constexpr ditto.
-+#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 9)
- RTC_CHECK_NOTREACHED();
-+#endif
- return "";
++ return StopCapture();
}
+ int32_t VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame) {
diff --git a/third_party/libwebrtc/moz-patch-stack/0095.patch b/third_party/libwebrtc/moz-patch-stack/0095.patch
index 3b8608fa76..983834acba 100644
--- a/third_party/libwebrtc/moz-patch-stack/0095.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0095.patch
@@ -1,41 +1,27 @@
From: Andreas Pehrson <apehrson@mozilla.com>
Date: Wed, 18 Oct 2023 17:21:00 +0000
-Subject: Bug 1859786 - Fix lock annotation warning in Mozilla-specific edit on
- top of video_capture_impl.cc. r=webrtc-reviewers,mjf
+Subject: Bug 1859786 - Fix clang-tidy warning in video_capture_impl.cc.
+ r=webrtc-reviewers,mjf
-The annotations were added in M116:
-https://hg.mozilla.org/mozilla-central/rev/9cd372df013948ad822ae936752d725d77474fb5
+clang-tidy says:
+ 'auto dataCallBack' can be declared as 'auto *dataCallBack'
-Note that this was never unsafe, since _dataCallbacks is only written on the
-same thread that we are patching here. This patch however, adds helpful static
-analysis.
-
-Differential Revision: https://phabricator.services.mozilla.com/D191301
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/56ff441b644400f09d2d0453dbd8991ea25db7b1
+Differential Revision: https://phabricator.services.mozilla.com/D191302
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/26c84d214137a1b0de0902c7038756964e5786f4
---
- modules/video_capture/video_capture_impl.cc | 11 +++++++----
- 1 file changed, 7 insertions(+), 4 deletions(-)
+ modules/video_capture/video_capture_impl.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
-index 02404697ad..1bddaf824d 100644
+index 1bddaf824d..15dfb7fe1f 100644
--- a/modules/video_capture/video_capture_impl.cc
+++ b/modules/video_capture/video_capture_impl.cc
-@@ -119,11 +119,14 @@ void VideoCaptureImpl::DeRegisterCaptureDataCallback(
- }
+@@ -134,7 +134,7 @@ int32_t VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame) {
+
+ UpdateFrameCount(); // frame count used for local frame rate callback.
- int32_t VideoCaptureImpl::StopCaptureIfAllClientsClose() {
-- if (_dataCallBacks.empty()) {
-- return StopCapture();
-- } else {
-- return 0;
-+ RTC_DCHECK_RUN_ON(&api_checker_);
-+ {
-+ MutexLock lock(&api_lock_);
-+ if (!_dataCallBacks.empty()) {
-+ return 0;
-+ }
+- for (auto dataCallBack : _dataCallBacks) {
++ for (auto* dataCallBack : _dataCallBacks) {
+ dataCallBack->OnFrame(captureFrame);
}
-+ return StopCapture();
- }
- int32_t VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame) {
diff --git a/third_party/libwebrtc/moz-patch-stack/0096.patch b/third_party/libwebrtc/moz-patch-stack/0096.patch
index 983834acba..1faafdf8cf 100644
--- a/third_party/libwebrtc/moz-patch-stack/0096.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0096.patch
@@ -1,27 +1,35362 @@
-From: Andreas Pehrson <apehrson@mozilla.com>
-Date: Wed, 18 Oct 2023 17:21:00 +0000
-Subject: Bug 1859786 - Fix clang-tidy warning in video_capture_impl.cc.
- r=webrtc-reviewers,mjf
+From: Nico Grunbaum <na-g@nostrum.com>
+Date: Fri, 30 Apr 2021 21:51:00 +0000
+Subject: Bug 1654112 - Add grit dep for building webrtc on android; r=mjf
-clang-tidy says:
- 'auto dataCallBack' can be declared as 'auto *dataCallBack'
-
-Differential Revision: https://phabricator.services.mozilla.com/D191302
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/26c84d214137a1b0de0902c7038756964e5786f4
+Differential Revision: https://phabricator.services.mozilla.com/D114027
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/3cce5e6938f0df87bd9ab12a5f556aceb93dfa1d
---
- modules/video_capture/video_capture_impl.cc | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
-index 1bddaf824d..15dfb7fe1f 100644
---- a/modules/video_capture/video_capture_impl.cc
-+++ b/modules/video_capture/video_capture_impl.cc
-@@ -134,7 +134,7 @@ int32_t VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame) {
-
- UpdateFrameCount(); // frame count used for local frame rate callback.
-
-- for (auto dataCallBack : _dataCallBacks) {
-+ for (auto* dataCallBack : _dataCallBacks) {
- dataCallBack->OnFrame(captureFrame);
- }
-
+ tools/grit/.gitignore | 1 +
+ tools/grit/BUILD.gn | 48 +
+ tools/grit/MANIFEST.in | 3 +
+ tools/grit/OWNERS | 8 +
+ tools/grit/PRESUBMIT.py | 22 +
+ tools/grit/README.md | 19 +
+ tools/grit/grit.py | 31 +
+ tools/grit/grit/__init__.py | 19 +
+ tools/grit/grit/clique.py | 491 +++
+ tools/grit/grit/clique_unittest.py | 265 ++
+ tools/grit/grit/constants.py | 23 +
+ tools/grit/grit/exception.py | 139 +
+ tools/grit/grit/extern/BogoFP.py | 22 +
+ tools/grit/grit/extern/FP.py | 72 +
+ tools/grit/grit/extern/__init__.py | 0
+ tools/grit/grit/extern/tclib.py | 503 +++
+ tools/grit/grit/format/__init__.py | 8 +
+ tools/grit/grit/format/android_xml.py | 212 ++
+ .../grit/grit/format/android_xml_unittest.py | 149 +
+ tools/grit/grit/format/c_format.py | 95 +
+ tools/grit/grit/format/c_format_unittest.py | 81 +
+ .../grit/grit/format/chrome_messages_json.py | 59 +
+ .../format/chrome_messages_json_unittest.py | 190 +
+ tools/grit/grit/format/data_pack.py | 321 ++
+ tools/grit/grit/format/data_pack_unittest.py | 102 +
+ .../grit/grit/format/gen_predetermined_ids.py | 144 +
+ .../format/gen_predetermined_ids_unittest.py | 46 +
+ tools/grit/grit/format/gzip_string.py | 46 +
+ .../grit/grit/format/gzip_string_unittest.py | 65 +
+ tools/grit/grit/format/html_inline.py | 602 ++++
+ .../grit/grit/format/html_inline_unittest.py | 927 +++++
+ tools/grit/grit/format/minifier.py | 45 +
+ .../grit/grit/format/policy_templates_json.py | 26 +
+ .../format/policy_templates_json_unittest.py | 207 ++
+ tools/grit/grit/format/rc.py | 474 +++
+ tools/grit/grit/format/rc_header.py | 48 +
+ tools/grit/grit/format/rc_header_unittest.py | 138 +
+ tools/grit/grit/format/rc_unittest.py | 415 +++
+ tools/grit/grit/format/resource_map.py | 159 +
+ .../grit/grit/format/resource_map_unittest.py | 345 ++
+ tools/grit/grit/gather/__init__.py | 8 +
+ tools/grit/grit/gather/admin_template.py | 62 +
+ .../grit/gather/admin_template_unittest.py | 115 +
+ tools/grit/grit/gather/chrome_html.py | 377 ++
+ .../grit/grit/gather/chrome_html_unittest.py | 610 ++++
+ tools/grit/grit/gather/chrome_scaled_image.py | 157 +
+ .../gather/chrome_scaled_image_unittest.py | 209 ++
+ tools/grit/grit/gather/interface.py | 172 +
+ tools/grit/grit/gather/json_loader.py | 27 +
+ tools/grit/grit/gather/policy_json.py | 325 ++
+ .../grit/grit/gather/policy_json_unittest.py | 347 ++
+ tools/grit/grit/gather/rc.py | 343 ++
+ tools/grit/grit/gather/rc_unittest.py | 372 ++
+ tools/grit/grit/gather/regexp.py | 82 +
+ tools/grit/grit/gather/skeleton_gatherer.py | 149 +
+ tools/grit/grit/gather/tr_html.py | 743 ++++
+ tools/grit/grit/gather/tr_html_unittest.py | 524 +++
+ tools/grit/grit/gather/txt.py | 38 +
+ tools/grit/grit/gather/txt_unittest.py | 35 +
+ tools/grit/grit/grd_reader.py | 238 ++
+ tools/grit/grit/grd_reader_unittest.py | 346 ++
+ tools/grit/grit/grit-todo.xml | 62 +
+ tools/grit/grit/grit_runner.py | 334 ++
+ tools/grit/grit/grit_runner_unittest.py | 42 +
+ tools/grit/grit/lazy_re.py | 46 +
+ tools/grit/grit/lazy_re_unittest.py | 40 +
+ tools/grit/grit/node/__init__.py | 8 +
+ tools/grit/grit/node/base.py | 670 ++++
+ tools/grit/grit/node/base_unittest.py | 259 ++
+ tools/grit/grit/node/brotli_util.py | 29 +
+ tools/grit/grit/node/custom/__init__.py | 8 +
+ tools/grit/grit/node/custom/filename.py | 29 +
+ .../grit/node/custom/filename_unittest.py | 34 +
+ tools/grit/grit/node/empty.py | 64 +
+ tools/grit/grit/node/include.py | 170 +
+ tools/grit/grit/node/include_unittest.py | 134 +
+ tools/grit/grit/node/mapping.py | 60 +
+ tools/grit/grit/node/message.py | 362 ++
+ tools/grit/grit/node/message_unittest.py | 380 ++
+ tools/grit/grit/node/misc.py | 707 ++++
+ tools/grit/grit/node/misc_unittest.py | 590 ++++
+ tools/grit/grit/node/mock_brotli.py | 10 +
+ tools/grit/grit/node/node_io.py | 117 +
+ tools/grit/grit/node/node_io_unittest.py | 182 +
+ tools/grit/grit/node/structure.py | 375 ++
+ tools/grit/grit/node/structure_unittest.py | 178 +
+ tools/grit/grit/node/variant.py | 41 +
+ tools/grit/grit/pseudo.py | 129 +
+ tools/grit/grit/pseudo_rtl.py | 104 +
+ tools/grit/grit/pseudo_unittest.py | 55 +
+ tools/grit/grit/shortcuts.py | 93 +
+ tools/grit/grit/shortcuts_unittest.py | 79 +
+ tools/grit/grit/tclib.py | 246 ++
+ tools/grit/grit/tclib_unittest.py | 180 +
+ tools/grit/grit/test_suite_all.py | 34 +
+ tools/grit/grit/testdata/GoogleDesktop.adm | 945 +++++
+ tools/grit/grit/testdata/README.txt | 87 +
+ tools/grit/grit/testdata/about.html | 45 +
+ tools/grit/grit/testdata/android.xml | 24 +
+ tools/grit/grit/testdata/bad_browser.html | 16 +
+ tools/grit/grit/testdata/browser.html | 42 +
+ tools/grit/grit/testdata/buildinfo.grd | 46 +
+ tools/grit/grit/testdata/cache_prefix.html | 24 +
+ .../grit/grit/testdata/cache_prefix_file.html | 25 +
+ tools/grit/grit/testdata/chat_result.html | 24 +
+ .../chrome/app/generated_resources.grd | 199 ++
+ tools/grit/grit/testdata/chrome_html.html | 6 +
+ .../grit/testdata/default_100_percent/a.png | Bin 0 -> 159 bytes
+ .../grit/testdata/default_100_percent/b.png | 1 +
+ tools/grit/grit/testdata/del_footer.html | 8 +
+ tools/grit/grit/testdata/del_header.html | 60 +
+ tools/grit/grit/testdata/deleted.html | 21 +
+ tools/grit/grit/testdata/depfile.grd | 18 +
+ tools/grit/grit/testdata/details.html | 10 +
+ .../grit/testdata/duplicate-name-input.xml | 26 +
+ tools/grit/grit/testdata/email_result.html | 34 +
+ tools/grit/grit/testdata/email_thread.html | 10 +
+ tools/grit/grit/testdata/error.html | 8 +
+ tools/grit/grit/testdata/explicit_web.html | 11 +
+ tools/grit/grit/testdata/footer.html | 14 +
+ .../grit/testdata/generated_resources_fr.xtb | 3079 +++++++++++++++++
+ .../grit/testdata/generated_resources_iw.xtb | 4 +
+ .../grit/testdata/generated_resources_no.xtb | 4 +
+ tools/grit/grit/testdata/grit_part.grdp | 5 +
+ tools/grit/grit/testdata/header.html | 39 +
+ tools/grit/grit/testdata/homepage.html | 37 +
+ tools/grit/grit/testdata/hover.html | 177 +
+ tools/grit/grit/testdata/include_test.html | 31 +
+ tools/grit/grit/testdata/included_sample.html | 1 +
+ tools/grit/grit/testdata/indexing_speed.html | 58 +
+ tools/grit/grit/testdata/install_prefs.html | 92 +
+ tools/grit/grit/testdata/install_prefs2.html | 52 +
+ .../grit/testdata/klonk-alternate-skeleton.rc | Bin 0 -> 1088 bytes
+ tools/grit/grit/testdata/klonk.ico | Bin 0 -> 766 bytes
+ tools/grit/grit/testdata/klonk.rc | Bin 0 -> 9824 bytes
+ .../grit/grit/testdata/ko_oem_enable_bug.html | 1 +
+ .../grit/testdata/ko_oem_non_admin_bug.html | 1 +
+ tools/grit/grit/testdata/mini.html | 36 +
+ tools/grit/grit/testdata/oem_enable.html | 106 +
+ tools/grit/grit/testdata/oem_non_admin.html | 39 +
+ tools/grit/grit/testdata/onebox.html | 21 +
+ tools/grit/grit/testdata/oneclick.html | 34 +
+ tools/grit/grit/testdata/password.html | 37 +
+ tools/grit/grit/testdata/preferences.html | 234 ++
+ tools/grit/grit/testdata/preprocess_test.html | 7 +
+ tools/grit/grit/testdata/privacy.html | 35 +
+ tools/grit/grit/testdata/quit_apps.html | 49 +
+ tools/grit/grit/testdata/recrawl.html | 30 +
+ tools/grit/grit/testdata/resource_ids | 13 +
+ tools/grit/grit/testdata/script.html | 38 +
+ tools/grit/grit/testdata/searchbox.html | 22 +
+ tools/grit/grit/testdata/sidebar_h.html | 82 +
+ tools/grit/grit/testdata/sidebar_v.html | 267 ++
+ tools/grit/grit/testdata/simple-input.xml | 52 +
+ tools/grit/grit/testdata/simple.html | 3 +
+ tools/grit/grit/testdata/source.rc | 57 +
+ .../grit/testdata/special_100_percent/a.png | Bin 0 -> 159 bytes
+ tools/grit/grit/testdata/status.html | 44 +
+ .../grit/testdata/structure_variables.html | 4 +
+ tools/grit/grit/testdata/substitute.grd | 31 +
+ tools/grit/grit/testdata/substitute.xmb | 10 +
+ .../grit/grit/testdata/substitute_no_ids.grd | 31 +
+ tools/grit/grit/testdata/substitute_tmpl.grd | 31 +
+ tools/grit/grit/testdata/test_css.css | 1 +
+ tools/grit/grit/testdata/test_html.html | 1 +
+ tools/grit/grit/testdata/test_js.js | 1 +
+ tools/grit/grit/testdata/test_svg.svg | 1 +
+ tools/grit/grit/testdata/test_text.txt | 1 +
+ tools/grit/grit/testdata/time_related.html | 11 +
+ tools/grit/grit/testdata/toolbar_about.html | 138 +
+ .../grit/testdata/tools/grit/resource_ids | 176 +
+ tools/grit/grit/testdata/transl.rc | 56 +
+ tools/grit/grit/testdata/versions.html | 7 +
+ tools/grit/grit/testdata/whitelist.txt | 4 +
+ .../grit/testdata/whitelist_resources.grd | 54 +
+ .../grit/grit/testdata/whitelist_strings.grd | 23 +
+ tools/grit/grit/tool/__init__.py | 8 +
+ tools/grit/grit/tool/android2grd.py | 484 +++
+ tools/grit/grit/tool/android2grd_unittest.py | 181 +
+ tools/grit/grit/tool/build.py | 556 +++
+ tools/grit/grit/tool/build_unittest.py | 341 ++
+ tools/grit/grit/tool/buildinfo.py | 78 +
+ tools/grit/grit/tool/buildinfo_unittest.py | 90 +
+ tools/grit/grit/tool/count.py | 52 +
+ tools/grit/grit/tool/diff_structures.py | 119 +
+ .../grit/tool/diff_structures_unittest.py | 46 +
+ tools/grit/grit/tool/interface.py | 62 +
+ tools/grit/grit/tool/menu_from_parts.py | 79 +
+ tools/grit/grit/tool/newgrd.py | 85 +
+ tools/grit/grit/tool/newgrd_unittest.py | 51 +
+ tools/grit/grit/tool/postprocess_interface.py | 29 +
+ tools/grit/grit/tool/postprocess_unittest.py | 64 +
+ tools/grit/grit/tool/preprocess_interface.py | 25 +
+ tools/grit/grit/tool/preprocess_unittest.py | 50 +
+ tools/grit/grit/tool/rc2grd.py | 418 +++
+ tools/grit/grit/tool/rc2grd_unittest.py | 163 +
+ tools/grit/grit/tool/resize.py | 295 ++
+ tools/grit/grit/tool/test.py | 24 +
+ tools/grit/grit/tool/transl2tc.py | 251 ++
+ tools/grit/grit/tool/transl2tc_unittest.py | 133 +
+ tools/grit/grit/tool/unit.py | 43 +
+ .../grit/tool/update_resource_ids/__init__.py | 305 ++
+ .../grit/tool/update_resource_ids/assigner.py | 286 ++
+ .../update_resource_ids/assigner_unittest.py | 154 +
+ .../grit/tool/update_resource_ids/common.py | 101 +
+ .../grit/tool/update_resource_ids/parser.py | 231 ++
+ .../grit/tool/update_resource_ids/reader.py | 83 +
+ tools/grit/grit/tool/xmb.py | 295 ++
+ tools/grit/grit/tool/xmb_unittest.py | 132 +
+ tools/grit/grit/util.py | 691 ++++
+ tools/grit/grit/util_unittest.py | 118 +
+ tools/grit/grit/xtb_reader.py | 140 +
+ tools/grit/grit/xtb_reader_unittest.py | 110 +
+ tools/grit/grit_info.py | 173 +
+ tools/grit/grit_rule.gni | 485 +++
+ tools/grit/minify_with_uglify.py | 44 +
+ tools/grit/minimize_css.py | 105 +
+ tools/grit/minimize_css_unittest.py | 58 +
+ tools/grit/pak_util.py | 223 ++
+ tools/grit/repack.gni | 189 +
+ tools/grit/setup.py | 46 +
+ tools/grit/stamp_grit_sources.py | 57 +
+ tools/grit/third_party/six/LICENSE | 18 +
+ tools/grit/third_party/six/README | 16 +
+ tools/grit/third_party/six/README.chromium | 13 +
+ tools/grit/third_party/six/__init__.py | 868 +++++
+ 226 files changed, 33440 insertions(+)
+ create mode 100644 tools/grit/.gitignore
+ create mode 100644 tools/grit/BUILD.gn
+ create mode 100644 tools/grit/MANIFEST.in
+ create mode 100644 tools/grit/OWNERS
+ create mode 100644 tools/grit/PRESUBMIT.py
+ create mode 100644 tools/grit/README.md
+ create mode 100644 tools/grit/grit.py
+ create mode 100644 tools/grit/grit/__init__.py
+ create mode 100644 tools/grit/grit/clique.py
+ create mode 100644 tools/grit/grit/clique_unittest.py
+ create mode 100644 tools/grit/grit/constants.py
+ create mode 100644 tools/grit/grit/exception.py
+ create mode 100644 tools/grit/grit/extern/BogoFP.py
+ create mode 100644 tools/grit/grit/extern/FP.py
+ create mode 100644 tools/grit/grit/extern/__init__.py
+ create mode 100644 tools/grit/grit/extern/tclib.py
+ create mode 100644 tools/grit/grit/format/__init__.py
+ create mode 100644 tools/grit/grit/format/android_xml.py
+ create mode 100644 tools/grit/grit/format/android_xml_unittest.py
+ create mode 100644 tools/grit/grit/format/c_format.py
+ create mode 100644 tools/grit/grit/format/c_format_unittest.py
+ create mode 100644 tools/grit/grit/format/chrome_messages_json.py
+ create mode 100644 tools/grit/grit/format/chrome_messages_json_unittest.py
+ create mode 100644 tools/grit/grit/format/data_pack.py
+ create mode 100644 tools/grit/grit/format/data_pack_unittest.py
+ create mode 100644 tools/grit/grit/format/gen_predetermined_ids.py
+ create mode 100644 tools/grit/grit/format/gen_predetermined_ids_unittest.py
+ create mode 100644 tools/grit/grit/format/gzip_string.py
+ create mode 100644 tools/grit/grit/format/gzip_string_unittest.py
+ create mode 100644 tools/grit/grit/format/html_inline.py
+ create mode 100644 tools/grit/grit/format/html_inline_unittest.py
+ create mode 100644 tools/grit/grit/format/minifier.py
+ create mode 100644 tools/grit/grit/format/policy_templates_json.py
+ create mode 100644 tools/grit/grit/format/policy_templates_json_unittest.py
+ create mode 100644 tools/grit/grit/format/rc.py
+ create mode 100644 tools/grit/grit/format/rc_header.py
+ create mode 100644 tools/grit/grit/format/rc_header_unittest.py
+ create mode 100644 tools/grit/grit/format/rc_unittest.py
+ create mode 100644 tools/grit/grit/format/resource_map.py
+ create mode 100644 tools/grit/grit/format/resource_map_unittest.py
+ create mode 100644 tools/grit/grit/gather/__init__.py
+ create mode 100644 tools/grit/grit/gather/admin_template.py
+ create mode 100644 tools/grit/grit/gather/admin_template_unittest.py
+ create mode 100644 tools/grit/grit/gather/chrome_html.py
+ create mode 100644 tools/grit/grit/gather/chrome_html_unittest.py
+ create mode 100644 tools/grit/grit/gather/chrome_scaled_image.py
+ create mode 100644 tools/grit/grit/gather/chrome_scaled_image_unittest.py
+ create mode 100644 tools/grit/grit/gather/interface.py
+ create mode 100644 tools/grit/grit/gather/json_loader.py
+ create mode 100644 tools/grit/grit/gather/policy_json.py
+ create mode 100644 tools/grit/grit/gather/policy_json_unittest.py
+ create mode 100644 tools/grit/grit/gather/rc.py
+ create mode 100644 tools/grit/grit/gather/rc_unittest.py
+ create mode 100644 tools/grit/grit/gather/regexp.py
+ create mode 100644 tools/grit/grit/gather/skeleton_gatherer.py
+ create mode 100644 tools/grit/grit/gather/tr_html.py
+ create mode 100644 tools/grit/grit/gather/tr_html_unittest.py
+ create mode 100644 tools/grit/grit/gather/txt.py
+ create mode 100644 tools/grit/grit/gather/txt_unittest.py
+ create mode 100644 tools/grit/grit/grd_reader.py
+ create mode 100644 tools/grit/grit/grd_reader_unittest.py
+ create mode 100644 tools/grit/grit/grit-todo.xml
+ create mode 100644 tools/grit/grit/grit_runner.py
+ create mode 100644 tools/grit/grit/grit_runner_unittest.py
+ create mode 100644 tools/grit/grit/lazy_re.py
+ create mode 100644 tools/grit/grit/lazy_re_unittest.py
+ create mode 100644 tools/grit/grit/node/__init__.py
+ create mode 100644 tools/grit/grit/node/base.py
+ create mode 100644 tools/grit/grit/node/base_unittest.py
+ create mode 100644 tools/grit/grit/node/brotli_util.py
+ create mode 100644 tools/grit/grit/node/custom/__init__.py
+ create mode 100644 tools/grit/grit/node/custom/filename.py
+ create mode 100644 tools/grit/grit/node/custom/filename_unittest.py
+ create mode 100644 tools/grit/grit/node/empty.py
+ create mode 100644 tools/grit/grit/node/include.py
+ create mode 100644 tools/grit/grit/node/include_unittest.py
+ create mode 100644 tools/grit/grit/node/mapping.py
+ create mode 100644 tools/grit/grit/node/message.py
+ create mode 100644 tools/grit/grit/node/message_unittest.py
+ create mode 100644 tools/grit/grit/node/misc.py
+ create mode 100644 tools/grit/grit/node/misc_unittest.py
+ create mode 100644 tools/grit/grit/node/mock_brotli.py
+ create mode 100644 tools/grit/grit/node/node_io.py
+ create mode 100644 tools/grit/grit/node/node_io_unittest.py
+ create mode 100644 tools/grit/grit/node/structure.py
+ create mode 100644 tools/grit/grit/node/structure_unittest.py
+ create mode 100644 tools/grit/grit/node/variant.py
+ create mode 100644 tools/grit/grit/pseudo.py
+ create mode 100644 tools/grit/grit/pseudo_rtl.py
+ create mode 100644 tools/grit/grit/pseudo_unittest.py
+ create mode 100644 tools/grit/grit/shortcuts.py
+ create mode 100644 tools/grit/grit/shortcuts_unittest.py
+ create mode 100644 tools/grit/grit/tclib.py
+ create mode 100644 tools/grit/grit/tclib_unittest.py
+ create mode 100644 tools/grit/grit/test_suite_all.py
+ create mode 100644 tools/grit/grit/testdata/GoogleDesktop.adm
+ create mode 100644 tools/grit/grit/testdata/README.txt
+ create mode 100644 tools/grit/grit/testdata/about.html
+ create mode 100644 tools/grit/grit/testdata/android.xml
+ create mode 100644 tools/grit/grit/testdata/bad_browser.html
+ create mode 100644 tools/grit/grit/testdata/browser.html
+ create mode 100644 tools/grit/grit/testdata/buildinfo.grd
+ create mode 100644 tools/grit/grit/testdata/cache_prefix.html
+ create mode 100644 tools/grit/grit/testdata/cache_prefix_file.html
+ create mode 100644 tools/grit/grit/testdata/chat_result.html
+ create mode 100644 tools/grit/grit/testdata/chrome/app/generated_resources.grd
+ create mode 100644 tools/grit/grit/testdata/chrome_html.html
+ create mode 100644 tools/grit/grit/testdata/default_100_percent/a.png
+ create mode 100644 tools/grit/grit/testdata/default_100_percent/b.png
+ create mode 100644 tools/grit/grit/testdata/del_footer.html
+ create mode 100644 tools/grit/grit/testdata/del_header.html
+ create mode 100644 tools/grit/grit/testdata/deleted.html
+ create mode 100644 tools/grit/grit/testdata/depfile.grd
+ create mode 100644 tools/grit/grit/testdata/details.html
+ create mode 100644 tools/grit/grit/testdata/duplicate-name-input.xml
+ create mode 100644 tools/grit/grit/testdata/email_result.html
+ create mode 100644 tools/grit/grit/testdata/email_thread.html
+ create mode 100644 tools/grit/grit/testdata/error.html
+ create mode 100644 tools/grit/grit/testdata/explicit_web.html
+ create mode 100644 tools/grit/grit/testdata/footer.html
+ create mode 100644 tools/grit/grit/testdata/generated_resources_fr.xtb
+ create mode 100644 tools/grit/grit/testdata/generated_resources_iw.xtb
+ create mode 100644 tools/grit/grit/testdata/generated_resources_no.xtb
+ create mode 100644 tools/grit/grit/testdata/grit_part.grdp
+ create mode 100644 tools/grit/grit/testdata/header.html
+ create mode 100644 tools/grit/grit/testdata/homepage.html
+ create mode 100644 tools/grit/grit/testdata/hover.html
+ create mode 100644 tools/grit/grit/testdata/include_test.html
+ create mode 100644 tools/grit/grit/testdata/included_sample.html
+ create mode 100644 tools/grit/grit/testdata/indexing_speed.html
+ create mode 100644 tools/grit/grit/testdata/install_prefs.html
+ create mode 100644 tools/grit/grit/testdata/install_prefs2.html
+ create mode 100644 tools/grit/grit/testdata/klonk-alternate-skeleton.rc
+ create mode 100644 tools/grit/grit/testdata/klonk.ico
+ create mode 100644 tools/grit/grit/testdata/klonk.rc
+ create mode 100644 tools/grit/grit/testdata/ko_oem_enable_bug.html
+ create mode 100644 tools/grit/grit/testdata/ko_oem_non_admin_bug.html
+ create mode 100644 tools/grit/grit/testdata/mini.html
+ create mode 100644 tools/grit/grit/testdata/oem_enable.html
+ create mode 100644 tools/grit/grit/testdata/oem_non_admin.html
+ create mode 100644 tools/grit/grit/testdata/onebox.html
+ create mode 100644 tools/grit/grit/testdata/oneclick.html
+ create mode 100644 tools/grit/grit/testdata/password.html
+ create mode 100644 tools/grit/grit/testdata/preferences.html
+ create mode 100644 tools/grit/grit/testdata/preprocess_test.html
+ create mode 100644 tools/grit/grit/testdata/privacy.html
+ create mode 100644 tools/grit/grit/testdata/quit_apps.html
+ create mode 100644 tools/grit/grit/testdata/recrawl.html
+ create mode 100644 tools/grit/grit/testdata/resource_ids
+ create mode 100644 tools/grit/grit/testdata/script.html
+ create mode 100644 tools/grit/grit/testdata/searchbox.html
+ create mode 100644 tools/grit/grit/testdata/sidebar_h.html
+ create mode 100644 tools/grit/grit/testdata/sidebar_v.html
+ create mode 100644 tools/grit/grit/testdata/simple-input.xml
+ create mode 100644 tools/grit/grit/testdata/simple.html
+ create mode 100644 tools/grit/grit/testdata/source.rc
+ create mode 100644 tools/grit/grit/testdata/special_100_percent/a.png
+ create mode 100644 tools/grit/grit/testdata/status.html
+ create mode 100644 tools/grit/grit/testdata/structure_variables.html
+ create mode 100644 tools/grit/grit/testdata/substitute.grd
+ create mode 100644 tools/grit/grit/testdata/substitute.xmb
+ create mode 100644 tools/grit/grit/testdata/substitute_no_ids.grd
+ create mode 100644 tools/grit/grit/testdata/substitute_tmpl.grd
+ create mode 100644 tools/grit/grit/testdata/test_css.css
+ create mode 100644 tools/grit/grit/testdata/test_html.html
+ create mode 100644 tools/grit/grit/testdata/test_js.js
+ create mode 100644 tools/grit/grit/testdata/test_svg.svg
+ create mode 100644 tools/grit/grit/testdata/test_text.txt
+ create mode 100644 tools/grit/grit/testdata/time_related.html
+ create mode 100644 tools/grit/grit/testdata/toolbar_about.html
+ create mode 100644 tools/grit/grit/testdata/tools/grit/resource_ids
+ create mode 100644 tools/grit/grit/testdata/transl.rc
+ create mode 100644 tools/grit/grit/testdata/versions.html
+ create mode 100644 tools/grit/grit/testdata/whitelist.txt
+ create mode 100644 tools/grit/grit/testdata/whitelist_resources.grd
+ create mode 100644 tools/grit/grit/testdata/whitelist_strings.grd
+ create mode 100644 tools/grit/grit/tool/__init__.py
+ create mode 100644 tools/grit/grit/tool/android2grd.py
+ create mode 100644 tools/grit/grit/tool/android2grd_unittest.py
+ create mode 100644 tools/grit/grit/tool/build.py
+ create mode 100644 tools/grit/grit/tool/build_unittest.py
+ create mode 100644 tools/grit/grit/tool/buildinfo.py
+ create mode 100644 tools/grit/grit/tool/buildinfo_unittest.py
+ create mode 100644 tools/grit/grit/tool/count.py
+ create mode 100644 tools/grit/grit/tool/diff_structures.py
+ create mode 100644 tools/grit/grit/tool/diff_structures_unittest.py
+ create mode 100644 tools/grit/grit/tool/interface.py
+ create mode 100644 tools/grit/grit/tool/menu_from_parts.py
+ create mode 100644 tools/grit/grit/tool/newgrd.py
+ create mode 100644 tools/grit/grit/tool/newgrd_unittest.py
+ create mode 100644 tools/grit/grit/tool/postprocess_interface.py
+ create mode 100644 tools/grit/grit/tool/postprocess_unittest.py
+ create mode 100644 tools/grit/grit/tool/preprocess_interface.py
+ create mode 100644 tools/grit/grit/tool/preprocess_unittest.py
+ create mode 100644 tools/grit/grit/tool/rc2grd.py
+ create mode 100644 tools/grit/grit/tool/rc2grd_unittest.py
+ create mode 100644 tools/grit/grit/tool/resize.py
+ create mode 100644 tools/grit/grit/tool/test.py
+ create mode 100644 tools/grit/grit/tool/transl2tc.py
+ create mode 100644 tools/grit/grit/tool/transl2tc_unittest.py
+ create mode 100644 tools/grit/grit/tool/unit.py
+ create mode 100644 tools/grit/grit/tool/update_resource_ids/__init__.py
+ create mode 100644 tools/grit/grit/tool/update_resource_ids/assigner.py
+ create mode 100644 tools/grit/grit/tool/update_resource_ids/assigner_unittest.py
+ create mode 100644 tools/grit/grit/tool/update_resource_ids/common.py
+ create mode 100644 tools/grit/grit/tool/update_resource_ids/parser.py
+ create mode 100644 tools/grit/grit/tool/update_resource_ids/reader.py
+ create mode 100644 tools/grit/grit/tool/xmb.py
+ create mode 100644 tools/grit/grit/tool/xmb_unittest.py
+ create mode 100644 tools/grit/grit/util.py
+ create mode 100644 tools/grit/grit/util_unittest.py
+ create mode 100644 tools/grit/grit/xtb_reader.py
+ create mode 100644 tools/grit/grit/xtb_reader_unittest.py
+ create mode 100644 tools/grit/grit_info.py
+ create mode 100644 tools/grit/grit_rule.gni
+ create mode 100644 tools/grit/minify_with_uglify.py
+ create mode 100644 tools/grit/minimize_css.py
+ create mode 100644 tools/grit/minimize_css_unittest.py
+ create mode 100644 tools/grit/pak_util.py
+ create mode 100644 tools/grit/repack.gni
+ create mode 100644 tools/grit/setup.py
+ create mode 100644 tools/grit/stamp_grit_sources.py
+ create mode 100644 tools/grit/third_party/six/LICENSE
+ create mode 100644 tools/grit/third_party/six/README
+ create mode 100644 tools/grit/third_party/six/README.chromium
+ create mode 100644 tools/grit/third_party/six/__init__.py
+
+diff --git a/tools/grit/.gitignore b/tools/grit/.gitignore
+new file mode 100644
+index 0000000000..0d20b6487c
+--- /dev/null
++++ b/tools/grit/.gitignore
+@@ -0,0 +1 @@
++*.pyc
+diff --git a/tools/grit/BUILD.gn b/tools/grit/BUILD.gn
+new file mode 100644
+index 0000000000..1cd3c75b55
+--- /dev/null
++++ b/tools/grit/BUILD.gn
+@@ -0,0 +1,48 @@
++# Copyright 2014 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++# This target creates a stamp file that depends on all the sources in the grit
++# directory. By depending on this, a target can force itself to be rebuilt if
++# grit itself changes.
++
++import("//build/config/sanitizers/sanitizers.gni")
++
++action("grit_sources") {
++ depfile = "$target_out_dir/grit_sources.d"
++ script = "stamp_grit_sources.py"
++
++ inputs = [ "grit.py" ]
++
++ # Note that we can't call this "grit_sources.stamp" because that file is
++ # implicitly created by GN for script actions.
++ outputs = [ "$target_out_dir/grit_sources.script.stamp" ]
++
++ args = [
++ rebase_path("//tools/grit", root_build_dir),
++ rebase_path(outputs[0], root_build_dir),
++ rebase_path(depfile, root_build_dir),
++ ]
++}
++
++group("grit_python_unittests") {
++ testonly = true
++
++ data = [
++ "//testing/scripts/common.py",
++ "//testing/scripts/run_isolated_script_test.py",
++ "//testing/xvfb.py",
++ "//tools/grit/",
++ "//third_party/catapult/third_party/typ/",
++ ]
++}
++
++# See https://crbug.com/983200
++if (is_mac && is_asan) {
++ create_bundle("brotli_mac_asan_workaround") {
++ bundle_root_dir = "$target_out_dir/$target_name"
++ bundle_executable_dir = bundle_root_dir
++
++ public_deps = [ "//third_party/brotli:brotli($host_toolchain)" ]
++ }
++}
+diff --git a/tools/grit/MANIFEST.in b/tools/grit/MANIFEST.in
+new file mode 100644
+index 0000000000..1cbff42400
+--- /dev/null
++++ b/tools/grit/MANIFEST.in
+@@ -0,0 +1,3 @@
++exclude grit/test_suite_all.py
++exclude grit/tool/test.py
++global-exclude *_unittest.py
+diff --git a/tools/grit/OWNERS b/tools/grit/OWNERS
+new file mode 100644
+index 0000000000..6a8f447b82
+--- /dev/null
++++ b/tools/grit/OWNERS
+@@ -0,0 +1,8 @@
++agrieve@chromium.org
++flackr@chromium.org
++thakis@chromium.org
++thestig@chromium.org
++
++# Admin policy related grit tools.
++per-file *policy*=file://components/policy/tools/OWNERS
++per-file *admin_template*=file://components/policy/tools/OWNERS
+diff --git a/tools/grit/PRESUBMIT.py b/tools/grit/PRESUBMIT.py
+new file mode 100644
+index 0000000000..03b7188551
+--- /dev/null
++++ b/tools/grit/PRESUBMIT.py
+@@ -0,0 +1,22 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""grit unittests presubmit script.
++
++See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
++details on the presubmit API built into gcl.
++"""
++
++
++def RunUnittests(input_api, output_api):
++ return input_api.canned_checks.RunUnitTests(input_api, output_api,
++ [input_api.os_path.join('grit', 'test_suite_all.py')])
++
++
++def CheckChangeOnUpload(input_api, output_api):
++ return RunUnittests(input_api, output_api)
++
++
++def CheckChangeOnCommit(input_api, output_api):
++ return RunUnittests(input_api, output_api)
+diff --git a/tools/grit/README.md b/tools/grit/README.md
+new file mode 100644
+index 0000000000..b5c3f4b51b
+--- /dev/null
++++ b/tools/grit/README.md
+@@ -0,0 +1,19 @@
++# GRIT (Google Resource and Internationalization Tool)
++
++This is a tool for projects to manage resources and simplify the localization
++workflow.
++
++See the user guide for more details on using this project:
++https://dev.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide
++
++## History
++
++This code previously used to live at
++https://code.google.com/p/grit-i18n/source/checkout which still contains the
++project's history. https://chromium.googlesource.com/external/grit-i18n/ is
++a git mirror of the SVN repository that's identical except for the last two
++commits. The project is now developed in the Chromium project directly.
++
++There is a read-only mirror of just this directory at
++https://chromium.googlesource.com/chromium/src/tools/grit/ if you don't want to
++check out all of Chromium.
+diff --git a/tools/grit/grit.py b/tools/grit/grit.py
+new file mode 100644
+index 0000000000..abd1ab6449
+--- /dev/null
++++ b/tools/grit/grit.py
+@@ -0,0 +1,31 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Bootstrapping for GRIT.
++'''
++
++from __future__ import print_function
++
++import os
++import sys
++
++import grit.grit_runner
++
++sys.path.append(
++ os.path.join(
++ os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
++ 'diagnosis'))
++try:
++ import crbug_1001171
++except ImportError:
++ crbug_1001171 = None
++
++
++if __name__ == '__main__':
++ if crbug_1001171:
++ with crbug_1001171.DumpStateOnLookupError():
++ sys.exit(grit.grit_runner.Main(sys.argv[1:]))
++ else:
++ sys.exit(grit.grit_runner.Main(sys.argv[1:]))
+diff --git a/tools/grit/grit/__init__.py b/tools/grit/grit/__init__.py
+new file mode 100644
+index 0000000000..91ac9ee896
+--- /dev/null
++++ b/tools/grit/grit/__init__.py
+@@ -0,0 +1,19 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Package 'grit'
++'''
++
++from __future__ import print_function
++
++import os
++import sys
++
++
++_CUR_DIR = os.path.abspath(os.path.dirname(__file__))
++_GRIT_DIR = os.path.dirname(_CUR_DIR)
++_THIRD_PARTY_DIR = os.path.join(_GRIT_DIR, 'third_party')
++
++if _THIRD_PARTY_DIR not in sys.path:
++ sys.path.insert(0, _THIRD_PARTY_DIR)
+diff --git a/tools/grit/grit/clique.py b/tools/grit/grit/clique.py
+new file mode 100644
+index 0000000000..e7be3ec164
+--- /dev/null
++++ b/tools/grit/grit/clique.py
+@@ -0,0 +1,491 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Collections of messages and their translations, called cliques. Also
++collections of cliques (uber-cliques).
++'''
++
++from __future__ import print_function
++
++import re
++
++import six
++
++from grit import constants
++from grit import exception
++from grit import lazy_re
++from grit import pseudo
++from grit import pseudo_rtl
++from grit import tclib
++
++
++class UberClique(object):
++ '''A factory (NOT a singleton factory) for making cliques. It has several
++ methods for working with the cliques created using the factory.
++ '''
++
++ def __init__(self):
++ # A map from message ID to list of cliques whose source messages have
++ # that ID. This will contain all cliques created using this factory.
++ # Different messages can have the same ID because they have the
++ # same translateable portion and placeholder names, but occur in different
++ # places in the resource tree.
++ #
++ # Each list of cliques is kept sorted by description, to achieve
++ # stable results from the BestClique method, see below.
++ self.cliques_ = {}
++
++ # A map of clique IDs to list of languages to indicate translations where we
++ # fell back to English.
++ self.fallback_translations_ = {}
++
++ # A map of clique IDs to list of languages to indicate missing translations.
++ self.missing_translations_ = {}
++
++ def _AddMissingTranslation(self, lang, clique, is_error):
++ tl = self.fallback_translations_
++ if is_error:
++ tl = self.missing_translations_
++ id = clique.GetId()
++ if id not in tl:
++ tl[id] = {}
++ if lang not in tl[id]:
++ tl[id][lang] = 1
++
++ def HasMissingTranslations(self):
++ return len(self.missing_translations_) > 0
++
++ def MissingTranslationsReport(self):
++ '''Returns a string suitable for printing to report missing
++ and fallback translations to the user.
++ '''
++ def ReportTranslation(clique, langs):
++ text = clique.GetMessage().GetPresentableContent()
++ # The text 'error' (usually 'Error:' but we are conservative)
++ # can trigger some build environments (Visual Studio, we're
++ # looking at you) to consider invocation of grit to have failed,
++ # so we make sure never to output that word.
++ extract = re.sub(r'(?i)error', 'REDACTED', text[0:40])[0:40]
++ ellipsis = ''
++ if len(text) > 40:
++ ellipsis = '...'
++ langs_extract = langs[0:6]
++ describe_langs = ','.join(langs_extract)
++ if len(langs) > 6:
++ describe_langs += " and %d more" % (len(langs) - 6)
++ return " %s \"%s%s\" %s" % (clique.GetId(), extract, ellipsis,
++ describe_langs)
++ lines = []
++ if len(self.fallback_translations_):
++ lines.append(
++ "WARNING: Fell back to English for the following translations:")
++ for (id, langs) in self.fallback_translations_.items():
++ lines.append(
++ ReportTranslation(self.cliques_[id][0], list(langs.keys())))
++ if len(self.missing_translations_):
++ lines.append("ERROR: The following translations are MISSING:")
++ for (id, langs) in self.missing_translations_.items():
++ lines.append(
++ ReportTranslation(self.cliques_[id][0], list(langs.keys())))
++ return '\n'.join(lines)
++
++ def MakeClique(self, message, translateable=True):
++ '''Create a new clique initialized with a message.
++
++ Args:
++ message: tclib.Message()
++ translateable: True | False
++ '''
++ clique = MessageClique(self, message, translateable)
++
++ # Enable others to find this clique by its message ID
++ if message.GetId() in self.cliques_:
++ presentable_text = clique.GetMessage().GetPresentableContent()
++ if not message.HasAssignedId():
++ for c in self.cliques_[message.GetId()]:
++ assert c.GetMessage().GetPresentableContent() == presentable_text
++ self.cliques_[message.GetId()].append(clique)
++ # We need to keep each list of cliques sorted by description, to
++ # achieve stable results from the BestClique method, see below.
++ self.cliques_[message.GetId()].sort(
++ key=lambda c:c.GetMessage().GetDescription())
++ else:
++ self.cliques_[message.GetId()] = [clique]
++
++ return clique
++
++ def FindCliqueAndAddTranslation(self, translation, language):
++ '''Adds the specified translation to the clique with the source message
++ it is a translation of.
++
++ Args:
++ translation: tclib.Translation()
++ language: 'en' | 'fr' ...
++
++ Return:
++ True if the source message was found, otherwise false.
++ '''
++ if translation.GetId() in self.cliques_:
++ for clique in self.cliques_[translation.GetId()]:
++ clique.AddTranslation(translation, language)
++ return True
++ else:
++ return False
++
++ def BestClique(self, id):
++ '''Returns the "best" clique from a list of cliques. All the cliques
++ must have the same ID. The "best" clique is chosen in the following
++ order of preference:
++ - The first clique that has a non-ID-based description.
++ - If no such clique found, the first clique with an ID-based description.
++ - Otherwise the first clique.
++
++ This method is stable in terms of always returning a clique with
++ an identical description (on different runs of GRIT on the same
++ data) because self.cliques_ is sorted by description.
++ '''
++ clique_list = self.cliques_[id]
++ clique_with_id = None
++ clique_default = None
++ for clique in clique_list:
++ if not clique_default:
++ clique_default = clique
++
++ description = clique.GetMessage().GetDescription()
++ if description and len(description) > 0:
++ if not description.startswith('ID:'):
++ # this is the preferred case so we exit right away
++ return clique
++ elif not clique_with_id:
++ clique_with_id = clique
++ if clique_with_id:
++ return clique_with_id
++ else:
++ return clique_default
++
++ def BestCliquePerId(self):
++ '''Iterates over the list of all cliques and returns the best clique for
++ each ID. This will be the first clique with a source message that has a
++ non-empty description, or an arbitrary clique if none of them has a
++ description.
++ '''
++ for id in self.cliques_:
++ yield self.BestClique(id)
++
++ def BestCliqueByOriginalText(self, text, meaning):
++ '''Finds the "best" (as in BestClique()) clique that has original text
++ 'text' and meaning 'meaning'. Returns None if there is no such clique.
++ '''
++ # If needed, this can be optimized by maintaining a map of
++ # fingerprints of original text+meaning to cliques.
++ for c in self.BestCliquePerId():
++ msg = c.GetMessage()
++ if msg.GetRealContent() == text and msg.GetMeaning() == meaning:
++ return msg
++ return None
++
++ def AllMessageIds(self):
++ '''Returns a list of all defined message IDs.
++ '''
++ return list(self.cliques_.keys())
++
++ def AllCliques(self):
++ '''Iterates over all cliques. Note that this can return multiple cliques
++ with the same ID.
++ '''
++ for cliques in self.cliques_.values():
++ for c in cliques:
++ yield c
++
++ def GenerateXtbParserCallback(self, lang, debug=False):
++ '''Creates a callback function as required by grit.xtb_reader.Parse().
++ This callback will create Translation objects for each message from
++ the XTB that exists in this uberclique, and add them as translations for
++ the relevant cliques. The callback will add translations to the language
++ specified by 'lang'
++
++ Args:
++ lang: 'fr'
++ debug: True | False
++ '''
++ def Callback(id, structure):
++ if id not in self.cliques_:
++ if debug:
++ print("Ignoring translation #%s" % id)
++ return
++
++ if debug:
++ print("Adding translation #%s" % id)
++
++ # We fetch placeholder information from the original message (the XTB file
++ # only contains placeholder names).
++ original_msg = self.BestClique(id).GetMessage()
++
++ translation = tclib.Translation(id=id)
++ for is_ph,text in structure:
++ if not is_ph:
++ translation.AppendText(text)
++ else:
++ found_placeholder = False
++ for ph in original_msg.GetPlaceholders():
++ if ph.GetPresentation() == text:
++ translation.AppendPlaceholder(tclib.Placeholder(
++ ph.GetPresentation(), ph.GetOriginal(), ph.GetExample()))
++ found_placeholder = True
++ break
++ if not found_placeholder:
++ raise exception.MismatchingPlaceholders(
++ 'Translation for message ID %s had <ph name="%s"/>, no match\n'
++ 'in original message' % (id, text))
++ self.FindCliqueAndAddTranslation(translation, lang)
++ return Callback
++
++
++class CustomType(object):
++ '''A base class you should implement if you wish to specify a custom type
++ for a message clique (i.e. custom validation and optional modification of
++ translations).'''
++
++ def Validate(self, message):
++ '''Returns true if the message (a tclib.Message object) is valid,
++ otherwise false.
++ '''
++ raise NotImplementedError()
++
++ def ValidateAndModify(self, lang, translation):
++ '''Returns true if the translation (a tclib.Translation object) is valid,
++ otherwise false. The language is also passed in. This method may modify
++ the translation that is passed in, if it so wishes.
++ '''
++ raise NotImplementedError()
++
++ def ModifyTextPart(self, lang, text):
++ '''If you call ModifyEachTextPart, it will turn around and call this method
++ for each text part of the translation. You should return the modified
++ version of the text, or just the original text to not change anything.
++ '''
++ raise NotImplementedError()
++
++ def ModifyEachTextPart(self, lang, translation):
++ '''Call this to easily modify one or more of the textual parts of a
++ translation. It will call ModifyTextPart for each part of the
++ translation.
++ '''
++ contents = translation.GetContent()
++ for ix in range(len(contents)):
++ if (isinstance(contents[ix], six.string_types)):
++ contents[ix] = self.ModifyTextPart(lang, contents[ix])
++
++
++class OneOffCustomType(CustomType):
++ '''A very simple custom type that performs the validation expressed by
++ the input expression on all languages including the source language.
++ The expression can access the variables 'lang', 'msg' and 'text()' where
++ 'lang' is the language of 'msg', 'msg' is the message or translation being
++ validated and 'text()' returns the real contents of 'msg' (for shorthand).
++ '''
++ def __init__(self, expression):
++ self.expr = expression
++ def Validate(self, message):
++ return self.ValidateAndModify(MessageClique.source_language, message)
++ def ValidateAndModify(self, lang, msg):
++ def text():
++ return msg.GetRealContent()
++ return eval(self.expr, {},
++ {'lang' : lang,
++ 'text' : text,
++ 'msg' : msg,
++ })
++
++
++class MessageClique(object):
++ '''A message along with all of its translations. Also code to bring
++ translations together with their original message.'''
++
++ # change this to the language code of Messages you add to cliques_.
++ # TODO(joi) Actually change this based on the <grit> node's source language
++ source_language = 'en'
++
++ # A constant translation we use when asked for a translation into the
++ # special language constants.CONSTANT_LANGUAGE.
++ CONSTANT_TRANSLATION = tclib.Translation(text='TTTTTT')
++
++ # A pattern to match messages that are empty or whitespace only.
++ WHITESPACE_MESSAGE = lazy_re.compile(r'^\s*$')
++
++ def __init__(self, uber_clique, message, translateable=True,
++ custom_type=None):
++ '''Create a new clique initialized with just a message.
++
++ Note that messages with a body comprised only of whitespace will implicitly
++ be marked non-translatable.
++
++ Args:
++ uber_clique: Our uber-clique (collection of cliques)
++ message: tclib.Message()
++ translateable: True | False
++ custom_type: instance of clique.CustomType interface
++ '''
++ # Our parent
++ self.uber_clique = uber_clique
++ # If not translateable, we only store the original message.
++ self.translateable = translateable
++
++ # We implicitly mark messages that have a whitespace-only body as
++ # non-translateable.
++ if MessageClique.WHITESPACE_MESSAGE.match(message.GetRealContent()):
++ self.translateable = False
++
++ # A mapping of language identifiers to tclib.BaseMessage and its
++ # subclasses (i.e. tclib.Message and tclib.Translation).
++ self.clique = { MessageClique.source_language : message }
++ # A list of the "shortcut groups" this clique is
++ # part of. Within any given shortcut group, no shortcut key (e.g. &J)
++ # must appear more than once in each language for all cliques that
++ # belong to the group.
++ self.shortcut_groups = []
++ # An instance of the CustomType interface, or None. If this is set, it will
++ # be used to validate the original message and translations thereof, and
++ # will also get a chance to modify translations of the message.
++ self.SetCustomType(custom_type)
++
++ def GetMessage(self):
++ '''Retrieves the tclib.Message that is the source for this clique.'''
++ return self.clique[MessageClique.source_language]
++
++ def GetId(self):
++ '''Retrieves the message ID of the messages in this clique.'''
++ return self.GetMessage().GetId()
++
++ def IsTranslateable(self):
++ return self.translateable
++
++ def AddToShortcutGroup(self, group):
++ self.shortcut_groups.append(group)
++
++ def SetCustomType(self, custom_type):
++ '''Makes this clique use custom_type for validating messages and
++ translations, and optionally modifying translations.
++ '''
++ self.custom_type = custom_type
++ if custom_type and not custom_type.Validate(self.GetMessage()):
++ raise exception.InvalidMessage(self.GetMessage().GetRealContent())
++
++ def MessageForLanguage(self, lang, pseudo_if_no_match=True,
++ fallback_to_english=False):
++ '''Returns the message/translation for the specified language, providing
++ a pseudotranslation if there is no available translation and a pseudo-
++ translation is requested.
++
++ The translation of any message whatsoever in the special language
++ 'x_constant' is the message "TTTTTT".
++
++ Args:
++ lang: 'en'
++ pseudo_if_no_match: True
++ fallback_to_english: False
++
++ Return:
++ tclib.BaseMessage
++ '''
++ if not self.translateable:
++ return self.GetMessage()
++
++ if lang == constants.CONSTANT_LANGUAGE:
++ return self.CONSTANT_TRANSLATION
++
++ for msglang in self.clique:
++ if lang == msglang:
++ return self.clique[msglang]
++
++ if lang == constants.FAKE_BIDI:
++ return pseudo_rtl.PseudoRTLMessage(self.GetMessage())
++
++ if fallback_to_english:
++ self.uber_clique._AddMissingTranslation(lang, self, is_error=False)
++ return self.GetMessage()
++
++ # If we're not supposed to generate pseudotranslations, we add an error
++ # report to a list of errors, then fail at a higher level, so that we
++ # get a list of all messages that are missing translations.
++ if not pseudo_if_no_match:
++ self.uber_clique._AddMissingTranslation(lang, self, is_error=True)
++
++ return pseudo.PseudoMessage(self.GetMessage())
++
++ def AllMessagesThatMatch(self, lang_re, include_pseudo = True):
++ '''Returns a map of all messages that match 'lang', including the pseudo
++ translation if requested.
++
++ Args:
++ lang_re: re.compile(r'fr|en')
++ include_pseudo: True
++
++ Return:
++ { 'en' : tclib.Message,
++ 'fr' : tclib.Translation,
++ pseudo.PSEUDO_LANG : tclib.Translation }
++ '''
++ if not self.translateable:
++ return [self.GetMessage()]
++
++ matches = {}
++ for msglang in self.clique:
++ if lang_re.match(msglang):
++ matches[msglang] = self.clique[msglang]
++
++ if include_pseudo:
++ matches[pseudo.PSEUDO_LANG] = pseudo.PseudoMessage(self.GetMessage())
++
++ return matches
++
++ def AddTranslation(self, translation, language):
++ '''Add a translation to this clique. The translation must have the same
++ ID as the message that is the source for this clique.
++
++ If this clique is not translateable, the function just returns.
++
++ Args:
++ translation: tclib.Translation()
++ language: 'en'
++
++ Throws:
++ grit.exception.InvalidTranslation if the translation you're trying to add
++ doesn't have the same message ID as the source message of this clique.
++ '''
++ if not self.translateable:
++ return
++ if translation.GetId() != self.GetId():
++ raise exception.InvalidTranslation(
++ 'Msg ID %s, transl ID %s' % (self.GetId(), translation.GetId()))
++
++ assert not language in self.clique
++
++ # Because two messages can differ in the original content of their
++ # placeholders yet share the same ID (because they are otherwise the
++ # same), the translation we are getting may have different original
++ # content for placeholders than our message, yet it is still the right
++ # translation for our message (because it is for the same ID). We must
++ # therefore fetch the original content of placeholders from our original
++ # English message.
++ #
++ # See grit.clique_unittest.MessageCliqueUnittest.testSemiIdenticalCliques
++ # for a concrete explanation of why this is necessary.
++
++ original = self.MessageForLanguage(self.source_language, False)
++ if len(original.GetPlaceholders()) != len(translation.GetPlaceholders()):
++ print("ERROR: '%s' translation of message id %s does not match" %
++ (language, translation.GetId()))
++ assert False
++
++ transl_msg = tclib.Translation(id=self.GetId(),
++ text=translation.GetPresentableContent(),
++ placeholders=original.GetPlaceholders())
++
++ if (self.custom_type and
++ not self.custom_type.ValidateAndModify(language, transl_msg)):
++ print("WARNING: %s translation failed validation: %s" %
++ (language, transl_msg.GetId()))
++
++ self.clique[language] = transl_msg
+diff --git a/tools/grit/grit/clique_unittest.py b/tools/grit/grit/clique_unittest.py
+new file mode 100644
+index 0000000000..7d2d7318ba
+--- /dev/null
++++ b/tools/grit/grit/clique_unittest.py
+@@ -0,0 +1,265 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.clique'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import re
++import unittest
++
++from six import StringIO
++
++from grit import clique
++from grit import exception
++from grit import pseudo
++from grit import tclib
++from grit import grd_reader
++from grit import util
++
++class MessageCliqueUnittest(unittest.TestCase):
++ def testClique(self):
++ factory = clique.UberClique()
++ msg = tclib.Message(text='Hello USERNAME, how are you?',
++ placeholders=[
++ tclib.Placeholder('USERNAME', '%s', 'Joi')])
++ c = factory.MakeClique(msg)
++
++ self.failUnless(c.GetMessage() == msg)
++ self.failUnless(c.GetId() == msg.GetId())
++
++ msg_fr = tclib.Translation(text='Bonjour USERNAME, comment ca va?',
++ id=msg.GetId(), placeholders=[
++ tclib.Placeholder('USERNAME', '%s', 'Joi')])
++ msg_de = tclib.Translation(text='Guten tag USERNAME, wie geht es dir?',
++ id=msg.GetId(), placeholders=[
++ tclib.Placeholder('USERNAME', '%s', 'Joi')])
++
++ c.AddTranslation(msg_fr, 'fr')
++ factory.FindCliqueAndAddTranslation(msg_de, 'de')
++
++ # sort() sorts lists in-place and does not return them
++ for lang in ('en', 'fr', 'de'):
++ self.failUnless(lang in c.clique)
++
++ self.failUnless(c.MessageForLanguage('fr').GetRealContent() ==
++ msg_fr.GetRealContent())
++
++ try:
++ c.MessageForLanguage('zh-CN', False)
++ self.fail('Should have gotten exception')
++ except:
++ pass
++
++ self.failUnless(c.MessageForLanguage('zh-CN', True) != None)
++
++ rex = re.compile('fr|de|bingo')
++ self.failUnless(len(c.AllMessagesThatMatch(rex, False)) == 2)
++ self.failUnless(
++ c.AllMessagesThatMatch(rex, True)[pseudo.PSEUDO_LANG] is not None)
++
++ def testBestClique(self):
++ factory = clique.UberClique()
++ factory.MakeClique(tclib.Message(text='Alfur', description='alfaholl'))
++ factory.MakeClique(tclib.Message(text='Alfur', description=''))
++ factory.MakeClique(tclib.Message(text='Vaettur', description=''))
++ factory.MakeClique(tclib.Message(text='Vaettur', description=''))
++ factory.MakeClique(tclib.Message(text='Troll', description=''))
++ factory.MakeClique(tclib.Message(text='Gryla', description='ID: IDS_GRYLA'))
++ factory.MakeClique(tclib.Message(text='Gryla', description='vondakerling'))
++ factory.MakeClique(tclib.Message(text='Leppaludi', description='ID: IDS_LL'))
++ factory.MakeClique(tclib.Message(text='Leppaludi', description=''))
++
++ count_best_cliques = 0
++ for c in factory.BestCliquePerId():
++ count_best_cliques += 1
++ msg = c.GetMessage()
++ text = msg.GetRealContent()
++ description = msg.GetDescription()
++ if text == 'Alfur':
++ self.failUnless(description == 'alfaholl')
++ elif text == 'Gryla':
++ self.failUnless(description == 'vondakerling')
++ elif text == 'Leppaludi':
++ self.failUnless(description == 'ID: IDS_LL')
++ self.failUnless(count_best_cliques == 5)
++
++ def testAllInUberClique(self):
++ resources = grd_reader.Parse(
++ StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ </messages>
++ <structures>
++ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
++ <structure type="tr_html" name="ID_HTML" file="grit/testdata/simple.html" />
++ </structures>
++ </release>
++</grit>'''), util.PathFromRoot('.'))
++ resources.SetOutputLanguage('en')
++ resources.RunGatherers()
++ content_list = []
++ for clique_list in resources.UberClique().cliques_.values():
++ for clique in clique_list:
++ content_list.append(clique.GetMessage().GetRealContent())
++ self.failUnless('Hello %s, how are you doing today?' in content_list)
++ self.failUnless('Jack "Black" Daniels' in content_list)
++ self.failUnless('Hello!' in content_list)
++
++ def testCorrectExceptionIfWrongEncodingOnResourceFile(self):
++ '''This doesn't really belong in this unittest file, but what the heck.'''
++ resources = grd_reader.Parse(
++ StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <structures>
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit/testdata/klonk.rc" />
++ </structures>
++ </release>
++</grit>'''), util.PathFromRoot('.'))
++ self.assertRaises(exception.SectionNotFound, resources.RunGatherers)
++
++ def testSemiIdenticalCliques(self):
++ messages = [
++ tclib.Message(text='Hello USERNAME',
++ placeholders=[tclib.Placeholder('USERNAME', '$1', 'Joi')]),
++ tclib.Message(text='Hello USERNAME',
++ placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi')]),
++ ]
++ self.failUnless(messages[0].GetId() == messages[1].GetId())
++
++ # Both of the above would share a translation.
++ translation = tclib.Translation(id=messages[0].GetId(),
++ text='Bonjour USERNAME',
++ placeholders=[tclib.Placeholder(
++ 'USERNAME', '$1', 'Joi')])
++
++ factory = clique.UberClique()
++ cliques = [factory.MakeClique(msg) for msg in messages]
++
++ for clq in cliques:
++ clq.AddTranslation(translation, 'fr')
++
++ self.failUnless(cliques[0].MessageForLanguage('fr').GetRealContent() ==
++ 'Bonjour $1')
++ self.failUnless(cliques[1].MessageForLanguage('fr').GetRealContent() ==
++ 'Bonjour %s')
++
++ def testMissingTranslations(self):
++ messages = [ tclib.Message(text='Hello'), tclib.Message(text='Goodbye') ]
++ factory = clique.UberClique()
++ cliques = [factory.MakeClique(msg) for msg in messages]
++
++ cliques[1].MessageForLanguage('fr', False, True)
++
++ self.failUnless(not factory.HasMissingTranslations())
++
++ cliques[0].MessageForLanguage('de', False, False)
++
++ self.failUnless(factory.HasMissingTranslations())
++
++ report = factory.MissingTranslationsReport()
++ self.failUnless(report.count('WARNING') == 1)
++ self.failUnless(report.count('8053599568341804890 "Goodbye" fr') == 1)
++ self.failUnless(report.count('ERROR') == 1)
++ self.failUnless(report.count('800120468867715734 "Hello" de') == 1)
++
++ def testCustomTypes(self):
++ factory = clique.UberClique()
++ message = tclib.Message(text='Bingo bongo')
++ c = factory.MakeClique(message)
++ try:
++ c.SetCustomType(DummyCustomType())
++ self.fail()
++ except:
++ pass # expected case - 'Bingo bongo' does not start with 'jjj'
++
++ message = tclib.Message(text='jjjBingo bongo')
++ c = factory.MakeClique(message)
++ c.SetCustomType(util.NewClassInstance(
++ 'grit.clique_unittest.DummyCustomType', clique.CustomType))
++ translation = tclib.Translation(id=message.GetId(), text='Bilingo bolongo')
++ c.AddTranslation(translation, 'fr')
++ self.failUnless(c.MessageForLanguage('fr').GetRealContent().startswith('jjj'))
++
++ def testWhitespaceMessagesAreNontranslateable(self):
++ factory = clique.UberClique()
++
++ message = tclib.Message(text=' \t')
++ c = factory.MakeClique(message, translateable=True)
++ self.failIf(c.IsTranslateable())
++
++ message = tclib.Message(text='\n \n ')
++ c = factory.MakeClique(message, translateable=True)
++ self.failIf(c.IsTranslateable())
++
++ message = tclib.Message(text='\n hello')
++ c = factory.MakeClique(message, translateable=True)
++ self.failUnless(c.IsTranslateable())
++
++ def testEachCliqueKeptSorted(self):
++ factory = clique.UberClique()
++ msg_a = tclib.Message(text='hello', description='a')
++ msg_b = tclib.Message(text='hello', description='b')
++ msg_c = tclib.Message(text='hello', description='c')
++ # Insert out of order
++ clique_b = factory.MakeClique(msg_b, translateable=True)
++ clique_a = factory.MakeClique(msg_a, translateable=True)
++ clique_c = factory.MakeClique(msg_c, translateable=True)
++ clique_list = factory.cliques_[clique_a.GetId()]
++ self.failUnless(len(clique_list) == 3)
++ self.failUnless(clique_list[0] == clique_a)
++ self.failUnless(clique_list[1] == clique_b)
++ self.failUnless(clique_list[2] == clique_c)
++
++ def testBestCliqueSortIsStable(self):
++ factory = clique.UberClique()
++ text = 'hello'
++ msg_no_description = tclib.Message(text=text)
++ msg_id_description_a = tclib.Message(text=text, description='ID: a')
++ msg_id_description_b = tclib.Message(text=text, description='ID: b')
++ msg_description_x = tclib.Message(text=text, description='x')
++ msg_description_y = tclib.Message(text=text, description='y')
++ clique_id = msg_no_description.GetId()
++
++ # Insert in an order that tests all outcomes.
++ clique_no_description = factory.MakeClique(msg_no_description,
++ translateable=True)
++ self.failUnless(factory.BestClique(clique_id) == clique_no_description)
++ clique_id_description_b = factory.MakeClique(msg_id_description_b,
++ translateable=True)
++ self.failUnless(factory.BestClique(clique_id) == clique_id_description_b)
++ clique_id_description_a = factory.MakeClique(msg_id_description_a,
++ translateable=True)
++ self.failUnless(factory.BestClique(clique_id) == clique_id_description_a)
++ clique_description_y = factory.MakeClique(msg_description_y,
++ translateable=True)
++ self.failUnless(factory.BestClique(clique_id) == clique_description_y)
++ clique_description_x = factory.MakeClique(msg_description_x,
++ translateable=True)
++ self.failUnless(factory.BestClique(clique_id) == clique_description_x)
++
++
++class DummyCustomType(clique.CustomType):
++ def Validate(self, message):
++ return message.GetRealContent().startswith('jjj')
++ def ValidateAndModify(self, lang, translation):
++ is_ok = self.Validate(translation)
++ self.ModifyEachTextPart(lang, translation)
++ def ModifyTextPart(self, lang, text):
++ return 'jjj%s' % text
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/constants.py b/tools/grit/grit/constants.py
+new file mode 100644
+index 0000000000..8229c94b09
+--- /dev/null
++++ b/tools/grit/grit/constants.py
+@@ -0,0 +1,23 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Constant definitions for GRIT.
++'''
++
++from __future__ import print_function
++
++# This is the Icelandic noun meaning "grit" and is used to check that our
++# input files are in the correct encoding. The middle character gets encoded
++# as two bytes in UTF-8, so this is sufficient to detect incorrect encoding.
++ENCODING_CHECK = u'm\u00f6l'
++
++# A special language, translations into which are always "TTTTTT".
++CONSTANT_LANGUAGE = 'x_constant'
++
++FAKE_BIDI = 'fake-bidi'
++
++# Magic number added to the header of resources brotli compressed by grit. Used
++# to easily identify resources as being brotli compressed. See
++# ui/base/resource/resource_bundle.h for decompression usage.
++BROTLI_CONST = b'\x1e\x9b'
+diff --git a/tools/grit/grit/exception.py b/tools/grit/grit/exception.py
+new file mode 100644
+index 0000000000..2a363fb077
+--- /dev/null
++++ b/tools/grit/grit/exception.py
+@@ -0,0 +1,139 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Exception types for GRIT.
++'''
++
++from __future__ import print_function
++
++class Base(Exception):
++ '''A base exception that uses the class's docstring in addition to any
++ user-provided message as the body of the Base.
++ '''
++ def __init__(self, msg=''):
++ if len(msg):
++ if self.__doc__:
++ msg = self.__doc__ + ': ' + msg
++ else:
++ msg = self.__doc__
++ super(Base, self).__init__(msg)
++
++
++class Parsing(Base):
++ '''An error occurred parsing a GRD or XTB file.'''
++ pass
++
++
++class UnknownElement(Parsing):
++ '''An unknown node type was encountered.'''
++ pass
++
++
++class MissingElement(Parsing):
++ '''An expected element was missing.'''
++ pass
++
++
++class UnexpectedChild(Parsing):
++ '''An unexpected child element was encountered (on a leaf node).'''
++ pass
++
++
++class UnexpectedAttribute(Parsing):
++ '''The attribute was not expected'''
++ pass
++
++
++class UnexpectedContent(Parsing):
++ '''This element should not have content'''
++ pass
++
++class MissingMandatoryAttribute(Parsing):
++ '''This element is missing a mandatory attribute'''
++ pass
++
++
++class MutuallyExclusiveMandatoryAttribute(Parsing):
++ '''This element has 2 mutually exclusive mandatory attributes'''
++ pass
++
++
++class DuplicateKey(Parsing):
++ '''A duplicate key attribute was found.'''
++ pass
++
++
++class TooManyExamples(Parsing):
++ '''Only one <ex> element is allowed for each <ph> element.'''
++ pass
++
++
++class FileNotFound(Parsing):
++ '''The resource file was not found.'''
++ pass
++
++
++class InvalidMessage(Base):
++ '''The specified message failed validation.'''
++ pass
++
++
++class InvalidTranslation(Base):
++ '''Attempt to add an invalid translation to a clique.'''
++ pass
++
++
++class NoSuchTranslation(Base):
++ '''Requested translation not available'''
++ pass
++
++
++class NotReady(Base):
++ '''Attempt to use an object before it is ready, or attempt to translate \
++an empty document.'''
++ pass
++
++
++class MismatchingPlaceholders(Base):
++ '''Placeholders do not match.'''
++ pass
++
++
++class InvalidPlaceholderName(Base):
++ '''Placeholder name can only contain A-Z, a-z, 0-9 and underscore.'''
++ pass
++
++
++class BlockTagInTranslateableChunk(Base):
++ '''A block tag was encountered where it wasn't expected.'''
++ pass
++
++
++class SectionNotFound(Base):
++ '''The section you requested was not found in the RC file. Make \
++sure the section ID is correct (matches the section's ID in the RC file). \
++Also note that you may need to specify the RC file's encoding (using the \
++encoding="" attribute) if it is not in the default Windows-1252 encoding. \
++'''
++ pass
++
++
++class IdRangeOverlap(Base):
++ '''ID range overlap.'''
++ pass
++
++
++class ReservedHeaderCollision(Base):
++ '''Resource included with first 3 bytes matching reserved header.'''
++ pass
++
++
++class PlaceholderNotInsidePhNode(Base):
++ '''Placeholder formatters should be inside <ph> element.'''
++ pass
++
++
++class InvalidCharactersInsidePhNode(Base):
++ '''Invalid characters found inside <ph> element.'''
++ pass
+diff --git a/tools/grit/grit/extern/BogoFP.py b/tools/grit/grit/extern/BogoFP.py
+new file mode 100644
+index 0000000000..fc90145833
+--- /dev/null
++++ b/tools/grit/grit/extern/BogoFP.py
+@@ -0,0 +1,22 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Bogus fingerprint implementation, do not use for production,
++provided only as an example.
++
++Usage:
++ grit.py -h grit.extern.BogoFP xmb /tmp/foo
++"""
++
++from __future__ import print_function
++
++import grit.extern.FP
++
++
++def UnsignedFingerPrint(str, encoding='utf-8'):
++ """Generate a fingerprint not intended for production from str (it
++ reduces the precision of the production fingerprint by one bit).
++ """
++ return (0xFFFFF7FFFFFFFFFF &
++ grit.extern.FP._UnsignedFingerPrintImpl(str, encoding))
+diff --git a/tools/grit/grit/extern/FP.py b/tools/grit/grit/extern/FP.py
+new file mode 100644
+index 0000000000..f4ec4d943f
+--- /dev/null
++++ b/tools/grit/grit/extern/FP.py
+@@ -0,0 +1,72 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++from __future__ import print_function
++
++try:
++ import hashlib
++ _new_md5 = hashlib.md5
++except ImportError:
++ import md5
++ _new_md5 = md5.new
++
++
++"""64-bit fingerprint support for strings.
++
++Usage:
++ from extern import FP
++ print('Fingerprint is %ld' % FP.FingerPrint('Hello world!'))
++"""
++
++
++def _UnsignedFingerPrintImpl(str, encoding='utf-8'):
++ """Generate a 64-bit fingerprint by taking the first half of the md5
++ of the string.
++ """
++ hex128 = _new_md5(str.encode(encoding)).hexdigest()
++ int64 = int(hex128[:16], 16)
++ return int64
++
++
++def UnsignedFingerPrint(str, encoding='utf-8'):
++ """Generate a 64-bit fingerprint.
++
++ The default implementation uses _UnsignedFingerPrintImpl, which
++ takes the first half of the md5 of the string, but the
++ implementation may be switched using SetUnsignedFingerPrintImpl.
++ """
++ return _UnsignedFingerPrintImpl(str, encoding)
++
++
++def FingerPrint(str, encoding='utf-8'):
++ fp = UnsignedFingerPrint(str, encoding=encoding)
++ # interpret fingerprint as signed longs
++ if fp & 0x8000000000000000:
++ fp = -((~fp & 0xFFFFFFFFFFFFFFFF) + 1)
++ return fp
++
++
++def UseUnsignedFingerPrintFromModule(module_name):
++ """Imports module_name and replaces UnsignedFingerPrint in the
++ current module with the function of the same name from the imported
++ module.
++
++ Returns the function object previously known as
++ grit.extern.FP.UnsignedFingerPrint.
++ """
++ hash_module = __import__(module_name, fromlist=[module_name])
++ return SetUnsignedFingerPrint(hash_module.UnsignedFingerPrint)
++
++
++def SetUnsignedFingerPrint(function_object):
++ """Sets grit.extern.FP.UnsignedFingerPrint to point to
++ function_object.
++
++ Returns the function object previously known as
++ grit.extern.FP.UnsignedFingerPrint.
++ """
++ global UnsignedFingerPrint
++ original_function_object = UnsignedFingerPrint
++ UnsignedFingerPrint = function_object
++ return original_function_object
+diff --git a/tools/grit/grit/extern/__init__.py b/tools/grit/grit/extern/__init__.py
+new file mode 100644
+index 0000000000..e69de29bb2
+diff --git a/tools/grit/grit/extern/tclib.py b/tools/grit/grit/extern/tclib.py
+new file mode 100644
+index 0000000000..9952a87c11
+--- /dev/null
++++ b/tools/grit/grit/extern/tclib.py
+@@ -0,0 +1,503 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++# The tclib module contains tools for aggregating, verifying, and storing
++# messages destined for the Translation Console, as well as for reading
++# translations back and outputting them in some desired format.
++#
++# This has been stripped down to include only the functionality needed by grit
++# for creating Windows .rc and .h files. These are the only parts needed by
++# the Chrome build process.
++
++from __future__ import print_function
++
++from grit.extern import FP
++
++# This module assumes that within a bundle no two messages can have the
++# same id unless they're identical.
++
++# The basic classes defined here for external use are Message and Translation,
++# where the former is used for English messages and the latter for
++# translations. These classes have a lot of common functionality, as expressed
++# by the common parent class BaseMessage. Perhaps the most important
++# distinction is that translated text is stored in UTF-8, whereas original text
++# is stored in whatever encoding the client uses (presumably Latin-1).
++
++# --------------------
++# The public interface
++# --------------------
++
++# Generate message id from message text and meaning string (optional),
++# both in utf-8 encoding
++#
++def GenerateMessageId(message, meaning=''):
++ fp = FP.FingerPrint(message)
++ if meaning:
++ # combine the fingerprints of message and meaning
++ fp2 = FP.FingerPrint(meaning)
++ if fp < 0:
++ fp = fp2 + (fp << 1) + 1
++ else:
++ fp = fp2 + (fp << 1)
++ # To avoid negative ids we strip the high-order bit
++ return str(fp & 0x7fffffffffffffff)
++
++# -------------------------------------------------------------------------
++# The MessageTranslationError class is used to signal tclib-specific errors.
++
++
++class MessageTranslationError(Exception):
++
++ def __init__(self, args = ''):
++ self.args = args
++
++
++# -----------------------------------------------------------
++# The Placeholder class represents a placeholder in a message.
++
++class Placeholder(object):
++ # String representation
++ def __str__(self):
++ return '%s, "%s", "%s"' % \
++ (self.__presentation, self.__original, self.__example)
++
++ # Getters
++ def GetOriginal(self):
++ return self.__original
++
++ def GetPresentation(self):
++ return self.__presentation
++
++ def GetExample(self):
++ return self.__example
++
++ def __eq__(self, other):
++ return self.EqualTo(other, strict=1, ignore_trailing_spaces=0)
++
++ # Equality test
++ #
++ # ignore_trailing_spaces: TC is using varchar to store the
++ # phrwr fields, as a result of that, the trailing spaces
++ # are removed by MySQL when the strings are stored into TC:-(
++ # ignore_trailing_spaces parameter is used to ignore
++ # trailing spaces during equivalence comparison.
++ #
++ def EqualTo(self, other, strict = 1, ignore_trailing_spaces = 1):
++ if type(other) is not Placeholder:
++ return 0
++ if StringEquals(self.__presentation, other.__presentation,
++ ignore_trailing_spaces):
++ if not strict or (StringEquals(self.__original, other.__original,
++ ignore_trailing_spaces) and
++ StringEquals(self.__example, other.__example,
++ ignore_trailing_spaces)):
++ return 1
++ return 0
++
++
++# -----------------------------------------------------------------
++# BaseMessage is the common parent class of Message and Translation.
++# It is not meant for direct use.
++
++class BaseMessage(object):
++ # Three types of message construction is supported. If the message text is a
++ # simple string with no dynamic content, you can pass it to the constructor
++ # as the "text" parameter. Otherwise, you can omit "text" and assemble the
++ # message step by step using AppendText() and AppendPlaceholder(). Or, as an
++ # alternative, you can give the constructor the "presentable" version of the
++ # message and a list of placeholders; it will then parse the presentation and
++ # build the message accordingly. For example:
++ # Message(text = "There are NUM_BUGS bugs in your code",
++ # placeholders = [Placeholder("NUM_BUGS", "%d", "33")],
++ # description = "Bla bla bla")
++ def __eq__(self, other):
++ # "source encoding" is nonsense, so ignore it
++ return _ObjectEquals(self, other, ['_BaseMessage__source_encoding'])
++
++ def GetName(self):
++ return self.__name
++
++ def GetSourceEncoding(self):
++ return self.__source_encoding
++
++ # Append a placeholder to the message
++ def AppendPlaceholder(self, placeholder):
++ if not isinstance(placeholder, Placeholder):
++ raise MessageTranslationError("Invalid message placeholder %s in "
++ "message %s" % (placeholder, self.GetId()))
++ # Are there other placeholders with the same presentation?
++ # If so, they need to be the same.
++ for other in self.GetPlaceholders():
++ if placeholder.GetPresentation() == other.GetPresentation():
++ if not placeholder.EqualTo(other):
++ raise MessageTranslationError(
++ "Conflicting declarations of %s within message" %
++ placeholder.GetPresentation())
++ # update placeholder list
++ dup = 0
++ for item in self.__content:
++ if isinstance(item, Placeholder) and placeholder.EqualTo(item):
++ dup = 1
++ break
++ if not dup:
++ self.__placeholders.append(placeholder)
++
++ # update content
++ self.__content.append(placeholder)
++
++ # Strips leading and trailing whitespace, and returns a tuple
++ # containing the leading and trailing space that was removed.
++ def Strip(self):
++ leading = trailing = ''
++ if len(self.__content) > 0:
++ s0 = self.__content[0]
++ if not isinstance(s0, Placeholder):
++ s = s0.lstrip()
++ leading = s0[:-len(s)]
++ self.__content[0] = s
++
++ s0 = self.__content[-1]
++ if not isinstance(s0, Placeholder):
++ s = s0.rstrip()
++ trailing = s0[len(s):]
++ self.__content[-1] = s
++ return leading, trailing
++
++ # Return the id of this message
++ def GetId(self):
++ if self.__id is None:
++ return self.GenerateId()
++ return self.__id
++
++ # Set the id of this message
++ def SetId(self, id):
++ if id is None:
++ self.__id = None
++ else:
++ self.__id = str(id) # Treat numerical ids as strings
++
++ # Return content of this message as a list (internal use only)
++ def GetContent(self):
++ return self.__content
++
++ # Return a human-readable version of this message
++ def GetPresentableContent(self):
++ presentable_content = ""
++ for item in self.__content:
++ if isinstance(item, Placeholder):
++ presentable_content += item.GetPresentation()
++ else:
++ presentable_content += item
++
++ return presentable_content
++
++ # Return a fragment of a message in escaped format
++ def EscapeFragment(self, fragment):
++ return fragment.replace('%', '%%')
++
++ # Return the "original" version of this message, doing %-escaping
++ # properly. If source_msg is specified, the placeholder original
++ # information inside source_msg will be used instead.
++ def GetOriginalContent(self, source_msg = None):
++ original_content = ""
++ for item in self.__content:
++ if isinstance(item, Placeholder):
++ if source_msg:
++ ph = source_msg.GetPlaceholder(item.GetPresentation())
++ if not ph:
++ raise MessageTranslationError(
++ "Placeholder %s doesn't exist in message: %s" %
++ (item.GetPresentation(), source_msg))
++ original_content += ph.GetOriginal()
++ else:
++ original_content += item.GetOriginal()
++ else:
++ original_content += self.EscapeFragment(item)
++ return original_content
++
++ # Return the example of this message
++ def GetExampleContent(self):
++ example_content = ""
++ for item in self.__content:
++ if isinstance(item, Placeholder):
++ example_content += item.GetExample()
++ else:
++ example_content += item
++ return example_content
++
++ # Return a list of all unique placeholders in this message
++ def GetPlaceholders(self):
++ return self.__placeholders
++
++ # Return a placeholder in this message
++ def GetPlaceholder(self, presentation):
++ for item in self.__content:
++ if (isinstance(item, Placeholder) and
++ item.GetPresentation() == presentation):
++ return item
++ return None
++
++ # Return this message's description
++ def GetDescription(self):
++ return self.__description
++
++ # Add a message source
++ def AddSource(self, source):
++ self.__sources.append(source)
++
++ # Return this message's sources as a list
++ def GetSources(self):
++ return self.__sources
++
++ # Return this message's sources as a string
++ def GetSourcesAsText(self, delimiter = "; "):
++ return delimiter.join(self.__sources)
++
++ # Set the obsolete flag for a message (internal use only)
++ def SetObsolete(self):
++ self.__obsolete = 1
++
++ # Get the obsolete flag for a message (internal use only)
++ def IsObsolete(self):
++ return self.__obsolete
++
++ # Get the sequence number (0 by default)
++ def GetSequenceNumber(self):
++ return self.__sequence_number
++
++ # Set the sequence number
++ def SetSequenceNumber(self, number):
++ self.__sequence_number = number
++
++ # Increment instance counter
++ def AddInstance(self):
++ self.__num_instances += 1
++
++ # Return instance count
++ def GetNumInstances(self):
++ return self.__num_instances
++
++ def GetErrors(self, from_tc=0):
++ """
++ Returns a description of the problem if the message is not
++ syntactically valid, or None if everything is fine.
++
++ Args:
++ from_tc: indicates whether this message came from the TC. We let
++ the TC get away with some things we normally wouldn't allow for
++ historical reasons.
++ """
++ # check that placeholders are unambiguous
++ pos = 0
++ phs = {}
++ for item in self.__content:
++ if isinstance(item, Placeholder):
++ phs[pos] = item
++ pos += len(item.GetPresentation())
++ else:
++ pos += len(item)
++ presentation = self.GetPresentableContent()
++ for ph in self.GetPlaceholders():
++ for pos in FindOverlapping(presentation, ph.GetPresentation()):
++ # message contains the same text as a placeholder presentation
++ other_ph = phs.get(pos)
++ if ((not other_ph
++ and not IsSubstringInPlaceholder(pos, len(ph.GetPresentation()), phs))
++ or
++ (other_ph and len(other_ph.GetPresentation()) < len(ph.GetPresentation()))):
++ return "message contains placeholder name '%s':\n%s" % (
++ ph.GetPresentation(), presentation)
++ return None
++
++
++ def __CopyTo(self, other):
++ """
++ Returns a copy of this BaseMessage.
++ """
++ assert isinstance(other, self.__class__) or isinstance(self, other.__class__)
++ other.__source_encoding = self.__source_encoding
++ other.__content = self.__content[:]
++ other.__description = self.__description
++ other.__id = self.__id
++ other.__num_instances = self.__num_instances
++ other.__obsolete = self.__obsolete
++ other.__name = self.__name
++ other.__placeholders = self.__placeholders[:]
++ other.__sequence_number = self.__sequence_number
++ other.__sources = self.__sources[:]
++
++ return other
++
++ def HasText(self):
++ """Returns true iff this message has anything other than placeholders."""
++ for item in self.__content:
++ if not isinstance(item, Placeholder):
++ return True
++ return False
++
++# --------------------------------------------------------
++# The Message class represents original (English) messages
++
++class Message(BaseMessage):
++ # See BaseMessage constructor
++ def __init__(self, source_encoding, text=None, id=None,
++ description=None, meaning="", placeholders=None,
++ source=None, sequence_number=0, clone_from=None,
++ time_created=0, name=None, is_hidden = 0):
++
++ if clone_from is not None:
++ BaseMessage.__init__(self, None, clone_from=clone_from)
++ self.__meaning = clone_from.__meaning
++ self.__time_created = clone_from.__time_created
++ self.__is_hidden = clone_from.__is_hidden
++ return
++
++ BaseMessage.__init__(self, source_encoding, text, id, description,
++ placeholders, source, sequence_number,
++ name=name)
++ self.__meaning = meaning
++ self.__time_created = time_created
++ self.SetIsHidden(is_hidden)
++
++ # String representation
++ def __str__(self):
++ s = 'source: %s, id: %s, content: "%s", meaning: "%s", ' \
++ 'description: "%s"' % \
++ (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
++ self.__meaning, self.GetDescription())
++ if self.GetName() is not None:
++ s += ', name: "%s"' % self.GetName()
++ placeholders = self.GetPlaceholders()
++ for i in range(len(placeholders)):
++ s += ", placeholder[%d]: %s" % (i, placeholders[i])
++ return s
++
++ # Strips leading and trailing whitespace, and returns a tuple
++ # containing the leading and trailing space that was removed.
++ def Strip(self):
++ leading = trailing = ''
++ content = self.GetContent()
++ if len(content) > 0:
++ s0 = content[0]
++ if not isinstance(s0, Placeholder):
++ s = s0.lstrip()
++ leading = s0[:-len(s)]
++ content[0] = s
++
++ s0 = content[-1]
++ if not isinstance(s0, Placeholder):
++ s = s0.rstrip()
++ trailing = s0[len(s):]
++ content[-1] = s
++ return leading, trailing
++
++ # Generate an id by hashing message content
++ def GenerateId(self):
++ self.SetId(GenerateMessageId(self.GetPresentableContent(),
++ self.__meaning))
++ return self.GetId()
++
++ def GetMeaning(self):
++ return self.__meaning
++
++ def GetTimeCreated(self):
++ return self.__time_created
++
++ # Equality operator
++ def EqualTo(self, other, strict = 1):
++ # Check id, meaning, content
++ if self.GetId() != other.GetId():
++ return 0
++ if self.__meaning != other.__meaning:
++ return 0
++ if self.GetPresentableContent() != other.GetPresentableContent():
++ return 0
++ # Check descriptions if comparison is strict
++ if (strict and
++ self.GetDescription() is not None and
++ other.GetDescription() is not None and
++ self.GetDescription() != other.GetDescription()):
++ return 0
++ # Check placeholders
++ ph1 = self.GetPlaceholders()
++ ph2 = other.GetPlaceholders()
++ if len(ph1) != len(ph2):
++ return 0
++ for i in range(len(ph1)):
++ if not ph1[i].EqualTo(ph2[i], strict):
++ return 0
++
++ return 1
++
++ def Copy(self):
++ """
++ Returns a copy of this Message.
++ """
++ assert isinstance(self, Message)
++ return Message(None, clone_from=self)
++
++ def SetIsHidden(self, is_hidden):
++ """Sets whether this message should be hidden.
++
++ Args:
++ is_hidden : 0 or 1 - if the message should be hidden, 0 otherwise
++ """
++ if is_hidden not in [0, 1]:
++ raise MessageTranslationError("is_hidden must be 0 or 1, got %s")
++ self.__is_hidden = is_hidden
++
++ def IsHidden(self):
++ """Returns 1 if this message is hidden, and 0 otherwise."""
++ return self.__is_hidden
++
++# ----------------------------------------------------
++# The Translation class represents translated messages
++
++class Translation(BaseMessage):
++ # See BaseMessage constructor
++ def __init__(self, source_encoding, text=None, id=None,
++ description=None, placeholders=None, source=None,
++ sequence_number=0, clone_from=None, ignore_ph_errors=0,
++ name=None):
++ if clone_from is not None:
++ BaseMessage.__init__(self, None, clone_from=clone_from)
++ return
++
++ BaseMessage.__init__(self, source_encoding, text, id, description,
++ placeholders, source, sequence_number,
++ ignore_ph_errors=ignore_ph_errors, name=name)
++
++ # String representation
++ def __str__(self):
++ s = 'source: %s, id: %s, content: "%s", description: "%s"' % \
++ (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
++ self.GetDescription());
++ placeholders = self.GetPlaceholders()
++ for i in range(len(placeholders)):
++ s += ", placeholder[%d]: %s" % (i, placeholders[i])
++ return s
++
++ # Equality operator
++ def EqualTo(self, other, strict=1):
++ # Check id and content
++ if self.GetId() != other.GetId():
++ return 0
++ if self.GetPresentableContent() != other.GetPresentableContent():
++ return 0
++ # Check placeholders
++ ph1 = self.GetPlaceholders()
++ ph2 = other.GetPlaceholders()
++ if len(ph1) != len(ph2):
++ return 0
++ for i in range(len(ph1)):
++ if not ph1[i].EqualTo(ph2[i], strict):
++ return 0
++
++ return 1
++
++ def Copy(self):
++ """
++ Returns a copy of this Translation.
++ """
++ return Translation(None, clone_from=self)
+diff --git a/tools/grit/grit/format/__init__.py b/tools/grit/grit/format/__init__.py
+new file mode 100644
+index 0000000000..55d56b8cfd
+--- /dev/null
++++ b/tools/grit/grit/format/__init__.py
+@@ -0,0 +1,8 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Module grit.format
++'''
++
++pass
+diff --git a/tools/grit/grit/format/android_xml.py b/tools/grit/grit/format/android_xml.py
+new file mode 100644
+index 0000000000..7eb288891f
+--- /dev/null
++++ b/tools/grit/grit/format/android_xml.py
+@@ -0,0 +1,212 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Produces localized strings.xml files for Android.
++
++In cases where an "android" type output file is requested in a grd, the classes
++in android_xml will process the messages and translations to produce a valid
++strings.xml that is properly localized with the specified language.
++
++For example if the following output tag were to be included in a grd file
++ <outputs>
++ ...
++ <output filename="values-es/strings.xml" type="android" lang="es" />
++ ...
++ </outputs>
++
++for a grd file with the following messages:
++
++ <message name="IDS_HELLO" desc="Simple greeting">Hello</message>
++ <message name="IDS_WORLD" desc="The world">world</message>
++
++and there existed an appropriate xtb file containing the Spanish translations,
++then the output would be:
++
++ <?xml version="1.0" encoding="utf-8"?>
++ <resources xmlns:android="http://schemas.android.com/apk/res/android">
++ <string name="hello">"Hola"</string>
++ <string name="world">"mundo"</string>
++ </resources>
++
++which would be written to values-es/strings.xml and usable by the Android
++resource framework.
++
++Advanced usage
++--------------
++
++To process only certain messages in a grd file, tag each desired message by
++adding "android_java" to formatter_data. Then set the environmental variable
++ANDROID_JAVA_TAGGED_ONLY to "true" when building the grd file. For example:
++
++ <message name="IDS_HELLO" formatter_data="android_java">Hello</message>
++
++To generate Android plurals (aka "quantity strings"), use the ICU plural syntax
++in the grd file. This will automatically be transformed into a <purals> element
++in the output xml file. For example:
++
++ <message name="IDS_CATS">
++ {NUM_CATS, plural,
++ =1 {1 cat}
++ other {# cats}}
++ </message>
++
++ will produce
++
++ <plurals name="cats">
++ <item quantity="one">1 Katze</item>
++ <item quantity="other">%d Katzen</item>
++ </plurals>
++"""
++
++from __future__ import print_function
++
++import os
++import re
++import xml.sax.saxutils
++
++from grit import lazy_re
++from grit.node import message
++
++
++# When this environmental variable has value "true", only tagged messages will
++# be outputted.
++_TAGGED_ONLY_ENV_VAR = 'ANDROID_JAVA_TAGGED_ONLY'
++_TAGGED_ONLY_DEFAULT = False
++
++# In tagged-only mode, only messages with this tag will be ouputted.
++_EMIT_TAG = 'android_java'
++
++_NAME_PATTERN = lazy_re.compile(r'IDS_(?P<name>[A-Z0-9_]+)\Z')
++
++# Most strings are output as a <string> element. Note the double quotes
++# around the value to preserve whitespace.
++_STRING_TEMPLATE = u'<string name="%s">"%s"</string>\n'
++
++# Some strings are output as a <plurals> element.
++_PLURALS_TEMPLATE = '<plurals name="%s">\n%s</plurals>\n'
++_PLURALS_ITEM_TEMPLATE = ' <item quantity="%s">%s</item>\n'
++
++# Matches e.g. "{HELLO, plural, HOW ARE YOU DOING}", while capturing
++# "HOW ARE YOU DOING" in <items>.
++_PLURALS_PATTERN = lazy_re.compile(r'\{[A-Z_]+,\s*plural,(?P<items>.*)\}$',
++ flags=re.S)
++
++# Repeatedly matched against the <items> capture in _PLURALS_PATTERN,
++# to match "<quantity>{<value>}".
++_PLURALS_ITEM_PATTERN = lazy_re.compile(r'(?P<quantity>\S+?)\s*'
++ r'\{(?P<value>.*?)\}')
++_PLURALS_QUANTITY_MAP = {
++ '=0': 'zero',
++ 'zero': 'zero',
++ '=1': 'one',
++ 'one': 'one',
++ '=2': 'two',
++ 'two': 'two',
++ 'few': 'few',
++ 'many': 'many',
++ 'other': 'other',
++}
++
++
++def Format(root, lang='en', output_dir='.'):
++ yield ('<?xml version="1.0" encoding="utf-8"?>\n'
++ '<resources '
++ 'xmlns:android="http://schemas.android.com/apk/res/android">\n')
++
++ tagged_only = _TAGGED_ONLY_DEFAULT
++ if _TAGGED_ONLY_ENV_VAR in os.environ:
++ tagged_only = os.environ[_TAGGED_ONLY_ENV_VAR].lower()
++ if tagged_only == 'true':
++ tagged_only = True
++ elif tagged_only == 'false':
++ tagged_only = False
++ else:
++ raise Exception('env variable ANDROID_JAVA_TAGGED_ONLY must have value '
++ 'true or false. Invalid value: %s' % tagged_only)
++
++ for item in root.ActiveDescendants():
++ with item:
++ if ShouldOutputNode(item, tagged_only):
++ yield _FormatMessage(item, lang)
++
++ yield '</resources>\n'
++
++
++def ShouldOutputNode(node, tagged_only):
++ """Returns true if node should be outputted.
++
++ Args:
++ node: a Node from the grd dom
++ tagged_only: true, if only tagged messages should be outputted
++ """
++ return (isinstance(node, message.MessageNode) and
++ (not tagged_only or _EMIT_TAG in node.formatter_data))
++
++
++def _FormatPluralMessage(message):
++ """Compiles ICU plural syntax to the body of an Android <plurals> element.
++
++ 1. In a .grd file, we can write a plural string like this:
++
++ <message name="IDS_THINGS">
++ {NUM_THINGS, plural,
++ =1 {1 thing}
++ other {# things}}
++ </message>
++
++ 2. The Android equivalent looks like this:
++
++ <plurals name="things">
++ <item quantity="one">1 thing</item>
++ <item quantity="other">%d things</item>
++ </plurals>
++
++ This method takes the body of (1) and converts it to the body of (2).
++
++ If the message is *not* a plural string, this function returns `None`.
++ If the message includes quantities without an equivalent format in Android,
++ it raises an exception.
++ """
++ ret = {}
++ plural_match = _PLURALS_PATTERN.match(message)
++ if not plural_match:
++ return None
++ body_in = plural_match.group('items').strip()
++ lines = []
++ quantities_so_far = set()
++ for item_match in _PLURALS_ITEM_PATTERN.finditer(body_in):
++ quantity_in = item_match.group('quantity')
++ quantity_out = _PLURALS_QUANTITY_MAP.get(quantity_in)
++ value_in = item_match.group('value')
++ value_out = '"' + value_in.replace('#', '%d') + '"'
++ if quantity_out:
++ # only one line per quantity out (https://crbug.com/787488)
++ if quantity_out not in quantities_so_far:
++ quantities_so_far.add(quantity_out)
++ lines.append(_PLURALS_ITEM_TEMPLATE % (quantity_out, value_out))
++ else:
++ raise Exception('Unsupported plural quantity for android '
++ 'strings.xml: %s' % quantity_in)
++ return ''.join(lines)
++
++
++def _FormatMessage(item, lang):
++ """Writes out a single string as a <resource/> element."""
++
++ mangled_name = item.GetTextualIds()[0]
++ match = _NAME_PATTERN.match(mangled_name)
++ if not match:
++ raise Exception('Unexpected resource name: %s' % mangled_name)
++ name = match.group('name').lower()
++
++ value = item.ws_at_start + item.Translate(lang) + item.ws_at_end
++ # Replace < > & with &lt; &gt; &amp; to ensure we generate valid XML and
++ # replace ' " with \' \" to conform to Android's string formatting rules.
++ value = xml.sax.saxutils.escape(value, {"'": "\\'", '"': '\\"'})
++
++ plurals = _FormatPluralMessage(value)
++ if plurals:
++ return _PLURALS_TEMPLATE % (name, plurals)
++ else:
++ return _STRING_TEMPLATE % (name, value)
+diff --git a/tools/grit/grit/format/android_xml_unittest.py b/tools/grit/grit/format/android_xml_unittest.py
+new file mode 100644
+index 0000000000..d9f476fddf
+--- /dev/null
++++ b/tools/grit/grit/format/android_xml_unittest.py
+@@ -0,0 +1,149 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Unittest for android_xml.py."""
++
++from __future__ import print_function
++
++import os
++import sys
++import unittest
++
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++from six import StringIO
++
++from grit import util
++from grit.format import android_xml
++from grit.node import message
++from grit.tool import build
++
++
++class AndroidXmlUnittest(unittest.TestCase):
++
++ def testMessages(self):
++ root = util.ParseGrdForUnittest(r"""
++ <messages>
++ <message name="IDS_SIMPLE" desc="A vanilla string">
++ Martha
++ </message>
++ <message name="IDS_ONE_LINE" desc="On one line">sat and wondered</message>
++ <message name="IDS_QUOTES" desc="A string with quotation marks">
++ out loud, "Why don't I build a flying car?"
++ </message>
++ <message name="IDS_MULTILINE" desc="A string split over several lines">
++ She gathered
++wood, charcoal, and
++a sledge hammer.
++ </message>
++ <message name="IDS_WHITESPACE" desc="A string with extra whitespace.">
++ ''' How old fashioned -- she thought. '''
++ </message>
++ <message name="IDS_PLACEHOLDERS" desc="A string with placeholders">
++ I'll buy a <ph name="WAVELENGTH">%d<ex>200</ex></ph> nm laser at <ph name="STORE_NAME">%s<ex>the grocery store</ex></ph>.
++ </message>
++ <message name="IDS_PLURALS" desc="A string using the ICU plural format">
++ {NUM_THINGS, plural,
++ =1 {Maybe I'll get one laser.}
++ other {Maybe I'll get # lasers.}}
++ </message>
++ <message name="IDS_PLURALS_NO_SPACE" desc="A string using the ICU plural format with no space">
++ {NUM_MISSISSIPPIS, plural,
++ =1{OneMississippi}other{ManyMississippis}}
++ </message>
++ </messages>
++ """)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('android', 'en'), buf)
++ output = buf.getvalue()
++ expected = r"""
++<?xml version="1.0" encoding="utf-8"?>
++<resources xmlns:android="http://schemas.android.com/apk/res/android">
++<string name="simple">"Martha"</string>
++<string name="one_line">"sat and wondered"</string>
++<string name="quotes">"out loud, \"Why don\'t I build a flying car?\""</string>
++<string name="multiline">"She gathered
++wood, charcoal, and
++a sledge hammer."</string>
++<string name="whitespace">" How old fashioned -- she thought. "</string>
++<string name="placeholders">"I\'ll buy a %d nm laser at %s."</string>
++<plurals name="plurals">
++ <item quantity="one">"Maybe I\'ll get one laser."</item>
++ <item quantity="other">"Maybe I\'ll get %d lasers."</item>
++</plurals>
++<plurals name="plurals_no_space">
++ <item quantity="one">"OneMississippi"</item>
++ <item quantity="other">"ManyMississippis"</item>
++</plurals>
++</resources>
++"""
++ self.assertEqual(output.strip(), expected.strip())
++
++
++ def testConflictingPlurals(self):
++ root = util.ParseGrdForUnittest(r"""
++ <messages>
++ <message name="IDS_PLURALS" desc="A string using the ICU plural format">
++ {NUM_THINGS, plural,
++ =1 {Maybe I'll get one laser.}
++ one {Maybe I'll get one laser.}
++ other {Maybe I'll get # lasers.}}
++ </message>
++ </messages>
++ """)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('android', 'en'), buf)
++ output = buf.getvalue()
++ expected = r"""
++<?xml version="1.0" encoding="utf-8"?>
++<resources xmlns:android="http://schemas.android.com/apk/res/android">
++<plurals name="plurals">
++ <item quantity="one">"Maybe I\'ll get one laser."</item>
++ <item quantity="other">"Maybe I\'ll get %d lasers."</item>
++</plurals>
++</resources>
++"""
++ self.assertEqual(output.strip(), expected.strip())
++
++
++ def testTaggedOnly(self):
++ root = util.ParseGrdForUnittest(r"""
++ <messages>
++ <message name="IDS_HELLO" desc="" formatter_data="android_java">
++ Hello
++ </message>
++ <message name="IDS_WORLD" desc="">
++ world
++ </message>
++ </messages>
++ """)
++
++ msg_hello, msg_world = root.GetChildrenOfType(message.MessageNode)
++ self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=True))
++ self.assertFalse(android_xml.ShouldOutputNode(msg_world, tagged_only=True))
++ self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=False))
++ self.assertTrue(android_xml.ShouldOutputNode(msg_world, tagged_only=False))
++
++
++class DummyOutput(object):
++
++ def __init__(self, type, language):
++ self.type = type
++ self.language = language
++
++ def GetType(self):
++ return self.type
++
++ def GetLanguage(self):
++ return self.language
++
++ def GetOutputFilename(self):
++ return 'hello.gif'
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/c_format.py b/tools/grit/grit/format/c_format.py
+new file mode 100644
+index 0000000000..16809a9f70
+--- /dev/null
++++ b/tools/grit/grit/format/c_format.py
+@@ -0,0 +1,95 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Formats as a .C file for compilation.
++"""
++
++from __future__ import print_function
++
++import codecs
++import os
++import re
++
++import six
++
++from grit import util
++
++
++def _FormatHeader(root, output_dir):
++ """Returns the required preamble for C files."""
++ # Find the location of the resource header file, so that we can include
++ # it.
++ resource_header = 'resource.h' # fall back to this
++ for output in root.GetOutputFiles():
++ if output.attrs['type'] == 'rc_header':
++ resource_header = os.path.abspath(output.GetOutputFilename())
++ resource_header = util.MakeRelativePath(output_dir, resource_header)
++ return """// This file is automatically generated by GRIT. Do not edit.
++
++#include "%s"
++
++// All strings are UTF-8
++""" % (resource_header)
++# end _FormatHeader() function
++
++
++def Format(root, lang='en', output_dir='.'):
++ """Outputs a C switch statement representing the string table."""
++ from grit.node import message
++ assert isinstance(lang, six.string_types)
++
++ yield _FormatHeader(root, output_dir)
++
++ yield 'const char* GetString(int id) {\n switch (id) {'
++
++ for item in root.ActiveDescendants():
++ with item:
++ if isinstance(item, message.MessageNode):
++ yield _FormatMessage(item, lang)
++
++ yield '\n default:\n return 0;\n }\n}\n'
++
++
++def _HexToOct(match):
++ "Return the octal form of the hex numbers"
++ hex = match.group("hex")
++ result = ""
++ while len(hex):
++ next_num = int(hex[2:4], 16)
++ result += "\\" + '%03o' % next_num
++ hex = hex[4:]
++ return match.group("escaped_backslashes") + result
++
++
++def _FormatMessage(item, lang):
++ """Format a single <message> element."""
++
++ message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
++ # Output message with non-ascii chars escaped as octal numbers C's grammar
++ # allows escaped hexadecimal numbers to be infinite, but octal is always of
++ # the form \OOO. Python 3 doesn't support string-escape, so we have to jump
++ # through some hoops here via codecs.escape_encode.
++ # This basically does:
++ # - message - the starting string
++ # - message.encode(...) - convert to bytes
++ # - codecs.escape_encode(...) - convert non-ASCII bytes to \x## escapes
++ # - (...).decode() - convert bytes back to a string
++ message = codecs.escape_encode(message.encode('utf-8'))[0].decode('utf-8')
++ # an escaped char is (\xHH)+ but only if the initial
++ # backslash is not escaped.
++ not_a_backslash = r"(^|[^\\])" # beginning of line or a non-backslash char
++ escaped_backslashes = not_a_backslash + r"(\\\\)*"
++ hex_digits = r"((\\x)[0-9a-f]{2})+"
++ two_digit_hex_num = re.compile(
++ r"(?P<escaped_backslashes>%s)(?P<hex>%s)"
++ % (escaped_backslashes, hex_digits))
++ message = two_digit_hex_num.sub(_HexToOct, message)
++ # unescape \ (convert \\ back to \)
++ message = message.replace('\\\\', '\\')
++ message = message.replace('"', '\\"')
++ message = util.LINEBREAKS.sub(r'\\n', message)
++
++ name_attr = item.GetTextualIds()[0]
++
++ return '\n case %s:\n return "%s";' % (name_attr, message)
+diff --git a/tools/grit/grit/format/c_format_unittest.py b/tools/grit/grit/format/c_format_unittest.py
+new file mode 100644
+index 0000000000..380120c42f
+--- /dev/null
++++ b/tools/grit/grit/format/c_format_unittest.py
+@@ -0,0 +1,81 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Unittest for c_format.py.
++"""
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit import util
++from grit.tool import build
++
++
++class CFormatUnittest(unittest.TestCase):
++
++ def testMessages(self):
++ root = util.ParseGrdForUnittest(u"""
++ <messages>
++ <message name="IDS_QUESTIONS">Do you want to play questions?</message>
++ <message name="IDS_QUOTES">
++ "What's in a name, <ph name="NAME">%s<ex>Brandon</ex></ph>?"
++ </message>
++ <message name="IDS_LINE_BREAKS">
++ Was that rhetoric?
++No.
++Statement. Two all. Game point.
++</message>
++ <message name="IDS_NON_ASCII">
++ \u00f5\\xc2\\xa4\\\u00a4\\\\xc3\\xb5\u4924
++ </message>
++ </messages>
++ """)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('c_format', 'en'), buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++ self.assertEqual(u"""\
++#include "resource.h"
++const char* GetString(int id) {
++ switch (id) {
++ case IDS_QUESTIONS:
++ return "Do you want to play questions?";
++ case IDS_QUOTES:
++ return "\\"What\\'s in a name, %s?\\"";
++ case IDS_LINE_BREAKS:
++ return "Was that rhetoric?\\nNo.\\nStatement. Two all. Game point.";
++ case IDS_NON_ASCII:
++ return "\\303\\265\\xc2\\xa4\\\\302\\244\\\\xc3\\xb5\\344\\244\\244";
++ default:
++ return 0;
++ }
++}""", output)
++
++
++class DummyOutput(object):
++
++ def __init__(self, type, language):
++ self.type = type
++ self.language = language
++
++ def GetType(self):
++ return self.type
++
++ def GetLanguage(self):
++ return self.language
++
++ def GetOutputFilename(self):
++ return 'hello.gif'
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/chrome_messages_json.py b/tools/grit/grit/format/chrome_messages_json.py
+new file mode 100644
+index 0000000000..88ec1d914b
+--- /dev/null
++++ b/tools/grit/grit/format/chrome_messages_json.py
+@@ -0,0 +1,59 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Formats as a .json file that can be used to localize Google Chrome
++extensions."""
++
++from __future__ import print_function
++
++from json import JSONEncoder
++
++from grit import constants
++from grit.node import message
++
++def Format(root, lang='en', output_dir='.'):
++ """Format the messages as JSON."""
++ yield '{'
++
++ encoder = JSONEncoder(ensure_ascii=False)
++ format = '"%s":{"message":%s%s}'
++ placeholder_format = '"%i":{"content":"$%i"}'
++ first = True
++ for child in root.ActiveDescendants():
++ if isinstance(child, message.MessageNode):
++ id = child.attrs['name']
++ if id.startswith('IDR_') or id.startswith('IDS_'):
++ id = id[4:]
++
++ translation_missing = child.GetCliques()[0].clique.get(lang) is None;
++ if (child.ShouldFallbackToEnglish() and translation_missing and
++ lang != constants.FAKE_BIDI):
++ # Skip the string if it's not translated. Chrome will fallback
++ # to English automatically.
++ continue
++
++ loc_message = encoder.encode(child.ws_at_start + child.Translate(lang) +
++ child.ws_at_end)
++
++ # Replace $n place-holders with $n$ and add an appropriate "placeholders"
++ # entry. Note that chrome.i18n.getMessage only supports 9 placeholders:
++ # https://developer.chrome.com/extensions/i18n#method-getMessage
++ placeholders = ''
++ for i in range(1, 10):
++ if loc_message.find('$%d' % i) == -1:
++ break
++ loc_message = loc_message.replace('$%d' % i, '$%d$' % i)
++ if placeholders:
++ placeholders += ','
++ placeholders += placeholder_format % (i, i)
++
++ if not first:
++ yield ','
++ first = False
++
++ if placeholders:
++ placeholders = ',"placeholders":{%s}' % placeholders
++ yield format % (id, loc_message, placeholders)
++
++ yield '}'
+diff --git a/tools/grit/grit/format/chrome_messages_json_unittest.py b/tools/grit/grit/format/chrome_messages_json_unittest.py
+new file mode 100644
+index 0000000000..a54e6bdc1c
+--- /dev/null
++++ b/tools/grit/grit/format/chrome_messages_json_unittest.py
+@@ -0,0 +1,190 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Unittest for chrome_messages_json.py.
++"""
++
++from __future__ import print_function
++
++import json
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit import grd_reader
++from grit import util
++from grit.tool import build
++
++class ChromeMessagesJsonFormatUnittest(unittest.TestCase):
++
++ # The default unittest diff limit is too low for our unittests.
++ # Allow the framework to show the full diff output all the time.
++ maxDiff = None
++
++ def testMessages(self):
++ root = util.ParseGrdForUnittest(u"""
++ <messages>
++ <message name="IDS_SIMPLE_MESSAGE">
++ Simple message.
++ </message>
++ <message name="IDS_QUOTES">
++ element\u2019s \u201c<ph name="NAME">%s<ex>name</ex></ph>\u201d attribute
++ </message>
++ <message name="IDS_PLACEHOLDERS">
++ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
++ </message>
++ <message name="IDS_PLACEHOLDERS_SUBSTITUTED_BY_GETMESSAGE">
++ <ph name="BEGIN">$1<ex>a</ex></ph>test<ph name="END">$2<ex>b</ex></ph>
++ </message>
++ <message name="IDS_STARTS_WITH_SPACE">
++ ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
++ </message>
++ <message name="IDS_ENDS_WITH_SPACE">
++ (<ph name="COUNT">%d<ex>2</ex></ph>) '''
++ </message>
++ <message name="IDS_SPACE_AT_BOTH_ENDS">
++ ''' (<ph name="COUNT">%d<ex>2</ex></ph>) '''
++ </message>
++ <message name="IDS_DOUBLE_QUOTES">
++ A "double quoted" message.
++ </message>
++ <message name="IDS_BACKSLASH">
++ \\
++ </message>
++ </messages>
++ """)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'en'),
++ buf)
++ output = buf.getvalue()
++ test = u"""
++{
++ "SIMPLE_MESSAGE": {
++ "message": "Simple message."
++ },
++ "QUOTES": {
++ "message": "element\u2019s \u201c%s\u201d attribute"
++ },
++ "PLACEHOLDERS": {
++ "message": "%1$d error, %2$d warning"
++ },
++ "PLACEHOLDERS_SUBSTITUTED_BY_GETMESSAGE": {
++ "message": "$1$test$2$",
++ "placeholders": {
++ "1": {
++ "content": "$1"
++ },
++ "2": {
++ "content": "$2"
++ }
++ }
++ },
++ "STARTS_WITH_SPACE": {
++ "message": " (%d)"
++ },
++ "ENDS_WITH_SPACE": {
++ "message": "(%d) "
++ },
++ "SPACE_AT_BOTH_ENDS": {
++ "message": " (%d) "
++ },
++ "DOUBLE_QUOTES": {
++ "message": "A \\"double quoted\\" message."
++ },
++ "BACKSLASH": {
++ "message": "\\\\"
++ }
++}
++"""
++ self.assertEqual(json.loads(test), json.loads(output))
++
++ def testTranslations(self):
++ root = util.ParseGrdForUnittest("""
++ <messages>
++ <message name="ID_HELLO">Hello!</message>
++ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
++ Joi</ex></ph></message>
++ </messages>
++ """)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'fr'),
++ buf)
++ output = buf.getvalue()
++ test = u"""
++{
++ "ID_HELLO": {
++ "message": "H\u00e9P\u00e9ll\u00f4P\u00f4!"
++ },
++ "ID_HELLO_USER": {
++ "message": "H\u00e9P\u00e9ll\u00f4P\u00f4 %s"
++ }
++}
++"""
++ self.assertEqual(json.loads(test), json.loads(output))
++
++ def testSkipMissingTranslations(self):
++ grd = """<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" current_release="3" source_lang_id="en"
++ base_dir="%s">
++ <outputs>
++ </outputs>
++ <release seq="3" allow_pseudo="False">
++ <messages fallback_to_english="true">
++ <message name="ID_HELLO_NO_TRANSLATION">Hello not translated</message>
++ </messages>
++ </release>
++</grit>"""
++ root = grd_reader.Parse(StringIO(grd), dir=".")
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'fr'),
++ buf)
++ output = buf.getvalue()
++ test = u'{}'
++ self.assertEqual(test, output)
++
++ def testVerifyMinification(self):
++ root = util.ParseGrdForUnittest(u"""
++ <messages>
++ <message name="IDS">
++ <ph name="BEGIN">$1<ex>a</ex></ph>test<ph name="END">$2<ex>b</ex></ph>
++ </message>
++ </messages>
++ """)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'en'),
++ buf)
++ output = buf.getvalue()
++ test = (u'{"IDS":{"message":"$1$test$2$","placeholders":'
++ u'{"1":{"content":"$1"},"2":{"content":"$2"}}}}')
++ self.assertEqual(test, output)
++
++
++class DummyOutput(object):
++
++ def __init__(self, type, language):
++ self.type = type
++ self.language = language
++
++ def GetType(self):
++ return self.type
++
++ def GetLanguage(self):
++ return self.language
++
++ def GetOutputFilename(self):
++ return 'hello.gif'
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/data_pack.py b/tools/grit/grit/format/data_pack.py
+new file mode 100644
+index 0000000000..f7128a4725
+--- /dev/null
++++ b/tools/grit/grit/format/data_pack.py
+@@ -0,0 +1,321 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Support for formatting a data pack file used for platform agnostic resource
++files.
++"""
++
++from __future__ import print_function
++
++import collections
++import os
++import struct
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import six
++
++from grit import util
++from grit.node import include
++from grit.node import message
++from grit.node import structure
++
++
++PACK_FILE_VERSION = 5
++BINARY, UTF8, UTF16 = range(3)
++
++
++GrdInfoItem = collections.namedtuple('GrdInfoItem',
++ ['textual_id', 'id', 'path'])
++
++
++class WrongFileVersion(Exception):
++ pass
++
++
++class CorruptDataPack(Exception):
++ pass
++
++
++class DataPackSizes(object):
++ def __init__(self, header, id_table, alias_table, data):
++ self.header = header
++ self.id_table = id_table
++ self.alias_table = alias_table
++ self.data = data
++
++ @property
++ def total(self):
++ return sum(v for v in self.__dict__.values())
++
++ def __iter__(self):
++ yield ('header', self.header)
++ yield ('id_table', self.id_table)
++ yield ('alias_table', self.alias_table)
++ yield ('data', self.data)
++
++ def __eq__(self, other):
++ return self.__dict__ == other.__dict__
++
++ def __repr__(self):
++ return self.__class__.__name__ + repr(self.__dict__)
++
++
++class DataPackContents(object):
++ def __init__(self, resources, encoding, version, aliases, sizes):
++ # Map of resource_id -> str.
++ self.resources = resources
++ # Encoding (int).
++ self.encoding = encoding
++ # Version (int).
++ self.version = version
++ # Map of resource_id->canonical_resource_id
++ self.aliases = aliases
++ # DataPackSizes instance.
++ self.sizes = sizes
++
++
++def Format(root, lang='en', output_dir='.'):
++ """Writes out the data pack file format (platform agnostic resource file)."""
++ id_map = root.GetIdMap()
++ data = {}
++ root.info = []
++ for node in root.ActiveDescendants():
++ with node:
++ if isinstance(node, (include.IncludeNode, message.MessageNode,
++ structure.StructureNode)):
++ value = node.GetDataPackValue(lang, util.BINARY)
++ if value is not None:
++ resource_id = id_map[node.GetTextualIds()[0]]
++ data[resource_id] = value
++ root.info.append('{},{},{}'.format(
++ node.attrs.get('name'), resource_id, node.source))
++ return WriteDataPackToString(data, UTF8)
++
++
++def ReadDataPack(input_file):
++ return ReadDataPackFromString(util.ReadFile(input_file, util.BINARY))
++
++
++def ReadDataPackFromString(data):
++ """Reads a data pack file and returns a dictionary."""
++ # Read the header.
++ version = struct.unpack('<I', data[:4])[0]
++ if version == 4:
++ resource_count, encoding = struct.unpack('<IB', data[4:9])
++ alias_count = 0
++ header_size = 9
++ elif version == 5:
++ encoding, resource_count, alias_count = struct.unpack('<BxxxHH', data[4:12])
++ header_size = 12
++ else:
++ raise WrongFileVersion('Found version: ' + str(version))
++
++ resources = {}
++ kIndexEntrySize = 2 + 4 # Each entry is a uint16 and a uint32.
++ def entry_at_index(idx):
++ offset = header_size + idx * kIndexEntrySize
++ return struct.unpack('<HI', data[offset:offset + kIndexEntrySize])
++
++ prev_resource_id, prev_offset = entry_at_index(0)
++ for i in range(1, resource_count + 1):
++ resource_id, offset = entry_at_index(i)
++ resources[prev_resource_id] = data[prev_offset:offset]
++ prev_resource_id, prev_offset = resource_id, offset
++
++ id_table_size = (resource_count + 1) * kIndexEntrySize
++ # Read the alias table.
++ kAliasEntrySize = 2 + 2 # uint16, uint16
++ def alias_at_index(idx):
++ offset = header_size + id_table_size + idx * kAliasEntrySize
++ return struct.unpack('<HH', data[offset:offset + kAliasEntrySize])
++
++ aliases = {}
++ for i in range(alias_count):
++ resource_id, index = alias_at_index(i)
++ aliased_id = entry_at_index(index)[0]
++ aliases[resource_id] = aliased_id
++ resources[resource_id] = resources[aliased_id]
++
++ alias_table_size = kAliasEntrySize * alias_count
++ sizes = DataPackSizes(
++ header_size, id_table_size, alias_table_size,
++ len(data) - header_size - id_table_size - alias_table_size)
++ assert sizes.total == len(data), 'original={} computed={}'.format(
++ len(data), sizes.total)
++ return DataPackContents(resources, encoding, version, aliases, sizes)
++
++
++def WriteDataPackToString(resources, encoding):
++ """Returns bytes with a map of id=>data in the data pack format."""
++ ret = []
++
++ # Compute alias map.
++ resource_ids = sorted(resources)
++ # Use reversed() so that for duplicates lower IDs clobber higher ones.
++ id_by_data = {resources[k]: k for k in reversed(resource_ids)}
++ # Map of resource_id -> resource_id, where value < key.
++ alias_map = {k: id_by_data[v] for k, v in resources.items()
++ if id_by_data[v] != k}
++
++ # Write file header.
++ resource_count = len(resources) - len(alias_map)
++ # Padding bytes added for alignment.
++ ret.append(struct.pack('<IBxxxHH', PACK_FILE_VERSION, encoding,
++ resource_count, len(alias_map)))
++ HEADER_LENGTH = 4 + 4 + 2 + 2
++
++ # Each main table entry is: uint16 + uint32 (and an extra entry at the end).
++ # Each alias table entry is: uint16 + uint16.
++ data_offset = HEADER_LENGTH + (resource_count + 1) * 6 + len(alias_map) * 4
++
++ # Write main table.
++ index_by_id = {}
++ deduped_data = []
++ index = 0
++ for resource_id in resource_ids:
++ if resource_id in alias_map:
++ continue
++ data = resources[resource_id]
++ if isinstance(data, six.text_type):
++ data = data.encode('utf-8')
++ index_by_id[resource_id] = index
++ ret.append(struct.pack('<HI', resource_id, data_offset))
++ data_offset += len(data)
++ deduped_data.append(data)
++ index += 1
++
++ assert index == resource_count
++ # Add an extra entry at the end.
++ ret.append(struct.pack('<HI', 0, data_offset))
++
++ # Write alias table.
++ for resource_id in sorted(alias_map):
++ index = index_by_id[alias_map[resource_id]]
++ ret.append(struct.pack('<HH', resource_id, index))
++
++ # Write data.
++ ret.extend(deduped_data)
++ return b''.join(ret)
++
++
++def WriteDataPack(resources, output_file, encoding):
++ """Writes a map of id=>data into output_file as a data pack."""
++ content = WriteDataPackToString(resources, encoding)
++ with open(output_file, 'wb') as file:
++ file.write(content)
++
++
++def ReadGrdInfo(grd_file):
++ info_dict = {}
++ with open(grd_file + '.info', 'rt') as f:
++ for line in f:
++ item = GrdInfoItem._make(line.strip().split(','))
++ info_dict[int(item.id)] = item
++ return info_dict
++
++
++def RePack(output_file, input_files, whitelist_file=None,
++ suppress_removed_key_output=False,
++ output_info_filepath=None):
++ """Write a new data pack file by combining input pack files.
++
++ Args:
++ output_file: path to the new data pack file.
++ input_files: a list of paths to the data pack files to combine.
++ whitelist_file: path to the file that contains the list of resource IDs
++ that should be kept in the output file or None to include
++ all resources.
++ suppress_removed_key_output: allows the caller to suppress the output from
++ RePackFromDataPackStrings.
++ output_info_file: If not None, specify the output .info filepath.
++
++ Raises:
++ KeyError: if there are duplicate keys or resource encoding is
++ inconsistent.
++ """
++ input_data_packs = [ReadDataPack(filename) for filename in input_files]
++ input_info_files = [filename + '.info' for filename in input_files]
++ whitelist = None
++ if whitelist_file:
++ lines = util.ReadFile(whitelist_file, 'utf-8').strip().splitlines()
++ if not lines:
++ raise Exception('Whitelist file should not be empty')
++ whitelist = set(int(x) for x in lines)
++ inputs = [(p.resources, p.encoding) for p in input_data_packs]
++ resources, encoding = RePackFromDataPackStrings(
++ inputs, whitelist, suppress_removed_key_output)
++ WriteDataPack(resources, output_file, encoding)
++ if output_info_filepath is None:
++ output_info_filepath = output_file + '.info'
++ with open(output_info_filepath, 'w') as output_info_file:
++ for filename in input_info_files:
++ with open(filename, 'r') as info_file:
++ output_info_file.writelines(info_file.readlines())
++
++
++def RePackFromDataPackStrings(inputs, whitelist,
++ suppress_removed_key_output=False):
++ """Combines all inputs into one.
++
++ Args:
++ inputs: a list of (resources_by_id, encoding) tuples to be combined.
++ whitelist: a list of resource IDs that should be kept in the output string
++ or None to include all resources.
++ suppress_removed_key_output: Do not print removed keys.
++
++ Returns:
++ Returns (resources_by_id, encoding).
++
++ Raises:
++ KeyError: if there are duplicate keys or resource encoding is
++ inconsistent.
++ """
++ resources = {}
++ encoding = None
++ for input_resources, input_encoding in inputs:
++ # Make sure we have no dups.
++ duplicate_keys = set(input_resources.keys()) & set(resources.keys())
++ if duplicate_keys:
++ raise KeyError('Duplicate keys: ' + str(list(duplicate_keys)))
++
++ # Make sure encoding is consistent.
++ if encoding in (None, BINARY):
++ encoding = input_encoding
++ elif input_encoding not in (BINARY, encoding):
++ raise KeyError('Inconsistent encodings: ' + str(encoding) +
++ ' vs ' + str(input_encoding))
++
++ if whitelist:
++ whitelisted_resources = dict([(key, input_resources[key])
++ for key in input_resources.keys()
++ if key in whitelist])
++ resources.update(whitelisted_resources)
++ removed_keys = [key for key in input_resources.keys()
++ if key not in whitelist]
++ if not suppress_removed_key_output:
++ for key in removed_keys:
++ print('RePackFromDataPackStrings Removed Key:', key)
++ else:
++ resources.update(input_resources)
++
++ # Encoding is 0 for BINARY, 1 for UTF8 and 2 for UTF16
++ if encoding is None:
++ encoding = BINARY
++ return resources, encoding
++
++
++def main():
++ # Write a simple file.
++ data = {1: '', 4: 'this is id 4', 6: 'this is id 6', 10: ''}
++ WriteDataPack(data, 'datapack1.pak', UTF8)
++ data2 = {1000: 'test', 5: 'five'}
++ WriteDataPack(data2, 'datapack2.pak', UTF8)
++ print('wrote datapack1 and datapack2 to current directory.')
++
++
++if __name__ == '__main__':
++ main()
+diff --git a/tools/grit/grit/format/data_pack_unittest.py b/tools/grit/grit/format/data_pack_unittest.py
+new file mode 100644
+index 0000000000..fcd7035473
+--- /dev/null
++++ b/tools/grit/grit/format/data_pack_unittest.py
+@@ -0,0 +1,102 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.format.data_pack'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit.format import data_pack
++
++
++class FormatDataPackUnittest(unittest.TestCase):
++ def testReadDataPackV4(self):
++ expected_data = (
++ b'\x04\x00\x00\x00' # header(version
++ b'\x04\x00\x00\x00' # no. entries,
++ b'\x01' # encoding)
++ b'\x01\x00\x27\x00\x00\x00' # index entry 1
++ b'\x04\x00\x27\x00\x00\x00' # index entry 4
++ b'\x06\x00\x33\x00\x00\x00' # index entry 6
++ b'\x0a\x00\x3f\x00\x00\x00' # index entry 10
++ b'\x00\x00\x3f\x00\x00\x00' # extra entry for the size of last
++ b'this is id 4this is id 6') # data
++ expected_data_pack = data_pack.DataPackContents(
++ {
++ 1: b'',
++ 4: b'this is id 4',
++ 6: b'this is id 6',
++ 10: b'',
++ }, data_pack.UTF8, 4, {}, data_pack.DataPackSizes(9, 30, 0, 24))
++ loaded = data_pack.ReadDataPackFromString(expected_data)
++ self.assertDictEqual(expected_data_pack.__dict__, loaded.__dict__)
++
++ def testReadWriteDataPackV5(self):
++ expected_data = (
++ b'\x05\x00\x00\x00' # version
++ b'\x01\x00\x00\x00' # encoding & padding
++ b'\x03\x00' # resource_count
++ b'\x01\x00' # alias_count
++ b'\x01\x00\x28\x00\x00\x00' # index entry 1
++ b'\x04\x00\x28\x00\x00\x00' # index entry 4
++ b'\x06\x00\x34\x00\x00\x00' # index entry 6
++ b'\x00\x00\x40\x00\x00\x00' # extra entry for the size of last
++ b'\x0a\x00\x01\x00' # alias table
++ b'this is id 4this is id 6') # data
++ input_resources = {
++ 1: b'',
++ 4: b'this is id 4',
++ 6: b'this is id 6',
++ 10: b'this is id 4',
++ }
++ data = data_pack.WriteDataPackToString(input_resources, data_pack.UTF8)
++ self.assertEquals(data, expected_data)
++
++ expected_data_pack = data_pack.DataPackContents({
++ 1: b'',
++ 4: input_resources[4],
++ 6: input_resources[6],
++ 10: input_resources[4],
++ }, data_pack.UTF8, 5, {10: 4}, data_pack.DataPackSizes(12, 24, 4, 24))
++ loaded = data_pack.ReadDataPackFromString(expected_data)
++ self.assertDictEqual(expected_data_pack.__dict__, loaded.__dict__)
++
++ def testRePackUnittest(self):
++ expected_with_whitelist = {
++ 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let',
++ 30: 'you down', 40: 'Never', 50: 'gonna run around and',
++ 60: 'desert you'}
++ expected_without_whitelist = {
++ 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let', 65: 'Close',
++ 30: 'you down', 40: 'Never', 50: 'gonna run around and', 4: 'click',
++ 60: 'desert you', 6: 'chirr', 32: 'oops, try again', 70: 'Awww, snap!'}
++ inputs = [{1: 'Never gonna', 4: 'click', 6: 'chirr', 10: 'give you up'},
++ {20: 'Never gonna let', 30: 'you down', 32: 'oops, try again'},
++ {40: 'Never', 50: 'gonna run around and', 60: 'desert you'},
++ {65: 'Close', 70: 'Awww, snap!'}]
++ whitelist = [1, 10, 20, 30, 40, 50, 60]
++ inputs = [(i, data_pack.UTF8) for i in inputs]
++
++ # RePack using whitelist
++ output, _ = data_pack.RePackFromDataPackStrings(
++ inputs, whitelist, suppress_removed_key_output=True)
++ self.assertDictEqual(expected_with_whitelist, output,
++ 'Incorrect resource output')
++
++ # RePack a None whitelist
++ output, _ = data_pack.RePackFromDataPackStrings(
++ inputs, None, suppress_removed_key_output=True)
++ self.assertDictEqual(expected_without_whitelist, output,
++ 'Incorrect resource output')
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/gen_predetermined_ids.py b/tools/grit/grit/format/gen_predetermined_ids.py
+new file mode 100644
+index 0000000000..9b2aa7b1a5
+--- /dev/null
++++ b/tools/grit/grit/format/gen_predetermined_ids.py
+@@ -0,0 +1,144 @@
++#!/usr/bin/env python
++# Copyright 2017 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""
++A tool to generate a predetermined resource ids file that can be used as an
++input to grit via the -p option. This is meant to be run manually every once in
++a while and its output checked in. See tools/gritsettings/README.md for details.
++"""
++
++from __future__ import print_function
++
++import os
++import re
++import sys
++
++# Regular expression for parsing the #define macro format. Matches both the
++# version of the macro with whitelist support and the one without. For example,
++# Without generate whitelist flag:
++# #define IDS_FOO_MESSAGE 1234
++# With generate whitelist flag:
++# #define IDS_FOO_MESSAGE (::ui::WhitelistedResource<1234>(), 1234)
++RESOURCE_EXTRACT_REGEX = re.compile(r'^#define (\S*).* (\d+)\)?$', re.MULTILINE)
++
++ORDERED_RESOURCE_IDS_REGEX = re.compile(r'^Resource=(\d*)$', re.MULTILINE)
++
++
++def _GetResourceNameIdPairsIter(string_to_scan):
++ """Gets an iterator of the resource name and id pairs of the given string.
++
++ Scans the input string for lines of the form "#define NAME ID" and returns
++ an iterator over all matching (NAME, ID) pairs.
++
++ Args:
++ string_to_scan: The input string to scan.
++
++ Yields:
++ A tuple of name and id.
++ """
++ for match in RESOURCE_EXTRACT_REGEX.finditer(string_to_scan):
++ yield match.group(1, 2)
++
++
++def _ReadOrderedResourceIds(path):
++ """Reads ordered resource ids from the given file.
++
++ The resources are expected to be of the format produced by running Chrome
++ with --print-resource-ids command line.
++
++ Args:
++ path: File path to read resource ids from.
++
++ Returns:
++ An array of ordered resource ids.
++ """
++ ordered_resource_ids = []
++ with open(path, "r") as f:
++ for match in ORDERED_RESOURCE_IDS_REGEX.finditer(f.read()):
++ ordered_resource_ids.append(int(match.group(1)))
++ return ordered_resource_ids
++
++
++def GenerateResourceMapping(original_resources, ordered_resource_ids):
++ """Generates a resource mapping from the ordered ids and the original mapping.
++
++ The returned dict will assign new ids to ordered_resource_ids numerically
++ increasing from 101.
++
++ Args:
++ original_resources: A dict of original resource ids to resource names.
++ ordered_resource_ids: An array of ordered resource ids.
++
++ Returns:
++ A dict of resource ids to resource names.
++ """
++ output_resource_map = {}
++ # 101 is used as the starting value since other parts of GRIT require it to be
++ # the minimum (e.g. rc_header.py) based on Windows resource numbering.
++ next_id = 101
++ for original_id in ordered_resource_ids:
++ resource_name = original_resources[original_id]
++ output_resource_map[next_id] = resource_name
++ next_id += 1
++ return output_resource_map
++
++
++def ReadResourceIdsFromFile(file, original_resources):
++ """Reads resource ids from a GRIT-produced header file.
++
++ Args:
++ file: File to a GRIT-produced header file to read from.
++ original_resources: Dict of resource ids to resource names to add to.
++ """
++ for resource_name, resource_id in _GetResourceNameIdPairsIter(file.read()):
++ original_resources[int(resource_id)] = resource_name
++
++
++def _ReadOriginalResourceIds(out_dir):
++ """Reads resource ids from GRIT header files in the specified directory.
++
++ Args:
++ out_dir: A Chrome build output directory (e.g. out/gn) to scan.
++
++ Returns:
++ A dict of resource ids to resource names.
++ """
++ original_resources = {}
++ for root, dirnames, filenames in os.walk(out_dir + '/gen'):
++ for filename in filenames:
++ if filename.endswith(('_resources.h', '_settings.h', '_strings.h')):
++ with open(os.path.join(root, filename), "r") as f:
++ ReadResourceIdsFromFile(f, original_resources)
++ return original_resources
++
++
++def _GeneratePredeterminedIdsFile(ordered_resources_file, out_dir):
++ """Generates a predetermined ids file.
++
++ Args:
++ ordered_resources_file: File path to read ordered resource ids from.
++ out_dir: A Chrome build output directory (e.g. out/gn) to scan.
++
++ Returns:
++ A dict of resource ids to resource names.
++ """
++ original_resources = _ReadOriginalResourceIds(out_dir)
++ ordered_resource_ids = _ReadOrderedResourceIds(ordered_resources_file)
++ output_resource_map = GenerateResourceMapping(original_resources,
++ ordered_resource_ids)
++ for res_id in sorted(output_resource_map.keys()):
++ print(output_resource_map[res_id], res_id)
++
++
++def main(argv):
++ if len(argv) != 2:
++ print("usage: gen_predetermined_ids.py <ordered_resources_file> <out_dir>")
++ sys.exit(1)
++ ordered_resources_file, out_dir = argv[0], argv[1]
++ _GeneratePredeterminedIdsFile(ordered_resources_file, out_dir)
++
++
++if '__main__' == __name__:
++ main(sys.argv[1:])
+diff --git a/tools/grit/grit/format/gen_predetermined_ids_unittest.py b/tools/grit/grit/format/gen_predetermined_ids_unittest.py
+new file mode 100644
+index 0000000000..bd0331adb4
+--- /dev/null
++++ b/tools/grit/grit/format/gen_predetermined_ids_unittest.py
+@@ -0,0 +1,46 @@
++#!/usr/bin/env python
++# Copyright 2017 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for the gen_predetermined_ids module.'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit.format import gen_predetermined_ids
++
++class GenPredeterminedIdsUnittest(unittest.TestCase):
++ def testGenerateResourceMapping(self):
++ original_resources = {200: 'A', 201: 'B', 300: 'C', 350: 'D', 370: 'E'}
++ ordered_resource_ids = [300, 201, 370]
++ mapping = gen_predetermined_ids.GenerateResourceMapping(
++ original_resources, ordered_resource_ids)
++ self.assertEqual({101: 'C', 102: 'B', 103: 'E'}, mapping)
++
++ def testReadResourceIdsFromFile(self):
++ f = StringIO('''
++// This file is automatically generated by GRIT. Do not edit.
++
++#pragma once
++
++#define IDS_BOOKMARKS_NO_ITEMS 12500
++#define IDS_BOOKMARK_BAR_IMPORT_LINK (::ui::WhitelistedResource<12501>(), 12501)
++#define IDS_BOOKMARK_X (::ui::WhitelistedResource<12502>(), 12502)
++''')
++ resources = {}
++ gen_predetermined_ids.ReadResourceIdsFromFile(f, resources)
++ self.assertEqual({12500: 'IDS_BOOKMARKS_OPEN_ALL',
++ 12501: 'IDS_BOOKMARKS_OPEN_ALL_INCOGNITO',
++ 12502: 'IDS_BOOKMARK_X'}, resources)
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/gzip_string.py b/tools/grit/grit/format/gzip_string.py
+new file mode 100644
+index 0000000000..3cd17185c9
+--- /dev/null
++++ b/tools/grit/grit/format/gzip_string.py
+@@ -0,0 +1,46 @@
++# Copyright (c) 2016 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++"""Provides gzip utilities for strings.
++"""
++
++from __future__ import print_function
++
++import gzip
++import io
++import subprocess
++
++
++def GzipStringRsyncable(data):
++ # Make call to host system's gzip to get access to --rsyncable option. This
++ # option makes updates much smaller - if one line is changed in the resource,
++ # it won't have to push the entire compressed resource with the update.
++ # Instead, --rsyncable breaks the file into small chunks, so that one doesn't
++ # affect the other in compression, and then only that chunk will have to be
++ # updated.
++ gzip_proc = subprocess.Popen(['gzip', '--stdout', '--rsyncable',
++ '--best', '--no-name'],
++ stdin=subprocess.PIPE,
++ stdout=subprocess.PIPE,
++ stderr=subprocess.PIPE)
++ data, stderr = gzip_proc.communicate(data)
++ if gzip_proc.returncode != 0:
++ raise subprocess.CalledProcessError(gzip_proc.returncode, 'gzip',
++ stderr)
++ return data
++
++
++def GzipString(data):
++ # Gzipping using Python's built in gzip: Windows doesn't ship with gzip, and
++ # OSX's gzip does not have an --rsyncable option built in. Although this is
++ # not preferable to --rsyncable, it is an option for the systems that do
++ # not have --rsyncable. If used over GzipStringRsyncable, the primary
++ # difference of this function's compression will be larger updates every time
++ # a compressed resource is changed.
++ gzip_output = io.BytesIO()
++ with gzip.GzipFile(mode='wb', compresslevel=9, fileobj=gzip_output,
++ mtime=0) as gzip_file:
++ gzip_file.write(data)
++ data = gzip_output.getvalue()
++ gzip_output.close()
++ return data
+diff --git a/tools/grit/grit/format/gzip_string_unittest.py b/tools/grit/grit/format/gzip_string_unittest.py
+new file mode 100644
+index 0000000000..c0cfbe1837
+--- /dev/null
++++ b/tools/grit/grit/format/gzip_string_unittest.py
+@@ -0,0 +1,65 @@
++#!/usr/bin/env python
++# Copyright (c) 2016 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.format.gzip_string'''
++
++from __future__ import print_function
++
++import gzip
++import io
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit.format import gzip_string
++
++
++class FormatGzipStringUnittest(unittest.TestCase):
++
++ def testGzipStringRsyncable(self):
++ # Can only test the rsyncable version on platforms which support rsyncable,
++ # which at the moment is Linux.
++ if sys.platform == 'linux2':
++ header_begin = (b'\x1f\x8b') # gzip first two bytes
++ input = (b'TEST STRING STARTING NOW'
++ b'continuing'
++ b'<even more>'
++ b'<finished NOW>')
++
++ compressed = gzip_string.GzipStringRsyncable(input)
++ self.failUnless(header_begin == compressed[:2])
++
++ compressed_file = io.BytesIO()
++ compressed_file.write(compressed)
++ compressed_file.seek(0)
++
++ with gzip.GzipFile(mode='rb', fileobj=compressed_file) as f:
++ output = f.read()
++ self.failUnless(output == input)
++
++ def testGzipString(self):
++ header_begin = b'\x1f\x8b' # gzip first two bytes
++ input = (b'TEST STRING STARTING NOW'
++ b'continuing'
++ b'<even more>'
++ b'<finished NOW>')
++
++ compressed = gzip_string.GzipString(input)
++ self.failUnless(header_begin == compressed[:2])
++
++ compressed_file = io.BytesIO()
++ compressed_file.write(compressed)
++ compressed_file.seek(0)
++
++ with gzip.GzipFile(mode='rb', fileobj=compressed_file) as f:
++ output = f.read()
++ self.failUnless(output == input)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/html_inline.py b/tools/grit/grit/format/html_inline.py
+new file mode 100644
+index 0000000000..da55216ea4
+--- /dev/null
++++ b/tools/grit/grit/format/html_inline.py
+@@ -0,0 +1,602 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Flattens a HTML file by inlining its external resources.
++
++This is a small script that takes a HTML file, looks for src attributes
++and inlines the specified file, producing one HTML file with no external
++dependencies. It recursively inlines the included files.
++"""
++
++from __future__ import print_function
++
++import os
++import re
++import sys
++import base64
++import mimetypes
++
++from grit import lazy_re
++from grit import util
++from grit.format import minifier
++
++# There is a python bug that makes mimetypes crash if the Windows
++# registry contains non-Latin keys ( http://bugs.python.org/issue9291
++# ). Initing manually and blocking external mime-type databases will
++# prevent that bug and if we add svg manually, it will still give us
++# the data we need.
++mimetypes.init([])
++mimetypes.add_type('image/svg+xml', '.svg')
++
++# webm video type is not always available if mimetype package is outdated.
++mimetypes.add_type('video/webm', '.webm')
++
++DIST_DEFAULT = 'chromium'
++DIST_ENV_VAR = 'CHROMIUM_BUILD'
++DIST_SUBSTR = '%DISTRIBUTION%'
++
++# Matches beginning of an "if" block.
++_BEGIN_IF_BLOCK = lazy_re.compile(
++ r'<if [^>]*?expr=("(?P<expr1>[^">]*)"|\'(?P<expr2>[^\'>]*)\')[^>]*?>')
++
++# Matches ending of an "if" block.
++_END_IF_BLOCK = lazy_re.compile(r'</if>')
++
++# Used by DoInline to replace various links with inline content.
++_STYLESHEET_RE = lazy_re.compile(
++ r'<link rel="stylesheet"[^>]+?href="(?P<filename>[^"]*)".*?>(\s*</link>)?',
++ re.DOTALL)
++_INCLUDE_RE = lazy_re.compile(
++ r'(?P<comment>\/\/ )?<include[^>]+?'
++ r'src=("(?P<file1>[^">]*)"|\'(?P<file2>[^\'>]*)\').*?>(\s*</include>)?',
++ re.DOTALL)
++_SRC_RE = lazy_re.compile(
++ r'<(?!script)(?:[^>]+?\s)src="(?!\[\[|{{)(?P<filename>[^"\']*)"',
++ re.MULTILINE)
++# This re matches '<img srcset="..."' or '<source srcset="..."'
++_SRCSET_RE = lazy_re.compile(
++ r'<(img|source)\b(?:[^>]*?\s)srcset="(?!\[\[|{{|\$i18n{)'
++ r'(?P<srcset>[^"\']*)"',
++ re.MULTILINE)
++# This re is for splitting srcset value string into "image candidate strings".
++# Notes:
++# - HTML 5.2 states that URL cannot start or end with comma.
++# - the "descriptor" is either "width descriptor" or "pixel density descriptor".
++# The first one consists of "valid non-negative integer + letter 'x'",
++# the second one is formed of "positive valid floating-point number +
++# letter 'w'". As a reasonable compromise, we match a list of characters
++# that form both of them.
++# Matches for example "img2.png 2x" or "img9.png 11E-2w".
++_SRCSET_ENTRY_RE = lazy_re.compile(
++ r'\s*(?P<url>[^,\s]\S+[^,\s])'
++ r'(?:\s+(?P<descriptor>[\deE.-]+[wx]))?\s*'
++ r'(?P<separator>,|$)',
++ re.MULTILINE)
++_ICON_RE = lazy_re.compile(
++ r'<link rel="icon"\s(?:[^>]+?\s)?'
++ r'href=(?P<quote>")(?P<filename>[^"\']*)\1',
++ re.MULTILINE)
++
++
++def GetDistribution():
++ """Helper function that gets the distribution we are building.
++
++ Returns:
++ string
++ """
++ distribution = DIST_DEFAULT
++ if DIST_ENV_VAR in os.environ:
++ distribution = os.environ[DIST_ENV_VAR]
++ if len(distribution) > 1 and distribution[0] == '_':
++ distribution = distribution[1:].lower()
++ return distribution
++
++def ConvertFileToDataURL(filename, base_path, distribution, inlined_files,
++ names_only):
++ """Convert filename to inlined data URI.
++
++ Takes a filename from ether "src" or "srcset", and attempts to read the file
++ at 'filename'. Returns data URI as string with given file inlined.
++ If it finds DIST_SUBSTR string in file name, replaces it with distribution.
++ If filename contains ':', it is considered URL and not translated.
++
++ Args:
++ filename: filename string from ether src or srcset attributes.
++ base_path: path that to look for files in
++ distribution: string that should replace DIST_SUBSTR
++ inlined_files: The name of the opened file is appended to this list.
++ names_only: If true, the function will not read the file but just return "".
++ It will still add the filename to |inlined_files|.
++
++ Returns:
++ string
++ """
++ if filename.find(':') != -1:
++ # filename is probably a URL, which we don't want to bother inlining
++ return filename
++
++ filename = filename.replace(DIST_SUBSTR , distribution)
++ filepath = os.path.normpath(os.path.join(base_path, filename))
++ inlined_files.add(filepath)
++
++ if names_only:
++ return ""
++
++ mimetype = mimetypes.guess_type(filename)[0]
++ if mimetype is None:
++ raise Exception('%s is of an an unknown type and '
++ 'cannot be stored in a data url.' % filename)
++ inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY))
++ return 'data:%s;base64,%s' % (mimetype, inline_data.decode('utf-8'))
++
++
++def SrcInlineAsDataURL(
++ src_match, base_path, distribution, inlined_files, names_only=False,
++ filename_expansion_function=None):
++ """regex replace function.
++
++ Takes a regex match for src="filename", attempts to read the file
++ at 'filename' and returns the src attribute with the file inlined
++ as a data URI. If it finds DIST_SUBSTR string in file name, replaces
++ it with distribution.
++
++ Args:
++ src_match: regex match object with 'filename' named capturing group
++ base_path: path that to look for files in
++ distribution: string that should replace DIST_SUBSTR
++ inlined_files: The name of the opened file is appended to this list.
++ names_only: If true, the function will not read the file but just return "".
++ It will still add the filename to |inlined_files|.
++
++ Returns:
++ string
++ """
++ filename = src_match.group('filename')
++ if filename_expansion_function:
++ filename = filename_expansion_function(filename)
++
++ data_url = ConvertFileToDataURL(filename, base_path, distribution,
++ inlined_files, names_only)
++
++ if not data_url:
++ return data_url
++
++ prefix = src_match.string[src_match.start():src_match.start('filename')]
++ suffix = src_match.string[src_match.end('filename'):src_match.end()]
++ return prefix + data_url + suffix
++
++def SrcsetInlineAsDataURL(
++ srcset_match, base_path, distribution, inlined_files, names_only=False,
++ filename_expansion_function=None):
++ """regex replace function to inline files in srcset="..." attributes
++
++ Takes a regex match for srcset="filename 1x, filename 2x, ...", attempts to
++ read the files referenced by filenames and returns the srcset attribute with
++ the files inlined as a data URI. If it finds DIST_SUBSTR string in file name,
++ replaces it with distribution.
++
++ Args:
++ srcset_match: regex match object with 'srcset' named capturing group
++ base_path: path that to look for files in
++ distribution: string that should replace DIST_SUBSTR
++ inlined_files: The name of the opened file is appended to this list.
++ names_only: If true, the function will not read the file but just return "".
++ It will still add the filename to |inlined_files|.
++
++ Returns:
++ string
++ """
++ srcset = srcset_match.group('srcset')
++
++ if not srcset:
++ return srcset_match.group(0)
++
++ # HTML 5.2 defines srcset as a list of "image candidate strings".
++ # Each of them consists of URL and descriptor.
++ # _SRCSET_ENTRY_RE splits srcset into a list of URLs, descriptors and
++ # commas.
++ # The descriptor part will be None if that optional regex didn't match
++ parts = _SRCSET_ENTRY_RE.split(srcset)
++
++ if not parts:
++ return srcset_match.group(0)
++
++ # List of image candidate strings that will form new srcset="..."
++ new_candidates = []
++
++ # When iterating over split srcset we fill this parts of a single image
++ # candidate string: [url, descriptor]
++ candidate = [];
++
++ # Each entry should consist of some text before the entry, the url,
++ # the descriptor or None if the entry has no descriptor, a comma separator or
++ # the end of the line, and finally some text after the entry (which is the
++ # same as the text before the next entry).
++ for i in range(0, len(parts) - 1, 4):
++ before, url, descriptor, separator, after = parts[i:i+5]
++
++ # There must be a comma-separated next entry or this must be the last entry.
++ assert separator == "," or (separator == "" and i == len(parts) - 5), (
++ "Bad srcset format in {}".format(srcset_match.group(0)))
++ # Both before and after the entry must be empty
++ assert before == after == "", (
++ "Bad srcset format in {}".format(srcset_match.group(0)))
++
++ if filename_expansion_function:
++ filename = filename_expansion_function(url)
++ else:
++ filename = url
++
++ data_url = ConvertFileToDataURL(filename, base_path, distribution,
++ inlined_files, names_only)
++
++ # This is not "names_only" mode
++ if data_url:
++ candidate = [data_url]
++ if descriptor:
++ candidate.append(descriptor)
++
++ new_candidates.append(" ".join(candidate))
++
++ prefix = srcset_match.string[srcset_match.start():
++ srcset_match.start('srcset')]
++ suffix = srcset_match.string[srcset_match.end('srcset'):srcset_match.end()]
++ return prefix + ','.join(new_candidates) + suffix
++
++class InlinedData:
++ """Helper class holding the results from DoInline().
++
++ Holds the inlined data and the set of filenames of all the inlined
++ files.
++ """
++ def __init__(self, inlined_data, inlined_files):
++ self.inlined_data = inlined_data
++ self.inlined_files = inlined_files
++
++def DoInline(
++ input_filename, grd_node, allow_external_script=False,
++ preprocess_only=False, names_only=False, strip_whitespace=False,
++ rewrite_function=None, filename_expansion_function=None):
++ """Helper function that inlines the resources in a specified file.
++
++ Reads input_filename, finds all the src attributes and attempts to
++ inline the files they are referring to, then returns the result and
++ the set of inlined files.
++
++ Args:
++ input_filename: name of file to read in
++ grd_node: html node from the grd file for this include tag
++ preprocess_only: Skip all HTML processing, only handle <if> and <include>.
++ names_only: |nil| will be returned for the inlined contents (faster).
++ strip_whitespace: remove whitespace and comments in the input files.
++ rewrite_function: function(filepath, text, distribution) which will be
++ called to rewrite html content before inlining images.
++ filename_expansion_function: function(filename) which will be called to
++ rewrite filenames before attempting to read them.
++ Returns:
++ a tuple of the inlined data as a string and the set of filenames
++ of all the inlined files
++ """
++ if filename_expansion_function:
++ input_filename = filename_expansion_function(input_filename)
++ input_filepath = os.path.dirname(input_filename)
++ distribution = GetDistribution()
++
++ # Keep track of all the files we inline.
++ inlined_files = set()
++
++ def SrcReplace(src_match, filepath=input_filepath,
++ inlined_files=inlined_files):
++ """Helper function to provide SrcInlineAsDataURL with the base file path"""
++ return SrcInlineAsDataURL(
++ src_match, filepath, distribution, inlined_files, names_only=names_only,
++ filename_expansion_function=filename_expansion_function)
++
++ def SrcsetReplace(srcset_match, filepath=input_filepath,
++ inlined_files=inlined_files):
++ """Helper function to provide SrcsetInlineAsDataURL with the base file
++ path.
++ """
++ return SrcsetInlineAsDataURL(
++ srcset_match, filepath, distribution, inlined_files,
++ names_only=names_only,
++ filename_expansion_function=filename_expansion_function)
++
++ def GetFilepath(src_match, base_path = input_filepath):
++ filename = [v for k, v in src_match.groupdict().items()
++ if k.startswith('file') and v][0]
++
++ if filename.find(':') != -1:
++ # filename is probably a URL, which we don't want to bother inlining
++ return None
++
++ filename = filename.replace('%DISTRIBUTION%', distribution)
++ if filename_expansion_function:
++ filename = filename_expansion_function(filename)
++ return os.path.normpath(os.path.join(base_path, filename))
++
++ def IsConditionSatisfied(src_match):
++ expr1 = src_match.group('expr1') or ''
++ expr2 = src_match.group('expr2') or ''
++ return grd_node is None or grd_node.EvaluateCondition(expr1 + expr2)
++
++ def CheckConditionalElements(str):
++ """Helper function to conditionally inline inner elements"""
++ while True:
++ begin_if = _BEGIN_IF_BLOCK.search(str)
++ if begin_if is None:
++ if _END_IF_BLOCK.search(str) is not None:
++ raise Exception('Unmatched </if>')
++ return str
++
++ condition_satisfied = IsConditionSatisfied(begin_if)
++ leading = str[0:begin_if.start()]
++ content_start = begin_if.end()
++
++ # Find matching "if" block end.
++ count = 1
++ pos = begin_if.end()
++ while True:
++ end_if = _END_IF_BLOCK.search(str, pos)
++ if end_if is None:
++ raise Exception('Unmatched <if>')
++
++ next_if = _BEGIN_IF_BLOCK.search(str, pos)
++ if next_if is None or next_if.start() >= end_if.end():
++ count = count - 1
++ if count == 0:
++ break
++ pos = end_if.end()
++ else:
++ count = count + 1
++ pos = next_if.end()
++
++ content = str[content_start:end_if.start()]
++ trailing = str[end_if.end():]
++
++ if condition_satisfied:
++ str = leading + CheckConditionalElements(content) + trailing
++ else:
++ str = leading + trailing
++
++ def InlineFileContents(src_match,
++ pattern,
++ inlined_files=inlined_files,
++ strip_whitespace=False):
++ """Helper function to inline external files of various types"""
++ filepath = GetFilepath(src_match)
++ if filepath is None:
++ return src_match.group(0)
++ inlined_files.add(filepath)
++
++ if names_only:
++ inlined_files.update(GetResourceFilenames(
++ filepath,
++ grd_node,
++ allow_external_script,
++ rewrite_function,
++ filename_expansion_function=filename_expansion_function))
++ return ""
++ # To recursively save inlined files, we need InlinedData instance returned
++ # by DoInline.
++ inlined_data_inst=DoInline(filepath, grd_node,
++ allow_external_script=allow_external_script,
++ preprocess_only=preprocess_only,
++ strip_whitespace=strip_whitespace,
++ filename_expansion_function=filename_expansion_function)
++
++ inlined_files.update(inlined_data_inst.inlined_files)
++
++ return pattern % inlined_data_inst.inlined_data;
++
++
++ def InlineIncludeFiles(src_match):
++ """Helper function to directly inline generic external files (without
++ wrapping them with any kind of tags).
++ """
++ return InlineFileContents(src_match, '%s')
++
++ def InlineScript(match):
++ """Helper function to inline external script files"""
++ attrs = (match.group('attrs1') + match.group('attrs2')).strip()
++ if attrs:
++ attrs = ' ' + attrs
++ return InlineFileContents(match, '<script' + attrs + '>%s</script>',
++ strip_whitespace=True)
++
++ def InlineCSSText(text, css_filepath):
++ """Helper function that inlines external resources in CSS text"""
++ filepath = os.path.dirname(css_filepath)
++ # Allow custom modifications before inlining images.
++ if rewrite_function:
++ text = rewrite_function(filepath, text, distribution)
++ text = InlineCSSImages(text, filepath)
++ return InlineCSSImports(text, filepath)
++
++ def InlineCSSFile(src_match, pattern, base_path=input_filepath):
++ """Helper function to inline external CSS files.
++
++ Args:
++ src_match: A regular expression match with a named group named "filename".
++ pattern: The pattern to replace with the contents of the CSS file.
++ base_path: The base path to use for resolving the CSS file.
++
++ Returns:
++ The text that should replace the reference to the CSS file.
++ """
++ filepath = GetFilepath(src_match, base_path)
++ if filepath is None:
++ return src_match.group(0)
++
++ # Even if names_only is set, the CSS file needs to be opened, because it
++ # can link to images that need to be added to the file set.
++ inlined_files.add(filepath)
++
++ # Inline stylesheets included in this css file.
++ text = _INCLUDE_RE.sub(InlineIncludeFiles, util.ReadFile(filepath, 'utf-8'))
++ # When resolving CSS files we need to pass in the path so that relative URLs
++ # can be resolved.
++
++ return pattern % InlineCSSText(text, filepath)
++
++ def GetUrlRegexString(postfix=''):
++ """Helper function that returns a string for a regex that matches url('')
++ but not url([[ ]]) or url({{ }}). Appends |postfix| to group names.
++ """
++ url_re = (r'url\((?!\[\[|{{)(?P<q%s>"|\'|)(?P<filename%s>[^"\'()]*)'
++ r'(?P=q%s)\)')
++ return url_re % (postfix, postfix, postfix)
++
++ def InlineCSSImages(text, filepath=input_filepath):
++ """Helper function that inlines external images in CSS backgrounds."""
++ # Replace contents of url() for css attributes: content, background,
++ # or *-image.
++ property_re = r'(content|background|[\w-]*-image):[^;]*'
++ # Replace group names to prevent duplicates when forming value_re.
++ image_set_value_re = (r'image-set\(([ ]*' + GetUrlRegexString('2') +
++ r'[ ]*[0-9.]*x[ ]*(,[ ]*)?)+\)')
++ value_re = '(%s|%s)' % (GetUrlRegexString(), image_set_value_re)
++ css_re = property_re + value_re
++ return re.sub(css_re, lambda m: InlineCSSUrls(m, filepath), text)
++
++ def InlineCSSUrls(src_match, filepath=input_filepath):
++ """Helper function that inlines each url on a CSS image rule match."""
++ # Replace contents of url() references in matches.
++ return re.sub(GetUrlRegexString(),
++ lambda m: SrcReplace(m, filepath),
++ src_match.group(0))
++
++ def InlineCSSImports(text, filepath=input_filepath):
++ """Helper function that inlines CSS files included via the @import
++ directive.
++ """
++ return re.sub(r'@import\s+' + GetUrlRegexString() + r';',
++ lambda m: InlineCSSFile(m, '%s', filepath),
++ text)
++
++
++ flat_text = util.ReadFile(input_filename, 'utf-8')
++
++ # Check conditional elements, remove unsatisfied ones from the file. We do
++ # this twice. The first pass is so that we don't even bother calling
++ # InlineScript, InlineCSSFile and InlineIncludeFiles on text we're eventually
++ # going to throw out anyway.
++ flat_text = CheckConditionalElements(flat_text)
++
++ flat_text = _INCLUDE_RE.sub(InlineIncludeFiles, flat_text)
++
++ if not preprocess_only:
++ if strip_whitespace:
++ flat_text = minifier.Minify(flat_text.encode('utf-8'),
++ input_filename).decode('utf-8')
++
++ if not allow_external_script:
++ # We need to inline css and js before we inline images so that image
++ # references gets inlined in the css and js
++ flat_text = re.sub(r'<script (?P<attrs1>.*?)src="(?P<filename>[^"\']*)"'
++ r'(?P<attrs2>.*?)></script>',
++ InlineScript,
++ flat_text)
++
++ flat_text = _STYLESHEET_RE.sub(
++ lambda m: InlineCSSFile(m, '<style>%s</style>'),
++ flat_text)
++
++ # Check conditional elements, second pass. This catches conditionals in any
++ # of the text we just inlined.
++ flat_text = CheckConditionalElements(flat_text)
++
++ # Allow custom modifications before inlining images.
++ if rewrite_function:
++ flat_text = rewrite_function(input_filepath, flat_text, distribution)
++
++ if not preprocess_only:
++ flat_text = _SRC_RE.sub(SrcReplace, flat_text)
++ flat_text = _SRCSET_RE.sub(SrcsetReplace, flat_text)
++
++ # TODO(arv): Only do this inside <style> tags.
++ flat_text = InlineCSSImages(flat_text)
++
++ flat_text = _ICON_RE.sub(SrcReplace, flat_text)
++
++ if names_only:
++ flat_text = None # Will contains garbage if the flag is set anyway.
++ return InlinedData(flat_text, inlined_files)
++
++
++def InlineToString(input_filename, grd_node, preprocess_only = False,
++ allow_external_script=False, strip_whitespace=False,
++ rewrite_function=None, filename_expansion_function=None):
++ """Inlines the resources in a specified file and returns it as a string.
++
++ Args:
++ input_filename: name of file to read in
++ grd_node: html node from the grd file for this include tag
++ Returns:
++ the inlined data as a string
++ """
++ try:
++ return DoInline(
++ input_filename,
++ grd_node,
++ preprocess_only=preprocess_only,
++ allow_external_script=allow_external_script,
++ strip_whitespace=strip_whitespace,
++ rewrite_function=rewrite_function,
++ filename_expansion_function=filename_expansion_function).inlined_data
++ except IOError as e:
++ raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
++ (e.filename, input_filename, e.strerror))
++
++
++def InlineToFile(input_filename, output_filename, grd_node):
++ """Inlines the resources in a specified file and writes it.
++
++ Reads input_filename, finds all the src attributes and attempts to
++ inline the files they are referring to, then writes the result
++ to output_filename.
++
++ Args:
++ input_filename: name of file to read in
++ output_filename: name of file to be written to
++ grd_node: html node from the grd file for this include tag
++ Returns:
++ a set of filenames of all the inlined files
++ """
++ inlined_data = InlineToString(input_filename, grd_node)
++ with open(output_filename, 'wb') as out_file:
++ out_file.write(inlined_data)
++
++
++def GetResourceFilenames(filename,
++ grd_node,
++ allow_external_script=False,
++ rewrite_function=None,
++ filename_expansion_function=None):
++ """For a grd file, returns a set of all the files that would be inline."""
++ try:
++ return DoInline(
++ filename,
++ grd_node,
++ names_only=True,
++ preprocess_only=False,
++ allow_external_script=allow_external_script,
++ strip_whitespace=False,
++ rewrite_function=rewrite_function,
++ filename_expansion_function=filename_expansion_function).inlined_files
++ except IOError as e:
++ raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
++ (e.filename, filename, e.strerror))
++
++
++def main():
++ if len(sys.argv) <= 2:
++ print("Flattens a HTML file by inlining its external resources.\n")
++ print("html_inline.py inputfile outputfile")
++ else:
++ InlineToFile(sys.argv[1], sys.argv[2], None)
++
++if __name__ == '__main__':
++ main()
+diff --git a/tools/grit/grit/format/html_inline_unittest.py b/tools/grit/grit/format/html_inline_unittest.py
+new file mode 100644
+index 0000000000..1b11e9e476
+--- /dev/null
++++ b/tools/grit/grit/format/html_inline_unittest.py
+@@ -0,0 +1,927 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.format.html_inline'''
++
++from __future__ import print_function
++
++import os
++import re
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit import util
++from grit.format import html_inline
++
++
++class HtmlInlineUnittest(unittest.TestCase):
++ '''Unit tests for HtmlInline.'''
++
++ def testGetResourceFilenames(self):
++ '''Tests that all included files are returned by GetResourceFilenames.'''
++
++ files = {
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ <link rel="stylesheet"
++ href="really-long-long-long-long-long-test.css">
++ </head>
++ <body>
++ <include src='test.html'>
++ <include
++ src="really-long-long-long-long-long-test-file-omg-so-long.html">
++ </body>
++ </html>
++ ''',
++
++ 'test.html': '''
++ <include src="test2.html">
++ ''',
++
++ 'really-long-long-long-long-long-test-file-omg-so-long.html': '''
++ <!-- This really long named resource should be included. -->
++ ''',
++
++ 'test2.html': '''
++ <!-- This second level resource should also be included. -->
++ ''',
++
++ 'test.css': '''
++ .image {
++ background: url('test.png');
++ }
++ ''',
++
++ 'really-long-long-long-long-long-test.css': '''
++ a:hover {
++ font-weight: bold; /* Awesome effect is awesome! */
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++ }
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'),
++ None)
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ tmp_dir.CleanUp()
++
++ def testUnmatchedEndIfBlock(self):
++ '''Tests that an unmatched </if> raises an exception.'''
++
++ files = {
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <if expr="lang == 'fr'">
++ bonjour
++ </if>
++ <if expr='lang == "de"'>
++ hallo
++ </if>
++ </if>
++ </html>
++ ''',
++ }
++
++ tmp_dir = util.TempDir(files)
++
++ with self.assertRaises(Exception) as cm:
++ html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'), None)
++ self.failUnlessEqual(str(cm.exception), 'Unmatched </if>')
++ tmp_dir.CleanUp()
++
++ def testCompressedJavaScript(self):
++ '''Tests that ".src=" doesn't treat as a tag.'''
++
++ files = {
++ 'index.js': '''
++ if(i<j)a.src="hoge.png";
++ ''',
++ }
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.js'),
++ None)
++ resources.add(tmp_dir.GetPath('index.js'))
++ self.failUnlessEqual(resources, source_resources)
++ tmp_dir.CleanUp()
++
++ def testInlineCSSImports(self):
++ '''Tests that @import directives in inlined CSS files are inlined too.
++ '''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="css/test.css">
++ </head>
++ </html>
++ ''',
++
++ 'css/test.css': '''
++ @import url('test2.css');
++ blink {
++ display: none;
++ }
++ ''',
++
++ 'css/test2.css': '''
++ .image {
++ background: url('../images/test.png');
++ }
++ '''.strip(),
++
++ 'images/test.png': 'PNG DATA'
++ }
++
++ expected_inlined = '''
++ <html>
++ <head>
++ <style>
++ .image {
++ background: url('data:image/png;base64,UE5HIERBVEE=');
++ }
++ blink {
++ display: none;
++ }
++ </style>
++ </head>
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++
++ tmp_dir.CleanUp()
++
++ def testInlineIgnoresPolymerBindings(self):
++ '''Tests that polymer bindings are ignored when inlining.
++ '''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ </head>
++ <body>
++ <iron-icon src="[[icon]]"></iron-icon><!-- Should be ignored. -->
++ <iron-icon src="{{src}}"></iron-icon><!-- Also ignored. -->
++ <!-- [[image]] should be ignored. -->
++ <div style="background: url([[image]]),
++ url('test.png');">
++ </div>
++ <div style="background: url('test.png'),
++ url([[image]]);">
++ </div>
++ </body>
++ </html>
++ ''',
++
++ 'test.css': '''
++ .image {
++ background: url('test.png');
++ background-image: url([[ignoreMe]]);
++ background-image: image-set(url({{alsoMe}}), 1x);
++ background-image: image-set(
++ url({{ignore}}) 1x,
++ url('test.png') 2x);
++ }
++ ''',
++
++ 'test.png': 'PNG DATA'
++ }
++
++ expected_inlined = '''
++ <html>
++ <head>
++ <style>
++ .image {
++ background: url('data:image/png;base64,UE5HIERBVEE=');
++ background-image: url([[ignoreMe]]);
++ background-image: image-set(url({{alsoMe}}), 1x);
++ background-image: image-set(
++ url({{ignore}}) 1x,
++ url('data:image/png;base64,UE5HIERBVEE=') 2x);
++ }
++ </style>
++ </head>
++ <body>
++ <iron-icon src="[[icon]]"></iron-icon><!-- Should be ignored. -->
++ <iron-icon src="{{src}}"></iron-icon><!-- Also ignored. -->
++ <!-- [[image]] should be ignored. -->
++ <div style="background: url([[image]]),
++ url('data:image/png;base64,UE5HIERBVEE=');">
++ </div>
++ <div style="background: url('data:image/png;base64,UE5HIERBVEE='),
++ url([[image]]);">
++ </div>
++ </body>
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++
++ tmp_dir.CleanUp()
++
++ def testInlineCSSWithIncludeDirective(self):
++ '''Tests that include directive in external css files also inlined'''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="foo.css">
++ </head>
++ </html>
++ ''',
++
++ 'foo.css': '''<include src="style.css">''',
++
++ 'style.css': '''
++ <include src="style2.css">
++ blink {
++ display: none;
++ }
++ ''',
++ 'style2.css': '''h1 {}''',
++ }
++
++ expected_inlined = '''
++ <html>
++ <head>
++ <style>
++ h1 {}
++ blink {
++ display: none;
++ }
++ </style>
++ </head>
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testCssIncludedFileNames(self):
++ '''Tests that all included files from css are returned'''
++
++ files = {
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ </head>
++ <body>
++ </body>
++ </html>
++ ''',
++
++ 'test.css': '''
++ <include src="test2.css">
++ ''',
++
++ 'test2.css': '''
++ <include src="test3.css">
++ .image {
++ background: url('test.png');
++ }
++ ''',
++
++ 'test3.css': '''h1 {}''',
++
++ 'test.png': 'PNG DATA'
++ }
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'),
++ None)
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ tmp_dir.CleanUp()
++
++ def testInlineCSSLinks(self):
++ '''Tests that only CSS files referenced via relative URLs are inlined.'''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="foo.css">
++ <link rel="stylesheet" href="chrome://resources/bar.css">
++ </head>
++ </html>
++ ''',
++
++ 'foo.css': '''
++ @import url(chrome://resources/blurp.css);
++ blink {
++ display: none;
++ }
++ ''',
++ }
++
++ expected_inlined = '''
++ <html>
++ <head>
++ <style>
++ @import url(chrome://resources/blurp.css);
++ blink {
++ display: none;
++ }
++ </style>
++ <link rel="stylesheet" href="chrome://resources/bar.css">
++ </head>
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testFilenameVariableExpansion(self):
++ '''Tests that variables are expanded in filenames before inlining.'''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="style[WHICH].css">
++ <script src="script[WHICH].js"></script>
++ </head>
++ <include src="tmpl[WHICH].html">
++ <img src="img[WHICH].png">
++ </html>
++ ''',
++ 'style1.css': '''h1 {}''',
++ 'tmpl1.html': '''<h1></h1>''',
++ 'script1.js': '''console.log('hello');''',
++ 'img1.png': '''abc''',
++ }
++
++ expected_inlined = '''
++ <html>
++ <head>
++ <style>h1 {}</style>
++ <script>console.log('hello');</script>
++ </head>
++ <h1></h1>
++ <img src="data:image/png;base64,YWJj">
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ def replacer(var, repl):
++ return lambda filename: filename.replace('[%s]' % var, repl)
++
++ # Test normal inlining.
++ result = html_inline.DoInline(
++ tmp_dir.GetPath('index.html'),
++ None,
++ filename_expansion_function=replacer('WHICH', '1'))
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++
++ # Test names-only inlining.
++ result = html_inline.DoInline(
++ tmp_dir.GetPath('index.html'),
++ None,
++ names_only=True,
++ filename_expansion_function=replacer('WHICH', '1'))
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ tmp_dir.CleanUp()
++
++ def testWithCloseTags(self):
++ '''Tests that close tags are removed.'''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="style1.css"></link>
++ <link rel="stylesheet" href="style2.css">
++ </link>
++ <link rel="stylesheet" href="style2.css"
++ >
++ </link>
++ <script src="script1.js"></script>
++ </head>
++ <include src="tmpl1.html"></include>
++ <include src="tmpl2.html">
++ </include>
++ <include src="tmpl2.html"
++ >
++ </include>
++ <img src="img1.png">
++ <include src='single-double-quotes.html"></include>
++ <include src="double-single-quotes.html'></include>
++ </html>
++ ''',
++ 'style1.css': '''h1 {}''',
++ 'style2.css': '''h2 {}''',
++ 'tmpl1.html': '''<h1></h1>''',
++ 'tmpl2.html': '''<h2></h2>''',
++ 'script1.js': '''console.log('hello');''',
++ 'img1.png': '''abc''',
++ }
++
++ expected_inlined = '''
++ <html>
++ <head>
++ <style>h1 {}</style>
++ <style>h2 {}</style>
++ <style>h2 {}</style>
++ <script>console.log('hello');</script>
++ </head>
++ <h1></h1>
++ <h2></h2>
++ <h2></h2>
++ <img src="data:image/png;base64,YWJj">
++ <include src='single-double-quotes.html"></include>
++ <include src="double-single-quotes.html'></include>
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ # Test normal inlining.
++ result = html_inline.DoInline(
++ tmp_dir.GetPath('index.html'),
++ None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testCommentedJsInclude(self):
++ '''Tests that <include> works inside a comment.'''
++
++ files = {
++ 'include.js': '// <include src="other.js">',
++ 'other.js': '// Copyright somebody\nalert(1);',
++ }
++
++ expected_inlined = '// Copyright somebody\nalert(1);'
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('include.js'), None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('include.js'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testCommentedJsIf(self):
++ '''Tests that <if> works inside a comment.'''
++
++ files = {
++ 'if.js': '''
++ // <if expr="True">
++ yep();
++ // </if>
++
++ // <if expr="False">
++ nope();
++ // </if>
++ ''',
++ }
++
++ expected_inlined = '''
++ //
++ yep();
++ //
++
++ //
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ class FakeGrdNode(object):
++ def EvaluateCondition(self, cond):
++ return eval(cond)
++
++ result = html_inline.DoInline(tmp_dir.GetPath('if.js'), FakeGrdNode())
++ resources = result.inlined_files
++
++ resources.add(tmp_dir.GetPath('if.js'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testImgSrcset(self):
++ '''Tests that img srcset="" attributes are converted.'''
++
++ # Note that there is no space before "img10.png" and that
++ # "img11.png" has no descriptor.
++ files = {
++ 'index.html': '''
++ <html>
++ <img src="img1.png" srcset="img2.png 1x, img3.png 2x">
++ <img src="img4.png" srcset=" img5.png 1x , img6.png 2x ">
++ <img src="chrome://theme/img11.png" srcset="img7.png 1x, '''\
++ '''chrome://theme/img13.png 2x">
++ <img srcset="img8.png 300w, img9.png 11E-2w,img10.png -1e2w">
++ <img srcset="img11.png">
++ <img srcset="img11.png, img2.png 1x">
++ <img srcset="img2.png 1x, img11.png">
++ </html>
++ ''',
++ 'img1.png': '''a1''',
++ 'img2.png': '''a2''',
++ 'img3.png': '''a3''',
++ 'img4.png': '''a4''',
++ 'img5.png': '''a5''',
++ 'img6.png': '''a6''',
++ 'img7.png': '''a7''',
++ 'img8.png': '''a8''',
++ 'img9.png': '''a9''',
++ 'img10.png': '''a10''',
++ 'img11.png': '''a11''',
++ }
++
++ expected_inlined = '''
++ <html>
++ <img src="data:image/png;base64,YTE=" srcset="data:image/png;base64,'''\
++ '''YTI= 1x,data:image/png;base64,YTM= 2x">
++ <img src="data:image/png;base64,YTQ=" srcset="data:image/png;base64,'''\
++ '''YTU= 1x,data:image/png;base64,YTY= 2x">
++ <img src="chrome://theme/img11.png" srcset="data:image/png;base64,'''\
++ '''YTc= 1x,chrome://theme/img13.png 2x">
++ <img srcset="data:image/png;base64,YTg= 300w,data:image/png;base64,'''\
++ '''YTk= 11E-2w,data:image/png;base64,YTEw -1e2w">
++ <img srcset="data:image/png;base64,YTEx">
++ <img srcset="data:image/png;base64,YTEx,data:image/png;base64,YTI= 1x">
++ <img srcset="data:image/png;base64,YTI= 1x,data:image/png;base64,YTEx">
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ # Test normal inlining.
++ result = html_inline.DoInline(
++ tmp_dir.GetPath('index.html'),
++ None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testImgSrcsetIgnoresI18n(self):
++ '''Tests that $i18n{...} strings are ignored when inlining.
++ '''
++
++ src_html = '''
++ <html>
++ <head></head>
++ <body>
++ <img srcset="$i18n{foo}">
++ </body>
++ </html>
++ '''
++
++ files = {
++ 'index.html': src_html,
++ }
++
++ expected_inlined = src_html
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testSourceSrcset(self):
++ '''Tests that source srcset="" attributes are converted.'''
++
++ # Note that there is no space before "img10.png" and that
++ # "img11.png" has no descriptor.
++ files = {
++ 'index.html': '''
++ <html>
++ <source src="img1.png" srcset="img2.png 1x, img3.png 2x">
++ <source src="img4.png" srcset=" img5.png 1x , img6.png 2x ">
++ <source src="chrome://theme/img11.png" srcset="img7.png 1x, '''\
++ '''chrome://theme/img13.png 2x">
++ <source srcset="img8.png 300w, img9.png 11E-2w,img10.png -1e2w">
++ <source srcset="img11.png">
++ </html>
++ ''',
++ 'img1.png': '''a1''',
++ 'img2.png': '''a2''',
++ 'img3.png': '''a3''',
++ 'img4.png': '''a4''',
++ 'img5.png': '''a5''',
++ 'img6.png': '''a6''',
++ 'img7.png': '''a7''',
++ 'img8.png': '''a8''',
++ 'img9.png': '''a9''',
++ 'img10.png': '''a10''',
++ 'img11.png': '''a11''',
++ }
++
++ expected_inlined = '''
++ <html>
++ <source src="data:image/png;base64,YTE=" srcset="data:image/png;'''\
++ '''base64,YTI= 1x,data:image/png;base64,YTM= 2x">
++ <source src="data:image/png;base64,YTQ=" srcset="data:image/png;'''\
++ '''base64,YTU= 1x,data:image/png;base64,YTY= 2x">
++ <source src="chrome://theme/img11.png" srcset="data:image/png;'''\
++ '''base64,YTc= 1x,chrome://theme/img13.png 2x">
++ <source srcset="data:image/png;base64,YTg= 300w,data:image/png;'''\
++ '''base64,YTk= 11E-2w,data:image/png;base64,YTEw -1e2w">
++ <source srcset="data:image/png;base64,YTEx">
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ # Test normal inlining.
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++ self.failUnlessEqual(expected_inlined,
++ util.FixLineEnd(result.inlined_data, '\n'))
++ tmp_dir.CleanUp()
++
++ def testConditionalInclude(self):
++ '''Tests that output and dependency generation includes only files not'''\
++ ''' blocked by <if> macros.'''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <if expr="True">
++ <img src="img1.png" srcset="img2.png 1x, img3.png 2x">
++ </if>
++ <if expr="False">
++ <img src="img4.png" srcset=" img5.png 1x, img6.png 2x ">
++ </if>
++ <if expr="True">
++ <img src="chrome://theme/img11.png" srcset="img7.png 1x, '''\
++ '''chrome://theme/img13.png 2x">
++ </if>
++ <img srcset="img8.png 300w, img9.png 11E-2w,img10.png -1e2w">
++ </html>
++ ''',
++ 'img1.png': '''a1''',
++ 'img2.png': '''a2''',
++ 'img3.png': '''a3''',
++ 'img4.png': '''a4''',
++ 'img5.png': '''a5''',
++ 'img6.png': '''a6''',
++ 'img7.png': '''a7''',
++ 'img8.png': '''a8''',
++ 'img9.png': '''a9''',
++ 'img10.png': '''a10''',
++ }
++
++ expected_inlined = '''
++ <html>
++ <img src="data:image/png;base64,YTE=" srcset="data:image/png;base64,'''\
++ '''YTI= 1x,data:image/png;base64,YTM= 2x">
++ <img src="chrome://theme/img11.png" srcset="data:image/png;base64,'''\
++ '''YTc= 1x,chrome://theme/img13.png 2x">
++ <img srcset="data:image/png;base64,YTg= 300w,data:image/png;base64,'''\
++ '''YTk= 11E-2w,data:image/png;base64,YTEw -1e2w">
++ </html>
++ '''
++
++ expected_files = [
++ 'index.html',
++ 'img1.png',
++ 'img2.png',
++ 'img3.png',
++ 'img7.png',
++ 'img8.png',
++ 'img9.png',
++ 'img10.png'
++ ]
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ for filename in expected_files:
++ source_resources.add(tmp_dir.GetPath(filename))
++
++ class FakeGrdNode(object):
++ def EvaluateCondition(self, cond):
++ return eval(cond)
++
++ # Test normal inlining.
++ result = html_inline.DoInline(
++ tmp_dir.GetPath('index.html'),
++ FakeGrdNode())
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++
++ # ignore whitespace
++ expected_inlined = re.sub(r'\s+', ' ', expected_inlined)
++ actually_inlined = re.sub(r'\s+', ' ',
++ util.FixLineEnd(result.inlined_data, '\n'))
++ self.failUnlessEqual(expected_inlined, actually_inlined);
++ tmp_dir.CleanUp()
++
++ def testPreprocessOnlyEvaluatesIncludeAndIf(self):
++ '''Tests that preprocess_only=true evaluates <include> and <if> only. '''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="not_inlined.css">
++ <script src="also_not_inlined.js">
++ </head>
++ <body>
++ <include src="inline_this.html">
++ <if expr="True">
++ <p>'if' should be evaluated.</p>
++ </if>
++ </body>
++ </html>
++ ''',
++ 'not_inlined.css': ''' /* <link> should not be inlined. */ ''',
++ 'also_not_inlined.js': ''' // <script> should not be inlined. ''',
++ 'inline_this.html': ''' <p>'include' should be inlined.</p> '''
++ }
++
++ expected_inlined = '''
++ <html>
++ <head>
++ <link rel="stylesheet" href="not_inlined.css">
++ <script src="also_not_inlined.js">
++ </head>
++ <body>
++ <p>'include' should be inlined.</p>
++ <p>'if' should be evaluated.</p>
++ </body>
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ source_resources.add(tmp_dir.GetPath('index.html'))
++ source_resources.add(tmp_dir.GetPath('inline_this.html'))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None,
++ preprocess_only=True)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++
++ # Ignore whitespace
++ expected_inlined = re.sub(r'\s+', ' ', expected_inlined)
++ actually_inlined = re.sub(r'\s+', ' ',
++ util.FixLineEnd(result.inlined_data, '\n'))
++ self.failUnlessEqual(expected_inlined, actually_inlined)
++
++ tmp_dir.CleanUp()
++
++ def testPreprocessOnlyAppliesRecursively(self):
++ '''Tests that preprocess_only=true propagates to included files. '''
++
++ files = {
++ 'index.html': '''
++ <html>
++ <include src="outer_include.html">
++ </html>
++ ''',
++ 'outer_include.html': '''
++ <include src="inner_include.html">
++ <link rel="stylesheet" href="not_inlined.css">
++ ''',
++ 'inner_include.html': ''' <p>This should be inlined in index.html</p> ''',
++ 'not_inlined.css': ''' /* This should not be inlined. */ '''
++ }
++
++ expected_inlined = '''
++ <html>
++ <p>This should be inlined in index.html</p>
++ <link rel="stylesheet" href="not_inlined.css">
++ </html>
++ '''
++
++ source_resources = set()
++ tmp_dir = util.TempDir(files)
++ source_resources.add(tmp_dir.GetPath('index.html'))
++ source_resources.add(tmp_dir.GetPath('outer_include.html'))
++ source_resources.add(tmp_dir.GetPath('inner_include.html'))
++
++ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None,
++ preprocess_only=True)
++ resources = result.inlined_files
++ resources.add(tmp_dir.GetPath('index.html'))
++ self.failUnlessEqual(resources, source_resources)
++
++ # Ignore whitespace
++ expected_inlined = re.sub(r'\s+', ' ', expected_inlined)
++ actually_inlined = re.sub(r'\s+', ' ',
++ util.FixLineEnd(result.inlined_data, '\n'))
++ self.failUnlessEqual(expected_inlined, actually_inlined)
++
++ tmp_dir.CleanUp()
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/minifier.py b/tools/grit/grit/format/minifier.py
+new file mode 100644
+index 0000000000..1a0ea34e49
+--- /dev/null
++++ b/tools/grit/grit/format/minifier.py
+@@ -0,0 +1,45 @@
++# Copyright 2016 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++"""Framework for stripping whitespace and comments from resource files"""
++
++from __future__ import print_function
++
++from os import path
++import subprocess
++import sys
++
++import six
++
++__js_minifier = None
++__css_minifier = None
++
++def SetJsMinifier(minifier):
++ global __js_minifier
++ __js_minifier = minifier.split()
++
++def SetCssMinifier(minifier):
++ global __css_minifier
++ __css_minifier = minifier.split()
++
++def Minify(source, filename):
++ """Minify |source| (bytes) from |filename| and return bytes."""
++ file_type = path.splitext(filename)[1]
++ minifier = None
++ if file_type == '.js':
++ minifier = __js_minifier
++ elif file_type == '.css':
++ minifier = __css_minifier
++ if not minifier:
++ return source
++ p = subprocess.Popen(
++ minifier,
++ stdin=subprocess.PIPE,
++ stdout=subprocess.PIPE,
++ stderr=subprocess.PIPE)
++ (stdout, stderr) = p.communicate(source)
++ if p.returncode != 0:
++ print('Minification failed for %s' % filename)
++ print(stderr)
++ sys.exit(p.returncode)
++ return stdout
+diff --git a/tools/grit/grit/format/policy_templates_json.py b/tools/grit/grit/format/policy_templates_json.py
+new file mode 100644
+index 0000000000..2f9330bb9a
+--- /dev/null
++++ b/tools/grit/grit/format/policy_templates_json.py
+@@ -0,0 +1,26 @@
++# Copyright 2017 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Translates policy_templates.json files.
++"""
++
++from __future__ import print_function
++
++from grit.node import structure
++
++
++def Format(root, lang='en', output_dir='.'):
++ policy_json = None
++ for item in root.ActiveDescendants():
++ with item:
++ if (isinstance(item, structure.StructureNode) and
++ item.attrs['type'] == 'policy_template_metafile'):
++ json_text = item.gatherer.Translate(
++ lang,
++ pseudo_if_not_available=item.PseudoIsAllowed(),
++ fallback_to_english=item.ShouldFallbackToEnglish())
++ # We're only expecting one node of this kind.
++ assert not policy_json
++ policy_json = json_text
++ return policy_json
+diff --git a/tools/grit/grit/format/policy_templates_json_unittest.py b/tools/grit/grit/format/policy_templates_json_unittest.py
+new file mode 100644
+index 0000000000..e252c94e2c
+--- /dev/null
++++ b/tools/grit/grit/format/policy_templates_json_unittest.py
+@@ -0,0 +1,207 @@
++#!/usr/bin/env python
++# coding: utf-8
++# Copyright 2017 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Unittest for policy_templates_json.py.
++"""
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import grit.extern.tclib
++import tempfile
++import unittest
++
++from six import StringIO
++
++from grit import grd_reader
++from grit.tool import build
++
++
++class PolicyTemplatesJsonUnittest(unittest.TestCase):
++
++ def testPolicyTranslation(self):
++ # Create test policy_templates.json data.
++ caption = "The main policy"
++ caption_translation = "Die Hauptrichtlinie"
++
++ message = \
++ "Red cabbage stays red cabbage and wedding dress stays wedding dress"
++ message_translation = \
++ "Blaukraut bleibt Blaukraut und Brautkleid bleibt Brautkleid"
++
++ schema_key_description = "Number of users"
++ schema_key_description_translation = "Anzahl der Nutzer"
++
++ policy_json = """
++ {
++ "policy_definitions": [
++ {
++ 'name': 'MainPolicy',
++ 'type': 'main',
++ 'owners': ['foo@bar.com'],
++ 'schema': {
++ 'properties': {
++ 'default_launch_container': {
++ 'enum': [
++ 'tab',
++ 'window',
++ ],
++ 'type': 'string',
++ },
++ 'users_number': {
++ 'description': '''%s''',
++ 'type': 'integer',
++ },
++ },
++ 'type': 'object',
++ },
++ 'supported_on': ['chrome_os:29-'],
++ 'features': {
++ 'can_be_recommended': True,
++ 'dynamic_refresh': True,
++ },
++ 'example_value': True,
++ 'caption': '''%s''',
++ 'tags': [],
++ 'desc': '''This policy does stuff.'''
++ },
++ ],
++ "policy_atomic_group_definitions": [],
++ "placeholders": [],
++ "messages": {
++ 'message_string_id': {
++ 'desc': '''The description is removed from the grit output''',
++ 'text': '''%s'''
++ }
++ }
++ }""" % (schema_key_description, caption, message)
++
++ # Create translations. The translation IDs are hashed from the English text.
++ caption_id = grit.extern.tclib.GenerateMessageId(caption);
++ message_id = grit.extern.tclib.GenerateMessageId(message);
++ schema_key_description_id = grit.extern.tclib.GenerateMessageId(
++ schema_key_description)
++ policy_xtb = """
++<?xml version="1.0" ?>
++<!DOCTYPE translationbundle>
++<translationbundle lang="de">
++<translation id="%s">%s</translation>
++<translation id="%s">%s</translation>
++<translation id="%s">%s</translation>
++</translationbundle>""" % (caption_id, caption_translation,
++ message_id, message_translation,
++ schema_key_description_id,
++ schema_key_description_translation)
++
++ # Write both to a temp file.
++ tmp_dir_name = tempfile.gettempdir()
++
++ json_file_path = os.path.join(tmp_dir_name, 'test.json')
++ with open(json_file_path, 'w') as f:
++ f.write(policy_json.strip())
++
++ xtb_file_path = os.path.join(tmp_dir_name, 'test.xtb')
++ with open(xtb_file_path, 'w') as f:
++ f.write(policy_xtb.strip())
++
++ # Assemble a test grit tree, similar to policy_templates.grd.
++ grd_text = '''
++ <grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
++ <translations>
++ <file path="%s" lang="de" />
++ </translations>
++ <release seq="1">
++ <structures>
++ <structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
++ </structures>
++ </release>
++ </grit>''' % (xtb_file_path, json_file_path)
++ grd_string_io = StringIO(grd_text)
++
++ # Parse the grit tree and load the policies' JSON with a gatherer.
++ grd = grd_reader.Parse(grd_string_io, dir=tmp_dir_name, defines={'_google_chrome': True})
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++
++ # Remove the temp files.
++ os.unlink(xtb_file_path)
++ os.unlink(json_file_path)
++
++ # Run grit with en->de translation.
++ env_lang = 'en'
++ out_lang = 'de'
++ env_defs = {'_google_chrome': '1'}
++
++ grd.SetOutputLanguage(env_lang)
++ grd.SetDefines(env_defs)
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(grd, DummyOutput('policy_templates', out_lang), buf)
++ output = buf.getvalue()
++
++ # Caption and message texts get taken from xtb.
++ # desc is 'translated' to some pseudo-English
++ # 'ThïPïs pôPôlïPïcýPý dôéPôés stüPüff'.
++ expected = u"""{
++ "policy_definitions": [
++ {
++ "caption": "%s",
++ "desc": "Th\xefP\xefs p\xf4P\xf4l\xefP\xefc\xfdP\xfd d\xf4\xe9P\xf4\xe9s st\xfcP\xfcff.",
++ "example_value": true,
++ "features": {"can_be_recommended": true, "dynamic_refresh": true},
++ "name": "MainPolicy",
++ "owners": ["foo@bar.com"],
++ "schema": {
++ "properties": {
++ "default_launch_container": {
++ "enum": [
++ "tab",
++ "window"
++ ],
++ "type": "string"
++ },
++ "users_number": {
++ "description": "%s",
++ "type": "integer"
++ }
++ },
++ "type": "object"
++ },
++ "supported_on": ["chrome_os:29-"],
++ "tags": [],
++ "type": "main"
++ }
++ ],
++ "policy_atomic_group_definitions": [
++ ],
++ "messages": {
++ "message_string_id": {
++ "text": "%s"
++ }
++ }
++
++}""" % (caption_translation, schema_key_description_translation,
++ message_translation)
++ self.assertEqual(expected, output)
++
++
++class DummyOutput(object):
++
++ def __init__(self, type, language):
++ self.type = type
++ self.language = language
++
++ def GetType(self):
++ return self.type
++
++ def GetLanguage(self):
++ return self.language
++
++ def GetOutputFilename(self):
++ return 'hello.gif'
+diff --git a/tools/grit/grit/format/rc.py b/tools/grit/grit/format/rc.py
+new file mode 100644
+index 0000000000..ed32bb809e
+--- /dev/null
++++ b/tools/grit/grit/format/rc.py
+@@ -0,0 +1,474 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Support for formatting an RC file for compilation.
++'''
++
++from __future__ import print_function
++
++import os
++import re
++from functools import partial
++
++import six
++
++from grit import util
++from grit.node import misc
++
++
++def Format(root, lang='en', output_dir='.'):
++ from grit.node import empty, include, message, structure
++
++ yield _FormatHeader(root, lang, output_dir)
++
++ for item in root.ActiveDescendants():
++ if isinstance(item, empty.MessagesNode):
++ # Write one STRINGTABLE per <messages> container.
++ # This is hacky: it iterates over the children twice.
++ yield 'STRINGTABLE\nBEGIN\n'
++ for subitem in item.ActiveDescendants():
++ if isinstance(subitem, message.MessageNode):
++ with subitem:
++ yield FormatMessage(subitem, lang)
++ yield 'END\n\n'
++ elif isinstance(item, include.IncludeNode):
++ with item:
++ yield FormatInclude(item, lang, output_dir)
++ elif isinstance(item, structure.StructureNode):
++ with item:
++ yield FormatStructure(item, lang, output_dir)
++
++
++'''
++This dictionary defines the language charset pair lookup table, which is used
++for replacing the GRIT expand variables for language info in Product Version
++resource. The key is the language ISO country code, and the value
++is the language and character-set pair, which is a hexadecimal string
++consisting of the concatenation of the language and character-set identifiers.
++The first 4 digit of the value is the hex value of LCID, the remaining
++4 digits is the hex value of character-set id(code page)of the language.
++
++LCID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
++Codepage resource: http://www.science.co.il/language/locale-codes.asp
++
++We have defined three GRIT expand_variables to be used in the version resource
++file to set the language info. Here is an example how they should be used in
++the VS_VERSION_INFO section of the resource file to allow GRIT to localize
++the language info correctly according to product locale.
++
++VS_VERSION_INFO VERSIONINFO
++...
++BEGIN
++ BLOCK "StringFileInfo"
++ BEGIN
++ BLOCK "[GRITVERLANGCHARSETHEX]"
++ BEGIN
++ ...
++ END
++ END
++ BLOCK "VarFileInfo"
++ BEGIN
++ VALUE "Translation", [GRITVERLANGID], [GRITVERCHARSETID]
++ END
++END
++
++'''
++
++_LANGUAGE_CHARSET_PAIR = {
++ # Language neutral LCID, unicode(1200) code page.
++ 'neutral' : '000004b0',
++ # LANG_USER_DEFAULT LCID, unicode(1200) code page.
++ 'userdefault' : '040004b0',
++ 'ar' : '040104e8',
++ 'fi' : '040b04e4',
++ 'ko' : '041203b5',
++ 'es' : '0c0a04e4',
++ 'bg' : '040204e3',
++ # No codepage for filipino, use unicode(1200).
++ 'fil' : '046404e4',
++ 'fr' : '040c04e4',
++ 'lv' : '042604e9',
++ 'sv' : '041d04e4',
++ 'ca' : '040304e4',
++ 'de' : '040704e4',
++ 'lt' : '042704e9',
++ # Do not use! This is only around for backwards
++ # compatibility and will be removed - use fil instead
++ 'tl' : '0c0004b0',
++ 'zh-CN' : '080403a8',
++ 'zh-TW' : '040403b6',
++ 'zh-HK' : '0c0403b6',
++ 'el' : '040804e5',
++ 'no' : '001404e4',
++ 'nb' : '041404e4',
++ 'nn' : '081404e4',
++ 'th' : '041e036a',
++ 'he' : '040d04e7',
++ 'iw' : '040d04e7',
++ 'pl' : '041504e2',
++ 'tr' : '041f04e6',
++ 'hr' : '041a04e4',
++ # No codepage for Hindi, use unicode(1200).
++ 'hi' : '043904b0',
++ 'pt-PT' : '081604e4',
++ 'pt-BR' : '041604e4',
++ 'uk' : '042204e3',
++ 'cs' : '040504e2',
++ 'hu' : '040e04e2',
++ 'ro' : '041804e2',
++ # No codepage for Urdu, use unicode(1200).
++ 'ur' : '042004b0',
++ 'da' : '040604e4',
++ 'is' : '040f04e4',
++ 'ru' : '041904e3',
++ 'vi' : '042a04ea',
++ 'nl' : '041304e4',
++ 'id' : '042104e4',
++ 'sr' : '081a04e2',
++ 'en-GB' : '0809040e',
++ 'it' : '041004e4',
++ 'sk' : '041b04e2',
++ 'et' : '042504e9',
++ 'ja' : '041103a4',
++ 'sl' : '042404e2',
++ 'en' : '040904b0',
++ # LCID for Mexico; Windows does not support L.A. LCID.
++ 'es-419' : '080a04e4',
++ # No codepage for Bengali, use unicode(1200).
++ 'bn' : '044504b0',
++ 'fa' : '042904e8',
++ # No codepage for Gujarati, use unicode(1200).
++ 'gu' : '044704b0',
++ # No codepage for Kannada, use unicode(1200).
++ 'kn' : '044b04b0',
++ # Malay (Malaysia) [ms-MY]
++ 'ms' : '043e04e4',
++ # No codepage for Malayalam, use unicode(1200).
++ 'ml' : '044c04b0',
++ # No codepage for Marathi, use unicode(1200).
++ 'mr' : '044e04b0',
++ # No codepage for Oriya , use unicode(1200).
++ 'or' : '044804b0',
++ # No codepage for Tamil, use unicode(1200).
++ 'ta' : '044904b0',
++ # No codepage for Telugu, use unicode(1200).
++ 'te' : '044a04b0',
++ # No codepage for Amharic, use unicode(1200). >= Vista.
++ 'am' : '045e04b0',
++ 'sw' : '044104e4',
++ 'af' : '043604e4',
++ 'eu' : '042d04e4',
++ 'fr-CA' : '0c0c04e4',
++ 'gl' : '045604e4',
++ # No codepage for Zulu, use unicode(1200).
++ 'zu' : '043504b0',
++ 'fake-bidi' : '040d04e7',
++}
++
++# Language ID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
++#
++# There is no appropriate sublang for Spanish (Latin America) [es-419], so we
++# use Mexico. SUBLANG_DEFAULT would incorrectly map to Spain. Unlike other
++# Latin American countries, Mexican Spanish is supported by VERSIONINFO:
++# http://msdn.microsoft.com/en-us/library/aa381058.aspx
++
++_LANGUAGE_DIRECTIVE_PAIR = {
++ 'neutral' : 'LANG_NEUTRAL, SUBLANG_NEUTRAL',
++ 'userdefault' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
++ 'ar' : 'LANG_ARABIC, SUBLANG_DEFAULT',
++ 'fi' : 'LANG_FINNISH, SUBLANG_DEFAULT',
++ 'ko' : 'LANG_KOREAN, SUBLANG_KOREAN',
++ 'es' : 'LANG_SPANISH, SUBLANG_SPANISH_MODERN',
++ 'bg' : 'LANG_BULGARIAN, SUBLANG_DEFAULT',
++ # LANG_FILIPINO (100) not in VC 7 winnt.h.
++ 'fil' : '100, SUBLANG_DEFAULT',
++ 'fr' : 'LANG_FRENCH, SUBLANG_FRENCH',
++ 'lv' : 'LANG_LATVIAN, SUBLANG_DEFAULT',
++ 'sv' : 'LANG_SWEDISH, SUBLANG_SWEDISH',
++ 'ca' : 'LANG_CATALAN, SUBLANG_DEFAULT',
++ 'de' : 'LANG_GERMAN, SUBLANG_GERMAN',
++ 'lt' : 'LANG_LITHUANIAN, SUBLANG_LITHUANIAN',
++ # Do not use! See above.
++ 'tl' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
++ 'zh-CN' : 'LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED',
++ 'zh-TW' : 'LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL',
++ 'zh-HK' : 'LANG_CHINESE, SUBLANG_CHINESE_HONGKONG',
++ 'el' : 'LANG_GREEK, SUBLANG_DEFAULT',
++ 'no' : 'LANG_NORWEGIAN, SUBLANG_DEFAULT',
++ 'nb' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL',
++ 'nn' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK',
++ 'th' : 'LANG_THAI, SUBLANG_DEFAULT',
++ 'he' : 'LANG_HEBREW, SUBLANG_DEFAULT',
++ 'iw' : 'LANG_HEBREW, SUBLANG_DEFAULT',
++ 'pl' : 'LANG_POLISH, SUBLANG_DEFAULT',
++ 'tr' : 'LANG_TURKISH, SUBLANG_DEFAULT',
++ 'hr' : 'LANG_CROATIAN, SUBLANG_DEFAULT',
++ 'hi' : 'LANG_HINDI, SUBLANG_DEFAULT',
++ 'pt-PT' : 'LANG_PORTUGUESE, SUBLANG_PORTUGUESE',
++ 'pt-BR' : 'LANG_PORTUGUESE, SUBLANG_DEFAULT',
++ 'uk' : 'LANG_UKRAINIAN, SUBLANG_DEFAULT',
++ 'cs' : 'LANG_CZECH, SUBLANG_DEFAULT',
++ 'hu' : 'LANG_HUNGARIAN, SUBLANG_DEFAULT',
++ 'ro' : 'LANG_ROMANIAN, SUBLANG_DEFAULT',
++ 'ur' : 'LANG_URDU, SUBLANG_DEFAULT',
++ 'da' : 'LANG_DANISH, SUBLANG_DEFAULT',
++ 'is' : 'LANG_ICELANDIC, SUBLANG_DEFAULT',
++ 'ru' : 'LANG_RUSSIAN, SUBLANG_DEFAULT',
++ 'vi' : 'LANG_VIETNAMESE, SUBLANG_DEFAULT',
++ 'nl' : 'LANG_DUTCH, SUBLANG_DEFAULT',
++ 'id' : 'LANG_INDONESIAN, SUBLANG_DEFAULT',
++ 'sr' : 'LANG_SERBIAN, SUBLANG_SERBIAN_LATIN',
++ 'en-GB' : 'LANG_ENGLISH, SUBLANG_ENGLISH_UK',
++ 'it' : 'LANG_ITALIAN, SUBLANG_DEFAULT',
++ 'sk' : 'LANG_SLOVAK, SUBLANG_DEFAULT',
++ 'et' : 'LANG_ESTONIAN, SUBLANG_DEFAULT',
++ 'ja' : 'LANG_JAPANESE, SUBLANG_DEFAULT',
++ 'sl' : 'LANG_SLOVENIAN, SUBLANG_DEFAULT',
++ 'en' : 'LANG_ENGLISH, SUBLANG_ENGLISH_US',
++ # No L.A. sublang exists.
++ 'es-419' : 'LANG_SPANISH, SUBLANG_SPANISH_MEXICAN',
++ 'bn' : 'LANG_BENGALI, SUBLANG_DEFAULT',
++ 'fa' : 'LANG_PERSIAN, SUBLANG_DEFAULT',
++ 'gu' : 'LANG_GUJARATI, SUBLANG_DEFAULT',
++ 'kn' : 'LANG_KANNADA, SUBLANG_DEFAULT',
++ 'ms' : 'LANG_MALAY, SUBLANG_DEFAULT',
++ 'ml' : 'LANG_MALAYALAM, SUBLANG_DEFAULT',
++ 'mr' : 'LANG_MARATHI, SUBLANG_DEFAULT',
++ 'or' : 'LANG_ORIYA, SUBLANG_DEFAULT',
++ 'ta' : 'LANG_TAMIL, SUBLANG_DEFAULT',
++ 'te' : 'LANG_TELUGU, SUBLANG_DEFAULT',
++ 'am' : 'LANG_AMHARIC, SUBLANG_DEFAULT',
++ 'sw' : 'LANG_SWAHILI, SUBLANG_DEFAULT',
++ 'af' : 'LANG_AFRIKAANS, SUBLANG_DEFAULT',
++ 'eu' : 'LANG_BASQUE, SUBLANG_DEFAULT',
++ 'fr-CA' : 'LANG_FRENCH, SUBLANG_FRENCH_CANADIAN',
++ 'gl' : 'LANG_GALICIAN, SUBLANG_DEFAULT',
++ 'zu' : 'LANG_ZULU, SUBLANG_DEFAULT',
++ 'pa' : 'LANG_PUNJABI, SUBLANG_PUNJABI_INDIA',
++ 'sa' : 'LANG_SANSKRIT, SUBLANG_SANSKRIT_INDIA',
++ 'si' : 'LANG_SINHALESE, SUBLANG_SINHALESE_SRI_LANKA',
++ 'ne' : 'LANG_NEPALI, SUBLANG_NEPALI_NEPAL',
++ 'ti' : 'LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ERITREA',
++ 'fake-bidi' : 'LANG_HEBREW, SUBLANG_DEFAULT',
++}
++
++# A note on 'no-specific-language' in the following few functions:
++# Some build systems may wish to call GRIT to scan for dependencies in
++# a language-agnostic way, and can then specify this fake language as
++# the output context. It should never be used when output is actually
++# being generated.
++
++def GetLangCharsetPair(language):
++ if language in _LANGUAGE_CHARSET_PAIR:
++ return _LANGUAGE_CHARSET_PAIR[language]
++ if language != 'no-specific-language':
++ print('Warning:GetLangCharsetPair() found undefined language %s' % language)
++ return ''
++
++def GetLangDirectivePair(language):
++ if language in _LANGUAGE_DIRECTIVE_PAIR:
++ return _LANGUAGE_DIRECTIVE_PAIR[language]
++
++ # We don't check for 'no-specific-language' here because this
++ # function should only get called when output is being formatted,
++ # and at that point we would not want to get
++ # 'no-specific-language' passed as the language.
++ print('Warning:GetLangDirectivePair() found undefined language %s' % language)
++ return 'unknown language: see tools/grit/format/rc.py'
++
++def GetLangIdHex(language):
++ if language in _LANGUAGE_CHARSET_PAIR:
++ langcharset = _LANGUAGE_CHARSET_PAIR[language]
++ lang_id = '0x' + langcharset[0:4]
++ return lang_id
++ if language != 'no-specific-language':
++ print('Warning:GetLangIdHex() found undefined language %s' % language)
++ return ''
++
++
++def GetCharsetIdDecimal(language):
++ if language in _LANGUAGE_CHARSET_PAIR:
++ langcharset = _LANGUAGE_CHARSET_PAIR[language]
++ charset_decimal = int(langcharset[4:], 16)
++ return str(charset_decimal)
++ if language != 'no-specific-language':
++ print('Warning:GetCharsetIdDecimal() found undefined language %s' % language)
++ return ''
++
++
++def GetUnifiedLangCode(language) :
++ r = re.compile('([a-z]{1,2})_([a-z]{1,2})')
++ if r.match(language) :
++ underscore = language.find('_')
++ return language[0:underscore] + '-' + language[underscore + 1:].upper()
++ return language
++
++
++def RcSubstitutions(substituter, lang):
++ '''Add language-based substitutions for Rc files to the substitutor.'''
++ unified_lang_code = GetUnifiedLangCode(lang)
++ substituter.AddSubstitutions({
++ 'GRITVERLANGCHARSETHEX': GetLangCharsetPair(unified_lang_code),
++ 'GRITVERLANGID': GetLangIdHex(unified_lang_code),
++ 'GRITVERCHARSETID': GetCharsetIdDecimal(unified_lang_code)})
++
++
++def _FormatHeader(root, lang, output_dir):
++ '''Returns the required preamble for RC files.'''
++ assert isinstance(lang, six.string_types)
++ assert isinstance(root, misc.GritNode)
++ # Find the location of the resource header file, so that we can include
++ # it.
++ resource_header = 'resource.h' # fall back to this
++ language_directive = ''
++ for output in root.GetOutputFiles():
++ if output.attrs['type'] == 'rc_header':
++ resource_header = os.path.abspath(output.GetOutputFilename())
++ resource_header = util.MakeRelativePath(output_dir, resource_header)
++ if output.attrs['lang'] != lang:
++ continue
++ if output.attrs['language_section'] == '':
++ # If no language_section is requested, no directive is added
++ # (Used when the generated rc will be included from another rc
++ # file that will have the appropriate language directive)
++ language_directive = ''
++ elif output.attrs['language_section'] == 'neutral':
++ # If a neutral language section is requested (default), add a
++ # neutral language directive
++ language_directive = 'LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL'
++ elif output.attrs['language_section'] == 'lang':
++ language_directive = 'LANGUAGE %s' % GetLangDirectivePair(lang)
++ resource_header = resource_header.replace('\\', '\\\\')
++ return '''// This file is automatically generated by GRIT. Do not edit.
++
++#include "%s"
++#include <winresrc.h>
++#ifdef IDC_STATIC
++#undef IDC_STATIC
++#endif
++#define IDC_STATIC (-1)
++
++%s
++
++
++''' % (resource_header, language_directive)
++# end _FormatHeader() function
++
++
++def FormatMessage(item, lang):
++ '''Returns a single message of a string table.'''
++ message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
++ # Escape quotation marks (RC format uses doubling-up
++ message = message.replace('"', '""')
++ # Replace linebreaks with a \n escape
++ message = util.LINEBREAKS.sub(r'\\n', message)
++ if hasattr(item.GetRoot(), 'GetSubstituter'):
++ substituter = item.GetRoot().GetSubstituter()
++ message = substituter.Substitute(message)
++
++ name_attr = item.GetTextualIds()[0]
++
++ return ' %-15s "%s"\n' % (name_attr, message)
++
++
++def _FormatSection(item, lang, output_dir):
++ '''Writes out an .rc file section.'''
++ assert isinstance(lang, six.string_types)
++ from grit.node import structure
++ assert isinstance(item, structure.StructureNode)
++
++ if item.IsExcludedFromRc():
++ return ''
++
++ text = item.gatherer.Translate(
++ lang, skeleton_gatherer=item.GetSkeletonGatherer(),
++ pseudo_if_not_available=item.PseudoIsAllowed(),
++ fallback_to_english=item.ShouldFallbackToEnglish()) + '\n\n'
++
++ # Replace the language expand_variables in version rc info.
++ if item.ExpandVariables() and hasattr(item.GetRoot(), 'GetSubstituter'):
++ substituter = item.GetRoot().GetSubstituter()
++ text = substituter.Substitute(text)
++ return text
++
++
++def FormatInclude(item, lang, output_dir, type=None, process_html=False):
++ '''Formats an item that is included in an .rc file (e.g. an ICON).
++
++ Args:
++ item: an IncludeNode or StructureNode
++ lang, output_dir: standard formatter parameters
++ type: .rc file resource type, e.g. 'ICON' (ignored unless item is a
++ StructureNode)
++ process_html: False/True (ignored unless item is a StructureNode)
++ '''
++ assert isinstance(lang, six.string_types)
++ from grit.node import structure
++ from grit.node import include
++ assert isinstance(item, (structure.StructureNode, include.IncludeNode))
++
++ if isinstance(item, include.IncludeNode):
++ type = item.attrs['type'].upper()
++ process_html = item.attrs['flattenhtml'] == 'true'
++ filename_only = item.attrs['filenameonly'] == 'true'
++ relative_path = item.attrs['relativepath'] == 'true'
++ else:
++ assert (isinstance(item, structure.StructureNode) and item.attrs['type'] in
++ ['admin_template', 'chrome_html', 'chrome_scaled_image',
++ 'tr_html', 'txt'])
++ filename_only = False
++ relative_path = False
++
++ # By default, we use relative pathnames to included resources so that
++ # sharing the resulting .rc files is possible.
++ #
++ # The FileForLanguage() Function has the side effect of generating the file
++ # if needed (e.g. if it is an HTML file include).
++ file_for_lang = item.FileForLanguage(lang, output_dir)
++ if file_for_lang is None:
++ return ''
++
++ filename = os.path.abspath(file_for_lang)
++ if process_html:
++ filename = item.Process(output_dir)
++ elif filename_only:
++ filename = os.path.basename(filename)
++ elif relative_path:
++ filename = util.MakeRelativePath(output_dir, filename)
++
++ filename = filename.replace('\\', '\\\\') # escape for the RC format
++
++ if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc():
++ return ''
++
++ name = item.attrs['name']
++ item_id = item.GetRoot().GetIdMap()[name]
++ return '// ID: %d\n%-18s %-18s "%s"\n' % (item_id, name, type, filename)
++
++
++def _DoNotFormat(item, lang, output_dir):
++ return ''
++
++
++# Formatter instance to use for each type attribute
++# when formatting Structure nodes.
++_STRUCTURE_FORMATTERS = {
++ 'accelerators' : _FormatSection,
++ 'dialog' : _FormatSection,
++ 'menu' : _FormatSection,
++ 'rcdata' : _FormatSection,
++ 'version' : _FormatSection,
++ 'admin_template' : partial(FormatInclude, type='ADM'),
++ 'chrome_html' : partial(FormatInclude, type='BINDATA',
++ process_html=True),
++ 'chrome_scaled_image' : partial(FormatInclude, type='BINDATA'),
++ 'tr_html' : partial(FormatInclude, type='HTML'),
++ 'txt' : partial(FormatInclude, type='TXT'),
++ 'policy_template_metafile': _DoNotFormat,
++}
++
++
++def FormatStructure(item, lang, output_dir):
++ formatter = _STRUCTURE_FORMATTERS[item.attrs['type']]
++ return formatter(item, lang, output_dir)
+diff --git a/tools/grit/grit/format/rc_header.py b/tools/grit/grit/format/rc_header.py
+new file mode 100644
+index 0000000000..ea2c217f53
+--- /dev/null
++++ b/tools/grit/grit/format/rc_header.py
+@@ -0,0 +1,48 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Item formatters for RC headers.
++'''
++
++from __future__ import print_function
++
++
++def Format(root, lang='en', output_dir='.'):
++ yield '''\
++// This file is automatically generated by GRIT. Do not edit.
++
++#pragma once
++'''
++ # Check for emit nodes under the rc_header. If any emit node
++ # is present, we assume it means the GRD file wants to override
++ # the default header, with no includes.
++ default_includes = ['#include <atlres.h>', '']
++ emit_lines = []
++ for output_node in root.GetOutputFiles():
++ if output_node.GetType() == 'rc_header':
++ for child in output_node.children:
++ if child.name == 'emit' and child.attrs['emit_type'] == 'prepend':
++ emit_lines.append(child.GetCdata())
++ for line in emit_lines or default_includes:
++ yield line + '\n'
++ if root.IsWhitelistSupportEnabled():
++ yield '#include "ui/base/resource/whitelist.h"\n'
++ for line in FormatDefines(root):
++ yield line
++
++
++def FormatDefines(root):
++ '''Yields #define SYMBOL 1234 lines.
++
++ Args:
++ root: A GritNode.
++ '''
++ tids = root.GetIdMap()
++ rc_header_format = '#define {0} {1}\n'
++ if root.IsWhitelistSupportEnabled():
++ rc_header_format = '#define {0} (::ui::WhitelistedResource<{1}>(), {1})\n'
++ for item in root.ActiveDescendants():
++ with item:
++ for tid in item.GetTextualIds():
++ yield rc_header_format.format(tid, tids[tid])
+diff --git a/tools/grit/grit/format/rc_header_unittest.py b/tools/grit/grit/format/rc_header_unittest.py
+new file mode 100644
+index 0000000000..eed4d70a99
+--- /dev/null
++++ b/tools/grit/grit/format/rc_header_unittest.py
+@@ -0,0 +1,138 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for the rc_header formatter'''
++
++# GRD samples exceed the 80 character limit.
++# pylint: disable-msg=C6310
++
++from __future__ import print_function
++
++import os
++import sys
++import unittest
++
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++from grit import util
++from grit.format import rc_header
++
++
++class RcHeaderFormatterUnittest(unittest.TestCase):
++ def FormatAll(self, grd):
++ output = rc_header.FormatDefines(grd)
++ return ''.join(output).replace(' ', '')
++
++ def testFormatter(self):
++ grd = util.ParseGrdForUnittest('''
++ <includes first_id="300" comment="bingo">
++ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
++ </includes>
++ <messages first_id="10000">
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ <message name="IDS_BONGO">
++ Bongo!
++ </message>
++ </messages>
++ <structures>
++ <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc" />
++ <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc" />
++ </structures>''')
++ output = self.FormatAll(grd)
++ self.failUnless(output.count('IDS_GREETING10000'))
++ self.failUnless(output.count('ID_LOGO300'))
++
++ def testOnlyDefineResourcesThatSatisfyOutputCondition(self):
++ grd = util.ParseGrdForUnittest('''
++ <includes first_id="300" comment="bingo">
++ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
++ </includes>
++ <messages first_id="10000">
++ <message name="IDS_FIRSTPRESENTSTRING" desc="Present in .rc file.">
++ I will appear in the .rc file.
++ </message>
++ <if expr="False"> <!--Do not include in the .rc files until used.-->
++ <message name="IDS_MISSINGSTRING" desc="Not present in .rc file.">
++ I will not appear in the .rc file.
++ </message>
++ </if>
++ <if expr="lang != 'es'">
++ <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
++ Hello.
++ </message>
++ </if>
++ <if expr="lang == 'es'">
++ <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
++ Hola.
++ </message>
++ </if>
++ <message name="IDS_THIRDPRESENTSTRING" desc="Present in .rc file.">
++ I will also appear in the .rc file.
++ </message>
++ </messages>''')
++ output = self.FormatAll(grd)
++ self.failUnless(output.count('IDS_FIRSTPRESENTSTRING10000'))
++ self.failIf(output.count('IDS_MISSINGSTRING'))
++ self.failUnless(output.count('IDS_LANGUAGESPECIFICSTRING10002'))
++ self.failUnless(output.count('IDS_THIRDPRESENTSTRING10003'))
++
++ def testEmit(self):
++ grd = util.ParseGrdForUnittest('''
++ <outputs>
++ <output type="rc_all" filename="dummy">
++ <emit emit_type="prepend">Wrong</emit>
++ </output>
++ <if expr="False">
++ <output type="rc_header" filename="dummy">
++ <emit emit_type="prepend">No</emit>
++ </output>
++ </if>
++ <output type="rc_header" filename="dummy">
++ <emit emit_type="append">Error</emit>
++ </output>
++ <output type="rc_header" filename="dummy">
++ <emit emit_type="prepend">Bingo</emit>
++ </output>
++ </outputs>''')
++ output = ''.join(rc_header.Format(grd, 'en', '.'))
++ output = util.StripBlankLinesAndComments(output)
++ self.assertEqual('#pragma once\nBingo', output)
++
++ def testRcHeaderFormat(self):
++ grd = util.ParseGrdForUnittest('''
++ <includes first_id="300" comment="bingo">
++ <include type="gif" name="IDR_LOGO" file="images/logo.gif" />
++ </includes>
++ <messages first_id="10000">
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ <message name="IDS_BONGO">
++ Bongo!
++ </message>
++ </messages>''')
++
++ # Using the default settings.
++ output = rc_header.FormatDefines(grd)
++ self.assertEqual(('#define IDR_LOGO 300\n'
++ '#define IDS_GREETING 10000\n'
++ '#define IDS_BONGO 10001\n'), ''.join(output))
++
++ # Using resource whitelist support.
++ grd.SetWhitelistSupportEnabled(True)
++ output = rc_header.FormatDefines(grd)
++ self.assertEqual(('#define IDR_LOGO '
++ '(::ui::WhitelistedResource<300>(), 300)\n'
++ '#define IDS_GREETING '
++ '(::ui::WhitelistedResource<10000>(), 10000)\n'
++ '#define IDS_BONGO '
++ '(::ui::WhitelistedResource<10001>(), 10001)\n'),
++ ''.join(output))
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/rc_unittest.py b/tools/grit/grit/format/rc_unittest.py
+new file mode 100644
+index 0000000000..d23f063596
+--- /dev/null
++++ b/tools/grit/grit/format/rc_unittest.py
+@@ -0,0 +1,415 @@
++#!/usr/bin/env python
++# Copyright (c) 2011 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.format.rc'''
++
++from __future__ import print_function
++
++import os
++import re
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import tempfile
++import unittest
++
++from six import StringIO
++
++from grit import grd_reader
++from grit import util
++from grit.node import structure
++from grit.tool import build
++
++
++_PREAMBLE = '''\
++#include "resource.h"
++#include <winresrc.h>
++#ifdef IDC_STATIC
++#undef IDC_STATIC
++#endif
++#define IDC_STATIC (-1)
++'''
++
++
++class DummyOutput(object):
++ def __init__(self, type, language, file = 'hello.gif'):
++ self.type = type
++ self.language = language
++ self.file = file
++
++ def GetType(self):
++ return self.type
++
++ def GetLanguage(self):
++ return self.language
++
++ def GetOutputFilename(self):
++ return self.file
++
++
++class FormatRcUnittest(unittest.TestCase):
++ def testMessages(self):
++ root = util.ParseGrdForUnittest("""
++ <messages>
++ <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ <message name="BONGO" desc="Flippo nippo">
++ Howdie "Mr. Elephant", how are you doing? '''
++ </message>
++ <message name="IDS_WITH_LINEBREAKS">
++Good day sir,
++I am a bee
++Sting sting
++ </message>
++ </messages>
++ """)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++ self.assertEqual(_PREAMBLE + u'''\
++STRINGTABLE
++BEGIN
++ IDS_BTN_GO "Go!"
++ IDS_GREETING "Hello %s, how are you doing today?"
++ BONGO "Howdie ""Mr. Elephant"", how are you doing? "
++ IDS_WITH_LINEBREAKS "Good day sir,\\nI am a bee\\nSting sting"
++END''', output)
++
++ def testRcSection(self):
++ root = util.ParseGrdForUnittest(r'''
++ <structures>
++ <structure type="menu" name="IDC_KLONKMENU" file="grit\testdata\klonk.rc" encoding="utf-16" />
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\testdata\klonk.rc" encoding="utf-16" />
++ <structure type="version" name="VS_VERSION_INFO" file="grit\testdata\klonk.rc" encoding="utf-16" />
++ </structures>''')
++ root.SetOutputLanguage('en')
++ root.RunGatherers()
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++ expected = _PREAMBLE + u'''\
++IDC_KLONKMENU MENU
++BEGIN
++ POPUP "&File"
++ BEGIN
++ MENUITEM "E&xit", IDM_EXIT
++ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
++ POPUP "gonk"
++ BEGIN
++ MENUITEM "Klonk && is [good]", ID_GONK_KLONKIS
++ END
++ END
++ POPUP "&Help"
++ BEGIN
++ MENUITEM "&About ...", IDM_ABOUT
++ END
++END
++
++IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "About"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
++ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
++ SS_NOPREFIX
++ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
++ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
++ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
++ BS_AUTORADIOBUTTON,46,51,84,10
++END
++
++VS_VERSION_INFO VERSIONINFO
++ FILEVERSION 1,0,0,1
++ PRODUCTVERSION 1,0,0,1
++ FILEFLAGSMASK 0x17L
++#ifdef _DEBUG
++ FILEFLAGS 0x1L
++#else
++ FILEFLAGS 0x0L
++#endif
++ FILEOS 0x4L
++ FILETYPE 0x1L
++ FILESUBTYPE 0x0L
++BEGIN
++ BLOCK "StringFileInfo"
++ BEGIN
++ BLOCK "040904b0"
++ BEGIN
++ VALUE "FileDescription", "klonk Application"
++ VALUE "FileVersion", "1, 0, 0, 1"
++ VALUE "InternalName", "klonk"
++ VALUE "LegalCopyright", "Copyright (C) 2005"
++ VALUE "OriginalFilename", "klonk.exe"
++ VALUE "ProductName", " klonk Application"
++ VALUE "ProductVersion", "1, 0, 0, 1"
++ END
++ END
++ BLOCK "VarFileInfo"
++ BEGIN
++ VALUE "Translation", 0x409, 1200
++ END
++END'''.strip()
++ for expected_line, output_line in zip(expected.split(), output.split()):
++ self.assertEqual(expected_line, output_line)
++
++ def testRcIncludeStructure(self):
++ root = util.ParseGrdForUnittest('''
++ <structures>
++ <structure type="tr_html" name="IDR_HTML" file="bingo.html"/>
++ <structure type="tr_html" name="IDR_HTML2" file="bingo2.html"/>
++ </structures>''', base_dir = '/temp')
++ # We do not run gatherers as it is not needed and wouldn't find the file
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++ expected = (_PREAMBLE +
++ u'IDR_HTML HTML "%s"\n'
++ u'IDR_HTML2 HTML "%s"'
++ % (util.normpath('/temp/bingo.html').replace('\\', '\\\\'),
++ util.normpath('/temp/bingo2.html').replace('\\', '\\\\')))
++ # hackety hack to work on win32&lin
++ output = re.sub(r'"[c-zC-Z]:', '"', output)
++ self.assertEqual(expected, output)
++
++ def testRcIncludeFile(self):
++ root = util.ParseGrdForUnittest('''
++ <includes>
++ <include type="TXT" name="TEXT_ONE" file="bingo.txt"/>
++ <include type="TXT" name="TEXT_TWO" file="bingo2.txt" filenameonly="true" />
++ </includes>''', base_dir = '/temp')
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++ expected = (_PREAMBLE +
++ u'TEXT_ONE TXT "%s"\n'
++ u'TEXT_TWO TXT "%s"'
++ % (util.normpath('/temp/bingo.txt').replace('\\', '\\\\'),
++ 'bingo2.txt'))
++ # hackety hack to work on win32&lin
++ output = re.sub(r'"[c-zC-Z]:', '"', output)
++ self.assertEqual(expected, output)
++
++ def testRcIncludeFlattenedHtmlFile(self):
++ input_file = util.PathFromRoot('grit/testdata/include_test.html')
++ output_file = '%s/HTML_FILE1_include_test.html' % tempfile.gettempdir()
++ root = util.ParseGrdForUnittest('''
++ <includes>
++ <include name="HTML_FILE1" flattenhtml="true" file="%s" type="BINDATA" />
++ </includes>''' % input_file)
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
++ buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++
++ expected = (_PREAMBLE +
++ u'HTML_FILE1 BINDATA "HTML_FILE1_include_test.html"')
++ # hackety hack to work on win32&lin
++ output = re.sub(r'"[c-zC-Z]:', '"', output)
++ self.assertEqual(expected, output)
++
++ file_contents = util.ReadFile(output_file, 'utf-8')
++
++ # Check for the content added by the <include> tag.
++ self.failUnless(file_contents.find('Hello Include!') != -1)
++ # Check for the content that was removed by if tag.
++ self.failUnless(file_contents.find('should be removed') == -1)
++ # Check for the content that was kept in place by if.
++ self.failUnless(file_contents.find('should be kept') != -1)
++ self.failUnless(file_contents.find('in the middle...') != -1)
++ self.failUnless(file_contents.find('at the end...') != -1)
++ # Check for nested content that was kept
++ self.failUnless(file_contents.find('nested true should be kept') != -1)
++ self.failUnless(file_contents.find('silbing true should be kept') != -1)
++ # Check for removed "<if>" and "</if>" tags.
++ self.failUnless(file_contents.find('<if expr=') == -1)
++ self.failUnless(file_contents.find('</if>') == -1)
++ os.remove(output_file)
++
++ def testStructureNodeOutputfile(self):
++ input_file = util.PathFromRoot('grit/testdata/simple.html')
++ root = util.ParseGrdForUnittest('''
++ <structures>
++ <structure type="tr_html" name="IDR_HTML" file="%s" />
++ </structures>''' % input_file)
++ struct, = root.GetChildrenOfType(structure.StructureNode)
++ # We must run the gatherer since we'll be wanting the translation of the
++ # file. The file exists in the location pointed to.
++ root.SetOutputLanguage('en')
++ root.RunGatherers()
++
++ output_dir = tempfile.gettempdir()
++ en_file = struct.FileForLanguage('en', output_dir)
++ self.failUnless(en_file == input_file)
++ fr_file = struct.FileForLanguage('fr', output_dir)
++ self.failUnless(fr_file == os.path.join(output_dir, 'fr_simple.html'))
++
++ contents = util.ReadFile(fr_file, 'utf-8')
++
++ self.failUnless(contents.find('<p>') != -1) # should contain the markup
++ self.failUnless(contents.find('Hello!') == -1) # should be translated
++ os.remove(fr_file)
++
++ def testChromeHtmlNodeOutputfile(self):
++ input_file = util.PathFromRoot('grit/testdata/chrome_html.html')
++ output_file = '%s/HTML_FILE1_chrome_html.html' % tempfile.gettempdir()
++ root = util.ParseGrdForUnittest('''
++ <structures>
++ <structure type="chrome_html" name="HTML_FILE1" file="%s" flattenhtml="true" />
++ </structures>''' % input_file)
++ struct, = root.GetChildrenOfType(structure.StructureNode)
++ struct.gatherer.SetDefines({'scale_factors': '2x'})
++ # We must run the gatherers since we'll be wanting the chrome_html output.
++ # The file exists in the location pointed to.
++ root.SetOutputLanguage('en')
++ root.RunGatherers()
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
++ buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++ expected = (_PREAMBLE +
++ u'HTML_FILE1 BINDATA "HTML_FILE1_chrome_html.html"')
++ # hackety hack to work on win32&lin
++ output = re.sub(r'"[c-zC-Z]:', '"', output)
++ self.assertEqual(expected, output)
++
++ file_contents = util.ReadFile(output_file, 'utf-8')
++
++ # Check for the content added by the <include> tag.
++ self.failUnless(file_contents.find('Hello Include!') != -1)
++ # Check for inserted -webkit-image-set.
++ self.failUnless(file_contents.find('content: -webkit-image-set') != -1)
++ os.remove(output_file)
++
++ def testSubstitutionHtml(self):
++ input_file = util.PathFromRoot('grit/testdata/toolbar_about.html')
++ root = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="1" allow_pseudo="False">
++ <structures fallback_to_english="True">
++ <structure type="tr_html" name="IDR_HTML" file="%s" expand_variables="true"/>
++ </structures>
++ </release>
++ </grit>
++ ''' % input_file), util.PathFromRoot('.'))
++ root.SetOutputLanguage('ar')
++ # We must run the gatherers since we'll be wanting the translation of the
++ # file. The file exists in the location pointed to.
++ root.RunGatherers()
++
++ output_dir = tempfile.gettempdir()
++ struct, = root.GetChildrenOfType(structure.StructureNode)
++ ar_file = struct.FileForLanguage('ar', output_dir)
++ self.failUnless(ar_file == os.path.join(output_dir,
++ 'ar_toolbar_about.html'))
++
++ contents = util.ReadFile(ar_file, 'utf-8')
++
++ self.failUnless(contents.find('dir="RTL"') != -1)
++ os.remove(ar_file)
++
++ def testFallbackToEnglish(self):
++ root = util.ParseGrdForUnittest(r'''
++ <structures fallback_to_english="True">
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\testdata\klonk.rc" encoding="utf-16" />
++ </structures>''', base_dir=util.PathFromRoot('.'))
++ root.SetOutputLanguage('en')
++ root.RunGatherers()
++
++ buf = StringIO()
++ formatter = build.RcBuilder.ProcessNode(
++ root, DummyOutput('rc_all', 'bingobongo'), buf)
++ output = util.StripBlankLinesAndComments(buf.getvalue())
++ self.assertEqual(_PREAMBLE + '''\
++IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "About"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
++ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
++ SS_NOPREFIX
++ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
++ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
++ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
++ BS_AUTORADIOBUTTON,46,51,84,10
++END''', output)
++
++
++ def testSubstitutionRc(self):
++ root = grd_reader.Parse(StringIO(r'''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
++ base_dir=".">
++ <outputs>
++ <output lang="en" type="rc_all" filename="grit\testdata\klonk_resources.rc"/>
++ </outputs>
++ <release seq="1" allow_pseudo="False">
++ <structures>
++ <structure type="menu" name="IDC_KLONKMENU"
++ file="grit\testdata\klonk.rc" encoding="utf-16"
++ expand_variables="true" />
++ </structures>
++ <messages>
++ <message name="good" sub_variable="true">
++ excellent
++ </message>
++ </messages>
++ </release>
++ </grit>
++ '''), util.PathFromRoot('.'))
++ root.SetOutputLanguage('en')
++ root.RunGatherers()
++
++ buf = StringIO()
++ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
++ output = buf.getvalue()
++ self.assertEqual('''
++// This file is automatically generated by GRIT. Do not edit.
++
++#include "resource.h"
++#include <winresrc.h>
++#ifdef IDC_STATIC
++#undef IDC_STATIC
++#endif
++#define IDC_STATIC (-1)
++
++LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
++
++
++IDC_KLONKMENU MENU
++BEGIN
++ POPUP "&File"
++ BEGIN
++ MENUITEM "E&xit", IDM_EXIT
++ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
++ POPUP "gonk"
++ BEGIN
++ MENUITEM "Klonk && is excellent", ID_GONK_KLONKIS
++ END
++ END
++ POPUP "&Help"
++ BEGIN
++ MENUITEM "&About ...", IDM_ABOUT
++ END
++END
++
++STRINGTABLE
++BEGIN
++ good "excellent"
++END
++'''.strip(), output.strip())
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py
+new file mode 100644
+index 0000000000..95a8b83160
+--- /dev/null
++++ b/tools/grit/grit/format/resource_map.py
+@@ -0,0 +1,159 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''This file contains item formatters for resource_map_header and
++resource_map_source files. A resource map is a mapping between resource names
++(string) and the internal resource ID.'''
++
++from __future__ import print_function
++
++import os
++from functools import partial
++
++from grit import util
++
++
++def GetFormatter(type):
++ if type == 'resource_map_header':
++ return _FormatHeader
++ if type == 'resource_file_map_source':
++ return partial(_FormatSource, _GetItemPath)
++ if type == 'resource_map_source':
++ return partial(_FormatSource, _GetItemName)
++
++
++def GetMapName(root):
++ '''Get the name of the resource map based on the header file name. E.g.,
++ if our header filename is theme_resources.h, we name our resource map
++ kThemeResourcesMap.
++
++ |root| is the grd file root.'''
++ outputs = root.GetOutputFiles()
++ rc_header_file = None
++ for output in outputs:
++ if 'rc_header' == output.GetType():
++ rc_header_file = output.GetFilename()
++ if not rc_header_file:
++ raise Exception('unable to find resource header filename')
++ filename = os.path.splitext(os.path.split(rc_header_file)[1])[0]
++ filename = filename[0].upper() + filename[1:]
++ while True:
++ pos = filename.find('_')
++ if pos == -1 or pos >= len(filename):
++ break
++ filename = filename[:pos] + filename[pos + 1].upper() + filename[pos + 2:]
++ return 'k' + filename
++
++
++def _FormatHeader(root, lang='en', output_dir='.'):
++ '''Create the header file for the resource mapping. This file just declares
++ an array of name/value pairs.'''
++ return '''\
++// This file is automatically generated by GRIT. Do not edit.
++
++#include <stddef.h>
++
++#ifndef GRIT_RESOURCE_MAP_STRUCT_
++#define GRIT_RESOURCE_MAP_STRUCT_
++struct GritResourceMap {
++ const char* const name;
++ int value;
++};
++#endif // GRIT_RESOURCE_MAP_STRUCT_
++
++extern const GritResourceMap %(map_name)s[];
++extern const size_t %(map_name)sSize;
++''' % { 'map_name': GetMapName(root) }
++
++
++def _FormatSourceHeader(root, output_dir):
++ '''Create the header of the C++ source file for the resource mapping.'''
++ rc_header_file = None
++ map_header_file = None
++ for output in root.GetOutputFiles():
++ type = output.GetType()
++ if 'rc_header' == type:
++ rc_header_file = util.MakeRelativePath(output_dir,
++ output.GetOutputFilename())
++ elif 'resource_map_header' == type:
++ map_header_file = util.MakeRelativePath(output_dir,
++ output.GetOutputFilename())
++ if not rc_header_file or not map_header_file:
++ raise Exception('resource_map_source output type requires '
++ 'a resource_map_header and rc_header outputs')
++ return '''\
++// This file is automatically generated by GRIT. Do not edit.
++
++#include "%(map_header_file)s"
++
++#include <stddef.h>
++
++#include "base/stl_util.h"
++
++#include "%(rc_header_file)s"
++
++const GritResourceMap %(map_name)s[] = {
++''' % { 'map_header_file': map_header_file,
++ 'rc_header_file': rc_header_file,
++ 'map_name': GetMapName(root),
++ }
++
++
++def _FormatSourceFooter(root):
++ # Return the footer text.
++ return '''\
++};
++
++const size_t %(map_name)sSize = base::size(%(map_name)s);
++''' % { 'map_name': GetMapName(root) }
++
++
++def _FormatSource(get_key, root, lang, output_dir):
++ from grit.node import include, structure, message
++ id_map = root.GetIdMap()
++ yield _FormatSourceHeader(root, output_dir)
++ seen = set()
++ for item in root.ActiveDescendants():
++ if not item.IsResourceMapSource():
++ continue
++ key = get_key(item)
++ tid = item.attrs['name']
++ if tid not in id_map or key in seen:
++ continue
++ seen.add(key)
++ yield ' {"%s", %s},\n' % (key, tid)
++ yield _FormatSourceFooter(root)
++
++
++def _GetItemName(item):
++ return item.attrs['name']
++
++# Check if |path2| is a subpath of |path1|.
++def _IsSubpath(path1, path2):
++ path1_abs = os.path.abspath(path1)
++ path2_abs = os.path.abspath(path2)
++ common = os.path.commonprefix([path1_abs, path2_abs])
++ return path1_abs == common
++
++def _GetItemPath(item):
++ path = item.GetInputPath().replace("\\", "/")
++
++ # Handle the case where the file resides within the output folder,
++ # by expanding any variables as well as replacing the output folder name with
++ # a fixed string such that the key added to the map does not depend on a given
++ # developer's setup.
++ #
++ # For example this will convert the following path:
++ # ../../out/gchrome/${root_gen_dir}/ui/webui/resources/js/foo.js
++ # to:
++ # @out_folder@/gen/ui/webui/resources/js/foo.js
++
++ real_path = item.ToRealPath(item.GetInputPath())
++ if (item.attrs.get('use_base_dir', 'true') != 'true' and
++ _IsSubpath(os.path.curdir, real_path)):
++ path = os.path.join(
++ '@out_folder@', os.path.relpath(real_path)).replace("\\", "/")
++
++ assert '$' not in path, 'all variables should have been expanded'
++ return path
+diff --git a/tools/grit/grit/format/resource_map_unittest.py b/tools/grit/grit/format/resource_map_unittest.py
+new file mode 100644
+index 0000000000..3499b321ef
+--- /dev/null
++++ b/tools/grit/grit/format/resource_map_unittest.py
+@@ -0,0 +1,345 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.format.resource_map'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit import util
++from grit.format import resource_map
++
++
++class FormatResourceMapUnittest(unittest.TestCase):
++ def testFormatResourceMap(self):
++ grd = util.ParseGrdForUnittest('''
++ <outputs>
++ <output type="rc_header" filename="the_rc_header.h" />
++ <output type="resource_map_header"
++ filename="the_resource_map_header.h" />
++ </outputs>
++ <release seq="3">
++ <structures first_id="300">
++ <structure type="menu" name="IDC_KLONKMENU"
++ file="grit\\testdata\\klonk.rc" encoding="utf-16" />
++ </structures>
++ <includes first_id="10000">
++ <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
++ <if expr="False">
++ <include type="foo" file="def" name="IDS_MISSING" />
++ </if>
++ <if expr="lang != 'es'">
++ <include type="foo" file="ghi" name="IDS_LANGUAGESPECIFIC" />
++ </if>
++ <if expr="lang == 'es'">
++ <include type="foo" file="jkl" name="IDS_LANGUAGESPECIFIC" />
++ </if>
++ <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
++ <include type="foo" file="opq" name="IDS_FOURTHPRESENT"
++ skip_in_resource_map="true" />
++ </includes>
++ </release>''', run_gatherers=True)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include <stddef.h>
++#ifndef GRIT_RESOURCE_MAP_STRUCT_
++#define GRIT_RESOURCE_MAP_STRUCT_
++struct GritResourceMap {
++ const char* const name;
++ int value;
++};
++#endif // GRIT_RESOURCE_MAP_STRUCT_
++extern const GritResourceMap kTheRcHeader[];
++extern const size_t kTheRcHeaderSize;''', output)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include "the_resource_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"IDC_KLONKMENU", IDC_KLONKMENU},
++ {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
++ {"IDS_LANGUAGESPECIFIC", IDS_LANGUAGESPECIFIC},
++ {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include "the_resource_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"grit/testdata/klonk.rc", IDC_KLONKMENU},
++ {"abc", IDS_FIRSTPRESENT},
++ {"ghi", IDS_LANGUAGESPECIFIC},
++ {"mno", IDS_THIRDPRESENT},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
++
++ def testFormatResourceMapWithGeneratedFile(self):
++ os.environ["root_gen_dir"] = "gen"
++
++ grd = util.ParseGrdForUnittest('''\
++ <outputs>
++ <output type="rc_header" filename="the_rc_header.h" />
++ <output type="resource_map_header"
++ filename="resource_map_header.h" />
++ </outputs>
++ <release seq="3">
++ <includes first_id="10000">
++ <include type="BINDATA"
++ file="${root_gen_dir}/foo/bar/baz.js"
++ name="IDR_FOO_BAR_BAZ_JS"
++ use_base_dir="false"
++ compress="gzip" />
++ </includes>
++ </release>''', run_gatherers=True)
++
++ formatter = resource_map.GetFormatter('resource_file_map_source')
++ output = util.StripBlankLinesAndComments(''.join(formatter(grd, 'en', '.')))
++ expected = '''\
++#include "resource_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"@out_folder@/gen/foo/bar/baz.js", IDR_FOO_BAR_BAZ_JS},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);'''
++ self.assertEqual(expected, output)
++
++ def testFormatResourceMapWithOutputAllEqualsFalseForStructures(self):
++ grd = util.ParseGrdForUnittest('''
++ <outputs>
++ <output type="rc_header" filename="the_rc_header.h" />
++ <output type="resource_map_header"
++ filename="the_resource_map_header.h" />
++ <output type="resource_map_source"
++ filename="the_resource_map_header.cc" />
++ </outputs>
++ <release seq="3">
++ <structures first_id="300">
++ <structure type="chrome_scaled_image" name="IDR_KLONKMENU"
++ file="foo.png" />
++ <if expr="False">
++ <structure type="chrome_scaled_image" name="IDR_MISSING"
++ file="bar.png" />
++ </if>
++ <if expr="True">
++ <structure type="chrome_scaled_image" name="IDR_BLOB"
++ file="blob.png" />
++ </if>
++ <if expr="True">
++ <then>
++ <structure type="chrome_scaled_image" name="IDR_METEOR"
++ file="meteor.png" />
++ </then>
++ <else>
++ <structure type="chrome_scaled_image" name="IDR_METEOR"
++ file="roetem.png" />
++ </else>
++ </if>
++ <if expr="False">
++ <structure type="chrome_scaled_image" name="IDR_LAST"
++ file="zyx.png" />
++ </if>
++ <if expr="True">
++ <structure type="chrome_scaled_image" name="IDR_LAST"
++ file="xyz.png" />
++ </if>
++ </structures>
++ </release>''', run_gatherers=True)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include <stddef.h>
++#ifndef GRIT_RESOURCE_MAP_STRUCT_
++#define GRIT_RESOURCE_MAP_STRUCT_
++struct GritResourceMap {
++ const char* const name;
++ int value;
++};
++#endif // GRIT_RESOURCE_MAP_STRUCT_
++extern const GritResourceMap kTheRcHeader[];
++extern const size_t kTheRcHeaderSize;''', output)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include "the_resource_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"IDR_KLONKMENU", IDR_KLONKMENU},
++ {"IDR_BLOB", IDR_BLOB},
++ {"IDR_METEOR", IDR_METEOR},
++ {"IDR_LAST", IDR_LAST},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include "the_resource_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"IDR_KLONKMENU", IDR_KLONKMENU},
++ {"IDR_BLOB", IDR_BLOB},
++ {"IDR_METEOR", IDR_METEOR},
++ {"IDR_LAST", IDR_LAST},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
++
++ def testFormatResourceMapWithOutputAllEqualsFalseForIncludes(self):
++ grd = util.ParseGrdForUnittest('''
++ <outputs>
++ <output type="rc_header" filename="the_rc_header.h" />
++ <output type="resource_map_header"
++ filename="the_resource_map_header.h" />
++ </outputs>
++ <release seq="3">
++ <structures first_id="300">
++ <structure type="menu" name="IDC_KLONKMENU"
++ file="grit\\testdata\\klonk.rc" encoding="utf-16" />
++ </structures>
++ <includes first_id="10000">
++ <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
++ <if expr="False">
++ <include type="foo" file="def" name="IDS_MISSING" />
++ </if>
++ <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
++ <if expr="True">
++ <include type="foo" file="blob" name="IDS_BLOB" />
++ </if>
++ <if expr="True">
++ <then>
++ <include type="foo" file="meteor" name="IDS_METEOR" />
++ </then>
++ <else>
++ <include type="foo" file="roetem" name="IDS_METEOR" />
++ </else>
++ </if>
++ <if expr="False">
++ <include type="foo" file="zyx" name="IDS_LAST" />
++ </if>
++ <if expr="True">
++ <include type="foo" file="xyz" name="IDS_LAST" />
++ </if>
++ </includes>
++ </release>''', run_gatherers=True)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include <stddef.h>
++#ifndef GRIT_RESOURCE_MAP_STRUCT_
++#define GRIT_RESOURCE_MAP_STRUCT_
++struct GritResourceMap {
++ const char* const name;
++ int value;
++};
++#endif // GRIT_RESOURCE_MAP_STRUCT_
++extern const GritResourceMap kTheRcHeader[];
++extern const size_t kTheRcHeaderSize;''', output)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include "the_resource_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"IDC_KLONKMENU", IDC_KLONKMENU},
++ {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
++ {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
++ {"IDS_BLOB", IDS_BLOB},
++ {"IDS_METEOR", IDS_METEOR},
++ {"IDS_LAST", IDS_LAST},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include "the_resource_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"grit/testdata/klonk.rc", IDC_KLONKMENU},
++ {"abc", IDS_FIRSTPRESENT},
++ {"mno", IDS_THIRDPRESENT},
++ {"blob", IDS_BLOB},
++ {"meteor", IDS_METEOR},
++ {"xyz", IDS_LAST},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
++
++ def testFormatStringResourceMap(self):
++ grd = util.ParseGrdForUnittest('''
++ <outputs>
++ <output type="rc_header" filename="the_rc_header.h" />
++ <output type="resource_map_header" filename="the_rc_map_header.h" />
++ <output type="resource_map_source" filename="the_rc_map_source.cc" />
++ </outputs>
++ <release seq="1" allow_pseudo="false">
++ <messages fallback_to_english="true">
++ <message name="IDS_PRODUCT_NAME" desc="The application name">
++ Application
++ </message>
++ <if expr="True">
++ <message name="IDS_DEFAULT_TAB_TITLE_TITLE_CASE"
++ desc="In Title Case: The default title in a tab.">
++ New Tab
++ </message>
++ </if>
++ <if expr="False">
++ <message name="IDS_DEFAULT_TAB_TITLE"
++ desc="The default title in a tab.">
++ New tab
++ </message>
++ </if>
++ </messages>
++ </release>''', run_gatherers=True)
++ grd.InitializeIds()
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include <stddef.h>
++#ifndef GRIT_RESOURCE_MAP_STRUCT_
++#define GRIT_RESOURCE_MAP_STRUCT_
++struct GritResourceMap {
++ const char* const name;
++ int value;
++};
++#endif // GRIT_RESOURCE_MAP_STRUCT_
++extern const GritResourceMap kTheRcHeader[];
++extern const size_t kTheRcHeaderSize;''', output)
++ output = util.StripBlankLinesAndComments(''.join(
++ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
++ self.assertEqual('''\
++#include "the_rc_map_header.h"
++#include <stddef.h>
++#include "base/stl_util.h"
++#include "the_rc_header.h"
++const GritResourceMap kTheRcHeader[] = {
++ {"IDS_PRODUCT_NAME", IDS_PRODUCT_NAME},
++ {"IDS_DEFAULT_TAB_TITLE_TITLE_CASE", IDS_DEFAULT_TAB_TITLE_TITLE_CASE},
++};
++const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/gather/__init__.py b/tools/grit/grit/gather/__init__.py
+new file mode 100644
+index 0000000000..2d578f5643
+--- /dev/null
++++ b/tools/grit/grit/gather/__init__.py
+@@ -0,0 +1,8 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Module grit.gather
++'''
++
++pass
+diff --git a/tools/grit/grit/gather/admin_template.py b/tools/grit/grit/gather/admin_template.py
+new file mode 100644
+index 0000000000..c26b6a88d7
+--- /dev/null
++++ b/tools/grit/grit/gather/admin_template.py
+@@ -0,0 +1,62 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Gatherer for administrative template files.
++'''
++
++from __future__ import print_function
++
++import re
++
++from grit.gather import regexp
++from grit import exception
++from grit import lazy_re
++
++
++class MalformedAdminTemplateException(exception.Base):
++ '''This file doesn't look like a .adm file to me.'''
++ pass
++
++
++class AdmGatherer(regexp.RegexpGatherer):
++ '''Gatherer for the translateable portions of an admin template.
++
++ This gatherer currently makes the following assumptions:
++ - there is only one [strings] section and it is always the last section
++ of the file
++ - translateable strings do not need to be escaped.
++ '''
++
++ # Finds the strings section as the group named 'strings'
++ _STRINGS_SECTION = lazy_re.compile(
++ r'(?P<first_part>.+^\[strings\])(?P<strings>.+)\Z',
++ re.MULTILINE | re.DOTALL)
++
++ # Finds the translateable sections from within the [strings] section.
++ _TRANSLATEABLES = lazy_re.compile(
++ r'^\s*[A-Za-z0-9_]+\s*=\s*"(?P<text>.+)"\s*$',
++ re.MULTILINE)
++
++ def Escape(self, text):
++ return text.replace('\n', '\\n')
++
++ def UnEscape(self, text):
++ return text.replace('\\n', '\n')
++
++ def Parse(self):
++ if self.have_parsed_:
++ return
++ self.have_parsed_ = True
++
++ self.text_ = self._LoadInputFile().strip()
++ m = self._STRINGS_SECTION.match(self.text_)
++ if not m:
++ raise MalformedAdminTemplateException()
++ # Add the first part, which is all nontranslateable, to the skeleton
++ self._AddNontranslateableChunk(m.group('first_part'))
++ # Then parse the rest using the _TRANSLATEABLES regexp.
++ self._RegExpParse(self._TRANSLATEABLES, m.group('strings'))
++
++ def GetTextualIds(self):
++ return [self.extkey]
+diff --git a/tools/grit/grit/gather/admin_template_unittest.py b/tools/grit/grit/gather/admin_template_unittest.py
+new file mode 100644
+index 0000000000..c637af3a75
+--- /dev/null
++++ b/tools/grit/grit/gather/admin_template_unittest.py
+@@ -0,0 +1,115 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for the admin template gatherer.'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit.gather import admin_template
++from grit import util
++from grit import grd_reader
++from grit import grit_runner
++from grit.tool import build
++
++
++class AdmGathererUnittest(unittest.TestCase):
++ def testParsingAndTranslating(self):
++ pseudofile = StringIO(
++ 'bingo bongo\n'
++ 'ding dong\n'
++ '[strings] \n'
++ 'whatcha="bingo bongo"\n'
++ 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
++ gatherer = admin_template.AdmGatherer(pseudofile)
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 2)
++ self.failUnless(gatherer.GetCliques()[1].GetMessage().GetRealContent() ==
++ 'bingolabongola "the wise" fingulafongula')
++
++ translation = gatherer.Translate('en')
++ self.failUnless(translation == gatherer.GetText().strip())
++
++ def testErrorHandling(self):
++ pseudofile = StringIO(
++ 'bingo bongo\n'
++ 'ding dong\n'
++ 'whatcha="bingo bongo"\n'
++ 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
++ gatherer = admin_template.AdmGatherer(pseudofile)
++ self.assertRaises(admin_template.MalformedAdminTemplateException,
++ gatherer.Parse)
++
++ _TRANSLATABLES_FROM_FILE = (
++ 'Google', 'Google Desktop', 'Preferences',
++ 'Controls Google Desktop preferences',
++ 'Indexing and Capture Control',
++ 'Controls what files, web pages, and other content will be indexed by Google Desktop.',
++ 'Prevent indexing of email',
++ # there are lots more but we don't check any further
++ )
++
++ def VerifyCliquesFromAdmFile(self, cliques):
++ self.failUnless(len(cliques) > 20)
++ for clique, expected in zip(cliques, self._TRANSLATABLES_FROM_FILE):
++ text = clique.GetMessage().GetRealContent()
++ self.failUnless(text == expected)
++
++ def testFromFile(self):
++ fname = util.PathFromRoot('grit/testdata/GoogleDesktop.adm')
++ gatherer = admin_template.AdmGatherer(fname)
++ gatherer.Parse()
++ cliques = gatherer.GetCliques()
++ self.VerifyCliquesFromAdmFile(cliques)
++
++ def MakeGrd(self):
++ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3">
++ <release seq="3">
++ <structures>
++ <structure type="admin_template" name="IDAT_GOOGLE_DESKTOP_SEARCH"
++ file="GoogleDesktop.adm" exclude_from_rc="true" />
++ <structure type="txt" name="BINGOBONGO"
++ file="README.txt" exclude_from_rc="true" />
++ </structures>
++ </release>
++ <outputs>
++ <output filename="de_res.rc" type="rc_all" lang="de" />
++ </outputs>
++ </grit>'''), util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ return grd
++
++ def testInGrd(self):
++ grd = self.MakeGrd()
++ cliques = grd.children[0].children[0].children[0].GetCliques()
++ self.VerifyCliquesFromAdmFile(cliques)
++
++ def testFileIsOutput(self):
++ grd = self.MakeGrd()
++ dirname = util.TempDir({})
++ try:
++ tool = build.RcBuilder()
++ tool.o = grit_runner.Options()
++ tool.output_directory = dirname.GetPath()
++ tool.res = grd
++ tool.Process()
++
++ self.failUnless(os.path.isfile(dirname.GetPath('de_GoogleDesktop.adm')))
++ self.failUnless(os.path.isfile(dirname.GetPath('de_README.txt')))
++ finally:
++ dirname.CleanUp()
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/gather/chrome_html.py b/tools/grit/grit/gather/chrome_html.py
+new file mode 100644
+index 0000000000..71c1332d66
+--- /dev/null
++++ b/tools/grit/grit/gather/chrome_html.py
+@@ -0,0 +1,377 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Prepares a Chrome HTML file by inlining resources and adding references to
++high DPI resources and removing references to unsupported scale factors.
++
++This is a small gatherer that takes a HTML file, looks for src attributes
++and inlines the specified file, producing one HTML file with no external
++dependencies. It recursively inlines the included files. When inlining CSS
++image files this script also checks for the existence of high DPI versions
++of the inlined file including those on relevant platforms. Unsupported scale
++factors are also removed from existing image sets to support explicitly
++referencing all available images.
++"""
++
++from __future__ import print_function
++
++import os
++import re
++
++from grit import lazy_re
++from grit import util
++from grit.format import html_inline
++from grit.gather import interface
++
++
++# Distribution string to replace with distribution.
++DIST_SUBSTR = '%DISTRIBUTION%'
++
++
++# Matches a chrome theme source URL.
++_THEME_SOURCE = lazy_re.compile(
++ r'(?P<baseurl>chrome://theme/IDR_[A-Z0-9_]*)(?P<query>\?.*)?')
++# Pattern for matching CSS url() function.
++_CSS_URL_PATTERN = r'url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)\)'
++# Matches CSS url() functions with the capture group 'filename'.
++_CSS_URL = lazy_re.compile(_CSS_URL_PATTERN)
++# Matches one or more CSS image urls used in given properties.
++_CSS_IMAGE_URLS = lazy_re.compile(
++ r'(?P<attribute>content|background|[\w-]*-image):\s*'
++ r'(?P<urls>(' + _CSS_URL_PATTERN + r'\s*,?\s*)+)')
++# Matches CSS image sets.
++_CSS_IMAGE_SETS = lazy_re.compile(
++ r'(?P<attribute>content|background|[\w-]*-image):[ ]*'
++ r'-webkit-image-set\((?P<images>'
++ r'(\s*,?\s*url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*[0-9.]*x)*)\)',
++ re.MULTILINE)
++# Matches a single image in a CSS image set with the capture group scale.
++_CSS_IMAGE_SET_IMAGE = lazy_re.compile(r'\s*,?\s*'
++ r'url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*(?P<scale>[0-9.]*x)',
++ re.MULTILINE)
++_HTML_IMAGE_SRC = lazy_re.compile(
++ r'<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>')
++
++def GetImageList(
++ base_path, filename, scale_factors, distribution,
++ filename_expansion_function=None):
++ """Generate the list of images which match the provided scale factors.
++
++ Takes an image filename and checks for files of the same name in folders
++ corresponding to the supported scale factors. If the file is from a
++ chrome://theme/ source, inserts supported @Nx scale factors as high DPI
++ versions.
++
++ Args:
++ base_path: path to look for relative file paths in
++ filename: name of the base image file
++ scale_factors: a list of the supported scale factors (i.e. ['2x'])
++ distribution: string that should replace %DISTRIBUTION%
++
++ Returns:
++ array of tuples containing scale factor and image (i.e.
++ [('1x', 'image.png'), ('2x', '2x/image.png')]).
++ """
++ # Any matches for which a chrome URL handler will serve all scale factors
++ # can simply request all scale factors.
++ theme_match = _THEME_SOURCE.match(filename)
++ if theme_match:
++ images = [('1x', filename)]
++ for scale_factor in scale_factors:
++ scale_filename = "%s@%s" % (theme_match.group('baseurl'), scale_factor)
++ if theme_match.group('query'):
++ scale_filename += theme_match.group('query')
++ images.append((scale_factor, scale_filename))
++ return images
++
++ if filename.find(':') != -1:
++ # filename is probably a URL, only return filename itself.
++ return [('1x', filename)]
++
++ filename = filename.replace(DIST_SUBSTR, distribution)
++ if filename_expansion_function:
++ filename = filename_expansion_function(filename)
++ filepath = os.path.join(base_path, filename)
++ images = [('1x', filename)]
++
++ for scale_factor in scale_factors:
++ # Check for existence of file and add to image set.
++ scale_path = os.path.split(os.path.join(base_path, filename))
++ scale_image_path = os.path.join(scale_path[0], scale_factor, scale_path[1])
++ if os.path.isfile(scale_image_path):
++ # HTML/CSS always uses forward slashed paths.
++ parts = filename.rsplit('/', 1)
++ if len(parts) == 1:
++ path = ''
++ else:
++ path = parts[0] + '/'
++ scale_image_name = path + scale_factor + '/' + parts[-1]
++ images.append((scale_factor, scale_image_name))
++ return images
++
++
++def GenerateImageSet(images, quote):
++ """Generates a -webkit-image-set for the provided list of images.
++
++ Args:
++ images: an array of tuples giving scale factor and file path
++ (i.e. [('1x', 'image.png'), ('2x', '2x/image.png')]).
++ quote: a string giving the quotation character to use (i.e. "'")
++
++ Returns:
++ string giving a -webkit-image-set rule referencing the provided images.
++ (i.e. '-webkit-image-set(url('image.png') 1x, url('2x/image.png') 2x)')
++ """
++ imageset = []
++ for (scale_factor, filename) in images:
++ imageset.append("url(%s%s%s) %s" % (quote, filename, quote, scale_factor))
++ return "-webkit-image-set(%s)" % (', '.join(imageset))
++
++
++def UrlToImageSet(
++ src_match, base_path, scale_factors, distribution,
++ filename_expansion_function=None):
++ """Regex replace function which replaces url() with -webkit-image-set.
++
++ Takes a regex match for url('path'). If the file is local, checks for
++ files of the same name in folders corresponding to the supported scale
++ factors. If the file is from a chrome://theme/ source, inserts the
++ supported @Nx scale factor request. In either case inserts a
++ -webkit-image-set rule to fetch the appropriate image for the current
++ scale factor.
++
++ Args:
++ src_match: regex match object from _CSS_URLS
++ base_path: path to look for relative file paths in
++ scale_factors: a list of the supported scale factors (i.e. ['2x'])
++ distribution: string that should replace %DISTRIBUTION%.
++
++ Returns:
++ string
++ """
++ quote = src_match.group('quote')
++ filename = src_match.group('filename')
++ image_list = GetImageList(
++ base_path, filename, scale_factors, distribution,
++ filename_expansion_function=filename_expansion_function)
++
++ # Don't modify the source if there is only one image.
++ if len(image_list) == 1:
++ return src_match.group(0)
++
++ return GenerateImageSet(image_list, quote)
++
++
++def InsertImageSet(
++ src_match, base_path, scale_factors, distribution,
++ filename_expansion_function=None):
++ """Regex replace function which inserts -webkit-image-set rules.
++
++ Takes a regex match for `property: url('path')[, url('path')]+`.
++ Replaces one or more occurances of the match with image set rules.
++
++ Args:
++ src_match: regex match object from _CSS_IMAGE_URLS
++ base_path: path to look for relative file paths in
++ scale_factors: a list of the supported scale factors (i.e. ['2x'])
++ distribution: string that should replace %DISTRIBUTION%.
++
++ Returns:
++ string
++ """
++ attr = src_match.group('attribute')
++ urls = _CSS_URL.sub(
++ lambda m: UrlToImageSet(m, base_path, scale_factors, distribution,
++ filename_expansion_function),
++ src_match.group('urls'))
++
++ return "%s: %s" % (attr, urls)
++
++
++def InsertImageStyle(
++ src_match, base_path, scale_factors, distribution,
++ filename_expansion_function=None):
++ """Regex replace function which adds a content style to an <img>.
++
++ Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS
++ style which defines the image set.
++ """
++ filename = src_match.group('filename')
++ image_list = GetImageList(
++ base_path, filename, scale_factors, distribution,
++ filename_expansion_function=filename_expansion_function)
++
++ # Don't modify the source if there is only one image or image already defines
++ # a style.
++ if src_match.group(0).find(" style=\"") != -1 or len(image_list) == 1:
++ return src_match.group(0)
++
++ return "%s style=\"content: %s;\">" % (src_match.group(0)[:-1],
++ GenerateImageSet(image_list, "'"))
++
++
++def InsertImageSets(
++ filepath, text, scale_factors, distribution,
++ filename_expansion_function=None):
++ """Helper function that adds references to external images available in any of
++ scale_factors in CSS backgrounds.
++ """
++ # Add high DPI urls for css attributes: content, background,
++ # or *-image or <img src="foo">.
++ return _CSS_IMAGE_URLS.sub(
++ lambda m: InsertImageSet(
++ m, filepath, scale_factors, distribution,
++ filename_expansion_function=filename_expansion_function),
++ _HTML_IMAGE_SRC.sub(
++ lambda m: InsertImageStyle(
++ m, filepath, scale_factors, distribution,
++ filename_expansion_function=filename_expansion_function),
++ text))
++
++
++def RemoveImagesNotIn(scale_factors, src_match):
++ """Regex replace function which removes images for scale factors not in
++ scale_factors.
++
++ Takes a regex match for _CSS_IMAGE_SETS. For each image in the group images,
++ checks if this scale factor is in scale_factors and if not, removes it.
++
++ Args:
++ scale_factors: a list of the supported scale factors (i.e. ['1x', '2x'])
++ src_match: regex match object from _CSS_IMAGE_SETS
++
++ Returns:
++ string
++ """
++ attr = src_match.group('attribute')
++ images = _CSS_IMAGE_SET_IMAGE.sub(
++ lambda m: m.group(0) if m.group('scale') in scale_factors else '',
++ src_match.group('images'))
++ return "%s: -webkit-image-set(%s)" % (attr, images)
++
++
++def RemoveImageSetImages(text, scale_factors):
++ """Helper function which removes images in image sets not in the list of
++ supported scale_factors.
++ """
++ return _CSS_IMAGE_SETS.sub(
++ lambda m: RemoveImagesNotIn(scale_factors, m), text)
++
++
++def ProcessImageSets(
++ filepath, text, scale_factors, distribution,
++ filename_expansion_function=None):
++ """Helper function that adds references to external images available in other
++ scale_factors and removes images from image-sets in unsupported scale_factors.
++ """
++ # Explicitly add 1x to supported scale factors so that it is not removed.
++ supported_scale_factors = ['1x']
++ supported_scale_factors.extend(scale_factors)
++ return InsertImageSets(
++ filepath,
++ RemoveImageSetImages(text, supported_scale_factors),
++ scale_factors,
++ distribution,
++ filename_expansion_function=filename_expansion_function)
++
++
++class ChromeHtml(interface.GathererBase):
++ """Represents an HTML document processed for Chrome WebUI.
++
++ HTML documents used in Chrome WebUI have local resources inlined and
++ automatically insert references to high DPI assets used in CSS properties
++ with the use of the -webkit-image-set value. References to unsupported scale
++ factors in image sets are also removed. This does not generate any
++ translateable messages and instead generates a single DataPack resource.
++ """
++
++ def __init__(self, *args, **kwargs):
++ super(ChromeHtml, self).__init__(*args, **kwargs)
++ self.allow_external_script_ = False
++ self.flatten_html_ = False
++ self.preprocess_only_ = False
++ # 1x resources are implicitly already in the source and do not need to be
++ # added.
++ self.scale_factors_ = []
++ self.filename_expansion_function = None
++
++ def SetAttributes(self, attrs):
++ self.allow_external_script_ = ('allowexternalscript' in attrs and
++ attrs['allowexternalscript'] == 'true')
++ self.preprocess_only_ = ('preprocess' in attrs and
++ attrs['preprocess'] == 'true')
++ self.flatten_html_ = (self.preprocess_only_ or ('flattenhtml' in attrs and
++ attrs['flattenhtml'] == 'true'))
++
++ def SetDefines(self, defines):
++ if 'scale_factors' in defines:
++ self.scale_factors_ = defines['scale_factors'].split(',')
++
++ def GetText(self):
++ """Returns inlined text of the HTML document."""
++ return self.inlined_text_
++
++ def GetTextualIds(self):
++ return [self.extkey]
++
++ def GetData(self, lang, encoding):
++ """Returns inlined text of the HTML document."""
++ ret = self.inlined_text_
++ if encoding == util.BINARY:
++ ret = ret.encode('utf-8')
++ return ret
++
++ def GetHtmlResourceFilenames(self):
++ """Returns a set of all filenames inlined by this file."""
++ if self.flatten_html_:
++ return html_inline.GetResourceFilenames(
++ self.grd_node.ToRealPath(self.GetInputPath()),
++ self.grd_node,
++ allow_external_script=self.allow_external_script_,
++ rewrite_function=lambda fp, t, d: ProcessImageSets(
++ fp, t, self.scale_factors_, d,
++ filename_expansion_function=self.filename_expansion_function),
++ filename_expansion_function=self.filename_expansion_function)
++ return []
++
++ def Translate(self, lang, pseudo_if_not_available=True,
++ skeleton_gatherer=None, fallback_to_english=False):
++ """Returns this document translated."""
++ return self.inlined_text_
++
++ def SetFilenameExpansionFunction(self, fn):
++ self.filename_expansion_function = fn
++
++ def Parse(self):
++ """Parses and inlines the represented file."""
++
++ filename = self.GetInputPath()
++ # If there is a grd_node, prefer its GetInputPath(), as that may do more
++ # processing to make the call to ToRealPath() below work correctly.
++ if self.grd_node:
++ filename = self.grd_node.GetInputPath()
++ if self.filename_expansion_function:
++ filename = self.filename_expansion_function(filename)
++ # Hack: some unit tests supply an absolute path and no root node.
++ if not os.path.isabs(filename):
++ filename = self.grd_node.ToRealPath(filename)
++ if self.flatten_html_:
++ self.inlined_text_ = html_inline.InlineToString(
++ filename,
++ self.grd_node,
++ allow_external_script = self.allow_external_script_,
++ strip_whitespace=True,
++ preprocess_only = self.preprocess_only_,
++ rewrite_function=lambda fp, t, d: ProcessImageSets(
++ fp, t, self.scale_factors_, d,
++ filename_expansion_function=self.filename_expansion_function),
++ filename_expansion_function=self.filename_expansion_function)
++ else:
++ distribution = html_inline.GetDistribution()
++ self.inlined_text_ = ProcessImageSets(
++ os.path.dirname(filename),
++ util.ReadFile(filename, 'utf-8'),
++ self.scale_factors_,
++ distribution,
++ filename_expansion_function=self.filename_expansion_function)
+diff --git a/tools/grit/grit/gather/chrome_html_unittest.py b/tools/grit/grit/gather/chrome_html_unittest.py
+new file mode 100644
+index 0000000000..8c75ee5bf4
+--- /dev/null
++++ b/tools/grit/grit/gather/chrome_html_unittest.py
+@@ -0,0 +1,610 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.gather.chrome_html'''
++
++from __future__ import print_function
++
++import os
++import re
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit import lazy_re
++from grit import util
++from grit.gather import chrome_html
++
++
++_NEW_LINE = lazy_re.compile('(\r\n|\r|\n)', re.MULTILINE)
++
++
++def StandardizeHtml(text):
++ '''Standardizes the newline format and png mime type in Html text.'''
++ return _NEW_LINE.sub('\n', text).replace('data:image/x-png;',
++ 'data:image/png;')
++
++
++class ChromeHtmlUnittest(unittest.TestCase):
++ '''Unit tests for ChromeHtml.'''
++
++ def testFileResources(self):
++ '''Tests inlined image file resources with available high DPI assets.'''
++
++ tmp_dir = util.TempDir({
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ ''',
++
++ 'test.css': '''
++ .image {
++ background: url('test.png');
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '1.4x/test.png': '1.4x PNG DATA',
++
++ '1.8x/test.png': '1.8x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
++ html.SetDefines({'scale_factors': '1.4x,1.8x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <style>
++ .image {
++ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
++ }
++ </style>
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesImageTag(self):
++ '''Tests inlined image file resources with available high DPI assets on
++ an image tag.'''
++
++ tmp_dir = util.TempDir({
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <body>
++ <img id="foo" src="test.png">
++ </body>
++ </html>
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ <!DOCTYPE HTML>
++ <html>
++ <body>
++ <img id="foo" src="data:image/png;base64,UE5HIERBVEE=" style="content: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MnggUE5HIERBVEE=') 2x);">
++ </body>
++ </html>
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesNoFlatten(self):
++ '''Tests non-inlined image file resources with available high DPI assets.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url('test.png');
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '1.4x/test.png': '1.4x PNG DATA',
++
++ '1.8x/test.png': '1.8x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '1.4x,1.8x'})
++ html.SetAttributes({'flattenhtml': 'false'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url('test.png') 1x, url('1.4x/test.png') 1.4x, url('1.8x/test.png') 1.8x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesNoFlattenSubdir(self):
++ '''Tests non-inlined image file resources w/high DPI assets in subdirs.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url('sub/test.png');
++ }
++ ''',
++
++ 'sub/test.png': 'PNG DATA',
++
++ 'sub/1.4x/test.png': '1.4x PNG DATA',
++
++ 'sub/1.8x/test.png': '1.8x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '1.4x,1.8x'})
++ html.SetAttributes({'flattenhtml': 'false'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url('sub/test.png') 1x, url('sub/1.4x/test.png') 1.4x, url('sub/1.8x/test.png') 1.8x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesPreprocess(self):
++ '''Tests preprocessed image file resources with available high DPI
++ assets.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url('test.png');
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '1.4x/test.png': '1.4x PNG DATA',
++
++ '1.8x/test.png': '1.8x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '1.4x,1.8x'})
++ html.SetAttributes({'flattenhtml': 'false', 'preprocess': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url('test.png') 1x, url('1.4x/test.png') 1.4x, url('1.8x/test.png') 1.8x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesDoubleQuotes(self):
++ '''Tests inlined image file resources if url() filename is double quoted.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url("test.png");
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url("data:image/png;base64,UE5HIERBVEE=") 1x, url("data:image/png;base64,MnggUE5HIERBVEE=") 2x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesNoQuotes(self):
++ '''Tests inlined image file resources when url() filename is unquoted.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url(test.png);
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesSubdirs(self):
++ '''Tests inlined image file resources if url() filename is in a subdir.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url('some/sub/path/test.png');
++ }
++ ''',
++
++ 'some/sub/path/test.png': 'PNG DATA',
++
++ 'some/sub/path/2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MnggUE5HIERBVEE=') 2x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesNoFile(self):
++ '''Tests inlined image file resources without available high DPI assets.'''
++
++ tmp_dir = util.TempDir({
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ ''',
++
++ 'test.css': '''
++ .image {
++ background: url('test.png');
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <style>
++ .image {
++ background: url('data:image/png;base64,UE5HIERBVEE=');
++ }
++ </style>
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesMultipleBackgrounds(self):
++ '''Tests inlined image file resources with two url()s.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url(test.png), url(test.png);
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x), -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesMultipleBackgroundsWithNewline1(self):
++ '''Tests inlined image file resources with line break after first url().'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background: url(test.png),
++ url(test.png);
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x),
++ -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesMultipleBackgroundsWithNewline2(self):
++ '''Tests inlined image file resources with line break before first url()
++ and before second url().'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background:
++ url(test.png),
++ url(test.png);
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x),
++ -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testFileResourcesCRLF(self):
++ '''Tests inlined image file resource when url() is preceded by a Windows
++ style line break.'''
++
++ tmp_dir = util.TempDir({
++ 'test.css': '''
++ .image {
++ background:\r\nurl(test.png);
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ '2x/test.png': '2x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ .image {
++ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
++ }
++ '''))
++ tmp_dir.CleanUp()
++
++ def testThemeResources(self):
++ '''Tests inserting high DPI chrome://theme references.'''
++
++ tmp_dir = util.TempDir({
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ ''',
++
++ 'test.css': '''
++ .image {
++ background: url('chrome://theme/IDR_RESOURCE_NAME');
++ content: url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1');
++ }
++ ''',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
++ html.SetDefines({'scale_factors': '2x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <style>
++ .image {
++ background: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME') 1x, url('chrome://theme/IDR_RESOURCE_NAME@2x') 2x);
++ content: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1') 1x, url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q@2x?$1') 2x);
++ }
++ </style>
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ '''))
++ tmp_dir.CleanUp()
++
++ def testRemoveUnsupportedScale(self):
++ '''Tests removing an unsupported scale factor from an explicit image-set.'''
++
++ tmp_dir = util.TempDir({
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ ''',
++
++ 'test.css': '''
++ .image {
++ background: -webkit-image-set(url('test.png') 1x,
++ url('test1.4.png') 1.4x,
++ url('test1.8.png') 1.8x);
++ }
++ ''',
++
++ 'test.png': 'PNG DATA',
++
++ 'test1.4.png': '1.4x PNG DATA',
++
++ 'test1.8.png': '1.8x PNG DATA',
++ })
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
++ html.SetDefines({'scale_factors': '1.8x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <style>
++ .image {
++ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x,
++ url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
++ }
++ </style>
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ '''))
++ tmp_dir.CleanUp()
++
++ def testExpandVariablesInFilename(self):
++ '''
++ Tests variable substitution in filenames while flattening images
++ with multiple scale factors.
++ '''
++
++ tmp_dir = util.TempDir({
++ 'index.html': '''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <link rel="stylesheet" href="test.css">
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ ''',
++
++ 'test.css': '''
++ .image {
++ background: url('test[WHICH].png');
++ }
++ ''',
++
++ 'test1.png': 'PNG DATA',
++ '1.4x/test1.png': '1.4x PNG DATA',
++ '1.8x/test1.png': '1.8x PNG DATA',
++ })
++
++ def replacer(var, repl):
++ return lambda filename: filename.replace('[%s]' % var, repl)
++
++ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
++ html.SetDefines({'scale_factors': '1.4x,1.8x'})
++ html.SetAttributes({'flattenhtml': 'true'})
++ html.SetFilenameExpansionFunction(replacer('WHICH', '1'));
++ html.Parse()
++ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
++ StandardizeHtml('''
++ <!DOCTYPE HTML>
++ <html>
++ <head>
++ <style>
++ .image {
++ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
++ }
++ </style>
++ </head>
++ <body>
++ <!-- Don't need a body. -->
++ </body>
++ </html>
++ '''))
++ tmp_dir.CleanUp()
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/gather/chrome_scaled_image.py b/tools/grit/grit/gather/chrome_scaled_image.py
+new file mode 100644
+index 0000000000..44f98cbcf0
+--- /dev/null
++++ b/tools/grit/grit/gather/chrome_scaled_image.py
+@@ -0,0 +1,157 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Gatherer for <structure type="chrome_scaled_image">.
++'''
++
++from __future__ import print_function
++
++import os
++import struct
++
++from grit import exception
++from grit import lazy_re
++from grit import util
++from grit.gather import interface
++
++
++_PNG_SCALE_CHUNK = b'\0\0\0\0csCl\xc1\x30\x60\x4d'
++
++
++def _RescaleImage(data, from_scale, to_scale):
++ if from_scale != to_scale:
++ assert from_scale == 100
++ # Rather than rescaling the image we add a custom chunk directing Chrome to
++ # rescale it on load. Just append it to the PNG data since
++ # _MoveSpecialChunksToFront will move it later anyway.
++ data += _PNG_SCALE_CHUNK
++ return data
++
++
++_PNG_MAGIC = b'\x89PNG\r\n\x1a\n'
++
++'''Mandatory first chunk in order for the png to be valid.'''
++_FIRST_CHUNK = b'IHDR'
++
++'''Special chunks to move immediately after the IHDR chunk. (so that the PNG
++remains valid.)
++'''
++_SPECIAL_CHUNKS = frozenset(b'csCl npTc'.split())
++
++'''Any ancillary chunk not in this list is deleted from the PNG.'''
++_ANCILLARY_CHUNKS_TO_LEAVE = frozenset(
++ b'bKGD cHRM gAMA iCCP pHYs sBIT sRGB tRNS acTL fcTL fdAT'.split())
++
++
++def _MoveSpecialChunksToFront(data):
++ '''Move special chunks immediately after the IHDR chunk (so that the PNG
++ remains valid). Also delete ancillary chunks that are not on our whitelist.
++ '''
++ first = [_PNG_MAGIC]
++ special_chunks = []
++ rest = []
++ for chunk in _ChunkifyPNG(data):
++ type = chunk[4:8]
++ critical = type < b'a'
++ if type == _FIRST_CHUNK:
++ first.append(chunk)
++ elif type in _SPECIAL_CHUNKS:
++ special_chunks.append(chunk)
++ elif critical or type in _ANCILLARY_CHUNKS_TO_LEAVE:
++ rest.append(chunk)
++ return b''.join(first + special_chunks + rest)
++
++
++def _ChunkifyPNG(data):
++ '''Given a PNG image, yield its chunks in order.'''
++ assert data.startswith(_PNG_MAGIC)
++ pos = 8
++ while pos != len(data):
++ length = 12 + struct.unpack_from('>I', data, pos)[0]
++ assert 12 <= length <= len(data) - pos
++ yield data[pos:pos+length]
++ pos += length
++
++
++def _MakeBraceGlob(strings):
++ '''Given ['foo', 'bar'], return '{foo,bar}', for error reporting.
++ '''
++ if len(strings) == 1:
++ return strings[0]
++ else:
++ return '{' + ','.join(strings) + '}'
++
++
++class ChromeScaledImage(interface.GathererBase):
++ '''Represents an image that exists in multiple layout variants
++ (e.g. "default", "touch") and multiple scale variants
++ (e.g. "100_percent", "200_percent").
++ '''
++
++ split_context_re_ = lazy_re.compile(r'(.+)_(\d+)_percent\Z')
++
++ def _FindInputFile(self):
++ output_context = self.grd_node.GetRoot().output_context
++ match = self.split_context_re_.match(output_context)
++ if not match:
++ raise exception.MissingMandatoryAttribute(
++ 'All <output> nodes must have an appropriate context attribute'
++ ' (e.g. context="touch_200_percent")')
++ req_layout, req_scale = match.group(1), int(match.group(2))
++
++ layouts = [req_layout]
++ try_default_layout = self.grd_node.GetRoot().fallback_to_default_layout
++ if try_default_layout and 'default' not in layouts:
++ layouts.append('default')
++
++ scales = [req_scale]
++ try_low_res = self.grd_node.FindBooleanAttribute(
++ 'fallback_to_low_resolution', default=False, skip_self=False)
++ if try_low_res and 100 not in scales:
++ scales.append(100)
++
++ for layout in layouts:
++ for scale in scales:
++ dir = '%s_%s_percent' % (layout, scale)
++ path = os.path.join(dir, self.rc_file)
++ if os.path.exists(self.grd_node.ToRealPath(path)):
++ return path, scale, req_scale
++
++ if not try_default_layout:
++ # The file was not found in the specified output context and it was
++ # explicitly indicated that the default context should not be searched
++ # as a fallback, so return an empty path.
++ return None, 100, req_scale
++
++ # The file was found in neither the specified context nor the default
++ # context, so raise an exception.
++ dir = "%s_%s_percent" % (_MakeBraceGlob(layouts),
++ _MakeBraceGlob([str(x) for x in scales]))
++ raise exception.FileNotFound(
++ 'Tried ' + self.grd_node.ToRealPath(os.path.join(dir, self.rc_file)))
++
++ def GetInputPath(self):
++ path, scale, req_scale = self._FindInputFile()
++ return path
++
++ def Parse(self):
++ pass
++
++ def GetTextualIds(self):
++ return [self.extkey]
++
++ def GetData(self, lang, encoding):
++ assert encoding == util.BINARY
++
++ path, scale, req_scale = self._FindInputFile()
++ if path is None:
++ return None
++
++ data = util.ReadFile(self.grd_node.ToRealPath(path), util.BINARY)
++ data = _RescaleImage(data, scale, req_scale)
++ data = _MoveSpecialChunksToFront(data)
++ return data
++
++ def Translate(self, *args, **kwargs):
++ return self.GetData()
+diff --git a/tools/grit/grit/gather/chrome_scaled_image_unittest.py b/tools/grit/grit/gather/chrome_scaled_image_unittest.py
+new file mode 100644
+index 0000000000..1cebfc6de2
+--- /dev/null
++++ b/tools/grit/grit/gather/chrome_scaled_image_unittest.py
+@@ -0,0 +1,209 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for ChromeScaledImage.'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
++ '../..')))
++
++import re
++import struct
++import unittest
++import zlib
++
++from grit import exception
++from grit import util
++from grit.format import data_pack
++from grit.tool import build
++
++
++_OUTFILETYPES = [
++ ('.h', 'rc_header'),
++ ('_map.cc', 'resource_map_source'),
++ ('_map.h', 'resource_map_header'),
++ ('.pak', 'data_package'),
++ ('.rc', 'rc_all'),
++]
++
++
++_PNG_HEADER = (
++ b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52'
++ b'\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53'
++ b'\xde')
++_PNG_FOOTER = (
++ b'\x00\x00\x00\x0c\x49\x44\x41\x54\x18\x57\x63\xf8\xff\xff\x3f\x00'
++ b'\x05\xfe\x02\xfe\xa7\x35\x81\x84\x00\x00\x00\x00\x49\x45\x4e\x44'
++ b'\xae\x42\x60\x82')
++
++
++def _MakePNG(chunks):
++ # Python 3 changed the return value of zlib.crc32 to an unsigned int.
++ format = 'i' if sys.version_info.major < 3 else 'I'
++ pack_int32 = struct.Struct('>' + format).pack
++ chunks = [pack_int32(len(payload)) + type + payload +
++ pack_int32(zlib.crc32(type + payload))
++ for type, payload in chunks]
++ return _PNG_HEADER + b''.join(chunks) + _PNG_FOOTER
++
++
++def _GetFilesInPak(pakname):
++ '''Get a set of the files that were actually included in the .pak output.
++ '''
++ return set(data_pack.ReadDataPack(pakname).resources.values())
++
++
++def _GetFilesInRc(rcname, tmp_dir, contents):
++ '''Get a set of the files that were actually included in the .rc output.
++ '''
++ data = util.ReadFile(rcname, util.BINARY).decode('utf-16')
++ contents = dict((tmp_dir.GetPath(k), v) for k, v in contents.items())
++ return set(contents[os.path.normpath(m.group(1))]
++ for m in re.finditer(r'(?m)^\w+\s+BINDATA\s+"([^"]+)"$', data))
++
++
++def _MakeFallbackAttr(fallback):
++ if fallback is None:
++ return ''
++ else:
++ return ' fallback_to_low_resolution="%s"' % ('false', 'true')[fallback]
++
++
++def _Structures(fallback, *body):
++ return '<structures%s>\n%s\n</structures>' % (
++ _MakeFallbackAttr(fallback), '\n'.join(body))
++
++
++def _Structure(name, file, fallback=None):
++ return '<structure name="%s" file="%s" type="chrome_scaled_image"%s />' % (
++ name, file, _MakeFallbackAttr(fallback))
++
++
++def _If(expr, *body):
++ return '<if expr="%s">\n%s\n</if>' % (expr, '\n'.join(body))
++
++
++def _RunBuildTest(self, structures, inputs, expected_outputs, skip_rc=False,
++ layout_fallback=''):
++ outputs = '\n'.join('<output filename="out/%s%s" type="%s" context="%s"%s />'
++ % (context, ext, type, context, layout_fallback)
++ for ext, type in _OUTFILETYPES
++ for context in expected_outputs)
++
++ infiles = {
++ 'in/in.grd': ('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="0" current_release="1">
++ <outputs>
++ %s
++ </outputs>
++ <release seq="1">
++ %s
++ </release>
++ </grit>
++ ''' % (outputs, structures)).encode('utf-8'),
++ }
++ for pngpath, pngdata in inputs.items():
++ normpath = os.path.normpath('in/' + pngpath)
++ infiles[normpath] = pngdata
++ class Options(object):
++ pass
++
++ with util.TempDir(infiles, mode='wb') as tmp_dir:
++ with tmp_dir.AsCurrentDir():
++ options = Options()
++ options.input = tmp_dir.GetPath('in/in.grd')
++ options.verbose = False
++ options.extra_verbose = False
++ build.RcBuilder().Run(options, [])
++ for context, expected_data in expected_outputs.items():
++ self.assertEquals(expected_data,
++ _GetFilesInPak(tmp_dir.GetPath('out/%s.pak' % context)))
++ if not skip_rc:
++ self.assertEquals(expected_data,
++ _GetFilesInRc(tmp_dir.GetPath('out/%s.rc' % context),
++ tmp_dir, infiles))
++
++
++class ChromeScaledImageUnittest(unittest.TestCase):
++ def testNormalFallback(self):
++ d123a = _MakePNG([(b'AbCd', b'')])
++ t123a = _MakePNG([(b'EfGh', b'')])
++ d123b = _MakePNG([(b'IjKl', b'')])
++ _RunBuildTest(self,
++ _Structures(None,
++ _Structure('IDR_A', 'a.png'),
++ _Structure('IDR_B', 'b.png'),
++ ),
++ {'default_123_percent/a.png': d123a,
++ 'tactile_123_percent/a.png': t123a,
++ 'default_123_percent/b.png': d123b,
++ },
++ {'default_123_percent': set([d123a, d123b]),
++ 'tactile_123_percent': set([t123a, d123b]),
++ })
++
++ def testNormalFallbackFailure(self):
++ self.assertRaises(
++ exception.FileNotFound, _RunBuildTest, self,
++ _Structures(
++ None,
++ _Structure('IDR_A', 'a.png'),
++ ), {
++ 'default_100_percent/a.png': _MakePNG([(b'AbCd', b'')]),
++ 'tactile_100_percent/a.png': _MakePNG([(b'EfGh', b'')]),
++ }, {'tactile_123_percent': 'should fail before using this'})
++
++ def testLowresFallback(self):
++ png = _MakePNG([(b'Abcd', b'')])
++ png_with_csCl = _MakePNG([(b'csCl', b''), (b'Abcd', b'')])
++ for outer in (None, False, True):
++ for inner in (None, False, True):
++ args = (
++ self,
++ _Structures(outer,
++ _Structure('IDR_A', 'a.png', inner),
++ ),
++ {'default_100_percent/a.png': png},
++ {'tactile_200_percent': set([png_with_csCl])})
++ if inner or (inner is None and outer):
++ # should fall back to 100%
++ _RunBuildTest(*args, skip_rc=True)
++ else:
++ # shouldn't fall back
++ self.assertRaises(exception.FileNotFound, _RunBuildTest, *args)
++
++ # Test fallback failure with fallback_to_low_resolution=True
++ self.assertRaises(exception.FileNotFound,
++ _RunBuildTest, self,
++ _Structures(True,
++ _Structure('IDR_A', 'a.png'),
++ ),
++ {}, # no files
++ {'tactile_123_percent': 'should fail before using this'})
++
++ def testNoFallbackToDefaultLayout(self):
++ d123a = _MakePNG([(b'AbCd', b'')])
++ t123a = _MakePNG([(b'EfGh', b'')])
++ d123b = _MakePNG([(b'IjKl', b'')])
++ _RunBuildTest(self,
++ _Structures(None,
++ _Structure('IDR_A', 'a.png'),
++ _Structure('IDR_B', 'b.png'),
++ ),
++ {'default_123_percent/a.png': d123a,
++ 'tactile_123_percent/a.png': t123a,
++ 'default_123_percent/b.png': d123b,
++ },
++ {'default_123_percent': set([d123a, d123b]),
++ 'tactile_123_percent': set([t123a]),
++ },
++ layout_fallback=' fallback_to_default_layout="false"')
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/gather/interface.py b/tools/grit/grit/gather/interface.py
+new file mode 100644
+index 0000000000..15d64f9326
+--- /dev/null
++++ b/tools/grit/grit/gather/interface.py
+@@ -0,0 +1,172 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Interface for all gatherers.
++'''
++
++from __future__ import print_function
++
++import os.path
++
++import six
++
++from grit import clique
++from grit import util
++
++
++class GathererBase(object):
++ '''Interface for all gatherer implementations. Subclasses must implement
++ all methods that raise NotImplemented.'''
++
++ def __init__(self, rc_file, extkey=None, encoding='cp1252', is_skeleton=False):
++ '''Initializes the gatherer object's attributes, but does not attempt to
++ read the input file.
++
++ Args:
++ rc_file: The 'file' attribute of the <structure> node (usually the
++ relative path to the source file).
++ extkey: e.g. 'ID_MY_DIALOG'
++ encoding: e.g. 'utf-8'
++ is_skeleton: Indicates whether this gatherer is a skeleton gatherer, in
++ which case we should not do some types of processing on the
++ translateable bits.
++ '''
++ self.rc_file = rc_file
++ self.extkey = extkey
++ self.encoding = encoding
++ # A default uberclique that is local to this object. Users can override
++ # this with the uberclique they are using.
++ self.uberclique = clique.UberClique()
++ # Indicates whether this gatherer is a skeleton gatherer, in which case
++ # we should not do some types of processing on the translateable bits.
++ self.is_skeleton = is_skeleton
++ # Stores the grd node on which this gatherer is running. This allows
++ # evaluating expressions.
++ self.grd_node = None
++
++ def SetAttributes(self, attrs):
++ '''Sets node attributes used by the gatherer.
++
++ By default, this does nothing. If special handling is desired, it should be
++ overridden by the child gatherer.
++
++ Args:
++ attrs: The mapping of node attributes.
++ '''
++ pass
++
++ def SetDefines(self, defines):
++ '''Sets global defines used by the gatherer.
++
++ By default, this does nothing. If special handling is desired, it should be
++ overridden by the child gatherer.
++
++ Args:
++ defines: The mapping of define values.
++ '''
++ pass
++
++ def SetGrdNode(self, node):
++ '''Sets the grd node on which this gatherer is running.
++ '''
++ self.grd_node = node
++
++ def SetUberClique(self, uberclique):
++ '''Overrides the default uberclique so that cliques created by this object
++ become part of the uberclique supplied by the user.
++ '''
++ self.uberclique = uberclique
++
++ def Parse(self):
++ '''Reads and parses the contents of what is being gathered.'''
++ raise NotImplementedError()
++
++ def GetData(self, lang, encoding):
++ '''Returns the data to be added to the DataPack for this node or None if
++ this node does not add a DataPack entry.
++ '''
++ return None
++
++ def GetText(self):
++ '''Returns the text of what is being gathered.'''
++ raise NotImplementedError()
++
++ def GetTextualIds(self):
++ '''Returns the mnemonic IDs that need to be defined for the resource
++ being gathered to compile correctly.'''
++ return []
++
++ def GetCliques(self):
++ '''Returns the MessageClique objects for all translateable portions.'''
++ return []
++
++ def GetInputPath(self):
++ return self.rc_file
++
++ def GetHtmlResourceFilenames(self):
++ """Returns a set of all filenames inlined by this gatherer."""
++ return []
++
++ def Translate(self, lang, pseudo_if_not_available=True,
++ skeleton_gatherer=None, fallback_to_english=False):
++ '''Returns the resource being gathered, with translateable portions filled
++ with the translation for language 'lang'.
++
++ If pseudo_if_not_available is true, a pseudotranslation will be used for any
++ message that doesn't have a real translation available.
++
++ If no translation is available and pseudo_if_not_available is false,
++ fallback_to_english controls the behavior. If it is false, throw an error.
++ If it is true, use the English version of the message as its own
++ "translation".
++
++ If skeleton_gatherer is specified, the translation will use the nontranslateable
++ parts from the gatherer 'skeleton_gatherer', which must be of the same type
++ as 'self'.
++
++ If fallback_to_english
++
++ Args:
++ lang: 'en'
++ pseudo_if_not_available: True | False
++ skeleton_gatherer: other_gatherer
++ fallback_to_english: True | False
++
++ Return:
++ e.g. 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND'
++
++ Raises:
++ grit.exception.NotReady() if used before Parse() has been successfully
++ called.
++ grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' and
++ fallback_to_english are both false and there is no translation for the
++ requested language.
++ '''
++ raise NotImplementedError()
++
++ def SubstituteMessages(self, substituter):
++ '''Applies substitutions to all messages in the gatherer.
++
++ Args:
++ substituter: a grit.util.Substituter object.
++ '''
++ pass
++
++ def SetFilenameExpansionFunction(self, fn):
++ '''Sets a function for rewriting filenames before gathering.'''
++ pass
++
++ # TODO(benrg): Move this elsewhere, since it isn't part of the interface.
++ def _LoadInputFile(self):
++ '''A convenience function for subclasses that loads the contents of the
++ input file.
++ '''
++ if isinstance(self.rc_file, six.string_types):
++ path = self.GetInputPath()
++ # Hack: some unit tests supply an absolute path and no root node.
++ if not os.path.isabs(path):
++ path = self.grd_node.ToRealPath(path)
++ return util.ReadFile(path, self.encoding)
++ else:
++ return self.rc_file.read()
+diff --git a/tools/grit/grit/gather/json_loader.py b/tools/grit/grit/gather/json_loader.py
+new file mode 100644
+index 0000000000..058e5f17ae
+--- /dev/null
++++ b/tools/grit/grit/gather/json_loader.py
+@@ -0,0 +1,27 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++from __future__ import print_function
++
++from grit.gather import interface
++
++
++class JsonLoader(interface.GathererBase):
++ '''A simple gatherer that loads and parses a JSON file.'''
++
++ def Parse(self):
++ '''Reads and parses the text of self._json_text into the data structure in
++ self._data.
++ '''
++ self._json_text = self._LoadInputFile()
++ self._data = None
++
++ globs = {}
++ exec('data = ' + self._json_text, globs)
++ self._data = globs['data']
++
++ def GetData(self, lang, encoding):
++ '''Returns the parsed JSON data.'''
++ assert encoding == 'utf-8'
++ return self._data
+diff --git a/tools/grit/grit/gather/policy_json.py b/tools/grit/grit/gather/policy_json.py
+new file mode 100644
+index 0000000000..6621c5f3c4
+--- /dev/null
++++ b/tools/grit/grit/gather/policy_json.py
+@@ -0,0 +1,325 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Support for "policy_templates.json" format used by the policy template
++generator as a source for generating ADM,ADMX,etc files.'''
++
++from __future__ import print_function
++
++import json
++import sys
++
++import six
++
++from grit.gather import skeleton_gatherer
++from grit import util
++from grit import tclib
++from xml.dom import minidom
++from xml.parsers.expat import ExpatError
++
++
++class PolicyJson(skeleton_gatherer.SkeletonGatherer):
++ '''Collects and translates the following strings from policy_templates.json:
++ - captions, descriptions, labels and Android app support details of policies
++ - captions of enumeration items
++ - misc strings from the 'messages' section
++ Translatable strings may have untranslateable placeholders with the same
++ format that is used in .grd files.
++ '''
++
++ def _AddEndline(self, add_comma):
++ '''Adds an endline to the skeleton tree. If add_comma is true, adds a
++ comma before the endline.
++
++ Args:
++ add_comma: A boolean to add a comma or not.
++ '''
++ self._AddNontranslateableChunk(',\n' if add_comma else '\n')
++
++ def _ParsePlaceholder(self, placeholder, msg):
++ '''Extracts a placeholder from a DOM node and adds it to a tclib Message.
++
++ Args:
++ placeholder: A DOM node of the form:
++ <ph name="PLACEHOLDER_NAME">Placeholder text<ex>Example value</ex></ph>
++ msg: The placeholder is added to this message.
++ '''
++ text = []
++ example_text = []
++ for node1 in placeholder.childNodes:
++ if (node1.nodeType == minidom.Node.TEXT_NODE):
++ text.append(node1.data)
++ elif (node1.nodeType == minidom.Node.ELEMENT_NODE and
++ node1.tagName == 'ex'):
++ for node2 in node1.childNodes:
++ example_text.append(node2.toxml())
++ else:
++ raise Exception('Unexpected element inside a placeholder: ' +
++ node2.toxml())
++ if example_text == []:
++ # In such cases the original text is okay for an example.
++ example_text = text
++
++ replaced_text = self.Escape(''.join(text).strip())
++ replaced_text = replaced_text.replace('$1', self._config['app_name'])
++ replaced_text = replaced_text.replace('$2', self._config['os_name'])
++ replaced_text = replaced_text.replace('$3', self._config['frame_name'])
++
++ msg.AppendPlaceholder(tclib.Placeholder(
++ placeholder.attributes['name'].value,
++ replaced_text,
++ ''.join(example_text).strip()))
++
++ def _ParseMessage(self, string, desc):
++ '''Parses a given string and adds it to the output as a translatable chunk
++ with a given description.
++
++ Args:
++ string: The message string to parse.
++ desc: The description of the message (for the translators).
++ '''
++ msg = tclib.Message(description=desc)
++ xml = '<msg>' + string + '</msg>'
++ try:
++ node = minidom.parseString(xml).childNodes[0]
++ except ExpatError:
++ reason = '''Input isn't valid XML (has < & > been escaped?): ''' + string
++ six.reraise(Exception, reason, sys.exc_info()[2])
++
++ for child in node.childNodes:
++ if child.nodeType == minidom.Node.TEXT_NODE:
++ msg.AppendText(child.data)
++ elif child.nodeType == minidom.Node.ELEMENT_NODE:
++ if child.tagName == 'ph':
++ self._ParsePlaceholder(child, msg)
++ else:
++ raise Exception("Not implemented.")
++ else:
++ raise Exception("Not implemented.")
++ self.skeleton_.append(self.uberclique.MakeClique(msg))
++
++ def _ParseNode(self, node):
++ '''Traverses the subtree of a DOM node, and register a tclib message for
++ all the <message> nodes.
++ '''
++ att_text = []
++ if node.attributes:
++ for key, value in sorted(node.attributes.items()):
++ att_text.append(' %s=\"%s\"' % (key, value))
++ self._AddNontranslateableChunk("<%s%s>" %
++ (node.tagName, ''.join(att_text)))
++ if node.tagName == 'message':
++ msg = tclib.Message(description=node.attributes['desc'])
++ for child in node.childNodes:
++ if child.nodeType == minidom.Node.TEXT_NODE:
++ if msg == None:
++ self._AddNontranslateableChunk(child.data)
++ else:
++ msg.AppendText(child.data)
++ elif child.nodeType == minidom.Node.ELEMENT_NODE:
++ if child.tagName == 'ph':
++ self._ParsePlaceholder(child, msg)
++ else:
++ assert False
++ self.skeleton_.append(self.uberclique.MakeClique(msg))
++ else:
++ for child in node.childNodes:
++ if child.nodeType == minidom.Node.TEXT_NODE:
++ self._AddNontranslateableChunk(child.data)
++ elif node.nodeType == minidom.Node.ELEMENT_NODE:
++ self._ParseNode(child)
++
++ self._AddNontranslateableChunk("</%s>" % node.tagName)
++
++ def _AddIndentedNontranslateableChunk(self, depth, string):
++ '''Adds a nontranslateable chunk of text to the internally stored output.
++
++ Args:
++ depth: The number of double spaces to prepend to the next argument string.
++ string: The chunk of text to add.
++ '''
++ result = []
++ while depth > 0:
++ result.append(' ')
++ depth = depth - 1
++ result.append(string)
++ self._AddNontranslateableChunk(''.join(result))
++
++ def _GetDescription(self, item, item_type, parent_item, key):
++ '''Creates a description for a translatable message. The description gives
++ some context for the person who will translate this message.
++
++ Args:
++ item: A policy or an enumeration item.
++ item_type: 'enum_item' | 'policy'
++ parent_item: The owner of item. (A policy of type group or enum.)
++ key: The name of the key to parse.
++ depth: The level of indentation.
++ '''
++ key_map = {
++ 'desc': 'Description',
++ 'caption': 'Caption',
++ 'label': 'Label',
++ 'arc_support': 'Information about the effect on Android apps'
++ }
++ if item_type == 'policy':
++ return ('%s of the policy named %s [owner(s): %s]' %
++ (key_map[key], item['name'],
++ ','.join(item['owners'] if 'owners' in item else 'unknown')))
++ if item_type == 'enum_item':
++ return ('%s of the option named %s in policy %s [owner(s): %s]' %
++ (key_map[key], item['name'], parent_item['name'],
++ ','.join(parent_item['owners'] if 'owners' in parent_item else 'unknown')))
++ raise Exception('Unexpected type %s' % item_type)
++
++ def _AddSchemaKeys(self, obj, depth):
++ obj_type = type(obj)
++ if obj_type == dict:
++ self._AddNontranslateableChunk('{\n')
++ keys = sorted(obj.keys())
++ for count, (key) in enumerate(keys, 1):
++ json_key = "%s: " % json.dumps(key)
++ self._AddIndentedNontranslateableChunk(depth + 1, json_key)
++ if key == 'description' and type(obj[key]) == str:
++ self._AddNontranslateableChunk("\"")
++ self._ParseMessage(obj[key], 'Description of schema property')
++ self._AddNontranslateableChunk("\"")
++ elif type(obj[key]) in (bool, int, str):
++ self._AddSchemaKeys(obj[key], 0)
++ else:
++ self._AddSchemaKeys(obj[key], depth + 1)
++ self._AddEndline(count < len(keys))
++ self._AddIndentedNontranslateableChunk(depth, '}')
++ elif obj_type == list:
++ self._AddNontranslateableChunk('[\n')
++ for count, (item) in enumerate(obj, 1):
++ self._AddSchemaKeys(item, depth + 1)
++ self._AddEndline(count < len(obj))
++ self._AddIndentedNontranslateableChunk(depth, ']')
++ elif obj_type in (bool, int, str):
++ self._AddIndentedNontranslateableChunk(depth, json.dumps(obj))
++ else:
++ raise Exception('Invalid schema object: %s' % obj)
++
++ def _AddPolicyKey(self, item, item_type, parent_item, key, depth):
++ '''Given a policy/enumeration item and a key, adds that key and its value
++ into the output.
++ E.g.:
++ 'example_value': 123
++ If key indicates that the value is a translatable string, then it is parsed
++ as a translatable string.
++
++ Args:
++ item: A policy or an enumeration item.
++ item_type: 'enum_item' | 'policy'
++ parent_item: The owner of item. (A policy of type group or enum.)
++ key: The name of the key to parse.
++ depth: The level of indentation.
++ '''
++ self._AddIndentedNontranslateableChunk(depth, "%s: " % json.dumps(key))
++ if key in ('desc', 'caption', 'label', 'arc_support'):
++ self._AddNontranslateableChunk("\"")
++ self._ParseMessage(
++ item[key],
++ self._GetDescription(item, item_type, parent_item, key))
++ self._AddNontranslateableChunk("\"")
++ elif key in ('schema', 'validation_schema', 'description_schema'):
++ self._AddSchemaKeys(item[key], depth)
++ else:
++ self._AddNontranslateableChunk(json.dumps(item[key], ensure_ascii=False))
++
++ def _AddItems(self, items, item_type, parent_item, depth):
++ '''Parses and adds a list of items from the JSON file. Items can be policies
++ or parts of an enum policy.
++
++ Args:
++ items: Either a list of policies or a list of dictionaries.
++ item_type: 'enum_item' | 'policy'
++ parent_item: If items contains a list of policies, then this is the policy
++ group that owns them. If items contains a list of enumeration items,
++ then this is the enum policy that holds them.
++ depth: Indicates the depth of our position in the JSON hierarchy. Used to
++ add nice line-indent to the output.
++ '''
++ for item_count, (item1) in enumerate(items, 1):
++ self._AddIndentedNontranslateableChunk(depth, "{\n")
++ keys = sorted(item1.keys())
++ for keys_count, (key) in enumerate(keys, 1):
++ if key == 'items':
++ self._AddIndentedNontranslateableChunk(depth + 1, "\"items\": [\n")
++ self._AddItems(item1['items'], 'enum_item', item1, depth + 2)
++ self._AddIndentedNontranslateableChunk(depth + 1, "]")
++ elif key == 'policies' and all(not isinstance(x, str)
++ for x in item1['policies']):
++ self._AddIndentedNontranslateableChunk(depth + 1, "\"policies\": [\n")
++ self._AddItems(item1['policies'], 'policy', item1, depth + 2)
++ self._AddIndentedNontranslateableChunk(depth + 1, "]")
++ else:
++ self._AddPolicyKey(item1, item_type, parent_item, key, depth + 1)
++ self._AddEndline(keys_count < len(keys))
++ self._AddIndentedNontranslateableChunk(depth, "}")
++ self._AddEndline(item_count < len(items))
++
++ def _AddMessages(self):
++ '''Processed and adds the 'messages' section to the output.'''
++ self._AddNontranslateableChunk(" \"messages\": {\n")
++ messages = self.data['messages'].items()
++ for count, (name, message) in enumerate(messages, 1):
++ self._AddNontranslateableChunk(" %s: {\n" % json.dumps(name))
++ self._AddNontranslateableChunk(" \"text\": \"")
++ self._ParseMessage(message['text'], message['desc'])
++ self._AddNontranslateableChunk("\"\n")
++ self._AddNontranslateableChunk(" }")
++ self._AddEndline(count < len(self.data['messages']))
++ self._AddNontranslateableChunk(" }\n")
++
++ # Although we use the RegexpGatherer base class, we do not use the
++ # _RegExpParse method of that class to implement Parse(). Instead, we
++ # parse using a DOM parser.
++ def Parse(self):
++ if self.have_parsed_:
++ return
++ self.have_parsed_ = True
++
++ self.text_ = self._LoadInputFile()
++ if util.IsExtraVerbose():
++ print(self.text_)
++
++ self.data = eval(self.text_)
++
++ self._AddNontranslateableChunk('{\n')
++ self._AddNontranslateableChunk(" \"policy_definitions\": [\n")
++ self._AddItems(self.data['policy_definitions'], 'policy', None, 2)
++ self._AddNontranslateableChunk(" ],\n")
++ self._AddNontranslateableChunk(" \"policy_atomic_group_definitions\": [\n")
++ if 'policy_atomic_group_definitions' in self.data:
++ self._AddItems(self.data['policy_atomic_group_definitions'],
++ 'policy', None, 2)
++ self._AddNontranslateableChunk(" ],\n")
++ self._AddMessages()
++ self._AddNontranslateableChunk('\n}')
++
++ def Escape(self, text):
++ return json.dumps(text, ensure_ascii=False)[1:-1]
++
++ def SetDefines(self, defines):
++ if not defines:
++ raise Exception('Must pass valid defines')
++
++ if '_chromium' in defines:
++ self._config = {
++ 'build': 'chromium',
++ 'app_name': 'Chromium',
++ 'frame_name': 'Chromium Frame',
++ 'os_name': 'Chromium OS',
++ }
++ elif '_google_chrome' in defines:
++ self._config = {
++ 'build': 'chrome',
++ 'app_name': 'Google Chrome',
++ 'frame_name': 'Google Chrome Frame',
++ 'os_name': 'Google Chrome OS',
++ }
++ else:
++ raise Exception('Unknown build')
+diff --git a/tools/grit/grit/gather/policy_json_unittest.py b/tools/grit/grit/gather/policy_json_unittest.py
+new file mode 100644
+index 0000000000..214cd276aa
+--- /dev/null
++++ b/tools/grit/grit/gather/policy_json_unittest.py
+@@ -0,0 +1,347 @@
++#!/usr/bin/env python
++# Copyright (c) 2011 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.gather.policy_json'''
++
++from __future__ import print_function
++
++import json
++import os
++import re
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit.gather import policy_json
++
++class PolicyJsonUnittest(unittest.TestCase):
++
++ def GetExpectedOutput(self, original):
++ expected = eval(original)
++ for key, message in expected['messages'].items():
++ del message['desc']
++ return expected
++
++ def testEmpty(self):
++ original = """{
++ 'policy_definitions': [],
++ 'policy_atomic_group_definitions': [],
++ 'messages': {}
++ }"""
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 0)
++ self.failUnless(eval(original) == json.loads(gatherer.Translate('en')))
++
++ def testGeneralPolicy(self):
++ original = (
++ "{"
++ " 'policy_definitions': ["
++ " {"
++ " 'name': 'HomepageLocation',"
++ " 'type': 'string',"
++ " 'owners': ['foo@bar.com'],"
++ " 'supported_on': ['chrome.*:8-'],"
++ " 'features': {'dynamic_refresh': 1},"
++ " 'example_value': 'http://chromium.org',"
++ " 'caption': 'nothing special 1',"
++ " 'desc': 'nothing special 2',"
++ " 'label': 'nothing special 3',"
++ " },"
++ " ],"
++ " 'policy_atomic_group_definitions': [],"
++ " 'messages': {"
++ " 'msg_identifier': {"
++ " 'text': 'nothing special 3',"
++ " 'desc': 'nothing special descr 3',"
++ " }"
++ " }"
++ "}")
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 4)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ def testEnum(self):
++ original = (
++ "{"
++ " 'policy_definitions': ["
++ " {"
++ " 'name': 'Policy1',"
++ " 'owners': ['a@b'],"
++ " 'items': ["
++ " {"
++ " 'name': 'Item1',"
++ " 'caption': 'nothing special',"
++ " }"
++ " ]"
++ " },"
++ " ],"
++ " 'policy_atomic_group_definitions': [],"
++ " 'messages': {}"
++ "}")
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ def testSchema(self):
++ original = ("{"
++ " 'policy_definitions': ["
++ " {"
++ " 'name': 'Policy1',"
++ " 'schema': {"
++ " 'type': 'object',"
++ " 'properties': {"
++ " 'outer': {"
++ " 'description': 'outer description',"
++ " 'type': 'object',"
++ " 'inner': {"
++ " 'description': 'inner description',"
++ " 'type': 'integer', 'minimum': 0, 'maximum': 100"
++ " },"
++ " 'inner2': {"
++ " 'description': 'inner2 description',"
++ " 'type': 'integer',"
++ " 'enum': [ 1, 2, 3 ],"
++ " 'sensitiveValue': True"
++ " },"
++ " },"
++ " },"
++ " },"
++ " 'caption': 'nothing special',"
++ " 'owners': ['a@b']"
++ " },"
++ " ],"
++ " 'policy_atomic_group_definitions': [],"
++ " 'messages': {}"
++ "}")
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 4)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ def testValidationSchema(self):
++ original = ("{"
++ " 'policy_definitions': ["
++ " {"
++ " 'name': 'Policy1',"
++ " 'owners': ['a@b'],"
++ " 'validation_schema': {"
++ " 'type': 'object',"
++ " 'properties': {"
++ " 'description': 'properties description',"
++ " 'type': 'object',"
++ " },"
++ " },"
++ " },"
++ " ],"
++ " 'policy_atomic_group_definitions': [],"
++ " 'messages': {}"
++ "}")
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ def testDescriptionSchema(self):
++ original = ("{"
++ " 'policy_definitions': ["
++ " {"
++ " 'name': 'Policy1',"
++ " 'owners': ['a@b'],"
++ " 'description_schema': {"
++ " 'type': 'object',"
++ " 'properties': {"
++ " 'description': 'properties description',"
++ " 'type': 'object',"
++ " },"
++ " },"
++ " },"
++ " ],"
++ " 'policy_atomic_group_definitions': [],"
++ " 'messages': {}"
++ "}")
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ # Keeping for backwards compatibility.
++ def testSubPolicyOldFormat(self):
++ original = (
++ "{"
++ " 'policy_definitions': ["
++ " {"
++ " 'type': 'group',"
++ " 'policies': ["
++ " {"
++ " 'name': 'Policy1',"
++ " 'caption': 'nothing special',"
++ " 'owners': ['a@b']"
++ " }"
++ " ]"
++ " }"
++ " ],"
++ " 'policy_atomic_group_definitions': [],"
++ " 'messages': {}"
++ "}")
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ def testSubPolicyNewFormat(self):
++ original = (
++ "{"
++ " 'policy_definitions': ["
++ " {"
++ " 'type': 'group',"
++ " 'policies': ['Policy1']"
++ " },"
++ " {"
++ " 'name': 'Policy1',"
++ " 'caption': 'nothing special',"
++ " 'owners': ['a@b']"
++ " }"
++ " ],"
++ " 'policy_atomic_group_definitions': [],"
++ " 'messages': {}"
++ "}")
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ def testEscapingAndLineBreaks(self):
++ original = """{
++ 'policy_definitions': [],
++ 'policy_atomic_group_definitions': [],
++ 'messages': {
++ 'msg1': {
++ # The following line will contain two backslash characters when it
++ # ends up in eval().
++ 'text': '''backslashes, Sir? \\\\''',
++ 'desc': ''
++ },
++ 'msg2': {
++ 'text': '''quotes, Madam? "''',
++ 'desc': ''
++ },
++ 'msg3': {
++ # The following line will contain two backslash characters when it
++ # ends up in eval().
++ 'text': 'backslashes, Sir? \\\\',
++ 'desc': ''
++ },
++ 'msg4': {
++ 'text': "quotes, Madam? '",
++ 'desc': ''
++ },
++ 'msg5': {
++ 'text': '''what happens
++with a newline?''',
++ 'desc': ''
++ },
++ 'msg6': {
++ # The following line will contain a backslash+n when it ends up in
++ # eval().
++ 'text': 'what happens\\nwith a newline? (Episode 1)',
++ 'desc': ''
++ }
++ }
++}"""
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 6)
++ expected = self.GetExpectedOutput(original)
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++
++ def testPlaceholdersChromium(self):
++ original = """{
++ "policy_definitions": [
++ {
++ "name": "Policy1",
++ "caption": "Please install\\n<ph name=\\"PRODUCT_NAME\\">$1<ex>Google Chrome</ex></ph>.",
++ "owners": "a@b"
++ }
++ ],
++ "policy_atomic_group_definitions": [],
++ "messages": {}
++}"""
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.SetDefines({'_chromium': True})
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ expected = json.loads(re.sub('<ph.*ph>', 'Chromium', original))
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++ self.failUnless(gatherer.GetCliques()[0].translateable)
++ msg = gatherer.GetCliques()[0].GetMessage()
++ self.failUnless(len(msg.GetPlaceholders()) == 1)
++ ph = msg.GetPlaceholders()[0]
++ self.failUnless(ph.GetOriginal() == 'Chromium')
++ self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
++ self.failUnless(ph.GetExample() == 'Google Chrome')
++
++ def testPlaceholdersChrome(self):
++ original = """{
++ "policy_definitions": [
++ {
++ "name": "Policy1",
++ "caption": "Please install\\n<ph name=\\"PRODUCT_NAME\\">$1<ex>Google Chrome</ex></ph>.",
++ "owners": "a@b"
++ }
++ ],
++ "policy_atomic_group_definitions": [],
++ "messages": {}
++}"""
++ gatherer = policy_json.PolicyJson(StringIO(original))
++ gatherer.SetDefines({'_google_chrome': True})
++ gatherer.Parse()
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ expected = json.loads(re.sub('<ph.*ph>', 'Google Chrome', original))
++ self.failUnless(expected == json.loads(gatherer.Translate('en')))
++ self.failUnless(gatherer.GetCliques()[0].translateable)
++ msg = gatherer.GetCliques()[0].GetMessage()
++ self.failUnless(len(msg.GetPlaceholders()) == 1)
++ ph = msg.GetPlaceholders()[0]
++ self.failUnless(ph.GetOriginal() == 'Google Chrome')
++ self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
++ self.failUnless(ph.GetExample() == 'Google Chrome')
++
++ def testGetDescription(self):
++ gatherer = policy_json.PolicyJson({})
++ gatherer.SetDefines({'_google_chrome': True})
++ self.assertEquals(
++ gatherer._GetDescription({'name': 'Policy1', 'owners': ['a@b']},
++ 'policy', None, 'desc'),
++ 'Description of the policy named Policy1 [owner(s): a@b]')
++ self.assertEquals(
++ gatherer._GetDescription({'name': 'Plcy2', 'owners': ['a@b', 'c@d']},
++ 'policy', None, 'caption'),
++ 'Caption of the policy named Plcy2 [owner(s): a@b,c@d]')
++ self.assertEquals(
++ gatherer._GetDescription({'name': 'Plcy3', 'owners': ['a@b']},
++ 'policy', None, 'label'),
++ 'Label of the policy named Plcy3 [owner(s): a@b]')
++ self.assertEquals(
++ gatherer._GetDescription({'name': 'Item'}, 'enum_item',
++ {'name': 'Plcy', 'owners': ['a@b']}, 'caption'),
++ 'Caption of the option named Item in policy Plcy [owner(s): a@b]')
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/gather/rc.py b/tools/grit/grit/gather/rc.py
+new file mode 100644
+index 0000000000..dd091d1e18
+--- /dev/null
++++ b/tools/grit/grit/gather/rc.py
+@@ -0,0 +1,343 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Support for gathering resources from RC files.
++'''
++
++from __future__ import print_function
++
++import re
++
++from grit import exception
++from grit import lazy_re
++from grit import tclib
++
++from grit.gather import regexp
++
++
++# Find portions that need unescaping in resource strings. We need to be
++# careful that a \\n is matched _first_ as a \\ rather than matching as
++# a \ followed by a \n.
++# TODO(joi) Handle ampersands if we decide to change them into <ph>
++# TODO(joi) May need to handle other control characters than \n
++_NEED_UNESCAPE = lazy_re.compile(r'""|\\\\|\\n|\\t')
++
++# Find portions that need escaping to encode string as a resource string.
++_NEED_ESCAPE = lazy_re.compile(r'"|\n|\t|\\|\&nbsp\;')
++
++# How to escape certain characters
++_ESCAPE_CHARS = {
++ '"' : '""',
++ '\n' : '\\n',
++ '\t' : '\\t',
++ '\\' : '\\\\',
++ '&nbsp;' : ' '
++}
++
++# How to unescape certain strings
++_UNESCAPE_CHARS = dict([[value, key] for key, value in _ESCAPE_CHARS.items()])
++
++
++
++class Section(regexp.RegexpGatherer):
++ '''A section from a resource file.'''
++
++ @staticmethod
++ def Escape(text):
++ '''Returns a version of 'text' with characters escaped that need to be
++ for inclusion in a resource section.'''
++ def Replace(match):
++ return _ESCAPE_CHARS[match.group()]
++ return _NEED_ESCAPE.sub(Replace, text)
++
++ @staticmethod
++ def UnEscape(text):
++ '''Returns a version of 'text' with escaped characters unescaped.'''
++ def Replace(match):
++ return _UNESCAPE_CHARS[match.group()]
++ return _NEED_UNESCAPE.sub(Replace, text)
++
++ def _RegExpParse(self, rexp, text_to_parse):
++ '''Overrides _RegExpParse to add shortcut group handling. Otherwise
++ the same.
++ '''
++ super(Section, self)._RegExpParse(rexp, text_to_parse)
++
++ if not self.is_skeleton and len(self.GetTextualIds()) > 0:
++ group_name = self.GetTextualIds()[0]
++ for c in self.GetCliques():
++ c.AddToShortcutGroup(group_name)
++
++ def ReadSection(self):
++ rc_text = self._LoadInputFile()
++
++ out = ''
++ begin_count = 0
++ assert self.extkey
++ first_line_re = re.compile(r'\s*' + self.extkey + r'\b')
++ for line in rc_text.splitlines(True):
++ if out or first_line_re.match(line):
++ out += line
++
++ # we stop once we reach the END for the outermost block.
++ begin_count_was = begin_count
++ if len(out) > 0 and line.strip() == 'BEGIN':
++ begin_count += 1
++ elif len(out) > 0 and line.strip() == 'END':
++ begin_count -= 1
++ if begin_count_was == 1 and begin_count == 0:
++ break
++
++ if len(out) == 0:
++ raise exception.SectionNotFound('%s in file %s' % (self.extkey, self.rc_file))
++
++ self.text_ = out.strip()
++
++
++class Dialog(Section):
++ '''A resource section that contains a dialog resource.'''
++
++ # A typical dialog resource section looks like this:
++ #
++ # IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
++ # STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++ # CAPTION "About"
++ # FONT 8, "System", 0, 0, 0x0
++ # BEGIN
++ # ICON IDI_KLONK,IDC_MYICON,14,9,20,20
++ # LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
++ # SS_NOPREFIX
++ # LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
++ # DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
++ # CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
++ # BS_AUTORADIOBUTTON,46,51,84,10
++ # END
++
++ # We are using a sorted set of keys, and we assume that the
++ # group name used for descriptions (type) will come after the "text"
++ # group in alphabetical order. We also assume that there cannot be
++ # more than one description per regular expression match.
++ # If that's not the case some descriptions will be clobbered.
++ dialog_re_ = lazy_re.compile(r'''
++ # The dialog's ID in the first line
++ (?P<id1>[A-Z0-9_]+)\s+DIALOG(EX)?
++ |
++ # The caption of the dialog
++ (?P<type1>CAPTION)\s+"(?P<text1>.*?([^"]|""))"\s
++ |
++ # Lines for controls that have text and an ID
++ \s+(?P<type2>[A-Z]+)\s+"(?P<text2>.*?([^"]|"")?)"\s*,\s*(?P<id2>[A-Z0-9_]+)\s*,
++ |
++ # Lines for controls that have text only
++ \s+(?P<type3>[A-Z]+)\s+"(?P<text3>.*?([^"]|"")?)"\s*,
++ |
++ # Lines for controls that reference other resources
++ \s+[A-Z]+\s+[A-Z0-9_]+\s*,\s*(?P<id3>[A-Z0-9_]*[A-Z][A-Z0-9_]*)
++ |
++ # This matches "NOT SOME_STYLE" so that it gets consumed and doesn't get
++ # matched by the next option (controls that have only an ID and then just
++ # numbers)
++ \s+NOT\s+[A-Z][A-Z0-9_]+
++ |
++ # Lines for controls that have only an ID and then just numbers
++ \s+[A-Z]+\s+(?P<id4>[A-Z0-9_]*[A-Z][A-Z0-9_]*)\s*,
++ ''', re.MULTILINE | re.VERBOSE)
++
++ def Parse(self):
++ '''Knows how to parse dialog resource sections.'''
++ self.ReadSection()
++ self._RegExpParse(self.dialog_re_, self.text_)
++
++
++class Menu(Section):
++ '''A resource section that contains a menu resource.'''
++
++ # A typical menu resource section looks something like this:
++ #
++ # IDC_KLONK MENU
++ # BEGIN
++ # POPUP "&File"
++ # BEGIN
++ # MENUITEM "E&xit", IDM_EXIT
++ # MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
++ # POPUP "gonk"
++ # BEGIN
++ # MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
++ # END
++ # END
++ # POPUP "&Help"
++ # BEGIN
++ # MENUITEM "&About ...", IDM_ABOUT
++ # END
++ # END
++
++ # Description used for the messages generated for menus, to explain to
++ # the translators how to handle them.
++ MENU_MESSAGE_DESCRIPTION = (
++ 'This message represents a menu. Each of the items appears in sequence '
++ '(some possibly within sub-menus) in the menu. The XX01XX placeholders '
++ 'serve to separate items. Each item contains an & (ampersand) character '
++ 'in front of the keystroke that should be used as a shortcut for that item '
++ 'in the menu. Please make sure that no two items in the same menu share '
++ 'the same shortcut.'
++ )
++
++ # A dandy regexp to suck all the IDs and translateables out of a menu
++ # resource
++ menu_re_ = lazy_re.compile(r'''
++ # Match the MENU ID on the first line
++ ^(?P<id1>[A-Z0-9_]+)\s+MENU
++ |
++ # Match the translateable caption for a popup menu
++ POPUP\s+"(?P<text1>.*?([^"]|""))"\s
++ |
++ # Match the caption & ID of a MENUITEM
++ MENUITEM\s+"(?P<text2>.*?([^"]|""))"\s*,\s*(?P<id2>[A-Z0-9_]+)
++ ''', re.MULTILINE | re.VERBOSE)
++
++ def Parse(self):
++ '''Knows how to parse menu resource sections. Because it is important that
++ menu shortcuts are unique within the menu, we return each menu as a single
++ message with placeholders to break up the different menu items, rather than
++ return a single message per menu item. we also add an automatic description
++ with instructions for the translators.'''
++ self.ReadSection()
++ self.single_message_ = tclib.Message(description=self.MENU_MESSAGE_DESCRIPTION)
++ self._RegExpParse(self.menu_re_, self.text_)
++
++
++class Version(Section):
++ '''A resource section that contains a VERSIONINFO resource.'''
++
++ # A typical version info resource can look like this:
++ #
++ # VS_VERSION_INFO VERSIONINFO
++ # FILEVERSION 1,0,0,1
++ # PRODUCTVERSION 1,0,0,1
++ # FILEFLAGSMASK 0x3fL
++ # #ifdef _DEBUG
++ # FILEFLAGS 0x1L
++ # #else
++ # FILEFLAGS 0x0L
++ # #endif
++ # FILEOS 0x4L
++ # FILETYPE 0x2L
++ # FILESUBTYPE 0x0L
++ # BEGIN
++ # BLOCK "StringFileInfo"
++ # BEGIN
++ # BLOCK "040904e4"
++ # BEGIN
++ # VALUE "CompanyName", "TODO: <Company name>"
++ # VALUE "FileDescription", "TODO: <File description>"
++ # VALUE "FileVersion", "1.0.0.1"
++ # VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
++ # VALUE "InternalName", "res_format_test.dll"
++ # VALUE "OriginalFilename", "res_format_test.dll"
++ # VALUE "ProductName", "TODO: <Product name>"
++ # VALUE "ProductVersion", "1.0.0.1"
++ # END
++ # END
++ # BLOCK "VarFileInfo"
++ # BEGIN
++ # VALUE "Translation", 0x409, 1252
++ # END
++ # END
++ #
++ #
++ # In addition to the above fields, VALUE fields named "Comments" and
++ # "LegalTrademarks" may also be translateable.
++
++ version_re_ = lazy_re.compile(r'''
++ # Match the ID on the first line
++ ^(?P<id1>[A-Z0-9_]+)\s+VERSIONINFO
++ |
++ # Match all potentially translateable VALUE sections
++ \s+VALUE\s+"
++ (
++ CompanyName|FileDescription|LegalCopyright|
++ ProductName|Comments|LegalTrademarks
++ )",\s+"(?P<text1>.*?([^"]|""))"\s
++ ''', re.MULTILINE | re.VERBOSE)
++
++ def Parse(self):
++ '''Knows how to parse VERSIONINFO resource sections.'''
++ self.ReadSection()
++ self._RegExpParse(self.version_re_, self.text_)
++
++ # TODO(joi) May need to override the Translate() method to change the
++ # "Translation" VALUE block to indicate the correct language code.
++
++
++class RCData(Section):
++ '''A resource section that contains some data .'''
++
++ # A typical rcdataresource section looks like this:
++ #
++ # IDR_BLAH RCDATA { 1, 2, 3, 4 }
++
++ dialog_re_ = lazy_re.compile(r'''
++ ^(?P<id1>[A-Z0-9_]+)\s+RCDATA\s+(DISCARDABLE)?\s+\{.*?\}
++ ''', re.MULTILINE | re.VERBOSE | re.DOTALL)
++
++ def Parse(self):
++ '''Implementation for resource types w/braces (not BEGIN/END)
++ '''
++ rc_text = self._LoadInputFile()
++
++ out = ''
++ begin_count = 0
++ openbrace_count = 0
++ assert self.extkey
++ first_line_re = re.compile(r'\s*' + self.extkey + r'\b')
++ for line in rc_text.splitlines(True):
++ if out or first_line_re.match(line):
++ out += line
++
++ # We stop once the braces balance (could happen in one line).
++ begin_count_was = begin_count
++ if len(out) > 0:
++ openbrace_count += line.count('{')
++ begin_count += line.count('{')
++ begin_count -= line.count('}')
++ if ((begin_count_was == 1 and begin_count == 0) or
++ (openbrace_count > 0 and begin_count == 0)):
++ break
++
++ if len(out) == 0:
++ raise exception.SectionNotFound('%s in file %s' % (self.extkey, self.rc_file))
++
++ self.text_ = out
++
++ self._RegExpParse(self.dialog_re_, out)
++
++
++class Accelerators(Section):
++ '''An ACCELERATORS table.
++ '''
++
++ # A typical ACCELERATORS section looks like this:
++ #
++ # IDR_ACCELERATOR1 ACCELERATORS
++ # BEGIN
++ # "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
++ # "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
++ # VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
++ # END
++
++ accelerators_re_ = lazy_re.compile(r'''
++ # Match the ID on the first line
++ ^(?P<id1>[A-Z0-9_]+)\s+ACCELERATORS\s+
++ |
++ # Match accelerators specified as VK_XXX
++ \s+VK_[A-Z0-9_]+,\s*(?P<id2>[A-Z0-9_]+)\s*,
++ |
++ # Match accelerators specified as e.g. "^C"
++ \s+"[^"]*",\s+(?P<id3>[A-Z0-9_]+)\s*,
++ ''', re.MULTILINE | re.VERBOSE)
++
++ def Parse(self):
++ '''Knows how to parse ACCELERATORS resource sections.'''
++ self.ReadSection()
++ self._RegExpParse(self.accelerators_re_, self.text_)
+diff --git a/tools/grit/grit/gather/rc_unittest.py b/tools/grit/grit/gather/rc_unittest.py
+new file mode 100644
+index 0000000000..3c26a4342a
+--- /dev/null
++++ b/tools/grit/grit/gather/rc_unittest.py
+@@ -0,0 +1,372 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.gather.rc'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit.gather import rc
++from grit import util
++
++
++class RcUnittest(unittest.TestCase):
++
++ part_we_want = '''IDC_KLONKACC ACCELERATORS
++BEGIN
++ "?", IDM_ABOUT, ASCII, ALT
++ "/", IDM_ABOUT, ASCII, ALT
++END'''
++
++ def testSectionFromFile(self):
++ buf = '''IDC_SOMETHINGELSE BINGO
++BEGIN
++ BLA BLA
++ BLA BLA
++END
++%s
++
++IDC_KLONK BINGOBONGO
++BEGIN
++ HONGO KONGO
++END
++''' % self.part_we_want
++
++ f = StringIO(buf)
++
++ out = rc.Section(f, 'IDC_KLONKACC')
++ out.ReadSection()
++ self.failUnless(out.GetText() == self.part_we_want)
++
++ out = rc.Section(util.PathFromRoot(r'grit/testdata/klonk.rc'),
++ 'IDC_KLONKACC',
++ encoding='utf-16')
++ out.ReadSection()
++ out_text = out.GetText().replace('\t', '')
++ out_text = out_text.replace(' ', '')
++ self.part_we_want = self.part_we_want.replace(' ', '')
++ self.failUnless(out_text.strip() == self.part_we_want.strip())
++
++
++ def testDialog(self):
++ dlg = rc.Dialog(StringIO('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "About"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
++ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
++ SS_NOPREFIX
++ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
++ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
++ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
++ BS_AUTORADIOBUTTON,46,51,84,10
++ // try a line where the ID is on the continuation line
++ LTEXT "blablablabla blablabla blablablablablablablabla blablabla",
++ ID_SMURF, whatever...
++END
++'''), 'IDD_ABOUTBOX')
++ dlg.Parse()
++ self.failUnless(len(dlg.GetTextualIds()) == 7)
++ self.failUnless(len(dlg.GetCliques()) == 6)
++ self.failUnless(dlg.GetCliques()[1].GetMessage().GetRealContent() ==
++ 'klonk Version "yibbee" 1.0')
++
++ transl = dlg.Translate('en')
++ self.failUnless(transl.strip() == dlg.GetText().strip())
++
++ def testAlternateSkeleton(self):
++ dlg = rc.Dialog(StringIO('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "About"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ LTEXT "Yipee skippy",IDC_STATIC,49,10,119,8,
++ SS_NOPREFIX
++END
++'''), 'IDD_ABOUTBOX')
++ dlg.Parse()
++
++ alt_dlg = rc.Dialog(StringIO('''IDD_ABOUTBOX DIALOGEX 040704, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "XXXXXXXXX"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ LTEXT "XXXXXXXXXXXXXXXXX",IDC_STATIC,110978,10,119,8,
++ SS_NOPREFIX
++END
++'''), 'IDD_ABOUTBOX')
++ alt_dlg.Parse()
++
++ transl = dlg.Translate('en', skeleton_gatherer=alt_dlg)
++ self.failUnless(transl.count('040704') and
++ transl.count('110978'))
++ self.failUnless(transl.count('Yipee skippy'))
++
++ def testMenu(self):
++ menu = rc.Menu(StringIO('''IDC_KLONK MENU
++BEGIN
++ POPUP "&File """
++ BEGIN
++ MENUITEM "E&xit", IDM_EXIT
++ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
++ POPUP "gonk"
++ BEGIN
++ MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
++ END
++ MENUITEM "This is a very long menu caption to try to see if we can make the ID go to a continuation line, blablabla blablabla bla blabla blablabla blablabla blablabla blablabla...",
++ ID_FILE_THISISAVERYLONGMENUCAPTIONTOTRYTOSEEIFWECANMAKETHEIDGOTOACONTINUATIONLINE
++ END
++ POPUP "&Help"
++ BEGIN
++ MENUITEM "&About ...", IDM_ABOUT
++ END
++END'''), 'IDC_KLONK')
++
++ menu.Parse()
++ self.failUnless(len(menu.GetTextualIds()) == 6)
++ self.failUnless(len(menu.GetCliques()) == 1)
++ self.failUnless(len(menu.GetCliques()[0].GetMessage().GetPlaceholders()) ==
++ 9)
++
++ transl = menu.Translate('en')
++ self.failUnless(transl.strip() == menu.GetText().strip())
++
++ def testVersion(self):
++ version = rc.Version(StringIO('''
++VS_VERSION_INFO VERSIONINFO
++ FILEVERSION 1,0,0,1
++ PRODUCTVERSION 1,0,0,1
++ FILEFLAGSMASK 0x3fL
++#ifdef _DEBUG
++ FILEFLAGS 0x1L
++#else
++ FILEFLAGS 0x0L
++#endif
++ FILEOS 0x4L
++ FILETYPE 0x2L
++ FILESUBTYPE 0x0L
++BEGIN
++ BLOCK "StringFileInfo"
++ BEGIN
++ BLOCK "040904e4"
++ BEGIN
++ VALUE "CompanyName", "TODO: <Company name>"
++ VALUE "FileDescription", "TODO: <File description>"
++ VALUE "FileVersion", "1.0.0.1"
++ VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
++ VALUE "InternalName", "res_format_test.dll"
++ VALUE "OriginalFilename", "res_format_test.dll"
++ VALUE "ProductName", "TODO: <Product name>"
++ VALUE "ProductVersion", "1.0.0.1"
++ END
++ END
++ BLOCK "VarFileInfo"
++ BEGIN
++ VALUE "Translation", 0x409, 1252
++ END
++END
++'''.strip()), 'VS_VERSION_INFO')
++ version.Parse()
++ self.failUnless(len(version.GetTextualIds()) == 1)
++ self.failUnless(len(version.GetCliques()) == 4)
++
++ transl = version.Translate('en')
++ self.failUnless(transl.strip() == version.GetText().strip())
++
++
++ def testRegressionDialogBox(self):
++ dialog = rc.Dialog(StringIO('''
++IDD_SIDEBAR_WEATHER_PANEL_PROPPAGE DIALOGEX 0, 0, 205, 157
++STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
++FONT 8, "MS Shell Dlg", 400, 0, 0x1
++BEGIN
++ EDITTEXT IDC_SIDEBAR_WEATHER_NEW_CITY,3,27,112,14,ES_AUTOHSCROLL
++ DEFPUSHBUTTON "Add Location",IDC_SIDEBAR_WEATHER_ADD,119,27,50,14
++ LISTBOX IDC_SIDEBAR_WEATHER_CURR_CITIES,3,48,127,89,
++ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
++ PUSHBUTTON "Move Up",IDC_SIDEBAR_WEATHER_MOVE_UP,134,104,50,14
++ PUSHBUTTON "Move Down",IDC_SIDEBAR_WEATHER_MOVE_DOWN,134,121,50,14
++ PUSHBUTTON "Remove",IDC_SIDEBAR_WEATHER_DELETE,134,48,50,14
++ LTEXT "To see current weather conditions and forecasts in the USA, enter the zip code (example: 94043) or city and state (example: Mountain View, CA).",
++ IDC_STATIC,3,0,199,25
++ CONTROL "Fahrenheit",IDC_SIDEBAR_WEATHER_FAHRENHEIT,"Button",
++ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,3,144,51,10
++ CONTROL "Celsius",IDC_SIDEBAR_WEATHER_CELSIUS,"Button",
++ BS_AUTORADIOBUTTON,57,144,38,10
++END'''.strip()), 'IDD_SIDEBAR_WEATHER_PANEL_PROPPAGE')
++ dialog.Parse()
++ self.failUnless(len(dialog.GetTextualIds()) == 10)
++
++
++ def testRegressionDialogBox2(self):
++ dialog = rc.Dialog(StringIO('''
++IDD_SIDEBAR_EMAIL_PANEL_PROPPAGE DIALOG DISCARDABLE 0, 0, 264, 220
++STYLE WS_CHILD
++FONT 8, "MS Shell Dlg"
++BEGIN
++ GROUPBOX "Email Filters",IDC_STATIC,7,3,250,190
++ LTEXT "Click Add Filter to create the email filter.",IDC_STATIC,16,41,130,9
++ PUSHBUTTON "Add Filter...",IDC_SIDEBAR_EMAIL_ADD_FILTER,196,38,50,14
++ PUSHBUTTON "Remove",IDC_SIDEBAR_EMAIL_REMOVE,196,174,50,14
++ PUSHBUTTON "", IDC_SIDEBAR_EMAIL_HIDDEN, 200, 178, 5, 5, NOT WS_VISIBLE
++ LISTBOX IDC_SIDEBAR_EMAIL_LIST,16,60,230,108,
++ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
++ LTEXT "You can prevent certain emails from showing up in the sidebar with a filter.",
++ IDC_STATIC,16,18,234,18
++END'''.strip()), 'IDD_SIDEBAR_EMAIL_PANEL_PROPPAGE')
++ dialog.Parse()
++ self.failUnless('IDC_SIDEBAR_EMAIL_HIDDEN' in dialog.GetTextualIds())
++
++
++ def testRegressionMenuId(self):
++ menu = rc.Menu(StringIO('''
++IDR_HYPERMENU_FOLDER MENU
++BEGIN
++ POPUP "HyperFolder"
++ BEGIN
++ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
++ END
++END'''.strip()), 'IDR_HYPERMENU_FOLDER')
++ menu.Parse()
++ self.failUnless(len(menu.GetTextualIds()) == 2)
++
++ def testRegressionNewlines(self):
++ menu = rc.Menu(StringIO('''
++IDR_HYPERMENU_FOLDER MENU
++BEGIN
++ POPUP "Hyper\\nFolder"
++ BEGIN
++ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
++ END
++END'''.strip()), 'IDR_HYPERMENU_FOLDER')
++ menu.Parse()
++ transl = menu.Translate('en')
++ # Shouldn't find \\n (the \n shouldn't be changed to \\n)
++ self.failUnless(transl.find('\\\\n') == -1)
++
++ def testRegressionTabs(self):
++ menu = rc.Menu(StringIO('''
++IDR_HYPERMENU_FOLDER MENU
++BEGIN
++ POPUP "Hyper\\tFolder"
++ BEGIN
++ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
++ END
++END'''.strip()), 'IDR_HYPERMENU_FOLDER')
++ menu.Parse()
++ transl = menu.Translate('en')
++ # Shouldn't find \\t (the \t shouldn't be changed to \\t)
++ self.failUnless(transl.find('\\\\t') == -1)
++
++ def testEscapeUnescape(self):
++ original = 'Hello "bingo"\n How\\are\\you\\n?'
++ escaped = rc.Section.Escape(original)
++ self.failUnless(escaped == 'Hello ""bingo""\\n How\\\\are\\\\you\\\\n?')
++ unescaped = rc.Section.UnEscape(escaped)
++ self.failUnless(unescaped == original)
++
++ def testRegressionPathsWithSlashN(self):
++ original = '..\\\\..\\\\trs\\\\res\\\\nav_first.gif'
++ unescaped = rc.Section.UnEscape(original)
++ self.failUnless(unescaped == '..\\..\\trs\\res\\nav_first.gif')
++
++ def testRegressionDialogItemsTextOnly(self):
++ dialog = rc.Dialog(StringIO('''IDD_OPTIONS_SEARCH DIALOGEX 0, 0, 280, 292
++STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
++ WS_DISABLED | WS_CAPTION | WS_SYSMENU
++CAPTION "Search"
++FONT 8, "MS Shell Dlg", 400, 0, 0x1
++BEGIN
++ GROUPBOX "Select search buttons and options",-1,7,5,266,262
++ CONTROL "",IDC_OPTIONS,"SysTreeView32",TVS_DISABLEDRAGDROP |
++ WS_BORDER | WS_TABSTOP | 0x800,16,19,248,218
++ LTEXT "Use Google site:",-1,26,248,52,8
++ COMBOBOX IDC_GOOGLE_HOME,87,245,177,256,CBS_DROPDOWNLIST |
++ WS_VSCROLL | WS_TABSTOP
++ PUSHBUTTON "Restore Defaults...",IDC_RESET,187,272,86,14
++END'''), 'IDD_OPTIONS_SEARCH')
++ dialog.Parse()
++ translateables = [c.GetMessage().GetRealContent()
++ for c in dialog.GetCliques()]
++ self.failUnless('Select search buttons and options' in translateables)
++ self.failUnless('Use Google site:' in translateables)
++
++ def testAccelerators(self):
++ acc = rc.Accelerators(StringIO('''\
++IDR_ACCELERATOR1 ACCELERATORS
++BEGIN
++ "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
++ "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
++ VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
++END
++'''), 'IDR_ACCELERATOR1')
++ acc.Parse()
++ self.failUnless(len(acc.GetTextualIds()) == 4)
++ self.failUnless(len(acc.GetCliques()) == 0)
++
++ transl = acc.Translate('en')
++ self.failUnless(transl.strip() == acc.GetText().strip())
++
++
++ def testRegressionEmptyString(self):
++ dlg = rc.Dialog(StringIO('''\
++IDD_CONFIRM_QUIT_GD_DLG DIALOGEX 0, 0, 267, 108
++STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
++ WS_CAPTION
++EXSTYLE WS_EX_TOPMOST
++CAPTION "Google Desktop"
++FONT 8, "MS Shell Dlg", 400, 0, 0x1
++BEGIN
++ DEFPUSHBUTTON "&Yes",IDYES,82,87,50,14
++ PUSHBUTTON "&No",IDNO,136,87,50,14
++ ICON 32514,IDC_STATIC,7,9,21,20
++ EDITTEXT IDC_TEXTBOX,34,7,231,60,ES_MULTILINE | ES_READONLY | NOT WS_BORDER
++ CONTROL "",
++ IDC_ENABLE_GD_AUTOSTART,"Button",BS_AUTOCHECKBOX |
++ WS_TABSTOP,33,70,231,10
++END'''), 'IDD_CONFIRM_QUIT_GD_DLG')
++ dlg.Parse()
++
++ def Check():
++ self.failUnless(transl.count('IDC_ENABLE_GD_AUTOSTART'))
++ self.failUnless(transl.count('END'))
++
++ transl = dlg.Translate('de', pseudo_if_not_available=True,
++ fallback_to_english=True)
++ Check()
++ transl = dlg.Translate('de', pseudo_if_not_available=True,
++ fallback_to_english=False)
++ Check()
++ transl = dlg.Translate('de', pseudo_if_not_available=False,
++ fallback_to_english=True)
++ Check()
++ transl = dlg.Translate('de', pseudo_if_not_available=False,
++ fallback_to_english=False)
++ Check()
++ transl = dlg.Translate('en', pseudo_if_not_available=True,
++ fallback_to_english=True)
++ Check()
++ transl = dlg.Translate('en', pseudo_if_not_available=True,
++ fallback_to_english=False)
++ Check()
++ transl = dlg.Translate('en', pseudo_if_not_available=False,
++ fallback_to_english=True)
++ Check()
++ transl = dlg.Translate('en', pseudo_if_not_available=False,
++ fallback_to_english=False)
++ Check()
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/gather/regexp.py b/tools/grit/grit/gather/regexp.py
+new file mode 100644
+index 0000000000..97ce2cfbf7
+--- /dev/null
++++ b/tools/grit/grit/gather/regexp.py
+@@ -0,0 +1,82 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''A baseclass for simple gatherers based on regular expressions.
++'''
++
++from __future__ import print_function
++
++from grit.gather import skeleton_gatherer
++
++
++class RegexpGatherer(skeleton_gatherer.SkeletonGatherer):
++ '''Common functionality of gatherers based on parsing using a single
++ regular expression.
++ '''
++
++ DescriptionMapping_ = {
++ 'CAPTION' : 'This is a caption for a dialog',
++ 'CHECKBOX' : 'This is a label for a checkbox',
++ 'CONTROL': 'This is the text on a control',
++ 'CTEXT': 'This is a label for a control',
++ 'DEFPUSHBUTTON': 'This is a button definition',
++ 'GROUPBOX': 'This is a label for a grouping',
++ 'ICON': 'This is a label for an icon',
++ 'LTEXT': 'This is the text for a label',
++ 'PUSHBUTTON': 'This is the text for a button',
++ }
++
++ # Contextualization elements. Used for adding additional information
++ # to the message bundle description string from RC files.
++ def AddDescriptionElement(self, string):
++ if string in self.DescriptionMapping_:
++ description = self.DescriptionMapping_[string]
++ else:
++ description = string
++ if self.single_message_:
++ self.single_message_.SetDescription(description)
++ else:
++ if (self.translatable_chunk_):
++ message = self.skeleton_[len(self.skeleton_) - 1].GetMessage()
++ message.SetDescription(description)
++
++ def _RegExpParse(self, regexp, text_to_parse):
++ '''An implementation of Parse() that can be used for resource sections that
++ can be parsed using a single multi-line regular expression.
++
++ All translateables must be in named groups that have names starting with
++ 'text'. All textual IDs must be in named groups that have names starting
++ with 'id'. All type definitions that can be included in the description
++ field for contextualization purposes should have a name that starts with
++ 'type'.
++
++ Args:
++ regexp: re.compile('...', re.MULTILINE)
++ text_to_parse:
++ '''
++ chunk_start = 0
++ for match in regexp.finditer(text_to_parse):
++ groups = match.groupdict()
++ keys = sorted(groups.keys())
++ self.translatable_chunk_ = False
++ for group in keys:
++ if group.startswith('id') and groups[group]:
++ self._AddTextualId(groups[group])
++ elif group.startswith('text') and groups[group]:
++ self._AddNontranslateableChunk(
++ text_to_parse[chunk_start : match.start(group)])
++ chunk_start = match.end(group) # Next chunk will start after the match
++ self._AddTranslateableChunk(groups[group])
++ elif group.startswith('type') and groups[group]:
++ # Add the description to the skeleton_ list. This works because
++ # we are using a sort set of keys, and because we assume that the
++ # group name used for descriptions (type) will come after the "text"
++ # group in alphabetical order. We also assume that there cannot be
++ # more than one description per regular expression match.
++ self.AddDescriptionElement(groups[group])
++
++ self._AddNontranslateableChunk(text_to_parse[chunk_start:])
++
++ if self.single_message_:
++ self.skeleton_.append(self.uberclique.MakeClique(self.single_message_))
+diff --git a/tools/grit/grit/gather/skeleton_gatherer.py b/tools/grit/grit/gather/skeleton_gatherer.py
+new file mode 100644
+index 0000000000..b11862b314
+--- /dev/null
++++ b/tools/grit/grit/gather/skeleton_gatherer.py
+@@ -0,0 +1,149 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''A baseclass for simple gatherers that store their gathered resource in a
++list.
++'''
++
++from __future__ import print_function
++
++import six
++
++from grit.gather import interface
++from grit import clique
++from grit import exception
++from grit import tclib
++
++
++class SkeletonGatherer(interface.GathererBase):
++ '''Common functionality of gatherers that parse their input as a skeleton of
++ translatable and nontranslatable chunks.
++ '''
++
++ def __init__(self, *args, **kwargs):
++ super(SkeletonGatherer, self).__init__(*args, **kwargs)
++ # List of parts of the document. Translateable parts are
++ # clique.MessageClique objects, nontranslateable parts are plain strings.
++ # Translated messages are inserted back into the skeleton using the quoting
++ # rules defined by self.Escape()
++ self.skeleton_ = []
++ # A list of the names of IDs that need to be defined for this resource
++ # section to compile correctly.
++ self.ids_ = []
++ # True if Parse() has already been called.
++ self.have_parsed_ = False
++ # True if a translatable chunk has been added
++ self.translatable_chunk_ = False
++ # If not None, all parts of the document will be put into this single
++ # message; otherwise the normal skeleton approach is used.
++ self.single_message_ = None
++ # Number to use for the next placeholder name. Used only if single_message
++ # is not None
++ self.ph_counter_ = 1
++
++ def GetText(self):
++ '''Returns the original text of the section'''
++ return self.text_
++
++ def Escape(self, text):
++ '''Subclasses can override. Base impl is identity.
++ '''
++ return text
++
++ def UnEscape(self, text):
++ '''Subclasses can override. Base impl is identity.
++ '''
++ return text
++
++ def GetTextualIds(self):
++ '''Returns the list of textual IDs that need to be defined for this
++ resource section to compile correctly.'''
++ return self.ids_
++
++ def _AddTextualId(self, id):
++ self.ids_.append(id)
++
++ def GetCliques(self):
++ '''Returns the message cliques for each translateable message in the
++ resource section.'''
++ return [x for x in self.skeleton_ if isinstance(x, clique.MessageClique)]
++
++ def Translate(self, lang, pseudo_if_not_available=True,
++ skeleton_gatherer=None, fallback_to_english=False):
++ if len(self.skeleton_) == 0:
++ raise exception.NotReady()
++ if skeleton_gatherer:
++ assert len(skeleton_gatherer.skeleton_) == len(self.skeleton_)
++
++ out = []
++ for ix in range(len(self.skeleton_)):
++ if isinstance(self.skeleton_[ix], six.string_types):
++ if skeleton_gatherer:
++ # Make sure the skeleton is like the original
++ assert(isinstance(skeleton_gatherer.skeleton_[ix], six.string_types))
++ out.append(skeleton_gatherer.skeleton_[ix])
++ else:
++ out.append(self.skeleton_[ix])
++ else:
++ if skeleton_gatherer: # Make sure the skeleton is like the original
++ assert(not isinstance(skeleton_gatherer.skeleton_[ix],
++ six.string_types))
++ msg = self.skeleton_[ix].MessageForLanguage(lang,
++ pseudo_if_not_available,
++ fallback_to_english)
++
++ def MyEscape(text):
++ return self.Escape(text)
++ text = msg.GetRealContent(escaping_function=MyEscape)
++ out.append(text)
++ return ''.join(out)
++
++ def Parse(self):
++ '''Parses the section. Implemented by subclasses. Idempotent.'''
++ raise NotImplementedError()
++
++ def _AddNontranslateableChunk(self, chunk):
++ '''Adds a nontranslateable chunk.'''
++ if self.single_message_:
++ ph = tclib.Placeholder('XX%02dXX' % self.ph_counter_, chunk, chunk)
++ self.ph_counter_ += 1
++ self.single_message_.AppendPlaceholder(ph)
++ else:
++ self.skeleton_.append(chunk)
++
++ def _AddTranslateableChunk(self, chunk):
++ '''Adds a translateable chunk. It will be unescaped before being added.'''
++ # We don't want empty messages since they are redundant and the TC
++ # doesn't allow them.
++ if chunk == '':
++ return
++
++ unescaped_text = self.UnEscape(chunk)
++ if self.single_message_:
++ self.single_message_.AppendText(unescaped_text)
++ else:
++ self.skeleton_.append(self.uberclique.MakeClique(
++ tclib.Message(text=unescaped_text)))
++ self.translatable_chunk_ = True
++
++ def SubstituteMessages(self, substituter):
++ '''Applies substitutions to all messages in the tree.
++
++ Goes through the skeleton and finds all MessageCliques.
++
++ Args:
++ substituter: a grit.util.Substituter object.
++ '''
++ if self.single_message_:
++ self.single_message_ = substituter.SubstituteMessage(self.single_message_)
++ new_skel = []
++ for chunk in self.skeleton_:
++ if isinstance(chunk, clique.MessageClique):
++ old_message = chunk.GetMessage()
++ new_message = substituter.SubstituteMessage(old_message)
++ if new_message is not old_message:
++ new_skel.append(self.uberclique.MakeClique(new_message))
++ continue
++ new_skel.append(chunk)
++ self.skeleton_ = new_skel
+diff --git a/tools/grit/grit/gather/tr_html.py b/tools/grit/grit/gather/tr_html.py
+new file mode 100644
+index 0000000000..60a9bfaf4e
+--- /dev/null
++++ b/tools/grit/grit/gather/tr_html.py
+@@ -0,0 +1,743 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''A gatherer for the TotalRecall brand of HTML templates with replaceable
++portions. We wanted to reuse extern.tclib.api.handlers.html.TCHTMLParser
++but this proved impossible due to the fact that the TotalRecall HTML templates
++are in general quite far from parseable HTML and the TCHTMLParser derives
++
++from HTMLParser.HTMLParser which requires relatively well-formed HTML. Some
++examples of "HTML" from the TotalRecall HTML templates that wouldn't be
++parseable include things like:
++
++ <a [PARAMS]>blabla</a> (not parseable because attributes are invalid)
++
++ <table><tr><td>[LOTSOFSTUFF]</tr></table> (not parseable because closing
++ </td> is in the HTML [LOTSOFSTUFF]
++ is replaced by)
++
++The other problem with using general parsers (such as TCHTMLParser) is that
++we want to make sure we output the TotalRecall template with as little changes
++as possible in terms of whitespace characters, layout etc. With any parser
++that generates a parse tree, and generates output by dumping the parse tree,
++we would always have little inconsistencies which could cause bugs (the
++TotalRecall template stuff is quite brittle and can break if e.g. a tab
++character is replaced with spaces).
++
++The solution, which may be applicable to some other HTML-like template
++languages floating around Google, is to create a parser with a simple state
++machine that keeps track of what kind of tag it's inside, and whether it's in
++a translateable section or not. Translateable sections are:
++
++a) text (including [BINGO] replaceables) inside of tags that
++ can contain translateable text (which is all tags except
++ for a few)
++
++b) text inside of an 'alt' attribute in an <image> element, or
++ the 'value' attribute of a <submit>, <button> or <text>
++ element.
++
++The parser does not build up a parse tree but rather a "skeleton" which
++is a list of nontranslateable strings intermingled with grit.clique.MessageClique
++objects. This simplifies the parser considerably compared to a regular HTML
++parser. To output a translated document, each item in the skeleton is
++printed out, with the relevant Translation from each MessageCliques being used
++for the requested language.
++
++This implementation borrows some code, constants and ideas from
++extern.tclib.api.handlers.html.TCHTMLParser.
++'''
++
++from __future__ import print_function
++
++import re
++
++import six
++
++from grit import clique
++from grit import exception
++from grit import lazy_re
++from grit import util
++from grit import tclib
++
++from grit.gather import interface
++
++
++# HTML tags which break (separate) chunks.
++_BLOCK_TAGS = ['script', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'br',
++ 'body', 'style', 'head', 'title', 'table', 'tr', 'td', 'th',
++ 'ul', 'ol', 'dl', 'nl', 'li', 'div', 'object', 'center',
++ 'html', 'link', 'form', 'select', 'textarea',
++ 'button', 'option', 'map', 'area', 'blockquote', 'pre',
++ 'meta', 'xmp', 'noscript', 'label', 'tbody', 'thead',
++ 'script', 'style', 'pre', 'iframe', 'img', 'input', 'nowrap',
++ 'fieldset', 'legend']
++
++# HTML tags which may appear within a chunk.
++_INLINE_TAGS = ['b', 'i', 'u', 'tt', 'code', 'font', 'a', 'span', 'small',
++ 'key', 'nobr', 'url', 'em', 's', 'sup', 'strike',
++ 'strong']
++
++# HTML tags within which linebreaks are significant.
++_PREFORMATTED_TAGS = ['textarea', 'xmp', 'pre']
++
++# An array mapping some of the inline HTML tags to more meaningful
++# names for those tags. This will be used when generating placeholders
++# representing these tags.
++_HTML_PLACEHOLDER_NAMES = { 'a' : 'link', 'br' : 'break', 'b' : 'bold',
++ 'i' : 'italic', 'li' : 'item', 'ol' : 'ordered_list', 'p' : 'paragraph',
++ 'ul' : 'unordered_list', 'img' : 'image', 'em' : 'emphasis' }
++
++# We append each of these characters in sequence to distinguish between
++# different placeholders with basically the same name (e.g. BOLD1, BOLD2).
++# Keep in mind that a placeholder name must not be a substring of any other
++# placeholder name in the same message, so we can't simply count (BOLD_1
++# would be a substring of BOLD_10).
++_SUFFIXES = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
++
++# Matches whitespace in an HTML document. Also matches HTML comments, which are
++# treated as whitespace.
++_WHITESPACE = lazy_re.compile(r'(\s|&nbsp;|\\n|\\r|<!--\s*desc\s*=.*?-->)+',
++ re.DOTALL)
++
++# Matches whitespace sequences which can be folded into a single whitespace
++# character. This matches single characters so that non-spaces are replaced
++# with spaces.
++_FOLD_WHITESPACE = lazy_re.compile(r'\s+')
++
++# Finds a non-whitespace character
++_NON_WHITESPACE = lazy_re.compile(r'\S')
++
++# Matches two or more &nbsp; in a row (a single &nbsp is not changed into
++# placeholders because different languages require different numbers of spaces
++# and placeholders must match exactly; more than one is probably a "special"
++# whitespace sequence and should be turned into a placeholder).
++_NBSP = lazy_re.compile(r'&nbsp;(&nbsp;)+')
++
++# Matches nontranslateable chunks of the document
++_NONTRANSLATEABLES = lazy_re.compile(r'''
++ <\s*script.+?<\s*/\s*script\s*>
++ |
++ <\s*style.+?<\s*/\s*style\s*>
++ |
++ <!--.+?-->
++ |
++ <\?IMPORT\s.+?> # import tag
++ |
++ <\s*[a-zA-Z_]+:.+?> # custom tag (open)
++ |
++ <\s*/\s*[a-zA-Z_]+:.+?> # custom tag (close)
++ |
++ <!\s*[A-Z]+\s*([^>]+|"[^"]+"|'[^']+')*?>
++ ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
++
++# Matches a tag and its attributes
++_ELEMENT = lazy_re.compile(r'''
++ # Optional closing /, element name
++ <\s*(?P<closing>/)?\s*(?P<element>[a-zA-Z0-9]+)\s*
++ # Attributes and/or replaceables inside the tag, if any
++ (?P<atts>(
++ \s*([a-zA-Z_][-:.a-zA-Z_0-9]*) # Attribute name
++ (\s*=\s*(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?
++ |
++ \s*\[(\$?\~)?([A-Z0-9-_]+?)(\~\$?)?\]
++ )*)
++ \s*(?P<empty>/)?\s*> # Optional empty-tag closing /, and tag close
++ ''',
++ re.MULTILINE | re.DOTALL | re.VERBOSE)
++
++# Matches elements that may have translateable attributes. The value of these
++# special attributes is given by group 'value1' or 'value2'. Note that this
++# regexp demands that the attribute value be quoted; this is necessary because
++# the non-tree-building nature of the parser means we don't know when we're
++# writing out attributes, so we wouldn't know to escape spaces.
++_SPECIAL_ELEMENT = lazy_re.compile(r'''
++ <\s*(
++ input[^>]+?value\s*=\s*(\'(?P<value3>[^\']*)\'|"(?P<value4>[^"]*)")
++ [^>]+type\s*=\s*"?'?(button|reset|text|submit)'?"?
++ |
++ (
++ table[^>]+?title\s*=
++ |
++ img[^>]+?alt\s*=
++ |
++ input[^>]+?type\s*=\s*"?'?(button|reset|text|submit)'?"?[^>]+?value\s*=
++ )
++ \s*(\'(?P<value1>[^\']*)\'|"(?P<value2>[^"]*)")
++ )[^>]*?>
++ ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
++
++# Matches stuff that is translateable if it occurs in the right context
++# (between tags). This includes all characters and character entities.
++# Note that this also matches &nbsp; which needs to be handled as whitespace
++# before this regexp is applied.
++_CHARACTERS = lazy_re.compile(r'''
++ (
++ \w
++ |
++ [\!\@\#\$\%\^\*\(\)\-\=\_\+\[\]\{\}\\\|\;\:\'\"\,\.\/\?\`\~]
++ |
++ &(\#[0-9]+|\#x[0-9a-fA-F]+|[A-Za-z0-9]+);
++ )+
++ ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
++
++# Matches Total Recall's "replaceable" tags, which are just any text
++# in capitals enclosed by delimiters like [] or [~~] or [$~~$] (e.g. [HELLO],
++# [~HELLO~] and [$~HELLO~$]).
++_REPLACEABLE = lazy_re.compile(r'\[(\$?\~)?(?P<name>[A-Z0-9-_]+?)(\~\$?)?\]',
++ re.MULTILINE)
++
++
++# Matches the silly [!]-prefixed "header" that is used in some TotalRecall
++# templates.
++_SILLY_HEADER = lazy_re.compile(r'\[!\]\ntitle\t(?P<title>[^\n]+?)\n.+?\n\n',
++ re.MULTILINE | re.DOTALL)
++
++
++# Matches a comment that provides a description for the message it occurs in.
++_DESCRIPTION_COMMENT = lazy_re.compile(
++ r'<!--\s*desc\s*=\s*(?P<description>.+?)\s*-->', re.DOTALL)
++
++# Matches a comment which is used to break apart multiple messages.
++_MESSAGE_BREAK_COMMENT = lazy_re.compile(r'<!--\s*message-break\s*-->',
++ re.DOTALL)
++
++# Matches a comment which is used to prevent block tags from splitting a message
++_MESSAGE_NO_BREAK_COMMENT = re.compile(r'<!--\s*message-no-break\s*-->',
++ re.DOTALL)
++
++
++_DEBUG = 0
++def _DebugPrint(text):
++ if _DEBUG:
++ print(text.encode('utf-8'))
++
++
++class HtmlChunks(object):
++ '''A parser that knows how to break an HTML-like document into a list of
++ chunks, where each chunk is either translateable or non-translateable.
++ The chunks are unmodified sections of the original document, so concatenating
++ the text of all chunks would result in the original document.'''
++
++ def InTranslateable(self):
++ return self.last_translateable != -1
++
++ def Rest(self):
++ return self.text_[self.current:]
++
++ def StartTranslateable(self):
++ assert not self.InTranslateable()
++ if self.current != 0:
++ # Append a nontranslateable chunk
++ chunk_text = self.text_[self.chunk_start : self.last_nontranslateable + 1]
++ # Needed in the case where document starts with a translateable.
++ if len(chunk_text) > 0:
++ self.AddChunk(False, chunk_text)
++ self.chunk_start = self.last_nontranslateable + 1
++ self.last_translateable = self.current
++ self.last_nontranslateable = -1
++
++ def EndTranslateable(self):
++ assert self.InTranslateable()
++ # Append a translateable chunk
++ self.AddChunk(True,
++ self.text_[self.chunk_start : self.last_translateable + 1])
++ self.chunk_start = self.last_translateable + 1
++ self.last_translateable = -1
++ self.last_nontranslateable = self.current
++
++ def AdvancePast(self, match):
++ self.current += match.end()
++
++ def AddChunk(self, translateable, text):
++ '''Adds a chunk to self, removing linebreaks and duplicate whitespace
++ if appropriate.
++ '''
++ m = _DESCRIPTION_COMMENT.search(text)
++ if m:
++ self.last_description = m.group('description')
++ # Remove the description from the output text
++ text = _DESCRIPTION_COMMENT.sub('', text)
++
++ m = _MESSAGE_BREAK_COMMENT.search(text)
++ if m:
++ # Remove the coment from the output text. It should already effectively
++ # break apart messages.
++ text = _MESSAGE_BREAK_COMMENT.sub('', text)
++
++ if translateable and not self.last_element_ in _PREFORMATTED_TAGS:
++ if self.fold_whitespace_:
++ # Fold whitespace sequences if appropriate. This is optional because it
++ # alters the output strings.
++ text = _FOLD_WHITESPACE.sub(' ', text)
++ else:
++ text = text.replace('\n', ' ')
++ text = text.replace('\r', ' ')
++ # This whitespace folding doesn't work in all cases, thus the
++ # fold_whitespace flag to support backwards compatibility.
++ text = text.replace(' ', ' ')
++ text = text.replace(' ', ' ')
++
++ if translateable:
++ description = self.last_description
++ self.last_description = ''
++ else:
++ description = ''
++
++ if text != '':
++ self.chunks_.append((translateable, text, description))
++
++ def Parse(self, text, fold_whitespace):
++ '''Parses self.text_ into an intermediate format stored in self.chunks_
++ which is translateable and nontranslateable chunks. Also returns
++ self.chunks_
++
++ Args:
++ text: The HTML for parsing.
++ fold_whitespace: Whether whitespace sequences should be folded into a
++ single space.
++
++ Return:
++ [chunk1, chunk2, chunk3, ...] (instances of class Chunk)
++ '''
++ #
++ # Chunker state
++ #
++
++ self.text_ = text
++ self.fold_whitespace_ = fold_whitespace
++
++ # A list of tuples (is_translateable, text) which represents the document
++ # after chunking.
++ self.chunks_ = []
++
++ # Start index of the last chunk, whether translateable or not
++ self.chunk_start = 0
++
++ # Index of the last for-sure translateable character if we are parsing
++ # a translateable chunk, -1 to indicate we are not in a translateable chunk.
++ # This is needed so that we don't include trailing whitespace in the
++ # translateable chunk (whitespace is neutral).
++ self.last_translateable = -1
++
++ # Index of the last for-sure nontranslateable character if we are parsing
++ # a nontranslateable chunk, -1 if we are not in a nontranslateable chunk.
++ # This is needed to make sure we can group e.g. "<b>Hello</b> there"
++ # together instead of just "Hello</b> there" which would be much worse
++ # for translation.
++ self.last_nontranslateable = -1
++
++ # Index of the character we're currently looking at.
++ self.current = 0
++
++ # The name of the last block element parsed.
++ self.last_element_ = ''
++
++ # The last explicit description we found.
++ self.last_description = ''
++
++ # Whether no-break was the last chunk seen
++ self.last_nobreak = False
++
++ while self.current < len(self.text_):
++ _DebugPrint('REST: %s' % self.text_[self.current:self.current+60])
++
++ m = _MESSAGE_NO_BREAK_COMMENT.match(self.Rest())
++ if m:
++ self.AdvancePast(m)
++ self.last_nobreak = True
++ continue
++
++ # Try to match whitespace
++ m = _WHITESPACE.match(self.Rest())
++ if m:
++ # Whitespace is neutral, it just advances 'current' and does not switch
++ # between translateable/nontranslateable. If we are in a
++ # nontranslateable section that extends to the current point, we extend
++ # it to include the whitespace. If we are in a translateable section,
++ # we do not extend it until we find
++ # more translateable parts, because we never want a translateable chunk
++ # to end with whitespace.
++ if (not self.InTranslateable() and
++ self.last_nontranslateable == self.current - 1):
++ self.last_nontranslateable = self.current + m.end() - 1
++ self.AdvancePast(m)
++ continue
++
++ # Then we try to match nontranslateables
++ m = _NONTRANSLATEABLES.match(self.Rest())
++ if m:
++ if self.InTranslateable():
++ self.EndTranslateable()
++ self.last_nontranslateable = self.current + m.end() - 1
++ self.AdvancePast(m)
++ continue
++
++ # Now match all other HTML element tags (opening, closing, or empty, we
++ # don't care).
++ m = _ELEMENT.match(self.Rest())
++ if m:
++ element_name = m.group('element').lower()
++ if element_name in _BLOCK_TAGS:
++ self.last_element_ = element_name
++ if self.InTranslateable():
++ if self.last_nobreak:
++ self.last_nobreak = False
++ else:
++ self.EndTranslateable()
++
++ # Check for "special" elements, i.e. ones that have a translateable
++ # attribute, and handle them correctly. Note that all of the
++ # "special" elements are block tags, so no need to check for this
++ # if the tag is not a block tag.
++ sm = _SPECIAL_ELEMENT.match(self.Rest())
++ if sm:
++ # Get the appropriate group name
++ for group in sm.groupdict():
++ if sm.groupdict()[group]:
++ break
++
++ # First make a nontranslateable chunk up to and including the
++ # quote before the translateable attribute value
++ self.AddChunk(False, self.text_[
++ self.chunk_start : self.current + sm.start(group)])
++ # Then a translateable for the translateable bit
++ self.AddChunk(True, self.Rest()[sm.start(group) : sm.end(group)])
++ # Finally correct the data invariant for the parser
++ self.chunk_start = self.current + sm.end(group)
++
++ self.last_nontranslateable = self.current + m.end() - 1
++ elif self.InTranslateable():
++ # We're in a translateable and the tag is an inline tag, so we
++ # need to include it in the translateable.
++ self.last_translateable = self.current + m.end() - 1
++ self.AdvancePast(m)
++ continue
++
++ # Anything else we find must be translateable, so we advance one character
++ # at a time until one of the above matches.
++ if not self.InTranslateable():
++ self.StartTranslateable()
++ else:
++ self.last_translateable = self.current
++ self.current += 1
++
++ # Close the final chunk
++ if self.InTranslateable():
++ self.AddChunk(True, self.text_[self.chunk_start : ])
++ else:
++ self.AddChunk(False, self.text_[self.chunk_start : ])
++
++ return self.chunks_
++
++
++def HtmlToMessage(html, include_block_tags=False, description=''):
++ '''Takes a bit of HTML, which must contain only "inline" HTML elements,
++ and changes it into a tclib.Message. This involves escaping any entities and
++ replacing any HTML code with placeholders.
++
++ If include_block_tags is true, no error will be given if block tags (e.g.
++ <p> or <br>) are included in the HTML.
++
++ Args:
++ html: 'Hello <b>[USERNAME]</b>, how&nbsp;<i>are</i> you?'
++ include_block_tags: False
++
++ Return:
++ tclib.Message('Hello START_BOLD1USERNAMEEND_BOLD, '
++ 'howNBSPSTART_ITALICareEND_ITALIC you?',
++ [ Placeholder('START_BOLD', '<b>', ''),
++ Placeholder('USERNAME', '[USERNAME]', ''),
++ Placeholder('END_BOLD', '</b>', ''),
++ Placeholder('START_ITALIC', '<i>', ''),
++ Placeholder('END_ITALIC', '</i>', ''), ])
++ '''
++ # Approach is:
++ # - first placeholderize, finding <elements>, [REPLACEABLES] and &nbsp;
++ # - then escape all character entities in text in-between placeholders
++
++ parts = [] # List of strings (for text chunks) and tuples (ID, original)
++ # for placeholders
++
++ count_names = {} # Map of base names to number of times used
++ end_names = {} # Map of base names to stack of end tags (for correct nesting)
++
++ def MakeNameClosure(base, type = ''):
++ '''Returns a closure that can be called once all names have been allocated
++ to return the final name of the placeholder. This allows us to minimally
++ number placeholders for non-overlap.
++
++ Also ensures that END_XXX_Y placeholders have the same Y as the
++ corresponding BEGIN_XXX_Y placeholder when we have nested tags of the same
++ type.
++
++ Args:
++ base: 'phname'
++ type: '' | 'begin' | 'end'
++
++ Return:
++ Closure()
++ '''
++ name = base.upper()
++ if type != '':
++ name = ('%s_%s' % (type, base)).upper()
++
++ count_names.setdefault(name, 0)
++ count_names[name] += 1
++
++ def MakeFinalName(name_ = name, index = count_names[name] - 1):
++ if type.lower() == 'end' and end_names.get(base):
++ return end_names[base].pop(-1) # For correct nesting
++ if count_names[name_] != 1:
++ name_ = '%s_%s' % (name_, _SUFFIXES[index])
++ # We need to use a stack to ensure that the end-tag suffixes match
++ # the begin-tag suffixes. Only needed when more than one tag of the
++ # same type.
++ if type == 'begin':
++ end_name = ('END_%s_%s' % (base, _SUFFIXES[index])).upper()
++ if base in end_names:
++ end_names[base].append(end_name)
++ else:
++ end_names[base] = [end_name]
++
++ return name_
++
++ return MakeFinalName
++
++ current = 0
++ last_nobreak = False
++
++ while current < len(html):
++ m = _MESSAGE_NO_BREAK_COMMENT.match(html[current:])
++ if m:
++ last_nobreak = True
++ current += m.end()
++ continue
++
++ m = _NBSP.match(html[current:])
++ if m:
++ parts.append((MakeNameClosure('SPACE'), m.group()))
++ current += m.end()
++ continue
++
++ m = _REPLACEABLE.match(html[current:])
++ if m:
++ # Replaceables allow - but placeholders don't, so replace - with _
++ ph_name = MakeNameClosure('X_%s_X' % m.group('name').replace('-', '_'))
++ parts.append((ph_name, m.group()))
++ current += m.end()
++ continue
++
++ m = _SPECIAL_ELEMENT.match(html[current:])
++ if m:
++ if not include_block_tags:
++ if last_nobreak:
++ last_nobreak = False
++ else:
++ raise exception.BlockTagInTranslateableChunk(html)
++ element_name = 'block' # for simplification
++ # Get the appropriate group name
++ for group in m.groupdict():
++ if m.groupdict()[group]:
++ break
++ parts.append((MakeNameClosure(element_name, 'begin'),
++ html[current : current + m.start(group)]))
++ parts.append(m.group(group))
++ parts.append((MakeNameClosure(element_name, 'end'),
++ html[current + m.end(group) : current + m.end()]))
++ current += m.end()
++ continue
++
++ m = _ELEMENT.match(html[current:])
++ if m:
++ element_name = m.group('element').lower()
++ if not include_block_tags and not element_name in _INLINE_TAGS:
++ if last_nobreak:
++ last_nobreak = False
++ else:
++ raise exception.BlockTagInTranslateableChunk(html[current:])
++ if element_name in _HTML_PLACEHOLDER_NAMES: # use meaningful names
++ element_name = _HTML_PLACEHOLDER_NAMES[element_name]
++
++ # Make a name for the placeholder
++ type = ''
++ if not m.group('empty'):
++ if m.group('closing'):
++ type = 'end'
++ else:
++ type = 'begin'
++ parts.append((MakeNameClosure(element_name, type), m.group()))
++ current += m.end()
++ continue
++
++ if len(parts) and isinstance(parts[-1], six.string_types):
++ parts[-1] += html[current]
++ else:
++ parts.append(html[current])
++ current += 1
++
++ msg_text = ''
++ placeholders = []
++ for part in parts:
++ if isinstance(part, tuple):
++ final_name = part[0]()
++ original = part[1]
++ msg_text += final_name
++ placeholders.append(tclib.Placeholder(final_name, original, '(HTML code)'))
++ else:
++ msg_text += part
++
++ msg = tclib.Message(text=msg_text, placeholders=placeholders,
++ description=description)
++ content = msg.GetContent()
++ for ix in range(len(content)):
++ if isinstance(content[ix], six.string_types):
++ content[ix] = util.UnescapeHtml(content[ix], replace_nbsp=False)
++
++ return msg
++
++
++class TrHtml(interface.GathererBase):
++ '''Represents a document or message in the template format used by
++ Total Recall for HTML documents.'''
++
++ def __init__(self, *args, **kwargs):
++ super(TrHtml, self).__init__(*args, **kwargs)
++ self.have_parsed_ = False
++ self.skeleton_ = [] # list of strings and MessageClique objects
++ self.fold_whitespace_ = False
++
++ def SetAttributes(self, attrs):
++ '''Sets node attributes used by the gatherer.
++
++ This checks the fold_whitespace attribute.
++
++ Args:
++ attrs: The mapping of node attributes.
++ '''
++ self.fold_whitespace_ = ('fold_whitespace' in attrs and
++ attrs['fold_whitespace'] == 'true')
++
++ def GetText(self):
++ '''Returns the original text of the HTML document'''
++ return self.text_
++
++ def GetTextualIds(self):
++ return [self.extkey]
++
++ def GetCliques(self):
++ '''Returns the message cliques for each translateable message in the
++ document.'''
++ return [x for x in self.skeleton_ if isinstance(x, clique.MessageClique)]
++
++ def Translate(self, lang, pseudo_if_not_available=True,
++ skeleton_gatherer=None, fallback_to_english=False):
++ '''Returns this document with translateable messages filled with
++ the translation for language 'lang'.
++
++ Args:
++ lang: 'en'
++ pseudo_if_not_available: True
++
++ Return:
++ 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND
++
++ Raises:
++ grit.exception.NotReady() if used before Parse() has been successfully
++ called.
++ grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' is false
++ and there is no translation for the requested language.
++ '''
++ if len(self.skeleton_) == 0:
++ raise exception.NotReady()
++
++ # TODO(joi) Implement support for skeleton gatherers here.
++
++ out = []
++ for item in self.skeleton_:
++ if isinstance(item, six.string_types):
++ out.append(item)
++ else:
++ msg = item.MessageForLanguage(lang,
++ pseudo_if_not_available,
++ fallback_to_english)
++ for content in msg.GetContent():
++ if isinstance(content, tclib.Placeholder):
++ out.append(content.GetOriginal())
++ else:
++ # We escape " characters to increase the chance that attributes
++ # will be properly escaped.
++ out.append(util.EscapeHtml(content, True))
++
++ return ''.join(out)
++
++ def Parse(self):
++ if self.have_parsed_:
++ return
++ self.have_parsed_ = True
++
++ text = self._LoadInputFile()
++
++ # Ignore the BOM character if the document starts with one.
++ if text.startswith(u'\ufeff'):
++ text = text[1:]
++
++ self.text_ = text
++
++ # Parsing is done in two phases: First, we break the document into
++ # translateable and nontranslateable chunks. Second, we run through each
++ # translateable chunk and insert placeholders for any HTML elements,
++ # unescape escaped characters, etc.
++
++ # First handle the silly little [!]-prefixed header because it's not
++ # handled by our HTML parsers.
++ m = _SILLY_HEADER.match(text)
++ if m:
++ self.skeleton_.append(text[:m.start('title')])
++ self.skeleton_.append(self.uberclique.MakeClique(
++ tclib.Message(text=text[m.start('title'):m.end('title')])))
++ self.skeleton_.append(text[m.end('title') : m.end()])
++ text = text[m.end():]
++
++ chunks = HtmlChunks().Parse(text, self.fold_whitespace_)
++
++ for chunk in chunks:
++ if chunk[0]: # Chunk is translateable
++ self.skeleton_.append(self.uberclique.MakeClique(
++ HtmlToMessage(chunk[1], description=chunk[2])))
++ else:
++ self.skeleton_.append(chunk[1])
++
++ # Go through the skeleton and change any messages that consist solely of
++ # placeholders and whitespace into nontranslateable strings.
++ for ix in range(len(self.skeleton_)):
++ got_text = False
++ if isinstance(self.skeleton_[ix], clique.MessageClique):
++ msg = self.skeleton_[ix].GetMessage()
++ for item in msg.GetContent():
++ if (isinstance(item, six.string_types)
++ and _NON_WHITESPACE.search(item) and item != '&nbsp;'):
++ got_text = True
++ break
++ if not got_text:
++ self.skeleton_[ix] = msg.GetRealContent()
++
++ def SubstituteMessages(self, substituter):
++ '''Applies substitutions to all messages in the tree.
++
++ Goes through the skeleton and finds all MessageCliques.
++
++ Args:
++ substituter: a grit.util.Substituter object.
++ '''
++ new_skel = []
++ for chunk in self.skeleton_:
++ if isinstance(chunk, clique.MessageClique):
++ old_message = chunk.GetMessage()
++ new_message = substituter.SubstituteMessage(old_message)
++ if new_message is not old_message:
++ new_skel.append(self.uberclique.MakeClique(new_message))
++ continue
++ new_skel.append(chunk)
++ self.skeleton_ = new_skel
+diff --git a/tools/grit/grit/gather/tr_html_unittest.py b/tools/grit/grit/gather/tr_html_unittest.py
+new file mode 100644
+index 0000000000..1194853d9a
+--- /dev/null
++++ b/tools/grit/grit/gather/tr_html_unittest.py
+@@ -0,0 +1,524 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.gather.tr_html'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++import six
++from six import StringIO
++
++from grit.gather import tr_html
++from grit import clique
++from grit import util
++
++
++class ParserUnittest(unittest.TestCase):
++ def testChunkingWithoutFoldWhitespace(self):
++ self.VerifyChunking(False)
++
++ def testChunkingWithFoldWhitespace(self):
++ self.VerifyChunking(True)
++
++ def VerifyChunking(self, fold_whitespace):
++ """Use a single function to run all chunking testing.
++
++ This makes it easier to run chunking with fold_whitespace both on and off,
++ to make sure the outputs are the same.
++
++ Args:
++ fold_whitespace: Whether whitespace sequences should be folded into a
++ single space.
++ """
++ self.VerifyChunkingBasic(fold_whitespace)
++ self.VerifyChunkingDescriptions(fold_whitespace)
++ self.VerifyChunkingReplaceables(fold_whitespace)
++ self.VerifyChunkingLineBreaks(fold_whitespace)
++ self.VerifyChunkingMessageBreak(fold_whitespace)
++ self.VerifyChunkingMessageNoBreak(fold_whitespace)
++
++ def VerifyChunkingBasic(self, fold_whitespace):
++ p = tr_html.HtmlChunks()
++ chunks = p.Parse('<p>Hello <b>dear</b> how <i>are</i>you?<p>Fine!',
++ fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (False, '<p>', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
++ (False, '<p>', ''), (True, 'Fine!', '')])
++
++ chunks = p.Parse('<p> Hello <b>dear</b> how <i>are</i>you? <p>Fine!',
++ fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (False, '<p> ', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
++ (False, ' <p>', ''), (True, 'Fine!', '')])
++
++ chunks = p.Parse('<p> Hello <b>dear how <i>are you? <p> Fine!',
++ fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (False, '<p> ', ''), (True, 'Hello <b>dear how <i>are you?', ''),
++ (False, ' <p> ', ''), (True, 'Fine!', '')])
++
++ # Ensure translateable sections that start with inline tags contain
++ # the starting inline tag.
++ chunks = p.Parse('<b>Hello!</b> how are you?<p><i>I am fine.</i>',
++ fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (True, '<b>Hello!</b> how are you?', ''), (False, '<p>', ''),
++ (True, '<i>I am fine.</i>', '')])
++
++ # Ensure translateable sections that end with inline tags contain
++ # the ending inline tag.
++ chunks = p.Parse("Hello! How are <b>you?</b><p><i>I'm fine!</i>",
++ fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (True, 'Hello! How are <b>you?</b>', ''), (False, '<p>', ''),
++ (True, "<i>I'm fine!</i>", '')])
++
++ def VerifyChunkingDescriptions(self, fold_whitespace):
++ p = tr_html.HtmlChunks()
++ # Check capitals and explicit descriptions
++ chunks = p.Parse('<!-- desc=bingo! --><B>Hello!</B> how are you?<P>'
++ '<I>I am fine.</I>', fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
++ (True, '<I>I am fine.</I>', '')])
++ chunks = p.Parse('<B><!-- desc=bingo! -->Hello!</B> how are you?<P>'
++ '<I>I am fine.</I>', fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
++ (True, '<I>I am fine.</I>', '')])
++ # Linebreaks get handled by the tclib message.
++ chunks = p.Parse('<B>Hello!</B> <!-- desc=bi\nngo\n! -->how are you?<P>'
++ '<I>I am fine.</I>', fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (True, '<B>Hello!</B> how are you?', 'bi\nngo\n!'), (False, '<P>', ''),
++ (True, '<I>I am fine.</I>', '')])
++
++ # In this case, because the explicit description appears after the first
++ # translateable, it will actually apply to the second translateable.
++ chunks = p.Parse('<B>Hello!</B> how are you?<!-- desc=bingo! --><P>'
++ '<I>I am fine.</I>', fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (True, '<B>Hello!</B> how are you?', ''), (False, '<P>', ''),
++ (True, '<I>I am fine.</I>', 'bingo!')])
++
++ def VerifyChunkingReplaceables(self, fold_whitespace):
++ # Check that replaceables within block tags (where attributes would go) are
++ # handled correctly.
++ p = tr_html.HtmlChunks()
++ chunks = p.Parse('<b>Hello!</b> how are you?<p [BINGO] [$~BONGO~$]>'
++ '<i>I am fine.</i>', fold_whitespace)
++ self.failUnlessEqual(chunks, [
++ (True, '<b>Hello!</b> how are you?', ''),
++ (False, '<p [BINGO] [$~BONGO~$]>', ''),
++ (True, '<i>I am fine.</i>', '')])
++
++ def VerifyChunkingLineBreaks(self, fold_whitespace):
++ # Check that the contents of preformatted tags preserve line breaks.
++ p = tr_html.HtmlChunks()
++ chunks = p.Parse('<textarea>Hello\nthere\nhow\nare\nyou?</textarea>',
++ fold_whitespace)
++ self.failUnlessEqual(chunks, [(False, '<textarea>', ''),
++ (True, 'Hello\nthere\nhow\nare\nyou?', ''), (False, '</textarea>', '')])
++
++ # ...and that other tags' line breaks are converted to spaces
++ chunks = p.Parse('<p>Hello\nthere\nhow\nare\nyou?</p>', fold_whitespace)
++ self.failUnlessEqual(chunks, [(False, '<p>', ''),
++ (True, 'Hello there how are you?', ''), (False, '</p>', '')])
++
++ def VerifyChunkingMessageBreak(self, fold_whitespace):
++ p = tr_html.HtmlChunks()
++ # Make sure that message-break comments work properly.
++ chunks = p.Parse('Break<!-- message-break --> apart '
++ '<!--message-break-->messages', fold_whitespace)
++ self.failUnlessEqual(chunks, [(True, 'Break', ''),
++ (False, ' ', ''),
++ (True, 'apart', ''),
++ (False, ' ', ''),
++ (True, 'messages', '')])
++
++ # Make sure message-break comments work in an inline tag.
++ chunks = p.Parse('<a href=\'google.com\'><!-- message-break -->Google'
++ '<!--message-break--></a>', fold_whitespace)
++ self.failUnlessEqual(chunks, [(False, '<a href=\'google.com\'>', ''),
++ (True, 'Google', ''),
++ (False, '</a>', '')])
++
++ def VerifyChunkingMessageNoBreak(self, fold_whitespace):
++ p = tr_html.HtmlChunks()
++ # Make sure that message-no-break comments work properly.
++ chunks = p.Parse('Please <!-- message-no-break --> <br />don\'t break',
++ fold_whitespace)
++ self.failUnlessEqual(chunks, [(True, 'Please <!-- message-no-break --> '
++ '<br />don\'t break', '')])
++
++ chunks = p.Parse('Please <br /> break. <!-- message-no-break --> <br /> '
++ 'But not this time.', fold_whitespace)
++ self.failUnlessEqual(chunks, [(True, 'Please', ''),
++ (False, ' <br /> ', ''),
++ (True, 'break. <!-- message-no-break --> '
++ '<br /> But not this time.', '')])
++
++ def testTranslateableAttributes(self):
++ p = tr_html.HtmlChunks()
++
++ # Check that the translateable attributes in <img>, <submit>, <button> and
++ # <text> elements buttons are handled correctly.
++ chunks = p.Parse('<img src=bingo.jpg alt="hello there">'
++ '<input type=submit value="hello">'
++ '<input type="button" value="hello">'
++ '<input type=\'text\' value=\'Howdie\'>', False)
++ self.failUnlessEqual(chunks, [
++ (False, '<img src=bingo.jpg alt="', ''), (True, 'hello there', ''),
++ (False, '"><input type=submit value="', ''), (True, 'hello', ''),
++ (False, '"><input type="button" value="', ''), (True, 'hello', ''),
++ (False, '"><input type=\'text\' value=\'', ''), (True, 'Howdie', ''),
++ (False, '\'>', '')])
++
++
++ def testTranslateableHtmlToMessage(self):
++ msg = tr_html.HtmlToMessage(
++ 'Hello <b>[USERNAME]</b>, &lt;how&gt;&nbsp;<i>are</i> you?')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres ==
++ 'Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, '
++ '<how>&nbsp;BEGIN_ITALICareEND_ITALIC you?')
++
++ msg = tr_html.HtmlToMessage('<b>Hello</b><I>Hello</I><b>Hello</b>')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres ==
++ 'BEGIN_BOLD_1HelloEND_BOLD_1BEGIN_ITALICHelloEND_ITALIC'
++ 'BEGIN_BOLD_2HelloEND_BOLD_2')
++
++ # Check that nesting (of the <font> tags) is handled correctly - i.e. that
++ # the closing placeholder numbers match the opening placeholders.
++ msg = tr_html.HtmlToMessage(
++ '''<font size=-1><font color=#FF0000>Update!</font> '''
++ '''<a href='http://desktop.google.com/whatsnew.html?hl=[$~LANG~$]'>'''
++ '''New Features</a>: Now search PDFs, MP3s, Firefox web history, and '''
++ '''more</font>''')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres ==
++ 'BEGIN_FONT_1BEGIN_FONT_2Update!END_FONT_2 BEGIN_LINK'
++ 'New FeaturesEND_LINK: Now search PDFs, MP3s, Firefox '
++ 'web history, and moreEND_FONT_1')
++
++ msg = tr_html.HtmlToMessage('''<a href='[$~URL~$]'><b>[NUM][CAT]</b></a>''')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres == 'BEGIN_LINKBEGIN_BOLDX_NUM_XX_CAT_XEND_BOLDEND_LINK')
++
++ msg = tr_html.HtmlToMessage(
++ '''<font size=-1><a class=q onClick='return window.qs?qs(this):1' '''
++ '''href='http://[WEBSERVER][SEARCH_URI]'>Desktop</a></font>&nbsp;&nbsp;'''
++ '''&nbsp;&nbsp;''')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres ==
++ '''BEGIN_FONTBEGIN_LINKDesktopEND_LINKEND_FONTSPACE''')
++
++ msg = tr_html.HtmlToMessage(
++ '''<br><br><center><font size=-2>&copy;2005 Google </font></center>''', 1)
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres ==
++ u'BEGIN_BREAK_1BEGIN_BREAK_2BEGIN_CENTERBEGIN_FONT\xa92005'
++ u' Google END_FONTEND_CENTER')
++
++ msg = tr_html.HtmlToMessage(
++ '''&nbsp;-&nbsp;<a class=c href=[$~CACHE~$]>Cached</a>''')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres ==
++ '&nbsp;-&nbsp;BEGIN_LINKCachedEND_LINK')
++
++ # Check that upper-case tags are handled correctly.
++ msg = tr_html.HtmlToMessage(
++ '''You can read the <A HREF='http://desktop.google.com/privacypolicy.'''
++ '''html?hl=[LANG_CODE]'>Privacy Policy</A> and <A HREF='http://desktop'''
++ '''.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres ==
++ 'You can read the BEGIN_LINK_1Privacy PolicyEND_LINK_1 and '
++ 'BEGIN_LINK_2Privacy FAQEND_LINK_2 online.')
++
++ # Check that tags with linebreaks immediately preceding them are handled
++ # correctly.
++ msg = tr_html.HtmlToMessage(
++ '''You can read the
++<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
++and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
++ pres = msg.GetPresentableContent()
++ self.failUnless(pres == '''You can read the
++BEGIN_LINK_1Privacy PolicyEND_LINK_1
++and BEGIN_LINK_2Privacy FAQEND_LINK_2 online.''')
++
++ # Check that message-no-break comments are handled correctly.
++ msg = tr_html.HtmlToMessage('''Please <!-- message-no-break --><br /> don't break''')
++ pres = msg.GetPresentableContent()
++ self.failUnlessEqual(pres, '''Please BREAK don't break''')
++
++class TrHtmlUnittest(unittest.TestCase):
++ def testSetAttributes(self):
++ html = tr_html.TrHtml(StringIO(''))
++ self.failUnlessEqual(html.fold_whitespace_, False)
++ html.SetAttributes({})
++ self.failUnlessEqual(html.fold_whitespace_, False)
++ html.SetAttributes({'fold_whitespace': 'false'})
++ self.failUnlessEqual(html.fold_whitespace_, False)
++ html.SetAttributes({'fold_whitespace': 'true'})
++ self.failUnlessEqual(html.fold_whitespace_, True)
++
++ def testFoldWhitespace(self):
++ text = '<td> Test Message </td>'
++
++ html = tr_html.TrHtml(StringIO(text))
++ html.Parse()
++ self.failUnlessEqual(html.skeleton_[1].GetMessage().GetPresentableContent(),
++ 'Test Message')
++
++ html = tr_html.TrHtml(StringIO(text))
++ html.fold_whitespace_ = True
++ html.Parse()
++ self.failUnlessEqual(html.skeleton_[1].GetMessage().GetPresentableContent(),
++ 'Test Message')
++
++ def testTable(self):
++ html = tr_html.TrHtml(StringIO('''<table class="shaded-header"><tr>
++<td class="header-element b expand">Preferences</td>
++<td class="header-element s">
++<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
++</td>
++</tr></table>'''))
++ html.Parse()
++ self.failUnless(html.skeleton_[3].GetMessage().GetPresentableContent() ==
++ 'BEGIN_LINKPreferences&nbsp;HelpEND_LINK')
++
++ def testSubmitAttribute(self):
++ html = tr_html.TrHtml(StringIO('''</td>
++<td class="header-element"><input type=submit value="Save Preferences"
++name=submit2></td>
++</tr></table>'''))
++ html.Parse()
++ self.failUnless(html.skeleton_[1].GetMessage().GetPresentableContent() ==
++ 'Save Preferences')
++
++ def testWhitespaceAfterInlineTag(self):
++ '''Test that even if there is whitespace after an inline tag at the start
++ of a translateable section the inline tag will be included.
++ '''
++ html = tr_html.TrHtml(
++ StringIO('''<label for=DISPLAYNONE><font size=-1> Hello</font>'''))
++ html.Parse()
++ self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
++ '<font size=-1> Hello</font>')
++
++ def testSillyHeader(self):
++ html = tr_html.TrHtml(StringIO('''[!]
++title\tHello
++bingo
++bongo
++bla
++
++<p>Other stuff</p>'''))
++ html.Parse()
++ content = html.skeleton_[1].GetMessage().GetRealContent()
++ self.failUnless(content == 'Hello')
++ self.failUnless(html.skeleton_[-1] == '</p>')
++ # Right after the translateable the nontranslateable should start with
++ # a linebreak (this catches a bug we had).
++ self.failUnless(html.skeleton_[2][0] == '\n')
++
++
++ def testExplicitDescriptions(self):
++ html = tr_html.TrHtml(
++ StringIO('Hello [USER]<br/><!-- desc=explicit -->'
++ '<input type="button">Go!</input>'))
++ html.Parse()
++ msg = html.GetCliques()[1].GetMessage()
++ self.failUnlessEqual(msg.GetDescription(), 'explicit')
++ self.failUnlessEqual(msg.GetRealContent(), 'Go!')
++
++ html = tr_html.TrHtml(
++ StringIO('Hello [USER]<br/><!-- desc=explicit\nmultiline -->'
++ '<input type="button">Go!</input>'))
++ html.Parse()
++ msg = html.GetCliques()[1].GetMessage()
++ self.failUnlessEqual(msg.GetDescription(), 'explicit multiline')
++ self.failUnlessEqual(msg.GetRealContent(), 'Go!')
++
++
++ def testRegressionInToolbarAbout(self):
++ html = tr_html.TrHtml(util.PathFromRoot(r'grit/testdata/toolbar_about.html'))
++ html.Parse()
++ cliques = html.GetCliques()
++ for cl in cliques:
++ content = cl.GetMessage().GetRealContent()
++ if content.count('De parvis grandis acervus erit'):
++ self.failIf(content.count('$/translate'))
++
++
++ def HtmlFromFileWithManualCheck(self, f):
++ html = tr_html.TrHtml(f)
++ html.Parse()
++
++ # For manual results inspection only...
++ list = []
++ for item in html.skeleton_:
++ if isinstance(item, six.string_types):
++ list.append(item)
++ else:
++ list.append(item.GetMessage().GetPresentableContent())
++
++ return html
++
++
++ def testPrivacyHtml(self):
++ html = self.HtmlFromFileWithManualCheck(
++ util.PathFromRoot(r'grit/testdata/privacy.html'))
++
++ self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
++ 'Privacy and Google Desktop Search')
++ self.failUnless(html.skeleton_[3].startswith('<'))
++ self.failUnless(len(html.skeleton_) > 10)
++
++
++ def testPreferencesHtml(self):
++ html = self.HtmlFromFileWithManualCheck(
++ util.PathFromRoot(r'grit/testdata/preferences.html'))
++
++ # Verify that we don't get '[STATUS-MESSAGE]' as the original content of
++ # one of the MessageClique objects (it would be a placeholder-only message
++ # and we're supposed to have stripped those).
++
++ for item in [x for x in html.skeleton_
++ if isinstance(x, clique.MessageClique)]:
++ if (item.GetMessage().GetRealContent() == '[STATUS-MESSAGE]' or
++ item.GetMessage().GetRealContent() == '[ADDIN-DO] [ADDIN-OPTIONS]'):
++ self.fail()
++
++ self.failUnless(len(html.skeleton_) > 100)
++
++ def AssertNumberOfTranslateables(self, files, num):
++ '''Fails if any of the files in files don't have exactly
++ num translateable sections.
++
++ Args:
++ files: ['file1', 'file2']
++ num: 3
++ '''
++ for f in files:
++ f = util.PathFromRoot(r'grit/testdata/%s' % f)
++ html = self.HtmlFromFileWithManualCheck(f)
++ self.failUnless(len(html.GetCliques()) == num)
++
++ def testFewTranslateables(self):
++ self.AssertNumberOfTranslateables(['browser.html', 'email_thread.html',
++ 'header.html', 'mini.html',
++ 'oneclick.html', 'script.html',
++ 'time_related.html', 'versions.html'], 0)
++ self.AssertNumberOfTranslateables(['footer.html', 'hover.html'], 1)
++
++ def testOtherHtmlFilesForManualInspection(self):
++ files = [
++ 'about.html', 'bad_browser.html', 'cache_prefix.html',
++ 'cache_prefix_file.html', 'chat_result.html', 'del_footer.html',
++ 'del_header.html', 'deleted.html', 'details.html', 'email_result.html',
++ 'error.html', 'explicit_web.html', 'footer.html',
++ 'homepage.html', 'indexing_speed.html',
++ 'install_prefs.html', 'install_prefs2.html',
++ 'oem_enable.html', 'oem_non_admin.html', 'onebox.html',
++ 'password.html', 'quit_apps.html', 'recrawl.html',
++ 'searchbox.html', 'sidebar_h.html', 'sidebar_v.html', 'status.html',
++ ]
++ for f in files:
++ self.HtmlFromFileWithManualCheck(
++ util.PathFromRoot(r'grit/testdata/%s' % f))
++
++ def testTranslate(self):
++ # Note that the English translation of documents that use character
++ # literals (e.g. &copy;) will not be the same as the original document
++ # because the character literal will be transformed into the Unicode
++ # character itself. So for this test we choose some relatively complex
++ # HTML without character entities (but with &nbsp; because that's handled
++ # specially).
++ html = tr_html.TrHtml(StringIO(''' <script>
++ <!--
++ function checkOffice() { var w = document.getElementById("h7");
++ var e = document.getElementById("h8"); var o = document.getElementById("h10");
++ if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
++ // -->
++ </script>
++ <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
++ <label for=h7> Word</label><br>
++ <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
++ <label for=h8> Excel</label><br>
++ <input type=checkbox [CHECK-PPT] name=PPT id=h9>
++ <label for=h9> PowerPoint</label><br>
++ </span></td><td nowrap valign=top><span class="s">
++ <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
++ <label for=hpdf> PDF</label><br>
++ <input type=checkbox [CHECK-TXT] name=TXT id=h6>
++ <label for=h6> Text, media, and other files</label><br>
++ </tr>&nbsp;&nbsp;
++ <tr><td nowrap valign=top colspan=3><span class="s"><br />
++ <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
++ <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
++ <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
++ for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
++ </table>'''))
++ html.Parse()
++ trans = html.Translate('en')
++ if (html.GetText() != trans):
++ self.fail()
++
++
++ def testHtmlToMessageWithBlockTags(self):
++ msg = tr_html.HtmlToMessage(
++ 'Hello<p>Howdie<img alt="bingo" src="image.gif">', True)
++ result = msg.GetPresentableContent()
++ self.failUnless(
++ result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
++
++ msg = tr_html.HtmlToMessage(
++ 'Hello<p>Howdie<input type="button" value="bingo">', True)
++ result = msg.GetPresentableContent()
++ self.failUnless(
++ result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
++
++
++ def testHtmlToMessageRegressions(self):
++ msg = tr_html.HtmlToMessage(' - ', True)
++ result = msg.GetPresentableContent()
++ self.failUnless(result == ' - ')
++
++
++ def testEscapeUnescaped(self):
++ text = '&copy;&nbsp; & &quot;&lt;hello&gt;&quot;'
++ unescaped = util.UnescapeHtml(text)
++ self.failUnless(unescaped == u'\u00a9\u00a0 & "<hello>"')
++ escaped_unescaped = util.EscapeHtml(unescaped, True)
++ self.failUnless(escaped_unescaped ==
++ u'\u00a9\u00a0 &amp; &quot;&lt;hello&gt;&quot;')
++
++ def testRegressionCjkHtmlFile(self):
++ # TODO(joi) Fix this problem where unquoted attributes that
++ # have a value that is CJK characters causes the regular expression
++ # match never to return. (culprit is the _ELEMENT regexp(
++ if False:
++ html = self.HtmlFromFileWithManualCheck(util.PathFromRoot(
++ r'grit/testdata/ko_oem_enable_bug.html'))
++ self.failUnless(True)
++
++ def testRegressionCpuHang(self):
++ # If this regression occurs, the unit test will never return
++ html = tr_html.TrHtml(StringIO(
++ '''<input type=text size=12 id=advFileTypeEntry [~SHOW-FILETYPE-BOX~] value="[EXT]" name=ext>'''))
++ html.Parse()
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/gather/txt.py b/tools/grit/grit/gather/txt.py
+new file mode 100644
+index 0000000000..e5c10abc28
+--- /dev/null
++++ b/tools/grit/grit/gather/txt.py
+@@ -0,0 +1,38 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Supports making amessage from a text file.
++'''
++
++from __future__ import print_function
++
++from grit.gather import interface
++from grit import tclib
++
++
++class TxtFile(interface.GathererBase):
++ '''A text file gatherer. Very simple, all text from the file becomes a
++ single clique.
++ '''
++
++ def Parse(self):
++ self.text_ = self._LoadInputFile()
++ self.clique_ = self.uberclique.MakeClique(tclib.Message(text=self.text_))
++
++ def GetText(self):
++ '''Returns the text of what is being gathered.'''
++ return self.text_
++
++ def GetTextualIds(self):
++ return [self.extkey]
++
++ def GetCliques(self):
++ '''Returns the MessageClique objects for all translateable portions.'''
++ return [self.clique_]
++
++ def Translate(self, lang, pseudo_if_not_available=True,
++ skeleton_gatherer=None, fallback_to_english=False):
++ return self.clique_.MessageForLanguage(lang,
++ pseudo_if_not_available,
++ fallback_to_english).GetRealContent()
+diff --git a/tools/grit/grit/gather/txt_unittest.py b/tools/grit/grit/gather/txt_unittest.py
+new file mode 100644
+index 0000000000..abb9ed98d7
+--- /dev/null
++++ b/tools/grit/grit/gather/txt_unittest.py
+@@ -0,0 +1,35 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for TxtFile gatherer'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++
++import unittest
++
++from six import StringIO
++
++from grit.gather import txt
++
++
++class TxtUnittest(unittest.TestCase):
++ def testGather(self):
++ input = StringIO('Hello there\nHow are you?')
++ gatherer = txt.TxtFile(input)
++ gatherer.Parse()
++ self.failUnless(gatherer.GetText() == input.getvalue())
++ self.failUnless(len(gatherer.GetCliques()) == 1)
++ self.failUnless(gatherer.GetCliques()[0].GetMessage().GetRealContent() ==
++ input.getvalue())
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/grd_reader.py b/tools/grit/grit/grd_reader.py
+new file mode 100644
+index 0000000000..b7bb782977
+--- /dev/null
++++ b/tools/grit/grit/grd_reader.py
+@@ -0,0 +1,238 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Class for reading GRD files into memory, without processing them.
++'''
++
++from __future__ import print_function
++
++import os.path
++import sys
++import xml.sax
++import xml.sax.handler
++
++import six
++
++from grit import exception
++from grit import util
++from grit.node import mapping
++from grit.node import misc
++
++
++class StopParsingException(Exception):
++ '''An exception used to stop parsing.'''
++ pass
++
++
++class GrdContentHandler(xml.sax.handler.ContentHandler):
++ def __init__(self, stop_after, debug, dir, defines, tags_to_ignore,
++ target_platform, source):
++ # Invariant of data:
++ # 'root' is the root of the parse tree being created, or None if we haven't
++ # parsed out any elements.
++ # 'stack' is the a stack of elements that we push new nodes onto and
++ # pop from when they finish parsing, or [] if we are not currently parsing.
++ # 'stack[-1]' is the top of the stack.
++ self.root = None
++ self.stack = []
++ self.stop_after = stop_after
++ self.debug = debug
++ self.dir = dir
++ self.defines = defines
++ self.tags_to_ignore = tags_to_ignore or set()
++ self.ignore_depth = 0
++ self.target_platform = target_platform
++ self.source = source
++
++ def startElement(self, name, attrs):
++ if self.ignore_depth or name in self.tags_to_ignore:
++ if self.debug and self.ignore_depth == 0:
++ print("Ignoring element %s and its children" % name)
++ self.ignore_depth += 1
++ return
++
++ if self.debug:
++ attr_list = ' '.join('%s="%s"' % kv for kv in attrs.items())
++ print("Starting parsing of element %s with attributes %r" %
++ (name, attr_list or '(none)'))
++
++ typeattr = attrs.get('type')
++ node = mapping.ElementToClass(name, typeattr)()
++ node.source = self.source
++
++ if self.stack:
++ self.stack[-1].AddChild(node)
++ node.StartParsing(name, self.stack[-1])
++ else:
++ assert self.root is None
++ self.root = node
++ if isinstance(self.root, misc.GritNode):
++ if self.target_platform:
++ self.root.SetTargetPlatform(self.target_platform)
++ node.StartParsing(name, None)
++ if self.defines:
++ node.SetDefines(self.defines)
++ self.stack.append(node)
++
++ for attr, attrval in attrs.items():
++ node.HandleAttribute(attr, attrval)
++
++ def endElement(self, name):
++ if self.ignore_depth:
++ self.ignore_depth -= 1
++ return
++
++ if name == 'part':
++ partnode = self.stack[-1]
++ partnode.started_inclusion = True
++ # Add the contents of the sub-grd file as children of the <part> node.
++ partname = os.path.join(self.dir, partnode.GetInputPath())
++ # Check the GRDP file exists.
++ if not os.path.exists(partname):
++ raise exception.FileNotFound(partname)
++ # Exceptions propagate to the handler in grd_reader.Parse().
++ oldsource = self.source
++ try:
++ self.source = partname
++ xml.sax.parse(partname, GrdPartContentHandler(self))
++ finally:
++ self.source = oldsource
++
++ if self.debug:
++ print("End parsing of element %s" % name)
++ self.stack.pop().EndParsing()
++
++ if name == self.stop_after:
++ raise StopParsingException()
++
++ def characters(self, content):
++ if self.ignore_depth == 0:
++ if self.stack[-1]:
++ self.stack[-1].AppendContent(content)
++
++ def ignorableWhitespace(self, whitespace):
++ # TODO(joi): This is not supported by expat. Should use a different XML
++ # parser?
++ pass
++
++
++class GrdPartContentHandler(xml.sax.handler.ContentHandler):
++ def __init__(self, parent):
++ self.parent = parent
++ self.depth = 0
++
++ def startElement(self, name, attrs):
++ if self.depth:
++ self.parent.startElement(name, attrs)
++ else:
++ if name != 'grit-part':
++ raise exception.MissingElement("root tag must be <grit-part>")
++ if attrs:
++ raise exception.UnexpectedAttribute(
++ "<grit-part> tag must not have attributes")
++ self.depth += 1
++
++ def endElement(self, name):
++ self.depth -= 1
++ if self.depth:
++ self.parent.endElement(name)
++
++ def characters(self, content):
++ self.parent.characters(content)
++
++ def ignorableWhitespace(self, whitespace):
++ self.parent.ignorableWhitespace(whitespace)
++
++
++def Parse(filename_or_stream, dir=None, stop_after=None, first_ids_file=None,
++ debug=False, defines=None, tags_to_ignore=None, target_platform=None,
++ predetermined_ids_file=None):
++ '''Parses a GRD file into a tree of nodes (from grit.node).
++
++ If filename_or_stream is a stream, 'dir' should point to the directory
++ notionally containing the stream (this feature is only used in unit tests).
++
++ If 'stop_after' is provided, the parsing will stop once the first node
++ with this name has been fully parsed (including all its contents).
++
++ If 'debug' is true, lots of information about the parsing events will be
++ printed out during parsing of the file.
++
++ If 'first_ids_file' is non-empty, it is used to override the setting for the
++ first_ids_file attribute of the <grit> root node. Note that the first_ids_file
++ parameter should be relative to the cwd, even though the first_ids_file
++ attribute of the <grit> node is relative to the grd file.
++
++ If 'target_platform' is set, this is used to determine the target
++ platform of builds, instead of using |sys.platform|.
++
++ Args:
++ filename_or_stream: './bla.xml'
++ dir: None (if filename_or_stream is a filename) or '.'
++ stop_after: 'inputs'
++ first_ids_file: 'GRIT_DIR/../gritsettings/resource_ids'
++ debug: False
++ defines: dictionary of defines, like {'chromeos': '1'}
++ target_platform: None or the value that would be returned by sys.platform
++ on your target platform.
++ predetermined_ids_file: File path to a file containing a pre-determined
++ mapping from resource names to resource ids which will be used to assign
++ resource ids to those resources.
++
++ Return:
++ Subclass of grit.node.base.Node
++
++ Throws:
++ grit.exception.Parsing
++ '''
++
++ if isinstance(filename_or_stream, six.string_types):
++ source = filename_or_stream
++ if dir is None:
++ dir = util.dirname(filename_or_stream)
++ else:
++ source = None
++
++ handler = GrdContentHandler(stop_after=stop_after, debug=debug, dir=dir,
++ defines=defines, tags_to_ignore=tags_to_ignore,
++ target_platform=target_platform, source=source)
++ try:
++ xml.sax.parse(filename_or_stream, handler)
++ except StopParsingException:
++ assert stop_after
++ pass
++ except:
++ if not debug:
++ print("parse exception: run GRIT with the -x flag to debug .grd problems")
++ raise
++
++ if handler.root.name != 'grit':
++ raise exception.MissingElement("root tag must be <grit>")
++
++ if hasattr(handler.root, 'SetOwnDir'):
++ # Fix up the base_dir so it is relative to the input file.
++ assert dir is not None
++ handler.root.SetOwnDir(dir)
++
++ if isinstance(handler.root, misc.GritNode):
++ handler.root.SetPredeterminedIdsFile(predetermined_ids_file)
++ if first_ids_file:
++ # Make the path to the first_ids_file relative to the grd file,
++ # unless it begins with GRIT_DIR.
++ GRIT_DIR_PREFIX = 'GRIT_DIR'
++ if not (first_ids_file.startswith(GRIT_DIR_PREFIX)
++ and first_ids_file[len(GRIT_DIR_PREFIX)] in ['/', '\\']):
++ rel_dir = os.path.relpath(os.getcwd(), dir)
++ first_ids_file = util.normpath(os.path.join(rel_dir, first_ids_file))
++ handler.root.attrs['first_ids_file'] = first_ids_file
++ # Assign first ids to the nodes that don't have them.
++ handler.root.AssignFirstIds(filename_or_stream, defines)
++
++ return handler.root
++
++
++if __name__ == '__main__':
++ util.ChangeStdoutEncoding()
++ print(six.text_type(Parse(sys.argv[1])))
+diff --git a/tools/grit/grit/grd_reader_unittest.py b/tools/grit/grit/grd_reader_unittest.py
+new file mode 100644
+index 0000000000..920a92f9c0
+--- /dev/null
++++ b/tools/grit/grit/grd_reader_unittest.py
+@@ -0,0 +1,346 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grd_reader package'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import unittest
++
++import six
++from six import StringIO
++
++from grit import exception
++from grit import grd_reader
++from grit import util
++from grit.node import empty
++from grit.node import message
++
++
++class GrdReaderUnittest(unittest.TestCase):
++ def testParsingAndXmlOutput(self):
++ input = u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit base_dir="." current_release="3" latest_public_release="2" source_lang_id="en-US">
++ <release seq="3">
++ <includes>
++ <include file="images/logo.gif" name="ID_LOGO" type="gif" />
++ </includes>
++ <messages>
++ <if expr="True">
++ <message desc="Printed to greet the currently logged in user" name="IDS_GREETING">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ </if>
++ </messages>
++ <structures>
++ <structure file="rc_files/dialogs.rc" name="IDD_NARROW_DIALOG" type="dialog">
++ <skeleton expr="lang == 'fr-FR'" file="bla.rc" variant_of_revision="3" />
++ </structure>
++ <structure file="rc_files/version.rc" name="VS_VERSION_INFO" type="version" />
++ </structures>
++ </release>
++ <translations>
++ <file lang="nl" path="nl_translations.xtb" />
++ </translations>
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="resource.rc" lang="en-US" type="rc_all" />
++ </outputs>
++</grit>'''
++ pseudo_file = StringIO(input)
++ tree = grd_reader.Parse(pseudo_file, '.')
++ output = six.text_type(tree)
++ expected_output = input.replace(u' base_dir="."', u'')
++ self.assertEqual(expected_output, output)
++ self.failUnless(tree.GetNodeById('IDS_GREETING'))
++
++
++ def testStopAfter(self):
++ input = u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="resource.rc" lang="en-US" type="rc_all" />
++ </outputs>
++ <release seq="3">
++ <includes>
++ <include type="gif" name="ID_LOGO" file="images/logo.gif"/>
++ </includes>
++ </release>
++</grit>'''
++ pseudo_file = StringIO(input)
++ tree = grd_reader.Parse(pseudo_file, '.', stop_after='outputs')
++ # only an <outputs> child
++ self.failUnless(len(tree.children) == 1)
++ self.failUnless(tree.children[0].name == 'outputs')
++
++ def testLongLinesWithComments(self):
++ input = u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ This is a very long line with no linebreaks yes yes it stretches on <!--
++ -->and on <!--
++ -->and on!
++ </message>
++ </messages>
++ </release>
++</grit>'''
++ pseudo_file = StringIO(input)
++ tree = grd_reader.Parse(pseudo_file, '.')
++
++ greeting = tree.GetNodeById('IDS_GREETING')
++ self.failUnless(greeting.GetCliques()[0].GetMessage().GetRealContent() ==
++ 'This is a very long line with no linebreaks yes yes it '
++ 'stretches on and on and on!')
++
++ def doTestAssignFirstIds(self, first_ids_path):
++ input = u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3"
++ base_dir="." first_ids_file="%s">
++ <release seq="3">
++ <messages>
++ <message name="IDS_TEST" desc="test">
++ test
++ </message>
++ </messages>
++ </release>
++</grit>''' % first_ids_path
++ pseudo_file = StringIO(input)
++ grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
++ '..')
++ fake_input_path = os.path.join(
++ grit_root_dir, "grit/testdata/chrome/app/generated_resources.grd")
++ root = grd_reader.Parse(pseudo_file, os.path.split(fake_input_path)[0])
++ root.AssignFirstIds(fake_input_path, {})
++ messages_node = root.children[0].children[0]
++ self.failUnless(isinstance(messages_node, empty.MessagesNode))
++ self.failUnless(messages_node.attrs["first_id"] !=
++ empty.MessagesNode().DefaultAttributes()["first_id"])
++
++ def testAssignFirstIds(self):
++ self.doTestAssignFirstIds("../../tools/grit/resource_ids")
++
++ def testAssignFirstIdsUseGritDir(self):
++ self.doTestAssignFirstIds("GRIT_DIR/grit/testdata/tools/grit/resource_ids")
++
++ def testAssignFirstIdsMultipleMessages(self):
++ """If there are multiple messages sections, the resource_ids file
++ needs to list multiple first_id values."""
++ input = u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3"
++ base_dir="." first_ids_file="resource_ids">
++ <release seq="3">
++ <messages>
++ <message name="IDS_TEST" desc="test">
++ test
++ </message>
++ </messages>
++ <messages>
++ <message name="IDS_TEST2" desc="test">
++ test2
++ </message>
++ </messages>
++ </release>
++</grit>'''
++ pseudo_file = StringIO(input)
++ grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
++ '..')
++ fake_input_path = os.path.join(grit_root_dir, "grit/testdata/test.grd")
++
++ root = grd_reader.Parse(pseudo_file, os.path.split(fake_input_path)[0])
++ root.AssignFirstIds(fake_input_path, {})
++ messages_node = root.children[0].children[0]
++ self.assertTrue(isinstance(messages_node, empty.MessagesNode))
++ self.assertEqual('100', messages_node.attrs["first_id"])
++ messages_node = root.children[0].children[1]
++ self.assertTrue(isinstance(messages_node, empty.MessagesNode))
++ self.assertEqual('10000', messages_node.attrs["first_id"])
++
++ def testUseNameForIdAndPpIfdef(self):
++ input = u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <if expr="pp_ifdef('hello')">
++ <message name="IDS_HELLO" use_name_for_id="true">
++ Hello!
++ </message>
++ </if>
++ </messages>
++ </release>
++</grit>'''
++ pseudo_file = StringIO(input)
++ root = grd_reader.Parse(pseudo_file, '.', defines={'hello': '1'})
++
++ # Check if the ID is set to the name. In the past, there was a bug
++ # that caused the ID to be a generated number.
++ hello = root.GetNodeById('IDS_HELLO')
++ self.failUnless(hello.GetCliques()[0].GetId() == 'IDS_HELLO')
++
++ def testUseNameForIdWithIfElse(self):
++ input = u'''<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <if expr="pp_ifdef('hello')">
++ <then>
++ <message name="IDS_HELLO" use_name_for_id="true">
++ Hello!
++ </message>
++ </then>
++ <else>
++ <message name="IDS_HELLO" use_name_for_id="true">
++ Yellow!
++ </message>
++ </else>
++ </if>
++ </messages>
++ </release>
++</grit>'''
++ pseudo_file = StringIO(input)
++ root = grd_reader.Parse(pseudo_file, '.', defines={'hello': '1'})
++
++ # Check if the ID is set to the name. In the past, there was a bug
++ # that caused the ID to be a generated number.
++ hello = root.GetNodeById('IDS_HELLO')
++ self.failUnless(hello.GetCliques()[0].GetId() == 'IDS_HELLO')
++
++ def testPartInclusionAndCorrectSource(self):
++ arbitrary_path_grd = u'''\
++ <grit-part>
++ <message name="IDS_TEST5" desc="test5">test5</message>
++ </grit-part>'''
++ tmp_dir = util.TempDir({'arbitrary_path.grp': arbitrary_path_grd})
++ arbitrary_path_grd_file = tmp_dir.GetPath('arbitrary_path.grp')
++ top_grd = u'''\
++ <grit latest_public_release="2" current_release="3">
++ <release seq="3">
++ <messages>
++ <message name="IDS_TEST" desc="test">
++ test
++ </message>
++ <part file="sub.grp" />
++ <part file="%s" />
++ </messages>
++ </release>
++ </grit>''' % arbitrary_path_grd_file
++ sub_grd = u'''\
++ <grit-part>
++ <message name="IDS_TEST2" desc="test2">test2</message>
++ <part file="subsub.grp" />
++ <message name="IDS_TEST3" desc="test3">test3</message>
++ </grit-part>'''
++ subsub_grd = u'''\
++ <grit-part>
++ <message name="IDS_TEST4" desc="test4">test4</message>
++ </grit-part>'''
++ expected_output = u'''\
++ <grit current_release="3" latest_public_release="2">
++ <release seq="3">
++ <messages>
++ <message desc="test" name="IDS_TEST">
++ test
++ </message>
++ <part file="sub.grp">
++ <message desc="test2" name="IDS_TEST2">
++ test2
++ </message>
++ <part file="subsub.grp">
++ <message desc="test4" name="IDS_TEST4">
++ test4
++ </message>
++ </part>
++ <message desc="test3" name="IDS_TEST3">
++ test3
++ </message>
++ </part>
++ <part file="%s">
++ <message desc="test5" name="IDS_TEST5">
++ test5
++ </message>
++ </part>
++ </messages>
++ </release>
++ </grit>''' % arbitrary_path_grd_file
++
++ with util.TempDir({'sub.grp': sub_grd,
++ 'subsub.grp': subsub_grd}) as tmp_sub_dir:
++ output = grd_reader.Parse(StringIO(top_grd),
++ tmp_sub_dir.GetPath())
++ correct_sources = {
++ 'IDS_TEST': None,
++ 'IDS_TEST2': tmp_sub_dir.GetPath('sub.grp'),
++ 'IDS_TEST3': tmp_sub_dir.GetPath('sub.grp'),
++ 'IDS_TEST4': tmp_sub_dir.GetPath('subsub.grp'),
++ 'IDS_TEST5': arbitrary_path_grd_file,
++ }
++
++ for node in output.ActiveDescendants():
++ with node:
++ if isinstance(node, message.MessageNode):
++ self.assertEqual(correct_sources[node.attrs.get('name')], node.source)
++ self.assertEqual(expected_output.split(), output.FormatXml().split())
++ tmp_dir.CleanUp()
++
++ def testPartInclusionFailure(self):
++ template = u'''
++ <grit latest_public_release="2" current_release="3">
++ <outputs>
++ %s
++ </outputs>
++ </grit>'''
++
++ part_failures = [
++ (exception.UnexpectedContent, u'<part file="x">fnord</part>'),
++ (exception.UnexpectedChild,
++ u'<part file="x"><output filename="x" type="y" /></part>'),
++ (exception.FileNotFound, u'<part file="yet_created_x" />'),
++ ]
++ for raises, data in part_failures:
++ data = StringIO(template % data)
++ self.assertRaises(raises, grd_reader.Parse, data, '.')
++
++ gritpart_failures = [
++ (exception.UnexpectedAttribute, u'<grit-part file="xyz"></grit-part>'),
++ (exception.MissingElement, u'<output filename="x" type="y" />'),
++ ]
++ for raises, data in gritpart_failures:
++ top_grd = StringIO(template % u'<part file="bad.grp" />')
++ with util.TempDir({'bad.grp': data}) as temp_dir:
++ self.assertRaises(raises, grd_reader.Parse, top_grd, temp_dir.GetPath())
++
++ def testEarlyEnoughPlatformSpecification(self):
++ # This is a regression test for issue
++ # https://code.google.com/p/grit-i18n/issues/detail?id=23
++ grd_text = u'''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="1" current_release="1">
++ <release seq="1">
++ <messages>
++ <if expr="not pp_ifdef('use_titlecase')">
++ <message name="IDS_XYZ">foo</message>
++ </if>
++ <!-- The assumption is that use_titlecase is never true for
++ this platform. When the platform isn't set to 'android'
++ early enough, we get a duplicate message name. -->
++ <if expr="os == '%s'">
++ <message name="IDS_XYZ">boo</message>
++ </if>
++ </messages>
++ </release>
++ </grit>''' % sys.platform
++ with util.TempDir({}) as temp_dir:
++ grd_reader.Parse(StringIO(grd_text), temp_dir.GetPath(),
++ target_platform='android')
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/grit-todo.xml b/tools/grit/grit/grit-todo.xml
+new file mode 100644
+index 0000000000..b8c20fdfad
+--- /dev/null
++++ b/tools/grit/grit/grit-todo.xml
+@@ -0,0 +1,62 @@
++<?xml version="1.0" encoding="windows-1252"?>
++<TODOLIST FILEFORMAT="6" PROJECTNAME="GRIT" NEXTUNIQUEID="56" FILEVERSION="69" LASTMODIFIED="2005-08-19">
++ <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38453.49975694" TITLE="check 'name' attribute is unique" TIMEESTUNITS="H" ID="2" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-04-11" POS="22" DONEDATE="38453.00000000"/>
++ <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48189815" TITLE="import id-calculating code" TIMEESTUNITS="H" ID="3" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-05-16" POS="13" DONEDATE="38488.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48209491" TITLE="Import tool for existing translations" TIMEESTUNITS="H" ID="6" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="12" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00805556" TITLE="Export XMBs" TIMEESTUNITS="H" ID="8" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="20" DONEDATE="38511.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00924769" TITLE="Initial Integration" TIMEESTUNITS="H" ID="10" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="10" DONEDATE="38511.00000000">
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.54048611" TITLE="parser for %s strings" TIMEESTUNITS="H" ID="4" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-24" POS="2" DONEDATE="38496.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00261574" TITLE="import tool for existing RC files" TIMEESTUNITS="H" ID="5" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-25" POS="4" DONEDATE="38497.00000000">
++ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.92990741" TITLE="handle button value= and img alt= in message HTML text" TIMEESTUNITS="H" ID="22" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-24" POS="1" DONEDATE="38496.00000000"/>
++ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00258102" TITLE="&amp;nbsp; bug" TIMEESTUNITS="H" ID="23" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-25" POS="2" DONEDATE="38497.00000000"/>
++ </TASK>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61171296" TITLE="grit build" TIMEESTUNITS="H" ID="7" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="6" DONEDATE="38490.00000000">
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61168981" TITLE="use IDs gathered from gatherers for .h file" TIMEESTUNITS="H" ID="20" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="1" DONEDATE="38490.00000000"/>
++ </TASK>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.55199074" TITLE="SCons Integration" TIMEESTUNITS="H" ID="9" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-01" POS="1" DONEDATE="38504.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61181713" TITLE="handle includes" TIMEESTUNITS="H" ID="12" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="5" DONEDATE="38490.00000000"/>
++ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.98567130" TITLE="output translated HTML templates" TIMEESTUNITS="H" ID="25" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-04" POS="3" DONEDATE="38507.00000000"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.99394676" TITLE="bug: re-escape too much in RC dialogs etc." TIMEESTUNITS="H" ID="38" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-04" POS="7" DONEDATE="38507.00000000"/>
++ </TASK>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46444444" TITLE="handle structure variants" TIMEESTUNITS="H" ID="11" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="15" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46456019" TITLE="handle include variants" TIMEESTUNITS="H" ID="13" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="17" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46537037" TITLE="handle translateable text for includes (e.g. image text)" TIMEESTUNITS="H" ID="14" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="14" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46712963" TITLE="ddoc" TIMEESTUNITS="H" ID="15" STARTDATE="38488.00000000" POS="4">
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46718750" TITLE="review comments miket" TIMEESTUNITS="H" ID="16" STARTDATE="38488.00000000" POS="2"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46722222" TITLE="review comments pdoyle" TIMEESTUNITS="H" ID="17" STARTDATE="38488.00000000" POS="1"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46732639" TITLE="remove 'extkey' from structure" TIMEESTUNITS="H" ID="18" STARTDATE="38488.00000000" POS="3"/>
++ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.53537037" TITLE="add 'encoding' to structure" TIMEESTUNITS="H" ID="19" STARTDATE="38488.00000000" POS="6"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38503.55304398" TITLE="document limitation: emitter doesn't emit the translated HTML templates" TIMEESTUNITS="H" ID="30" STARTDATE="38503.00000000" POS="4"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.58541667" TITLE="add 'internal_comment' to &lt;message&gt;" TIMEESTUNITS="H" ID="32" STARTDATE="38503.00000000" POS="5"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.73391204" TITLE="&lt;outputs&gt; can not have paths (because of SCons integration - goes to build dir)" TIMEESTUNITS="H" ID="36" STARTDATE="38503.00000000" POS="9"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38506.64265046" TITLE="&lt;identifers&gt; and &lt;identifier&gt; nodes" TIMEESTUNITS="H" ID="37" STARTDATE="38503.00000000" POS="10"/>
++ <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38526.62344907" TITLE="&lt;structure&gt; can have 'exclude_from_rc' attribute (default false)" TIMEESTUNITS="H" ID="47" STARTDATE="38526.00000000" POS="8"/>
++ <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38531.94135417" TITLE="add 'enc_check' to &lt;grit&gt;" TIMEESTUNITS="H" ID="48" STARTDATE="38526.00000000" POS="7"/>
++ </TASK>
++ <TASK STARTDATESTRING="2005-05-18" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38492.51549769" TITLE="handle nontranslateable messages (in MessageClique?)" TIMEESTUNITS="H" ID="21" PERCENTDONE="100" STARTDATE="38490.00000000" DONEDATESTRING="2005-06-16" POS="16" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70454861" TITLE="ask cprince about SCons builder in new mk system" TIMEESTUNITS="H" ID="24" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-02" POS="25" DONEDATE="38505.00000000"/>
++ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.57436343" TITLE="fix AOL resource in trunk (&quot;???????&quot;)" TIMEESTUNITS="H" ID="26" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-01" POS="19" DONEDATE="38504.00000000"/>
++ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38498.53893519" TITLE="rc_all vs. rc_translateable vs. rc_nontranslateable" TIMEESTUNITS="H" ID="27" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-16" POS="6" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38509.45532407" TITLE="make separate .grb &quot;outputs&quot; file (and change SCons integ) (??)" TIMEESTUNITS="H" ID="28" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-06" POS="8" DONEDATE="38509.00000000"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00939815" TITLE="fix unit tests so they run from any directory" TIMEESTUNITS="H" ID="33" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-08" POS="18" DONEDATE="38511.00000000"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38508.96640046" TITLE="Change R4 tool to CC correct team(s) on GRIT changes" TIMEESTUNITS="H" ID="39" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-05" POS="23" DONEDATE="38508.00000000"/>
++ <TASK STARTDATESTRING="2005-06-07" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00881944" TITLE="Document why wrapper.rc" TIMEESTUNITS="H" ID="40" PERCENTDONE="100" STARTDATE="38510.00000000" DONEDATESTRING="2005-06-08" POS="21" DONEDATE="38511.00000000"/>
++ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00804398" TITLE="import XTBs" TIMEESTUNITS="H" ID="41" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="11" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00875000" TITLE="Nightly build integration" TIMEESTUNITS="H" ID="42" STARTDATE="38511.00000000" POS="3"/>
++ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00891204" TITLE="BUGS" TIMEESTUNITS="H" ID="43" STARTDATE="38511.00000000" POS="24">
++ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38513.03375000" TITLE="Should report error if RC-section structure refers to does not exist" TIMEESTUNITS="H" ID="44" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-10" POS="1" DONEDATE="38513.00000000"/>
++ </TASK>
++ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00981481" TITLE="NEW FEATURES" TIMEESTUNITS="H" ID="45" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="7" DONEDATE="38519.00000000">
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70077546" TITLE="Implement line-continuation feature (\ at end of line?)" TIMEESTUNITS="H" ID="34" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="1" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70262731" TITLE="Implement conditional inclusion &amp; reflect the conditionals from R3 RC file" TIMEESTUNITS="H" ID="35" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="2" DONEDATE="38519.00000000"/>
++ </TASK>
++ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.01046296" TITLE="TC integration (one-way TO the TC)" TIMEESTUNITS="H" ID="46" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="5" DONEDATE="38519.00000000"/>
++ <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38533.59072917" TITLE="bazaar20 ad for GRIT help" TIMEESTUNITS="H" ID="49" STARTDATE="38533.00000000" POS="2">
++ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72346065" TITLE="bazaar20 ideas" TIMEESTUNITS="H" ID="51" STARTDATE="38583.00000000" POS="1">
++ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72354167" TITLE="GUI for adding/editing messages" TIMEESTUNITS="H" ID="52" STARTDATE="38583.00000000" POS="2"/>
++ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72365741" TITLE="XLIFF import/export" TIMEESTUNITS="H" ID="54" STARTDATE="38583.00000000" POS="1"/>
++ </TASK>
++ </TASK>
++ <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73721065" TITLE="internal_comment for all resource nodes (not just &lt;message&gt;)" TIMEESTUNITS="H" ID="50" PERCENTDONE="100" STARTDATE="38533.00000000" DONEDATESTRING="2005-08-19" POS="9" DONEDATE="38583.73721065"/>
++ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73743056" TITLE="Preserve XML comments - this gives us line continuation and more" TIMEESTUNITS="H" ID="55" STARTDATE="38583.72326389" POS="1"/>
++</TODOLIST>
+diff --git a/tools/grit/grit/grit_runner.py b/tools/grit/grit/grit_runner.py
+new file mode 100644
+index 0000000000..26aa0d58c4
+--- /dev/null
++++ b/tools/grit/grit/grit_runner.py
+@@ -0,0 +1,334 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Command processor for GRIT. This is the script you invoke to run the various
++GRIT tools.
++"""
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import getopt
++
++from grit import util
++
++import grit.extern.FP
++
++# Tool info factories; these import only within each factory to avoid
++# importing most of the GRIT code until required.
++def ToolFactoryBuild():
++ import grit.tool.build
++ return grit.tool.build.RcBuilder()
++
++def ToolFactoryBuildInfo():
++ import grit.tool.buildinfo
++ return grit.tool.buildinfo.DetermineBuildInfo()
++
++def ToolFactoryCount():
++ import grit.tool.count
++ return grit.tool.count.CountMessage()
++
++def ToolFactoryDiffStructures():
++ import grit.tool.diff_structures
++ return grit.tool.diff_structures.DiffStructures()
++
++def ToolFactoryMenuTranslationsFromParts():
++ import grit.tool.menu_from_parts
++ return grit.tool.menu_from_parts.MenuTranslationsFromParts()
++
++def ToolFactoryNewGrd():
++ import grit.tool.newgrd
++ return grit.tool.newgrd.NewGrd()
++
++def ToolFactoryResizeDialog():
++ import grit.tool.resize
++ return grit.tool.resize.ResizeDialog()
++
++def ToolFactoryRc2Grd():
++ import grit.tool.rc2grd
++ return grit.tool.rc2grd.Rc2Grd()
++
++def ToolFactoryTest():
++ import grit.tool.test
++ return grit.tool.test.TestTool()
++
++def ToolFactoryTranslationToTc():
++ import grit.tool.transl2tc
++ return grit.tool.transl2tc.TranslationToTc()
++
++def ToolFactoryUnit():
++ import grit.tool.unit
++ return grit.tool.unit.UnitTestTool()
++
++
++def ToolFactoryUpdateResourceIds():
++ import grit.tool.update_resource_ids
++ return grit.tool.update_resource_ids.UpdateResourceIds()
++
++
++def ToolFactoryXmb():
++ import grit.tool.xmb
++ return grit.tool.xmb.OutputXmb()
++
++def ToolAndroid2Grd():
++ import grit.tool.android2grd
++ return grit.tool.android2grd.Android2Grd()
++
++# Keys for the following map
++_FACTORY = 1
++_REQUIRES_INPUT = 2
++_HIDDEN = 3 # optional key - presence indicates tool is hidden
++
++# Maps tool names to the tool's module. Done as a list of (key, value) tuples
++# instead of a map to preserve ordering.
++_TOOLS = [
++ ['android2grd', {
++ _FACTORY: ToolAndroid2Grd,
++ _REQUIRES_INPUT: False
++ }],
++ ['build', {
++ _FACTORY: ToolFactoryBuild,
++ _REQUIRES_INPUT: True
++ }],
++ ['buildinfo', {
++ _FACTORY: ToolFactoryBuildInfo,
++ _REQUIRES_INPUT: True
++ }],
++ ['count', {
++ _FACTORY: ToolFactoryCount,
++ _REQUIRES_INPUT: True
++ }],
++ [
++ 'menufromparts',
++ {
++ _FACTORY: ToolFactoryMenuTranslationsFromParts,
++ _REQUIRES_INPUT: True,
++ _HIDDEN: True
++ }
++ ],
++ ['newgrd', {
++ _FACTORY: ToolFactoryNewGrd,
++ _REQUIRES_INPUT: False
++ }],
++ ['rc2grd', {
++ _FACTORY: ToolFactoryRc2Grd,
++ _REQUIRES_INPUT: False
++ }],
++ ['resize', {
++ _FACTORY: ToolFactoryResizeDialog,
++ _REQUIRES_INPUT: True
++ }],
++ ['sdiff', {
++ _FACTORY: ToolFactoryDiffStructures,
++ _REQUIRES_INPUT: False
++ }],
++ ['test', {
++ _FACTORY: ToolFactoryTest,
++ _REQUIRES_INPUT: True,
++ _HIDDEN: True
++ }],
++ [
++ 'transl2tc',
++ {
++ _FACTORY: ToolFactoryTranslationToTc,
++ _REQUIRES_INPUT: False
++ }
++ ],
++ ['unit', {
++ _FACTORY: ToolFactoryUnit,
++ _REQUIRES_INPUT: False
++ }],
++ [
++ 'update_resource_ids',
++ {
++ _FACTORY: ToolFactoryUpdateResourceIds,
++ _REQUIRES_INPUT: False
++ }
++ ],
++ ['xmb', {
++ _FACTORY: ToolFactoryXmb,
++ _REQUIRES_INPUT: True
++ }],
++]
++
++
++def PrintUsage():
++ tool_list = ''
++ for (tool, info) in _TOOLS:
++ if not _HIDDEN in info:
++ tool_list += ' %-12s %s\n' % (
++ tool, info[_FACTORY]().ShortDescription())
++
++ print("""GRIT - the Google Resource and Internationalization Tool
++
++Usage: grit [GLOBALOPTIONS] TOOL [args to tool]
++
++Global options:
++
++ -i INPUT Specifies the INPUT file to use (a .grd file). If this is not
++ specified, GRIT will look for the environment variable GRIT_INPUT.
++ If it is not present either, GRIT will try to find an input file
++ named 'resource.grd' in the current working directory.
++
++ -h MODULE Causes GRIT to use MODULE.UnsignedFingerPrint instead of
++ grit.extern.FP.UnsignedFingerprint. MODULE must be
++ available somewhere in the PYTHONPATH search path.
++
++ -v Print more verbose runtime information.
++
++ -x Print extremely verbose runtime information. Implies -v
++
++ -p FNAME Specifies that GRIT should profile its execution and output the
++ results to the file FNAME.
++
++Tools:
++
++ TOOL can be one of the following:
++%s
++ For more information on how to use a particular tool, and the specific
++ arguments you can send to that tool, execute 'grit help TOOL'
++""" % (tool_list))
++
++
++class Options(object):
++ """Option storage and parsing."""
++
++ def __init__(self):
++ self.hash = None
++ self.input = None
++ self.verbose = False
++ self.extra_verbose = False
++ self.output_stream = sys.stdout
++ self.profile_dest = None
++
++ def ReadOptions(self, args):
++ """Reads options from the start of args and returns the remainder."""
++ (opts, args) = getopt.getopt(args, 'vxi:p:h:', ('help',))
++ for (key, val) in opts:
++ if key == '-h': self.hash = val
++ elif key == '-i': self.input = val
++ elif key == '-v':
++ self.verbose = True
++ util.verbose = True
++ elif key == '-x':
++ self.verbose = True
++ util.verbose = True
++ self.extra_verbose = True
++ util.extra_verbose = True
++ elif key == '-p': self.profile_dest = val
++ elif key == '--help':
++ PrintUsage()
++ sys.exit(0)
++
++ if not self.input:
++ if 'GRIT_INPUT' in os.environ:
++ self.input = os.environ['GRIT_INPUT']
++ else:
++ self.input = 'resource.grd'
++
++ return args
++
++ def __repr__(self):
++ return '(verbose: %d, input: %s)' % (
++ self.verbose, self.input)
++
++
++def _GetToolInfo(tool):
++ """Returns the info map for the tool named 'tool' or None if there is no
++ such tool."""
++ matches = [t for t in _TOOLS if t[0] == tool]
++ if not matches:
++ return None
++ else:
++ return matches[0][1]
++
++
++def Main(args=None):
++ """Parses arguments and does the appropriate thing."""
++ util.ChangeStdoutEncoding()
++
++ # Support for setuptools console wrappers.
++ if args is None:
++ args = sys.argv[1:]
++
++ options = Options()
++ try:
++ args = options.ReadOptions(args) # args may be shorter after this
++ except getopt.GetoptError as e:
++ print("grit:", str(e))
++ print("Try running 'grit help' for valid options.")
++ return 1
++ if not args:
++ print("No tool provided. Try running 'grit help' for a list of tools.")
++ return 2
++
++ tool = args[0]
++ if tool == 'help':
++ if len(args) == 1:
++ PrintUsage()
++ return 0
++ else:
++ tool = args[1]
++ if not _GetToolInfo(tool):
++ print("No such tool. Try running 'grit help' for a list of tools.")
++ return 2
++
++ print("Help for 'grit %s' (for general help, run 'grit help'):\n" %
++ (tool,))
++ _GetToolInfo(tool)[_FACTORY]().ShowUsage()
++ return 0
++ if not _GetToolInfo(tool):
++ print("No such tool. Try running 'grit help' for a list of tools.")
++ return 2
++
++ try:
++ if _GetToolInfo(tool)[_REQUIRES_INPUT]:
++ os.stat(options.input)
++ except OSError:
++ print('Input file %s not found.\n'
++ 'To specify a different input file:\n'
++ ' 1. Use the GRIT_INPUT environment variable.\n'
++ ' 2. Use the -i command-line option. This overrides '
++ 'GRIT_INPUT.\n'
++ ' 3. Specify neither GRIT_INPUT or -i and GRIT will try to load '
++ "'resource.grd'\n"
++ ' from the current directory.' % options.input)
++ return 2
++
++ if options.hash:
++ grit.extern.FP.UseUnsignedFingerPrintFromModule(options.hash)
++
++ try:
++ toolobject = _GetToolInfo(tool)[_FACTORY]()
++ if options.profile_dest:
++ import hotshot
++ prof = hotshot.Profile(options.profile_dest)
++ return prof.runcall(toolobject.Run, options, args[1:])
++ else:
++ return toolobject.Run(options, args[1:])
++ except getopt.GetoptError as e:
++ print("grit: %s: %s" % (tool, str(e)))
++ print("Try running 'grit help %s' for valid options." % (tool,))
++ return 1
++
++
++if __name__ == '__main__':
++ sys.path.append(
++ os.path.join(
++ os.path.dirname(
++ os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
++ 'diagnosis'))
++ try:
++ import crbug_1001171
++ with crbug_1001171.DumpStateOnLookupError():
++ sys.exit(Main(sys.argv[1:]))
++ except ImportError:
++ pass
++
++ sys.exit(Main(sys.argv[1:]))
+diff --git a/tools/grit/grit/grit_runner_unittest.py b/tools/grit/grit/grit_runner_unittest.py
+new file mode 100644
+index 0000000000..1487001d81
+--- /dev/null
++++ b/tools/grit/grit/grit_runner_unittest.py
+@@ -0,0 +1,42 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.py'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import unittest
++
++from six import StringIO
++
++from grit import util
++import grit.grit_runner
++
++class OptionArgsUnittest(unittest.TestCase):
++ def setUp(self):
++ self.buf = StringIO()
++ self.old_stdout = sys.stdout
++ sys.stdout = self.buf
++
++ def tearDown(self):
++ sys.stdout = self.old_stdout
++
++ def testSimple(self):
++ grit.grit_runner.Main(['-i',
++ util.PathFromRoot('grit/testdata/simple-input.xml'),
++ 'test', 'bla', 'voff', 'ga'])
++ output = self.buf.getvalue()
++ self.failUnless(output.count("'test'") == 0) # tool name doesn't occur
++ self.failUnless(output.count('bla'))
++ self.failUnless(output.count('simple-input.xml'))
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/lazy_re.py b/tools/grit/grit/lazy_re.py
+new file mode 100644
+index 0000000000..5c461e87e7
+--- /dev/null
++++ b/tools/grit/grit/lazy_re.py
+@@ -0,0 +1,46 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''In GRIT, we used to compile a lot of regular expressions at parse
++time. Since many of them never get used, we use lazy_re to compile
++them on demand the first time they are used, thus speeding up startup
++time in some cases.
++'''
++
++from __future__ import print_function
++
++import re
++
++
++class LazyRegexObject(object):
++ '''This object creates a RegexObject with the arguments passed in
++ its constructor, the first time any attribute except the several on
++ the class itself is accessed. This accomplishes lazy compilation of
++ the regular expression while maintaining a nearly-identical
++ interface.
++ '''
++
++ def __init__(self, *args, **kwargs):
++ self._stash_args = args
++ self._stash_kwargs = kwargs
++ self._lazy_re = None
++
++ def _LazyInit(self):
++ if not self._lazy_re:
++ self._lazy_re = re.compile(*self._stash_args, **self._stash_kwargs)
++
++ def __getattribute__(self, name):
++ if name in ('_LazyInit', '_lazy_re', '_stash_args', '_stash_kwargs'):
++ return object.__getattribute__(self, name)
++ else:
++ self._LazyInit()
++ return getattr(self._lazy_re, name)
++
++
++def compile(*args, **kwargs):
++ '''Creates a LazyRegexObject that, when invoked on, will compile a
++ re.RegexObject (via re.compile) with the same arguments passed to
++ this function, and delegate almost all of its methods to it.
++ '''
++ return LazyRegexObject(*args, **kwargs)
+diff --git a/tools/grit/grit/lazy_re_unittest.py b/tools/grit/grit/lazy_re_unittest.py
+new file mode 100644
+index 0000000000..8488b454ee
+--- /dev/null
++++ b/tools/grit/grit/lazy_re_unittest.py
+@@ -0,0 +1,40 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit test for lazy_re.
++'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import re
++import unittest
++
++from grit import lazy_re
++
++
++class LazyReUnittest(unittest.TestCase):
++
++ def testCreatedOnlyOnDemand(self):
++ rex = lazy_re.compile('bingo')
++ self.assertEqual(None, rex._lazy_re)
++ self.assertTrue(rex.match('bingo'))
++ self.assertNotEqual(None, rex._lazy_re)
++
++ def testJustKwargsWork(self):
++ rex = lazy_re.compile(flags=re.I, pattern='BiNgO')
++ self.assertTrue(rex.match('bingo'))
++
++ def testPositionalAndKwargsWork(self):
++ rex = lazy_re.compile('BiNgO', flags=re.I)
++ self.assertTrue(rex.match('bingo'))
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/__init__.py b/tools/grit/grit/node/__init__.py
+new file mode 100644
+index 0000000000..2fc0d3360c
+--- /dev/null
++++ b/tools/grit/grit/node/__init__.py
+@@ -0,0 +1,8 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Package 'grit.node'
++'''
++
++pass
+diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py
+new file mode 100644
+index 0000000000..40859d301d
+--- /dev/null
++++ b/tools/grit/grit/node/base.py
+@@ -0,0 +1,670 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Base types for nodes in a GRIT resource tree.
++'''
++
++from __future__ import print_function
++
++import ast
++import os
++import struct
++import sys
++from xml.sax import saxutils
++
++import six
++
++from grit import constants
++from grit import clique
++from grit import exception
++from grit import util
++from grit.node import brotli_util
++import grit.format.gzip_string
++
++
++class Node(object):
++ '''An item in the tree that has children.'''
++
++ # Valid content types that can be returned by _ContentType()
++ _CONTENT_TYPE_NONE = 0 # No CDATA content but may have children
++ _CONTENT_TYPE_CDATA = 1 # Only CDATA, no children.
++ _CONTENT_TYPE_MIXED = 2 # CDATA and children, possibly intermingled
++
++ # Types of files to be compressed by default.
++ _COMPRESS_BY_DEFAULT_EXTENSIONS = ('.js', '.html', '.css', '.svg')
++
++ # Default nodes to not whitelist skipped
++ _whitelist_marked_as_skip = False
++
++ # A class-static cache to speed up EvaluateExpression().
++ # Keys are expressions (e.g. 'is_ios and lang == "fr"'). Values are tuples
++ # (code, variables_in_expr) where code is the compiled expression and can be
++ # directly eval'd, and variables_in_expr is the list of variable and method
++ # names used in the expression (e.g. ['is_ios', 'lang']).
++ eval_expr_cache = {}
++
++ def __init__(self):
++ self.children = [] # A list of child elements
++ self.mixed_content = [] # A list of u'' and/or child elements (this
++ # duplicates 'children' but
++ # is needed to preserve markup-type content).
++ self.name = u'' # The name of this element
++ self.attrs = {} # The set of attributes (keys to values)
++ self.parent = None # Our parent unless we are the root element.
++ self.uberclique = None # Allows overriding uberclique for parts of tree
++ self.source = None # File that this node was parsed from
++
++ # This context handler allows you to write "with node:" and get a
++ # line identifying the offending node if an exception escapes from the body
++ # of the with statement.
++ def __enter__(self):
++ return self
++
++ def __exit__(self, exc_type, exc_value, traceback):
++ if exc_type is not None:
++ print(u'Error processing node %s: %s' % (six.text_type(self), exc_value))
++
++ def __iter__(self):
++ '''A preorder iteration through the tree that this node is the root of.'''
++ return self.Preorder()
++
++ def Preorder(self):
++ '''Generator that generates first this node, then the same generator for
++ any child nodes.'''
++ yield self
++ for child in self.children:
++ for iterchild in child.Preorder():
++ yield iterchild
++
++ def ActiveChildren(self):
++ '''Returns the children of this node that should be included in the current
++ configuration. Overridden by <if>.'''
++ return [node for node in self.children if not node.WhitelistMarkedAsSkip()]
++
++ def ActiveDescendants(self):
++ '''Yields the current node and all descendants that should be included in
++ the current configuration, in preorder.'''
++ yield self
++ for child in self.ActiveChildren():
++ for descendant in child.ActiveDescendants():
++ yield descendant
++
++ def GetRoot(self):
++ '''Returns the root Node in the tree this Node belongs to.'''
++ curr = self
++ while curr.parent:
++ curr = curr.parent
++ return curr
++
++ # TODO(joi) Use this (currently untested) optimization?:
++ #if hasattr(self, '_root'):
++ # return self._root
++ #curr = self
++ #while curr.parent and not hasattr(curr, '_root'):
++ # curr = curr.parent
++ #if curr.parent:
++ # self._root = curr._root
++ #else:
++ # self._root = curr
++ #return self._root
++
++ def StartParsing(self, name, parent):
++ '''Called at the start of parsing.
++
++ Args:
++ name: u'elementname'
++ parent: grit.node.base.Node or subclass or None
++ '''
++ assert isinstance(name, six.string_types)
++ assert not parent or isinstance(parent, Node)
++ self.name = name
++ self.parent = parent
++
++ def AddChild(self, child):
++ '''Adds a child to the list of children of this node, if it is a valid
++ child for the node.'''
++ assert isinstance(child, Node)
++ if (not self._IsValidChild(child) or
++ self._ContentType() == self._CONTENT_TYPE_CDATA):
++ explanation = 'invalid child %s for parent %s' % (str(child), self.name)
++ raise exception.UnexpectedChild(explanation)
++ self.children.append(child)
++ self.mixed_content.append(child)
++
++ def RemoveChild(self, child_id):
++ '''Removes the first node that has a "name" attribute which
++ matches "child_id" in the list of immediate children of
++ this node.
++
++ Args:
++ child_id: String identifying the child to be removed
++ '''
++ index = 0
++ # Safe not to copy since we only remove the first element found
++ for child in self.children:
++ name_attr = child.attrs['name']
++ if name_attr == child_id:
++ self.children.pop(index)
++ self.mixed_content.pop(index)
++ break
++ index += 1
++
++ def AppendContent(self, content):
++ '''Appends a chunk of text as content of this node.
++
++ Args:
++ content: u'hello'
++
++ Return:
++ None
++ '''
++ assert isinstance(content, six.string_types)
++ if self._ContentType() != self._CONTENT_TYPE_NONE:
++ self.mixed_content.append(content)
++ elif content.strip() != '':
++ raise exception.UnexpectedContent()
++
++ def HandleAttribute(self, attrib, value):
++ '''Informs the node of an attribute that was parsed out of the GRD file
++ for it.
++
++ Args:
++ attrib: 'name'
++ value: 'fooblat'
++
++ Return:
++ None
++ '''
++ assert isinstance(attrib, six.string_types)
++ assert isinstance(value, six.string_types)
++ if self._IsValidAttribute(attrib, value):
++ self.attrs[attrib] = value
++ else:
++ raise exception.UnexpectedAttribute(attrib)
++
++ def EndParsing(self):
++ '''Called at the end of parsing.'''
++
++ # TODO(joi) Rewrite this, it's extremely ugly!
++ if len(self.mixed_content):
++ if isinstance(self.mixed_content[0], six.string_types):
++ # Remove leading and trailing chunks of pure whitespace.
++ while (len(self.mixed_content) and
++ isinstance(self.mixed_content[0], six.string_types) and
++ self.mixed_content[0].strip() == ''):
++ self.mixed_content = self.mixed_content[1:]
++ # Strip leading and trailing whitespace from mixed content chunks
++ # at front and back.
++ if (len(self.mixed_content) and
++ isinstance(self.mixed_content[0], six.string_types)):
++ self.mixed_content[0] = self.mixed_content[0].lstrip()
++ # Remove leading and trailing ''' (used to demarcate whitespace)
++ if (len(self.mixed_content) and
++ isinstance(self.mixed_content[0], six.string_types)):
++ if self.mixed_content[0].startswith("'''"):
++ self.mixed_content[0] = self.mixed_content[0][3:]
++ if len(self.mixed_content):
++ if isinstance(self.mixed_content[-1], six.string_types):
++ # Same stuff all over again for the tail end.
++ while (len(self.mixed_content) and
++ isinstance(self.mixed_content[-1], six.string_types) and
++ self.mixed_content[-1].strip() == ''):
++ self.mixed_content = self.mixed_content[:-1]
++ if (len(self.mixed_content) and
++ isinstance(self.mixed_content[-1], six.string_types)):
++ self.mixed_content[-1] = self.mixed_content[-1].rstrip()
++ if (len(self.mixed_content) and
++ isinstance(self.mixed_content[-1], six.string_types)):
++ if self.mixed_content[-1].endswith("'''"):
++ self.mixed_content[-1] = self.mixed_content[-1][:-3]
++
++ # Check that all mandatory attributes are there.
++ for node_mandatt in self.MandatoryAttributes():
++ mandatt_list = []
++ if node_mandatt.find('|') >= 0:
++ mandatt_list = node_mandatt.split('|')
++ else:
++ mandatt_list.append(node_mandatt)
++
++ mandatt_option_found = False
++ for mandatt in mandatt_list:
++ assert mandatt not in self.DefaultAttributes()
++ if mandatt in self.attrs:
++ if not mandatt_option_found:
++ mandatt_option_found = True
++ else:
++ raise exception.MutuallyExclusiveMandatoryAttribute(mandatt)
++
++ if not mandatt_option_found:
++ raise exception.MissingMandatoryAttribute(mandatt)
++
++ # Add default attributes if not specified in input file.
++ for defattr in self.DefaultAttributes():
++ if not defattr in self.attrs:
++ self.attrs[defattr] = self.DefaultAttributes()[defattr]
++
++ def GetCdata(self):
++ '''Returns all CDATA of this element, concatenated into a single
++ string. Note that this ignores any elements embedded in CDATA.'''
++ return ''.join([c for c in self.mixed_content
++ if isinstance(c, six.string_types)])
++
++ def __str__(self):
++ '''Returns this node and all nodes below it as an XML document in a Unicode
++ string.'''
++ header = u'<?xml version="1.0" encoding="UTF-8"?>\n'
++ return header + self.FormatXml()
++
++ # Some Python 2 glue.
++ __unicode__ = __str__
++
++ def FormatXml(self, indent = u'', one_line = False):
++ '''Returns this node and all nodes below it as an XML
++ element in a Unicode string. This differs from __unicode__ in that it does
++ not include the <?xml> stuff at the top of the string. If one_line is true,
++ children and CDATA are layed out in a way that preserves internal
++ whitespace.
++ '''
++ assert isinstance(indent, six.string_types)
++
++ content_one_line = (one_line or
++ self._ContentType() == self._CONTENT_TYPE_MIXED)
++ inside_content = self.ContentsAsXml(indent, content_one_line)
++
++ # Then the attributes for this node.
++ attribs = u''
++ default_attribs = self.DefaultAttributes()
++ for attrib, value in sorted(self.attrs.items()):
++ # Only print an attribute if it is other than the default value.
++ if attrib not in default_attribs or value != default_attribs[attrib]:
++ attribs += u' %s=%s' % (attrib, saxutils.quoteattr(value))
++
++ # Finally build the XML for our node and return it
++ if len(inside_content) > 0:
++ if one_line:
++ return u'<%s%s>%s</%s>' % (self.name, attribs, inside_content,
++ self.name)
++ elif content_one_line:
++ return u'%s<%s%s>\n%s %s\n%s</%s>' % (
++ indent, self.name, attribs,
++ indent, inside_content,
++ indent, self.name)
++ else:
++ return u'%s<%s%s>\n%s\n%s</%s>' % (
++ indent, self.name, attribs,
++ inside_content,
++ indent, self.name)
++ else:
++ return u'%s<%s%s />' % (indent, self.name, attribs)
++
++ def ContentsAsXml(self, indent, one_line):
++ '''Returns the contents of this node (CDATA and child elements) in XML
++ format. If 'one_line' is true, the content will be laid out on one line.'''
++ assert isinstance(indent, six.string_types)
++
++ # Build the contents of the element.
++ inside_parts = []
++ last_item = None
++ for mixed_item in self.mixed_content:
++ if isinstance(mixed_item, Node):
++ inside_parts.append(mixed_item.FormatXml(indent + u' ', one_line))
++ if not one_line:
++ inside_parts.append(u'\n')
++ else:
++ message = mixed_item
++ # If this is the first item and it starts with whitespace, we add
++ # the ''' delimiter.
++ if not last_item and message.lstrip() != message:
++ message = u"'''" + message
++ inside_parts.append(util.EncodeCdata(message))
++ last_item = mixed_item
++
++ # If there are only child nodes and no cdata, there will be a spurious
++ # trailing \n
++ if len(inside_parts) and inside_parts[-1] == '\n':
++ inside_parts = inside_parts[:-1]
++
++ # If the last item is a string (not a node) and ends with whitespace,
++ # we need to add the ''' delimiter.
++ if (isinstance(last_item, six.string_types) and
++ last_item.rstrip() != last_item):
++ inside_parts[-1] = inside_parts[-1] + u"'''"
++
++ return u''.join(inside_parts)
++
++ def SubstituteMessages(self, substituter):
++ '''Applies substitutions to all messages in the tree.
++
++ Called as a final step of RunGatherers.
++
++ Args:
++ substituter: a grit.util.Substituter object.
++ '''
++ for child in self.children:
++ child.SubstituteMessages(substituter)
++
++ def _IsValidChild(self, child):
++ '''Returns true if 'child' is a valid child of this node.
++ Overridden by subclasses.'''
++ return False
++
++ def _IsValidAttribute(self, name, value):
++ '''Returns true if 'name' is the name of a valid attribute of this element
++ and 'value' is a valid value for that attribute. Overriden by
++ subclasses unless they have only mandatory attributes.'''
++ return (name in self.MandatoryAttributes() or
++ name in self.DefaultAttributes())
++
++ def _ContentType(self):
++ '''Returns the type of content this element can have. Overridden by
++ subclasses. The content type can be one of the _CONTENT_TYPE_XXX constants
++ above.'''
++ return self._CONTENT_TYPE_NONE
++
++ def MandatoryAttributes(self):
++ '''Returns a list of attribute names that are mandatory (non-optional)
++ on the current element. One can specify a list of
++ "mutually exclusive mandatory" attributes by specifying them as one
++ element in the list, separated by a "|" character.
++ '''
++ return []
++
++ def DefaultAttributes(self):
++ '''Returns a dictionary of attribute names that have defaults, mapped to
++ the default value. Overridden by subclasses.'''
++ return {}
++
++ def GetCliques(self):
++ '''Returns all MessageClique objects belonging to this node. Overridden
++ by subclasses.
++
++ Return:
++ [clique1, clique2] or []
++ '''
++ return []
++
++ def ToRealPath(self, path_from_basedir):
++ '''Returns a real path (which can be absolute or relative to the current
++ working directory), given a path that is relative to the base directory
++ set for the GRIT input file.
++
++ Args:
++ path_from_basedir: '..'
++
++ Return:
++ 'resource'
++ '''
++ return util.normpath(os.path.join(self.GetRoot().GetBaseDir(),
++ os.path.expandvars(path_from_basedir)))
++
++ def GetInputPath(self):
++ '''Returns a path, relative to the base directory set for the grd file,
++ that points to the file the node refers to.
++ '''
++ # This implementation works for most nodes that have an input file.
++ return self.attrs['file']
++
++ def UberClique(self):
++ '''Returns the uberclique that should be used for messages originating in
++ a given node. If the node itself has its uberclique set, that is what we
++ use, otherwise we search upwards until we find one. If we do not find one
++ even at the root node, we set the root node's uberclique to a new
++ uberclique instance.
++ '''
++ node = self
++ while not node.uberclique and node.parent:
++ node = node.parent
++ if not node.uberclique:
++ node.uberclique = clique.UberClique()
++ return node.uberclique
++
++ def IsTranslateable(self):
++ '''Returns false if the node has contents that should not be translated,
++ otherwise returns false (even if the node has no contents).
++ '''
++ if not 'translateable' in self.attrs:
++ return True
++ else:
++ return self.attrs['translateable'] == 'true'
++
++ def IsAccessibilityWithNoUI(self):
++ '''Returns true if the node is marked as an accessibility label and the
++ message isn't shown in the UI. Otherwise returns false. This label is
++ used to determine if the text requires screenshots.'''
++ if not 'is_accessibility_with_no_ui' in self.attrs:
++ return False
++ else:
++ return self.attrs['is_accessibility_with_no_ui'] == 'true'
++
++ def GetNodeById(self, id):
++ '''Returns the node in the subtree parented by this node that has a 'name'
++ attribute matching 'id'. Returns None if no such node is found.
++ '''
++ for node in self:
++ if 'name' in node.attrs and node.attrs['name'] == id:
++ return node
++ return None
++
++ def GetChildrenOfType(self, type):
++ '''Returns a list of all subnodes (recursing to all leaves) of this node
++ that are of the indicated type (or tuple of types).
++
++ Args:
++ type: A type you could use with isinstance().
++
++ Return:
++ A list, possibly empty.
++ '''
++ return [child for child in self if isinstance(child, type)]
++
++ def GetTextualIds(self):
++ '''Returns a list of the textual ids of this node.
++ '''
++ if 'name' in self.attrs:
++ return [self.attrs['name']]
++ return []
++
++ @classmethod
++ def EvaluateExpression(cls, expr, defs, target_platform, extra_variables={}):
++ '''Worker for EvaluateCondition (below) and conditions in XTB files.'''
++ if expr in cls.eval_expr_cache:
++ code, variables_in_expr = cls.eval_expr_cache[expr]
++ else:
++ # Get a list of all variable and method names used in the expression.
++ syntax_tree = ast.parse(expr, mode='eval')
++ variables_in_expr = [node.id for node in ast.walk(syntax_tree) if
++ isinstance(node, ast.Name) and node.id not in ('True', 'False')]
++ code = compile(syntax_tree, filename='<string>', mode='eval')
++ cls.eval_expr_cache[expr] = code, variables_in_expr
++
++ # Set values only for variables that are needed to eval the expression.
++ variable_map = {}
++ for name in variables_in_expr:
++ if name == 'os':
++ value = target_platform
++ elif name == 'defs':
++ value = defs
++
++ elif name == 'is_linux':
++ value = target_platform.startswith('linux')
++ elif name == 'is_macosx':
++ value = target_platform == 'darwin'
++ elif name == 'is_win':
++ value = target_platform in ('cygwin', 'win32')
++ elif name == 'is_android':
++ value = target_platform == 'android'
++ elif name == 'is_ios':
++ value = target_platform == 'ios'
++ elif name == 'is_bsd':
++ value = 'bsd' in target_platform
++ elif name == 'is_posix':
++ value = (target_platform in ('darwin', 'linux2', 'linux3', 'sunos5',
++ 'android', 'ios')
++ or 'bsd' in target_platform)
++
++ elif name == 'pp_ifdef':
++ def pp_ifdef(symbol):
++ return symbol in defs
++ value = pp_ifdef
++ elif name == 'pp_if':
++ def pp_if(symbol):
++ return defs.get(symbol, False)
++ value = pp_if
++
++ elif name in defs:
++ value = defs[name]
++ elif name in extra_variables:
++ value = extra_variables[name]
++ else:
++ # Undefined variables default to False.
++ value = False
++
++ variable_map[name] = value
++
++ eval_result = eval(code, {}, variable_map)
++ assert isinstance(eval_result, bool)
++ return eval_result
++
++ def EvaluateCondition(self, expr):
++ '''Returns true if and only if the Python expression 'expr' evaluates
++ to true.
++
++ The expression is given a few local variables:
++ - 'lang' is the language currently being output
++ (the 'lang' attribute of the <output> element).
++ - 'context' is the current output context
++ (the 'context' attribute of the <output> element).
++ - 'defs' is a map of C preprocessor-style symbol names to their values.
++ - 'os' is the current platform (likely 'linux2', 'win32' or 'darwin').
++ - 'pp_ifdef(symbol)' is a shorthand for "symbol in defs".
++ - 'pp_if(symbol)' is a shorthand for "symbol in defs and defs[symbol]".
++ - 'is_linux', 'is_macosx', 'is_win', 'is_posix' are true if 'os'
++ matches the given platform.
++ '''
++ root = self.GetRoot()
++ lang = getattr(root, 'output_language', '')
++ context = getattr(root, 'output_context', '')
++ defs = getattr(root, 'defines', {})
++ target_platform = getattr(root, 'target_platform', '')
++ extra_variables = {
++ 'lang': lang,
++ 'context': context,
++ }
++ return Node.EvaluateExpression(
++ expr, defs, target_platform, extra_variables)
++
++ def OnlyTheseTranslations(self, languages):
++ '''Turns off loading of translations for languages not in the provided list.
++
++ Attrs:
++ languages: ['fr', 'zh_cn']
++ '''
++ for node in self:
++ if (hasattr(node, 'IsTranslation') and
++ node.IsTranslation() and
++ node.GetLang() not in languages):
++ node.DisableLoading()
++
++ def FindBooleanAttribute(self, attr, default, skip_self):
++ '''Searches all ancestors of the current node for the nearest enclosing
++ definition of the given boolean attribute.
++
++ Args:
++ attr: 'fallback_to_english'
++ default: What to return if no node defines the attribute.
++ skip_self: Don't check the current node, only its parents.
++ '''
++ p = self.parent if skip_self else self
++ while p:
++ value = p.attrs.get(attr, 'default').lower()
++ if value != 'default':
++ return (value == 'true')
++ p = p.parent
++ return default
++
++ def PseudoIsAllowed(self):
++ '''Returns true if this node is allowed to use pseudo-translations. This
++ is true by default, unless this node is within a <release> node that has
++ the allow_pseudo attribute set to false.
++ '''
++ return self.FindBooleanAttribute('allow_pseudo',
++ default=True, skip_self=True)
++
++ def ShouldFallbackToEnglish(self):
++ '''Returns true iff this node should fall back to English when
++ pseudotranslations are disabled and no translation is available for a
++ given message.
++ '''
++ return self.FindBooleanAttribute('fallback_to_english',
++ default=False, skip_self=True)
++
++ def WhitelistMarkedAsSkip(self):
++ '''Returns true if the node is marked to be skipped in the output by a
++ whitelist.
++ '''
++ return self._whitelist_marked_as_skip
++
++ def SetWhitelistMarkedAsSkip(self, mark_skipped):
++ '''Sets WhitelistMarkedAsSkip.
++ '''
++ self._whitelist_marked_as_skip = mark_skipped
++
++ def ExpandVariables(self):
++ '''Whether we need to expand variables on a given node.'''
++ return False
++
++ def IsResourceMapSource(self):
++ '''Whether this node is a resource map source.'''
++ return False
++
++ def CompressDataIfNeeded(self, data):
++ '''Compress data using the format specified in the compress attribute.
++
++ Args:
++ data: The data to compressed.
++ Returns:
++ The data in gzipped or brotli compressed format. If the format is
++ unspecified then this returns the data uncompressed.
++ '''
++
++ compress = self.attrs.get('compress')
++
++ # Compress JS, HTML, CSS and SVG files by default (gzip), unless |compress|
++ # is explicitly specified.
++ compress_by_default = (compress == 'default'
++ and self.attrs.get('file').endswith(
++ self._COMPRESS_BY_DEFAULT_EXTENSIONS))
++
++ if compress == 'gzip' or compress_by_default:
++ # We only use rsyncable compression on Linux.
++ # We exclude ChromeOS since ChromeOS bots are Linux based but do not have
++ # the --rsyncable option built in for gzip. See crbug.com/617950.
++ if sys.platform == 'linux2' and 'chromeos' not in self.GetRoot().defines:
++ return grit.format.gzip_string.GzipStringRsyncable(data)
++ return grit.format.gzip_string.GzipString(data)
++
++ if compress == 'brotli':
++ # The length of the uncompressed data as 8 bytes little-endian.
++ size_bytes = struct.pack("<q", len(data))
++ data = brotli_util.BrotliCompress(data)
++ # BROTLI_CONST is prepended to brotli decompressed data in order to
++ # easily check if a resource has been brotli compressed.
++ # The length of the uncompressed data is also appended to the start,
++ # truncated to 6 bytes, little-endian. size_bytes is 8 bytes,
++ # need to truncate further to 6.
++ formatter = b'%ds %dx %ds' % (6, 2, len(size_bytes) - 8)
++ return (constants.BROTLI_CONST +
++ b''.join(struct.unpack(formatter, size_bytes)) +
++ data)
++
++ if compress == 'false' or compress == 'default':
++ return data
++
++ raise Exception('Invalid value for compression')
++
++
++class ContentNode(Node):
++ '''Convenience baseclass for nodes that can have content.'''
++ def _ContentType(self):
++ return self._CONTENT_TYPE_MIXED
+diff --git a/tools/grit/grit/node/base_unittest.py b/tools/grit/grit/node/base_unittest.py
+new file mode 100644
+index 0000000000..32a5a0ca59
+--- /dev/null
++++ b/tools/grit/grit/node/base_unittest.py
+@@ -0,0 +1,259 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for base.Node functionality (as used in various subclasses)'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit import grd_reader
++from grit import util
++from grit.node import base
++from grit.node import message
++
++
++def MakePlaceholder(phname='BINGO'):
++ ph = message.PhNode()
++ ph.StartParsing(u'ph', None)
++ ph.HandleAttribute(u'name', phname)
++ ph.AppendContent(u'bongo')
++ ph.EndParsing()
++ return ph
++
++
++class NodeUnittest(unittest.TestCase):
++ def testWhitespaceHandling(self):
++ # We test using the Message node type.
++ node = message.MessageNode()
++ node.StartParsing(u'hello', None)
++ node.HandleAttribute(u'name', u'bla')
++ node.AppendContent(u" ''' two spaces ")
++ node.EndParsing()
++ self.failUnless(node.GetCdata() == u' two spaces')
++
++ node = message.MessageNode()
++ node.StartParsing(u'message', None)
++ node.HandleAttribute(u'name', u'bla')
++ node.AppendContent(u" two spaces ''' ")
++ node.EndParsing()
++ self.failUnless(node.GetCdata() == u'two spaces ')
++
++ def testWhitespaceHandlingWithChildren(self):
++ # We test using the Message node type.
++ node = message.MessageNode()
++ node.StartParsing(u'message', None)
++ node.HandleAttribute(u'name', u'bla')
++ node.AppendContent(u" ''' two spaces ")
++ node.AddChild(MakePlaceholder())
++ node.AppendContent(u' space before and after ')
++ node.AddChild(MakePlaceholder('BONGO'))
++ node.AppendContent(u" space before two after '''")
++ node.EndParsing()
++ self.failUnless(node.mixed_content[0] == u' two spaces ')
++ self.failUnless(node.mixed_content[2] == u' space before and after ')
++ self.failUnless(node.mixed_content[-1] == u' space before two after ')
++
++ def testXmlFormatMixedContent(self):
++ # Again test using the Message node type, because it is the only mixed
++ # content node.
++ node = message.MessageNode()
++ node.StartParsing(u'message', None)
++ node.HandleAttribute(u'name', u'name')
++ node.AppendContent(u'Hello <young> ')
++
++ ph = message.PhNode()
++ ph.StartParsing(u'ph', None)
++ ph.HandleAttribute(u'name', u'USERNAME')
++ ph.AppendContent(u'$1')
++ ex = message.ExNode()
++ ex.StartParsing(u'ex', None)
++ ex.AppendContent(u'Joi')
++ ex.EndParsing()
++ ph.AddChild(ex)
++ ph.EndParsing()
++
++ node.AddChild(ph)
++ node.EndParsing()
++
++ non_indented_xml = node.FormatXml()
++ self.failUnless(non_indented_xml == u'<message name="name">\n Hello '
++ u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
++ u'\n</message>')
++
++ indented_xml = node.FormatXml(u' ')
++ self.failUnless(indented_xml == u' <message name="name">\n Hello '
++ u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
++ u'\n </message>')
++
++ def testXmlFormatMixedContentWithLeadingWhitespace(self):
++ # Again test using the Message node type, because it is the only mixed
++ # content node.
++ node = message.MessageNode()
++ node.StartParsing(u'message', None)
++ node.HandleAttribute(u'name', u'name')
++ node.AppendContent(u"''' Hello <young> ")
++
++ ph = message.PhNode()
++ ph.StartParsing(u'ph', None)
++ ph.HandleAttribute(u'name', u'USERNAME')
++ ph.AppendContent(u'$1')
++ ex = message.ExNode()
++ ex.StartParsing(u'ex', None)
++ ex.AppendContent(u'Joi')
++ ex.EndParsing()
++ ph.AddChild(ex)
++ ph.EndParsing()
++
++ node.AddChild(ph)
++ node.AppendContent(u" yessiree '''")
++ node.EndParsing()
++
++ non_indented_xml = node.FormatXml()
++ self.failUnless(non_indented_xml ==
++ u"<message name=\"name\">\n ''' Hello"
++ u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
++ u" yessiree '''\n</message>")
++
++ indented_xml = node.FormatXml(u' ')
++ self.failUnless(indented_xml ==
++ u" <message name=\"name\">\n ''' Hello"
++ u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
++ u" yessiree '''\n </message>")
++
++ self.failUnless(node.GetNodeById('name'))
++
++ def testXmlFormatContentWithEntities(self):
++ '''Tests a bug where &nbsp; would not be escaped correctly.'''
++ from grit import tclib
++ msg_node = message.MessageNode.Construct(None, tclib.Message(
++ text = 'BEGIN_BOLDHelloWHITESPACEthere!END_BOLD Bingo!',
++ placeholders = [
++ tclib.Placeholder('BEGIN_BOLD', '<b>', 'bla'),
++ tclib.Placeholder('WHITESPACE', '&nbsp;', 'bla'),
++ tclib.Placeholder('END_BOLD', '</b>', 'bla')]),
++ 'BINGOBONGO')
++ xml = msg_node.FormatXml()
++ self.failUnless(xml.find('&nbsp;') == -1, 'should have no entities')
++
++ def testIter(self):
++ # First build a little tree of message and ph nodes.
++ node = message.MessageNode()
++ node.StartParsing(u'message', None)
++ node.HandleAttribute(u'name', u'bla')
++ node.AppendContent(u" ''' two spaces ")
++ node.AppendContent(u' space before and after ')
++ ph = message.PhNode()
++ ph.StartParsing(u'ph', None)
++ ph.AddChild(message.ExNode())
++ ph.HandleAttribute(u'name', u'BINGO')
++ ph.AppendContent(u'bongo')
++ node.AddChild(ph)
++ node.AddChild(message.PhNode())
++ node.AppendContent(u" space before two after '''")
++
++ order = [message.MessageNode, message.PhNode, message.ExNode, message.PhNode]
++ for n in node:
++ self.failUnless(type(n) == order[0])
++ order = order[1:]
++ self.failUnless(len(order) == 0)
++
++ def testGetChildrenOfType(self):
++ xml = '''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US"
++ current_release="3" base_dir=".">
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="en/generated_resources.rc" type="rc_all"
++ lang="en" />
++ <if expr="pp_if('NOT_TRUE')">
++ <output filename="de/generated_resources.rc" type="rc_all"
++ lang="de" />
++ </if>
++ </outputs>
++ <release seq="3">
++ <messages>
++ <message name="ID_HELLO">Hello!</message>
++ </messages>
++ </release>
++ </grit>'''
++ grd = grd_reader.Parse(StringIO(xml),
++ util.PathFromRoot('grit/test/data'))
++ from grit.node import node_io
++ output_nodes = grd.GetChildrenOfType(node_io.OutputNode)
++ self.failUnlessEqual(len(output_nodes), 3)
++ self.failUnlessEqual(output_nodes[2].attrs['filename'],
++ 'de/generated_resources.rc')
++
++ def testEvaluateExpression(self):
++ def AssertExpr(expected_value, expr, defs, target_platform,
++ extra_variables):
++ self.failUnlessEqual(expected_value, base.Node.EvaluateExpression(
++ expr, defs, target_platform, extra_variables))
++
++ AssertExpr(True, "True", {}, 'linux', {})
++ AssertExpr(False, "False", {}, 'linux', {})
++ AssertExpr(True, "True or False", {}, 'linux', {})
++ AssertExpr(False, "True and False", {}, 'linux', {})
++ AssertExpr(True, "os == 'linux'", {}, 'linux', {})
++ AssertExpr(False, "os == 'linux'", {}, 'ios', {})
++ AssertExpr(True, "'foo' in defs", {'foo': 'bar'}, 'ios', {})
++ AssertExpr(False, "'foo' in defs", {'baz': 'bar'}, 'ios', {})
++ AssertExpr(False, "'foo' in defs", {}, 'ios', {})
++ AssertExpr(True, "is_linux", {}, 'linux2', {})
++ AssertExpr(False, "is_linux", {}, 'win32', {})
++ AssertExpr(True, "is_macosx", {}, 'darwin', {})
++ AssertExpr(False, "is_macosx", {}, 'ios', {})
++ AssertExpr(True, "is_win", {}, 'win32', {})
++ AssertExpr(False, "is_win", {}, 'darwin', {})
++ AssertExpr(True, "is_android", {}, 'android', {})
++ AssertExpr(False, "is_android", {}, 'linux3', {})
++ AssertExpr(True, "is_ios", {}, 'ios', {})
++ AssertExpr(False, "is_ios", {}, 'darwin', {})
++ AssertExpr(True, "is_posix", {}, 'linux2', {})
++ AssertExpr(True, "is_posix", {}, 'darwin', {})
++ AssertExpr(True, "is_posix", {}, 'android', {})
++ AssertExpr(True, "is_posix", {}, 'ios', {})
++ AssertExpr(True, "is_posix", {}, 'freebsd7', {})
++ AssertExpr(False, "is_posix", {}, 'win32', {})
++ AssertExpr(True, "pp_ifdef('foo')", {'foo': True}, 'win32', {})
++ AssertExpr(True, "pp_ifdef('foo')", {'foo': False}, 'win32', {})
++ AssertExpr(False, "pp_ifdef('foo')", {'bar': True}, 'win32', {})
++ AssertExpr(True, "pp_if('foo')", {'foo': True}, 'win32', {})
++ AssertExpr(False, "pp_if('foo')", {'foo': False}, 'win32', {})
++ AssertExpr(False, "pp_if('foo')", {'bar': True}, 'win32', {})
++ AssertExpr(True, "foo", {'foo': True}, 'win32', {})
++ AssertExpr(False, "foo", {'foo': False}, 'win32', {})
++ AssertExpr(False, "foo", {'bar': True}, 'win32', {})
++ AssertExpr(True, "foo == 'baz'", {'foo': 'baz'}, 'win32', {})
++ AssertExpr(False, "foo == 'baz'", {'foo': True}, 'win32', {})
++ AssertExpr(False, "foo == 'baz'", {}, 'win32', {})
++ AssertExpr(True, "lang == 'de'", {}, 'win32', {'lang': 'de'})
++ AssertExpr(False, "lang == 'de'", {}, 'win32', {'lang': 'fr'})
++ AssertExpr(False, "lang == 'de'", {}, 'win32', {})
++
++ # Test a couple more complex expressions for good measure.
++ AssertExpr(True, "is_ios and (lang in ['de', 'fr'] or foo)",
++ {'foo': 'bar'}, 'ios', {'lang': 'fr', 'context': 'today'})
++ AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)",
++ {'foo': False}, 'linux2', {'lang': 'fr', 'context': 'today'})
++ AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)",
++ {'baz': 'bar'}, 'ios', {'lang': 'he', 'context': 'today'})
++ AssertExpr(True, "foo == 'bar' or not baz",
++ {'foo': 'bar', 'fun': True}, 'ios', {'lang': 'en'})
++ AssertExpr(True, "foo == 'bar' or not baz",
++ {}, 'ios', {'lang': 'en', 'context': 'java'})
++ AssertExpr(False, "foo == 'bar' or not baz",
++ {'foo': 'ruz', 'baz': True}, 'ios', {'lang': 'en'})
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/brotli_util.py b/tools/grit/grit/node/brotli_util.py
+new file mode 100644
+index 0000000000..77f70e49d5
+--- /dev/null
++++ b/tools/grit/grit/node/brotli_util.py
+@@ -0,0 +1,29 @@
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Framework for compressing resources using Brotli."""
++
++import subprocess
++
++__brotli_executable = None
++
++
++def SetBrotliCommand(brotli):
++ # brotli is a list. In production it contains the path to the Brotli executable.
++ # During testing it contains [python, mock_brotli.py] for testing on Windows.
++ global __brotli_executable
++ __brotli_executable = brotli
++
++
++def BrotliCompress(data):
++ if not __brotli_executable:
++ raise Exception('Add "use_brotli = true" to you GN grit(...) target ' +
++ 'if you want to use brotli.')
++ compress = subprocess.Popen(__brotli_executable + ['-', '-f'],
++ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
++ return compress.communicate(data)[0]
++
++def IsInitialized():
++ global __brotli_executable
++ return __brotli_executable is not None
+diff --git a/tools/grit/grit/node/custom/__init__.py b/tools/grit/grit/node/custom/__init__.py
+new file mode 100644
+index 0000000000..e179cf7730
+--- /dev/null
++++ b/tools/grit/grit/node/custom/__init__.py
+@@ -0,0 +1,8 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Package 'grit.node.custom'
++'''
++
++pass
+diff --git a/tools/grit/grit/node/custom/filename.py b/tools/grit/grit/node/custom/filename.py
+new file mode 100644
+index 0000000000..55a27e58c1
+--- /dev/null
++++ b/tools/grit/grit/node/custom/filename.py
+@@ -0,0 +1,29 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''A CustomType for filenames.'''
++
++from __future__ import print_function
++
++from grit import clique
++from grit import lazy_re
++
++
++class WindowsFilename(clique.CustomType):
++ '''Validates that messages can be used as Windows filenames, and strips
++ illegal characters out of translations.
++ '''
++
++ BANNED = lazy_re.compile(r'\+|:|\/|\\\\|\*|\?|\"|\<|\>|\|')
++
++ def Validate(self, message):
++ return not self.BANNED.search(message.GetPresentableContent())
++
++ def ValidateAndModify(self, lang, translation):
++ is_ok = self.Validate(translation)
++ self.ModifyEachTextPart(lang, translation)
++ return is_ok
++
++ def ModifyTextPart(self, lang, text):
++ return self.BANNED.sub(' ', text)
+diff --git a/tools/grit/grit/node/custom/filename_unittest.py b/tools/grit/grit/node/custom/filename_unittest.py
+new file mode 100644
+index 0000000000..8e2a6dd64a
+--- /dev/null
++++ b/tools/grit/grit/node/custom/filename_unittest.py
+@@ -0,0 +1,34 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.node.custom.filename'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../../..'))
++
++import unittest
++from grit.node.custom import filename
++from grit import clique
++from grit import tclib
++
++
++class WindowsFilenameUnittest(unittest.TestCase):
++
++ def testValidate(self):
++ factory = clique.UberClique()
++ msg = tclib.Message(text='Bingo bongo')
++ c = factory.MakeClique(msg)
++ c.SetCustomType(filename.WindowsFilename())
++ translation = tclib.Translation(id=msg.GetId(), text='Bilingo bolongo:')
++ c.AddTranslation(translation, 'fr')
++ self.failUnless(c.MessageForLanguage('fr').GetRealContent() == 'Bilingo bolongo ')
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/empty.py b/tools/grit/grit/node/empty.py
+new file mode 100644
+index 0000000000..e19d2c4ddb
+--- /dev/null
++++ b/tools/grit/grit/node/empty.py
+@@ -0,0 +1,64 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Container nodes that don't have any logic.
++'''
++
++from __future__ import print_function
++
++from grit.node import base
++from grit.node import include
++from grit.node import message
++from grit.node import misc
++from grit.node import node_io
++from grit.node import structure
++
++
++class GroupingNode(base.Node):
++ '''Base class for all the grouping elements (<structures>, <includes>,
++ <messages> and <identifiers>).'''
++ def DefaultAttributes(self):
++ return {
++ 'first_id' : '',
++ 'comment' : '',
++ 'fallback_to_english' : 'false',
++ 'fallback_to_low_resolution' : 'false',
++ }
++
++
++class IncludesNode(GroupingNode):
++ '''The <includes> element.'''
++ def _IsValidChild(self, child):
++ return isinstance(child, (include.IncludeNode, misc.IfNode, misc.PartNode))
++
++
++class MessagesNode(GroupingNode):
++ '''The <messages> element.'''
++ def _IsValidChild(self, child):
++ return isinstance(child, (message.MessageNode, misc.IfNode, misc.PartNode))
++
++
++class StructuresNode(GroupingNode):
++ '''The <structures> element.'''
++ def _IsValidChild(self, child):
++ return isinstance(child, (structure.StructureNode,
++ misc.IfNode, misc.PartNode))
++
++
++class TranslationsNode(base.Node):
++ '''The <translations> element.'''
++ def _IsValidChild(self, child):
++ return isinstance(child, (node_io.FileNode, misc.IfNode, misc.PartNode))
++
++
++class OutputsNode(base.Node):
++ '''The <outputs> element.'''
++ def _IsValidChild(self, child):
++ return isinstance(child, (node_io.OutputNode, misc.IfNode, misc.PartNode))
++
++
++class IdentifiersNode(GroupingNode):
++ '''The <identifiers> element.'''
++ def _IsValidChild(self, child):
++ return isinstance(child, misc.IdentifierNode)
+diff --git a/tools/grit/grit/node/include.py b/tools/grit/grit/node/include.py
+new file mode 100644
+index 0000000000..b06b9889bb
+--- /dev/null
++++ b/tools/grit/grit/node/include.py
+@@ -0,0 +1,170 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Handling of the <include> element.
++"""
++
++from __future__ import print_function
++
++import os
++
++from grit import util
++import grit.format.html_inline
++import grit.format.rc
++from grit.format import minifier
++from grit.node import base
++
++class IncludeNode(base.Node):
++ """An <include> element."""
++
++ def __init__(self):
++ super(IncludeNode, self).__init__()
++
++ # Cache flattened data so that we don't flatten the same file
++ # multiple times.
++ self._flattened_data = None
++ # Also keep track of the last filename we flattened to, so we can
++ # avoid doing it more than once.
++ self._last_flat_filename = None
++
++ def _IsValidChild(self, child):
++ return False
++
++ def _GetFlattenedData(
++ self, allow_external_script=False, preprocess_only=False):
++ if not self._flattened_data:
++ filename = self.ToRealPath(self.GetInputPath())
++ self._flattened_data = (
++ grit.format.html_inline.InlineToString(filename, self,
++ preprocess_only=preprocess_only,
++ allow_external_script=allow_external_script))
++ return self._flattened_data.encode('utf-8')
++
++ def MandatoryAttributes(self):
++ return ['name', 'type', 'file']
++
++ def DefaultAttributes(self):
++ """Attributes:
++ translateable: False if the node has contents that should not be
++ translated.
++ preprocess: Takes the same code path as flattenhtml, but it
++ disables any processing/inlining outside of <if>
++ and <include>.
++ compress: The format to compress the data with, e.g. 'gzip'
++ or 'false' if data should not be compressed.
++ skip_minify: If true, skips minifying the node's contents.
++ skip_in_resource_map: If true, do not add to the resource map.
++ """
++ return {
++ 'translateable': 'true',
++ 'generateid': 'true',
++ 'filenameonly': 'false',
++ 'mkoutput': 'false',
++ 'preprocess': 'false',
++ 'flattenhtml': 'false',
++ 'compress': 'default',
++ 'allowexternalscript': 'false',
++ 'relativepath': 'false',
++ 'use_base_dir': 'true',
++ 'skip_minify': 'false',
++ 'skip_in_resource_map': 'false',
++ }
++
++ def GetInputPath(self):
++ # Do not mess with absolute paths, that would make them invalid.
++ if os.path.isabs(os.path.expandvars(self.attrs['file'])):
++ return self.attrs['file']
++
++ # We have no control over code that calls ToRealPath later, so convert
++ # the path to be relative against our basedir.
++ if self.attrs.get('use_base_dir', 'true') != 'true':
++ # Normalize the directory path to use the appropriate OS separator.
++ # GetBaseDir() may return paths\like\this or paths/like/this, since it is
++ # read from the base_dir attribute in the grd file.
++ norm_base_dir = util.normpath(self.GetRoot().GetBaseDir())
++ return os.path.relpath(self.attrs['file'], norm_base_dir)
++
++ return self.attrs['file']
++
++ def FileForLanguage(self, lang, output_dir):
++ """Returns the file for the specified language. This allows us to return
++ different files for different language variants of the include file.
++ """
++ input_path = self.GetInputPath()
++ if input_path is None:
++ return None
++
++ return self.ToRealPath(input_path)
++
++ def GetDataPackValue(self, lang, encoding):
++ '''Returns bytes or a str represenation for a data_pack entry.'''
++ filename = self.ToRealPath(self.GetInputPath())
++ if self.attrs['flattenhtml'] == 'true':
++ allow_external_script = self.attrs['allowexternalscript'] == 'true'
++ data = self._GetFlattenedData(allow_external_script=allow_external_script)
++ elif self.attrs['preprocess'] == 'true':
++ data = self._GetFlattenedData(preprocess_only=True)
++ else:
++ data = util.ReadFile(filename, util.BINARY)
++
++ if self.attrs['skip_minify'] != 'true':
++ # Note that the minifier will only do anything if a minifier command
++ # has been set in the command line.
++ data = minifier.Minify(data, filename)
++
++ # Include does not care about the encoding, because it only returns binary
++ # data.
++ return self.CompressDataIfNeeded(data)
++
++ def Process(self, output_dir):
++ """Rewrite file references to be base64 encoded data URLs. The new file
++ will be written to output_dir and the name of the new file is returned."""
++ filename = self.ToRealPath(self.GetInputPath())
++ flat_filename = os.path.join(output_dir,
++ self.attrs['name'] + '_' + os.path.basename(filename))
++
++ if self._last_flat_filename == flat_filename:
++ return
++
++ with open(flat_filename, 'wb') as outfile:
++ outfile.write(self._GetFlattenedData())
++
++ self._last_flat_filename = flat_filename
++ return os.path.basename(flat_filename)
++
++ def GetHtmlResourceFilenames(self):
++ """Returns a set of all filenames inlined by this file."""
++ allow_external_script = self.attrs['allowexternalscript'] == 'true'
++ return grit.format.html_inline.GetResourceFilenames(
++ self.ToRealPath(self.GetInputPath()),
++ self,
++ allow_external_script=allow_external_script)
++
++ def IsResourceMapSource(self):
++ skip = self.attrs.get('skip_in_resource_map', 'false') == 'true'
++ return not skip
++
++ @staticmethod
++ def Construct(parent, name, type, file, translateable=True,
++ filenameonly=False, mkoutput=False, relativepath=False):
++ """Creates a new node which is a child of 'parent', with attributes set
++ by parameters of the same name.
++ """
++ # Convert types to appropriate strings
++ translateable = util.BoolToString(translateable)
++ filenameonly = util.BoolToString(filenameonly)
++ mkoutput = util.BoolToString(mkoutput)
++ relativepath = util.BoolToString(relativepath)
++
++ node = IncludeNode()
++ node.StartParsing('include', parent)
++ node.HandleAttribute('name', name)
++ node.HandleAttribute('type', type)
++ node.HandleAttribute('file', file)
++ node.HandleAttribute('translateable', translateable)
++ node.HandleAttribute('filenameonly', filenameonly)
++ node.HandleAttribute('mkoutput', mkoutput)
++ node.HandleAttribute('relativepath', relativepath)
++ node.EndParsing()
++ return node
+diff --git a/tools/grit/grit/node/include_unittest.py b/tools/grit/grit/node/include_unittest.py
+new file mode 100644
+index 0000000000..4c658f1ffe
+--- /dev/null
++++ b/tools/grit/grit/node/include_unittest.py
+@@ -0,0 +1,134 @@
++#!/usr/bin/env python
++# Copyright (c) 2013 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for include.IncludeNode'''
++
++from __future__ import print_function
++
++import os
++import sys
++import unittest
++import zlib
++
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++from grit.node import misc
++from grit.node import include
++from grit.node import empty
++from grit import util
++
++
++def checkIsGzipped(filename, compress_attr):
++ test_data_root = util.PathFromRoot('grit/testdata')
++ root = util.ParseGrdForUnittest(
++ '''
++ <includes>
++ <include name="TEST_TXT" file="%s" %s type="BINDATA"/>
++ </includes>''' % (filename, compress_attr),
++ base_dir=test_data_root)
++ node, = root.GetChildrenOfType(include.IncludeNode)
++ compressed = node.GetDataPackValue(lang='en', encoding=util.BINARY)
++
++ decompressed_data = zlib.decompress(compressed, 16 + zlib.MAX_WBITS)
++ expected = util.ReadFile(os.path.join(test_data_root, filename), util.BINARY)
++ return expected == decompressed_data
++
++
++class IncludeNodeUnittest(unittest.TestCase):
++ def testGetPath(self):
++ root = misc.GritNode()
++ root.StartParsing(u'grit', None)
++ root.HandleAttribute(u'latest_public_release', u'0')
++ root.HandleAttribute(u'current_release', u'1')
++ root.HandleAttribute(u'base_dir', r'..\resource')
++ release = misc.ReleaseNode()
++ release.StartParsing(u'release', root)
++ release.HandleAttribute(u'seq', u'1')
++ root.AddChild(release)
++ includes = empty.IncludesNode()
++ includes.StartParsing(u'includes', release)
++ release.AddChild(includes)
++ include_node = include.IncludeNode()
++ include_node.StartParsing(u'include', includes)
++ include_node.HandleAttribute(u'file', r'flugel\kugel.pdf')
++ includes.AddChild(include_node)
++ root.EndParsing()
++
++ self.assertEqual(root.ToRealPath(include_node.GetInputPath()),
++ util.normpath(
++ os.path.join(r'../resource', r'flugel/kugel.pdf')))
++
++ def testGetPathNoBasedir(self):
++ root = misc.GritNode()
++ root.StartParsing(u'grit', None)
++ root.HandleAttribute(u'latest_public_release', u'0')
++ root.HandleAttribute(u'current_release', u'1')
++ root.HandleAttribute(u'base_dir', r'..\resource')
++ release = misc.ReleaseNode()
++ release.StartParsing(u'release', root)
++ release.HandleAttribute(u'seq', u'1')
++ root.AddChild(release)
++ includes = empty.IncludesNode()
++ includes.StartParsing(u'includes', release)
++ release.AddChild(includes)
++ include_node = include.IncludeNode()
++ include_node.StartParsing(u'include', includes)
++ include_node.HandleAttribute(u'file', r'flugel\kugel.pdf')
++ include_node.HandleAttribute(u'use_base_dir', u'false')
++ includes.AddChild(include_node)
++ root.EndParsing()
++
++ last_dir = os.path.basename(os.getcwd())
++ expected_path = util.normpath(os.path.join(
++ u'..', last_dir, u'flugel/kugel.pdf'))
++ self.assertEqual(root.ToRealPath(include_node.GetInputPath()),
++ expected_path)
++
++ def testCompressGzip(self):
++ self.assertTrue(checkIsGzipped('test_text.txt', 'compress="gzip"'))
++
++ def testCompressGzipByDefault(self):
++ self.assertTrue(checkIsGzipped('test_html.html', ''))
++ self.assertTrue(checkIsGzipped('test_js.js', ''))
++ self.assertTrue(checkIsGzipped('test_css.css', ''))
++ self.assertTrue(checkIsGzipped('test_svg.svg', ''))
++
++ self.assertTrue(checkIsGzipped('test_html.html', 'compress="default"'))
++ self.assertTrue(checkIsGzipped('test_js.js', 'compress="default"'))
++ self.assertTrue(checkIsGzipped('test_css.css', 'compress="default"'))
++ self.assertTrue(checkIsGzipped('test_svg.svg', 'compress="default"'))
++
++ def testSkipInResourceMap(self):
++ root = util.ParseGrdForUnittest('''
++ <includes>
++ <include name="TEST1_TXT" file="test1_text.txt" type="BINDATA"/>
++ <include name="TEST2_TXT" file="test1_text.txt" type="BINDATA"
++ skip_in_resource_map="true"/>
++ <include name="TEST3_TXT" file="test1_text.txt" type="BINDATA"
++ skip_in_resource_map="false"/>
++ </includes>''', base_dir = util.PathFromRoot('grit/testdata'))
++ inc = root.GetChildrenOfType(include.IncludeNode)
++ self.assertTrue(inc[0].IsResourceMapSource())
++ self.assertFalse(inc[1].IsResourceMapSource())
++ self.assertTrue(inc[2].IsResourceMapSource())
++
++ def testAcceptsPreprocess(self):
++ root = util.ParseGrdForUnittest(
++ '''
++ <includes>
++ <include name="PREPROCESS_TEST" file="preprocess_test.html"
++ preprocess="true" compress="false" type="chrome_html"/>
++ </includes>''',
++ base_dir=util.PathFromRoot('grit/testdata'))
++ inc, = root.GetChildrenOfType(include.IncludeNode)
++ result = inc.GetDataPackValue(lang='en', encoding=util.BINARY)
++ self.assertIn(b'should be kept', result)
++ self.assertIn(b'in the middle...', result)
++ self.assertNotIn(b'should be removed', result)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/mapping.py b/tools/grit/grit/node/mapping.py
+new file mode 100644
+index 0000000000..6297f0b666
+--- /dev/null
++++ b/tools/grit/grit/node/mapping.py
+@@ -0,0 +1,60 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Maps each node type to an implementation class.
++When adding a new node type, you add to this mapping.
++'''
++
++from __future__ import print_function
++
++from grit import exception
++
++from grit.node import empty
++from grit.node import include
++from grit.node import message
++from grit.node import misc
++from grit.node import node_io
++from grit.node import structure
++from grit.node import variant
++
++
++_ELEMENT_TO_CLASS = {
++ 'identifiers' : empty.IdentifiersNode,
++ 'includes' : empty.IncludesNode,
++ 'messages' : empty.MessagesNode,
++ 'outputs' : empty.OutputsNode,
++ 'structures' : empty.StructuresNode,
++ 'translations' : empty.TranslationsNode,
++ 'include' : include.IncludeNode,
++ 'emit' : node_io.EmitNode,
++ 'file' : node_io.FileNode,
++ 'output' : node_io.OutputNode,
++ 'ex' : message.ExNode,
++ 'message' : message.MessageNode,
++ 'ph' : message.PhNode,
++ 'else' : misc.ElseNode,
++ 'grit' : misc.GritNode,
++ 'identifier' : misc.IdentifierNode,
++ 'if' : misc.IfNode,
++ 'part' : misc.PartNode,
++ 'release' : misc.ReleaseNode,
++ 'then' : misc.ThenNode,
++ 'structure' : structure.StructureNode,
++ 'skeleton' : variant.SkeletonNode,
++}
++
++
++def ElementToClass(name, typeattr):
++ '''Maps an element to a class that handles the element.
++
++ Args:
++ name: 'element' (the name of the element)
++ typeattr: 'type' (the value of the type attribute, if present, else None)
++
++ Return:
++ type
++ '''
++ if name not in _ELEMENT_TO_CLASS:
++ raise exception.UnknownElement()
++ return _ELEMENT_TO_CLASS[name]
+diff --git a/tools/grit/grit/node/message.py b/tools/grit/grit/node/message.py
+new file mode 100644
+index 0000000000..4fa83cf26b
+--- /dev/null
++++ b/tools/grit/grit/node/message.py
+@@ -0,0 +1,362 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Handling of the <message> element.
++'''
++
++from __future__ import print_function
++
++import re
++
++import six
++
++from grit.node import base
++
++from grit import clique
++from grit import exception
++from grit import lazy_re
++from grit import tclib
++from grit import util
++
++
++# Matches exactly three dots ending a line or followed by whitespace.
++_ELLIPSIS_PATTERN = lazy_re.compile(r'(?<!\.)\.\.\.(?=$|\s)')
++_ELLIPSIS_SYMBOL = u'\u2026' # Ellipsis
++
++# Finds whitespace at the start and end of a string which can be multiline.
++_WHITESPACE = lazy_re.compile(r'(?P<start>\s*)(?P<body>.+?)(?P<end>\s*)\Z',
++ re.DOTALL | re.MULTILINE)
++
++# <ph> placeholder elements should contain the special character formatters
++# used to format <ph> element content.
++# Android format.
++_ANDROID_FORMAT = (r'%[1-9]+\$'
++ r'([-#+ 0,(]*)([0-9]+)?(\.[0-9]+)?'
++ r'([bBhHsScCdoxXeEfgGaAtT%n])')
++# Chrome l10n format.
++_CHROME_FORMAT = r'\$+\d'
++# Windows EWT numeric and GRIT %s %d formats.
++_OTHER_FORMAT = r'%[0-9sd]'
++
++# Finds formatters that must be in a placeholder (<ph>) element.
++_FORMATTERS = lazy_re.compile(
++ '(%s)|(%s)|(%s)' % (_ANDROID_FORMAT, _CHROME_FORMAT, _OTHER_FORMAT))
++_BAD_PLACEHOLDER_MSG = ('ERROR: Placeholder formatter found outside of <ph> '
++ 'tag in message "%s" in %s.')
++_INVALID_PH_CHAR_MSG = ('ERROR: Invalid format characters found in message '
++ '"%s" <ph> tag in %s.')
++
++# Finds HTML tag tokens.
++_HTMLTOKEN = lazy_re.compile(r'<[/]?[a-z][a-z0-9]*[^>]*>', re.I)
++
++# Finds HTML entities.
++_HTMLENTITY = lazy_re.compile(r'&[^\s]*;')
++
++
++class MessageNode(base.ContentNode):
++ '''A <message> element.'''
++
++ # For splitting a list of things that can be separated by commas or
++ # whitespace
++ _SPLIT_RE = lazy_re.compile(r'\s*,\s*|\s+')
++
++ def __init__(self):
++ super(MessageNode, self).__init__()
++ # Valid after EndParsing, this is the MessageClique that contains the
++ # source message and any translations of it that have been loaded.
++ self.clique = None
++
++ # We don't send leading and trailing whitespace into the translation
++ # console, but rather tack it onto the source message and any
++ # translations when formatting them into RC files or what have you.
++ self.ws_at_start = '' # Any whitespace characters at the start of the text
++ self.ws_at_end = '' # --"-- at the end of the text
++
++ # A list of "shortcut groups" this message is in. We check to make sure
++ # that shortcut keys (e.g. &J) within each shortcut group are unique.
++ self.shortcut_groups_ = []
++
++ # Formatter-specific data used to control the output of individual strings.
++ # formatter_data is a space separated list of C preprocessor-style
++ # definitions. Names without values are given the empty string value.
++ # Example: "foo=5 bar baz=100"
++ self.formatter_data = {}
++
++ # Whether or not to convert ... -> U+2026 within Translate().
++ self._replace_ellipsis = False
++
++ def _IsValidChild(self, child):
++ return isinstance(child, (PhNode))
++
++ def _IsValidAttribute(self, name, value):
++ if name not in [
++ 'name', 'offset', 'translateable', 'desc', 'meaning',
++ 'internal_comment', 'shortcut_groups', 'custom_type', 'validation_expr',
++ 'use_name_for_id', 'sub_variable', 'formatter_data',
++ 'is_accessibility_with_no_ui'
++ ]:
++ return False
++ if (name in ('translateable', 'sub_variable') and
++ value not in ['true', 'false']):
++ return False
++ return True
++
++ def SetReplaceEllipsis(self, value):
++ r'''Sets whether to replace ... with \u2026.
++ '''
++ self._replace_ellipsis = value
++
++ def MandatoryAttributes(self):
++ return ['name|offset']
++
++ def DefaultAttributes(self):
++ return {
++ 'custom_type': '',
++ 'desc': '',
++ 'formatter_data': '',
++ 'internal_comment': '',
++ 'is_accessibility_with_no_ui': 'false',
++ 'meaning': '',
++ 'shortcut_groups': '',
++ 'sub_variable': 'false',
++ 'translateable': 'true',
++ 'use_name_for_id': 'false',
++ 'validation_expr': '',
++ }
++
++ def HandleAttribute(self, attrib, value):
++ base.ContentNode.HandleAttribute(self, attrib, value)
++ if attrib != 'formatter_data':
++ return
++
++ # Parse value, a space-separated list of defines, into a dict.
++ # Example: "foo=5 bar" -> {'foo':'5', 'bar':''}
++ for item in value.split():
++ name, _, val = item.partition('=')
++ self.formatter_data[name] = val
++
++ def GetTextualIds(self):
++ '''
++ Returns the concatenation of the parent's node first_id and
++ this node's offset if it has one, otherwise just call the
++ superclass' implementation
++ '''
++ if 'offset' not in self.attrs:
++ return super(MessageNode, self).GetTextualIds()
++
++ # we search for the first grouping node in the parents' list
++ # to take care of the case where the first parent is an <if> node
++ grouping_parent = self.parent
++ import grit.node.empty
++ while grouping_parent and not isinstance(grouping_parent,
++ grit.node.empty.GroupingNode):
++ grouping_parent = grouping_parent.parent
++
++ assert 'first_id' in grouping_parent.attrs
++ return [grouping_parent.attrs['first_id'] + '_' + self.attrs['offset']]
++
++ def IsTranslateable(self):
++ return self.attrs['translateable'] == 'true'
++
++ def EndParsing(self):
++ super(MessageNode, self).EndParsing()
++
++ # Make the text (including placeholder references) and list of placeholders,
++ # verify placeholder formats, then strip and store leading and trailing
++ # whitespace and create the tclib.Message() and a clique to contain it.
++
++ text = ''
++ placeholders = []
++
++ for item in self.mixed_content:
++ if isinstance(item, six.string_types):
++ # Not a <ph> element: fail if any <ph> formatters are detected.
++ if _FORMATTERS.search(item):
++ print(_BAD_PLACEHOLDER_MSG % (item, self.source))
++ raise exception.PlaceholderNotInsidePhNode
++ text += item
++ else:
++ # Extract the <ph> element components.
++ presentation = item.attrs['name'].upper()
++ text += presentation
++ ex = ' ' # <ex> example element cdata if present.
++ if len(item.children):
++ ex = item.children[0].GetCdata()
++ original = item.GetCdata()
++
++ # Sanity check the <ph> element content.
++ cdata = original
++ # Replace all HTML tag tokens in cdata.
++ match = _HTMLTOKEN.search(cdata)
++ while match:
++ cdata = cdata.replace(match.group(0), '_')
++ match = _HTMLTOKEN.search(cdata)
++ # Replace all HTML entities in cdata.
++ match = _HTMLENTITY.search(cdata)
++ while match:
++ cdata = cdata.replace(match.group(0), '_')
++ match = _HTMLENTITY.search(cdata)
++ # Remove first matching formatter from cdata.
++ match = _FORMATTERS.search(cdata)
++ if match:
++ cdata = cdata.replace(match.group(0), '')
++ # Fail if <ph> special chars remain in cdata.
++ if re.search(r'[%\$]', cdata):
++ message_id = self.attrs['name'] + ' ' + original;
++ print(_INVALID_PH_CHAR_MSG % (message_id, self.source))
++ raise exception.InvalidCharactersInsidePhNode
++
++ # Otherwise, accept this <ph> placeholder.
++ placeholders.append(tclib.Placeholder(presentation, original, ex))
++
++ m = _WHITESPACE.match(text)
++ if m:
++ self.ws_at_start = m.group('start')
++ self.ws_at_end = m.group('end')
++ text = m.group('body')
++
++ self.shortcut_groups_ = self._SPLIT_RE.split(self.attrs['shortcut_groups'])
++ self.shortcut_groups_ = [i for i in self.shortcut_groups_ if i != '']
++
++ description_or_id = self.attrs['desc']
++ if description_or_id == '' and 'name' in self.attrs:
++ description_or_id = 'ID: %s' % self.attrs['name']
++
++ assigned_id = None
++ if self.attrs['use_name_for_id'] == 'true':
++ assigned_id = self.attrs['name']
++ message = tclib.Message(text=text, placeholders=placeholders,
++ description=description_or_id,
++ meaning=self.attrs['meaning'],
++ assigned_id=assigned_id)
++ self.InstallMessage(message)
++
++ def InstallMessage(self, message):
++ '''Sets this node's clique from a tclib.Message instance.
++
++ Args:
++ message: A tclib.Message.
++ '''
++ self.clique = self.UberClique().MakeClique(message, self.IsTranslateable())
++ for group in self.shortcut_groups_:
++ self.clique.AddToShortcutGroup(group)
++ if self.attrs['custom_type'] != '':
++ self.clique.SetCustomType(util.NewClassInstance(self.attrs['custom_type'],
++ clique.CustomType))
++ elif self.attrs['validation_expr'] != '':
++ self.clique.SetCustomType(
++ clique.OneOffCustomType(self.attrs['validation_expr']))
++
++ def SubstituteMessages(self, substituter):
++ '''Applies substitution to this message.
++
++ Args:
++ substituter: a grit.util.Substituter object.
++ '''
++ message = substituter.SubstituteMessage(self.clique.GetMessage())
++ if message is not self.clique.GetMessage():
++ self.InstallMessage(message)
++
++ def GetCliques(self):
++ return [self.clique] if self.clique else []
++
++ def Translate(self, lang):
++ '''Returns a translated version of this message.
++ '''
++ assert self.clique
++ msg = self.clique.MessageForLanguage(lang,
++ self.PseudoIsAllowed(),
++ self.ShouldFallbackToEnglish()
++ ).GetRealContent()
++ if self._replace_ellipsis:
++ msg = _ELLIPSIS_PATTERN.sub(_ELLIPSIS_SYMBOL, msg)
++ # Always remove all byte order marks (\uFEFF) https://crbug.com/1033305
++ msg = msg.replace(u'\uFEFF','')
++ return msg.replace('[GRITLANGCODE]', lang)
++
++ def NameOrOffset(self):
++ key = 'name' if 'name' in self.attrs else 'offset'
++ return self.attrs[key]
++
++ def ExpandVariables(self):
++ '''We always expand variables on Messages.'''
++ return True
++
++ def GetDataPackValue(self, lang, encoding):
++ '''Returns a str represenation for a data_pack entry.'''
++ message = self.ws_at_start + self.Translate(lang) + self.ws_at_end
++ return util.Encode(message, encoding)
++
++ def IsResourceMapSource(self):
++ return True
++
++ @staticmethod
++ def Construct(parent, message, name, desc='', meaning='', translateable=True):
++ '''Constructs a new message node that is a child of 'parent', with the
++ name, desc, meaning and translateable attributes set using the same-named
++ parameters and the text of the message and any placeholders taken from
++ 'message', which must be a tclib.Message() object.'''
++ # Convert type to appropriate string
++ translateable = 'true' if translateable else 'false'
++
++ node = MessageNode()
++ node.StartParsing('message', parent)
++ node.HandleAttribute('name', name)
++ node.HandleAttribute('desc', desc)
++ node.HandleAttribute('meaning', meaning)
++ node.HandleAttribute('translateable', translateable)
++
++ items = message.GetContent()
++ for ix, item in enumerate(items):
++ if isinstance(item, six.string_types):
++ # Ensure whitespace at front and back of message is correctly handled.
++ if ix == 0:
++ item = "'''" + item
++ if ix == len(items) - 1:
++ item = item + "'''"
++
++ node.AppendContent(item)
++ else:
++ phnode = PhNode()
++ phnode.StartParsing('ph', node)
++ phnode.HandleAttribute('name', item.GetPresentation())
++ phnode.AppendContent(item.GetOriginal())
++
++ if len(item.GetExample()) and item.GetExample() != ' ':
++ exnode = ExNode()
++ exnode.StartParsing('ex', phnode)
++ exnode.AppendContent(item.GetExample())
++ exnode.EndParsing()
++ phnode.AddChild(exnode)
++
++ phnode.EndParsing()
++ node.AddChild(phnode)
++
++ node.EndParsing()
++ return node
++
++
++class PhNode(base.ContentNode):
++ '''A <ph> element.'''
++
++ def _IsValidChild(self, child):
++ return isinstance(child, ExNode)
++
++ def MandatoryAttributes(self):
++ return ['name']
++
++ def EndParsing(self):
++ super(PhNode, self).EndParsing()
++ # We only allow a single example for each placeholder
++ if len(self.children) > 1:
++ raise exception.TooManyExamples()
++
++ def GetTextualIds(self):
++ # The 'name' attribute is not an ID.
++ return []
++
++
++class ExNode(base.ContentNode):
++ '''An <ex> element.'''
++ pass
+diff --git a/tools/grit/grit/node/message_unittest.py b/tools/grit/grit/node/message_unittest.py
+new file mode 100644
+index 0000000000..7a4cbbedc2
+--- /dev/null
++++ b/tools/grit/grit/node/message_unittest.py
+@@ -0,0 +1,380 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.node.message'''
++
++from __future__ import print_function
++
++import os
++import sys
++import unittest
++
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++from grit import exception
++from grit import tclib
++from grit import util
++from grit.node import message
++
++class MessageUnittest(unittest.TestCase):
++ def testMessage(self):
++ root = util.ParseGrdForUnittest('''
++ <messages>
++ <message name="IDS_GREETING"
++ desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ </messages>''')
++ msg, = root.GetChildrenOfType(message.MessageNode)
++ cliques = msg.GetCliques()
++ content = cliques[0].GetMessage().GetPresentableContent()
++ self.failUnless(content == 'Hello USERNAME, how are you doing today?')
++
++ def testMessageWithWhitespace(self):
++ root = util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_BLA" desc="">
++ ''' Hello there <ph name="USERNAME">%s</ph> '''
++ </message>
++ </messages>""")
++ msg, = root.GetChildrenOfType(message.MessageNode)
++ content = msg.GetCliques()[0].GetMessage().GetPresentableContent()
++ self.failUnless(content == 'Hello there USERNAME')
++ self.failUnless(msg.ws_at_start == ' ')
++ self.failUnless(msg.ws_at_end == ' ')
++
++ def testConstruct(self):
++ msg = tclib.Message(text=" Hello USERNAME, how are you? BINGO\t\t",
++ placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi'),
++ tclib.Placeholder('BINGO', '%d', '11')])
++ msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
++ self.failUnless(msg_node.children[0].name == 'ph')
++ self.failUnless(msg_node.children[0].children[0].name == 'ex')
++ self.failUnless(msg_node.children[0].children[0].GetCdata() == 'Joi')
++ self.failUnless(msg_node.children[1].children[0].GetCdata() == '11')
++ self.failUnless(msg_node.ws_at_start == ' ')
++ self.failUnless(msg_node.ws_at_end == '\t\t')
++
++ def testUnicodeConstruct(self):
++ text = u'Howdie \u00fe'
++ msg = tclib.Message(text=text)
++ msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
++ msg_from_node = msg_node.GetCdata()
++ self.failUnless(msg_from_node == text)
++
++ def testFormatterData(self):
++ root = util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_BLA" desc="" formatter_data=" foo=123 bar qux=low">
++ Text
++ </message>
++ </messages>""")
++ msg, = root.GetChildrenOfType(message.MessageNode)
++ expected_formatter_data = {
++ 'foo': '123',
++ 'bar': '',
++ 'qux': 'low'}
++
++ # Can't use assertDictEqual, not available in Python 2.6, so do it
++ # by hand.
++ self.failUnlessEqual(len(expected_formatter_data),
++ len(msg.formatter_data))
++ for key in expected_formatter_data:
++ self.failUnlessEqual(expected_formatter_data[key],
++ msg.formatter_data[key])
++
++ def testReplaceEllipsis(self):
++ root = util.ParseGrdForUnittest('''
++ <messages>
++ <message name="IDS_GREETING" desc="">
++ A...B.... <ph name="PH">%s<ex>A</ex></ph>... B... C...
++ </message>
++ </messages>''')
++ msg, = root.GetChildrenOfType(message.MessageNode)
++ msg.SetReplaceEllipsis(True)
++ content = msg.Translate('en')
++ self.failUnlessEqual(u'A...B.... %s\u2026 B\u2026 C\u2026', content)
++
++ def testRemoveByteOrderMark(self):
++ root = util.ParseGrdForUnittest(u'''
++ <messages>
++ <message name="IDS_HAS_BOM" desc="">
++ \uFEFFThis\uFEFF i\uFEFFs OK\uFEFF
++ </message>
++ </messages>''')
++ msg, = root.GetChildrenOfType(message.MessageNode)
++ content = msg.Translate('en')
++ self.failUnlessEqual(u'This is OK', content)
++
++ def testPlaceholderHasTooManyExamples(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_FOO" desc="foo">
++ Hi <ph name="NAME">$1<ex>Joi</ex><ex>Joy</ex></ph>
++ </message>
++ </messages>""")
++ except exception.TooManyExamples:
++ return
++ self.fail('Should have gotten exception')
++
++ def testPlaceholderHasInvalidName(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_FOO" desc="foo">
++ Hi <ph name="ABC!">$1</ph>
++ </message>
++ </messages>""")
++ except exception.InvalidPlaceholderName:
++ return
++ self.fail('Should have gotten exception')
++
++ def testChromeLocalizedFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_CHROME_L10N" desc="l10n format">
++ This message is missing the ph node: $1
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testAndroidStringFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_ANDROID" desc="string format">
++ This message is missing a ph node: %1$s
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testAndroidIntegerFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_ANDROID" desc="integer format">
++ This message is missing a ph node: %2$d
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testAndroidIntegerWidthFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_ANDROID" desc="integer width format">
++ This message is missing a ph node: %2$3d
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testValidAndroidIntegerWidthFormatInPhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_ANDROID_WIDTH">
++ <ph name="VALID">%2$3d<ex>042</ex></ph>
++ </message>
++ </messages>""")
++ except:
++ self.fail('Should not have gotten exception')
++
++ def testAndroidFloatFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_ANDROID" desc="float number format">
++ This message is missing a ph node: %3$4.5f
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testGritStringFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_GRIT_STRING" desc="grit string format">
++ This message is missing the ph node: %s
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testGritIntegerFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_GRIT_INTEGER" desc="grit integer format">
++ This message is missing the ph node: %d
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testWindowsETWIntegerFormatIsInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_WINDOWS_ETW" desc="ETW tracing integer">
++ This message is missing the ph node: %1
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testValidMultipleFormattersInsidePhNodes(self):
++ root = util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_MULTIPLE_FORMATTERS">
++ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
++ </message>
++ </messages>""")
++ msg, = root.GetChildrenOfType(message.MessageNode)
++ cliques = msg.GetCliques()
++ content = cliques[0].GetMessage().GetPresentableContent()
++ self.failUnless(content == 'ERROR_COUNT error, WARNING_COUNT warning')
++
++ def testMultipleFormattersAreInsidePhNodes(self):
++ failed = True
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_MULTIPLE_FORMATTERS">
++ %1$d error, %2$d warning
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ failed = False
++ if failed:
++ self.fail('Should have gotten exception')
++ return
++
++ failed = True
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_MULTIPLE_FORMATTERS">
++ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, %2$d warning
++ </message>
++ </messages>""")
++ except exception.PlaceholderNotInsidePhNode:
++ failed = False
++ if failed:
++ self.fail('Should have gotten exception')
++ return
++
++ failed = True
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_MULTIPLE_FORMATTERS">
++ <ph name="INVALID">%1$d %2$d</ph>
++ </message>
++ </messages>""")
++ except exception.InvalidCharactersInsidePhNode:
++ failed = False
++ if failed:
++ self.fail('Should have gotten exception')
++ return
++
++ def testValidHTMLFormatInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_HTML">
++ <ph name="VALID">&lt;span&gt;$1&lt;/span&gt;<ex>1</ex></ph>
++ </message>
++ </messages>""")
++ except:
++ self.fail('Should not have gotten exception')
++
++ def testValidHTMLWithAttributesFormatInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_HTML_ATTRIBUTE">
++ <ph name="VALID">&lt;span attribute="js:$this %"&gt;$2&lt;/span&gt;<ex>2</ex></ph>
++ </message>
++ </messages>""")
++ except:
++ self.fail('Should not have gotten exception')
++
++ def testValidHTMLEntityFormatInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_ENTITY">
++ <ph name="VALID">&gt;%1$d&lt;<ex>1</ex></ph>
++ </message>
++ </messages>""")
++ except:
++ self.fail('Should not have gotten exception')
++
++ def testValidMultipleDollarFormatInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_DOLLARS" desc="l10n dollars format">
++ <ph name="VALID">$$1</ph>
++ </message>
++ </messages>""")
++ except:
++ self.fail('Should not have gotten exception')
++
++ def testInvalidDollarCharacterInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_BAD_DOLLAR">
++ <ph name="INVALID">%1$d $</ph>
++ </message>
++ </messages>""")
++ except exception.InvalidCharactersInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testInvalidPercentCharacterInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_BAD_PERCENT">
++ <ph name="INVALID">%1$d %</ph>
++ </message>
++ </messages>""")
++ except exception.InvalidCharactersInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++ def testInvalidMixedFormatCharactersInsidePhNode(self):
++ try:
++ util.ParseGrdForUnittest("""\
++ <messages>
++ <message name="IDS_MIXED_FORMATS">
++ <ph name="INVALID">%1$2</ph>
++ </message>
++ </messages>""")
++ except exception.InvalidCharactersInsidePhNode:
++ return
++ self.fail('Should have gotten exception')
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py
+new file mode 100644
+index 0000000000..2d8b06d6a5
+--- /dev/null
++++ b/tools/grit/grit/node/misc.py
+@@ -0,0 +1,707 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Miscellaneous node types.
++"""
++
++from __future__ import print_function
++
++import os.path
++import re
++import sys
++
++import six
++
++from grit import constants
++from grit import exception
++from grit import util
++from grit.extern import FP
++from grit.node import base
++from grit.node import message
++from grit.node import node_io
++
++
++# Python 3 doesn't have long() as int() works everywhere. But we really do need
++# the long() behavior on Python 2 as our ids are much too large for int().
++try:
++ long
++except NameError:
++ long = int
++
++
++# RTL languages
++# TODO(jennyz): remove this fixed set of RTL language array
++# now that generic expand_variable code exists.
++_RTL_LANGS = (
++ 'ar', # Arabic
++ 'fa', # Farsi
++ 'iw', # Hebrew
++ 'ks', # Kashmiri
++ 'ku', # Kurdish
++ 'ps', # Pashto
++ 'ur', # Urdu
++ 'yi', # Yiddish
++)
++
++
++def _ReadFirstIdsFromFile(filename, defines):
++ """Read the starting resource id values from |filename|. We also
++ expand variables of the form <(FOO) based on defines passed in on
++ the command line.
++
++ Returns a tuple, the absolute path of SRCDIR followed by the
++ first_ids dictionary.
++ """
++ first_ids_dict = eval(util.ReadFile(filename, 'utf-8'))
++ src_root_dir = os.path.abspath(os.path.join(os.path.dirname(filename),
++ first_ids_dict['SRCDIR']))
++
++ def ReplaceVariable(matchobj):
++ for key, value in defines.items():
++ if matchobj.group(1) == key:
++ return value
++ return ''
++
++ renames = []
++ for grd_filename in first_ids_dict:
++ new_grd_filename = re.sub(r'<\(([A-Za-z_]+)\)', ReplaceVariable,
++ grd_filename)
++ if new_grd_filename != grd_filename:
++ abs_grd_filename = os.path.abspath(new_grd_filename)
++ if abs_grd_filename[:len(src_root_dir)] != src_root_dir:
++ new_grd_filename = os.path.basename(abs_grd_filename)
++ else:
++ new_grd_filename = abs_grd_filename[len(src_root_dir) + 1:]
++ new_grd_filename = new_grd_filename.replace('\\', '/')
++ renames.append((grd_filename, new_grd_filename))
++
++ for grd_filename, new_grd_filename in renames:
++ first_ids_dict[new_grd_filename] = first_ids_dict[grd_filename]
++ del(first_ids_dict[grd_filename])
++
++ return (src_root_dir, first_ids_dict)
++
++
++def _ComputeIds(root, predetermined_tids):
++ """Returns a dict of textual id -> numeric id for all nodes in root.
++
++ IDs are mostly assigned sequentially, but will vary based on:
++ * first_id node attribute (from first_ids_file)
++ * hash of textual id (if not first_id is defined)
++ * offset node attribute
++ * whether the textual id matches a system id
++ * whether the node generates its own ID via GetId()
++
++ Args:
++ predetermined_tids: Dict of textual id -> numeric id to use in return dict.
++ """
++ from grit.node import empty, include, misc, structure
++
++ ids = {} # Maps numeric id to textual id
++ tids = {} # Maps textual id to numeric id
++ id_reasons = {} # Maps numeric id to text id and a human-readable explanation
++ group = None
++ last_id = None
++ predetermined_ids = {value: key
++ for key, value in predetermined_tids.items()}
++
++ for item in root:
++ if isinstance(item, empty.GroupingNode):
++ # Note: this won't work if any GroupingNode can be contained inside
++ # another.
++ group = item
++ last_id = None
++ continue
++
++ assert not item.GetTextualIds() or isinstance(item,
++ (include.IncludeNode, message.MessageNode,
++ misc.IdentifierNode, structure.StructureNode))
++
++ # Resources that use the RES protocol don't need
++ # any numerical ids generated, so we skip them altogether.
++ # This is accomplished by setting the flag 'generateid' to false
++ # in the GRD file.
++ if item.attrs.get('generateid', 'true') == 'false':
++ continue
++
++ for tid in item.GetTextualIds():
++ if util.SYSTEM_IDENTIFIERS.match(tid):
++ # Don't emit a new ID for predefined IDs
++ continue
++
++ if tid in tids:
++ continue
++
++ if predetermined_tids and tid in predetermined_tids:
++ id = predetermined_tids[tid]
++ reason = "from predetermined_tids map"
++
++ # Some identifier nodes can provide their own id,
++ # and we use that id in the generated header in that case.
++ elif hasattr(item, 'GetId') and item.GetId():
++ id = long(item.GetId())
++ reason = 'returned by GetId() method'
++
++ elif ('offset' in item.attrs and group and
++ group.attrs.get('first_id', '') != ''):
++ offset_text = item.attrs['offset']
++ parent_text = group.attrs['first_id']
++
++ try:
++ offset_id = long(offset_text)
++ except ValueError:
++ offset_id = tids[offset_text]
++
++ try:
++ parent_id = long(parent_text)
++ except ValueError:
++ parent_id = tids[parent_text]
++
++ id = parent_id + offset_id
++ reason = 'first_id %d + offset %d' % (parent_id, offset_id)
++
++ # We try to allocate IDs sequentially for blocks of items that might
++ # be related, for instance strings in a stringtable (as their IDs might be
++ # used e.g. as IDs for some radio buttons, in which case the IDs must
++ # be sequential).
++ #
++ # We do this by having the first item in a section store its computed ID
++ # (computed from a fingerprint) in its parent object. Subsequent children
++ # of the same parent will then try to get IDs that sequentially follow
++ # the currently stored ID (on the parent) and increment it.
++ elif last_id is None:
++ # First check if the starting ID is explicitly specified by the parent.
++ if group and group.attrs.get('first_id', '') != '':
++ id = long(group.attrs['first_id'])
++ reason = "from parent's first_id attribute"
++ else:
++ # Automatically generate the ID based on the first clique from the
++ # first child of the first child node of our parent (i.e. when we
++ # first get to this location in the code).
++
++ # According to
++ # http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
++ # the safe usable range for resource IDs in Windows is from decimal
++ # 101 to 0x7FFF.
++
++ id = FP.UnsignedFingerPrint(tid)
++ id = id % (0x7FFF - 101) + 101
++ reason = 'chosen by random fingerprint -- use first_id to override'
++
++ last_id = id
++ else:
++ id = last_id = last_id + 1
++ reason = 'sequentially assigned'
++
++ reason = "%s (%s)" % (tid, reason)
++ # Don't fail when 'offset' is specified, as the base and the 0th
++ # offset will have the same ID.
++ if id in id_reasons and not 'offset' in item.attrs:
++ raise exception.IdRangeOverlap('ID %d was assigned to both %s and %s.'
++ % (id, id_reasons[id], reason))
++
++ if id < 101:
++ print('WARNING: Numeric resource IDs should be greater than 100 to\n'
++ 'avoid conflicts with system-defined resource IDs.')
++
++ if tid not in predetermined_tids and id in predetermined_ids:
++ raise exception.IdRangeOverlap('ID %d overlaps between %s and %s'
++ % (id, tid, predetermined_ids[tid]))
++
++ ids[id] = tid
++ tids[tid] = id
++ id_reasons[id] = reason
++
++ return tids
++
++class SplicingNode(base.Node):
++ """A node whose children should be considered to be at the same level as
++ its siblings for most purposes. This includes <if> and <part> nodes.
++ """
++
++ def _IsValidChild(self, child):
++ assert self.parent, '<%s> node should never be root.' % self.name
++ if isinstance(child, SplicingNode):
++ return True # avoid O(n^2) behavior
++ return self.parent._IsValidChild(child)
++
++
++class IfNode(SplicingNode):
++ """A node for conditional inclusion of resources.
++ """
++
++ def MandatoryAttributes(self):
++ return ['expr']
++
++ def _IsValidChild(self, child):
++ return (isinstance(child, (ThenNode, ElseNode)) or
++ super(IfNode, self)._IsValidChild(child))
++
++ def EndParsing(self):
++ children = self.children
++ self.if_then_else = False
++ if any(isinstance(node, (ThenNode, ElseNode)) for node in children):
++ if (len(children) != 2 or not isinstance(children[0], ThenNode) or
++ not isinstance(children[1], ElseNode)):
++ raise exception.UnexpectedChild(
++ '<if> element must be <if><then>...</then><else>...</else></if>')
++ self.if_then_else = True
++
++ def ActiveChildren(self):
++ cond = self.EvaluateCondition(self.attrs['expr'])
++ if self.if_then_else:
++ return self.children[0 if cond else 1].ActiveChildren()
++ else:
++ # Equivalent to having all children inside <then> with an empty <else>
++ return super(IfNode, self).ActiveChildren() if cond else []
++
++
++class ThenNode(SplicingNode):
++ """A <then> node. Can only appear directly inside an <if> node."""
++ pass
++
++
++class ElseNode(SplicingNode):
++ """An <else> node. Can only appear directly inside an <if> node."""
++ pass
++
++
++class PartNode(SplicingNode):
++ """A node for inclusion of sub-grd (*.grp) files.
++ """
++
++ def __init__(self):
++ super(PartNode, self).__init__()
++ self.started_inclusion = False
++
++ def MandatoryAttributes(self):
++ return ['file']
++
++ def _IsValidChild(self, child):
++ return self.started_inclusion and super(PartNode, self)._IsValidChild(child)
++
++
++class ReleaseNode(base.Node):
++ """The <release> element."""
++
++ def _IsValidChild(self, child):
++ from grit.node import empty
++ return isinstance(child, (empty.IncludesNode, empty.MessagesNode,
++ empty.StructuresNode, empty.IdentifiersNode))
++
++ def _IsValidAttribute(self, name, value):
++ return (
++ (name == 'seq' and int(value) <= self.GetRoot().GetCurrentRelease()) or
++ name == 'allow_pseudo'
++ )
++
++ def MandatoryAttributes(self):
++ return ['seq']
++
++ def DefaultAttributes(self):
++ return { 'allow_pseudo' : 'true' }
++
++
++class GritNode(base.Node):
++ """The <grit> root element."""
++
++ def __init__(self):
++ super(GritNode, self).__init__()
++ self.output_language = ''
++ self.defines = {}
++ self.substituter = None
++ self.target_platform = sys.platform
++ self.whitelist_support = False
++ self._predetermined_ids_file = None
++ self._id_map = None # Dict of textual_id -> numeric_id.
++
++ def _IsValidChild(self, child):
++ from grit.node import empty
++ return isinstance(child, (ReleaseNode, empty.TranslationsNode,
++ empty.OutputsNode))
++
++ def _IsValidAttribute(self, name, value):
++ if name not in ['base_dir', 'first_ids_file', 'source_lang_id',
++ 'latest_public_release', 'current_release',
++ 'enc_check', 'tc_project', 'grit_version',
++ 'output_all_resource_defines']:
++ return False
++ if name in ['latest_public_release', 'current_release'] and value.strip(
++ '0123456789') != '':
++ return False
++ return True
++
++ def MandatoryAttributes(self):
++ return ['latest_public_release', 'current_release']
++
++ def DefaultAttributes(self):
++ return {
++ 'base_dir' : '.',
++ 'first_ids_file': '',
++ 'grit_version': 1,
++ 'source_lang_id' : 'en',
++ 'enc_check' : constants.ENCODING_CHECK,
++ 'tc_project' : 'NEED_TO_SET_tc_project_ATTRIBUTE',
++ }
++
++ def EndParsing(self):
++ super(GritNode, self).EndParsing()
++ if (int(self.attrs['latest_public_release'])
++ > int(self.attrs['current_release'])):
++ raise exception.Parsing('latest_public_release cannot have a greater '
++ 'value than current_release')
++
++ self.ValidateUniqueIds()
++
++ # Add the encoding check if it's not present (should ensure that it's always
++ # present in all .grd files generated by GRIT). If it's present, assert if
++ # it's not correct.
++ if 'enc_check' not in self.attrs or self.attrs['enc_check'] == '':
++ self.attrs['enc_check'] = constants.ENCODING_CHECK
++ else:
++ assert self.attrs['enc_check'] == constants.ENCODING_CHECK, (
++ 'Are you sure your .grd file is in the correct encoding (UTF-8)?')
++
++ def ValidateUniqueIds(self):
++ """Validate that 'name' attribute is unique in all nodes in this tree
++ except for nodes that are children of <if> nodes.
++ """
++ unique_names = {}
++ duplicate_names = []
++ # To avoid false positives from mutually exclusive <if> clauses, check
++ # against whatever the output condition happens to be right now.
++ # TODO(benrg): do something better.
++ for node in self.ActiveDescendants():
++ if node.attrs.get('generateid', 'true') == 'false':
++ continue # Duplication not relevant in that case
++
++ for node_id in node.GetTextualIds():
++ if util.SYSTEM_IDENTIFIERS.match(node_id):
++ continue # predefined IDs are sometimes used more than once
++
++ if node_id in unique_names and node_id not in duplicate_names:
++ duplicate_names.append(node_id)
++ unique_names[node_id] = 1
++
++ if len(duplicate_names):
++ raise exception.DuplicateKey(', '.join(duplicate_names))
++
++
++ def GetCurrentRelease(self):
++ """Returns the current release number."""
++ return int(self.attrs['current_release'])
++
++ def GetLatestPublicRelease(self):
++ """Returns the latest public release number."""
++ return int(self.attrs['latest_public_release'])
++
++ def GetSourceLanguage(self):
++ """Returns the language code of the source language."""
++ return self.attrs['source_lang_id']
++
++ def GetTcProject(self):
++ """Returns the name of this project in the TranslationConsole, or
++ 'NEED_TO_SET_tc_project_ATTRIBUTE' if it is not defined."""
++ return self.attrs['tc_project']
++
++ def SetOwnDir(self, dir):
++ """Informs the 'grit' element of the directory the file it is in resides.
++ This allows it to calculate relative paths from the input file, which is
++ what we desire (rather than from the current path).
++
++ Args:
++ dir: r'c:\bla'
++
++ Return:
++ None
++ """
++ assert dir
++ self.base_dir = os.path.normpath(os.path.join(dir, self.attrs['base_dir']))
++
++ def GetBaseDir(self):
++ """Returns the base directory, relative to the working directory. To get
++ the base directory as set in the .grd file, use GetOriginalBaseDir()
++ """
++ if hasattr(self, 'base_dir'):
++ return self.base_dir
++ else:
++ return self.GetOriginalBaseDir()
++
++ def GetOriginalBaseDir(self):
++ """Returns the base directory, as set in the .grd file.
++ """
++ return self.attrs['base_dir']
++
++ def IsWhitelistSupportEnabled(self):
++ return self.whitelist_support
++
++ def SetWhitelistSupportEnabled(self, whitelist_support):
++ self.whitelist_support = whitelist_support
++
++ def GetInputFiles(self):
++ """Returns the list of files that are read to produce the output."""
++
++ # Importing this here avoids a circular dependency in the imports.
++ # pylint: disable-msg=C6204
++ from grit.node import include
++ from grit.node import misc
++ from grit.node import structure
++ from grit.node import variant
++
++ # Check if the input is required for any output configuration.
++ input_files = set()
++ # Collect even inactive PartNodes since they affect ID assignments.
++ for node in self:
++ if isinstance(node, misc.PartNode):
++ input_files.add(self.ToRealPath(node.GetInputPath()))
++
++ old_output_language = self.output_language
++ for lang, ctx, fallback in self.GetConfigurations():
++ self.SetOutputLanguage(lang or self.GetSourceLanguage())
++ self.SetOutputContext(ctx)
++ self.SetFallbackToDefaultLayout(fallback)
++
++ for node in self.ActiveDescendants():
++ if isinstance(node, (node_io.FileNode, include.IncludeNode,
++ structure.StructureNode, variant.SkeletonNode)):
++ input_path = node.GetInputPath()
++ if input_path is not None:
++ input_files.add(self.ToRealPath(input_path))
++
++ # If it's a flattened node, grab inlined resources too.
++ if ((node.name == 'structure' or node.name == 'include')
++ and node.attrs['flattenhtml'] == 'true'):
++ if node.name == 'structure':
++ node.RunPreSubstitutionGatherer()
++ input_files.update(node.GetHtmlResourceFilenames())
++
++ self.SetOutputLanguage(old_output_language)
++ return sorted(input_files)
++
++ def GetFirstIdsFile(self):
++ """Returns a usable path to the first_ids file, if set, otherwise
++ returns None.
++
++ The first_ids_file attribute is by default relative to the
++ base_dir of the .grd file, but may be prefixed by GRIT_DIR/,
++ which makes it relative to the directory of grit.py
++ (e.g. GRIT_DIR/../gritsettings/resource_ids).
++ """
++ if not self.attrs['first_ids_file']:
++ return None
++
++ path = self.attrs['first_ids_file']
++ GRIT_DIR_PREFIX = 'GRIT_DIR'
++ if (path.startswith(GRIT_DIR_PREFIX)
++ and path[len(GRIT_DIR_PREFIX)] in ['/', '\\']):
++ return util.PathFromRoot(path[len(GRIT_DIR_PREFIX) + 1:])
++ else:
++ return self.ToRealPath(path)
++
++ def GetOutputFiles(self):
++ """Returns the list of <output> nodes that are descendants of this node's
++ <outputs> child and are not enclosed by unsatisfied <if> conditionals.
++ """
++ for child in self.children:
++ if child.name == 'outputs':
++ return [node for node in child.ActiveDescendants()
++ if node.name == 'output']
++ raise exception.MissingElement()
++
++ def GetConfigurations(self):
++ """Returns the distinct (language, context, fallback_to_default_layout)
++ triples from the output nodes.
++ """
++ return set((n.GetLanguage(), n.GetContext(), n.GetFallbackToDefaultLayout())
++ for n in self.GetOutputFiles())
++
++ def GetSubstitutionMessages(self):
++ """Returns the list of <message sub_variable="true"> nodes."""
++ return [n for n in self.ActiveDescendants()
++ if isinstance(n, message.MessageNode)
++ and n.attrs['sub_variable'] == 'true']
++
++ def SetOutputLanguage(self, output_language):
++ """Set the output language. Prepares substitutions.
++
++ The substitutions are reset every time the language is changed.
++ They include messages designated as variables, and language codes for html
++ and rc files.
++
++ Args:
++ output_language: a two-letter language code (eg: 'en', 'ar'...) or ''
++ """
++ if not output_language:
++ # We do not specify the output language for .grh files,
++ # so we get an empty string as the default.
++ # The value should match grit.clique.MessageClique.source_language.
++ output_language = self.GetSourceLanguage()
++ if output_language != self.output_language:
++ self.output_language = output_language
++ self.substituter = None # force recalculate
++
++ def SetOutputContext(self, output_context):
++ self.output_context = output_context
++ self.substituter = None # force recalculate
++
++ def SetFallbackToDefaultLayout(self, fallback_to_default_layout):
++ self.fallback_to_default_layout = fallback_to_default_layout
++ self.substituter = None # force recalculate
++
++ def SetDefines(self, defines):
++ self.defines = defines
++ self.substituter = None # force recalculate
++
++ def SetTargetPlatform(self, target_platform):
++ self.target_platform = target_platform
++
++ def GetSubstituter(self):
++ if self.substituter is None:
++ self.substituter = util.Substituter()
++ self.substituter.AddMessages(self.GetSubstitutionMessages(),
++ self.output_language)
++ if self.output_language in _RTL_LANGS:
++ direction = 'dir="RTL"'
++ else:
++ direction = 'dir="LTR"'
++ self.substituter.AddSubstitutions({
++ 'GRITLANGCODE': self.output_language,
++ 'GRITDIR': direction,
++ })
++ from grit.format import rc # avoid circular dep
++ rc.RcSubstitutions(self.substituter, self.output_language)
++ return self.substituter
++
++ def AssignFirstIds(self, filename_or_stream, defines):
++ """Assign first ids to each grouping node based on values from the
++ first_ids file (if specified on the <grit> node).
++ """
++ assert self._id_map is None, 'AssignFirstIds() after InitializeIds()'
++ # If the input is a stream, then we're probably in a unit test and
++ # should skip this step.
++ if not isinstance(filename_or_stream, six.string_types):
++ return
++
++ # Nothing to do if the first_ids_filename attribute isn't set.
++ first_ids_filename = self.GetFirstIdsFile()
++ if not first_ids_filename:
++ return
++
++ src_root_dir, first_ids = _ReadFirstIdsFromFile(first_ids_filename,
++ defines)
++ from grit.node import empty
++ for node in self.Preorder():
++ if isinstance(node, empty.GroupingNode):
++ abs_filename = os.path.abspath(filename_or_stream)
++ if abs_filename[:len(src_root_dir)] != src_root_dir:
++ filename = os.path.basename(filename_or_stream)
++ else:
++ filename = abs_filename[len(src_root_dir) + 1:]
++ filename = filename.replace('\\', '/')
++
++ if node.attrs['first_id'] != '':
++ raise Exception(
++ "Don't set the first_id attribute when using the first_ids_file "
++ "attribute on the <grit> node, update %s instead." %
++ first_ids_filename)
++
++ try:
++ id_list = first_ids[filename][node.name]
++ except KeyError as e:
++ print('-' * 78)
++ print('Resource id not set for %s (%s)!' % (filename, node.name))
++ print('Please update %s to include an entry for %s. See the '
++ 'comments in resource_ids for information on why you need to '
++ 'update that file.' % (first_ids_filename, filename))
++ print('-' * 78)
++ raise e
++
++ try:
++ node.attrs['first_id'] = str(id_list.pop(0))
++ except IndexError as e:
++ raise Exception('Please update %s and add a first id for %s (%s).'
++ % (first_ids_filename, filename, node.name))
++
++ def GetIdMap(self):
++ '''Return a dictionary mapping textual ids to numeric ids.'''
++ return self._id_map
++
++ def SetPredeterminedIdsFile(self, predetermined_ids_file):
++ assert self._id_map is None, (
++ 'SetPredeterminedIdsFile() after InitializeIds()')
++ self._predetermined_ids_file = predetermined_ids_file
++
++ def InitializeIds(self):
++ '''Initializes the text ID -> numeric ID mapping.'''
++ predetermined_id_map = {}
++ if self._predetermined_ids_file:
++ with open(self._predetermined_ids_file) as f:
++ for line in f:
++ tid, nid = line.split()
++ predetermined_id_map[tid] = int(nid)
++ self._id_map = _ComputeIds(self, predetermined_id_map)
++
++ def RunGatherers(self, debug=False):
++ '''Call RunPreSubstitutionGatherer() on every node of the tree, then apply
++ substitutions, then call RunPostSubstitutionGatherer() on every node.
++
++ The substitutions step requires that the output language has been set.
++ Locally, get the Substitution messages and add them to the substituter.
++ Also add substitutions for language codes in the Rc.
++
++ Args:
++ debug: will print information while running gatherers.
++ '''
++ for node in self.ActiveDescendants():
++ if hasattr(node, 'RunPreSubstitutionGatherer'):
++ with node:
++ node.RunPreSubstitutionGatherer(debug=debug)
++
++ assert self.output_language
++ self.SubstituteMessages(self.GetSubstituter())
++
++ for node in self.ActiveDescendants():
++ if hasattr(node, 'RunPostSubstitutionGatherer'):
++ with node:
++ node.RunPostSubstitutionGatherer(debug=debug)
++
++
++class IdentifierNode(base.Node):
++ """A node for specifying identifiers that should appear in the resource
++ header file, and be unique amongst all other resource identifiers, but don't
++ have any other attributes or reference any resources.
++ """
++
++ def MandatoryAttributes(self):
++ return ['name']
++
++ def DefaultAttributes(self):
++ return { 'comment' : '', 'id' : '', 'systemid': 'false' }
++
++ def GetId(self):
++ """Returns the id of this identifier if it has one, None otherwise
++ """
++ if 'id' in self.attrs:
++ return self.attrs['id']
++ return None
++
++ def EndParsing(self):
++ """Handles system identifiers."""
++ super(IdentifierNode, self).EndParsing()
++ if self.attrs['systemid'] == 'true':
++ util.SetupSystemIdentifiers((self.attrs['name'],))
++
++ @staticmethod
++ def Construct(parent, name, id, comment, systemid='false'):
++ """Creates a new node which is a child of 'parent', with attributes set
++ by parameters of the same name.
++ """
++ node = IdentifierNode()
++ node.StartParsing('identifier', parent)
++ node.HandleAttribute('name', name)
++ node.HandleAttribute('id', id)
++ node.HandleAttribute('comment', comment)
++ node.HandleAttribute('systemid', systemid)
++ node.EndParsing()
++ return node
+diff --git a/tools/grit/grit/node/misc_unittest.py b/tools/grit/grit/node/misc_unittest.py
+new file mode 100644
+index 0000000000..c192b096f4
+--- /dev/null
++++ b/tools/grit/grit/node/misc_unittest.py
+@@ -0,0 +1,590 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for misc.GritNode'''
++
++from __future__ import print_function
++
++import contextlib
++import os
++import sys
++import tempfile
++import unittest
++
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++from six import StringIO
++
++from grit import grd_reader
++import grit.exception
++from grit import util
++from grit.format import rc
++from grit.format import rc_header
++from grit.node import misc
++
++
++@contextlib.contextmanager
++def _MakeTempPredeterminedIdsFile(content):
++ """Write the |content| string to a temporary file.
++
++ The temporary file must be deleted by the caller.
++
++ Example:
++ with _MakeTempPredeterminedIdsFile('foo') as path:
++ ...
++ os.remove(path)
++
++ Args:
++ content: The string to write.
++
++ Yields:
++ The name of the temporary file.
++ """
++ with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
++ f.write(content)
++ f.flush()
++ f.close()
++ yield f.name
++
++
++class GritNodeUnittest(unittest.TestCase):
++ def testUniqueNameAttribute(self):
++ try:
++ restree = grd_reader.Parse(
++ util.PathFromRoot('grit/testdata/duplicate-name-input.xml'))
++ self.fail('Expected parsing exception because of duplicate names.')
++ except grit.exception.Parsing:
++ pass # Expected case
++
++ def testReadFirstIdsFromFile(self):
++ test_resource_ids = os.path.join(os.path.dirname(__file__), '..',
++ 'testdata', 'resource_ids')
++ base_dir = os.path.dirname(test_resource_ids)
++
++ src_dir, id_dict = misc._ReadFirstIdsFromFile(
++ test_resource_ids,
++ {
++ 'FOO': os.path.join(base_dir, 'bar'),
++ 'SHARED_INTERMEDIATE_DIR': os.path.join(base_dir,
++ 'out/Release/obj/gen'),
++ })
++ self.assertEqual({}, id_dict.get('bar/file.grd', None))
++ self.assertEqual({},
++ id_dict.get('out/Release/obj/gen/devtools/devtools.grd', None))
++
++ src_dir, id_dict = misc._ReadFirstIdsFromFile(
++ test_resource_ids,
++ {
++ 'SHARED_INTERMEDIATE_DIR': '/outside/src_dir',
++ })
++ self.assertEqual({}, id_dict.get('devtools.grd', None))
++
++ # Verifies that GetInputFiles() returns the correct list of files
++ # corresponding to ChromeScaledImage nodes when assets are missing.
++ def testGetInputFilesChromeScaledImage(self):
++ chrome_html_path = util.PathFromRoot('grit/testdata/chrome_html.html')
++ xml = '''<?xml version="1.0" encoding="utf-8"?>
++ <grit latest_public_release="0" current_release="1">
++ <outputs>
++ <output filename="default.pak" type="data_package" context="default_100_percent" />
++ <output filename="special.pak" type="data_package" context="special_100_percent" fallback_to_default_layout="false" />
++ </outputs>
++ <release seq="1">
++ <structures fallback_to_low_resolution="true">
++ <structure type="chrome_scaled_image" name="IDR_A" file="a.png" />
++ <structure type="chrome_scaled_image" name="IDR_B" file="b.png" />
++ <structure type="chrome_html" name="HTML_FILE1" file="%s" flattenhtml="true" />
++ </structures>
++ </release>
++ </grit>''' % chrome_html_path
++
++ grd = grd_reader.Parse(StringIO(xml),
++ util.PathFromRoot('grit/testdata'))
++ expected = ['chrome_html.html', 'default_100_percent/a.png',
++ 'default_100_percent/b.png', 'included_sample.html',
++ 'special_100_percent/a.png']
++ actual = [os.path.relpath(path, util.PathFromRoot('grit/testdata')) for
++ path in grd.GetInputFiles()]
++ # Convert path separator for Windows paths.
++ actual = [path.replace('\\', '/') for path in actual]
++ self.assertEquals(expected, actual)
++
++ # Verifies that GetInputFiles() returns the correct list of files
++ # when files include other files.
++ def testGetInputFilesFromIncludes(self):
++ chrome_html_path = util.PathFromRoot('grit/testdata/chrome_html.html')
++ xml = '''<?xml version="1.0" encoding="utf-8"?>
++ <grit latest_public_release="0" current_release="1">
++ <outputs>
++ <output filename="default.pak" type="data_package" context="default_100_percent" />
++ <output filename="special.pak" type="data_package" context="special_100_percent" fallback_to_default_layout="false" />
++ </outputs>
++ <release seq="1">
++ <includes>
++ <include name="IDR_TESTDATA_CHROME_HTML" file="%s" flattenhtml="true"
++ allowexternalscript="true" type="BINDATA" />
++ </includes>
++ </release>
++ </grit>''' % chrome_html_path
++
++ grd = grd_reader.Parse(StringIO(xml), util.PathFromRoot('grit/testdata'))
++ expected = ['chrome_html.html', 'included_sample.html']
++ actual = [os.path.relpath(path, util.PathFromRoot('grit/testdata')) for
++ path in grd.GetInputFiles()]
++ # Convert path separator for Windows paths.
++ actual = [path.replace('\\', '/') for path in actual]
++ self.assertEquals(expected, actual)
++
++ def testNonDefaultEntry(self):
++ grd = util.ParseGrdForUnittest('''
++ <messages>
++ <message name="IDS_A" desc="foo">bar</message>
++ <if expr="lang == 'fr'">
++ <message name="IDS_B" desc="foo">bar</message>
++ </if>
++ </messages>''')
++ grd.SetOutputLanguage('fr')
++ output = ''.join(rc_header.Format(grd, 'fr', '.'))
++ self.assertIn('#define IDS_A 2378\n#define IDS_B 2379', output)
++
++ def testExplicitFirstIdOverlaps(self):
++ # second first_id will overlap preexisting range
++ self.assertRaises(grit.exception.IdRangeOverlap,
++ util.ParseGrdForUnittest, '''
++ <includes first_id="300" comment="bingo">
++ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
++ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
++ </includes>
++ <messages first_id="301">
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ <message name="IDS_SMURFGEBURF">Frubegfrums</message>
++ </messages>''')
++
++ def testImplicitOverlapsPreexisting(self):
++ # second message in <messages> will overlap preexisting range
++ self.assertRaises(grit.exception.IdRangeOverlap,
++ util.ParseGrdForUnittest, '''
++ <includes first_id="301" comment="bingo">
++ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
++ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
++ </includes>
++ <messages first_id="300">
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ <message name="IDS_SMURFGEBURF">Frubegfrums</message>
++ </messages>''')
++
++ def testPredeterminedIds(self):
++ with _MakeTempPredeterminedIdsFile('IDS_A 101\nIDS_B 102') as ids_file:
++ grd = util.ParseGrdForUnittest('''
++ <includes first_id="300" comment="bingo">
++ <include type="gif" name="IDS_B" file="images/logo.gif" />
++ </includes>
++ <messages first_id="10000">
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ <message name="IDS_A">
++ Bongo!
++ </message>
++ </messages>''', predetermined_ids_file=ids_file)
++ output = rc_header.FormatDefines(grd)
++ self.assertEqual(('#define IDS_B 102\n'
++ '#define IDS_GREETING 10000\n'
++ '#define IDS_A 101\n'), ''.join(output))
++ os.remove(ids_file)
++
++ def testPredeterminedIdsOverlap(self):
++ with _MakeTempPredeterminedIdsFile('ID_LOGO 10000') as ids_file:
++ self.assertRaises(grit.exception.IdRangeOverlap,
++ util.ParseGrdForUnittest, '''
++ <includes first_id="300" comment="bingo">
++ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
++ </includes>
++ <messages first_id="10000">
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ <message name="IDS_BONGO">
++ Bongo!
++ </message>
++ </messages>''', predetermined_ids_file=ids_file)
++ os.remove(ids_file)
++
++
++class IfNodeUnittest(unittest.TestCase):
++ def testIffyness(self):
++ grd = grd_reader.Parse(StringIO('''
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <if expr="'bingo' in defs">
++ <message name="IDS_BINGO">
++ Bingo!
++ </message>
++ </if>
++ <if expr="'hello' in defs">
++ <message name="IDS_HELLO">
++ Hello!
++ </message>
++ </if>
++ <if expr="lang == 'fr' or 'FORCE_FRENCH' in defs">
++ <message name="IDS_HELLO" internal_comment="French version">
++ Good morning
++ </message>
++ </if>
++ <if expr="is_win">
++ <message name="IDS_ISWIN">is_win</message>
++ </if>
++ </messages>
++ </release>
++ </grit>'''), dir='.')
++
++ messages_node = grd.children[0].children[0]
++ bingo_message = messages_node.children[0].children[0]
++ hello_message = messages_node.children[1].children[0]
++ french_message = messages_node.children[2].children[0]
++ is_win_message = messages_node.children[3].children[0]
++
++ self.assertTrue(bingo_message.name == 'message')
++ self.assertTrue(hello_message.name == 'message')
++ self.assertTrue(french_message.name == 'message')
++
++ grd.SetOutputLanguage('fr')
++ grd.SetDefines({'hello': '1'})
++ active = set(grd.ActiveDescendants())
++ self.failUnless(bingo_message not in active)
++ self.failUnless(hello_message in active)
++ self.failUnless(french_message in active)
++
++ grd.SetOutputLanguage('en')
++ grd.SetDefines({'bingo': 1})
++ active = set(grd.ActiveDescendants())
++ self.failUnless(bingo_message in active)
++ self.failUnless(hello_message not in active)
++ self.failUnless(french_message not in active)
++
++ grd.SetOutputLanguage('en')
++ grd.SetDefines({'FORCE_FRENCH': '1', 'bingo': '1'})
++ active = set(grd.ActiveDescendants())
++ self.failUnless(bingo_message in active)
++ self.failUnless(hello_message not in active)
++ self.failUnless(french_message in active)
++
++ grd.SetOutputLanguage('en')
++ grd.SetDefines({})
++ self.failUnless(grd.target_platform == sys.platform)
++ grd.SetTargetPlatform('darwin')
++ active = set(grd.ActiveDescendants())
++ self.failUnless(is_win_message not in active)
++ grd.SetTargetPlatform('win32')
++ active = set(grd.ActiveDescendants())
++ self.failUnless(is_win_message in active)
++
++ def testElsiness(self):
++ grd = util.ParseGrdForUnittest('''
++ <messages>
++ <if expr="True">
++ <then> <message name="IDS_YES1"></message> </then>
++ <else> <message name="IDS_NO1"></message> </else>
++ </if>
++ <if expr="True">
++ <then> <message name="IDS_YES2"></message> </then>
++ <else> </else>
++ </if>
++ <if expr="True">
++ <then> </then>
++ <else> <message name="IDS_NO2"></message> </else>
++ </if>
++ <if expr="True">
++ <then> </then>
++ <else> </else>
++ </if>
++ <if expr="False">
++ <then> <message name="IDS_NO3"></message> </then>
++ <else> <message name="IDS_YES3"></message> </else>
++ </if>
++ <if expr="False">
++ <then> <message name="IDS_NO4"></message> </then>
++ <else> </else>
++ </if>
++ <if expr="False">
++ <then> </then>
++ <else> <message name="IDS_YES4"></message> </else>
++ </if>
++ <if expr="False">
++ <then> </then>
++ <else> </else>
++ </if>
++ </messages>''')
++ included = [msg.attrs['name'] for msg in grd.ActiveDescendants()
++ if msg.name == 'message']
++ self.assertEqual(['IDS_YES1', 'IDS_YES2', 'IDS_YES3', 'IDS_YES4'], included)
++
++ def testIffynessWithOutputNodes(self):
++ grd = grd_reader.Parse(StringIO('''
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <outputs>
++ <output filename="uncond1.rc" type="rc_data" />
++ <if expr="lang == 'fr' or 'hello' in defs">
++ <output filename="only_fr.adm" type="adm" />
++ <output filename="only_fr.plist" type="plist" />
++ </if>
++ <if expr="lang == 'ru'">
++ <output filename="doc.html" type="document" />
++ </if>
++ <output filename="uncond2.adm" type="adm" />
++ <output filename="iftest.h" type="rc_header">
++ <emit emit_type='prepend'></emit>
++ </output>
++ </outputs>
++ </grit>'''), dir='.')
++
++ outputs_node = grd.children[0]
++ uncond1_output = outputs_node.children[0]
++ only_fr_adm_output = outputs_node.children[1].children[0]
++ only_fr_plist_output = outputs_node.children[1].children[1]
++ doc_output = outputs_node.children[2].children[0]
++ uncond2_output = outputs_node.children[0]
++ self.assertTrue(uncond1_output.name == 'output')
++ self.assertTrue(only_fr_adm_output.name == 'output')
++ self.assertTrue(only_fr_plist_output.name == 'output')
++ self.assertTrue(doc_output.name == 'output')
++ self.assertTrue(uncond2_output.name == 'output')
++
++ grd.SetOutputLanguage('ru')
++ grd.SetDefines({'hello': '1'})
++ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
++ self.assertEquals(
++ outputs,
++ ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'doc.html',
++ 'uncond2.adm', 'iftest.h'])
++
++ grd.SetOutputLanguage('ru')
++ grd.SetDefines({'bingo': '2'})
++ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
++ self.assertEquals(
++ outputs,
++ ['uncond1.rc', 'doc.html', 'uncond2.adm', 'iftest.h'])
++
++ grd.SetOutputLanguage('fr')
++ grd.SetDefines({'hello': '1'})
++ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
++ self.assertEquals(
++ outputs,
++ ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'uncond2.adm',
++ 'iftest.h'])
++
++ grd.SetOutputLanguage('en')
++ grd.SetDefines({'bingo': '1'})
++ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
++ self.assertEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
++
++ grd.SetOutputLanguage('fr')
++ grd.SetDefines({'bingo': '1'})
++ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
++ self.assertNotEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
++
++ def testChildrenAccepted(self):
++ grd_reader.Parse(StringIO(r'''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <includes>
++ <if expr="'bingo' in defs">
++ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
++ </if>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
++ </if>
++ </if>
++ </includes>
++ <structures>
++ <if expr="'bingo' in defs">
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
++ </if>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
++ </if>
++ </if>
++ </structures>
++ <messages>
++ <if expr="'bingo' in defs">
++ <message name="IDS_BINGO">Bingo!</message>
++ </if>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <message name="IDS_BINGO">Bingo!</message>
++ </if>
++ </if>
++ </messages>
++ </release>
++ <translations>
++ <if expr="'bingo' in defs">
++ <file lang="nl" path="nl_translations.xtb" />
++ </if>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <file lang="nl" path="nl_translations.xtb" />
++ </if>
++ </if>
++ </translations>
++ </grit>'''), dir='.')
++
++ def testIfBadChildrenNesting(self):
++ # includes
++ xml = StringIO(r'''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <includes>
++ <if expr="'bingo' in defs">
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
++ </if>
++ </includes>
++ </release>
++ </grit>''')
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++ # messages
++ xml = StringIO(r'''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <if expr="'bingo' in defs">
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
++ </if>
++ </messages>
++ </release>
++ </grit>''')
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++ # structures
++ xml = StringIO('''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <structures>
++ <if expr="'bingo' in defs">
++ <message name="IDS_BINGO">Bingo!</message>
++ </if>
++ </structures>
++ </release>
++ </grit>''')
++ # translations
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++ xml = StringIO('''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <translations>
++ <if expr="'bingo' in defs">
++ <message name="IDS_BINGO">Bingo!</message>
++ </if>
++ </translations>
++ </grit>''')
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++ # same with nesting
++ xml = StringIO(r'''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <includes>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
++ </if>
++ </if>
++ </includes>
++ </release>
++ </grit>''')
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++ xml = StringIO(r'''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
++ </if>
++ </if>
++ </messages>
++ </release>
++ </grit>''')
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++ xml = StringIO('''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <structures>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <message name="IDS_BINGO">Bingo!</message>
++ </if>
++ </if>
++ </structures>
++ </release>
++ </grit>''')
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++ xml = StringIO('''<?xml version="1.0"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <translations>
++ <if expr="'bingo' in defs">
++ <if expr="'hello' in defs">
++ <message name="IDS_BINGO">Bingo!</message>
++ </if>
++ </if>
++ </translations>
++ </grit>''')
++ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
++
++
++class ReleaseNodeUnittest(unittest.TestCase):
++ def testPseudoControl(self):
++ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="1" source_lang_id="en-US" current_release="2" base_dir=".">
++ <release seq="1" allow_pseudo="false">
++ <messages>
++ <message name="IDS_HELLO">
++ Hello
++ </message>
++ </messages>
++ <structures>
++ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
++ </structures>
++ </release>
++ <release seq="2">
++ <messages>
++ <message name="IDS_BINGO">
++ Bingo
++ </message>
++ </messages>
++ <structures>
++ <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
++ </structures>
++ </release>
++ </grit>'''), util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++
++ hello = grd.GetNodeById('IDS_HELLO')
++ aboutbox = grd.GetNodeById('IDD_ABOUTBOX')
++ bingo = grd.GetNodeById('IDS_BINGO')
++ menu = grd.GetNodeById('IDC_KLONKMENU')
++
++ for node in [hello, aboutbox]:
++ self.failUnless(not node.PseudoIsAllowed())
++
++ for node in [bingo, menu]:
++ self.failUnless(node.PseudoIsAllowed())
++
++ # TODO(benrg): There was a test here that formatting hello and aboutbox with
++ # a pseudo language should fail, but they do not fail and the test was
++ # broken and failed to catch it. Fix this.
++
++ # Should not raise an exception since pseudo is allowed
++ rc.FormatMessage(bingo, 'xyz-pseudo')
++ rc.FormatStructure(menu, 'xyz-pseudo', '.')
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/mock_brotli.py b/tools/grit/grit/node/mock_brotli.py
+new file mode 100644
+index 0000000000..14237aab20
+--- /dev/null
++++ b/tools/grit/grit/node/mock_brotli.py
+@@ -0,0 +1,10 @@
++#!/usr/bin/env python
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Mock Brotli Executable for testing purposes."""
++
++import sys
++
++sys.stdout.write('This has been mock compressed!')
+diff --git a/tools/grit/grit/node/node_io.py b/tools/grit/grit/node/node_io.py
+new file mode 100644
+index 0000000000..ccbc2c0647
+--- /dev/null
++++ b/tools/grit/grit/node/node_io.py
+@@ -0,0 +1,117 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The <output> and <file> elements.
++'''
++
++from __future__ import print_function
++
++import os
++
++from grit import xtb_reader
++from grit.node import base
++
++
++class FileNode(base.Node):
++ '''A <file> element.'''
++
++ def __init__(self):
++ super(FileNode, self).__init__()
++ self.re = None
++ self.should_load_ = True
++
++ def IsTranslation(self):
++ return True
++
++ def GetLang(self):
++ return self.attrs['lang']
++
++ def DisableLoading(self):
++ self.should_load_ = False
++
++ def MandatoryAttributes(self):
++ return ['path', 'lang']
++
++ def RunPostSubstitutionGatherer(self, debug=False):
++ if not self.should_load_:
++ return
++
++ root = self.GetRoot()
++ defs = getattr(root, 'defines', {})
++ target_platform = getattr(root, 'target_platform', '')
++
++ xtb_file = open(self.ToRealPath(self.GetInputPath()), 'rb')
++ try:
++ lang = xtb_reader.Parse(xtb_file,
++ self.UberClique().GenerateXtbParserCallback(
++ self.attrs['lang'], debug=debug),
++ defs=defs,
++ target_platform=target_platform)
++ except:
++ print("Exception during parsing of %s" % self.GetInputPath())
++ raise
++ # Translation console uses non-standard language codes 'iw' and 'no' for
++ # Hebrew and Norwegian Bokmal instead of 'he' and 'nb' used in Chrome.
++ # Note that some Chrome's .grd still use 'no' instead of 'nb', but 'nb' is
++ # always used for generated .pak files.
++ ALTERNATIVE_LANG_CODE_MAP = { 'he': 'iw', 'nb': 'no' }
++ assert (lang == self.attrs['lang'] or
++ lang == ALTERNATIVE_LANG_CODE_MAP[self.attrs['lang']]), (
++ 'The XTB file you reference must contain messages in the language '
++ 'specified\nby the \'lang\' attribute.')
++
++ def GetInputPath(self):
++ return os.path.expandvars(self.attrs['path'])
++
++
++class OutputNode(base.Node):
++ '''An <output> element.'''
++
++ def MandatoryAttributes(self):
++ return ['filename', 'type']
++
++ def DefaultAttributes(self):
++ return {
++ 'lang' : '', # empty lang indicates all languages
++ 'language_section' : 'neutral', # defines a language neutral section
++ 'context' : '',
++ 'fallback_to_default_layout' : 'true',
++ }
++
++ def GetType(self):
++ return self.attrs['type']
++
++ def GetLanguage(self):
++ '''Returns the language ID, default 'en'.'''
++ return self.attrs['lang']
++
++ def GetContext(self):
++ return self.attrs['context']
++
++ def GetFilename(self):
++ return self.attrs['filename']
++
++ def GetOutputFilename(self):
++ path = None
++ if hasattr(self, 'output_filename'):
++ path = self.output_filename
++ else:
++ path = self.attrs['filename']
++ return os.path.expandvars(path)
++
++ def GetFallbackToDefaultLayout(self):
++ return self.attrs['fallback_to_default_layout'].lower() == 'true'
++
++ def _IsValidChild(self, child):
++ return isinstance(child, EmitNode)
++
++class EmitNode(base.ContentNode):
++ ''' An <emit> element.'''
++
++ def DefaultAttributes(self):
++ return { 'emit_type' : 'prepend'}
++
++ def GetEmitType(self):
++ '''Returns the emit_type for this node. Default is 'append'.'''
++ return self.attrs['emit_type']
+diff --git a/tools/grit/grit/node/node_io_unittest.py b/tools/grit/grit/node/node_io_unittest.py
+new file mode 100644
+index 0000000000..1f45e51af8
+--- /dev/null
++++ b/tools/grit/grit/node/node_io_unittest.py
+@@ -0,0 +1,182 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for node_io.FileNode'''
++
++from __future__ import print_function
++
++import os
++import sys
++import unittest
++
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++from six import StringIO
++
++from grit.node import misc
++from grit.node import node_io
++from grit.node import empty
++from grit import grd_reader
++from grit import util
++
++
++def _GetAllCliques(root_node):
++ """Return all cliques in the |root_node| tree."""
++ ret = []
++ for node in root_node:
++ ret.extend(node.GetCliques())
++ return ret
++
++
++class FileNodeUnittest(unittest.TestCase):
++ def testGetPath(self):
++ root = misc.GritNode()
++ root.StartParsing(u'grit', None)
++ root.HandleAttribute(u'latest_public_release', u'0')
++ root.HandleAttribute(u'current_release', u'1')
++ root.HandleAttribute(u'base_dir', r'..\resource')
++ translations = empty.TranslationsNode()
++ translations.StartParsing(u'translations', root)
++ root.AddChild(translations)
++ file_node = node_io.FileNode()
++ file_node.StartParsing(u'file', translations)
++ file_node.HandleAttribute(u'path', r'flugel\kugel.pdf')
++ translations.AddChild(file_node)
++ root.EndParsing()
++
++ self.failUnless(root.ToRealPath(file_node.GetInputPath()) ==
++ util.normpath(
++ os.path.join(r'../resource', r'flugel/kugel.pdf')))
++
++ def VerifyCliquesContainEnglishAndFrenchAndNothingElse(self, cliques):
++ self.assertEqual(2, len(cliques))
++ for clique in cliques:
++ self.assertEqual({'en', 'fr'}, set(clique.clique.keys()))
++
++ def testLoadTranslations(self):
++ xml = '''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <translations>
++ <file path="generated_resources_fr.xtb" lang="fr" />
++ </translations>
++ <release seq="3">
++ <messages>
++ <message name="ID_HELLO">Hello!</message>
++ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
++ </messages>
++ </release>
++ </grit>'''
++ grd = grd_reader.Parse(StringIO(xml),
++ util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(_GetAllCliques(grd))
++
++ def testIffyness(self):
++ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <translations>
++ <if expr="lang == 'fr'">
++ <file path="generated_resources_fr.xtb" lang="fr" />
++ </if>
++ </translations>
++ <release seq="3">
++ <messages>
++ <message name="ID_HELLO">Hello!</message>
++ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
++ </messages>
++ </release>
++ </grit>'''), util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ cliques = _GetAllCliques(grd)
++ self.assertEqual(2, len(cliques))
++ for clique in cliques:
++ self.assertEqual({'en'}, set(clique.clique.keys()))
++
++ grd.SetOutputLanguage('fr')
++ grd.RunGatherers()
++ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(_GetAllCliques(grd))
++
++ def testConditionalLoadTranslations(self):
++ xml = '''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
++ base_dir=".">
++ <translations>
++ <if expr="True">
++ <file path="generated_resources_fr.xtb" lang="fr" />
++ </if>
++ <if expr="False">
++ <file path="no_such_file.xtb" lang="de" />
++ </if>
++ </translations>
++ <release seq="3">
++ <messages>
++ <message name="ID_HELLO">Hello!</message>
++ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
++ Joi</ex></ph></message>
++ </messages>
++ </release>
++ </grit>'''
++ grd = grd_reader.Parse(StringIO(xml),
++ util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(_GetAllCliques(grd))
++
++ def testConditionalOutput(self):
++ xml = '''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
++ base_dir=".">
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="en/generated_resources.rc" type="rc_all"
++ lang="en" />
++ <if expr="pp_if('NOT_TRUE')">
++ <output filename="de/generated_resources.rc" type="rc_all"
++ lang="de" />
++ </if>
++ </outputs>
++ <release seq="3">
++ <messages>
++ <message name="ID_HELLO">Hello!</message>
++ </messages>
++ </release>
++ </grit>'''
++ grd = grd_reader.Parse(StringIO(xml),
++ util.PathFromRoot('grit/test/data'),
++ defines={})
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ outputs = grd.GetChildrenOfType(node_io.OutputNode)
++ active = set(grd.ActiveDescendants())
++ self.failUnless(outputs[0] in active)
++ self.failUnless(outputs[0].GetType() == 'rc_header')
++ self.failUnless(outputs[1] in active)
++ self.failUnless(outputs[1].GetType() == 'rc_all')
++ self.failUnless(outputs[2] not in active)
++ self.failUnless(outputs[2].GetType() == 'rc_all')
++
++ # Verify that 'iw' and 'no' language codes in xtb files are mapped to 'he' and
++ # 'nb'.
++ def testLangCodeMapping(self):
++ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <translations>
++ <file path="generated_resources_no.xtb" lang="nb" />
++ <file path="generated_resources_iw.xtb" lang="he" />
++ </translations>
++ <release seq="3">
++ <messages></messages>
++ </release>
++ </grit>'''), util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ self.assertEqual([], _GetAllCliques(grd))
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/structure.py b/tools/grit/grit/node/structure.py
+new file mode 100644
+index 0000000000..ec170faebb
+--- /dev/null
++++ b/tools/grit/grit/node/structure.py
+@@ -0,0 +1,375 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The <structure> element.
++'''
++
++from __future__ import print_function
++
++import os
++import platform
++import re
++
++from grit import exception
++from grit import util
++from grit.node import base
++from grit.node import variant
++
++import grit.gather.admin_template
++import grit.gather.chrome_html
++import grit.gather.chrome_scaled_image
++import grit.gather.policy_json
++import grit.gather.rc
++import grit.gather.tr_html
++import grit.gather.txt
++
++import grit.format.rc
++
++# Type of the gatherer to use for each type attribute
++_GATHERERS = {
++ 'accelerators' : grit.gather.rc.Accelerators,
++ 'admin_template' : grit.gather.admin_template.AdmGatherer,
++ 'chrome_html' : grit.gather.chrome_html.ChromeHtml,
++ 'chrome_scaled_image' : grit.gather.chrome_scaled_image.ChromeScaledImage,
++ 'dialog' : grit.gather.rc.Dialog,
++ 'menu' : grit.gather.rc.Menu,
++ 'rcdata' : grit.gather.rc.RCData,
++ 'tr_html' : grit.gather.tr_html.TrHtml,
++ 'txt' : grit.gather.txt.TxtFile,
++ 'version' : grit.gather.rc.Version,
++ 'policy_template_metafile' : grit.gather.policy_json.PolicyJson,
++}
++
++
++# TODO(joi) Print a warning if the 'variant_of_revision' attribute indicates
++# that a skeleton variant is older than the original file.
++
++
++class StructureNode(base.Node):
++ '''A <structure> element.'''
++
++ # Regular expression for a local variable definition. Each definition
++ # is of the form NAME=VALUE, where NAME cannot contain '=' or ',' and
++ # VALUE must escape all commas: ',' -> ',,'. Each variable definition
++ # should be separated by a comma with no extra whitespace.
++ # Example: THING1=foo,THING2=bar
++ variable_pattern = re.compile(r'([^,=\s]+)=((?:,,|[^,])*)')
++
++ def __init__(self):
++ super(StructureNode, self).__init__()
++
++ # Keep track of the last filename we flattened to, so we can
++ # avoid doing it more than once.
++ self._last_flat_filename = None
++
++ # See _Substitute; this substituter is used for local variables and
++ # the root substituter is used for global variables.
++ self.substituter = None
++
++ def _IsValidChild(self, child):
++ return isinstance(child, variant.SkeletonNode)
++
++ def _ParseVariables(self, variables):
++ '''Parse a variable string into a dictionary.'''
++ matches = StructureNode.variable_pattern.findall(variables)
++ return dict((name, value.replace(',,', ',')) for name, value in matches)
++
++ def EndParsing(self):
++ super(StructureNode, self).EndParsing()
++
++ # Now that we have attributes and children, instantiate the gatherers.
++ gathertype = _GATHERERS[self.attrs['type']]
++
++ self.gatherer = gathertype(self.attrs['file'],
++ self.attrs['name'],
++ self.attrs['encoding'])
++ self.gatherer.SetGrdNode(self)
++ self.gatherer.SetUberClique(self.UberClique())
++ if hasattr(self.GetRoot(), 'defines'):
++ self.gatherer.SetDefines(self.GetRoot().defines)
++ self.gatherer.SetAttributes(self.attrs)
++ if self.ExpandVariables():
++ self.gatherer.SetFilenameExpansionFunction(self._Substitute)
++
++ # Parse local variables and instantiate the substituter.
++ if self.attrs['variables']:
++ variables = self.attrs['variables']
++ self.substituter = util.Substituter()
++ self.substituter.AddSubstitutions(self._ParseVariables(variables))
++
++ self.skeletons = {} # Maps expressions to skeleton gatherers
++ for child in self.children:
++ assert isinstance(child, variant.SkeletonNode)
++ skel = gathertype(child.attrs['file'],
++ self.attrs['name'],
++ child.GetEncodingToUse(),
++ is_skeleton=True)
++ skel.SetGrdNode(self) # TODO(benrg): Or child? Only used for ToRealPath
++ skel.SetUberClique(self.UberClique())
++ if hasattr(self.GetRoot(), 'defines'):
++ skel.SetDefines(self.GetRoot().defines)
++ if self.ExpandVariables():
++ skel.SetFilenameExpansionFunction(self._Substitute)
++ self.skeletons[child.attrs['expr']] = skel
++
++ def MandatoryAttributes(self):
++ return ['type', 'name', 'file']
++
++ def DefaultAttributes(self):
++ return {
++ 'encoding': 'cp1252',
++ 'exclude_from_rc': 'false',
++ 'line_end': 'unix',
++ 'output_encoding': 'utf-8',
++ 'generateid': 'true',
++ 'expand_variables': 'false',
++ 'output_filename': '',
++ 'fold_whitespace': 'false',
++ # Run an arbitrary command after translation is complete
++ # so that it doesn't interfere with what's in translation
++ # console.
++ 'run_command': '',
++ # Leave empty to run on all platforms, comma-separated
++ # for one or more specific platforms. Values must match
++ # output of platform.system().
++ 'run_command_on_platforms': '',
++ 'allowexternalscript': 'false',
++ # preprocess takes the same code path as flattenhtml, but it
++ # disables any processing/inlining outside of <if> and <include>.
++ 'preprocess': 'false',
++ 'flattenhtml': 'false',
++ 'fallback_to_low_resolution': 'default',
++ 'variables': '',
++ 'compress': 'default',
++ 'use_base_dir': 'true',
++ }
++
++ def IsExcludedFromRc(self):
++ return self.attrs['exclude_from_rc'] == 'true'
++
++ def Process(self, output_dir):
++ """Writes the processed data to output_dir. In the case of a chrome_html
++ structure this will add references to other scale factors. If flattening
++ this will also write file references to be base64 encoded data URLs. The
++ name of the new file is returned."""
++ filename = self.ToRealPath(self.GetInputPath())
++ flat_filename = os.path.join(output_dir,
++ self.attrs['name'] + '_' + os.path.basename(filename))
++
++ if self._last_flat_filename == flat_filename:
++ return
++
++ with open(flat_filename, 'wb') as outfile:
++ if self.ExpandVariables():
++ text = self.gatherer.GetText()
++ file_contents = self._Substitute(text)
++ else:
++ file_contents = self.gatherer.GetData('', 'utf-8')
++ outfile.write(file_contents.encode('utf-8'))
++
++ self._last_flat_filename = flat_filename
++ return os.path.basename(flat_filename)
++
++ def GetLineEnd(self):
++ '''Returns the end-of-line character or characters for files output because
++ of this node ('\r\n', '\n', or '\r' depending on the 'line_end' attribute).
++ '''
++ if self.attrs['line_end'] == 'unix':
++ return '\n'
++ elif self.attrs['line_end'] == 'windows':
++ return '\r\n'
++ elif self.attrs['line_end'] == 'mac':
++ return '\r'
++ else:
++ raise exception.UnexpectedAttribute(
++ "Attribute 'line_end' must be one of 'unix' (default), 'windows' or "
++ "'mac'")
++
++ def GetCliques(self):
++ return self.gatherer.GetCliques()
++
++ def GetDataPackValue(self, lang, encoding):
++ """Returns a bytes representation for a data_pack entry."""
++ if self.ExpandVariables():
++ text = self.gatherer.GetText()
++ data = util.Encode(self._Substitute(text), encoding)
++ else:
++ data = self.gatherer.GetData(lang, encoding)
++ if encoding != util.BINARY:
++ data = data.encode(encoding)
++ return self.CompressDataIfNeeded(data)
++
++ def GetHtmlResourceFilenames(self):
++ """Returns a set of all filenames inlined by this node."""
++ return self.gatherer.GetHtmlResourceFilenames()
++
++ def GetInputPath(self):
++ path = self.gatherer.GetInputPath()
++ if path is None:
++ return path
++
++ # Do not mess with absolute paths, that would make them invalid.
++ if os.path.isabs(os.path.expandvars(path)):
++ return path
++
++ # We have no control over code that calls ToRealPath later, so convert
++ # the path to be relative against our basedir.
++ if self.attrs.get('use_base_dir', 'true') != 'true':
++ # Normalize the directory path to use the appropriate OS separator.
++ # GetBaseDir() may return paths\like\this or paths/like/this, since it is
++ # read from the base_dir attribute in the grd file.
++ norm_base_dir = util.normpath(self.GetRoot().GetBaseDir())
++ return os.path.relpath(path, norm_base_dir)
++
++ return path
++
++ def GetTextualIds(self):
++ if not hasattr(self, 'gatherer'):
++ # This case is needed because this method is called by
++ # GritNode.ValidateUniqueIds before RunGatherers has been called.
++ # TODO(benrg): Fix this?
++ return [self.attrs['name']]
++ return self.gatherer.GetTextualIds()
++
++ def RunPreSubstitutionGatherer(self, debug=False):
++ if debug:
++ print('Running gatherer %s for file %s' %
++ (type(self.gatherer), self.GetInputPath()))
++
++ # Note: Parse() is idempotent, therefore this method is also.
++ self.gatherer.Parse()
++ for skel in self.skeletons.values():
++ skel.Parse()
++
++ def GetSkeletonGatherer(self):
++ '''Returns the gatherer for the alternate skeleton that should be used,
++ based on the expressions for selecting skeletons, or None if the skeleton
++ from the English version of the structure should be used.
++ '''
++ for expr in self.skeletons:
++ if self.EvaluateCondition(expr):
++ return self.skeletons[expr]
++ return None
++
++ def HasFileForLanguage(self):
++ return self.attrs['type'] in ['tr_html', 'admin_template', 'txt',
++ 'chrome_scaled_image',
++ 'chrome_html']
++
++ def ExpandVariables(self):
++ '''Variable expansion on structures is controlled by an XML attribute.
++
++ However, old files assume that expansion is always on for Rc files.
++
++ Returns:
++ A boolean.
++ '''
++ attrs = self.GetRoot().attrs
++ if 'grit_version' in attrs and attrs['grit_version'] > 1:
++ return self.attrs['expand_variables'] == 'true'
++ else:
++ return (self.attrs['expand_variables'] == 'true' or
++ self.attrs['file'].lower().endswith('.rc'))
++
++ def _Substitute(self, text):
++ '''Perform local and global variable substitution.'''
++ if self.substituter:
++ text = self.substituter.Substitute(text)
++ return self.GetRoot().GetSubstituter().Substitute(text)
++
++ def RunCommandOnCurrentPlatform(self):
++ if self.attrs['run_command_on_platforms'] == '':
++ return True
++ else:
++ target_platforms = self.attrs['run_command_on_platforms'].split(',')
++ return platform.system() in target_platforms
++
++ def FileForLanguage(self, lang, output_dir, create_file=True,
++ return_if_not_generated=True):
++ '''Returns the filename of the file associated with this structure,
++ for the specified language.
++
++ Args:
++ lang: 'fr'
++ output_dir: 'c:\temp'
++ create_file: True
++ '''
++ assert self.HasFileForLanguage()
++ # If the source language is requested, and no extra changes are requested,
++ # use the existing file.
++ if ((not lang or lang == self.GetRoot().GetSourceLanguage()) and
++ self.attrs['expand_variables'] != 'true' and
++ (not self.attrs['run_command'] or
++ not self.RunCommandOnCurrentPlatform())):
++ if return_if_not_generated:
++ input_path = self.GetInputPath()
++ if input_path is None:
++ return None
++ return self.ToRealPath(input_path)
++ else:
++ return None
++
++ if self.attrs['output_filename'] != '':
++ filename = self.attrs['output_filename']
++ else:
++ filename = os.path.basename(self.attrs['file'])
++ assert len(filename)
++ filename = '%s_%s' % (lang, filename)
++ filename = os.path.join(output_dir, filename)
++
++ # Only create the output if it was requested by the call.
++ if create_file:
++ text = self.gatherer.Translate(
++ lang,
++ pseudo_if_not_available=self.PseudoIsAllowed(),
++ fallback_to_english=self.ShouldFallbackToEnglish(),
++ skeleton_gatherer=self.GetSkeletonGatherer())
++
++ file_contents = util.FixLineEnd(text, self.GetLineEnd())
++ if self.ExpandVariables():
++ # Note that we reapply substitution a second time here.
++ # This is because a) we need to look inside placeholders
++ # b) the substitution values are language-dependent
++ file_contents = self._Substitute(file_contents)
++
++ with open(filename, 'wb') as file_object:
++ output_stream = util.WrapOutputStream(file_object,
++ self.attrs['output_encoding'])
++ output_stream.write(file_contents)
++
++ if self.attrs['run_command'] and self.RunCommandOnCurrentPlatform():
++ # Run arbitrary commands after translation is complete so that it
++ # doesn't interfere with what's in translation console.
++ command = self.attrs['run_command'] % {'filename': filename}
++ result = os.system(command)
++ assert result == 0, '"%s" failed.' % command
++
++ return filename
++
++ def IsResourceMapSource(self):
++ return True
++
++ @staticmethod
++ def Construct(parent, name, type, file, encoding='cp1252'):
++ '''Creates a new node which is a child of 'parent', with attributes set
++ by parameters of the same name.
++ '''
++ node = StructureNode()
++ node.StartParsing('structure', parent)
++ node.HandleAttribute('name', name)
++ node.HandleAttribute('type', type)
++ node.HandleAttribute('file', file)
++ node.HandleAttribute('encoding', encoding)
++ node.EndParsing()
++ return node
++
++ def SubstituteMessages(self, substituter):
++ '''Propagates substitution to gatherer.
++
++ Args:
++ substituter: a grit.util.Substituter object.
++ '''
++ assert hasattr(self, 'gatherer')
++ if self.ExpandVariables():
++ self.gatherer.SubstituteMessages(substituter)
+diff --git a/tools/grit/grit/node/structure_unittest.py b/tools/grit/grit/node/structure_unittest.py
+new file mode 100644
+index 0000000000..0e66dce37a
+--- /dev/null
++++ b/tools/grit/grit/node/structure_unittest.py
+@@ -0,0 +1,178 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for <structure> nodes.
++'''
++
++from __future__ import print_function
++
++import os
++import os.path
++import sys
++import zlib
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import platform
++import tempfile
++import unittest
++import struct
++
++from grit import constants
++from grit import util
++from grit.node import brotli_util
++from grit.node import structure
++from grit.format import rc
++
++
++def checkIsGzipped(filename, compress_attr):
++ test_data_root = util.PathFromRoot('grit/testdata')
++ root = util.ParseGrdForUnittest(
++ '''
++ <structures>
++ <structure name="TEST_TXT" file="%s" %s type="chrome_html"/>
++ </structures>''' % (filename, compress_attr),
++ base_dir=test_data_root)
++ node, = root.GetChildrenOfType(structure.StructureNode)
++ node.RunPreSubstitutionGatherer()
++ compressed = node.GetDataPackValue(lang='en', encoding=util.BINARY)
++
++ decompressed_data = zlib.decompress(compressed, 16 + zlib.MAX_WBITS)
++ expected = util.ReadFile(os.path.join(test_data_root, filename), util.BINARY)
++ return expected == decompressed_data
++
++
++class StructureUnittest(unittest.TestCase):
++ def testSkeleton(self):
++ grd = util.ParseGrdForUnittest('''
++ <structures>
++ <structure type="dialog" name="IDD_ABOUTBOX" file="klonk.rc" encoding="utf-16-le">
++ <skeleton expr="lang == 'fr'" variant_of_revision="1" file="klonk-alternate-skeleton.rc" />
++ </structure>
++ </structures>''', base_dir=util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('fr')
++ grd.RunGatherers()
++ transl = ''.join(rc.Format(grd, 'fr', '.'))
++ self.failUnless(transl.count('040704') and transl.count('110978'))
++ self.failUnless(transl.count('2005",IDC_STATIC'))
++
++ def testRunCommandOnCurrentPlatform(self):
++ node = structure.StructureNode()
++ node.attrs = node.DefaultAttributes()
++ self.failUnless(node.RunCommandOnCurrentPlatform())
++ node.attrs['run_command_on_platforms'] = 'Nosuch'
++ self.failIf(node.RunCommandOnCurrentPlatform())
++ node.attrs['run_command_on_platforms'] = (
++ 'Nosuch,%s,Othernot' % platform.system())
++ self.failUnless(node.RunCommandOnCurrentPlatform())
++
++ def testVariables(self):
++ grd = util.ParseGrdForUnittest('''
++ <structures>
++ <structure type="chrome_html" name="hello_tmpl" file="structure_variables.html" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true"></structure>
++ </structures>''', base_dir=util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ node, = grd.GetChildrenOfType(structure.StructureNode)
++ filename = node.Process(tempfile.gettempdir())
++ filepath = os.path.join(tempfile.gettempdir(), filename)
++ with open(filepath) as f:
++ result = f.read()
++ self.failUnlessEqual(('<h1>Hello!</h1>\n'
++ 'Some cool things are foo, bar, baz.\n'
++ 'Did you know that 2+2==4?\n'
++ '<p>\n'
++ ' Hello!\n'
++ '</p>\n'), result)
++ os.remove(filepath)
++
++ def testGetPath(self):
++ base_dir = util.PathFromRoot('grit/testdata')
++ grd = util.ParseGrdForUnittest('''
++ <structures>
++ <structure type="chrome_html" name="hello_tmpl" file="structure_variables.html" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true" use_base_dir="true"></structure>
++ </structures>''', base_dir)
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ node, = grd.GetChildrenOfType(structure.StructureNode)
++ self.assertEqual(grd.ToRealPath(node.GetInputPath()),
++ os.path.abspath(os.path.join(
++ base_dir, r'structure_variables.html')))
++
++ def testGetPathNoBasedir(self):
++ base_dir = util.PathFromRoot('grit/testdata')
++ abs_path = os.path.join(base_dir, r'structure_variables.html')
++ rel_path = os.path.relpath(abs_path, os.getcwd())
++ grd = util.ParseGrdForUnittest('''
++ <structures>
++ <structure type="chrome_html" name="hello_tmpl" file="''' + rel_path + '''" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true" use_base_dir="false"></structure>
++ </structures>''', util.PathFromRoot('grit/testdata'))
++ grd.SetOutputLanguage('en')
++ grd.RunGatherers()
++ node, = grd.GetChildrenOfType(structure.StructureNode)
++ self.assertEqual(grd.ToRealPath(node.GetInputPath()),
++ os.path.abspath(os.path.join(
++ base_dir, r'structure_variables.html')))
++
++ def testCompressGzip(self):
++ self.assertTrue(checkIsGzipped('test_text.txt', 'compress="gzip"'))
++
++ def testCompressGzipByDefault(self):
++ self.assertTrue(checkIsGzipped('test_html.html', ''))
++ self.assertTrue(checkIsGzipped('test_js.js', ''))
++ self.assertTrue(checkIsGzipped('test_css.css', ''))
++ self.assertTrue(checkIsGzipped('test_svg.svg', ''))
++
++ self.assertTrue(checkIsGzipped('test_html.html', 'compress="default"'))
++ self.assertTrue(checkIsGzipped('test_js.js', 'compress="default"'))
++ self.assertTrue(checkIsGzipped('test_css.css', 'compress="default"'))
++ self.assertTrue(checkIsGzipped('test_svg.svg', 'compress="default"'))
++
++ def testCompressBrotli(self):
++ test_data_root = util.PathFromRoot('grit/testdata')
++ root = util.ParseGrdForUnittest(
++ '''
++ <structures>
++ <structure name="TEST_TXT" file="test_text.txt"
++ compress="brotli" type="chrome_html" />
++ </structures>''',
++ base_dir=test_data_root)
++ node, = root.GetChildrenOfType(structure.StructureNode)
++ node.RunPreSubstitutionGatherer()
++
++ # Using the mock brotli decompression executable.
++ brotli_util.SetBrotliCommand([sys.executable,
++ os.path.join(os.path.dirname(__file__),
++ 'mock_brotli.py')])
++ compressed = node.GetDataPackValue(lang='en', encoding=util.BINARY)
++ # Assert that the first two bytes in compressed format is BROTLI_CONST.
++ self.assertEqual(constants.BROTLI_CONST, compressed[0:2])
++
++ # Compare the actual size of the uncompressed test data with
++ # the size appended during compression.
++ actual_size = len(util.ReadFile(
++ os.path.join(test_data_root, 'test_text.txt'), util.BINARY))
++ uncompress_size = struct.unpack('<i', compressed[2:6])[0]
++ uncompress_size += struct.unpack('<h', compressed[6:8])[0] << 4*8
++ self.assertEqual(actual_size, uncompress_size)
++
++ self.assertEqual(b'This has been mock compressed!', compressed[8:])
++
++ def testNotCompressed(self):
++ test_data_root = util.PathFromRoot('grit/testdata')
++ root = util.ParseGrdForUnittest('''
++ <structures>
++ <structure name="TEST_TXT" file="test_text.txt" type="chrome_html" />
++ </structures>''', base_dir=test_data_root)
++ node, = root.GetChildrenOfType(structure.StructureNode)
++ node.RunPreSubstitutionGatherer()
++ data = node.GetDataPackValue(lang='en', encoding=util.BINARY)
++
++ self.assertEqual(util.ReadFile(
++ os.path.join(test_data_root, 'test_text.txt'), util.BINARY), data)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/node/variant.py b/tools/grit/grit/node/variant.py
+new file mode 100644
+index 0000000000..9f5845f954
+--- /dev/null
++++ b/tools/grit/grit/node/variant.py
+@@ -0,0 +1,41 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The <skeleton> element.
++'''
++
++from __future__ import print_function
++
++from grit.node import base
++
++
++class SkeletonNode(base.Node):
++ '''A <skeleton> element.'''
++
++ # TODO(joi) Support inline skeleton variants as CDATA instead of requiring
++ # a 'file' attribute.
++
++ def MandatoryAttributes(self):
++ return ['expr', 'variant_of_revision', 'file']
++
++ def DefaultAttributes(self):
++ '''If not specified, 'encoding' will actually default to the parent node's
++ encoding.
++ '''
++ return {'encoding' : ''}
++
++ def _ContentType(self):
++ if 'file' in self.attrs:
++ return self._CONTENT_TYPE_NONE
++ else:
++ return self._CONTENT_TYPE_CDATA
++
++ def GetEncodingToUse(self):
++ if self.attrs['encoding'] == '':
++ return self.parent.attrs['encoding']
++ else:
++ return self.attrs['encoding']
++
++ def GetInputPath(self):
++ return self.attrs['file']
+diff --git a/tools/grit/grit/pseudo.py b/tools/grit/grit/pseudo.py
+new file mode 100644
+index 0000000000..b607bfc6bb
+--- /dev/null
++++ b/tools/grit/grit/pseudo.py
+@@ -0,0 +1,129 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Pseudotranslation support. Our pseudotranslations are based on the
++P-language, which is a simple vowel-extending language. Examples of P:
++ - "hello" becomes "hepellopo"
++ - "howdie" becomes "hopowdiepie"
++ - "because" becomes "bepecaupause" (but in our implementation we don't
++ handle the silent e at the end so it actually would return "bepecaupausepe"
++
++The P-language has the excellent quality of increasing the length of text
++by around 30-50% which is great for pseudotranslations, to stress test any
++GUI layouts etc.
++
++To make the pseudotranslations more obviously "not a translation" and to make
++them exercise any code that deals with encodings, we also transform all English
++vowels into equivalent vowels with diacriticals on them (rings, acutes,
++diaresis, and circumflex), and we write the "p" in the P-language as a Hebrew
++character Qof. It looks sort of like a latin character "p" but it is outside
++the latin-1 character set which will stress character encoding bugs.
++'''
++
++from __future__ import print_function
++
++from grit import lazy_re
++from grit import tclib
++
++
++# An RFC language code for the P pseudolanguage.
++PSEUDO_LANG = 'x-P-pseudo'
++
++# Hebrew character Qof. It looks kind of like a 'p' but is outside
++# the latin-1 character set which is good for our purposes.
++# TODO(joi) For now using P instead of Qof, because of some bugs it used. Find
++# a better solution, i.e. one that introduces a non-latin1 character into the
++# pseudotranslation.
++#_QOF = u'\u05e7'
++_QOF = u'P'
++
++# How we map each vowel.
++_VOWELS = {
++ u'a' : u'\u00e5', # a with ring
++ u'e' : u'\u00e9', # e acute
++ u'i' : u'\u00ef', # i diaresis
++ u'o' : u'\u00f4', # o circumflex
++ u'u' : u'\u00fc', # u diaresis
++ u'y' : u'\u00fd', # y acute
++ u'A' : u'\u00c5', # A with ring
++ u'E' : u'\u00c9', # E acute
++ u'I' : u'\u00cf', # I diaresis
++ u'O' : u'\u00d4', # O circumflex
++ u'U' : u'\u00dc', # U diaresis
++ u'Y' : u'\u00dd', # Y acute
++}
++_VOWELS_KEYS = set(_VOWELS.keys())
++
++# Matches vowels and P
++_PSUB_RE = lazy_re.compile("(%s)" % '|'.join(_VOWELS_KEYS | {'P'}))
++
++
++# Pseudotranslations previously created. This is important for performance
++# reasons, especially since we routinely pseudotranslate the whole project
++# several or many different times for each build.
++_existing_translations = {}
++
++
++def MapVowels(str, also_p = False):
++ '''Returns a copy of 'str' where characters that exist as keys in _VOWELS
++ have been replaced with the corresponding value. If also_p is true, this
++ function will also change capital P characters into a Hebrew character Qof.
++ '''
++ def Repl(match):
++ if match.group() == 'p':
++ if also_p:
++ return _QOF
++ else:
++ return 'p'
++ else:
++ return _VOWELS[match.group()]
++ return _PSUB_RE.sub(Repl, str)
++
++
++def PseudoString(str):
++ '''Returns a pseudotranslation of the provided string, in our enhanced
++ P-language.'''
++ if str in _existing_translations:
++ return _existing_translations[str]
++
++ outstr = u''
++ ix = 0
++ while ix < len(str):
++ if str[ix] not in _VOWELS_KEYS:
++ outstr += str[ix]
++ ix += 1
++ else:
++ # We want to treat consecutive vowels as one composite vowel. This is not
++ # always accurate e.g. in composite words but good enough.
++ consecutive_vowels = u''
++ while ix < len(str) and str[ix] in _VOWELS_KEYS:
++ consecutive_vowels += str[ix]
++ ix += 1
++ changed_vowels = MapVowels(consecutive_vowels)
++ outstr += changed_vowels
++ outstr += _QOF
++ outstr += changed_vowels
++
++ _existing_translations[str] = outstr
++ return outstr
++
++
++def PseudoMessage(message):
++ '''Returns a pseudotranslation of the provided message.
++
++ Args:
++ message: tclib.Message()
++
++ Return:
++ tclib.Translation()
++ '''
++ transl = tclib.Translation()
++
++ for part in message.GetContent():
++ if isinstance(part, tclib.Placeholder):
++ transl.AppendPlaceholder(part)
++ else:
++ transl.AppendText(PseudoString(part))
++
++ return transl
+diff --git a/tools/grit/grit/pseudo_rtl.py b/tools/grit/grit/pseudo_rtl.py
+new file mode 100644
+index 0000000000..2240b571de
+--- /dev/null
++++ b/tools/grit/grit/pseudo_rtl.py
+@@ -0,0 +1,104 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Pseudo RTL, (aka Fake Bidi) support. It simply wraps each word with
++Unicode RTL overrides.
++More info at https://sites.google.com/a/chromium.org/dev/Home/fake-bidi
++'''
++
++from __future__ import print_function
++
++import re
++
++from grit import lazy_re
++from grit import tclib
++
++ACCENTED_STRINGS = {
++ 'a': u"\u00e5", 'e': u"\u00e9", 'i': u"\u00ee", 'o': u"\u00f6",
++ 'u': u"\u00fb", 'A': u"\u00c5", 'E': u"\u00c9", 'I': u"\u00ce",
++ 'O': u"\u00d6", 'U': u"\u00db", 'c': u"\u00e7", 'd': u"\u00f0",
++ 'n': u"\u00f1", 'p': u"\u00fe", 'y': u"\u00fd", 'C': u"\u00c7",
++ 'D': u"\u00d0", 'N': u"\u00d1", 'P': u"\u00de", 'Y': u"\u00dd",
++ 'f': u"\u0192", 's': u"\u0161", 'S': u"\u0160", 'z': u"\u017e",
++ 'Z': u"\u017d", 'g': u"\u011d", 'G': u"\u011c", 'h': u"\u0125",
++ 'H': u"\u0124", 'j': u"\u0135", 'J': u"\u0134", 'k': u"\u0137",
++ 'K': u"\u0136", 'l': u"\u013c", 'L': u"\u013b", 't': u"\u0163",
++ 'T': u"\u0162", 'w': u"\u0175", 'W': u"\u0174",
++ '$': u"\u20ac", '?': u"\u00bf", 'R': u"\u00ae", r'!': u"\u00a1",
++}
++
++# a character set containing the keys in ACCENTED_STRINGS
++# We should not accent characters in an escape sequence such as "\n".
++# To be safe, we assume every character following a backslash is an escaped
++# character. We also need to consider the case like "\\n", which means
++# a blackslash and a character "n", we will accent the character "n".
++TO_ACCENT = lazy_re.compile(
++ r'[%s]|\\[a-z\\]' % ''.join(ACCENTED_STRINGS.keys()))
++
++# Lex text so that we don't interfere with html tokens and entities.
++# This lexing scheme will handle all well formed tags and entities, html or
++# xhtml. It will not handle comments, CDATA sections, or the unescaping tags:
++# script, style, xmp or listing. If any of those appear in messages,
++# something is wrong.
++TOKENS = [ lazy_re.compile(
++ '^%s' % pattern, # match at the beginning of input
++ re.I | re.S # html tokens are case-insensitive
++ )
++ for pattern in
++ (
++ # a run of non html special characters
++ r'[^<&]+',
++ # a tag
++ (r'</?[a-z]\w*' # beginning of tag
++ r'(?:\s+\w+(?:\s*=\s*' # attribute start
++ r'(?:[^\s"\'>]+|"[^\"]*"|\'[^\']*\'))?' # attribute value
++ r')*\s*/?>'),
++ # an entity
++ r'&(?:[a-z]\w+|#\d+|#x[\da-f]+);',
++ # an html special character not part of a special sequence
++ r'.'
++ ) ]
++
++ALPHABETIC_RUN = lazy_re.compile(r'([^\W0-9_]+)')
++
++RLO = u'\u202e'
++PDF = u'\u202c'
++
++def PseudoRTLString(text):
++ '''Returns a fake bidirectional version of the source string. This code is
++ based on accentString above, in turn copied from Frank Tang.
++ '''
++ parts = []
++ while text:
++ m = None
++ for token in TOKENS:
++ m = token.search(text)
++ if m:
++ part = m.group(0)
++ text = text[len(part):]
++ if part[0] not in ('<', '&'):
++ # not a tag or entity, so accent
++ part = ALPHABETIC_RUN.sub(lambda run: RLO + run.group() + PDF, part)
++ parts.append(part)
++ break
++ return ''.join(parts)
++
++
++def PseudoRTLMessage(message):
++ '''Returns a pseudo-RTL (aka Fake-Bidi) translation of the provided message.
++
++ Args:
++ message: tclib.Message()
++
++ Return:
++ tclib.Translation()
++ '''
++ transl = tclib.Translation()
++ for part in message.GetContent():
++ if isinstance(part, tclib.Placeholder):
++ transl.AppendPlaceholder(part)
++ else:
++ transl.AppendText(PseudoRTLString(part))
++
++ return transl
+diff --git a/tools/grit/grit/pseudo_unittest.py b/tools/grit/grit/pseudo_unittest.py
+new file mode 100644
+index 0000000000..b1d53ff401
+--- /dev/null
++++ b/tools/grit/grit/pseudo_unittest.py
+@@ -0,0 +1,55 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.pseudo'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import unittest
++
++from grit import pseudo
++from grit import tclib
++
++
++class PseudoUnittest(unittest.TestCase):
++ def testVowelMapping(self):
++ self.failUnless(pseudo.MapVowels('abebibobuby') ==
++ u'\u00e5b\u00e9b\u00efb\u00f4b\u00fcb\u00fd')
++ self.failUnless(pseudo.MapVowels('ABEBIBOBUBY') ==
++ u'\u00c5B\u00c9B\u00cfB\u00d4B\u00dcB\u00dd')
++
++ def testPseudoString(self):
++ out = pseudo.PseudoString('hello')
++ self.failUnless(out == pseudo.MapVowels(u'hePelloPo', True))
++
++ def testConsecutiveVowels(self):
++ out = pseudo.PseudoString("beautiful weather, ain't it?")
++ self.failUnless(out == pseudo.MapVowels(
++ u"beauPeautiPifuPul weaPeathePer, aiPain't iPit?", 1))
++
++ def testCapitals(self):
++ out = pseudo.PseudoString("HOWDIE DOODIE, DR. JONES")
++ self.failUnless(out == pseudo.MapVowels(
++ u"HOPOWDIEPIE DOOPOODIEPIE, DR. JOPONEPES", 1))
++
++ def testPseudoMessage(self):
++ msg = tclib.Message(text='Hello USERNAME, how are you?',
++ placeholders=[
++ tclib.Placeholder('USERNAME', '%s', 'Joi')])
++ trans = pseudo.PseudoMessage(msg)
++ # TODO(joi) It would be nicer if 'you' -> 'youPou' instead of
++ # 'you' -> 'youPyou' and if we handled the silent e in 'are'
++ self.failUnless(trans.GetPresentableContent() ==
++ pseudo.MapVowels(
++ u'HePelloPo USERNAME, hoPow aParePe youPyou?', 1))
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/shortcuts.py b/tools/grit/grit/shortcuts.py
+new file mode 100644
+index 0000000000..0db2ce436c
+--- /dev/null
++++ b/tools/grit/grit/shortcuts.py
+@@ -0,0 +1,93 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Stuff to prevent conflicting shortcuts.
++'''
++
++from __future__ import print_function
++
++from grit import lazy_re
++
++
++class ShortcutGroup(object):
++ '''Manages a list of cliques that belong together in a single shortcut
++ group. Knows how to detect conflicting shortcut keys.
++ '''
++
++ # Matches shortcut keys, e.g. &J
++ SHORTCUT_RE = lazy_re.compile('([^&]|^)(&[A-Za-z])')
++
++ def __init__(self, name):
++ self.name = name
++ # Map of language codes to shortcut keys used (which is a map of
++ # shortcut keys to counts).
++ self.keys_by_lang = {}
++ # List of cliques in this group
++ self.cliques = []
++
++ def AddClique(self, c):
++ for existing_clique in self.cliques:
++ if existing_clique.GetId() == c.GetId():
++ # This happens e.g. when we have e.g.
++ # <if expr1><structure 1></if> <if expr2><structure 2></if>
++ # where only one will really be included in the output.
++ return
++
++ self.cliques.append(c)
++ for (lang, msg) in c.clique.items():
++ if lang not in self.keys_by_lang:
++ self.keys_by_lang[lang] = {}
++ keymap = self.keys_by_lang[lang]
++
++ content = msg.GetRealContent()
++ keys = [groups[1] for groups in self.SHORTCUT_RE.findall(content)]
++ for key in keys:
++ key = key.upper()
++ if key in keymap:
++ keymap[key] += 1
++ else:
++ keymap[key] = 1
++
++ def GenerateWarnings(self, tc_project):
++ # For any language that has more than one occurrence of any shortcut,
++ # make a list of the conflicting shortcuts.
++ problem_langs = {}
++ for (lang, keys) in self.keys_by_lang.items():
++ for (key, count) in keys.items():
++ if count > 1:
++ if lang not in problem_langs:
++ problem_langs[lang] = []
++ problem_langs[lang].append(key)
++
++ warnings = []
++ if len(problem_langs):
++ warnings.append("WARNING - duplicate keys exist in shortcut group %s" %
++ self.name)
++ for (lang,keys) in problem_langs.items():
++ warnings.append(" %6s duplicates: %s" % (lang, ', '.join(keys)))
++ return warnings
++
++
++def GenerateDuplicateShortcutsWarnings(uberclique, tc_project):
++ '''Given an UberClique and a project name, will print out helpful warnings
++ if there are conflicting shortcuts within shortcut groups in the provided
++ UberClique.
++
++ Args:
++ uberclique: clique.UberClique()
++ tc_project: 'MyProjectNameInTheTranslationConsole'
++
++ Returns:
++ ['warning line 1', 'warning line 2', ...]
++ '''
++ warnings = []
++ groups = {}
++ for c in uberclique.AllCliques():
++ for group in c.shortcut_groups:
++ if group not in groups:
++ groups[group] = ShortcutGroup(group)
++ groups[group].AddClique(c)
++ for group in groups.values():
++ warnings += group.GenerateWarnings(tc_project)
++ return warnings
+diff --git a/tools/grit/grit/shortcuts_unittest.py b/tools/grit/grit/shortcuts_unittest.py
+new file mode 100644
+index 0000000000..30e7c4f758
+--- /dev/null
++++ b/tools/grit/grit/shortcuts_unittest.py
+@@ -0,0 +1,79 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.shortcuts
++'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import unittest
++
++from six import StringIO
++
++from grit import shortcuts
++from grit import clique
++from grit import tclib
++from grit.gather import rc
++
++class ShortcutsUnittest(unittest.TestCase):
++
++ def setUp(self):
++ self.uq = clique.UberClique()
++
++ def testFunctionality(self):
++ c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
++ c.AddToShortcutGroup('group_name')
++ c = self.uq.MakeClique(tclib.Message(text="Howdie &there partner"))
++ c.AddToShortcutGroup('group_name')
++
++ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
++ self.failUnless(warnings)
++
++ def testAmpersandEscaping(self):
++ c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
++ c.AddToShortcutGroup('group_name')
++ c = self.uq.MakeClique(tclib.Message(text="S&&T are the &letters S and T"))
++ c.AddToShortcutGroup('group_name')
++
++ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
++ self.failUnless(len(warnings) == 0)
++
++ def testDialog(self):
++ dlg = rc.Dialog(StringIO('''\
++IDD_SIDEBAR_RSS_PANEL_PROPPAGE DIALOGEX 0, 0, 239, 221
++STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
++FONT 8, "MS Shell Dlg", 400, 0, 0x1
++BEGIN
++ PUSHBUTTON "Add &URL",IDC_SIDEBAR_RSS_ADD_URL,182,53,57,14
++ EDITTEXT IDC_SIDEBAR_RSS_NEW_URL,0,53,178,15,ES_AUTOHSCROLL
++ PUSHBUTTON "&Remove",IDC_SIDEBAR_RSS_REMOVE,183,200,56,14
++ PUSHBUTTON "&Edit",IDC_SIDEBAR_RSS_EDIT,123,200,56,14
++ CONTROL "&Automatically add commonly viewed clips",
++ IDC_SIDEBAR_RSS_AUTO_ADD,"Button",BS_AUTOCHECKBOX |
++ BS_MULTILINE | WS_TABSTOP,0,200,120,17
++ PUSHBUTTON "",IDC_SIDEBAR_RSS_HIDDEN,179,208,6,6,NOT WS_VISIBLE
++ LTEXT "You can display clips from blogs, news sites, and other online sources.",
++ IDC_STATIC,0,0,239,10
++ LISTBOX IDC_SIDEBAR_DISPLAYED_FEED_LIST,0,69,239,127,LBS_SORT |
++ LBS_OWNERDRAWFIXED | LBS_HASSTRINGS |
++ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL |
++ WS_TABSTOP
++ LTEXT "Add a clip from a recently viewed website by clicking Add Recent Clips.",
++ IDC_STATIC,0,13,141,19
++ LTEXT "Or, if you know a site supports RSS or Atom, you can enter the RSS or Atom URL below and add it to your list of Web Clips.",
++ IDC_STATIC,0,33,239,18
++ PUSHBUTTON "Add Recent &Clips (10)...",
++ IDC_SIDEBAR_RSS_ADD_RECENT_CLIPS,146,14,93,14
++END'''), 'IDD_SIDEBAR_RSS_PANEL_PROPPAGE')
++ dlg.SetUberClique(self.uq)
++ dlg.Parse()
++
++ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
++ self.failUnless(len(warnings) == 0)
++
+diff --git a/tools/grit/grit/tclib.py b/tools/grit/grit/tclib.py
+new file mode 100644
+index 0000000000..27ba366924
+--- /dev/null
++++ b/tools/grit/grit/tclib.py
+@@ -0,0 +1,246 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Adaptation of the extern.tclib classes for our needs.
++'''
++
++from __future__ import print_function
++
++import functools
++import re
++
++import six
++
++from grit import exception
++from grit import lazy_re
++import grit.extern.tclib
++
++
++# Matches whitespace sequences which can be folded into a single whitespace
++# character. This matches single characters so that non-spaces are replaced
++# with spaces.
++_FOLD_WHITESPACE = re.compile(r'\s+')
++
++# Caches compiled regexp used to split tags in BaseMessage.__init__()
++_RE_CACHE = {}
++
++def Identity(i):
++ return i
++
++
++class BaseMessage(object):
++ '''Base class with methods shared by Message and Translation.
++ '''
++
++ def __init__(self, text='', placeholders=[], description='', meaning=''):
++ self.parts = []
++ self.placeholders = []
++ self.meaning = meaning
++ self.dirty = True # True if self.id is (or might be) wrong
++ self.id = 0
++ self.SetDescription(description)
++
++ if text != '':
++ if not placeholders or placeholders == []:
++ self.AppendText(text)
++ else:
++ tag_map = {}
++ for placeholder in placeholders:
++ tag_map[placeholder.GetPresentation()] = [placeholder, 0]
++ # This creates a regexp like '(TAG1|TAG2|TAG3)'.
++ # The tags have to be sorted in order of decreasing length, so that
++ # longer tags are substituted before shorter tags that happen to be
++ # substrings of the longer tag.
++ # E.g. "EXAMPLE_FOO_NAME" must be matched before "EXAMPLE_FOO",
++ # otherwise "EXAMPLE_FOO" splits "EXAMPLE_FOO_NAME" too.
++ tags = sorted(tag_map.keys(),
++ key=functools.cmp_to_key(
++ lambda x, y: len(x) - len(y) or ((x > y) - (x < y))),
++ reverse=True)
++ tag_re = '(' + '|'.join(tags) + ')'
++
++ # This caching improves the time to build
++ # chrome/app:generated_resources from 21.562s to 17.672s on Linux.
++ compiled_re = _RE_CACHE.get(tag_re, None)
++ if compiled_re is None:
++ compiled_re = re.compile(tag_re)
++ _RE_CACHE[tag_re] = compiled_re
++
++ chunked_text = compiled_re.split(text)
++
++ for chunk in chunked_text:
++ if chunk: # ignore empty chunk
++ if chunk in tag_map:
++ self.AppendPlaceholder(tag_map[chunk][0])
++ tag_map[chunk][1] += 1 # increase placeholder use count
++ else:
++ self.AppendText(chunk)
++ for key in tag_map:
++ assert tag_map[key][1] != 0
++
++ def GetRealContent(self, escaping_function=Identity):
++ '''Returns the original content, i.e. what your application and users
++ will see.
++
++ Specify a function to escape each translateable bit, if you like.
++ '''
++ bits = []
++ for item in self.parts:
++ if isinstance(item, six.string_types):
++ bits.append(escaping_function(item))
++ else:
++ bits.append(item.GetOriginal())
++ return ''.join(bits)
++
++ def GetPresentableContent(self):
++ presentable_content = []
++ for part in self.parts:
++ if isinstance(part, Placeholder):
++ presentable_content.append(part.GetPresentation())
++ else:
++ presentable_content.append(part)
++ return ''.join(presentable_content)
++
++ def AppendPlaceholder(self, placeholder):
++ assert isinstance(placeholder, Placeholder)
++ dup = False
++ for other in self.GetPlaceholders():
++ if other.presentation == placeholder.presentation:
++ assert other.original == placeholder.original
++ dup = True
++
++ if not dup:
++ self.placeholders.append(placeholder)
++ self.parts.append(placeholder)
++ self.dirty = True
++
++ def AppendText(self, text):
++ assert isinstance(text, six.string_types)
++ assert text != ''
++
++ self.parts.append(text)
++ self.dirty = True
++
++ def GetContent(self):
++ '''Returns the parts of the message. You may modify parts if you wish.
++ Note that you must not call GetId() on this object until you have finished
++ modifying the contents.
++ '''
++ self.dirty = True # user might modify content
++ return self.parts
++
++ def GetDescription(self):
++ return self.description
++
++ def SetDescription(self, description):
++ self.description = _FOLD_WHITESPACE.sub(' ', description)
++
++ def GetMeaning(self):
++ return self.meaning
++
++ def GetId(self):
++ if self.dirty:
++ self.id = self.GenerateId()
++ self.dirty = False
++ return self.id
++
++ def GenerateId(self):
++ return grit.extern.tclib.GenerateMessageId(self.GetPresentableContent(),
++ self.meaning)
++
++ def GetPlaceholders(self):
++ return self.placeholders
++
++ def FillTclibBaseMessage(self, msg):
++ msg.SetDescription(self.description.encode('utf-8'))
++
++ for part in self.parts:
++ if isinstance(part, Placeholder):
++ ph = grit.extern.tclib.Placeholder(
++ part.presentation.encode('utf-8'),
++ part.original.encode('utf-8'),
++ part.example.encode('utf-8'))
++ msg.AppendPlaceholder(ph)
++ else:
++ msg.AppendText(part.encode('utf-8'))
++
++
++class Message(BaseMessage):
++ '''A message.'''
++
++ def __init__(self, text='', placeholders=[], description='', meaning='',
++ assigned_id=None):
++ super(Message, self).__init__(text, placeholders, description, meaning)
++ self.assigned_id = assigned_id
++
++ def ToTclibMessage(self):
++ msg = grit.extern.tclib.Message('utf-8', meaning=self.meaning)
++ self.FillTclibBaseMessage(msg)
++ return msg
++
++ def GetId(self):
++ '''Use the assigned id if we have one.'''
++ if self.assigned_id:
++ return self.assigned_id
++
++ return super(Message, self).GetId()
++
++ def HasAssignedId(self):
++ '''Returns True if this message has an assigned id.'''
++ return bool(self.assigned_id)
++
++
++class Translation(BaseMessage):
++ '''A translation.'''
++
++ def __init__(self, text='', id='', placeholders=[], description='', meaning=''):
++ super(Translation, self).__init__(text, placeholders, description, meaning)
++ self.id = id
++
++ def GetId(self):
++ assert id != '', "ID has not been set."
++ return self.id
++
++ def SetId(self, id):
++ self.id = id
++
++ def ToTclibMessage(self):
++ msg = grit.extern.tclib.Message(
++ 'utf-8', id=self.id, meaning=self.meaning)
++ self.FillTclibBaseMessage(msg)
++ return msg
++
++
++class Placeholder(grit.extern.tclib.Placeholder):
++ '''Modifies constructor to accept a Unicode string
++ '''
++
++ # Must match placeholder presentation names
++ _NAME_RE = lazy_re.compile('^[A-Za-z0-9_]+$')
++
++ def __init__(self, presentation, original, example):
++ '''Creates a new placeholder.
++
++ Args:
++ presentation: 'USERNAME'
++ original: '%s'
++ example: 'Joi'
++ '''
++ assert presentation != ''
++ assert original != ''
++ assert example != ''
++ if not self._NAME_RE.match(presentation):
++ raise exception.InvalidPlaceholderName(presentation)
++ self.presentation = presentation
++ self.original = original
++ self.example = example
++
++ def GetPresentation(self):
++ return self.presentation
++
++ def GetOriginal(self):
++ return self.original
++
++ def GetExample(self):
++ return self.example
+diff --git a/tools/grit/grit/tclib_unittest.py b/tools/grit/grit/tclib_unittest.py
+new file mode 100644
+index 0000000000..7a08654e1b
+--- /dev/null
++++ b/tools/grit/grit/tclib_unittest.py
+@@ -0,0 +1,180 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.tclib'''
++
++from __future__ import print_function
++
++import sys
++import os.path
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import unittest
++
++import six
++
++from grit import tclib
++
++from grit import exception
++import grit.extern.tclib
++
++
++class TclibUnittest(unittest.TestCase):
++ def testInit(self):
++ msg = tclib.Message(text=u'Hello Earthlings',
++ description='Greetings\n\t message')
++ self.failUnlessEqual(msg.GetPresentableContent(), 'Hello Earthlings')
++ self.failUnless(isinstance(msg.GetPresentableContent(), six.string_types))
++ self.failUnlessEqual(msg.GetDescription(), 'Greetings message')
++
++ def testGetAttr(self):
++ msg = tclib.Message()
++ msg.AppendText(u'Hello') # Tests __getattr__
++ self.failUnless(msg.GetPresentableContent() == 'Hello')
++ self.failUnless(isinstance(msg.GetPresentableContent(), six.string_types))
++
++ def testAll(self):
++ text = u'Howdie USERNAME'
++ phs = [tclib.Placeholder(u'USERNAME', u'%s', 'Joi')]
++ msg = tclib.Message(text=text, placeholders=phs)
++ self.failUnless(msg.GetPresentableContent() == 'Howdie USERNAME')
++
++ trans = tclib.Translation(text=text, placeholders=phs)
++ self.failUnless(trans.GetPresentableContent() == 'Howdie USERNAME')
++ self.failUnless(isinstance(trans.GetPresentableContent(), six.string_types))
++
++ def testUnicodeReturn(self):
++ text = u'\u00fe'
++ msg = tclib.Message(text=text)
++ self.failUnless(msg.GetPresentableContent() == text)
++ from_list = msg.GetContent()[0]
++ self.failUnless(from_list == text)
++
++ def testRegressionTranslationInherited(self):
++ '''Regression tests a bug that was caused by grit.tclib.Translation
++ inheriting from the translation console's Translation object
++ instead of only owning an instance of it.
++ '''
++ msg = tclib.Message(text=u"BLA1\r\nFrom: BLA2 \u00fe BLA3",
++ placeholders=[
++ tclib.Placeholder('BLA1', '%s', '%s'),
++ tclib.Placeholder('BLA2', '%s', '%s'),
++ tclib.Placeholder('BLA3', '%s', '%s')])
++ transl = tclib.Translation(text=msg.GetPresentableContent(),
++ placeholders=msg.GetPlaceholders())
++ content = transl.GetContent()
++ self.failUnless(isinstance(content[3], six.string_types))
++
++ def testFingerprint(self):
++ # This has Windows line endings. That is on purpose.
++ id = grit.extern.tclib.GenerateMessageId(
++ 'Google Desktop for Enterprise\r\n'
++ 'All Rights Reserved\r\n'
++ '\r\n'
++ '---------\r\n'
++ 'Contents\r\n'
++ '---------\r\n'
++ 'This distribution contains the following files:\r\n'
++ '\r\n'
++ 'GoogleDesktopSetup.msi - Installation and setup program\r\n'
++ 'GoogleDesktop.adm - Group Policy administrative template file\r\n'
++ 'AdminGuide.pdf - Google Desktop for Enterprise administrative guide\r\n'
++ '\r\n'
++ '\r\n'
++ '--------------\r\n'
++ 'Documentation\r\n'
++ '--------------\r\n'
++ 'Full documentation and installation instructions are in the \r\n'
++ 'administrative guide, and also online at \r\n'
++ 'http://desktop.google.com/enterprise/adminguide.html.\r\n'
++ '\r\n'
++ '\r\n'
++ '------------------------\r\n'
++ 'IBM Lotus Notes Plug-In\r\n'
++ '------------------------\r\n'
++ 'The Lotus Notes plug-in is included in the release of Google \r\n'
++ 'Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google \r\n'
++ 'Desktop indexes mail, calendar, task, contact and journal \r\n'
++ 'documents from Notes. Discussion documents including those from \r\n'
++ 'the discussion and team room templates can also be indexed by \r\n'
++ 'selecting an option from the preferences. Once indexed, this data\r\n'
++ 'will be returned in Google Desktop searches. The corresponding\r\n'
++ 'document can be opened in Lotus Notes from the Google Desktop \r\n'
++ 'results page.\r\n'
++ '\r\n'
++ 'Install: The plug-in will install automatically during the Google \r\n'
++ 'Desktop setup process if Lotus Notes is already installed. Lotus \r\n'
++ 'Notes must not be running in order for the install to occur. \r\n'
++ '\r\n'
++ 'Preferences: Preferences and selection of databases to index are\r\n'
++ 'set in the \'Google Desktop for Notes\' dialog reached through the \r\n'
++ '\'Actions\' menu.\r\n'
++ '\r\n'
++ 'Reindexing: Selecting \'Reindex all databases\' will index all the \r\n'
++ 'documents in each database again.\r\n'
++ '\r\n'
++ '\r\n'
++ 'Notes Plug-in Known Issues\r\n'
++ '---------------------------\r\n'
++ '\r\n'
++ 'If the \'Google Desktop for Notes\' item is not available from the \r\n'
++ 'Lotus Notes Actions menu, then installation was not successful. \r\n'
++ 'Installation consists of writing one file, notesgdsplugin.dll, to \r\n'
++ 'the Notes application directory and a setting to the notes.ini \r\n'
++ 'configuration file. The most likely cause of an unsuccessful \r\n'
++ 'installation is that the installer was not able to locate the \r\n'
++ 'notes.ini file. Installation will complete if the user closes Notes\r\n'
++ 'and manually adds the following setting to this file on a new line:\r\n'
++ 'AddinMenus=notegdsplugin.dll\r\n'
++ '\r\n'
++ 'If the notesgdsplugin.dll file is not in the application directory\r\n'
++ r'(e.g., C:\Program Files\Lotus\Notes) after Google Desktop \r\n'
++ 'installation, it is likely that Notes was not installed correctly. \r\n'
++ '\r\n'
++ 'Only local databases can be indexed. If they can be determined, \r\n'
++ 'the user\'s local mail file and address book will be included in the\r\n'
++ 'list automatically. Mail archives and other databases must be \r\n'
++ 'added with the \'Add\' button.\r\n'
++ '\r\n'
++ 'Some users may experience performance issues during the initial \r\n'
++ 'indexing of a database. The \'Perform the initial index of a \r\n'
++ 'database only when I\'m idle\' option will limit the indexing process\r\n'
++ 'to times when the user is not using the machine. If this does not \r\n'
++ 'alleviate the problem or the user would like to continually index \r\n'
++ 'but just do so more slowly or quickly, the GoogleWaitTime notes.ini\r\n'
++ 'value can be set. Increasing the GoogleWaitTime value will slow \r\n'
++ 'down the indexing process, and lowering the value will speed it up.\r\n'
++ 'A value of zero causes the fastest possible indexing. Removing the\r\n'
++ 'ini parameter altogether returns it to the default (20).\r\n'
++ '\r\n'
++ 'Crashes have been known to occur with certain types of history \r\n'
++ 'bookmarks. If the Notes client seems to crash randomly, try \r\n'
++ 'disabling the \'Index note history\' option. If it crashes before,\r\n'
++ 'you can get to the preferences, add the following line to your \r\n'
++ 'notes.ini file:\r\n'
++ 'GDSNoIndexHistory=1\r\n')
++ self.assertEqual(id, '7660964495923572726')
++
++ def testPlaceholderNameChecking(self):
++ try:
++ ph = tclib.Placeholder('BINGO BONGO', 'bla', 'bla')
++ raise Exception("We shouldn't get here")
++ except exception.InvalidPlaceholderName:
++ pass # Expect exception to be thrown because presentation contained space
++
++ def testTagsWithCommonSubstring(self):
++ word = 'ABCDEFGHIJ'
++ text = ' '.join([word[:i] for i in range(1, 11)])
++ phs = [tclib.Placeholder(word[:i], str(i), str(i)) for i in range(1, 11)]
++ try:
++ msg = tclib.Message(text=text, placeholders=phs)
++ self.failUnless(msg.GetRealContent() == '1 2 3 4 5 6 7 8 9 10')
++ except:
++ self.fail('tclib.Message() should handle placeholders that are '
++ 'substrings of each other')
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/test_suite_all.py b/tools/grit/grit/test_suite_all.py
+new file mode 100644
+index 0000000000..3bfe2a79d5
+--- /dev/null
++++ b/tools/grit/grit/test_suite_all.py
+@@ -0,0 +1,34 @@
++#!/usr/bin/env python3
++# Copyright (c) 2011 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit test suite that collects all test cases for GRIT.'''
++
++from __future__ import print_function
++
++import os
++import sys
++
++
++CUR_DIR = os.path.dirname(os.path.realpath(__file__))
++SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(CUR_DIR)))
++TYP_DIR = os.path.join(
++ SRC_DIR, 'third_party', 'catapult', 'third_party', 'typ')
++
++if TYP_DIR not in sys.path:
++ sys.path.insert(0, TYP_DIR)
++
++
++import typ # pylint: disable=import-error,unused-import
++
++
++def main(args):
++ return typ.main(
++ top_level_dirs=[os.path.join(CUR_DIR, '..')],
++ skip=['grit.format.gen_predetermined_ids_unittest.*',
++ 'grit.pseudo_unittest.*']
++ )
++
++if __name__ == '__main__':
++ sys.exit(main(sys.argv[1:]))
+diff --git a/tools/grit/grit/testdata/GoogleDesktop.adm b/tools/grit/grit/testdata/GoogleDesktop.adm
+new file mode 100644
+index 0000000000..082f56bb1a
+--- /dev/null
++++ b/tools/grit/grit/testdata/GoogleDesktop.adm
+@@ -0,0 +1,945 @@
++CLASS MACHINE
++ CATEGORY !!Cat_Google
++ CATEGORY !!Cat_GoogleDesktopSearch
++ KEYNAME "Software\Policies\Google\Google Desktop"
++
++ CATEGORY !!Cat_Preferences
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
++
++ CATEGORY !!Cat_IndexAndCaptureControl
++ POLICY !!Blacklist_Email
++ EXPLAIN !!Explain_Blacklist_Email
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ VALUENAME "1"
++ END POLICY
++
++ POLICY !!Blacklist_Gmail
++ EXPLAIN !!Explain_Blacklist_Gmail
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
++ VALUENAME "gmail"
++ END POLICY
++
++ POLICY !!Blacklist_WebHistory
++ EXPLAIN !!Explain_Blacklist_WebHistory
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ VALUENAME "2"
++ END POLICY
++
++ POLICY !!Blacklist_Chat
++ EXPLAIN !!Explain_Blacklist_Chat
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "3" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Text
++ EXPLAIN !!Explain_Blacklist_Text
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "4" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Media
++ EXPLAIN !!Explain_Blacklist_Media
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "5" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Contact
++ EXPLAIN !!Explain_Blacklist_Contact
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "9" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Calendar
++ EXPLAIN !!Explain_Blacklist_Calendar
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "10" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Task
++ EXPLAIN !!Explain_Blacklist_Task
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "11" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Note
++ EXPLAIN !!Explain_Blacklist_Note
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "12" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Journal
++ EXPLAIN !!Explain_Blacklist_Journal
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "13" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Word
++ EXPLAIN !!Explain_Blacklist_Word
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "DOC"
++ END POLICY
++
++ POLICY !!Blacklist_Excel
++ EXPLAIN !!Explain_Blacklist_Excel
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "XLS"
++ END POLICY
++
++ POLICY !!Blacklist_Powerpoint
++ EXPLAIN !!Explain_Blacklist_Powerpoint
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "PPT"
++ END POLICY
++
++ POLICY !!Blacklist_PDF
++ EXPLAIN !!Explain_Blacklist_PDF
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "PDF"
++ END POLICY
++
++ POLICY !!Blacklist_ZIP
++ EXPLAIN !!Explain_Blacklist_ZIP
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "ZIP"
++ END POLICY
++
++ POLICY !!Blacklist_HTTPS
++ EXPLAIN !!Explain_Blacklist_HTTPS
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
++ VALUENAME "HTTPS"
++ END POLICY
++
++ POLICY !!Blacklist_PasswordProtectedOffice
++ EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
++ VALUENAME "SECUREOFFICE"
++ END POLICY
++
++ POLICY !!Blacklist_URI_Contains
++ EXPLAIN !!Explain_Blacklist_URI_Contains
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
++ PART !!Blacklist_URI_Contains LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Blacklist_Extensions
++ EXPLAIN !!Explain_Blacklist_Extensions
++ PART !!Blacklist_Extensions EDITTEXT
++ VALUENAME "file_extensions_to_skip"
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Disallow_UserSearchLocations
++ EXPLAIN !!Explain_Disallow_UserSearchLocations
++ VALUENAME user_search_locations
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Search_Location_Whitelist
++ EXPLAIN !!Explain_Search_Location_Whitelist
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
++ PART !!Search_Locations_Whitelist LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Email_Retention
++ EXPLAIN !!Explain_Email_Retention
++ PART !!Email_Retention_Edit NUMERIC
++ VALUENAME "email_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Webpage_Retention
++ EXPLAIN !!Explain_Webpage_Retention
++ PART !!Webpage_Retention_Edit NUMERIC
++ VALUENAME "webpage_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!File_Retention
++ EXPLAIN !!Explain_File_Retention
++ PART !!File_Retention_Edit NUMERIC
++ VALUENAME "file_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!IM_Retention
++ EXPLAIN !!Explain_IM_Retention
++ PART !!IM_Retention_Edit NUMERIC
++ VALUENAME "im_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Remove_Deleted_Items
++ EXPLAIN !!Explain_Remove_Deleted_Items
++ VALUENAME remove_deleted_items
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Allow_Simultaneous_Indexing
++ EXPLAIN !!Explain_Allow_Simultaneous_Indexing
++ VALUENAME simultaneous_indexing
++ VALUEON NUMERIC 1
++ END POLICY
++
++ END CATEGORY
++
++ POLICY !!Pol_TurnOffAdvancedFeatures
++ EXPLAIN !!Explain_TurnOffAdvancedFeatures
++ VALUENAME error_report_on
++ VALUEON NUMERIC 0
++ END POLICY
++
++ POLICY !!Pol_TurnOffImproveGd
++ EXPLAIN !!Explain_TurnOffImproveGd
++ VALUENAME improve_gd
++ VALUEON NUMERIC 0
++ VALUEOFF NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_NoPersonalizationInfo
++ EXPLAIN !!Explain_NoPersonalizationInfo
++ VALUENAME send_personalization_info
++ VALUEON NUMERIC 0
++ VALUEOFF NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_OneBoxMode
++ EXPLAIN !!Explain_OneBoxMode
++ VALUENAME onebox_mode
++ VALUEON NUMERIC 0
++ END POLICY
++
++ POLICY !!Pol_EncryptIndex
++ EXPLAIN !!Explain_EncryptIndex
++ VALUENAME encrypt_index
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Hyper
++ EXPLAIN !!Explain_Hyper
++ VALUENAME hyper_off
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Display_Mode
++ EXPLAIN !!Explain_Display_Mode
++ PART !!Pol_Display_Mode DROPDOWNLIST
++ VALUENAME display_mode
++ ITEMLIST
++ NAME !!Sidebar VALUE NUMERIC 1
++ NAME !!Deskbar VALUE NUMERIC 8
++ NAME !!FloatingDeskbar VALUE NUMERIC 4
++ NAME !!None VALUE NUMERIC 0
++ END ITEMLIST
++ END PART
++ END POLICY
++
++ END CATEGORY ; Preferences
++
++ CATEGORY !!Cat_Enterprise
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
++
++ POLICY !!Pol_Autoupdate
++ EXPLAIN !!Explain_Autoupdate
++ VALUENAME autoupdate_host
++ VALUEON ""
++ END POLICY
++
++ POLICY !!Pol_AutoupdateAsSystem
++ EXPLAIN !!Explain_AutoupdateAsSystem
++ VALUENAME autoupdate_impersonate_user
++ VALUEON NUMERIC 0
++ VALUEOFF NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_EnterpriseTab
++ EXPLAIN !!Explain_EnterpriseTab
++ PART !!EnterpriseTabText EDITTEXT
++ VALUENAME enterprise_tab_text
++ END PART
++ PART !!EnterpriseTabHomepage EDITTEXT
++ VALUENAME enterprise_tab_homepage
++ END PART
++ PART !!EnterpriseTabHomepageQuery CHECKBOX
++ VALUENAME enterprise_tab_homepage_query
++ END PART
++ PART !!EnterpriseTabResults EDITTEXT
++ VALUENAME enterprise_tab_results
++ END PART
++ PART !!EnterpriseTabResultsQuery CHECKBOX
++ VALUENAME enterprise_tab_results_query
++ END PART
++ END POLICY
++
++ POLICY !!Pol_GSAHosts
++ EXPLAIN !!Explain_GSAHosts
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
++ PART !!Pol_GSAHosts LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Pol_PolicyUnawareClientProhibitedFlag
++ EXPLAIN !!Explain_PolicyUnawareClientProhibitedFlag
++ KEYNAME "Software\Policies\Google\Google Desktop"
++ VALUENAME PolicyUnawareClientProhibitedFlag
++ END POLICY
++
++ POLICY !!Pol_MinimumAllowedVersion
++ EXPLAIN !!Explain_MinimumAllowedVersion
++ PART !!Pol_MinimumAllowedVersion EDITTEXT
++ VALUENAME minimum_allowed_version
++ END PART
++ END POLICY
++
++ POLICY !!Pol_MaximumAllowedVersion
++ EXPLAIN !!Explain_MaximumAllowedVersion
++ PART !!Pol_MaximumAllowedVersion EDITTEXT
++ VALUENAME maximum_allowed_version
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Disallow_Gadgets
++ EXPLAIN !!Explain_Disallow_Gadgets
++ VALUENAME disallow_gadgets
++ VALUEON NUMERIC 1
++ PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
++ VALUENAME disallow_only_non_builtin_gadgets
++ VALUEON NUMERIC 1
++ VALUEOFF NUMERIC 0
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Gadget_Whitelist
++ EXPLAIN !!Explain_Gadget_Whitelist
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
++ PART !!Pol_Gadget_Whitelist LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
++ EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
++ PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Alternate_User_Data_Dir
++ EXPLAIN !!Explain_Alternate_User_Data_Dir
++ PART !!Pol_Alternate_User_Data_Dir EDITTEXT
++ VALUENAME alternate_user_data_dir
++ END PART
++ END POLICY
++
++ POLICY !!Pol_MaxAllowedOutlookConnections
++ EXPLAIN !!Explain_MaxAllowedOutlookConnections
++ PART !!Pol_MaxAllowedOutlookConnections NUMERIC
++ VALUENAME max_allowed_outlook_connections
++ MIN 1 MAX 65535 DEFAULT 400 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Pol_DisallowSsdService
++ EXPLAIN !!Explain_DisallowSsdService
++ VALUENAME disallow_ssd_service
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_DisallowSsdOutbound
++ EXPLAIN !!Explain_DisallowSsdOutbound
++ VALUENAME disallow_ssd_outbound
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Disallow_Store_Gadget_Service
++ EXPLAIN !!Explain_Disallow_Store_Gadget_Service
++ VALUENAME disallow_store_gadget_service
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_MaxExchangeIndexingRate
++ EXPLAIN !!Explain_MaxExchangeIndexingRate
++ PART !!Pol_MaxExchangeIndexingRate NUMERIC
++ VALUENAME max_exchange_indexing_rate
++ MIN 1 MAX 1000 DEFAULT 60 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Pol_EnableSafeweb
++ EXPLAIN !!Explain_Safeweb
++ VALUENAME safe_browsing
++ VALUEON NUMERIC 1
++ VALUEOFF NUMERIC 0
++ END POLICY
++
++ END CATEGORY ; Enterprise
++
++ END CATEGORY ; GoogleDesktopSearch
++ END CATEGORY ; Google
++
++
++CLASS USER
++ CATEGORY !!Cat_Google
++ CATEGORY !!Cat_GoogleDesktopSearch
++ KEYNAME "Software\Policies\Google\Google Desktop"
++
++ CATEGORY !!Cat_Preferences
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
++
++ CATEGORY !!Cat_IndexAndCaptureControl
++ POLICY !!Blacklist_Email
++ EXPLAIN !!Explain_Blacklist_Email
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ VALUENAME "1"
++ END POLICY
++
++ POLICY !!Blacklist_Gmail
++ EXPLAIN !!Explain_Blacklist_Gmail
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
++ VALUENAME "gmail"
++ END POLICY
++
++ POLICY !!Blacklist_WebHistory
++ EXPLAIN !!Explain_Blacklist_WebHistory
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ VALUENAME "2"
++ END POLICY
++
++ POLICY !!Blacklist_Chat
++ EXPLAIN !!Explain_Blacklist_Chat
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "3" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Text
++ EXPLAIN !!Explain_Blacklist_Text
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "4" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Media
++ EXPLAIN !!Explain_Blacklist_Media
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "5" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Contact
++ EXPLAIN !!Explain_Blacklist_Contact
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "9" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Calendar
++ EXPLAIN !!Explain_Blacklist_Calendar
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "10" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Task
++ EXPLAIN !!Explain_Blacklist_Task
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "11" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Note
++ EXPLAIN !!Explain_Blacklist_Note
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "12" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Journal
++ EXPLAIN !!Explain_Blacklist_Journal
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
++ ACTIONLISTON
++ VALUENAME "13" VALUE NUMERIC 1
++ END ACTIONLISTON
++ END POLICY
++
++ POLICY !!Blacklist_Word
++ EXPLAIN !!Explain_Blacklist_Word
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "DOC"
++ END POLICY
++
++ POLICY !!Blacklist_Excel
++ EXPLAIN !!Explain_Blacklist_Excel
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "XLS"
++ END POLICY
++
++ POLICY !!Blacklist_Powerpoint
++ EXPLAIN !!Explain_Blacklist_Powerpoint
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "PPT"
++ END POLICY
++
++ POLICY !!Blacklist_PDF
++ EXPLAIN !!Explain_Blacklist_PDF
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "PDF"
++ END POLICY
++
++ POLICY !!Blacklist_ZIP
++ EXPLAIN !!Explain_Blacklist_ZIP
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
++ VALUENAME "ZIP"
++ END POLICY
++
++ POLICY !!Blacklist_HTTPS
++ EXPLAIN !!Explain_Blacklist_HTTPS
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
++ VALUENAME "HTTPS"
++ END POLICY
++
++ POLICY !!Blacklist_PasswordProtectedOffice
++ EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
++ VALUENAME "SECUREOFFICE"
++ END POLICY
++
++ POLICY !!Blacklist_URI_Contains
++ EXPLAIN !!Explain_Blacklist_URI_Contains
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
++ PART !!Blacklist_URI_Contains LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Blacklist_Extensions
++ EXPLAIN !!Explain_Blacklist_Extensions
++ PART !!Blacklist_Extensions EDITTEXT
++ VALUENAME "file_extensions_to_skip"
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Disallow_UserSearchLocations
++ EXPLAIN !!Explain_Disallow_UserSearchLocations
++ VALUENAME user_search_locations
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Search_Location_Whitelist
++ EXPLAIN !!Explain_Search_Location_Whitelist
++ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
++ PART !!Search_Locations_Whitelist LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Email_Retention
++ EXPLAIN !!Explain_Email_Retention
++ PART !!Email_Retention_Edit NUMERIC
++ VALUENAME "email_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Webpage_Retention
++ EXPLAIN !!Explain_Webpage_Retention
++ PART !!Webpage_Retention_Edit NUMERIC
++ VALUENAME "webpage_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!File_Retention
++ EXPLAIN !!Explain_File_Retention
++ PART !!File_Retention_Edit NUMERIC
++ VALUENAME "file_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!IM_Retention
++ EXPLAIN !!Explain_IM_Retention
++ PART !!IM_Retention_Edit NUMERIC
++ VALUENAME "im_days_to_retain"
++ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Remove_Deleted_Items
++ EXPLAIN !!Explain_Remove_Deleted_Items
++ VALUENAME remove_deleted_items
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Allow_Simultaneous_Indexing
++ EXPLAIN !!Explain_Allow_Simultaneous_Indexing
++ VALUENAME simultaneous_indexing
++ VALUEON NUMERIC 1
++ END POLICY
++
++ END CATEGORY
++
++ POLICY !!Pol_TurnOffAdvancedFeatures
++ EXPLAIN !!Explain_TurnOffAdvancedFeatures
++ VALUENAME error_report_on
++ VALUEON NUMERIC 0
++ END POLICY
++
++ POLICY !!Pol_TurnOffImproveGd
++ EXPLAIN !!Explain_TurnOffImproveGd
++ VALUENAME improve_gd
++ VALUEON NUMERIC 0
++ VALUEOFF NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_NoPersonalizationInfo
++ EXPLAIN !!Explain_NoPersonalizationInfo
++ VALUENAME send_personalization_info
++ VALUEON NUMERIC 0
++ VALUEOFF NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_OneBoxMode
++ EXPLAIN !!Explain_OneBoxMode
++ VALUENAME onebox_mode
++ VALUEON NUMERIC 0
++ END POLICY
++
++ POLICY !!Pol_EncryptIndex
++ EXPLAIN !!Explain_EncryptIndex
++ VALUENAME encrypt_index
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Hyper
++ EXPLAIN !!Explain_Hyper
++ VALUENAME hyper_off
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Display_Mode
++ EXPLAIN !!Explain_Display_Mode
++ PART !!Pol_Display_Mode DROPDOWNLIST
++ VALUENAME display_mode
++ ITEMLIST
++ NAME !!Sidebar VALUE NUMERIC 1
++ NAME !!Deskbar VALUE NUMERIC 8
++ NAME !!FloatingDeskbar VALUE NUMERIC 4
++ NAME !!None VALUE NUMERIC 0
++ END ITEMLIST
++ END PART
++ END POLICY
++
++ END CATEGORY ; Preferences
++
++ CATEGORY !!Cat_Enterprise
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
++
++ POLICY !!Pol_Autoupdate
++ EXPLAIN !!Explain_Autoupdate
++ VALUENAME autoupdate_host
++ VALUEON ""
++ END POLICY
++
++ POLICY !!Pol_AutoupdateAsSystem
++ EXPLAIN !!Explain_AutoupdateAsSystem
++ VALUENAME autoupdate_impersonate_user
++ VALUEON NUMERIC 0
++ VALUEOFF NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_EnterpriseTab
++ EXPLAIN !!Explain_EnterpriseTab
++ PART !!EnterpriseTabText EDITTEXT
++ VALUENAME enterprise_tab_text
++ END PART
++ PART !!EnterpriseTabHomepage EDITTEXT
++ VALUENAME enterprise_tab_homepage
++ END PART
++ PART !!EnterpriseTabHomepageQuery CHECKBOX
++ VALUENAME enterprise_tab_homepage_query
++ END PART
++ PART !!EnterpriseTabResults EDITTEXT
++ VALUENAME enterprise_tab_results
++ END PART
++ PART !!EnterpriseTabResultsQuery CHECKBOX
++ VALUENAME enterprise_tab_results_query
++ END PART
++ END POLICY
++
++ POLICY !!Pol_GSAHosts
++ EXPLAIN !!Explain_GSAHosts
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
++ PART !!Pol_GSAHosts LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Disallow_Gadgets
++ EXPLAIN !!Explain_Disallow_Gadgets
++ VALUENAME disallow_gadgets
++ VALUEON NUMERIC 1
++ PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
++ VALUENAME disallow_only_non_builtin_gadgets
++ VALUEON NUMERIC 1
++ VALUEOFF NUMERIC 0
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Gadget_Whitelist
++ EXPLAIN !!Explain_Gadget_Whitelist
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
++ PART !!Pol_Gadget_Whitelist LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
++ EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
++ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
++ PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
++ END PART
++ END POLICY
++
++ POLICY !!Pol_Alternate_User_Data_Dir
++ EXPLAIN !!Explain_Alternate_User_Data_Dir
++ PART !!Pol_Alternate_User_Data_Dir EDITTEXT
++ VALUENAME alternate_user_data_dir
++ END PART
++ END POLICY
++
++ POLICY !!Pol_MaxAllowedOutlookConnections
++ EXPLAIN !!Explain_MaxAllowedOutlookConnections
++ PART !!Pol_MaxAllowedOutlookConnections NUMERIC
++ VALUENAME max_allowed_outlook_connections
++ MIN 1 MAX 65535 DEFAULT 400 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Pol_DisallowSsdService
++ EXPLAIN !!Explain_DisallowSsdService
++ VALUENAME disallow_ssd_service
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_DisallowSsdOutbound
++ EXPLAIN !!Explain_DisallowSsdOutbound
++ VALUENAME disallow_ssd_outbound
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_Disallow_Store_Gadget_Service
++ EXPLAIN !!Explain_Disallow_Store_Gadget_Service
++ VALUENAME disallow_store_gadget_service
++ VALUEON NUMERIC 1
++ END POLICY
++
++ POLICY !!Pol_MaxExchangeIndexingRate
++ EXPLAIN !!Explain_MaxExchangeIndexingRate
++ PART !!Pol_MaxExchangeIndexingRate NUMERIC
++ VALUENAME max_exchange_indexing_rate
++ MIN 1 MAX 1000 DEFAULT 60 SPIN 1
++ END PART
++ END POLICY
++
++ POLICY !!Pol_EnableSafeweb
++ EXPLAIN !!Explain_Safeweb
++ VALUENAME safe_browsing
++ VALUEON NUMERIC 1
++ VALUEOFF NUMERIC 0
++ END POLICY
++
++ END CATEGORY ; Enterprise
++
++ END CATEGORY ; GoogleDesktopSearch
++ END CATEGORY ; Google
++
++;------------------------------------------------------------------------------
++
++[strings]
++Cat_Google="Google"
++Cat_GoogleDesktopSearch="Google Desktop"
++
++;------------------------------------------------------------------------------
++; Preferences
++;------------------------------------------------------------------------------
++Cat_Preferences="Preferences"
++Explain_Preferences="Controls Google Desktop preferences"
++
++Cat_IndexAndCaptureControl="Indexing and Capture Control"
++Explain_IndexAndCaptureControl="Controls what files, web pages, and other content will be indexed by Google Desktop."
++
++Blacklist_Email="Prevent indexing of email"
++Explain_Blacklist_Email="Enabling this policy will prevent Google Desktop from indexing emails.\n\nIf this policy is not configured, the user can choose whether or not to index emails."
++Blacklist_Gmail="Prevent indexing of Gmail"
++Explain_Blacklist_Gmail="Enabling this policy prevents Google Desktop from indexing Gmail messages.\n\nThis policy is in effect only when the policy "Prevent indexing of email" is disabled. When that policy is enabled, all email indexing is disabled, including Gmail indexing.\n\nIf both this policy and "Prevent indexing of email" are disabled or not configured, a user can choose whether or not to index Gmail messages."
++Blacklist_WebHistory="Prevent indexing of web pages"
++Explain_Blacklist_WebHistory="Enabling this policy will prevent Google Desktop from indexing web pages.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index web pages."
++Blacklist_Text="Prevent indexing of text files"
++Explain_Blacklist_Text="Enabling this policy will prevent Google Desktop from indexing text files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index text files."
++Blacklist_Media="Prevent indexing of media files"
++Explain_Blacklist_Media="Enabling this policy will prevent Google Desktop from indexing media files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index media files."
++Blacklist_Contact="Prevent indexing of contacts"
++Explain_Blacklist_Contact="Enabling this policy will prevent Google Desktop from indexing contacts.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index contacts."
++Blacklist_Calendar="Prevent indexing of calendar entries"
++Explain_Blacklist_Calendar="Enabling this policy will prevent Google Desktop from indexing calendar entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index calendar entries."
++Blacklist_Task="Prevent indexing of tasks"
++Explain_Blacklist_Task="Enabling this policy will prevent Google Desktop from indexing tasks.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index tasks."
++Blacklist_Note="Prevent indexing of notes"
++Explain_Blacklist_Note="Enabling this policy will prevent Google Desktop from indexing notes.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index notes."
++Blacklist_Journal="Prevent indexing of journal entries"
++Explain_Blacklist_Journal="Enabling this policy will prevent Google Desktop from indexing journal entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index journal entries."
++Blacklist_Word="Prevent indexing of Word documents"
++Explain_Blacklist_Word="Enabling this policy will prevent Google Desktop from indexing Word documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Word documents."
++Blacklist_Excel="Prevent indexing of Excel documents"
++Explain_Blacklist_Excel="Enabling this policy will prevent Google Desktop from indexing Excel documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Excel documents."
++Blacklist_Powerpoint="Prevent indexing of PowerPoint documents"
++Explain_Blacklist_Powerpoint="Enabling this policy will prevent Google Desktop from indexing PowerPoint documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PowerPoint documents."
++Blacklist_PDF="Prevent indexing of PDF documents"
++Explain_Blacklist_PDF="Enabling this policy will prevent Google Desktop from indexing PDF documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PDF documents."
++Blacklist_ZIP="Prevent indexing of ZIP files"
++Explain_Blacklist_ZIP="Enabling this policy will prevent Google Desktop from indexing ZIP files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index ZIP files."
++Blacklist_HTTPS="Prevent indexing of secure web pages"
++Explain_Blacklist_HTTPS="Enabling this policy will prevent Google Desktop from indexing secure web pages (pages with HTTPS in the URL).\n\nIf this policy is disabled or not configured, the user can choose whether or not to index secure web pages."
++Blacklist_URI_Contains="Prevent indexing of specific web sites and folders"
++Explain_Blacklist_URI_Contains="This policy allows you to prevent Google Desktop from indexing specific websites or folders. If an item's URL or path name contains any of these specified strings, it will not be indexed. These restrictions will be applied in addition to any websites or folders that the user has specified.\n\nThis policy has no effect when disabled or not configured."
++Blacklist_Chat="Prevent indexing of IM chats"
++Explain_Blacklist_Chat="Enabling this policy will prevent Google Desktop from indexing IM chat conversations.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index IM chat conversations."
++Blacklist_PasswordProtectedOffice="Prevent indexing of password-protected Office documents (Word, Excel)"
++Explain_Blacklist_PasswordProtectedOffice="Enabling this policy will prevent Google Desktop from indexing password-protected office documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index password-protected office documents."
++Blacklist_Extensions="Prevent indexing of specific file extensions"
++Explain_Blacklist_Extensions="This policy allows you to prevent Google Desktop from indexing files with specific extensions. Enter a list of file extensions, separated by commas, that you wish to exclude from indexing.\n\nThis policy has no effect when disabled or not configured."
++Pol_Disallow_UserSearchLocations="Disallow adding search locations for indexing"
++Explain_Disallow_UserSearchLocations="Enabling this policy will prevent the user from specifying additional drives or networked folders to be indexed by Google Desktop.\n\nIf this policy is disabled or not configured, users may specify additional drives and networked folders to be indexed."
++Pol_Search_Location_Whitelist="Allow indexing of specific folders"
++Explain_Search_Location_Whitelist="This policy allows you to add additional drives and networked folders to index."
++Search_Locations_Whitelist="Search these locations"
++Email_Retention="Only retain emails that are less than x days old"
++Explain_Email_Retention="This policy allows you to configure Google Desktop to only retain emails that are less than the specified number of days old in the index. Enter the number of days to retain emails for\n\nThis policy has no effect when disabled or not configured."
++Email_Retention_Edit="Number of days to retain emails"
++Webpage_Retention="Only retain webpages that are less than x days old"
++Explain_Webpage_Retention="This policy allows you to configure Google Desktop to only retain webpages that are less than the specified number of days old in the index. Enter the number of days to retain webpages for\n\nThis policy has no effect when disabled or not configured."
++Webpage_Retention_Edit="Number of days to retain webpages"
++File_Retention="Only retain files that are less than x days old"
++Explain_File_Retention="This policy allows you to configure Google Desktop to only retain files that are less than the specified number of days old in the index. Enter the number of days to retain files for\n\nThis policy has no effect when disabled or not configured."
++File_Retention_Edit="Number of days to retain files"
++IM_Retention="Only retain IM that are less than x days old"
++Explain_IM_Retention="This policy allows you to configure Google Desktop to only retain IM that are less than the specified number of days old in the index. Enter the number of days to retain IM for\n\nThis policy has no effect when disabled or not configured."
++IM_Retention_Edit="Number of days to retain IM"
++
++Pol_Remove_Deleted_Items="Remove deleted items from the index."
++Explain_Remove_Deleted_Items="Enabling this policy will remove all deleted items from the index and cache. Any items that are deleted will no longer be searchable."
++
++Pol_Allow_Simultaneous_Indexing="Allow historical indexing for multiple users simultaneously."
++Explain_Allow_Simultaneous_Indexing="Enabling this policy will allow a computer to generate first-time indexes for multiple users simultaneously. \n\nIf this policy is disabled or not configured, historical indexing will happen only for the logged-in user that was connected last; historical indexing for any other logged-in user will happen the next time that other user connects."
++
++Pol_TurnOffAdvancedFeatures="Turn off Advanced Features options"
++Explain_TurnOffAdvancedFeatures="Enabling this policy will prevent Google Desktop from sending Advanced Features data to Google (for either improvements or personalization), and users won't be able to change these options. Enabling this policy also prevents older versions of Google Desktop from sending data.\n\nIf this policy is disabled or not configured and the user has a pre-5.5 version of Google Desktop, the user can choose whether or not to enable sending data to Google. If the user has version 5.5 or later, the 'Turn off Improve Google Desktop option' and 'Do not send personalization info' policies will be used instead."
++
++Pol_TurnOffImproveGd="Turn off Improve Google Desktop option"
++Explain_TurnOffImproveGd="Enabling this policy will prevent Google Desktop from sending improvement data, including crash reports and anonymous usage data, to Google.\n\nIf this policy is disabled, improvement data will be sent to Google and the user won't be able to change the option.\n\nIf this policy is not configured, the user can choose whether or not to enable the Improve Google Desktop option.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
++
++Pol_NoPersonalizationInfo="Do not send personalization info"
++Explain_NoPersonalizationInfo="Enabling this policy will prevent Google Desktop from displaying personalized content, such as news that reflects the user's past interest in articles. Personalized content is derived from anonymous usage data sent to Google.\n\nIf this policy is disabled, personalized content will be displayed for all users, and users won't be able to disable this feature.\n\nIf this policy is not configured, users can choose whether or not to enable personalization in each gadget that supports this feature.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
++
++Pol_OneBoxMode="Turn off Google Web Search Integration"
++Explain_OneBoxMode="Enabling this policy will prevent Google Desktop from displaying Desktop Search results in queries to google.com.\n\nIf this policy is disabled or not configured, the user can choose whether or not to include Desktop Search results in queries to google.com."
++
++Pol_EncryptIndex="Encrypt index data"
++Explain_EncryptIndex="Enabling this policy will cause Google Desktop to turn on Windows file encryption for the folder containing the Google Desktop index and related user data the next time it is run.\n\nNote that Windows EFS is only available on NTFS volumes. If the user's data is stored on a FAT volume, this policy will have no effect.\n\nThis policy has no effect when disabled or not configured."
++
++Pol_Hyper="Turn off Quick Find"
++Explain_Hyper="Enabling this policy will cause Google Desktop to turn off Quick Find feature. Quick Find allows you to see results as you type.\n\nIf this policy is disabled or not configured, the user can choose whether or not to enable it."
++
++Pol_Display_Mode="Choose display option"
++Explain_Display_Mode="This policy sets the Google Desktop display option: Sidebar, Deskbar, Floating Deskbar or none.\n\nNote that on 64-bit systems, a setting of Deskbar will be interpreted as Floating Deskbar.\n\nIf this policy is disabled or not configured, the user can choose a display option."
++Sidebar="Sidebar"
++Deskbar="Deskbar"
++FloatingDeskbar="Floating Deskbar"
++None="None"
++
++;------------------------------------------------------------------------------
++; Enterprise
++;------------------------------------------------------------------------------
++Cat_Enterprise="Enterprise Integration"
++Explain_Enterprise="Controls features specific to Enterprise installations of Google Desktop"
++
++Pol_Autoupdate="Block Auto-update"
++Explain_Autoupdate="Enabling this policy prevents Google Desktop from automatically checking for and installing updates from google.com.\n\nIf you enable this policy, you must distribute updates to Google Desktop using Group Policy, SMS, or a similar enterprise software distribution mechanism. You should check http://desktop.google.com/enterprise/ for updates.\n\nIf this policy is disabled or not configured, Google Desktop will periodically check for updates from desktop.google.com."
++
++Pol_AutoupdateAsSystem="Use system proxy settings when auto-updating"
++Explain_AutoupdateAsSystem="Enabling this policy makes Google Desktop use the machine-wide proxy settings (as specified using e.g. proxycfg.exe) when performing autoupdates (if enabled).\n\nIf this policy is disabled or not configured, Google Desktop will use the logged-on user's Internet Explorer proxy settings when checking for auto-updates (if enabled)."
++
++Pol_EnterpriseTab="Enterprise search tab"
++Explain_EnterpriseTab="This policy allows you to add a search tab for your Google Search Appliance to Google Desktop and google.com web pages.\n\nYou must provide the name of the tab, such as "Intranet", as well as URLs for the search homepage and for retrieving search results. Use [DISP_QUERY] in place of the query term for the search results URL.\n\nSee the administrator's guide for more details."
++EnterpriseTabText="Tab name"
++EnterpriseTabHomepage="Search homepage URL"
++EnterpriseTabHomepageQuery="Check if search homepage supports '&&q=<query>'"
++EnterpriseTabResults="Search results URL"
++EnterpriseTabResultsQuery="Check if search results page supports '&&q=<query>'"
++
++Pol_GSAHosts="Google Search Appliances"
++Explain_GSAHosts="This policy allows you to list any Google Search Appliances in your intranet. When properly configured, Google Desktop will insert Google Desktop results into the results of queries on the Google Search Appliance"
++
++Pol_PolicyUnawareClientProhibitedFlag="Prohibit Policy-Unaware versions"
++Explain_PolicyUnawareClientProhibitedFlag="Prohibits installation and execution of versions of Google Desktop that are unaware of group policy.\n\nEnabling this policy will prevent users from installing or running version 1.0 of Google Desktop.\n\nThis policy has no effect when disabled or not configured."
++
++Pol_MinimumAllowedVersion="Minimum allowed version"
++Explain_MinimumAllowedVersion="This policy allows you to prevent installation and/or execution of older versions of Google Desktop by specifying the minimum version you wish to allow. When enabling this policy, you should also enable the "Prohibit Policy-Unaware versions" policy to block versions of Google Desktop that did not support group policy.\n\nThis policy has no effect when disabled or not configured."
++
++Pol_MaximumAllowedVersion="Maximum allowed version"
++Explain_MaximumAllowedVersion="This policy allows you to prevent installation and/or execution of newer versions of Google Desktop by specifying the maximum version you wish to allow.\n\nThis policy has no effect when disabled or not configured."
++
++Pol_Disallow_Gadgets="Disallow gadgets and indexing plug-ins"
++Explain_Disallow_Gadgets="This policy prevents the use of all Google Desktop gadgets and indexing plug-ins. The policy applies to gadgets that are included in the Google Desktop installation package (built-in gadgets), built-in indexing plug-ins (currently only the Lotus Notes plug-in), and to gadgets or indexing plug-ins that a user might want to add later (non-built-in gadgets and indexing plug-ins).\n\nYou can prohibit use of all non-built-in gadgets and indexing plug-ins, but allow use of built-in gadgets and indexing plug-ins. To do so, enable this policy and then select the option "Disallow only non-built-in gadgets and indexing plug-ins.\n\nYou can supersede this policy to allow specified built-in and non-built-in gadgets and indexing plug-ins. To do so, enable this policy and then specify the gadgets and/or indexing plug-ins you want to allow under "Gadget and Plug-in Whitelist.""
++Disallow_Only_Non_Builtin_Gadgets="Disallow only non-built-in gadgets and indexing plug-ins"
++
++Pol_Gadget_Whitelist="Gadget and plug-in whitelist"
++Explain_Gadget_Whitelist="This policy specifies a list of Google Desktop gadgets and indexing plug-ins that you want to allow, as exceptions to the "Disallow gadgets and indexing plug-ins" policy. This policy is valid only when the "Disallow gadgets and indexing plug-ins" policy is enabled.\n\nFor each gadget or indexing plug-in you wish to allow, add the CLSID or PROGID of the gadget or indexing plug-in (see the administrator's guide for more details).\n\nThis policy has no effect when disabled or not configured."
++
++Pol_Gadget_Install_Confirmation_Whitelist="Allow silent installation of gadgets"
++Explain_Gadget_Install_Confirmation_Whitelist="Enabling this policy lets you specify a list of Google Desktop gadgets or indexing plug-ins that can be installed without confirmation from the user.\n\nAdd a gadget or indexing plug-in by placing its class ID (CLSID) or program identifier (PROGID) in the list, surrounded with curly braces ({ }).\n\nThis policy has no effect when disabled or not configured."
++
++Pol_Alternate_User_Data_Dir="Alternate user data directory"
++Explain_Alternate_User_Data_Dir="This policy allows you to specify a directory to be used to store user data for Google Desktop (such as index data and cached documents).\n\nYou may use [USER_NAME] or [DOMAIN_NAME] in the path to specify the current user's name or domain. If [USER_NAME] is not specified, the user name will be appended at the end of the path.\n\nThis policy has no effect when disabled or not configured."
++
++Pol_MaxAllowedOutlookConnections="Maximum allowed Outlook connections"
++Explain_MaxAllowedOutlookConnections="This policy specifies the maximum number of open connections that Google Desktop maintains with the Exchange server. Google Desktop opens a connection for each email folder that it indexes. If insufficient connections are allowed, Google Desktop cannot index all the user email folders.\n\nThe default value is 400. Because users rarely have as many as 400 email folders, Google Desktop rarely reaches the limit.\n\nIf you set this policy's value above 400, you must also configure the number of open connections between Outlook and the Exchange server. By default, approximately 400 connections are allowed. If Google Desktop uses too many of these connections, Outlook might be unable to access email.\n\nThis policy has no effect when disabled or not configured."
++
++Pol_DisallowSsdService="Disallow sharing and receiving of web history and documents across computers"
++Explain_DisallowSsdService="Enabling this policy will prevent Google Desktop from sharing the user's web history and document contents across the user's different Google Desktop installations, and will also prevent it from receiving such shared items from the user's other machines. To allow reception but disallow sharing, use DisallowSsdOutbound.\nThis policy has no effect when disabled or not configured."
++
++Pol_DisallowSsdOutbound="Disallow sharing of web history and documents to user's other computers."
++Explain_DisallowSsdOutbound="Enabling this policy will prevent Google Desktop from sending the user's web history and document contents from this machine to the user's other machines. It does not prevent reception of items from the user's other machines; to disallow both, use DisallowSsdService.\nThis policy has no effect when disabled or not configured."
++
++Pol_Disallow_Store_Gadget_Service="Disallow storage of gadget content and settings."
++Explain_Disallow_Store_Gadget_Service="Enabling this policy will prevent users from storing their gadget content and settings with Google. Users will be unable to access their gadget content and settings from other computers and all content and settings will be lost if Google Desktop is uninstalled."
++
++Pol_MaxExchangeIndexingRate="Maximum allowed Exchange indexing rate"
++Explain_MaxExchangeIndexingRate="This policy allows you to specify the maximum number of emails that are indexed per minute. \n\nThis policy has no effect when disabled or not configured."
++
++Pol_EnableSafeweb="Enable or disable safe browsing"
++Explain_Safeweb="Google Desktop safe browsing informs the user whenever they visit any site which is a suspected forgery site or may harm their computer. Enabling this policy turns on safe browsing; disabling the policy turns it off. \n\nIf this policy is not configured, the user can select whether to turn on safe browsing."
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/README.txt b/tools/grit/grit/testdata/README.txt
+new file mode 100644
+index 0000000000..a683b3b9e3
+--- /dev/null
++++ b/tools/grit/grit/testdata/README.txt
+@@ -0,0 +1,87 @@
++Google Desktop for Enterprise
++Copyright (C) 2007 Google Inc.
++All Rights Reserved
++
++---------
++Contents
++---------
++This distribution contains the following files:
++
++GoogleDesktopSetup.msi - Installation and setup program
++GoogleDesktop.adm - Group Policy administrative template file
++AdminGuide.pdf - Google Desktop for Enterprise administrative guide
++
++
++--------------
++Documentation
++--------------
++Full documentation and installation instructions are in the
++administrative guide, and also online at
++http://desktop.google.com/enterprise/adminguide.html.
++
++
++------------------------
++IBM Lotus Notes Plug-In
++------------------------
++The Lotus Notes plug-in is included in the release of Google
++Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google
++Desktop indexes mail, calendar, task, contact and journal
++documents from Notes. Discussion documents including those from
++the discussion and team room templates can also be indexed by
++selecting an option from the preferences. Once indexed, this data
++will be returned in Google Desktop searches. The corresponding
++document can be opened in Lotus Notes from the Google Desktop
++results page.
++
++Install: The plug-in will install automatically during the Google
++Desktop setup process if Lotus Notes is already installed. Lotus
++Notes must not be running in order for the install to occur. The
++Class ID for this plug-in is {8F42BDFB-33E8-427B-AFDC-A04E046D3F07}.
++
++Preferences: Preferences and selection of databases to index are
++set in the 'Google Desktop for Notes' dialog reached through the
++'Actions' menu.
++
++Reindexing: Selecting 'Reindex all databases' will index all the
++documents in each database again.
++
++
++Notes Plug-in Known Issues
++---------------------------
++
++If the 'Google Desktop for Notes' item is not available from the
++Lotus Notes Actions menu, then installation was not successful.
++Installation consists of writing one file, notesgdsplugin.dll, to
++the Notes application directory and a setting to the notes.ini
++configuration file. The most likely cause of an unsuccessful
++installation is that the installer was not able to locate the
++notes.ini file. Installation will complete if the user closes Notes
++and manually adds the following setting to this file on a new line:
++AddinMenus=notesgdsplugin.dll
++
++If the notesgdsplugin.dll file is not in the application directory
++(e.g., C:\Program Files\Lotus\Notes) after Google Desktop
++installation, it is likely that Notes was not installed correctly.
++
++Only local databases can be indexed. If they can be determined,
++the user's local mail file and address book will be included in the
++list automatically. Mail archives and other databases must be
++added with the 'Add' button.
++
++Some users may experience performance issues during the initial
++indexing of a database. The 'Perform the initial index of a
++database only when I'm idle' option will limit the indexing process
++to times when the user is not using the machine. If this does not
++alleviate the problem or the user would like to continually index
++but just do so more slowly or quickly, the GoogleWaitTime notes.ini
++value can be set. Increasing the GoogleWaitTime value will slow
++down the indexing process, and lowering the value will speed it up.
++A value of zero causes the fastest possible indexing. Removing the
++ini parameter altogether returns it to the default (20).
++
++Crashes have been known to occur with certain types of history
++bookmarks. If the Notes client seems to crash randomly, try
++disabling the 'Index note history' option. If it crashes before,
++you can get to the preferences, add the following line to your
++notes.ini file:
++GDSNoIndexHistory=1
+diff --git a/tools/grit/grit/testdata/about.html b/tools/grit/grit/testdata/about.html
+new file mode 100644
+index 0000000000..8e5fad7b2b
+--- /dev/null
++++ b/tools/grit/grit/testdata/about.html
+@@ -0,0 +1,45 @@
++[HEADER]
++<table cellspacing=0 cellPadding=0 width="100%" border=0><tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr></table>
++<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0><tr><td height=20><font size=+1 color=#000000>&nbsp;<b>[TITLE]</b></font></td></tr></table>
++<br><center><span style="line-height:16pt"><font color=#335cec><B>Google Desktop Search: Search your own computer.</B></font></span></center><br>
++
++<table cellspacing=1 cellpadding=0 width=300 align=center border=0>
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="outlook.gif" width=16>&nbsp;&nbsp;Outlook Email</font></td>
++<td nowrap>&nbsp;</td>
++<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="netscape.gif" width=16>&nbsp;&nbsp;Netscape Mail / Thunderbird</font></td></tr>
++
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="oe.gif" width=16>&nbsp;&nbsp;Outlook Express</font></td>
++<td nowrap>&nbsp;</td>
++<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ff.gif" width=16>&nbsp;&nbsp;Netscape / Firefox / Mozilla</font></td></tr>
++
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="doc.gif" width=16>&nbsp;&nbsp;Word</font></td>
++<td nowrap>&nbsp;</td>
++<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="pdf.gif" width=16>&nbsp;&nbsp;PDF</font></td></tr>
++
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="xls.gif" width=16>&nbsp;&nbsp;Excel</font></td>
++<td nowrap>&nbsp;</td>
++<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mus.gif" width=16>&nbsp;&nbsp;Music</font></td></tr>
++
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ppt.gif" width=16>&nbsp;&nbsp;PowerPoint</font></td>
++<td nowrap>&nbsp;</td>
++<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="jpg.gif" width=16>&nbsp;&nbsp;Images</font></td></tr>
++
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ie.gif" width=16>&nbsp;&nbsp;Internet Explorer</font></td>
++<td nowrap>&nbsp;</td>
++<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mov.gif" width=16>&nbsp;&nbsp;Video</font></td></tr>
++
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="aim.gif" width=16>&nbsp;&nbsp;AOL Instant Messenger</font></td>
++<td nowrap>&nbsp;</td>
++<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="other.gif" width=16>&nbsp;&nbsp;Even more with <a href="http://desktop.google.com/plugins.html">these plug-ins</A></font></td></tr>
++
++<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="txt.gif" width=16>&nbsp;&nbsp;Text and others</font></td></tr>
++</table>
++<center>
++<p><table cellpadding=1>
++<tr><td><a href="http://desktop.google.com/gettingstarted.html?hl=[LANG_CODE]"><B>Getting Started</B></A> - Learn more about using Google Desktop Search</td></tr>
++<tr><td><a href="http://desktop.google.com/help.html?hl=[LANG_CODE]"><B>Online Help</B></A> - Up-to-date answers to your questions</td></tr>
++<tr><td><a href="[$~PRIVACY~$]"><B>Privacy</B></A> - A few words about privacy and Google Desktop Search</td></tr>
++<tr><td><a href="http://desktop.google.com/uninstall.html?hl=[LANG_CODE]"><B>Uninstall</B></A> - How to uninstall Google Desktop Search</td></tr>
++<tr><td><a href="http://desktop.google.com/feedback.html?hl=[LANG_CODE]"><B>Submit Feedback</B></A> - Send us your comments and ideas</td></tr>
++</table><br><font size=-2>Google Desktop Search [$~BUILDNUMBER~$]</font><br><br>
++[FOOTER]
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/android.xml b/tools/grit/grit/testdata/android.xml
+new file mode 100644
+index 0000000000..cc3b141f70
+--- /dev/null
++++ b/tools/grit/grit/testdata/android.xml
+@@ -0,0 +1,24 @@
++<!--
++ Copyright (c) 2012 The Chromium Authors. All rights reserved.
++ Use of this source code is governed by a BSD-style license that can be
++ found in the LICENSE file.
++-->
++
++<resources>
++ <!-- A string with placeholder. -->
++ <string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" name="placeholders">
++ Open <xliff:g id="FILENAME" example="internet.html">%s</xliff:g>?
++ </string>
++
++ <!-- A simple string. -->
++ <string name="simple">A simple string.</string>
++
++ <!-- A string with a comment. -->
++ <string name="comment">Contains a <!-- ignore this --> comment. </string>
++
++ <!-- A second simple string. -->
++ <string name="simple2"> Another simple string. </string>
++
++ <!-- A non-translatable string. -->
++ <string name="constant" translatable="false">Do not translate me.</string>
++</resources>
+diff --git a/tools/grit/grit/testdata/bad_browser.html b/tools/grit/grit/testdata/bad_browser.html
+new file mode 100644
+index 0000000000..e8cf34664d
+--- /dev/null
++++ b/tools/grit/grit/testdata/bad_browser.html
+@@ -0,0 +1,16 @@
++<p><b>We're sorry, but we don't seem to be compatible.</b></p>
++<p><font size="-1">Our software suggests that you're using a browser incompatible with Google Desktop Search.
++ Google Desktop Search currently supports the following:</font></p>
++<ul><font size="-1">
++ <li>Microsoft IE 5 and newer (<a href="http://www.microsoft.com/windows/ie/downloads/default.asp">Download</a>)</li>
++ <li>Mozilla (<a href="http://www.mozilla.org/products/mozilla1.x/">Download</a>)</li>
++ <li>Mozilla Firefox (<a href="http://www.mozilla.org/products/firefox/">Download</a>)</li>
++ <li>Netscape 7 and newer (<a href="http://channels.netscape.com/ns/browsers/download.jsp">Download</a>)</li>
++</font></ul>
++
++<p><font size="-1">You may <a href="[REDIR]">click here</a> to use your
++ unsupported browser, though you likely will encounter some areas that don't
++ work as expected. You need to have Javascript enabled, regardless of the
++ browser you use.</font>
++<p><font size="-1">We hope to expand this list in the near future and announce new
++ browsers as they become available.
+diff --git a/tools/grit/grit/testdata/browser.html b/tools/grit/grit/testdata/browser.html
+new file mode 100644
+index 0000000000..45d364d56f
+--- /dev/null
++++ b/tools/grit/grit/testdata/browser.html
+@@ -0,0 +1,42 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>[$~TITLE~$]</title>
++<style>
++BODY { MARGIN-LEFT: 1em; MARGIN-RIGHT: 1em }
++BODY, TD, DIV, A { FONT-FAMILY: arial,sans-serif}
++DIV, TD { COLOR: #000}
++A:link { COLOR: #00c}
++A:visited { COLOR: #551a8b}
++A:active { COLOR: #f00 }
++</style>
++</head>
++
++<body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#800080" alink="#ff0000" topmargin=2>
++
++<table cellspacing=2 cellpadding=0 width="99%" border=0>
++<tr>
++ <td width="1%" rowspan=2>[$~IMAGE~$]
++ <td>&nbsp;</td>
++ <td rowspan=2>
++ <table cellspacing=0 cellpadding=0 width="100%" border=0>
++ <tr>
++ <td bgcolor=#3399cc><img height=1 width=1></td>
++ </tr>
++ </table>
++ <table cellspacing=0 cellpadding=0 width="100%" border=0 bgcolor=#efefef>
++ <tr>
++ <td nowrap bgcolor=#E8F4F7><font face=arial,sans-serif color=#000000 size=+1><b>&nbsp;[$~CHROME_TITLE~$]</b></font></td>
++ </tr>
++ </table>
++ </td>
++</tr>
++</table>
++
++<table cellpadding=3 width="94%" align="center" cellspacing=0 border=0>
++<tr valign="middle">
++ <td valign="top">
++ [$~BODY~$]
++ </td>
++ </tr>
++</table>
++[$~FOOTER~$]
++</body></html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/buildinfo.grd b/tools/grit/grit/testdata/buildinfo.grd
+new file mode 100644
+index 0000000000..80458a8265
+--- /dev/null
++++ b/tools/grit/grit/testdata/buildinfo.grd
+@@ -0,0 +1,46 @@
++<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
++<grit
++ base_dir="."
++ source_lang_id="en"
++ tc_project="GoogleDesktopWindowsClient"
++ latest_public_release="0"
++ current_release="1"
++ enc_check="möl">
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
++ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
++ </outputs>
++ <translations>
++ <file path="substitute.xmb" lang="sv" />
++ </translations>
++ <release seq="1" allow_pseudo="false">
++ <includes>
++ <include type="BITMAP" name="IDB_PR" file="pr.bmp" />
++ <if expr="lang == 'sv'">
++ <include type="BITMAP" name="IDB_PR2" file="pr2.bmp" />
++ </if>
++ </includes>
++ <structures>
++ <structure name="SIDEBAR_LOADING.HTML" encoding="utf-8" file="sidebar_loading.html" type="tr_html" generateid="false" expand_variables="false"/>
++ <structure name="IDS_PLACEHOLDER" file="transl.rc" type="dialog" >
++ <skeleton expr="lang == 'sv'" file="transl1.rc" variant_of_revision="1"/>
++ </structure>
++ <if expr="lang != 'sv'">
++ <structure name="WELCOME_TOAST.HTML" encoding="utf-8" file="welcome_toast.html" type="tr_html" generateid="false" expand_variables="true"/>
++ </if>
++ </structures>
++ <messages first_id="8192">
++ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
++ Copyright 2008 Google Inc. All Rights Reserved.
++ </message>
++ <message name="IDS_NEWS_PANEL_COPYRIGHT">
++ Google Desktop News gadget
++[IDS_COPYRIGHT_GOOGLE_LONG]
++View news that is personalized based on the articles you read.
++
++For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
++ </message>
++ </messages>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/testdata/cache_prefix.html b/tools/grit/grit/testdata/cache_prefix.html
+new file mode 100644
+index 0000000000..b1f91dd82b
+--- /dev/null
++++ b/tools/grit/grit/testdata/cache_prefix.html
+@@ -0,0 +1,24 @@
++<head>
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++</head>
++<body onload="[ONLOAD]">
++<table width="100%" border=1><tr><td>
++<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
++<tr><td><font face="arial,sans-serif" color=black size=-1>This is one version of <a href="[$~URL~$]">
++<font color="blue">[URL-DISP]</font></a> from your personal <a href="http://desktop.google.com/webcache.html"><font color=blue>cache</font></a>.<br>
++The page may have changed since that time. Click here for the <a href="[$~URL~$]"><font color="blue">current page</font></a>.<br>
++Since this page is stored on your computer, publicly linking to this page will not work.[$~EXTRA~$]<br><br>
++<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
++</td>
++</tr></table></td></tr></table>
++<style>
++.hl { color:black; background-color:#ffff88}
++</style>
++<script>
++[$~HIGHLIGHT_SCRIPT~$]
++window.onerror=new Function(';');
++</script>
++<hr id=gg_1>
++</body>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/cache_prefix_file.html b/tools/grit/grit/testdata/cache_prefix_file.html
+new file mode 100644
+index 0000000000..f3eb8e0f11
+--- /dev/null
++++ b/tools/grit/grit/testdata/cache_prefix_file.html
+@@ -0,0 +1,25 @@
++<head>
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1"></head>
++<body onload="[ONLOAD]">
++<table width="100%" border=1>
++<tr><td>
++<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
++<tr><td><font face=arial,sans-serif color=black size=-1>This is one version of <a href="[$~URL~$]"><font color=blue>[URL-DISP]</font></a>
++from your personal <a href="http://desktop.google.com/filecache.html"><font color=blue>cache</font></a>.<br>
++The file may have changed since that time. Click here for the <a href="[$~URL~$]"><font color=blue>current file</font></a>.<br>
++Since this file is stored on your computer, publicly linking to it will not work.[$~EXTRA~$]<br><br>
++<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
++</td></tr>
++</table>
++</td></tr></table>
++<style>
++.hl { color:black; background-color:#ffff88}
++</style>
++<script>
++[$~HIGHLIGHT_SCRIPT~$]
++window.onerror=new Function(';');
++</script>
++<hr id=gg_1>
++</body>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/chat_result.html b/tools/grit/grit/testdata/chat_result.html
+new file mode 100644
+index 0000000000..318078bc3d
+--- /dev/null
++++ b/tools/grit/grit/testdata/chat_result.html
+@@ -0,0 +1,24 @@
++[HEADER]
++[CHROME]
++<table border=0 cellpadding=2 cellspacing=2>
++<tr><td>[$~STARTCHAT~$]</td></tr>
++</table>
++<blockquote id=gg_1>
++<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
++<img style="vertical-align:middle;" height=16 src="16x16_chat.gif" width=16> &nbsp; <b>[$~TITLE~$]</b>
++<font size=-1><br><br>Participants: [USERNAME], [BUDDYNAME]<br>
++Date: [TIME]</font></td></tr></table>
++<br id=contents>
++<label>[CONTENTS]</label>
++</blockquote>
++<table border=0 cellpadding=2 cellspacing=2>
++<tr><td>[$~STARTCHAT~$]</td></tr>
++</table>
++<style>
++.hl { color:black; background-color:#ffff88}
++</style>
++<script>
++[$~HIGHLIGHT_SCRIPT~$]
++[ONLOAD]
++</script>
++[FOOTER]
+diff --git a/tools/grit/grit/testdata/chrome/app/generated_resources.grd b/tools/grit/grit/testdata/chrome/app/generated_resources.grd
+new file mode 100644
+index 0000000000..c2efb77fd8
+--- /dev/null
++++ b/tools/grit/grit/testdata/chrome/app/generated_resources.grd
+@@ -0,0 +1,199 @@
++<?xml version="1.0" encoding="UTF-8"?>
++
++<!--
++This file contains definitions of resources that will be translated for each
++locale. The variables is_win, is_macosx, is_linux, and is_posix are available
++for making strings OS specific. Other platform defines such as use_titlecase
++are declared in build/common.gypi.
++-->
++
++<grit base_dir="." latest_public_release="0" current_release="1"
++ source_lang_id="en" enc_check="möl">
++ <outputs>
++ <output filename="grit/generated_resources.h" type="rc_header">
++ <emit emit_type='prepend'></emit>
++ </output>
++ <output filename="generated_resources_am.pak" type="data_package" lang="am" />
++ <output filename="generated_resources_ar.pak" type="data_package" lang="ar" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_ast.pak" type="data_package" lang="ast" />
++ </if>
++ <output filename="generated_resources_bg.pak" type="data_package" lang="bg" />
++ <output filename="generated_resources_bn.pak" type="data_package" lang="bn" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_bs.pak" type="data_package" lang="bs" />
++ </if>
++ <output filename="generated_resources_ca.pak" type="data_package" lang="ca" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_ca@valencia.pak" type="data_package" lang="ca@valencia" />
++ </if>
++ <output filename="generated_resources_cs.pak" type="data_package" lang="cs" />
++ <output filename="generated_resources_da.pak" type="data_package" lang="da" />
++ <output filename="generated_resources_de.pak" type="data_package" lang="de" />
++ <output filename="generated_resources_el.pak" type="data_package" lang="el" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_en-AU.pak" type="data_package" lang="en-AU" />
++ </if>
++ <output filename="generated_resources_en-GB.pak" type="data_package" lang="en-GB" />
++ <output filename="generated_resources_en-US.pak" type="data_package" lang="en" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_eo.pak" type="data_package" lang="eo" />
++ </if>
++ <output filename="generated_resources_es.pak" type="data_package" lang="es" />
++ <output filename="generated_resources_es-419.pak" type="data_package" lang="es-419" />
++ <output filename="generated_resources_et.pak" type="data_package" lang="et" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_eu.pak" type="data_package" lang="eu" />
++ </if>
++ <output filename="generated_resources_fa.pak" type="data_package" lang="fa" />
++ <output filename="generated_resources_fake-bidi.pak" type="data_package" lang="fake-bidi" />
++ <output filename="generated_resources_fi.pak" type="data_package" lang="fi" />
++ <output filename="generated_resources_fil.pak" type="data_package" lang="fil" />
++ <output filename="generated_resources_fr.pak" type="data_package" lang="fr" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_gl.pak" type="data_package" lang="gl" />
++ </if>
++ <output filename="generated_resources_gu.pak" type="data_package" lang="gu" />
++ <output filename="generated_resources_he.pak" type="data_package" lang="he" />
++ <output filename="generated_resources_hi.pak" type="data_package" lang="hi" />
++ <output filename="generated_resources_hr.pak" type="data_package" lang="hr" />
++ <output filename="generated_resources_hu.pak" type="data_package" lang="hu" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_hy.pak" type="data_package" lang="hy" />
++ <output filename="generated_resources_ia.pak" type="data_package" lang="ia" />
++ </if>
++ <output filename="generated_resources_id.pak" type="data_package" lang="id" />
++ <output filename="generated_resources_it.pak" type="data_package" lang="it" />
++ <output filename="generated_resources_ja.pak" type="data_package" lang="ja" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_ka.pak" type="data_package" lang="ka" />
++ </if>
++ <output filename="generated_resources_kn.pak" type="data_package" lang="kn" />
++ <output filename="generated_resources_ko.pak" type="data_package" lang="ko" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_ku.pak" type="data_package" lang="ku" />
++ <output filename="generated_resources_kw.pak" type="data_package" lang="kw" />
++ </if>
++ <output filename="generated_resources_lt.pak" type="data_package" lang="lt" />
++ <output filename="generated_resources_lv.pak" type="data_package" lang="lv" />
++ <output filename="generated_resources_ml.pak" type="data_package" lang="ml" />
++ <output filename="generated_resources_mr.pak" type="data_package" lang="mr" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_ms.pak" type="data_package" lang="ms" />
++ </if>
++ <output filename="generated_resources_nl.pak" type="data_package" lang="nl" />
++ <!-- The translation console uses 'no' for Norwegian Bokmål. It should
++ be 'nb'. -->
++ <output filename="generated_resources_nb.pak" type="data_package" lang="no" />
++ <output filename="generated_resources_pl.pak" type="data_package" lang="pl" />
++ <output filename="generated_resources_pt-BR.pak" type="data_package" lang="pt-BR" />
++ <output filename="generated_resources_pt-PT.pak" type="data_package" lang="pt-PT" />
++ <output filename="generated_resources_ro.pak" type="data_package" lang="ro" />
++ <output filename="generated_resources_ru.pak" type="data_package" lang="ru" />
++ <output filename="generated_resources_sk.pak" type="data_package" lang="sk" />
++ <output filename="generated_resources_sl.pak" type="data_package" lang="sl" />
++ <output filename="generated_resources_sr.pak" type="data_package" lang="sr" />
++ <output filename="generated_resources_sv.pak" type="data_package" lang="sv" />
++ <output filename="generated_resources_sw.pak" type="data_package" lang="sw" />
++ <output filename="generated_resources_ta.pak" type="data_package" lang="ta" />
++ <output filename="generated_resources_te.pak" type="data_package" lang="te" />
++ <output filename="generated_resources_th.pak" type="data_package" lang="th" />
++ <output filename="generated_resources_tr.pak" type="data_package" lang="tr" />
++ <if expr="pp_ifdef('use_third_party_translations')">
++ <output filename="generated_resources_ug.pak" type="data_package" lang="ug" />
++ </if>
++ <output filename="generated_resources_uk.pak" type="data_package" lang="uk" />
++ <output filename="generated_resources_vi.pak" type="data_package" lang="vi" />
++ <output filename="generated_resources_zh-CN.pak" type="data_package" lang="zh-CN" />
++ <output filename="generated_resources_zh-TW.pak" type="data_package" lang="zh-TW" />
++ </outputs>
++ <translations>
++ <file path="resources/generated_resources_am.xtb" lang="am" />
++ <file path="resources/generated_resources_ar.xtb" lang="ar" />
++ <file path="../../third_party/launchpad_translations/generated_resources_ast.xtb" lang="ast" />
++ <file path="resources/generated_resources_bg.xtb" lang="bg" />
++ <file path="resources/generated_resources_bn.xtb" lang="bn" />
++ <file path="../../third_party/launchpad_translations/generated_resources_bs.xtb" lang="bs" />
++ <file path="resources/generated_resources_ca.xtb" lang="ca" />
++ <file path="../../third_party/launchpad_translations/generated_resources_ca-valencia.xtb" lang="ca@valencia" />
++ <file path="resources/generated_resources_cs.xtb" lang="cs" />
++ <file path="resources/generated_resources_da.xtb" lang="da" />
++ <file path="resources/generated_resources_de.xtb" lang="de" />
++ <file path="resources/generated_resources_el.xtb" lang="el" />
++ <file path="../../third_party/launchpad_translations/generated_resources_en-AU.xtb" lang="en-AU" />
++ <file path="resources/generated_resources_en-GB.xtb" lang="en-GB" />
++ <file path="../../third_party/launchpad_translations/generated_resources_eo.xtb" lang="eo" />
++ <file path="resources/generated_resources_es.xtb" lang="es" />
++ <file path="resources/generated_resources_es-419.xtb" lang="es-419" />
++ <file path="resources/generated_resources_et.xtb" lang="et" />
++ <file path="../../third_party/launchpad_translations/generated_resources_eu.xtb" lang="eu" />
++ <file path="resources/generated_resources_fa.xtb" lang="fa" />
++ <file path="resources/generated_resources_fi.xtb" lang="fi" />
++ <file path="resources/generated_resources_fil.xtb" lang="fil" />
++ <file path="resources/generated_resources_fr.xtb" lang="fr" />
++ <file path="../../third_party/launchpad_translations/generated_resources_gl.xtb" lang="gl" />
++ <file path="resources/generated_resources_gu.xtb" lang="gu" />
++ <file path="resources/generated_resources_hi.xtb" lang="hi" />
++ <file path="resources/generated_resources_hr.xtb" lang="hr" />
++ <file path="resources/generated_resources_hu.xtb" lang="hu" />
++ <file path="../../third_party/launchpad_translations/generated_resources_hy.xtb" lang="hy" />
++ <file path="../../third_party/launchpad_translations/generated_resources_ia.xtb" lang="ia" />
++ <file path="resources/generated_resources_id.xtb" lang="id" />
++ <file path="resources/generated_resources_it.xtb" lang="it" />
++ <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
++ <file path="resources/generated_resources_iw.xtb" lang="he" />
++ <file path="resources/generated_resources_ja.xtb" lang="ja" />
++ <file path="../../third_party/launchpad_translations/generated_resources_ka.xtb" lang="ka" />
++ <file path="resources/generated_resources_kn.xtb" lang="kn" />
++ <file path="resources/generated_resources_ko.xtb" lang="ko" />
++ <file path="../../third_party/launchpad_translations/generated_resources_ku.xtb" lang="ku" />
++ <file path="../../third_party/launchpad_translations/generated_resources_kw.xtb" lang="kw" />
++ <file path="resources/generated_resources_lt.xtb" lang="lt" />
++ <file path="resources/generated_resources_lv.xtb" lang="lv" />
++ <file path="resources/generated_resources_ml.xtb" lang="ml" />
++ <file path="resources/generated_resources_mr.xtb" lang="mr" />
++ <file path="../../third_party/launchpad_translations/generated_resources_ms.xtb" lang="ms" />
++ <file path="resources/generated_resources_nl.xtb" lang="nl" />
++ <file path="resources/generated_resources_no.xtb" lang="no" />
++ <file path="resources/generated_resources_pl.xtb" lang="pl" />
++ <file path="resources/generated_resources_pt-BR.xtb" lang="pt-BR" />
++ <file path="resources/generated_resources_pt-PT.xtb" lang="pt-PT" />
++ <file path="resources/generated_resources_ro.xtb" lang="ro" />
++ <file path="resources/generated_resources_ru.xtb" lang="ru" />
++ <file path="resources/generated_resources_sk.xtb" lang="sk" />
++ <file path="resources/generated_resources_sl.xtb" lang="sl" />
++ <file path="resources/generated_resources_sr.xtb" lang="sr" />
++ <file path="resources/generated_resources_sv.xtb" lang="sv" />
++ <file path="resources/generated_resources_sw.xtb" lang="sw" />
++ <file path="resources/generated_resources_ta.xtb" lang="ta" />
++ <file path="resources/generated_resources_te.xtb" lang="te" />
++ <file path="resources/generated_resources_th.xtb" lang="th" />
++ <file path="resources/generated_resources_tr.xtb" lang="tr" />
++ <file path="../../third_party/launchpad_translations/generated_resources_ug.xtb" lang="ug" />
++ <file path="resources/generated_resources_uk.xtb" lang="uk" />
++ <file path="resources/generated_resources_vi.xtb" lang="vi" />
++ <file path="resources/generated_resources_zh-CN.xtb" lang="zh-CN" />
++ <file path="resources/generated_resources_zh-TW.xtb" lang="zh-TW" />
++ </translations>
++ <release seq="1" allow_pseudo="false">
++ <messages fallback_to_english="true">
++ <!-- TODO add all of your "string table" messages here. Remember to
++ change nontranslateable parts of the messages into placeholders (using the
++ <ph> element). You can also use the 'grit add' tool to help you identify
++ nontranslateable parts and create placeholders for them. -->
++ <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_TITLE" desc="The title of the balloon that is displayed when a background app is installed">
++ New background app installed
++ </message>
++ <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY" desc="The contents of the balloon that is displayed when a background app is installed">
++ <ph name="APP_NAME">$1<ex>Background App</ex></ph> will launch at system startup and continue to run in the background even once you've closed all other <ph name="PRODUCT_NAME">$2<ex>Google Chrome</ex></ph> windows.
++ </message>
++ </messages>
++ <structures fallback_to_english="true">
++ <!-- Make sure these stay in sync with the structures in generated_resources.grd. -->
++ <structure name="IDD_CHROME_FRAME_FIND_DIALOG" file="cf_resources.rc" type="dialog" >
++ </structure>
++ <structure name="IDD_CHROME_FRAME_READY_PROMPT" file="cf_resources.rc" type="dialog" >
++ </structure>
++ </structures>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/testdata/chrome_html.html b/tools/grit/grit/testdata/chrome_html.html
+new file mode 100644
+index 0000000000..7f7633c5cf
+--- /dev/null
++++ b/tools/grit/grit/testdata/chrome_html.html
+@@ -0,0 +1,6 @@
++<include src="included_sample.html">
++<style type="text/css">
++#image {
++ content: url('chrome://theme/IDR_SOME_FILE');
++}
++</style>
+diff --git a/tools/grit/grit/testdata/default_100_percent/a.png b/tools/grit/grit/testdata/default_100_percent/a.png
+new file mode 100644
+index 0000000000000000000000000000000000000000..5d5089038ca71172e95db9e7aae1e1fa5cebd505
+GIT binary patch
+literal 159
+zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>0wld=oSO}#(mY)pLnNjq|2Y3)zGGzYPN&L+
+zMSC}CcCfp=Dtxv4%6W%G#Q=|R|L;6pCCLUWO)Z<5eoL%TkDTw=s4X!^d(Qa<2khAN
+zZPy!XToBAic1Ss}vcWiD27B3&`Zj^H6CO>7R1{ToQ;=ggdEYbV=IISvfHpFCy85}S
+Ib4q9e0O9jEh5!Hn
+
+literal 0
+HcmV?d00001
+
+diff --git a/tools/grit/grit/testdata/default_100_percent/b.png b/tools/grit/grit/testdata/default_100_percent/b.png
+new file mode 100644
+index 0000000000..6178079822
+--- /dev/null
++++ b/tools/grit/grit/testdata/default_100_percent/b.png
+@@ -0,0 +1 @@
++b
+diff --git a/tools/grit/grit/testdata/del_footer.html b/tools/grit/grit/testdata/del_footer.html
+new file mode 100644
+index 0000000000..4e19950bfc
+--- /dev/null
++++ b/tools/grit/grit/testdata/del_footer.html
+@@ -0,0 +1,8 @@
++<table cellspacing=0 cellpadding=2 width="100%" border=0>
++<tr bgcolor=#EFEFEF><td><font size=-1>&nbsp;<b>Remove</b> checked results and <b>return to search</b>.</font></td>
++<td align=right><font size=-1><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">Uncheck all</a>&nbsp;&nbsp;</font></td>
++<td align=right width=1% nowrap><font size=-1>
++<input onclick=deleting() type=submit value="Remove checked results" name=submit2>
++</font></td></tr></table>
++<center><br><font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
++</body></html>
+diff --git a/tools/grit/grit/testdata/del_header.html b/tools/grit/grit/testdata/del_header.html
+new file mode 100644
+index 0000000000..72bc6756eb
+--- /dev/null
++++ b/tools/grit/grit/testdata/del_header.html
+@@ -0,0 +1,60 @@
++<body bgcolor="#ffffff" topmargin="2" marginheight="2">
++<table cellSpacing="2" cellPadding="0" width="100%" border="0">
++<form action='[$~DELETE~$]' method="post" name="delform">
++<input name="redir" type="hidden" value="[REDIR]">
++<script>
++<!--
++function deleting() {
++f=document.getElementsByName("del");
++var num = 0;
++if (f.length)
++ for(i=0;i<f.length; i++)
++ if(f[i].checked) num++;
++ if (num == 1) alert("One checked result has been removed");
++ else if (num > 1) alert(num + " checked results have been removed");
++ else alert("No results were checked, so no results have been removed");
++}
++function checkall(v) {
++ f=document.getElementsByName("del");
++ if (f.length)
++ for(i=0;i<f.length; i++)
++ f[i].checked=v;
++}
++//-->
++</script>
++<tr>
++<td vAlign="top" width="1%"><A href='[$~HOMEPAGE~$]'> <img alt="Go to Google Desktop Search" width="150" height="55" src="/logo3.gif" border="0" vspace="12"></A></td>
++<td>&nbsp;</td>
++<td noWrap>
++ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
++ <tr>
++ <td bgColor="#DD0000"><img height="1" alt="" width="1"></td>
++ </tr>
++ </table>
++ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
++ <tr>
++ <td noWrap bgColor="#efefef"><font size="+1"><b>&nbsp;Remove Specific Items</b></font></td>
++ <td noWrap align="right" bgColor="#efefef"><font size="-1"><a href="http://desktop.google.com/remove.html">Help</a>&nbsp;&nbsp;</font></td>
++ </tr>
++ </table>
++</td>
++</tr>
++</table>
++<table cellSpacing="0" cellPadding="2" width="100%" border="0">
++<tr bgColor="#EFEFEF">
++<td><font size="-1">&nbsp;<B>Remove</B> checked results and <B>return to search</B>.</font></td>
++<td align="right"><font size="-1"><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">
++Uncheck all</a>&nbsp;&nbsp;</font></td>
++<td align="right" width="1%" nowrap><font size="-1"><input onclick="deleting()" type="submit" value="Remove checked results" name="submit2"></font></td>
++</tr>
++</table>
++<br>
++<table cellspacing="0" cellpadding="2" width="100%" border="0">
++<tr>
++<td colSpan="3" bgcolor="#FFFFFF" style="border:solid; border-width:1px; border-color:#DD0000"><font size="-1">&nbsp;<b>Remove
++checked items from Google Desktop Search. Other copies of the same items will not be
++affected.<br>
++&nbsp;If you view the item again, it will be added back to Google Desktop Search.</b></font></td>
++</tr>
++</table>
++<br>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/deleted.html b/tools/grit/grit/testdata/deleted.html
+new file mode 100644
+index 0000000000..5ae5f355fa
+--- /dev/null
++++ b/tools/grit/grit/testdata/deleted.html
+@@ -0,0 +1,21 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Database Deleted</title>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
++.q {COLOR: #0000cc}
++</style>
++</head>
++<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
++<center>
++<TABLE cellSpacing=0 cellPadding=0 border=0>
++<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a>
++</td></tr></table><BR>
++<center>The database has been deleted. Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
++</td></tr>
++</table>
++<br><FONT size=-1>[$~BOTTOMLINE~$]</font></p>
++<p><FONT size=-2>&copy;2005 Google</font></p></center></body></html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/depfile.grd b/tools/grit/grit/testdata/depfile.grd
+new file mode 100644
+index 0000000000..e2f7191218
+--- /dev/null
++++ b/tools/grit/grit/testdata/depfile.grd
+@@ -0,0 +1,18 @@
++<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
++<grit
++ base_dir="."
++ latest_public_release="0"
++ current_release="1">
++ <outputs>
++ <output filename="default_100_percent.pak" lang="en" type="data_package" context="default_100_percent" />
++ <output filename="special_100_percent.pak" lang="en" type="data_package" context="special_100_percent" />
++ </outputs>
++ <release seq="1">
++ <structures fallback_to_low_resolution="true">
++ <if expr="False">
++ <part file="grit_part.grdp" />
++ </if>
++ <structure type="chrome_scaled_image" name="IDR_A" file="a.png" />
++ </structures>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/testdata/details.html b/tools/grit/grit/testdata/details.html
+new file mode 100644
+index 0000000000..0ab0e2a90c
+--- /dev/null
++++ b/tools/grit/grit/testdata/details.html
+@@ -0,0 +1,10 @@
++[!]
++title Improve Google Desktop Search by Sending Non-Personal Information
++template
++bottomline
++hp_image
++
++<p><strong>This documentation is not yet available</strong></p>
++<center><br>
++<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font>
++</center>
+diff --git a/tools/grit/grit/testdata/duplicate-name-input.xml b/tools/grit/grit/testdata/duplicate-name-input.xml
+new file mode 100644
+index 0000000000..cc4d1d65c5
+--- /dev/null
++++ b/tools/grit/grit/testdata/duplicate-name-input.xml
+@@ -0,0 +1,26 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
++ <release seq="3">
++ <messages>
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ </messages>
++ <structures>
++ <!-- Duplicate name here -->
++ <structure type="version" name="IDS_GREETING" file="rc_files/bla.rc" />
++ </structures>
++ </release>
++ <translations>
++ <file path="figs_nl_translations.xml" />
++ <file path="cjk_translations.xml" />
++ </translations>
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="resource_en.rc" type="rc_all" lang="en-US" />
++ <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
++ <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
++ <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
++ <output filename="nontranslateable.rc" type="rc_nontranslateable" />
++ </outputs>
++</grit>
+diff --git a/tools/grit/grit/testdata/email_result.html b/tools/grit/grit/testdata/email_result.html
+new file mode 100644
+index 0000000000..8bb04b988c
+--- /dev/null
++++ b/tools/grit/grit/testdata/email_result.html
+@@ -0,0 +1,34 @@
++[HEADER]
++[CHROME]
++<table border=0 cellpadding=2 cellspacing=2 width='100%'>
++<tr><td><font size=-1>[CONV]
++<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
++</font></td></tr>
++</table>
++<blockquote id=gg_1>
++<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
++<img style="vertical-align:middle;" height=16 src='/email.gif' width=16> &nbsp; <b>[SUBJECT]</b>
++<p><font size=-1>[FROM-DISP]
++[TO-DISP]
++[CC-DISP]
++[BCC-DISP]
++[REPLYTO-DISP]
++[DATE-DISP]
++[VIEW-DISP]
++[$~ATTACH~$]
++</font></td></tr></table>
++<p class=g><span style="width:500;"><font size=-1><label>[MESSAGE]</label></span></p>
++</font>
++</blockquote>
++<table border=0 cellpadding=2 cellspacing=2 width='100%'>
++<tr><td><font size=-1>[CONV]
++<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
++</font></td></tr></table>
++<style>
++.hl { color:black; background-color:#ffff88}
++</style>
++<script>
++[$~HIGHLIGHT_SCRIPT~$]
++[ONLOAD]
++</script>
++[FOOTER]
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/email_thread.html b/tools/grit/grit/testdata/email_thread.html
+new file mode 100644
+index 0000000000..3c7279b841
+--- /dev/null
++++ b/tools/grit/grit/testdata/email_thread.html
+@@ -0,0 +1,10 @@
++[HEADER]
++[CHROME]
++<blockquote [MAXWIDTH]>
++<b><img src=email.gif style="vertical-align:middle;" width=16 height=16> &nbsp; [SUBJECT]</b><br><br>
++<TABLE cellSpacing=0 cellPadding=3 border=0>
++[CONTENTS]
++</table>
++</blockquote>
++[NEXT_PREV]
++[FOOTER]
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/error.html b/tools/grit/grit/testdata/error.html
+new file mode 100644
+index 0000000000..66875a234c
+--- /dev/null
++++ b/tools/grit/grit/testdata/error.html
+@@ -0,0 +1,8 @@
++[HEADER]
++[CHROME]
++<br>
++<blockquote>
++[ERROR]<br><br>
++If you think this is an error, please <a href="http://desktop.google.com/feedback.html?version=[VERSION]">contact us</a>.
++</blockquote>
++[FOOTER]
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/explicit_web.html b/tools/grit/grit/testdata/explicit_web.html
+new file mode 100644
+index 0000000000..1424adc617
+--- /dev/null
++++ b/tools/grit/grit/testdata/explicit_web.html
+@@ -0,0 +1,11 @@
++[HEADER]
++<style>
++.image {BORDER: #0000cc 1px solid;}
++.imageh {BORDER: #0000cc 1px solid;}
++</style>
++[WEB_TOP_CHROME]
++[$~STATUS~$]
++[$~MESSAGE~$]
++[WEB_FILES]
++<br>[NEXT_PREV]
++[FOOTER]
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/footer.html b/tools/grit/grit/testdata/footer.html
+new file mode 100644
+index 0000000000..3372d6afac
+--- /dev/null
++++ b/tools/grit/grit/testdata/footer.html
+@@ -0,0 +1,14 @@
++<center><br clear=all><br>
++<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table>
++<table cellspacing=0 cellpadding=0 width="100%" bgcolor=#e8f4f7 border=0>
++<tr bgcolor=#e8f4f7>
++<td><br>
++<table cellpadding=1 align=center border=0 cellspacing=0 bgcolor=#e8f4f7>
++<form action='[$~SEARCHURL~$]' method=get>
++<tr><td noWrap>[$~BOTTOM~$]</td></tr></form>
++</table><br>
++</td></tr></table>
++<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table><br>
++<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
++[SCRIPT]
++</body></html>
+diff --git a/tools/grit/grit/testdata/generated_resources_fr.xtb b/tools/grit/grit/testdata/generated_resources_fr.xtb
+new file mode 100644
+index 0000000000..373c40feea
+--- /dev/null
++++ b/tools/grit/grit/testdata/generated_resources_fr.xtb
+@@ -0,0 +1,3079 @@
++<?xml version="1.0" ?>
++<!DOCTYPE translationbundle>
++<translationbundle lang="fr">
++<translation id="1525924600121678168">Salut!</translation>
++<translation id="5335090254790956485">Salut <ph name="USERNAME"/></translation>
++<translation id="6779164083355903755">Supprime&amp;r</translation>
++<translation id="6879617193011158416">Activer la barre de favoris</translation>
++<translation id="8130276680150879341">Déconnexion du réseau privé</translation>
++<translation id="1058418043520174283"><ph name="INDEX"/> sur <ph name="COUNT"/></translation>
++<translation id="4480627574828695486">Déconnecter ce compte...</translation>
++<translation id="7040807039050164757">&amp;Vérifier l'orthographe dans ce champ</translation>
++<translation id="778579833039460630">Aucune donnée reçue.</translation>
++<translation id="1852799913675865625">Une erreur s'est produite lors de la tentative de lecture du fichier : <ph name="ERROR_TEXT"/>.</translation>
++<translation id="3828924085048779000">Le mot de passe multiterme est obligatoire.</translation>
++<translation id="8265562484034134517">Importer les données d'un autre navigateur...</translation>
++<translation id="2709516037105925701">Saisie automatique</translation>
++<translation id="4857138207355690859">API P2P</translation>
++<translation id="250599269244456932">Exécuter automatiquement (recommandé)</translation>
++<translation id="3581034179710640788">Le certificat de sécurité du site a expiré !</translation>
++<translation id="2825758591930162672">Clé publique de l'objet</translation>
++<translation id="8275038454117074363">Importer</translation>
++<translation id="8418445294933751433">Afficher dan&amp;s un onglet</translation>
++<translation id="6985276906761169321">ID :</translation>
++<translation id="859285277496340001">Le certificat n'indique aucun mécanisme permettant de vérifier s'il a été révoqué.</translation>
++<translation id="2010799328026760191">Touches de modification...</translation>
++<translation id="3300394989536077382">Signé par :</translation>
++<translation id="654233263479157500">Utiliser un service Web pour résoudre les erreurs de navigation</translation>
++<translation id="4940047036413029306">Guillemet</translation>
++<translation id="1526811905352917883">Une nouvelle tentative de connexion avec SSL 3.0 a dû être effectuée. Cette opération indique généralement que le serveur utilise un logiciel très ancien et qu'il est susceptible de présenter d'autres problèmes de sécurité.</translation>
++<translation id="1497897566809397301">Autoriser le stockage des données locales (recommandé)</translation>
++<translation id="3275778913554317645">Ouvrir dans une fenêtre</translation>
++<translation id="4553117311324416101">Google pense qu'un logiciel malveillant pourrait être installé sur votre ordinateur si vous continuez. Nous vous conseillons de ne pas continuer, même si vous avez déjà consulté ce site auparavant ou si vous avez confiance en celui-ci. Il se peut qu'il ait été piraté récemment. Réessayez demain ou utilisez un autre site.</translation>
++<translation id="509988127256758334">&amp;Rechercher :</translation>
++<translation id="1420684932347524586">Échec de génération de clé privée RSA aléatoire</translation>
++<translation id="2501173422421700905">Certificat en attente</translation>
++<translation id="2313634973119803790">Technologie réseau :</translation>
++<translation id="2382901536325590843">Le certificat du serveur ne figure pas dans le DNS.</translation>
++<translation id="2833791489321462313">Demander le mot de passe au retour de veille</translation>
++<translation id="3850258314292525915">Désactiver la synchronisation</translation>
++<translation id="2721561274224027017">Base de données indexée</translation>
++<translation id="8208216423136871611">Ne pas enregistrer</translation>
++<translation id="684587995079587263"><ph name="PRODUCT_NAME"/> synchronise vos données avec votre compte Google en toute sécurité. Synchronisez toutes vos données ou personnalisez les types de données synchronisées et les options de chiffrement.</translation>
++<translation id="4405141258442788789">Le délai imparti à l'opération est dépassé.</translation>
++<translation id="5048179823246820836">Nordique</translation>
++<translation id="1763046204212875858">Créer des raccourcis vers des applications</translation>
++<translation id="2105006017282194539">Pas encore chargé</translation>
++<translation id="524759338601046922">Confirmer le nouveau code PIN :</translation>
++<translation id="688547603556380205">L2TP/IPSec + Certificat utilisateur</translation>
++<translation id="777702478322588152">Préfecture</translation>
++<translation id="6562437808764959486">Extraction de l'image de récupération...</translation>
++<translation id="561349411957324076">Terminé</translation>
++<translation id="4764776831041365478">Il se peut que la page Web à l'adresse <ph name="URL"/> soit temporairement inaccessible ou qu'elle ait été déplacée de façon permanente à une autre adresse Web.</translation>
++<translation id="6156863943908443225">Cache des scripts</translation>
++<translation id="4610656722473172270">Barre d'outils Google</translation>
++<translation id="151501797353681931">Importés depuis Safari</translation>
++<translation id="6706684875496318067">Le plug-in <ph name="PLUGIN_NAME"/> n'est pas autorisé.</translation>
++<translation id="586567932979200359">Vous exécutez <ph name="PRODUCT_NAME"/> à partir de son image disque. Si vous l'installez sur votre ordinateur, vous pourrez l'utiliser sans image disque et bénéficierez de mises à jour automatiques.</translation>
++<translation id="3775432569830822555">Certificat du serveur SSL</translation>
++<translation id="1829192082282182671">Z&amp;oom arrière</translation>
++<translation id="6102827823267795198">Indique si la suggestion du moteur de recherche doit être entrée immédiatement via la saisie semi-automatique lorsque la fonctionnalité Recherche instantanée est activée.</translation>
++<translation id="1467071896935429871">Mise à jour du système : <ph name="PERCENT"/> % téléchargés</translation>
++<translation id="7881267037441701396">Les informations d'identification associées au partage de vos imprimantes via <ph name="CLOUD_PRINT_NAME"/> sont arrivées à expiration. Cliquez ici pour saisir à nouveau votre nom d'utilisateur et votre mot de passe.</translation>
++<translation id="816055135686411707">Erreur de définition du paramètre de confiance du certificat</translation>
++<translation id="4714531393479055912"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe.</translation>
++<translation id="5704565838965461712">Sélectionnez le certificat à présenter pour l'identification :</translation>
++<translation id="2025632980034333559"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour actualiser l'extension.</translation>
++<translation id="4059593000330943833">Compatibilité expérimentale avec des méthodes Wi-Fi Extensible Authentication Protocol supplémentaires, telles que EAP-TLS et LEAP.</translation>
++<translation id="6322279351188361895">Échec de lecture de la clé privée</translation>
++<translation id="3781072658385678636">Les plug-ins suivants ont été bloqués sur cette page :</translation>
++<translation id="4428782877951507641">Configuration de la synchronisation</translation>
++<translation id="3648460724479383440">Case d'option cochée</translation>
++<translation id="4654488276758583406">Très petite</translation>
++<translation id="6647228709620733774">URL de révocation de l'autorité de certification Netscape</translation>
++<translation id="546411240573627095">Style de pavé numérique</translation>
++<translation id="7663002797281767775">Active les feuilles de style CSS 3D et la composition graphique haute performance des pages Web via le processeur graphique.</translation>
++<translation id="2972581237482394796">&amp;Rétablir</translation>
++<translation id="5895138241574237353">Redémarrer</translation>
++<translation id="1858072074757584559">La connexion n'est pas compressée.</translation>
++<translation id="528468243742722775">Fin</translation>
++<translation id="1723824996674794290">&amp;Nouvelle fenêtre</translation>
++<translation id="1313405956111467313">Configuration automatique du proxy</translation>
++<translation id="1589055389569595240">Afficher l'orthographe et la grammaire</translation>
++<translation id="4364779374839574930">Aucune imprimante n'a été trouvée. Veuillez en installer une.</translation>
++<translation id="7017587484910029005">Saisissez les caractères visibles dans l'image ci-dessous.</translation>
++<translation id="9013589315497579992">Certificat d'authentification de client SSL incorrect</translation>
++<translation id="8595062045771121608">Le certificat du serveur ou un certificat AC intermédiaire présenté au navigateur a été signé avec un algorithme de signature faible tel que RSA-MD2. D'après des études récentes menées par des informaticiens, les algorithmes de signature seraient plus faibles qu'on ne le pensait jusqu'alors. Aujourd'hui, ils sont très rarement utilisés par les sites Web jugés dignes de confiance. Ce certificat a peut-être été contrefait. Nous vous déconseillons vivement de continuer.</translation>
++<translation id="8666632926482119393">Rechercher le précédent</translation>
++<translation id="7567293639574541773">I&amp;nspecter l'élément</translation>
++<translation id="8392896330146417149">État d'itinérance :</translation>
++<translation id="6813971406343552491">&amp;Non</translation>
++<translation id="36224234498066874">Effacer les données de navigation...</translation>
++<translation id="3384773155383850738">Nombre maximal de suggestions</translation>
++<translation id="8331498498435985864">L'accessibilité est désactivée.</translation>
++<translation id="8530339740589765688">Sélectionner par domaine</translation>
++<translation id="8677212948402625567">Tout réduire...</translation>
++<translation id="7600965453749440009">Ne jamais traduire les pages rédigées en <ph name="LANGUAGE"/> </translation>
++<translation id="3208703785962634733">Non confirmé</translation>
++<translation id="6523841952727744497">Avant de vous connecter, démarrez une session en tant qu'invité afin d'activer le réseau <ph name="NETWORK_ID"/>.</translation>
++<translation id="7450044767321666434">La gravure de l'image est terminée.</translation>
++<translation id="2653266418988778031">Si vous supprimez le certificat d'une autorité de certification, votre navigateur ne fera plus confiance aux certificats émis par cette autorité de certification.</translation>
++<translation id="298068999958468740">Synchronisez toutes les données de cet ordinateur ou sélectionnez celles que vous souhaitez synchroniser.</translation>
++<translation id="5341849548509163798"><ph name="NUMBER_MANY"/> hours ago</translation>
++<translation id="4422428420715047158">Domaine :</translation>
++<translation id="3602290021589620013">Aperçu</translation>
++<translation id="7516602544578411747">Associe chaque fenêtre du navigateur à un profil et ajoute une option de sélection des profils en haut à droite. Chaque profil possède ses propres favoris, extensions, applications, etc.</translation>
++<translation id="7082055294850503883">Ignorer le verrouillage des majuscules et saisir des minuscules par défaut</translation>
++<translation id="1800124151523561876">Aucune parole détectée</translation>
++<translation id="7814266509351532385">Changer de moteur de recherche par défaut</translation>
++<translation id="5376169624176189338">Cliquer pour revenir en arrière, maintenir pour voir l'historique</translation>
++<translation id="6310545596129886942"><ph name="NUMBER_FEW"/> secondes restantes</translation>
++<translation id="9181716872983600413">Unicode</translation>
++<translation id="1383861834909034572">Ouverture à la fin du téléchargement</translation>
++<translation id="5727728807527375859">Les extensions, les applications et les thèmes peuvent endommager votre ordinateur. Voulez-vous vraiment continuer ?</translation>
++<translation id="3857272004253733895">Schéma du pinyin double</translation>
++<translation id="1636842079139032947">Déconnecter ce compte...</translation>
++<translation id="6721972322305477112">&amp;Fichier</translation>
++<translation id="1076818208934827215">Microsoft Internet Explorer</translation>
++<translation id="9056810968620647706">Aucune correspondance trouvée</translation>
++<translation id="1901494098092085382">État de votre commentaire</translation>
++<translation id="2861301611394761800">Mise à jour terminée. Veuillez redémarrer le système.</translation>
++<translation id="2231238007119540260">Lorsque vous supprimez un certificat de serveur, vous rétablissez les contrôles de sécurité habituels du serveur et un certificat valide lui est demandé.</translation>
++<translation id="5463582782056205887">Essayez d'ajouter
++ <ph name="PRODUCT_NAME"/>
++ aux programmes autorisés dans les paramètres de votre pare-feu ou de votre antivirus. S'il
++ est déjà autorisé, tentez de le supprimer de la liste et de l'ajouter à nouveau à
++ la liste des programmes autorisés.</translation>
++<translation id="7624154074265342755">Réseaux sans fil</translation>
++<translation id="3315158641124845231">Masquer <ph name="PRODUCT_NAME"/></translation>
++<translation id="3496213124478423963">Zoom arrière</translation>
++<translation id="2296019197782308739">Méthode EAP :</translation>
++<translation id="42981349822642051">Développer</translation>
++<translation id="4013794286379809233">Veuillez vous connecter</translation>
++<translation id="7693221960936265065">de n'importe quand</translation>
++<translation id="1763138995382273070">Désactiver la validation des formulaires interactifs HTML5</translation>
++<translation id="4920887663447894854">Le suivi de votre position géographique sur cette page a été bloqué pour les sites suivants :</translation>
++<translation id="7690346658388844119">La gravure de l'image a été interrompue.</translation>
++<translation id="8133676275609324831">&amp;Afficher dans le dossier</translation>
++<translation id="645705751491738698">Continuer à bloquer JavaScript</translation>
++<translation id="4780321648949301421">Enregistrer la page sous...</translation>
++<translation id="9154072353677278078">Le serveur <ph name="DOMAIN"/> à l'adresse <ph name="REALM"/> requiert un nom d'utilisateur et un mot de passe.</translation>
++<translation id="2551191967044410069">Exceptions de géolocalisation</translation>
++<translation id="4092066334306401966">13px</translation>
++<translation id="8178665534778830238">Contenu :</translation>
++<translation id="153384433402665971">Le plug-in <ph name="PLUGIN_NAME"/> a été bloqué, car il n'est plus à jour.</translation>
++<translation id="2610260699262139870">Taille ré&amp;elle</translation>
++<translation id="4535734014498033861">Échec de la connexion au serveur proxy.</translation>
++<translation id="558170650521898289">Vérification de pilote matériel Microsoft Windows</translation>
++<translation id="98515147261107953">Paysage</translation>
++<translation id="8974161578568356045">Détecter automatiquement</translation>
++<translation id="1818606096021558659">Page</translation>
++<translation id="5388588172257446328">Nom d'utilisateur :</translation>
++<translation id="1657406563541664238">Nous aider à améliorer <ph name="PRODUCT_NAME"/> en envoyant automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
++<translation id="7982789257301363584">Réseau</translation>
++<translation id="8528962588711550376">Connexion en cours</translation>
++<translation id="2336228925368920074">Ajouter tous les onglets aux favoris...</translation>
++<translation id="4985312428111449076">Onglets ou fenêtres</translation>
++<translation id="7481475534986701730">Sites récemment consultés</translation>
++<translation id="4260722247480053581">Ouvrir dans une fenêtre de navigation privée</translation>
++<translation id="8503758797520866434">Préférences de saisie automatique...</translation>
++<translation id="2757031529886297178">Compteur d'images par seconde</translation>
++<translation id="6657585470893396449">Mot de passe</translation>
++<translation id="7881483672146086348">Afficher le compte</translation>
++<translation id="1776883657531386793"><ph name="OID"/> : <ph name="INFO"/></translation>
++<translation id="1510030919967934016">Le suivi de votre position géographique a été bloqué pour cette page.</translation>
++<translation id="4640525840053037973">Connexion à l'aide de votre compte Google</translation>
++<translation id="5255315797444241226">Le mot de passe multiterme entré est incorrect.</translation>
++<translation id="6242054993434749861">télécopie : #<ph name="FAX"/></translation>
++<translation id="762917759028004464">Le navigateur par défaut est actuellement <ph name="BROWSER_NAME"/>.</translation>
++<translation id="9213479837033539041"><ph name="NUMBER_MANY"/> secondes restantes</translation>
++<translation id="300544934591011246">Mot de passe précédent</translation>
++<translation id="5078796286268621944">Code PIN incorrect</translation>
++<translation id="989988560359834682">Modifier l'adresse</translation>
++<translation id="8487678622945914333">Zoom avant</translation>
++<translation id="2972557485845626008">Micrologiciel</translation>
++<translation id="735327918767574393">Une erreur s'est produite lors de l'affichage de cette page Web. Pour continuer, actualisez cette page ou ouvrez-en une autre.</translation>
++<translation id="8028060951694135607">Récupération de clé Microsoft</translation>
++<translation id="9187657844611842955">recto verso</translation>
++<translation id="6391832066170725637">Fichier ou répertoire introuvable</translation>
++<translation id="4694445829210540512">Aucun forfait de données <ph name="NETWORK"/> actif</translation>
++<translation id="5494920125229734069">Tout sélectionner</translation>
++<translation id="2857834222104759979">Le fichier manifeste est incorrect.</translation>
++<translation id="7931071620596053769">Les pages suivantes ne répondent plus. Vous pouvez attendre qu'elles soient de nouveau accessibles ou les supprimer.</translation>
++<translation id="1209866192426315618"><ph name="NUMBER_DEFAULT"/> minutes restantes</translation>
++<translation id="7938958445268990899">Le certificat du serveur n'est pas encore valide.</translation>
++<translation id="4569998400745857585">Menu contenant des extensions masquées</translation>
++<translation id="4081383687659939437">Enregistrer les infos</translation>
++<translation id="5786805320574273267">Configuration de l'accès à distance à cet ordinateur.</translation>
++<translation id="1801827354178857021">Point</translation>
++<translation id="2179052183774520942">Ajouter un moteur de recherche</translation>
++<translation id="5498951625591520696">Impossible d'atteindre le serveur.</translation>
++<translation id="2956948609882871496">Importer mes favoris...</translation>
++<translation id="1621207256975573490">Enregistrer le &amp;cadre sous...</translation>
++<translation id="4681260323810445443">Vous n'êtes pas autorisé à accéder à la page Web <ph name="URL"/>. Votre connexion peut être requise.</translation>
++<translation id="2176444992480806665">Envoyer la capture d'écran du dernier onglet actif</translation>
++<translation id="1165039591588034296">Erreur</translation>
++<translation id="2064942105849061141">Utiliser le thème GTK+</translation>
++<translation id="2278562042389100163">Ouvrir une fenêtre du navigateur</translation>
++<translation id="5246282308050205996"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour redémarrer l'application.</translation>
++<translation id="9218430445555521422">Définir comme navigateur par défaut</translation>
++<translation id="5027550639139316293">Certificat de courrier électronique</translation>
++<translation id="938582441709398163">Clavier en superposition</translation>
++<translation id="427208986916971462">La connexion est compressée avec <ph name="COMPRESSION"/>.</translation>
++<translation id="4589279373639964403">Exporter mes favoris...</translation>
++<translation id="8876215549894133151">Format :</translation>
++<translation id="5234764350956374838">Ignorer</translation>
++<translation id="40027638859996362">Déplacer un mot</translation>
++<translation id="5463275305984126951">Index de <ph name="LOCATION"/></translation>
++<translation id="5154917547274118687">Mémoire</translation>
++<translation id="1493492096534259649">Impossible d'utiliser cette langue pour corriger l'orthographe.</translation>
++<translation id="6628463337424475685">Recherche <ph name="ENGINE"/></translation>
++<translation id="2502105862509471425">Ajouter une autre carte de paiement...</translation>
++<translation id="4037618776454394829">Envoyer la dernière capture d'écran enregistrée</translation>
++<translation id="8987670145726065238">Ce fichier contient du code malveillant. Voulez-vous vraiment continuer ?</translation>
++<translation id="182729337634291014">Erreur de synchronisation...</translation>
++<translation id="4465830120256509958">Clavier brésilien</translation>
++<translation id="2459861677908225199">Utiliser TLS 1.0</translation>
++<translation id="4792711294155034829">&amp;Signaler un problème...</translation>
++<translation id="5819484510464120153">Créer des raccourci&amp;s vers des applications...</translation>
++<translation id="6845180713465955339">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; a été émis par :</translation>
++<translation id="7531238562312180404"><ph name="PRODUCT_NAME"/> ne contrôlant pas la façon dont les extensions gèrent vos données personnelles, toutes les extensions sont désactivées dans les fenêtres de navigation privée. Vous pouvez les réactiver individuellement dans le <ph name="BEGIN_LINK"/>gestionnaire des extensions<ph name="END_LINK"/>.</translation>
++<translation id="5667293444945855280">Logiciels malveillants</translation>
++<translation id="3435845180011337502">Mise en page ou mise en forme de la page</translation>
++<translation id="3838186299160040975">Acheter davantage...</translation>
++<translation id="6831043979455480757">Traduire</translation>
++<translation id="3587482841069643663">Tout</translation>
++<translation id="6698381487523150993">Créé :</translation>
++<translation id="4684748086689879921">Annuler l'importation</translation>
++<translation id="9130015405878219958">Le mode indiqué est incorrect.</translation>
++<translation id="6615807189585243369"><ph name="BURNT_AMOUNT"/> copié(s) sur <ph name="TOTAL_SIZE"/></translation>
++<translation id="8518425453349204360">L'accès à distance à cet ordinateur est activé pour <ph name="USER_EMAIL_ADDRESS"/>.</translation>
++<translation id="4950138595962845479">Options...</translation>
++<translation id="4653235815000740718">Un problème est survenu lors de la création du support de récupération du système d'exploitation. Le périphérique de stockage utilisé est introuvable.</translation>
++<translation id="5516565854418269276">Toujours &amp;afficher la barre de favoris</translation>
++<translation id="6426222199977479699">Erreur SSL</translation>
++<translation id="7104784605502674932">Confirmer les préférences de synchronisation</translation>
++<translation id="1788636309517085411">Utiliser les valeurs par défaut</translation>
++<translation id="1661867754829461514">Code secret manquant</translation>
++<translation id="7406714851119047430">L'accès à distance à cet ordinateur est désactivé.</translation>
++<translation id="8589311641140863898">API des extensions expérimentales</translation>
++<translation id="2804922931795102237">Inclure les informations système</translation>
++<translation id="869891660844655955">Date d'expiration</translation>
++<translation id="2178614541317717477">Autorité de certification compromise</translation>
++<translation id="4449935293120761385">À propos de la saisie automatique</translation>
++<translation id="4194570336751258953">Activer la fonction &quot;Taper pour cliquer&quot;</translation>
++<translation id="6066742401428748382">Accès à la page Web refusé</translation>
++<translation id="5111692334209731439">&amp;Gestionnaire de favoris</translation>
++<translation id="8295070100601117548">Erreur serveur</translation>
++<translation id="5661272705528507004">Cette carte SIM est désactivée et ne peut être utilisée. Veuillez demander à votre fournisseur de services de la remplacer.</translation>
++<translation id="443008484043213881">Outils</translation>
++<translation id="2529657954821696995">Clavier néerlandais</translation>
++<translation id="1128128132059598906">EAP-TTLS</translation>
++<translation id="6585234750898046415">Choisissez une image à associer à votre compte. Celle-ci s'affichera sur l'écran de connexion.</translation>
++<translation id="7957054228628133943">Configurer le blocage des fenêtres pop-up...</translation>
++<translation id="179767530217573436">des 4 dernières semaines</translation>
++<translation id="2279770628980885996">Une situation inattendue s'est produite tandis que le serveur tentait de traiter la demande.</translation>
++<translation id="8079135502601738761">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous l'ouvrir dans Adobe Reader ?</translation>
++<translation id="9123413579398459698">Proxy FTP</translation>
++<translation id="3887875461425980041">Si vous utilisez la version PPAPI de Flash, exécutez-la dans chaque processus de moteur du rendu plutôt que dans un processus de plug-in dédié.</translation>
++<translation id="8534801226027872331">Cela signifie que le certificat présenté à votre navigateur contient des erreurs et qu'il ne peut pas être compris. Il est possible que les informations sur l'identité du certificat ou que d'autres informations du certificat relatives à la sécurité de la connexion soient incompréhensibles. Ne poursuivez pas.</translation>
++<translation id="3608527593787258723">Activer l'onglet 1</translation>
++<translation id="4497369307931735818">Communication à distance</translation>
++<translation id="3855676282923585394">Importer les favoris et les paramètres...</translation>
++<translation id="1116694919640316211">À propos</translation>
++<translation id="4422347585044846479">Modifier le favori de cette page</translation>
++<translation id="1684638090259711957">Ajouter un format d'exception</translation>
++<translation id="4925481733100738363">Configurer l'accès à distance...</translation>
++<translation id="1880905663253319515">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; ?</translation>
++<translation id="8546306075665861288">Cache des images</translation>
++<translation id="5904093760909470684">Configuration du proxy</translation>
++<translation id="2874027208508018603">En l'absence de connexion Wi-Fi, Google Chrome utilise les données 3G.</translation>
++<translation id="4558734465070698159">Appuyez sur <ph name="HOTKEY_NAME"/> pour sélectionner le mode de saisie précédent.</translation>
++<translation id="3348643303702027858">La création du support de récupération du système d'exploitation a été annulée.</translation>
++<translation id="3391060940042023865">Le plug-in suivant est bloqué : <ph name="PLUGIN_NAME"/></translation>
++<translation id="4237016987259239829">Erreur de connexion réseau</translation>
++<translation id="9050666287014529139">Mot de passe multiterme</translation>
++<translation id="5197255632782567636">Internet</translation>
++<translation id="4755860829306298968">Configurer les paramètres de blocage des plug-ins...</translation>
++<translation id="8879284080359814990">Afficher dan&amp;s un onglet</translation>
++<translation id="2786847742169026523">Synchroniser vos mots de passe</translation>
++<translation id="41293960377217290">Le serveur proxy agit comme un intermédiaire entre votre ordinateur et les autres serveurs. Votre configuration système utilise actuellement un proxy, mais
++ <ph name="PRODUCT_NAME"/>
++ ne parvient pas à s'y connecter.</translation>
++<translation id="4520722934040288962">Sélectionner par type d'application</translation>
++<translation id="3873139305050062481">Procéder à l'i&amp;nspection de l'élément</translation>
++<translation id="7445762425076701745">Impossible de valider entièrement l'identité du serveur auquel vous êtes connecté. Le nom utilisé pour cette connexion n'est valide que sur votre réseau et aucune autorité de certification externe ne peut en vérifier la propriété. Certaines autorités de certification délivrent tout de même des certificats pour ces types de nom, par conséquent nous ne sommes pas en mesure de vérifier que vous êtes connecté au site voulu et non à un site malveillant.</translation>
++<translation id="1556537182262721003">Impossible de déplacer le répertoire d'extensions dans le profil.</translation>
++<translation id="5866557323934807206">Supprimer ces paramètres pour les prochaines visites</translation>
++<translation id="6506104645588011859">L'accessibilité est activée.</translation>
++<translation id="5355351445385646029">Appuyer sur la touche Espace pour sélectionner la suggestion</translation>
++<translation id="6978622699095559061">Vos favoris</translation>
++<translation id="6370820475163108109"><ph name="ORGANIZATION_NAME"/> (<ph name="DOMAIN_NAME"/>)</translation>
++<translation id="5453029940327926427">Fermer les onglets</translation>
++<translation id="406070391919917862">Applications en arrière-plan</translation>
++<translation id="8820817407110198400">Favoris</translation>
++<translation id="3214837514330816581">Supprimer les données synchronisées de Google Dashboard</translation>
++<translation id="2580170710466019930">Veuillez patienter pendant que <ph name="PRODUCT_NAME"/> installe les dernières mises à jour système.</translation>
++<translation id="7428061718435085649">Utilisez les touches Maj gauche et droite pour sélectionner les 2e et 3e propositions</translation>
++<translation id="1070066693520972135">WEP</translation>
++<translation id="206683469794463668">Mode Zhuyin complet. La sélection automatique de la suggestion et les options associées sont désactivées ou ignorées.</translation>
++<translation id="5191625995327478163">&amp;Paramètres linguistiques...</translation>
++<translation id="8833054222610756741">CRX-less Web Apps</translation>
++<translation id="4031729365043810780">Connexion au réseau</translation>
++<translation id="3332115613788466465">Reliure bord long</translation>
++<translation id="1985136186573666099"><ph name="PRODUCT_NAME"/> utilise les paramètres proxy du système pour se connecter au réseau.</translation>
++<translation id="6508261954199872201">Application : <ph name="APP_NAME"/></translation>
++<translation id="5585645215698205895">&amp;Descendre</translation>
++<translation id="8366757838691703947">? Toutes les données présentes sur le périphérique seront supprimées.</translation>
++<translation id="6596816719288285829">Adresse IP</translation>
++<translation id="7747704580171477003">Active le nouveau design de la page &quot;Nouvel onglet&quot; (en cours de développement).</translation>
++<translation id="4508265954913339219">Échec de l'activation</translation>
++<translation id="8656768832129462377">Ne pas vérifier</translation>
++<translation id="715487527529576698">Le chinois simplifié est le mode de saisie initial</translation>
++<translation id="1674989413181946727">Paramètres SSL sur tout l'ordinateur :</translation>
++<translation id="8703575177326907206">Votre connexion à <ph name="DOMAIN"/> n'est pas chiffrée.</translation>
++<translation id="8472623782143987204">matériel requis</translation>
++<translation id="4865571580044923428">Gérer les exceptions...</translation>
++<translation id="2526619973349913024">Rechercher des mises à jour</translation>
++<translation id="3874070094967379652">Utiliser un mot de passe multiterme pour chiffrer mes données de synchronisation</translation>
++<translation id="4864369630010738180">Connexion en cours...</translation>
++<translation id="6500116422101723010">Le serveur ne parvient pas à traiter la demande pour le moment. Ce code indique une situation temporaire. Le serveur sera de nouveau opérationnel ultérieurement.</translation>
++<translation id="1644574205037202324">Historique</translation>
++<translation id="1297175357211070620">Destination</translation>
++<translation id="6219983382864672018">Web audio</translation>
++<translation id="479280082949089240">Cookies placés par cette page</translation>
++<translation id="4198861010405014042">Accès partagé</translation>
++<translation id="6204930791202015665">Afficher...</translation>
++<translation id="5941343993301164315">Veuillez vous connecter à <ph name="TOKEN_NAME"/>.</translation>
++<translation id="4417229845571722044">Ajouter un nouvel e-mail</translation>
++<translation id="8049151370369915255">Personnaliser les polices...</translation>
++<translation id="2886862922374605295">Matériel :</translation>
++<translation id="4497097279402334319">Erreur de connexion au réseau.</translation>
++<translation id="5303618139271450299">Cette page Web est introuvable.</translation>
++<translation id="4256316378292851214">En&amp;registrer la vidéo sous...</translation>
++<translation id="3528171143076753409">Le certificat du serveur n'est pas approuvé.</translation>
++<translation id="6518014396551869914">Cop&amp;ier l'image</translation>
++<translation id="3236997602556743698">Sebeol-sik 390</translation>
++<translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation>
++<translation id="289426338439836048">Autre réseau mobile...</translation>
++<translation id="3986287159189541211">Erreur HTTP <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
++<translation id="3225319735946384299">Signature du code</translation>
++<translation id="3118319026408854581">Aide <ph name="PRODUCT_NAME"/></translation>
++<translation id="2422426094670600218">&lt;sans nom&gt;</translation>
++<translation id="2012766523151663935">Version du micrologiciel :</translation>
++<translation id="4120898696391891645">La page ne se charge pas</translation>
++<translation id="6060685159320643512">Attention, ces fonctionnalités expérimentales peuvent mordre.</translation>
++<translation id="5829990587040054282">Verrouiller l'écran ou éteindre</translation>
++<translation id="7800304661137206267">La connexion est chiffrée au moyen de <ph name="CIPHER"/>, avec <ph name="MAC"/> pour l'authentification des messages et <ph name="KX"/> pour la méthode d'échange de clés.</translation>
++<translation id="7706319470528945664">Clavier portugais</translation>
++<translation id="5584537427775243893">Importation</translation>
++<translation id="9128870381267983090">Connexion au réseau</translation>
++<translation id="4181841719683918333">Langues</translation>
++<translation id="6535131196824081346">Cette erreur peut se produire lors de la connexion à un serveur sécurisé (HTTPS).
++ Elle indique que le serveur tente d'établir une connexion sécurisée, mais
++ que celle-ci ne sera pas du tout sécurisée en raison d'une grave erreur de configuration.
++ <ph name="LINE_BREAK"/> Dans ce cas, une intervention
++ est requise sur le serveur.
++ <ph name="PRODUCT_NAME"/>
++ n'utilise pas de connexion non sécurisée pour protéger la confidentialité
++ de vos données.</translation>
++<translation id="5235889404533735074">La synchronisation de <ph name="PRODUCT_NAME"/> vous permet de partager vos données (favoris, préférences) sur vos ordinateurs en toute simplicité. Pour ce faire, <ph name="PRODUCT_NAME"/> enregistre vos données en ligne via Google lorsque vous vous connectez à votre compte.</translation>
++<translation id="6533668113756472185">Format ou mise en forme de la page</translation>
++<translation id="5640179856859982418">Clavier suisse</translation>
++<translation id="5910363049092958439">En&amp;registrer l'image sous...</translation>
++<translation id="1363055550067308502">Basculer en mode pleine chasse ou demi-chasse</translation>
++<translation id="3108967419958202225">Sélectionner...</translation>
++<translation id="6451650035642342749">Effacer les paramètres d'ouverture automatique</translation>
++<translation id="5948544841277865110">Ajouter un réseau privé</translation>
++<translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secondes</translation>
++<translation id="1378451347523657898">Ne pas envoyer de capture d'écran</translation>
++<translation id="5098629044894065541">Hébreu</translation>
++<translation id="7751559664766943798">Toujours afficher la barre de favoris</translation>
++<translation id="5098647635849512368">Impossible de trouver le chemin d'accès absolu du répertoire à empaqueter.</translation>
++<translation id="780617032715125782">Créer un profil</translation>
++<translation id="933712198907837967">Diners Club</translation>
++<translation id="6380224340023442078">Paramètres de contenu...</translation>
++<translation id="950108145290971791">Activer la recherche instantanée pour accélérer la recherche et la navigation ?</translation>
++<translation id="144136026008224475">Plus d'extensions &gt;&gt;</translation>
++<translation id="5486326529110362464">La valeur d'entrée de la clé privée est obligatoire.</translation>
++<translation id="9039663905644212491">PEAP</translation>
++<translation id="62780591024586043">Fonctionnalités de localisation expérimentales</translation>
++<translation id="8584280235376696778">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
++<translation id="2845382757467349449">Toujours afficher la barre de favoris</translation>
++<translation id="2516384155283419848">Reliure</translation>
++<translation id="3053013834507634016">Utilisation de la clé du certificat</translation>
++<translation id="4487088045714738411">Clavier belge</translation>
++<translation id="7511635910912978956"><ph name="NUMBER_FEW"/> heures restantes</translation>
++<translation id="2152580633399033274">Afficher toutes les images (recommandé)</translation>
++<translation id="7894567402659809897">Cliquez sur
++ <ph name="BEGIN_BOLD"/>Démarrer<ph name="END_BOLD"/>,
++ puis sur
++ <ph name="BEGIN_BOLD"/>Exécuter<ph name="END_BOLD"/>.
++ Saisissez
++ et cliquez sur
++ <ph name="BEGIN_BOLD"/>OK<ph name="END_BOLD"/>.</translation>
++<translation id="2934952234745269935">Nom de volume</translation>
++<translation id="7960533875494434480">Reliure bord court</translation>
++<translation id="6431347207794742960"><ph name="PRODUCT_NAME"/> va configurer les mises à jour automatiques pour tous les utilisateurs de cet ordinateur.</translation>
++<translation id="4973698491777102067">Effacer les éléments datant :</translation>
++<translation id="6074963268421707432">Interdire à tous les sites d'afficher des notifications sur le Bureau</translation>
++<translation id="8508050303181238566">Appuyez sur <ph name="HOTKEY_NAME"/> pour passer d'un mode de saisie à l'autre.</translation>
++<translation id="6273404661268779365">Ajouter un nouveau fax</translation>
++<translation id="1995173078718234136">Recherche de contenu en cours...</translation>
++<translation id="4735819417216076266">Style d'entrée avec Espace</translation>
++<translation id="2977095037388048586">Vous avez tenté d'accéder à <ph name="DOMAIN"/>, mais, au lieu de cela, vous communiquez actuellement avec un serveur identifié comme <ph name="DOMAIN2"/>. Cela est peut-être dû à un défaut de configuration du serveur ou à quelque chose de plus grave. Un pirate informatique sur votre réseau cherche peut-être à vous faire visiter une version falsifiée de <ph name="DOMAIN3"/>, donc potentiellement préjudiciable. Nous vous déconseillons vivement de continuer.</translation>
++<translation id="220138918934036434">Masquer le bouton</translation>
++<translation id="5374359983950678924">Modifier l'image</translation>
++<translation id="5158548125608505876">Ne pas synchroniser mes mots de passe</translation>
++<translation id="2167276631610992935">JavaScript</translation>
++<translation id="6974306300279582256">Activer les notifications de <ph name="SITE"/></translation>
++<translation id="492914099844938733">Afficher les incompatibilités</translation>
++<translation id="5233638681132016545">Nouvel onglet</translation>
++<translation id="6567688344210276845">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action de page.</translation>
++<translation id="5210365745912300556">Fermer l'onglet</translation>
++<translation id="8628085465172583869">Nom d'hôte du serveur :</translation>
++<translation id="498765271601821113">Ajouter une carte de paiement</translation>
++<translation id="7694379099184430148"><ph name="FILENAME"/> : type de fichier inconnu</translation>
++<translation id="1992397118740194946">Non défini</translation>
++<translation id="7966826846893205925">Gérer les paramètres de saisie automatique...</translation>
++<translation id="8556732995053816225">Respecter la &amp;casse</translation>
++<translation id="3314070176311241517">Autoriser tous les sites à exécuter JavaScript (recommandé)</translation>
++<translation id="2406911946387278693">Gérer vos périphériques depuis le cloud</translation>
++<translation id="7419631653042041064">Clavier catalan</translation>
++<translation id="5710740561465385694">Me demander lorsqu'un site essaie de stocker des données</translation>
++<translation id="3897092660631435901">Menu</translation>
++<translation id="7024867552176634416">Sélectionnez le périphérique de stockage amovible à utiliser.</translation>
++<translation id="8553075262323480129">La traduction a échoué, car nous n'avons pas pu déterminer la langue de la page.</translation>
++<translation id="5910680277043747137">Vous pouvez créer des profils supplémentaires pour autoriser plusieurs personnes à utiliser et personnaliser Google Chrome.</translation>
++<translation id="4381849418013903196">Deux-points</translation>
++<translation id="1103523840287552314">Toujours traduire en <ph name="LANGUAGE"/></translation>
++<translation id="2263497240924215535">(désactivée)</translation>
++<translation id="2159087636560291862">Cela signifie que le certificat n'a pas été vérifié par un tiers reconnu par votre ordinateur. N'importe qui peut émettre un certificat en se faisant passer pour un autre site Web. Ce certificat doit donc être vérifié par un tiers approuvé. Sans cette vérification, les informations sur l'identité du certificat sont sans intérêt. Par conséquent, il nous est impossible de vérifier que vous communiquez bien avec <ph name="DOMAIN"/> et non avec un pirate informatique ayant émis son propre certificat en prétendant être <ph name="DOMAIN2"/>. Nous vous déconseillons vivement de continuer.</translation>
++<translation id="58625595078799656"><ph name="PRODUCT_NAME"/> requiert que vous cryptiez vos données à l'aide de votre mot de passe Google ou de votre propre mot de passe multiterme.</translation>
++<translation id="8017335670460187064"><ph name="LABEL"/></translation>
++<translation id="6840184929775541289">N'est pas une autorité de certification</translation>
++<translation id="6099520380851856040">Date et heure : <ph name="CRASH_TIME"/></translation>
++<translation id="144518587530125858">Impossible de charger &quot;<ph name="IMAGE_PATH"/>&quot; pour le thème.</translation>
++<translation id="5355097969896547230">Rechercher à nouveau</translation>
++<translation id="7925285046818567682">En attente de <ph name="HOST_NAME"/>...</translation>
++<translation id="2553440850688409052">Masquer ce plug-in</translation>
++<translation id="3280237271814976245">Enregistrer &amp;sous...</translation>
++<translation id="8301162128839682420">Ajouter une langue :</translation>
++<translation id="7658239707568436148">Annuler</translation>
++<translation id="8695825812785969222">Ouvrir une &amp;adresse...</translation>
++<translation id="4538417792467843292">Supprimer le mot</translation>
++<translation id="8412392972487953978">Vous devez saisir deux fois le même mot de passe multiterme.</translation>
++<translation id="9121814364785106365">Ouvrir dans un onglet épinglé</translation>
++<translation id="6996264303975215450">Page Web, tout type de contenu</translation>
++<translation id="3435896845095436175">Activer</translation>
++<translation id="1891668193654680795">Considérer ce certificat comme fiable pour identifier les développeurs de logiciels.</translation>
++<translation id="5078638979202084724">Ajouter tous les onglets aux favoris</translation>
++<translation id="5585118885427931890">Impossible de créer le dossier de favoris.</translation>
++<translation id="2154710561487035718">Copier l'URL</translation>
++<translation id="8163672774605900272">Si vous pensez ne pas avoir à utiliser de serveur proxy, procédez comme suit :
++ <ph name="PLATFORM_TEXT"/></translation>
++<translation id="5510687173983454382">Définir les utilisateurs autorisés à se connecter à un périphérique et autoriser les sessions de navigation en tant qu'invité</translation>
++<translation id="3241680850019875542">Sélectionnez le répertoire racine de l'extension à empaqueter. Pour mettre à jour une extension, sélectionnez également le fichier de clé privée à réutiliser.</translation>
++<translation id="7500424997253660722">Pool restreint :</translation>
++<translation id="657402800789773160">&amp;Rafraîchir cette page</translation>
++<translation id="6163363155248589649">&amp;Normal</translation>
++<translation id="7972714317346275248">PKCS #1 SHA-384 avec chiffrement RSA</translation>
++<translation id="3020990233660977256">Numéro de série : <ph name="SERIAL_NUMBER"/></translation>
++<translation id="8426519927982004547">HTTPS/SSL</translation>
++<translation id="8216781342946147825">Toutes les données de votre ordinateur et des sites Web que vous visitez</translation>
++<translation id="5548207786079516019">Ceci est une installation secondaire de <ph name="PRODUCT_NAME"/> et ce dernier ne peut pas être défini comme navigateur par défaut.</translation>
++<translation id="3984413272403535372">Erreur lors de la signature de l'extension</translation>
++<translation id="8807083958935897582"><ph name="PRODUCT_NAME"/> permet d'effectuer des recherches sur Internet à l'aide du champ polyvalent. Sélectionnez le moteur de recherche à utiliser :</translation>
++<translation id="6629104427484407292">Sécurité : <ph name="SECURITY"/></translation>
++<translation id="9208886416788010685">Adobe Reader n'est pas à jour</translation>
++<translation id="3373604799988099680">Extensions ou applications</translation>
++<translation id="318408932946428277">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
++<translation id="314141447227043789">Téléchargement de l'image terminé.</translation>
++<translation id="8725178340343806893">Favoris</translation>
++<translation id="5177526793333269655">Afficher les vignettes</translation>
++<translation id="8926389886865778422">Ne plus afficher ce message</translation>
++<translation id="6985235333261347343">Agent de récupération de clé Microsoft</translation>
++<translation id="3605499851022050619">Page de diagnostic de navigation sécurisée</translation>
++<translation id="4417271111203525803">Adresse ligne 2</translation>
++<translation id="7617095560120859490">Décrivez-nous le problème recontré. (Champ obligatoire)</translation>
++<translation id="5618333180342767515">Cela peut prendre quelques minutes.</translation>
++<translation id="4307992518367153382">Options de base</translation>
++<translation id="8480417584335382321">Niveau de zoom par défaut :</translation>
++<translation id="3872166400289564527">Stockage externe</translation>
++<translation id="5912378097832178659">Modifi&amp;er les moteurs de recherche...</translation>
++<translation id="8272426682713568063">Cartes de paiement</translation>
++<translation id="3749289110408117711">Nom du fichier</translation>
++<translation id="3173397526570909331">Arrêter la synchronisation</translation>
++<translation id="5538092967727216836">Actualiser le cadre</translation>
++<translation id="4813345808229079766">Connexion</translation>
++<translation id="411666854932687641">Mémoire privée</translation>
++<translation id="119944043368869598">Tout effacer</translation>
++<translation id="3467848195100883852">Activer la correction orthographique automatique</translation>
++<translation id="1336254985736398701">Afficher les &amp;infos sur la page</translation>
++<translation id="7550830279652415241">favoris_<ph name="DATESTAMP"/>.html</translation>
++<translation id="6828153365543658583">Autoriser uniquement les utilisateurs suivants à se connecter :</translation>
++<translation id="1652965563555864525">&amp;Muet</translation>
++<translation id="4200983522494130825">Nouvel ongle&amp;t</translation>
++<translation id="7979036127916589816">Erreur de synchronisation</translation>
++<translation id="1029317248976101138">Zoom</translation>
++<translation id="5455790498993699893"><ph name="ACTIVE_MATCH"/> sur <ph name="TOTAL_MATCHCOUNT"/></translation>
++<translation id="8890069497175260255">Type de clavier</translation>
++<translation id="1202290638211552064">Délai d'expiration atteint au niveau de la passerelle ou du serveur proxy en attente d'une réponse d'un serveur en amont.</translation>
++<translation id="7765158879357617694">Déplacer</translation>
++<translation id="5731751937436428514">Mode de saisie du vietnamien (VIQR)</translation>
++<translation id="8412144371993786373">Ajouter la page actuelle aux favoris</translation>
++<translation id="7615851733760445951">&lt;aucun cookie sélectionné&gt;</translation>
++<translation id="469553822757430352">Le mot de passe de l'application est incorrect.</translation>
++<translation id="2493021387995458222">Sélectionner &quot;un mot à la fois&quot;</translation>
++<translation id="5279600392753459966">Tout bloquer</translation>
++<translation id="6846298663435243399">Chargement en cours…</translation>
++<translation id="7392915005464253525">&amp;Rouvrir la fenêtre fermée</translation>
++<translation id="1144684570366564048">Gérer les exceptions...</translation>
++<translation id="7400418766976504921">URL</translation>
++<translation id="1541725072327856736">Katakana demi-chasse</translation>
++<translation id="7456847797759667638">Ouvrir une adresse</translation>
++<translation id="1388866984373351434">Données de navigation</translation>
++<translation id="3754634516926225076">Code PIN incorrect. Veuillez réessayer.</translation>
++<translation id="7378627244592794276">Non</translation>
++<translation id="2800537048826676660">Utiliser cette langue pour corriger l'orthographe</translation>
++<translation id="68541483639528434">Fermer les autres onglets</translation>
++<translation id="941543339607623937">Clé privée non valide.</translation>
++<translation id="6499058468232888609">Une erreur réseau s'est produite pendant la communication avec le service de gestion des périphériques.</translation>
++<translation id="4433862206975946675">Importer les données d'un autre navigateur...</translation>
++<translation id="4022426551683927403">&amp;Ajouter au dictionnaire</translation>
++<translation id="2897878306272793870">Voulez-vous vraiment ouvrir <ph name="TAB_COUNT"/> onglets ?</translation>
++<translation id="312759608736432009">Fabricant du périphérique :</translation>
++<translation id="362276910939193118">Afficher l'historique complet</translation>
++<translation id="6079696972035130497">Illimité</translation>
++<translation id="4365411729367255048">Clavier Neo2 allemand</translation>
++<translation id="6348657800373377022">Liste déroulante</translation>
++<translation id="8064671687106936412">Clé :</translation>
++<translation id="2218515861914035131">Coller en texte brut</translation>
++<translation id="1725149567830788547">Afficher les &amp;commandes</translation>
++<translation id="3528033729920178817">Cette page suit votre position géographique.</translation>
++<translation id="5518584115117143805">Certificat de chiffrement de courrier électronique</translation>
++<translation id="9203398526606335860">&amp;Profilage activé</translation>
++<translation id="4307281933914537745">En savoir plus sur la récupération du système</translation>
++<translation id="2849936225196189499">Essentielle</translation>
++<translation id="9001035236599590379">Type MIME</translation>
++<translation id="5612754943696799373">Autoriser le téléchargement ?</translation>
++<translation id="6353618411602605519">Clavier croate</translation>
++<translation id="5515810278159179124">Interdire à tous les sites de suivre ma position géographique</translation>
++<translation id="5999606216064768721">Utiliser la barre de titre du système et les bordures de la fenêtre</translation>
++<translation id="904752364881701675">En bas à gauche</translation>
++<translation id="3398951731874728419">Informations sur l'erreur :</translation>
++<translation id="1464570622807304272">Essayez : saisissez &quot;orchidées&quot;, puis appuyez sur Entrée.</translation>
++<translation id="8026684114486203427">Pour utiliser Chrome Web Store, vous devez être connecté à un compte Google.</translation>
++<translation id="8417276187983054885">Configurer <ph name="CLOUD_PRINT_NAME"/></translation>
++<translation id="3056462238804545033">Petit problème... Nous n'avons pas réussi à vous authentifier. Veuillez vérifier vos identifiants de connexion puis réessayer.</translation>
++<translation id="5298420986276701358">Pour gérer à distance la configuration de ce périphérique <ph name="PRODUCT_NAME"/> depuis le cloud, connectez-vous avec votre compte Google Apps.</translation>
++<translation id="2678063897982469759">Réactiver</translation>
++<translation id="1779766957982586368">Fermer la fenêtre</translation>
++<translation id="4850886885716139402">Présentation</translation>
++<translation id="89217462949994770">Vous avez saisi un trop grand nombre de codes PIN incorrects. Veuillez contacter <ph name="CARRIER_ID"/> pour obtenir une nouvelle clé de déverrouillage du code PIN à 8 chiffres.</translation>
++<translation id="5920618722884262402">Bloquer le contenu inapproprié</translation>
++<translation id="5120247199412907247">Configuration avancée</translation>
++<translation id="5922220455727404691">Utiliser SSL 3.0</translation>
++<translation id="1368352873613152012">Règles de confidentialité liées à la navigation sécurisée</translation>
++<translation id="5105859138906591953">Vous devez être connecté à votre compte Google pour importer les favoris de la barre d'outils Google dans Google Chrome. Connectez-vous et relancez l'importation.</translation>
++<translation id="8899851313684471736">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
++<translation id="4110342520124362335">Les cookies de <ph name="DOMAIN"/> ont été bloqués.</translation>
++<translation id="3303818374450886607">Copies</translation>
++<translation id="2019718679933488176">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
++<translation id="4138267921960073861">Afficher les noms d'utilisateurs et leur photo sur la page de connexion</translation>
++<translation id="7465778193084373987">URL de révocation de certificat Netscape</translation>
++<translation id="5976690834266782200">Ajoute des options de regroupement des onglets dans le menu contextuel des onglets.</translation>
++<translation id="4755240240651974342">Clavier finnois</translation>
++<translation id="7049893973755373474">Vérifiez votre connexion Internet. Redémarrez votre routeur, votre modem
++ ou tout autre périphérique réseau que vous utilisez.</translation>
++<translation id="7421925624202799674">&amp;Afficher le code source de la page</translation>
++<translation id="3940082421246752453">Le serveur ne prend pas en charge la version HTTP utilisée dans la demande.</translation>
++<translation id="661719348160586794">Vos mots de passe enregistrés s'afficheront ici.</translation>
++<translation id="6686490380836145850">Fermer les onglets sur la droite</translation>
++<translation id="5608669887400696928"><ph name="NUMBER_DEFAULT"/> heures</translation>
++<translation id="8844709414456935411"><ph name="PRODUCT_NAME"/>
++ indique qu'un produit ESET intercepte les connexions sécurisées.
++ En général, cela ne constitue pas un problème de sécurité car le
++ logiciel ESET s'exécute souvent sur le même ordinateur. Toutefois, en raison
++ de certaines incompatibilités avec les connexions sécurisées
++ <ph name="PRODUCT_NAME"/>,
++ vous devez configurer les produits ESET de manière à éviter ces
++ interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
++<translation id="3936877246852975078">Les requêtes adressées au serveur ont été temporairement limitées.</translation>
++<translation id="2600306978737826651">Impossible de télécharger l'image. Gravure annulée.</translation>
++<translation id="609978099044725181">Activer/désactiver le mode Hanja</translation>
++<translation id="1829483195200467833">Effacer les paramètres d'ouverture automatique</translation>
++<translation id="2738771556149464852">Pas après le</translation>
++<translation id="5774515636230743468">Manifeste :</translation>
++<translation id="719464814642662924">Visa</translation>
++<translation id="7474889694310679759">Clavier anglais canadien</translation>
++<translation id="1817871734039893258">Récupération de fichier Microsoft</translation>
++<translation id="2423578206845792524">En&amp;registrer l'image sous...</translation>
++<translation id="6839929833149231406">Zone</translation>
++<translation id="9068931793451030927">Chemin :</translation>
++<translation id="283278805979278081">Prendre la photo</translation>
++<translation id="7320906967354320621">Inactif</translation>
++<translation id="1407050882688520094">Certains de vos certificats enregistrés identifient ces autorités de certification :</translation>
++<translation id="4287689875748136217">Impossible d'afficher la page Web, car le serveur n'a envoyé aucune donnée.</translation>
++<translation id="1634788685286903402">Considérer ce certificat comme fiable pour identifier les utilisateurs de messageries.</translation>
++<translation id="7052402604161570346">Ce type de fichier peut endommager votre ordinateur. Voulez-vous vraiment télécharger <ph name="FILE_NAME"/> ?</translation>
++<translation id="8642489171979176277">Importés depuis la barre d'outils Google</translation>
++<translation id="4142744419835627535">Recherche instantanée et saisie semi-automatique</translation>
++<translation id="4684427112815847243">Tout synchroniser</translation>
++<translation id="1125520545229165057">Dvorak (Hsu)</translation>
++<translation id="8940229512486821554">Exécuter la commande <ph name="EXTENSION_NAME"/> : <ph name="SEARCH_TERMS"/></translation>
++<translation id="2232876851878324699">Le fichier contenait un certificat, qui n'a pas été importé :</translation>
++<translation id="7787129790495067395">Vous utilisez actuellement un mot de passe multiterme. Si vous l'oubliez, vous pouvez réinitialiser la synchronisation afin de supprimer vos données des serveurs Google à l'aide de Google Dashboard.</translation>
++<translation id="2686759344028411998">Impossible de détecter les modules chargés.</translation>
++<translation id="572525680133754531">Cette fonctionnalité affiche une bordure autour des couches de rendu afin de déboguer et d'étudier leur composition.</translation>
++<translation id="2011110593081822050">Processus de traitement Web : <ph name="WORKER_NAME"/></translation>
++<translation id="3294437725009624529">Invité</translation>
++<translation id="350069200438440499">Nom du fichier :</translation>
++<translation id="9058204152876341570">Un élément est manquant.</translation>
++<translation id="8494979374722910010">Échec de la tentative de connexion au serveur.</translation>
++<translation id="7810202088502699111">Des fenêtres pop-up ont été bloquées sur cette page.</translation>
++<translation id="8190698733819146287">Personnaliser les langues et la saisie...</translation>
++<translation id="646727171725540434">Proxy HTTP</translation>
++<translation id="1006316751839332762">Mot de passe multiterme de chiffrement</translation>
++<translation id="8795916974678578410">Nouvelle fenêtre</translation>
++<translation id="2733275712367076659">Certains certificats provenant de ces organisations vous identifient :</translation>
++<translation id="4801512016965057443">Autoriser l'itinérance des données mobiles</translation>
++<translation id="2515586267016047495">Alt</translation>
++<translation id="2046040965693081040">Utiliser les pages actuelles</translation>
++<translation id="3798449238516105146">Version</translation>
++<translation id="5764483294734785780">En&amp;registrer le fichier audio sous...</translation>
++<translation id="5252456968953390977">Itinérance</translation>
++<translation id="8744641000906923997">Romaji</translation>
++<translation id="8507996248087185956"><ph name="NUMBER_DEFAULT"/> minutes</translation>
++<translation id="4845656988780854088">Synchroniser uniquement les paramètres et\ndonnées qui ont changé depuis la dernière connexion\n(requiert votre mot de passe précédent)</translation>
++<translation id="348620396154188443">Autoriser tous les sites à afficher des notifications sur le Bureau</translation>
++<translation id="8214489666383623925">Ouvrir le fichier...</translation>
++<translation id="5376120287135475614">Changer de fenêtre</translation>
++<translation id="5230160809118287008">Chèvres téléportées</translation>
++<translation id="1701567960725324452">Si vous arrêtez la synchronisation, les données stockées sur cet ordinateur et dans votre compte Google demeureront à ces deux emplacements. Toutefois, les nouvelles données ou les modifications apportées au contenu existant ne seront pas synchronisées.</translation>
++<translation id="7761701407923456692">Le certificat du serveur ne correspond pas à l'URL.</translation>
++<translation id="3885155851504623709">Commune</translation>
++<translation id="4910171858422458941">Impossible d'activer les plug-ins désactivés par une stratégie d'entreprise.</translation>
++<translation id="4495419450179050807">Ne pas afficher sur cette page</translation>
++<translation id="4745800796303246012">Méthodes EAP en Wi-Fi expérimentales</translation>
++<translation id="1225544122210684390">Disque dur</translation>
++<translation id="939736085109172342">Nouveau dossier</translation>
++<translation id="4933484234309072027">intégration sur <ph name="URL"/></translation>
++<translation id="5554720593229208774">Autorité de certification de messagerie</translation>
++<translation id="862750493060684461">Cache CSS</translation>
++<translation id="2832519330402637498">En haut à gauche</translation>
++<translation id="6749695674681934117">Saisissez le nom du nouveau dossier.</translation>
++<translation id="6204994989617056362">L'extension de renégociation SSL était introuvable lors de la négociation sécurisée. Avec certains sites, connus pour leur prise en charge de l'extension de renégociation, Google Chrome exige une négociation mieux sécurisée afin de prévenir certaines attaques. L'absence de cette extension suggère que votre connexion a été interceptée et manipulée au cours du transfert.</translation>
++<translation id="6679492495854441399">Petit problème... Une erreur de communication avec le réseau est survenue lors de la tentative d'inscription de ce périphérique. Veuillez vérifier votre connexion réseau et réessayer.</translation>
++<translation id="7789962463072032349">pause</translation>
++<translation id="121827551500866099">Afficher tous les téléchargements...</translation>
++<translation id="1562633988311880769">Connexion à <ph name="CLOUD_PRINT_NAME"/></translation>
++<translation id="5949910269212525572">Impossible de résoudre l'adresse DNS du serveur.</translation>
++<translation id="3115147772012638511">En attente de l'affichage du cache</translation>
++<translation id="257088987046510401">Thèmes</translation>
++<translation id="6771079623344431310">Impossible de se connecter au serveur proxy.</translation>
++<translation id="2200129049109201305">Ignorer la synchronisation des données chiffrées ?</translation>
++<translation id="1426410128494586442">Oui</translation>
++<translation id="6725970970008349185">Nombre de suggestions par page</translation>
++<translation id="6198252989419008588">Modifier le code PIN</translation>
++<translation id="5749483996735055937">Un problème est survenu lors de la copie de l'image de récupération sur le périphérique.</translation>
++<translation id="3520476450377425184"><ph name="NUMBER_MANY"/> jours restants</translation>
++<translation id="7643817847124207232">La connexion Internet a été interrompue.</translation>
++<translation id="932327136139879170">Début</translation>
++<translation id="4764675709794295630">« Précédent</translation>
++<translation id="2560794850818211873">C&amp;opier l'URL de la vidéo</translation>
++<translation id="6042708169578999844">Vos données sur <ph name="WEBSITE_1"/> et <ph name="WEBSITE_2"/></translation>
++<translation id="5302048478445481009">Langue</translation>
++<translation id="5553089923092577885">Mappages des stratégies de certificat</translation>
++<translation id="5600907569873192868"><ph name="NUMBER_MANY"/> minutes restantes</translation>
++<translation id="1519704592140256923">Sélectionner la position</translation>
++<translation id="1275018677838892971">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
++<translation id="702455272205692181"><ph name="EXTENSION_NAME"/></translation>
++<translation id="7170041865419449892">Hors de portée</translation>
++<translation id="908263542783690259">Effacer l'historique de navigation</translation>
++<translation id="7518003948725431193">Aucune page Web trouvée à l'adresse :<ph name="URL"/></translation>
++<translation id="745602119385594863">Nouveau moteur de recherche :</translation>
++<translation id="7484645889979462775">Jamais pour ce site</translation>
++<translation id="8666066831007952346"><ph name="NUMBER_TWO"/> jours restants</translation>
++<translation id="9086455579313502267">Impossible d'accéder au réseau.</translation>
++<translation id="5595485650161345191">Modifier l'adresse</translation>
++<translation id="2374144379568843525">&amp;Masquer le panneau de la vérification orthographique</translation>
++<translation id="2694026874607847549">1 cookie</translation>
++<translation id="4393664266930911253">Activer ces fonctionnalités...</translation>
++<translation id="6390842777729054533"><ph name="NUMBER_ZERO"/> secondes restantes</translation>
++<translation id="3909791450649380159">Cou&amp;per</translation>
++<translation id="2955913368246107853">Fermer la barre de recherche</translation>
++<translation id="5642508497713047">Signataire de la liste de révocation de certificats</translation>
++<translation id="813082847718468539">Afficher des informations à propos du site</translation>
++<translation id="3122464029669770682">UC</translation>
++<translation id="1684861821302948641">Fermer les pages</translation>
++<translation id="6092270396854197260">MSPY</translation>
++<translation id="6802031077390104172"><ph name="USAGE"/> (<ph name="OID"/>)</translation>
++<translation id="4052120076834320548">Très petite</translation>
++<translation id="6623138136890659562">Afficher les réseaux privés dans le menu Réseau pour activer la connexion à un VPN</translation>
++<translation id="8969837897925075737">Vérification de la mise à jour du système...</translation>
++<translation id="3393716657345709557">L'entrée demandée est introuvable dans le cache.</translation>
++<translation id="7241389281993241388">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client.</translation>
++<translation id="40334469106837974">Modifier la mise en page</translation>
++<translation id="4804818685124855865">Se déconnecter</translation>
++<translation id="2617919205928008385">Espace insuffisant.</translation>
++<translation id="210445503571712769">Préférences synchronisées</translation>
++<translation id="1608306110678187802">Imp&amp;rimer le cadre...</translation>
++<translation id="7427315641433634153">MSCHAP</translation>
++<translation id="6622980291894852883">Continuer à bloquer les images</translation>
++<translation id="5937837224523037661">Lorsqu'un site utilise des plug-ins :</translation>
++<translation id="4988792151665380515">Échec d'exportation de la clé publique</translation>
++<translation id="6333049849394141510">Choisir les éléments à synchroniser</translation>
++<translation id="446322110108864323">Paramètres de saisie du Pinyin</translation>
++<translation id="4948468046837535074">Ouvrir les pages suivantes :</translation>
++<translation id="5222676887888702881">Déconnexion</translation>
++<translation id="6978121630131642226">Moteurs de recherche</translation>
++<translation id="6839225236531462745">Erreur de suppression de certificat</translation>
++<translation id="6745994589677103306">Ne rien faire</translation>
++<translation id="855081842937141170">Épingler l'onglet</translation>
++<translation id="6263541650532042179">réinitialiser la synchronisation</translation>
++<translation id="6055392876709372977">PKCS #1 SHA-256 avec chiffrement RSA</translation>
++<translation id="7903984238293908205">Katakana</translation>
++<translation id="3781488789734864345">Choisir un réseau mobile</translation>
++<translation id="268053382412112343">&amp;Historique</translation>
++<translation id="2723893843198727027">Mode développeur :</translation>
++<translation id="1722567105086139392">Lien</translation>
++<translation id="2620436844016719705">Système</translation>
++<translation id="5362741141255528695">Sélectionnez le fichier de clé privée.</translation>
++<translation id="5292890015345653304">Insérez une carte SD ou une carte mémoire USB.</translation>
++<translation id="5583370583559395927">Temps restant : <ph name="TIME_REMAINING"/></translation>
++<translation id="8065982201906486420">Cliquez ici pour exécuter le plug-in <ph name="PLUGIN_NAME"/>.</translation>
++<translation id="6219717821796422795">Hanyu</translation>
++<translation id="3725367690636977613">pages</translation>
++<translation id="2688477613306174402">Configuration en cours</translation>
++<translation id="1195447618553298278">Erreur inconnue</translation>
++<translation id="3353284378027041011"><ph name="NUMBER_FEW"/> days ago</translation>
++<translation id="8811462119186190367">La langue utilisée pour Google Chrome est passée de &quot;<ph name="FROM_LOCALE"/>&quot; à &quot;<ph name="TO_LOCALE"/>&quot; après la synchronisation de vos paramètres.</translation>
++<translation id="1087119889335281750">&amp;Aucune suggestion orthographique</translation>
++<translation id="5228309736894624122">Erreur de protocole SSL</translation>
++<translation id="8216170236829567922">Mode de saisie du thaï (clavier Pattachote)</translation>
++<translation id="8464132254133862871">Ce compte utilisateur n'est pas compatible avec ce service.</translation>
++<translation id="6812349420832218321"><ph name="PRODUCT_NAME"/> ne peut pas être exécuté en tant que root.</translation>
++<translation id="5076340679995252485">C&amp;oller</translation>
++<translation id="2904348843321044456">Paramètres de contenu...</translation>
++<translation id="1055216403268280980">Dimensions de l'image</translation>
++<translation id="1784284518684746740">Sélectionner le fichier à enregistrer sous</translation>
++<translation id="7032947513385578725">Disque Flash</translation>
++<translation id="5518442882456325299">Moteur de recherche actuel :</translation>
++<translation id="14171126816530869">L'identité de <ph name="ORGANIZATION"/> situé à <ph name="LOCALITY"/> a été vérifiée par <ph name="ISSUER"/>.</translation>
++<translation id="6263082573641595914">Version de l'autorité de certification Microsoft</translation>
++<translation id="3105917916468784889">Enregistrer une capture d'écran</translation>
++<translation id="1741763547273950878">Page sur <ph name="SITE"/></translation>
++<translation id="1587275751631642843">Console &amp;JavaScript</translation>
++<translation id="8460696843433742627">Réponse reçue incorrecte lors de la tentative de chargement de <ph name="URL"/>.
++ Cela peut être dû à une opération de maintenance ou à une configuration incorrecte sur le serveur.</translation>
++<translation id="297870353673992530">Serveur DNS :</translation>
++<translation id="3222066309010235055">Pré-rendu : <ph name="PRERENDER_CONTENTS_NAME"/></translation>
++<translation id="6410063390789552572">Impossible d'accéder à la bibliothèque réseau.</translation>
++<translation id="6880587130513028875">Des images ont été bloquées sur cette page.</translation>
++<translation id="851263357009351303">Toujours autoriser <ph name="HOST"/> à afficher les images</translation>
++<translation id="3511307672085573050">Copier l'adr&amp;esse du lien</translation>
++<translation id="1134009406053225289">Ouvrir dans une fenêtre de navigation privée</translation>
++<translation id="6655190889273724601">Mode développeur</translation>
++<translation id="1071917609930274619">Chiffrement des données</translation>
++<translation id="3473105180351527598">Activer la protection contre le phishing et les logiciels malveillants</translation>
++<translation id="6151323131516309312">Appuyez sur <ph name="SEARCH_KEY"/> pour rechercher sur <ph name="SITE_NAME"/></translation>
++<translation id="3753317529742723206">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) au lieu de <ph name="REPLACED_HANDLER_TITLE"/> pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
++<translation id="6216679966696797604">Démarrer une session en tant qu'invité</translation>
++<translation id="5456397824015721611">Nombre maximal de caractères chinois dans la mémoire tampon de pré-édition, notamment les entrées de symboles Zhuyin</translation>
++<translation id="2055443983279698110">Barre de menus GNOME expérimentale disponible</translation>
++<translation id="2342959293776168129">Effacer l'historique des téléchargements</translation>
++<translation id="2503522102815150840">Navigateur bloqué...</translation>
++<translation id="7201354769043018523">Parenthèse drte</translation>
++<translation id="425878420164891689">Calcul du temps de chargement</translation>
++<translation id="508794495705880051">Ajouter une carte de paiement...</translation>
++<translation id="1425975335069981043">Itinérance :</translation>
++<translation id="1272079795634619415">Arrêter</translation>
++<translation id="5442787703230926158">Erreur de synchronisation...</translation>
++<translation id="2462724976360937186">ID de clé de l'autorité de certification</translation>
++<translation id="6786747875388722282">Extensions</translation>
++<translation id="3944384147860595744">Imprimez où que vous soyez.</translation>
++<translation id="2570648609346224037">Un problème est survenu lors du téléchargement de l'image de récupération.</translation>
++<translation id="4306718255138772973">Cloud Print Proxy</translation>
++<translation id="9053965862400494292">Une erreur s'est produite lors de la configuration de la synchronisation.</translation>
++<translation id="8596540852772265699">Fichiers personnalisés</translation>
++<translation id="7017354871202642555">Impossible de définir le mode une fois la fenêtre créée.</translation>
++<translation id="3101709781009526431">Date et heure</translation>
++<translation id="69375245706918574">Personnaliser les préférences de synchronisation</translation>
++<translation id="833853299050699606">Aucune information disponible sur le forfait</translation>
++<translation id="1737968601308870607">Signaler un problème</translation>
++<translation id="4571852245489094179">Importer mes favoris et paramètres</translation>
++<translation id="99648783926443049">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Paramètres &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
++<translation id="4421917670248123270">Fermer et annuler les téléchargements</translation>
++<translation id="5605623530403479164">Autres moteurs de recherche</translation>
++<translation id="8887243200615092733"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Pour protéger vos données, vous devez confirmer les informations relatives à votre compte.</translation>
++<translation id="4740663705480958372">Cette fonctionnalité active les API P2P Pepper et P2P JavaScript. L'API est en cours de développement et n'est pas encore opérationnelle.</translation>
++<translation id="5710435578057952990">L'identité de ce site Web n'a pas été vérifiée.</translation>
++<translation id="1421046588786494306">Sessions à l'étranger</translation>
++<translation id="1661245713600520330">Cette page répertorie tous les modules chargés dans le processus principal et les modules enregistrés de manière à être chargés ultérieurement.</translation>
++<translation id="5451646087589576080">Afficher les &amp;infos sur le cadre</translation>
++<translation id="3368922792935385530">Connecté</translation>
++<translation id="3498309188699715599">Paramètres d'entrée en Chewing</translation>
++<translation id="8486154204771389705">Conserver sur cette page</translation>
++<translation id="3866443872548686097">Votre support de récupération est prêt. Vous pouvez le retirer du système.</translation>
++<translation id="6824564591481349393">Copi&amp;er l'adresse e-mail</translation>
++<translation id="907148966137935206">Interdire à tous les sites d'afficher des fenêtres pop-up (recommandé)</translation>
++<translation id="5184063094292164363">Console &amp;JavaScript</translation>
++<translation id="333371639341676808">Empêcher cette page de générer des boîtes de dialogue supplémentaires</translation>
++<translation id="7632380866023782514">En haut à droite</translation>
++<translation id="4925520021222027859">Entrez le mot de passe associé à votre application :</translation>
++<translation id="3494768541638400973">Mode de saisie Google du japonais (pour clavier japonais)</translation>
++<translation id="5844183150118566785"><ph name="PRODUCT_NAME"/> est à jour (<ph name="VERSION"/>)</translation>
++<translation id="3118046075435288765">Le serveur a mis fin à la connexion de manière inattendue.</translation>
++<translation id="8041140688818013446">Il est possible que le serveur hébergeant la page Web soit surchargé ou ait rencontré une erreur. Pour éviter de générer
++ trop de trafic et d'aggraver la situation,
++ <ph name="PRODUCT_NAME"/> a temporairement
++ bloqué l'acceptation des requêtes adressées au serveur.
++ <ph name="LINE_BREAK"/>
++ Si vous pensez que ce comportement n'est pas souhaitable, (par exemple, dans le cas où vous déboguez votre propre site Web), vous pouvez
++ consulter la page <ph name="NET_INTERNALS_PAGE"/>,
++ sur laquelle vous pourrez trouver plus d'informations ou désactiver cette fonctionnalité.</translation>
++<translation id="1725068750138367834">Gestionnaire de &amp;fichiers</translation>
++<translation id="4254921211241441775">Arrêter la synchronisation du compte</translation>
++<translation id="7791543448312431591">Ajouter</translation>
++<translation id="8569764466147087991">Sélectionnez le fichier à ouvrir</translation>
++<translation id="5449451542704866098">Aucun forfait de données</translation>
++<translation id="307505906468538196">Créer un compte Google</translation>
++<translation id="2053553514270667976">Code postal</translation>
++<translation id="48838266408104654">&amp;Gestionnaire de tâches</translation>
++<translation id="4378154925671717803">Téléphone</translation>
++<translation id="3694027410380121301">Sélectionner l'onglet précédent</translation>
++<translation id="6178664161104547336">Sélectionner un certificat</translation>
++<translation id="1375321115329958930">Mots de passe enregistrés</translation>
++<translation id="3341703758641437857">Autoriser l'accès aux URL de fichier</translation>
++<translation id="5702898740348134351">Modifi&amp;er les moteurs de recherche...</translation>
++<translation id="734303607351427494">Gérer les moteurs de recherche...</translation>
++<translation id="8326478304147373412">PKCS #7, chaîne de certificats</translation>
++<translation id="3242765319725186192">Clé pré-partagée :</translation>
++<translation id="8089798106823170468">Contrôlez et partagez l'accès à vos imprimantes depuis n'importe quel compte Google.</translation>
++<translation id="5984992849064510607">Ajoute l'option &quot;Utiliser les onglets latéraux&quot; au menu contextuel de la barre d'onglets. Utilisez cette option pour déplacer les onglets du haut de l'écran (affichage par défaut) vers le côté. Particulièrement utile sur les grands écrans.</translation>
++<translation id="839736845446313156">S'inscrire</translation>
++<translation id="4668929960204016307">,</translation>
++<translation id="2409527877874991071">Saisissez un nouveau nom.</translation>
++<translation id="4240069395079660403"><ph name="PRODUCT_NAME"/> ne peut pas être affiché dans cette langue.</translation>
++<translation id="747114903913869239">Erreur : impossible de décoder l'extension.</translation>
++<translation id="5412637665001827670">Clavier bulgare</translation>
++<translation id="2113921862428609753">Accès aux informations de l'autorité</translation>
++<translation id="5227536357203429560">Ajouter un réseau privé...</translation>
++<translation id="732677191631732447">C&amp;opier l'URL du fichier audio</translation>
++<translation id="7224023051066864079">Masque de sous-réseau :</translation>
++<translation id="2401813394437822086">Impossible d'accéder à votre compte ?</translation>
++<translation id="2344262275956902282">Utiliser les touches - et = pour paginer une liste d'entrées</translation>
++<translation id="3609138628363401169">Le serveur ne prend pas en charge l'extension de renégociation TLS.</translation>
++<translation id="3369624026883419694">Résolution de l'hôte...</translation>
++<translation id="8870413625673593573">Récemment fermés</translation>
++<translation id="9145357542626308749">Le certificat de sécurité du site a été signé avec un algorithme de signature faible.</translation>
++<translation id="8502803898357295528">Votre mot de passe a été modifié</translation>
++<translation id="4064488613268730704">Gérer les paramètres de saisie automatique...</translation>
++<translation id="6830600606572693159">La page Web <ph name="URL"/> n'est pas disponible pour le moment. Cela peut être dû à une surcharge ou à une opération de maintenance.</translation>
++<translation id="4145797339181155891">Éjecter</translation>
++<translation id="7886793013438592140">Impossible de lancer le processus de service.</translation>
++<translation id="8417944620073548444"><ph name="MEGABYTES"/> Mo restants</translation>
++<translation id="7339898014177206373">Nouvelle fenêtre</translation>
++<translation id="3026202950002788510">Sélectionnez
++ <ph name="BEGIN_BOLD"/>
++ Applications &gt; Préférences système &gt; Réseau &gt; Avancé &gt; Proxys
++ <ph name="END_BOLD"/>
++ et désélectionnez les serveurs proxy sélectionnés.</translation>
++<translation id="7033648024564583278">Gravure en cours d'initialisation...</translation>
++<translation id="2246340272688122454">Téléchargement de l'image de récupération...</translation>
++<translation id="7770995925463083016">il y a <ph name="NUMBER_TWO"/> minutes</translation>
++<translation id="2816269189405906839">Mode de saisie du chinois (cangjie)</translation>
++<translation id="7087282848513945231">Comté</translation>
++<translation id="2149951639139208969">Ouvrir l'adresse dans un nouvel onglet</translation>
++<translation id="175196451752279553">&amp;Rouvrir l'onglet fermé</translation>
++<translation id="5992618901488170220">Impossible d'afficher la page Web, car votre ordinateur est passé en mode
++ veille ou hibernation. Dans ce cas, les connexions réseau sont
++ coupées et les requêtes réseau échouent. L'actualisation de la page
++ devrait permettre de résoudre ce problème.</translation>
++<translation id="2655386581175833247">Certificat utilisateur :</translation>
++<translation id="5039804452771397117">Autoriser</translation>
++<translation id="5435964418642993308">Appuyer sur Entrée pour revenir en arrière et sur la touche de menu contextuel pour afficher l'historique</translation>
++<translation id="81686154743329117">ZRM</translation>
++<translation id="7564146504836211400">Cookies et autres données</translation>
++<translation id="2266011376676382776">Page(s) ne répondant pas</translation>
++<translation id="2714313179822741882">Paramètres d'entrée hangûl</translation>
++<translation id="8658163650946386262">Configurer la synchronisation...</translation>
++<translation id="3100609564180505575">Modules (<ph name="TOTAL_COUNT"/>). Conflits connus : <ph name="BAD_COUNT"/>, conflits probables : <ph name="SUSPICIOUS_COUNT"/></translation>
++<translation id="3627671146180677314">Date de renouvellement du certificat Netscape</translation>
++<translation id="1319824869167805246">Ouvrir tous les favoris dans une nouvelle fenêtre</translation>
++<translation id="8652487083013326477">bouton radio concernant l'étendue de pages</translation>
++<translation id="5204967432542742771">Saisissez votre mot de passe</translation>
++<translation id="4388712255200933062"><ph name="CLOUD_PRINT_NAME"/> est conçu pour rendre l'impression plus intuitive, accessible et utile. <ph name="CLOUD_PRINT_NAME"/> vous permet de rendre vos imprimantes accessibles depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
++<translation id="2932611376188126394">Dictionnaire de kanji unique</translation>
++<translation id="5485754497697573575">Rétablir tous les onglets</translation>
++<translation id="3371861036502301517">Échec de l'installation de l'extension</translation>
++<translation id="644038709730536388">En savoir plus sur la manière de se protéger des logiciels malveillants en ligne</translation>
++<translation id="2155931291251286316">Toujours afficher les fenêtres pop-up de <ph name="HOST"/></translation>
++<translation id="3445830502289589282">Authentification phase 2 :</translation>
++<translation id="5650551054760837876">Aucun résultat de recherche trouvé</translation>
++<translation id="5494362494988149300">Ouvrir une fois le téléchargement &amp;terminé</translation>
++<translation id="2956763290572484660"><ph name="COOKIES"/> cookies</translation>
++<translation id="6989836856146457314">Mode de saisie du japonais (pour clavier américain)</translation>
++<translation id="9187787570099877815">Continuer à bloquer les plug-ins</translation>
++<translation id="8425492902634685834">Épingler sur la barre des tâches</translation>
++<translation id="825608351287166772">Les certificats ont une période de validité, comme tous les documents relatifs à votre identité (tel qu'un passeport). Le certificat présenté à votre navigateur n'est pas encore valide ! Lorsqu'un certificat est en dehors de sa période de validité, il n'est pas nécessaire d'assurer la maintenance de certaines informations relatives à son état (s'il a été révoqué ou s'il n'est plus approuvé). Par conséquent, il est impossible de vérifier que le certificat est fiable. Ne poursuivez pas.</translation>
++<translation id="741630086309232721">Fermer la session d'invité</translation>
++<translation id="7309459761865060639">Contrôlez vos tâches d'impression et l'état de connexion de vos imprimantes en ligne.</translation>
++<translation id="4803909571878637176">Désinstallation</translation>
++<translation id="5209518306177824490">Empreinte SHA-1</translation>
++<translation id="3300768886937313568">Modifier le code PIN de la carte SIM</translation>
++<translation id="7447657194129453603">État du réseau :</translation>
++<translation id="1553538517812678578">sans limite</translation>
++<translation id="7947315300197525319">(Choisir une autre capture d'écran)</translation>
++<translation id="3612070600336666959">Désactivation</translation>
++<translation id="3759461132968374835">Aucune erreur n'a été signalée récemment. Les erreurs n'apparaissent ici que lorsque l'envoi de rapports d'erreur est activé.</translation>
++<translation id="1516602185768225813">Rouvrir les dernières pages ouvertes</translation>
++<translation id="189210018541388520">Ouvrir en mode plein écran</translation>
++<translation id="8795668016723474529">Ajouter une carte de paiement</translation>
++<translation id="5860033963881614850">Désactivé</translation>
++<translation id="3956882961292411849">Chargement des informations sur votre forfait Internet mobile, veuillez patienter...</translation>
++<translation id="689050928053557380">Acheter un forfait de données...</translation>
++<translation id="4235618124995926194">Inclure cet e-mail :</translation>
++<translation id="4874539263382920044">Le titre doit comporter au moins un caractère.</translation>
++<translation id="798525203920325731">Espaces de noms réseau</translation>
++<translation id="263325223718984101"><ph name="PRODUCT_NAME"/> n'a pas pu terminer l'installation, mais va poursuivre son exécution à partir de son image disque.</translation>
++<translation id="7025190659207909717">Gestion des services Internet mobiles</translation>
++<translation id="8265096285667890932">Utiliser les onglets latéraux</translation>
++<translation id="4250680216510889253">Non</translation>
++<translation id="3949593566929137881">Saisir le code PIN de la carte SIM</translation>
++<translation id="6291953229176937411">&amp;Afficher dans le Finder</translation>
++<translation id="2476990193835943955">Maintenez la touche Ctrl, Alt ou Maj enfoncée&lt;br&gt;pour afficher le raccourci clavier qui lui est associé.</translation>
++<translation id="9187827965378254003">Vraiment désolé, aucun prototype n'est disponible pour le moment.</translation>
++<translation id="8933960630081805351">&amp;Afficher dans le Finder</translation>
++<translation id="3041612393474885105">Informations relatives au certificat</translation>
++<translation id="7378810950367401542">/</translation>
++<translation id="4611079913162790275">La synchronisation des mots de passe requiert votre attention.</translation>
++<translation id="6562758426028728553">Veuillez saisir l'ancien et le nouveau code PIN.</translation>
++<translation id="614161640521680948">Langue :</translation>
++<translation id="3665650519256633768">Résultats de recherche</translation>
++<translation id="3733127536501031542">Serveur SSL avec fonction d'optimisation</translation>
++<translation id="3614837889828516995">Enregistrer en PDF</translation>
++<translation id="5745056705311424885">Mémoire USB détectée</translation>
++<translation id="5895875028328858187">M'avertir lorsque le flux de données est faible ou presque inexistant</translation>
++<translation id="939598580284253335">Saisir le mot de passe multiterme</translation>
++<translation id="7917972308273378936">Clavier lituanien</translation>
++<translation id="8371806639176876412">Les éléments saisis dans le champ polyvalent peuvent être enregistrés.</translation>
++<translation id="4216499942524365685">Les informations de connexion à votre compte sont obsolètes. Cliquez ici pour saisir à nouveau votre mot de passe.</translation>
++<translation id="8899388739470541164">Vietnamien</translation>
++<translation id="4091434297613116013">feuilles de papier</translation>
++<translation id="7475671414023905704">URL de mot de passe perdu Netscape</translation>
++<translation id="3335947283844343239">Rouvrir l'onglet fermé</translation>
++<translation id="4089663545127310568">Effacer les mots de passe enregistrés</translation>
++<translation id="6500444002471948304">Créer un nouveau dossier...</translation>
++<translation id="2480626392695177423">Basculer en mode ponctuation pleine chasse ou demi-chasse</translation>
++<translation id="5830410401012830739">Gérer les paramètres de localisation...</translation>
++<translation id="8977410484919641907">Synchronisé...</translation>
++<translation id="2794293857160098038">Options de recherche par défaut</translation>
++<translation id="3947376313153737208">Aucune sélection</translation>
++<translation id="1346104802985271895">Mode de saisie du vietnamien (TELEX)</translation>
++<translation id="5935630983280450497"><ph name="NUMBER_ONE"/> minute restante</translation>
++<translation id="5889282057229379085">Le nombre maximal d'autorités de certification intermédiaires a été dépassé : <ph name="NUM_INTERMEDIATE_CA"/></translation>
++<translation id="3180365125572747493">Saisissez un mot de passe pour chiffrer ce fichier de certificat.</translation>
++<translation id="5496587651328244253">Organiser</translation>
++<translation id="4821086771593057290">Votre mot de passe a changé. Veuillez réessayer avec votre nouveau mot de passe.</translation>
++<translation id="7075513071073410194">PKCS #1 MD5 avec chiffrement RSA</translation>
++<translation id="4378727699507047138">Utiliser le thème classique</translation>
++<translation id="7124398136655728606">Échap efface toute la mémoire tampon de pré-édition</translation>
++<translation id="8293206222192510085">Ajouter aux favoris</translation>
++<translation id="2592884116796016067">Un incident est survenu sur une partie de cette page (HTML WebWorker). Elle risque de ne pas fonctionner correctement.</translation>
++<translation id="2529133382850673012">Clavier américain</translation>
++<translation id="4411578466613447185">Signataire de code</translation>
++<translation id="1354868058853714482">Adobe Reader n'est pas à jour et risque de ne plus être sécurisé.</translation>
++<translation id="6252594924928912846">Personnaliser les paramètres de synchronisation...</translation>
++<translation id="8425755597197517046">Co&amp;ller et rechercher</translation>
++<translation id="1093148655619282731">Détails du certificat sélectionné :</translation>
++<translation id="5568069709869097550">Impossible de se connecter</translation>
++<translation id="2743322561779022895">Activation :</translation>
++<translation id="4181898366589410653">Système de révocation introuvable dans le certificat du serveur</translation>
++<translation id="8705331520020532516">Numéro de série</translation>
++<translation id="1665770420914915777">Afficher la page &quot;Nouvel onglet&quot;</translation>
++<translation id="2629089419211541119">il y a <ph name="NUMBER_ONE"/> heure</translation>
++<translation id="1691063574428301566">Votre ordinateur redémarrera une fois la mise à jour effectuée.</translation>
++<translation id="131364520783682672">Verr. maj.</translation>
++<translation id="6259308910735500867">L'accès au répertoire de l'hôte de communication à distance a été refusé. Essayez avec un autre compte.</translation>
++<translation id="3415261598051655619">Accessible aux scripts :</translation>
++<translation id="2335122562899522968">Cette page place des cookies.</translation>
++<translation id="8461914792118322307">Proxy</translation>
++<translation id="4089521618207933045">Avec sous-menu</translation>
++<translation id="1936157145127842922">Afficher dans le dossier</translation>
++<translation id="6982279413068714821">il y a <ph name="NUMBER_DEFAULT"/> minutes</translation>
++<translation id="7977590112176369853">&lt;saisir une requête&gt;</translation>
++<translation id="3449839693241009168">Appuyez sur <ph name="SEARCH_KEY"/> pour envoyer des commandes à <ph name="EXTENSION_NAME"/>.</translation>
++<translation id="7443484992065838938">Prévisualiser le rapport</translation>
++<translation id="5714678912774000384">Activer le dernier onglet</translation>
++<translation id="3799598397265899467">Lorsque je quitte le navigateur</translation>
++<translation id="2125314715136825419">Continuer sans mettre à jour Adobe Reader (non recommandé)</translation>
++<translation id="1120026268649657149">Le champ de mot clé doit être vide ou comporter un mot unique</translation>
++<translation id="542318722822983047">Déplacer le curseur automatiquement au caractère suivant</translation>
++<translation id="5317780077021120954">Enregistrer</translation>
++<translation id="9027459031423301635">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
++<translation id="2251809247798634662">Nouvelle fenêtre de navigation privée</translation>
++<translation id="358344266898797651">Celtique</translation>
++<translation id="3625870480639975468">Réinitialiser le zoom</translation>
++<translation id="5199729219167945352">Prototypes</translation>
++<translation id="5055518462594137986">Mémoriser mes choix pour tous les liens de ce type</translation>
++<translation id="246059062092993255">Les plug-ins de cette page ont été bloqués.</translation>
++<translation id="2870560284913253234">Site</translation>
++<translation id="6945221475159498467">Sélectionner</translation>
++<translation id="7724603315864178912">Couper</translation>
++<translation id="4164507027399414915">Restaurer toutes les miniatures supprimées</translation>
++<translation id="917051065831856788">Utiliser les onglets latéraux</translation>
++<translation id="1976150099241323601">Se connecter au dispositif de sécurité</translation>
++<translation id="6620110761915583480">Enregistrer le fichier</translation>
++<translation id="4988526792673242964">Pages</translation>
++<translation id="7543025879977230179">Options de <ph name="PRODUCT_NAME"/></translation>
++<translation id="2175607476662778685">Barre de lancement rapide</translation>
++<translation id="6434309073475700221">Annuler</translation>
++<translation id="1367951781824006909">Choisir un fichier</translation>
++<translation id="1425127764082410430">&amp;Rechercher <ph name="SEARCH_TERMS"/> avec <ph name="SEARCH_ENGINE"/></translation>
++<translation id="684265517037058883">(pas encore valide)</translation>
++<translation id="2027538664690697700">Mettre à jour le plug-in...</translation>
++<translation id="8205333955675906842">Police Sans-Serif</translation>
++<translation id="39964277676607559">Impossible de charger le JavaScript &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
++<translation id="4378551569595875038">Connexion...</translation>
++<translation id="7029809446516969842">Mots de passe</translation>
++<translation id="8053278772142718589">Fichiers PKCS #12</translation>
++<translation id="3129020372442395066">Options de saisie automatique de <ph name="PRODUCT_NAME_SHORT"/></translation>
++<translation id="4114360727879906392">Fenêtre précédente</translation>
++<translation id="8238649969398088015">Astuce</translation>
++<translation id="5958418293370246440"><ph name="SAVED_FILES"/> / <ph name="TOTAL_FILES"/> fichiers</translation>
++<translation id="2350172092385603347">Localisation utilisée, mais les paramètres régionaux par défaut (default_locale) n'ont pas été indiqués dans le manifeste. </translation>
++<translation id="8221729492052686226">Si vous n'êtes pas à l'origine de cette requête, il s'agit probablement d'une attaque contre votre système. Si vous n'avez pas lancé cette requête de manière intentionnelle, cliquez sur Ne rien faire.</translation>
++<translation id="5894314466642127212">Votre commentaire a bien été envoyé.</translation>
++<translation id="894360074127026135">Fonction d'optimisation internationale Netscape </translation>
++<translation id="6025294537656405544">Taille de police minimale</translation>
++<translation id="1201402288615127009">Suivant</translation>
++<translation id="1335588927966684346">Utilitaire :</translation>
++<translation id="7857823885309308051">Cette opération peut prendre une minute...</translation>
++<translation id="662870454757950142">Le format du mot de passe est incorrect.</translation>
++<translation id="370665806235115550">Chargement...</translation>
++<translation id="1808792122276977615">Ajouter la page...</translation>
++<translation id="2076269580855484719">Masquer ce plug-in</translation>
++<translation id="254416073296957292">&amp;Paramètres linguistiques...</translation>
++<translation id="6652975592920847366">Créer un support de récupération du système d'exploitation</translation>
++<translation id="52912272896845572">Le fichier de clé privée est incorrect.</translation>
++<translation id="3232318083971127729">Valeur :</translation>
++<translation id="8807632654848257479">Stable</translation>
++<translation id="4209092469652827314">Grande</translation>
++<translation id="4222982218026733335">Certificat serveur invalide</translation>
++<translation id="152234381334907219">Jamais enregistrés</translation>
++<translation id="5600599436595580114">Cette page a été préchargée.</translation>
++<translation id="8926468725336609312">Google Chrome ne peut pas afficher l'aperçu avant impression lorsque la visionneuse de documents PDF intégrée est désactivée. Pour l'afficher, veuillez accéder à <ph name="BEGIN_LINK"/>chrome://plugins<ph name="END_LINK"/>, activer &quot;Chrome PDF Viewer&quot; et réessayer.</translation>
++<translation id="8494214181322051417">Nouveau !</translation>
++<translation id="7762841930144642410"><ph name="BEGIN_BOLD"/>Vous êtes passé en navigation privée<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront ni dans l'historique de votre navigateur, ni dans l'historique des recherches, et ne laisseront aucune trace (comme les cookies) sur votre ordinateur une fois que vous aurez fermé la fenêtre de navigation privée. Tous les fichiers téléchargés et les favoris créés seront toutefois conservés. <ph name="LINE_BREAK"/> <ph name="BEGIN_BOLD"/>Passer en navigation privée n'a aucun effet sur les autres utilisateurs, serveurs ou logiciels. Méfiez-vous :<ph name="END_BOLD"/> <ph name="BEGIN_LIST"/> <ph name="BEGIN_LIST_ITEM"/>Des sites Web qui collectent ou partagent des informations vous concernant<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des fournisseurs d'accès Internet ou des employeurs qui conservent une trace des pages que vous visitez<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des programmes indésirables qui enregistrent vos frappes en échange d'émoticônes gratuites<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui pourraient surveiller vos activités<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui se tiennent derrière vous<ph name="END_LIST_ITEM"/> <ph name="END_LIST"/> <ph name="BEGIN_LINK"/>En savoir plus sur la navigation privée<ph name="END_LINK"/></translation>
++<translation id="2386255080630008482">Le certificat du serveur a été révoqué.</translation>
++<translation id="2135787500304447609">&amp;Reprendre</translation>
++<translation id="8309505303672555187">Sélectionnez un réseau :</translation>
++<translation id="6143635259298204954">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils ne contenant pas de lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
++<translation id="1813414402673211292">Effacer les données de navigation</translation>
++<translation id="4062903950301992112">Si vous êtes conscient que la visite de ce site peut être préjudiciable à votre ordinateur, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
++<translation id="32330993344203779">Votre périphérique est inscrit pour bénéficier de la gestion d'entreprise.</translation>
++<translation id="2356762928523809690">Serveur de mise à jour non disponible (erreur : <ph name="ERROR_NUMBER"/>)</translation>
++<translation id="219008588003277019">Module client natif : <ph name="NEXE_NAME"/></translation>
++<translation id="5436510242972373446">Rechercher sur <ph name="SITE_NAME"/> :</translation>
++<translation id="3800764353337460026">Style de symboles</translation>
++<translation id="6719684875142564568"><ph name="NUMBER_ZERO"/> hours</translation>
++<translation id="2096368010154057602">Département</translation>
++<translation id="1036561994998035917">Continuer à utiliser <ph name="ENGINE_NAME"/></translation>
++<translation id="8730621377337864115">OK</translation>
++<translation id="665757950158579497">Essayez de désactiver les prédictions d'actions du réseau en procédant comme suit :
++ Sélectionnez le
++ <ph name="BEGIN_BOLD"/>
++ menu clé à molette &gt;
++ <ph name="SETTINGS_TITLE"/>
++ &gt;
++ <ph name="ADVANCED_TITLE"/>
++ <ph name="END_BOLD"/>
++ et désélectionnez &quot;<ph name="NO_PREFETCH_DESCRIPTION"/>&quot;.
++ Si le problème n'est pas résolu, nous vous conseillons de sélectionner de nouveau
++ cette option pour améliorer les performances.</translation>
++<translation id="4932733599132424254">Date</translation>
++<translation id="6267166720438879315">Sélectionnez un certificat pour vous authentifier sur <ph name="HOST_NAME"/>.</translation>
++<translation id="2422927186524098759">Barre latérale</translation>
++<translation id="7839809549045544450">La clé publique éphémère Diffie-Hellman associée au serveur est peu sûre.</translation>
++<translation id="5515806255487262353">Rechercher dans Dictionnaire</translation>
++<translation id="350048665517711141">Sélectionnez un moteur de recherche</translation>
++<translation id="2790805296069989825">Clavier russe</translation>
++<translation id="5708171344853220004">Nom Microsoft principal</translation>
++<translation id="5464696796438641524">Clavier polonais</translation>
++<translation id="2080010875307505892">Clavier serbe</translation>
++<translation id="2953767478223974804"><ph name="NUMBER_ONE"/> minute</translation>
++<translation id="201192063813189384">Erreur lors de la lecture des données du cache.</translation>
++<translation id="7851768487828137624">Canary</translation>
++<translation id="6129938384427316298">Commentaire du certificat Netscape</translation>
++<translation id="8210608804940886430">Page suivante</translation>
++<translation id="9065596142905430007"><ph name="PRODUCT_NAME"/> est à jour.</translation>
++<translation id="1035650339541835006">Paramètres de saisie automatique...</translation>
++<translation id="6315493146179903667">Tout ramener au premier plan</translation>
++<translation id="1000498691615767391">Sélectionner le dossier à ouvrir</translation>
++<translation id="3593152357631900254">Activer le mode Pinyin fuzzy</translation>
++<translation id="5015344424288992913">Résolution du proxy...</translation>
++<translation id="8506299468868975633">Le téléchargement de l'image a été interrompu.</translation>
++<translation id="4724168406730866204">Eten 26</translation>
++<translation id="308268297242056490">URI</translation>
++<translation id="4479812471636796472">Clavier Dvorak américain</translation>
++<translation id="8673026256276578048">Rechercher sur le Web...</translation>
++<translation id="1437307674059038925">Si vous utilisez un serveur proxy, vérifiez les paramètres associés ou demandez à votre administrateur réseau
++ si ce serveur fonctionne.</translation>
++<translation id="149347756975725155">Impossible de charger l'icône de l'extension &quot;<ph name="ICON"/>&quot;.</translation>
++<translation id="3675321783533846350">Définir un proxy pour se connecter au réseau</translation>
++<translation id="5451285724299252438">zone de texte concernant l'étendue de pages</translation>
++<translation id="5669267381087807207">Activation</translation>
++<translation id="7434823369735508263">Clavier Dvorak britannique</translation>
++<translation id="1572103024875503863"><ph name="NUMBER_MANY"/> jours</translation>
++<translation id="2084978867795361905">MS-IME</translation>
++<translation id="7227669995306390694">Aucun forfait de données <ph name="NETWORK"/></translation>
++<translation id="3481915276125965083">Les fenêtres pop-up suivantes ont été bloquées sur cette page :</translation>
++<translation id="7163503212501929773"><ph name="NUMBER_MANY"/> heures restantes</translation>
++<translation id="7705276765467986571">Impossible de charger le modèle du favori.</translation>
++<translation id="1196338895211115272">Échec d'exportation de la clé privée</translation>
++<translation id="5586329397967040209">Utiliser comme page d'accueil</translation>
++<translation id="629730747756840877">Compte</translation>
++<translation id="8525306231823319788">Plein écran</translation>
++<translation id="9054208318010838">Autoriser tous les sites à suivre ma position géographique</translation>
++<translation id="3058212636943679650">Si la restauration du système d'exploitation de votre ordinateur s'avère nécessaire, une carte SD ou une clé USB de récupération vous sera demandée.</translation>
++<translation id="2815382244540487333">Les cookies suivants ont été bloqués :</translation>
++<translation id="8882395288517865445">Inclure les adresses de ma fiche de Carnet d’adresses</translation>
++<translation id="374530189620960299">Le certificat de sécurité du site n'est pas approuvé !</translation>
++<translation id="8852407435047342287">Votre liste d'applications, d'extensions et de thèmes installés</translation>
++<translation id="5647283451836752568">Exécuter tous les plug-ins de cette page</translation>
++<translation id="8642947597466641025">Augmente la taille du texte</translation>
++<translation id="5188181431048702787">Accepter et continuer »</translation>
++<translation id="1293556467332435079">Fichiers
++</translation>
++<translation id="2490270303663597841">Appliquer uniquement à cette session de navigation privée</translation>
++<translation id="1757915090001272240">Latin large</translation>
++<translation id="8496717697661868878">Exécuter ce plug-in</translation>
++<translation id="3450660100078934250">MasterCard</translation>
++<translation id="2916073183900451334">Sur le Web, Tab permet de sélectionner les liens, ainsi que les champs de formulaire.</translation>
++<translation id="7772127298218883077">À propos de <ph name="PRODUCT_NAME"/></translation>
++<translation id="2090876986345970080">Paramètres de sécurité du système</translation>
++<translation id="9219103736887031265">Images</translation>
++<translation id="5453632173748266363">Cyrillique</translation>
++<translation id="1008557486741366299">Pas maintenant</translation>
++<translation id="8415351664471761088">Attendre la fin du téléchargement</translation>
++<translation id="1545775234664667895">Thème &quot;<ph name="THEME_NAME"/>&quot; installé</translation>
++<translation id="5329858601952122676">&amp;Supprimer</translation>
++<translation id="6100736666660498114">Menu Démarrer</translation>
++<translation id="3994878504415702912">&amp;Zoom</translation>
++<translation id="9009369504041480176">Transfert en cours (<ph name="PROGRESS_PERCENT"/> %)...</translation>
++<translation id="8995603266996330174">Géré par <ph name="DOMAIN"/></translation>
++<translation id="5602600725402519729">&amp;Rafraîchir</translation>
++<translation id="172612876728038702">Configuration du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, cela peut prendre quelques minutes.</translation>
++<translation id="1362165759943288856">Vous avez acheté une quantité illimitée de données le <ph name="DATE"/>.</translation>
++<translation id="2078019350989722914">Confirmer avant de quitter (<ph name="KEY_EQUIVALENT"/>)</translation>
++<translation id="7965010376480416255">Mémoire partagée</translation>
++<translation id="6248988683584659830">Rech. dans les paramètres</translation>
++<translation id="8323232699731382745">mot de passe d'accès au réseau</translation>
++<translation id="6588399906604251380">Activer la vérification orthographique</translation>
++<translation id="7167621057293532233">Types de données</translation>
++<translation id="7053983685419859001">Bloquer</translation>
++<translation id="2485056306054380289">Certificat de l'autorité de certification du serveur :</translation>
++<translation id="6462109140674788769">Clavier grec</translation>
++<translation id="2727712005121231835">Taille réelle</translation>
++<translation id="8887733174653581061">Toujours en haut</translation>
++<translation id="5581211282705227543">Aucun plug-in installé.</translation>
++<translation id="610886263749567451">Alerte JavaScript</translation>
++<translation id="5488468185303821006">Autoriser en mode navigation privée</translation>
++<translation id="6556866813142980365">Rétablir</translation>
++<translation id="2107287771748948380"><ph name="OBFUSCATED_CC_NUMBER"/>, expire le : <ph name="CC_EXPIRATION_DATE"/></translation>
++<translation id="6584811624537923135">Confirmer la désinstallation</translation>
++<translation id="7429235532957570505">Impossible de désactiver les plug-ins ayant été activés par une stratégie d'entreprise.</translation>
++<translation id="7866522434127619318">Cette fonctionnalité active l'option &quot;Lire en un clic&quot; dans les paramètres de contenu du plug-in.</translation>
++<translation id="8860923508273563464">Attendre la fin des téléchargements</translation>
++<translation id="6406506848690869874">Synchronisation</translation>
++<translation id="5288678174502918605">&amp;Rouvrir l'onglet fermé</translation>
++<translation id="7238461040709361198">Votre mot de passe de compte Google a changé depuis votre dernière connexion à partir de cet ordinateur.</translation>
++<translation id="1956050014111002555">Le fichier contenait plusieurs certificats, aucun d'eux n'a été importé :</translation>
++<translation id="302620147503052030">Afficher le bouton</translation>
++<translation id="5512074755152723588">La saisie dans le champ polyvalent d'une URL déjà ouverte dans un autre onglet entraîne l'affichage de l'onglet en question, et non l'affichage de l'URL dans l'onglet actuel.</translation>
++<translation id="9157595877708044936">Configuration en cours...</translation>
++<translation id="4475552974751346499">Rechercher dans les téléchargements</translation>
++<translation id="3021256392995617989">Me demander lorsqu'un site tente de suivre ma position géographique (recommandé)</translation>
++<translation id="5185386675596372454">La nouvelle version de &quot;<ph name="EXTENSION_NAME"/>&quot; a été désactivée, car elle nécessite davantage d'autorisations.</translation>
++<translation id="4285669636069255873">Clavier phonétique russe</translation>
++<translation id="4148925816941278100">American Express</translation>
++<translation id="2320435940785160168">Ce serveur exige un certificat d'authentification et n'a pas accepté celui envoyé par le navigateur.
++Votre certificat a peut-être expiré ou le serveur n'a pas approuvé l'émetteur.
++Réessayez avec un autre certificat si vous en avez un.
++Sinon, vous devrez en obtenir un nouveau d'un autre émetteur.</translation>
++<translation id="6295228342562451544">Lorsque vous vous connectez à un site Web sécurisé, le serveur hébergeant ce site présente à votre navigateur un &quot;certificat&quot; afin de vérifier l'identité du site. Ce certificat contient des informations d'identité, telles que l'adresse du site Web, laquelle est vérifiée par un tiers approuvé par votre ordinateur. En vérifiant que l'adresse du certificat correspond à l'adresse du site Web, il est possible de s'assurer que vous êtes connecté de façon sécurisée avec le site Web souhaité et non pas avec un tiers (tel qu'un pirate informatique sur votre réseau).</translation>
++<translation id="6342069812937806050">À l'instant</translation>
++<translation id="5605716740717446121">Votre carte SIM sera définitivement désactivée si vous ne saisissez pas correctement la clé de déverrouillage du code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
++<translation id="8836712291807476944"><ph name="SAVED_BYTES"/> / <ph name="TOTAL_BYTES"/> octets, Interrompu</translation>
++<translation id="5502500733115278303">Importés depuis Firefox</translation>
++<translation id="569109051430110155">Détection automatique</translation>
++<translation id="4408599188496843485">&amp;Aide</translation>
++<translation id="5399158067281117682">Les codes PIN sont différents !</translation>
++<translation id="8494234776635784157">Contenu Web</translation>
++<translation id="2681441671465314329">Vider le cache</translation>
++<translation id="3646789916214779970">Rétablir le thème par défaut</translation>
++<translation id="1592960452683145077">Le service de communication à distance a démarré correctement. Vous devriez maintenant pouvoir vous connecter à distance à cet ordinateur.</translation>
++<translation id="1679068421605151609">Outils de développement</translation>
++<translation id="6648524591329069940">Police Serif</translation>
++<translation id="6896758677409633944">Copier</translation>
++<translation id="5260508466980570042">Adresse e-mail ou mot de passe incorrect. Veuillez réessayer.</translation>
++<translation id="7887998671651498201">Le plug-in suivant ne répond pas : souhaitez-vous interrompre <ph name="PLUGIN_NAME"/> ?</translation>
++<translation id="173188813625889224">Sens</translation>
++<translation id="8088823334188264070"><ph name="NUMBER_MANY"/> secondes</translation>
++<translation id="1337036551624197047">Clavier tchèque</translation>
++<translation id="4212108296677106246">Voulez-vous que &quot;<ph name="CERTIFICATE_NAME"/>&quot; soit considérée comme une autorité de certification fiable ?</translation>
++<translation id="2861941300086904918">Gestionnaire de sécurité natif du client</translation>
++<translation id="6991443949605114807">&lt;p&gt;Lorsque vous exécutez <ph name="PRODUCT_NAME"/> dans un environnement de bureau pris en charge, les paramètres proxy du système sont utilisés. Toutefois, soit votre système n'est pas pris en charge, soit un problème est survenu lors du lancement de votre configuration système.&lt;/p&gt;
++
++ &lt;p&gt;Vous avez toujours la possibilité d'effectuer la configuration via la ligne de commande. Pour plus d'informations sur les indicateurs et les variables d'environnement, veuillez vous reporter à &lt;code&gt;man <ph name="PRODUCT_BINARY_NAME"/>&lt;/code&gt;.&lt;/p&gt;</translation>
++<translation id="9071590393348537582">La page Web à l'adresse <ph name="URL"/> a déclenché trop de redirections. Pour résoudre le problème, effacez les cookies de ce site ou autorisez les cookies tiers. Si le problème persiste, il peut être dû à une mauvaise configuration du serveur et n'être aucunement lié à votre ordinateur.</translation>
++<translation id="7205869271332034173">SSID :</translation>
++<translation id="7084579131203911145">Nom du forfait :</translation>
++<translation id="5815645614496570556">Adresse X.400</translation>
++<translation id="3551320343578183772">Fermer l'onglet</translation>
++<translation id="3345886924813989455">Impossible de trouver un navigateur pris en charge.</translation>
++<translation id="74354239584446316">Le compte associé à la boutique en ligne est le suivant : <ph name="EMAIL_ADDRESS"/>. L'utilisation d'un autre compte pour la synchronisation provoque des erreurs.</translation>
++<translation id="3712897371525859903">Enregistrer la p&amp;age sous...</translation>
++<translation id="7926251226597967072"><ph name="PRODUCT_NAME"/> importe actuellement les éléments suivants à partir de <ph name="IMPORT_BROWSER_NAME"/> :</translation>
++<translation id="2767649238005085901">Appuyez sur Entrée pour avancer et sur la touche de menu contextuel pour afficher l'historique</translation>
++<translation id="8580634710208701824">Actualiser le cadre</translation>
++<translation id="1018656279737460067">Annulé</translation>
++<translation id="7606992457248886637">Autorités</translation>
++<translation id="707392107419594760">Sélectionnez votre clavier :</translation>
++<translation id="2007404777272201486">Signaler un problème...</translation>
++<translation id="2390045462562521613">Ignorer ce réseau</translation>
++<translation id="3348038390189153836">Nouveau matériel détecté</translation>
++<translation id="1666788816626221136">Vous disposez de certificats qui n'appartiennent à aucune autre catégorie :</translation>
++<translation id="4821935166599369261">&amp;Profilage activé</translation>
++<translation id="1603914832182249871">(Navigation privée)</translation>
++<translation id="7910768399700579500">&amp;Nouveau dossier</translation>
++<translation id="7472639616520044048">Types MIME :</translation>
++<translation id="2307164895203900614">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
++<translation id="3192947282887913208">Fichiers audio</translation>
++<translation id="6295535972717341389">Plug-ins</translation>
++<translation id="8116190140324504026">Plus d'informations...</translation>
++<translation id="7469894403370665791">Se connecter automatiquement à ce réseau</translation>
++<translation id="4807098396393229769">Titulaire de la carte</translation>
++<translation id="4094130554533891764">Elle peut désormais accéder à :</translation>
++<translation id="4131410914670010031">Noir et blanc</translation>
++<translation id="3800503346337426623">Ignorer la connexion et naviguer en tant qu'invité</translation>
++<translation id="2615413226240911668">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer l'aspect et le comportement de cette page.</translation>
++<translation id="5880867612172997051">Accès réseau interrompu</translation>
++<translation id="7842346819602959665">La dernière version de l'extension &quot;<ph name="EXTENSION_NAME"/>&quot; requiert d'autres permissions. Elle a donc été désactivée.</translation>
++<translation id="3776667127601582921">Dans ce cas, le certificat du serveur ou un certificat d'autorité intermédiaire présenté à votre navigateur n'est pas valide. Cela peut signifier que le certificat est incorrect, qu'il contient des champs non valides ou qu'il n'est pas compatible.</translation>
++<translation id="2412835451908901523">Veuillez saisir la clé de déverrouillage du code PIN à 8 chiffres fournie par <ph name="CARRIER_ID"/>.</translation>
++<translation id="6979448128170032817">Exceptions...</translation>
++<translation id="7584802760054545466">Connexion à <ph name="NETWORK_ID"/></translation>
++<translation id="208047771235602537">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors qu'un téléchargement est en cours ?</translation>
++<translation id="4060383410180771901">Le site Web ne parvient pas à gérer la demande associée à <ph name="URL"/>.</translation>
++<translation id="6710213216561001401">Précédent</translation>
++<translation id="1108600514891325577">&amp;Arrêter</translation>
++<translation id="6035087343161522833">Lorsque l'option permettant de bloquer l'enregistrement des cookies tiers est activée, la lecture de ces cookies est également bloquée.</translation>
++<translation id="8619892228487928601"><ph name="CERTIFICATE_NAME"/> : <ph name="ERROR"/></translation>
++<translation id="1567993339577891801">Console JavaScript</translation>
++<translation id="1548132948283577726">Les sites pour lesquels vos mots de passe ne seront jamais enregistrés s'afficheront ici.</translation>
++<translation id="583281660410589416">Inconnu</translation>
++<translation id="3774278775728862009">Mode de saisie du thaï (clavier TIS-820.2538)</translation>
++<translation id="9115675100829699941">&amp;Favoris</translation>
++<translation id="2485422356828889247">Désinstaller</translation>
++<translation id="2621889926470140926">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors que <ph name="DOWNLOAD_COUNT"/> téléchargements sont en cours ?</translation>
++<translation id="7279701417129455881">Configurer le blocage des cookies...</translation>
++<translation id="1166359541137214543">ABC</translation>
++<translation id="5412713837047574330">L'application hébergée par <ph name="HOST_NAME"/> est inaccessible, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
++<translation id="5528368756083817449">Gestionnaire de favoris</translation>
++<translation id="7275974018215686543"><ph name="NUMBER_MANY"/> secs ago</translation>
++<translation id="215753907730220065">Quitter le mode plein écran</translation>
++<translation id="7849264908733290972">Ouvrir l'&amp;image dans un nouvel onglet</translation>
++<translation id="1560991001553749272">Favori ajouté !</translation>
++<translation id="3966072572894326936">Choisir un autre dossier...</translation>
++<translation id="8766796754185931010">Kotoeri</translation>
++<translation id="7781829728241885113">Hier</translation>
++<translation id="2762402405578816341">Synchroniser automatiquement les éléments suivants :</translation>
++<translation id="1623661092385839831">Votre ordinateur intègre un périphérique de sécurité TPM (module de plate-forme sécurisée) qui permet de mettre en œuvre plusieurs fonctionnalités de sécurité critiques dans Google Chrome OS.</translation>
++<translation id="3359256513598016054">Contraintes des stratégies de certificat</translation>
++<translation id="4433914671537236274">Créer un support de récupération</translation>
++<translation id="4509345063551561634">Emplacement :</translation>
++<translation id="7596288230018319236">Toutes les pages que vous consultez apparaîtront ici à moins que vous ne les ouvriez dans une fenêtre en navigation privée. Vous pouvez utiliser le bouton Rechercher de cette page pour rechercher dans toutes les pages de votre historique.</translation>
++<translation id="7434509671034404296">Options pour les développeurs</translation>
++<translation id="6447842834002726250">Cookies</translation>
++<translation id="2609371827041010694">Toujours exécuter pour ce site</translation>
++<translation id="5170568018924773124">Afficher le dossier</translation>
++<translation id="883848425547221593">Autres favoris</translation>
++<translation id="6054173164583630569">Clavier français</translation>
++<translation id="4870177177395420201"><ph name="PRODUCT_NAME"/> ne parvient pas à déterminer ou à définir le navigateur par défaut.</translation>
++<translation id="8898786835233784856">Sélectionner l'onglet suivant</translation>
++<translation id="2674170444375937751">Voulez-vous vraiment supprimer ces pages de votre historique ?</translation>
++<translation id="9111102763498581341">Déverrouiller</translation>
++<translation id="289695669188700754">ID de clé : <ph name="KEY_ID"/></translation>
++<translation id="3067198360141518313">Exécuter ce plug-in</translation>
++<translation id="8767072502252310690">Utilisateurs</translation>
++<translation id="683526731807555621">Ajouter un moteur</translation>
++<translation id="6871644448911473373">Répondeur OCSP : <ph name="LOCATION"/></translation>
++<translation id="8281886186245836920">Ignorer</translation>
++<translation id="3867944738977021751">Champs de certificat</translation>
++<translation id="2114224913786726438">Modules (<ph name="TOTAL_COUNT"/>) : aucun conflit détecté.</translation>
++<translation id="7629827748548208700">Onglet : <ph name="TAB_NAME"/></translation>
++<translation id="388442998277590542">Impossible de charger la page d'options &quot;<ph name="OPTIONS_PAGE"/>&quot;.</translation>
++<translation id="8449008133205184768">Coller en adaptant le style</translation>
++<translation id="9114223350847410618">Veuillez ajouter une autre langue avant de supprimer celle-ci.</translation>
++<translation id="4408427661507229495">nom du réseau</translation>
++<translation id="8886960478266132308"><ph name="PRODUCT_NAME"/> synchronise de manière sécurisée vos données avec votre compte Google.</translation>
++<translation id="8028993641010258682">Taille</translation>
++<translation id="5031603669928715570">Activer...</translation>
++<translation id="1383876407941801731">Recherche</translation>
++<translation id="8398877366907290961">Poursuivre quand même</translation>
++<translation id="5063180925553000800">Nouveau code PIN :</translation>
++<translation id="2496540304887968742">La capacité du périphérique doit être d'au moins 4 Go.</translation>
++<translation id="6974053822202609517">De droite à gauche</translation>
++<translation id="2370882663124746154">Activer le mode Pinyin double</translation>
++<translation id="5463856536939868464">Menu contenant des favoris masqués</translation>
++<translation id="8286227656784970313">Utiliser le dictionnaire système</translation>
++<translation id="5431084084184068621">Vous avez choisi de chiffrer les données à l'aide de votre mot de passe Google. Vous pouvez modifier vos paramètres de synchronisation à tout moment, si vous changez d'avis.</translation>
++<translation id="1493263392339817010">Personnaliser les polices...</translation>
++<translation id="5352033265844765294">Enregistrement des informations de date</translation>
++<translation id="6449085810994685586">&amp;Vérifier l'orthographe du texte de ce champ</translation>
++<translation id="3621320549246006887">Ceci est un modèle expérimental qui permet aux enregistrements DNS (utilisant le protocole de sécurité DNSSEC) d'autoriser ou de refuser des certificats HTTPS. Ce message s'affiche lorsque vous activez des fonctionnalités expérimentales via des options de ligne de commande. Vous pouvez supprimer ces options de ligne de commande pour ignorer cette erreur.</translation>
++<translation id="50960180632766478"><ph name="NUMBER_FEW"/> minutes restantes</translation>
++<translation id="3174168572213147020">Île</translation>
++<translation id="748138892655239008">Contraintes de base du certificat</translation>
++<translation id="457386861538956877">Autres...</translation>
++<translation id="8063491445163840780">Activer l'onglet 4</translation>
++<translation id="5966654788342289517">Données personnelles</translation>
++<translation id="9137013805542155359">Afficher l'original</translation>
++<translation id="4792385443586519711">Nom de la société</translation>
++<translation id="6423731501149634044">Définir Adobe Reader comme visionneuse de documents PDF par défaut ?</translation>
++<translation id="8839907368860424444">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Fenêtre.</translation>
++<translation id="2461687051570989462">Accédez à vos imprimantes depuis n'importe quel ordinateur ou smartphone. <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/></translation>
++<translation id="7194430665029924274">Me &amp;le rappeler plus tard</translation>
++<translation id="5790085346892983794">Opération réussie !</translation>
++<translation id="1901769927849168791">Carte SD détectée.</translation>
++<translation id="818454486170715660"><ph name="NAME"/> - Propriétaire</translation>
++<translation id="1358032944105037487">Clavier japonais</translation>
++<translation id="8201956630388867069">WPA</translation>
++<translation id="603890000178803545">janv.^févr.^mars^avr.^mai^juin^juil.^août^sept.^oct.^nov.^déc.</translation>
++<translation id="8302838426652833913">Sélectionnez
++ <ph name="BEGIN_BOLD"/>
++ Applications &gt; Préférences système &gt; Réseau &gt; Assistant
++ <ph name="END_BOLD"/>
++ pour tester votre connexion.</translation>
++<translation id="8664389313780386848">&amp;Afficher le code source de la page</translation>
++<translation id="8970407809569722516">Micrologiciel :</translation>
++<translation id="1180549724812639004">Créer un profil</translation>
++<translation id="57646104491463491">Date de modification</translation>
++<translation id="5992752872167177798">Sandbox seccomp</translation>
++<translation id="6362853299801475928">Signale&amp;r un problème...</translation>
++<translation id="3289566588497100676">Entrée de symboles simplifiée</translation>
++<translation id="6507969014813375884">Chinois simplifié</translation>
++<translation id="7314244761674113881">Hôte SOCKS</translation>
++<translation id="5285794783728826432">Considérer ce certificat comme fiable pour identifier les sites Web.</translation>
++<translation id="4224803122026931301">Exceptions de localisation</translation>
++<translation id="749452993132003881">Hiragana</translation>
++<translation id="8226742006292257240">Le mot de passe TPM ci-dessous, généré de façon aléatoire, a été attribué à votre ordinateur :</translation>
++<translation id="8487693399751278191">Importer mes favoris maintenant...</translation>
++<translation id="7985242821674907985"><ph name="PRODUCT_NAME"/></translation>
++<translation id="7484580869648358686">Avertissement : Un problème a été détecté sur cette page.</translation>
++<translation id="2074739700630368799">Avec Google Chrome OS for business, vous pouvez connecter votre périphérique à Google Apps, ce qui vous permet de le rechercher et de le contrôler depuis le panneau de configuration de Google Apps.</translation>
++<translation id="4474155171896946103">Ajouter tous les onglets aux favoris...</translation>
++<translation id="5895187275912066135">Émis le</translation>
++<translation id="1190844492833803334">Lorsque je ferme le navigateur</translation>
++<translation id="5646376287012673985">Localisation</translation>
++<translation id="1110155001042129815">Attendre</translation>
++<translation id="2607101320794533334">Infos sur la clé publique de l'objet</translation>
++<translation id="7071586181848220801">Plug-in inconnu</translation>
++<translation id="3354601307791487577">Connexion en mode invité</translation>
++<translation id="4419409365248380979">Toujours autoriser <ph name="HOST"/> à paramétrer les cookies</translation>
++<translation id="2956070106555335453">Résumé</translation>
++<translation id="917450738466192189">Le certificat du serveur n'est pas valide.</translation>
++<translation id="2649045351178520408">Chaîne de certificats codés Base 64 ASCII</translation>
++<translation id="7424526482660971538">Choisir mon propre mot de passe multiterme</translation>
++<translation id="380271916710942399">Certificat de serveur non répertorié</translation>
++<translation id="6459488832681039634">Rechercher la sélection</translation>
++<translation id="2392369802118427583">Activer</translation>
++<translation id="9040421302519041149">L'accès à ce réseau est protégé.</translation>
++<translation id="5659593005791499971">E-mail</translation>
++<translation id="8235325155053717782">Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
++<translation id="6584878029876017575">Signature permanente Microsoft</translation>
++<translation id="562901740552630300">Sélectionnez
++ <ph name="BEGIN_BOLD"/>
++ Démarrer &gt; Panneau de configuration &gt; Réseau et Internet &gt; Centre Réseau et partage &gt; Résolution des problèmes (en bas) &gt; Connexions Internet.
++ <ph name="END_BOLD"/></translation>
++<translation id="8816996941061600321">Gestionnaire de &amp;fichiers</translation>
++<translation id="2773223079752808209">Service client</translation>
++<translation id="4585473702689066695">Impossible de se connecter au réseau &quot;<ph name="NAME"/>&quot;.</translation>
++<translation id="4647175434312795566">J'accepte ces termes</translation>
++<translation id="1084824384139382525">Copier l'adr&amp;esse du lien</translation>
++<translation id="1221462285898798023">Veuillez démarrer <ph name="PRODUCT_NAME"/> en tant qu'utilisateur normal. Pour l'exécuter en tant que root, vous devez indiquer un autre répertoire de données utilisateur pour stocker les informations du profil.</translation>
++<translation id="3220586366024592812">Le processus du connecteur <ph name="CLOUD_PRINT_NAME"/> est bloqué. Voulez-vous le redémarrer ?</translation>
++<translation id="5042992464904238023">Contenu Web</translation>
++<translation id="6254503684448816922">Clé compromise</translation>
++<translation id="1181037720776840403">Supprimer</translation>
++<translation id="4006726980536015530">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, ces téléchargements seront annulés.</translation>
++<translation id="4194415033234465088">Dachen 26</translation>
++<translation id="1664712100580477121">Voulez-vous vraiment graver l'image sur le périphérique suivant :</translation>
++<translation id="6639554308659482635">Mémoire SQLite</translation>
++<translation id="8141503649579618569"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, <ph name="TIME_LEFT"/></translation>
++<translation id="7650701856438921772"><ph name="PRODUCT_NAME"/> est affiché dans cette langue.</translation>
++<translation id="740624631517654988">Fenêtre pop-up bloquée</translation>
++<translation id="3738924763801731196"><ph name="OID"/> :</translation>
++<translation id="6550769511678490130">Ouvrir tous les favoris</translation>
++<translation id="1847961471583915783">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
++<translation id="8870318296973696995">Page d'accueil</translation>
++<translation id="6659594942844771486">Onglet</translation>
++<translation id="6575134580692778371">Non configuré</translation>
++<translation id="4624768044135598934">Opération réussie !</translation>
++<translation id="6014776969142880350">Relancez <ph name="PRODUCT_NAME"/> pour terminer la mise à jour.</translation>
++<translation id="5582768900447355629">Chiffrer toutes mes données</translation>
++<translation id="6122365914076864562">Veuillez patienter pendant que nous configurons votre réseau pour mobile.</translation>
++<translation id="1974043046396539880">Points de distribution de listes de révocation des certificats</translation>
++<translation id="7049357003967926684">Association</translation>
++<translation id="8641392906089904981">Appuyez sur Maj+Alt pour changer la disposition du clavier.</translation>
++<translation id="3024374909719388945">Utiliser l'horloge au format 24 heures</translation>
++<translation id="1867780286110144690"><ph name="PRODUCT_NAME"/> est prêt à terminer l'installation.</translation>
++<translation id="5316814419223884568">Lancez votre recherche à partir d'ici</translation>
++<translation id="8142732521333266922">OK, synchroniser tout</translation>
++<translation id="965674096648379287">Afin d'être correctement affichée, cette page requiert des données que vous avez précédemment entrées. Vous pouvez de nouveau transmettre ces données, mais, en procédant ainsi, vous devrez répéter chaque action que cette page a effectuée auparavant. Cliquez sur Rafraîchir pour transmettre de nouveau ces données et pour afficher cette page.</translation>
++<translation id="43742617823094120">Cela signifie que le certificat présenté à votre navigateur a été révoqué par son émetteur. L'intégrité de ce certificat a certainement été compromise, et il ne doit donc pas être approuvé. Ne poursuivez pas.</translation>
++<translation id="9019654278847959325">Clavier slovaque</translation>
++<translation id="18139523105317219">Nom de partie EDI</translation>
++<translation id="6657193944556309583">Vous avez déjà chiffré des données avec un mot de passe multiterme. Saisissez-le ci-dessous.</translation>
++<translation id="3328801116991980348">Informations sur le site</translation>
++<translation id="1205605488412590044">Créer un raccourci vers l'application...</translation>
++<translation id="2065985942032347596">Authentification requise</translation>
++<translation id="2553340429761841190"><ph name="PRODUCT_NAME"/> n'est pas parvenu à se connecter à <ph name="NETWORK_ID"/>. Sélectionnez un autre réseau ou réessayez.</translation>
++<translation id="2086712242472027775">Votre compte n'est pas compatible avec <ph name="PRODUCT_NAME"/>. Contactez l'administrateur de votre domaine ou utilisez un compte Google standard pour vous connecter.</translation>
++<translation id="7222232353993864120">Adresse e-mail</translation>
++<translation id="2128531968068887769">Client natif</translation>
++<translation id="7175353351958621980">Chargé depuis :</translation>
++<translation id="4590074117005971373">Active les balises canvas hautes performances dans un contexte 2D, pour effectuer le rendu via le processeur graphique.</translation>
++<translation id="7186367841673660872">Cette page en<ph name="ORIGINAL_LANGUAGE"/>a été traduite en<ph name="LANGUAGE_LANGUAGE"/></translation>
++<translation id="8448695406146523553">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez</translation>
++<translation id="6052976518993719690">Autorité de certification SSL</translation>
++<translation id="1636959874332483835"><ph name="HOST_NAME"/> contient un logiciel malveillant. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
++<translation id="8050783156231782848">Aucune donnée disponible.</translation>
++<translation id="1175364870820465910">Im&amp;primer...</translation>
++<translation id="3866249974567520381">Description</translation>
++<translation id="2900139581179749587">Voix non reconnue.</translation>
++<translation id="953692523250483872">Aucun fichier sélectionné</translation>
++<translation id="2294358108254308676">Souhaitez-vous installer <ph name="PRODUCT_NAME"/> ?</translation>
++<translation id="6549689063733911810">Activité récente</translation>
++<translation id="1529968269513889022">de la dernière semaine</translation>
++<translation id="5542132724887566711">Profil</translation>
++<translation id="5196117515621749903">Actualiser sans utiliser le cache</translation>
++<translation id="5552632479093547648">Logiciels malveillants et sites de phishing détectés !</translation>
++<translation id="4310537301481716192">Onglet fermé !</translation>
++<translation id="4988273303304146523">il y a <ph name="NUMBER_DEFAULT"/> jours</translation>
++<translation id="8428213095426709021">Paramètres</translation>
++<translation id="1588343679702972132">Ce site exige que vous vous identifiiez avec un certificat :</translation>
++<translation id="7211994749225247711">Supprimer...</translation>
++<translation id="2819994928625218237">&amp;Aucune suggestion orthographique</translation>
++<translation id="1065449928621190041">Clavier franco-canadien</translation>
++<translation id="8327626790128680264">Clavier étendu américain</translation>
++<translation id="2950186680359523359">Le serveur a mis fin à la connexion sans envoyer de données.</translation>
++<translation id="9142623379911037913">Autoriser <ph name="SITE"/> à afficher des notifications sur le Bureau ?</translation>
++<translation id="4196320913210960460">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Outils.</translation>
++<translation id="3449494395612243720">Erreur de synchronisation, veuillez vous connecter à nouveau.</translation>
++<translation id="9118804773997839291">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur un élément particulier.</translation>
++<translation id="7139724024395191329">Émirat</translation>
++<translation id="1761265592227862828">Synchroniser tous les paramètres et toutes les données\n(peut prendre un certain temps)</translation>
++<translation id="7754704193130578113">Toujours demander où enregistrer les fichiers</translation>
++<translation id="204914487372604757">Créer un raccourci</translation>
++<translation id="2497284189126895209">Tous les fichiers</translation>
++<translation id="696036063053180184">Sebeol-sik No-shift</translation>
++<translation id="452785312504541111">Anglais (pleine chasse)</translation>
++<translation id="945332329539165145">2D avec canvas et accélération matérielle</translation>
++<translation id="5220797120063118010">Cette fonctionnalité autorise l'installation d'applications Google Chrome déployées à partir d'un manifeste situé sur une page Web, plutôt qu'avec un fichier crx contenant le manifeste et les icônes.</translation>
++<translation id="9148126808321036104">Nouvelle connexion</translation>
++<translation id="2282146716419988068">GPU</translation>
++<translation id="428771275901304970">Moins de 1 Mo disponible</translation>
++<translation id="1682548588986054654">Nouvelle fenêtre de navigation privée</translation>
++<translation id="6833901631330113163">Europe du Sud</translation>
++<translation id="8691262314411702087">Sélectionner les éléments à synchroniser</translation>
++<translation id="6065289257230303064">Attributs du répertoire de l'objet du certificat</translation>
++<translation id="2423017480076849397">Accédez à vos imprimantes et partagez-les en ligne via <ph name="CLOUD_PRINT_NAME"/>.</translation>
++<translation id="569520194956422927">&amp;Ajouter...</translation>
++<translation id="4018133169783460046">Afficher <ph name="PRODUCT_NAME"/> dans cette langue</translation>
++<translation id="5110450810124758964">il y a <ph name="NUMBER_ONE"/> jour</translation>
++<translation id="3264544094376351444">Police Sans-Serif</translation>
++<translation id="5586942249556966598">Ne rien faire</translation>
++<translation id="2820806154655529776"><ph name="NUMBER_ONE"/> seconde</translation>
++<translation id="1077946062898560804">Configurer les mises à jour automatiques pour tous les utilisateurs</translation>
++<translation id="3122496702278727796">Échec de la création du répertoire des données</translation>
++<translation id="4517036173149081027">Fermer et annuler le chargement</translation>
++<translation id="7150146631451105528"><ph name="DATE"/></translation>
++<translation id="3166547286524371413">Adresse :</translation>
++<translation id="4522570452068850558">Détails</translation>
++<translation id="59659456909144943">Notification : <ph name="NOTIFICATION_NAME"/></translation>
++<translation id="6731320427842222405">Cette opération peut prendre quelques minutes.</translation>
++<translation id="4806525999832945986">Géré par <ph name="DOMAIN"/> (<ph name="STATUS"/>)</translation>
++<translation id="7503191893372251637">Type de certificat Netscape</translation>
++<translation id="1502960562739459116">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous installer Adobe Reader ?</translation>
++<translation id="4135450933899346655">Vos certificats</translation>
++<translation id="4731578803613910821">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et <ph name="WEBSITE_3"/></translation>
++<translation id="7716781361494605745">URL de stratégie de l'autorité de certification Netscape</translation>
++<translation id="2881966438216424900">Dernier accès :</translation>
++<translation id="7552203043556919163">Synchroniser les mots de passe</translation>
++<translation id="630065524203833229">&amp;Quitter</translation>
++<translation id="4647090755847581616">&amp;Fermer l'onglet</translation>
++<translation id="2649204054376361687"><ph name="CITY"/>, <ph name="COUNTRY"/></translation>
++<translation id="7886758531743562066">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur.</translation>
++<translation id="2064746092913005102">Total : <ph name="NUMBER_OF_PAGES"/> <ph name="PAGE_OR_PAGES_LABEL"/> <ph name="TWO_SIDED"/> <ph name="TIMES"/> <ph name="NUMBER_OF_COPIES"/> <ph name="COPIES_LABEL"/> <ph name="EQUAL_SIGN"/> <ph name="NUMBER_OF_SHEETS"/> <ph name="SHEETS_LABEL"/></translation>
++<translation id="7538227655922918841">Les cookies de plusieurs sites ont été autorisés pour la session uniquement.</translation>
++<translation id="2385700042425247848">Nom du service :</translation>
++<translation id="7751005832163144684">Imprimer une page de test</translation>
++<translation id="3638865692466101147">Aperçu avant impression - <ph name="PREVIEW_TAB_TITLE"/></translation>
++<translation id="1471300011765310414"><ph name="PRODUCT_NAME"/>
++ ne peut pas à afficher la page Web, car votre ordinateur n'est pas connecté à Internet.</translation>
++<translation id="5464632865477611176">Exécuter cette fois</translation>
++<translation id="4268025649754414643">Chiffrement de la clé</translation>
++<translation id="7925247922861151263">Échec de la vérification AAA</translation>
++<translation id="1168020859489941584">Ouverture dans <ph name="TIME_REMAINING"/>...</translation>
++<translation id="7814458197256864873">&amp;Copier</translation>
++<translation id="8186706823560132848">Logiciel</translation>
++<translation id="4692623383562244444">Moteurs de recherche</translation>
++<translation id="567760371929988174">&amp;Méthodes d'entrée</translation>
++<translation id="10614374240317010">Jamais enregistrés</translation>
++<translation id="5116300307302421503">Impossible d'analyser le fichier.</translation>
++<translation id="2745080116229976798">Subordination qualifiée Microsoft</translation>
++<translation id="2526590354069164005">Bureau</translation>
++<translation id="7983301409776629893">Toujours traduire en <ph name="TARGET_LANGUAGE"/> les pages en <ph name="ORIGINAL_LANGUAGE"/></translation>
++<translation id="4890284164788142455">Thaï</translation>
++<translation id="4312207540304900419">Activer l'onglet suivant</translation>
++<translation id="8456362689280298700"><ph name="HOUR"/>:<ph name="MINUTE"/> de chargement</translation>
++<translation id="7648048654005891115">Style de mappage du clavier</translation>
++<translation id="539295039523818097">Un problème lié à votre microphone s'est produit.</translation>
++<translation id="4033319557821527966"><ph name="CLOUD_PRINT_NAME"/> vous permet d'accéder aux imprimantes de cet ordinateur, où que vous soyez. Connectez-vous pour l'activer.</translation>
++<translation id="6970216967273061347">District</translation>
++<translation id="4479639480957787382">Ethernet</translation>
++<translation id="6312403991423642364">Erreur de réseau inconnue.</translation>
++<translation id="751377616343077236">Nom du certificat</translation>
++<translation id="7154108546743862496">Plus d'informations</translation>
++<translation id="8637688295594795546">Mise à jour du système disponible. Préparation du téléchargement…</translation>
++<translation id="5167270755190684957">Galerie des thèmes Google Chrome</translation>
++<translation id="8382913212082956454">Copi&amp;er l'adresse e-mail</translation>
++<translation id="7447930227192971403">Activer l'onglet 3</translation>
++<translation id="2903493209154104877">Adresses</translation>
++<translation id="2056143100006548702">Plug-in : <ph name="PLUGIN_NAME"/> (<ph name="PLUGIN_VERSION"/>)</translation>
++<translation id="3479552764303398839">Pas maintenant</translation>
++<translation id="6445051938772793705">Pays</translation>
++<translation id="3251759466064201842">&lt;Ne fait pas partie du certificat&gt;</translation>
++<translation id="4229495110203539533">il y a <ph name="NUMBER_ONE"/> seconde</translation>
++<translation id="6410257289063177456">Fichiers image</translation>
++<translation id="6419902127459849040">Europe centrale</translation>
++<translation id="6707389671160270963">Certificat client SSL</translation>
++<translation id="6083557600037991373">Pour accélérer l'affichage des pages Web,
++ <ph name="PRODUCT_NAME"/>
++ enregistre temporairement les fichiers téléchargés sur le disque. Si
++ <ph name="PRODUCT_NAME"/>
++ ne s'arrête pas correctement, ces fichiers peuvent être endommagés, ce qui
++ génère cette erreur. L'actualisation de la page devrait permettre de résoudre
++ ce problème ; celui-ci ne se reproduira vraisemblablement plus si l'arrêt s'effectue
++ correctement.
++ <ph name="LINE_BREAK"/>
++ Si le problème persiste, essayez de supprimer le contenu du cache. Cette
++ erreur peut aussi indiquer que le matériel est sur le point de tomber
++ en panne.</translation>
++<translation id="5298219193514155779">Thème créé par</translation>
++<translation id="7366909168761621528">Données de navigation</translation>
++<translation id="1047726139967079566">Ajouter cette page aux favoris</translation>
++<translation id="9020142588544155172">Le serveur a refusé la connexion.</translation>
++<translation id="6113225828180044308">Module (<ph name="MODULUS_NUM_BITS"/> bits) :\n<ph name="MODULUS_HEX_DUMP"/>\n\nExposant public (<ph name="PUBLIC_EXPONENT_NUM_BITS"/> bits) :\n<ph name="EXPONENT_HEX_DUMP"/></translation>
++<translation id="2544782972264605588"><ph name="NUMBER_DEFAULT"/> secondes restantes</translation>
++<translation id="8871696467337989339">Vous utilisez un indicateur de ligne de commande non pris en charge : <ph name="BAD_FLAG"/>. La stabilité et la sécurité en seront affectées.</translation>
++<translation id="4767443964295394154">Emplacement de téléchargement</translation>
++<translation id="5031870354684148875">À propos de Google Traduction</translation>
++<translation id="720658115504386855">Les lettres ne sont pas sensibles à la casse.</translation>
++<translation id="2454247629720664989">Mot clé</translation>
++<translation id="3950820424414687140">Connexion</translation>
++<translation id="4626106357471783850">Redémarrez <ph name="PRODUCT_NAME"/> pour appliquer la mise à jour.</translation>
++<translation id="1697068104427956555">Sélectionner un carré dans l'image</translation>
++<translation id="2840798130349147766">Bases de données Web</translation>
++<translation id="1628736721748648976">Codage</translation>
++<translation id="1198271701881992799">Mise en route</translation>
++<translation id="782590969421016895">Utiliser les pages actuelles</translation>
++<translation id="6521850982405273806">Signaler une erreur</translation>
++<translation id="736515969993332243">Recherche de réseaux en cours</translation>
++<translation id="8026334261755873520">Effacer les données de navigation</translation>
++<translation id="1769104665586091481">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
++<translation id="8503813439785031346">Nom d'utilisateur</translation>
++<translation id="5319782540886810524">Clavier letton</translation>
++<translation id="8651585100578802546">Forcer l'actualisation de cette page</translation>
++<translation id="685714579710025096">Disposition du clavier :</translation>
++<translation id="1361655923249334273">Non utilisé</translation>
++<translation id="290555789621781773"><ph name="NUMBER_TWO"/> minutes</translation>
++<translation id="5434065355175441495">Chiffrement RSA PKCS #1</translation>
++<translation id="7073704676847768330">Ce n'est probablement pas le site que vous recherchez !</translation>
++<translation id="8477384620836102176">&amp;Général</translation>
++<translation id="1074663319790387896">Configurer la synchronisation</translation>
++<translation id="4302315780171881488">État de connexion :</translation>
++<translation id="3391392691301057522">Ancien code PIN :</translation>
++<translation id="1344519653668879001">Désactiver le contrôle des liens hypertexte</translation>
++<translation id="6463795194797719782">&amp;Modifier</translation>
++<translation id="4262113024799883061">Chinois</translation>
++<translation id="4775879719735953715">Navigateur par défaut</translation>
++<translation id="5575473780076478375">Extension en mode navigation privée :<ph name="EXTENSION_NAME"/></translation>
++<translation id="4188026131102273494">Mot clé :</translation>
++<translation id="2930644991850369934">Un problème est survenu lors du téléchargement de l'image de récupération. La connexion réseau a été perdue.</translation>
++<translation id="3461610253915486539">Votre administrateur a désactivé certaines préférences.</translation>
++<translation id="5750053751252005701">Forfait de données <ph name="NETWORK"/> épuisé</translation>
++<translation id="8858939932848080433">Veuillez indiquer à quel niveau vous rencontrez des problèmes avant d'envoyer vos commentaires.</translation>
++<translation id="1720318856472900922">Authentification du serveur WWW TLS</translation>
++<translation id="8550022383519221471">Le service de synchronisation n'est pas disponible pour votre domaine.</translation>
++<translation id="3355823806454867987">Modifier les paramètres du proxy...</translation>
++<translation id="4780374166989101364">Cette fonctionnalité active les API des extensions expérimentales. Notez que vous ne pouvez pas mettre en ligne des extensions qui font appel aux API expérimentales dans la galerie d'extensions.</translation>
++<translation id="7227780179130368205">Un logiciel malveillant a été détecté !</translation>
++<translation id="435243347905038008">Forfait de données <ph name="NETWORK"/> presque épuisé</translation>
++<translation id="2489428929217601177">des dernières 24 heures</translation>
++<translation id="7418490403869327287">Une fois activée, la recherche instantanée charge la plupart des pages Web dès que vous saisissez l'URL dans le champ polyvalent, avant même que vous n'appuyiez sur Entrée. Si votre moteur de recherche par défaut est compatible, toute lettre saisie dans ce champ offre de nouveaux résultats et les prédictions intégrées vous guident dans vos recherches.\n\nChaque touche utilisée fait l'objet d'une requête, par conséquent il se peut que les éléments saisies dans le champ polyvalent soient enregistrés par votre moteur de recherche par défaut.\n</translation>
++<translation id="5149131957118398098"><ph name="NUMBER_ZERO"/> hours left</translation>
++<translation id="2541913031883863396">poursuivre quand même</translation>
++<translation id="4278390842282768270">Autorisé</translation>
++<translation id="2074527029802029717">Retirer l'onglet</translation>
++<translation id="1533897085022183721">Moins de <ph name="MINUTES"/></translation>
++<translation id="7503821294401948377">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action du navigateur.</translation>
++<translation id="5539694491979265537">Consulter Google Dashboard</translation>
++<translation id="3942946088478181888">Plus d'informations</translation>
++<translation id="3722396466546931176">Ajoutez des langues puis faites-les glisser pour les classer dans l'ordre souhaité.</translation>
++<translation id="7396845648024431313"><ph name="APP_NAME"/> sera lancé au démarrage du système et continuera de s'exécuter en arrière-plan, même toutes les fenêtres de <ph name="PRODUCT_NAME"/> sont fermées.</translation>
++<translation id="8539727552378197395">Non (HttpOnly)</translation>
++<translation id="4519351128520996510">Saisir votre mot de passe multiterme pour la synchronisation</translation>
++<translation id="2391419135980381625">Police standard</translation>
++<translation id="7893393459573308604"><ph name="ENGINE_NAME"/> (par défaut)</translation>
++<translation id="5392544185395226057">Cette fonctionnalité active la prise en charge du client natif.</translation>
++<translation id="5400640815024374115">La puce du module de plate-forme sécurisée (TPM) est désactivée ou inexistante.</translation>
++<translation id="2151576029659734873">L'index de l'onglet indiqué est incorrect.</translation>
++<translation id="5150254825601720210">Nom du serveur SSL du certificat Netscape</translation>
++<translation id="6771503742377376720">Est une autorité de certification</translation>
++<translation id="8814190375133053267">Wi-Fi</translation>
++<translation id="2040078585890208937">Connexion à <ph name="NAME"/></translation>
++<translation id="8410619858754994443">Confirmer le mot de passe :</translation>
++<translation id="2210840298541351314">Aperçu avant impression</translation>
++<translation id="3858678421048828670">Clavier italien</translation>
++<translation id="4938277090904056629">Impossible d'établir une connexion sécurisée à cause de l'antivirus ESET.</translation>
++<translation id="4521805507184738876">(expiré)</translation>
++<translation id="111844081046043029">Voulez-vous vraiment quitter cette page ?</translation>
++<translation id="1951615167417147110">Faire défiler d'une page vers le haut</translation>
++<translation id="4154664944169082762">Empreintes</translation>
++<translation id="3202578601642193415">Le plus récent</translation>
++<translation id="8112886015144590373"><ph name="NUMBER_FEW"/> heures</translation>
++<translation id="1398853756734560583">Agrandir</translation>
++<translation id="8988255471271407508">La page Web est introuvable dans le cache. Certaines ressources ne sont restituées fidèlement que si elles sont extraites du cache, notamment les pages générées à partir de données que vous avez envoyées. <ph name="LINE_BREAK"/> Cette erreur peut également être due à un cache endommagé lors d'une fermeture incorrecte. <ph name="LINE_BREAK"/> Si le problème persiste, essayez d'effacer le cache.</translation>
++<translation id="1195977189444203128">Le plug-in <ph name="PLUGIN_NAME"/> n'est plus à jour.</translation>
++<translation id="3878562341724547165">Vous avez changé de position. Souhaitez-vous utiliser <ph name="NEW_GOOGLE_URL"/> ?</translation>
++<translation id="1758018619400202187">EAP-TLS</translation>
++<translation id="6690744523875189208"><ph name="NUMBER_TWO"/> heures</translation>
++<translation id="8053390638574070785">Rafraîchir cette page</translation>
++<translation id="5507756662695126555">Non-répudiation</translation>
++<translation id="3678156199662914018">Extension : <ph name="EXTENSION_NAME"/></translation>
++<translation id="9194519262242876737">Active l'API Web audio.</translation>
++<translation id="3531250013160506608">Zone de saisie de mot de passe</translation>
++<translation id="8314066201485587418">Effacer les cookies et autres données de site lorsque je quitte le navigateur</translation>
++<translation id="4094105377635924481">Ajouter l'option de regroupement au menu contextuel des onglets</translation>
++<translation id="8655295600908251630">Version</translation>
++<translation id="8250690786522693009">Latin</translation>
++<translation id="2119721408814495896">Le connecteur <ph name="CLOUD_PRINT_NAME"/> requiert l'installation du pack Microsoft XML Paper Specification Essentials.</translation>
++<translation id="7624267205732106503">Effacer les cookies et autres données de site lorsque je ferme le navigateur</translation>
++<translation id="8401363965527883709">Case décochée</translation>
++<translation id="7771452384635174008">Mise en page</translation>
++<translation id="6188939051578398125">Saisir un nom ou une adresse</translation>
++<translation id="8443621894987748190">Choix de l'image du compte</translation>
++<translation id="10122177803156699">Me montrer</translation>
++<translation id="5260878308685146029"><ph name="NUMBER_TWO"/> minutes restantes</translation>
++<translation id="2192505247865591433">De :</translation>
++<translation id="238391805422906964">Ouvrir un rapport de phishing</translation>
++<translation id="5921544176073914576">Page de phishing</translation>
++<translation id="3727187387656390258">Inspecter le pop-up</translation>
++<translation id="569068482611873351">Importer...</translation>
++<translation id="6571070086367343653">Modifier la carte de paiement</translation>
++<translation id="1204242529756846967">Cette langue est utilisée pour corriger l'orthographe.</translation>
++<translation id="3981760180856053153">Le type d'enregistrement indiqué est incorrect.</translation>
++<translation id="8464591670878858520">Forfait de données <ph name="NETWORK"/> arrivé à expiration</translation>
++<translation id="4568660204877256194">Exporter mes favoris...</translation>
++<translation id="3116361045094675131">Clavier britannique</translation>
++<translation id="4577070033074325641">Importer des favoris...</translation>
++<translation id="1641504961675316934"><ph name="CLOUD_PRINT_NAME"/></translation>
++<translation id="1715941336038158809">Nom d'utilisateur ou mot de passe incorrect</translation>
++<translation id="1901303067676059328">&amp;Tout sélectionner</translation>
++<translation id="674375294223700098">Erreur inconnue liée au certificat du serveur.</translation>
++<translation id="7780428956635859355">Envoyer une capture d'écran enregistrée</translation>
++<translation id="2850961597638370327">Émis pour : <ph name="NAME"/></translation>
++<translation id="2168039046890040389">Page précédente</translation>
++<translation id="1767519210550978135">Hsu</translation>
++<translation id="2498539833203011245">Réduire</translation>
++<translation id="2893168226686371498">Navigateur par défaut</translation>
++<translation id="2435457462613246316">Afficher le mot de passe</translation>
++<translation id="7988355189918024273">Activer les fonctionnalités d'accessibilité</translation>
++<translation id="5438653034651341183">Inclure la capture d'écran actuelle :</translation>
++<translation id="1899708097738826574"><ph name="OPTIONS_TITLE"/> - <ph name="SUBPAGE_TITLE"/></translation>
++<translation id="1765313842989969521">(cette extension est gérée et ne peut être désinstallée ni désactivée)</translation>
++<translation id="6983783921975806247">OID enregistré</translation>
++<translation id="394984172568887996">Importés depuis IE</translation>
++<translation id="5311260548612583999">Fichier de clé privée (facultatif) :</translation>
++<translation id="2430043402233747791">Autoriser pour la session uniquement</translation>
++<translation id="7363290921156020669"><ph name="NUMBER_ZERO"/> mins</translation>
++<translation id="7568790562536448087">Mise à jour en cours</translation>
++<translation id="4856408283021169561">Aucun microphone trouvé.</translation>
++<translation id="8190193592390505034">Connexion à <ph name="PROVIDER_NAME"/></translation>
++<translation id="6144890426075165477"><ph name="PRODUCT_NAME"/> n'est pas votre navigateur par défaut.</translation>
++<translation id="823241703361685511">Forfait</translation>
++<translation id="4068506536726151626">Cette page contient des éléments des sites ci-dessous qui suivent votre position géographique :</translation>
++<translation id="4721475475128190282">Plusieurs profils</translation>
++<translation id="4220128509585149162">Plantages</translation>
++<translation id="8798099450830957504">Par défaut</translation>
++<translation id="9107059250669762581"><ph name="NUMBER_DEFAULT"/> jours</translation>
++<translation id="1640283014264083726">PKCS #1 MD4 avec chiffrement RSA</translation>
++<translation id="872451400847464257">Modifier le moteur de recherche</translation>
++<translation id="6463061331681402734"><ph name="NUMBER_MANY"/> minutes</translation>
++<translation id="2466804342846034717">Indiquez le mot de passe approprié ci-dessus, puis saisissez les caractères figurant dans l'image ci-dessous.</translation>
++<translation id="3881435075661337013">Expiration de <ph name="NETWORK"/> imminente</translation>
++<translation id="5681833099441553262">Activer l'onglet précédent</translation>
++<translation id="4792057643643237295">Désactiver l'accès à distance</translation>
++<translation id="1681614449735360921">Afficher les incompatibilités</translation>
++<translation id="19094784437781028">Carte de débit Solo</translation>
++<translation id="2657327428424666237"><ph name="BEGIN_LINK"/>Actualisez<ph name="END_LINK"/> cette page Web ultérieurement.</translation>
++<translation id="7347751611463936647">Pour utiliser cette extension, saisissez &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, TAB, puis votre commande ou votre recherche.</translation>
++<translation id="659432221160402784"><ph name="PRODUCT_NAME"/> synchronisera les applications installées, afin que vous puissiez y accéder en vous connectant depuis tout navigateur <ph name="PRODUCT_NAME"/>.</translation>
++<translation id="892464165639979917">Langues et paramètres du correcteur orthographique...</translation>
++<translation id="5645845270586517071">Erreur de sécurité</translation>
++<translation id="2805756323405976993">Applications</translation>
++<translation id="3651020361689274926">La ressource demandée n'existe plus et aucune adresse de transfert n'est disponible. Il semble que cet état de fait soit permanent.</translation>
++<translation id="2989786307324390836">Certificat unique binaire codé DER</translation>
++<translation id="3827774300009121996">&amp;Plein écran</translation>
++<translation id="3771294271822695279">Fichiers vidéo</translation>
++<translation id="6704875430222476107"><ph name="PRODUCT_NAME"/> indique que
++ NetNanny intercepte les connexions sécurisées. En général, cela
++ ne constitue pas un problème de sécurité, car le logiciel NetNanny s'exécute souvent
++ sur le même ordinateur. Toutefois, en raison de certaines incompatibilités avec
++ les connexions sécurisées Google Chrome, vous devez configurer NetNanny
++ de manière à éviter ces interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
++<translation id="3388026114049080752">Vos onglets et activités de navigation</translation>
++<translation id="7525067979554623046">Créer</translation>
++<translation id="4711094779914110278">Turc</translation>
++<translation id="1031460590482534116">Une erreur s'est produite lors de la tentative d'enregistrement du certificat client. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
++<translation id="7136984461011502314">Bienvenue dans <ph name="PRODUCT_NAME"/></translation>
++<translation id="1594030484168838125">Sélectionner</translation>
++<translation id="204497730941176055">Nom du modèle de certificat Microsoft</translation>
++<translation id="6705264787989366486">Configuration de l'adresse IP pour <ph name="NAME"/></translation>
++<translation id="8970721300630048025">Immortalisez votre plus beau sourire et utilisez la photo comme image de compte.</translation>
++<translation id="4087089424473531098">Extension créée :
++
++<ph name="EXTENSION_FILE"/></translation>
++<translation id="16620462294541761">Mot de passe incorrect. Veuillez réessayer.</translation>
++<translation id="5017508259293544172">LEAP</translation>
++<translation id="1394630846966197578">Échec de la connexion aux serveurs de reconnaissance vocale.</translation>
++<translation id="2498765460639677199">Très grande</translation>
++<translation id="2378982052244864789">Sélectionner le répertoire de l'extension</translation>
++<translation id="7861215335140947162">&amp;Téléchargements</translation>
++<translation id="4778630024246633221">Gestionnaire des certificats</translation>
++<translation id="6705050455568279082"><ph name="URL"/> souhaite suivre votre position géographique</translation>
++<translation id="4708849949179781599">Quitter <ph name="PRODUCT_NAME"/></translation>
++<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
++<translation id="6644512095122093795">Proposer d'enregistrer les mots de passe</translation>
++<translation id="4724450788351008910">Modification de l'affiliation</translation>
++<translation id="2249605167705922988">par exemple : 1-5, 8, 11-13</translation>
++<translation id="8691686986795184760">(Activé par une stratégie d'entreprise)</translation>
++<translation id="1911483096198679472">Qu'est-ce que c'est ?</translation>
++<translation id="1976323404609382849">Les cookies de plusieurs sites ont été bloqués.</translation>
++<translation id="2662952950313424742">Serveur DNS spécifié par l'utilisateur et utilisé par Google Chrome, à la place du paramètre système par défaut, pour les résolutions DNS.</translation>
++<translation id="4176463684765177261">Désactivé</translation>
++<translation id="2079545284768500474">Annuler</translation>
++<translation id="114140604515785785">Répertoire racine de l'extension :</translation>
++<translation id="4788968718241181184">Mode de saisie du vietnamien (TCVN6064)</translation>
++<translation id="1512064327686280138">Échec de l'activation</translation>
++<translation id="3254409185687681395">Ajouter cette page aux favoris</translation>
++<translation id="1384616079544830839">L'identité de ce site Web a été vérifiée par <ph name="ISSUER"/>.</translation>
++<translation id="8710160868773349942">Adresse e-mail : <ph name="EMAIL_ADDRESSES"/></translation>
++<translation id="4057991113334098539">Activation...</translation>
++<translation id="9073281213608662541">PAP</translation>
++<translation id="1800035677272595847">Sites de phishing</translation>
++<translation id="8448317557906454022"><ph name="NUMBER_ZERO"/> secs ago</translation>
++<translation id="402759845255257575">Interdire à tous les sites d'exécuter JavaScript</translation>
++<translation id="4610637590575890427">Vouliez-vous accéder à <ph name="SITE"/> ?</translation>
++<translation id="7723779034587221017">La connexion avec le service de configuration a été perdue. Veuillez réinitialiser votre périphérique ou contacter votre représentant de l'assistance technique.</translation>
++<translation id="3046388203776734202">Paramètres des fenêtres pop-up :</translation>
++<translation id="3437994698969764647">Tout exporter...</translation>
++<translation id="8349305172487531364">Barre de favoris</translation>
++<translation id="1898064240243672867">Stocké dans : <ph name="CERT_LOCATION"/></translation>
++<translation id="444134486829715816">Développer...</translation>
++<translation id="1401874662068168819">Gin Yieh</translation>
++<translation id="7208899522964477531">Rechercher <ph name="SEARCH_TERMS"/> sur <ph name="SITE_NAME"/></translation>
++<translation id="6255097610484507482">Modifier la carte de paiement</translation>
++<translation id="5584091888252706332">Au démarrage</translation>
++<translation id="8960795431111723921">Nous examinons actuellement le problème.</translation>
++<translation id="2482878487686419369">Notifications</translation>
++<translation id="8004582292198964060">Navigateur</translation>
++<translation id="695755122858488207">Case d'option décochée</translation>
++<translation id="6357135709975569075"><ph name="NUMBER_ZERO"/> days</translation>
++<translation id="8666678546361132282">Anglais</translation>
++<translation id="2224551243087462610">Modifier le nom du dossier</translation>
++<translation id="1358741672408003399">Grammaire et orthographe</translation>
++<translation id="4910673011243110136">Réseaux privés</translation>
++<translation id="2527167509808613699">Toutes sortes de connexions</translation>
++<translation id="9095710730982563314">Exceptions liées aux notifications</translation>
++<translation id="8072988827236813198">Épingler les onglets</translation>
++<translation id="1234466194727942574">Barre d'onglets</translation>
++<translation id="7974087985088771286">Activer l'onglet 6</translation>
++<translation id="4035758313003622889">Gestionnaire de &amp;tâches</translation>
++<translation id="6356936121715252359">Paramètres de stockage d'Adobe Flash Player...</translation>
++<translation id="5885996401168273077">Connexion au réseau</translation>
++<translation id="7313804056609272439">Mode de saisie du vietnamien (VNI)</translation>
++<translation id="1768211415369530011">L'application suivante va être lancée si vous acceptez cette requête :\n\n<ph name="APPLICATION"/></translation>
++<translation id="8793043992023823866">Importation...</translation>
++<translation id="8106211421800660735">N° de carte</translation>
++<translation id="2550839177807794974">Gérer les moteurs de recherche...</translation>
++<translation id="7031711645186424727">Utiliser un moniteur externe</translation>
++<translation id="6316768948917110108">Gravure de l'image en cours...</translation>
++<translation id="5089810972385038852">État</translation>
++<translation id="2872961005593481000">Éteindre</translation>
++<translation id="8986267729801483565">Enregistrer les fichiers dans le dossier :</translation>
++<translation id="4322394346347055525">Fermer les autres onglets</translation>
++<translation id="4411770745820968260">Répertoire de fichiers</translation>
++<translation id="881799181680267069">Masquer les autres</translation>
++<translation id="1812631533912615985">Annuler l'épinglage des onglets</translation>
++<translation id="6042308850641462728">Plus</translation>
++<translation id="8318945219881683434">Échec de la vérification de la révocation</translation>
++<translation id="1650709179466243265">Ajouter www. et .com, puis ouvrir la page</translation>
++<translation id="3524079319150349823">Pour inspecter un pop-up, cliquez avec le bouton droit sur la page ou sur l'icône d'action du navigateur, puis sélectionnez Inspecter le pop-up.</translation>
++<translation id="994289308992179865">&amp;Répéter</translation>
++<translation id="7793343764764530903"><ph name="CLOUD_PRINT_NAME"/> est à présent activé. <ph name="PRODUCT_NAME"/> a enregistré les imprimantes installées sur cette machine en les associant à &lt;b&gt;<ph name="EMAIL_ADDRESSES"/>&lt;/b&gt;. Vous pouvez désormais utiliser vos imprimantes depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
++<translation id="1703490097606704369">Le serveur de <ph name="HOST_NAME"/>
++ est introuvable, car la résolution DNS a échoué. DNS est le service Web qui
++ traduit les noms de site Web en adresses Internet. Cette erreur est
++ généralement due à l'absence de connexion Internet ou à une configuration
++ incorrecte du réseau. Cela peut également venir d'un serveur DNS qui ne
++ répond pas ou d'un pare-feu interdisant l'accès de
++ <ph name="PRODUCT_NAME"/>
++ au réseau.</translation>
++<translation id="8887090188469175989">ZGPY</translation>
++<translation id="3302709122321372472">Impossible de charger le fichier css &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
++<translation id="305803244554250778">Créer des raccourcis vers des applications aux emplacements suivants :</translation>
++<translation id="574392208103952083">Moyenne</translation>
++<translation id="3745810751851099214">Envoyé pour :</translation>
++<translation id="3937609171782005782">Aider Google à détecter les logiciels malveillants en envoyant des données supplémentaires concernant les sites pour lesquels cet avertissement s'affiche. Ces données seront gérées conformément aux règles définies sur la page <ph name="PRIVACY_PAGE_LINK"/>.</translation>
++<translation id="8877448029301136595">[répertoire parent]</translation>
++<translation id="7301360164412453905">Touches de sélection du clavier Hsu</translation>
++<translation id="8631271110654520730">Copie de l'image de récupération...</translation>
++<translation id="1963227389609234879">Tout supprimer</translation>
++<translation id="7779140087128114262">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez réinitialiser la synchronisation.</translation>
++<translation id="8027581147000338959">Ouvrir dans une nouvelle fenêtre</translation>
++<translation id="8019305344918958688">Dommage... Aucune extension n'est installée. :-(</translation>
++<translation id="7466861475611330213">Style de ponctuation</translation>
++<translation id="2496180316473517155">Historique de navigation</translation>
++<translation id="602251597322198729">Ce site tente de télécharger plusieurs fichiers. Voulez-vous autoriser le chargement ?</translation>
++<translation id="5843685321177053287">Établissement de la liaison avec le service de gestion des périphériques en attente...</translation>
++<translation id="2052389551707911401"><ph name="NUMBER_MANY"/> heures</translation>
++<translation id="5411472733320185105">Ne pas utiliser les paramètres du proxy pour les hôtes et domaines suivants :</translation>
++<translation id="6691936601825168937">&amp;Avancer</translation>
++<translation id="6566142449942033617">Impossible de charger &quot;<ph name="PLUGIN_PATH"/>&quot; pour le plug-in.</translation>
++<translation id="7065534935986314333">À propos du système</translation>
++<translation id="45025857977132537">Utilisation de la clé du certificat : <ph name="USAGES"/></translation>
++<translation id="6454421252317455908">Mode de saisie du chinois (quick)</translation>
++<translation id="368789413795732264">Une erreur s'est produite lors de la tentative d'écriture du fichier : <ph name="ERROR_TEXT"/>.</translation>
++<translation id="1173894706177603556">Renommer</translation>
++<translation id="5670032673361607750">La synchronisation requiert votre attention.</translation>
++<translation id="2148716181193084225">Aujourd'hui</translation>
++<translation id="1002064594444093641">Imp&amp;rimer le cadre...</translation>
++<translation id="7234674978021619913">Le site <ph name="HOST_NAME"/> a déjà été informé qu'un logiciel malveillant a été détecté sur ses pages. Pour plus d'informations concernant les problèmes rencontrés sur <ph name="HOST_NAME2"/>, consultez notre <ph name="DIAGNOSTIC_PAGE"/> Google.</translation>
++<translation id="8202390211066742724">Adresse de serveur DNS spécifiée par l'utilisateur.</translation>
++<translation id="4608500690299898628">&amp;Rechercher...</translation>
++<translation id="3574305903863751447"><ph name="CITY"/>, <ph name="STATE"/> <ph name="COUNTRY"/></translation>
++<translation id="8724859055372736596">&amp;Afficher dans le dossier</translation>
++<translation id="4605399136610325267">Non connecté à Internet.</translation>
++<translation id="978407797571588532">Sélectionnez
++ <ph name="BEGIN_BOLD"/>
++ Démarrer &gt; Panneau de configuration &gt; Connexions réseau &gt; Assistant Nouvelle connexion
++ <ph name="END_BOLD"/>
++ pour tester votre connexion.</translation>
++<translation id="5554489410841842733">Cette icône s'affiche lorsque l'extension peut agir sur la page active.</translation>
++<translation id="579702532610384533">Reconnexion</translation>
++<translation id="4862642413395066333">Réponses OCSP de signature</translation>
++<translation id="5266113311903163739">Erreur d'importation de l'autorité de certification</translation>
++<translation id="9563164493805065">Gravure de l'image terminée.</translation>
++<translation id="4756388243121344051">&amp;Historique</translation>
++<translation id="3789841737615482174">Installer</translation>
++<translation id="4320697033624943677">Ajouter des utilisateurs</translation>
++<translation id="9153934054460603056">Enregistrer l'authentification et le mot de passe</translation>
++<translation id="1455548678241328678">Clavier norvégien</translation>
++<translation id="2520481907516975884">Basculer en mode chinois/anglais</translation>
++<translation id="8571890674111243710">Traduction de la page en <ph name="LANGUAGE"/>...</translation>
++<translation id="4789872672210757069">À propos de &amp;<ph name="PRODUCT_NAME"/></translation>
++<translation id="4056561919922437609"><ph name="TAB_COUNT"/> onglets</translation>
++<translation id="4373894838514502496">il y a <ph name="NUMBER_FEW"/> minutes</translation>
++<translation id="6358450015545214790">Qu'est-ce que c'est ?</translation>
++<translation id="6264365405983206840">Tout &amp;sélectionner</translation>
++<translation id="1017280919048282932">&amp;Ajouter au dictionnaire</translation>
++<translation id="8319414634934645341">Utilisation étendue de la clé</translation>
++<translation id="4563210852471260509">Le chinois est la langue de saisie initiale</translation>
++<translation id="6897140037006041989">Agent utilisateur</translation>
++<translation id="3413122095806433232">Émetteurs de l'autorité de certification : <ph name="LOCATION"/></translation>
++<translation id="4115153316875436289"><ph name="NUMBER_TWO"/> jours</translation>
++<translation id="701080569351381435">Code source</translation>
++<translation id="3286538390144397061">Redémarrer maintenant</translation>
++<translation id="163309982320328737">La largeur de caractères initiale est Complète</translation>
++<translation id="5107325588313356747">Pour masquer l'accès à ce programme, vous devez le désinstaller au moyen de \n<ph name="CONTROL_PANEL_APPLET_NAME"/> du Panneau de configuration.\n\nSouhaitez-vous exécuter <ph name="CONTROL_PANEL_APPLET_NAME"/> ?</translation>
++<translation id="4841055638263130507">Paramètres du microphone</translation>
++<translation id="6965648386495488594">Port</translation>
++<translation id="7631887513477658702">&amp;Toujours ouvrir les fichiers de ce type</translation>
++<translation id="8627795981664801467">Uniquement les connexions sécurisées</translation>
++<translation id="8680787084697685621">Les informations de connexion au compte sont obsolètes.</translation>
++<translation id="3228969707346345236">La traduction a échoué, car la page est déjà en <ph name="LANGUAGE"/>.</translation>
++<translation id="1873879463550486830">Sandbox SUID</translation>
++<translation id="2190355936436201913">(vide)</translation>
++<translation id="8515737884867295000">Échec de l'authentification basée sur le certificat</translation>
++<translation id="5868426874618963178">Envoyer le code source de la page actuelle</translation>
++<translation id="1269138312169077280">Votre administrateur a désactivé certains paramètres.</translation>
++<translation id="5818003990515275822">Coréen</translation>
++<translation id="4182252350869425879">Avertissement : Il s'agit peut-être d'un site de phishing !</translation>
++<translation id="5458214261780477893">Dvorak</translation>
++<translation id="5353719617589986386">Étendue de pages incorrecte</translation>
++<translation id="1164369517022005061"><ph name="NUMBER_DEFAULT"/> heures restantes</translation>
++<translation id="5943260032016910017">Exceptions liées aux cookies et aux données de site</translation>
++<translation id="2214283295778284209"><ph name="SITE"/> n'est pas accessible</translation>
++<translation id="8755376271068075440">P&amp;lus grand</translation>
++<translation id="8132793192354020517">Connecté à <ph name="NAME"/></translation>
++<translation id="8187473050234053012">Le certificat de sécurité du site a été révoqué !</translation>
++<translation id="7444983668544353857">Désactiver <ph name="NETWORKDEVICE"/></translation>
++<translation id="6003177993629630467"><ph name="PRODUCT_NAME"/> risque de ne pas rester à jour.</translation>
++<translation id="421577943854572179">intégré sur tout autre site</translation>
++<translation id="580886651983547002"><ph name="PRODUCT_NAME"/>
++ ne parvient pas à atteindre le site Web. Cela vient probablement d'un problème de réseau,
++ mais peut également être dû à un pare-feu ou à un serveur proxy mal configuré.</translation>
++<translation id="5445557969380904478">À propos de la reconnaissance vocale</translation>
++<translation id="3093473105505681231">Langues et paramètres du correcteur orthographique...</translation>
++<translation id="152482086482215392"><ph name="NUMBER_ONE"/> seconde restante</translation>
++<translation id="529172024324796256">Nom d'utilisateur :</translation>
++<translation id="3308116878371095290">Le stockage des cookies n'est pas autorisé pour cette page.</translation>
++<translation id="7521387064766892559">JavaScript</translation>
++<translation id="7219179957768738017">La connexion utilise <ph name="SSL_VERSION"/>.</translation>
++<translation id="7014174261166285193">Échec de l'installation</translation>
++<translation id="1970746430676306437">Afficher les &amp;infos sur la page</translation>
++<translation id="3199127022143353223">Serveurs</translation>
++<translation id="2805646850212350655">Système de fichiers de chiffrement Microsoft </translation>
++<translation id="8053959338015477773">Un plug-in supplémentaire est requis pour afficher certains éléments sur cette page.</translation>
++<translation id="3541661933757219855">Appuyez sur Ctrl+Alt+/ ou sur Échap pour masquer</translation>
++<translation id="8813873272012220470">Cette fonctionnalité effectue des vérifications en arrière-plan et vous avertit en cas d'incompatibilité logicielle (modules tiers bloquant le navigateur, par exemple).</translation>
++<translation id="5020734739305654865">Connexion avec</translation>
++<translation id="2679385451463308372">Imprimer depuis la boîte de dialogue système…</translation>
++<translation id="7414887922320653780"><ph name="NUMBER_ONE"/> heure restante</translation>
++<translation id="121632099317611328">Échec de l'initialisation de l'appareil photo</translation>
++<translation id="399179161741278232">Importés</translation>
++<translation id="3829932584934971895">Type de fournisseur :</translation>
++<translation id="462288279674432182">IP restreinte :</translation>
++<translation id="3927932062596804919">Refuser</translation>
++<translation id="3524915994314972210">Démarrage du téléchargement en cours...</translation>
++<translation id="6484929352454160200">Une nouvelle version de <ph name="PRODUCT_NAME"/> est disponible.</translation>
++<translation id="3187212781151025377">Clavier hébreu</translation>
++<translation id="351152300840026870">Police à largeur fixe</translation>
++<translation id="5827266244928330802">Safari</translation>
++<translation id="778881183694837592">Les champs obligatoires ne doivent pas rester vides.</translation>
++<translation id="2371076942591664043">Ouvrir une fois le téléchargement &amp;terminé</translation>
++<translation id="3920504717067627103">Stratégies de certificat</translation>
++<translation id="155865706765934889">Pavé tactile</translation>
++<translation id="7701040980221191251">Aucun</translation>
++<translation id="5917011688104426363">Activer la barre d'adresse en mode recherche</translation>
++<translation id="6910239454641394402">Exceptions pour JavaScript</translation>
++<translation id="2979639724566107830">Ouvrir dans une nouvelle fenêtre</translation>
++<translation id="3269101346657272573">Veuillez saisir le code PIN.</translation>
++<translation id="9204065299849069896">Options de saisie automatique...</translation>
++<translation id="2822854841007275488">Arabe</translation>
++<translation id="5857090052475505287">Nouveau dossier</translation>
++<translation id="7450732239874446337">E/S réseau interrompue</translation>
++<translation id="5178667623289523808">Rechercher le précédent</translation>
++<translation id="2815448242176260024">Ne jamais enregistrer les mots de passe</translation>
++<translation id="2989805286512600854">Ouvrir dans un nouvel onglet</translation>
++<translation id="8687485617085920635">Fenêtre suivante</translation>
++<translation id="4122118036811378575">&amp;Rechercher le suivant</translation>
++<translation id="6008256403891681546">JCB</translation>
++<translation id="2610780100389066815">Signature de liste d'approbation Microsoft</translation>
++<translation id="8289811203643526145">Gérer les certificats...</translation>
++<translation id="2788575669734834343">Sélectionnez le fichier de certificat.</translation>
++<translation id="8404409224170843728">Fabricant :</translation>
++<translation id="8267453826113867474">Bloquer le contenu inapproprié</translation>
++<translation id="7959074893852789871">Le fichier contenait plusieurs certificats, dont certains n'ont pas été importés :</translation>
++<translation id="1213999834285861200">Exceptions pour les images</translation>
++<translation id="2805707493867224476">Autoriser tous les sites à afficher des fenêtres pop-up</translation>
++<translation id="3561217442734750519">Vous devez indiquer un chemin valide comme valeur de clé privée.</translation>
++<translation id="2444609190341826949">Sans mot de passe multiterme, vos mots de passe et autres données chiffrées ne seront pas synchronisés sur cet ordinateur.</translation>
++<translation id="77221669950527621">Extensions ou applications</translation>
++<translation id="6650142020817594541">Ce site recommande Google Chrome Frame (déjà installé).</translation>
++<translation id="6503077044568424649">Les plus visités</translation>
++<translation id="4625904365165566833">Vous n'êtes pas autorisé à vous connecter. Consultez le propriétaire de cet ordinateur portable.</translation>
++<translation id="7450633916678972976">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome joint à votre
++ envoi un journal indiquant votre version de Google Chrome et celle du système
++ d'exploitation utilisé, ainsi que l'URL associée à votre rapport. Vous pouvez
++ également joindre une capture d'écran. Ces informations nous
++ permettent de diagnostiquer les problèmes et d'améliorer les performances de
++ Google Chrome. Les informations personnelles fournies sciemment dans vos
++ commentaires ou involontairement dans le journal, l'URL ou la capture
++ d'écran sont protégées conformément à nos règles de
++ confidentialité. Si vous ne souhaitez pas indiquer d'URL et/ou de capture
++ d'écran, décochez les cases &quot;Inclure cette URL&quot; et/ou &quot;Inclure cette capture d'écran&quot;. Vous acceptez que Google utilise vos commentaires pour améliorer ses produits ou services.</translation>
++<translation id="465365366590259328">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
++<translation id="7168109975831002660">Taille de police minimale</translation>
++<translation id="7070804685954057874">Entrée directe</translation>
++<translation id="3265459715026181080">Fermer la fenêtre</translation>
++<translation id="6074871234879228294">Mode de saisie du japonais (pour clavier japonais)</translation>
++<translation id="7855296476260297092">Inscription réussie</translation>
++<translation id="907841381057066561">Échec de création du fichier zip temporaire lors de la création du pack</translation>
++<translation id="1294298200424241932">Modifier les paramètres de confiance :</translation>
++<translation id="1384617406392001144">Votre historique de navigation</translation>
++<translation id="3831099738707437457">&amp;Masquer le panneau de la vérification orthographique</translation>
++<translation id="1040471547130882189">Plug-in ne répondant pas</translation>
++<translation id="5473075389972733037">IBM</translation>
++<translation id="8307664665247532435">Les paramètres seront effacés lors de la prochaine actualisation.</translation>
++<translation id="790025292736025802"><ph name="URL"/> introuvable</translation>
++<translation id="895347679606913382">Démarrage...</translation>
++<translation id="3319048459796106952">Nouvelle fenêtre de nav&amp;igation privée</translation>
++<translation id="5832669303303483065">Ajouter une adresse postale...</translation>
++<translation id="3127919023693423797">Authentification en cours...</translation>
++<translation id="4195643157523330669">Ouvrir dans un nouvel onglet</translation>
++<translation id="8030169304546394654">Déconnecté</translation>
++<translation id="4010065515774514159">Action du navigateur</translation>
++<translation id="4286563808063000730">Le mot de passe multiterme saisi ne peut pas être utilisé, car vous avez déjà chiffré des données avec un mot de passe multiterme. Entrez ci-dessous le mot de passe multiterme actuellement défini pour la synchronisation.</translation>
++<translation id="1154228249304313899">Ouvrir cette page :</translation>
++<translation id="9074348188580488499">Voulez-vous vraiment supprimer tous les mots de passe ?</translation>
++<translation id="6635491740861629599">Sélectionner par domaine</translation>
++<translation id="3627588569887975815">Ouvrir le lien dans une fenêtre en navi&amp;gation privée</translation>
++<translation id="5851868085455377790">Émetteur</translation>
++<translation id="8223496248037436966">Options de saisie automatique</translation>
++<translation id="1470719357688513792">Les nouveaux paramètres des cookies seront appliqués quand vous aurez actualisé la page.</translation>
++<translation id="5578327870501192725">Votre connexion à <ph name="DOMAIN"/> est sécurisée par un chiffrement <ph name="BIT_COUNT"/> bits.</translation>
++<translation id="869884720829132584">Menu Applications</translation>
++<translation id="7764209408768029281">Outi&amp;ls</translation>
++<translation id="1139892513581762545">Onglets latéraux</translation>
++<translation id="7634357567062076565">Reprendre</translation>
++<translation id="4779083564647765204">Zoom</translation>
++<translation id="3282430104564575032">Inspecteur de DOM</translation>
++<translation id="1526560967942511387">Document sans titre</translation>
++<translation id="1291144580684226670">Police standard</translation>
++<translation id="3979748722126423326">Activer <ph name="NETWORKDEVICE"/></translation>
++<translation id="5538307496474303926">Opération en cours...</translation>
++<translation id="4367133129601245178">C&amp;opier l'URL de l'image</translation>
++<translation id="7542995811387359312">La saisie automatique des numéros de carte de paiement est désactivée, car la connexion utilisée par ce formulaire n'est pas sécurisée.</translation>
++<translation id="3494444535872870968">Enregistrer le &amp;cadre sous...</translation>
++<translation id="987264212798334818">Général</translation>
++<translation id="7005812687360380971">Défaillance</translation>
++<translation id="2356070529366658676">Demander</translation>
++<translation id="5731247495086897348">Coller l'URL et y a&amp;ccéder</translation>
++<translation id="8467548439852845758">Pour plus de sécurité, <ph name="PRODUCT_NAME"/> va chiffrer vos mots de passe.</translation>
++<translation id="2524947000814989347">Si vous avez oublié votre mot de passe multiterme, vous devrez arrêter la synchronisation via Google Dashboard.</translation>
++<translation id="8018154597338652331"><ph name="BURNT_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
++<translation id="7635741716790924709">Adresse ligne 1</translation>
++<translation id="5135533361271311778">Impossible de créer le favori.</translation>
++<translation id="5271247532544265821">Basculer en mode chinois simplifié/traditionnel</translation>
++<translation id="2052610617971448509">Votre système Sandbox n'est pas correctement configuré.</translation>
++<translation id="7384913436093989340">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Préférences &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
++<translation id="6417515091412812850">Impossible de vérifier si le certificat a été révoqué.</translation>
++<translation id="7282743297697561153">Stockage des données</translation>
++<translation id="3363332416643747536"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, Interrompu</translation>
++<translation id="7347702518873971555">Acheter un forfait</translation>
++<translation id="5285267187067365830">Installer le plug-in...</translation>
++<translation id="5334844597069022743">Afficher le code source</translation>
++<translation id="1166212789817575481">Fermer les onglets sur la droite</translation>
++<translation id="6472893788822429178">Afficher le bouton &quot;Accueil&quot;</translation>
++<translation id="4270393598798225102">Version <ph name="NUMBER"/></translation>
++<translation id="534916491091036097">Parenthèse gche</translation>
++<translation id="4157869833395312646">Microsoft Server Gated Cryptography</translation>
++<translation id="8903921497873541725">Zoom avant</translation>
++<translation id="2195729137168608510">Protection du courrier électronique</translation>
++<translation id="1425734930786274278">Les cookies suivants ont été bloqués (tous les cookies tiers sont bloqués, sans exception) :</translation>
++<translation id="6805647936811177813">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client de <ph name="HOST_NAME"/></translation>
++<translation id="3437016096396740659">La batterie est chargée.</translation>
++<translation id="6916146760805488559">Créer un nouveau profil...</translation>
++<translation id="1199232041627643649">Maintenez la touche <ph name="KEY_EQUIVALENT"/> enfoncée pour quitter.</translation>
++<translation id="5428562714029661924">Masquer ce plug-in</translation>
++<translation id="7907591526440419938">Ouvrir le fichier</translation>
++<translation id="2568774940984945469">Conteneur de barres d'infos</translation>
++<translation id="8971063699422889582">Le certificat du serveur a expiré.</translation>
++<translation id="8281596639154340028">Utiliser <ph name="HANDLER_TITLE"/></translation>
++<translation id="7134098520442464001">Réduit la taille du texte</translation>
++<translation id="21133533946938348">Épingler l'onglet</translation>
++<translation id="1325040735987616223">Mise à jour du système</translation>
++<translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation>
++<translation id="9090669887503413452">Inclure les informations système</translation>
++<translation id="3084771660770137092">Google Chrome n'avait pas suffisamment de mémoire ou le processus de la page Web a été arrêté pour une autre raison. Pour continuer, actualisez la page ou ouvrez-en une autre.</translation>
++<translation id="1114901192629963971">Impossible de valider votre mot de passe sur le réseau actuel. Sélectionnez un autre réseau.</translation>
++<translation id="5179510805599951267">Cette page n'est pas rédigée en <ph name="ORIGINAL_LANGUAGE"/> ? Signaler l'erreur</translation>
++<translation id="6430814529589430811">Certificat unique codé Base 64 ASCII</translation>
++<translation id="5143712164865402236">Activer le mode plein écran</translation>
++<translation id="8434177709403049435">Codag&amp;e</translation>
++<translation id="4051923669149193910"><ph name="HANDLER_TITLE"/> est déjà utilisé pour gérer les liens <ph name="PROTOCOL"/>://.</translation>
++<translation id="2722201176532936492">Touches de sélection</translation>
++<translation id="385120052649200804">Clavier international américain</translation>
++<translation id="9012607008263791152">Je comprends que la visite de ce site peut être préjudiciable à mon ordinateur.</translation>
++<translation id="6640442327198413730">Ressource cache manquante.</translation>
++<translation id="1441458099223378239">Impossible d'accéder à mon compte</translation>
++<translation id="5793220536715630615">C&amp;opier l'URL de la vidéo</translation>
++<translation id="523397668577733901">Vous préférez <ph name="BEGIN_LINK"/>parcourir la galerie<ph name="END_LINK"/> ?</translation>
++<translation id="2922350208395188000">Impossible de vérifier le certificat du serveur.</translation>
++<translation id="3778740492972734840">Outils de &amp;développement</translation>
++<translation id="8335971947739877923">Exporter...</translation>
++<translation id="5680966941935662618">Paramètres de saisie automatique</translation>
++<translation id="38385141699319881">Téléchargement de l'image en cours...</translation>
++<translation id="6004539838376062211">&amp;Options du vérificateur d'orthographe</translation>
++<translation id="5350198318881239970">Impossible d'ouvrir votre profil correctement.\n\nIl est possible que certaines fonctionnalités ne soient pas disponibles. Vérifiez que ce profil existe et que vous disposez d'une autorisation d'accès à son contenu en lecture et en écriture.</translation>
++<translation id="4058793769387728514">Vérifier le document maintenant</translation>
++<translation id="1810107444790159527">Zone de liste</translation>
++<translation id="3338239663705455570">Clavier slovène</translation>
++<translation id="1859234291848436338">Sens de l'écriture</translation>
++<translation id="4567836003335927027">Vos données sur <ph name="WEBSITE_1"/></translation>
++<translation id="756445078718366910">Ouvrir une fenêtre du navigateur</translation>
++<translation id="4126154898592630571">Conversion de la date et de l'heure</translation>
++<translation id="5088534251099454936">PKCS #1 SHA-512 avec chiffrement RSA</translation>
++<translation id="6392373519963504642">Clavier coréen</translation>
++<translation id="7887334752153342268">Dupliquer</translation>
++<translation id="4980691186726139495">Ne pas conserver sur cette page</translation>
++<translation id="3081523290047420375">Désactiver <ph name="CLOUD_PRINT_NAME"/></translation>
++<translation id="9207194316435230304">ATOK</translation>
++<translation id="9026731007018893674">téléchargement</translation>
++<translation id="7646591409235458998">E-mail :</translation>
++<translation id="703748601351783580">Ouvrir tous les favoris dans une nouvelle &amp;fenêtre</translation>
++<translation id="6199775032047436064">Rafraîchir la page actuelle</translation>
++<translation id="6981982820502123353">Accessibilité</translation>
++<translation id="112343676265501403">Exceptions pour les plug-ins</translation>
++<translation id="770273299705142744">Remplissage automatique des formulaires</translation>
++<translation id="7210998213739223319">Nom d'utilisateur</translation>
++<translation id="4478664379124702289">Enregistrer le lie&amp;n sous...</translation>
++<translation id="8725066075913043281">Réessayer</translation>
++<translation id="8502249598105294518">Personnaliser et configurer <ph name="PRODUCT_NAME"/></translation>
++<translation id="7392089327262158658">Préférences de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
++<translation id="4163521619127344201">Votre position géographique</translation>
++<translation id="3797008485206955964">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
++<translation id="8590375307970699841">Configurer les mises à jour automatiques</translation>
++<translation id="2797524280730715045">il y a <ph name="NUMBER_DEFAULT"/> heures</translation>
++<translation id="265390580714150011">Valeur du champ</translation>
++<translation id="9073247318500677671">Les dernières versions d'Unity et GNOME (ainsi que la prochaine version d'Ubuntu, Natty Narwhal) affichent une barre de menus de type OSX sur toute la largeur supérieure de l'écran.</translation>
++<translation id="3869917919960562512">Index erroné.</translation>
++<translation id="7031962166228839643">Préparation du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, l'opération peut prendre quelques minutes.</translation>
++<translation id="4250377793615429299">Nombre de copies incorrect</translation>
++<translation id="7180865173735832675">Personnaliser</translation>
++<translation id="5737306429639033676">Prédire les actions du réseau pour améliorer les performances de chargement des pages</translation>
++<translation id="8123426182923614874">Données restantes :</translation>
++<translation id="3707020109030358290">N'est pas une autorité de certification.</translation>
++<translation id="2115926821277323019">L'URL doit être valide.</translation>
++<translation id="8986494364107987395">Envoyer automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
++<translation id="7070714457904110559">Cette fonctionnalité active la géolocalisation dans les extensions expérimentales. Cela implique l'utilisation des API de localisation du système d'exploitation (si disponibles) et l'envoi de données sur la configuration réseau locale au service de localisation de Google afin de déterminer une position précise.</translation>
++<translation id="6701535245008341853">Impossible de charger le profil.</translation>
++<translation id="527605982717517565">Toujours exécuter JavaScript sur <ph name="HOST"/></translation>
++<translation id="702373420751953740">Version PRL :</translation>
++<translation id="1307041843857566458">Confirmer la réactivation</translation>
++<translation id="8314308967132194952">Ajouter une adresse postale...</translation>
++<translation id="1221024147024329929">PKCS #1 MD2 avec chiffrement RSA</translation>
++<translation id="853265131227167869">Dim.^Lun.^Mar.^Mer.^Jeu.^Ven.^Sam.</translation>
++<translation id="3323447499041942178">Zone de saisie</translation>
++<translation id="580571955903695899">Trier par nom</translation>
++<translation id="5230516054153933099">Fenêtre</translation>
++<translation id="7554791636758816595">Nouvel onglet</translation>
++<translation id="5503844897713343920">Vous tentez d'accéder au site <ph name="DOMAIN"/>, mais le certificat présenté par le serveur a été révoqué par son émetteur. Cela signifie que les informations d'identification présentées par le serveur ne sont pas approuvées. Vous communiquez peut-être avec un pirate informatique. Nous vous déconseillons vivement de continuer.</translation>
++<translation id="6928853950228839340">Composition hors écran</translation>
++<translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation>
++<translation id="7671576867600624">Technologie :</translation>
++<translation id="1103966635949043187">Accédez à la page d'accueil du site :</translation>
++<translation id="1951332921786364801">Configurer la communication à distance</translation>
++<translation id="1086613338090581534">L'émetteur d'un certificat n'ayant pas expiré est tenu d'assurer la maintenance de ce qui s'appelle &quot;une liste de révocation&quot;. Si un certificat est compromis, l'émetteur peut le révoquer en l'ajoutant à la liste de révocation. Ce certificat n'est alors plus approuvé par votre navigateur. Il n'est pas nécessaire d'assurer la maintenance de l'état &quot;révoqué&quot; des certificats expirés. Donc, bien qu'un certificat ait été qualifié de valide pour le site Web que vous visitez actuellement, il est impossible de déterminer s'il a été, depuis, compromis puis révoqué ou s'il est toujours valide. Par conséquent, il n'est pas possible de s'assurer si vous communiquez avec un site Web légitime ou si le certificat a été compromis et se trouve maintenant en la possession d'un pirate informatique avec lequel vous communiquez. Ne poursuivez pas.</translation>
++<translation id="2645575947416143543">Néanmoins, si vous travaillez dans une entreprise qui génère ses propres certificats, et que vous essayez de vous connecter au site Web interne de l'entreprise avec un certificat de ce type, vous pouvez résoudre ce problème en toute sécurité. Pour ce faire, importez le certificat racine de l'entreprise en tant que &quot;certificat racine&quot;. Par la suite, les certificats émis ou vérifiés par votre entreprise seront approuvés et vous ne verrez plus cette erreur lorsque vous tenterez de vous connecter à nouveau au site Web interne. Contactez le support informatique de votre entreprise pour savoir comment ajouter un nouveau certificat racine sur votre ordinateur.</translation>
++<translation id="376466258076168640">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
++<translation id="1056898198331236512">Avertissement</translation>
++<translation id="8630826211403662855">Préférences de recherche</translation>
++<translation id="8432745813735585631">Clavier Colemak américain</translation>
++<translation id="8151639108075998630">Activer la navigation en tant qu'invité</translation>
++<translation id="2608770217409477136">Utiliser les paramètres par défaut</translation>
++<translation id="3157931365184549694">Rétablir</translation>
++<translation id="7426243339717063209">Désinstaller &quot;<ph name="EXTENSION_NAME"/>&quot; ?</translation>
++<translation id="996250603853062861">Établissement de la connexion sécurisée...</translation>
++<translation id="6059232451013891645">Dossier :</translation>
++<translation id="4274292172790327596">Erreur non reconnue</translation>
++<translation id="760537465793895946">Consultez les conflits connus avec des modules tiers.</translation>
++<translation id="7042418530779813870">Co&amp;ller et rechercher</translation>
++<translation id="9110447413660189038">&amp;Remonter</translation>
++<translation id="375403751935624634">Échec de la traduction en raison d'une erreur de serveur</translation>
++<translation id="2101225219012730419">Version :</translation>
++<translation id="1570242578492689919">Polices et codage</translation>
++<translation id="3082374807674020857"><ph name="PAGE_TITLE"/> - <ph name="PAGE_URL"/></translation>
++<translation id="8050038245906040378">Signature du code commercial Microsoft</translation>
++<translation id="3031557471081358569">Sélectionnez les éléments à importer :</translation>
++<translation id="1368832886055348810">De gauche à droite</translation>
++<translation id="3031433885594348982">Votre connexion à <ph name="DOMAIN"/> est sécurisée par le biais d'un faible chiffrement.</translation>
++<translation id="4047345532928475040">sans objet</translation>
++<translation id="5604324414379907186">Toujours afficher la barre de favoris</translation>
++<translation id="3220630151624181591">Activer l'onglet 2</translation>
++<translation id="8898139864468905752">Aperçu des onglets</translation>
++<translation id="2799223571221894425">Redémarrer</translation>
++<translation id="5771816112378578655">Configuration en cours...</translation>
++<translation id="1197979282329025000">Une erreur s'est produite lors de la récupération des fonctions de l'imprimante <ph name="PRINTER_NAME"/>. Cette imprimante n'a pas pu être enregistrée dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
++<translation id="8820901253980281117">Exceptions pour les fenêtres pop-up</translation>
++<translation id="1143142264369994168">Signataire du certificat </translation>
++<translation id="904949795138183864">La page Web <ph name="URL"/> n'existe plus.</translation>
++<translation id="3228279582454007836">Vous n'avez jamais visité ce site auparavant.</translation>
++<translation id="2159017110205600596">Personnaliser...</translation>
++<translation id="5449716055534515760">Fe&amp;rmer la fenêtre</translation>
++<translation id="2814489978934728345">Arrêter le chargement de cette page</translation>
++<translation id="2354001756790975382">Autres favoris</translation>
++<translation id="8561574028787046517"><ph name="PRODUCT_NAME"/> a été mis à jour.</translation>
++<translation id="5234325087306733083">Mode hors connexion</translation>
++<translation id="1779392088388639487">Erreur d'importation de fichier PKCS #12</translation>
++<translation id="166278006618318542">Algorithme de clé publique de l'objet</translation>
++<translation id="5759272020525228995">Le site Web a rencontré une erreur lors de l'extraction de <ph name="URL"/>.
++ Cela peut être dû à une opération de maintenance ou à une configuration incorrecte.</translation>
++<translation id="641480858134062906">Échec du chargement de la page <ph name="URL"/></translation>
++<translation id="3693415264595406141">Mot de passe :</translation>
++<translation id="74568296546932365">Conserver <ph name="PAGE_TITLE"/> en tant que moteur de recherche par défaut</translation>
++<translation id="8602184400052594090">Fichier manifeste absent ou illisible</translation>
++<translation id="2784949926578158345">La connexion a été réinitialisée.</translation>
++<translation id="6663792236418322902">Le mot de passe choisi vous sera demandé pour restaurer le fichier. Veillez à le conserver en lieu sûr.</translation>
++<translation id="4532822216683966758">La vérification de la provenance du certificat DNS est activée, ce qui peut entraîner l'envoi d'informations privées à Google.</translation>
++<translation id="6321196148033717308">À propos de la reconnaissance vocale</translation>
++<translation id="3412265149091626468">Aller à la sélection</translation>
++<translation id="8167737133281862792">Ajouter un certificat</translation>
++<translation id="2911372483530471524">Espaces de noms PID</translation>
++<translation id="6093374025603915876">Préférences de saisie automatique</translation>
++<translation id="8584134039559266300">Activer l'onglet 8</translation>
++<translation id="5189060859917252173">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; représente une autorité de certification.</translation>
++<translation id="3785852283863272759">Envoyer par e-mail l'emplacement de la page</translation>
++<translation id="2255317897038918278">Enregistrement des informations de date Microsoft</translation>
++<translation id="3493881266323043047">Validité</translation>
++<translation id="5979421442488174909">&amp;Traduire en <ph name="LANGUAGE"/></translation>
++<translation id="7326526699920221209">Batterie : <ph name="PRECENTAGE"/> %</translation>
++<translation id="952992212772159698">Désactivé</translation>
++<translation id="8299269255470343364">Japonais</translation>
++<translation id="5187826826541650604"><ph name="KEY_NAME"/> (<ph name="DEVICE"/>)</translation>
++<translation id="6429639049555216915">L'application est actuellement inaccessible.</translation>
++<translation id="2144536955299248197">Lecteur du certificat : <ph name="CERTIFICATE_NAME"/></translation>
++<translation id="50030952220075532"><ph name="NUMBER_ONE"/> jour restant</translation>
++<translation id="2885378588091291677">Gestionnaire de tâches</translation>
++<translation id="5792852254658380406">Gérer les extensions...</translation>
++<translation id="2359808026110333948">Continuer</translation>
++<translation id="176759384517330673">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
++<translation id="1618661679583408047">Le certificat de sécurité du site n'est pas encore valide !</translation>
++<translation id="7039912931802252762">Ouverture de session par carte à puce Microsoft</translation>
++<translation id="6285074077487067719">Format</translation>
++<translation id="3065140616557457172">Tapez votre requête ou saisissez une URL pour commencer la navigation : c'est à vous de choisir.</translation>
++<translation id="5509693895992845810">Enregistrer &amp;sous...</translation>
++<translation id="5986279928654338866">Le serveur <ph name="DOMAIN"/> requiert un nom d'utilisateur et un mot de passe.</translation>
++<translation id="521467793286158632">Supprimer tous les mots de passe</translation>
++<translation id="2491120439723279231">Le certificat du serveur contient des erreurs.</translation>
++<translation id="4448844063988177157">Recherche de réseaux Wi-Fi...</translation>
++<translation id="5765780083710877561">Description :</translation>
++<translation id="338583716107319301">Séparateur</translation>
++<translation id="2079053412993822885">Si vous supprimez l'un de vos propres certificats, vous ne pouvez plus l'utiliser pour vous identifier.</translation>
++<translation id="7221869452894271364">Rafraîchir cette page</translation>
++<translation id="6791443592650989371">État d'activation :</translation>
++<translation id="4801257000660565496">Créer des raccourcis vers des applications</translation>
++<translation id="6503256918647795660">Clavier franco-suisse</translation>
++<translation id="6175314957787328458">GUID de domaine Microsoft</translation>
++<translation id="8179976553408161302">Entrer</translation>
++<translation id="8261506727792406068">Supprimer</translation>
++<translation id="4404805853119650018">Échec de l'enregistrement de cet ordinateur pour l'accès à distance.</translation>
++<translation id="345693547134384690">Ouvrir l'&amp;image dans un nouvel onglet</translation>
++<translation id="7422192691352527311">Préférences...</translation>
++<translation id="354211537509721945">L'administrateur a désactivé les mises à jour.</translation>
++<translation id="1375198122581997741">À propos de la version</translation>
++<translation id="7915471803647590281">Veuillez nous indiquer ce qu'il se passe avant d'envoyer votre rapport.</translation>
++<translation id="5725124651280963564">Connectez-vous à <ph name="TOKEN_NAME"/> afin de générer une clé pour <ph name="HOST_NAME"/>.</translation>
++<translation id="8418113698656761985">Clavier roumain</translation>
++<translation id="5976160379964388480">Autres</translation>
++<translation id="3665842570601375360">Sécurité :</translation>
++<translation id="1430915738399379752">Imprimer</translation>
++<translation id="7999087758969799248">Mode de saisie standard</translation>
++<translation id="2635276683026132559">Signature</translation>
++<translation id="4835836146030131423">Erreur lors de la connexion</translation>
++<translation id="7715454002193035316">Pour cette session uniquement</translation>
++<translation id="2475982808118771221">Une erreur s'est produite.</translation>
++<translation id="3324684065575061611">(Désactivé par une stratégie d'entreprise)</translation>
++<translation id="7385854874724088939">Erreur lors de la tentative d'impression. Vérifiez votre imprimante et réessayez.</translation>
++<translation id="770015031906360009">Grec</translation>
++<translation id="3834901049798243128">Ignorer les exceptions et bloquer l'enregistrement des cookies tiers</translation>
++<translation id="8116152017593700047">Cet outil vous permet de sélectionner une capture d'écran enregistrée. Aucune capture d'écran n'est disponible pour le moment. Appuyez simultanément sur Ctrl et sur la touche &quot;Mode Présentation&quot; pour enregistrer une capture d'écran. Vos trois dernières captures apparaissent ici.</translation>
++<translation id="3454157711543303649">Activation effectuée</translation>
++<translation id="884923133447025588">Aucun système de révocation trouvé</translation>
++<translation id="556042886152191864">Bouton</translation>
++<translation id="1352060938076340443">Interrompu</translation>
++<translation id="8571226144504132898">Dictionnaire de symboles</translation>
++<translation id="7229570126336867161">Technologie EvDo requise</translation>
++<translation id="7582844466922312471">Internet mobile</translation>
++<translation id="945522503751344254">Envoyer le commentaire</translation>
++<translation id="4539401194496451708">Associé au profil Chrome <ph name="USER_EMAIL_ADDRESS"/>. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
++<translation id="7369847606959702983">Carte de crédit (autre)</translation>
++<translation id="6867459744367338172">Langues et saisie</translation>
++<translation id="7671130400130574146">Utiliser la barre de titre et les bordures de fenêtre du système</translation>
++<translation id="9170848237812810038">Ann&amp;uler</translation>
++<translation id="284970761985428403"><ph name="ASCII_NAME"/> (<ph name="UNICODE_NAME"/>)</translation>
++<translation id="3903912596042358459">Le serveur a refusé d'exécuter la demande.</translation>
++<translation id="8135557862853121765"><ph name="NUM_KILOBYTES"/> Ko</translation>
++<translation id="4444364671565852729"><ph name="PRODUCT_NAME"/> a été mis à jour vers la version <ph name="VERSION"/>.</translation>
++<translation id="5819890516935349394">Navigateur de contenu</translation>
++<translation id="2731392572903530958">&amp;Rouvrir la fenêtre fermée</translation>
++<translation id="1254593899333212300">Se connecter directement à Internet</translation>
++<translation id="6107012941649240045">Émis pour</translation>
++<translation id="6483805311199035658">Ouverture de <ph name="FILE"/> en cours</translation>
++<translation id="3576278878016363465">Cibles disponibles pour l'image</translation>
++<translation id="895541991026785598">Signaler un problème</translation>
++<translation id="940425055435005472">Taille de police :</translation>
++<translation id="494286511941020793">Aide pour la configuration de proxy</translation>
++<translation id="2765217105034171413">Petite</translation>
++<translation id="1285266685456062655"><ph name="NUMBER_FEW"/> hours ago</translation>
++<translation id="9154176715500758432">Rester sur cette page</translation>
++<translation id="5875565123733157100">Type de bug :</translation>
++<translation id="6988771638657196063">Inclure cette URL :</translation>
++<translation id="5717920936024713315">Cookies et données de site...</translation>
++<translation id="3842552989725514455">Police Serif</translation>
++<translation id="1949795154112250744"><ph name="BEGIN_BOLD"/>Avertissement :<ph name="END_BOLD"/> <ph name="PRODUCT_NAME"/> ne peut pas empêcher les extensions d'enregistrer votre historique de navigation. Pour désactiver cette extension en mode navigation privée, désélectionnez-la.</translation>
++<translation id="4440967101351338638">ChromiumOs Image Burn</translation>
++<translation id="1813278315230285598">Services</translation>
++<translation id="6860097299815761905">Paramètres du proxy...</translation>
++<translation id="373572798843615002">1 onglet</translation>
++<translation id="4162393307849942816"><ph name="BEGIN_BOLD"/>Vous naviguez en tant qu'invité<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront pas dans l'historique de votre navigateur ni dans votre historique des recherches. Les autres traces telles que les cookies seront supprimées de l'ordinateur à la fin de votre session. En revanche, les fichiers téléchargés et les favoris créés seront conservés.
++ <ph name="LINE_BREAK"/>
++ <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur le mode invité</translation>
++<translation id="827924395145979961">Chargement des pages impossible</translation>
++<translation id="3092544800441494315">Inclure cette capture d'écran :</translation>
++<translation id="7714464543167945231">Certificat</translation>
++<translation id="3616741288025931835">&amp;Effacer les données de navigation...</translation>
++<translation id="3313622045786997898">Valeur de signature du certificat</translation>
++<translation id="8535005006684281994">URL de renouvellement du certificat Netscape</translation>
++<translation id="2440604414813129000">Afficher la s&amp;ource</translation>
++<translation id="816095449251911490"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/>, <ph name="TIME_REMAINING"/></translation>
++<translation id="8200772114523450471">Reprendre</translation>
++<translation id="6358975074282722691"><ph name="NUMBER_TWO"/> secs ago</translation>
++<translation id="5423849171846380976">Activé</translation>
++<translation id="6748105842970712833">Carte SIM désactivée</translation>
++<translation id="7323391064335160098">Compatibilité avec VPN</translation>
++<translation id="3929673387302322681">Développement - Instable</translation>
++<translation id="4251486191409116828">Échec de création du raccourci vers l'application</translation>
++<translation id="5190835502935405962">Barre de favoris</translation>
++<translation id="7828272290962178636">Le serveur est en mesure de répondre à la demande.</translation>
++<translation id="7823073559911777904">Modifier les paramètres du proxy...</translation>
++<translation id="5438430601586617544">(non empaquetée)</translation>
++<translation id="6460601847208524483">Rechercher le suivant</translation>
++<translation id="8433186206711564395">Paramètres réseau</translation>
++<translation id="4856478137399998590">Votre service Internet mobile est activé et prêt à l'emploi.</translation>
++<translation id="1676388805288306495">Modifier la police et la langue par défaut des pages Web</translation>
++<translation id="8969761905474557563">Composition graphique avec accélération matérielle</translation>
++<translation id="3937640725563832867">Autre nom de l'émetteur du certificat</translation>
++<translation id="4701488924964507374"><ph name="SENTENCE1"/> <ph name="SENTENCE2"/></translation>
++<translation id="1163931534039071049">&amp;Afficher le code source du cadre</translation>
++<translation id="8770196827482281187">Mode de saisie du persan (clavier ISIRI 2901)</translation>
++<translation id="6423239382391657905">OpenVPN</translation>
++<translation id="7564847347806291057">Arrêter le processus</translation>
++<translation id="1607220950420093847">Votre compte a peut-être été supprimé ou désactivé. Veuillez vous déconnecter.</translation>
++<translation id="5613695965848159202">Authentification anonyme :</translation>
++<translation id="2233320200890047564">Bases de données indexées</translation>
++<translation id="7063412606254013905">En savoir plus sur les escroqueries par phishing</translation>
++<translation id="307767688111441685">Page à l'apparence anormale</translation>
++<translation id="9076523132036239772">Adresse e-mail ou mot de passe incorrect. Essayez tout d'abord de vous connecter à un réseau.</translation>
++<translation id="6965978654500191972">Périphérique</translation>
++<translation id="1242521815104806351">Informations sur la connexion</translation>
++<translation id="5295309862264981122">Confirmer la navigation</translation>
++<translation id="1492817554256909552">Nom du point d'accès :</translation>
++<translation id="5546865291508181392">Rechercher</translation>
++<translation id="1999115740519098545">Au démarrage</translation>
++<translation id="2983818520079887040">Paramètres...</translation>
++<translation id="1465619815762735808">Lire en un clic</translation>
++<translation id="6941937518557314510">Connectez-vous à <ph name="TOKEN_NAME"/> pour vous authentifier auprès de <ph name="HOST_NAME"/> avec votre certificat.</translation>
++<translation id="2783600004153937501">Votre administrateur informatique a désactivé certaines options.</translation>
++<translation id="2099686503067610784">Supprimer le certificat de serveur &quot;<ph name="CERTIFICATE_NAME"/>&quot;?</translation>
++<translation id="9027603907212475920">Configurer la synchronisation...</translation>
++<translation id="6873213799448839504">Valider automatiquement une chaîne</translation>
++<translation id="7238585580608191973">Empreinte SHA-256</translation>
++<translation id="2501278716633472235">Retour</translation>
++<translation id="131461803491198646">Réseau domestique, sans itinérance</translation>
++<translation id="7377249249140280793"><ph name="RELATIVE_DATE"/> - <ph name="FULL_DATE"/></translation>
++<translation id="5679279978772703611">Gérer les mots de passe enregistrés...</translation>
++<translation id="4551440281920791563">Sélectionnez
++ <ph name="BEGIN_BOLD"/>
++ Menu clé à molette &gt; Options &gt; Options avancées &gt; Modifier les paramètres du proxy &gt; Paramètres réseau
++ <ph name="END_BOLD"/>
++ et désélectionnez l'option &quot;Utiliser un serveur proxy pour votre réseau local&quot;.</translation>
++<translation id="1285320974508926690">Ne jamais traduire ce site</translation>
++<translation id="8954894007019320973">(suite)</translation>
++<translation id="3748412725338508953">Trop de redirections</translation>
++<translation id="5833726373896279253">Ces paramètres ne peuvent être modifiés que par le propriétaire :</translation>
++<translation id="6858960932090176617">Active la protection XSS Auditor de WebKit (protection contre le Cross-site Scripting), une fonctionnalité qui vous protège de certaines attaques de sites malveillants et offre une sécurité accrue, mais qui n'est pas compatible avec tous les sites Web.</translation>
++<translation id="6005282720244019462">Clavier latino-américain</translation>
++<translation id="8831104962952173133">Phishing détecté !</translation>
++<translation id="5141720258550370428">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
++<translation id="6751344591405861699"><ph name="WINDOW_TITLE"/> (Navigation privée)</translation>
++<translation id="6681668084120808868">Prendre une photo</translation>
++<translation id="780301667611848630">Non merci</translation>
++<translation id="2812989263793994277">Ne pas afficher les images</translation>
++<translation id="7190251665563814471">Toujours autoriser ces plug-ins sur <ph name="HOST"/></translation>
++<translation id="6845383723252244143">Sélectionner un dossier</translation>
++<translation id="8925458182817574960">&amp;Paramètres</translation>
++<translation id="6361850914223837199">Informations sur l'erreur :</translation>
++<translation id="8948393169621400698">Toujours autoriser les plug-ins sur <ph name="HOST"/></translation>
++<translation id="3865082058368813534">Effacer les données de saisie automatique enregistrées</translation>
++<translation id="8288345061925649502">Changer de moteur de recherche</translation>
++<translation id="5436492226391861498">En attente du tunnel proxy...</translation>
++<translation id="3803991353670408298">Veuillez ajouter un autre mode de saisie avant de supprimer celui-ci.</translation>
++<translation id="1095623615273566396"><ph name="NUMBER_FEW"/> secondes</translation>
++<translation id="7006788746334555276">Paramètres de contenu</translation>
++<translation id="3369521687965833290">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils commençant par une lettre de lecteur et ne contenant ni jonction, ni point de montage, ni lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
++<translation id="337920581046691015"><ph name="PRODUCT_NAME"/> va être installé.</translation>
++<translation id="6282194474023008486">Code postal</translation>
++<translation id="7733107687644253241">En bas à droite</translation>
++<translation id="5139955368427980650">&amp;Ouvrir</translation>
++<translation id="8136149669168180907"><ph name="DOWNLOADED_AMOUNT"/> téléchargé(s) sur <ph name="TOTAL_SIZE"/></translation>
++<translation id="7375268158414503514">Commentaires d'ordre général/Autres</translation>
++<translation id="4643612240819915418">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
++<translation id="7997479212858899587">Identité :</translation>
++<translation id="8300849813060516376">Échec de l'opération OTASP</translation>
++<translation id="2213819743710253654">Action sur la page</translation>
++<translation id="1317130519471511503">Modifier des éléments...</translation>
++<translation id="6391538222494443604">Le répertoire d'extensions est obligatoire.</translation>
++<translation id="8051695050440594747"><ph name="MEGABYTES"/> Mo disponibles</translation>
++<translation id="7088615885725309056">Ancien</translation>
++<translation id="461656879692943278"><ph name="HOST_NAME"/> fournit du contenu provenant de <ph name="ELEMENTS_HOST_NAME"/>, un site connu pour distribuer des logiciels malveillants. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
++<translation id="1387022316521171484">Ces fonctionnalités expérimentales sont susceptibles d'être modifiées, interrompues ou supprimées à tout moment. Nous ne fournissons aucune garantie quant aux effets de leur activation. Votre navigateur pourrait bien prendre feu. Trêve de plaisanterie, il est possible que votre navigateur supprime toutes vos données ou que votre sécurité et votre vie privée soient compromises de manière inattendue. Nous vous prions d'agir avec précaution.</translation>
++<translation id="2143778271340628265">Configuration manuelle du proxy</translation>
++<translation id="5294529402252479912">Mettre à jour Adobe Reader maintenant</translation>
++<translation id="5263972071113911534"><ph name="NUMBER_MANY"/> days ago</translation>
++<translation id="7461850476009326849">Désactiver les plug-ins individuels...</translation>
++<translation id="4097411759948332224">Envoyer une capture d'écran de la page en cours</translation>
++<translation id="2231990265377706070">Point d'exclamation</translation>
++<translation id="7199540622786492483"><ph name="PRODUCT_NAME"/> n'est plus à jour, car il n'a pas été relancé depuis quelque temps. La mise à jour disponible sera installée dès que vous le relancerez.</translation>
++<translation id="8652722422052983852">Petit problème... Tentons de le résoudre.</translation>
++<translation id="5970231080121144965">Cette fonctionnalité permet d'établir des correspondances entre les sous-chaînes et plusieurs fragments d'URL figurant dans l'historique.</translation>
++<translation id="4665674675433053715">Page &quot;Nouvel onglet&quot; expérimentale</translation>
++<translation id="3726527440140411893">Les cookies suivants étaient autorisés lorsque vous avez consulté cette page :</translation>
++<translation id="3320859581025497771">votre opérateur</translation>
++<translation id="8828781037212165374">Activer ces fonctionnalités...</translation>
++<translation id="8562413501751825163">Quitter Firefox avant l'importation</translation>
++<translation id="3435541101098866721">Ajouter un nouveau téléphone</translation>
++<translation id="2448046586580826824">Proxy HTTP sécurisé</translation>
++<translation id="4032534284272647190">Accès à <ph name="URL"/> refusé.</translation>
++<translation id="4928569512886388887">Finalisation de la mise à jour du système...</translation>
++<translation id="8258002508340330928">Voulez-vous continuer ?</translation>
++<translation id="4309420042698375243"><ph name="NUM_KILOBYTES"/> Ko (<ph name="NUM_KILOBYTES_LIVE"/> Ko effectifs)</translation>
++<translation id="5554573843028719904">Autre réseau Wi-Fi...</translation>
++<translation id="5034259512732355072">Choisir un autre répertoire...</translation>
++<translation id="8885905466771744233">L'extension indiquée est déjà associée à une clé privée. Utilisez cette clé ou supprimez-la.</translation>
++<translation id="7831504847856284956">Ajouter une adresse</translation>
++<translation id="7505152414826719222">Stockage local</translation>
++<translation id="2541423446708352368">Afficher tous les téléchargements</translation>
++<translation id="4381021079159453506">Navigateur de contenu</translation>
++<translation id="8109246889182548008">Magasin de certificats</translation>
++<translation id="5030338702439866405">Émis par</translation>
++<translation id="5280833172404792470">Quitter le mode plein écran (<ph name="ACCELERATOR"/>)</translation>
++<translation id="2728127805433021124">Le certificat du serveur a été signé avec un algorithme de signature faible.</translation>
++<translation id="2137808486242513288">Ajouter un utilisateur</translation>
++<translation id="6193618946302416945">Me proposer de traduire les pages qui sont écrites dans une langue que je ne sais pas lire</translation>
++<translation id="129553762522093515">Récemment fermés</translation>
++<translation id="4287167099933143704">Saisir la clé de déverrouillage du code PIN</translation>
++<translation id="8355915647418390920"><ph name="NUMBER_FEW"/> jours</translation>
++<translation id="3129140854689651517">Rechercher du texte</translation>
++<translation id="7221585318879598658">Sans-Serif</translation>
++<translation id="5558129378926964177">Zoom &amp;avant</translation>
++<translation id="6451458296329894277">Confirmer le nouvel envoi du formulaire</translation>
++<translation id="5116333507878097773"><ph name="NUMBER_ONE"/> heure</translation>
++<translation id="8028152732786498049">Cet élément doit être installé depuis <ph name="CHROME_WEB_STORE"/>.</translation>
++<translation id="9199258761842902152">Mise en veille ou reprise</translation>
++<translation id="1851266746056575977">Mettre à jour maintenant</translation>
++<translation id="7017219178341817193">Ajouter une page</translation>
++<translation id="1038168778161626396">Chiffrer seulement</translation>
++<translation id="2756651186786928409">Ne jamais intervertir les touches de modification</translation>
++<translation id="1217515703261622005">Conversion des numéros spéciaux</translation>
++<translation id="7179921470347911571">Relancer maintenant</translation>
++<translation id="3715099868207290855">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée</translation>
++<translation id="2679312662830811292">il y a <ph name="NUMBER_ONE"/> minute</translation>
++<translation id="9065203028668620118">Édition</translation>
++<translation id="4718464510840275738">Préférences synchronisées</translation>
++<translation id="8788572795284305350"><ph name="NUMBER_ZERO"/> hours ago</translation>
++<translation id="1177863135347784049">Personnalisé</translation>
++<translation id="8236028464988198644">Rechercher à partir de la barre d'adresse</translation>
++<translation id="4881695831933465202">Ouvrir</translation>
++<translation id="5988520580879236902">Inspecter les vues actives :</translation>
++<translation id="3593965109698325041">Contraintes de nom du certificat</translation>
++<translation id="4358697938732213860">Ajouter une adresse</translation>
++<translation id="8396532978067103567">Mot de passe incorrect.</translation>
++<translation id="5981759340456370804">Statistiques avancées</translation>
++<translation id="8160015581537295331">Clavier espagnol</translation>
++<translation id="3505920073976671674">Sélectionnez votre réseau</translation>
++<translation id="6644971472240498405"><ph name="NUMBER_ONE"/> jour</translation>
++<translation id="1782924894173027610">Le serveur de synchronisation est occupé. Veuillez réessayer ultérieurement.</translation>
++<translation id="6512448926095770873">Quitter cette page</translation>
++<translation id="5457599981699367932">Naviguer en tant qu'invité</translation>
++<translation id="3169472444629675720">Discover</translation>
++<translation id="6294193300318171613">&amp;Toujours afficher la barre de favoris</translation>
++<translation id="4088820693488683766">Options de recherche</translation>
++<translation id="3414952576877147120">Taille :</translation>
++<translation id="9098468523912235228">il y a <ph name="NUMBER_DEFAULT"/> secondes</translation>
++<translation id="7009102566764819240">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur une ressource particulière. Si une ressource a été signalée comme site de phishing alors que vous êtes certain de sa fiabilité, cliquez sur le lien &quot;Signaler une erreur&quot;.</translation>
++<translation id="4923417429809017348">Cette page rédigée dans une langue non identifiée a été traduite en <ph name="LANGUAGE_LANGUAGE"/>.</translation>
++<translation id="3631337165634322335">Les exceptions ci-dessous s'appliquent uniquement à la session de navigation privée actuelle.</translation>
++<translation id="676327646545845024">Ne plus afficher la boîte de dialogue pour les liens de ce type</translation>
++<translation id="494645311413743213"><ph name="NUMBER_TWO"/> secondes restantes</translation>
++<translation id="1485146213770915382">Insérez <ph name="SEARCH_TERMS_LITERAL"/> dans l'URL où les termes de recherche devraient apparaître.</translation>
++<translation id="4839303808932127586">En&amp;registrer la vidéo sous...</translation>
++<translation id="5626134646977739690">Nom :</translation>
++<translation id="5854409662653665676">Si vous rencontrez des problèmes fréquents avec ce module, vous pouvez tenter d'y remédier en suivant la procédure ci-après :</translation>
++<translation id="3681007416295224113">Informations relatives au certificat</translation>
++<translation id="3046084099139788433">Activer l'onglet 7</translation>
++<translation id="721197778055552897"><ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur ce problème.</translation>
++<translation id="1699395855685456105">Version du matériel :</translation>
++<translation id="212464871579942993">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur. Ce site héberge également des informations provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer des informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
++<translation id="8156020606310233796">Afficher la liste</translation>
++<translation id="957120528631539888">Désactivez l'affichage des messages de confirmation et le blocage de l'envoi des formulaires.</translation>
++<translation id="146000042969587795">Ce cadre a été bloqué, car il contient des éléments non sécurisés.</translation>
++<translation id="8112223930265703044">Tout</translation>
++<translation id="3968739731834770921">Kana</translation>
++<translation id="3729920814805072072">Gérer les mots de passe enregistrés...</translation>
++<translation id="7387829944233909572">Boîte de dialogue &quot;Effacer les données de navigation&quot;</translation>
++<translation id="8023801379949507775">Mettre à jour les extensions maintenant</translation>
++<translation id="6549677549082720666">Nouvelle application en arrière-plan installée</translation>
++<translation id="1983108933174595844">Envoyer une capture d'écran de la page actuelle</translation>
++<translation id="3298789223962368867">L'URL indiquée est incorrecte.</translation>
++<translation id="2202898655984161076">Un problème est survenu lors de l'affichage de la liste des imprimantes. Certaines de vos imprimantes ne sont peut-être pas correctement enregistrées dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
++<translation id="6154697846084421647">Actuellement connecté</translation>
++<translation id="8241707690549784388">La page que vous recherchez a utilisé des informations que vous avez envoyées. Si vous revenez sur cette page, chaque action précédemment effectuée sera répétée. Souhaitez-vous continuer ?</translation>
++<translation id="5359419173856026110">Cette fonctionnalité indique la vitesse d'affichage réelle d'une page, en images par seconde, lorsque l'accélération matérielle est active.</translation>
++<translation id="4104163789986725820">E&amp;xporter...</translation>
++<translation id="2113479184312716848">&amp;Ouvrir un fichier...</translation>
++<translation id="8412709057120877195">Configurer le contrôle d'accès pour vos périphériques</translation>
++<translation id="486595306984036763">Ouvrir un rapport de phishing</translation>
++<translation id="3140353188828248647">Activer la barre d'adresse</translation>
++<translation id="4860787810836767172"><ph name="NUMBER_FEW"/> secs ago</translation>
++<translation id="5565871407246142825">Cartes de paiement</translation>
++<translation id="2587203970400270934">Code opérateur :</translation>
++<translation id="3355936511340229503">Erreur de connexion</translation>
++<translation id="1824910108648426227">Vous avez la possibilité de désactiver ces services.</translation>
++<translation id="3092040396860056776">Essayer d'afficher la page malgré tout</translation>
++<translation id="4350711002179453268">Impossible d'établir une connexion sécurisée avec le serveur. Le serveur a peut-être rencontré un problème ou exige un certificat d'authentification du client dont vous ne disposez pas.</translation>
++<translation id="91731790394942114">Ajouter un nouveau nom</translation>
++<translation id="5963026469094486319">Obtenir d'autres thèmes</translation>
++<translation id="2441719842399509963">Rétablir les valeurs par défaut</translation>
++<translation id="1893137424981664888">Aucun Plug-in installé.</translation>
++<translation id="3718288130002896473">Action</translation>
++<translation id="2168725742002792683">Extensions de fichier</translation>
++<translation id="1753905327828125965">Les plus visités</translation>
++<translation id="8116972784401310538">&amp;Gestionnaire de favoris</translation>
++<translation id="1849632043866553433">Caches des applications</translation>
++<translation id="3591607774768458617">Cette langue est actuellement utilisée par <ph name="PRODUCT_NAME"/>.</translation>
++<translation id="621638399744152264"><ph name="VALUE"/> %</translation>
++<translation id="4927301649992043040">Empaqueter l'extension</translation>
++<translation id="8679658258416378906">Activer l'onglet 5</translation>
++<translation id="4763816722366148126">Sélectionner le mode de saisie précédent</translation>
++<translation id="6458308652667395253">Configurer le blocage de JavaScript...</translation>
++<translation id="8435334418765210033">Réseaux mémorisés</translation>
++<translation id="6516193643535292276">Impossible de se connecter à Internet.</translation>
++<translation id="5125751979347152379">URL incorrecte</translation>
++<translation id="2791364193466153585">Informations sur la sécurité</translation>
++<translation id="4673916386520338632">Impossible d'installer l'application, car elle est en conflit avec &quot;<ph name="APP_NAME"/>&quot;, qui est déjà installé.</translation>
++<translation id="2024918351532495204">Votre périphérique n'est pas connecté.</translation>
++<translation id="6040143037577758943">Fermer</translation>
++<translation id="5787146423283493983">Accord de la clé</translation>
++<translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation>
++<translation id="4265682251887479829">Vous ne trouvez pas ce que vous recherchez ?</translation>
++<translation id="1804251416207250805">Désactivez l'envoi des pings de contrôle des liens hypertexte.</translation>
++<translation id="5116628073786783676">En&amp;registrer le fichier audio sous...</translation>
++<translation id="2557899542277210112">Accédez rapidement à vos favoris en les ajoutant à la barre de favoris.</translation>
++<translation id="2749881179542288782">Vérifier la grammaire et l'orthographe</translation>
++<translation id="5105855035535475848">Épingler les onglets</translation>
++<translation id="6892450194319317066">Sélectionner par type d'application</translation>
++<translation id="3549436232897695316">assembler</translation>
++<translation id="5414121716219514204"><ph name="ENGINE_HOST_NAME"/> souhaite devenir votre moteur de recherche.</translation>
++<translation id="2752805177271551234">Utiliser l'historique d'entrée</translation>
++<translation id="7268365133021434339">Fermer les onglets</translation>
++<translation id="4910619056351738551">Voici quelques suggestions :</translation>
++<translation id="9131598836763251128">Sélectionnez un ou plusieurs fichiers</translation>
++<translation id="5489059749897101717">Afficher le panneau de la &amp;vérification orthographique</translation>
++<translation id="3423858849633684918">Veuillez relancer <ph name="PRODUCT_NAME"/>.</translation>
++<translation id="1232569758102978740">Sans titre</translation>
++<translation id="1903219944620007795">Pour saisir du texte, sélectionnez une langue et consultez la liste des modes de saisie disponibles.</translation>
++<translation id="4362187533051781987">Ville</translation>
++<translation id="9149866541089851383">Modifier...</translation>
++<translation id="7608619752233383356">Réinitialiser la synchronisation</translation>
++<translation id="1065245965611933814">Inclure une capture d'écran enregistrée :</translation>
++<translation id="7876243839304621966">Tout supprimer</translation>
++<translation id="5663459693447872156">Passer automatiquement en demi-chasse</translation>
++<translation id="4593021220803146968">&amp;Accéder à <ph name="URL"/></translation>
++<translation id="1128987120443782698">La capacité de ce périphérique de stockage est de <ph name="DEVICE_CAPACITY"/>. Veuillez insérer une carte SD ou une clé USB d'au moins 4 Go.</translation>
++<translation id="869257642790614972">Rouvrir le dernier onglet fermé</translation>
++<translation id="3978267865113951599">(blocage)</translation>
++<translation id="8412145213513410671">Erreurs (<ph name="CRASH_COUNT"/>)</translation>
++<translation id="560602183358579978">Traitement de la sélection...</translation>
++<translation id="7649070708921625228">Aide</translation>
++<translation id="5994107996638824097">Désolé ! La visionneuse de documents PDF intégrée à Google Chrome, nécessaire à l'affichage de l'aperçu avant impression, n'est pas incluse dans Chromium.</translation>
++<translation id="976526967778596630">Impossible d'ouvrir <ph name="HOST_NAME"/>, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
++<translation id="1734072960870006811">Télécopie</translation>
++<translation id="3095995014811312755">version</translation>
++<translation id="7052500709156631672">La passerelle ou le serveur proxy a reçu une réponse incorrecte d'un serveur en amont.</translation>
++<translation id="281133045296806353">Nouvelle fenêtre ouverte dans la session du navigateur</translation>
++<translation id="7144878232160441200">Réessayer</translation>
++<translation id="2860002559146138960"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Vos données seront chiffrées avec le mot de passe de votre compte Google ou le mot de passe multiterme de votre choix.</translation>
++<translation id="3951872452847539732">Les paramètres réseau de votre proxy sont gérés par une extension.</translation>
++<translation id="6442697326824312960">Retirer l'onglet</translation>
++<translation id="6382612843547381371">Valable du <ph name="START_DATE_TIME"/> au <ph name="END_DATE_TIME"/></translation>
++<translation id="6869402422344886127">Case cochée</translation>
++<translation id="5637380810526272785">Mode de saisie</translation>
++<translation id="404928562651467259">AVERTISSEMENT</translation>
++<translation id="7172053773111046550">Clavier estonien</translation>
++<translation id="497490572025913070">Ajout de bordures aux couches de rendu composées</translation>
++<translation id="9002707937526687073">Imp&amp;rimer...</translation>
++<translation id="5953934840931207585">Paramètres de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
++<translation id="5556459405103347317">Rafraîchir</translation>
++<translation id="8000020256436988724">Barre d'outils</translation>
++<translation id="8326395326942127023">Nom de la base de données :</translation>
++<translation id="7507930499305566459">Certificat du répondeur d'état</translation>
++<translation id="2689915906323125315">Utiliser le mot de passe de mon compte Google</translation>
++<translation id="6440205424473899061">Vos favoris sont maintenant synchronisés avec Google Documents !
++Pour fusionner et synchroniser vos favoris dans <ph name="PRODUCT_NAME"/> sur un autre ordinateur, procédez de la même manière que précédemment sur l'ordinateur voulu.</translation>
++<translation id="7727721885715384408">Renommer...</translation>
++<translation id="2604243255129603442"><ph name="NAME_OF_EXTENSION"/> a été désactivé. Si vous arrêtez la synchronisation des favoris, vous pouvez la réactiver sur la page des extensions, via le menu Outils.</translation>
++<translation id="2024621544377454980">Affichage des pages impossible</translation>
++<translation id="7136694880210472378">Utiliser par défaut</translation>
++<translation id="7681202901521675750">La carte SIM est verrouillée. Veuillez saisir votre code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
++<translation id="1731346223650886555">Point-virgule</translation>
++<translation id="158849752021629804">Réseau domestique requis</translation>
++<translation id="7339763383339757376">PKCS #7, certificat unique</translation>
++<translation id="7587108133605326224">Langues baltes</translation>
++<translation id="3991936620356087075">Vous avez saisi un trop grand nombre de clés de verrouillage du code PIN incorrectes. Votre carte SIM est définitivement désactivée.</translation>
++<translation id="936801553271523408">Données de diagnostic système</translation>
++<translation id="6389701355360299052">Page Web, contenu HTML uniquement</translation>
++<translation id="8067791725177197206">Continuer »</translation>
++<translation id="9009144784540995197">Gérez vos imprimantes.</translation>
++<translation id="1055006259534905434">(Choisir un problème dans la liste ci-dessous)</translation>
++<translation id="3021678814754966447">&amp;Afficher le code source du cadre</translation>
++<translation id="8601206103050338563">Authentification du client WWW TLS</translation>
++<translation id="1692799361700686467">Les cookies de plusieurs sites sont autorisés.</translation>
++<translation id="7074488040076962230">Impossible d'afficher la page de la barre latérale &quot;<ph name="SIDEBAR_PAGE"/>&quot;.</translation>
++<translation id="529232389703829405">Vous avez acheté <ph name="DATA_AMOUNT"/> de données le <ph name="DATE"/>.</translation>
++<translation id="5271549068863921519">Enregistrer le mot de passe</translation>
++<translation id="4345587454538109430">Configurer...</translation>
++<translation id="8148264977957212129">Mode de saisie du pinyin</translation>
++<translation id="5787378733537687553">Intervertir les touches Ctrl et Alt de gauche</translation>
++<translation id="7772032839648071052">Confirmer le mot de passe multiterme</translation>
++<translation id="6857811139397017780">Activer <ph name="NETWORKSERVICE"/></translation>
++<translation id="3251855518428926750">Ajouter...</translation>
++<translation id="4120075327926916474">Voulez-vous que Google Chrome enregistre ces informations de carte de paiement pour le remplissage de formulaires Web ?</translation>
++<translation id="6929555043669117778">Continuer à bloquer les fenêtres pop-up</translation>
++<translation id="5864471791310927901">Échec de la vérification DHCP</translation>
++<translation id="3508920295779105875">Choisir un autre dossier...</translation>
++<translation id="2503458975635466059">Le profil semble être utilisé par le processus <ph name="PROCESS_ID"/> sur l'hôte <ph name="HOST_NAME"/>. Si vous êtes certain qu'aucun autre processus n'utilise ce profil, supprimez le fichier <ph name="LOCK_FILE"/> et relancez <ph name="PRODUCT_NAME"/>.</translation>
++<translation id="2987775926667433828">Chinois traditionnel</translation>
++<translation id="6684737638449364721">Effacer les données de navigation...</translation>
++<translation id="3954582159466790312">Ré&amp;activer le son</translation>
++<translation id="1110772031432362678">Aucun réseau trouvé.</translation>
++<translation id="3936390757709632190">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
++<translation id="7297622089831776169">&amp;Méthodes d'entrée</translation>
++<translation id="5731698828607291678">Onglets ou fenêtres</translation>
++<translation id="1152775729948968688">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer le comportement de cette page.</translation>
++<translation id="604124094241169006">Automatique</translation>
++<translation id="862542460444371744">&amp;Extensions</translation>
++<translation id="8045462269890919536">Roumain</translation>
++<translation id="6320286250305104236">Paramètres du réseau...</translation>
++<translation id="2927657246008729253">Changer...</translation>
++<translation id="7978412674231730200">Clé privée</translation>
++<translation id="464745974361668466">Format :</translation>
++<translation id="5308380583665731573">Se connecter</translation>
++<translation id="9111395131601239814"><ph name="NETWORKDEVICE"/> : <ph name="STATUS"/></translation>
++<translation id="9049981332609050619">Vous avez tenté de contacter <ph name="DOMAIN"/>, mais le certificat présenté par le serveur est incorrect.</translation>
++<translation id="4414232939543644979">Nouvelle fenêtre de nav&amp;igation privée</translation>
++<translation id="1693754753824026215">La page à l'adresse <ph name="SITE"/> indique :</translation>
++<translation id="7148804936871729015">Le serveur associé à <ph name="URL"/> n'a pas répondu à temps. Cela peut être dû à une surcharge.</translation>
++<translation id="5950967683057767490">L2TP/IPSec + Clé pré-partagée</translation>
++<translation id="8108473539339615591">XSS Auditor</translation>
++<translation id="1902576642799138955">Durée de validité</translation>
++<translation id="4910021444507283344">WebGL</translation>
++<translation id="6692173217867674490">Mot de passe multiterme erroné</translation>
++<translation id="5550431144454300634">Corriger automatiquement la saisie</translation>
++<translation id="3308006649705061278">Unité d'organisation</translation>
++<translation id="8912362522468806198">Compte Google</translation>
++<translation id="4443536555189480885">&amp;Aide</translation>
++<translation id="340485819826776184">Utiliser un service de prédiction afin de compléter les recherches et les URL saisies dans la barre d'adresse</translation>
++<translation id="4074900173531346617">Certificat du signataire de courrier électronique</translation>
++<translation id="6165508094623778733">En savoir plus</translation>
++<translation id="9052208328806230490">Vous avez enregistré vos imprimantes sur <ph name="CLOUD_PRINT_NAME"/> via le compte <ph name="EMAIL"/>.</translation>
++<translation id="822618367988303761">il y a <ph name="NUMBER_TWO"/> jours</translation>
++<translation id="7928333295097642153"><ph name="HOUR"/>:<ph name="MINUTE"/> restantes</translation>
++<translation id="7568593326407688803">Cette page est en<ph name="ORIGINAL_LANGUAGE"/>Voulez-vous la traduire ?</translation>
++<translation id="563969276220951735">Saisie automatique des formulaires</translation>
++<translation id="6870130893560916279">Clavier ukrainien</translation>
++<translation id="8629974950076222828">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
++<translation id="3126026824346185272">Ctrl</translation>
++<translation id="4745438305783437565"><ph name="NUMBER_FEW"/> minutes</translation>
++<translation id="2649911884196340328">Le certificat de sécurité du serveur contient des erreurs !</translation>
++<translation id="6666647326143344290">avec votre compte Google</translation>
++<translation id="3828029223314399057">Rechercher dans les favoris</translation>
++<translation id="4885705234041587624">MSCHAPv2</translation>
++<translation id="5614190747811328134">Avertissement utilisateur</translation>
++<translation id="8906421963862390172">&amp;Options du vérificateur d'orthographe</translation>
++<translation id="9046895021617826162">Échec de la connexion</translation>
++<translation id="1492188167929010410">Identifiant de l'erreur <ph name="CRASH_ID"/></translation>
++<translation id="1963692530539281474"><ph name="NUMBER_DEFAULT"/> jours restants</translation>
++<translation id="4470270245053809099">Émis par : <ph name="NAME"/></translation>
++<translation id="5365539031341696497">Mode de saisie du thaï (clavier Kesmanee)</translation>
++<translation id="2403091441537561402">Passerelle :</translation>
++<translation id="6337234675334993532">Chiffrement</translation>
++<translation id="668171684555832681">Autre...</translation>
++<translation id="1932098463447129402">Pas avant le</translation>
++<translation id="7845920762538502375"><ph name="PRODUCT_NAME"/> n'a pas pu synchroniser vos données, car la connexion avec le serveur de synchronisation n'a pas pu être établie. Nouvel essai...</translation>
++<translation id="2192664328428693215">Me demander lorsqu'un site souhaite afficher des notifications sur le Bureau (recommandé)</translation>
++<translation id="6708242697268981054">Source :</translation>
++<translation id="4786993863723020412">Erreur de lecture du cache</translation>
++<translation id="6630452975878488444">Raccourci de sélection</translation>
++<translation id="8709969075297564489">Vérifier la révocation du certificat serveur</translation>
++<translation id="8698171900303917290">Vous rencontrez des problèmes lors de l'installation ?</translation>
++<translation id="830868413617744215">Bêta</translation>
++<translation id="5925147183566400388">Pointeur de la déclaration CPS (Certification Practice Statement)</translation>
++<translation id="1497270430858433901">Le <ph name="DATE"/>, vous avez reçu <ph name="DATA_AMOUNT"/> à utiliser librement.</translation>
++<translation id="8150167929304790980">Nom complet</translation>
++<translation id="636850387210749493">Inscription d'entreprise</translation>
++<translation id="1947424002851288782">Clavier allemand</translation>
++<translation id="932508678520956232">Impossible de lancer l'impression.</translation>
++<translation id="4861833787540810454">&amp;Lire</translation>
++<translation id="2552545117464357659">Récent</translation>
++<translation id="7269802741830436641">Cette page Web présente une boucle de redirection.</translation>
++<translation id="4180788401304023883">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; émis par l'autorité de certification ?</translation>
++<translation id="5869522115854928033">Mots de passe enregistrés</translation>
++<translation id="2089090684895656482">Moins</translation>
++<translation id="1709220265083931213">Options avancées</translation>
++<translation id="5748266869826978907">Vérifiez vos paramètres DNS. Contactez votre administrateur réseau si vous n'êtes pas sûr de vous.</translation>
++<translation id="4771973620359291008">Une erreur inconnue s'est produite.</translation>
++<translation id="5509914365760201064">Émetteur : <ph name="CERTIFICATE_AUTHORITY"/></translation>
++<translation id="7073385929680664879">Passer d'un mode de saisie à l'autre</translation>
++<translation id="6898699227549475383">Organisation (O)</translation>
++<translation id="4333854382783149454">PKCS #1 SHA-1 avec chiffrement RSA</translation>
++<translation id="762904068808419792">Entrez la requête de recherche ici.</translation>
++<translation id="8615618338313291042">Application en mode navigation privée : <ph name="APP_NAME"/></translation>
++<translation id="978146274692397928">La largeur de ponctuation initiale est Complète</translation>
++<translation id="8959027566438633317">Installer <ph name="EXTENSION_NAME"/> ?</translation>
++<translation id="8155798677707647270">Installation d'une nouvelle version...</translation>
++<translation id="6886871292305414135">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
++<translation id="1639192739400715787">Pour accéder aux paramètres de sécurité, saisissez le code PIN de la carte SIM.</translation>
++<translation id="7961015016161918242">Jamais</translation>
++<translation id="3950924596163729246">Impossible d'accéder au réseau.</translation>
++<translation id="2835170189407361413">Effacer le formulaire</translation>
++<translation id="4631110328717267096">Échec de la mise à jour du système</translation>
++<translation id="3695919544155087829">Saisissez le mot de passe utilisé pour chiffrer ce fichier de certificat.</translation>
++<translation id="2230051135190148440">CHAP</translation>
++<translation id="6308937455967653460">Enregistrer le lie&amp;n sous...</translation>
++<translation id="5421136146218899937">Effacer les données de navigation...</translation>
++<translation id="5783059781478674569">Options de reconnaissance vocale</translation>
++<translation id="5441100684135434593">Réseau câblé</translation>
++<translation id="3285322247471302225">Nouvel ongle&amp;t</translation>
++<translation id="3943582379552582368">R&amp;etour</translation>
++<translation id="7607002721634913082">Téléchargement suspendu</translation>
++<translation id="480990236307250886">Ouvrir la page d'accueil</translation>
++<translation id="8286036467436129157">Connexion</translation>
++<translation id="5999940714422617743">L'installation de <ph name="EXTENSION_NAME"/> est terminée.</translation>
++<translation id="1122198203221319518">&amp;Outils</translation>
++<translation id="5757539081890243754">Page d'accueil</translation>
++<translation id="2760009672169282879">Clavier phonétique bulgare</translation>
++<translation id="6608140561353073361">Cookies et données de site...</translation>
++<translation id="8007030362289124303">Batterie faible</translation>
++<translation id="4513946894732546136">Commentaires</translation>
++<translation id="1135328998467923690">Package incorrect : &quot;<ph name="ERROR_CODE"/>&quot;.</translation>
++<translation id="5906719743126878045"><ph name="NUMBER_TWO"/> heures restantes</translation>
++<translation id="1753682364559456262">Configurer les paramètres de blocage des images...</translation>
++<translation id="6550675742724504774">Options</translation>
++<translation id="8959208747503200525"><ph name="NUMBER_TWO"/> hours ago</translation>
++<translation id="431076611119798497">&amp;Détails</translation>
++<translation id="737801893573836157">Masquer la barre de titre du système et utiliser les bordures</translation>
++<translation id="5352235189388345738">Elle peut accéder aux éléments suivants :</translation>
++<translation id="5040262127954254034">Confidentialité</translation>
++<translation id="7666868073052500132">Objets : <ph name="USAGES"/></translation>
++<translation id="6985345720668445131">Paramètres d'entrée du japonais</translation>
++<translation id="3258281577757096226">Sebeol-sik Final</translation>
++<translation id="6906268095242253962">Veuillez vous connecter à Internet pour continuer.</translation>
++<translation id="1908748899139377733">Afficher les &amp;infos sur le cadre</translation>
++<translation id="803771048473350947">Fichier</translation>
++<translation id="6206311232642889873">Cop&amp;ier l'image</translation>
++<translation id="5158983316805876233">Utiliser le même proxy pour tous les protocoles</translation>
++<translation id="7108338896283013870">Masquer</translation>
++<translation id="3366404380928138336">Requête de protocole externe</translation>
++<translation id="5300589172476337783">Afficher</translation>
++<translation id="3160041952246459240">Certains de vos certificats enregistrés identifient ces serveurs :</translation>
++<translation id="566920818739465183">Vous avez visité ce site pour la première fois le <ph name="VISIT_DATE"/>.</translation>
++<translation id="2961695502793809356">Cliquer pour avancer, maintenir pour voir l'historique</translation>
++<translation id="4092878864607680421">La dernière version de l'application &quot;<ph name="APP_NAME"/>&quot; requiert d'autres autorisations. Elle a donc été désactivée.</translation>
++<translation id="8421864404045570940"><ph name="NUMBER_DEFAULT"/> secondes</translation>
++<translation id="5828228029189342317">Vous avez choisi d'ouvrir automatiquement certains types de fichiers après leur téléchargement.</translation>
++<translation id="1416836038590872660">EAP-MD5</translation>
++<translation id="176587472219019965">&amp;Nouvelle fenêtre</translation>
++<translation id="2788135150614412178">+</translation>
++<translation id="4055738107007928968">Vous avez essayé d'accéder au site <ph name="DOMAIN"/>, mais le serveur a présenté un certificat signé avec un algorithme de signature faible. Il se peut que les informations d'identification fournies par le serveur aient été falsifiées. Le serveur n'est peut-être pas celui auquel vous souhaitez accéder (il peut s'agir d'une tentative de piratage). Nous nous déconseillons vivement de continuer.</translation>
++<translation id="5308689395849655368">L'envoi de rapports d'erreur est désactivé.</translation>
++<translation id="8372369524088641025">Clé WEP incorrecte</translation>
++<translation id="8689341121182997459">Date d'expiration :</translation>
++<translation id="899403249577094719">URL de base du certificat Netscape</translation>
++<translation id="2737363922397526254">Réduire...</translation>
++<translation id="4880827082731008257">Rechercher dans l'historique</translation>
++<translation id="8661290697478713397">Ouvrir le lien dans la fenêtre de navi&amp;gation privée</translation>
++<translation id="4197700912384709145"><ph name="NUMBER_ZERO"/> secondes</translation>
++<translation id="7454780465968211330">Historique avancé pour le champ polyvalent</translation>
++<translation id="2158448795143567596">Active l'utilisation de graphismes 3D dans les éléments canvas via l'API WebGL.</translation>
++<translation id="1702534956030472451">Occident</translation>
++<translation id="6636709850131805001">État non reconnu</translation>
++<translation id="6095984072944024315">−</translation>
++<translation id="9141716082071217089">Impossible de vérifier si le certificat du serveur a été révoqué.</translation>
++<translation id="4304224509867189079">Se connecter</translation>
++<translation id="5332624210073556029">Fuseau horaire :</translation>
++<translation id="4799797264838369263">Cette option est soumise à une stratégie d'entreprise. Contactez votre administrateur pour plus d'informations.</translation>
++<translation id="4492190037599258964">Résultats de recherche pour &quot;<ph name="SEARCH_STRING"/>&quot;</translation>
++<translation id="3573179567135747900">Revenir à &quot;<ph name="FROM_LOCALE"/>&quot; (redémarrage requis)</translation>
++<translation id="2238123906478057869"><ph name="PRODUCT_NAME"/> va exécuter les tâches suivantes :</translation>
++<translation id="4042471398575101546">Ajouter la page</translation>
++<translation id="8848709220963126773">Changement de mode via la touche Maj</translation>
++<translation id="4871865824885782245">Options de date et d'heure...</translation>
++<translation id="8828933418460119530">Nom DNS</translation>
++<translation id="988159990683914416">Build de développement</translation>
++<translation id="8026354464835030469"><ph name="BURNT_AMOUNT"/> sur ...</translation>
++<translation id="4114470632216071239">Verrouiller la carte SIM (code PIN obligatoire pour utiliser les données mobiles)</translation>
++<translation id="2183426022964444701">Sélectionnez le répertoire racine de l'extension.</translation>
++<translation id="2517143724531502372">Les cookies de <ph name="DOMAIN"/> sont autorisés uniquement pour cette session.</translation>
++<translation id="9018524897810991865">Confirmer les préférences de synchronisation</translation>
++<translation id="4719905780348837473">RSN</translation>
++<translation id="5212108862377457573">Ajuster la conversion en fonction de l'entrée précédente</translation>
++<translation id="5398353896536222911">Afficher le panneau de la &amp;vérification orthographique</translation>
++<translation id="5811533512835101223">(Revenir à la capture d'écran d'origine)</translation>
++<translation id="5131817835990480221">Mettre à jour &amp;<ph name="PRODUCT_NAME"/></translation>
++<translation id="939519157834106403">SSID</translation>
++<translation id="3705722231355495246">-</translation>
++<translation id="2635102990349508383">Les informations de connexion au compte n'ont pas encore été saisies.</translation>
++<translation id="6902055721023340732">URL de configuration automatique</translation>
++<translation id="4268574628540273656">URL :</translation>
++<translation id="7481312909269577407">Avancer</translation>
++<translation id="3759876923365568382"><ph name="NUMBER_FEW"/> jours restants</translation>
++<translation id="295228163843771014">Vous avez choisi de ne pas synchroniser les mots de passe. Vous pouvez à tout moment modifier vos paramètres de synchronisation, si vous changez d'avis.</translation>
++<translation id="5972826969634861500">Lancer <ph name="PRODUCT_NAME"/></translation>
++<translation id="7828702903116529889"><ph name="PRODUCT_NAME"/>
++ ne parvient pas à accéder au réseau.
++ <ph name="LINE_BREAK"/>
++ Il est possible que votre pare-feu ou votre antivirus considère
++ <ph name="PRODUCT_NAME"/>
++ comme un intrus dans votre ordinateur et qu'il bloque ses tentatives de connexion à Internet.</translation>
++<translation id="878069093594050299">Ce certificat a été vérifié pour les utilisations suivantes :</translation>
++<translation id="5852112051279473187">Petit problème ! Une erreur est survenue lors de l'inscription de ce périphérique. Veuillez réessayer ou contacter votre représentant de l'assistance technique.</translation>
++<translation id="1664314758578115406">Ajouter aux favoris</translation>
++<translation id="7088418943933034707">Gérer les certificats...</translation>
++<translation id="8482183012530311851">Analyse du périphérique...</translation>
++<translation id="3127589841327267804">PYJJ</translation>
++<translation id="8808478386290700967">Web Store</translation>
++<translation id="1732215134274276513">Annuler l'épinglage des onglets</translation>
++<translation id="4084682180776658562">Favori</translation>
++<translation id="8859057652521303089">Sélectionnez votre langue :</translation>
++<translation id="3030138564564344289">Réessayer le téléchargement</translation>
++<translation id="8525552230188318924">Configurer la synchronisation des mots de passe</translation>
++<translation id="4381091992796011497">Nom d'utilisateur :</translation>
++<translation id="5830720307094128296">Enregistrer la p&amp;age sous...</translation>
++<translation id="8114439576766120195">Vos données sur tous les sites Web</translation>
++<translation id="4668954208278016290">Un problème est survenu lors de l'extraction de l'image sur l'ordinateur.</translation>
++<translation id="5822838715583768518">Lancer l'application</translation>
++<translation id="3942974664341190312">Dubeol-sik</translation>
++<translation id="8477241577829954800">Remplacé</translation>
++<translation id="6735304988756581115">Afficher les cookies et autres données de site...</translation>
++<translation id="3048564749795856202">Si vous pensez avoir cerné les risques, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
++<translation id="2433507940547922241">Apparence</translation>
++<translation id="839072384475670817">Créer des raccourci&amp;s vers des applications...</translation>
++<translation id="1478632774608054702">Exécuter le flash PPAPI dans le processus du moteur de rendu</translation>
++<translation id="6756161853376828318">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
++<translation id="9112614144067920641">Veuillez choisir un nouveau code PIN.</translation>
++<translation id="2061855250933714566"><ph name="ENCODING_CATEGORY"/> (<ph name="ENCODING_NAME"/>)</translation>
++<translation id="7138678301420049075">Autre</translation>
++<translation id="9147392381910171771">&amp;Options</translation>
++<translation id="1803557475693955505">Impossible de charger la page d'arrière-plan &quot;<ph name="BACKGROUND_PAGE"/>&quot;.</translation>
++<translation id="5818334088068591797">À quel niveau rencontrez-vous des problèmes ? (Champ obligatoire)</translation>
++<translation id="6264485186158353794">Retour à la sécurité</translation>
++<translation id="5130080518784460891">Eten</translation>
++<translation id="5847724078457510387">Ce site répertorie tous ses certificats valides dans le système DNS. Un certificat non répertorié a cependant été utilisé par le serveur.</translation>
++<translation id="1394853081832053657">Options de reconnaissance vocale</translation>
++<translation id="5037676449506322593">Tout sélectionner</translation>
++<translation id="2785530881066938471">Impossible de charger le fichier &quot;<ph name="RELATIVE_PATH"/>&quot; pour le script de contenu, car ce fichier n'est pas codé en UTF-8.</translation>
++<translation id="3807747707162121253">&amp;Annuler</translation>
++<translation id="3306897190788753224">Désactiver temporairement la personnalisation des conversions, les suggestions basées sur l'historique et le dictionnaire utilisateur</translation>
++<translation id="2574102660421949343">Les cookies de <ph name="DOMAIN"/> sont autorisés.</translation>
++<translation id="77999321721642562">Au fil du temps, la zone ci-dessous affichera les huit sites que vous avez le plus visités.</translation>
++<translation id="1503894213707460512">Le plug-in <ph name="PLUGIN_NAME"/> a besoin de votre autorisation pour s'exécuter.</translation>
++<translation id="471800408830181311">Échec de création de clé privée</translation>
++<translation id="1273291576878293349">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
++<translation id="1639058970766796751">Placer dans la file d'attente</translation>
++<translation id="1177437665183591855">Erreur de certificat serveur inconnue</translation>
++<translation id="8467473010914675605">Mode de saisie du coréen</translation>
++<translation id="3819800052061700452">&amp;Plein écran</translation>
++<translation id="5419540894229653647"><ph name="ERROR_DESCRIPTION_TEXT"/>
++ <ph name="LINE_BREAK"/>
++ Vous pouvez essayer de diagnostiquer le problème en procédant comme suit :
++ <ph name="LINE_BREAK"/>
++ <ph name="PLATFORM_TEXT"/></translation>
++<translation id="3533943170037501541">Bienvenue sur votre page d'accueil !</translation>
++<translation id="2333340435262918287">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
++<translation id="5906065664303289925">Adresse du matériel :</translation>
++<translation id="3178000186192127858">Lecture seule</translation>
++<translation id="2187895286714876935">Erreur d'importation du certificat serveur</translation>
++<translation id="5460896875189097758">Données stockées localement</translation>
++<translation id="4618990963915449444">Tous les fichiers de <ph name="DEVICE_NAME"/> vont être effacés.</translation>
++<translation id="614998064310228828">Modèle du périphérique :</translation>
++<translation id="1581962803218266616">Afficher dans le Finder</translation>
++<translation id="6096326118418049043">Nom X.500</translation>
++<translation id="6086259540486894113">Vous devez sélectionner au moins un type de données à synchroniser.</translation>
++<translation id="923467487918828349">Tout afficher</translation>
++<translation id="5101042277149003567">Ouvrir tous les favoris</translation>
++<translation id="4298972503445160211">Clavier danois</translation>
++<translation id="6621440228032089700">Cette fonctionnalité permet de réaliser un rendu hors écran de la texture, au lieu d'un affichage direct.</translation>
++<translation id="3488065109653206955">Partiellement activé</translation>
++<translation id="1481244281142949601">Votre système Sandbox est correctement configuré.</translation>
++<translation id="4849517651082200438">Ne pas installer</translation>
++<translation id="8602882075393902833">Activer la recherche instantanée pour accélérer la recherche et la navigation</translation>
++<translation id="6349678711452810642">Utiliser par défaut</translation>
++<translation id="6263284346895336537">Non essentielle</translation>
++<translation id="6409731863280057959">Fenêtres pop-up</translation>
++<translation id="3459774175445953971">Dernière modification :</translation>
++<translation id="73289266812733869">Désélectionné</translation>
++<translation id="3435738964857648380">Sécurité</translation>
++<translation id="9112987648460918699">Rechercher...</translation>
++<translation id="2231233239095101917">Le script de la page utilisait trop de mémoire. Rafraîchissez la page pour réactiver le script.</translation>
++<translation id="870805141700401153">Signature du code individuel Microsoft</translation>
++<translation id="5119173345047096771">Mozilla Firefox</translation>
++<translation id="9020278534503090146">Page Web inaccessible</translation>
++<translation id="4768698601728450387">Recadrer l'image</translation>
++<translation id="6245028464673554252">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, le téléchargement sera annulé.</translation>
++<translation id="3943857333388298514">Coller</translation>
++<translation id="385051799172605136">Retour</translation>
++<translation id="1742300158964248589">Impossible de graver l'image.</translation>
++<translation id="2670965183549957348">Mode de saisie du Chewing</translation>
++<translation id="5095208057601539847">Province</translation>
++<translation id="4085298594534903246">JavaScript a été bloqué sur cette page.</translation>
++<translation id="5630492933376732170">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome OS
++ joint à votre envoi un journal des événements système de
++ votre périphérique. Ces informations nous permettent de diagnostiquer les
++ problèmes, de comprendre comment vous interagissez avec votre
++ périphérique et d'améliorer les performances de ce dernier. Les
++ informations personnelles fournies sciemment dans vos commentaires ou
++ involontairement dans les journaux système et la capture d'écran sont
++ protégées conformément à nos <ph name="BEGIN_LINK"/>Règles de confidentialité<ph name="END_LINK"/>.
++ Si vous ne souhaitez pas envoyer de journaux système, décochez la case
++ &quot;Inclure les informations système&quot;.</translation>
++<translation id="4341977339441987045">Interdire à tous les sites de stocker des données</translation>
++<translation id="806812017500012252">Trier par nom</translation>
++<translation id="3781751432212184938">Afficher un aperçu des onglets...</translation>
++<translation id="2960316970329790041">Annuler l'importation</translation>
++<translation id="3835522725882634757">Ce serveur envoie des données que <ph name="PRODUCT_NAME"/> ne comprend pas. Veuillez <ph name="BEGIN_LINK"/>signaler un bug<ph name="END_LINK"/> et inclure la <ph name="BEGIN2_LINK"/>liste des raw<ph name="END2_LINK"/>.</translation>
++<translation id="5361734574074701223">Calcul de la durée restante</translation>
++<translation id="6937152069980083337">Mode de saisie Google du japonais (pour clavier américain)</translation>
++<translation id="1731911755844941020">Envoi de la requête...</translation>
++<translation id="8371695176452482769">Parlez maintenant</translation>
++<translation id="2988488679308982380">Impossible d'installer le package : &quot;<ph name="ERROR_CODE"/>&quot;</translation>
++<translation id="2904079386864173492">Modèle :</translation>
++<translation id="3447644283769633681">Bloquer tous les cookies tiers</translation>
++<translation id="8917047707340793412">Remplacer par <ph name="ENGINE_NAME"/></translation>
++<translation id="6129953537138746214">Espace</translation>
++<translation id="3704331259350077894">Arrêt du fonctionnement</translation>
++<translation id="5801568494490449797">Préférences</translation>
++<translation id="1038842779957582377">Nom inconnu</translation>
++<translation id="5327248766486351172">Nom</translation>
++<translation id="5553784454066145694">Choisir un nouveau code PIN</translation>
++<translation id="8989148748219918422"><ph name="ORGANIZATION"/> [<ph name="COUNTRY"/>]</translation>
++<translation id="4664482161435122549">Erreur d'exportation de fichier PKCS #12</translation>
++<translation id="2445081178310039857">Le répertoire racine de l'extension doit être indiqué.</translation>
++<translation id="8251578425305135684">Miniature supprimée</translation>
++<translation id="6163522313638838258">Tout développer...</translation>
++<translation id="3037605927509011580">Aie aie aie</translation>
++<translation id="5803531701633845775">Choisir les expressions en arrière-plan, sans déplacer le pointeur</translation>
++<translation id="1918141783557917887">Plu&amp;s petit</translation>
++<translation id="6996550240668667907">Afficher le clavier en superposition</translation>
++<translation id="4065006016613364460">C&amp;opier l'URL de l'image</translation>
++<translation id="6965382102122355670">OK</translation>
++<translation id="8000066093800657092">Aucun réseau détecté</translation>
++<translation id="4481249487722541506">Charger l'extension non empaquetée...</translation>
++<translation id="8180239481735238521">page</translation>
++<translation id="8321738493186308836">Active l'interface utilisateur et le code de support pour le processus du service de communication à distance, de même que le plug-in client. Avertissement : ce service n'est actuellement disponible que pour les tests de développeurs. Si vous ne faites pas partie de l'équipe de développement et ne figurez pas sur la liste blanche, aucun élément de l'interface utilisateur activée ne fonctionnera.</translation>
++<translation id="2963783323012015985">Clavier turc</translation>
++<translation id="2149973817440762519">Modifier le favori</translation>
++<translation id="5431318178759467895">Couleur</translation>
++<translation id="7064842770504520784">Personnaliser les paramètres de synchronisation...</translation>
++<translation id="2784407158394623927">Activation de votre service Internet mobile</translation>
++<translation id="3679848754951088761"><ph name="SOURCE_ORIGIN"/></translation>
++<translation id="6920989436227028121">Ouvrir dans un onglet standard</translation>
++<translation id="4057041477816018958"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/></translation>
++<translation id="2050339315714019657">Portrait</translation>
++<translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation>
++<translation id="6139139147415955203">Active un service en arrière-plan qui connecte le service <ph name="CLOUD_PRINT_NAME"/> aux éventuelles imprimantes installées sur cet ordinateur. Une fois ce labo activé, vous pouvez lancer <ph name="CLOUD_PRINT_NAME"/> en vous connectant à votre compte Google via Options/Préférences dans la section Options avancées.</translation>
++<translation id="5112577000029535889">Outils de &amp;développement</translation>
++<translation id="2301382460326681002">Le répertoire racine de l'extension est incorrect.</translation>
++<translation id="7839192898639727867">ID de clé de l'objet du certificat</translation>
++<translation id="4759238208242260848">Téléchargements</translation>
++<translation id="2879560882721503072">Le stockage du certificat client généré par <ph name="ISSUER"/> a réussi.</translation>
++<translation id="1275718070701477396">Sélectionnée</translation>
++<translation id="1178581264944972037">Suspendre</translation>
++<translation id="6492313032770352219">Taille sur le disque :</translation>
++<translation id="5233231016133573565">ID du processus</translation>
++<translation id="5941711191222866238">Réduire</translation>
++<translation id="4121428309786185360">Expire le</translation>
++<translation id="2049137146490122801">Votre administrateur a désactivé l'accès aux fichiers locaux sur votre ordinateur.</translation>
++<translation id="1146498888431277930">Erreur de connexion SSL</translation>
++<translation id="8041089156583427627">Envoyer</translation>
++<translation id="6394627529324717982">Virgule</translation>
++<translation id="253434972992662860">&amp;Pause</translation>
++<translation id="335985608243443814">Parcourir...</translation>
++<translation id="7802488492289385605">Mode de saisie Google du japonais (pour clavier Dvorak américain)</translation>
++<translation id="7452120598248906474">Police à largeur fixe</translation>
++<translation id="3129687551880844787">Stockage de session</translation>
++<translation id="7427348830195639090">Page en arrière-plan : <ph name="BACKGROUND_PAGE_URL"/></translation>
++<translation id="5898154795085152510">Le serveur a renvoyé un certificat client incorrect. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
++<translation id="2704184184447774363">Signature de document Microsoft</translation>
++<translation id="5677928146339483299">Bloqué</translation>
++<translation id="1474842329983231719">Gérer les paramètres d'impression...</translation>
++<translation id="2455981314101692989">Cette page Web a désactivé la saisie automatique dans ce formulaire.</translation>
++<translation id="1646136617204068573">Clavier hongrois</translation>
++<translation id="5988840637546770870">Les versions en développement permettent de tester de nouvelles idées, mais elles peuvent s'avérer très instables. Nous vous prions d'agir avec précaution.</translation>
++<translation id="3569713929051927529">Ajouter un dossier...</translation>
++<translation id="4032664149172368180">Mode de saisie du japonais (pour clavier Dvorak américain)</translation>
++<translation id="3748706263662799310">Signaler un bug</translation>
++<translation id="7167486101654761064">&amp;Toujours ouvrir les fichiers de ce type</translation>
++<translation id="4283623729247862189">Disque optique</translation>
++<translation id="5826507051599432481">Nom commun</translation>
++<translation id="8914326144705007149">Très grande</translation>
++<translation id="4215444178533108414">Modification terminée</translation>
++<translation id="5154702632169343078">Objet</translation>
++<translation id="2273562597641264981">Opérateur :</translation>
++<translation id="122082903575839559">Algorithme de signature du certificat</translation>
++<translation id="2181257377760181418">Cette fonctionnalité permet d'afficher un onglet d'aperçu avant de lancer une impression.</translation>
++<translation id="7240120331469437312">Autre nom de l'objet du certificat</translation>
++<translation id="6900113680982781280">Activer la saisie automatique pour remplir les formulaires Web d'un simple clic</translation>
++<translation id="1131850611586448366">Le site Web à l'adresse <ph name="HOST_NAME"/> a été signalé comme étant un site de phishing. Ces sites tentent d'amener les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
++<translation id="5413218268059792983">Rechercher directement sur <ph name="SEARCH_ENGINE"/></translation>
++<translation id="1161575384898972166">Connectez-vous à <ph name="TOKEN_NAME"/> pour exporter le certificat client.</translation>
++<translation id="1718559768876751602">Créer un compte Google maintenant</translation>
++<translation id="1884319566525838835">État Sandbox</translation>
++<translation id="2770465223704140727">Retirer de la liste</translation>
++<translation id="3590587280253938212">rapide</translation>
++<translation id="6053401458108962351">&amp;Effacer les données de navigation…</translation>
++<translation id="2339641773402824483">Vérification des mises à jour...</translation>
++<translation id="9111742992492686570">Télécharger les mises à jour de sécurité essentielles</translation>
++<translation id="8636666366616799973">Package incorrect. Détails : &quot;<ph name="ERROR_MESSAGE"/>&quot;.</translation>
++<translation id="2045969484888636535">Continuer à bloquer les cookies</translation>
++<translation id="7353601530677266744">Ligne de commande</translation>
++<translation id="2766006623206032690">Coller l'URL et y a&amp;ccéder</translation>
++<translation id="4394049700291259645">Désactiver</translation>
++<translation id="969892804517981540">Build officiel</translation>
++<translation id="445923051607553918">Se connecter à un réseau Wi-Fi</translation>
++<translation id="100242374795662595">Périphérique inconnu</translation>
++<translation id="9087725134750123268">Supprimer les cookies et autres données de site</translation>
++<translation id="5050255233730056751">URL saisies</translation>
++<translation id="3349155901412833452">Utiliser les touches , et . pour paginer une liste d'entrées</translation>
++<translation id="6872947427305732831">Vider la mémoire</translation>
++<translation id="2742870351467570537">Supprimer les éléments sélectionnés</translation>
++<translation id="7561196759112975576">Toujours</translation>
++<translation id="2116673936380190819">de moins d'une heure</translation>
++<translation id="5765491088802881382">Aucun réseau n'est disponible.</translation>
++<translation id="1971538228422220140">Supprimer les cookies et autres données de site et de plug-in</translation>
++<translation id="883487340845134897">Intervertir les touches Rechercher et Ctrl gauche</translation>
++<translation id="5692957461404855190">Faites glisser trois doigts sur la surface de votre trackpad pour afficher un aperçu de tous vos onglets. Cliquez sur une vignette pour la sélectionner. Idéal en mode plein écran.</translation>
++<translation id="1375215959205954975">Nouveau ! Configurer la synchronisation des mots de passe</translation>
++<translation id="5183088099396036950">Échec de la tentative de connexion au serveur</translation>
++<translation id="4469842253116033348">Désactiver les notifications de <ph name="SITE"/></translation>
++<translation id="7999229196265990314">Les fichiers suivants ont été créés :
++
++Extension : <ph name="EXTENSION_FILE"/>
++Fichier de clé : <ph name="KEY_FILE"/>
++
++Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la création de nouvelles versions de l'extension.</translation>
++<translation id="1846078536247420691">&amp;Oui</translation>
++<translation id="3036649622769666520">Ouvrir les fichiers</translation>
++<translation id="2966459079597787514">Clavier suédois</translation>
++<translation id="7685049629764448582">Mémoire JavaScript </translation>
++<translation id="6398765197997659313">Quitter le mode plein écran</translation>
++<translation id="6059652578941944813">Hiérarchie des certificats</translation>
++<translation id="4886690096315032939">Afficher l'onglet existant si l'URL associée est demandée dans un autre</translation>
++<translation id="5729712731028706266">&amp;Afficher</translation>
++<translation id="774576312655125744">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et sur <ph name="NUMBER_OF_OTHER_WEBSITES"/> autres sites Web</translation>
++<translation id="6359806961507272919">SMS de <ph name="PHONE_NUMBER"/></translation>
++<translation id="4508765956121923607">Afficher la s&amp;ource</translation>
++<translation id="5975083100439434680">Zoom arrière</translation>
++<translation id="8080048886850452639">C&amp;opier l'URL du fichier audio</translation>
++<translation id="2817109084437064140">Importer et associer au périphérique...</translation>
++<translation id="3331321258768829690">(<ph name="UTCOFFSET"/>) <ph name="LONGTZNAME"/> (<ph name="EXEMPLARCITY"/>)</translation>
++<translation id="619398760000422129">Plug-ins (par ex. Adobe Flash Player, QuickTime, etc.)</translation>
++<translation id="5849869942539715694">Empaqueter l'extension...</translation>
++<translation id="7339785458027436441">Vérifier l'orthographe lors de la frappe</translation>
++<translation id="8308427013383895095">Échec de la traduction en raison d'un problème de connexion réseau</translation>
++<translation id="1801298019027379214">Code PIN incorrect. Veuillez réessayer. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
++<translation id="1384721974622518101">Vous pouvez effectuer une recherche directement à partir du champ ci-dessus.</translation>
++<translation id="992543612453727859">Ajouter les expressions au premier plan</translation>
++<translation id="3857773447683694438">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</translation>
++<translation id="1244147615850840081">Opérateur</translation>
++<translation id="8203365863660628138">Confirmer l'installation</translation>
++<translation id="406259880812417922">(Mot clé : <ph name="KEYWORD"/>)</translation>
++<translation id="309628958563171656">Sensibilité :</translation>
++</translationbundle>
+diff --git a/tools/grit/grit/testdata/generated_resources_iw.xtb b/tools/grit/grit/testdata/generated_resources_iw.xtb
+new file mode 100644
+index 0000000000..86b55334c0
+--- /dev/null
++++ b/tools/grit/grit/testdata/generated_resources_iw.xtb
+@@ -0,0 +1,4 @@
++<?xml version="1.0" ?>
++<!DOCTYPE translationbundle>
++<translationbundle lang="iw">
++</translationbundle>
+diff --git a/tools/grit/grit/testdata/generated_resources_no.xtb b/tools/grit/grit/testdata/generated_resources_no.xtb
+new file mode 100644
+index 0000000000..913638ba4e
+--- /dev/null
++++ b/tools/grit/grit/testdata/generated_resources_no.xtb
+@@ -0,0 +1,4 @@
++<?xml version="1.0" ?>
++<!DOCTYPE translationbundle>
++<translationbundle lang="no">
++</translationbundle>
+diff --git a/tools/grit/grit/testdata/grit_part.grdp b/tools/grit/grit/testdata/grit_part.grdp
+new file mode 100644
+index 0000000000..c8e9d92692
+--- /dev/null
++++ b/tools/grit/grit/testdata/grit_part.grdp
+@@ -0,0 +1,5 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grit-part>
++ <!-- Important for test purposes that this file not exist. -->
++ <structure type="chrome_scaled_image" name="IDR_DOES_NOT_EXIST" file="does-not-exist.png" />
++</grit-part>
+diff --git a/tools/grit/grit/testdata/header.html b/tools/grit/grit/testdata/header.html
+new file mode 100644
+index 0000000000..8e9d10ec50
+--- /dev/null
++++ b/tools/grit/grit/testdata/header.html
+@@ -0,0 +1,39 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>[$~TITLE~$]</title>
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++[EXTRA_META]
++<style>
++BODY,TD,DIV,.P,A { FONT-FAMILY: arial,sans-serif}
++DIV,TD { COLOR: #000}
++.f { COLOR: #6f6f6f}
++.fl:link { COLOR: #6f6f6f}
++A:link, .w, A.w:link, .w A:link { COLOR: #00c}
++A:visited { COLOR: #551a8b}
++.fl:visited { COLOR: #551a8b}
++A:active, .fl:active { COLOR: #f00}
++.h { COLOR: #3399CC}
++.i { COLOR: #a90a08}
++.i:link { COLOR: #a90a08}
++.a, .a:link, .a:visited { COLOR: #008000}
++DIV.n { MARGIN-TOP: 1ex}
++.n A { FONT-SIZE: 10pt; COLOR: #000}
++.n .i { FONT-WEIGHT: bold; FONT-SIZE: 10pt}
++.q A:visited { COLOR: #00c}
++.q A:link { COLOR: #00c}
++.q A:active { COLOR: #00c}
++.q { COLOR: #00c}
++.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
++.ch { CURSOR: hand}
++.e { MARGIN-TOP: 0.75em; MARGIN-BOTTOM: 0.75em}
++.g { MARGIN-TOP: 1em; MARGIN-BOTTOM: 1em}
++.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
++.s { HEIGHT: 10px }
++.c:active { COLOR: #ff0000}
++.c:visited { COLOR: #551a8b}
++.c:link { COLOR: #7777cc}
++.c { COLOR: #7777cc }
++</style>
++</head>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/homepage.html b/tools/grit/grit/testdata/homepage.html
+new file mode 100644
+index 0000000000..cce4f2cf35
+--- /dev/null
++++ b/tools/grit/grit/testdata/homepage.html
+@@ -0,0 +1,37 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Google Desktop Search</title>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
++.q {COLOR: #0000cc}
++</style>
++<script>
++<!--
++function sf(){document.f.q.focus();}
++// -->
++</script>
++</head>
++<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
++<center>
++<TABLE cellSpacing=0 cellPadding=0 border=0>
++<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
++<FORM name=f method=GET action='[$~SEARCHURL~$]'>
++<TABLE cellSpacing=0 cellPadding=4 border=0>
++<tr>
++<TD class=q noWrap><FONT size=-1>
++[$~LINKS~$]
++</font></td>
++</tr></table>
++<table cellspacing=0 cellpadding=0>
++<tr vAlign=top>
++<td width=25%>&nbsp;</td>
++<td align=center><input maxlength=256 size=62 name=q value="[DISP_QUERY]"><br><input type=submit value="Search Desktop" name=btnG><INPUT type=submit value="Search the Web" name="redir" accesskey=w></td>
++<td align=left valign=top nowrap width=25%><font size=-2>&nbsp;&nbsp;<A href="[$~PREFERENCES~$]">Desktop&nbsp;Preferences</a></font></td>
++</tr></table></FORM>
++<p><FONT color=#224499><B>Search your own computer.</B></font></p>
++<span style='width:29em'>[$~MESSAGE~$]</span><br>
++<br><FONT size=-1>[$~SETHOMEPAGE~$][$~BOTTOMLINE~$]</font></p>
++<p><FONT size=-2>&copy;2005 Google - Searching [NUM_ITEMS] items</font></p></center></body></html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/hover.html b/tools/grit/grit/testdata/hover.html
+new file mode 100644
+index 0000000000..b8f9ce0200
+--- /dev/null
++++ b/tools/grit/grit/testdata/hover.html
+@@ -0,0 +1,177 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
++A:hover { COLOR: #ffffff }
++.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
++</style>
++
++<!-- menu experiment start -->
++
++<style>
++<!--
++.menu1 {
++cursor:default;
++position:absolute;
++left: 10;
++top: 0;
++text-align: left;
++font-family: Arial, Helvetica, sans-serif;
++font-size: 8pt;
++background-color: menu;
++visibility: hidden;
++padding-top: 2px;
++padding-bottom: 2px;
++border: 1 solid;
++border-color: #888888;
++z-index: 100;
++}
++.menuitems {
++padding-left: 5px;
++padding-right: 5px;
++}
++-->
++</style>
++<SCRIPT LANGUAGE="JavaScript1.2">
++<!--
++var menustyle = "menu1";
++
++function showmenu() {
++ // var rightedge = document.body.clientWidth-event.clientX;
++ // var bottomedge = document.body.clientHeight-event.clientY;
++ // if (rightedge < rcmenu.offsetWidth)
++ // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
++ // else
++ // rcmenu.style.left = document.body.scrollLeft + event.clientX;
++ // if (bottomedge < rcmenu.offsetHeight)
++ // rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
++ // else
++ // rcmenu.style.top = document.body.scrollTop + event.clientY;
++
++ rcmenu.style.visibility = "visible";
++ // rcmenu.style.zindex = 0;
++ // document.all('rcmenu').style.zindex = 20;
++ document.onkeydown=ck;
++ return false;
++}
++
++function hidemenu() {
++ rcmenu.style.visibility = "hidden";
++}
++
++function ck(e){
++ evt=document.all?window.event:e;
++ k=document.all?window.event.keyCode:e.keyCode;
++
++ if(k==27 /*<Esc>*/) {
++ hidemenu();
++ }
++}
++
++function menumouseover() {
++ if (event.srcElement.className == "menuitems") {
++ event.srcElement.style.backgroundColor = "highlight";
++ event.srcElement.style.color = "white";
++ }
++}
++
++function menumouseout() {
++ if (event.srcElement.className == "menuitems") {
++ event.srcElement.style.backgroundColor = "";
++ event.srcElement.style.color = "black";
++ window.status = "";
++ }
++}
++
++function menuselect() {
++ if (event.srcElement.className == "menuitems") {
++ if (event.srcElement.getAttribute("target") != null)
++ window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
++ else if (event.srcElement.url.length)
++ window.location = event.srcElement.url;
++ }
++}
++// -->
++</script>
++
++<!-- menu experiment end -->
++
++</head>
++<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0" border=0 style="border-width:0;" scroll=no>
++
++<!-- <br> -->
++
++<!-- menu experiment start -->
++
++<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
++<span class="menuitems" url="[$~SETDISP1~$]">Sidebar</span>
++<span class="menuitems" url="[$~SETDISP4~$]">Minibar</span>
++<span class="menuitems" url="[$~HIDE2~$]">Close</span>
++</div>
++
++<script language="JavaScript1.2">
++if (document.all && window.print) {
++ rcmenu.className = menustyle;
++ document.oncontextmenu = showmenu;
++ document.body.onclick = hidemenu;
++}
++</script>
++
++<!-- menu experiment end -->
++
++<script>
++function hide() {
++ return 1;
++ // return confirm("Are you sure you want to hide the minibar?\nYou can show it again in Google Desktop Search Preferences. ");
++}
++function clear() {
++ document.getElementById('q').value='';
++}
++</script>
++
++<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
++<tr><TD vAlign=top>
++
++<form method=get action="[$~SEARCHURL~$]" [$~SEARCH_TARGET~$] name=f1 ID="f1" onsubmit="window.setTimeout('clear()', 500)">
++<input type=hidden name=src value=3>
++<input type=hidden name=redir value='' ID="redir">
++
++<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
++
++<tr>
++<!-- border-top: #414a4f 0px solid; -->
++<!-- z-index:2; z-order:2; -->
++<TD vAlign=top>&nbsp;<INPUT name=q style="position:relative; height=19px;" class=border size=12>&nbsp;</td>
++
++<TD TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit();q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="logo.gif" align=middle></td>
++
++<TD width=2><IMG height=1 width=1></td>
++
++<TD TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="gfavicon.ico" align=middle></td></tr>
++</TBODY></table>
++</td>
++
++<TD width=5><IMG height=1 width=1></td>
++
++<TD vAlign=top>
++
++<TABLE cellSpacing=0 cellPadding=1 bgColor=#000099><TBODY>
++<tr><TD TABINDEX="4" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="location.href='[$~SETDISP1~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="down.gif"></td></tr></TBODY></table>
++
++</td>
++
++<TD width=1><IMG height=1 width=1></td>
++
++<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
++<tr><TD TABINDEX="5" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="if (hide())location.href='[$~HIDE2~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="close.gif"></td></tr></TBODY></table></td></tr></TBODY></table>
++
++</form>
++</body></html>
+diff --git a/tools/grit/grit/testdata/include_test.html b/tools/grit/grit/testdata/include_test.html
+new file mode 100644
+index 0000000000..e08f2e2e8a
+--- /dev/null
++++ b/tools/grit/grit/testdata/include_test.html
+@@ -0,0 +1,31 @@
++<include src="included_sample.html">
++<if expr="True">
++should be kept
++</if>
++in the middle...
++<if expr="False">
++should be removed
++</if>
++
++<if expr="False">
++should be removed
++ <if expr="True">
++ should be removed because outer expr is False
++ </if>
++should be removed
++</if>
++
++<if expr="True">
++ <if expr="True">
++ <if expr="True">
++ nested true should be kept
++ </if>
++ <if expr="False">
++ should be removed
++ </if>
++ </if>
++ <if expr="True">
++ silbing true should be kept
++ </if>
++</if>
++at the end...
+diff --git a/tools/grit/grit/testdata/included_sample.html b/tools/grit/grit/testdata/included_sample.html
+new file mode 100644
+index 0000000000..7150ffcbea
+--- /dev/null
++++ b/tools/grit/grit/testdata/included_sample.html
+@@ -0,0 +1 @@
++Hello Include!
+diff --git a/tools/grit/grit/testdata/indexing_speed.html b/tools/grit/grit/testdata/indexing_speed.html
+new file mode 100644
+index 0000000000..db1787b0e2
+--- /dev/null
++++ b/tools/grit/grit/testdata/indexing_speed.html
+@@ -0,0 +1,58 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Google Desktop Search Index Speed</title>
++<meta http-equiv=content-type content="text/html; charset=utf-8">
++<style>
++BODY {
++ MARGIN-LEFT: 3em; MARGIN-RIGHT: 3em; FONT-FAMILY: arial,sans-serif
++}
++</style>
++</head>
++<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff>
++<TABLE cellSpacing=2 cellPadding=0 width="100%" border=0>
++ <tr>
++ <TD vAlign=top width="1%"><A href="[$~HOMEPAGE~$]">
++ <IMG alt="Go to Google Desktop Search" src="/logo3.gif" border=0></A></td>
++ <td>&nbsp;</td>
++ <TD noWrap>
++ <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
++ <tr>
++ <TD bgColor=#3399CC><IMG height=1 alt="" width=1></td>
++ </tr>
++ </table>
++ <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
++ <tr>
++ <TD noWrap bgColor=#efefef><B>&nbsp;Index Speed</B></td>
++ <TD noWrap align=right bgColor=#efefef><FONT size=-1><A href="/customize.html">Index Speed
++ Help</A> | <A href="[$~ABOUT~$]"> About Google Desktop Search</A></font></td>
++ </tr></table></td></tr></table>
++<FONT size=-1>
++<p>
++To make your emails, files, and previously viewed web pages searchable, Google Desktop Search
++needs to index them. This indexing process is currently occuring in the background
++and your computer performance is minimally impacted.
++<p>
++You have the option of speeding up this process.
++<p><B><FONT color=#FF0000>Warning:</font></B> Speeding up indexing will cause your computer
++to become unusable for many minutes, depending on how many items need to be indexed. FAST INDEXING IS NOT
++RECOMMENDED.
++<BR>&nbsp;<BR>
++<FORM action="[$~SETINDEXSPEED~$]" method=GET>
++<input name=url value="[PREVPAGE]" type=hidden>
++<input type=radio name=FAST value="0" [FAST0-CHECKED] id=f0><label for=f0>Use background indexing (recommended)</label><br>
++<input type=radio name=FAST value="1" [FAST1-CHECKED] id=f1><label for=f1>Use fast indexing</label><br><br>
++<input type=submit value="Set Indexing Speed">
++</FORM>
++<BR>
++
++<p>&nbsp;<BR>
++<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
++<TR bgColor=#3399CC>
++ <TD align=middle height=1><IMG height=1 alt="" width=1></td></tr>
++</table>
++
++<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center bgColor=#efefef border=0>
++<tr>
++ <TD align=middle height=20><FONT size=-1><A href="[$~HOMEPAGE~$]">Google Desktop Search&nbsp;Home</A> - <a href="[$~STATUS~$]">Status</a> - <A href="[$~ABOUT~$]">About Google Desktop Search</A> - [$~BUILDNUMBER~$] - &copy;2005 Google </font> </td></tr>
++</table><BR>
++</body>
++</html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/install_prefs.html b/tools/grit/grit/testdata/install_prefs.html
+new file mode 100644
+index 0000000000..eca0b56de5
+--- /dev/null
++++ b/tools/grit/grit/testdata/install_prefs.html
+@@ -0,0 +1,92 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Google Desktop Search: Initial Preferences</title>
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY { FONT-FAMILY: arial,sans-serif }
++.c:active { COLOR: #FF0000 }
++.c:visited { COLOR: #7777CC }
++.c:link { COLOR: #7777CC }
++</style>
++<script>
++<!--
++override = 1;
++function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
++// -->
++</script>
++</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
++<form onsubmit='override=0;return true;' action='[STEP2]' name=f method=post>
++<img src="logo3.gif" border=0>
++<div id=c1 style="width:600px">
++<br><font color=#00218a><b>To continue, please set these initial preferences:</b></font><br><br>
++<table border=0 id=t1 width=100%>
++<tr>
++ <td valign=top><input name=AIM id=chat type=checkbox checked></td>
++ <td>&nbsp;</td><td><label for=chat><font size=-1><B>Enable search over Instant Messenger chats</b><br>
++ <font size=-1>Google Desktop Search will store your chats and make them searchable.
++</font></label></td></tr>
++<tr height=1><td height=10px></td></tr>
++<tr>
++ <td valign=top><input name=HTTPS id=https type=checkbox checked></td>
++ <td>&nbsp;</td><td><label for=https><font size=-1><b>Enable search over secure web pages (HTTPS)</b>
++ <br><font size=-1>Google Desktop Search will store secure web pages that you view and make them
++ searchable.</font></label> </td></tr>
++<tr height=1px><td height=10px></td></tr>
++
++<tr>
++ <td valign=top><input name=SEARCHBOX id=SEARCHBOX type=checkbox checked
++ onclick="handleSBClick(this)"></td>
++ <td>&nbsp;</td><td><label for=searchbox><font size=-1><b>Display search box</b></label>
++ <br><table border=0 cellpadding=0><tr><td valign=top>
++
++<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [DB-CHECKED] value="DISPLAYDB"></td><td>
++<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
++<tr><td></td></tr>
++<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
++<tr><td height=2></td></tr>
++<tr><td valign=top>
++
++<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [MB-CHECKED] VALUE="DISPLAYMB"></td><td>
++<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box that you can put anywhere on your desktop</font></label></td></tr>
++<tr><td></td></tr>
++<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
++<tr><td height=2></td></tr>
++
++</table>
++</td></tr>
++
++<tr>
++ <td valign=top><input name=SENDDATA id=usage type=checkbox checked></td>
++ <td>&nbsp;</td><td><label for=usage><font size=-1><b>Help us improve Google Desktop Search by sending usage data and crash reports</b></label>
++</font></td></tr>
++<tr height=8px><td colspan=3 height=8px></td></tr>
++<tr><td colspan=3><font size=-1>You can change these and other preferences at any time.</font></td></tr>
++</table></div>
++<p><input type=submit value="Set Preferences and Continue" id=s><br>
++</form>
++</center>
++[SCRIPT]
++<script>
++<!--
++function handleSBClick(checkbox) {
++ document.getElementById("DISPLAYDB").disabled = !checkbox.checked;
++ document.getElementById("DISPLAYMB").disabled = !checkbox.checked;
++}
++function stw() {
++if (document.all && document.body.clientWidth < 600) {
++ var w = document.body.clientWidth-35;
++ if (w < 10) { w = 10; }
++ w = w + 'px';
++ document.getElementById('c1').style.width=w;
++ return false;
++}
++document.getElementById('c1').style.width='600px';
++}
++stw();
++document.f.s.focus();
++// -->
++</script>
++<img SRC="http://www.google.com" WIDTH="0" HEIGHT="0" ALIGN="right"></img>
++</body></html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/install_prefs2.html b/tools/grit/grit/testdata/install_prefs2.html
+new file mode 100644
+index 0000000000..18380397c2
+--- /dev/null
++++ b/tools/grit/grit/testdata/install_prefs2.html
+@@ -0,0 +1,52 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Indexing has Started</title>
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY { FONT-FAMILY: arial,sans-serif }
++}
++</style>
++<script>
++<!--
++override = 1;
++function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
++// -->
++</script>
++</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
++<form onsubmit='override=0;return true;' action="[STEP3]" name=f>
++<img src="/logo3.gif" border=0><br><br>
++<div id=c1 style="width:575px">
++<table border=0 id=t1 width=100%><tr><td>
++<font color=#00218a><b>One-time indexing has started.</b></font><br><br>
++<font size=-1>An index is being prepared on your computer to allow you
++to search your information as fast as you can search the web.<br><br>
++<li>This is a one-time process that may take several hours.
++<li>You may continue to use your computer as usual and it is safe to shut down your computer.
++<li>Indexing will be performed only when your computer is idle.
++</ul>
++</font>
++<p><input type=submit value="Go to the Desktop Search homepage" name=s><br>
++</center>
++</td></tr></table>
++</form>
++</div>
++<script>
++<!--
++function stw() {
++if (document.all && document.body.clientWidth < 575) {
++ var w = document.body.clientWidth-35;
++ if (w < 10) { w = 10; }
++ w = w + 'px';
++ document.getElementById('c1').style.width=w;
++ return false;
++}
++document.getElementById('c1').style.width='575px';
++}
++stw();
++// -->
++document.f.s.focus();
++</script>
++[SCRIPT]
++</body></html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/klonk-alternate-skeleton.rc b/tools/grit/grit/testdata/klonk-alternate-skeleton.rc
+new file mode 100644
+index 0000000000000000000000000000000000000000..5f2c82a55469ddaab246c095826ad9e6743c0015
+GIT binary patch
+literal 1088
+zcmbW0Pfr3t48`AhKZV)z#sGrI5!gjnU?DC>IT2z!82=r_L=!)}zjnmk5b$6oGo9&7
+z+t=4lu9UG-Ujxl_t%b{59ih$9PSBn!lW7`iGrKMm&Q10vTRK5!yRJHlRN`fcWril@
+zv|?uHM))d_NBa7`nW9TQ&PZ3tsax6ojav@U&9TYdHduz6k{G4GFTfpX_hk&`!z0F`
+z!gJ>6WBh&UO&i_oS+VOvUfcD9JR=y&;3OxP2%KT$#JB9W=UtgQpDT@>(E^#^A;oG%
+z4omjIK7rLXcRgmyS+%u_Gl2`MhOxMB{GGM&5o6cXF<vdhEe5Mu-+3OQZF~Ht$8Yl5
+z&=^M*j(xG~y3(sxz{#AtW^kPoyR!dZ9)}Sd$_6;Qjx#V<A+O@5j%7~Al)9jj*71v4
+z<zn{ZUuJA?73tB}iB6fJ)6H}8)1l|&XFq3N%P!P%;Wv{#b&7SVweIxDUCbEh>E~=G
+z`!#F5=z%_bq95y7+aIx?IdcSN`A)xX^vZjCS7lnS#=iZ)E7W%eX8!kr-#RDO36^!o
+Qqn&wY8qX0d7T}2V4SbP+*8l(j
+
+literal 0
+HcmV?d00001
+
+diff --git a/tools/grit/grit/testdata/klonk.ico b/tools/grit/grit/testdata/klonk.ico
+new file mode 100644
+index 0000000000000000000000000000000000000000..d371b214dc366249870efccc5da278d023aa91f1
+GIT binary patch
+literal 766
+zcmeH_F%H5o5CqSFL>Ve71Sxq1;TtsMEB*!Fv6LbmDQFSUL1mXjO7OC0gpl|G?B1ML
+zXS=a1V(2`di0U>FnQ~o{oUDnF5j(}bxAgSuhE8lMu~rkI8Ju%mb%Im^Xd<+ZwEgwd
+zFTg+WQOj5lfvO*4mbEA^bCj9KHh65vjx^zvsKW{eA8|Ah`w&r;%!`QgmEiG3hXCcC
+L+@V2V6oA7MJIRBx
+
+literal 0
+HcmV?d00001
+
+diff --git a/tools/grit/grit/testdata/klonk.rc b/tools/grit/grit/testdata/klonk.rc
+new file mode 100644
+index 0000000000000000000000000000000000000000..35652c4e6dd7cf7b7f62f637e191acf66f487235
+GIT binary patch
+literal 9824
+zcmeI2+j1L48poSUd<zdSObP?FE=Nu{E-aL6%Z`X;t1MXwwb^nxw&R#MQm|was(2h8
+z0*VVRxZyQ;25z?&e*drad1j>1!LS!j6*Z-q>7MTIeClrf{=b{yW=KLKoQA`29(tkA
+z?@<`g*P*W;F2X@LqqP?P!IgxQa2&e)&gmcUJfiQMr{-PocF21|OVCckGsY~31#sNt
+zeuJJaU(OhLWaHAYxy#{kNExfq8uQ5J2xc`jLo2kyURV$HuoL#fZm7|_&ii)Q3SZFE
+z;@$|W^lb4S@e23#yIdxsED4)%Ix5vi$fg&b@^yerB!M>k-sfJ2-!(XtBx>~E;y0>;
+zywqpO@eUBz4c2yv49m3k+_Z88eb3Rg>+A-4?GCk8rmyLEuD7;k@iyBQuQz|u4r}P|
+z1pk!hKgO!w#>STMq~-8ViH-G#etL?RCgF{OzaBBS8aA-k=%+1wau1JP!(#WbwJk2e
+z{FW=3II|6mUA$wTS=-Ei$KrzUMVn6ea?kwXHeRp*%qrtH8Cm5n-|(IYVUu<pe(r=N
+zzO@*)I&s84Ull`c5XBVjPVmJ8W*uVn!oE+xdXM3B1?=zfi}cBtkC36HBDof6y#96&
+zDNK-*c<mwsaiN$Tt;G8iy#LgqQ-aMX7AOxWcPO4D;cMihSg+XijJE^e#f+h-em)#K
+zU}i#pm$ov9MjtR<GnAE-XHJcd#M&7}G3rSx$}4^5MSA<RMTcOD8qE;QGcM((Z-!r=
+z@>HA@wRN;~7h6y+xyz_&R~;+XxM^eZ-_q~|%%b86_{3Asa-8FBk+Z7c-kJgN>UjHR
+zv*J6C_vNv`hUxGkXMvL0T0vKhVQf$p6QjfeUR}fgl_wW2W!gk%O?<jZPZ}19O{d7^
+z*finVDx2ru9D3dIaKoU~fb#-41E46PT;&oc4LDIw7tD-Ohf;>IO<b0BC*h%aN($z?
+zm)50Lg3jeb@}4KgpHn7``|w@I(iDZ;#6d+vaXpT`D6f;D{i-%|`usUfYCfinmyGTN
+zIW7V>a`tbcYLDwE{AY?>BR88vkIj3pcp9ftwy~b;A8i-;T|_p=$nY5yWU!`jTE^ib
+ze*F+mE-Vf$<AuvpIC5FVr`t!>>e;=5g*fg0^w_NUeElxZA2EAWiGRui^1Zl<=<)P1
+zF&Y;=yo$%KVIA>VGwa=@)kgQbrt31jq~WuvvL2VO`$<s`-l~FW4S%T*JzWty@3kqC
+zpB4rFU-(`|ov-8B%D+84yQpbJq|Cy#a=VYFm5(Lg9joHhbBjy*SqUH5^H#VWD)#mP
+zmDd8gX|wiIT+{3pP+PpWiFV4=ZF*H_#xD)})(!p!_EWXI5x?KFnQQblnWI&vvb<)-
+zFIrzJTT2IfU>zNqGSmHCaU;Y2q0yQ$JF7mTwL~ub{sOMb^Vh8GFZ(K1F-x>#wroJR
+z&tF1@??TN-{BD^Hb<bj)tU9hU-SUgid^Mw80(r42u2^L$1ARm5q2(uK*A(fk5cewP
+z9Zr$-B@Y%=OVA@~R*aezo@z;A8C69Z##=4Z+%_6(qSKmXx%;{Kv$<M>gJ;mLeTx&a
+ztSZO1p-!t5NvMLINn_JEi1N%h$mrKfeZ%Sxtv*(<o;FujMW(#py@aoK$>Sq%E`|5`
+zMQa!2rJ*fu!l%|$%^a7pE^XVFE$AM-((pNcct~BK8YqR1Sd~Aqmi*&@D)rQ&bN`YW
+zMPvC%+;<TLnyH+o+P!PzGEPTvj<#1#Q&p3I;<v-i%S09-uHQ3$KQw!lbu5_YDT~KE
+zq3F><0?G_uSf2bldXz_x`Rp$tXUa07m0#5g^O>n*TJE4PW#|}5_jztxOjO*+fAM}<
+zk=Lii5sD#879SKTSIp++>5AlgXumxIv246U-XKqCe;}^ATDIP+P{%8`Yynw2Uilpc
+z$xha}X;{ahB+#YVajq(xJ|2|kCBqoURxZc-PC<V34wS`l@7lObCdzS5sL5l@zQ+BG
+z;+Tl3tUl7t#}1OyYFBw_V3AMzKfW@m<J*t$@OdlXBE$+_TOoq!`H*`aipPX9y8N3z
+zJLpP#o#HyZq-`Au=XaT7{)rj2n4zkrdkJOKOvhNvbdE_@DQ#r;l~PX2VN1f=r#R=S
+z`e>WGR&NeH+c%h>-Yw>z7_{+>=5WWql;yg~F}<jhong+@E{wQv`%$Z$n`LNxVSLVu
+zqX`bJ2rtN9gE2WJxg8d*6Uugv=9gd**I(1S$3)lvXuIe$9VB*sDZi`wUr{S<ASs*o
+zEyw#FTC@PgtLUAvrjGSZrVFRipYc2<9~H+>V-&+XR>jna$uG|ylUKW<KRZ>)Rw*m^
+z_oOjp@vHny>%lMrW)jt@&DG$}J`tOC!twxncz`|R{U9wplS^%1SD7h)zLPS$9KxSJ
+z^(luqF00#DmestFZxDq%2fL5@KE>#H<EVwdOuH`m{4TpYASY`FCbM&`$abwl+vH7a
+za;>I|)#R(g69An@YFD|(_t^K?Y(=LYvGR$s)LKbvaYc(JPp$Xb2G?a>eC9KE-cEhZ
+zHSZ3+_C$Rze-w`BSsn7ZgI%TJO=9FfdDBy)V;pqaYpnOHjNdZ)cZhIWOV;71NPE_b
+z5ZwYd@EV=tI))^?mN>3>KBO~=3-s|NvQu_bO!m`Xy&s`1RS8A9bec9lO`@(ym$)sX
+zMVVq?wjta)kvTJp%Bk>bSh}4@HcmwuW}T<$ta~!gT03ja*d|hI1w9*Uk>}TwPvL12
+z=Q{J$UgQ8RXmu+(2GDd)J#{>6mrEh;W{57|8=6JgB)U>?#`vQXEaBEZgsP}6H0c~I
+zlTn_wQLB~3>U1IQ2y}Rh=cM|##66Rnd!p7F(K=LbM6B`LtO3?OS3Ko>03~gD6g5tu
+zOSRooa>4*SqvO;gSO;d)IuFc4e&rSY3#4arR~e}tmqXie5w!0rzg2#y{KWm2%CD85
+zD?e8LTlv1?UR>st9pKlDtGM^mfuA&df=7MIT`QQ#k8mnxoriygx5#|&^UZ&6F?Nx!
+z2jMH^+zTJm>H?vU#6L!6XLz9~{RHheL_xo4SVUcx*(c|e8ZfVRzJC37^PM7DoUXW9
+zRu0v_b;|ztF`73W!u5N4HWX!l^<O!vStkE0N0PgK{5wU`>ZH1;i+3m{&0Ya4gg*c`
+C>9bG(
+
+literal 0
+HcmV?d00001
+
+diff --git a/tools/grit/grit/testdata/ko_oem_enable_bug.html b/tools/grit/grit/testdata/ko_oem_enable_bug.html
+new file mode 100644
+index 0000000000..f2c199cc15
+--- /dev/null
++++ b/tools/grit/grit/testdata/ko_oem_enable_bug.html
+@@ -0,0 +1 @@
++<IMG style="VERTICAL-ALIGN: middle" height=16 alt=아웃룩 src="/email.gif" width=16>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/ko_oem_non_admin_bug.html b/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
+new file mode 100644
+index 0000000000..b9e8a1f288
+--- /dev/null
++++ b/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
+@@ -0,0 +1 @@
++<INPUT id=s type=submit value="&nbsp;&nbsp;확인&nbsp;&nbsp;">
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/mini.html b/tools/grit/grit/testdata/mini.html
+new file mode 100644
+index 0000000000..8ac0a231a0
+--- /dev/null
++++ b/tools/grit/grit/testdata/mini.html
+@@ -0,0 +1,36 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head>
++<meta http-equiv=content-type content="text/html; charset=windows-1252">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
++DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
++A:hover { COLOR: #ffffff }
++.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
++</style>
++</head>
++
++<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0">
++
++<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
++<tr><TD vAlign=top>
++
++<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
++
++<tr>
++<TD vAlign=top>&nbsp;<INPUT style="position:relative; height=17px;" class=border size=10>&nbsp;</td>
++
++<TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><img height=1 width=1><IMG src="logo.gif" align=middle><img height=1 width=1></td>
++
++</TBODY></table>
++</td>
++
++<TD width=2><IMG height=1 width=1></td>
++
++<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
++<tr><TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="mini_close.gif"></td></tr></TBODY></table></td></tr></TBODY></table></body></html>
+diff --git a/tools/grit/grit/testdata/oem_enable.html b/tools/grit/grit/testdata/oem_enable.html
+new file mode 100644
+index 0000000000..db6b85eca6
+--- /dev/null
++++ b/tools/grit/grit/testdata/oem_enable.html
+@@ -0,0 +1,106 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Google Desktop Search Download</title>
++<meta http-equiv=content-type content="text/html; charset=utf-8">
++<style>BODY {
++ FONT-FAMILY: arial,sans-serif
++}
++TD {
++ FONT-FAMILY: arial,sans-serif
++}
++DIV {
++ FONT-FAMILY: arial,sans-serif
++}
++.p {
++ FONT-FAMILY: arial,sans-serif
++}
++A {
++ FONT-FAMILY: arial,sans-serif
++}
++DIV {
++ COLOR: #000
++}
++TD {
++ COLOR: #000
++}
++A:link {
++ COLOR: #00c
++}
++A:visited {
++ COLOR: #551a8b
++}
++</style>
++
++<meta content="mshtml 6.00.2800.1476" name=generator></head>
++<body>
++<center>
++<TABLE cellSpacing=0 cellPadding=0 border=0>
++ <TBODY>
++ <TR vAlign=center>
++ <td>
++ <DIV align=center><IMG height=55 alt="Google Desktop Search"
++ src="/logo3.gif" width=150 border=0 search=""
++ desktop=""></DIV></td>
++ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
++ <td><FONT size=+1><B>Search your own
++computer.</B></font></td></tr></TBODY></table><BR>
++<TABLE cellSpacing=0 cellPadding=0 width=630 border=0>
++ <TBODY>
++ <tr>
++ <TD vAlign=top width="53%"><FONT size=-1>
++ <LI>Find your email, files, web history and chats instantly <NOBR>
++ <LI>View web pages you've seen, even when you're not online</NOBR>
++ <LI>Search as easily as you do on Google
++ <p><B>Google Desktop Search finds:</B></p></font>
++ <TABLE cellSpacing=1 cellPadding=0 width=325 border=0 valign="center">
++ <TBODY>
++ <TR vAlign=center>
++ <TD colSpan=3><FONT size=-1><IMG style="VERTICAL-ALIGN: middle"
++ height=16 alt=Outlook src="/email.gif"
++ width=16>&nbsp;&nbsp;Email from Outlook, Outlook Express, &amp;
++ Thunderbird</font></td></tr>
++ <tr>
++ <TD noWrap colSpan=3><FONT size=-1><IMG
++ style="VERTICAL-ALIGN: middle" height=16 alt="Internet Explorer"
++ src="/html.gif" width=16>&nbsp;&nbsp;Web history
++ from IE/Firefox/Mozilla/Netscape</font></td></tr>
++ <tr>
++ <TD noWrap colSpan=3><FONT size=-1><IMG
++ style="VERTICAL-ALIGN: middle" height=16 alt=Text
++ src="/file.gif" width=16>&nbsp;&nbsp;Files in Word,
++ Excel, Powerpoint, PDF, &amp; media formats</font></td></tr>
++ <tr>
++ <TD vAlign=top colSpan=3><FONT size=-1><IMG
++ style="VERTICAL-ALIGN: middle" height=16 alt="AOL IM"
++ src="/aim.gif" width=16>&nbsp;&nbsp;Chats from AOL
++ Instant Messenger</font></td></tr>
++ <tr>
++ <TD noWrap><FONT size=-1>&nbsp;</font></td></tr></TBODY></table><FONT
++ size=-1>&nbsp;</font><FONT size=-1><A
++ href="http://desktop.google.com/about.html">About Desktop
++ Search</A>&nbsp;&nbsp; <A
++ href="http://desktop.google.com/screenshots.html">Screenshots</A>&nbsp;&nbsp;
++ <A href="http://desktop.google.com/support">Help</A>&nbsp;&nbsp; <A
++ href="http://desktop.google.com/feedback.html">Contact
++ Us</A><BR></font></LI></td>
++ <td>&nbsp;&nbsp;&nbsp;</td>
++ <TD vAlign=top width="53%">
++ <TABLE cellPadding=2 width="100%" align=center>
++ <TBODY>
++ <tr>
++ <TD
++ style="BORDER-RIGHT: rgb(204,204,204) 1px solid; BORDER-TOP: rgb(204,204,204) 1px solid; BORDER-LEFT: rgb(204,204,204) 1px solid; BORDER-BOTTOM: rgb(204,204,204) 1px solid"
++ width="100%" bgColor=#e7eff7 blah2="#fff8dd" blah="#e7eaf7"><BR>
++ <center><FONT size=-1>By using, you agree to our <A
++ href="http://desktop.google.com/eula.html"><BR>Terms &amp;
++ Conditions</A> and <A
++ href="http://desktop.google.com/privacypolicy.html">Privacy
++ Policy</A></font></center>
++ <p></p>
++ <FORM action='[STEP2]'>
++ <P align=center><INPUT style="PADDING-RIGHT: 3px; PADDING-LEFT: 3px; FONT-WEIGHT: bold; FONT-SIZE: 17px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px" type=submit value="Agree and Start Using" name=Submit>
++ </p></FORM><FONT size=-2>* Automatically starts when you turn on
++ your computer</font> </td></tr></TBODY></table>
++ <p></p></td></tr></TBODY></table></center>
++<p></p>
++<center><FONT color=#666666 size=-2>©2005 Google</font>
++<p></p></center></body></html>
+diff --git a/tools/grit/grit/testdata/oem_non_admin.html b/tools/grit/grit/testdata/oem_non_admin.html
+new file mode 100644
+index 0000000000..8b7ca13e21
+--- /dev/null
++++ b/tools/grit/grit/testdata/oem_non_admin.html
+@@ -0,0 +1,39 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Google Desktop Search Preferences</title>
++<meta http-equiv=cache-control content=no-cache>
++<meta http-equiv=content-type content="text/html; charset=utf-8">
++<meta http-equiv=pragma content=no-cache>
++<meta http-equiv=expires content=-1>
++<style>BODY {
++ FONT-FAMILY: arial,sans-serif
++}
++.c:active {
++ COLOR: #ff0000
++}
++.c:visited {
++ COLOR: #7777cc
++}
++.c:link {
++ COLOR: #7777cc
++}
++</style>
++
++<script>
++<!--
++override = 1;
++function ee() {if (override==1) {(new Image()).src="/doneinstallprefs&s=3286011577";}}
++// -->
++</script>
++
++<meta content="mshtml 6.00.2800.1476" name=generator></head>
++<BODY onresize=stw() leftMargin=30 rightMargin=30 onunload=ee()>
++<FORM name=f onsubmit=javascript:window.close();><IMG
++src="/logo3.gif" border=0>
++<DIV id=c1 style="WIDTH: 600px">
++<p><BR><FONT color=#00218a><B>We're sorry, but you need administrator access to
++enable Desktop Search.</B></font></p><FONT size=-1>
++<p>To install or run Google Desktop Search you need administrator access on this
++computer. Please try installing again once you have administrator
++access.</p></font></DIV>
++<p><INPUT id=s type=submit value=&nbsp;&nbsp;OK&nbsp;&nbsp;> <BR></p>
++<center></center></FORM></body></html>
+diff --git a/tools/grit/grit/testdata/onebox.html b/tools/grit/grit/testdata/onebox.html
+new file mode 100644
+index 0000000000..c24ff043a5
+--- /dev/null
++++ b/tools/grit/grit/testdata/onebox.html
+@@ -0,0 +1,21 @@
++<html><head><title>Google Desktop Search Results</title>
++<style><!--
++body,td,div,.p,a{font-family:arial,sans-serif }
++body{ background-color: transparent }
++div,td{color:#000}
++.f,.fl:link{color:#6f6f6f}
++a:link,.w,a.w:link,.w a:link{color:#00c}
++a:visited,.fl:visited{color:#551a8b}
++a:active,.fl:active{color:#f00}
++.t a:link,.t a:active,.t a:visited,.t{color:#000}
++//-->
++</style>
++</head>
++<body>
++<table cellspacing=0 cellpadding=1 border=0 ID="Google Desktop Search">
++<tr><td colspan=2><nobr><a href="http://[WEBSERVER][$~QUERY~$]" target=_parent>[NUMRESULTS] [RESULT-STRING] stored on your computer</a><font size=-1>&nbsp;-&nbsp;<a href="[HIDENOW]" style="color:#7777cc;" target=_parent>Hide</a>&nbsp;-&nbsp;<a href="http://desktop.google.com/integration.html" style="color:#7777cc;" target=_parent>About</a></font></nobr></td></tr>
++<tr><td valign=top width=40><img height=27 style="margin-top:2px;" src="http://[WEBSERVER]/onebox.gif"></td>
++<td valign=top width="99%"><font size=-1>[RESULTS]</font></td></tr>
++</table>
++</body>
++</html>
+diff --git a/tools/grit/grit/testdata/oneclick.html b/tools/grit/grit/testdata/oneclick.html
+new file mode 100644
+index 0000000000..32dc6459dd
+--- /dev/null
++++ b/tools/grit/grit/testdata/oneclick.html
+@@ -0,0 +1,34 @@
++[HEADER]
++
++
++<TABLE cellSpacing=4 cellPadding=0 width="100%" border=0>
++<tr>
++ <TD vAlign=top align=left width=50%>
++ [EMAIL_TOP_CHROME]
++
++ <p class=f>
++ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0>
++ [EMAIL]
++ </table>
++ </td>
++
++
++ <TD width=1 align=middle bgColor=#cfcfcf><IMG height=1 width=1></td>
++ <TD width=50% vAlign=top align=left>
++ [FREQ_TOP_CHROME]
++ <p class=f>
++ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table1">
++ [$~FREQ~$]
++ </table>
++ <p class=g>
++ [RECENT_TOP_CHROME]
++ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table2">
++ [$~RECENT~$]
++ </table>
++ </td>
++ </tr>
++</table>
++<center><BR>
++
++
++[FOOTER]
+diff --git a/tools/grit/grit/testdata/password.html b/tools/grit/grit/testdata/password.html
+new file mode 100644
+index 0000000000..16007a1ac0
+--- /dev/null
++++ b/tools/grit/grit/testdata/password.html
+@@ -0,0 +1,37 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Password Required</title>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
++.q {COLOR: #0000cc}
++</style>
++<script>
++<!--
++function sf(){document.f.q.focus();}
++// -->
++</script>
++</head>
++<body text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
++<center>
++<table cellSpacing=0 cellPadding=0 border=0>
++<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
++<form name=f method=GET action='/password'>
++<table cellSpacing=0 cellPadding=4 border=0>
++<tr><td class=q noWrap><font size=-1>
++ <table cellSpacing=0 cellPadding=0>
++ <tr vAlign=top>
++ <td align=middle>Password required:&nbsp;&nbsp;<input maxLength=80 size=30 type=password name=pw value="">
++ <script>
++ document.f.q.focus();
++ </script>
++ &nbsp;<input type=submit value="Submit" name=submit>
++ </td></tr>
++ </table>
++ </form>
++</td></tr>
++</table>
++<br><font size=-1>[$~BOTTOMLINE~$]</font></p>
++<p><font size=-2>&copy;2005 Google</font></p></center></body></html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/preferences.html b/tools/grit/grit/testdata/preferences.html
+new file mode 100644
+index 0000000000..b37412436b
+--- /dev/null
++++ b/tools/grit/grit/testdata/preferences.html
+@@ -0,0 +1,234 @@
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
++"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
++<html><head><title>Google Desktop Search Preferences</title>
++<meta http-equiv=content-type content="text/html; charset=utf-8">
++<style>
++body {
++ margin-left: 2em; margin-right: 2em;
++ font-family: arial,sans-serif;
++ color:#000; background-color:#fff;
++}
++a:active { color:#f00 }
++a:visited { color:#551a8b }
++a:link { color:#00c }
++a.c:active { color: #ff0000 }
++a.c:visited { color: #7777cc }
++a.c:link { color: #7777cc }
++.b { font-weight: bold }
++.shaded-header { background-color: #e8f4f7; border-top: 1px solid #39c;
++margin: 0px; padding: 0px }
++.shaded-subheader { background-color: #e8f4f7; margin: 12px 0px 0px 0px;
++ padding: 0px }
++.plain-subheader { background-color: #fff; margin: 12px 0px 0px 0px;
++ padding: 0px }
++.header-element { margin: 0px; padding: 2px}
++.expand { width: 98% }
++.s { font-size: smaller }
++.prefgroup { border: 2px solid #e8f4f7; width: 100% }
++.phead { font-weight: bold; font-size: smaller; vertical-align: top;
++text-transform: capitalize; border-bottom: 2px solid #e8f4f7; margin: 0px;
++padding: 8px}
++.pbody { border-bottom: 2px solid #e8f4f7; margin: 0px;
++padding: 8px}
++.pref-last { border-bottom: 0px }
++.example { color: gray; font-family: monospace; }
++</style>
++<script>
++<!--
++function validate() {}
++function fnOnClickAll() {for (var i = 0; i < document.langform.lr.length; i++) {
++document.langform.lr[i].checked = false;}}
++function fnOnClickSome() {
++var count = 0;for (var i = 0; i < document.langform.lr.length; i++) {
++if (document.langform.lr[i].checked) {count++;}}
++document.langform.lang[0].checked = (count <= 0);
++document.langform.lang[1].checked = (count > 0);}
++// -->
++</script>
++</head>
++<body onload="checkOffice()">
++<form name=prefs action="[$~SETPREFS~$]" method=post><input name=url
++value="[PREVPAGE]" type=hidden>
++<table cellspacing=2 cellpadding=0 width="100%" border=0>
++<tr>
++<td valign=top width="1%"><a href="[$~HOMEPAGE~$]">
++<img alt="Go to Google Desktop Search" src="logo3.gif" border=0></a></td>
++<td>&nbsp;</td>
++<td nowrap>
++
++<table class="shaded-header"><tr>
++<td class="header-element b expand">Preferences</td>
++<td class="header-element s">
++<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
++</td>
++</tr></table>
++
++</tr></table>
++
++<table class="shaded-subheader"><tr>
++<td class="header-element expand s">
++<span class="b">Save</span> your preferences when finished.</td>
++<td class="header-element"><input type=submit value="Save Preferences"
++name=submit2></td>
++</tr></table>
++
++[STATUS-MESSAGE]
++<table class="plain-subheader"><tr>
++<td class="header-element expand"><span class="b">Preferences</span><span
++class="s"> (changes apply to Google Desktop Search application)</span></td>
++</tr></table>
++
++<table class="prefgroup" cellpadding=0 cellspacing=0>
++
++<!-- -->
++<tr>
++<td class="phead">Search types</td>
++<td class="pbody"><div class="s">Index the following items so that you can
++search for them:<br />&nbsp;</div>
++<div>
++ <table border=0>
++ <tr>
++ <td width=150 nowrap valign=top><span class="s">
++ <input type=checkbox [CHECK-EMAIL] name=EMAIL id=h3><label for=h3>
++ Email</label><br>
++ <input type=checkbox [CHECK-AIM] name=AIM id=h5><label for=h5> Chats
++ (AOL/MSN IM)</label><br>
++ <input type=checkbox onclick='if(!this.checked){h12.checked=0;h12.disabled=1;}
++ else {h12.disabled=0;}' [CHECK-WEB] name=WEB id=h11><label for=h11> Web
++ history</label>
++
++ </span></td>
++ <td width=120 nowrap valign=top><span class="s">
++ <script>
++<!--
++function checkOffice() { var w = document.getElementById("h7");
++var e = document.getElementById("h8"); var o = document.getElementById("h10");
++if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
++// -->
++ </script>
++ <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
++ <label for=h7> Word</label><br>
++ <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
++ <label for=h8> Excel</label><br>
++ <input type=checkbox [CHECK-PPT] name=PPT id=h9>
++ <label for=h9> PowerPoint</label><br>
++ </span></td><td nowrap valign=top><span class="s">
++ <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
++ <label for=hpdf> PDF</label><br>
++ <input type=checkbox [CHECK-TXT] name=TXT id=h6>
++ <label for=h6> Text, media, and other files</label><br>
++ </tr>
++ <tr><td nowrap valign=top colspan=3><span class="s"><br />
++ <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
++ <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
++ <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
++ for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
++</table>
++</div></td></tr>
++</div>
++</td>
++</tr>
++
++<!-- -->
++<tr>
++<td class="phead">Plug-ins</td>
++<td class="pbody"><div class="s"
++style="display:[ADDIN-DISPLAYSTYLE]">Index these additional items:<p>
++[ADDIN-DO]
++[ADDIN-OPTIONS]</div><div class="s">
++To install plug-ins to index other items, visit the
++<a href="http://desktop.google.com/plugins.html">Plug-ins Download page</a>.</div>
++</tr>
++
++<!-- -->
++<tr>
++<td class="phead">Don't search these items</td>
++<td class="pbody"><div class="s">
++<label for=FORBIDDEN>Do not search web sites with the following URLs or files
++with the following paths. Put each entry on a separate line. Examples:</label><br>
++<span class="example">c:\Documents and Settings\username\Private Stuff</span><br>
++<span class="example">http://www.domain.com/</span><br>
++<div>&nbsp;</div>
++<div><TEXTAREA rows=3 cols=65 name=FORBIDDEN id=FORBIDDEN>[FORBIDDEN]
++</TEXTAREA></div>
++</tr>
++
++<!-- -->
++<tr>
++<td class="phead pref">Search Box Display</td>
++<td class="pbody pref" valign=top>
++
++<table border=0 cellpadding=0><tr><td valign=top>
++
++<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [CHECK-DISPLAYDB] value="DISPLAYDB"></td><td>
++<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
++<tr><td></td></tr>
++<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
++<tr><td height=2></td></tr>
++<tr><td valign=top>
++
++<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [CHECK-DISPLAYMB] VALUE="DISPLAYMB"></td><td>
++<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box you can put anywhere on your desktop</font></label></td></tr>
++<tr><td></td></tr>
++<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
++<tr><td height=2></td></tr>
++<tr><td valign=top>
++
++<input type=radio name="SBDISPLAY" id="DISPLAYNONE" [CHECK-DISPLAYNONE] VALUE="DISPLAYNONE"></td><td valign=top>
++<label for=DISPLAYNONE><font size=-1> None</font></label>
++</td></tr>
++</table>
++
++</td></tr>
++
++<!-- -->
++<tr>
++<td class="phead pref">Number of Results</td>
++<td class="pbody pref"><label for=num><span class="s">
++Display <select name=num id="num">
++<option [CHECK-NUM-10]>10
++<option [CHECK-NUM-20]>20
++<option [CHECK-NUM-30]>30
++<option [CHECK-NUM-50]>50
++<option [CHECK-NUM-100]>100</select>
++ results per page</span></label>
++</td>
++</tr>
++
++<!-- -->
++<tr>
++<td class="phead">Google integration</td>
++<td class="pbody">
++<table border=0 cellpadding=0>
++<tr><td><input type=CHECKBOX name=ONEBOX [CHECK-ONEBOX] id=onebox></td>
++<td><label for=onebox>
++ <span class="s">Show Desktop Search results on Google Web Search result pages.
++ </span></label></td></tr>
++ <tr><td></td><td>
++ <span class="s">Your personal results are private from Google.</span>
++ </td></tr></table>
++</td>
++</tr>
++
++<!-- -->
++<tr>
++<td class="phead pref-last">Help us improve</td>
++<td class="pbody pref-last">
++<input type=CHECKBOX name=SENDDATA id="SENDDATA" [CHECK-SENDDATA]><label for=
++SENDDATA> <span class="s">Send non-personal usage data and crash reports to
++Google to help improve Desktop Search.</span></label>
++</td>
++</tr>
++
++</table>
++
++<table class="shaded-subheader"><tr>
++<td class="header-element expand s"><span class="b">Save</span> your preferences
++when finished.</td>
++<td class="header-element"><input type=submit value="Save Preferences"
++name=submit2></td>
++</tr></table>
++
++<p><div align=center>[$~BOTTOMLINE~$]</div>
++<br><center><span class="s">&copy;2005 Google</span></center>
++</form></body></html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/preprocess_test.html b/tools/grit/grit/testdata/preprocess_test.html
+new file mode 100644
+index 0000000000..13ece9a9f6
+--- /dev/null
++++ b/tools/grit/grit/testdata/preprocess_test.html
+@@ -0,0 +1,7 @@
++<if expr="True">
++should be kept
++</if>
++in the middle...
++<if expr="False">
++should be removed
++</if>
+diff --git a/tools/grit/grit/testdata/privacy.html b/tools/grit/grit/testdata/privacy.html
+new file mode 100644
+index 0000000000..1d45f4a539
+--- /dev/null
++++ b/tools/grit/grit/testdata/privacy.html
+@@ -0,0 +1,35 @@
++[!]
++title Privacy and Google Desktop Search
++template
++privacy_bottomline
++hp_image
++
++<TABLE CELLSPACING=0 CELLPADDING=5 WIDTH="98%" BORDER=0>
++<TR VALIGN=TOP>
++<td>
++<h4>Privacy and Google Desktop Search</h4>
++
++<p><FONT SIZE=-1>Google is committed to making search on your desktop as easy
++as searching the web. We recognize that privacy is an important issue,
++so we designed and built Google Desktop Search with respect for your privacy.
++<p>
++So that you can easily search your computer, the Google Desktop Search application indexes
++and stores versions of your files and other computer activity,
++such as email, chats, and web history. These versions may also be mixed
++with your Web search results to produce
++results pages for you that integrate relevant content from your computer and
++information from the Web.
++<p>
++Your computer's content is not made accessible to Google or anyone else without your explicit permission.
++
++<p>You can read the
++<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
++and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.
++</font>
++</td></tr></table>
++
++<center><br>
++<TABLE CELLSPACING=0 CELLPADDING=0 WIDTH="100%" BORDER=0>
++<TR BGCOLOR=#3399CC><TD ALIGN=MIDDLE HEIGHT=1><IMG HEIGHT=1 ALT="" WIDTH=1></td></tr></table>
++<FONT SIZE=-1>[$~PRIVACY_BOTTOMLINE~$] - &copy;2005 Google </font>
++</center>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/quit_apps.html b/tools/grit/grit/testdata/quit_apps.html
+new file mode 100644
+index 0000000000..a501b0e2bf
+--- /dev/null
++++ b/tools/grit/grit/testdata/quit_apps.html
+@@ -0,0 +1,49 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Google Desktop Search Preferences</title>
++<meta http-equiv=cache-control content=no-cache>
++<meta http-equiv=content-type content="text/html; charset=utf-8">
++<meta http-equiv=pragma content=no-cache>
++<meta http-equiv=expires content=-1>
++<style>BODY {
++ FONT-FAMILY: arial,sans-serif
++}
++.c:active {
++ COLOR: #ff0000
++}
++.c:visited {
++ COLOR: #7777cc
++}
++.c:link {
++ COLOR: #7777cc
++}
++</style>
++
++<script>
++<!--
++// -->
++</script>
++
++<meta content="mshtml 6.00.2800.1476" name=generator></head>
++<BODY onresize=stw() leftMargin=30 rightMargin=30>
++<FORM name=f action='[NEXTSTEP]' method=post><IMG src="/logo3.gif"
++border=0>
++<DIV id=c1 style="WIDTH: 600px">
++<p><BR><FONT color=#00218a><B>To start using Google Desktop Search, we may need to close the following programs if they are running:</B></font></p>
++<FONT size=-1><p>You can start these programs once Google Desktop Search is running.</p></font>
++
++<LI><FONT size=-1>AOL Instant Messenger</font>
++<LI><FONT size=-1>Firefox</font>
++<LI><FONT size=-1>Internet Explorer</font>
++<LI><FONT size=-1>Microsoft Excel</font>
++<LI><FONT size=-1>Microsoft Outlook </font>
++<LI><FONT size=-1>Microsoft Word </font>
++<LI><FONT size=-1>Mozilla</font>
++<LI><FONT size=-1>Mozilla Thunderbird</font>
++<LI><FONT size=-1>Netscape</font>
++<LI><FONT size=-1>Opera</font>
++<LI><FONT size=-1>Other web browsers</font>
++<FONT size=-1>
++<p>This will take only a few seconds to complete. </p></font></LI></DIV>
++<p><INPUT id=s type=submit name="quit" value="&nbsp;&nbsp;OK.&nbsp;&nbsp;Close&nbsp;these&nbsp;applications&nbsp;&nbsp;">
++ <INPUT id=s type=submit name="redir" value="&nbsp;&nbsp;Cancel.&nbsp;I'll&nbsp;run&nbsp;this&nbsp;later&nbsp;&nbsp;"><BR></p>
++<center></center></FORM></body></html>
+diff --git a/tools/grit/grit/testdata/recrawl.html b/tools/grit/grit/testdata/recrawl.html
+new file mode 100644
+index 0000000000..0401e7c2b0
+--- /dev/null
++++ b/tools/grit/grit/testdata/recrawl.html
+@@ -0,0 +1,30 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head><title>Refresh index</title>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
++.q {COLOR: #0000cc}
++</style>
++</head>
++<body text="#000000" vLink="#551a8b" aLink="#ff0000" link="#0000cc" bgColor="#ffffff">
++<center>
++<table cellSpacing="0" cellPadding="0" border="0">
++<tr>
++<td><a href="[$~HOMEPAGE~$]"><img border="0" height="110" alt="Google Desktop Search" src="hp_logo.gif" width="276"></a>
++</td>
++</tr>
++</table>
++<br>
++<center>Google Desktop Search is now recrawling your drive to index new files.</center>
++<center>Note that new files are indexed automatically, and this step is generally not needed.</center>
++<center>Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
++</td></tr></table>
++<br>
++<font size="-1">[$~BOTTOMLINE~$]</font>
++<p><font size="-2">&copy;2005 Google</font></p>
++</center>
++</body>
++</html>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/resource_ids b/tools/grit/grit/testdata/resource_ids
+new file mode 100644
+index 0000000000..d5d440d57f
+--- /dev/null
++++ b/tools/grit/grit/testdata/resource_ids
+@@ -0,0 +1,13 @@
++{
++ "SRCDIR": ".",
++ "test.grd": {
++ "messages": [100, 10000],
++ },
++ "substitute_no_ids.grd": {
++ "messages": [10000, 20000],
++ },
++ "<(FOO)/file.grd": {
++ },
++ "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools.grd": {
++ },
++}
+diff --git a/tools/grit/grit/testdata/script.html b/tools/grit/grit/testdata/script.html
+new file mode 100644
+index 0000000000..f177d9c30e
+--- /dev/null
++++ b/tools/grit/grit/testdata/script.html
+@@ -0,0 +1,38 @@
++<script>
++function run(n,cut){
++ var out = "", str = "abcdefghijklmnopqrstuvwxyz 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ,./:;'\"()*!?-_@[]{}#%`+=|\\>";
++ n.innerHTML = 'aa';
++
++ var base = n.scrollWidth;
++ for(var i=0;i<str.length;i++) {
++ n.innerHTML = 'a'+str.charAt(i)+'a';
++ out += str.charAt(i) + (n.scrollWidth-base) +";";
++
++ if(cut && !i && (n.scrollWidth-base == cut)) {
++ return '\x02'+"0;";
++ }
++ }
++ // extra cases for literals
++ n.innerHTML = 'a&lt;a';
++ out += '<' + (n.scrollWidth-base) +";";
++ n.innerHTML = 'a&amp;a';
++ out += '&' + (n.scrollWidth-base) +";";
++
++ var base_height = n.scrollHeight;
++ n.innerHTML += '<br>a';
++ out += '\x01' + (n.scrollHeight-base_height) +";";
++
++ return out;
++}
++
++function TEST_WIDTH() {
++ var n = document.getElementById('test');
++ var out = run(n[$~CUT~$]);
++ if (out.length>4){
++ n.style.fontWeight='bold';
++ out += run(n);
++ }
++ n.outerHTML = "";
++ (new Image()).src="[$~SETWIDTH~$]?src=[COMPONENT]&data="+escape(out).replace(/\+/g,"%2B");
++}
++</script>
+diff --git a/tools/grit/grit/testdata/searchbox.html b/tools/grit/grit/testdata/searchbox.html
+new file mode 100644
+index 0000000000..9eccba99a5
+--- /dev/null
++++ b/tools/grit/grit/testdata/searchbox.html
+@@ -0,0 +1,22 @@
++<body bgcolor=#ffffff topmargin=2 marginheight=2>
++<table border=0 cellpadding=0 cellspacing=0 width=1%>
++<tr>
++<td valign=top><a href='[$~HOMEPAGE~$]'><img width=150 height=55 src="/logo3.gif" alt="Go to Google Desktop Search" border=0 vspace=12></a></td>
++<td>&nbsp;&nbsp;</td>
++<td valign=top>
++<table cellpadding=0 cellspacing=0 border=0><tr><td colspan=2 height=14 valign=bottom>
++<table border=0 cellpadding=4 cellspacing=0>
++<tr><td class=q><font size=-1>
++[$~LINKS~$]
++</tr>
++</table>
++</td>
++</tr>
++<tr><td nowrap><form name=gs method=GET action='[$~SEARCHURL~$]'><input type=text name=q size=41 maxlength=2048 value="[DISP_QUERY]"><input type=hidden name=ie value="UTF-8">
++<font size=-1>[$~FLAGS~$]<input type=submit name="btnG" value="Search Desktop"><span id=hf></span></font></td>
++<td><font size=-2>&nbsp;&nbsp;<a href='[$~PREFERENCES~$]'>Desktop&nbsp;Preferences</a><br>&nbsp;&nbsp;<a [DELETE_EXTRA] href=[DELETE_PAGE]><nobr>[DELETE_NAME]</nobr></a></font></td>
++</tr></table>
++<table cellpadding=0 cellspacing=0 border=0>
++<tr><td><font size=-1>&nbsp;</font></td></tr>
++</table>
++</td></tr></form></table>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/sidebar_h.html b/tools/grit/grit/testdata/sidebar_h.html
+new file mode 100644
+index 0000000000..e103e8f8db
+--- /dev/null
++++ b/tools/grit/grit/testdata/sidebar_h.html
+@@ -0,0 +1,82 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY,TD,DIV,A,.p { FONT-FAMILY: arial,sans-serif; SCROLL: no}
++DIV,TD {COLOR: #000}
++.f, .fl:link {COLOR: #6f6f6f}
++A:link { COLOR: #00c}
++A:visited { COLOR: #551a8b}
++A:active { COLOR: #f00}
++.fl:active { COLOR: #f00}
++.h { COLOR: #3399CC}
++.a, .a:link {COLOR: #008000}
++.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
++.g { MARGIN-TOP: .5em; MARGIN-BOTTOM: .5em}
++.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
++.c:active, .c:visited, .c:link { COLOR: #6f6f6f}
++.ch {CURSOR: hand}
++</style>
++</head>
++<BODY onload="TEST_WIDTH();" bottomMargin=0 leftMargin=2 topMargin=0 rightMargin=2 marginwidth=0 marginheight=0 SCROLL=NO bgcolor=#E0E0E0 style="border-style:solid; border-width:0;" oncontextmenu="return false;">
++
++<script>
++function hide() {
++ return 1;
++ // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences. ");
++}
++</script>
++
++
++<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%"><tr>
++<TD WIDTH="19%" VALIGN=TOP>
++
++<form method=get action="[$~SEARCHURL~$]">
++<input type=hidden name=src value=4>
++
++ <table cellspacing=0 cellpadding=0 width='1%'>
++ <tr><td nowrap align=center valign=middle><nobr><img width=16 height=16 src=logo.gif>&nbsp;<b><i><font color=#6F6F6F>Google Desktop Search</font></i></b><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></nobr></td></tr>
++ <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="1" style="font-size:10px; width:'100%';" name="q" id="q"></nobr></td></tr>
++ <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="2" style="font-size:10px" type=submit value="Local search" name=btnG> <input TABINDEX="3" style="font-size:9px" type=submit value="Web search" name=redir></nobr></td></tr>
++<MAP name="control">
++<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++</MAP>
++ </table>
++</form>
++
++</td>
++<TD WIDTH="27%" VALIGN=TOP>
++
++[HEADER_SECTION1]
++[CONTENT_INBOX]
++
++</td>
++<TD WIDTH="27%" VALIGN=top>
++
++[HEADER_SECTION2]
++[CONTENT_HIST]
++
++</td>
++<TD WIDTH="27%" VALIGN=top>
++
++[CONTENT_NEWS]
++[CONTENT_OTHER]
++
++</td>
++<TD WIDTH="1%" VALIGN=top>
++
++<a TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick='return hide()' href='[$~HIDE1~$]' class=ch><img width=12 height=11 style='vertical-align:top;' src=/hide.gif valign=top border=0></a>
++
++</td>
++</tr></table>
++
++<font size=-1><span style="visibility:hidden" id='test'>t</span></font>
++
++[SCRIPT]
++</body></html>
+diff --git a/tools/grit/grit/testdata/sidebar_v.html b/tools/grit/grit/testdata/sidebar_v.html
+new file mode 100644
+index 0000000000..e040d8ec59
+--- /dev/null
++++ b/tools/grit/grit/testdata/sidebar_v.html
+@@ -0,0 +1,267 @@
++<html><head>
++<title>Google Desktop Search Sidebar</title>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<meta http-equiv="cache-control" content="no-cache">
++<meta http-equiv="pragma" content="no-cache">
++<meta http-equiv="expires" content="-1">
++<style>
++BODY,TD,P,A {FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt; color:#fff}
++a:link, a:visited, a:hover, b, q b { color: #ffffff}
++a:active { color: #ff0000}
++a:link,a:active,a:visited,div { text-decoration: none;font-size:8pt }
++.g{margin-top: 1em;}
++.gg{margin-top: .4em;}
++.norepeat { background-repeat: no-repeat }
++.indent{margin-top: 0px; margin-bottom: 0px;margin-left:3px;}
++.c:link, .c:visited, .c:active { color: #959595;font-size:8pt }
++.ch{cursor:pointer;cursor:hand}
++.gap{margin-top: 10px; margin-bottom: 10px;}
++.off {display:none}
++.on {display:on}
++.but { border-top: 1px solid #73787E;border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-left: 1px solid #73787E;margin-top: 0px; margin-bottom: 0px; cursor:pointer;cursor:hand}
++</style>
++<script>
++
++function toggle(i) {
++ var v = document.getElementById(i);
++ var vi = document.getElementById(i+'icon');
++ var c = (v['className'] == 'on');
++ if (c) {
++ v['className'] = 'off';
++ vi.src='up.gif';
++ }
++ else {
++ v['className'] = 'on';
++ vi.src='down.gif';
++ }
++ (new Image()).src="[$~TOGGLE~$]?setting="+i+"&mode="+v['className']+"&rnd="+Math.random();
++
++ if (!c && (v['oclass'] == 'off')) {
++ location.href = location.href;
++ }
++
++ return true;
++}
++function hide() {
++ // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences.");
++ return 1;
++}
++</script>
++
++<!-- menu experiment start -->
++
++<style>
++<!--
++.menu1 {
++cursor:default;
++position:absolute;
++text-align: left;
++font-family: Arial, Helvetica, sans-serif;
++font-size: 8pt;
++font-color: #000000;
++color: #000000;
++background-color: menu;
++visibility: hidden;
++padding-top: 2px;
++padding-bottom: 2px;
++border: 1 solid;
++border-color: #888888;
++z-index: 100;
++}
++.menuitems {
++padding-left: 5px;
++padding-right: 5px;
++}
++-->
++</style>
++<SCRIPT LANGUAGE="JavaScript1.2">
++<!--
++var menustyle = "menu1";
++
++function showmenu() {
++ var rightedge = document.body.clientWidth-event.clientX;
++ var bottomedge = document.body.clientHeight-event.clientY;
++ // if (rightedge < rcmenu.offsetWidth)
++ // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
++ // else
++ // rcmenu.style.left = document.body.scrollLeft + event.clientX;
++
++ // if (rcmenu.style.left < 0) rcmenu.style.left = 0;
++ rcmenu.style.left = 0;
++
++ if (bottomedge < rcmenu.offsetHeight)
++ rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
++ else
++ rcmenu.style.top = document.body.scrollTop + event.clientY;
++
++ if (rcmenu.style.top < 0) rcmenu.style.top = 0;
++
++ rcmenu.style.visibility = "visible";
++ // rcmenu.style.zindex = 0;
++ // document.all('rcmenu').style.zindex = 20;
++ document.onkeydown=ck;
++ return false;
++}
++
++function hidemenu() {
++ rcmenu.style.visibility = "hidden";
++}
++
++function ck(e){
++ evt=document.all?window.event:e;
++ k=document.all?window.event.keyCode:e.keyCode;
++
++ if(k==27 /*<Esc>*/) {
++ hidemenu();
++ }
++}
++
++function menumouseover() {
++ if (event.srcElement.className == "menuitems") {
++ event.srcElement.style.backgroundColor = "highlight";
++ event.srcElement.style.color = "white";
++ }
++}
++
++function menumouseout() {
++ if (event.srcElement.className == "menuitems") {
++ event.srcElement.style.backgroundColor = "";
++ event.srcElement.style.color = "black";
++ window.status = "";
++ }
++}
++
++function menuselect() {
++ if (event.srcElement.className == "menuitems") {
++ if (event.srcElement.getAttribute("target") != null)
++ window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
++ else if (event.srcElement.url.length)
++ window.location = event.srcElement.url;
++ }
++}
++// -->
++</script>
++
++<!-- menu experiment end -->
++
++</head>
++
++<body onload="TEST_WIDTH();" bottommargin=0 leftmargin=0 marginheight=0 marginwidth=0 rightmargin=0 topmargin=0 style="background-color:'#384146'; background-repeat: repeat-y; border-style:solid; border-width:0;" background="greyback.jpg" scroll=NO oncontextmenu="return false;">
++
++<!-- menu experiment start -->
++
++<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
++<div class="menuitems" url="[$~SETDISP4~$]">Switch to minibar</div>
++<div class="menuitems" url="[$~SETDISP2~$]">Switch to hoverbar</div>
++<div class="menuitems" url="[$~HIDE1~$]">Close sidebar</div>
++<div class="menuitems" url="">No change</div>
++</div>
++
++<script language="JavaScript1.2">
++if (document.all && window.print) {
++ rcmenu.className = menustyle;
++ document.oncontextmenu = showmenu;
++ document.body.onclick = hidemenu;
++}
++</script>
++
++<!-- menu experiment end -->
++
++<div id="oneliner" style="visibility:hidden; position:absolute; left:0px; top:0px;"></div>
++<script>
++var h = document.getElementById("oneliner").offsetHeight*2;
++document.write("<style type='text/css'>.truncme { overflow:hidden;height: " +h+"px; }</style>");
++</script>
++
++<table cellpadding=0 cellspacing=0 border=0 width='100%'>
++<form method=get action="[$~SEARCHURL~$]" id=f1>
++<input type=hidden name=src value=5>
++<input type=hidden name=redir value=''>
++<tr>
++ <td width='1%'><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></td>
++ <td width='97%'><input TABINDEX="1" NAME="q" style="width:'100%'; FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt"></td>
++ <td width='1%'><table cellpadding=2 cellspacing=0><tr><td> </td><td TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="location.href='[$~SETDISP2~$]';"><img src="mini_mini.gif"></td></tr></table></td>
++ <td width='1%'><table cellpadding=2 cellspacing=0><tr><td TABINDEX="9" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="if (hide())location.href='[$~HIDE1~$]';"><img src="mini_close.gif"></td></tr></table></td>
++</tr>
++<MAP name="control">
++<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
++</MAP>
++</table>
++
++<center>
++<table cellpadding=2 cellspacing=3>
++<tr>
++ <td TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit()" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch nowrap bgcolor=414A4F valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;"><img src="logo.gif" align="texttop"> <font color=ffffff>Google Desktop Search&nbsp;</td>
++ <td TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch bgcolor=414A4F nowrap valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;">&nbsp;<font color=ffffff>Web&nbsp;</td>
++</tr>
++</form>
++</table>
++</center>
++
++<p class=gg>
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
++<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("news");' onclick='return toggle("news");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=newsicon src="[$~NEWS_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>News</td></tr></table>
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
++
++<span id="news" class=[$~NEWS_CLASS~$] oclass=[$~NEWS_CLASS~$]>
++[CONTENT_NEWS]
++<p class=g>
++</span>
++
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
++<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("inbox");' onclick='return toggle("inbox");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=inboxicon src="[$~INBOX_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Email</td></tr></table>
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
++
++<span id=inbox class=[$~INBOX_CLASS~$] oclass=[$~INBOX_CLASS~$]>
++[CONTENT_INBOX]
++<p class=g>
++</span>
++
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
++<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("hist");' onclick='return toggle("hist");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=histicon src="[$~HIST_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Related History</td></tr></table>
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
++
++<span id="hist" class=[$~HIST_CLASS~$] oclass=[$~HIST_CLASS~$]>
++[CONTENT_HIST]
++<p class=g>
++</span>
++
++
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
++<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("recent");' onclick='return toggle("recent");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=recenticon src="[$~RECENT_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Recent</td></tr></table>
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
++
++<span id="recent" class=[$~RECENT_CLASS~$] oclass=[$~RECENT_CLASS~$]>
++[CONTENT_RECENT]
++<p class=g>
++</span>
++
++
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
++<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("popular");' onclick='return toggle("popular");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=popularicon src="[$~POPULAR_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Frequently Visited</td></tr></table>
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
++
++<span id="popular" class=[$~POPULAR_CLASS~$] oclass=[$~POPULAR_CLASS~$]>
++[CONTENT_POPULAR]
++<p class=g>
++</span>
++
++
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
++<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("quib_debug");' onclick='return toggle("quib_debug");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=quib_debugicon src="[$~QUIB_DEBUG_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Implicit Query Debug</td></tr></table>
++<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
++
++<span id="quib_debug" class=[$~QUIB_DEBUG_CLASS~$] oclass=[$~QUIB_DEBUG_CLASS~$]>
++[CONTENT_QUIB_DEBUG]
++</span>
++
++<span style="visibility:hidden" id='test'>t</span>
++
++[CONTENT_OTHER]
++
++[SCRIPT]
++</body>
++</html>
+diff --git a/tools/grit/grit/testdata/simple-input.xml b/tools/grit/grit/testdata/simple-input.xml
+new file mode 100644
+index 0000000000..92827fa4b5
+--- /dev/null
++++ b/tools/grit/grit/testdata/simple-input.xml
+@@ -0,0 +1,52 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
++ <release seq="2">
++ <messages>
++ <message name="IDS_OLD_MESSAGE" translateable="true">Hello earthlings!</message>
++ </messages>
++ </release>
++ <release seq="3">
++ <includes>
++ <include name="ID_EDIT_BOX_ICON" type="icon" translateable="false" file="images/edit_box.ico" />
++ <include name="ID_LOGO" type="gif" translateable="true" file="images/logo.gif"/>
++ </includes>
++ <messages>
++ <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ </messages>
++ <structures>
++ <structure type="menu" name="IDM_FOO" file="rc_files/menus.rc" />
++ <structure type="dialog" name="IDD_BLAT" file="rc_files/dialogs.rc" />
++ <structure type="tr_html" name="IDR_HTML_TEMPLATE" file="templates/homepage.html" />
++ <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc">
++ <skeleton expr="lang == 'fr-FR'" variant_of_revision="3">
++ <![CDATA[IDD_DIALOG1 DIALOGEX 0, 0, 186, 90
++STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
++ WS_SYSMENU
++CAPTION "TRANSLATEABLEPLACEHOLDER1"
++FONT 8, "MS Shell Dlg", 400, 0, 0x1
++BEGIN
++ DEFPUSHBUTTON "TRANSLATEABLEPLACEHOLDER2",IDOK,129,7,50,14
++ PUSHBUTTON "TRANSLATEABLEPLACEHOLDER3",IDCANCEL,129,24,50,14
++ LTEXT "TRANSLATEABLEPLACEHOLDER4",IDC_STATIC,23,31,40,8
++END]]>
++ </skeleton>
++ </structure>
++ <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc"/>
++ </structures>
++ </release>
++ <translations>
++ <file path="figs_nl_translations.xml" />
++ <file path="cjk_translations.xml" />
++ </translations>
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="resource_en.rc" type="rc_all" lang="en-US" />
++ <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
++ <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
++ <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
++ <output filename="nontranslateable.rc" type="rc_nontranslateable" />
++ </outputs>
++</grit>
+diff --git a/tools/grit/grit/testdata/simple.html b/tools/grit/grit/testdata/simple.html
+new file mode 100644
+index 0000000000..4392d23e98
+--- /dev/null
++++ b/tools/grit/grit/testdata/simple.html
+@@ -0,0 +1,3 @@
++<p>
++ Hello!
++</p>
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/source.rc b/tools/grit/grit/testdata/source.rc
+new file mode 100644
+index 0000000000..fbc72284e9
+--- /dev/null
++++ b/tools/grit/grit/testdata/source.rc
+@@ -0,0 +1,57 @@
++IDC_KLONKMENU MENU
++BEGIN
++ POPUP "&File"
++ BEGIN
++ MENUITEM "E&xit", IDM_EXIT
++ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
++ POPUP "gonk"
++ BEGIN
++ MENUITEM "Klonk && is [good]", ID_GONK_KLONKIS
++ END
++ END
++ POPUP "&Help"
++ BEGIN
++ MENUITEM "&About ...", IDM_ABOUT
++ END
++END
++
++IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "About"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
++ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
++ SS_NOPREFIX
++ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
++ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
++ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
++ BS_AUTORADIOBUTTON,46,51,84,10
++END
++
++IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "Bingobobbi"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
++ LTEXT "Yo froodie!",IDC_STATIC,49,20,119,8
++END
++
++STRINGTABLE
++BEGIN
++ IDS_SIMPLE "One"
++ IDS_PLACEHOLDER "%s birds"
++ IDS_PLACEHOLDERS "%d of %d"
++ IDS_REORDERED_PLACEHOLDERS "$1 of $2"
++ // Won't be in translations list because it has changed
++ IDS_CHANGED "This was the old version"
++ IDS_TWIN_1 "Hello"
++ IDS_TWIN_2 "Hello"
++ IDS_NOT_TRANSLATEABLE ":"
++ IDS_LONGER_TRANSLATED "Removed document $1"
++ // Won't appear in the list of translations because it's not in the .grd file
++ IDS_NO_LONGER_USED "Not used"
++ IDS_DIFFERENT_TWIN_1 "Howdie"
++ IDS_DIFFERENT_TWIN_2 "Howdie"
++END
+diff --git a/tools/grit/grit/testdata/special_100_percent/a.png b/tools/grit/grit/testdata/special_100_percent/a.png
+new file mode 100644
+index 0000000000000000000000000000000000000000..5d5089038ca71172e95db9e7aae1e1fa5cebd505
+GIT binary patch
+literal 159
+zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>0wld=oSO}#(mY)pLnNjq|2Y3)zGGzYPN&L+
+zMSC}CcCfp=Dtxv4%6W%G#Q=|R|L;6pCCLUWO)Z<5eoL%TkDTw=s4X!^d(Qa<2khAN
+zZPy!XToBAic1Ss}vcWiD27B3&`Zj^H6CO>7R1{ToQ;=ggdEYbV=IISvfHpFCy85}S
+Ib4q9e0O9jEh5!Hn
+
+literal 0
+HcmV?d00001
+
+diff --git a/tools/grit/grit/testdata/status.html b/tools/grit/grit/testdata/status.html
+new file mode 100644
+index 0000000000..6b997b9369
+--- /dev/null
++++ b/tools/grit/grit/testdata/status.html
+@@ -0,0 +1,44 @@
++[HEADER]
++<table cellspacing=0 cellPadding=0 width="100%" border=0>
++<tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr>
++</table>
++<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0>
++<tr><td height=20><font size=+1 color=#000000>&nbsp;<b>Desktop Search Status</b></font></td></tr>
++</table>
++<br>
++<center>
++[$~MESSAGE~$]
++<table cellspacing=0 cellPadding=6 width=500 border=0>
++<tr>
++ <td>&nbsp;</td>
++ <td align=right nowrap><i><font size=-1>Number of items</font></i></td>
++ <td align=right nowrap><i><font size=-1>Time of newest item</font></i></td>
++</tr>
++<tr>
++ <td width=1% nowrap><img style="vertical-align:middle" width=16 height=16 src=favicon.ico>&nbsp; Total searchable items</td>
++ <td align=right><b>[TOTAL_COUNT]</b></td>
++ <td align=right><b>[TOTAL_TIME]</b></td>
++</tr>
++<tr>
++ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=email.gif width=16 height=16>&nbsp; Emails</font></td>
++ <td align=right><font size=-1>[EMAIL_COUNT]</font></td>
++ <td align=right><font size=-1>[EMAIL_TIME]</font></td>
++</tr>
++<tr>
++ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src="16x16_chat.gif" width=16 height=16>&nbsp; Chats</font></td>
++ <td align=right><font size=-1>[IM_COUNT]</font></td>
++ <td align=right><font size=-1>[IM_TIME]</font></td>
++</tr>
++<tr>
++ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=html.gif width=16 height=16>&nbsp; Web history</font></td>
++ <td align=right><font size=-1>[WEB_COUNT]</font></td>
++ <td align=right><font size=-1>[WEB_TIME]</font></td>
++</tr>
++<tr>
++ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=file.gif width=16 height=16>&nbsp; Files</font></td>
++ <td align=right><font size=-1>[FILE_COUNT]</font></td>
++ <td align=right><font size=-1>[FILE_TIME]</font></td>
++</tr>
++</table>
++</center>
++[FOOTER]
+\ No newline at end of file
+diff --git a/tools/grit/grit/testdata/structure_variables.html b/tools/grit/grit/testdata/structure_variables.html
+new file mode 100644
+index 0000000000..2a15de8072
+--- /dev/null
++++ b/tools/grit/grit/testdata/structure_variables.html
+@@ -0,0 +1,4 @@
++<h1>[GREETING]!</h1>
++Some cool things are [THINGS].
++Did you know that [EQUATION]?
++<include src="[filename].html">
+diff --git a/tools/grit/grit/testdata/substitute.grd b/tools/grit/grit/testdata/substitute.grd
+new file mode 100644
+index 0000000000..95dcc56e1d
+--- /dev/null
++++ b/tools/grit/grit/testdata/substitute.grd
+@@ -0,0 +1,31 @@
++<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
++<grit
++ base_dir="."
++ source_lang_id="en"
++ tc_project="GoogleDesktopWindowsClient"
++ latest_public_release="0"
++ current_release="1"
++ enc_check="möl">
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
++ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
++ </outputs>
++ <translations>
++ <file path="substitute.xmb" lang="sv" />
++ </translations>
++ <release seq="1" allow_pseudo="false">
++ <messages first_id="8192">
++ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
++ Copyright 2008 Google Inc. All Rights Reserved.
++ </message>
++ <message name="IDS_NEWS_PANEL_COPYRIGHT">
++ Google Desktop News gadget
++[IDS_COPYRIGHT_GOOGLE_LONG]
++View news that is personalized based on the articles you read.
++
++For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
++ </message>
++ </messages>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/testdata/substitute.xmb b/tools/grit/grit/testdata/substitute.xmb
+new file mode 100644
+index 0000000000..e592069c8b
+--- /dev/null
++++ b/tools/grit/grit/testdata/substitute.xmb
+@@ -0,0 +1,10 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE translationbundle SYSTEM "/home/build/nonconf/google3/i18n/translationbundle.dtd">
++<translationbundle lang="sv">
++<translation id="7239109800378180620">© 2008 Google Inc. Med ensamrätt.</translation>
++<translation id="6212022020330010625">Google Desktop News gadget
++<ph name="IDS_COPYRIGHT_GOOGLE_LONG_1"/>
++Se nyheter som är anpassade till dig, baserat på de artiklar du läser.
++
++Om du t.ex. läser massor av sportnyheter kommer du att se fler sportartiklar. Om du inte läser tekniknyheter lika ofta ser du färre av dessa artiklar.</translation>
++</translationbundle>
+diff --git a/tools/grit/grit/testdata/substitute_no_ids.grd b/tools/grit/grit/testdata/substitute_no_ids.grd
+new file mode 100644
+index 0000000000..d569d1cacd
+--- /dev/null
++++ b/tools/grit/grit/testdata/substitute_no_ids.grd
+@@ -0,0 +1,31 @@
++<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
++<grit
++ base_dir="."
++ source_lang_id="en"
++ tc_project="GoogleDesktopWindowsClient"
++ latest_public_release="0"
++ current_release="1"
++ enc_check="möl">
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
++ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
++ </outputs>
++ <translations>
++ <file path="substitute.xmb" lang="sv" />
++ </translations>
++ <release seq="1" allow_pseudo="false">
++ <messages>
++ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
++ Copyright 2008 Google Inc. All Rights Reserved.
++ </message>
++ <message name="IDS_NEWS_PANEL_COPYRIGHT">
++ Google Desktop News gadget
++[IDS_COPYRIGHT_GOOGLE_LONG]
++View news that is personalized based on the articles you read.
++
++For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
++ </message>
++ </messages>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/testdata/substitute_tmpl.grd b/tools/grit/grit/testdata/substitute_tmpl.grd
+new file mode 100644
+index 0000000000..be7b601707
+--- /dev/null
++++ b/tools/grit/grit/testdata/substitute_tmpl.grd
+@@ -0,0 +1,31 @@
++<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
++<grit
++ base_dir="."
++ source_lang_id="en"
++ tc_project="GoogleDesktopWindowsClient"
++ latest_public_release="0"
++ current_release="1"
++ enc_check="möl">
++ <outputs>
++ <output filename="resource.h" type="rc_header" />
++ <output filename="en_${name}_resources.rc" type="rc_all" lang="en" />
++ <output filename="sv_${name}_resources.rc" type="rc_all" lang="sv" />
++ </outputs>
++ <translations>
++ <file path="substitute.xmb" lang="sv" />
++ </translations>
++ <release seq="1" allow_pseudo="false">
++ <messages first_id="8192">
++ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
++ Copyright 2008 Google Inc. All Rights Reserved.
++ </message>
++ <message name="IDS_NEWS_PANEL_COPYRIGHT">
++ Google Desktop News gadget
++[IDS_COPYRIGHT_GOOGLE_LONG]
++View news that is personalized based on the articles you read.
++
++For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
++ </message>
++ </messages>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/testdata/test_css.css b/tools/grit/grit/testdata/test_css.css
+new file mode 100644
+index 0000000000..55d5dd1770
+--- /dev/null
++++ b/tools/grit/grit/testdata/test_css.css
+@@ -0,0 +1 @@
++This is a test!
+diff --git a/tools/grit/grit/testdata/test_html.html b/tools/grit/grit/testdata/test_html.html
+new file mode 100644
+index 0000000000..55d5dd1770
+--- /dev/null
++++ b/tools/grit/grit/testdata/test_html.html
+@@ -0,0 +1 @@
++This is a test!
+diff --git a/tools/grit/grit/testdata/test_js.js b/tools/grit/grit/testdata/test_js.js
+new file mode 100644
+index 0000000000..55d5dd1770
+--- /dev/null
++++ b/tools/grit/grit/testdata/test_js.js
+@@ -0,0 +1 @@
++This is a test!
+diff --git a/tools/grit/grit/testdata/test_svg.svg b/tools/grit/grit/testdata/test_svg.svg
+new file mode 100644
+index 0000000000..55d5dd1770
+--- /dev/null
++++ b/tools/grit/grit/testdata/test_svg.svg
+@@ -0,0 +1 @@
++This is a test!
+diff --git a/tools/grit/grit/testdata/test_text.txt b/tools/grit/grit/testdata/test_text.txt
+new file mode 100644
+index 0000000000..55d5dd1770
+--- /dev/null
++++ b/tools/grit/grit/testdata/test_text.txt
+@@ -0,0 +1 @@
++This is a test!
+diff --git a/tools/grit/grit/testdata/time_related.html b/tools/grit/grit/testdata/time_related.html
+new file mode 100644
+index 0000000000..ee64b1665e
+--- /dev/null
++++ b/tools/grit/grit/testdata/time_related.html
+@@ -0,0 +1,11 @@
++[HEADER]
++[CHROME]
++[NAV_PRE_POST]
++[$~MESSAGE~$]<br>
++<table border=0 cellpadding=2 cellspacing=0 width='100%'>
++[CONTENTS]
++</table><br>
++
++[NAV_PRE_POST]
++[FOOTER]
++
+diff --git a/tools/grit/grit/testdata/toolbar_about.html b/tools/grit/grit/testdata/toolbar_about.html
+new file mode 100644
+index 0000000000..bb4b0eb355
+--- /dev/null
++++ b/tools/grit/grit/testdata/toolbar_about.html
+@@ -0,0 +1,138 @@
++<html id=dlgAbout STYLE="width: 25.8em; height: 17em" [GRITDIR]>
++<head>
++<meta http-equiv="content-type" content="text/html; charset=utf-8">
++<title>About Google Toolbar</title>
++<style>
++.button {
++ width: 7em;
++ height: 2.2em;
++ color: buttontext;
++ font-family: MS Sans Serif;
++ font-size:8pt;
++ cursor: hand;
++}
++</style>
++
++<script> <!--
++ function HandleError(message, url, line) {
++ var L_Dialog_ErrorMessage = "An error has occured in this dialog.";
++ var L_ErrorNumber_Text = "Error: ";
++ var str = L_Dialog_ErrorMessage + "\n\n"
++ + L_ErrorNumber_Text + line + "\n"
++ + message;
++ alert (str);
++ window.close();
++ return true;
++ }
++
++ function OnKeyPress(nCode) {
++ if (nCode == 27) {
++ window.close();
++ return;
++ }
++ }
++
++ function OnLoad() {
++ if ((null != window.dialogArguments) && (window.dialogArguments.indexOf("&") == -1) && (window.dialogArguments.indexOf("<") == -1)) {
++ version.innerHTML = window.dialogArguments;
++ } else {
++ version.innerText = "Version: Unknown";
++ }
++ }
++
++ window.onerror = HandleError;
++ // -->
++</script>
++
++</head>
++
++
++<body bgcolor="#FFFFFF" onload="OnLoad()" onkeydown="OnKeyPress(event.keyCode)" onkeypress="OnKeyPress(event.keyCode)" scroll=no>
++
++<table border=0>
++
++ <tr height=5>
++ <td width=5></td>
++ <td></td>
++ <td></td>
++ <td></td>
++ <td width=5></td>
++ </tr>
++
++ <tr>
++ <td></td>
++ <td colspan=3>
++
++
++<table border="0" cellpadding="0" cellspacing="0" valign="top">
++ <tr>
++ <td valign="top" height="47" width="155">
++ <div align="center"><img src="title_toolbar.gif" width="275" height="59" alt="Google Toolbar"></div>
++ </td>
++ <td valign="middle" height="47" width="713">
++ <hr size=1 color=25479D></td></tr>
++</table>
++
++
++ </td>
++ <!--
++ <TD colspan=2>
++ <span style="COLOR: black; FONT: 18pt Tahoma, MS Shell Dlg"><b>
++ Google Toolbar&trade;</b>
++ </span>
++ </TD>
++ -->
++ <td valign="middle">
++ </td>
++ </tr>
++
++ <tr>
++ <td></td>
++ <td align=center><img src="googly.gif"></td>
++ <td colspan=2 align=left>
++ <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
++ <span id=version></span><br>
++ </span>
++ </td>
++ <td></td>
++ </tr>
++
++ <tr height=50>
++ <td></td>
++ <td></td>
++ <td colspan=2 align=left>
++ <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
++ <!--$/translate-->
++ <i>De parvis grandis acervus erit</i>
++ <!--$translate-->
++ </span>
++ </td>
++ <td></td>
++ </tr>
++
++ <tr height=40>
++ <td></td>
++ <td></td>
++ <td></td>
++ <td></td>
++ <td></td>
++ </tr>
++
++ <tr>
++ <td></td>
++ <td width=80></td>
++ <td>
++ <!--$/translate-->
++ <span style="WIDTH: 20em; COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg" id="copyright">&copy; 2006 Google</span>
++ <!--$translate-->
++ </td>
++ <td id=ok-button align=right><button tabindex=1 type=submit align=right id="okButton" class=button onClick="window.close();" >OK</button>
++ </td>
++ <td></td>
++ </tr>
++
++</table>
++</span>
++
++</body>
++</html>
+diff --git a/tools/grit/grit/testdata/tools/grit/resource_ids b/tools/grit/grit/testdata/tools/grit/resource_ids
+new file mode 100644
+index 0000000000..8a2b608df1
+--- /dev/null
++++ b/tools/grit/grit/testdata/tools/grit/resource_ids
+@@ -0,0 +1,176 @@
++# Copyright (c) 2011 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++#
++# This file is used to assign starting resource ids for resources and strings
++# used by Chromium. This is done to ensure that resource ids are unique
++# across all the grd files. If you are adding a new grd file, please add
++# a new entry to this file.
++#
++# The first entry in the file, SRCDIR, is special: It is a relative path from
++# this file to the base of your checkout.
++#
++# http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx says that the
++# range for IDR_ is 1 to 28,671 and the range for IDS_ is 1 to 32,767 and
++# common convention starts practical use of IDs at 100 or 101.
++{
++ "SRCDIR": "../..",
++
++ "chrome/browser/browser_resources.grd": {
++ "includes": [500],
++ },
++ "chrome/browser/resources/component_extension_resources.grd": {
++ "includes": [1000],
++ },
++ "chrome/browser/resources/net_internals_resources.grd": {
++ "includes": [1500],
++ },
++ "chrome/browser/resources/shared_resources.grd": {
++ "includes": [2000],
++ },
++ "chrome/common/common_resources.grd": {
++ "includes": [2500],
++ },
++ "chrome/default_plugin/default_plugin_resources.grd": {
++ "includes": [3000],
++ },
++ "chrome/renderer/renderer_resources.grd": {
++ "includes": [3500],
++ },
++ "net/base/net_resources.grd": {
++ "includes": [4000],
++ },
++ "webkit/glue/webkit_resources.grd": {
++ "includes": [4500],
++ },
++ "webkit/tools/test_shell/test_shell_resources.grd": {
++ "includes": [5000],
++ },
++ "ui/resources/ui_resources.grd": {
++ "includes": [5500],
++ },
++ "chrome/app/theme/theme_resources.grd": {
++ "includes": [6000],
++ },
++ "chrome_frame/resources/chrome_frame_resources.grd": {
++ "includes": [6500],
++ },
++ # WebKit.grd can be in two different places depending on whether we are
++ # in a chromium checkout or a webkit-only checkout.
++ "third_party/WebKit/Source/WebKit/chromium/WebKit.grd": {
++ "includes": [7000],
++ },
++ "WebKit.grd": {
++ "includes": [7000],
++ },
++
++ "ui/base/strings/app_locale_settings.grd": {
++ "META": {"join": 2},
++ "messages": [7500],
++ },
++ "chrome/app/resources/locale_settings.grd": {
++ "includes": [8000],
++ "messages": [8500],
++ },
++ # These each start with the same resource id because we only use one
++ # file for each build (cros, linux, mac, or win).
++ "chrome/app/resources/locale_settings_cros.grd": {
++ "messages": [9000],
++ },
++ "chrome/app/resources/locale_settings_linux.grd": {
++ "messages": [9000],
++ },
++ "chrome/app/resources/locale_settings_mac.grd": {
++ "messages": [9000],
++ },
++ "chrome/app/resources/locale_settings_win.grd": {
++ "messages": [9000],
++ },
++
++ "ui/base/strings/ui_strings.grd": {
++ "META": {"join": 4},
++ "messages": [9500],
++ },
++ # Chromium strings and Google Chrome strings must start at the same id.
++ # We only use one file depending on whether we're building Chromium or
++ # Google Chrome.
++ "chrome/app/chromium_strings.grd": {
++ "messages": [10000],
++ },
++ "chrome/app/google_chrome_strings.grd": {
++ "messages": [10000],
++ },
++ # Leave lots of space for generated_resources since it has most of our
++ # strings.
++ "chrome/app/generated_resources.grd": {
++ "META": {"join": 2},
++ "structures": [10500],
++ "messages": [11000],
++ },
++ # The chrome frame dialogs are also in generated_resources.grd so they
++ # get included by the translation console. We make sure that the ids
++ # for structures here are the same as for generated_resources.grd.
++ "chrome_frame/resources/chrome_frame_dialogs.grd": {
++ "structures": [10500],
++ "includes": [10750],
++ },
++ "webkit/glue/inspector_strings.grd": {
++ "messages": [16000],
++ },
++ "webkit/glue/webkit_strings.grd": {
++ "messages": [16500],
++ },
++
++ "chrome_frame/resources/chrome_frame_resources.grd": {
++ "includes": [17500],
++ "structures": [18000],
++ },
++
++ "ui/gfx/gfx_resources.grd": {
++ "includes": [18500],
++ },
++
++ "chrome/app/policy/policy_templates.grd": {
++ "structures": [19000],
++ "messages": [19010],
++ },
++
++ "chrome/browser/autofill/autofill_resources.grd": {
++ "messages": [19500],
++ },
++ "chrome/browser/resources/sync_internals_resources.grd": {
++ "includes": [20000],
++ },
++ # This file is generated during the build.
++ "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd": {
++ "includes": [20500],
++ },
++ # All standard and large theme resources should have the same IDs.
++ "chrome/app/theme/theme_resources_standard.grd": {
++ "includes": [21000],
++ },
++ "chrome/app/theme/theme_resources_large.grd": {
++ "includes": [21000],
++ },
++ # This file is generated during the build.
++ "chrome/browser/debugger/frontend/devtools_frontend_resources.grd": {
++ "META": {"join": 2},
++ "includes": [21500],
++ },
++ "cloud_print/virtual_driver/win/install/virtual_driver_setup_resources.grd": {
++ "messages": [22500],
++ },
++ "chrome/browser/resources/quota_internals_resources.grd": {
++ "includes": [23000],
++ },
++ "chrome/browser/resources/workers_resources.grd": {
++ "includes": [23500],
++ },
++ # All standard and large theme resources should have the same IDs.
++ "ui/resources/ui_resources_standard.grd": {
++ "includes": [24000],
++ },
++ "ui/resources/ui_resources_large.grd": {
++ "includes": [24000],
++ },
++}
+diff --git a/tools/grit/grit/testdata/transl.rc b/tools/grit/grit/testdata/transl.rc
+new file mode 100644
+index 0000000000..2f2595db3f
+--- /dev/null
++++ b/tools/grit/grit/testdata/transl.rc
+@@ -0,0 +1,56 @@
++IDC_KLONKMENU MENU
++BEGIN
++ POPUP "&Skra"
++ BEGIN
++ MENUITEM "&Haetta", IDM_EXIT
++ MENUITEM "Thetta er ""Klonk"" sem eg fyla", ID_FILE_THISBE
++ POPUP "gonkurinn"
++ BEGIN
++ MENUITEM "Klonk && er [good]", ID_GONK_KLONKIS
++ END
++ END
++ POPUP "&Hjalp"
++ BEGIN
++ MENUITEM "&Um...", IDM_ABOUT
++ END
++END
++
++IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "Um Klonk"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
++ LTEXT "klonk utgafa ""jibbi"" 1.0",IDC_STATIC,49,10,119,8,
++ SS_NOPREFIX
++ LTEXT "Hofundarrettur (C) 2005",IDC_STATIC,49,20,119,8
++ DEFPUSHBUTTON "I lagi",IDOK,195,6,30,11,WS_GROUP
++ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
++ BS_AUTORADIOBUTTON,46,51,84,10
++END
++
++IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
++STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
++CAPTION "Bingobobbi"
++FONT 8, "System", 0, 0, 0x0
++BEGIN
++ LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
++END
++
++STRINGTABLE
++BEGIN
++ IDS_SIMPLE "Ein"
++ IDS_PLACEHOLDER "%s Vogeln"
++ IDS_PLACEHOLDERS "%d von %d"
++ // Shouldn't be part of translations list because the translation is
++ // reordered so placeholder fixup fails
++ IDS_REORDERED_PLACEHOLDERS "$2 auf $1"
++ IDS_CHANGED "Dass war die alte Version"
++ IDS_TWIN_1 "Hallo"
++ IDS_TWIN_2 "Hallo"
++ IDS_NOT_TRANSLATEABLE ":"
++ IDS_LONGER_TRANSLATED "Dokument $1 ist entfernt worden"
++ IDS_NO_LONGER_USED "Nicht verwendet"
++ IDS_DIFFERENT_TWIN_1 "Howdie"
++ IDS_DIFFERENT_TWIN_2 "Hallo sagt man"
++END
+diff --git a/tools/grit/grit/testdata/versions.html b/tools/grit/grit/testdata/versions.html
+new file mode 100644
+index 0000000000..d1f40d8d72
+--- /dev/null
++++ b/tools/grit/grit/testdata/versions.html
+@@ -0,0 +1,7 @@
++[HEADER]
++
++[TOP_CHROME]
++[CONTENTS]
++
++[NEXT_PREV]
++[FOOTER]
+diff --git a/tools/grit/grit/testdata/whitelist.txt b/tools/grit/grit/testdata/whitelist.txt
+new file mode 100644
+index 0000000000..5b3aca40b5
+--- /dev/null
++++ b/tools/grit/grit/testdata/whitelist.txt
+@@ -0,0 +1,4 @@
++IDS_MESSAGE_WHITELISTED
++IDR_STRUCTURE_WHITELISTED
++IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED
++IDR_INCLUDE_WHITELISTED
+diff --git a/tools/grit/grit/testdata/whitelist_resources.grd b/tools/grit/grit/testdata/whitelist_resources.grd
+new file mode 100644
+index 0000000000..9925688ff5
+--- /dev/null
++++ b/tools/grit/grit/testdata/whitelist_resources.grd
+@@ -0,0 +1,54 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="0"
++ current_release="1"
++ output_all_resource_defines="false">
++ <outputs>
++ <output filename="whitelist_test_resources.h" type="rc_header">
++ <emit emit_type='prepend'></emit>
++ </output>
++ <output filename="whitelist_test_resources_map.cc"
++ type="resource_file_map_source" />
++ <output filename="whitelist_test_resources_map.h"
++ type="resource_map_header" />
++ <output filename="whitelist_test_resources.pak" type="data_package" />
++ </outputs>
++ <translations>
++ <file path="substitute.xmb" lang="sv" />
++ </translations>
++ <release seq="1">
++ <structures>
++ <structure name="IDR_STRUCTURE_WHITELISTED" file="browser.html"
++ type="chrome_html" >
++ </structure>
++ <structure name="IDR_STRUCTURE_NOT_WHITELISTED" file="deleted.html"
++ type="chrome_html" >
++ </structure>
++ <if expr="True">
++ <structure name="IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED"
++ file="details.html"
++ type="chrome_html" >
++ </structure>
++ <structure name="IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED"
++ file="error.html"
++ type="chrome_html" >
++ </structure>
++ </if>
++ <if expr="False">
++ <structure name="IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED"
++ file="status.html"
++ type="chrome_html" >
++ </structure>
++ <structure name="IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED"
++ file="simple.html"
++ type="chrome_html" >
++ </structure>
++ </if>
++ </structures>
++ <includes>
++ <include name="IDR_INCLUDE_WHITELISTED" file="klonk.ico"
++ type="BINDATA" />
++ <include name="IDR_INCLUDE_NOT_WHITELISTED" file="klonk.rc"
++ type="BINDATA" />
++ </includes>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/testdata/whitelist_strings.grd b/tools/grit/grit/testdata/whitelist_strings.grd
+new file mode 100644
+index 0000000000..df80f5fd32
+--- /dev/null
++++ b/tools/grit/grit/testdata/whitelist_strings.grd
+@@ -0,0 +1,23 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grit latest_public_release="0"
++ current_release="1"
++ output_all_resource_defines="false">
++ <outputs >
++ <output filename="whitelist_test_resources.h" type="rc_header">
++ <emit emit_type='prepend'></emit>
++ </output>
++ <output filename="en_whitelist_test_strings.rc" type="rc_all" lang="en" />
++ </outputs>
++ <release seq="1">
++ <messages>
++ <message name="IDS_MESSAGE_WHITELISTED"
++ desc="A message in the whiltelist file.">
++ Whitelisted.
++ </message>
++ <message name="IDS_MESSAGE_NOT_WHITELISTED"
++ desc="A message that isn't in the whiltelist file.">
++ Not whitelisted.
++ </message>
++ </messages>
++ </release>
++</grit>
+diff --git a/tools/grit/grit/tool/__init__.py b/tools/grit/grit/tool/__init__.py
+new file mode 100644
+index 0000000000..cc455b36e7
+--- /dev/null
++++ b/tools/grit/grit/tool/__init__.py
+@@ -0,0 +1,8 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Package grit.tool
++'''
++
++pass
+diff --git a/tools/grit/grit/tool/android2grd.py b/tools/grit/grit/tool/android2grd.py
+new file mode 100644
+index 0000000000..005297bafe
+--- /dev/null
++++ b/tools/grit/grit/tool/android2grd.py
+@@ -0,0 +1,484 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""The 'grit android2grd' tool."""
++
++from __future__ import print_function
++
++import getopt
++import os.path
++import sys
++from xml.dom import Node
++import xml.dom.minidom
++
++import six
++from six import StringIO
++
++import grit.node.empty
++from grit.node import node_io
++from grit.node import message
++
++from grit.tool import interface
++
++from grit import grd_reader
++from grit import lazy_re
++from grit import tclib
++
++
++# The name of a string in strings.xml
++_STRING_NAME = lazy_re.compile(r'[a-z0-9_]+\Z')
++
++# A string's character limit in strings.xml
++_CHAR_LIMIT = lazy_re.compile(r'\[CHAR-LIMIT=(\d+)\]')
++
++# Finds String.Format() style format specifiers such as "%-5.2f".
++_FORMAT_SPECIFIER = lazy_re.compile(
++ r'%'
++ r'([1-9][0-9]*\$|<)?' # argument_index
++ r'([-#+ 0,(]*)' # flags
++ r'([0-9]+)?' # width
++ r'(\.[0-9]+)?' # precision
++ r'([bBhHsScCdoxXeEfgGaAtT%n])') # conversion
++
++
++class Android2Grd(interface.Tool):
++ """Tool for converting Android string.xml files into chrome Grd files.
++
++Usage: grit [global options] android2grd [OPTIONS] STRINGS_XML
++
++The Android2Grd tool will convert an Android strings.xml file (whose path is
++specified by STRINGS_XML) and create a chrome style grd file containing the
++relevant information.
++
++Because grd documents are much richer than strings.xml documents we supplement
++the information required by grds using OPTIONS with sensible defaults.
++
++OPTIONS may be any of the following:
++
++ --name FILENAME Specify the base FILENAME. This should be without
++ any file type suffix. By default
++ "chrome_android_strings" will be used.
++
++ --languages LANGUAGES Comma separated list of ISO language codes (e.g.
++ en-US, en-GB, ru, zh-CN). These codes will be used
++ to determine the names of resource and translations
++ files that will be declared by the output grd file.
++
++ --grd-dir GRD_DIR Specify where the resultant grd file
++ (FILENAME.grd) should be output. By default this
++ will be the present working directory.
++
++ --header-dir HEADER_DIR Specify the location of the directory where grit
++ generated C++ headers (whose name will be
++ FILENAME.h) will be placed. Use an empty string to
++ disable rc generation. Default: empty.
++
++ --rc-dir RC_DIR Specify the directory where resource files will
++ be located relative to grit build's output
++ directory. Use an empty string to disable rc
++ generation. Default: empty.
++
++ --xml-dir XML_DIR Specify where to place localized strings.xml files
++ relative to grit build's output directory. For each
++ language xx a values-xx/strings.xml file will be
++ generated. Use an empty string to disable
++ strings.xml generation. Default: '.'.
++
++ --xtb-dir XTB_DIR Specify where the xtb files containing translations
++ will be located relative to the grd file. Default:
++ '.'.
++"""
++
++ _NAME_FLAG = 'name'
++ _LANGUAGES_FLAG = 'languages'
++ _GRD_DIR_FLAG = 'grd-dir'
++ _RC_DIR_FLAG = 'rc-dir'
++ _HEADER_DIR_FLAG = 'header-dir'
++ _XTB_DIR_FLAG = 'xtb-dir'
++ _XML_DIR_FLAG = 'xml-dir'
++
++ def __init__(self):
++ self.name = 'chrome_android_strings'
++ self.languages = []
++ self.grd_dir = '.'
++ self.rc_dir = None
++ self.xtb_dir = '.'
++ self.xml_res_dir = '.'
++ self.header_dir = None
++
++ def ShortDescription(self):
++ """Returns a short description of the Android2Grd tool.
++
++ Overridden from grit.interface.Tool
++
++ Returns:
++ A string containing a short description of the android2grd tool.
++ """
++ return 'Converts Android string.xml files into Chrome grd files.'
++
++ def ParseOptions(self, args):
++ """Set this objects and return all non-option arguments."""
++ flags = [
++ Android2Grd._NAME_FLAG,
++ Android2Grd._LANGUAGES_FLAG,
++ Android2Grd._GRD_DIR_FLAG,
++ Android2Grd._RC_DIR_FLAG,
++ Android2Grd._HEADER_DIR_FLAG,
++ Android2Grd._XTB_DIR_FLAG,
++ Android2Grd._XML_DIR_FLAG, ]
++ (opts, args) = getopt.getopt(
++ args, None, ['%s=' % o for o in flags] + ['help'])
++
++ for key, val in opts:
++ # Get rid of the preceding hypens.
++ k = key[2:]
++ if k == Android2Grd._NAME_FLAG:
++ self.name = val
++ elif k == Android2Grd._LANGUAGES_FLAG:
++ self.languages = val.split(',')
++ elif k == Android2Grd._GRD_DIR_FLAG:
++ self.grd_dir = val
++ elif k == Android2Grd._RC_DIR_FLAG:
++ self.rc_dir = val
++ elif k == Android2Grd._HEADER_DIR_FLAG:
++ self.header_dir = val
++ elif k == Android2Grd._XTB_DIR_FLAG:
++ self.xtb_dir = val
++ elif k == Android2Grd._XML_DIR_FLAG:
++ self.xml_res_dir = val
++ elif k == 'help':
++ self.ShowUsage()
++ sys.exit(0)
++ return args
++
++ def Run(self, opts, args):
++ """Runs the Android2Grd tool.
++
++ Inherited from grit.interface.Tool.
++
++ Args:
++ opts: List of string arguments that should be parsed.
++ args: String containing the path of the strings.xml file to be converted.
++ """
++ args = self.ParseOptions(args)
++ if len(args) != 1:
++ print('Tool requires one argument, the path to the Android '
++ 'strings.xml resource file to be converted.')
++ return 2
++ self.SetOptions(opts)
++
++ android_path = args[0]
++
++ # Read and parse the Android strings.xml file.
++ with open(android_path) as android_file:
++ android_dom = xml.dom.minidom.parse(android_file)
++
++ # Do the hard work -- convert the Android dom to grd file contents.
++ grd_dom = self.AndroidDomToGrdDom(android_dom)
++ grd_string = six.text_type(grd_dom)
++
++ # Write the grd string to a file in grd_dir.
++ grd_filename = self.name + '.grd'
++ grd_path = os.path.join(self.grd_dir, grd_filename)
++ with open(grd_path, 'w') as grd_file:
++ grd_file.write(grd_string)
++
++ def AndroidDomToGrdDom(self, android_dom):
++ """Converts a strings.xml DOM into a DOM representing the contents of
++ a grd file.
++
++ Args:
++ android_dom: A xml.dom.Document containing the contents of the Android
++ string.xml document.
++ Returns:
++ The DOM for the grd xml document produced by converting the Android DOM.
++ """
++
++ # Start with a basic skeleton for the .grd file.
++ root = grd_reader.Parse(StringIO(
++ '''<?xml version="1.0" encoding="UTF-8"?>
++ <grit base_dir="." latest_public_release="0"
++ current_release="1" source_lang_id="en">
++ <outputs />
++ <translations />
++ <release allow_pseudo="false" seq="1">
++ <messages fallback_to_english="true" />
++ </release>
++ </grit>'''), dir='.')
++ outputs = root.children[0]
++ translations = root.children[1]
++ messages = root.children[2].children[0]
++ assert (isinstance(messages, grit.node.empty.MessagesNode) and
++ isinstance(translations, grit.node.empty.TranslationsNode) and
++ isinstance(outputs, grit.node.empty.OutputsNode))
++
++ if self.header_dir:
++ cpp_header = self.__CreateCppHeaderOutputNode(outputs, self.header_dir)
++ for lang in self.languages:
++ # Create an output element for each language.
++ if self.rc_dir:
++ self.__CreateRcOutputNode(outputs, lang, self.rc_dir)
++ if self.xml_res_dir:
++ self.__CreateAndroidXmlOutputNode(outputs, lang, self.xml_res_dir)
++ if lang != 'en':
++ self.__CreateFileNode(translations, lang)
++ # Convert all the strings.xml strings into grd messages.
++ self.__CreateMessageNodes(messages, android_dom.documentElement)
++
++ return root
++
++ def __CreateMessageNodes(self, messages, resources):
++ """Creates the <message> elements and adds them as children of <messages>.
++
++ Args:
++ messages: the <messages> element in the strings.xml dom.
++ resources: the <resources> element in the grd dom.
++ """
++ # <string> elements contain the definition of the resource.
++ # The description of a <string> element is contained within the comment
++ # node element immediately preceeding the string element in question.
++ description = ''
++ for child in resources.childNodes:
++ if child.nodeType == Node.COMMENT_NODE:
++ # Remove leading/trailing whitespace; collapse consecutive whitespaces.
++ description = ' '.join(child.data.split())
++ elif child.nodeType == Node.ELEMENT_NODE:
++ if child.tagName != 'string':
++ print('Warning: ignoring unknown tag <%s>' % child.tagName)
++ else:
++ translatable = self.IsTranslatable(child)
++ raw_name = child.getAttribute('name')
++ if not _STRING_NAME.match(raw_name):
++ print('Error: illegal string name: %s' % raw_name)
++ grd_name = 'IDS_' + raw_name.upper()
++ # Transform the <string> node contents into a tclib.Message, taking
++ # care to handle whitespace transformations and escaped characters,
++ # and coverting <xliff:g> placeholders into <ph> placeholders.
++ msg = self.CreateTclibMessage(child)
++ msg_node = self.__CreateMessageNode(messages, grd_name, description,
++ msg, translatable)
++ messages.AddChild(msg_node)
++ # Reset the description once a message has been parsed.
++ description = ''
++
++ def CreateTclibMessage(self, android_string):
++ """Transforms a <string/> element from strings.xml into a tclib.Message.
++
++ Interprets whitespace, quotes, and escaped characters in the android_string
++ according to Android's formatting and styling rules for strings. Also
++ converts <xliff:g> placeholders into <ph> placeholders, e.g.:
++
++ <xliff:g id="website" example="google.com">%s</xliff:g>
++ becomes
++ <ph name="website"><ex>google.com</ex>%s</ph>
++
++ Returns:
++ The tclib.Message.
++ """
++ msg = tclib.Message()
++ current_text = '' # Accumulated text that hasn't yet been added to msg.
++ nodes = android_string.childNodes
++
++ for i, node in enumerate(nodes):
++ # Handle text nodes.
++ if node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
++ current_text += node.data
++
++ # Handle <xliff:g> and other tags.
++ elif node.nodeType == Node.ELEMENT_NODE:
++ if node.tagName == 'xliff:g':
++ assert node.hasAttribute('id'), 'missing id: ' + node.data()
++ placeholder_id = node.getAttribute('id')
++ placeholder_text = self.__FormatPlaceholderText(node)
++ placeholder_example = node.getAttribute('example')
++ if not placeholder_example:
++ print('Info: placeholder does not contain an example: %s' %
++ node.toxml())
++ placeholder_example = placeholder_id.upper()
++ msg.AppendPlaceholder(tclib.Placeholder(placeholder_id,
++ placeholder_text, placeholder_example))
++ else:
++ print('Warning: removing tag <%s> which must be inside a '
++ 'placeholder: %s' % (node.tagName, node.toxml()))
++ msg.AppendText(self.__FormatPlaceholderText(node))
++
++ # Handle other nodes.
++ elif node.nodeType != Node.COMMENT_NODE:
++ assert False, 'Unknown node type: %s' % node.nodeType
++
++ is_last_node = (i == len(nodes) - 1)
++ if (current_text and
++ (is_last_node or nodes[i + 1].nodeType == Node.ELEMENT_NODE)):
++ # For messages containing just text and comments (no xml tags) Android
++ # strips leading and trailing whitespace. We mimic that behavior.
++ if not msg.GetContent() and is_last_node:
++ current_text = current_text.strip()
++ msg.AppendText(self.__FormatAndroidString(current_text))
++ current_text = ''
++
++ return msg
++
++ def __FormatAndroidString(self, android_string, inside_placeholder=False):
++ r"""Returns android_string formatted for a .grd file.
++
++ * Collapses consecutive whitespaces, except when inside double-quotes.
++ * Replaces \\, \n, \t, \", \' with \, newline, tab, ", '.
++ """
++ backslash_map = {'\\' : '\\', 'n' : '\n', 't' : '\t', '"' : '"', "'" : "'"}
++ is_quoted_section = False # True when we're inside double quotes.
++ is_backslash_sequence = False # True after seeing an unescaped backslash.
++ prev_char = ''
++ output = []
++ for c in android_string:
++ if is_backslash_sequence:
++ # Unescape \\, \n, \t, \", and \'.
++ assert c in backslash_map, 'Illegal escape sequence: \\%s' % c
++ output.append(backslash_map[c])
++ is_backslash_sequence = False
++ elif c == '\\':
++ is_backslash_sequence = True
++ elif c.isspace() and not is_quoted_section:
++ # Turn whitespace into ' ' and collapse consecutive whitespaces.
++ if not prev_char.isspace():
++ output.append(' ')
++ elif c == '"':
++ is_quoted_section = not is_quoted_section
++ else:
++ output.append(c)
++ prev_char = c
++ output = ''.join(output)
++
++ if is_quoted_section:
++ print('Warning: unbalanced quotes in string: %s' % android_string)
++
++ if is_backslash_sequence:
++ print('Warning: trailing backslash in string: %s' % android_string)
++
++ # Check for format specifiers outside of placeholder tags.
++ if not inside_placeholder:
++ format_specifier = _FORMAT_SPECIFIER.search(output)
++ if format_specifier:
++ print('Warning: format specifiers are not inside a placeholder '
++ '<xliff:g/> tag: %s' % output)
++
++ return output
++
++ def __FormatPlaceholderText(self, placeholder_node):
++ """Returns the text inside of an <xliff:g> placeholder node."""
++ text = []
++ for childNode in placeholder_node.childNodes:
++ if childNode.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
++ text.append(childNode.data)
++ elif childNode.nodeType != Node.COMMENT_NODE:
++ assert False, 'Unknown node type in ' + placeholder_node.toxml()
++ return self.__FormatAndroidString(''.join(text), inside_placeholder=True)
++
++ def __CreateMessageNode(self, messages_node, grd_name, description, msg,
++ translatable):
++ """Creates and initializes a <message> element.
++
++ Message elements correspond to Android <string> elements in that they
++ declare a string resource along with a programmatic id.
++ """
++ if not description:
++ print('Warning: no description for %s' % grd_name)
++ # Check that we actually fit within the character limit we've specified.
++ match = _CHAR_LIMIT.search(description)
++ if match:
++ char_limit = int(match.group(1))
++ msg_content = msg.GetRealContent()
++ if len(msg_content) > char_limit:
++ print('Warning: char-limit for %s is %d, but length is %d: %s' %
++ (grd_name, char_limit, len(msg_content), msg_content))
++ return message.MessageNode.Construct(parent=messages_node,
++ name=grd_name,
++ message=msg,
++ desc=description,
++ translateable=translatable)
++
++ def __CreateFileNode(self, translations_node, lang):
++ """Creates and initializes the <file> elements.
++
++ File elements provide information on the location of translation files
++ (xtbs)
++ """
++ xtb_file = os.path.normpath(os.path.join(
++ self.xtb_dir, '%s_%s.xtb' % (self.name, lang)))
++ fnode = node_io.FileNode()
++ fnode.StartParsing(u'file', translations_node)
++ fnode.HandleAttribute('path', xtb_file)
++ fnode.HandleAttribute('lang', lang)
++ fnode.EndParsing()
++ translations_node.AddChild(fnode)
++ return fnode
++
++ def __CreateCppHeaderOutputNode(self, outputs_node, header_dir):
++ """Creates the <output> element corresponding to the generated c header."""
++ header_file_name = os.path.join(header_dir, self.name + '.h')
++ header_node = node_io.OutputNode()
++ header_node.StartParsing(u'output', outputs_node)
++ header_node.HandleAttribute('filename', header_file_name)
++ header_node.HandleAttribute('type', 'rc_header')
++ emit_node = node_io.EmitNode()
++ emit_node.StartParsing(u'emit', header_node)
++ emit_node.HandleAttribute('emit_type', 'prepend')
++ emit_node.EndParsing()
++ header_node.AddChild(emit_node)
++ header_node.EndParsing()
++ outputs_node.AddChild(header_node)
++ return header_node
++
++ def __CreateRcOutputNode(self, outputs_node, lang, rc_dir):
++ """Creates the <output> element corresponding to various rc file output."""
++ rc_file_name = self.name + '_' + lang + ".rc"
++ rc_path = os.path.join(rc_dir, rc_file_name)
++ node = node_io.OutputNode()
++ node.StartParsing(u'output', outputs_node)
++ node.HandleAttribute('filename', rc_path)
++ node.HandleAttribute('lang', lang)
++ node.HandleAttribute('type', 'rc_all')
++ node.EndParsing()
++ outputs_node.AddChild(node)
++ return node
++
++ def __CreateAndroidXmlOutputNode(self, outputs_node, locale, xml_res_dir):
++ """Creates the <output> element corresponding to various rc file output."""
++ # Need to check to see if the locale has a region, e.g. the GB in en-GB.
++ # When a locale has a region Android expects the region to be prefixed
++ # with an 'r'. For example for en-GB Android expects a values-en-rGB
++ # directory. Also, Android expects nb, tl, in, iw, ji as the language
++ # codes for Norwegian, Tagalog/Filipino, Indonesian, Hebrew, and Yiddish:
++ # http://developer.android.com/reference/java/util/Locale.html
++ if locale == 'es-419':
++ android_locale = 'es-rUS'
++ else:
++ android_lang, dash, region = locale.partition('-')
++ lang_map = {'no': 'nb', 'fil': 'tl', 'id': 'in', 'he': 'iw', 'yi': 'ji'}
++ android_lang = lang_map.get(android_lang, android_lang)
++ android_locale = android_lang + ('-r' + region if region else '')
++ values = 'values-' + android_locale if android_locale != 'en' else 'values'
++ xml_path = os.path.normpath(os.path.join(
++ xml_res_dir, values, 'strings.xml'))
++
++ node = node_io.OutputNode()
++ node.StartParsing(u'output', outputs_node)
++ node.HandleAttribute('filename', xml_path)
++ node.HandleAttribute('lang', locale)
++ node.HandleAttribute('type', 'android')
++ node.EndParsing()
++ outputs_node.AddChild(node)
++ return node
++
++ def IsTranslatable(self, android_string):
++ """Determines if a <string> element is a candidate for translation.
++
++ A <string> element is by default translatable unless otherwise marked.
++ """
++ if android_string.hasAttribute('translatable'):
++ value = android_string.getAttribute('translatable').lower()
++ if value not in ('true', 'false'):
++ print('Warning: translatable attribute has invalid value: %s' % value)
++ return value == 'true'
++ else:
++ return True
+diff --git a/tools/grit/grit/tool/android2grd_unittest.py b/tools/grit/grit/tool/android2grd_unittest.py
+new file mode 100644
+index 0000000000..a6934a707c
+--- /dev/null
++++ b/tools/grit/grit/tool/android2grd_unittest.py
+@@ -0,0 +1,181 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.tool.android2grd'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++import xml.dom.minidom
++
++from grit import util
++from grit.node import empty
++from grit.node import message
++from grit.node import misc
++from grit.node import node_io
++from grit.tool import android2grd
++
++
++class Android2GrdUnittest(unittest.TestCase):
++
++ def __Parse(self, xml_string):
++ return xml.dom.minidom.parseString(xml_string).childNodes[0]
++
++ def testCreateTclibMessage(self):
++ tool = android2grd.Android2Grd()
++ msg = tool.CreateTclibMessage(self.__Parse(r'''
++ <string name="simple">A simple string</string>'''))
++ self.assertEqual(msg.GetRealContent(), 'A simple string')
++ msg = tool.CreateTclibMessage(self.__Parse(r'''
++ <string name="outer_whitespace">
++ Strip leading/trailing whitespace
++ </string>'''))
++ self.assertEqual(msg.GetRealContent(), 'Strip leading/trailing whitespace')
++ msg = tool.CreateTclibMessage(self.__Parse(r'''
++ <string name="inner_whitespace">Fold multiple spaces</string>'''))
++ self.assertEqual(msg.GetRealContent(), 'Fold multiple spaces')
++ msg = tool.CreateTclibMessage(self.__Parse(r'''
++ <string name="escaped_spaces">Retain \n escaped\t spaces</string>'''))
++ self.assertEqual(msg.GetRealContent(), 'Retain \n escaped\t spaces')
++ msg = tool.CreateTclibMessage(self.__Parse(r'''
++ <string name="quotes"> " Quotes preserve
++ whitespace" but only for "enclosed elements "
++ </string>'''))
++ self.assertEqual(msg.GetRealContent(), ''' Quotes preserve
++ whitespace but only for enclosed elements ''')
++ msg = tool.CreateTclibMessage(self.__Parse(
++ r'''<string name="escaped_characters">Escaped characters: \"\'\\\t\n'''
++ '</string>'))
++ self.assertEqual(msg.GetRealContent(), '''Escaped characters: "'\\\t\n''')
++ msg = tool.CreateTclibMessage(self.__Parse(
++ '<string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" '
++ 'name="placeholders">'
++ 'Open <xliff:g id="FILENAME" example="internet.html">%s</xliff:g>?'
++ '</string>'))
++ self.assertEqual(msg.GetRealContent(), 'Open %s?')
++ self.assertEqual(len(msg.GetPlaceholders()), 1)
++ self.assertEqual(msg.GetPlaceholders()[0].presentation, 'FILENAME')
++ self.assertEqual(msg.GetPlaceholders()[0].original, '%s')
++ self.assertEqual(msg.GetPlaceholders()[0].example, 'internet.html')
++ msg = tool.CreateTclibMessage(self.__Parse(r'''
++ <string name="comment">Contains a <!-- ignore this --> comment
++ </string>'''))
++ self.assertEqual(msg.GetRealContent(), 'Contains a comment')
++
++ def testIsTranslatable(self):
++ tool = android2grd.Android2Grd()
++ string_el = self.__Parse('<string>Hi</string>')
++ self.assertTrue(tool.IsTranslatable(string_el))
++ string_el = self.__Parse(
++ '<string translatable="true">Hi</string>')
++ self.assertTrue(tool.IsTranslatable(string_el))
++ string_el = self.__Parse(
++ '<string translatable="false">Hi</string>')
++ self.assertFalse(tool.IsTranslatable(string_el))
++
++ def __ParseAndroidXml(self, options = []):
++ tool = android2grd.Android2Grd()
++
++ tool.ParseOptions(options)
++
++ android_path = util.PathFromRoot('grit/testdata/android.xml')
++ with open(android_path) as android_file:
++ android_dom = xml.dom.minidom.parse(android_file)
++
++ grd = tool.AndroidDomToGrdDom(android_dom)
++ self.assertTrue(isinstance(grd, misc.GritNode))
++
++ return grd
++
++ def testAndroidDomToGrdDom(self):
++ grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru'])
++
++ # Check that the structure of the GritNode is as expected.
++ messages = grd.GetChildrenOfType(message.MessageNode)
++ translations = grd.GetChildrenOfType(empty.TranslationsNode)
++ files = grd.GetChildrenOfType(node_io.FileNode)
++
++ self.assertEqual(len(translations), 1)
++ self.assertEqual(len(files), 3)
++ self.assertEqual(len(messages), 5)
++
++ # Check that a message node is constructed correctly.
++ msg = [x for x in messages if x.GetTextualIds()[0] == 'IDS_PLACEHOLDERS']
++ self.assertTrue(msg)
++ msg = msg[0]
++
++ self.assertTrue(msg.IsTranslateable())
++ self.assertEqual(msg.attrs["desc"], "A string with placeholder.")
++
++ def testTranslatableAttribute(self):
++ grd = self.__ParseAndroidXml([])
++ messages = grd.GetChildrenOfType(message.MessageNode)
++ msgs = [x for x in messages if x.GetTextualIds()[0] == 'IDS_CONSTANT']
++ self.assertTrue(msgs)
++ self.assertFalse(msgs[0].IsTranslateable())
++
++ def testTranslations(self):
++ grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru,id'])
++
++ files = grd.GetChildrenOfType(node_io.FileNode)
++ us_file = [x for x in files if x.attrs['lang'] == 'en-US']
++ self.assertTrue(us_file)
++ self.assertEqual(us_file[0].GetInputPath(),
++ 'chrome_android_strings_en-US.xtb')
++
++ id_file = [x for x in files if x.attrs['lang'] == 'id']
++ self.assertTrue(id_file)
++ self.assertEqual(id_file[0].GetInputPath(),
++ 'chrome_android_strings_id.xtb')
++
++ def testOutputs(self):
++ grd = self.__ParseAndroidXml(['--languages', 'en-US,ru,id',
++ '--rc-dir', 'rc/dir',
++ '--header-dir', 'header/dir',
++ '--xtb-dir', 'xtb/dir',
++ '--xml-dir', 'xml/dir'])
++
++ outputs = grd.GetChildrenOfType(node_io.OutputNode)
++ self.assertEqual(len(outputs), 7)
++
++ header_outputs = [x for x in outputs if x.GetType() == 'rc_header']
++ rc_outputs = [x for x in outputs if x.GetType() == 'rc_all']
++ xml_outputs = [x for x in outputs if x.GetType() == 'android']
++
++ self.assertEqual(len(header_outputs), 1)
++ self.assertEqual(len(rc_outputs), 3)
++ self.assertEqual(len(xml_outputs), 3)
++
++ # The header node should have an "<emit>" child and the proper filename.
++ self.assertTrue(header_outputs[0].GetChildrenOfType(node_io.EmitNode))
++ self.assertEqual(util.normpath(header_outputs[0].GetFilename()),
++ util.normpath('header/dir/chrome_android_strings.h'))
++
++ id_rc = [x for x in rc_outputs if x.GetLanguage() == 'id']
++ id_xml = [x for x in xml_outputs if x.GetLanguage() == 'id']
++ self.assertTrue(id_rc)
++ self.assertTrue(id_xml)
++ self.assertEqual(util.normpath(id_rc[0].GetFilename()),
++ util.normpath('rc/dir/chrome_android_strings_id.rc'))
++ self.assertEqual(util.normpath(id_xml[0].GetFilename()),
++ util.normpath('xml/dir/values-in/strings.xml'))
++
++ us_rc = [x for x in rc_outputs if x.GetLanguage() == 'en-US']
++ us_xml = [x for x in xml_outputs if x.GetLanguage() == 'en-US']
++ self.assertTrue(us_rc)
++ self.assertTrue(us_xml)
++ self.assertEqual(util.normpath(us_rc[0].GetFilename()),
++ util.normpath('rc/dir/chrome_android_strings_en-US.rc'))
++ self.assertEqual(util.normpath(us_xml[0].GetFilename()),
++ util.normpath('xml/dir/values-en-rUS/strings.xml'))
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
+new file mode 100644
+index 0000000000..204592bf0d
+--- /dev/null
++++ b/tools/grit/grit/tool/build.py
+@@ -0,0 +1,556 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The 'grit build' tool.
++'''
++
++from __future__ import print_function
++
++import codecs
++import filecmp
++import getopt
++import gzip
++import os
++import shutil
++import sys
++
++import six
++
++from grit import grd_reader
++from grit import shortcuts
++from grit import util
++from grit.format import minifier
++from grit.node import brotli_util
++from grit.node import include
++from grit.node import message
++from grit.node import structure
++from grit.tool import interface
++
++
++# It would be cleaner to have each module register itself, but that would
++# require importing all of them on every run of GRIT.
++'''Map from <output> node types to modules under grit.format.'''
++_format_modules = {
++ 'android': 'android_xml',
++ 'c_format': 'c_format',
++ 'chrome_messages_json': 'chrome_messages_json',
++ 'chrome_messages_json_gzip': 'chrome_messages_json',
++ 'data_package': 'data_pack',
++ 'policy_templates': 'policy_templates_json',
++ 'rc_all': 'rc',
++ 'rc_header': 'rc_header',
++ 'rc_nontranslateable': 'rc',
++ 'rc_translateable': 'rc',
++ 'resource_file_map_source': 'resource_map',
++ 'resource_map_header': 'resource_map',
++ 'resource_map_source': 'resource_map',
++}
++
++def GetFormatter(type):
++ modulename = 'grit.format.' + _format_modules[type]
++ __import__(modulename)
++ module = sys.modules[modulename]
++ try:
++ return module.Format
++ except AttributeError:
++ return module.GetFormatter(type)
++
++
++class RcBuilder(interface.Tool):
++ '''A tool that builds RC files and resource header files for compilation.
++
++Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]*
++
++All output options for this tool are specified in the input file (see
++'grit help' for details on how to specify the input file - it is a global
++option).
++
++Options:
++
++ -a FILE Assert that the given file is an output. There can be
++ multiple "-a" flags listed for multiple outputs. If a "-a"
++ or "--assert-file-list" argument is present, then the list
++ of asserted files must match the output files or the tool
++ will fail. The use-case is for the build system to maintain
++ separate lists of output files and to catch errors if the
++ build system's list and the grit list are out-of-sync.
++
++ --assert-file-list Provide a file listing multiple asserted output files.
++ There is one file name per line. This acts like specifying
++ each file with "-a" on the command line, but without the
++ possibility of running into OS line-length limits for very
++ long lists.
++
++ -o OUTPUTDIR Specify what directory output paths are relative to.
++ Defaults to the current directory.
++
++ -p FILE Specify a file containing a pre-determined mapping from
++ resource names to resource ids which will be used to assign
++ resource ids to those resources. Resources not found in this
++ file will be assigned ids normally. The motivation is to run
++ your app's startup and have it dump the resources it loads,
++ and then pass these via this flag. This will pack startup
++ resources together, thus reducing paging while all other
++ resources are unperturbed. The file should have the format:
++ RESOURCE_ONE_NAME 123
++ RESOURCE_TWO_NAME 124
++
++ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
++ value VAL (defaults to 1) which will be used to control
++ conditional inclusion of resources.
++
++ -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
++
++ -f FIRSTIDSFILE Path to a python file that specifies the first id of
++ value to use for resources. A non-empty value here will
++ override the value specified in the <grit> node's
++ first_ids_file.
++
++ -w WHITELISTFILE Path to a file containing the string names of the
++ resources to include. Anything not listed is dropped.
++
++ -t PLATFORM Specifies the platform the build is targeting; defaults
++ to the value of sys.platform. The value provided via this
++ flag should match what sys.platform would report for your
++ target platform; see grit.node.base.EvaluateCondition.
++
++ --whitelist-support
++ Generate code to support extracting a resource whitelist
++ from executables.
++
++ --write-only-new flag
++ If flag is non-0, write output files to a temporary file
++ first, and copy it to the real output only if the new file
++ is different from the old file. This allows some build
++ systems to realize that dependent build steps might be
++ unnecessary, at the cost of comparing the output data at
++ grit time.
++
++ --depend-on-stamp
++ If specified along with --depfile and --depdir, the depfile
++ generated will depend on a stampfile instead of the first
++ output in the input .grd file.
++
++ --js-minifier A command to run the Javascript minifier. If not set then
++ Javascript won't be minified. The command should read the
++ original Javascript from standard input, and output the
++ minified Javascript to standard output. A non-zero exit
++ status will be taken as indicating failure.
++
++ --css-minifier A command to run the CSS minifier. If not set then CSS won't
++ be minified. The command should read the original CSS from
++ standard input, and output the minified CSS to standard
++ output. A non-zero exit status will be taken as indicating
++ failure.
++
++ --brotli The full path to the brotli executable generated by
++ third_party/brotli/BUILD.gn, required if any entries use
++ compress="brotli".
++
++Conditional inclusion of resources only affects the output of files which
++control which resources get linked into a binary, e.g. it affects .rc files
++meant for compilation but it does not affect resource header files (that define
++IDs). This helps ensure that values of IDs stay the same, that all messages
++are exported to translation interchange files (e.g. XMB files), etc.
++'''
++
++ def ShortDescription(self):
++ return 'A tool that builds RC files for compilation.'
++
++ def Run(self, opts, args):
++ brotli_util.SetBrotliCommand(None)
++ os.environ['cwd'] = os.getcwd()
++ self.output_directory = '.'
++ first_ids_file = None
++ predetermined_ids_file = None
++ whitelist_filenames = []
++ assert_output_files = []
++ target_platform = None
++ depfile = None
++ depdir = None
++ whitelist_support = False
++ write_only_new = False
++ depend_on_stamp = False
++ js_minifier = None
++ css_minifier = None
++ replace_ellipsis = True
++ (own_opts, args) = getopt.getopt(
++ args, 'a:p:o:D:E:f:w:t:',
++ ('depdir=', 'depfile=', 'assert-file-list=', 'help',
++ 'output-all-resource-defines', 'no-output-all-resource-defines',
++ 'no-replace-ellipsis', 'depend-on-stamp', 'js-minifier=',
++ 'css-minifier=', 'write-only-new=', 'whitelist-support', 'brotli='))
++ for (key, val) in own_opts:
++ if key == '-a':
++ assert_output_files.append(val)
++ elif key == '--assert-file-list':
++ with open(val) as f:
++ assert_output_files += f.read().splitlines()
++ elif key == '-o':
++ self.output_directory = val
++ elif key == '-D':
++ name, val = util.ParseDefine(val)
++ self.defines[name] = val
++ elif key == '-E':
++ (env_name, env_value) = val.split('=', 1)
++ os.environ[env_name] = env_value
++ elif key == '-f':
++ # TODO(joi@chromium.org): Remove this override once change
++ # lands in WebKit.grd to specify the first_ids_file in the
++ # .grd itself.
++ first_ids_file = val
++ elif key == '-w':
++ whitelist_filenames.append(val)
++ elif key == '--no-replace-ellipsis':
++ replace_ellipsis = False
++ elif key == '-p':
++ predetermined_ids_file = val
++ elif key == '-t':
++ target_platform = val
++ elif key == '--depdir':
++ depdir = val
++ elif key == '--depfile':
++ depfile = val
++ elif key == '--write-only-new':
++ write_only_new = val != '0'
++ elif key == '--depend-on-stamp':
++ depend_on_stamp = True
++ elif key == '--js-minifier':
++ js_minifier = val
++ elif key == '--css-minifier':
++ css_minifier = val
++ elif key == '--whitelist-support':
++ whitelist_support = True
++ elif key == '--brotli':
++ brotli_util.SetBrotliCommand([os.path.abspath(val)])
++ elif key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++
++ if len(args):
++ print('This tool takes no tool-specific arguments.')
++ return 2
++ self.SetOptions(opts)
++ self.VerboseOut('Output directory: %s (absolute path: %s)\n' %
++ (self.output_directory,
++ os.path.abspath(self.output_directory)))
++
++ if whitelist_filenames:
++ self.whitelist_names = set()
++ for whitelist_filename in whitelist_filenames:
++ self.VerboseOut('Using whitelist: %s\n' % whitelist_filename);
++ whitelist_contents = util.ReadFile(whitelist_filename, 'utf-8')
++ self.whitelist_names.update(whitelist_contents.strip().split('\n'))
++
++ if js_minifier:
++ minifier.SetJsMinifier(js_minifier)
++
++ if css_minifier:
++ minifier.SetCssMinifier(css_minifier)
++
++ self.write_only_new = write_only_new
++
++ self.res = grd_reader.Parse(opts.input,
++ debug=opts.extra_verbose,
++ first_ids_file=first_ids_file,
++ predetermined_ids_file=predetermined_ids_file,
++ defines=self.defines,
++ target_platform=target_platform)
++
++ # Set an output context so that conditionals can use defines during the
++ # gathering stage; we use a dummy language here since we are not outputting
++ # a specific language.
++ self.res.SetOutputLanguage('en')
++ self.res.SetWhitelistSupportEnabled(whitelist_support)
++ self.res.RunGatherers()
++
++ # Replace ... with the single-character version. http://crbug.com/621772
++ if replace_ellipsis:
++ for node in self.res:
++ if isinstance(node, message.MessageNode):
++ node.SetReplaceEllipsis(True)
++
++ self.Process()
++
++ if assert_output_files:
++ if not self.CheckAssertedOutputFiles(assert_output_files):
++ return 2
++
++ if depfile and depdir:
++ self.GenerateDepfile(depfile, depdir, first_ids_file, depend_on_stamp)
++
++ return 0
++
++ def __init__(self, defines=None):
++ # Default file-creation function is codecs.open(). Only done to allow
++ # overriding by unit test.
++ self.fo_create = codecs.open
++
++ # key/value pairs of C-preprocessor like defines that are used for
++ # conditional output of resources
++ self.defines = defines or {}
++
++ # self.res is a fully-populated resource tree if Run()
++ # has been called, otherwise None.
++ self.res = None
++
++ # The set of names that are whitelisted to actually be included in the
++ # output.
++ self.whitelist_names = None
++
++ # Whether to compare outputs to their old contents before writing.
++ self.write_only_new = False
++
++ @staticmethod
++ def AddWhitelistTags(start_node, whitelist_names):
++ # Walk the tree of nodes added attributes for the nodes that shouldn't
++ # be written into the target files (skip markers).
++ for node in start_node:
++ # Same trick data_pack.py uses to see what nodes actually result in
++ # real items.
++ if (isinstance(node, include.IncludeNode) or
++ isinstance(node, message.MessageNode) or
++ isinstance(node, structure.StructureNode)):
++ text_ids = node.GetTextualIds()
++ # Mark the item to be skipped if it wasn't in the whitelist.
++ if text_ids and text_ids[0] not in whitelist_names:
++ node.SetWhitelistMarkedAsSkip(True)
++
++ @staticmethod
++ def ProcessNode(node, output_node, outfile):
++ '''Processes a node in-order, calling its formatter before and after
++ recursing to its children.
++
++ Args:
++ node: grit.node.base.Node subclass
++ output_node: grit.node.io.OutputNode
++ outfile: open filehandle
++ '''
++ base_dir = util.dirname(output_node.GetOutputFilename())
++
++ formatter = GetFormatter(output_node.GetType())
++ formatted = formatter(node, output_node.GetLanguage(), output_dir=base_dir)
++ # NB: Formatters may be generators or return lists. The writelines API
++ # accepts iterables as a shortcut to calling write directly. That means
++ # you can pass strings (iteration yields characters), but not bytes (as
++ # iteration yields integers). Python 2 worked due to its quirks with
++ # bytes/string implementation, but Python 3 fails. It's also a bit more
++ # inefficient to call write once per character/byte. Handle all of this
++ # ourselves by calling write directly on strings/bytes before falling back
++ # to writelines.
++ if isinstance(formatted, (six.string_types, six.binary_type)):
++ outfile.write(formatted)
++ else:
++ outfile.writelines(formatted)
++ if output_node.GetType() == 'data_package':
++ with open(output_node.GetOutputFilename() + '.info', 'w') as infofile:
++ if node.info:
++ # We terminate with a newline so that when these files are
++ # concatenated later we consistently terminate with a newline so
++ # consumers can account for terminating newlines.
++ infofile.writelines(['\n'.join(node.info), '\n'])
++
++ @staticmethod
++ def _EncodingForOutputType(output_type):
++ # Microsoft's RC compiler can only deal with single-byte or double-byte
++ # files (no UTF-8), so we make all RC files UTF-16 to support all
++ # character sets.
++ if output_type in ('rc_header', 'resource_file_map_source',
++ 'resource_map_header', 'resource_map_source'):
++ return 'cp1252'
++ if output_type in ('android', 'c_format', 'plist', 'plist_strings', 'doc',
++ 'json', 'android_policy', 'chrome_messages_json',
++ 'chrome_messages_json_gzip', 'policy_templates'):
++ return 'utf_8'
++ # TODO(gfeher) modify here to set utf-8 encoding for admx/adml
++ return 'utf_16'
++
++ def Process(self):
++ for output in self.res.GetOutputFiles():
++ output.output_filename = os.path.abspath(os.path.join(
++ self.output_directory, output.GetOutputFilename()))
++
++ # If there are whitelisted names, tag the tree once up front, this way
++ # while looping through the actual output, it is just an attribute check.
++ if self.whitelist_names:
++ self.AddWhitelistTags(self.res, self.whitelist_names)
++
++ for output in self.res.GetOutputFiles():
++ self.VerboseOut('Creating %s...' % output.GetOutputFilename())
++
++ # Set the context, for conditional inclusion of resources
++ self.res.SetOutputLanguage(output.GetLanguage())
++ self.res.SetOutputContext(output.GetContext())
++ self.res.SetFallbackToDefaultLayout(output.GetFallbackToDefaultLayout())
++ self.res.SetDefines(self.defines)
++
++ # Assign IDs only once to ensure that all outputs use the same IDs.
++ if self.res.GetIdMap() is None:
++ self.res.InitializeIds()
++
++ # Make the output directory if it doesn't exist.
++ self.MakeDirectoriesTo(output.GetOutputFilename())
++
++ # Write the results to a temporary file and only overwrite the original
++ # if the file changed. This avoids unnecessary rebuilds.
++ out_filename = output.GetOutputFilename()
++ tmp_filename = out_filename + '.tmp'
++ tmpfile = self.fo_create(tmp_filename, 'wb')
++
++ output_type = output.GetType()
++ if output_type != 'data_package':
++ encoding = self._EncodingForOutputType(output_type)
++ tmpfile = util.WrapOutputStream(tmpfile, encoding)
++
++ # Iterate in-order through entire resource tree, calling formatters on
++ # the entry into a node and on exit out of it.
++ with tmpfile:
++ self.ProcessNode(self.res, output, tmpfile)
++
++ if output_type == 'chrome_messages_json_gzip':
++ gz_filename = tmp_filename + '.gz'
++ with open(tmp_filename, 'rb') as tmpfile, open(gz_filename, 'wb') as f:
++ with gzip.GzipFile(filename='', mode='wb', fileobj=f, mtime=0) as fgz:
++ shutil.copyfileobj(tmpfile, fgz)
++ os.remove(tmp_filename)
++ tmp_filename = gz_filename
++
++ # Now copy from the temp file back to the real output, but on Windows,
++ # only if the real output doesn't exist or the contents of the file
++ # changed. This prevents identical headers from being written and .cc
++ # files from recompiling (which is painful on Windows).
++ if not os.path.exists(out_filename):
++ os.rename(tmp_filename, out_filename)
++ else:
++ # CHROMIUM SPECIFIC CHANGE.
++ # This clashes with gyp + vstudio, which expect the output timestamp
++ # to change on a rebuild, even if nothing has changed, so only do
++ # it when opted in.
++ if not self.write_only_new:
++ write_file = True
++ else:
++ files_match = filecmp.cmp(out_filename, tmp_filename)
++ write_file = not files_match
++ if write_file:
++ shutil.copy2(tmp_filename, out_filename)
++ os.remove(tmp_filename)
++
++ self.VerboseOut(' done.\n')
++
++ # Print warnings if there are any duplicate shortcuts.
++ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(
++ self.res.UberClique(), self.res.GetTcProject())
++ if warnings:
++ print('\n'.join(warnings))
++
++ # Print out any fallback warnings, and missing translation errors, and
++ # exit with an error code if there are missing translations in a non-pseudo
++ # and non-official build.
++ warnings = (self.res.UberClique().MissingTranslationsReport().
++ encode('ascii', 'replace'))
++ if warnings:
++ self.VerboseOut(warnings)
++ if self.res.UberClique().HasMissingTranslations():
++ print(self.res.UberClique().missing_translations_)
++ sys.exit(-1)
++
++
++ def CheckAssertedOutputFiles(self, assert_output_files):
++ '''Checks that the asserted output files are specified in the given list.
++
++ Returns true if the asserted files are present. If they are not, returns
++ False and prints the failure.
++ '''
++ # Compare the absolute path names, sorted.
++ asserted = sorted([os.path.abspath(i) for i in assert_output_files])
++ actual = sorted([
++ os.path.abspath(os.path.join(self.output_directory,
++ i.GetOutputFilename()))
++ for i in self.res.GetOutputFiles()])
++
++ if asserted != actual:
++ missing = list(set(asserted) - set(actual))
++ extra = list(set(actual) - set(asserted))
++ error = '''Asserted file list does not match.
++
++Expected output files:
++%s
++Actual output files:
++%s
++Missing output files:
++%s
++Extra output files:
++%s
++'''
++ print(error % ('\n'.join(asserted), '\n'.join(actual), '\n'.join(missing),
++ ' \n'.join(extra)))
++ return False
++ return True
++
++
++ def GenerateDepfile(self, depfile, depdir, first_ids_file, depend_on_stamp):
++ '''Generate a depfile that contains the imlicit dependencies of the input
++ grd. The depfile will be in the same format as a makefile, and will contain
++ references to files relative to |depdir|. It will be put in |depfile|.
++
++ For example, supposing we have three files in a directory src/
++
++ src/
++ blah.grd <- depends on input{1,2}.xtb
++ input1.xtb
++ input2.xtb
++
++ and we run
++
++ grit -i blah.grd -o ../out/gen \
++ --depdir ../out \
++ --depfile ../out/gen/blah.rd.d
++
++ from the directory src/ we will generate a depfile ../out/gen/blah.grd.d
++ that has the contents
++
++ gen/blah.h: ../src/input1.xtb ../src/input2.xtb
++
++ Where "gen/blah.h" is the first output (Ninja expects the .d file to list
++ the first output in cases where there is more than one). If the flag
++ --depend-on-stamp is specified, "gen/blah.rd.d.stamp" will be used that is
++ 'touched' whenever a new depfile is generated.
++
++ Note that all paths in the depfile are relative to ../out, the depdir.
++ '''
++ depfile = os.path.abspath(depfile)
++ depdir = os.path.abspath(depdir)
++ infiles = self.res.GetInputFiles()
++
++ # We want to trigger a rebuild if the first ids change.
++ if first_ids_file is not None:
++ infiles.append(first_ids_file)
++
++ if (depend_on_stamp):
++ output_file = depfile + ".stamp"
++ # Touch the stamp file before generating the depfile.
++ with open(output_file, 'a'):
++ os.utime(output_file, None)
++ else:
++ # Get the first output file relative to the depdir.
++ outputs = self.res.GetOutputFiles()
++ output_file = os.path.join(self.output_directory,
++ outputs[0].GetOutputFilename())
++
++ output_file = os.path.relpath(output_file, depdir)
++ # The path prefix to prepend to dependencies in the depfile.
++ prefix = os.path.relpath(os.getcwd(), depdir)
++ deps_text = ' '.join([os.path.join(prefix, i) for i in infiles])
++
++ depfile_contents = output_file + ': ' + deps_text
++ self.MakeDirectoriesTo(depfile)
++ outfile = self.fo_create(depfile, 'w', encoding='utf-8')
++ outfile.write(depfile_contents)
++
++ @staticmethod
++ def MakeDirectoriesTo(file):
++ '''Creates directories necessary to contain |file|.'''
++ dir = os.path.split(file)[0]
++ if not os.path.exists(dir):
++ os.makedirs(dir)
+diff --git a/tools/grit/grit/tool/build_unittest.py b/tools/grit/grit/tool/build_unittest.py
+new file mode 100644
+index 0000000000..c4a2f2752b
+--- /dev/null
++++ b/tools/grit/grit/tool/build_unittest.py
+@@ -0,0 +1,341 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for the 'grit build' tool.
++'''
++
++from __future__ import print_function
++
++import codecs
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit import util
++from grit.tool import build
++
++
++class BuildUnittest(unittest.TestCase):
++
++ # IDs should not change based on whitelisting.
++ # Android WebView currently relies on this.
++ EXPECTED_ID_MAP = {
++ 'IDS_MESSAGE_WHITELISTED': 6889,
++ 'IDR_STRUCTURE_WHITELISTED': 11546,
++ 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED': 11548,
++ 'IDR_INCLUDE_WHITELISTED': 15601,
++ }
++
++ def testFindTranslationsWithSubstitutions(self):
++ # This is a regression test; we had a bug where GRIT would fail to find
++ # messages with substitutions e.g. "Hello [IDS_USER]" where IDS_USER is
++ # another <message>.
++ output_dir = util.TempDir({})
++ builder = build.RcBuilder()
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
++ self.verbose = False
++ self.extra_verbose = False
++ builder.Run(DummyOpts(), ['-o', output_dir.GetPath()])
++ output_dir.CleanUp()
++
++ def testGenerateDepFile(self):
++ output_dir = util.TempDir({})
++ builder = build.RcBuilder()
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/depfile.grd')
++ self.verbose = False
++ self.extra_verbose = False
++ expected_dep_file = output_dir.GetPath('substitute.grd.d')
++ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
++ '--depdir', output_dir.GetPath(),
++ '--depfile', expected_dep_file])
++
++ self.failUnless(os.path.isfile(expected_dep_file))
++ with open(expected_dep_file) as f:
++ line = f.readline()
++ (dep_output_file, deps_string) = line.split(': ')
++ deps = deps_string.split(' ')
++
++ self.failUnlessEqual("default_100_percent.pak", dep_output_file)
++ self.failUnlessEqual(deps, [
++ util.PathFromRoot('grit/testdata/default_100_percent/a.png'),
++ util.PathFromRoot('grit/testdata/grit_part.grdp'),
++ util.PathFromRoot('grit/testdata/special_100_percent/a.png'),
++ ])
++ output_dir.CleanUp()
++
++ def testGenerateDepFileWithResourceIds(self):
++ output_dir = util.TempDir({})
++ builder = build.RcBuilder()
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/substitute_no_ids.grd')
++ self.verbose = False
++ self.extra_verbose = False
++ expected_dep_file = output_dir.GetPath('substitute_no_ids.grd.d')
++ builder.Run(DummyOpts(),
++ ['-f', util.PathFromRoot('grit/testdata/resource_ids'),
++ '-o', output_dir.GetPath(),
++ '--depdir', output_dir.GetPath(),
++ '--depfile', expected_dep_file])
++
++ self.failUnless(os.path.isfile(expected_dep_file))
++ with open(expected_dep_file) as f:
++ line = f.readline()
++ (dep_output_file, deps_string) = line.split(': ')
++ deps = deps_string.split(' ')
++
++ self.failUnlessEqual("resource.h", dep_output_file)
++ self.failUnlessEqual(2, len(deps))
++ self.failUnlessEqual(deps[0],
++ util.PathFromRoot('grit/testdata/substitute.xmb'))
++ self.failUnlessEqual(deps[1],
++ util.PathFromRoot('grit/testdata/resource_ids'))
++ output_dir.CleanUp()
++
++ def testAssertOutputs(self):
++ output_dir = util.TempDir({})
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
++ self.verbose = False
++ self.extra_verbose = False
++
++ # Incomplete output file list should fail.
++ builder_fail = build.RcBuilder()
++ self.failUnlessEqual(2,
++ builder_fail.Run(DummyOpts(), [
++ '-o', output_dir.GetPath(),
++ '-a', os.path.abspath(
++ output_dir.GetPath('en_generated_resources.rc'))]))
++
++ # Complete output file list should succeed.
++ builder_ok = build.RcBuilder()
++ self.failUnlessEqual(0,
++ builder_ok.Run(DummyOpts(), [
++ '-o', output_dir.GetPath(),
++ '-a', os.path.abspath(
++ output_dir.GetPath('en_generated_resources.rc')),
++ '-a', os.path.abspath(
++ output_dir.GetPath('sv_generated_resources.rc')),
++ '-a', os.path.abspath(output_dir.GetPath('resource.h'))]))
++ output_dir.CleanUp()
++
++ def testAssertTemplateOutputs(self):
++ output_dir = util.TempDir({})
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/substitute_tmpl.grd')
++ self.verbose = False
++ self.extra_verbose = False
++
++ # Incomplete output file list should fail.
++ builder_fail = build.RcBuilder()
++ self.failUnlessEqual(2,
++ builder_fail.Run(DummyOpts(), [
++ '-o', output_dir.GetPath(),
++ '-E', 'name=foo',
++ '-a', os.path.abspath(output_dir.GetPath('en_foo_resources.rc'))]))
++
++ # Complete output file list should succeed.
++ builder_ok = build.RcBuilder()
++ self.failUnlessEqual(0,
++ builder_ok.Run(DummyOpts(), [
++ '-o', output_dir.GetPath(),
++ '-E', 'name=foo',
++ '-a', os.path.abspath(output_dir.GetPath('en_foo_resources.rc')),
++ '-a', os.path.abspath(output_dir.GetPath('sv_foo_resources.rc')),
++ '-a', os.path.abspath(output_dir.GetPath('resource.h'))]))
++ output_dir.CleanUp()
++
++ def _verifyWhitelistedOutput(self,
++ filename,
++ whitelisted_ids,
++ non_whitelisted_ids,
++ encoding='utf8'):
++ self.failUnless(os.path.exists(filename))
++ whitelisted_ids_found = []
++ non_whitelisted_ids_found = []
++ with codecs.open(filename, encoding=encoding) as f:
++ for line in f.readlines():
++ for whitelisted_id in whitelisted_ids:
++ if whitelisted_id in line:
++ whitelisted_ids_found.append(whitelisted_id)
++ if filename.endswith('.h'):
++ numeric_id = int(line.split()[2])
++ expected_numeric_id = self.EXPECTED_ID_MAP.get(whitelisted_id)
++ self.assertEqual(
++ expected_numeric_id, numeric_id,
++ 'Numeric ID for {} was {} should be {}'.format(
++ whitelisted_id, numeric_id, expected_numeric_id))
++ for non_whitelisted_id in non_whitelisted_ids:
++ if non_whitelisted_id in line:
++ non_whitelisted_ids_found.append(non_whitelisted_id)
++ self.longMessage = True
++ self.assertEqual(whitelisted_ids,
++ whitelisted_ids_found,
++ '\nin file {}'.format(os.path.basename(filename)))
++ non_whitelisted_msg = ('Non-Whitelisted IDs {} found in {}'
++ .format(non_whitelisted_ids_found, os.path.basename(filename)))
++ self.assertFalse(non_whitelisted_ids_found, non_whitelisted_msg)
++
++ def testWhitelistStrings(self):
++ output_dir = util.TempDir({})
++ builder = build.RcBuilder()
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/whitelist_strings.grd')
++ self.verbose = False
++ self.extra_verbose = False
++ whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt')
++ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
++ '-w', whitelist_file])
++ header = output_dir.GetPath('whitelist_test_resources.h')
++ rc = output_dir.GetPath('en_whitelist_test_strings.rc')
++
++ whitelisted_ids = ['IDS_MESSAGE_WHITELISTED']
++ non_whitelisted_ids = ['IDS_MESSAGE_NOT_WHITELISTED']
++ self._verifyWhitelistedOutput(
++ header,
++ whitelisted_ids,
++ non_whitelisted_ids,
++ )
++ self._verifyWhitelistedOutput(
++ rc,
++ whitelisted_ids,
++ non_whitelisted_ids,
++ encoding='utf16'
++ )
++ output_dir.CleanUp()
++
++ def testWhitelistResources(self):
++ output_dir = util.TempDir({})
++ builder = build.RcBuilder()
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/whitelist_resources.grd')
++ self.verbose = False
++ self.extra_verbose = False
++ whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt')
++ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
++ '-w', whitelist_file])
++ header = output_dir.GetPath('whitelist_test_resources.h')
++ map_cc = output_dir.GetPath('whitelist_test_resources_map.cc')
++ map_h = output_dir.GetPath('whitelist_test_resources_map.h')
++ pak = output_dir.GetPath('whitelist_test_resources.pak')
++
++ # Ensure the resource map header and .pak files exist, but don't verify
++ # their content.
++ self.failUnless(os.path.exists(map_h))
++ self.failUnless(os.path.exists(pak))
++
++ whitelisted_ids = [
++ 'IDR_STRUCTURE_WHITELISTED',
++ 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED',
++ 'IDR_INCLUDE_WHITELISTED',
++ ]
++ non_whitelisted_ids = [
++ 'IDR_STRUCTURE_NOT_WHITELISTED',
++ 'IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED',
++ 'IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED',
++ 'IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED',
++ 'IDR_INCLUDE_NOT_WHITELISTED',
++ ]
++ for output_file in (header, map_cc):
++ self._verifyWhitelistedOutput(
++ output_file,
++ whitelisted_ids,
++ non_whitelisted_ids,
++ )
++ output_dir.CleanUp()
++
++ def testWriteOnlyNew(self):
++ output_dir = util.TempDir({})
++ builder = build.RcBuilder()
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
++ self.verbose = False
++ self.extra_verbose = False
++ UNCHANGED = 10
++ header = output_dir.GetPath('resource.h')
++
++ builder.Run(DummyOpts(), ['-o', output_dir.GetPath()])
++ self.failUnless(os.path.exists(header))
++ first_mtime = os.stat(header).st_mtime
++
++ os.utime(header, (UNCHANGED, UNCHANGED))
++ builder.Run(DummyOpts(),
++ ['-o', output_dir.GetPath(), '--write-only-new', '0'])
++ self.failUnless(os.path.exists(header))
++ second_mtime = os.stat(header).st_mtime
++
++ os.utime(header, (UNCHANGED, UNCHANGED))
++ builder.Run(DummyOpts(),
++ ['-o', output_dir.GetPath(), '--write-only-new', '1'])
++ self.failUnless(os.path.exists(header))
++ third_mtime = os.stat(header).st_mtime
++
++ self.assertTrue(abs(second_mtime - UNCHANGED) > 5)
++ self.assertTrue(abs(third_mtime - UNCHANGED) < 5)
++ output_dir.CleanUp()
++
++ def testGenerateDepFileWithDependOnStamp(self):
++ output_dir = util.TempDir({})
++ builder = build.RcBuilder()
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
++ self.verbose = False
++ self.extra_verbose = False
++ expected_dep_file_name = 'substitute.grd.d'
++ expected_stamp_file_name = expected_dep_file_name + '.stamp'
++ expected_dep_file = output_dir.GetPath(expected_dep_file_name)
++ expected_stamp_file = output_dir.GetPath(expected_stamp_file_name)
++ if os.path.isfile(expected_stamp_file):
++ os.remove(expected_stamp_file)
++ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
++ '--depdir', output_dir.GetPath(),
++ '--depfile', expected_dep_file,
++ '--depend-on-stamp'])
++ self.failUnless(os.path.isfile(expected_stamp_file))
++ first_mtime = os.stat(expected_stamp_file).st_mtime
++
++ # Reset mtime to very old.
++ OLDTIME = 10
++ os.utime(expected_stamp_file, (OLDTIME, OLDTIME))
++
++ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
++ '--depdir', output_dir.GetPath(),
++ '--depfile', expected_dep_file,
++ '--depend-on-stamp'])
++ self.failUnless(os.path.isfile(expected_stamp_file))
++ second_mtime = os.stat(expected_stamp_file).st_mtime
++
++ # Some OS have a 2s stat resolution window, so can't do a direct comparison.
++ self.assertTrue((second_mtime - OLDTIME) > 5)
++ self.assertTrue(abs(second_mtime - first_mtime) < 5)
++
++ self.failUnless(os.path.isfile(expected_dep_file))
++ with open(expected_dep_file) as f:
++ line = f.readline()
++ (dep_output_file, deps_string) = line.split(': ')
++ deps = deps_string.split(' ')
++
++ self.failUnlessEqual(expected_stamp_file_name, dep_output_file)
++ self.failUnlessEqual(deps, [
++ util.PathFromRoot('grit/testdata/substitute.xmb'),
++ ])
++ output_dir.CleanUp()
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/buildinfo.py b/tools/grit/grit/tool/buildinfo.py
+new file mode 100644
+index 0000000000..7f8d1a3b04
+--- /dev/null
++++ b/tools/grit/grit/tool/buildinfo.py
+@@ -0,0 +1,78 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Output the list of files to be generated by GRIT from an input.
++"""
++
++from __future__ import print_function
++
++import getopt
++import os
++import sys
++
++from grit import grd_reader
++from grit.node import structure
++from grit.tool import interface
++
++class DetermineBuildInfo(interface.Tool):
++ """Determine what files will be read and output by GRIT.
++Outputs the list of generated files and inputs used to stdout.
++
++Usage: grit buildinfo [-o DIR]
++
++The output directory is used for display only.
++"""
++
++ def __init__(self):
++ pass
++
++ def ShortDescription(self):
++ """Describes this tool for the usage message."""
++ return ('Determine what files will be needed and\n'
++ 'output by GRIT with a given input.')
++
++ def Run(self, opts, args):
++ """Main method for the buildinfo tool."""
++ self.output_directory = '.'
++ (own_opts, args) = getopt.getopt(args, 'o:', ('help',))
++ for (key, val) in own_opts:
++ if key == '-o':
++ self.output_directory = val
++ elif key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++ if len(args) > 0:
++ print('This tool takes exactly one argument: the output directory via -o')
++ return 2
++ self.SetOptions(opts)
++
++ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
++
++ langs = {}
++ for output in res_tree.GetOutputFiles():
++ if output.attrs['lang']:
++ langs[output.attrs['lang']] = os.path.dirname(output.GetFilename())
++
++ for lang, dirname in langs.items():
++ old_output_language = res_tree.output_language
++ res_tree.SetOutputLanguage(lang)
++ for node in res_tree.ActiveDescendants():
++ with node:
++ if (isinstance(node, structure.StructureNode) and
++ node.HasFileForLanguage()):
++ path = node.FileForLanguage(lang, dirname, create_file=False,
++ return_if_not_generated=False)
++ if path:
++ path = os.path.join(self.output_directory, path)
++ path = os.path.normpath(path)
++ print('%s|%s' % ('rc_all', path))
++ res_tree.SetOutputLanguage(old_output_language)
++
++ for output in res_tree.GetOutputFiles():
++ path = os.path.join(self.output_directory, output.GetFilename())
++ path = os.path.normpath(path)
++ print('%s|%s' % (output.GetType(), path))
++
++ for infile in res_tree.GetInputFiles():
++ print('input|%s' % os.path.normpath(infile))
+diff --git a/tools/grit/grit/tool/buildinfo_unittest.py b/tools/grit/grit/tool/buildinfo_unittest.py
+new file mode 100644
+index 0000000000..24e9ddf8d8
+--- /dev/null
++++ b/tools/grit/grit/tool/buildinfo_unittest.py
+@@ -0,0 +1,90 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Unit tests for the 'grit buildinfo' tool.
++"""
++
++from __future__ import print_function
++
++import os
++import sys
++import unittest
++
++# This is needed to find some of the imports below.
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++from six import StringIO
++
++# pylint: disable-msg=C6204
++from grit.tool import buildinfo
++
++
++class BuildInfoUnittest(unittest.TestCase):
++ def setUp(self):
++ self.old_cwd = os.getcwd()
++ # Change CWD to make tests work independently of callers CWD.
++ os.chdir(os.path.dirname(__file__))
++ os.chdir('..')
++ self.buf = StringIO()
++ self.old_stdout = sys.stdout
++ sys.stdout = self.buf
++
++ def tearDown(self):
++ sys.stdout = self.old_stdout
++ os.chdir(self.old_cwd)
++
++ def testBuildOutput(self):
++ """Find all of the inputs and outputs for a GRD file."""
++ info_object = buildinfo.DetermineBuildInfo()
++
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = '../grit/testdata/buildinfo.grd'
++ self.print_header = False
++ self.verbose = False
++ self.extra_verbose = False
++ info_object.Run(DummyOpts(), [])
++ output = self.buf.getvalue().replace('\\', '/')
++ self.failUnless(output.count(r'rc_all|sv_sidebar_loading.html'))
++ self.failUnless(output.count(r'rc_header|resource.h'))
++ self.failUnless(output.count(r'rc_all|en_generated_resources.rc'))
++ self.failUnless(output.count(r'rc_all|sv_generated_resources.rc'))
++ self.failUnless(output.count(r'input|../grit/testdata/substitute.xmb'))
++ self.failUnless(output.count(r'input|../grit/testdata/pr.bmp'))
++ self.failUnless(output.count(r'input|../grit/testdata/pr2.bmp'))
++ self.failUnless(
++ output.count(r'input|../grit/testdata/sidebar_loading.html'))
++ self.failUnless(output.count(r'input|../grit/testdata/transl.rc'))
++ self.failUnless(output.count(r'input|../grit/testdata/transl1.rc'))
++
++ def testBuildOutputWithDir(self):
++ """Find all the inputs and outputs for a GRD file with an output dir."""
++ info_object = buildinfo.DetermineBuildInfo()
++
++ class DummyOpts(object):
++ def __init__(self):
++ self.input = '../grit/testdata/buildinfo.grd'
++ self.print_header = False
++ self.verbose = False
++ self.extra_verbose = False
++ info_object.Run(DummyOpts(), ['-o', '../grit/testdata'])
++ output = self.buf.getvalue().replace('\\', '/')
++ self.failUnless(
++ output.count(r'rc_all|../grit/testdata/sv_sidebar_loading.html'))
++ self.failUnless(output.count(r'rc_header|../grit/testdata/resource.h'))
++ self.failUnless(
++ output.count(r'rc_all|../grit/testdata/en_generated_resources.rc'))
++ self.failUnless(
++ output.count(r'rc_all|../grit/testdata/sv_generated_resources.rc'))
++ self.failUnless(output.count(r'input|../grit/testdata/substitute.xmb'))
++ self.failUnlessEqual(0,
++ output.count(r'rc_all|../grit/testdata/sv_welcome_toast.html'))
++ self.failUnless(
++ output.count(r'rc_all|../grit/testdata/en_welcome_toast.html'))
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/count.py b/tools/grit/grit/tool/count.py
+new file mode 100644
+index 0000000000..ab37f2ddb3
+--- /dev/null
++++ b/tools/grit/grit/tool/count.py
+@@ -0,0 +1,52 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Count number of occurrences of a given message ID.'''
++
++from __future__ import print_function
++
++import getopt
++import sys
++
++from grit import grd_reader
++from grit.tool import interface
++
++
++class CountMessage(interface.Tool):
++ '''Count the number of times a given message ID is used.'''
++
++ def __init__(self):
++ pass
++
++ def ShortDescription(self):
++ return 'Count the number of times a given message ID is used.'
++
++ def ParseOptions(self, args):
++ """Set this objects and return all non-option arguments."""
++ own_opts, args = getopt.getopt(args, '', ('help',))
++ for key, val in own_opts:
++ if key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++ return args
++
++ def Run(self, opts, args):
++ args = self.ParseOptions(args)
++ if len(args) != 1:
++ print('This tool takes a single tool-specific argument, the message '
++ 'ID to count.')
++ return 2
++ self.SetOptions(opts)
++
++ id = args[0]
++ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
++ res_tree.OnlyTheseTranslations([])
++ res_tree.RunGatherers()
++
++ count = 0
++ for c in res_tree.UberClique().AllCliques():
++ if c.GetId() == id:
++ count += 1
++
++ print("There are %d occurrences of message %s." % (count, id))
+diff --git a/tools/grit/grit/tool/diff_structures.py b/tools/grit/grit/tool/diff_structures.py
+new file mode 100644
+index 0000000000..d69e009b58
+--- /dev/null
++++ b/tools/grit/grit/tool/diff_structures.py
+@@ -0,0 +1,119 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The 'grit sdiff' tool.
++'''
++
++from __future__ import print_function
++
++import os
++import getopt
++import sys
++import tempfile
++
++from grit.node import structure
++from grit.tool import interface
++
++from grit import constants
++from grit import util
++
++# Builds the description for the tool (used as the __doc__
++# for the DiffStructures class).
++_class_doc = """\
++Allows you to view the differences in the structure of two files,
++disregarding their translateable content. Translateable portions of
++each file are changed to the string "TTTTTT" before invoking the diff program
++specified by the P4DIFF environment variable.
++
++Usage: grit sdiff [-t TYPE] [-s SECTION] [-e ENCODING] LEFT RIGHT
++
++LEFT and RIGHT are the files you want to diff. SECTION is required
++for structure types like 'dialog' to identify the part of the file to look at.
++ENCODING indicates the encoding of the left and right files (default 'cp1252').
++TYPE can be one of the following, defaults to 'tr_html':
++"""
++for gatherer in structure._GATHERERS:
++ _class_doc += " - %s\n" % gatherer
++
++
++class DiffStructures(interface.Tool):
++ __doc__ = _class_doc
++
++ def __init__(self):
++ self.section = None
++ self.left_encoding = 'cp1252'
++ self.right_encoding = 'cp1252'
++ self.structure_type = 'tr_html'
++
++ def ShortDescription(self):
++ return 'View differences without regard for translateable portions.'
++
++ def Run(self, global_opts, args):
++ (opts, args) = getopt.getopt(args, 's:e:t:',
++ ('help', 'left_encoding=', 'right_encoding='))
++ for key, val in opts:
++ if key == '-s':
++ self.section = val
++ elif key == '-e':
++ self.left_encoding = val
++ self.right_encoding = val
++ elif key == '-t':
++ self.structure_type = val
++ elif key == '--left_encoding':
++ self.left_encoding = val
++ elif key == '--right_encoding':
++ self.right_encoding == val
++ elif key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++
++ if len(args) != 2:
++ print("Incorrect usage - 'grit help sdiff' for usage details.")
++ return 2
++
++ if 'P4DIFF' not in os.environ:
++ print("Environment variable P4DIFF not set; defaulting to 'windiff'.")
++ diff_program = 'windiff'
++ else:
++ diff_program = os.environ['P4DIFF']
++
++ left_trans = self.MakeStaticTranslation(args[0], self.left_encoding)
++ try:
++ try:
++ right_trans = self.MakeStaticTranslation(args[1], self.right_encoding)
++
++ os.system('%s %s %s' % (diff_program, left_trans, right_trans))
++ finally:
++ os.unlink(right_trans)
++ finally:
++ os.unlink(left_trans)
++
++ def MakeStaticTranslation(self, original_filename, encoding):
++ """Given the name of the structure type (self.structure_type), the filename
++ of the file holding the original structure, and optionally the "section" key
++ identifying the part of the file to look at (self.section), creates a
++ temporary file holding a "static" translation of the original structure
++ (i.e. one where all translateable parts have been replaced with "TTTTTT")
++ and returns the temporary file name. It is the caller's responsibility to
++ delete the file when finished.
++
++ Args:
++ original_filename: 'c:\\bingo\\bla.rc'
++
++ Return:
++ 'c:\\temp\\werlkjsdf334.tmp'
++ """
++ original = structure._GATHERERS[self.structure_type](original_filename,
++ extkey=self.section,
++ encoding=encoding)
++ original.Parse()
++ translated = original.Translate(constants.CONSTANT_LANGUAGE, False)
++
++ fname = tempfile.mktemp()
++ with util.WrapOutputStream(open(fname, 'wb')) as writer:
++ writer.write("Original filename: %s\n=============\n\n"
++ % original_filename)
++ writer.write(translated) # write in UTF-8
++
++ return fname
+diff --git a/tools/grit/grit/tool/diff_structures_unittest.py b/tools/grit/grit/tool/diff_structures_unittest.py
+new file mode 100644
+index 0000000000..a6d7585761
+--- /dev/null
++++ b/tools/grit/grit/tool/diff_structures_unittest.py
+@@ -0,0 +1,46 @@
++#!/usr/bin/env python
++# Copyright 2020 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for the 'grit newgrd' tool.'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit.tool import diff_structures
++
++
++class DummyOpts(object):
++ """Options needed by NewGrd."""
++
++
++class DiffStructuresUnittest(unittest.TestCase):
++
++ def testMissingFiles(self):
++ """Verify failure w/out file inputs."""
++ tool = diff_structures.DiffStructures()
++ ret = tool.Run(DummyOpts(), [])
++ self.assertIsNotNone(ret)
++ self.assertGreater(ret, 0)
++
++ ret = tool.Run(DummyOpts(), ['left'])
++ self.assertIsNotNone(ret)
++ self.assertGreater(ret, 0)
++
++ def testTooManyArgs(self):
++ """Verify failure w/too many inputs."""
++ tool = diff_structures.DiffStructures()
++ ret = tool.Run(DummyOpts(), ['a', 'b', 'c'])
++ self.assertIsNotNone(ret)
++ self.assertGreater(ret, 0)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/interface.py b/tools/grit/grit/tool/interface.py
+new file mode 100644
+index 0000000000..e923205223
+--- /dev/null
++++ b/tools/grit/grit/tool/interface.py
+@@ -0,0 +1,62 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Base class and interface for tools.
++'''
++
++from __future__ import print_function
++
++class Tool(object):
++ '''Base class for all tools. Tools should use their docstring (i.e. the
++ class-level docstring) for the help they want to have printed when they
++ are invoked.'''
++
++ #
++ # Interface (abstract methods)
++ #
++
++ def ShortDescription(self):
++ '''Returns a short description of the functionality of the tool.'''
++ raise NotImplementedError()
++
++ def Run(self, global_options, my_arguments):
++ '''Runs the tool.
++
++ Args:
++ global_options: object grit_runner.Options
++ my_arguments: [arg1 arg2 ...]
++
++ Return:
++ 0 for success, non-0 for error
++ '''
++ raise NotImplementedError()
++
++ #
++ # Base class implementation
++ #
++
++ def __init__(self):
++ self.o = None
++
++ def ShowUsage(self):
++ '''Show usage text for this tool.'''
++ print(self.__doc__)
++
++ def SetOptions(self, opts):
++ self.o = opts
++
++ def Out(self, text):
++ '''Always writes out 'text'.'''
++ self.o.output_stream.write(text)
++
++ def VerboseOut(self, text):
++ '''Writes out 'text' if the verbose option is on.'''
++ if self.o.verbose:
++ self.o.output_stream.write(text)
++
++ def ExtraVerboseOut(self, text):
++ '''Writes out 'text' if the extra-verbose option is on.
++ '''
++ if self.o.extra_verbose:
++ self.o.output_stream.write(text)
+diff --git a/tools/grit/grit/tool/menu_from_parts.py b/tools/grit/grit/tool/menu_from_parts.py
+new file mode 100644
+index 0000000000..fcec26c5b1
+--- /dev/null
++++ b/tools/grit/grit/tool/menu_from_parts.py
+@@ -0,0 +1,79 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The 'grit menufromparts' tool.'''
++
++from __future__ import print_function
++
++import six
++
++from grit import grd_reader
++from grit import util
++from grit import xtb_reader
++from grit.tool import interface
++from grit.tool import transl2tc
++
++import grit.extern.tclib
++
++
++class MenuTranslationsFromParts(interface.Tool):
++ '''One-off tool to generate translated menu messages (where each menu is kept
++in a single message) based on existing translations of the individual menu
++items. Was needed when changing menus from being one message per menu item
++to being one message for the whole menu.'''
++
++ def ShortDescription(self):
++ return ('Create translations of whole menus from existing translations of '
++ 'menu items.')
++
++ def Run(self, globopt, args):
++ self.SetOptions(globopt)
++ assert len(args) == 2, "Need exactly two arguments, the XTB file and the output file"
++
++ xtb_file = args[0]
++ output_file = args[1]
++
++ grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
++ grd.OnlyTheseTranslations([]) # don't load translations
++ grd.RunGatherers()
++
++ xtb = {}
++ def Callback(msg_id, parts):
++ msg = []
++ for part in parts:
++ if part[0]:
++ msg = []
++ break # it had a placeholder so ignore it
++ else:
++ msg.append(part[1])
++ if len(msg):
++ xtb[msg_id] = ''.join(msg)
++ with open(xtb_file, 'rb') as f:
++ xtb_reader.Parse(f, Callback)
++
++ translations = [] # list of translations as per transl2tc.WriteTranslations
++ for node in grd:
++ if node.name == 'structure' and node.attrs['type'] == 'menu':
++ assert len(node.GetCliques()) == 1
++ message = node.GetCliques()[0].GetMessage()
++ translation = []
++
++ contents = message.GetContent()
++ for part in contents:
++ if isinstance(part, six.string_types):
++ id = grit.extern.tclib.GenerateMessageId(part)
++ if id not in xtb:
++ print("WARNING didn't find all translations for menu %s" %
++ (node.attrs['name'],))
++ translation = []
++ break
++ translation.append(xtb[id])
++ else:
++ translation.append(part.GetPresentation())
++
++ if len(translation):
++ translations.append([message.GetId(), ''.join(translation)])
++
++ with util.WrapOutputStream(open(output_file, 'wb')) as f:
++ transl2tc.TranslationToTc.WriteTranslations(f, translations)
+diff --git a/tools/grit/grit/tool/newgrd.py b/tools/grit/grit/tool/newgrd.py
+new file mode 100644
+index 0000000000..66a18e9c04
+--- /dev/null
++++ b/tools/grit/grit/tool/newgrd.py
+@@ -0,0 +1,85 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Tool to create a new, empty .grd file with all the basic sections.
++'''
++
++from __future__ import print_function
++
++import getopt
++import sys
++
++from grit.tool import interface
++from grit import constants
++from grit import util
++
++# The contents of the new .grd file
++_FILE_CONTENTS = '''\
++<?xml version="1.0" encoding="UTF-8"?>
++<grit base_dir="." latest_public_release="0" current_release="1"
++ source_lang_id="en" enc_check="%s">
++ <outputs>
++ <!-- TODO add each of your output files. Modify the three below, and add
++ your own for your various languages. See the user's guide for more
++ details.
++ Note that all output references are relative to the output directory
++ which is specified at build time. -->
++ <output filename="resource.h" type="rc_header" />
++ <output filename="en_resource.rc" type="rc_all" />
++ <output filename="fr_resource.rc" type="rc_all" />
++ </outputs>
++ <translations>
++ <!-- TODO add references to each of the XTB files (from the Translation
++ Console) that contain translations of messages in your project. Each
++ takes a form like <file path="english.xtb" />. Remember that all file
++ references are relative to this .grd file. -->
++ </translations>
++ <release seq="1">
++ <includes>
++ <!-- TODO add a list of your included resources here, e.g. BMP and GIF
++ resources. -->
++ </includes>
++ <structures>
++ <!-- TODO add a list of all your structured resources here, e.g. HTML
++ templates, menus, dialogs etc. Note that for menus, dialogs and version
++ information resources you reference an .rc file containing them.-->
++ </structures>
++ <messages>
++ <!-- TODO add all of your "string table" messages here. Remember to
++ change nontranslateable parts of the messages into placeholders (using the
++ <ph> element). You can also use the 'grit add' tool to help you identify
++ nontranslateable parts and create placeholders for them. -->
++ </messages>
++ </release>
++</grit>''' % constants.ENCODING_CHECK
++
++
++class NewGrd(interface.Tool):
++ '''Usage: grit newgrd OUTPUT_FILE
++
++Creates a new, empty .grd file OUTPUT_FILE with comments about what to put
++where in the file.'''
++
++ def ShortDescription(self):
++ return 'Create a new empty .grd file.'
++
++ def ParseOptions(self, args):
++ """Set this objects and return all non-option arguments."""
++ own_opts, args = getopt.getopt(args, '', ('help',))
++ for key, val in own_opts:
++ if key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++ return args
++
++ def Run(self, opts, args):
++ args = self.ParseOptions(args)
++ if len(args) != 1:
++ print('This tool requires exactly one argument, the name of the output '
++ 'file.')
++ return 2
++ filename = args[0]
++ with util.WrapOutputStream(open(filename, 'wb'), 'utf-8') as out:
++ out.write(_FILE_CONTENTS)
++ print("Wrote file %s" % filename)
+diff --git a/tools/grit/grit/tool/newgrd_unittest.py b/tools/grit/grit/tool/newgrd_unittest.py
+new file mode 100644
+index 0000000000..f7c8831df5
+--- /dev/null
++++ b/tools/grit/grit/tool/newgrd_unittest.py
+@@ -0,0 +1,51 @@
++#!/usr/bin/env python
++# Copyright 2020 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for the 'grit newgrd' tool.'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from grit import util
++from grit.tool import newgrd
++
++
++class DummyOpts(object):
++ """Options needed by NewGrd."""
++
++
++class NewgrdUnittest(unittest.TestCase):
++
++ def testNewFile(self):
++ """Create a new file."""
++ tool = newgrd.NewGrd()
++ with util.TempDir({}) as output_dir:
++ output_file = os.path.join(output_dir.GetPath(), 'new.grd')
++ self.assertIsNone(tool.Run(DummyOpts(), [output_file]))
++ self.assertTrue(os.path.exists(output_file))
++
++ def testMissingFile(self):
++ """Verify failure w/out file output."""
++ tool = newgrd.NewGrd()
++ ret = tool.Run(DummyOpts(), [])
++ self.assertIsNotNone(ret)
++ self.assertGreater(ret, 0)
++
++ def testTooManyArgs(self):
++ """Verify failure w/too many outputs."""
++ tool = newgrd.NewGrd()
++ ret = tool.Run(DummyOpts(), ['a', 'b'])
++ self.assertIsNotNone(ret)
++ self.assertGreater(ret, 0)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/postprocess_interface.py b/tools/grit/grit/tool/postprocess_interface.py
+new file mode 100644
+index 0000000000..4bb8c5871f
+--- /dev/null
++++ b/tools/grit/grit/tool/postprocess_interface.py
+@@ -0,0 +1,29 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++''' Base class for postprocessing of RC files.
++'''
++
++from __future__ import print_function
++
++class PostProcessor(object):
++ ''' Base class for postprocessing of the RC file data before being
++ output through the RC2GRD tool. You should implement this class if
++ you want GRIT to do specific things to the RC files after it has
++ converted the data into GRD format, i.e. change the content of the
++ RC file, and put it into a P4 changelist, etc.'''
++
++
++ def Process(self, rctext, rcpath, grdnode):
++ ''' Processes the data in rctext and grdnode.
++ Args:
++ rctext: string containing the contents of the RC file being processed.
++ rcpath: the path used to access the file.
++ grdtext: the root node of the grd xml data generated by
++ the rc2grd tool.
++
++ Return:
++ The root node of the processed GRD tree.
++ '''
++ raise NotImplementedError()
+diff --git a/tools/grit/grit/tool/postprocess_unittest.py b/tools/grit/grit/tool/postprocess_unittest.py
+new file mode 100644
+index 0000000000..77fe228bbe
+--- /dev/null
++++ b/tools/grit/grit/tool/postprocess_unittest.py
+@@ -0,0 +1,64 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit test that checks postprocessing of files.
++ Tests postprocessing by having the postprocessor
++ modify the grd data tree, changing the message name attributes.
++'''
++
++from __future__ import print_function
++
++import os
++import re
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++import grit.tool.postprocess_interface
++from grit.tool import rc2grd
++
++
++class PostProcessingUnittest(unittest.TestCase):
++
++ def testPostProcessing(self):
++ rctext = '''STRINGTABLE
++BEGIN
++ DUMMY_STRING_1 "String 1"
++ // Some random description
++ DUMMY_STRING_2 "This text was added during preprocessing"
++END
++ '''
++ tool = rc2grd.Rc2Grd()
++ class DummyOpts(object):
++ verbose = False
++ extra_verbose = False
++ tool.o = DummyOpts()
++ tool.post_process = 'grit.tool.postprocess_unittest.DummyPostProcessor'
++ result = tool.Process(rctext, '.\resource.rc')
++
++ self.failUnless(
++ result.children[2].children[2].children[0].attrs['name'] == 'SMART_STRING_1')
++ self.failUnless(
++ result.children[2].children[2].children[1].attrs['name'] == 'SMART_STRING_2')
++
++class DummyPostProcessor(grit.tool.postprocess_interface.PostProcessor):
++ '''
++ Post processing replaces all message name attributes containing "DUMMY" to
++ "SMART".
++ '''
++ def Process(self, rctext, rcpath, grdnode):
++ smarter = re.compile(r'(DUMMY)(.*)')
++ messages = grdnode.children[2].children[2]
++ for node in messages.children:
++ name_attr = node.attrs['name']
++ m = smarter.search(name_attr)
++ if m:
++ node.attrs['name'] = 'SMART' + m.group(2)
++ return grdnode
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/preprocess_interface.py b/tools/grit/grit/tool/preprocess_interface.py
+new file mode 100644
+index 0000000000..67974e704e
+--- /dev/null
++++ b/tools/grit/grit/tool/preprocess_interface.py
+@@ -0,0 +1,25 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++''' Base class for preprocessing of RC files.
++'''
++
++from __future__ import print_function
++
++class PreProcessor(object):
++ ''' Base class for preprocessing of the RC file data before being
++ output through the RC2GRD tool. You should implement this class if
++ you have specific constructs in your RC files that GRIT cannot handle.'''
++
++
++ def Process(self, rctext, rcpath):
++ ''' Processes the data in rctext.
++ Args:
++ rctext: string containing the contents of the RC file being processed
++ rcpath: the path used to access the file.
++
++ Return:
++ The processed text.
++ '''
++ raise NotImplementedError()
+diff --git a/tools/grit/grit/tool/preprocess_unittest.py b/tools/grit/grit/tool/preprocess_unittest.py
+new file mode 100644
+index 0000000000..40b95cd6f8
+--- /dev/null
++++ b/tools/grit/grit/tool/preprocess_unittest.py
+@@ -0,0 +1,50 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit test that checks preprocessing of files.
++ Tests preprocessing by adding having the preprocessor
++ provide the actual rctext data.
++'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++import grit.tool.preprocess_interface
++from grit.tool import rc2grd
++
++
++class PreProcessingUnittest(unittest.TestCase):
++
++ def testPreProcessing(self):
++ tool = rc2grd.Rc2Grd()
++ class DummyOpts(object):
++ verbose = False
++ extra_verbose = False
++ tool.o = DummyOpts()
++ tool.pre_process = 'grit.tool.preprocess_unittest.DummyPreProcessor'
++ result = tool.Process('', '.\resource.rc')
++
++ self.failUnless(
++ result.children[2].children[2].children[0].attrs['name'] == 'DUMMY_STRING_1')
++
++class DummyPreProcessor(grit.tool.preprocess_interface.PreProcessor):
++ def Process(self, rctext, rcpath):
++ rctext = '''STRINGTABLE
++BEGIN
++ DUMMY_STRING_1 "String 1"
++ // Some random description
++ DUMMY_STRING_2 "This text was added during preprocessing"
++END
++ '''
++ return rctext
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/rc2grd.py b/tools/grit/grit/tool/rc2grd.py
+new file mode 100644
+index 0000000000..3195b39000
+--- /dev/null
++++ b/tools/grit/grit/tool/rc2grd.py
+@@ -0,0 +1,418 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The 'grit rc2grd' tool.'''
++
++from __future__ import print_function
++
++import os.path
++import getopt
++import re
++import sys
++
++import six
++from six import StringIO
++
++import grit.node.empty
++from grit.node import include
++from grit.node import structure
++from grit.node import message
++
++from grit.gather import rc
++from grit.gather import tr_html
++
++from grit.tool import interface
++from grit.tool import postprocess_interface
++from grit.tool import preprocess_interface
++
++from grit import grd_reader
++from grit import lazy_re
++from grit import tclib
++from grit import util
++
++
++# Matches files referenced from an .rc file
++_FILE_REF = lazy_re.compile(r'''
++ ^(?P<id>[A-Z_0-9.]+)[ \t]+
++ (?P<type>[A-Z_0-9]+)[ \t]+
++ "(?P<file>.*?([^"]|""))"[ \t]*$''', re.VERBOSE | re.MULTILINE)
++
++
++# Matches a dialog section
++_DIALOG = lazy_re.compile(
++ r'^(?P<id>[A-Z0-9_]+)\s+DIALOG(EX)?\s.+?^BEGIN\s*$.+?^END\s*$',
++ re.MULTILINE | re.DOTALL)
++
++
++# Matches a menu section
++_MENU = lazy_re.compile(r'^(?P<id>[A-Z0-9_]+)\s+MENU.+?^BEGIN\s*$.+?^END\s*$',
++ re.MULTILINE | re.DOTALL)
++
++
++# Matches a versioninfo section
++_VERSIONINFO = lazy_re.compile(
++ r'^(?P<id>[A-Z0-9_]+)\s+VERSIONINFO\s.+?^BEGIN\s*$.+?^END\s*$',
++ re.MULTILINE | re.DOTALL)
++
++
++# Matches a stringtable
++_STRING_TABLE = lazy_re.compile(
++ (r'^STRINGTABLE(\s+(PRELOAD|DISCARDABLE|CHARACTERISTICS.+|LANGUAGE.+|'
++ r'VERSION.+))*\s*\nBEGIN\s*$(?P<body>.+?)^END\s*$'),
++ re.MULTILINE | re.DOTALL)
++
++
++# Matches each message inside a stringtable, breaking it up into comments,
++# the ID of the message, and the (RC-escaped) message text.
++_MESSAGE = lazy_re.compile(r'''
++ (?P<comment>(^\s+//.+?)*) # 0 or more lines of comments preceding the message
++ ^\s*
++ (?P<id>[A-Za-z0-9_]+) # id
++ \s+
++ "(?P<text>.*?([^"]|""))"([^"]|$) # The message itself
++ ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
++
++
++# Matches each line of comment text in a multi-line comment.
++_COMMENT_TEXT = lazy_re.compile(r'^\s*//\s*(?P<text>.+?)$', re.MULTILINE)
++
++
++# Matches a string that is empty or all whitespace
++_WHITESPACE_ONLY = lazy_re.compile(r'\A\s*\Z', re.MULTILINE)
++
++
++# Finds printf and FormatMessage style format specifiers
++# Uses non-capturing groups except for the outermost group, so the output of
++# re.split() should include both the normal text and what we intend to
++# replace with placeholders.
++# TODO(joi) Check documentation for printf (and Windows variants) and FormatMessage
++_FORMAT_SPECIFIER = lazy_re.compile(
++ r'(%[-# +]?(?:[0-9]*|\*)(?:\.(?:[0-9]+|\*))?(?:h|l|L)?' # printf up to last char
++ r'(?:d|i|o|u|x|X|e|E|f|F|g|G|c|r|s|ls|ws)' # printf last char
++ r'|\$[1-9][0-9]*)') # FormatMessage
++
++
++class Rc2Grd(interface.Tool):
++ '''A tool for converting .rc files to .grd files. This tool is only for
++converting the source (nontranslated) .rc file to a .grd file. For importing
++existing translations, use the rc2xtb tool.
++
++Usage: grit [global options] rc2grd [OPTIONS] RCFILE
++
++The tool takes a single argument, which is the path to the .rc file to convert.
++It outputs a .grd file with the same name in the same directory as the .rc file.
++The .grd file may have one or more TODO comments for things that have to be
++cleaned up manually.
++
++OPTIONS may be any of the following:
++
++ -e ENCODING Specify the ENCODING of the .rc file. Default is 'cp1252'.
++
++ -h TYPE Specify the TYPE attribute for HTML structures.
++ Default is 'tr_html'.
++
++ -u ENCODING Specify the ENCODING of HTML files. Default is 'utf-8'.
++
++ -n MATCH Specify the regular expression to match in comments that will
++ indicate that the resource the comment belongs to is not
++ translateable. Default is 'Not locali(s|z)able'.
++
++ -r GRDFILE Specify that GRDFILE should be used as a "role model" for
++ any placeholders that otherwise would have had TODO names.
++ This attempts to find an identical message in the GRDFILE
++ and uses that instead of the automatically placeholderized
++ message.
++
++ --pre CLASS Specify an optional, fully qualified classname, which
++ has to be a subclass of grit.tool.PreProcessor, to
++ run on the text of the RC file before conversion occurs.
++ This can be used to support constructs in the RC files
++ that GRIT cannot handle on its own.
++
++ --post CLASS Specify an optional, fully qualified classname, which
++ has to be a subclass of grit.tool.PostProcessor, to
++ run on the text of the converted RC file.
++ This can be used to alter the content of the RC file
++ based on the conversion that occured.
++
++For menus, dialogs and version info, the .grd file will refer to the original
++.rc file. Once conversion is complete, you can strip the original .rc file
++of its string table and all comments as these will be available in the .grd
++file.
++
++Note that this tool WILL NOT obey C preprocessor rules, so even if something
++is #if 0-ed out it will still be included in the output of this tool
++Therefore, if your .rc file contains sections like this, you should run the
++C preprocessor on the .rc file or manually edit it before using this tool.
++'''
++
++ def ShortDescription(self):
++ return 'A tool for converting .rc source files to .grd files.'
++
++ def __init__(self):
++ self.input_encoding = 'cp1252'
++ self.html_type = 'tr_html'
++ self.html_encoding = 'utf-8'
++ self.not_localizable_re = re.compile('Not locali(s|z)able')
++ self.role_model = None
++ self.pre_process = None
++ self.post_process = None
++
++ def ParseOptions(self, args, help_func=None):
++ '''Given a list of arguments, set this object's options and return
++ all non-option arguments.
++ '''
++ (own_opts, args) = getopt.getopt(args, 'e:h:u:n:r',
++ ('help', 'pre=', 'post='))
++ for (key, val) in own_opts:
++ if key == '-e':
++ self.input_encoding = val
++ elif key == '-h':
++ self.html_type = val
++ elif key == '-u':
++ self.html_encoding = val
++ elif key == '-n':
++ self.not_localizable_re = re.compile(val)
++ elif key == '-r':
++ self.role_model = grd_reader.Parse(val)
++ elif key == '--pre':
++ self.pre_process = val
++ elif key == '--post':
++ self.post_process = val
++ elif key == '--help':
++ if help_func is None:
++ self.ShowUsage()
++ else:
++ help_func()
++ sys.exit(0)
++ return args
++
++ def Run(self, opts, args):
++ args = self.ParseOptions(args)
++ if len(args) != 1:
++ print('This tool takes a single tool-specific argument, the path to the\n'
++ '.rc file to process.')
++ return 2
++ self.SetOptions(opts)
++
++ path = args[0]
++ out_path = os.path.join(util.dirname(path),
++ os.path.splitext(os.path.basename(path))[0] + '.grd')
++
++ rctext = util.ReadFile(path, self.input_encoding)
++ grd_text = six.text_type(self.Process(rctext, path))
++ with util.WrapOutputStream(open(out_path, 'wb'), 'utf-8') as outfile:
++ outfile.write(grd_text)
++
++ print('Wrote output file %s.\nPlease check for TODO items in the file.' %
++ (out_path,))
++
++
++ def Process(self, rctext, rc_path):
++ '''Processes 'rctext' and returns a resource tree corresponding to it.
++
++ Args:
++ rctext: complete text of the rc file
++ rc_path: 'resource\resource.rc'
++
++ Return:
++ grit.node.base.Node subclass
++ '''
++
++ if self.pre_process:
++ preprocess_class = util.NewClassInstance(self.pre_process,
++ preprocess_interface.PreProcessor)
++ if preprocess_class:
++ rctext = preprocess_class.Process(rctext, rc_path)
++ else:
++ self.Out(
++ 'PreProcessing class could not be found. Skipping preprocessing.\n')
++
++ # Start with a basic skeleton for the .grd file
++ root = grd_reader.Parse(StringIO(
++ '''<?xml version="1.0" encoding="UTF-8"?>
++ <grit base_dir="." latest_public_release="0"
++ current_release="1" source_lang_id="en">
++ <outputs />
++ <translations />
++ <release seq="1">
++ <includes />
++ <structures />
++ <messages />
++ </release>
++ </grit>'''), util.dirname(rc_path))
++ includes = root.children[2].children[0]
++ structures = root.children[2].children[1]
++ messages = root.children[2].children[2]
++ assert (isinstance(includes, grit.node.empty.IncludesNode) and
++ isinstance(structures, grit.node.empty.StructuresNode) and
++ isinstance(messages, grit.node.empty.MessagesNode))
++
++ self.AddIncludes(rctext, includes)
++ self.AddStructures(rctext, structures, os.path.basename(rc_path))
++ self.AddMessages(rctext, messages)
++
++ self.VerboseOut('Validating that all IDs are unique...\n')
++ root.ValidateUniqueIds()
++ self.ExtraVerboseOut('Done validating that all IDs are unique.\n')
++
++ if self.post_process:
++ postprocess_class = util.NewClassInstance(self.post_process,
++ postprocess_interface.PostProcessor)
++ if postprocess_class:
++ root = postprocess_class.Process(rctext, rc_path, root)
++ else:
++ self.Out(
++ 'PostProcessing class could not be found. Skipping postprocessing.\n')
++
++ return root
++
++
++ def IsHtml(self, res_type, fname):
++ '''Check whether both the type and file extension indicate HTML'''
++ fext = fname.split('.')[-1].lower()
++ return res_type == 'HTML' and fext in ('htm', 'html')
++
++
++ def AddIncludes(self, rctext, node):
++ '''Scans 'rctext' for included resources (e.g. BITMAP, ICON) and
++ adds each included resource as an <include> child node of 'node'.'''
++ for m in _FILE_REF.finditer(rctext):
++ id = m.group('id')
++ res_type = m.group('type').upper()
++ fname = rc.Section.UnEscape(m.group('file'))
++ assert fname.find('\n') == -1
++ if not self.IsHtml(res_type, fname):
++ self.VerboseOut('Processing %s with ID %s (filename: %s)\n' %
++ (res_type, id, fname))
++ node.AddChild(include.IncludeNode.Construct(node, id, res_type, fname))
++
++
++ def AddStructures(self, rctext, node, rc_filename):
++ '''Scans 'rctext' for structured resources (e.g. menus, dialogs, version
++ information resources and HTML templates) and adds each as a <structure>
++ child of 'node'.'''
++ # First add HTML includes
++ for m in _FILE_REF.finditer(rctext):
++ id = m.group('id')
++ res_type = m.group('type').upper()
++ fname = rc.Section.UnEscape(m.group('file'))
++ if self.IsHtml(type, fname):
++ node.AddChild(structure.StructureNode.Construct(
++ node, id, self.html_type, fname, self.html_encoding))
++
++ # Then add all RC includes
++ def AddStructure(res_type, id):
++ self.VerboseOut('Processing %s with ID %s\n' % (res_type, id))
++ node.AddChild(structure.StructureNode.Construct(node, id, res_type,
++ rc_filename,
++ encoding=self.input_encoding))
++ for m in _MENU.finditer(rctext):
++ AddStructure('menu', m.group('id'))
++ for m in _DIALOG.finditer(rctext):
++ AddStructure('dialog', m.group('id'))
++ for m in _VERSIONINFO.finditer(rctext):
++ AddStructure('version', m.group('id'))
++
++
++ def AddMessages(self, rctext, node):
++ '''Scans 'rctext' for all messages in string tables, preprocesses them as
++ much as possible for placeholders (e.g. messages containing $1, $2 or %s, %d
++ type format specifiers get those specifiers replaced with placeholders, and
++ HTML-formatted messages get run through the HTML-placeholderizer). Adds
++ each message as a <message> node child of 'node'.'''
++ for tm in _STRING_TABLE.finditer(rctext):
++ table = tm.group('body')
++ for mm in _MESSAGE.finditer(table):
++ comment_block = mm.group('comment')
++ comment_text = []
++ for cm in _COMMENT_TEXT.finditer(comment_block):
++ comment_text.append(cm.group('text'))
++ comment_text = ' '.join(comment_text)
++
++ id = mm.group('id')
++ text = rc.Section.UnEscape(mm.group('text'))
++
++ self.VerboseOut('Processing message %s (text: "%s")\n' % (id, text))
++
++ msg_obj = self.Placeholderize(text)
++
++ # Messages that contain only placeholders do not need translation.
++ is_translateable = False
++ for item in msg_obj.GetContent():
++ if isinstance(item, six.string_types):
++ if not _WHITESPACE_ONLY.match(item):
++ is_translateable = True
++
++ if self.not_localizable_re.search(comment_text):
++ is_translateable = False
++
++ message_meaning = ''
++ internal_comment = ''
++
++ # If we have a "role model" (existing GRD file) and this node exists
++ # in the role model, use the description, meaning and translateable
++ # attributes from the role model.
++ if self.role_model:
++ role_node = self.role_model.GetNodeById(id)
++ if role_node:
++ is_translateable = role_node.IsTranslateable()
++ message_meaning = role_node.attrs['meaning']
++ comment_text = role_node.attrs['desc']
++ internal_comment = role_node.attrs['internal_comment']
++
++ # For nontranslateable messages, we don't want the complexity of
++ # placeholderizing everything.
++ if not is_translateable:
++ msg_obj = tclib.Message(text=text)
++
++ msg_node = message.MessageNode.Construct(node, msg_obj, id,
++ desc=comment_text,
++ translateable=is_translateable,
++ meaning=message_meaning)
++ msg_node.attrs['internal_comment'] = internal_comment
++
++ node.AddChild(msg_node)
++ self.ExtraVerboseOut('Done processing message %s\n' % id)
++
++
++ def Placeholderize(self, text):
++ '''Creates a tclib.Message object from 'text', attempting to recognize
++ a few different formats of text that can be automatically placeholderized
++ (HTML code, printf-style format strings, and FormatMessage-style format
++ strings).
++ '''
++
++ try:
++ # First try HTML placeholderizing.
++ # TODO(joi) Allow use of non-TotalRecall flavors of HTML placeholderizing
++ msg = tr_html.HtmlToMessage(text, True)
++ for item in msg.GetContent():
++ if not isinstance(item, six.string_types):
++ return msg # Contained at least one placeholder, so we're done
++
++ # HTML placeholderization didn't do anything, so try to find printf or
++ # FormatMessage format specifiers and change them into placeholders.
++ msg = tclib.Message()
++ parts = _FORMAT_SPECIFIER.split(text)
++ todo_counter = 1 # We make placeholder IDs 'TODO_0001' etc.
++ for part in parts:
++ if _FORMAT_SPECIFIER.match(part):
++ msg.AppendPlaceholder(tclib.Placeholder(
++ 'TODO_%04d' % todo_counter, part, 'TODO'))
++ todo_counter += 1
++ elif part != '':
++ msg.AppendText(part)
++
++ if self.role_model and len(parts) > 1: # there are TODO placeholders
++ role_model_msg = self.role_model.UberClique().BestCliqueByOriginalText(
++ msg.GetRealContent(), '')
++ if role_model_msg:
++ # replace wholesale to get placeholder names and examples
++ msg = role_model_msg
++
++ return msg
++ except:
++ print('Exception processing message with text "%s"' % text)
++ raise
+diff --git a/tools/grit/grit/tool/rc2grd_unittest.py b/tools/grit/grit/tool/rc2grd_unittest.py
+new file mode 100644
+index 0000000000..6d53794c27
+--- /dev/null
++++ b/tools/grit/grit/tool/rc2grd_unittest.py
+@@ -0,0 +1,163 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.tool.rc2grd'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import re
++import unittest
++
++from six import StringIO
++
++from grit import grd_reader
++from grit import util
++from grit.node import base
++from grit.tool import rc2grd
++
++
++class Rc2GrdUnittest(unittest.TestCase):
++ def testPlaceholderize(self):
++ tool = rc2grd.Rc2Grd()
++ original = "Hello %s, how are you? I'm $1 years old!"
++ msg = tool.Placeholderize(original)
++ self.failUnless(msg.GetPresentableContent() == "Hello TODO_0001, how are you? I'm TODO_0002 years old!")
++ self.failUnless(msg.GetRealContent() == original)
++
++ def testHtmlPlaceholderize(self):
++ tool = rc2grd.Rc2Grd()
++ original = "Hello <b>[USERNAME]</b>, how are you? I'm [AGE] years old!"
++ msg = tool.Placeholderize(original)
++ self.failUnless(msg.GetPresentableContent() ==
++ "Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, how are you? I'm X_AGE_X years old!")
++ self.failUnless(msg.GetRealContent() == original)
++
++ def testMenuWithoutWhitespaceRegression(self):
++ # There was a problem in the original regular expression for parsing out
++ # menu sections, that would parse the following block of text as a single
++ # menu instead of two.
++ two_menus = '''
++// Hyper context menus
++IDR_HYPERMENU_FOLDER MENU
++BEGIN
++ POPUP "HyperFolder"
++ BEGIN
++ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
++ END
++END
++
++IDR_HYPERMENU_FILE MENU
++BEGIN
++ POPUP "HyperFile"
++ BEGIN
++ MENUITEM "Open Folder", IDM_OPENFOLDER
++ END
++END
++
++'''
++ self.failUnless(len(rc2grd._MENU.findall(two_menus)) == 2)
++
++ def testRegressionScriptWithTranslateable(self):
++ tool = rc2grd.Rc2Grd()
++
++ # test rig
++ class DummyNode(base.Node):
++ def AddChild(self, item):
++ self.node = item
++ verbose = False
++ extra_verbose = False
++ tool.not_localizable_re = re.compile('')
++ tool.o = DummyNode()
++
++ rc_text = '''STRINGTABLE\nBEGIN\nID_BINGO "<SPAN id=hp style='BEHAVIOR: url(#default#homepage)'></SPAN><script>if (!hp.isHomePage('[$~HOMEPAGE~$]')) {document.write(""<a href=\\""[$~SETHOMEPAGEURL~$]\\"" >Set As Homepage</a> - "");}</script>"\nEND\n'''
++ tool.AddMessages(rc_text, tool.o)
++ self.failUnless(tool.o.node.GetCdata().find('Set As Homepage') != -1)
++
++ # TODO(joi) Improve the HTML parser to support translateables inside
++ # <script> blocks?
++ self.failUnless(tool.o.node.attrs['translateable'] == 'false')
++
++ def testRoleModel(self):
++ rc_text = ('STRINGTABLE\n'
++ 'BEGIN\n'
++ ' // This should not show up\n'
++ ' IDS_BINGO "Hello %s, how are you?"\n'
++ ' // The first description\n'
++ ' IDS_BONGO "Hello %s, my name is %s, and yours?"\n'
++ ' IDS_PROGRAMS_SHUTDOWN_TEXT "Google Desktop Search needs to close the following programs:\\n\\n$1\\nThe installation will not proceed if you choose to cancel."\n'
++ 'END\n')
++ tool = rc2grd.Rc2Grd()
++ tool.role_model = grd_reader.Parse(StringIO(
++ '''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <message name="IDS_BINGO">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you?
++ </message>
++ <message name="IDS_BONGO" desc="The other description">
++ Hello <ph name="USERNAME">%s<ex>Jakob</ex></ph>, my name is <ph name="ADMINNAME">%s<ex>Joi</ex></ph>, and yours?
++ </message>
++ <message name="IDS_PROGRAMS_SHUTDOWN_TEXT" desc="LIST_OF_PROGRAMS is replaced by a bulleted list of program names.">
++ Google Desktop Search needs to close the following programs:
++
++<ph name="LIST_OF_PROGRAMS">$1<ex>Program 1, Program 2</ex></ph>
++The installation will not proceed if you choose to cancel.
++ </message>
++ </messages>
++ </release>
++ </grit>'''), dir='.')
++
++ # test rig
++ class DummyOpts(object):
++ verbose = False
++ extra_verbose = False
++ tool.o = DummyOpts()
++ result = tool.Process(rc_text, '.\resource.rc')
++ self.failUnless(
++ result.children[2].children[2].children[0].attrs['desc'] == '')
++ self.failUnless(
++ result.children[2].children[2].children[0].children[0].attrs['name'] == 'USERNAME')
++ self.failUnless(
++ result.children[2].children[2].children[1].attrs['desc'] == 'The other description')
++ self.failUnless(
++ result.children[2].children[2].children[1].attrs['meaning'] == '')
++ self.failUnless(
++ result.children[2].children[2].children[1].children[0].attrs['name'] == 'USERNAME')
++ self.failUnless(
++ result.children[2].children[2].children[1].children[1].attrs['name'] == 'ADMINNAME')
++ self.failUnless(
++ result.children[2].children[2].children[2].children[0].attrs['name'] == 'LIST_OF_PROGRAMS')
++
++ def testRunOutput(self):
++ """Verify basic correct Run behavior."""
++ tool = rc2grd.Rc2Grd()
++ class DummyOpts(object):
++ verbose = False
++ extra_verbose = False
++ with util.TempDir({}) as output_dir:
++ rcfile = os.path.join(output_dir.GetPath(), 'foo.rc')
++ open(rcfile, 'w').close()
++ self.assertIsNone(tool.Run(DummyOpts(), [rcfile]))
++ self.assertTrue(os.path.exists(os.path.join(output_dir.GetPath(), 'foo.grd')))
++
++ def testMissingOutput(self):
++ """Verify failure with no args."""
++ tool = rc2grd.Rc2Grd()
++ class DummyOpts(object):
++ verbose = False
++ extra_verbose = False
++ ret = tool.Run(DummyOpts(), [])
++ self.assertIsNotNone(ret)
++ self.assertGreater(ret, 0)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/resize.py b/tools/grit/grit/tool/resize.py
+new file mode 100644
+index 0000000000..6a897c077e
+--- /dev/null
++++ b/tools/grit/grit/tool/resize.py
+@@ -0,0 +1,295 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The 'grit resize' tool.
++'''
++
++from __future__ import print_function
++
++import getopt
++import os
++import sys
++
++from grit import grd_reader
++from grit import pseudo
++from grit import util
++from grit.format import rc
++from grit.format import rc_header
++from grit.node import include
++from grit.tool import interface
++
++
++# Template for the .vcproj file, with a couple of [[REPLACEABLE]] parts.
++PROJECT_TEMPLATE = '''\
++<?xml version="1.0" encoding="Windows-1252"?>
++<VisualStudioProject
++ ProjectType="Visual C++"
++ Version="7.10"
++ Name="[[DIALOG_NAME]]"
++ ProjectGUID="[[PROJECT_GUID]]"
++ Keyword="Win32Proj">
++ <Platforms>
++ <Platform
++ Name="Win32"/>
++ </Platforms>
++ <Configurations>
++ <Configuration
++ Name="Debug|Win32"
++ OutputDirectory="Debug"
++ IntermediateDirectory="Debug"
++ ConfigurationType="1"
++ CharacterSet="2">
++ </Configuration>
++ </Configurations>
++ <References>
++ </References>
++ <Files>
++ <Filter
++ Name="Resource Files"
++ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
++ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
++ <File
++ RelativePath=".\\[[DIALOG_NAME]].rc">
++ </File>
++ </Filter>
++ </Files>
++ <Globals>
++ </Globals>
++</VisualStudioProject>'''
++
++
++# Template for the .rc file with a couple of [[REPLACEABLE]] parts.
++# TODO(joi) Improve this (and the resource.h template) to allow saving and then
++# reopening of the RC file in Visual Studio. Currently you can only open it
++# once and change it, then after you close it you won't be able to reopen it.
++RC_TEMPLATE = '''\
++// This file is automatically generated by GRIT and intended for editing
++// the layout of the dialogs contained in it. Do not edit anything but the
++// dialogs. Any changes made to translateable portions of the dialogs will
++// be ignored by GRIT.
++
++#include "resource.h"
++#include <winresrc.h>
++#ifdef IDC_STATIC
++#undef IDC_STATIC
++#endif
++#define IDC_STATIC (-1)
++
++LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
++
++#pragma code_page([[CODEPAGE_NUM]])
++
++[[INCLUDES]]
++
++[[DIALOGS]]
++'''
++
++
++# Template for the resource.h file with a couple of [[REPLACEABLE]] parts.
++HEADER_TEMPLATE = '''\
++// This file is automatically generated by GRIT. Do not edit.
++
++#pragma once
++
++// Edit commands
++#define ID_EDIT_CLEAR 0xE120
++#define ID_EDIT_CLEAR_ALL 0xE121
++#define ID_EDIT_COPY 0xE122
++#define ID_EDIT_CUT 0xE123
++#define ID_EDIT_FIND 0xE124
++#define ID_EDIT_PASTE 0xE125
++#define ID_EDIT_PASTE_LINK 0xE126
++#define ID_EDIT_PASTE_SPECIAL 0xE127
++#define ID_EDIT_REPEAT 0xE128
++#define ID_EDIT_REPLACE 0xE129
++#define ID_EDIT_SELECT_ALL 0xE12A
++#define ID_EDIT_UNDO 0xE12B
++#define ID_EDIT_REDO 0xE12C
++
++
++[[DEFINES]]
++'''
++
++
++class ResizeDialog(interface.Tool):
++ '''Generates an RC file, header and Visual Studio project that you can use
++with Visual Studio's GUI resource editor to modify the layout of dialogs for
++the language of your choice. You then use the RC file, after you resize the
++dialog, for the language or languages of your choice, using the <skeleton> child
++of the <structure> node for the dialog. The translateable bits of the dialog
++will be ignored when you use the <skeleton> node (GRIT will instead use the
++translateable bits from the original dialog) but the layout changes you make
++will be used. Note that your layout changes must preserve the order of the
++translateable elements in the RC file.
++
++Usage: grit resize [-f BASEFOLDER] [-l LANG] [-e RCENCODING] DIALOGID*
++
++Arguments:
++ DIALOGID The 'name' attribute of a dialog to output for resizing. Zero
++ or more of these parameters can be used. If none are
++ specified, all dialogs from the input .grd file are output.
++
++Options:
++
++ -f BASEFOLDER The project will be created in a subfolder of BASEFOLDER.
++ The name of the subfolder will be the first DIALOGID you
++ specify. Defaults to '.'
++
++ -l LANG Specifies that the RC file should contain a dialog translated
++ into the language LANG. The default is a cp1252-representable
++ pseudotranslation, because Visual Studio's GUI RC editor only
++ supports single-byte encodings.
++
++ -c CODEPAGE Code page number to indicate to the RC compiler the encoding
++ of the RC file, default is something reasonable for the
++ language you selected (but this does not work for every single
++ language). See details on codepages below. NOTE that you do
++ not need to specify the codepage unless the tool complains
++ that it's not sure which codepage to use. See the following
++ page for codepage numbers supported by Windows:
++ http://www.microsoft.com/globaldev/reference/wincp.mspx
++
++ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
++ value VAL (defaults to 1) which will be used to control
++ conditional inclusion of resources.
++
++
++IMPORTANT NOTE: For now, the tool outputs a UTF-8 encoded file for any language
++that can not be represented in cp1252 (i.e. anything other than Western
++European languages). You will need to open this file in a text editor and
++save it using the codepage indicated in the #pragma code_page(XXXX) command
++near the top of the file, before you open it in Visual Studio.
++
++'''
++
++ # TODO(joi) It would be cool to have this tool note the Perforce revision
++ # of the original RC file somewhere, such that the <skeleton> node could warn
++ # if the original RC file gets updated without the skeleton file being updated.
++
++ # TODO(joi) Would be cool to have option to add the files to Perforce
++
++ def __init__(self):
++ self.lang = pseudo.PSEUDO_LANG
++ self.defines = {}
++ self.base_folder = '.'
++ self.codepage_number = 1252
++ self.codepage_number_specified_explicitly = False
++
++ def SetLanguage(self, lang):
++ '''Sets the language code to output things in.
++ '''
++ self.lang = lang
++ if not self.codepage_number_specified_explicitly:
++ self.codepage_number = util.LanguageToCodepage(lang)
++
++ def GetEncoding(self):
++ if self.codepage_number == 1200:
++ return 'utf_16'
++ if self.codepage_number == 65001:
++ return 'utf_8'
++ return 'cp%d' % self.codepage_number
++
++ def ShortDescription(self):
++ return 'Generate a file where you can resize a given dialog.'
++
++ def Run(self, opts, args):
++ self.SetOptions(opts)
++
++ own_opts, args = getopt.getopt(args, 'l:f:c:D:', ('help',))
++ for key, val in own_opts:
++ if key == '-l':
++ self.SetLanguage(val)
++ if key == '-f':
++ self.base_folder = val
++ if key == '-c':
++ self.codepage_number = int(val)
++ self.codepage_number_specified_explicitly = True
++ if key == '-D':
++ name, val = util.ParseDefine(val)
++ self.defines[name] = val
++ elif key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++
++ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
++ res_tree.OnlyTheseTranslations([self.lang])
++ res_tree.RunGatherers()
++
++ # Dialog IDs are either explicitly listed, or we output all dialogs from the
++ # .grd file
++ dialog_ids = args
++ if not len(dialog_ids):
++ for node in res_tree:
++ if node.name == 'structure' and node.attrs['type'] == 'dialog':
++ dialog_ids.append(node.attrs['name'])
++
++ self.Process(res_tree, dialog_ids)
++
++ def Process(self, grd, dialog_ids):
++ '''Outputs an RC file and header file for the dialog 'dialog_id' stored in
++ resource tree 'grd', to self.base_folder, as discussed in this class's
++ documentation.
++
++ Arguments:
++ grd: grd = grd_reader.Parse(...); grd.RunGatherers()
++ dialog_ids: ['IDD_MYDIALOG', 'IDD_OTHERDIALOG']
++ '''
++ grd.SetOutputLanguage(self.lang)
++ grd.SetDefines(self.defines)
++
++ project_name = dialog_ids[0]
++
++ dir_path = os.path.join(self.base_folder, project_name)
++ if not os.path.isdir(dir_path):
++ os.mkdir(dir_path)
++
++ # If this fails then we're not on Windows (or you don't have the required
++ # win32all Python libraries installed), so what are you doing mucking
++ # about with RC files anyway? :)
++ # pylint: disable=import-error
++ import pythoncom
++
++ # Create the .vcproj file
++ project_text = PROJECT_TEMPLATE.replace(
++ '[[PROJECT_GUID]]', str(pythoncom.CreateGuid())
++ ).replace('[[DIALOG_NAME]]', project_name)
++ fname = os.path.join(dir_path, '%s.vcproj' % project_name)
++ self.WriteFile(fname, project_text)
++ print("Wrote %s" % fname)
++
++ # Create the .rc file
++ # Output all <include> nodes since the dialogs might depend on them (e.g.
++ # for icons and bitmaps).
++ include_items = []
++ for node in grd.ActiveDescendants():
++ if isinstance(node, include.IncludeNode):
++ include_items.append(rc.FormatInclude(node, self.lang, '.'))
++ rc_text = RC_TEMPLATE.replace('[[CODEPAGE_NUM]]',
++ str(self.codepage_number))
++ rc_text = rc_text.replace('[[INCLUDES]]', ''.join(include_items))
++
++ # Then output the dialogs we have been asked to output.
++ dialogs = []
++ for dialog_id in dialog_ids:
++ node = grd.GetNodeById(dialog_id)
++ assert node.name == 'structure' and node.attrs['type'] == 'dialog'
++ # TODO(joi) Add exception handling for better error reporting
++ dialogs.append(rc.FormatStructure(node, self.lang, '.'))
++ rc_text = rc_text.replace('[[DIALOGS]]', ''.join(dialogs))
++
++ fname = os.path.join(dir_path, '%s.rc' % project_name)
++ self.WriteFile(fname, rc_text, self.GetEncoding())
++ print("Wrote %s" % fname)
++
++ # Create the resource.h file
++ header_defines = ''.join(rc_header.FormatDefines(grd))
++ header_text = HEADER_TEMPLATE.replace('[[DEFINES]]', header_defines)
++ fname = os.path.join(dir_path, 'resource.h')
++ self.WriteFile(fname, header_text)
++ print("Wrote %s" % fname)
++
++ def WriteFile(self, filename, contents, encoding='cp1252'):
++ with open(filename, 'wb') as f:
++ writer = util.WrapOutputStream(f, encoding)
++ writer.write(contents)
+diff --git a/tools/grit/grit/tool/test.py b/tools/grit/grit/tool/test.py
+new file mode 100644
+index 0000000000..241a976d74
+--- /dev/null
++++ b/tools/grit/grit/tool/test.py
+@@ -0,0 +1,24 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++from __future__ import print_function
++
++from grit.tool import interface
++
++class TestTool(interface.Tool):
++ '''This tool does nothing except print out the global options and
++tool-specific arguments that it receives. It is intended only for testing,
++hence the name :)
++'''
++
++ def ShortDescription(self):
++ return 'A do-nothing tool for testing command-line parsing.'
++
++ def Run(self, global_options, my_arguments):
++ print('NOTE This tool is only for testing the parsing of global options and')
++ print('tool-specific arguments that it receives. You may have intended to')
++ print('run "grit unit" which is the unit-test suite for GRIT.')
++ print('Options: %s' % repr(global_options))
++ print('Arguments: %s' % repr(my_arguments))
++ return 0
+diff --git a/tools/grit/grit/tool/transl2tc.py b/tools/grit/grit/tool/transl2tc.py
+new file mode 100644
+index 0000000000..45301bbf58
+--- /dev/null
++++ b/tools/grit/grit/tool/transl2tc.py
+@@ -0,0 +1,251 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''The 'grit transl2tc' tool.
++'''
++
++from __future__ import print_function
++
++from grit import grd_reader
++from grit import util
++from grit.tool import interface
++from grit.tool import rc2grd
++
++from grit.extern import tclib
++
++
++class TranslationToTc(interface.Tool):
++ '''A tool for importing existing translations in RC format into the
++Translation Console.
++
++Usage:
++
++grit -i GRD transl2tc [-l LIMITS] [RCOPTS] SOURCE_RC TRANSLATED_RC OUT_FILE
++
++The tool needs a "source" RC file, i.e. in English, and an RC file that is a
++translation of precisely the source RC file (not of an older or newer version).
++
++The tool also requires you to provide a .grd file (input file) e.g. using the
++-i global option or the GRIT_INPUT environment variable. The tool uses
++information from your .grd file to correct placeholder names in the
++translations and ensure that only translatable items and translations still
++being used are output.
++
++This tool will accept all the same RCOPTS as the 'grit rc2grd' tool. To get
++a list of these options, run 'grit help rc2grd'.
++
++Additionally, you can use the -l option (which must be the first option to the
++tool) to specify a file containing a list of message IDs to which output should
++be limited. This is only useful if you are limiting the output to your XMB
++files using the 'grit xmb' tool's -l option. See 'grit help xmb' for how to
++generate a file containing a list of the message IDs in an XMB file.
++
++The tool will scan through both of the RC files as well as any HTML files they
++refer to, and match together the source messages and translated messages. It
++will output a file (OUTPUT_FILE) you can import directly into the TC using the
++Bulk Translation Upload tool.
++'''
++
++ def ShortDescription(self):
++ return 'Import existing translations in RC format into the TC'
++
++ def Setup(self, globopt, args):
++ '''Sets the instance up for use.
++ '''
++ self.SetOptions(globopt)
++ self.rc2grd = rc2grd.Rc2Grd()
++ self.rc2grd.SetOptions(globopt)
++ self.limits = None
++ if len(args) and args[0] == '-l':
++ self.limits = util.ReadFile(args[1], 'utf-8').splitlines()
++ args = args[2:]
++ return self.rc2grd.ParseOptions(args, help_func=self.ShowUsage)
++
++ def Run(self, globopt, args):
++ args = self.Setup(globopt, args)
++
++ if len(args) != 3:
++ self.Out('This tool takes exactly three arguments:\n'
++ ' 1. The path to the original RC file\n'
++ ' 2. The path to the translated RC file\n'
++ ' 3. The output file path.\n')
++ return 2
++
++ grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
++ grd.RunGatherers()
++
++ source_rc = util.ReadFile(args[0], self.rc2grd.input_encoding)
++ transl_rc = util.ReadFile(args[1], self.rc2grd.input_encoding)
++ translations = self.ExtractTranslations(grd,
++ source_rc, args[0],
++ transl_rc, args[1])
++
++ with util.WrapOutputStream(open(args[2], 'wb')) as output_file:
++ self.WriteTranslations(output_file, translations.items())
++
++ self.Out('Wrote output file %s' % args[2])
++
++ def ExtractTranslations(self, current_grd, source_rc, source_path,
++ transl_rc, transl_path):
++ '''Extracts translations from the translated RC file, matching them with
++ translations in the source RC file to calculate their ID, and correcting
++ placeholders, limiting output to translateables, etc. using the supplied
++ .grd file which is the current .grd file for your project.
++
++ If this object's 'limits' attribute is not None but a list, the output of
++ this function will be further limited to include only messages that have
++ message IDs in the 'limits' list.
++
++ Args:
++ current_grd: grit.node.base.Node child, that has had RunGatherers() run
++ on it
++ source_rc: Complete text of source RC file
++ source_path: Path to the source RC file
++ transl_rc: Complete text of translated RC file
++ transl_path: Path to the translated RC file
++
++ Return:
++ { id1 : text1, '12345678' : 'Hello USERNAME, howzit?' }
++ '''
++ source_grd = self.rc2grd.Process(source_rc, source_path)
++ self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % source_path)
++ source_grd.SetOutputLanguage(current_grd.output_language)
++ source_grd.SetDefines(current_grd.defines)
++ source_grd.RunGatherers(debug=self.o.extra_verbose)
++ transl_grd = self.rc2grd.Process(transl_rc, transl_path)
++ transl_grd.SetOutputLanguage(current_grd.output_language)
++ transl_grd.SetDefines(current_grd.defines)
++ self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % transl_path)
++ transl_grd.RunGatherers(debug=self.o.extra_verbose)
++ self.VerboseOut('Done running gatherers for %s.\n' % transl_path)
++
++ # Proceed to create a map from ID to translation, getting the ID from the
++ # source GRD and the translation from the translated GRD.
++ id2transl = {}
++ for source_node in source_grd:
++ source_cliques = source_node.GetCliques()
++ if not len(source_cliques):
++ continue
++
++ assert 'name' in source_node.attrs, 'All nodes with cliques should have an ID'
++ node_id = source_node.attrs['name']
++ self.ExtraVerboseOut('Processing node %s\n' % node_id)
++ transl_node = transl_grd.GetNodeById(node_id)
++
++ if transl_node:
++ transl_cliques = transl_node.GetCliques()
++ if not len(transl_cliques) == len(source_cliques):
++ self.Out(
++ 'Warning: Translation for %s has wrong # of cliques, skipping.\n' %
++ node_id)
++ continue
++ else:
++ self.Out('Warning: No translation for %s, skipping.\n' % node_id)
++ continue
++
++ if source_node.name == 'message':
++ # Fixup placeholders as well as possible based on information from
++ # the current .grd file if they are 'TODO_XXXX' placeholders. We need
++ # to fixup placeholders in the translated message so that it looks right
++ # and we also need to fixup placeholders in the source message so that
++ # its calculated ID will match the current message.
++ current_node = current_grd.GetNodeById(node_id)
++ if current_node:
++ assert len(source_cliques) == len(current_node.GetCliques()) == 1
++
++ source_msg = source_cliques[0].GetMessage()
++ current_msg = current_node.GetCliques()[0].GetMessage()
++
++ # Only do this for messages whose source version has not changed.
++ if (source_msg.GetRealContent() != current_msg.GetRealContent()):
++ self.VerboseOut('Info: Message %s has changed; skipping\n' % node_id)
++ else:
++ transl_msg = transl_cliques[0].GetMessage()
++ transl_content = transl_msg.GetContent()
++ current_content = current_msg.GetContent()
++ source_content = source_msg.GetContent()
++
++ ok_to_fixup = True
++ if (len(transl_content) != len(current_content)):
++ # message structure of translation is different, don't try fixup
++ ok_to_fixup = False
++ if ok_to_fixup:
++ for ix in range(len(transl_content)):
++ if isinstance(transl_content[ix], tclib.Placeholder):
++ if not isinstance(current_content[ix], tclib.Placeholder):
++ ok_to_fixup = False # structure has changed
++ break
++ if (transl_content[ix].GetOriginal() !=
++ current_content[ix].GetOriginal()):
++ ok_to_fixup = False # placeholders have likely been reordered
++ break
++ else: # translated part is not a placeholder but a string
++ if isinstance(current_content[ix], tclib.Placeholder):
++ ok_to_fixup = False # placeholders have likely been reordered
++ break
++
++ if not ok_to_fixup:
++ self.VerboseOut(
++ 'Info: Structure of message %s has changed; skipping.\n' % node_id)
++ else:
++ def Fixup(content, ix):
++ if (isinstance(content[ix], tclib.Placeholder) and
++ content[ix].GetPresentation().startswith('TODO_')):
++ assert isinstance(current_content[ix], tclib.Placeholder)
++ # Get the placeholder ID and example from the current message
++ content[ix] = current_content[ix]
++ for ix in range(len(transl_content)):
++ Fixup(transl_content, ix)
++ Fixup(source_content, ix)
++
++ # Only put each translation once into the map. Warn if translations
++ # for the same message are different.
++ for ix in range(len(transl_cliques)):
++ source_msg = source_cliques[ix].GetMessage()
++ source_msg.GenerateId() # needed to refresh ID based on new placeholders
++ message_id = source_msg.GetId()
++ translated_content = transl_cliques[ix].GetMessage().GetPresentableContent()
++
++ if message_id in id2transl:
++ existing_translation = id2transl[message_id]
++ if existing_translation != translated_content:
++ original_text = source_cliques[ix].GetMessage().GetPresentableContent()
++ self.Out('Warning: Two different translations for "%s":\n'
++ ' Translation 1: "%s"\n'
++ ' Translation 2: "%s"\n' %
++ (original_text, existing_translation, translated_content))
++ else:
++ id2transl[message_id] = translated_content
++
++ # Remove translations for messages that do not occur in the current .grd
++ # or have been marked as not translateable, or do not occur in the 'limits'
++ # list (if it has been set).
++ current_message_ids = current_grd.UberClique().AllMessageIds()
++ for message_id in list(id2transl.keys()):
++ if (message_id not in current_message_ids or
++ not current_grd.UberClique().BestClique(message_id).IsTranslateable() or
++ (self.limits and message_id not in self.limits)):
++ del id2transl[message_id]
++
++ return id2transl
++
++ @staticmethod
++ def WriteTranslations(output_file, translations):
++ '''Writes the provided list of translations to the provided output file
++ in the format used by the TC's Bulk Translation Upload tool. The file
++ must be UTF-8 encoded.
++
++ Args:
++ output_file: util.WrapOutputStream(open('bingo.out', 'wb'))
++ translations: [ [id1, text1], ['12345678', 'Hello USERNAME, howzit?'] ]
++
++ Return:
++ None
++ '''
++ for id, text in translations:
++ text = text.replace('<', '&lt;').replace('>', '&gt;')
++ output_file.write(id)
++ output_file.write(' ')
++ output_file.write(text)
++ output_file.write('\n')
+diff --git a/tools/grit/grit/tool/transl2tc_unittest.py b/tools/grit/grit/tool/transl2tc_unittest.py
+new file mode 100644
+index 0000000000..22e937f9f2
+--- /dev/null
++++ b/tools/grit/grit/tool/transl2tc_unittest.py
+@@ -0,0 +1,133 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for the 'grit transl2tc' tool.'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++
++from six import StringIO
++
++from grit.tool import transl2tc
++from grit import grd_reader
++from grit import util
++
++
++def MakeOptions():
++ from grit import grit_runner
++ return grit_runner.Options()
++
++
++class TranslationToTcUnittest(unittest.TestCase):
++
++ def testOutput(self):
++ buf = StringIO()
++ tool = transl2tc.TranslationToTc()
++ translations = [
++ ['1', 'Hello USERNAME, how are you?'],
++ ['12', 'Howdie doodie!'],
++ ['123', 'Hello\n\nthere\n\nhow are you?'],
++ ['1234', 'Hello is > goodbye but < howdie pardner'],
++ ]
++ tool.WriteTranslations(buf, translations)
++ output = buf.getvalue()
++ self.failUnless(output.strip() == '''
++1 Hello USERNAME, how are you?
++12 Howdie doodie!
++123 Hello
++
++there
++
++how are you?
++1234 Hello is &gt; goodbye but &lt; howdie pardner
++'''.strip())
++
++ def testExtractTranslations(self):
++ path = util.PathFromRoot('grit/testdata')
++ current_grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <message name="IDS_SIMPLE">
++ One
++ </message>
++ <message name="IDS_PLACEHOLDER">
++ <ph name="NUMBIRDS">%s<ex>3</ex></ph> birds
++ </message>
++ <message name="IDS_PLACEHOLDERS">
++ <ph name="ITEM">%d<ex>1</ex></ph> of <ph name="COUNT">%d<ex>3</ex></ph>
++ </message>
++ <message name="IDS_REORDERED_PLACEHOLDERS">
++ <ph name="ITEM">$1<ex>1</ex></ph> of <ph name="COUNT">$2<ex>3</ex></ph>
++ </message>
++ <message name="IDS_CHANGED">
++ This is the new version
++ </message>
++ <message name="IDS_TWIN_1">Hello</message>
++ <message name="IDS_TWIN_2">Hello</message>
++ <message name="IDS_NOT_TRANSLATEABLE" translateable="false">:</message>
++ <message name="IDS_LONGER_TRANSLATED">
++ Removed document <ph name="FILENAME">$1<ex>c:\temp</ex></ph>
++ </message>
++ <message name="IDS_DIFFERENT_TWIN_1">Howdie</message>
++ <message name="IDS_DIFFERENT_TWIN_2">Howdie</message>
++ </messages>
++ <structures>
++ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
++ <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
++ </structures>
++ </release>
++ </grit>'''), path)
++ current_grd.SetOutputLanguage('en')
++ current_grd.RunGatherers()
++
++ source_rc_path = util.PathFromRoot('grit/testdata/source.rc')
++ source_rc = util.ReadFile(source_rc_path, 'utf-8')
++ transl_rc_path = util.PathFromRoot('grit/testdata/transl.rc')
++ transl_rc = util.ReadFile(transl_rc_path, 'utf-8')
++
++ tool = transl2tc.TranslationToTc()
++ output_buf = StringIO()
++ globopts = MakeOptions()
++ globopts.verbose = True
++ globopts.output_stream = output_buf
++ tool.Setup(globopts, [])
++ translations = tool.ExtractTranslations(current_grd,
++ source_rc, source_rc_path,
++ transl_rc, transl_rc_path)
++
++ values = list(translations.values())
++ output = output_buf.getvalue()
++
++ self.failUnless('Ein' in values)
++ self.failUnless('NUMBIRDS Vogeln' in values)
++ self.failUnless('ITEM von COUNT' in values)
++ self.failUnless(values.count('Hallo') == 1)
++ self.failIf('Dass war die alte Version' in values)
++ self.failIf(':' in values)
++ self.failIf('Dokument FILENAME ist entfernt worden' in values)
++ self.failIf('Nicht verwendet' in values)
++ self.failUnless(('Howdie' in values or 'Hallo sagt man' in values) and not
++ ('Howdie' in values and 'Hallo sagt man' in values))
++
++ self.failUnless('XX01XX&SkraXX02XX&HaettaXX03XXThetta er "Klonk" sem eg fylaXX04XXgonkurinnXX05XXKlonk && er [good]XX06XX&HjalpXX07XX&Um...XX08XX' in values)
++
++ self.failUnless('I lagi' in values)
++
++ self.failUnless(output.count('Structure of message IDS_REORDERED_PLACEHOLDERS has changed'))
++ self.failUnless(output.count('Message IDS_CHANGED has changed'))
++ self.failUnless(output.count('Structure of message IDS_LONGER_TRANSLATED has changed'))
++ self.failUnless(output.count('Two different translations for "Howdie"'))
++ self.failUnless(output.count('IDD_DIFFERENT_LENGTH_IN_TRANSL has wrong # of cliques'))
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/unit.py b/tools/grit/grit/tool/unit.py
+new file mode 100644
+index 0000000000..7e96b699c3
+--- /dev/null
++++ b/tools/grit/grit/tool/unit.py
+@@ -0,0 +1,43 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''GRIT tool that runs the unit test suite for GRIT.'''
++
++from __future__ import print_function
++
++import getopt
++import sys
++import unittest
++
++try:
++ import grit.test_suite_all
++except ImportError:
++ pass
++from grit.tool import interface
++
++
++class UnitTestTool(interface.Tool):
++ '''By using this tool (e.g. 'grit unit') you run all the unit tests for GRIT.
++This happens in the environment that is set up by the basic GRIT runner.'''
++
++ def ShortDescription(self):
++ return 'Use this tool to run all the unit tests for GRIT.'
++
++ def ParseOptions(self, args):
++ """Set this objects and return all non-option arguments."""
++ own_opts, args = getopt.getopt(args, '', ('help',))
++ for key, val in own_opts:
++ if key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++ return args
++
++ def Run(self, opts, args):
++ args = self.ParseOptions(args)
++ if args:
++ print('This tool takes no arguments.')
++ return 2
++
++ return unittest.TextTestRunner(verbosity=2).run(
++ grit.test_suite_all.TestSuiteAll())
+diff --git a/tools/grit/grit/tool/update_resource_ids/__init__.py b/tools/grit/grit/tool/update_resource_ids/__init__.py
+new file mode 100644
+index 0000000000..3006fbffab
+--- /dev/null
++++ b/tools/grit/grit/tool/update_resource_ids/__init__.py
+@@ -0,0 +1,305 @@
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++"""Package grit.tool.update_resource_ids
++
++Updates GRID resource_ids from linked GRD files, while preserving structure.
++
++A resource_ids file is a JSON dict (with Python comments) that maps GRD paths
++to *items*. Item order is ignored by GRIT, but is important since it establishes
++a narrative of item dependency (needs non-overlapping IDs) and mutual exclusion
++(allows ID overlap). Example:
++
++{
++ # The first entry in the file, SRCDIR, is special: It is a relative path from
++ # this file to the base of your checkout.
++ "SRCDIR": "../..",
++
++ # First GRD file. This entry is an "Item".
++ "1.grd": {
++ "messages": [400], # "Tag".
++ },
++ # Depends on 1.grd, i.e., 500 >= 400 + (# of IDs used in 1.grd).
++ "2a.grd": {
++ "includes": [500], # "Tag".
++ "structures": [510], # "Tag" (etc.).
++ },
++ # Depends on 2a.grd.
++ "3a.grd": {
++ "includes": [1000],
++ },
++ # Depends on 2a.grd, but overlaps with 3b.grd due to mutually exclusivity.
++ "3b.grd": {
++ "includes": [1000],
++ },
++ # Depends on {3a.grd, 3b.grd}.
++ "4.grd": {
++ "META": {"join": 2}, # Hint for update_resource_ids.
++ "structures": [1500],
++ },
++ # Depends on 1.grd but overlaps with 2a.grd.
++ "2b.grd": {
++ "includes": [500],
++ "structures": [540],
++ },
++ # Depends on {4.grd, 2b.grd}.
++ "5.grd": {
++ "META": {"join": 2}, # Hint for update_resource_ids.
++ "includes": [600],
++ },
++ # Depends on 5.grd. File is generated, so hint is needed for sizes.
++ "<(SHARED_INTERMEDIATE_DIR)/6.grd": {
++ "META": {"sizes": {"includes": [10]}},
++ "includes": [700],
++ },
++}
++
++The "structure" within a resouces_ids file are as follows:
++1. Comments and spacing.
++2. Item ordering, to establish dependency and grouping.
++3. Special provision to allow ID overlaps from mutual exclusion.
++
++This module parses a resource_ids file, reads ID usages from GRD files it refers
++to, and generates an updated version of the resource_ids file while preserving
++structure elements 1-3 stated above.
++"""
++
++from __future__ import print_function
++
++import collections
++import getopt
++import os
++import shutil
++import sys
++import tempfile
++
++from grit.tool import interface
++from grit.tool.update_resource_ids import assigner, common, parser, reader
++
++
++def _ReadData(input_file):
++ if input_file == '-':
++ data = sys.stdin.read()
++ file_dir = os.getcwd()
++ else:
++ with open(input_file, 'rt') as f:
++ data = f.read()
++ file_dir = os.path.dirname(input_file)
++ return data, file_dir
++
++
++def _MultiReplace(data, repl):
++ """Multi-replacement of text |data| by ranges and replacement text.
++
++ Args:
++ data: Original text.
++ repl: List of (lo, hi, s) tuples, specifying that |data[lo:hi]| should be
++ replaced with |s|. The ranges must be inside |data|, and not overlap.
++ Returns: New text.
++ """
++ res = []
++ prev = 0
++ for (lo, hi, s) in sorted(repl):
++ if prev < lo:
++ res.append(data[prev:lo])
++ res.append(s)
++ prev = hi
++ res.append(data[prev:])
++ return ''.join(res)
++
++
++def _WriteFileIfChanged(output, new_data):
++ if not output:
++ sys.stdout.write(new_data)
++ return
++
++ # Avoid touching outputs if file contents has not changed so that ninja
++ # does not rebuild dependent when not necessary.
++ if os.path.exists(output) and _ReadData(output)[0] == new_data:
++ return
++
++ # Write to a temporary file to ensure atomic changes.
++ with tempfile.NamedTemporaryFile('wt', delete=False) as f:
++ f.write(new_data)
++ shutil.move(f.name, output)
++
++
++class _Args:
++ """Encapsulated arguments for this module."""
++ def __init__(self):
++ self.add_header = False
++ self.analyze_inputs = False
++ self.count = False
++ self.depfile = None
++ self.fake = False
++ self.input = None
++ self.naive = False
++ self.output = None
++ self.parse = False
++ self.tokenize = False
++
++ @staticmethod
++ def Parse(raw_args):
++ own_opts, raw_args = getopt.getopt(raw_args, 'o:cpt', [
++ 'add-header',
++ 'analyze-inputs',
++ 'count',
++ 'depfile=',
++ 'fake',
++ 'naive',
++ 'parse',
++ 'tokenize',
++ ])
++ args = _Args();
++ if not len(raw_args) == 1:
++ print('grit update_resource_ids takes exactly one argument, the path to '
++ 'the resource ids file.')
++ return 2
++ args.input = raw_args[0]
++ for (key, val) in own_opts:
++ if key == '-o':
++ args.output = val
++ elif key == '--add-header':
++ args.add_header = True
++ elif key == '--analyze-inputs':
++ args.analyze_inputs = True
++ elif key in ('--count', '-c'):
++ args.count = True
++ elif key == '--depfile':
++ args.depfile = val
++ elif key == '--fake':
++ args.fake = True
++ elif key == '--naive':
++ args.naive = True
++ elif key in ('--parse', '-p'):
++ args.parse = True
++ elif key in ('--tokenize', '-t'):
++ args.tokenize = True
++ return args
++
++
++class UpdateResourceIds(interface.Tool):
++ """Updates all start IDs in an resource_ids file by reading all GRD files it
++refers to, estimating the number of required IDs of each type, then rewrites
++start IDs while preserving structure.
++
++Usage: grit update_resource_ids [--parse|-p] [--read-grd|-r] [--tokenize|-t]
++ [--naive] [--fake] [-o OUTPUT_FILE]
++ [--analyze-inputs] [--depfile DEPFILE]
++ [--add-header] RESOURCE_IDS_FILE
++
++RESOURCE_IDS_FILE is the path of the input resource_ids file.
++
++The -o option redirects output (default stdout) to OUPTUT_FILE, which can also
++be RESOURCE_IDS_FILE.
++
++Other options:
++
++ -E NAME=VALUE Sets environment variable NAME to VALUE (within grit).
++
++ --count|-c Parses RESOURCE_IDS_FILE, reads the GRD files, and prints
++ required sizes.
++
++ --fake For testing: Skips reading GRD files, and assigns 10 as the
++ usage of every tag.
++
++ --naive Use naive coarse assigner.
++
++ --parse|-p Parses RESOURCE_IDS_FILE and dumps its nodes to console.
++
++ --tokenize|-t Tokenizes RESOURCE_IDS_FILE and reprints it as syntax-
++ highlighted output.
++
++ --depfile=DEPFILE Write out a depfile for ninja to know about dependencies.
++ --analyze-inputs Writes dependencies to stdout.
++ --add-header Adds a "THIS FILE IS GENERATED" header to the output.
++"""
++
++ def __init(self):
++ super(UpdateResourceIds, self).__init__()
++
++ def ShortDescription(self):
++ return 'Updates a resource_ids file based on usage, preserving structure'
++
++ def _DumpTokens(self, data, tok_gen):
++ # Reprint |data| with syntax highlight.
++ color_map = {
++ '#': common.Color.GRAY,
++ 'S': common.Color.CYAN,
++ '0': common.Color.RED,
++ '{': common.Color.YELLOW,
++ '}': common.Color.YELLOW,
++ '[': common.Color.GREEN,
++ ']': common.Color.GREEN,
++ ':': common.Color.MAGENTA,
++ ',': common.Color.MAGENTA,
++ }
++ for t, lo, hi in tok_gen:
++ c = color_map.get(t, common.Color.NONE)
++ sys.stdout.write(c(data[lo:hi]))
++
++ def _DumpRootObj(self, root_obj):
++ print(root_obj)
++
++ def _DumpResourceCounts(self, usage_gen):
++ tot = collections.Counter()
++ for item, tag_name_to_usage in usage_gen:
++ c = common.Color.YELLOW if item.grd.startswith('<') else common.Color.CYAN
++ print('%s: %r' % (c(item.grd), dict(tag_name_to_usage)))
++ tot += collections.Counter(tag_name_to_usage)
++ print(common.Color.GRAY('-' * 80))
++ print('%s: %r' % (common.Color.GREEN('Total'), dict(tot)))
++ print('%s: %d' % (common.Color.GREEN('Grand Total'), sum(tot.values())))
++
++ def Run(self, opts, raw_args):
++ self.SetOptions(opts)
++
++ args = _Args.Parse(raw_args)
++ data, file_dir = _ReadData(args.input)
++
++ tok_gen = parser.Tokenize(data)
++ if args.tokenize:
++ return self._DumpTokens(data, tok_gen)
++
++ root_obj = parser.ResourceIdParser(data, tok_gen).Parse()
++ if args.parse:
++ return self._DumpRootObj(root_obj)
++ item_list = common.BuildItemList(root_obj)
++
++ src_dir = os.path.normpath(os.path.join(file_dir, root_obj['SRCDIR'].val))
++ seen_files = set()
++ usage_gen = reader.GenerateResourceUsages(item_list, src_dir, args.fake,
++ seen_files)
++ if args.count:
++ return self._DumpResourceCounts(usage_gen)
++ for item, tag_name_to_usage in usage_gen:
++ item.SetUsages(tag_name_to_usage)
++
++ if args.analyze_inputs:
++ print('\n'.join(sorted(seen_files)))
++ return 0
++
++ new_ids_gen = assigner.GenerateNewIds(item_list, args.naive)
++ # Create replacement specs usable by _MultiReplace().
++ repl = [(tag.lo, tag.hi, str(new_id)) for tag, new_id in new_ids_gen]
++ rel_input_dir = args.input
++ # Update "SRCDIR" entry if output is specified.
++ if args.output:
++ new_srcdir = os.path.relpath(src_dir, os.path.dirname(args.output))
++ repl.append((root_obj['SRCDIR'].lo, root_obj['SRCDIR'].hi,
++ repr(new_srcdir)))
++ rel_input_dir = os.path.join('$SRCDIR',
++ os.path.relpath(rel_input_dir, new_srcdir))
++
++ new_data = _MultiReplace(data, repl)
++ if args.add_header:
++ header = []
++ header.append('# GENERATED FILE.')
++ header.append('# Edit %s instead.' % rel_input_dir)
++ header.append('#' * 80)
++ new_data = '\n'.join(header + ['']) + new_data
++ _WriteFileIfChanged(args.output, new_data)
++
++ if args.depfile:
++ deps_data = '{}: {}'.format(args.output, ' '.join(sorted(seen_files)))
++ _WriteFileIfChanged(args.depfile, deps_data)
+diff --git a/tools/grit/grit/tool/update_resource_ids/assigner.py b/tools/grit/grit/tool/update_resource_ids/assigner.py
+new file mode 100644
+index 0000000000..6cd46031a6
+--- /dev/null
++++ b/tools/grit/grit/tool/update_resource_ids/assigner.py
+@@ -0,0 +1,286 @@
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++"""Assign IDs to resource_ids file based on usage, while preserving structure.
++
++resource_ids assignment is divided into two parts:
++(A) Coarse assignment: Assigns start IDs of items.
++(B) Quota assignment: Assigns per-tag ID allotments for a given item, allowing
++ padding for IDs.
++
++These parts are interdependent: Start IDs (A) of an item depends on ID
++allotments (B) of *other* items; and ID allotment (B) of an item depends on its
++start IDs (A) to compute alignment.
++
++(B) hides padding and alignment details of tags so that (A) can be abstracted
++into the graph construction and traversal problem in DagCoarseIdAssigner.
++"""
++
++import math
++
++from grit.tool.update_resource_ids import common
++
++
++class Aligner:
++ """Helper to allot IDs, given start ID and ID usage.
++
++ Args:
++ expand: Scale factor relative to ID usage. Must be >= 1.0.
++ slack: Minimum number of reserved ID at end. Must be >= 0.
++ align: ID alignment of results. Must be >= 1.
++ """
++
++ def __init__(self, expand=1.0, slack=0, align=1):
++ assert expand >= 1.0 and slack >= 0 and align >= 1
++ self._expand = expand
++ self._slack = slack
++ self._align = align
++
++ def Calc(self, cur_id, usage):
++ quota = max(int(math.ceil(usage * self._expand)), usage + self._slack)
++ return common.AlignUp(cur_id + quota, self._align)
++
++
++class QuotaAssigner:
++ """Main class for (B), for ID allotment of tags for an item."""
++
++ def __init__(self, aligner):
++ self._aligner = aligner
++
++ def Gen(self, item, start_id):
++ """Generates per-tag *end* ID in |item|, succeeding |start_id|."""
++ cur_id = start_id
++ for tag in item.tags: # Sorted by |tag.lo|.
++ cur_id = self._aligner.Calc(cur_id, tag.usage)
++ yield tag, cur_id
++
++
++class BaseCoarseIdAssigner(object):
++ """Base class for coarse assignment."""
++
++ def __init__(self, item_list, align):
++ self._item_list = item_list
++ self._align = align
++
++ def GenStartIds(self):
++ """Visits |_item_list| and yields (|item|, new |start_id|).
++
++ Visit follows dependency order: If item B succeeds item A, then A is visited
++ before B. Caller must call FeedWeight() to assign ID allotment.
++ """
++ raise NotImplementedError()
++
++ def FeedWeight(self, item, weight):
++ """Callback to assign number of IDs allotted to |item|."""
++ raise NotImplementedError()
++
++
++class NaiveCoarseIdAssigner(BaseCoarseIdAssigner):
++ """CoarseIdAssigner that assigns item with non-overlapping start IDs."""
++
++ def __init__(self, item_list, align):
++ super(NaiveCoarseIdAssigner, self).__init__(item_list, align)
++ first_id = self._item_list[0].tags[0].id
++ self._cur_id = common.AlignUp(first_id, self._align)
++
++ def GenStartIds(self):
++ """Visits items in array order."""
++ for item in self._item_list:
++ yield item, self._cur_id
++
++ def FeedWeight(self, item, weight):
++ self._cur_id = common.AlignUp(self._cur_id + weight, self._align)
++
++
++class DagCoarseIdAssigner(BaseCoarseIdAssigner):
++ """CoarseIdAssigner that preserves existing structure.
++
++Start ID assignment in resource_ids is structured a Series-Parallel Graph, which
++is a directed, acyclic multi-graph generated by the following:
++* Start: Single directed edge. S <-- T.
++* Operation 1: A <-- B becomes A <-- C <-- B.
++* Operation 2: A <-- B becomes A <== B (add parallel edge).
++
++Each vertex (A, B, ...) is a start ID. S = globally minimal ID. T = \infty is an
++implicit sentinel. Each edge maps to an item, and edge weight is ID allotment.
++The edge A <-- B means "A's ID assignment needs to be determined before B's"
++(i.e., "B depends on A"), and requires A < B.
++
++resource_ids stores a "flattened" representation of the graph, as a list of
++items (with meta data). Thus coarse ID assignment consists of the following:
++(1) Process list of items (with old start ID and meta data) to rebuild graph.
++(2) Traverse graph in an order that satisfies dependencies.
++(3) When vertex A has its ID assigned, the weight of each edge "A <--" (i.e., an
++ item) can have its weight (ID allotment) computed via quota assignment of A.
++(4) New start IDs satisfy A + w <= B for each edge A <-- B with weight w > 0.
++
++The key algorithm challenge is (1). Note that it does not need weight details,
++so we only assume A < B whenever A <-- B. Now we're faced with 2 subproblems:
++(1a) How to represent the graph as a list of integers (with meta data)?
++(1b) Given the list representation, how to recover the graph?
++
++For (1a), we start with DFS traversal of the (transposed, i.e., reversed) graph
++starting from S, and apply the following:
++* For each edge A <-- B traversed, emit A into sequence,
++* Traverse a B <-- Y only when all X <-- B have been traversed.
++
++The resulting sequence has the length as the number of edges, and has the useful
++property that a vertex's dependencies always appear before the vertex itself!
++Note this the sentinel T is omitted.
++
++Example 1:
++ S <-- A <-- B <-- C <-- T => "SABC".
++
++Example 2:
++ S <-- A <-- B <-- C <-- T => "SA|AB|SDEC|SF",
++ | | | | | or "SF|SA|AB|SDEC",
++ | + <-- + | | or "SDE|SA|ABC|SF",
++ | | | or "SF|SDE|SA|ABC".
++ + <---D <-- E <---+ |
++ | |
++ + <-- F <---------------+
++
++Here, "X|Y" denotes backtracking between visiting X and visiting Y. This appears
++if and only if X >= Y, so "|" an optional (but illustrative) character that's
++not in the actual output. We will use it consistently in comments, and so the
++absence of "|" denotes the converse. For example, "XY" implies X < Y.
++
++In terms of the basic operations:
++* Start: S <-- T => "S".
++* Operation 1: "...AB..." => "...ACB..." (or "...A" => "...AB").
++* Operation 2: "...AB..." => "...A|AB..." (or "...A" => "...A|A").
++
++For Example 2, a viable "evolution path" is:
++"S" => "S|S" => "SC|S" => "S|SC|S" => "SA|SC|S" => "SAB|SC|S" => "SA|AB|SC|S"
++ => "SA|AB|SDC|S" => "SA|AB|SDEC|S" => "SA|AB|SDEC|SF".
++(Alternative: "S|S" => "S|SC" => etc.).
++
++Note: {A, ...} are *unlabelled* integers, and "spurious equalities" such as
++A = D or A = F can occur!
++
++For (1b), we wish to build the graph from the sequence. This requires (1a) to be
++injective (up to isomorphism). Unfortunately, this does not always hold.
++Example:
++ S <-- A <-- C <-- D <-- T => "SA|SBCD".
++ | |
++ + <-- B <---+
++vs.
++ S <----- A <----- D <-- T => "SA|SBCD".
++ | |
++ + <-- B <-- C <---+
++
++To fix this, we prepend a "join" label (*) to each vertex that has multiple
++dependencies. With this, the example above produce different results:
++ "SA|SB*CD" != "SA|SBC*D".
++
++Unfortunately, this is also inadequate. Example:
++ S <-------- B <-- T => "S|S|S|S*A*B",
++ | |
++ + <---------+
++ | |
++ + <-- A <---+
++ | |
++ + <---+
++vs.
++ S <-------- B <-- T => "S|S|S|S*A*B".
++ | |
++ + <---A <---+
++ | |
++ + <---+
++ | |
++ + <---+
++
++To fix this, we also label the number of dependencies. In text representation,
++we just show multiple (#dependencies - 1) copies of '*'. Now we have:
++ "S|S|S|S*A**B" != "S|S|S|S**A*B".
++
++The "join" label with count adequately addresses the issue (proof omitted). In
++the resource_ids files, these are stored as the "join" field of an item's meta
++data.
++
++Additional comments for (1b) and other steps are detailed below.
++"""
++
++ class DagNode:
++ """An element of the implicit graph, corresponding to an item.
++
++ This actually represents an edge-vertex pair, corresponding to an item.
++ A vertex is represented by a collection of DagNode that uses |sib| to link
++ to a "representative node". The representative node, in turn, holds the list
++ of all |deps| (dependencies) of the vertex.
++ """
++
++ def __init__(self, item, old_id):
++ self.item = item
++ self.old_id = old_id
++ self.new_id = None
++ self.weight = None
++
++ def __init__(self, item_list, align):
++ super(DagCoarseIdAssigner, self).__init__(item_list, align)
++ self._node_dict = {} # Maps from |lo| to item.
++
++ def GenStartIds(self):
++ """Traverses implicit graph and yields new IDs.
++
++ Algorithm: Process |old_id| of items sequentially. Successive items A and B
++ can be "AB" (A < B), "A*...B" (A < B), or "A|B" (A >= B). "AB" and "A*...B"
++ imply A <-- B, and are accumulated in |trace|. "A|B" are jumps that rewinds
++ |trace| to the latest B (must exist), and A is pushed into |jumps|. A join
++ "A*...B" also pops |num_join - 1| items {X_i} in |jump|, and X_i <-- B. In
++ the end, unprocessed elements in |jumps| all link to sentinel T, and can be
++ ignored.
++ """
++ # DagNode stack of "A" when "AB" is found (increasing |old_id|).
++ trace = []
++ # DagNode stack of "A" when "A|B" jumps is found.
++ jumps = []
++ for item in self._item_list: # Sorted by |lo|.
++ meta = item.meta
++ # |num_join| indicates "*" in "A*...B", and specify B's dependencies: +1
++ # from A, and +count("*") from |jumps|.
++ num_join = meta['join'].val if meta and 'join' in meta else None
++ node = DagCoarseIdAssigner.DagNode(item, item.tags[0].id)
++ self._node_dict[item.lo] = node
++ if trace:
++ if trace[-1].old_id >= node.old_id: # "A|B".
++ if num_join:
++ raise ValueError('Cannot join on jump: %d' % node.old_id)
++ jumps.append(trace[-1]) # Add A to |jumps|, for later join.
++ while trace and trace[-1].old_id > node.old_id: # Rewind to find B.
++ trace.pop()
++ if not trace or trace[-1].old_id != node.old_id: #
++ raise ValueError('Cannot jump to unvisited: %d' % node.old_id)
++ node.new_id = trace.pop().new_id # Copy B & remove. Will re-add B.
++ else: # "AB" or "A*...B".
++ node.new_id = trace[-1].new_id + trace[-1].weight # A --> B
++ if num_join: # "A*...B".
++ for _ in range(1, num_join):
++ t = jumps.pop()
++ node.new_id = max(node.new_id, t.new_id + t.weight) # X_i --> B.
++ else:
++ node.new_id = node.old_id # Initial S.
++ trace.append(node) # Add B.
++ align = meta['align'].val if meta and 'align' in meta else self._align
++ node.new_id = common.AlignUp(node.new_id, align)
++ yield node.item, node.new_id
++ # Expect caller to calling FreedWeight() and update |node.weight|.
++
++ def FeedWeight(self, item, weight):
++ self._node_dict[item.lo].weight = weight
++
++
++def GenerateNewIds(item_list, use_naive):
++ """Visits all tags in |item_list| and generates new ids.
++
++ New ids are generated based on old ids and usages.
++ """
++ Assigner = NaiveCoarseIdAssigner if use_naive else DagCoarseIdAssigner
++ coarse_id_assigner = Assigner(item_list, 10)
++ quota_assigner = QuotaAssigner(Aligner(expand=1.15, slack=3, align=10))
++ for item, start_id in coarse_id_assigner.GenStartIds(): # Topo-sorted.
++ cur_id = start_id
++ for tag, next_id in quota_assigner.Gen(item, start_id): # Sorted by |lo|.
++ yield tag, cur_id
++ cur_id = next_id
++ coarse_id_assigner.FeedWeight(item, next_id - start_id)
+diff --git a/tools/grit/grit/tool/update_resource_ids/assigner_unittest.py b/tools/grit/grit/tool/update_resource_ids/assigner_unittest.py
+new file mode 100644
+index 0000000000..164d820762
+--- /dev/null
++++ b/tools/grit/grit/tool/update_resource_ids/assigner_unittest.py
+@@ -0,0 +1,154 @@
++#!/usr/bin/env python
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++from __future__ import print_function
++
++import os
++import sys
++import traceback
++import unittest
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../../..'))
++
++from grit.tool.update_resource_ids import assigner, common, parser
++
++# |spec| format: A comma-separated list of (old) start IDs. Modifiers:
++# * Prefix with n '*' to assign the item's META "join" field to n + 1.
++# * Suffix with "+[usage]" to assign |usage| for the item (else default=10)
++
++
++def _RenderTestResourceId(spec):
++ """Renders barebone resource_ids data based on |spec|."""
++ data = '{"SRCDIR": ".",'
++ for i, tok in enumerate(spec.split(',')):
++ num_star = len(tok) - len(tok.lstrip('*'))
++ tok = tok[num_star:]
++ meta = '"META":{"join": %d},' % (num_star + 1) if num_star else ''
++ start_id = tok.split('+')[0] # Strip '+usage'.
++ data += '"foo%d.grd": {%s"includes": [%s]},' % (i, meta, start_id)
++ data += '}'
++ return data
++
++
++def _CreateTestItemList(spec):
++ """Creates list of ItemInfo based on |spec|."""
++ data = _RenderTestResourceId(spec)
++ item_list = common.BuildItemList(
++ parser.ResourceIdParser(data, parser.Tokenize(data)).Parse())
++ # Assign usages from "id+usage", default to 10.
++ for i, tok in enumerate(spec.split(',')):
++ item_list[i].tags[0].usage = int((tok.split('+') + ['10'])[1])
++ return item_list
++
++
++def _RunCoarseIdAssigner(spec):
++ item_list = _CreateTestItemList(spec)
++ coarse_id_assigner = assigner.DagCoarseIdAssigner(item_list, 1)
++ new_id_list = [] # List of new IDs, to check ID assignment.
++ new_spec_list = [] # List of new tokens to construct new |spec|.
++ for item, start_id in coarse_id_assigner.GenStartIds(): # Topo-sorted..
++ new_id_list.append(str(start_id))
++ meta = item.meta
++ num_join = meta['join'].val if meta and 'join' in meta else 0
++ t = '*' * max(0, num_join - 1)
++ t += str(start_id)
++ t += '' if item.tags[0].usage == 10 else '+' + str(item.tags[0].usage)
++ new_spec_list.append((item.lo, t))
++ coarse_id_assigner.FeedWeight(item, item.tags[0].usage)
++ new_spec = ','.join(s for _, s in sorted(new_spec_list))
++ return ','.join(new_id_list), new_spec
++
++
++class AssignerUnittest(unittest.TestCase):
++
++ def testDagAssigner(self):
++ test_cases = [
++ # Trivial.
++ ('0', '0'),
++ ('137', '137'),
++ ('5,15', '5,6'),
++ ('11,18', '11+7,12'),
++ ('5,5', '5,5'),
++ # Series only.
++ ('0,10,20,30,40', '0,1,2,3,4'),
++ ('5,15,25,35,45,55', '5,6,7,8,9,10'),
++ ('5,15,25,35,45,55', '5,7,100,101,256,1001'),
++ ('0,10,20,45,85', '0,1,2+25,3+40,4'),
++ # Branching with and without join.
++ ('0,0,10,20,20,30,40', '0,0,1,2,2,3,4'),
++ ('0,0,10,20,20,30,40', '0,0,*1,2,2,*3,4'),
++ ('0,0,2,12,12,16,26', '0+4,0+2,1,2+8,2+4,3,4'),
++ ('0,0,4,14,14,22,32', '0+4,0+2,*1,2+8,2+4,*3,4'),
++ # Wide branching with and without join.
++ ('0,10,10,10,10,10,10,20,30', '0,1,1,1,1,1,1,2,3'),
++ ('0,10,10,10,10,10,10,20,30', '0,1,1,1,1,1,1,*****2,3'),
++ ('0,2,2,2,2,2,2,7,17', '0+2,1+4,1+19,1,1+4,1+2,1+5,2,3'),
++ ('0,2,2,2,2,2,2,21,31', '0+2,1+4,1+19,1,1+4,1+2,1+5,*****2,3'),
++ # Expanding different branch, without join.
++ ('0,10,10,10,60,70,80', '0,1+15,1+15,1+50,2,3,4'),
++ ('0,10,10,10,25,35,45', '0,1+15,1+50,1+15,2,3,4'),
++ ('0,10,10,10,25,35,45', '0,1+50,1+15,1+15,2,3,4'),
++ # ... with join.
++ ('0,10,10,10,60,70,80', '0,1+15,1+15,1+50,**2,3,4'),
++ ('0,10,10,10,60,70,80', '0,1+15,1+50,1+15,**2,3,4'),
++ ('0,10,10,10,60,70,80', '0,1+50,1+15,1+15,**2,3,4'),
++ # ... with alternative join.
++ ('0,10,10,10,60,70,80', '0,1+15,1+15,1+50,2,**3,4'),
++ ('0,10,10,10,25,60,70', '0,1+15,1+50,1+15,2,**3,4'),
++ ('0,10,10,10,25,60,70', '0,1+50,1+15,1+15,2,**3,4'),
++ # Examples from assigner.py.
++ ('0,10,10,20,0,10,20,30,0,10',
++ '0,1,1,*2,0,4,5,*6,0,7'), # SA|AB|SDEC|SF
++ ('0,10,0,10,20,30', '0,1,0,2,*3,4'), # SA|SB*CD
++ ('0,10,0,10,20,30', '0,1,0,2,3,*4'), # SA|SBC*D
++ ('0,7,0,5,11,21', '0+7,1+4,0+5,2+3,*3,4'), # SA|SB*CD
++ ('0,7,0,5,8,18', '0+7,1+4,0+5,2+3,3,*4'), # SA|SBC*D
++ ('0,0,0,0,10,20', '0,0,0,0,*1,**2'), # S|S|S|S*A**B
++ ('0,0,0,0,10,20', '0,0,0,0,**1,*2'), # S|S|S|S**A*B
++ ('0,0,0,0,6,16', '0+8,0+7,0+6,0+5,*1,**2'), # S|S|S|S*A**B
++ ('0,0,0,0,7,17', '0+8,0+7,0+6,0+5,**1,*2'), # S|S|S|S**A*B
++ # Long branches without join.
++ ('0,10,0,0,10,20,0,10,20,30', '0,1,0,0,1,2,0,1,2,3'),
++ ('0,30,0,0,20,30,0,10,13,28', '0+30,1,0+50,0+20,1,2+17,0,1+3,2+15,3'),
++ # Long branches with join.
++ ('0,10,0,0,10,20,0,10,20,30', '0,1,0,0,1,2,0,1,2,***3'),
++ ('0,30,0,0,20,30,0,10,13,50',
++ '0+30,1,0+50,0+20,1,2+17,0,1+3,2+15,***3'),
++ # 2-level hierarchy.
++ ('0,10,10,20,0,10,10,20,30', '0,1,1,*2,0,1,1,*2,*3'),
++ ('0,2,2,10,0,3,3,6,34', '0+2,1+5,1+8,*2+24,0+3,1+2,1+3,*2+27,*3'),
++ ('0,2,2,10,0,3,3,6,34', '0+2,1+5,1+8,*2+24,0+3,1+2,1+3,*2+28,*3'),
++ ('0,2,2,10,0,3,3,6,35', '0+2,1+5,1+8,*2+24,0+3,1+2,1+3,*2+29,*3'),
++ # Binary hierarchy.
++ ('0,0,10,0,0,10,20,0,0,10,0,0,10,20,30',
++ '0,0,*1,0,0,*1,*2,0,0,*1,0,0,*1,*2,*3'),
++ ('0,0,2,0,0,5,11,0,0,8,0,0,5,14,18',
++ '0+1,0+2,*1+3,0+4,0+5,*1+6,*2+7,0+8,0+7,*1+6,0+5,0+4,*1+3,*2+2,*3+1'),
++ # Joining from different heads.
++ ('0,10,20,30,40,30,20,10,0,50', '0,1,2,3,4,3,2,1,0,****5'),
++ # Miscellaneous.
++ ('0,1,0,11', '0+1,1,0,*1'),
++ ]
++ for exp, spec in test_cases:
++ try:
++ actual, new_spec = _RunCoarseIdAssigner(spec)
++ self.failUnlessEqual(exp, actual)
++ # Test that assignment is idempotent.
++ actual2, new_spec2 = _RunCoarseIdAssigner(new_spec)
++ self.failUnlessEqual(actual, actual2)
++ self.failUnlessEqual(new_spec, new_spec2)
++ except Exception as e:
++ print(common.Color.RED(traceback.format_exc().rstrip()))
++ print('Failed spec: %s' % common.Color.CYAN(spec))
++ print(' Expected: %s' % common.Color.YELLOW(exp))
++ print(' Actual: %s' % common.Color.YELLOW(actual))
++ if new_spec != new_spec2:
++ print('Not idempotent')
++ if isinstance(e, AssertionError):
++ raise e
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/tool/update_resource_ids/common.py b/tools/grit/grit/tool/update_resource_ids/common.py
+new file mode 100644
+index 0000000000..004d8aa0e3
+--- /dev/null
++++ b/tools/grit/grit/tool/update_resource_ids/common.py
+@@ -0,0 +1,101 @@
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++
++def AlignUp(v, align):
++ return (v + align - 1) // align * align
++
++
++def StripPlural(s):
++ assert s.endswith('s'), 'Expect %s to be plural' % s
++ return s[:-1]
++
++
++class Color:
++
++ def _MakeColor(code):
++ t = '\033[' + code + 'm%s\033[0m'
++ return lambda s: t % s
++
++ NONE = staticmethod(lambda s: s)
++ RED = staticmethod(_MakeColor('31'))
++ GREEN = staticmethod(_MakeColor('32'))
++ YELLOW = staticmethod(_MakeColor('33'))
++ BLUE = staticmethod(_MakeColor('34'))
++ MAGENTA = staticmethod(_MakeColor('35'))
++ CYAN = staticmethod(_MakeColor('36'))
++ WHITE = staticmethod(_MakeColor('37'))
++ GRAY = staticmethod(_MakeColor('30;1'))
++
++
++class TagInfo:
++ """Stores resource_ids tag entry (e.g., {"includes": 100} pair)."""
++
++ def __init__(self, raw_key, raw_value):
++ """TagInfo Constructor.
++
++ Args:
++ raw_key: parser.AnnotatedValue for the parsed key, e.g., "includes".
++ raw_value: parser.AnnotatedValue for the parsed value, e.g., 100.
++ """
++ # Tag name, e.g., 'include' (no "s" at end).
++ self.name = StripPlural(raw_key.val)
++ # |len(raw_value) > 1| is possible, e.g., see grd_reader_unittest.py's
++ # testAssignFirstIdsMultipleMessages. This feature seems unused though.
++ # TODO(huangs): Reconcile this (may end up removing multi-value feature).
++ assert len(raw_value) == 1
++ # Inclusive start *position* of the tag's start ID in resource_ids.
++ self.lo = raw_value[0].lo
++ # Exclusive end *position* of the tag's start ID in resource_ids.
++ self.hi = raw_value[0].hi
++ # The tag's start ID. Initially the old value, but may be reassigned to new.
++ self.id = raw_value[0].val
++ # The number of IDs the tag uses, to be assigned by ItemInfo.SetUsages().
++ self.usage = None
++
++
++class ItemInfo:
++ """resource_ids item, containing multiple TagInfo."""
++
++ def __init__(self, lo, grd, raw_item):
++ # Inclusive start position of the item's key. Serve as unique identifier.
++ self.lo = lo
++ # The GRD filename for the item.
++ self.grd = grd
++ # Optional META information for the item.
++ self.meta = None
++ # List of TagInfo associated witih the item.
++ self.tags = []
++ for k, v in raw_item.items():
++ if k.val == 'META':
++ assert self.meta is None
++ self.meta = v # Not flattened.
++ else:
++ self.tags.append(TagInfo(k, v))
++ self.tags.sort(key=lambda tag: tag.lo)
++
++ def SetUsages(self, tag_name_to_usage):
++ for tag in self.tags:
++ tag.usage = tag_name_to_usage.get(tag.name, 0)
++
++
++def BuildItemList(root_obj):
++ """Extracts ID assignments and structure from parsed resource_ids.
++
++ Returns: A list of ItemInfo, ordered by |lo|.
++ """
++ item_list = []
++ grd_seen = set()
++ for raw_key, raw_item in root_obj.items(): # Unordered.
++ grd = raw_key.val
++ if grd == 'SRCDIR':
++ continue
++ if not grd.endswith('.grd'):
++ raise ValueError('Invalid GRD file: %s' % grd)
++ if grd in grd_seen:
++ raise ValueError('Duplicate GRD: %s' % grd)
++ grd_seen.add(grd)
++ item_list.append(ItemInfo(raw_key.lo, grd, raw_item))
++ item_list.sort(key=lambda item: item.lo)
++ return item_list
+diff --git a/tools/grit/grit/tool/update_resource_ids/parser.py b/tools/grit/grit/tool/update_resource_ids/parser.py
+new file mode 100644
+index 0000000000..da956bbd1c
+--- /dev/null
++++ b/tools/grit/grit/tool/update_resource_ids/parser.py
+@@ -0,0 +1,231 @@
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++"""Structure-preserving parser for resource_ids files.
++
++Naive usage of eval() destroys resource_ids structure. This module provides a
++custom parser that annotates source byte ranges of "leaf values" (strings and
++integers).
++"""
++
++from __future__ import print_function
++
++_isWhitespace = lambda ch: ch in ' \t\n'
++_isNotNewline = lambda ch: ch != '\n'
++_isDigit = lambda ch: ch.isdigit()
++
++
++def _RenderLineCol(data, pos):
++ """Renders |pos| within text |data| in as text showing line and column."""
++ # This is used to pinpoint fatal parse errors, so okay to be inefficient.
++ new_lines = [i for i in range(pos) if data[i] == '\n']
++ row = 1 + len(new_lines)
++ col = (pos - new_lines[-1]) if new_lines else 1 + pos
++ return 'line %d, column %d' % (row, col)
++
++
++def Tokenize(data):
++ """Generator to split |data| into tokens.
++
++ Each token is specified as |(t, lo, hi)|:
++ * |t|: Type, with '#' = space / comments, '0' = int, 'S' = string, 'E' = end,
++ and other characters denoting themselves.
++ * |lo, hi|: Token's range within |data| (as |data[lo:hi]|).
++ """
++
++ class ctx: # Local context for mutable data shared across inner functions.
++ pos = 0
++
++ def _HasData():
++ return ctx.pos < len(data)
++
++ # Returns True if ended by |not pred()|, or False if ended by EOF.
++ def _EatWhile(pred):
++ while _HasData():
++ if pred(data[ctx.pos]):
++ ctx.pos += 1
++ else:
++ return True
++ return False
++
++ def _NextBlank():
++ lo = ctx.pos
++ while True:
++ if not _EatWhile(_isWhitespace) or data[ctx.pos] != '#':
++ break
++ ctx.pos += 1
++ if not _EatWhile(_isNotNewline):
++ break
++ ctx.pos += 1
++ return None if ctx.pos == lo else (lo, ctx.pos)
++
++ def _EatString():
++ lo = ctx.pos
++ delim = data[ctx.pos]
++ is_escaped = False
++ ctx.pos += 1
++ while _HasData():
++ ch = data[ctx.pos]
++ ctx.pos += 1
++ if is_escaped:
++ is_escaped = False
++ elif ch == '\\':
++ is_escaped = True
++ elif ch == delim:
++ return
++ raise ValueError('Unterminated string at %s' % _RenderLineCol(data, lo))
++
++ while _HasData():
++ blank = _NextBlank()
++ if blank is not None:
++ yield ('#', blank[0], blank[1])
++ if not _HasData():
++ break
++ lo = ctx.pos
++ ch = data[ctx.pos]
++ if ch in '{}[],:':
++ ctx.pos += 1
++ t = ch
++ elif ch.isdigit():
++ _EatWhile(_isDigit)
++ t = '0'
++ elif ch in '+-':
++ ctx.pos += 1
++ if not _HasData() or not data[ctx.pos].isdigit():
++ raise ValueError('Invalid int at %s' % _RenderLineCol(data, lo))
++ _EatWhile(_isDigit)
++ t = '0'
++ elif ch in '"\'':
++ _EatString()
++ t = 'S'
++ else:
++ raise ValueError('Unknown char %s at %s' %
++ (repr(ch), _RenderLineCol(data, lo)))
++ yield (t, lo, ctx.pos)
++ yield ('E', ctx.pos, ctx.pos) # End sentinel.
++
++
++def _SkipBlanks(toks):
++ """Generator to remove whitespace and comments from Tokenize()."""
++ for t, lo, hi in toks:
++ if t != '#':
++ yield t, lo, hi
++
++
++class AnnotatedValue:
++ """Container for leaf values (ints or strings) with an annotated range."""
++
++ def __init__(self, val, lo, hi):
++ self.val = val
++ self.lo = lo
++ self.hi = hi
++
++ def __str__(self):
++ return '<%s@%d:%d>' % (str(self.val), self.lo, self.hi)
++
++ def __repr__(self):
++ return '<%r@%d:%d>' % (self.val, self.lo, self.hi)
++
++ def __hash__(self):
++ return hash(self.val)
++
++ def __eq__(self, other):
++ return self.val == other
++
++
++class ResourceIdParser:
++ """resource_ids parser that stores leaf values as AnnotatedValue.
++
++ Algorithm: Use Tokenize() to split |data| into tokens and _SkipBlanks() to
++ ignore comments and spacing, then apply a recursive parsing, using a one-token
++ look-ahead for decision making.
++ """
++
++ def __init__(self, data, tok_gen):
++ self.data = data
++ self.state = []
++ self.toks = _SkipBlanks(tok_gen)
++ self.tok_look_ahead = None
++
++ def _MakeErr(self, msg, pos):
++ return ValueError(msg + ' at ' + _RenderLineCol(self.data, pos))
++
++ def _PeekTok(self):
++ if self.tok_look_ahead is None:
++ self.tok_look_ahead = next(self.toks)
++ return self.tok_look_ahead
++
++ def _NextTok(self):
++ if self.tok_look_ahead is None:
++ return next(self.toks)
++ ret = self.tok_look_ahead
++ self.tok_look_ahead = None
++ return ret
++
++ def _EatTok(self, exp_t, tok_name=None):
++ t, lo, _ = self._NextTok()
++ if t != exp_t:
++ raise self._MakeErr('Bad token: Expect \'%s\'' % (tok_name or exp_t), lo)
++
++ def _NextIntOrString(self):
++ t, lo, hi = self._NextTok()
++ if t != '0' and t != 'S':
++ raise self._MakeErr('Expected number or string', lo)
++ value = eval(self.data[lo:hi])
++ return AnnotatedValue(value, lo, hi)
++
++ # Consumes separator ',' and returns whether |end_ch| is encountered.
++ def _EatSep(self, end_ch):
++ t, lo, _ = self._PeekTok()
++ if t == ',':
++ self._EatTok(',')
++ # Allow trailing ','.
++ t, _, _ = self._PeekTok()
++ return t == end_ch
++ elif t == end_ch:
++ return True
++ else:
++ raise self._MakeErr('Expect \',\' or \'%s\'' % end_ch, lo)
++
++ def _NextList(self):
++ self._EatTok('[')
++ ret = []
++ t, _, _ = self._PeekTok()
++ if t != ']':
++ while True:
++ ret.append(self._NextObject())
++ if self._EatSep(']'):
++ break
++ self._EatTok(']')
++ return ret
++
++ def _NextDict(self):
++ self._EatTok('{')
++ ret = {}
++ t, _, _ = self._PeekTok()
++ if t != '}':
++ while True:
++ k = self._NextIntOrString()
++ self._EatTok(':')
++ v = self._NextObject()
++ ret[k] = v
++ if self._EatSep('}'):
++ break
++ self._EatTok('}')
++ return ret
++
++ def _NextObject(self):
++ t, lo, _ = self._PeekTok()
++ if t == '[':
++ return self._NextList()
++ elif t == '{':
++ return self._NextDict()
++ elif t == '0' or t == 'S':
++ return self._NextIntOrString()
++ else:
++ raise self._MakeErr('Bad token: Type = %s' % t, lo)
++
++ def Parse(self):
++ root_obj = self._NextObject()
++ self._EatTok('E', 'EOF')
++ return root_obj
+diff --git a/tools/grit/grit/tool/update_resource_ids/reader.py b/tools/grit/grit/tool/update_resource_ids/reader.py
+new file mode 100644
+index 0000000000..0a156d2deb
+--- /dev/null
++++ b/tools/grit/grit/tool/update_resource_ids/reader.py
+@@ -0,0 +1,83 @@
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++"""Helpers to read GRD files and estimate resource ID usages.
++
++This module uses grit.grd_reader to estimate resource ID usages in GRD
++(and GRDP) files by counting the occurrences of {include, message, structure}
++tags. This approach avoids the complexties of conditional inclusions, but
++produces a conservative estimate of ID usages.
++"""
++
++from __future__ import print_function
++
++import collections
++import os
++
++from grit import grd_reader
++from grit import util
++from grit.tool.update_resource_ids import common
++
++TAGS_OF_INTEREST = set(['include', 'message', 'structure'])
++
++def _CountResourceUsage(grd, seen_files):
++ tag_name_to_count = {tag: set() for tag in TAGS_OF_INTEREST}
++ # Pass '_chromium', but '_google_chrome' would produce the same result.
++ root = grd_reader.Parse(grd, defines={'_chromium': True})
++ seen_files.add(grd)
++ # Count all descendant tags, regardless of whether they're active.
++ for node in root.Preorder():
++ if node.name in TAGS_OF_INTEREST:
++ tag_name_to_count[node.name].add(node.attrs['name'])
++ elif node.name == 'part':
++ part_path = os.path.join(os.path.dirname(grd), node.GetInputPath())
++ seen_files.add(util.normpath(part_path))
++ return {k: len(v) for k, v in tag_name_to_count.items() if v}
++
++
++def GenerateResourceUsages(item_list, src_dir, fake, seen_files):
++ """Visits a list of ItemInfo to generate maps from tag name to usage.
++
++ Args:
++ root_obj: Root dict of a resource_ids file.
++ src_dir: Absolute directory of Chrome's src/ directory.
++ fake: For testing: Sets 10 as usages for all tags, to avoid reading GRD.
++ seen_files: A set to collect paths of files read.
++ Yields:
++ Tuple (item, tag_name_to_usage), where |item| is from |item_list| and
++ |tag_name_to_usage| is a dict() mapping tag name to (int) usage.
++ """
++ if fake:
++ for item in item_list:
++ tag_name_to_usage = collections.Counter({t.name: 10 for t in item.tags})
++ yield item, tag_name_to_usage
++ return
++ for item in item_list:
++ supported_tag_names = set(tag.name for tag in item.tags)
++ if item.meta and 'sizes' in item.meta:
++ # If META has "sizes" field, use it instead of reading GRD.
++ tag_name_to_usage = collections.Counter()
++ for k, vlist in item.meta['sizes'].items():
++ tag_name_to_usage[common.StripPlural(k.val)] = sum(v.val for v in vlist)
++ tag_names = set(tag_name_to_usage.keys())
++ if tag_names != supported_tag_names:
++ raise ValueError('META "sizes" field have identical fields as actual '
++ '"sizes" field.')
++ else:
++ # Generated GRD start with '<(SHARED_INTERMEDIATE_DIR)'. Just check '<'.
++ if item.grd.startswith('<'):
++ raise ValueError('%s: Generated GRD must use META with "sizes" field '
++ 'to specify size bounds.' % item.grd)
++ grd_file = os.path.join(src_dir, item.grd)
++ if not os.path.exists(grd_file):
++ # Silently skip missing files so that src-internal files do not break
++ # public checkouts.
++ yield item, {}
++ continue
++ tag_name_to_usage = _CountResourceUsage(grd_file, seen_files)
++ tag_names = set(tag_name_to_usage.keys())
++ if not tag_names.issubset(supported_tag_names):
++ missing = [t + 's' for t in tag_names - supported_tag_names]
++ raise ValueError(
++ 'Resource ids for %s needs entry for %s' % (item.grd, missing))
++ yield item, tag_name_to_usage
+diff --git a/tools/grit/grit/tool/xmb.py b/tools/grit/grit/tool/xmb.py
+new file mode 100644
+index 0000000000..b821308369
+--- /dev/null
++++ b/tools/grit/grit/tool/xmb.py
+@@ -0,0 +1,295 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""The 'grit xmb' tool.
++"""
++
++from __future__ import print_function
++
++import getopt
++import os
++import sys
++
++from xml.sax import saxutils
++
++import six
++
++from grit import grd_reader
++from grit import lazy_re
++from grit import tclib
++from grit import util
++from grit.tool import interface
++
++
++# Used to collapse presentable content to determine if
++# xml:space="preserve" is needed.
++_WHITESPACES_REGEX = lazy_re.compile(r'\s\s*')
++
++
++# See XmlEscape below.
++_XML_QUOTE_ESCAPES = {
++ u"'": u'&apos;',
++ u'"': u'&quot;',
++}
++
++def _XmlEscape(s):
++ """Returns text escaped for XML in a way compatible with Google's
++ internal Translation Console tool. May be used for attributes as
++ well as for contents.
++ """
++ return saxutils.escape(six.text_type(s), _XML_QUOTE_ESCAPES).encode('utf-8')
++
++
++def _WriteAttribute(file, name, value):
++ """Writes an XML attribute to the specified file.
++
++ Args:
++ file: file to write to
++ name: name of the attribute
++ value: (unescaped) value of the attribute
++ """
++ name = name.encode('utf-8')
++ if value:
++ file.write(b' %s="%s"' % (name, _XmlEscape(value)))
++
++
++def _WriteMessage(file, message):
++ presentable_content = message.GetPresentableContent()
++ assert (isinstance(presentable_content, six.string_types) or
++ (len(message.parts) == 1 and
++ type(message.parts[0] == tclib.Placeholder)))
++ preserve_space = presentable_content != _WHITESPACES_REGEX.sub(
++ u' ', presentable_content.strip())
++
++ file.write(b'<msg')
++ _WriteAttribute(file, 'desc', message.GetDescription())
++ _WriteAttribute(file, 'id', message.GetId())
++ _WriteAttribute(file, 'meaning', message.GetMeaning())
++ if preserve_space:
++ _WriteAttribute(file, 'xml:space', 'preserve')
++ file.write(b'>')
++ if not preserve_space:
++ file.write(b'\n ')
++
++ parts = message.GetContent()
++ for part in parts:
++ if isinstance(part, tclib.Placeholder):
++ file.write(b'<ph')
++ _WriteAttribute(file, 'name', part.GetPresentation())
++ file.write(b'><ex>')
++ file.write(_XmlEscape(part.GetExample()))
++ file.write(b'</ex>')
++ file.write(_XmlEscape(part.GetOriginal()))
++ file.write(b'</ph>')
++ else:
++ file.write(_XmlEscape(part))
++ if not preserve_space:
++ file.write(b'\n')
++ file.write(b'</msg>\n')
++
++
++def WriteXmbFile(file, messages):
++ """Writes the given grit.tclib.Message items to the specified open
++ file-like object in the XMB format.
++ """
++ file.write(b"""<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE messagebundle [
++<!ELEMENT messagebundle (msg)*>
++<!ATTLIST messagebundle class CDATA #IMPLIED>
++
++<!ELEMENT msg (#PCDATA|ph|source)*>
++<!ATTLIST msg id CDATA #IMPLIED>
++<!ATTLIST msg seq CDATA #IMPLIED>
++<!ATTLIST msg name CDATA #IMPLIED>
++<!ATTLIST msg desc CDATA #IMPLIED>
++<!ATTLIST msg meaning CDATA #IMPLIED>
++<!ATTLIST msg obsolete (obsolete) #IMPLIED>
++<!ATTLIST msg xml:space (default|preserve) "default">
++<!ATTLIST msg is_hidden CDATA #IMPLIED>
++
++<!ELEMENT source (#PCDATA)>
++
++<!ELEMENT ph (#PCDATA|ex)*>
++<!ATTLIST ph name CDATA #REQUIRED>
++
++<!ELEMENT ex (#PCDATA)>
++]>
++<messagebundle>
++""")
++ for message in messages:
++ _WriteMessage(file, message)
++ file.write(b'</messagebundle>')
++
++
++class OutputXmb(interface.Tool):
++ """Outputs all translateable messages in the .grd input file to an
++.xmb file, which is the format used to give source messages to
++Google's internal Translation Console tool. The format could easily
++be used for other systems.
++
++Usage: grit xmb [-i|-h] [-l LIMITFILE] OUTPUTPATH
++
++OUTPUTPATH is the path you want to output the .xmb file to.
++
++The -l option can be used to output only some of the resources to the .xmb file.
++LIMITFILE is the path to a file that is used to limit the items output to the
++xmb file. If the filename extension is .grd, the file must be a .grd file
++and the tool only output the contents of nodes from the input file that also
++exist in the limit file (as compared on the 'name' attribute). Otherwise it must
++contain a list of the IDs that output should be limited to, one ID per line, and
++the tool will only output nodes with 'name' attributes that match one of the
++IDs.
++
++The -i option causes 'grit xmb' to output an "IDs only" file instead of an XMB
++file. The "IDs only" file contains the message ID of each message that would
++normally be output to the XMB file, one message ID per line. It is designed for
++use with the 'grit transl2tc' tool's -l option.
++
++Other options:
++
++ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
++ value VAL (defaults to 1) which will be used to control
++ conditional inclusion of resources.
++
++ -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
++
++"""
++ # The different output formats supported by this tool
++ FORMAT_XMB = 0
++ FORMAT_IDS_ONLY = 1
++
++ def __init__(self, defines=None):
++ super(OutputXmb, self).__init__()
++ self.format = self.FORMAT_XMB
++ self.defines = defines or {}
++
++ def ShortDescription(self):
++ return 'Exports all translateable messages into an XMB file.'
++
++ def Run(self, opts, args):
++ os.environ['cwd'] = os.getcwd()
++
++ self.SetOptions(opts)
++
++ limit_file = None
++ limit_is_grd = False
++ limit_file_dir = None
++ own_opts, args = getopt.getopt(args, 'l:D:ih', ('help',))
++ for key, val in own_opts:
++ if key == '-l':
++ limit_file = open(val, 'r')
++ limit_file_dir = util.dirname(val)
++ if not len(limit_file_dir):
++ limit_file_dir = '.'
++ limit_is_grd = os.path.splitext(val)[1] == '.grd'
++ elif key == '-i':
++ self.format = self.FORMAT_IDS_ONLY
++ elif key == '-D':
++ name, val = util.ParseDefine(val)
++ self.defines[name] = val
++ elif key == '-E':
++ (env_name, env_value) = val.split('=', 1)
++ os.environ[env_name] = env_value
++ elif key == '--help':
++ self.ShowUsage()
++ sys.exit(0)
++ if not len(args) == 1:
++ print('grit xmb takes exactly one argument, the path to the XMB file '
++ 'to output.')
++ return 2
++
++ xmb_path = args[0]
++ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose, defines=self.defines)
++ res_tree.SetOutputLanguage('en')
++ res_tree.SetDefines(self.defines)
++ res_tree.OnlyTheseTranslations([])
++ res_tree.RunGatherers()
++
++ with open(xmb_path, 'wb') as output_file:
++ self.Process(
++ res_tree, output_file, limit_file, limit_is_grd, limit_file_dir)
++ if limit_file:
++ limit_file.close()
++ print("Wrote %s" % xmb_path)
++
++ def Process(self, res_tree, output_file, limit_file=None, limit_is_grd=False,
++ dir=None):
++ """Writes a document with the contents of res_tree into output_file,
++ limiting output to the IDs specified in limit_file, which is a GRD file if
++ limit_is_grd is true, otherwise a file with one ID per line.
++
++ The format of the output document depends on this object's format attribute.
++ It can be FORMAT_XMB or FORMAT_IDS_ONLY.
++
++ The FORMAT_IDS_ONLY format causes this function to write just a list
++ of the IDs of all messages that would have been added to the XMB file, one
++ ID per line.
++
++ The FORMAT_XMB format causes this function to output the (default) XMB
++ format.
++
++ Args:
++ res_tree: base.Node()
++ output_file: file open for writing
++ limit_file: None or file open for reading
++ limit_is_grd: True | False
++ dir: Directory of the limit file
++ """
++ if limit_file:
++ if limit_is_grd:
++ limit_list = []
++ limit_tree = grd_reader.Parse(limit_file,
++ dir=dir,
++ debug=self.o.extra_verbose)
++ for node in limit_tree:
++ if 'name' in node.attrs:
++ limit_list.append(node.attrs['name'])
++ else:
++ # Not a GRD file, so it's just a file with one ID per line
++ limit_list = [item.strip() for item in limit_file.read().split('\n')]
++
++ ids_already_done = {}
++ messages = []
++ for node in res_tree:
++ if (limit_file and
++ not ('name' in node.attrs and node.attrs['name'] in limit_list)):
++ continue
++ if not node.IsTranslateable():
++ continue
++
++ for clique in node.GetCliques():
++ if not clique.IsTranslateable():
++ continue
++ if not clique.GetMessage().GetRealContent():
++ continue
++
++ # Some explanation is in order here. Note that we can have
++ # many messages with the same ID.
++ #
++ # The way we work around this is to maintain a list of cliques
++ # per message ID (in the UberClique) and select the "best" one
++ # (the first one that has a description, or an arbitrary one
++ # if there is no description) for inclusion in the XMB file.
++ # The translations are all going to be the same for messages
++ # with the same ID, although the way we replace placeholders
++ # might be slightly different.
++ id = clique.GetMessage().GetId()
++ if id in ids_already_done:
++ continue
++ ids_already_done[id] = 1
++
++ message = node.UberClique().BestClique(id).GetMessage()
++ messages += [message]
++
++ # Ensure a stable order of messages, to help regression testing.
++ messages.sort(key=lambda x:x.GetId())
++
++ if self.format == self.FORMAT_IDS_ONLY:
++ # We just print the list of IDs to the output file.
++ for msg in messages:
++ output_file.write(msg.GetId())
++ output_file.write('\n')
++ else:
++ assert self.format == self.FORMAT_XMB
++ WriteXmbFile(output_file, messages)
+diff --git a/tools/grit/grit/tool/xmb_unittest.py b/tools/grit/grit/tool/xmb_unittest.py
+new file mode 100644
+index 0000000000..3c7e92cee7
+--- /dev/null
++++ b/tools/grit/grit/tool/xmb_unittest.py
+@@ -0,0 +1,132 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for 'grit xmb' tool.'''
++
++from __future__ import print_function
++
++import io
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
++
++import unittest
++import xml.sax
++
++from six import StringIO
++
++from grit import grd_reader
++from grit import util
++from grit.tool import xmb
++
++
++class XmbUnittest(unittest.TestCase):
++ def setUp(self):
++ self.res_tree = grd_reader.Parse(
++ io.BytesIO(u'''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <includes>
++ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
++ </includes>
++ <messages>
++ <message name="GOOD" desc="sub" sub_variable="true">
++ excellent
++ </message>
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, are you doing [GOOD] today?
++ </message>
++ <message name="IDS_BONGOBINGO">
++ Yibbee
++ </message>
++ <message name="IDS_UNICODE">
++ Ol\xe1, \u4eca\u65e5\u306f! \U0001F60A
++ </message>
++ </messages>
++ <structures>
++ <structure type="dialog" name="IDD_SPACYBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
++ </structures>
++ </release>
++ </grit>'''.encode('utf-8')), '.')
++ self.xmb_file = io.BytesIO()
++
++ def testNormalOutput(self):
++ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
++ output = self.xmb_file.getvalue().decode('utf-8')
++ self.failUnless(output.count('Joi'))
++ self.failUnless(output.count('Yibbee'))
++ self.failUnless(output.count(u'Ol\xe1, \u4eca\u65e5\u306f! \U0001F60A'))
++
++ def testLimitList(self):
++ limit_file = StringIO(
++ 'IDS_BONGOBINGO\nIDS_DOES_NOT_EXIST\nIDS_ALSO_DOES_NOT_EXIST')
++ xmb.OutputXmb().Process(self.res_tree, self.xmb_file, limit_file, False)
++ output = self.xmb_file.getvalue().decode('utf-8')
++ self.failUnless(output.count('Yibbee'))
++ self.failUnless(not output.count('Joi'))
++
++ def testLimitGrd(self):
++ limit_file = StringIO('''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
++ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
++ </message>
++ </messages>
++ </release>
++ </grit>''')
++ tool = xmb.OutputXmb()
++ class DummyOpts(object):
++ extra_verbose = False
++ tool.o = DummyOpts()
++ tool.Process(self.res_tree, self.xmb_file, limit_file, True, dir='.')
++ output = self.xmb_file.getvalue().decode('utf-8')
++ self.failUnless(output.count('Joi'))
++ self.failUnless(not output.count('Yibbee'))
++
++ def testSubstitution(self):
++ self.res_tree.SetOutputLanguage('en')
++ os.chdir(util.PathFromRoot('.')) # so it can find klonk.rc
++ self.res_tree.RunGatherers()
++ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
++ output = self.xmb_file.getvalue().decode('utf-8')
++ self.failUnless(output.count(
++ '<ph name="GOOD_1"><ex>excellent</ex>[GOOD]</ph>'))
++
++ def testLeadingTrailingWhitespace(self):
++ # Regression test for problems outputting messages with leading or
++ # trailing whitespace (these come in via structures only, as
++ # message nodes already strip and store whitespace).
++ self.res_tree.SetOutputLanguage('en')
++ os.chdir(util.PathFromRoot('.')) # so it can find klonk.rc
++ self.res_tree.RunGatherers()
++ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
++ output = self.xmb_file.getvalue().decode('utf-8')
++ self.failUnless(output.count('OK ? </msg>'))
++
++ def testDisallowedChars(self):
++ # Validate that the invalid unicode is not accepted. Since it's not valid,
++ # we can't specify it in a string literal, so write as a byte sequence.
++ bad_xml = io.BytesIO()
++ bad_xml.write(b'''<?xml version="1.0" encoding="UTF-8"?>
++ <grit latest_public_release="2" source_lang_id="en-US"
++ current_release="3" base_dir=".">
++ <release seq="3">
++ <messages>
++ <message name="ID_FOO">''')
++ # UTF-8 corresponding to to \U00110000
++ # http://apps.timwhitlock.info/unicode/inspect/hex/110000
++ bad_xml.write(b'\xF4\x90\x80\x80')
++ bad_xml.write(b'''</message>
++ </messages>
++ </release>
++ </grit>''')
++ bad_xml.seek(0)
++ self.assertRaises(xml.sax.SAXParseException, grd_reader.Parse, bad_xml, '.')
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/util.py b/tools/grit/grit/util.py
+new file mode 100644
+index 0000000000..98433d154c
+--- /dev/null
++++ b/tools/grit/grit/util.py
+@@ -0,0 +1,691 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Utilities used by GRIT.
++'''
++
++from __future__ import print_function
++
++import codecs
++import io
++import os
++import re
++import shutil
++import sys
++import tempfile
++from xml.sax import saxutils
++
++import six
++from six import StringIO
++from six.moves import html_entities as entities
++
++from grit import lazy_re
++
++_root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
++
++
++# Unique constants for use by ReadFile().
++BINARY = 0
++
++
++# Unique constants representing data pack encodings.
++_, UTF8, UTF16 = range(3)
++
++
++def Encode(message, encoding):
++ '''Returns a byte stream that represents |message| in the given |encoding|.'''
++ # |message| is a python unicode string, so convert to a byte stream that
++ # has the correct encoding requested for the datapacks. We skip the first
++ # 2 bytes of text resources because it is the BOM.
++ if encoding == UTF8:
++ return message.encode('utf8')
++ if encoding == UTF16:
++ return message.encode('utf16')[2:]
++ # Default is BINARY
++ return message
++
++
++# Matches all different types of linebreaks.
++LINEBREAKS = re.compile('\r\n|\n|\r')
++
++def MakeRelativePath(base_path, path_to_make_relative):
++ """Returns a relative path such from the base_path to
++ the path_to_make_relative.
++
++ In other words, os.join(base_path,
++ MakeRelativePath(base_path, path_to_make_relative))
++ is the same location as path_to_make_relative.
++
++ Args:
++ base_path: the root path
++ path_to_make_relative: an absolute path that is on the same drive
++ as base_path
++ """
++
++ def _GetPathAfterPrefix(prefix_path, path_with_prefix):
++ """Gets the subpath within in prefix_path for the path_with_prefix
++ with no beginning or trailing path separators.
++
++ Args:
++ prefix_path: the base path
++ path_with_prefix: a path that starts with prefix_path
++ """
++ assert path_with_prefix.startswith(prefix_path)
++ path_without_prefix = path_with_prefix[len(prefix_path):]
++ normalized_path = os.path.normpath(path_without_prefix.strip(os.path.sep))
++ if normalized_path == '.':
++ normalized_path = ''
++ return normalized_path
++
++ def _GetCommonBaseDirectory(*args):
++ """Returns the common prefix directory for the given paths
++
++ Args:
++ The list of paths (at least one of which should be a directory)
++ """
++ prefix = os.path.commonprefix(args)
++ # prefix is a character-by-character prefix (i.e. it does not end
++ # on a directory bound, so this code fixes that)
++
++ # if the prefix ends with the separator, then it is prefect.
++ if len(prefix) > 0 and prefix[-1] == os.path.sep:
++ return prefix
++
++ # We need to loop through all paths or else we can get
++ # tripped up by "c:\a" and "c:\abc". The common prefix
++ # is "c:\a" which is a directory and looks good with
++ # respect to the first directory but it is clear that
++ # isn't a common directory when the second path is
++ # examined.
++ for path in args:
++ assert len(path) >= len(prefix)
++ # If the prefix the same length as the path,
++ # then the prefix must be a directory (since one
++ # of the arguements should be a directory).
++ if path == prefix:
++ continue
++ # if the character after the prefix in the path
++ # is the separator, then the prefix appears to be a
++ # valid a directory as well for the given path
++ if path[len(prefix)] == os.path.sep:
++ continue
++ # Otherwise, the prefix is not a directory, so it needs
++ # to be shortened to be one
++ index_sep = prefix.rfind(os.path.sep)
++ # The use "index_sep + 1" because it includes the final sep
++ # and it handles the case when the index_sep is -1 as well
++ prefix = prefix[:index_sep + 1]
++ # At this point we backed up to a directory bound which is
++ # common to all paths, so we can quit going through all of
++ # the paths.
++ break
++ return prefix
++
++ prefix = _GetCommonBaseDirectory(base_path, path_to_make_relative)
++ # If the paths had no commonality at all, then return the absolute path
++ # because it is the best that can be done. If the path had to be relative
++ # then eventually this absolute path will be discovered (when a build breaks)
++ # and an appropriate fix can be made, but having this allows for the best
++ # backward compatibility with the absolute path behavior in the past.
++ if len(prefix) <= 0:
++ return path_to_make_relative
++ # Build a path from the base dir to the common prefix
++ remaining_base_path = _GetPathAfterPrefix(prefix, base_path)
++
++ # The follow handles two case: "" and "foo\\bar"
++ path_pieces = remaining_base_path.split(os.path.sep)
++ base_depth_from_prefix = len([d for d in path_pieces if len(d)])
++ base_to_prefix = (".." + os.path.sep) * base_depth_from_prefix
++
++ # Put add in the path from the prefix to the path_to_make_relative
++ remaining_other_path = _GetPathAfterPrefix(prefix, path_to_make_relative)
++ return base_to_prefix + remaining_other_path
++
++
++KNOWN_SYSTEM_IDENTIFIERS = set()
++
++SYSTEM_IDENTIFIERS = None
++
++def SetupSystemIdentifiers(ids):
++ '''Adds ids to a regexp of known system identifiers.
++
++ Can be called many times, ids will be accumulated.
++
++ Args:
++ ids: an iterable of strings
++ '''
++ KNOWN_SYSTEM_IDENTIFIERS.update(ids)
++ global SYSTEM_IDENTIFIERS
++ SYSTEM_IDENTIFIERS = lazy_re.compile(
++ ' | '.join([r'\b%s\b' % i for i in KNOWN_SYSTEM_IDENTIFIERS]),
++ re.VERBOSE)
++
++
++# Matches all of the resource IDs predefined by Windows.
++SetupSystemIdentifiers((
++ 'IDOK', 'IDCANCEL', 'IDC_STATIC', 'IDYES', 'IDNO',
++ 'ID_FILE_NEW', 'ID_FILE_OPEN', 'ID_FILE_CLOSE', 'ID_FILE_SAVE',
++ 'ID_FILE_SAVE_AS', 'ID_FILE_PAGE_SETUP', 'ID_FILE_PRINT_SETUP',
++ 'ID_FILE_PRINT', 'ID_FILE_PRINT_DIRECT', 'ID_FILE_PRINT_PREVIEW',
++ 'ID_FILE_UPDATE', 'ID_FILE_SAVE_COPY_AS', 'ID_FILE_SEND_MAIL',
++ 'ID_FILE_MRU_FIRST', 'ID_FILE_MRU_LAST',
++ 'ID_EDIT_CLEAR', 'ID_EDIT_CLEAR_ALL', 'ID_EDIT_COPY',
++ 'ID_EDIT_CUT', 'ID_EDIT_FIND', 'ID_EDIT_PASTE', 'ID_EDIT_PASTE_LINK',
++ 'ID_EDIT_PASTE_SPECIAL', 'ID_EDIT_REPEAT', 'ID_EDIT_REPLACE',
++ 'ID_EDIT_SELECT_ALL', 'ID_EDIT_UNDO', 'ID_EDIT_REDO',
++ 'VS_VERSION_INFO', 'IDRETRY',
++ 'ID_APP_ABOUT', 'ID_APP_EXIT',
++ 'ID_NEXT_PANE', 'ID_PREV_PANE',
++ 'ID_WINDOW_NEW', 'ID_WINDOW_ARRANGE', 'ID_WINDOW_CASCADE',
++ 'ID_WINDOW_TILE_HORZ', 'ID_WINDOW_TILE_VERT', 'ID_WINDOW_SPLIT',
++ 'ATL_IDS_SCSIZE', 'ATL_IDS_SCMOVE', 'ATL_IDS_SCMINIMIZE',
++ 'ATL_IDS_SCMAXIMIZE', 'ATL_IDS_SCNEXTWINDOW', 'ATL_IDS_SCPREVWINDOW',
++ 'ATL_IDS_SCCLOSE', 'ATL_IDS_SCRESTORE', 'ATL_IDS_SCTASKLIST',
++ 'ATL_IDS_MDICHILD', 'ATL_IDS_IDLEMESSAGE', 'ATL_IDS_MRU_FILE' ))
++
++
++# Matches character entities, whether specified by name, decimal or hex.
++_HTML_ENTITY = lazy_re.compile(
++ '&(#(?P<decimal>[0-9]+)|#x(?P<hex>[a-fA-F0-9]+)|(?P<named>[a-z0-9]+));',
++ re.IGNORECASE)
++
++# Matches characters that should be HTML-escaped. This is <, > and &, but only
++# if the & is not the start of an HTML character entity.
++_HTML_CHARS_TO_ESCAPE = lazy_re.compile(
++ '"|<|>|&(?!#[0-9]+|#x[0-9a-z]+|[a-z]+;)',
++ re.IGNORECASE | re.MULTILINE)
++
++
++def ReadFile(filename, encoding):
++ '''Reads and returns the entire contents of the given file.
++
++ Args:
++ filename: The path to the file.
++ encoding: A Python codec name or the special value: BINARY to read
++ the file in binary mode.
++ '''
++ if encoding == BINARY:
++ mode = 'rb'
++ encoding = None
++ else:
++ mode = 'rU'
++
++ with io.open(filename, mode, encoding=encoding) as f:
++ return f.read()
++
++
++def WrapOutputStream(stream, encoding = 'utf-8'):
++ '''Returns a stream that wraps the provided stream, making it write
++ characters using the specified encoding.'''
++ return codecs.getwriter(encoding)(stream)
++
++
++def ChangeStdoutEncoding(encoding = 'utf-8'):
++ '''Changes STDOUT to print characters using the specified encoding.'''
++ # If we're unittesting, don't reconfigure.
++ if isinstance(sys.stdout, StringIO):
++ return
++
++ if sys.version_info.major < 3:
++ # Python 2 has binary streams by default, so reconfigure directly.
++ sys.stdout = WrapOutputStream(sys.stdout, encoding)
++ sys.stderr = WrapOutputStream(sys.stderr, encoding)
++ elif sys.version_info < (3, 7):
++ # Python 3 has text streams by default, so we have to detach them first.
++ sys.stdout = WrapOutputStream(sys.stdout.detach(), encoding)
++ sys.stderr = WrapOutputStream(sys.stderr.detach(), encoding)
++ else:
++ # Python 3.7+ provides an API for this specifically.
++ sys.stdout.reconfigure(encoding=encoding)
++ sys.stderr.reconfigure(encoding=encoding)
++
++
++def EscapeHtml(text, escape_quotes = False):
++ '''Returns 'text' with <, > and & (and optionally ") escaped to named HTML
++ entities. Any existing named entity or HTML entity defined by decimal or
++ hex code will be left untouched. This is appropriate for escaping text for
++ inclusion in HTML, but not for XML.
++ '''
++ def Replace(match):
++ if match.group() == '&': return '&amp;'
++ elif match.group() == '<': return '&lt;'
++ elif match.group() == '>': return '&gt;'
++ elif match.group() == '"':
++ if escape_quotes: return '&quot;'
++ else: return match.group()
++ else: assert False
++ out = _HTML_CHARS_TO_ESCAPE.sub(Replace, text)
++ return out
++
++
++def UnescapeHtml(text, replace_nbsp=True):
++ '''Returns 'text' with all HTML character entities (both named character
++ entities and those specified by decimal or hexadecimal Unicode ordinal)
++ replaced by their Unicode characters (or latin1 characters if possible).
++
++ The only exception is that &nbsp; will not be escaped if 'replace_nbsp' is
++ False.
++ '''
++ def Replace(match):
++ groups = match.groupdict()
++ if groups['hex']:
++ return six.unichr(int(groups['hex'], 16))
++ elif groups['decimal']:
++ return six.unichr(int(groups['decimal'], 10))
++ else:
++ name = groups['named']
++ if name == 'nbsp' and not replace_nbsp:
++ return match.group() # Don't replace &nbsp;
++ assert name != None
++ if name in entities.name2codepoint:
++ return six.unichr(entities.name2codepoint[name])
++ else:
++ return match.group() # Unknown HTML character entity - don't replace
++
++ out = _HTML_ENTITY.sub(Replace, text)
++ return out
++
++
++def EncodeCdata(cdata):
++ '''Returns the provided cdata in either escaped format or <![CDATA[xxx]]>
++ format, depending on which is more appropriate for easy editing. The data
++ is escaped for inclusion in an XML element's body.
++
++ Args:
++ cdata: 'If x < y and y < z then x < z'
++
++ Return:
++ '<![CDATA[If x < y and y < z then x < z]]>'
++ '''
++ if cdata.count('<') > 1 or cdata.count('>') > 1 and cdata.count(']]>') == 0:
++ return '<![CDATA[%s]]>' % cdata
++ else:
++ return saxutils.escape(cdata)
++
++
++def FixupNamedParam(function, param_name, param_value):
++ '''Returns a closure that is identical to 'function' but ensures that the
++ named parameter 'param_name' is always set to 'param_value' unless explicitly
++ set by the caller.
++
++ Args:
++ function: callable
++ param_name: 'bingo'
++ param_value: 'bongo' (any type)
++
++ Return:
++ callable
++ '''
++ def FixupClosure(*args, **kw):
++ if not param_name in kw:
++ kw[param_name] = param_value
++ return function(*args, **kw)
++ return FixupClosure
++
++
++def PathFromRoot(path):
++ r'''Takes a path relative to the root directory for GRIT (the one that grit.py
++ resides in) and returns a path that is either absolute or relative to the
++ current working directory (i.e .a path you can use to open the file).
++
++ Args:
++ path: 'rel_dir\file.ext'
++
++ Return:
++ 'c:\src\tools\rel_dir\file.ext
++ '''
++ return os.path.normpath(os.path.join(_root_dir, path))
++
++
++def ParseGrdForUnittest(body, base_dir=None, predetermined_ids_file=None,
++ run_gatherers=False):
++ '''Parse a skeleton .grd file and return it, for use in unit tests.
++
++ Args:
++ body: XML that goes inside the <release> element.
++ base_dir: The base_dir attribute of the <grit> tag.
++ '''
++ from grit import grd_reader
++ if isinstance(body, six.text_type):
++ body = body.encode('utf-8')
++ if base_dir is None:
++ base_dir = PathFromRoot('.')
++ lines = [b'<?xml version="1.0" encoding="UTF-8"?>']
++ lines.append(b'<grit latest_public_release="2" current_release="3" '
++ b'source_lang_id="en" base_dir="%s">' % base_dir.encode('utf-8'))
++ if b'<outputs>' in body:
++ lines.append(body)
++ else:
++ lines.append(b' <outputs></outputs>')
++ lines.append(b' <release seq="3">')
++ lines.append(body)
++ lines.append(b' </release>')
++ lines.append(b'</grit>')
++ ret = grd_reader.Parse(io.BytesIO(b'\n'.join(lines)), dir='.')
++ ret.SetOutputLanguage('en')
++ if run_gatherers:
++ ret.RunGatherers()
++ ret.SetPredeterminedIdsFile(predetermined_ids_file)
++ ret.InitializeIds()
++ return ret
++
++
++def StripBlankLinesAndComments(text):
++ '''Strips blank lines and comments from C source code, for unit tests.'''
++ return '\n'.join(line for line in text.splitlines()
++ if line and not line.startswith('//'))
++
++
++def dirname(filename):
++ '''Version of os.path.dirname() that never returns empty paths (returns
++ '.' if the result of os.path.dirname() is empty).
++ '''
++ ret = os.path.dirname(filename)
++ if ret == '':
++ ret = '.'
++ return ret
++
++
++def normpath(path):
++ '''Version of os.path.normpath that also changes backward slashes to
++ forward slashes when not running on Windows.
++ '''
++ # This is safe to always do because the Windows version of os.path.normpath
++ # will replace forward slashes with backward slashes.
++ path = path.replace('\\', '/')
++ return os.path.normpath(path)
++
++
++_LANGUAGE_SPLIT_RE = lazy_re.compile('-|_|/')
++
++
++def CanonicalLanguage(code):
++ '''Canonicalizes two-part language codes by using a dash and making the
++ second part upper case. Returns one-part language codes unchanged.
++
++ Args:
++ code: 'zh_cn'
++
++ Return:
++ code: 'zh-CN'
++ '''
++ parts = _LANGUAGE_SPLIT_RE.split(code)
++ code = [ parts[0] ]
++ for part in parts[1:]:
++ code.append(part.upper())
++ return '-'.join(code)
++
++
++_LANG_TO_CODEPAGE = {
++ 'en' : 1252,
++ 'fr' : 1252,
++ 'it' : 1252,
++ 'de' : 1252,
++ 'es' : 1252,
++ 'nl' : 1252,
++ 'sv' : 1252,
++ 'no' : 1252,
++ 'da' : 1252,
++ 'fi' : 1252,
++ 'pt-BR' : 1252,
++ 'ru' : 1251,
++ 'ja' : 932,
++ 'zh-TW' : 950,
++ 'zh-CN' : 936,
++ 'ko' : 949,
++}
++
++
++def LanguageToCodepage(lang):
++ '''Returns the codepage _number_ that can be used to represent 'lang', which
++ may be either in formats such as 'en', 'pt_br', 'pt-BR', etc.
++
++ The codepage returned will be one of the 'cpXXXX' codepage numbers.
++
++ Args:
++ lang: 'de'
++
++ Return:
++ 1252
++ '''
++ lang = CanonicalLanguage(lang)
++ if lang in _LANG_TO_CODEPAGE:
++ return _LANG_TO_CODEPAGE[lang]
++ else:
++ print("Not sure which codepage to use for %s, assuming cp1252" % lang)
++ return 1252
++
++def NewClassInstance(class_name, class_type):
++ '''Returns an instance of the class specified in classname
++
++ Args:
++ class_name: the fully qualified, dot separated package + classname,
++ i.e. "my.package.name.MyClass". Short class names are not supported.
++ class_type: the class or superclass this object must implement
++
++ Return:
++ An instance of the class, or None if none was found
++ '''
++ lastdot = class_name.rfind('.')
++ module_name = ''
++ if lastdot >= 0:
++ module_name = class_name[0:lastdot]
++ if module_name:
++ class_name = class_name[lastdot+1:]
++ module = __import__(module_name, globals(), locals(), [''])
++ if hasattr(module, class_name):
++ class_ = getattr(module, class_name)
++ class_instance = class_()
++ if isinstance(class_instance, class_type):
++ return class_instance
++ return None
++
++
++def FixLineEnd(text, line_end):
++ # First normalize
++ text = text.replace('\r\n', '\n')
++ text = text.replace('\r', '\n')
++ # Then fix
++ text = text.replace('\n', line_end)
++ return text
++
++
++def BoolToString(bool):
++ if bool:
++ return 'true'
++ else:
++ return 'false'
++
++
++verbose = False
++extra_verbose = False
++
++def IsVerbose():
++ return verbose
++
++def IsExtraVerbose():
++ return extra_verbose
++
++def ParseDefine(define):
++ '''Parses a define argument and returns the name and value.
++
++ The format is either "NAME=VAL" or "NAME", using True as the default value.
++ Values of "1"/"true" and "0"/"false" are transformed to True and False
++ respectively.
++
++ Args:
++ define: a string of the form "NAME=VAL" or "NAME".
++
++ Returns:
++ A (name, value) pair. name is a string, value a string or boolean.
++ '''
++ parts = [part.strip() for part in define.split('=', 1)]
++ assert len(parts) >= 1
++ name = parts[0]
++ val = True
++ if len(parts) > 1:
++ val = parts[1]
++ if val == "1" or val == "true": val = True
++ elif val == "0" or val == "false": val = False
++ return (name, val)
++
++
++class Substituter(object):
++ '''Finds and substitutes variable names in text strings.
++
++ Given a dictionary of variable names and values, prepares to
++ search for patterns of the form [VAR_NAME] in a text.
++ The value will be substituted back efficiently.
++ Also applies to tclib.Message objects.
++ '''
++
++ def __init__(self):
++ '''Create an empty substituter.'''
++ self.substitutions_ = {}
++ self.dirty_ = True
++
++ def AddSubstitutions(self, subs):
++ '''Add new values to the substitutor.
++
++ Args:
++ subs: A dictionary of new substitutions.
++ '''
++ self.substitutions_.update(subs)
++ self.dirty_ = True
++
++ def AddMessages(self, messages, lang):
++ '''Adds substitutions extracted from node.Message objects.
++
++ Args:
++ messages: a list of node.Message objects.
++ lang: The translation language to use in substitutions.
++ '''
++ subs = [(str(msg.attrs['name']), msg.Translate(lang)) for msg in messages]
++ self.AddSubstitutions(dict(subs))
++ self.dirty_ = True
++
++ def GetExp(self):
++ '''Obtain a regular expression that will find substitution keys in text.
++
++ Create and cache if the substituter has been updated. Use the cached value
++ otherwise. Keys will be enclosed in [square brackets] in text.
++
++ Returns:
++ A regular expression object.
++ '''
++ if self.dirty_:
++ components = [r'\[%s\]' % (k,) for k in self.substitutions_]
++ self.exp = re.compile(r'(%s)' % ('|'.join(components),))
++ self.dirty_ = False
++ return self.exp
++
++ def Substitute(self, text):
++ '''Substitute the variable values in the given text.
++
++ Text of the form [message_name] will be replaced by the message's value.
++
++ Args:
++ text: A string of text.
++
++ Returns:
++ A string of text with substitutions done.
++ '''
++ return ''.join([self._SubFragment(f) for f in self.GetExp().split(text)])
++
++ def _SubFragment(self, fragment):
++ '''Utility function for Substitute.
++
++ Performs a simple substitution if the fragment is exactly of the form
++ [message_name].
++
++ Args:
++ fragment: A simple string.
++
++ Returns:
++ A string with the substitution done.
++ '''
++ if len(fragment) > 2 and fragment[0] == '[' and fragment[-1] == ']':
++ sub = self.substitutions_.get(fragment[1:-1], None)
++ if sub is not None:
++ return sub
++ return fragment
++
++ def SubstituteMessage(self, msg):
++ '''Apply substitutions to a tclib.Message object.
++
++ Text of the form [message_name] will be replaced by a new placeholder,
++ whose presentation will take the form the message_name_{UsageCount}, and
++ whose example will be the message's value. Existing placeholders are
++ not affected.
++
++ Args:
++ msg: A tclib.Message object.
++
++ Returns:
++ A tclib.Message object, with substitutions done.
++ '''
++ from grit import tclib # avoid circular import
++ counts = {}
++ text = msg.GetPresentableContent()
++ placeholders = []
++ newtext = ''
++ for f in self.GetExp().split(text):
++ sub = self._SubFragment(f)
++ if f != sub:
++ f = str(f)
++ count = counts.get(f, 0) + 1
++ counts[f] = count
++ name = "%s_%d" % (f[1:-1], count)
++ placeholders.append(tclib.Placeholder(name, f, sub))
++ newtext += name
++ else:
++ newtext += f
++ if placeholders:
++ return tclib.Message(newtext, msg.GetPlaceholders() + placeholders,
++ msg.GetDescription(), msg.GetMeaning())
++ else:
++ return msg
++
++
++class TempDir(object):
++ '''Creates files with the specified contents in a temporary directory,
++ for unit testing.
++ '''
++
++ def __init__(self, file_data, mode='w'):
++ self._tmp_dir_name = tempfile.mkdtemp()
++ assert not os.listdir(self.GetPath())
++ for name, contents in file_data.items():
++ file_path = self.GetPath(name)
++ dir_path = os.path.split(file_path)[0]
++ if not os.path.exists(dir_path):
++ os.makedirs(dir_path)
++ with open(file_path, mode) as f:
++ f.write(file_data[name])
++
++ def __enter__(self):
++ return self
++
++ def __exit__(self, *exc_info):
++ self.CleanUp()
++
++ def CleanUp(self):
++ shutil.rmtree(self.GetPath())
++
++ def GetPath(self, name=''):
++ name = os.path.join(self._tmp_dir_name, name)
++ assert name.startswith(self._tmp_dir_name)
++ return name
++
++ def AsCurrentDir(self):
++ return self._AsCurrentDirClass(self.GetPath())
++
++ class _AsCurrentDirClass(object):
++ def __init__(self, path):
++ self.path = path
++ def __enter__(self):
++ self.oldpath = os.getcwd()
++ os.chdir(self.path)
++ def __exit__(self, *exc_info):
++ os.chdir(self.oldpath)
+diff --git a/tools/grit/grit/util_unittest.py b/tools/grit/grit/util_unittest.py
+new file mode 100644
+index 0000000000..7d6efaf858
+--- /dev/null
++++ b/tools/grit/grit/util_unittest.py
+@@ -0,0 +1,118 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit test that checks some of util functions.
++'''
++
++from __future__ import print_function
++
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import unittest
++
++import six
++
++from grit import util
++
++
++class UtilUnittest(unittest.TestCase):
++ ''' Tests functions from util
++ '''
++
++ def testNewClassInstance(self):
++ # Test short class name with no fully qualified package name
++ # Should fail, it is not supported by the function now (as documented)
++ cls = util.NewClassInstance('grit.util.TestClassToLoad',
++ TestBaseClassToLoad)
++ self.failUnless(cls == None)
++
++ # Test non existent class name
++ cls = util.NewClassInstance('grit.util_unittest.NotExistingClass',
++ TestBaseClassToLoad)
++ self.failUnless(cls == None)
++
++ # Test valid class name and valid base class
++ cls = util.NewClassInstance('grit.util_unittest.TestClassToLoad',
++ TestBaseClassToLoad)
++ self.failUnless(isinstance(cls, TestBaseClassToLoad))
++
++ # Test valid class name with wrong hierarchy
++ cls = util.NewClassInstance('grit.util_unittest.TestClassNoBase',
++ TestBaseClassToLoad)
++ self.failUnless(cls == None)
++
++ def testCanonicalLanguage(self):
++ self.failUnless(util.CanonicalLanguage('en') == 'en')
++ self.failUnless(util.CanonicalLanguage('pt_br') == 'pt-BR')
++ self.failUnless(util.CanonicalLanguage('pt-br') == 'pt-BR')
++ self.failUnless(util.CanonicalLanguage('pt-BR') == 'pt-BR')
++ self.failUnless(util.CanonicalLanguage('pt/br') == 'pt-BR')
++ self.failUnless(util.CanonicalLanguage('pt/BR') == 'pt-BR')
++ self.failUnless(util.CanonicalLanguage('no_no_bokmal') == 'no-NO-BOKMAL')
++
++ def testUnescapeHtml(self):
++ self.failUnless(util.UnescapeHtml('&#1010;') == six.unichr(1010))
++ self.failUnless(util.UnescapeHtml('&#xABcd;') == six.unichr(43981))
++
++ def testRelativePath(self):
++ """ Verify that MakeRelativePath works in some tricky cases."""
++
++ def TestRelativePathCombinations(base_path, other_path, expected_result):
++ """ Verify that the relative path function works for
++ the given paths regardless of whether or not they end with
++ a trailing slash."""
++ for path1 in [base_path, base_path + os.path.sep]:
++ for path2 in [other_path, other_path + os.path.sep]:
++ result = util.MakeRelativePath(path1, path2)
++ self.failUnless(result == expected_result)
++
++ # set-up variables
++ root_dir = 'c:%sa' % os.path.sep
++ result1 = '..%sabc' % os.path.sep
++ path1 = root_dir + 'bc'
++ result2 = 'bc'
++ path2 = '%s%s%s' % (root_dir, os.path.sep, result2)
++ # run the tests
++ TestRelativePathCombinations(root_dir, path1, result1)
++ TestRelativePathCombinations(root_dir, path2, result2)
++
++ def testReadFile(self):
++ def Test(data, encoding, expected_result):
++ with open('testfile', 'wb') as f:
++ f.write(data)
++ self.assertEqual(util.ReadFile('testfile', encoding), expected_result)
++
++ test_std_newline = b'\xEF\xBB\xBFabc\ndef' # EF BB BF is UTF-8 BOM
++ newlines = [b'\n', b'\r\n', b'\r']
++
++ with util.TempDir({}) as tmp_dir:
++ with tmp_dir.AsCurrentDir():
++ for newline in newlines:
++ test = test_std_newline.replace(b'\n', newline)
++ Test(test, util.BINARY, test)
++ # utf-8 doesn't strip BOM
++ Test(test, 'utf-8', test_std_newline.decode('utf-8'))
++ # utf-8-sig strips BOM
++ Test(test, 'utf-8-sig', test_std_newline.decode('utf-8')[1:])
++ # test another encoding
++ Test(test, 'cp1252', test_std_newline.decode('cp1252'))
++ self.assertRaises(UnicodeDecodeError, Test, b'\x80', 'utf-8', None)
++
++
++class TestBaseClassToLoad(object):
++ pass
++
++class TestClassToLoad(TestBaseClassToLoad):
++ pass
++
++class TestClassNoBase(object):
++ pass
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit/xtb_reader.py b/tools/grit/grit/xtb_reader.py
+new file mode 100644
+index 0000000000..e0f842588a
+--- /dev/null
++++ b/tools/grit/grit/xtb_reader.py
+@@ -0,0 +1,140 @@
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Fast and efficient parser for XTB files.
++'''
++
++from __future__ import print_function
++
++import sys
++import xml.sax
++import xml.sax.handler
++
++import grit.node.base
++
++
++class XtbContentHandler(xml.sax.handler.ContentHandler):
++ '''A content handler that calls a given callback function for each
++ translation in the XTB file.
++ '''
++
++ def __init__(self, callback, defs=None, debug=False, target_platform=None):
++ self.callback = callback
++ self.debug = debug
++ # 0 if we are not currently parsing a translation, otherwise the message
++ # ID of that translation.
++ self.current_id = 0
++ # Empty if we are not currently parsing a translation, otherwise the
++ # parts we have for that translation - a list of tuples
++ # (is_placeholder, text)
++ self.current_structure = []
++ # Set to the language ID when we see the <translationbundle> node.
++ self.language = ''
++ # Keep track of the if block we're inside. We can't nest ifs.
++ self.if_expr = None
++ # Root defines to be used with if expr.
++ if defs:
++ self.defines = defs
++ else:
++ self.defines = {}
++ # Target platform for build.
++ if target_platform:
++ self.target_platform = target_platform
++ else:
++ self.target_platform = sys.platform
++
++ def startElement(self, name, attrs):
++ if name == 'translation':
++ assert self.current_id == 0 and len(self.current_structure) == 0, (
++ "Didn't expect a <translation> element here.")
++ self.current_id = attrs.getValue('id')
++ elif name == 'ph':
++ assert self.current_id != 0, "Didn't expect a <ph> element here."
++ self.current_structure.append((True, attrs.getValue('name')))
++ elif name == 'translationbundle':
++ self.language = attrs.getValue('lang')
++ elif name in ('if', 'then', 'else'):
++ assert self.if_expr is None, "Can't nest <if> or use <else> in xtb files"
++ self.if_expr = attrs.getValue('expr')
++
++ def endElement(self, name):
++ if name == 'translation':
++ assert self.current_id != 0
++
++ defs = self.defines
++ def pp_ifdef(define):
++ return define in defs
++ def pp_if(define):
++ return define in defs and defs[define]
++
++ # If we're in an if block, only call the callback (add the translation)
++ # if the expression is True.
++ should_run_callback = True
++ if self.if_expr:
++ should_run_callback = grit.node.base.Node.EvaluateExpression(
++ self.if_expr, self.defines, self.target_platform)
++ if should_run_callback:
++ self.callback(self.current_id, self.current_structure)
++
++ self.current_id = 0
++ self.current_structure = []
++ elif name == 'if':
++ assert self.if_expr is not None
++ self.if_expr = None
++
++ def characters(self, content):
++ if self.current_id != 0:
++ # We are inside a <translation> node so just add the characters to our
++ # structure.
++ #
++ # This naive way of handling characters is OK because in the XTB format,
++ # <ph> nodes are always empty (always <ph name="XXX"/>) and whitespace
++ # inside the <translation> node should be preserved.
++ self.current_structure.append((False, content))
++
++
++class XtbErrorHandler(xml.sax.handler.ErrorHandler):
++ def error(self, exception):
++ pass
++
++ def fatalError(self, exception):
++ raise exception
++
++ def warning(self, exception):
++ pass
++
++
++def Parse(xtb_file, callback_function, defs=None, debug=False,
++ target_platform=None):
++ '''Parse xtb_file, making a call to callback_function for every translation
++ in the XTB file.
++
++ The callback function must have the signature as described below. The 'parts'
++ parameter is a list of tuples (is_placeholder, text). The 'text' part is
++ either the raw text (if is_placeholder is False) or the name of the placeholder
++ (if is_placeholder is True).
++
++ Args:
++ xtb_file: open('fr.xtb', 'rb')
++ callback_function: def Callback(msg_id, parts): pass
++ defs: None, or a dictionary of preprocessor definitions.
++ debug: Default False. Set True for verbose debug output.
++ target_platform: None, or a sys.platform-like identifier of the build
++ target platform.
++
++ Return:
++ The language of the XTB, e.g. 'fr'
++ '''
++ # Start by advancing the file pointer past the DOCTYPE thing, as the TC
++ # uses a path to the DTD that only works in Unix.
++ # TODO(joi) Remove this ugly hack by getting the TC gang to change the
++ # XTB files somehow?
++ front_of_file = xtb_file.read(1024)
++ xtb_file.seek(front_of_file.find(b'<translationbundle'))
++
++ handler = XtbContentHandler(callback=callback_function, defs=defs,
++ debug=debug, target_platform=target_platform)
++ xml.sax.parse(xtb_file, handler)
++ assert handler.language != ''
++ return handler.language
+diff --git a/tools/grit/grit/xtb_reader_unittest.py b/tools/grit/grit/xtb_reader_unittest.py
+new file mode 100644
+index 0000000000..79c0ac9ef1
+--- /dev/null
++++ b/tools/grit/grit/xtb_reader_unittest.py
+@@ -0,0 +1,110 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Unit tests for grit.xtb_reader'''
++
++from __future__ import print_function
++
++import io
++import os
++import sys
++if __name__ == '__main__':
++ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
++
++import unittest
++
++from grit import util
++from grit import xtb_reader
++from grit.node import empty
++
++
++class XtbReaderUnittest(unittest.TestCase):
++ def testParsing(self):
++ xtb_file = io.BytesIO(b'''<?xml version="1.0" encoding="UTF-8"?>
++ <!DOCTYPE translationbundle>
++ <translationbundle lang="fr">
++ <translation id="5282608565720904145">Bingo.</translation>
++ <translation id="2955977306445326147">Bongo longo.</translation>
++ <translation id="238824332917605038">Hullo</translation>
++ <translation id="6629135689895381486"><ph name="PROBLEM_REPORT"/> peut <ph name="START_LINK"/>utilisation excessive de majuscules<ph name="END_LINK"/>.</translation>
++ <translation id="7729135689895381486">Hello
++this is another line
++and another
++
++and another after a blank line.</translation>
++ </translationbundle>''')
++
++ messages = []
++ def Callback(id, structure):
++ messages.append((id, structure))
++ xtb_reader.Parse(xtb_file, Callback)
++ self.failUnless(len(messages[0][1]) == 1)
++ self.failUnless(messages[3][1][0]) # PROBLEM_REPORT placeholder
++ self.failUnless(messages[4][0] == '7729135689895381486')
++ self.failUnless(messages[4][1][7][1] == 'and another after a blank line.')
++
++ def testParsingIntoMessages(self):
++ root = util.ParseGrdForUnittest('''
++ <messages>
++ <message name="ID_MEGA">Fantastic!</message>
++ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
++ </messages>''')
++
++ msgs, = root.GetChildrenOfType(empty.MessagesNode)
++ clique_mega = msgs.children[0].GetCliques()[0]
++ msg_mega = clique_mega.GetMessage()
++ clique_hello_user = msgs.children[1].GetCliques()[0]
++ msg_hello_user = clique_hello_user.GetMessage()
++
++ xtb_file = io.BytesIO(b'''<?xml version="1.0" encoding="UTF-8"?>
++ <!DOCTYPE translationbundle>
++ <translationbundle lang="is">
++ <translation id="%s">Meirihattar!</translation>
++ <translation id="%s">Saelir <ph name="USERNAME"/></translation>
++ </translationbundle>''' % (
++ msg_mega.GetId().encode('utf-8'),
++ msg_hello_user.GetId().encode('utf-8')))
++
++ xtb_reader.Parse(xtb_file,
++ msgs.UberClique().GenerateXtbParserCallback('is'))
++ self.assertEqual('Meirihattar!',
++ clique_mega.MessageForLanguage('is').GetRealContent())
++ self.failUnless('Saelir %s',
++ clique_hello_user.MessageForLanguage('is').GetRealContent())
++
++ def testIfNodesWithUseNameForId(self):
++ root = util.ParseGrdForUnittest('''
++ <messages>
++ <message name="ID_BINGO" use_name_for_id="true">Bingo!</message>
++ </messages>''')
++ msgs, = root.GetChildrenOfType(empty.MessagesNode)
++ clique = msgs.children[0].GetCliques()[0]
++ msg = clique.GetMessage()
++
++ xtb_file = io.BytesIO(b'''<?xml version="1.0" encoding="UTF-8"?>
++ <!DOCTYPE translationbundle>
++ <translationbundle lang="is">
++ <if expr="is_linux">
++ <translation id="ID_BINGO">Bongo!</translation>
++ </if>
++ <if expr="not is_linux">
++ <translation id="ID_BINGO">Congo!</translation>
++ </if>
++ </translationbundle>''')
++ xtb_reader.Parse(xtb_file,
++ msgs.UberClique().GenerateXtbParserCallback('is'),
++ target_platform='darwin')
++ self.assertEqual('Congo!', clique.MessageForLanguage('is').GetRealContent())
++
++ def testParseLargeFile(self):
++ def Callback(id, structure):
++ pass
++ path = util.PathFromRoot('grit/testdata/generated_resources_fr.xtb')
++ with open(path, 'rb') as xtb:
++ xtb_reader.Parse(xtb, Callback)
++
++
++if __name__ == '__main__':
++ unittest.main()
+diff --git a/tools/grit/grit_info.py b/tools/grit/grit_info.py
+new file mode 100644
+index 0000000000..55738f25f6
+--- /dev/null
++++ b/tools/grit/grit_info.py
+@@ -0,0 +1,173 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++'''Tool to determine inputs and outputs of a grit file.
++'''
++
++from __future__ import print_function
++
++import optparse
++import os
++import posixpath
++import sys
++
++from grit import grd_reader
++from grit import util
++
++class WrongNumberOfArguments(Exception):
++ pass
++
++
++def Outputs(filename, defines, ids_file, target_platform=None):
++ grd = grd_reader.Parse(
++ filename, defines=defines, tags_to_ignore=set(['messages']),
++ first_ids_file=ids_file, target_platform=target_platform)
++
++ target = []
++ lang_folders = {}
++ # Add all explicitly-specified output files
++ for output in grd.GetOutputFiles():
++ path = output.GetFilename()
++ target.append(path)
++
++ if path.endswith('.h'):
++ path, filename = os.path.split(path)
++ if output.attrs['lang']:
++ lang_folders[output.attrs['lang']] = os.path.dirname(path)
++
++ return [t.replace('\\', '/') for t in target]
++
++
++def GritSourceFiles():
++ files = []
++ grit_root_dir = os.path.relpath(os.path.dirname(__file__), os.getcwd())
++ for root, dirs, filenames in os.walk(grit_root_dir):
++ grit_src = [os.path.join(root, f) for f in filenames
++ if f.endswith('.py') and not f.endswith('_unittest.py')]
++ files.extend(grit_src)
++ return sorted(files)
++
++
++def Inputs(filename, defines, ids_file, target_platform=None):
++ grd = grd_reader.Parse(
++ filename, debug=False, defines=defines, tags_to_ignore=set(['message']),
++ first_ids_file=ids_file, target_platform=target_platform)
++ files = set()
++ for lang, ctx, fallback in grd.GetConfigurations():
++ # TODO(tdanderson): Refactor all places which perform the action of setting
++ # output attributes on the root. See crbug.com/503637.
++ grd.SetOutputLanguage(lang or grd.GetSourceLanguage())
++ grd.SetOutputContext(ctx)
++ grd.SetFallbackToDefaultLayout(fallback)
++ for node in grd.ActiveDescendants():
++ with node:
++ if (node.name == 'structure' or node.name == 'skeleton' or
++ (node.name == 'file' and node.parent and
++ node.parent.name == 'translations')):
++ path = node.GetInputPath()
++ if path is not None:
++ files.add(grd.ToRealPath(path))
++
++ # If it's a flattened node, grab inlined resources too.
++ if node.name == 'structure' and node.attrs['flattenhtml'] == 'true':
++ node.RunPreSubstitutionGatherer()
++ files.update(node.GetHtmlResourceFilenames())
++ elif node.name == 'grit':
++ first_ids_file = node.GetFirstIdsFile()
++ if first_ids_file:
++ files.add(first_ids_file)
++ elif node.name == 'include':
++ files.add(grd.ToRealPath(node.GetInputPath()))
++ # If it's a flattened node, grab inlined resources too.
++ if node.attrs['flattenhtml'] == 'true':
++ files.update(node.GetHtmlResourceFilenames())
++ elif node.name == 'part':
++ files.add(util.normpath(os.path.join(os.path.dirname(filename),
++ node.GetInputPath())))
++
++ cwd = os.getcwd()
++ return [os.path.relpath(f, cwd) for f in sorted(files)]
++
++
++def PrintUsage():
++ print('USAGE: ./grit_info.py --inputs [-D foo] [-f resource_ids] <grd-file>')
++ print(' ./grit_info.py --outputs [-D foo] [-f resource_ids] ' +
++ '<out-prefix> <grd-file>')
++
++
++def DoMain(argv):
++ os.environ['cwd'] = os.getcwd()
++
++ parser = optparse.OptionParser()
++ parser.add_option("--inputs", action="store_true", dest="inputs")
++ parser.add_option("--outputs", action="store_true", dest="outputs")
++ parser.add_option("-D", action="append", dest="defines", default=[])
++ # grit build also supports '-E KEY=VALUE', support that to share command
++ # line flags.
++ parser.add_option("-E", action="append", dest="build_env", default=[])
++ parser.add_option("-p", action="store", dest="predetermined_ids_file")
++ parser.add_option("-w", action="append", dest="whitelist_files", default=[])
++ parser.add_option("-f", dest="ids_file", default="")
++ parser.add_option("-t", dest="target_platform", default=None)
++
++ options, args = parser.parse_args(argv)
++
++ defines = {}
++ for define in options.defines:
++ name, val = util.ParseDefine(define)
++ defines[name] = val
++
++ for env_pair in options.build_env:
++ (env_name, env_value) = env_pair.split('=', 1)
++ os.environ[env_name] = env_value
++
++ if options.inputs:
++ if len(args) > 1:
++ raise WrongNumberOfArguments("Expected 0 or 1 arguments for --inputs.")
++
++ inputs = []
++ if len(args) == 1:
++ filename = args[0]
++ inputs = Inputs(filename, defines, options.ids_file,
++ options.target_platform)
++
++ # Add in the grit source files. If one of these change, we want to re-run
++ # grit.
++ inputs.extend(GritSourceFiles())
++ inputs = [f.replace('\\', '/') for f in inputs]
++
++ if len(args) == 1:
++ # Include grd file as second input (works around gyp expecting it).
++ inputs.insert(1, args[0])
++ if options.whitelist_files:
++ inputs.extend(options.whitelist_files)
++ return '\n'.join(inputs)
++ elif options.outputs:
++ if len(args) != 2:
++ raise WrongNumberOfArguments(
++ "Expected exactly 2 arguments for --outputs.")
++
++ prefix, filename = args
++ outputs = [posixpath.join(prefix, f)
++ for f in Outputs(filename, defines,
++ options.ids_file, options.target_platform)]
++ return '\n'.join(outputs)
++ else:
++ raise WrongNumberOfArguments("Expected --inputs or --outputs.")
++
++
++def main(argv):
++ try:
++ result = DoMain(argv[1:])
++ except WrongNumberOfArguments as e:
++ PrintUsage()
++ print(e)
++ return 1
++ print(result)
++ return 0
++
++
++if __name__ == '__main__':
++ sys.exit(main(sys.argv))
+diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni
+new file mode 100644
+index 0000000000..fb107ef1a3
+--- /dev/null
++++ b/tools/grit/grit_rule.gni
+@@ -0,0 +1,485 @@
++# Copyright 2014 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++# Instantiate grit. This will produce a script target to run grit (named
++# ${target_name}_grit), and a static library that compiles the .cc files.
++#
++# In general, code should depend on the static library. However, if the
++# generated files are only processed by other actions to generate other
++# files, it is possible to depend on the script target directly.
++#
++# Parameters
++#
++# source (required)
++# Path to .grd file.
++#
++# enable_input_discovery_for_gn_analyze (default=true)
++# Runs grit_info.py via exec_script() when compute_inputs_for_analyze=true
++# in order to discover all files that affect this target.
++# Turn this off when the .grd file is generated, or an <include> with
++# flattenhtml=true points to a generated file.
++# For "gn analyze" to be correct with this arg disabled, all inputs
++# must be listed via |inputs|.
++#
++# inputs (optional)
++# List of additional files, required for grit to process source file.
++#
++# outputs (required)
++# List of outputs from grit, relative to the target_gen_dir. Grit will
++# verify at build time that this list is correct and will fail if there
++# is a mismatch between the outputs specified by the .grd file and the
++# outputs list here.
++#
++# To get this list, you can look in the .grd file for
++# <output filename="..." and put those filename here. The base directory
++# of the list in Grit and the output list specified in the GN grit target
++# are the same (the target_gen_dir) so you can generally copy the names
++# exactly.
++#
++# To get the list of outputs programatically, run:
++# python tools/grit/grit_info.py --outputs . path/to/your.grd
++# And strip the leading "./" from the output files.
++#
++# defines (optional)
++# Extra defines to pass to grit (on top of the global grit_defines list).
++#
++# grit_flags (optional)
++# List of strings containing extra command-line flags to pass to Grit.
++#
++# resource_ids (optional)
++# Path to a grit "firstidsfile". Default is
++# //tools/gritsettings/resource_ids. Set to "" to use the value specified
++# in the <grit> nodes of the processed files.
++#
++# output_dir (optional)
++# Directory for generated files. If you specify this, you will often
++# want to specify output_name if the target name is not particularly
++# unique, since this can cause files from multiple grit targets to
++# overwrite each other.
++#
++# output_name (optional)
++# Provide an alternate base name for the generated files, like the .d
++# files. Normally these are based on the target name and go in the
++# output_dir, but if multiple targets with the same name end up in
++# the same output_dir, they can collide.
++#
++# configs (optional)
++# List of additional configs to be applied to the generated target.
++#
++# deps (optional)
++# testonly (optional)
++# visibility (optional)
++# Normal meaning.
++#
++# Example
++#
++# grit("my_resources") {
++# # Source and outputs are required.
++# source = "myfile.grd"
++# outputs = [
++# "foo_strings.h",
++# "foo_strings.pak",
++# ]
++#
++# grit_flags = [ "-E", "foo=bar" ] # Optional extra flags.
++# # You can also put deps here if the grit source depends on generated
++# # files.
++# }
++import("//build/config/chrome_build.gni")
++import("//build/config/chromeos/ui_mode.gni")
++import("//build/config/compiler/compiler.gni")
++import("//build/config/compute_inputs_for_analyze.gni")
++import("//build/config/crypto.gni")
++import("//build/config/features.gni")
++import("//build/config/sanitizers/sanitizers.gni")
++import("//build/config/ui.gni")
++import("//build/toolchain/gcc_toolchain.gni")
++
++declare_args() {
++ enable_resource_whitelist_generation = is_android && is_official_build
++}
++
++if (enable_resource_whitelist_generation) {
++ assert(target_os == "android" || target_os == "win",
++ "unsupported platform for resource whitelist generation")
++ assert(
++ symbol_level > 0 && !strip_debug_info && !is_component_build,
++ "resource whitelist generation only works on non-component builds with debug info enabled.")
++}
++
++grit_defines = []
++
++if (is_mac || is_win || is_linux || is_chromeos || is_ios) {
++ grit_defines += [
++ "-D",
++ "scale_factors=2x",
++ ]
++}
++
++# Mac and iOS want Title Case strings.
++use_titlecase_in_grd_files = is_apple
++if (use_titlecase_in_grd_files) {
++ grit_defines += [
++ "-D",
++ "use_titlecase",
++ ]
++}
++
++if (is_chrome_branded) {
++ grit_defines += [
++ "-D",
++ "_google_chrome",
++ "-E",
++ "CHROMIUM_BUILD=google_chrome",
++ ]
++} else {
++ grit_defines += [
++ "-D",
++ "_chromium",
++ "-E",
++ "CHROMIUM_BUILD=chromium",
++ ]
++}
++
++if (is_chromeos) {
++ grit_defines += [
++ "-D",
++ "chromeos",
++ ]
++}
++
++if (chromeos_is_browser_only) {
++ grit_defines += [
++ "-D",
++ "lacros",
++ ]
++}
++
++if (is_desktop_linux) {
++ grit_defines += [
++ "-D",
++ "desktop_linux",
++ ]
++}
++
++if (toolkit_views) {
++ grit_defines += [
++ "-D",
++ "toolkit_views",
++ ]
++}
++
++if (use_aura) {
++ grit_defines += [
++ "-D",
++ "use_aura",
++ ]
++}
++
++if (use_nss_certs) {
++ grit_defines += [
++ "-D",
++ "use_nss_certs",
++ ]
++}
++
++if (use_ozone) {
++ grit_defines += [
++ "-D",
++ "use_ozone",
++ ]
++}
++
++if (is_android) {
++ grit_defines += [
++ "-E",
++ "ANDROID_JAVA_TAGGED_ONLY=true",
++ ]
++}
++
++# When cross-compiling, explicitly pass the target system to grit.
++if (current_toolchain != host_toolchain) {
++ if (is_android) {
++ grit_defines += [
++ "-t",
++ "android",
++ ]
++ }
++ if (is_ios) {
++ grit_defines += [
++ "-t",
++ "ios",
++ ]
++ }
++ if (is_linux || is_chromeos) {
++ grit_defines += [
++ "-t",
++ "linux2",
++ ]
++ }
++ if (is_mac) {
++ grit_defines += [
++ "-t",
++ "darwin",
++ ]
++ }
++ if (is_win) {
++ grit_defines += [
++ "-t",
++ "win32",
++ ]
++ }
++}
++
++_strip_resource_files = is_android && is_official_build
++_js_minifier = "//tools/grit/minify_with_uglify.py"
++_css_minifier = "//tools/grit/minimize_css.py"
++
++grit_resource_id_target = "//tools/gritsettings:default_resource_ids"
++grit_resource_id_file =
++ get_label_info(grit_resource_id_target, "target_gen_dir") +
++ "/default_resource_ids"
++grit_info_script = "//tools/grit/grit_info.py"
++
++# TODO(asvitkine): Add predetermined ids files for other platforms.
++grit_predetermined_resource_ids_file = ""
++if (is_mac) {
++ grit_predetermined_resource_ids_file =
++ "//tools/gritsettings/startup_resources_mac.txt"
++}
++if (is_win) {
++ grit_predetermined_resource_ids_file =
++ "//tools/gritsettings/startup_resources_win.txt"
++}
++
++template("grit") {
++ if (defined(invoker.output_dir)) {
++ _output_dir = invoker.output_dir
++ } else {
++ _output_dir = target_gen_dir
++ }
++
++ _grit_outputs =
++ get_path_info(rebase_path(invoker.outputs, ".", _output_dir), "abspath")
++
++ # Add .info output for all pak files
++ _pak_info_outputs = []
++ foreach(output, _grit_outputs) {
++ if (get_path_info(output, "extension") == "pak") {
++ _pak_info_outputs += [ output + ".info" ]
++ }
++ }
++
++ if (defined(invoker.output_name)) {
++ _grit_output_name = invoker.output_name
++ } else {
++ _grit_output_name = target_name
++ }
++
++ _grit_custom_target = target_name + "_grit"
++ action(_grit_custom_target) {
++ testonly = defined(invoker.testonly) && invoker.testonly
++
++ script = "//tools/grit/grit.py"
++ depfile = "$target_gen_dir/$target_name.d"
++
++ inputs = [ invoker.source ]
++ deps = [ "//tools/grit:grit_sources" ]
++ outputs = [ "${depfile}.stamp" ] + _grit_outputs + _pak_info_outputs
++
++ _grit_flags = grit_defines
++
++ # Add extra defines with -D flags.
++ if (defined(invoker.defines)) {
++ foreach(i, invoker.defines) {
++ _grit_flags += [
++ "-D",
++ i,
++ ]
++ }
++ }
++
++ if (defined(invoker.grit_flags)) {
++ _grit_flags += invoker.grit_flags
++ }
++
++ _rebased_source_path = rebase_path(invoker.source, root_build_dir)
++ _enable_grit_info =
++ !defined(invoker.enable_input_discovery_for_gn_analyze) ||
++ invoker.enable_input_discovery_for_gn_analyze
++ if (_enable_grit_info && compute_inputs_for_analyze) {
++ # Only call exec_script when the user has explicitly opted into greater
++ # precision at the expense of performance.
++ _rel_inputs = exec_script("//tools/grit/grit_info.py",
++ [
++ "--inputs",
++ _rebased_source_path,
++ ] + _grit_flags,
++ "list lines")
++ inputs += rebase_path(_rel_inputs, ".", root_build_dir)
++ }
++
++ args = [
++ "-i",
++ _rebased_source_path,
++ "build",
++ "-o",
++ rebase_path(_output_dir, root_build_dir),
++ "--depdir",
++ ".",
++ "--depfile",
++ rebase_path(depfile, root_build_dir),
++ "--write-only-new=1",
++ "--depend-on-stamp",
++ ] + _grit_flags
++
++ # Add brotli executable if using brotli.
++ if (defined(invoker.use_brotli) && invoker.use_brotli) {
++ _brotli_target = "//third_party/brotli:brotli($host_toolchain)"
++ _brotli_executable = get_label_info(_brotli_target, "root_out_dir") +
++ "/" + get_label_info(_brotli_target, "name")
++ if (host_os == "win") {
++ _brotli_executable += ".exe"
++ }
++
++ inputs += [ _brotli_executable ]
++ args += [
++ "--brotli",
++ rebase_path(_brotli_executable, root_build_dir),
++ ]
++ }
++
++ _resource_ids = grit_resource_id_file
++ if (defined(invoker.resource_ids)) {
++ _resource_ids = invoker.resource_ids
++ }
++
++ if (_resource_ids != "") {
++ inputs += [ _resource_ids ]
++ args += [
++ "-f",
++ rebase_path(_resource_ids, root_build_dir),
++ ]
++ if (_resource_ids == grit_resource_id_file) {
++ deps += [ grit_resource_id_target ]
++ }
++ }
++ if (grit_predetermined_resource_ids_file != "") {
++ inputs += [ grit_predetermined_resource_ids_file ]
++ args += [
++ "-p",
++ rebase_path(grit_predetermined_resource_ids_file, root_build_dir),
++ ]
++ }
++
++ # We want to make sure the declared outputs actually match what Grit is
++ # writing. We write the list to a file (some of the output lists are long
++ # enough to not fit on a Windows command line) and ask Grit to verify those
++ # are the actual outputs at runtime.
++ _asserted_list_file =
++ "$target_out_dir/${_grit_output_name}_expected_outputs.txt"
++ write_file(_asserted_list_file,
++ rebase_path(invoker.outputs, root_build_dir, _output_dir))
++ inputs += [ _asserted_list_file ]
++ args += [
++ "--assert-file-list",
++ rebase_path(_asserted_list_file, root_build_dir),
++ ]
++
++ if (enable_resource_whitelist_generation) {
++ _rc_grit_outputs = []
++ foreach(output, _grit_outputs) {
++ if (get_path_info(output, "extension") == "rc") {
++ _rc_grit_outputs += [ output ]
++ }
++ }
++
++ if (_rc_grit_outputs != []) {
++ # Resource whitelisting cannot be used with .rc files.
++ # Make sure that there aren't any .pak outputs which would require
++ # whitelist annotations.
++ assert(_pak_info_outputs == [], "can't combine .pak and .rc outputs")
++ } else {
++ args += [ "--whitelist-support" ]
++ }
++ }
++ if (_strip_resource_files) {
++ _js_minifier_command = rebase_path(_js_minifier, root_build_dir)
++ _css_minifier_command = rebase_path(_css_minifier, root_build_dir)
++ args += [
++ "--js-minifier",
++ _js_minifier_command,
++ "--css-minifier",
++ _css_minifier_command,
++ ]
++ inputs += [
++ _js_minifier,
++ _css_minifier,
++ ]
++ }
++
++ if (defined(invoker.visibility)) {
++ # This needs to include both what the invoker specified (since they
++ # probably include generated headers from this target), as well as the
++ # generated source set (since there's no guarantee that the visibility
++ # specified by the invoker includes our target).
++ #
++ # Only define visibility at all if the invoker specified it. Otherwise,
++ # we want to keep the public "no visibility specified" default.
++ visibility = [ ":${invoker.target_name}" ] + invoker.visibility
++ }
++
++ if (defined(invoker.use_brotli) && invoker.use_brotli) {
++ if (is_mac && is_asan) {
++ deps += [ "//tools/grit:brotli_mac_asan_workaround" ]
++ } else {
++ deps += [ "//third_party/brotli:brotli($host_toolchain)" ]
++ }
++ }
++ if (defined(invoker.deps)) {
++ deps += invoker.deps
++ }
++ if (defined(invoker.inputs)) {
++ inputs += invoker.inputs
++ }
++ }
++
++ # This is the thing that people actually link with, it must be named the
++ # same as the argument the template was invoked with.
++ source_set(target_name) {
++ testonly = defined(invoker.testonly) && invoker.testonly
++
++ # Since we generate a file, we need to be run before the targets that
++ # depend on us.
++ sources = []
++ foreach(_output, _grit_outputs) {
++ _extension = get_path_info(_output, "extension")
++ if (_extension != "json" && _extension != "gz" && _extension != "pak" &&
++ _extension != "xml") {
++ sources += [ _output ]
++ }
++ }
++
++ # Deps set on the template invocation will go on the action that runs
++ # grit above rather than this library. This target needs to depend on the
++ # action publicly so other scripts can take the outputs from the grit
++ # script as inputs.
++ public_deps = [ ":$_grit_custom_target" ]
++
++ deps = [ "//base" ]
++
++ if (defined(invoker.public_configs)) {
++ public_configs += invoker.public_configs
++ }
++
++ if (defined(invoker.configs)) {
++ configs += invoker.configs
++ }
++
++ if (defined(invoker.visibility)) {
++ visibility = invoker.visibility
++ }
++ output_name = _grit_output_name
++ }
++}
+diff --git a/tools/grit/minify_with_uglify.py b/tools/grit/minify_with_uglify.py
+new file mode 100644
+index 0000000000..788ffa6a75
+--- /dev/null
++++ b/tools/grit/minify_with_uglify.py
+@@ -0,0 +1,44 @@
++#!/usr/bin/env python
++# Copyright 2019 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++from __future__ import print_function
++
++import os
++import sys
++import tempfile
++
++_HERE_PATH = os.path.dirname(__file__)
++_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..'))
++sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node'))
++
++import node
++import node_modules
++
++def Minify(source):
++ # Open two temporary files, so that uglify can read the input from one and
++ # write its output to the other.
++ with tempfile.NamedTemporaryFile(suffix='.js') as infile, \
++ tempfile.NamedTemporaryFile(suffix='.js') as outfile:
++ infile.write(source)
++ infile.flush();
++ node.RunNode([
++ node_modules.PathToUglify(), infile.name, '--output', outfile.name])
++ result = outfile.read()
++ return result
++
++
++def main():
++ orig_stdout = sys.stdout
++ result = ''
++ try:
++ sys.stdout = sys.stderr
++ result = Minify(sys.stdin.read())
++ finally:
++ sys.stdout = orig_stdout
++ print(result)
++
++
++if __name__ == '__main__':
++ main()
+diff --git a/tools/grit/minimize_css.py b/tools/grit/minimize_css.py
+new file mode 100644
+index 0000000000..2c3b8aeb1e
+--- /dev/null
++++ b/tools/grit/minimize_css.py
+@@ -0,0 +1,105 @@
++#!/usr/bin/env python
++# Copyright 2016 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++import re
++import sys
++
++class CSSMinimizer(object):
++
++ INITIAL = 0
++ MAYBE_COMMENT_START = 1
++ INSIDE_COMMENT = 2
++ MAYBE_COMMENT_END = 3
++ INSIDE_SINGLE_QUOTE = 4
++ INSIDE_SINGLE_QUOTE_ESCAPE = 5
++ INSIDE_DOUBLE_QUOTE = 6
++ INSIDE_DOUBLE_QUOTE_ESCAPE = 7
++
++ def __init__(self):
++ self._output = ''
++ self._codeblock = ''
++
++ def flush_codeblock(self):
++ stripped = re.sub(r"\s+", ' ', self._codeblock)
++ stripped = re.sub(r";?\s*(?P<op>[{};])\s*", r'\g<op>', stripped)
++ self._output += stripped
++ self._codeblock = ''
++
++ def parse(self, content):
++ state = self.INITIAL
++ for char in content:
++ if state == self.INITIAL:
++ if char == '/':
++ state = self.MAYBE_COMMENT_START
++ elif char == "'":
++ self.flush_codeblock()
++ self._output += char
++ state = self.INSIDE_SINGLE_QUOTE
++ elif char == '"':
++ self.flush_codeblock()
++ self._output += char
++ state = self.INSIDE_DOUBLE_QUOTE
++ else:
++ self._codeblock += char
++ elif state == self.MAYBE_COMMENT_START:
++ if char == '*':
++ self.flush_codeblock()
++ state = self.INSIDE_COMMENT
++ else:
++ self._codeblock += '/' + char
++ state = self.INITIAL
++ elif state == self.INSIDE_COMMENT:
++ if char == '*':
++ state = self.MAYBE_COMMENT_END
++ else:
++ pass
++ elif state == self.MAYBE_COMMENT_END:
++ if char == '/':
++ state = self.INITIAL
++ else:
++ state = self.INSIDE_COMMENT
++ elif state == self.INSIDE_SINGLE_QUOTE:
++ if char == '\\':
++ self._output += char
++ state = self.INSIDE_SINGLE_QUOTE_ESCAPE
++ elif char == "'":
++ self._output += char
++ state = self.INITIAL
++ else:
++ self._output += char
++ elif state == self.INSIDE_SINGLE_QUOTE_ESCAPE:
++ self._output += char
++ state = self.INSIDE_SINGLE_QUOTE
++ elif state == self.INSIDE_DOUBLE_QUOTE:
++ if char == '\\':
++ self._output += char
++ state = self.INSIDE_DOUBLE_QUOTE_ESCAPE
++ elif char == '"':
++ self._output += char
++ state = self.INITIAL
++ else:
++ self._output += char
++ elif state == self.INSIDE_DOUBLE_QUOTE_ESCAPE:
++ self._output += char
++ state = self.INSIDE_DOUBLE_QUOTE
++
++ self.flush_codeblock()
++ self._output = self._output.strip()
++ return self._output
++
++ @classmethod
++ def minimize_css(cls, content):
++ minimizer = CSSMinimizer()
++ return minimizer.parse(content)
++
++def main():
++ result = ''
++ try:
++ result = CSSMinimizer.minimize_css(sys.stdin.read())
++ finally:
++ print(result)
++
++if __name__ == '__main__':
++ main()
+diff --git a/tools/grit/minimize_css_unittest.py b/tools/grit/minimize_css_unittest.py
+new file mode 100644
+index 0000000000..cddc313078
+--- /dev/null
++++ b/tools/grit/minimize_css_unittest.py
+@@ -0,0 +1,58 @@
++#!/usr/bin/env python
++# Copyright 2016 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++import unittest
++
++import minimize_css
++
++
++class CSSMinimizerTest(unittest.TestCase):
++
++ def test_simple(self):
++ source = """
++ div {
++ color: blue;
++ }
++ """
++ minimized = minimize_css.CSSMinimizer.minimize_css(source)
++ self.assertEquals(minimized, "div{color: blue}")
++
++ def test_attribute_selectors(self):
++ source = """
++ input[type="search" i]::-webkit-textfield-decoration-container {
++ direction: ltr;
++ }
++ """
++ minimized = minimize_css.CSSMinimizer.minimize_css(source)
++ self.assertEquals(
++ minimized,
++ # pylint: disable=line-too-long
++ """input[type="search" i]::-webkit-textfield-decoration-container{direction: ltr}""")
++
++ def test_strip_comment(self):
++ source = """
++ /* header */
++ html {
++ /* inside block */
++ display: block;
++ }
++ /* footer */
++ """
++ minimized = minimize_css.CSSMinimizer.minimize_css(source)
++ self.assertEquals(minimized, "html{ display: block}")
++
++ def test_no_strip_inside_quotes(self):
++ source = """div[foo=' bar ']"""
++ minimized = minimize_css.CSSMinimizer.minimize_css(source)
++ self.assertEquals(minimized, source)
++
++ source = """div[foo=" bar "]"""
++ minimized = minimize_css.CSSMinimizer.minimize_css(source)
++ self.assertEquals(minimized, source)
++
++ def test_escape_string(self):
++ source = """content: " <a onclick=\\\"javascript: alert ( 'foobar' ); \\\">";"""
++ minimized = minimize_css.CSSMinimizer.minimize_css(source)
++ self.assertEquals(minimized, source)
+diff --git a/tools/grit/pak_util.py b/tools/grit/pak_util.py
+new file mode 100644
+index 0000000000..ede638bbe1
+--- /dev/null
++++ b/tools/grit/pak_util.py
+@@ -0,0 +1,223 @@
++#!/usr/bin/env python
++# Copyright 2017 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""A tool for interacting with .pak files.
++
++For details on the pak file format, see:
++https://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
++"""
++
++from __future__ import print_function
++
++import argparse
++import gzip
++import hashlib
++import os
++import shutil
++import sys
++import tempfile
++
++# Import grit first to get local third_party modules.
++import grit # pylint: disable=ungrouped-imports,unused-import
++
++import six
++
++from grit.format import data_pack
++
++
++def _RepackMain(args):
++ output_info_filepath = args.output_pak_file + '.info'
++ if args.compress:
++ # If the file needs to be compressed, call RePack with a tempfile path,
++ # then compress the tempfile to args.output_pak_file.
++ temp_outfile = tempfile.NamedTemporaryFile()
++ out_path = temp_outfile.name
++ # Strip any non .pak extension from the .info output file path.
++ splitext = os.path.splitext(args.output_pak_file)
++ if splitext[1] != '.pak':
++ output_info_filepath = splitext[0] + '.info'
++ else:
++ out_path = args.output_pak_file
++ data_pack.RePack(out_path, args.input_pak_files, args.whitelist,
++ args.suppress_removed_key_output,
++ output_info_filepath=output_info_filepath)
++ if args.compress:
++ with open(args.output_pak_file, 'wb') as out:
++ with gzip.GzipFile(filename='', mode='wb', fileobj=out, mtime=0) as outgz:
++ shutil.copyfileobj(temp_outfile, outgz)
++
++
++def _ExtractMain(args):
++ pak = data_pack.ReadDataPack(args.pak_file)
++ if args.textual_id:
++ info_dict = data_pack.ReadGrdInfo(args.pak_file)
++ for resource_id, payload in pak.resources.items():
++ filename = (
++ info_dict[resource_id].textual_id
++ if args.textual_id else str(resource_id))
++ path = os.path.join(args.output_dir, filename)
++ with open(path, 'w') as f:
++ f.write(payload)
++
++
++def _CreateMain(args):
++ pak = {}
++ for name in os.listdir(args.input_dir):
++ try:
++ resource_id = int(name)
++ except:
++ continue
++ filename = os.path.join(args.input_dir, name)
++ if os.path.isfile(filename):
++ with open(filename, 'rb') as f:
++ pak[resource_id] = f.read()
++ data_pack.WriteDataPack(pak, args.output_pak_file, data_pack.UTF8)
++
++
++def _PrintMain(args):
++ pak = data_pack.ReadDataPack(args.pak_file)
++ if args.textual_id:
++ info_dict = data_pack.ReadGrdInfo(args.pak_file)
++ output = args.output
++ encoding = 'binary'
++ if pak.encoding == 1:
++ encoding = 'utf-8'
++ elif pak.encoding == 2:
++ encoding = 'utf-16'
++ else:
++ encoding = '?' + str(pak.encoding)
++
++ output.write('version: {}\n'.format(pak.version))
++ output.write('encoding: {}\n'.format(encoding))
++ output.write('num_resources: {}\n'.format(len(pak.resources)))
++ output.write('num_aliases: {}\n'.format(len(pak.aliases)))
++ breakdown = ', '.join('{}: {}'.format(*x) for x in pak.sizes)
++ output.write('total_size: {} ({})\n'.format(pak.sizes.total, breakdown))
++
++ try_decode = args.decode and encoding.startswith('utf')
++ # Print IDs in ascending order, since that's the order in which they appear in
++ # the file (order is lost by Python dict).
++ for resource_id in sorted(pak.resources):
++ data = pak.resources[resource_id]
++ canonical_id = pak.aliases.get(resource_id, resource_id)
++ desc = '<data>'
++ if try_decode:
++ try:
++ desc = six.text_type(data, encoding)
++ if len(desc) > 60:
++ desc = desc[:60] + u'...'
++ desc = desc.replace('\n', '\\n')
++ except UnicodeDecodeError:
++ pass
++ sha1 = hashlib.sha1(data).hexdigest()[:10]
++ if args.textual_id:
++ textual_id = info_dict[resource_id].textual_id
++ canonical_textual_id = info_dict[canonical_id].textual_id
++ output.write(
++ u'Entry(id={}, canonical_id={}, size={}, sha1={}): {}\n'.format(
++ textual_id, canonical_textual_id, len(data), sha1,
++ desc).encode('utf-8'))
++ else:
++ output.write(
++ u'Entry(id={}, canonical_id={}, size={}, sha1={}): {}\n'.format(
++ resource_id, canonical_id, len(data), sha1, desc).encode('utf-8'))
++
++
++def _ListMain(args):
++ pak = data_pack.ReadDataPack(args.pak_file)
++ if args.textual_id or args.path:
++ info_dict = data_pack.ReadGrdInfo(args.pak_file)
++ fmt = ''.join([
++ '{id}', ' = {textual_id}' if args.textual_id else '',
++ ' @ {path}' if args.path else '', '\n'
++ ])
++ for resource_id in sorted(pak.resources):
++ item = info_dict[resource_id]
++ args.output.write(
++ fmt.format(textual_id=item.textual_id, id=item.id, path=item.path))
++ else:
++ for resource_id in sorted(pak.resources):
++ args.output.write('%d\n' % resource_id)
++
++
++def main():
++ parser = argparse.ArgumentParser(
++ description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
++ # Subparsers are required by default under Python 2. Python 3 changed to
++ # not required, but didn't include a required option until 3.7. Setting
++ # the required member works in all versions (and setting dest name).
++ sub_parsers = parser.add_subparsers(dest='action')
++ sub_parsers.required = True
++
++ sub_parser = sub_parsers.add_parser('repack',
++ help='Combines several .pak files into one.')
++ sub_parser.add_argument('output_pak_file', help='File to create.')
++ sub_parser.add_argument('input_pak_files', nargs='+',
++ help='Input .pak files.')
++ sub_parser.add_argument('--whitelist',
++ help='Path to a whitelist used to filter output pak file resource IDs.')
++ sub_parser.add_argument('--suppress-removed-key-output', action='store_true',
++ help='Do not log which keys were removed by the whitelist.')
++ sub_parser.add_argument('--compress', dest='compress', action='store_true',
++ default=False, help='Compress output_pak_file using gzip.')
++ sub_parser.set_defaults(func=_RepackMain)
++
++ sub_parser = sub_parsers.add_parser('extract', help='Extracts pak file')
++ sub_parser.add_argument('pak_file')
++ sub_parser.add_argument('-o', '--output-dir', default='.',
++ help='Directory to extract to.')
++ sub_parser.add_argument(
++ '-t',
++ '--textual-id',
++ action='store_true',
++ help='Use textual resource ID (name) (from .info file) as filenames.')
++ sub_parser.set_defaults(func=_ExtractMain)
++
++ sub_parser = sub_parsers.add_parser('create',
++ help='Creates pak file from extracted directory.')
++ sub_parser.add_argument('output_pak_file', help='File to create.')
++ sub_parser.add_argument('-i', '--input-dir', default='.',
++ help='Directory to create from.')
++ sub_parser.set_defaults(func=_CreateMain)
++
++ sub_parser = sub_parsers.add_parser('print',
++ help='Prints all pak IDs and contents. Useful for diffing.')
++ sub_parser.add_argument('pak_file')
++ sub_parser.add_argument('--output', type=argparse.FileType('w'),
++ default=sys.stdout,
++ help='The resource list path to write (default stdout)')
++ sub_parser.add_argument('--no-decode', dest='decode', action='store_false',
++ default=True, help='Do not print entry data.')
++ sub_parser.add_argument(
++ '-t',
++ '--textual-id',
++ action='store_true',
++ help='Print textual ID (name) (from .info file) instead of the ID.')
++ sub_parser.set_defaults(func=_PrintMain)
++
++ sub_parser = sub_parsers.add_parser('list-id',
++ help='Outputs all resource IDs to a file.')
++ sub_parser.add_argument('pak_file')
++ sub_parser.add_argument('--output', type=argparse.FileType('w'),
++ default=sys.stdout,
++ help='The resource list path to write (default stdout)')
++ sub_parser.add_argument(
++ '-t',
++ '--textual-id',
++ action='store_true',
++ help='Print the textual resource ID (from .info file).')
++ sub_parser.add_argument(
++ '-p',
++ '--path',
++ action='store_true',
++ help='Print the resource path (from .info file).')
++ sub_parser.set_defaults(func=_ListMain)
++
++ args = parser.parse_args()
++ args.func(args)
++
++
++if __name__ == '__main__':
++ main()
+diff --git a/tools/grit/repack.gni b/tools/grit/repack.gni
+new file mode 100644
+index 0000000000..193f2dc43f
+--- /dev/null
++++ b/tools/grit/repack.gni
+@@ -0,0 +1,189 @@
++# Copyright 2014 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++import("//tools/grit/grit_rule.gni")
++
++# This file defines a template to invoke grit repack in a consistent manner.
++#
++# Parameters:
++# sources [required]
++# List of pak files that need to be combined.
++#
++# output [required]
++# File name (single string) of the output file.
++#
++# copy_data_to_bundle [optional]
++# Whether to define a bundle_data() for the resulting pak.
++#
++# bundle_output [optional]
++# Path of the file in the application bundle, defaults to
++# {{bundle_resources_dir}}/{{source_file_part}}.
++#
++# compress [optional]
++# Gzip the resulting bundle (and append .gz to the output name).
++#
++# deps [optional]
++# public_deps [optional]
++# visibility [optional]
++# Normal meaning.
++template("repack") {
++ _copy_data_to_bundle =
++ defined(invoker.copy_data_to_bundle) && invoker.copy_data_to_bundle
++ _repack_target_name = target_name
++ if (_copy_data_to_bundle) {
++ _repack_target_name = "${target_name}__repack"
++ }
++
++ _compress = defined(invoker.compress) && invoker.compress
++
++ action(_repack_target_name) {
++ forward_variables_from(invoker,
++ [
++ "deps",
++ "public_deps",
++ "testonly",
++ "visibility",
++ ])
++ if (defined(visibility) && _copy_data_to_bundle) {
++ visibility += [ ":${invoker.target_name}" ]
++ }
++ assert(defined(invoker.sources), "Need sources for $target_name")
++ assert(defined(invoker.output), "Need output for $target_name")
++
++ script = "//tools/grit/pak_util.py"
++
++ inputs = invoker.sources
++ outputs = [
++ invoker.output,
++ "${invoker.output}.info",
++ ]
++
++ args = [ "repack" ]
++ if (defined(invoker.repack_whitelist)) {
++ inputs += [ invoker.repack_whitelist ]
++ _rebased_whitelist = rebase_path(invoker.repack_whitelist)
++ args += [ "--whitelist=$_rebased_whitelist" ]
++ args += [ "--suppress-removed-key-output" ]
++ }
++ args += [ rebase_path(invoker.output, root_build_dir) ]
++ args += rebase_path(invoker.sources, root_build_dir)
++ if (_compress) {
++ args += [ "--compress" ]
++ }
++ }
++
++ if (_copy_data_to_bundle) {
++ bundle_data(target_name) {
++ forward_variables_from(invoker,
++ [
++ "testonly",
++ "visibility",
++ ])
++
++ public_deps = [ ":$_repack_target_name" ]
++ sources = [ invoker.output ]
++ if (defined(invoker.bundle_output)) {
++ outputs = [ invoker.bundle_output ]
++ } else {
++ outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
++ }
++ }
++ }
++}
++
++# Repacks a set of .pak files for each locale.
++#
++# Parameters:
++#
++# input_locales [required]
++# List of locale names to use as inputs.
++#
++# output_locales [required]
++# A list containing the corresponding output names for each of the
++# input names. Mac and iOS use different names in some cases.
++#
++# source_patterns [required]
++# The pattern for pak files which need repacked. The filenames always end
++# with "${locale}.pak".
++# E.g.:
++# ${root_gen_dir}/foo_ expands to ${root_gen_dir}/foo_zh-CN.pak
++# when locale is zh-CN.
++#
++# output_dir [optional]
++# Directory in which to put all pak files.
++#
++# deps [optional]
++# visibility [optional]
++# testonly [optional]
++# copy_data_to_bundle [optional]
++# repack_whitelist [optional]
++# Normal meaning.
++template("repack_locales") {
++ if (defined(invoker.output_dir)) {
++ _output_dir = invoker.output_dir
++ } else if (is_ios) {
++ _output_dir = "$target_gen_dir"
++ } else {
++ _output_dir = "$target_gen_dir/$target_name"
++ }
++
++ # GN can't handle invoker.output_locales[foo] (http://crbug.com/614747).
++ _output_locales = invoker.output_locales
++
++ # Collects all targets the loop generates.
++ _locale_targets = []
++
++ # This loop iterates over the input locales and also keeps a counter so it
++ # can simultaneously iterate over the output locales (using GN's very
++ # limited looping capabilities).
++ _current_index = 0
++ foreach(_input_locale, invoker.input_locales) {
++ _output_locale = _output_locales[_current_index]
++
++ # Compute the name of the target for the current file. Save it for the deps.
++ _current_name = "${target_name}_${_input_locale}"
++ _locale_targets += [ ":$_current_name" ]
++
++ repack(_current_name) {
++ forward_variables_from(invoker,
++ [
++ "copy_data_to_bundle",
++ "bundle_output",
++ "compress",
++ "deps",
++ "repack_whitelist",
++ "testonly",
++ ])
++ visibility = [ ":${invoker.target_name}" ]
++ if (is_ios) {
++ output = "$_output_dir/${_output_locale}.lproj/locale.pak"
++ } else {
++ output = "$_output_dir/${_output_locale}.pak"
++ }
++ if (defined(copy_data_to_bundle) && copy_data_to_bundle) {
++ bundle_output =
++ "{{bundle_resources_dir}}/${_output_locale}.lproj/locale.pak"
++ }
++ sources = []
++ foreach(_pattern, invoker.source_patterns) {
++ sources += [ "${_pattern}${_input_locale}.pak" ]
++ }
++ }
++
++ _current_index = _current_index + 1
++ }
++
++ # The group that external targets depend on which collects all deps.
++ group(target_name) {
++ forward_variables_from(invoker,
++ [
++ "visibility",
++ "testonly",
++ ])
++ public_deps = _locale_targets
++ if (!defined(invoker.copy_data_to_bundle) || !invoker.copy_data_to_bundle) {
++ data_deps = public_deps
++ }
++ }
++}
+diff --git a/tools/grit/setup.py b/tools/grit/setup.py
+new file mode 100644
+index 0000000000..5d86dfc2fc
+--- /dev/null
++++ b/tools/grit/setup.py
+@@ -0,0 +1,46 @@
++#!/usr/bin/env python3
++# Copyright 2020 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""Install the package!"""
++
++from __future__ import absolute_import
++
++import setuptools
++
++
++setuptools.setup(
++ name='grit',
++ version='0',
++ entry_points={
++ 'console_scripts': ['grit = grit.grit_runner:Main'],
++ },
++ packages=setuptools.find_packages(),
++ install_requires=[
++ 'six >= 1.10',
++ ],
++ author='The Chromium Authors',
++ author_email='chromium-dev@chromium.org',
++ description='Google Resource and Internationalization Tool for managing '
++ 'translations & resource files',
++ license='BSD-3',
++ url='https://chromium.googlesource.com/chromium/src/tools/grit/',
++ classifiers=[
++ 'Development Status :: 6 - Mature',
++ 'Environment :: Console',
++ 'Intended Audience :: Developers',
++ 'License :: OSI Approved :: BSD License',
++ 'Operating System :: MacOS',
++ 'Operating System :: Microsoft :: Windows',
++ 'Operating System :: POSIX :: Linux',
++ 'Programming Language :: Python',
++ 'Programming Language :: Python :: 2.7',
++ 'Programming Language :: Python :: 3',
++ 'Programming Language :: Python :: 3.6',
++ 'Programming Language :: Python :: 3.7',
++ 'Programming Language :: Python :: 3.8',
++ 'Programming Language :: Python :: 3.9',
++ 'Topic :: Utilities',
++ ],
++)
+diff --git a/tools/grit/stamp_grit_sources.py b/tools/grit/stamp_grit_sources.py
+new file mode 100644
+index 0000000000..bc7265c6cb
+--- /dev/null
++++ b/tools/grit/stamp_grit_sources.py
+@@ -0,0 +1,57 @@
++# Copyright 2014 The Chromium Authors. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++# This script enumerates the files in the given directory, writing an empty
++# stamp file and a .d file listing the inputs required to make the stamp. This
++# allows us to dynamically depend on the grit sources without enumerating the
++# grit directory for every invocation of grit (which is what adding the source
++# files to every .grd file's .d file would entail) or shelling out to grit
++# synchronously during GN execution to get the list (which would be slow).
++#
++# Usage:
++# stamp_grit_sources.py <directory> <stamp-file> <.d-file>
++
++from __future__ import print_function
++
++import os
++import sys
++
++def GritSourceFiles(grit_root_dir):
++ files = []
++ for root, _, filenames in os.walk(grit_root_dir):
++ grit_src = [os.path.join(root, f) for f in filenames
++ if f.endswith('.py') and not f.endswith('_unittest.py')]
++ files.extend(grit_src)
++ files = [f.replace('\\', '/') for f in files]
++ return sorted(files)
++
++
++def WriteDepFile(dep_file, stamp_file, source_files):
++ with open(dep_file, "w") as f:
++ f.write(stamp_file)
++ f.write(": ")
++ f.write(' '.join(source_files))
++
++
++def WriteStampFile(stamp_file):
++ with open(stamp_file, "w"):
++ pass
++
++
++def main(argv):
++ if len(argv) != 4:
++ print("Error: expecting 3 args.")
++ return 1
++
++ grit_root_dir = sys.argv[1]
++ stamp_file = sys.argv[2]
++ dep_file = sys.argv[3]
++
++ WriteStampFile(stamp_file)
++ WriteDepFile(dep_file, stamp_file, GritSourceFiles(grit_root_dir))
++ return 0
++
++
++if __name__ == '__main__':
++ sys.exit(main(sys.argv))
+diff --git a/tools/grit/third_party/six/LICENSE b/tools/grit/third_party/six/LICENSE
+new file mode 100644
+index 0000000000..e558f9d494
+--- /dev/null
++++ b/tools/grit/third_party/six/LICENSE
+@@ -0,0 +1,18 @@
++Copyright (c) 2010-2015 Benjamin Peterson
++
++Permission is hereby granted, free of charge, to any person obtaining a copy of
++this software and associated documentation files (the "Software"), to deal in
++the Software without restriction, including without limitation the rights to
++use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
++the Software, and to permit persons to whom the Software is furnished to do so,
++subject to the following conditions:
++
++The above copyright notice and this permission notice shall be included in all
++copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
++FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
++COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
++IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+diff --git a/tools/grit/third_party/six/README b/tools/grit/third_party/six/README
+new file mode 100644
+index 0000000000..ee628a9db6
+--- /dev/null
++++ b/tools/grit/third_party/six/README
+@@ -0,0 +1,16 @@
++Six is a Python 2 and 3 compatibility library. It provides utility functions
++for smoothing over the differences between the Python versions with the goal of
++writing Python code that is compatible on both Python versions. See the
++documentation for more information on what is provided.
++
++Six supports every Python version since 2.6. It is contained in only one Python
++file, so it can be easily copied into your project. (The copyright and license
++notice must be retained.)
++
++Online documentation is at https://pythonhosted.org/six/.
++
++Bugs can be reported to https://bitbucket.org/gutworth/six. The code can also
++be found there.
++
++For questions about six or porting in general, email the python-porting mailing
++list: https://mail.python.org/mailman/listinfo/python-porting
+diff --git a/tools/grit/third_party/six/README.chromium b/tools/grit/third_party/six/README.chromium
+new file mode 100644
+index 0000000000..100b24d046
+--- /dev/null
++++ b/tools/grit/third_party/six/README.chromium
+@@ -0,0 +1,13 @@
++Name: six
++Short Name: six
++URL: https://bitbucket.org/gutworth/six/commits/tag/1.10.0
++Version: 1.10.0
++Revision: 403:e5218c3f66a2
++License: Apache License, Version 2.0
++
++Description:
++Six is a Python 2 and 3 compatibility library.
++
++Local Modifications:
++- Copied six.py as __init__.py.
++- Kept LICENSE and README.
+diff --git a/tools/grit/third_party/six/__init__.py b/tools/grit/third_party/six/__init__.py
+new file mode 100644
+index 0000000000..56e4272cb3
+--- /dev/null
++++ b/tools/grit/third_party/six/__init__.py
+@@ -0,0 +1,868 @@
++# Copyright (c) 2010-2015 Benjamin Peterson
++#
++# Permission is hereby granted, free of charge, to any person obtaining a copy
++# of this software and associated documentation files (the "Software"), to deal
++# in the Software without restriction, including without limitation the rights
++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++# copies of the Software, and to permit persons to whom the Software is
++# furnished to do so, subject to the following conditions:
++#
++# The above copyright notice and this permission notice shall be included in all
++# copies or substantial portions of the Software.
++#
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++# SOFTWARE.
++
++"""Utilities for writing code that runs on Python 2 and 3"""
++
++from __future__ import absolute_import
++
++import functools
++import itertools
++import operator
++import sys
++import types
++
++__author__ = "Benjamin Peterson <benjamin@python.org>"
++__version__ = "1.10.0"
++
++
++# Useful for very coarse version differentiation.
++PY2 = sys.version_info[0] == 2
++PY3 = sys.version_info[0] == 3
++PY34 = sys.version_info[0:2] >= (3, 4)
++
++if PY3:
++ string_types = str,
++ integer_types = int,
++ class_types = type,
++ text_type = str
++ binary_type = bytes
++
++ MAXSIZE = sys.maxsize
++else:
++ string_types = basestring,
++ integer_types = (int, long)
++ class_types = (type, types.ClassType)
++ text_type = unicode
++ binary_type = str
++
++ if sys.platform.startswith("java"):
++ # Jython always uses 32 bits.
++ MAXSIZE = int((1 << 31) - 1)
++ else:
++ # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
++ class X(object):
++
++ def __len__(self):
++ return 1 << 31
++ try:
++ len(X())
++ except OverflowError:
++ # 32-bit
++ MAXSIZE = int((1 << 31) - 1)
++ else:
++ # 64-bit
++ MAXSIZE = int((1 << 63) - 1)
++ del X
++
++
++def _add_doc(func, doc):
++ """Add documentation to a function."""
++ func.__doc__ = doc
++
++
++def _import_module(name):
++ """Import module, returning the module after the last dot."""
++ __import__(name)
++ return sys.modules[name]
++
++
++class _LazyDescr(object):
++
++ def __init__(self, name):
++ self.name = name
++
++ def __get__(self, obj, tp):
++ result = self._resolve()
++ setattr(obj, self.name, result) # Invokes __set__.
++ try:
++ # This is a bit ugly, but it avoids running this again by
++ # removing this descriptor.
++ delattr(obj.__class__, self.name)
++ except AttributeError:
++ pass
++ return result
++
++
++class MovedModule(_LazyDescr):
++
++ def __init__(self, name, old, new=None):
++ super(MovedModule, self).__init__(name)
++ if PY3:
++ if new is None:
++ new = name
++ self.mod = new
++ else:
++ self.mod = old
++
++ def _resolve(self):
++ return _import_module(self.mod)
++
++ def __getattr__(self, attr):
++ _module = self._resolve()
++ value = getattr(_module, attr)
++ setattr(self, attr, value)
++ return value
++
++
++class _LazyModule(types.ModuleType):
++
++ def __init__(self, name):
++ super(_LazyModule, self).__init__(name)
++ self.__doc__ = self.__class__.__doc__
++
++ def __dir__(self):
++ attrs = ["__doc__", "__name__"]
++ attrs += [attr.name for attr in self._moved_attributes]
++ return attrs
++
++ # Subclasses should override this
++ _moved_attributes = []
++
++
++class MovedAttribute(_LazyDescr):
++
++ def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
++ super(MovedAttribute, self).__init__(name)
++ if PY3:
++ if new_mod is None:
++ new_mod = name
++ self.mod = new_mod
++ if new_attr is None:
++ if old_attr is None:
++ new_attr = name
++ else:
++ new_attr = old_attr
++ self.attr = new_attr
++ else:
++ self.mod = old_mod
++ if old_attr is None:
++ old_attr = name
++ self.attr = old_attr
++
++ def _resolve(self):
++ module = _import_module(self.mod)
++ return getattr(module, self.attr)
++
++
++class _SixMetaPathImporter(object):
++
++ """
++ A meta path importer to import six.moves and its submodules.
++
++ This class implements a PEP302 finder and loader. It should be compatible
++ with Python 2.5 and all existing versions of Python3
++ """
++
++ def __init__(self, six_module_name):
++ self.name = six_module_name
++ self.known_modules = {}
++
++ def _add_module(self, mod, *fullnames):
++ for fullname in fullnames:
++ self.known_modules[self.name + "." + fullname] = mod
++
++ def _get_module(self, fullname):
++ return self.known_modules[self.name + "." + fullname]
++
++ def find_module(self, fullname, path=None):
++ if fullname in self.known_modules:
++ return self
++ return None
++
++ def __get_module(self, fullname):
++ try:
++ return self.known_modules[fullname]
++ except KeyError:
++ raise ImportError("This loader does not know module " + fullname)
++
++ def load_module(self, fullname):
++ try:
++ # in case of a reload
++ return sys.modules[fullname]
++ except KeyError:
++ pass
++ mod = self.__get_module(fullname)
++ if isinstance(mod, MovedModule):
++ mod = mod._resolve()
++ else:
++ mod.__loader__ = self
++ sys.modules[fullname] = mod
++ return mod
++
++ def is_package(self, fullname):
++ """
++ Return true, if the named module is a package.
++
++ We need this method to get correct spec objects with
++ Python 3.4 (see PEP451)
++ """
++ return hasattr(self.__get_module(fullname), "__path__")
++
++ def get_code(self, fullname):
++ """Return None
++
++ Required, if is_package is implemented"""
++ self.__get_module(fullname) # eventually raises ImportError
++ return None
++ get_source = get_code # same as get_code
++
++_importer = _SixMetaPathImporter(__name__)
++
++
++class _MovedItems(_LazyModule):
++
++ """Lazy loading of moved objects"""
++ __path__ = [] # mark as package
++
++
++_moved_attributes = [
++ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
++ MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
++ MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
++ MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
++ MovedAttribute("intern", "__builtin__", "sys"),
++ MovedAttribute("map", "itertools", "builtins", "imap", "map"),
++ MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
++ MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
++ MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
++ MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
++ MovedAttribute("reduce", "__builtin__", "functools"),
++ MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
++ MovedAttribute("StringIO", "StringIO", "io"),
++ MovedAttribute("UserDict", "UserDict", "collections"),
++ MovedAttribute("UserList", "UserList", "collections"),
++ MovedAttribute("UserString", "UserString", "collections"),
++ MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
++ MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
++ MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
++ MovedModule("builtins", "__builtin__"),
++ MovedModule("configparser", "ConfigParser"),
++ MovedModule("copyreg", "copy_reg"),
++ MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
++ MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
++ MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
++ MovedModule("http_cookies", "Cookie", "http.cookies"),
++ MovedModule("html_entities", "htmlentitydefs", "html.entities"),
++ MovedModule("html_parser", "HTMLParser", "html.parser"),
++ MovedModule("http_client", "httplib", "http.client"),
++ MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
++ MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
++ MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
++ MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
++ MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
++ MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
++ MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
++ MovedModule("cPickle", "cPickle", "pickle"),
++ MovedModule("queue", "Queue"),
++ MovedModule("reprlib", "repr"),
++ MovedModule("socketserver", "SocketServer"),
++ MovedModule("_thread", "thread", "_thread"),
++ MovedModule("tkinter", "Tkinter"),
++ MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
++ MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
++ MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
++ MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
++ MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
++ MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
++ MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
++ MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
++ MovedModule("tkinter_colorchooser", "tkColorChooser",
++ "tkinter.colorchooser"),
++ MovedModule("tkinter_commondialog", "tkCommonDialog",
++ "tkinter.commondialog"),
++ MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
++ MovedModule("tkinter_font", "tkFont", "tkinter.font"),
++ MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
++ MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
++ "tkinter.simpledialog"),
++ MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
++ MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
++ MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
++ MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
++ MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
++ MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
++]
++# Add windows specific modules.
++if sys.platform == "win32":
++ _moved_attributes += [
++ MovedModule("winreg", "_winreg"),
++ ]
++
++for attr in _moved_attributes:
++ setattr(_MovedItems, attr.name, attr)
++ if isinstance(attr, MovedModule):
++ _importer._add_module(attr, "moves." + attr.name)
++del attr
++
++_MovedItems._moved_attributes = _moved_attributes
++
++moves = _MovedItems(__name__ + ".moves")
++_importer._add_module(moves, "moves")
++
++
++class Module_six_moves_urllib_parse(_LazyModule):
++
++ """Lazy loading of moved objects in six.moves.urllib_parse"""
++
++
++_urllib_parse_moved_attributes = [
++ MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
++ MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
++ MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
++ MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
++ MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
++ MovedAttribute("urljoin", "urlparse", "urllib.parse"),
++ MovedAttribute("urlparse", "urlparse", "urllib.parse"),
++ MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
++ MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
++ MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
++ MovedAttribute("quote", "urllib", "urllib.parse"),
++ MovedAttribute("quote_plus", "urllib", "urllib.parse"),
++ MovedAttribute("unquote", "urllib", "urllib.parse"),
++ MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
++ MovedAttribute("urlencode", "urllib", "urllib.parse"),
++ MovedAttribute("splitquery", "urllib", "urllib.parse"),
++ MovedAttribute("splittag", "urllib", "urllib.parse"),
++ MovedAttribute("splituser", "urllib", "urllib.parse"),
++ MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
++ MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
++ MovedAttribute("uses_params", "urlparse", "urllib.parse"),
++ MovedAttribute("uses_query", "urlparse", "urllib.parse"),
++ MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
++]
++for attr in _urllib_parse_moved_attributes:
++ setattr(Module_six_moves_urllib_parse, attr.name, attr)
++del attr
++
++Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
++
++_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
++ "moves.urllib_parse", "moves.urllib.parse")
++
++
++class Module_six_moves_urllib_error(_LazyModule):
++
++ """Lazy loading of moved objects in six.moves.urllib_error"""
++
++
++_urllib_error_moved_attributes = [
++ MovedAttribute("URLError", "urllib2", "urllib.error"),
++ MovedAttribute("HTTPError", "urllib2", "urllib.error"),
++ MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
++]
++for attr in _urllib_error_moved_attributes:
++ setattr(Module_six_moves_urllib_error, attr.name, attr)
++del attr
++
++Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
++
++_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
++ "moves.urllib_error", "moves.urllib.error")
++
++
++class Module_six_moves_urllib_request(_LazyModule):
++
++ """Lazy loading of moved objects in six.moves.urllib_request"""
++
++
++_urllib_request_moved_attributes = [
++ MovedAttribute("urlopen", "urllib2", "urllib.request"),
++ MovedAttribute("install_opener", "urllib2", "urllib.request"),
++ MovedAttribute("build_opener", "urllib2", "urllib.request"),
++ MovedAttribute("pathname2url", "urllib", "urllib.request"),
++ MovedAttribute("url2pathname", "urllib", "urllib.request"),
++ MovedAttribute("getproxies", "urllib", "urllib.request"),
++ MovedAttribute("Request", "urllib2", "urllib.request"),
++ MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
++ MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
++ MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
++ MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
++ MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
++ MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
++ MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
++ MovedAttribute("FileHandler", "urllib2", "urllib.request"),
++ MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
++ MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
++ MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
++ MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
++ MovedAttribute("urlretrieve", "urllib", "urllib.request"),
++ MovedAttribute("urlcleanup", "urllib", "urllib.request"),
++ MovedAttribute("URLopener", "urllib", "urllib.request"),
++ MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
++ MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
++]
++for attr in _urllib_request_moved_attributes:
++ setattr(Module_six_moves_urllib_request, attr.name, attr)
++del attr
++
++Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
++
++_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
++ "moves.urllib_request", "moves.urllib.request")
++
++
++class Module_six_moves_urllib_response(_LazyModule):
++
++ """Lazy loading of moved objects in six.moves.urllib_response"""
++
++
++_urllib_response_moved_attributes = [
++ MovedAttribute("addbase", "urllib", "urllib.response"),
++ MovedAttribute("addclosehook", "urllib", "urllib.response"),
++ MovedAttribute("addinfo", "urllib", "urllib.response"),
++ MovedAttribute("addinfourl", "urllib", "urllib.response"),
++]
++for attr in _urllib_response_moved_attributes:
++ setattr(Module_six_moves_urllib_response, attr.name, attr)
++del attr
++
++Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
++
++_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
++ "moves.urllib_response", "moves.urllib.response")
++
++
++class Module_six_moves_urllib_robotparser(_LazyModule):
++
++ """Lazy loading of moved objects in six.moves.urllib_robotparser"""
++
++
++_urllib_robotparser_moved_attributes = [
++ MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
++]
++for attr in _urllib_robotparser_moved_attributes:
++ setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
++del attr
++
++Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
++
++_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
++ "moves.urllib_robotparser", "moves.urllib.robotparser")
++
++
++class Module_six_moves_urllib(types.ModuleType):
++
++ """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
++ __path__ = [] # mark as package
++ parse = _importer._get_module("moves.urllib_parse")
++ error = _importer._get_module("moves.urllib_error")
++ request = _importer._get_module("moves.urllib_request")
++ response = _importer._get_module("moves.urllib_response")
++ robotparser = _importer._get_module("moves.urllib_robotparser")
++
++ def __dir__(self):
++ return ['parse', 'error', 'request', 'response', 'robotparser']
++
++_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
++ "moves.urllib")
++
++
++def add_move(move):
++ """Add an item to six.moves."""
++ setattr(_MovedItems, move.name, move)
++
++
++def remove_move(name):
++ """Remove item from six.moves."""
++ try:
++ delattr(_MovedItems, name)
++ except AttributeError:
++ try:
++ del moves.__dict__[name]
++ except KeyError:
++ raise AttributeError("no such move, %r" % (name,))
++
++
++if PY3:
++ _meth_func = "__func__"
++ _meth_self = "__self__"
++
++ _func_closure = "__closure__"
++ _func_code = "__code__"
++ _func_defaults = "__defaults__"
++ _func_globals = "__globals__"
++else:
++ _meth_func = "im_func"
++ _meth_self = "im_self"
++
++ _func_closure = "func_closure"
++ _func_code = "func_code"
++ _func_defaults = "func_defaults"
++ _func_globals = "func_globals"
++
++
++try:
++ advance_iterator = next
++except NameError:
++ def advance_iterator(it):
++ return it.next()
++next = advance_iterator
++
++
++try:
++ callable = callable
++except NameError:
++ def callable(obj):
++ return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
++
++
++if PY3:
++ def get_unbound_function(unbound):
++ return unbound
++
++ create_bound_method = types.MethodType
++
++ def create_unbound_method(func, cls):
++ return func
++
++ Iterator = object
++else:
++ def get_unbound_function(unbound):
++ return unbound.im_func
++
++ def create_bound_method(func, obj):
++ return types.MethodType(func, obj, obj.__class__)
++
++ def create_unbound_method(func, cls):
++ return types.MethodType(func, None, cls)
++
++ class Iterator(object):
++
++ def next(self):
++ return type(self).__next__(self)
++
++ callable = callable
++_add_doc(get_unbound_function,
++ """Get the function out of a possibly unbound function""")
++
++
++get_method_function = operator.attrgetter(_meth_func)
++get_method_self = operator.attrgetter(_meth_self)
++get_function_closure = operator.attrgetter(_func_closure)
++get_function_code = operator.attrgetter(_func_code)
++get_function_defaults = operator.attrgetter(_func_defaults)
++get_function_globals = operator.attrgetter(_func_globals)
++
++
++if PY3:
++ def iterkeys(d, **kw):
++ return iter(d.keys(**kw))
++
++ def itervalues(d, **kw):
++ return iter(d.values(**kw))
++
++ def iteritems(d, **kw):
++ return iter(d.items(**kw))
++
++ def iterlists(d, **kw):
++ return iter(d.lists(**kw))
++
++ viewkeys = operator.methodcaller("keys")
++
++ viewvalues = operator.methodcaller("values")
++
++ viewitems = operator.methodcaller("items")
++else:
++ def iterkeys(d, **kw):
++ return d.iterkeys(**kw)
++
++ def itervalues(d, **kw):
++ return d.itervalues(**kw)
++
++ def iteritems(d, **kw):
++ return d.iteritems(**kw)
++
++ def iterlists(d, **kw):
++ return d.iterlists(**kw)
++
++ viewkeys = operator.methodcaller("viewkeys")
++
++ viewvalues = operator.methodcaller("viewvalues")
++
++ viewitems = operator.methodcaller("viewitems")
++
++_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
++_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
++_add_doc(iteritems,
++ "Return an iterator over the (key, value) pairs of a dictionary.")
++_add_doc(iterlists,
++ "Return an iterator over the (key, [values]) pairs of a dictionary.")
++
++
++if PY3:
++ def b(s):
++ return s.encode("latin-1")
++
++ def u(s):
++ return s
++ unichr = chr
++ import struct
++ int2byte = struct.Struct(">B").pack
++ del struct
++ byte2int = operator.itemgetter(0)
++ indexbytes = operator.getitem
++ iterbytes = iter
++ import io
++ StringIO = io.StringIO
++ BytesIO = io.BytesIO
++ _assertCountEqual = "assertCountEqual"
++ if sys.version_info[1] <= 1:
++ _assertRaisesRegex = "assertRaisesRegexp"
++ _assertRegex = "assertRegexpMatches"
++ else:
++ _assertRaisesRegex = "assertRaisesRegex"
++ _assertRegex = "assertRegex"
++else:
++ def b(s):
++ return s
++ # Workaround for standalone backslash
++
++ def u(s):
++ return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
++ unichr = unichr
++ int2byte = chr
++
++ def byte2int(bs):
++ return ord(bs[0])
++
++ def indexbytes(buf, i):
++ return ord(buf[i])
++ iterbytes = functools.partial(itertools.imap, ord)
++ import StringIO
++ StringIO = BytesIO = StringIO.StringIO
++ _assertCountEqual = "assertItemsEqual"
++ _assertRaisesRegex = "assertRaisesRegexp"
++ _assertRegex = "assertRegexpMatches"
++_add_doc(b, """Byte literal""")
++_add_doc(u, """Text literal""")
++
++
++def assertCountEqual(self, *args, **kwargs):
++ return getattr(self, _assertCountEqual)(*args, **kwargs)
++
++
++def assertRaisesRegex(self, *args, **kwargs):
++ return getattr(self, _assertRaisesRegex)(*args, **kwargs)
++
++
++def assertRegex(self, *args, **kwargs):
++ return getattr(self, _assertRegex)(*args, **kwargs)
++
++
++if PY3:
++ exec_ = getattr(moves.builtins, "exec")
++
++ def reraise(tp, value, tb=None):
++ if value is None:
++ value = tp()
++ if value.__traceback__ is not tb:
++ raise value.with_traceback(tb)
++ raise value
++
++else:
++ def exec_(_code_, _globs_=None, _locs_=None):
++ """Execute code in a namespace."""
++ if _globs_ is None:
++ frame = sys._getframe(1)
++ _globs_ = frame.f_globals
++ if _locs_ is None:
++ _locs_ = frame.f_locals
++ del frame
++ elif _locs_ is None:
++ _locs_ = _globs_
++ exec("""exec _code_ in _globs_, _locs_""")
++
++ exec_("""def reraise(tp, value, tb=None):
++ raise tp, value, tb
++""")
++
++
++if sys.version_info[:2] == (3, 2):
++ exec_("""def raise_from(value, from_value):
++ if from_value is None:
++ raise value
++ raise value from from_value
++""")
++elif sys.version_info[:2] > (3, 2):
++ exec_("""def raise_from(value, from_value):
++ raise value from from_value
++""")
++else:
++ def raise_from(value, from_value):
++ raise value
++
++
++print_ = getattr(moves.builtins, "print", None)
++if print_ is None:
++ def print_(*args, **kwargs):
++ """The new-style print function for Python 2.4 and 2.5."""
++ fp = kwargs.pop("file", sys.stdout)
++ if fp is None:
++ return
++
++ def write(data):
++ if not isinstance(data, basestring):
++ data = str(data)
++ # If the file has an encoding, encode unicode with it.
++ if (isinstance(fp, file) and
++ isinstance(data, unicode) and
++ fp.encoding is not None):
++ errors = getattr(fp, "errors", None)
++ if errors is None:
++ errors = "strict"
++ data = data.encode(fp.encoding, errors)
++ fp.write(data)
++ want_unicode = False
++ sep = kwargs.pop("sep", None)
++ if sep is not None:
++ if isinstance(sep, unicode):
++ want_unicode = True
++ elif not isinstance(sep, str):
++ raise TypeError("sep must be None or a string")
++ end = kwargs.pop("end", None)
++ if end is not None:
++ if isinstance(end, unicode):
++ want_unicode = True
++ elif not isinstance(end, str):
++ raise TypeError("end must be None or a string")
++ if kwargs:
++ raise TypeError("invalid keyword arguments to print()")
++ if not want_unicode:
++ for arg in args:
++ if isinstance(arg, unicode):
++ want_unicode = True
++ break
++ if want_unicode:
++ newline = unicode("\n")
++ space = unicode(" ")
++ else:
++ newline = "\n"
++ space = " "
++ if sep is None:
++ sep = space
++ if end is None:
++ end = newline
++ for i, arg in enumerate(args):
++ if i:
++ write(sep)
++ write(arg)
++ write(end)
++if sys.version_info[:2] < (3, 3):
++ _print = print_
++
++ def print_(*args, **kwargs):
++ fp = kwargs.get("file", sys.stdout)
++ flush = kwargs.pop("flush", False)
++ _print(*args, **kwargs)
++ if flush and fp is not None:
++ fp.flush()
++
++_add_doc(reraise, """Reraise an exception.""")
++
++if sys.version_info[0:2] < (3, 4):
++ def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
++ updated=functools.WRAPPER_UPDATES):
++ def wrapper(f):
++ f = functools.wraps(wrapped, assigned, updated)(f)
++ f.__wrapped__ = wrapped
++ return f
++ return wrapper
++else:
++ wraps = functools.wraps
++
++
++def with_metaclass(meta, *bases):
++ """Create a base class with a metaclass."""
++ # This requires a bit of explanation: the basic idea is to make a dummy
++ # metaclass for one level of class instantiation that replaces itself with
++ # the actual metaclass.
++ class metaclass(meta):
++
++ def __new__(cls, name, this_bases, d):
++ return meta(name, bases, d)
++ return type.__new__(metaclass, 'temporary_class', (), {})
++
++
++def add_metaclass(metaclass):
++ """Class decorator for creating a class with a metaclass."""
++ def wrapper(cls):
++ orig_vars = cls.__dict__.copy()
++ slots = orig_vars.get('__slots__')
++ if slots is not None:
++ if isinstance(slots, str):
++ slots = [slots]
++ for slots_var in slots:
++ orig_vars.pop(slots_var)
++ orig_vars.pop('__dict__', None)
++ orig_vars.pop('__weakref__', None)
++ return metaclass(cls.__name__, cls.__bases__, orig_vars)
++ return wrapper
++
++
++def python_2_unicode_compatible(klass):
++ """
++ A decorator that defines __unicode__ and __str__ methods under Python 2.
++ Under Python 3 it does nothing.
++
++ To support Python 2 and 3 with a single code base, define a __str__ method
++ returning text and apply this decorator to the class.
++ """
++ if PY2:
++ if '__str__' not in klass.__dict__:
++ raise ValueError("@python_2_unicode_compatible cannot be applied "
++ "to %s because it doesn't define __str__()." %
++ klass.__name__)
++ klass.__unicode__ = klass.__str__
++ klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
++ return klass
++
++
++# Complete the moves implementation.
++# This code is at the end of this module to speed up module loading.
++# Turn this module into a package.
++__path__ = [] # required for PEP 302 and PEP 451
++__package__ = __name__ # see PEP 366 @ReservedAssignment
++if globals().get("__spec__") is not None:
++ __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
++# Remove other six meta path importers, since they cause problems. This can
++# happen if six is removed from sys.modules and then reloaded. (Setuptools does
++# this for some reason.)
++if sys.meta_path:
++ for i, importer in enumerate(sys.meta_path):
++ # Here's some real nastiness: Another "instance" of the six module might
++ # be floating around. Therefore, we can't use isinstance() to check for
++ # the six meta path importer, since the other six instance will have
++ # inserted an importer with different class.
++ if (type(importer).__name__ == "_SixMetaPathImporter" and
++ importer.name == __name__):
++ del sys.meta_path[i]
++ break
++ del i, importer
++# Finally, add the importer to the meta path import hook.
++sys.meta_path.append(_importer)
diff --git a/third_party/libwebrtc/moz-patch-stack/0097.patch b/third_party/libwebrtc/moz-patch-stack/0097.patch
index 1faafdf8cf..dc3cc7ca1a 100644
--- a/third_party/libwebrtc/moz-patch-stack/0097.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0097.patch
@@ -1,35362 +1,20 @@
-From: Nico Grunbaum <na-g@nostrum.com>
-Date: Fri, 30 Apr 2021 21:51:00 +0000
-Subject: Bug 1654112 - Add grit dep for building webrtc on android; r=mjf
+From: Michael Froman <mfroman@mozilla.com>
+Date: Wed, 7 Dec 2022 17:09:00 +0000
+Subject: Bug 1744645 - pt1 - add a couple empty gni files to help with
+ BUILD.gn corrections. r=ng
-Differential Revision: https://phabricator.services.mozilla.com/D114027
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/3cce5e6938f0df87bd9ab12a5f556aceb93dfa1d
+Differential Revision: https://phabricator.services.mozilla.com/D163991
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/81d86382ee468f3b36deed00d0c9d59eb85524be
---
- tools/grit/.gitignore | 1 +
- tools/grit/BUILD.gn | 48 +
- tools/grit/MANIFEST.in | 3 +
- tools/grit/OWNERS | 8 +
- tools/grit/PRESUBMIT.py | 22 +
- tools/grit/README.md | 19 +
- tools/grit/grit.py | 31 +
- tools/grit/grit/__init__.py | 19 +
- tools/grit/grit/clique.py | 491 +++
- tools/grit/grit/clique_unittest.py | 265 ++
- tools/grit/grit/constants.py | 23 +
- tools/grit/grit/exception.py | 139 +
- tools/grit/grit/extern/BogoFP.py | 22 +
- tools/grit/grit/extern/FP.py | 72 +
- tools/grit/grit/extern/__init__.py | 0
- tools/grit/grit/extern/tclib.py | 503 +++
- tools/grit/grit/format/__init__.py | 8 +
- tools/grit/grit/format/android_xml.py | 212 ++
- .../grit/grit/format/android_xml_unittest.py | 149 +
- tools/grit/grit/format/c_format.py | 95 +
- tools/grit/grit/format/c_format_unittest.py | 81 +
- .../grit/grit/format/chrome_messages_json.py | 59 +
- .../format/chrome_messages_json_unittest.py | 190 +
- tools/grit/grit/format/data_pack.py | 321 ++
- tools/grit/grit/format/data_pack_unittest.py | 102 +
- .../grit/grit/format/gen_predetermined_ids.py | 144 +
- .../format/gen_predetermined_ids_unittest.py | 46 +
- tools/grit/grit/format/gzip_string.py | 46 +
- .../grit/grit/format/gzip_string_unittest.py | 65 +
- tools/grit/grit/format/html_inline.py | 602 ++++
- .../grit/grit/format/html_inline_unittest.py | 927 +++++
- tools/grit/grit/format/minifier.py | 45 +
- .../grit/grit/format/policy_templates_json.py | 26 +
- .../format/policy_templates_json_unittest.py | 207 ++
- tools/grit/grit/format/rc.py | 474 +++
- tools/grit/grit/format/rc_header.py | 48 +
- tools/grit/grit/format/rc_header_unittest.py | 138 +
- tools/grit/grit/format/rc_unittest.py | 415 +++
- tools/grit/grit/format/resource_map.py | 159 +
- .../grit/grit/format/resource_map_unittest.py | 345 ++
- tools/grit/grit/gather/__init__.py | 8 +
- tools/grit/grit/gather/admin_template.py | 62 +
- .../grit/gather/admin_template_unittest.py | 115 +
- tools/grit/grit/gather/chrome_html.py | 377 ++
- .../grit/grit/gather/chrome_html_unittest.py | 610 ++++
- tools/grit/grit/gather/chrome_scaled_image.py | 157 +
- .../gather/chrome_scaled_image_unittest.py | 209 ++
- tools/grit/grit/gather/interface.py | 172 +
- tools/grit/grit/gather/json_loader.py | 27 +
- tools/grit/grit/gather/policy_json.py | 325 ++
- .../grit/grit/gather/policy_json_unittest.py | 347 ++
- tools/grit/grit/gather/rc.py | 343 ++
- tools/grit/grit/gather/rc_unittest.py | 372 ++
- tools/grit/grit/gather/regexp.py | 82 +
- tools/grit/grit/gather/skeleton_gatherer.py | 149 +
- tools/grit/grit/gather/tr_html.py | 743 ++++
- tools/grit/grit/gather/tr_html_unittest.py | 524 +++
- tools/grit/grit/gather/txt.py | 38 +
- tools/grit/grit/gather/txt_unittest.py | 35 +
- tools/grit/grit/grd_reader.py | 238 ++
- tools/grit/grit/grd_reader_unittest.py | 346 ++
- tools/grit/grit/grit-todo.xml | 62 +
- tools/grit/grit/grit_runner.py | 334 ++
- tools/grit/grit/grit_runner_unittest.py | 42 +
- tools/grit/grit/lazy_re.py | 46 +
- tools/grit/grit/lazy_re_unittest.py | 40 +
- tools/grit/grit/node/__init__.py | 8 +
- tools/grit/grit/node/base.py | 670 ++++
- tools/grit/grit/node/base_unittest.py | 259 ++
- tools/grit/grit/node/brotli_util.py | 29 +
- tools/grit/grit/node/custom/__init__.py | 8 +
- tools/grit/grit/node/custom/filename.py | 29 +
- .../grit/node/custom/filename_unittest.py | 34 +
- tools/grit/grit/node/empty.py | 64 +
- tools/grit/grit/node/include.py | 170 +
- tools/grit/grit/node/include_unittest.py | 134 +
- tools/grit/grit/node/mapping.py | 60 +
- tools/grit/grit/node/message.py | 362 ++
- tools/grit/grit/node/message_unittest.py | 380 ++
- tools/grit/grit/node/misc.py | 707 ++++
- tools/grit/grit/node/misc_unittest.py | 590 ++++
- tools/grit/grit/node/mock_brotli.py | 10 +
- tools/grit/grit/node/node_io.py | 117 +
- tools/grit/grit/node/node_io_unittest.py | 182 +
- tools/grit/grit/node/structure.py | 375 ++
- tools/grit/grit/node/structure_unittest.py | 178 +
- tools/grit/grit/node/variant.py | 41 +
- tools/grit/grit/pseudo.py | 129 +
- tools/grit/grit/pseudo_rtl.py | 104 +
- tools/grit/grit/pseudo_unittest.py | 55 +
- tools/grit/grit/shortcuts.py | 93 +
- tools/grit/grit/shortcuts_unittest.py | 79 +
- tools/grit/grit/tclib.py | 246 ++
- tools/grit/grit/tclib_unittest.py | 180 +
- tools/grit/grit/test_suite_all.py | 34 +
- tools/grit/grit/testdata/GoogleDesktop.adm | 945 +++++
- tools/grit/grit/testdata/README.txt | 87 +
- tools/grit/grit/testdata/about.html | 45 +
- tools/grit/grit/testdata/android.xml | 24 +
- tools/grit/grit/testdata/bad_browser.html | 16 +
- tools/grit/grit/testdata/browser.html | 42 +
- tools/grit/grit/testdata/buildinfo.grd | 46 +
- tools/grit/grit/testdata/cache_prefix.html | 24 +
- .../grit/grit/testdata/cache_prefix_file.html | 25 +
- tools/grit/grit/testdata/chat_result.html | 24 +
- .../chrome/app/generated_resources.grd | 199 ++
- tools/grit/grit/testdata/chrome_html.html | 6 +
- .../grit/testdata/default_100_percent/a.png | Bin 0 -> 159 bytes
- .../grit/testdata/default_100_percent/b.png | 1 +
- tools/grit/grit/testdata/del_footer.html | 8 +
- tools/grit/grit/testdata/del_header.html | 60 +
- tools/grit/grit/testdata/deleted.html | 21 +
- tools/grit/grit/testdata/depfile.grd | 18 +
- tools/grit/grit/testdata/details.html | 10 +
- .../grit/testdata/duplicate-name-input.xml | 26 +
- tools/grit/grit/testdata/email_result.html | 34 +
- tools/grit/grit/testdata/email_thread.html | 10 +
- tools/grit/grit/testdata/error.html | 8 +
- tools/grit/grit/testdata/explicit_web.html | 11 +
- tools/grit/grit/testdata/footer.html | 14 +
- .../grit/testdata/generated_resources_fr.xtb | 3079 +++++++++++++++++
- .../grit/testdata/generated_resources_iw.xtb | 4 +
- .../grit/testdata/generated_resources_no.xtb | 4 +
- tools/grit/grit/testdata/grit_part.grdp | 5 +
- tools/grit/grit/testdata/header.html | 39 +
- tools/grit/grit/testdata/homepage.html | 37 +
- tools/grit/grit/testdata/hover.html | 177 +
- tools/grit/grit/testdata/include_test.html | 31 +
- tools/grit/grit/testdata/included_sample.html | 1 +
- tools/grit/grit/testdata/indexing_speed.html | 58 +
- tools/grit/grit/testdata/install_prefs.html | 92 +
- tools/grit/grit/testdata/install_prefs2.html | 52 +
- .../grit/testdata/klonk-alternate-skeleton.rc | Bin 0 -> 1088 bytes
- tools/grit/grit/testdata/klonk.ico | Bin 0 -> 766 bytes
- tools/grit/grit/testdata/klonk.rc | Bin 0 -> 9824 bytes
- .../grit/grit/testdata/ko_oem_enable_bug.html | 1 +
- .../grit/testdata/ko_oem_non_admin_bug.html | 1 +
- tools/grit/grit/testdata/mini.html | 36 +
- tools/grit/grit/testdata/oem_enable.html | 106 +
- tools/grit/grit/testdata/oem_non_admin.html | 39 +
- tools/grit/grit/testdata/onebox.html | 21 +
- tools/grit/grit/testdata/oneclick.html | 34 +
- tools/grit/grit/testdata/password.html | 37 +
- tools/grit/grit/testdata/preferences.html | 234 ++
- tools/grit/grit/testdata/preprocess_test.html | 7 +
- tools/grit/grit/testdata/privacy.html | 35 +
- tools/grit/grit/testdata/quit_apps.html | 49 +
- tools/grit/grit/testdata/recrawl.html | 30 +
- tools/grit/grit/testdata/resource_ids | 13 +
- tools/grit/grit/testdata/script.html | 38 +
- tools/grit/grit/testdata/searchbox.html | 22 +
- tools/grit/grit/testdata/sidebar_h.html | 82 +
- tools/grit/grit/testdata/sidebar_v.html | 267 ++
- tools/grit/grit/testdata/simple-input.xml | 52 +
- tools/grit/grit/testdata/simple.html | 3 +
- tools/grit/grit/testdata/source.rc | 57 +
- .../grit/testdata/special_100_percent/a.png | Bin 0 -> 159 bytes
- tools/grit/grit/testdata/status.html | 44 +
- .../grit/testdata/structure_variables.html | 4 +
- tools/grit/grit/testdata/substitute.grd | 31 +
- tools/grit/grit/testdata/substitute.xmb | 10 +
- .../grit/grit/testdata/substitute_no_ids.grd | 31 +
- tools/grit/grit/testdata/substitute_tmpl.grd | 31 +
- tools/grit/grit/testdata/test_css.css | 1 +
- tools/grit/grit/testdata/test_html.html | 1 +
- tools/grit/grit/testdata/test_js.js | 1 +
- tools/grit/grit/testdata/test_svg.svg | 1 +
- tools/grit/grit/testdata/test_text.txt | 1 +
- tools/grit/grit/testdata/time_related.html | 11 +
- tools/grit/grit/testdata/toolbar_about.html | 138 +
- .../grit/testdata/tools/grit/resource_ids | 176 +
- tools/grit/grit/testdata/transl.rc | 56 +
- tools/grit/grit/testdata/versions.html | 7 +
- tools/grit/grit/testdata/whitelist.txt | 4 +
- .../grit/testdata/whitelist_resources.grd | 54 +
- .../grit/grit/testdata/whitelist_strings.grd | 23 +
- tools/grit/grit/tool/__init__.py | 8 +
- tools/grit/grit/tool/android2grd.py | 484 +++
- tools/grit/grit/tool/android2grd_unittest.py | 181 +
- tools/grit/grit/tool/build.py | 556 +++
- tools/grit/grit/tool/build_unittest.py | 341 ++
- tools/grit/grit/tool/buildinfo.py | 78 +
- tools/grit/grit/tool/buildinfo_unittest.py | 90 +
- tools/grit/grit/tool/count.py | 52 +
- tools/grit/grit/tool/diff_structures.py | 119 +
- .../grit/tool/diff_structures_unittest.py | 46 +
- tools/grit/grit/tool/interface.py | 62 +
- tools/grit/grit/tool/menu_from_parts.py | 79 +
- tools/grit/grit/tool/newgrd.py | 85 +
- tools/grit/grit/tool/newgrd_unittest.py | 51 +
- tools/grit/grit/tool/postprocess_interface.py | 29 +
- tools/grit/grit/tool/postprocess_unittest.py | 64 +
- tools/grit/grit/tool/preprocess_interface.py | 25 +
- tools/grit/grit/tool/preprocess_unittest.py | 50 +
- tools/grit/grit/tool/rc2grd.py | 418 +++
- tools/grit/grit/tool/rc2grd_unittest.py | 163 +
- tools/grit/grit/tool/resize.py | 295 ++
- tools/grit/grit/tool/test.py | 24 +
- tools/grit/grit/tool/transl2tc.py | 251 ++
- tools/grit/grit/tool/transl2tc_unittest.py | 133 +
- tools/grit/grit/tool/unit.py | 43 +
- .../grit/tool/update_resource_ids/__init__.py | 305 ++
- .../grit/tool/update_resource_ids/assigner.py | 286 ++
- .../update_resource_ids/assigner_unittest.py | 154 +
- .../grit/tool/update_resource_ids/common.py | 101 +
- .../grit/tool/update_resource_ids/parser.py | 231 ++
- .../grit/tool/update_resource_ids/reader.py | 83 +
- tools/grit/grit/tool/xmb.py | 295 ++
- tools/grit/grit/tool/xmb_unittest.py | 132 +
- tools/grit/grit/util.py | 691 ++++
- tools/grit/grit/util_unittest.py | 118 +
- tools/grit/grit/xtb_reader.py | 140 +
- tools/grit/grit/xtb_reader_unittest.py | 110 +
- tools/grit/grit_info.py | 173 +
- tools/grit/grit_rule.gni | 485 +++
- tools/grit/minify_with_uglify.py | 44 +
- tools/grit/minimize_css.py | 105 +
- tools/grit/minimize_css_unittest.py | 58 +
- tools/grit/pak_util.py | 223 ++
- tools/grit/repack.gni | 189 +
- tools/grit/setup.py | 46 +
- tools/grit/stamp_grit_sources.py | 57 +
- tools/grit/third_party/six/LICENSE | 18 +
- tools/grit/third_party/six/README | 16 +
- tools/grit/third_party/six/README.chromium | 13 +
- tools/grit/third_party/six/__init__.py | 868 +++++
- 226 files changed, 33440 insertions(+)
- create mode 100644 tools/grit/.gitignore
- create mode 100644 tools/grit/BUILD.gn
- create mode 100644 tools/grit/MANIFEST.in
- create mode 100644 tools/grit/OWNERS
- create mode 100644 tools/grit/PRESUBMIT.py
- create mode 100644 tools/grit/README.md
- create mode 100644 tools/grit/grit.py
- create mode 100644 tools/grit/grit/__init__.py
- create mode 100644 tools/grit/grit/clique.py
- create mode 100644 tools/grit/grit/clique_unittest.py
- create mode 100644 tools/grit/grit/constants.py
- create mode 100644 tools/grit/grit/exception.py
- create mode 100644 tools/grit/grit/extern/BogoFP.py
- create mode 100644 tools/grit/grit/extern/FP.py
- create mode 100644 tools/grit/grit/extern/__init__.py
- create mode 100644 tools/grit/grit/extern/tclib.py
- create mode 100644 tools/grit/grit/format/__init__.py
- create mode 100644 tools/grit/grit/format/android_xml.py
- create mode 100644 tools/grit/grit/format/android_xml_unittest.py
- create mode 100644 tools/grit/grit/format/c_format.py
- create mode 100644 tools/grit/grit/format/c_format_unittest.py
- create mode 100644 tools/grit/grit/format/chrome_messages_json.py
- create mode 100644 tools/grit/grit/format/chrome_messages_json_unittest.py
- create mode 100644 tools/grit/grit/format/data_pack.py
- create mode 100644 tools/grit/grit/format/data_pack_unittest.py
- create mode 100644 tools/grit/grit/format/gen_predetermined_ids.py
- create mode 100644 tools/grit/grit/format/gen_predetermined_ids_unittest.py
- create mode 100644 tools/grit/grit/format/gzip_string.py
- create mode 100644 tools/grit/grit/format/gzip_string_unittest.py
- create mode 100644 tools/grit/grit/format/html_inline.py
- create mode 100644 tools/grit/grit/format/html_inline_unittest.py
- create mode 100644 tools/grit/grit/format/minifier.py
- create mode 100644 tools/grit/grit/format/policy_templates_json.py
- create mode 100644 tools/grit/grit/format/policy_templates_json_unittest.py
- create mode 100644 tools/grit/grit/format/rc.py
- create mode 100644 tools/grit/grit/format/rc_header.py
- create mode 100644 tools/grit/grit/format/rc_header_unittest.py
- create mode 100644 tools/grit/grit/format/rc_unittest.py
- create mode 100644 tools/grit/grit/format/resource_map.py
- create mode 100644 tools/grit/grit/format/resource_map_unittest.py
- create mode 100644 tools/grit/grit/gather/__init__.py
- create mode 100644 tools/grit/grit/gather/admin_template.py
- create mode 100644 tools/grit/grit/gather/admin_template_unittest.py
- create mode 100644 tools/grit/grit/gather/chrome_html.py
- create mode 100644 tools/grit/grit/gather/chrome_html_unittest.py
- create mode 100644 tools/grit/grit/gather/chrome_scaled_image.py
- create mode 100644 tools/grit/grit/gather/chrome_scaled_image_unittest.py
- create mode 100644 tools/grit/grit/gather/interface.py
- create mode 100644 tools/grit/grit/gather/json_loader.py
- create mode 100644 tools/grit/grit/gather/policy_json.py
- create mode 100644 tools/grit/grit/gather/policy_json_unittest.py
- create mode 100644 tools/grit/grit/gather/rc.py
- create mode 100644 tools/grit/grit/gather/rc_unittest.py
- create mode 100644 tools/grit/grit/gather/regexp.py
- create mode 100644 tools/grit/grit/gather/skeleton_gatherer.py
- create mode 100644 tools/grit/grit/gather/tr_html.py
- create mode 100644 tools/grit/grit/gather/tr_html_unittest.py
- create mode 100644 tools/grit/grit/gather/txt.py
- create mode 100644 tools/grit/grit/gather/txt_unittest.py
- create mode 100644 tools/grit/grit/grd_reader.py
- create mode 100644 tools/grit/grit/grd_reader_unittest.py
- create mode 100644 tools/grit/grit/grit-todo.xml
- create mode 100644 tools/grit/grit/grit_runner.py
- create mode 100644 tools/grit/grit/grit_runner_unittest.py
- create mode 100644 tools/grit/grit/lazy_re.py
- create mode 100644 tools/grit/grit/lazy_re_unittest.py
- create mode 100644 tools/grit/grit/node/__init__.py
- create mode 100644 tools/grit/grit/node/base.py
- create mode 100644 tools/grit/grit/node/base_unittest.py
- create mode 100644 tools/grit/grit/node/brotli_util.py
- create mode 100644 tools/grit/grit/node/custom/__init__.py
- create mode 100644 tools/grit/grit/node/custom/filename.py
- create mode 100644 tools/grit/grit/node/custom/filename_unittest.py
- create mode 100644 tools/grit/grit/node/empty.py
- create mode 100644 tools/grit/grit/node/include.py
- create mode 100644 tools/grit/grit/node/include_unittest.py
- create mode 100644 tools/grit/grit/node/mapping.py
- create mode 100644 tools/grit/grit/node/message.py
- create mode 100644 tools/grit/grit/node/message_unittest.py
- create mode 100644 tools/grit/grit/node/misc.py
- create mode 100644 tools/grit/grit/node/misc_unittest.py
- create mode 100644 tools/grit/grit/node/mock_brotli.py
- create mode 100644 tools/grit/grit/node/node_io.py
- create mode 100644 tools/grit/grit/node/node_io_unittest.py
- create mode 100644 tools/grit/grit/node/structure.py
- create mode 100644 tools/grit/grit/node/structure_unittest.py
- create mode 100644 tools/grit/grit/node/variant.py
- create mode 100644 tools/grit/grit/pseudo.py
- create mode 100644 tools/grit/grit/pseudo_rtl.py
- create mode 100644 tools/grit/grit/pseudo_unittest.py
- create mode 100644 tools/grit/grit/shortcuts.py
- create mode 100644 tools/grit/grit/shortcuts_unittest.py
- create mode 100644 tools/grit/grit/tclib.py
- create mode 100644 tools/grit/grit/tclib_unittest.py
- create mode 100644 tools/grit/grit/test_suite_all.py
- create mode 100644 tools/grit/grit/testdata/GoogleDesktop.adm
- create mode 100644 tools/grit/grit/testdata/README.txt
- create mode 100644 tools/grit/grit/testdata/about.html
- create mode 100644 tools/grit/grit/testdata/android.xml
- create mode 100644 tools/grit/grit/testdata/bad_browser.html
- create mode 100644 tools/grit/grit/testdata/browser.html
- create mode 100644 tools/grit/grit/testdata/buildinfo.grd
- create mode 100644 tools/grit/grit/testdata/cache_prefix.html
- create mode 100644 tools/grit/grit/testdata/cache_prefix_file.html
- create mode 100644 tools/grit/grit/testdata/chat_result.html
- create mode 100644 tools/grit/grit/testdata/chrome/app/generated_resources.grd
- create mode 100644 tools/grit/grit/testdata/chrome_html.html
- create mode 100644 tools/grit/grit/testdata/default_100_percent/a.png
- create mode 100644 tools/grit/grit/testdata/default_100_percent/b.png
- create mode 100644 tools/grit/grit/testdata/del_footer.html
- create mode 100644 tools/grit/grit/testdata/del_header.html
- create mode 100644 tools/grit/grit/testdata/deleted.html
- create mode 100644 tools/grit/grit/testdata/depfile.grd
- create mode 100644 tools/grit/grit/testdata/details.html
- create mode 100644 tools/grit/grit/testdata/duplicate-name-input.xml
- create mode 100644 tools/grit/grit/testdata/email_result.html
- create mode 100644 tools/grit/grit/testdata/email_thread.html
- create mode 100644 tools/grit/grit/testdata/error.html
- create mode 100644 tools/grit/grit/testdata/explicit_web.html
- create mode 100644 tools/grit/grit/testdata/footer.html
- create mode 100644 tools/grit/grit/testdata/generated_resources_fr.xtb
- create mode 100644 tools/grit/grit/testdata/generated_resources_iw.xtb
- create mode 100644 tools/grit/grit/testdata/generated_resources_no.xtb
- create mode 100644 tools/grit/grit/testdata/grit_part.grdp
- create mode 100644 tools/grit/grit/testdata/header.html
- create mode 100644 tools/grit/grit/testdata/homepage.html
- create mode 100644 tools/grit/grit/testdata/hover.html
- create mode 100644 tools/grit/grit/testdata/include_test.html
- create mode 100644 tools/grit/grit/testdata/included_sample.html
- create mode 100644 tools/grit/grit/testdata/indexing_speed.html
- create mode 100644 tools/grit/grit/testdata/install_prefs.html
- create mode 100644 tools/grit/grit/testdata/install_prefs2.html
- create mode 100644 tools/grit/grit/testdata/klonk-alternate-skeleton.rc
- create mode 100644 tools/grit/grit/testdata/klonk.ico
- create mode 100644 tools/grit/grit/testdata/klonk.rc
- create mode 100644 tools/grit/grit/testdata/ko_oem_enable_bug.html
- create mode 100644 tools/grit/grit/testdata/ko_oem_non_admin_bug.html
- create mode 100644 tools/grit/grit/testdata/mini.html
- create mode 100644 tools/grit/grit/testdata/oem_enable.html
- create mode 100644 tools/grit/grit/testdata/oem_non_admin.html
- create mode 100644 tools/grit/grit/testdata/onebox.html
- create mode 100644 tools/grit/grit/testdata/oneclick.html
- create mode 100644 tools/grit/grit/testdata/password.html
- create mode 100644 tools/grit/grit/testdata/preferences.html
- create mode 100644 tools/grit/grit/testdata/preprocess_test.html
- create mode 100644 tools/grit/grit/testdata/privacy.html
- create mode 100644 tools/grit/grit/testdata/quit_apps.html
- create mode 100644 tools/grit/grit/testdata/recrawl.html
- create mode 100644 tools/grit/grit/testdata/resource_ids
- create mode 100644 tools/grit/grit/testdata/script.html
- create mode 100644 tools/grit/grit/testdata/searchbox.html
- create mode 100644 tools/grit/grit/testdata/sidebar_h.html
- create mode 100644 tools/grit/grit/testdata/sidebar_v.html
- create mode 100644 tools/grit/grit/testdata/simple-input.xml
- create mode 100644 tools/grit/grit/testdata/simple.html
- create mode 100644 tools/grit/grit/testdata/source.rc
- create mode 100644 tools/grit/grit/testdata/special_100_percent/a.png
- create mode 100644 tools/grit/grit/testdata/status.html
- create mode 100644 tools/grit/grit/testdata/structure_variables.html
- create mode 100644 tools/grit/grit/testdata/substitute.grd
- create mode 100644 tools/grit/grit/testdata/substitute.xmb
- create mode 100644 tools/grit/grit/testdata/substitute_no_ids.grd
- create mode 100644 tools/grit/grit/testdata/substitute_tmpl.grd
- create mode 100644 tools/grit/grit/testdata/test_css.css
- create mode 100644 tools/grit/grit/testdata/test_html.html
- create mode 100644 tools/grit/grit/testdata/test_js.js
- create mode 100644 tools/grit/grit/testdata/test_svg.svg
- create mode 100644 tools/grit/grit/testdata/test_text.txt
- create mode 100644 tools/grit/grit/testdata/time_related.html
- create mode 100644 tools/grit/grit/testdata/toolbar_about.html
- create mode 100644 tools/grit/grit/testdata/tools/grit/resource_ids
- create mode 100644 tools/grit/grit/testdata/transl.rc
- create mode 100644 tools/grit/grit/testdata/versions.html
- create mode 100644 tools/grit/grit/testdata/whitelist.txt
- create mode 100644 tools/grit/grit/testdata/whitelist_resources.grd
- create mode 100644 tools/grit/grit/testdata/whitelist_strings.grd
- create mode 100644 tools/grit/grit/tool/__init__.py
- create mode 100644 tools/grit/grit/tool/android2grd.py
- create mode 100644 tools/grit/grit/tool/android2grd_unittest.py
- create mode 100644 tools/grit/grit/tool/build.py
- create mode 100644 tools/grit/grit/tool/build_unittest.py
- create mode 100644 tools/grit/grit/tool/buildinfo.py
- create mode 100644 tools/grit/grit/tool/buildinfo_unittest.py
- create mode 100644 tools/grit/grit/tool/count.py
- create mode 100644 tools/grit/grit/tool/diff_structures.py
- create mode 100644 tools/grit/grit/tool/diff_structures_unittest.py
- create mode 100644 tools/grit/grit/tool/interface.py
- create mode 100644 tools/grit/grit/tool/menu_from_parts.py
- create mode 100644 tools/grit/grit/tool/newgrd.py
- create mode 100644 tools/grit/grit/tool/newgrd_unittest.py
- create mode 100644 tools/grit/grit/tool/postprocess_interface.py
- create mode 100644 tools/grit/grit/tool/postprocess_unittest.py
- create mode 100644 tools/grit/grit/tool/preprocess_interface.py
- create mode 100644 tools/grit/grit/tool/preprocess_unittest.py
- create mode 100644 tools/grit/grit/tool/rc2grd.py
- create mode 100644 tools/grit/grit/tool/rc2grd_unittest.py
- create mode 100644 tools/grit/grit/tool/resize.py
- create mode 100644 tools/grit/grit/tool/test.py
- create mode 100644 tools/grit/grit/tool/transl2tc.py
- create mode 100644 tools/grit/grit/tool/transl2tc_unittest.py
- create mode 100644 tools/grit/grit/tool/unit.py
- create mode 100644 tools/grit/grit/tool/update_resource_ids/__init__.py
- create mode 100644 tools/grit/grit/tool/update_resource_ids/assigner.py
- create mode 100644 tools/grit/grit/tool/update_resource_ids/assigner_unittest.py
- create mode 100644 tools/grit/grit/tool/update_resource_ids/common.py
- create mode 100644 tools/grit/grit/tool/update_resource_ids/parser.py
- create mode 100644 tools/grit/grit/tool/update_resource_ids/reader.py
- create mode 100644 tools/grit/grit/tool/xmb.py
- create mode 100644 tools/grit/grit/tool/xmb_unittest.py
- create mode 100644 tools/grit/grit/util.py
- create mode 100644 tools/grit/grit/util_unittest.py
- create mode 100644 tools/grit/grit/xtb_reader.py
- create mode 100644 tools/grit/grit/xtb_reader_unittest.py
- create mode 100644 tools/grit/grit_info.py
- create mode 100644 tools/grit/grit_rule.gni
- create mode 100644 tools/grit/minify_with_uglify.py
- create mode 100644 tools/grit/minimize_css.py
- create mode 100644 tools/grit/minimize_css_unittest.py
- create mode 100644 tools/grit/pak_util.py
- create mode 100644 tools/grit/repack.gni
- create mode 100644 tools/grit/setup.py
- create mode 100644 tools/grit/stamp_grit_sources.py
- create mode 100644 tools/grit/third_party/six/LICENSE
- create mode 100644 tools/grit/third_party/six/README
- create mode 100644 tools/grit/third_party/six/README.chromium
- create mode 100644 tools/grit/third_party/six/__init__.py
+ tools/generate_stubs/rules.gni | 2 ++
+ 1 file changed, 2 insertions(+)
+ create mode 100644 tools/generate_stubs/rules.gni
-diff --git a/tools/grit/.gitignore b/tools/grit/.gitignore
+diff --git a/tools/generate_stubs/rules.gni b/tools/generate_stubs/rules.gni
new file mode 100644
-index 0000000000..0d20b6487c
+index 0000000000..1d9f36eb72
--- /dev/null
-+++ b/tools/grit/.gitignore
-@@ -0,0 +1 @@
-+*.pyc
-diff --git a/tools/grit/BUILD.gn b/tools/grit/BUILD.gn
-new file mode 100644
-index 0000000000..1cd3c75b55
---- /dev/null
-+++ b/tools/grit/BUILD.gn
-@@ -0,0 +1,48 @@
-+# Copyright 2014 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+# This target creates a stamp file that depends on all the sources in the grit
-+# directory. By depending on this, a target can force itself to be rebuilt if
-+# grit itself changes.
-+
-+import("//build/config/sanitizers/sanitizers.gni")
-+
-+action("grit_sources") {
-+ depfile = "$target_out_dir/grit_sources.d"
-+ script = "stamp_grit_sources.py"
-+
-+ inputs = [ "grit.py" ]
-+
-+ # Note that we can't call this "grit_sources.stamp" because that file is
-+ # implicitly created by GN for script actions.
-+ outputs = [ "$target_out_dir/grit_sources.script.stamp" ]
-+
-+ args = [
-+ rebase_path("//tools/grit", root_build_dir),
-+ rebase_path(outputs[0], root_build_dir),
-+ rebase_path(depfile, root_build_dir),
-+ ]
-+}
-+
-+group("grit_python_unittests") {
-+ testonly = true
-+
-+ data = [
-+ "//testing/scripts/common.py",
-+ "//testing/scripts/run_isolated_script_test.py",
-+ "//testing/xvfb.py",
-+ "//tools/grit/",
-+ "//third_party/catapult/third_party/typ/",
-+ ]
-+}
-+
-+# See https://crbug.com/983200
-+if (is_mac && is_asan) {
-+ create_bundle("brotli_mac_asan_workaround") {
-+ bundle_root_dir = "$target_out_dir/$target_name"
-+ bundle_executable_dir = bundle_root_dir
-+
-+ public_deps = [ "//third_party/brotli:brotli($host_toolchain)" ]
-+ }
-+}
-diff --git a/tools/grit/MANIFEST.in b/tools/grit/MANIFEST.in
-new file mode 100644
-index 0000000000..1cbff42400
---- /dev/null
-+++ b/tools/grit/MANIFEST.in
-@@ -0,0 +1,3 @@
-+exclude grit/test_suite_all.py
-+exclude grit/tool/test.py
-+global-exclude *_unittest.py
-diff --git a/tools/grit/OWNERS b/tools/grit/OWNERS
-new file mode 100644
-index 0000000000..6a8f447b82
---- /dev/null
-+++ b/tools/grit/OWNERS
-@@ -0,0 +1,8 @@
-+agrieve@chromium.org
-+flackr@chromium.org
-+thakis@chromium.org
-+thestig@chromium.org
-+
-+# Admin policy related grit tools.
-+per-file *policy*=file://components/policy/tools/OWNERS
-+per-file *admin_template*=file://components/policy/tools/OWNERS
-diff --git a/tools/grit/PRESUBMIT.py b/tools/grit/PRESUBMIT.py
-new file mode 100644
-index 0000000000..03b7188551
---- /dev/null
-+++ b/tools/grit/PRESUBMIT.py
-@@ -0,0 +1,22 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""grit unittests presubmit script.
-+
-+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
-+details on the presubmit API built into gcl.
-+"""
-+
-+
-+def RunUnittests(input_api, output_api):
-+ return input_api.canned_checks.RunUnitTests(input_api, output_api,
-+ [input_api.os_path.join('grit', 'test_suite_all.py')])
-+
-+
-+def CheckChangeOnUpload(input_api, output_api):
-+ return RunUnittests(input_api, output_api)
-+
-+
-+def CheckChangeOnCommit(input_api, output_api):
-+ return RunUnittests(input_api, output_api)
-diff --git a/tools/grit/README.md b/tools/grit/README.md
-new file mode 100644
-index 0000000000..b5c3f4b51b
---- /dev/null
-+++ b/tools/grit/README.md
-@@ -0,0 +1,19 @@
-+# GRIT (Google Resource and Internationalization Tool)
-+
-+This is a tool for projects to manage resources and simplify the localization
-+workflow.
-+
-+See the user guide for more details on using this project:
-+https://dev.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide
-+
-+## History
-+
-+This code previously used to live at
-+https://code.google.com/p/grit-i18n/source/checkout which still contains the
-+project's history. https://chromium.googlesource.com/external/grit-i18n/ is
-+a git mirror of the SVN repository that's identical except for the last two
-+commits. The project is now developed in the Chromium project directly.
-+
-+There is a read-only mirror of just this directory at
-+https://chromium.googlesource.com/chromium/src/tools/grit/ if you don't want to
-+check out all of Chromium.
-diff --git a/tools/grit/grit.py b/tools/grit/grit.py
-new file mode 100644
-index 0000000000..abd1ab6449
---- /dev/null
-+++ b/tools/grit/grit.py
-@@ -0,0 +1,31 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Bootstrapping for GRIT.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+
-+import grit.grit_runner
-+
-+sys.path.append(
-+ os.path.join(
-+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
-+ 'diagnosis'))
-+try:
-+ import crbug_1001171
-+except ImportError:
-+ crbug_1001171 = None
-+
-+
-+if __name__ == '__main__':
-+ if crbug_1001171:
-+ with crbug_1001171.DumpStateOnLookupError():
-+ sys.exit(grit.grit_runner.Main(sys.argv[1:]))
-+ else:
-+ sys.exit(grit.grit_runner.Main(sys.argv[1:]))
-diff --git a/tools/grit/grit/__init__.py b/tools/grit/grit/__init__.py
-new file mode 100644
-index 0000000000..91ac9ee896
---- /dev/null
-+++ b/tools/grit/grit/__init__.py
-@@ -0,0 +1,19 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Package 'grit'
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+
-+
-+_CUR_DIR = os.path.abspath(os.path.dirname(__file__))
-+_GRIT_DIR = os.path.dirname(_CUR_DIR)
-+_THIRD_PARTY_DIR = os.path.join(_GRIT_DIR, 'third_party')
-+
-+if _THIRD_PARTY_DIR not in sys.path:
-+ sys.path.insert(0, _THIRD_PARTY_DIR)
-diff --git a/tools/grit/grit/clique.py b/tools/grit/grit/clique.py
-new file mode 100644
-index 0000000000..e7be3ec164
---- /dev/null
-+++ b/tools/grit/grit/clique.py
-@@ -0,0 +1,491 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Collections of messages and their translations, called cliques. Also
-+collections of cliques (uber-cliques).
-+'''
-+
-+from __future__ import print_function
-+
-+import re
-+
-+import six
-+
-+from grit import constants
-+from grit import exception
-+from grit import lazy_re
-+from grit import pseudo
-+from grit import pseudo_rtl
-+from grit import tclib
-+
-+
-+class UberClique(object):
-+ '''A factory (NOT a singleton factory) for making cliques. It has several
-+ methods for working with the cliques created using the factory.
-+ '''
-+
-+ def __init__(self):
-+ # A map from message ID to list of cliques whose source messages have
-+ # that ID. This will contain all cliques created using this factory.
-+ # Different messages can have the same ID because they have the
-+ # same translateable portion and placeholder names, but occur in different
-+ # places in the resource tree.
-+ #
-+ # Each list of cliques is kept sorted by description, to achieve
-+ # stable results from the BestClique method, see below.
-+ self.cliques_ = {}
-+
-+ # A map of clique IDs to list of languages to indicate translations where we
-+ # fell back to English.
-+ self.fallback_translations_ = {}
-+
-+ # A map of clique IDs to list of languages to indicate missing translations.
-+ self.missing_translations_ = {}
-+
-+ def _AddMissingTranslation(self, lang, clique, is_error):
-+ tl = self.fallback_translations_
-+ if is_error:
-+ tl = self.missing_translations_
-+ id = clique.GetId()
-+ if id not in tl:
-+ tl[id] = {}
-+ if lang not in tl[id]:
-+ tl[id][lang] = 1
-+
-+ def HasMissingTranslations(self):
-+ return len(self.missing_translations_) > 0
-+
-+ def MissingTranslationsReport(self):
-+ '''Returns a string suitable for printing to report missing
-+ and fallback translations to the user.
-+ '''
-+ def ReportTranslation(clique, langs):
-+ text = clique.GetMessage().GetPresentableContent()
-+ # The text 'error' (usually 'Error:' but we are conservative)
-+ # can trigger some build environments (Visual Studio, we're
-+ # looking at you) to consider invocation of grit to have failed,
-+ # so we make sure never to output that word.
-+ extract = re.sub(r'(?i)error', 'REDACTED', text[0:40])[0:40]
-+ ellipsis = ''
-+ if len(text) > 40:
-+ ellipsis = '...'
-+ langs_extract = langs[0:6]
-+ describe_langs = ','.join(langs_extract)
-+ if len(langs) > 6:
-+ describe_langs += " and %d more" % (len(langs) - 6)
-+ return " %s \"%s%s\" %s" % (clique.GetId(), extract, ellipsis,
-+ describe_langs)
-+ lines = []
-+ if len(self.fallback_translations_):
-+ lines.append(
-+ "WARNING: Fell back to English for the following translations:")
-+ for (id, langs) in self.fallback_translations_.items():
-+ lines.append(
-+ ReportTranslation(self.cliques_[id][0], list(langs.keys())))
-+ if len(self.missing_translations_):
-+ lines.append("ERROR: The following translations are MISSING:")
-+ for (id, langs) in self.missing_translations_.items():
-+ lines.append(
-+ ReportTranslation(self.cliques_[id][0], list(langs.keys())))
-+ return '\n'.join(lines)
-+
-+ def MakeClique(self, message, translateable=True):
-+ '''Create a new clique initialized with a message.
-+
-+ Args:
-+ message: tclib.Message()
-+ translateable: True | False
-+ '''
-+ clique = MessageClique(self, message, translateable)
-+
-+ # Enable others to find this clique by its message ID
-+ if message.GetId() in self.cliques_:
-+ presentable_text = clique.GetMessage().GetPresentableContent()
-+ if not message.HasAssignedId():
-+ for c in self.cliques_[message.GetId()]:
-+ assert c.GetMessage().GetPresentableContent() == presentable_text
-+ self.cliques_[message.GetId()].append(clique)
-+ # We need to keep each list of cliques sorted by description, to
-+ # achieve stable results from the BestClique method, see below.
-+ self.cliques_[message.GetId()].sort(
-+ key=lambda c:c.GetMessage().GetDescription())
-+ else:
-+ self.cliques_[message.GetId()] = [clique]
-+
-+ return clique
-+
-+ def FindCliqueAndAddTranslation(self, translation, language):
-+ '''Adds the specified translation to the clique with the source message
-+ it is a translation of.
-+
-+ Args:
-+ translation: tclib.Translation()
-+ language: 'en' | 'fr' ...
-+
-+ Return:
-+ True if the source message was found, otherwise false.
-+ '''
-+ if translation.GetId() in self.cliques_:
-+ for clique in self.cliques_[translation.GetId()]:
-+ clique.AddTranslation(translation, language)
-+ return True
-+ else:
-+ return False
-+
-+ def BestClique(self, id):
-+ '''Returns the "best" clique from a list of cliques. All the cliques
-+ must have the same ID. The "best" clique is chosen in the following
-+ order of preference:
-+ - The first clique that has a non-ID-based description.
-+ - If no such clique found, the first clique with an ID-based description.
-+ - Otherwise the first clique.
-+
-+ This method is stable in terms of always returning a clique with
-+ an identical description (on different runs of GRIT on the same
-+ data) because self.cliques_ is sorted by description.
-+ '''
-+ clique_list = self.cliques_[id]
-+ clique_with_id = None
-+ clique_default = None
-+ for clique in clique_list:
-+ if not clique_default:
-+ clique_default = clique
-+
-+ description = clique.GetMessage().GetDescription()
-+ if description and len(description) > 0:
-+ if not description.startswith('ID:'):
-+ # this is the preferred case so we exit right away
-+ return clique
-+ elif not clique_with_id:
-+ clique_with_id = clique
-+ if clique_with_id:
-+ return clique_with_id
-+ else:
-+ return clique_default
-+
-+ def BestCliquePerId(self):
-+ '''Iterates over the list of all cliques and returns the best clique for
-+ each ID. This will be the first clique with a source message that has a
-+ non-empty description, or an arbitrary clique if none of them has a
-+ description.
-+ '''
-+ for id in self.cliques_:
-+ yield self.BestClique(id)
-+
-+ def BestCliqueByOriginalText(self, text, meaning):
-+ '''Finds the "best" (as in BestClique()) clique that has original text
-+ 'text' and meaning 'meaning'. Returns None if there is no such clique.
-+ '''
-+ # If needed, this can be optimized by maintaining a map of
-+ # fingerprints of original text+meaning to cliques.
-+ for c in self.BestCliquePerId():
-+ msg = c.GetMessage()
-+ if msg.GetRealContent() == text and msg.GetMeaning() == meaning:
-+ return msg
-+ return None
-+
-+ def AllMessageIds(self):
-+ '''Returns a list of all defined message IDs.
-+ '''
-+ return list(self.cliques_.keys())
-+
-+ def AllCliques(self):
-+ '''Iterates over all cliques. Note that this can return multiple cliques
-+ with the same ID.
-+ '''
-+ for cliques in self.cliques_.values():
-+ for c in cliques:
-+ yield c
-+
-+ def GenerateXtbParserCallback(self, lang, debug=False):
-+ '''Creates a callback function as required by grit.xtb_reader.Parse().
-+ This callback will create Translation objects for each message from
-+ the XTB that exists in this uberclique, and add them as translations for
-+ the relevant cliques. The callback will add translations to the language
-+ specified by 'lang'
-+
-+ Args:
-+ lang: 'fr'
-+ debug: True | False
-+ '''
-+ def Callback(id, structure):
-+ if id not in self.cliques_:
-+ if debug:
-+ print("Ignoring translation #%s" % id)
-+ return
-+
-+ if debug:
-+ print("Adding translation #%s" % id)
-+
-+ # We fetch placeholder information from the original message (the XTB file
-+ # only contains placeholder names).
-+ original_msg = self.BestClique(id).GetMessage()
-+
-+ translation = tclib.Translation(id=id)
-+ for is_ph,text in structure:
-+ if not is_ph:
-+ translation.AppendText(text)
-+ else:
-+ found_placeholder = False
-+ for ph in original_msg.GetPlaceholders():
-+ if ph.GetPresentation() == text:
-+ translation.AppendPlaceholder(tclib.Placeholder(
-+ ph.GetPresentation(), ph.GetOriginal(), ph.GetExample()))
-+ found_placeholder = True
-+ break
-+ if not found_placeholder:
-+ raise exception.MismatchingPlaceholders(
-+ 'Translation for message ID %s had <ph name="%s"/>, no match\n'
-+ 'in original message' % (id, text))
-+ self.FindCliqueAndAddTranslation(translation, lang)
-+ return Callback
-+
-+
-+class CustomType(object):
-+ '''A base class you should implement if you wish to specify a custom type
-+ for a message clique (i.e. custom validation and optional modification of
-+ translations).'''
-+
-+ def Validate(self, message):
-+ '''Returns true if the message (a tclib.Message object) is valid,
-+ otherwise false.
-+ '''
-+ raise NotImplementedError()
-+
-+ def ValidateAndModify(self, lang, translation):
-+ '''Returns true if the translation (a tclib.Translation object) is valid,
-+ otherwise false. The language is also passed in. This method may modify
-+ the translation that is passed in, if it so wishes.
-+ '''
-+ raise NotImplementedError()
-+
-+ def ModifyTextPart(self, lang, text):
-+ '''If you call ModifyEachTextPart, it will turn around and call this method
-+ for each text part of the translation. You should return the modified
-+ version of the text, or just the original text to not change anything.
-+ '''
-+ raise NotImplementedError()
-+
-+ def ModifyEachTextPart(self, lang, translation):
-+ '''Call this to easily modify one or more of the textual parts of a
-+ translation. It will call ModifyTextPart for each part of the
-+ translation.
-+ '''
-+ contents = translation.GetContent()
-+ for ix in range(len(contents)):
-+ if (isinstance(contents[ix], six.string_types)):
-+ contents[ix] = self.ModifyTextPart(lang, contents[ix])
-+
-+
-+class OneOffCustomType(CustomType):
-+ '''A very simple custom type that performs the validation expressed by
-+ the input expression on all languages including the source language.
-+ The expression can access the variables 'lang', 'msg' and 'text()' where
-+ 'lang' is the language of 'msg', 'msg' is the message or translation being
-+ validated and 'text()' returns the real contents of 'msg' (for shorthand).
-+ '''
-+ def __init__(self, expression):
-+ self.expr = expression
-+ def Validate(self, message):
-+ return self.ValidateAndModify(MessageClique.source_language, message)
-+ def ValidateAndModify(self, lang, msg):
-+ def text():
-+ return msg.GetRealContent()
-+ return eval(self.expr, {},
-+ {'lang' : lang,
-+ 'text' : text,
-+ 'msg' : msg,
-+ })
-+
-+
-+class MessageClique(object):
-+ '''A message along with all of its translations. Also code to bring
-+ translations together with their original message.'''
-+
-+ # change this to the language code of Messages you add to cliques_.
-+ # TODO(joi) Actually change this based on the <grit> node's source language
-+ source_language = 'en'
-+
-+ # A constant translation we use when asked for a translation into the
-+ # special language constants.CONSTANT_LANGUAGE.
-+ CONSTANT_TRANSLATION = tclib.Translation(text='TTTTTT')
-+
-+ # A pattern to match messages that are empty or whitespace only.
-+ WHITESPACE_MESSAGE = lazy_re.compile(r'^\s*$')
-+
-+ def __init__(self, uber_clique, message, translateable=True,
-+ custom_type=None):
-+ '''Create a new clique initialized with just a message.
-+
-+ Note that messages with a body comprised only of whitespace will implicitly
-+ be marked non-translatable.
-+
-+ Args:
-+ uber_clique: Our uber-clique (collection of cliques)
-+ message: tclib.Message()
-+ translateable: True | False
-+ custom_type: instance of clique.CustomType interface
-+ '''
-+ # Our parent
-+ self.uber_clique = uber_clique
-+ # If not translateable, we only store the original message.
-+ self.translateable = translateable
-+
-+ # We implicitly mark messages that have a whitespace-only body as
-+ # non-translateable.
-+ if MessageClique.WHITESPACE_MESSAGE.match(message.GetRealContent()):
-+ self.translateable = False
-+
-+ # A mapping of language identifiers to tclib.BaseMessage and its
-+ # subclasses (i.e. tclib.Message and tclib.Translation).
-+ self.clique = { MessageClique.source_language : message }
-+ # A list of the "shortcut groups" this clique is
-+ # part of. Within any given shortcut group, no shortcut key (e.g. &J)
-+ # must appear more than once in each language for all cliques that
-+ # belong to the group.
-+ self.shortcut_groups = []
-+ # An instance of the CustomType interface, or None. If this is set, it will
-+ # be used to validate the original message and translations thereof, and
-+ # will also get a chance to modify translations of the message.
-+ self.SetCustomType(custom_type)
-+
-+ def GetMessage(self):
-+ '''Retrieves the tclib.Message that is the source for this clique.'''
-+ return self.clique[MessageClique.source_language]
-+
-+ def GetId(self):
-+ '''Retrieves the message ID of the messages in this clique.'''
-+ return self.GetMessage().GetId()
-+
-+ def IsTranslateable(self):
-+ return self.translateable
-+
-+ def AddToShortcutGroup(self, group):
-+ self.shortcut_groups.append(group)
-+
-+ def SetCustomType(self, custom_type):
-+ '''Makes this clique use custom_type for validating messages and
-+ translations, and optionally modifying translations.
-+ '''
-+ self.custom_type = custom_type
-+ if custom_type and not custom_type.Validate(self.GetMessage()):
-+ raise exception.InvalidMessage(self.GetMessage().GetRealContent())
-+
-+ def MessageForLanguage(self, lang, pseudo_if_no_match=True,
-+ fallback_to_english=False):
-+ '''Returns the message/translation for the specified language, providing
-+ a pseudotranslation if there is no available translation and a pseudo-
-+ translation is requested.
-+
-+ The translation of any message whatsoever in the special language
-+ 'x_constant' is the message "TTTTTT".
-+
-+ Args:
-+ lang: 'en'
-+ pseudo_if_no_match: True
-+ fallback_to_english: False
-+
-+ Return:
-+ tclib.BaseMessage
-+ '''
-+ if not self.translateable:
-+ return self.GetMessage()
-+
-+ if lang == constants.CONSTANT_LANGUAGE:
-+ return self.CONSTANT_TRANSLATION
-+
-+ for msglang in self.clique:
-+ if lang == msglang:
-+ return self.clique[msglang]
-+
-+ if lang == constants.FAKE_BIDI:
-+ return pseudo_rtl.PseudoRTLMessage(self.GetMessage())
-+
-+ if fallback_to_english:
-+ self.uber_clique._AddMissingTranslation(lang, self, is_error=False)
-+ return self.GetMessage()
-+
-+ # If we're not supposed to generate pseudotranslations, we add an error
-+ # report to a list of errors, then fail at a higher level, so that we
-+ # get a list of all messages that are missing translations.
-+ if not pseudo_if_no_match:
-+ self.uber_clique._AddMissingTranslation(lang, self, is_error=True)
-+
-+ return pseudo.PseudoMessage(self.GetMessage())
-+
-+ def AllMessagesThatMatch(self, lang_re, include_pseudo = True):
-+ '''Returns a map of all messages that match 'lang', including the pseudo
-+ translation if requested.
-+
-+ Args:
-+ lang_re: re.compile(r'fr|en')
-+ include_pseudo: True
-+
-+ Return:
-+ { 'en' : tclib.Message,
-+ 'fr' : tclib.Translation,
-+ pseudo.PSEUDO_LANG : tclib.Translation }
-+ '''
-+ if not self.translateable:
-+ return [self.GetMessage()]
-+
-+ matches = {}
-+ for msglang in self.clique:
-+ if lang_re.match(msglang):
-+ matches[msglang] = self.clique[msglang]
-+
-+ if include_pseudo:
-+ matches[pseudo.PSEUDO_LANG] = pseudo.PseudoMessage(self.GetMessage())
-+
-+ return matches
-+
-+ def AddTranslation(self, translation, language):
-+ '''Add a translation to this clique. The translation must have the same
-+ ID as the message that is the source for this clique.
-+
-+ If this clique is not translateable, the function just returns.
-+
-+ Args:
-+ translation: tclib.Translation()
-+ language: 'en'
-+
-+ Throws:
-+ grit.exception.InvalidTranslation if the translation you're trying to add
-+ doesn't have the same message ID as the source message of this clique.
-+ '''
-+ if not self.translateable:
-+ return
-+ if translation.GetId() != self.GetId():
-+ raise exception.InvalidTranslation(
-+ 'Msg ID %s, transl ID %s' % (self.GetId(), translation.GetId()))
-+
-+ assert not language in self.clique
-+
-+ # Because two messages can differ in the original content of their
-+ # placeholders yet share the same ID (because they are otherwise the
-+ # same), the translation we are getting may have different original
-+ # content for placeholders than our message, yet it is still the right
-+ # translation for our message (because it is for the same ID). We must
-+ # therefore fetch the original content of placeholders from our original
-+ # English message.
-+ #
-+ # See grit.clique_unittest.MessageCliqueUnittest.testSemiIdenticalCliques
-+ # for a concrete explanation of why this is necessary.
-+
-+ original = self.MessageForLanguage(self.source_language, False)
-+ if len(original.GetPlaceholders()) != len(translation.GetPlaceholders()):
-+ print("ERROR: '%s' translation of message id %s does not match" %
-+ (language, translation.GetId()))
-+ assert False
-+
-+ transl_msg = tclib.Translation(id=self.GetId(),
-+ text=translation.GetPresentableContent(),
-+ placeholders=original.GetPlaceholders())
-+
-+ if (self.custom_type and
-+ not self.custom_type.ValidateAndModify(language, transl_msg)):
-+ print("WARNING: %s translation failed validation: %s" %
-+ (language, transl_msg.GetId()))
-+
-+ self.clique[language] = transl_msg
-diff --git a/tools/grit/grit/clique_unittest.py b/tools/grit/grit/clique_unittest.py
-new file mode 100644
-index 0000000000..7d2d7318ba
---- /dev/null
-+++ b/tools/grit/grit/clique_unittest.py
-@@ -0,0 +1,265 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.clique'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import re
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import clique
-+from grit import exception
-+from grit import pseudo
-+from grit import tclib
-+from grit import grd_reader
-+from grit import util
-+
-+class MessageCliqueUnittest(unittest.TestCase):
-+ def testClique(self):
-+ factory = clique.UberClique()
-+ msg = tclib.Message(text='Hello USERNAME, how are you?',
-+ placeholders=[
-+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
-+ c = factory.MakeClique(msg)
-+
-+ self.failUnless(c.GetMessage() == msg)
-+ self.failUnless(c.GetId() == msg.GetId())
-+
-+ msg_fr = tclib.Translation(text='Bonjour USERNAME, comment ca va?',
-+ id=msg.GetId(), placeholders=[
-+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
-+ msg_de = tclib.Translation(text='Guten tag USERNAME, wie geht es dir?',
-+ id=msg.GetId(), placeholders=[
-+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
-+
-+ c.AddTranslation(msg_fr, 'fr')
-+ factory.FindCliqueAndAddTranslation(msg_de, 'de')
-+
-+ # sort() sorts lists in-place and does not return them
-+ for lang in ('en', 'fr', 'de'):
-+ self.failUnless(lang in c.clique)
-+
-+ self.failUnless(c.MessageForLanguage('fr').GetRealContent() ==
-+ msg_fr.GetRealContent())
-+
-+ try:
-+ c.MessageForLanguage('zh-CN', False)
-+ self.fail('Should have gotten exception')
-+ except:
-+ pass
-+
-+ self.failUnless(c.MessageForLanguage('zh-CN', True) != None)
-+
-+ rex = re.compile('fr|de|bingo')
-+ self.failUnless(len(c.AllMessagesThatMatch(rex, False)) == 2)
-+ self.failUnless(
-+ c.AllMessagesThatMatch(rex, True)[pseudo.PSEUDO_LANG] is not None)
-+
-+ def testBestClique(self):
-+ factory = clique.UberClique()
-+ factory.MakeClique(tclib.Message(text='Alfur', description='alfaholl'))
-+ factory.MakeClique(tclib.Message(text='Alfur', description=''))
-+ factory.MakeClique(tclib.Message(text='Vaettur', description=''))
-+ factory.MakeClique(tclib.Message(text='Vaettur', description=''))
-+ factory.MakeClique(tclib.Message(text='Troll', description=''))
-+ factory.MakeClique(tclib.Message(text='Gryla', description='ID: IDS_GRYLA'))
-+ factory.MakeClique(tclib.Message(text='Gryla', description='vondakerling'))
-+ factory.MakeClique(tclib.Message(text='Leppaludi', description='ID: IDS_LL'))
-+ factory.MakeClique(tclib.Message(text='Leppaludi', description=''))
-+
-+ count_best_cliques = 0
-+ for c in factory.BestCliquePerId():
-+ count_best_cliques += 1
-+ msg = c.GetMessage()
-+ text = msg.GetRealContent()
-+ description = msg.GetDescription()
-+ if text == 'Alfur':
-+ self.failUnless(description == 'alfaholl')
-+ elif text == 'Gryla':
-+ self.failUnless(description == 'vondakerling')
-+ elif text == 'Leppaludi':
-+ self.failUnless(description == 'ID: IDS_LL')
-+ self.failUnless(count_best_cliques == 5)
-+
-+ def testAllInUberClique(self):
-+ resources = grd_reader.Parse(
-+ StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ </messages>
-+ <structures>
-+ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
-+ <structure type="tr_html" name="ID_HTML" file="grit/testdata/simple.html" />
-+ </structures>
-+ </release>
-+</grit>'''), util.PathFromRoot('.'))
-+ resources.SetOutputLanguage('en')
-+ resources.RunGatherers()
-+ content_list = []
-+ for clique_list in resources.UberClique().cliques_.values():
-+ for clique in clique_list:
-+ content_list.append(clique.GetMessage().GetRealContent())
-+ self.failUnless('Hello %s, how are you doing today?' in content_list)
-+ self.failUnless('Jack "Black" Daniels' in content_list)
-+ self.failUnless('Hello!' in content_list)
-+
-+ def testCorrectExceptionIfWrongEncodingOnResourceFile(self):
-+ '''This doesn't really belong in this unittest file, but what the heck.'''
-+ resources = grd_reader.Parse(
-+ StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <structures>
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit/testdata/klonk.rc" />
-+ </structures>
-+ </release>
-+</grit>'''), util.PathFromRoot('.'))
-+ self.assertRaises(exception.SectionNotFound, resources.RunGatherers)
-+
-+ def testSemiIdenticalCliques(self):
-+ messages = [
-+ tclib.Message(text='Hello USERNAME',
-+ placeholders=[tclib.Placeholder('USERNAME', '$1', 'Joi')]),
-+ tclib.Message(text='Hello USERNAME',
-+ placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi')]),
-+ ]
-+ self.failUnless(messages[0].GetId() == messages[1].GetId())
-+
-+ # Both of the above would share a translation.
-+ translation = tclib.Translation(id=messages[0].GetId(),
-+ text='Bonjour USERNAME',
-+ placeholders=[tclib.Placeholder(
-+ 'USERNAME', '$1', 'Joi')])
-+
-+ factory = clique.UberClique()
-+ cliques = [factory.MakeClique(msg) for msg in messages]
-+
-+ for clq in cliques:
-+ clq.AddTranslation(translation, 'fr')
-+
-+ self.failUnless(cliques[0].MessageForLanguage('fr').GetRealContent() ==
-+ 'Bonjour $1')
-+ self.failUnless(cliques[1].MessageForLanguage('fr').GetRealContent() ==
-+ 'Bonjour %s')
-+
-+ def testMissingTranslations(self):
-+ messages = [ tclib.Message(text='Hello'), tclib.Message(text='Goodbye') ]
-+ factory = clique.UberClique()
-+ cliques = [factory.MakeClique(msg) for msg in messages]
-+
-+ cliques[1].MessageForLanguage('fr', False, True)
-+
-+ self.failUnless(not factory.HasMissingTranslations())
-+
-+ cliques[0].MessageForLanguage('de', False, False)
-+
-+ self.failUnless(factory.HasMissingTranslations())
-+
-+ report = factory.MissingTranslationsReport()
-+ self.failUnless(report.count('WARNING') == 1)
-+ self.failUnless(report.count('8053599568341804890 "Goodbye" fr') == 1)
-+ self.failUnless(report.count('ERROR') == 1)
-+ self.failUnless(report.count('800120468867715734 "Hello" de') == 1)
-+
-+ def testCustomTypes(self):
-+ factory = clique.UberClique()
-+ message = tclib.Message(text='Bingo bongo')
-+ c = factory.MakeClique(message)
-+ try:
-+ c.SetCustomType(DummyCustomType())
-+ self.fail()
-+ except:
-+ pass # expected case - 'Bingo bongo' does not start with 'jjj'
-+
-+ message = tclib.Message(text='jjjBingo bongo')
-+ c = factory.MakeClique(message)
-+ c.SetCustomType(util.NewClassInstance(
-+ 'grit.clique_unittest.DummyCustomType', clique.CustomType))
-+ translation = tclib.Translation(id=message.GetId(), text='Bilingo bolongo')
-+ c.AddTranslation(translation, 'fr')
-+ self.failUnless(c.MessageForLanguage('fr').GetRealContent().startswith('jjj'))
-+
-+ def testWhitespaceMessagesAreNontranslateable(self):
-+ factory = clique.UberClique()
-+
-+ message = tclib.Message(text=' \t')
-+ c = factory.MakeClique(message, translateable=True)
-+ self.failIf(c.IsTranslateable())
-+
-+ message = tclib.Message(text='\n \n ')
-+ c = factory.MakeClique(message, translateable=True)
-+ self.failIf(c.IsTranslateable())
-+
-+ message = tclib.Message(text='\n hello')
-+ c = factory.MakeClique(message, translateable=True)
-+ self.failUnless(c.IsTranslateable())
-+
-+ def testEachCliqueKeptSorted(self):
-+ factory = clique.UberClique()
-+ msg_a = tclib.Message(text='hello', description='a')
-+ msg_b = tclib.Message(text='hello', description='b')
-+ msg_c = tclib.Message(text='hello', description='c')
-+ # Insert out of order
-+ clique_b = factory.MakeClique(msg_b, translateable=True)
-+ clique_a = factory.MakeClique(msg_a, translateable=True)
-+ clique_c = factory.MakeClique(msg_c, translateable=True)
-+ clique_list = factory.cliques_[clique_a.GetId()]
-+ self.failUnless(len(clique_list) == 3)
-+ self.failUnless(clique_list[0] == clique_a)
-+ self.failUnless(clique_list[1] == clique_b)
-+ self.failUnless(clique_list[2] == clique_c)
-+
-+ def testBestCliqueSortIsStable(self):
-+ factory = clique.UberClique()
-+ text = 'hello'
-+ msg_no_description = tclib.Message(text=text)
-+ msg_id_description_a = tclib.Message(text=text, description='ID: a')
-+ msg_id_description_b = tclib.Message(text=text, description='ID: b')
-+ msg_description_x = tclib.Message(text=text, description='x')
-+ msg_description_y = tclib.Message(text=text, description='y')
-+ clique_id = msg_no_description.GetId()
-+
-+ # Insert in an order that tests all outcomes.
-+ clique_no_description = factory.MakeClique(msg_no_description,
-+ translateable=True)
-+ self.failUnless(factory.BestClique(clique_id) == clique_no_description)
-+ clique_id_description_b = factory.MakeClique(msg_id_description_b,
-+ translateable=True)
-+ self.failUnless(factory.BestClique(clique_id) == clique_id_description_b)
-+ clique_id_description_a = factory.MakeClique(msg_id_description_a,
-+ translateable=True)
-+ self.failUnless(factory.BestClique(clique_id) == clique_id_description_a)
-+ clique_description_y = factory.MakeClique(msg_description_y,
-+ translateable=True)
-+ self.failUnless(factory.BestClique(clique_id) == clique_description_y)
-+ clique_description_x = factory.MakeClique(msg_description_x,
-+ translateable=True)
-+ self.failUnless(factory.BestClique(clique_id) == clique_description_x)
-+
-+
-+class DummyCustomType(clique.CustomType):
-+ def Validate(self, message):
-+ return message.GetRealContent().startswith('jjj')
-+ def ValidateAndModify(self, lang, translation):
-+ is_ok = self.Validate(translation)
-+ self.ModifyEachTextPart(lang, translation)
-+ def ModifyTextPart(self, lang, text):
-+ return 'jjj%s' % text
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/constants.py b/tools/grit/grit/constants.py
-new file mode 100644
-index 0000000000..8229c94b09
---- /dev/null
-+++ b/tools/grit/grit/constants.py
-@@ -0,0 +1,23 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Constant definitions for GRIT.
-+'''
-+
-+from __future__ import print_function
-+
-+# This is the Icelandic noun meaning "grit" and is used to check that our
-+# input files are in the correct encoding. The middle character gets encoded
-+# as two bytes in UTF-8, so this is sufficient to detect incorrect encoding.
-+ENCODING_CHECK = u'm\u00f6l'
-+
-+# A special language, translations into which are always "TTTTTT".
-+CONSTANT_LANGUAGE = 'x_constant'
-+
-+FAKE_BIDI = 'fake-bidi'
-+
-+# Magic number added to the header of resources brotli compressed by grit. Used
-+# to easily identify resources as being brotli compressed. See
-+# ui/base/resource/resource_bundle.h for decompression usage.
-+BROTLI_CONST = b'\x1e\x9b'
-diff --git a/tools/grit/grit/exception.py b/tools/grit/grit/exception.py
-new file mode 100644
-index 0000000000..2a363fb077
---- /dev/null
-+++ b/tools/grit/grit/exception.py
-@@ -0,0 +1,139 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Exception types for GRIT.
-+'''
-+
-+from __future__ import print_function
-+
-+class Base(Exception):
-+ '''A base exception that uses the class's docstring in addition to any
-+ user-provided message as the body of the Base.
-+ '''
-+ def __init__(self, msg=''):
-+ if len(msg):
-+ if self.__doc__:
-+ msg = self.__doc__ + ': ' + msg
-+ else:
-+ msg = self.__doc__
-+ super(Base, self).__init__(msg)
-+
-+
-+class Parsing(Base):
-+ '''An error occurred parsing a GRD or XTB file.'''
-+ pass
-+
-+
-+class UnknownElement(Parsing):
-+ '''An unknown node type was encountered.'''
-+ pass
-+
-+
-+class MissingElement(Parsing):
-+ '''An expected element was missing.'''
-+ pass
-+
-+
-+class UnexpectedChild(Parsing):
-+ '''An unexpected child element was encountered (on a leaf node).'''
-+ pass
-+
-+
-+class UnexpectedAttribute(Parsing):
-+ '''The attribute was not expected'''
-+ pass
-+
-+
-+class UnexpectedContent(Parsing):
-+ '''This element should not have content'''
-+ pass
-+
-+class MissingMandatoryAttribute(Parsing):
-+ '''This element is missing a mandatory attribute'''
-+ pass
-+
-+
-+class MutuallyExclusiveMandatoryAttribute(Parsing):
-+ '''This element has 2 mutually exclusive mandatory attributes'''
-+ pass
-+
-+
-+class DuplicateKey(Parsing):
-+ '''A duplicate key attribute was found.'''
-+ pass
-+
-+
-+class TooManyExamples(Parsing):
-+ '''Only one <ex> element is allowed for each <ph> element.'''
-+ pass
-+
-+
-+class FileNotFound(Parsing):
-+ '''The resource file was not found.'''
-+ pass
-+
-+
-+class InvalidMessage(Base):
-+ '''The specified message failed validation.'''
-+ pass
-+
-+
-+class InvalidTranslation(Base):
-+ '''Attempt to add an invalid translation to a clique.'''
-+ pass
-+
-+
-+class NoSuchTranslation(Base):
-+ '''Requested translation not available'''
-+ pass
-+
-+
-+class NotReady(Base):
-+ '''Attempt to use an object before it is ready, or attempt to translate \
-+an empty document.'''
-+ pass
-+
-+
-+class MismatchingPlaceholders(Base):
-+ '''Placeholders do not match.'''
-+ pass
-+
-+
-+class InvalidPlaceholderName(Base):
-+ '''Placeholder name can only contain A-Z, a-z, 0-9 and underscore.'''
-+ pass
-+
-+
-+class BlockTagInTranslateableChunk(Base):
-+ '''A block tag was encountered where it wasn't expected.'''
-+ pass
-+
-+
-+class SectionNotFound(Base):
-+ '''The section you requested was not found in the RC file. Make \
-+sure the section ID is correct (matches the section's ID in the RC file). \
-+Also note that you may need to specify the RC file's encoding (using the \
-+encoding="" attribute) if it is not in the default Windows-1252 encoding. \
-+'''
-+ pass
-+
-+
-+class IdRangeOverlap(Base):
-+ '''ID range overlap.'''
-+ pass
-+
-+
-+class ReservedHeaderCollision(Base):
-+ '''Resource included with first 3 bytes matching reserved header.'''
-+ pass
-+
-+
-+class PlaceholderNotInsidePhNode(Base):
-+ '''Placeholder formatters should be inside <ph> element.'''
-+ pass
-+
-+
-+class InvalidCharactersInsidePhNode(Base):
-+ '''Invalid characters found inside <ph> element.'''
-+ pass
-diff --git a/tools/grit/grit/extern/BogoFP.py b/tools/grit/grit/extern/BogoFP.py
-new file mode 100644
-index 0000000000..fc90145833
---- /dev/null
-+++ b/tools/grit/grit/extern/BogoFP.py
-@@ -0,0 +1,22 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Bogus fingerprint implementation, do not use for production,
-+provided only as an example.
-+
-+Usage:
-+ grit.py -h grit.extern.BogoFP xmb /tmp/foo
-+"""
-+
-+from __future__ import print_function
-+
-+import grit.extern.FP
-+
-+
-+def UnsignedFingerPrint(str, encoding='utf-8'):
-+ """Generate a fingerprint not intended for production from str (it
-+ reduces the precision of the production fingerprint by one bit).
-+ """
-+ return (0xFFFFF7FFFFFFFFFF &
-+ grit.extern.FP._UnsignedFingerPrintImpl(str, encoding))
-diff --git a/tools/grit/grit/extern/FP.py b/tools/grit/grit/extern/FP.py
-new file mode 100644
-index 0000000000..f4ec4d943f
---- /dev/null
-+++ b/tools/grit/grit/extern/FP.py
-@@ -0,0 +1,72 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+from __future__ import print_function
-+
-+try:
-+ import hashlib
-+ _new_md5 = hashlib.md5
-+except ImportError:
-+ import md5
-+ _new_md5 = md5.new
-+
-+
-+"""64-bit fingerprint support for strings.
-+
-+Usage:
-+ from extern import FP
-+ print('Fingerprint is %ld' % FP.FingerPrint('Hello world!'))
-+"""
-+
-+
-+def _UnsignedFingerPrintImpl(str, encoding='utf-8'):
-+ """Generate a 64-bit fingerprint by taking the first half of the md5
-+ of the string.
-+ """
-+ hex128 = _new_md5(str.encode(encoding)).hexdigest()
-+ int64 = int(hex128[:16], 16)
-+ return int64
-+
-+
-+def UnsignedFingerPrint(str, encoding='utf-8'):
-+ """Generate a 64-bit fingerprint.
-+
-+ The default implementation uses _UnsignedFingerPrintImpl, which
-+ takes the first half of the md5 of the string, but the
-+ implementation may be switched using SetUnsignedFingerPrintImpl.
-+ """
-+ return _UnsignedFingerPrintImpl(str, encoding)
-+
-+
-+def FingerPrint(str, encoding='utf-8'):
-+ fp = UnsignedFingerPrint(str, encoding=encoding)
-+ # interpret fingerprint as signed longs
-+ if fp & 0x8000000000000000:
-+ fp = -((~fp & 0xFFFFFFFFFFFFFFFF) + 1)
-+ return fp
-+
-+
-+def UseUnsignedFingerPrintFromModule(module_name):
-+ """Imports module_name and replaces UnsignedFingerPrint in the
-+ current module with the function of the same name from the imported
-+ module.
-+
-+ Returns the function object previously known as
-+ grit.extern.FP.UnsignedFingerPrint.
-+ """
-+ hash_module = __import__(module_name, fromlist=[module_name])
-+ return SetUnsignedFingerPrint(hash_module.UnsignedFingerPrint)
-+
-+
-+def SetUnsignedFingerPrint(function_object):
-+ """Sets grit.extern.FP.UnsignedFingerPrint to point to
-+ function_object.
-+
-+ Returns the function object previously known as
-+ grit.extern.FP.UnsignedFingerPrint.
-+ """
-+ global UnsignedFingerPrint
-+ original_function_object = UnsignedFingerPrint
-+ UnsignedFingerPrint = function_object
-+ return original_function_object
-diff --git a/tools/grit/grit/extern/__init__.py b/tools/grit/grit/extern/__init__.py
-new file mode 100644
-index 0000000000..e69de29bb2
-diff --git a/tools/grit/grit/extern/tclib.py b/tools/grit/grit/extern/tclib.py
-new file mode 100644
-index 0000000000..9952a87c11
---- /dev/null
-+++ b/tools/grit/grit/extern/tclib.py
-@@ -0,0 +1,503 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+# The tclib module contains tools for aggregating, verifying, and storing
-+# messages destined for the Translation Console, as well as for reading
-+# translations back and outputting them in some desired format.
-+#
-+# This has been stripped down to include only the functionality needed by grit
-+# for creating Windows .rc and .h files. These are the only parts needed by
-+# the Chrome build process.
-+
-+from __future__ import print_function
-+
-+from grit.extern import FP
-+
-+# This module assumes that within a bundle no two messages can have the
-+# same id unless they're identical.
-+
-+# The basic classes defined here for external use are Message and Translation,
-+# where the former is used for English messages and the latter for
-+# translations. These classes have a lot of common functionality, as expressed
-+# by the common parent class BaseMessage. Perhaps the most important
-+# distinction is that translated text is stored in UTF-8, whereas original text
-+# is stored in whatever encoding the client uses (presumably Latin-1).
-+
-+# --------------------
-+# The public interface
-+# --------------------
-+
-+# Generate message id from message text and meaning string (optional),
-+# both in utf-8 encoding
-+#
-+def GenerateMessageId(message, meaning=''):
-+ fp = FP.FingerPrint(message)
-+ if meaning:
-+ # combine the fingerprints of message and meaning
-+ fp2 = FP.FingerPrint(meaning)
-+ if fp < 0:
-+ fp = fp2 + (fp << 1) + 1
-+ else:
-+ fp = fp2 + (fp << 1)
-+ # To avoid negative ids we strip the high-order bit
-+ return str(fp & 0x7fffffffffffffff)
-+
-+# -------------------------------------------------------------------------
-+# The MessageTranslationError class is used to signal tclib-specific errors.
-+
-+
-+class MessageTranslationError(Exception):
-+
-+ def __init__(self, args = ''):
-+ self.args = args
-+
-+
-+# -----------------------------------------------------------
-+# The Placeholder class represents a placeholder in a message.
-+
-+class Placeholder(object):
-+ # String representation
-+ def __str__(self):
-+ return '%s, "%s", "%s"' % \
-+ (self.__presentation, self.__original, self.__example)
-+
-+ # Getters
-+ def GetOriginal(self):
-+ return self.__original
-+
-+ def GetPresentation(self):
-+ return self.__presentation
-+
-+ def GetExample(self):
-+ return self.__example
-+
-+ def __eq__(self, other):
-+ return self.EqualTo(other, strict=1, ignore_trailing_spaces=0)
-+
-+ # Equality test
-+ #
-+ # ignore_trailing_spaces: TC is using varchar to store the
-+ # phrwr fields, as a result of that, the trailing spaces
-+ # are removed by MySQL when the strings are stored into TC:-(
-+ # ignore_trailing_spaces parameter is used to ignore
-+ # trailing spaces during equivalence comparison.
-+ #
-+ def EqualTo(self, other, strict = 1, ignore_trailing_spaces = 1):
-+ if type(other) is not Placeholder:
-+ return 0
-+ if StringEquals(self.__presentation, other.__presentation,
-+ ignore_trailing_spaces):
-+ if not strict or (StringEquals(self.__original, other.__original,
-+ ignore_trailing_spaces) and
-+ StringEquals(self.__example, other.__example,
-+ ignore_trailing_spaces)):
-+ return 1
-+ return 0
-+
-+
-+# -----------------------------------------------------------------
-+# BaseMessage is the common parent class of Message and Translation.
-+# It is not meant for direct use.
-+
-+class BaseMessage(object):
-+ # Three types of message construction is supported. If the message text is a
-+ # simple string with no dynamic content, you can pass it to the constructor
-+ # as the "text" parameter. Otherwise, you can omit "text" and assemble the
-+ # message step by step using AppendText() and AppendPlaceholder(). Or, as an
-+ # alternative, you can give the constructor the "presentable" version of the
-+ # message and a list of placeholders; it will then parse the presentation and
-+ # build the message accordingly. For example:
-+ # Message(text = "There are NUM_BUGS bugs in your code",
-+ # placeholders = [Placeholder("NUM_BUGS", "%d", "33")],
-+ # description = "Bla bla bla")
-+ def __eq__(self, other):
-+ # "source encoding" is nonsense, so ignore it
-+ return _ObjectEquals(self, other, ['_BaseMessage__source_encoding'])
-+
-+ def GetName(self):
-+ return self.__name
-+
-+ def GetSourceEncoding(self):
-+ return self.__source_encoding
-+
-+ # Append a placeholder to the message
-+ def AppendPlaceholder(self, placeholder):
-+ if not isinstance(placeholder, Placeholder):
-+ raise MessageTranslationError("Invalid message placeholder %s in "
-+ "message %s" % (placeholder, self.GetId()))
-+ # Are there other placeholders with the same presentation?
-+ # If so, they need to be the same.
-+ for other in self.GetPlaceholders():
-+ if placeholder.GetPresentation() == other.GetPresentation():
-+ if not placeholder.EqualTo(other):
-+ raise MessageTranslationError(
-+ "Conflicting declarations of %s within message" %
-+ placeholder.GetPresentation())
-+ # update placeholder list
-+ dup = 0
-+ for item in self.__content:
-+ if isinstance(item, Placeholder) and placeholder.EqualTo(item):
-+ dup = 1
-+ break
-+ if not dup:
-+ self.__placeholders.append(placeholder)
-+
-+ # update content
-+ self.__content.append(placeholder)
-+
-+ # Strips leading and trailing whitespace, and returns a tuple
-+ # containing the leading and trailing space that was removed.
-+ def Strip(self):
-+ leading = trailing = ''
-+ if len(self.__content) > 0:
-+ s0 = self.__content[0]
-+ if not isinstance(s0, Placeholder):
-+ s = s0.lstrip()
-+ leading = s0[:-len(s)]
-+ self.__content[0] = s
-+
-+ s0 = self.__content[-1]
-+ if not isinstance(s0, Placeholder):
-+ s = s0.rstrip()
-+ trailing = s0[len(s):]
-+ self.__content[-1] = s
-+ return leading, trailing
-+
-+ # Return the id of this message
-+ def GetId(self):
-+ if self.__id is None:
-+ return self.GenerateId()
-+ return self.__id
-+
-+ # Set the id of this message
-+ def SetId(self, id):
-+ if id is None:
-+ self.__id = None
-+ else:
-+ self.__id = str(id) # Treat numerical ids as strings
-+
-+ # Return content of this message as a list (internal use only)
-+ def GetContent(self):
-+ return self.__content
-+
-+ # Return a human-readable version of this message
-+ def GetPresentableContent(self):
-+ presentable_content = ""
-+ for item in self.__content:
-+ if isinstance(item, Placeholder):
-+ presentable_content += item.GetPresentation()
-+ else:
-+ presentable_content += item
-+
-+ return presentable_content
-+
-+ # Return a fragment of a message in escaped format
-+ def EscapeFragment(self, fragment):
-+ return fragment.replace('%', '%%')
-+
-+ # Return the "original" version of this message, doing %-escaping
-+ # properly. If source_msg is specified, the placeholder original
-+ # information inside source_msg will be used instead.
-+ def GetOriginalContent(self, source_msg = None):
-+ original_content = ""
-+ for item in self.__content:
-+ if isinstance(item, Placeholder):
-+ if source_msg:
-+ ph = source_msg.GetPlaceholder(item.GetPresentation())
-+ if not ph:
-+ raise MessageTranslationError(
-+ "Placeholder %s doesn't exist in message: %s" %
-+ (item.GetPresentation(), source_msg))
-+ original_content += ph.GetOriginal()
-+ else:
-+ original_content += item.GetOriginal()
-+ else:
-+ original_content += self.EscapeFragment(item)
-+ return original_content
-+
-+ # Return the example of this message
-+ def GetExampleContent(self):
-+ example_content = ""
-+ for item in self.__content:
-+ if isinstance(item, Placeholder):
-+ example_content += item.GetExample()
-+ else:
-+ example_content += item
-+ return example_content
-+
-+ # Return a list of all unique placeholders in this message
-+ def GetPlaceholders(self):
-+ return self.__placeholders
-+
-+ # Return a placeholder in this message
-+ def GetPlaceholder(self, presentation):
-+ for item in self.__content:
-+ if (isinstance(item, Placeholder) and
-+ item.GetPresentation() == presentation):
-+ return item
-+ return None
-+
-+ # Return this message's description
-+ def GetDescription(self):
-+ return self.__description
-+
-+ # Add a message source
-+ def AddSource(self, source):
-+ self.__sources.append(source)
-+
-+ # Return this message's sources as a list
-+ def GetSources(self):
-+ return self.__sources
-+
-+ # Return this message's sources as a string
-+ def GetSourcesAsText(self, delimiter = "; "):
-+ return delimiter.join(self.__sources)
-+
-+ # Set the obsolete flag for a message (internal use only)
-+ def SetObsolete(self):
-+ self.__obsolete = 1
-+
-+ # Get the obsolete flag for a message (internal use only)
-+ def IsObsolete(self):
-+ return self.__obsolete
-+
-+ # Get the sequence number (0 by default)
-+ def GetSequenceNumber(self):
-+ return self.__sequence_number
-+
-+ # Set the sequence number
-+ def SetSequenceNumber(self, number):
-+ self.__sequence_number = number
-+
-+ # Increment instance counter
-+ def AddInstance(self):
-+ self.__num_instances += 1
-+
-+ # Return instance count
-+ def GetNumInstances(self):
-+ return self.__num_instances
-+
-+ def GetErrors(self, from_tc=0):
-+ """
-+ Returns a description of the problem if the message is not
-+ syntactically valid, or None if everything is fine.
-+
-+ Args:
-+ from_tc: indicates whether this message came from the TC. We let
-+ the TC get away with some things we normally wouldn't allow for
-+ historical reasons.
-+ """
-+ # check that placeholders are unambiguous
-+ pos = 0
-+ phs = {}
-+ for item in self.__content:
-+ if isinstance(item, Placeholder):
-+ phs[pos] = item
-+ pos += len(item.GetPresentation())
-+ else:
-+ pos += len(item)
-+ presentation = self.GetPresentableContent()
-+ for ph in self.GetPlaceholders():
-+ for pos in FindOverlapping(presentation, ph.GetPresentation()):
-+ # message contains the same text as a placeholder presentation
-+ other_ph = phs.get(pos)
-+ if ((not other_ph
-+ and not IsSubstringInPlaceholder(pos, len(ph.GetPresentation()), phs))
-+ or
-+ (other_ph and len(other_ph.GetPresentation()) < len(ph.GetPresentation()))):
-+ return "message contains placeholder name '%s':\n%s" % (
-+ ph.GetPresentation(), presentation)
-+ return None
-+
-+
-+ def __CopyTo(self, other):
-+ """
-+ Returns a copy of this BaseMessage.
-+ """
-+ assert isinstance(other, self.__class__) or isinstance(self, other.__class__)
-+ other.__source_encoding = self.__source_encoding
-+ other.__content = self.__content[:]
-+ other.__description = self.__description
-+ other.__id = self.__id
-+ other.__num_instances = self.__num_instances
-+ other.__obsolete = self.__obsolete
-+ other.__name = self.__name
-+ other.__placeholders = self.__placeholders[:]
-+ other.__sequence_number = self.__sequence_number
-+ other.__sources = self.__sources[:]
-+
-+ return other
-+
-+ def HasText(self):
-+ """Returns true iff this message has anything other than placeholders."""
-+ for item in self.__content:
-+ if not isinstance(item, Placeholder):
-+ return True
-+ return False
-+
-+# --------------------------------------------------------
-+# The Message class represents original (English) messages
-+
-+class Message(BaseMessage):
-+ # See BaseMessage constructor
-+ def __init__(self, source_encoding, text=None, id=None,
-+ description=None, meaning="", placeholders=None,
-+ source=None, sequence_number=0, clone_from=None,
-+ time_created=0, name=None, is_hidden = 0):
-+
-+ if clone_from is not None:
-+ BaseMessage.__init__(self, None, clone_from=clone_from)
-+ self.__meaning = clone_from.__meaning
-+ self.__time_created = clone_from.__time_created
-+ self.__is_hidden = clone_from.__is_hidden
-+ return
-+
-+ BaseMessage.__init__(self, source_encoding, text, id, description,
-+ placeholders, source, sequence_number,
-+ name=name)
-+ self.__meaning = meaning
-+ self.__time_created = time_created
-+ self.SetIsHidden(is_hidden)
-+
-+ # String representation
-+ def __str__(self):
-+ s = 'source: %s, id: %s, content: "%s", meaning: "%s", ' \
-+ 'description: "%s"' % \
-+ (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
-+ self.__meaning, self.GetDescription())
-+ if self.GetName() is not None:
-+ s += ', name: "%s"' % self.GetName()
-+ placeholders = self.GetPlaceholders()
-+ for i in range(len(placeholders)):
-+ s += ", placeholder[%d]: %s" % (i, placeholders[i])
-+ return s
-+
-+ # Strips leading and trailing whitespace, and returns a tuple
-+ # containing the leading and trailing space that was removed.
-+ def Strip(self):
-+ leading = trailing = ''
-+ content = self.GetContent()
-+ if len(content) > 0:
-+ s0 = content[0]
-+ if not isinstance(s0, Placeholder):
-+ s = s0.lstrip()
-+ leading = s0[:-len(s)]
-+ content[0] = s
-+
-+ s0 = content[-1]
-+ if not isinstance(s0, Placeholder):
-+ s = s0.rstrip()
-+ trailing = s0[len(s):]
-+ content[-1] = s
-+ return leading, trailing
-+
-+ # Generate an id by hashing message content
-+ def GenerateId(self):
-+ self.SetId(GenerateMessageId(self.GetPresentableContent(),
-+ self.__meaning))
-+ return self.GetId()
-+
-+ def GetMeaning(self):
-+ return self.__meaning
-+
-+ def GetTimeCreated(self):
-+ return self.__time_created
-+
-+ # Equality operator
-+ def EqualTo(self, other, strict = 1):
-+ # Check id, meaning, content
-+ if self.GetId() != other.GetId():
-+ return 0
-+ if self.__meaning != other.__meaning:
-+ return 0
-+ if self.GetPresentableContent() != other.GetPresentableContent():
-+ return 0
-+ # Check descriptions if comparison is strict
-+ if (strict and
-+ self.GetDescription() is not None and
-+ other.GetDescription() is not None and
-+ self.GetDescription() != other.GetDescription()):
-+ return 0
-+ # Check placeholders
-+ ph1 = self.GetPlaceholders()
-+ ph2 = other.GetPlaceholders()
-+ if len(ph1) != len(ph2):
-+ return 0
-+ for i in range(len(ph1)):
-+ if not ph1[i].EqualTo(ph2[i], strict):
-+ return 0
-+
-+ return 1
-+
-+ def Copy(self):
-+ """
-+ Returns a copy of this Message.
-+ """
-+ assert isinstance(self, Message)
-+ return Message(None, clone_from=self)
-+
-+ def SetIsHidden(self, is_hidden):
-+ """Sets whether this message should be hidden.
-+
-+ Args:
-+ is_hidden : 0 or 1 - if the message should be hidden, 0 otherwise
-+ """
-+ if is_hidden not in [0, 1]:
-+ raise MessageTranslationError("is_hidden must be 0 or 1, got %s")
-+ self.__is_hidden = is_hidden
-+
-+ def IsHidden(self):
-+ """Returns 1 if this message is hidden, and 0 otherwise."""
-+ return self.__is_hidden
-+
-+# ----------------------------------------------------
-+# The Translation class represents translated messages
-+
-+class Translation(BaseMessage):
-+ # See BaseMessage constructor
-+ def __init__(self, source_encoding, text=None, id=None,
-+ description=None, placeholders=None, source=None,
-+ sequence_number=0, clone_from=None, ignore_ph_errors=0,
-+ name=None):
-+ if clone_from is not None:
-+ BaseMessage.__init__(self, None, clone_from=clone_from)
-+ return
-+
-+ BaseMessage.__init__(self, source_encoding, text, id, description,
-+ placeholders, source, sequence_number,
-+ ignore_ph_errors=ignore_ph_errors, name=name)
-+
-+ # String representation
-+ def __str__(self):
-+ s = 'source: %s, id: %s, content: "%s", description: "%s"' % \
-+ (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
-+ self.GetDescription());
-+ placeholders = self.GetPlaceholders()
-+ for i in range(len(placeholders)):
-+ s += ", placeholder[%d]: %s" % (i, placeholders[i])
-+ return s
-+
-+ # Equality operator
-+ def EqualTo(self, other, strict=1):
-+ # Check id and content
-+ if self.GetId() != other.GetId():
-+ return 0
-+ if self.GetPresentableContent() != other.GetPresentableContent():
-+ return 0
-+ # Check placeholders
-+ ph1 = self.GetPlaceholders()
-+ ph2 = other.GetPlaceholders()
-+ if len(ph1) != len(ph2):
-+ return 0
-+ for i in range(len(ph1)):
-+ if not ph1[i].EqualTo(ph2[i], strict):
-+ return 0
-+
-+ return 1
-+
-+ def Copy(self):
-+ """
-+ Returns a copy of this Translation.
-+ """
-+ return Translation(None, clone_from=self)
-diff --git a/tools/grit/grit/format/__init__.py b/tools/grit/grit/format/__init__.py
-new file mode 100644
-index 0000000000..55d56b8cfd
---- /dev/null
-+++ b/tools/grit/grit/format/__init__.py
-@@ -0,0 +1,8 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Module grit.format
-+'''
-+
-+pass
-diff --git a/tools/grit/grit/format/android_xml.py b/tools/grit/grit/format/android_xml.py
-new file mode 100644
-index 0000000000..7eb288891f
---- /dev/null
-+++ b/tools/grit/grit/format/android_xml.py
-@@ -0,0 +1,212 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Produces localized strings.xml files for Android.
-+
-+In cases where an "android" type output file is requested in a grd, the classes
-+in android_xml will process the messages and translations to produce a valid
-+strings.xml that is properly localized with the specified language.
-+
-+For example if the following output tag were to be included in a grd file
-+ <outputs>
-+ ...
-+ <output filename="values-es/strings.xml" type="android" lang="es" />
-+ ...
-+ </outputs>
-+
-+for a grd file with the following messages:
-+
-+ <message name="IDS_HELLO" desc="Simple greeting">Hello</message>
-+ <message name="IDS_WORLD" desc="The world">world</message>
-+
-+and there existed an appropriate xtb file containing the Spanish translations,
-+then the output would be:
-+
-+ <?xml version="1.0" encoding="utf-8"?>
-+ <resources xmlns:android="http://schemas.android.com/apk/res/android">
-+ <string name="hello">"Hola"</string>
-+ <string name="world">"mundo"</string>
-+ </resources>
-+
-+which would be written to values-es/strings.xml and usable by the Android
-+resource framework.
-+
-+Advanced usage
-+--------------
-+
-+To process only certain messages in a grd file, tag each desired message by
-+adding "android_java" to formatter_data. Then set the environmental variable
-+ANDROID_JAVA_TAGGED_ONLY to "true" when building the grd file. For example:
-+
-+ <message name="IDS_HELLO" formatter_data="android_java">Hello</message>
-+
-+To generate Android plurals (aka "quantity strings"), use the ICU plural syntax
-+in the grd file. This will automatically be transformed into a <purals> element
-+in the output xml file. For example:
-+
-+ <message name="IDS_CATS">
-+ {NUM_CATS, plural,
-+ =1 {1 cat}
-+ other {# cats}}
-+ </message>
-+
-+ will produce
-+
-+ <plurals name="cats">
-+ <item quantity="one">1 Katze</item>
-+ <item quantity="other">%d Katzen</item>
-+ </plurals>
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+import xml.sax.saxutils
-+
-+from grit import lazy_re
-+from grit.node import message
-+
-+
-+# When this environmental variable has value "true", only tagged messages will
-+# be outputted.
-+_TAGGED_ONLY_ENV_VAR = 'ANDROID_JAVA_TAGGED_ONLY'
-+_TAGGED_ONLY_DEFAULT = False
-+
-+# In tagged-only mode, only messages with this tag will be ouputted.
-+_EMIT_TAG = 'android_java'
-+
-+_NAME_PATTERN = lazy_re.compile(r'IDS_(?P<name>[A-Z0-9_]+)\Z')
-+
-+# Most strings are output as a <string> element. Note the double quotes
-+# around the value to preserve whitespace.
-+_STRING_TEMPLATE = u'<string name="%s">"%s"</string>\n'
-+
-+# Some strings are output as a <plurals> element.
-+_PLURALS_TEMPLATE = '<plurals name="%s">\n%s</plurals>\n'
-+_PLURALS_ITEM_TEMPLATE = ' <item quantity="%s">%s</item>\n'
-+
-+# Matches e.g. "{HELLO, plural, HOW ARE YOU DOING}", while capturing
-+# "HOW ARE YOU DOING" in <items>.
-+_PLURALS_PATTERN = lazy_re.compile(r'\{[A-Z_]+,\s*plural,(?P<items>.*)\}$',
-+ flags=re.S)
-+
-+# Repeatedly matched against the <items> capture in _PLURALS_PATTERN,
-+# to match "<quantity>{<value>}".
-+_PLURALS_ITEM_PATTERN = lazy_re.compile(r'(?P<quantity>\S+?)\s*'
-+ r'\{(?P<value>.*?)\}')
-+_PLURALS_QUANTITY_MAP = {
-+ '=0': 'zero',
-+ 'zero': 'zero',
-+ '=1': 'one',
-+ 'one': 'one',
-+ '=2': 'two',
-+ 'two': 'two',
-+ 'few': 'few',
-+ 'many': 'many',
-+ 'other': 'other',
-+}
-+
-+
-+def Format(root, lang='en', output_dir='.'):
-+ yield ('<?xml version="1.0" encoding="utf-8"?>\n'
-+ '<resources '
-+ 'xmlns:android="http://schemas.android.com/apk/res/android">\n')
-+
-+ tagged_only = _TAGGED_ONLY_DEFAULT
-+ if _TAGGED_ONLY_ENV_VAR in os.environ:
-+ tagged_only = os.environ[_TAGGED_ONLY_ENV_VAR].lower()
-+ if tagged_only == 'true':
-+ tagged_only = True
-+ elif tagged_only == 'false':
-+ tagged_only = False
-+ else:
-+ raise Exception('env variable ANDROID_JAVA_TAGGED_ONLY must have value '
-+ 'true or false. Invalid value: %s' % tagged_only)
-+
-+ for item in root.ActiveDescendants():
-+ with item:
-+ if ShouldOutputNode(item, tagged_only):
-+ yield _FormatMessage(item, lang)
-+
-+ yield '</resources>\n'
-+
-+
-+def ShouldOutputNode(node, tagged_only):
-+ """Returns true if node should be outputted.
-+
-+ Args:
-+ node: a Node from the grd dom
-+ tagged_only: true, if only tagged messages should be outputted
-+ """
-+ return (isinstance(node, message.MessageNode) and
-+ (not tagged_only or _EMIT_TAG in node.formatter_data))
-+
-+
-+def _FormatPluralMessage(message):
-+ """Compiles ICU plural syntax to the body of an Android <plurals> element.
-+
-+ 1. In a .grd file, we can write a plural string like this:
-+
-+ <message name="IDS_THINGS">
-+ {NUM_THINGS, plural,
-+ =1 {1 thing}
-+ other {# things}}
-+ </message>
-+
-+ 2. The Android equivalent looks like this:
-+
-+ <plurals name="things">
-+ <item quantity="one">1 thing</item>
-+ <item quantity="other">%d things</item>
-+ </plurals>
-+
-+ This method takes the body of (1) and converts it to the body of (2).
-+
-+ If the message is *not* a plural string, this function returns `None`.
-+ If the message includes quantities without an equivalent format in Android,
-+ it raises an exception.
-+ """
-+ ret = {}
-+ plural_match = _PLURALS_PATTERN.match(message)
-+ if not plural_match:
-+ return None
-+ body_in = plural_match.group('items').strip()
-+ lines = []
-+ quantities_so_far = set()
-+ for item_match in _PLURALS_ITEM_PATTERN.finditer(body_in):
-+ quantity_in = item_match.group('quantity')
-+ quantity_out = _PLURALS_QUANTITY_MAP.get(quantity_in)
-+ value_in = item_match.group('value')
-+ value_out = '"' + value_in.replace('#', '%d') + '"'
-+ if quantity_out:
-+ # only one line per quantity out (https://crbug.com/787488)
-+ if quantity_out not in quantities_so_far:
-+ quantities_so_far.add(quantity_out)
-+ lines.append(_PLURALS_ITEM_TEMPLATE % (quantity_out, value_out))
-+ else:
-+ raise Exception('Unsupported plural quantity for android '
-+ 'strings.xml: %s' % quantity_in)
-+ return ''.join(lines)
-+
-+
-+def _FormatMessage(item, lang):
-+ """Writes out a single string as a <resource/> element."""
-+
-+ mangled_name = item.GetTextualIds()[0]
-+ match = _NAME_PATTERN.match(mangled_name)
-+ if not match:
-+ raise Exception('Unexpected resource name: %s' % mangled_name)
-+ name = match.group('name').lower()
-+
-+ value = item.ws_at_start + item.Translate(lang) + item.ws_at_end
-+ # Replace < > & with &lt; &gt; &amp; to ensure we generate valid XML and
-+ # replace ' " with \' \" to conform to Android's string formatting rules.
-+ value = xml.sax.saxutils.escape(value, {"'": "\\'", '"': '\\"'})
-+
-+ plurals = _FormatPluralMessage(value)
-+ if plurals:
-+ return _PLURALS_TEMPLATE % (name, plurals)
-+ else:
-+ return _STRING_TEMPLATE % (name, value)
-diff --git a/tools/grit/grit/format/android_xml_unittest.py b/tools/grit/grit/format/android_xml_unittest.py
-new file mode 100644
-index 0000000000..d9f476fddf
---- /dev/null
-+++ b/tools/grit/grit/format/android_xml_unittest.py
-@@ -0,0 +1,149 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Unittest for android_xml.py."""
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import unittest
-+
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+from six import StringIO
-+
-+from grit import util
-+from grit.format import android_xml
-+from grit.node import message
-+from grit.tool import build
-+
-+
-+class AndroidXmlUnittest(unittest.TestCase):
-+
-+ def testMessages(self):
-+ root = util.ParseGrdForUnittest(r"""
-+ <messages>
-+ <message name="IDS_SIMPLE" desc="A vanilla string">
-+ Martha
-+ </message>
-+ <message name="IDS_ONE_LINE" desc="On one line">sat and wondered</message>
-+ <message name="IDS_QUOTES" desc="A string with quotation marks">
-+ out loud, "Why don't I build a flying car?"
-+ </message>
-+ <message name="IDS_MULTILINE" desc="A string split over several lines">
-+ She gathered
-+wood, charcoal, and
-+a sledge hammer.
-+ </message>
-+ <message name="IDS_WHITESPACE" desc="A string with extra whitespace.">
-+ ''' How old fashioned -- she thought. '''
-+ </message>
-+ <message name="IDS_PLACEHOLDERS" desc="A string with placeholders">
-+ I'll buy a <ph name="WAVELENGTH">%d<ex>200</ex></ph> nm laser at <ph name="STORE_NAME">%s<ex>the grocery store</ex></ph>.
-+ </message>
-+ <message name="IDS_PLURALS" desc="A string using the ICU plural format">
-+ {NUM_THINGS, plural,
-+ =1 {Maybe I'll get one laser.}
-+ other {Maybe I'll get # lasers.}}
-+ </message>
-+ <message name="IDS_PLURALS_NO_SPACE" desc="A string using the ICU plural format with no space">
-+ {NUM_MISSISSIPPIS, plural,
-+ =1{OneMississippi}other{ManyMississippis}}
-+ </message>
-+ </messages>
-+ """)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('android', 'en'), buf)
-+ output = buf.getvalue()
-+ expected = r"""
-+<?xml version="1.0" encoding="utf-8"?>
-+<resources xmlns:android="http://schemas.android.com/apk/res/android">
-+<string name="simple">"Martha"</string>
-+<string name="one_line">"sat and wondered"</string>
-+<string name="quotes">"out loud, \"Why don\'t I build a flying car?\""</string>
-+<string name="multiline">"She gathered
-+wood, charcoal, and
-+a sledge hammer."</string>
-+<string name="whitespace">" How old fashioned -- she thought. "</string>
-+<string name="placeholders">"I\'ll buy a %d nm laser at %s."</string>
-+<plurals name="plurals">
-+ <item quantity="one">"Maybe I\'ll get one laser."</item>
-+ <item quantity="other">"Maybe I\'ll get %d lasers."</item>
-+</plurals>
-+<plurals name="plurals_no_space">
-+ <item quantity="one">"OneMississippi"</item>
-+ <item quantity="other">"ManyMississippis"</item>
-+</plurals>
-+</resources>
-+"""
-+ self.assertEqual(output.strip(), expected.strip())
-+
-+
-+ def testConflictingPlurals(self):
-+ root = util.ParseGrdForUnittest(r"""
-+ <messages>
-+ <message name="IDS_PLURALS" desc="A string using the ICU plural format">
-+ {NUM_THINGS, plural,
-+ =1 {Maybe I'll get one laser.}
-+ one {Maybe I'll get one laser.}
-+ other {Maybe I'll get # lasers.}}
-+ </message>
-+ </messages>
-+ """)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('android', 'en'), buf)
-+ output = buf.getvalue()
-+ expected = r"""
-+<?xml version="1.0" encoding="utf-8"?>
-+<resources xmlns:android="http://schemas.android.com/apk/res/android">
-+<plurals name="plurals">
-+ <item quantity="one">"Maybe I\'ll get one laser."</item>
-+ <item quantity="other">"Maybe I\'ll get %d lasers."</item>
-+</plurals>
-+</resources>
-+"""
-+ self.assertEqual(output.strip(), expected.strip())
-+
-+
-+ def testTaggedOnly(self):
-+ root = util.ParseGrdForUnittest(r"""
-+ <messages>
-+ <message name="IDS_HELLO" desc="" formatter_data="android_java">
-+ Hello
-+ </message>
-+ <message name="IDS_WORLD" desc="">
-+ world
-+ </message>
-+ </messages>
-+ """)
-+
-+ msg_hello, msg_world = root.GetChildrenOfType(message.MessageNode)
-+ self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=True))
-+ self.assertFalse(android_xml.ShouldOutputNode(msg_world, tagged_only=True))
-+ self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=False))
-+ self.assertTrue(android_xml.ShouldOutputNode(msg_world, tagged_only=False))
-+
-+
-+class DummyOutput(object):
-+
-+ def __init__(self, type, language):
-+ self.type = type
-+ self.language = language
-+
-+ def GetType(self):
-+ return self.type
-+
-+ def GetLanguage(self):
-+ return self.language
-+
-+ def GetOutputFilename(self):
-+ return 'hello.gif'
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/c_format.py b/tools/grit/grit/format/c_format.py
-new file mode 100644
-index 0000000000..16809a9f70
---- /dev/null
-+++ b/tools/grit/grit/format/c_format.py
-@@ -0,0 +1,95 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Formats as a .C file for compilation.
-+"""
-+
-+from __future__ import print_function
-+
-+import codecs
-+import os
-+import re
-+
-+import six
-+
-+from grit import util
-+
-+
-+def _FormatHeader(root, output_dir):
-+ """Returns the required preamble for C files."""
-+ # Find the location of the resource header file, so that we can include
-+ # it.
-+ resource_header = 'resource.h' # fall back to this
-+ for output in root.GetOutputFiles():
-+ if output.attrs['type'] == 'rc_header':
-+ resource_header = os.path.abspath(output.GetOutputFilename())
-+ resource_header = util.MakeRelativePath(output_dir, resource_header)
-+ return """// This file is automatically generated by GRIT. Do not edit.
-+
-+#include "%s"
-+
-+// All strings are UTF-8
-+""" % (resource_header)
-+# end _FormatHeader() function
-+
-+
-+def Format(root, lang='en', output_dir='.'):
-+ """Outputs a C switch statement representing the string table."""
-+ from grit.node import message
-+ assert isinstance(lang, six.string_types)
-+
-+ yield _FormatHeader(root, output_dir)
-+
-+ yield 'const char* GetString(int id) {\n switch (id) {'
-+
-+ for item in root.ActiveDescendants():
-+ with item:
-+ if isinstance(item, message.MessageNode):
-+ yield _FormatMessage(item, lang)
-+
-+ yield '\n default:\n return 0;\n }\n}\n'
-+
-+
-+def _HexToOct(match):
-+ "Return the octal form of the hex numbers"
-+ hex = match.group("hex")
-+ result = ""
-+ while len(hex):
-+ next_num = int(hex[2:4], 16)
-+ result += "\\" + '%03o' % next_num
-+ hex = hex[4:]
-+ return match.group("escaped_backslashes") + result
-+
-+
-+def _FormatMessage(item, lang):
-+ """Format a single <message> element."""
-+
-+ message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
-+ # Output message with non-ascii chars escaped as octal numbers C's grammar
-+ # allows escaped hexadecimal numbers to be infinite, but octal is always of
-+ # the form \OOO. Python 3 doesn't support string-escape, so we have to jump
-+ # through some hoops here via codecs.escape_encode.
-+ # This basically does:
-+ # - message - the starting string
-+ # - message.encode(...) - convert to bytes
-+ # - codecs.escape_encode(...) - convert non-ASCII bytes to \x## escapes
-+ # - (...).decode() - convert bytes back to a string
-+ message = codecs.escape_encode(message.encode('utf-8'))[0].decode('utf-8')
-+ # an escaped char is (\xHH)+ but only if the initial
-+ # backslash is not escaped.
-+ not_a_backslash = r"(^|[^\\])" # beginning of line or a non-backslash char
-+ escaped_backslashes = not_a_backslash + r"(\\\\)*"
-+ hex_digits = r"((\\x)[0-9a-f]{2})+"
-+ two_digit_hex_num = re.compile(
-+ r"(?P<escaped_backslashes>%s)(?P<hex>%s)"
-+ % (escaped_backslashes, hex_digits))
-+ message = two_digit_hex_num.sub(_HexToOct, message)
-+ # unescape \ (convert \\ back to \)
-+ message = message.replace('\\\\', '\\')
-+ message = message.replace('"', '\\"')
-+ message = util.LINEBREAKS.sub(r'\\n', message)
-+
-+ name_attr = item.GetTextualIds()[0]
-+
-+ return '\n case %s:\n return "%s";' % (name_attr, message)
-diff --git a/tools/grit/grit/format/c_format_unittest.py b/tools/grit/grit/format/c_format_unittest.py
-new file mode 100644
-index 0000000000..380120c42f
---- /dev/null
-+++ b/tools/grit/grit/format/c_format_unittest.py
-@@ -0,0 +1,81 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Unittest for c_format.py.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import util
-+from grit.tool import build
-+
-+
-+class CFormatUnittest(unittest.TestCase):
-+
-+ def testMessages(self):
-+ root = util.ParseGrdForUnittest(u"""
-+ <messages>
-+ <message name="IDS_QUESTIONS">Do you want to play questions?</message>
-+ <message name="IDS_QUOTES">
-+ "What's in a name, <ph name="NAME">%s<ex>Brandon</ex></ph>?"
-+ </message>
-+ <message name="IDS_LINE_BREAKS">
-+ Was that rhetoric?
-+No.
-+Statement. Two all. Game point.
-+</message>
-+ <message name="IDS_NON_ASCII">
-+ \u00f5\\xc2\\xa4\\\u00a4\\\\xc3\\xb5\u4924
-+ </message>
-+ </messages>
-+ """)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('c_format', 'en'), buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+ self.assertEqual(u"""\
-+#include "resource.h"
-+const char* GetString(int id) {
-+ switch (id) {
-+ case IDS_QUESTIONS:
-+ return "Do you want to play questions?";
-+ case IDS_QUOTES:
-+ return "\\"What\\'s in a name, %s?\\"";
-+ case IDS_LINE_BREAKS:
-+ return "Was that rhetoric?\\nNo.\\nStatement. Two all. Game point.";
-+ case IDS_NON_ASCII:
-+ return "\\303\\265\\xc2\\xa4\\\\302\\244\\\\xc3\\xb5\\344\\244\\244";
-+ default:
-+ return 0;
-+ }
-+}""", output)
-+
-+
-+class DummyOutput(object):
-+
-+ def __init__(self, type, language):
-+ self.type = type
-+ self.language = language
-+
-+ def GetType(self):
-+ return self.type
-+
-+ def GetLanguage(self):
-+ return self.language
-+
-+ def GetOutputFilename(self):
-+ return 'hello.gif'
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/chrome_messages_json.py b/tools/grit/grit/format/chrome_messages_json.py
-new file mode 100644
-index 0000000000..88ec1d914b
---- /dev/null
-+++ b/tools/grit/grit/format/chrome_messages_json.py
-@@ -0,0 +1,59 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Formats as a .json file that can be used to localize Google Chrome
-+extensions."""
-+
-+from __future__ import print_function
-+
-+from json import JSONEncoder
-+
-+from grit import constants
-+from grit.node import message
-+
-+def Format(root, lang='en', output_dir='.'):
-+ """Format the messages as JSON."""
-+ yield '{'
-+
-+ encoder = JSONEncoder(ensure_ascii=False)
-+ format = '"%s":{"message":%s%s}'
-+ placeholder_format = '"%i":{"content":"$%i"}'
-+ first = True
-+ for child in root.ActiveDescendants():
-+ if isinstance(child, message.MessageNode):
-+ id = child.attrs['name']
-+ if id.startswith('IDR_') or id.startswith('IDS_'):
-+ id = id[4:]
-+
-+ translation_missing = child.GetCliques()[0].clique.get(lang) is None;
-+ if (child.ShouldFallbackToEnglish() and translation_missing and
-+ lang != constants.FAKE_BIDI):
-+ # Skip the string if it's not translated. Chrome will fallback
-+ # to English automatically.
-+ continue
-+
-+ loc_message = encoder.encode(child.ws_at_start + child.Translate(lang) +
-+ child.ws_at_end)
-+
-+ # Replace $n place-holders with $n$ and add an appropriate "placeholders"
-+ # entry. Note that chrome.i18n.getMessage only supports 9 placeholders:
-+ # https://developer.chrome.com/extensions/i18n#method-getMessage
-+ placeholders = ''
-+ for i in range(1, 10):
-+ if loc_message.find('$%d' % i) == -1:
-+ break
-+ loc_message = loc_message.replace('$%d' % i, '$%d$' % i)
-+ if placeholders:
-+ placeholders += ','
-+ placeholders += placeholder_format % (i, i)
-+
-+ if not first:
-+ yield ','
-+ first = False
-+
-+ if placeholders:
-+ placeholders = ',"placeholders":{%s}' % placeholders
-+ yield format % (id, loc_message, placeholders)
-+
-+ yield '}'
-diff --git a/tools/grit/grit/format/chrome_messages_json_unittest.py b/tools/grit/grit/format/chrome_messages_json_unittest.py
-new file mode 100644
-index 0000000000..a54e6bdc1c
---- /dev/null
-+++ b/tools/grit/grit/format/chrome_messages_json_unittest.py
-@@ -0,0 +1,190 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Unittest for chrome_messages_json.py.
-+"""
-+
-+from __future__ import print_function
-+
-+import json
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import grd_reader
-+from grit import util
-+from grit.tool import build
-+
-+class ChromeMessagesJsonFormatUnittest(unittest.TestCase):
-+
-+ # The default unittest diff limit is too low for our unittests.
-+ # Allow the framework to show the full diff output all the time.
-+ maxDiff = None
-+
-+ def testMessages(self):
-+ root = util.ParseGrdForUnittest(u"""
-+ <messages>
-+ <message name="IDS_SIMPLE_MESSAGE">
-+ Simple message.
-+ </message>
-+ <message name="IDS_QUOTES">
-+ element\u2019s \u201c<ph name="NAME">%s<ex>name</ex></ph>\u201d attribute
-+ </message>
-+ <message name="IDS_PLACEHOLDERS">
-+ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
-+ </message>
-+ <message name="IDS_PLACEHOLDERS_SUBSTITUTED_BY_GETMESSAGE">
-+ <ph name="BEGIN">$1<ex>a</ex></ph>test<ph name="END">$2<ex>b</ex></ph>
-+ </message>
-+ <message name="IDS_STARTS_WITH_SPACE">
-+ ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
-+ </message>
-+ <message name="IDS_ENDS_WITH_SPACE">
-+ (<ph name="COUNT">%d<ex>2</ex></ph>) '''
-+ </message>
-+ <message name="IDS_SPACE_AT_BOTH_ENDS">
-+ ''' (<ph name="COUNT">%d<ex>2</ex></ph>) '''
-+ </message>
-+ <message name="IDS_DOUBLE_QUOTES">
-+ A "double quoted" message.
-+ </message>
-+ <message name="IDS_BACKSLASH">
-+ \\
-+ </message>
-+ </messages>
-+ """)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'en'),
-+ buf)
-+ output = buf.getvalue()
-+ test = u"""
-+{
-+ "SIMPLE_MESSAGE": {
-+ "message": "Simple message."
-+ },
-+ "QUOTES": {
-+ "message": "element\u2019s \u201c%s\u201d attribute"
-+ },
-+ "PLACEHOLDERS": {
-+ "message": "%1$d error, %2$d warning"
-+ },
-+ "PLACEHOLDERS_SUBSTITUTED_BY_GETMESSAGE": {
-+ "message": "$1$test$2$",
-+ "placeholders": {
-+ "1": {
-+ "content": "$1"
-+ },
-+ "2": {
-+ "content": "$2"
-+ }
-+ }
-+ },
-+ "STARTS_WITH_SPACE": {
-+ "message": " (%d)"
-+ },
-+ "ENDS_WITH_SPACE": {
-+ "message": "(%d) "
-+ },
-+ "SPACE_AT_BOTH_ENDS": {
-+ "message": " (%d) "
-+ },
-+ "DOUBLE_QUOTES": {
-+ "message": "A \\"double quoted\\" message."
-+ },
-+ "BACKSLASH": {
-+ "message": "\\\\"
-+ }
-+}
-+"""
-+ self.assertEqual(json.loads(test), json.loads(output))
-+
-+ def testTranslations(self):
-+ root = util.ParseGrdForUnittest("""
-+ <messages>
-+ <message name="ID_HELLO">Hello!</message>
-+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
-+ Joi</ex></ph></message>
-+ </messages>
-+ """)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'fr'),
-+ buf)
-+ output = buf.getvalue()
-+ test = u"""
-+{
-+ "ID_HELLO": {
-+ "message": "H\u00e9P\u00e9ll\u00f4P\u00f4!"
-+ },
-+ "ID_HELLO_USER": {
-+ "message": "H\u00e9P\u00e9ll\u00f4P\u00f4 %s"
-+ }
-+}
-+"""
-+ self.assertEqual(json.loads(test), json.loads(output))
-+
-+ def testSkipMissingTranslations(self):
-+ grd = """<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" current_release="3" source_lang_id="en"
-+ base_dir="%s">
-+ <outputs>
-+ </outputs>
-+ <release seq="3" allow_pseudo="False">
-+ <messages fallback_to_english="true">
-+ <message name="ID_HELLO_NO_TRANSLATION">Hello not translated</message>
-+ </messages>
-+ </release>
-+</grit>"""
-+ root = grd_reader.Parse(StringIO(grd), dir=".")
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'fr'),
-+ buf)
-+ output = buf.getvalue()
-+ test = u'{}'
-+ self.assertEqual(test, output)
-+
-+ def testVerifyMinification(self):
-+ root = util.ParseGrdForUnittest(u"""
-+ <messages>
-+ <message name="IDS">
-+ <ph name="BEGIN">$1<ex>a</ex></ph>test<ph name="END">$2<ex>b</ex></ph>
-+ </message>
-+ </messages>
-+ """)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'en'),
-+ buf)
-+ output = buf.getvalue()
-+ test = (u'{"IDS":{"message":"$1$test$2$","placeholders":'
-+ u'{"1":{"content":"$1"},"2":{"content":"$2"}}}}')
-+ self.assertEqual(test, output)
-+
-+
-+class DummyOutput(object):
-+
-+ def __init__(self, type, language):
-+ self.type = type
-+ self.language = language
-+
-+ def GetType(self):
-+ return self.type
-+
-+ def GetLanguage(self):
-+ return self.language
-+
-+ def GetOutputFilename(self):
-+ return 'hello.gif'
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/data_pack.py b/tools/grit/grit/format/data_pack.py
-new file mode 100644
-index 0000000000..f7128a4725
---- /dev/null
-+++ b/tools/grit/grit/format/data_pack.py
-@@ -0,0 +1,321 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Support for formatting a data pack file used for platform agnostic resource
-+files.
-+"""
-+
-+from __future__ import print_function
-+
-+import collections
-+import os
-+import struct
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import six
-+
-+from grit import util
-+from grit.node import include
-+from grit.node import message
-+from grit.node import structure
-+
-+
-+PACK_FILE_VERSION = 5
-+BINARY, UTF8, UTF16 = range(3)
-+
-+
-+GrdInfoItem = collections.namedtuple('GrdInfoItem',
-+ ['textual_id', 'id', 'path'])
-+
-+
-+class WrongFileVersion(Exception):
-+ pass
-+
-+
-+class CorruptDataPack(Exception):
-+ pass
-+
-+
-+class DataPackSizes(object):
-+ def __init__(self, header, id_table, alias_table, data):
-+ self.header = header
-+ self.id_table = id_table
-+ self.alias_table = alias_table
-+ self.data = data
-+
-+ @property
-+ def total(self):
-+ return sum(v for v in self.__dict__.values())
-+
-+ def __iter__(self):
-+ yield ('header', self.header)
-+ yield ('id_table', self.id_table)
-+ yield ('alias_table', self.alias_table)
-+ yield ('data', self.data)
-+
-+ def __eq__(self, other):
-+ return self.__dict__ == other.__dict__
-+
-+ def __repr__(self):
-+ return self.__class__.__name__ + repr(self.__dict__)
-+
-+
-+class DataPackContents(object):
-+ def __init__(self, resources, encoding, version, aliases, sizes):
-+ # Map of resource_id -> str.
-+ self.resources = resources
-+ # Encoding (int).
-+ self.encoding = encoding
-+ # Version (int).
-+ self.version = version
-+ # Map of resource_id->canonical_resource_id
-+ self.aliases = aliases
-+ # DataPackSizes instance.
-+ self.sizes = sizes
-+
-+
-+def Format(root, lang='en', output_dir='.'):
-+ """Writes out the data pack file format (platform agnostic resource file)."""
-+ id_map = root.GetIdMap()
-+ data = {}
-+ root.info = []
-+ for node in root.ActiveDescendants():
-+ with node:
-+ if isinstance(node, (include.IncludeNode, message.MessageNode,
-+ structure.StructureNode)):
-+ value = node.GetDataPackValue(lang, util.BINARY)
-+ if value is not None:
-+ resource_id = id_map[node.GetTextualIds()[0]]
-+ data[resource_id] = value
-+ root.info.append('{},{},{}'.format(
-+ node.attrs.get('name'), resource_id, node.source))
-+ return WriteDataPackToString(data, UTF8)
-+
-+
-+def ReadDataPack(input_file):
-+ return ReadDataPackFromString(util.ReadFile(input_file, util.BINARY))
-+
-+
-+def ReadDataPackFromString(data):
-+ """Reads a data pack file and returns a dictionary."""
-+ # Read the header.
-+ version = struct.unpack('<I', data[:4])[0]
-+ if version == 4:
-+ resource_count, encoding = struct.unpack('<IB', data[4:9])
-+ alias_count = 0
-+ header_size = 9
-+ elif version == 5:
-+ encoding, resource_count, alias_count = struct.unpack('<BxxxHH', data[4:12])
-+ header_size = 12
-+ else:
-+ raise WrongFileVersion('Found version: ' + str(version))
-+
-+ resources = {}
-+ kIndexEntrySize = 2 + 4 # Each entry is a uint16 and a uint32.
-+ def entry_at_index(idx):
-+ offset = header_size + idx * kIndexEntrySize
-+ return struct.unpack('<HI', data[offset:offset + kIndexEntrySize])
-+
-+ prev_resource_id, prev_offset = entry_at_index(0)
-+ for i in range(1, resource_count + 1):
-+ resource_id, offset = entry_at_index(i)
-+ resources[prev_resource_id] = data[prev_offset:offset]
-+ prev_resource_id, prev_offset = resource_id, offset
-+
-+ id_table_size = (resource_count + 1) * kIndexEntrySize
-+ # Read the alias table.
-+ kAliasEntrySize = 2 + 2 # uint16, uint16
-+ def alias_at_index(idx):
-+ offset = header_size + id_table_size + idx * kAliasEntrySize
-+ return struct.unpack('<HH', data[offset:offset + kAliasEntrySize])
-+
-+ aliases = {}
-+ for i in range(alias_count):
-+ resource_id, index = alias_at_index(i)
-+ aliased_id = entry_at_index(index)[0]
-+ aliases[resource_id] = aliased_id
-+ resources[resource_id] = resources[aliased_id]
-+
-+ alias_table_size = kAliasEntrySize * alias_count
-+ sizes = DataPackSizes(
-+ header_size, id_table_size, alias_table_size,
-+ len(data) - header_size - id_table_size - alias_table_size)
-+ assert sizes.total == len(data), 'original={} computed={}'.format(
-+ len(data), sizes.total)
-+ return DataPackContents(resources, encoding, version, aliases, sizes)
-+
-+
-+def WriteDataPackToString(resources, encoding):
-+ """Returns bytes with a map of id=>data in the data pack format."""
-+ ret = []
-+
-+ # Compute alias map.
-+ resource_ids = sorted(resources)
-+ # Use reversed() so that for duplicates lower IDs clobber higher ones.
-+ id_by_data = {resources[k]: k for k in reversed(resource_ids)}
-+ # Map of resource_id -> resource_id, where value < key.
-+ alias_map = {k: id_by_data[v] for k, v in resources.items()
-+ if id_by_data[v] != k}
-+
-+ # Write file header.
-+ resource_count = len(resources) - len(alias_map)
-+ # Padding bytes added for alignment.
-+ ret.append(struct.pack('<IBxxxHH', PACK_FILE_VERSION, encoding,
-+ resource_count, len(alias_map)))
-+ HEADER_LENGTH = 4 + 4 + 2 + 2
-+
-+ # Each main table entry is: uint16 + uint32 (and an extra entry at the end).
-+ # Each alias table entry is: uint16 + uint16.
-+ data_offset = HEADER_LENGTH + (resource_count + 1) * 6 + len(alias_map) * 4
-+
-+ # Write main table.
-+ index_by_id = {}
-+ deduped_data = []
-+ index = 0
-+ for resource_id in resource_ids:
-+ if resource_id in alias_map:
-+ continue
-+ data = resources[resource_id]
-+ if isinstance(data, six.text_type):
-+ data = data.encode('utf-8')
-+ index_by_id[resource_id] = index
-+ ret.append(struct.pack('<HI', resource_id, data_offset))
-+ data_offset += len(data)
-+ deduped_data.append(data)
-+ index += 1
-+
-+ assert index == resource_count
-+ # Add an extra entry at the end.
-+ ret.append(struct.pack('<HI', 0, data_offset))
-+
-+ # Write alias table.
-+ for resource_id in sorted(alias_map):
-+ index = index_by_id[alias_map[resource_id]]
-+ ret.append(struct.pack('<HH', resource_id, index))
-+
-+ # Write data.
-+ ret.extend(deduped_data)
-+ return b''.join(ret)
-+
-+
-+def WriteDataPack(resources, output_file, encoding):
-+ """Writes a map of id=>data into output_file as a data pack."""
-+ content = WriteDataPackToString(resources, encoding)
-+ with open(output_file, 'wb') as file:
-+ file.write(content)
-+
-+
-+def ReadGrdInfo(grd_file):
-+ info_dict = {}
-+ with open(grd_file + '.info', 'rt') as f:
-+ for line in f:
-+ item = GrdInfoItem._make(line.strip().split(','))
-+ info_dict[int(item.id)] = item
-+ return info_dict
-+
-+
-+def RePack(output_file, input_files, whitelist_file=None,
-+ suppress_removed_key_output=False,
-+ output_info_filepath=None):
-+ """Write a new data pack file by combining input pack files.
-+
-+ Args:
-+ output_file: path to the new data pack file.
-+ input_files: a list of paths to the data pack files to combine.
-+ whitelist_file: path to the file that contains the list of resource IDs
-+ that should be kept in the output file or None to include
-+ all resources.
-+ suppress_removed_key_output: allows the caller to suppress the output from
-+ RePackFromDataPackStrings.
-+ output_info_file: If not None, specify the output .info filepath.
-+
-+ Raises:
-+ KeyError: if there are duplicate keys or resource encoding is
-+ inconsistent.
-+ """
-+ input_data_packs = [ReadDataPack(filename) for filename in input_files]
-+ input_info_files = [filename + '.info' for filename in input_files]
-+ whitelist = None
-+ if whitelist_file:
-+ lines = util.ReadFile(whitelist_file, 'utf-8').strip().splitlines()
-+ if not lines:
-+ raise Exception('Whitelist file should not be empty')
-+ whitelist = set(int(x) for x in lines)
-+ inputs = [(p.resources, p.encoding) for p in input_data_packs]
-+ resources, encoding = RePackFromDataPackStrings(
-+ inputs, whitelist, suppress_removed_key_output)
-+ WriteDataPack(resources, output_file, encoding)
-+ if output_info_filepath is None:
-+ output_info_filepath = output_file + '.info'
-+ with open(output_info_filepath, 'w') as output_info_file:
-+ for filename in input_info_files:
-+ with open(filename, 'r') as info_file:
-+ output_info_file.writelines(info_file.readlines())
-+
-+
-+def RePackFromDataPackStrings(inputs, whitelist,
-+ suppress_removed_key_output=False):
-+ """Combines all inputs into one.
-+
-+ Args:
-+ inputs: a list of (resources_by_id, encoding) tuples to be combined.
-+ whitelist: a list of resource IDs that should be kept in the output string
-+ or None to include all resources.
-+ suppress_removed_key_output: Do not print removed keys.
-+
-+ Returns:
-+ Returns (resources_by_id, encoding).
-+
-+ Raises:
-+ KeyError: if there are duplicate keys or resource encoding is
-+ inconsistent.
-+ """
-+ resources = {}
-+ encoding = None
-+ for input_resources, input_encoding in inputs:
-+ # Make sure we have no dups.
-+ duplicate_keys = set(input_resources.keys()) & set(resources.keys())
-+ if duplicate_keys:
-+ raise KeyError('Duplicate keys: ' + str(list(duplicate_keys)))
-+
-+ # Make sure encoding is consistent.
-+ if encoding in (None, BINARY):
-+ encoding = input_encoding
-+ elif input_encoding not in (BINARY, encoding):
-+ raise KeyError('Inconsistent encodings: ' + str(encoding) +
-+ ' vs ' + str(input_encoding))
-+
-+ if whitelist:
-+ whitelisted_resources = dict([(key, input_resources[key])
-+ for key in input_resources.keys()
-+ if key in whitelist])
-+ resources.update(whitelisted_resources)
-+ removed_keys = [key for key in input_resources.keys()
-+ if key not in whitelist]
-+ if not suppress_removed_key_output:
-+ for key in removed_keys:
-+ print('RePackFromDataPackStrings Removed Key:', key)
-+ else:
-+ resources.update(input_resources)
-+
-+ # Encoding is 0 for BINARY, 1 for UTF8 and 2 for UTF16
-+ if encoding is None:
-+ encoding = BINARY
-+ return resources, encoding
-+
-+
-+def main():
-+ # Write a simple file.
-+ data = {1: '', 4: 'this is id 4', 6: 'this is id 6', 10: ''}
-+ WriteDataPack(data, 'datapack1.pak', UTF8)
-+ data2 = {1000: 'test', 5: 'five'}
-+ WriteDataPack(data2, 'datapack2.pak', UTF8)
-+ print('wrote datapack1 and datapack2 to current directory.')
-+
-+
-+if __name__ == '__main__':
-+ main()
-diff --git a/tools/grit/grit/format/data_pack_unittest.py b/tools/grit/grit/format/data_pack_unittest.py
-new file mode 100644
-index 0000000000..fcd7035473
---- /dev/null
-+++ b/tools/grit/grit/format/data_pack_unittest.py
-@@ -0,0 +1,102 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.format.data_pack'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit.format import data_pack
-+
-+
-+class FormatDataPackUnittest(unittest.TestCase):
-+ def testReadDataPackV4(self):
-+ expected_data = (
-+ b'\x04\x00\x00\x00' # header(version
-+ b'\x04\x00\x00\x00' # no. entries,
-+ b'\x01' # encoding)
-+ b'\x01\x00\x27\x00\x00\x00' # index entry 1
-+ b'\x04\x00\x27\x00\x00\x00' # index entry 4
-+ b'\x06\x00\x33\x00\x00\x00' # index entry 6
-+ b'\x0a\x00\x3f\x00\x00\x00' # index entry 10
-+ b'\x00\x00\x3f\x00\x00\x00' # extra entry for the size of last
-+ b'this is id 4this is id 6') # data
-+ expected_data_pack = data_pack.DataPackContents(
-+ {
-+ 1: b'',
-+ 4: b'this is id 4',
-+ 6: b'this is id 6',
-+ 10: b'',
-+ }, data_pack.UTF8, 4, {}, data_pack.DataPackSizes(9, 30, 0, 24))
-+ loaded = data_pack.ReadDataPackFromString(expected_data)
-+ self.assertDictEqual(expected_data_pack.__dict__, loaded.__dict__)
-+
-+ def testReadWriteDataPackV5(self):
-+ expected_data = (
-+ b'\x05\x00\x00\x00' # version
-+ b'\x01\x00\x00\x00' # encoding & padding
-+ b'\x03\x00' # resource_count
-+ b'\x01\x00' # alias_count
-+ b'\x01\x00\x28\x00\x00\x00' # index entry 1
-+ b'\x04\x00\x28\x00\x00\x00' # index entry 4
-+ b'\x06\x00\x34\x00\x00\x00' # index entry 6
-+ b'\x00\x00\x40\x00\x00\x00' # extra entry for the size of last
-+ b'\x0a\x00\x01\x00' # alias table
-+ b'this is id 4this is id 6') # data
-+ input_resources = {
-+ 1: b'',
-+ 4: b'this is id 4',
-+ 6: b'this is id 6',
-+ 10: b'this is id 4',
-+ }
-+ data = data_pack.WriteDataPackToString(input_resources, data_pack.UTF8)
-+ self.assertEquals(data, expected_data)
-+
-+ expected_data_pack = data_pack.DataPackContents({
-+ 1: b'',
-+ 4: input_resources[4],
-+ 6: input_resources[6],
-+ 10: input_resources[4],
-+ }, data_pack.UTF8, 5, {10: 4}, data_pack.DataPackSizes(12, 24, 4, 24))
-+ loaded = data_pack.ReadDataPackFromString(expected_data)
-+ self.assertDictEqual(expected_data_pack.__dict__, loaded.__dict__)
-+
-+ def testRePackUnittest(self):
-+ expected_with_whitelist = {
-+ 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let',
-+ 30: 'you down', 40: 'Never', 50: 'gonna run around and',
-+ 60: 'desert you'}
-+ expected_without_whitelist = {
-+ 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let', 65: 'Close',
-+ 30: 'you down', 40: 'Never', 50: 'gonna run around and', 4: 'click',
-+ 60: 'desert you', 6: 'chirr', 32: 'oops, try again', 70: 'Awww, snap!'}
-+ inputs = [{1: 'Never gonna', 4: 'click', 6: 'chirr', 10: 'give you up'},
-+ {20: 'Never gonna let', 30: 'you down', 32: 'oops, try again'},
-+ {40: 'Never', 50: 'gonna run around and', 60: 'desert you'},
-+ {65: 'Close', 70: 'Awww, snap!'}]
-+ whitelist = [1, 10, 20, 30, 40, 50, 60]
-+ inputs = [(i, data_pack.UTF8) for i in inputs]
-+
-+ # RePack using whitelist
-+ output, _ = data_pack.RePackFromDataPackStrings(
-+ inputs, whitelist, suppress_removed_key_output=True)
-+ self.assertDictEqual(expected_with_whitelist, output,
-+ 'Incorrect resource output')
-+
-+ # RePack a None whitelist
-+ output, _ = data_pack.RePackFromDataPackStrings(
-+ inputs, None, suppress_removed_key_output=True)
-+ self.assertDictEqual(expected_without_whitelist, output,
-+ 'Incorrect resource output')
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/gen_predetermined_ids.py b/tools/grit/grit/format/gen_predetermined_ids.py
-new file mode 100644
-index 0000000000..9b2aa7b1a5
---- /dev/null
-+++ b/tools/grit/grit/format/gen_predetermined_ids.py
-@@ -0,0 +1,144 @@
-+#!/usr/bin/env python
-+# Copyright 2017 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""
-+A tool to generate a predetermined resource ids file that can be used as an
-+input to grit via the -p option. This is meant to be run manually every once in
-+a while and its output checked in. See tools/gritsettings/README.md for details.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+import sys
-+
-+# Regular expression for parsing the #define macro format. Matches both the
-+# version of the macro with whitelist support and the one without. For example,
-+# Without generate whitelist flag:
-+# #define IDS_FOO_MESSAGE 1234
-+# With generate whitelist flag:
-+# #define IDS_FOO_MESSAGE (::ui::WhitelistedResource<1234>(), 1234)
-+RESOURCE_EXTRACT_REGEX = re.compile(r'^#define (\S*).* (\d+)\)?$', re.MULTILINE)
-+
-+ORDERED_RESOURCE_IDS_REGEX = re.compile(r'^Resource=(\d*)$', re.MULTILINE)
-+
-+
-+def _GetResourceNameIdPairsIter(string_to_scan):
-+ """Gets an iterator of the resource name and id pairs of the given string.
-+
-+ Scans the input string for lines of the form "#define NAME ID" and returns
-+ an iterator over all matching (NAME, ID) pairs.
-+
-+ Args:
-+ string_to_scan: The input string to scan.
-+
-+ Yields:
-+ A tuple of name and id.
-+ """
-+ for match in RESOURCE_EXTRACT_REGEX.finditer(string_to_scan):
-+ yield match.group(1, 2)
-+
-+
-+def _ReadOrderedResourceIds(path):
-+ """Reads ordered resource ids from the given file.
-+
-+ The resources are expected to be of the format produced by running Chrome
-+ with --print-resource-ids command line.
-+
-+ Args:
-+ path: File path to read resource ids from.
-+
-+ Returns:
-+ An array of ordered resource ids.
-+ """
-+ ordered_resource_ids = []
-+ with open(path, "r") as f:
-+ for match in ORDERED_RESOURCE_IDS_REGEX.finditer(f.read()):
-+ ordered_resource_ids.append(int(match.group(1)))
-+ return ordered_resource_ids
-+
-+
-+def GenerateResourceMapping(original_resources, ordered_resource_ids):
-+ """Generates a resource mapping from the ordered ids and the original mapping.
-+
-+ The returned dict will assign new ids to ordered_resource_ids numerically
-+ increasing from 101.
-+
-+ Args:
-+ original_resources: A dict of original resource ids to resource names.
-+ ordered_resource_ids: An array of ordered resource ids.
-+
-+ Returns:
-+ A dict of resource ids to resource names.
-+ """
-+ output_resource_map = {}
-+ # 101 is used as the starting value since other parts of GRIT require it to be
-+ # the minimum (e.g. rc_header.py) based on Windows resource numbering.
-+ next_id = 101
-+ for original_id in ordered_resource_ids:
-+ resource_name = original_resources[original_id]
-+ output_resource_map[next_id] = resource_name
-+ next_id += 1
-+ return output_resource_map
-+
-+
-+def ReadResourceIdsFromFile(file, original_resources):
-+ """Reads resource ids from a GRIT-produced header file.
-+
-+ Args:
-+ file: File to a GRIT-produced header file to read from.
-+ original_resources: Dict of resource ids to resource names to add to.
-+ """
-+ for resource_name, resource_id in _GetResourceNameIdPairsIter(file.read()):
-+ original_resources[int(resource_id)] = resource_name
-+
-+
-+def _ReadOriginalResourceIds(out_dir):
-+ """Reads resource ids from GRIT header files in the specified directory.
-+
-+ Args:
-+ out_dir: A Chrome build output directory (e.g. out/gn) to scan.
-+
-+ Returns:
-+ A dict of resource ids to resource names.
-+ """
-+ original_resources = {}
-+ for root, dirnames, filenames in os.walk(out_dir + '/gen'):
-+ for filename in filenames:
-+ if filename.endswith(('_resources.h', '_settings.h', '_strings.h')):
-+ with open(os.path.join(root, filename), "r") as f:
-+ ReadResourceIdsFromFile(f, original_resources)
-+ return original_resources
-+
-+
-+def _GeneratePredeterminedIdsFile(ordered_resources_file, out_dir):
-+ """Generates a predetermined ids file.
-+
-+ Args:
-+ ordered_resources_file: File path to read ordered resource ids from.
-+ out_dir: A Chrome build output directory (e.g. out/gn) to scan.
-+
-+ Returns:
-+ A dict of resource ids to resource names.
-+ """
-+ original_resources = _ReadOriginalResourceIds(out_dir)
-+ ordered_resource_ids = _ReadOrderedResourceIds(ordered_resources_file)
-+ output_resource_map = GenerateResourceMapping(original_resources,
-+ ordered_resource_ids)
-+ for res_id in sorted(output_resource_map.keys()):
-+ print(output_resource_map[res_id], res_id)
-+
-+
-+def main(argv):
-+ if len(argv) != 2:
-+ print("usage: gen_predetermined_ids.py <ordered_resources_file> <out_dir>")
-+ sys.exit(1)
-+ ordered_resources_file, out_dir = argv[0], argv[1]
-+ _GeneratePredeterminedIdsFile(ordered_resources_file, out_dir)
-+
-+
-+if '__main__' == __name__:
-+ main(sys.argv[1:])
-diff --git a/tools/grit/grit/format/gen_predetermined_ids_unittest.py b/tools/grit/grit/format/gen_predetermined_ids_unittest.py
-new file mode 100644
-index 0000000000..bd0331adb4
---- /dev/null
-+++ b/tools/grit/grit/format/gen_predetermined_ids_unittest.py
-@@ -0,0 +1,46 @@
-+#!/usr/bin/env python
-+# Copyright 2017 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for the gen_predetermined_ids module.'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit.format import gen_predetermined_ids
-+
-+class GenPredeterminedIdsUnittest(unittest.TestCase):
-+ def testGenerateResourceMapping(self):
-+ original_resources = {200: 'A', 201: 'B', 300: 'C', 350: 'D', 370: 'E'}
-+ ordered_resource_ids = [300, 201, 370]
-+ mapping = gen_predetermined_ids.GenerateResourceMapping(
-+ original_resources, ordered_resource_ids)
-+ self.assertEqual({101: 'C', 102: 'B', 103: 'E'}, mapping)
-+
-+ def testReadResourceIdsFromFile(self):
-+ f = StringIO('''
-+// This file is automatically generated by GRIT. Do not edit.
-+
-+#pragma once
-+
-+#define IDS_BOOKMARKS_NO_ITEMS 12500
-+#define IDS_BOOKMARK_BAR_IMPORT_LINK (::ui::WhitelistedResource<12501>(), 12501)
-+#define IDS_BOOKMARK_X (::ui::WhitelistedResource<12502>(), 12502)
-+''')
-+ resources = {}
-+ gen_predetermined_ids.ReadResourceIdsFromFile(f, resources)
-+ self.assertEqual({12500: 'IDS_BOOKMARKS_OPEN_ALL',
-+ 12501: 'IDS_BOOKMARKS_OPEN_ALL_INCOGNITO',
-+ 12502: 'IDS_BOOKMARK_X'}, resources)
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/gzip_string.py b/tools/grit/grit/format/gzip_string.py
-new file mode 100644
-index 0000000000..3cd17185c9
---- /dev/null
-+++ b/tools/grit/grit/format/gzip_string.py
-@@ -0,0 +1,46 @@
-+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+"""Provides gzip utilities for strings.
-+"""
-+
-+from __future__ import print_function
-+
-+import gzip
-+import io
-+import subprocess
-+
-+
-+def GzipStringRsyncable(data):
-+ # Make call to host system's gzip to get access to --rsyncable option. This
-+ # option makes updates much smaller - if one line is changed in the resource,
-+ # it won't have to push the entire compressed resource with the update.
-+ # Instead, --rsyncable breaks the file into small chunks, so that one doesn't
-+ # affect the other in compression, and then only that chunk will have to be
-+ # updated.
-+ gzip_proc = subprocess.Popen(['gzip', '--stdout', '--rsyncable',
-+ '--best', '--no-name'],
-+ stdin=subprocess.PIPE,
-+ stdout=subprocess.PIPE,
-+ stderr=subprocess.PIPE)
-+ data, stderr = gzip_proc.communicate(data)
-+ if gzip_proc.returncode != 0:
-+ raise subprocess.CalledProcessError(gzip_proc.returncode, 'gzip',
-+ stderr)
-+ return data
-+
-+
-+def GzipString(data):
-+ # Gzipping using Python's built in gzip: Windows doesn't ship with gzip, and
-+ # OSX's gzip does not have an --rsyncable option built in. Although this is
-+ # not preferable to --rsyncable, it is an option for the systems that do
-+ # not have --rsyncable. If used over GzipStringRsyncable, the primary
-+ # difference of this function's compression will be larger updates every time
-+ # a compressed resource is changed.
-+ gzip_output = io.BytesIO()
-+ with gzip.GzipFile(mode='wb', compresslevel=9, fileobj=gzip_output,
-+ mtime=0) as gzip_file:
-+ gzip_file.write(data)
-+ data = gzip_output.getvalue()
-+ gzip_output.close()
-+ return data
-diff --git a/tools/grit/grit/format/gzip_string_unittest.py b/tools/grit/grit/format/gzip_string_unittest.py
-new file mode 100644
-index 0000000000..c0cfbe1837
---- /dev/null
-+++ b/tools/grit/grit/format/gzip_string_unittest.py
-@@ -0,0 +1,65 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.format.gzip_string'''
-+
-+from __future__ import print_function
-+
-+import gzip
-+import io
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit.format import gzip_string
-+
-+
-+class FormatGzipStringUnittest(unittest.TestCase):
-+
-+ def testGzipStringRsyncable(self):
-+ # Can only test the rsyncable version on platforms which support rsyncable,
-+ # which at the moment is Linux.
-+ if sys.platform == 'linux2':
-+ header_begin = (b'\x1f\x8b') # gzip first two bytes
-+ input = (b'TEST STRING STARTING NOW'
-+ b'continuing'
-+ b'<even more>'
-+ b'<finished NOW>')
-+
-+ compressed = gzip_string.GzipStringRsyncable(input)
-+ self.failUnless(header_begin == compressed[:2])
-+
-+ compressed_file = io.BytesIO()
-+ compressed_file.write(compressed)
-+ compressed_file.seek(0)
-+
-+ with gzip.GzipFile(mode='rb', fileobj=compressed_file) as f:
-+ output = f.read()
-+ self.failUnless(output == input)
-+
-+ def testGzipString(self):
-+ header_begin = b'\x1f\x8b' # gzip first two bytes
-+ input = (b'TEST STRING STARTING NOW'
-+ b'continuing'
-+ b'<even more>'
-+ b'<finished NOW>')
-+
-+ compressed = gzip_string.GzipString(input)
-+ self.failUnless(header_begin == compressed[:2])
-+
-+ compressed_file = io.BytesIO()
-+ compressed_file.write(compressed)
-+ compressed_file.seek(0)
-+
-+ with gzip.GzipFile(mode='rb', fileobj=compressed_file) as f:
-+ output = f.read()
-+ self.failUnless(output == input)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/html_inline.py b/tools/grit/grit/format/html_inline.py
-new file mode 100644
-index 0000000000..da55216ea4
---- /dev/null
-+++ b/tools/grit/grit/format/html_inline.py
-@@ -0,0 +1,602 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Flattens a HTML file by inlining its external resources.
-+
-+This is a small script that takes a HTML file, looks for src attributes
-+and inlines the specified file, producing one HTML file with no external
-+dependencies. It recursively inlines the included files.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+import sys
-+import base64
-+import mimetypes
-+
-+from grit import lazy_re
-+from grit import util
-+from grit.format import minifier
-+
-+# There is a python bug that makes mimetypes crash if the Windows
-+# registry contains non-Latin keys ( http://bugs.python.org/issue9291
-+# ). Initing manually and blocking external mime-type databases will
-+# prevent that bug and if we add svg manually, it will still give us
-+# the data we need.
-+mimetypes.init([])
-+mimetypes.add_type('image/svg+xml', '.svg')
-+
-+# webm video type is not always available if mimetype package is outdated.
-+mimetypes.add_type('video/webm', '.webm')
-+
-+DIST_DEFAULT = 'chromium'
-+DIST_ENV_VAR = 'CHROMIUM_BUILD'
-+DIST_SUBSTR = '%DISTRIBUTION%'
-+
-+# Matches beginning of an "if" block.
-+_BEGIN_IF_BLOCK = lazy_re.compile(
-+ r'<if [^>]*?expr=("(?P<expr1>[^">]*)"|\'(?P<expr2>[^\'>]*)\')[^>]*?>')
-+
-+# Matches ending of an "if" block.
-+_END_IF_BLOCK = lazy_re.compile(r'</if>')
-+
-+# Used by DoInline to replace various links with inline content.
-+_STYLESHEET_RE = lazy_re.compile(
-+ r'<link rel="stylesheet"[^>]+?href="(?P<filename>[^"]*)".*?>(\s*</link>)?',
-+ re.DOTALL)
-+_INCLUDE_RE = lazy_re.compile(
-+ r'(?P<comment>\/\/ )?<include[^>]+?'
-+ r'src=("(?P<file1>[^">]*)"|\'(?P<file2>[^\'>]*)\').*?>(\s*</include>)?',
-+ re.DOTALL)
-+_SRC_RE = lazy_re.compile(
-+ r'<(?!script)(?:[^>]+?\s)src="(?!\[\[|{{)(?P<filename>[^"\']*)"',
-+ re.MULTILINE)
-+# This re matches '<img srcset="..."' or '<source srcset="..."'
-+_SRCSET_RE = lazy_re.compile(
-+ r'<(img|source)\b(?:[^>]*?\s)srcset="(?!\[\[|{{|\$i18n{)'
-+ r'(?P<srcset>[^"\']*)"',
-+ re.MULTILINE)
-+# This re is for splitting srcset value string into "image candidate strings".
-+# Notes:
-+# - HTML 5.2 states that URL cannot start or end with comma.
-+# - the "descriptor" is either "width descriptor" or "pixel density descriptor".
-+# The first one consists of "valid non-negative integer + letter 'x'",
-+# the second one is formed of "positive valid floating-point number +
-+# letter 'w'". As a reasonable compromise, we match a list of characters
-+# that form both of them.
-+# Matches for example "img2.png 2x" or "img9.png 11E-2w".
-+_SRCSET_ENTRY_RE = lazy_re.compile(
-+ r'\s*(?P<url>[^,\s]\S+[^,\s])'
-+ r'(?:\s+(?P<descriptor>[\deE.-]+[wx]))?\s*'
-+ r'(?P<separator>,|$)',
-+ re.MULTILINE)
-+_ICON_RE = lazy_re.compile(
-+ r'<link rel="icon"\s(?:[^>]+?\s)?'
-+ r'href=(?P<quote>")(?P<filename>[^"\']*)\1',
-+ re.MULTILINE)
-+
-+
-+def GetDistribution():
-+ """Helper function that gets the distribution we are building.
-+
-+ Returns:
-+ string
-+ """
-+ distribution = DIST_DEFAULT
-+ if DIST_ENV_VAR in os.environ:
-+ distribution = os.environ[DIST_ENV_VAR]
-+ if len(distribution) > 1 and distribution[0] == '_':
-+ distribution = distribution[1:].lower()
-+ return distribution
-+
-+def ConvertFileToDataURL(filename, base_path, distribution, inlined_files,
-+ names_only):
-+ """Convert filename to inlined data URI.
-+
-+ Takes a filename from ether "src" or "srcset", and attempts to read the file
-+ at 'filename'. Returns data URI as string with given file inlined.
-+ If it finds DIST_SUBSTR string in file name, replaces it with distribution.
-+ If filename contains ':', it is considered URL and not translated.
-+
-+ Args:
-+ filename: filename string from ether src or srcset attributes.
-+ base_path: path that to look for files in
-+ distribution: string that should replace DIST_SUBSTR
-+ inlined_files: The name of the opened file is appended to this list.
-+ names_only: If true, the function will not read the file but just return "".
-+ It will still add the filename to |inlined_files|.
-+
-+ Returns:
-+ string
-+ """
-+ if filename.find(':') != -1:
-+ # filename is probably a URL, which we don't want to bother inlining
-+ return filename
-+
-+ filename = filename.replace(DIST_SUBSTR , distribution)
-+ filepath = os.path.normpath(os.path.join(base_path, filename))
-+ inlined_files.add(filepath)
-+
-+ if names_only:
-+ return ""
-+
-+ mimetype = mimetypes.guess_type(filename)[0]
-+ if mimetype is None:
-+ raise Exception('%s is of an an unknown type and '
-+ 'cannot be stored in a data url.' % filename)
-+ inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY))
-+ return 'data:%s;base64,%s' % (mimetype, inline_data.decode('utf-8'))
-+
-+
-+def SrcInlineAsDataURL(
-+ src_match, base_path, distribution, inlined_files, names_only=False,
-+ filename_expansion_function=None):
-+ """regex replace function.
-+
-+ Takes a regex match for src="filename", attempts to read the file
-+ at 'filename' and returns the src attribute with the file inlined
-+ as a data URI. If it finds DIST_SUBSTR string in file name, replaces
-+ it with distribution.
-+
-+ Args:
-+ src_match: regex match object with 'filename' named capturing group
-+ base_path: path that to look for files in
-+ distribution: string that should replace DIST_SUBSTR
-+ inlined_files: The name of the opened file is appended to this list.
-+ names_only: If true, the function will not read the file but just return "".
-+ It will still add the filename to |inlined_files|.
-+
-+ Returns:
-+ string
-+ """
-+ filename = src_match.group('filename')
-+ if filename_expansion_function:
-+ filename = filename_expansion_function(filename)
-+
-+ data_url = ConvertFileToDataURL(filename, base_path, distribution,
-+ inlined_files, names_only)
-+
-+ if not data_url:
-+ return data_url
-+
-+ prefix = src_match.string[src_match.start():src_match.start('filename')]
-+ suffix = src_match.string[src_match.end('filename'):src_match.end()]
-+ return prefix + data_url + suffix
-+
-+def SrcsetInlineAsDataURL(
-+ srcset_match, base_path, distribution, inlined_files, names_only=False,
-+ filename_expansion_function=None):
-+ """regex replace function to inline files in srcset="..." attributes
-+
-+ Takes a regex match for srcset="filename 1x, filename 2x, ...", attempts to
-+ read the files referenced by filenames and returns the srcset attribute with
-+ the files inlined as a data URI. If it finds DIST_SUBSTR string in file name,
-+ replaces it with distribution.
-+
-+ Args:
-+ srcset_match: regex match object with 'srcset' named capturing group
-+ base_path: path that to look for files in
-+ distribution: string that should replace DIST_SUBSTR
-+ inlined_files: The name of the opened file is appended to this list.
-+ names_only: If true, the function will not read the file but just return "".
-+ It will still add the filename to |inlined_files|.
-+
-+ Returns:
-+ string
-+ """
-+ srcset = srcset_match.group('srcset')
-+
-+ if not srcset:
-+ return srcset_match.group(0)
-+
-+ # HTML 5.2 defines srcset as a list of "image candidate strings".
-+ # Each of them consists of URL and descriptor.
-+ # _SRCSET_ENTRY_RE splits srcset into a list of URLs, descriptors and
-+ # commas.
-+ # The descriptor part will be None if that optional regex didn't match
-+ parts = _SRCSET_ENTRY_RE.split(srcset)
-+
-+ if not parts:
-+ return srcset_match.group(0)
-+
-+ # List of image candidate strings that will form new srcset="..."
-+ new_candidates = []
-+
-+ # When iterating over split srcset we fill this parts of a single image
-+ # candidate string: [url, descriptor]
-+ candidate = [];
-+
-+ # Each entry should consist of some text before the entry, the url,
-+ # the descriptor or None if the entry has no descriptor, a comma separator or
-+ # the end of the line, and finally some text after the entry (which is the
-+ # same as the text before the next entry).
-+ for i in range(0, len(parts) - 1, 4):
-+ before, url, descriptor, separator, after = parts[i:i+5]
-+
-+ # There must be a comma-separated next entry or this must be the last entry.
-+ assert separator == "," or (separator == "" and i == len(parts) - 5), (
-+ "Bad srcset format in {}".format(srcset_match.group(0)))
-+ # Both before and after the entry must be empty
-+ assert before == after == "", (
-+ "Bad srcset format in {}".format(srcset_match.group(0)))
-+
-+ if filename_expansion_function:
-+ filename = filename_expansion_function(url)
-+ else:
-+ filename = url
-+
-+ data_url = ConvertFileToDataURL(filename, base_path, distribution,
-+ inlined_files, names_only)
-+
-+ # This is not "names_only" mode
-+ if data_url:
-+ candidate = [data_url]
-+ if descriptor:
-+ candidate.append(descriptor)
-+
-+ new_candidates.append(" ".join(candidate))
-+
-+ prefix = srcset_match.string[srcset_match.start():
-+ srcset_match.start('srcset')]
-+ suffix = srcset_match.string[srcset_match.end('srcset'):srcset_match.end()]
-+ return prefix + ','.join(new_candidates) + suffix
-+
-+class InlinedData:
-+ """Helper class holding the results from DoInline().
-+
-+ Holds the inlined data and the set of filenames of all the inlined
-+ files.
-+ """
-+ def __init__(self, inlined_data, inlined_files):
-+ self.inlined_data = inlined_data
-+ self.inlined_files = inlined_files
-+
-+def DoInline(
-+ input_filename, grd_node, allow_external_script=False,
-+ preprocess_only=False, names_only=False, strip_whitespace=False,
-+ rewrite_function=None, filename_expansion_function=None):
-+ """Helper function that inlines the resources in a specified file.
-+
-+ Reads input_filename, finds all the src attributes and attempts to
-+ inline the files they are referring to, then returns the result and
-+ the set of inlined files.
-+
-+ Args:
-+ input_filename: name of file to read in
-+ grd_node: html node from the grd file for this include tag
-+ preprocess_only: Skip all HTML processing, only handle <if> and <include>.
-+ names_only: |nil| will be returned for the inlined contents (faster).
-+ strip_whitespace: remove whitespace and comments in the input files.
-+ rewrite_function: function(filepath, text, distribution) which will be
-+ called to rewrite html content before inlining images.
-+ filename_expansion_function: function(filename) which will be called to
-+ rewrite filenames before attempting to read them.
-+ Returns:
-+ a tuple of the inlined data as a string and the set of filenames
-+ of all the inlined files
-+ """
-+ if filename_expansion_function:
-+ input_filename = filename_expansion_function(input_filename)
-+ input_filepath = os.path.dirname(input_filename)
-+ distribution = GetDistribution()
-+
-+ # Keep track of all the files we inline.
-+ inlined_files = set()
-+
-+ def SrcReplace(src_match, filepath=input_filepath,
-+ inlined_files=inlined_files):
-+ """Helper function to provide SrcInlineAsDataURL with the base file path"""
-+ return SrcInlineAsDataURL(
-+ src_match, filepath, distribution, inlined_files, names_only=names_only,
-+ filename_expansion_function=filename_expansion_function)
-+
-+ def SrcsetReplace(srcset_match, filepath=input_filepath,
-+ inlined_files=inlined_files):
-+ """Helper function to provide SrcsetInlineAsDataURL with the base file
-+ path.
-+ """
-+ return SrcsetInlineAsDataURL(
-+ srcset_match, filepath, distribution, inlined_files,
-+ names_only=names_only,
-+ filename_expansion_function=filename_expansion_function)
-+
-+ def GetFilepath(src_match, base_path = input_filepath):
-+ filename = [v for k, v in src_match.groupdict().items()
-+ if k.startswith('file') and v][0]
-+
-+ if filename.find(':') != -1:
-+ # filename is probably a URL, which we don't want to bother inlining
-+ return None
-+
-+ filename = filename.replace('%DISTRIBUTION%', distribution)
-+ if filename_expansion_function:
-+ filename = filename_expansion_function(filename)
-+ return os.path.normpath(os.path.join(base_path, filename))
-+
-+ def IsConditionSatisfied(src_match):
-+ expr1 = src_match.group('expr1') or ''
-+ expr2 = src_match.group('expr2') or ''
-+ return grd_node is None or grd_node.EvaluateCondition(expr1 + expr2)
-+
-+ def CheckConditionalElements(str):
-+ """Helper function to conditionally inline inner elements"""
-+ while True:
-+ begin_if = _BEGIN_IF_BLOCK.search(str)
-+ if begin_if is None:
-+ if _END_IF_BLOCK.search(str) is not None:
-+ raise Exception('Unmatched </if>')
-+ return str
-+
-+ condition_satisfied = IsConditionSatisfied(begin_if)
-+ leading = str[0:begin_if.start()]
-+ content_start = begin_if.end()
-+
-+ # Find matching "if" block end.
-+ count = 1
-+ pos = begin_if.end()
-+ while True:
-+ end_if = _END_IF_BLOCK.search(str, pos)
-+ if end_if is None:
-+ raise Exception('Unmatched <if>')
-+
-+ next_if = _BEGIN_IF_BLOCK.search(str, pos)
-+ if next_if is None or next_if.start() >= end_if.end():
-+ count = count - 1
-+ if count == 0:
-+ break
-+ pos = end_if.end()
-+ else:
-+ count = count + 1
-+ pos = next_if.end()
-+
-+ content = str[content_start:end_if.start()]
-+ trailing = str[end_if.end():]
-+
-+ if condition_satisfied:
-+ str = leading + CheckConditionalElements(content) + trailing
-+ else:
-+ str = leading + trailing
-+
-+ def InlineFileContents(src_match,
-+ pattern,
-+ inlined_files=inlined_files,
-+ strip_whitespace=False):
-+ """Helper function to inline external files of various types"""
-+ filepath = GetFilepath(src_match)
-+ if filepath is None:
-+ return src_match.group(0)
-+ inlined_files.add(filepath)
-+
-+ if names_only:
-+ inlined_files.update(GetResourceFilenames(
-+ filepath,
-+ grd_node,
-+ allow_external_script,
-+ rewrite_function,
-+ filename_expansion_function=filename_expansion_function))
-+ return ""
-+ # To recursively save inlined files, we need InlinedData instance returned
-+ # by DoInline.
-+ inlined_data_inst=DoInline(filepath, grd_node,
-+ allow_external_script=allow_external_script,
-+ preprocess_only=preprocess_only,
-+ strip_whitespace=strip_whitespace,
-+ filename_expansion_function=filename_expansion_function)
-+
-+ inlined_files.update(inlined_data_inst.inlined_files)
-+
-+ return pattern % inlined_data_inst.inlined_data;
-+
-+
-+ def InlineIncludeFiles(src_match):
-+ """Helper function to directly inline generic external files (without
-+ wrapping them with any kind of tags).
-+ """
-+ return InlineFileContents(src_match, '%s')
-+
-+ def InlineScript(match):
-+ """Helper function to inline external script files"""
-+ attrs = (match.group('attrs1') + match.group('attrs2')).strip()
-+ if attrs:
-+ attrs = ' ' + attrs
-+ return InlineFileContents(match, '<script' + attrs + '>%s</script>',
-+ strip_whitespace=True)
-+
-+ def InlineCSSText(text, css_filepath):
-+ """Helper function that inlines external resources in CSS text"""
-+ filepath = os.path.dirname(css_filepath)
-+ # Allow custom modifications before inlining images.
-+ if rewrite_function:
-+ text = rewrite_function(filepath, text, distribution)
-+ text = InlineCSSImages(text, filepath)
-+ return InlineCSSImports(text, filepath)
-+
-+ def InlineCSSFile(src_match, pattern, base_path=input_filepath):
-+ """Helper function to inline external CSS files.
-+
-+ Args:
-+ src_match: A regular expression match with a named group named "filename".
-+ pattern: The pattern to replace with the contents of the CSS file.
-+ base_path: The base path to use for resolving the CSS file.
-+
-+ Returns:
-+ The text that should replace the reference to the CSS file.
-+ """
-+ filepath = GetFilepath(src_match, base_path)
-+ if filepath is None:
-+ return src_match.group(0)
-+
-+ # Even if names_only is set, the CSS file needs to be opened, because it
-+ # can link to images that need to be added to the file set.
-+ inlined_files.add(filepath)
-+
-+ # Inline stylesheets included in this css file.
-+ text = _INCLUDE_RE.sub(InlineIncludeFiles, util.ReadFile(filepath, 'utf-8'))
-+ # When resolving CSS files we need to pass in the path so that relative URLs
-+ # can be resolved.
-+
-+ return pattern % InlineCSSText(text, filepath)
-+
-+ def GetUrlRegexString(postfix=''):
-+ """Helper function that returns a string for a regex that matches url('')
-+ but not url([[ ]]) or url({{ }}). Appends |postfix| to group names.
-+ """
-+ url_re = (r'url\((?!\[\[|{{)(?P<q%s>"|\'|)(?P<filename%s>[^"\'()]*)'
-+ r'(?P=q%s)\)')
-+ return url_re % (postfix, postfix, postfix)
-+
-+ def InlineCSSImages(text, filepath=input_filepath):
-+ """Helper function that inlines external images in CSS backgrounds."""
-+ # Replace contents of url() for css attributes: content, background,
-+ # or *-image.
-+ property_re = r'(content|background|[\w-]*-image):[^;]*'
-+ # Replace group names to prevent duplicates when forming value_re.
-+ image_set_value_re = (r'image-set\(([ ]*' + GetUrlRegexString('2') +
-+ r'[ ]*[0-9.]*x[ ]*(,[ ]*)?)+\)')
-+ value_re = '(%s|%s)' % (GetUrlRegexString(), image_set_value_re)
-+ css_re = property_re + value_re
-+ return re.sub(css_re, lambda m: InlineCSSUrls(m, filepath), text)
-+
-+ def InlineCSSUrls(src_match, filepath=input_filepath):
-+ """Helper function that inlines each url on a CSS image rule match."""
-+ # Replace contents of url() references in matches.
-+ return re.sub(GetUrlRegexString(),
-+ lambda m: SrcReplace(m, filepath),
-+ src_match.group(0))
-+
-+ def InlineCSSImports(text, filepath=input_filepath):
-+ """Helper function that inlines CSS files included via the @import
-+ directive.
-+ """
-+ return re.sub(r'@import\s+' + GetUrlRegexString() + r';',
-+ lambda m: InlineCSSFile(m, '%s', filepath),
-+ text)
-+
-+
-+ flat_text = util.ReadFile(input_filename, 'utf-8')
-+
-+ # Check conditional elements, remove unsatisfied ones from the file. We do
-+ # this twice. The first pass is so that we don't even bother calling
-+ # InlineScript, InlineCSSFile and InlineIncludeFiles on text we're eventually
-+ # going to throw out anyway.
-+ flat_text = CheckConditionalElements(flat_text)
-+
-+ flat_text = _INCLUDE_RE.sub(InlineIncludeFiles, flat_text)
-+
-+ if not preprocess_only:
-+ if strip_whitespace:
-+ flat_text = minifier.Minify(flat_text.encode('utf-8'),
-+ input_filename).decode('utf-8')
-+
-+ if not allow_external_script:
-+ # We need to inline css and js before we inline images so that image
-+ # references gets inlined in the css and js
-+ flat_text = re.sub(r'<script (?P<attrs1>.*?)src="(?P<filename>[^"\']*)"'
-+ r'(?P<attrs2>.*?)></script>',
-+ InlineScript,
-+ flat_text)
-+
-+ flat_text = _STYLESHEET_RE.sub(
-+ lambda m: InlineCSSFile(m, '<style>%s</style>'),
-+ flat_text)
-+
-+ # Check conditional elements, second pass. This catches conditionals in any
-+ # of the text we just inlined.
-+ flat_text = CheckConditionalElements(flat_text)
-+
-+ # Allow custom modifications before inlining images.
-+ if rewrite_function:
-+ flat_text = rewrite_function(input_filepath, flat_text, distribution)
-+
-+ if not preprocess_only:
-+ flat_text = _SRC_RE.sub(SrcReplace, flat_text)
-+ flat_text = _SRCSET_RE.sub(SrcsetReplace, flat_text)
-+
-+ # TODO(arv): Only do this inside <style> tags.
-+ flat_text = InlineCSSImages(flat_text)
-+
-+ flat_text = _ICON_RE.sub(SrcReplace, flat_text)
-+
-+ if names_only:
-+ flat_text = None # Will contains garbage if the flag is set anyway.
-+ return InlinedData(flat_text, inlined_files)
-+
-+
-+def InlineToString(input_filename, grd_node, preprocess_only = False,
-+ allow_external_script=False, strip_whitespace=False,
-+ rewrite_function=None, filename_expansion_function=None):
-+ """Inlines the resources in a specified file and returns it as a string.
-+
-+ Args:
-+ input_filename: name of file to read in
-+ grd_node: html node from the grd file for this include tag
-+ Returns:
-+ the inlined data as a string
-+ """
-+ try:
-+ return DoInline(
-+ input_filename,
-+ grd_node,
-+ preprocess_only=preprocess_only,
-+ allow_external_script=allow_external_script,
-+ strip_whitespace=strip_whitespace,
-+ rewrite_function=rewrite_function,
-+ filename_expansion_function=filename_expansion_function).inlined_data
-+ except IOError as e:
-+ raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
-+ (e.filename, input_filename, e.strerror))
-+
-+
-+def InlineToFile(input_filename, output_filename, grd_node):
-+ """Inlines the resources in a specified file and writes it.
-+
-+ Reads input_filename, finds all the src attributes and attempts to
-+ inline the files they are referring to, then writes the result
-+ to output_filename.
-+
-+ Args:
-+ input_filename: name of file to read in
-+ output_filename: name of file to be written to
-+ grd_node: html node from the grd file for this include tag
-+ Returns:
-+ a set of filenames of all the inlined files
-+ """
-+ inlined_data = InlineToString(input_filename, grd_node)
-+ with open(output_filename, 'wb') as out_file:
-+ out_file.write(inlined_data)
-+
-+
-+def GetResourceFilenames(filename,
-+ grd_node,
-+ allow_external_script=False,
-+ rewrite_function=None,
-+ filename_expansion_function=None):
-+ """For a grd file, returns a set of all the files that would be inline."""
-+ try:
-+ return DoInline(
-+ filename,
-+ grd_node,
-+ names_only=True,
-+ preprocess_only=False,
-+ allow_external_script=allow_external_script,
-+ strip_whitespace=False,
-+ rewrite_function=rewrite_function,
-+ filename_expansion_function=filename_expansion_function).inlined_files
-+ except IOError as e:
-+ raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
-+ (e.filename, filename, e.strerror))
-+
-+
-+def main():
-+ if len(sys.argv) <= 2:
-+ print("Flattens a HTML file by inlining its external resources.\n")
-+ print("html_inline.py inputfile outputfile")
-+ else:
-+ InlineToFile(sys.argv[1], sys.argv[2], None)
-+
-+if __name__ == '__main__':
-+ main()
-diff --git a/tools/grit/grit/format/html_inline_unittest.py b/tools/grit/grit/format/html_inline_unittest.py
-new file mode 100644
-index 0000000000..1b11e9e476
---- /dev/null
-+++ b/tools/grit/grit/format/html_inline_unittest.py
-@@ -0,0 +1,927 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.format.html_inline'''
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit import util
-+from grit.format import html_inline
-+
-+
-+class HtmlInlineUnittest(unittest.TestCase):
-+ '''Unit tests for HtmlInline.'''
-+
-+ def testGetResourceFilenames(self):
-+ '''Tests that all included files are returned by GetResourceFilenames.'''
-+
-+ files = {
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ <link rel="stylesheet"
-+ href="really-long-long-long-long-long-test.css">
-+ </head>
-+ <body>
-+ <include src='test.html'>
-+ <include
-+ src="really-long-long-long-long-long-test-file-omg-so-long.html">
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.html': '''
-+ <include src="test2.html">
-+ ''',
-+
-+ 'really-long-long-long-long-long-test-file-omg-so-long.html': '''
-+ <!-- This really long named resource should be included. -->
-+ ''',
-+
-+ 'test2.html': '''
-+ <!-- This second level resource should also be included. -->
-+ ''',
-+
-+ 'test.css': '''
-+ .image {
-+ background: url('test.png');
-+ }
-+ ''',
-+
-+ 'really-long-long-long-long-long-test.css': '''
-+ a:hover {
-+ font-weight: bold; /* Awesome effect is awesome! */
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+ }
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'),
-+ None)
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ tmp_dir.CleanUp()
-+
-+ def testUnmatchedEndIfBlock(self):
-+ '''Tests that an unmatched </if> raises an exception.'''
-+
-+ files = {
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <if expr="lang == 'fr'">
-+ bonjour
-+ </if>
-+ <if expr='lang == "de"'>
-+ hallo
-+ </if>
-+ </if>
-+ </html>
-+ ''',
-+ }
-+
-+ tmp_dir = util.TempDir(files)
-+
-+ with self.assertRaises(Exception) as cm:
-+ html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'), None)
-+ self.failUnlessEqual(str(cm.exception), 'Unmatched </if>')
-+ tmp_dir.CleanUp()
-+
-+ def testCompressedJavaScript(self):
-+ '''Tests that ".src=" doesn't treat as a tag.'''
-+
-+ files = {
-+ 'index.js': '''
-+ if(i<j)a.src="hoge.png";
-+ ''',
-+ }
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.js'),
-+ None)
-+ resources.add(tmp_dir.GetPath('index.js'))
-+ self.failUnlessEqual(resources, source_resources)
-+ tmp_dir.CleanUp()
-+
-+ def testInlineCSSImports(self):
-+ '''Tests that @import directives in inlined CSS files are inlined too.
-+ '''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="css/test.css">
-+ </head>
-+ </html>
-+ ''',
-+
-+ 'css/test.css': '''
-+ @import url('test2.css');
-+ blink {
-+ display: none;
-+ }
-+ ''',
-+
-+ 'css/test2.css': '''
-+ .image {
-+ background: url('../images/test.png');
-+ }
-+ '''.strip(),
-+
-+ 'images/test.png': 'PNG DATA'
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <head>
-+ <style>
-+ .image {
-+ background: url('data:image/png;base64,UE5HIERBVEE=');
-+ }
-+ blink {
-+ display: none;
-+ }
-+ </style>
-+ </head>
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+
-+ tmp_dir.CleanUp()
-+
-+ def testInlineIgnoresPolymerBindings(self):
-+ '''Tests that polymer bindings are ignored when inlining.
-+ '''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ </head>
-+ <body>
-+ <iron-icon src="[[icon]]"></iron-icon><!-- Should be ignored. -->
-+ <iron-icon src="{{src}}"></iron-icon><!-- Also ignored. -->
-+ <!-- [[image]] should be ignored. -->
-+ <div style="background: url([[image]]),
-+ url('test.png');">
-+ </div>
-+ <div style="background: url('test.png'),
-+ url([[image]]);">
-+ </div>
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.css': '''
-+ .image {
-+ background: url('test.png');
-+ background-image: url([[ignoreMe]]);
-+ background-image: image-set(url({{alsoMe}}), 1x);
-+ background-image: image-set(
-+ url({{ignore}}) 1x,
-+ url('test.png') 2x);
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA'
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <head>
-+ <style>
-+ .image {
-+ background: url('data:image/png;base64,UE5HIERBVEE=');
-+ background-image: url([[ignoreMe]]);
-+ background-image: image-set(url({{alsoMe}}), 1x);
-+ background-image: image-set(
-+ url({{ignore}}) 1x,
-+ url('data:image/png;base64,UE5HIERBVEE=') 2x);
-+ }
-+ </style>
-+ </head>
-+ <body>
-+ <iron-icon src="[[icon]]"></iron-icon><!-- Should be ignored. -->
-+ <iron-icon src="{{src}}"></iron-icon><!-- Also ignored. -->
-+ <!-- [[image]] should be ignored. -->
-+ <div style="background: url([[image]]),
-+ url('data:image/png;base64,UE5HIERBVEE=');">
-+ </div>
-+ <div style="background: url('data:image/png;base64,UE5HIERBVEE='),
-+ url([[image]]);">
-+ </div>
-+ </body>
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+
-+ tmp_dir.CleanUp()
-+
-+ def testInlineCSSWithIncludeDirective(self):
-+ '''Tests that include directive in external css files also inlined'''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="foo.css">
-+ </head>
-+ </html>
-+ ''',
-+
-+ 'foo.css': '''<include src="style.css">''',
-+
-+ 'style.css': '''
-+ <include src="style2.css">
-+ blink {
-+ display: none;
-+ }
-+ ''',
-+ 'style2.css': '''h1 {}''',
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <head>
-+ <style>
-+ h1 {}
-+ blink {
-+ display: none;
-+ }
-+ </style>
-+ </head>
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testCssIncludedFileNames(self):
-+ '''Tests that all included files from css are returned'''
-+
-+ files = {
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ </head>
-+ <body>
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.css': '''
-+ <include src="test2.css">
-+ ''',
-+
-+ 'test2.css': '''
-+ <include src="test3.css">
-+ .image {
-+ background: url('test.png');
-+ }
-+ ''',
-+
-+ 'test3.css': '''h1 {}''',
-+
-+ 'test.png': 'PNG DATA'
-+ }
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'),
-+ None)
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ tmp_dir.CleanUp()
-+
-+ def testInlineCSSLinks(self):
-+ '''Tests that only CSS files referenced via relative URLs are inlined.'''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="foo.css">
-+ <link rel="stylesheet" href="chrome://resources/bar.css">
-+ </head>
-+ </html>
-+ ''',
-+
-+ 'foo.css': '''
-+ @import url(chrome://resources/blurp.css);
-+ blink {
-+ display: none;
-+ }
-+ ''',
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <head>
-+ <style>
-+ @import url(chrome://resources/blurp.css);
-+ blink {
-+ display: none;
-+ }
-+ </style>
-+ <link rel="stylesheet" href="chrome://resources/bar.css">
-+ </head>
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testFilenameVariableExpansion(self):
-+ '''Tests that variables are expanded in filenames before inlining.'''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="style[WHICH].css">
-+ <script src="script[WHICH].js"></script>
-+ </head>
-+ <include src="tmpl[WHICH].html">
-+ <img src="img[WHICH].png">
-+ </html>
-+ ''',
-+ 'style1.css': '''h1 {}''',
-+ 'tmpl1.html': '''<h1></h1>''',
-+ 'script1.js': '''console.log('hello');''',
-+ 'img1.png': '''abc''',
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <head>
-+ <style>h1 {}</style>
-+ <script>console.log('hello');</script>
-+ </head>
-+ <h1></h1>
-+ <img src="data:image/png;base64,YWJj">
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ def replacer(var, repl):
-+ return lambda filename: filename.replace('[%s]' % var, repl)
-+
-+ # Test normal inlining.
-+ result = html_inline.DoInline(
-+ tmp_dir.GetPath('index.html'),
-+ None,
-+ filename_expansion_function=replacer('WHICH', '1'))
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+
-+ # Test names-only inlining.
-+ result = html_inline.DoInline(
-+ tmp_dir.GetPath('index.html'),
-+ None,
-+ names_only=True,
-+ filename_expansion_function=replacer('WHICH', '1'))
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ tmp_dir.CleanUp()
-+
-+ def testWithCloseTags(self):
-+ '''Tests that close tags are removed.'''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="style1.css"></link>
-+ <link rel="stylesheet" href="style2.css">
-+ </link>
-+ <link rel="stylesheet" href="style2.css"
-+ >
-+ </link>
-+ <script src="script1.js"></script>
-+ </head>
-+ <include src="tmpl1.html"></include>
-+ <include src="tmpl2.html">
-+ </include>
-+ <include src="tmpl2.html"
-+ >
-+ </include>
-+ <img src="img1.png">
-+ <include src='single-double-quotes.html"></include>
-+ <include src="double-single-quotes.html'></include>
-+ </html>
-+ ''',
-+ 'style1.css': '''h1 {}''',
-+ 'style2.css': '''h2 {}''',
-+ 'tmpl1.html': '''<h1></h1>''',
-+ 'tmpl2.html': '''<h2></h2>''',
-+ 'script1.js': '''console.log('hello');''',
-+ 'img1.png': '''abc''',
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <head>
-+ <style>h1 {}</style>
-+ <style>h2 {}</style>
-+ <style>h2 {}</style>
-+ <script>console.log('hello');</script>
-+ </head>
-+ <h1></h1>
-+ <h2></h2>
-+ <h2></h2>
-+ <img src="data:image/png;base64,YWJj">
-+ <include src='single-double-quotes.html"></include>
-+ <include src="double-single-quotes.html'></include>
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ # Test normal inlining.
-+ result = html_inline.DoInline(
-+ tmp_dir.GetPath('index.html'),
-+ None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testCommentedJsInclude(self):
-+ '''Tests that <include> works inside a comment.'''
-+
-+ files = {
-+ 'include.js': '// <include src="other.js">',
-+ 'other.js': '// Copyright somebody\nalert(1);',
-+ }
-+
-+ expected_inlined = '// Copyright somebody\nalert(1);'
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('include.js'), None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('include.js'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testCommentedJsIf(self):
-+ '''Tests that <if> works inside a comment.'''
-+
-+ files = {
-+ 'if.js': '''
-+ // <if expr="True">
-+ yep();
-+ // </if>
-+
-+ // <if expr="False">
-+ nope();
-+ // </if>
-+ ''',
-+ }
-+
-+ expected_inlined = '''
-+ //
-+ yep();
-+ //
-+
-+ //
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ class FakeGrdNode(object):
-+ def EvaluateCondition(self, cond):
-+ return eval(cond)
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('if.js'), FakeGrdNode())
-+ resources = result.inlined_files
-+
-+ resources.add(tmp_dir.GetPath('if.js'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testImgSrcset(self):
-+ '''Tests that img srcset="" attributes are converted.'''
-+
-+ # Note that there is no space before "img10.png" and that
-+ # "img11.png" has no descriptor.
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <img src="img1.png" srcset="img2.png 1x, img3.png 2x">
-+ <img src="img4.png" srcset=" img5.png 1x , img6.png 2x ">
-+ <img src="chrome://theme/img11.png" srcset="img7.png 1x, '''\
-+ '''chrome://theme/img13.png 2x">
-+ <img srcset="img8.png 300w, img9.png 11E-2w,img10.png -1e2w">
-+ <img srcset="img11.png">
-+ <img srcset="img11.png, img2.png 1x">
-+ <img srcset="img2.png 1x, img11.png">
-+ </html>
-+ ''',
-+ 'img1.png': '''a1''',
-+ 'img2.png': '''a2''',
-+ 'img3.png': '''a3''',
-+ 'img4.png': '''a4''',
-+ 'img5.png': '''a5''',
-+ 'img6.png': '''a6''',
-+ 'img7.png': '''a7''',
-+ 'img8.png': '''a8''',
-+ 'img9.png': '''a9''',
-+ 'img10.png': '''a10''',
-+ 'img11.png': '''a11''',
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <img src="data:image/png;base64,YTE=" srcset="data:image/png;base64,'''\
-+ '''YTI= 1x,data:image/png;base64,YTM= 2x">
-+ <img src="data:image/png;base64,YTQ=" srcset="data:image/png;base64,'''\
-+ '''YTU= 1x,data:image/png;base64,YTY= 2x">
-+ <img src="chrome://theme/img11.png" srcset="data:image/png;base64,'''\
-+ '''YTc= 1x,chrome://theme/img13.png 2x">
-+ <img srcset="data:image/png;base64,YTg= 300w,data:image/png;base64,'''\
-+ '''YTk= 11E-2w,data:image/png;base64,YTEw -1e2w">
-+ <img srcset="data:image/png;base64,YTEx">
-+ <img srcset="data:image/png;base64,YTEx,data:image/png;base64,YTI= 1x">
-+ <img srcset="data:image/png;base64,YTI= 1x,data:image/png;base64,YTEx">
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ # Test normal inlining.
-+ result = html_inline.DoInline(
-+ tmp_dir.GetPath('index.html'),
-+ None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testImgSrcsetIgnoresI18n(self):
-+ '''Tests that $i18n{...} strings are ignored when inlining.
-+ '''
-+
-+ src_html = '''
-+ <html>
-+ <head></head>
-+ <body>
-+ <img srcset="$i18n{foo}">
-+ </body>
-+ </html>
-+ '''
-+
-+ files = {
-+ 'index.html': src_html,
-+ }
-+
-+ expected_inlined = src_html
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testSourceSrcset(self):
-+ '''Tests that source srcset="" attributes are converted.'''
-+
-+ # Note that there is no space before "img10.png" and that
-+ # "img11.png" has no descriptor.
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <source src="img1.png" srcset="img2.png 1x, img3.png 2x">
-+ <source src="img4.png" srcset=" img5.png 1x , img6.png 2x ">
-+ <source src="chrome://theme/img11.png" srcset="img7.png 1x, '''\
-+ '''chrome://theme/img13.png 2x">
-+ <source srcset="img8.png 300w, img9.png 11E-2w,img10.png -1e2w">
-+ <source srcset="img11.png">
-+ </html>
-+ ''',
-+ 'img1.png': '''a1''',
-+ 'img2.png': '''a2''',
-+ 'img3.png': '''a3''',
-+ 'img4.png': '''a4''',
-+ 'img5.png': '''a5''',
-+ 'img6.png': '''a6''',
-+ 'img7.png': '''a7''',
-+ 'img8.png': '''a8''',
-+ 'img9.png': '''a9''',
-+ 'img10.png': '''a10''',
-+ 'img11.png': '''a11''',
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <source src="data:image/png;base64,YTE=" srcset="data:image/png;'''\
-+ '''base64,YTI= 1x,data:image/png;base64,YTM= 2x">
-+ <source src="data:image/png;base64,YTQ=" srcset="data:image/png;'''\
-+ '''base64,YTU= 1x,data:image/png;base64,YTY= 2x">
-+ <source src="chrome://theme/img11.png" srcset="data:image/png;'''\
-+ '''base64,YTc= 1x,chrome://theme/img13.png 2x">
-+ <source srcset="data:image/png;base64,YTg= 300w,data:image/png;'''\
-+ '''base64,YTk= 11E-2w,data:image/png;base64,YTEw -1e2w">
-+ <source srcset="data:image/png;base64,YTEx">
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ # Test normal inlining.
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+ self.failUnlessEqual(expected_inlined,
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ tmp_dir.CleanUp()
-+
-+ def testConditionalInclude(self):
-+ '''Tests that output and dependency generation includes only files not'''\
-+ ''' blocked by <if> macros.'''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <if expr="True">
-+ <img src="img1.png" srcset="img2.png 1x, img3.png 2x">
-+ </if>
-+ <if expr="False">
-+ <img src="img4.png" srcset=" img5.png 1x, img6.png 2x ">
-+ </if>
-+ <if expr="True">
-+ <img src="chrome://theme/img11.png" srcset="img7.png 1x, '''\
-+ '''chrome://theme/img13.png 2x">
-+ </if>
-+ <img srcset="img8.png 300w, img9.png 11E-2w,img10.png -1e2w">
-+ </html>
-+ ''',
-+ 'img1.png': '''a1''',
-+ 'img2.png': '''a2''',
-+ 'img3.png': '''a3''',
-+ 'img4.png': '''a4''',
-+ 'img5.png': '''a5''',
-+ 'img6.png': '''a6''',
-+ 'img7.png': '''a7''',
-+ 'img8.png': '''a8''',
-+ 'img9.png': '''a9''',
-+ 'img10.png': '''a10''',
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <img src="data:image/png;base64,YTE=" srcset="data:image/png;base64,'''\
-+ '''YTI= 1x,data:image/png;base64,YTM= 2x">
-+ <img src="chrome://theme/img11.png" srcset="data:image/png;base64,'''\
-+ '''YTc= 1x,chrome://theme/img13.png 2x">
-+ <img srcset="data:image/png;base64,YTg= 300w,data:image/png;base64,'''\
-+ '''YTk= 11E-2w,data:image/png;base64,YTEw -1e2w">
-+ </html>
-+ '''
-+
-+ expected_files = [
-+ 'index.html',
-+ 'img1.png',
-+ 'img2.png',
-+ 'img3.png',
-+ 'img7.png',
-+ 'img8.png',
-+ 'img9.png',
-+ 'img10.png'
-+ ]
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ for filename in expected_files:
-+ source_resources.add(tmp_dir.GetPath(filename))
-+
-+ class FakeGrdNode(object):
-+ def EvaluateCondition(self, cond):
-+ return eval(cond)
-+
-+ # Test normal inlining.
-+ result = html_inline.DoInline(
-+ tmp_dir.GetPath('index.html'),
-+ FakeGrdNode())
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+
-+ # ignore whitespace
-+ expected_inlined = re.sub(r'\s+', ' ', expected_inlined)
-+ actually_inlined = re.sub(r'\s+', ' ',
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ self.failUnlessEqual(expected_inlined, actually_inlined);
-+ tmp_dir.CleanUp()
-+
-+ def testPreprocessOnlyEvaluatesIncludeAndIf(self):
-+ '''Tests that preprocess_only=true evaluates <include> and <if> only. '''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="not_inlined.css">
-+ <script src="also_not_inlined.js">
-+ </head>
-+ <body>
-+ <include src="inline_this.html">
-+ <if expr="True">
-+ <p>'if' should be evaluated.</p>
-+ </if>
-+ </body>
-+ </html>
-+ ''',
-+ 'not_inlined.css': ''' /* <link> should not be inlined. */ ''',
-+ 'also_not_inlined.js': ''' // <script> should not be inlined. ''',
-+ 'inline_this.html': ''' <p>'include' should be inlined.</p> '''
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="not_inlined.css">
-+ <script src="also_not_inlined.js">
-+ </head>
-+ <body>
-+ <p>'include' should be inlined.</p>
-+ <p>'if' should be evaluated.</p>
-+ </body>
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ source_resources.add(tmp_dir.GetPath('index.html'))
-+ source_resources.add(tmp_dir.GetPath('inline_this.html'))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None,
-+ preprocess_only=True)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+
-+ # Ignore whitespace
-+ expected_inlined = re.sub(r'\s+', ' ', expected_inlined)
-+ actually_inlined = re.sub(r'\s+', ' ',
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ self.failUnlessEqual(expected_inlined, actually_inlined)
-+
-+ tmp_dir.CleanUp()
-+
-+ def testPreprocessOnlyAppliesRecursively(self):
-+ '''Tests that preprocess_only=true propagates to included files. '''
-+
-+ files = {
-+ 'index.html': '''
-+ <html>
-+ <include src="outer_include.html">
-+ </html>
-+ ''',
-+ 'outer_include.html': '''
-+ <include src="inner_include.html">
-+ <link rel="stylesheet" href="not_inlined.css">
-+ ''',
-+ 'inner_include.html': ''' <p>This should be inlined in index.html</p> ''',
-+ 'not_inlined.css': ''' /* This should not be inlined. */ '''
-+ }
-+
-+ expected_inlined = '''
-+ <html>
-+ <p>This should be inlined in index.html</p>
-+ <link rel="stylesheet" href="not_inlined.css">
-+ </html>
-+ '''
-+
-+ source_resources = set()
-+ tmp_dir = util.TempDir(files)
-+ source_resources.add(tmp_dir.GetPath('index.html'))
-+ source_resources.add(tmp_dir.GetPath('outer_include.html'))
-+ source_resources.add(tmp_dir.GetPath('inner_include.html'))
-+
-+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None,
-+ preprocess_only=True)
-+ resources = result.inlined_files
-+ resources.add(tmp_dir.GetPath('index.html'))
-+ self.failUnlessEqual(resources, source_resources)
-+
-+ # Ignore whitespace
-+ expected_inlined = re.sub(r'\s+', ' ', expected_inlined)
-+ actually_inlined = re.sub(r'\s+', ' ',
-+ util.FixLineEnd(result.inlined_data, '\n'))
-+ self.failUnlessEqual(expected_inlined, actually_inlined)
-+
-+ tmp_dir.CleanUp()
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/minifier.py b/tools/grit/grit/format/minifier.py
-new file mode 100644
-index 0000000000..1a0ea34e49
---- /dev/null
-+++ b/tools/grit/grit/format/minifier.py
-@@ -0,0 +1,45 @@
-+# Copyright 2016 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+"""Framework for stripping whitespace and comments from resource files"""
-+
-+from __future__ import print_function
-+
-+from os import path
-+import subprocess
-+import sys
-+
-+import six
-+
-+__js_minifier = None
-+__css_minifier = None
-+
-+def SetJsMinifier(minifier):
-+ global __js_minifier
-+ __js_minifier = minifier.split()
-+
-+def SetCssMinifier(minifier):
-+ global __css_minifier
-+ __css_minifier = minifier.split()
-+
-+def Minify(source, filename):
-+ """Minify |source| (bytes) from |filename| and return bytes."""
-+ file_type = path.splitext(filename)[1]
-+ minifier = None
-+ if file_type == '.js':
-+ minifier = __js_minifier
-+ elif file_type == '.css':
-+ minifier = __css_minifier
-+ if not minifier:
-+ return source
-+ p = subprocess.Popen(
-+ minifier,
-+ stdin=subprocess.PIPE,
-+ stdout=subprocess.PIPE,
-+ stderr=subprocess.PIPE)
-+ (stdout, stderr) = p.communicate(source)
-+ if p.returncode != 0:
-+ print('Minification failed for %s' % filename)
-+ print(stderr)
-+ sys.exit(p.returncode)
-+ return stdout
-diff --git a/tools/grit/grit/format/policy_templates_json.py b/tools/grit/grit/format/policy_templates_json.py
-new file mode 100644
-index 0000000000..2f9330bb9a
---- /dev/null
-+++ b/tools/grit/grit/format/policy_templates_json.py
-@@ -0,0 +1,26 @@
-+# Copyright 2017 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Translates policy_templates.json files.
-+"""
-+
-+from __future__ import print_function
-+
-+from grit.node import structure
-+
-+
-+def Format(root, lang='en', output_dir='.'):
-+ policy_json = None
-+ for item in root.ActiveDescendants():
-+ with item:
-+ if (isinstance(item, structure.StructureNode) and
-+ item.attrs['type'] == 'policy_template_metafile'):
-+ json_text = item.gatherer.Translate(
-+ lang,
-+ pseudo_if_not_available=item.PseudoIsAllowed(),
-+ fallback_to_english=item.ShouldFallbackToEnglish())
-+ # We're only expecting one node of this kind.
-+ assert not policy_json
-+ policy_json = json_text
-+ return policy_json
-diff --git a/tools/grit/grit/format/policy_templates_json_unittest.py b/tools/grit/grit/format/policy_templates_json_unittest.py
-new file mode 100644
-index 0000000000..e252c94e2c
---- /dev/null
-+++ b/tools/grit/grit/format/policy_templates_json_unittest.py
-@@ -0,0 +1,207 @@
-+#!/usr/bin/env python
-+# coding: utf-8
-+# Copyright 2017 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Unittest for policy_templates_json.py.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import grit.extern.tclib
-+import tempfile
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import grd_reader
-+from grit.tool import build
-+
-+
-+class PolicyTemplatesJsonUnittest(unittest.TestCase):
-+
-+ def testPolicyTranslation(self):
-+ # Create test policy_templates.json data.
-+ caption = "The main policy"
-+ caption_translation = "Die Hauptrichtlinie"
-+
-+ message = \
-+ "Red cabbage stays red cabbage and wedding dress stays wedding dress"
-+ message_translation = \
-+ "Blaukraut bleibt Blaukraut und Brautkleid bleibt Brautkleid"
-+
-+ schema_key_description = "Number of users"
-+ schema_key_description_translation = "Anzahl der Nutzer"
-+
-+ policy_json = """
-+ {
-+ "policy_definitions": [
-+ {
-+ 'name': 'MainPolicy',
-+ 'type': 'main',
-+ 'owners': ['foo@bar.com'],
-+ 'schema': {
-+ 'properties': {
-+ 'default_launch_container': {
-+ 'enum': [
-+ 'tab',
-+ 'window',
-+ ],
-+ 'type': 'string',
-+ },
-+ 'users_number': {
-+ 'description': '''%s''',
-+ 'type': 'integer',
-+ },
-+ },
-+ 'type': 'object',
-+ },
-+ 'supported_on': ['chrome_os:29-'],
-+ 'features': {
-+ 'can_be_recommended': True,
-+ 'dynamic_refresh': True,
-+ },
-+ 'example_value': True,
-+ 'caption': '''%s''',
-+ 'tags': [],
-+ 'desc': '''This policy does stuff.'''
-+ },
-+ ],
-+ "policy_atomic_group_definitions": [],
-+ "placeholders": [],
-+ "messages": {
-+ 'message_string_id': {
-+ 'desc': '''The description is removed from the grit output''',
-+ 'text': '''%s'''
-+ }
-+ }
-+ }""" % (schema_key_description, caption, message)
-+
-+ # Create translations. The translation IDs are hashed from the English text.
-+ caption_id = grit.extern.tclib.GenerateMessageId(caption);
-+ message_id = grit.extern.tclib.GenerateMessageId(message);
-+ schema_key_description_id = grit.extern.tclib.GenerateMessageId(
-+ schema_key_description)
-+ policy_xtb = """
-+<?xml version="1.0" ?>
-+<!DOCTYPE translationbundle>
-+<translationbundle lang="de">
-+<translation id="%s">%s</translation>
-+<translation id="%s">%s</translation>
-+<translation id="%s">%s</translation>
-+</translationbundle>""" % (caption_id, caption_translation,
-+ message_id, message_translation,
-+ schema_key_description_id,
-+ schema_key_description_translation)
-+
-+ # Write both to a temp file.
-+ tmp_dir_name = tempfile.gettempdir()
-+
-+ json_file_path = os.path.join(tmp_dir_name, 'test.json')
-+ with open(json_file_path, 'w') as f:
-+ f.write(policy_json.strip())
-+
-+ xtb_file_path = os.path.join(tmp_dir_name, 'test.xtb')
-+ with open(xtb_file_path, 'w') as f:
-+ f.write(policy_xtb.strip())
-+
-+ # Assemble a test grit tree, similar to policy_templates.grd.
-+ grd_text = '''
-+ <grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
-+ <translations>
-+ <file path="%s" lang="de" />
-+ </translations>
-+ <release seq="1">
-+ <structures>
-+ <structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
-+ </structures>
-+ </release>
-+ </grit>''' % (xtb_file_path, json_file_path)
-+ grd_string_io = StringIO(grd_text)
-+
-+ # Parse the grit tree and load the policies' JSON with a gatherer.
-+ grd = grd_reader.Parse(grd_string_io, dir=tmp_dir_name, defines={'_google_chrome': True})
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+
-+ # Remove the temp files.
-+ os.unlink(xtb_file_path)
-+ os.unlink(json_file_path)
-+
-+ # Run grit with en->de translation.
-+ env_lang = 'en'
-+ out_lang = 'de'
-+ env_defs = {'_google_chrome': '1'}
-+
-+ grd.SetOutputLanguage(env_lang)
-+ grd.SetDefines(env_defs)
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(grd, DummyOutput('policy_templates', out_lang), buf)
-+ output = buf.getvalue()
-+
-+ # Caption and message texts get taken from xtb.
-+ # desc is 'translated' to some pseudo-English
-+ # 'ThïPïs pôPôlïPïcýPý dôéPôés stüPüff'.
-+ expected = u"""{
-+ "policy_definitions": [
-+ {
-+ "caption": "%s",
-+ "desc": "Th\xefP\xefs p\xf4P\xf4l\xefP\xefc\xfdP\xfd d\xf4\xe9P\xf4\xe9s st\xfcP\xfcff.",
-+ "example_value": true,
-+ "features": {"can_be_recommended": true, "dynamic_refresh": true},
-+ "name": "MainPolicy",
-+ "owners": ["foo@bar.com"],
-+ "schema": {
-+ "properties": {
-+ "default_launch_container": {
-+ "enum": [
-+ "tab",
-+ "window"
-+ ],
-+ "type": "string"
-+ },
-+ "users_number": {
-+ "description": "%s",
-+ "type": "integer"
-+ }
-+ },
-+ "type": "object"
-+ },
-+ "supported_on": ["chrome_os:29-"],
-+ "tags": [],
-+ "type": "main"
-+ }
-+ ],
-+ "policy_atomic_group_definitions": [
-+ ],
-+ "messages": {
-+ "message_string_id": {
-+ "text": "%s"
-+ }
-+ }
-+
-+}""" % (caption_translation, schema_key_description_translation,
-+ message_translation)
-+ self.assertEqual(expected, output)
-+
-+
-+class DummyOutput(object):
-+
-+ def __init__(self, type, language):
-+ self.type = type
-+ self.language = language
-+
-+ def GetType(self):
-+ return self.type
-+
-+ def GetLanguage(self):
-+ return self.language
-+
-+ def GetOutputFilename(self):
-+ return 'hello.gif'
-diff --git a/tools/grit/grit/format/rc.py b/tools/grit/grit/format/rc.py
-new file mode 100644
-index 0000000000..ed32bb809e
---- /dev/null
-+++ b/tools/grit/grit/format/rc.py
-@@ -0,0 +1,474 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Support for formatting an RC file for compilation.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+from functools import partial
-+
-+import six
-+
-+from grit import util
-+from grit.node import misc
-+
-+
-+def Format(root, lang='en', output_dir='.'):
-+ from grit.node import empty, include, message, structure
-+
-+ yield _FormatHeader(root, lang, output_dir)
-+
-+ for item in root.ActiveDescendants():
-+ if isinstance(item, empty.MessagesNode):
-+ # Write one STRINGTABLE per <messages> container.
-+ # This is hacky: it iterates over the children twice.
-+ yield 'STRINGTABLE\nBEGIN\n'
-+ for subitem in item.ActiveDescendants():
-+ if isinstance(subitem, message.MessageNode):
-+ with subitem:
-+ yield FormatMessage(subitem, lang)
-+ yield 'END\n\n'
-+ elif isinstance(item, include.IncludeNode):
-+ with item:
-+ yield FormatInclude(item, lang, output_dir)
-+ elif isinstance(item, structure.StructureNode):
-+ with item:
-+ yield FormatStructure(item, lang, output_dir)
-+
-+
-+'''
-+This dictionary defines the language charset pair lookup table, which is used
-+for replacing the GRIT expand variables for language info in Product Version
-+resource. The key is the language ISO country code, and the value
-+is the language and character-set pair, which is a hexadecimal string
-+consisting of the concatenation of the language and character-set identifiers.
-+The first 4 digit of the value is the hex value of LCID, the remaining
-+4 digits is the hex value of character-set id(code page)of the language.
-+
-+LCID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
-+Codepage resource: http://www.science.co.il/language/locale-codes.asp
-+
-+We have defined three GRIT expand_variables to be used in the version resource
-+file to set the language info. Here is an example how they should be used in
-+the VS_VERSION_INFO section of the resource file to allow GRIT to localize
-+the language info correctly according to product locale.
-+
-+VS_VERSION_INFO VERSIONINFO
-+...
-+BEGIN
-+ BLOCK "StringFileInfo"
-+ BEGIN
-+ BLOCK "[GRITVERLANGCHARSETHEX]"
-+ BEGIN
-+ ...
-+ END
-+ END
-+ BLOCK "VarFileInfo"
-+ BEGIN
-+ VALUE "Translation", [GRITVERLANGID], [GRITVERCHARSETID]
-+ END
-+END
-+
-+'''
-+
-+_LANGUAGE_CHARSET_PAIR = {
-+ # Language neutral LCID, unicode(1200) code page.
-+ 'neutral' : '000004b0',
-+ # LANG_USER_DEFAULT LCID, unicode(1200) code page.
-+ 'userdefault' : '040004b0',
-+ 'ar' : '040104e8',
-+ 'fi' : '040b04e4',
-+ 'ko' : '041203b5',
-+ 'es' : '0c0a04e4',
-+ 'bg' : '040204e3',
-+ # No codepage for filipino, use unicode(1200).
-+ 'fil' : '046404e4',
-+ 'fr' : '040c04e4',
-+ 'lv' : '042604e9',
-+ 'sv' : '041d04e4',
-+ 'ca' : '040304e4',
-+ 'de' : '040704e4',
-+ 'lt' : '042704e9',
-+ # Do not use! This is only around for backwards
-+ # compatibility and will be removed - use fil instead
-+ 'tl' : '0c0004b0',
-+ 'zh-CN' : '080403a8',
-+ 'zh-TW' : '040403b6',
-+ 'zh-HK' : '0c0403b6',
-+ 'el' : '040804e5',
-+ 'no' : '001404e4',
-+ 'nb' : '041404e4',
-+ 'nn' : '081404e4',
-+ 'th' : '041e036a',
-+ 'he' : '040d04e7',
-+ 'iw' : '040d04e7',
-+ 'pl' : '041504e2',
-+ 'tr' : '041f04e6',
-+ 'hr' : '041a04e4',
-+ # No codepage for Hindi, use unicode(1200).
-+ 'hi' : '043904b0',
-+ 'pt-PT' : '081604e4',
-+ 'pt-BR' : '041604e4',
-+ 'uk' : '042204e3',
-+ 'cs' : '040504e2',
-+ 'hu' : '040e04e2',
-+ 'ro' : '041804e2',
-+ # No codepage for Urdu, use unicode(1200).
-+ 'ur' : '042004b0',
-+ 'da' : '040604e4',
-+ 'is' : '040f04e4',
-+ 'ru' : '041904e3',
-+ 'vi' : '042a04ea',
-+ 'nl' : '041304e4',
-+ 'id' : '042104e4',
-+ 'sr' : '081a04e2',
-+ 'en-GB' : '0809040e',
-+ 'it' : '041004e4',
-+ 'sk' : '041b04e2',
-+ 'et' : '042504e9',
-+ 'ja' : '041103a4',
-+ 'sl' : '042404e2',
-+ 'en' : '040904b0',
-+ # LCID for Mexico; Windows does not support L.A. LCID.
-+ 'es-419' : '080a04e4',
-+ # No codepage for Bengali, use unicode(1200).
-+ 'bn' : '044504b0',
-+ 'fa' : '042904e8',
-+ # No codepage for Gujarati, use unicode(1200).
-+ 'gu' : '044704b0',
-+ # No codepage for Kannada, use unicode(1200).
-+ 'kn' : '044b04b0',
-+ # Malay (Malaysia) [ms-MY]
-+ 'ms' : '043e04e4',
-+ # No codepage for Malayalam, use unicode(1200).
-+ 'ml' : '044c04b0',
-+ # No codepage for Marathi, use unicode(1200).
-+ 'mr' : '044e04b0',
-+ # No codepage for Oriya , use unicode(1200).
-+ 'or' : '044804b0',
-+ # No codepage for Tamil, use unicode(1200).
-+ 'ta' : '044904b0',
-+ # No codepage for Telugu, use unicode(1200).
-+ 'te' : '044a04b0',
-+ # No codepage for Amharic, use unicode(1200). >= Vista.
-+ 'am' : '045e04b0',
-+ 'sw' : '044104e4',
-+ 'af' : '043604e4',
-+ 'eu' : '042d04e4',
-+ 'fr-CA' : '0c0c04e4',
-+ 'gl' : '045604e4',
-+ # No codepage for Zulu, use unicode(1200).
-+ 'zu' : '043504b0',
-+ 'fake-bidi' : '040d04e7',
-+}
-+
-+# Language ID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
-+#
-+# There is no appropriate sublang for Spanish (Latin America) [es-419], so we
-+# use Mexico. SUBLANG_DEFAULT would incorrectly map to Spain. Unlike other
-+# Latin American countries, Mexican Spanish is supported by VERSIONINFO:
-+# http://msdn.microsoft.com/en-us/library/aa381058.aspx
-+
-+_LANGUAGE_DIRECTIVE_PAIR = {
-+ 'neutral' : 'LANG_NEUTRAL, SUBLANG_NEUTRAL',
-+ 'userdefault' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
-+ 'ar' : 'LANG_ARABIC, SUBLANG_DEFAULT',
-+ 'fi' : 'LANG_FINNISH, SUBLANG_DEFAULT',
-+ 'ko' : 'LANG_KOREAN, SUBLANG_KOREAN',
-+ 'es' : 'LANG_SPANISH, SUBLANG_SPANISH_MODERN',
-+ 'bg' : 'LANG_BULGARIAN, SUBLANG_DEFAULT',
-+ # LANG_FILIPINO (100) not in VC 7 winnt.h.
-+ 'fil' : '100, SUBLANG_DEFAULT',
-+ 'fr' : 'LANG_FRENCH, SUBLANG_FRENCH',
-+ 'lv' : 'LANG_LATVIAN, SUBLANG_DEFAULT',
-+ 'sv' : 'LANG_SWEDISH, SUBLANG_SWEDISH',
-+ 'ca' : 'LANG_CATALAN, SUBLANG_DEFAULT',
-+ 'de' : 'LANG_GERMAN, SUBLANG_GERMAN',
-+ 'lt' : 'LANG_LITHUANIAN, SUBLANG_LITHUANIAN',
-+ # Do not use! See above.
-+ 'tl' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
-+ 'zh-CN' : 'LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED',
-+ 'zh-TW' : 'LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL',
-+ 'zh-HK' : 'LANG_CHINESE, SUBLANG_CHINESE_HONGKONG',
-+ 'el' : 'LANG_GREEK, SUBLANG_DEFAULT',
-+ 'no' : 'LANG_NORWEGIAN, SUBLANG_DEFAULT',
-+ 'nb' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL',
-+ 'nn' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK',
-+ 'th' : 'LANG_THAI, SUBLANG_DEFAULT',
-+ 'he' : 'LANG_HEBREW, SUBLANG_DEFAULT',
-+ 'iw' : 'LANG_HEBREW, SUBLANG_DEFAULT',
-+ 'pl' : 'LANG_POLISH, SUBLANG_DEFAULT',
-+ 'tr' : 'LANG_TURKISH, SUBLANG_DEFAULT',
-+ 'hr' : 'LANG_CROATIAN, SUBLANG_DEFAULT',
-+ 'hi' : 'LANG_HINDI, SUBLANG_DEFAULT',
-+ 'pt-PT' : 'LANG_PORTUGUESE, SUBLANG_PORTUGUESE',
-+ 'pt-BR' : 'LANG_PORTUGUESE, SUBLANG_DEFAULT',
-+ 'uk' : 'LANG_UKRAINIAN, SUBLANG_DEFAULT',
-+ 'cs' : 'LANG_CZECH, SUBLANG_DEFAULT',
-+ 'hu' : 'LANG_HUNGARIAN, SUBLANG_DEFAULT',
-+ 'ro' : 'LANG_ROMANIAN, SUBLANG_DEFAULT',
-+ 'ur' : 'LANG_URDU, SUBLANG_DEFAULT',
-+ 'da' : 'LANG_DANISH, SUBLANG_DEFAULT',
-+ 'is' : 'LANG_ICELANDIC, SUBLANG_DEFAULT',
-+ 'ru' : 'LANG_RUSSIAN, SUBLANG_DEFAULT',
-+ 'vi' : 'LANG_VIETNAMESE, SUBLANG_DEFAULT',
-+ 'nl' : 'LANG_DUTCH, SUBLANG_DEFAULT',
-+ 'id' : 'LANG_INDONESIAN, SUBLANG_DEFAULT',
-+ 'sr' : 'LANG_SERBIAN, SUBLANG_SERBIAN_LATIN',
-+ 'en-GB' : 'LANG_ENGLISH, SUBLANG_ENGLISH_UK',
-+ 'it' : 'LANG_ITALIAN, SUBLANG_DEFAULT',
-+ 'sk' : 'LANG_SLOVAK, SUBLANG_DEFAULT',
-+ 'et' : 'LANG_ESTONIAN, SUBLANG_DEFAULT',
-+ 'ja' : 'LANG_JAPANESE, SUBLANG_DEFAULT',
-+ 'sl' : 'LANG_SLOVENIAN, SUBLANG_DEFAULT',
-+ 'en' : 'LANG_ENGLISH, SUBLANG_ENGLISH_US',
-+ # No L.A. sublang exists.
-+ 'es-419' : 'LANG_SPANISH, SUBLANG_SPANISH_MEXICAN',
-+ 'bn' : 'LANG_BENGALI, SUBLANG_DEFAULT',
-+ 'fa' : 'LANG_PERSIAN, SUBLANG_DEFAULT',
-+ 'gu' : 'LANG_GUJARATI, SUBLANG_DEFAULT',
-+ 'kn' : 'LANG_KANNADA, SUBLANG_DEFAULT',
-+ 'ms' : 'LANG_MALAY, SUBLANG_DEFAULT',
-+ 'ml' : 'LANG_MALAYALAM, SUBLANG_DEFAULT',
-+ 'mr' : 'LANG_MARATHI, SUBLANG_DEFAULT',
-+ 'or' : 'LANG_ORIYA, SUBLANG_DEFAULT',
-+ 'ta' : 'LANG_TAMIL, SUBLANG_DEFAULT',
-+ 'te' : 'LANG_TELUGU, SUBLANG_DEFAULT',
-+ 'am' : 'LANG_AMHARIC, SUBLANG_DEFAULT',
-+ 'sw' : 'LANG_SWAHILI, SUBLANG_DEFAULT',
-+ 'af' : 'LANG_AFRIKAANS, SUBLANG_DEFAULT',
-+ 'eu' : 'LANG_BASQUE, SUBLANG_DEFAULT',
-+ 'fr-CA' : 'LANG_FRENCH, SUBLANG_FRENCH_CANADIAN',
-+ 'gl' : 'LANG_GALICIAN, SUBLANG_DEFAULT',
-+ 'zu' : 'LANG_ZULU, SUBLANG_DEFAULT',
-+ 'pa' : 'LANG_PUNJABI, SUBLANG_PUNJABI_INDIA',
-+ 'sa' : 'LANG_SANSKRIT, SUBLANG_SANSKRIT_INDIA',
-+ 'si' : 'LANG_SINHALESE, SUBLANG_SINHALESE_SRI_LANKA',
-+ 'ne' : 'LANG_NEPALI, SUBLANG_NEPALI_NEPAL',
-+ 'ti' : 'LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ERITREA',
-+ 'fake-bidi' : 'LANG_HEBREW, SUBLANG_DEFAULT',
-+}
-+
-+# A note on 'no-specific-language' in the following few functions:
-+# Some build systems may wish to call GRIT to scan for dependencies in
-+# a language-agnostic way, and can then specify this fake language as
-+# the output context. It should never be used when output is actually
-+# being generated.
-+
-+def GetLangCharsetPair(language):
-+ if language in _LANGUAGE_CHARSET_PAIR:
-+ return _LANGUAGE_CHARSET_PAIR[language]
-+ if language != 'no-specific-language':
-+ print('Warning:GetLangCharsetPair() found undefined language %s' % language)
-+ return ''
-+
-+def GetLangDirectivePair(language):
-+ if language in _LANGUAGE_DIRECTIVE_PAIR:
-+ return _LANGUAGE_DIRECTIVE_PAIR[language]
-+
-+ # We don't check for 'no-specific-language' here because this
-+ # function should only get called when output is being formatted,
-+ # and at that point we would not want to get
-+ # 'no-specific-language' passed as the language.
-+ print('Warning:GetLangDirectivePair() found undefined language %s' % language)
-+ return 'unknown language: see tools/grit/format/rc.py'
-+
-+def GetLangIdHex(language):
-+ if language in _LANGUAGE_CHARSET_PAIR:
-+ langcharset = _LANGUAGE_CHARSET_PAIR[language]
-+ lang_id = '0x' + langcharset[0:4]
-+ return lang_id
-+ if language != 'no-specific-language':
-+ print('Warning:GetLangIdHex() found undefined language %s' % language)
-+ return ''
-+
-+
-+def GetCharsetIdDecimal(language):
-+ if language in _LANGUAGE_CHARSET_PAIR:
-+ langcharset = _LANGUAGE_CHARSET_PAIR[language]
-+ charset_decimal = int(langcharset[4:], 16)
-+ return str(charset_decimal)
-+ if language != 'no-specific-language':
-+ print('Warning:GetCharsetIdDecimal() found undefined language %s' % language)
-+ return ''
-+
-+
-+def GetUnifiedLangCode(language) :
-+ r = re.compile('([a-z]{1,2})_([a-z]{1,2})')
-+ if r.match(language) :
-+ underscore = language.find('_')
-+ return language[0:underscore] + '-' + language[underscore + 1:].upper()
-+ return language
-+
-+
-+def RcSubstitutions(substituter, lang):
-+ '''Add language-based substitutions for Rc files to the substitutor.'''
-+ unified_lang_code = GetUnifiedLangCode(lang)
-+ substituter.AddSubstitutions({
-+ 'GRITVERLANGCHARSETHEX': GetLangCharsetPair(unified_lang_code),
-+ 'GRITVERLANGID': GetLangIdHex(unified_lang_code),
-+ 'GRITVERCHARSETID': GetCharsetIdDecimal(unified_lang_code)})
-+
-+
-+def _FormatHeader(root, lang, output_dir):
-+ '''Returns the required preamble for RC files.'''
-+ assert isinstance(lang, six.string_types)
-+ assert isinstance(root, misc.GritNode)
-+ # Find the location of the resource header file, so that we can include
-+ # it.
-+ resource_header = 'resource.h' # fall back to this
-+ language_directive = ''
-+ for output in root.GetOutputFiles():
-+ if output.attrs['type'] == 'rc_header':
-+ resource_header = os.path.abspath(output.GetOutputFilename())
-+ resource_header = util.MakeRelativePath(output_dir, resource_header)
-+ if output.attrs['lang'] != lang:
-+ continue
-+ if output.attrs['language_section'] == '':
-+ # If no language_section is requested, no directive is added
-+ # (Used when the generated rc will be included from another rc
-+ # file that will have the appropriate language directive)
-+ language_directive = ''
-+ elif output.attrs['language_section'] == 'neutral':
-+ # If a neutral language section is requested (default), add a
-+ # neutral language directive
-+ language_directive = 'LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL'
-+ elif output.attrs['language_section'] == 'lang':
-+ language_directive = 'LANGUAGE %s' % GetLangDirectivePair(lang)
-+ resource_header = resource_header.replace('\\', '\\\\')
-+ return '''// This file is automatically generated by GRIT. Do not edit.
-+
-+#include "%s"
-+#include <winresrc.h>
-+#ifdef IDC_STATIC
-+#undef IDC_STATIC
-+#endif
-+#define IDC_STATIC (-1)
-+
-+%s
-+
-+
-+''' % (resource_header, language_directive)
-+# end _FormatHeader() function
-+
-+
-+def FormatMessage(item, lang):
-+ '''Returns a single message of a string table.'''
-+ message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
-+ # Escape quotation marks (RC format uses doubling-up
-+ message = message.replace('"', '""')
-+ # Replace linebreaks with a \n escape
-+ message = util.LINEBREAKS.sub(r'\\n', message)
-+ if hasattr(item.GetRoot(), 'GetSubstituter'):
-+ substituter = item.GetRoot().GetSubstituter()
-+ message = substituter.Substitute(message)
-+
-+ name_attr = item.GetTextualIds()[0]
-+
-+ return ' %-15s "%s"\n' % (name_attr, message)
-+
-+
-+def _FormatSection(item, lang, output_dir):
-+ '''Writes out an .rc file section.'''
-+ assert isinstance(lang, six.string_types)
-+ from grit.node import structure
-+ assert isinstance(item, structure.StructureNode)
-+
-+ if item.IsExcludedFromRc():
-+ return ''
-+
-+ text = item.gatherer.Translate(
-+ lang, skeleton_gatherer=item.GetSkeletonGatherer(),
-+ pseudo_if_not_available=item.PseudoIsAllowed(),
-+ fallback_to_english=item.ShouldFallbackToEnglish()) + '\n\n'
-+
-+ # Replace the language expand_variables in version rc info.
-+ if item.ExpandVariables() and hasattr(item.GetRoot(), 'GetSubstituter'):
-+ substituter = item.GetRoot().GetSubstituter()
-+ text = substituter.Substitute(text)
-+ return text
-+
-+
-+def FormatInclude(item, lang, output_dir, type=None, process_html=False):
-+ '''Formats an item that is included in an .rc file (e.g. an ICON).
-+
-+ Args:
-+ item: an IncludeNode or StructureNode
-+ lang, output_dir: standard formatter parameters
-+ type: .rc file resource type, e.g. 'ICON' (ignored unless item is a
-+ StructureNode)
-+ process_html: False/True (ignored unless item is a StructureNode)
-+ '''
-+ assert isinstance(lang, six.string_types)
-+ from grit.node import structure
-+ from grit.node import include
-+ assert isinstance(item, (structure.StructureNode, include.IncludeNode))
-+
-+ if isinstance(item, include.IncludeNode):
-+ type = item.attrs['type'].upper()
-+ process_html = item.attrs['flattenhtml'] == 'true'
-+ filename_only = item.attrs['filenameonly'] == 'true'
-+ relative_path = item.attrs['relativepath'] == 'true'
-+ else:
-+ assert (isinstance(item, structure.StructureNode) and item.attrs['type'] in
-+ ['admin_template', 'chrome_html', 'chrome_scaled_image',
-+ 'tr_html', 'txt'])
-+ filename_only = False
-+ relative_path = False
-+
-+ # By default, we use relative pathnames to included resources so that
-+ # sharing the resulting .rc files is possible.
-+ #
-+ # The FileForLanguage() Function has the side effect of generating the file
-+ # if needed (e.g. if it is an HTML file include).
-+ file_for_lang = item.FileForLanguage(lang, output_dir)
-+ if file_for_lang is None:
-+ return ''
-+
-+ filename = os.path.abspath(file_for_lang)
-+ if process_html:
-+ filename = item.Process(output_dir)
-+ elif filename_only:
-+ filename = os.path.basename(filename)
-+ elif relative_path:
-+ filename = util.MakeRelativePath(output_dir, filename)
-+
-+ filename = filename.replace('\\', '\\\\') # escape for the RC format
-+
-+ if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc():
-+ return ''
-+
-+ name = item.attrs['name']
-+ item_id = item.GetRoot().GetIdMap()[name]
-+ return '// ID: %d\n%-18s %-18s "%s"\n' % (item_id, name, type, filename)
-+
-+
-+def _DoNotFormat(item, lang, output_dir):
-+ return ''
-+
-+
-+# Formatter instance to use for each type attribute
-+# when formatting Structure nodes.
-+_STRUCTURE_FORMATTERS = {
-+ 'accelerators' : _FormatSection,
-+ 'dialog' : _FormatSection,
-+ 'menu' : _FormatSection,
-+ 'rcdata' : _FormatSection,
-+ 'version' : _FormatSection,
-+ 'admin_template' : partial(FormatInclude, type='ADM'),
-+ 'chrome_html' : partial(FormatInclude, type='BINDATA',
-+ process_html=True),
-+ 'chrome_scaled_image' : partial(FormatInclude, type='BINDATA'),
-+ 'tr_html' : partial(FormatInclude, type='HTML'),
-+ 'txt' : partial(FormatInclude, type='TXT'),
-+ 'policy_template_metafile': _DoNotFormat,
-+}
-+
-+
-+def FormatStructure(item, lang, output_dir):
-+ formatter = _STRUCTURE_FORMATTERS[item.attrs['type']]
-+ return formatter(item, lang, output_dir)
-diff --git a/tools/grit/grit/format/rc_header.py b/tools/grit/grit/format/rc_header.py
-new file mode 100644
-index 0000000000..ea2c217f53
---- /dev/null
-+++ b/tools/grit/grit/format/rc_header.py
-@@ -0,0 +1,48 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Item formatters for RC headers.
-+'''
-+
-+from __future__ import print_function
-+
-+
-+def Format(root, lang='en', output_dir='.'):
-+ yield '''\
-+// This file is automatically generated by GRIT. Do not edit.
-+
-+#pragma once
-+'''
-+ # Check for emit nodes under the rc_header. If any emit node
-+ # is present, we assume it means the GRD file wants to override
-+ # the default header, with no includes.
-+ default_includes = ['#include <atlres.h>', '']
-+ emit_lines = []
-+ for output_node in root.GetOutputFiles():
-+ if output_node.GetType() == 'rc_header':
-+ for child in output_node.children:
-+ if child.name == 'emit' and child.attrs['emit_type'] == 'prepend':
-+ emit_lines.append(child.GetCdata())
-+ for line in emit_lines or default_includes:
-+ yield line + '\n'
-+ if root.IsWhitelistSupportEnabled():
-+ yield '#include "ui/base/resource/whitelist.h"\n'
-+ for line in FormatDefines(root):
-+ yield line
-+
-+
-+def FormatDefines(root):
-+ '''Yields #define SYMBOL 1234 lines.
-+
-+ Args:
-+ root: A GritNode.
-+ '''
-+ tids = root.GetIdMap()
-+ rc_header_format = '#define {0} {1}\n'
-+ if root.IsWhitelistSupportEnabled():
-+ rc_header_format = '#define {0} (::ui::WhitelistedResource<{1}>(), {1})\n'
-+ for item in root.ActiveDescendants():
-+ with item:
-+ for tid in item.GetTextualIds():
-+ yield rc_header_format.format(tid, tids[tid])
-diff --git a/tools/grit/grit/format/rc_header_unittest.py b/tools/grit/grit/format/rc_header_unittest.py
-new file mode 100644
-index 0000000000..eed4d70a99
---- /dev/null
-+++ b/tools/grit/grit/format/rc_header_unittest.py
-@@ -0,0 +1,138 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for the rc_header formatter'''
-+
-+# GRD samples exceed the 80 character limit.
-+# pylint: disable-msg=C6310
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import unittest
-+
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+from grit import util
-+from grit.format import rc_header
-+
-+
-+class RcHeaderFormatterUnittest(unittest.TestCase):
-+ def FormatAll(self, grd):
-+ output = rc_header.FormatDefines(grd)
-+ return ''.join(output).replace(' ', '')
-+
-+ def testFormatter(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <includes first_id="300" comment="bingo">
-+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
-+ </includes>
-+ <messages first_id="10000">
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ <message name="IDS_BONGO">
-+ Bongo!
-+ </message>
-+ </messages>
-+ <structures>
-+ <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc" />
-+ <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc" />
-+ </structures>''')
-+ output = self.FormatAll(grd)
-+ self.failUnless(output.count('IDS_GREETING10000'))
-+ self.failUnless(output.count('ID_LOGO300'))
-+
-+ def testOnlyDefineResourcesThatSatisfyOutputCondition(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <includes first_id="300" comment="bingo">
-+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
-+ </includes>
-+ <messages first_id="10000">
-+ <message name="IDS_FIRSTPRESENTSTRING" desc="Present in .rc file.">
-+ I will appear in the .rc file.
-+ </message>
-+ <if expr="False"> <!--Do not include in the .rc files until used.-->
-+ <message name="IDS_MISSINGSTRING" desc="Not present in .rc file.">
-+ I will not appear in the .rc file.
-+ </message>
-+ </if>
-+ <if expr="lang != 'es'">
-+ <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
-+ Hello.
-+ </message>
-+ </if>
-+ <if expr="lang == 'es'">
-+ <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
-+ Hola.
-+ </message>
-+ </if>
-+ <message name="IDS_THIRDPRESENTSTRING" desc="Present in .rc file.">
-+ I will also appear in the .rc file.
-+ </message>
-+ </messages>''')
-+ output = self.FormatAll(grd)
-+ self.failUnless(output.count('IDS_FIRSTPRESENTSTRING10000'))
-+ self.failIf(output.count('IDS_MISSINGSTRING'))
-+ self.failUnless(output.count('IDS_LANGUAGESPECIFICSTRING10002'))
-+ self.failUnless(output.count('IDS_THIRDPRESENTSTRING10003'))
-+
-+ def testEmit(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <outputs>
-+ <output type="rc_all" filename="dummy">
-+ <emit emit_type="prepend">Wrong</emit>
-+ </output>
-+ <if expr="False">
-+ <output type="rc_header" filename="dummy">
-+ <emit emit_type="prepend">No</emit>
-+ </output>
-+ </if>
-+ <output type="rc_header" filename="dummy">
-+ <emit emit_type="append">Error</emit>
-+ </output>
-+ <output type="rc_header" filename="dummy">
-+ <emit emit_type="prepend">Bingo</emit>
-+ </output>
-+ </outputs>''')
-+ output = ''.join(rc_header.Format(grd, 'en', '.'))
-+ output = util.StripBlankLinesAndComments(output)
-+ self.assertEqual('#pragma once\nBingo', output)
-+
-+ def testRcHeaderFormat(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <includes first_id="300" comment="bingo">
-+ <include type="gif" name="IDR_LOGO" file="images/logo.gif" />
-+ </includes>
-+ <messages first_id="10000">
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ <message name="IDS_BONGO">
-+ Bongo!
-+ </message>
-+ </messages>''')
-+
-+ # Using the default settings.
-+ output = rc_header.FormatDefines(grd)
-+ self.assertEqual(('#define IDR_LOGO 300\n'
-+ '#define IDS_GREETING 10000\n'
-+ '#define IDS_BONGO 10001\n'), ''.join(output))
-+
-+ # Using resource whitelist support.
-+ grd.SetWhitelistSupportEnabled(True)
-+ output = rc_header.FormatDefines(grd)
-+ self.assertEqual(('#define IDR_LOGO '
-+ '(::ui::WhitelistedResource<300>(), 300)\n'
-+ '#define IDS_GREETING '
-+ '(::ui::WhitelistedResource<10000>(), 10000)\n'
-+ '#define IDS_BONGO '
-+ '(::ui::WhitelistedResource<10001>(), 10001)\n'),
-+ ''.join(output))
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/rc_unittest.py b/tools/grit/grit/format/rc_unittest.py
-new file mode 100644
-index 0000000000..d23f063596
---- /dev/null
-+++ b/tools/grit/grit/format/rc_unittest.py
-@@ -0,0 +1,415 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.format.rc'''
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import tempfile
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import grd_reader
-+from grit import util
-+from grit.node import structure
-+from grit.tool import build
-+
-+
-+_PREAMBLE = '''\
-+#include "resource.h"
-+#include <winresrc.h>
-+#ifdef IDC_STATIC
-+#undef IDC_STATIC
-+#endif
-+#define IDC_STATIC (-1)
-+'''
-+
-+
-+class DummyOutput(object):
-+ def __init__(self, type, language, file = 'hello.gif'):
-+ self.type = type
-+ self.language = language
-+ self.file = file
-+
-+ def GetType(self):
-+ return self.type
-+
-+ def GetLanguage(self):
-+ return self.language
-+
-+ def GetOutputFilename(self):
-+ return self.file
-+
-+
-+class FormatRcUnittest(unittest.TestCase):
-+ def testMessages(self):
-+ root = util.ParseGrdForUnittest("""
-+ <messages>
-+ <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ <message name="BONGO" desc="Flippo nippo">
-+ Howdie "Mr. Elephant", how are you doing? '''
-+ </message>
-+ <message name="IDS_WITH_LINEBREAKS">
-+Good day sir,
-+I am a bee
-+Sting sting
-+ </message>
-+ </messages>
-+ """)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+ self.assertEqual(_PREAMBLE + u'''\
-+STRINGTABLE
-+BEGIN
-+ IDS_BTN_GO "Go!"
-+ IDS_GREETING "Hello %s, how are you doing today?"
-+ BONGO "Howdie ""Mr. Elephant"", how are you doing? "
-+ IDS_WITH_LINEBREAKS "Good day sir,\\nI am a bee\\nSting sting"
-+END''', output)
-+
-+ def testRcSection(self):
-+ root = util.ParseGrdForUnittest(r'''
-+ <structures>
-+ <structure type="menu" name="IDC_KLONKMENU" file="grit\testdata\klonk.rc" encoding="utf-16" />
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\testdata\klonk.rc" encoding="utf-16" />
-+ <structure type="version" name="VS_VERSION_INFO" file="grit\testdata\klonk.rc" encoding="utf-16" />
-+ </structures>''')
-+ root.SetOutputLanguage('en')
-+ root.RunGatherers()
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+ expected = _PREAMBLE + u'''\
-+IDC_KLONKMENU MENU
-+BEGIN
-+ POPUP "&File"
-+ BEGIN
-+ MENUITEM "E&xit", IDM_EXIT
-+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
-+ POPUP "gonk"
-+ BEGIN
-+ MENUITEM "Klonk && is [good]", ID_GONK_KLONKIS
-+ END
-+ END
-+ POPUP "&Help"
-+ BEGIN
-+ MENUITEM "&About ...", IDM_ABOUT
-+ END
-+END
-+
-+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "About"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
-+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
-+ SS_NOPREFIX
-+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
-+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
-+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
-+ BS_AUTORADIOBUTTON,46,51,84,10
-+END
-+
-+VS_VERSION_INFO VERSIONINFO
-+ FILEVERSION 1,0,0,1
-+ PRODUCTVERSION 1,0,0,1
-+ FILEFLAGSMASK 0x17L
-+#ifdef _DEBUG
-+ FILEFLAGS 0x1L
-+#else
-+ FILEFLAGS 0x0L
-+#endif
-+ FILEOS 0x4L
-+ FILETYPE 0x1L
-+ FILESUBTYPE 0x0L
-+BEGIN
-+ BLOCK "StringFileInfo"
-+ BEGIN
-+ BLOCK "040904b0"
-+ BEGIN
-+ VALUE "FileDescription", "klonk Application"
-+ VALUE "FileVersion", "1, 0, 0, 1"
-+ VALUE "InternalName", "klonk"
-+ VALUE "LegalCopyright", "Copyright (C) 2005"
-+ VALUE "OriginalFilename", "klonk.exe"
-+ VALUE "ProductName", " klonk Application"
-+ VALUE "ProductVersion", "1, 0, 0, 1"
-+ END
-+ END
-+ BLOCK "VarFileInfo"
-+ BEGIN
-+ VALUE "Translation", 0x409, 1200
-+ END
-+END'''.strip()
-+ for expected_line, output_line in zip(expected.split(), output.split()):
-+ self.assertEqual(expected_line, output_line)
-+
-+ def testRcIncludeStructure(self):
-+ root = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure type="tr_html" name="IDR_HTML" file="bingo.html"/>
-+ <structure type="tr_html" name="IDR_HTML2" file="bingo2.html"/>
-+ </structures>''', base_dir = '/temp')
-+ # We do not run gatherers as it is not needed and wouldn't find the file
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+ expected = (_PREAMBLE +
-+ u'IDR_HTML HTML "%s"\n'
-+ u'IDR_HTML2 HTML "%s"'
-+ % (util.normpath('/temp/bingo.html').replace('\\', '\\\\'),
-+ util.normpath('/temp/bingo2.html').replace('\\', '\\\\')))
-+ # hackety hack to work on win32&lin
-+ output = re.sub(r'"[c-zC-Z]:', '"', output)
-+ self.assertEqual(expected, output)
-+
-+ def testRcIncludeFile(self):
-+ root = util.ParseGrdForUnittest('''
-+ <includes>
-+ <include type="TXT" name="TEXT_ONE" file="bingo.txt"/>
-+ <include type="TXT" name="TEXT_TWO" file="bingo2.txt" filenameonly="true" />
-+ </includes>''', base_dir = '/temp')
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+ expected = (_PREAMBLE +
-+ u'TEXT_ONE TXT "%s"\n'
-+ u'TEXT_TWO TXT "%s"'
-+ % (util.normpath('/temp/bingo.txt').replace('\\', '\\\\'),
-+ 'bingo2.txt'))
-+ # hackety hack to work on win32&lin
-+ output = re.sub(r'"[c-zC-Z]:', '"', output)
-+ self.assertEqual(expected, output)
-+
-+ def testRcIncludeFlattenedHtmlFile(self):
-+ input_file = util.PathFromRoot('grit/testdata/include_test.html')
-+ output_file = '%s/HTML_FILE1_include_test.html' % tempfile.gettempdir()
-+ root = util.ParseGrdForUnittest('''
-+ <includes>
-+ <include name="HTML_FILE1" flattenhtml="true" file="%s" type="BINDATA" />
-+ </includes>''' % input_file)
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
-+ buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+
-+ expected = (_PREAMBLE +
-+ u'HTML_FILE1 BINDATA "HTML_FILE1_include_test.html"')
-+ # hackety hack to work on win32&lin
-+ output = re.sub(r'"[c-zC-Z]:', '"', output)
-+ self.assertEqual(expected, output)
-+
-+ file_contents = util.ReadFile(output_file, 'utf-8')
-+
-+ # Check for the content added by the <include> tag.
-+ self.failUnless(file_contents.find('Hello Include!') != -1)
-+ # Check for the content that was removed by if tag.
-+ self.failUnless(file_contents.find('should be removed') == -1)
-+ # Check for the content that was kept in place by if.
-+ self.failUnless(file_contents.find('should be kept') != -1)
-+ self.failUnless(file_contents.find('in the middle...') != -1)
-+ self.failUnless(file_contents.find('at the end...') != -1)
-+ # Check for nested content that was kept
-+ self.failUnless(file_contents.find('nested true should be kept') != -1)
-+ self.failUnless(file_contents.find('silbing true should be kept') != -1)
-+ # Check for removed "<if>" and "</if>" tags.
-+ self.failUnless(file_contents.find('<if expr=') == -1)
-+ self.failUnless(file_contents.find('</if>') == -1)
-+ os.remove(output_file)
-+
-+ def testStructureNodeOutputfile(self):
-+ input_file = util.PathFromRoot('grit/testdata/simple.html')
-+ root = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure type="tr_html" name="IDR_HTML" file="%s" />
-+ </structures>''' % input_file)
-+ struct, = root.GetChildrenOfType(structure.StructureNode)
-+ # We must run the gatherer since we'll be wanting the translation of the
-+ # file. The file exists in the location pointed to.
-+ root.SetOutputLanguage('en')
-+ root.RunGatherers()
-+
-+ output_dir = tempfile.gettempdir()
-+ en_file = struct.FileForLanguage('en', output_dir)
-+ self.failUnless(en_file == input_file)
-+ fr_file = struct.FileForLanguage('fr', output_dir)
-+ self.failUnless(fr_file == os.path.join(output_dir, 'fr_simple.html'))
-+
-+ contents = util.ReadFile(fr_file, 'utf-8')
-+
-+ self.failUnless(contents.find('<p>') != -1) # should contain the markup
-+ self.failUnless(contents.find('Hello!') == -1) # should be translated
-+ os.remove(fr_file)
-+
-+ def testChromeHtmlNodeOutputfile(self):
-+ input_file = util.PathFromRoot('grit/testdata/chrome_html.html')
-+ output_file = '%s/HTML_FILE1_chrome_html.html' % tempfile.gettempdir()
-+ root = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure type="chrome_html" name="HTML_FILE1" file="%s" flattenhtml="true" />
-+ </structures>''' % input_file)
-+ struct, = root.GetChildrenOfType(structure.StructureNode)
-+ struct.gatherer.SetDefines({'scale_factors': '2x'})
-+ # We must run the gatherers since we'll be wanting the chrome_html output.
-+ # The file exists in the location pointed to.
-+ root.SetOutputLanguage('en')
-+ root.RunGatherers()
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
-+ buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+ expected = (_PREAMBLE +
-+ u'HTML_FILE1 BINDATA "HTML_FILE1_chrome_html.html"')
-+ # hackety hack to work on win32&lin
-+ output = re.sub(r'"[c-zC-Z]:', '"', output)
-+ self.assertEqual(expected, output)
-+
-+ file_contents = util.ReadFile(output_file, 'utf-8')
-+
-+ # Check for the content added by the <include> tag.
-+ self.failUnless(file_contents.find('Hello Include!') != -1)
-+ # Check for inserted -webkit-image-set.
-+ self.failUnless(file_contents.find('content: -webkit-image-set') != -1)
-+ os.remove(output_file)
-+
-+ def testSubstitutionHtml(self):
-+ input_file = util.PathFromRoot('grit/testdata/toolbar_about.html')
-+ root = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="1" allow_pseudo="False">
-+ <structures fallback_to_english="True">
-+ <structure type="tr_html" name="IDR_HTML" file="%s" expand_variables="true"/>
-+ </structures>
-+ </release>
-+ </grit>
-+ ''' % input_file), util.PathFromRoot('.'))
-+ root.SetOutputLanguage('ar')
-+ # We must run the gatherers since we'll be wanting the translation of the
-+ # file. The file exists in the location pointed to.
-+ root.RunGatherers()
-+
-+ output_dir = tempfile.gettempdir()
-+ struct, = root.GetChildrenOfType(structure.StructureNode)
-+ ar_file = struct.FileForLanguage('ar', output_dir)
-+ self.failUnless(ar_file == os.path.join(output_dir,
-+ 'ar_toolbar_about.html'))
-+
-+ contents = util.ReadFile(ar_file, 'utf-8')
-+
-+ self.failUnless(contents.find('dir="RTL"') != -1)
-+ os.remove(ar_file)
-+
-+ def testFallbackToEnglish(self):
-+ root = util.ParseGrdForUnittest(r'''
-+ <structures fallback_to_english="True">
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\testdata\klonk.rc" encoding="utf-16" />
-+ </structures>''', base_dir=util.PathFromRoot('.'))
-+ root.SetOutputLanguage('en')
-+ root.RunGatherers()
-+
-+ buf = StringIO()
-+ formatter = build.RcBuilder.ProcessNode(
-+ root, DummyOutput('rc_all', 'bingobongo'), buf)
-+ output = util.StripBlankLinesAndComments(buf.getvalue())
-+ self.assertEqual(_PREAMBLE + '''\
-+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "About"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
-+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
-+ SS_NOPREFIX
-+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
-+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
-+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
-+ BS_AUTORADIOBUTTON,46,51,84,10
-+END''', output)
-+
-+
-+ def testSubstitutionRc(self):
-+ root = grd_reader.Parse(StringIO(r'''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
-+ base_dir=".">
-+ <outputs>
-+ <output lang="en" type="rc_all" filename="grit\testdata\klonk_resources.rc"/>
-+ </outputs>
-+ <release seq="1" allow_pseudo="False">
-+ <structures>
-+ <structure type="menu" name="IDC_KLONKMENU"
-+ file="grit\testdata\klonk.rc" encoding="utf-16"
-+ expand_variables="true" />
-+ </structures>
-+ <messages>
-+ <message name="good" sub_variable="true">
-+ excellent
-+ </message>
-+ </messages>
-+ </release>
-+ </grit>
-+ '''), util.PathFromRoot('.'))
-+ root.SetOutputLanguage('en')
-+ root.RunGatherers()
-+
-+ buf = StringIO()
-+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
-+ output = buf.getvalue()
-+ self.assertEqual('''
-+// This file is automatically generated by GRIT. Do not edit.
-+
-+#include "resource.h"
-+#include <winresrc.h>
-+#ifdef IDC_STATIC
-+#undef IDC_STATIC
-+#endif
-+#define IDC_STATIC (-1)
-+
-+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
-+
-+
-+IDC_KLONKMENU MENU
-+BEGIN
-+ POPUP "&File"
-+ BEGIN
-+ MENUITEM "E&xit", IDM_EXIT
-+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
-+ POPUP "gonk"
-+ BEGIN
-+ MENUITEM "Klonk && is excellent", ID_GONK_KLONKIS
-+ END
-+ END
-+ POPUP "&Help"
-+ BEGIN
-+ MENUITEM "&About ...", IDM_ABOUT
-+ END
-+END
-+
-+STRINGTABLE
-+BEGIN
-+ good "excellent"
-+END
-+'''.strip(), output.strip())
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py
-new file mode 100644
-index 0000000000..95a8b83160
---- /dev/null
-+++ b/tools/grit/grit/format/resource_map.py
-@@ -0,0 +1,159 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''This file contains item formatters for resource_map_header and
-+resource_map_source files. A resource map is a mapping between resource names
-+(string) and the internal resource ID.'''
-+
-+from __future__ import print_function
-+
-+import os
-+from functools import partial
-+
-+from grit import util
-+
-+
-+def GetFormatter(type):
-+ if type == 'resource_map_header':
-+ return _FormatHeader
-+ if type == 'resource_file_map_source':
-+ return partial(_FormatSource, _GetItemPath)
-+ if type == 'resource_map_source':
-+ return partial(_FormatSource, _GetItemName)
-+
-+
-+def GetMapName(root):
-+ '''Get the name of the resource map based on the header file name. E.g.,
-+ if our header filename is theme_resources.h, we name our resource map
-+ kThemeResourcesMap.
-+
-+ |root| is the grd file root.'''
-+ outputs = root.GetOutputFiles()
-+ rc_header_file = None
-+ for output in outputs:
-+ if 'rc_header' == output.GetType():
-+ rc_header_file = output.GetFilename()
-+ if not rc_header_file:
-+ raise Exception('unable to find resource header filename')
-+ filename = os.path.splitext(os.path.split(rc_header_file)[1])[0]
-+ filename = filename[0].upper() + filename[1:]
-+ while True:
-+ pos = filename.find('_')
-+ if pos == -1 or pos >= len(filename):
-+ break
-+ filename = filename[:pos] + filename[pos + 1].upper() + filename[pos + 2:]
-+ return 'k' + filename
-+
-+
-+def _FormatHeader(root, lang='en', output_dir='.'):
-+ '''Create the header file for the resource mapping. This file just declares
-+ an array of name/value pairs.'''
-+ return '''\
-+// This file is automatically generated by GRIT. Do not edit.
-+
-+#include <stddef.h>
-+
-+#ifndef GRIT_RESOURCE_MAP_STRUCT_
-+#define GRIT_RESOURCE_MAP_STRUCT_
-+struct GritResourceMap {
-+ const char* const name;
-+ int value;
-+};
-+#endif // GRIT_RESOURCE_MAP_STRUCT_
-+
-+extern const GritResourceMap %(map_name)s[];
-+extern const size_t %(map_name)sSize;
-+''' % { 'map_name': GetMapName(root) }
-+
-+
-+def _FormatSourceHeader(root, output_dir):
-+ '''Create the header of the C++ source file for the resource mapping.'''
-+ rc_header_file = None
-+ map_header_file = None
-+ for output in root.GetOutputFiles():
-+ type = output.GetType()
-+ if 'rc_header' == type:
-+ rc_header_file = util.MakeRelativePath(output_dir,
-+ output.GetOutputFilename())
-+ elif 'resource_map_header' == type:
-+ map_header_file = util.MakeRelativePath(output_dir,
-+ output.GetOutputFilename())
-+ if not rc_header_file or not map_header_file:
-+ raise Exception('resource_map_source output type requires '
-+ 'a resource_map_header and rc_header outputs')
-+ return '''\
-+// This file is automatically generated by GRIT. Do not edit.
-+
-+#include "%(map_header_file)s"
-+
-+#include <stddef.h>
-+
-+#include "base/stl_util.h"
-+
-+#include "%(rc_header_file)s"
-+
-+const GritResourceMap %(map_name)s[] = {
-+''' % { 'map_header_file': map_header_file,
-+ 'rc_header_file': rc_header_file,
-+ 'map_name': GetMapName(root),
-+ }
-+
-+
-+def _FormatSourceFooter(root):
-+ # Return the footer text.
-+ return '''\
-+};
-+
-+const size_t %(map_name)sSize = base::size(%(map_name)s);
-+''' % { 'map_name': GetMapName(root) }
-+
-+
-+def _FormatSource(get_key, root, lang, output_dir):
-+ from grit.node import include, structure, message
-+ id_map = root.GetIdMap()
-+ yield _FormatSourceHeader(root, output_dir)
-+ seen = set()
-+ for item in root.ActiveDescendants():
-+ if not item.IsResourceMapSource():
-+ continue
-+ key = get_key(item)
-+ tid = item.attrs['name']
-+ if tid not in id_map or key in seen:
-+ continue
-+ seen.add(key)
-+ yield ' {"%s", %s},\n' % (key, tid)
-+ yield _FormatSourceFooter(root)
-+
-+
-+def _GetItemName(item):
-+ return item.attrs['name']
-+
-+# Check if |path2| is a subpath of |path1|.
-+def _IsSubpath(path1, path2):
-+ path1_abs = os.path.abspath(path1)
-+ path2_abs = os.path.abspath(path2)
-+ common = os.path.commonprefix([path1_abs, path2_abs])
-+ return path1_abs == common
-+
-+def _GetItemPath(item):
-+ path = item.GetInputPath().replace("\\", "/")
-+
-+ # Handle the case where the file resides within the output folder,
-+ # by expanding any variables as well as replacing the output folder name with
-+ # a fixed string such that the key added to the map does not depend on a given
-+ # developer's setup.
-+ #
-+ # For example this will convert the following path:
-+ # ../../out/gchrome/${root_gen_dir}/ui/webui/resources/js/foo.js
-+ # to:
-+ # @out_folder@/gen/ui/webui/resources/js/foo.js
-+
-+ real_path = item.ToRealPath(item.GetInputPath())
-+ if (item.attrs.get('use_base_dir', 'true') != 'true' and
-+ _IsSubpath(os.path.curdir, real_path)):
-+ path = os.path.join(
-+ '@out_folder@', os.path.relpath(real_path)).replace("\\", "/")
-+
-+ assert '$' not in path, 'all variables should have been expanded'
-+ return path
-diff --git a/tools/grit/grit/format/resource_map_unittest.py b/tools/grit/grit/format/resource_map_unittest.py
-new file mode 100644
-index 0000000000..3499b321ef
---- /dev/null
-+++ b/tools/grit/grit/format/resource_map_unittest.py
-@@ -0,0 +1,345 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.format.resource_map'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit import util
-+from grit.format import resource_map
-+
-+
-+class FormatResourceMapUnittest(unittest.TestCase):
-+ def testFormatResourceMap(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <outputs>
-+ <output type="rc_header" filename="the_rc_header.h" />
-+ <output type="resource_map_header"
-+ filename="the_resource_map_header.h" />
-+ </outputs>
-+ <release seq="3">
-+ <structures first_id="300">
-+ <structure type="menu" name="IDC_KLONKMENU"
-+ file="grit\\testdata\\klonk.rc" encoding="utf-16" />
-+ </structures>
-+ <includes first_id="10000">
-+ <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
-+ <if expr="False">
-+ <include type="foo" file="def" name="IDS_MISSING" />
-+ </if>
-+ <if expr="lang != 'es'">
-+ <include type="foo" file="ghi" name="IDS_LANGUAGESPECIFIC" />
-+ </if>
-+ <if expr="lang == 'es'">
-+ <include type="foo" file="jkl" name="IDS_LANGUAGESPECIFIC" />
-+ </if>
-+ <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
-+ <include type="foo" file="opq" name="IDS_FOURTHPRESENT"
-+ skip_in_resource_map="true" />
-+ </includes>
-+ </release>''', run_gatherers=True)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include <stddef.h>
-+#ifndef GRIT_RESOURCE_MAP_STRUCT_
-+#define GRIT_RESOURCE_MAP_STRUCT_
-+struct GritResourceMap {
-+ const char* const name;
-+ int value;
-+};
-+#endif // GRIT_RESOURCE_MAP_STRUCT_
-+extern const GritResourceMap kTheRcHeader[];
-+extern const size_t kTheRcHeaderSize;''', output)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include "the_resource_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"IDC_KLONKMENU", IDC_KLONKMENU},
-+ {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
-+ {"IDS_LANGUAGESPECIFIC", IDS_LANGUAGESPECIFIC},
-+ {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include "the_resource_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"grit/testdata/klonk.rc", IDC_KLONKMENU},
-+ {"abc", IDS_FIRSTPRESENT},
-+ {"ghi", IDS_LANGUAGESPECIFIC},
-+ {"mno", IDS_THIRDPRESENT},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
-+
-+ def testFormatResourceMapWithGeneratedFile(self):
-+ os.environ["root_gen_dir"] = "gen"
-+
-+ grd = util.ParseGrdForUnittest('''\
-+ <outputs>
-+ <output type="rc_header" filename="the_rc_header.h" />
-+ <output type="resource_map_header"
-+ filename="resource_map_header.h" />
-+ </outputs>
-+ <release seq="3">
-+ <includes first_id="10000">
-+ <include type="BINDATA"
-+ file="${root_gen_dir}/foo/bar/baz.js"
-+ name="IDR_FOO_BAR_BAZ_JS"
-+ use_base_dir="false"
-+ compress="gzip" />
-+ </includes>
-+ </release>''', run_gatherers=True)
-+
-+ formatter = resource_map.GetFormatter('resource_file_map_source')
-+ output = util.StripBlankLinesAndComments(''.join(formatter(grd, 'en', '.')))
-+ expected = '''\
-+#include "resource_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"@out_folder@/gen/foo/bar/baz.js", IDR_FOO_BAR_BAZ_JS},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);'''
-+ self.assertEqual(expected, output)
-+
-+ def testFormatResourceMapWithOutputAllEqualsFalseForStructures(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <outputs>
-+ <output type="rc_header" filename="the_rc_header.h" />
-+ <output type="resource_map_header"
-+ filename="the_resource_map_header.h" />
-+ <output type="resource_map_source"
-+ filename="the_resource_map_header.cc" />
-+ </outputs>
-+ <release seq="3">
-+ <structures first_id="300">
-+ <structure type="chrome_scaled_image" name="IDR_KLONKMENU"
-+ file="foo.png" />
-+ <if expr="False">
-+ <structure type="chrome_scaled_image" name="IDR_MISSING"
-+ file="bar.png" />
-+ </if>
-+ <if expr="True">
-+ <structure type="chrome_scaled_image" name="IDR_BLOB"
-+ file="blob.png" />
-+ </if>
-+ <if expr="True">
-+ <then>
-+ <structure type="chrome_scaled_image" name="IDR_METEOR"
-+ file="meteor.png" />
-+ </then>
-+ <else>
-+ <structure type="chrome_scaled_image" name="IDR_METEOR"
-+ file="roetem.png" />
-+ </else>
-+ </if>
-+ <if expr="False">
-+ <structure type="chrome_scaled_image" name="IDR_LAST"
-+ file="zyx.png" />
-+ </if>
-+ <if expr="True">
-+ <structure type="chrome_scaled_image" name="IDR_LAST"
-+ file="xyz.png" />
-+ </if>
-+ </structures>
-+ </release>''', run_gatherers=True)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include <stddef.h>
-+#ifndef GRIT_RESOURCE_MAP_STRUCT_
-+#define GRIT_RESOURCE_MAP_STRUCT_
-+struct GritResourceMap {
-+ const char* const name;
-+ int value;
-+};
-+#endif // GRIT_RESOURCE_MAP_STRUCT_
-+extern const GritResourceMap kTheRcHeader[];
-+extern const size_t kTheRcHeaderSize;''', output)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include "the_resource_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"IDR_KLONKMENU", IDR_KLONKMENU},
-+ {"IDR_BLOB", IDR_BLOB},
-+ {"IDR_METEOR", IDR_METEOR},
-+ {"IDR_LAST", IDR_LAST},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include "the_resource_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"IDR_KLONKMENU", IDR_KLONKMENU},
-+ {"IDR_BLOB", IDR_BLOB},
-+ {"IDR_METEOR", IDR_METEOR},
-+ {"IDR_LAST", IDR_LAST},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
-+
-+ def testFormatResourceMapWithOutputAllEqualsFalseForIncludes(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <outputs>
-+ <output type="rc_header" filename="the_rc_header.h" />
-+ <output type="resource_map_header"
-+ filename="the_resource_map_header.h" />
-+ </outputs>
-+ <release seq="3">
-+ <structures first_id="300">
-+ <structure type="menu" name="IDC_KLONKMENU"
-+ file="grit\\testdata\\klonk.rc" encoding="utf-16" />
-+ </structures>
-+ <includes first_id="10000">
-+ <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
-+ <if expr="False">
-+ <include type="foo" file="def" name="IDS_MISSING" />
-+ </if>
-+ <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
-+ <if expr="True">
-+ <include type="foo" file="blob" name="IDS_BLOB" />
-+ </if>
-+ <if expr="True">
-+ <then>
-+ <include type="foo" file="meteor" name="IDS_METEOR" />
-+ </then>
-+ <else>
-+ <include type="foo" file="roetem" name="IDS_METEOR" />
-+ </else>
-+ </if>
-+ <if expr="False">
-+ <include type="foo" file="zyx" name="IDS_LAST" />
-+ </if>
-+ <if expr="True">
-+ <include type="foo" file="xyz" name="IDS_LAST" />
-+ </if>
-+ </includes>
-+ </release>''', run_gatherers=True)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include <stddef.h>
-+#ifndef GRIT_RESOURCE_MAP_STRUCT_
-+#define GRIT_RESOURCE_MAP_STRUCT_
-+struct GritResourceMap {
-+ const char* const name;
-+ int value;
-+};
-+#endif // GRIT_RESOURCE_MAP_STRUCT_
-+extern const GritResourceMap kTheRcHeader[];
-+extern const size_t kTheRcHeaderSize;''', output)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include "the_resource_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"IDC_KLONKMENU", IDC_KLONKMENU},
-+ {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
-+ {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
-+ {"IDS_BLOB", IDS_BLOB},
-+ {"IDS_METEOR", IDS_METEOR},
-+ {"IDS_LAST", IDS_LAST},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include "the_resource_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"grit/testdata/klonk.rc", IDC_KLONKMENU},
-+ {"abc", IDS_FIRSTPRESENT},
-+ {"mno", IDS_THIRDPRESENT},
-+ {"blob", IDS_BLOB},
-+ {"meteor", IDS_METEOR},
-+ {"xyz", IDS_LAST},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
-+
-+ def testFormatStringResourceMap(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <outputs>
-+ <output type="rc_header" filename="the_rc_header.h" />
-+ <output type="resource_map_header" filename="the_rc_map_header.h" />
-+ <output type="resource_map_source" filename="the_rc_map_source.cc" />
-+ </outputs>
-+ <release seq="1" allow_pseudo="false">
-+ <messages fallback_to_english="true">
-+ <message name="IDS_PRODUCT_NAME" desc="The application name">
-+ Application
-+ </message>
-+ <if expr="True">
-+ <message name="IDS_DEFAULT_TAB_TITLE_TITLE_CASE"
-+ desc="In Title Case: The default title in a tab.">
-+ New Tab
-+ </message>
-+ </if>
-+ <if expr="False">
-+ <message name="IDS_DEFAULT_TAB_TITLE"
-+ desc="The default title in a tab.">
-+ New tab
-+ </message>
-+ </if>
-+ </messages>
-+ </release>''', run_gatherers=True)
-+ grd.InitializeIds()
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include <stddef.h>
-+#ifndef GRIT_RESOURCE_MAP_STRUCT_
-+#define GRIT_RESOURCE_MAP_STRUCT_
-+struct GritResourceMap {
-+ const char* const name;
-+ int value;
-+};
-+#endif // GRIT_RESOURCE_MAP_STRUCT_
-+extern const GritResourceMap kTheRcHeader[];
-+extern const size_t kTheRcHeaderSize;''', output)
-+ output = util.StripBlankLinesAndComments(''.join(
-+ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
-+ self.assertEqual('''\
-+#include "the_rc_map_header.h"
-+#include <stddef.h>
-+#include "base/stl_util.h"
-+#include "the_rc_header.h"
-+const GritResourceMap kTheRcHeader[] = {
-+ {"IDS_PRODUCT_NAME", IDS_PRODUCT_NAME},
-+ {"IDS_DEFAULT_TAB_TITLE_TITLE_CASE", IDS_DEFAULT_TAB_TITLE_TITLE_CASE},
-+};
-+const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''', output)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/gather/__init__.py b/tools/grit/grit/gather/__init__.py
-new file mode 100644
-index 0000000000..2d578f5643
---- /dev/null
-+++ b/tools/grit/grit/gather/__init__.py
-@@ -0,0 +1,8 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Module grit.gather
-+'''
-+
-+pass
-diff --git a/tools/grit/grit/gather/admin_template.py b/tools/grit/grit/gather/admin_template.py
-new file mode 100644
-index 0000000000..c26b6a88d7
---- /dev/null
-+++ b/tools/grit/grit/gather/admin_template.py
-@@ -0,0 +1,62 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Gatherer for administrative template files.
-+'''
-+
-+from __future__ import print_function
-+
-+import re
-+
-+from grit.gather import regexp
-+from grit import exception
-+from grit import lazy_re
-+
-+
-+class MalformedAdminTemplateException(exception.Base):
-+ '''This file doesn't look like a .adm file to me.'''
-+ pass
-+
-+
-+class AdmGatherer(regexp.RegexpGatherer):
-+ '''Gatherer for the translateable portions of an admin template.
-+
-+ This gatherer currently makes the following assumptions:
-+ - there is only one [strings] section and it is always the last section
-+ of the file
-+ - translateable strings do not need to be escaped.
-+ '''
-+
-+ # Finds the strings section as the group named 'strings'
-+ _STRINGS_SECTION = lazy_re.compile(
-+ r'(?P<first_part>.+^\[strings\])(?P<strings>.+)\Z',
-+ re.MULTILINE | re.DOTALL)
-+
-+ # Finds the translateable sections from within the [strings] section.
-+ _TRANSLATEABLES = lazy_re.compile(
-+ r'^\s*[A-Za-z0-9_]+\s*=\s*"(?P<text>.+)"\s*$',
-+ re.MULTILINE)
-+
-+ def Escape(self, text):
-+ return text.replace('\n', '\\n')
-+
-+ def UnEscape(self, text):
-+ return text.replace('\\n', '\n')
-+
-+ def Parse(self):
-+ if self.have_parsed_:
-+ return
-+ self.have_parsed_ = True
-+
-+ self.text_ = self._LoadInputFile().strip()
-+ m = self._STRINGS_SECTION.match(self.text_)
-+ if not m:
-+ raise MalformedAdminTemplateException()
-+ # Add the first part, which is all nontranslateable, to the skeleton
-+ self._AddNontranslateableChunk(m.group('first_part'))
-+ # Then parse the rest using the _TRANSLATEABLES regexp.
-+ self._RegExpParse(self._TRANSLATEABLES, m.group('strings'))
-+
-+ def GetTextualIds(self):
-+ return [self.extkey]
-diff --git a/tools/grit/grit/gather/admin_template_unittest.py b/tools/grit/grit/gather/admin_template_unittest.py
-new file mode 100644
-index 0000000000..c637af3a75
---- /dev/null
-+++ b/tools/grit/grit/gather/admin_template_unittest.py
-@@ -0,0 +1,115 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for the admin template gatherer.'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit.gather import admin_template
-+from grit import util
-+from grit import grd_reader
-+from grit import grit_runner
-+from grit.tool import build
-+
-+
-+class AdmGathererUnittest(unittest.TestCase):
-+ def testParsingAndTranslating(self):
-+ pseudofile = StringIO(
-+ 'bingo bongo\n'
-+ 'ding dong\n'
-+ '[strings] \n'
-+ 'whatcha="bingo bongo"\n'
-+ 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
-+ gatherer = admin_template.AdmGatherer(pseudofile)
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 2)
-+ self.failUnless(gatherer.GetCliques()[1].GetMessage().GetRealContent() ==
-+ 'bingolabongola "the wise" fingulafongula')
-+
-+ translation = gatherer.Translate('en')
-+ self.failUnless(translation == gatherer.GetText().strip())
-+
-+ def testErrorHandling(self):
-+ pseudofile = StringIO(
-+ 'bingo bongo\n'
-+ 'ding dong\n'
-+ 'whatcha="bingo bongo"\n'
-+ 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
-+ gatherer = admin_template.AdmGatherer(pseudofile)
-+ self.assertRaises(admin_template.MalformedAdminTemplateException,
-+ gatherer.Parse)
-+
-+ _TRANSLATABLES_FROM_FILE = (
-+ 'Google', 'Google Desktop', 'Preferences',
-+ 'Controls Google Desktop preferences',
-+ 'Indexing and Capture Control',
-+ 'Controls what files, web pages, and other content will be indexed by Google Desktop.',
-+ 'Prevent indexing of email',
-+ # there are lots more but we don't check any further
-+ )
-+
-+ def VerifyCliquesFromAdmFile(self, cliques):
-+ self.failUnless(len(cliques) > 20)
-+ for clique, expected in zip(cliques, self._TRANSLATABLES_FROM_FILE):
-+ text = clique.GetMessage().GetRealContent()
-+ self.failUnless(text == expected)
-+
-+ def testFromFile(self):
-+ fname = util.PathFromRoot('grit/testdata/GoogleDesktop.adm')
-+ gatherer = admin_template.AdmGatherer(fname)
-+ gatherer.Parse()
-+ cliques = gatherer.GetCliques()
-+ self.VerifyCliquesFromAdmFile(cliques)
-+
-+ def MakeGrd(self):
-+ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3">
-+ <release seq="3">
-+ <structures>
-+ <structure type="admin_template" name="IDAT_GOOGLE_DESKTOP_SEARCH"
-+ file="GoogleDesktop.adm" exclude_from_rc="true" />
-+ <structure type="txt" name="BINGOBONGO"
-+ file="README.txt" exclude_from_rc="true" />
-+ </structures>
-+ </release>
-+ <outputs>
-+ <output filename="de_res.rc" type="rc_all" lang="de" />
-+ </outputs>
-+ </grit>'''), util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ return grd
-+
-+ def testInGrd(self):
-+ grd = self.MakeGrd()
-+ cliques = grd.children[0].children[0].children[0].GetCliques()
-+ self.VerifyCliquesFromAdmFile(cliques)
-+
-+ def testFileIsOutput(self):
-+ grd = self.MakeGrd()
-+ dirname = util.TempDir({})
-+ try:
-+ tool = build.RcBuilder()
-+ tool.o = grit_runner.Options()
-+ tool.output_directory = dirname.GetPath()
-+ tool.res = grd
-+ tool.Process()
-+
-+ self.failUnless(os.path.isfile(dirname.GetPath('de_GoogleDesktop.adm')))
-+ self.failUnless(os.path.isfile(dirname.GetPath('de_README.txt')))
-+ finally:
-+ dirname.CleanUp()
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/gather/chrome_html.py b/tools/grit/grit/gather/chrome_html.py
-new file mode 100644
-index 0000000000..71c1332d66
---- /dev/null
-+++ b/tools/grit/grit/gather/chrome_html.py
-@@ -0,0 +1,377 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Prepares a Chrome HTML file by inlining resources and adding references to
-+high DPI resources and removing references to unsupported scale factors.
-+
-+This is a small gatherer that takes a HTML file, looks for src attributes
-+and inlines the specified file, producing one HTML file with no external
-+dependencies. It recursively inlines the included files. When inlining CSS
-+image files this script also checks for the existence of high DPI versions
-+of the inlined file including those on relevant platforms. Unsupported scale
-+factors are also removed from existing image sets to support explicitly
-+referencing all available images.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+
-+from grit import lazy_re
-+from grit import util
-+from grit.format import html_inline
-+from grit.gather import interface
-+
-+
-+# Distribution string to replace with distribution.
-+DIST_SUBSTR = '%DISTRIBUTION%'
-+
-+
-+# Matches a chrome theme source URL.
-+_THEME_SOURCE = lazy_re.compile(
-+ r'(?P<baseurl>chrome://theme/IDR_[A-Z0-9_]*)(?P<query>\?.*)?')
-+# Pattern for matching CSS url() function.
-+_CSS_URL_PATTERN = r'url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)\)'
-+# Matches CSS url() functions with the capture group 'filename'.
-+_CSS_URL = lazy_re.compile(_CSS_URL_PATTERN)
-+# Matches one or more CSS image urls used in given properties.
-+_CSS_IMAGE_URLS = lazy_re.compile(
-+ r'(?P<attribute>content|background|[\w-]*-image):\s*'
-+ r'(?P<urls>(' + _CSS_URL_PATTERN + r'\s*,?\s*)+)')
-+# Matches CSS image sets.
-+_CSS_IMAGE_SETS = lazy_re.compile(
-+ r'(?P<attribute>content|background|[\w-]*-image):[ ]*'
-+ r'-webkit-image-set\((?P<images>'
-+ r'(\s*,?\s*url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*[0-9.]*x)*)\)',
-+ re.MULTILINE)
-+# Matches a single image in a CSS image set with the capture group scale.
-+_CSS_IMAGE_SET_IMAGE = lazy_re.compile(r'\s*,?\s*'
-+ r'url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*(?P<scale>[0-9.]*x)',
-+ re.MULTILINE)
-+_HTML_IMAGE_SRC = lazy_re.compile(
-+ r'<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>')
-+
-+def GetImageList(
-+ base_path, filename, scale_factors, distribution,
-+ filename_expansion_function=None):
-+ """Generate the list of images which match the provided scale factors.
-+
-+ Takes an image filename and checks for files of the same name in folders
-+ corresponding to the supported scale factors. If the file is from a
-+ chrome://theme/ source, inserts supported @Nx scale factors as high DPI
-+ versions.
-+
-+ Args:
-+ base_path: path to look for relative file paths in
-+ filename: name of the base image file
-+ scale_factors: a list of the supported scale factors (i.e. ['2x'])
-+ distribution: string that should replace %DISTRIBUTION%
-+
-+ Returns:
-+ array of tuples containing scale factor and image (i.e.
-+ [('1x', 'image.png'), ('2x', '2x/image.png')]).
-+ """
-+ # Any matches for which a chrome URL handler will serve all scale factors
-+ # can simply request all scale factors.
-+ theme_match = _THEME_SOURCE.match(filename)
-+ if theme_match:
-+ images = [('1x', filename)]
-+ for scale_factor in scale_factors:
-+ scale_filename = "%s@%s" % (theme_match.group('baseurl'), scale_factor)
-+ if theme_match.group('query'):
-+ scale_filename += theme_match.group('query')
-+ images.append((scale_factor, scale_filename))
-+ return images
-+
-+ if filename.find(':') != -1:
-+ # filename is probably a URL, only return filename itself.
-+ return [('1x', filename)]
-+
-+ filename = filename.replace(DIST_SUBSTR, distribution)
-+ if filename_expansion_function:
-+ filename = filename_expansion_function(filename)
-+ filepath = os.path.join(base_path, filename)
-+ images = [('1x', filename)]
-+
-+ for scale_factor in scale_factors:
-+ # Check for existence of file and add to image set.
-+ scale_path = os.path.split(os.path.join(base_path, filename))
-+ scale_image_path = os.path.join(scale_path[0], scale_factor, scale_path[1])
-+ if os.path.isfile(scale_image_path):
-+ # HTML/CSS always uses forward slashed paths.
-+ parts = filename.rsplit('/', 1)
-+ if len(parts) == 1:
-+ path = ''
-+ else:
-+ path = parts[0] + '/'
-+ scale_image_name = path + scale_factor + '/' + parts[-1]
-+ images.append((scale_factor, scale_image_name))
-+ return images
-+
-+
-+def GenerateImageSet(images, quote):
-+ """Generates a -webkit-image-set for the provided list of images.
-+
-+ Args:
-+ images: an array of tuples giving scale factor and file path
-+ (i.e. [('1x', 'image.png'), ('2x', '2x/image.png')]).
-+ quote: a string giving the quotation character to use (i.e. "'")
-+
-+ Returns:
-+ string giving a -webkit-image-set rule referencing the provided images.
-+ (i.e. '-webkit-image-set(url('image.png') 1x, url('2x/image.png') 2x)')
-+ """
-+ imageset = []
-+ for (scale_factor, filename) in images:
-+ imageset.append("url(%s%s%s) %s" % (quote, filename, quote, scale_factor))
-+ return "-webkit-image-set(%s)" % (', '.join(imageset))
-+
-+
-+def UrlToImageSet(
-+ src_match, base_path, scale_factors, distribution,
-+ filename_expansion_function=None):
-+ """Regex replace function which replaces url() with -webkit-image-set.
-+
-+ Takes a regex match for url('path'). If the file is local, checks for
-+ files of the same name in folders corresponding to the supported scale
-+ factors. If the file is from a chrome://theme/ source, inserts the
-+ supported @Nx scale factor request. In either case inserts a
-+ -webkit-image-set rule to fetch the appropriate image for the current
-+ scale factor.
-+
-+ Args:
-+ src_match: regex match object from _CSS_URLS
-+ base_path: path to look for relative file paths in
-+ scale_factors: a list of the supported scale factors (i.e. ['2x'])
-+ distribution: string that should replace %DISTRIBUTION%.
-+
-+ Returns:
-+ string
-+ """
-+ quote = src_match.group('quote')
-+ filename = src_match.group('filename')
-+ image_list = GetImageList(
-+ base_path, filename, scale_factors, distribution,
-+ filename_expansion_function=filename_expansion_function)
-+
-+ # Don't modify the source if there is only one image.
-+ if len(image_list) == 1:
-+ return src_match.group(0)
-+
-+ return GenerateImageSet(image_list, quote)
-+
-+
-+def InsertImageSet(
-+ src_match, base_path, scale_factors, distribution,
-+ filename_expansion_function=None):
-+ """Regex replace function which inserts -webkit-image-set rules.
-+
-+ Takes a regex match for `property: url('path')[, url('path')]+`.
-+ Replaces one or more occurances of the match with image set rules.
-+
-+ Args:
-+ src_match: regex match object from _CSS_IMAGE_URLS
-+ base_path: path to look for relative file paths in
-+ scale_factors: a list of the supported scale factors (i.e. ['2x'])
-+ distribution: string that should replace %DISTRIBUTION%.
-+
-+ Returns:
-+ string
-+ """
-+ attr = src_match.group('attribute')
-+ urls = _CSS_URL.sub(
-+ lambda m: UrlToImageSet(m, base_path, scale_factors, distribution,
-+ filename_expansion_function),
-+ src_match.group('urls'))
-+
-+ return "%s: %s" % (attr, urls)
-+
-+
-+def InsertImageStyle(
-+ src_match, base_path, scale_factors, distribution,
-+ filename_expansion_function=None):
-+ """Regex replace function which adds a content style to an <img>.
-+
-+ Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS
-+ style which defines the image set.
-+ """
-+ filename = src_match.group('filename')
-+ image_list = GetImageList(
-+ base_path, filename, scale_factors, distribution,
-+ filename_expansion_function=filename_expansion_function)
-+
-+ # Don't modify the source if there is only one image or image already defines
-+ # a style.
-+ if src_match.group(0).find(" style=\"") != -1 or len(image_list) == 1:
-+ return src_match.group(0)
-+
-+ return "%s style=\"content: %s;\">" % (src_match.group(0)[:-1],
-+ GenerateImageSet(image_list, "'"))
-+
-+
-+def InsertImageSets(
-+ filepath, text, scale_factors, distribution,
-+ filename_expansion_function=None):
-+ """Helper function that adds references to external images available in any of
-+ scale_factors in CSS backgrounds.
-+ """
-+ # Add high DPI urls for css attributes: content, background,
-+ # or *-image or <img src="foo">.
-+ return _CSS_IMAGE_URLS.sub(
-+ lambda m: InsertImageSet(
-+ m, filepath, scale_factors, distribution,
-+ filename_expansion_function=filename_expansion_function),
-+ _HTML_IMAGE_SRC.sub(
-+ lambda m: InsertImageStyle(
-+ m, filepath, scale_factors, distribution,
-+ filename_expansion_function=filename_expansion_function),
-+ text))
-+
-+
-+def RemoveImagesNotIn(scale_factors, src_match):
-+ """Regex replace function which removes images for scale factors not in
-+ scale_factors.
-+
-+ Takes a regex match for _CSS_IMAGE_SETS. For each image in the group images,
-+ checks if this scale factor is in scale_factors and if not, removes it.
-+
-+ Args:
-+ scale_factors: a list of the supported scale factors (i.e. ['1x', '2x'])
-+ src_match: regex match object from _CSS_IMAGE_SETS
-+
-+ Returns:
-+ string
-+ """
-+ attr = src_match.group('attribute')
-+ images = _CSS_IMAGE_SET_IMAGE.sub(
-+ lambda m: m.group(0) if m.group('scale') in scale_factors else '',
-+ src_match.group('images'))
-+ return "%s: -webkit-image-set(%s)" % (attr, images)
-+
-+
-+def RemoveImageSetImages(text, scale_factors):
-+ """Helper function which removes images in image sets not in the list of
-+ supported scale_factors.
-+ """
-+ return _CSS_IMAGE_SETS.sub(
-+ lambda m: RemoveImagesNotIn(scale_factors, m), text)
-+
-+
-+def ProcessImageSets(
-+ filepath, text, scale_factors, distribution,
-+ filename_expansion_function=None):
-+ """Helper function that adds references to external images available in other
-+ scale_factors and removes images from image-sets in unsupported scale_factors.
-+ """
-+ # Explicitly add 1x to supported scale factors so that it is not removed.
-+ supported_scale_factors = ['1x']
-+ supported_scale_factors.extend(scale_factors)
-+ return InsertImageSets(
-+ filepath,
-+ RemoveImageSetImages(text, supported_scale_factors),
-+ scale_factors,
-+ distribution,
-+ filename_expansion_function=filename_expansion_function)
-+
-+
-+class ChromeHtml(interface.GathererBase):
-+ """Represents an HTML document processed for Chrome WebUI.
-+
-+ HTML documents used in Chrome WebUI have local resources inlined and
-+ automatically insert references to high DPI assets used in CSS properties
-+ with the use of the -webkit-image-set value. References to unsupported scale
-+ factors in image sets are also removed. This does not generate any
-+ translateable messages and instead generates a single DataPack resource.
-+ """
-+
-+ def __init__(self, *args, **kwargs):
-+ super(ChromeHtml, self).__init__(*args, **kwargs)
-+ self.allow_external_script_ = False
-+ self.flatten_html_ = False
-+ self.preprocess_only_ = False
-+ # 1x resources are implicitly already in the source and do not need to be
-+ # added.
-+ self.scale_factors_ = []
-+ self.filename_expansion_function = None
-+
-+ def SetAttributes(self, attrs):
-+ self.allow_external_script_ = ('allowexternalscript' in attrs and
-+ attrs['allowexternalscript'] == 'true')
-+ self.preprocess_only_ = ('preprocess' in attrs and
-+ attrs['preprocess'] == 'true')
-+ self.flatten_html_ = (self.preprocess_only_ or ('flattenhtml' in attrs and
-+ attrs['flattenhtml'] == 'true'))
-+
-+ def SetDefines(self, defines):
-+ if 'scale_factors' in defines:
-+ self.scale_factors_ = defines['scale_factors'].split(',')
-+
-+ def GetText(self):
-+ """Returns inlined text of the HTML document."""
-+ return self.inlined_text_
-+
-+ def GetTextualIds(self):
-+ return [self.extkey]
-+
-+ def GetData(self, lang, encoding):
-+ """Returns inlined text of the HTML document."""
-+ ret = self.inlined_text_
-+ if encoding == util.BINARY:
-+ ret = ret.encode('utf-8')
-+ return ret
-+
-+ def GetHtmlResourceFilenames(self):
-+ """Returns a set of all filenames inlined by this file."""
-+ if self.flatten_html_:
-+ return html_inline.GetResourceFilenames(
-+ self.grd_node.ToRealPath(self.GetInputPath()),
-+ self.grd_node,
-+ allow_external_script=self.allow_external_script_,
-+ rewrite_function=lambda fp, t, d: ProcessImageSets(
-+ fp, t, self.scale_factors_, d,
-+ filename_expansion_function=self.filename_expansion_function),
-+ filename_expansion_function=self.filename_expansion_function)
-+ return []
-+
-+ def Translate(self, lang, pseudo_if_not_available=True,
-+ skeleton_gatherer=None, fallback_to_english=False):
-+ """Returns this document translated."""
-+ return self.inlined_text_
-+
-+ def SetFilenameExpansionFunction(self, fn):
-+ self.filename_expansion_function = fn
-+
-+ def Parse(self):
-+ """Parses and inlines the represented file."""
-+
-+ filename = self.GetInputPath()
-+ # If there is a grd_node, prefer its GetInputPath(), as that may do more
-+ # processing to make the call to ToRealPath() below work correctly.
-+ if self.grd_node:
-+ filename = self.grd_node.GetInputPath()
-+ if self.filename_expansion_function:
-+ filename = self.filename_expansion_function(filename)
-+ # Hack: some unit tests supply an absolute path and no root node.
-+ if not os.path.isabs(filename):
-+ filename = self.grd_node.ToRealPath(filename)
-+ if self.flatten_html_:
-+ self.inlined_text_ = html_inline.InlineToString(
-+ filename,
-+ self.grd_node,
-+ allow_external_script = self.allow_external_script_,
-+ strip_whitespace=True,
-+ preprocess_only = self.preprocess_only_,
-+ rewrite_function=lambda fp, t, d: ProcessImageSets(
-+ fp, t, self.scale_factors_, d,
-+ filename_expansion_function=self.filename_expansion_function),
-+ filename_expansion_function=self.filename_expansion_function)
-+ else:
-+ distribution = html_inline.GetDistribution()
-+ self.inlined_text_ = ProcessImageSets(
-+ os.path.dirname(filename),
-+ util.ReadFile(filename, 'utf-8'),
-+ self.scale_factors_,
-+ distribution,
-+ filename_expansion_function=self.filename_expansion_function)
-diff --git a/tools/grit/grit/gather/chrome_html_unittest.py b/tools/grit/grit/gather/chrome_html_unittest.py
-new file mode 100644
-index 0000000000..8c75ee5bf4
---- /dev/null
-+++ b/tools/grit/grit/gather/chrome_html_unittest.py
-@@ -0,0 +1,610 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.gather.chrome_html'''
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit import lazy_re
-+from grit import util
-+from grit.gather import chrome_html
-+
-+
-+_NEW_LINE = lazy_re.compile('(\r\n|\r|\n)', re.MULTILINE)
-+
-+
-+def StandardizeHtml(text):
-+ '''Standardizes the newline format and png mime type in Html text.'''
-+ return _NEW_LINE.sub('\n', text).replace('data:image/x-png;',
-+ 'data:image/png;')
-+
-+
-+class ChromeHtmlUnittest(unittest.TestCase):
-+ '''Unit tests for ChromeHtml.'''
-+
-+ def testFileResources(self):
-+ '''Tests inlined image file resources with available high DPI assets.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.css': '''
-+ .image {
-+ background: url('test.png');
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '1.4x/test.png': '1.4x PNG DATA',
-+
-+ '1.8x/test.png': '1.8x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
-+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <style>
-+ .image {
-+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
-+ }
-+ </style>
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesImageTag(self):
-+ '''Tests inlined image file resources with available high DPI assets on
-+ an image tag.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <body>
-+ <img id="foo" src="test.png">
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <body>
-+ <img id="foo" src="data:image/png;base64,UE5HIERBVEE=" style="content: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MnggUE5HIERBVEE=') 2x);">
-+ </body>
-+ </html>
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesNoFlatten(self):
-+ '''Tests non-inlined image file resources with available high DPI assets.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url('test.png');
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '1.4x/test.png': '1.4x PNG DATA',
-+
-+ '1.8x/test.png': '1.8x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
-+ html.SetAttributes({'flattenhtml': 'false'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url('test.png') 1x, url('1.4x/test.png') 1.4x, url('1.8x/test.png') 1.8x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesNoFlattenSubdir(self):
-+ '''Tests non-inlined image file resources w/high DPI assets in subdirs.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url('sub/test.png');
-+ }
-+ ''',
-+
-+ 'sub/test.png': 'PNG DATA',
-+
-+ 'sub/1.4x/test.png': '1.4x PNG DATA',
-+
-+ 'sub/1.8x/test.png': '1.8x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
-+ html.SetAttributes({'flattenhtml': 'false'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url('sub/test.png') 1x, url('sub/1.4x/test.png') 1.4x, url('sub/1.8x/test.png') 1.8x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesPreprocess(self):
-+ '''Tests preprocessed image file resources with available high DPI
-+ assets.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url('test.png');
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '1.4x/test.png': '1.4x PNG DATA',
-+
-+ '1.8x/test.png': '1.8x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
-+ html.SetAttributes({'flattenhtml': 'false', 'preprocess': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url('test.png') 1x, url('1.4x/test.png') 1.4x, url('1.8x/test.png') 1.8x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesDoubleQuotes(self):
-+ '''Tests inlined image file resources if url() filename is double quoted.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url("test.png");
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url("data:image/png;base64,UE5HIERBVEE=") 1x, url("data:image/png;base64,MnggUE5HIERBVEE=") 2x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesNoQuotes(self):
-+ '''Tests inlined image file resources when url() filename is unquoted.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url(test.png);
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesSubdirs(self):
-+ '''Tests inlined image file resources if url() filename is in a subdir.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url('some/sub/path/test.png');
-+ }
-+ ''',
-+
-+ 'some/sub/path/test.png': 'PNG DATA',
-+
-+ 'some/sub/path/2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MnggUE5HIERBVEE=') 2x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesNoFile(self):
-+ '''Tests inlined image file resources without available high DPI assets.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.css': '''
-+ .image {
-+ background: url('test.png');
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <style>
-+ .image {
-+ background: url('data:image/png;base64,UE5HIERBVEE=');
-+ }
-+ </style>
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesMultipleBackgrounds(self):
-+ '''Tests inlined image file resources with two url()s.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url(test.png), url(test.png);
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x), -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesMultipleBackgroundsWithNewline1(self):
-+ '''Tests inlined image file resources with line break after first url().'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background: url(test.png),
-+ url(test.png);
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x),
-+ -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesMultipleBackgroundsWithNewline2(self):
-+ '''Tests inlined image file resources with line break before first url()
-+ and before second url().'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background:
-+ url(test.png),
-+ url(test.png);
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x),
-+ -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testFileResourcesCRLF(self):
-+ '''Tests inlined image file resource when url() is preceded by a Windows
-+ style line break.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'test.css': '''
-+ .image {
-+ background:\r\nurl(test.png);
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ '2x/test.png': '2x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ .image {
-+ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
-+ }
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testThemeResources(self):
-+ '''Tests inserting high DPI chrome://theme references.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.css': '''
-+ .image {
-+ background: url('chrome://theme/IDR_RESOURCE_NAME');
-+ content: url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1');
-+ }
-+ ''',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
-+ html.SetDefines({'scale_factors': '2x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <style>
-+ .image {
-+ background: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME') 1x, url('chrome://theme/IDR_RESOURCE_NAME@2x') 2x);
-+ content: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1') 1x, url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q@2x?$1') 2x);
-+ }
-+ </style>
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testRemoveUnsupportedScale(self):
-+ '''Tests removing an unsupported scale factor from an explicit image-set.'''
-+
-+ tmp_dir = util.TempDir({
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.css': '''
-+ .image {
-+ background: -webkit-image-set(url('test.png') 1x,
-+ url('test1.4.png') 1.4x,
-+ url('test1.8.png') 1.8x);
-+ }
-+ ''',
-+
-+ 'test.png': 'PNG DATA',
-+
-+ 'test1.4.png': '1.4x PNG DATA',
-+
-+ 'test1.8.png': '1.8x PNG DATA',
-+ })
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
-+ html.SetDefines({'scale_factors': '1.8x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <style>
-+ .image {
-+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x,
-+ url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
-+ }
-+ </style>
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+ def testExpandVariablesInFilename(self):
-+ '''
-+ Tests variable substitution in filenames while flattening images
-+ with multiple scale factors.
-+ '''
-+
-+ tmp_dir = util.TempDir({
-+ 'index.html': '''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <link rel="stylesheet" href="test.css">
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ ''',
-+
-+ 'test.css': '''
-+ .image {
-+ background: url('test[WHICH].png');
-+ }
-+ ''',
-+
-+ 'test1.png': 'PNG DATA',
-+ '1.4x/test1.png': '1.4x PNG DATA',
-+ '1.8x/test1.png': '1.8x PNG DATA',
-+ })
-+
-+ def replacer(var, repl):
-+ return lambda filename: filename.replace('[%s]' % var, repl)
-+
-+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
-+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
-+ html.SetAttributes({'flattenhtml': 'true'})
-+ html.SetFilenameExpansionFunction(replacer('WHICH', '1'));
-+ html.Parse()
-+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
-+ StandardizeHtml('''
-+ <!DOCTYPE HTML>
-+ <html>
-+ <head>
-+ <style>
-+ .image {
-+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
-+ }
-+ </style>
-+ </head>
-+ <body>
-+ <!-- Don't need a body. -->
-+ </body>
-+ </html>
-+ '''))
-+ tmp_dir.CleanUp()
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/gather/chrome_scaled_image.py b/tools/grit/grit/gather/chrome_scaled_image.py
-new file mode 100644
-index 0000000000..44f98cbcf0
---- /dev/null
-+++ b/tools/grit/grit/gather/chrome_scaled_image.py
-@@ -0,0 +1,157 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Gatherer for <structure type="chrome_scaled_image">.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import struct
-+
-+from grit import exception
-+from grit import lazy_re
-+from grit import util
-+from grit.gather import interface
-+
-+
-+_PNG_SCALE_CHUNK = b'\0\0\0\0csCl\xc1\x30\x60\x4d'
-+
-+
-+def _RescaleImage(data, from_scale, to_scale):
-+ if from_scale != to_scale:
-+ assert from_scale == 100
-+ # Rather than rescaling the image we add a custom chunk directing Chrome to
-+ # rescale it on load. Just append it to the PNG data since
-+ # _MoveSpecialChunksToFront will move it later anyway.
-+ data += _PNG_SCALE_CHUNK
-+ return data
-+
-+
-+_PNG_MAGIC = b'\x89PNG\r\n\x1a\n'
-+
-+'''Mandatory first chunk in order for the png to be valid.'''
-+_FIRST_CHUNK = b'IHDR'
-+
-+'''Special chunks to move immediately after the IHDR chunk. (so that the PNG
-+remains valid.)
-+'''
-+_SPECIAL_CHUNKS = frozenset(b'csCl npTc'.split())
-+
-+'''Any ancillary chunk not in this list is deleted from the PNG.'''
-+_ANCILLARY_CHUNKS_TO_LEAVE = frozenset(
-+ b'bKGD cHRM gAMA iCCP pHYs sBIT sRGB tRNS acTL fcTL fdAT'.split())
-+
-+
-+def _MoveSpecialChunksToFront(data):
-+ '''Move special chunks immediately after the IHDR chunk (so that the PNG
-+ remains valid). Also delete ancillary chunks that are not on our whitelist.
-+ '''
-+ first = [_PNG_MAGIC]
-+ special_chunks = []
-+ rest = []
-+ for chunk in _ChunkifyPNG(data):
-+ type = chunk[4:8]
-+ critical = type < b'a'
-+ if type == _FIRST_CHUNK:
-+ first.append(chunk)
-+ elif type in _SPECIAL_CHUNKS:
-+ special_chunks.append(chunk)
-+ elif critical or type in _ANCILLARY_CHUNKS_TO_LEAVE:
-+ rest.append(chunk)
-+ return b''.join(first + special_chunks + rest)
-+
-+
-+def _ChunkifyPNG(data):
-+ '''Given a PNG image, yield its chunks in order.'''
-+ assert data.startswith(_PNG_MAGIC)
-+ pos = 8
-+ while pos != len(data):
-+ length = 12 + struct.unpack_from('>I', data, pos)[0]
-+ assert 12 <= length <= len(data) - pos
-+ yield data[pos:pos+length]
-+ pos += length
-+
-+
-+def _MakeBraceGlob(strings):
-+ '''Given ['foo', 'bar'], return '{foo,bar}', for error reporting.
-+ '''
-+ if len(strings) == 1:
-+ return strings[0]
-+ else:
-+ return '{' + ','.join(strings) + '}'
-+
-+
-+class ChromeScaledImage(interface.GathererBase):
-+ '''Represents an image that exists in multiple layout variants
-+ (e.g. "default", "touch") and multiple scale variants
-+ (e.g. "100_percent", "200_percent").
-+ '''
-+
-+ split_context_re_ = lazy_re.compile(r'(.+)_(\d+)_percent\Z')
-+
-+ def _FindInputFile(self):
-+ output_context = self.grd_node.GetRoot().output_context
-+ match = self.split_context_re_.match(output_context)
-+ if not match:
-+ raise exception.MissingMandatoryAttribute(
-+ 'All <output> nodes must have an appropriate context attribute'
-+ ' (e.g. context="touch_200_percent")')
-+ req_layout, req_scale = match.group(1), int(match.group(2))
-+
-+ layouts = [req_layout]
-+ try_default_layout = self.grd_node.GetRoot().fallback_to_default_layout
-+ if try_default_layout and 'default' not in layouts:
-+ layouts.append('default')
-+
-+ scales = [req_scale]
-+ try_low_res = self.grd_node.FindBooleanAttribute(
-+ 'fallback_to_low_resolution', default=False, skip_self=False)
-+ if try_low_res and 100 not in scales:
-+ scales.append(100)
-+
-+ for layout in layouts:
-+ for scale in scales:
-+ dir = '%s_%s_percent' % (layout, scale)
-+ path = os.path.join(dir, self.rc_file)
-+ if os.path.exists(self.grd_node.ToRealPath(path)):
-+ return path, scale, req_scale
-+
-+ if not try_default_layout:
-+ # The file was not found in the specified output context and it was
-+ # explicitly indicated that the default context should not be searched
-+ # as a fallback, so return an empty path.
-+ return None, 100, req_scale
-+
-+ # The file was found in neither the specified context nor the default
-+ # context, so raise an exception.
-+ dir = "%s_%s_percent" % (_MakeBraceGlob(layouts),
-+ _MakeBraceGlob([str(x) for x in scales]))
-+ raise exception.FileNotFound(
-+ 'Tried ' + self.grd_node.ToRealPath(os.path.join(dir, self.rc_file)))
-+
-+ def GetInputPath(self):
-+ path, scale, req_scale = self._FindInputFile()
-+ return path
-+
-+ def Parse(self):
-+ pass
-+
-+ def GetTextualIds(self):
-+ return [self.extkey]
-+
-+ def GetData(self, lang, encoding):
-+ assert encoding == util.BINARY
-+
-+ path, scale, req_scale = self._FindInputFile()
-+ if path is None:
-+ return None
-+
-+ data = util.ReadFile(self.grd_node.ToRealPath(path), util.BINARY)
-+ data = _RescaleImage(data, scale, req_scale)
-+ data = _MoveSpecialChunksToFront(data)
-+ return data
-+
-+ def Translate(self, *args, **kwargs):
-+ return self.GetData()
-diff --git a/tools/grit/grit/gather/chrome_scaled_image_unittest.py b/tools/grit/grit/gather/chrome_scaled_image_unittest.py
-new file mode 100644
-index 0000000000..1cebfc6de2
---- /dev/null
-+++ b/tools/grit/grit/gather/chrome_scaled_image_unittest.py
-@@ -0,0 +1,209 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for ChromeScaledImage.'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
-+ '../..')))
-+
-+import re
-+import struct
-+import unittest
-+import zlib
-+
-+from grit import exception
-+from grit import util
-+from grit.format import data_pack
-+from grit.tool import build
-+
-+
-+_OUTFILETYPES = [
-+ ('.h', 'rc_header'),
-+ ('_map.cc', 'resource_map_source'),
-+ ('_map.h', 'resource_map_header'),
-+ ('.pak', 'data_package'),
-+ ('.rc', 'rc_all'),
-+]
-+
-+
-+_PNG_HEADER = (
-+ b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52'
-+ b'\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53'
-+ b'\xde')
-+_PNG_FOOTER = (
-+ b'\x00\x00\x00\x0c\x49\x44\x41\x54\x18\x57\x63\xf8\xff\xff\x3f\x00'
-+ b'\x05\xfe\x02\xfe\xa7\x35\x81\x84\x00\x00\x00\x00\x49\x45\x4e\x44'
-+ b'\xae\x42\x60\x82')
-+
-+
-+def _MakePNG(chunks):
-+ # Python 3 changed the return value of zlib.crc32 to an unsigned int.
-+ format = 'i' if sys.version_info.major < 3 else 'I'
-+ pack_int32 = struct.Struct('>' + format).pack
-+ chunks = [pack_int32(len(payload)) + type + payload +
-+ pack_int32(zlib.crc32(type + payload))
-+ for type, payload in chunks]
-+ return _PNG_HEADER + b''.join(chunks) + _PNG_FOOTER
-+
-+
-+def _GetFilesInPak(pakname):
-+ '''Get a set of the files that were actually included in the .pak output.
-+ '''
-+ return set(data_pack.ReadDataPack(pakname).resources.values())
-+
-+
-+def _GetFilesInRc(rcname, tmp_dir, contents):
-+ '''Get a set of the files that were actually included in the .rc output.
-+ '''
-+ data = util.ReadFile(rcname, util.BINARY).decode('utf-16')
-+ contents = dict((tmp_dir.GetPath(k), v) for k, v in contents.items())
-+ return set(contents[os.path.normpath(m.group(1))]
-+ for m in re.finditer(r'(?m)^\w+\s+BINDATA\s+"([^"]+)"$', data))
-+
-+
-+def _MakeFallbackAttr(fallback):
-+ if fallback is None:
-+ return ''
-+ else:
-+ return ' fallback_to_low_resolution="%s"' % ('false', 'true')[fallback]
-+
-+
-+def _Structures(fallback, *body):
-+ return '<structures%s>\n%s\n</structures>' % (
-+ _MakeFallbackAttr(fallback), '\n'.join(body))
-+
-+
-+def _Structure(name, file, fallback=None):
-+ return '<structure name="%s" file="%s" type="chrome_scaled_image"%s />' % (
-+ name, file, _MakeFallbackAttr(fallback))
-+
-+
-+def _If(expr, *body):
-+ return '<if expr="%s">\n%s\n</if>' % (expr, '\n'.join(body))
-+
-+
-+def _RunBuildTest(self, structures, inputs, expected_outputs, skip_rc=False,
-+ layout_fallback=''):
-+ outputs = '\n'.join('<output filename="out/%s%s" type="%s" context="%s"%s />'
-+ % (context, ext, type, context, layout_fallback)
-+ for ext, type in _OUTFILETYPES
-+ for context in expected_outputs)
-+
-+ infiles = {
-+ 'in/in.grd': ('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="0" current_release="1">
-+ <outputs>
-+ %s
-+ </outputs>
-+ <release seq="1">
-+ %s
-+ </release>
-+ </grit>
-+ ''' % (outputs, structures)).encode('utf-8'),
-+ }
-+ for pngpath, pngdata in inputs.items():
-+ normpath = os.path.normpath('in/' + pngpath)
-+ infiles[normpath] = pngdata
-+ class Options(object):
-+ pass
-+
-+ with util.TempDir(infiles, mode='wb') as tmp_dir:
-+ with tmp_dir.AsCurrentDir():
-+ options = Options()
-+ options.input = tmp_dir.GetPath('in/in.grd')
-+ options.verbose = False
-+ options.extra_verbose = False
-+ build.RcBuilder().Run(options, [])
-+ for context, expected_data in expected_outputs.items():
-+ self.assertEquals(expected_data,
-+ _GetFilesInPak(tmp_dir.GetPath('out/%s.pak' % context)))
-+ if not skip_rc:
-+ self.assertEquals(expected_data,
-+ _GetFilesInRc(tmp_dir.GetPath('out/%s.rc' % context),
-+ tmp_dir, infiles))
-+
-+
-+class ChromeScaledImageUnittest(unittest.TestCase):
-+ def testNormalFallback(self):
-+ d123a = _MakePNG([(b'AbCd', b'')])
-+ t123a = _MakePNG([(b'EfGh', b'')])
-+ d123b = _MakePNG([(b'IjKl', b'')])
-+ _RunBuildTest(self,
-+ _Structures(None,
-+ _Structure('IDR_A', 'a.png'),
-+ _Structure('IDR_B', 'b.png'),
-+ ),
-+ {'default_123_percent/a.png': d123a,
-+ 'tactile_123_percent/a.png': t123a,
-+ 'default_123_percent/b.png': d123b,
-+ },
-+ {'default_123_percent': set([d123a, d123b]),
-+ 'tactile_123_percent': set([t123a, d123b]),
-+ })
-+
-+ def testNormalFallbackFailure(self):
-+ self.assertRaises(
-+ exception.FileNotFound, _RunBuildTest, self,
-+ _Structures(
-+ None,
-+ _Structure('IDR_A', 'a.png'),
-+ ), {
-+ 'default_100_percent/a.png': _MakePNG([(b'AbCd', b'')]),
-+ 'tactile_100_percent/a.png': _MakePNG([(b'EfGh', b'')]),
-+ }, {'tactile_123_percent': 'should fail before using this'})
-+
-+ def testLowresFallback(self):
-+ png = _MakePNG([(b'Abcd', b'')])
-+ png_with_csCl = _MakePNG([(b'csCl', b''), (b'Abcd', b'')])
-+ for outer in (None, False, True):
-+ for inner in (None, False, True):
-+ args = (
-+ self,
-+ _Structures(outer,
-+ _Structure('IDR_A', 'a.png', inner),
-+ ),
-+ {'default_100_percent/a.png': png},
-+ {'tactile_200_percent': set([png_with_csCl])})
-+ if inner or (inner is None and outer):
-+ # should fall back to 100%
-+ _RunBuildTest(*args, skip_rc=True)
-+ else:
-+ # shouldn't fall back
-+ self.assertRaises(exception.FileNotFound, _RunBuildTest, *args)
-+
-+ # Test fallback failure with fallback_to_low_resolution=True
-+ self.assertRaises(exception.FileNotFound,
-+ _RunBuildTest, self,
-+ _Structures(True,
-+ _Structure('IDR_A', 'a.png'),
-+ ),
-+ {}, # no files
-+ {'tactile_123_percent': 'should fail before using this'})
-+
-+ def testNoFallbackToDefaultLayout(self):
-+ d123a = _MakePNG([(b'AbCd', b'')])
-+ t123a = _MakePNG([(b'EfGh', b'')])
-+ d123b = _MakePNG([(b'IjKl', b'')])
-+ _RunBuildTest(self,
-+ _Structures(None,
-+ _Structure('IDR_A', 'a.png'),
-+ _Structure('IDR_B', 'b.png'),
-+ ),
-+ {'default_123_percent/a.png': d123a,
-+ 'tactile_123_percent/a.png': t123a,
-+ 'default_123_percent/b.png': d123b,
-+ },
-+ {'default_123_percent': set([d123a, d123b]),
-+ 'tactile_123_percent': set([t123a]),
-+ },
-+ layout_fallback=' fallback_to_default_layout="false"')
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/gather/interface.py b/tools/grit/grit/gather/interface.py
-new file mode 100644
-index 0000000000..15d64f9326
---- /dev/null
-+++ b/tools/grit/grit/gather/interface.py
-@@ -0,0 +1,172 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Interface for all gatherers.
-+'''
-+
-+from __future__ import print_function
-+
-+import os.path
-+
-+import six
-+
-+from grit import clique
-+from grit import util
-+
-+
-+class GathererBase(object):
-+ '''Interface for all gatherer implementations. Subclasses must implement
-+ all methods that raise NotImplemented.'''
-+
-+ def __init__(self, rc_file, extkey=None, encoding='cp1252', is_skeleton=False):
-+ '''Initializes the gatherer object's attributes, but does not attempt to
-+ read the input file.
-+
-+ Args:
-+ rc_file: The 'file' attribute of the <structure> node (usually the
-+ relative path to the source file).
-+ extkey: e.g. 'ID_MY_DIALOG'
-+ encoding: e.g. 'utf-8'
-+ is_skeleton: Indicates whether this gatherer is a skeleton gatherer, in
-+ which case we should not do some types of processing on the
-+ translateable bits.
-+ '''
-+ self.rc_file = rc_file
-+ self.extkey = extkey
-+ self.encoding = encoding
-+ # A default uberclique that is local to this object. Users can override
-+ # this with the uberclique they are using.
-+ self.uberclique = clique.UberClique()
-+ # Indicates whether this gatherer is a skeleton gatherer, in which case
-+ # we should not do some types of processing on the translateable bits.
-+ self.is_skeleton = is_skeleton
-+ # Stores the grd node on which this gatherer is running. This allows
-+ # evaluating expressions.
-+ self.grd_node = None
-+
-+ def SetAttributes(self, attrs):
-+ '''Sets node attributes used by the gatherer.
-+
-+ By default, this does nothing. If special handling is desired, it should be
-+ overridden by the child gatherer.
-+
-+ Args:
-+ attrs: The mapping of node attributes.
-+ '''
-+ pass
-+
-+ def SetDefines(self, defines):
-+ '''Sets global defines used by the gatherer.
-+
-+ By default, this does nothing. If special handling is desired, it should be
-+ overridden by the child gatherer.
-+
-+ Args:
-+ defines: The mapping of define values.
-+ '''
-+ pass
-+
-+ def SetGrdNode(self, node):
-+ '''Sets the grd node on which this gatherer is running.
-+ '''
-+ self.grd_node = node
-+
-+ def SetUberClique(self, uberclique):
-+ '''Overrides the default uberclique so that cliques created by this object
-+ become part of the uberclique supplied by the user.
-+ '''
-+ self.uberclique = uberclique
-+
-+ def Parse(self):
-+ '''Reads and parses the contents of what is being gathered.'''
-+ raise NotImplementedError()
-+
-+ def GetData(self, lang, encoding):
-+ '''Returns the data to be added to the DataPack for this node or None if
-+ this node does not add a DataPack entry.
-+ '''
-+ return None
-+
-+ def GetText(self):
-+ '''Returns the text of what is being gathered.'''
-+ raise NotImplementedError()
-+
-+ def GetTextualIds(self):
-+ '''Returns the mnemonic IDs that need to be defined for the resource
-+ being gathered to compile correctly.'''
-+ return []
-+
-+ def GetCliques(self):
-+ '''Returns the MessageClique objects for all translateable portions.'''
-+ return []
-+
-+ def GetInputPath(self):
-+ return self.rc_file
-+
-+ def GetHtmlResourceFilenames(self):
-+ """Returns a set of all filenames inlined by this gatherer."""
-+ return []
-+
-+ def Translate(self, lang, pseudo_if_not_available=True,
-+ skeleton_gatherer=None, fallback_to_english=False):
-+ '''Returns the resource being gathered, with translateable portions filled
-+ with the translation for language 'lang'.
-+
-+ If pseudo_if_not_available is true, a pseudotranslation will be used for any
-+ message that doesn't have a real translation available.
-+
-+ If no translation is available and pseudo_if_not_available is false,
-+ fallback_to_english controls the behavior. If it is false, throw an error.
-+ If it is true, use the English version of the message as its own
-+ "translation".
-+
-+ If skeleton_gatherer is specified, the translation will use the nontranslateable
-+ parts from the gatherer 'skeleton_gatherer', which must be of the same type
-+ as 'self'.
-+
-+ If fallback_to_english
-+
-+ Args:
-+ lang: 'en'
-+ pseudo_if_not_available: True | False
-+ skeleton_gatherer: other_gatherer
-+ fallback_to_english: True | False
-+
-+ Return:
-+ e.g. 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND'
-+
-+ Raises:
-+ grit.exception.NotReady() if used before Parse() has been successfully
-+ called.
-+ grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' and
-+ fallback_to_english are both false and there is no translation for the
-+ requested language.
-+ '''
-+ raise NotImplementedError()
-+
-+ def SubstituteMessages(self, substituter):
-+ '''Applies substitutions to all messages in the gatherer.
-+
-+ Args:
-+ substituter: a grit.util.Substituter object.
-+ '''
-+ pass
-+
-+ def SetFilenameExpansionFunction(self, fn):
-+ '''Sets a function for rewriting filenames before gathering.'''
-+ pass
-+
-+ # TODO(benrg): Move this elsewhere, since it isn't part of the interface.
-+ def _LoadInputFile(self):
-+ '''A convenience function for subclasses that loads the contents of the
-+ input file.
-+ '''
-+ if isinstance(self.rc_file, six.string_types):
-+ path = self.GetInputPath()
-+ # Hack: some unit tests supply an absolute path and no root node.
-+ if not os.path.isabs(path):
-+ path = self.grd_node.ToRealPath(path)
-+ return util.ReadFile(path, self.encoding)
-+ else:
-+ return self.rc_file.read()
-diff --git a/tools/grit/grit/gather/json_loader.py b/tools/grit/grit/gather/json_loader.py
-new file mode 100644
-index 0000000000..058e5f17ae
---- /dev/null
-+++ b/tools/grit/grit/gather/json_loader.py
-@@ -0,0 +1,27 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+from __future__ import print_function
-+
-+from grit.gather import interface
-+
-+
-+class JsonLoader(interface.GathererBase):
-+ '''A simple gatherer that loads and parses a JSON file.'''
-+
-+ def Parse(self):
-+ '''Reads and parses the text of self._json_text into the data structure in
-+ self._data.
-+ '''
-+ self._json_text = self._LoadInputFile()
-+ self._data = None
-+
-+ globs = {}
-+ exec('data = ' + self._json_text, globs)
-+ self._data = globs['data']
-+
-+ def GetData(self, lang, encoding):
-+ '''Returns the parsed JSON data.'''
-+ assert encoding == 'utf-8'
-+ return self._data
-diff --git a/tools/grit/grit/gather/policy_json.py b/tools/grit/grit/gather/policy_json.py
-new file mode 100644
-index 0000000000..6621c5f3c4
---- /dev/null
-+++ b/tools/grit/grit/gather/policy_json.py
-@@ -0,0 +1,325 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Support for "policy_templates.json" format used by the policy template
-+generator as a source for generating ADM,ADMX,etc files.'''
-+
-+from __future__ import print_function
-+
-+import json
-+import sys
-+
-+import six
-+
-+from grit.gather import skeleton_gatherer
-+from grit import util
-+from grit import tclib
-+from xml.dom import minidom
-+from xml.parsers.expat import ExpatError
-+
-+
-+class PolicyJson(skeleton_gatherer.SkeletonGatherer):
-+ '''Collects and translates the following strings from policy_templates.json:
-+ - captions, descriptions, labels and Android app support details of policies
-+ - captions of enumeration items
-+ - misc strings from the 'messages' section
-+ Translatable strings may have untranslateable placeholders with the same
-+ format that is used in .grd files.
-+ '''
-+
-+ def _AddEndline(self, add_comma):
-+ '''Adds an endline to the skeleton tree. If add_comma is true, adds a
-+ comma before the endline.
-+
-+ Args:
-+ add_comma: A boolean to add a comma or not.
-+ '''
-+ self._AddNontranslateableChunk(',\n' if add_comma else '\n')
-+
-+ def _ParsePlaceholder(self, placeholder, msg):
-+ '''Extracts a placeholder from a DOM node and adds it to a tclib Message.
-+
-+ Args:
-+ placeholder: A DOM node of the form:
-+ <ph name="PLACEHOLDER_NAME">Placeholder text<ex>Example value</ex></ph>
-+ msg: The placeholder is added to this message.
-+ '''
-+ text = []
-+ example_text = []
-+ for node1 in placeholder.childNodes:
-+ if (node1.nodeType == minidom.Node.TEXT_NODE):
-+ text.append(node1.data)
-+ elif (node1.nodeType == minidom.Node.ELEMENT_NODE and
-+ node1.tagName == 'ex'):
-+ for node2 in node1.childNodes:
-+ example_text.append(node2.toxml())
-+ else:
-+ raise Exception('Unexpected element inside a placeholder: ' +
-+ node2.toxml())
-+ if example_text == []:
-+ # In such cases the original text is okay for an example.
-+ example_text = text
-+
-+ replaced_text = self.Escape(''.join(text).strip())
-+ replaced_text = replaced_text.replace('$1', self._config['app_name'])
-+ replaced_text = replaced_text.replace('$2', self._config['os_name'])
-+ replaced_text = replaced_text.replace('$3', self._config['frame_name'])
-+
-+ msg.AppendPlaceholder(tclib.Placeholder(
-+ placeholder.attributes['name'].value,
-+ replaced_text,
-+ ''.join(example_text).strip()))
-+
-+ def _ParseMessage(self, string, desc):
-+ '''Parses a given string and adds it to the output as a translatable chunk
-+ with a given description.
-+
-+ Args:
-+ string: The message string to parse.
-+ desc: The description of the message (for the translators).
-+ '''
-+ msg = tclib.Message(description=desc)
-+ xml = '<msg>' + string + '</msg>'
-+ try:
-+ node = minidom.parseString(xml).childNodes[0]
-+ except ExpatError:
-+ reason = '''Input isn't valid XML (has < & > been escaped?): ''' + string
-+ six.reraise(Exception, reason, sys.exc_info()[2])
-+
-+ for child in node.childNodes:
-+ if child.nodeType == minidom.Node.TEXT_NODE:
-+ msg.AppendText(child.data)
-+ elif child.nodeType == minidom.Node.ELEMENT_NODE:
-+ if child.tagName == 'ph':
-+ self._ParsePlaceholder(child, msg)
-+ else:
-+ raise Exception("Not implemented.")
-+ else:
-+ raise Exception("Not implemented.")
-+ self.skeleton_.append(self.uberclique.MakeClique(msg))
-+
-+ def _ParseNode(self, node):
-+ '''Traverses the subtree of a DOM node, and register a tclib message for
-+ all the <message> nodes.
-+ '''
-+ att_text = []
-+ if node.attributes:
-+ for key, value in sorted(node.attributes.items()):
-+ att_text.append(' %s=\"%s\"' % (key, value))
-+ self._AddNontranslateableChunk("<%s%s>" %
-+ (node.tagName, ''.join(att_text)))
-+ if node.tagName == 'message':
-+ msg = tclib.Message(description=node.attributes['desc'])
-+ for child in node.childNodes:
-+ if child.nodeType == minidom.Node.TEXT_NODE:
-+ if msg == None:
-+ self._AddNontranslateableChunk(child.data)
-+ else:
-+ msg.AppendText(child.data)
-+ elif child.nodeType == minidom.Node.ELEMENT_NODE:
-+ if child.tagName == 'ph':
-+ self._ParsePlaceholder(child, msg)
-+ else:
-+ assert False
-+ self.skeleton_.append(self.uberclique.MakeClique(msg))
-+ else:
-+ for child in node.childNodes:
-+ if child.nodeType == minidom.Node.TEXT_NODE:
-+ self._AddNontranslateableChunk(child.data)
-+ elif node.nodeType == minidom.Node.ELEMENT_NODE:
-+ self._ParseNode(child)
-+
-+ self._AddNontranslateableChunk("</%s>" % node.tagName)
-+
-+ def _AddIndentedNontranslateableChunk(self, depth, string):
-+ '''Adds a nontranslateable chunk of text to the internally stored output.
-+
-+ Args:
-+ depth: The number of double spaces to prepend to the next argument string.
-+ string: The chunk of text to add.
-+ '''
-+ result = []
-+ while depth > 0:
-+ result.append(' ')
-+ depth = depth - 1
-+ result.append(string)
-+ self._AddNontranslateableChunk(''.join(result))
-+
-+ def _GetDescription(self, item, item_type, parent_item, key):
-+ '''Creates a description for a translatable message. The description gives
-+ some context for the person who will translate this message.
-+
-+ Args:
-+ item: A policy or an enumeration item.
-+ item_type: 'enum_item' | 'policy'
-+ parent_item: The owner of item. (A policy of type group or enum.)
-+ key: The name of the key to parse.
-+ depth: The level of indentation.
-+ '''
-+ key_map = {
-+ 'desc': 'Description',
-+ 'caption': 'Caption',
-+ 'label': 'Label',
-+ 'arc_support': 'Information about the effect on Android apps'
-+ }
-+ if item_type == 'policy':
-+ return ('%s of the policy named %s [owner(s): %s]' %
-+ (key_map[key], item['name'],
-+ ','.join(item['owners'] if 'owners' in item else 'unknown')))
-+ if item_type == 'enum_item':
-+ return ('%s of the option named %s in policy %s [owner(s): %s]' %
-+ (key_map[key], item['name'], parent_item['name'],
-+ ','.join(parent_item['owners'] if 'owners' in parent_item else 'unknown')))
-+ raise Exception('Unexpected type %s' % item_type)
-+
-+ def _AddSchemaKeys(self, obj, depth):
-+ obj_type = type(obj)
-+ if obj_type == dict:
-+ self._AddNontranslateableChunk('{\n')
-+ keys = sorted(obj.keys())
-+ for count, (key) in enumerate(keys, 1):
-+ json_key = "%s: " % json.dumps(key)
-+ self._AddIndentedNontranslateableChunk(depth + 1, json_key)
-+ if key == 'description' and type(obj[key]) == str:
-+ self._AddNontranslateableChunk("\"")
-+ self._ParseMessage(obj[key], 'Description of schema property')
-+ self._AddNontranslateableChunk("\"")
-+ elif type(obj[key]) in (bool, int, str):
-+ self._AddSchemaKeys(obj[key], 0)
-+ else:
-+ self._AddSchemaKeys(obj[key], depth + 1)
-+ self._AddEndline(count < len(keys))
-+ self._AddIndentedNontranslateableChunk(depth, '}')
-+ elif obj_type == list:
-+ self._AddNontranslateableChunk('[\n')
-+ for count, (item) in enumerate(obj, 1):
-+ self._AddSchemaKeys(item, depth + 1)
-+ self._AddEndline(count < len(obj))
-+ self._AddIndentedNontranslateableChunk(depth, ']')
-+ elif obj_type in (bool, int, str):
-+ self._AddIndentedNontranslateableChunk(depth, json.dumps(obj))
-+ else:
-+ raise Exception('Invalid schema object: %s' % obj)
-+
-+ def _AddPolicyKey(self, item, item_type, parent_item, key, depth):
-+ '''Given a policy/enumeration item and a key, adds that key and its value
-+ into the output.
-+ E.g.:
-+ 'example_value': 123
-+ If key indicates that the value is a translatable string, then it is parsed
-+ as a translatable string.
-+
-+ Args:
-+ item: A policy or an enumeration item.
-+ item_type: 'enum_item' | 'policy'
-+ parent_item: The owner of item. (A policy of type group or enum.)
-+ key: The name of the key to parse.
-+ depth: The level of indentation.
-+ '''
-+ self._AddIndentedNontranslateableChunk(depth, "%s: " % json.dumps(key))
-+ if key in ('desc', 'caption', 'label', 'arc_support'):
-+ self._AddNontranslateableChunk("\"")
-+ self._ParseMessage(
-+ item[key],
-+ self._GetDescription(item, item_type, parent_item, key))
-+ self._AddNontranslateableChunk("\"")
-+ elif key in ('schema', 'validation_schema', 'description_schema'):
-+ self._AddSchemaKeys(item[key], depth)
-+ else:
-+ self._AddNontranslateableChunk(json.dumps(item[key], ensure_ascii=False))
-+
-+ def _AddItems(self, items, item_type, parent_item, depth):
-+ '''Parses and adds a list of items from the JSON file. Items can be policies
-+ or parts of an enum policy.
-+
-+ Args:
-+ items: Either a list of policies or a list of dictionaries.
-+ item_type: 'enum_item' | 'policy'
-+ parent_item: If items contains a list of policies, then this is the policy
-+ group that owns them. If items contains a list of enumeration items,
-+ then this is the enum policy that holds them.
-+ depth: Indicates the depth of our position in the JSON hierarchy. Used to
-+ add nice line-indent to the output.
-+ '''
-+ for item_count, (item1) in enumerate(items, 1):
-+ self._AddIndentedNontranslateableChunk(depth, "{\n")
-+ keys = sorted(item1.keys())
-+ for keys_count, (key) in enumerate(keys, 1):
-+ if key == 'items':
-+ self._AddIndentedNontranslateableChunk(depth + 1, "\"items\": [\n")
-+ self._AddItems(item1['items'], 'enum_item', item1, depth + 2)
-+ self._AddIndentedNontranslateableChunk(depth + 1, "]")
-+ elif key == 'policies' and all(not isinstance(x, str)
-+ for x in item1['policies']):
-+ self._AddIndentedNontranslateableChunk(depth + 1, "\"policies\": [\n")
-+ self._AddItems(item1['policies'], 'policy', item1, depth + 2)
-+ self._AddIndentedNontranslateableChunk(depth + 1, "]")
-+ else:
-+ self._AddPolicyKey(item1, item_type, parent_item, key, depth + 1)
-+ self._AddEndline(keys_count < len(keys))
-+ self._AddIndentedNontranslateableChunk(depth, "}")
-+ self._AddEndline(item_count < len(items))
-+
-+ def _AddMessages(self):
-+ '''Processed and adds the 'messages' section to the output.'''
-+ self._AddNontranslateableChunk(" \"messages\": {\n")
-+ messages = self.data['messages'].items()
-+ for count, (name, message) in enumerate(messages, 1):
-+ self._AddNontranslateableChunk(" %s: {\n" % json.dumps(name))
-+ self._AddNontranslateableChunk(" \"text\": \"")
-+ self._ParseMessage(message['text'], message['desc'])
-+ self._AddNontranslateableChunk("\"\n")
-+ self._AddNontranslateableChunk(" }")
-+ self._AddEndline(count < len(self.data['messages']))
-+ self._AddNontranslateableChunk(" }\n")
-+
-+ # Although we use the RegexpGatherer base class, we do not use the
-+ # _RegExpParse method of that class to implement Parse(). Instead, we
-+ # parse using a DOM parser.
-+ def Parse(self):
-+ if self.have_parsed_:
-+ return
-+ self.have_parsed_ = True
-+
-+ self.text_ = self._LoadInputFile()
-+ if util.IsExtraVerbose():
-+ print(self.text_)
-+
-+ self.data = eval(self.text_)
-+
-+ self._AddNontranslateableChunk('{\n')
-+ self._AddNontranslateableChunk(" \"policy_definitions\": [\n")
-+ self._AddItems(self.data['policy_definitions'], 'policy', None, 2)
-+ self._AddNontranslateableChunk(" ],\n")
-+ self._AddNontranslateableChunk(" \"policy_atomic_group_definitions\": [\n")
-+ if 'policy_atomic_group_definitions' in self.data:
-+ self._AddItems(self.data['policy_atomic_group_definitions'],
-+ 'policy', None, 2)
-+ self._AddNontranslateableChunk(" ],\n")
-+ self._AddMessages()
-+ self._AddNontranslateableChunk('\n}')
-+
-+ def Escape(self, text):
-+ return json.dumps(text, ensure_ascii=False)[1:-1]
-+
-+ def SetDefines(self, defines):
-+ if not defines:
-+ raise Exception('Must pass valid defines')
-+
-+ if '_chromium' in defines:
-+ self._config = {
-+ 'build': 'chromium',
-+ 'app_name': 'Chromium',
-+ 'frame_name': 'Chromium Frame',
-+ 'os_name': 'Chromium OS',
-+ }
-+ elif '_google_chrome' in defines:
-+ self._config = {
-+ 'build': 'chrome',
-+ 'app_name': 'Google Chrome',
-+ 'frame_name': 'Google Chrome Frame',
-+ 'os_name': 'Google Chrome OS',
-+ }
-+ else:
-+ raise Exception('Unknown build')
-diff --git a/tools/grit/grit/gather/policy_json_unittest.py b/tools/grit/grit/gather/policy_json_unittest.py
-new file mode 100644
-index 0000000000..214cd276aa
---- /dev/null
-+++ b/tools/grit/grit/gather/policy_json_unittest.py
-@@ -0,0 +1,347 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.gather.policy_json'''
-+
-+from __future__ import print_function
-+
-+import json
-+import os
-+import re
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit.gather import policy_json
-+
-+class PolicyJsonUnittest(unittest.TestCase):
-+
-+ def GetExpectedOutput(self, original):
-+ expected = eval(original)
-+ for key, message in expected['messages'].items():
-+ del message['desc']
-+ return expected
-+
-+ def testEmpty(self):
-+ original = """{
-+ 'policy_definitions': [],
-+ 'policy_atomic_group_definitions': [],
-+ 'messages': {}
-+ }"""
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 0)
-+ self.failUnless(eval(original) == json.loads(gatherer.Translate('en')))
-+
-+ def testGeneralPolicy(self):
-+ original = (
-+ "{"
-+ " 'policy_definitions': ["
-+ " {"
-+ " 'name': 'HomepageLocation',"
-+ " 'type': 'string',"
-+ " 'owners': ['foo@bar.com'],"
-+ " 'supported_on': ['chrome.*:8-'],"
-+ " 'features': {'dynamic_refresh': 1},"
-+ " 'example_value': 'http://chromium.org',"
-+ " 'caption': 'nothing special 1',"
-+ " 'desc': 'nothing special 2',"
-+ " 'label': 'nothing special 3',"
-+ " },"
-+ " ],"
-+ " 'policy_atomic_group_definitions': [],"
-+ " 'messages': {"
-+ " 'msg_identifier': {"
-+ " 'text': 'nothing special 3',"
-+ " 'desc': 'nothing special descr 3',"
-+ " }"
-+ " }"
-+ "}")
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 4)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ def testEnum(self):
-+ original = (
-+ "{"
-+ " 'policy_definitions': ["
-+ " {"
-+ " 'name': 'Policy1',"
-+ " 'owners': ['a@b'],"
-+ " 'items': ["
-+ " {"
-+ " 'name': 'Item1',"
-+ " 'caption': 'nothing special',"
-+ " }"
-+ " ]"
-+ " },"
-+ " ],"
-+ " 'policy_atomic_group_definitions': [],"
-+ " 'messages': {}"
-+ "}")
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ def testSchema(self):
-+ original = ("{"
-+ " 'policy_definitions': ["
-+ " {"
-+ " 'name': 'Policy1',"
-+ " 'schema': {"
-+ " 'type': 'object',"
-+ " 'properties': {"
-+ " 'outer': {"
-+ " 'description': 'outer description',"
-+ " 'type': 'object',"
-+ " 'inner': {"
-+ " 'description': 'inner description',"
-+ " 'type': 'integer', 'minimum': 0, 'maximum': 100"
-+ " },"
-+ " 'inner2': {"
-+ " 'description': 'inner2 description',"
-+ " 'type': 'integer',"
-+ " 'enum': [ 1, 2, 3 ],"
-+ " 'sensitiveValue': True"
-+ " },"
-+ " },"
-+ " },"
-+ " },"
-+ " 'caption': 'nothing special',"
-+ " 'owners': ['a@b']"
-+ " },"
-+ " ],"
-+ " 'policy_atomic_group_definitions': [],"
-+ " 'messages': {}"
-+ "}")
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 4)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ def testValidationSchema(self):
-+ original = ("{"
-+ " 'policy_definitions': ["
-+ " {"
-+ " 'name': 'Policy1',"
-+ " 'owners': ['a@b'],"
-+ " 'validation_schema': {"
-+ " 'type': 'object',"
-+ " 'properties': {"
-+ " 'description': 'properties description',"
-+ " 'type': 'object',"
-+ " },"
-+ " },"
-+ " },"
-+ " ],"
-+ " 'policy_atomic_group_definitions': [],"
-+ " 'messages': {}"
-+ "}")
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ def testDescriptionSchema(self):
-+ original = ("{"
-+ " 'policy_definitions': ["
-+ " {"
-+ " 'name': 'Policy1',"
-+ " 'owners': ['a@b'],"
-+ " 'description_schema': {"
-+ " 'type': 'object',"
-+ " 'properties': {"
-+ " 'description': 'properties description',"
-+ " 'type': 'object',"
-+ " },"
-+ " },"
-+ " },"
-+ " ],"
-+ " 'policy_atomic_group_definitions': [],"
-+ " 'messages': {}"
-+ "}")
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ # Keeping for backwards compatibility.
-+ def testSubPolicyOldFormat(self):
-+ original = (
-+ "{"
-+ " 'policy_definitions': ["
-+ " {"
-+ " 'type': 'group',"
-+ " 'policies': ["
-+ " {"
-+ " 'name': 'Policy1',"
-+ " 'caption': 'nothing special',"
-+ " 'owners': ['a@b']"
-+ " }"
-+ " ]"
-+ " }"
-+ " ],"
-+ " 'policy_atomic_group_definitions': [],"
-+ " 'messages': {}"
-+ "}")
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ def testSubPolicyNewFormat(self):
-+ original = (
-+ "{"
-+ " 'policy_definitions': ["
-+ " {"
-+ " 'type': 'group',"
-+ " 'policies': ['Policy1']"
-+ " },"
-+ " {"
-+ " 'name': 'Policy1',"
-+ " 'caption': 'nothing special',"
-+ " 'owners': ['a@b']"
-+ " }"
-+ " ],"
-+ " 'policy_atomic_group_definitions': [],"
-+ " 'messages': {}"
-+ "}")
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ def testEscapingAndLineBreaks(self):
-+ original = """{
-+ 'policy_definitions': [],
-+ 'policy_atomic_group_definitions': [],
-+ 'messages': {
-+ 'msg1': {
-+ # The following line will contain two backslash characters when it
-+ # ends up in eval().
-+ 'text': '''backslashes, Sir? \\\\''',
-+ 'desc': ''
-+ },
-+ 'msg2': {
-+ 'text': '''quotes, Madam? "''',
-+ 'desc': ''
-+ },
-+ 'msg3': {
-+ # The following line will contain two backslash characters when it
-+ # ends up in eval().
-+ 'text': 'backslashes, Sir? \\\\',
-+ 'desc': ''
-+ },
-+ 'msg4': {
-+ 'text': "quotes, Madam? '",
-+ 'desc': ''
-+ },
-+ 'msg5': {
-+ 'text': '''what happens
-+with a newline?''',
-+ 'desc': ''
-+ },
-+ 'msg6': {
-+ # The following line will contain a backslash+n when it ends up in
-+ # eval().
-+ 'text': 'what happens\\nwith a newline? (Episode 1)',
-+ 'desc': ''
-+ }
-+ }
-+}"""
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 6)
-+ expected = self.GetExpectedOutput(original)
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+
-+ def testPlaceholdersChromium(self):
-+ original = """{
-+ "policy_definitions": [
-+ {
-+ "name": "Policy1",
-+ "caption": "Please install\\n<ph name=\\"PRODUCT_NAME\\">$1<ex>Google Chrome</ex></ph>.",
-+ "owners": "a@b"
-+ }
-+ ],
-+ "policy_atomic_group_definitions": [],
-+ "messages": {}
-+}"""
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.SetDefines({'_chromium': True})
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ expected = json.loads(re.sub('<ph.*ph>', 'Chromium', original))
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+ self.failUnless(gatherer.GetCliques()[0].translateable)
-+ msg = gatherer.GetCliques()[0].GetMessage()
-+ self.failUnless(len(msg.GetPlaceholders()) == 1)
-+ ph = msg.GetPlaceholders()[0]
-+ self.failUnless(ph.GetOriginal() == 'Chromium')
-+ self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
-+ self.failUnless(ph.GetExample() == 'Google Chrome')
-+
-+ def testPlaceholdersChrome(self):
-+ original = """{
-+ "policy_definitions": [
-+ {
-+ "name": "Policy1",
-+ "caption": "Please install\\n<ph name=\\"PRODUCT_NAME\\">$1<ex>Google Chrome</ex></ph>.",
-+ "owners": "a@b"
-+ }
-+ ],
-+ "policy_atomic_group_definitions": [],
-+ "messages": {}
-+}"""
-+ gatherer = policy_json.PolicyJson(StringIO(original))
-+ gatherer.SetDefines({'_google_chrome': True})
-+ gatherer.Parse()
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ expected = json.loads(re.sub('<ph.*ph>', 'Google Chrome', original))
-+ self.failUnless(expected == json.loads(gatherer.Translate('en')))
-+ self.failUnless(gatherer.GetCliques()[0].translateable)
-+ msg = gatherer.GetCliques()[0].GetMessage()
-+ self.failUnless(len(msg.GetPlaceholders()) == 1)
-+ ph = msg.GetPlaceholders()[0]
-+ self.failUnless(ph.GetOriginal() == 'Google Chrome')
-+ self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
-+ self.failUnless(ph.GetExample() == 'Google Chrome')
-+
-+ def testGetDescription(self):
-+ gatherer = policy_json.PolicyJson({})
-+ gatherer.SetDefines({'_google_chrome': True})
-+ self.assertEquals(
-+ gatherer._GetDescription({'name': 'Policy1', 'owners': ['a@b']},
-+ 'policy', None, 'desc'),
-+ 'Description of the policy named Policy1 [owner(s): a@b]')
-+ self.assertEquals(
-+ gatherer._GetDescription({'name': 'Plcy2', 'owners': ['a@b', 'c@d']},
-+ 'policy', None, 'caption'),
-+ 'Caption of the policy named Plcy2 [owner(s): a@b,c@d]')
-+ self.assertEquals(
-+ gatherer._GetDescription({'name': 'Plcy3', 'owners': ['a@b']},
-+ 'policy', None, 'label'),
-+ 'Label of the policy named Plcy3 [owner(s): a@b]')
-+ self.assertEquals(
-+ gatherer._GetDescription({'name': 'Item'}, 'enum_item',
-+ {'name': 'Plcy', 'owners': ['a@b']}, 'caption'),
-+ 'Caption of the option named Item in policy Plcy [owner(s): a@b]')
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/gather/rc.py b/tools/grit/grit/gather/rc.py
-new file mode 100644
-index 0000000000..dd091d1e18
---- /dev/null
-+++ b/tools/grit/grit/gather/rc.py
-@@ -0,0 +1,343 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Support for gathering resources from RC files.
-+'''
-+
-+from __future__ import print_function
-+
-+import re
-+
-+from grit import exception
-+from grit import lazy_re
-+from grit import tclib
-+
-+from grit.gather import regexp
-+
-+
-+# Find portions that need unescaping in resource strings. We need to be
-+# careful that a \\n is matched _first_ as a \\ rather than matching as
-+# a \ followed by a \n.
-+# TODO(joi) Handle ampersands if we decide to change them into <ph>
-+# TODO(joi) May need to handle other control characters than \n
-+_NEED_UNESCAPE = lazy_re.compile(r'""|\\\\|\\n|\\t')
-+
-+# Find portions that need escaping to encode string as a resource string.
-+_NEED_ESCAPE = lazy_re.compile(r'"|\n|\t|\\|\&nbsp\;')
-+
-+# How to escape certain characters
-+_ESCAPE_CHARS = {
-+ '"' : '""',
-+ '\n' : '\\n',
-+ '\t' : '\\t',
-+ '\\' : '\\\\',
-+ '&nbsp;' : ' '
-+}
-+
-+# How to unescape certain strings
-+_UNESCAPE_CHARS = dict([[value, key] for key, value in _ESCAPE_CHARS.items()])
-+
-+
-+
-+class Section(regexp.RegexpGatherer):
-+ '''A section from a resource file.'''
-+
-+ @staticmethod
-+ def Escape(text):
-+ '''Returns a version of 'text' with characters escaped that need to be
-+ for inclusion in a resource section.'''
-+ def Replace(match):
-+ return _ESCAPE_CHARS[match.group()]
-+ return _NEED_ESCAPE.sub(Replace, text)
-+
-+ @staticmethod
-+ def UnEscape(text):
-+ '''Returns a version of 'text' with escaped characters unescaped.'''
-+ def Replace(match):
-+ return _UNESCAPE_CHARS[match.group()]
-+ return _NEED_UNESCAPE.sub(Replace, text)
-+
-+ def _RegExpParse(self, rexp, text_to_parse):
-+ '''Overrides _RegExpParse to add shortcut group handling. Otherwise
-+ the same.
-+ '''
-+ super(Section, self)._RegExpParse(rexp, text_to_parse)
-+
-+ if not self.is_skeleton and len(self.GetTextualIds()) > 0:
-+ group_name = self.GetTextualIds()[0]
-+ for c in self.GetCliques():
-+ c.AddToShortcutGroup(group_name)
-+
-+ def ReadSection(self):
-+ rc_text = self._LoadInputFile()
-+
-+ out = ''
-+ begin_count = 0
-+ assert self.extkey
-+ first_line_re = re.compile(r'\s*' + self.extkey + r'\b')
-+ for line in rc_text.splitlines(True):
-+ if out or first_line_re.match(line):
-+ out += line
-+
-+ # we stop once we reach the END for the outermost block.
-+ begin_count_was = begin_count
-+ if len(out) > 0 and line.strip() == 'BEGIN':
-+ begin_count += 1
-+ elif len(out) > 0 and line.strip() == 'END':
-+ begin_count -= 1
-+ if begin_count_was == 1 and begin_count == 0:
-+ break
-+
-+ if len(out) == 0:
-+ raise exception.SectionNotFound('%s in file %s' % (self.extkey, self.rc_file))
-+
-+ self.text_ = out.strip()
-+
-+
-+class Dialog(Section):
-+ '''A resource section that contains a dialog resource.'''
-+
-+ # A typical dialog resource section looks like this:
-+ #
-+ # IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-+ # STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+ # CAPTION "About"
-+ # FONT 8, "System", 0, 0, 0x0
-+ # BEGIN
-+ # ICON IDI_KLONK,IDC_MYICON,14,9,20,20
-+ # LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
-+ # SS_NOPREFIX
-+ # LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
-+ # DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
-+ # CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
-+ # BS_AUTORADIOBUTTON,46,51,84,10
-+ # END
-+
-+ # We are using a sorted set of keys, and we assume that the
-+ # group name used for descriptions (type) will come after the "text"
-+ # group in alphabetical order. We also assume that there cannot be
-+ # more than one description per regular expression match.
-+ # If that's not the case some descriptions will be clobbered.
-+ dialog_re_ = lazy_re.compile(r'''
-+ # The dialog's ID in the first line
-+ (?P<id1>[A-Z0-9_]+)\s+DIALOG(EX)?
-+ |
-+ # The caption of the dialog
-+ (?P<type1>CAPTION)\s+"(?P<text1>.*?([^"]|""))"\s
-+ |
-+ # Lines for controls that have text and an ID
-+ \s+(?P<type2>[A-Z]+)\s+"(?P<text2>.*?([^"]|"")?)"\s*,\s*(?P<id2>[A-Z0-9_]+)\s*,
-+ |
-+ # Lines for controls that have text only
-+ \s+(?P<type3>[A-Z]+)\s+"(?P<text3>.*?([^"]|"")?)"\s*,
-+ |
-+ # Lines for controls that reference other resources
-+ \s+[A-Z]+\s+[A-Z0-9_]+\s*,\s*(?P<id3>[A-Z0-9_]*[A-Z][A-Z0-9_]*)
-+ |
-+ # This matches "NOT SOME_STYLE" so that it gets consumed and doesn't get
-+ # matched by the next option (controls that have only an ID and then just
-+ # numbers)
-+ \s+NOT\s+[A-Z][A-Z0-9_]+
-+ |
-+ # Lines for controls that have only an ID and then just numbers
-+ \s+[A-Z]+\s+(?P<id4>[A-Z0-9_]*[A-Z][A-Z0-9_]*)\s*,
-+ ''', re.MULTILINE | re.VERBOSE)
-+
-+ def Parse(self):
-+ '''Knows how to parse dialog resource sections.'''
-+ self.ReadSection()
-+ self._RegExpParse(self.dialog_re_, self.text_)
-+
-+
-+class Menu(Section):
-+ '''A resource section that contains a menu resource.'''
-+
-+ # A typical menu resource section looks something like this:
-+ #
-+ # IDC_KLONK MENU
-+ # BEGIN
-+ # POPUP "&File"
-+ # BEGIN
-+ # MENUITEM "E&xit", IDM_EXIT
-+ # MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
-+ # POPUP "gonk"
-+ # BEGIN
-+ # MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
-+ # END
-+ # END
-+ # POPUP "&Help"
-+ # BEGIN
-+ # MENUITEM "&About ...", IDM_ABOUT
-+ # END
-+ # END
-+
-+ # Description used for the messages generated for menus, to explain to
-+ # the translators how to handle them.
-+ MENU_MESSAGE_DESCRIPTION = (
-+ 'This message represents a menu. Each of the items appears in sequence '
-+ '(some possibly within sub-menus) in the menu. The XX01XX placeholders '
-+ 'serve to separate items. Each item contains an & (ampersand) character '
-+ 'in front of the keystroke that should be used as a shortcut for that item '
-+ 'in the menu. Please make sure that no two items in the same menu share '
-+ 'the same shortcut.'
-+ )
-+
-+ # A dandy regexp to suck all the IDs and translateables out of a menu
-+ # resource
-+ menu_re_ = lazy_re.compile(r'''
-+ # Match the MENU ID on the first line
-+ ^(?P<id1>[A-Z0-9_]+)\s+MENU
-+ |
-+ # Match the translateable caption for a popup menu
-+ POPUP\s+"(?P<text1>.*?([^"]|""))"\s
-+ |
-+ # Match the caption & ID of a MENUITEM
-+ MENUITEM\s+"(?P<text2>.*?([^"]|""))"\s*,\s*(?P<id2>[A-Z0-9_]+)
-+ ''', re.MULTILINE | re.VERBOSE)
-+
-+ def Parse(self):
-+ '''Knows how to parse menu resource sections. Because it is important that
-+ menu shortcuts are unique within the menu, we return each menu as a single
-+ message with placeholders to break up the different menu items, rather than
-+ return a single message per menu item. we also add an automatic description
-+ with instructions for the translators.'''
-+ self.ReadSection()
-+ self.single_message_ = tclib.Message(description=self.MENU_MESSAGE_DESCRIPTION)
-+ self._RegExpParse(self.menu_re_, self.text_)
-+
-+
-+class Version(Section):
-+ '''A resource section that contains a VERSIONINFO resource.'''
-+
-+ # A typical version info resource can look like this:
-+ #
-+ # VS_VERSION_INFO VERSIONINFO
-+ # FILEVERSION 1,0,0,1
-+ # PRODUCTVERSION 1,0,0,1
-+ # FILEFLAGSMASK 0x3fL
-+ # #ifdef _DEBUG
-+ # FILEFLAGS 0x1L
-+ # #else
-+ # FILEFLAGS 0x0L
-+ # #endif
-+ # FILEOS 0x4L
-+ # FILETYPE 0x2L
-+ # FILESUBTYPE 0x0L
-+ # BEGIN
-+ # BLOCK "StringFileInfo"
-+ # BEGIN
-+ # BLOCK "040904e4"
-+ # BEGIN
-+ # VALUE "CompanyName", "TODO: <Company name>"
-+ # VALUE "FileDescription", "TODO: <File description>"
-+ # VALUE "FileVersion", "1.0.0.1"
-+ # VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
-+ # VALUE "InternalName", "res_format_test.dll"
-+ # VALUE "OriginalFilename", "res_format_test.dll"
-+ # VALUE "ProductName", "TODO: <Product name>"
-+ # VALUE "ProductVersion", "1.0.0.1"
-+ # END
-+ # END
-+ # BLOCK "VarFileInfo"
-+ # BEGIN
-+ # VALUE "Translation", 0x409, 1252
-+ # END
-+ # END
-+ #
-+ #
-+ # In addition to the above fields, VALUE fields named "Comments" and
-+ # "LegalTrademarks" may also be translateable.
-+
-+ version_re_ = lazy_re.compile(r'''
-+ # Match the ID on the first line
-+ ^(?P<id1>[A-Z0-9_]+)\s+VERSIONINFO
-+ |
-+ # Match all potentially translateable VALUE sections
-+ \s+VALUE\s+"
-+ (
-+ CompanyName|FileDescription|LegalCopyright|
-+ ProductName|Comments|LegalTrademarks
-+ )",\s+"(?P<text1>.*?([^"]|""))"\s
-+ ''', re.MULTILINE | re.VERBOSE)
-+
-+ def Parse(self):
-+ '''Knows how to parse VERSIONINFO resource sections.'''
-+ self.ReadSection()
-+ self._RegExpParse(self.version_re_, self.text_)
-+
-+ # TODO(joi) May need to override the Translate() method to change the
-+ # "Translation" VALUE block to indicate the correct language code.
-+
-+
-+class RCData(Section):
-+ '''A resource section that contains some data .'''
-+
-+ # A typical rcdataresource section looks like this:
-+ #
-+ # IDR_BLAH RCDATA { 1, 2, 3, 4 }
-+
-+ dialog_re_ = lazy_re.compile(r'''
-+ ^(?P<id1>[A-Z0-9_]+)\s+RCDATA\s+(DISCARDABLE)?\s+\{.*?\}
-+ ''', re.MULTILINE | re.VERBOSE | re.DOTALL)
-+
-+ def Parse(self):
-+ '''Implementation for resource types w/braces (not BEGIN/END)
-+ '''
-+ rc_text = self._LoadInputFile()
-+
-+ out = ''
-+ begin_count = 0
-+ openbrace_count = 0
-+ assert self.extkey
-+ first_line_re = re.compile(r'\s*' + self.extkey + r'\b')
-+ for line in rc_text.splitlines(True):
-+ if out or first_line_re.match(line):
-+ out += line
-+
-+ # We stop once the braces balance (could happen in one line).
-+ begin_count_was = begin_count
-+ if len(out) > 0:
-+ openbrace_count += line.count('{')
-+ begin_count += line.count('{')
-+ begin_count -= line.count('}')
-+ if ((begin_count_was == 1 and begin_count == 0) or
-+ (openbrace_count > 0 and begin_count == 0)):
-+ break
-+
-+ if len(out) == 0:
-+ raise exception.SectionNotFound('%s in file %s' % (self.extkey, self.rc_file))
-+
-+ self.text_ = out
-+
-+ self._RegExpParse(self.dialog_re_, out)
-+
-+
-+class Accelerators(Section):
-+ '''An ACCELERATORS table.
-+ '''
-+
-+ # A typical ACCELERATORS section looks like this:
-+ #
-+ # IDR_ACCELERATOR1 ACCELERATORS
-+ # BEGIN
-+ # "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
-+ # "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
-+ # VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
-+ # END
-+
-+ accelerators_re_ = lazy_re.compile(r'''
-+ # Match the ID on the first line
-+ ^(?P<id1>[A-Z0-9_]+)\s+ACCELERATORS\s+
-+ |
-+ # Match accelerators specified as VK_XXX
-+ \s+VK_[A-Z0-9_]+,\s*(?P<id2>[A-Z0-9_]+)\s*,
-+ |
-+ # Match accelerators specified as e.g. "^C"
-+ \s+"[^"]*",\s+(?P<id3>[A-Z0-9_]+)\s*,
-+ ''', re.MULTILINE | re.VERBOSE)
-+
-+ def Parse(self):
-+ '''Knows how to parse ACCELERATORS resource sections.'''
-+ self.ReadSection()
-+ self._RegExpParse(self.accelerators_re_, self.text_)
-diff --git a/tools/grit/grit/gather/rc_unittest.py b/tools/grit/grit/gather/rc_unittest.py
-new file mode 100644
-index 0000000000..3c26a4342a
---- /dev/null
-+++ b/tools/grit/grit/gather/rc_unittest.py
-@@ -0,0 +1,372 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.gather.rc'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit.gather import rc
-+from grit import util
-+
-+
-+class RcUnittest(unittest.TestCase):
-+
-+ part_we_want = '''IDC_KLONKACC ACCELERATORS
-+BEGIN
-+ "?", IDM_ABOUT, ASCII, ALT
-+ "/", IDM_ABOUT, ASCII, ALT
-+END'''
-+
-+ def testSectionFromFile(self):
-+ buf = '''IDC_SOMETHINGELSE BINGO
-+BEGIN
-+ BLA BLA
-+ BLA BLA
-+END
-+%s
-+
-+IDC_KLONK BINGOBONGO
-+BEGIN
-+ HONGO KONGO
-+END
-+''' % self.part_we_want
-+
-+ f = StringIO(buf)
-+
-+ out = rc.Section(f, 'IDC_KLONKACC')
-+ out.ReadSection()
-+ self.failUnless(out.GetText() == self.part_we_want)
-+
-+ out = rc.Section(util.PathFromRoot(r'grit/testdata/klonk.rc'),
-+ 'IDC_KLONKACC',
-+ encoding='utf-16')
-+ out.ReadSection()
-+ out_text = out.GetText().replace('\t', '')
-+ out_text = out_text.replace(' ', '')
-+ self.part_we_want = self.part_we_want.replace(' ', '')
-+ self.failUnless(out_text.strip() == self.part_we_want.strip())
-+
-+
-+ def testDialog(self):
-+ dlg = rc.Dialog(StringIO('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "About"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
-+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
-+ SS_NOPREFIX
-+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
-+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
-+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
-+ BS_AUTORADIOBUTTON,46,51,84,10
-+ // try a line where the ID is on the continuation line
-+ LTEXT "blablablabla blablabla blablablablablablablabla blablabla",
-+ ID_SMURF, whatever...
-+END
-+'''), 'IDD_ABOUTBOX')
-+ dlg.Parse()
-+ self.failUnless(len(dlg.GetTextualIds()) == 7)
-+ self.failUnless(len(dlg.GetCliques()) == 6)
-+ self.failUnless(dlg.GetCliques()[1].GetMessage().GetRealContent() ==
-+ 'klonk Version "yibbee" 1.0')
-+
-+ transl = dlg.Translate('en')
-+ self.failUnless(transl.strip() == dlg.GetText().strip())
-+
-+ def testAlternateSkeleton(self):
-+ dlg = rc.Dialog(StringIO('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "About"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ LTEXT "Yipee skippy",IDC_STATIC,49,10,119,8,
-+ SS_NOPREFIX
-+END
-+'''), 'IDD_ABOUTBOX')
-+ dlg.Parse()
-+
-+ alt_dlg = rc.Dialog(StringIO('''IDD_ABOUTBOX DIALOGEX 040704, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "XXXXXXXXX"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ LTEXT "XXXXXXXXXXXXXXXXX",IDC_STATIC,110978,10,119,8,
-+ SS_NOPREFIX
-+END
-+'''), 'IDD_ABOUTBOX')
-+ alt_dlg.Parse()
-+
-+ transl = dlg.Translate('en', skeleton_gatherer=alt_dlg)
-+ self.failUnless(transl.count('040704') and
-+ transl.count('110978'))
-+ self.failUnless(transl.count('Yipee skippy'))
-+
-+ def testMenu(self):
-+ menu = rc.Menu(StringIO('''IDC_KLONK MENU
-+BEGIN
-+ POPUP "&File """
-+ BEGIN
-+ MENUITEM "E&xit", IDM_EXIT
-+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
-+ POPUP "gonk"
-+ BEGIN
-+ MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
-+ END
-+ MENUITEM "This is a very long menu caption to try to see if we can make the ID go to a continuation line, blablabla blablabla bla blabla blablabla blablabla blablabla blablabla...",
-+ ID_FILE_THISISAVERYLONGMENUCAPTIONTOTRYTOSEEIFWECANMAKETHEIDGOTOACONTINUATIONLINE
-+ END
-+ POPUP "&Help"
-+ BEGIN
-+ MENUITEM "&About ...", IDM_ABOUT
-+ END
-+END'''), 'IDC_KLONK')
-+
-+ menu.Parse()
-+ self.failUnless(len(menu.GetTextualIds()) == 6)
-+ self.failUnless(len(menu.GetCliques()) == 1)
-+ self.failUnless(len(menu.GetCliques()[0].GetMessage().GetPlaceholders()) ==
-+ 9)
-+
-+ transl = menu.Translate('en')
-+ self.failUnless(transl.strip() == menu.GetText().strip())
-+
-+ def testVersion(self):
-+ version = rc.Version(StringIO('''
-+VS_VERSION_INFO VERSIONINFO
-+ FILEVERSION 1,0,0,1
-+ PRODUCTVERSION 1,0,0,1
-+ FILEFLAGSMASK 0x3fL
-+#ifdef _DEBUG
-+ FILEFLAGS 0x1L
-+#else
-+ FILEFLAGS 0x0L
-+#endif
-+ FILEOS 0x4L
-+ FILETYPE 0x2L
-+ FILESUBTYPE 0x0L
-+BEGIN
-+ BLOCK "StringFileInfo"
-+ BEGIN
-+ BLOCK "040904e4"
-+ BEGIN
-+ VALUE "CompanyName", "TODO: <Company name>"
-+ VALUE "FileDescription", "TODO: <File description>"
-+ VALUE "FileVersion", "1.0.0.1"
-+ VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
-+ VALUE "InternalName", "res_format_test.dll"
-+ VALUE "OriginalFilename", "res_format_test.dll"
-+ VALUE "ProductName", "TODO: <Product name>"
-+ VALUE "ProductVersion", "1.0.0.1"
-+ END
-+ END
-+ BLOCK "VarFileInfo"
-+ BEGIN
-+ VALUE "Translation", 0x409, 1252
-+ END
-+END
-+'''.strip()), 'VS_VERSION_INFO')
-+ version.Parse()
-+ self.failUnless(len(version.GetTextualIds()) == 1)
-+ self.failUnless(len(version.GetCliques()) == 4)
-+
-+ transl = version.Translate('en')
-+ self.failUnless(transl.strip() == version.GetText().strip())
-+
-+
-+ def testRegressionDialogBox(self):
-+ dialog = rc.Dialog(StringIO('''
-+IDD_SIDEBAR_WEATHER_PANEL_PROPPAGE DIALOGEX 0, 0, 205, 157
-+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-+FONT 8, "MS Shell Dlg", 400, 0, 0x1
-+BEGIN
-+ EDITTEXT IDC_SIDEBAR_WEATHER_NEW_CITY,3,27,112,14,ES_AUTOHSCROLL
-+ DEFPUSHBUTTON "Add Location",IDC_SIDEBAR_WEATHER_ADD,119,27,50,14
-+ LISTBOX IDC_SIDEBAR_WEATHER_CURR_CITIES,3,48,127,89,
-+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
-+ PUSHBUTTON "Move Up",IDC_SIDEBAR_WEATHER_MOVE_UP,134,104,50,14
-+ PUSHBUTTON "Move Down",IDC_SIDEBAR_WEATHER_MOVE_DOWN,134,121,50,14
-+ PUSHBUTTON "Remove",IDC_SIDEBAR_WEATHER_DELETE,134,48,50,14
-+ LTEXT "To see current weather conditions and forecasts in the USA, enter the zip code (example: 94043) or city and state (example: Mountain View, CA).",
-+ IDC_STATIC,3,0,199,25
-+ CONTROL "Fahrenheit",IDC_SIDEBAR_WEATHER_FAHRENHEIT,"Button",
-+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,3,144,51,10
-+ CONTROL "Celsius",IDC_SIDEBAR_WEATHER_CELSIUS,"Button",
-+ BS_AUTORADIOBUTTON,57,144,38,10
-+END'''.strip()), 'IDD_SIDEBAR_WEATHER_PANEL_PROPPAGE')
-+ dialog.Parse()
-+ self.failUnless(len(dialog.GetTextualIds()) == 10)
-+
-+
-+ def testRegressionDialogBox2(self):
-+ dialog = rc.Dialog(StringIO('''
-+IDD_SIDEBAR_EMAIL_PANEL_PROPPAGE DIALOG DISCARDABLE 0, 0, 264, 220
-+STYLE WS_CHILD
-+FONT 8, "MS Shell Dlg"
-+BEGIN
-+ GROUPBOX "Email Filters",IDC_STATIC,7,3,250,190
-+ LTEXT "Click Add Filter to create the email filter.",IDC_STATIC,16,41,130,9
-+ PUSHBUTTON "Add Filter...",IDC_SIDEBAR_EMAIL_ADD_FILTER,196,38,50,14
-+ PUSHBUTTON "Remove",IDC_SIDEBAR_EMAIL_REMOVE,196,174,50,14
-+ PUSHBUTTON "", IDC_SIDEBAR_EMAIL_HIDDEN, 200, 178, 5, 5, NOT WS_VISIBLE
-+ LISTBOX IDC_SIDEBAR_EMAIL_LIST,16,60,230,108,
-+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
-+ LTEXT "You can prevent certain emails from showing up in the sidebar with a filter.",
-+ IDC_STATIC,16,18,234,18
-+END'''.strip()), 'IDD_SIDEBAR_EMAIL_PANEL_PROPPAGE')
-+ dialog.Parse()
-+ self.failUnless('IDC_SIDEBAR_EMAIL_HIDDEN' in dialog.GetTextualIds())
-+
-+
-+ def testRegressionMenuId(self):
-+ menu = rc.Menu(StringIO('''
-+IDR_HYPERMENU_FOLDER MENU
-+BEGIN
-+ POPUP "HyperFolder"
-+ BEGIN
-+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
-+ END
-+END'''.strip()), 'IDR_HYPERMENU_FOLDER')
-+ menu.Parse()
-+ self.failUnless(len(menu.GetTextualIds()) == 2)
-+
-+ def testRegressionNewlines(self):
-+ menu = rc.Menu(StringIO('''
-+IDR_HYPERMENU_FOLDER MENU
-+BEGIN
-+ POPUP "Hyper\\nFolder"
-+ BEGIN
-+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
-+ END
-+END'''.strip()), 'IDR_HYPERMENU_FOLDER')
-+ menu.Parse()
-+ transl = menu.Translate('en')
-+ # Shouldn't find \\n (the \n shouldn't be changed to \\n)
-+ self.failUnless(transl.find('\\\\n') == -1)
-+
-+ def testRegressionTabs(self):
-+ menu = rc.Menu(StringIO('''
-+IDR_HYPERMENU_FOLDER MENU
-+BEGIN
-+ POPUP "Hyper\\tFolder"
-+ BEGIN
-+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
-+ END
-+END'''.strip()), 'IDR_HYPERMENU_FOLDER')
-+ menu.Parse()
-+ transl = menu.Translate('en')
-+ # Shouldn't find \\t (the \t shouldn't be changed to \\t)
-+ self.failUnless(transl.find('\\\\t') == -1)
-+
-+ def testEscapeUnescape(self):
-+ original = 'Hello "bingo"\n How\\are\\you\\n?'
-+ escaped = rc.Section.Escape(original)
-+ self.failUnless(escaped == 'Hello ""bingo""\\n How\\\\are\\\\you\\\\n?')
-+ unescaped = rc.Section.UnEscape(escaped)
-+ self.failUnless(unescaped == original)
-+
-+ def testRegressionPathsWithSlashN(self):
-+ original = '..\\\\..\\\\trs\\\\res\\\\nav_first.gif'
-+ unescaped = rc.Section.UnEscape(original)
-+ self.failUnless(unescaped == '..\\..\\trs\\res\\nav_first.gif')
-+
-+ def testRegressionDialogItemsTextOnly(self):
-+ dialog = rc.Dialog(StringIO('''IDD_OPTIONS_SEARCH DIALOGEX 0, 0, 280, 292
-+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
-+ WS_DISABLED | WS_CAPTION | WS_SYSMENU
-+CAPTION "Search"
-+FONT 8, "MS Shell Dlg", 400, 0, 0x1
-+BEGIN
-+ GROUPBOX "Select search buttons and options",-1,7,5,266,262
-+ CONTROL "",IDC_OPTIONS,"SysTreeView32",TVS_DISABLEDRAGDROP |
-+ WS_BORDER | WS_TABSTOP | 0x800,16,19,248,218
-+ LTEXT "Use Google site:",-1,26,248,52,8
-+ COMBOBOX IDC_GOOGLE_HOME,87,245,177,256,CBS_DROPDOWNLIST |
-+ WS_VSCROLL | WS_TABSTOP
-+ PUSHBUTTON "Restore Defaults...",IDC_RESET,187,272,86,14
-+END'''), 'IDD_OPTIONS_SEARCH')
-+ dialog.Parse()
-+ translateables = [c.GetMessage().GetRealContent()
-+ for c in dialog.GetCliques()]
-+ self.failUnless('Select search buttons and options' in translateables)
-+ self.failUnless('Use Google site:' in translateables)
-+
-+ def testAccelerators(self):
-+ acc = rc.Accelerators(StringIO('''\
-+IDR_ACCELERATOR1 ACCELERATORS
-+BEGIN
-+ "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
-+ "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
-+ VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
-+END
-+'''), 'IDR_ACCELERATOR1')
-+ acc.Parse()
-+ self.failUnless(len(acc.GetTextualIds()) == 4)
-+ self.failUnless(len(acc.GetCliques()) == 0)
-+
-+ transl = acc.Translate('en')
-+ self.failUnless(transl.strip() == acc.GetText().strip())
-+
-+
-+ def testRegressionEmptyString(self):
-+ dlg = rc.Dialog(StringIO('''\
-+IDD_CONFIRM_QUIT_GD_DLG DIALOGEX 0, 0, 267, 108
-+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
-+ WS_CAPTION
-+EXSTYLE WS_EX_TOPMOST
-+CAPTION "Google Desktop"
-+FONT 8, "MS Shell Dlg", 400, 0, 0x1
-+BEGIN
-+ DEFPUSHBUTTON "&Yes",IDYES,82,87,50,14
-+ PUSHBUTTON "&No",IDNO,136,87,50,14
-+ ICON 32514,IDC_STATIC,7,9,21,20
-+ EDITTEXT IDC_TEXTBOX,34,7,231,60,ES_MULTILINE | ES_READONLY | NOT WS_BORDER
-+ CONTROL "",
-+ IDC_ENABLE_GD_AUTOSTART,"Button",BS_AUTOCHECKBOX |
-+ WS_TABSTOP,33,70,231,10
-+END'''), 'IDD_CONFIRM_QUIT_GD_DLG')
-+ dlg.Parse()
-+
-+ def Check():
-+ self.failUnless(transl.count('IDC_ENABLE_GD_AUTOSTART'))
-+ self.failUnless(transl.count('END'))
-+
-+ transl = dlg.Translate('de', pseudo_if_not_available=True,
-+ fallback_to_english=True)
-+ Check()
-+ transl = dlg.Translate('de', pseudo_if_not_available=True,
-+ fallback_to_english=False)
-+ Check()
-+ transl = dlg.Translate('de', pseudo_if_not_available=False,
-+ fallback_to_english=True)
-+ Check()
-+ transl = dlg.Translate('de', pseudo_if_not_available=False,
-+ fallback_to_english=False)
-+ Check()
-+ transl = dlg.Translate('en', pseudo_if_not_available=True,
-+ fallback_to_english=True)
-+ Check()
-+ transl = dlg.Translate('en', pseudo_if_not_available=True,
-+ fallback_to_english=False)
-+ Check()
-+ transl = dlg.Translate('en', pseudo_if_not_available=False,
-+ fallback_to_english=True)
-+ Check()
-+ transl = dlg.Translate('en', pseudo_if_not_available=False,
-+ fallback_to_english=False)
-+ Check()
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/gather/regexp.py b/tools/grit/grit/gather/regexp.py
-new file mode 100644
-index 0000000000..97ce2cfbf7
---- /dev/null
-+++ b/tools/grit/grit/gather/regexp.py
-@@ -0,0 +1,82 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''A baseclass for simple gatherers based on regular expressions.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit.gather import skeleton_gatherer
-+
-+
-+class RegexpGatherer(skeleton_gatherer.SkeletonGatherer):
-+ '''Common functionality of gatherers based on parsing using a single
-+ regular expression.
-+ '''
-+
-+ DescriptionMapping_ = {
-+ 'CAPTION' : 'This is a caption for a dialog',
-+ 'CHECKBOX' : 'This is a label for a checkbox',
-+ 'CONTROL': 'This is the text on a control',
-+ 'CTEXT': 'This is a label for a control',
-+ 'DEFPUSHBUTTON': 'This is a button definition',
-+ 'GROUPBOX': 'This is a label for a grouping',
-+ 'ICON': 'This is a label for an icon',
-+ 'LTEXT': 'This is the text for a label',
-+ 'PUSHBUTTON': 'This is the text for a button',
-+ }
-+
-+ # Contextualization elements. Used for adding additional information
-+ # to the message bundle description string from RC files.
-+ def AddDescriptionElement(self, string):
-+ if string in self.DescriptionMapping_:
-+ description = self.DescriptionMapping_[string]
-+ else:
-+ description = string
-+ if self.single_message_:
-+ self.single_message_.SetDescription(description)
-+ else:
-+ if (self.translatable_chunk_):
-+ message = self.skeleton_[len(self.skeleton_) - 1].GetMessage()
-+ message.SetDescription(description)
-+
-+ def _RegExpParse(self, regexp, text_to_parse):
-+ '''An implementation of Parse() that can be used for resource sections that
-+ can be parsed using a single multi-line regular expression.
-+
-+ All translateables must be in named groups that have names starting with
-+ 'text'. All textual IDs must be in named groups that have names starting
-+ with 'id'. All type definitions that can be included in the description
-+ field for contextualization purposes should have a name that starts with
-+ 'type'.
-+
-+ Args:
-+ regexp: re.compile('...', re.MULTILINE)
-+ text_to_parse:
-+ '''
-+ chunk_start = 0
-+ for match in regexp.finditer(text_to_parse):
-+ groups = match.groupdict()
-+ keys = sorted(groups.keys())
-+ self.translatable_chunk_ = False
-+ for group in keys:
-+ if group.startswith('id') and groups[group]:
-+ self._AddTextualId(groups[group])
-+ elif group.startswith('text') and groups[group]:
-+ self._AddNontranslateableChunk(
-+ text_to_parse[chunk_start : match.start(group)])
-+ chunk_start = match.end(group) # Next chunk will start after the match
-+ self._AddTranslateableChunk(groups[group])
-+ elif group.startswith('type') and groups[group]:
-+ # Add the description to the skeleton_ list. This works because
-+ # we are using a sort set of keys, and because we assume that the
-+ # group name used for descriptions (type) will come after the "text"
-+ # group in alphabetical order. We also assume that there cannot be
-+ # more than one description per regular expression match.
-+ self.AddDescriptionElement(groups[group])
-+
-+ self._AddNontranslateableChunk(text_to_parse[chunk_start:])
-+
-+ if self.single_message_:
-+ self.skeleton_.append(self.uberclique.MakeClique(self.single_message_))
-diff --git a/tools/grit/grit/gather/skeleton_gatherer.py b/tools/grit/grit/gather/skeleton_gatherer.py
-new file mode 100644
-index 0000000000..b11862b314
---- /dev/null
-+++ b/tools/grit/grit/gather/skeleton_gatherer.py
-@@ -0,0 +1,149 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''A baseclass for simple gatherers that store their gathered resource in a
-+list.
-+'''
-+
-+from __future__ import print_function
-+
-+import six
-+
-+from grit.gather import interface
-+from grit import clique
-+from grit import exception
-+from grit import tclib
-+
-+
-+class SkeletonGatherer(interface.GathererBase):
-+ '''Common functionality of gatherers that parse their input as a skeleton of
-+ translatable and nontranslatable chunks.
-+ '''
-+
-+ def __init__(self, *args, **kwargs):
-+ super(SkeletonGatherer, self).__init__(*args, **kwargs)
-+ # List of parts of the document. Translateable parts are
-+ # clique.MessageClique objects, nontranslateable parts are plain strings.
-+ # Translated messages are inserted back into the skeleton using the quoting
-+ # rules defined by self.Escape()
-+ self.skeleton_ = []
-+ # A list of the names of IDs that need to be defined for this resource
-+ # section to compile correctly.
-+ self.ids_ = []
-+ # True if Parse() has already been called.
-+ self.have_parsed_ = False
-+ # True if a translatable chunk has been added
-+ self.translatable_chunk_ = False
-+ # If not None, all parts of the document will be put into this single
-+ # message; otherwise the normal skeleton approach is used.
-+ self.single_message_ = None
-+ # Number to use for the next placeholder name. Used only if single_message
-+ # is not None
-+ self.ph_counter_ = 1
-+
-+ def GetText(self):
-+ '''Returns the original text of the section'''
-+ return self.text_
-+
-+ def Escape(self, text):
-+ '''Subclasses can override. Base impl is identity.
-+ '''
-+ return text
-+
-+ def UnEscape(self, text):
-+ '''Subclasses can override. Base impl is identity.
-+ '''
-+ return text
-+
-+ def GetTextualIds(self):
-+ '''Returns the list of textual IDs that need to be defined for this
-+ resource section to compile correctly.'''
-+ return self.ids_
-+
-+ def _AddTextualId(self, id):
-+ self.ids_.append(id)
-+
-+ def GetCliques(self):
-+ '''Returns the message cliques for each translateable message in the
-+ resource section.'''
-+ return [x for x in self.skeleton_ if isinstance(x, clique.MessageClique)]
-+
-+ def Translate(self, lang, pseudo_if_not_available=True,
-+ skeleton_gatherer=None, fallback_to_english=False):
-+ if len(self.skeleton_) == 0:
-+ raise exception.NotReady()
-+ if skeleton_gatherer:
-+ assert len(skeleton_gatherer.skeleton_) == len(self.skeleton_)
-+
-+ out = []
-+ for ix in range(len(self.skeleton_)):
-+ if isinstance(self.skeleton_[ix], six.string_types):
-+ if skeleton_gatherer:
-+ # Make sure the skeleton is like the original
-+ assert(isinstance(skeleton_gatherer.skeleton_[ix], six.string_types))
-+ out.append(skeleton_gatherer.skeleton_[ix])
-+ else:
-+ out.append(self.skeleton_[ix])
-+ else:
-+ if skeleton_gatherer: # Make sure the skeleton is like the original
-+ assert(not isinstance(skeleton_gatherer.skeleton_[ix],
-+ six.string_types))
-+ msg = self.skeleton_[ix].MessageForLanguage(lang,
-+ pseudo_if_not_available,
-+ fallback_to_english)
-+
-+ def MyEscape(text):
-+ return self.Escape(text)
-+ text = msg.GetRealContent(escaping_function=MyEscape)
-+ out.append(text)
-+ return ''.join(out)
-+
-+ def Parse(self):
-+ '''Parses the section. Implemented by subclasses. Idempotent.'''
-+ raise NotImplementedError()
-+
-+ def _AddNontranslateableChunk(self, chunk):
-+ '''Adds a nontranslateable chunk.'''
-+ if self.single_message_:
-+ ph = tclib.Placeholder('XX%02dXX' % self.ph_counter_, chunk, chunk)
-+ self.ph_counter_ += 1
-+ self.single_message_.AppendPlaceholder(ph)
-+ else:
-+ self.skeleton_.append(chunk)
-+
-+ def _AddTranslateableChunk(self, chunk):
-+ '''Adds a translateable chunk. It will be unescaped before being added.'''
-+ # We don't want empty messages since they are redundant and the TC
-+ # doesn't allow them.
-+ if chunk == '':
-+ return
-+
-+ unescaped_text = self.UnEscape(chunk)
-+ if self.single_message_:
-+ self.single_message_.AppendText(unescaped_text)
-+ else:
-+ self.skeleton_.append(self.uberclique.MakeClique(
-+ tclib.Message(text=unescaped_text)))
-+ self.translatable_chunk_ = True
-+
-+ def SubstituteMessages(self, substituter):
-+ '''Applies substitutions to all messages in the tree.
-+
-+ Goes through the skeleton and finds all MessageCliques.
-+
-+ Args:
-+ substituter: a grit.util.Substituter object.
-+ '''
-+ if self.single_message_:
-+ self.single_message_ = substituter.SubstituteMessage(self.single_message_)
-+ new_skel = []
-+ for chunk in self.skeleton_:
-+ if isinstance(chunk, clique.MessageClique):
-+ old_message = chunk.GetMessage()
-+ new_message = substituter.SubstituteMessage(old_message)
-+ if new_message is not old_message:
-+ new_skel.append(self.uberclique.MakeClique(new_message))
-+ continue
-+ new_skel.append(chunk)
-+ self.skeleton_ = new_skel
-diff --git a/tools/grit/grit/gather/tr_html.py b/tools/grit/grit/gather/tr_html.py
-new file mode 100644
-index 0000000000..60a9bfaf4e
---- /dev/null
-+++ b/tools/grit/grit/gather/tr_html.py
-@@ -0,0 +1,743 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''A gatherer for the TotalRecall brand of HTML templates with replaceable
-+portions. We wanted to reuse extern.tclib.api.handlers.html.TCHTMLParser
-+but this proved impossible due to the fact that the TotalRecall HTML templates
-+are in general quite far from parseable HTML and the TCHTMLParser derives
-+
-+from HTMLParser.HTMLParser which requires relatively well-formed HTML. Some
-+examples of "HTML" from the TotalRecall HTML templates that wouldn't be
-+parseable include things like:
-+
-+ <a [PARAMS]>blabla</a> (not parseable because attributes are invalid)
-+
-+ <table><tr><td>[LOTSOFSTUFF]</tr></table> (not parseable because closing
-+ </td> is in the HTML [LOTSOFSTUFF]
-+ is replaced by)
-+
-+The other problem with using general parsers (such as TCHTMLParser) is that
-+we want to make sure we output the TotalRecall template with as little changes
-+as possible in terms of whitespace characters, layout etc. With any parser
-+that generates a parse tree, and generates output by dumping the parse tree,
-+we would always have little inconsistencies which could cause bugs (the
-+TotalRecall template stuff is quite brittle and can break if e.g. a tab
-+character is replaced with spaces).
-+
-+The solution, which may be applicable to some other HTML-like template
-+languages floating around Google, is to create a parser with a simple state
-+machine that keeps track of what kind of tag it's inside, and whether it's in
-+a translateable section or not. Translateable sections are:
-+
-+a) text (including [BINGO] replaceables) inside of tags that
-+ can contain translateable text (which is all tags except
-+ for a few)
-+
-+b) text inside of an 'alt' attribute in an <image> element, or
-+ the 'value' attribute of a <submit>, <button> or <text>
-+ element.
-+
-+The parser does not build up a parse tree but rather a "skeleton" which
-+is a list of nontranslateable strings intermingled with grit.clique.MessageClique
-+objects. This simplifies the parser considerably compared to a regular HTML
-+parser. To output a translated document, each item in the skeleton is
-+printed out, with the relevant Translation from each MessageCliques being used
-+for the requested language.
-+
-+This implementation borrows some code, constants and ideas from
-+extern.tclib.api.handlers.html.TCHTMLParser.
-+'''
-+
-+from __future__ import print_function
-+
-+import re
-+
-+import six
-+
-+from grit import clique
-+from grit import exception
-+from grit import lazy_re
-+from grit import util
-+from grit import tclib
-+
-+from grit.gather import interface
-+
-+
-+# HTML tags which break (separate) chunks.
-+_BLOCK_TAGS = ['script', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'br',
-+ 'body', 'style', 'head', 'title', 'table', 'tr', 'td', 'th',
-+ 'ul', 'ol', 'dl', 'nl', 'li', 'div', 'object', 'center',
-+ 'html', 'link', 'form', 'select', 'textarea',
-+ 'button', 'option', 'map', 'area', 'blockquote', 'pre',
-+ 'meta', 'xmp', 'noscript', 'label', 'tbody', 'thead',
-+ 'script', 'style', 'pre', 'iframe', 'img', 'input', 'nowrap',
-+ 'fieldset', 'legend']
-+
-+# HTML tags which may appear within a chunk.
-+_INLINE_TAGS = ['b', 'i', 'u', 'tt', 'code', 'font', 'a', 'span', 'small',
-+ 'key', 'nobr', 'url', 'em', 's', 'sup', 'strike',
-+ 'strong']
-+
-+# HTML tags within which linebreaks are significant.
-+_PREFORMATTED_TAGS = ['textarea', 'xmp', 'pre']
-+
-+# An array mapping some of the inline HTML tags to more meaningful
-+# names for those tags. This will be used when generating placeholders
-+# representing these tags.
-+_HTML_PLACEHOLDER_NAMES = { 'a' : 'link', 'br' : 'break', 'b' : 'bold',
-+ 'i' : 'italic', 'li' : 'item', 'ol' : 'ordered_list', 'p' : 'paragraph',
-+ 'ul' : 'unordered_list', 'img' : 'image', 'em' : 'emphasis' }
-+
-+# We append each of these characters in sequence to distinguish between
-+# different placeholders with basically the same name (e.g. BOLD1, BOLD2).
-+# Keep in mind that a placeholder name must not be a substring of any other
-+# placeholder name in the same message, so we can't simply count (BOLD_1
-+# would be a substring of BOLD_10).
-+_SUFFIXES = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-+
-+# Matches whitespace in an HTML document. Also matches HTML comments, which are
-+# treated as whitespace.
-+_WHITESPACE = lazy_re.compile(r'(\s|&nbsp;|\\n|\\r|<!--\s*desc\s*=.*?-->)+',
-+ re.DOTALL)
-+
-+# Matches whitespace sequences which can be folded into a single whitespace
-+# character. This matches single characters so that non-spaces are replaced
-+# with spaces.
-+_FOLD_WHITESPACE = lazy_re.compile(r'\s+')
-+
-+# Finds a non-whitespace character
-+_NON_WHITESPACE = lazy_re.compile(r'\S')
-+
-+# Matches two or more &nbsp; in a row (a single &nbsp is not changed into
-+# placeholders because different languages require different numbers of spaces
-+# and placeholders must match exactly; more than one is probably a "special"
-+# whitespace sequence and should be turned into a placeholder).
-+_NBSP = lazy_re.compile(r'&nbsp;(&nbsp;)+')
-+
-+# Matches nontranslateable chunks of the document
-+_NONTRANSLATEABLES = lazy_re.compile(r'''
-+ <\s*script.+?<\s*/\s*script\s*>
-+ |
-+ <\s*style.+?<\s*/\s*style\s*>
-+ |
-+ <!--.+?-->
-+ |
-+ <\?IMPORT\s.+?> # import tag
-+ |
-+ <\s*[a-zA-Z_]+:.+?> # custom tag (open)
-+ |
-+ <\s*/\s*[a-zA-Z_]+:.+?> # custom tag (close)
-+ |
-+ <!\s*[A-Z]+\s*([^>]+|"[^"]+"|'[^']+')*?>
-+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
-+
-+# Matches a tag and its attributes
-+_ELEMENT = lazy_re.compile(r'''
-+ # Optional closing /, element name
-+ <\s*(?P<closing>/)?\s*(?P<element>[a-zA-Z0-9]+)\s*
-+ # Attributes and/or replaceables inside the tag, if any
-+ (?P<atts>(
-+ \s*([a-zA-Z_][-:.a-zA-Z_0-9]*) # Attribute name
-+ (\s*=\s*(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?
-+ |
-+ \s*\[(\$?\~)?([A-Z0-9-_]+?)(\~\$?)?\]
-+ )*)
-+ \s*(?P<empty>/)?\s*> # Optional empty-tag closing /, and tag close
-+ ''',
-+ re.MULTILINE | re.DOTALL | re.VERBOSE)
-+
-+# Matches elements that may have translateable attributes. The value of these
-+# special attributes is given by group 'value1' or 'value2'. Note that this
-+# regexp demands that the attribute value be quoted; this is necessary because
-+# the non-tree-building nature of the parser means we don't know when we're
-+# writing out attributes, so we wouldn't know to escape spaces.
-+_SPECIAL_ELEMENT = lazy_re.compile(r'''
-+ <\s*(
-+ input[^>]+?value\s*=\s*(\'(?P<value3>[^\']*)\'|"(?P<value4>[^"]*)")
-+ [^>]+type\s*=\s*"?'?(button|reset|text|submit)'?"?
-+ |
-+ (
-+ table[^>]+?title\s*=
-+ |
-+ img[^>]+?alt\s*=
-+ |
-+ input[^>]+?type\s*=\s*"?'?(button|reset|text|submit)'?"?[^>]+?value\s*=
-+ )
-+ \s*(\'(?P<value1>[^\']*)\'|"(?P<value2>[^"]*)")
-+ )[^>]*?>
-+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
-+
-+# Matches stuff that is translateable if it occurs in the right context
-+# (between tags). This includes all characters and character entities.
-+# Note that this also matches &nbsp; which needs to be handled as whitespace
-+# before this regexp is applied.
-+_CHARACTERS = lazy_re.compile(r'''
-+ (
-+ \w
-+ |
-+ [\!\@\#\$\%\^\*\(\)\-\=\_\+\[\]\{\}\\\|\;\:\'\"\,\.\/\?\`\~]
-+ |
-+ &(\#[0-9]+|\#x[0-9a-fA-F]+|[A-Za-z0-9]+);
-+ )+
-+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
-+
-+# Matches Total Recall's "replaceable" tags, which are just any text
-+# in capitals enclosed by delimiters like [] or [~~] or [$~~$] (e.g. [HELLO],
-+# [~HELLO~] and [$~HELLO~$]).
-+_REPLACEABLE = lazy_re.compile(r'\[(\$?\~)?(?P<name>[A-Z0-9-_]+?)(\~\$?)?\]',
-+ re.MULTILINE)
-+
-+
-+# Matches the silly [!]-prefixed "header" that is used in some TotalRecall
-+# templates.
-+_SILLY_HEADER = lazy_re.compile(r'\[!\]\ntitle\t(?P<title>[^\n]+?)\n.+?\n\n',
-+ re.MULTILINE | re.DOTALL)
-+
-+
-+# Matches a comment that provides a description for the message it occurs in.
-+_DESCRIPTION_COMMENT = lazy_re.compile(
-+ r'<!--\s*desc\s*=\s*(?P<description>.+?)\s*-->', re.DOTALL)
-+
-+# Matches a comment which is used to break apart multiple messages.
-+_MESSAGE_BREAK_COMMENT = lazy_re.compile(r'<!--\s*message-break\s*-->',
-+ re.DOTALL)
-+
-+# Matches a comment which is used to prevent block tags from splitting a message
-+_MESSAGE_NO_BREAK_COMMENT = re.compile(r'<!--\s*message-no-break\s*-->',
-+ re.DOTALL)
-+
-+
-+_DEBUG = 0
-+def _DebugPrint(text):
-+ if _DEBUG:
-+ print(text.encode('utf-8'))
-+
-+
-+class HtmlChunks(object):
-+ '''A parser that knows how to break an HTML-like document into a list of
-+ chunks, where each chunk is either translateable or non-translateable.
-+ The chunks are unmodified sections of the original document, so concatenating
-+ the text of all chunks would result in the original document.'''
-+
-+ def InTranslateable(self):
-+ return self.last_translateable != -1
-+
-+ def Rest(self):
-+ return self.text_[self.current:]
-+
-+ def StartTranslateable(self):
-+ assert not self.InTranslateable()
-+ if self.current != 0:
-+ # Append a nontranslateable chunk
-+ chunk_text = self.text_[self.chunk_start : self.last_nontranslateable + 1]
-+ # Needed in the case where document starts with a translateable.
-+ if len(chunk_text) > 0:
-+ self.AddChunk(False, chunk_text)
-+ self.chunk_start = self.last_nontranslateable + 1
-+ self.last_translateable = self.current
-+ self.last_nontranslateable = -1
-+
-+ def EndTranslateable(self):
-+ assert self.InTranslateable()
-+ # Append a translateable chunk
-+ self.AddChunk(True,
-+ self.text_[self.chunk_start : self.last_translateable + 1])
-+ self.chunk_start = self.last_translateable + 1
-+ self.last_translateable = -1
-+ self.last_nontranslateable = self.current
-+
-+ def AdvancePast(self, match):
-+ self.current += match.end()
-+
-+ def AddChunk(self, translateable, text):
-+ '''Adds a chunk to self, removing linebreaks and duplicate whitespace
-+ if appropriate.
-+ '''
-+ m = _DESCRIPTION_COMMENT.search(text)
-+ if m:
-+ self.last_description = m.group('description')
-+ # Remove the description from the output text
-+ text = _DESCRIPTION_COMMENT.sub('', text)
-+
-+ m = _MESSAGE_BREAK_COMMENT.search(text)
-+ if m:
-+ # Remove the coment from the output text. It should already effectively
-+ # break apart messages.
-+ text = _MESSAGE_BREAK_COMMENT.sub('', text)
-+
-+ if translateable and not self.last_element_ in _PREFORMATTED_TAGS:
-+ if self.fold_whitespace_:
-+ # Fold whitespace sequences if appropriate. This is optional because it
-+ # alters the output strings.
-+ text = _FOLD_WHITESPACE.sub(' ', text)
-+ else:
-+ text = text.replace('\n', ' ')
-+ text = text.replace('\r', ' ')
-+ # This whitespace folding doesn't work in all cases, thus the
-+ # fold_whitespace flag to support backwards compatibility.
-+ text = text.replace(' ', ' ')
-+ text = text.replace(' ', ' ')
-+
-+ if translateable:
-+ description = self.last_description
-+ self.last_description = ''
-+ else:
-+ description = ''
-+
-+ if text != '':
-+ self.chunks_.append((translateable, text, description))
-+
-+ def Parse(self, text, fold_whitespace):
-+ '''Parses self.text_ into an intermediate format stored in self.chunks_
-+ which is translateable and nontranslateable chunks. Also returns
-+ self.chunks_
-+
-+ Args:
-+ text: The HTML for parsing.
-+ fold_whitespace: Whether whitespace sequences should be folded into a
-+ single space.
-+
-+ Return:
-+ [chunk1, chunk2, chunk3, ...] (instances of class Chunk)
-+ '''
-+ #
-+ # Chunker state
-+ #
-+
-+ self.text_ = text
-+ self.fold_whitespace_ = fold_whitespace
-+
-+ # A list of tuples (is_translateable, text) which represents the document
-+ # after chunking.
-+ self.chunks_ = []
-+
-+ # Start index of the last chunk, whether translateable or not
-+ self.chunk_start = 0
-+
-+ # Index of the last for-sure translateable character if we are parsing
-+ # a translateable chunk, -1 to indicate we are not in a translateable chunk.
-+ # This is needed so that we don't include trailing whitespace in the
-+ # translateable chunk (whitespace is neutral).
-+ self.last_translateable = -1
-+
-+ # Index of the last for-sure nontranslateable character if we are parsing
-+ # a nontranslateable chunk, -1 if we are not in a nontranslateable chunk.
-+ # This is needed to make sure we can group e.g. "<b>Hello</b> there"
-+ # together instead of just "Hello</b> there" which would be much worse
-+ # for translation.
-+ self.last_nontranslateable = -1
-+
-+ # Index of the character we're currently looking at.
-+ self.current = 0
-+
-+ # The name of the last block element parsed.
-+ self.last_element_ = ''
-+
-+ # The last explicit description we found.
-+ self.last_description = ''
-+
-+ # Whether no-break was the last chunk seen
-+ self.last_nobreak = False
-+
-+ while self.current < len(self.text_):
-+ _DebugPrint('REST: %s' % self.text_[self.current:self.current+60])
-+
-+ m = _MESSAGE_NO_BREAK_COMMENT.match(self.Rest())
-+ if m:
-+ self.AdvancePast(m)
-+ self.last_nobreak = True
-+ continue
-+
-+ # Try to match whitespace
-+ m = _WHITESPACE.match(self.Rest())
-+ if m:
-+ # Whitespace is neutral, it just advances 'current' and does not switch
-+ # between translateable/nontranslateable. If we are in a
-+ # nontranslateable section that extends to the current point, we extend
-+ # it to include the whitespace. If we are in a translateable section,
-+ # we do not extend it until we find
-+ # more translateable parts, because we never want a translateable chunk
-+ # to end with whitespace.
-+ if (not self.InTranslateable() and
-+ self.last_nontranslateable == self.current - 1):
-+ self.last_nontranslateable = self.current + m.end() - 1
-+ self.AdvancePast(m)
-+ continue
-+
-+ # Then we try to match nontranslateables
-+ m = _NONTRANSLATEABLES.match(self.Rest())
-+ if m:
-+ if self.InTranslateable():
-+ self.EndTranslateable()
-+ self.last_nontranslateable = self.current + m.end() - 1
-+ self.AdvancePast(m)
-+ continue
-+
-+ # Now match all other HTML element tags (opening, closing, or empty, we
-+ # don't care).
-+ m = _ELEMENT.match(self.Rest())
-+ if m:
-+ element_name = m.group('element').lower()
-+ if element_name in _BLOCK_TAGS:
-+ self.last_element_ = element_name
-+ if self.InTranslateable():
-+ if self.last_nobreak:
-+ self.last_nobreak = False
-+ else:
-+ self.EndTranslateable()
-+
-+ # Check for "special" elements, i.e. ones that have a translateable
-+ # attribute, and handle them correctly. Note that all of the
-+ # "special" elements are block tags, so no need to check for this
-+ # if the tag is not a block tag.
-+ sm = _SPECIAL_ELEMENT.match(self.Rest())
-+ if sm:
-+ # Get the appropriate group name
-+ for group in sm.groupdict():
-+ if sm.groupdict()[group]:
-+ break
-+
-+ # First make a nontranslateable chunk up to and including the
-+ # quote before the translateable attribute value
-+ self.AddChunk(False, self.text_[
-+ self.chunk_start : self.current + sm.start(group)])
-+ # Then a translateable for the translateable bit
-+ self.AddChunk(True, self.Rest()[sm.start(group) : sm.end(group)])
-+ # Finally correct the data invariant for the parser
-+ self.chunk_start = self.current + sm.end(group)
-+
-+ self.last_nontranslateable = self.current + m.end() - 1
-+ elif self.InTranslateable():
-+ # We're in a translateable and the tag is an inline tag, so we
-+ # need to include it in the translateable.
-+ self.last_translateable = self.current + m.end() - 1
-+ self.AdvancePast(m)
-+ continue
-+
-+ # Anything else we find must be translateable, so we advance one character
-+ # at a time until one of the above matches.
-+ if not self.InTranslateable():
-+ self.StartTranslateable()
-+ else:
-+ self.last_translateable = self.current
-+ self.current += 1
-+
-+ # Close the final chunk
-+ if self.InTranslateable():
-+ self.AddChunk(True, self.text_[self.chunk_start : ])
-+ else:
-+ self.AddChunk(False, self.text_[self.chunk_start : ])
-+
-+ return self.chunks_
-+
-+
-+def HtmlToMessage(html, include_block_tags=False, description=''):
-+ '''Takes a bit of HTML, which must contain only "inline" HTML elements,
-+ and changes it into a tclib.Message. This involves escaping any entities and
-+ replacing any HTML code with placeholders.
-+
-+ If include_block_tags is true, no error will be given if block tags (e.g.
-+ <p> or <br>) are included in the HTML.
-+
-+ Args:
-+ html: 'Hello <b>[USERNAME]</b>, how&nbsp;<i>are</i> you?'
-+ include_block_tags: False
-+
-+ Return:
-+ tclib.Message('Hello START_BOLD1USERNAMEEND_BOLD, '
-+ 'howNBSPSTART_ITALICareEND_ITALIC you?',
-+ [ Placeholder('START_BOLD', '<b>', ''),
-+ Placeholder('USERNAME', '[USERNAME]', ''),
-+ Placeholder('END_BOLD', '</b>', ''),
-+ Placeholder('START_ITALIC', '<i>', ''),
-+ Placeholder('END_ITALIC', '</i>', ''), ])
-+ '''
-+ # Approach is:
-+ # - first placeholderize, finding <elements>, [REPLACEABLES] and &nbsp;
-+ # - then escape all character entities in text in-between placeholders
-+
-+ parts = [] # List of strings (for text chunks) and tuples (ID, original)
-+ # for placeholders
-+
-+ count_names = {} # Map of base names to number of times used
-+ end_names = {} # Map of base names to stack of end tags (for correct nesting)
-+
-+ def MakeNameClosure(base, type = ''):
-+ '''Returns a closure that can be called once all names have been allocated
-+ to return the final name of the placeholder. This allows us to minimally
-+ number placeholders for non-overlap.
-+
-+ Also ensures that END_XXX_Y placeholders have the same Y as the
-+ corresponding BEGIN_XXX_Y placeholder when we have nested tags of the same
-+ type.
-+
-+ Args:
-+ base: 'phname'
-+ type: '' | 'begin' | 'end'
-+
-+ Return:
-+ Closure()
-+ '''
-+ name = base.upper()
-+ if type != '':
-+ name = ('%s_%s' % (type, base)).upper()
-+
-+ count_names.setdefault(name, 0)
-+ count_names[name] += 1
-+
-+ def MakeFinalName(name_ = name, index = count_names[name] - 1):
-+ if type.lower() == 'end' and end_names.get(base):
-+ return end_names[base].pop(-1) # For correct nesting
-+ if count_names[name_] != 1:
-+ name_ = '%s_%s' % (name_, _SUFFIXES[index])
-+ # We need to use a stack to ensure that the end-tag suffixes match
-+ # the begin-tag suffixes. Only needed when more than one tag of the
-+ # same type.
-+ if type == 'begin':
-+ end_name = ('END_%s_%s' % (base, _SUFFIXES[index])).upper()
-+ if base in end_names:
-+ end_names[base].append(end_name)
-+ else:
-+ end_names[base] = [end_name]
-+
-+ return name_
-+
-+ return MakeFinalName
-+
-+ current = 0
-+ last_nobreak = False
-+
-+ while current < len(html):
-+ m = _MESSAGE_NO_BREAK_COMMENT.match(html[current:])
-+ if m:
-+ last_nobreak = True
-+ current += m.end()
-+ continue
-+
-+ m = _NBSP.match(html[current:])
-+ if m:
-+ parts.append((MakeNameClosure('SPACE'), m.group()))
-+ current += m.end()
-+ continue
-+
-+ m = _REPLACEABLE.match(html[current:])
-+ if m:
-+ # Replaceables allow - but placeholders don't, so replace - with _
-+ ph_name = MakeNameClosure('X_%s_X' % m.group('name').replace('-', '_'))
-+ parts.append((ph_name, m.group()))
-+ current += m.end()
-+ continue
-+
-+ m = _SPECIAL_ELEMENT.match(html[current:])
-+ if m:
-+ if not include_block_tags:
-+ if last_nobreak:
-+ last_nobreak = False
-+ else:
-+ raise exception.BlockTagInTranslateableChunk(html)
-+ element_name = 'block' # for simplification
-+ # Get the appropriate group name
-+ for group in m.groupdict():
-+ if m.groupdict()[group]:
-+ break
-+ parts.append((MakeNameClosure(element_name, 'begin'),
-+ html[current : current + m.start(group)]))
-+ parts.append(m.group(group))
-+ parts.append((MakeNameClosure(element_name, 'end'),
-+ html[current + m.end(group) : current + m.end()]))
-+ current += m.end()
-+ continue
-+
-+ m = _ELEMENT.match(html[current:])
-+ if m:
-+ element_name = m.group('element').lower()
-+ if not include_block_tags and not element_name in _INLINE_TAGS:
-+ if last_nobreak:
-+ last_nobreak = False
-+ else:
-+ raise exception.BlockTagInTranslateableChunk(html[current:])
-+ if element_name in _HTML_PLACEHOLDER_NAMES: # use meaningful names
-+ element_name = _HTML_PLACEHOLDER_NAMES[element_name]
-+
-+ # Make a name for the placeholder
-+ type = ''
-+ if not m.group('empty'):
-+ if m.group('closing'):
-+ type = 'end'
-+ else:
-+ type = 'begin'
-+ parts.append((MakeNameClosure(element_name, type), m.group()))
-+ current += m.end()
-+ continue
-+
-+ if len(parts) and isinstance(parts[-1], six.string_types):
-+ parts[-1] += html[current]
-+ else:
-+ parts.append(html[current])
-+ current += 1
-+
-+ msg_text = ''
-+ placeholders = []
-+ for part in parts:
-+ if isinstance(part, tuple):
-+ final_name = part[0]()
-+ original = part[1]
-+ msg_text += final_name
-+ placeholders.append(tclib.Placeholder(final_name, original, '(HTML code)'))
-+ else:
-+ msg_text += part
-+
-+ msg = tclib.Message(text=msg_text, placeholders=placeholders,
-+ description=description)
-+ content = msg.GetContent()
-+ for ix in range(len(content)):
-+ if isinstance(content[ix], six.string_types):
-+ content[ix] = util.UnescapeHtml(content[ix], replace_nbsp=False)
-+
-+ return msg
-+
-+
-+class TrHtml(interface.GathererBase):
-+ '''Represents a document or message in the template format used by
-+ Total Recall for HTML documents.'''
-+
-+ def __init__(self, *args, **kwargs):
-+ super(TrHtml, self).__init__(*args, **kwargs)
-+ self.have_parsed_ = False
-+ self.skeleton_ = [] # list of strings and MessageClique objects
-+ self.fold_whitespace_ = False
-+
-+ def SetAttributes(self, attrs):
-+ '''Sets node attributes used by the gatherer.
-+
-+ This checks the fold_whitespace attribute.
-+
-+ Args:
-+ attrs: The mapping of node attributes.
-+ '''
-+ self.fold_whitespace_ = ('fold_whitespace' in attrs and
-+ attrs['fold_whitespace'] == 'true')
-+
-+ def GetText(self):
-+ '''Returns the original text of the HTML document'''
-+ return self.text_
-+
-+ def GetTextualIds(self):
-+ return [self.extkey]
-+
-+ def GetCliques(self):
-+ '''Returns the message cliques for each translateable message in the
-+ document.'''
-+ return [x for x in self.skeleton_ if isinstance(x, clique.MessageClique)]
-+
-+ def Translate(self, lang, pseudo_if_not_available=True,
-+ skeleton_gatherer=None, fallback_to_english=False):
-+ '''Returns this document with translateable messages filled with
-+ the translation for language 'lang'.
-+
-+ Args:
-+ lang: 'en'
-+ pseudo_if_not_available: True
-+
-+ Return:
-+ 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND
-+
-+ Raises:
-+ grit.exception.NotReady() if used before Parse() has been successfully
-+ called.
-+ grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' is false
-+ and there is no translation for the requested language.
-+ '''
-+ if len(self.skeleton_) == 0:
-+ raise exception.NotReady()
-+
-+ # TODO(joi) Implement support for skeleton gatherers here.
-+
-+ out = []
-+ for item in self.skeleton_:
-+ if isinstance(item, six.string_types):
-+ out.append(item)
-+ else:
-+ msg = item.MessageForLanguage(lang,
-+ pseudo_if_not_available,
-+ fallback_to_english)
-+ for content in msg.GetContent():
-+ if isinstance(content, tclib.Placeholder):
-+ out.append(content.GetOriginal())
-+ else:
-+ # We escape " characters to increase the chance that attributes
-+ # will be properly escaped.
-+ out.append(util.EscapeHtml(content, True))
-+
-+ return ''.join(out)
-+
-+ def Parse(self):
-+ if self.have_parsed_:
-+ return
-+ self.have_parsed_ = True
-+
-+ text = self._LoadInputFile()
-+
-+ # Ignore the BOM character if the document starts with one.
-+ if text.startswith(u'\ufeff'):
-+ text = text[1:]
-+
-+ self.text_ = text
-+
-+ # Parsing is done in two phases: First, we break the document into
-+ # translateable and nontranslateable chunks. Second, we run through each
-+ # translateable chunk and insert placeholders for any HTML elements,
-+ # unescape escaped characters, etc.
-+
-+ # First handle the silly little [!]-prefixed header because it's not
-+ # handled by our HTML parsers.
-+ m = _SILLY_HEADER.match(text)
-+ if m:
-+ self.skeleton_.append(text[:m.start('title')])
-+ self.skeleton_.append(self.uberclique.MakeClique(
-+ tclib.Message(text=text[m.start('title'):m.end('title')])))
-+ self.skeleton_.append(text[m.end('title') : m.end()])
-+ text = text[m.end():]
-+
-+ chunks = HtmlChunks().Parse(text, self.fold_whitespace_)
-+
-+ for chunk in chunks:
-+ if chunk[0]: # Chunk is translateable
-+ self.skeleton_.append(self.uberclique.MakeClique(
-+ HtmlToMessage(chunk[1], description=chunk[2])))
-+ else:
-+ self.skeleton_.append(chunk[1])
-+
-+ # Go through the skeleton and change any messages that consist solely of
-+ # placeholders and whitespace into nontranslateable strings.
-+ for ix in range(len(self.skeleton_)):
-+ got_text = False
-+ if isinstance(self.skeleton_[ix], clique.MessageClique):
-+ msg = self.skeleton_[ix].GetMessage()
-+ for item in msg.GetContent():
-+ if (isinstance(item, six.string_types)
-+ and _NON_WHITESPACE.search(item) and item != '&nbsp;'):
-+ got_text = True
-+ break
-+ if not got_text:
-+ self.skeleton_[ix] = msg.GetRealContent()
-+
-+ def SubstituteMessages(self, substituter):
-+ '''Applies substitutions to all messages in the tree.
-+
-+ Goes through the skeleton and finds all MessageCliques.
-+
-+ Args:
-+ substituter: a grit.util.Substituter object.
-+ '''
-+ new_skel = []
-+ for chunk in self.skeleton_:
-+ if isinstance(chunk, clique.MessageClique):
-+ old_message = chunk.GetMessage()
-+ new_message = substituter.SubstituteMessage(old_message)
-+ if new_message is not old_message:
-+ new_skel.append(self.uberclique.MakeClique(new_message))
-+ continue
-+ new_skel.append(chunk)
-+ self.skeleton_ = new_skel
-diff --git a/tools/grit/grit/gather/tr_html_unittest.py b/tools/grit/grit/gather/tr_html_unittest.py
-new file mode 100644
-index 0000000000..1194853d9a
---- /dev/null
-+++ b/tools/grit/grit/gather/tr_html_unittest.py
-@@ -0,0 +1,524 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.gather.tr_html'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+import six
-+from six import StringIO
-+
-+from grit.gather import tr_html
-+from grit import clique
-+from grit import util
-+
-+
-+class ParserUnittest(unittest.TestCase):
-+ def testChunkingWithoutFoldWhitespace(self):
-+ self.VerifyChunking(False)
-+
-+ def testChunkingWithFoldWhitespace(self):
-+ self.VerifyChunking(True)
-+
-+ def VerifyChunking(self, fold_whitespace):
-+ """Use a single function to run all chunking testing.
-+
-+ This makes it easier to run chunking with fold_whitespace both on and off,
-+ to make sure the outputs are the same.
-+
-+ Args:
-+ fold_whitespace: Whether whitespace sequences should be folded into a
-+ single space.
-+ """
-+ self.VerifyChunkingBasic(fold_whitespace)
-+ self.VerifyChunkingDescriptions(fold_whitespace)
-+ self.VerifyChunkingReplaceables(fold_whitespace)
-+ self.VerifyChunkingLineBreaks(fold_whitespace)
-+ self.VerifyChunkingMessageBreak(fold_whitespace)
-+ self.VerifyChunkingMessageNoBreak(fold_whitespace)
-+
-+ def VerifyChunkingBasic(self, fold_whitespace):
-+ p = tr_html.HtmlChunks()
-+ chunks = p.Parse('<p>Hello <b>dear</b> how <i>are</i>you?<p>Fine!',
-+ fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (False, '<p>', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
-+ (False, '<p>', ''), (True, 'Fine!', '')])
-+
-+ chunks = p.Parse('<p> Hello <b>dear</b> how <i>are</i>you? <p>Fine!',
-+ fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (False, '<p> ', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
-+ (False, ' <p>', ''), (True, 'Fine!', '')])
-+
-+ chunks = p.Parse('<p> Hello <b>dear how <i>are you? <p> Fine!',
-+ fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (False, '<p> ', ''), (True, 'Hello <b>dear how <i>are you?', ''),
-+ (False, ' <p> ', ''), (True, 'Fine!', '')])
-+
-+ # Ensure translateable sections that start with inline tags contain
-+ # the starting inline tag.
-+ chunks = p.Parse('<b>Hello!</b> how are you?<p><i>I am fine.</i>',
-+ fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (True, '<b>Hello!</b> how are you?', ''), (False, '<p>', ''),
-+ (True, '<i>I am fine.</i>', '')])
-+
-+ # Ensure translateable sections that end with inline tags contain
-+ # the ending inline tag.
-+ chunks = p.Parse("Hello! How are <b>you?</b><p><i>I'm fine!</i>",
-+ fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (True, 'Hello! How are <b>you?</b>', ''), (False, '<p>', ''),
-+ (True, "<i>I'm fine!</i>", '')])
-+
-+ def VerifyChunkingDescriptions(self, fold_whitespace):
-+ p = tr_html.HtmlChunks()
-+ # Check capitals and explicit descriptions
-+ chunks = p.Parse('<!-- desc=bingo! --><B>Hello!</B> how are you?<P>'
-+ '<I>I am fine.</I>', fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
-+ (True, '<I>I am fine.</I>', '')])
-+ chunks = p.Parse('<B><!-- desc=bingo! -->Hello!</B> how are you?<P>'
-+ '<I>I am fine.</I>', fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
-+ (True, '<I>I am fine.</I>', '')])
-+ # Linebreaks get handled by the tclib message.
-+ chunks = p.Parse('<B>Hello!</B> <!-- desc=bi\nngo\n! -->how are you?<P>'
-+ '<I>I am fine.</I>', fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (True, '<B>Hello!</B> how are you?', 'bi\nngo\n!'), (False, '<P>', ''),
-+ (True, '<I>I am fine.</I>', '')])
-+
-+ # In this case, because the explicit description appears after the first
-+ # translateable, it will actually apply to the second translateable.
-+ chunks = p.Parse('<B>Hello!</B> how are you?<!-- desc=bingo! --><P>'
-+ '<I>I am fine.</I>', fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (True, '<B>Hello!</B> how are you?', ''), (False, '<P>', ''),
-+ (True, '<I>I am fine.</I>', 'bingo!')])
-+
-+ def VerifyChunkingReplaceables(self, fold_whitespace):
-+ # Check that replaceables within block tags (where attributes would go) are
-+ # handled correctly.
-+ p = tr_html.HtmlChunks()
-+ chunks = p.Parse('<b>Hello!</b> how are you?<p [BINGO] [$~BONGO~$]>'
-+ '<i>I am fine.</i>', fold_whitespace)
-+ self.failUnlessEqual(chunks, [
-+ (True, '<b>Hello!</b> how are you?', ''),
-+ (False, '<p [BINGO] [$~BONGO~$]>', ''),
-+ (True, '<i>I am fine.</i>', '')])
-+
-+ def VerifyChunkingLineBreaks(self, fold_whitespace):
-+ # Check that the contents of preformatted tags preserve line breaks.
-+ p = tr_html.HtmlChunks()
-+ chunks = p.Parse('<textarea>Hello\nthere\nhow\nare\nyou?</textarea>',
-+ fold_whitespace)
-+ self.failUnlessEqual(chunks, [(False, '<textarea>', ''),
-+ (True, 'Hello\nthere\nhow\nare\nyou?', ''), (False, '</textarea>', '')])
-+
-+ # ...and that other tags' line breaks are converted to spaces
-+ chunks = p.Parse('<p>Hello\nthere\nhow\nare\nyou?</p>', fold_whitespace)
-+ self.failUnlessEqual(chunks, [(False, '<p>', ''),
-+ (True, 'Hello there how are you?', ''), (False, '</p>', '')])
-+
-+ def VerifyChunkingMessageBreak(self, fold_whitespace):
-+ p = tr_html.HtmlChunks()
-+ # Make sure that message-break comments work properly.
-+ chunks = p.Parse('Break<!-- message-break --> apart '
-+ '<!--message-break-->messages', fold_whitespace)
-+ self.failUnlessEqual(chunks, [(True, 'Break', ''),
-+ (False, ' ', ''),
-+ (True, 'apart', ''),
-+ (False, ' ', ''),
-+ (True, 'messages', '')])
-+
-+ # Make sure message-break comments work in an inline tag.
-+ chunks = p.Parse('<a href=\'google.com\'><!-- message-break -->Google'
-+ '<!--message-break--></a>', fold_whitespace)
-+ self.failUnlessEqual(chunks, [(False, '<a href=\'google.com\'>', ''),
-+ (True, 'Google', ''),
-+ (False, '</a>', '')])
-+
-+ def VerifyChunkingMessageNoBreak(self, fold_whitespace):
-+ p = tr_html.HtmlChunks()
-+ # Make sure that message-no-break comments work properly.
-+ chunks = p.Parse('Please <!-- message-no-break --> <br />don\'t break',
-+ fold_whitespace)
-+ self.failUnlessEqual(chunks, [(True, 'Please <!-- message-no-break --> '
-+ '<br />don\'t break', '')])
-+
-+ chunks = p.Parse('Please <br /> break. <!-- message-no-break --> <br /> '
-+ 'But not this time.', fold_whitespace)
-+ self.failUnlessEqual(chunks, [(True, 'Please', ''),
-+ (False, ' <br /> ', ''),
-+ (True, 'break. <!-- message-no-break --> '
-+ '<br /> But not this time.', '')])
-+
-+ def testTranslateableAttributes(self):
-+ p = tr_html.HtmlChunks()
-+
-+ # Check that the translateable attributes in <img>, <submit>, <button> and
-+ # <text> elements buttons are handled correctly.
-+ chunks = p.Parse('<img src=bingo.jpg alt="hello there">'
-+ '<input type=submit value="hello">'
-+ '<input type="button" value="hello">'
-+ '<input type=\'text\' value=\'Howdie\'>', False)
-+ self.failUnlessEqual(chunks, [
-+ (False, '<img src=bingo.jpg alt="', ''), (True, 'hello there', ''),
-+ (False, '"><input type=submit value="', ''), (True, 'hello', ''),
-+ (False, '"><input type="button" value="', ''), (True, 'hello', ''),
-+ (False, '"><input type=\'text\' value=\'', ''), (True, 'Howdie', ''),
-+ (False, '\'>', '')])
-+
-+
-+ def testTranslateableHtmlToMessage(self):
-+ msg = tr_html.HtmlToMessage(
-+ 'Hello <b>[USERNAME]</b>, &lt;how&gt;&nbsp;<i>are</i> you?')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres ==
-+ 'Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, '
-+ '<how>&nbsp;BEGIN_ITALICareEND_ITALIC you?')
-+
-+ msg = tr_html.HtmlToMessage('<b>Hello</b><I>Hello</I><b>Hello</b>')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres ==
-+ 'BEGIN_BOLD_1HelloEND_BOLD_1BEGIN_ITALICHelloEND_ITALIC'
-+ 'BEGIN_BOLD_2HelloEND_BOLD_2')
-+
-+ # Check that nesting (of the <font> tags) is handled correctly - i.e. that
-+ # the closing placeholder numbers match the opening placeholders.
-+ msg = tr_html.HtmlToMessage(
-+ '''<font size=-1><font color=#FF0000>Update!</font> '''
-+ '''<a href='http://desktop.google.com/whatsnew.html?hl=[$~LANG~$]'>'''
-+ '''New Features</a>: Now search PDFs, MP3s, Firefox web history, and '''
-+ '''more</font>''')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres ==
-+ 'BEGIN_FONT_1BEGIN_FONT_2Update!END_FONT_2 BEGIN_LINK'
-+ 'New FeaturesEND_LINK: Now search PDFs, MP3s, Firefox '
-+ 'web history, and moreEND_FONT_1')
-+
-+ msg = tr_html.HtmlToMessage('''<a href='[$~URL~$]'><b>[NUM][CAT]</b></a>''')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres == 'BEGIN_LINKBEGIN_BOLDX_NUM_XX_CAT_XEND_BOLDEND_LINK')
-+
-+ msg = tr_html.HtmlToMessage(
-+ '''<font size=-1><a class=q onClick='return window.qs?qs(this):1' '''
-+ '''href='http://[WEBSERVER][SEARCH_URI]'>Desktop</a></font>&nbsp;&nbsp;'''
-+ '''&nbsp;&nbsp;''')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres ==
-+ '''BEGIN_FONTBEGIN_LINKDesktopEND_LINKEND_FONTSPACE''')
-+
-+ msg = tr_html.HtmlToMessage(
-+ '''<br><br><center><font size=-2>&copy;2005 Google </font></center>''', 1)
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres ==
-+ u'BEGIN_BREAK_1BEGIN_BREAK_2BEGIN_CENTERBEGIN_FONT\xa92005'
-+ u' Google END_FONTEND_CENTER')
-+
-+ msg = tr_html.HtmlToMessage(
-+ '''&nbsp;-&nbsp;<a class=c href=[$~CACHE~$]>Cached</a>''')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres ==
-+ '&nbsp;-&nbsp;BEGIN_LINKCachedEND_LINK')
-+
-+ # Check that upper-case tags are handled correctly.
-+ msg = tr_html.HtmlToMessage(
-+ '''You can read the <A HREF='http://desktop.google.com/privacypolicy.'''
-+ '''html?hl=[LANG_CODE]'>Privacy Policy</A> and <A HREF='http://desktop'''
-+ '''.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres ==
-+ 'You can read the BEGIN_LINK_1Privacy PolicyEND_LINK_1 and '
-+ 'BEGIN_LINK_2Privacy FAQEND_LINK_2 online.')
-+
-+ # Check that tags with linebreaks immediately preceding them are handled
-+ # correctly.
-+ msg = tr_html.HtmlToMessage(
-+ '''You can read the
-+<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
-+and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
-+ pres = msg.GetPresentableContent()
-+ self.failUnless(pres == '''You can read the
-+BEGIN_LINK_1Privacy PolicyEND_LINK_1
-+and BEGIN_LINK_2Privacy FAQEND_LINK_2 online.''')
-+
-+ # Check that message-no-break comments are handled correctly.
-+ msg = tr_html.HtmlToMessage('''Please <!-- message-no-break --><br /> don't break''')
-+ pres = msg.GetPresentableContent()
-+ self.failUnlessEqual(pres, '''Please BREAK don't break''')
-+
-+class TrHtmlUnittest(unittest.TestCase):
-+ def testSetAttributes(self):
-+ html = tr_html.TrHtml(StringIO(''))
-+ self.failUnlessEqual(html.fold_whitespace_, False)
-+ html.SetAttributes({})
-+ self.failUnlessEqual(html.fold_whitespace_, False)
-+ html.SetAttributes({'fold_whitespace': 'false'})
-+ self.failUnlessEqual(html.fold_whitespace_, False)
-+ html.SetAttributes({'fold_whitespace': 'true'})
-+ self.failUnlessEqual(html.fold_whitespace_, True)
-+
-+ def testFoldWhitespace(self):
-+ text = '<td> Test Message </td>'
-+
-+ html = tr_html.TrHtml(StringIO(text))
-+ html.Parse()
-+ self.failUnlessEqual(html.skeleton_[1].GetMessage().GetPresentableContent(),
-+ 'Test Message')
-+
-+ html = tr_html.TrHtml(StringIO(text))
-+ html.fold_whitespace_ = True
-+ html.Parse()
-+ self.failUnlessEqual(html.skeleton_[1].GetMessage().GetPresentableContent(),
-+ 'Test Message')
-+
-+ def testTable(self):
-+ html = tr_html.TrHtml(StringIO('''<table class="shaded-header"><tr>
-+<td class="header-element b expand">Preferences</td>
-+<td class="header-element s">
-+<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
-+</td>
-+</tr></table>'''))
-+ html.Parse()
-+ self.failUnless(html.skeleton_[3].GetMessage().GetPresentableContent() ==
-+ 'BEGIN_LINKPreferences&nbsp;HelpEND_LINK')
-+
-+ def testSubmitAttribute(self):
-+ html = tr_html.TrHtml(StringIO('''</td>
-+<td class="header-element"><input type=submit value="Save Preferences"
-+name=submit2></td>
-+</tr></table>'''))
-+ html.Parse()
-+ self.failUnless(html.skeleton_[1].GetMessage().GetPresentableContent() ==
-+ 'Save Preferences')
-+
-+ def testWhitespaceAfterInlineTag(self):
-+ '''Test that even if there is whitespace after an inline tag at the start
-+ of a translateable section the inline tag will be included.
-+ '''
-+ html = tr_html.TrHtml(
-+ StringIO('''<label for=DISPLAYNONE><font size=-1> Hello</font>'''))
-+ html.Parse()
-+ self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
-+ '<font size=-1> Hello</font>')
-+
-+ def testSillyHeader(self):
-+ html = tr_html.TrHtml(StringIO('''[!]
-+title\tHello
-+bingo
-+bongo
-+bla
-+
-+<p>Other stuff</p>'''))
-+ html.Parse()
-+ content = html.skeleton_[1].GetMessage().GetRealContent()
-+ self.failUnless(content == 'Hello')
-+ self.failUnless(html.skeleton_[-1] == '</p>')
-+ # Right after the translateable the nontranslateable should start with
-+ # a linebreak (this catches a bug we had).
-+ self.failUnless(html.skeleton_[2][0] == '\n')
-+
-+
-+ def testExplicitDescriptions(self):
-+ html = tr_html.TrHtml(
-+ StringIO('Hello [USER]<br/><!-- desc=explicit -->'
-+ '<input type="button">Go!</input>'))
-+ html.Parse()
-+ msg = html.GetCliques()[1].GetMessage()
-+ self.failUnlessEqual(msg.GetDescription(), 'explicit')
-+ self.failUnlessEqual(msg.GetRealContent(), 'Go!')
-+
-+ html = tr_html.TrHtml(
-+ StringIO('Hello [USER]<br/><!-- desc=explicit\nmultiline -->'
-+ '<input type="button">Go!</input>'))
-+ html.Parse()
-+ msg = html.GetCliques()[1].GetMessage()
-+ self.failUnlessEqual(msg.GetDescription(), 'explicit multiline')
-+ self.failUnlessEqual(msg.GetRealContent(), 'Go!')
-+
-+
-+ def testRegressionInToolbarAbout(self):
-+ html = tr_html.TrHtml(util.PathFromRoot(r'grit/testdata/toolbar_about.html'))
-+ html.Parse()
-+ cliques = html.GetCliques()
-+ for cl in cliques:
-+ content = cl.GetMessage().GetRealContent()
-+ if content.count('De parvis grandis acervus erit'):
-+ self.failIf(content.count('$/translate'))
-+
-+
-+ def HtmlFromFileWithManualCheck(self, f):
-+ html = tr_html.TrHtml(f)
-+ html.Parse()
-+
-+ # For manual results inspection only...
-+ list = []
-+ for item in html.skeleton_:
-+ if isinstance(item, six.string_types):
-+ list.append(item)
-+ else:
-+ list.append(item.GetMessage().GetPresentableContent())
-+
-+ return html
-+
-+
-+ def testPrivacyHtml(self):
-+ html = self.HtmlFromFileWithManualCheck(
-+ util.PathFromRoot(r'grit/testdata/privacy.html'))
-+
-+ self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
-+ 'Privacy and Google Desktop Search')
-+ self.failUnless(html.skeleton_[3].startswith('<'))
-+ self.failUnless(len(html.skeleton_) > 10)
-+
-+
-+ def testPreferencesHtml(self):
-+ html = self.HtmlFromFileWithManualCheck(
-+ util.PathFromRoot(r'grit/testdata/preferences.html'))
-+
-+ # Verify that we don't get '[STATUS-MESSAGE]' as the original content of
-+ # one of the MessageClique objects (it would be a placeholder-only message
-+ # and we're supposed to have stripped those).
-+
-+ for item in [x for x in html.skeleton_
-+ if isinstance(x, clique.MessageClique)]:
-+ if (item.GetMessage().GetRealContent() == '[STATUS-MESSAGE]' or
-+ item.GetMessage().GetRealContent() == '[ADDIN-DO] [ADDIN-OPTIONS]'):
-+ self.fail()
-+
-+ self.failUnless(len(html.skeleton_) > 100)
-+
-+ def AssertNumberOfTranslateables(self, files, num):
-+ '''Fails if any of the files in files don't have exactly
-+ num translateable sections.
-+
-+ Args:
-+ files: ['file1', 'file2']
-+ num: 3
-+ '''
-+ for f in files:
-+ f = util.PathFromRoot(r'grit/testdata/%s' % f)
-+ html = self.HtmlFromFileWithManualCheck(f)
-+ self.failUnless(len(html.GetCliques()) == num)
-+
-+ def testFewTranslateables(self):
-+ self.AssertNumberOfTranslateables(['browser.html', 'email_thread.html',
-+ 'header.html', 'mini.html',
-+ 'oneclick.html', 'script.html',
-+ 'time_related.html', 'versions.html'], 0)
-+ self.AssertNumberOfTranslateables(['footer.html', 'hover.html'], 1)
-+
-+ def testOtherHtmlFilesForManualInspection(self):
-+ files = [
-+ 'about.html', 'bad_browser.html', 'cache_prefix.html',
-+ 'cache_prefix_file.html', 'chat_result.html', 'del_footer.html',
-+ 'del_header.html', 'deleted.html', 'details.html', 'email_result.html',
-+ 'error.html', 'explicit_web.html', 'footer.html',
-+ 'homepage.html', 'indexing_speed.html',
-+ 'install_prefs.html', 'install_prefs2.html',
-+ 'oem_enable.html', 'oem_non_admin.html', 'onebox.html',
-+ 'password.html', 'quit_apps.html', 'recrawl.html',
-+ 'searchbox.html', 'sidebar_h.html', 'sidebar_v.html', 'status.html',
-+ ]
-+ for f in files:
-+ self.HtmlFromFileWithManualCheck(
-+ util.PathFromRoot(r'grit/testdata/%s' % f))
-+
-+ def testTranslate(self):
-+ # Note that the English translation of documents that use character
-+ # literals (e.g. &copy;) will not be the same as the original document
-+ # because the character literal will be transformed into the Unicode
-+ # character itself. So for this test we choose some relatively complex
-+ # HTML without character entities (but with &nbsp; because that's handled
-+ # specially).
-+ html = tr_html.TrHtml(StringIO(''' <script>
-+ <!--
-+ function checkOffice() { var w = document.getElementById("h7");
-+ var e = document.getElementById("h8"); var o = document.getElementById("h10");
-+ if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
-+ // -->
-+ </script>
-+ <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
-+ <label for=h7> Word</label><br>
-+ <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
-+ <label for=h8> Excel</label><br>
-+ <input type=checkbox [CHECK-PPT] name=PPT id=h9>
-+ <label for=h9> PowerPoint</label><br>
-+ </span></td><td nowrap valign=top><span class="s">
-+ <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
-+ <label for=hpdf> PDF</label><br>
-+ <input type=checkbox [CHECK-TXT] name=TXT id=h6>
-+ <label for=h6> Text, media, and other files</label><br>
-+ </tr>&nbsp;&nbsp;
-+ <tr><td nowrap valign=top colspan=3><span class="s"><br />
-+ <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
-+ <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
-+ <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
-+ for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
-+ </table>'''))
-+ html.Parse()
-+ trans = html.Translate('en')
-+ if (html.GetText() != trans):
-+ self.fail()
-+
-+
-+ def testHtmlToMessageWithBlockTags(self):
-+ msg = tr_html.HtmlToMessage(
-+ 'Hello<p>Howdie<img alt="bingo" src="image.gif">', True)
-+ result = msg.GetPresentableContent()
-+ self.failUnless(
-+ result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
-+
-+ msg = tr_html.HtmlToMessage(
-+ 'Hello<p>Howdie<input type="button" value="bingo">', True)
-+ result = msg.GetPresentableContent()
-+ self.failUnless(
-+ result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
-+
-+
-+ def testHtmlToMessageRegressions(self):
-+ msg = tr_html.HtmlToMessage(' - ', True)
-+ result = msg.GetPresentableContent()
-+ self.failUnless(result == ' - ')
-+
-+
-+ def testEscapeUnescaped(self):
-+ text = '&copy;&nbsp; & &quot;&lt;hello&gt;&quot;'
-+ unescaped = util.UnescapeHtml(text)
-+ self.failUnless(unescaped == u'\u00a9\u00a0 & "<hello>"')
-+ escaped_unescaped = util.EscapeHtml(unescaped, True)
-+ self.failUnless(escaped_unescaped ==
-+ u'\u00a9\u00a0 &amp; &quot;&lt;hello&gt;&quot;')
-+
-+ def testRegressionCjkHtmlFile(self):
-+ # TODO(joi) Fix this problem where unquoted attributes that
-+ # have a value that is CJK characters causes the regular expression
-+ # match never to return. (culprit is the _ELEMENT regexp(
-+ if False:
-+ html = self.HtmlFromFileWithManualCheck(util.PathFromRoot(
-+ r'grit/testdata/ko_oem_enable_bug.html'))
-+ self.failUnless(True)
-+
-+ def testRegressionCpuHang(self):
-+ # If this regression occurs, the unit test will never return
-+ html = tr_html.TrHtml(StringIO(
-+ '''<input type=text size=12 id=advFileTypeEntry [~SHOW-FILETYPE-BOX~] value="[EXT]" name=ext>'''))
-+ html.Parse()
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/gather/txt.py b/tools/grit/grit/gather/txt.py
-new file mode 100644
-index 0000000000..e5c10abc28
---- /dev/null
-+++ b/tools/grit/grit/gather/txt.py
-@@ -0,0 +1,38 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Supports making amessage from a text file.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit.gather import interface
-+from grit import tclib
-+
-+
-+class TxtFile(interface.GathererBase):
-+ '''A text file gatherer. Very simple, all text from the file becomes a
-+ single clique.
-+ '''
-+
-+ def Parse(self):
-+ self.text_ = self._LoadInputFile()
-+ self.clique_ = self.uberclique.MakeClique(tclib.Message(text=self.text_))
-+
-+ def GetText(self):
-+ '''Returns the text of what is being gathered.'''
-+ return self.text_
-+
-+ def GetTextualIds(self):
-+ return [self.extkey]
-+
-+ def GetCliques(self):
-+ '''Returns the MessageClique objects for all translateable portions.'''
-+ return [self.clique_]
-+
-+ def Translate(self, lang, pseudo_if_not_available=True,
-+ skeleton_gatherer=None, fallback_to_english=False):
-+ return self.clique_.MessageForLanguage(lang,
-+ pseudo_if_not_available,
-+ fallback_to_english).GetRealContent()
-diff --git a/tools/grit/grit/gather/txt_unittest.py b/tools/grit/grit/gather/txt_unittest.py
-new file mode 100644
-index 0000000000..abb9ed98d7
---- /dev/null
-+++ b/tools/grit/grit/gather/txt_unittest.py
-@@ -0,0 +1,35 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for TxtFile gatherer'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit.gather import txt
-+
-+
-+class TxtUnittest(unittest.TestCase):
-+ def testGather(self):
-+ input = StringIO('Hello there\nHow are you?')
-+ gatherer = txt.TxtFile(input)
-+ gatherer.Parse()
-+ self.failUnless(gatherer.GetText() == input.getvalue())
-+ self.failUnless(len(gatherer.GetCliques()) == 1)
-+ self.failUnless(gatherer.GetCliques()[0].GetMessage().GetRealContent() ==
-+ input.getvalue())
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/grd_reader.py b/tools/grit/grit/grd_reader.py
-new file mode 100644
-index 0000000000..b7bb782977
---- /dev/null
-+++ b/tools/grit/grit/grd_reader.py
-@@ -0,0 +1,238 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Class for reading GRD files into memory, without processing them.
-+'''
-+
-+from __future__ import print_function
-+
-+import os.path
-+import sys
-+import xml.sax
-+import xml.sax.handler
-+
-+import six
-+
-+from grit import exception
-+from grit import util
-+from grit.node import mapping
-+from grit.node import misc
-+
-+
-+class StopParsingException(Exception):
-+ '''An exception used to stop parsing.'''
-+ pass
-+
-+
-+class GrdContentHandler(xml.sax.handler.ContentHandler):
-+ def __init__(self, stop_after, debug, dir, defines, tags_to_ignore,
-+ target_platform, source):
-+ # Invariant of data:
-+ # 'root' is the root of the parse tree being created, or None if we haven't
-+ # parsed out any elements.
-+ # 'stack' is the a stack of elements that we push new nodes onto and
-+ # pop from when they finish parsing, or [] if we are not currently parsing.
-+ # 'stack[-1]' is the top of the stack.
-+ self.root = None
-+ self.stack = []
-+ self.stop_after = stop_after
-+ self.debug = debug
-+ self.dir = dir
-+ self.defines = defines
-+ self.tags_to_ignore = tags_to_ignore or set()
-+ self.ignore_depth = 0
-+ self.target_platform = target_platform
-+ self.source = source
-+
-+ def startElement(self, name, attrs):
-+ if self.ignore_depth or name in self.tags_to_ignore:
-+ if self.debug and self.ignore_depth == 0:
-+ print("Ignoring element %s and its children" % name)
-+ self.ignore_depth += 1
-+ return
-+
-+ if self.debug:
-+ attr_list = ' '.join('%s="%s"' % kv for kv in attrs.items())
-+ print("Starting parsing of element %s with attributes %r" %
-+ (name, attr_list or '(none)'))
-+
-+ typeattr = attrs.get('type')
-+ node = mapping.ElementToClass(name, typeattr)()
-+ node.source = self.source
-+
-+ if self.stack:
-+ self.stack[-1].AddChild(node)
-+ node.StartParsing(name, self.stack[-1])
-+ else:
-+ assert self.root is None
-+ self.root = node
-+ if isinstance(self.root, misc.GritNode):
-+ if self.target_platform:
-+ self.root.SetTargetPlatform(self.target_platform)
-+ node.StartParsing(name, None)
-+ if self.defines:
-+ node.SetDefines(self.defines)
-+ self.stack.append(node)
-+
-+ for attr, attrval in attrs.items():
-+ node.HandleAttribute(attr, attrval)
-+
-+ def endElement(self, name):
-+ if self.ignore_depth:
-+ self.ignore_depth -= 1
-+ return
-+
-+ if name == 'part':
-+ partnode = self.stack[-1]
-+ partnode.started_inclusion = True
-+ # Add the contents of the sub-grd file as children of the <part> node.
-+ partname = os.path.join(self.dir, partnode.GetInputPath())
-+ # Check the GRDP file exists.
-+ if not os.path.exists(partname):
-+ raise exception.FileNotFound(partname)
-+ # Exceptions propagate to the handler in grd_reader.Parse().
-+ oldsource = self.source
-+ try:
-+ self.source = partname
-+ xml.sax.parse(partname, GrdPartContentHandler(self))
-+ finally:
-+ self.source = oldsource
-+
-+ if self.debug:
-+ print("End parsing of element %s" % name)
-+ self.stack.pop().EndParsing()
-+
-+ if name == self.stop_after:
-+ raise StopParsingException()
-+
-+ def characters(self, content):
-+ if self.ignore_depth == 0:
-+ if self.stack[-1]:
-+ self.stack[-1].AppendContent(content)
-+
-+ def ignorableWhitespace(self, whitespace):
-+ # TODO(joi): This is not supported by expat. Should use a different XML
-+ # parser?
-+ pass
-+
-+
-+class GrdPartContentHandler(xml.sax.handler.ContentHandler):
-+ def __init__(self, parent):
-+ self.parent = parent
-+ self.depth = 0
-+
-+ def startElement(self, name, attrs):
-+ if self.depth:
-+ self.parent.startElement(name, attrs)
-+ else:
-+ if name != 'grit-part':
-+ raise exception.MissingElement("root tag must be <grit-part>")
-+ if attrs:
-+ raise exception.UnexpectedAttribute(
-+ "<grit-part> tag must not have attributes")
-+ self.depth += 1
-+
-+ def endElement(self, name):
-+ self.depth -= 1
-+ if self.depth:
-+ self.parent.endElement(name)
-+
-+ def characters(self, content):
-+ self.parent.characters(content)
-+
-+ def ignorableWhitespace(self, whitespace):
-+ self.parent.ignorableWhitespace(whitespace)
-+
-+
-+def Parse(filename_or_stream, dir=None, stop_after=None, first_ids_file=None,
-+ debug=False, defines=None, tags_to_ignore=None, target_platform=None,
-+ predetermined_ids_file=None):
-+ '''Parses a GRD file into a tree of nodes (from grit.node).
-+
-+ If filename_or_stream is a stream, 'dir' should point to the directory
-+ notionally containing the stream (this feature is only used in unit tests).
-+
-+ If 'stop_after' is provided, the parsing will stop once the first node
-+ with this name has been fully parsed (including all its contents).
-+
-+ If 'debug' is true, lots of information about the parsing events will be
-+ printed out during parsing of the file.
-+
-+ If 'first_ids_file' is non-empty, it is used to override the setting for the
-+ first_ids_file attribute of the <grit> root node. Note that the first_ids_file
-+ parameter should be relative to the cwd, even though the first_ids_file
-+ attribute of the <grit> node is relative to the grd file.
-+
-+ If 'target_platform' is set, this is used to determine the target
-+ platform of builds, instead of using |sys.platform|.
-+
-+ Args:
-+ filename_or_stream: './bla.xml'
-+ dir: None (if filename_or_stream is a filename) or '.'
-+ stop_after: 'inputs'
-+ first_ids_file: 'GRIT_DIR/../gritsettings/resource_ids'
-+ debug: False
-+ defines: dictionary of defines, like {'chromeos': '1'}
-+ target_platform: None or the value that would be returned by sys.platform
-+ on your target platform.
-+ predetermined_ids_file: File path to a file containing a pre-determined
-+ mapping from resource names to resource ids which will be used to assign
-+ resource ids to those resources.
-+
-+ Return:
-+ Subclass of grit.node.base.Node
-+
-+ Throws:
-+ grit.exception.Parsing
-+ '''
-+
-+ if isinstance(filename_or_stream, six.string_types):
-+ source = filename_or_stream
-+ if dir is None:
-+ dir = util.dirname(filename_or_stream)
-+ else:
-+ source = None
-+
-+ handler = GrdContentHandler(stop_after=stop_after, debug=debug, dir=dir,
-+ defines=defines, tags_to_ignore=tags_to_ignore,
-+ target_platform=target_platform, source=source)
-+ try:
-+ xml.sax.parse(filename_or_stream, handler)
-+ except StopParsingException:
-+ assert stop_after
-+ pass
-+ except:
-+ if not debug:
-+ print("parse exception: run GRIT with the -x flag to debug .grd problems")
-+ raise
-+
-+ if handler.root.name != 'grit':
-+ raise exception.MissingElement("root tag must be <grit>")
-+
-+ if hasattr(handler.root, 'SetOwnDir'):
-+ # Fix up the base_dir so it is relative to the input file.
-+ assert dir is not None
-+ handler.root.SetOwnDir(dir)
-+
-+ if isinstance(handler.root, misc.GritNode):
-+ handler.root.SetPredeterminedIdsFile(predetermined_ids_file)
-+ if first_ids_file:
-+ # Make the path to the first_ids_file relative to the grd file,
-+ # unless it begins with GRIT_DIR.
-+ GRIT_DIR_PREFIX = 'GRIT_DIR'
-+ if not (first_ids_file.startswith(GRIT_DIR_PREFIX)
-+ and first_ids_file[len(GRIT_DIR_PREFIX)] in ['/', '\\']):
-+ rel_dir = os.path.relpath(os.getcwd(), dir)
-+ first_ids_file = util.normpath(os.path.join(rel_dir, first_ids_file))
-+ handler.root.attrs['first_ids_file'] = first_ids_file
-+ # Assign first ids to the nodes that don't have them.
-+ handler.root.AssignFirstIds(filename_or_stream, defines)
-+
-+ return handler.root
-+
-+
-+if __name__ == '__main__':
-+ util.ChangeStdoutEncoding()
-+ print(six.text_type(Parse(sys.argv[1])))
-diff --git a/tools/grit/grit/grd_reader_unittest.py b/tools/grit/grit/grd_reader_unittest.py
-new file mode 100644
-index 0000000000..920a92f9c0
---- /dev/null
-+++ b/tools/grit/grit/grd_reader_unittest.py
-@@ -0,0 +1,346 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grd_reader package'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import unittest
-+
-+import six
-+from six import StringIO
-+
-+from grit import exception
-+from grit import grd_reader
-+from grit import util
-+from grit.node import empty
-+from grit.node import message
-+
-+
-+class GrdReaderUnittest(unittest.TestCase):
-+ def testParsingAndXmlOutput(self):
-+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit base_dir="." current_release="3" latest_public_release="2" source_lang_id="en-US">
-+ <release seq="3">
-+ <includes>
-+ <include file="images/logo.gif" name="ID_LOGO" type="gif" />
-+ </includes>
-+ <messages>
-+ <if expr="True">
-+ <message desc="Printed to greet the currently logged in user" name="IDS_GREETING">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ </if>
-+ </messages>
-+ <structures>
-+ <structure file="rc_files/dialogs.rc" name="IDD_NARROW_DIALOG" type="dialog">
-+ <skeleton expr="lang == 'fr-FR'" file="bla.rc" variant_of_revision="3" />
-+ </structure>
-+ <structure file="rc_files/version.rc" name="VS_VERSION_INFO" type="version" />
-+ </structures>
-+ </release>
-+ <translations>
-+ <file lang="nl" path="nl_translations.xtb" />
-+ </translations>
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="resource.rc" lang="en-US" type="rc_all" />
-+ </outputs>
-+</grit>'''
-+ pseudo_file = StringIO(input)
-+ tree = grd_reader.Parse(pseudo_file, '.')
-+ output = six.text_type(tree)
-+ expected_output = input.replace(u' base_dir="."', u'')
-+ self.assertEqual(expected_output, output)
-+ self.failUnless(tree.GetNodeById('IDS_GREETING'))
-+
-+
-+ def testStopAfter(self):
-+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="resource.rc" lang="en-US" type="rc_all" />
-+ </outputs>
-+ <release seq="3">
-+ <includes>
-+ <include type="gif" name="ID_LOGO" file="images/logo.gif"/>
-+ </includes>
-+ </release>
-+</grit>'''
-+ pseudo_file = StringIO(input)
-+ tree = grd_reader.Parse(pseudo_file, '.', stop_after='outputs')
-+ # only an <outputs> child
-+ self.failUnless(len(tree.children) == 1)
-+ self.failUnless(tree.children[0].name == 'outputs')
-+
-+ def testLongLinesWithComments(self):
-+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ This is a very long line with no linebreaks yes yes it stretches on <!--
-+ -->and on <!--
-+ -->and on!
-+ </message>
-+ </messages>
-+ </release>
-+</grit>'''
-+ pseudo_file = StringIO(input)
-+ tree = grd_reader.Parse(pseudo_file, '.')
-+
-+ greeting = tree.GetNodeById('IDS_GREETING')
-+ self.failUnless(greeting.GetCliques()[0].GetMessage().GetRealContent() ==
-+ 'This is a very long line with no linebreaks yes yes it '
-+ 'stretches on and on and on!')
-+
-+ def doTestAssignFirstIds(self, first_ids_path):
-+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3"
-+ base_dir="." first_ids_file="%s">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_TEST" desc="test">
-+ test
-+ </message>
-+ </messages>
-+ </release>
-+</grit>''' % first_ids_path
-+ pseudo_file = StringIO(input)
-+ grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
-+ '..')
-+ fake_input_path = os.path.join(
-+ grit_root_dir, "grit/testdata/chrome/app/generated_resources.grd")
-+ root = grd_reader.Parse(pseudo_file, os.path.split(fake_input_path)[0])
-+ root.AssignFirstIds(fake_input_path, {})
-+ messages_node = root.children[0].children[0]
-+ self.failUnless(isinstance(messages_node, empty.MessagesNode))
-+ self.failUnless(messages_node.attrs["first_id"] !=
-+ empty.MessagesNode().DefaultAttributes()["first_id"])
-+
-+ def testAssignFirstIds(self):
-+ self.doTestAssignFirstIds("../../tools/grit/resource_ids")
-+
-+ def testAssignFirstIdsUseGritDir(self):
-+ self.doTestAssignFirstIds("GRIT_DIR/grit/testdata/tools/grit/resource_ids")
-+
-+ def testAssignFirstIdsMultipleMessages(self):
-+ """If there are multiple messages sections, the resource_ids file
-+ needs to list multiple first_id values."""
-+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3"
-+ base_dir="." first_ids_file="resource_ids">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_TEST" desc="test">
-+ test
-+ </message>
-+ </messages>
-+ <messages>
-+ <message name="IDS_TEST2" desc="test">
-+ test2
-+ </message>
-+ </messages>
-+ </release>
-+</grit>'''
-+ pseudo_file = StringIO(input)
-+ grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
-+ '..')
-+ fake_input_path = os.path.join(grit_root_dir, "grit/testdata/test.grd")
-+
-+ root = grd_reader.Parse(pseudo_file, os.path.split(fake_input_path)[0])
-+ root.AssignFirstIds(fake_input_path, {})
-+ messages_node = root.children[0].children[0]
-+ self.assertTrue(isinstance(messages_node, empty.MessagesNode))
-+ self.assertEqual('100', messages_node.attrs["first_id"])
-+ messages_node = root.children[0].children[1]
-+ self.assertTrue(isinstance(messages_node, empty.MessagesNode))
-+ self.assertEqual('10000', messages_node.attrs["first_id"])
-+
-+ def testUseNameForIdAndPpIfdef(self):
-+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <if expr="pp_ifdef('hello')">
-+ <message name="IDS_HELLO" use_name_for_id="true">
-+ Hello!
-+ </message>
-+ </if>
-+ </messages>
-+ </release>
-+</grit>'''
-+ pseudo_file = StringIO(input)
-+ root = grd_reader.Parse(pseudo_file, '.', defines={'hello': '1'})
-+
-+ # Check if the ID is set to the name. In the past, there was a bug
-+ # that caused the ID to be a generated number.
-+ hello = root.GetNodeById('IDS_HELLO')
-+ self.failUnless(hello.GetCliques()[0].GetId() == 'IDS_HELLO')
-+
-+ def testUseNameForIdWithIfElse(self):
-+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <if expr="pp_ifdef('hello')">
-+ <then>
-+ <message name="IDS_HELLO" use_name_for_id="true">
-+ Hello!
-+ </message>
-+ </then>
-+ <else>
-+ <message name="IDS_HELLO" use_name_for_id="true">
-+ Yellow!
-+ </message>
-+ </else>
-+ </if>
-+ </messages>
-+ </release>
-+</grit>'''
-+ pseudo_file = StringIO(input)
-+ root = grd_reader.Parse(pseudo_file, '.', defines={'hello': '1'})
-+
-+ # Check if the ID is set to the name. In the past, there was a bug
-+ # that caused the ID to be a generated number.
-+ hello = root.GetNodeById('IDS_HELLO')
-+ self.failUnless(hello.GetCliques()[0].GetId() == 'IDS_HELLO')
-+
-+ def testPartInclusionAndCorrectSource(self):
-+ arbitrary_path_grd = u'''\
-+ <grit-part>
-+ <message name="IDS_TEST5" desc="test5">test5</message>
-+ </grit-part>'''
-+ tmp_dir = util.TempDir({'arbitrary_path.grp': arbitrary_path_grd})
-+ arbitrary_path_grd_file = tmp_dir.GetPath('arbitrary_path.grp')
-+ top_grd = u'''\
-+ <grit latest_public_release="2" current_release="3">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_TEST" desc="test">
-+ test
-+ </message>
-+ <part file="sub.grp" />
-+ <part file="%s" />
-+ </messages>
-+ </release>
-+ </grit>''' % arbitrary_path_grd_file
-+ sub_grd = u'''\
-+ <grit-part>
-+ <message name="IDS_TEST2" desc="test2">test2</message>
-+ <part file="subsub.grp" />
-+ <message name="IDS_TEST3" desc="test3">test3</message>
-+ </grit-part>'''
-+ subsub_grd = u'''\
-+ <grit-part>
-+ <message name="IDS_TEST4" desc="test4">test4</message>
-+ </grit-part>'''
-+ expected_output = u'''\
-+ <grit current_release="3" latest_public_release="2">
-+ <release seq="3">
-+ <messages>
-+ <message desc="test" name="IDS_TEST">
-+ test
-+ </message>
-+ <part file="sub.grp">
-+ <message desc="test2" name="IDS_TEST2">
-+ test2
-+ </message>
-+ <part file="subsub.grp">
-+ <message desc="test4" name="IDS_TEST4">
-+ test4
-+ </message>
-+ </part>
-+ <message desc="test3" name="IDS_TEST3">
-+ test3
-+ </message>
-+ </part>
-+ <part file="%s">
-+ <message desc="test5" name="IDS_TEST5">
-+ test5
-+ </message>
-+ </part>
-+ </messages>
-+ </release>
-+ </grit>''' % arbitrary_path_grd_file
-+
-+ with util.TempDir({'sub.grp': sub_grd,
-+ 'subsub.grp': subsub_grd}) as tmp_sub_dir:
-+ output = grd_reader.Parse(StringIO(top_grd),
-+ tmp_sub_dir.GetPath())
-+ correct_sources = {
-+ 'IDS_TEST': None,
-+ 'IDS_TEST2': tmp_sub_dir.GetPath('sub.grp'),
-+ 'IDS_TEST3': tmp_sub_dir.GetPath('sub.grp'),
-+ 'IDS_TEST4': tmp_sub_dir.GetPath('subsub.grp'),
-+ 'IDS_TEST5': arbitrary_path_grd_file,
-+ }
-+
-+ for node in output.ActiveDescendants():
-+ with node:
-+ if isinstance(node, message.MessageNode):
-+ self.assertEqual(correct_sources[node.attrs.get('name')], node.source)
-+ self.assertEqual(expected_output.split(), output.FormatXml().split())
-+ tmp_dir.CleanUp()
-+
-+ def testPartInclusionFailure(self):
-+ template = u'''
-+ <grit latest_public_release="2" current_release="3">
-+ <outputs>
-+ %s
-+ </outputs>
-+ </grit>'''
-+
-+ part_failures = [
-+ (exception.UnexpectedContent, u'<part file="x">fnord</part>'),
-+ (exception.UnexpectedChild,
-+ u'<part file="x"><output filename="x" type="y" /></part>'),
-+ (exception.FileNotFound, u'<part file="yet_created_x" />'),
-+ ]
-+ for raises, data in part_failures:
-+ data = StringIO(template % data)
-+ self.assertRaises(raises, grd_reader.Parse, data, '.')
-+
-+ gritpart_failures = [
-+ (exception.UnexpectedAttribute, u'<grit-part file="xyz"></grit-part>'),
-+ (exception.MissingElement, u'<output filename="x" type="y" />'),
-+ ]
-+ for raises, data in gritpart_failures:
-+ top_grd = StringIO(template % u'<part file="bad.grp" />')
-+ with util.TempDir({'bad.grp': data}) as temp_dir:
-+ self.assertRaises(raises, grd_reader.Parse, top_grd, temp_dir.GetPath())
-+
-+ def testEarlyEnoughPlatformSpecification(self):
-+ # This is a regression test for issue
-+ # https://code.google.com/p/grit-i18n/issues/detail?id=23
-+ grd_text = u'''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="1" current_release="1">
-+ <release seq="1">
-+ <messages>
-+ <if expr="not pp_ifdef('use_titlecase')">
-+ <message name="IDS_XYZ">foo</message>
-+ </if>
-+ <!-- The assumption is that use_titlecase is never true for
-+ this platform. When the platform isn't set to 'android'
-+ early enough, we get a duplicate message name. -->
-+ <if expr="os == '%s'">
-+ <message name="IDS_XYZ">boo</message>
-+ </if>
-+ </messages>
-+ </release>
-+ </grit>''' % sys.platform
-+ with util.TempDir({}) as temp_dir:
-+ grd_reader.Parse(StringIO(grd_text), temp_dir.GetPath(),
-+ target_platform='android')
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/grit-todo.xml b/tools/grit/grit/grit-todo.xml
-new file mode 100644
-index 0000000000..b8c20fdfad
---- /dev/null
-+++ b/tools/grit/grit/grit-todo.xml
-@@ -0,0 +1,62 @@
-+<?xml version="1.0" encoding="windows-1252"?>
-+<TODOLIST FILEFORMAT="6" PROJECTNAME="GRIT" NEXTUNIQUEID="56" FILEVERSION="69" LASTMODIFIED="2005-08-19">
-+ <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38453.49975694" TITLE="check 'name' attribute is unique" TIMEESTUNITS="H" ID="2" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-04-11" POS="22" DONEDATE="38453.00000000"/>
-+ <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48189815" TITLE="import id-calculating code" TIMEESTUNITS="H" ID="3" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-05-16" POS="13" DONEDATE="38488.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48209491" TITLE="Import tool for existing translations" TIMEESTUNITS="H" ID="6" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="12" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00805556" TITLE="Export XMBs" TIMEESTUNITS="H" ID="8" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="20" DONEDATE="38511.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00924769" TITLE="Initial Integration" TIMEESTUNITS="H" ID="10" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="10" DONEDATE="38511.00000000">
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.54048611" TITLE="parser for %s strings" TIMEESTUNITS="H" ID="4" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-24" POS="2" DONEDATE="38496.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00261574" TITLE="import tool for existing RC files" TIMEESTUNITS="H" ID="5" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-25" POS="4" DONEDATE="38497.00000000">
-+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.92990741" TITLE="handle button value= and img alt= in message HTML text" TIMEESTUNITS="H" ID="22" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-24" POS="1" DONEDATE="38496.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00258102" TITLE="&amp;nbsp; bug" TIMEESTUNITS="H" ID="23" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-25" POS="2" DONEDATE="38497.00000000"/>
-+ </TASK>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61171296" TITLE="grit build" TIMEESTUNITS="H" ID="7" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="6" DONEDATE="38490.00000000">
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61168981" TITLE="use IDs gathered from gatherers for .h file" TIMEESTUNITS="H" ID="20" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="1" DONEDATE="38490.00000000"/>
-+ </TASK>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.55199074" TITLE="SCons Integration" TIMEESTUNITS="H" ID="9" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-01" POS="1" DONEDATE="38504.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61181713" TITLE="handle includes" TIMEESTUNITS="H" ID="12" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="5" DONEDATE="38490.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.98567130" TITLE="output translated HTML templates" TIMEESTUNITS="H" ID="25" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-04" POS="3" DONEDATE="38507.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.99394676" TITLE="bug: re-escape too much in RC dialogs etc." TIMEESTUNITS="H" ID="38" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-04" POS="7" DONEDATE="38507.00000000"/>
-+ </TASK>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46444444" TITLE="handle structure variants" TIMEESTUNITS="H" ID="11" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="15" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46456019" TITLE="handle include variants" TIMEESTUNITS="H" ID="13" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="17" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46537037" TITLE="handle translateable text for includes (e.g. image text)" TIMEESTUNITS="H" ID="14" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="14" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46712963" TITLE="ddoc" TIMEESTUNITS="H" ID="15" STARTDATE="38488.00000000" POS="4">
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46718750" TITLE="review comments miket" TIMEESTUNITS="H" ID="16" STARTDATE="38488.00000000" POS="2"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46722222" TITLE="review comments pdoyle" TIMEESTUNITS="H" ID="17" STARTDATE="38488.00000000" POS="1"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46732639" TITLE="remove 'extkey' from structure" TIMEESTUNITS="H" ID="18" STARTDATE="38488.00000000" POS="3"/>
-+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.53537037" TITLE="add 'encoding' to structure" TIMEESTUNITS="H" ID="19" STARTDATE="38488.00000000" POS="6"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38503.55304398" TITLE="document limitation: emitter doesn't emit the translated HTML templates" TIMEESTUNITS="H" ID="30" STARTDATE="38503.00000000" POS="4"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.58541667" TITLE="add 'internal_comment' to &lt;message&gt;" TIMEESTUNITS="H" ID="32" STARTDATE="38503.00000000" POS="5"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.73391204" TITLE="&lt;outputs&gt; can not have paths (because of SCons integration - goes to build dir)" TIMEESTUNITS="H" ID="36" STARTDATE="38503.00000000" POS="9"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38506.64265046" TITLE="&lt;identifers&gt; and &lt;identifier&gt; nodes" TIMEESTUNITS="H" ID="37" STARTDATE="38503.00000000" POS="10"/>
-+ <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38526.62344907" TITLE="&lt;structure&gt; can have 'exclude_from_rc' attribute (default false)" TIMEESTUNITS="H" ID="47" STARTDATE="38526.00000000" POS="8"/>
-+ <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38531.94135417" TITLE="add 'enc_check' to &lt;grit&gt;" TIMEESTUNITS="H" ID="48" STARTDATE="38526.00000000" POS="7"/>
-+ </TASK>
-+ <TASK STARTDATESTRING="2005-05-18" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38492.51549769" TITLE="handle nontranslateable messages (in MessageClique?)" TIMEESTUNITS="H" ID="21" PERCENTDONE="100" STARTDATE="38490.00000000" DONEDATESTRING="2005-06-16" POS="16" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70454861" TITLE="ask cprince about SCons builder in new mk system" TIMEESTUNITS="H" ID="24" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-02" POS="25" DONEDATE="38505.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.57436343" TITLE="fix AOL resource in trunk (&quot;???????&quot;)" TIMEESTUNITS="H" ID="26" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-01" POS="19" DONEDATE="38504.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38498.53893519" TITLE="rc_all vs. rc_translateable vs. rc_nontranslateable" TIMEESTUNITS="H" ID="27" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-16" POS="6" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38509.45532407" TITLE="make separate .grb &quot;outputs&quot; file (and change SCons integ) (??)" TIMEESTUNITS="H" ID="28" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-06" POS="8" DONEDATE="38509.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00939815" TITLE="fix unit tests so they run from any directory" TIMEESTUNITS="H" ID="33" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-08" POS="18" DONEDATE="38511.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38508.96640046" TITLE="Change R4 tool to CC correct team(s) on GRIT changes" TIMEESTUNITS="H" ID="39" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-05" POS="23" DONEDATE="38508.00000000"/>
-+ <TASK STARTDATESTRING="2005-06-07" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00881944" TITLE="Document why wrapper.rc" TIMEESTUNITS="H" ID="40" PERCENTDONE="100" STARTDATE="38510.00000000" DONEDATESTRING="2005-06-08" POS="21" DONEDATE="38511.00000000"/>
-+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00804398" TITLE="import XTBs" TIMEESTUNITS="H" ID="41" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="11" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00875000" TITLE="Nightly build integration" TIMEESTUNITS="H" ID="42" STARTDATE="38511.00000000" POS="3"/>
-+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00891204" TITLE="BUGS" TIMEESTUNITS="H" ID="43" STARTDATE="38511.00000000" POS="24">
-+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38513.03375000" TITLE="Should report error if RC-section structure refers to does not exist" TIMEESTUNITS="H" ID="44" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-10" POS="1" DONEDATE="38513.00000000"/>
-+ </TASK>
-+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00981481" TITLE="NEW FEATURES" TIMEESTUNITS="H" ID="45" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="7" DONEDATE="38519.00000000">
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70077546" TITLE="Implement line-continuation feature (\ at end of line?)" TIMEESTUNITS="H" ID="34" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="1" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70262731" TITLE="Implement conditional inclusion &amp; reflect the conditionals from R3 RC file" TIMEESTUNITS="H" ID="35" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="2" DONEDATE="38519.00000000"/>
-+ </TASK>
-+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.01046296" TITLE="TC integration (one-way TO the TC)" TIMEESTUNITS="H" ID="46" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="5" DONEDATE="38519.00000000"/>
-+ <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38533.59072917" TITLE="bazaar20 ad for GRIT help" TIMEESTUNITS="H" ID="49" STARTDATE="38533.00000000" POS="2">
-+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72346065" TITLE="bazaar20 ideas" TIMEESTUNITS="H" ID="51" STARTDATE="38583.00000000" POS="1">
-+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72354167" TITLE="GUI for adding/editing messages" TIMEESTUNITS="H" ID="52" STARTDATE="38583.00000000" POS="2"/>
-+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72365741" TITLE="XLIFF import/export" TIMEESTUNITS="H" ID="54" STARTDATE="38583.00000000" POS="1"/>
-+ </TASK>
-+ </TASK>
-+ <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73721065" TITLE="internal_comment for all resource nodes (not just &lt;message&gt;)" TIMEESTUNITS="H" ID="50" PERCENTDONE="100" STARTDATE="38533.00000000" DONEDATESTRING="2005-08-19" POS="9" DONEDATE="38583.73721065"/>
-+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73743056" TITLE="Preserve XML comments - this gives us line continuation and more" TIMEESTUNITS="H" ID="55" STARTDATE="38583.72326389" POS="1"/>
-+</TODOLIST>
-diff --git a/tools/grit/grit/grit_runner.py b/tools/grit/grit/grit_runner.py
-new file mode 100644
-index 0000000000..26aa0d58c4
---- /dev/null
-+++ b/tools/grit/grit/grit_runner.py
-@@ -0,0 +1,334 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Command processor for GRIT. This is the script you invoke to run the various
-+GRIT tools.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import getopt
-+
-+from grit import util
-+
-+import grit.extern.FP
-+
-+# Tool info factories; these import only within each factory to avoid
-+# importing most of the GRIT code until required.
-+def ToolFactoryBuild():
-+ import grit.tool.build
-+ return grit.tool.build.RcBuilder()
-+
-+def ToolFactoryBuildInfo():
-+ import grit.tool.buildinfo
-+ return grit.tool.buildinfo.DetermineBuildInfo()
-+
-+def ToolFactoryCount():
-+ import grit.tool.count
-+ return grit.tool.count.CountMessage()
-+
-+def ToolFactoryDiffStructures():
-+ import grit.tool.diff_structures
-+ return grit.tool.diff_structures.DiffStructures()
-+
-+def ToolFactoryMenuTranslationsFromParts():
-+ import grit.tool.menu_from_parts
-+ return grit.tool.menu_from_parts.MenuTranslationsFromParts()
-+
-+def ToolFactoryNewGrd():
-+ import grit.tool.newgrd
-+ return grit.tool.newgrd.NewGrd()
-+
-+def ToolFactoryResizeDialog():
-+ import grit.tool.resize
-+ return grit.tool.resize.ResizeDialog()
-+
-+def ToolFactoryRc2Grd():
-+ import grit.tool.rc2grd
-+ return grit.tool.rc2grd.Rc2Grd()
-+
-+def ToolFactoryTest():
-+ import grit.tool.test
-+ return grit.tool.test.TestTool()
-+
-+def ToolFactoryTranslationToTc():
-+ import grit.tool.transl2tc
-+ return grit.tool.transl2tc.TranslationToTc()
-+
-+def ToolFactoryUnit():
-+ import grit.tool.unit
-+ return grit.tool.unit.UnitTestTool()
-+
-+
-+def ToolFactoryUpdateResourceIds():
-+ import grit.tool.update_resource_ids
-+ return grit.tool.update_resource_ids.UpdateResourceIds()
-+
-+
-+def ToolFactoryXmb():
-+ import grit.tool.xmb
-+ return grit.tool.xmb.OutputXmb()
-+
-+def ToolAndroid2Grd():
-+ import grit.tool.android2grd
-+ return grit.tool.android2grd.Android2Grd()
-+
-+# Keys for the following map
-+_FACTORY = 1
-+_REQUIRES_INPUT = 2
-+_HIDDEN = 3 # optional key - presence indicates tool is hidden
-+
-+# Maps tool names to the tool's module. Done as a list of (key, value) tuples
-+# instead of a map to preserve ordering.
-+_TOOLS = [
-+ ['android2grd', {
-+ _FACTORY: ToolAndroid2Grd,
-+ _REQUIRES_INPUT: False
-+ }],
-+ ['build', {
-+ _FACTORY: ToolFactoryBuild,
-+ _REQUIRES_INPUT: True
-+ }],
-+ ['buildinfo', {
-+ _FACTORY: ToolFactoryBuildInfo,
-+ _REQUIRES_INPUT: True
-+ }],
-+ ['count', {
-+ _FACTORY: ToolFactoryCount,
-+ _REQUIRES_INPUT: True
-+ }],
-+ [
-+ 'menufromparts',
-+ {
-+ _FACTORY: ToolFactoryMenuTranslationsFromParts,
-+ _REQUIRES_INPUT: True,
-+ _HIDDEN: True
-+ }
-+ ],
-+ ['newgrd', {
-+ _FACTORY: ToolFactoryNewGrd,
-+ _REQUIRES_INPUT: False
-+ }],
-+ ['rc2grd', {
-+ _FACTORY: ToolFactoryRc2Grd,
-+ _REQUIRES_INPUT: False
-+ }],
-+ ['resize', {
-+ _FACTORY: ToolFactoryResizeDialog,
-+ _REQUIRES_INPUT: True
-+ }],
-+ ['sdiff', {
-+ _FACTORY: ToolFactoryDiffStructures,
-+ _REQUIRES_INPUT: False
-+ }],
-+ ['test', {
-+ _FACTORY: ToolFactoryTest,
-+ _REQUIRES_INPUT: True,
-+ _HIDDEN: True
-+ }],
-+ [
-+ 'transl2tc',
-+ {
-+ _FACTORY: ToolFactoryTranslationToTc,
-+ _REQUIRES_INPUT: False
-+ }
-+ ],
-+ ['unit', {
-+ _FACTORY: ToolFactoryUnit,
-+ _REQUIRES_INPUT: False
-+ }],
-+ [
-+ 'update_resource_ids',
-+ {
-+ _FACTORY: ToolFactoryUpdateResourceIds,
-+ _REQUIRES_INPUT: False
-+ }
-+ ],
-+ ['xmb', {
-+ _FACTORY: ToolFactoryXmb,
-+ _REQUIRES_INPUT: True
-+ }],
-+]
-+
-+
-+def PrintUsage():
-+ tool_list = ''
-+ for (tool, info) in _TOOLS:
-+ if not _HIDDEN in info:
-+ tool_list += ' %-12s %s\n' % (
-+ tool, info[_FACTORY]().ShortDescription())
-+
-+ print("""GRIT - the Google Resource and Internationalization Tool
-+
-+Usage: grit [GLOBALOPTIONS] TOOL [args to tool]
-+
-+Global options:
-+
-+ -i INPUT Specifies the INPUT file to use (a .grd file). If this is not
-+ specified, GRIT will look for the environment variable GRIT_INPUT.
-+ If it is not present either, GRIT will try to find an input file
-+ named 'resource.grd' in the current working directory.
-+
-+ -h MODULE Causes GRIT to use MODULE.UnsignedFingerPrint instead of
-+ grit.extern.FP.UnsignedFingerprint. MODULE must be
-+ available somewhere in the PYTHONPATH search path.
-+
-+ -v Print more verbose runtime information.
-+
-+ -x Print extremely verbose runtime information. Implies -v
-+
-+ -p FNAME Specifies that GRIT should profile its execution and output the
-+ results to the file FNAME.
-+
-+Tools:
-+
-+ TOOL can be one of the following:
-+%s
-+ For more information on how to use a particular tool, and the specific
-+ arguments you can send to that tool, execute 'grit help TOOL'
-+""" % (tool_list))
-+
-+
-+class Options(object):
-+ """Option storage and parsing."""
-+
-+ def __init__(self):
-+ self.hash = None
-+ self.input = None
-+ self.verbose = False
-+ self.extra_verbose = False
-+ self.output_stream = sys.stdout
-+ self.profile_dest = None
-+
-+ def ReadOptions(self, args):
-+ """Reads options from the start of args and returns the remainder."""
-+ (opts, args) = getopt.getopt(args, 'vxi:p:h:', ('help',))
-+ for (key, val) in opts:
-+ if key == '-h': self.hash = val
-+ elif key == '-i': self.input = val
-+ elif key == '-v':
-+ self.verbose = True
-+ util.verbose = True
-+ elif key == '-x':
-+ self.verbose = True
-+ util.verbose = True
-+ self.extra_verbose = True
-+ util.extra_verbose = True
-+ elif key == '-p': self.profile_dest = val
-+ elif key == '--help':
-+ PrintUsage()
-+ sys.exit(0)
-+
-+ if not self.input:
-+ if 'GRIT_INPUT' in os.environ:
-+ self.input = os.environ['GRIT_INPUT']
-+ else:
-+ self.input = 'resource.grd'
-+
-+ return args
-+
-+ def __repr__(self):
-+ return '(verbose: %d, input: %s)' % (
-+ self.verbose, self.input)
-+
-+
-+def _GetToolInfo(tool):
-+ """Returns the info map for the tool named 'tool' or None if there is no
-+ such tool."""
-+ matches = [t for t in _TOOLS if t[0] == tool]
-+ if not matches:
-+ return None
-+ else:
-+ return matches[0][1]
-+
-+
-+def Main(args=None):
-+ """Parses arguments and does the appropriate thing."""
-+ util.ChangeStdoutEncoding()
-+
-+ # Support for setuptools console wrappers.
-+ if args is None:
-+ args = sys.argv[1:]
-+
-+ options = Options()
-+ try:
-+ args = options.ReadOptions(args) # args may be shorter after this
-+ except getopt.GetoptError as e:
-+ print("grit:", str(e))
-+ print("Try running 'grit help' for valid options.")
-+ return 1
-+ if not args:
-+ print("No tool provided. Try running 'grit help' for a list of tools.")
-+ return 2
-+
-+ tool = args[0]
-+ if tool == 'help':
-+ if len(args) == 1:
-+ PrintUsage()
-+ return 0
-+ else:
-+ tool = args[1]
-+ if not _GetToolInfo(tool):
-+ print("No such tool. Try running 'grit help' for a list of tools.")
-+ return 2
-+
-+ print("Help for 'grit %s' (for general help, run 'grit help'):\n" %
-+ (tool,))
-+ _GetToolInfo(tool)[_FACTORY]().ShowUsage()
-+ return 0
-+ if not _GetToolInfo(tool):
-+ print("No such tool. Try running 'grit help' for a list of tools.")
-+ return 2
-+
-+ try:
-+ if _GetToolInfo(tool)[_REQUIRES_INPUT]:
-+ os.stat(options.input)
-+ except OSError:
-+ print('Input file %s not found.\n'
-+ 'To specify a different input file:\n'
-+ ' 1. Use the GRIT_INPUT environment variable.\n'
-+ ' 2. Use the -i command-line option. This overrides '
-+ 'GRIT_INPUT.\n'
-+ ' 3. Specify neither GRIT_INPUT or -i and GRIT will try to load '
-+ "'resource.grd'\n"
-+ ' from the current directory.' % options.input)
-+ return 2
-+
-+ if options.hash:
-+ grit.extern.FP.UseUnsignedFingerPrintFromModule(options.hash)
-+
-+ try:
-+ toolobject = _GetToolInfo(tool)[_FACTORY]()
-+ if options.profile_dest:
-+ import hotshot
-+ prof = hotshot.Profile(options.profile_dest)
-+ return prof.runcall(toolobject.Run, options, args[1:])
-+ else:
-+ return toolobject.Run(options, args[1:])
-+ except getopt.GetoptError as e:
-+ print("grit: %s: %s" % (tool, str(e)))
-+ print("Try running 'grit help %s' for valid options." % (tool,))
-+ return 1
-+
-+
-+if __name__ == '__main__':
-+ sys.path.append(
-+ os.path.join(
-+ os.path.dirname(
-+ os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
-+ 'diagnosis'))
-+ try:
-+ import crbug_1001171
-+ with crbug_1001171.DumpStateOnLookupError():
-+ sys.exit(Main(sys.argv[1:]))
-+ except ImportError:
-+ pass
-+
-+ sys.exit(Main(sys.argv[1:]))
-diff --git a/tools/grit/grit/grit_runner_unittest.py b/tools/grit/grit/grit_runner_unittest.py
-new file mode 100644
-index 0000000000..1487001d81
---- /dev/null
-+++ b/tools/grit/grit/grit_runner_unittest.py
-@@ -0,0 +1,42 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.py'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import util
-+import grit.grit_runner
-+
-+class OptionArgsUnittest(unittest.TestCase):
-+ def setUp(self):
-+ self.buf = StringIO()
-+ self.old_stdout = sys.stdout
-+ sys.stdout = self.buf
-+
-+ def tearDown(self):
-+ sys.stdout = self.old_stdout
-+
-+ def testSimple(self):
-+ grit.grit_runner.Main(['-i',
-+ util.PathFromRoot('grit/testdata/simple-input.xml'),
-+ 'test', 'bla', 'voff', 'ga'])
-+ output = self.buf.getvalue()
-+ self.failUnless(output.count("'test'") == 0) # tool name doesn't occur
-+ self.failUnless(output.count('bla'))
-+ self.failUnless(output.count('simple-input.xml'))
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/lazy_re.py b/tools/grit/grit/lazy_re.py
-new file mode 100644
-index 0000000000..5c461e87e7
---- /dev/null
-+++ b/tools/grit/grit/lazy_re.py
-@@ -0,0 +1,46 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''In GRIT, we used to compile a lot of regular expressions at parse
-+time. Since many of them never get used, we use lazy_re to compile
-+them on demand the first time they are used, thus speeding up startup
-+time in some cases.
-+'''
-+
-+from __future__ import print_function
-+
-+import re
-+
-+
-+class LazyRegexObject(object):
-+ '''This object creates a RegexObject with the arguments passed in
-+ its constructor, the first time any attribute except the several on
-+ the class itself is accessed. This accomplishes lazy compilation of
-+ the regular expression while maintaining a nearly-identical
-+ interface.
-+ '''
-+
-+ def __init__(self, *args, **kwargs):
-+ self._stash_args = args
-+ self._stash_kwargs = kwargs
-+ self._lazy_re = None
-+
-+ def _LazyInit(self):
-+ if not self._lazy_re:
-+ self._lazy_re = re.compile(*self._stash_args, **self._stash_kwargs)
-+
-+ def __getattribute__(self, name):
-+ if name in ('_LazyInit', '_lazy_re', '_stash_args', '_stash_kwargs'):
-+ return object.__getattribute__(self, name)
-+ else:
-+ self._LazyInit()
-+ return getattr(self._lazy_re, name)
-+
-+
-+def compile(*args, **kwargs):
-+ '''Creates a LazyRegexObject that, when invoked on, will compile a
-+ re.RegexObject (via re.compile) with the same arguments passed to
-+ this function, and delegate almost all of its methods to it.
-+ '''
-+ return LazyRegexObject(*args, **kwargs)
-diff --git a/tools/grit/grit/lazy_re_unittest.py b/tools/grit/grit/lazy_re_unittest.py
-new file mode 100644
-index 0000000000..8488b454ee
---- /dev/null
-+++ b/tools/grit/grit/lazy_re_unittest.py
-@@ -0,0 +1,40 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit test for lazy_re.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import re
-+import unittest
-+
-+from grit import lazy_re
-+
-+
-+class LazyReUnittest(unittest.TestCase):
-+
-+ def testCreatedOnlyOnDemand(self):
-+ rex = lazy_re.compile('bingo')
-+ self.assertEqual(None, rex._lazy_re)
-+ self.assertTrue(rex.match('bingo'))
-+ self.assertNotEqual(None, rex._lazy_re)
-+
-+ def testJustKwargsWork(self):
-+ rex = lazy_re.compile(flags=re.I, pattern='BiNgO')
-+ self.assertTrue(rex.match('bingo'))
-+
-+ def testPositionalAndKwargsWork(self):
-+ rex = lazy_re.compile('BiNgO', flags=re.I)
-+ self.assertTrue(rex.match('bingo'))
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/__init__.py b/tools/grit/grit/node/__init__.py
-new file mode 100644
-index 0000000000..2fc0d3360c
---- /dev/null
-+++ b/tools/grit/grit/node/__init__.py
-@@ -0,0 +1,8 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Package 'grit.node'
-+'''
-+
-+pass
-diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py
-new file mode 100644
-index 0000000000..40859d301d
---- /dev/null
-+++ b/tools/grit/grit/node/base.py
-@@ -0,0 +1,670 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Base types for nodes in a GRIT resource tree.
-+'''
-+
-+from __future__ import print_function
-+
-+import ast
-+import os
-+import struct
-+import sys
-+from xml.sax import saxutils
-+
-+import six
-+
-+from grit import constants
-+from grit import clique
-+from grit import exception
-+from grit import util
-+from grit.node import brotli_util
-+import grit.format.gzip_string
-+
-+
-+class Node(object):
-+ '''An item in the tree that has children.'''
-+
-+ # Valid content types that can be returned by _ContentType()
-+ _CONTENT_TYPE_NONE = 0 # No CDATA content but may have children
-+ _CONTENT_TYPE_CDATA = 1 # Only CDATA, no children.
-+ _CONTENT_TYPE_MIXED = 2 # CDATA and children, possibly intermingled
-+
-+ # Types of files to be compressed by default.
-+ _COMPRESS_BY_DEFAULT_EXTENSIONS = ('.js', '.html', '.css', '.svg')
-+
-+ # Default nodes to not whitelist skipped
-+ _whitelist_marked_as_skip = False
-+
-+ # A class-static cache to speed up EvaluateExpression().
-+ # Keys are expressions (e.g. 'is_ios and lang == "fr"'). Values are tuples
-+ # (code, variables_in_expr) where code is the compiled expression and can be
-+ # directly eval'd, and variables_in_expr is the list of variable and method
-+ # names used in the expression (e.g. ['is_ios', 'lang']).
-+ eval_expr_cache = {}
-+
-+ def __init__(self):
-+ self.children = [] # A list of child elements
-+ self.mixed_content = [] # A list of u'' and/or child elements (this
-+ # duplicates 'children' but
-+ # is needed to preserve markup-type content).
-+ self.name = u'' # The name of this element
-+ self.attrs = {} # The set of attributes (keys to values)
-+ self.parent = None # Our parent unless we are the root element.
-+ self.uberclique = None # Allows overriding uberclique for parts of tree
-+ self.source = None # File that this node was parsed from
-+
-+ # This context handler allows you to write "with node:" and get a
-+ # line identifying the offending node if an exception escapes from the body
-+ # of the with statement.
-+ def __enter__(self):
-+ return self
-+
-+ def __exit__(self, exc_type, exc_value, traceback):
-+ if exc_type is not None:
-+ print(u'Error processing node %s: %s' % (six.text_type(self), exc_value))
-+
-+ def __iter__(self):
-+ '''A preorder iteration through the tree that this node is the root of.'''
-+ return self.Preorder()
-+
-+ def Preorder(self):
-+ '''Generator that generates first this node, then the same generator for
-+ any child nodes.'''
-+ yield self
-+ for child in self.children:
-+ for iterchild in child.Preorder():
-+ yield iterchild
-+
-+ def ActiveChildren(self):
-+ '''Returns the children of this node that should be included in the current
-+ configuration. Overridden by <if>.'''
-+ return [node for node in self.children if not node.WhitelistMarkedAsSkip()]
-+
-+ def ActiveDescendants(self):
-+ '''Yields the current node and all descendants that should be included in
-+ the current configuration, in preorder.'''
-+ yield self
-+ for child in self.ActiveChildren():
-+ for descendant in child.ActiveDescendants():
-+ yield descendant
-+
-+ def GetRoot(self):
-+ '''Returns the root Node in the tree this Node belongs to.'''
-+ curr = self
-+ while curr.parent:
-+ curr = curr.parent
-+ return curr
-+
-+ # TODO(joi) Use this (currently untested) optimization?:
-+ #if hasattr(self, '_root'):
-+ # return self._root
-+ #curr = self
-+ #while curr.parent and not hasattr(curr, '_root'):
-+ # curr = curr.parent
-+ #if curr.parent:
-+ # self._root = curr._root
-+ #else:
-+ # self._root = curr
-+ #return self._root
-+
-+ def StartParsing(self, name, parent):
-+ '''Called at the start of parsing.
-+
-+ Args:
-+ name: u'elementname'
-+ parent: grit.node.base.Node or subclass or None
-+ '''
-+ assert isinstance(name, six.string_types)
-+ assert not parent or isinstance(parent, Node)
-+ self.name = name
-+ self.parent = parent
-+
-+ def AddChild(self, child):
-+ '''Adds a child to the list of children of this node, if it is a valid
-+ child for the node.'''
-+ assert isinstance(child, Node)
-+ if (not self._IsValidChild(child) or
-+ self._ContentType() == self._CONTENT_TYPE_CDATA):
-+ explanation = 'invalid child %s for parent %s' % (str(child), self.name)
-+ raise exception.UnexpectedChild(explanation)
-+ self.children.append(child)
-+ self.mixed_content.append(child)
-+
-+ def RemoveChild(self, child_id):
-+ '''Removes the first node that has a "name" attribute which
-+ matches "child_id" in the list of immediate children of
-+ this node.
-+
-+ Args:
-+ child_id: String identifying the child to be removed
-+ '''
-+ index = 0
-+ # Safe not to copy since we only remove the first element found
-+ for child in self.children:
-+ name_attr = child.attrs['name']
-+ if name_attr == child_id:
-+ self.children.pop(index)
-+ self.mixed_content.pop(index)
-+ break
-+ index += 1
-+
-+ def AppendContent(self, content):
-+ '''Appends a chunk of text as content of this node.
-+
-+ Args:
-+ content: u'hello'
-+
-+ Return:
-+ None
-+ '''
-+ assert isinstance(content, six.string_types)
-+ if self._ContentType() != self._CONTENT_TYPE_NONE:
-+ self.mixed_content.append(content)
-+ elif content.strip() != '':
-+ raise exception.UnexpectedContent()
-+
-+ def HandleAttribute(self, attrib, value):
-+ '''Informs the node of an attribute that was parsed out of the GRD file
-+ for it.
-+
-+ Args:
-+ attrib: 'name'
-+ value: 'fooblat'
-+
-+ Return:
-+ None
-+ '''
-+ assert isinstance(attrib, six.string_types)
-+ assert isinstance(value, six.string_types)
-+ if self._IsValidAttribute(attrib, value):
-+ self.attrs[attrib] = value
-+ else:
-+ raise exception.UnexpectedAttribute(attrib)
-+
-+ def EndParsing(self):
-+ '''Called at the end of parsing.'''
-+
-+ # TODO(joi) Rewrite this, it's extremely ugly!
-+ if len(self.mixed_content):
-+ if isinstance(self.mixed_content[0], six.string_types):
-+ # Remove leading and trailing chunks of pure whitespace.
-+ while (len(self.mixed_content) and
-+ isinstance(self.mixed_content[0], six.string_types) and
-+ self.mixed_content[0].strip() == ''):
-+ self.mixed_content = self.mixed_content[1:]
-+ # Strip leading and trailing whitespace from mixed content chunks
-+ # at front and back.
-+ if (len(self.mixed_content) and
-+ isinstance(self.mixed_content[0], six.string_types)):
-+ self.mixed_content[0] = self.mixed_content[0].lstrip()
-+ # Remove leading and trailing ''' (used to demarcate whitespace)
-+ if (len(self.mixed_content) and
-+ isinstance(self.mixed_content[0], six.string_types)):
-+ if self.mixed_content[0].startswith("'''"):
-+ self.mixed_content[0] = self.mixed_content[0][3:]
-+ if len(self.mixed_content):
-+ if isinstance(self.mixed_content[-1], six.string_types):
-+ # Same stuff all over again for the tail end.
-+ while (len(self.mixed_content) and
-+ isinstance(self.mixed_content[-1], six.string_types) and
-+ self.mixed_content[-1].strip() == ''):
-+ self.mixed_content = self.mixed_content[:-1]
-+ if (len(self.mixed_content) and
-+ isinstance(self.mixed_content[-1], six.string_types)):
-+ self.mixed_content[-1] = self.mixed_content[-1].rstrip()
-+ if (len(self.mixed_content) and
-+ isinstance(self.mixed_content[-1], six.string_types)):
-+ if self.mixed_content[-1].endswith("'''"):
-+ self.mixed_content[-1] = self.mixed_content[-1][:-3]
-+
-+ # Check that all mandatory attributes are there.
-+ for node_mandatt in self.MandatoryAttributes():
-+ mandatt_list = []
-+ if node_mandatt.find('|') >= 0:
-+ mandatt_list = node_mandatt.split('|')
-+ else:
-+ mandatt_list.append(node_mandatt)
-+
-+ mandatt_option_found = False
-+ for mandatt in mandatt_list:
-+ assert mandatt not in self.DefaultAttributes()
-+ if mandatt in self.attrs:
-+ if not mandatt_option_found:
-+ mandatt_option_found = True
-+ else:
-+ raise exception.MutuallyExclusiveMandatoryAttribute(mandatt)
-+
-+ if not mandatt_option_found:
-+ raise exception.MissingMandatoryAttribute(mandatt)
-+
-+ # Add default attributes if not specified in input file.
-+ for defattr in self.DefaultAttributes():
-+ if not defattr in self.attrs:
-+ self.attrs[defattr] = self.DefaultAttributes()[defattr]
-+
-+ def GetCdata(self):
-+ '''Returns all CDATA of this element, concatenated into a single
-+ string. Note that this ignores any elements embedded in CDATA.'''
-+ return ''.join([c for c in self.mixed_content
-+ if isinstance(c, six.string_types)])
-+
-+ def __str__(self):
-+ '''Returns this node and all nodes below it as an XML document in a Unicode
-+ string.'''
-+ header = u'<?xml version="1.0" encoding="UTF-8"?>\n'
-+ return header + self.FormatXml()
-+
-+ # Some Python 2 glue.
-+ __unicode__ = __str__
-+
-+ def FormatXml(self, indent = u'', one_line = False):
-+ '''Returns this node and all nodes below it as an XML
-+ element in a Unicode string. This differs from __unicode__ in that it does
-+ not include the <?xml> stuff at the top of the string. If one_line is true,
-+ children and CDATA are layed out in a way that preserves internal
-+ whitespace.
-+ '''
-+ assert isinstance(indent, six.string_types)
-+
-+ content_one_line = (one_line or
-+ self._ContentType() == self._CONTENT_TYPE_MIXED)
-+ inside_content = self.ContentsAsXml(indent, content_one_line)
-+
-+ # Then the attributes for this node.
-+ attribs = u''
-+ default_attribs = self.DefaultAttributes()
-+ for attrib, value in sorted(self.attrs.items()):
-+ # Only print an attribute if it is other than the default value.
-+ if attrib not in default_attribs or value != default_attribs[attrib]:
-+ attribs += u' %s=%s' % (attrib, saxutils.quoteattr(value))
-+
-+ # Finally build the XML for our node and return it
-+ if len(inside_content) > 0:
-+ if one_line:
-+ return u'<%s%s>%s</%s>' % (self.name, attribs, inside_content,
-+ self.name)
-+ elif content_one_line:
-+ return u'%s<%s%s>\n%s %s\n%s</%s>' % (
-+ indent, self.name, attribs,
-+ indent, inside_content,
-+ indent, self.name)
-+ else:
-+ return u'%s<%s%s>\n%s\n%s</%s>' % (
-+ indent, self.name, attribs,
-+ inside_content,
-+ indent, self.name)
-+ else:
-+ return u'%s<%s%s />' % (indent, self.name, attribs)
-+
-+ def ContentsAsXml(self, indent, one_line):
-+ '''Returns the contents of this node (CDATA and child elements) in XML
-+ format. If 'one_line' is true, the content will be laid out on one line.'''
-+ assert isinstance(indent, six.string_types)
-+
-+ # Build the contents of the element.
-+ inside_parts = []
-+ last_item = None
-+ for mixed_item in self.mixed_content:
-+ if isinstance(mixed_item, Node):
-+ inside_parts.append(mixed_item.FormatXml(indent + u' ', one_line))
-+ if not one_line:
-+ inside_parts.append(u'\n')
-+ else:
-+ message = mixed_item
-+ # If this is the first item and it starts with whitespace, we add
-+ # the ''' delimiter.
-+ if not last_item and message.lstrip() != message:
-+ message = u"'''" + message
-+ inside_parts.append(util.EncodeCdata(message))
-+ last_item = mixed_item
-+
-+ # If there are only child nodes and no cdata, there will be a spurious
-+ # trailing \n
-+ if len(inside_parts) and inside_parts[-1] == '\n':
-+ inside_parts = inside_parts[:-1]
-+
-+ # If the last item is a string (not a node) and ends with whitespace,
-+ # we need to add the ''' delimiter.
-+ if (isinstance(last_item, six.string_types) and
-+ last_item.rstrip() != last_item):
-+ inside_parts[-1] = inside_parts[-1] + u"'''"
-+
-+ return u''.join(inside_parts)
-+
-+ def SubstituteMessages(self, substituter):
-+ '''Applies substitutions to all messages in the tree.
-+
-+ Called as a final step of RunGatherers.
-+
-+ Args:
-+ substituter: a grit.util.Substituter object.
-+ '''
-+ for child in self.children:
-+ child.SubstituteMessages(substituter)
-+
-+ def _IsValidChild(self, child):
-+ '''Returns true if 'child' is a valid child of this node.
-+ Overridden by subclasses.'''
-+ return False
-+
-+ def _IsValidAttribute(self, name, value):
-+ '''Returns true if 'name' is the name of a valid attribute of this element
-+ and 'value' is a valid value for that attribute. Overriden by
-+ subclasses unless they have only mandatory attributes.'''
-+ return (name in self.MandatoryAttributes() or
-+ name in self.DefaultAttributes())
-+
-+ def _ContentType(self):
-+ '''Returns the type of content this element can have. Overridden by
-+ subclasses. The content type can be one of the _CONTENT_TYPE_XXX constants
-+ above.'''
-+ return self._CONTENT_TYPE_NONE
-+
-+ def MandatoryAttributes(self):
-+ '''Returns a list of attribute names that are mandatory (non-optional)
-+ on the current element. One can specify a list of
-+ "mutually exclusive mandatory" attributes by specifying them as one
-+ element in the list, separated by a "|" character.
-+ '''
-+ return []
-+
-+ def DefaultAttributes(self):
-+ '''Returns a dictionary of attribute names that have defaults, mapped to
-+ the default value. Overridden by subclasses.'''
-+ return {}
-+
-+ def GetCliques(self):
-+ '''Returns all MessageClique objects belonging to this node. Overridden
-+ by subclasses.
-+
-+ Return:
-+ [clique1, clique2] or []
-+ '''
-+ return []
-+
-+ def ToRealPath(self, path_from_basedir):
-+ '''Returns a real path (which can be absolute or relative to the current
-+ working directory), given a path that is relative to the base directory
-+ set for the GRIT input file.
-+
-+ Args:
-+ path_from_basedir: '..'
-+
-+ Return:
-+ 'resource'
-+ '''
-+ return util.normpath(os.path.join(self.GetRoot().GetBaseDir(),
-+ os.path.expandvars(path_from_basedir)))
-+
-+ def GetInputPath(self):
-+ '''Returns a path, relative to the base directory set for the grd file,
-+ that points to the file the node refers to.
-+ '''
-+ # This implementation works for most nodes that have an input file.
-+ return self.attrs['file']
-+
-+ def UberClique(self):
-+ '''Returns the uberclique that should be used for messages originating in
-+ a given node. If the node itself has its uberclique set, that is what we
-+ use, otherwise we search upwards until we find one. If we do not find one
-+ even at the root node, we set the root node's uberclique to a new
-+ uberclique instance.
-+ '''
-+ node = self
-+ while not node.uberclique and node.parent:
-+ node = node.parent
-+ if not node.uberclique:
-+ node.uberclique = clique.UberClique()
-+ return node.uberclique
-+
-+ def IsTranslateable(self):
-+ '''Returns false if the node has contents that should not be translated,
-+ otherwise returns false (even if the node has no contents).
-+ '''
-+ if not 'translateable' in self.attrs:
-+ return True
-+ else:
-+ return self.attrs['translateable'] == 'true'
-+
-+ def IsAccessibilityWithNoUI(self):
-+ '''Returns true if the node is marked as an accessibility label and the
-+ message isn't shown in the UI. Otherwise returns false. This label is
-+ used to determine if the text requires screenshots.'''
-+ if not 'is_accessibility_with_no_ui' in self.attrs:
-+ return False
-+ else:
-+ return self.attrs['is_accessibility_with_no_ui'] == 'true'
-+
-+ def GetNodeById(self, id):
-+ '''Returns the node in the subtree parented by this node that has a 'name'
-+ attribute matching 'id'. Returns None if no such node is found.
-+ '''
-+ for node in self:
-+ if 'name' in node.attrs and node.attrs['name'] == id:
-+ return node
-+ return None
-+
-+ def GetChildrenOfType(self, type):
-+ '''Returns a list of all subnodes (recursing to all leaves) of this node
-+ that are of the indicated type (or tuple of types).
-+
-+ Args:
-+ type: A type you could use with isinstance().
-+
-+ Return:
-+ A list, possibly empty.
-+ '''
-+ return [child for child in self if isinstance(child, type)]
-+
-+ def GetTextualIds(self):
-+ '''Returns a list of the textual ids of this node.
-+ '''
-+ if 'name' in self.attrs:
-+ return [self.attrs['name']]
-+ return []
-+
-+ @classmethod
-+ def EvaluateExpression(cls, expr, defs, target_platform, extra_variables={}):
-+ '''Worker for EvaluateCondition (below) and conditions in XTB files.'''
-+ if expr in cls.eval_expr_cache:
-+ code, variables_in_expr = cls.eval_expr_cache[expr]
-+ else:
-+ # Get a list of all variable and method names used in the expression.
-+ syntax_tree = ast.parse(expr, mode='eval')
-+ variables_in_expr = [node.id for node in ast.walk(syntax_tree) if
-+ isinstance(node, ast.Name) and node.id not in ('True', 'False')]
-+ code = compile(syntax_tree, filename='<string>', mode='eval')
-+ cls.eval_expr_cache[expr] = code, variables_in_expr
-+
-+ # Set values only for variables that are needed to eval the expression.
-+ variable_map = {}
-+ for name in variables_in_expr:
-+ if name == 'os':
-+ value = target_platform
-+ elif name == 'defs':
-+ value = defs
-+
-+ elif name == 'is_linux':
-+ value = target_platform.startswith('linux')
-+ elif name == 'is_macosx':
-+ value = target_platform == 'darwin'
-+ elif name == 'is_win':
-+ value = target_platform in ('cygwin', 'win32')
-+ elif name == 'is_android':
-+ value = target_platform == 'android'
-+ elif name == 'is_ios':
-+ value = target_platform == 'ios'
-+ elif name == 'is_bsd':
-+ value = 'bsd' in target_platform
-+ elif name == 'is_posix':
-+ value = (target_platform in ('darwin', 'linux2', 'linux3', 'sunos5',
-+ 'android', 'ios')
-+ or 'bsd' in target_platform)
-+
-+ elif name == 'pp_ifdef':
-+ def pp_ifdef(symbol):
-+ return symbol in defs
-+ value = pp_ifdef
-+ elif name == 'pp_if':
-+ def pp_if(symbol):
-+ return defs.get(symbol, False)
-+ value = pp_if
-+
-+ elif name in defs:
-+ value = defs[name]
-+ elif name in extra_variables:
-+ value = extra_variables[name]
-+ else:
-+ # Undefined variables default to False.
-+ value = False
-+
-+ variable_map[name] = value
-+
-+ eval_result = eval(code, {}, variable_map)
-+ assert isinstance(eval_result, bool)
-+ return eval_result
-+
-+ def EvaluateCondition(self, expr):
-+ '''Returns true if and only if the Python expression 'expr' evaluates
-+ to true.
-+
-+ The expression is given a few local variables:
-+ - 'lang' is the language currently being output
-+ (the 'lang' attribute of the <output> element).
-+ - 'context' is the current output context
-+ (the 'context' attribute of the <output> element).
-+ - 'defs' is a map of C preprocessor-style symbol names to their values.
-+ - 'os' is the current platform (likely 'linux2', 'win32' or 'darwin').
-+ - 'pp_ifdef(symbol)' is a shorthand for "symbol in defs".
-+ - 'pp_if(symbol)' is a shorthand for "symbol in defs and defs[symbol]".
-+ - 'is_linux', 'is_macosx', 'is_win', 'is_posix' are true if 'os'
-+ matches the given platform.
-+ '''
-+ root = self.GetRoot()
-+ lang = getattr(root, 'output_language', '')
-+ context = getattr(root, 'output_context', '')
-+ defs = getattr(root, 'defines', {})
-+ target_platform = getattr(root, 'target_platform', '')
-+ extra_variables = {
-+ 'lang': lang,
-+ 'context': context,
-+ }
-+ return Node.EvaluateExpression(
-+ expr, defs, target_platform, extra_variables)
-+
-+ def OnlyTheseTranslations(self, languages):
-+ '''Turns off loading of translations for languages not in the provided list.
-+
-+ Attrs:
-+ languages: ['fr', 'zh_cn']
-+ '''
-+ for node in self:
-+ if (hasattr(node, 'IsTranslation') and
-+ node.IsTranslation() and
-+ node.GetLang() not in languages):
-+ node.DisableLoading()
-+
-+ def FindBooleanAttribute(self, attr, default, skip_self):
-+ '''Searches all ancestors of the current node for the nearest enclosing
-+ definition of the given boolean attribute.
-+
-+ Args:
-+ attr: 'fallback_to_english'
-+ default: What to return if no node defines the attribute.
-+ skip_self: Don't check the current node, only its parents.
-+ '''
-+ p = self.parent if skip_self else self
-+ while p:
-+ value = p.attrs.get(attr, 'default').lower()
-+ if value != 'default':
-+ return (value == 'true')
-+ p = p.parent
-+ return default
-+
-+ def PseudoIsAllowed(self):
-+ '''Returns true if this node is allowed to use pseudo-translations. This
-+ is true by default, unless this node is within a <release> node that has
-+ the allow_pseudo attribute set to false.
-+ '''
-+ return self.FindBooleanAttribute('allow_pseudo',
-+ default=True, skip_self=True)
-+
-+ def ShouldFallbackToEnglish(self):
-+ '''Returns true iff this node should fall back to English when
-+ pseudotranslations are disabled and no translation is available for a
-+ given message.
-+ '''
-+ return self.FindBooleanAttribute('fallback_to_english',
-+ default=False, skip_self=True)
-+
-+ def WhitelistMarkedAsSkip(self):
-+ '''Returns true if the node is marked to be skipped in the output by a
-+ whitelist.
-+ '''
-+ return self._whitelist_marked_as_skip
-+
-+ def SetWhitelistMarkedAsSkip(self, mark_skipped):
-+ '''Sets WhitelistMarkedAsSkip.
-+ '''
-+ self._whitelist_marked_as_skip = mark_skipped
-+
-+ def ExpandVariables(self):
-+ '''Whether we need to expand variables on a given node.'''
-+ return False
-+
-+ def IsResourceMapSource(self):
-+ '''Whether this node is a resource map source.'''
-+ return False
-+
-+ def CompressDataIfNeeded(self, data):
-+ '''Compress data using the format specified in the compress attribute.
-+
-+ Args:
-+ data: The data to compressed.
-+ Returns:
-+ The data in gzipped or brotli compressed format. If the format is
-+ unspecified then this returns the data uncompressed.
-+ '''
-+
-+ compress = self.attrs.get('compress')
-+
-+ # Compress JS, HTML, CSS and SVG files by default (gzip), unless |compress|
-+ # is explicitly specified.
-+ compress_by_default = (compress == 'default'
-+ and self.attrs.get('file').endswith(
-+ self._COMPRESS_BY_DEFAULT_EXTENSIONS))
-+
-+ if compress == 'gzip' or compress_by_default:
-+ # We only use rsyncable compression on Linux.
-+ # We exclude ChromeOS since ChromeOS bots are Linux based but do not have
-+ # the --rsyncable option built in for gzip. See crbug.com/617950.
-+ if sys.platform == 'linux2' and 'chromeos' not in self.GetRoot().defines:
-+ return grit.format.gzip_string.GzipStringRsyncable(data)
-+ return grit.format.gzip_string.GzipString(data)
-+
-+ if compress == 'brotli':
-+ # The length of the uncompressed data as 8 bytes little-endian.
-+ size_bytes = struct.pack("<q", len(data))
-+ data = brotli_util.BrotliCompress(data)
-+ # BROTLI_CONST is prepended to brotli decompressed data in order to
-+ # easily check if a resource has been brotli compressed.
-+ # The length of the uncompressed data is also appended to the start,
-+ # truncated to 6 bytes, little-endian. size_bytes is 8 bytes,
-+ # need to truncate further to 6.
-+ formatter = b'%ds %dx %ds' % (6, 2, len(size_bytes) - 8)
-+ return (constants.BROTLI_CONST +
-+ b''.join(struct.unpack(formatter, size_bytes)) +
-+ data)
-+
-+ if compress == 'false' or compress == 'default':
-+ return data
-+
-+ raise Exception('Invalid value for compression')
-+
-+
-+class ContentNode(Node):
-+ '''Convenience baseclass for nodes that can have content.'''
-+ def _ContentType(self):
-+ return self._CONTENT_TYPE_MIXED
-diff --git a/tools/grit/grit/node/base_unittest.py b/tools/grit/grit/node/base_unittest.py
-new file mode 100644
-index 0000000000..32a5a0ca59
---- /dev/null
-+++ b/tools/grit/grit/node/base_unittest.py
-@@ -0,0 +1,259 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for base.Node functionality (as used in various subclasses)'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import grd_reader
-+from grit import util
-+from grit.node import base
-+from grit.node import message
-+
-+
-+def MakePlaceholder(phname='BINGO'):
-+ ph = message.PhNode()
-+ ph.StartParsing(u'ph', None)
-+ ph.HandleAttribute(u'name', phname)
-+ ph.AppendContent(u'bongo')
-+ ph.EndParsing()
-+ return ph
-+
-+
-+class NodeUnittest(unittest.TestCase):
-+ def testWhitespaceHandling(self):
-+ # We test using the Message node type.
-+ node = message.MessageNode()
-+ node.StartParsing(u'hello', None)
-+ node.HandleAttribute(u'name', u'bla')
-+ node.AppendContent(u" ''' two spaces ")
-+ node.EndParsing()
-+ self.failUnless(node.GetCdata() == u' two spaces')
-+
-+ node = message.MessageNode()
-+ node.StartParsing(u'message', None)
-+ node.HandleAttribute(u'name', u'bla')
-+ node.AppendContent(u" two spaces ''' ")
-+ node.EndParsing()
-+ self.failUnless(node.GetCdata() == u'two spaces ')
-+
-+ def testWhitespaceHandlingWithChildren(self):
-+ # We test using the Message node type.
-+ node = message.MessageNode()
-+ node.StartParsing(u'message', None)
-+ node.HandleAttribute(u'name', u'bla')
-+ node.AppendContent(u" ''' two spaces ")
-+ node.AddChild(MakePlaceholder())
-+ node.AppendContent(u' space before and after ')
-+ node.AddChild(MakePlaceholder('BONGO'))
-+ node.AppendContent(u" space before two after '''")
-+ node.EndParsing()
-+ self.failUnless(node.mixed_content[0] == u' two spaces ')
-+ self.failUnless(node.mixed_content[2] == u' space before and after ')
-+ self.failUnless(node.mixed_content[-1] == u' space before two after ')
-+
-+ def testXmlFormatMixedContent(self):
-+ # Again test using the Message node type, because it is the only mixed
-+ # content node.
-+ node = message.MessageNode()
-+ node.StartParsing(u'message', None)
-+ node.HandleAttribute(u'name', u'name')
-+ node.AppendContent(u'Hello <young> ')
-+
-+ ph = message.PhNode()
-+ ph.StartParsing(u'ph', None)
-+ ph.HandleAttribute(u'name', u'USERNAME')
-+ ph.AppendContent(u'$1')
-+ ex = message.ExNode()
-+ ex.StartParsing(u'ex', None)
-+ ex.AppendContent(u'Joi')
-+ ex.EndParsing()
-+ ph.AddChild(ex)
-+ ph.EndParsing()
-+
-+ node.AddChild(ph)
-+ node.EndParsing()
-+
-+ non_indented_xml = node.FormatXml()
-+ self.failUnless(non_indented_xml == u'<message name="name">\n Hello '
-+ u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
-+ u'\n</message>')
-+
-+ indented_xml = node.FormatXml(u' ')
-+ self.failUnless(indented_xml == u' <message name="name">\n Hello '
-+ u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
-+ u'\n </message>')
-+
-+ def testXmlFormatMixedContentWithLeadingWhitespace(self):
-+ # Again test using the Message node type, because it is the only mixed
-+ # content node.
-+ node = message.MessageNode()
-+ node.StartParsing(u'message', None)
-+ node.HandleAttribute(u'name', u'name')
-+ node.AppendContent(u"''' Hello <young> ")
-+
-+ ph = message.PhNode()
-+ ph.StartParsing(u'ph', None)
-+ ph.HandleAttribute(u'name', u'USERNAME')
-+ ph.AppendContent(u'$1')
-+ ex = message.ExNode()
-+ ex.StartParsing(u'ex', None)
-+ ex.AppendContent(u'Joi')
-+ ex.EndParsing()
-+ ph.AddChild(ex)
-+ ph.EndParsing()
-+
-+ node.AddChild(ph)
-+ node.AppendContent(u" yessiree '''")
-+ node.EndParsing()
-+
-+ non_indented_xml = node.FormatXml()
-+ self.failUnless(non_indented_xml ==
-+ u"<message name=\"name\">\n ''' Hello"
-+ u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
-+ u" yessiree '''\n</message>")
-+
-+ indented_xml = node.FormatXml(u' ')
-+ self.failUnless(indented_xml ==
-+ u" <message name=\"name\">\n ''' Hello"
-+ u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
-+ u" yessiree '''\n </message>")
-+
-+ self.failUnless(node.GetNodeById('name'))
-+
-+ def testXmlFormatContentWithEntities(self):
-+ '''Tests a bug where &nbsp; would not be escaped correctly.'''
-+ from grit import tclib
-+ msg_node = message.MessageNode.Construct(None, tclib.Message(
-+ text = 'BEGIN_BOLDHelloWHITESPACEthere!END_BOLD Bingo!',
-+ placeholders = [
-+ tclib.Placeholder('BEGIN_BOLD', '<b>', 'bla'),
-+ tclib.Placeholder('WHITESPACE', '&nbsp;', 'bla'),
-+ tclib.Placeholder('END_BOLD', '</b>', 'bla')]),
-+ 'BINGOBONGO')
-+ xml = msg_node.FormatXml()
-+ self.failUnless(xml.find('&nbsp;') == -1, 'should have no entities')
-+
-+ def testIter(self):
-+ # First build a little tree of message and ph nodes.
-+ node = message.MessageNode()
-+ node.StartParsing(u'message', None)
-+ node.HandleAttribute(u'name', u'bla')
-+ node.AppendContent(u" ''' two spaces ")
-+ node.AppendContent(u' space before and after ')
-+ ph = message.PhNode()
-+ ph.StartParsing(u'ph', None)
-+ ph.AddChild(message.ExNode())
-+ ph.HandleAttribute(u'name', u'BINGO')
-+ ph.AppendContent(u'bongo')
-+ node.AddChild(ph)
-+ node.AddChild(message.PhNode())
-+ node.AppendContent(u" space before two after '''")
-+
-+ order = [message.MessageNode, message.PhNode, message.ExNode, message.PhNode]
-+ for n in node:
-+ self.failUnless(type(n) == order[0])
-+ order = order[1:]
-+ self.failUnless(len(order) == 0)
-+
-+ def testGetChildrenOfType(self):
-+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US"
-+ current_release="3" base_dir=".">
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="en/generated_resources.rc" type="rc_all"
-+ lang="en" />
-+ <if expr="pp_if('NOT_TRUE')">
-+ <output filename="de/generated_resources.rc" type="rc_all"
-+ lang="de" />
-+ </if>
-+ </outputs>
-+ <release seq="3">
-+ <messages>
-+ <message name="ID_HELLO">Hello!</message>
-+ </messages>
-+ </release>
-+ </grit>'''
-+ grd = grd_reader.Parse(StringIO(xml),
-+ util.PathFromRoot('grit/test/data'))
-+ from grit.node import node_io
-+ output_nodes = grd.GetChildrenOfType(node_io.OutputNode)
-+ self.failUnlessEqual(len(output_nodes), 3)
-+ self.failUnlessEqual(output_nodes[2].attrs['filename'],
-+ 'de/generated_resources.rc')
-+
-+ def testEvaluateExpression(self):
-+ def AssertExpr(expected_value, expr, defs, target_platform,
-+ extra_variables):
-+ self.failUnlessEqual(expected_value, base.Node.EvaluateExpression(
-+ expr, defs, target_platform, extra_variables))
-+
-+ AssertExpr(True, "True", {}, 'linux', {})
-+ AssertExpr(False, "False", {}, 'linux', {})
-+ AssertExpr(True, "True or False", {}, 'linux', {})
-+ AssertExpr(False, "True and False", {}, 'linux', {})
-+ AssertExpr(True, "os == 'linux'", {}, 'linux', {})
-+ AssertExpr(False, "os == 'linux'", {}, 'ios', {})
-+ AssertExpr(True, "'foo' in defs", {'foo': 'bar'}, 'ios', {})
-+ AssertExpr(False, "'foo' in defs", {'baz': 'bar'}, 'ios', {})
-+ AssertExpr(False, "'foo' in defs", {}, 'ios', {})
-+ AssertExpr(True, "is_linux", {}, 'linux2', {})
-+ AssertExpr(False, "is_linux", {}, 'win32', {})
-+ AssertExpr(True, "is_macosx", {}, 'darwin', {})
-+ AssertExpr(False, "is_macosx", {}, 'ios', {})
-+ AssertExpr(True, "is_win", {}, 'win32', {})
-+ AssertExpr(False, "is_win", {}, 'darwin', {})
-+ AssertExpr(True, "is_android", {}, 'android', {})
-+ AssertExpr(False, "is_android", {}, 'linux3', {})
-+ AssertExpr(True, "is_ios", {}, 'ios', {})
-+ AssertExpr(False, "is_ios", {}, 'darwin', {})
-+ AssertExpr(True, "is_posix", {}, 'linux2', {})
-+ AssertExpr(True, "is_posix", {}, 'darwin', {})
-+ AssertExpr(True, "is_posix", {}, 'android', {})
-+ AssertExpr(True, "is_posix", {}, 'ios', {})
-+ AssertExpr(True, "is_posix", {}, 'freebsd7', {})
-+ AssertExpr(False, "is_posix", {}, 'win32', {})
-+ AssertExpr(True, "pp_ifdef('foo')", {'foo': True}, 'win32', {})
-+ AssertExpr(True, "pp_ifdef('foo')", {'foo': False}, 'win32', {})
-+ AssertExpr(False, "pp_ifdef('foo')", {'bar': True}, 'win32', {})
-+ AssertExpr(True, "pp_if('foo')", {'foo': True}, 'win32', {})
-+ AssertExpr(False, "pp_if('foo')", {'foo': False}, 'win32', {})
-+ AssertExpr(False, "pp_if('foo')", {'bar': True}, 'win32', {})
-+ AssertExpr(True, "foo", {'foo': True}, 'win32', {})
-+ AssertExpr(False, "foo", {'foo': False}, 'win32', {})
-+ AssertExpr(False, "foo", {'bar': True}, 'win32', {})
-+ AssertExpr(True, "foo == 'baz'", {'foo': 'baz'}, 'win32', {})
-+ AssertExpr(False, "foo == 'baz'", {'foo': True}, 'win32', {})
-+ AssertExpr(False, "foo == 'baz'", {}, 'win32', {})
-+ AssertExpr(True, "lang == 'de'", {}, 'win32', {'lang': 'de'})
-+ AssertExpr(False, "lang == 'de'", {}, 'win32', {'lang': 'fr'})
-+ AssertExpr(False, "lang == 'de'", {}, 'win32', {})
-+
-+ # Test a couple more complex expressions for good measure.
-+ AssertExpr(True, "is_ios and (lang in ['de', 'fr'] or foo)",
-+ {'foo': 'bar'}, 'ios', {'lang': 'fr', 'context': 'today'})
-+ AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)",
-+ {'foo': False}, 'linux2', {'lang': 'fr', 'context': 'today'})
-+ AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)",
-+ {'baz': 'bar'}, 'ios', {'lang': 'he', 'context': 'today'})
-+ AssertExpr(True, "foo == 'bar' or not baz",
-+ {'foo': 'bar', 'fun': True}, 'ios', {'lang': 'en'})
-+ AssertExpr(True, "foo == 'bar' or not baz",
-+ {}, 'ios', {'lang': 'en', 'context': 'java'})
-+ AssertExpr(False, "foo == 'bar' or not baz",
-+ {'foo': 'ruz', 'baz': True}, 'ios', {'lang': 'en'})
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/brotli_util.py b/tools/grit/grit/node/brotli_util.py
-new file mode 100644
-index 0000000000..77f70e49d5
---- /dev/null
-+++ b/tools/grit/grit/node/brotli_util.py
-@@ -0,0 +1,29 @@
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Framework for compressing resources using Brotli."""
-+
-+import subprocess
-+
-+__brotli_executable = None
-+
-+
-+def SetBrotliCommand(brotli):
-+ # brotli is a list. In production it contains the path to the Brotli executable.
-+ # During testing it contains [python, mock_brotli.py] for testing on Windows.
-+ global __brotli_executable
-+ __brotli_executable = brotli
-+
-+
-+def BrotliCompress(data):
-+ if not __brotli_executable:
-+ raise Exception('Add "use_brotli = true" to you GN grit(...) target ' +
-+ 'if you want to use brotli.')
-+ compress = subprocess.Popen(__brotli_executable + ['-', '-f'],
-+ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
-+ return compress.communicate(data)[0]
-+
-+def IsInitialized():
-+ global __brotli_executable
-+ return __brotli_executable is not None
-diff --git a/tools/grit/grit/node/custom/__init__.py b/tools/grit/grit/node/custom/__init__.py
-new file mode 100644
-index 0000000000..e179cf7730
---- /dev/null
-+++ b/tools/grit/grit/node/custom/__init__.py
-@@ -0,0 +1,8 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Package 'grit.node.custom'
-+'''
-+
-+pass
-diff --git a/tools/grit/grit/node/custom/filename.py b/tools/grit/grit/node/custom/filename.py
-new file mode 100644
-index 0000000000..55a27e58c1
---- /dev/null
-+++ b/tools/grit/grit/node/custom/filename.py
-@@ -0,0 +1,29 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''A CustomType for filenames.'''
-+
-+from __future__ import print_function
-+
-+from grit import clique
-+from grit import lazy_re
-+
-+
-+class WindowsFilename(clique.CustomType):
-+ '''Validates that messages can be used as Windows filenames, and strips
-+ illegal characters out of translations.
-+ '''
-+
-+ BANNED = lazy_re.compile(r'\+|:|\/|\\\\|\*|\?|\"|\<|\>|\|')
-+
-+ def Validate(self, message):
-+ return not self.BANNED.search(message.GetPresentableContent())
-+
-+ def ValidateAndModify(self, lang, translation):
-+ is_ok = self.Validate(translation)
-+ self.ModifyEachTextPart(lang, translation)
-+ return is_ok
-+
-+ def ModifyTextPart(self, lang, text):
-+ return self.BANNED.sub(' ', text)
-diff --git a/tools/grit/grit/node/custom/filename_unittest.py b/tools/grit/grit/node/custom/filename_unittest.py
-new file mode 100644
-index 0000000000..8e2a6dd64a
---- /dev/null
-+++ b/tools/grit/grit/node/custom/filename_unittest.py
-@@ -0,0 +1,34 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.node.custom.filename'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../..'))
-+
-+import unittest
-+from grit.node.custom import filename
-+from grit import clique
-+from grit import tclib
-+
-+
-+class WindowsFilenameUnittest(unittest.TestCase):
-+
-+ def testValidate(self):
-+ factory = clique.UberClique()
-+ msg = tclib.Message(text='Bingo bongo')
-+ c = factory.MakeClique(msg)
-+ c.SetCustomType(filename.WindowsFilename())
-+ translation = tclib.Translation(id=msg.GetId(), text='Bilingo bolongo:')
-+ c.AddTranslation(translation, 'fr')
-+ self.failUnless(c.MessageForLanguage('fr').GetRealContent() == 'Bilingo bolongo ')
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/empty.py b/tools/grit/grit/node/empty.py
-new file mode 100644
-index 0000000000..e19d2c4ddb
---- /dev/null
-+++ b/tools/grit/grit/node/empty.py
-@@ -0,0 +1,64 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Container nodes that don't have any logic.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit.node import base
-+from grit.node import include
-+from grit.node import message
-+from grit.node import misc
-+from grit.node import node_io
-+from grit.node import structure
-+
-+
-+class GroupingNode(base.Node):
-+ '''Base class for all the grouping elements (<structures>, <includes>,
-+ <messages> and <identifiers>).'''
-+ def DefaultAttributes(self):
-+ return {
-+ 'first_id' : '',
-+ 'comment' : '',
-+ 'fallback_to_english' : 'false',
-+ 'fallback_to_low_resolution' : 'false',
-+ }
-+
-+
-+class IncludesNode(GroupingNode):
-+ '''The <includes> element.'''
-+ def _IsValidChild(self, child):
-+ return isinstance(child, (include.IncludeNode, misc.IfNode, misc.PartNode))
-+
-+
-+class MessagesNode(GroupingNode):
-+ '''The <messages> element.'''
-+ def _IsValidChild(self, child):
-+ return isinstance(child, (message.MessageNode, misc.IfNode, misc.PartNode))
-+
-+
-+class StructuresNode(GroupingNode):
-+ '''The <structures> element.'''
-+ def _IsValidChild(self, child):
-+ return isinstance(child, (structure.StructureNode,
-+ misc.IfNode, misc.PartNode))
-+
-+
-+class TranslationsNode(base.Node):
-+ '''The <translations> element.'''
-+ def _IsValidChild(self, child):
-+ return isinstance(child, (node_io.FileNode, misc.IfNode, misc.PartNode))
-+
-+
-+class OutputsNode(base.Node):
-+ '''The <outputs> element.'''
-+ def _IsValidChild(self, child):
-+ return isinstance(child, (node_io.OutputNode, misc.IfNode, misc.PartNode))
-+
-+
-+class IdentifiersNode(GroupingNode):
-+ '''The <identifiers> element.'''
-+ def _IsValidChild(self, child):
-+ return isinstance(child, misc.IdentifierNode)
-diff --git a/tools/grit/grit/node/include.py b/tools/grit/grit/node/include.py
-new file mode 100644
-index 0000000000..b06b9889bb
---- /dev/null
-+++ b/tools/grit/grit/node/include.py
-@@ -0,0 +1,170 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Handling of the <include> element.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+
-+from grit import util
-+import grit.format.html_inline
-+import grit.format.rc
-+from grit.format import minifier
-+from grit.node import base
-+
-+class IncludeNode(base.Node):
-+ """An <include> element."""
-+
-+ def __init__(self):
-+ super(IncludeNode, self).__init__()
-+
-+ # Cache flattened data so that we don't flatten the same file
-+ # multiple times.
-+ self._flattened_data = None
-+ # Also keep track of the last filename we flattened to, so we can
-+ # avoid doing it more than once.
-+ self._last_flat_filename = None
-+
-+ def _IsValidChild(self, child):
-+ return False
-+
-+ def _GetFlattenedData(
-+ self, allow_external_script=False, preprocess_only=False):
-+ if not self._flattened_data:
-+ filename = self.ToRealPath(self.GetInputPath())
-+ self._flattened_data = (
-+ grit.format.html_inline.InlineToString(filename, self,
-+ preprocess_only=preprocess_only,
-+ allow_external_script=allow_external_script))
-+ return self._flattened_data.encode('utf-8')
-+
-+ def MandatoryAttributes(self):
-+ return ['name', 'type', 'file']
-+
-+ def DefaultAttributes(self):
-+ """Attributes:
-+ translateable: False if the node has contents that should not be
-+ translated.
-+ preprocess: Takes the same code path as flattenhtml, but it
-+ disables any processing/inlining outside of <if>
-+ and <include>.
-+ compress: The format to compress the data with, e.g. 'gzip'
-+ or 'false' if data should not be compressed.
-+ skip_minify: If true, skips minifying the node's contents.
-+ skip_in_resource_map: If true, do not add to the resource map.
-+ """
-+ return {
-+ 'translateable': 'true',
-+ 'generateid': 'true',
-+ 'filenameonly': 'false',
-+ 'mkoutput': 'false',
-+ 'preprocess': 'false',
-+ 'flattenhtml': 'false',
-+ 'compress': 'default',
-+ 'allowexternalscript': 'false',
-+ 'relativepath': 'false',
-+ 'use_base_dir': 'true',
-+ 'skip_minify': 'false',
-+ 'skip_in_resource_map': 'false',
-+ }
-+
-+ def GetInputPath(self):
-+ # Do not mess with absolute paths, that would make them invalid.
-+ if os.path.isabs(os.path.expandvars(self.attrs['file'])):
-+ return self.attrs['file']
-+
-+ # We have no control over code that calls ToRealPath later, so convert
-+ # the path to be relative against our basedir.
-+ if self.attrs.get('use_base_dir', 'true') != 'true':
-+ # Normalize the directory path to use the appropriate OS separator.
-+ # GetBaseDir() may return paths\like\this or paths/like/this, since it is
-+ # read from the base_dir attribute in the grd file.
-+ norm_base_dir = util.normpath(self.GetRoot().GetBaseDir())
-+ return os.path.relpath(self.attrs['file'], norm_base_dir)
-+
-+ return self.attrs['file']
-+
-+ def FileForLanguage(self, lang, output_dir):
-+ """Returns the file for the specified language. This allows us to return
-+ different files for different language variants of the include file.
-+ """
-+ input_path = self.GetInputPath()
-+ if input_path is None:
-+ return None
-+
-+ return self.ToRealPath(input_path)
-+
-+ def GetDataPackValue(self, lang, encoding):
-+ '''Returns bytes or a str represenation for a data_pack entry.'''
-+ filename = self.ToRealPath(self.GetInputPath())
-+ if self.attrs['flattenhtml'] == 'true':
-+ allow_external_script = self.attrs['allowexternalscript'] == 'true'
-+ data = self._GetFlattenedData(allow_external_script=allow_external_script)
-+ elif self.attrs['preprocess'] == 'true':
-+ data = self._GetFlattenedData(preprocess_only=True)
-+ else:
-+ data = util.ReadFile(filename, util.BINARY)
-+
-+ if self.attrs['skip_minify'] != 'true':
-+ # Note that the minifier will only do anything if a minifier command
-+ # has been set in the command line.
-+ data = minifier.Minify(data, filename)
-+
-+ # Include does not care about the encoding, because it only returns binary
-+ # data.
-+ return self.CompressDataIfNeeded(data)
-+
-+ def Process(self, output_dir):
-+ """Rewrite file references to be base64 encoded data URLs. The new file
-+ will be written to output_dir and the name of the new file is returned."""
-+ filename = self.ToRealPath(self.GetInputPath())
-+ flat_filename = os.path.join(output_dir,
-+ self.attrs['name'] + '_' + os.path.basename(filename))
-+
-+ if self._last_flat_filename == flat_filename:
-+ return
-+
-+ with open(flat_filename, 'wb') as outfile:
-+ outfile.write(self._GetFlattenedData())
-+
-+ self._last_flat_filename = flat_filename
-+ return os.path.basename(flat_filename)
-+
-+ def GetHtmlResourceFilenames(self):
-+ """Returns a set of all filenames inlined by this file."""
-+ allow_external_script = self.attrs['allowexternalscript'] == 'true'
-+ return grit.format.html_inline.GetResourceFilenames(
-+ self.ToRealPath(self.GetInputPath()),
-+ self,
-+ allow_external_script=allow_external_script)
-+
-+ def IsResourceMapSource(self):
-+ skip = self.attrs.get('skip_in_resource_map', 'false') == 'true'
-+ return not skip
-+
-+ @staticmethod
-+ def Construct(parent, name, type, file, translateable=True,
-+ filenameonly=False, mkoutput=False, relativepath=False):
-+ """Creates a new node which is a child of 'parent', with attributes set
-+ by parameters of the same name.
-+ """
-+ # Convert types to appropriate strings
-+ translateable = util.BoolToString(translateable)
-+ filenameonly = util.BoolToString(filenameonly)
-+ mkoutput = util.BoolToString(mkoutput)
-+ relativepath = util.BoolToString(relativepath)
-+
-+ node = IncludeNode()
-+ node.StartParsing('include', parent)
-+ node.HandleAttribute('name', name)
-+ node.HandleAttribute('type', type)
-+ node.HandleAttribute('file', file)
-+ node.HandleAttribute('translateable', translateable)
-+ node.HandleAttribute('filenameonly', filenameonly)
-+ node.HandleAttribute('mkoutput', mkoutput)
-+ node.HandleAttribute('relativepath', relativepath)
-+ node.EndParsing()
-+ return node
-diff --git a/tools/grit/grit/node/include_unittest.py b/tools/grit/grit/node/include_unittest.py
-new file mode 100644
-index 0000000000..4c658f1ffe
---- /dev/null
-+++ b/tools/grit/grit/node/include_unittest.py
-@@ -0,0 +1,134 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for include.IncludeNode'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import unittest
-+import zlib
-+
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+from grit.node import misc
-+from grit.node import include
-+from grit.node import empty
-+from grit import util
-+
-+
-+def checkIsGzipped(filename, compress_attr):
-+ test_data_root = util.PathFromRoot('grit/testdata')
-+ root = util.ParseGrdForUnittest(
-+ '''
-+ <includes>
-+ <include name="TEST_TXT" file="%s" %s type="BINDATA"/>
-+ </includes>''' % (filename, compress_attr),
-+ base_dir=test_data_root)
-+ node, = root.GetChildrenOfType(include.IncludeNode)
-+ compressed = node.GetDataPackValue(lang='en', encoding=util.BINARY)
-+
-+ decompressed_data = zlib.decompress(compressed, 16 + zlib.MAX_WBITS)
-+ expected = util.ReadFile(os.path.join(test_data_root, filename), util.BINARY)
-+ return expected == decompressed_data
-+
-+
-+class IncludeNodeUnittest(unittest.TestCase):
-+ def testGetPath(self):
-+ root = misc.GritNode()
-+ root.StartParsing(u'grit', None)
-+ root.HandleAttribute(u'latest_public_release', u'0')
-+ root.HandleAttribute(u'current_release', u'1')
-+ root.HandleAttribute(u'base_dir', r'..\resource')
-+ release = misc.ReleaseNode()
-+ release.StartParsing(u'release', root)
-+ release.HandleAttribute(u'seq', u'1')
-+ root.AddChild(release)
-+ includes = empty.IncludesNode()
-+ includes.StartParsing(u'includes', release)
-+ release.AddChild(includes)
-+ include_node = include.IncludeNode()
-+ include_node.StartParsing(u'include', includes)
-+ include_node.HandleAttribute(u'file', r'flugel\kugel.pdf')
-+ includes.AddChild(include_node)
-+ root.EndParsing()
-+
-+ self.assertEqual(root.ToRealPath(include_node.GetInputPath()),
-+ util.normpath(
-+ os.path.join(r'../resource', r'flugel/kugel.pdf')))
-+
-+ def testGetPathNoBasedir(self):
-+ root = misc.GritNode()
-+ root.StartParsing(u'grit', None)
-+ root.HandleAttribute(u'latest_public_release', u'0')
-+ root.HandleAttribute(u'current_release', u'1')
-+ root.HandleAttribute(u'base_dir', r'..\resource')
-+ release = misc.ReleaseNode()
-+ release.StartParsing(u'release', root)
-+ release.HandleAttribute(u'seq', u'1')
-+ root.AddChild(release)
-+ includes = empty.IncludesNode()
-+ includes.StartParsing(u'includes', release)
-+ release.AddChild(includes)
-+ include_node = include.IncludeNode()
-+ include_node.StartParsing(u'include', includes)
-+ include_node.HandleAttribute(u'file', r'flugel\kugel.pdf')
-+ include_node.HandleAttribute(u'use_base_dir', u'false')
-+ includes.AddChild(include_node)
-+ root.EndParsing()
-+
-+ last_dir = os.path.basename(os.getcwd())
-+ expected_path = util.normpath(os.path.join(
-+ u'..', last_dir, u'flugel/kugel.pdf'))
-+ self.assertEqual(root.ToRealPath(include_node.GetInputPath()),
-+ expected_path)
-+
-+ def testCompressGzip(self):
-+ self.assertTrue(checkIsGzipped('test_text.txt', 'compress="gzip"'))
-+
-+ def testCompressGzipByDefault(self):
-+ self.assertTrue(checkIsGzipped('test_html.html', ''))
-+ self.assertTrue(checkIsGzipped('test_js.js', ''))
-+ self.assertTrue(checkIsGzipped('test_css.css', ''))
-+ self.assertTrue(checkIsGzipped('test_svg.svg', ''))
-+
-+ self.assertTrue(checkIsGzipped('test_html.html', 'compress="default"'))
-+ self.assertTrue(checkIsGzipped('test_js.js', 'compress="default"'))
-+ self.assertTrue(checkIsGzipped('test_css.css', 'compress="default"'))
-+ self.assertTrue(checkIsGzipped('test_svg.svg', 'compress="default"'))
-+
-+ def testSkipInResourceMap(self):
-+ root = util.ParseGrdForUnittest('''
-+ <includes>
-+ <include name="TEST1_TXT" file="test1_text.txt" type="BINDATA"/>
-+ <include name="TEST2_TXT" file="test1_text.txt" type="BINDATA"
-+ skip_in_resource_map="true"/>
-+ <include name="TEST3_TXT" file="test1_text.txt" type="BINDATA"
-+ skip_in_resource_map="false"/>
-+ </includes>''', base_dir = util.PathFromRoot('grit/testdata'))
-+ inc = root.GetChildrenOfType(include.IncludeNode)
-+ self.assertTrue(inc[0].IsResourceMapSource())
-+ self.assertFalse(inc[1].IsResourceMapSource())
-+ self.assertTrue(inc[2].IsResourceMapSource())
-+
-+ def testAcceptsPreprocess(self):
-+ root = util.ParseGrdForUnittest(
-+ '''
-+ <includes>
-+ <include name="PREPROCESS_TEST" file="preprocess_test.html"
-+ preprocess="true" compress="false" type="chrome_html"/>
-+ </includes>''',
-+ base_dir=util.PathFromRoot('grit/testdata'))
-+ inc, = root.GetChildrenOfType(include.IncludeNode)
-+ result = inc.GetDataPackValue(lang='en', encoding=util.BINARY)
-+ self.assertIn(b'should be kept', result)
-+ self.assertIn(b'in the middle...', result)
-+ self.assertNotIn(b'should be removed', result)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/mapping.py b/tools/grit/grit/node/mapping.py
-new file mode 100644
-index 0000000000..6297f0b666
---- /dev/null
-+++ b/tools/grit/grit/node/mapping.py
-@@ -0,0 +1,60 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Maps each node type to an implementation class.
-+When adding a new node type, you add to this mapping.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit import exception
-+
-+from grit.node import empty
-+from grit.node import include
-+from grit.node import message
-+from grit.node import misc
-+from grit.node import node_io
-+from grit.node import structure
-+from grit.node import variant
-+
-+
-+_ELEMENT_TO_CLASS = {
-+ 'identifiers' : empty.IdentifiersNode,
-+ 'includes' : empty.IncludesNode,
-+ 'messages' : empty.MessagesNode,
-+ 'outputs' : empty.OutputsNode,
-+ 'structures' : empty.StructuresNode,
-+ 'translations' : empty.TranslationsNode,
-+ 'include' : include.IncludeNode,
-+ 'emit' : node_io.EmitNode,
-+ 'file' : node_io.FileNode,
-+ 'output' : node_io.OutputNode,
-+ 'ex' : message.ExNode,
-+ 'message' : message.MessageNode,
-+ 'ph' : message.PhNode,
-+ 'else' : misc.ElseNode,
-+ 'grit' : misc.GritNode,
-+ 'identifier' : misc.IdentifierNode,
-+ 'if' : misc.IfNode,
-+ 'part' : misc.PartNode,
-+ 'release' : misc.ReleaseNode,
-+ 'then' : misc.ThenNode,
-+ 'structure' : structure.StructureNode,
-+ 'skeleton' : variant.SkeletonNode,
-+}
-+
-+
-+def ElementToClass(name, typeattr):
-+ '''Maps an element to a class that handles the element.
-+
-+ Args:
-+ name: 'element' (the name of the element)
-+ typeattr: 'type' (the value of the type attribute, if present, else None)
-+
-+ Return:
-+ type
-+ '''
-+ if name not in _ELEMENT_TO_CLASS:
-+ raise exception.UnknownElement()
-+ return _ELEMENT_TO_CLASS[name]
-diff --git a/tools/grit/grit/node/message.py b/tools/grit/grit/node/message.py
-new file mode 100644
-index 0000000000..4fa83cf26b
---- /dev/null
-+++ b/tools/grit/grit/node/message.py
-@@ -0,0 +1,362 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Handling of the <message> element.
-+'''
-+
-+from __future__ import print_function
-+
-+import re
-+
-+import six
-+
-+from grit.node import base
-+
-+from grit import clique
-+from grit import exception
-+from grit import lazy_re
-+from grit import tclib
-+from grit import util
-+
-+
-+# Matches exactly three dots ending a line or followed by whitespace.
-+_ELLIPSIS_PATTERN = lazy_re.compile(r'(?<!\.)\.\.\.(?=$|\s)')
-+_ELLIPSIS_SYMBOL = u'\u2026' # Ellipsis
-+
-+# Finds whitespace at the start and end of a string which can be multiline.
-+_WHITESPACE = lazy_re.compile(r'(?P<start>\s*)(?P<body>.+?)(?P<end>\s*)\Z',
-+ re.DOTALL | re.MULTILINE)
-+
-+# <ph> placeholder elements should contain the special character formatters
-+# used to format <ph> element content.
-+# Android format.
-+_ANDROID_FORMAT = (r'%[1-9]+\$'
-+ r'([-#+ 0,(]*)([0-9]+)?(\.[0-9]+)?'
-+ r'([bBhHsScCdoxXeEfgGaAtT%n])')
-+# Chrome l10n format.
-+_CHROME_FORMAT = r'\$+\d'
-+# Windows EWT numeric and GRIT %s %d formats.
-+_OTHER_FORMAT = r'%[0-9sd]'
-+
-+# Finds formatters that must be in a placeholder (<ph>) element.
-+_FORMATTERS = lazy_re.compile(
-+ '(%s)|(%s)|(%s)' % (_ANDROID_FORMAT, _CHROME_FORMAT, _OTHER_FORMAT))
-+_BAD_PLACEHOLDER_MSG = ('ERROR: Placeholder formatter found outside of <ph> '
-+ 'tag in message "%s" in %s.')
-+_INVALID_PH_CHAR_MSG = ('ERROR: Invalid format characters found in message '
-+ '"%s" <ph> tag in %s.')
-+
-+# Finds HTML tag tokens.
-+_HTMLTOKEN = lazy_re.compile(r'<[/]?[a-z][a-z0-9]*[^>]*>', re.I)
-+
-+# Finds HTML entities.
-+_HTMLENTITY = lazy_re.compile(r'&[^\s]*;')
-+
-+
-+class MessageNode(base.ContentNode):
-+ '''A <message> element.'''
-+
-+ # For splitting a list of things that can be separated by commas or
-+ # whitespace
-+ _SPLIT_RE = lazy_re.compile(r'\s*,\s*|\s+')
-+
-+ def __init__(self):
-+ super(MessageNode, self).__init__()
-+ # Valid after EndParsing, this is the MessageClique that contains the
-+ # source message and any translations of it that have been loaded.
-+ self.clique = None
-+
-+ # We don't send leading and trailing whitespace into the translation
-+ # console, but rather tack it onto the source message and any
-+ # translations when formatting them into RC files or what have you.
-+ self.ws_at_start = '' # Any whitespace characters at the start of the text
-+ self.ws_at_end = '' # --"-- at the end of the text
-+
-+ # A list of "shortcut groups" this message is in. We check to make sure
-+ # that shortcut keys (e.g. &J) within each shortcut group are unique.
-+ self.shortcut_groups_ = []
-+
-+ # Formatter-specific data used to control the output of individual strings.
-+ # formatter_data is a space separated list of C preprocessor-style
-+ # definitions. Names without values are given the empty string value.
-+ # Example: "foo=5 bar baz=100"
-+ self.formatter_data = {}
-+
-+ # Whether or not to convert ... -> U+2026 within Translate().
-+ self._replace_ellipsis = False
-+
-+ def _IsValidChild(self, child):
-+ return isinstance(child, (PhNode))
-+
-+ def _IsValidAttribute(self, name, value):
-+ if name not in [
-+ 'name', 'offset', 'translateable', 'desc', 'meaning',
-+ 'internal_comment', 'shortcut_groups', 'custom_type', 'validation_expr',
-+ 'use_name_for_id', 'sub_variable', 'formatter_data',
-+ 'is_accessibility_with_no_ui'
-+ ]:
-+ return False
-+ if (name in ('translateable', 'sub_variable') and
-+ value not in ['true', 'false']):
-+ return False
-+ return True
-+
-+ def SetReplaceEllipsis(self, value):
-+ r'''Sets whether to replace ... with \u2026.
-+ '''
-+ self._replace_ellipsis = value
-+
-+ def MandatoryAttributes(self):
-+ return ['name|offset']
-+
-+ def DefaultAttributes(self):
-+ return {
-+ 'custom_type': '',
-+ 'desc': '',
-+ 'formatter_data': '',
-+ 'internal_comment': '',
-+ 'is_accessibility_with_no_ui': 'false',
-+ 'meaning': '',
-+ 'shortcut_groups': '',
-+ 'sub_variable': 'false',
-+ 'translateable': 'true',
-+ 'use_name_for_id': 'false',
-+ 'validation_expr': '',
-+ }
-+
-+ def HandleAttribute(self, attrib, value):
-+ base.ContentNode.HandleAttribute(self, attrib, value)
-+ if attrib != 'formatter_data':
-+ return
-+
-+ # Parse value, a space-separated list of defines, into a dict.
-+ # Example: "foo=5 bar" -> {'foo':'5', 'bar':''}
-+ for item in value.split():
-+ name, _, val = item.partition('=')
-+ self.formatter_data[name] = val
-+
-+ def GetTextualIds(self):
-+ '''
-+ Returns the concatenation of the parent's node first_id and
-+ this node's offset if it has one, otherwise just call the
-+ superclass' implementation
-+ '''
-+ if 'offset' not in self.attrs:
-+ return super(MessageNode, self).GetTextualIds()
-+
-+ # we search for the first grouping node in the parents' list
-+ # to take care of the case where the first parent is an <if> node
-+ grouping_parent = self.parent
-+ import grit.node.empty
-+ while grouping_parent and not isinstance(grouping_parent,
-+ grit.node.empty.GroupingNode):
-+ grouping_parent = grouping_parent.parent
-+
-+ assert 'first_id' in grouping_parent.attrs
-+ return [grouping_parent.attrs['first_id'] + '_' + self.attrs['offset']]
-+
-+ def IsTranslateable(self):
-+ return self.attrs['translateable'] == 'true'
-+
-+ def EndParsing(self):
-+ super(MessageNode, self).EndParsing()
-+
-+ # Make the text (including placeholder references) and list of placeholders,
-+ # verify placeholder formats, then strip and store leading and trailing
-+ # whitespace and create the tclib.Message() and a clique to contain it.
-+
-+ text = ''
-+ placeholders = []
-+
-+ for item in self.mixed_content:
-+ if isinstance(item, six.string_types):
-+ # Not a <ph> element: fail if any <ph> formatters are detected.
-+ if _FORMATTERS.search(item):
-+ print(_BAD_PLACEHOLDER_MSG % (item, self.source))
-+ raise exception.PlaceholderNotInsidePhNode
-+ text += item
-+ else:
-+ # Extract the <ph> element components.
-+ presentation = item.attrs['name'].upper()
-+ text += presentation
-+ ex = ' ' # <ex> example element cdata if present.
-+ if len(item.children):
-+ ex = item.children[0].GetCdata()
-+ original = item.GetCdata()
-+
-+ # Sanity check the <ph> element content.
-+ cdata = original
-+ # Replace all HTML tag tokens in cdata.
-+ match = _HTMLTOKEN.search(cdata)
-+ while match:
-+ cdata = cdata.replace(match.group(0), '_')
-+ match = _HTMLTOKEN.search(cdata)
-+ # Replace all HTML entities in cdata.
-+ match = _HTMLENTITY.search(cdata)
-+ while match:
-+ cdata = cdata.replace(match.group(0), '_')
-+ match = _HTMLENTITY.search(cdata)
-+ # Remove first matching formatter from cdata.
-+ match = _FORMATTERS.search(cdata)
-+ if match:
-+ cdata = cdata.replace(match.group(0), '')
-+ # Fail if <ph> special chars remain in cdata.
-+ if re.search(r'[%\$]', cdata):
-+ message_id = self.attrs['name'] + ' ' + original;
-+ print(_INVALID_PH_CHAR_MSG % (message_id, self.source))
-+ raise exception.InvalidCharactersInsidePhNode
-+
-+ # Otherwise, accept this <ph> placeholder.
-+ placeholders.append(tclib.Placeholder(presentation, original, ex))
-+
-+ m = _WHITESPACE.match(text)
-+ if m:
-+ self.ws_at_start = m.group('start')
-+ self.ws_at_end = m.group('end')
-+ text = m.group('body')
-+
-+ self.shortcut_groups_ = self._SPLIT_RE.split(self.attrs['shortcut_groups'])
-+ self.shortcut_groups_ = [i for i in self.shortcut_groups_ if i != '']
-+
-+ description_or_id = self.attrs['desc']
-+ if description_or_id == '' and 'name' in self.attrs:
-+ description_or_id = 'ID: %s' % self.attrs['name']
-+
-+ assigned_id = None
-+ if self.attrs['use_name_for_id'] == 'true':
-+ assigned_id = self.attrs['name']
-+ message = tclib.Message(text=text, placeholders=placeholders,
-+ description=description_or_id,
-+ meaning=self.attrs['meaning'],
-+ assigned_id=assigned_id)
-+ self.InstallMessage(message)
-+
-+ def InstallMessage(self, message):
-+ '''Sets this node's clique from a tclib.Message instance.
-+
-+ Args:
-+ message: A tclib.Message.
-+ '''
-+ self.clique = self.UberClique().MakeClique(message, self.IsTranslateable())
-+ for group in self.shortcut_groups_:
-+ self.clique.AddToShortcutGroup(group)
-+ if self.attrs['custom_type'] != '':
-+ self.clique.SetCustomType(util.NewClassInstance(self.attrs['custom_type'],
-+ clique.CustomType))
-+ elif self.attrs['validation_expr'] != '':
-+ self.clique.SetCustomType(
-+ clique.OneOffCustomType(self.attrs['validation_expr']))
-+
-+ def SubstituteMessages(self, substituter):
-+ '''Applies substitution to this message.
-+
-+ Args:
-+ substituter: a grit.util.Substituter object.
-+ '''
-+ message = substituter.SubstituteMessage(self.clique.GetMessage())
-+ if message is not self.clique.GetMessage():
-+ self.InstallMessage(message)
-+
-+ def GetCliques(self):
-+ return [self.clique] if self.clique else []
-+
-+ def Translate(self, lang):
-+ '''Returns a translated version of this message.
-+ '''
-+ assert self.clique
-+ msg = self.clique.MessageForLanguage(lang,
-+ self.PseudoIsAllowed(),
-+ self.ShouldFallbackToEnglish()
-+ ).GetRealContent()
-+ if self._replace_ellipsis:
-+ msg = _ELLIPSIS_PATTERN.sub(_ELLIPSIS_SYMBOL, msg)
-+ # Always remove all byte order marks (\uFEFF) https://crbug.com/1033305
-+ msg = msg.replace(u'\uFEFF','')
-+ return msg.replace('[GRITLANGCODE]', lang)
-+
-+ def NameOrOffset(self):
-+ key = 'name' if 'name' in self.attrs else 'offset'
-+ return self.attrs[key]
-+
-+ def ExpandVariables(self):
-+ '''We always expand variables on Messages.'''
-+ return True
-+
-+ def GetDataPackValue(self, lang, encoding):
-+ '''Returns a str represenation for a data_pack entry.'''
-+ message = self.ws_at_start + self.Translate(lang) + self.ws_at_end
-+ return util.Encode(message, encoding)
-+
-+ def IsResourceMapSource(self):
-+ return True
-+
-+ @staticmethod
-+ def Construct(parent, message, name, desc='', meaning='', translateable=True):
-+ '''Constructs a new message node that is a child of 'parent', with the
-+ name, desc, meaning and translateable attributes set using the same-named
-+ parameters and the text of the message and any placeholders taken from
-+ 'message', which must be a tclib.Message() object.'''
-+ # Convert type to appropriate string
-+ translateable = 'true' if translateable else 'false'
-+
-+ node = MessageNode()
-+ node.StartParsing('message', parent)
-+ node.HandleAttribute('name', name)
-+ node.HandleAttribute('desc', desc)
-+ node.HandleAttribute('meaning', meaning)
-+ node.HandleAttribute('translateable', translateable)
-+
-+ items = message.GetContent()
-+ for ix, item in enumerate(items):
-+ if isinstance(item, six.string_types):
-+ # Ensure whitespace at front and back of message is correctly handled.
-+ if ix == 0:
-+ item = "'''" + item
-+ if ix == len(items) - 1:
-+ item = item + "'''"
-+
-+ node.AppendContent(item)
-+ else:
-+ phnode = PhNode()
-+ phnode.StartParsing('ph', node)
-+ phnode.HandleAttribute('name', item.GetPresentation())
-+ phnode.AppendContent(item.GetOriginal())
-+
-+ if len(item.GetExample()) and item.GetExample() != ' ':
-+ exnode = ExNode()
-+ exnode.StartParsing('ex', phnode)
-+ exnode.AppendContent(item.GetExample())
-+ exnode.EndParsing()
-+ phnode.AddChild(exnode)
-+
-+ phnode.EndParsing()
-+ node.AddChild(phnode)
-+
-+ node.EndParsing()
-+ return node
-+
-+
-+class PhNode(base.ContentNode):
-+ '''A <ph> element.'''
-+
-+ def _IsValidChild(self, child):
-+ return isinstance(child, ExNode)
-+
-+ def MandatoryAttributes(self):
-+ return ['name']
-+
-+ def EndParsing(self):
-+ super(PhNode, self).EndParsing()
-+ # We only allow a single example for each placeholder
-+ if len(self.children) > 1:
-+ raise exception.TooManyExamples()
-+
-+ def GetTextualIds(self):
-+ # The 'name' attribute is not an ID.
-+ return []
-+
-+
-+class ExNode(base.ContentNode):
-+ '''An <ex> element.'''
-+ pass
-diff --git a/tools/grit/grit/node/message_unittest.py b/tools/grit/grit/node/message_unittest.py
-new file mode 100644
-index 0000000000..7a4cbbedc2
---- /dev/null
-+++ b/tools/grit/grit/node/message_unittest.py
-@@ -0,0 +1,380 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.node.message'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import unittest
-+
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+from grit import exception
-+from grit import tclib
-+from grit import util
-+from grit.node import message
-+
-+class MessageUnittest(unittest.TestCase):
-+ def testMessage(self):
-+ root = util.ParseGrdForUnittest('''
-+ <messages>
-+ <message name="IDS_GREETING"
-+ desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ </messages>''')
-+ msg, = root.GetChildrenOfType(message.MessageNode)
-+ cliques = msg.GetCliques()
-+ content = cliques[0].GetMessage().GetPresentableContent()
-+ self.failUnless(content == 'Hello USERNAME, how are you doing today?')
-+
-+ def testMessageWithWhitespace(self):
-+ root = util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_BLA" desc="">
-+ ''' Hello there <ph name="USERNAME">%s</ph> '''
-+ </message>
-+ </messages>""")
-+ msg, = root.GetChildrenOfType(message.MessageNode)
-+ content = msg.GetCliques()[0].GetMessage().GetPresentableContent()
-+ self.failUnless(content == 'Hello there USERNAME')
-+ self.failUnless(msg.ws_at_start == ' ')
-+ self.failUnless(msg.ws_at_end == ' ')
-+
-+ def testConstruct(self):
-+ msg = tclib.Message(text=" Hello USERNAME, how are you? BINGO\t\t",
-+ placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi'),
-+ tclib.Placeholder('BINGO', '%d', '11')])
-+ msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
-+ self.failUnless(msg_node.children[0].name == 'ph')
-+ self.failUnless(msg_node.children[0].children[0].name == 'ex')
-+ self.failUnless(msg_node.children[0].children[0].GetCdata() == 'Joi')
-+ self.failUnless(msg_node.children[1].children[0].GetCdata() == '11')
-+ self.failUnless(msg_node.ws_at_start == ' ')
-+ self.failUnless(msg_node.ws_at_end == '\t\t')
-+
-+ def testUnicodeConstruct(self):
-+ text = u'Howdie \u00fe'
-+ msg = tclib.Message(text=text)
-+ msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
-+ msg_from_node = msg_node.GetCdata()
-+ self.failUnless(msg_from_node == text)
-+
-+ def testFormatterData(self):
-+ root = util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_BLA" desc="" formatter_data=" foo=123 bar qux=low">
-+ Text
-+ </message>
-+ </messages>""")
-+ msg, = root.GetChildrenOfType(message.MessageNode)
-+ expected_formatter_data = {
-+ 'foo': '123',
-+ 'bar': '',
-+ 'qux': 'low'}
-+
-+ # Can't use assertDictEqual, not available in Python 2.6, so do it
-+ # by hand.
-+ self.failUnlessEqual(len(expected_formatter_data),
-+ len(msg.formatter_data))
-+ for key in expected_formatter_data:
-+ self.failUnlessEqual(expected_formatter_data[key],
-+ msg.formatter_data[key])
-+
-+ def testReplaceEllipsis(self):
-+ root = util.ParseGrdForUnittest('''
-+ <messages>
-+ <message name="IDS_GREETING" desc="">
-+ A...B.... <ph name="PH">%s<ex>A</ex></ph>... B... C...
-+ </message>
-+ </messages>''')
-+ msg, = root.GetChildrenOfType(message.MessageNode)
-+ msg.SetReplaceEllipsis(True)
-+ content = msg.Translate('en')
-+ self.failUnlessEqual(u'A...B.... %s\u2026 B\u2026 C\u2026', content)
-+
-+ def testRemoveByteOrderMark(self):
-+ root = util.ParseGrdForUnittest(u'''
-+ <messages>
-+ <message name="IDS_HAS_BOM" desc="">
-+ \uFEFFThis\uFEFF i\uFEFFs OK\uFEFF
-+ </message>
-+ </messages>''')
-+ msg, = root.GetChildrenOfType(message.MessageNode)
-+ content = msg.Translate('en')
-+ self.failUnlessEqual(u'This is OK', content)
-+
-+ def testPlaceholderHasTooManyExamples(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_FOO" desc="foo">
-+ Hi <ph name="NAME">$1<ex>Joi</ex><ex>Joy</ex></ph>
-+ </message>
-+ </messages>""")
-+ except exception.TooManyExamples:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testPlaceholderHasInvalidName(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_FOO" desc="foo">
-+ Hi <ph name="ABC!">$1</ph>
-+ </message>
-+ </messages>""")
-+ except exception.InvalidPlaceholderName:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testChromeLocalizedFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_CHROME_L10N" desc="l10n format">
-+ This message is missing the ph node: $1
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testAndroidStringFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_ANDROID" desc="string format">
-+ This message is missing a ph node: %1$s
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testAndroidIntegerFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_ANDROID" desc="integer format">
-+ This message is missing a ph node: %2$d
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testAndroidIntegerWidthFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_ANDROID" desc="integer width format">
-+ This message is missing a ph node: %2$3d
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testValidAndroidIntegerWidthFormatInPhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_ANDROID_WIDTH">
-+ <ph name="VALID">%2$3d<ex>042</ex></ph>
-+ </message>
-+ </messages>""")
-+ except:
-+ self.fail('Should not have gotten exception')
-+
-+ def testAndroidFloatFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_ANDROID" desc="float number format">
-+ This message is missing a ph node: %3$4.5f
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testGritStringFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_GRIT_STRING" desc="grit string format">
-+ This message is missing the ph node: %s
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testGritIntegerFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_GRIT_INTEGER" desc="grit integer format">
-+ This message is missing the ph node: %d
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testWindowsETWIntegerFormatIsInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_WINDOWS_ETW" desc="ETW tracing integer">
-+ This message is missing the ph node: %1
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testValidMultipleFormattersInsidePhNodes(self):
-+ root = util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_MULTIPLE_FORMATTERS">
-+ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
-+ </message>
-+ </messages>""")
-+ msg, = root.GetChildrenOfType(message.MessageNode)
-+ cliques = msg.GetCliques()
-+ content = cliques[0].GetMessage().GetPresentableContent()
-+ self.failUnless(content == 'ERROR_COUNT error, WARNING_COUNT warning')
-+
-+ def testMultipleFormattersAreInsidePhNodes(self):
-+ failed = True
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_MULTIPLE_FORMATTERS">
-+ %1$d error, %2$d warning
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ failed = False
-+ if failed:
-+ self.fail('Should have gotten exception')
-+ return
-+
-+ failed = True
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_MULTIPLE_FORMATTERS">
-+ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, %2$d warning
-+ </message>
-+ </messages>""")
-+ except exception.PlaceholderNotInsidePhNode:
-+ failed = False
-+ if failed:
-+ self.fail('Should have gotten exception')
-+ return
-+
-+ failed = True
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_MULTIPLE_FORMATTERS">
-+ <ph name="INVALID">%1$d %2$d</ph>
-+ </message>
-+ </messages>""")
-+ except exception.InvalidCharactersInsidePhNode:
-+ failed = False
-+ if failed:
-+ self.fail('Should have gotten exception')
-+ return
-+
-+ def testValidHTMLFormatInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_HTML">
-+ <ph name="VALID">&lt;span&gt;$1&lt;/span&gt;<ex>1</ex></ph>
-+ </message>
-+ </messages>""")
-+ except:
-+ self.fail('Should not have gotten exception')
-+
-+ def testValidHTMLWithAttributesFormatInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_HTML_ATTRIBUTE">
-+ <ph name="VALID">&lt;span attribute="js:$this %"&gt;$2&lt;/span&gt;<ex>2</ex></ph>
-+ </message>
-+ </messages>""")
-+ except:
-+ self.fail('Should not have gotten exception')
-+
-+ def testValidHTMLEntityFormatInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_ENTITY">
-+ <ph name="VALID">&gt;%1$d&lt;<ex>1</ex></ph>
-+ </message>
-+ </messages>""")
-+ except:
-+ self.fail('Should not have gotten exception')
-+
-+ def testValidMultipleDollarFormatInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_DOLLARS" desc="l10n dollars format">
-+ <ph name="VALID">$$1</ph>
-+ </message>
-+ </messages>""")
-+ except:
-+ self.fail('Should not have gotten exception')
-+
-+ def testInvalidDollarCharacterInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_BAD_DOLLAR">
-+ <ph name="INVALID">%1$d $</ph>
-+ </message>
-+ </messages>""")
-+ except exception.InvalidCharactersInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testInvalidPercentCharacterInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_BAD_PERCENT">
-+ <ph name="INVALID">%1$d %</ph>
-+ </message>
-+ </messages>""")
-+ except exception.InvalidCharactersInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+ def testInvalidMixedFormatCharactersInsidePhNode(self):
-+ try:
-+ util.ParseGrdForUnittest("""\
-+ <messages>
-+ <message name="IDS_MIXED_FORMATS">
-+ <ph name="INVALID">%1$2</ph>
-+ </message>
-+ </messages>""")
-+ except exception.InvalidCharactersInsidePhNode:
-+ return
-+ self.fail('Should have gotten exception')
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py
-new file mode 100644
-index 0000000000..2d8b06d6a5
---- /dev/null
-+++ b/tools/grit/grit/node/misc.py
-@@ -0,0 +1,707 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Miscellaneous node types.
-+"""
-+
-+from __future__ import print_function
-+
-+import os.path
-+import re
-+import sys
-+
-+import six
-+
-+from grit import constants
-+from grit import exception
-+from grit import util
-+from grit.extern import FP
-+from grit.node import base
-+from grit.node import message
-+from grit.node import node_io
-+
-+
-+# Python 3 doesn't have long() as int() works everywhere. But we really do need
-+# the long() behavior on Python 2 as our ids are much too large for int().
-+try:
-+ long
-+except NameError:
-+ long = int
-+
-+
-+# RTL languages
-+# TODO(jennyz): remove this fixed set of RTL language array
-+# now that generic expand_variable code exists.
-+_RTL_LANGS = (
-+ 'ar', # Arabic
-+ 'fa', # Farsi
-+ 'iw', # Hebrew
-+ 'ks', # Kashmiri
-+ 'ku', # Kurdish
-+ 'ps', # Pashto
-+ 'ur', # Urdu
-+ 'yi', # Yiddish
-+)
-+
-+
-+def _ReadFirstIdsFromFile(filename, defines):
-+ """Read the starting resource id values from |filename|. We also
-+ expand variables of the form <(FOO) based on defines passed in on
-+ the command line.
-+
-+ Returns a tuple, the absolute path of SRCDIR followed by the
-+ first_ids dictionary.
-+ """
-+ first_ids_dict = eval(util.ReadFile(filename, 'utf-8'))
-+ src_root_dir = os.path.abspath(os.path.join(os.path.dirname(filename),
-+ first_ids_dict['SRCDIR']))
-+
-+ def ReplaceVariable(matchobj):
-+ for key, value in defines.items():
-+ if matchobj.group(1) == key:
-+ return value
-+ return ''
-+
-+ renames = []
-+ for grd_filename in first_ids_dict:
-+ new_grd_filename = re.sub(r'<\(([A-Za-z_]+)\)', ReplaceVariable,
-+ grd_filename)
-+ if new_grd_filename != grd_filename:
-+ abs_grd_filename = os.path.abspath(new_grd_filename)
-+ if abs_grd_filename[:len(src_root_dir)] != src_root_dir:
-+ new_grd_filename = os.path.basename(abs_grd_filename)
-+ else:
-+ new_grd_filename = abs_grd_filename[len(src_root_dir) + 1:]
-+ new_grd_filename = new_grd_filename.replace('\\', '/')
-+ renames.append((grd_filename, new_grd_filename))
-+
-+ for grd_filename, new_grd_filename in renames:
-+ first_ids_dict[new_grd_filename] = first_ids_dict[grd_filename]
-+ del(first_ids_dict[grd_filename])
-+
-+ return (src_root_dir, first_ids_dict)
-+
-+
-+def _ComputeIds(root, predetermined_tids):
-+ """Returns a dict of textual id -> numeric id for all nodes in root.
-+
-+ IDs are mostly assigned sequentially, but will vary based on:
-+ * first_id node attribute (from first_ids_file)
-+ * hash of textual id (if not first_id is defined)
-+ * offset node attribute
-+ * whether the textual id matches a system id
-+ * whether the node generates its own ID via GetId()
-+
-+ Args:
-+ predetermined_tids: Dict of textual id -> numeric id to use in return dict.
-+ """
-+ from grit.node import empty, include, misc, structure
-+
-+ ids = {} # Maps numeric id to textual id
-+ tids = {} # Maps textual id to numeric id
-+ id_reasons = {} # Maps numeric id to text id and a human-readable explanation
-+ group = None
-+ last_id = None
-+ predetermined_ids = {value: key
-+ for key, value in predetermined_tids.items()}
-+
-+ for item in root:
-+ if isinstance(item, empty.GroupingNode):
-+ # Note: this won't work if any GroupingNode can be contained inside
-+ # another.
-+ group = item
-+ last_id = None
-+ continue
-+
-+ assert not item.GetTextualIds() or isinstance(item,
-+ (include.IncludeNode, message.MessageNode,
-+ misc.IdentifierNode, structure.StructureNode))
-+
-+ # Resources that use the RES protocol don't need
-+ # any numerical ids generated, so we skip them altogether.
-+ # This is accomplished by setting the flag 'generateid' to false
-+ # in the GRD file.
-+ if item.attrs.get('generateid', 'true') == 'false':
-+ continue
-+
-+ for tid in item.GetTextualIds():
-+ if util.SYSTEM_IDENTIFIERS.match(tid):
-+ # Don't emit a new ID for predefined IDs
-+ continue
-+
-+ if tid in tids:
-+ continue
-+
-+ if predetermined_tids and tid in predetermined_tids:
-+ id = predetermined_tids[tid]
-+ reason = "from predetermined_tids map"
-+
-+ # Some identifier nodes can provide their own id,
-+ # and we use that id in the generated header in that case.
-+ elif hasattr(item, 'GetId') and item.GetId():
-+ id = long(item.GetId())
-+ reason = 'returned by GetId() method'
-+
-+ elif ('offset' in item.attrs and group and
-+ group.attrs.get('first_id', '') != ''):
-+ offset_text = item.attrs['offset']
-+ parent_text = group.attrs['first_id']
-+
-+ try:
-+ offset_id = long(offset_text)
-+ except ValueError:
-+ offset_id = tids[offset_text]
-+
-+ try:
-+ parent_id = long(parent_text)
-+ except ValueError:
-+ parent_id = tids[parent_text]
-+
-+ id = parent_id + offset_id
-+ reason = 'first_id %d + offset %d' % (parent_id, offset_id)
-+
-+ # We try to allocate IDs sequentially for blocks of items that might
-+ # be related, for instance strings in a stringtable (as their IDs might be
-+ # used e.g. as IDs for some radio buttons, in which case the IDs must
-+ # be sequential).
-+ #
-+ # We do this by having the first item in a section store its computed ID
-+ # (computed from a fingerprint) in its parent object. Subsequent children
-+ # of the same parent will then try to get IDs that sequentially follow
-+ # the currently stored ID (on the parent) and increment it.
-+ elif last_id is None:
-+ # First check if the starting ID is explicitly specified by the parent.
-+ if group and group.attrs.get('first_id', '') != '':
-+ id = long(group.attrs['first_id'])
-+ reason = "from parent's first_id attribute"
-+ else:
-+ # Automatically generate the ID based on the first clique from the
-+ # first child of the first child node of our parent (i.e. when we
-+ # first get to this location in the code).
-+
-+ # According to
-+ # http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
-+ # the safe usable range for resource IDs in Windows is from decimal
-+ # 101 to 0x7FFF.
-+
-+ id = FP.UnsignedFingerPrint(tid)
-+ id = id % (0x7FFF - 101) + 101
-+ reason = 'chosen by random fingerprint -- use first_id to override'
-+
-+ last_id = id
-+ else:
-+ id = last_id = last_id + 1
-+ reason = 'sequentially assigned'
-+
-+ reason = "%s (%s)" % (tid, reason)
-+ # Don't fail when 'offset' is specified, as the base and the 0th
-+ # offset will have the same ID.
-+ if id in id_reasons and not 'offset' in item.attrs:
-+ raise exception.IdRangeOverlap('ID %d was assigned to both %s and %s.'
-+ % (id, id_reasons[id], reason))
-+
-+ if id < 101:
-+ print('WARNING: Numeric resource IDs should be greater than 100 to\n'
-+ 'avoid conflicts with system-defined resource IDs.')
-+
-+ if tid not in predetermined_tids and id in predetermined_ids:
-+ raise exception.IdRangeOverlap('ID %d overlaps between %s and %s'
-+ % (id, tid, predetermined_ids[tid]))
-+
-+ ids[id] = tid
-+ tids[tid] = id
-+ id_reasons[id] = reason
-+
-+ return tids
-+
-+class SplicingNode(base.Node):
-+ """A node whose children should be considered to be at the same level as
-+ its siblings for most purposes. This includes <if> and <part> nodes.
-+ """
-+
-+ def _IsValidChild(self, child):
-+ assert self.parent, '<%s> node should never be root.' % self.name
-+ if isinstance(child, SplicingNode):
-+ return True # avoid O(n^2) behavior
-+ return self.parent._IsValidChild(child)
-+
-+
-+class IfNode(SplicingNode):
-+ """A node for conditional inclusion of resources.
-+ """
-+
-+ def MandatoryAttributes(self):
-+ return ['expr']
-+
-+ def _IsValidChild(self, child):
-+ return (isinstance(child, (ThenNode, ElseNode)) or
-+ super(IfNode, self)._IsValidChild(child))
-+
-+ def EndParsing(self):
-+ children = self.children
-+ self.if_then_else = False
-+ if any(isinstance(node, (ThenNode, ElseNode)) for node in children):
-+ if (len(children) != 2 or not isinstance(children[0], ThenNode) or
-+ not isinstance(children[1], ElseNode)):
-+ raise exception.UnexpectedChild(
-+ '<if> element must be <if><then>...</then><else>...</else></if>')
-+ self.if_then_else = True
-+
-+ def ActiveChildren(self):
-+ cond = self.EvaluateCondition(self.attrs['expr'])
-+ if self.if_then_else:
-+ return self.children[0 if cond else 1].ActiveChildren()
-+ else:
-+ # Equivalent to having all children inside <then> with an empty <else>
-+ return super(IfNode, self).ActiveChildren() if cond else []
-+
-+
-+class ThenNode(SplicingNode):
-+ """A <then> node. Can only appear directly inside an <if> node."""
-+ pass
-+
-+
-+class ElseNode(SplicingNode):
-+ """An <else> node. Can only appear directly inside an <if> node."""
-+ pass
-+
-+
-+class PartNode(SplicingNode):
-+ """A node for inclusion of sub-grd (*.grp) files.
-+ """
-+
-+ def __init__(self):
-+ super(PartNode, self).__init__()
-+ self.started_inclusion = False
-+
-+ def MandatoryAttributes(self):
-+ return ['file']
-+
-+ def _IsValidChild(self, child):
-+ return self.started_inclusion and super(PartNode, self)._IsValidChild(child)
-+
-+
-+class ReleaseNode(base.Node):
-+ """The <release> element."""
-+
-+ def _IsValidChild(self, child):
-+ from grit.node import empty
-+ return isinstance(child, (empty.IncludesNode, empty.MessagesNode,
-+ empty.StructuresNode, empty.IdentifiersNode))
-+
-+ def _IsValidAttribute(self, name, value):
-+ return (
-+ (name == 'seq' and int(value) <= self.GetRoot().GetCurrentRelease()) or
-+ name == 'allow_pseudo'
-+ )
-+
-+ def MandatoryAttributes(self):
-+ return ['seq']
-+
-+ def DefaultAttributes(self):
-+ return { 'allow_pseudo' : 'true' }
-+
-+
-+class GritNode(base.Node):
-+ """The <grit> root element."""
-+
-+ def __init__(self):
-+ super(GritNode, self).__init__()
-+ self.output_language = ''
-+ self.defines = {}
-+ self.substituter = None
-+ self.target_platform = sys.platform
-+ self.whitelist_support = False
-+ self._predetermined_ids_file = None
-+ self._id_map = None # Dict of textual_id -> numeric_id.
-+
-+ def _IsValidChild(self, child):
-+ from grit.node import empty
-+ return isinstance(child, (ReleaseNode, empty.TranslationsNode,
-+ empty.OutputsNode))
-+
-+ def _IsValidAttribute(self, name, value):
-+ if name not in ['base_dir', 'first_ids_file', 'source_lang_id',
-+ 'latest_public_release', 'current_release',
-+ 'enc_check', 'tc_project', 'grit_version',
-+ 'output_all_resource_defines']:
-+ return False
-+ if name in ['latest_public_release', 'current_release'] and value.strip(
-+ '0123456789') != '':
-+ return False
-+ return True
-+
-+ def MandatoryAttributes(self):
-+ return ['latest_public_release', 'current_release']
-+
-+ def DefaultAttributes(self):
-+ return {
-+ 'base_dir' : '.',
-+ 'first_ids_file': '',
-+ 'grit_version': 1,
-+ 'source_lang_id' : 'en',
-+ 'enc_check' : constants.ENCODING_CHECK,
-+ 'tc_project' : 'NEED_TO_SET_tc_project_ATTRIBUTE',
-+ }
-+
-+ def EndParsing(self):
-+ super(GritNode, self).EndParsing()
-+ if (int(self.attrs['latest_public_release'])
-+ > int(self.attrs['current_release'])):
-+ raise exception.Parsing('latest_public_release cannot have a greater '
-+ 'value than current_release')
-+
-+ self.ValidateUniqueIds()
-+
-+ # Add the encoding check if it's not present (should ensure that it's always
-+ # present in all .grd files generated by GRIT). If it's present, assert if
-+ # it's not correct.
-+ if 'enc_check' not in self.attrs or self.attrs['enc_check'] == '':
-+ self.attrs['enc_check'] = constants.ENCODING_CHECK
-+ else:
-+ assert self.attrs['enc_check'] == constants.ENCODING_CHECK, (
-+ 'Are you sure your .grd file is in the correct encoding (UTF-8)?')
-+
-+ def ValidateUniqueIds(self):
-+ """Validate that 'name' attribute is unique in all nodes in this tree
-+ except for nodes that are children of <if> nodes.
-+ """
-+ unique_names = {}
-+ duplicate_names = []
-+ # To avoid false positives from mutually exclusive <if> clauses, check
-+ # against whatever the output condition happens to be right now.
-+ # TODO(benrg): do something better.
-+ for node in self.ActiveDescendants():
-+ if node.attrs.get('generateid', 'true') == 'false':
-+ continue # Duplication not relevant in that case
-+
-+ for node_id in node.GetTextualIds():
-+ if util.SYSTEM_IDENTIFIERS.match(node_id):
-+ continue # predefined IDs are sometimes used more than once
-+
-+ if node_id in unique_names and node_id not in duplicate_names:
-+ duplicate_names.append(node_id)
-+ unique_names[node_id] = 1
-+
-+ if len(duplicate_names):
-+ raise exception.DuplicateKey(', '.join(duplicate_names))
-+
-+
-+ def GetCurrentRelease(self):
-+ """Returns the current release number."""
-+ return int(self.attrs['current_release'])
-+
-+ def GetLatestPublicRelease(self):
-+ """Returns the latest public release number."""
-+ return int(self.attrs['latest_public_release'])
-+
-+ def GetSourceLanguage(self):
-+ """Returns the language code of the source language."""
-+ return self.attrs['source_lang_id']
-+
-+ def GetTcProject(self):
-+ """Returns the name of this project in the TranslationConsole, or
-+ 'NEED_TO_SET_tc_project_ATTRIBUTE' if it is not defined."""
-+ return self.attrs['tc_project']
-+
-+ def SetOwnDir(self, dir):
-+ """Informs the 'grit' element of the directory the file it is in resides.
-+ This allows it to calculate relative paths from the input file, which is
-+ what we desire (rather than from the current path).
-+
-+ Args:
-+ dir: r'c:\bla'
-+
-+ Return:
-+ None
-+ """
-+ assert dir
-+ self.base_dir = os.path.normpath(os.path.join(dir, self.attrs['base_dir']))
-+
-+ def GetBaseDir(self):
-+ """Returns the base directory, relative to the working directory. To get
-+ the base directory as set in the .grd file, use GetOriginalBaseDir()
-+ """
-+ if hasattr(self, 'base_dir'):
-+ return self.base_dir
-+ else:
-+ return self.GetOriginalBaseDir()
-+
-+ def GetOriginalBaseDir(self):
-+ """Returns the base directory, as set in the .grd file.
-+ """
-+ return self.attrs['base_dir']
-+
-+ def IsWhitelistSupportEnabled(self):
-+ return self.whitelist_support
-+
-+ def SetWhitelistSupportEnabled(self, whitelist_support):
-+ self.whitelist_support = whitelist_support
-+
-+ def GetInputFiles(self):
-+ """Returns the list of files that are read to produce the output."""
-+
-+ # Importing this here avoids a circular dependency in the imports.
-+ # pylint: disable-msg=C6204
-+ from grit.node import include
-+ from grit.node import misc
-+ from grit.node import structure
-+ from grit.node import variant
-+
-+ # Check if the input is required for any output configuration.
-+ input_files = set()
-+ # Collect even inactive PartNodes since they affect ID assignments.
-+ for node in self:
-+ if isinstance(node, misc.PartNode):
-+ input_files.add(self.ToRealPath(node.GetInputPath()))
-+
-+ old_output_language = self.output_language
-+ for lang, ctx, fallback in self.GetConfigurations():
-+ self.SetOutputLanguage(lang or self.GetSourceLanguage())
-+ self.SetOutputContext(ctx)
-+ self.SetFallbackToDefaultLayout(fallback)
-+
-+ for node in self.ActiveDescendants():
-+ if isinstance(node, (node_io.FileNode, include.IncludeNode,
-+ structure.StructureNode, variant.SkeletonNode)):
-+ input_path = node.GetInputPath()
-+ if input_path is not None:
-+ input_files.add(self.ToRealPath(input_path))
-+
-+ # If it's a flattened node, grab inlined resources too.
-+ if ((node.name == 'structure' or node.name == 'include')
-+ and node.attrs['flattenhtml'] == 'true'):
-+ if node.name == 'structure':
-+ node.RunPreSubstitutionGatherer()
-+ input_files.update(node.GetHtmlResourceFilenames())
-+
-+ self.SetOutputLanguage(old_output_language)
-+ return sorted(input_files)
-+
-+ def GetFirstIdsFile(self):
-+ """Returns a usable path to the first_ids file, if set, otherwise
-+ returns None.
-+
-+ The first_ids_file attribute is by default relative to the
-+ base_dir of the .grd file, but may be prefixed by GRIT_DIR/,
-+ which makes it relative to the directory of grit.py
-+ (e.g. GRIT_DIR/../gritsettings/resource_ids).
-+ """
-+ if not self.attrs['first_ids_file']:
-+ return None
-+
-+ path = self.attrs['first_ids_file']
-+ GRIT_DIR_PREFIX = 'GRIT_DIR'
-+ if (path.startswith(GRIT_DIR_PREFIX)
-+ and path[len(GRIT_DIR_PREFIX)] in ['/', '\\']):
-+ return util.PathFromRoot(path[len(GRIT_DIR_PREFIX) + 1:])
-+ else:
-+ return self.ToRealPath(path)
-+
-+ def GetOutputFiles(self):
-+ """Returns the list of <output> nodes that are descendants of this node's
-+ <outputs> child and are not enclosed by unsatisfied <if> conditionals.
-+ """
-+ for child in self.children:
-+ if child.name == 'outputs':
-+ return [node for node in child.ActiveDescendants()
-+ if node.name == 'output']
-+ raise exception.MissingElement()
-+
-+ def GetConfigurations(self):
-+ """Returns the distinct (language, context, fallback_to_default_layout)
-+ triples from the output nodes.
-+ """
-+ return set((n.GetLanguage(), n.GetContext(), n.GetFallbackToDefaultLayout())
-+ for n in self.GetOutputFiles())
-+
-+ def GetSubstitutionMessages(self):
-+ """Returns the list of <message sub_variable="true"> nodes."""
-+ return [n for n in self.ActiveDescendants()
-+ if isinstance(n, message.MessageNode)
-+ and n.attrs['sub_variable'] == 'true']
-+
-+ def SetOutputLanguage(self, output_language):
-+ """Set the output language. Prepares substitutions.
-+
-+ The substitutions are reset every time the language is changed.
-+ They include messages designated as variables, and language codes for html
-+ and rc files.
-+
-+ Args:
-+ output_language: a two-letter language code (eg: 'en', 'ar'...) or ''
-+ """
-+ if not output_language:
-+ # We do not specify the output language for .grh files,
-+ # so we get an empty string as the default.
-+ # The value should match grit.clique.MessageClique.source_language.
-+ output_language = self.GetSourceLanguage()
-+ if output_language != self.output_language:
-+ self.output_language = output_language
-+ self.substituter = None # force recalculate
-+
-+ def SetOutputContext(self, output_context):
-+ self.output_context = output_context
-+ self.substituter = None # force recalculate
-+
-+ def SetFallbackToDefaultLayout(self, fallback_to_default_layout):
-+ self.fallback_to_default_layout = fallback_to_default_layout
-+ self.substituter = None # force recalculate
-+
-+ def SetDefines(self, defines):
-+ self.defines = defines
-+ self.substituter = None # force recalculate
-+
-+ def SetTargetPlatform(self, target_platform):
-+ self.target_platform = target_platform
-+
-+ def GetSubstituter(self):
-+ if self.substituter is None:
-+ self.substituter = util.Substituter()
-+ self.substituter.AddMessages(self.GetSubstitutionMessages(),
-+ self.output_language)
-+ if self.output_language in _RTL_LANGS:
-+ direction = 'dir="RTL"'
-+ else:
-+ direction = 'dir="LTR"'
-+ self.substituter.AddSubstitutions({
-+ 'GRITLANGCODE': self.output_language,
-+ 'GRITDIR': direction,
-+ })
-+ from grit.format import rc # avoid circular dep
-+ rc.RcSubstitutions(self.substituter, self.output_language)
-+ return self.substituter
-+
-+ def AssignFirstIds(self, filename_or_stream, defines):
-+ """Assign first ids to each grouping node based on values from the
-+ first_ids file (if specified on the <grit> node).
-+ """
-+ assert self._id_map is None, 'AssignFirstIds() after InitializeIds()'
-+ # If the input is a stream, then we're probably in a unit test and
-+ # should skip this step.
-+ if not isinstance(filename_or_stream, six.string_types):
-+ return
-+
-+ # Nothing to do if the first_ids_filename attribute isn't set.
-+ first_ids_filename = self.GetFirstIdsFile()
-+ if not first_ids_filename:
-+ return
-+
-+ src_root_dir, first_ids = _ReadFirstIdsFromFile(first_ids_filename,
-+ defines)
-+ from grit.node import empty
-+ for node in self.Preorder():
-+ if isinstance(node, empty.GroupingNode):
-+ abs_filename = os.path.abspath(filename_or_stream)
-+ if abs_filename[:len(src_root_dir)] != src_root_dir:
-+ filename = os.path.basename(filename_or_stream)
-+ else:
-+ filename = abs_filename[len(src_root_dir) + 1:]
-+ filename = filename.replace('\\', '/')
-+
-+ if node.attrs['first_id'] != '':
-+ raise Exception(
-+ "Don't set the first_id attribute when using the first_ids_file "
-+ "attribute on the <grit> node, update %s instead." %
-+ first_ids_filename)
-+
-+ try:
-+ id_list = first_ids[filename][node.name]
-+ except KeyError as e:
-+ print('-' * 78)
-+ print('Resource id not set for %s (%s)!' % (filename, node.name))
-+ print('Please update %s to include an entry for %s. See the '
-+ 'comments in resource_ids for information on why you need to '
-+ 'update that file.' % (first_ids_filename, filename))
-+ print('-' * 78)
-+ raise e
-+
-+ try:
-+ node.attrs['first_id'] = str(id_list.pop(0))
-+ except IndexError as e:
-+ raise Exception('Please update %s and add a first id for %s (%s).'
-+ % (first_ids_filename, filename, node.name))
-+
-+ def GetIdMap(self):
-+ '''Return a dictionary mapping textual ids to numeric ids.'''
-+ return self._id_map
-+
-+ def SetPredeterminedIdsFile(self, predetermined_ids_file):
-+ assert self._id_map is None, (
-+ 'SetPredeterminedIdsFile() after InitializeIds()')
-+ self._predetermined_ids_file = predetermined_ids_file
-+
-+ def InitializeIds(self):
-+ '''Initializes the text ID -> numeric ID mapping.'''
-+ predetermined_id_map = {}
-+ if self._predetermined_ids_file:
-+ with open(self._predetermined_ids_file) as f:
-+ for line in f:
-+ tid, nid = line.split()
-+ predetermined_id_map[tid] = int(nid)
-+ self._id_map = _ComputeIds(self, predetermined_id_map)
-+
-+ def RunGatherers(self, debug=False):
-+ '''Call RunPreSubstitutionGatherer() on every node of the tree, then apply
-+ substitutions, then call RunPostSubstitutionGatherer() on every node.
-+
-+ The substitutions step requires that the output language has been set.
-+ Locally, get the Substitution messages and add them to the substituter.
-+ Also add substitutions for language codes in the Rc.
-+
-+ Args:
-+ debug: will print information while running gatherers.
-+ '''
-+ for node in self.ActiveDescendants():
-+ if hasattr(node, 'RunPreSubstitutionGatherer'):
-+ with node:
-+ node.RunPreSubstitutionGatherer(debug=debug)
-+
-+ assert self.output_language
-+ self.SubstituteMessages(self.GetSubstituter())
-+
-+ for node in self.ActiveDescendants():
-+ if hasattr(node, 'RunPostSubstitutionGatherer'):
-+ with node:
-+ node.RunPostSubstitutionGatherer(debug=debug)
-+
-+
-+class IdentifierNode(base.Node):
-+ """A node for specifying identifiers that should appear in the resource
-+ header file, and be unique amongst all other resource identifiers, but don't
-+ have any other attributes or reference any resources.
-+ """
-+
-+ def MandatoryAttributes(self):
-+ return ['name']
-+
-+ def DefaultAttributes(self):
-+ return { 'comment' : '', 'id' : '', 'systemid': 'false' }
-+
-+ def GetId(self):
-+ """Returns the id of this identifier if it has one, None otherwise
-+ """
-+ if 'id' in self.attrs:
-+ return self.attrs['id']
-+ return None
-+
-+ def EndParsing(self):
-+ """Handles system identifiers."""
-+ super(IdentifierNode, self).EndParsing()
-+ if self.attrs['systemid'] == 'true':
-+ util.SetupSystemIdentifiers((self.attrs['name'],))
-+
-+ @staticmethod
-+ def Construct(parent, name, id, comment, systemid='false'):
-+ """Creates a new node which is a child of 'parent', with attributes set
-+ by parameters of the same name.
-+ """
-+ node = IdentifierNode()
-+ node.StartParsing('identifier', parent)
-+ node.HandleAttribute('name', name)
-+ node.HandleAttribute('id', id)
-+ node.HandleAttribute('comment', comment)
-+ node.HandleAttribute('systemid', systemid)
-+ node.EndParsing()
-+ return node
-diff --git a/tools/grit/grit/node/misc_unittest.py b/tools/grit/grit/node/misc_unittest.py
-new file mode 100644
-index 0000000000..c192b096f4
---- /dev/null
-+++ b/tools/grit/grit/node/misc_unittest.py
-@@ -0,0 +1,590 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for misc.GritNode'''
-+
-+from __future__ import print_function
-+
-+import contextlib
-+import os
-+import sys
-+import tempfile
-+import unittest
-+
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+from six import StringIO
-+
-+from grit import grd_reader
-+import grit.exception
-+from grit import util
-+from grit.format import rc
-+from grit.format import rc_header
-+from grit.node import misc
-+
-+
-+@contextlib.contextmanager
-+def _MakeTempPredeterminedIdsFile(content):
-+ """Write the |content| string to a temporary file.
-+
-+ The temporary file must be deleted by the caller.
-+
-+ Example:
-+ with _MakeTempPredeterminedIdsFile('foo') as path:
-+ ...
-+ os.remove(path)
-+
-+ Args:
-+ content: The string to write.
-+
-+ Yields:
-+ The name of the temporary file.
-+ """
-+ with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
-+ f.write(content)
-+ f.flush()
-+ f.close()
-+ yield f.name
-+
-+
-+class GritNodeUnittest(unittest.TestCase):
-+ def testUniqueNameAttribute(self):
-+ try:
-+ restree = grd_reader.Parse(
-+ util.PathFromRoot('grit/testdata/duplicate-name-input.xml'))
-+ self.fail('Expected parsing exception because of duplicate names.')
-+ except grit.exception.Parsing:
-+ pass # Expected case
-+
-+ def testReadFirstIdsFromFile(self):
-+ test_resource_ids = os.path.join(os.path.dirname(__file__), '..',
-+ 'testdata', 'resource_ids')
-+ base_dir = os.path.dirname(test_resource_ids)
-+
-+ src_dir, id_dict = misc._ReadFirstIdsFromFile(
-+ test_resource_ids,
-+ {
-+ 'FOO': os.path.join(base_dir, 'bar'),
-+ 'SHARED_INTERMEDIATE_DIR': os.path.join(base_dir,
-+ 'out/Release/obj/gen'),
-+ })
-+ self.assertEqual({}, id_dict.get('bar/file.grd', None))
-+ self.assertEqual({},
-+ id_dict.get('out/Release/obj/gen/devtools/devtools.grd', None))
-+
-+ src_dir, id_dict = misc._ReadFirstIdsFromFile(
-+ test_resource_ids,
-+ {
-+ 'SHARED_INTERMEDIATE_DIR': '/outside/src_dir',
-+ })
-+ self.assertEqual({}, id_dict.get('devtools.grd', None))
-+
-+ # Verifies that GetInputFiles() returns the correct list of files
-+ # corresponding to ChromeScaledImage nodes when assets are missing.
-+ def testGetInputFilesChromeScaledImage(self):
-+ chrome_html_path = util.PathFromRoot('grit/testdata/chrome_html.html')
-+ xml = '''<?xml version="1.0" encoding="utf-8"?>
-+ <grit latest_public_release="0" current_release="1">
-+ <outputs>
-+ <output filename="default.pak" type="data_package" context="default_100_percent" />
-+ <output filename="special.pak" type="data_package" context="special_100_percent" fallback_to_default_layout="false" />
-+ </outputs>
-+ <release seq="1">
-+ <structures fallback_to_low_resolution="true">
-+ <structure type="chrome_scaled_image" name="IDR_A" file="a.png" />
-+ <structure type="chrome_scaled_image" name="IDR_B" file="b.png" />
-+ <structure type="chrome_html" name="HTML_FILE1" file="%s" flattenhtml="true" />
-+ </structures>
-+ </release>
-+ </grit>''' % chrome_html_path
-+
-+ grd = grd_reader.Parse(StringIO(xml),
-+ util.PathFromRoot('grit/testdata'))
-+ expected = ['chrome_html.html', 'default_100_percent/a.png',
-+ 'default_100_percent/b.png', 'included_sample.html',
-+ 'special_100_percent/a.png']
-+ actual = [os.path.relpath(path, util.PathFromRoot('grit/testdata')) for
-+ path in grd.GetInputFiles()]
-+ # Convert path separator for Windows paths.
-+ actual = [path.replace('\\', '/') for path in actual]
-+ self.assertEquals(expected, actual)
-+
-+ # Verifies that GetInputFiles() returns the correct list of files
-+ # when files include other files.
-+ def testGetInputFilesFromIncludes(self):
-+ chrome_html_path = util.PathFromRoot('grit/testdata/chrome_html.html')
-+ xml = '''<?xml version="1.0" encoding="utf-8"?>
-+ <grit latest_public_release="0" current_release="1">
-+ <outputs>
-+ <output filename="default.pak" type="data_package" context="default_100_percent" />
-+ <output filename="special.pak" type="data_package" context="special_100_percent" fallback_to_default_layout="false" />
-+ </outputs>
-+ <release seq="1">
-+ <includes>
-+ <include name="IDR_TESTDATA_CHROME_HTML" file="%s" flattenhtml="true"
-+ allowexternalscript="true" type="BINDATA" />
-+ </includes>
-+ </release>
-+ </grit>''' % chrome_html_path
-+
-+ grd = grd_reader.Parse(StringIO(xml), util.PathFromRoot('grit/testdata'))
-+ expected = ['chrome_html.html', 'included_sample.html']
-+ actual = [os.path.relpath(path, util.PathFromRoot('grit/testdata')) for
-+ path in grd.GetInputFiles()]
-+ # Convert path separator for Windows paths.
-+ actual = [path.replace('\\', '/') for path in actual]
-+ self.assertEquals(expected, actual)
-+
-+ def testNonDefaultEntry(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <messages>
-+ <message name="IDS_A" desc="foo">bar</message>
-+ <if expr="lang == 'fr'">
-+ <message name="IDS_B" desc="foo">bar</message>
-+ </if>
-+ </messages>''')
-+ grd.SetOutputLanguage('fr')
-+ output = ''.join(rc_header.Format(grd, 'fr', '.'))
-+ self.assertIn('#define IDS_A 2378\n#define IDS_B 2379', output)
-+
-+ def testExplicitFirstIdOverlaps(self):
-+ # second first_id will overlap preexisting range
-+ self.assertRaises(grit.exception.IdRangeOverlap,
-+ util.ParseGrdForUnittest, '''
-+ <includes first_id="300" comment="bingo">
-+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
-+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
-+ </includes>
-+ <messages first_id="301">
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ <message name="IDS_SMURFGEBURF">Frubegfrums</message>
-+ </messages>''')
-+
-+ def testImplicitOverlapsPreexisting(self):
-+ # second message in <messages> will overlap preexisting range
-+ self.assertRaises(grit.exception.IdRangeOverlap,
-+ util.ParseGrdForUnittest, '''
-+ <includes first_id="301" comment="bingo">
-+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
-+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
-+ </includes>
-+ <messages first_id="300">
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ <message name="IDS_SMURFGEBURF">Frubegfrums</message>
-+ </messages>''')
-+
-+ def testPredeterminedIds(self):
-+ with _MakeTempPredeterminedIdsFile('IDS_A 101\nIDS_B 102') as ids_file:
-+ grd = util.ParseGrdForUnittest('''
-+ <includes first_id="300" comment="bingo">
-+ <include type="gif" name="IDS_B" file="images/logo.gif" />
-+ </includes>
-+ <messages first_id="10000">
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ <message name="IDS_A">
-+ Bongo!
-+ </message>
-+ </messages>''', predetermined_ids_file=ids_file)
-+ output = rc_header.FormatDefines(grd)
-+ self.assertEqual(('#define IDS_B 102\n'
-+ '#define IDS_GREETING 10000\n'
-+ '#define IDS_A 101\n'), ''.join(output))
-+ os.remove(ids_file)
-+
-+ def testPredeterminedIdsOverlap(self):
-+ with _MakeTempPredeterminedIdsFile('ID_LOGO 10000') as ids_file:
-+ self.assertRaises(grit.exception.IdRangeOverlap,
-+ util.ParseGrdForUnittest, '''
-+ <includes first_id="300" comment="bingo">
-+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
-+ </includes>
-+ <messages first_id="10000">
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ <message name="IDS_BONGO">
-+ Bongo!
-+ </message>
-+ </messages>''', predetermined_ids_file=ids_file)
-+ os.remove(ids_file)
-+
-+
-+class IfNodeUnittest(unittest.TestCase):
-+ def testIffyness(self):
-+ grd = grd_reader.Parse(StringIO('''
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <if expr="'bingo' in defs">
-+ <message name="IDS_BINGO">
-+ Bingo!
-+ </message>
-+ </if>
-+ <if expr="'hello' in defs">
-+ <message name="IDS_HELLO">
-+ Hello!
-+ </message>
-+ </if>
-+ <if expr="lang == 'fr' or 'FORCE_FRENCH' in defs">
-+ <message name="IDS_HELLO" internal_comment="French version">
-+ Good morning
-+ </message>
-+ </if>
-+ <if expr="is_win">
-+ <message name="IDS_ISWIN">is_win</message>
-+ </if>
-+ </messages>
-+ </release>
-+ </grit>'''), dir='.')
-+
-+ messages_node = grd.children[0].children[0]
-+ bingo_message = messages_node.children[0].children[0]
-+ hello_message = messages_node.children[1].children[0]
-+ french_message = messages_node.children[2].children[0]
-+ is_win_message = messages_node.children[3].children[0]
-+
-+ self.assertTrue(bingo_message.name == 'message')
-+ self.assertTrue(hello_message.name == 'message')
-+ self.assertTrue(french_message.name == 'message')
-+
-+ grd.SetOutputLanguage('fr')
-+ grd.SetDefines({'hello': '1'})
-+ active = set(grd.ActiveDescendants())
-+ self.failUnless(bingo_message not in active)
-+ self.failUnless(hello_message in active)
-+ self.failUnless(french_message in active)
-+
-+ grd.SetOutputLanguage('en')
-+ grd.SetDefines({'bingo': 1})
-+ active = set(grd.ActiveDescendants())
-+ self.failUnless(bingo_message in active)
-+ self.failUnless(hello_message not in active)
-+ self.failUnless(french_message not in active)
-+
-+ grd.SetOutputLanguage('en')
-+ grd.SetDefines({'FORCE_FRENCH': '1', 'bingo': '1'})
-+ active = set(grd.ActiveDescendants())
-+ self.failUnless(bingo_message in active)
-+ self.failUnless(hello_message not in active)
-+ self.failUnless(french_message in active)
-+
-+ grd.SetOutputLanguage('en')
-+ grd.SetDefines({})
-+ self.failUnless(grd.target_platform == sys.platform)
-+ grd.SetTargetPlatform('darwin')
-+ active = set(grd.ActiveDescendants())
-+ self.failUnless(is_win_message not in active)
-+ grd.SetTargetPlatform('win32')
-+ active = set(grd.ActiveDescendants())
-+ self.failUnless(is_win_message in active)
-+
-+ def testElsiness(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <messages>
-+ <if expr="True">
-+ <then> <message name="IDS_YES1"></message> </then>
-+ <else> <message name="IDS_NO1"></message> </else>
-+ </if>
-+ <if expr="True">
-+ <then> <message name="IDS_YES2"></message> </then>
-+ <else> </else>
-+ </if>
-+ <if expr="True">
-+ <then> </then>
-+ <else> <message name="IDS_NO2"></message> </else>
-+ </if>
-+ <if expr="True">
-+ <then> </then>
-+ <else> </else>
-+ </if>
-+ <if expr="False">
-+ <then> <message name="IDS_NO3"></message> </then>
-+ <else> <message name="IDS_YES3"></message> </else>
-+ </if>
-+ <if expr="False">
-+ <then> <message name="IDS_NO4"></message> </then>
-+ <else> </else>
-+ </if>
-+ <if expr="False">
-+ <then> </then>
-+ <else> <message name="IDS_YES4"></message> </else>
-+ </if>
-+ <if expr="False">
-+ <then> </then>
-+ <else> </else>
-+ </if>
-+ </messages>''')
-+ included = [msg.attrs['name'] for msg in grd.ActiveDescendants()
-+ if msg.name == 'message']
-+ self.assertEqual(['IDS_YES1', 'IDS_YES2', 'IDS_YES3', 'IDS_YES4'], included)
-+
-+ def testIffynessWithOutputNodes(self):
-+ grd = grd_reader.Parse(StringIO('''
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <outputs>
-+ <output filename="uncond1.rc" type="rc_data" />
-+ <if expr="lang == 'fr' or 'hello' in defs">
-+ <output filename="only_fr.adm" type="adm" />
-+ <output filename="only_fr.plist" type="plist" />
-+ </if>
-+ <if expr="lang == 'ru'">
-+ <output filename="doc.html" type="document" />
-+ </if>
-+ <output filename="uncond2.adm" type="adm" />
-+ <output filename="iftest.h" type="rc_header">
-+ <emit emit_type='prepend'></emit>
-+ </output>
-+ </outputs>
-+ </grit>'''), dir='.')
-+
-+ outputs_node = grd.children[0]
-+ uncond1_output = outputs_node.children[0]
-+ only_fr_adm_output = outputs_node.children[1].children[0]
-+ only_fr_plist_output = outputs_node.children[1].children[1]
-+ doc_output = outputs_node.children[2].children[0]
-+ uncond2_output = outputs_node.children[0]
-+ self.assertTrue(uncond1_output.name == 'output')
-+ self.assertTrue(only_fr_adm_output.name == 'output')
-+ self.assertTrue(only_fr_plist_output.name == 'output')
-+ self.assertTrue(doc_output.name == 'output')
-+ self.assertTrue(uncond2_output.name == 'output')
-+
-+ grd.SetOutputLanguage('ru')
-+ grd.SetDefines({'hello': '1'})
-+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
-+ self.assertEquals(
-+ outputs,
-+ ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'doc.html',
-+ 'uncond2.adm', 'iftest.h'])
-+
-+ grd.SetOutputLanguage('ru')
-+ grd.SetDefines({'bingo': '2'})
-+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
-+ self.assertEquals(
-+ outputs,
-+ ['uncond1.rc', 'doc.html', 'uncond2.adm', 'iftest.h'])
-+
-+ grd.SetOutputLanguage('fr')
-+ grd.SetDefines({'hello': '1'})
-+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
-+ self.assertEquals(
-+ outputs,
-+ ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'uncond2.adm',
-+ 'iftest.h'])
-+
-+ grd.SetOutputLanguage('en')
-+ grd.SetDefines({'bingo': '1'})
-+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
-+ self.assertEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
-+
-+ grd.SetOutputLanguage('fr')
-+ grd.SetDefines({'bingo': '1'})
-+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
-+ self.assertNotEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
-+
-+ def testChildrenAccepted(self):
-+ grd_reader.Parse(StringIO(r'''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <includes>
-+ <if expr="'bingo' in defs">
-+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
-+ </if>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
-+ </if>
-+ </if>
-+ </includes>
-+ <structures>
-+ <if expr="'bingo' in defs">
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
-+ </if>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
-+ </if>
-+ </if>
-+ </structures>
-+ <messages>
-+ <if expr="'bingo' in defs">
-+ <message name="IDS_BINGO">Bingo!</message>
-+ </if>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <message name="IDS_BINGO">Bingo!</message>
-+ </if>
-+ </if>
-+ </messages>
-+ </release>
-+ <translations>
-+ <if expr="'bingo' in defs">
-+ <file lang="nl" path="nl_translations.xtb" />
-+ </if>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <file lang="nl" path="nl_translations.xtb" />
-+ </if>
-+ </if>
-+ </translations>
-+ </grit>'''), dir='.')
-+
-+ def testIfBadChildrenNesting(self):
-+ # includes
-+ xml = StringIO(r'''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <includes>
-+ <if expr="'bingo' in defs">
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
-+ </if>
-+ </includes>
-+ </release>
-+ </grit>''')
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+ # messages
-+ xml = StringIO(r'''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <if expr="'bingo' in defs">
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
-+ </if>
-+ </messages>
-+ </release>
-+ </grit>''')
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+ # structures
-+ xml = StringIO('''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <structures>
-+ <if expr="'bingo' in defs">
-+ <message name="IDS_BINGO">Bingo!</message>
-+ </if>
-+ </structures>
-+ </release>
-+ </grit>''')
-+ # translations
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+ xml = StringIO('''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <translations>
-+ <if expr="'bingo' in defs">
-+ <message name="IDS_BINGO">Bingo!</message>
-+ </if>
-+ </translations>
-+ </grit>''')
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+ # same with nesting
-+ xml = StringIO(r'''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <includes>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
-+ </if>
-+ </if>
-+ </includes>
-+ </release>
-+ </grit>''')
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+ xml = StringIO(r'''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\test\data\klonk.rc" encoding="utf-16" />
-+ </if>
-+ </if>
-+ </messages>
-+ </release>
-+ </grit>''')
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+ xml = StringIO('''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <structures>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <message name="IDS_BINGO">Bingo!</message>
-+ </if>
-+ </if>
-+ </structures>
-+ </release>
-+ </grit>''')
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+ xml = StringIO('''<?xml version="1.0"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <translations>
-+ <if expr="'bingo' in defs">
-+ <if expr="'hello' in defs">
-+ <message name="IDS_BINGO">Bingo!</message>
-+ </if>
-+ </if>
-+ </translations>
-+ </grit>''')
-+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
-+
-+
-+class ReleaseNodeUnittest(unittest.TestCase):
-+ def testPseudoControl(self):
-+ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="1" source_lang_id="en-US" current_release="2" base_dir=".">
-+ <release seq="1" allow_pseudo="false">
-+ <messages>
-+ <message name="IDS_HELLO">
-+ Hello
-+ </message>
-+ </messages>
-+ <structures>
-+ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
-+ </structures>
-+ </release>
-+ <release seq="2">
-+ <messages>
-+ <message name="IDS_BINGO">
-+ Bingo
-+ </message>
-+ </messages>
-+ <structures>
-+ <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
-+ </structures>
-+ </release>
-+ </grit>'''), util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+
-+ hello = grd.GetNodeById('IDS_HELLO')
-+ aboutbox = grd.GetNodeById('IDD_ABOUTBOX')
-+ bingo = grd.GetNodeById('IDS_BINGO')
-+ menu = grd.GetNodeById('IDC_KLONKMENU')
-+
-+ for node in [hello, aboutbox]:
-+ self.failUnless(not node.PseudoIsAllowed())
-+
-+ for node in [bingo, menu]:
-+ self.failUnless(node.PseudoIsAllowed())
-+
-+ # TODO(benrg): There was a test here that formatting hello and aboutbox with
-+ # a pseudo language should fail, but they do not fail and the test was
-+ # broken and failed to catch it. Fix this.
-+
-+ # Should not raise an exception since pseudo is allowed
-+ rc.FormatMessage(bingo, 'xyz-pseudo')
-+ rc.FormatStructure(menu, 'xyz-pseudo', '.')
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/mock_brotli.py b/tools/grit/grit/node/mock_brotli.py
-new file mode 100644
-index 0000000000..14237aab20
---- /dev/null
-+++ b/tools/grit/grit/node/mock_brotli.py
-@@ -0,0 +1,10 @@
-+#!/usr/bin/env python
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Mock Brotli Executable for testing purposes."""
-+
-+import sys
-+
-+sys.stdout.write('This has been mock compressed!')
-diff --git a/tools/grit/grit/node/node_io.py b/tools/grit/grit/node/node_io.py
-new file mode 100644
-index 0000000000..ccbc2c0647
---- /dev/null
-+++ b/tools/grit/grit/node/node_io.py
-@@ -0,0 +1,117 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The <output> and <file> elements.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+
-+from grit import xtb_reader
-+from grit.node import base
-+
-+
-+class FileNode(base.Node):
-+ '''A <file> element.'''
-+
-+ def __init__(self):
-+ super(FileNode, self).__init__()
-+ self.re = None
-+ self.should_load_ = True
-+
-+ def IsTranslation(self):
-+ return True
-+
-+ def GetLang(self):
-+ return self.attrs['lang']
-+
-+ def DisableLoading(self):
-+ self.should_load_ = False
-+
-+ def MandatoryAttributes(self):
-+ return ['path', 'lang']
-+
-+ def RunPostSubstitutionGatherer(self, debug=False):
-+ if not self.should_load_:
-+ return
-+
-+ root = self.GetRoot()
-+ defs = getattr(root, 'defines', {})
-+ target_platform = getattr(root, 'target_platform', '')
-+
-+ xtb_file = open(self.ToRealPath(self.GetInputPath()), 'rb')
-+ try:
-+ lang = xtb_reader.Parse(xtb_file,
-+ self.UberClique().GenerateXtbParserCallback(
-+ self.attrs['lang'], debug=debug),
-+ defs=defs,
-+ target_platform=target_platform)
-+ except:
-+ print("Exception during parsing of %s" % self.GetInputPath())
-+ raise
-+ # Translation console uses non-standard language codes 'iw' and 'no' for
-+ # Hebrew and Norwegian Bokmal instead of 'he' and 'nb' used in Chrome.
-+ # Note that some Chrome's .grd still use 'no' instead of 'nb', but 'nb' is
-+ # always used for generated .pak files.
-+ ALTERNATIVE_LANG_CODE_MAP = { 'he': 'iw', 'nb': 'no' }
-+ assert (lang == self.attrs['lang'] or
-+ lang == ALTERNATIVE_LANG_CODE_MAP[self.attrs['lang']]), (
-+ 'The XTB file you reference must contain messages in the language '
-+ 'specified\nby the \'lang\' attribute.')
-+
-+ def GetInputPath(self):
-+ return os.path.expandvars(self.attrs['path'])
-+
-+
-+class OutputNode(base.Node):
-+ '''An <output> element.'''
-+
-+ def MandatoryAttributes(self):
-+ return ['filename', 'type']
-+
-+ def DefaultAttributes(self):
-+ return {
-+ 'lang' : '', # empty lang indicates all languages
-+ 'language_section' : 'neutral', # defines a language neutral section
-+ 'context' : '',
-+ 'fallback_to_default_layout' : 'true',
-+ }
-+
-+ def GetType(self):
-+ return self.attrs['type']
-+
-+ def GetLanguage(self):
-+ '''Returns the language ID, default 'en'.'''
-+ return self.attrs['lang']
-+
-+ def GetContext(self):
-+ return self.attrs['context']
-+
-+ def GetFilename(self):
-+ return self.attrs['filename']
-+
-+ def GetOutputFilename(self):
-+ path = None
-+ if hasattr(self, 'output_filename'):
-+ path = self.output_filename
-+ else:
-+ path = self.attrs['filename']
-+ return os.path.expandvars(path)
-+
-+ def GetFallbackToDefaultLayout(self):
-+ return self.attrs['fallback_to_default_layout'].lower() == 'true'
-+
-+ def _IsValidChild(self, child):
-+ return isinstance(child, EmitNode)
-+
-+class EmitNode(base.ContentNode):
-+ ''' An <emit> element.'''
-+
-+ def DefaultAttributes(self):
-+ return { 'emit_type' : 'prepend'}
-+
-+ def GetEmitType(self):
-+ '''Returns the emit_type for this node. Default is 'append'.'''
-+ return self.attrs['emit_type']
-diff --git a/tools/grit/grit/node/node_io_unittest.py b/tools/grit/grit/node/node_io_unittest.py
-new file mode 100644
-index 0000000000..1f45e51af8
---- /dev/null
-+++ b/tools/grit/grit/node/node_io_unittest.py
-@@ -0,0 +1,182 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for node_io.FileNode'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import unittest
-+
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+from six import StringIO
-+
-+from grit.node import misc
-+from grit.node import node_io
-+from grit.node import empty
-+from grit import grd_reader
-+from grit import util
-+
-+
-+def _GetAllCliques(root_node):
-+ """Return all cliques in the |root_node| tree."""
-+ ret = []
-+ for node in root_node:
-+ ret.extend(node.GetCliques())
-+ return ret
-+
-+
-+class FileNodeUnittest(unittest.TestCase):
-+ def testGetPath(self):
-+ root = misc.GritNode()
-+ root.StartParsing(u'grit', None)
-+ root.HandleAttribute(u'latest_public_release', u'0')
-+ root.HandleAttribute(u'current_release', u'1')
-+ root.HandleAttribute(u'base_dir', r'..\resource')
-+ translations = empty.TranslationsNode()
-+ translations.StartParsing(u'translations', root)
-+ root.AddChild(translations)
-+ file_node = node_io.FileNode()
-+ file_node.StartParsing(u'file', translations)
-+ file_node.HandleAttribute(u'path', r'flugel\kugel.pdf')
-+ translations.AddChild(file_node)
-+ root.EndParsing()
-+
-+ self.failUnless(root.ToRealPath(file_node.GetInputPath()) ==
-+ util.normpath(
-+ os.path.join(r'../resource', r'flugel/kugel.pdf')))
-+
-+ def VerifyCliquesContainEnglishAndFrenchAndNothingElse(self, cliques):
-+ self.assertEqual(2, len(cliques))
-+ for clique in cliques:
-+ self.assertEqual({'en', 'fr'}, set(clique.clique.keys()))
-+
-+ def testLoadTranslations(self):
-+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <translations>
-+ <file path="generated_resources_fr.xtb" lang="fr" />
-+ </translations>
-+ <release seq="3">
-+ <messages>
-+ <message name="ID_HELLO">Hello!</message>
-+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
-+ </messages>
-+ </release>
-+ </grit>'''
-+ grd = grd_reader.Parse(StringIO(xml),
-+ util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(_GetAllCliques(grd))
-+
-+ def testIffyness(self):
-+ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <translations>
-+ <if expr="lang == 'fr'">
-+ <file path="generated_resources_fr.xtb" lang="fr" />
-+ </if>
-+ </translations>
-+ <release seq="3">
-+ <messages>
-+ <message name="ID_HELLO">Hello!</message>
-+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
-+ </messages>
-+ </release>
-+ </grit>'''), util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ cliques = _GetAllCliques(grd)
-+ self.assertEqual(2, len(cliques))
-+ for clique in cliques:
-+ self.assertEqual({'en'}, set(clique.clique.keys()))
-+
-+ grd.SetOutputLanguage('fr')
-+ grd.RunGatherers()
-+ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(_GetAllCliques(grd))
-+
-+ def testConditionalLoadTranslations(self):
-+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
-+ base_dir=".">
-+ <translations>
-+ <if expr="True">
-+ <file path="generated_resources_fr.xtb" lang="fr" />
-+ </if>
-+ <if expr="False">
-+ <file path="no_such_file.xtb" lang="de" />
-+ </if>
-+ </translations>
-+ <release seq="3">
-+ <messages>
-+ <message name="ID_HELLO">Hello!</message>
-+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
-+ Joi</ex></ph></message>
-+ </messages>
-+ </release>
-+ </grit>'''
-+ grd = grd_reader.Parse(StringIO(xml),
-+ util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(_GetAllCliques(grd))
-+
-+ def testConditionalOutput(self):
-+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
-+ base_dir=".">
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="en/generated_resources.rc" type="rc_all"
-+ lang="en" />
-+ <if expr="pp_if('NOT_TRUE')">
-+ <output filename="de/generated_resources.rc" type="rc_all"
-+ lang="de" />
-+ </if>
-+ </outputs>
-+ <release seq="3">
-+ <messages>
-+ <message name="ID_HELLO">Hello!</message>
-+ </messages>
-+ </release>
-+ </grit>'''
-+ grd = grd_reader.Parse(StringIO(xml),
-+ util.PathFromRoot('grit/test/data'),
-+ defines={})
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ outputs = grd.GetChildrenOfType(node_io.OutputNode)
-+ active = set(grd.ActiveDescendants())
-+ self.failUnless(outputs[0] in active)
-+ self.failUnless(outputs[0].GetType() == 'rc_header')
-+ self.failUnless(outputs[1] in active)
-+ self.failUnless(outputs[1].GetType() == 'rc_all')
-+ self.failUnless(outputs[2] not in active)
-+ self.failUnless(outputs[2].GetType() == 'rc_all')
-+
-+ # Verify that 'iw' and 'no' language codes in xtb files are mapped to 'he' and
-+ # 'nb'.
-+ def testLangCodeMapping(self):
-+ grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <translations>
-+ <file path="generated_resources_no.xtb" lang="nb" />
-+ <file path="generated_resources_iw.xtb" lang="he" />
-+ </translations>
-+ <release seq="3">
-+ <messages></messages>
-+ </release>
-+ </grit>'''), util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ self.assertEqual([], _GetAllCliques(grd))
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/structure.py b/tools/grit/grit/node/structure.py
-new file mode 100644
-index 0000000000..ec170faebb
---- /dev/null
-+++ b/tools/grit/grit/node/structure.py
-@@ -0,0 +1,375 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The <structure> element.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import platform
-+import re
-+
-+from grit import exception
-+from grit import util
-+from grit.node import base
-+from grit.node import variant
-+
-+import grit.gather.admin_template
-+import grit.gather.chrome_html
-+import grit.gather.chrome_scaled_image
-+import grit.gather.policy_json
-+import grit.gather.rc
-+import grit.gather.tr_html
-+import grit.gather.txt
-+
-+import grit.format.rc
-+
-+# Type of the gatherer to use for each type attribute
-+_GATHERERS = {
-+ 'accelerators' : grit.gather.rc.Accelerators,
-+ 'admin_template' : grit.gather.admin_template.AdmGatherer,
-+ 'chrome_html' : grit.gather.chrome_html.ChromeHtml,
-+ 'chrome_scaled_image' : grit.gather.chrome_scaled_image.ChromeScaledImage,
-+ 'dialog' : grit.gather.rc.Dialog,
-+ 'menu' : grit.gather.rc.Menu,
-+ 'rcdata' : grit.gather.rc.RCData,
-+ 'tr_html' : grit.gather.tr_html.TrHtml,
-+ 'txt' : grit.gather.txt.TxtFile,
-+ 'version' : grit.gather.rc.Version,
-+ 'policy_template_metafile' : grit.gather.policy_json.PolicyJson,
-+}
-+
-+
-+# TODO(joi) Print a warning if the 'variant_of_revision' attribute indicates
-+# that a skeleton variant is older than the original file.
-+
-+
-+class StructureNode(base.Node):
-+ '''A <structure> element.'''
-+
-+ # Regular expression for a local variable definition. Each definition
-+ # is of the form NAME=VALUE, where NAME cannot contain '=' or ',' and
-+ # VALUE must escape all commas: ',' -> ',,'. Each variable definition
-+ # should be separated by a comma with no extra whitespace.
-+ # Example: THING1=foo,THING2=bar
-+ variable_pattern = re.compile(r'([^,=\s]+)=((?:,,|[^,])*)')
-+
-+ def __init__(self):
-+ super(StructureNode, self).__init__()
-+
-+ # Keep track of the last filename we flattened to, so we can
-+ # avoid doing it more than once.
-+ self._last_flat_filename = None
-+
-+ # See _Substitute; this substituter is used for local variables and
-+ # the root substituter is used for global variables.
-+ self.substituter = None
-+
-+ def _IsValidChild(self, child):
-+ return isinstance(child, variant.SkeletonNode)
-+
-+ def _ParseVariables(self, variables):
-+ '''Parse a variable string into a dictionary.'''
-+ matches = StructureNode.variable_pattern.findall(variables)
-+ return dict((name, value.replace(',,', ',')) for name, value in matches)
-+
-+ def EndParsing(self):
-+ super(StructureNode, self).EndParsing()
-+
-+ # Now that we have attributes and children, instantiate the gatherers.
-+ gathertype = _GATHERERS[self.attrs['type']]
-+
-+ self.gatherer = gathertype(self.attrs['file'],
-+ self.attrs['name'],
-+ self.attrs['encoding'])
-+ self.gatherer.SetGrdNode(self)
-+ self.gatherer.SetUberClique(self.UberClique())
-+ if hasattr(self.GetRoot(), 'defines'):
-+ self.gatherer.SetDefines(self.GetRoot().defines)
-+ self.gatherer.SetAttributes(self.attrs)
-+ if self.ExpandVariables():
-+ self.gatherer.SetFilenameExpansionFunction(self._Substitute)
-+
-+ # Parse local variables and instantiate the substituter.
-+ if self.attrs['variables']:
-+ variables = self.attrs['variables']
-+ self.substituter = util.Substituter()
-+ self.substituter.AddSubstitutions(self._ParseVariables(variables))
-+
-+ self.skeletons = {} # Maps expressions to skeleton gatherers
-+ for child in self.children:
-+ assert isinstance(child, variant.SkeletonNode)
-+ skel = gathertype(child.attrs['file'],
-+ self.attrs['name'],
-+ child.GetEncodingToUse(),
-+ is_skeleton=True)
-+ skel.SetGrdNode(self) # TODO(benrg): Or child? Only used for ToRealPath
-+ skel.SetUberClique(self.UberClique())
-+ if hasattr(self.GetRoot(), 'defines'):
-+ skel.SetDefines(self.GetRoot().defines)
-+ if self.ExpandVariables():
-+ skel.SetFilenameExpansionFunction(self._Substitute)
-+ self.skeletons[child.attrs['expr']] = skel
-+
-+ def MandatoryAttributes(self):
-+ return ['type', 'name', 'file']
-+
-+ def DefaultAttributes(self):
-+ return {
-+ 'encoding': 'cp1252',
-+ 'exclude_from_rc': 'false',
-+ 'line_end': 'unix',
-+ 'output_encoding': 'utf-8',
-+ 'generateid': 'true',
-+ 'expand_variables': 'false',
-+ 'output_filename': '',
-+ 'fold_whitespace': 'false',
-+ # Run an arbitrary command after translation is complete
-+ # so that it doesn't interfere with what's in translation
-+ # console.
-+ 'run_command': '',
-+ # Leave empty to run on all platforms, comma-separated
-+ # for one or more specific platforms. Values must match
-+ # output of platform.system().
-+ 'run_command_on_platforms': '',
-+ 'allowexternalscript': 'false',
-+ # preprocess takes the same code path as flattenhtml, but it
-+ # disables any processing/inlining outside of <if> and <include>.
-+ 'preprocess': 'false',
-+ 'flattenhtml': 'false',
-+ 'fallback_to_low_resolution': 'default',
-+ 'variables': '',
-+ 'compress': 'default',
-+ 'use_base_dir': 'true',
-+ }
-+
-+ def IsExcludedFromRc(self):
-+ return self.attrs['exclude_from_rc'] == 'true'
-+
-+ def Process(self, output_dir):
-+ """Writes the processed data to output_dir. In the case of a chrome_html
-+ structure this will add references to other scale factors. If flattening
-+ this will also write file references to be base64 encoded data URLs. The
-+ name of the new file is returned."""
-+ filename = self.ToRealPath(self.GetInputPath())
-+ flat_filename = os.path.join(output_dir,
-+ self.attrs['name'] + '_' + os.path.basename(filename))
-+
-+ if self._last_flat_filename == flat_filename:
-+ return
-+
-+ with open(flat_filename, 'wb') as outfile:
-+ if self.ExpandVariables():
-+ text = self.gatherer.GetText()
-+ file_contents = self._Substitute(text)
-+ else:
-+ file_contents = self.gatherer.GetData('', 'utf-8')
-+ outfile.write(file_contents.encode('utf-8'))
-+
-+ self._last_flat_filename = flat_filename
-+ return os.path.basename(flat_filename)
-+
-+ def GetLineEnd(self):
-+ '''Returns the end-of-line character or characters for files output because
-+ of this node ('\r\n', '\n', or '\r' depending on the 'line_end' attribute).
-+ '''
-+ if self.attrs['line_end'] == 'unix':
-+ return '\n'
-+ elif self.attrs['line_end'] == 'windows':
-+ return '\r\n'
-+ elif self.attrs['line_end'] == 'mac':
-+ return '\r'
-+ else:
-+ raise exception.UnexpectedAttribute(
-+ "Attribute 'line_end' must be one of 'unix' (default), 'windows' or "
-+ "'mac'")
-+
-+ def GetCliques(self):
-+ return self.gatherer.GetCliques()
-+
-+ def GetDataPackValue(self, lang, encoding):
-+ """Returns a bytes representation for a data_pack entry."""
-+ if self.ExpandVariables():
-+ text = self.gatherer.GetText()
-+ data = util.Encode(self._Substitute(text), encoding)
-+ else:
-+ data = self.gatherer.GetData(lang, encoding)
-+ if encoding != util.BINARY:
-+ data = data.encode(encoding)
-+ return self.CompressDataIfNeeded(data)
-+
-+ def GetHtmlResourceFilenames(self):
-+ """Returns a set of all filenames inlined by this node."""
-+ return self.gatherer.GetHtmlResourceFilenames()
-+
-+ def GetInputPath(self):
-+ path = self.gatherer.GetInputPath()
-+ if path is None:
-+ return path
-+
-+ # Do not mess with absolute paths, that would make them invalid.
-+ if os.path.isabs(os.path.expandvars(path)):
-+ return path
-+
-+ # We have no control over code that calls ToRealPath later, so convert
-+ # the path to be relative against our basedir.
-+ if self.attrs.get('use_base_dir', 'true') != 'true':
-+ # Normalize the directory path to use the appropriate OS separator.
-+ # GetBaseDir() may return paths\like\this or paths/like/this, since it is
-+ # read from the base_dir attribute in the grd file.
-+ norm_base_dir = util.normpath(self.GetRoot().GetBaseDir())
-+ return os.path.relpath(path, norm_base_dir)
-+
-+ return path
-+
-+ def GetTextualIds(self):
-+ if not hasattr(self, 'gatherer'):
-+ # This case is needed because this method is called by
-+ # GritNode.ValidateUniqueIds before RunGatherers has been called.
-+ # TODO(benrg): Fix this?
-+ return [self.attrs['name']]
-+ return self.gatherer.GetTextualIds()
-+
-+ def RunPreSubstitutionGatherer(self, debug=False):
-+ if debug:
-+ print('Running gatherer %s for file %s' %
-+ (type(self.gatherer), self.GetInputPath()))
-+
-+ # Note: Parse() is idempotent, therefore this method is also.
-+ self.gatherer.Parse()
-+ for skel in self.skeletons.values():
-+ skel.Parse()
-+
-+ def GetSkeletonGatherer(self):
-+ '''Returns the gatherer for the alternate skeleton that should be used,
-+ based on the expressions for selecting skeletons, or None if the skeleton
-+ from the English version of the structure should be used.
-+ '''
-+ for expr in self.skeletons:
-+ if self.EvaluateCondition(expr):
-+ return self.skeletons[expr]
-+ return None
-+
-+ def HasFileForLanguage(self):
-+ return self.attrs['type'] in ['tr_html', 'admin_template', 'txt',
-+ 'chrome_scaled_image',
-+ 'chrome_html']
-+
-+ def ExpandVariables(self):
-+ '''Variable expansion on structures is controlled by an XML attribute.
-+
-+ However, old files assume that expansion is always on for Rc files.
-+
-+ Returns:
-+ A boolean.
-+ '''
-+ attrs = self.GetRoot().attrs
-+ if 'grit_version' in attrs and attrs['grit_version'] > 1:
-+ return self.attrs['expand_variables'] == 'true'
-+ else:
-+ return (self.attrs['expand_variables'] == 'true' or
-+ self.attrs['file'].lower().endswith('.rc'))
-+
-+ def _Substitute(self, text):
-+ '''Perform local and global variable substitution.'''
-+ if self.substituter:
-+ text = self.substituter.Substitute(text)
-+ return self.GetRoot().GetSubstituter().Substitute(text)
-+
-+ def RunCommandOnCurrentPlatform(self):
-+ if self.attrs['run_command_on_platforms'] == '':
-+ return True
-+ else:
-+ target_platforms = self.attrs['run_command_on_platforms'].split(',')
-+ return platform.system() in target_platforms
-+
-+ def FileForLanguage(self, lang, output_dir, create_file=True,
-+ return_if_not_generated=True):
-+ '''Returns the filename of the file associated with this structure,
-+ for the specified language.
-+
-+ Args:
-+ lang: 'fr'
-+ output_dir: 'c:\temp'
-+ create_file: True
-+ '''
-+ assert self.HasFileForLanguage()
-+ # If the source language is requested, and no extra changes are requested,
-+ # use the existing file.
-+ if ((not lang or lang == self.GetRoot().GetSourceLanguage()) and
-+ self.attrs['expand_variables'] != 'true' and
-+ (not self.attrs['run_command'] or
-+ not self.RunCommandOnCurrentPlatform())):
-+ if return_if_not_generated:
-+ input_path = self.GetInputPath()
-+ if input_path is None:
-+ return None
-+ return self.ToRealPath(input_path)
-+ else:
-+ return None
-+
-+ if self.attrs['output_filename'] != '':
-+ filename = self.attrs['output_filename']
-+ else:
-+ filename = os.path.basename(self.attrs['file'])
-+ assert len(filename)
-+ filename = '%s_%s' % (lang, filename)
-+ filename = os.path.join(output_dir, filename)
-+
-+ # Only create the output if it was requested by the call.
-+ if create_file:
-+ text = self.gatherer.Translate(
-+ lang,
-+ pseudo_if_not_available=self.PseudoIsAllowed(),
-+ fallback_to_english=self.ShouldFallbackToEnglish(),
-+ skeleton_gatherer=self.GetSkeletonGatherer())
-+
-+ file_contents = util.FixLineEnd(text, self.GetLineEnd())
-+ if self.ExpandVariables():
-+ # Note that we reapply substitution a second time here.
-+ # This is because a) we need to look inside placeholders
-+ # b) the substitution values are language-dependent
-+ file_contents = self._Substitute(file_contents)
-+
-+ with open(filename, 'wb') as file_object:
-+ output_stream = util.WrapOutputStream(file_object,
-+ self.attrs['output_encoding'])
-+ output_stream.write(file_contents)
-+
-+ if self.attrs['run_command'] and self.RunCommandOnCurrentPlatform():
-+ # Run arbitrary commands after translation is complete so that it
-+ # doesn't interfere with what's in translation console.
-+ command = self.attrs['run_command'] % {'filename': filename}
-+ result = os.system(command)
-+ assert result == 0, '"%s" failed.' % command
-+
-+ return filename
-+
-+ def IsResourceMapSource(self):
-+ return True
-+
-+ @staticmethod
-+ def Construct(parent, name, type, file, encoding='cp1252'):
-+ '''Creates a new node which is a child of 'parent', with attributes set
-+ by parameters of the same name.
-+ '''
-+ node = StructureNode()
-+ node.StartParsing('structure', parent)
-+ node.HandleAttribute('name', name)
-+ node.HandleAttribute('type', type)
-+ node.HandleAttribute('file', file)
-+ node.HandleAttribute('encoding', encoding)
-+ node.EndParsing()
-+ return node
-+
-+ def SubstituteMessages(self, substituter):
-+ '''Propagates substitution to gatherer.
-+
-+ Args:
-+ substituter: a grit.util.Substituter object.
-+ '''
-+ assert hasattr(self, 'gatherer')
-+ if self.ExpandVariables():
-+ self.gatherer.SubstituteMessages(substituter)
-diff --git a/tools/grit/grit/node/structure_unittest.py b/tools/grit/grit/node/structure_unittest.py
-new file mode 100644
-index 0000000000..0e66dce37a
---- /dev/null
-+++ b/tools/grit/grit/node/structure_unittest.py
-@@ -0,0 +1,178 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for <structure> nodes.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import os.path
-+import sys
-+import zlib
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import platform
-+import tempfile
-+import unittest
-+import struct
-+
-+from grit import constants
-+from grit import util
-+from grit.node import brotli_util
-+from grit.node import structure
-+from grit.format import rc
-+
-+
-+def checkIsGzipped(filename, compress_attr):
-+ test_data_root = util.PathFromRoot('grit/testdata')
-+ root = util.ParseGrdForUnittest(
-+ '''
-+ <structures>
-+ <structure name="TEST_TXT" file="%s" %s type="chrome_html"/>
-+ </structures>''' % (filename, compress_attr),
-+ base_dir=test_data_root)
-+ node, = root.GetChildrenOfType(structure.StructureNode)
-+ node.RunPreSubstitutionGatherer()
-+ compressed = node.GetDataPackValue(lang='en', encoding=util.BINARY)
-+
-+ decompressed_data = zlib.decompress(compressed, 16 + zlib.MAX_WBITS)
-+ expected = util.ReadFile(os.path.join(test_data_root, filename), util.BINARY)
-+ return expected == decompressed_data
-+
-+
-+class StructureUnittest(unittest.TestCase):
-+ def testSkeleton(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure type="dialog" name="IDD_ABOUTBOX" file="klonk.rc" encoding="utf-16-le">
-+ <skeleton expr="lang == 'fr'" variant_of_revision="1" file="klonk-alternate-skeleton.rc" />
-+ </structure>
-+ </structures>''', base_dir=util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('fr')
-+ grd.RunGatherers()
-+ transl = ''.join(rc.Format(grd, 'fr', '.'))
-+ self.failUnless(transl.count('040704') and transl.count('110978'))
-+ self.failUnless(transl.count('2005",IDC_STATIC'))
-+
-+ def testRunCommandOnCurrentPlatform(self):
-+ node = structure.StructureNode()
-+ node.attrs = node.DefaultAttributes()
-+ self.failUnless(node.RunCommandOnCurrentPlatform())
-+ node.attrs['run_command_on_platforms'] = 'Nosuch'
-+ self.failIf(node.RunCommandOnCurrentPlatform())
-+ node.attrs['run_command_on_platforms'] = (
-+ 'Nosuch,%s,Othernot' % platform.system())
-+ self.failUnless(node.RunCommandOnCurrentPlatform())
-+
-+ def testVariables(self):
-+ grd = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure type="chrome_html" name="hello_tmpl" file="structure_variables.html" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true"></structure>
-+ </structures>''', base_dir=util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ node, = grd.GetChildrenOfType(structure.StructureNode)
-+ filename = node.Process(tempfile.gettempdir())
-+ filepath = os.path.join(tempfile.gettempdir(), filename)
-+ with open(filepath) as f:
-+ result = f.read()
-+ self.failUnlessEqual(('<h1>Hello!</h1>\n'
-+ 'Some cool things are foo, bar, baz.\n'
-+ 'Did you know that 2+2==4?\n'
-+ '<p>\n'
-+ ' Hello!\n'
-+ '</p>\n'), result)
-+ os.remove(filepath)
-+
-+ def testGetPath(self):
-+ base_dir = util.PathFromRoot('grit/testdata')
-+ grd = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure type="chrome_html" name="hello_tmpl" file="structure_variables.html" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true" use_base_dir="true"></structure>
-+ </structures>''', base_dir)
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ node, = grd.GetChildrenOfType(structure.StructureNode)
-+ self.assertEqual(grd.ToRealPath(node.GetInputPath()),
-+ os.path.abspath(os.path.join(
-+ base_dir, r'structure_variables.html')))
-+
-+ def testGetPathNoBasedir(self):
-+ base_dir = util.PathFromRoot('grit/testdata')
-+ abs_path = os.path.join(base_dir, r'structure_variables.html')
-+ rel_path = os.path.relpath(abs_path, os.getcwd())
-+ grd = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure type="chrome_html" name="hello_tmpl" file="''' + rel_path + '''" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true" use_base_dir="false"></structure>
-+ </structures>''', util.PathFromRoot('grit/testdata'))
-+ grd.SetOutputLanguage('en')
-+ grd.RunGatherers()
-+ node, = grd.GetChildrenOfType(structure.StructureNode)
-+ self.assertEqual(grd.ToRealPath(node.GetInputPath()),
-+ os.path.abspath(os.path.join(
-+ base_dir, r'structure_variables.html')))
-+
-+ def testCompressGzip(self):
-+ self.assertTrue(checkIsGzipped('test_text.txt', 'compress="gzip"'))
-+
-+ def testCompressGzipByDefault(self):
-+ self.assertTrue(checkIsGzipped('test_html.html', ''))
-+ self.assertTrue(checkIsGzipped('test_js.js', ''))
-+ self.assertTrue(checkIsGzipped('test_css.css', ''))
-+ self.assertTrue(checkIsGzipped('test_svg.svg', ''))
-+
-+ self.assertTrue(checkIsGzipped('test_html.html', 'compress="default"'))
-+ self.assertTrue(checkIsGzipped('test_js.js', 'compress="default"'))
-+ self.assertTrue(checkIsGzipped('test_css.css', 'compress="default"'))
-+ self.assertTrue(checkIsGzipped('test_svg.svg', 'compress="default"'))
-+
-+ def testCompressBrotli(self):
-+ test_data_root = util.PathFromRoot('grit/testdata')
-+ root = util.ParseGrdForUnittest(
-+ '''
-+ <structures>
-+ <structure name="TEST_TXT" file="test_text.txt"
-+ compress="brotli" type="chrome_html" />
-+ </structures>''',
-+ base_dir=test_data_root)
-+ node, = root.GetChildrenOfType(structure.StructureNode)
-+ node.RunPreSubstitutionGatherer()
-+
-+ # Using the mock brotli decompression executable.
-+ brotli_util.SetBrotliCommand([sys.executable,
-+ os.path.join(os.path.dirname(__file__),
-+ 'mock_brotli.py')])
-+ compressed = node.GetDataPackValue(lang='en', encoding=util.BINARY)
-+ # Assert that the first two bytes in compressed format is BROTLI_CONST.
-+ self.assertEqual(constants.BROTLI_CONST, compressed[0:2])
-+
-+ # Compare the actual size of the uncompressed test data with
-+ # the size appended during compression.
-+ actual_size = len(util.ReadFile(
-+ os.path.join(test_data_root, 'test_text.txt'), util.BINARY))
-+ uncompress_size = struct.unpack('<i', compressed[2:6])[0]
-+ uncompress_size += struct.unpack('<h', compressed[6:8])[0] << 4*8
-+ self.assertEqual(actual_size, uncompress_size)
-+
-+ self.assertEqual(b'This has been mock compressed!', compressed[8:])
-+
-+ def testNotCompressed(self):
-+ test_data_root = util.PathFromRoot('grit/testdata')
-+ root = util.ParseGrdForUnittest('''
-+ <structures>
-+ <structure name="TEST_TXT" file="test_text.txt" type="chrome_html" />
-+ </structures>''', base_dir=test_data_root)
-+ node, = root.GetChildrenOfType(structure.StructureNode)
-+ node.RunPreSubstitutionGatherer()
-+ data = node.GetDataPackValue(lang='en', encoding=util.BINARY)
-+
-+ self.assertEqual(util.ReadFile(
-+ os.path.join(test_data_root, 'test_text.txt'), util.BINARY), data)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/node/variant.py b/tools/grit/grit/node/variant.py
-new file mode 100644
-index 0000000000..9f5845f954
---- /dev/null
-+++ b/tools/grit/grit/node/variant.py
-@@ -0,0 +1,41 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The <skeleton> element.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit.node import base
-+
-+
-+class SkeletonNode(base.Node):
-+ '''A <skeleton> element.'''
-+
-+ # TODO(joi) Support inline skeleton variants as CDATA instead of requiring
-+ # a 'file' attribute.
-+
-+ def MandatoryAttributes(self):
-+ return ['expr', 'variant_of_revision', 'file']
-+
-+ def DefaultAttributes(self):
-+ '''If not specified, 'encoding' will actually default to the parent node's
-+ encoding.
-+ '''
-+ return {'encoding' : ''}
-+
-+ def _ContentType(self):
-+ if 'file' in self.attrs:
-+ return self._CONTENT_TYPE_NONE
-+ else:
-+ return self._CONTENT_TYPE_CDATA
-+
-+ def GetEncodingToUse(self):
-+ if self.attrs['encoding'] == '':
-+ return self.parent.attrs['encoding']
-+ else:
-+ return self.attrs['encoding']
-+
-+ def GetInputPath(self):
-+ return self.attrs['file']
-diff --git a/tools/grit/grit/pseudo.py b/tools/grit/grit/pseudo.py
-new file mode 100644
-index 0000000000..b607bfc6bb
---- /dev/null
-+++ b/tools/grit/grit/pseudo.py
-@@ -0,0 +1,129 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Pseudotranslation support. Our pseudotranslations are based on the
-+P-language, which is a simple vowel-extending language. Examples of P:
-+ - "hello" becomes "hepellopo"
-+ - "howdie" becomes "hopowdiepie"
-+ - "because" becomes "bepecaupause" (but in our implementation we don't
-+ handle the silent e at the end so it actually would return "bepecaupausepe"
-+
-+The P-language has the excellent quality of increasing the length of text
-+by around 30-50% which is great for pseudotranslations, to stress test any
-+GUI layouts etc.
-+
-+To make the pseudotranslations more obviously "not a translation" and to make
-+them exercise any code that deals with encodings, we also transform all English
-+vowels into equivalent vowels with diacriticals on them (rings, acutes,
-+diaresis, and circumflex), and we write the "p" in the P-language as a Hebrew
-+character Qof. It looks sort of like a latin character "p" but it is outside
-+the latin-1 character set which will stress character encoding bugs.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit import lazy_re
-+from grit import tclib
-+
-+
-+# An RFC language code for the P pseudolanguage.
-+PSEUDO_LANG = 'x-P-pseudo'
-+
-+# Hebrew character Qof. It looks kind of like a 'p' but is outside
-+# the latin-1 character set which is good for our purposes.
-+# TODO(joi) For now using P instead of Qof, because of some bugs it used. Find
-+# a better solution, i.e. one that introduces a non-latin1 character into the
-+# pseudotranslation.
-+#_QOF = u'\u05e7'
-+_QOF = u'P'
-+
-+# How we map each vowel.
-+_VOWELS = {
-+ u'a' : u'\u00e5', # a with ring
-+ u'e' : u'\u00e9', # e acute
-+ u'i' : u'\u00ef', # i diaresis
-+ u'o' : u'\u00f4', # o circumflex
-+ u'u' : u'\u00fc', # u diaresis
-+ u'y' : u'\u00fd', # y acute
-+ u'A' : u'\u00c5', # A with ring
-+ u'E' : u'\u00c9', # E acute
-+ u'I' : u'\u00cf', # I diaresis
-+ u'O' : u'\u00d4', # O circumflex
-+ u'U' : u'\u00dc', # U diaresis
-+ u'Y' : u'\u00dd', # Y acute
-+}
-+_VOWELS_KEYS = set(_VOWELS.keys())
-+
-+# Matches vowels and P
-+_PSUB_RE = lazy_re.compile("(%s)" % '|'.join(_VOWELS_KEYS | {'P'}))
-+
-+
-+# Pseudotranslations previously created. This is important for performance
-+# reasons, especially since we routinely pseudotranslate the whole project
-+# several or many different times for each build.
-+_existing_translations = {}
-+
-+
-+def MapVowels(str, also_p = False):
-+ '''Returns a copy of 'str' where characters that exist as keys in _VOWELS
-+ have been replaced with the corresponding value. If also_p is true, this
-+ function will also change capital P characters into a Hebrew character Qof.
-+ '''
-+ def Repl(match):
-+ if match.group() == 'p':
-+ if also_p:
-+ return _QOF
-+ else:
-+ return 'p'
-+ else:
-+ return _VOWELS[match.group()]
-+ return _PSUB_RE.sub(Repl, str)
-+
-+
-+def PseudoString(str):
-+ '''Returns a pseudotranslation of the provided string, in our enhanced
-+ P-language.'''
-+ if str in _existing_translations:
-+ return _existing_translations[str]
-+
-+ outstr = u''
-+ ix = 0
-+ while ix < len(str):
-+ if str[ix] not in _VOWELS_KEYS:
-+ outstr += str[ix]
-+ ix += 1
-+ else:
-+ # We want to treat consecutive vowels as one composite vowel. This is not
-+ # always accurate e.g. in composite words but good enough.
-+ consecutive_vowels = u''
-+ while ix < len(str) and str[ix] in _VOWELS_KEYS:
-+ consecutive_vowels += str[ix]
-+ ix += 1
-+ changed_vowels = MapVowels(consecutive_vowels)
-+ outstr += changed_vowels
-+ outstr += _QOF
-+ outstr += changed_vowels
-+
-+ _existing_translations[str] = outstr
-+ return outstr
-+
-+
-+def PseudoMessage(message):
-+ '''Returns a pseudotranslation of the provided message.
-+
-+ Args:
-+ message: tclib.Message()
-+
-+ Return:
-+ tclib.Translation()
-+ '''
-+ transl = tclib.Translation()
-+
-+ for part in message.GetContent():
-+ if isinstance(part, tclib.Placeholder):
-+ transl.AppendPlaceholder(part)
-+ else:
-+ transl.AppendText(PseudoString(part))
-+
-+ return transl
-diff --git a/tools/grit/grit/pseudo_rtl.py b/tools/grit/grit/pseudo_rtl.py
-new file mode 100644
-index 0000000000..2240b571de
---- /dev/null
-+++ b/tools/grit/grit/pseudo_rtl.py
-@@ -0,0 +1,104 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Pseudo RTL, (aka Fake Bidi) support. It simply wraps each word with
-+Unicode RTL overrides.
-+More info at https://sites.google.com/a/chromium.org/dev/Home/fake-bidi
-+'''
-+
-+from __future__ import print_function
-+
-+import re
-+
-+from grit import lazy_re
-+from grit import tclib
-+
-+ACCENTED_STRINGS = {
-+ 'a': u"\u00e5", 'e': u"\u00e9", 'i': u"\u00ee", 'o': u"\u00f6",
-+ 'u': u"\u00fb", 'A': u"\u00c5", 'E': u"\u00c9", 'I': u"\u00ce",
-+ 'O': u"\u00d6", 'U': u"\u00db", 'c': u"\u00e7", 'd': u"\u00f0",
-+ 'n': u"\u00f1", 'p': u"\u00fe", 'y': u"\u00fd", 'C': u"\u00c7",
-+ 'D': u"\u00d0", 'N': u"\u00d1", 'P': u"\u00de", 'Y': u"\u00dd",
-+ 'f': u"\u0192", 's': u"\u0161", 'S': u"\u0160", 'z': u"\u017e",
-+ 'Z': u"\u017d", 'g': u"\u011d", 'G': u"\u011c", 'h': u"\u0125",
-+ 'H': u"\u0124", 'j': u"\u0135", 'J': u"\u0134", 'k': u"\u0137",
-+ 'K': u"\u0136", 'l': u"\u013c", 'L': u"\u013b", 't': u"\u0163",
-+ 'T': u"\u0162", 'w': u"\u0175", 'W': u"\u0174",
-+ '$': u"\u20ac", '?': u"\u00bf", 'R': u"\u00ae", r'!': u"\u00a1",
-+}
-+
-+# a character set containing the keys in ACCENTED_STRINGS
-+# We should not accent characters in an escape sequence such as "\n".
-+# To be safe, we assume every character following a backslash is an escaped
-+# character. We also need to consider the case like "\\n", which means
-+# a blackslash and a character "n", we will accent the character "n".
-+TO_ACCENT = lazy_re.compile(
-+ r'[%s]|\\[a-z\\]' % ''.join(ACCENTED_STRINGS.keys()))
-+
-+# Lex text so that we don't interfere with html tokens and entities.
-+# This lexing scheme will handle all well formed tags and entities, html or
-+# xhtml. It will not handle comments, CDATA sections, or the unescaping tags:
-+# script, style, xmp or listing. If any of those appear in messages,
-+# something is wrong.
-+TOKENS = [ lazy_re.compile(
-+ '^%s' % pattern, # match at the beginning of input
-+ re.I | re.S # html tokens are case-insensitive
-+ )
-+ for pattern in
-+ (
-+ # a run of non html special characters
-+ r'[^<&]+',
-+ # a tag
-+ (r'</?[a-z]\w*' # beginning of tag
-+ r'(?:\s+\w+(?:\s*=\s*' # attribute start
-+ r'(?:[^\s"\'>]+|"[^\"]*"|\'[^\']*\'))?' # attribute value
-+ r')*\s*/?>'),
-+ # an entity
-+ r'&(?:[a-z]\w+|#\d+|#x[\da-f]+);',
-+ # an html special character not part of a special sequence
-+ r'.'
-+ ) ]
-+
-+ALPHABETIC_RUN = lazy_re.compile(r'([^\W0-9_]+)')
-+
-+RLO = u'\u202e'
-+PDF = u'\u202c'
-+
-+def PseudoRTLString(text):
-+ '''Returns a fake bidirectional version of the source string. This code is
-+ based on accentString above, in turn copied from Frank Tang.
-+ '''
-+ parts = []
-+ while text:
-+ m = None
-+ for token in TOKENS:
-+ m = token.search(text)
-+ if m:
-+ part = m.group(0)
-+ text = text[len(part):]
-+ if part[0] not in ('<', '&'):
-+ # not a tag or entity, so accent
-+ part = ALPHABETIC_RUN.sub(lambda run: RLO + run.group() + PDF, part)
-+ parts.append(part)
-+ break
-+ return ''.join(parts)
-+
-+
-+def PseudoRTLMessage(message):
-+ '''Returns a pseudo-RTL (aka Fake-Bidi) translation of the provided message.
-+
-+ Args:
-+ message: tclib.Message()
-+
-+ Return:
-+ tclib.Translation()
-+ '''
-+ transl = tclib.Translation()
-+ for part in message.GetContent():
-+ if isinstance(part, tclib.Placeholder):
-+ transl.AppendPlaceholder(part)
-+ else:
-+ transl.AppendText(PseudoRTLString(part))
-+
-+ return transl
-diff --git a/tools/grit/grit/pseudo_unittest.py b/tools/grit/grit/pseudo_unittest.py
-new file mode 100644
-index 0000000000..b1d53ff401
---- /dev/null
-+++ b/tools/grit/grit/pseudo_unittest.py
-@@ -0,0 +1,55 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.pseudo'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import unittest
-+
-+from grit import pseudo
-+from grit import tclib
-+
-+
-+class PseudoUnittest(unittest.TestCase):
-+ def testVowelMapping(self):
-+ self.failUnless(pseudo.MapVowels('abebibobuby') ==
-+ u'\u00e5b\u00e9b\u00efb\u00f4b\u00fcb\u00fd')
-+ self.failUnless(pseudo.MapVowels('ABEBIBOBUBY') ==
-+ u'\u00c5B\u00c9B\u00cfB\u00d4B\u00dcB\u00dd')
-+
-+ def testPseudoString(self):
-+ out = pseudo.PseudoString('hello')
-+ self.failUnless(out == pseudo.MapVowels(u'hePelloPo', True))
-+
-+ def testConsecutiveVowels(self):
-+ out = pseudo.PseudoString("beautiful weather, ain't it?")
-+ self.failUnless(out == pseudo.MapVowels(
-+ u"beauPeautiPifuPul weaPeathePer, aiPain't iPit?", 1))
-+
-+ def testCapitals(self):
-+ out = pseudo.PseudoString("HOWDIE DOODIE, DR. JONES")
-+ self.failUnless(out == pseudo.MapVowels(
-+ u"HOPOWDIEPIE DOOPOODIEPIE, DR. JOPONEPES", 1))
-+
-+ def testPseudoMessage(self):
-+ msg = tclib.Message(text='Hello USERNAME, how are you?',
-+ placeholders=[
-+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
-+ trans = pseudo.PseudoMessage(msg)
-+ # TODO(joi) It would be nicer if 'you' -> 'youPou' instead of
-+ # 'you' -> 'youPyou' and if we handled the silent e in 'are'
-+ self.failUnless(trans.GetPresentableContent() ==
-+ pseudo.MapVowels(
-+ u'HePelloPo USERNAME, hoPow aParePe youPyou?', 1))
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/shortcuts.py b/tools/grit/grit/shortcuts.py
-new file mode 100644
-index 0000000000..0db2ce436c
---- /dev/null
-+++ b/tools/grit/grit/shortcuts.py
-@@ -0,0 +1,93 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Stuff to prevent conflicting shortcuts.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit import lazy_re
-+
-+
-+class ShortcutGroup(object):
-+ '''Manages a list of cliques that belong together in a single shortcut
-+ group. Knows how to detect conflicting shortcut keys.
-+ '''
-+
-+ # Matches shortcut keys, e.g. &J
-+ SHORTCUT_RE = lazy_re.compile('([^&]|^)(&[A-Za-z])')
-+
-+ def __init__(self, name):
-+ self.name = name
-+ # Map of language codes to shortcut keys used (which is a map of
-+ # shortcut keys to counts).
-+ self.keys_by_lang = {}
-+ # List of cliques in this group
-+ self.cliques = []
-+
-+ def AddClique(self, c):
-+ for existing_clique in self.cliques:
-+ if existing_clique.GetId() == c.GetId():
-+ # This happens e.g. when we have e.g.
-+ # <if expr1><structure 1></if> <if expr2><structure 2></if>
-+ # where only one will really be included in the output.
-+ return
-+
-+ self.cliques.append(c)
-+ for (lang, msg) in c.clique.items():
-+ if lang not in self.keys_by_lang:
-+ self.keys_by_lang[lang] = {}
-+ keymap = self.keys_by_lang[lang]
-+
-+ content = msg.GetRealContent()
-+ keys = [groups[1] for groups in self.SHORTCUT_RE.findall(content)]
-+ for key in keys:
-+ key = key.upper()
-+ if key in keymap:
-+ keymap[key] += 1
-+ else:
-+ keymap[key] = 1
-+
-+ def GenerateWarnings(self, tc_project):
-+ # For any language that has more than one occurrence of any shortcut,
-+ # make a list of the conflicting shortcuts.
-+ problem_langs = {}
-+ for (lang, keys) in self.keys_by_lang.items():
-+ for (key, count) in keys.items():
-+ if count > 1:
-+ if lang not in problem_langs:
-+ problem_langs[lang] = []
-+ problem_langs[lang].append(key)
-+
-+ warnings = []
-+ if len(problem_langs):
-+ warnings.append("WARNING - duplicate keys exist in shortcut group %s" %
-+ self.name)
-+ for (lang,keys) in problem_langs.items():
-+ warnings.append(" %6s duplicates: %s" % (lang, ', '.join(keys)))
-+ return warnings
-+
-+
-+def GenerateDuplicateShortcutsWarnings(uberclique, tc_project):
-+ '''Given an UberClique and a project name, will print out helpful warnings
-+ if there are conflicting shortcuts within shortcut groups in the provided
-+ UberClique.
-+
-+ Args:
-+ uberclique: clique.UberClique()
-+ tc_project: 'MyProjectNameInTheTranslationConsole'
-+
-+ Returns:
-+ ['warning line 1', 'warning line 2', ...]
-+ '''
-+ warnings = []
-+ groups = {}
-+ for c in uberclique.AllCliques():
-+ for group in c.shortcut_groups:
-+ if group not in groups:
-+ groups[group] = ShortcutGroup(group)
-+ groups[group].AddClique(c)
-+ for group in groups.values():
-+ warnings += group.GenerateWarnings(tc_project)
-+ return warnings
-diff --git a/tools/grit/grit/shortcuts_unittest.py b/tools/grit/grit/shortcuts_unittest.py
-new file mode 100644
-index 0000000000..30e7c4f758
---- /dev/null
-+++ b/tools/grit/grit/shortcuts_unittest.py
-@@ -0,0 +1,79 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.shortcuts
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import shortcuts
-+from grit import clique
-+from grit import tclib
-+from grit.gather import rc
-+
-+class ShortcutsUnittest(unittest.TestCase):
-+
-+ def setUp(self):
-+ self.uq = clique.UberClique()
-+
-+ def testFunctionality(self):
-+ c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
-+ c.AddToShortcutGroup('group_name')
-+ c = self.uq.MakeClique(tclib.Message(text="Howdie &there partner"))
-+ c.AddToShortcutGroup('group_name')
-+
-+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
-+ self.failUnless(warnings)
-+
-+ def testAmpersandEscaping(self):
-+ c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
-+ c.AddToShortcutGroup('group_name')
-+ c = self.uq.MakeClique(tclib.Message(text="S&&T are the &letters S and T"))
-+ c.AddToShortcutGroup('group_name')
-+
-+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
-+ self.failUnless(len(warnings) == 0)
-+
-+ def testDialog(self):
-+ dlg = rc.Dialog(StringIO('''\
-+IDD_SIDEBAR_RSS_PANEL_PROPPAGE DIALOGEX 0, 0, 239, 221
-+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-+FONT 8, "MS Shell Dlg", 400, 0, 0x1
-+BEGIN
-+ PUSHBUTTON "Add &URL",IDC_SIDEBAR_RSS_ADD_URL,182,53,57,14
-+ EDITTEXT IDC_SIDEBAR_RSS_NEW_URL,0,53,178,15,ES_AUTOHSCROLL
-+ PUSHBUTTON "&Remove",IDC_SIDEBAR_RSS_REMOVE,183,200,56,14
-+ PUSHBUTTON "&Edit",IDC_SIDEBAR_RSS_EDIT,123,200,56,14
-+ CONTROL "&Automatically add commonly viewed clips",
-+ IDC_SIDEBAR_RSS_AUTO_ADD,"Button",BS_AUTOCHECKBOX |
-+ BS_MULTILINE | WS_TABSTOP,0,200,120,17
-+ PUSHBUTTON "",IDC_SIDEBAR_RSS_HIDDEN,179,208,6,6,NOT WS_VISIBLE
-+ LTEXT "You can display clips from blogs, news sites, and other online sources.",
-+ IDC_STATIC,0,0,239,10
-+ LISTBOX IDC_SIDEBAR_DISPLAYED_FEED_LIST,0,69,239,127,LBS_SORT |
-+ LBS_OWNERDRAWFIXED | LBS_HASSTRINGS |
-+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL |
-+ WS_TABSTOP
-+ LTEXT "Add a clip from a recently viewed website by clicking Add Recent Clips.",
-+ IDC_STATIC,0,13,141,19
-+ LTEXT "Or, if you know a site supports RSS or Atom, you can enter the RSS or Atom URL below and add it to your list of Web Clips.",
-+ IDC_STATIC,0,33,239,18
-+ PUSHBUTTON "Add Recent &Clips (10)...",
-+ IDC_SIDEBAR_RSS_ADD_RECENT_CLIPS,146,14,93,14
-+END'''), 'IDD_SIDEBAR_RSS_PANEL_PROPPAGE')
-+ dlg.SetUberClique(self.uq)
-+ dlg.Parse()
-+
-+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
-+ self.failUnless(len(warnings) == 0)
-+
-diff --git a/tools/grit/grit/tclib.py b/tools/grit/grit/tclib.py
-new file mode 100644
-index 0000000000..27ba366924
---- /dev/null
-+++ b/tools/grit/grit/tclib.py
-@@ -0,0 +1,246 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Adaptation of the extern.tclib classes for our needs.
-+'''
-+
-+from __future__ import print_function
-+
-+import functools
-+import re
-+
-+import six
-+
-+from grit import exception
-+from grit import lazy_re
-+import grit.extern.tclib
-+
-+
-+# Matches whitespace sequences which can be folded into a single whitespace
-+# character. This matches single characters so that non-spaces are replaced
-+# with spaces.
-+_FOLD_WHITESPACE = re.compile(r'\s+')
-+
-+# Caches compiled regexp used to split tags in BaseMessage.__init__()
-+_RE_CACHE = {}
-+
-+def Identity(i):
-+ return i
-+
-+
-+class BaseMessage(object):
-+ '''Base class with methods shared by Message and Translation.
-+ '''
-+
-+ def __init__(self, text='', placeholders=[], description='', meaning=''):
-+ self.parts = []
-+ self.placeholders = []
-+ self.meaning = meaning
-+ self.dirty = True # True if self.id is (or might be) wrong
-+ self.id = 0
-+ self.SetDescription(description)
-+
-+ if text != '':
-+ if not placeholders or placeholders == []:
-+ self.AppendText(text)
-+ else:
-+ tag_map = {}
-+ for placeholder in placeholders:
-+ tag_map[placeholder.GetPresentation()] = [placeholder, 0]
-+ # This creates a regexp like '(TAG1|TAG2|TAG3)'.
-+ # The tags have to be sorted in order of decreasing length, so that
-+ # longer tags are substituted before shorter tags that happen to be
-+ # substrings of the longer tag.
-+ # E.g. "EXAMPLE_FOO_NAME" must be matched before "EXAMPLE_FOO",
-+ # otherwise "EXAMPLE_FOO" splits "EXAMPLE_FOO_NAME" too.
-+ tags = sorted(tag_map.keys(),
-+ key=functools.cmp_to_key(
-+ lambda x, y: len(x) - len(y) or ((x > y) - (x < y))),
-+ reverse=True)
-+ tag_re = '(' + '|'.join(tags) + ')'
-+
-+ # This caching improves the time to build
-+ # chrome/app:generated_resources from 21.562s to 17.672s on Linux.
-+ compiled_re = _RE_CACHE.get(tag_re, None)
-+ if compiled_re is None:
-+ compiled_re = re.compile(tag_re)
-+ _RE_CACHE[tag_re] = compiled_re
-+
-+ chunked_text = compiled_re.split(text)
-+
-+ for chunk in chunked_text:
-+ if chunk: # ignore empty chunk
-+ if chunk in tag_map:
-+ self.AppendPlaceholder(tag_map[chunk][0])
-+ tag_map[chunk][1] += 1 # increase placeholder use count
-+ else:
-+ self.AppendText(chunk)
-+ for key in tag_map:
-+ assert tag_map[key][1] != 0
-+
-+ def GetRealContent(self, escaping_function=Identity):
-+ '''Returns the original content, i.e. what your application and users
-+ will see.
-+
-+ Specify a function to escape each translateable bit, if you like.
-+ '''
-+ bits = []
-+ for item in self.parts:
-+ if isinstance(item, six.string_types):
-+ bits.append(escaping_function(item))
-+ else:
-+ bits.append(item.GetOriginal())
-+ return ''.join(bits)
-+
-+ def GetPresentableContent(self):
-+ presentable_content = []
-+ for part in self.parts:
-+ if isinstance(part, Placeholder):
-+ presentable_content.append(part.GetPresentation())
-+ else:
-+ presentable_content.append(part)
-+ return ''.join(presentable_content)
-+
-+ def AppendPlaceholder(self, placeholder):
-+ assert isinstance(placeholder, Placeholder)
-+ dup = False
-+ for other in self.GetPlaceholders():
-+ if other.presentation == placeholder.presentation:
-+ assert other.original == placeholder.original
-+ dup = True
-+
-+ if not dup:
-+ self.placeholders.append(placeholder)
-+ self.parts.append(placeholder)
-+ self.dirty = True
-+
-+ def AppendText(self, text):
-+ assert isinstance(text, six.string_types)
-+ assert text != ''
-+
-+ self.parts.append(text)
-+ self.dirty = True
-+
-+ def GetContent(self):
-+ '''Returns the parts of the message. You may modify parts if you wish.
-+ Note that you must not call GetId() on this object until you have finished
-+ modifying the contents.
-+ '''
-+ self.dirty = True # user might modify content
-+ return self.parts
-+
-+ def GetDescription(self):
-+ return self.description
-+
-+ def SetDescription(self, description):
-+ self.description = _FOLD_WHITESPACE.sub(' ', description)
-+
-+ def GetMeaning(self):
-+ return self.meaning
-+
-+ def GetId(self):
-+ if self.dirty:
-+ self.id = self.GenerateId()
-+ self.dirty = False
-+ return self.id
-+
-+ def GenerateId(self):
-+ return grit.extern.tclib.GenerateMessageId(self.GetPresentableContent(),
-+ self.meaning)
-+
-+ def GetPlaceholders(self):
-+ return self.placeholders
-+
-+ def FillTclibBaseMessage(self, msg):
-+ msg.SetDescription(self.description.encode('utf-8'))
-+
-+ for part in self.parts:
-+ if isinstance(part, Placeholder):
-+ ph = grit.extern.tclib.Placeholder(
-+ part.presentation.encode('utf-8'),
-+ part.original.encode('utf-8'),
-+ part.example.encode('utf-8'))
-+ msg.AppendPlaceholder(ph)
-+ else:
-+ msg.AppendText(part.encode('utf-8'))
-+
-+
-+class Message(BaseMessage):
-+ '''A message.'''
-+
-+ def __init__(self, text='', placeholders=[], description='', meaning='',
-+ assigned_id=None):
-+ super(Message, self).__init__(text, placeholders, description, meaning)
-+ self.assigned_id = assigned_id
-+
-+ def ToTclibMessage(self):
-+ msg = grit.extern.tclib.Message('utf-8', meaning=self.meaning)
-+ self.FillTclibBaseMessage(msg)
-+ return msg
-+
-+ def GetId(self):
-+ '''Use the assigned id if we have one.'''
-+ if self.assigned_id:
-+ return self.assigned_id
-+
-+ return super(Message, self).GetId()
-+
-+ def HasAssignedId(self):
-+ '''Returns True if this message has an assigned id.'''
-+ return bool(self.assigned_id)
-+
-+
-+class Translation(BaseMessage):
-+ '''A translation.'''
-+
-+ def __init__(self, text='', id='', placeholders=[], description='', meaning=''):
-+ super(Translation, self).__init__(text, placeholders, description, meaning)
-+ self.id = id
-+
-+ def GetId(self):
-+ assert id != '', "ID has not been set."
-+ return self.id
-+
-+ def SetId(self, id):
-+ self.id = id
-+
-+ def ToTclibMessage(self):
-+ msg = grit.extern.tclib.Message(
-+ 'utf-8', id=self.id, meaning=self.meaning)
-+ self.FillTclibBaseMessage(msg)
-+ return msg
-+
-+
-+class Placeholder(grit.extern.tclib.Placeholder):
-+ '''Modifies constructor to accept a Unicode string
-+ '''
-+
-+ # Must match placeholder presentation names
-+ _NAME_RE = lazy_re.compile('^[A-Za-z0-9_]+$')
-+
-+ def __init__(self, presentation, original, example):
-+ '''Creates a new placeholder.
-+
-+ Args:
-+ presentation: 'USERNAME'
-+ original: '%s'
-+ example: 'Joi'
-+ '''
-+ assert presentation != ''
-+ assert original != ''
-+ assert example != ''
-+ if not self._NAME_RE.match(presentation):
-+ raise exception.InvalidPlaceholderName(presentation)
-+ self.presentation = presentation
-+ self.original = original
-+ self.example = example
-+
-+ def GetPresentation(self):
-+ return self.presentation
-+
-+ def GetOriginal(self):
-+ return self.original
-+
-+ def GetExample(self):
-+ return self.example
-diff --git a/tools/grit/grit/tclib_unittest.py b/tools/grit/grit/tclib_unittest.py
-new file mode 100644
-index 0000000000..7a08654e1b
---- /dev/null
-+++ b/tools/grit/grit/tclib_unittest.py
-@@ -0,0 +1,180 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.tclib'''
-+
-+from __future__ import print_function
-+
-+import sys
-+import os.path
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import unittest
-+
-+import six
-+
-+from grit import tclib
-+
-+from grit import exception
-+import grit.extern.tclib
-+
-+
-+class TclibUnittest(unittest.TestCase):
-+ def testInit(self):
-+ msg = tclib.Message(text=u'Hello Earthlings',
-+ description='Greetings\n\t message')
-+ self.failUnlessEqual(msg.GetPresentableContent(), 'Hello Earthlings')
-+ self.failUnless(isinstance(msg.GetPresentableContent(), six.string_types))
-+ self.failUnlessEqual(msg.GetDescription(), 'Greetings message')
-+
-+ def testGetAttr(self):
-+ msg = tclib.Message()
-+ msg.AppendText(u'Hello') # Tests __getattr__
-+ self.failUnless(msg.GetPresentableContent() == 'Hello')
-+ self.failUnless(isinstance(msg.GetPresentableContent(), six.string_types))
-+
-+ def testAll(self):
-+ text = u'Howdie USERNAME'
-+ phs = [tclib.Placeholder(u'USERNAME', u'%s', 'Joi')]
-+ msg = tclib.Message(text=text, placeholders=phs)
-+ self.failUnless(msg.GetPresentableContent() == 'Howdie USERNAME')
-+
-+ trans = tclib.Translation(text=text, placeholders=phs)
-+ self.failUnless(trans.GetPresentableContent() == 'Howdie USERNAME')
-+ self.failUnless(isinstance(trans.GetPresentableContent(), six.string_types))
-+
-+ def testUnicodeReturn(self):
-+ text = u'\u00fe'
-+ msg = tclib.Message(text=text)
-+ self.failUnless(msg.GetPresentableContent() == text)
-+ from_list = msg.GetContent()[0]
-+ self.failUnless(from_list == text)
-+
-+ def testRegressionTranslationInherited(self):
-+ '''Regression tests a bug that was caused by grit.tclib.Translation
-+ inheriting from the translation console's Translation object
-+ instead of only owning an instance of it.
-+ '''
-+ msg = tclib.Message(text=u"BLA1\r\nFrom: BLA2 \u00fe BLA3",
-+ placeholders=[
-+ tclib.Placeholder('BLA1', '%s', '%s'),
-+ tclib.Placeholder('BLA2', '%s', '%s'),
-+ tclib.Placeholder('BLA3', '%s', '%s')])
-+ transl = tclib.Translation(text=msg.GetPresentableContent(),
-+ placeholders=msg.GetPlaceholders())
-+ content = transl.GetContent()
-+ self.failUnless(isinstance(content[3], six.string_types))
-+
-+ def testFingerprint(self):
-+ # This has Windows line endings. That is on purpose.
-+ id = grit.extern.tclib.GenerateMessageId(
-+ 'Google Desktop for Enterprise\r\n'
-+ 'All Rights Reserved\r\n'
-+ '\r\n'
-+ '---------\r\n'
-+ 'Contents\r\n'
-+ '---------\r\n'
-+ 'This distribution contains the following files:\r\n'
-+ '\r\n'
-+ 'GoogleDesktopSetup.msi - Installation and setup program\r\n'
-+ 'GoogleDesktop.adm - Group Policy administrative template file\r\n'
-+ 'AdminGuide.pdf - Google Desktop for Enterprise administrative guide\r\n'
-+ '\r\n'
-+ '\r\n'
-+ '--------------\r\n'
-+ 'Documentation\r\n'
-+ '--------------\r\n'
-+ 'Full documentation and installation instructions are in the \r\n'
-+ 'administrative guide, and also online at \r\n'
-+ 'http://desktop.google.com/enterprise/adminguide.html.\r\n'
-+ '\r\n'
-+ '\r\n'
-+ '------------------------\r\n'
-+ 'IBM Lotus Notes Plug-In\r\n'
-+ '------------------------\r\n'
-+ 'The Lotus Notes plug-in is included in the release of Google \r\n'
-+ 'Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google \r\n'
-+ 'Desktop indexes mail, calendar, task, contact and journal \r\n'
-+ 'documents from Notes. Discussion documents including those from \r\n'
-+ 'the discussion and team room templates can also be indexed by \r\n'
-+ 'selecting an option from the preferences. Once indexed, this data\r\n'
-+ 'will be returned in Google Desktop searches. The corresponding\r\n'
-+ 'document can be opened in Lotus Notes from the Google Desktop \r\n'
-+ 'results page.\r\n'
-+ '\r\n'
-+ 'Install: The plug-in will install automatically during the Google \r\n'
-+ 'Desktop setup process if Lotus Notes is already installed. Lotus \r\n'
-+ 'Notes must not be running in order for the install to occur. \r\n'
-+ '\r\n'
-+ 'Preferences: Preferences and selection of databases to index are\r\n'
-+ 'set in the \'Google Desktop for Notes\' dialog reached through the \r\n'
-+ '\'Actions\' menu.\r\n'
-+ '\r\n'
-+ 'Reindexing: Selecting \'Reindex all databases\' will index all the \r\n'
-+ 'documents in each database again.\r\n'
-+ '\r\n'
-+ '\r\n'
-+ 'Notes Plug-in Known Issues\r\n'
-+ '---------------------------\r\n'
-+ '\r\n'
-+ 'If the \'Google Desktop for Notes\' item is not available from the \r\n'
-+ 'Lotus Notes Actions menu, then installation was not successful. \r\n'
-+ 'Installation consists of writing one file, notesgdsplugin.dll, to \r\n'
-+ 'the Notes application directory and a setting to the notes.ini \r\n'
-+ 'configuration file. The most likely cause of an unsuccessful \r\n'
-+ 'installation is that the installer was not able to locate the \r\n'
-+ 'notes.ini file. Installation will complete if the user closes Notes\r\n'
-+ 'and manually adds the following setting to this file on a new line:\r\n'
-+ 'AddinMenus=notegdsplugin.dll\r\n'
-+ '\r\n'
-+ 'If the notesgdsplugin.dll file is not in the application directory\r\n'
-+ r'(e.g., C:\Program Files\Lotus\Notes) after Google Desktop \r\n'
-+ 'installation, it is likely that Notes was not installed correctly. \r\n'
-+ '\r\n'
-+ 'Only local databases can be indexed. If they can be determined, \r\n'
-+ 'the user\'s local mail file and address book will be included in the\r\n'
-+ 'list automatically. Mail archives and other databases must be \r\n'
-+ 'added with the \'Add\' button.\r\n'
-+ '\r\n'
-+ 'Some users may experience performance issues during the initial \r\n'
-+ 'indexing of a database. The \'Perform the initial index of a \r\n'
-+ 'database only when I\'m idle\' option will limit the indexing process\r\n'
-+ 'to times when the user is not using the machine. If this does not \r\n'
-+ 'alleviate the problem or the user would like to continually index \r\n'
-+ 'but just do so more slowly or quickly, the GoogleWaitTime notes.ini\r\n'
-+ 'value can be set. Increasing the GoogleWaitTime value will slow \r\n'
-+ 'down the indexing process, and lowering the value will speed it up.\r\n'
-+ 'A value of zero causes the fastest possible indexing. Removing the\r\n'
-+ 'ini parameter altogether returns it to the default (20).\r\n'
-+ '\r\n'
-+ 'Crashes have been known to occur with certain types of history \r\n'
-+ 'bookmarks. If the Notes client seems to crash randomly, try \r\n'
-+ 'disabling the \'Index note history\' option. If it crashes before,\r\n'
-+ 'you can get to the preferences, add the following line to your \r\n'
-+ 'notes.ini file:\r\n'
-+ 'GDSNoIndexHistory=1\r\n')
-+ self.assertEqual(id, '7660964495923572726')
-+
-+ def testPlaceholderNameChecking(self):
-+ try:
-+ ph = tclib.Placeholder('BINGO BONGO', 'bla', 'bla')
-+ raise Exception("We shouldn't get here")
-+ except exception.InvalidPlaceholderName:
-+ pass # Expect exception to be thrown because presentation contained space
-+
-+ def testTagsWithCommonSubstring(self):
-+ word = 'ABCDEFGHIJ'
-+ text = ' '.join([word[:i] for i in range(1, 11)])
-+ phs = [tclib.Placeholder(word[:i], str(i), str(i)) for i in range(1, 11)]
-+ try:
-+ msg = tclib.Message(text=text, placeholders=phs)
-+ self.failUnless(msg.GetRealContent() == '1 2 3 4 5 6 7 8 9 10')
-+ except:
-+ self.fail('tclib.Message() should handle placeholders that are '
-+ 'substrings of each other')
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/test_suite_all.py b/tools/grit/grit/test_suite_all.py
-new file mode 100644
-index 0000000000..3bfe2a79d5
---- /dev/null
-+++ b/tools/grit/grit/test_suite_all.py
-@@ -0,0 +1,34 @@
-+#!/usr/bin/env python3
-+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit test suite that collects all test cases for GRIT.'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+
-+
-+CUR_DIR = os.path.dirname(os.path.realpath(__file__))
-+SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(CUR_DIR)))
-+TYP_DIR = os.path.join(
-+ SRC_DIR, 'third_party', 'catapult', 'third_party', 'typ')
-+
-+if TYP_DIR not in sys.path:
-+ sys.path.insert(0, TYP_DIR)
-+
-+
-+import typ # pylint: disable=import-error,unused-import
-+
-+
-+def main(args):
-+ return typ.main(
-+ top_level_dirs=[os.path.join(CUR_DIR, '..')],
-+ skip=['grit.format.gen_predetermined_ids_unittest.*',
-+ 'grit.pseudo_unittest.*']
-+ )
-+
-+if __name__ == '__main__':
-+ sys.exit(main(sys.argv[1:]))
-diff --git a/tools/grit/grit/testdata/GoogleDesktop.adm b/tools/grit/grit/testdata/GoogleDesktop.adm
-new file mode 100644
-index 0000000000..082f56bb1a
---- /dev/null
-+++ b/tools/grit/grit/testdata/GoogleDesktop.adm
-@@ -0,0 +1,945 @@
-+CLASS MACHINE
-+ CATEGORY !!Cat_Google
-+ CATEGORY !!Cat_GoogleDesktopSearch
-+ KEYNAME "Software\Policies\Google\Google Desktop"
-+
-+ CATEGORY !!Cat_Preferences
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
-+
-+ CATEGORY !!Cat_IndexAndCaptureControl
-+ POLICY !!Blacklist_Email
-+ EXPLAIN !!Explain_Blacklist_Email
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ VALUENAME "1"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Gmail
-+ EXPLAIN !!Explain_Blacklist_Gmail
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
-+ VALUENAME "gmail"
-+ END POLICY
-+
-+ POLICY !!Blacklist_WebHistory
-+ EXPLAIN !!Explain_Blacklist_WebHistory
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ VALUENAME "2"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Chat
-+ EXPLAIN !!Explain_Blacklist_Chat
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "3" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Text
-+ EXPLAIN !!Explain_Blacklist_Text
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "4" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Media
-+ EXPLAIN !!Explain_Blacklist_Media
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "5" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Contact
-+ EXPLAIN !!Explain_Blacklist_Contact
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "9" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Calendar
-+ EXPLAIN !!Explain_Blacklist_Calendar
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "10" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Task
-+ EXPLAIN !!Explain_Blacklist_Task
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "11" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Note
-+ EXPLAIN !!Explain_Blacklist_Note
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "12" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Journal
-+ EXPLAIN !!Explain_Blacklist_Journal
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "13" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Word
-+ EXPLAIN !!Explain_Blacklist_Word
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "DOC"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Excel
-+ EXPLAIN !!Explain_Blacklist_Excel
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "XLS"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Powerpoint
-+ EXPLAIN !!Explain_Blacklist_Powerpoint
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "PPT"
-+ END POLICY
-+
-+ POLICY !!Blacklist_PDF
-+ EXPLAIN !!Explain_Blacklist_PDF
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "PDF"
-+ END POLICY
-+
-+ POLICY !!Blacklist_ZIP
-+ EXPLAIN !!Explain_Blacklist_ZIP
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "ZIP"
-+ END POLICY
-+
-+ POLICY !!Blacklist_HTTPS
-+ EXPLAIN !!Explain_Blacklist_HTTPS
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
-+ VALUENAME "HTTPS"
-+ END POLICY
-+
-+ POLICY !!Blacklist_PasswordProtectedOffice
-+ EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
-+ VALUENAME "SECUREOFFICE"
-+ END POLICY
-+
-+ POLICY !!Blacklist_URI_Contains
-+ EXPLAIN !!Explain_Blacklist_URI_Contains
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
-+ PART !!Blacklist_URI_Contains LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Blacklist_Extensions
-+ EXPLAIN !!Explain_Blacklist_Extensions
-+ PART !!Blacklist_Extensions EDITTEXT
-+ VALUENAME "file_extensions_to_skip"
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Disallow_UserSearchLocations
-+ EXPLAIN !!Explain_Disallow_UserSearchLocations
-+ VALUENAME user_search_locations
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Search_Location_Whitelist
-+ EXPLAIN !!Explain_Search_Location_Whitelist
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
-+ PART !!Search_Locations_Whitelist LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Email_Retention
-+ EXPLAIN !!Explain_Email_Retention
-+ PART !!Email_Retention_Edit NUMERIC
-+ VALUENAME "email_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Webpage_Retention
-+ EXPLAIN !!Explain_Webpage_Retention
-+ PART !!Webpage_Retention_Edit NUMERIC
-+ VALUENAME "webpage_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!File_Retention
-+ EXPLAIN !!Explain_File_Retention
-+ PART !!File_Retention_Edit NUMERIC
-+ VALUENAME "file_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!IM_Retention
-+ EXPLAIN !!Explain_IM_Retention
-+ PART !!IM_Retention_Edit NUMERIC
-+ VALUENAME "im_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Remove_Deleted_Items
-+ EXPLAIN !!Explain_Remove_Deleted_Items
-+ VALUENAME remove_deleted_items
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Allow_Simultaneous_Indexing
-+ EXPLAIN !!Explain_Allow_Simultaneous_Indexing
-+ VALUENAME simultaneous_indexing
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ END CATEGORY
-+
-+ POLICY !!Pol_TurnOffAdvancedFeatures
-+ EXPLAIN !!Explain_TurnOffAdvancedFeatures
-+ VALUENAME error_report_on
-+ VALUEON NUMERIC 0
-+ END POLICY
-+
-+ POLICY !!Pol_TurnOffImproveGd
-+ EXPLAIN !!Explain_TurnOffImproveGd
-+ VALUENAME improve_gd
-+ VALUEON NUMERIC 0
-+ VALUEOFF NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_NoPersonalizationInfo
-+ EXPLAIN !!Explain_NoPersonalizationInfo
-+ VALUENAME send_personalization_info
-+ VALUEON NUMERIC 0
-+ VALUEOFF NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_OneBoxMode
-+ EXPLAIN !!Explain_OneBoxMode
-+ VALUENAME onebox_mode
-+ VALUEON NUMERIC 0
-+ END POLICY
-+
-+ POLICY !!Pol_EncryptIndex
-+ EXPLAIN !!Explain_EncryptIndex
-+ VALUENAME encrypt_index
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Hyper
-+ EXPLAIN !!Explain_Hyper
-+ VALUENAME hyper_off
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Display_Mode
-+ EXPLAIN !!Explain_Display_Mode
-+ PART !!Pol_Display_Mode DROPDOWNLIST
-+ VALUENAME display_mode
-+ ITEMLIST
-+ NAME !!Sidebar VALUE NUMERIC 1
-+ NAME !!Deskbar VALUE NUMERIC 8
-+ NAME !!FloatingDeskbar VALUE NUMERIC 4
-+ NAME !!None VALUE NUMERIC 0
-+ END ITEMLIST
-+ END PART
-+ END POLICY
-+
-+ END CATEGORY ; Preferences
-+
-+ CATEGORY !!Cat_Enterprise
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
-+
-+ POLICY !!Pol_Autoupdate
-+ EXPLAIN !!Explain_Autoupdate
-+ VALUENAME autoupdate_host
-+ VALUEON ""
-+ END POLICY
-+
-+ POLICY !!Pol_AutoupdateAsSystem
-+ EXPLAIN !!Explain_AutoupdateAsSystem
-+ VALUENAME autoupdate_impersonate_user
-+ VALUEON NUMERIC 0
-+ VALUEOFF NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_EnterpriseTab
-+ EXPLAIN !!Explain_EnterpriseTab
-+ PART !!EnterpriseTabText EDITTEXT
-+ VALUENAME enterprise_tab_text
-+ END PART
-+ PART !!EnterpriseTabHomepage EDITTEXT
-+ VALUENAME enterprise_tab_homepage
-+ END PART
-+ PART !!EnterpriseTabHomepageQuery CHECKBOX
-+ VALUENAME enterprise_tab_homepage_query
-+ END PART
-+ PART !!EnterpriseTabResults EDITTEXT
-+ VALUENAME enterprise_tab_results
-+ END PART
-+ PART !!EnterpriseTabResultsQuery CHECKBOX
-+ VALUENAME enterprise_tab_results_query
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_GSAHosts
-+ EXPLAIN !!Explain_GSAHosts
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
-+ PART !!Pol_GSAHosts LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_PolicyUnawareClientProhibitedFlag
-+ EXPLAIN !!Explain_PolicyUnawareClientProhibitedFlag
-+ KEYNAME "Software\Policies\Google\Google Desktop"
-+ VALUENAME PolicyUnawareClientProhibitedFlag
-+ END POLICY
-+
-+ POLICY !!Pol_MinimumAllowedVersion
-+ EXPLAIN !!Explain_MinimumAllowedVersion
-+ PART !!Pol_MinimumAllowedVersion EDITTEXT
-+ VALUENAME minimum_allowed_version
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_MaximumAllowedVersion
-+ EXPLAIN !!Explain_MaximumAllowedVersion
-+ PART !!Pol_MaximumAllowedVersion EDITTEXT
-+ VALUENAME maximum_allowed_version
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Disallow_Gadgets
-+ EXPLAIN !!Explain_Disallow_Gadgets
-+ VALUENAME disallow_gadgets
-+ VALUEON NUMERIC 1
-+ PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
-+ VALUENAME disallow_only_non_builtin_gadgets
-+ VALUEON NUMERIC 1
-+ VALUEOFF NUMERIC 0
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Gadget_Whitelist
-+ EXPLAIN !!Explain_Gadget_Whitelist
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
-+ PART !!Pol_Gadget_Whitelist LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
-+ EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
-+ PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Alternate_User_Data_Dir
-+ EXPLAIN !!Explain_Alternate_User_Data_Dir
-+ PART !!Pol_Alternate_User_Data_Dir EDITTEXT
-+ VALUENAME alternate_user_data_dir
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_MaxAllowedOutlookConnections
-+ EXPLAIN !!Explain_MaxAllowedOutlookConnections
-+ PART !!Pol_MaxAllowedOutlookConnections NUMERIC
-+ VALUENAME max_allowed_outlook_connections
-+ MIN 1 MAX 65535 DEFAULT 400 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_DisallowSsdService
-+ EXPLAIN !!Explain_DisallowSsdService
-+ VALUENAME disallow_ssd_service
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_DisallowSsdOutbound
-+ EXPLAIN !!Explain_DisallowSsdOutbound
-+ VALUENAME disallow_ssd_outbound
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Disallow_Store_Gadget_Service
-+ EXPLAIN !!Explain_Disallow_Store_Gadget_Service
-+ VALUENAME disallow_store_gadget_service
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_MaxExchangeIndexingRate
-+ EXPLAIN !!Explain_MaxExchangeIndexingRate
-+ PART !!Pol_MaxExchangeIndexingRate NUMERIC
-+ VALUENAME max_exchange_indexing_rate
-+ MIN 1 MAX 1000 DEFAULT 60 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_EnableSafeweb
-+ EXPLAIN !!Explain_Safeweb
-+ VALUENAME safe_browsing
-+ VALUEON NUMERIC 1
-+ VALUEOFF NUMERIC 0
-+ END POLICY
-+
-+ END CATEGORY ; Enterprise
-+
-+ END CATEGORY ; GoogleDesktopSearch
-+ END CATEGORY ; Google
-+
-+
-+CLASS USER
-+ CATEGORY !!Cat_Google
-+ CATEGORY !!Cat_GoogleDesktopSearch
-+ KEYNAME "Software\Policies\Google\Google Desktop"
-+
-+ CATEGORY !!Cat_Preferences
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
-+
-+ CATEGORY !!Cat_IndexAndCaptureControl
-+ POLICY !!Blacklist_Email
-+ EXPLAIN !!Explain_Blacklist_Email
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ VALUENAME "1"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Gmail
-+ EXPLAIN !!Explain_Blacklist_Gmail
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
-+ VALUENAME "gmail"
-+ END POLICY
-+
-+ POLICY !!Blacklist_WebHistory
-+ EXPLAIN !!Explain_Blacklist_WebHistory
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ VALUENAME "2"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Chat
-+ EXPLAIN !!Explain_Blacklist_Chat
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "3" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Text
-+ EXPLAIN !!Explain_Blacklist_Text
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "4" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Media
-+ EXPLAIN !!Explain_Blacklist_Media
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "5" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Contact
-+ EXPLAIN !!Explain_Blacklist_Contact
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "9" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Calendar
-+ EXPLAIN !!Explain_Blacklist_Calendar
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "10" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Task
-+ EXPLAIN !!Explain_Blacklist_Task
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "11" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Note
-+ EXPLAIN !!Explain_Blacklist_Note
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "12" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Journal
-+ EXPLAIN !!Explain_Blacklist_Journal
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
-+ ACTIONLISTON
-+ VALUENAME "13" VALUE NUMERIC 1
-+ END ACTIONLISTON
-+ END POLICY
-+
-+ POLICY !!Blacklist_Word
-+ EXPLAIN !!Explain_Blacklist_Word
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "DOC"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Excel
-+ EXPLAIN !!Explain_Blacklist_Excel
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "XLS"
-+ END POLICY
-+
-+ POLICY !!Blacklist_Powerpoint
-+ EXPLAIN !!Explain_Blacklist_Powerpoint
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "PPT"
-+ END POLICY
-+
-+ POLICY !!Blacklist_PDF
-+ EXPLAIN !!Explain_Blacklist_PDF
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "PDF"
-+ END POLICY
-+
-+ POLICY !!Blacklist_ZIP
-+ EXPLAIN !!Explain_Blacklist_ZIP
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
-+ VALUENAME "ZIP"
-+ END POLICY
-+
-+ POLICY !!Blacklist_HTTPS
-+ EXPLAIN !!Explain_Blacklist_HTTPS
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
-+ VALUENAME "HTTPS"
-+ END POLICY
-+
-+ POLICY !!Blacklist_PasswordProtectedOffice
-+ EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
-+ VALUENAME "SECUREOFFICE"
-+ END POLICY
-+
-+ POLICY !!Blacklist_URI_Contains
-+ EXPLAIN !!Explain_Blacklist_URI_Contains
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
-+ PART !!Blacklist_URI_Contains LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Blacklist_Extensions
-+ EXPLAIN !!Explain_Blacklist_Extensions
-+ PART !!Blacklist_Extensions EDITTEXT
-+ VALUENAME "file_extensions_to_skip"
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Disallow_UserSearchLocations
-+ EXPLAIN !!Explain_Disallow_UserSearchLocations
-+ VALUENAME user_search_locations
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Search_Location_Whitelist
-+ EXPLAIN !!Explain_Search_Location_Whitelist
-+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
-+ PART !!Search_Locations_Whitelist LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Email_Retention
-+ EXPLAIN !!Explain_Email_Retention
-+ PART !!Email_Retention_Edit NUMERIC
-+ VALUENAME "email_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Webpage_Retention
-+ EXPLAIN !!Explain_Webpage_Retention
-+ PART !!Webpage_Retention_Edit NUMERIC
-+ VALUENAME "webpage_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!File_Retention
-+ EXPLAIN !!Explain_File_Retention
-+ PART !!File_Retention_Edit NUMERIC
-+ VALUENAME "file_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!IM_Retention
-+ EXPLAIN !!Explain_IM_Retention
-+ PART !!IM_Retention_Edit NUMERIC
-+ VALUENAME "im_days_to_retain"
-+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Remove_Deleted_Items
-+ EXPLAIN !!Explain_Remove_Deleted_Items
-+ VALUENAME remove_deleted_items
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Allow_Simultaneous_Indexing
-+ EXPLAIN !!Explain_Allow_Simultaneous_Indexing
-+ VALUENAME simultaneous_indexing
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ END CATEGORY
-+
-+ POLICY !!Pol_TurnOffAdvancedFeatures
-+ EXPLAIN !!Explain_TurnOffAdvancedFeatures
-+ VALUENAME error_report_on
-+ VALUEON NUMERIC 0
-+ END POLICY
-+
-+ POLICY !!Pol_TurnOffImproveGd
-+ EXPLAIN !!Explain_TurnOffImproveGd
-+ VALUENAME improve_gd
-+ VALUEON NUMERIC 0
-+ VALUEOFF NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_NoPersonalizationInfo
-+ EXPLAIN !!Explain_NoPersonalizationInfo
-+ VALUENAME send_personalization_info
-+ VALUEON NUMERIC 0
-+ VALUEOFF NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_OneBoxMode
-+ EXPLAIN !!Explain_OneBoxMode
-+ VALUENAME onebox_mode
-+ VALUEON NUMERIC 0
-+ END POLICY
-+
-+ POLICY !!Pol_EncryptIndex
-+ EXPLAIN !!Explain_EncryptIndex
-+ VALUENAME encrypt_index
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Hyper
-+ EXPLAIN !!Explain_Hyper
-+ VALUENAME hyper_off
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Display_Mode
-+ EXPLAIN !!Explain_Display_Mode
-+ PART !!Pol_Display_Mode DROPDOWNLIST
-+ VALUENAME display_mode
-+ ITEMLIST
-+ NAME !!Sidebar VALUE NUMERIC 1
-+ NAME !!Deskbar VALUE NUMERIC 8
-+ NAME !!FloatingDeskbar VALUE NUMERIC 4
-+ NAME !!None VALUE NUMERIC 0
-+ END ITEMLIST
-+ END PART
-+ END POLICY
-+
-+ END CATEGORY ; Preferences
-+
-+ CATEGORY !!Cat_Enterprise
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
-+
-+ POLICY !!Pol_Autoupdate
-+ EXPLAIN !!Explain_Autoupdate
-+ VALUENAME autoupdate_host
-+ VALUEON ""
-+ END POLICY
-+
-+ POLICY !!Pol_AutoupdateAsSystem
-+ EXPLAIN !!Explain_AutoupdateAsSystem
-+ VALUENAME autoupdate_impersonate_user
-+ VALUEON NUMERIC 0
-+ VALUEOFF NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_EnterpriseTab
-+ EXPLAIN !!Explain_EnterpriseTab
-+ PART !!EnterpriseTabText EDITTEXT
-+ VALUENAME enterprise_tab_text
-+ END PART
-+ PART !!EnterpriseTabHomepage EDITTEXT
-+ VALUENAME enterprise_tab_homepage
-+ END PART
-+ PART !!EnterpriseTabHomepageQuery CHECKBOX
-+ VALUENAME enterprise_tab_homepage_query
-+ END PART
-+ PART !!EnterpriseTabResults EDITTEXT
-+ VALUENAME enterprise_tab_results
-+ END PART
-+ PART !!EnterpriseTabResultsQuery CHECKBOX
-+ VALUENAME enterprise_tab_results_query
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_GSAHosts
-+ EXPLAIN !!Explain_GSAHosts
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
-+ PART !!Pol_GSAHosts LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Disallow_Gadgets
-+ EXPLAIN !!Explain_Disallow_Gadgets
-+ VALUENAME disallow_gadgets
-+ VALUEON NUMERIC 1
-+ PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
-+ VALUENAME disallow_only_non_builtin_gadgets
-+ VALUEON NUMERIC 1
-+ VALUEOFF NUMERIC 0
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Gadget_Whitelist
-+ EXPLAIN !!Explain_Gadget_Whitelist
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
-+ PART !!Pol_Gadget_Whitelist LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
-+ EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
-+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
-+ PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_Alternate_User_Data_Dir
-+ EXPLAIN !!Explain_Alternate_User_Data_Dir
-+ PART !!Pol_Alternate_User_Data_Dir EDITTEXT
-+ VALUENAME alternate_user_data_dir
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_MaxAllowedOutlookConnections
-+ EXPLAIN !!Explain_MaxAllowedOutlookConnections
-+ PART !!Pol_MaxAllowedOutlookConnections NUMERIC
-+ VALUENAME max_allowed_outlook_connections
-+ MIN 1 MAX 65535 DEFAULT 400 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_DisallowSsdService
-+ EXPLAIN !!Explain_DisallowSsdService
-+ VALUENAME disallow_ssd_service
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_DisallowSsdOutbound
-+ EXPLAIN !!Explain_DisallowSsdOutbound
-+ VALUENAME disallow_ssd_outbound
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_Disallow_Store_Gadget_Service
-+ EXPLAIN !!Explain_Disallow_Store_Gadget_Service
-+ VALUENAME disallow_store_gadget_service
-+ VALUEON NUMERIC 1
-+ END POLICY
-+
-+ POLICY !!Pol_MaxExchangeIndexingRate
-+ EXPLAIN !!Explain_MaxExchangeIndexingRate
-+ PART !!Pol_MaxExchangeIndexingRate NUMERIC
-+ VALUENAME max_exchange_indexing_rate
-+ MIN 1 MAX 1000 DEFAULT 60 SPIN 1
-+ END PART
-+ END POLICY
-+
-+ POLICY !!Pol_EnableSafeweb
-+ EXPLAIN !!Explain_Safeweb
-+ VALUENAME safe_browsing
-+ VALUEON NUMERIC 1
-+ VALUEOFF NUMERIC 0
-+ END POLICY
-+
-+ END CATEGORY ; Enterprise
-+
-+ END CATEGORY ; GoogleDesktopSearch
-+ END CATEGORY ; Google
-+
-+;------------------------------------------------------------------------------
-+
-+[strings]
-+Cat_Google="Google"
-+Cat_GoogleDesktopSearch="Google Desktop"
-+
-+;------------------------------------------------------------------------------
-+; Preferences
-+;------------------------------------------------------------------------------
-+Cat_Preferences="Preferences"
-+Explain_Preferences="Controls Google Desktop preferences"
-+
-+Cat_IndexAndCaptureControl="Indexing and Capture Control"
-+Explain_IndexAndCaptureControl="Controls what files, web pages, and other content will be indexed by Google Desktop."
-+
-+Blacklist_Email="Prevent indexing of email"
-+Explain_Blacklist_Email="Enabling this policy will prevent Google Desktop from indexing emails.\n\nIf this policy is not configured, the user can choose whether or not to index emails."
-+Blacklist_Gmail="Prevent indexing of Gmail"
-+Explain_Blacklist_Gmail="Enabling this policy prevents Google Desktop from indexing Gmail messages.\n\nThis policy is in effect only when the policy "Prevent indexing of email" is disabled. When that policy is enabled, all email indexing is disabled, including Gmail indexing.\n\nIf both this policy and "Prevent indexing of email" are disabled or not configured, a user can choose whether or not to index Gmail messages."
-+Blacklist_WebHistory="Prevent indexing of web pages"
-+Explain_Blacklist_WebHistory="Enabling this policy will prevent Google Desktop from indexing web pages.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index web pages."
-+Blacklist_Text="Prevent indexing of text files"
-+Explain_Blacklist_Text="Enabling this policy will prevent Google Desktop from indexing text files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index text files."
-+Blacklist_Media="Prevent indexing of media files"
-+Explain_Blacklist_Media="Enabling this policy will prevent Google Desktop from indexing media files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index media files."
-+Blacklist_Contact="Prevent indexing of contacts"
-+Explain_Blacklist_Contact="Enabling this policy will prevent Google Desktop from indexing contacts.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index contacts."
-+Blacklist_Calendar="Prevent indexing of calendar entries"
-+Explain_Blacklist_Calendar="Enabling this policy will prevent Google Desktop from indexing calendar entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index calendar entries."
-+Blacklist_Task="Prevent indexing of tasks"
-+Explain_Blacklist_Task="Enabling this policy will prevent Google Desktop from indexing tasks.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index tasks."
-+Blacklist_Note="Prevent indexing of notes"
-+Explain_Blacklist_Note="Enabling this policy will prevent Google Desktop from indexing notes.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index notes."
-+Blacklist_Journal="Prevent indexing of journal entries"
-+Explain_Blacklist_Journal="Enabling this policy will prevent Google Desktop from indexing journal entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index journal entries."
-+Blacklist_Word="Prevent indexing of Word documents"
-+Explain_Blacklist_Word="Enabling this policy will prevent Google Desktop from indexing Word documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Word documents."
-+Blacklist_Excel="Prevent indexing of Excel documents"
-+Explain_Blacklist_Excel="Enabling this policy will prevent Google Desktop from indexing Excel documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Excel documents."
-+Blacklist_Powerpoint="Prevent indexing of PowerPoint documents"
-+Explain_Blacklist_Powerpoint="Enabling this policy will prevent Google Desktop from indexing PowerPoint documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PowerPoint documents."
-+Blacklist_PDF="Prevent indexing of PDF documents"
-+Explain_Blacklist_PDF="Enabling this policy will prevent Google Desktop from indexing PDF documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PDF documents."
-+Blacklist_ZIP="Prevent indexing of ZIP files"
-+Explain_Blacklist_ZIP="Enabling this policy will prevent Google Desktop from indexing ZIP files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index ZIP files."
-+Blacklist_HTTPS="Prevent indexing of secure web pages"
-+Explain_Blacklist_HTTPS="Enabling this policy will prevent Google Desktop from indexing secure web pages (pages with HTTPS in the URL).\n\nIf this policy is disabled or not configured, the user can choose whether or not to index secure web pages."
-+Blacklist_URI_Contains="Prevent indexing of specific web sites and folders"
-+Explain_Blacklist_URI_Contains="This policy allows you to prevent Google Desktop from indexing specific websites or folders. If an item's URL or path name contains any of these specified strings, it will not be indexed. These restrictions will be applied in addition to any websites or folders that the user has specified.\n\nThis policy has no effect when disabled or not configured."
-+Blacklist_Chat="Prevent indexing of IM chats"
-+Explain_Blacklist_Chat="Enabling this policy will prevent Google Desktop from indexing IM chat conversations.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index IM chat conversations."
-+Blacklist_PasswordProtectedOffice="Prevent indexing of password-protected Office documents (Word, Excel)"
-+Explain_Blacklist_PasswordProtectedOffice="Enabling this policy will prevent Google Desktop from indexing password-protected office documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index password-protected office documents."
-+Blacklist_Extensions="Prevent indexing of specific file extensions"
-+Explain_Blacklist_Extensions="This policy allows you to prevent Google Desktop from indexing files with specific extensions. Enter a list of file extensions, separated by commas, that you wish to exclude from indexing.\n\nThis policy has no effect when disabled or not configured."
-+Pol_Disallow_UserSearchLocations="Disallow adding search locations for indexing"
-+Explain_Disallow_UserSearchLocations="Enabling this policy will prevent the user from specifying additional drives or networked folders to be indexed by Google Desktop.\n\nIf this policy is disabled or not configured, users may specify additional drives and networked folders to be indexed."
-+Pol_Search_Location_Whitelist="Allow indexing of specific folders"
-+Explain_Search_Location_Whitelist="This policy allows you to add additional drives and networked folders to index."
-+Search_Locations_Whitelist="Search these locations"
-+Email_Retention="Only retain emails that are less than x days old"
-+Explain_Email_Retention="This policy allows you to configure Google Desktop to only retain emails that are less than the specified number of days old in the index. Enter the number of days to retain emails for\n\nThis policy has no effect when disabled or not configured."
-+Email_Retention_Edit="Number of days to retain emails"
-+Webpage_Retention="Only retain webpages that are less than x days old"
-+Explain_Webpage_Retention="This policy allows you to configure Google Desktop to only retain webpages that are less than the specified number of days old in the index. Enter the number of days to retain webpages for\n\nThis policy has no effect when disabled or not configured."
-+Webpage_Retention_Edit="Number of days to retain webpages"
-+File_Retention="Only retain files that are less than x days old"
-+Explain_File_Retention="This policy allows you to configure Google Desktop to only retain files that are less than the specified number of days old in the index. Enter the number of days to retain files for\n\nThis policy has no effect when disabled or not configured."
-+File_Retention_Edit="Number of days to retain files"
-+IM_Retention="Only retain IM that are less than x days old"
-+Explain_IM_Retention="This policy allows you to configure Google Desktop to only retain IM that are less than the specified number of days old in the index. Enter the number of days to retain IM for\n\nThis policy has no effect when disabled or not configured."
-+IM_Retention_Edit="Number of days to retain IM"
-+
-+Pol_Remove_Deleted_Items="Remove deleted items from the index."
-+Explain_Remove_Deleted_Items="Enabling this policy will remove all deleted items from the index and cache. Any items that are deleted will no longer be searchable."
-+
-+Pol_Allow_Simultaneous_Indexing="Allow historical indexing for multiple users simultaneously."
-+Explain_Allow_Simultaneous_Indexing="Enabling this policy will allow a computer to generate first-time indexes for multiple users simultaneously. \n\nIf this policy is disabled or not configured, historical indexing will happen only for the logged-in user that was connected last; historical indexing for any other logged-in user will happen the next time that other user connects."
-+
-+Pol_TurnOffAdvancedFeatures="Turn off Advanced Features options"
-+Explain_TurnOffAdvancedFeatures="Enabling this policy will prevent Google Desktop from sending Advanced Features data to Google (for either improvements or personalization), and users won't be able to change these options. Enabling this policy also prevents older versions of Google Desktop from sending data.\n\nIf this policy is disabled or not configured and the user has a pre-5.5 version of Google Desktop, the user can choose whether or not to enable sending data to Google. If the user has version 5.5 or later, the 'Turn off Improve Google Desktop option' and 'Do not send personalization info' policies will be used instead."
-+
-+Pol_TurnOffImproveGd="Turn off Improve Google Desktop option"
-+Explain_TurnOffImproveGd="Enabling this policy will prevent Google Desktop from sending improvement data, including crash reports and anonymous usage data, to Google.\n\nIf this policy is disabled, improvement data will be sent to Google and the user won't be able to change the option.\n\nIf this policy is not configured, the user can choose whether or not to enable the Improve Google Desktop option.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
-+
-+Pol_NoPersonalizationInfo="Do not send personalization info"
-+Explain_NoPersonalizationInfo="Enabling this policy will prevent Google Desktop from displaying personalized content, such as news that reflects the user's past interest in articles. Personalized content is derived from anonymous usage data sent to Google.\n\nIf this policy is disabled, personalized content will be displayed for all users, and users won't be able to disable this feature.\n\nIf this policy is not configured, users can choose whether or not to enable personalization in each gadget that supports this feature.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
-+
-+Pol_OneBoxMode="Turn off Google Web Search Integration"
-+Explain_OneBoxMode="Enabling this policy will prevent Google Desktop from displaying Desktop Search results in queries to google.com.\n\nIf this policy is disabled or not configured, the user can choose whether or not to include Desktop Search results in queries to google.com."
-+
-+Pol_EncryptIndex="Encrypt index data"
-+Explain_EncryptIndex="Enabling this policy will cause Google Desktop to turn on Windows file encryption for the folder containing the Google Desktop index and related user data the next time it is run.\n\nNote that Windows EFS is only available on NTFS volumes. If the user's data is stored on a FAT volume, this policy will have no effect.\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_Hyper="Turn off Quick Find"
-+Explain_Hyper="Enabling this policy will cause Google Desktop to turn off Quick Find feature. Quick Find allows you to see results as you type.\n\nIf this policy is disabled or not configured, the user can choose whether or not to enable it."
-+
-+Pol_Display_Mode="Choose display option"
-+Explain_Display_Mode="This policy sets the Google Desktop display option: Sidebar, Deskbar, Floating Deskbar or none.\n\nNote that on 64-bit systems, a setting of Deskbar will be interpreted as Floating Deskbar.\n\nIf this policy is disabled or not configured, the user can choose a display option."
-+Sidebar="Sidebar"
-+Deskbar="Deskbar"
-+FloatingDeskbar="Floating Deskbar"
-+None="None"
-+
-+;------------------------------------------------------------------------------
-+; Enterprise
-+;------------------------------------------------------------------------------
-+Cat_Enterprise="Enterprise Integration"
-+Explain_Enterprise="Controls features specific to Enterprise installations of Google Desktop"
-+
-+Pol_Autoupdate="Block Auto-update"
-+Explain_Autoupdate="Enabling this policy prevents Google Desktop from automatically checking for and installing updates from google.com.\n\nIf you enable this policy, you must distribute updates to Google Desktop using Group Policy, SMS, or a similar enterprise software distribution mechanism. You should check http://desktop.google.com/enterprise/ for updates.\n\nIf this policy is disabled or not configured, Google Desktop will periodically check for updates from desktop.google.com."
-+
-+Pol_AutoupdateAsSystem="Use system proxy settings when auto-updating"
-+Explain_AutoupdateAsSystem="Enabling this policy makes Google Desktop use the machine-wide proxy settings (as specified using e.g. proxycfg.exe) when performing autoupdates (if enabled).\n\nIf this policy is disabled or not configured, Google Desktop will use the logged-on user's Internet Explorer proxy settings when checking for auto-updates (if enabled)."
-+
-+Pol_EnterpriseTab="Enterprise search tab"
-+Explain_EnterpriseTab="This policy allows you to add a search tab for your Google Search Appliance to Google Desktop and google.com web pages.\n\nYou must provide the name of the tab, such as "Intranet", as well as URLs for the search homepage and for retrieving search results. Use [DISP_QUERY] in place of the query term for the search results URL.\n\nSee the administrator's guide for more details."
-+EnterpriseTabText="Tab name"
-+EnterpriseTabHomepage="Search homepage URL"
-+EnterpriseTabHomepageQuery="Check if search homepage supports '&&q=<query>'"
-+EnterpriseTabResults="Search results URL"
-+EnterpriseTabResultsQuery="Check if search results page supports '&&q=<query>'"
-+
-+Pol_GSAHosts="Google Search Appliances"
-+Explain_GSAHosts="This policy allows you to list any Google Search Appliances in your intranet. When properly configured, Google Desktop will insert Google Desktop results into the results of queries on the Google Search Appliance"
-+
-+Pol_PolicyUnawareClientProhibitedFlag="Prohibit Policy-Unaware versions"
-+Explain_PolicyUnawareClientProhibitedFlag="Prohibits installation and execution of versions of Google Desktop that are unaware of group policy.\n\nEnabling this policy will prevent users from installing or running version 1.0 of Google Desktop.\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_MinimumAllowedVersion="Minimum allowed version"
-+Explain_MinimumAllowedVersion="This policy allows you to prevent installation and/or execution of older versions of Google Desktop by specifying the minimum version you wish to allow. When enabling this policy, you should also enable the "Prohibit Policy-Unaware versions" policy to block versions of Google Desktop that did not support group policy.\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_MaximumAllowedVersion="Maximum allowed version"
-+Explain_MaximumAllowedVersion="This policy allows you to prevent installation and/or execution of newer versions of Google Desktop by specifying the maximum version you wish to allow.\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_Disallow_Gadgets="Disallow gadgets and indexing plug-ins"
-+Explain_Disallow_Gadgets="This policy prevents the use of all Google Desktop gadgets and indexing plug-ins. The policy applies to gadgets that are included in the Google Desktop installation package (built-in gadgets), built-in indexing plug-ins (currently only the Lotus Notes plug-in), and to gadgets or indexing plug-ins that a user might want to add later (non-built-in gadgets and indexing plug-ins).\n\nYou can prohibit use of all non-built-in gadgets and indexing plug-ins, but allow use of built-in gadgets and indexing plug-ins. To do so, enable this policy and then select the option "Disallow only non-built-in gadgets and indexing plug-ins.\n\nYou can supersede this policy to allow specified built-in and non-built-in gadgets and indexing plug-ins. To do so, enable this policy and then specify the gadgets and/or indexing plug-ins you want to allow under "Gadget and Plug-in Whitelist.""
-+Disallow_Only_Non_Builtin_Gadgets="Disallow only non-built-in gadgets and indexing plug-ins"
-+
-+Pol_Gadget_Whitelist="Gadget and plug-in whitelist"
-+Explain_Gadget_Whitelist="This policy specifies a list of Google Desktop gadgets and indexing plug-ins that you want to allow, as exceptions to the "Disallow gadgets and indexing plug-ins" policy. This policy is valid only when the "Disallow gadgets and indexing plug-ins" policy is enabled.\n\nFor each gadget or indexing plug-in you wish to allow, add the CLSID or PROGID of the gadget or indexing plug-in (see the administrator's guide for more details).\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_Gadget_Install_Confirmation_Whitelist="Allow silent installation of gadgets"
-+Explain_Gadget_Install_Confirmation_Whitelist="Enabling this policy lets you specify a list of Google Desktop gadgets or indexing plug-ins that can be installed without confirmation from the user.\n\nAdd a gadget or indexing plug-in by placing its class ID (CLSID) or program identifier (PROGID) in the list, surrounded with curly braces ({ }).\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_Alternate_User_Data_Dir="Alternate user data directory"
-+Explain_Alternate_User_Data_Dir="This policy allows you to specify a directory to be used to store user data for Google Desktop (such as index data and cached documents).\n\nYou may use [USER_NAME] or [DOMAIN_NAME] in the path to specify the current user's name or domain. If [USER_NAME] is not specified, the user name will be appended at the end of the path.\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_MaxAllowedOutlookConnections="Maximum allowed Outlook connections"
-+Explain_MaxAllowedOutlookConnections="This policy specifies the maximum number of open connections that Google Desktop maintains with the Exchange server. Google Desktop opens a connection for each email folder that it indexes. If insufficient connections are allowed, Google Desktop cannot index all the user email folders.\n\nThe default value is 400. Because users rarely have as many as 400 email folders, Google Desktop rarely reaches the limit.\n\nIf you set this policy's value above 400, you must also configure the number of open connections between Outlook and the Exchange server. By default, approximately 400 connections are allowed. If Google Desktop uses too many of these connections, Outlook might be unable to access email.\n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_DisallowSsdService="Disallow sharing and receiving of web history and documents across computers"
-+Explain_DisallowSsdService="Enabling this policy will prevent Google Desktop from sharing the user's web history and document contents across the user's different Google Desktop installations, and will also prevent it from receiving such shared items from the user's other machines. To allow reception but disallow sharing, use DisallowSsdOutbound.\nThis policy has no effect when disabled or not configured."
-+
-+Pol_DisallowSsdOutbound="Disallow sharing of web history and documents to user's other computers."
-+Explain_DisallowSsdOutbound="Enabling this policy will prevent Google Desktop from sending the user's web history and document contents from this machine to the user's other machines. It does not prevent reception of items from the user's other machines; to disallow both, use DisallowSsdService.\nThis policy has no effect when disabled or not configured."
-+
-+Pol_Disallow_Store_Gadget_Service="Disallow storage of gadget content and settings."
-+Explain_Disallow_Store_Gadget_Service="Enabling this policy will prevent users from storing their gadget content and settings with Google. Users will be unable to access their gadget content and settings from other computers and all content and settings will be lost if Google Desktop is uninstalled."
-+
-+Pol_MaxExchangeIndexingRate="Maximum allowed Exchange indexing rate"
-+Explain_MaxExchangeIndexingRate="This policy allows you to specify the maximum number of emails that are indexed per minute. \n\nThis policy has no effect when disabled or not configured."
-+
-+Pol_EnableSafeweb="Enable or disable safe browsing"
-+Explain_Safeweb="Google Desktop safe browsing informs the user whenever they visit any site which is a suspected forgery site or may harm their computer. Enabling this policy turns on safe browsing; disabling the policy turns it off. \n\nIf this policy is not configured, the user can select whether to turn on safe browsing."
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/README.txt b/tools/grit/grit/testdata/README.txt
-new file mode 100644
-index 0000000000..a683b3b9e3
---- /dev/null
-+++ b/tools/grit/grit/testdata/README.txt
-@@ -0,0 +1,87 @@
-+Google Desktop for Enterprise
-+Copyright (C) 2007 Google Inc.
-+All Rights Reserved
-+
-+---------
-+Contents
-+---------
-+This distribution contains the following files:
-+
-+GoogleDesktopSetup.msi - Installation and setup program
-+GoogleDesktop.adm - Group Policy administrative template file
-+AdminGuide.pdf - Google Desktop for Enterprise administrative guide
-+
-+
-+--------------
-+Documentation
-+--------------
-+Full documentation and installation instructions are in the
-+administrative guide, and also online at
-+http://desktop.google.com/enterprise/adminguide.html.
-+
-+
-+------------------------
-+IBM Lotus Notes Plug-In
-+------------------------
-+The Lotus Notes plug-in is included in the release of Google
-+Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google
-+Desktop indexes mail, calendar, task, contact and journal
-+documents from Notes. Discussion documents including those from
-+the discussion and team room templates can also be indexed by
-+selecting an option from the preferences. Once indexed, this data
-+will be returned in Google Desktop searches. The corresponding
-+document can be opened in Lotus Notes from the Google Desktop
-+results page.
-+
-+Install: The plug-in will install automatically during the Google
-+Desktop setup process if Lotus Notes is already installed. Lotus
-+Notes must not be running in order for the install to occur. The
-+Class ID for this plug-in is {8F42BDFB-33E8-427B-AFDC-A04E046D3F07}.
-+
-+Preferences: Preferences and selection of databases to index are
-+set in the 'Google Desktop for Notes' dialog reached through the
-+'Actions' menu.
-+
-+Reindexing: Selecting 'Reindex all databases' will index all the
-+documents in each database again.
-+
-+
-+Notes Plug-in Known Issues
-+---------------------------
-+
-+If the 'Google Desktop for Notes' item is not available from the
-+Lotus Notes Actions menu, then installation was not successful.
-+Installation consists of writing one file, notesgdsplugin.dll, to
-+the Notes application directory and a setting to the notes.ini
-+configuration file. The most likely cause of an unsuccessful
-+installation is that the installer was not able to locate the
-+notes.ini file. Installation will complete if the user closes Notes
-+and manually adds the following setting to this file on a new line:
-+AddinMenus=notesgdsplugin.dll
-+
-+If the notesgdsplugin.dll file is not in the application directory
-+(e.g., C:\Program Files\Lotus\Notes) after Google Desktop
-+installation, it is likely that Notes was not installed correctly.
-+
-+Only local databases can be indexed. If they can be determined,
-+the user's local mail file and address book will be included in the
-+list automatically. Mail archives and other databases must be
-+added with the 'Add' button.
-+
-+Some users may experience performance issues during the initial
-+indexing of a database. The 'Perform the initial index of a
-+database only when I'm idle' option will limit the indexing process
-+to times when the user is not using the machine. If this does not
-+alleviate the problem or the user would like to continually index
-+but just do so more slowly or quickly, the GoogleWaitTime notes.ini
-+value can be set. Increasing the GoogleWaitTime value will slow
-+down the indexing process, and lowering the value will speed it up.
-+A value of zero causes the fastest possible indexing. Removing the
-+ini parameter altogether returns it to the default (20).
-+
-+Crashes have been known to occur with certain types of history
-+bookmarks. If the Notes client seems to crash randomly, try
-+disabling the 'Index note history' option. If it crashes before,
-+you can get to the preferences, add the following line to your
-+notes.ini file:
-+GDSNoIndexHistory=1
-diff --git a/tools/grit/grit/testdata/about.html b/tools/grit/grit/testdata/about.html
-new file mode 100644
-index 0000000000..8e5fad7b2b
---- /dev/null
-+++ b/tools/grit/grit/testdata/about.html
-@@ -0,0 +1,45 @@
-+[HEADER]
-+<table cellspacing=0 cellPadding=0 width="100%" border=0><tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr></table>
-+<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0><tr><td height=20><font size=+1 color=#000000>&nbsp;<b>[TITLE]</b></font></td></tr></table>
-+<br><center><span style="line-height:16pt"><font color=#335cec><B>Google Desktop Search: Search your own computer.</B></font></span></center><br>
-+
-+<table cellspacing=1 cellpadding=0 width=300 align=center border=0>
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="outlook.gif" width=16>&nbsp;&nbsp;Outlook Email</font></td>
-+<td nowrap>&nbsp;</td>
-+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="netscape.gif" width=16>&nbsp;&nbsp;Netscape Mail / Thunderbird</font></td></tr>
-+
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="oe.gif" width=16>&nbsp;&nbsp;Outlook Express</font></td>
-+<td nowrap>&nbsp;</td>
-+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ff.gif" width=16>&nbsp;&nbsp;Netscape / Firefox / Mozilla</font></td></tr>
-+
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="doc.gif" width=16>&nbsp;&nbsp;Word</font></td>
-+<td nowrap>&nbsp;</td>
-+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="pdf.gif" width=16>&nbsp;&nbsp;PDF</font></td></tr>
-+
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="xls.gif" width=16>&nbsp;&nbsp;Excel</font></td>
-+<td nowrap>&nbsp;</td>
-+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mus.gif" width=16>&nbsp;&nbsp;Music</font></td></tr>
-+
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ppt.gif" width=16>&nbsp;&nbsp;PowerPoint</font></td>
-+<td nowrap>&nbsp;</td>
-+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="jpg.gif" width=16>&nbsp;&nbsp;Images</font></td></tr>
-+
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ie.gif" width=16>&nbsp;&nbsp;Internet Explorer</font></td>
-+<td nowrap>&nbsp;</td>
-+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mov.gif" width=16>&nbsp;&nbsp;Video</font></td></tr>
-+
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="aim.gif" width=16>&nbsp;&nbsp;AOL Instant Messenger</font></td>
-+<td nowrap>&nbsp;</td>
-+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="other.gif" width=16>&nbsp;&nbsp;Even more with <a href="http://desktop.google.com/plugins.html">these plug-ins</A></font></td></tr>
-+
-+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="txt.gif" width=16>&nbsp;&nbsp;Text and others</font></td></tr>
-+</table>
-+<center>
-+<p><table cellpadding=1>
-+<tr><td><a href="http://desktop.google.com/gettingstarted.html?hl=[LANG_CODE]"><B>Getting Started</B></A> - Learn more about using Google Desktop Search</td></tr>
-+<tr><td><a href="http://desktop.google.com/help.html?hl=[LANG_CODE]"><B>Online Help</B></A> - Up-to-date answers to your questions</td></tr>
-+<tr><td><a href="[$~PRIVACY~$]"><B>Privacy</B></A> - A few words about privacy and Google Desktop Search</td></tr>
-+<tr><td><a href="http://desktop.google.com/uninstall.html?hl=[LANG_CODE]"><B>Uninstall</B></A> - How to uninstall Google Desktop Search</td></tr>
-+<tr><td><a href="http://desktop.google.com/feedback.html?hl=[LANG_CODE]"><B>Submit Feedback</B></A> - Send us your comments and ideas</td></tr>
-+</table><br><font size=-2>Google Desktop Search [$~BUILDNUMBER~$]</font><br><br>
-+[FOOTER]
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/android.xml b/tools/grit/grit/testdata/android.xml
-new file mode 100644
-index 0000000000..cc3b141f70
---- /dev/null
-+++ b/tools/grit/grit/testdata/android.xml
-@@ -0,0 +1,24 @@
-+<!--
-+ Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+ Use of this source code is governed by a BSD-style license that can be
-+ found in the LICENSE file.
-+-->
-+
-+<resources>
-+ <!-- A string with placeholder. -->
-+ <string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" name="placeholders">
-+ Open <xliff:g id="FILENAME" example="internet.html">%s</xliff:g>?
-+ </string>
-+
-+ <!-- A simple string. -->
-+ <string name="simple">A simple string.</string>
-+
-+ <!-- A string with a comment. -->
-+ <string name="comment">Contains a <!-- ignore this --> comment. </string>
-+
-+ <!-- A second simple string. -->
-+ <string name="simple2"> Another simple string. </string>
-+
-+ <!-- A non-translatable string. -->
-+ <string name="constant" translatable="false">Do not translate me.</string>
-+</resources>
-diff --git a/tools/grit/grit/testdata/bad_browser.html b/tools/grit/grit/testdata/bad_browser.html
-new file mode 100644
-index 0000000000..e8cf34664d
---- /dev/null
-+++ b/tools/grit/grit/testdata/bad_browser.html
-@@ -0,0 +1,16 @@
-+<p><b>We're sorry, but we don't seem to be compatible.</b></p>
-+<p><font size="-1">Our software suggests that you're using a browser incompatible with Google Desktop Search.
-+ Google Desktop Search currently supports the following:</font></p>
-+<ul><font size="-1">
-+ <li>Microsoft IE 5 and newer (<a href="http://www.microsoft.com/windows/ie/downloads/default.asp">Download</a>)</li>
-+ <li>Mozilla (<a href="http://www.mozilla.org/products/mozilla1.x/">Download</a>)</li>
-+ <li>Mozilla Firefox (<a href="http://www.mozilla.org/products/firefox/">Download</a>)</li>
-+ <li>Netscape 7 and newer (<a href="http://channels.netscape.com/ns/browsers/download.jsp">Download</a>)</li>
-+</font></ul>
-+
-+<p><font size="-1">You may <a href="[REDIR]">click here</a> to use your
-+ unsupported browser, though you likely will encounter some areas that don't
-+ work as expected. You need to have Javascript enabled, regardless of the
-+ browser you use.</font>
-+<p><font size="-1">We hope to expand this list in the near future and announce new
-+ browsers as they become available.
-diff --git a/tools/grit/grit/testdata/browser.html b/tools/grit/grit/testdata/browser.html
-new file mode 100644
-index 0000000000..45d364d56f
---- /dev/null
-+++ b/tools/grit/grit/testdata/browser.html
-@@ -0,0 +1,42 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>[$~TITLE~$]</title>
-+<style>
-+BODY { MARGIN-LEFT: 1em; MARGIN-RIGHT: 1em }
-+BODY, TD, DIV, A { FONT-FAMILY: arial,sans-serif}
-+DIV, TD { COLOR: #000}
-+A:link { COLOR: #00c}
-+A:visited { COLOR: #551a8b}
-+A:active { COLOR: #f00 }
-+</style>
-+</head>
-+
-+<body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#800080" alink="#ff0000" topmargin=2>
-+
-+<table cellspacing=2 cellpadding=0 width="99%" border=0>
-+<tr>
-+ <td width="1%" rowspan=2>[$~IMAGE~$]
-+ <td>&nbsp;</td>
-+ <td rowspan=2>
-+ <table cellspacing=0 cellpadding=0 width="100%" border=0>
-+ <tr>
-+ <td bgcolor=#3399cc><img height=1 width=1></td>
-+ </tr>
-+ </table>
-+ <table cellspacing=0 cellpadding=0 width="100%" border=0 bgcolor=#efefef>
-+ <tr>
-+ <td nowrap bgcolor=#E8F4F7><font face=arial,sans-serif color=#000000 size=+1><b>&nbsp;[$~CHROME_TITLE~$]</b></font></td>
-+ </tr>
-+ </table>
-+ </td>
-+</tr>
-+</table>
-+
-+<table cellpadding=3 width="94%" align="center" cellspacing=0 border=0>
-+<tr valign="middle">
-+ <td valign="top">
-+ [$~BODY~$]
-+ </td>
-+ </tr>
-+</table>
-+[$~FOOTER~$]
-+</body></html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/buildinfo.grd b/tools/grit/grit/testdata/buildinfo.grd
-new file mode 100644
-index 0000000000..80458a8265
---- /dev/null
-+++ b/tools/grit/grit/testdata/buildinfo.grd
-@@ -0,0 +1,46 @@
-+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-+<grit
-+ base_dir="."
-+ source_lang_id="en"
-+ tc_project="GoogleDesktopWindowsClient"
-+ latest_public_release="0"
-+ current_release="1"
-+ enc_check="möl">
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
-+ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
-+ </outputs>
-+ <translations>
-+ <file path="substitute.xmb" lang="sv" />
-+ </translations>
-+ <release seq="1" allow_pseudo="false">
-+ <includes>
-+ <include type="BITMAP" name="IDB_PR" file="pr.bmp" />
-+ <if expr="lang == 'sv'">
-+ <include type="BITMAP" name="IDB_PR2" file="pr2.bmp" />
-+ </if>
-+ </includes>
-+ <structures>
-+ <structure name="SIDEBAR_LOADING.HTML" encoding="utf-8" file="sidebar_loading.html" type="tr_html" generateid="false" expand_variables="false"/>
-+ <structure name="IDS_PLACEHOLDER" file="transl.rc" type="dialog" >
-+ <skeleton expr="lang == 'sv'" file="transl1.rc" variant_of_revision="1"/>
-+ </structure>
-+ <if expr="lang != 'sv'">
-+ <structure name="WELCOME_TOAST.HTML" encoding="utf-8" file="welcome_toast.html" type="tr_html" generateid="false" expand_variables="true"/>
-+ </if>
-+ </structures>
-+ <messages first_id="8192">
-+ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
-+ Copyright 2008 Google Inc. All Rights Reserved.
-+ </message>
-+ <message name="IDS_NEWS_PANEL_COPYRIGHT">
-+ Google Desktop News gadget
-+[IDS_COPYRIGHT_GOOGLE_LONG]
-+View news that is personalized based on the articles you read.
-+
-+For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
-+ </message>
-+ </messages>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/testdata/cache_prefix.html b/tools/grit/grit/testdata/cache_prefix.html
-new file mode 100644
-index 0000000000..b1f91dd82b
---- /dev/null
-+++ b/tools/grit/grit/testdata/cache_prefix.html
-@@ -0,0 +1,24 @@
-+<head>
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+</head>
-+<body onload="[ONLOAD]">
-+<table width="100%" border=1><tr><td>
-+<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
-+<tr><td><font face="arial,sans-serif" color=black size=-1>This is one version of <a href="[$~URL~$]">
-+<font color="blue">[URL-DISP]</font></a> from your personal <a href="http://desktop.google.com/webcache.html"><font color=blue>cache</font></a>.<br>
-+The page may have changed since that time. Click here for the <a href="[$~URL~$]"><font color="blue">current page</font></a>.<br>
-+Since this page is stored on your computer, publicly linking to this page will not work.[$~EXTRA~$]<br><br>
-+<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
-+</td>
-+</tr></table></td></tr></table>
-+<style>
-+.hl { color:black; background-color:#ffff88}
-+</style>
-+<script>
-+[$~HIGHLIGHT_SCRIPT~$]
-+window.onerror=new Function(';');
-+</script>
-+<hr id=gg_1>
-+</body>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/cache_prefix_file.html b/tools/grit/grit/testdata/cache_prefix_file.html
-new file mode 100644
-index 0000000000..f3eb8e0f11
---- /dev/null
-+++ b/tools/grit/grit/testdata/cache_prefix_file.html
-@@ -0,0 +1,25 @@
-+<head>
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1"></head>
-+<body onload="[ONLOAD]">
-+<table width="100%" border=1>
-+<tr><td>
-+<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
-+<tr><td><font face=arial,sans-serif color=black size=-1>This is one version of <a href="[$~URL~$]"><font color=blue>[URL-DISP]</font></a>
-+from your personal <a href="http://desktop.google.com/filecache.html"><font color=blue>cache</font></a>.<br>
-+The file may have changed since that time. Click here for the <a href="[$~URL~$]"><font color=blue>current file</font></a>.<br>
-+Since this file is stored on your computer, publicly linking to it will not work.[$~EXTRA~$]<br><br>
-+<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
-+</td></tr>
-+</table>
-+</td></tr></table>
-+<style>
-+.hl { color:black; background-color:#ffff88}
-+</style>
-+<script>
-+[$~HIGHLIGHT_SCRIPT~$]
-+window.onerror=new Function(';');
-+</script>
-+<hr id=gg_1>
-+</body>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/chat_result.html b/tools/grit/grit/testdata/chat_result.html
-new file mode 100644
-index 0000000000..318078bc3d
---- /dev/null
-+++ b/tools/grit/grit/testdata/chat_result.html
-@@ -0,0 +1,24 @@
-+[HEADER]
-+[CHROME]
-+<table border=0 cellpadding=2 cellspacing=2>
-+<tr><td>[$~STARTCHAT~$]</td></tr>
-+</table>
-+<blockquote id=gg_1>
-+<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
-+<img style="vertical-align:middle;" height=16 src="16x16_chat.gif" width=16> &nbsp; <b>[$~TITLE~$]</b>
-+<font size=-1><br><br>Participants: [USERNAME], [BUDDYNAME]<br>
-+Date: [TIME]</font></td></tr></table>
-+<br id=contents>
-+<label>[CONTENTS]</label>
-+</blockquote>
-+<table border=0 cellpadding=2 cellspacing=2>
-+<tr><td>[$~STARTCHAT~$]</td></tr>
-+</table>
-+<style>
-+.hl { color:black; background-color:#ffff88}
-+</style>
-+<script>
-+[$~HIGHLIGHT_SCRIPT~$]
-+[ONLOAD]
-+</script>
-+[FOOTER]
-diff --git a/tools/grit/grit/testdata/chrome/app/generated_resources.grd b/tools/grit/grit/testdata/chrome/app/generated_resources.grd
-new file mode 100644
-index 0000000000..c2efb77fd8
---- /dev/null
-+++ b/tools/grit/grit/testdata/chrome/app/generated_resources.grd
-@@ -0,0 +1,199 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+
-+<!--
-+This file contains definitions of resources that will be translated for each
-+locale. The variables is_win, is_macosx, is_linux, and is_posix are available
-+for making strings OS specific. Other platform defines such as use_titlecase
-+are declared in build/common.gypi.
-+-->
-+
-+<grit base_dir="." latest_public_release="0" current_release="1"
-+ source_lang_id="en" enc_check="möl">
-+ <outputs>
-+ <output filename="grit/generated_resources.h" type="rc_header">
-+ <emit emit_type='prepend'></emit>
-+ </output>
-+ <output filename="generated_resources_am.pak" type="data_package" lang="am" />
-+ <output filename="generated_resources_ar.pak" type="data_package" lang="ar" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_ast.pak" type="data_package" lang="ast" />
-+ </if>
-+ <output filename="generated_resources_bg.pak" type="data_package" lang="bg" />
-+ <output filename="generated_resources_bn.pak" type="data_package" lang="bn" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_bs.pak" type="data_package" lang="bs" />
-+ </if>
-+ <output filename="generated_resources_ca.pak" type="data_package" lang="ca" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_ca@valencia.pak" type="data_package" lang="ca@valencia" />
-+ </if>
-+ <output filename="generated_resources_cs.pak" type="data_package" lang="cs" />
-+ <output filename="generated_resources_da.pak" type="data_package" lang="da" />
-+ <output filename="generated_resources_de.pak" type="data_package" lang="de" />
-+ <output filename="generated_resources_el.pak" type="data_package" lang="el" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_en-AU.pak" type="data_package" lang="en-AU" />
-+ </if>
-+ <output filename="generated_resources_en-GB.pak" type="data_package" lang="en-GB" />
-+ <output filename="generated_resources_en-US.pak" type="data_package" lang="en" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_eo.pak" type="data_package" lang="eo" />
-+ </if>
-+ <output filename="generated_resources_es.pak" type="data_package" lang="es" />
-+ <output filename="generated_resources_es-419.pak" type="data_package" lang="es-419" />
-+ <output filename="generated_resources_et.pak" type="data_package" lang="et" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_eu.pak" type="data_package" lang="eu" />
-+ </if>
-+ <output filename="generated_resources_fa.pak" type="data_package" lang="fa" />
-+ <output filename="generated_resources_fake-bidi.pak" type="data_package" lang="fake-bidi" />
-+ <output filename="generated_resources_fi.pak" type="data_package" lang="fi" />
-+ <output filename="generated_resources_fil.pak" type="data_package" lang="fil" />
-+ <output filename="generated_resources_fr.pak" type="data_package" lang="fr" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_gl.pak" type="data_package" lang="gl" />
-+ </if>
-+ <output filename="generated_resources_gu.pak" type="data_package" lang="gu" />
-+ <output filename="generated_resources_he.pak" type="data_package" lang="he" />
-+ <output filename="generated_resources_hi.pak" type="data_package" lang="hi" />
-+ <output filename="generated_resources_hr.pak" type="data_package" lang="hr" />
-+ <output filename="generated_resources_hu.pak" type="data_package" lang="hu" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_hy.pak" type="data_package" lang="hy" />
-+ <output filename="generated_resources_ia.pak" type="data_package" lang="ia" />
-+ </if>
-+ <output filename="generated_resources_id.pak" type="data_package" lang="id" />
-+ <output filename="generated_resources_it.pak" type="data_package" lang="it" />
-+ <output filename="generated_resources_ja.pak" type="data_package" lang="ja" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_ka.pak" type="data_package" lang="ka" />
-+ </if>
-+ <output filename="generated_resources_kn.pak" type="data_package" lang="kn" />
-+ <output filename="generated_resources_ko.pak" type="data_package" lang="ko" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_ku.pak" type="data_package" lang="ku" />
-+ <output filename="generated_resources_kw.pak" type="data_package" lang="kw" />
-+ </if>
-+ <output filename="generated_resources_lt.pak" type="data_package" lang="lt" />
-+ <output filename="generated_resources_lv.pak" type="data_package" lang="lv" />
-+ <output filename="generated_resources_ml.pak" type="data_package" lang="ml" />
-+ <output filename="generated_resources_mr.pak" type="data_package" lang="mr" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_ms.pak" type="data_package" lang="ms" />
-+ </if>
-+ <output filename="generated_resources_nl.pak" type="data_package" lang="nl" />
-+ <!-- The translation console uses 'no' for Norwegian Bokmål. It should
-+ be 'nb'. -->
-+ <output filename="generated_resources_nb.pak" type="data_package" lang="no" />
-+ <output filename="generated_resources_pl.pak" type="data_package" lang="pl" />
-+ <output filename="generated_resources_pt-BR.pak" type="data_package" lang="pt-BR" />
-+ <output filename="generated_resources_pt-PT.pak" type="data_package" lang="pt-PT" />
-+ <output filename="generated_resources_ro.pak" type="data_package" lang="ro" />
-+ <output filename="generated_resources_ru.pak" type="data_package" lang="ru" />
-+ <output filename="generated_resources_sk.pak" type="data_package" lang="sk" />
-+ <output filename="generated_resources_sl.pak" type="data_package" lang="sl" />
-+ <output filename="generated_resources_sr.pak" type="data_package" lang="sr" />
-+ <output filename="generated_resources_sv.pak" type="data_package" lang="sv" />
-+ <output filename="generated_resources_sw.pak" type="data_package" lang="sw" />
-+ <output filename="generated_resources_ta.pak" type="data_package" lang="ta" />
-+ <output filename="generated_resources_te.pak" type="data_package" lang="te" />
-+ <output filename="generated_resources_th.pak" type="data_package" lang="th" />
-+ <output filename="generated_resources_tr.pak" type="data_package" lang="tr" />
-+ <if expr="pp_ifdef('use_third_party_translations')">
-+ <output filename="generated_resources_ug.pak" type="data_package" lang="ug" />
-+ </if>
-+ <output filename="generated_resources_uk.pak" type="data_package" lang="uk" />
-+ <output filename="generated_resources_vi.pak" type="data_package" lang="vi" />
-+ <output filename="generated_resources_zh-CN.pak" type="data_package" lang="zh-CN" />
-+ <output filename="generated_resources_zh-TW.pak" type="data_package" lang="zh-TW" />
-+ </outputs>
-+ <translations>
-+ <file path="resources/generated_resources_am.xtb" lang="am" />
-+ <file path="resources/generated_resources_ar.xtb" lang="ar" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_ast.xtb" lang="ast" />
-+ <file path="resources/generated_resources_bg.xtb" lang="bg" />
-+ <file path="resources/generated_resources_bn.xtb" lang="bn" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_bs.xtb" lang="bs" />
-+ <file path="resources/generated_resources_ca.xtb" lang="ca" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_ca-valencia.xtb" lang="ca@valencia" />
-+ <file path="resources/generated_resources_cs.xtb" lang="cs" />
-+ <file path="resources/generated_resources_da.xtb" lang="da" />
-+ <file path="resources/generated_resources_de.xtb" lang="de" />
-+ <file path="resources/generated_resources_el.xtb" lang="el" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_en-AU.xtb" lang="en-AU" />
-+ <file path="resources/generated_resources_en-GB.xtb" lang="en-GB" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_eo.xtb" lang="eo" />
-+ <file path="resources/generated_resources_es.xtb" lang="es" />
-+ <file path="resources/generated_resources_es-419.xtb" lang="es-419" />
-+ <file path="resources/generated_resources_et.xtb" lang="et" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_eu.xtb" lang="eu" />
-+ <file path="resources/generated_resources_fa.xtb" lang="fa" />
-+ <file path="resources/generated_resources_fi.xtb" lang="fi" />
-+ <file path="resources/generated_resources_fil.xtb" lang="fil" />
-+ <file path="resources/generated_resources_fr.xtb" lang="fr" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_gl.xtb" lang="gl" />
-+ <file path="resources/generated_resources_gu.xtb" lang="gu" />
-+ <file path="resources/generated_resources_hi.xtb" lang="hi" />
-+ <file path="resources/generated_resources_hr.xtb" lang="hr" />
-+ <file path="resources/generated_resources_hu.xtb" lang="hu" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_hy.xtb" lang="hy" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_ia.xtb" lang="ia" />
-+ <file path="resources/generated_resources_id.xtb" lang="id" />
-+ <file path="resources/generated_resources_it.xtb" lang="it" />
-+ <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
-+ <file path="resources/generated_resources_iw.xtb" lang="he" />
-+ <file path="resources/generated_resources_ja.xtb" lang="ja" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_ka.xtb" lang="ka" />
-+ <file path="resources/generated_resources_kn.xtb" lang="kn" />
-+ <file path="resources/generated_resources_ko.xtb" lang="ko" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_ku.xtb" lang="ku" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_kw.xtb" lang="kw" />
-+ <file path="resources/generated_resources_lt.xtb" lang="lt" />
-+ <file path="resources/generated_resources_lv.xtb" lang="lv" />
-+ <file path="resources/generated_resources_ml.xtb" lang="ml" />
-+ <file path="resources/generated_resources_mr.xtb" lang="mr" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_ms.xtb" lang="ms" />
-+ <file path="resources/generated_resources_nl.xtb" lang="nl" />
-+ <file path="resources/generated_resources_no.xtb" lang="no" />
-+ <file path="resources/generated_resources_pl.xtb" lang="pl" />
-+ <file path="resources/generated_resources_pt-BR.xtb" lang="pt-BR" />
-+ <file path="resources/generated_resources_pt-PT.xtb" lang="pt-PT" />
-+ <file path="resources/generated_resources_ro.xtb" lang="ro" />
-+ <file path="resources/generated_resources_ru.xtb" lang="ru" />
-+ <file path="resources/generated_resources_sk.xtb" lang="sk" />
-+ <file path="resources/generated_resources_sl.xtb" lang="sl" />
-+ <file path="resources/generated_resources_sr.xtb" lang="sr" />
-+ <file path="resources/generated_resources_sv.xtb" lang="sv" />
-+ <file path="resources/generated_resources_sw.xtb" lang="sw" />
-+ <file path="resources/generated_resources_ta.xtb" lang="ta" />
-+ <file path="resources/generated_resources_te.xtb" lang="te" />
-+ <file path="resources/generated_resources_th.xtb" lang="th" />
-+ <file path="resources/generated_resources_tr.xtb" lang="tr" />
-+ <file path="../../third_party/launchpad_translations/generated_resources_ug.xtb" lang="ug" />
-+ <file path="resources/generated_resources_uk.xtb" lang="uk" />
-+ <file path="resources/generated_resources_vi.xtb" lang="vi" />
-+ <file path="resources/generated_resources_zh-CN.xtb" lang="zh-CN" />
-+ <file path="resources/generated_resources_zh-TW.xtb" lang="zh-TW" />
-+ </translations>
-+ <release seq="1" allow_pseudo="false">
-+ <messages fallback_to_english="true">
-+ <!-- TODO add all of your "string table" messages here. Remember to
-+ change nontranslateable parts of the messages into placeholders (using the
-+ <ph> element). You can also use the 'grit add' tool to help you identify
-+ nontranslateable parts and create placeholders for them. -->
-+ <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_TITLE" desc="The title of the balloon that is displayed when a background app is installed">
-+ New background app installed
-+ </message>
-+ <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY" desc="The contents of the balloon that is displayed when a background app is installed">
-+ <ph name="APP_NAME">$1<ex>Background App</ex></ph> will launch at system startup and continue to run in the background even once you've closed all other <ph name="PRODUCT_NAME">$2<ex>Google Chrome</ex></ph> windows.
-+ </message>
-+ </messages>
-+ <structures fallback_to_english="true">
-+ <!-- Make sure these stay in sync with the structures in generated_resources.grd. -->
-+ <structure name="IDD_CHROME_FRAME_FIND_DIALOG" file="cf_resources.rc" type="dialog" >
-+ </structure>
-+ <structure name="IDD_CHROME_FRAME_READY_PROMPT" file="cf_resources.rc" type="dialog" >
-+ </structure>
-+ </structures>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/testdata/chrome_html.html b/tools/grit/grit/testdata/chrome_html.html
-new file mode 100644
-index 0000000000..7f7633c5cf
---- /dev/null
-+++ b/tools/grit/grit/testdata/chrome_html.html
-@@ -0,0 +1,6 @@
-+<include src="included_sample.html">
-+<style type="text/css">
-+#image {
-+ content: url('chrome://theme/IDR_SOME_FILE');
-+}
-+</style>
-diff --git a/tools/grit/grit/testdata/default_100_percent/a.png b/tools/grit/grit/testdata/default_100_percent/a.png
-new file mode 100644
-index 0000000000000000000000000000000000000000..5d5089038ca71172e95db9e7aae1e1fa5cebd505
-GIT binary patch
-literal 159
-zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>0wld=oSO}#(mY)pLnNjq|2Y3)zGGzYPN&L+
-zMSC}CcCfp=Dtxv4%6W%G#Q=|R|L;6pCCLUWO)Z<5eoL%TkDTw=s4X!^d(Qa<2khAN
-zZPy!XToBAic1Ss}vcWiD27B3&`Zj^H6CO>7R1{ToQ;=ggdEYbV=IISvfHpFCy85}S
-Ib4q9e0O9jEh5!Hn
-
-literal 0
-HcmV?d00001
-
-diff --git a/tools/grit/grit/testdata/default_100_percent/b.png b/tools/grit/grit/testdata/default_100_percent/b.png
-new file mode 100644
-index 0000000000..6178079822
---- /dev/null
-+++ b/tools/grit/grit/testdata/default_100_percent/b.png
-@@ -0,0 +1 @@
-+b
-diff --git a/tools/grit/grit/testdata/del_footer.html b/tools/grit/grit/testdata/del_footer.html
-new file mode 100644
-index 0000000000..4e19950bfc
---- /dev/null
-+++ b/tools/grit/grit/testdata/del_footer.html
-@@ -0,0 +1,8 @@
-+<table cellspacing=0 cellpadding=2 width="100%" border=0>
-+<tr bgcolor=#EFEFEF><td><font size=-1>&nbsp;<b>Remove</b> checked results and <b>return to search</b>.</font></td>
-+<td align=right><font size=-1><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">Uncheck all</a>&nbsp;&nbsp;</font></td>
-+<td align=right width=1% nowrap><font size=-1>
-+<input onclick=deleting() type=submit value="Remove checked results" name=submit2>
-+</font></td></tr></table>
-+<center><br><font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
-+</body></html>
-diff --git a/tools/grit/grit/testdata/del_header.html b/tools/grit/grit/testdata/del_header.html
-new file mode 100644
-index 0000000000..72bc6756eb
---- /dev/null
-+++ b/tools/grit/grit/testdata/del_header.html
-@@ -0,0 +1,60 @@
-+<body bgcolor="#ffffff" topmargin="2" marginheight="2">
-+<table cellSpacing="2" cellPadding="0" width="100%" border="0">
-+<form action='[$~DELETE~$]' method="post" name="delform">
-+<input name="redir" type="hidden" value="[REDIR]">
-+<script>
-+<!--
-+function deleting() {
-+f=document.getElementsByName("del");
-+var num = 0;
-+if (f.length)
-+ for(i=0;i<f.length; i++)
-+ if(f[i].checked) num++;
-+ if (num == 1) alert("One checked result has been removed");
-+ else if (num > 1) alert(num + " checked results have been removed");
-+ else alert("No results were checked, so no results have been removed");
-+}
-+function checkall(v) {
-+ f=document.getElementsByName("del");
-+ if (f.length)
-+ for(i=0;i<f.length; i++)
-+ f[i].checked=v;
-+}
-+//-->
-+</script>
-+<tr>
-+<td vAlign="top" width="1%"><A href='[$~HOMEPAGE~$]'> <img alt="Go to Google Desktop Search" width="150" height="55" src="/logo3.gif" border="0" vspace="12"></A></td>
-+<td>&nbsp;</td>
-+<td noWrap>
-+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
-+ <tr>
-+ <td bgColor="#DD0000"><img height="1" alt="" width="1"></td>
-+ </tr>
-+ </table>
-+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
-+ <tr>
-+ <td noWrap bgColor="#efefef"><font size="+1"><b>&nbsp;Remove Specific Items</b></font></td>
-+ <td noWrap align="right" bgColor="#efefef"><font size="-1"><a href="http://desktop.google.com/remove.html">Help</a>&nbsp;&nbsp;</font></td>
-+ </tr>
-+ </table>
-+</td>
-+</tr>
-+</table>
-+<table cellSpacing="0" cellPadding="2" width="100%" border="0">
-+<tr bgColor="#EFEFEF">
-+<td><font size="-1">&nbsp;<B>Remove</B> checked results and <B>return to search</B>.</font></td>
-+<td align="right"><font size="-1"><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">
-+Uncheck all</a>&nbsp;&nbsp;</font></td>
-+<td align="right" width="1%" nowrap><font size="-1"><input onclick="deleting()" type="submit" value="Remove checked results" name="submit2"></font></td>
-+</tr>
-+</table>
-+<br>
-+<table cellspacing="0" cellpadding="2" width="100%" border="0">
-+<tr>
-+<td colSpan="3" bgcolor="#FFFFFF" style="border:solid; border-width:1px; border-color:#DD0000"><font size="-1">&nbsp;<b>Remove
-+checked items from Google Desktop Search. Other copies of the same items will not be
-+affected.<br>
-+&nbsp;If you view the item again, it will be added back to Google Desktop Search.</b></font></td>
-+</tr>
-+</table>
-+<br>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/deleted.html b/tools/grit/grit/testdata/deleted.html
-new file mode 100644
-index 0000000000..5ae5f355fa
---- /dev/null
-+++ b/tools/grit/grit/testdata/deleted.html
-@@ -0,0 +1,21 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Database Deleted</title>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-+.q {COLOR: #0000cc}
-+</style>
-+</head>
-+<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
-+<center>
-+<TABLE cellSpacing=0 cellPadding=0 border=0>
-+<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a>
-+</td></tr></table><BR>
-+<center>The database has been deleted. Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
-+</td></tr>
-+</table>
-+<br><FONT size=-1>[$~BOTTOMLINE~$]</font></p>
-+<p><FONT size=-2>&copy;2005 Google</font></p></center></body></html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/depfile.grd b/tools/grit/grit/testdata/depfile.grd
-new file mode 100644
-index 0000000000..e2f7191218
---- /dev/null
-+++ b/tools/grit/grit/testdata/depfile.grd
-@@ -0,0 +1,18 @@
-+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-+<grit
-+ base_dir="."
-+ latest_public_release="0"
-+ current_release="1">
-+ <outputs>
-+ <output filename="default_100_percent.pak" lang="en" type="data_package" context="default_100_percent" />
-+ <output filename="special_100_percent.pak" lang="en" type="data_package" context="special_100_percent" />
-+ </outputs>
-+ <release seq="1">
-+ <structures fallback_to_low_resolution="true">
-+ <if expr="False">
-+ <part file="grit_part.grdp" />
-+ </if>
-+ <structure type="chrome_scaled_image" name="IDR_A" file="a.png" />
-+ </structures>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/testdata/details.html b/tools/grit/grit/testdata/details.html
-new file mode 100644
-index 0000000000..0ab0e2a90c
---- /dev/null
-+++ b/tools/grit/grit/testdata/details.html
-@@ -0,0 +1,10 @@
-+[!]
-+title Improve Google Desktop Search by Sending Non-Personal Information
-+template
-+bottomline
-+hp_image
-+
-+<p><strong>This documentation is not yet available</strong></p>
-+<center><br>
-+<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font>
-+</center>
-diff --git a/tools/grit/grit/testdata/duplicate-name-input.xml b/tools/grit/grit/testdata/duplicate-name-input.xml
-new file mode 100644
-index 0000000000..cc4d1d65c5
---- /dev/null
-+++ b/tools/grit/grit/testdata/duplicate-name-input.xml
-@@ -0,0 +1,26 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ </messages>
-+ <structures>
-+ <!-- Duplicate name here -->
-+ <structure type="version" name="IDS_GREETING" file="rc_files/bla.rc" />
-+ </structures>
-+ </release>
-+ <translations>
-+ <file path="figs_nl_translations.xml" />
-+ <file path="cjk_translations.xml" />
-+ </translations>
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="resource_en.rc" type="rc_all" lang="en-US" />
-+ <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
-+ <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
-+ <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
-+ <output filename="nontranslateable.rc" type="rc_nontranslateable" />
-+ </outputs>
-+</grit>
-diff --git a/tools/grit/grit/testdata/email_result.html b/tools/grit/grit/testdata/email_result.html
-new file mode 100644
-index 0000000000..8bb04b988c
---- /dev/null
-+++ b/tools/grit/grit/testdata/email_result.html
-@@ -0,0 +1,34 @@
-+[HEADER]
-+[CHROME]
-+<table border=0 cellpadding=2 cellspacing=2 width='100%'>
-+<tr><td><font size=-1>[CONV]
-+<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
-+</font></td></tr>
-+</table>
-+<blockquote id=gg_1>
-+<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
-+<img style="vertical-align:middle;" height=16 src='/email.gif' width=16> &nbsp; <b>[SUBJECT]</b>
-+<p><font size=-1>[FROM-DISP]
-+[TO-DISP]
-+[CC-DISP]
-+[BCC-DISP]
-+[REPLYTO-DISP]
-+[DATE-DISP]
-+[VIEW-DISP]
-+[$~ATTACH~$]
-+</font></td></tr></table>
-+<p class=g><span style="width:500;"><font size=-1><label>[MESSAGE]</label></span></p>
-+</font>
-+</blockquote>
-+<table border=0 cellpadding=2 cellspacing=2 width='100%'>
-+<tr><td><font size=-1>[CONV]
-+<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
-+</font></td></tr></table>
-+<style>
-+.hl { color:black; background-color:#ffff88}
-+</style>
-+<script>
-+[$~HIGHLIGHT_SCRIPT~$]
-+[ONLOAD]
-+</script>
-+[FOOTER]
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/email_thread.html b/tools/grit/grit/testdata/email_thread.html
-new file mode 100644
-index 0000000000..3c7279b841
---- /dev/null
-+++ b/tools/grit/grit/testdata/email_thread.html
-@@ -0,0 +1,10 @@
-+[HEADER]
-+[CHROME]
-+<blockquote [MAXWIDTH]>
-+<b><img src=email.gif style="vertical-align:middle;" width=16 height=16> &nbsp; [SUBJECT]</b><br><br>
-+<TABLE cellSpacing=0 cellPadding=3 border=0>
-+[CONTENTS]
-+</table>
-+</blockquote>
-+[NEXT_PREV]
-+[FOOTER]
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/error.html b/tools/grit/grit/testdata/error.html
-new file mode 100644
-index 0000000000..66875a234c
---- /dev/null
-+++ b/tools/grit/grit/testdata/error.html
-@@ -0,0 +1,8 @@
-+[HEADER]
-+[CHROME]
-+<br>
-+<blockquote>
-+[ERROR]<br><br>
-+If you think this is an error, please <a href="http://desktop.google.com/feedback.html?version=[VERSION]">contact us</a>.
-+</blockquote>
-+[FOOTER]
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/explicit_web.html b/tools/grit/grit/testdata/explicit_web.html
-new file mode 100644
-index 0000000000..1424adc617
---- /dev/null
-+++ b/tools/grit/grit/testdata/explicit_web.html
-@@ -0,0 +1,11 @@
-+[HEADER]
-+<style>
-+.image {BORDER: #0000cc 1px solid;}
-+.imageh {BORDER: #0000cc 1px solid;}
-+</style>
-+[WEB_TOP_CHROME]
-+[$~STATUS~$]
-+[$~MESSAGE~$]
-+[WEB_FILES]
-+<br>[NEXT_PREV]
-+[FOOTER]
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/footer.html b/tools/grit/grit/testdata/footer.html
-new file mode 100644
-index 0000000000..3372d6afac
---- /dev/null
-+++ b/tools/grit/grit/testdata/footer.html
-@@ -0,0 +1,14 @@
-+<center><br clear=all><br>
-+<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table>
-+<table cellspacing=0 cellpadding=0 width="100%" bgcolor=#e8f4f7 border=0>
-+<tr bgcolor=#e8f4f7>
-+<td><br>
-+<table cellpadding=1 align=center border=0 cellspacing=0 bgcolor=#e8f4f7>
-+<form action='[$~SEARCHURL~$]' method=get>
-+<tr><td noWrap>[$~BOTTOM~$]</td></tr></form>
-+</table><br>
-+</td></tr></table>
-+<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table><br>
-+<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
-+[SCRIPT]
-+</body></html>
-diff --git a/tools/grit/grit/testdata/generated_resources_fr.xtb b/tools/grit/grit/testdata/generated_resources_fr.xtb
-new file mode 100644
-index 0000000000..373c40feea
---- /dev/null
-+++ b/tools/grit/grit/testdata/generated_resources_fr.xtb
-@@ -0,0 +1,3079 @@
-+<?xml version="1.0" ?>
-+<!DOCTYPE translationbundle>
-+<translationbundle lang="fr">
-+<translation id="1525924600121678168">Salut!</translation>
-+<translation id="5335090254790956485">Salut <ph name="USERNAME"/></translation>
-+<translation id="6779164083355903755">Supprime&amp;r</translation>
-+<translation id="6879617193011158416">Activer la barre de favoris</translation>
-+<translation id="8130276680150879341">Déconnexion du réseau privé</translation>
-+<translation id="1058418043520174283"><ph name="INDEX"/> sur <ph name="COUNT"/></translation>
-+<translation id="4480627574828695486">Déconnecter ce compte...</translation>
-+<translation id="7040807039050164757">&amp;Vérifier l'orthographe dans ce champ</translation>
-+<translation id="778579833039460630">Aucune donnée reçue.</translation>
-+<translation id="1852799913675865625">Une erreur s'est produite lors de la tentative de lecture du fichier : <ph name="ERROR_TEXT"/>.</translation>
-+<translation id="3828924085048779000">Le mot de passe multiterme est obligatoire.</translation>
-+<translation id="8265562484034134517">Importer les données d'un autre navigateur...</translation>
-+<translation id="2709516037105925701">Saisie automatique</translation>
-+<translation id="4857138207355690859">API P2P</translation>
-+<translation id="250599269244456932">Exécuter automatiquement (recommandé)</translation>
-+<translation id="3581034179710640788">Le certificat de sécurité du site a expiré !</translation>
-+<translation id="2825758591930162672">Clé publique de l'objet</translation>
-+<translation id="8275038454117074363">Importer</translation>
-+<translation id="8418445294933751433">Afficher dan&amp;s un onglet</translation>
-+<translation id="6985276906761169321">ID :</translation>
-+<translation id="859285277496340001">Le certificat n'indique aucun mécanisme permettant de vérifier s'il a été révoqué.</translation>
-+<translation id="2010799328026760191">Touches de modification...</translation>
-+<translation id="3300394989536077382">Signé par :</translation>
-+<translation id="654233263479157500">Utiliser un service Web pour résoudre les erreurs de navigation</translation>
-+<translation id="4940047036413029306">Guillemet</translation>
-+<translation id="1526811905352917883">Une nouvelle tentative de connexion avec SSL 3.0 a dû être effectuée. Cette opération indique généralement que le serveur utilise un logiciel très ancien et qu'il est susceptible de présenter d'autres problèmes de sécurité.</translation>
-+<translation id="1497897566809397301">Autoriser le stockage des données locales (recommandé)</translation>
-+<translation id="3275778913554317645">Ouvrir dans une fenêtre</translation>
-+<translation id="4553117311324416101">Google pense qu'un logiciel malveillant pourrait être installé sur votre ordinateur si vous continuez. Nous vous conseillons de ne pas continuer, même si vous avez déjà consulté ce site auparavant ou si vous avez confiance en celui-ci. Il se peut qu'il ait été piraté récemment. Réessayez demain ou utilisez un autre site.</translation>
-+<translation id="509988127256758334">&amp;Rechercher :</translation>
-+<translation id="1420684932347524586">Échec de génération de clé privée RSA aléatoire</translation>
-+<translation id="2501173422421700905">Certificat en attente</translation>
-+<translation id="2313634973119803790">Technologie réseau :</translation>
-+<translation id="2382901536325590843">Le certificat du serveur ne figure pas dans le DNS.</translation>
-+<translation id="2833791489321462313">Demander le mot de passe au retour de veille</translation>
-+<translation id="3850258314292525915">Désactiver la synchronisation</translation>
-+<translation id="2721561274224027017">Base de données indexée</translation>
-+<translation id="8208216423136871611">Ne pas enregistrer</translation>
-+<translation id="684587995079587263"><ph name="PRODUCT_NAME"/> synchronise vos données avec votre compte Google en toute sécurité. Synchronisez toutes vos données ou personnalisez les types de données synchronisées et les options de chiffrement.</translation>
-+<translation id="4405141258442788789">Le délai imparti à l'opération est dépassé.</translation>
-+<translation id="5048179823246820836">Nordique</translation>
-+<translation id="1763046204212875858">Créer des raccourcis vers des applications</translation>
-+<translation id="2105006017282194539">Pas encore chargé</translation>
-+<translation id="524759338601046922">Confirmer le nouveau code PIN :</translation>
-+<translation id="688547603556380205">L2TP/IPSec + Certificat utilisateur</translation>
-+<translation id="777702478322588152">Préfecture</translation>
-+<translation id="6562437808764959486">Extraction de l'image de récupération...</translation>
-+<translation id="561349411957324076">Terminé</translation>
-+<translation id="4764776831041365478">Il se peut que la page Web à l'adresse <ph name="URL"/> soit temporairement inaccessible ou qu'elle ait été déplacée de façon permanente à une autre adresse Web.</translation>
-+<translation id="6156863943908443225">Cache des scripts</translation>
-+<translation id="4610656722473172270">Barre d'outils Google</translation>
-+<translation id="151501797353681931">Importés depuis Safari</translation>
-+<translation id="6706684875496318067">Le plug-in <ph name="PLUGIN_NAME"/> n'est pas autorisé.</translation>
-+<translation id="586567932979200359">Vous exécutez <ph name="PRODUCT_NAME"/> à partir de son image disque. Si vous l'installez sur votre ordinateur, vous pourrez l'utiliser sans image disque et bénéficierez de mises à jour automatiques.</translation>
-+<translation id="3775432569830822555">Certificat du serveur SSL</translation>
-+<translation id="1829192082282182671">Z&amp;oom arrière</translation>
-+<translation id="6102827823267795198">Indique si la suggestion du moteur de recherche doit être entrée immédiatement via la saisie semi-automatique lorsque la fonctionnalité Recherche instantanée est activée.</translation>
-+<translation id="1467071896935429871">Mise à jour du système : <ph name="PERCENT"/> % téléchargés</translation>
-+<translation id="7881267037441701396">Les informations d'identification associées au partage de vos imprimantes via <ph name="CLOUD_PRINT_NAME"/> sont arrivées à expiration. Cliquez ici pour saisir à nouveau votre nom d'utilisateur et votre mot de passe.</translation>
-+<translation id="816055135686411707">Erreur de définition du paramètre de confiance du certificat</translation>
-+<translation id="4714531393479055912"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe.</translation>
-+<translation id="5704565838965461712">Sélectionnez le certificat à présenter pour l'identification :</translation>
-+<translation id="2025632980034333559"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour actualiser l'extension.</translation>
-+<translation id="4059593000330943833">Compatibilité expérimentale avec des méthodes Wi-Fi Extensible Authentication Protocol supplémentaires, telles que EAP-TLS et LEAP.</translation>
-+<translation id="6322279351188361895">Échec de lecture de la clé privée</translation>
-+<translation id="3781072658385678636">Les plug-ins suivants ont été bloqués sur cette page :</translation>
-+<translation id="4428782877951507641">Configuration de la synchronisation</translation>
-+<translation id="3648460724479383440">Case d'option cochée</translation>
-+<translation id="4654488276758583406">Très petite</translation>
-+<translation id="6647228709620733774">URL de révocation de l'autorité de certification Netscape</translation>
-+<translation id="546411240573627095">Style de pavé numérique</translation>
-+<translation id="7663002797281767775">Active les feuilles de style CSS 3D et la composition graphique haute performance des pages Web via le processeur graphique.</translation>
-+<translation id="2972581237482394796">&amp;Rétablir</translation>
-+<translation id="5895138241574237353">Redémarrer</translation>
-+<translation id="1858072074757584559">La connexion n'est pas compressée.</translation>
-+<translation id="528468243742722775">Fin</translation>
-+<translation id="1723824996674794290">&amp;Nouvelle fenêtre</translation>
-+<translation id="1313405956111467313">Configuration automatique du proxy</translation>
-+<translation id="1589055389569595240">Afficher l'orthographe et la grammaire</translation>
-+<translation id="4364779374839574930">Aucune imprimante n'a été trouvée. Veuillez en installer une.</translation>
-+<translation id="7017587484910029005">Saisissez les caractères visibles dans l'image ci-dessous.</translation>
-+<translation id="9013589315497579992">Certificat d'authentification de client SSL incorrect</translation>
-+<translation id="8595062045771121608">Le certificat du serveur ou un certificat AC intermédiaire présenté au navigateur a été signé avec un algorithme de signature faible tel que RSA-MD2. D'après des études récentes menées par des informaticiens, les algorithmes de signature seraient plus faibles qu'on ne le pensait jusqu'alors. Aujourd'hui, ils sont très rarement utilisés par les sites Web jugés dignes de confiance. Ce certificat a peut-être été contrefait. Nous vous déconseillons vivement de continuer.</translation>
-+<translation id="8666632926482119393">Rechercher le précédent</translation>
-+<translation id="7567293639574541773">I&amp;nspecter l'élément</translation>
-+<translation id="8392896330146417149">État d'itinérance :</translation>
-+<translation id="6813971406343552491">&amp;Non</translation>
-+<translation id="36224234498066874">Effacer les données de navigation...</translation>
-+<translation id="3384773155383850738">Nombre maximal de suggestions</translation>
-+<translation id="8331498498435985864">L'accessibilité est désactivée.</translation>
-+<translation id="8530339740589765688">Sélectionner par domaine</translation>
-+<translation id="8677212948402625567">Tout réduire...</translation>
-+<translation id="7600965453749440009">Ne jamais traduire les pages rédigées en <ph name="LANGUAGE"/> </translation>
-+<translation id="3208703785962634733">Non confirmé</translation>
-+<translation id="6523841952727744497">Avant de vous connecter, démarrez une session en tant qu'invité afin d'activer le réseau <ph name="NETWORK_ID"/>.</translation>
-+<translation id="7450044767321666434">La gravure de l'image est terminée.</translation>
-+<translation id="2653266418988778031">Si vous supprimez le certificat d'une autorité de certification, votre navigateur ne fera plus confiance aux certificats émis par cette autorité de certification.</translation>
-+<translation id="298068999958468740">Synchronisez toutes les données de cet ordinateur ou sélectionnez celles que vous souhaitez synchroniser.</translation>
-+<translation id="5341849548509163798"><ph name="NUMBER_MANY"/> hours ago</translation>
-+<translation id="4422428420715047158">Domaine :</translation>
-+<translation id="3602290021589620013">Aperçu</translation>
-+<translation id="7516602544578411747">Associe chaque fenêtre du navigateur à un profil et ajoute une option de sélection des profils en haut à droite. Chaque profil possède ses propres favoris, extensions, applications, etc.</translation>
-+<translation id="7082055294850503883">Ignorer le verrouillage des majuscules et saisir des minuscules par défaut</translation>
-+<translation id="1800124151523561876">Aucune parole détectée</translation>
-+<translation id="7814266509351532385">Changer de moteur de recherche par défaut</translation>
-+<translation id="5376169624176189338">Cliquer pour revenir en arrière, maintenir pour voir l'historique</translation>
-+<translation id="6310545596129886942"><ph name="NUMBER_FEW"/> secondes restantes</translation>
-+<translation id="9181716872983600413">Unicode</translation>
-+<translation id="1383861834909034572">Ouverture à la fin du téléchargement</translation>
-+<translation id="5727728807527375859">Les extensions, les applications et les thèmes peuvent endommager votre ordinateur. Voulez-vous vraiment continuer ?</translation>
-+<translation id="3857272004253733895">Schéma du pinyin double</translation>
-+<translation id="1636842079139032947">Déconnecter ce compte...</translation>
-+<translation id="6721972322305477112">&amp;Fichier</translation>
-+<translation id="1076818208934827215">Microsoft Internet Explorer</translation>
-+<translation id="9056810968620647706">Aucune correspondance trouvée</translation>
-+<translation id="1901494098092085382">État de votre commentaire</translation>
-+<translation id="2861301611394761800">Mise à jour terminée. Veuillez redémarrer le système.</translation>
-+<translation id="2231238007119540260">Lorsque vous supprimez un certificat de serveur, vous rétablissez les contrôles de sécurité habituels du serveur et un certificat valide lui est demandé.</translation>
-+<translation id="5463582782056205887">Essayez d'ajouter
-+ <ph name="PRODUCT_NAME"/>
-+ aux programmes autorisés dans les paramètres de votre pare-feu ou de votre antivirus. S'il
-+ est déjà autorisé, tentez de le supprimer de la liste et de l'ajouter à nouveau à
-+ la liste des programmes autorisés.</translation>
-+<translation id="7624154074265342755">Réseaux sans fil</translation>
-+<translation id="3315158641124845231">Masquer <ph name="PRODUCT_NAME"/></translation>
-+<translation id="3496213124478423963">Zoom arrière</translation>
-+<translation id="2296019197782308739">Méthode EAP :</translation>
-+<translation id="42981349822642051">Développer</translation>
-+<translation id="4013794286379809233">Veuillez vous connecter</translation>
-+<translation id="7693221960936265065">de n'importe quand</translation>
-+<translation id="1763138995382273070">Désactiver la validation des formulaires interactifs HTML5</translation>
-+<translation id="4920887663447894854">Le suivi de votre position géographique sur cette page a été bloqué pour les sites suivants :</translation>
-+<translation id="7690346658388844119">La gravure de l'image a été interrompue.</translation>
-+<translation id="8133676275609324831">&amp;Afficher dans le dossier</translation>
-+<translation id="645705751491738698">Continuer à bloquer JavaScript</translation>
-+<translation id="4780321648949301421">Enregistrer la page sous...</translation>
-+<translation id="9154072353677278078">Le serveur <ph name="DOMAIN"/> à l'adresse <ph name="REALM"/> requiert un nom d'utilisateur et un mot de passe.</translation>
-+<translation id="2551191967044410069">Exceptions de géolocalisation</translation>
-+<translation id="4092066334306401966">13px</translation>
-+<translation id="8178665534778830238">Contenu :</translation>
-+<translation id="153384433402665971">Le plug-in <ph name="PLUGIN_NAME"/> a été bloqué, car il n'est plus à jour.</translation>
-+<translation id="2610260699262139870">Taille ré&amp;elle</translation>
-+<translation id="4535734014498033861">Échec de la connexion au serveur proxy.</translation>
-+<translation id="558170650521898289">Vérification de pilote matériel Microsoft Windows</translation>
-+<translation id="98515147261107953">Paysage</translation>
-+<translation id="8974161578568356045">Détecter automatiquement</translation>
-+<translation id="1818606096021558659">Page</translation>
-+<translation id="5388588172257446328">Nom d'utilisateur :</translation>
-+<translation id="1657406563541664238">Nous aider à améliorer <ph name="PRODUCT_NAME"/> en envoyant automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
-+<translation id="7982789257301363584">Réseau</translation>
-+<translation id="8528962588711550376">Connexion en cours</translation>
-+<translation id="2336228925368920074">Ajouter tous les onglets aux favoris...</translation>
-+<translation id="4985312428111449076">Onglets ou fenêtres</translation>
-+<translation id="7481475534986701730">Sites récemment consultés</translation>
-+<translation id="4260722247480053581">Ouvrir dans une fenêtre de navigation privée</translation>
-+<translation id="8503758797520866434">Préférences de saisie automatique...</translation>
-+<translation id="2757031529886297178">Compteur d'images par seconde</translation>
-+<translation id="6657585470893396449">Mot de passe</translation>
-+<translation id="7881483672146086348">Afficher le compte</translation>
-+<translation id="1776883657531386793"><ph name="OID"/> : <ph name="INFO"/></translation>
-+<translation id="1510030919967934016">Le suivi de votre position géographique a été bloqué pour cette page.</translation>
-+<translation id="4640525840053037973">Connexion à l'aide de votre compte Google</translation>
-+<translation id="5255315797444241226">Le mot de passe multiterme entré est incorrect.</translation>
-+<translation id="6242054993434749861">télécopie : #<ph name="FAX"/></translation>
-+<translation id="762917759028004464">Le navigateur par défaut est actuellement <ph name="BROWSER_NAME"/>.</translation>
-+<translation id="9213479837033539041"><ph name="NUMBER_MANY"/> secondes restantes</translation>
-+<translation id="300544934591011246">Mot de passe précédent</translation>
-+<translation id="5078796286268621944">Code PIN incorrect</translation>
-+<translation id="989988560359834682">Modifier l'adresse</translation>
-+<translation id="8487678622945914333">Zoom avant</translation>
-+<translation id="2972557485845626008">Micrologiciel</translation>
-+<translation id="735327918767574393">Une erreur s'est produite lors de l'affichage de cette page Web. Pour continuer, actualisez cette page ou ouvrez-en une autre.</translation>
-+<translation id="8028060951694135607">Récupération de clé Microsoft</translation>
-+<translation id="9187657844611842955">recto verso</translation>
-+<translation id="6391832066170725637">Fichier ou répertoire introuvable</translation>
-+<translation id="4694445829210540512">Aucun forfait de données <ph name="NETWORK"/> actif</translation>
-+<translation id="5494920125229734069">Tout sélectionner</translation>
-+<translation id="2857834222104759979">Le fichier manifeste est incorrect.</translation>
-+<translation id="7931071620596053769">Les pages suivantes ne répondent plus. Vous pouvez attendre qu'elles soient de nouveau accessibles ou les supprimer.</translation>
-+<translation id="1209866192426315618"><ph name="NUMBER_DEFAULT"/> minutes restantes</translation>
-+<translation id="7938958445268990899">Le certificat du serveur n'est pas encore valide.</translation>
-+<translation id="4569998400745857585">Menu contenant des extensions masquées</translation>
-+<translation id="4081383687659939437">Enregistrer les infos</translation>
-+<translation id="5786805320574273267">Configuration de l'accès à distance à cet ordinateur.</translation>
-+<translation id="1801827354178857021">Point</translation>
-+<translation id="2179052183774520942">Ajouter un moteur de recherche</translation>
-+<translation id="5498951625591520696">Impossible d'atteindre le serveur.</translation>
-+<translation id="2956948609882871496">Importer mes favoris...</translation>
-+<translation id="1621207256975573490">Enregistrer le &amp;cadre sous...</translation>
-+<translation id="4681260323810445443">Vous n'êtes pas autorisé à accéder à la page Web <ph name="URL"/>. Votre connexion peut être requise.</translation>
-+<translation id="2176444992480806665">Envoyer la capture d'écran du dernier onglet actif</translation>
-+<translation id="1165039591588034296">Erreur</translation>
-+<translation id="2064942105849061141">Utiliser le thème GTK+</translation>
-+<translation id="2278562042389100163">Ouvrir une fenêtre du navigateur</translation>
-+<translation id="5246282308050205996"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour redémarrer l'application.</translation>
-+<translation id="9218430445555521422">Définir comme navigateur par défaut</translation>
-+<translation id="5027550639139316293">Certificat de courrier électronique</translation>
-+<translation id="938582441709398163">Clavier en superposition</translation>
-+<translation id="427208986916971462">La connexion est compressée avec <ph name="COMPRESSION"/>.</translation>
-+<translation id="4589279373639964403">Exporter mes favoris...</translation>
-+<translation id="8876215549894133151">Format :</translation>
-+<translation id="5234764350956374838">Ignorer</translation>
-+<translation id="40027638859996362">Déplacer un mot</translation>
-+<translation id="5463275305984126951">Index de <ph name="LOCATION"/></translation>
-+<translation id="5154917547274118687">Mémoire</translation>
-+<translation id="1493492096534259649">Impossible d'utiliser cette langue pour corriger l'orthographe.</translation>
-+<translation id="6628463337424475685">Recherche <ph name="ENGINE"/></translation>
-+<translation id="2502105862509471425">Ajouter une autre carte de paiement...</translation>
-+<translation id="4037618776454394829">Envoyer la dernière capture d'écran enregistrée</translation>
-+<translation id="8987670145726065238">Ce fichier contient du code malveillant. Voulez-vous vraiment continuer ?</translation>
-+<translation id="182729337634291014">Erreur de synchronisation...</translation>
-+<translation id="4465830120256509958">Clavier brésilien</translation>
-+<translation id="2459861677908225199">Utiliser TLS 1.0</translation>
-+<translation id="4792711294155034829">&amp;Signaler un problème...</translation>
-+<translation id="5819484510464120153">Créer des raccourci&amp;s vers des applications...</translation>
-+<translation id="6845180713465955339">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; a été émis par :</translation>
-+<translation id="7531238562312180404"><ph name="PRODUCT_NAME"/> ne contrôlant pas la façon dont les extensions gèrent vos données personnelles, toutes les extensions sont désactivées dans les fenêtres de navigation privée. Vous pouvez les réactiver individuellement dans le <ph name="BEGIN_LINK"/>gestionnaire des extensions<ph name="END_LINK"/>.</translation>
-+<translation id="5667293444945855280">Logiciels malveillants</translation>
-+<translation id="3435845180011337502">Mise en page ou mise en forme de la page</translation>
-+<translation id="3838186299160040975">Acheter davantage...</translation>
-+<translation id="6831043979455480757">Traduire</translation>
-+<translation id="3587482841069643663">Tout</translation>
-+<translation id="6698381487523150993">Créé :</translation>
-+<translation id="4684748086689879921">Annuler l'importation</translation>
-+<translation id="9130015405878219958">Le mode indiqué est incorrect.</translation>
-+<translation id="6615807189585243369"><ph name="BURNT_AMOUNT"/> copié(s) sur <ph name="TOTAL_SIZE"/></translation>
-+<translation id="8518425453349204360">L'accès à distance à cet ordinateur est activé pour <ph name="USER_EMAIL_ADDRESS"/>.</translation>
-+<translation id="4950138595962845479">Options...</translation>
-+<translation id="4653235815000740718">Un problème est survenu lors de la création du support de récupération du système d'exploitation. Le périphérique de stockage utilisé est introuvable.</translation>
-+<translation id="5516565854418269276">Toujours &amp;afficher la barre de favoris</translation>
-+<translation id="6426222199977479699">Erreur SSL</translation>
-+<translation id="7104784605502674932">Confirmer les préférences de synchronisation</translation>
-+<translation id="1788636309517085411">Utiliser les valeurs par défaut</translation>
-+<translation id="1661867754829461514">Code secret manquant</translation>
-+<translation id="7406714851119047430">L'accès à distance à cet ordinateur est désactivé.</translation>
-+<translation id="8589311641140863898">API des extensions expérimentales</translation>
-+<translation id="2804922931795102237">Inclure les informations système</translation>
-+<translation id="869891660844655955">Date d'expiration</translation>
-+<translation id="2178614541317717477">Autorité de certification compromise</translation>
-+<translation id="4449935293120761385">À propos de la saisie automatique</translation>
-+<translation id="4194570336751258953">Activer la fonction &quot;Taper pour cliquer&quot;</translation>
-+<translation id="6066742401428748382">Accès à la page Web refusé</translation>
-+<translation id="5111692334209731439">&amp;Gestionnaire de favoris</translation>
-+<translation id="8295070100601117548">Erreur serveur</translation>
-+<translation id="5661272705528507004">Cette carte SIM est désactivée et ne peut être utilisée. Veuillez demander à votre fournisseur de services de la remplacer.</translation>
-+<translation id="443008484043213881">Outils</translation>
-+<translation id="2529657954821696995">Clavier néerlandais</translation>
-+<translation id="1128128132059598906">EAP-TTLS</translation>
-+<translation id="6585234750898046415">Choisissez une image à associer à votre compte. Celle-ci s'affichera sur l'écran de connexion.</translation>
-+<translation id="7957054228628133943">Configurer le blocage des fenêtres pop-up...</translation>
-+<translation id="179767530217573436">des 4 dernières semaines</translation>
-+<translation id="2279770628980885996">Une situation inattendue s'est produite tandis que le serveur tentait de traiter la demande.</translation>
-+<translation id="8079135502601738761">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous l'ouvrir dans Adobe Reader ?</translation>
-+<translation id="9123413579398459698">Proxy FTP</translation>
-+<translation id="3887875461425980041">Si vous utilisez la version PPAPI de Flash, exécutez-la dans chaque processus de moteur du rendu plutôt que dans un processus de plug-in dédié.</translation>
-+<translation id="8534801226027872331">Cela signifie que le certificat présenté à votre navigateur contient des erreurs et qu'il ne peut pas être compris. Il est possible que les informations sur l'identité du certificat ou que d'autres informations du certificat relatives à la sécurité de la connexion soient incompréhensibles. Ne poursuivez pas.</translation>
-+<translation id="3608527593787258723">Activer l'onglet 1</translation>
-+<translation id="4497369307931735818">Communication à distance</translation>
-+<translation id="3855676282923585394">Importer les favoris et les paramètres...</translation>
-+<translation id="1116694919640316211">À propos</translation>
-+<translation id="4422347585044846479">Modifier le favori de cette page</translation>
-+<translation id="1684638090259711957">Ajouter un format d'exception</translation>
-+<translation id="4925481733100738363">Configurer l'accès à distance...</translation>
-+<translation id="1880905663253319515">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; ?</translation>
-+<translation id="8546306075665861288">Cache des images</translation>
-+<translation id="5904093760909470684">Configuration du proxy</translation>
-+<translation id="2874027208508018603">En l'absence de connexion Wi-Fi, Google Chrome utilise les données 3G.</translation>
-+<translation id="4558734465070698159">Appuyez sur <ph name="HOTKEY_NAME"/> pour sélectionner le mode de saisie précédent.</translation>
-+<translation id="3348643303702027858">La création du support de récupération du système d'exploitation a été annulée.</translation>
-+<translation id="3391060940042023865">Le plug-in suivant est bloqué : <ph name="PLUGIN_NAME"/></translation>
-+<translation id="4237016987259239829">Erreur de connexion réseau</translation>
-+<translation id="9050666287014529139">Mot de passe multiterme</translation>
-+<translation id="5197255632782567636">Internet</translation>
-+<translation id="4755860829306298968">Configurer les paramètres de blocage des plug-ins...</translation>
-+<translation id="8879284080359814990">Afficher dan&amp;s un onglet</translation>
-+<translation id="2786847742169026523">Synchroniser vos mots de passe</translation>
-+<translation id="41293960377217290">Le serveur proxy agit comme un intermédiaire entre votre ordinateur et les autres serveurs. Votre configuration système utilise actuellement un proxy, mais
-+ <ph name="PRODUCT_NAME"/>
-+ ne parvient pas à s'y connecter.</translation>
-+<translation id="4520722934040288962">Sélectionner par type d'application</translation>
-+<translation id="3873139305050062481">Procéder à l'i&amp;nspection de l'élément</translation>
-+<translation id="7445762425076701745">Impossible de valider entièrement l'identité du serveur auquel vous êtes connecté. Le nom utilisé pour cette connexion n'est valide que sur votre réseau et aucune autorité de certification externe ne peut en vérifier la propriété. Certaines autorités de certification délivrent tout de même des certificats pour ces types de nom, par conséquent nous ne sommes pas en mesure de vérifier que vous êtes connecté au site voulu et non à un site malveillant.</translation>
-+<translation id="1556537182262721003">Impossible de déplacer le répertoire d'extensions dans le profil.</translation>
-+<translation id="5866557323934807206">Supprimer ces paramètres pour les prochaines visites</translation>
-+<translation id="6506104645588011859">L'accessibilité est activée.</translation>
-+<translation id="5355351445385646029">Appuyer sur la touche Espace pour sélectionner la suggestion</translation>
-+<translation id="6978622699095559061">Vos favoris</translation>
-+<translation id="6370820475163108109"><ph name="ORGANIZATION_NAME"/> (<ph name="DOMAIN_NAME"/>)</translation>
-+<translation id="5453029940327926427">Fermer les onglets</translation>
-+<translation id="406070391919917862">Applications en arrière-plan</translation>
-+<translation id="8820817407110198400">Favoris</translation>
-+<translation id="3214837514330816581">Supprimer les données synchronisées de Google Dashboard</translation>
-+<translation id="2580170710466019930">Veuillez patienter pendant que <ph name="PRODUCT_NAME"/> installe les dernières mises à jour système.</translation>
-+<translation id="7428061718435085649">Utilisez les touches Maj gauche et droite pour sélectionner les 2e et 3e propositions</translation>
-+<translation id="1070066693520972135">WEP</translation>
-+<translation id="206683469794463668">Mode Zhuyin complet. La sélection automatique de la suggestion et les options associées sont désactivées ou ignorées.</translation>
-+<translation id="5191625995327478163">&amp;Paramètres linguistiques...</translation>
-+<translation id="8833054222610756741">CRX-less Web Apps</translation>
-+<translation id="4031729365043810780">Connexion au réseau</translation>
-+<translation id="3332115613788466465">Reliure bord long</translation>
-+<translation id="1985136186573666099"><ph name="PRODUCT_NAME"/> utilise les paramètres proxy du système pour se connecter au réseau.</translation>
-+<translation id="6508261954199872201">Application : <ph name="APP_NAME"/></translation>
-+<translation id="5585645215698205895">&amp;Descendre</translation>
-+<translation id="8366757838691703947">? Toutes les données présentes sur le périphérique seront supprimées.</translation>
-+<translation id="6596816719288285829">Adresse IP</translation>
-+<translation id="7747704580171477003">Active le nouveau design de la page &quot;Nouvel onglet&quot; (en cours de développement).</translation>
-+<translation id="4508265954913339219">Échec de l'activation</translation>
-+<translation id="8656768832129462377">Ne pas vérifier</translation>
-+<translation id="715487527529576698">Le chinois simplifié est le mode de saisie initial</translation>
-+<translation id="1674989413181946727">Paramètres SSL sur tout l'ordinateur :</translation>
-+<translation id="8703575177326907206">Votre connexion à <ph name="DOMAIN"/> n'est pas chiffrée.</translation>
-+<translation id="8472623782143987204">matériel requis</translation>
-+<translation id="4865571580044923428">Gérer les exceptions...</translation>
-+<translation id="2526619973349913024">Rechercher des mises à jour</translation>
-+<translation id="3874070094967379652">Utiliser un mot de passe multiterme pour chiffrer mes données de synchronisation</translation>
-+<translation id="4864369630010738180">Connexion en cours...</translation>
-+<translation id="6500116422101723010">Le serveur ne parvient pas à traiter la demande pour le moment. Ce code indique une situation temporaire. Le serveur sera de nouveau opérationnel ultérieurement.</translation>
-+<translation id="1644574205037202324">Historique</translation>
-+<translation id="1297175357211070620">Destination</translation>
-+<translation id="6219983382864672018">Web audio</translation>
-+<translation id="479280082949089240">Cookies placés par cette page</translation>
-+<translation id="4198861010405014042">Accès partagé</translation>
-+<translation id="6204930791202015665">Afficher...</translation>
-+<translation id="5941343993301164315">Veuillez vous connecter à <ph name="TOKEN_NAME"/>.</translation>
-+<translation id="4417229845571722044">Ajouter un nouvel e-mail</translation>
-+<translation id="8049151370369915255">Personnaliser les polices...</translation>
-+<translation id="2886862922374605295">Matériel :</translation>
-+<translation id="4497097279402334319">Erreur de connexion au réseau.</translation>
-+<translation id="5303618139271450299">Cette page Web est introuvable.</translation>
-+<translation id="4256316378292851214">En&amp;registrer la vidéo sous...</translation>
-+<translation id="3528171143076753409">Le certificat du serveur n'est pas approuvé.</translation>
-+<translation id="6518014396551869914">Cop&amp;ier l'image</translation>
-+<translation id="3236997602556743698">Sebeol-sik 390</translation>
-+<translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation>
-+<translation id="289426338439836048">Autre réseau mobile...</translation>
-+<translation id="3986287159189541211">Erreur HTTP <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
-+<translation id="3225319735946384299">Signature du code</translation>
-+<translation id="3118319026408854581">Aide <ph name="PRODUCT_NAME"/></translation>
-+<translation id="2422426094670600218">&lt;sans nom&gt;</translation>
-+<translation id="2012766523151663935">Version du micrologiciel :</translation>
-+<translation id="4120898696391891645">La page ne se charge pas</translation>
-+<translation id="6060685159320643512">Attention, ces fonctionnalités expérimentales peuvent mordre.</translation>
-+<translation id="5829990587040054282">Verrouiller l'écran ou éteindre</translation>
-+<translation id="7800304661137206267">La connexion est chiffrée au moyen de <ph name="CIPHER"/>, avec <ph name="MAC"/> pour l'authentification des messages et <ph name="KX"/> pour la méthode d'échange de clés.</translation>
-+<translation id="7706319470528945664">Clavier portugais</translation>
-+<translation id="5584537427775243893">Importation</translation>
-+<translation id="9128870381267983090">Connexion au réseau</translation>
-+<translation id="4181841719683918333">Langues</translation>
-+<translation id="6535131196824081346">Cette erreur peut se produire lors de la connexion à un serveur sécurisé (HTTPS).
-+ Elle indique que le serveur tente d'établir une connexion sécurisée, mais
-+ que celle-ci ne sera pas du tout sécurisée en raison d'une grave erreur de configuration.
-+ <ph name="LINE_BREAK"/> Dans ce cas, une intervention
-+ est requise sur le serveur.
-+ <ph name="PRODUCT_NAME"/>
-+ n'utilise pas de connexion non sécurisée pour protéger la confidentialité
-+ de vos données.</translation>
-+<translation id="5235889404533735074">La synchronisation de <ph name="PRODUCT_NAME"/> vous permet de partager vos données (favoris, préférences) sur vos ordinateurs en toute simplicité. Pour ce faire, <ph name="PRODUCT_NAME"/> enregistre vos données en ligne via Google lorsque vous vous connectez à votre compte.</translation>
-+<translation id="6533668113756472185">Format ou mise en forme de la page</translation>
-+<translation id="5640179856859982418">Clavier suisse</translation>
-+<translation id="5910363049092958439">En&amp;registrer l'image sous...</translation>
-+<translation id="1363055550067308502">Basculer en mode pleine chasse ou demi-chasse</translation>
-+<translation id="3108967419958202225">Sélectionner...</translation>
-+<translation id="6451650035642342749">Effacer les paramètres d'ouverture automatique</translation>
-+<translation id="5948544841277865110">Ajouter un réseau privé</translation>
-+<translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secondes</translation>
-+<translation id="1378451347523657898">Ne pas envoyer de capture d'écran</translation>
-+<translation id="5098629044894065541">Hébreu</translation>
-+<translation id="7751559664766943798">Toujours afficher la barre de favoris</translation>
-+<translation id="5098647635849512368">Impossible de trouver le chemin d'accès absolu du répertoire à empaqueter.</translation>
-+<translation id="780617032715125782">Créer un profil</translation>
-+<translation id="933712198907837967">Diners Club</translation>
-+<translation id="6380224340023442078">Paramètres de contenu...</translation>
-+<translation id="950108145290971791">Activer la recherche instantanée pour accélérer la recherche et la navigation ?</translation>
-+<translation id="144136026008224475">Plus d'extensions &gt;&gt;</translation>
-+<translation id="5486326529110362464">La valeur d'entrée de la clé privée est obligatoire.</translation>
-+<translation id="9039663905644212491">PEAP</translation>
-+<translation id="62780591024586043">Fonctionnalités de localisation expérimentales</translation>
-+<translation id="8584280235376696778">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
-+<translation id="2845382757467349449">Toujours afficher la barre de favoris</translation>
-+<translation id="2516384155283419848">Reliure</translation>
-+<translation id="3053013834507634016">Utilisation de la clé du certificat</translation>
-+<translation id="4487088045714738411">Clavier belge</translation>
-+<translation id="7511635910912978956"><ph name="NUMBER_FEW"/> heures restantes</translation>
-+<translation id="2152580633399033274">Afficher toutes les images (recommandé)</translation>
-+<translation id="7894567402659809897">Cliquez sur
-+ <ph name="BEGIN_BOLD"/>Démarrer<ph name="END_BOLD"/>,
-+ puis sur
-+ <ph name="BEGIN_BOLD"/>Exécuter<ph name="END_BOLD"/>.
-+ Saisissez
-+ et cliquez sur
-+ <ph name="BEGIN_BOLD"/>OK<ph name="END_BOLD"/>.</translation>
-+<translation id="2934952234745269935">Nom de volume</translation>
-+<translation id="7960533875494434480">Reliure bord court</translation>
-+<translation id="6431347207794742960"><ph name="PRODUCT_NAME"/> va configurer les mises à jour automatiques pour tous les utilisateurs de cet ordinateur.</translation>
-+<translation id="4973698491777102067">Effacer les éléments datant :</translation>
-+<translation id="6074963268421707432">Interdire à tous les sites d'afficher des notifications sur le Bureau</translation>
-+<translation id="8508050303181238566">Appuyez sur <ph name="HOTKEY_NAME"/> pour passer d'un mode de saisie à l'autre.</translation>
-+<translation id="6273404661268779365">Ajouter un nouveau fax</translation>
-+<translation id="1995173078718234136">Recherche de contenu en cours...</translation>
-+<translation id="4735819417216076266">Style d'entrée avec Espace</translation>
-+<translation id="2977095037388048586">Vous avez tenté d'accéder à <ph name="DOMAIN"/>, mais, au lieu de cela, vous communiquez actuellement avec un serveur identifié comme <ph name="DOMAIN2"/>. Cela est peut-être dû à un défaut de configuration du serveur ou à quelque chose de plus grave. Un pirate informatique sur votre réseau cherche peut-être à vous faire visiter une version falsifiée de <ph name="DOMAIN3"/>, donc potentiellement préjudiciable. Nous vous déconseillons vivement de continuer.</translation>
-+<translation id="220138918934036434">Masquer le bouton</translation>
-+<translation id="5374359983950678924">Modifier l'image</translation>
-+<translation id="5158548125608505876">Ne pas synchroniser mes mots de passe</translation>
-+<translation id="2167276631610992935">JavaScript</translation>
-+<translation id="6974306300279582256">Activer les notifications de <ph name="SITE"/></translation>
-+<translation id="492914099844938733">Afficher les incompatibilités</translation>
-+<translation id="5233638681132016545">Nouvel onglet</translation>
-+<translation id="6567688344210276845">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action de page.</translation>
-+<translation id="5210365745912300556">Fermer l'onglet</translation>
-+<translation id="8628085465172583869">Nom d'hôte du serveur :</translation>
-+<translation id="498765271601821113">Ajouter une carte de paiement</translation>
-+<translation id="7694379099184430148"><ph name="FILENAME"/> : type de fichier inconnu</translation>
-+<translation id="1992397118740194946">Non défini</translation>
-+<translation id="7966826846893205925">Gérer les paramètres de saisie automatique...</translation>
-+<translation id="8556732995053816225">Respecter la &amp;casse</translation>
-+<translation id="3314070176311241517">Autoriser tous les sites à exécuter JavaScript (recommandé)</translation>
-+<translation id="2406911946387278693">Gérer vos périphériques depuis le cloud</translation>
-+<translation id="7419631653042041064">Clavier catalan</translation>
-+<translation id="5710740561465385694">Me demander lorsqu'un site essaie de stocker des données</translation>
-+<translation id="3897092660631435901">Menu</translation>
-+<translation id="7024867552176634416">Sélectionnez le périphérique de stockage amovible à utiliser.</translation>
-+<translation id="8553075262323480129">La traduction a échoué, car nous n'avons pas pu déterminer la langue de la page.</translation>
-+<translation id="5910680277043747137">Vous pouvez créer des profils supplémentaires pour autoriser plusieurs personnes à utiliser et personnaliser Google Chrome.</translation>
-+<translation id="4381849418013903196">Deux-points</translation>
-+<translation id="1103523840287552314">Toujours traduire en <ph name="LANGUAGE"/></translation>
-+<translation id="2263497240924215535">(désactivée)</translation>
-+<translation id="2159087636560291862">Cela signifie que le certificat n'a pas été vérifié par un tiers reconnu par votre ordinateur. N'importe qui peut émettre un certificat en se faisant passer pour un autre site Web. Ce certificat doit donc être vérifié par un tiers approuvé. Sans cette vérification, les informations sur l'identité du certificat sont sans intérêt. Par conséquent, il nous est impossible de vérifier que vous communiquez bien avec <ph name="DOMAIN"/> et non avec un pirate informatique ayant émis son propre certificat en prétendant être <ph name="DOMAIN2"/>. Nous vous déconseillons vivement de continuer.</translation>
-+<translation id="58625595078799656"><ph name="PRODUCT_NAME"/> requiert que vous cryptiez vos données à l'aide de votre mot de passe Google ou de votre propre mot de passe multiterme.</translation>
-+<translation id="8017335670460187064"><ph name="LABEL"/></translation>
-+<translation id="6840184929775541289">N'est pas une autorité de certification</translation>
-+<translation id="6099520380851856040">Date et heure : <ph name="CRASH_TIME"/></translation>
-+<translation id="144518587530125858">Impossible de charger &quot;<ph name="IMAGE_PATH"/>&quot; pour le thème.</translation>
-+<translation id="5355097969896547230">Rechercher à nouveau</translation>
-+<translation id="7925285046818567682">En attente de <ph name="HOST_NAME"/>...</translation>
-+<translation id="2553440850688409052">Masquer ce plug-in</translation>
-+<translation id="3280237271814976245">Enregistrer &amp;sous...</translation>
-+<translation id="8301162128839682420">Ajouter une langue :</translation>
-+<translation id="7658239707568436148">Annuler</translation>
-+<translation id="8695825812785969222">Ouvrir une &amp;adresse...</translation>
-+<translation id="4538417792467843292">Supprimer le mot</translation>
-+<translation id="8412392972487953978">Vous devez saisir deux fois le même mot de passe multiterme.</translation>
-+<translation id="9121814364785106365">Ouvrir dans un onglet épinglé</translation>
-+<translation id="6996264303975215450">Page Web, tout type de contenu</translation>
-+<translation id="3435896845095436175">Activer</translation>
-+<translation id="1891668193654680795">Considérer ce certificat comme fiable pour identifier les développeurs de logiciels.</translation>
-+<translation id="5078638979202084724">Ajouter tous les onglets aux favoris</translation>
-+<translation id="5585118885427931890">Impossible de créer le dossier de favoris.</translation>
-+<translation id="2154710561487035718">Copier l'URL</translation>
-+<translation id="8163672774605900272">Si vous pensez ne pas avoir à utiliser de serveur proxy, procédez comme suit :
-+ <ph name="PLATFORM_TEXT"/></translation>
-+<translation id="5510687173983454382">Définir les utilisateurs autorisés à se connecter à un périphérique et autoriser les sessions de navigation en tant qu'invité</translation>
-+<translation id="3241680850019875542">Sélectionnez le répertoire racine de l'extension à empaqueter. Pour mettre à jour une extension, sélectionnez également le fichier de clé privée à réutiliser.</translation>
-+<translation id="7500424997253660722">Pool restreint :</translation>
-+<translation id="657402800789773160">&amp;Rafraîchir cette page</translation>
-+<translation id="6163363155248589649">&amp;Normal</translation>
-+<translation id="7972714317346275248">PKCS #1 SHA-384 avec chiffrement RSA</translation>
-+<translation id="3020990233660977256">Numéro de série : <ph name="SERIAL_NUMBER"/></translation>
-+<translation id="8426519927982004547">HTTPS/SSL</translation>
-+<translation id="8216781342946147825">Toutes les données de votre ordinateur et des sites Web que vous visitez</translation>
-+<translation id="5548207786079516019">Ceci est une installation secondaire de <ph name="PRODUCT_NAME"/> et ce dernier ne peut pas être défini comme navigateur par défaut.</translation>
-+<translation id="3984413272403535372">Erreur lors de la signature de l'extension</translation>
-+<translation id="8807083958935897582"><ph name="PRODUCT_NAME"/> permet d'effectuer des recherches sur Internet à l'aide du champ polyvalent. Sélectionnez le moteur de recherche à utiliser :</translation>
-+<translation id="6629104427484407292">Sécurité : <ph name="SECURITY"/></translation>
-+<translation id="9208886416788010685">Adobe Reader n'est pas à jour</translation>
-+<translation id="3373604799988099680">Extensions ou applications</translation>
-+<translation id="318408932946428277">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
-+<translation id="314141447227043789">Téléchargement de l'image terminé.</translation>
-+<translation id="8725178340343806893">Favoris</translation>
-+<translation id="5177526793333269655">Afficher les vignettes</translation>
-+<translation id="8926389886865778422">Ne plus afficher ce message</translation>
-+<translation id="6985235333261347343">Agent de récupération de clé Microsoft</translation>
-+<translation id="3605499851022050619">Page de diagnostic de navigation sécurisée</translation>
-+<translation id="4417271111203525803">Adresse ligne 2</translation>
-+<translation id="7617095560120859490">Décrivez-nous le problème recontré. (Champ obligatoire)</translation>
-+<translation id="5618333180342767515">Cela peut prendre quelques minutes.</translation>
-+<translation id="4307992518367153382">Options de base</translation>
-+<translation id="8480417584335382321">Niveau de zoom par défaut :</translation>
-+<translation id="3872166400289564527">Stockage externe</translation>
-+<translation id="5912378097832178659">Modifi&amp;er les moteurs de recherche...</translation>
-+<translation id="8272426682713568063">Cartes de paiement</translation>
-+<translation id="3749289110408117711">Nom du fichier</translation>
-+<translation id="3173397526570909331">Arrêter la synchronisation</translation>
-+<translation id="5538092967727216836">Actualiser le cadre</translation>
-+<translation id="4813345808229079766">Connexion</translation>
-+<translation id="411666854932687641">Mémoire privée</translation>
-+<translation id="119944043368869598">Tout effacer</translation>
-+<translation id="3467848195100883852">Activer la correction orthographique automatique</translation>
-+<translation id="1336254985736398701">Afficher les &amp;infos sur la page</translation>
-+<translation id="7550830279652415241">favoris_<ph name="DATESTAMP"/>.html</translation>
-+<translation id="6828153365543658583">Autoriser uniquement les utilisateurs suivants à se connecter :</translation>
-+<translation id="1652965563555864525">&amp;Muet</translation>
-+<translation id="4200983522494130825">Nouvel ongle&amp;t</translation>
-+<translation id="7979036127916589816">Erreur de synchronisation</translation>
-+<translation id="1029317248976101138">Zoom</translation>
-+<translation id="5455790498993699893"><ph name="ACTIVE_MATCH"/> sur <ph name="TOTAL_MATCHCOUNT"/></translation>
-+<translation id="8890069497175260255">Type de clavier</translation>
-+<translation id="1202290638211552064">Délai d'expiration atteint au niveau de la passerelle ou du serveur proxy en attente d'une réponse d'un serveur en amont.</translation>
-+<translation id="7765158879357617694">Déplacer</translation>
-+<translation id="5731751937436428514">Mode de saisie du vietnamien (VIQR)</translation>
-+<translation id="8412144371993786373">Ajouter la page actuelle aux favoris</translation>
-+<translation id="7615851733760445951">&lt;aucun cookie sélectionné&gt;</translation>
-+<translation id="469553822757430352">Le mot de passe de l'application est incorrect.</translation>
-+<translation id="2493021387995458222">Sélectionner &quot;un mot à la fois&quot;</translation>
-+<translation id="5279600392753459966">Tout bloquer</translation>
-+<translation id="6846298663435243399">Chargement en cours…</translation>
-+<translation id="7392915005464253525">&amp;Rouvrir la fenêtre fermée</translation>
-+<translation id="1144684570366564048">Gérer les exceptions...</translation>
-+<translation id="7400418766976504921">URL</translation>
-+<translation id="1541725072327856736">Katakana demi-chasse</translation>
-+<translation id="7456847797759667638">Ouvrir une adresse</translation>
-+<translation id="1388866984373351434">Données de navigation</translation>
-+<translation id="3754634516926225076">Code PIN incorrect. Veuillez réessayer.</translation>
-+<translation id="7378627244592794276">Non</translation>
-+<translation id="2800537048826676660">Utiliser cette langue pour corriger l'orthographe</translation>
-+<translation id="68541483639528434">Fermer les autres onglets</translation>
-+<translation id="941543339607623937">Clé privée non valide.</translation>
-+<translation id="6499058468232888609">Une erreur réseau s'est produite pendant la communication avec le service de gestion des périphériques.</translation>
-+<translation id="4433862206975946675">Importer les données d'un autre navigateur...</translation>
-+<translation id="4022426551683927403">&amp;Ajouter au dictionnaire</translation>
-+<translation id="2897878306272793870">Voulez-vous vraiment ouvrir <ph name="TAB_COUNT"/> onglets ?</translation>
-+<translation id="312759608736432009">Fabricant du périphérique :</translation>
-+<translation id="362276910939193118">Afficher l'historique complet</translation>
-+<translation id="6079696972035130497">Illimité</translation>
-+<translation id="4365411729367255048">Clavier Neo2 allemand</translation>
-+<translation id="6348657800373377022">Liste déroulante</translation>
-+<translation id="8064671687106936412">Clé :</translation>
-+<translation id="2218515861914035131">Coller en texte brut</translation>
-+<translation id="1725149567830788547">Afficher les &amp;commandes</translation>
-+<translation id="3528033729920178817">Cette page suit votre position géographique.</translation>
-+<translation id="5518584115117143805">Certificat de chiffrement de courrier électronique</translation>
-+<translation id="9203398526606335860">&amp;Profilage activé</translation>
-+<translation id="4307281933914537745">En savoir plus sur la récupération du système</translation>
-+<translation id="2849936225196189499">Essentielle</translation>
-+<translation id="9001035236599590379">Type MIME</translation>
-+<translation id="5612754943696799373">Autoriser le téléchargement ?</translation>
-+<translation id="6353618411602605519">Clavier croate</translation>
-+<translation id="5515810278159179124">Interdire à tous les sites de suivre ma position géographique</translation>
-+<translation id="5999606216064768721">Utiliser la barre de titre du système et les bordures de la fenêtre</translation>
-+<translation id="904752364881701675">En bas à gauche</translation>
-+<translation id="3398951731874728419">Informations sur l'erreur :</translation>
-+<translation id="1464570622807304272">Essayez : saisissez &quot;orchidées&quot;, puis appuyez sur Entrée.</translation>
-+<translation id="8026684114486203427">Pour utiliser Chrome Web Store, vous devez être connecté à un compte Google.</translation>
-+<translation id="8417276187983054885">Configurer <ph name="CLOUD_PRINT_NAME"/></translation>
-+<translation id="3056462238804545033">Petit problème... Nous n'avons pas réussi à vous authentifier. Veuillez vérifier vos identifiants de connexion puis réessayer.</translation>
-+<translation id="5298420986276701358">Pour gérer à distance la configuration de ce périphérique <ph name="PRODUCT_NAME"/> depuis le cloud, connectez-vous avec votre compte Google Apps.</translation>
-+<translation id="2678063897982469759">Réactiver</translation>
-+<translation id="1779766957982586368">Fermer la fenêtre</translation>
-+<translation id="4850886885716139402">Présentation</translation>
-+<translation id="89217462949994770">Vous avez saisi un trop grand nombre de codes PIN incorrects. Veuillez contacter <ph name="CARRIER_ID"/> pour obtenir une nouvelle clé de déverrouillage du code PIN à 8 chiffres.</translation>
-+<translation id="5920618722884262402">Bloquer le contenu inapproprié</translation>
-+<translation id="5120247199412907247">Configuration avancée</translation>
-+<translation id="5922220455727404691">Utiliser SSL 3.0</translation>
-+<translation id="1368352873613152012">Règles de confidentialité liées à la navigation sécurisée</translation>
-+<translation id="5105859138906591953">Vous devez être connecté à votre compte Google pour importer les favoris de la barre d'outils Google dans Google Chrome. Connectez-vous et relancez l'importation.</translation>
-+<translation id="8899851313684471736">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
-+<translation id="4110342520124362335">Les cookies de <ph name="DOMAIN"/> ont été bloqués.</translation>
-+<translation id="3303818374450886607">Copies</translation>
-+<translation id="2019718679933488176">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
-+<translation id="4138267921960073861">Afficher les noms d'utilisateurs et leur photo sur la page de connexion</translation>
-+<translation id="7465778193084373987">URL de révocation de certificat Netscape</translation>
-+<translation id="5976690834266782200">Ajoute des options de regroupement des onglets dans le menu contextuel des onglets.</translation>
-+<translation id="4755240240651974342">Clavier finnois</translation>
-+<translation id="7049893973755373474">Vérifiez votre connexion Internet. Redémarrez votre routeur, votre modem
-+ ou tout autre périphérique réseau que vous utilisez.</translation>
-+<translation id="7421925624202799674">&amp;Afficher le code source de la page</translation>
-+<translation id="3940082421246752453">Le serveur ne prend pas en charge la version HTTP utilisée dans la demande.</translation>
-+<translation id="661719348160586794">Vos mots de passe enregistrés s'afficheront ici.</translation>
-+<translation id="6686490380836145850">Fermer les onglets sur la droite</translation>
-+<translation id="5608669887400696928"><ph name="NUMBER_DEFAULT"/> heures</translation>
-+<translation id="8844709414456935411"><ph name="PRODUCT_NAME"/>
-+ indique qu'un produit ESET intercepte les connexions sécurisées.
-+ En général, cela ne constitue pas un problème de sécurité car le
-+ logiciel ESET s'exécute souvent sur le même ordinateur. Toutefois, en raison
-+ de certaines incompatibilités avec les connexions sécurisées
-+ <ph name="PRODUCT_NAME"/>,
-+ vous devez configurer les produits ESET de manière à éviter ces
-+ interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
-+<translation id="3936877246852975078">Les requêtes adressées au serveur ont été temporairement limitées.</translation>
-+<translation id="2600306978737826651">Impossible de télécharger l'image. Gravure annulée.</translation>
-+<translation id="609978099044725181">Activer/désactiver le mode Hanja</translation>
-+<translation id="1829483195200467833">Effacer les paramètres d'ouverture automatique</translation>
-+<translation id="2738771556149464852">Pas après le</translation>
-+<translation id="5774515636230743468">Manifeste :</translation>
-+<translation id="719464814642662924">Visa</translation>
-+<translation id="7474889694310679759">Clavier anglais canadien</translation>
-+<translation id="1817871734039893258">Récupération de fichier Microsoft</translation>
-+<translation id="2423578206845792524">En&amp;registrer l'image sous...</translation>
-+<translation id="6839929833149231406">Zone</translation>
-+<translation id="9068931793451030927">Chemin :</translation>
-+<translation id="283278805979278081">Prendre la photo</translation>
-+<translation id="7320906967354320621">Inactif</translation>
-+<translation id="1407050882688520094">Certains de vos certificats enregistrés identifient ces autorités de certification :</translation>
-+<translation id="4287689875748136217">Impossible d'afficher la page Web, car le serveur n'a envoyé aucune donnée.</translation>
-+<translation id="1634788685286903402">Considérer ce certificat comme fiable pour identifier les utilisateurs de messageries.</translation>
-+<translation id="7052402604161570346">Ce type de fichier peut endommager votre ordinateur. Voulez-vous vraiment télécharger <ph name="FILE_NAME"/> ?</translation>
-+<translation id="8642489171979176277">Importés depuis la barre d'outils Google</translation>
-+<translation id="4142744419835627535">Recherche instantanée et saisie semi-automatique</translation>
-+<translation id="4684427112815847243">Tout synchroniser</translation>
-+<translation id="1125520545229165057">Dvorak (Hsu)</translation>
-+<translation id="8940229512486821554">Exécuter la commande <ph name="EXTENSION_NAME"/> : <ph name="SEARCH_TERMS"/></translation>
-+<translation id="2232876851878324699">Le fichier contenait un certificat, qui n'a pas été importé :</translation>
-+<translation id="7787129790495067395">Vous utilisez actuellement un mot de passe multiterme. Si vous l'oubliez, vous pouvez réinitialiser la synchronisation afin de supprimer vos données des serveurs Google à l'aide de Google Dashboard.</translation>
-+<translation id="2686759344028411998">Impossible de détecter les modules chargés.</translation>
-+<translation id="572525680133754531">Cette fonctionnalité affiche une bordure autour des couches de rendu afin de déboguer et d'étudier leur composition.</translation>
-+<translation id="2011110593081822050">Processus de traitement Web : <ph name="WORKER_NAME"/></translation>
-+<translation id="3294437725009624529">Invité</translation>
-+<translation id="350069200438440499">Nom du fichier :</translation>
-+<translation id="9058204152876341570">Un élément est manquant.</translation>
-+<translation id="8494979374722910010">Échec de la tentative de connexion au serveur.</translation>
-+<translation id="7810202088502699111">Des fenêtres pop-up ont été bloquées sur cette page.</translation>
-+<translation id="8190698733819146287">Personnaliser les langues et la saisie...</translation>
-+<translation id="646727171725540434">Proxy HTTP</translation>
-+<translation id="1006316751839332762">Mot de passe multiterme de chiffrement</translation>
-+<translation id="8795916974678578410">Nouvelle fenêtre</translation>
-+<translation id="2733275712367076659">Certains certificats provenant de ces organisations vous identifient :</translation>
-+<translation id="4801512016965057443">Autoriser l'itinérance des données mobiles</translation>
-+<translation id="2515586267016047495">Alt</translation>
-+<translation id="2046040965693081040">Utiliser les pages actuelles</translation>
-+<translation id="3798449238516105146">Version</translation>
-+<translation id="5764483294734785780">En&amp;registrer le fichier audio sous...</translation>
-+<translation id="5252456968953390977">Itinérance</translation>
-+<translation id="8744641000906923997">Romaji</translation>
-+<translation id="8507996248087185956"><ph name="NUMBER_DEFAULT"/> minutes</translation>
-+<translation id="4845656988780854088">Synchroniser uniquement les paramètres et\ndonnées qui ont changé depuis la dernière connexion\n(requiert votre mot de passe précédent)</translation>
-+<translation id="348620396154188443">Autoriser tous les sites à afficher des notifications sur le Bureau</translation>
-+<translation id="8214489666383623925">Ouvrir le fichier...</translation>
-+<translation id="5376120287135475614">Changer de fenêtre</translation>
-+<translation id="5230160809118287008">Chèvres téléportées</translation>
-+<translation id="1701567960725324452">Si vous arrêtez la synchronisation, les données stockées sur cet ordinateur et dans votre compte Google demeureront à ces deux emplacements. Toutefois, les nouvelles données ou les modifications apportées au contenu existant ne seront pas synchronisées.</translation>
-+<translation id="7761701407923456692">Le certificat du serveur ne correspond pas à l'URL.</translation>
-+<translation id="3885155851504623709">Commune</translation>
-+<translation id="4910171858422458941">Impossible d'activer les plug-ins désactivés par une stratégie d'entreprise.</translation>
-+<translation id="4495419450179050807">Ne pas afficher sur cette page</translation>
-+<translation id="4745800796303246012">Méthodes EAP en Wi-Fi expérimentales</translation>
-+<translation id="1225544122210684390">Disque dur</translation>
-+<translation id="939736085109172342">Nouveau dossier</translation>
-+<translation id="4933484234309072027">intégration sur <ph name="URL"/></translation>
-+<translation id="5554720593229208774">Autorité de certification de messagerie</translation>
-+<translation id="862750493060684461">Cache CSS</translation>
-+<translation id="2832519330402637498">En haut à gauche</translation>
-+<translation id="6749695674681934117">Saisissez le nom du nouveau dossier.</translation>
-+<translation id="6204994989617056362">L'extension de renégociation SSL était introuvable lors de la négociation sécurisée. Avec certains sites, connus pour leur prise en charge de l'extension de renégociation, Google Chrome exige une négociation mieux sécurisée afin de prévenir certaines attaques. L'absence de cette extension suggère que votre connexion a été interceptée et manipulée au cours du transfert.</translation>
-+<translation id="6679492495854441399">Petit problème... Une erreur de communication avec le réseau est survenue lors de la tentative d'inscription de ce périphérique. Veuillez vérifier votre connexion réseau et réessayer.</translation>
-+<translation id="7789962463072032349">pause</translation>
-+<translation id="121827551500866099">Afficher tous les téléchargements...</translation>
-+<translation id="1562633988311880769">Connexion à <ph name="CLOUD_PRINT_NAME"/></translation>
-+<translation id="5949910269212525572">Impossible de résoudre l'adresse DNS du serveur.</translation>
-+<translation id="3115147772012638511">En attente de l'affichage du cache</translation>
-+<translation id="257088987046510401">Thèmes</translation>
-+<translation id="6771079623344431310">Impossible de se connecter au serveur proxy.</translation>
-+<translation id="2200129049109201305">Ignorer la synchronisation des données chiffrées ?</translation>
-+<translation id="1426410128494586442">Oui</translation>
-+<translation id="6725970970008349185">Nombre de suggestions par page</translation>
-+<translation id="6198252989419008588">Modifier le code PIN</translation>
-+<translation id="5749483996735055937">Un problème est survenu lors de la copie de l'image de récupération sur le périphérique.</translation>
-+<translation id="3520476450377425184"><ph name="NUMBER_MANY"/> jours restants</translation>
-+<translation id="7643817847124207232">La connexion Internet a été interrompue.</translation>
-+<translation id="932327136139879170">Début</translation>
-+<translation id="4764675709794295630">« Précédent</translation>
-+<translation id="2560794850818211873">C&amp;opier l'URL de la vidéo</translation>
-+<translation id="6042708169578999844">Vos données sur <ph name="WEBSITE_1"/> et <ph name="WEBSITE_2"/></translation>
-+<translation id="5302048478445481009">Langue</translation>
-+<translation id="5553089923092577885">Mappages des stratégies de certificat</translation>
-+<translation id="5600907569873192868"><ph name="NUMBER_MANY"/> minutes restantes</translation>
-+<translation id="1519704592140256923">Sélectionner la position</translation>
-+<translation id="1275018677838892971">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
-+<translation id="702455272205692181"><ph name="EXTENSION_NAME"/></translation>
-+<translation id="7170041865419449892">Hors de portée</translation>
-+<translation id="908263542783690259">Effacer l'historique de navigation</translation>
-+<translation id="7518003948725431193">Aucune page Web trouvée à l'adresse :<ph name="URL"/></translation>
-+<translation id="745602119385594863">Nouveau moteur de recherche :</translation>
-+<translation id="7484645889979462775">Jamais pour ce site</translation>
-+<translation id="8666066831007952346"><ph name="NUMBER_TWO"/> jours restants</translation>
-+<translation id="9086455579313502267">Impossible d'accéder au réseau.</translation>
-+<translation id="5595485650161345191">Modifier l'adresse</translation>
-+<translation id="2374144379568843525">&amp;Masquer le panneau de la vérification orthographique</translation>
-+<translation id="2694026874607847549">1 cookie</translation>
-+<translation id="4393664266930911253">Activer ces fonctionnalités...</translation>
-+<translation id="6390842777729054533"><ph name="NUMBER_ZERO"/> secondes restantes</translation>
-+<translation id="3909791450649380159">Cou&amp;per</translation>
-+<translation id="2955913368246107853">Fermer la barre de recherche</translation>
-+<translation id="5642508497713047">Signataire de la liste de révocation de certificats</translation>
-+<translation id="813082847718468539">Afficher des informations à propos du site</translation>
-+<translation id="3122464029669770682">UC</translation>
-+<translation id="1684861821302948641">Fermer les pages</translation>
-+<translation id="6092270396854197260">MSPY</translation>
-+<translation id="6802031077390104172"><ph name="USAGE"/> (<ph name="OID"/>)</translation>
-+<translation id="4052120076834320548">Très petite</translation>
-+<translation id="6623138136890659562">Afficher les réseaux privés dans le menu Réseau pour activer la connexion à un VPN</translation>
-+<translation id="8969837897925075737">Vérification de la mise à jour du système...</translation>
-+<translation id="3393716657345709557">L'entrée demandée est introuvable dans le cache.</translation>
-+<translation id="7241389281993241388">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client.</translation>
-+<translation id="40334469106837974">Modifier la mise en page</translation>
-+<translation id="4804818685124855865">Se déconnecter</translation>
-+<translation id="2617919205928008385">Espace insuffisant.</translation>
-+<translation id="210445503571712769">Préférences synchronisées</translation>
-+<translation id="1608306110678187802">Imp&amp;rimer le cadre...</translation>
-+<translation id="7427315641433634153">MSCHAP</translation>
-+<translation id="6622980291894852883">Continuer à bloquer les images</translation>
-+<translation id="5937837224523037661">Lorsqu'un site utilise des plug-ins :</translation>
-+<translation id="4988792151665380515">Échec d'exportation de la clé publique</translation>
-+<translation id="6333049849394141510">Choisir les éléments à synchroniser</translation>
-+<translation id="446322110108864323">Paramètres de saisie du Pinyin</translation>
-+<translation id="4948468046837535074">Ouvrir les pages suivantes :</translation>
-+<translation id="5222676887888702881">Déconnexion</translation>
-+<translation id="6978121630131642226">Moteurs de recherche</translation>
-+<translation id="6839225236531462745">Erreur de suppression de certificat</translation>
-+<translation id="6745994589677103306">Ne rien faire</translation>
-+<translation id="855081842937141170">Épingler l'onglet</translation>
-+<translation id="6263541650532042179">réinitialiser la synchronisation</translation>
-+<translation id="6055392876709372977">PKCS #1 SHA-256 avec chiffrement RSA</translation>
-+<translation id="7903984238293908205">Katakana</translation>
-+<translation id="3781488789734864345">Choisir un réseau mobile</translation>
-+<translation id="268053382412112343">&amp;Historique</translation>
-+<translation id="2723893843198727027">Mode développeur :</translation>
-+<translation id="1722567105086139392">Lien</translation>
-+<translation id="2620436844016719705">Système</translation>
-+<translation id="5362741141255528695">Sélectionnez le fichier de clé privée.</translation>
-+<translation id="5292890015345653304">Insérez une carte SD ou une carte mémoire USB.</translation>
-+<translation id="5583370583559395927">Temps restant : <ph name="TIME_REMAINING"/></translation>
-+<translation id="8065982201906486420">Cliquez ici pour exécuter le plug-in <ph name="PLUGIN_NAME"/>.</translation>
-+<translation id="6219717821796422795">Hanyu</translation>
-+<translation id="3725367690636977613">pages</translation>
-+<translation id="2688477613306174402">Configuration en cours</translation>
-+<translation id="1195447618553298278">Erreur inconnue</translation>
-+<translation id="3353284378027041011"><ph name="NUMBER_FEW"/> days ago</translation>
-+<translation id="8811462119186190367">La langue utilisée pour Google Chrome est passée de &quot;<ph name="FROM_LOCALE"/>&quot; à &quot;<ph name="TO_LOCALE"/>&quot; après la synchronisation de vos paramètres.</translation>
-+<translation id="1087119889335281750">&amp;Aucune suggestion orthographique</translation>
-+<translation id="5228309736894624122">Erreur de protocole SSL</translation>
-+<translation id="8216170236829567922">Mode de saisie du thaï (clavier Pattachote)</translation>
-+<translation id="8464132254133862871">Ce compte utilisateur n'est pas compatible avec ce service.</translation>
-+<translation id="6812349420832218321"><ph name="PRODUCT_NAME"/> ne peut pas être exécuté en tant que root.</translation>
-+<translation id="5076340679995252485">C&amp;oller</translation>
-+<translation id="2904348843321044456">Paramètres de contenu...</translation>
-+<translation id="1055216403268280980">Dimensions de l'image</translation>
-+<translation id="1784284518684746740">Sélectionner le fichier à enregistrer sous</translation>
-+<translation id="7032947513385578725">Disque Flash</translation>
-+<translation id="5518442882456325299">Moteur de recherche actuel :</translation>
-+<translation id="14171126816530869">L'identité de <ph name="ORGANIZATION"/> situé à <ph name="LOCALITY"/> a été vérifiée par <ph name="ISSUER"/>.</translation>
-+<translation id="6263082573641595914">Version de l'autorité de certification Microsoft</translation>
-+<translation id="3105917916468784889">Enregistrer une capture d'écran</translation>
-+<translation id="1741763547273950878">Page sur <ph name="SITE"/></translation>
-+<translation id="1587275751631642843">Console &amp;JavaScript</translation>
-+<translation id="8460696843433742627">Réponse reçue incorrecte lors de la tentative de chargement de <ph name="URL"/>.
-+ Cela peut être dû à une opération de maintenance ou à une configuration incorrecte sur le serveur.</translation>
-+<translation id="297870353673992530">Serveur DNS :</translation>
-+<translation id="3222066309010235055">Pré-rendu : <ph name="PRERENDER_CONTENTS_NAME"/></translation>
-+<translation id="6410063390789552572">Impossible d'accéder à la bibliothèque réseau.</translation>
-+<translation id="6880587130513028875">Des images ont été bloquées sur cette page.</translation>
-+<translation id="851263357009351303">Toujours autoriser <ph name="HOST"/> à afficher les images</translation>
-+<translation id="3511307672085573050">Copier l'adr&amp;esse du lien</translation>
-+<translation id="1134009406053225289">Ouvrir dans une fenêtre de navigation privée</translation>
-+<translation id="6655190889273724601">Mode développeur</translation>
-+<translation id="1071917609930274619">Chiffrement des données</translation>
-+<translation id="3473105180351527598">Activer la protection contre le phishing et les logiciels malveillants</translation>
-+<translation id="6151323131516309312">Appuyez sur <ph name="SEARCH_KEY"/> pour rechercher sur <ph name="SITE_NAME"/></translation>
-+<translation id="3753317529742723206">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) au lieu de <ph name="REPLACED_HANDLER_TITLE"/> pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
-+<translation id="6216679966696797604">Démarrer une session en tant qu'invité</translation>
-+<translation id="5456397824015721611">Nombre maximal de caractères chinois dans la mémoire tampon de pré-édition, notamment les entrées de symboles Zhuyin</translation>
-+<translation id="2055443983279698110">Barre de menus GNOME expérimentale disponible</translation>
-+<translation id="2342959293776168129">Effacer l'historique des téléchargements</translation>
-+<translation id="2503522102815150840">Navigateur bloqué...</translation>
-+<translation id="7201354769043018523">Parenthèse drte</translation>
-+<translation id="425878420164891689">Calcul du temps de chargement</translation>
-+<translation id="508794495705880051">Ajouter une carte de paiement...</translation>
-+<translation id="1425975335069981043">Itinérance :</translation>
-+<translation id="1272079795634619415">Arrêter</translation>
-+<translation id="5442787703230926158">Erreur de synchronisation...</translation>
-+<translation id="2462724976360937186">ID de clé de l'autorité de certification</translation>
-+<translation id="6786747875388722282">Extensions</translation>
-+<translation id="3944384147860595744">Imprimez où que vous soyez.</translation>
-+<translation id="2570648609346224037">Un problème est survenu lors du téléchargement de l'image de récupération.</translation>
-+<translation id="4306718255138772973">Cloud Print Proxy</translation>
-+<translation id="9053965862400494292">Une erreur s'est produite lors de la configuration de la synchronisation.</translation>
-+<translation id="8596540852772265699">Fichiers personnalisés</translation>
-+<translation id="7017354871202642555">Impossible de définir le mode une fois la fenêtre créée.</translation>
-+<translation id="3101709781009526431">Date et heure</translation>
-+<translation id="69375245706918574">Personnaliser les préférences de synchronisation</translation>
-+<translation id="833853299050699606">Aucune information disponible sur le forfait</translation>
-+<translation id="1737968601308870607">Signaler un problème</translation>
-+<translation id="4571852245489094179">Importer mes favoris et paramètres</translation>
-+<translation id="99648783926443049">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Paramètres &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
-+<translation id="4421917670248123270">Fermer et annuler les téléchargements</translation>
-+<translation id="5605623530403479164">Autres moteurs de recherche</translation>
-+<translation id="8887243200615092733"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Pour protéger vos données, vous devez confirmer les informations relatives à votre compte.</translation>
-+<translation id="4740663705480958372">Cette fonctionnalité active les API P2P Pepper et P2P JavaScript. L'API est en cours de développement et n'est pas encore opérationnelle.</translation>
-+<translation id="5710435578057952990">L'identité de ce site Web n'a pas été vérifiée.</translation>
-+<translation id="1421046588786494306">Sessions à l'étranger</translation>
-+<translation id="1661245713600520330">Cette page répertorie tous les modules chargés dans le processus principal et les modules enregistrés de manière à être chargés ultérieurement.</translation>
-+<translation id="5451646087589576080">Afficher les &amp;infos sur le cadre</translation>
-+<translation id="3368922792935385530">Connecté</translation>
-+<translation id="3498309188699715599">Paramètres d'entrée en Chewing</translation>
-+<translation id="8486154204771389705">Conserver sur cette page</translation>
-+<translation id="3866443872548686097">Votre support de récupération est prêt. Vous pouvez le retirer du système.</translation>
-+<translation id="6824564591481349393">Copi&amp;er l'adresse e-mail</translation>
-+<translation id="907148966137935206">Interdire à tous les sites d'afficher des fenêtres pop-up (recommandé)</translation>
-+<translation id="5184063094292164363">Console &amp;JavaScript</translation>
-+<translation id="333371639341676808">Empêcher cette page de générer des boîtes de dialogue supplémentaires</translation>
-+<translation id="7632380866023782514">En haut à droite</translation>
-+<translation id="4925520021222027859">Entrez le mot de passe associé à votre application :</translation>
-+<translation id="3494768541638400973">Mode de saisie Google du japonais (pour clavier japonais)</translation>
-+<translation id="5844183150118566785"><ph name="PRODUCT_NAME"/> est à jour (<ph name="VERSION"/>)</translation>
-+<translation id="3118046075435288765">Le serveur a mis fin à la connexion de manière inattendue.</translation>
-+<translation id="8041140688818013446">Il est possible que le serveur hébergeant la page Web soit surchargé ou ait rencontré une erreur. Pour éviter de générer
-+ trop de trafic et d'aggraver la situation,
-+ <ph name="PRODUCT_NAME"/> a temporairement
-+ bloqué l'acceptation des requêtes adressées au serveur.
-+ <ph name="LINE_BREAK"/>
-+ Si vous pensez que ce comportement n'est pas souhaitable, (par exemple, dans le cas où vous déboguez votre propre site Web), vous pouvez
-+ consulter la page <ph name="NET_INTERNALS_PAGE"/>,
-+ sur laquelle vous pourrez trouver plus d'informations ou désactiver cette fonctionnalité.</translation>
-+<translation id="1725068750138367834">Gestionnaire de &amp;fichiers</translation>
-+<translation id="4254921211241441775">Arrêter la synchronisation du compte</translation>
-+<translation id="7791543448312431591">Ajouter</translation>
-+<translation id="8569764466147087991">Sélectionnez le fichier à ouvrir</translation>
-+<translation id="5449451542704866098">Aucun forfait de données</translation>
-+<translation id="307505906468538196">Créer un compte Google</translation>
-+<translation id="2053553514270667976">Code postal</translation>
-+<translation id="48838266408104654">&amp;Gestionnaire de tâches</translation>
-+<translation id="4378154925671717803">Téléphone</translation>
-+<translation id="3694027410380121301">Sélectionner l'onglet précédent</translation>
-+<translation id="6178664161104547336">Sélectionner un certificat</translation>
-+<translation id="1375321115329958930">Mots de passe enregistrés</translation>
-+<translation id="3341703758641437857">Autoriser l'accès aux URL de fichier</translation>
-+<translation id="5702898740348134351">Modifi&amp;er les moteurs de recherche...</translation>
-+<translation id="734303607351427494">Gérer les moteurs de recherche...</translation>
-+<translation id="8326478304147373412">PKCS #7, chaîne de certificats</translation>
-+<translation id="3242765319725186192">Clé pré-partagée :</translation>
-+<translation id="8089798106823170468">Contrôlez et partagez l'accès à vos imprimantes depuis n'importe quel compte Google.</translation>
-+<translation id="5984992849064510607">Ajoute l'option &quot;Utiliser les onglets latéraux&quot; au menu contextuel de la barre d'onglets. Utilisez cette option pour déplacer les onglets du haut de l'écran (affichage par défaut) vers le côté. Particulièrement utile sur les grands écrans.</translation>
-+<translation id="839736845446313156">S'inscrire</translation>
-+<translation id="4668929960204016307">,</translation>
-+<translation id="2409527877874991071">Saisissez un nouveau nom.</translation>
-+<translation id="4240069395079660403"><ph name="PRODUCT_NAME"/> ne peut pas être affiché dans cette langue.</translation>
-+<translation id="747114903913869239">Erreur : impossible de décoder l'extension.</translation>
-+<translation id="5412637665001827670">Clavier bulgare</translation>
-+<translation id="2113921862428609753">Accès aux informations de l'autorité</translation>
-+<translation id="5227536357203429560">Ajouter un réseau privé...</translation>
-+<translation id="732677191631732447">C&amp;opier l'URL du fichier audio</translation>
-+<translation id="7224023051066864079">Masque de sous-réseau :</translation>
-+<translation id="2401813394437822086">Impossible d'accéder à votre compte ?</translation>
-+<translation id="2344262275956902282">Utiliser les touches - et = pour paginer une liste d'entrées</translation>
-+<translation id="3609138628363401169">Le serveur ne prend pas en charge l'extension de renégociation TLS.</translation>
-+<translation id="3369624026883419694">Résolution de l'hôte...</translation>
-+<translation id="8870413625673593573">Récemment fermés</translation>
-+<translation id="9145357542626308749">Le certificat de sécurité du site a été signé avec un algorithme de signature faible.</translation>
-+<translation id="8502803898357295528">Votre mot de passe a été modifié</translation>
-+<translation id="4064488613268730704">Gérer les paramètres de saisie automatique...</translation>
-+<translation id="6830600606572693159">La page Web <ph name="URL"/> n'est pas disponible pour le moment. Cela peut être dû à une surcharge ou à une opération de maintenance.</translation>
-+<translation id="4145797339181155891">Éjecter</translation>
-+<translation id="7886793013438592140">Impossible de lancer le processus de service.</translation>
-+<translation id="8417944620073548444"><ph name="MEGABYTES"/> Mo restants</translation>
-+<translation id="7339898014177206373">Nouvelle fenêtre</translation>
-+<translation id="3026202950002788510">Sélectionnez
-+ <ph name="BEGIN_BOLD"/>
-+ Applications &gt; Préférences système &gt; Réseau &gt; Avancé &gt; Proxys
-+ <ph name="END_BOLD"/>
-+ et désélectionnez les serveurs proxy sélectionnés.</translation>
-+<translation id="7033648024564583278">Gravure en cours d'initialisation...</translation>
-+<translation id="2246340272688122454">Téléchargement de l'image de récupération...</translation>
-+<translation id="7770995925463083016">il y a <ph name="NUMBER_TWO"/> minutes</translation>
-+<translation id="2816269189405906839">Mode de saisie du chinois (cangjie)</translation>
-+<translation id="7087282848513945231">Comté</translation>
-+<translation id="2149951639139208969">Ouvrir l'adresse dans un nouvel onglet</translation>
-+<translation id="175196451752279553">&amp;Rouvrir l'onglet fermé</translation>
-+<translation id="5992618901488170220">Impossible d'afficher la page Web, car votre ordinateur est passé en mode
-+ veille ou hibernation. Dans ce cas, les connexions réseau sont
-+ coupées et les requêtes réseau échouent. L'actualisation de la page
-+ devrait permettre de résoudre ce problème.</translation>
-+<translation id="2655386581175833247">Certificat utilisateur :</translation>
-+<translation id="5039804452771397117">Autoriser</translation>
-+<translation id="5435964418642993308">Appuyer sur Entrée pour revenir en arrière et sur la touche de menu contextuel pour afficher l'historique</translation>
-+<translation id="81686154743329117">ZRM</translation>
-+<translation id="7564146504836211400">Cookies et autres données</translation>
-+<translation id="2266011376676382776">Page(s) ne répondant pas</translation>
-+<translation id="2714313179822741882">Paramètres d'entrée hangûl</translation>
-+<translation id="8658163650946386262">Configurer la synchronisation...</translation>
-+<translation id="3100609564180505575">Modules (<ph name="TOTAL_COUNT"/>). Conflits connus : <ph name="BAD_COUNT"/>, conflits probables : <ph name="SUSPICIOUS_COUNT"/></translation>
-+<translation id="3627671146180677314">Date de renouvellement du certificat Netscape</translation>
-+<translation id="1319824869167805246">Ouvrir tous les favoris dans une nouvelle fenêtre</translation>
-+<translation id="8652487083013326477">bouton radio concernant l'étendue de pages</translation>
-+<translation id="5204967432542742771">Saisissez votre mot de passe</translation>
-+<translation id="4388712255200933062"><ph name="CLOUD_PRINT_NAME"/> est conçu pour rendre l'impression plus intuitive, accessible et utile. <ph name="CLOUD_PRINT_NAME"/> vous permet de rendre vos imprimantes accessibles depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
-+<translation id="2932611376188126394">Dictionnaire de kanji unique</translation>
-+<translation id="5485754497697573575">Rétablir tous les onglets</translation>
-+<translation id="3371861036502301517">Échec de l'installation de l'extension</translation>
-+<translation id="644038709730536388">En savoir plus sur la manière de se protéger des logiciels malveillants en ligne</translation>
-+<translation id="2155931291251286316">Toujours afficher les fenêtres pop-up de <ph name="HOST"/></translation>
-+<translation id="3445830502289589282">Authentification phase 2 :</translation>
-+<translation id="5650551054760837876">Aucun résultat de recherche trouvé</translation>
-+<translation id="5494362494988149300">Ouvrir une fois le téléchargement &amp;terminé</translation>
-+<translation id="2956763290572484660"><ph name="COOKIES"/> cookies</translation>
-+<translation id="6989836856146457314">Mode de saisie du japonais (pour clavier américain)</translation>
-+<translation id="9187787570099877815">Continuer à bloquer les plug-ins</translation>
-+<translation id="8425492902634685834">Épingler sur la barre des tâches</translation>
-+<translation id="825608351287166772">Les certificats ont une période de validité, comme tous les documents relatifs à votre identité (tel qu'un passeport). Le certificat présenté à votre navigateur n'est pas encore valide ! Lorsqu'un certificat est en dehors de sa période de validité, il n'est pas nécessaire d'assurer la maintenance de certaines informations relatives à son état (s'il a été révoqué ou s'il n'est plus approuvé). Par conséquent, il est impossible de vérifier que le certificat est fiable. Ne poursuivez pas.</translation>
-+<translation id="741630086309232721">Fermer la session d'invité</translation>
-+<translation id="7309459761865060639">Contrôlez vos tâches d'impression et l'état de connexion de vos imprimantes en ligne.</translation>
-+<translation id="4803909571878637176">Désinstallation</translation>
-+<translation id="5209518306177824490">Empreinte SHA-1</translation>
-+<translation id="3300768886937313568">Modifier le code PIN de la carte SIM</translation>
-+<translation id="7447657194129453603">État du réseau :</translation>
-+<translation id="1553538517812678578">sans limite</translation>
-+<translation id="7947315300197525319">(Choisir une autre capture d'écran)</translation>
-+<translation id="3612070600336666959">Désactivation</translation>
-+<translation id="3759461132968374835">Aucune erreur n'a été signalée récemment. Les erreurs n'apparaissent ici que lorsque l'envoi de rapports d'erreur est activé.</translation>
-+<translation id="1516602185768225813">Rouvrir les dernières pages ouvertes</translation>
-+<translation id="189210018541388520">Ouvrir en mode plein écran</translation>
-+<translation id="8795668016723474529">Ajouter une carte de paiement</translation>
-+<translation id="5860033963881614850">Désactivé</translation>
-+<translation id="3956882961292411849">Chargement des informations sur votre forfait Internet mobile, veuillez patienter...</translation>
-+<translation id="689050928053557380">Acheter un forfait de données...</translation>
-+<translation id="4235618124995926194">Inclure cet e-mail :</translation>
-+<translation id="4874539263382920044">Le titre doit comporter au moins un caractère.</translation>
-+<translation id="798525203920325731">Espaces de noms réseau</translation>
-+<translation id="263325223718984101"><ph name="PRODUCT_NAME"/> n'a pas pu terminer l'installation, mais va poursuivre son exécution à partir de son image disque.</translation>
-+<translation id="7025190659207909717">Gestion des services Internet mobiles</translation>
-+<translation id="8265096285667890932">Utiliser les onglets latéraux</translation>
-+<translation id="4250680216510889253">Non</translation>
-+<translation id="3949593566929137881">Saisir le code PIN de la carte SIM</translation>
-+<translation id="6291953229176937411">&amp;Afficher dans le Finder</translation>
-+<translation id="2476990193835943955">Maintenez la touche Ctrl, Alt ou Maj enfoncée&lt;br&gt;pour afficher le raccourci clavier qui lui est associé.</translation>
-+<translation id="9187827965378254003">Vraiment désolé, aucun prototype n'est disponible pour le moment.</translation>
-+<translation id="8933960630081805351">&amp;Afficher dans le Finder</translation>
-+<translation id="3041612393474885105">Informations relatives au certificat</translation>
-+<translation id="7378810950367401542">/</translation>
-+<translation id="4611079913162790275">La synchronisation des mots de passe requiert votre attention.</translation>
-+<translation id="6562758426028728553">Veuillez saisir l'ancien et le nouveau code PIN.</translation>
-+<translation id="614161640521680948">Langue :</translation>
-+<translation id="3665650519256633768">Résultats de recherche</translation>
-+<translation id="3733127536501031542">Serveur SSL avec fonction d'optimisation</translation>
-+<translation id="3614837889828516995">Enregistrer en PDF</translation>
-+<translation id="5745056705311424885">Mémoire USB détectée</translation>
-+<translation id="5895875028328858187">M'avertir lorsque le flux de données est faible ou presque inexistant</translation>
-+<translation id="939598580284253335">Saisir le mot de passe multiterme</translation>
-+<translation id="7917972308273378936">Clavier lituanien</translation>
-+<translation id="8371806639176876412">Les éléments saisis dans le champ polyvalent peuvent être enregistrés.</translation>
-+<translation id="4216499942524365685">Les informations de connexion à votre compte sont obsolètes. Cliquez ici pour saisir à nouveau votre mot de passe.</translation>
-+<translation id="8899388739470541164">Vietnamien</translation>
-+<translation id="4091434297613116013">feuilles de papier</translation>
-+<translation id="7475671414023905704">URL de mot de passe perdu Netscape</translation>
-+<translation id="3335947283844343239">Rouvrir l'onglet fermé</translation>
-+<translation id="4089663545127310568">Effacer les mots de passe enregistrés</translation>
-+<translation id="6500444002471948304">Créer un nouveau dossier...</translation>
-+<translation id="2480626392695177423">Basculer en mode ponctuation pleine chasse ou demi-chasse</translation>
-+<translation id="5830410401012830739">Gérer les paramètres de localisation...</translation>
-+<translation id="8977410484919641907">Synchronisé...</translation>
-+<translation id="2794293857160098038">Options de recherche par défaut</translation>
-+<translation id="3947376313153737208">Aucune sélection</translation>
-+<translation id="1346104802985271895">Mode de saisie du vietnamien (TELEX)</translation>
-+<translation id="5935630983280450497"><ph name="NUMBER_ONE"/> minute restante</translation>
-+<translation id="5889282057229379085">Le nombre maximal d'autorités de certification intermédiaires a été dépassé : <ph name="NUM_INTERMEDIATE_CA"/></translation>
-+<translation id="3180365125572747493">Saisissez un mot de passe pour chiffrer ce fichier de certificat.</translation>
-+<translation id="5496587651328244253">Organiser</translation>
-+<translation id="4821086771593057290">Votre mot de passe a changé. Veuillez réessayer avec votre nouveau mot de passe.</translation>
-+<translation id="7075513071073410194">PKCS #1 MD5 avec chiffrement RSA</translation>
-+<translation id="4378727699507047138">Utiliser le thème classique</translation>
-+<translation id="7124398136655728606">Échap efface toute la mémoire tampon de pré-édition</translation>
-+<translation id="8293206222192510085">Ajouter aux favoris</translation>
-+<translation id="2592884116796016067">Un incident est survenu sur une partie de cette page (HTML WebWorker). Elle risque de ne pas fonctionner correctement.</translation>
-+<translation id="2529133382850673012">Clavier américain</translation>
-+<translation id="4411578466613447185">Signataire de code</translation>
-+<translation id="1354868058853714482">Adobe Reader n'est pas à jour et risque de ne plus être sécurisé.</translation>
-+<translation id="6252594924928912846">Personnaliser les paramètres de synchronisation...</translation>
-+<translation id="8425755597197517046">Co&amp;ller et rechercher</translation>
-+<translation id="1093148655619282731">Détails du certificat sélectionné :</translation>
-+<translation id="5568069709869097550">Impossible de se connecter</translation>
-+<translation id="2743322561779022895">Activation :</translation>
-+<translation id="4181898366589410653">Système de révocation introuvable dans le certificat du serveur</translation>
-+<translation id="8705331520020532516">Numéro de série</translation>
-+<translation id="1665770420914915777">Afficher la page &quot;Nouvel onglet&quot;</translation>
-+<translation id="2629089419211541119">il y a <ph name="NUMBER_ONE"/> heure</translation>
-+<translation id="1691063574428301566">Votre ordinateur redémarrera une fois la mise à jour effectuée.</translation>
-+<translation id="131364520783682672">Verr. maj.</translation>
-+<translation id="6259308910735500867">L'accès au répertoire de l'hôte de communication à distance a été refusé. Essayez avec un autre compte.</translation>
-+<translation id="3415261598051655619">Accessible aux scripts :</translation>
-+<translation id="2335122562899522968">Cette page place des cookies.</translation>
-+<translation id="8461914792118322307">Proxy</translation>
-+<translation id="4089521618207933045">Avec sous-menu</translation>
-+<translation id="1936157145127842922">Afficher dans le dossier</translation>
-+<translation id="6982279413068714821">il y a <ph name="NUMBER_DEFAULT"/> minutes</translation>
-+<translation id="7977590112176369853">&lt;saisir une requête&gt;</translation>
-+<translation id="3449839693241009168">Appuyez sur <ph name="SEARCH_KEY"/> pour envoyer des commandes à <ph name="EXTENSION_NAME"/>.</translation>
-+<translation id="7443484992065838938">Prévisualiser le rapport</translation>
-+<translation id="5714678912774000384">Activer le dernier onglet</translation>
-+<translation id="3799598397265899467">Lorsque je quitte le navigateur</translation>
-+<translation id="2125314715136825419">Continuer sans mettre à jour Adobe Reader (non recommandé)</translation>
-+<translation id="1120026268649657149">Le champ de mot clé doit être vide ou comporter un mot unique</translation>
-+<translation id="542318722822983047">Déplacer le curseur automatiquement au caractère suivant</translation>
-+<translation id="5317780077021120954">Enregistrer</translation>
-+<translation id="9027459031423301635">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
-+<translation id="2251809247798634662">Nouvelle fenêtre de navigation privée</translation>
-+<translation id="358344266898797651">Celtique</translation>
-+<translation id="3625870480639975468">Réinitialiser le zoom</translation>
-+<translation id="5199729219167945352">Prototypes</translation>
-+<translation id="5055518462594137986">Mémoriser mes choix pour tous les liens de ce type</translation>
-+<translation id="246059062092993255">Les plug-ins de cette page ont été bloqués.</translation>
-+<translation id="2870560284913253234">Site</translation>
-+<translation id="6945221475159498467">Sélectionner</translation>
-+<translation id="7724603315864178912">Couper</translation>
-+<translation id="4164507027399414915">Restaurer toutes les miniatures supprimées</translation>
-+<translation id="917051065831856788">Utiliser les onglets latéraux</translation>
-+<translation id="1976150099241323601">Se connecter au dispositif de sécurité</translation>
-+<translation id="6620110761915583480">Enregistrer le fichier</translation>
-+<translation id="4988526792673242964">Pages</translation>
-+<translation id="7543025879977230179">Options de <ph name="PRODUCT_NAME"/></translation>
-+<translation id="2175607476662778685">Barre de lancement rapide</translation>
-+<translation id="6434309073475700221">Annuler</translation>
-+<translation id="1367951781824006909">Choisir un fichier</translation>
-+<translation id="1425127764082410430">&amp;Rechercher <ph name="SEARCH_TERMS"/> avec <ph name="SEARCH_ENGINE"/></translation>
-+<translation id="684265517037058883">(pas encore valide)</translation>
-+<translation id="2027538664690697700">Mettre à jour le plug-in...</translation>
-+<translation id="8205333955675906842">Police Sans-Serif</translation>
-+<translation id="39964277676607559">Impossible de charger le JavaScript &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
-+<translation id="4378551569595875038">Connexion...</translation>
-+<translation id="7029809446516969842">Mots de passe</translation>
-+<translation id="8053278772142718589">Fichiers PKCS #12</translation>
-+<translation id="3129020372442395066">Options de saisie automatique de <ph name="PRODUCT_NAME_SHORT"/></translation>
-+<translation id="4114360727879906392">Fenêtre précédente</translation>
-+<translation id="8238649969398088015">Astuce</translation>
-+<translation id="5958418293370246440"><ph name="SAVED_FILES"/> / <ph name="TOTAL_FILES"/> fichiers</translation>
-+<translation id="2350172092385603347">Localisation utilisée, mais les paramètres régionaux par défaut (default_locale) n'ont pas été indiqués dans le manifeste. </translation>
-+<translation id="8221729492052686226">Si vous n'êtes pas à l'origine de cette requête, il s'agit probablement d'une attaque contre votre système. Si vous n'avez pas lancé cette requête de manière intentionnelle, cliquez sur Ne rien faire.</translation>
-+<translation id="5894314466642127212">Votre commentaire a bien été envoyé.</translation>
-+<translation id="894360074127026135">Fonction d'optimisation internationale Netscape </translation>
-+<translation id="6025294537656405544">Taille de police minimale</translation>
-+<translation id="1201402288615127009">Suivant</translation>
-+<translation id="1335588927966684346">Utilitaire :</translation>
-+<translation id="7857823885309308051">Cette opération peut prendre une minute...</translation>
-+<translation id="662870454757950142">Le format du mot de passe est incorrect.</translation>
-+<translation id="370665806235115550">Chargement...</translation>
-+<translation id="1808792122276977615">Ajouter la page...</translation>
-+<translation id="2076269580855484719">Masquer ce plug-in</translation>
-+<translation id="254416073296957292">&amp;Paramètres linguistiques...</translation>
-+<translation id="6652975592920847366">Créer un support de récupération du système d'exploitation</translation>
-+<translation id="52912272896845572">Le fichier de clé privée est incorrect.</translation>
-+<translation id="3232318083971127729">Valeur :</translation>
-+<translation id="8807632654848257479">Stable</translation>
-+<translation id="4209092469652827314">Grande</translation>
-+<translation id="4222982218026733335">Certificat serveur invalide</translation>
-+<translation id="152234381334907219">Jamais enregistrés</translation>
-+<translation id="5600599436595580114">Cette page a été préchargée.</translation>
-+<translation id="8926468725336609312">Google Chrome ne peut pas afficher l'aperçu avant impression lorsque la visionneuse de documents PDF intégrée est désactivée. Pour l'afficher, veuillez accéder à <ph name="BEGIN_LINK"/>chrome://plugins<ph name="END_LINK"/>, activer &quot;Chrome PDF Viewer&quot; et réessayer.</translation>
-+<translation id="8494214181322051417">Nouveau !</translation>
-+<translation id="7762841930144642410"><ph name="BEGIN_BOLD"/>Vous êtes passé en navigation privée<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront ni dans l'historique de votre navigateur, ni dans l'historique des recherches, et ne laisseront aucune trace (comme les cookies) sur votre ordinateur une fois que vous aurez fermé la fenêtre de navigation privée. Tous les fichiers téléchargés et les favoris créés seront toutefois conservés. <ph name="LINE_BREAK"/> <ph name="BEGIN_BOLD"/>Passer en navigation privée n'a aucun effet sur les autres utilisateurs, serveurs ou logiciels. Méfiez-vous :<ph name="END_BOLD"/> <ph name="BEGIN_LIST"/> <ph name="BEGIN_LIST_ITEM"/>Des sites Web qui collectent ou partagent des informations vous concernant<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des fournisseurs d'accès Internet ou des employeurs qui conservent une trace des pages que vous visitez<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des programmes indésirables qui enregistrent vos frappes en échange d'émoticônes gratuites<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui pourraient surveiller vos activités<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui se tiennent derrière vous<ph name="END_LIST_ITEM"/> <ph name="END_LIST"/> <ph name="BEGIN_LINK"/>En savoir plus sur la navigation privée<ph name="END_LINK"/></translation>
-+<translation id="2386255080630008482">Le certificat du serveur a été révoqué.</translation>
-+<translation id="2135787500304447609">&amp;Reprendre</translation>
-+<translation id="8309505303672555187">Sélectionnez un réseau :</translation>
-+<translation id="6143635259298204954">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils ne contenant pas de lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
-+<translation id="1813414402673211292">Effacer les données de navigation</translation>
-+<translation id="4062903950301992112">Si vous êtes conscient que la visite de ce site peut être préjudiciable à votre ordinateur, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
-+<translation id="32330993344203779">Votre périphérique est inscrit pour bénéficier de la gestion d'entreprise.</translation>
-+<translation id="2356762928523809690">Serveur de mise à jour non disponible (erreur : <ph name="ERROR_NUMBER"/>)</translation>
-+<translation id="219008588003277019">Module client natif : <ph name="NEXE_NAME"/></translation>
-+<translation id="5436510242972373446">Rechercher sur <ph name="SITE_NAME"/> :</translation>
-+<translation id="3800764353337460026">Style de symboles</translation>
-+<translation id="6719684875142564568"><ph name="NUMBER_ZERO"/> hours</translation>
-+<translation id="2096368010154057602">Département</translation>
-+<translation id="1036561994998035917">Continuer à utiliser <ph name="ENGINE_NAME"/></translation>
-+<translation id="8730621377337864115">OK</translation>
-+<translation id="665757950158579497">Essayez de désactiver les prédictions d'actions du réseau en procédant comme suit :
-+ Sélectionnez le
-+ <ph name="BEGIN_BOLD"/>
-+ menu clé à molette &gt;
-+ <ph name="SETTINGS_TITLE"/>
-+ &gt;
-+ <ph name="ADVANCED_TITLE"/>
-+ <ph name="END_BOLD"/>
-+ et désélectionnez &quot;<ph name="NO_PREFETCH_DESCRIPTION"/>&quot;.
-+ Si le problème n'est pas résolu, nous vous conseillons de sélectionner de nouveau
-+ cette option pour améliorer les performances.</translation>
-+<translation id="4932733599132424254">Date</translation>
-+<translation id="6267166720438879315">Sélectionnez un certificat pour vous authentifier sur <ph name="HOST_NAME"/>.</translation>
-+<translation id="2422927186524098759">Barre latérale</translation>
-+<translation id="7839809549045544450">La clé publique éphémère Diffie-Hellman associée au serveur est peu sûre.</translation>
-+<translation id="5515806255487262353">Rechercher dans Dictionnaire</translation>
-+<translation id="350048665517711141">Sélectionnez un moteur de recherche</translation>
-+<translation id="2790805296069989825">Clavier russe</translation>
-+<translation id="5708171344853220004">Nom Microsoft principal</translation>
-+<translation id="5464696796438641524">Clavier polonais</translation>
-+<translation id="2080010875307505892">Clavier serbe</translation>
-+<translation id="2953767478223974804"><ph name="NUMBER_ONE"/> minute</translation>
-+<translation id="201192063813189384">Erreur lors de la lecture des données du cache.</translation>
-+<translation id="7851768487828137624">Canary</translation>
-+<translation id="6129938384427316298">Commentaire du certificat Netscape</translation>
-+<translation id="8210608804940886430">Page suivante</translation>
-+<translation id="9065596142905430007"><ph name="PRODUCT_NAME"/> est à jour.</translation>
-+<translation id="1035650339541835006">Paramètres de saisie automatique...</translation>
-+<translation id="6315493146179903667">Tout ramener au premier plan</translation>
-+<translation id="1000498691615767391">Sélectionner le dossier à ouvrir</translation>
-+<translation id="3593152357631900254">Activer le mode Pinyin fuzzy</translation>
-+<translation id="5015344424288992913">Résolution du proxy...</translation>
-+<translation id="8506299468868975633">Le téléchargement de l'image a été interrompu.</translation>
-+<translation id="4724168406730866204">Eten 26</translation>
-+<translation id="308268297242056490">URI</translation>
-+<translation id="4479812471636796472">Clavier Dvorak américain</translation>
-+<translation id="8673026256276578048">Rechercher sur le Web...</translation>
-+<translation id="1437307674059038925">Si vous utilisez un serveur proxy, vérifiez les paramètres associés ou demandez à votre administrateur réseau
-+ si ce serveur fonctionne.</translation>
-+<translation id="149347756975725155">Impossible de charger l'icône de l'extension &quot;<ph name="ICON"/>&quot;.</translation>
-+<translation id="3675321783533846350">Définir un proxy pour se connecter au réseau</translation>
-+<translation id="5451285724299252438">zone de texte concernant l'étendue de pages</translation>
-+<translation id="5669267381087807207">Activation</translation>
-+<translation id="7434823369735508263">Clavier Dvorak britannique</translation>
-+<translation id="1572103024875503863"><ph name="NUMBER_MANY"/> jours</translation>
-+<translation id="2084978867795361905">MS-IME</translation>
-+<translation id="7227669995306390694">Aucun forfait de données <ph name="NETWORK"/></translation>
-+<translation id="3481915276125965083">Les fenêtres pop-up suivantes ont été bloquées sur cette page :</translation>
-+<translation id="7163503212501929773"><ph name="NUMBER_MANY"/> heures restantes</translation>
-+<translation id="7705276765467986571">Impossible de charger le modèle du favori.</translation>
-+<translation id="1196338895211115272">Échec d'exportation de la clé privée</translation>
-+<translation id="5586329397967040209">Utiliser comme page d'accueil</translation>
-+<translation id="629730747756840877">Compte</translation>
-+<translation id="8525306231823319788">Plein écran</translation>
-+<translation id="9054208318010838">Autoriser tous les sites à suivre ma position géographique</translation>
-+<translation id="3058212636943679650">Si la restauration du système d'exploitation de votre ordinateur s'avère nécessaire, une carte SD ou une clé USB de récupération vous sera demandée.</translation>
-+<translation id="2815382244540487333">Les cookies suivants ont été bloqués :</translation>
-+<translation id="8882395288517865445">Inclure les adresses de ma fiche de Carnet d’adresses</translation>
-+<translation id="374530189620960299">Le certificat de sécurité du site n'est pas approuvé !</translation>
-+<translation id="8852407435047342287">Votre liste d'applications, d'extensions et de thèmes installés</translation>
-+<translation id="5647283451836752568">Exécuter tous les plug-ins de cette page</translation>
-+<translation id="8642947597466641025">Augmente la taille du texte</translation>
-+<translation id="5188181431048702787">Accepter et continuer »</translation>
-+<translation id="1293556467332435079">Fichiers
-+</translation>
-+<translation id="2490270303663597841">Appliquer uniquement à cette session de navigation privée</translation>
-+<translation id="1757915090001272240">Latin large</translation>
-+<translation id="8496717697661868878">Exécuter ce plug-in</translation>
-+<translation id="3450660100078934250">MasterCard</translation>
-+<translation id="2916073183900451334">Sur le Web, Tab permet de sélectionner les liens, ainsi que les champs de formulaire.</translation>
-+<translation id="7772127298218883077">À propos de <ph name="PRODUCT_NAME"/></translation>
-+<translation id="2090876986345970080">Paramètres de sécurité du système</translation>
-+<translation id="9219103736887031265">Images</translation>
-+<translation id="5453632173748266363">Cyrillique</translation>
-+<translation id="1008557486741366299">Pas maintenant</translation>
-+<translation id="8415351664471761088">Attendre la fin du téléchargement</translation>
-+<translation id="1545775234664667895">Thème &quot;<ph name="THEME_NAME"/>&quot; installé</translation>
-+<translation id="5329858601952122676">&amp;Supprimer</translation>
-+<translation id="6100736666660498114">Menu Démarrer</translation>
-+<translation id="3994878504415702912">&amp;Zoom</translation>
-+<translation id="9009369504041480176">Transfert en cours (<ph name="PROGRESS_PERCENT"/> %)...</translation>
-+<translation id="8995603266996330174">Géré par <ph name="DOMAIN"/></translation>
-+<translation id="5602600725402519729">&amp;Rafraîchir</translation>
-+<translation id="172612876728038702">Configuration du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, cela peut prendre quelques minutes.</translation>
-+<translation id="1362165759943288856">Vous avez acheté une quantité illimitée de données le <ph name="DATE"/>.</translation>
-+<translation id="2078019350989722914">Confirmer avant de quitter (<ph name="KEY_EQUIVALENT"/>)</translation>
-+<translation id="7965010376480416255">Mémoire partagée</translation>
-+<translation id="6248988683584659830">Rech. dans les paramètres</translation>
-+<translation id="8323232699731382745">mot de passe d'accès au réseau</translation>
-+<translation id="6588399906604251380">Activer la vérification orthographique</translation>
-+<translation id="7167621057293532233">Types de données</translation>
-+<translation id="7053983685419859001">Bloquer</translation>
-+<translation id="2485056306054380289">Certificat de l'autorité de certification du serveur :</translation>
-+<translation id="6462109140674788769">Clavier grec</translation>
-+<translation id="2727712005121231835">Taille réelle</translation>
-+<translation id="8887733174653581061">Toujours en haut</translation>
-+<translation id="5581211282705227543">Aucun plug-in installé.</translation>
-+<translation id="610886263749567451">Alerte JavaScript</translation>
-+<translation id="5488468185303821006">Autoriser en mode navigation privée</translation>
-+<translation id="6556866813142980365">Rétablir</translation>
-+<translation id="2107287771748948380"><ph name="OBFUSCATED_CC_NUMBER"/>, expire le : <ph name="CC_EXPIRATION_DATE"/></translation>
-+<translation id="6584811624537923135">Confirmer la désinstallation</translation>
-+<translation id="7429235532957570505">Impossible de désactiver les plug-ins ayant été activés par une stratégie d'entreprise.</translation>
-+<translation id="7866522434127619318">Cette fonctionnalité active l'option &quot;Lire en un clic&quot; dans les paramètres de contenu du plug-in.</translation>
-+<translation id="8860923508273563464">Attendre la fin des téléchargements</translation>
-+<translation id="6406506848690869874">Synchronisation</translation>
-+<translation id="5288678174502918605">&amp;Rouvrir l'onglet fermé</translation>
-+<translation id="7238461040709361198">Votre mot de passe de compte Google a changé depuis votre dernière connexion à partir de cet ordinateur.</translation>
-+<translation id="1956050014111002555">Le fichier contenait plusieurs certificats, aucun d'eux n'a été importé :</translation>
-+<translation id="302620147503052030">Afficher le bouton</translation>
-+<translation id="5512074755152723588">La saisie dans le champ polyvalent d'une URL déjà ouverte dans un autre onglet entraîne l'affichage de l'onglet en question, et non l'affichage de l'URL dans l'onglet actuel.</translation>
-+<translation id="9157595877708044936">Configuration en cours...</translation>
-+<translation id="4475552974751346499">Rechercher dans les téléchargements</translation>
-+<translation id="3021256392995617989">Me demander lorsqu'un site tente de suivre ma position géographique (recommandé)</translation>
-+<translation id="5185386675596372454">La nouvelle version de &quot;<ph name="EXTENSION_NAME"/>&quot; a été désactivée, car elle nécessite davantage d'autorisations.</translation>
-+<translation id="4285669636069255873">Clavier phonétique russe</translation>
-+<translation id="4148925816941278100">American Express</translation>
-+<translation id="2320435940785160168">Ce serveur exige un certificat d'authentification et n'a pas accepté celui envoyé par le navigateur.
-+Votre certificat a peut-être expiré ou le serveur n'a pas approuvé l'émetteur.
-+Réessayez avec un autre certificat si vous en avez un.
-+Sinon, vous devrez en obtenir un nouveau d'un autre émetteur.</translation>
-+<translation id="6295228342562451544">Lorsque vous vous connectez à un site Web sécurisé, le serveur hébergeant ce site présente à votre navigateur un &quot;certificat&quot; afin de vérifier l'identité du site. Ce certificat contient des informations d'identité, telles que l'adresse du site Web, laquelle est vérifiée par un tiers approuvé par votre ordinateur. En vérifiant que l'adresse du certificat correspond à l'adresse du site Web, il est possible de s'assurer que vous êtes connecté de façon sécurisée avec le site Web souhaité et non pas avec un tiers (tel qu'un pirate informatique sur votre réseau).</translation>
-+<translation id="6342069812937806050">À l'instant</translation>
-+<translation id="5605716740717446121">Votre carte SIM sera définitivement désactivée si vous ne saisissez pas correctement la clé de déverrouillage du code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
-+<translation id="8836712291807476944"><ph name="SAVED_BYTES"/> / <ph name="TOTAL_BYTES"/> octets, Interrompu</translation>
-+<translation id="5502500733115278303">Importés depuis Firefox</translation>
-+<translation id="569109051430110155">Détection automatique</translation>
-+<translation id="4408599188496843485">&amp;Aide</translation>
-+<translation id="5399158067281117682">Les codes PIN sont différents !</translation>
-+<translation id="8494234776635784157">Contenu Web</translation>
-+<translation id="2681441671465314329">Vider le cache</translation>
-+<translation id="3646789916214779970">Rétablir le thème par défaut</translation>
-+<translation id="1592960452683145077">Le service de communication à distance a démarré correctement. Vous devriez maintenant pouvoir vous connecter à distance à cet ordinateur.</translation>
-+<translation id="1679068421605151609">Outils de développement</translation>
-+<translation id="6648524591329069940">Police Serif</translation>
-+<translation id="6896758677409633944">Copier</translation>
-+<translation id="5260508466980570042">Adresse e-mail ou mot de passe incorrect. Veuillez réessayer.</translation>
-+<translation id="7887998671651498201">Le plug-in suivant ne répond pas : souhaitez-vous interrompre <ph name="PLUGIN_NAME"/> ?</translation>
-+<translation id="173188813625889224">Sens</translation>
-+<translation id="8088823334188264070"><ph name="NUMBER_MANY"/> secondes</translation>
-+<translation id="1337036551624197047">Clavier tchèque</translation>
-+<translation id="4212108296677106246">Voulez-vous que &quot;<ph name="CERTIFICATE_NAME"/>&quot; soit considérée comme une autorité de certification fiable ?</translation>
-+<translation id="2861941300086904918">Gestionnaire de sécurité natif du client</translation>
-+<translation id="6991443949605114807">&lt;p&gt;Lorsque vous exécutez <ph name="PRODUCT_NAME"/> dans un environnement de bureau pris en charge, les paramètres proxy du système sont utilisés. Toutefois, soit votre système n'est pas pris en charge, soit un problème est survenu lors du lancement de votre configuration système.&lt;/p&gt;
-+
-+ &lt;p&gt;Vous avez toujours la possibilité d'effectuer la configuration via la ligne de commande. Pour plus d'informations sur les indicateurs et les variables d'environnement, veuillez vous reporter à &lt;code&gt;man <ph name="PRODUCT_BINARY_NAME"/>&lt;/code&gt;.&lt;/p&gt;</translation>
-+<translation id="9071590393348537582">La page Web à l'adresse <ph name="URL"/> a déclenché trop de redirections. Pour résoudre le problème, effacez les cookies de ce site ou autorisez les cookies tiers. Si le problème persiste, il peut être dû à une mauvaise configuration du serveur et n'être aucunement lié à votre ordinateur.</translation>
-+<translation id="7205869271332034173">SSID :</translation>
-+<translation id="7084579131203911145">Nom du forfait :</translation>
-+<translation id="5815645614496570556">Adresse X.400</translation>
-+<translation id="3551320343578183772">Fermer l'onglet</translation>
-+<translation id="3345886924813989455">Impossible de trouver un navigateur pris en charge.</translation>
-+<translation id="74354239584446316">Le compte associé à la boutique en ligne est le suivant : <ph name="EMAIL_ADDRESS"/>. L'utilisation d'un autre compte pour la synchronisation provoque des erreurs.</translation>
-+<translation id="3712897371525859903">Enregistrer la p&amp;age sous...</translation>
-+<translation id="7926251226597967072"><ph name="PRODUCT_NAME"/> importe actuellement les éléments suivants à partir de <ph name="IMPORT_BROWSER_NAME"/> :</translation>
-+<translation id="2767649238005085901">Appuyez sur Entrée pour avancer et sur la touche de menu contextuel pour afficher l'historique</translation>
-+<translation id="8580634710208701824">Actualiser le cadre</translation>
-+<translation id="1018656279737460067">Annulé</translation>
-+<translation id="7606992457248886637">Autorités</translation>
-+<translation id="707392107419594760">Sélectionnez votre clavier :</translation>
-+<translation id="2007404777272201486">Signaler un problème...</translation>
-+<translation id="2390045462562521613">Ignorer ce réseau</translation>
-+<translation id="3348038390189153836">Nouveau matériel détecté</translation>
-+<translation id="1666788816626221136">Vous disposez de certificats qui n'appartiennent à aucune autre catégorie :</translation>
-+<translation id="4821935166599369261">&amp;Profilage activé</translation>
-+<translation id="1603914832182249871">(Navigation privée)</translation>
-+<translation id="7910768399700579500">&amp;Nouveau dossier</translation>
-+<translation id="7472639616520044048">Types MIME :</translation>
-+<translation id="2307164895203900614">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
-+<translation id="3192947282887913208">Fichiers audio</translation>
-+<translation id="6295535972717341389">Plug-ins</translation>
-+<translation id="8116190140324504026">Plus d'informations...</translation>
-+<translation id="7469894403370665791">Se connecter automatiquement à ce réseau</translation>
-+<translation id="4807098396393229769">Titulaire de la carte</translation>
-+<translation id="4094130554533891764">Elle peut désormais accéder à :</translation>
-+<translation id="4131410914670010031">Noir et blanc</translation>
-+<translation id="3800503346337426623">Ignorer la connexion et naviguer en tant qu'invité</translation>
-+<translation id="2615413226240911668">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer l'aspect et le comportement de cette page.</translation>
-+<translation id="5880867612172997051">Accès réseau interrompu</translation>
-+<translation id="7842346819602959665">La dernière version de l'extension &quot;<ph name="EXTENSION_NAME"/>&quot; requiert d'autres permissions. Elle a donc été désactivée.</translation>
-+<translation id="3776667127601582921">Dans ce cas, le certificat du serveur ou un certificat d'autorité intermédiaire présenté à votre navigateur n'est pas valide. Cela peut signifier que le certificat est incorrect, qu'il contient des champs non valides ou qu'il n'est pas compatible.</translation>
-+<translation id="2412835451908901523">Veuillez saisir la clé de déverrouillage du code PIN à 8 chiffres fournie par <ph name="CARRIER_ID"/>.</translation>
-+<translation id="6979448128170032817">Exceptions...</translation>
-+<translation id="7584802760054545466">Connexion à <ph name="NETWORK_ID"/></translation>
-+<translation id="208047771235602537">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors qu'un téléchargement est en cours ?</translation>
-+<translation id="4060383410180771901">Le site Web ne parvient pas à gérer la demande associée à <ph name="URL"/>.</translation>
-+<translation id="6710213216561001401">Précédent</translation>
-+<translation id="1108600514891325577">&amp;Arrêter</translation>
-+<translation id="6035087343161522833">Lorsque l'option permettant de bloquer l'enregistrement des cookies tiers est activée, la lecture de ces cookies est également bloquée.</translation>
-+<translation id="8619892228487928601"><ph name="CERTIFICATE_NAME"/> : <ph name="ERROR"/></translation>
-+<translation id="1567993339577891801">Console JavaScript</translation>
-+<translation id="1548132948283577726">Les sites pour lesquels vos mots de passe ne seront jamais enregistrés s'afficheront ici.</translation>
-+<translation id="583281660410589416">Inconnu</translation>
-+<translation id="3774278775728862009">Mode de saisie du thaï (clavier TIS-820.2538)</translation>
-+<translation id="9115675100829699941">&amp;Favoris</translation>
-+<translation id="2485422356828889247">Désinstaller</translation>
-+<translation id="2621889926470140926">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors que <ph name="DOWNLOAD_COUNT"/> téléchargements sont en cours ?</translation>
-+<translation id="7279701417129455881">Configurer le blocage des cookies...</translation>
-+<translation id="1166359541137214543">ABC</translation>
-+<translation id="5412713837047574330">L'application hébergée par <ph name="HOST_NAME"/> est inaccessible, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
-+<translation id="5528368756083817449">Gestionnaire de favoris</translation>
-+<translation id="7275974018215686543"><ph name="NUMBER_MANY"/> secs ago</translation>
-+<translation id="215753907730220065">Quitter le mode plein écran</translation>
-+<translation id="7849264908733290972">Ouvrir l'&amp;image dans un nouvel onglet</translation>
-+<translation id="1560991001553749272">Favori ajouté !</translation>
-+<translation id="3966072572894326936">Choisir un autre dossier...</translation>
-+<translation id="8766796754185931010">Kotoeri</translation>
-+<translation id="7781829728241885113">Hier</translation>
-+<translation id="2762402405578816341">Synchroniser automatiquement les éléments suivants :</translation>
-+<translation id="1623661092385839831">Votre ordinateur intègre un périphérique de sécurité TPM (module de plate-forme sécurisée) qui permet de mettre en œuvre plusieurs fonctionnalités de sécurité critiques dans Google Chrome OS.</translation>
-+<translation id="3359256513598016054">Contraintes des stratégies de certificat</translation>
-+<translation id="4433914671537236274">Créer un support de récupération</translation>
-+<translation id="4509345063551561634">Emplacement :</translation>
-+<translation id="7596288230018319236">Toutes les pages que vous consultez apparaîtront ici à moins que vous ne les ouvriez dans une fenêtre en navigation privée. Vous pouvez utiliser le bouton Rechercher de cette page pour rechercher dans toutes les pages de votre historique.</translation>
-+<translation id="7434509671034404296">Options pour les développeurs</translation>
-+<translation id="6447842834002726250">Cookies</translation>
-+<translation id="2609371827041010694">Toujours exécuter pour ce site</translation>
-+<translation id="5170568018924773124">Afficher le dossier</translation>
-+<translation id="883848425547221593">Autres favoris</translation>
-+<translation id="6054173164583630569">Clavier français</translation>
-+<translation id="4870177177395420201"><ph name="PRODUCT_NAME"/> ne parvient pas à déterminer ou à définir le navigateur par défaut.</translation>
-+<translation id="8898786835233784856">Sélectionner l'onglet suivant</translation>
-+<translation id="2674170444375937751">Voulez-vous vraiment supprimer ces pages de votre historique ?</translation>
-+<translation id="9111102763498581341">Déverrouiller</translation>
-+<translation id="289695669188700754">ID de clé : <ph name="KEY_ID"/></translation>
-+<translation id="3067198360141518313">Exécuter ce plug-in</translation>
-+<translation id="8767072502252310690">Utilisateurs</translation>
-+<translation id="683526731807555621">Ajouter un moteur</translation>
-+<translation id="6871644448911473373">Répondeur OCSP : <ph name="LOCATION"/></translation>
-+<translation id="8281886186245836920">Ignorer</translation>
-+<translation id="3867944738977021751">Champs de certificat</translation>
-+<translation id="2114224913786726438">Modules (<ph name="TOTAL_COUNT"/>) : aucun conflit détecté.</translation>
-+<translation id="7629827748548208700">Onglet : <ph name="TAB_NAME"/></translation>
-+<translation id="388442998277590542">Impossible de charger la page d'options &quot;<ph name="OPTIONS_PAGE"/>&quot;.</translation>
-+<translation id="8449008133205184768">Coller en adaptant le style</translation>
-+<translation id="9114223350847410618">Veuillez ajouter une autre langue avant de supprimer celle-ci.</translation>
-+<translation id="4408427661507229495">nom du réseau</translation>
-+<translation id="8886960478266132308"><ph name="PRODUCT_NAME"/> synchronise de manière sécurisée vos données avec votre compte Google.</translation>
-+<translation id="8028993641010258682">Taille</translation>
-+<translation id="5031603669928715570">Activer...</translation>
-+<translation id="1383876407941801731">Recherche</translation>
-+<translation id="8398877366907290961">Poursuivre quand même</translation>
-+<translation id="5063180925553000800">Nouveau code PIN :</translation>
-+<translation id="2496540304887968742">La capacité du périphérique doit être d'au moins 4 Go.</translation>
-+<translation id="6974053822202609517">De droite à gauche</translation>
-+<translation id="2370882663124746154">Activer le mode Pinyin double</translation>
-+<translation id="5463856536939868464">Menu contenant des favoris masqués</translation>
-+<translation id="8286227656784970313">Utiliser le dictionnaire système</translation>
-+<translation id="5431084084184068621">Vous avez choisi de chiffrer les données à l'aide de votre mot de passe Google. Vous pouvez modifier vos paramètres de synchronisation à tout moment, si vous changez d'avis.</translation>
-+<translation id="1493263392339817010">Personnaliser les polices...</translation>
-+<translation id="5352033265844765294">Enregistrement des informations de date</translation>
-+<translation id="6449085810994685586">&amp;Vérifier l'orthographe du texte de ce champ</translation>
-+<translation id="3621320549246006887">Ceci est un modèle expérimental qui permet aux enregistrements DNS (utilisant le protocole de sécurité DNSSEC) d'autoriser ou de refuser des certificats HTTPS. Ce message s'affiche lorsque vous activez des fonctionnalités expérimentales via des options de ligne de commande. Vous pouvez supprimer ces options de ligne de commande pour ignorer cette erreur.</translation>
-+<translation id="50960180632766478"><ph name="NUMBER_FEW"/> minutes restantes</translation>
-+<translation id="3174168572213147020">Île</translation>
-+<translation id="748138892655239008">Contraintes de base du certificat</translation>
-+<translation id="457386861538956877">Autres...</translation>
-+<translation id="8063491445163840780">Activer l'onglet 4</translation>
-+<translation id="5966654788342289517">Données personnelles</translation>
-+<translation id="9137013805542155359">Afficher l'original</translation>
-+<translation id="4792385443586519711">Nom de la société</translation>
-+<translation id="6423731501149634044">Définir Adobe Reader comme visionneuse de documents PDF par défaut ?</translation>
-+<translation id="8839907368860424444">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Fenêtre.</translation>
-+<translation id="2461687051570989462">Accédez à vos imprimantes depuis n'importe quel ordinateur ou smartphone. <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/></translation>
-+<translation id="7194430665029924274">Me &amp;le rappeler plus tard</translation>
-+<translation id="5790085346892983794">Opération réussie !</translation>
-+<translation id="1901769927849168791">Carte SD détectée.</translation>
-+<translation id="818454486170715660"><ph name="NAME"/> - Propriétaire</translation>
-+<translation id="1358032944105037487">Clavier japonais</translation>
-+<translation id="8201956630388867069">WPA</translation>
-+<translation id="603890000178803545">janv.^févr.^mars^avr.^mai^juin^juil.^août^sept.^oct.^nov.^déc.</translation>
-+<translation id="8302838426652833913">Sélectionnez
-+ <ph name="BEGIN_BOLD"/>
-+ Applications &gt; Préférences système &gt; Réseau &gt; Assistant
-+ <ph name="END_BOLD"/>
-+ pour tester votre connexion.</translation>
-+<translation id="8664389313780386848">&amp;Afficher le code source de la page</translation>
-+<translation id="8970407809569722516">Micrologiciel :</translation>
-+<translation id="1180549724812639004">Créer un profil</translation>
-+<translation id="57646104491463491">Date de modification</translation>
-+<translation id="5992752872167177798">Sandbox seccomp</translation>
-+<translation id="6362853299801475928">Signale&amp;r un problème...</translation>
-+<translation id="3289566588497100676">Entrée de symboles simplifiée</translation>
-+<translation id="6507969014813375884">Chinois simplifié</translation>
-+<translation id="7314244761674113881">Hôte SOCKS</translation>
-+<translation id="5285794783728826432">Considérer ce certificat comme fiable pour identifier les sites Web.</translation>
-+<translation id="4224803122026931301">Exceptions de localisation</translation>
-+<translation id="749452993132003881">Hiragana</translation>
-+<translation id="8226742006292257240">Le mot de passe TPM ci-dessous, généré de façon aléatoire, a été attribué à votre ordinateur :</translation>
-+<translation id="8487693399751278191">Importer mes favoris maintenant...</translation>
-+<translation id="7985242821674907985"><ph name="PRODUCT_NAME"/></translation>
-+<translation id="7484580869648358686">Avertissement : Un problème a été détecté sur cette page.</translation>
-+<translation id="2074739700630368799">Avec Google Chrome OS for business, vous pouvez connecter votre périphérique à Google Apps, ce qui vous permet de le rechercher et de le contrôler depuis le panneau de configuration de Google Apps.</translation>
-+<translation id="4474155171896946103">Ajouter tous les onglets aux favoris...</translation>
-+<translation id="5895187275912066135">Émis le</translation>
-+<translation id="1190844492833803334">Lorsque je ferme le navigateur</translation>
-+<translation id="5646376287012673985">Localisation</translation>
-+<translation id="1110155001042129815">Attendre</translation>
-+<translation id="2607101320794533334">Infos sur la clé publique de l'objet</translation>
-+<translation id="7071586181848220801">Plug-in inconnu</translation>
-+<translation id="3354601307791487577">Connexion en mode invité</translation>
-+<translation id="4419409365248380979">Toujours autoriser <ph name="HOST"/> à paramétrer les cookies</translation>
-+<translation id="2956070106555335453">Résumé</translation>
-+<translation id="917450738466192189">Le certificat du serveur n'est pas valide.</translation>
-+<translation id="2649045351178520408">Chaîne de certificats codés Base 64 ASCII</translation>
-+<translation id="7424526482660971538">Choisir mon propre mot de passe multiterme</translation>
-+<translation id="380271916710942399">Certificat de serveur non répertorié</translation>
-+<translation id="6459488832681039634">Rechercher la sélection</translation>
-+<translation id="2392369802118427583">Activer</translation>
-+<translation id="9040421302519041149">L'accès à ce réseau est protégé.</translation>
-+<translation id="5659593005791499971">E-mail</translation>
-+<translation id="8235325155053717782">Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
-+<translation id="6584878029876017575">Signature permanente Microsoft</translation>
-+<translation id="562901740552630300">Sélectionnez
-+ <ph name="BEGIN_BOLD"/>
-+ Démarrer &gt; Panneau de configuration &gt; Réseau et Internet &gt; Centre Réseau et partage &gt; Résolution des problèmes (en bas) &gt; Connexions Internet.
-+ <ph name="END_BOLD"/></translation>
-+<translation id="8816996941061600321">Gestionnaire de &amp;fichiers</translation>
-+<translation id="2773223079752808209">Service client</translation>
-+<translation id="4585473702689066695">Impossible de se connecter au réseau &quot;<ph name="NAME"/>&quot;.</translation>
-+<translation id="4647175434312795566">J'accepte ces termes</translation>
-+<translation id="1084824384139382525">Copier l'adr&amp;esse du lien</translation>
-+<translation id="1221462285898798023">Veuillez démarrer <ph name="PRODUCT_NAME"/> en tant qu'utilisateur normal. Pour l'exécuter en tant que root, vous devez indiquer un autre répertoire de données utilisateur pour stocker les informations du profil.</translation>
-+<translation id="3220586366024592812">Le processus du connecteur <ph name="CLOUD_PRINT_NAME"/> est bloqué. Voulez-vous le redémarrer ?</translation>
-+<translation id="5042992464904238023">Contenu Web</translation>
-+<translation id="6254503684448816922">Clé compromise</translation>
-+<translation id="1181037720776840403">Supprimer</translation>
-+<translation id="4006726980536015530">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, ces téléchargements seront annulés.</translation>
-+<translation id="4194415033234465088">Dachen 26</translation>
-+<translation id="1664712100580477121">Voulez-vous vraiment graver l'image sur le périphérique suivant :</translation>
-+<translation id="6639554308659482635">Mémoire SQLite</translation>
-+<translation id="8141503649579618569"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, <ph name="TIME_LEFT"/></translation>
-+<translation id="7650701856438921772"><ph name="PRODUCT_NAME"/> est affiché dans cette langue.</translation>
-+<translation id="740624631517654988">Fenêtre pop-up bloquée</translation>
-+<translation id="3738924763801731196"><ph name="OID"/> :</translation>
-+<translation id="6550769511678490130">Ouvrir tous les favoris</translation>
-+<translation id="1847961471583915783">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
-+<translation id="8870318296973696995">Page d'accueil</translation>
-+<translation id="6659594942844771486">Onglet</translation>
-+<translation id="6575134580692778371">Non configuré</translation>
-+<translation id="4624768044135598934">Opération réussie !</translation>
-+<translation id="6014776969142880350">Relancez <ph name="PRODUCT_NAME"/> pour terminer la mise à jour.</translation>
-+<translation id="5582768900447355629">Chiffrer toutes mes données</translation>
-+<translation id="6122365914076864562">Veuillez patienter pendant que nous configurons votre réseau pour mobile.</translation>
-+<translation id="1974043046396539880">Points de distribution de listes de révocation des certificats</translation>
-+<translation id="7049357003967926684">Association</translation>
-+<translation id="8641392906089904981">Appuyez sur Maj+Alt pour changer la disposition du clavier.</translation>
-+<translation id="3024374909719388945">Utiliser l'horloge au format 24 heures</translation>
-+<translation id="1867780286110144690"><ph name="PRODUCT_NAME"/> est prêt à terminer l'installation.</translation>
-+<translation id="5316814419223884568">Lancez votre recherche à partir d'ici</translation>
-+<translation id="8142732521333266922">OK, synchroniser tout</translation>
-+<translation id="965674096648379287">Afin d'être correctement affichée, cette page requiert des données que vous avez précédemment entrées. Vous pouvez de nouveau transmettre ces données, mais, en procédant ainsi, vous devrez répéter chaque action que cette page a effectuée auparavant. Cliquez sur Rafraîchir pour transmettre de nouveau ces données et pour afficher cette page.</translation>
-+<translation id="43742617823094120">Cela signifie que le certificat présenté à votre navigateur a été révoqué par son émetteur. L'intégrité de ce certificat a certainement été compromise, et il ne doit donc pas être approuvé. Ne poursuivez pas.</translation>
-+<translation id="9019654278847959325">Clavier slovaque</translation>
-+<translation id="18139523105317219">Nom de partie EDI</translation>
-+<translation id="6657193944556309583">Vous avez déjà chiffré des données avec un mot de passe multiterme. Saisissez-le ci-dessous.</translation>
-+<translation id="3328801116991980348">Informations sur le site</translation>
-+<translation id="1205605488412590044">Créer un raccourci vers l'application...</translation>
-+<translation id="2065985942032347596">Authentification requise</translation>
-+<translation id="2553340429761841190"><ph name="PRODUCT_NAME"/> n'est pas parvenu à se connecter à <ph name="NETWORK_ID"/>. Sélectionnez un autre réseau ou réessayez.</translation>
-+<translation id="2086712242472027775">Votre compte n'est pas compatible avec <ph name="PRODUCT_NAME"/>. Contactez l'administrateur de votre domaine ou utilisez un compte Google standard pour vous connecter.</translation>
-+<translation id="7222232353993864120">Adresse e-mail</translation>
-+<translation id="2128531968068887769">Client natif</translation>
-+<translation id="7175353351958621980">Chargé depuis :</translation>
-+<translation id="4590074117005971373">Active les balises canvas hautes performances dans un contexte 2D, pour effectuer le rendu via le processeur graphique.</translation>
-+<translation id="7186367841673660872">Cette page en<ph name="ORIGINAL_LANGUAGE"/>a été traduite en<ph name="LANGUAGE_LANGUAGE"/></translation>
-+<translation id="8448695406146523553">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez</translation>
-+<translation id="6052976518993719690">Autorité de certification SSL</translation>
-+<translation id="1636959874332483835"><ph name="HOST_NAME"/> contient un logiciel malveillant. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
-+<translation id="8050783156231782848">Aucune donnée disponible.</translation>
-+<translation id="1175364870820465910">Im&amp;primer...</translation>
-+<translation id="3866249974567520381">Description</translation>
-+<translation id="2900139581179749587">Voix non reconnue.</translation>
-+<translation id="953692523250483872">Aucun fichier sélectionné</translation>
-+<translation id="2294358108254308676">Souhaitez-vous installer <ph name="PRODUCT_NAME"/> ?</translation>
-+<translation id="6549689063733911810">Activité récente</translation>
-+<translation id="1529968269513889022">de la dernière semaine</translation>
-+<translation id="5542132724887566711">Profil</translation>
-+<translation id="5196117515621749903">Actualiser sans utiliser le cache</translation>
-+<translation id="5552632479093547648">Logiciels malveillants et sites de phishing détectés !</translation>
-+<translation id="4310537301481716192">Onglet fermé !</translation>
-+<translation id="4988273303304146523">il y a <ph name="NUMBER_DEFAULT"/> jours</translation>
-+<translation id="8428213095426709021">Paramètres</translation>
-+<translation id="1588343679702972132">Ce site exige que vous vous identifiiez avec un certificat :</translation>
-+<translation id="7211994749225247711">Supprimer...</translation>
-+<translation id="2819994928625218237">&amp;Aucune suggestion orthographique</translation>
-+<translation id="1065449928621190041">Clavier franco-canadien</translation>
-+<translation id="8327626790128680264">Clavier étendu américain</translation>
-+<translation id="2950186680359523359">Le serveur a mis fin à la connexion sans envoyer de données.</translation>
-+<translation id="9142623379911037913">Autoriser <ph name="SITE"/> à afficher des notifications sur le Bureau ?</translation>
-+<translation id="4196320913210960460">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Outils.</translation>
-+<translation id="3449494395612243720">Erreur de synchronisation, veuillez vous connecter à nouveau.</translation>
-+<translation id="9118804773997839291">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur un élément particulier.</translation>
-+<translation id="7139724024395191329">Émirat</translation>
-+<translation id="1761265592227862828">Synchroniser tous les paramètres et toutes les données\n(peut prendre un certain temps)</translation>
-+<translation id="7754704193130578113">Toujours demander où enregistrer les fichiers</translation>
-+<translation id="204914487372604757">Créer un raccourci</translation>
-+<translation id="2497284189126895209">Tous les fichiers</translation>
-+<translation id="696036063053180184">Sebeol-sik No-shift</translation>
-+<translation id="452785312504541111">Anglais (pleine chasse)</translation>
-+<translation id="945332329539165145">2D avec canvas et accélération matérielle</translation>
-+<translation id="5220797120063118010">Cette fonctionnalité autorise l'installation d'applications Google Chrome déployées à partir d'un manifeste situé sur une page Web, plutôt qu'avec un fichier crx contenant le manifeste et les icônes.</translation>
-+<translation id="9148126808321036104">Nouvelle connexion</translation>
-+<translation id="2282146716419988068">GPU</translation>
-+<translation id="428771275901304970">Moins de 1 Mo disponible</translation>
-+<translation id="1682548588986054654">Nouvelle fenêtre de navigation privée</translation>
-+<translation id="6833901631330113163">Europe du Sud</translation>
-+<translation id="8691262314411702087">Sélectionner les éléments à synchroniser</translation>
-+<translation id="6065289257230303064">Attributs du répertoire de l'objet du certificat</translation>
-+<translation id="2423017480076849397">Accédez à vos imprimantes et partagez-les en ligne via <ph name="CLOUD_PRINT_NAME"/>.</translation>
-+<translation id="569520194956422927">&amp;Ajouter...</translation>
-+<translation id="4018133169783460046">Afficher <ph name="PRODUCT_NAME"/> dans cette langue</translation>
-+<translation id="5110450810124758964">il y a <ph name="NUMBER_ONE"/> jour</translation>
-+<translation id="3264544094376351444">Police Sans-Serif</translation>
-+<translation id="5586942249556966598">Ne rien faire</translation>
-+<translation id="2820806154655529776"><ph name="NUMBER_ONE"/> seconde</translation>
-+<translation id="1077946062898560804">Configurer les mises à jour automatiques pour tous les utilisateurs</translation>
-+<translation id="3122496702278727796">Échec de la création du répertoire des données</translation>
-+<translation id="4517036173149081027">Fermer et annuler le chargement</translation>
-+<translation id="7150146631451105528"><ph name="DATE"/></translation>
-+<translation id="3166547286524371413">Adresse :</translation>
-+<translation id="4522570452068850558">Détails</translation>
-+<translation id="59659456909144943">Notification : <ph name="NOTIFICATION_NAME"/></translation>
-+<translation id="6731320427842222405">Cette opération peut prendre quelques minutes.</translation>
-+<translation id="4806525999832945986">Géré par <ph name="DOMAIN"/> (<ph name="STATUS"/>)</translation>
-+<translation id="7503191893372251637">Type de certificat Netscape</translation>
-+<translation id="1502960562739459116">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous installer Adobe Reader ?</translation>
-+<translation id="4135450933899346655">Vos certificats</translation>
-+<translation id="4731578803613910821">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et <ph name="WEBSITE_3"/></translation>
-+<translation id="7716781361494605745">URL de stratégie de l'autorité de certification Netscape</translation>
-+<translation id="2881966438216424900">Dernier accès :</translation>
-+<translation id="7552203043556919163">Synchroniser les mots de passe</translation>
-+<translation id="630065524203833229">&amp;Quitter</translation>
-+<translation id="4647090755847581616">&amp;Fermer l'onglet</translation>
-+<translation id="2649204054376361687"><ph name="CITY"/>, <ph name="COUNTRY"/></translation>
-+<translation id="7886758531743562066">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur.</translation>
-+<translation id="2064746092913005102">Total : <ph name="NUMBER_OF_PAGES"/> <ph name="PAGE_OR_PAGES_LABEL"/> <ph name="TWO_SIDED"/> <ph name="TIMES"/> <ph name="NUMBER_OF_COPIES"/> <ph name="COPIES_LABEL"/> <ph name="EQUAL_SIGN"/> <ph name="NUMBER_OF_SHEETS"/> <ph name="SHEETS_LABEL"/></translation>
-+<translation id="7538227655922918841">Les cookies de plusieurs sites ont été autorisés pour la session uniquement.</translation>
-+<translation id="2385700042425247848">Nom du service :</translation>
-+<translation id="7751005832163144684">Imprimer une page de test</translation>
-+<translation id="3638865692466101147">Aperçu avant impression - <ph name="PREVIEW_TAB_TITLE"/></translation>
-+<translation id="1471300011765310414"><ph name="PRODUCT_NAME"/>
-+ ne peut pas à afficher la page Web, car votre ordinateur n'est pas connecté à Internet.</translation>
-+<translation id="5464632865477611176">Exécuter cette fois</translation>
-+<translation id="4268025649754414643">Chiffrement de la clé</translation>
-+<translation id="7925247922861151263">Échec de la vérification AAA</translation>
-+<translation id="1168020859489941584">Ouverture dans <ph name="TIME_REMAINING"/>...</translation>
-+<translation id="7814458197256864873">&amp;Copier</translation>
-+<translation id="8186706823560132848">Logiciel</translation>
-+<translation id="4692623383562244444">Moteurs de recherche</translation>
-+<translation id="567760371929988174">&amp;Méthodes d'entrée</translation>
-+<translation id="10614374240317010">Jamais enregistrés</translation>
-+<translation id="5116300307302421503">Impossible d'analyser le fichier.</translation>
-+<translation id="2745080116229976798">Subordination qualifiée Microsoft</translation>
-+<translation id="2526590354069164005">Bureau</translation>
-+<translation id="7983301409776629893">Toujours traduire en <ph name="TARGET_LANGUAGE"/> les pages en <ph name="ORIGINAL_LANGUAGE"/></translation>
-+<translation id="4890284164788142455">Thaï</translation>
-+<translation id="4312207540304900419">Activer l'onglet suivant</translation>
-+<translation id="8456362689280298700"><ph name="HOUR"/>:<ph name="MINUTE"/> de chargement</translation>
-+<translation id="7648048654005891115">Style de mappage du clavier</translation>
-+<translation id="539295039523818097">Un problème lié à votre microphone s'est produit.</translation>
-+<translation id="4033319557821527966"><ph name="CLOUD_PRINT_NAME"/> vous permet d'accéder aux imprimantes de cet ordinateur, où que vous soyez. Connectez-vous pour l'activer.</translation>
-+<translation id="6970216967273061347">District</translation>
-+<translation id="4479639480957787382">Ethernet</translation>
-+<translation id="6312403991423642364">Erreur de réseau inconnue.</translation>
-+<translation id="751377616343077236">Nom du certificat</translation>
-+<translation id="7154108546743862496">Plus d'informations</translation>
-+<translation id="8637688295594795546">Mise à jour du système disponible. Préparation du téléchargement…</translation>
-+<translation id="5167270755190684957">Galerie des thèmes Google Chrome</translation>
-+<translation id="8382913212082956454">Copi&amp;er l'adresse e-mail</translation>
-+<translation id="7447930227192971403">Activer l'onglet 3</translation>
-+<translation id="2903493209154104877">Adresses</translation>
-+<translation id="2056143100006548702">Plug-in : <ph name="PLUGIN_NAME"/> (<ph name="PLUGIN_VERSION"/>)</translation>
-+<translation id="3479552764303398839">Pas maintenant</translation>
-+<translation id="6445051938772793705">Pays</translation>
-+<translation id="3251759466064201842">&lt;Ne fait pas partie du certificat&gt;</translation>
-+<translation id="4229495110203539533">il y a <ph name="NUMBER_ONE"/> seconde</translation>
-+<translation id="6410257289063177456">Fichiers image</translation>
-+<translation id="6419902127459849040">Europe centrale</translation>
-+<translation id="6707389671160270963">Certificat client SSL</translation>
-+<translation id="6083557600037991373">Pour accélérer l'affichage des pages Web,
-+ <ph name="PRODUCT_NAME"/>
-+ enregistre temporairement les fichiers téléchargés sur le disque. Si
-+ <ph name="PRODUCT_NAME"/>
-+ ne s'arrête pas correctement, ces fichiers peuvent être endommagés, ce qui
-+ génère cette erreur. L'actualisation de la page devrait permettre de résoudre
-+ ce problème ; celui-ci ne se reproduira vraisemblablement plus si l'arrêt s'effectue
-+ correctement.
-+ <ph name="LINE_BREAK"/>
-+ Si le problème persiste, essayez de supprimer le contenu du cache. Cette
-+ erreur peut aussi indiquer que le matériel est sur le point de tomber
-+ en panne.</translation>
-+<translation id="5298219193514155779">Thème créé par</translation>
-+<translation id="7366909168761621528">Données de navigation</translation>
-+<translation id="1047726139967079566">Ajouter cette page aux favoris</translation>
-+<translation id="9020142588544155172">Le serveur a refusé la connexion.</translation>
-+<translation id="6113225828180044308">Module (<ph name="MODULUS_NUM_BITS"/> bits) :\n<ph name="MODULUS_HEX_DUMP"/>\n\nExposant public (<ph name="PUBLIC_EXPONENT_NUM_BITS"/> bits) :\n<ph name="EXPONENT_HEX_DUMP"/></translation>
-+<translation id="2544782972264605588"><ph name="NUMBER_DEFAULT"/> secondes restantes</translation>
-+<translation id="8871696467337989339">Vous utilisez un indicateur de ligne de commande non pris en charge : <ph name="BAD_FLAG"/>. La stabilité et la sécurité en seront affectées.</translation>
-+<translation id="4767443964295394154">Emplacement de téléchargement</translation>
-+<translation id="5031870354684148875">À propos de Google Traduction</translation>
-+<translation id="720658115504386855">Les lettres ne sont pas sensibles à la casse.</translation>
-+<translation id="2454247629720664989">Mot clé</translation>
-+<translation id="3950820424414687140">Connexion</translation>
-+<translation id="4626106357471783850">Redémarrez <ph name="PRODUCT_NAME"/> pour appliquer la mise à jour.</translation>
-+<translation id="1697068104427956555">Sélectionner un carré dans l'image</translation>
-+<translation id="2840798130349147766">Bases de données Web</translation>
-+<translation id="1628736721748648976">Codage</translation>
-+<translation id="1198271701881992799">Mise en route</translation>
-+<translation id="782590969421016895">Utiliser les pages actuelles</translation>
-+<translation id="6521850982405273806">Signaler une erreur</translation>
-+<translation id="736515969993332243">Recherche de réseaux en cours</translation>
-+<translation id="8026334261755873520">Effacer les données de navigation</translation>
-+<translation id="1769104665586091481">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
-+<translation id="8503813439785031346">Nom d'utilisateur</translation>
-+<translation id="5319782540886810524">Clavier letton</translation>
-+<translation id="8651585100578802546">Forcer l'actualisation de cette page</translation>
-+<translation id="685714579710025096">Disposition du clavier :</translation>
-+<translation id="1361655923249334273">Non utilisé</translation>
-+<translation id="290555789621781773"><ph name="NUMBER_TWO"/> minutes</translation>
-+<translation id="5434065355175441495">Chiffrement RSA PKCS #1</translation>
-+<translation id="7073704676847768330">Ce n'est probablement pas le site que vous recherchez !</translation>
-+<translation id="8477384620836102176">&amp;Général</translation>
-+<translation id="1074663319790387896">Configurer la synchronisation</translation>
-+<translation id="4302315780171881488">État de connexion :</translation>
-+<translation id="3391392691301057522">Ancien code PIN :</translation>
-+<translation id="1344519653668879001">Désactiver le contrôle des liens hypertexte</translation>
-+<translation id="6463795194797719782">&amp;Modifier</translation>
-+<translation id="4262113024799883061">Chinois</translation>
-+<translation id="4775879719735953715">Navigateur par défaut</translation>
-+<translation id="5575473780076478375">Extension en mode navigation privée :<ph name="EXTENSION_NAME"/></translation>
-+<translation id="4188026131102273494">Mot clé :</translation>
-+<translation id="2930644991850369934">Un problème est survenu lors du téléchargement de l'image de récupération. La connexion réseau a été perdue.</translation>
-+<translation id="3461610253915486539">Votre administrateur a désactivé certaines préférences.</translation>
-+<translation id="5750053751252005701">Forfait de données <ph name="NETWORK"/> épuisé</translation>
-+<translation id="8858939932848080433">Veuillez indiquer à quel niveau vous rencontrez des problèmes avant d'envoyer vos commentaires.</translation>
-+<translation id="1720318856472900922">Authentification du serveur WWW TLS</translation>
-+<translation id="8550022383519221471">Le service de synchronisation n'est pas disponible pour votre domaine.</translation>
-+<translation id="3355823806454867987">Modifier les paramètres du proxy...</translation>
-+<translation id="4780374166989101364">Cette fonctionnalité active les API des extensions expérimentales. Notez que vous ne pouvez pas mettre en ligne des extensions qui font appel aux API expérimentales dans la galerie d'extensions.</translation>
-+<translation id="7227780179130368205">Un logiciel malveillant a été détecté !</translation>
-+<translation id="435243347905038008">Forfait de données <ph name="NETWORK"/> presque épuisé</translation>
-+<translation id="2489428929217601177">des dernières 24 heures</translation>
-+<translation id="7418490403869327287">Une fois activée, la recherche instantanée charge la plupart des pages Web dès que vous saisissez l'URL dans le champ polyvalent, avant même que vous n'appuyiez sur Entrée. Si votre moteur de recherche par défaut est compatible, toute lettre saisie dans ce champ offre de nouveaux résultats et les prédictions intégrées vous guident dans vos recherches.\n\nChaque touche utilisée fait l'objet d'une requête, par conséquent il se peut que les éléments saisies dans le champ polyvalent soient enregistrés par votre moteur de recherche par défaut.\n</translation>
-+<translation id="5149131957118398098"><ph name="NUMBER_ZERO"/> hours left</translation>
-+<translation id="2541913031883863396">poursuivre quand même</translation>
-+<translation id="4278390842282768270">Autorisé</translation>
-+<translation id="2074527029802029717">Retirer l'onglet</translation>
-+<translation id="1533897085022183721">Moins de <ph name="MINUTES"/></translation>
-+<translation id="7503821294401948377">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action du navigateur.</translation>
-+<translation id="5539694491979265537">Consulter Google Dashboard</translation>
-+<translation id="3942946088478181888">Plus d'informations</translation>
-+<translation id="3722396466546931176">Ajoutez des langues puis faites-les glisser pour les classer dans l'ordre souhaité.</translation>
-+<translation id="7396845648024431313"><ph name="APP_NAME"/> sera lancé au démarrage du système et continuera de s'exécuter en arrière-plan, même toutes les fenêtres de <ph name="PRODUCT_NAME"/> sont fermées.</translation>
-+<translation id="8539727552378197395">Non (HttpOnly)</translation>
-+<translation id="4519351128520996510">Saisir votre mot de passe multiterme pour la synchronisation</translation>
-+<translation id="2391419135980381625">Police standard</translation>
-+<translation id="7893393459573308604"><ph name="ENGINE_NAME"/> (par défaut)</translation>
-+<translation id="5392544185395226057">Cette fonctionnalité active la prise en charge du client natif.</translation>
-+<translation id="5400640815024374115">La puce du module de plate-forme sécurisée (TPM) est désactivée ou inexistante.</translation>
-+<translation id="2151576029659734873">L'index de l'onglet indiqué est incorrect.</translation>
-+<translation id="5150254825601720210">Nom du serveur SSL du certificat Netscape</translation>
-+<translation id="6771503742377376720">Est une autorité de certification</translation>
-+<translation id="8814190375133053267">Wi-Fi</translation>
-+<translation id="2040078585890208937">Connexion à <ph name="NAME"/></translation>
-+<translation id="8410619858754994443">Confirmer le mot de passe :</translation>
-+<translation id="2210840298541351314">Aperçu avant impression</translation>
-+<translation id="3858678421048828670">Clavier italien</translation>
-+<translation id="4938277090904056629">Impossible d'établir une connexion sécurisée à cause de l'antivirus ESET.</translation>
-+<translation id="4521805507184738876">(expiré)</translation>
-+<translation id="111844081046043029">Voulez-vous vraiment quitter cette page ?</translation>
-+<translation id="1951615167417147110">Faire défiler d'une page vers le haut</translation>
-+<translation id="4154664944169082762">Empreintes</translation>
-+<translation id="3202578601642193415">Le plus récent</translation>
-+<translation id="8112886015144590373"><ph name="NUMBER_FEW"/> heures</translation>
-+<translation id="1398853756734560583">Agrandir</translation>
-+<translation id="8988255471271407508">La page Web est introuvable dans le cache. Certaines ressources ne sont restituées fidèlement que si elles sont extraites du cache, notamment les pages générées à partir de données que vous avez envoyées. <ph name="LINE_BREAK"/> Cette erreur peut également être due à un cache endommagé lors d'une fermeture incorrecte. <ph name="LINE_BREAK"/> Si le problème persiste, essayez d'effacer le cache.</translation>
-+<translation id="1195977189444203128">Le plug-in <ph name="PLUGIN_NAME"/> n'est plus à jour.</translation>
-+<translation id="3878562341724547165">Vous avez changé de position. Souhaitez-vous utiliser <ph name="NEW_GOOGLE_URL"/> ?</translation>
-+<translation id="1758018619400202187">EAP-TLS</translation>
-+<translation id="6690744523875189208"><ph name="NUMBER_TWO"/> heures</translation>
-+<translation id="8053390638574070785">Rafraîchir cette page</translation>
-+<translation id="5507756662695126555">Non-répudiation</translation>
-+<translation id="3678156199662914018">Extension : <ph name="EXTENSION_NAME"/></translation>
-+<translation id="9194519262242876737">Active l'API Web audio.</translation>
-+<translation id="3531250013160506608">Zone de saisie de mot de passe</translation>
-+<translation id="8314066201485587418">Effacer les cookies et autres données de site lorsque je quitte le navigateur</translation>
-+<translation id="4094105377635924481">Ajouter l'option de regroupement au menu contextuel des onglets</translation>
-+<translation id="8655295600908251630">Version</translation>
-+<translation id="8250690786522693009">Latin</translation>
-+<translation id="2119721408814495896">Le connecteur <ph name="CLOUD_PRINT_NAME"/> requiert l'installation du pack Microsoft XML Paper Specification Essentials.</translation>
-+<translation id="7624267205732106503">Effacer les cookies et autres données de site lorsque je ferme le navigateur</translation>
-+<translation id="8401363965527883709">Case décochée</translation>
-+<translation id="7771452384635174008">Mise en page</translation>
-+<translation id="6188939051578398125">Saisir un nom ou une adresse</translation>
-+<translation id="8443621894987748190">Choix de l'image du compte</translation>
-+<translation id="10122177803156699">Me montrer</translation>
-+<translation id="5260878308685146029"><ph name="NUMBER_TWO"/> minutes restantes</translation>
-+<translation id="2192505247865591433">De :</translation>
-+<translation id="238391805422906964">Ouvrir un rapport de phishing</translation>
-+<translation id="5921544176073914576">Page de phishing</translation>
-+<translation id="3727187387656390258">Inspecter le pop-up</translation>
-+<translation id="569068482611873351">Importer...</translation>
-+<translation id="6571070086367343653">Modifier la carte de paiement</translation>
-+<translation id="1204242529756846967">Cette langue est utilisée pour corriger l'orthographe.</translation>
-+<translation id="3981760180856053153">Le type d'enregistrement indiqué est incorrect.</translation>
-+<translation id="8464591670878858520">Forfait de données <ph name="NETWORK"/> arrivé à expiration</translation>
-+<translation id="4568660204877256194">Exporter mes favoris...</translation>
-+<translation id="3116361045094675131">Clavier britannique</translation>
-+<translation id="4577070033074325641">Importer des favoris...</translation>
-+<translation id="1641504961675316934"><ph name="CLOUD_PRINT_NAME"/></translation>
-+<translation id="1715941336038158809">Nom d'utilisateur ou mot de passe incorrect</translation>
-+<translation id="1901303067676059328">&amp;Tout sélectionner</translation>
-+<translation id="674375294223700098">Erreur inconnue liée au certificat du serveur.</translation>
-+<translation id="7780428956635859355">Envoyer une capture d'écran enregistrée</translation>
-+<translation id="2850961597638370327">Émis pour : <ph name="NAME"/></translation>
-+<translation id="2168039046890040389">Page précédente</translation>
-+<translation id="1767519210550978135">Hsu</translation>
-+<translation id="2498539833203011245">Réduire</translation>
-+<translation id="2893168226686371498">Navigateur par défaut</translation>
-+<translation id="2435457462613246316">Afficher le mot de passe</translation>
-+<translation id="7988355189918024273">Activer les fonctionnalités d'accessibilité</translation>
-+<translation id="5438653034651341183">Inclure la capture d'écran actuelle :</translation>
-+<translation id="1899708097738826574"><ph name="OPTIONS_TITLE"/> - <ph name="SUBPAGE_TITLE"/></translation>
-+<translation id="1765313842989969521">(cette extension est gérée et ne peut être désinstallée ni désactivée)</translation>
-+<translation id="6983783921975806247">OID enregistré</translation>
-+<translation id="394984172568887996">Importés depuis IE</translation>
-+<translation id="5311260548612583999">Fichier de clé privée (facultatif) :</translation>
-+<translation id="2430043402233747791">Autoriser pour la session uniquement</translation>
-+<translation id="7363290921156020669"><ph name="NUMBER_ZERO"/> mins</translation>
-+<translation id="7568790562536448087">Mise à jour en cours</translation>
-+<translation id="4856408283021169561">Aucun microphone trouvé.</translation>
-+<translation id="8190193592390505034">Connexion à <ph name="PROVIDER_NAME"/></translation>
-+<translation id="6144890426075165477"><ph name="PRODUCT_NAME"/> n'est pas votre navigateur par défaut.</translation>
-+<translation id="823241703361685511">Forfait</translation>
-+<translation id="4068506536726151626">Cette page contient des éléments des sites ci-dessous qui suivent votre position géographique :</translation>
-+<translation id="4721475475128190282">Plusieurs profils</translation>
-+<translation id="4220128509585149162">Plantages</translation>
-+<translation id="8798099450830957504">Par défaut</translation>
-+<translation id="9107059250669762581"><ph name="NUMBER_DEFAULT"/> jours</translation>
-+<translation id="1640283014264083726">PKCS #1 MD4 avec chiffrement RSA</translation>
-+<translation id="872451400847464257">Modifier le moteur de recherche</translation>
-+<translation id="6463061331681402734"><ph name="NUMBER_MANY"/> minutes</translation>
-+<translation id="2466804342846034717">Indiquez le mot de passe approprié ci-dessus, puis saisissez les caractères figurant dans l'image ci-dessous.</translation>
-+<translation id="3881435075661337013">Expiration de <ph name="NETWORK"/> imminente</translation>
-+<translation id="5681833099441553262">Activer l'onglet précédent</translation>
-+<translation id="4792057643643237295">Désactiver l'accès à distance</translation>
-+<translation id="1681614449735360921">Afficher les incompatibilités</translation>
-+<translation id="19094784437781028">Carte de débit Solo</translation>
-+<translation id="2657327428424666237"><ph name="BEGIN_LINK"/>Actualisez<ph name="END_LINK"/> cette page Web ultérieurement.</translation>
-+<translation id="7347751611463936647">Pour utiliser cette extension, saisissez &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, TAB, puis votre commande ou votre recherche.</translation>
-+<translation id="659432221160402784"><ph name="PRODUCT_NAME"/> synchronisera les applications installées, afin que vous puissiez y accéder en vous connectant depuis tout navigateur <ph name="PRODUCT_NAME"/>.</translation>
-+<translation id="892464165639979917">Langues et paramètres du correcteur orthographique...</translation>
-+<translation id="5645845270586517071">Erreur de sécurité</translation>
-+<translation id="2805756323405976993">Applications</translation>
-+<translation id="3651020361689274926">La ressource demandée n'existe plus et aucune adresse de transfert n'est disponible. Il semble que cet état de fait soit permanent.</translation>
-+<translation id="2989786307324390836">Certificat unique binaire codé DER</translation>
-+<translation id="3827774300009121996">&amp;Plein écran</translation>
-+<translation id="3771294271822695279">Fichiers vidéo</translation>
-+<translation id="6704875430222476107"><ph name="PRODUCT_NAME"/> indique que
-+ NetNanny intercepte les connexions sécurisées. En général, cela
-+ ne constitue pas un problème de sécurité, car le logiciel NetNanny s'exécute souvent
-+ sur le même ordinateur. Toutefois, en raison de certaines incompatibilités avec
-+ les connexions sécurisées Google Chrome, vous devez configurer NetNanny
-+ de manière à éviter ces interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
-+<translation id="3388026114049080752">Vos onglets et activités de navigation</translation>
-+<translation id="7525067979554623046">Créer</translation>
-+<translation id="4711094779914110278">Turc</translation>
-+<translation id="1031460590482534116">Une erreur s'est produite lors de la tentative d'enregistrement du certificat client. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
-+<translation id="7136984461011502314">Bienvenue dans <ph name="PRODUCT_NAME"/></translation>
-+<translation id="1594030484168838125">Sélectionner</translation>
-+<translation id="204497730941176055">Nom du modèle de certificat Microsoft</translation>
-+<translation id="6705264787989366486">Configuration de l'adresse IP pour <ph name="NAME"/></translation>
-+<translation id="8970721300630048025">Immortalisez votre plus beau sourire et utilisez la photo comme image de compte.</translation>
-+<translation id="4087089424473531098">Extension créée :
-+
-+<ph name="EXTENSION_FILE"/></translation>
-+<translation id="16620462294541761">Mot de passe incorrect. Veuillez réessayer.</translation>
-+<translation id="5017508259293544172">LEAP</translation>
-+<translation id="1394630846966197578">Échec de la connexion aux serveurs de reconnaissance vocale.</translation>
-+<translation id="2498765460639677199">Très grande</translation>
-+<translation id="2378982052244864789">Sélectionner le répertoire de l'extension</translation>
-+<translation id="7861215335140947162">&amp;Téléchargements</translation>
-+<translation id="4778630024246633221">Gestionnaire des certificats</translation>
-+<translation id="6705050455568279082"><ph name="URL"/> souhaite suivre votre position géographique</translation>
-+<translation id="4708849949179781599">Quitter <ph name="PRODUCT_NAME"/></translation>
-+<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
-+<translation id="6644512095122093795">Proposer d'enregistrer les mots de passe</translation>
-+<translation id="4724450788351008910">Modification de l'affiliation</translation>
-+<translation id="2249605167705922988">par exemple : 1-5, 8, 11-13</translation>
-+<translation id="8691686986795184760">(Activé par une stratégie d'entreprise)</translation>
-+<translation id="1911483096198679472">Qu'est-ce que c'est ?</translation>
-+<translation id="1976323404609382849">Les cookies de plusieurs sites ont été bloqués.</translation>
-+<translation id="2662952950313424742">Serveur DNS spécifié par l'utilisateur et utilisé par Google Chrome, à la place du paramètre système par défaut, pour les résolutions DNS.</translation>
-+<translation id="4176463684765177261">Désactivé</translation>
-+<translation id="2079545284768500474">Annuler</translation>
-+<translation id="114140604515785785">Répertoire racine de l'extension :</translation>
-+<translation id="4788968718241181184">Mode de saisie du vietnamien (TCVN6064)</translation>
-+<translation id="1512064327686280138">Échec de l'activation</translation>
-+<translation id="3254409185687681395">Ajouter cette page aux favoris</translation>
-+<translation id="1384616079544830839">L'identité de ce site Web a été vérifiée par <ph name="ISSUER"/>.</translation>
-+<translation id="8710160868773349942">Adresse e-mail : <ph name="EMAIL_ADDRESSES"/></translation>
-+<translation id="4057991113334098539">Activation...</translation>
-+<translation id="9073281213608662541">PAP</translation>
-+<translation id="1800035677272595847">Sites de phishing</translation>
-+<translation id="8448317557906454022"><ph name="NUMBER_ZERO"/> secs ago</translation>
-+<translation id="402759845255257575">Interdire à tous les sites d'exécuter JavaScript</translation>
-+<translation id="4610637590575890427">Vouliez-vous accéder à <ph name="SITE"/> ?</translation>
-+<translation id="7723779034587221017">La connexion avec le service de configuration a été perdue. Veuillez réinitialiser votre périphérique ou contacter votre représentant de l'assistance technique.</translation>
-+<translation id="3046388203776734202">Paramètres des fenêtres pop-up :</translation>
-+<translation id="3437994698969764647">Tout exporter...</translation>
-+<translation id="8349305172487531364">Barre de favoris</translation>
-+<translation id="1898064240243672867">Stocké dans : <ph name="CERT_LOCATION"/></translation>
-+<translation id="444134486829715816">Développer...</translation>
-+<translation id="1401874662068168819">Gin Yieh</translation>
-+<translation id="7208899522964477531">Rechercher <ph name="SEARCH_TERMS"/> sur <ph name="SITE_NAME"/></translation>
-+<translation id="6255097610484507482">Modifier la carte de paiement</translation>
-+<translation id="5584091888252706332">Au démarrage</translation>
-+<translation id="8960795431111723921">Nous examinons actuellement le problème.</translation>
-+<translation id="2482878487686419369">Notifications</translation>
-+<translation id="8004582292198964060">Navigateur</translation>
-+<translation id="695755122858488207">Case d'option décochée</translation>
-+<translation id="6357135709975569075"><ph name="NUMBER_ZERO"/> days</translation>
-+<translation id="8666678546361132282">Anglais</translation>
-+<translation id="2224551243087462610">Modifier le nom du dossier</translation>
-+<translation id="1358741672408003399">Grammaire et orthographe</translation>
-+<translation id="4910673011243110136">Réseaux privés</translation>
-+<translation id="2527167509808613699">Toutes sortes de connexions</translation>
-+<translation id="9095710730982563314">Exceptions liées aux notifications</translation>
-+<translation id="8072988827236813198">Épingler les onglets</translation>
-+<translation id="1234466194727942574">Barre d'onglets</translation>
-+<translation id="7974087985088771286">Activer l'onglet 6</translation>
-+<translation id="4035758313003622889">Gestionnaire de &amp;tâches</translation>
-+<translation id="6356936121715252359">Paramètres de stockage d'Adobe Flash Player...</translation>
-+<translation id="5885996401168273077">Connexion au réseau</translation>
-+<translation id="7313804056609272439">Mode de saisie du vietnamien (VNI)</translation>
-+<translation id="1768211415369530011">L'application suivante va être lancée si vous acceptez cette requête :\n\n<ph name="APPLICATION"/></translation>
-+<translation id="8793043992023823866">Importation...</translation>
-+<translation id="8106211421800660735">N° de carte</translation>
-+<translation id="2550839177807794974">Gérer les moteurs de recherche...</translation>
-+<translation id="7031711645186424727">Utiliser un moniteur externe</translation>
-+<translation id="6316768948917110108">Gravure de l'image en cours...</translation>
-+<translation id="5089810972385038852">État</translation>
-+<translation id="2872961005593481000">Éteindre</translation>
-+<translation id="8986267729801483565">Enregistrer les fichiers dans le dossier :</translation>
-+<translation id="4322394346347055525">Fermer les autres onglets</translation>
-+<translation id="4411770745820968260">Répertoire de fichiers</translation>
-+<translation id="881799181680267069">Masquer les autres</translation>
-+<translation id="1812631533912615985">Annuler l'épinglage des onglets</translation>
-+<translation id="6042308850641462728">Plus</translation>
-+<translation id="8318945219881683434">Échec de la vérification de la révocation</translation>
-+<translation id="1650709179466243265">Ajouter www. et .com, puis ouvrir la page</translation>
-+<translation id="3524079319150349823">Pour inspecter un pop-up, cliquez avec le bouton droit sur la page ou sur l'icône d'action du navigateur, puis sélectionnez Inspecter le pop-up.</translation>
-+<translation id="994289308992179865">&amp;Répéter</translation>
-+<translation id="7793343764764530903"><ph name="CLOUD_PRINT_NAME"/> est à présent activé. <ph name="PRODUCT_NAME"/> a enregistré les imprimantes installées sur cette machine en les associant à &lt;b&gt;<ph name="EMAIL_ADDRESSES"/>&lt;/b&gt;. Vous pouvez désormais utiliser vos imprimantes depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
-+<translation id="1703490097606704369">Le serveur de <ph name="HOST_NAME"/>
-+ est introuvable, car la résolution DNS a échoué. DNS est le service Web qui
-+ traduit les noms de site Web en adresses Internet. Cette erreur est
-+ généralement due à l'absence de connexion Internet ou à une configuration
-+ incorrecte du réseau. Cela peut également venir d'un serveur DNS qui ne
-+ répond pas ou d'un pare-feu interdisant l'accès de
-+ <ph name="PRODUCT_NAME"/>
-+ au réseau.</translation>
-+<translation id="8887090188469175989">ZGPY</translation>
-+<translation id="3302709122321372472">Impossible de charger le fichier css &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
-+<translation id="305803244554250778">Créer des raccourcis vers des applications aux emplacements suivants :</translation>
-+<translation id="574392208103952083">Moyenne</translation>
-+<translation id="3745810751851099214">Envoyé pour :</translation>
-+<translation id="3937609171782005782">Aider Google à détecter les logiciels malveillants en envoyant des données supplémentaires concernant les sites pour lesquels cet avertissement s'affiche. Ces données seront gérées conformément aux règles définies sur la page <ph name="PRIVACY_PAGE_LINK"/>.</translation>
-+<translation id="8877448029301136595">[répertoire parent]</translation>
-+<translation id="7301360164412453905">Touches de sélection du clavier Hsu</translation>
-+<translation id="8631271110654520730">Copie de l'image de récupération...</translation>
-+<translation id="1963227389609234879">Tout supprimer</translation>
-+<translation id="7779140087128114262">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez réinitialiser la synchronisation.</translation>
-+<translation id="8027581147000338959">Ouvrir dans une nouvelle fenêtre</translation>
-+<translation id="8019305344918958688">Dommage... Aucune extension n'est installée. :-(</translation>
-+<translation id="7466861475611330213">Style de ponctuation</translation>
-+<translation id="2496180316473517155">Historique de navigation</translation>
-+<translation id="602251597322198729">Ce site tente de télécharger plusieurs fichiers. Voulez-vous autoriser le chargement ?</translation>
-+<translation id="5843685321177053287">Établissement de la liaison avec le service de gestion des périphériques en attente...</translation>
-+<translation id="2052389551707911401"><ph name="NUMBER_MANY"/> heures</translation>
-+<translation id="5411472733320185105">Ne pas utiliser les paramètres du proxy pour les hôtes et domaines suivants :</translation>
-+<translation id="6691936601825168937">&amp;Avancer</translation>
-+<translation id="6566142449942033617">Impossible de charger &quot;<ph name="PLUGIN_PATH"/>&quot; pour le plug-in.</translation>
-+<translation id="7065534935986314333">À propos du système</translation>
-+<translation id="45025857977132537">Utilisation de la clé du certificat : <ph name="USAGES"/></translation>
-+<translation id="6454421252317455908">Mode de saisie du chinois (quick)</translation>
-+<translation id="368789413795732264">Une erreur s'est produite lors de la tentative d'écriture du fichier : <ph name="ERROR_TEXT"/>.</translation>
-+<translation id="1173894706177603556">Renommer</translation>
-+<translation id="5670032673361607750">La synchronisation requiert votre attention.</translation>
-+<translation id="2148716181193084225">Aujourd'hui</translation>
-+<translation id="1002064594444093641">Imp&amp;rimer le cadre...</translation>
-+<translation id="7234674978021619913">Le site <ph name="HOST_NAME"/> a déjà été informé qu'un logiciel malveillant a été détecté sur ses pages. Pour plus d'informations concernant les problèmes rencontrés sur <ph name="HOST_NAME2"/>, consultez notre <ph name="DIAGNOSTIC_PAGE"/> Google.</translation>
-+<translation id="8202390211066742724">Adresse de serveur DNS spécifiée par l'utilisateur.</translation>
-+<translation id="4608500690299898628">&amp;Rechercher...</translation>
-+<translation id="3574305903863751447"><ph name="CITY"/>, <ph name="STATE"/> <ph name="COUNTRY"/></translation>
-+<translation id="8724859055372736596">&amp;Afficher dans le dossier</translation>
-+<translation id="4605399136610325267">Non connecté à Internet.</translation>
-+<translation id="978407797571588532">Sélectionnez
-+ <ph name="BEGIN_BOLD"/>
-+ Démarrer &gt; Panneau de configuration &gt; Connexions réseau &gt; Assistant Nouvelle connexion
-+ <ph name="END_BOLD"/>
-+ pour tester votre connexion.</translation>
-+<translation id="5554489410841842733">Cette icône s'affiche lorsque l'extension peut agir sur la page active.</translation>
-+<translation id="579702532610384533">Reconnexion</translation>
-+<translation id="4862642413395066333">Réponses OCSP de signature</translation>
-+<translation id="5266113311903163739">Erreur d'importation de l'autorité de certification</translation>
-+<translation id="9563164493805065">Gravure de l'image terminée.</translation>
-+<translation id="4756388243121344051">&amp;Historique</translation>
-+<translation id="3789841737615482174">Installer</translation>
-+<translation id="4320697033624943677">Ajouter des utilisateurs</translation>
-+<translation id="9153934054460603056">Enregistrer l'authentification et le mot de passe</translation>
-+<translation id="1455548678241328678">Clavier norvégien</translation>
-+<translation id="2520481907516975884">Basculer en mode chinois/anglais</translation>
-+<translation id="8571890674111243710">Traduction de la page en <ph name="LANGUAGE"/>...</translation>
-+<translation id="4789872672210757069">À propos de &amp;<ph name="PRODUCT_NAME"/></translation>
-+<translation id="4056561919922437609"><ph name="TAB_COUNT"/> onglets</translation>
-+<translation id="4373894838514502496">il y a <ph name="NUMBER_FEW"/> minutes</translation>
-+<translation id="6358450015545214790">Qu'est-ce que c'est ?</translation>
-+<translation id="6264365405983206840">Tout &amp;sélectionner</translation>
-+<translation id="1017280919048282932">&amp;Ajouter au dictionnaire</translation>
-+<translation id="8319414634934645341">Utilisation étendue de la clé</translation>
-+<translation id="4563210852471260509">Le chinois est la langue de saisie initiale</translation>
-+<translation id="6897140037006041989">Agent utilisateur</translation>
-+<translation id="3413122095806433232">Émetteurs de l'autorité de certification : <ph name="LOCATION"/></translation>
-+<translation id="4115153316875436289"><ph name="NUMBER_TWO"/> jours</translation>
-+<translation id="701080569351381435">Code source</translation>
-+<translation id="3286538390144397061">Redémarrer maintenant</translation>
-+<translation id="163309982320328737">La largeur de caractères initiale est Complète</translation>
-+<translation id="5107325588313356747">Pour masquer l'accès à ce programme, vous devez le désinstaller au moyen de \n<ph name="CONTROL_PANEL_APPLET_NAME"/> du Panneau de configuration.\n\nSouhaitez-vous exécuter <ph name="CONTROL_PANEL_APPLET_NAME"/> ?</translation>
-+<translation id="4841055638263130507">Paramètres du microphone</translation>
-+<translation id="6965648386495488594">Port</translation>
-+<translation id="7631887513477658702">&amp;Toujours ouvrir les fichiers de ce type</translation>
-+<translation id="8627795981664801467">Uniquement les connexions sécurisées</translation>
-+<translation id="8680787084697685621">Les informations de connexion au compte sont obsolètes.</translation>
-+<translation id="3228969707346345236">La traduction a échoué, car la page est déjà en <ph name="LANGUAGE"/>.</translation>
-+<translation id="1873879463550486830">Sandbox SUID</translation>
-+<translation id="2190355936436201913">(vide)</translation>
-+<translation id="8515737884867295000">Échec de l'authentification basée sur le certificat</translation>
-+<translation id="5868426874618963178">Envoyer le code source de la page actuelle</translation>
-+<translation id="1269138312169077280">Votre administrateur a désactivé certains paramètres.</translation>
-+<translation id="5818003990515275822">Coréen</translation>
-+<translation id="4182252350869425879">Avertissement : Il s'agit peut-être d'un site de phishing !</translation>
-+<translation id="5458214261780477893">Dvorak</translation>
-+<translation id="5353719617589986386">Étendue de pages incorrecte</translation>
-+<translation id="1164369517022005061"><ph name="NUMBER_DEFAULT"/> heures restantes</translation>
-+<translation id="5943260032016910017">Exceptions liées aux cookies et aux données de site</translation>
-+<translation id="2214283295778284209"><ph name="SITE"/> n'est pas accessible</translation>
-+<translation id="8755376271068075440">P&amp;lus grand</translation>
-+<translation id="8132793192354020517">Connecté à <ph name="NAME"/></translation>
-+<translation id="8187473050234053012">Le certificat de sécurité du site a été révoqué !</translation>
-+<translation id="7444983668544353857">Désactiver <ph name="NETWORKDEVICE"/></translation>
-+<translation id="6003177993629630467"><ph name="PRODUCT_NAME"/> risque de ne pas rester à jour.</translation>
-+<translation id="421577943854572179">intégré sur tout autre site</translation>
-+<translation id="580886651983547002"><ph name="PRODUCT_NAME"/>
-+ ne parvient pas à atteindre le site Web. Cela vient probablement d'un problème de réseau,
-+ mais peut également être dû à un pare-feu ou à un serveur proxy mal configuré.</translation>
-+<translation id="5445557969380904478">À propos de la reconnaissance vocale</translation>
-+<translation id="3093473105505681231">Langues et paramètres du correcteur orthographique...</translation>
-+<translation id="152482086482215392"><ph name="NUMBER_ONE"/> seconde restante</translation>
-+<translation id="529172024324796256">Nom d'utilisateur :</translation>
-+<translation id="3308116878371095290">Le stockage des cookies n'est pas autorisé pour cette page.</translation>
-+<translation id="7521387064766892559">JavaScript</translation>
-+<translation id="7219179957768738017">La connexion utilise <ph name="SSL_VERSION"/>.</translation>
-+<translation id="7014174261166285193">Échec de l'installation</translation>
-+<translation id="1970746430676306437">Afficher les &amp;infos sur la page</translation>
-+<translation id="3199127022143353223">Serveurs</translation>
-+<translation id="2805646850212350655">Système de fichiers de chiffrement Microsoft </translation>
-+<translation id="8053959338015477773">Un plug-in supplémentaire est requis pour afficher certains éléments sur cette page.</translation>
-+<translation id="3541661933757219855">Appuyez sur Ctrl+Alt+/ ou sur Échap pour masquer</translation>
-+<translation id="8813873272012220470">Cette fonctionnalité effectue des vérifications en arrière-plan et vous avertit en cas d'incompatibilité logicielle (modules tiers bloquant le navigateur, par exemple).</translation>
-+<translation id="5020734739305654865">Connexion avec</translation>
-+<translation id="2679385451463308372">Imprimer depuis la boîte de dialogue système…</translation>
-+<translation id="7414887922320653780"><ph name="NUMBER_ONE"/> heure restante</translation>
-+<translation id="121632099317611328">Échec de l'initialisation de l'appareil photo</translation>
-+<translation id="399179161741278232">Importés</translation>
-+<translation id="3829932584934971895">Type de fournisseur :</translation>
-+<translation id="462288279674432182">IP restreinte :</translation>
-+<translation id="3927932062596804919">Refuser</translation>
-+<translation id="3524915994314972210">Démarrage du téléchargement en cours...</translation>
-+<translation id="6484929352454160200">Une nouvelle version de <ph name="PRODUCT_NAME"/> est disponible.</translation>
-+<translation id="3187212781151025377">Clavier hébreu</translation>
-+<translation id="351152300840026870">Police à largeur fixe</translation>
-+<translation id="5827266244928330802">Safari</translation>
-+<translation id="778881183694837592">Les champs obligatoires ne doivent pas rester vides.</translation>
-+<translation id="2371076942591664043">Ouvrir une fois le téléchargement &amp;terminé</translation>
-+<translation id="3920504717067627103">Stratégies de certificat</translation>
-+<translation id="155865706765934889">Pavé tactile</translation>
-+<translation id="7701040980221191251">Aucun</translation>
-+<translation id="5917011688104426363">Activer la barre d'adresse en mode recherche</translation>
-+<translation id="6910239454641394402">Exceptions pour JavaScript</translation>
-+<translation id="2979639724566107830">Ouvrir dans une nouvelle fenêtre</translation>
-+<translation id="3269101346657272573">Veuillez saisir le code PIN.</translation>
-+<translation id="9204065299849069896">Options de saisie automatique...</translation>
-+<translation id="2822854841007275488">Arabe</translation>
-+<translation id="5857090052475505287">Nouveau dossier</translation>
-+<translation id="7450732239874446337">E/S réseau interrompue</translation>
-+<translation id="5178667623289523808">Rechercher le précédent</translation>
-+<translation id="2815448242176260024">Ne jamais enregistrer les mots de passe</translation>
-+<translation id="2989805286512600854">Ouvrir dans un nouvel onglet</translation>
-+<translation id="8687485617085920635">Fenêtre suivante</translation>
-+<translation id="4122118036811378575">&amp;Rechercher le suivant</translation>
-+<translation id="6008256403891681546">JCB</translation>
-+<translation id="2610780100389066815">Signature de liste d'approbation Microsoft</translation>
-+<translation id="8289811203643526145">Gérer les certificats...</translation>
-+<translation id="2788575669734834343">Sélectionnez le fichier de certificat.</translation>
-+<translation id="8404409224170843728">Fabricant :</translation>
-+<translation id="8267453826113867474">Bloquer le contenu inapproprié</translation>
-+<translation id="7959074893852789871">Le fichier contenait plusieurs certificats, dont certains n'ont pas été importés :</translation>
-+<translation id="1213999834285861200">Exceptions pour les images</translation>
-+<translation id="2805707493867224476">Autoriser tous les sites à afficher des fenêtres pop-up</translation>
-+<translation id="3561217442734750519">Vous devez indiquer un chemin valide comme valeur de clé privée.</translation>
-+<translation id="2444609190341826949">Sans mot de passe multiterme, vos mots de passe et autres données chiffrées ne seront pas synchronisés sur cet ordinateur.</translation>
-+<translation id="77221669950527621">Extensions ou applications</translation>
-+<translation id="6650142020817594541">Ce site recommande Google Chrome Frame (déjà installé).</translation>
-+<translation id="6503077044568424649">Les plus visités</translation>
-+<translation id="4625904365165566833">Vous n'êtes pas autorisé à vous connecter. Consultez le propriétaire de cet ordinateur portable.</translation>
-+<translation id="7450633916678972976">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome joint à votre
-+ envoi un journal indiquant votre version de Google Chrome et celle du système
-+ d'exploitation utilisé, ainsi que l'URL associée à votre rapport. Vous pouvez
-+ également joindre une capture d'écran. Ces informations nous
-+ permettent de diagnostiquer les problèmes et d'améliorer les performances de
-+ Google Chrome. Les informations personnelles fournies sciemment dans vos
-+ commentaires ou involontairement dans le journal, l'URL ou la capture
-+ d'écran sont protégées conformément à nos règles de
-+ confidentialité. Si vous ne souhaitez pas indiquer d'URL et/ou de capture
-+ d'écran, décochez les cases &quot;Inclure cette URL&quot; et/ou &quot;Inclure cette capture d'écran&quot;. Vous acceptez que Google utilise vos commentaires pour améliorer ses produits ou services.</translation>
-+<translation id="465365366590259328">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
-+<translation id="7168109975831002660">Taille de police minimale</translation>
-+<translation id="7070804685954057874">Entrée directe</translation>
-+<translation id="3265459715026181080">Fermer la fenêtre</translation>
-+<translation id="6074871234879228294">Mode de saisie du japonais (pour clavier japonais)</translation>
-+<translation id="7855296476260297092">Inscription réussie</translation>
-+<translation id="907841381057066561">Échec de création du fichier zip temporaire lors de la création du pack</translation>
-+<translation id="1294298200424241932">Modifier les paramètres de confiance :</translation>
-+<translation id="1384617406392001144">Votre historique de navigation</translation>
-+<translation id="3831099738707437457">&amp;Masquer le panneau de la vérification orthographique</translation>
-+<translation id="1040471547130882189">Plug-in ne répondant pas</translation>
-+<translation id="5473075389972733037">IBM</translation>
-+<translation id="8307664665247532435">Les paramètres seront effacés lors de la prochaine actualisation.</translation>
-+<translation id="790025292736025802"><ph name="URL"/> introuvable</translation>
-+<translation id="895347679606913382">Démarrage...</translation>
-+<translation id="3319048459796106952">Nouvelle fenêtre de nav&amp;igation privée</translation>
-+<translation id="5832669303303483065">Ajouter une adresse postale...</translation>
-+<translation id="3127919023693423797">Authentification en cours...</translation>
-+<translation id="4195643157523330669">Ouvrir dans un nouvel onglet</translation>
-+<translation id="8030169304546394654">Déconnecté</translation>
-+<translation id="4010065515774514159">Action du navigateur</translation>
-+<translation id="4286563808063000730">Le mot de passe multiterme saisi ne peut pas être utilisé, car vous avez déjà chiffré des données avec un mot de passe multiterme. Entrez ci-dessous le mot de passe multiterme actuellement défini pour la synchronisation.</translation>
-+<translation id="1154228249304313899">Ouvrir cette page :</translation>
-+<translation id="9074348188580488499">Voulez-vous vraiment supprimer tous les mots de passe ?</translation>
-+<translation id="6635491740861629599">Sélectionner par domaine</translation>
-+<translation id="3627588569887975815">Ouvrir le lien dans une fenêtre en navi&amp;gation privée</translation>
-+<translation id="5851868085455377790">Émetteur</translation>
-+<translation id="8223496248037436966">Options de saisie automatique</translation>
-+<translation id="1470719357688513792">Les nouveaux paramètres des cookies seront appliqués quand vous aurez actualisé la page.</translation>
-+<translation id="5578327870501192725">Votre connexion à <ph name="DOMAIN"/> est sécurisée par un chiffrement <ph name="BIT_COUNT"/> bits.</translation>
-+<translation id="869884720829132584">Menu Applications</translation>
-+<translation id="7764209408768029281">Outi&amp;ls</translation>
-+<translation id="1139892513581762545">Onglets latéraux</translation>
-+<translation id="7634357567062076565">Reprendre</translation>
-+<translation id="4779083564647765204">Zoom</translation>
-+<translation id="3282430104564575032">Inspecteur de DOM</translation>
-+<translation id="1526560967942511387">Document sans titre</translation>
-+<translation id="1291144580684226670">Police standard</translation>
-+<translation id="3979748722126423326">Activer <ph name="NETWORKDEVICE"/></translation>
-+<translation id="5538307496474303926">Opération en cours...</translation>
-+<translation id="4367133129601245178">C&amp;opier l'URL de l'image</translation>
-+<translation id="7542995811387359312">La saisie automatique des numéros de carte de paiement est désactivée, car la connexion utilisée par ce formulaire n'est pas sécurisée.</translation>
-+<translation id="3494444535872870968">Enregistrer le &amp;cadre sous...</translation>
-+<translation id="987264212798334818">Général</translation>
-+<translation id="7005812687360380971">Défaillance</translation>
-+<translation id="2356070529366658676">Demander</translation>
-+<translation id="5731247495086897348">Coller l'URL et y a&amp;ccéder</translation>
-+<translation id="8467548439852845758">Pour plus de sécurité, <ph name="PRODUCT_NAME"/> va chiffrer vos mots de passe.</translation>
-+<translation id="2524947000814989347">Si vous avez oublié votre mot de passe multiterme, vous devrez arrêter la synchronisation via Google Dashboard.</translation>
-+<translation id="8018154597338652331"><ph name="BURNT_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
-+<translation id="7635741716790924709">Adresse ligne 1</translation>
-+<translation id="5135533361271311778">Impossible de créer le favori.</translation>
-+<translation id="5271247532544265821">Basculer en mode chinois simplifié/traditionnel</translation>
-+<translation id="2052610617971448509">Votre système Sandbox n'est pas correctement configuré.</translation>
-+<translation id="7384913436093989340">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Préférences &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
-+<translation id="6417515091412812850">Impossible de vérifier si le certificat a été révoqué.</translation>
-+<translation id="7282743297697561153">Stockage des données</translation>
-+<translation id="3363332416643747536"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, Interrompu</translation>
-+<translation id="7347702518873971555">Acheter un forfait</translation>
-+<translation id="5285267187067365830">Installer le plug-in...</translation>
-+<translation id="5334844597069022743">Afficher le code source</translation>
-+<translation id="1166212789817575481">Fermer les onglets sur la droite</translation>
-+<translation id="6472893788822429178">Afficher le bouton &quot;Accueil&quot;</translation>
-+<translation id="4270393598798225102">Version <ph name="NUMBER"/></translation>
-+<translation id="534916491091036097">Parenthèse gche</translation>
-+<translation id="4157869833395312646">Microsoft Server Gated Cryptography</translation>
-+<translation id="8903921497873541725">Zoom avant</translation>
-+<translation id="2195729137168608510">Protection du courrier électronique</translation>
-+<translation id="1425734930786274278">Les cookies suivants ont été bloqués (tous les cookies tiers sont bloqués, sans exception) :</translation>
-+<translation id="6805647936811177813">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client de <ph name="HOST_NAME"/></translation>
-+<translation id="3437016096396740659">La batterie est chargée.</translation>
-+<translation id="6916146760805488559">Créer un nouveau profil...</translation>
-+<translation id="1199232041627643649">Maintenez la touche <ph name="KEY_EQUIVALENT"/> enfoncée pour quitter.</translation>
-+<translation id="5428562714029661924">Masquer ce plug-in</translation>
-+<translation id="7907591526440419938">Ouvrir le fichier</translation>
-+<translation id="2568774940984945469">Conteneur de barres d'infos</translation>
-+<translation id="8971063699422889582">Le certificat du serveur a expiré.</translation>
-+<translation id="8281596639154340028">Utiliser <ph name="HANDLER_TITLE"/></translation>
-+<translation id="7134098520442464001">Réduit la taille du texte</translation>
-+<translation id="21133533946938348">Épingler l'onglet</translation>
-+<translation id="1325040735987616223">Mise à jour du système</translation>
-+<translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation>
-+<translation id="9090669887503413452">Inclure les informations système</translation>
-+<translation id="3084771660770137092">Google Chrome n'avait pas suffisamment de mémoire ou le processus de la page Web a été arrêté pour une autre raison. Pour continuer, actualisez la page ou ouvrez-en une autre.</translation>
-+<translation id="1114901192629963971">Impossible de valider votre mot de passe sur le réseau actuel. Sélectionnez un autre réseau.</translation>
-+<translation id="5179510805599951267">Cette page n'est pas rédigée en <ph name="ORIGINAL_LANGUAGE"/> ? Signaler l'erreur</translation>
-+<translation id="6430814529589430811">Certificat unique codé Base 64 ASCII</translation>
-+<translation id="5143712164865402236">Activer le mode plein écran</translation>
-+<translation id="8434177709403049435">Codag&amp;e</translation>
-+<translation id="4051923669149193910"><ph name="HANDLER_TITLE"/> est déjà utilisé pour gérer les liens <ph name="PROTOCOL"/>://.</translation>
-+<translation id="2722201176532936492">Touches de sélection</translation>
-+<translation id="385120052649200804">Clavier international américain</translation>
-+<translation id="9012607008263791152">Je comprends que la visite de ce site peut être préjudiciable à mon ordinateur.</translation>
-+<translation id="6640442327198413730">Ressource cache manquante.</translation>
-+<translation id="1441458099223378239">Impossible d'accéder à mon compte</translation>
-+<translation id="5793220536715630615">C&amp;opier l'URL de la vidéo</translation>
-+<translation id="523397668577733901">Vous préférez <ph name="BEGIN_LINK"/>parcourir la galerie<ph name="END_LINK"/> ?</translation>
-+<translation id="2922350208395188000">Impossible de vérifier le certificat du serveur.</translation>
-+<translation id="3778740492972734840">Outils de &amp;développement</translation>
-+<translation id="8335971947739877923">Exporter...</translation>
-+<translation id="5680966941935662618">Paramètres de saisie automatique</translation>
-+<translation id="38385141699319881">Téléchargement de l'image en cours...</translation>
-+<translation id="6004539838376062211">&amp;Options du vérificateur d'orthographe</translation>
-+<translation id="5350198318881239970">Impossible d'ouvrir votre profil correctement.\n\nIl est possible que certaines fonctionnalités ne soient pas disponibles. Vérifiez que ce profil existe et que vous disposez d'une autorisation d'accès à son contenu en lecture et en écriture.</translation>
-+<translation id="4058793769387728514">Vérifier le document maintenant</translation>
-+<translation id="1810107444790159527">Zone de liste</translation>
-+<translation id="3338239663705455570">Clavier slovène</translation>
-+<translation id="1859234291848436338">Sens de l'écriture</translation>
-+<translation id="4567836003335927027">Vos données sur <ph name="WEBSITE_1"/></translation>
-+<translation id="756445078718366910">Ouvrir une fenêtre du navigateur</translation>
-+<translation id="4126154898592630571">Conversion de la date et de l'heure</translation>
-+<translation id="5088534251099454936">PKCS #1 SHA-512 avec chiffrement RSA</translation>
-+<translation id="6392373519963504642">Clavier coréen</translation>
-+<translation id="7887334752153342268">Dupliquer</translation>
-+<translation id="4980691186726139495">Ne pas conserver sur cette page</translation>
-+<translation id="3081523290047420375">Désactiver <ph name="CLOUD_PRINT_NAME"/></translation>
-+<translation id="9207194316435230304">ATOK</translation>
-+<translation id="9026731007018893674">téléchargement</translation>
-+<translation id="7646591409235458998">E-mail :</translation>
-+<translation id="703748601351783580">Ouvrir tous les favoris dans une nouvelle &amp;fenêtre</translation>
-+<translation id="6199775032047436064">Rafraîchir la page actuelle</translation>
-+<translation id="6981982820502123353">Accessibilité</translation>
-+<translation id="112343676265501403">Exceptions pour les plug-ins</translation>
-+<translation id="770273299705142744">Remplissage automatique des formulaires</translation>
-+<translation id="7210998213739223319">Nom d'utilisateur</translation>
-+<translation id="4478664379124702289">Enregistrer le lie&amp;n sous...</translation>
-+<translation id="8725066075913043281">Réessayer</translation>
-+<translation id="8502249598105294518">Personnaliser et configurer <ph name="PRODUCT_NAME"/></translation>
-+<translation id="7392089327262158658">Préférences de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
-+<translation id="4163521619127344201">Votre position géographique</translation>
-+<translation id="3797008485206955964">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
-+<translation id="8590375307970699841">Configurer les mises à jour automatiques</translation>
-+<translation id="2797524280730715045">il y a <ph name="NUMBER_DEFAULT"/> heures</translation>
-+<translation id="265390580714150011">Valeur du champ</translation>
-+<translation id="9073247318500677671">Les dernières versions d'Unity et GNOME (ainsi que la prochaine version d'Ubuntu, Natty Narwhal) affichent une barre de menus de type OSX sur toute la largeur supérieure de l'écran.</translation>
-+<translation id="3869917919960562512">Index erroné.</translation>
-+<translation id="7031962166228839643">Préparation du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, l'opération peut prendre quelques minutes.</translation>
-+<translation id="4250377793615429299">Nombre de copies incorrect</translation>
-+<translation id="7180865173735832675">Personnaliser</translation>
-+<translation id="5737306429639033676">Prédire les actions du réseau pour améliorer les performances de chargement des pages</translation>
-+<translation id="8123426182923614874">Données restantes :</translation>
-+<translation id="3707020109030358290">N'est pas une autorité de certification.</translation>
-+<translation id="2115926821277323019">L'URL doit être valide.</translation>
-+<translation id="8986494364107987395">Envoyer automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
-+<translation id="7070714457904110559">Cette fonctionnalité active la géolocalisation dans les extensions expérimentales. Cela implique l'utilisation des API de localisation du système d'exploitation (si disponibles) et l'envoi de données sur la configuration réseau locale au service de localisation de Google afin de déterminer une position précise.</translation>
-+<translation id="6701535245008341853">Impossible de charger le profil.</translation>
-+<translation id="527605982717517565">Toujours exécuter JavaScript sur <ph name="HOST"/></translation>
-+<translation id="702373420751953740">Version PRL :</translation>
-+<translation id="1307041843857566458">Confirmer la réactivation</translation>
-+<translation id="8314308967132194952">Ajouter une adresse postale...</translation>
-+<translation id="1221024147024329929">PKCS #1 MD2 avec chiffrement RSA</translation>
-+<translation id="853265131227167869">Dim.^Lun.^Mar.^Mer.^Jeu.^Ven.^Sam.</translation>
-+<translation id="3323447499041942178">Zone de saisie</translation>
-+<translation id="580571955903695899">Trier par nom</translation>
-+<translation id="5230516054153933099">Fenêtre</translation>
-+<translation id="7554791636758816595">Nouvel onglet</translation>
-+<translation id="5503844897713343920">Vous tentez d'accéder au site <ph name="DOMAIN"/>, mais le certificat présenté par le serveur a été révoqué par son émetteur. Cela signifie que les informations d'identification présentées par le serveur ne sont pas approuvées. Vous communiquez peut-être avec un pirate informatique. Nous vous déconseillons vivement de continuer.</translation>
-+<translation id="6928853950228839340">Composition hors écran</translation>
-+<translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation>
-+<translation id="7671576867600624">Technologie :</translation>
-+<translation id="1103966635949043187">Accédez à la page d'accueil du site :</translation>
-+<translation id="1951332921786364801">Configurer la communication à distance</translation>
-+<translation id="1086613338090581534">L'émetteur d'un certificat n'ayant pas expiré est tenu d'assurer la maintenance de ce qui s'appelle &quot;une liste de révocation&quot;. Si un certificat est compromis, l'émetteur peut le révoquer en l'ajoutant à la liste de révocation. Ce certificat n'est alors plus approuvé par votre navigateur. Il n'est pas nécessaire d'assurer la maintenance de l'état &quot;révoqué&quot; des certificats expirés. Donc, bien qu'un certificat ait été qualifié de valide pour le site Web que vous visitez actuellement, il est impossible de déterminer s'il a été, depuis, compromis puis révoqué ou s'il est toujours valide. Par conséquent, il n'est pas possible de s'assurer si vous communiquez avec un site Web légitime ou si le certificat a été compromis et se trouve maintenant en la possession d'un pirate informatique avec lequel vous communiquez. Ne poursuivez pas.</translation>
-+<translation id="2645575947416143543">Néanmoins, si vous travaillez dans une entreprise qui génère ses propres certificats, et que vous essayez de vous connecter au site Web interne de l'entreprise avec un certificat de ce type, vous pouvez résoudre ce problème en toute sécurité. Pour ce faire, importez le certificat racine de l'entreprise en tant que &quot;certificat racine&quot;. Par la suite, les certificats émis ou vérifiés par votre entreprise seront approuvés et vous ne verrez plus cette erreur lorsque vous tenterez de vous connecter à nouveau au site Web interne. Contactez le support informatique de votre entreprise pour savoir comment ajouter un nouveau certificat racine sur votre ordinateur.</translation>
-+<translation id="376466258076168640">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
-+<translation id="1056898198331236512">Avertissement</translation>
-+<translation id="8630826211403662855">Préférences de recherche</translation>
-+<translation id="8432745813735585631">Clavier Colemak américain</translation>
-+<translation id="8151639108075998630">Activer la navigation en tant qu'invité</translation>
-+<translation id="2608770217409477136">Utiliser les paramètres par défaut</translation>
-+<translation id="3157931365184549694">Rétablir</translation>
-+<translation id="7426243339717063209">Désinstaller &quot;<ph name="EXTENSION_NAME"/>&quot; ?</translation>
-+<translation id="996250603853062861">Établissement de la connexion sécurisée...</translation>
-+<translation id="6059232451013891645">Dossier :</translation>
-+<translation id="4274292172790327596">Erreur non reconnue</translation>
-+<translation id="760537465793895946">Consultez les conflits connus avec des modules tiers.</translation>
-+<translation id="7042418530779813870">Co&amp;ller et rechercher</translation>
-+<translation id="9110447413660189038">&amp;Remonter</translation>
-+<translation id="375403751935624634">Échec de la traduction en raison d'une erreur de serveur</translation>
-+<translation id="2101225219012730419">Version :</translation>
-+<translation id="1570242578492689919">Polices et codage</translation>
-+<translation id="3082374807674020857"><ph name="PAGE_TITLE"/> - <ph name="PAGE_URL"/></translation>
-+<translation id="8050038245906040378">Signature du code commercial Microsoft</translation>
-+<translation id="3031557471081358569">Sélectionnez les éléments à importer :</translation>
-+<translation id="1368832886055348810">De gauche à droite</translation>
-+<translation id="3031433885594348982">Votre connexion à <ph name="DOMAIN"/> est sécurisée par le biais d'un faible chiffrement.</translation>
-+<translation id="4047345532928475040">sans objet</translation>
-+<translation id="5604324414379907186">Toujours afficher la barre de favoris</translation>
-+<translation id="3220630151624181591">Activer l'onglet 2</translation>
-+<translation id="8898139864468905752">Aperçu des onglets</translation>
-+<translation id="2799223571221894425">Redémarrer</translation>
-+<translation id="5771816112378578655">Configuration en cours...</translation>
-+<translation id="1197979282329025000">Une erreur s'est produite lors de la récupération des fonctions de l'imprimante <ph name="PRINTER_NAME"/>. Cette imprimante n'a pas pu être enregistrée dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
-+<translation id="8820901253980281117">Exceptions pour les fenêtres pop-up</translation>
-+<translation id="1143142264369994168">Signataire du certificat </translation>
-+<translation id="904949795138183864">La page Web <ph name="URL"/> n'existe plus.</translation>
-+<translation id="3228279582454007836">Vous n'avez jamais visité ce site auparavant.</translation>
-+<translation id="2159017110205600596">Personnaliser...</translation>
-+<translation id="5449716055534515760">Fe&amp;rmer la fenêtre</translation>
-+<translation id="2814489978934728345">Arrêter le chargement de cette page</translation>
-+<translation id="2354001756790975382">Autres favoris</translation>
-+<translation id="8561574028787046517"><ph name="PRODUCT_NAME"/> a été mis à jour.</translation>
-+<translation id="5234325087306733083">Mode hors connexion</translation>
-+<translation id="1779392088388639487">Erreur d'importation de fichier PKCS #12</translation>
-+<translation id="166278006618318542">Algorithme de clé publique de l'objet</translation>
-+<translation id="5759272020525228995">Le site Web a rencontré une erreur lors de l'extraction de <ph name="URL"/>.
-+ Cela peut être dû à une opération de maintenance ou à une configuration incorrecte.</translation>
-+<translation id="641480858134062906">Échec du chargement de la page <ph name="URL"/></translation>
-+<translation id="3693415264595406141">Mot de passe :</translation>
-+<translation id="74568296546932365">Conserver <ph name="PAGE_TITLE"/> en tant que moteur de recherche par défaut</translation>
-+<translation id="8602184400052594090">Fichier manifeste absent ou illisible</translation>
-+<translation id="2784949926578158345">La connexion a été réinitialisée.</translation>
-+<translation id="6663792236418322902">Le mot de passe choisi vous sera demandé pour restaurer le fichier. Veillez à le conserver en lieu sûr.</translation>
-+<translation id="4532822216683966758">La vérification de la provenance du certificat DNS est activée, ce qui peut entraîner l'envoi d'informations privées à Google.</translation>
-+<translation id="6321196148033717308">À propos de la reconnaissance vocale</translation>
-+<translation id="3412265149091626468">Aller à la sélection</translation>
-+<translation id="8167737133281862792">Ajouter un certificat</translation>
-+<translation id="2911372483530471524">Espaces de noms PID</translation>
-+<translation id="6093374025603915876">Préférences de saisie automatique</translation>
-+<translation id="8584134039559266300">Activer l'onglet 8</translation>
-+<translation id="5189060859917252173">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; représente une autorité de certification.</translation>
-+<translation id="3785852283863272759">Envoyer par e-mail l'emplacement de la page</translation>
-+<translation id="2255317897038918278">Enregistrement des informations de date Microsoft</translation>
-+<translation id="3493881266323043047">Validité</translation>
-+<translation id="5979421442488174909">&amp;Traduire en <ph name="LANGUAGE"/></translation>
-+<translation id="7326526699920221209">Batterie : <ph name="PRECENTAGE"/> %</translation>
-+<translation id="952992212772159698">Désactivé</translation>
-+<translation id="8299269255470343364">Japonais</translation>
-+<translation id="5187826826541650604"><ph name="KEY_NAME"/> (<ph name="DEVICE"/>)</translation>
-+<translation id="6429639049555216915">L'application est actuellement inaccessible.</translation>
-+<translation id="2144536955299248197">Lecteur du certificat : <ph name="CERTIFICATE_NAME"/></translation>
-+<translation id="50030952220075532"><ph name="NUMBER_ONE"/> jour restant</translation>
-+<translation id="2885378588091291677">Gestionnaire de tâches</translation>
-+<translation id="5792852254658380406">Gérer les extensions...</translation>
-+<translation id="2359808026110333948">Continuer</translation>
-+<translation id="176759384517330673">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
-+<translation id="1618661679583408047">Le certificat de sécurité du site n'est pas encore valide !</translation>
-+<translation id="7039912931802252762">Ouverture de session par carte à puce Microsoft</translation>
-+<translation id="6285074077487067719">Format</translation>
-+<translation id="3065140616557457172">Tapez votre requête ou saisissez une URL pour commencer la navigation : c'est à vous de choisir.</translation>
-+<translation id="5509693895992845810">Enregistrer &amp;sous...</translation>
-+<translation id="5986279928654338866">Le serveur <ph name="DOMAIN"/> requiert un nom d'utilisateur et un mot de passe.</translation>
-+<translation id="521467793286158632">Supprimer tous les mots de passe</translation>
-+<translation id="2491120439723279231">Le certificat du serveur contient des erreurs.</translation>
-+<translation id="4448844063988177157">Recherche de réseaux Wi-Fi...</translation>
-+<translation id="5765780083710877561">Description :</translation>
-+<translation id="338583716107319301">Séparateur</translation>
-+<translation id="2079053412993822885">Si vous supprimez l'un de vos propres certificats, vous ne pouvez plus l'utiliser pour vous identifier.</translation>
-+<translation id="7221869452894271364">Rafraîchir cette page</translation>
-+<translation id="6791443592650989371">État d'activation :</translation>
-+<translation id="4801257000660565496">Créer des raccourcis vers des applications</translation>
-+<translation id="6503256918647795660">Clavier franco-suisse</translation>
-+<translation id="6175314957787328458">GUID de domaine Microsoft</translation>
-+<translation id="8179976553408161302">Entrer</translation>
-+<translation id="8261506727792406068">Supprimer</translation>
-+<translation id="4404805853119650018">Échec de l'enregistrement de cet ordinateur pour l'accès à distance.</translation>
-+<translation id="345693547134384690">Ouvrir l'&amp;image dans un nouvel onglet</translation>
-+<translation id="7422192691352527311">Préférences...</translation>
-+<translation id="354211537509721945">L'administrateur a désactivé les mises à jour.</translation>
-+<translation id="1375198122581997741">À propos de la version</translation>
-+<translation id="7915471803647590281">Veuillez nous indiquer ce qu'il se passe avant d'envoyer votre rapport.</translation>
-+<translation id="5725124651280963564">Connectez-vous à <ph name="TOKEN_NAME"/> afin de générer une clé pour <ph name="HOST_NAME"/>.</translation>
-+<translation id="8418113698656761985">Clavier roumain</translation>
-+<translation id="5976160379964388480">Autres</translation>
-+<translation id="3665842570601375360">Sécurité :</translation>
-+<translation id="1430915738399379752">Imprimer</translation>
-+<translation id="7999087758969799248">Mode de saisie standard</translation>
-+<translation id="2635276683026132559">Signature</translation>
-+<translation id="4835836146030131423">Erreur lors de la connexion</translation>
-+<translation id="7715454002193035316">Pour cette session uniquement</translation>
-+<translation id="2475982808118771221">Une erreur s'est produite.</translation>
-+<translation id="3324684065575061611">(Désactivé par une stratégie d'entreprise)</translation>
-+<translation id="7385854874724088939">Erreur lors de la tentative d'impression. Vérifiez votre imprimante et réessayez.</translation>
-+<translation id="770015031906360009">Grec</translation>
-+<translation id="3834901049798243128">Ignorer les exceptions et bloquer l'enregistrement des cookies tiers</translation>
-+<translation id="8116152017593700047">Cet outil vous permet de sélectionner une capture d'écran enregistrée. Aucune capture d'écran n'est disponible pour le moment. Appuyez simultanément sur Ctrl et sur la touche &quot;Mode Présentation&quot; pour enregistrer une capture d'écran. Vos trois dernières captures apparaissent ici.</translation>
-+<translation id="3454157711543303649">Activation effectuée</translation>
-+<translation id="884923133447025588">Aucun système de révocation trouvé</translation>
-+<translation id="556042886152191864">Bouton</translation>
-+<translation id="1352060938076340443">Interrompu</translation>
-+<translation id="8571226144504132898">Dictionnaire de symboles</translation>
-+<translation id="7229570126336867161">Technologie EvDo requise</translation>
-+<translation id="7582844466922312471">Internet mobile</translation>
-+<translation id="945522503751344254">Envoyer le commentaire</translation>
-+<translation id="4539401194496451708">Associé au profil Chrome <ph name="USER_EMAIL_ADDRESS"/>. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
-+<translation id="7369847606959702983">Carte de crédit (autre)</translation>
-+<translation id="6867459744367338172">Langues et saisie</translation>
-+<translation id="7671130400130574146">Utiliser la barre de titre et les bordures de fenêtre du système</translation>
-+<translation id="9170848237812810038">Ann&amp;uler</translation>
-+<translation id="284970761985428403"><ph name="ASCII_NAME"/> (<ph name="UNICODE_NAME"/>)</translation>
-+<translation id="3903912596042358459">Le serveur a refusé d'exécuter la demande.</translation>
-+<translation id="8135557862853121765"><ph name="NUM_KILOBYTES"/> Ko</translation>
-+<translation id="4444364671565852729"><ph name="PRODUCT_NAME"/> a été mis à jour vers la version <ph name="VERSION"/>.</translation>
-+<translation id="5819890516935349394">Navigateur de contenu</translation>
-+<translation id="2731392572903530958">&amp;Rouvrir la fenêtre fermée</translation>
-+<translation id="1254593899333212300">Se connecter directement à Internet</translation>
-+<translation id="6107012941649240045">Émis pour</translation>
-+<translation id="6483805311199035658">Ouverture de <ph name="FILE"/> en cours</translation>
-+<translation id="3576278878016363465">Cibles disponibles pour l'image</translation>
-+<translation id="895541991026785598">Signaler un problème</translation>
-+<translation id="940425055435005472">Taille de police :</translation>
-+<translation id="494286511941020793">Aide pour la configuration de proxy</translation>
-+<translation id="2765217105034171413">Petite</translation>
-+<translation id="1285266685456062655"><ph name="NUMBER_FEW"/> hours ago</translation>
-+<translation id="9154176715500758432">Rester sur cette page</translation>
-+<translation id="5875565123733157100">Type de bug :</translation>
-+<translation id="6988771638657196063">Inclure cette URL :</translation>
-+<translation id="5717920936024713315">Cookies et données de site...</translation>
-+<translation id="3842552989725514455">Police Serif</translation>
-+<translation id="1949795154112250744"><ph name="BEGIN_BOLD"/>Avertissement :<ph name="END_BOLD"/> <ph name="PRODUCT_NAME"/> ne peut pas empêcher les extensions d'enregistrer votre historique de navigation. Pour désactiver cette extension en mode navigation privée, désélectionnez-la.</translation>
-+<translation id="4440967101351338638">ChromiumOs Image Burn</translation>
-+<translation id="1813278315230285598">Services</translation>
-+<translation id="6860097299815761905">Paramètres du proxy...</translation>
-+<translation id="373572798843615002">1 onglet</translation>
-+<translation id="4162393307849942816"><ph name="BEGIN_BOLD"/>Vous naviguez en tant qu'invité<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront pas dans l'historique de votre navigateur ni dans votre historique des recherches. Les autres traces telles que les cookies seront supprimées de l'ordinateur à la fin de votre session. En revanche, les fichiers téléchargés et les favoris créés seront conservés.
-+ <ph name="LINE_BREAK"/>
-+ <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur le mode invité</translation>
-+<translation id="827924395145979961">Chargement des pages impossible</translation>
-+<translation id="3092544800441494315">Inclure cette capture d'écran :</translation>
-+<translation id="7714464543167945231">Certificat</translation>
-+<translation id="3616741288025931835">&amp;Effacer les données de navigation...</translation>
-+<translation id="3313622045786997898">Valeur de signature du certificat</translation>
-+<translation id="8535005006684281994">URL de renouvellement du certificat Netscape</translation>
-+<translation id="2440604414813129000">Afficher la s&amp;ource</translation>
-+<translation id="816095449251911490"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/>, <ph name="TIME_REMAINING"/></translation>
-+<translation id="8200772114523450471">Reprendre</translation>
-+<translation id="6358975074282722691"><ph name="NUMBER_TWO"/> secs ago</translation>
-+<translation id="5423849171846380976">Activé</translation>
-+<translation id="6748105842970712833">Carte SIM désactivée</translation>
-+<translation id="7323391064335160098">Compatibilité avec VPN</translation>
-+<translation id="3929673387302322681">Développement - Instable</translation>
-+<translation id="4251486191409116828">Échec de création du raccourci vers l'application</translation>
-+<translation id="5190835502935405962">Barre de favoris</translation>
-+<translation id="7828272290962178636">Le serveur est en mesure de répondre à la demande.</translation>
-+<translation id="7823073559911777904">Modifier les paramètres du proxy...</translation>
-+<translation id="5438430601586617544">(non empaquetée)</translation>
-+<translation id="6460601847208524483">Rechercher le suivant</translation>
-+<translation id="8433186206711564395">Paramètres réseau</translation>
-+<translation id="4856478137399998590">Votre service Internet mobile est activé et prêt à l'emploi.</translation>
-+<translation id="1676388805288306495">Modifier la police et la langue par défaut des pages Web</translation>
-+<translation id="8969761905474557563">Composition graphique avec accélération matérielle</translation>
-+<translation id="3937640725563832867">Autre nom de l'émetteur du certificat</translation>
-+<translation id="4701488924964507374"><ph name="SENTENCE1"/> <ph name="SENTENCE2"/></translation>
-+<translation id="1163931534039071049">&amp;Afficher le code source du cadre</translation>
-+<translation id="8770196827482281187">Mode de saisie du persan (clavier ISIRI 2901)</translation>
-+<translation id="6423239382391657905">OpenVPN</translation>
-+<translation id="7564847347806291057">Arrêter le processus</translation>
-+<translation id="1607220950420093847">Votre compte a peut-être été supprimé ou désactivé. Veuillez vous déconnecter.</translation>
-+<translation id="5613695965848159202">Authentification anonyme :</translation>
-+<translation id="2233320200890047564">Bases de données indexées</translation>
-+<translation id="7063412606254013905">En savoir plus sur les escroqueries par phishing</translation>
-+<translation id="307767688111441685">Page à l'apparence anormale</translation>
-+<translation id="9076523132036239772">Adresse e-mail ou mot de passe incorrect. Essayez tout d'abord de vous connecter à un réseau.</translation>
-+<translation id="6965978654500191972">Périphérique</translation>
-+<translation id="1242521815104806351">Informations sur la connexion</translation>
-+<translation id="5295309862264981122">Confirmer la navigation</translation>
-+<translation id="1492817554256909552">Nom du point d'accès :</translation>
-+<translation id="5546865291508181392">Rechercher</translation>
-+<translation id="1999115740519098545">Au démarrage</translation>
-+<translation id="2983818520079887040">Paramètres...</translation>
-+<translation id="1465619815762735808">Lire en un clic</translation>
-+<translation id="6941937518557314510">Connectez-vous à <ph name="TOKEN_NAME"/> pour vous authentifier auprès de <ph name="HOST_NAME"/> avec votre certificat.</translation>
-+<translation id="2783600004153937501">Votre administrateur informatique a désactivé certaines options.</translation>
-+<translation id="2099686503067610784">Supprimer le certificat de serveur &quot;<ph name="CERTIFICATE_NAME"/>&quot;?</translation>
-+<translation id="9027603907212475920">Configurer la synchronisation...</translation>
-+<translation id="6873213799448839504">Valider automatiquement une chaîne</translation>
-+<translation id="7238585580608191973">Empreinte SHA-256</translation>
-+<translation id="2501278716633472235">Retour</translation>
-+<translation id="131461803491198646">Réseau domestique, sans itinérance</translation>
-+<translation id="7377249249140280793"><ph name="RELATIVE_DATE"/> - <ph name="FULL_DATE"/></translation>
-+<translation id="5679279978772703611">Gérer les mots de passe enregistrés...</translation>
-+<translation id="4551440281920791563">Sélectionnez
-+ <ph name="BEGIN_BOLD"/>
-+ Menu clé à molette &gt; Options &gt; Options avancées &gt; Modifier les paramètres du proxy &gt; Paramètres réseau
-+ <ph name="END_BOLD"/>
-+ et désélectionnez l'option &quot;Utiliser un serveur proxy pour votre réseau local&quot;.</translation>
-+<translation id="1285320974508926690">Ne jamais traduire ce site</translation>
-+<translation id="8954894007019320973">(suite)</translation>
-+<translation id="3748412725338508953">Trop de redirections</translation>
-+<translation id="5833726373896279253">Ces paramètres ne peuvent être modifiés que par le propriétaire :</translation>
-+<translation id="6858960932090176617">Active la protection XSS Auditor de WebKit (protection contre le Cross-site Scripting), une fonctionnalité qui vous protège de certaines attaques de sites malveillants et offre une sécurité accrue, mais qui n'est pas compatible avec tous les sites Web.</translation>
-+<translation id="6005282720244019462">Clavier latino-américain</translation>
-+<translation id="8831104962952173133">Phishing détecté !</translation>
-+<translation id="5141720258550370428">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
-+<translation id="6751344591405861699"><ph name="WINDOW_TITLE"/> (Navigation privée)</translation>
-+<translation id="6681668084120808868">Prendre une photo</translation>
-+<translation id="780301667611848630">Non merci</translation>
-+<translation id="2812989263793994277">Ne pas afficher les images</translation>
-+<translation id="7190251665563814471">Toujours autoriser ces plug-ins sur <ph name="HOST"/></translation>
-+<translation id="6845383723252244143">Sélectionner un dossier</translation>
-+<translation id="8925458182817574960">&amp;Paramètres</translation>
-+<translation id="6361850914223837199">Informations sur l'erreur :</translation>
-+<translation id="8948393169621400698">Toujours autoriser les plug-ins sur <ph name="HOST"/></translation>
-+<translation id="3865082058368813534">Effacer les données de saisie automatique enregistrées</translation>
-+<translation id="8288345061925649502">Changer de moteur de recherche</translation>
-+<translation id="5436492226391861498">En attente du tunnel proxy...</translation>
-+<translation id="3803991353670408298">Veuillez ajouter un autre mode de saisie avant de supprimer celui-ci.</translation>
-+<translation id="1095623615273566396"><ph name="NUMBER_FEW"/> secondes</translation>
-+<translation id="7006788746334555276">Paramètres de contenu</translation>
-+<translation id="3369521687965833290">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils commençant par une lettre de lecteur et ne contenant ni jonction, ni point de montage, ni lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
-+<translation id="337920581046691015"><ph name="PRODUCT_NAME"/> va être installé.</translation>
-+<translation id="6282194474023008486">Code postal</translation>
-+<translation id="7733107687644253241">En bas à droite</translation>
-+<translation id="5139955368427980650">&amp;Ouvrir</translation>
-+<translation id="8136149669168180907"><ph name="DOWNLOADED_AMOUNT"/> téléchargé(s) sur <ph name="TOTAL_SIZE"/></translation>
-+<translation id="7375268158414503514">Commentaires d'ordre général/Autres</translation>
-+<translation id="4643612240819915418">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
-+<translation id="7997479212858899587">Identité :</translation>
-+<translation id="8300849813060516376">Échec de l'opération OTASP</translation>
-+<translation id="2213819743710253654">Action sur la page</translation>
-+<translation id="1317130519471511503">Modifier des éléments...</translation>
-+<translation id="6391538222494443604">Le répertoire d'extensions est obligatoire.</translation>
-+<translation id="8051695050440594747"><ph name="MEGABYTES"/> Mo disponibles</translation>
-+<translation id="7088615885725309056">Ancien</translation>
-+<translation id="461656879692943278"><ph name="HOST_NAME"/> fournit du contenu provenant de <ph name="ELEMENTS_HOST_NAME"/>, un site connu pour distribuer des logiciels malveillants. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
-+<translation id="1387022316521171484">Ces fonctionnalités expérimentales sont susceptibles d'être modifiées, interrompues ou supprimées à tout moment. Nous ne fournissons aucune garantie quant aux effets de leur activation. Votre navigateur pourrait bien prendre feu. Trêve de plaisanterie, il est possible que votre navigateur supprime toutes vos données ou que votre sécurité et votre vie privée soient compromises de manière inattendue. Nous vous prions d'agir avec précaution.</translation>
-+<translation id="2143778271340628265">Configuration manuelle du proxy</translation>
-+<translation id="5294529402252479912">Mettre à jour Adobe Reader maintenant</translation>
-+<translation id="5263972071113911534"><ph name="NUMBER_MANY"/> days ago</translation>
-+<translation id="7461850476009326849">Désactiver les plug-ins individuels...</translation>
-+<translation id="4097411759948332224">Envoyer une capture d'écran de la page en cours</translation>
-+<translation id="2231990265377706070">Point d'exclamation</translation>
-+<translation id="7199540622786492483"><ph name="PRODUCT_NAME"/> n'est plus à jour, car il n'a pas été relancé depuis quelque temps. La mise à jour disponible sera installée dès que vous le relancerez.</translation>
-+<translation id="8652722422052983852">Petit problème... Tentons de le résoudre.</translation>
-+<translation id="5970231080121144965">Cette fonctionnalité permet d'établir des correspondances entre les sous-chaînes et plusieurs fragments d'URL figurant dans l'historique.</translation>
-+<translation id="4665674675433053715">Page &quot;Nouvel onglet&quot; expérimentale</translation>
-+<translation id="3726527440140411893">Les cookies suivants étaient autorisés lorsque vous avez consulté cette page :</translation>
-+<translation id="3320859581025497771">votre opérateur</translation>
-+<translation id="8828781037212165374">Activer ces fonctionnalités...</translation>
-+<translation id="8562413501751825163">Quitter Firefox avant l'importation</translation>
-+<translation id="3435541101098866721">Ajouter un nouveau téléphone</translation>
-+<translation id="2448046586580826824">Proxy HTTP sécurisé</translation>
-+<translation id="4032534284272647190">Accès à <ph name="URL"/> refusé.</translation>
-+<translation id="4928569512886388887">Finalisation de la mise à jour du système...</translation>
-+<translation id="8258002508340330928">Voulez-vous continuer ?</translation>
-+<translation id="4309420042698375243"><ph name="NUM_KILOBYTES"/> Ko (<ph name="NUM_KILOBYTES_LIVE"/> Ko effectifs)</translation>
-+<translation id="5554573843028719904">Autre réseau Wi-Fi...</translation>
-+<translation id="5034259512732355072">Choisir un autre répertoire...</translation>
-+<translation id="8885905466771744233">L'extension indiquée est déjà associée à une clé privée. Utilisez cette clé ou supprimez-la.</translation>
-+<translation id="7831504847856284956">Ajouter une adresse</translation>
-+<translation id="7505152414826719222">Stockage local</translation>
-+<translation id="2541423446708352368">Afficher tous les téléchargements</translation>
-+<translation id="4381021079159453506">Navigateur de contenu</translation>
-+<translation id="8109246889182548008">Magasin de certificats</translation>
-+<translation id="5030338702439866405">Émis par</translation>
-+<translation id="5280833172404792470">Quitter le mode plein écran (<ph name="ACCELERATOR"/>)</translation>
-+<translation id="2728127805433021124">Le certificat du serveur a été signé avec un algorithme de signature faible.</translation>
-+<translation id="2137808486242513288">Ajouter un utilisateur</translation>
-+<translation id="6193618946302416945">Me proposer de traduire les pages qui sont écrites dans une langue que je ne sais pas lire</translation>
-+<translation id="129553762522093515">Récemment fermés</translation>
-+<translation id="4287167099933143704">Saisir la clé de déverrouillage du code PIN</translation>
-+<translation id="8355915647418390920"><ph name="NUMBER_FEW"/> jours</translation>
-+<translation id="3129140854689651517">Rechercher du texte</translation>
-+<translation id="7221585318879598658">Sans-Serif</translation>
-+<translation id="5558129378926964177">Zoom &amp;avant</translation>
-+<translation id="6451458296329894277">Confirmer le nouvel envoi du formulaire</translation>
-+<translation id="5116333507878097773"><ph name="NUMBER_ONE"/> heure</translation>
-+<translation id="8028152732786498049">Cet élément doit être installé depuis <ph name="CHROME_WEB_STORE"/>.</translation>
-+<translation id="9199258761842902152">Mise en veille ou reprise</translation>
-+<translation id="1851266746056575977">Mettre à jour maintenant</translation>
-+<translation id="7017219178341817193">Ajouter une page</translation>
-+<translation id="1038168778161626396">Chiffrer seulement</translation>
-+<translation id="2756651186786928409">Ne jamais intervertir les touches de modification</translation>
-+<translation id="1217515703261622005">Conversion des numéros spéciaux</translation>
-+<translation id="7179921470347911571">Relancer maintenant</translation>
-+<translation id="3715099868207290855">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée</translation>
-+<translation id="2679312662830811292">il y a <ph name="NUMBER_ONE"/> minute</translation>
-+<translation id="9065203028668620118">Édition</translation>
-+<translation id="4718464510840275738">Préférences synchronisées</translation>
-+<translation id="8788572795284305350"><ph name="NUMBER_ZERO"/> hours ago</translation>
-+<translation id="1177863135347784049">Personnalisé</translation>
-+<translation id="8236028464988198644">Rechercher à partir de la barre d'adresse</translation>
-+<translation id="4881695831933465202">Ouvrir</translation>
-+<translation id="5988520580879236902">Inspecter les vues actives :</translation>
-+<translation id="3593965109698325041">Contraintes de nom du certificat</translation>
-+<translation id="4358697938732213860">Ajouter une adresse</translation>
-+<translation id="8396532978067103567">Mot de passe incorrect.</translation>
-+<translation id="5981759340456370804">Statistiques avancées</translation>
-+<translation id="8160015581537295331">Clavier espagnol</translation>
-+<translation id="3505920073976671674">Sélectionnez votre réseau</translation>
-+<translation id="6644971472240498405"><ph name="NUMBER_ONE"/> jour</translation>
-+<translation id="1782924894173027610">Le serveur de synchronisation est occupé. Veuillez réessayer ultérieurement.</translation>
-+<translation id="6512448926095770873">Quitter cette page</translation>
-+<translation id="5457599981699367932">Naviguer en tant qu'invité</translation>
-+<translation id="3169472444629675720">Discover</translation>
-+<translation id="6294193300318171613">&amp;Toujours afficher la barre de favoris</translation>
-+<translation id="4088820693488683766">Options de recherche</translation>
-+<translation id="3414952576877147120">Taille :</translation>
-+<translation id="9098468523912235228">il y a <ph name="NUMBER_DEFAULT"/> secondes</translation>
-+<translation id="7009102566764819240">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur une ressource particulière. Si une ressource a été signalée comme site de phishing alors que vous êtes certain de sa fiabilité, cliquez sur le lien &quot;Signaler une erreur&quot;.</translation>
-+<translation id="4923417429809017348">Cette page rédigée dans une langue non identifiée a été traduite en <ph name="LANGUAGE_LANGUAGE"/>.</translation>
-+<translation id="3631337165634322335">Les exceptions ci-dessous s'appliquent uniquement à la session de navigation privée actuelle.</translation>
-+<translation id="676327646545845024">Ne plus afficher la boîte de dialogue pour les liens de ce type</translation>
-+<translation id="494645311413743213"><ph name="NUMBER_TWO"/> secondes restantes</translation>
-+<translation id="1485146213770915382">Insérez <ph name="SEARCH_TERMS_LITERAL"/> dans l'URL où les termes de recherche devraient apparaître.</translation>
-+<translation id="4839303808932127586">En&amp;registrer la vidéo sous...</translation>
-+<translation id="5626134646977739690">Nom :</translation>
-+<translation id="5854409662653665676">Si vous rencontrez des problèmes fréquents avec ce module, vous pouvez tenter d'y remédier en suivant la procédure ci-après :</translation>
-+<translation id="3681007416295224113">Informations relatives au certificat</translation>
-+<translation id="3046084099139788433">Activer l'onglet 7</translation>
-+<translation id="721197778055552897"><ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur ce problème.</translation>
-+<translation id="1699395855685456105">Version du matériel :</translation>
-+<translation id="212464871579942993">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur. Ce site héberge également des informations provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer des informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
-+<translation id="8156020606310233796">Afficher la liste</translation>
-+<translation id="957120528631539888">Désactivez l'affichage des messages de confirmation et le blocage de l'envoi des formulaires.</translation>
-+<translation id="146000042969587795">Ce cadre a été bloqué, car il contient des éléments non sécurisés.</translation>
-+<translation id="8112223930265703044">Tout</translation>
-+<translation id="3968739731834770921">Kana</translation>
-+<translation id="3729920814805072072">Gérer les mots de passe enregistrés...</translation>
-+<translation id="7387829944233909572">Boîte de dialogue &quot;Effacer les données de navigation&quot;</translation>
-+<translation id="8023801379949507775">Mettre à jour les extensions maintenant</translation>
-+<translation id="6549677549082720666">Nouvelle application en arrière-plan installée</translation>
-+<translation id="1983108933174595844">Envoyer une capture d'écran de la page actuelle</translation>
-+<translation id="3298789223962368867">L'URL indiquée est incorrecte.</translation>
-+<translation id="2202898655984161076">Un problème est survenu lors de l'affichage de la liste des imprimantes. Certaines de vos imprimantes ne sont peut-être pas correctement enregistrées dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
-+<translation id="6154697846084421647">Actuellement connecté</translation>
-+<translation id="8241707690549784388">La page que vous recherchez a utilisé des informations que vous avez envoyées. Si vous revenez sur cette page, chaque action précédemment effectuée sera répétée. Souhaitez-vous continuer ?</translation>
-+<translation id="5359419173856026110">Cette fonctionnalité indique la vitesse d'affichage réelle d'une page, en images par seconde, lorsque l'accélération matérielle est active.</translation>
-+<translation id="4104163789986725820">E&amp;xporter...</translation>
-+<translation id="2113479184312716848">&amp;Ouvrir un fichier...</translation>
-+<translation id="8412709057120877195">Configurer le contrôle d'accès pour vos périphériques</translation>
-+<translation id="486595306984036763">Ouvrir un rapport de phishing</translation>
-+<translation id="3140353188828248647">Activer la barre d'adresse</translation>
-+<translation id="4860787810836767172"><ph name="NUMBER_FEW"/> secs ago</translation>
-+<translation id="5565871407246142825">Cartes de paiement</translation>
-+<translation id="2587203970400270934">Code opérateur :</translation>
-+<translation id="3355936511340229503">Erreur de connexion</translation>
-+<translation id="1824910108648426227">Vous avez la possibilité de désactiver ces services.</translation>
-+<translation id="3092040396860056776">Essayer d'afficher la page malgré tout</translation>
-+<translation id="4350711002179453268">Impossible d'établir une connexion sécurisée avec le serveur. Le serveur a peut-être rencontré un problème ou exige un certificat d'authentification du client dont vous ne disposez pas.</translation>
-+<translation id="91731790394942114">Ajouter un nouveau nom</translation>
-+<translation id="5963026469094486319">Obtenir d'autres thèmes</translation>
-+<translation id="2441719842399509963">Rétablir les valeurs par défaut</translation>
-+<translation id="1893137424981664888">Aucun Plug-in installé.</translation>
-+<translation id="3718288130002896473">Action</translation>
-+<translation id="2168725742002792683">Extensions de fichier</translation>
-+<translation id="1753905327828125965">Les plus visités</translation>
-+<translation id="8116972784401310538">&amp;Gestionnaire de favoris</translation>
-+<translation id="1849632043866553433">Caches des applications</translation>
-+<translation id="3591607774768458617">Cette langue est actuellement utilisée par <ph name="PRODUCT_NAME"/>.</translation>
-+<translation id="621638399744152264"><ph name="VALUE"/> %</translation>
-+<translation id="4927301649992043040">Empaqueter l'extension</translation>
-+<translation id="8679658258416378906">Activer l'onglet 5</translation>
-+<translation id="4763816722366148126">Sélectionner le mode de saisie précédent</translation>
-+<translation id="6458308652667395253">Configurer le blocage de JavaScript...</translation>
-+<translation id="8435334418765210033">Réseaux mémorisés</translation>
-+<translation id="6516193643535292276">Impossible de se connecter à Internet.</translation>
-+<translation id="5125751979347152379">URL incorrecte</translation>
-+<translation id="2791364193466153585">Informations sur la sécurité</translation>
-+<translation id="4673916386520338632">Impossible d'installer l'application, car elle est en conflit avec &quot;<ph name="APP_NAME"/>&quot;, qui est déjà installé.</translation>
-+<translation id="2024918351532495204">Votre périphérique n'est pas connecté.</translation>
-+<translation id="6040143037577758943">Fermer</translation>
-+<translation id="5787146423283493983">Accord de la clé</translation>
-+<translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation>
-+<translation id="4265682251887479829">Vous ne trouvez pas ce que vous recherchez ?</translation>
-+<translation id="1804251416207250805">Désactivez l'envoi des pings de contrôle des liens hypertexte.</translation>
-+<translation id="5116628073786783676">En&amp;registrer le fichier audio sous...</translation>
-+<translation id="2557899542277210112">Accédez rapidement à vos favoris en les ajoutant à la barre de favoris.</translation>
-+<translation id="2749881179542288782">Vérifier la grammaire et l'orthographe</translation>
-+<translation id="5105855035535475848">Épingler les onglets</translation>
-+<translation id="6892450194319317066">Sélectionner par type d'application</translation>
-+<translation id="3549436232897695316">assembler</translation>
-+<translation id="5414121716219514204"><ph name="ENGINE_HOST_NAME"/> souhaite devenir votre moteur de recherche.</translation>
-+<translation id="2752805177271551234">Utiliser l'historique d'entrée</translation>
-+<translation id="7268365133021434339">Fermer les onglets</translation>
-+<translation id="4910619056351738551">Voici quelques suggestions :</translation>
-+<translation id="9131598836763251128">Sélectionnez un ou plusieurs fichiers</translation>
-+<translation id="5489059749897101717">Afficher le panneau de la &amp;vérification orthographique</translation>
-+<translation id="3423858849633684918">Veuillez relancer <ph name="PRODUCT_NAME"/>.</translation>
-+<translation id="1232569758102978740">Sans titre</translation>
-+<translation id="1903219944620007795">Pour saisir du texte, sélectionnez une langue et consultez la liste des modes de saisie disponibles.</translation>
-+<translation id="4362187533051781987">Ville</translation>
-+<translation id="9149866541089851383">Modifier...</translation>
-+<translation id="7608619752233383356">Réinitialiser la synchronisation</translation>
-+<translation id="1065245965611933814">Inclure une capture d'écran enregistrée :</translation>
-+<translation id="7876243839304621966">Tout supprimer</translation>
-+<translation id="5663459693447872156">Passer automatiquement en demi-chasse</translation>
-+<translation id="4593021220803146968">&amp;Accéder à <ph name="URL"/></translation>
-+<translation id="1128987120443782698">La capacité de ce périphérique de stockage est de <ph name="DEVICE_CAPACITY"/>. Veuillez insérer une carte SD ou une clé USB d'au moins 4 Go.</translation>
-+<translation id="869257642790614972">Rouvrir le dernier onglet fermé</translation>
-+<translation id="3978267865113951599">(blocage)</translation>
-+<translation id="8412145213513410671">Erreurs (<ph name="CRASH_COUNT"/>)</translation>
-+<translation id="560602183358579978">Traitement de la sélection...</translation>
-+<translation id="7649070708921625228">Aide</translation>
-+<translation id="5994107996638824097">Désolé ! La visionneuse de documents PDF intégrée à Google Chrome, nécessaire à l'affichage de l'aperçu avant impression, n'est pas incluse dans Chromium.</translation>
-+<translation id="976526967778596630">Impossible d'ouvrir <ph name="HOST_NAME"/>, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
-+<translation id="1734072960870006811">Télécopie</translation>
-+<translation id="3095995014811312755">version</translation>
-+<translation id="7052500709156631672">La passerelle ou le serveur proxy a reçu une réponse incorrecte d'un serveur en amont.</translation>
-+<translation id="281133045296806353">Nouvelle fenêtre ouverte dans la session du navigateur</translation>
-+<translation id="7144878232160441200">Réessayer</translation>
-+<translation id="2860002559146138960"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Vos données seront chiffrées avec le mot de passe de votre compte Google ou le mot de passe multiterme de votre choix.</translation>
-+<translation id="3951872452847539732">Les paramètres réseau de votre proxy sont gérés par une extension.</translation>
-+<translation id="6442697326824312960">Retirer l'onglet</translation>
-+<translation id="6382612843547381371">Valable du <ph name="START_DATE_TIME"/> au <ph name="END_DATE_TIME"/></translation>
-+<translation id="6869402422344886127">Case cochée</translation>
-+<translation id="5637380810526272785">Mode de saisie</translation>
-+<translation id="404928562651467259">AVERTISSEMENT</translation>
-+<translation id="7172053773111046550">Clavier estonien</translation>
-+<translation id="497490572025913070">Ajout de bordures aux couches de rendu composées</translation>
-+<translation id="9002707937526687073">Imp&amp;rimer...</translation>
-+<translation id="5953934840931207585">Paramètres de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
-+<translation id="5556459405103347317">Rafraîchir</translation>
-+<translation id="8000020256436988724">Barre d'outils</translation>
-+<translation id="8326395326942127023">Nom de la base de données :</translation>
-+<translation id="7507930499305566459">Certificat du répondeur d'état</translation>
-+<translation id="2689915906323125315">Utiliser le mot de passe de mon compte Google</translation>
-+<translation id="6440205424473899061">Vos favoris sont maintenant synchronisés avec Google Documents !
-+Pour fusionner et synchroniser vos favoris dans <ph name="PRODUCT_NAME"/> sur un autre ordinateur, procédez de la même manière que précédemment sur l'ordinateur voulu.</translation>
-+<translation id="7727721885715384408">Renommer...</translation>
-+<translation id="2604243255129603442"><ph name="NAME_OF_EXTENSION"/> a été désactivé. Si vous arrêtez la synchronisation des favoris, vous pouvez la réactiver sur la page des extensions, via le menu Outils.</translation>
-+<translation id="2024621544377454980">Affichage des pages impossible</translation>
-+<translation id="7136694880210472378">Utiliser par défaut</translation>
-+<translation id="7681202901521675750">La carte SIM est verrouillée. Veuillez saisir votre code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
-+<translation id="1731346223650886555">Point-virgule</translation>
-+<translation id="158849752021629804">Réseau domestique requis</translation>
-+<translation id="7339763383339757376">PKCS #7, certificat unique</translation>
-+<translation id="7587108133605326224">Langues baltes</translation>
-+<translation id="3991936620356087075">Vous avez saisi un trop grand nombre de clés de verrouillage du code PIN incorrectes. Votre carte SIM est définitivement désactivée.</translation>
-+<translation id="936801553271523408">Données de diagnostic système</translation>
-+<translation id="6389701355360299052">Page Web, contenu HTML uniquement</translation>
-+<translation id="8067791725177197206">Continuer »</translation>
-+<translation id="9009144784540995197">Gérez vos imprimantes.</translation>
-+<translation id="1055006259534905434">(Choisir un problème dans la liste ci-dessous)</translation>
-+<translation id="3021678814754966447">&amp;Afficher le code source du cadre</translation>
-+<translation id="8601206103050338563">Authentification du client WWW TLS</translation>
-+<translation id="1692799361700686467">Les cookies de plusieurs sites sont autorisés.</translation>
-+<translation id="7074488040076962230">Impossible d'afficher la page de la barre latérale &quot;<ph name="SIDEBAR_PAGE"/>&quot;.</translation>
-+<translation id="529232389703829405">Vous avez acheté <ph name="DATA_AMOUNT"/> de données le <ph name="DATE"/>.</translation>
-+<translation id="5271549068863921519">Enregistrer le mot de passe</translation>
-+<translation id="4345587454538109430">Configurer...</translation>
-+<translation id="8148264977957212129">Mode de saisie du pinyin</translation>
-+<translation id="5787378733537687553">Intervertir les touches Ctrl et Alt de gauche</translation>
-+<translation id="7772032839648071052">Confirmer le mot de passe multiterme</translation>
-+<translation id="6857811139397017780">Activer <ph name="NETWORKSERVICE"/></translation>
-+<translation id="3251855518428926750">Ajouter...</translation>
-+<translation id="4120075327926916474">Voulez-vous que Google Chrome enregistre ces informations de carte de paiement pour le remplissage de formulaires Web ?</translation>
-+<translation id="6929555043669117778">Continuer à bloquer les fenêtres pop-up</translation>
-+<translation id="5864471791310927901">Échec de la vérification DHCP</translation>
-+<translation id="3508920295779105875">Choisir un autre dossier...</translation>
-+<translation id="2503458975635466059">Le profil semble être utilisé par le processus <ph name="PROCESS_ID"/> sur l'hôte <ph name="HOST_NAME"/>. Si vous êtes certain qu'aucun autre processus n'utilise ce profil, supprimez le fichier <ph name="LOCK_FILE"/> et relancez <ph name="PRODUCT_NAME"/>.</translation>
-+<translation id="2987775926667433828">Chinois traditionnel</translation>
-+<translation id="6684737638449364721">Effacer les données de navigation...</translation>
-+<translation id="3954582159466790312">Ré&amp;activer le son</translation>
-+<translation id="1110772031432362678">Aucun réseau trouvé.</translation>
-+<translation id="3936390757709632190">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
-+<translation id="7297622089831776169">&amp;Méthodes d'entrée</translation>
-+<translation id="5731698828607291678">Onglets ou fenêtres</translation>
-+<translation id="1152775729948968688">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer le comportement de cette page.</translation>
-+<translation id="604124094241169006">Automatique</translation>
-+<translation id="862542460444371744">&amp;Extensions</translation>
-+<translation id="8045462269890919536">Roumain</translation>
-+<translation id="6320286250305104236">Paramètres du réseau...</translation>
-+<translation id="2927657246008729253">Changer...</translation>
-+<translation id="7978412674231730200">Clé privée</translation>
-+<translation id="464745974361668466">Format :</translation>
-+<translation id="5308380583665731573">Se connecter</translation>
-+<translation id="9111395131601239814"><ph name="NETWORKDEVICE"/> : <ph name="STATUS"/></translation>
-+<translation id="9049981332609050619">Vous avez tenté de contacter <ph name="DOMAIN"/>, mais le certificat présenté par le serveur est incorrect.</translation>
-+<translation id="4414232939543644979">Nouvelle fenêtre de nav&amp;igation privée</translation>
-+<translation id="1693754753824026215">La page à l'adresse <ph name="SITE"/> indique :</translation>
-+<translation id="7148804936871729015">Le serveur associé à <ph name="URL"/> n'a pas répondu à temps. Cela peut être dû à une surcharge.</translation>
-+<translation id="5950967683057767490">L2TP/IPSec + Clé pré-partagée</translation>
-+<translation id="8108473539339615591">XSS Auditor</translation>
-+<translation id="1902576642799138955">Durée de validité</translation>
-+<translation id="4910021444507283344">WebGL</translation>
-+<translation id="6692173217867674490">Mot de passe multiterme erroné</translation>
-+<translation id="5550431144454300634">Corriger automatiquement la saisie</translation>
-+<translation id="3308006649705061278">Unité d'organisation</translation>
-+<translation id="8912362522468806198">Compte Google</translation>
-+<translation id="4443536555189480885">&amp;Aide</translation>
-+<translation id="340485819826776184">Utiliser un service de prédiction afin de compléter les recherches et les URL saisies dans la barre d'adresse</translation>
-+<translation id="4074900173531346617">Certificat du signataire de courrier électronique</translation>
-+<translation id="6165508094623778733">En savoir plus</translation>
-+<translation id="9052208328806230490">Vous avez enregistré vos imprimantes sur <ph name="CLOUD_PRINT_NAME"/> via le compte <ph name="EMAIL"/>.</translation>
-+<translation id="822618367988303761">il y a <ph name="NUMBER_TWO"/> jours</translation>
-+<translation id="7928333295097642153"><ph name="HOUR"/>:<ph name="MINUTE"/> restantes</translation>
-+<translation id="7568593326407688803">Cette page est en<ph name="ORIGINAL_LANGUAGE"/>Voulez-vous la traduire ?</translation>
-+<translation id="563969276220951735">Saisie automatique des formulaires</translation>
-+<translation id="6870130893560916279">Clavier ukrainien</translation>
-+<translation id="8629974950076222828">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
-+<translation id="3126026824346185272">Ctrl</translation>
-+<translation id="4745438305783437565"><ph name="NUMBER_FEW"/> minutes</translation>
-+<translation id="2649911884196340328">Le certificat de sécurité du serveur contient des erreurs !</translation>
-+<translation id="6666647326143344290">avec votre compte Google</translation>
-+<translation id="3828029223314399057">Rechercher dans les favoris</translation>
-+<translation id="4885705234041587624">MSCHAPv2</translation>
-+<translation id="5614190747811328134">Avertissement utilisateur</translation>
-+<translation id="8906421963862390172">&amp;Options du vérificateur d'orthographe</translation>
-+<translation id="9046895021617826162">Échec de la connexion</translation>
-+<translation id="1492188167929010410">Identifiant de l'erreur <ph name="CRASH_ID"/></translation>
-+<translation id="1963692530539281474"><ph name="NUMBER_DEFAULT"/> jours restants</translation>
-+<translation id="4470270245053809099">Émis par : <ph name="NAME"/></translation>
-+<translation id="5365539031341696497">Mode de saisie du thaï (clavier Kesmanee)</translation>
-+<translation id="2403091441537561402">Passerelle :</translation>
-+<translation id="6337234675334993532">Chiffrement</translation>
-+<translation id="668171684555832681">Autre...</translation>
-+<translation id="1932098463447129402">Pas avant le</translation>
-+<translation id="7845920762538502375"><ph name="PRODUCT_NAME"/> n'a pas pu synchroniser vos données, car la connexion avec le serveur de synchronisation n'a pas pu être établie. Nouvel essai...</translation>
-+<translation id="2192664328428693215">Me demander lorsqu'un site souhaite afficher des notifications sur le Bureau (recommandé)</translation>
-+<translation id="6708242697268981054">Source :</translation>
-+<translation id="4786993863723020412">Erreur de lecture du cache</translation>
-+<translation id="6630452975878488444">Raccourci de sélection</translation>
-+<translation id="8709969075297564489">Vérifier la révocation du certificat serveur</translation>
-+<translation id="8698171900303917290">Vous rencontrez des problèmes lors de l'installation ?</translation>
-+<translation id="830868413617744215">Bêta</translation>
-+<translation id="5925147183566400388">Pointeur de la déclaration CPS (Certification Practice Statement)</translation>
-+<translation id="1497270430858433901">Le <ph name="DATE"/>, vous avez reçu <ph name="DATA_AMOUNT"/> à utiliser librement.</translation>
-+<translation id="8150167929304790980">Nom complet</translation>
-+<translation id="636850387210749493">Inscription d'entreprise</translation>
-+<translation id="1947424002851288782">Clavier allemand</translation>
-+<translation id="932508678520956232">Impossible de lancer l'impression.</translation>
-+<translation id="4861833787540810454">&amp;Lire</translation>
-+<translation id="2552545117464357659">Récent</translation>
-+<translation id="7269802741830436641">Cette page Web présente une boucle de redirection.</translation>
-+<translation id="4180788401304023883">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; émis par l'autorité de certification ?</translation>
-+<translation id="5869522115854928033">Mots de passe enregistrés</translation>
-+<translation id="2089090684895656482">Moins</translation>
-+<translation id="1709220265083931213">Options avancées</translation>
-+<translation id="5748266869826978907">Vérifiez vos paramètres DNS. Contactez votre administrateur réseau si vous n'êtes pas sûr de vous.</translation>
-+<translation id="4771973620359291008">Une erreur inconnue s'est produite.</translation>
-+<translation id="5509914365760201064">Émetteur : <ph name="CERTIFICATE_AUTHORITY"/></translation>
-+<translation id="7073385929680664879">Passer d'un mode de saisie à l'autre</translation>
-+<translation id="6898699227549475383">Organisation (O)</translation>
-+<translation id="4333854382783149454">PKCS #1 SHA-1 avec chiffrement RSA</translation>
-+<translation id="762904068808419792">Entrez la requête de recherche ici.</translation>
-+<translation id="8615618338313291042">Application en mode navigation privée : <ph name="APP_NAME"/></translation>
-+<translation id="978146274692397928">La largeur de ponctuation initiale est Complète</translation>
-+<translation id="8959027566438633317">Installer <ph name="EXTENSION_NAME"/> ?</translation>
-+<translation id="8155798677707647270">Installation d'une nouvelle version...</translation>
-+<translation id="6886871292305414135">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
-+<translation id="1639192739400715787">Pour accéder aux paramètres de sécurité, saisissez le code PIN de la carte SIM.</translation>
-+<translation id="7961015016161918242">Jamais</translation>
-+<translation id="3950924596163729246">Impossible d'accéder au réseau.</translation>
-+<translation id="2835170189407361413">Effacer le formulaire</translation>
-+<translation id="4631110328717267096">Échec de la mise à jour du système</translation>
-+<translation id="3695919544155087829">Saisissez le mot de passe utilisé pour chiffrer ce fichier de certificat.</translation>
-+<translation id="2230051135190148440">CHAP</translation>
-+<translation id="6308937455967653460">Enregistrer le lie&amp;n sous...</translation>
-+<translation id="5421136146218899937">Effacer les données de navigation...</translation>
-+<translation id="5783059781478674569">Options de reconnaissance vocale</translation>
-+<translation id="5441100684135434593">Réseau câblé</translation>
-+<translation id="3285322247471302225">Nouvel ongle&amp;t</translation>
-+<translation id="3943582379552582368">R&amp;etour</translation>
-+<translation id="7607002721634913082">Téléchargement suspendu</translation>
-+<translation id="480990236307250886">Ouvrir la page d'accueil</translation>
-+<translation id="8286036467436129157">Connexion</translation>
-+<translation id="5999940714422617743">L'installation de <ph name="EXTENSION_NAME"/> est terminée.</translation>
-+<translation id="1122198203221319518">&amp;Outils</translation>
-+<translation id="5757539081890243754">Page d'accueil</translation>
-+<translation id="2760009672169282879">Clavier phonétique bulgare</translation>
-+<translation id="6608140561353073361">Cookies et données de site...</translation>
-+<translation id="8007030362289124303">Batterie faible</translation>
-+<translation id="4513946894732546136">Commentaires</translation>
-+<translation id="1135328998467923690">Package incorrect : &quot;<ph name="ERROR_CODE"/>&quot;.</translation>
-+<translation id="5906719743126878045"><ph name="NUMBER_TWO"/> heures restantes</translation>
-+<translation id="1753682364559456262">Configurer les paramètres de blocage des images...</translation>
-+<translation id="6550675742724504774">Options</translation>
-+<translation id="8959208747503200525"><ph name="NUMBER_TWO"/> hours ago</translation>
-+<translation id="431076611119798497">&amp;Détails</translation>
-+<translation id="737801893573836157">Masquer la barre de titre du système et utiliser les bordures</translation>
-+<translation id="5352235189388345738">Elle peut accéder aux éléments suivants :</translation>
-+<translation id="5040262127954254034">Confidentialité</translation>
-+<translation id="7666868073052500132">Objets : <ph name="USAGES"/></translation>
-+<translation id="6985345720668445131">Paramètres d'entrée du japonais</translation>
-+<translation id="3258281577757096226">Sebeol-sik Final</translation>
-+<translation id="6906268095242253962">Veuillez vous connecter à Internet pour continuer.</translation>
-+<translation id="1908748899139377733">Afficher les &amp;infos sur le cadre</translation>
-+<translation id="803771048473350947">Fichier</translation>
-+<translation id="6206311232642889873">Cop&amp;ier l'image</translation>
-+<translation id="5158983316805876233">Utiliser le même proxy pour tous les protocoles</translation>
-+<translation id="7108338896283013870">Masquer</translation>
-+<translation id="3366404380928138336">Requête de protocole externe</translation>
-+<translation id="5300589172476337783">Afficher</translation>
-+<translation id="3160041952246459240">Certains de vos certificats enregistrés identifient ces serveurs :</translation>
-+<translation id="566920818739465183">Vous avez visité ce site pour la première fois le <ph name="VISIT_DATE"/>.</translation>
-+<translation id="2961695502793809356">Cliquer pour avancer, maintenir pour voir l'historique</translation>
-+<translation id="4092878864607680421">La dernière version de l'application &quot;<ph name="APP_NAME"/>&quot; requiert d'autres autorisations. Elle a donc été désactivée.</translation>
-+<translation id="8421864404045570940"><ph name="NUMBER_DEFAULT"/> secondes</translation>
-+<translation id="5828228029189342317">Vous avez choisi d'ouvrir automatiquement certains types de fichiers après leur téléchargement.</translation>
-+<translation id="1416836038590872660">EAP-MD5</translation>
-+<translation id="176587472219019965">&amp;Nouvelle fenêtre</translation>
-+<translation id="2788135150614412178">+</translation>
-+<translation id="4055738107007928968">Vous avez essayé d'accéder au site <ph name="DOMAIN"/>, mais le serveur a présenté un certificat signé avec un algorithme de signature faible. Il se peut que les informations d'identification fournies par le serveur aient été falsifiées. Le serveur n'est peut-être pas celui auquel vous souhaitez accéder (il peut s'agir d'une tentative de piratage). Nous nous déconseillons vivement de continuer.</translation>
-+<translation id="5308689395849655368">L'envoi de rapports d'erreur est désactivé.</translation>
-+<translation id="8372369524088641025">Clé WEP incorrecte</translation>
-+<translation id="8689341121182997459">Date d'expiration :</translation>
-+<translation id="899403249577094719">URL de base du certificat Netscape</translation>
-+<translation id="2737363922397526254">Réduire...</translation>
-+<translation id="4880827082731008257">Rechercher dans l'historique</translation>
-+<translation id="8661290697478713397">Ouvrir le lien dans la fenêtre de navi&amp;gation privée</translation>
-+<translation id="4197700912384709145"><ph name="NUMBER_ZERO"/> secondes</translation>
-+<translation id="7454780465968211330">Historique avancé pour le champ polyvalent</translation>
-+<translation id="2158448795143567596">Active l'utilisation de graphismes 3D dans les éléments canvas via l'API WebGL.</translation>
-+<translation id="1702534956030472451">Occident</translation>
-+<translation id="6636709850131805001">État non reconnu</translation>
-+<translation id="6095984072944024315">−</translation>
-+<translation id="9141716082071217089">Impossible de vérifier si le certificat du serveur a été révoqué.</translation>
-+<translation id="4304224509867189079">Se connecter</translation>
-+<translation id="5332624210073556029">Fuseau horaire :</translation>
-+<translation id="4799797264838369263">Cette option est soumise à une stratégie d'entreprise. Contactez votre administrateur pour plus d'informations.</translation>
-+<translation id="4492190037599258964">Résultats de recherche pour &quot;<ph name="SEARCH_STRING"/>&quot;</translation>
-+<translation id="3573179567135747900">Revenir à &quot;<ph name="FROM_LOCALE"/>&quot; (redémarrage requis)</translation>
-+<translation id="2238123906478057869"><ph name="PRODUCT_NAME"/> va exécuter les tâches suivantes :</translation>
-+<translation id="4042471398575101546">Ajouter la page</translation>
-+<translation id="8848709220963126773">Changement de mode via la touche Maj</translation>
-+<translation id="4871865824885782245">Options de date et d'heure...</translation>
-+<translation id="8828933418460119530">Nom DNS</translation>
-+<translation id="988159990683914416">Build de développement</translation>
-+<translation id="8026354464835030469"><ph name="BURNT_AMOUNT"/> sur ...</translation>
-+<translation id="4114470632216071239">Verrouiller la carte SIM (code PIN obligatoire pour utiliser les données mobiles)</translation>
-+<translation id="2183426022964444701">Sélectionnez le répertoire racine de l'extension.</translation>
-+<translation id="2517143724531502372">Les cookies de <ph name="DOMAIN"/> sont autorisés uniquement pour cette session.</translation>
-+<translation id="9018524897810991865">Confirmer les préférences de synchronisation</translation>
-+<translation id="4719905780348837473">RSN</translation>
-+<translation id="5212108862377457573">Ajuster la conversion en fonction de l'entrée précédente</translation>
-+<translation id="5398353896536222911">Afficher le panneau de la &amp;vérification orthographique</translation>
-+<translation id="5811533512835101223">(Revenir à la capture d'écran d'origine)</translation>
-+<translation id="5131817835990480221">Mettre à jour &amp;<ph name="PRODUCT_NAME"/></translation>
-+<translation id="939519157834106403">SSID</translation>
-+<translation id="3705722231355495246">-</translation>
-+<translation id="2635102990349508383">Les informations de connexion au compte n'ont pas encore été saisies.</translation>
-+<translation id="6902055721023340732">URL de configuration automatique</translation>
-+<translation id="4268574628540273656">URL :</translation>
-+<translation id="7481312909269577407">Avancer</translation>
-+<translation id="3759876923365568382"><ph name="NUMBER_FEW"/> jours restants</translation>
-+<translation id="295228163843771014">Vous avez choisi de ne pas synchroniser les mots de passe. Vous pouvez à tout moment modifier vos paramètres de synchronisation, si vous changez d'avis.</translation>
-+<translation id="5972826969634861500">Lancer <ph name="PRODUCT_NAME"/></translation>
-+<translation id="7828702903116529889"><ph name="PRODUCT_NAME"/>
-+ ne parvient pas à accéder au réseau.
-+ <ph name="LINE_BREAK"/>
-+ Il est possible que votre pare-feu ou votre antivirus considère
-+ <ph name="PRODUCT_NAME"/>
-+ comme un intrus dans votre ordinateur et qu'il bloque ses tentatives de connexion à Internet.</translation>
-+<translation id="878069093594050299">Ce certificat a été vérifié pour les utilisations suivantes :</translation>
-+<translation id="5852112051279473187">Petit problème ! Une erreur est survenue lors de l'inscription de ce périphérique. Veuillez réessayer ou contacter votre représentant de l'assistance technique.</translation>
-+<translation id="1664314758578115406">Ajouter aux favoris</translation>
-+<translation id="7088418943933034707">Gérer les certificats...</translation>
-+<translation id="8482183012530311851">Analyse du périphérique...</translation>
-+<translation id="3127589841327267804">PYJJ</translation>
-+<translation id="8808478386290700967">Web Store</translation>
-+<translation id="1732215134274276513">Annuler l'épinglage des onglets</translation>
-+<translation id="4084682180776658562">Favori</translation>
-+<translation id="8859057652521303089">Sélectionnez votre langue :</translation>
-+<translation id="3030138564564344289">Réessayer le téléchargement</translation>
-+<translation id="8525552230188318924">Configurer la synchronisation des mots de passe</translation>
-+<translation id="4381091992796011497">Nom d'utilisateur :</translation>
-+<translation id="5830720307094128296">Enregistrer la p&amp;age sous...</translation>
-+<translation id="8114439576766120195">Vos données sur tous les sites Web</translation>
-+<translation id="4668954208278016290">Un problème est survenu lors de l'extraction de l'image sur l'ordinateur.</translation>
-+<translation id="5822838715583768518">Lancer l'application</translation>
-+<translation id="3942974664341190312">Dubeol-sik</translation>
-+<translation id="8477241577829954800">Remplacé</translation>
-+<translation id="6735304988756581115">Afficher les cookies et autres données de site...</translation>
-+<translation id="3048564749795856202">Si vous pensez avoir cerné les risques, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
-+<translation id="2433507940547922241">Apparence</translation>
-+<translation id="839072384475670817">Créer des raccourci&amp;s vers des applications...</translation>
-+<translation id="1478632774608054702">Exécuter le flash PPAPI dans le processus du moteur de rendu</translation>
-+<translation id="6756161853376828318">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
-+<translation id="9112614144067920641">Veuillez choisir un nouveau code PIN.</translation>
-+<translation id="2061855250933714566"><ph name="ENCODING_CATEGORY"/> (<ph name="ENCODING_NAME"/>)</translation>
-+<translation id="7138678301420049075">Autre</translation>
-+<translation id="9147392381910171771">&amp;Options</translation>
-+<translation id="1803557475693955505">Impossible de charger la page d'arrière-plan &quot;<ph name="BACKGROUND_PAGE"/>&quot;.</translation>
-+<translation id="5818334088068591797">À quel niveau rencontrez-vous des problèmes ? (Champ obligatoire)</translation>
-+<translation id="6264485186158353794">Retour à la sécurité</translation>
-+<translation id="5130080518784460891">Eten</translation>
-+<translation id="5847724078457510387">Ce site répertorie tous ses certificats valides dans le système DNS. Un certificat non répertorié a cependant été utilisé par le serveur.</translation>
-+<translation id="1394853081832053657">Options de reconnaissance vocale</translation>
-+<translation id="5037676449506322593">Tout sélectionner</translation>
-+<translation id="2785530881066938471">Impossible de charger le fichier &quot;<ph name="RELATIVE_PATH"/>&quot; pour le script de contenu, car ce fichier n'est pas codé en UTF-8.</translation>
-+<translation id="3807747707162121253">&amp;Annuler</translation>
-+<translation id="3306897190788753224">Désactiver temporairement la personnalisation des conversions, les suggestions basées sur l'historique et le dictionnaire utilisateur</translation>
-+<translation id="2574102660421949343">Les cookies de <ph name="DOMAIN"/> sont autorisés.</translation>
-+<translation id="77999321721642562">Au fil du temps, la zone ci-dessous affichera les huit sites que vous avez le plus visités.</translation>
-+<translation id="1503894213707460512">Le plug-in <ph name="PLUGIN_NAME"/> a besoin de votre autorisation pour s'exécuter.</translation>
-+<translation id="471800408830181311">Échec de création de clé privée</translation>
-+<translation id="1273291576878293349">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
-+<translation id="1639058970766796751">Placer dans la file d'attente</translation>
-+<translation id="1177437665183591855">Erreur de certificat serveur inconnue</translation>
-+<translation id="8467473010914675605">Mode de saisie du coréen</translation>
-+<translation id="3819800052061700452">&amp;Plein écran</translation>
-+<translation id="5419540894229653647"><ph name="ERROR_DESCRIPTION_TEXT"/>
-+ <ph name="LINE_BREAK"/>
-+ Vous pouvez essayer de diagnostiquer le problème en procédant comme suit :
-+ <ph name="LINE_BREAK"/>
-+ <ph name="PLATFORM_TEXT"/></translation>
-+<translation id="3533943170037501541">Bienvenue sur votre page d'accueil !</translation>
-+<translation id="2333340435262918287">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
-+<translation id="5906065664303289925">Adresse du matériel :</translation>
-+<translation id="3178000186192127858">Lecture seule</translation>
-+<translation id="2187895286714876935">Erreur d'importation du certificat serveur</translation>
-+<translation id="5460896875189097758">Données stockées localement</translation>
-+<translation id="4618990963915449444">Tous les fichiers de <ph name="DEVICE_NAME"/> vont être effacés.</translation>
-+<translation id="614998064310228828">Modèle du périphérique :</translation>
-+<translation id="1581962803218266616">Afficher dans le Finder</translation>
-+<translation id="6096326118418049043">Nom X.500</translation>
-+<translation id="6086259540486894113">Vous devez sélectionner au moins un type de données à synchroniser.</translation>
-+<translation id="923467487918828349">Tout afficher</translation>
-+<translation id="5101042277149003567">Ouvrir tous les favoris</translation>
-+<translation id="4298972503445160211">Clavier danois</translation>
-+<translation id="6621440228032089700">Cette fonctionnalité permet de réaliser un rendu hors écran de la texture, au lieu d'un affichage direct.</translation>
-+<translation id="3488065109653206955">Partiellement activé</translation>
-+<translation id="1481244281142949601">Votre système Sandbox est correctement configuré.</translation>
-+<translation id="4849517651082200438">Ne pas installer</translation>
-+<translation id="8602882075393902833">Activer la recherche instantanée pour accélérer la recherche et la navigation</translation>
-+<translation id="6349678711452810642">Utiliser par défaut</translation>
-+<translation id="6263284346895336537">Non essentielle</translation>
-+<translation id="6409731863280057959">Fenêtres pop-up</translation>
-+<translation id="3459774175445953971">Dernière modification :</translation>
-+<translation id="73289266812733869">Désélectionné</translation>
-+<translation id="3435738964857648380">Sécurité</translation>
-+<translation id="9112987648460918699">Rechercher...</translation>
-+<translation id="2231233239095101917">Le script de la page utilisait trop de mémoire. Rafraîchissez la page pour réactiver le script.</translation>
-+<translation id="870805141700401153">Signature du code individuel Microsoft</translation>
-+<translation id="5119173345047096771">Mozilla Firefox</translation>
-+<translation id="9020278534503090146">Page Web inaccessible</translation>
-+<translation id="4768698601728450387">Recadrer l'image</translation>
-+<translation id="6245028464673554252">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, le téléchargement sera annulé.</translation>
-+<translation id="3943857333388298514">Coller</translation>
-+<translation id="385051799172605136">Retour</translation>
-+<translation id="1742300158964248589">Impossible de graver l'image.</translation>
-+<translation id="2670965183549957348">Mode de saisie du Chewing</translation>
-+<translation id="5095208057601539847">Province</translation>
-+<translation id="4085298594534903246">JavaScript a été bloqué sur cette page.</translation>
-+<translation id="5630492933376732170">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome OS
-+ joint à votre envoi un journal des événements système de
-+ votre périphérique. Ces informations nous permettent de diagnostiquer les
-+ problèmes, de comprendre comment vous interagissez avec votre
-+ périphérique et d'améliorer les performances de ce dernier. Les
-+ informations personnelles fournies sciemment dans vos commentaires ou
-+ involontairement dans les journaux système et la capture d'écran sont
-+ protégées conformément à nos <ph name="BEGIN_LINK"/>Règles de confidentialité<ph name="END_LINK"/>.
-+ Si vous ne souhaitez pas envoyer de journaux système, décochez la case
-+ &quot;Inclure les informations système&quot;.</translation>
-+<translation id="4341977339441987045">Interdire à tous les sites de stocker des données</translation>
-+<translation id="806812017500012252">Trier par nom</translation>
-+<translation id="3781751432212184938">Afficher un aperçu des onglets...</translation>
-+<translation id="2960316970329790041">Annuler l'importation</translation>
-+<translation id="3835522725882634757">Ce serveur envoie des données que <ph name="PRODUCT_NAME"/> ne comprend pas. Veuillez <ph name="BEGIN_LINK"/>signaler un bug<ph name="END_LINK"/> et inclure la <ph name="BEGIN2_LINK"/>liste des raw<ph name="END2_LINK"/>.</translation>
-+<translation id="5361734574074701223">Calcul de la durée restante</translation>
-+<translation id="6937152069980083337">Mode de saisie Google du japonais (pour clavier américain)</translation>
-+<translation id="1731911755844941020">Envoi de la requête...</translation>
-+<translation id="8371695176452482769">Parlez maintenant</translation>
-+<translation id="2988488679308982380">Impossible d'installer le package : &quot;<ph name="ERROR_CODE"/>&quot;</translation>
-+<translation id="2904079386864173492">Modèle :</translation>
-+<translation id="3447644283769633681">Bloquer tous les cookies tiers</translation>
-+<translation id="8917047707340793412">Remplacer par <ph name="ENGINE_NAME"/></translation>
-+<translation id="6129953537138746214">Espace</translation>
-+<translation id="3704331259350077894">Arrêt du fonctionnement</translation>
-+<translation id="5801568494490449797">Préférences</translation>
-+<translation id="1038842779957582377">Nom inconnu</translation>
-+<translation id="5327248766486351172">Nom</translation>
-+<translation id="5553784454066145694">Choisir un nouveau code PIN</translation>
-+<translation id="8989148748219918422"><ph name="ORGANIZATION"/> [<ph name="COUNTRY"/>]</translation>
-+<translation id="4664482161435122549">Erreur d'exportation de fichier PKCS #12</translation>
-+<translation id="2445081178310039857">Le répertoire racine de l'extension doit être indiqué.</translation>
-+<translation id="8251578425305135684">Miniature supprimée</translation>
-+<translation id="6163522313638838258">Tout développer...</translation>
-+<translation id="3037605927509011580">Aie aie aie</translation>
-+<translation id="5803531701633845775">Choisir les expressions en arrière-plan, sans déplacer le pointeur</translation>
-+<translation id="1918141783557917887">Plu&amp;s petit</translation>
-+<translation id="6996550240668667907">Afficher le clavier en superposition</translation>
-+<translation id="4065006016613364460">C&amp;opier l'URL de l'image</translation>
-+<translation id="6965382102122355670">OK</translation>
-+<translation id="8000066093800657092">Aucun réseau détecté</translation>
-+<translation id="4481249487722541506">Charger l'extension non empaquetée...</translation>
-+<translation id="8180239481735238521">page</translation>
-+<translation id="8321738493186308836">Active l'interface utilisateur et le code de support pour le processus du service de communication à distance, de même que le plug-in client. Avertissement : ce service n'est actuellement disponible que pour les tests de développeurs. Si vous ne faites pas partie de l'équipe de développement et ne figurez pas sur la liste blanche, aucun élément de l'interface utilisateur activée ne fonctionnera.</translation>
-+<translation id="2963783323012015985">Clavier turc</translation>
-+<translation id="2149973817440762519">Modifier le favori</translation>
-+<translation id="5431318178759467895">Couleur</translation>
-+<translation id="7064842770504520784">Personnaliser les paramètres de synchronisation...</translation>
-+<translation id="2784407158394623927">Activation de votre service Internet mobile</translation>
-+<translation id="3679848754951088761"><ph name="SOURCE_ORIGIN"/></translation>
-+<translation id="6920989436227028121">Ouvrir dans un onglet standard</translation>
-+<translation id="4057041477816018958"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/></translation>
-+<translation id="2050339315714019657">Portrait</translation>
-+<translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation>
-+<translation id="6139139147415955203">Active un service en arrière-plan qui connecte le service <ph name="CLOUD_PRINT_NAME"/> aux éventuelles imprimantes installées sur cet ordinateur. Une fois ce labo activé, vous pouvez lancer <ph name="CLOUD_PRINT_NAME"/> en vous connectant à votre compte Google via Options/Préférences dans la section Options avancées.</translation>
-+<translation id="5112577000029535889">Outils de &amp;développement</translation>
-+<translation id="2301382460326681002">Le répertoire racine de l'extension est incorrect.</translation>
-+<translation id="7839192898639727867">ID de clé de l'objet du certificat</translation>
-+<translation id="4759238208242260848">Téléchargements</translation>
-+<translation id="2879560882721503072">Le stockage du certificat client généré par <ph name="ISSUER"/> a réussi.</translation>
-+<translation id="1275718070701477396">Sélectionnée</translation>
-+<translation id="1178581264944972037">Suspendre</translation>
-+<translation id="6492313032770352219">Taille sur le disque :</translation>
-+<translation id="5233231016133573565">ID du processus</translation>
-+<translation id="5941711191222866238">Réduire</translation>
-+<translation id="4121428309786185360">Expire le</translation>
-+<translation id="2049137146490122801">Votre administrateur a désactivé l'accès aux fichiers locaux sur votre ordinateur.</translation>
-+<translation id="1146498888431277930">Erreur de connexion SSL</translation>
-+<translation id="8041089156583427627">Envoyer</translation>
-+<translation id="6394627529324717982">Virgule</translation>
-+<translation id="253434972992662860">&amp;Pause</translation>
-+<translation id="335985608243443814">Parcourir...</translation>
-+<translation id="7802488492289385605">Mode de saisie Google du japonais (pour clavier Dvorak américain)</translation>
-+<translation id="7452120598248906474">Police à largeur fixe</translation>
-+<translation id="3129687551880844787">Stockage de session</translation>
-+<translation id="7427348830195639090">Page en arrière-plan : <ph name="BACKGROUND_PAGE_URL"/></translation>
-+<translation id="5898154795085152510">Le serveur a renvoyé un certificat client incorrect. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
-+<translation id="2704184184447774363">Signature de document Microsoft</translation>
-+<translation id="5677928146339483299">Bloqué</translation>
-+<translation id="1474842329983231719">Gérer les paramètres d'impression...</translation>
-+<translation id="2455981314101692989">Cette page Web a désactivé la saisie automatique dans ce formulaire.</translation>
-+<translation id="1646136617204068573">Clavier hongrois</translation>
-+<translation id="5988840637546770870">Les versions en développement permettent de tester de nouvelles idées, mais elles peuvent s'avérer très instables. Nous vous prions d'agir avec précaution.</translation>
-+<translation id="3569713929051927529">Ajouter un dossier...</translation>
-+<translation id="4032664149172368180">Mode de saisie du japonais (pour clavier Dvorak américain)</translation>
-+<translation id="3748706263662799310">Signaler un bug</translation>
-+<translation id="7167486101654761064">&amp;Toujours ouvrir les fichiers de ce type</translation>
-+<translation id="4283623729247862189">Disque optique</translation>
-+<translation id="5826507051599432481">Nom commun</translation>
-+<translation id="8914326144705007149">Très grande</translation>
-+<translation id="4215444178533108414">Modification terminée</translation>
-+<translation id="5154702632169343078">Objet</translation>
-+<translation id="2273562597641264981">Opérateur :</translation>
-+<translation id="122082903575839559">Algorithme de signature du certificat</translation>
-+<translation id="2181257377760181418">Cette fonctionnalité permet d'afficher un onglet d'aperçu avant de lancer une impression.</translation>
-+<translation id="7240120331469437312">Autre nom de l'objet du certificat</translation>
-+<translation id="6900113680982781280">Activer la saisie automatique pour remplir les formulaires Web d'un simple clic</translation>
-+<translation id="1131850611586448366">Le site Web à l'adresse <ph name="HOST_NAME"/> a été signalé comme étant un site de phishing. Ces sites tentent d'amener les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
-+<translation id="5413218268059792983">Rechercher directement sur <ph name="SEARCH_ENGINE"/></translation>
-+<translation id="1161575384898972166">Connectez-vous à <ph name="TOKEN_NAME"/> pour exporter le certificat client.</translation>
-+<translation id="1718559768876751602">Créer un compte Google maintenant</translation>
-+<translation id="1884319566525838835">État Sandbox</translation>
-+<translation id="2770465223704140727">Retirer de la liste</translation>
-+<translation id="3590587280253938212">rapide</translation>
-+<translation id="6053401458108962351">&amp;Effacer les données de navigation…</translation>
-+<translation id="2339641773402824483">Vérification des mises à jour...</translation>
-+<translation id="9111742992492686570">Télécharger les mises à jour de sécurité essentielles</translation>
-+<translation id="8636666366616799973">Package incorrect. Détails : &quot;<ph name="ERROR_MESSAGE"/>&quot;.</translation>
-+<translation id="2045969484888636535">Continuer à bloquer les cookies</translation>
-+<translation id="7353601530677266744">Ligne de commande</translation>
-+<translation id="2766006623206032690">Coller l'URL et y a&amp;ccéder</translation>
-+<translation id="4394049700291259645">Désactiver</translation>
-+<translation id="969892804517981540">Build officiel</translation>
-+<translation id="445923051607553918">Se connecter à un réseau Wi-Fi</translation>
-+<translation id="100242374795662595">Périphérique inconnu</translation>
-+<translation id="9087725134750123268">Supprimer les cookies et autres données de site</translation>
-+<translation id="5050255233730056751">URL saisies</translation>
-+<translation id="3349155901412833452">Utiliser les touches , et . pour paginer une liste d'entrées</translation>
-+<translation id="6872947427305732831">Vider la mémoire</translation>
-+<translation id="2742870351467570537">Supprimer les éléments sélectionnés</translation>
-+<translation id="7561196759112975576">Toujours</translation>
-+<translation id="2116673936380190819">de moins d'une heure</translation>
-+<translation id="5765491088802881382">Aucun réseau n'est disponible.</translation>
-+<translation id="1971538228422220140">Supprimer les cookies et autres données de site et de plug-in</translation>
-+<translation id="883487340845134897">Intervertir les touches Rechercher et Ctrl gauche</translation>
-+<translation id="5692957461404855190">Faites glisser trois doigts sur la surface de votre trackpad pour afficher un aperçu de tous vos onglets. Cliquez sur une vignette pour la sélectionner. Idéal en mode plein écran.</translation>
-+<translation id="1375215959205954975">Nouveau ! Configurer la synchronisation des mots de passe</translation>
-+<translation id="5183088099396036950">Échec de la tentative de connexion au serveur</translation>
-+<translation id="4469842253116033348">Désactiver les notifications de <ph name="SITE"/></translation>
-+<translation id="7999229196265990314">Les fichiers suivants ont été créés :
-+
-+Extension : <ph name="EXTENSION_FILE"/>
-+Fichier de clé : <ph name="KEY_FILE"/>
-+
-+Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la création de nouvelles versions de l'extension.</translation>
-+<translation id="1846078536247420691">&amp;Oui</translation>
-+<translation id="3036649622769666520">Ouvrir les fichiers</translation>
-+<translation id="2966459079597787514">Clavier suédois</translation>
-+<translation id="7685049629764448582">Mémoire JavaScript </translation>
-+<translation id="6398765197997659313">Quitter le mode plein écran</translation>
-+<translation id="6059652578941944813">Hiérarchie des certificats</translation>
-+<translation id="4886690096315032939">Afficher l'onglet existant si l'URL associée est demandée dans un autre</translation>
-+<translation id="5729712731028706266">&amp;Afficher</translation>
-+<translation id="774576312655125744">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et sur <ph name="NUMBER_OF_OTHER_WEBSITES"/> autres sites Web</translation>
-+<translation id="6359806961507272919">SMS de <ph name="PHONE_NUMBER"/></translation>
-+<translation id="4508765956121923607">Afficher la s&amp;ource</translation>
-+<translation id="5975083100439434680">Zoom arrière</translation>
-+<translation id="8080048886850452639">C&amp;opier l'URL du fichier audio</translation>
-+<translation id="2817109084437064140">Importer et associer au périphérique...</translation>
-+<translation id="3331321258768829690">(<ph name="UTCOFFSET"/>) <ph name="LONGTZNAME"/> (<ph name="EXEMPLARCITY"/>)</translation>
-+<translation id="619398760000422129">Plug-ins (par ex. Adobe Flash Player, QuickTime, etc.)</translation>
-+<translation id="5849869942539715694">Empaqueter l'extension...</translation>
-+<translation id="7339785458027436441">Vérifier l'orthographe lors de la frappe</translation>
-+<translation id="8308427013383895095">Échec de la traduction en raison d'un problème de connexion réseau</translation>
-+<translation id="1801298019027379214">Code PIN incorrect. Veuillez réessayer. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
-+<translation id="1384721974622518101">Vous pouvez effectuer une recherche directement à partir du champ ci-dessus.</translation>
-+<translation id="992543612453727859">Ajouter les expressions au premier plan</translation>
-+<translation id="3857773447683694438">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</translation>
-+<translation id="1244147615850840081">Opérateur</translation>
-+<translation id="8203365863660628138">Confirmer l'installation</translation>
-+<translation id="406259880812417922">(Mot clé : <ph name="KEYWORD"/>)</translation>
-+<translation id="309628958563171656">Sensibilité :</translation>
-+</translationbundle>
-diff --git a/tools/grit/grit/testdata/generated_resources_iw.xtb b/tools/grit/grit/testdata/generated_resources_iw.xtb
-new file mode 100644
-index 0000000000..86b55334c0
---- /dev/null
-+++ b/tools/grit/grit/testdata/generated_resources_iw.xtb
-@@ -0,0 +1,4 @@
-+<?xml version="1.0" ?>
-+<!DOCTYPE translationbundle>
-+<translationbundle lang="iw">
-+</translationbundle>
-diff --git a/tools/grit/grit/testdata/generated_resources_no.xtb b/tools/grit/grit/testdata/generated_resources_no.xtb
-new file mode 100644
-index 0000000000..913638ba4e
---- /dev/null
-+++ b/tools/grit/grit/testdata/generated_resources_no.xtb
-@@ -0,0 +1,4 @@
-+<?xml version="1.0" ?>
-+<!DOCTYPE translationbundle>
-+<translationbundle lang="no">
-+</translationbundle>
-diff --git a/tools/grit/grit/testdata/grit_part.grdp b/tools/grit/grit/testdata/grit_part.grdp
-new file mode 100644
-index 0000000000..c8e9d92692
---- /dev/null
-+++ b/tools/grit/grit/testdata/grit_part.grdp
-@@ -0,0 +1,5 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<grit-part>
-+ <!-- Important for test purposes that this file not exist. -->
-+ <structure type="chrome_scaled_image" name="IDR_DOES_NOT_EXIST" file="does-not-exist.png" />
-+</grit-part>
-diff --git a/tools/grit/grit/testdata/header.html b/tools/grit/grit/testdata/header.html
-new file mode 100644
-index 0000000000..8e9d10ec50
---- /dev/null
-+++ b/tools/grit/grit/testdata/header.html
-@@ -0,0 +1,39 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>[$~TITLE~$]</title>
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+[EXTRA_META]
-+<style>
-+BODY,TD,DIV,.P,A { FONT-FAMILY: arial,sans-serif}
-+DIV,TD { COLOR: #000}
-+.f { COLOR: #6f6f6f}
-+.fl:link { COLOR: #6f6f6f}
-+A:link, .w, A.w:link, .w A:link { COLOR: #00c}
-+A:visited { COLOR: #551a8b}
-+.fl:visited { COLOR: #551a8b}
-+A:active, .fl:active { COLOR: #f00}
-+.h { COLOR: #3399CC}
-+.i { COLOR: #a90a08}
-+.i:link { COLOR: #a90a08}
-+.a, .a:link, .a:visited { COLOR: #008000}
-+DIV.n { MARGIN-TOP: 1ex}
-+.n A { FONT-SIZE: 10pt; COLOR: #000}
-+.n .i { FONT-WEIGHT: bold; FONT-SIZE: 10pt}
-+.q A:visited { COLOR: #00c}
-+.q A:link { COLOR: #00c}
-+.q A:active { COLOR: #00c}
-+.q { COLOR: #00c}
-+.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
-+.ch { CURSOR: hand}
-+.e { MARGIN-TOP: 0.75em; MARGIN-BOTTOM: 0.75em}
-+.g { MARGIN-TOP: 1em; MARGIN-BOTTOM: 1em}
-+.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
-+.s { HEIGHT: 10px }
-+.c:active { COLOR: #ff0000}
-+.c:visited { COLOR: #551a8b}
-+.c:link { COLOR: #7777cc}
-+.c { COLOR: #7777cc }
-+</style>
-+</head>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/homepage.html b/tools/grit/grit/testdata/homepage.html
-new file mode 100644
-index 0000000000..cce4f2cf35
---- /dev/null
-+++ b/tools/grit/grit/testdata/homepage.html
-@@ -0,0 +1,37 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Google Desktop Search</title>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-+.q {COLOR: #0000cc}
-+</style>
-+<script>
-+<!--
-+function sf(){document.f.q.focus();}
-+// -->
-+</script>
-+</head>
-+<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
-+<center>
-+<TABLE cellSpacing=0 cellPadding=0 border=0>
-+<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
-+<FORM name=f method=GET action='[$~SEARCHURL~$]'>
-+<TABLE cellSpacing=0 cellPadding=4 border=0>
-+<tr>
-+<TD class=q noWrap><FONT size=-1>
-+[$~LINKS~$]
-+</font></td>
-+</tr></table>
-+<table cellspacing=0 cellpadding=0>
-+<tr vAlign=top>
-+<td width=25%>&nbsp;</td>
-+<td align=center><input maxlength=256 size=62 name=q value="[DISP_QUERY]"><br><input type=submit value="Search Desktop" name=btnG><INPUT type=submit value="Search the Web" name="redir" accesskey=w></td>
-+<td align=left valign=top nowrap width=25%><font size=-2>&nbsp;&nbsp;<A href="[$~PREFERENCES~$]">Desktop&nbsp;Preferences</a></font></td>
-+</tr></table></FORM>
-+<p><FONT color=#224499><B>Search your own computer.</B></font></p>
-+<span style='width:29em'>[$~MESSAGE~$]</span><br>
-+<br><FONT size=-1>[$~SETHOMEPAGE~$][$~BOTTOMLINE~$]</font></p>
-+<p><FONT size=-2>&copy;2005 Google - Searching [NUM_ITEMS] items</font></p></center></body></html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/hover.html b/tools/grit/grit/testdata/hover.html
-new file mode 100644
-index 0000000000..b8f9ce0200
---- /dev/null
-+++ b/tools/grit/grit/testdata/hover.html
-@@ -0,0 +1,177 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
-+A:hover { COLOR: #ffffff }
-+.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
-+</style>
-+
-+<!-- menu experiment start -->
-+
-+<style>
-+<!--
-+.menu1 {
-+cursor:default;
-+position:absolute;
-+left: 10;
-+top: 0;
-+text-align: left;
-+font-family: Arial, Helvetica, sans-serif;
-+font-size: 8pt;
-+background-color: menu;
-+visibility: hidden;
-+padding-top: 2px;
-+padding-bottom: 2px;
-+border: 1 solid;
-+border-color: #888888;
-+z-index: 100;
-+}
-+.menuitems {
-+padding-left: 5px;
-+padding-right: 5px;
-+}
-+-->
-+</style>
-+<SCRIPT LANGUAGE="JavaScript1.2">
-+<!--
-+var menustyle = "menu1";
-+
-+function showmenu() {
-+ // var rightedge = document.body.clientWidth-event.clientX;
-+ // var bottomedge = document.body.clientHeight-event.clientY;
-+ // if (rightedge < rcmenu.offsetWidth)
-+ // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
-+ // else
-+ // rcmenu.style.left = document.body.scrollLeft + event.clientX;
-+ // if (bottomedge < rcmenu.offsetHeight)
-+ // rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
-+ // else
-+ // rcmenu.style.top = document.body.scrollTop + event.clientY;
-+
-+ rcmenu.style.visibility = "visible";
-+ // rcmenu.style.zindex = 0;
-+ // document.all('rcmenu').style.zindex = 20;
-+ document.onkeydown=ck;
-+ return false;
-+}
-+
-+function hidemenu() {
-+ rcmenu.style.visibility = "hidden";
-+}
-+
-+function ck(e){
-+ evt=document.all?window.event:e;
-+ k=document.all?window.event.keyCode:e.keyCode;
-+
-+ if(k==27 /*<Esc>*/) {
-+ hidemenu();
-+ }
-+}
-+
-+function menumouseover() {
-+ if (event.srcElement.className == "menuitems") {
-+ event.srcElement.style.backgroundColor = "highlight";
-+ event.srcElement.style.color = "white";
-+ }
-+}
-+
-+function menumouseout() {
-+ if (event.srcElement.className == "menuitems") {
-+ event.srcElement.style.backgroundColor = "";
-+ event.srcElement.style.color = "black";
-+ window.status = "";
-+ }
-+}
-+
-+function menuselect() {
-+ if (event.srcElement.className == "menuitems") {
-+ if (event.srcElement.getAttribute("target") != null)
-+ window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
-+ else if (event.srcElement.url.length)
-+ window.location = event.srcElement.url;
-+ }
-+}
-+// -->
-+</script>
-+
-+<!-- menu experiment end -->
-+
-+</head>
-+<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0" border=0 style="border-width:0;" scroll=no>
-+
-+<!-- <br> -->
-+
-+<!-- menu experiment start -->
-+
-+<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
-+<span class="menuitems" url="[$~SETDISP1~$]">Sidebar</span>
-+<span class="menuitems" url="[$~SETDISP4~$]">Minibar</span>
-+<span class="menuitems" url="[$~HIDE2~$]">Close</span>
-+</div>
-+
-+<script language="JavaScript1.2">
-+if (document.all && window.print) {
-+ rcmenu.className = menustyle;
-+ document.oncontextmenu = showmenu;
-+ document.body.onclick = hidemenu;
-+}
-+</script>
-+
-+<!-- menu experiment end -->
-+
-+<script>
-+function hide() {
-+ return 1;
-+ // return confirm("Are you sure you want to hide the minibar?\nYou can show it again in Google Desktop Search Preferences. ");
-+}
-+function clear() {
-+ document.getElementById('q').value='';
-+}
-+</script>
-+
-+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-+<tr><TD vAlign=top>
-+
-+<form method=get action="[$~SEARCHURL~$]" [$~SEARCH_TARGET~$] name=f1 ID="f1" onsubmit="window.setTimeout('clear()', 500)">
-+<input type=hidden name=src value=3>
-+<input type=hidden name=redir value='' ID="redir">
-+
-+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-+
-+<tr>
-+<!-- border-top: #414a4f 0px solid; -->
-+<!-- z-index:2; z-order:2; -->
-+<TD vAlign=top>&nbsp;<INPUT name=q style="position:relative; height=19px;" class=border size=12>&nbsp;</td>
-+
-+<TD TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit();q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="logo.gif" align=middle></td>
-+
-+<TD width=2><IMG height=1 width=1></td>
-+
-+<TD TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="gfavicon.ico" align=middle></td></tr>
-+</TBODY></table>
-+</td>
-+
-+<TD width=5><IMG height=1 width=1></td>
-+
-+<TD vAlign=top>
-+
-+<TABLE cellSpacing=0 cellPadding=1 bgColor=#000099><TBODY>
-+<tr><TD TABINDEX="4" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="location.href='[$~SETDISP1~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="down.gif"></td></tr></TBODY></table>
-+
-+</td>
-+
-+<TD width=1><IMG height=1 width=1></td>
-+
-+<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
-+<tr><TD TABINDEX="5" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="if (hide())location.href='[$~HIDE2~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="close.gif"></td></tr></TBODY></table></td></tr></TBODY></table>
-+
-+</form>
-+</body></html>
-diff --git a/tools/grit/grit/testdata/include_test.html b/tools/grit/grit/testdata/include_test.html
-new file mode 100644
-index 0000000000..e08f2e2e8a
---- /dev/null
-+++ b/tools/grit/grit/testdata/include_test.html
-@@ -0,0 +1,31 @@
-+<include src="included_sample.html">
-+<if expr="True">
-+should be kept
-+</if>
-+in the middle...
-+<if expr="False">
-+should be removed
-+</if>
-+
-+<if expr="False">
-+should be removed
-+ <if expr="True">
-+ should be removed because outer expr is False
-+ </if>
-+should be removed
-+</if>
-+
-+<if expr="True">
-+ <if expr="True">
-+ <if expr="True">
-+ nested true should be kept
-+ </if>
-+ <if expr="False">
-+ should be removed
-+ </if>
-+ </if>
-+ <if expr="True">
-+ silbing true should be kept
-+ </if>
-+</if>
-+at the end...
-diff --git a/tools/grit/grit/testdata/included_sample.html b/tools/grit/grit/testdata/included_sample.html
-new file mode 100644
-index 0000000000..7150ffcbea
---- /dev/null
-+++ b/tools/grit/grit/testdata/included_sample.html
-@@ -0,0 +1 @@
-+Hello Include!
-diff --git a/tools/grit/grit/testdata/indexing_speed.html b/tools/grit/grit/testdata/indexing_speed.html
-new file mode 100644
-index 0000000000..db1787b0e2
---- /dev/null
-+++ b/tools/grit/grit/testdata/indexing_speed.html
-@@ -0,0 +1,58 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Google Desktop Search Index Speed</title>
-+<meta http-equiv=content-type content="text/html; charset=utf-8">
-+<style>
-+BODY {
-+ MARGIN-LEFT: 3em; MARGIN-RIGHT: 3em; FONT-FAMILY: arial,sans-serif
-+}
-+</style>
-+</head>
-+<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff>
-+<TABLE cellSpacing=2 cellPadding=0 width="100%" border=0>
-+ <tr>
-+ <TD vAlign=top width="1%"><A href="[$~HOMEPAGE~$]">
-+ <IMG alt="Go to Google Desktop Search" src="/logo3.gif" border=0></A></td>
-+ <td>&nbsp;</td>
-+ <TD noWrap>
-+ <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
-+ <tr>
-+ <TD bgColor=#3399CC><IMG height=1 alt="" width=1></td>
-+ </tr>
-+ </table>
-+ <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
-+ <tr>
-+ <TD noWrap bgColor=#efefef><B>&nbsp;Index Speed</B></td>
-+ <TD noWrap align=right bgColor=#efefef><FONT size=-1><A href="/customize.html">Index Speed
-+ Help</A> | <A href="[$~ABOUT~$]"> About Google Desktop Search</A></font></td>
-+ </tr></table></td></tr></table>
-+<FONT size=-1>
-+<p>
-+To make your emails, files, and previously viewed web pages searchable, Google Desktop Search
-+needs to index them. This indexing process is currently occuring in the background
-+and your computer performance is minimally impacted.
-+<p>
-+You have the option of speeding up this process.
-+<p><B><FONT color=#FF0000>Warning:</font></B> Speeding up indexing will cause your computer
-+to become unusable for many minutes, depending on how many items need to be indexed. FAST INDEXING IS NOT
-+RECOMMENDED.
-+<BR>&nbsp;<BR>
-+<FORM action="[$~SETINDEXSPEED~$]" method=GET>
-+<input name=url value="[PREVPAGE]" type=hidden>
-+<input type=radio name=FAST value="0" [FAST0-CHECKED] id=f0><label for=f0>Use background indexing (recommended)</label><br>
-+<input type=radio name=FAST value="1" [FAST1-CHECKED] id=f1><label for=f1>Use fast indexing</label><br><br>
-+<input type=submit value="Set Indexing Speed">
-+</FORM>
-+<BR>
-+
-+<p>&nbsp;<BR>
-+<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
-+<TR bgColor=#3399CC>
-+ <TD align=middle height=1><IMG height=1 alt="" width=1></td></tr>
-+</table>
-+
-+<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center bgColor=#efefef border=0>
-+<tr>
-+ <TD align=middle height=20><FONT size=-1><A href="[$~HOMEPAGE~$]">Google Desktop Search&nbsp;Home</A> - <a href="[$~STATUS~$]">Status</a> - <A href="[$~ABOUT~$]">About Google Desktop Search</A> - [$~BUILDNUMBER~$] - &copy;2005 Google </font> </td></tr>
-+</table><BR>
-+</body>
-+</html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/install_prefs.html b/tools/grit/grit/testdata/install_prefs.html
-new file mode 100644
-index 0000000000..eca0b56de5
---- /dev/null
-+++ b/tools/grit/grit/testdata/install_prefs.html
-@@ -0,0 +1,92 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Google Desktop Search: Initial Preferences</title>
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY { FONT-FAMILY: arial,sans-serif }
-+.c:active { COLOR: #FF0000 }
-+.c:visited { COLOR: #7777CC }
-+.c:link { COLOR: #7777CC }
-+</style>
-+<script>
-+<!--
-+override = 1;
-+function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
-+// -->
-+</script>
-+</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
-+<form onsubmit='override=0;return true;' action='[STEP2]' name=f method=post>
-+<img src="logo3.gif" border=0>
-+<div id=c1 style="width:600px">
-+<br><font color=#00218a><b>To continue, please set these initial preferences:</b></font><br><br>
-+<table border=0 id=t1 width=100%>
-+<tr>
-+ <td valign=top><input name=AIM id=chat type=checkbox checked></td>
-+ <td>&nbsp;</td><td><label for=chat><font size=-1><B>Enable search over Instant Messenger chats</b><br>
-+ <font size=-1>Google Desktop Search will store your chats and make them searchable.
-+</font></label></td></tr>
-+<tr height=1><td height=10px></td></tr>
-+<tr>
-+ <td valign=top><input name=HTTPS id=https type=checkbox checked></td>
-+ <td>&nbsp;</td><td><label for=https><font size=-1><b>Enable search over secure web pages (HTTPS)</b>
-+ <br><font size=-1>Google Desktop Search will store secure web pages that you view and make them
-+ searchable.</font></label> </td></tr>
-+<tr height=1px><td height=10px></td></tr>
-+
-+<tr>
-+ <td valign=top><input name=SEARCHBOX id=SEARCHBOX type=checkbox checked
-+ onclick="handleSBClick(this)"></td>
-+ <td>&nbsp;</td><td><label for=searchbox><font size=-1><b>Display search box</b></label>
-+ <br><table border=0 cellpadding=0><tr><td valign=top>
-+
-+<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [DB-CHECKED] value="DISPLAYDB"></td><td>
-+<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
-+<tr><td></td></tr>
-+<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
-+<tr><td height=2></td></tr>
-+<tr><td valign=top>
-+
-+<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [MB-CHECKED] VALUE="DISPLAYMB"></td><td>
-+<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box that you can put anywhere on your desktop</font></label></td></tr>
-+<tr><td></td></tr>
-+<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
-+<tr><td height=2></td></tr>
-+
-+</table>
-+</td></tr>
-+
-+<tr>
-+ <td valign=top><input name=SENDDATA id=usage type=checkbox checked></td>
-+ <td>&nbsp;</td><td><label for=usage><font size=-1><b>Help us improve Google Desktop Search by sending usage data and crash reports</b></label>
-+</font></td></tr>
-+<tr height=8px><td colspan=3 height=8px></td></tr>
-+<tr><td colspan=3><font size=-1>You can change these and other preferences at any time.</font></td></tr>
-+</table></div>
-+<p><input type=submit value="Set Preferences and Continue" id=s><br>
-+</form>
-+</center>
-+[SCRIPT]
-+<script>
-+<!--
-+function handleSBClick(checkbox) {
-+ document.getElementById("DISPLAYDB").disabled = !checkbox.checked;
-+ document.getElementById("DISPLAYMB").disabled = !checkbox.checked;
-+}
-+function stw() {
-+if (document.all && document.body.clientWidth < 600) {
-+ var w = document.body.clientWidth-35;
-+ if (w < 10) { w = 10; }
-+ w = w + 'px';
-+ document.getElementById('c1').style.width=w;
-+ return false;
-+}
-+document.getElementById('c1').style.width='600px';
-+}
-+stw();
-+document.f.s.focus();
-+// -->
-+</script>
-+<img SRC="http://www.google.com" WIDTH="0" HEIGHT="0" ALIGN="right"></img>
-+</body></html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/install_prefs2.html b/tools/grit/grit/testdata/install_prefs2.html
-new file mode 100644
-index 0000000000..18380397c2
---- /dev/null
-+++ b/tools/grit/grit/testdata/install_prefs2.html
-@@ -0,0 +1,52 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Indexing has Started</title>
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY { FONT-FAMILY: arial,sans-serif }
-+}
-+</style>
-+<script>
-+<!--
-+override = 1;
-+function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
-+// -->
-+</script>
-+</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
-+<form onsubmit='override=0;return true;' action="[STEP3]" name=f>
-+<img src="/logo3.gif" border=0><br><br>
-+<div id=c1 style="width:575px">
-+<table border=0 id=t1 width=100%><tr><td>
-+<font color=#00218a><b>One-time indexing has started.</b></font><br><br>
-+<font size=-1>An index is being prepared on your computer to allow you
-+to search your information as fast as you can search the web.<br><br>
-+<li>This is a one-time process that may take several hours.
-+<li>You may continue to use your computer as usual and it is safe to shut down your computer.
-+<li>Indexing will be performed only when your computer is idle.
-+</ul>
-+</font>
-+<p><input type=submit value="Go to the Desktop Search homepage" name=s><br>
-+</center>
-+</td></tr></table>
-+</form>
-+</div>
-+<script>
-+<!--
-+function stw() {
-+if (document.all && document.body.clientWidth < 575) {
-+ var w = document.body.clientWidth-35;
-+ if (w < 10) { w = 10; }
-+ w = w + 'px';
-+ document.getElementById('c1').style.width=w;
-+ return false;
-+}
-+document.getElementById('c1').style.width='575px';
-+}
-+stw();
-+// -->
-+document.f.s.focus();
-+</script>
-+[SCRIPT]
-+</body></html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/klonk-alternate-skeleton.rc b/tools/grit/grit/testdata/klonk-alternate-skeleton.rc
-new file mode 100644
-index 0000000000000000000000000000000000000000..5f2c82a55469ddaab246c095826ad9e6743c0015
-GIT binary patch
-literal 1088
-zcmbW0Pfr3t48`AhKZV)z#sGrI5!gjnU?DC>IT2z!82=r_L=!)}zjnmk5b$6oGo9&7
-z+t=4lu9UG-Ujxl_t%b{59ih$9PSBn!lW7`iGrKMm&Q10vTRK5!yRJHlRN`fcWril@
-zv|?uHM))d_NBa7`nW9TQ&PZ3tsax6ojav@U&9TYdHduz6k{G4GFTfpX_hk&`!z0F`
-z!gJ>6WBh&UO&i_oS+VOvUfcD9JR=y&;3OxP2%KT$#JB9W=UtgQpDT@>(E^#^A;oG%
-z4omjIK7rLXcRgmyS+%u_Gl2`MhOxMB{GGM&5o6cXF<vdhEe5Mu-+3OQZF~Ht$8Yl5
-z&=^M*j(xG~y3(sxz{#AtW^kPoyR!dZ9)}Sd$_6;Qjx#V<A+O@5j%7~Al)9jj*71v4
-z<zn{ZUuJA?73tB}iB6fJ)6H}8)1l|&XFq3N%P!P%;Wv{#b&7SVweIxDUCbEh>E~=G
-z`!#F5=z%_bq95y7+aIx?IdcSN`A)xX^vZjCS7lnS#=iZ)E7W%eX8!kr-#RDO36^!o
-Qqn&wY8qX0d7T}2V4SbP+*8l(j
-
-literal 0
-HcmV?d00001
-
-diff --git a/tools/grit/grit/testdata/klonk.ico b/tools/grit/grit/testdata/klonk.ico
-new file mode 100644
-index 0000000000000000000000000000000000000000..d371b214dc366249870efccc5da278d023aa91f1
-GIT binary patch
-literal 766
-zcmeH_F%H5o5CqSFL>Ve71Sxq1;TtsMEB*!Fv6LbmDQFSUL1mXjO7OC0gpl|G?B1ML
-zXS=a1V(2`di0U>FnQ~o{oUDnF5j(}bxAgSuhE8lMu~rkI8Ju%mb%Im^Xd<+ZwEgwd
-zFTg+WQOj5lfvO*4mbEA^bCj9KHh65vjx^zvsKW{eA8|Ah`w&r;%!`QgmEiG3hXCcC
-L+@V2V6oA7MJIRBx
-
-literal 0
-HcmV?d00001
-
-diff --git a/tools/grit/grit/testdata/klonk.rc b/tools/grit/grit/testdata/klonk.rc
-new file mode 100644
-index 0000000000000000000000000000000000000000..35652c4e6dd7cf7b7f62f637e191acf66f487235
-GIT binary patch
-literal 9824
-zcmeI2+j1L48poSUd<zdSObP?FE=Nu{E-aL6%Z`X;t1MXwwb^nxw&R#MQm|was(2h8
-z0*VVRxZyQ;25z?&e*drad1j>1!LS!j6*Z-q>7MTIeClrf{=b{yW=KLKoQA`29(tkA
-z?@<`g*P*W;F2X@LqqP?P!IgxQa2&e)&gmcUJfiQMr{-PocF21|OVCckGsY~31#sNt
-zeuJJaU(OhLWaHAYxy#{kNExfq8uQ5J2xc`jLo2kyURV$HuoL#fZm7|_&ii)Q3SZFE
-z;@$|W^lb4S@e23#yIdxsED4)%Ix5vi$fg&b@^yerB!M>k-sfJ2-!(XtBx>~E;y0>;
-zywqpO@eUBz4c2yv49m3k+_Z88eb3Rg>+A-4?GCk8rmyLEuD7;k@iyBQuQz|u4r}P|
-z1pk!hKgO!w#>STMq~-8ViH-G#etL?RCgF{OzaBBS8aA-k=%+1wau1JP!(#WbwJk2e
-z{FW=3II|6mUA$wTS=-Ei$KrzUMVn6ea?kwXHeRp*%qrtH8Cm5n-|(IYVUu<pe(r=N
-zzO@*)I&s84Ull`c5XBVjPVmJ8W*uVn!oE+xdXM3B1?=zfi}cBtkC36HBDof6y#96&
-zDNK-*c<mwsaiN$Tt;G8iy#LgqQ-aMX7AOxWcPO4D;cMihSg+XijJE^e#f+h-em)#K
-zU}i#pm$ov9MjtR<GnAE-XHJcd#M&7}G3rSx$}4^5MSA<RMTcOD8qE;QGcM((Z-!r=
-z@>HA@wRN;~7h6y+xyz_&R~;+XxM^eZ-_q~|%%b86_{3Asa-8FBk+Z7c-kJgN>UjHR
-zv*J6C_vNv`hUxGkXMvL0T0vKhVQf$p6QjfeUR}fgl_wW2W!gk%O?<jZPZ}19O{d7^
-z*finVDx2ru9D3dIaKoU~fb#-41E46PT;&oc4LDIw7tD-Ohf;>IO<b0BC*h%aN($z?
-zm)50Lg3jeb@}4KgpHn7``|w@I(iDZ;#6d+vaXpT`D6f;D{i-%|`usUfYCfinmyGTN
-zIW7V>a`tbcYLDwE{AY?>BR88vkIj3pcp9ftwy~b;A8i-;T|_p=$nY5yWU!`jTE^ib
-ze*F+mE-Vf$<AuvpIC5FVr`t!>>e;=5g*fg0^w_NUeElxZA2EAWiGRui^1Zl<=<)P1
-zF&Y;=yo$%KVIA>VGwa=@)kgQbrt31jq~WuvvL2VO`$<s`-l~FW4S%T*JzWty@3kqC
-zpB4rFU-(`|ov-8B%D+84yQpbJq|Cy#a=VYFm5(Lg9joHhbBjy*SqUH5^H#VWD)#mP
-zmDd8gX|wiIT+{3pP+PpWiFV4=ZF*H_#xD)})(!p!_EWXI5x?KFnQQblnWI&vvb<)-
-zFIrzJTT2IfU>zNqGSmHCaU;Y2q0yQ$JF7mTwL~ub{sOMb^Vh8GFZ(K1F-x>#wroJR
-z&tF1@??TN-{BD^Hb<bj)tU9hU-SUgid^Mw80(r42u2^L$1ARm5q2(uK*A(fk5cewP
-z9Zr$-B@Y%=OVA@~R*aezo@z;A8C69Z##=4Z+%_6(qSKmXx%;{Kv$<M>gJ;mLeTx&a
-ztSZO1p-!t5NvMLINn_JEi1N%h$mrKfeZ%Sxtv*(<o;FujMW(#py@aoK$>Sq%E`|5`
-zMQa!2rJ*fu!l%|$%^a7pE^XVFE$AM-((pNcct~BK8YqR1Sd~Aqmi*&@D)rQ&bN`YW
-zMPvC%+;<TLnyH+o+P!PzGEPTvj<#1#Q&p3I;<v-i%S09-uHQ3$KQw!lbu5_YDT~KE
-zq3F><0?G_uSf2bldXz_x`Rp$tXUa07m0#5g^O>n*TJE4PW#|}5_jztxOjO*+fAM}<
-zk=Lii5sD#879SKTSIp++>5AlgXumxIv246U-XKqCe;}^ATDIP+P{%8`Yynw2Uilpc
-z$xha}X;{ahB+#YVajq(xJ|2|kCBqoURxZc-PC<V34wS`l@7lObCdzS5sL5l@zQ+BG
-z;+Tl3tUl7t#}1OyYFBw_V3AMzKfW@m<J*t$@OdlXBE$+_TOoq!`H*`aipPX9y8N3z
-zJLpP#o#HyZq-`Au=XaT7{)rj2n4zkrdkJOKOvhNvbdE_@DQ#r;l~PX2VN1f=r#R=S
-z`e>WGR&NeH+c%h>-Yw>z7_{+>=5WWql;yg~F}<jhong+@E{wQv`%$Z$n`LNxVSLVu
-zqX`bJ2rtN9gE2WJxg8d*6Uugv=9gd**I(1S$3)lvXuIe$9VB*sDZi`wUr{S<ASs*o
-zEyw#FTC@PgtLUAvrjGSZrVFRipYc2<9~H+>V-&+XR>jna$uG|ylUKW<KRZ>)Rw*m^
-z_oOjp@vHny>%lMrW)jt@&DG$}J`tOC!twxncz`|R{U9wplS^%1SD7h)zLPS$9KxSJ
-z^(luqF00#DmestFZxDq%2fL5@KE>#H<EVwdOuH`m{4TpYASY`FCbM&`$abwl+vH7a
-za;>I|)#R(g69An@YFD|(_t^K?Y(=LYvGR$s)LKbvaYc(JPp$Xb2G?a>eC9KE-cEhZ
-zHSZ3+_C$Rze-w`BSsn7ZgI%TJO=9FfdDBy)V;pqaYpnOHjNdZ)cZhIWOV;71NPE_b
-z5ZwYd@EV=tI))^?mN>3>KBO~=3-s|NvQu_bO!m`Xy&s`1RS8A9bec9lO`@(ym$)sX
-zMVVq?wjta)kvTJp%Bk>bSh}4@HcmwuW}T<$ta~!gT03ja*d|hI1w9*Uk>}TwPvL12
-z=Q{J$UgQ8RXmu+(2GDd)J#{>6mrEh;W{57|8=6JgB)U>?#`vQXEaBEZgsP}6H0c~I
-zlTn_wQLB~3>U1IQ2y}Rh=cM|##66Rnd!p7F(K=LbM6B`LtO3?OS3Ko>03~gD6g5tu
-zOSRooa>4*SqvO;gSO;d)IuFc4e&rSY3#4arR~e}tmqXie5w!0rzg2#y{KWm2%CD85
-zD?e8LTlv1?UR>st9pKlDtGM^mfuA&df=7MIT`QQ#k8mnxoriygx5#|&^UZ&6F?Nx!
-z2jMH^+zTJm>H?vU#6L!6XLz9~{RHheL_xo4SVUcx*(c|e8ZfVRzJC37^PM7DoUXW9
-zRu0v_b;|ztF`73W!u5N4HWX!l^<O!vStkE0N0PgK{5wU`>ZH1;i+3m{&0Ya4gg*c`
-C>9bG(
-
-literal 0
-HcmV?d00001
-
-diff --git a/tools/grit/grit/testdata/ko_oem_enable_bug.html b/tools/grit/grit/testdata/ko_oem_enable_bug.html
-new file mode 100644
-index 0000000000..f2c199cc15
---- /dev/null
-+++ b/tools/grit/grit/testdata/ko_oem_enable_bug.html
-@@ -0,0 +1 @@
-+<IMG style="VERTICAL-ALIGN: middle" height=16 alt=아웃룩 src="/email.gif" width=16>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/ko_oem_non_admin_bug.html b/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
-new file mode 100644
-index 0000000000..b9e8a1f288
---- /dev/null
-+++ b/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
-@@ -0,0 +1 @@
-+<INPUT id=s type=submit value="&nbsp;&nbsp;확인&nbsp;&nbsp;">
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/mini.html b/tools/grit/grit/testdata/mini.html
-new file mode 100644
-index 0000000000..8ac0a231a0
---- /dev/null
-+++ b/tools/grit/grit/testdata/mini.html
-@@ -0,0 +1,36 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head>
-+<meta http-equiv=content-type content="text/html; charset=windows-1252">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-+DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
-+A:hover { COLOR: #ffffff }
-+.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
-+</style>
-+</head>
-+
-+<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0">
-+
-+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-+<tr><TD vAlign=top>
-+
-+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-+
-+<tr>
-+<TD vAlign=top>&nbsp;<INPUT style="position:relative; height=17px;" class=border size=10>&nbsp;</td>
-+
-+<TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><img height=1 width=1><IMG src="logo.gif" align=middle><img height=1 width=1></td>
-+
-+</TBODY></table>
-+</td>
-+
-+<TD width=2><IMG height=1 width=1></td>
-+
-+<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
-+<tr><TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="mini_close.gif"></td></tr></TBODY></table></td></tr></TBODY></table></body></html>
-diff --git a/tools/grit/grit/testdata/oem_enable.html b/tools/grit/grit/testdata/oem_enable.html
-new file mode 100644
-index 0000000000..db6b85eca6
---- /dev/null
-+++ b/tools/grit/grit/testdata/oem_enable.html
-@@ -0,0 +1,106 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Google Desktop Search Download</title>
-+<meta http-equiv=content-type content="text/html; charset=utf-8">
-+<style>BODY {
-+ FONT-FAMILY: arial,sans-serif
-+}
-+TD {
-+ FONT-FAMILY: arial,sans-serif
-+}
-+DIV {
-+ FONT-FAMILY: arial,sans-serif
-+}
-+.p {
-+ FONT-FAMILY: arial,sans-serif
-+}
-+A {
-+ FONT-FAMILY: arial,sans-serif
-+}
-+DIV {
-+ COLOR: #000
-+}
-+TD {
-+ COLOR: #000
-+}
-+A:link {
-+ COLOR: #00c
-+}
-+A:visited {
-+ COLOR: #551a8b
-+}
-+</style>
-+
-+<meta content="mshtml 6.00.2800.1476" name=generator></head>
-+<body>
-+<center>
-+<TABLE cellSpacing=0 cellPadding=0 border=0>
-+ <TBODY>
-+ <TR vAlign=center>
-+ <td>
-+ <DIV align=center><IMG height=55 alt="Google Desktop Search"
-+ src="/logo3.gif" width=150 border=0 search=""
-+ desktop=""></DIV></td>
-+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
-+ <td><FONT size=+1><B>Search your own
-+computer.</B></font></td></tr></TBODY></table><BR>
-+<TABLE cellSpacing=0 cellPadding=0 width=630 border=0>
-+ <TBODY>
-+ <tr>
-+ <TD vAlign=top width="53%"><FONT size=-1>
-+ <LI>Find your email, files, web history and chats instantly <NOBR>
-+ <LI>View web pages you've seen, even when you're not online</NOBR>
-+ <LI>Search as easily as you do on Google
-+ <p><B>Google Desktop Search finds:</B></p></font>
-+ <TABLE cellSpacing=1 cellPadding=0 width=325 border=0 valign="center">
-+ <TBODY>
-+ <TR vAlign=center>
-+ <TD colSpan=3><FONT size=-1><IMG style="VERTICAL-ALIGN: middle"
-+ height=16 alt=Outlook src="/email.gif"
-+ width=16>&nbsp;&nbsp;Email from Outlook, Outlook Express, &amp;
-+ Thunderbird</font></td></tr>
-+ <tr>
-+ <TD noWrap colSpan=3><FONT size=-1><IMG
-+ style="VERTICAL-ALIGN: middle" height=16 alt="Internet Explorer"
-+ src="/html.gif" width=16>&nbsp;&nbsp;Web history
-+ from IE/Firefox/Mozilla/Netscape</font></td></tr>
-+ <tr>
-+ <TD noWrap colSpan=3><FONT size=-1><IMG
-+ style="VERTICAL-ALIGN: middle" height=16 alt=Text
-+ src="/file.gif" width=16>&nbsp;&nbsp;Files in Word,
-+ Excel, Powerpoint, PDF, &amp; media formats</font></td></tr>
-+ <tr>
-+ <TD vAlign=top colSpan=3><FONT size=-1><IMG
-+ style="VERTICAL-ALIGN: middle" height=16 alt="AOL IM"
-+ src="/aim.gif" width=16>&nbsp;&nbsp;Chats from AOL
-+ Instant Messenger</font></td></tr>
-+ <tr>
-+ <TD noWrap><FONT size=-1>&nbsp;</font></td></tr></TBODY></table><FONT
-+ size=-1>&nbsp;</font><FONT size=-1><A
-+ href="http://desktop.google.com/about.html">About Desktop
-+ Search</A>&nbsp;&nbsp; <A
-+ href="http://desktop.google.com/screenshots.html">Screenshots</A>&nbsp;&nbsp;
-+ <A href="http://desktop.google.com/support">Help</A>&nbsp;&nbsp; <A
-+ href="http://desktop.google.com/feedback.html">Contact
-+ Us</A><BR></font></LI></td>
-+ <td>&nbsp;&nbsp;&nbsp;</td>
-+ <TD vAlign=top width="53%">
-+ <TABLE cellPadding=2 width="100%" align=center>
-+ <TBODY>
-+ <tr>
-+ <TD
-+ style="BORDER-RIGHT: rgb(204,204,204) 1px solid; BORDER-TOP: rgb(204,204,204) 1px solid; BORDER-LEFT: rgb(204,204,204) 1px solid; BORDER-BOTTOM: rgb(204,204,204) 1px solid"
-+ width="100%" bgColor=#e7eff7 blah2="#fff8dd" blah="#e7eaf7"><BR>
-+ <center><FONT size=-1>By using, you agree to our <A
-+ href="http://desktop.google.com/eula.html"><BR>Terms &amp;
-+ Conditions</A> and <A
-+ href="http://desktop.google.com/privacypolicy.html">Privacy
-+ Policy</A></font></center>
-+ <p></p>
-+ <FORM action='[STEP2]'>
-+ <P align=center><INPUT style="PADDING-RIGHT: 3px; PADDING-LEFT: 3px; FONT-WEIGHT: bold; FONT-SIZE: 17px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px" type=submit value="Agree and Start Using" name=Submit>
-+ </p></FORM><FONT size=-2>* Automatically starts when you turn on
-+ your computer</font> </td></tr></TBODY></table>
-+ <p></p></td></tr></TBODY></table></center>
-+<p></p>
-+<center><FONT color=#666666 size=-2>©2005 Google</font>
-+<p></p></center></body></html>
-diff --git a/tools/grit/grit/testdata/oem_non_admin.html b/tools/grit/grit/testdata/oem_non_admin.html
-new file mode 100644
-index 0000000000..8b7ca13e21
---- /dev/null
-+++ b/tools/grit/grit/testdata/oem_non_admin.html
-@@ -0,0 +1,39 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Google Desktop Search Preferences</title>
-+<meta http-equiv=cache-control content=no-cache>
-+<meta http-equiv=content-type content="text/html; charset=utf-8">
-+<meta http-equiv=pragma content=no-cache>
-+<meta http-equiv=expires content=-1>
-+<style>BODY {
-+ FONT-FAMILY: arial,sans-serif
-+}
-+.c:active {
-+ COLOR: #ff0000
-+}
-+.c:visited {
-+ COLOR: #7777cc
-+}
-+.c:link {
-+ COLOR: #7777cc
-+}
-+</style>
-+
-+<script>
-+<!--
-+override = 1;
-+function ee() {if (override==1) {(new Image()).src="/doneinstallprefs&s=3286011577";}}
-+// -->
-+</script>
-+
-+<meta content="mshtml 6.00.2800.1476" name=generator></head>
-+<BODY onresize=stw() leftMargin=30 rightMargin=30 onunload=ee()>
-+<FORM name=f onsubmit=javascript:window.close();><IMG
-+src="/logo3.gif" border=0>
-+<DIV id=c1 style="WIDTH: 600px">
-+<p><BR><FONT color=#00218a><B>We're sorry, but you need administrator access to
-+enable Desktop Search.</B></font></p><FONT size=-1>
-+<p>To install or run Google Desktop Search you need administrator access on this
-+computer. Please try installing again once you have administrator
-+access.</p></font></DIV>
-+<p><INPUT id=s type=submit value=&nbsp;&nbsp;OK&nbsp;&nbsp;> <BR></p>
-+<center></center></FORM></body></html>
-diff --git a/tools/grit/grit/testdata/onebox.html b/tools/grit/grit/testdata/onebox.html
-new file mode 100644
-index 0000000000..c24ff043a5
---- /dev/null
-+++ b/tools/grit/grit/testdata/onebox.html
-@@ -0,0 +1,21 @@
-+<html><head><title>Google Desktop Search Results</title>
-+<style><!--
-+body,td,div,.p,a{font-family:arial,sans-serif }
-+body{ background-color: transparent }
-+div,td{color:#000}
-+.f,.fl:link{color:#6f6f6f}
-+a:link,.w,a.w:link,.w a:link{color:#00c}
-+a:visited,.fl:visited{color:#551a8b}
-+a:active,.fl:active{color:#f00}
-+.t a:link,.t a:active,.t a:visited,.t{color:#000}
-+//-->
-+</style>
-+</head>
-+<body>
-+<table cellspacing=0 cellpadding=1 border=0 ID="Google Desktop Search">
-+<tr><td colspan=2><nobr><a href="http://[WEBSERVER][$~QUERY~$]" target=_parent>[NUMRESULTS] [RESULT-STRING] stored on your computer</a><font size=-1>&nbsp;-&nbsp;<a href="[HIDENOW]" style="color:#7777cc;" target=_parent>Hide</a>&nbsp;-&nbsp;<a href="http://desktop.google.com/integration.html" style="color:#7777cc;" target=_parent>About</a></font></nobr></td></tr>
-+<tr><td valign=top width=40><img height=27 style="margin-top:2px;" src="http://[WEBSERVER]/onebox.gif"></td>
-+<td valign=top width="99%"><font size=-1>[RESULTS]</font></td></tr>
-+</table>
-+</body>
-+</html>
-diff --git a/tools/grit/grit/testdata/oneclick.html b/tools/grit/grit/testdata/oneclick.html
-new file mode 100644
-index 0000000000..32dc6459dd
---- /dev/null
-+++ b/tools/grit/grit/testdata/oneclick.html
-@@ -0,0 +1,34 @@
-+[HEADER]
-+
-+
-+<TABLE cellSpacing=4 cellPadding=0 width="100%" border=0>
-+<tr>
-+ <TD vAlign=top align=left width=50%>
-+ [EMAIL_TOP_CHROME]
-+
-+ <p class=f>
-+ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0>
-+ [EMAIL]
-+ </table>
-+ </td>
-+
-+
-+ <TD width=1 align=middle bgColor=#cfcfcf><IMG height=1 width=1></td>
-+ <TD width=50% vAlign=top align=left>
-+ [FREQ_TOP_CHROME]
-+ <p class=f>
-+ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table1">
-+ [$~FREQ~$]
-+ </table>
-+ <p class=g>
-+ [RECENT_TOP_CHROME]
-+ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table2">
-+ [$~RECENT~$]
-+ </table>
-+ </td>
-+ </tr>
-+</table>
-+<center><BR>
-+
-+
-+[FOOTER]
-diff --git a/tools/grit/grit/testdata/password.html b/tools/grit/grit/testdata/password.html
-new file mode 100644
-index 0000000000..16007a1ac0
---- /dev/null
-+++ b/tools/grit/grit/testdata/password.html
-@@ -0,0 +1,37 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Password Required</title>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-+.q {COLOR: #0000cc}
-+</style>
-+<script>
-+<!--
-+function sf(){document.f.q.focus();}
-+// -->
-+</script>
-+</head>
-+<body text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
-+<center>
-+<table cellSpacing=0 cellPadding=0 border=0>
-+<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
-+<form name=f method=GET action='/password'>
-+<table cellSpacing=0 cellPadding=4 border=0>
-+<tr><td class=q noWrap><font size=-1>
-+ <table cellSpacing=0 cellPadding=0>
-+ <tr vAlign=top>
-+ <td align=middle>Password required:&nbsp;&nbsp;<input maxLength=80 size=30 type=password name=pw value="">
-+ <script>
-+ document.f.q.focus();
-+ </script>
-+ &nbsp;<input type=submit value="Submit" name=submit>
-+ </td></tr>
-+ </table>
-+ </form>
-+</td></tr>
-+</table>
-+<br><font size=-1>[$~BOTTOMLINE~$]</font></p>
-+<p><font size=-2>&copy;2005 Google</font></p></center></body></html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/preferences.html b/tools/grit/grit/testdata/preferences.html
-new file mode 100644
-index 0000000000..b37412436b
---- /dev/null
-+++ b/tools/grit/grit/testdata/preferences.html
-@@ -0,0 +1,234 @@
-+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-+<html><head><title>Google Desktop Search Preferences</title>
-+<meta http-equiv=content-type content="text/html; charset=utf-8">
-+<style>
-+body {
-+ margin-left: 2em; margin-right: 2em;
-+ font-family: arial,sans-serif;
-+ color:#000; background-color:#fff;
-+}
-+a:active { color:#f00 }
-+a:visited { color:#551a8b }
-+a:link { color:#00c }
-+a.c:active { color: #ff0000 }
-+a.c:visited { color: #7777cc }
-+a.c:link { color: #7777cc }
-+.b { font-weight: bold }
-+.shaded-header { background-color: #e8f4f7; border-top: 1px solid #39c;
-+margin: 0px; padding: 0px }
-+.shaded-subheader { background-color: #e8f4f7; margin: 12px 0px 0px 0px;
-+ padding: 0px }
-+.plain-subheader { background-color: #fff; margin: 12px 0px 0px 0px;
-+ padding: 0px }
-+.header-element { margin: 0px; padding: 2px}
-+.expand { width: 98% }
-+.s { font-size: smaller }
-+.prefgroup { border: 2px solid #e8f4f7; width: 100% }
-+.phead { font-weight: bold; font-size: smaller; vertical-align: top;
-+text-transform: capitalize; border-bottom: 2px solid #e8f4f7; margin: 0px;
-+padding: 8px}
-+.pbody { border-bottom: 2px solid #e8f4f7; margin: 0px;
-+padding: 8px}
-+.pref-last { border-bottom: 0px }
-+.example { color: gray; font-family: monospace; }
-+</style>
-+<script>
-+<!--
-+function validate() {}
-+function fnOnClickAll() {for (var i = 0; i < document.langform.lr.length; i++) {
-+document.langform.lr[i].checked = false;}}
-+function fnOnClickSome() {
-+var count = 0;for (var i = 0; i < document.langform.lr.length; i++) {
-+if (document.langform.lr[i].checked) {count++;}}
-+document.langform.lang[0].checked = (count <= 0);
-+document.langform.lang[1].checked = (count > 0);}
-+// -->
-+</script>
-+</head>
-+<body onload="checkOffice()">
-+<form name=prefs action="[$~SETPREFS~$]" method=post><input name=url
-+value="[PREVPAGE]" type=hidden>
-+<table cellspacing=2 cellpadding=0 width="100%" border=0>
-+<tr>
-+<td valign=top width="1%"><a href="[$~HOMEPAGE~$]">
-+<img alt="Go to Google Desktop Search" src="logo3.gif" border=0></a></td>
-+<td>&nbsp;</td>
-+<td nowrap>
-+
-+<table class="shaded-header"><tr>
-+<td class="header-element b expand">Preferences</td>
-+<td class="header-element s">
-+<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
-+</td>
-+</tr></table>
-+
-+</tr></table>
-+
-+<table class="shaded-subheader"><tr>
-+<td class="header-element expand s">
-+<span class="b">Save</span> your preferences when finished.</td>
-+<td class="header-element"><input type=submit value="Save Preferences"
-+name=submit2></td>
-+</tr></table>
-+
-+[STATUS-MESSAGE]
-+<table class="plain-subheader"><tr>
-+<td class="header-element expand"><span class="b">Preferences</span><span
-+class="s"> (changes apply to Google Desktop Search application)</span></td>
-+</tr></table>
-+
-+<table class="prefgroup" cellpadding=0 cellspacing=0>
-+
-+<!-- -->
-+<tr>
-+<td class="phead">Search types</td>
-+<td class="pbody"><div class="s">Index the following items so that you can
-+search for them:<br />&nbsp;</div>
-+<div>
-+ <table border=0>
-+ <tr>
-+ <td width=150 nowrap valign=top><span class="s">
-+ <input type=checkbox [CHECK-EMAIL] name=EMAIL id=h3><label for=h3>
-+ Email</label><br>
-+ <input type=checkbox [CHECK-AIM] name=AIM id=h5><label for=h5> Chats
-+ (AOL/MSN IM)</label><br>
-+ <input type=checkbox onclick='if(!this.checked){h12.checked=0;h12.disabled=1;}
-+ else {h12.disabled=0;}' [CHECK-WEB] name=WEB id=h11><label for=h11> Web
-+ history</label>
-+
-+ </span></td>
-+ <td width=120 nowrap valign=top><span class="s">
-+ <script>
-+<!--
-+function checkOffice() { var w = document.getElementById("h7");
-+var e = document.getElementById("h8"); var o = document.getElementById("h10");
-+if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
-+// -->
-+ </script>
-+ <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
-+ <label for=h7> Word</label><br>
-+ <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
-+ <label for=h8> Excel</label><br>
-+ <input type=checkbox [CHECK-PPT] name=PPT id=h9>
-+ <label for=h9> PowerPoint</label><br>
-+ </span></td><td nowrap valign=top><span class="s">
-+ <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
-+ <label for=hpdf> PDF</label><br>
-+ <input type=checkbox [CHECK-TXT] name=TXT id=h6>
-+ <label for=h6> Text, media, and other files</label><br>
-+ </tr>
-+ <tr><td nowrap valign=top colspan=3><span class="s"><br />
-+ <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
-+ <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
-+ <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
-+ for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
-+</table>
-+</div></td></tr>
-+</div>
-+</td>
-+</tr>
-+
-+<!-- -->
-+<tr>
-+<td class="phead">Plug-ins</td>
-+<td class="pbody"><div class="s"
-+style="display:[ADDIN-DISPLAYSTYLE]">Index these additional items:<p>
-+[ADDIN-DO]
-+[ADDIN-OPTIONS]</div><div class="s">
-+To install plug-ins to index other items, visit the
-+<a href="http://desktop.google.com/plugins.html">Plug-ins Download page</a>.</div>
-+</tr>
-+
-+<!-- -->
-+<tr>
-+<td class="phead">Don't search these items</td>
-+<td class="pbody"><div class="s">
-+<label for=FORBIDDEN>Do not search web sites with the following URLs or files
-+with the following paths. Put each entry on a separate line. Examples:</label><br>
-+<span class="example">c:\Documents and Settings\username\Private Stuff</span><br>
-+<span class="example">http://www.domain.com/</span><br>
-+<div>&nbsp;</div>
-+<div><TEXTAREA rows=3 cols=65 name=FORBIDDEN id=FORBIDDEN>[FORBIDDEN]
-+</TEXTAREA></div>
-+</tr>
-+
-+<!-- -->
-+<tr>
-+<td class="phead pref">Search Box Display</td>
-+<td class="pbody pref" valign=top>
-+
-+<table border=0 cellpadding=0><tr><td valign=top>
-+
-+<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [CHECK-DISPLAYDB] value="DISPLAYDB"></td><td>
-+<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
-+<tr><td></td></tr>
-+<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
-+<tr><td height=2></td></tr>
-+<tr><td valign=top>
-+
-+<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [CHECK-DISPLAYMB] VALUE="DISPLAYMB"></td><td>
-+<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box you can put anywhere on your desktop</font></label></td></tr>
-+<tr><td></td></tr>
-+<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
-+<tr><td height=2></td></tr>
-+<tr><td valign=top>
-+
-+<input type=radio name="SBDISPLAY" id="DISPLAYNONE" [CHECK-DISPLAYNONE] VALUE="DISPLAYNONE"></td><td valign=top>
-+<label for=DISPLAYNONE><font size=-1> None</font></label>
-+</td></tr>
-+</table>
-+
-+</td></tr>
-+
-+<!-- -->
-+<tr>
-+<td class="phead pref">Number of Results</td>
-+<td class="pbody pref"><label for=num><span class="s">
-+Display <select name=num id="num">
-+<option [CHECK-NUM-10]>10
-+<option [CHECK-NUM-20]>20
-+<option [CHECK-NUM-30]>30
-+<option [CHECK-NUM-50]>50
-+<option [CHECK-NUM-100]>100</select>
-+ results per page</span></label>
-+</td>
-+</tr>
-+
-+<!-- -->
-+<tr>
-+<td class="phead">Google integration</td>
-+<td class="pbody">
-+<table border=0 cellpadding=0>
-+<tr><td><input type=CHECKBOX name=ONEBOX [CHECK-ONEBOX] id=onebox></td>
-+<td><label for=onebox>
-+ <span class="s">Show Desktop Search results on Google Web Search result pages.
-+ </span></label></td></tr>
-+ <tr><td></td><td>
-+ <span class="s">Your personal results are private from Google.</span>
-+ </td></tr></table>
-+</td>
-+</tr>
-+
-+<!-- -->
-+<tr>
-+<td class="phead pref-last">Help us improve</td>
-+<td class="pbody pref-last">
-+<input type=CHECKBOX name=SENDDATA id="SENDDATA" [CHECK-SENDDATA]><label for=
-+SENDDATA> <span class="s">Send non-personal usage data and crash reports to
-+Google to help improve Desktop Search.</span></label>
-+</td>
-+</tr>
-+
-+</table>
-+
-+<table class="shaded-subheader"><tr>
-+<td class="header-element expand s"><span class="b">Save</span> your preferences
-+when finished.</td>
-+<td class="header-element"><input type=submit value="Save Preferences"
-+name=submit2></td>
-+</tr></table>
-+
-+<p><div align=center>[$~BOTTOMLINE~$]</div>
-+<br><center><span class="s">&copy;2005 Google</span></center>
-+</form></body></html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/preprocess_test.html b/tools/grit/grit/testdata/preprocess_test.html
-new file mode 100644
-index 0000000000..13ece9a9f6
---- /dev/null
-+++ b/tools/grit/grit/testdata/preprocess_test.html
-@@ -0,0 +1,7 @@
-+<if expr="True">
-+should be kept
-+</if>
-+in the middle...
-+<if expr="False">
-+should be removed
-+</if>
-diff --git a/tools/grit/grit/testdata/privacy.html b/tools/grit/grit/testdata/privacy.html
-new file mode 100644
-index 0000000000..1d45f4a539
---- /dev/null
-+++ b/tools/grit/grit/testdata/privacy.html
-@@ -0,0 +1,35 @@
-+[!]
-+title Privacy and Google Desktop Search
-+template
-+privacy_bottomline
-+hp_image
-+
-+<TABLE CELLSPACING=0 CELLPADDING=5 WIDTH="98%" BORDER=0>
-+<TR VALIGN=TOP>
-+<td>
-+<h4>Privacy and Google Desktop Search</h4>
-+
-+<p><FONT SIZE=-1>Google is committed to making search on your desktop as easy
-+as searching the web. We recognize that privacy is an important issue,
-+so we designed and built Google Desktop Search with respect for your privacy.
-+<p>
-+So that you can easily search your computer, the Google Desktop Search application indexes
-+and stores versions of your files and other computer activity,
-+such as email, chats, and web history. These versions may also be mixed
-+with your Web search results to produce
-+results pages for you that integrate relevant content from your computer and
-+information from the Web.
-+<p>
-+Your computer's content is not made accessible to Google or anyone else without your explicit permission.
-+
-+<p>You can read the
-+<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
-+and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.
-+</font>
-+</td></tr></table>
-+
-+<center><br>
-+<TABLE CELLSPACING=0 CELLPADDING=0 WIDTH="100%" BORDER=0>
-+<TR BGCOLOR=#3399CC><TD ALIGN=MIDDLE HEIGHT=1><IMG HEIGHT=1 ALT="" WIDTH=1></td></tr></table>
-+<FONT SIZE=-1>[$~PRIVACY_BOTTOMLINE~$] - &copy;2005 Google </font>
-+</center>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/quit_apps.html b/tools/grit/grit/testdata/quit_apps.html
-new file mode 100644
-index 0000000000..a501b0e2bf
---- /dev/null
-+++ b/tools/grit/grit/testdata/quit_apps.html
-@@ -0,0 +1,49 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Google Desktop Search Preferences</title>
-+<meta http-equiv=cache-control content=no-cache>
-+<meta http-equiv=content-type content="text/html; charset=utf-8">
-+<meta http-equiv=pragma content=no-cache>
-+<meta http-equiv=expires content=-1>
-+<style>BODY {
-+ FONT-FAMILY: arial,sans-serif
-+}
-+.c:active {
-+ COLOR: #ff0000
-+}
-+.c:visited {
-+ COLOR: #7777cc
-+}
-+.c:link {
-+ COLOR: #7777cc
-+}
-+</style>
-+
-+<script>
-+<!--
-+// -->
-+</script>
-+
-+<meta content="mshtml 6.00.2800.1476" name=generator></head>
-+<BODY onresize=stw() leftMargin=30 rightMargin=30>
-+<FORM name=f action='[NEXTSTEP]' method=post><IMG src="/logo3.gif"
-+border=0>
-+<DIV id=c1 style="WIDTH: 600px">
-+<p><BR><FONT color=#00218a><B>To start using Google Desktop Search, we may need to close the following programs if they are running:</B></font></p>
-+<FONT size=-1><p>You can start these programs once Google Desktop Search is running.</p></font>
-+
-+<LI><FONT size=-1>AOL Instant Messenger</font>
-+<LI><FONT size=-1>Firefox</font>
-+<LI><FONT size=-1>Internet Explorer</font>
-+<LI><FONT size=-1>Microsoft Excel</font>
-+<LI><FONT size=-1>Microsoft Outlook </font>
-+<LI><FONT size=-1>Microsoft Word </font>
-+<LI><FONT size=-1>Mozilla</font>
-+<LI><FONT size=-1>Mozilla Thunderbird</font>
-+<LI><FONT size=-1>Netscape</font>
-+<LI><FONT size=-1>Opera</font>
-+<LI><FONT size=-1>Other web browsers</font>
-+<FONT size=-1>
-+<p>This will take only a few seconds to complete. </p></font></LI></DIV>
-+<p><INPUT id=s type=submit name="quit" value="&nbsp;&nbsp;OK.&nbsp;&nbsp;Close&nbsp;these&nbsp;applications&nbsp;&nbsp;">
-+ <INPUT id=s type=submit name="redir" value="&nbsp;&nbsp;Cancel.&nbsp;I'll&nbsp;run&nbsp;this&nbsp;later&nbsp;&nbsp;"><BR></p>
-+<center></center></FORM></body></html>
-diff --git a/tools/grit/grit/testdata/recrawl.html b/tools/grit/grit/testdata/recrawl.html
-new file mode 100644
-index 0000000000..0401e7c2b0
---- /dev/null
-+++ b/tools/grit/grit/testdata/recrawl.html
-@@ -0,0 +1,30 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head><title>Refresh index</title>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-+.q {COLOR: #0000cc}
-+</style>
-+</head>
-+<body text="#000000" vLink="#551a8b" aLink="#ff0000" link="#0000cc" bgColor="#ffffff">
-+<center>
-+<table cellSpacing="0" cellPadding="0" border="0">
-+<tr>
-+<td><a href="[$~HOMEPAGE~$]"><img border="0" height="110" alt="Google Desktop Search" src="hp_logo.gif" width="276"></a>
-+</td>
-+</tr>
-+</table>
-+<br>
-+<center>Google Desktop Search is now recrawling your drive to index new files.</center>
-+<center>Note that new files are indexed automatically, and this step is generally not needed.</center>
-+<center>Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
-+</td></tr></table>
-+<br>
-+<font size="-1">[$~BOTTOMLINE~$]</font>
-+<p><font size="-2">&copy;2005 Google</font></p>
-+</center>
-+</body>
-+</html>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/resource_ids b/tools/grit/grit/testdata/resource_ids
-new file mode 100644
-index 0000000000..d5d440d57f
---- /dev/null
-+++ b/tools/grit/grit/testdata/resource_ids
-@@ -0,0 +1,13 @@
-+{
-+ "SRCDIR": ".",
-+ "test.grd": {
-+ "messages": [100, 10000],
-+ },
-+ "substitute_no_ids.grd": {
-+ "messages": [10000, 20000],
-+ },
-+ "<(FOO)/file.grd": {
-+ },
-+ "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools.grd": {
-+ },
-+}
-diff --git a/tools/grit/grit/testdata/script.html b/tools/grit/grit/testdata/script.html
-new file mode 100644
-index 0000000000..f177d9c30e
---- /dev/null
-+++ b/tools/grit/grit/testdata/script.html
-@@ -0,0 +1,38 @@
-+<script>
-+function run(n,cut){
-+ var out = "", str = "abcdefghijklmnopqrstuvwxyz 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ,./:;'\"()*!?-_@[]{}#%`+=|\\>";
-+ n.innerHTML = 'aa';
-+
-+ var base = n.scrollWidth;
-+ for(var i=0;i<str.length;i++) {
-+ n.innerHTML = 'a'+str.charAt(i)+'a';
-+ out += str.charAt(i) + (n.scrollWidth-base) +";";
-+
-+ if(cut && !i && (n.scrollWidth-base == cut)) {
-+ return '\x02'+"0;";
-+ }
-+ }
-+ // extra cases for literals
-+ n.innerHTML = 'a&lt;a';
-+ out += '<' + (n.scrollWidth-base) +";";
-+ n.innerHTML = 'a&amp;a';
-+ out += '&' + (n.scrollWidth-base) +";";
-+
-+ var base_height = n.scrollHeight;
-+ n.innerHTML += '<br>a';
-+ out += '\x01' + (n.scrollHeight-base_height) +";";
-+
-+ return out;
-+}
-+
-+function TEST_WIDTH() {
-+ var n = document.getElementById('test');
-+ var out = run(n[$~CUT~$]);
-+ if (out.length>4){
-+ n.style.fontWeight='bold';
-+ out += run(n);
-+ }
-+ n.outerHTML = "";
-+ (new Image()).src="[$~SETWIDTH~$]?src=[COMPONENT]&data="+escape(out).replace(/\+/g,"%2B");
-+}
-+</script>
-diff --git a/tools/grit/grit/testdata/searchbox.html b/tools/grit/grit/testdata/searchbox.html
-new file mode 100644
-index 0000000000..9eccba99a5
---- /dev/null
-+++ b/tools/grit/grit/testdata/searchbox.html
-@@ -0,0 +1,22 @@
-+<body bgcolor=#ffffff topmargin=2 marginheight=2>
-+<table border=0 cellpadding=0 cellspacing=0 width=1%>
-+<tr>
-+<td valign=top><a href='[$~HOMEPAGE~$]'><img width=150 height=55 src="/logo3.gif" alt="Go to Google Desktop Search" border=0 vspace=12></a></td>
-+<td>&nbsp;&nbsp;</td>
-+<td valign=top>
-+<table cellpadding=0 cellspacing=0 border=0><tr><td colspan=2 height=14 valign=bottom>
-+<table border=0 cellpadding=4 cellspacing=0>
-+<tr><td class=q><font size=-1>
-+[$~LINKS~$]
-+</tr>
-+</table>
-+</td>
-+</tr>
-+<tr><td nowrap><form name=gs method=GET action='[$~SEARCHURL~$]'><input type=text name=q size=41 maxlength=2048 value="[DISP_QUERY]"><input type=hidden name=ie value="UTF-8">
-+<font size=-1>[$~FLAGS~$]<input type=submit name="btnG" value="Search Desktop"><span id=hf></span></font></td>
-+<td><font size=-2>&nbsp;&nbsp;<a href='[$~PREFERENCES~$]'>Desktop&nbsp;Preferences</a><br>&nbsp;&nbsp;<a [DELETE_EXTRA] href=[DELETE_PAGE]><nobr>[DELETE_NAME]</nobr></a></font></td>
-+</tr></table>
-+<table cellpadding=0 cellspacing=0 border=0>
-+<tr><td><font size=-1>&nbsp;</font></td></tr>
-+</table>
-+</td></tr></form></table>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/sidebar_h.html b/tools/grit/grit/testdata/sidebar_h.html
-new file mode 100644
-index 0000000000..e103e8f8db
---- /dev/null
-+++ b/tools/grit/grit/testdata/sidebar_h.html
-@@ -0,0 +1,82 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-+<html><head>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY,TD,DIV,A,.p { FONT-FAMILY: arial,sans-serif; SCROLL: no}
-+DIV,TD {COLOR: #000}
-+.f, .fl:link {COLOR: #6f6f6f}
-+A:link { COLOR: #00c}
-+A:visited { COLOR: #551a8b}
-+A:active { COLOR: #f00}
-+.fl:active { COLOR: #f00}
-+.h { COLOR: #3399CC}
-+.a, .a:link {COLOR: #008000}
-+.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
-+.g { MARGIN-TOP: .5em; MARGIN-BOTTOM: .5em}
-+.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
-+.c:active, .c:visited, .c:link { COLOR: #6f6f6f}
-+.ch {CURSOR: hand}
-+</style>
-+</head>
-+<BODY onload="TEST_WIDTH();" bottomMargin=0 leftMargin=2 topMargin=0 rightMargin=2 marginwidth=0 marginheight=0 SCROLL=NO bgcolor=#E0E0E0 style="border-style:solid; border-width:0;" oncontextmenu="return false;">
-+
-+<script>
-+function hide() {
-+ return 1;
-+ // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences. ");
-+}
-+</script>
-+
-+
-+<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%"><tr>
-+<TD WIDTH="19%" VALIGN=TOP>
-+
-+<form method=get action="[$~SEARCHURL~$]">
-+<input type=hidden name=src value=4>
-+
-+ <table cellspacing=0 cellpadding=0 width='1%'>
-+ <tr><td nowrap align=center valign=middle><nobr><img width=16 height=16 src=logo.gif>&nbsp;<b><i><font color=#6F6F6F>Google Desktop Search</font></i></b><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></nobr></td></tr>
-+ <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="1" style="font-size:10px; width:'100%';" name="q" id="q"></nobr></td></tr>
-+ <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="2" style="font-size:10px" type=submit value="Local search" name=btnG> <input TABINDEX="3" style="font-size:9px" type=submit value="Web search" name=redir></nobr></td></tr>
-+<MAP name="control">
-+<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+</MAP>
-+ </table>
-+</form>
-+
-+</td>
-+<TD WIDTH="27%" VALIGN=TOP>
-+
-+[HEADER_SECTION1]
-+[CONTENT_INBOX]
-+
-+</td>
-+<TD WIDTH="27%" VALIGN=top>
-+
-+[HEADER_SECTION2]
-+[CONTENT_HIST]
-+
-+</td>
-+<TD WIDTH="27%" VALIGN=top>
-+
-+[CONTENT_NEWS]
-+[CONTENT_OTHER]
-+
-+</td>
-+<TD WIDTH="1%" VALIGN=top>
-+
-+<a TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick='return hide()' href='[$~HIDE1~$]' class=ch><img width=12 height=11 style='vertical-align:top;' src=/hide.gif valign=top border=0></a>
-+
-+</td>
-+</tr></table>
-+
-+<font size=-1><span style="visibility:hidden" id='test'>t</span></font>
-+
-+[SCRIPT]
-+</body></html>
-diff --git a/tools/grit/grit/testdata/sidebar_v.html b/tools/grit/grit/testdata/sidebar_v.html
-new file mode 100644
-index 0000000000..e040d8ec59
---- /dev/null
-+++ b/tools/grit/grit/testdata/sidebar_v.html
-@@ -0,0 +1,267 @@
-+<html><head>
-+<title>Google Desktop Search Sidebar</title>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<meta http-equiv="cache-control" content="no-cache">
-+<meta http-equiv="pragma" content="no-cache">
-+<meta http-equiv="expires" content="-1">
-+<style>
-+BODY,TD,P,A {FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt; color:#fff}
-+a:link, a:visited, a:hover, b, q b { color: #ffffff}
-+a:active { color: #ff0000}
-+a:link,a:active,a:visited,div { text-decoration: none;font-size:8pt }
-+.g{margin-top: 1em;}
-+.gg{margin-top: .4em;}
-+.norepeat { background-repeat: no-repeat }
-+.indent{margin-top: 0px; margin-bottom: 0px;margin-left:3px;}
-+.c:link, .c:visited, .c:active { color: #959595;font-size:8pt }
-+.ch{cursor:pointer;cursor:hand}
-+.gap{margin-top: 10px; margin-bottom: 10px;}
-+.off {display:none}
-+.on {display:on}
-+.but { border-top: 1px solid #73787E;border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-left: 1px solid #73787E;margin-top: 0px; margin-bottom: 0px; cursor:pointer;cursor:hand}
-+</style>
-+<script>
-+
-+function toggle(i) {
-+ var v = document.getElementById(i);
-+ var vi = document.getElementById(i+'icon');
-+ var c = (v['className'] == 'on');
-+ if (c) {
-+ v['className'] = 'off';
-+ vi.src='up.gif';
-+ }
-+ else {
-+ v['className'] = 'on';
-+ vi.src='down.gif';
-+ }
-+ (new Image()).src="[$~TOGGLE~$]?setting="+i+"&mode="+v['className']+"&rnd="+Math.random();
-+
-+ if (!c && (v['oclass'] == 'off')) {
-+ location.href = location.href;
-+ }
-+
-+ return true;
-+}
-+function hide() {
-+ // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences.");
-+ return 1;
-+}
-+</script>
-+
-+<!-- menu experiment start -->
-+
-+<style>
-+<!--
-+.menu1 {
-+cursor:default;
-+position:absolute;
-+text-align: left;
-+font-family: Arial, Helvetica, sans-serif;
-+font-size: 8pt;
-+font-color: #000000;
-+color: #000000;
-+background-color: menu;
-+visibility: hidden;
-+padding-top: 2px;
-+padding-bottom: 2px;
-+border: 1 solid;
-+border-color: #888888;
-+z-index: 100;
-+}
-+.menuitems {
-+padding-left: 5px;
-+padding-right: 5px;
-+}
-+-->
-+</style>
-+<SCRIPT LANGUAGE="JavaScript1.2">
-+<!--
-+var menustyle = "menu1";
-+
-+function showmenu() {
-+ var rightedge = document.body.clientWidth-event.clientX;
-+ var bottomedge = document.body.clientHeight-event.clientY;
-+ // if (rightedge < rcmenu.offsetWidth)
-+ // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
-+ // else
-+ // rcmenu.style.left = document.body.scrollLeft + event.clientX;
-+
-+ // if (rcmenu.style.left < 0) rcmenu.style.left = 0;
-+ rcmenu.style.left = 0;
-+
-+ if (bottomedge < rcmenu.offsetHeight)
-+ rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
-+ else
-+ rcmenu.style.top = document.body.scrollTop + event.clientY;
-+
-+ if (rcmenu.style.top < 0) rcmenu.style.top = 0;
-+
-+ rcmenu.style.visibility = "visible";
-+ // rcmenu.style.zindex = 0;
-+ // document.all('rcmenu').style.zindex = 20;
-+ document.onkeydown=ck;
-+ return false;
-+}
-+
-+function hidemenu() {
-+ rcmenu.style.visibility = "hidden";
-+}
-+
-+function ck(e){
-+ evt=document.all?window.event:e;
-+ k=document.all?window.event.keyCode:e.keyCode;
-+
-+ if(k==27 /*<Esc>*/) {
-+ hidemenu();
-+ }
-+}
-+
-+function menumouseover() {
-+ if (event.srcElement.className == "menuitems") {
-+ event.srcElement.style.backgroundColor = "highlight";
-+ event.srcElement.style.color = "white";
-+ }
-+}
-+
-+function menumouseout() {
-+ if (event.srcElement.className == "menuitems") {
-+ event.srcElement.style.backgroundColor = "";
-+ event.srcElement.style.color = "black";
-+ window.status = "";
-+ }
-+}
-+
-+function menuselect() {
-+ if (event.srcElement.className == "menuitems") {
-+ if (event.srcElement.getAttribute("target") != null)
-+ window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
-+ else if (event.srcElement.url.length)
-+ window.location = event.srcElement.url;
-+ }
-+}
-+// -->
-+</script>
-+
-+<!-- menu experiment end -->
-+
-+</head>
-+
-+<body onload="TEST_WIDTH();" bottommargin=0 leftmargin=0 marginheight=0 marginwidth=0 rightmargin=0 topmargin=0 style="background-color:'#384146'; background-repeat: repeat-y; border-style:solid; border-width:0;" background="greyback.jpg" scroll=NO oncontextmenu="return false;">
-+
-+<!-- menu experiment start -->
-+
-+<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
-+<div class="menuitems" url="[$~SETDISP4~$]">Switch to minibar</div>
-+<div class="menuitems" url="[$~SETDISP2~$]">Switch to hoverbar</div>
-+<div class="menuitems" url="[$~HIDE1~$]">Close sidebar</div>
-+<div class="menuitems" url="">No change</div>
-+</div>
-+
-+<script language="JavaScript1.2">
-+if (document.all && window.print) {
-+ rcmenu.className = menustyle;
-+ document.oncontextmenu = showmenu;
-+ document.body.onclick = hidemenu;
-+}
-+</script>
-+
-+<!-- menu experiment end -->
-+
-+<div id="oneliner" style="visibility:hidden; position:absolute; left:0px; top:0px;"></div>
-+<script>
-+var h = document.getElementById("oneliner").offsetHeight*2;
-+document.write("<style type='text/css'>.truncme { overflow:hidden;height: " +h+"px; }</style>");
-+</script>
-+
-+<table cellpadding=0 cellspacing=0 border=0 width='100%'>
-+<form method=get action="[$~SEARCHURL~$]" id=f1>
-+<input type=hidden name=src value=5>
-+<input type=hidden name=redir value=''>
-+<tr>
-+ <td width='1%'><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></td>
-+ <td width='97%'><input TABINDEX="1" NAME="q" style="width:'100%'; FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt"></td>
-+ <td width='1%'><table cellpadding=2 cellspacing=0><tr><td> </td><td TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="location.href='[$~SETDISP2~$]';"><img src="mini_mini.gif"></td></tr></table></td>
-+ <td width='1%'><table cellpadding=2 cellspacing=0><tr><td TABINDEX="9" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="if (hide())location.href='[$~HIDE1~$]';"><img src="mini_close.gif"></td></tr></table></td>
-+</tr>
-+<MAP name="control">
-+<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-+</MAP>
-+</table>
-+
-+<center>
-+<table cellpadding=2 cellspacing=3>
-+<tr>
-+ <td TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit()" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch nowrap bgcolor=414A4F valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;"><img src="logo.gif" align="texttop"> <font color=ffffff>Google Desktop Search&nbsp;</td>
-+ <td TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch bgcolor=414A4F nowrap valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;">&nbsp;<font color=ffffff>Web&nbsp;</td>
-+</tr>
-+</form>
-+</table>
-+</center>
-+
-+<p class=gg>
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("news");' onclick='return toggle("news");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=newsicon src="[$~NEWS_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>News</td></tr></table>
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-+
-+<span id="news" class=[$~NEWS_CLASS~$] oclass=[$~NEWS_CLASS~$]>
-+[CONTENT_NEWS]
-+<p class=g>
-+</span>
-+
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("inbox");' onclick='return toggle("inbox");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=inboxicon src="[$~INBOX_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Email</td></tr></table>
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-+
-+<span id=inbox class=[$~INBOX_CLASS~$] oclass=[$~INBOX_CLASS~$]>
-+[CONTENT_INBOX]
-+<p class=g>
-+</span>
-+
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("hist");' onclick='return toggle("hist");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=histicon src="[$~HIST_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Related History</td></tr></table>
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-+
-+<span id="hist" class=[$~HIST_CLASS~$] oclass=[$~HIST_CLASS~$]>
-+[CONTENT_HIST]
-+<p class=g>
-+</span>
-+
-+
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("recent");' onclick='return toggle("recent");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=recenticon src="[$~RECENT_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Recent</td></tr></table>
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-+
-+<span id="recent" class=[$~RECENT_CLASS~$] oclass=[$~RECENT_CLASS~$]>
-+[CONTENT_RECENT]
-+<p class=g>
-+</span>
-+
-+
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("popular");' onclick='return toggle("popular");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=popularicon src="[$~POPULAR_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Frequently Visited</td></tr></table>
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-+
-+<span id="popular" class=[$~POPULAR_CLASS~$] oclass=[$~POPULAR_CLASS~$]>
-+[CONTENT_POPULAR]
-+<p class=g>
-+</span>
-+
-+
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("quib_debug");' onclick='return toggle("quib_debug");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=quib_debugicon src="[$~QUIB_DEBUG_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Implicit Query Debug</td></tr></table>
-+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-+
-+<span id="quib_debug" class=[$~QUIB_DEBUG_CLASS~$] oclass=[$~QUIB_DEBUG_CLASS~$]>
-+[CONTENT_QUIB_DEBUG]
-+</span>
-+
-+<span style="visibility:hidden" id='test'>t</span>
-+
-+[CONTENT_OTHER]
-+
-+[SCRIPT]
-+</body>
-+</html>
-diff --git a/tools/grit/grit/testdata/simple-input.xml b/tools/grit/grit/testdata/simple-input.xml
-new file mode 100644
-index 0000000000..92827fa4b5
---- /dev/null
-+++ b/tools/grit/grit/testdata/simple-input.xml
-@@ -0,0 +1,52 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
-+ <release seq="2">
-+ <messages>
-+ <message name="IDS_OLD_MESSAGE" translateable="true">Hello earthlings!</message>
-+ </messages>
-+ </release>
-+ <release seq="3">
-+ <includes>
-+ <include name="ID_EDIT_BOX_ICON" type="icon" translateable="false" file="images/edit_box.ico" />
-+ <include name="ID_LOGO" type="gif" translateable="true" file="images/logo.gif"/>
-+ </includes>
-+ <messages>
-+ <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ </messages>
-+ <structures>
-+ <structure type="menu" name="IDM_FOO" file="rc_files/menus.rc" />
-+ <structure type="dialog" name="IDD_BLAT" file="rc_files/dialogs.rc" />
-+ <structure type="tr_html" name="IDR_HTML_TEMPLATE" file="templates/homepage.html" />
-+ <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc">
-+ <skeleton expr="lang == 'fr-FR'" variant_of_revision="3">
-+ <![CDATA[IDD_DIALOG1 DIALOGEX 0, 0, 186, 90
-+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
-+ WS_SYSMENU
-+CAPTION "TRANSLATEABLEPLACEHOLDER1"
-+FONT 8, "MS Shell Dlg", 400, 0, 0x1
-+BEGIN
-+ DEFPUSHBUTTON "TRANSLATEABLEPLACEHOLDER2",IDOK,129,7,50,14
-+ PUSHBUTTON "TRANSLATEABLEPLACEHOLDER3",IDCANCEL,129,24,50,14
-+ LTEXT "TRANSLATEABLEPLACEHOLDER4",IDC_STATIC,23,31,40,8
-+END]]>
-+ </skeleton>
-+ </structure>
-+ <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc"/>
-+ </structures>
-+ </release>
-+ <translations>
-+ <file path="figs_nl_translations.xml" />
-+ <file path="cjk_translations.xml" />
-+ </translations>
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="resource_en.rc" type="rc_all" lang="en-US" />
-+ <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
-+ <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
-+ <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
-+ <output filename="nontranslateable.rc" type="rc_nontranslateable" />
-+ </outputs>
-+</grit>
-diff --git a/tools/grit/grit/testdata/simple.html b/tools/grit/grit/testdata/simple.html
-new file mode 100644
-index 0000000000..4392d23e98
---- /dev/null
-+++ b/tools/grit/grit/testdata/simple.html
-@@ -0,0 +1,3 @@
-+<p>
-+ Hello!
-+</p>
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/source.rc b/tools/grit/grit/testdata/source.rc
-new file mode 100644
-index 0000000000..fbc72284e9
---- /dev/null
-+++ b/tools/grit/grit/testdata/source.rc
-@@ -0,0 +1,57 @@
-+IDC_KLONKMENU MENU
-+BEGIN
-+ POPUP "&File"
-+ BEGIN
-+ MENUITEM "E&xit", IDM_EXIT
-+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
-+ POPUP "gonk"
-+ BEGIN
-+ MENUITEM "Klonk && is [good]", ID_GONK_KLONKIS
-+ END
-+ END
-+ POPUP "&Help"
-+ BEGIN
-+ MENUITEM "&About ...", IDM_ABOUT
-+ END
-+END
-+
-+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "About"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
-+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
-+ SS_NOPREFIX
-+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
-+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
-+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
-+ BS_AUTORADIOBUTTON,46,51,84,10
-+END
-+
-+IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "Bingobobbi"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
-+ LTEXT "Yo froodie!",IDC_STATIC,49,20,119,8
-+END
-+
-+STRINGTABLE
-+BEGIN
-+ IDS_SIMPLE "One"
-+ IDS_PLACEHOLDER "%s birds"
-+ IDS_PLACEHOLDERS "%d of %d"
-+ IDS_REORDERED_PLACEHOLDERS "$1 of $2"
-+ // Won't be in translations list because it has changed
-+ IDS_CHANGED "This was the old version"
-+ IDS_TWIN_1 "Hello"
-+ IDS_TWIN_2 "Hello"
-+ IDS_NOT_TRANSLATEABLE ":"
-+ IDS_LONGER_TRANSLATED "Removed document $1"
-+ // Won't appear in the list of translations because it's not in the .grd file
-+ IDS_NO_LONGER_USED "Not used"
-+ IDS_DIFFERENT_TWIN_1 "Howdie"
-+ IDS_DIFFERENT_TWIN_2 "Howdie"
-+END
-diff --git a/tools/grit/grit/testdata/special_100_percent/a.png b/tools/grit/grit/testdata/special_100_percent/a.png
-new file mode 100644
-index 0000000000000000000000000000000000000000..5d5089038ca71172e95db9e7aae1e1fa5cebd505
-GIT binary patch
-literal 159
-zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>0wld=oSO}#(mY)pLnNjq|2Y3)zGGzYPN&L+
-zMSC}CcCfp=Dtxv4%6W%G#Q=|R|L;6pCCLUWO)Z<5eoL%TkDTw=s4X!^d(Qa<2khAN
-zZPy!XToBAic1Ss}vcWiD27B3&`Zj^H6CO>7R1{ToQ;=ggdEYbV=IISvfHpFCy85}S
-Ib4q9e0O9jEh5!Hn
-
-literal 0
-HcmV?d00001
-
-diff --git a/tools/grit/grit/testdata/status.html b/tools/grit/grit/testdata/status.html
-new file mode 100644
-index 0000000000..6b997b9369
---- /dev/null
-+++ b/tools/grit/grit/testdata/status.html
-@@ -0,0 +1,44 @@
-+[HEADER]
-+<table cellspacing=0 cellPadding=0 width="100%" border=0>
-+<tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr>
-+</table>
-+<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0>
-+<tr><td height=20><font size=+1 color=#000000>&nbsp;<b>Desktop Search Status</b></font></td></tr>
-+</table>
-+<br>
-+<center>
-+[$~MESSAGE~$]
-+<table cellspacing=0 cellPadding=6 width=500 border=0>
-+<tr>
-+ <td>&nbsp;</td>
-+ <td align=right nowrap><i><font size=-1>Number of items</font></i></td>
-+ <td align=right nowrap><i><font size=-1>Time of newest item</font></i></td>
-+</tr>
-+<tr>
-+ <td width=1% nowrap><img style="vertical-align:middle" width=16 height=16 src=favicon.ico>&nbsp; Total searchable items</td>
-+ <td align=right><b>[TOTAL_COUNT]</b></td>
-+ <td align=right><b>[TOTAL_TIME]</b></td>
-+</tr>
-+<tr>
-+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=email.gif width=16 height=16>&nbsp; Emails</font></td>
-+ <td align=right><font size=-1>[EMAIL_COUNT]</font></td>
-+ <td align=right><font size=-1>[EMAIL_TIME]</font></td>
-+</tr>
-+<tr>
-+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src="16x16_chat.gif" width=16 height=16>&nbsp; Chats</font></td>
-+ <td align=right><font size=-1>[IM_COUNT]</font></td>
-+ <td align=right><font size=-1>[IM_TIME]</font></td>
-+</tr>
-+<tr>
-+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=html.gif width=16 height=16>&nbsp; Web history</font></td>
-+ <td align=right><font size=-1>[WEB_COUNT]</font></td>
-+ <td align=right><font size=-1>[WEB_TIME]</font></td>
-+</tr>
-+<tr>
-+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=file.gif width=16 height=16>&nbsp; Files</font></td>
-+ <td align=right><font size=-1>[FILE_COUNT]</font></td>
-+ <td align=right><font size=-1>[FILE_TIME]</font></td>
-+</tr>
-+</table>
-+</center>
-+[FOOTER]
-\ No newline at end of file
-diff --git a/tools/grit/grit/testdata/structure_variables.html b/tools/grit/grit/testdata/structure_variables.html
-new file mode 100644
-index 0000000000..2a15de8072
---- /dev/null
-+++ b/tools/grit/grit/testdata/structure_variables.html
-@@ -0,0 +1,4 @@
-+<h1>[GREETING]!</h1>
-+Some cool things are [THINGS].
-+Did you know that [EQUATION]?
-+<include src="[filename].html">
-diff --git a/tools/grit/grit/testdata/substitute.grd b/tools/grit/grit/testdata/substitute.grd
-new file mode 100644
-index 0000000000..95dcc56e1d
---- /dev/null
-+++ b/tools/grit/grit/testdata/substitute.grd
-@@ -0,0 +1,31 @@
-+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-+<grit
-+ base_dir="."
-+ source_lang_id="en"
-+ tc_project="GoogleDesktopWindowsClient"
-+ latest_public_release="0"
-+ current_release="1"
-+ enc_check="möl">
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
-+ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
-+ </outputs>
-+ <translations>
-+ <file path="substitute.xmb" lang="sv" />
-+ </translations>
-+ <release seq="1" allow_pseudo="false">
-+ <messages first_id="8192">
-+ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
-+ Copyright 2008 Google Inc. All Rights Reserved.
-+ </message>
-+ <message name="IDS_NEWS_PANEL_COPYRIGHT">
-+ Google Desktop News gadget
-+[IDS_COPYRIGHT_GOOGLE_LONG]
-+View news that is personalized based on the articles you read.
-+
-+For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
-+ </message>
-+ </messages>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/testdata/substitute.xmb b/tools/grit/grit/testdata/substitute.xmb
-new file mode 100644
-index 0000000000..e592069c8b
---- /dev/null
-+++ b/tools/grit/grit/testdata/substitute.xmb
-@@ -0,0 +1,10 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<!DOCTYPE translationbundle SYSTEM "/home/build/nonconf/google3/i18n/translationbundle.dtd">
-+<translationbundle lang="sv">
-+<translation id="7239109800378180620">© 2008 Google Inc. Med ensamrätt.</translation>
-+<translation id="6212022020330010625">Google Desktop News gadget
-+<ph name="IDS_COPYRIGHT_GOOGLE_LONG_1"/>
-+Se nyheter som är anpassade till dig, baserat på de artiklar du läser.
-+
-+Om du t.ex. läser massor av sportnyheter kommer du att se fler sportartiklar. Om du inte läser tekniknyheter lika ofta ser du färre av dessa artiklar.</translation>
-+</translationbundle>
-diff --git a/tools/grit/grit/testdata/substitute_no_ids.grd b/tools/grit/grit/testdata/substitute_no_ids.grd
-new file mode 100644
-index 0000000000..d569d1cacd
---- /dev/null
-+++ b/tools/grit/grit/testdata/substitute_no_ids.grd
-@@ -0,0 +1,31 @@
-+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-+<grit
-+ base_dir="."
-+ source_lang_id="en"
-+ tc_project="GoogleDesktopWindowsClient"
-+ latest_public_release="0"
-+ current_release="1"
-+ enc_check="möl">
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
-+ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
-+ </outputs>
-+ <translations>
-+ <file path="substitute.xmb" lang="sv" />
-+ </translations>
-+ <release seq="1" allow_pseudo="false">
-+ <messages>
-+ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
-+ Copyright 2008 Google Inc. All Rights Reserved.
-+ </message>
-+ <message name="IDS_NEWS_PANEL_COPYRIGHT">
-+ Google Desktop News gadget
-+[IDS_COPYRIGHT_GOOGLE_LONG]
-+View news that is personalized based on the articles you read.
-+
-+For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
-+ </message>
-+ </messages>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/testdata/substitute_tmpl.grd b/tools/grit/grit/testdata/substitute_tmpl.grd
-new file mode 100644
-index 0000000000..be7b601707
---- /dev/null
-+++ b/tools/grit/grit/testdata/substitute_tmpl.grd
-@@ -0,0 +1,31 @@
-+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-+<grit
-+ base_dir="."
-+ source_lang_id="en"
-+ tc_project="GoogleDesktopWindowsClient"
-+ latest_public_release="0"
-+ current_release="1"
-+ enc_check="möl">
-+ <outputs>
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="en_${name}_resources.rc" type="rc_all" lang="en" />
-+ <output filename="sv_${name}_resources.rc" type="rc_all" lang="sv" />
-+ </outputs>
-+ <translations>
-+ <file path="substitute.xmb" lang="sv" />
-+ </translations>
-+ <release seq="1" allow_pseudo="false">
-+ <messages first_id="8192">
-+ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
-+ Copyright 2008 Google Inc. All Rights Reserved.
-+ </message>
-+ <message name="IDS_NEWS_PANEL_COPYRIGHT">
-+ Google Desktop News gadget
-+[IDS_COPYRIGHT_GOOGLE_LONG]
-+View news that is personalized based on the articles you read.
-+
-+For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
-+ </message>
-+ </messages>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/testdata/test_css.css b/tools/grit/grit/testdata/test_css.css
-new file mode 100644
-index 0000000000..55d5dd1770
---- /dev/null
-+++ b/tools/grit/grit/testdata/test_css.css
-@@ -0,0 +1 @@
-+This is a test!
-diff --git a/tools/grit/grit/testdata/test_html.html b/tools/grit/grit/testdata/test_html.html
-new file mode 100644
-index 0000000000..55d5dd1770
---- /dev/null
-+++ b/tools/grit/grit/testdata/test_html.html
-@@ -0,0 +1 @@
-+This is a test!
-diff --git a/tools/grit/grit/testdata/test_js.js b/tools/grit/grit/testdata/test_js.js
-new file mode 100644
-index 0000000000..55d5dd1770
---- /dev/null
-+++ b/tools/grit/grit/testdata/test_js.js
-@@ -0,0 +1 @@
-+This is a test!
-diff --git a/tools/grit/grit/testdata/test_svg.svg b/tools/grit/grit/testdata/test_svg.svg
-new file mode 100644
-index 0000000000..55d5dd1770
---- /dev/null
-+++ b/tools/grit/grit/testdata/test_svg.svg
-@@ -0,0 +1 @@
-+This is a test!
-diff --git a/tools/grit/grit/testdata/test_text.txt b/tools/grit/grit/testdata/test_text.txt
-new file mode 100644
-index 0000000000..55d5dd1770
---- /dev/null
-+++ b/tools/grit/grit/testdata/test_text.txt
-@@ -0,0 +1 @@
-+This is a test!
-diff --git a/tools/grit/grit/testdata/time_related.html b/tools/grit/grit/testdata/time_related.html
-new file mode 100644
-index 0000000000..ee64b1665e
---- /dev/null
-+++ b/tools/grit/grit/testdata/time_related.html
-@@ -0,0 +1,11 @@
-+[HEADER]
-+[CHROME]
-+[NAV_PRE_POST]
-+[$~MESSAGE~$]<br>
-+<table border=0 cellpadding=2 cellspacing=0 width='100%'>
-+[CONTENTS]
-+</table><br>
-+
-+[NAV_PRE_POST]
-+[FOOTER]
-+
-diff --git a/tools/grit/grit/testdata/toolbar_about.html b/tools/grit/grit/testdata/toolbar_about.html
-new file mode 100644
-index 0000000000..bb4b0eb355
---- /dev/null
-+++ b/tools/grit/grit/testdata/toolbar_about.html
-@@ -0,0 +1,138 @@
-+<html id=dlgAbout STYLE="width: 25.8em; height: 17em" [GRITDIR]>
-+<head>
-+<meta http-equiv="content-type" content="text/html; charset=utf-8">
-+<title>About Google Toolbar</title>
-+<style>
-+.button {
-+ width: 7em;
-+ height: 2.2em;
-+ color: buttontext;
-+ font-family: MS Sans Serif;
-+ font-size:8pt;
-+ cursor: hand;
-+}
-+</style>
-+
-+<script> <!--
-+ function HandleError(message, url, line) {
-+ var L_Dialog_ErrorMessage = "An error has occured in this dialog.";
-+ var L_ErrorNumber_Text = "Error: ";
-+ var str = L_Dialog_ErrorMessage + "\n\n"
-+ + L_ErrorNumber_Text + line + "\n"
-+ + message;
-+ alert (str);
-+ window.close();
-+ return true;
-+ }
-+
-+ function OnKeyPress(nCode) {
-+ if (nCode == 27) {
-+ window.close();
-+ return;
-+ }
-+ }
-+
-+ function OnLoad() {
-+ if ((null != window.dialogArguments) && (window.dialogArguments.indexOf("&") == -1) && (window.dialogArguments.indexOf("<") == -1)) {
-+ version.innerHTML = window.dialogArguments;
-+ } else {
-+ version.innerText = "Version: Unknown";
-+ }
-+ }
-+
-+ window.onerror = HandleError;
-+ // -->
-+</script>
-+
-+</head>
-+
-+
-+<body bgcolor="#FFFFFF" onload="OnLoad()" onkeydown="OnKeyPress(event.keyCode)" onkeypress="OnKeyPress(event.keyCode)" scroll=no>
-+
-+<table border=0>
-+
-+ <tr height=5>
-+ <td width=5></td>
-+ <td></td>
-+ <td></td>
-+ <td></td>
-+ <td width=5></td>
-+ </tr>
-+
-+ <tr>
-+ <td></td>
-+ <td colspan=3>
-+
-+
-+<table border="0" cellpadding="0" cellspacing="0" valign="top">
-+ <tr>
-+ <td valign="top" height="47" width="155">
-+ <div align="center"><img src="title_toolbar.gif" width="275" height="59" alt="Google Toolbar"></div>
-+ </td>
-+ <td valign="middle" height="47" width="713">
-+ <hr size=1 color=25479D></td></tr>
-+</table>
-+
-+
-+ </td>
-+ <!--
-+ <TD colspan=2>
-+ <span style="COLOR: black; FONT: 18pt Tahoma, MS Shell Dlg"><b>
-+ Google Toolbar&trade;</b>
-+ </span>
-+ </TD>
-+ -->
-+ <td valign="middle">
-+ </td>
-+ </tr>
-+
-+ <tr>
-+ <td></td>
-+ <td align=center><img src="googly.gif"></td>
-+ <td colspan=2 align=left>
-+ <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
-+ <span id=version></span><br>
-+ </span>
-+ </td>
-+ <td></td>
-+ </tr>
-+
-+ <tr height=50>
-+ <td></td>
-+ <td></td>
-+ <td colspan=2 align=left>
-+ <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
-+ <!--$/translate-->
-+ <i>De parvis grandis acervus erit</i>
-+ <!--$translate-->
-+ </span>
-+ </td>
-+ <td></td>
-+ </tr>
-+
-+ <tr height=40>
-+ <td></td>
-+ <td></td>
-+ <td></td>
-+ <td></td>
-+ <td></td>
-+ </tr>
-+
-+ <tr>
-+ <td></td>
-+ <td width=80></td>
-+ <td>
-+ <!--$/translate-->
-+ <span style="WIDTH: 20em; COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg" id="copyright">&copy; 2006 Google</span>
-+ <!--$translate-->
-+ </td>
-+ <td id=ok-button align=right><button tabindex=1 type=submit align=right id="okButton" class=button onClick="window.close();" >OK</button>
-+ </td>
-+ <td></td>
-+ </tr>
-+
-+</table>
-+</span>
-+
-+</body>
-+</html>
-diff --git a/tools/grit/grit/testdata/tools/grit/resource_ids b/tools/grit/grit/testdata/tools/grit/resource_ids
-new file mode 100644
-index 0000000000..8a2b608df1
---- /dev/null
-+++ b/tools/grit/grit/testdata/tools/grit/resource_ids
-@@ -0,0 +1,176 @@
-+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+#
-+# This file is used to assign starting resource ids for resources and strings
-+# used by Chromium. This is done to ensure that resource ids are unique
-+# across all the grd files. If you are adding a new grd file, please add
-+# a new entry to this file.
-+#
-+# The first entry in the file, SRCDIR, is special: It is a relative path from
-+# this file to the base of your checkout.
-+#
-+# http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx says that the
-+# range for IDR_ is 1 to 28,671 and the range for IDS_ is 1 to 32,767 and
-+# common convention starts practical use of IDs at 100 or 101.
-+{
-+ "SRCDIR": "../..",
-+
-+ "chrome/browser/browser_resources.grd": {
-+ "includes": [500],
-+ },
-+ "chrome/browser/resources/component_extension_resources.grd": {
-+ "includes": [1000],
-+ },
-+ "chrome/browser/resources/net_internals_resources.grd": {
-+ "includes": [1500],
-+ },
-+ "chrome/browser/resources/shared_resources.grd": {
-+ "includes": [2000],
-+ },
-+ "chrome/common/common_resources.grd": {
-+ "includes": [2500],
-+ },
-+ "chrome/default_plugin/default_plugin_resources.grd": {
-+ "includes": [3000],
-+ },
-+ "chrome/renderer/renderer_resources.grd": {
-+ "includes": [3500],
-+ },
-+ "net/base/net_resources.grd": {
-+ "includes": [4000],
-+ },
-+ "webkit/glue/webkit_resources.grd": {
-+ "includes": [4500],
-+ },
-+ "webkit/tools/test_shell/test_shell_resources.grd": {
-+ "includes": [5000],
-+ },
-+ "ui/resources/ui_resources.grd": {
-+ "includes": [5500],
-+ },
-+ "chrome/app/theme/theme_resources.grd": {
-+ "includes": [6000],
-+ },
-+ "chrome_frame/resources/chrome_frame_resources.grd": {
-+ "includes": [6500],
-+ },
-+ # WebKit.grd can be in two different places depending on whether we are
-+ # in a chromium checkout or a webkit-only checkout.
-+ "third_party/WebKit/Source/WebKit/chromium/WebKit.grd": {
-+ "includes": [7000],
-+ },
-+ "WebKit.grd": {
-+ "includes": [7000],
-+ },
-+
-+ "ui/base/strings/app_locale_settings.grd": {
-+ "META": {"join": 2},
-+ "messages": [7500],
-+ },
-+ "chrome/app/resources/locale_settings.grd": {
-+ "includes": [8000],
-+ "messages": [8500],
-+ },
-+ # These each start with the same resource id because we only use one
-+ # file for each build (cros, linux, mac, or win).
-+ "chrome/app/resources/locale_settings_cros.grd": {
-+ "messages": [9000],
-+ },
-+ "chrome/app/resources/locale_settings_linux.grd": {
-+ "messages": [9000],
-+ },
-+ "chrome/app/resources/locale_settings_mac.grd": {
-+ "messages": [9000],
-+ },
-+ "chrome/app/resources/locale_settings_win.grd": {
-+ "messages": [9000],
-+ },
-+
-+ "ui/base/strings/ui_strings.grd": {
-+ "META": {"join": 4},
-+ "messages": [9500],
-+ },
-+ # Chromium strings and Google Chrome strings must start at the same id.
-+ # We only use one file depending on whether we're building Chromium or
-+ # Google Chrome.
-+ "chrome/app/chromium_strings.grd": {
-+ "messages": [10000],
-+ },
-+ "chrome/app/google_chrome_strings.grd": {
-+ "messages": [10000],
-+ },
-+ # Leave lots of space for generated_resources since it has most of our
-+ # strings.
-+ "chrome/app/generated_resources.grd": {
-+ "META": {"join": 2},
-+ "structures": [10500],
-+ "messages": [11000],
-+ },
-+ # The chrome frame dialogs are also in generated_resources.grd so they
-+ # get included by the translation console. We make sure that the ids
-+ # for structures here are the same as for generated_resources.grd.
-+ "chrome_frame/resources/chrome_frame_dialogs.grd": {
-+ "structures": [10500],
-+ "includes": [10750],
-+ },
-+ "webkit/glue/inspector_strings.grd": {
-+ "messages": [16000],
-+ },
-+ "webkit/glue/webkit_strings.grd": {
-+ "messages": [16500],
-+ },
-+
-+ "chrome_frame/resources/chrome_frame_resources.grd": {
-+ "includes": [17500],
-+ "structures": [18000],
-+ },
-+
-+ "ui/gfx/gfx_resources.grd": {
-+ "includes": [18500],
-+ },
-+
-+ "chrome/app/policy/policy_templates.grd": {
-+ "structures": [19000],
-+ "messages": [19010],
-+ },
-+
-+ "chrome/browser/autofill/autofill_resources.grd": {
-+ "messages": [19500],
-+ },
-+ "chrome/browser/resources/sync_internals_resources.grd": {
-+ "includes": [20000],
-+ },
-+ # This file is generated during the build.
-+ "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd": {
-+ "includes": [20500],
-+ },
-+ # All standard and large theme resources should have the same IDs.
-+ "chrome/app/theme/theme_resources_standard.grd": {
-+ "includes": [21000],
-+ },
-+ "chrome/app/theme/theme_resources_large.grd": {
-+ "includes": [21000],
-+ },
-+ # This file is generated during the build.
-+ "chrome/browser/debugger/frontend/devtools_frontend_resources.grd": {
-+ "META": {"join": 2},
-+ "includes": [21500],
-+ },
-+ "cloud_print/virtual_driver/win/install/virtual_driver_setup_resources.grd": {
-+ "messages": [22500],
-+ },
-+ "chrome/browser/resources/quota_internals_resources.grd": {
-+ "includes": [23000],
-+ },
-+ "chrome/browser/resources/workers_resources.grd": {
-+ "includes": [23500],
-+ },
-+ # All standard and large theme resources should have the same IDs.
-+ "ui/resources/ui_resources_standard.grd": {
-+ "includes": [24000],
-+ },
-+ "ui/resources/ui_resources_large.grd": {
-+ "includes": [24000],
-+ },
-+}
-diff --git a/tools/grit/grit/testdata/transl.rc b/tools/grit/grit/testdata/transl.rc
-new file mode 100644
-index 0000000000..2f2595db3f
---- /dev/null
-+++ b/tools/grit/grit/testdata/transl.rc
-@@ -0,0 +1,56 @@
-+IDC_KLONKMENU MENU
-+BEGIN
-+ POPUP "&Skra"
-+ BEGIN
-+ MENUITEM "&Haetta", IDM_EXIT
-+ MENUITEM "Thetta er ""Klonk"" sem eg fyla", ID_FILE_THISBE
-+ POPUP "gonkurinn"
-+ BEGIN
-+ MENUITEM "Klonk && er [good]", ID_GONK_KLONKIS
-+ END
-+ END
-+ POPUP "&Hjalp"
-+ BEGIN
-+ MENUITEM "&Um...", IDM_ABOUT
-+ END
-+END
-+
-+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "Um Klonk"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
-+ LTEXT "klonk utgafa ""jibbi"" 1.0",IDC_STATIC,49,10,119,8,
-+ SS_NOPREFIX
-+ LTEXT "Hofundarrettur (C) 2005",IDC_STATIC,49,20,119,8
-+ DEFPUSHBUTTON "I lagi",IDOK,195,6,30,11,WS_GROUP
-+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
-+ BS_AUTORADIOBUTTON,46,51,84,10
-+END
-+
-+IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
-+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-+CAPTION "Bingobobbi"
-+FONT 8, "System", 0, 0, 0x0
-+BEGIN
-+ LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
-+END
-+
-+STRINGTABLE
-+BEGIN
-+ IDS_SIMPLE "Ein"
-+ IDS_PLACEHOLDER "%s Vogeln"
-+ IDS_PLACEHOLDERS "%d von %d"
-+ // Shouldn't be part of translations list because the translation is
-+ // reordered so placeholder fixup fails
-+ IDS_REORDERED_PLACEHOLDERS "$2 auf $1"
-+ IDS_CHANGED "Dass war die alte Version"
-+ IDS_TWIN_1 "Hallo"
-+ IDS_TWIN_2 "Hallo"
-+ IDS_NOT_TRANSLATEABLE ":"
-+ IDS_LONGER_TRANSLATED "Dokument $1 ist entfernt worden"
-+ IDS_NO_LONGER_USED "Nicht verwendet"
-+ IDS_DIFFERENT_TWIN_1 "Howdie"
-+ IDS_DIFFERENT_TWIN_2 "Hallo sagt man"
-+END
-diff --git a/tools/grit/grit/testdata/versions.html b/tools/grit/grit/testdata/versions.html
-new file mode 100644
-index 0000000000..d1f40d8d72
---- /dev/null
-+++ b/tools/grit/grit/testdata/versions.html
-@@ -0,0 +1,7 @@
-+[HEADER]
-+
-+[TOP_CHROME]
-+[CONTENTS]
-+
-+[NEXT_PREV]
-+[FOOTER]
-diff --git a/tools/grit/grit/testdata/whitelist.txt b/tools/grit/grit/testdata/whitelist.txt
-new file mode 100644
-index 0000000000..5b3aca40b5
---- /dev/null
-+++ b/tools/grit/grit/testdata/whitelist.txt
-@@ -0,0 +1,4 @@
-+IDS_MESSAGE_WHITELISTED
-+IDR_STRUCTURE_WHITELISTED
-+IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED
-+IDR_INCLUDE_WHITELISTED
-diff --git a/tools/grit/grit/testdata/whitelist_resources.grd b/tools/grit/grit/testdata/whitelist_resources.grd
-new file mode 100644
-index 0000000000..9925688ff5
---- /dev/null
-+++ b/tools/grit/grit/testdata/whitelist_resources.grd
-@@ -0,0 +1,54 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="0"
-+ current_release="1"
-+ output_all_resource_defines="false">
-+ <outputs>
-+ <output filename="whitelist_test_resources.h" type="rc_header">
-+ <emit emit_type='prepend'></emit>
-+ </output>
-+ <output filename="whitelist_test_resources_map.cc"
-+ type="resource_file_map_source" />
-+ <output filename="whitelist_test_resources_map.h"
-+ type="resource_map_header" />
-+ <output filename="whitelist_test_resources.pak" type="data_package" />
-+ </outputs>
-+ <translations>
-+ <file path="substitute.xmb" lang="sv" />
-+ </translations>
-+ <release seq="1">
-+ <structures>
-+ <structure name="IDR_STRUCTURE_WHITELISTED" file="browser.html"
-+ type="chrome_html" >
-+ </structure>
-+ <structure name="IDR_STRUCTURE_NOT_WHITELISTED" file="deleted.html"
-+ type="chrome_html" >
-+ </structure>
-+ <if expr="True">
-+ <structure name="IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED"
-+ file="details.html"
-+ type="chrome_html" >
-+ </structure>
-+ <structure name="IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED"
-+ file="error.html"
-+ type="chrome_html" >
-+ </structure>
-+ </if>
-+ <if expr="False">
-+ <structure name="IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED"
-+ file="status.html"
-+ type="chrome_html" >
-+ </structure>
-+ <structure name="IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED"
-+ file="simple.html"
-+ type="chrome_html" >
-+ </structure>
-+ </if>
-+ </structures>
-+ <includes>
-+ <include name="IDR_INCLUDE_WHITELISTED" file="klonk.ico"
-+ type="BINDATA" />
-+ <include name="IDR_INCLUDE_NOT_WHITELISTED" file="klonk.rc"
-+ type="BINDATA" />
-+ </includes>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/testdata/whitelist_strings.grd b/tools/grit/grit/testdata/whitelist_strings.grd
-new file mode 100644
-index 0000000000..df80f5fd32
---- /dev/null
-+++ b/tools/grit/grit/testdata/whitelist_strings.grd
-@@ -0,0 +1,23 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<grit latest_public_release="0"
-+ current_release="1"
-+ output_all_resource_defines="false">
-+ <outputs >
-+ <output filename="whitelist_test_resources.h" type="rc_header">
-+ <emit emit_type='prepend'></emit>
-+ </output>
-+ <output filename="en_whitelist_test_strings.rc" type="rc_all" lang="en" />
-+ </outputs>
-+ <release seq="1">
-+ <messages>
-+ <message name="IDS_MESSAGE_WHITELISTED"
-+ desc="A message in the whiltelist file.">
-+ Whitelisted.
-+ </message>
-+ <message name="IDS_MESSAGE_NOT_WHITELISTED"
-+ desc="A message that isn't in the whiltelist file.">
-+ Not whitelisted.
-+ </message>
-+ </messages>
-+ </release>
-+</grit>
-diff --git a/tools/grit/grit/tool/__init__.py b/tools/grit/grit/tool/__init__.py
-new file mode 100644
-index 0000000000..cc455b36e7
---- /dev/null
-+++ b/tools/grit/grit/tool/__init__.py
-@@ -0,0 +1,8 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Package grit.tool
-+'''
-+
-+pass
-diff --git a/tools/grit/grit/tool/android2grd.py b/tools/grit/grit/tool/android2grd.py
-new file mode 100644
-index 0000000000..005297bafe
---- /dev/null
-+++ b/tools/grit/grit/tool/android2grd.py
-@@ -0,0 +1,484 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""The 'grit android2grd' tool."""
-+
-+from __future__ import print_function
-+
-+import getopt
-+import os.path
-+import sys
-+from xml.dom import Node
-+import xml.dom.minidom
-+
-+import six
-+from six import StringIO
-+
-+import grit.node.empty
-+from grit.node import node_io
-+from grit.node import message
-+
-+from grit.tool import interface
-+
-+from grit import grd_reader
-+from grit import lazy_re
-+from grit import tclib
-+
-+
-+# The name of a string in strings.xml
-+_STRING_NAME = lazy_re.compile(r'[a-z0-9_]+\Z')
-+
-+# A string's character limit in strings.xml
-+_CHAR_LIMIT = lazy_re.compile(r'\[CHAR-LIMIT=(\d+)\]')
-+
-+# Finds String.Format() style format specifiers such as "%-5.2f".
-+_FORMAT_SPECIFIER = lazy_re.compile(
-+ r'%'
-+ r'([1-9][0-9]*\$|<)?' # argument_index
-+ r'([-#+ 0,(]*)' # flags
-+ r'([0-9]+)?' # width
-+ r'(\.[0-9]+)?' # precision
-+ r'([bBhHsScCdoxXeEfgGaAtT%n])') # conversion
-+
-+
-+class Android2Grd(interface.Tool):
-+ """Tool for converting Android string.xml files into chrome Grd files.
-+
-+Usage: grit [global options] android2grd [OPTIONS] STRINGS_XML
-+
-+The Android2Grd tool will convert an Android strings.xml file (whose path is
-+specified by STRINGS_XML) and create a chrome style grd file containing the
-+relevant information.
-+
-+Because grd documents are much richer than strings.xml documents we supplement
-+the information required by grds using OPTIONS with sensible defaults.
-+
-+OPTIONS may be any of the following:
-+
-+ --name FILENAME Specify the base FILENAME. This should be without
-+ any file type suffix. By default
-+ "chrome_android_strings" will be used.
-+
-+ --languages LANGUAGES Comma separated list of ISO language codes (e.g.
-+ en-US, en-GB, ru, zh-CN). These codes will be used
-+ to determine the names of resource and translations
-+ files that will be declared by the output grd file.
-+
-+ --grd-dir GRD_DIR Specify where the resultant grd file
-+ (FILENAME.grd) should be output. By default this
-+ will be the present working directory.
-+
-+ --header-dir HEADER_DIR Specify the location of the directory where grit
-+ generated C++ headers (whose name will be
-+ FILENAME.h) will be placed. Use an empty string to
-+ disable rc generation. Default: empty.
-+
-+ --rc-dir RC_DIR Specify the directory where resource files will
-+ be located relative to grit build's output
-+ directory. Use an empty string to disable rc
-+ generation. Default: empty.
-+
-+ --xml-dir XML_DIR Specify where to place localized strings.xml files
-+ relative to grit build's output directory. For each
-+ language xx a values-xx/strings.xml file will be
-+ generated. Use an empty string to disable
-+ strings.xml generation. Default: '.'.
-+
-+ --xtb-dir XTB_DIR Specify where the xtb files containing translations
-+ will be located relative to the grd file. Default:
-+ '.'.
-+"""
-+
-+ _NAME_FLAG = 'name'
-+ _LANGUAGES_FLAG = 'languages'
-+ _GRD_DIR_FLAG = 'grd-dir'
-+ _RC_DIR_FLAG = 'rc-dir'
-+ _HEADER_DIR_FLAG = 'header-dir'
-+ _XTB_DIR_FLAG = 'xtb-dir'
-+ _XML_DIR_FLAG = 'xml-dir'
-+
-+ def __init__(self):
-+ self.name = 'chrome_android_strings'
-+ self.languages = []
-+ self.grd_dir = '.'
-+ self.rc_dir = None
-+ self.xtb_dir = '.'
-+ self.xml_res_dir = '.'
-+ self.header_dir = None
-+
-+ def ShortDescription(self):
-+ """Returns a short description of the Android2Grd tool.
-+
-+ Overridden from grit.interface.Tool
-+
-+ Returns:
-+ A string containing a short description of the android2grd tool.
-+ """
-+ return 'Converts Android string.xml files into Chrome grd files.'
-+
-+ def ParseOptions(self, args):
-+ """Set this objects and return all non-option arguments."""
-+ flags = [
-+ Android2Grd._NAME_FLAG,
-+ Android2Grd._LANGUAGES_FLAG,
-+ Android2Grd._GRD_DIR_FLAG,
-+ Android2Grd._RC_DIR_FLAG,
-+ Android2Grd._HEADER_DIR_FLAG,
-+ Android2Grd._XTB_DIR_FLAG,
-+ Android2Grd._XML_DIR_FLAG, ]
-+ (opts, args) = getopt.getopt(
-+ args, None, ['%s=' % o for o in flags] + ['help'])
-+
-+ for key, val in opts:
-+ # Get rid of the preceding hypens.
-+ k = key[2:]
-+ if k == Android2Grd._NAME_FLAG:
-+ self.name = val
-+ elif k == Android2Grd._LANGUAGES_FLAG:
-+ self.languages = val.split(',')
-+ elif k == Android2Grd._GRD_DIR_FLAG:
-+ self.grd_dir = val
-+ elif k == Android2Grd._RC_DIR_FLAG:
-+ self.rc_dir = val
-+ elif k == Android2Grd._HEADER_DIR_FLAG:
-+ self.header_dir = val
-+ elif k == Android2Grd._XTB_DIR_FLAG:
-+ self.xtb_dir = val
-+ elif k == Android2Grd._XML_DIR_FLAG:
-+ self.xml_res_dir = val
-+ elif k == 'help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+ return args
-+
-+ def Run(self, opts, args):
-+ """Runs the Android2Grd tool.
-+
-+ Inherited from grit.interface.Tool.
-+
-+ Args:
-+ opts: List of string arguments that should be parsed.
-+ args: String containing the path of the strings.xml file to be converted.
-+ """
-+ args = self.ParseOptions(args)
-+ if len(args) != 1:
-+ print('Tool requires one argument, the path to the Android '
-+ 'strings.xml resource file to be converted.')
-+ return 2
-+ self.SetOptions(opts)
-+
-+ android_path = args[0]
-+
-+ # Read and parse the Android strings.xml file.
-+ with open(android_path) as android_file:
-+ android_dom = xml.dom.minidom.parse(android_file)
-+
-+ # Do the hard work -- convert the Android dom to grd file contents.
-+ grd_dom = self.AndroidDomToGrdDom(android_dom)
-+ grd_string = six.text_type(grd_dom)
-+
-+ # Write the grd string to a file in grd_dir.
-+ grd_filename = self.name + '.grd'
-+ grd_path = os.path.join(self.grd_dir, grd_filename)
-+ with open(grd_path, 'w') as grd_file:
-+ grd_file.write(grd_string)
-+
-+ def AndroidDomToGrdDom(self, android_dom):
-+ """Converts a strings.xml DOM into a DOM representing the contents of
-+ a grd file.
-+
-+ Args:
-+ android_dom: A xml.dom.Document containing the contents of the Android
-+ string.xml document.
-+ Returns:
-+ The DOM for the grd xml document produced by converting the Android DOM.
-+ """
-+
-+ # Start with a basic skeleton for the .grd file.
-+ root = grd_reader.Parse(StringIO(
-+ '''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit base_dir="." latest_public_release="0"
-+ current_release="1" source_lang_id="en">
-+ <outputs />
-+ <translations />
-+ <release allow_pseudo="false" seq="1">
-+ <messages fallback_to_english="true" />
-+ </release>
-+ </grit>'''), dir='.')
-+ outputs = root.children[0]
-+ translations = root.children[1]
-+ messages = root.children[2].children[0]
-+ assert (isinstance(messages, grit.node.empty.MessagesNode) and
-+ isinstance(translations, grit.node.empty.TranslationsNode) and
-+ isinstance(outputs, grit.node.empty.OutputsNode))
-+
-+ if self.header_dir:
-+ cpp_header = self.__CreateCppHeaderOutputNode(outputs, self.header_dir)
-+ for lang in self.languages:
-+ # Create an output element for each language.
-+ if self.rc_dir:
-+ self.__CreateRcOutputNode(outputs, lang, self.rc_dir)
-+ if self.xml_res_dir:
-+ self.__CreateAndroidXmlOutputNode(outputs, lang, self.xml_res_dir)
-+ if lang != 'en':
-+ self.__CreateFileNode(translations, lang)
-+ # Convert all the strings.xml strings into grd messages.
-+ self.__CreateMessageNodes(messages, android_dom.documentElement)
-+
-+ return root
-+
-+ def __CreateMessageNodes(self, messages, resources):
-+ """Creates the <message> elements and adds them as children of <messages>.
-+
-+ Args:
-+ messages: the <messages> element in the strings.xml dom.
-+ resources: the <resources> element in the grd dom.
-+ """
-+ # <string> elements contain the definition of the resource.
-+ # The description of a <string> element is contained within the comment
-+ # node element immediately preceeding the string element in question.
-+ description = ''
-+ for child in resources.childNodes:
-+ if child.nodeType == Node.COMMENT_NODE:
-+ # Remove leading/trailing whitespace; collapse consecutive whitespaces.
-+ description = ' '.join(child.data.split())
-+ elif child.nodeType == Node.ELEMENT_NODE:
-+ if child.tagName != 'string':
-+ print('Warning: ignoring unknown tag <%s>' % child.tagName)
-+ else:
-+ translatable = self.IsTranslatable(child)
-+ raw_name = child.getAttribute('name')
-+ if not _STRING_NAME.match(raw_name):
-+ print('Error: illegal string name: %s' % raw_name)
-+ grd_name = 'IDS_' + raw_name.upper()
-+ # Transform the <string> node contents into a tclib.Message, taking
-+ # care to handle whitespace transformations and escaped characters,
-+ # and coverting <xliff:g> placeholders into <ph> placeholders.
-+ msg = self.CreateTclibMessage(child)
-+ msg_node = self.__CreateMessageNode(messages, grd_name, description,
-+ msg, translatable)
-+ messages.AddChild(msg_node)
-+ # Reset the description once a message has been parsed.
-+ description = ''
-+
-+ def CreateTclibMessage(self, android_string):
-+ """Transforms a <string/> element from strings.xml into a tclib.Message.
-+
-+ Interprets whitespace, quotes, and escaped characters in the android_string
-+ according to Android's formatting and styling rules for strings. Also
-+ converts <xliff:g> placeholders into <ph> placeholders, e.g.:
-+
-+ <xliff:g id="website" example="google.com">%s</xliff:g>
-+ becomes
-+ <ph name="website"><ex>google.com</ex>%s</ph>
-+
-+ Returns:
-+ The tclib.Message.
-+ """
-+ msg = tclib.Message()
-+ current_text = '' # Accumulated text that hasn't yet been added to msg.
-+ nodes = android_string.childNodes
-+
-+ for i, node in enumerate(nodes):
-+ # Handle text nodes.
-+ if node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
-+ current_text += node.data
-+
-+ # Handle <xliff:g> and other tags.
-+ elif node.nodeType == Node.ELEMENT_NODE:
-+ if node.tagName == 'xliff:g':
-+ assert node.hasAttribute('id'), 'missing id: ' + node.data()
-+ placeholder_id = node.getAttribute('id')
-+ placeholder_text = self.__FormatPlaceholderText(node)
-+ placeholder_example = node.getAttribute('example')
-+ if not placeholder_example:
-+ print('Info: placeholder does not contain an example: %s' %
-+ node.toxml())
-+ placeholder_example = placeholder_id.upper()
-+ msg.AppendPlaceholder(tclib.Placeholder(placeholder_id,
-+ placeholder_text, placeholder_example))
-+ else:
-+ print('Warning: removing tag <%s> which must be inside a '
-+ 'placeholder: %s' % (node.tagName, node.toxml()))
-+ msg.AppendText(self.__FormatPlaceholderText(node))
-+
-+ # Handle other nodes.
-+ elif node.nodeType != Node.COMMENT_NODE:
-+ assert False, 'Unknown node type: %s' % node.nodeType
-+
-+ is_last_node = (i == len(nodes) - 1)
-+ if (current_text and
-+ (is_last_node or nodes[i + 1].nodeType == Node.ELEMENT_NODE)):
-+ # For messages containing just text and comments (no xml tags) Android
-+ # strips leading and trailing whitespace. We mimic that behavior.
-+ if not msg.GetContent() and is_last_node:
-+ current_text = current_text.strip()
-+ msg.AppendText(self.__FormatAndroidString(current_text))
-+ current_text = ''
-+
-+ return msg
-+
-+ def __FormatAndroidString(self, android_string, inside_placeholder=False):
-+ r"""Returns android_string formatted for a .grd file.
-+
-+ * Collapses consecutive whitespaces, except when inside double-quotes.
-+ * Replaces \\, \n, \t, \", \' with \, newline, tab, ", '.
-+ """
-+ backslash_map = {'\\' : '\\', 'n' : '\n', 't' : '\t', '"' : '"', "'" : "'"}
-+ is_quoted_section = False # True when we're inside double quotes.
-+ is_backslash_sequence = False # True after seeing an unescaped backslash.
-+ prev_char = ''
-+ output = []
-+ for c in android_string:
-+ if is_backslash_sequence:
-+ # Unescape \\, \n, \t, \", and \'.
-+ assert c in backslash_map, 'Illegal escape sequence: \\%s' % c
-+ output.append(backslash_map[c])
-+ is_backslash_sequence = False
-+ elif c == '\\':
-+ is_backslash_sequence = True
-+ elif c.isspace() and not is_quoted_section:
-+ # Turn whitespace into ' ' and collapse consecutive whitespaces.
-+ if not prev_char.isspace():
-+ output.append(' ')
-+ elif c == '"':
-+ is_quoted_section = not is_quoted_section
-+ else:
-+ output.append(c)
-+ prev_char = c
-+ output = ''.join(output)
-+
-+ if is_quoted_section:
-+ print('Warning: unbalanced quotes in string: %s' % android_string)
-+
-+ if is_backslash_sequence:
-+ print('Warning: trailing backslash in string: %s' % android_string)
-+
-+ # Check for format specifiers outside of placeholder tags.
-+ if not inside_placeholder:
-+ format_specifier = _FORMAT_SPECIFIER.search(output)
-+ if format_specifier:
-+ print('Warning: format specifiers are not inside a placeholder '
-+ '<xliff:g/> tag: %s' % output)
-+
-+ return output
-+
-+ def __FormatPlaceholderText(self, placeholder_node):
-+ """Returns the text inside of an <xliff:g> placeholder node."""
-+ text = []
-+ for childNode in placeholder_node.childNodes:
-+ if childNode.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
-+ text.append(childNode.data)
-+ elif childNode.nodeType != Node.COMMENT_NODE:
-+ assert False, 'Unknown node type in ' + placeholder_node.toxml()
-+ return self.__FormatAndroidString(''.join(text), inside_placeholder=True)
-+
-+ def __CreateMessageNode(self, messages_node, grd_name, description, msg,
-+ translatable):
-+ """Creates and initializes a <message> element.
-+
-+ Message elements correspond to Android <string> elements in that they
-+ declare a string resource along with a programmatic id.
-+ """
-+ if not description:
-+ print('Warning: no description for %s' % grd_name)
-+ # Check that we actually fit within the character limit we've specified.
-+ match = _CHAR_LIMIT.search(description)
-+ if match:
-+ char_limit = int(match.group(1))
-+ msg_content = msg.GetRealContent()
-+ if len(msg_content) > char_limit:
-+ print('Warning: char-limit for %s is %d, but length is %d: %s' %
-+ (grd_name, char_limit, len(msg_content), msg_content))
-+ return message.MessageNode.Construct(parent=messages_node,
-+ name=grd_name,
-+ message=msg,
-+ desc=description,
-+ translateable=translatable)
-+
-+ def __CreateFileNode(self, translations_node, lang):
-+ """Creates and initializes the <file> elements.
-+
-+ File elements provide information on the location of translation files
-+ (xtbs)
-+ """
-+ xtb_file = os.path.normpath(os.path.join(
-+ self.xtb_dir, '%s_%s.xtb' % (self.name, lang)))
-+ fnode = node_io.FileNode()
-+ fnode.StartParsing(u'file', translations_node)
-+ fnode.HandleAttribute('path', xtb_file)
-+ fnode.HandleAttribute('lang', lang)
-+ fnode.EndParsing()
-+ translations_node.AddChild(fnode)
-+ return fnode
-+
-+ def __CreateCppHeaderOutputNode(self, outputs_node, header_dir):
-+ """Creates the <output> element corresponding to the generated c header."""
-+ header_file_name = os.path.join(header_dir, self.name + '.h')
-+ header_node = node_io.OutputNode()
-+ header_node.StartParsing(u'output', outputs_node)
-+ header_node.HandleAttribute('filename', header_file_name)
-+ header_node.HandleAttribute('type', 'rc_header')
-+ emit_node = node_io.EmitNode()
-+ emit_node.StartParsing(u'emit', header_node)
-+ emit_node.HandleAttribute('emit_type', 'prepend')
-+ emit_node.EndParsing()
-+ header_node.AddChild(emit_node)
-+ header_node.EndParsing()
-+ outputs_node.AddChild(header_node)
-+ return header_node
-+
-+ def __CreateRcOutputNode(self, outputs_node, lang, rc_dir):
-+ """Creates the <output> element corresponding to various rc file output."""
-+ rc_file_name = self.name + '_' + lang + ".rc"
-+ rc_path = os.path.join(rc_dir, rc_file_name)
-+ node = node_io.OutputNode()
-+ node.StartParsing(u'output', outputs_node)
-+ node.HandleAttribute('filename', rc_path)
-+ node.HandleAttribute('lang', lang)
-+ node.HandleAttribute('type', 'rc_all')
-+ node.EndParsing()
-+ outputs_node.AddChild(node)
-+ return node
-+
-+ def __CreateAndroidXmlOutputNode(self, outputs_node, locale, xml_res_dir):
-+ """Creates the <output> element corresponding to various rc file output."""
-+ # Need to check to see if the locale has a region, e.g. the GB in en-GB.
-+ # When a locale has a region Android expects the region to be prefixed
-+ # with an 'r'. For example for en-GB Android expects a values-en-rGB
-+ # directory. Also, Android expects nb, tl, in, iw, ji as the language
-+ # codes for Norwegian, Tagalog/Filipino, Indonesian, Hebrew, and Yiddish:
-+ # http://developer.android.com/reference/java/util/Locale.html
-+ if locale == 'es-419':
-+ android_locale = 'es-rUS'
-+ else:
-+ android_lang, dash, region = locale.partition('-')
-+ lang_map = {'no': 'nb', 'fil': 'tl', 'id': 'in', 'he': 'iw', 'yi': 'ji'}
-+ android_lang = lang_map.get(android_lang, android_lang)
-+ android_locale = android_lang + ('-r' + region if region else '')
-+ values = 'values-' + android_locale if android_locale != 'en' else 'values'
-+ xml_path = os.path.normpath(os.path.join(
-+ xml_res_dir, values, 'strings.xml'))
-+
-+ node = node_io.OutputNode()
-+ node.StartParsing(u'output', outputs_node)
-+ node.HandleAttribute('filename', xml_path)
-+ node.HandleAttribute('lang', locale)
-+ node.HandleAttribute('type', 'android')
-+ node.EndParsing()
-+ outputs_node.AddChild(node)
-+ return node
-+
-+ def IsTranslatable(self, android_string):
-+ """Determines if a <string> element is a candidate for translation.
-+
-+ A <string> element is by default translatable unless otherwise marked.
-+ """
-+ if android_string.hasAttribute('translatable'):
-+ value = android_string.getAttribute('translatable').lower()
-+ if value not in ('true', 'false'):
-+ print('Warning: translatable attribute has invalid value: %s' % value)
-+ return value == 'true'
-+ else:
-+ return True
-diff --git a/tools/grit/grit/tool/android2grd_unittest.py b/tools/grit/grit/tool/android2grd_unittest.py
-new file mode 100644
-index 0000000000..a6934a707c
---- /dev/null
-+++ b/tools/grit/grit/tool/android2grd_unittest.py
-@@ -0,0 +1,181 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.tool.android2grd'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+import xml.dom.minidom
-+
-+from grit import util
-+from grit.node import empty
-+from grit.node import message
-+from grit.node import misc
-+from grit.node import node_io
-+from grit.tool import android2grd
-+
-+
-+class Android2GrdUnittest(unittest.TestCase):
-+
-+ def __Parse(self, xml_string):
-+ return xml.dom.minidom.parseString(xml_string).childNodes[0]
-+
-+ def testCreateTclibMessage(self):
-+ tool = android2grd.Android2Grd()
-+ msg = tool.CreateTclibMessage(self.__Parse(r'''
-+ <string name="simple">A simple string</string>'''))
-+ self.assertEqual(msg.GetRealContent(), 'A simple string')
-+ msg = tool.CreateTclibMessage(self.__Parse(r'''
-+ <string name="outer_whitespace">
-+ Strip leading/trailing whitespace
-+ </string>'''))
-+ self.assertEqual(msg.GetRealContent(), 'Strip leading/trailing whitespace')
-+ msg = tool.CreateTclibMessage(self.__Parse(r'''
-+ <string name="inner_whitespace">Fold multiple spaces</string>'''))
-+ self.assertEqual(msg.GetRealContent(), 'Fold multiple spaces')
-+ msg = tool.CreateTclibMessage(self.__Parse(r'''
-+ <string name="escaped_spaces">Retain \n escaped\t spaces</string>'''))
-+ self.assertEqual(msg.GetRealContent(), 'Retain \n escaped\t spaces')
-+ msg = tool.CreateTclibMessage(self.__Parse(r'''
-+ <string name="quotes"> " Quotes preserve
-+ whitespace" but only for "enclosed elements "
-+ </string>'''))
-+ self.assertEqual(msg.GetRealContent(), ''' Quotes preserve
-+ whitespace but only for enclosed elements ''')
-+ msg = tool.CreateTclibMessage(self.__Parse(
-+ r'''<string name="escaped_characters">Escaped characters: \"\'\\\t\n'''
-+ '</string>'))
-+ self.assertEqual(msg.GetRealContent(), '''Escaped characters: "'\\\t\n''')
-+ msg = tool.CreateTclibMessage(self.__Parse(
-+ '<string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" '
-+ 'name="placeholders">'
-+ 'Open <xliff:g id="FILENAME" example="internet.html">%s</xliff:g>?'
-+ '</string>'))
-+ self.assertEqual(msg.GetRealContent(), 'Open %s?')
-+ self.assertEqual(len(msg.GetPlaceholders()), 1)
-+ self.assertEqual(msg.GetPlaceholders()[0].presentation, 'FILENAME')
-+ self.assertEqual(msg.GetPlaceholders()[0].original, '%s')
-+ self.assertEqual(msg.GetPlaceholders()[0].example, 'internet.html')
-+ msg = tool.CreateTclibMessage(self.__Parse(r'''
-+ <string name="comment">Contains a <!-- ignore this --> comment
-+ </string>'''))
-+ self.assertEqual(msg.GetRealContent(), 'Contains a comment')
-+
-+ def testIsTranslatable(self):
-+ tool = android2grd.Android2Grd()
-+ string_el = self.__Parse('<string>Hi</string>')
-+ self.assertTrue(tool.IsTranslatable(string_el))
-+ string_el = self.__Parse(
-+ '<string translatable="true">Hi</string>')
-+ self.assertTrue(tool.IsTranslatable(string_el))
-+ string_el = self.__Parse(
-+ '<string translatable="false">Hi</string>')
-+ self.assertFalse(tool.IsTranslatable(string_el))
-+
-+ def __ParseAndroidXml(self, options = []):
-+ tool = android2grd.Android2Grd()
-+
-+ tool.ParseOptions(options)
-+
-+ android_path = util.PathFromRoot('grit/testdata/android.xml')
-+ with open(android_path) as android_file:
-+ android_dom = xml.dom.minidom.parse(android_file)
-+
-+ grd = tool.AndroidDomToGrdDom(android_dom)
-+ self.assertTrue(isinstance(grd, misc.GritNode))
-+
-+ return grd
-+
-+ def testAndroidDomToGrdDom(self):
-+ grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru'])
-+
-+ # Check that the structure of the GritNode is as expected.
-+ messages = grd.GetChildrenOfType(message.MessageNode)
-+ translations = grd.GetChildrenOfType(empty.TranslationsNode)
-+ files = grd.GetChildrenOfType(node_io.FileNode)
-+
-+ self.assertEqual(len(translations), 1)
-+ self.assertEqual(len(files), 3)
-+ self.assertEqual(len(messages), 5)
-+
-+ # Check that a message node is constructed correctly.
-+ msg = [x for x in messages if x.GetTextualIds()[0] == 'IDS_PLACEHOLDERS']
-+ self.assertTrue(msg)
-+ msg = msg[0]
-+
-+ self.assertTrue(msg.IsTranslateable())
-+ self.assertEqual(msg.attrs["desc"], "A string with placeholder.")
-+
-+ def testTranslatableAttribute(self):
-+ grd = self.__ParseAndroidXml([])
-+ messages = grd.GetChildrenOfType(message.MessageNode)
-+ msgs = [x for x in messages if x.GetTextualIds()[0] == 'IDS_CONSTANT']
-+ self.assertTrue(msgs)
-+ self.assertFalse(msgs[0].IsTranslateable())
-+
-+ def testTranslations(self):
-+ grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru,id'])
-+
-+ files = grd.GetChildrenOfType(node_io.FileNode)
-+ us_file = [x for x in files if x.attrs['lang'] == 'en-US']
-+ self.assertTrue(us_file)
-+ self.assertEqual(us_file[0].GetInputPath(),
-+ 'chrome_android_strings_en-US.xtb')
-+
-+ id_file = [x for x in files if x.attrs['lang'] == 'id']
-+ self.assertTrue(id_file)
-+ self.assertEqual(id_file[0].GetInputPath(),
-+ 'chrome_android_strings_id.xtb')
-+
-+ def testOutputs(self):
-+ grd = self.__ParseAndroidXml(['--languages', 'en-US,ru,id',
-+ '--rc-dir', 'rc/dir',
-+ '--header-dir', 'header/dir',
-+ '--xtb-dir', 'xtb/dir',
-+ '--xml-dir', 'xml/dir'])
-+
-+ outputs = grd.GetChildrenOfType(node_io.OutputNode)
-+ self.assertEqual(len(outputs), 7)
-+
-+ header_outputs = [x for x in outputs if x.GetType() == 'rc_header']
-+ rc_outputs = [x for x in outputs if x.GetType() == 'rc_all']
-+ xml_outputs = [x for x in outputs if x.GetType() == 'android']
-+
-+ self.assertEqual(len(header_outputs), 1)
-+ self.assertEqual(len(rc_outputs), 3)
-+ self.assertEqual(len(xml_outputs), 3)
-+
-+ # The header node should have an "<emit>" child and the proper filename.
-+ self.assertTrue(header_outputs[0].GetChildrenOfType(node_io.EmitNode))
-+ self.assertEqual(util.normpath(header_outputs[0].GetFilename()),
-+ util.normpath('header/dir/chrome_android_strings.h'))
-+
-+ id_rc = [x for x in rc_outputs if x.GetLanguage() == 'id']
-+ id_xml = [x for x in xml_outputs if x.GetLanguage() == 'id']
-+ self.assertTrue(id_rc)
-+ self.assertTrue(id_xml)
-+ self.assertEqual(util.normpath(id_rc[0].GetFilename()),
-+ util.normpath('rc/dir/chrome_android_strings_id.rc'))
-+ self.assertEqual(util.normpath(id_xml[0].GetFilename()),
-+ util.normpath('xml/dir/values-in/strings.xml'))
-+
-+ us_rc = [x for x in rc_outputs if x.GetLanguage() == 'en-US']
-+ us_xml = [x for x in xml_outputs if x.GetLanguage() == 'en-US']
-+ self.assertTrue(us_rc)
-+ self.assertTrue(us_xml)
-+ self.assertEqual(util.normpath(us_rc[0].GetFilename()),
-+ util.normpath('rc/dir/chrome_android_strings_en-US.rc'))
-+ self.assertEqual(util.normpath(us_xml[0].GetFilename()),
-+ util.normpath('xml/dir/values-en-rUS/strings.xml'))
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
-new file mode 100644
-index 0000000000..204592bf0d
---- /dev/null
-+++ b/tools/grit/grit/tool/build.py
-@@ -0,0 +1,556 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The 'grit build' tool.
-+'''
-+
-+from __future__ import print_function
-+
-+import codecs
-+import filecmp
-+import getopt
-+import gzip
-+import os
-+import shutil
-+import sys
-+
-+import six
-+
-+from grit import grd_reader
-+from grit import shortcuts
-+from grit import util
-+from grit.format import minifier
-+from grit.node import brotli_util
-+from grit.node import include
-+from grit.node import message
-+from grit.node import structure
-+from grit.tool import interface
-+
-+
-+# It would be cleaner to have each module register itself, but that would
-+# require importing all of them on every run of GRIT.
-+'''Map from <output> node types to modules under grit.format.'''
-+_format_modules = {
-+ 'android': 'android_xml',
-+ 'c_format': 'c_format',
-+ 'chrome_messages_json': 'chrome_messages_json',
-+ 'chrome_messages_json_gzip': 'chrome_messages_json',
-+ 'data_package': 'data_pack',
-+ 'policy_templates': 'policy_templates_json',
-+ 'rc_all': 'rc',
-+ 'rc_header': 'rc_header',
-+ 'rc_nontranslateable': 'rc',
-+ 'rc_translateable': 'rc',
-+ 'resource_file_map_source': 'resource_map',
-+ 'resource_map_header': 'resource_map',
-+ 'resource_map_source': 'resource_map',
-+}
-+
-+def GetFormatter(type):
-+ modulename = 'grit.format.' + _format_modules[type]
-+ __import__(modulename)
-+ module = sys.modules[modulename]
-+ try:
-+ return module.Format
-+ except AttributeError:
-+ return module.GetFormatter(type)
-+
-+
-+class RcBuilder(interface.Tool):
-+ '''A tool that builds RC files and resource header files for compilation.
-+
-+Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]*
-+
-+All output options for this tool are specified in the input file (see
-+'grit help' for details on how to specify the input file - it is a global
-+option).
-+
-+Options:
-+
-+ -a FILE Assert that the given file is an output. There can be
-+ multiple "-a" flags listed for multiple outputs. If a "-a"
-+ or "--assert-file-list" argument is present, then the list
-+ of asserted files must match the output files or the tool
-+ will fail. The use-case is for the build system to maintain
-+ separate lists of output files and to catch errors if the
-+ build system's list and the grit list are out-of-sync.
-+
-+ --assert-file-list Provide a file listing multiple asserted output files.
-+ There is one file name per line. This acts like specifying
-+ each file with "-a" on the command line, but without the
-+ possibility of running into OS line-length limits for very
-+ long lists.
-+
-+ -o OUTPUTDIR Specify what directory output paths are relative to.
-+ Defaults to the current directory.
-+
-+ -p FILE Specify a file containing a pre-determined mapping from
-+ resource names to resource ids which will be used to assign
-+ resource ids to those resources. Resources not found in this
-+ file will be assigned ids normally. The motivation is to run
-+ your app's startup and have it dump the resources it loads,
-+ and then pass these via this flag. This will pack startup
-+ resources together, thus reducing paging while all other
-+ resources are unperturbed. The file should have the format:
-+ RESOURCE_ONE_NAME 123
-+ RESOURCE_TWO_NAME 124
-+
-+ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
-+ value VAL (defaults to 1) which will be used to control
-+ conditional inclusion of resources.
-+
-+ -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
-+
-+ -f FIRSTIDSFILE Path to a python file that specifies the first id of
-+ value to use for resources. A non-empty value here will
-+ override the value specified in the <grit> node's
-+ first_ids_file.
-+
-+ -w WHITELISTFILE Path to a file containing the string names of the
-+ resources to include. Anything not listed is dropped.
-+
-+ -t PLATFORM Specifies the platform the build is targeting; defaults
-+ to the value of sys.platform. The value provided via this
-+ flag should match what sys.platform would report for your
-+ target platform; see grit.node.base.EvaluateCondition.
-+
-+ --whitelist-support
-+ Generate code to support extracting a resource whitelist
-+ from executables.
-+
-+ --write-only-new flag
-+ If flag is non-0, write output files to a temporary file
-+ first, and copy it to the real output only if the new file
-+ is different from the old file. This allows some build
-+ systems to realize that dependent build steps might be
-+ unnecessary, at the cost of comparing the output data at
-+ grit time.
-+
-+ --depend-on-stamp
-+ If specified along with --depfile and --depdir, the depfile
-+ generated will depend on a stampfile instead of the first
-+ output in the input .grd file.
-+
-+ --js-minifier A command to run the Javascript minifier. If not set then
-+ Javascript won't be minified. The command should read the
-+ original Javascript from standard input, and output the
-+ minified Javascript to standard output. A non-zero exit
-+ status will be taken as indicating failure.
-+
-+ --css-minifier A command to run the CSS minifier. If not set then CSS won't
-+ be minified. The command should read the original CSS from
-+ standard input, and output the minified CSS to standard
-+ output. A non-zero exit status will be taken as indicating
-+ failure.
-+
-+ --brotli The full path to the brotli executable generated by
-+ third_party/brotli/BUILD.gn, required if any entries use
-+ compress="brotli".
-+
-+Conditional inclusion of resources only affects the output of files which
-+control which resources get linked into a binary, e.g. it affects .rc files
-+meant for compilation but it does not affect resource header files (that define
-+IDs). This helps ensure that values of IDs stay the same, that all messages
-+are exported to translation interchange files (e.g. XMB files), etc.
-+'''
-+
-+ def ShortDescription(self):
-+ return 'A tool that builds RC files for compilation.'
-+
-+ def Run(self, opts, args):
-+ brotli_util.SetBrotliCommand(None)
-+ os.environ['cwd'] = os.getcwd()
-+ self.output_directory = '.'
-+ first_ids_file = None
-+ predetermined_ids_file = None
-+ whitelist_filenames = []
-+ assert_output_files = []
-+ target_platform = None
-+ depfile = None
-+ depdir = None
-+ whitelist_support = False
-+ write_only_new = False
-+ depend_on_stamp = False
-+ js_minifier = None
-+ css_minifier = None
-+ replace_ellipsis = True
-+ (own_opts, args) = getopt.getopt(
-+ args, 'a:p:o:D:E:f:w:t:',
-+ ('depdir=', 'depfile=', 'assert-file-list=', 'help',
-+ 'output-all-resource-defines', 'no-output-all-resource-defines',
-+ 'no-replace-ellipsis', 'depend-on-stamp', 'js-minifier=',
-+ 'css-minifier=', 'write-only-new=', 'whitelist-support', 'brotli='))
-+ for (key, val) in own_opts:
-+ if key == '-a':
-+ assert_output_files.append(val)
-+ elif key == '--assert-file-list':
-+ with open(val) as f:
-+ assert_output_files += f.read().splitlines()
-+ elif key == '-o':
-+ self.output_directory = val
-+ elif key == '-D':
-+ name, val = util.ParseDefine(val)
-+ self.defines[name] = val
-+ elif key == '-E':
-+ (env_name, env_value) = val.split('=', 1)
-+ os.environ[env_name] = env_value
-+ elif key == '-f':
-+ # TODO(joi@chromium.org): Remove this override once change
-+ # lands in WebKit.grd to specify the first_ids_file in the
-+ # .grd itself.
-+ first_ids_file = val
-+ elif key == '-w':
-+ whitelist_filenames.append(val)
-+ elif key == '--no-replace-ellipsis':
-+ replace_ellipsis = False
-+ elif key == '-p':
-+ predetermined_ids_file = val
-+ elif key == '-t':
-+ target_platform = val
-+ elif key == '--depdir':
-+ depdir = val
-+ elif key == '--depfile':
-+ depfile = val
-+ elif key == '--write-only-new':
-+ write_only_new = val != '0'
-+ elif key == '--depend-on-stamp':
-+ depend_on_stamp = True
-+ elif key == '--js-minifier':
-+ js_minifier = val
-+ elif key == '--css-minifier':
-+ css_minifier = val
-+ elif key == '--whitelist-support':
-+ whitelist_support = True
-+ elif key == '--brotli':
-+ brotli_util.SetBrotliCommand([os.path.abspath(val)])
-+ elif key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+
-+ if len(args):
-+ print('This tool takes no tool-specific arguments.')
-+ return 2
-+ self.SetOptions(opts)
-+ self.VerboseOut('Output directory: %s (absolute path: %s)\n' %
-+ (self.output_directory,
-+ os.path.abspath(self.output_directory)))
-+
-+ if whitelist_filenames:
-+ self.whitelist_names = set()
-+ for whitelist_filename in whitelist_filenames:
-+ self.VerboseOut('Using whitelist: %s\n' % whitelist_filename);
-+ whitelist_contents = util.ReadFile(whitelist_filename, 'utf-8')
-+ self.whitelist_names.update(whitelist_contents.strip().split('\n'))
-+
-+ if js_minifier:
-+ minifier.SetJsMinifier(js_minifier)
-+
-+ if css_minifier:
-+ minifier.SetCssMinifier(css_minifier)
-+
-+ self.write_only_new = write_only_new
-+
-+ self.res = grd_reader.Parse(opts.input,
-+ debug=opts.extra_verbose,
-+ first_ids_file=first_ids_file,
-+ predetermined_ids_file=predetermined_ids_file,
-+ defines=self.defines,
-+ target_platform=target_platform)
-+
-+ # Set an output context so that conditionals can use defines during the
-+ # gathering stage; we use a dummy language here since we are not outputting
-+ # a specific language.
-+ self.res.SetOutputLanguage('en')
-+ self.res.SetWhitelistSupportEnabled(whitelist_support)
-+ self.res.RunGatherers()
-+
-+ # Replace ... with the single-character version. http://crbug.com/621772
-+ if replace_ellipsis:
-+ for node in self.res:
-+ if isinstance(node, message.MessageNode):
-+ node.SetReplaceEllipsis(True)
-+
-+ self.Process()
-+
-+ if assert_output_files:
-+ if not self.CheckAssertedOutputFiles(assert_output_files):
-+ return 2
-+
-+ if depfile and depdir:
-+ self.GenerateDepfile(depfile, depdir, first_ids_file, depend_on_stamp)
-+
-+ return 0
-+
-+ def __init__(self, defines=None):
-+ # Default file-creation function is codecs.open(). Only done to allow
-+ # overriding by unit test.
-+ self.fo_create = codecs.open
-+
-+ # key/value pairs of C-preprocessor like defines that are used for
-+ # conditional output of resources
-+ self.defines = defines or {}
-+
-+ # self.res is a fully-populated resource tree if Run()
-+ # has been called, otherwise None.
-+ self.res = None
-+
-+ # The set of names that are whitelisted to actually be included in the
-+ # output.
-+ self.whitelist_names = None
-+
-+ # Whether to compare outputs to their old contents before writing.
-+ self.write_only_new = False
-+
-+ @staticmethod
-+ def AddWhitelistTags(start_node, whitelist_names):
-+ # Walk the tree of nodes added attributes for the nodes that shouldn't
-+ # be written into the target files (skip markers).
-+ for node in start_node:
-+ # Same trick data_pack.py uses to see what nodes actually result in
-+ # real items.
-+ if (isinstance(node, include.IncludeNode) or
-+ isinstance(node, message.MessageNode) or
-+ isinstance(node, structure.StructureNode)):
-+ text_ids = node.GetTextualIds()
-+ # Mark the item to be skipped if it wasn't in the whitelist.
-+ if text_ids and text_ids[0] not in whitelist_names:
-+ node.SetWhitelistMarkedAsSkip(True)
-+
-+ @staticmethod
-+ def ProcessNode(node, output_node, outfile):
-+ '''Processes a node in-order, calling its formatter before and after
-+ recursing to its children.
-+
-+ Args:
-+ node: grit.node.base.Node subclass
-+ output_node: grit.node.io.OutputNode
-+ outfile: open filehandle
-+ '''
-+ base_dir = util.dirname(output_node.GetOutputFilename())
-+
-+ formatter = GetFormatter(output_node.GetType())
-+ formatted = formatter(node, output_node.GetLanguage(), output_dir=base_dir)
-+ # NB: Formatters may be generators or return lists. The writelines API
-+ # accepts iterables as a shortcut to calling write directly. That means
-+ # you can pass strings (iteration yields characters), but not bytes (as
-+ # iteration yields integers). Python 2 worked due to its quirks with
-+ # bytes/string implementation, but Python 3 fails. It's also a bit more
-+ # inefficient to call write once per character/byte. Handle all of this
-+ # ourselves by calling write directly on strings/bytes before falling back
-+ # to writelines.
-+ if isinstance(formatted, (six.string_types, six.binary_type)):
-+ outfile.write(formatted)
-+ else:
-+ outfile.writelines(formatted)
-+ if output_node.GetType() == 'data_package':
-+ with open(output_node.GetOutputFilename() + '.info', 'w') as infofile:
-+ if node.info:
-+ # We terminate with a newline so that when these files are
-+ # concatenated later we consistently terminate with a newline so
-+ # consumers can account for terminating newlines.
-+ infofile.writelines(['\n'.join(node.info), '\n'])
-+
-+ @staticmethod
-+ def _EncodingForOutputType(output_type):
-+ # Microsoft's RC compiler can only deal with single-byte or double-byte
-+ # files (no UTF-8), so we make all RC files UTF-16 to support all
-+ # character sets.
-+ if output_type in ('rc_header', 'resource_file_map_source',
-+ 'resource_map_header', 'resource_map_source'):
-+ return 'cp1252'
-+ if output_type in ('android', 'c_format', 'plist', 'plist_strings', 'doc',
-+ 'json', 'android_policy', 'chrome_messages_json',
-+ 'chrome_messages_json_gzip', 'policy_templates'):
-+ return 'utf_8'
-+ # TODO(gfeher) modify here to set utf-8 encoding for admx/adml
-+ return 'utf_16'
-+
-+ def Process(self):
-+ for output in self.res.GetOutputFiles():
-+ output.output_filename = os.path.abspath(os.path.join(
-+ self.output_directory, output.GetOutputFilename()))
-+
-+ # If there are whitelisted names, tag the tree once up front, this way
-+ # while looping through the actual output, it is just an attribute check.
-+ if self.whitelist_names:
-+ self.AddWhitelistTags(self.res, self.whitelist_names)
-+
-+ for output in self.res.GetOutputFiles():
-+ self.VerboseOut('Creating %s...' % output.GetOutputFilename())
-+
-+ # Set the context, for conditional inclusion of resources
-+ self.res.SetOutputLanguage(output.GetLanguage())
-+ self.res.SetOutputContext(output.GetContext())
-+ self.res.SetFallbackToDefaultLayout(output.GetFallbackToDefaultLayout())
-+ self.res.SetDefines(self.defines)
-+
-+ # Assign IDs only once to ensure that all outputs use the same IDs.
-+ if self.res.GetIdMap() is None:
-+ self.res.InitializeIds()
-+
-+ # Make the output directory if it doesn't exist.
-+ self.MakeDirectoriesTo(output.GetOutputFilename())
-+
-+ # Write the results to a temporary file and only overwrite the original
-+ # if the file changed. This avoids unnecessary rebuilds.
-+ out_filename = output.GetOutputFilename()
-+ tmp_filename = out_filename + '.tmp'
-+ tmpfile = self.fo_create(tmp_filename, 'wb')
-+
-+ output_type = output.GetType()
-+ if output_type != 'data_package':
-+ encoding = self._EncodingForOutputType(output_type)
-+ tmpfile = util.WrapOutputStream(tmpfile, encoding)
-+
-+ # Iterate in-order through entire resource tree, calling formatters on
-+ # the entry into a node and on exit out of it.
-+ with tmpfile:
-+ self.ProcessNode(self.res, output, tmpfile)
-+
-+ if output_type == 'chrome_messages_json_gzip':
-+ gz_filename = tmp_filename + '.gz'
-+ with open(tmp_filename, 'rb') as tmpfile, open(gz_filename, 'wb') as f:
-+ with gzip.GzipFile(filename='', mode='wb', fileobj=f, mtime=0) as fgz:
-+ shutil.copyfileobj(tmpfile, fgz)
-+ os.remove(tmp_filename)
-+ tmp_filename = gz_filename
-+
-+ # Now copy from the temp file back to the real output, but on Windows,
-+ # only if the real output doesn't exist or the contents of the file
-+ # changed. This prevents identical headers from being written and .cc
-+ # files from recompiling (which is painful on Windows).
-+ if not os.path.exists(out_filename):
-+ os.rename(tmp_filename, out_filename)
-+ else:
-+ # CHROMIUM SPECIFIC CHANGE.
-+ # This clashes with gyp + vstudio, which expect the output timestamp
-+ # to change on a rebuild, even if nothing has changed, so only do
-+ # it when opted in.
-+ if not self.write_only_new:
-+ write_file = True
-+ else:
-+ files_match = filecmp.cmp(out_filename, tmp_filename)
-+ write_file = not files_match
-+ if write_file:
-+ shutil.copy2(tmp_filename, out_filename)
-+ os.remove(tmp_filename)
-+
-+ self.VerboseOut(' done.\n')
-+
-+ # Print warnings if there are any duplicate shortcuts.
-+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(
-+ self.res.UberClique(), self.res.GetTcProject())
-+ if warnings:
-+ print('\n'.join(warnings))
-+
-+ # Print out any fallback warnings, and missing translation errors, and
-+ # exit with an error code if there are missing translations in a non-pseudo
-+ # and non-official build.
-+ warnings = (self.res.UberClique().MissingTranslationsReport().
-+ encode('ascii', 'replace'))
-+ if warnings:
-+ self.VerboseOut(warnings)
-+ if self.res.UberClique().HasMissingTranslations():
-+ print(self.res.UberClique().missing_translations_)
-+ sys.exit(-1)
-+
-+
-+ def CheckAssertedOutputFiles(self, assert_output_files):
-+ '''Checks that the asserted output files are specified in the given list.
-+
-+ Returns true if the asserted files are present. If they are not, returns
-+ False and prints the failure.
-+ '''
-+ # Compare the absolute path names, sorted.
-+ asserted = sorted([os.path.abspath(i) for i in assert_output_files])
-+ actual = sorted([
-+ os.path.abspath(os.path.join(self.output_directory,
-+ i.GetOutputFilename()))
-+ for i in self.res.GetOutputFiles()])
-+
-+ if asserted != actual:
-+ missing = list(set(asserted) - set(actual))
-+ extra = list(set(actual) - set(asserted))
-+ error = '''Asserted file list does not match.
-+
-+Expected output files:
-+%s
-+Actual output files:
-+%s
-+Missing output files:
-+%s
-+Extra output files:
-+%s
-+'''
-+ print(error % ('\n'.join(asserted), '\n'.join(actual), '\n'.join(missing),
-+ ' \n'.join(extra)))
-+ return False
-+ return True
-+
-+
-+ def GenerateDepfile(self, depfile, depdir, first_ids_file, depend_on_stamp):
-+ '''Generate a depfile that contains the imlicit dependencies of the input
-+ grd. The depfile will be in the same format as a makefile, and will contain
-+ references to files relative to |depdir|. It will be put in |depfile|.
-+
-+ For example, supposing we have three files in a directory src/
-+
-+ src/
-+ blah.grd <- depends on input{1,2}.xtb
-+ input1.xtb
-+ input2.xtb
-+
-+ and we run
-+
-+ grit -i blah.grd -o ../out/gen \
-+ --depdir ../out \
-+ --depfile ../out/gen/blah.rd.d
-+
-+ from the directory src/ we will generate a depfile ../out/gen/blah.grd.d
-+ that has the contents
-+
-+ gen/blah.h: ../src/input1.xtb ../src/input2.xtb
-+
-+ Where "gen/blah.h" is the first output (Ninja expects the .d file to list
-+ the first output in cases where there is more than one). If the flag
-+ --depend-on-stamp is specified, "gen/blah.rd.d.stamp" will be used that is
-+ 'touched' whenever a new depfile is generated.
-+
-+ Note that all paths in the depfile are relative to ../out, the depdir.
-+ '''
-+ depfile = os.path.abspath(depfile)
-+ depdir = os.path.abspath(depdir)
-+ infiles = self.res.GetInputFiles()
-+
-+ # We want to trigger a rebuild if the first ids change.
-+ if first_ids_file is not None:
-+ infiles.append(first_ids_file)
-+
-+ if (depend_on_stamp):
-+ output_file = depfile + ".stamp"
-+ # Touch the stamp file before generating the depfile.
-+ with open(output_file, 'a'):
-+ os.utime(output_file, None)
-+ else:
-+ # Get the first output file relative to the depdir.
-+ outputs = self.res.GetOutputFiles()
-+ output_file = os.path.join(self.output_directory,
-+ outputs[0].GetOutputFilename())
-+
-+ output_file = os.path.relpath(output_file, depdir)
-+ # The path prefix to prepend to dependencies in the depfile.
-+ prefix = os.path.relpath(os.getcwd(), depdir)
-+ deps_text = ' '.join([os.path.join(prefix, i) for i in infiles])
-+
-+ depfile_contents = output_file + ': ' + deps_text
-+ self.MakeDirectoriesTo(depfile)
-+ outfile = self.fo_create(depfile, 'w', encoding='utf-8')
-+ outfile.write(depfile_contents)
-+
-+ @staticmethod
-+ def MakeDirectoriesTo(file):
-+ '''Creates directories necessary to contain |file|.'''
-+ dir = os.path.split(file)[0]
-+ if not os.path.exists(dir):
-+ os.makedirs(dir)
-diff --git a/tools/grit/grit/tool/build_unittest.py b/tools/grit/grit/tool/build_unittest.py
-new file mode 100644
-index 0000000000..c4a2f2752b
---- /dev/null
-+++ b/tools/grit/grit/tool/build_unittest.py
-@@ -0,0 +1,341 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for the 'grit build' tool.
-+'''
-+
-+from __future__ import print_function
-+
-+import codecs
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit import util
-+from grit.tool import build
-+
-+
-+class BuildUnittest(unittest.TestCase):
-+
-+ # IDs should not change based on whitelisting.
-+ # Android WebView currently relies on this.
-+ EXPECTED_ID_MAP = {
-+ 'IDS_MESSAGE_WHITELISTED': 6889,
-+ 'IDR_STRUCTURE_WHITELISTED': 11546,
-+ 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED': 11548,
-+ 'IDR_INCLUDE_WHITELISTED': 15601,
-+ }
-+
-+ def testFindTranslationsWithSubstitutions(self):
-+ # This is a regression test; we had a bug where GRIT would fail to find
-+ # messages with substitutions e.g. "Hello [IDS_USER]" where IDS_USER is
-+ # another <message>.
-+ output_dir = util.TempDir({})
-+ builder = build.RcBuilder()
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+ builder.Run(DummyOpts(), ['-o', output_dir.GetPath()])
-+ output_dir.CleanUp()
-+
-+ def testGenerateDepFile(self):
-+ output_dir = util.TempDir({})
-+ builder = build.RcBuilder()
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/depfile.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+ expected_dep_file = output_dir.GetPath('substitute.grd.d')
-+ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
-+ '--depdir', output_dir.GetPath(),
-+ '--depfile', expected_dep_file])
-+
-+ self.failUnless(os.path.isfile(expected_dep_file))
-+ with open(expected_dep_file) as f:
-+ line = f.readline()
-+ (dep_output_file, deps_string) = line.split(': ')
-+ deps = deps_string.split(' ')
-+
-+ self.failUnlessEqual("default_100_percent.pak", dep_output_file)
-+ self.failUnlessEqual(deps, [
-+ util.PathFromRoot('grit/testdata/default_100_percent/a.png'),
-+ util.PathFromRoot('grit/testdata/grit_part.grdp'),
-+ util.PathFromRoot('grit/testdata/special_100_percent/a.png'),
-+ ])
-+ output_dir.CleanUp()
-+
-+ def testGenerateDepFileWithResourceIds(self):
-+ output_dir = util.TempDir({})
-+ builder = build.RcBuilder()
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/substitute_no_ids.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+ expected_dep_file = output_dir.GetPath('substitute_no_ids.grd.d')
-+ builder.Run(DummyOpts(),
-+ ['-f', util.PathFromRoot('grit/testdata/resource_ids'),
-+ '-o', output_dir.GetPath(),
-+ '--depdir', output_dir.GetPath(),
-+ '--depfile', expected_dep_file])
-+
-+ self.failUnless(os.path.isfile(expected_dep_file))
-+ with open(expected_dep_file) as f:
-+ line = f.readline()
-+ (dep_output_file, deps_string) = line.split(': ')
-+ deps = deps_string.split(' ')
-+
-+ self.failUnlessEqual("resource.h", dep_output_file)
-+ self.failUnlessEqual(2, len(deps))
-+ self.failUnlessEqual(deps[0],
-+ util.PathFromRoot('grit/testdata/substitute.xmb'))
-+ self.failUnlessEqual(deps[1],
-+ util.PathFromRoot('grit/testdata/resource_ids'))
-+ output_dir.CleanUp()
-+
-+ def testAssertOutputs(self):
-+ output_dir = util.TempDir({})
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+
-+ # Incomplete output file list should fail.
-+ builder_fail = build.RcBuilder()
-+ self.failUnlessEqual(2,
-+ builder_fail.Run(DummyOpts(), [
-+ '-o', output_dir.GetPath(),
-+ '-a', os.path.abspath(
-+ output_dir.GetPath('en_generated_resources.rc'))]))
-+
-+ # Complete output file list should succeed.
-+ builder_ok = build.RcBuilder()
-+ self.failUnlessEqual(0,
-+ builder_ok.Run(DummyOpts(), [
-+ '-o', output_dir.GetPath(),
-+ '-a', os.path.abspath(
-+ output_dir.GetPath('en_generated_resources.rc')),
-+ '-a', os.path.abspath(
-+ output_dir.GetPath('sv_generated_resources.rc')),
-+ '-a', os.path.abspath(output_dir.GetPath('resource.h'))]))
-+ output_dir.CleanUp()
-+
-+ def testAssertTemplateOutputs(self):
-+ output_dir = util.TempDir({})
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/substitute_tmpl.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+
-+ # Incomplete output file list should fail.
-+ builder_fail = build.RcBuilder()
-+ self.failUnlessEqual(2,
-+ builder_fail.Run(DummyOpts(), [
-+ '-o', output_dir.GetPath(),
-+ '-E', 'name=foo',
-+ '-a', os.path.abspath(output_dir.GetPath('en_foo_resources.rc'))]))
-+
-+ # Complete output file list should succeed.
-+ builder_ok = build.RcBuilder()
-+ self.failUnlessEqual(0,
-+ builder_ok.Run(DummyOpts(), [
-+ '-o', output_dir.GetPath(),
-+ '-E', 'name=foo',
-+ '-a', os.path.abspath(output_dir.GetPath('en_foo_resources.rc')),
-+ '-a', os.path.abspath(output_dir.GetPath('sv_foo_resources.rc')),
-+ '-a', os.path.abspath(output_dir.GetPath('resource.h'))]))
-+ output_dir.CleanUp()
-+
-+ def _verifyWhitelistedOutput(self,
-+ filename,
-+ whitelisted_ids,
-+ non_whitelisted_ids,
-+ encoding='utf8'):
-+ self.failUnless(os.path.exists(filename))
-+ whitelisted_ids_found = []
-+ non_whitelisted_ids_found = []
-+ with codecs.open(filename, encoding=encoding) as f:
-+ for line in f.readlines():
-+ for whitelisted_id in whitelisted_ids:
-+ if whitelisted_id in line:
-+ whitelisted_ids_found.append(whitelisted_id)
-+ if filename.endswith('.h'):
-+ numeric_id = int(line.split()[2])
-+ expected_numeric_id = self.EXPECTED_ID_MAP.get(whitelisted_id)
-+ self.assertEqual(
-+ expected_numeric_id, numeric_id,
-+ 'Numeric ID for {} was {} should be {}'.format(
-+ whitelisted_id, numeric_id, expected_numeric_id))
-+ for non_whitelisted_id in non_whitelisted_ids:
-+ if non_whitelisted_id in line:
-+ non_whitelisted_ids_found.append(non_whitelisted_id)
-+ self.longMessage = True
-+ self.assertEqual(whitelisted_ids,
-+ whitelisted_ids_found,
-+ '\nin file {}'.format(os.path.basename(filename)))
-+ non_whitelisted_msg = ('Non-Whitelisted IDs {} found in {}'
-+ .format(non_whitelisted_ids_found, os.path.basename(filename)))
-+ self.assertFalse(non_whitelisted_ids_found, non_whitelisted_msg)
-+
-+ def testWhitelistStrings(self):
-+ output_dir = util.TempDir({})
-+ builder = build.RcBuilder()
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/whitelist_strings.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+ whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt')
-+ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
-+ '-w', whitelist_file])
-+ header = output_dir.GetPath('whitelist_test_resources.h')
-+ rc = output_dir.GetPath('en_whitelist_test_strings.rc')
-+
-+ whitelisted_ids = ['IDS_MESSAGE_WHITELISTED']
-+ non_whitelisted_ids = ['IDS_MESSAGE_NOT_WHITELISTED']
-+ self._verifyWhitelistedOutput(
-+ header,
-+ whitelisted_ids,
-+ non_whitelisted_ids,
-+ )
-+ self._verifyWhitelistedOutput(
-+ rc,
-+ whitelisted_ids,
-+ non_whitelisted_ids,
-+ encoding='utf16'
-+ )
-+ output_dir.CleanUp()
-+
-+ def testWhitelistResources(self):
-+ output_dir = util.TempDir({})
-+ builder = build.RcBuilder()
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/whitelist_resources.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+ whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt')
-+ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
-+ '-w', whitelist_file])
-+ header = output_dir.GetPath('whitelist_test_resources.h')
-+ map_cc = output_dir.GetPath('whitelist_test_resources_map.cc')
-+ map_h = output_dir.GetPath('whitelist_test_resources_map.h')
-+ pak = output_dir.GetPath('whitelist_test_resources.pak')
-+
-+ # Ensure the resource map header and .pak files exist, but don't verify
-+ # their content.
-+ self.failUnless(os.path.exists(map_h))
-+ self.failUnless(os.path.exists(pak))
-+
-+ whitelisted_ids = [
-+ 'IDR_STRUCTURE_WHITELISTED',
-+ 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED',
-+ 'IDR_INCLUDE_WHITELISTED',
-+ ]
-+ non_whitelisted_ids = [
-+ 'IDR_STRUCTURE_NOT_WHITELISTED',
-+ 'IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED',
-+ 'IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED',
-+ 'IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED',
-+ 'IDR_INCLUDE_NOT_WHITELISTED',
-+ ]
-+ for output_file in (header, map_cc):
-+ self._verifyWhitelistedOutput(
-+ output_file,
-+ whitelisted_ids,
-+ non_whitelisted_ids,
-+ )
-+ output_dir.CleanUp()
-+
-+ def testWriteOnlyNew(self):
-+ output_dir = util.TempDir({})
-+ builder = build.RcBuilder()
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+ UNCHANGED = 10
-+ header = output_dir.GetPath('resource.h')
-+
-+ builder.Run(DummyOpts(), ['-o', output_dir.GetPath()])
-+ self.failUnless(os.path.exists(header))
-+ first_mtime = os.stat(header).st_mtime
-+
-+ os.utime(header, (UNCHANGED, UNCHANGED))
-+ builder.Run(DummyOpts(),
-+ ['-o', output_dir.GetPath(), '--write-only-new', '0'])
-+ self.failUnless(os.path.exists(header))
-+ second_mtime = os.stat(header).st_mtime
-+
-+ os.utime(header, (UNCHANGED, UNCHANGED))
-+ builder.Run(DummyOpts(),
-+ ['-o', output_dir.GetPath(), '--write-only-new', '1'])
-+ self.failUnless(os.path.exists(header))
-+ third_mtime = os.stat(header).st_mtime
-+
-+ self.assertTrue(abs(second_mtime - UNCHANGED) > 5)
-+ self.assertTrue(abs(third_mtime - UNCHANGED) < 5)
-+ output_dir.CleanUp()
-+
-+ def testGenerateDepFileWithDependOnStamp(self):
-+ output_dir = util.TempDir({})
-+ builder = build.RcBuilder()
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
-+ self.verbose = False
-+ self.extra_verbose = False
-+ expected_dep_file_name = 'substitute.grd.d'
-+ expected_stamp_file_name = expected_dep_file_name + '.stamp'
-+ expected_dep_file = output_dir.GetPath(expected_dep_file_name)
-+ expected_stamp_file = output_dir.GetPath(expected_stamp_file_name)
-+ if os.path.isfile(expected_stamp_file):
-+ os.remove(expected_stamp_file)
-+ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
-+ '--depdir', output_dir.GetPath(),
-+ '--depfile', expected_dep_file,
-+ '--depend-on-stamp'])
-+ self.failUnless(os.path.isfile(expected_stamp_file))
-+ first_mtime = os.stat(expected_stamp_file).st_mtime
-+
-+ # Reset mtime to very old.
-+ OLDTIME = 10
-+ os.utime(expected_stamp_file, (OLDTIME, OLDTIME))
-+
-+ builder.Run(DummyOpts(), ['-o', output_dir.GetPath(),
-+ '--depdir', output_dir.GetPath(),
-+ '--depfile', expected_dep_file,
-+ '--depend-on-stamp'])
-+ self.failUnless(os.path.isfile(expected_stamp_file))
-+ second_mtime = os.stat(expected_stamp_file).st_mtime
-+
-+ # Some OS have a 2s stat resolution window, so can't do a direct comparison.
-+ self.assertTrue((second_mtime - OLDTIME) > 5)
-+ self.assertTrue(abs(second_mtime - first_mtime) < 5)
-+
-+ self.failUnless(os.path.isfile(expected_dep_file))
-+ with open(expected_dep_file) as f:
-+ line = f.readline()
-+ (dep_output_file, deps_string) = line.split(': ')
-+ deps = deps_string.split(' ')
-+
-+ self.failUnlessEqual(expected_stamp_file_name, dep_output_file)
-+ self.failUnlessEqual(deps, [
-+ util.PathFromRoot('grit/testdata/substitute.xmb'),
-+ ])
-+ output_dir.CleanUp()
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/buildinfo.py b/tools/grit/grit/tool/buildinfo.py
-new file mode 100644
-index 0000000000..7f8d1a3b04
---- /dev/null
-+++ b/tools/grit/grit/tool/buildinfo.py
-@@ -0,0 +1,78 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Output the list of files to be generated by GRIT from an input.
-+"""
-+
-+from __future__ import print_function
-+
-+import getopt
-+import os
-+import sys
-+
-+from grit import grd_reader
-+from grit.node import structure
-+from grit.tool import interface
-+
-+class DetermineBuildInfo(interface.Tool):
-+ """Determine what files will be read and output by GRIT.
-+Outputs the list of generated files and inputs used to stdout.
-+
-+Usage: grit buildinfo [-o DIR]
-+
-+The output directory is used for display only.
-+"""
-+
-+ def __init__(self):
-+ pass
-+
-+ def ShortDescription(self):
-+ """Describes this tool for the usage message."""
-+ return ('Determine what files will be needed and\n'
-+ 'output by GRIT with a given input.')
-+
-+ def Run(self, opts, args):
-+ """Main method for the buildinfo tool."""
-+ self.output_directory = '.'
-+ (own_opts, args) = getopt.getopt(args, 'o:', ('help',))
-+ for (key, val) in own_opts:
-+ if key == '-o':
-+ self.output_directory = val
-+ elif key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+ if len(args) > 0:
-+ print('This tool takes exactly one argument: the output directory via -o')
-+ return 2
-+ self.SetOptions(opts)
-+
-+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
-+
-+ langs = {}
-+ for output in res_tree.GetOutputFiles():
-+ if output.attrs['lang']:
-+ langs[output.attrs['lang']] = os.path.dirname(output.GetFilename())
-+
-+ for lang, dirname in langs.items():
-+ old_output_language = res_tree.output_language
-+ res_tree.SetOutputLanguage(lang)
-+ for node in res_tree.ActiveDescendants():
-+ with node:
-+ if (isinstance(node, structure.StructureNode) and
-+ node.HasFileForLanguage()):
-+ path = node.FileForLanguage(lang, dirname, create_file=False,
-+ return_if_not_generated=False)
-+ if path:
-+ path = os.path.join(self.output_directory, path)
-+ path = os.path.normpath(path)
-+ print('%s|%s' % ('rc_all', path))
-+ res_tree.SetOutputLanguage(old_output_language)
-+
-+ for output in res_tree.GetOutputFiles():
-+ path = os.path.join(self.output_directory, output.GetFilename())
-+ path = os.path.normpath(path)
-+ print('%s|%s' % (output.GetType(), path))
-+
-+ for infile in res_tree.GetInputFiles():
-+ print('input|%s' % os.path.normpath(infile))
-diff --git a/tools/grit/grit/tool/buildinfo_unittest.py b/tools/grit/grit/tool/buildinfo_unittest.py
-new file mode 100644
-index 0000000000..24e9ddf8d8
---- /dev/null
-+++ b/tools/grit/grit/tool/buildinfo_unittest.py
-@@ -0,0 +1,90 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Unit tests for the 'grit buildinfo' tool.
-+"""
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import unittest
-+
-+# This is needed to find some of the imports below.
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+from six import StringIO
-+
-+# pylint: disable-msg=C6204
-+from grit.tool import buildinfo
-+
-+
-+class BuildInfoUnittest(unittest.TestCase):
-+ def setUp(self):
-+ self.old_cwd = os.getcwd()
-+ # Change CWD to make tests work independently of callers CWD.
-+ os.chdir(os.path.dirname(__file__))
-+ os.chdir('..')
-+ self.buf = StringIO()
-+ self.old_stdout = sys.stdout
-+ sys.stdout = self.buf
-+
-+ def tearDown(self):
-+ sys.stdout = self.old_stdout
-+ os.chdir(self.old_cwd)
-+
-+ def testBuildOutput(self):
-+ """Find all of the inputs and outputs for a GRD file."""
-+ info_object = buildinfo.DetermineBuildInfo()
-+
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = '../grit/testdata/buildinfo.grd'
-+ self.print_header = False
-+ self.verbose = False
-+ self.extra_verbose = False
-+ info_object.Run(DummyOpts(), [])
-+ output = self.buf.getvalue().replace('\\', '/')
-+ self.failUnless(output.count(r'rc_all|sv_sidebar_loading.html'))
-+ self.failUnless(output.count(r'rc_header|resource.h'))
-+ self.failUnless(output.count(r'rc_all|en_generated_resources.rc'))
-+ self.failUnless(output.count(r'rc_all|sv_generated_resources.rc'))
-+ self.failUnless(output.count(r'input|../grit/testdata/substitute.xmb'))
-+ self.failUnless(output.count(r'input|../grit/testdata/pr.bmp'))
-+ self.failUnless(output.count(r'input|../grit/testdata/pr2.bmp'))
-+ self.failUnless(
-+ output.count(r'input|../grit/testdata/sidebar_loading.html'))
-+ self.failUnless(output.count(r'input|../grit/testdata/transl.rc'))
-+ self.failUnless(output.count(r'input|../grit/testdata/transl1.rc'))
-+
-+ def testBuildOutputWithDir(self):
-+ """Find all the inputs and outputs for a GRD file with an output dir."""
-+ info_object = buildinfo.DetermineBuildInfo()
-+
-+ class DummyOpts(object):
-+ def __init__(self):
-+ self.input = '../grit/testdata/buildinfo.grd'
-+ self.print_header = False
-+ self.verbose = False
-+ self.extra_verbose = False
-+ info_object.Run(DummyOpts(), ['-o', '../grit/testdata'])
-+ output = self.buf.getvalue().replace('\\', '/')
-+ self.failUnless(
-+ output.count(r'rc_all|../grit/testdata/sv_sidebar_loading.html'))
-+ self.failUnless(output.count(r'rc_header|../grit/testdata/resource.h'))
-+ self.failUnless(
-+ output.count(r'rc_all|../grit/testdata/en_generated_resources.rc'))
-+ self.failUnless(
-+ output.count(r'rc_all|../grit/testdata/sv_generated_resources.rc'))
-+ self.failUnless(output.count(r'input|../grit/testdata/substitute.xmb'))
-+ self.failUnlessEqual(0,
-+ output.count(r'rc_all|../grit/testdata/sv_welcome_toast.html'))
-+ self.failUnless(
-+ output.count(r'rc_all|../grit/testdata/en_welcome_toast.html'))
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/count.py b/tools/grit/grit/tool/count.py
-new file mode 100644
-index 0000000000..ab37f2ddb3
---- /dev/null
-+++ b/tools/grit/grit/tool/count.py
-@@ -0,0 +1,52 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Count number of occurrences of a given message ID.'''
-+
-+from __future__ import print_function
-+
-+import getopt
-+import sys
-+
-+from grit import grd_reader
-+from grit.tool import interface
-+
-+
-+class CountMessage(interface.Tool):
-+ '''Count the number of times a given message ID is used.'''
-+
-+ def __init__(self):
-+ pass
-+
-+ def ShortDescription(self):
-+ return 'Count the number of times a given message ID is used.'
-+
-+ def ParseOptions(self, args):
-+ """Set this objects and return all non-option arguments."""
-+ own_opts, args = getopt.getopt(args, '', ('help',))
-+ for key, val in own_opts:
-+ if key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+ return args
-+
-+ def Run(self, opts, args):
-+ args = self.ParseOptions(args)
-+ if len(args) != 1:
-+ print('This tool takes a single tool-specific argument, the message '
-+ 'ID to count.')
-+ return 2
-+ self.SetOptions(opts)
-+
-+ id = args[0]
-+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
-+ res_tree.OnlyTheseTranslations([])
-+ res_tree.RunGatherers()
-+
-+ count = 0
-+ for c in res_tree.UberClique().AllCliques():
-+ if c.GetId() == id:
-+ count += 1
-+
-+ print("There are %d occurrences of message %s." % (count, id))
-diff --git a/tools/grit/grit/tool/diff_structures.py b/tools/grit/grit/tool/diff_structures.py
-new file mode 100644
-index 0000000000..d69e009b58
---- /dev/null
-+++ b/tools/grit/grit/tool/diff_structures.py
-@@ -0,0 +1,119 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The 'grit sdiff' tool.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import getopt
-+import sys
-+import tempfile
-+
-+from grit.node import structure
-+from grit.tool import interface
-+
-+from grit import constants
-+from grit import util
-+
-+# Builds the description for the tool (used as the __doc__
-+# for the DiffStructures class).
-+_class_doc = """\
-+Allows you to view the differences in the structure of two files,
-+disregarding their translateable content. Translateable portions of
-+each file are changed to the string "TTTTTT" before invoking the diff program
-+specified by the P4DIFF environment variable.
-+
-+Usage: grit sdiff [-t TYPE] [-s SECTION] [-e ENCODING] LEFT RIGHT
-+
-+LEFT and RIGHT are the files you want to diff. SECTION is required
-+for structure types like 'dialog' to identify the part of the file to look at.
-+ENCODING indicates the encoding of the left and right files (default 'cp1252').
-+TYPE can be one of the following, defaults to 'tr_html':
-+"""
-+for gatherer in structure._GATHERERS:
-+ _class_doc += " - %s\n" % gatherer
-+
-+
-+class DiffStructures(interface.Tool):
-+ __doc__ = _class_doc
-+
-+ def __init__(self):
-+ self.section = None
-+ self.left_encoding = 'cp1252'
-+ self.right_encoding = 'cp1252'
-+ self.structure_type = 'tr_html'
-+
-+ def ShortDescription(self):
-+ return 'View differences without regard for translateable portions.'
-+
-+ def Run(self, global_opts, args):
-+ (opts, args) = getopt.getopt(args, 's:e:t:',
-+ ('help', 'left_encoding=', 'right_encoding='))
-+ for key, val in opts:
-+ if key == '-s':
-+ self.section = val
-+ elif key == '-e':
-+ self.left_encoding = val
-+ self.right_encoding = val
-+ elif key == '-t':
-+ self.structure_type = val
-+ elif key == '--left_encoding':
-+ self.left_encoding = val
-+ elif key == '--right_encoding':
-+ self.right_encoding == val
-+ elif key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+
-+ if len(args) != 2:
-+ print("Incorrect usage - 'grit help sdiff' for usage details.")
-+ return 2
-+
-+ if 'P4DIFF' not in os.environ:
-+ print("Environment variable P4DIFF not set; defaulting to 'windiff'.")
-+ diff_program = 'windiff'
-+ else:
-+ diff_program = os.environ['P4DIFF']
-+
-+ left_trans = self.MakeStaticTranslation(args[0], self.left_encoding)
-+ try:
-+ try:
-+ right_trans = self.MakeStaticTranslation(args[1], self.right_encoding)
-+
-+ os.system('%s %s %s' % (diff_program, left_trans, right_trans))
-+ finally:
-+ os.unlink(right_trans)
-+ finally:
-+ os.unlink(left_trans)
-+
-+ def MakeStaticTranslation(self, original_filename, encoding):
-+ """Given the name of the structure type (self.structure_type), the filename
-+ of the file holding the original structure, and optionally the "section" key
-+ identifying the part of the file to look at (self.section), creates a
-+ temporary file holding a "static" translation of the original structure
-+ (i.e. one where all translateable parts have been replaced with "TTTTTT")
-+ and returns the temporary file name. It is the caller's responsibility to
-+ delete the file when finished.
-+
-+ Args:
-+ original_filename: 'c:\\bingo\\bla.rc'
-+
-+ Return:
-+ 'c:\\temp\\werlkjsdf334.tmp'
-+ """
-+ original = structure._GATHERERS[self.structure_type](original_filename,
-+ extkey=self.section,
-+ encoding=encoding)
-+ original.Parse()
-+ translated = original.Translate(constants.CONSTANT_LANGUAGE, False)
-+
-+ fname = tempfile.mktemp()
-+ with util.WrapOutputStream(open(fname, 'wb')) as writer:
-+ writer.write("Original filename: %s\n=============\n\n"
-+ % original_filename)
-+ writer.write(translated) # write in UTF-8
-+
-+ return fname
-diff --git a/tools/grit/grit/tool/diff_structures_unittest.py b/tools/grit/grit/tool/diff_structures_unittest.py
-new file mode 100644
-index 0000000000..a6d7585761
---- /dev/null
-+++ b/tools/grit/grit/tool/diff_structures_unittest.py
-@@ -0,0 +1,46 @@
-+#!/usr/bin/env python
-+# Copyright 2020 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for the 'grit newgrd' tool.'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit.tool import diff_structures
-+
-+
-+class DummyOpts(object):
-+ """Options needed by NewGrd."""
-+
-+
-+class DiffStructuresUnittest(unittest.TestCase):
-+
-+ def testMissingFiles(self):
-+ """Verify failure w/out file inputs."""
-+ tool = diff_structures.DiffStructures()
-+ ret = tool.Run(DummyOpts(), [])
-+ self.assertIsNotNone(ret)
-+ self.assertGreater(ret, 0)
-+
-+ ret = tool.Run(DummyOpts(), ['left'])
-+ self.assertIsNotNone(ret)
-+ self.assertGreater(ret, 0)
-+
-+ def testTooManyArgs(self):
-+ """Verify failure w/too many inputs."""
-+ tool = diff_structures.DiffStructures()
-+ ret = tool.Run(DummyOpts(), ['a', 'b', 'c'])
-+ self.assertIsNotNone(ret)
-+ self.assertGreater(ret, 0)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/interface.py b/tools/grit/grit/tool/interface.py
-new file mode 100644
-index 0000000000..e923205223
---- /dev/null
-+++ b/tools/grit/grit/tool/interface.py
-@@ -0,0 +1,62 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Base class and interface for tools.
-+'''
-+
-+from __future__ import print_function
-+
-+class Tool(object):
-+ '''Base class for all tools. Tools should use their docstring (i.e. the
-+ class-level docstring) for the help they want to have printed when they
-+ are invoked.'''
-+
-+ #
-+ # Interface (abstract methods)
-+ #
-+
-+ def ShortDescription(self):
-+ '''Returns a short description of the functionality of the tool.'''
-+ raise NotImplementedError()
-+
-+ def Run(self, global_options, my_arguments):
-+ '''Runs the tool.
-+
-+ Args:
-+ global_options: object grit_runner.Options
-+ my_arguments: [arg1 arg2 ...]
-+
-+ Return:
-+ 0 for success, non-0 for error
-+ '''
-+ raise NotImplementedError()
-+
-+ #
-+ # Base class implementation
-+ #
-+
-+ def __init__(self):
-+ self.o = None
-+
-+ def ShowUsage(self):
-+ '''Show usage text for this tool.'''
-+ print(self.__doc__)
-+
-+ def SetOptions(self, opts):
-+ self.o = opts
-+
-+ def Out(self, text):
-+ '''Always writes out 'text'.'''
-+ self.o.output_stream.write(text)
-+
-+ def VerboseOut(self, text):
-+ '''Writes out 'text' if the verbose option is on.'''
-+ if self.o.verbose:
-+ self.o.output_stream.write(text)
-+
-+ def ExtraVerboseOut(self, text):
-+ '''Writes out 'text' if the extra-verbose option is on.
-+ '''
-+ if self.o.extra_verbose:
-+ self.o.output_stream.write(text)
-diff --git a/tools/grit/grit/tool/menu_from_parts.py b/tools/grit/grit/tool/menu_from_parts.py
-new file mode 100644
-index 0000000000..fcec26c5b1
---- /dev/null
-+++ b/tools/grit/grit/tool/menu_from_parts.py
-@@ -0,0 +1,79 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The 'grit menufromparts' tool.'''
-+
-+from __future__ import print_function
-+
-+import six
-+
-+from grit import grd_reader
-+from grit import util
-+from grit import xtb_reader
-+from grit.tool import interface
-+from grit.tool import transl2tc
-+
-+import grit.extern.tclib
-+
-+
-+class MenuTranslationsFromParts(interface.Tool):
-+ '''One-off tool to generate translated menu messages (where each menu is kept
-+in a single message) based on existing translations of the individual menu
-+items. Was needed when changing menus from being one message per menu item
-+to being one message for the whole menu.'''
-+
-+ def ShortDescription(self):
-+ return ('Create translations of whole menus from existing translations of '
-+ 'menu items.')
-+
-+ def Run(self, globopt, args):
-+ self.SetOptions(globopt)
-+ assert len(args) == 2, "Need exactly two arguments, the XTB file and the output file"
-+
-+ xtb_file = args[0]
-+ output_file = args[1]
-+
-+ grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
-+ grd.OnlyTheseTranslations([]) # don't load translations
-+ grd.RunGatherers()
-+
-+ xtb = {}
-+ def Callback(msg_id, parts):
-+ msg = []
-+ for part in parts:
-+ if part[0]:
-+ msg = []
-+ break # it had a placeholder so ignore it
-+ else:
-+ msg.append(part[1])
-+ if len(msg):
-+ xtb[msg_id] = ''.join(msg)
-+ with open(xtb_file, 'rb') as f:
-+ xtb_reader.Parse(f, Callback)
-+
-+ translations = [] # list of translations as per transl2tc.WriteTranslations
-+ for node in grd:
-+ if node.name == 'structure' and node.attrs['type'] == 'menu':
-+ assert len(node.GetCliques()) == 1
-+ message = node.GetCliques()[0].GetMessage()
-+ translation = []
-+
-+ contents = message.GetContent()
-+ for part in contents:
-+ if isinstance(part, six.string_types):
-+ id = grit.extern.tclib.GenerateMessageId(part)
-+ if id not in xtb:
-+ print("WARNING didn't find all translations for menu %s" %
-+ (node.attrs['name'],))
-+ translation = []
-+ break
-+ translation.append(xtb[id])
-+ else:
-+ translation.append(part.GetPresentation())
-+
-+ if len(translation):
-+ translations.append([message.GetId(), ''.join(translation)])
-+
-+ with util.WrapOutputStream(open(output_file, 'wb')) as f:
-+ transl2tc.TranslationToTc.WriteTranslations(f, translations)
-diff --git a/tools/grit/grit/tool/newgrd.py b/tools/grit/grit/tool/newgrd.py
-new file mode 100644
-index 0000000000..66a18e9c04
---- /dev/null
-+++ b/tools/grit/grit/tool/newgrd.py
-@@ -0,0 +1,85 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Tool to create a new, empty .grd file with all the basic sections.
-+'''
-+
-+from __future__ import print_function
-+
-+import getopt
-+import sys
-+
-+from grit.tool import interface
-+from grit import constants
-+from grit import util
-+
-+# The contents of the new .grd file
-+_FILE_CONTENTS = '''\
-+<?xml version="1.0" encoding="UTF-8"?>
-+<grit base_dir="." latest_public_release="0" current_release="1"
-+ source_lang_id="en" enc_check="%s">
-+ <outputs>
-+ <!-- TODO add each of your output files. Modify the three below, and add
-+ your own for your various languages. See the user's guide for more
-+ details.
-+ Note that all output references are relative to the output directory
-+ which is specified at build time. -->
-+ <output filename="resource.h" type="rc_header" />
-+ <output filename="en_resource.rc" type="rc_all" />
-+ <output filename="fr_resource.rc" type="rc_all" />
-+ </outputs>
-+ <translations>
-+ <!-- TODO add references to each of the XTB files (from the Translation
-+ Console) that contain translations of messages in your project. Each
-+ takes a form like <file path="english.xtb" />. Remember that all file
-+ references are relative to this .grd file. -->
-+ </translations>
-+ <release seq="1">
-+ <includes>
-+ <!-- TODO add a list of your included resources here, e.g. BMP and GIF
-+ resources. -->
-+ </includes>
-+ <structures>
-+ <!-- TODO add a list of all your structured resources here, e.g. HTML
-+ templates, menus, dialogs etc. Note that for menus, dialogs and version
-+ information resources you reference an .rc file containing them.-->
-+ </structures>
-+ <messages>
-+ <!-- TODO add all of your "string table" messages here. Remember to
-+ change nontranslateable parts of the messages into placeholders (using the
-+ <ph> element). You can also use the 'grit add' tool to help you identify
-+ nontranslateable parts and create placeholders for them. -->
-+ </messages>
-+ </release>
-+</grit>''' % constants.ENCODING_CHECK
-+
-+
-+class NewGrd(interface.Tool):
-+ '''Usage: grit newgrd OUTPUT_FILE
-+
-+Creates a new, empty .grd file OUTPUT_FILE with comments about what to put
-+where in the file.'''
-+
-+ def ShortDescription(self):
-+ return 'Create a new empty .grd file.'
-+
-+ def ParseOptions(self, args):
-+ """Set this objects and return all non-option arguments."""
-+ own_opts, args = getopt.getopt(args, '', ('help',))
-+ for key, val in own_opts:
-+ if key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+ return args
-+
-+ def Run(self, opts, args):
-+ args = self.ParseOptions(args)
-+ if len(args) != 1:
-+ print('This tool requires exactly one argument, the name of the output '
-+ 'file.')
-+ return 2
-+ filename = args[0]
-+ with util.WrapOutputStream(open(filename, 'wb'), 'utf-8') as out:
-+ out.write(_FILE_CONTENTS)
-+ print("Wrote file %s" % filename)
-diff --git a/tools/grit/grit/tool/newgrd_unittest.py b/tools/grit/grit/tool/newgrd_unittest.py
-new file mode 100644
-index 0000000000..f7c8831df5
---- /dev/null
-+++ b/tools/grit/grit/tool/newgrd_unittest.py
-@@ -0,0 +1,51 @@
-+#!/usr/bin/env python
-+# Copyright 2020 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for the 'grit newgrd' tool.'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from grit import util
-+from grit.tool import newgrd
-+
-+
-+class DummyOpts(object):
-+ """Options needed by NewGrd."""
-+
-+
-+class NewgrdUnittest(unittest.TestCase):
-+
-+ def testNewFile(self):
-+ """Create a new file."""
-+ tool = newgrd.NewGrd()
-+ with util.TempDir({}) as output_dir:
-+ output_file = os.path.join(output_dir.GetPath(), 'new.grd')
-+ self.assertIsNone(tool.Run(DummyOpts(), [output_file]))
-+ self.assertTrue(os.path.exists(output_file))
-+
-+ def testMissingFile(self):
-+ """Verify failure w/out file output."""
-+ tool = newgrd.NewGrd()
-+ ret = tool.Run(DummyOpts(), [])
-+ self.assertIsNotNone(ret)
-+ self.assertGreater(ret, 0)
-+
-+ def testTooManyArgs(self):
-+ """Verify failure w/too many outputs."""
-+ tool = newgrd.NewGrd()
-+ ret = tool.Run(DummyOpts(), ['a', 'b'])
-+ self.assertIsNotNone(ret)
-+ self.assertGreater(ret, 0)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/postprocess_interface.py b/tools/grit/grit/tool/postprocess_interface.py
-new file mode 100644
-index 0000000000..4bb8c5871f
---- /dev/null
-+++ b/tools/grit/grit/tool/postprocess_interface.py
-@@ -0,0 +1,29 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+''' Base class for postprocessing of RC files.
-+'''
-+
-+from __future__ import print_function
-+
-+class PostProcessor(object):
-+ ''' Base class for postprocessing of the RC file data before being
-+ output through the RC2GRD tool. You should implement this class if
-+ you want GRIT to do specific things to the RC files after it has
-+ converted the data into GRD format, i.e. change the content of the
-+ RC file, and put it into a P4 changelist, etc.'''
-+
-+
-+ def Process(self, rctext, rcpath, grdnode):
-+ ''' Processes the data in rctext and grdnode.
-+ Args:
-+ rctext: string containing the contents of the RC file being processed.
-+ rcpath: the path used to access the file.
-+ grdtext: the root node of the grd xml data generated by
-+ the rc2grd tool.
-+
-+ Return:
-+ The root node of the processed GRD tree.
-+ '''
-+ raise NotImplementedError()
-diff --git a/tools/grit/grit/tool/postprocess_unittest.py b/tools/grit/grit/tool/postprocess_unittest.py
-new file mode 100644
-index 0000000000..77fe228bbe
---- /dev/null
-+++ b/tools/grit/grit/tool/postprocess_unittest.py
-@@ -0,0 +1,64 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit test that checks postprocessing of files.
-+ Tests postprocessing by having the postprocessor
-+ modify the grd data tree, changing the message name attributes.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import re
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+import grit.tool.postprocess_interface
-+from grit.tool import rc2grd
-+
-+
-+class PostProcessingUnittest(unittest.TestCase):
-+
-+ def testPostProcessing(self):
-+ rctext = '''STRINGTABLE
-+BEGIN
-+ DUMMY_STRING_1 "String 1"
-+ // Some random description
-+ DUMMY_STRING_2 "This text was added during preprocessing"
-+END
-+ '''
-+ tool = rc2grd.Rc2Grd()
-+ class DummyOpts(object):
-+ verbose = False
-+ extra_verbose = False
-+ tool.o = DummyOpts()
-+ tool.post_process = 'grit.tool.postprocess_unittest.DummyPostProcessor'
-+ result = tool.Process(rctext, '.\resource.rc')
-+
-+ self.failUnless(
-+ result.children[2].children[2].children[0].attrs['name'] == 'SMART_STRING_1')
-+ self.failUnless(
-+ result.children[2].children[2].children[1].attrs['name'] == 'SMART_STRING_2')
-+
-+class DummyPostProcessor(grit.tool.postprocess_interface.PostProcessor):
-+ '''
-+ Post processing replaces all message name attributes containing "DUMMY" to
-+ "SMART".
-+ '''
-+ def Process(self, rctext, rcpath, grdnode):
-+ smarter = re.compile(r'(DUMMY)(.*)')
-+ messages = grdnode.children[2].children[2]
-+ for node in messages.children:
-+ name_attr = node.attrs['name']
-+ m = smarter.search(name_attr)
-+ if m:
-+ node.attrs['name'] = 'SMART' + m.group(2)
-+ return grdnode
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/preprocess_interface.py b/tools/grit/grit/tool/preprocess_interface.py
-new file mode 100644
-index 0000000000..67974e704e
---- /dev/null
-+++ b/tools/grit/grit/tool/preprocess_interface.py
-@@ -0,0 +1,25 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+''' Base class for preprocessing of RC files.
-+'''
-+
-+from __future__ import print_function
-+
-+class PreProcessor(object):
-+ ''' Base class for preprocessing of the RC file data before being
-+ output through the RC2GRD tool. You should implement this class if
-+ you have specific constructs in your RC files that GRIT cannot handle.'''
-+
-+
-+ def Process(self, rctext, rcpath):
-+ ''' Processes the data in rctext.
-+ Args:
-+ rctext: string containing the contents of the RC file being processed
-+ rcpath: the path used to access the file.
-+
-+ Return:
-+ The processed text.
-+ '''
-+ raise NotImplementedError()
-diff --git a/tools/grit/grit/tool/preprocess_unittest.py b/tools/grit/grit/tool/preprocess_unittest.py
-new file mode 100644
-index 0000000000..40b95cd6f8
---- /dev/null
-+++ b/tools/grit/grit/tool/preprocess_unittest.py
-@@ -0,0 +1,50 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit test that checks preprocessing of files.
-+ Tests preprocessing by adding having the preprocessor
-+ provide the actual rctext data.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+import grit.tool.preprocess_interface
-+from grit.tool import rc2grd
-+
-+
-+class PreProcessingUnittest(unittest.TestCase):
-+
-+ def testPreProcessing(self):
-+ tool = rc2grd.Rc2Grd()
-+ class DummyOpts(object):
-+ verbose = False
-+ extra_verbose = False
-+ tool.o = DummyOpts()
-+ tool.pre_process = 'grit.tool.preprocess_unittest.DummyPreProcessor'
-+ result = tool.Process('', '.\resource.rc')
-+
-+ self.failUnless(
-+ result.children[2].children[2].children[0].attrs['name'] == 'DUMMY_STRING_1')
-+
-+class DummyPreProcessor(grit.tool.preprocess_interface.PreProcessor):
-+ def Process(self, rctext, rcpath):
-+ rctext = '''STRINGTABLE
-+BEGIN
-+ DUMMY_STRING_1 "String 1"
-+ // Some random description
-+ DUMMY_STRING_2 "This text was added during preprocessing"
-+END
-+ '''
-+ return rctext
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/rc2grd.py b/tools/grit/grit/tool/rc2grd.py
-new file mode 100644
-index 0000000000..3195b39000
---- /dev/null
-+++ b/tools/grit/grit/tool/rc2grd.py
-@@ -0,0 +1,418 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The 'grit rc2grd' tool.'''
-+
-+from __future__ import print_function
-+
-+import os.path
-+import getopt
-+import re
-+import sys
-+
-+import six
-+from six import StringIO
-+
-+import grit.node.empty
-+from grit.node import include
-+from grit.node import structure
-+from grit.node import message
-+
-+from grit.gather import rc
-+from grit.gather import tr_html
-+
-+from grit.tool import interface
-+from grit.tool import postprocess_interface
-+from grit.tool import preprocess_interface
-+
-+from grit import grd_reader
-+from grit import lazy_re
-+from grit import tclib
-+from grit import util
-+
-+
-+# Matches files referenced from an .rc file
-+_FILE_REF = lazy_re.compile(r'''
-+ ^(?P<id>[A-Z_0-9.]+)[ \t]+
-+ (?P<type>[A-Z_0-9]+)[ \t]+
-+ "(?P<file>.*?([^"]|""))"[ \t]*$''', re.VERBOSE | re.MULTILINE)
-+
-+
-+# Matches a dialog section
-+_DIALOG = lazy_re.compile(
-+ r'^(?P<id>[A-Z0-9_]+)\s+DIALOG(EX)?\s.+?^BEGIN\s*$.+?^END\s*$',
-+ re.MULTILINE | re.DOTALL)
-+
-+
-+# Matches a menu section
-+_MENU = lazy_re.compile(r'^(?P<id>[A-Z0-9_]+)\s+MENU.+?^BEGIN\s*$.+?^END\s*$',
-+ re.MULTILINE | re.DOTALL)
-+
-+
-+# Matches a versioninfo section
-+_VERSIONINFO = lazy_re.compile(
-+ r'^(?P<id>[A-Z0-9_]+)\s+VERSIONINFO\s.+?^BEGIN\s*$.+?^END\s*$',
-+ re.MULTILINE | re.DOTALL)
-+
-+
-+# Matches a stringtable
-+_STRING_TABLE = lazy_re.compile(
-+ (r'^STRINGTABLE(\s+(PRELOAD|DISCARDABLE|CHARACTERISTICS.+|LANGUAGE.+|'
-+ r'VERSION.+))*\s*\nBEGIN\s*$(?P<body>.+?)^END\s*$'),
-+ re.MULTILINE | re.DOTALL)
-+
-+
-+# Matches each message inside a stringtable, breaking it up into comments,
-+# the ID of the message, and the (RC-escaped) message text.
-+_MESSAGE = lazy_re.compile(r'''
-+ (?P<comment>(^\s+//.+?)*) # 0 or more lines of comments preceding the message
-+ ^\s*
-+ (?P<id>[A-Za-z0-9_]+) # id
-+ \s+
-+ "(?P<text>.*?([^"]|""))"([^"]|$) # The message itself
-+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
-+
-+
-+# Matches each line of comment text in a multi-line comment.
-+_COMMENT_TEXT = lazy_re.compile(r'^\s*//\s*(?P<text>.+?)$', re.MULTILINE)
-+
-+
-+# Matches a string that is empty or all whitespace
-+_WHITESPACE_ONLY = lazy_re.compile(r'\A\s*\Z', re.MULTILINE)
-+
-+
-+# Finds printf and FormatMessage style format specifiers
-+# Uses non-capturing groups except for the outermost group, so the output of
-+# re.split() should include both the normal text and what we intend to
-+# replace with placeholders.
-+# TODO(joi) Check documentation for printf (and Windows variants) and FormatMessage
-+_FORMAT_SPECIFIER = lazy_re.compile(
-+ r'(%[-# +]?(?:[0-9]*|\*)(?:\.(?:[0-9]+|\*))?(?:h|l|L)?' # printf up to last char
-+ r'(?:d|i|o|u|x|X|e|E|f|F|g|G|c|r|s|ls|ws)' # printf last char
-+ r'|\$[1-9][0-9]*)') # FormatMessage
-+
-+
-+class Rc2Grd(interface.Tool):
-+ '''A tool for converting .rc files to .grd files. This tool is only for
-+converting the source (nontranslated) .rc file to a .grd file. For importing
-+existing translations, use the rc2xtb tool.
-+
-+Usage: grit [global options] rc2grd [OPTIONS] RCFILE
-+
-+The tool takes a single argument, which is the path to the .rc file to convert.
-+It outputs a .grd file with the same name in the same directory as the .rc file.
-+The .grd file may have one or more TODO comments for things that have to be
-+cleaned up manually.
-+
-+OPTIONS may be any of the following:
-+
-+ -e ENCODING Specify the ENCODING of the .rc file. Default is 'cp1252'.
-+
-+ -h TYPE Specify the TYPE attribute for HTML structures.
-+ Default is 'tr_html'.
-+
-+ -u ENCODING Specify the ENCODING of HTML files. Default is 'utf-8'.
-+
-+ -n MATCH Specify the regular expression to match in comments that will
-+ indicate that the resource the comment belongs to is not
-+ translateable. Default is 'Not locali(s|z)able'.
-+
-+ -r GRDFILE Specify that GRDFILE should be used as a "role model" for
-+ any placeholders that otherwise would have had TODO names.
-+ This attempts to find an identical message in the GRDFILE
-+ and uses that instead of the automatically placeholderized
-+ message.
-+
-+ --pre CLASS Specify an optional, fully qualified classname, which
-+ has to be a subclass of grit.tool.PreProcessor, to
-+ run on the text of the RC file before conversion occurs.
-+ This can be used to support constructs in the RC files
-+ that GRIT cannot handle on its own.
-+
-+ --post CLASS Specify an optional, fully qualified classname, which
-+ has to be a subclass of grit.tool.PostProcessor, to
-+ run on the text of the converted RC file.
-+ This can be used to alter the content of the RC file
-+ based on the conversion that occured.
-+
-+For menus, dialogs and version info, the .grd file will refer to the original
-+.rc file. Once conversion is complete, you can strip the original .rc file
-+of its string table and all comments as these will be available in the .grd
-+file.
-+
-+Note that this tool WILL NOT obey C preprocessor rules, so even if something
-+is #if 0-ed out it will still be included in the output of this tool
-+Therefore, if your .rc file contains sections like this, you should run the
-+C preprocessor on the .rc file or manually edit it before using this tool.
-+'''
-+
-+ def ShortDescription(self):
-+ return 'A tool for converting .rc source files to .grd files.'
-+
-+ def __init__(self):
-+ self.input_encoding = 'cp1252'
-+ self.html_type = 'tr_html'
-+ self.html_encoding = 'utf-8'
-+ self.not_localizable_re = re.compile('Not locali(s|z)able')
-+ self.role_model = None
-+ self.pre_process = None
-+ self.post_process = None
-+
-+ def ParseOptions(self, args, help_func=None):
-+ '''Given a list of arguments, set this object's options and return
-+ all non-option arguments.
-+ '''
-+ (own_opts, args) = getopt.getopt(args, 'e:h:u:n:r',
-+ ('help', 'pre=', 'post='))
-+ for (key, val) in own_opts:
-+ if key == '-e':
-+ self.input_encoding = val
-+ elif key == '-h':
-+ self.html_type = val
-+ elif key == '-u':
-+ self.html_encoding = val
-+ elif key == '-n':
-+ self.not_localizable_re = re.compile(val)
-+ elif key == '-r':
-+ self.role_model = grd_reader.Parse(val)
-+ elif key == '--pre':
-+ self.pre_process = val
-+ elif key == '--post':
-+ self.post_process = val
-+ elif key == '--help':
-+ if help_func is None:
-+ self.ShowUsage()
-+ else:
-+ help_func()
-+ sys.exit(0)
-+ return args
-+
-+ def Run(self, opts, args):
-+ args = self.ParseOptions(args)
-+ if len(args) != 1:
-+ print('This tool takes a single tool-specific argument, the path to the\n'
-+ '.rc file to process.')
-+ return 2
-+ self.SetOptions(opts)
-+
-+ path = args[0]
-+ out_path = os.path.join(util.dirname(path),
-+ os.path.splitext(os.path.basename(path))[0] + '.grd')
-+
-+ rctext = util.ReadFile(path, self.input_encoding)
-+ grd_text = six.text_type(self.Process(rctext, path))
-+ with util.WrapOutputStream(open(out_path, 'wb'), 'utf-8') as outfile:
-+ outfile.write(grd_text)
-+
-+ print('Wrote output file %s.\nPlease check for TODO items in the file.' %
-+ (out_path,))
-+
-+
-+ def Process(self, rctext, rc_path):
-+ '''Processes 'rctext' and returns a resource tree corresponding to it.
-+
-+ Args:
-+ rctext: complete text of the rc file
-+ rc_path: 'resource\resource.rc'
-+
-+ Return:
-+ grit.node.base.Node subclass
-+ '''
-+
-+ if self.pre_process:
-+ preprocess_class = util.NewClassInstance(self.pre_process,
-+ preprocess_interface.PreProcessor)
-+ if preprocess_class:
-+ rctext = preprocess_class.Process(rctext, rc_path)
-+ else:
-+ self.Out(
-+ 'PreProcessing class could not be found. Skipping preprocessing.\n')
-+
-+ # Start with a basic skeleton for the .grd file
-+ root = grd_reader.Parse(StringIO(
-+ '''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit base_dir="." latest_public_release="0"
-+ current_release="1" source_lang_id="en">
-+ <outputs />
-+ <translations />
-+ <release seq="1">
-+ <includes />
-+ <structures />
-+ <messages />
-+ </release>
-+ </grit>'''), util.dirname(rc_path))
-+ includes = root.children[2].children[0]
-+ structures = root.children[2].children[1]
-+ messages = root.children[2].children[2]
-+ assert (isinstance(includes, grit.node.empty.IncludesNode) and
-+ isinstance(structures, grit.node.empty.StructuresNode) and
-+ isinstance(messages, grit.node.empty.MessagesNode))
-+
-+ self.AddIncludes(rctext, includes)
-+ self.AddStructures(rctext, structures, os.path.basename(rc_path))
-+ self.AddMessages(rctext, messages)
-+
-+ self.VerboseOut('Validating that all IDs are unique...\n')
-+ root.ValidateUniqueIds()
-+ self.ExtraVerboseOut('Done validating that all IDs are unique.\n')
-+
-+ if self.post_process:
-+ postprocess_class = util.NewClassInstance(self.post_process,
-+ postprocess_interface.PostProcessor)
-+ if postprocess_class:
-+ root = postprocess_class.Process(rctext, rc_path, root)
-+ else:
-+ self.Out(
-+ 'PostProcessing class could not be found. Skipping postprocessing.\n')
-+
-+ return root
-+
-+
-+ def IsHtml(self, res_type, fname):
-+ '''Check whether both the type and file extension indicate HTML'''
-+ fext = fname.split('.')[-1].lower()
-+ return res_type == 'HTML' and fext in ('htm', 'html')
-+
-+
-+ def AddIncludes(self, rctext, node):
-+ '''Scans 'rctext' for included resources (e.g. BITMAP, ICON) and
-+ adds each included resource as an <include> child node of 'node'.'''
-+ for m in _FILE_REF.finditer(rctext):
-+ id = m.group('id')
-+ res_type = m.group('type').upper()
-+ fname = rc.Section.UnEscape(m.group('file'))
-+ assert fname.find('\n') == -1
-+ if not self.IsHtml(res_type, fname):
-+ self.VerboseOut('Processing %s with ID %s (filename: %s)\n' %
-+ (res_type, id, fname))
-+ node.AddChild(include.IncludeNode.Construct(node, id, res_type, fname))
-+
-+
-+ def AddStructures(self, rctext, node, rc_filename):
-+ '''Scans 'rctext' for structured resources (e.g. menus, dialogs, version
-+ information resources and HTML templates) and adds each as a <structure>
-+ child of 'node'.'''
-+ # First add HTML includes
-+ for m in _FILE_REF.finditer(rctext):
-+ id = m.group('id')
-+ res_type = m.group('type').upper()
-+ fname = rc.Section.UnEscape(m.group('file'))
-+ if self.IsHtml(type, fname):
-+ node.AddChild(structure.StructureNode.Construct(
-+ node, id, self.html_type, fname, self.html_encoding))
-+
-+ # Then add all RC includes
-+ def AddStructure(res_type, id):
-+ self.VerboseOut('Processing %s with ID %s\n' % (res_type, id))
-+ node.AddChild(structure.StructureNode.Construct(node, id, res_type,
-+ rc_filename,
-+ encoding=self.input_encoding))
-+ for m in _MENU.finditer(rctext):
-+ AddStructure('menu', m.group('id'))
-+ for m in _DIALOG.finditer(rctext):
-+ AddStructure('dialog', m.group('id'))
-+ for m in _VERSIONINFO.finditer(rctext):
-+ AddStructure('version', m.group('id'))
-+
-+
-+ def AddMessages(self, rctext, node):
-+ '''Scans 'rctext' for all messages in string tables, preprocesses them as
-+ much as possible for placeholders (e.g. messages containing $1, $2 or %s, %d
-+ type format specifiers get those specifiers replaced with placeholders, and
-+ HTML-formatted messages get run through the HTML-placeholderizer). Adds
-+ each message as a <message> node child of 'node'.'''
-+ for tm in _STRING_TABLE.finditer(rctext):
-+ table = tm.group('body')
-+ for mm in _MESSAGE.finditer(table):
-+ comment_block = mm.group('comment')
-+ comment_text = []
-+ for cm in _COMMENT_TEXT.finditer(comment_block):
-+ comment_text.append(cm.group('text'))
-+ comment_text = ' '.join(comment_text)
-+
-+ id = mm.group('id')
-+ text = rc.Section.UnEscape(mm.group('text'))
-+
-+ self.VerboseOut('Processing message %s (text: "%s")\n' % (id, text))
-+
-+ msg_obj = self.Placeholderize(text)
-+
-+ # Messages that contain only placeholders do not need translation.
-+ is_translateable = False
-+ for item in msg_obj.GetContent():
-+ if isinstance(item, six.string_types):
-+ if not _WHITESPACE_ONLY.match(item):
-+ is_translateable = True
-+
-+ if self.not_localizable_re.search(comment_text):
-+ is_translateable = False
-+
-+ message_meaning = ''
-+ internal_comment = ''
-+
-+ # If we have a "role model" (existing GRD file) and this node exists
-+ # in the role model, use the description, meaning and translateable
-+ # attributes from the role model.
-+ if self.role_model:
-+ role_node = self.role_model.GetNodeById(id)
-+ if role_node:
-+ is_translateable = role_node.IsTranslateable()
-+ message_meaning = role_node.attrs['meaning']
-+ comment_text = role_node.attrs['desc']
-+ internal_comment = role_node.attrs['internal_comment']
-+
-+ # For nontranslateable messages, we don't want the complexity of
-+ # placeholderizing everything.
-+ if not is_translateable:
-+ msg_obj = tclib.Message(text=text)
-+
-+ msg_node = message.MessageNode.Construct(node, msg_obj, id,
-+ desc=comment_text,
-+ translateable=is_translateable,
-+ meaning=message_meaning)
-+ msg_node.attrs['internal_comment'] = internal_comment
-+
-+ node.AddChild(msg_node)
-+ self.ExtraVerboseOut('Done processing message %s\n' % id)
-+
-+
-+ def Placeholderize(self, text):
-+ '''Creates a tclib.Message object from 'text', attempting to recognize
-+ a few different formats of text that can be automatically placeholderized
-+ (HTML code, printf-style format strings, and FormatMessage-style format
-+ strings).
-+ '''
-+
-+ try:
-+ # First try HTML placeholderizing.
-+ # TODO(joi) Allow use of non-TotalRecall flavors of HTML placeholderizing
-+ msg = tr_html.HtmlToMessage(text, True)
-+ for item in msg.GetContent():
-+ if not isinstance(item, six.string_types):
-+ return msg # Contained at least one placeholder, so we're done
-+
-+ # HTML placeholderization didn't do anything, so try to find printf or
-+ # FormatMessage format specifiers and change them into placeholders.
-+ msg = tclib.Message()
-+ parts = _FORMAT_SPECIFIER.split(text)
-+ todo_counter = 1 # We make placeholder IDs 'TODO_0001' etc.
-+ for part in parts:
-+ if _FORMAT_SPECIFIER.match(part):
-+ msg.AppendPlaceholder(tclib.Placeholder(
-+ 'TODO_%04d' % todo_counter, part, 'TODO'))
-+ todo_counter += 1
-+ elif part != '':
-+ msg.AppendText(part)
-+
-+ if self.role_model and len(parts) > 1: # there are TODO placeholders
-+ role_model_msg = self.role_model.UberClique().BestCliqueByOriginalText(
-+ msg.GetRealContent(), '')
-+ if role_model_msg:
-+ # replace wholesale to get placeholder names and examples
-+ msg = role_model_msg
-+
-+ return msg
-+ except:
-+ print('Exception processing message with text "%s"' % text)
-+ raise
-diff --git a/tools/grit/grit/tool/rc2grd_unittest.py b/tools/grit/grit/tool/rc2grd_unittest.py
-new file mode 100644
-index 0000000000..6d53794c27
---- /dev/null
-+++ b/tools/grit/grit/tool/rc2grd_unittest.py
-@@ -0,0 +1,163 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.tool.rc2grd'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import re
-+import unittest
-+
-+from six import StringIO
-+
-+from grit import grd_reader
-+from grit import util
-+from grit.node import base
-+from grit.tool import rc2grd
-+
-+
-+class Rc2GrdUnittest(unittest.TestCase):
-+ def testPlaceholderize(self):
-+ tool = rc2grd.Rc2Grd()
-+ original = "Hello %s, how are you? I'm $1 years old!"
-+ msg = tool.Placeholderize(original)
-+ self.failUnless(msg.GetPresentableContent() == "Hello TODO_0001, how are you? I'm TODO_0002 years old!")
-+ self.failUnless(msg.GetRealContent() == original)
-+
-+ def testHtmlPlaceholderize(self):
-+ tool = rc2grd.Rc2Grd()
-+ original = "Hello <b>[USERNAME]</b>, how are you? I'm [AGE] years old!"
-+ msg = tool.Placeholderize(original)
-+ self.failUnless(msg.GetPresentableContent() ==
-+ "Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, how are you? I'm X_AGE_X years old!")
-+ self.failUnless(msg.GetRealContent() == original)
-+
-+ def testMenuWithoutWhitespaceRegression(self):
-+ # There was a problem in the original regular expression for parsing out
-+ # menu sections, that would parse the following block of text as a single
-+ # menu instead of two.
-+ two_menus = '''
-+// Hyper context menus
-+IDR_HYPERMENU_FOLDER MENU
-+BEGIN
-+ POPUP "HyperFolder"
-+ BEGIN
-+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
-+ END
-+END
-+
-+IDR_HYPERMENU_FILE MENU
-+BEGIN
-+ POPUP "HyperFile"
-+ BEGIN
-+ MENUITEM "Open Folder", IDM_OPENFOLDER
-+ END
-+END
-+
-+'''
-+ self.failUnless(len(rc2grd._MENU.findall(two_menus)) == 2)
-+
-+ def testRegressionScriptWithTranslateable(self):
-+ tool = rc2grd.Rc2Grd()
-+
-+ # test rig
-+ class DummyNode(base.Node):
-+ def AddChild(self, item):
-+ self.node = item
-+ verbose = False
-+ extra_verbose = False
-+ tool.not_localizable_re = re.compile('')
-+ tool.o = DummyNode()
-+
-+ rc_text = '''STRINGTABLE\nBEGIN\nID_BINGO "<SPAN id=hp style='BEHAVIOR: url(#default#homepage)'></SPAN><script>if (!hp.isHomePage('[$~HOMEPAGE~$]')) {document.write(""<a href=\\""[$~SETHOMEPAGEURL~$]\\"" >Set As Homepage</a> - "");}</script>"\nEND\n'''
-+ tool.AddMessages(rc_text, tool.o)
-+ self.failUnless(tool.o.node.GetCdata().find('Set As Homepage') != -1)
-+
-+ # TODO(joi) Improve the HTML parser to support translateables inside
-+ # <script> blocks?
-+ self.failUnless(tool.o.node.attrs['translateable'] == 'false')
-+
-+ def testRoleModel(self):
-+ rc_text = ('STRINGTABLE\n'
-+ 'BEGIN\n'
-+ ' // This should not show up\n'
-+ ' IDS_BINGO "Hello %s, how are you?"\n'
-+ ' // The first description\n'
-+ ' IDS_BONGO "Hello %s, my name is %s, and yours?"\n'
-+ ' IDS_PROGRAMS_SHUTDOWN_TEXT "Google Desktop Search needs to close the following programs:\\n\\n$1\\nThe installation will not proceed if you choose to cancel."\n'
-+ 'END\n')
-+ tool = rc2grd.Rc2Grd()
-+ tool.role_model = grd_reader.Parse(StringIO(
-+ '''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_BINGO">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you?
-+ </message>
-+ <message name="IDS_BONGO" desc="The other description">
-+ Hello <ph name="USERNAME">%s<ex>Jakob</ex></ph>, my name is <ph name="ADMINNAME">%s<ex>Joi</ex></ph>, and yours?
-+ </message>
-+ <message name="IDS_PROGRAMS_SHUTDOWN_TEXT" desc="LIST_OF_PROGRAMS is replaced by a bulleted list of program names.">
-+ Google Desktop Search needs to close the following programs:
-+
-+<ph name="LIST_OF_PROGRAMS">$1<ex>Program 1, Program 2</ex></ph>
-+The installation will not proceed if you choose to cancel.
-+ </message>
-+ </messages>
-+ </release>
-+ </grit>'''), dir='.')
-+
-+ # test rig
-+ class DummyOpts(object):
-+ verbose = False
-+ extra_verbose = False
-+ tool.o = DummyOpts()
-+ result = tool.Process(rc_text, '.\resource.rc')
-+ self.failUnless(
-+ result.children[2].children[2].children[0].attrs['desc'] == '')
-+ self.failUnless(
-+ result.children[2].children[2].children[0].children[0].attrs['name'] == 'USERNAME')
-+ self.failUnless(
-+ result.children[2].children[2].children[1].attrs['desc'] == 'The other description')
-+ self.failUnless(
-+ result.children[2].children[2].children[1].attrs['meaning'] == '')
-+ self.failUnless(
-+ result.children[2].children[2].children[1].children[0].attrs['name'] == 'USERNAME')
-+ self.failUnless(
-+ result.children[2].children[2].children[1].children[1].attrs['name'] == 'ADMINNAME')
-+ self.failUnless(
-+ result.children[2].children[2].children[2].children[0].attrs['name'] == 'LIST_OF_PROGRAMS')
-+
-+ def testRunOutput(self):
-+ """Verify basic correct Run behavior."""
-+ tool = rc2grd.Rc2Grd()
-+ class DummyOpts(object):
-+ verbose = False
-+ extra_verbose = False
-+ with util.TempDir({}) as output_dir:
-+ rcfile = os.path.join(output_dir.GetPath(), 'foo.rc')
-+ open(rcfile, 'w').close()
-+ self.assertIsNone(tool.Run(DummyOpts(), [rcfile]))
-+ self.assertTrue(os.path.exists(os.path.join(output_dir.GetPath(), 'foo.grd')))
-+
-+ def testMissingOutput(self):
-+ """Verify failure with no args."""
-+ tool = rc2grd.Rc2Grd()
-+ class DummyOpts(object):
-+ verbose = False
-+ extra_verbose = False
-+ ret = tool.Run(DummyOpts(), [])
-+ self.assertIsNotNone(ret)
-+ self.assertGreater(ret, 0)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/resize.py b/tools/grit/grit/tool/resize.py
-new file mode 100644
-index 0000000000..6a897c077e
---- /dev/null
-+++ b/tools/grit/grit/tool/resize.py
-@@ -0,0 +1,295 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The 'grit resize' tool.
-+'''
-+
-+from __future__ import print_function
-+
-+import getopt
-+import os
-+import sys
-+
-+from grit import grd_reader
-+from grit import pseudo
-+from grit import util
-+from grit.format import rc
-+from grit.format import rc_header
-+from grit.node import include
-+from grit.tool import interface
-+
-+
-+# Template for the .vcproj file, with a couple of [[REPLACEABLE]] parts.
-+PROJECT_TEMPLATE = '''\
-+<?xml version="1.0" encoding="Windows-1252"?>
-+<VisualStudioProject
-+ ProjectType="Visual C++"
-+ Version="7.10"
-+ Name="[[DIALOG_NAME]]"
-+ ProjectGUID="[[PROJECT_GUID]]"
-+ Keyword="Win32Proj">
-+ <Platforms>
-+ <Platform
-+ Name="Win32"/>
-+ </Platforms>
-+ <Configurations>
-+ <Configuration
-+ Name="Debug|Win32"
-+ OutputDirectory="Debug"
-+ IntermediateDirectory="Debug"
-+ ConfigurationType="1"
-+ CharacterSet="2">
-+ </Configuration>
-+ </Configurations>
-+ <References>
-+ </References>
-+ <Files>
-+ <Filter
-+ Name="Resource Files"
-+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
-+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
-+ <File
-+ RelativePath=".\\[[DIALOG_NAME]].rc">
-+ </File>
-+ </Filter>
-+ </Files>
-+ <Globals>
-+ </Globals>
-+</VisualStudioProject>'''
-+
-+
-+# Template for the .rc file with a couple of [[REPLACEABLE]] parts.
-+# TODO(joi) Improve this (and the resource.h template) to allow saving and then
-+# reopening of the RC file in Visual Studio. Currently you can only open it
-+# once and change it, then after you close it you won't be able to reopen it.
-+RC_TEMPLATE = '''\
-+// This file is automatically generated by GRIT and intended for editing
-+// the layout of the dialogs contained in it. Do not edit anything but the
-+// dialogs. Any changes made to translateable portions of the dialogs will
-+// be ignored by GRIT.
-+
-+#include "resource.h"
-+#include <winresrc.h>
-+#ifdef IDC_STATIC
-+#undef IDC_STATIC
-+#endif
-+#define IDC_STATIC (-1)
-+
-+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
-+
-+#pragma code_page([[CODEPAGE_NUM]])
-+
-+[[INCLUDES]]
-+
-+[[DIALOGS]]
-+'''
-+
-+
-+# Template for the resource.h file with a couple of [[REPLACEABLE]] parts.
-+HEADER_TEMPLATE = '''\
-+// This file is automatically generated by GRIT. Do not edit.
-+
-+#pragma once
-+
-+// Edit commands
-+#define ID_EDIT_CLEAR 0xE120
-+#define ID_EDIT_CLEAR_ALL 0xE121
-+#define ID_EDIT_COPY 0xE122
-+#define ID_EDIT_CUT 0xE123
-+#define ID_EDIT_FIND 0xE124
-+#define ID_EDIT_PASTE 0xE125
-+#define ID_EDIT_PASTE_LINK 0xE126
-+#define ID_EDIT_PASTE_SPECIAL 0xE127
-+#define ID_EDIT_REPEAT 0xE128
-+#define ID_EDIT_REPLACE 0xE129
-+#define ID_EDIT_SELECT_ALL 0xE12A
-+#define ID_EDIT_UNDO 0xE12B
-+#define ID_EDIT_REDO 0xE12C
-+
-+
-+[[DEFINES]]
-+'''
-+
-+
-+class ResizeDialog(interface.Tool):
-+ '''Generates an RC file, header and Visual Studio project that you can use
-+with Visual Studio's GUI resource editor to modify the layout of dialogs for
-+the language of your choice. You then use the RC file, after you resize the
-+dialog, for the language or languages of your choice, using the <skeleton> child
-+of the <structure> node for the dialog. The translateable bits of the dialog
-+will be ignored when you use the <skeleton> node (GRIT will instead use the
-+translateable bits from the original dialog) but the layout changes you make
-+will be used. Note that your layout changes must preserve the order of the
-+translateable elements in the RC file.
-+
-+Usage: grit resize [-f BASEFOLDER] [-l LANG] [-e RCENCODING] DIALOGID*
-+
-+Arguments:
-+ DIALOGID The 'name' attribute of a dialog to output for resizing. Zero
-+ or more of these parameters can be used. If none are
-+ specified, all dialogs from the input .grd file are output.
-+
-+Options:
-+
-+ -f BASEFOLDER The project will be created in a subfolder of BASEFOLDER.
-+ The name of the subfolder will be the first DIALOGID you
-+ specify. Defaults to '.'
-+
-+ -l LANG Specifies that the RC file should contain a dialog translated
-+ into the language LANG. The default is a cp1252-representable
-+ pseudotranslation, because Visual Studio's GUI RC editor only
-+ supports single-byte encodings.
-+
-+ -c CODEPAGE Code page number to indicate to the RC compiler the encoding
-+ of the RC file, default is something reasonable for the
-+ language you selected (but this does not work for every single
-+ language). See details on codepages below. NOTE that you do
-+ not need to specify the codepage unless the tool complains
-+ that it's not sure which codepage to use. See the following
-+ page for codepage numbers supported by Windows:
-+ http://www.microsoft.com/globaldev/reference/wincp.mspx
-+
-+ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
-+ value VAL (defaults to 1) which will be used to control
-+ conditional inclusion of resources.
-+
-+
-+IMPORTANT NOTE: For now, the tool outputs a UTF-8 encoded file for any language
-+that can not be represented in cp1252 (i.e. anything other than Western
-+European languages). You will need to open this file in a text editor and
-+save it using the codepage indicated in the #pragma code_page(XXXX) command
-+near the top of the file, before you open it in Visual Studio.
-+
-+'''
-+
-+ # TODO(joi) It would be cool to have this tool note the Perforce revision
-+ # of the original RC file somewhere, such that the <skeleton> node could warn
-+ # if the original RC file gets updated without the skeleton file being updated.
-+
-+ # TODO(joi) Would be cool to have option to add the files to Perforce
-+
-+ def __init__(self):
-+ self.lang = pseudo.PSEUDO_LANG
-+ self.defines = {}
-+ self.base_folder = '.'
-+ self.codepage_number = 1252
-+ self.codepage_number_specified_explicitly = False
-+
-+ def SetLanguage(self, lang):
-+ '''Sets the language code to output things in.
-+ '''
-+ self.lang = lang
-+ if not self.codepage_number_specified_explicitly:
-+ self.codepage_number = util.LanguageToCodepage(lang)
-+
-+ def GetEncoding(self):
-+ if self.codepage_number == 1200:
-+ return 'utf_16'
-+ if self.codepage_number == 65001:
-+ return 'utf_8'
-+ return 'cp%d' % self.codepage_number
-+
-+ def ShortDescription(self):
-+ return 'Generate a file where you can resize a given dialog.'
-+
-+ def Run(self, opts, args):
-+ self.SetOptions(opts)
-+
-+ own_opts, args = getopt.getopt(args, 'l:f:c:D:', ('help',))
-+ for key, val in own_opts:
-+ if key == '-l':
-+ self.SetLanguage(val)
-+ if key == '-f':
-+ self.base_folder = val
-+ if key == '-c':
-+ self.codepage_number = int(val)
-+ self.codepage_number_specified_explicitly = True
-+ if key == '-D':
-+ name, val = util.ParseDefine(val)
-+ self.defines[name] = val
-+ elif key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+
-+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
-+ res_tree.OnlyTheseTranslations([self.lang])
-+ res_tree.RunGatherers()
-+
-+ # Dialog IDs are either explicitly listed, or we output all dialogs from the
-+ # .grd file
-+ dialog_ids = args
-+ if not len(dialog_ids):
-+ for node in res_tree:
-+ if node.name == 'structure' and node.attrs['type'] == 'dialog':
-+ dialog_ids.append(node.attrs['name'])
-+
-+ self.Process(res_tree, dialog_ids)
-+
-+ def Process(self, grd, dialog_ids):
-+ '''Outputs an RC file and header file for the dialog 'dialog_id' stored in
-+ resource tree 'grd', to self.base_folder, as discussed in this class's
-+ documentation.
-+
-+ Arguments:
-+ grd: grd = grd_reader.Parse(...); grd.RunGatherers()
-+ dialog_ids: ['IDD_MYDIALOG', 'IDD_OTHERDIALOG']
-+ '''
-+ grd.SetOutputLanguage(self.lang)
-+ grd.SetDefines(self.defines)
-+
-+ project_name = dialog_ids[0]
-+
-+ dir_path = os.path.join(self.base_folder, project_name)
-+ if not os.path.isdir(dir_path):
-+ os.mkdir(dir_path)
-+
-+ # If this fails then we're not on Windows (or you don't have the required
-+ # win32all Python libraries installed), so what are you doing mucking
-+ # about with RC files anyway? :)
-+ # pylint: disable=import-error
-+ import pythoncom
-+
-+ # Create the .vcproj file
-+ project_text = PROJECT_TEMPLATE.replace(
-+ '[[PROJECT_GUID]]', str(pythoncom.CreateGuid())
-+ ).replace('[[DIALOG_NAME]]', project_name)
-+ fname = os.path.join(dir_path, '%s.vcproj' % project_name)
-+ self.WriteFile(fname, project_text)
-+ print("Wrote %s" % fname)
-+
-+ # Create the .rc file
-+ # Output all <include> nodes since the dialogs might depend on them (e.g.
-+ # for icons and bitmaps).
-+ include_items = []
-+ for node in grd.ActiveDescendants():
-+ if isinstance(node, include.IncludeNode):
-+ include_items.append(rc.FormatInclude(node, self.lang, '.'))
-+ rc_text = RC_TEMPLATE.replace('[[CODEPAGE_NUM]]',
-+ str(self.codepage_number))
-+ rc_text = rc_text.replace('[[INCLUDES]]', ''.join(include_items))
-+
-+ # Then output the dialogs we have been asked to output.
-+ dialogs = []
-+ for dialog_id in dialog_ids:
-+ node = grd.GetNodeById(dialog_id)
-+ assert node.name == 'structure' and node.attrs['type'] == 'dialog'
-+ # TODO(joi) Add exception handling for better error reporting
-+ dialogs.append(rc.FormatStructure(node, self.lang, '.'))
-+ rc_text = rc_text.replace('[[DIALOGS]]', ''.join(dialogs))
-+
-+ fname = os.path.join(dir_path, '%s.rc' % project_name)
-+ self.WriteFile(fname, rc_text, self.GetEncoding())
-+ print("Wrote %s" % fname)
-+
-+ # Create the resource.h file
-+ header_defines = ''.join(rc_header.FormatDefines(grd))
-+ header_text = HEADER_TEMPLATE.replace('[[DEFINES]]', header_defines)
-+ fname = os.path.join(dir_path, 'resource.h')
-+ self.WriteFile(fname, header_text)
-+ print("Wrote %s" % fname)
-+
-+ def WriteFile(self, filename, contents, encoding='cp1252'):
-+ with open(filename, 'wb') as f:
-+ writer = util.WrapOutputStream(f, encoding)
-+ writer.write(contents)
-diff --git a/tools/grit/grit/tool/test.py b/tools/grit/grit/tool/test.py
-new file mode 100644
-index 0000000000..241a976d74
---- /dev/null
-+++ b/tools/grit/grit/tool/test.py
-@@ -0,0 +1,24 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+from __future__ import print_function
-+
-+from grit.tool import interface
-+
-+class TestTool(interface.Tool):
-+ '''This tool does nothing except print out the global options and
-+tool-specific arguments that it receives. It is intended only for testing,
-+hence the name :)
-+'''
-+
-+ def ShortDescription(self):
-+ return 'A do-nothing tool for testing command-line parsing.'
-+
-+ def Run(self, global_options, my_arguments):
-+ print('NOTE This tool is only for testing the parsing of global options and')
-+ print('tool-specific arguments that it receives. You may have intended to')
-+ print('run "grit unit" which is the unit-test suite for GRIT.')
-+ print('Options: %s' % repr(global_options))
-+ print('Arguments: %s' % repr(my_arguments))
-+ return 0
-diff --git a/tools/grit/grit/tool/transl2tc.py b/tools/grit/grit/tool/transl2tc.py
-new file mode 100644
-index 0000000000..45301bbf58
---- /dev/null
-+++ b/tools/grit/grit/tool/transl2tc.py
-@@ -0,0 +1,251 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''The 'grit transl2tc' tool.
-+'''
-+
-+from __future__ import print_function
-+
-+from grit import grd_reader
-+from grit import util
-+from grit.tool import interface
-+from grit.tool import rc2grd
-+
-+from grit.extern import tclib
-+
-+
-+class TranslationToTc(interface.Tool):
-+ '''A tool for importing existing translations in RC format into the
-+Translation Console.
-+
-+Usage:
-+
-+grit -i GRD transl2tc [-l LIMITS] [RCOPTS] SOURCE_RC TRANSLATED_RC OUT_FILE
-+
-+The tool needs a "source" RC file, i.e. in English, and an RC file that is a
-+translation of precisely the source RC file (not of an older or newer version).
-+
-+The tool also requires you to provide a .grd file (input file) e.g. using the
-+-i global option or the GRIT_INPUT environment variable. The tool uses
-+information from your .grd file to correct placeholder names in the
-+translations and ensure that only translatable items and translations still
-+being used are output.
-+
-+This tool will accept all the same RCOPTS as the 'grit rc2grd' tool. To get
-+a list of these options, run 'grit help rc2grd'.
-+
-+Additionally, you can use the -l option (which must be the first option to the
-+tool) to specify a file containing a list of message IDs to which output should
-+be limited. This is only useful if you are limiting the output to your XMB
-+files using the 'grit xmb' tool's -l option. See 'grit help xmb' for how to
-+generate a file containing a list of the message IDs in an XMB file.
-+
-+The tool will scan through both of the RC files as well as any HTML files they
-+refer to, and match together the source messages and translated messages. It
-+will output a file (OUTPUT_FILE) you can import directly into the TC using the
-+Bulk Translation Upload tool.
-+'''
-+
-+ def ShortDescription(self):
-+ return 'Import existing translations in RC format into the TC'
-+
-+ def Setup(self, globopt, args):
-+ '''Sets the instance up for use.
-+ '''
-+ self.SetOptions(globopt)
-+ self.rc2grd = rc2grd.Rc2Grd()
-+ self.rc2grd.SetOptions(globopt)
-+ self.limits = None
-+ if len(args) and args[0] == '-l':
-+ self.limits = util.ReadFile(args[1], 'utf-8').splitlines()
-+ args = args[2:]
-+ return self.rc2grd.ParseOptions(args, help_func=self.ShowUsage)
-+
-+ def Run(self, globopt, args):
-+ args = self.Setup(globopt, args)
-+
-+ if len(args) != 3:
-+ self.Out('This tool takes exactly three arguments:\n'
-+ ' 1. The path to the original RC file\n'
-+ ' 2. The path to the translated RC file\n'
-+ ' 3. The output file path.\n')
-+ return 2
-+
-+ grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
-+ grd.RunGatherers()
-+
-+ source_rc = util.ReadFile(args[0], self.rc2grd.input_encoding)
-+ transl_rc = util.ReadFile(args[1], self.rc2grd.input_encoding)
-+ translations = self.ExtractTranslations(grd,
-+ source_rc, args[0],
-+ transl_rc, args[1])
-+
-+ with util.WrapOutputStream(open(args[2], 'wb')) as output_file:
-+ self.WriteTranslations(output_file, translations.items())
-+
-+ self.Out('Wrote output file %s' % args[2])
-+
-+ def ExtractTranslations(self, current_grd, source_rc, source_path,
-+ transl_rc, transl_path):
-+ '''Extracts translations from the translated RC file, matching them with
-+ translations in the source RC file to calculate their ID, and correcting
-+ placeholders, limiting output to translateables, etc. using the supplied
-+ .grd file which is the current .grd file for your project.
-+
-+ If this object's 'limits' attribute is not None but a list, the output of
-+ this function will be further limited to include only messages that have
-+ message IDs in the 'limits' list.
-+
-+ Args:
-+ current_grd: grit.node.base.Node child, that has had RunGatherers() run
-+ on it
-+ source_rc: Complete text of source RC file
-+ source_path: Path to the source RC file
-+ transl_rc: Complete text of translated RC file
-+ transl_path: Path to the translated RC file
-+
-+ Return:
-+ { id1 : text1, '12345678' : 'Hello USERNAME, howzit?' }
-+ '''
-+ source_grd = self.rc2grd.Process(source_rc, source_path)
-+ self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % source_path)
-+ source_grd.SetOutputLanguage(current_grd.output_language)
-+ source_grd.SetDefines(current_grd.defines)
-+ source_grd.RunGatherers(debug=self.o.extra_verbose)
-+ transl_grd = self.rc2grd.Process(transl_rc, transl_path)
-+ transl_grd.SetOutputLanguage(current_grd.output_language)
-+ transl_grd.SetDefines(current_grd.defines)
-+ self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % transl_path)
-+ transl_grd.RunGatherers(debug=self.o.extra_verbose)
-+ self.VerboseOut('Done running gatherers for %s.\n' % transl_path)
-+
-+ # Proceed to create a map from ID to translation, getting the ID from the
-+ # source GRD and the translation from the translated GRD.
-+ id2transl = {}
-+ for source_node in source_grd:
-+ source_cliques = source_node.GetCliques()
-+ if not len(source_cliques):
-+ continue
-+
-+ assert 'name' in source_node.attrs, 'All nodes with cliques should have an ID'
-+ node_id = source_node.attrs['name']
-+ self.ExtraVerboseOut('Processing node %s\n' % node_id)
-+ transl_node = transl_grd.GetNodeById(node_id)
-+
-+ if transl_node:
-+ transl_cliques = transl_node.GetCliques()
-+ if not len(transl_cliques) == len(source_cliques):
-+ self.Out(
-+ 'Warning: Translation for %s has wrong # of cliques, skipping.\n' %
-+ node_id)
-+ continue
-+ else:
-+ self.Out('Warning: No translation for %s, skipping.\n' % node_id)
-+ continue
-+
-+ if source_node.name == 'message':
-+ # Fixup placeholders as well as possible based on information from
-+ # the current .grd file if they are 'TODO_XXXX' placeholders. We need
-+ # to fixup placeholders in the translated message so that it looks right
-+ # and we also need to fixup placeholders in the source message so that
-+ # its calculated ID will match the current message.
-+ current_node = current_grd.GetNodeById(node_id)
-+ if current_node:
-+ assert len(source_cliques) == len(current_node.GetCliques()) == 1
-+
-+ source_msg = source_cliques[0].GetMessage()
-+ current_msg = current_node.GetCliques()[0].GetMessage()
-+
-+ # Only do this for messages whose source version has not changed.
-+ if (source_msg.GetRealContent() != current_msg.GetRealContent()):
-+ self.VerboseOut('Info: Message %s has changed; skipping\n' % node_id)
-+ else:
-+ transl_msg = transl_cliques[0].GetMessage()
-+ transl_content = transl_msg.GetContent()
-+ current_content = current_msg.GetContent()
-+ source_content = source_msg.GetContent()
-+
-+ ok_to_fixup = True
-+ if (len(transl_content) != len(current_content)):
-+ # message structure of translation is different, don't try fixup
-+ ok_to_fixup = False
-+ if ok_to_fixup:
-+ for ix in range(len(transl_content)):
-+ if isinstance(transl_content[ix], tclib.Placeholder):
-+ if not isinstance(current_content[ix], tclib.Placeholder):
-+ ok_to_fixup = False # structure has changed
-+ break
-+ if (transl_content[ix].GetOriginal() !=
-+ current_content[ix].GetOriginal()):
-+ ok_to_fixup = False # placeholders have likely been reordered
-+ break
-+ else: # translated part is not a placeholder but a string
-+ if isinstance(current_content[ix], tclib.Placeholder):
-+ ok_to_fixup = False # placeholders have likely been reordered
-+ break
-+
-+ if not ok_to_fixup:
-+ self.VerboseOut(
-+ 'Info: Structure of message %s has changed; skipping.\n' % node_id)
-+ else:
-+ def Fixup(content, ix):
-+ if (isinstance(content[ix], tclib.Placeholder) and
-+ content[ix].GetPresentation().startswith('TODO_')):
-+ assert isinstance(current_content[ix], tclib.Placeholder)
-+ # Get the placeholder ID and example from the current message
-+ content[ix] = current_content[ix]
-+ for ix in range(len(transl_content)):
-+ Fixup(transl_content, ix)
-+ Fixup(source_content, ix)
-+
-+ # Only put each translation once into the map. Warn if translations
-+ # for the same message are different.
-+ for ix in range(len(transl_cliques)):
-+ source_msg = source_cliques[ix].GetMessage()
-+ source_msg.GenerateId() # needed to refresh ID based on new placeholders
-+ message_id = source_msg.GetId()
-+ translated_content = transl_cliques[ix].GetMessage().GetPresentableContent()
-+
-+ if message_id in id2transl:
-+ existing_translation = id2transl[message_id]
-+ if existing_translation != translated_content:
-+ original_text = source_cliques[ix].GetMessage().GetPresentableContent()
-+ self.Out('Warning: Two different translations for "%s":\n'
-+ ' Translation 1: "%s"\n'
-+ ' Translation 2: "%s"\n' %
-+ (original_text, existing_translation, translated_content))
-+ else:
-+ id2transl[message_id] = translated_content
-+
-+ # Remove translations for messages that do not occur in the current .grd
-+ # or have been marked as not translateable, or do not occur in the 'limits'
-+ # list (if it has been set).
-+ current_message_ids = current_grd.UberClique().AllMessageIds()
-+ for message_id in list(id2transl.keys()):
-+ if (message_id not in current_message_ids or
-+ not current_grd.UberClique().BestClique(message_id).IsTranslateable() or
-+ (self.limits and message_id not in self.limits)):
-+ del id2transl[message_id]
-+
-+ return id2transl
-+
-+ @staticmethod
-+ def WriteTranslations(output_file, translations):
-+ '''Writes the provided list of translations to the provided output file
-+ in the format used by the TC's Bulk Translation Upload tool. The file
-+ must be UTF-8 encoded.
-+
-+ Args:
-+ output_file: util.WrapOutputStream(open('bingo.out', 'wb'))
-+ translations: [ [id1, text1], ['12345678', 'Hello USERNAME, howzit?'] ]
-+
-+ Return:
-+ None
-+ '''
-+ for id, text in translations:
-+ text = text.replace('<', '&lt;').replace('>', '&gt;')
-+ output_file.write(id)
-+ output_file.write(' ')
-+ output_file.write(text)
-+ output_file.write('\n')
-diff --git a/tools/grit/grit/tool/transl2tc_unittest.py b/tools/grit/grit/tool/transl2tc_unittest.py
-new file mode 100644
-index 0000000000..22e937f9f2
---- /dev/null
-+++ b/tools/grit/grit/tool/transl2tc_unittest.py
-@@ -0,0 +1,133 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for the 'grit transl2tc' tool.'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+
-+from six import StringIO
-+
-+from grit.tool import transl2tc
-+from grit import grd_reader
-+from grit import util
-+
-+
-+def MakeOptions():
-+ from grit import grit_runner
-+ return grit_runner.Options()
-+
-+
-+class TranslationToTcUnittest(unittest.TestCase):
-+
-+ def testOutput(self):
-+ buf = StringIO()
-+ tool = transl2tc.TranslationToTc()
-+ translations = [
-+ ['1', 'Hello USERNAME, how are you?'],
-+ ['12', 'Howdie doodie!'],
-+ ['123', 'Hello\n\nthere\n\nhow are you?'],
-+ ['1234', 'Hello is > goodbye but < howdie pardner'],
-+ ]
-+ tool.WriteTranslations(buf, translations)
-+ output = buf.getvalue()
-+ self.failUnless(output.strip() == '''
-+1 Hello USERNAME, how are you?
-+12 Howdie doodie!
-+123 Hello
-+
-+there
-+
-+how are you?
-+1234 Hello is &gt; goodbye but &lt; howdie pardner
-+'''.strip())
-+
-+ def testExtractTranslations(self):
-+ path = util.PathFromRoot('grit/testdata')
-+ current_grd = grd_reader.Parse(StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_SIMPLE">
-+ One
-+ </message>
-+ <message name="IDS_PLACEHOLDER">
-+ <ph name="NUMBIRDS">%s<ex>3</ex></ph> birds
-+ </message>
-+ <message name="IDS_PLACEHOLDERS">
-+ <ph name="ITEM">%d<ex>1</ex></ph> of <ph name="COUNT">%d<ex>3</ex></ph>
-+ </message>
-+ <message name="IDS_REORDERED_PLACEHOLDERS">
-+ <ph name="ITEM">$1<ex>1</ex></ph> of <ph name="COUNT">$2<ex>3</ex></ph>
-+ </message>
-+ <message name="IDS_CHANGED">
-+ This is the new version
-+ </message>
-+ <message name="IDS_TWIN_1">Hello</message>
-+ <message name="IDS_TWIN_2">Hello</message>
-+ <message name="IDS_NOT_TRANSLATEABLE" translateable="false">:</message>
-+ <message name="IDS_LONGER_TRANSLATED">
-+ Removed document <ph name="FILENAME">$1<ex>c:\temp</ex></ph>
-+ </message>
-+ <message name="IDS_DIFFERENT_TWIN_1">Howdie</message>
-+ <message name="IDS_DIFFERENT_TWIN_2">Howdie</message>
-+ </messages>
-+ <structures>
-+ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
-+ <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
-+ </structures>
-+ </release>
-+ </grit>'''), path)
-+ current_grd.SetOutputLanguage('en')
-+ current_grd.RunGatherers()
-+
-+ source_rc_path = util.PathFromRoot('grit/testdata/source.rc')
-+ source_rc = util.ReadFile(source_rc_path, 'utf-8')
-+ transl_rc_path = util.PathFromRoot('grit/testdata/transl.rc')
-+ transl_rc = util.ReadFile(transl_rc_path, 'utf-8')
-+
-+ tool = transl2tc.TranslationToTc()
-+ output_buf = StringIO()
-+ globopts = MakeOptions()
-+ globopts.verbose = True
-+ globopts.output_stream = output_buf
-+ tool.Setup(globopts, [])
-+ translations = tool.ExtractTranslations(current_grd,
-+ source_rc, source_rc_path,
-+ transl_rc, transl_rc_path)
-+
-+ values = list(translations.values())
-+ output = output_buf.getvalue()
-+
-+ self.failUnless('Ein' in values)
-+ self.failUnless('NUMBIRDS Vogeln' in values)
-+ self.failUnless('ITEM von COUNT' in values)
-+ self.failUnless(values.count('Hallo') == 1)
-+ self.failIf('Dass war die alte Version' in values)
-+ self.failIf(':' in values)
-+ self.failIf('Dokument FILENAME ist entfernt worden' in values)
-+ self.failIf('Nicht verwendet' in values)
-+ self.failUnless(('Howdie' in values or 'Hallo sagt man' in values) and not
-+ ('Howdie' in values and 'Hallo sagt man' in values))
-+
-+ self.failUnless('XX01XX&SkraXX02XX&HaettaXX03XXThetta er "Klonk" sem eg fylaXX04XXgonkurinnXX05XXKlonk && er [good]XX06XX&HjalpXX07XX&Um...XX08XX' in values)
-+
-+ self.failUnless('I lagi' in values)
-+
-+ self.failUnless(output.count('Structure of message IDS_REORDERED_PLACEHOLDERS has changed'))
-+ self.failUnless(output.count('Message IDS_CHANGED has changed'))
-+ self.failUnless(output.count('Structure of message IDS_LONGER_TRANSLATED has changed'))
-+ self.failUnless(output.count('Two different translations for "Howdie"'))
-+ self.failUnless(output.count('IDD_DIFFERENT_LENGTH_IN_TRANSL has wrong # of cliques'))
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/unit.py b/tools/grit/grit/tool/unit.py
-new file mode 100644
-index 0000000000..7e96b699c3
---- /dev/null
-+++ b/tools/grit/grit/tool/unit.py
-@@ -0,0 +1,43 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''GRIT tool that runs the unit test suite for GRIT.'''
-+
-+from __future__ import print_function
-+
-+import getopt
-+import sys
-+import unittest
-+
-+try:
-+ import grit.test_suite_all
-+except ImportError:
-+ pass
-+from grit.tool import interface
-+
-+
-+class UnitTestTool(interface.Tool):
-+ '''By using this tool (e.g. 'grit unit') you run all the unit tests for GRIT.
-+This happens in the environment that is set up by the basic GRIT runner.'''
-+
-+ def ShortDescription(self):
-+ return 'Use this tool to run all the unit tests for GRIT.'
-+
-+ def ParseOptions(self, args):
-+ """Set this objects and return all non-option arguments."""
-+ own_opts, args = getopt.getopt(args, '', ('help',))
-+ for key, val in own_opts:
-+ if key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+ return args
-+
-+ def Run(self, opts, args):
-+ args = self.ParseOptions(args)
-+ if args:
-+ print('This tool takes no arguments.')
-+ return 2
-+
-+ return unittest.TextTestRunner(verbosity=2).run(
-+ grit.test_suite_all.TestSuiteAll())
-diff --git a/tools/grit/grit/tool/update_resource_ids/__init__.py b/tools/grit/grit/tool/update_resource_ids/__init__.py
-new file mode 100644
-index 0000000000..3006fbffab
---- /dev/null
-+++ b/tools/grit/grit/tool/update_resource_ids/__init__.py
-@@ -0,0 +1,305 @@
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+"""Package grit.tool.update_resource_ids
-+
-+Updates GRID resource_ids from linked GRD files, while preserving structure.
-+
-+A resource_ids file is a JSON dict (with Python comments) that maps GRD paths
-+to *items*. Item order is ignored by GRIT, but is important since it establishes
-+a narrative of item dependency (needs non-overlapping IDs) and mutual exclusion
-+(allows ID overlap). Example:
-+
-+{
-+ # The first entry in the file, SRCDIR, is special: It is a relative path from
-+ # this file to the base of your checkout.
-+ "SRCDIR": "../..",
-+
-+ # First GRD file. This entry is an "Item".
-+ "1.grd": {
-+ "messages": [400], # "Tag".
-+ },
-+ # Depends on 1.grd, i.e., 500 >= 400 + (# of IDs used in 1.grd).
-+ "2a.grd": {
-+ "includes": [500], # "Tag".
-+ "structures": [510], # "Tag" (etc.).
-+ },
-+ # Depends on 2a.grd.
-+ "3a.grd": {
-+ "includes": [1000],
-+ },
-+ # Depends on 2a.grd, but overlaps with 3b.grd due to mutually exclusivity.
-+ "3b.grd": {
-+ "includes": [1000],
-+ },
-+ # Depends on {3a.grd, 3b.grd}.
-+ "4.grd": {
-+ "META": {"join": 2}, # Hint for update_resource_ids.
-+ "structures": [1500],
-+ },
-+ # Depends on 1.grd but overlaps with 2a.grd.
-+ "2b.grd": {
-+ "includes": [500],
-+ "structures": [540],
-+ },
-+ # Depends on {4.grd, 2b.grd}.
-+ "5.grd": {
-+ "META": {"join": 2}, # Hint for update_resource_ids.
-+ "includes": [600],
-+ },
-+ # Depends on 5.grd. File is generated, so hint is needed for sizes.
-+ "<(SHARED_INTERMEDIATE_DIR)/6.grd": {
-+ "META": {"sizes": {"includes": [10]}},
-+ "includes": [700],
-+ },
-+}
-+
-+The "structure" within a resouces_ids file are as follows:
-+1. Comments and spacing.
-+2. Item ordering, to establish dependency and grouping.
-+3. Special provision to allow ID overlaps from mutual exclusion.
-+
-+This module parses a resource_ids file, reads ID usages from GRD files it refers
-+to, and generates an updated version of the resource_ids file while preserving
-+structure elements 1-3 stated above.
-+"""
-+
-+from __future__ import print_function
-+
-+import collections
-+import getopt
-+import os
-+import shutil
-+import sys
-+import tempfile
-+
-+from grit.tool import interface
-+from grit.tool.update_resource_ids import assigner, common, parser, reader
-+
-+
-+def _ReadData(input_file):
-+ if input_file == '-':
-+ data = sys.stdin.read()
-+ file_dir = os.getcwd()
-+ else:
-+ with open(input_file, 'rt') as f:
-+ data = f.read()
-+ file_dir = os.path.dirname(input_file)
-+ return data, file_dir
-+
-+
-+def _MultiReplace(data, repl):
-+ """Multi-replacement of text |data| by ranges and replacement text.
-+
-+ Args:
-+ data: Original text.
-+ repl: List of (lo, hi, s) tuples, specifying that |data[lo:hi]| should be
-+ replaced with |s|. The ranges must be inside |data|, and not overlap.
-+ Returns: New text.
-+ """
-+ res = []
-+ prev = 0
-+ for (lo, hi, s) in sorted(repl):
-+ if prev < lo:
-+ res.append(data[prev:lo])
-+ res.append(s)
-+ prev = hi
-+ res.append(data[prev:])
-+ return ''.join(res)
-+
-+
-+def _WriteFileIfChanged(output, new_data):
-+ if not output:
-+ sys.stdout.write(new_data)
-+ return
-+
-+ # Avoid touching outputs if file contents has not changed so that ninja
-+ # does not rebuild dependent when not necessary.
-+ if os.path.exists(output) and _ReadData(output)[0] == new_data:
-+ return
-+
-+ # Write to a temporary file to ensure atomic changes.
-+ with tempfile.NamedTemporaryFile('wt', delete=False) as f:
-+ f.write(new_data)
-+ shutil.move(f.name, output)
-+
-+
-+class _Args:
-+ """Encapsulated arguments for this module."""
-+ def __init__(self):
-+ self.add_header = False
-+ self.analyze_inputs = False
-+ self.count = False
-+ self.depfile = None
-+ self.fake = False
-+ self.input = None
-+ self.naive = False
-+ self.output = None
-+ self.parse = False
-+ self.tokenize = False
-+
-+ @staticmethod
-+ def Parse(raw_args):
-+ own_opts, raw_args = getopt.getopt(raw_args, 'o:cpt', [
-+ 'add-header',
-+ 'analyze-inputs',
-+ 'count',
-+ 'depfile=',
-+ 'fake',
-+ 'naive',
-+ 'parse',
-+ 'tokenize',
-+ ])
-+ args = _Args();
-+ if not len(raw_args) == 1:
-+ print('grit update_resource_ids takes exactly one argument, the path to '
-+ 'the resource ids file.')
-+ return 2
-+ args.input = raw_args[0]
-+ for (key, val) in own_opts:
-+ if key == '-o':
-+ args.output = val
-+ elif key == '--add-header':
-+ args.add_header = True
-+ elif key == '--analyze-inputs':
-+ args.analyze_inputs = True
-+ elif key in ('--count', '-c'):
-+ args.count = True
-+ elif key == '--depfile':
-+ args.depfile = val
-+ elif key == '--fake':
-+ args.fake = True
-+ elif key == '--naive':
-+ args.naive = True
-+ elif key in ('--parse', '-p'):
-+ args.parse = True
-+ elif key in ('--tokenize', '-t'):
-+ args.tokenize = True
-+ return args
-+
-+
-+class UpdateResourceIds(interface.Tool):
-+ """Updates all start IDs in an resource_ids file by reading all GRD files it
-+refers to, estimating the number of required IDs of each type, then rewrites
-+start IDs while preserving structure.
-+
-+Usage: grit update_resource_ids [--parse|-p] [--read-grd|-r] [--tokenize|-t]
-+ [--naive] [--fake] [-o OUTPUT_FILE]
-+ [--analyze-inputs] [--depfile DEPFILE]
-+ [--add-header] RESOURCE_IDS_FILE
-+
-+RESOURCE_IDS_FILE is the path of the input resource_ids file.
-+
-+The -o option redirects output (default stdout) to OUPTUT_FILE, which can also
-+be RESOURCE_IDS_FILE.
-+
-+Other options:
-+
-+ -E NAME=VALUE Sets environment variable NAME to VALUE (within grit).
-+
-+ --count|-c Parses RESOURCE_IDS_FILE, reads the GRD files, and prints
-+ required sizes.
-+
-+ --fake For testing: Skips reading GRD files, and assigns 10 as the
-+ usage of every tag.
-+
-+ --naive Use naive coarse assigner.
-+
-+ --parse|-p Parses RESOURCE_IDS_FILE and dumps its nodes to console.
-+
-+ --tokenize|-t Tokenizes RESOURCE_IDS_FILE and reprints it as syntax-
-+ highlighted output.
-+
-+ --depfile=DEPFILE Write out a depfile for ninja to know about dependencies.
-+ --analyze-inputs Writes dependencies to stdout.
-+ --add-header Adds a "THIS FILE IS GENERATED" header to the output.
-+"""
-+
-+ def __init(self):
-+ super(UpdateResourceIds, self).__init__()
-+
-+ def ShortDescription(self):
-+ return 'Updates a resource_ids file based on usage, preserving structure'
-+
-+ def _DumpTokens(self, data, tok_gen):
-+ # Reprint |data| with syntax highlight.
-+ color_map = {
-+ '#': common.Color.GRAY,
-+ 'S': common.Color.CYAN,
-+ '0': common.Color.RED,
-+ '{': common.Color.YELLOW,
-+ '}': common.Color.YELLOW,
-+ '[': common.Color.GREEN,
-+ ']': common.Color.GREEN,
-+ ':': common.Color.MAGENTA,
-+ ',': common.Color.MAGENTA,
-+ }
-+ for t, lo, hi in tok_gen:
-+ c = color_map.get(t, common.Color.NONE)
-+ sys.stdout.write(c(data[lo:hi]))
-+
-+ def _DumpRootObj(self, root_obj):
-+ print(root_obj)
-+
-+ def _DumpResourceCounts(self, usage_gen):
-+ tot = collections.Counter()
-+ for item, tag_name_to_usage in usage_gen:
-+ c = common.Color.YELLOW if item.grd.startswith('<') else common.Color.CYAN
-+ print('%s: %r' % (c(item.grd), dict(tag_name_to_usage)))
-+ tot += collections.Counter(tag_name_to_usage)
-+ print(common.Color.GRAY('-' * 80))
-+ print('%s: %r' % (common.Color.GREEN('Total'), dict(tot)))
-+ print('%s: %d' % (common.Color.GREEN('Grand Total'), sum(tot.values())))
-+
-+ def Run(self, opts, raw_args):
-+ self.SetOptions(opts)
-+
-+ args = _Args.Parse(raw_args)
-+ data, file_dir = _ReadData(args.input)
-+
-+ tok_gen = parser.Tokenize(data)
-+ if args.tokenize:
-+ return self._DumpTokens(data, tok_gen)
-+
-+ root_obj = parser.ResourceIdParser(data, tok_gen).Parse()
-+ if args.parse:
-+ return self._DumpRootObj(root_obj)
-+ item_list = common.BuildItemList(root_obj)
-+
-+ src_dir = os.path.normpath(os.path.join(file_dir, root_obj['SRCDIR'].val))
-+ seen_files = set()
-+ usage_gen = reader.GenerateResourceUsages(item_list, src_dir, args.fake,
-+ seen_files)
-+ if args.count:
-+ return self._DumpResourceCounts(usage_gen)
-+ for item, tag_name_to_usage in usage_gen:
-+ item.SetUsages(tag_name_to_usage)
-+
-+ if args.analyze_inputs:
-+ print('\n'.join(sorted(seen_files)))
-+ return 0
-+
-+ new_ids_gen = assigner.GenerateNewIds(item_list, args.naive)
-+ # Create replacement specs usable by _MultiReplace().
-+ repl = [(tag.lo, tag.hi, str(new_id)) for tag, new_id in new_ids_gen]
-+ rel_input_dir = args.input
-+ # Update "SRCDIR" entry if output is specified.
-+ if args.output:
-+ new_srcdir = os.path.relpath(src_dir, os.path.dirname(args.output))
-+ repl.append((root_obj['SRCDIR'].lo, root_obj['SRCDIR'].hi,
-+ repr(new_srcdir)))
-+ rel_input_dir = os.path.join('$SRCDIR',
-+ os.path.relpath(rel_input_dir, new_srcdir))
-+
-+ new_data = _MultiReplace(data, repl)
-+ if args.add_header:
-+ header = []
-+ header.append('# GENERATED FILE.')
-+ header.append('# Edit %s instead.' % rel_input_dir)
-+ header.append('#' * 80)
-+ new_data = '\n'.join(header + ['']) + new_data
-+ _WriteFileIfChanged(args.output, new_data)
-+
-+ if args.depfile:
-+ deps_data = '{}: {}'.format(args.output, ' '.join(sorted(seen_files)))
-+ _WriteFileIfChanged(args.depfile, deps_data)
-diff --git a/tools/grit/grit/tool/update_resource_ids/assigner.py b/tools/grit/grit/tool/update_resource_ids/assigner.py
-new file mode 100644
-index 0000000000..6cd46031a6
---- /dev/null
-+++ b/tools/grit/grit/tool/update_resource_ids/assigner.py
-@@ -0,0 +1,286 @@
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+"""Assign IDs to resource_ids file based on usage, while preserving structure.
-+
-+resource_ids assignment is divided into two parts:
-+(A) Coarse assignment: Assigns start IDs of items.
-+(B) Quota assignment: Assigns per-tag ID allotments for a given item, allowing
-+ padding for IDs.
-+
-+These parts are interdependent: Start IDs (A) of an item depends on ID
-+allotments (B) of *other* items; and ID allotment (B) of an item depends on its
-+start IDs (A) to compute alignment.
-+
-+(B) hides padding and alignment details of tags so that (A) can be abstracted
-+into the graph construction and traversal problem in DagCoarseIdAssigner.
-+"""
-+
-+import math
-+
-+from grit.tool.update_resource_ids import common
-+
-+
-+class Aligner:
-+ """Helper to allot IDs, given start ID and ID usage.
-+
-+ Args:
-+ expand: Scale factor relative to ID usage. Must be >= 1.0.
-+ slack: Minimum number of reserved ID at end. Must be >= 0.
-+ align: ID alignment of results. Must be >= 1.
-+ """
-+
-+ def __init__(self, expand=1.0, slack=0, align=1):
-+ assert expand >= 1.0 and slack >= 0 and align >= 1
-+ self._expand = expand
-+ self._slack = slack
-+ self._align = align
-+
-+ def Calc(self, cur_id, usage):
-+ quota = max(int(math.ceil(usage * self._expand)), usage + self._slack)
-+ return common.AlignUp(cur_id + quota, self._align)
-+
-+
-+class QuotaAssigner:
-+ """Main class for (B), for ID allotment of tags for an item."""
-+
-+ def __init__(self, aligner):
-+ self._aligner = aligner
-+
-+ def Gen(self, item, start_id):
-+ """Generates per-tag *end* ID in |item|, succeeding |start_id|."""
-+ cur_id = start_id
-+ for tag in item.tags: # Sorted by |tag.lo|.
-+ cur_id = self._aligner.Calc(cur_id, tag.usage)
-+ yield tag, cur_id
-+
-+
-+class BaseCoarseIdAssigner(object):
-+ """Base class for coarse assignment."""
-+
-+ def __init__(self, item_list, align):
-+ self._item_list = item_list
-+ self._align = align
-+
-+ def GenStartIds(self):
-+ """Visits |_item_list| and yields (|item|, new |start_id|).
-+
-+ Visit follows dependency order: If item B succeeds item A, then A is visited
-+ before B. Caller must call FeedWeight() to assign ID allotment.
-+ """
-+ raise NotImplementedError()
-+
-+ def FeedWeight(self, item, weight):
-+ """Callback to assign number of IDs allotted to |item|."""
-+ raise NotImplementedError()
-+
-+
-+class NaiveCoarseIdAssigner(BaseCoarseIdAssigner):
-+ """CoarseIdAssigner that assigns item with non-overlapping start IDs."""
-+
-+ def __init__(self, item_list, align):
-+ super(NaiveCoarseIdAssigner, self).__init__(item_list, align)
-+ first_id = self._item_list[0].tags[0].id
-+ self._cur_id = common.AlignUp(first_id, self._align)
-+
-+ def GenStartIds(self):
-+ """Visits items in array order."""
-+ for item in self._item_list:
-+ yield item, self._cur_id
-+
-+ def FeedWeight(self, item, weight):
-+ self._cur_id = common.AlignUp(self._cur_id + weight, self._align)
-+
-+
-+class DagCoarseIdAssigner(BaseCoarseIdAssigner):
-+ """CoarseIdAssigner that preserves existing structure.
-+
-+Start ID assignment in resource_ids is structured a Series-Parallel Graph, which
-+is a directed, acyclic multi-graph generated by the following:
-+* Start: Single directed edge. S <-- T.
-+* Operation 1: A <-- B becomes A <-- C <-- B.
-+* Operation 2: A <-- B becomes A <== B (add parallel edge).
-+
-+Each vertex (A, B, ...) is a start ID. S = globally minimal ID. T = \infty is an
-+implicit sentinel. Each edge maps to an item, and edge weight is ID allotment.
-+The edge A <-- B means "A's ID assignment needs to be determined before B's"
-+(i.e., "B depends on A"), and requires A < B.
-+
-+resource_ids stores a "flattened" representation of the graph, as a list of
-+items (with meta data). Thus coarse ID assignment consists of the following:
-+(1) Process list of items (with old start ID and meta data) to rebuild graph.
-+(2) Traverse graph in an order that satisfies dependencies.
-+(3) When vertex A has its ID assigned, the weight of each edge "A <--" (i.e., an
-+ item) can have its weight (ID allotment) computed via quota assignment of A.
-+(4) New start IDs satisfy A + w <= B for each edge A <-- B with weight w > 0.
-+
-+The key algorithm challenge is (1). Note that it does not need weight details,
-+so we only assume A < B whenever A <-- B. Now we're faced with 2 subproblems:
-+(1a) How to represent the graph as a list of integers (with meta data)?
-+(1b) Given the list representation, how to recover the graph?
-+
-+For (1a), we start with DFS traversal of the (transposed, i.e., reversed) graph
-+starting from S, and apply the following:
-+* For each edge A <-- B traversed, emit A into sequence,
-+* Traverse a B <-- Y only when all X <-- B have been traversed.
-+
-+The resulting sequence has the length as the number of edges, and has the useful
-+property that a vertex's dependencies always appear before the vertex itself!
-+Note this the sentinel T is omitted.
-+
-+Example 1:
-+ S <-- A <-- B <-- C <-- T => "SABC".
-+
-+Example 2:
-+ S <-- A <-- B <-- C <-- T => "SA|AB|SDEC|SF",
-+ | | | | | or "SF|SA|AB|SDEC",
-+ | + <-- + | | or "SDE|SA|ABC|SF",
-+ | | | or "SF|SDE|SA|ABC".
-+ + <---D <-- E <---+ |
-+ | |
-+ + <-- F <---------------+
-+
-+Here, "X|Y" denotes backtracking between visiting X and visiting Y. This appears
-+if and only if X >= Y, so "|" an optional (but illustrative) character that's
-+not in the actual output. We will use it consistently in comments, and so the
-+absence of "|" denotes the converse. For example, "XY" implies X < Y.
-+
-+In terms of the basic operations:
-+* Start: S <-- T => "S".
-+* Operation 1: "...AB..." => "...ACB..." (or "...A" => "...AB").
-+* Operation 2: "...AB..." => "...A|AB..." (or "...A" => "...A|A").
-+
-+For Example 2, a viable "evolution path" is:
-+"S" => "S|S" => "SC|S" => "S|SC|S" => "SA|SC|S" => "SAB|SC|S" => "SA|AB|SC|S"
-+ => "SA|AB|SDC|S" => "SA|AB|SDEC|S" => "SA|AB|SDEC|SF".
-+(Alternative: "S|S" => "S|SC" => etc.).
-+
-+Note: {A, ...} are *unlabelled* integers, and "spurious equalities" such as
-+A = D or A = F can occur!
-+
-+For (1b), we wish to build the graph from the sequence. This requires (1a) to be
-+injective (up to isomorphism). Unfortunately, this does not always hold.
-+Example:
-+ S <-- A <-- C <-- D <-- T => "SA|SBCD".
-+ | |
-+ + <-- B <---+
-+vs.
-+ S <----- A <----- D <-- T => "SA|SBCD".
-+ | |
-+ + <-- B <-- C <---+
-+
-+To fix this, we prepend a "join" label (*) to each vertex that has multiple
-+dependencies. With this, the example above produce different results:
-+ "SA|SB*CD" != "SA|SBC*D".
-+
-+Unfortunately, this is also inadequate. Example:
-+ S <-------- B <-- T => "S|S|S|S*A*B",
-+ | |
-+ + <---------+
-+ | |
-+ + <-- A <---+
-+ | |
-+ + <---+
-+vs.
-+ S <-------- B <-- T => "S|S|S|S*A*B".
-+ | |
-+ + <---A <---+
-+ | |
-+ + <---+
-+ | |
-+ + <---+
-+
-+To fix this, we also label the number of dependencies. In text representation,
-+we just show multiple (#dependencies - 1) copies of '*'. Now we have:
-+ "S|S|S|S*A**B" != "S|S|S|S**A*B".
-+
-+The "join" label with count adequately addresses the issue (proof omitted). In
-+the resource_ids files, these are stored as the "join" field of an item's meta
-+data.
-+
-+Additional comments for (1b) and other steps are detailed below.
-+"""
-+
-+ class DagNode:
-+ """An element of the implicit graph, corresponding to an item.
-+
-+ This actually represents an edge-vertex pair, corresponding to an item.
-+ A vertex is represented by a collection of DagNode that uses |sib| to link
-+ to a "representative node". The representative node, in turn, holds the list
-+ of all |deps| (dependencies) of the vertex.
-+ """
-+
-+ def __init__(self, item, old_id):
-+ self.item = item
-+ self.old_id = old_id
-+ self.new_id = None
-+ self.weight = None
-+
-+ def __init__(self, item_list, align):
-+ super(DagCoarseIdAssigner, self).__init__(item_list, align)
-+ self._node_dict = {} # Maps from |lo| to item.
-+
-+ def GenStartIds(self):
-+ """Traverses implicit graph and yields new IDs.
-+
-+ Algorithm: Process |old_id| of items sequentially. Successive items A and B
-+ can be "AB" (A < B), "A*...B" (A < B), or "A|B" (A >= B). "AB" and "A*...B"
-+ imply A <-- B, and are accumulated in |trace|. "A|B" are jumps that rewinds
-+ |trace| to the latest B (must exist), and A is pushed into |jumps|. A join
-+ "A*...B" also pops |num_join - 1| items {X_i} in |jump|, and X_i <-- B. In
-+ the end, unprocessed elements in |jumps| all link to sentinel T, and can be
-+ ignored.
-+ """
-+ # DagNode stack of "A" when "AB" is found (increasing |old_id|).
-+ trace = []
-+ # DagNode stack of "A" when "A|B" jumps is found.
-+ jumps = []
-+ for item in self._item_list: # Sorted by |lo|.
-+ meta = item.meta
-+ # |num_join| indicates "*" in "A*...B", and specify B's dependencies: +1
-+ # from A, and +count("*") from |jumps|.
-+ num_join = meta['join'].val if meta and 'join' in meta else None
-+ node = DagCoarseIdAssigner.DagNode(item, item.tags[0].id)
-+ self._node_dict[item.lo] = node
-+ if trace:
-+ if trace[-1].old_id >= node.old_id: # "A|B".
-+ if num_join:
-+ raise ValueError('Cannot join on jump: %d' % node.old_id)
-+ jumps.append(trace[-1]) # Add A to |jumps|, for later join.
-+ while trace and trace[-1].old_id > node.old_id: # Rewind to find B.
-+ trace.pop()
-+ if not trace or trace[-1].old_id != node.old_id: #
-+ raise ValueError('Cannot jump to unvisited: %d' % node.old_id)
-+ node.new_id = trace.pop().new_id # Copy B & remove. Will re-add B.
-+ else: # "AB" or "A*...B".
-+ node.new_id = trace[-1].new_id + trace[-1].weight # A --> B
-+ if num_join: # "A*...B".
-+ for _ in range(1, num_join):
-+ t = jumps.pop()
-+ node.new_id = max(node.new_id, t.new_id + t.weight) # X_i --> B.
-+ else:
-+ node.new_id = node.old_id # Initial S.
-+ trace.append(node) # Add B.
-+ align = meta['align'].val if meta and 'align' in meta else self._align
-+ node.new_id = common.AlignUp(node.new_id, align)
-+ yield node.item, node.new_id
-+ # Expect caller to calling FreedWeight() and update |node.weight|.
-+
-+ def FeedWeight(self, item, weight):
-+ self._node_dict[item.lo].weight = weight
-+
-+
-+def GenerateNewIds(item_list, use_naive):
-+ """Visits all tags in |item_list| and generates new ids.
-+
-+ New ids are generated based on old ids and usages.
-+ """
-+ Assigner = NaiveCoarseIdAssigner if use_naive else DagCoarseIdAssigner
-+ coarse_id_assigner = Assigner(item_list, 10)
-+ quota_assigner = QuotaAssigner(Aligner(expand=1.15, slack=3, align=10))
-+ for item, start_id in coarse_id_assigner.GenStartIds(): # Topo-sorted.
-+ cur_id = start_id
-+ for tag, next_id in quota_assigner.Gen(item, start_id): # Sorted by |lo|.
-+ yield tag, cur_id
-+ cur_id = next_id
-+ coarse_id_assigner.FeedWeight(item, next_id - start_id)
-diff --git a/tools/grit/grit/tool/update_resource_ids/assigner_unittest.py b/tools/grit/grit/tool/update_resource_ids/assigner_unittest.py
-new file mode 100644
-index 0000000000..164d820762
---- /dev/null
-+++ b/tools/grit/grit/tool/update_resource_ids/assigner_unittest.py
-@@ -0,0 +1,154 @@
-+#!/usr/bin/env python
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import traceback
-+import unittest
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../..'))
-+
-+from grit.tool.update_resource_ids import assigner, common, parser
-+
-+# |spec| format: A comma-separated list of (old) start IDs. Modifiers:
-+# * Prefix with n '*' to assign the item's META "join" field to n + 1.
-+# * Suffix with "+[usage]" to assign |usage| for the item (else default=10)
-+
-+
-+def _RenderTestResourceId(spec):
-+ """Renders barebone resource_ids data based on |spec|."""
-+ data = '{"SRCDIR": ".",'
-+ for i, tok in enumerate(spec.split(',')):
-+ num_star = len(tok) - len(tok.lstrip('*'))
-+ tok = tok[num_star:]
-+ meta = '"META":{"join": %d},' % (num_star + 1) if num_star else ''
-+ start_id = tok.split('+')[0] # Strip '+usage'.
-+ data += '"foo%d.grd": {%s"includes": [%s]},' % (i, meta, start_id)
-+ data += '}'
-+ return data
-+
-+
-+def _CreateTestItemList(spec):
-+ """Creates list of ItemInfo based on |spec|."""
-+ data = _RenderTestResourceId(spec)
-+ item_list = common.BuildItemList(
-+ parser.ResourceIdParser(data, parser.Tokenize(data)).Parse())
-+ # Assign usages from "id+usage", default to 10.
-+ for i, tok in enumerate(spec.split(',')):
-+ item_list[i].tags[0].usage = int((tok.split('+') + ['10'])[1])
-+ return item_list
-+
-+
-+def _RunCoarseIdAssigner(spec):
-+ item_list = _CreateTestItemList(spec)
-+ coarse_id_assigner = assigner.DagCoarseIdAssigner(item_list, 1)
-+ new_id_list = [] # List of new IDs, to check ID assignment.
-+ new_spec_list = [] # List of new tokens to construct new |spec|.
-+ for item, start_id in coarse_id_assigner.GenStartIds(): # Topo-sorted..
-+ new_id_list.append(str(start_id))
-+ meta = item.meta
-+ num_join = meta['join'].val if meta and 'join' in meta else 0
-+ t = '*' * max(0, num_join - 1)
-+ t += str(start_id)
-+ t += '' if item.tags[0].usage == 10 else '+' + str(item.tags[0].usage)
-+ new_spec_list.append((item.lo, t))
-+ coarse_id_assigner.FeedWeight(item, item.tags[0].usage)
-+ new_spec = ','.join(s for _, s in sorted(new_spec_list))
-+ return ','.join(new_id_list), new_spec
-+
-+
-+class AssignerUnittest(unittest.TestCase):
-+
-+ def testDagAssigner(self):
-+ test_cases = [
-+ # Trivial.
-+ ('0', '0'),
-+ ('137', '137'),
-+ ('5,15', '5,6'),
-+ ('11,18', '11+7,12'),
-+ ('5,5', '5,5'),
-+ # Series only.
-+ ('0,10,20,30,40', '0,1,2,3,4'),
-+ ('5,15,25,35,45,55', '5,6,7,8,9,10'),
-+ ('5,15,25,35,45,55', '5,7,100,101,256,1001'),
-+ ('0,10,20,45,85', '0,1,2+25,3+40,4'),
-+ # Branching with and without join.
-+ ('0,0,10,20,20,30,40', '0,0,1,2,2,3,4'),
-+ ('0,0,10,20,20,30,40', '0,0,*1,2,2,*3,4'),
-+ ('0,0,2,12,12,16,26', '0+4,0+2,1,2+8,2+4,3,4'),
-+ ('0,0,4,14,14,22,32', '0+4,0+2,*1,2+8,2+4,*3,4'),
-+ # Wide branching with and without join.
-+ ('0,10,10,10,10,10,10,20,30', '0,1,1,1,1,1,1,2,3'),
-+ ('0,10,10,10,10,10,10,20,30', '0,1,1,1,1,1,1,*****2,3'),
-+ ('0,2,2,2,2,2,2,7,17', '0+2,1+4,1+19,1,1+4,1+2,1+5,2,3'),
-+ ('0,2,2,2,2,2,2,21,31', '0+2,1+4,1+19,1,1+4,1+2,1+5,*****2,3'),
-+ # Expanding different branch, without join.
-+ ('0,10,10,10,60,70,80', '0,1+15,1+15,1+50,2,3,4'),
-+ ('0,10,10,10,25,35,45', '0,1+15,1+50,1+15,2,3,4'),
-+ ('0,10,10,10,25,35,45', '0,1+50,1+15,1+15,2,3,4'),
-+ # ... with join.
-+ ('0,10,10,10,60,70,80', '0,1+15,1+15,1+50,**2,3,4'),
-+ ('0,10,10,10,60,70,80', '0,1+15,1+50,1+15,**2,3,4'),
-+ ('0,10,10,10,60,70,80', '0,1+50,1+15,1+15,**2,3,4'),
-+ # ... with alternative join.
-+ ('0,10,10,10,60,70,80', '0,1+15,1+15,1+50,2,**3,4'),
-+ ('0,10,10,10,25,60,70', '0,1+15,1+50,1+15,2,**3,4'),
-+ ('0,10,10,10,25,60,70', '0,1+50,1+15,1+15,2,**3,4'),
-+ # Examples from assigner.py.
-+ ('0,10,10,20,0,10,20,30,0,10',
-+ '0,1,1,*2,0,4,5,*6,0,7'), # SA|AB|SDEC|SF
-+ ('0,10,0,10,20,30', '0,1,0,2,*3,4'), # SA|SB*CD
-+ ('0,10,0,10,20,30', '0,1,0,2,3,*4'), # SA|SBC*D
-+ ('0,7,0,5,11,21', '0+7,1+4,0+5,2+3,*3,4'), # SA|SB*CD
-+ ('0,7,0,5,8,18', '0+7,1+4,0+5,2+3,3,*4'), # SA|SBC*D
-+ ('0,0,0,0,10,20', '0,0,0,0,*1,**2'), # S|S|S|S*A**B
-+ ('0,0,0,0,10,20', '0,0,0,0,**1,*2'), # S|S|S|S**A*B
-+ ('0,0,0,0,6,16', '0+8,0+7,0+6,0+5,*1,**2'), # S|S|S|S*A**B
-+ ('0,0,0,0,7,17', '0+8,0+7,0+6,0+5,**1,*2'), # S|S|S|S**A*B
-+ # Long branches without join.
-+ ('0,10,0,0,10,20,0,10,20,30', '0,1,0,0,1,2,0,1,2,3'),
-+ ('0,30,0,0,20,30,0,10,13,28', '0+30,1,0+50,0+20,1,2+17,0,1+3,2+15,3'),
-+ # Long branches with join.
-+ ('0,10,0,0,10,20,0,10,20,30', '0,1,0,0,1,2,0,1,2,***3'),
-+ ('0,30,0,0,20,30,0,10,13,50',
-+ '0+30,1,0+50,0+20,1,2+17,0,1+3,2+15,***3'),
-+ # 2-level hierarchy.
-+ ('0,10,10,20,0,10,10,20,30', '0,1,1,*2,0,1,1,*2,*3'),
-+ ('0,2,2,10,0,3,3,6,34', '0+2,1+5,1+8,*2+24,0+3,1+2,1+3,*2+27,*3'),
-+ ('0,2,2,10,0,3,3,6,34', '0+2,1+5,1+8,*2+24,0+3,1+2,1+3,*2+28,*3'),
-+ ('0,2,2,10,0,3,3,6,35', '0+2,1+5,1+8,*2+24,0+3,1+2,1+3,*2+29,*3'),
-+ # Binary hierarchy.
-+ ('0,0,10,0,0,10,20,0,0,10,0,0,10,20,30',
-+ '0,0,*1,0,0,*1,*2,0,0,*1,0,0,*1,*2,*3'),
-+ ('0,0,2,0,0,5,11,0,0,8,0,0,5,14,18',
-+ '0+1,0+2,*1+3,0+4,0+5,*1+6,*2+7,0+8,0+7,*1+6,0+5,0+4,*1+3,*2+2,*3+1'),
-+ # Joining from different heads.
-+ ('0,10,20,30,40,30,20,10,0,50', '0,1,2,3,4,3,2,1,0,****5'),
-+ # Miscellaneous.
-+ ('0,1,0,11', '0+1,1,0,*1'),
-+ ]
-+ for exp, spec in test_cases:
-+ try:
-+ actual, new_spec = _RunCoarseIdAssigner(spec)
-+ self.failUnlessEqual(exp, actual)
-+ # Test that assignment is idempotent.
-+ actual2, new_spec2 = _RunCoarseIdAssigner(new_spec)
-+ self.failUnlessEqual(actual, actual2)
-+ self.failUnlessEqual(new_spec, new_spec2)
-+ except Exception as e:
-+ print(common.Color.RED(traceback.format_exc().rstrip()))
-+ print('Failed spec: %s' % common.Color.CYAN(spec))
-+ print(' Expected: %s' % common.Color.YELLOW(exp))
-+ print(' Actual: %s' % common.Color.YELLOW(actual))
-+ if new_spec != new_spec2:
-+ print('Not idempotent')
-+ if isinstance(e, AssertionError):
-+ raise e
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/tool/update_resource_ids/common.py b/tools/grit/grit/tool/update_resource_ids/common.py
-new file mode 100644
-index 0000000000..004d8aa0e3
---- /dev/null
-+++ b/tools/grit/grit/tool/update_resource_ids/common.py
-@@ -0,0 +1,101 @@
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+
-+def AlignUp(v, align):
-+ return (v + align - 1) // align * align
-+
-+
-+def StripPlural(s):
-+ assert s.endswith('s'), 'Expect %s to be plural' % s
-+ return s[:-1]
-+
-+
-+class Color:
-+
-+ def _MakeColor(code):
-+ t = '\033[' + code + 'm%s\033[0m'
-+ return lambda s: t % s
-+
-+ NONE = staticmethod(lambda s: s)
-+ RED = staticmethod(_MakeColor('31'))
-+ GREEN = staticmethod(_MakeColor('32'))
-+ YELLOW = staticmethod(_MakeColor('33'))
-+ BLUE = staticmethod(_MakeColor('34'))
-+ MAGENTA = staticmethod(_MakeColor('35'))
-+ CYAN = staticmethod(_MakeColor('36'))
-+ WHITE = staticmethod(_MakeColor('37'))
-+ GRAY = staticmethod(_MakeColor('30;1'))
-+
-+
-+class TagInfo:
-+ """Stores resource_ids tag entry (e.g., {"includes": 100} pair)."""
-+
-+ def __init__(self, raw_key, raw_value):
-+ """TagInfo Constructor.
-+
-+ Args:
-+ raw_key: parser.AnnotatedValue for the parsed key, e.g., "includes".
-+ raw_value: parser.AnnotatedValue for the parsed value, e.g., 100.
-+ """
-+ # Tag name, e.g., 'include' (no "s" at end).
-+ self.name = StripPlural(raw_key.val)
-+ # |len(raw_value) > 1| is possible, e.g., see grd_reader_unittest.py's
-+ # testAssignFirstIdsMultipleMessages. This feature seems unused though.
-+ # TODO(huangs): Reconcile this (may end up removing multi-value feature).
-+ assert len(raw_value) == 1
-+ # Inclusive start *position* of the tag's start ID in resource_ids.
-+ self.lo = raw_value[0].lo
-+ # Exclusive end *position* of the tag's start ID in resource_ids.
-+ self.hi = raw_value[0].hi
-+ # The tag's start ID. Initially the old value, but may be reassigned to new.
-+ self.id = raw_value[0].val
-+ # The number of IDs the tag uses, to be assigned by ItemInfo.SetUsages().
-+ self.usage = None
-+
-+
-+class ItemInfo:
-+ """resource_ids item, containing multiple TagInfo."""
-+
-+ def __init__(self, lo, grd, raw_item):
-+ # Inclusive start position of the item's key. Serve as unique identifier.
-+ self.lo = lo
-+ # The GRD filename for the item.
-+ self.grd = grd
-+ # Optional META information for the item.
-+ self.meta = None
-+ # List of TagInfo associated witih the item.
-+ self.tags = []
-+ for k, v in raw_item.items():
-+ if k.val == 'META':
-+ assert self.meta is None
-+ self.meta = v # Not flattened.
-+ else:
-+ self.tags.append(TagInfo(k, v))
-+ self.tags.sort(key=lambda tag: tag.lo)
-+
-+ def SetUsages(self, tag_name_to_usage):
-+ for tag in self.tags:
-+ tag.usage = tag_name_to_usage.get(tag.name, 0)
-+
-+
-+def BuildItemList(root_obj):
-+ """Extracts ID assignments and structure from parsed resource_ids.
-+
-+ Returns: A list of ItemInfo, ordered by |lo|.
-+ """
-+ item_list = []
-+ grd_seen = set()
-+ for raw_key, raw_item in root_obj.items(): # Unordered.
-+ grd = raw_key.val
-+ if grd == 'SRCDIR':
-+ continue
-+ if not grd.endswith('.grd'):
-+ raise ValueError('Invalid GRD file: %s' % grd)
-+ if grd in grd_seen:
-+ raise ValueError('Duplicate GRD: %s' % grd)
-+ grd_seen.add(grd)
-+ item_list.append(ItemInfo(raw_key.lo, grd, raw_item))
-+ item_list.sort(key=lambda item: item.lo)
-+ return item_list
-diff --git a/tools/grit/grit/tool/update_resource_ids/parser.py b/tools/grit/grit/tool/update_resource_ids/parser.py
-new file mode 100644
-index 0000000000..da956bbd1c
---- /dev/null
-+++ b/tools/grit/grit/tool/update_resource_ids/parser.py
-@@ -0,0 +1,231 @@
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+"""Structure-preserving parser for resource_ids files.
-+
-+Naive usage of eval() destroys resource_ids structure. This module provides a
-+custom parser that annotates source byte ranges of "leaf values" (strings and
-+integers).
-+"""
-+
-+from __future__ import print_function
-+
-+_isWhitespace = lambda ch: ch in ' \t\n'
-+_isNotNewline = lambda ch: ch != '\n'
-+_isDigit = lambda ch: ch.isdigit()
-+
-+
-+def _RenderLineCol(data, pos):
-+ """Renders |pos| within text |data| in as text showing line and column."""
-+ # This is used to pinpoint fatal parse errors, so okay to be inefficient.
-+ new_lines = [i for i in range(pos) if data[i] == '\n']
-+ row = 1 + len(new_lines)
-+ col = (pos - new_lines[-1]) if new_lines else 1 + pos
-+ return 'line %d, column %d' % (row, col)
-+
-+
-+def Tokenize(data):
-+ """Generator to split |data| into tokens.
-+
-+ Each token is specified as |(t, lo, hi)|:
-+ * |t|: Type, with '#' = space / comments, '0' = int, 'S' = string, 'E' = end,
-+ and other characters denoting themselves.
-+ * |lo, hi|: Token's range within |data| (as |data[lo:hi]|).
-+ """
-+
-+ class ctx: # Local context for mutable data shared across inner functions.
-+ pos = 0
-+
-+ def _HasData():
-+ return ctx.pos < len(data)
-+
-+ # Returns True if ended by |not pred()|, or False if ended by EOF.
-+ def _EatWhile(pred):
-+ while _HasData():
-+ if pred(data[ctx.pos]):
-+ ctx.pos += 1
-+ else:
-+ return True
-+ return False
-+
-+ def _NextBlank():
-+ lo = ctx.pos
-+ while True:
-+ if not _EatWhile(_isWhitespace) or data[ctx.pos] != '#':
-+ break
-+ ctx.pos += 1
-+ if not _EatWhile(_isNotNewline):
-+ break
-+ ctx.pos += 1
-+ return None if ctx.pos == lo else (lo, ctx.pos)
-+
-+ def _EatString():
-+ lo = ctx.pos
-+ delim = data[ctx.pos]
-+ is_escaped = False
-+ ctx.pos += 1
-+ while _HasData():
-+ ch = data[ctx.pos]
-+ ctx.pos += 1
-+ if is_escaped:
-+ is_escaped = False
-+ elif ch == '\\':
-+ is_escaped = True
-+ elif ch == delim:
-+ return
-+ raise ValueError('Unterminated string at %s' % _RenderLineCol(data, lo))
-+
-+ while _HasData():
-+ blank = _NextBlank()
-+ if blank is not None:
-+ yield ('#', blank[0], blank[1])
-+ if not _HasData():
-+ break
-+ lo = ctx.pos
-+ ch = data[ctx.pos]
-+ if ch in '{}[],:':
-+ ctx.pos += 1
-+ t = ch
-+ elif ch.isdigit():
-+ _EatWhile(_isDigit)
-+ t = '0'
-+ elif ch in '+-':
-+ ctx.pos += 1
-+ if not _HasData() or not data[ctx.pos].isdigit():
-+ raise ValueError('Invalid int at %s' % _RenderLineCol(data, lo))
-+ _EatWhile(_isDigit)
-+ t = '0'
-+ elif ch in '"\'':
-+ _EatString()
-+ t = 'S'
-+ else:
-+ raise ValueError('Unknown char %s at %s' %
-+ (repr(ch), _RenderLineCol(data, lo)))
-+ yield (t, lo, ctx.pos)
-+ yield ('E', ctx.pos, ctx.pos) # End sentinel.
-+
-+
-+def _SkipBlanks(toks):
-+ """Generator to remove whitespace and comments from Tokenize()."""
-+ for t, lo, hi in toks:
-+ if t != '#':
-+ yield t, lo, hi
-+
-+
-+class AnnotatedValue:
-+ """Container for leaf values (ints or strings) with an annotated range."""
-+
-+ def __init__(self, val, lo, hi):
-+ self.val = val
-+ self.lo = lo
-+ self.hi = hi
-+
-+ def __str__(self):
-+ return '<%s@%d:%d>' % (str(self.val), self.lo, self.hi)
-+
-+ def __repr__(self):
-+ return '<%r@%d:%d>' % (self.val, self.lo, self.hi)
-+
-+ def __hash__(self):
-+ return hash(self.val)
-+
-+ def __eq__(self, other):
-+ return self.val == other
-+
-+
-+class ResourceIdParser:
-+ """resource_ids parser that stores leaf values as AnnotatedValue.
-+
-+ Algorithm: Use Tokenize() to split |data| into tokens and _SkipBlanks() to
-+ ignore comments and spacing, then apply a recursive parsing, using a one-token
-+ look-ahead for decision making.
-+ """
-+
-+ def __init__(self, data, tok_gen):
-+ self.data = data
-+ self.state = []
-+ self.toks = _SkipBlanks(tok_gen)
-+ self.tok_look_ahead = None
-+
-+ def _MakeErr(self, msg, pos):
-+ return ValueError(msg + ' at ' + _RenderLineCol(self.data, pos))
-+
-+ def _PeekTok(self):
-+ if self.tok_look_ahead is None:
-+ self.tok_look_ahead = next(self.toks)
-+ return self.tok_look_ahead
-+
-+ def _NextTok(self):
-+ if self.tok_look_ahead is None:
-+ return next(self.toks)
-+ ret = self.tok_look_ahead
-+ self.tok_look_ahead = None
-+ return ret
-+
-+ def _EatTok(self, exp_t, tok_name=None):
-+ t, lo, _ = self._NextTok()
-+ if t != exp_t:
-+ raise self._MakeErr('Bad token: Expect \'%s\'' % (tok_name or exp_t), lo)
-+
-+ def _NextIntOrString(self):
-+ t, lo, hi = self._NextTok()
-+ if t != '0' and t != 'S':
-+ raise self._MakeErr('Expected number or string', lo)
-+ value = eval(self.data[lo:hi])
-+ return AnnotatedValue(value, lo, hi)
-+
-+ # Consumes separator ',' and returns whether |end_ch| is encountered.
-+ def _EatSep(self, end_ch):
-+ t, lo, _ = self._PeekTok()
-+ if t == ',':
-+ self._EatTok(',')
-+ # Allow trailing ','.
-+ t, _, _ = self._PeekTok()
-+ return t == end_ch
-+ elif t == end_ch:
-+ return True
-+ else:
-+ raise self._MakeErr('Expect \',\' or \'%s\'' % end_ch, lo)
-+
-+ def _NextList(self):
-+ self._EatTok('[')
-+ ret = []
-+ t, _, _ = self._PeekTok()
-+ if t != ']':
-+ while True:
-+ ret.append(self._NextObject())
-+ if self._EatSep(']'):
-+ break
-+ self._EatTok(']')
-+ return ret
-+
-+ def _NextDict(self):
-+ self._EatTok('{')
-+ ret = {}
-+ t, _, _ = self._PeekTok()
-+ if t != '}':
-+ while True:
-+ k = self._NextIntOrString()
-+ self._EatTok(':')
-+ v = self._NextObject()
-+ ret[k] = v
-+ if self._EatSep('}'):
-+ break
-+ self._EatTok('}')
-+ return ret
-+
-+ def _NextObject(self):
-+ t, lo, _ = self._PeekTok()
-+ if t == '[':
-+ return self._NextList()
-+ elif t == '{':
-+ return self._NextDict()
-+ elif t == '0' or t == 'S':
-+ return self._NextIntOrString()
-+ else:
-+ raise self._MakeErr('Bad token: Type = %s' % t, lo)
-+
-+ def Parse(self):
-+ root_obj = self._NextObject()
-+ self._EatTok('E', 'EOF')
-+ return root_obj
-diff --git a/tools/grit/grit/tool/update_resource_ids/reader.py b/tools/grit/grit/tool/update_resource_ids/reader.py
-new file mode 100644
-index 0000000000..0a156d2deb
---- /dev/null
-+++ b/tools/grit/grit/tool/update_resource_ids/reader.py
-@@ -0,0 +1,83 @@
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+"""Helpers to read GRD files and estimate resource ID usages.
-+
-+This module uses grit.grd_reader to estimate resource ID usages in GRD
-+(and GRDP) files by counting the occurrences of {include, message, structure}
-+tags. This approach avoids the complexties of conditional inclusions, but
-+produces a conservative estimate of ID usages.
-+"""
-+
-+from __future__ import print_function
-+
-+import collections
-+import os
-+
-+from grit import grd_reader
-+from grit import util
-+from grit.tool.update_resource_ids import common
-+
-+TAGS_OF_INTEREST = set(['include', 'message', 'structure'])
-+
-+def _CountResourceUsage(grd, seen_files):
-+ tag_name_to_count = {tag: set() for tag in TAGS_OF_INTEREST}
-+ # Pass '_chromium', but '_google_chrome' would produce the same result.
-+ root = grd_reader.Parse(grd, defines={'_chromium': True})
-+ seen_files.add(grd)
-+ # Count all descendant tags, regardless of whether they're active.
-+ for node in root.Preorder():
-+ if node.name in TAGS_OF_INTEREST:
-+ tag_name_to_count[node.name].add(node.attrs['name'])
-+ elif node.name == 'part':
-+ part_path = os.path.join(os.path.dirname(grd), node.GetInputPath())
-+ seen_files.add(util.normpath(part_path))
-+ return {k: len(v) for k, v in tag_name_to_count.items() if v}
-+
-+
-+def GenerateResourceUsages(item_list, src_dir, fake, seen_files):
-+ """Visits a list of ItemInfo to generate maps from tag name to usage.
-+
-+ Args:
-+ root_obj: Root dict of a resource_ids file.
-+ src_dir: Absolute directory of Chrome's src/ directory.
-+ fake: For testing: Sets 10 as usages for all tags, to avoid reading GRD.
-+ seen_files: A set to collect paths of files read.
-+ Yields:
-+ Tuple (item, tag_name_to_usage), where |item| is from |item_list| and
-+ |tag_name_to_usage| is a dict() mapping tag name to (int) usage.
-+ """
-+ if fake:
-+ for item in item_list:
-+ tag_name_to_usage = collections.Counter({t.name: 10 for t in item.tags})
-+ yield item, tag_name_to_usage
-+ return
-+ for item in item_list:
-+ supported_tag_names = set(tag.name for tag in item.tags)
-+ if item.meta and 'sizes' in item.meta:
-+ # If META has "sizes" field, use it instead of reading GRD.
-+ tag_name_to_usage = collections.Counter()
-+ for k, vlist in item.meta['sizes'].items():
-+ tag_name_to_usage[common.StripPlural(k.val)] = sum(v.val for v in vlist)
-+ tag_names = set(tag_name_to_usage.keys())
-+ if tag_names != supported_tag_names:
-+ raise ValueError('META "sizes" field have identical fields as actual '
-+ '"sizes" field.')
-+ else:
-+ # Generated GRD start with '<(SHARED_INTERMEDIATE_DIR)'. Just check '<'.
-+ if item.grd.startswith('<'):
-+ raise ValueError('%s: Generated GRD must use META with "sizes" field '
-+ 'to specify size bounds.' % item.grd)
-+ grd_file = os.path.join(src_dir, item.grd)
-+ if not os.path.exists(grd_file):
-+ # Silently skip missing files so that src-internal files do not break
-+ # public checkouts.
-+ yield item, {}
-+ continue
-+ tag_name_to_usage = _CountResourceUsage(grd_file, seen_files)
-+ tag_names = set(tag_name_to_usage.keys())
-+ if not tag_names.issubset(supported_tag_names):
-+ missing = [t + 's' for t in tag_names - supported_tag_names]
-+ raise ValueError(
-+ 'Resource ids for %s needs entry for %s' % (item.grd, missing))
-+ yield item, tag_name_to_usage
-diff --git a/tools/grit/grit/tool/xmb.py b/tools/grit/grit/tool/xmb.py
-new file mode 100644
-index 0000000000..b821308369
---- /dev/null
-+++ b/tools/grit/grit/tool/xmb.py
-@@ -0,0 +1,295 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""The 'grit xmb' tool.
-+"""
-+
-+from __future__ import print_function
-+
-+import getopt
-+import os
-+import sys
-+
-+from xml.sax import saxutils
-+
-+import six
-+
-+from grit import grd_reader
-+from grit import lazy_re
-+from grit import tclib
-+from grit import util
-+from grit.tool import interface
-+
-+
-+# Used to collapse presentable content to determine if
-+# xml:space="preserve" is needed.
-+_WHITESPACES_REGEX = lazy_re.compile(r'\s\s*')
-+
-+
-+# See XmlEscape below.
-+_XML_QUOTE_ESCAPES = {
-+ u"'": u'&apos;',
-+ u'"': u'&quot;',
-+}
-+
-+def _XmlEscape(s):
-+ """Returns text escaped for XML in a way compatible with Google's
-+ internal Translation Console tool. May be used for attributes as
-+ well as for contents.
-+ """
-+ return saxutils.escape(six.text_type(s), _XML_QUOTE_ESCAPES).encode('utf-8')
-+
-+
-+def _WriteAttribute(file, name, value):
-+ """Writes an XML attribute to the specified file.
-+
-+ Args:
-+ file: file to write to
-+ name: name of the attribute
-+ value: (unescaped) value of the attribute
-+ """
-+ name = name.encode('utf-8')
-+ if value:
-+ file.write(b' %s="%s"' % (name, _XmlEscape(value)))
-+
-+
-+def _WriteMessage(file, message):
-+ presentable_content = message.GetPresentableContent()
-+ assert (isinstance(presentable_content, six.string_types) or
-+ (len(message.parts) == 1 and
-+ type(message.parts[0] == tclib.Placeholder)))
-+ preserve_space = presentable_content != _WHITESPACES_REGEX.sub(
-+ u' ', presentable_content.strip())
-+
-+ file.write(b'<msg')
-+ _WriteAttribute(file, 'desc', message.GetDescription())
-+ _WriteAttribute(file, 'id', message.GetId())
-+ _WriteAttribute(file, 'meaning', message.GetMeaning())
-+ if preserve_space:
-+ _WriteAttribute(file, 'xml:space', 'preserve')
-+ file.write(b'>')
-+ if not preserve_space:
-+ file.write(b'\n ')
-+
-+ parts = message.GetContent()
-+ for part in parts:
-+ if isinstance(part, tclib.Placeholder):
-+ file.write(b'<ph')
-+ _WriteAttribute(file, 'name', part.GetPresentation())
-+ file.write(b'><ex>')
-+ file.write(_XmlEscape(part.GetExample()))
-+ file.write(b'</ex>')
-+ file.write(_XmlEscape(part.GetOriginal()))
-+ file.write(b'</ph>')
-+ else:
-+ file.write(_XmlEscape(part))
-+ if not preserve_space:
-+ file.write(b'\n')
-+ file.write(b'</msg>\n')
-+
-+
-+def WriteXmbFile(file, messages):
-+ """Writes the given grit.tclib.Message items to the specified open
-+ file-like object in the XMB format.
-+ """
-+ file.write(b"""<?xml version="1.0" encoding="UTF-8"?>
-+<!DOCTYPE messagebundle [
-+<!ELEMENT messagebundle (msg)*>
-+<!ATTLIST messagebundle class CDATA #IMPLIED>
-+
-+<!ELEMENT msg (#PCDATA|ph|source)*>
-+<!ATTLIST msg id CDATA #IMPLIED>
-+<!ATTLIST msg seq CDATA #IMPLIED>
-+<!ATTLIST msg name CDATA #IMPLIED>
-+<!ATTLIST msg desc CDATA #IMPLIED>
-+<!ATTLIST msg meaning CDATA #IMPLIED>
-+<!ATTLIST msg obsolete (obsolete) #IMPLIED>
-+<!ATTLIST msg xml:space (default|preserve) "default">
-+<!ATTLIST msg is_hidden CDATA #IMPLIED>
-+
-+<!ELEMENT source (#PCDATA)>
-+
-+<!ELEMENT ph (#PCDATA|ex)*>
-+<!ATTLIST ph name CDATA #REQUIRED>
-+
-+<!ELEMENT ex (#PCDATA)>
-+]>
-+<messagebundle>
-+""")
-+ for message in messages:
-+ _WriteMessage(file, message)
-+ file.write(b'</messagebundle>')
-+
-+
-+class OutputXmb(interface.Tool):
-+ """Outputs all translateable messages in the .grd input file to an
-+.xmb file, which is the format used to give source messages to
-+Google's internal Translation Console tool. The format could easily
-+be used for other systems.
-+
-+Usage: grit xmb [-i|-h] [-l LIMITFILE] OUTPUTPATH
-+
-+OUTPUTPATH is the path you want to output the .xmb file to.
-+
-+The -l option can be used to output only some of the resources to the .xmb file.
-+LIMITFILE is the path to a file that is used to limit the items output to the
-+xmb file. If the filename extension is .grd, the file must be a .grd file
-+and the tool only output the contents of nodes from the input file that also
-+exist in the limit file (as compared on the 'name' attribute). Otherwise it must
-+contain a list of the IDs that output should be limited to, one ID per line, and
-+the tool will only output nodes with 'name' attributes that match one of the
-+IDs.
-+
-+The -i option causes 'grit xmb' to output an "IDs only" file instead of an XMB
-+file. The "IDs only" file contains the message ID of each message that would
-+normally be output to the XMB file, one message ID per line. It is designed for
-+use with the 'grit transl2tc' tool's -l option.
-+
-+Other options:
-+
-+ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
-+ value VAL (defaults to 1) which will be used to control
-+ conditional inclusion of resources.
-+
-+ -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
-+
-+"""
-+ # The different output formats supported by this tool
-+ FORMAT_XMB = 0
-+ FORMAT_IDS_ONLY = 1
-+
-+ def __init__(self, defines=None):
-+ super(OutputXmb, self).__init__()
-+ self.format = self.FORMAT_XMB
-+ self.defines = defines or {}
-+
-+ def ShortDescription(self):
-+ return 'Exports all translateable messages into an XMB file.'
-+
-+ def Run(self, opts, args):
-+ os.environ['cwd'] = os.getcwd()
-+
-+ self.SetOptions(opts)
-+
-+ limit_file = None
-+ limit_is_grd = False
-+ limit_file_dir = None
-+ own_opts, args = getopt.getopt(args, 'l:D:ih', ('help',))
-+ for key, val in own_opts:
-+ if key == '-l':
-+ limit_file = open(val, 'r')
-+ limit_file_dir = util.dirname(val)
-+ if not len(limit_file_dir):
-+ limit_file_dir = '.'
-+ limit_is_grd = os.path.splitext(val)[1] == '.grd'
-+ elif key == '-i':
-+ self.format = self.FORMAT_IDS_ONLY
-+ elif key == '-D':
-+ name, val = util.ParseDefine(val)
-+ self.defines[name] = val
-+ elif key == '-E':
-+ (env_name, env_value) = val.split('=', 1)
-+ os.environ[env_name] = env_value
-+ elif key == '--help':
-+ self.ShowUsage()
-+ sys.exit(0)
-+ if not len(args) == 1:
-+ print('grit xmb takes exactly one argument, the path to the XMB file '
-+ 'to output.')
-+ return 2
-+
-+ xmb_path = args[0]
-+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose, defines=self.defines)
-+ res_tree.SetOutputLanguage('en')
-+ res_tree.SetDefines(self.defines)
-+ res_tree.OnlyTheseTranslations([])
-+ res_tree.RunGatherers()
-+
-+ with open(xmb_path, 'wb') as output_file:
-+ self.Process(
-+ res_tree, output_file, limit_file, limit_is_grd, limit_file_dir)
-+ if limit_file:
-+ limit_file.close()
-+ print("Wrote %s" % xmb_path)
-+
-+ def Process(self, res_tree, output_file, limit_file=None, limit_is_grd=False,
-+ dir=None):
-+ """Writes a document with the contents of res_tree into output_file,
-+ limiting output to the IDs specified in limit_file, which is a GRD file if
-+ limit_is_grd is true, otherwise a file with one ID per line.
-+
-+ The format of the output document depends on this object's format attribute.
-+ It can be FORMAT_XMB or FORMAT_IDS_ONLY.
-+
-+ The FORMAT_IDS_ONLY format causes this function to write just a list
-+ of the IDs of all messages that would have been added to the XMB file, one
-+ ID per line.
-+
-+ The FORMAT_XMB format causes this function to output the (default) XMB
-+ format.
-+
-+ Args:
-+ res_tree: base.Node()
-+ output_file: file open for writing
-+ limit_file: None or file open for reading
-+ limit_is_grd: True | False
-+ dir: Directory of the limit file
-+ """
-+ if limit_file:
-+ if limit_is_grd:
-+ limit_list = []
-+ limit_tree = grd_reader.Parse(limit_file,
-+ dir=dir,
-+ debug=self.o.extra_verbose)
-+ for node in limit_tree:
-+ if 'name' in node.attrs:
-+ limit_list.append(node.attrs['name'])
-+ else:
-+ # Not a GRD file, so it's just a file with one ID per line
-+ limit_list = [item.strip() for item in limit_file.read().split('\n')]
-+
-+ ids_already_done = {}
-+ messages = []
-+ for node in res_tree:
-+ if (limit_file and
-+ not ('name' in node.attrs and node.attrs['name'] in limit_list)):
-+ continue
-+ if not node.IsTranslateable():
-+ continue
-+
-+ for clique in node.GetCliques():
-+ if not clique.IsTranslateable():
-+ continue
-+ if not clique.GetMessage().GetRealContent():
-+ continue
-+
-+ # Some explanation is in order here. Note that we can have
-+ # many messages with the same ID.
-+ #
-+ # The way we work around this is to maintain a list of cliques
-+ # per message ID (in the UberClique) and select the "best" one
-+ # (the first one that has a description, or an arbitrary one
-+ # if there is no description) for inclusion in the XMB file.
-+ # The translations are all going to be the same for messages
-+ # with the same ID, although the way we replace placeholders
-+ # might be slightly different.
-+ id = clique.GetMessage().GetId()
-+ if id in ids_already_done:
-+ continue
-+ ids_already_done[id] = 1
-+
-+ message = node.UberClique().BestClique(id).GetMessage()
-+ messages += [message]
-+
-+ # Ensure a stable order of messages, to help regression testing.
-+ messages.sort(key=lambda x:x.GetId())
-+
-+ if self.format == self.FORMAT_IDS_ONLY:
-+ # We just print the list of IDs to the output file.
-+ for msg in messages:
-+ output_file.write(msg.GetId())
-+ output_file.write('\n')
-+ else:
-+ assert self.format == self.FORMAT_XMB
-+ WriteXmbFile(output_file, messages)
-diff --git a/tools/grit/grit/tool/xmb_unittest.py b/tools/grit/grit/tool/xmb_unittest.py
-new file mode 100644
-index 0000000000..3c7e92cee7
---- /dev/null
-+++ b/tools/grit/grit/tool/xmb_unittest.py
-@@ -0,0 +1,132 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for 'grit xmb' tool.'''
-+
-+from __future__ import print_function
-+
-+import io
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-+
-+import unittest
-+import xml.sax
-+
-+from six import StringIO
-+
-+from grit import grd_reader
-+from grit import util
-+from grit.tool import xmb
-+
-+
-+class XmbUnittest(unittest.TestCase):
-+ def setUp(self):
-+ self.res_tree = grd_reader.Parse(
-+ io.BytesIO(u'''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <includes>
-+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
-+ </includes>
-+ <messages>
-+ <message name="GOOD" desc="sub" sub_variable="true">
-+ excellent
-+ </message>
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, are you doing [GOOD] today?
-+ </message>
-+ <message name="IDS_BONGOBINGO">
-+ Yibbee
-+ </message>
-+ <message name="IDS_UNICODE">
-+ Ol\xe1, \u4eca\u65e5\u306f! \U0001F60A
-+ </message>
-+ </messages>
-+ <structures>
-+ <structure type="dialog" name="IDD_SPACYBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
-+ </structures>
-+ </release>
-+ </grit>'''.encode('utf-8')), '.')
-+ self.xmb_file = io.BytesIO()
-+
-+ def testNormalOutput(self):
-+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
-+ output = self.xmb_file.getvalue().decode('utf-8')
-+ self.failUnless(output.count('Joi'))
-+ self.failUnless(output.count('Yibbee'))
-+ self.failUnless(output.count(u'Ol\xe1, \u4eca\u65e5\u306f! \U0001F60A'))
-+
-+ def testLimitList(self):
-+ limit_file = StringIO(
-+ 'IDS_BONGOBINGO\nIDS_DOES_NOT_EXIST\nIDS_ALSO_DOES_NOT_EXIST')
-+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file, limit_file, False)
-+ output = self.xmb_file.getvalue().decode('utf-8')
-+ self.failUnless(output.count('Yibbee'))
-+ self.failUnless(not output.count('Joi'))
-+
-+ def testLimitGrd(self):
-+ limit_file = StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
-+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
-+ </message>
-+ </messages>
-+ </release>
-+ </grit>''')
-+ tool = xmb.OutputXmb()
-+ class DummyOpts(object):
-+ extra_verbose = False
-+ tool.o = DummyOpts()
-+ tool.Process(self.res_tree, self.xmb_file, limit_file, True, dir='.')
-+ output = self.xmb_file.getvalue().decode('utf-8')
-+ self.failUnless(output.count('Joi'))
-+ self.failUnless(not output.count('Yibbee'))
-+
-+ def testSubstitution(self):
-+ self.res_tree.SetOutputLanguage('en')
-+ os.chdir(util.PathFromRoot('.')) # so it can find klonk.rc
-+ self.res_tree.RunGatherers()
-+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
-+ output = self.xmb_file.getvalue().decode('utf-8')
-+ self.failUnless(output.count(
-+ '<ph name="GOOD_1"><ex>excellent</ex>[GOOD]</ph>'))
-+
-+ def testLeadingTrailingWhitespace(self):
-+ # Regression test for problems outputting messages with leading or
-+ # trailing whitespace (these come in via structures only, as
-+ # message nodes already strip and store whitespace).
-+ self.res_tree.SetOutputLanguage('en')
-+ os.chdir(util.PathFromRoot('.')) # so it can find klonk.rc
-+ self.res_tree.RunGatherers()
-+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
-+ output = self.xmb_file.getvalue().decode('utf-8')
-+ self.failUnless(output.count('OK ? </msg>'))
-+
-+ def testDisallowedChars(self):
-+ # Validate that the invalid unicode is not accepted. Since it's not valid,
-+ # we can't specify it in a string literal, so write as a byte sequence.
-+ bad_xml = io.BytesIO()
-+ bad_xml.write(b'''<?xml version="1.0" encoding="UTF-8"?>
-+ <grit latest_public_release="2" source_lang_id="en-US"
-+ current_release="3" base_dir=".">
-+ <release seq="3">
-+ <messages>
-+ <message name="ID_FOO">''')
-+ # UTF-8 corresponding to to \U00110000
-+ # http://apps.timwhitlock.info/unicode/inspect/hex/110000
-+ bad_xml.write(b'\xF4\x90\x80\x80')
-+ bad_xml.write(b'''</message>
-+ </messages>
-+ </release>
-+ </grit>''')
-+ bad_xml.seek(0)
-+ self.assertRaises(xml.sax.SAXParseException, grd_reader.Parse, bad_xml, '.')
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/util.py b/tools/grit/grit/util.py
-new file mode 100644
-index 0000000000..98433d154c
---- /dev/null
-+++ b/tools/grit/grit/util.py
-@@ -0,0 +1,691 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Utilities used by GRIT.
-+'''
-+
-+from __future__ import print_function
-+
-+import codecs
-+import io
-+import os
-+import re
-+import shutil
-+import sys
-+import tempfile
-+from xml.sax import saxutils
-+
-+import six
-+from six import StringIO
-+from six.moves import html_entities as entities
-+
-+from grit import lazy_re
-+
-+_root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
-+
-+
-+# Unique constants for use by ReadFile().
-+BINARY = 0
-+
-+
-+# Unique constants representing data pack encodings.
-+_, UTF8, UTF16 = range(3)
-+
-+
-+def Encode(message, encoding):
-+ '''Returns a byte stream that represents |message| in the given |encoding|.'''
-+ # |message| is a python unicode string, so convert to a byte stream that
-+ # has the correct encoding requested for the datapacks. We skip the first
-+ # 2 bytes of text resources because it is the BOM.
-+ if encoding == UTF8:
-+ return message.encode('utf8')
-+ if encoding == UTF16:
-+ return message.encode('utf16')[2:]
-+ # Default is BINARY
-+ return message
-+
-+
-+# Matches all different types of linebreaks.
-+LINEBREAKS = re.compile('\r\n|\n|\r')
-+
-+def MakeRelativePath(base_path, path_to_make_relative):
-+ """Returns a relative path such from the base_path to
-+ the path_to_make_relative.
-+
-+ In other words, os.join(base_path,
-+ MakeRelativePath(base_path, path_to_make_relative))
-+ is the same location as path_to_make_relative.
-+
-+ Args:
-+ base_path: the root path
-+ path_to_make_relative: an absolute path that is on the same drive
-+ as base_path
-+ """
-+
-+ def _GetPathAfterPrefix(prefix_path, path_with_prefix):
-+ """Gets the subpath within in prefix_path for the path_with_prefix
-+ with no beginning or trailing path separators.
-+
-+ Args:
-+ prefix_path: the base path
-+ path_with_prefix: a path that starts with prefix_path
-+ """
-+ assert path_with_prefix.startswith(prefix_path)
-+ path_without_prefix = path_with_prefix[len(prefix_path):]
-+ normalized_path = os.path.normpath(path_without_prefix.strip(os.path.sep))
-+ if normalized_path == '.':
-+ normalized_path = ''
-+ return normalized_path
-+
-+ def _GetCommonBaseDirectory(*args):
-+ """Returns the common prefix directory for the given paths
-+
-+ Args:
-+ The list of paths (at least one of which should be a directory)
-+ """
-+ prefix = os.path.commonprefix(args)
-+ # prefix is a character-by-character prefix (i.e. it does not end
-+ # on a directory bound, so this code fixes that)
-+
-+ # if the prefix ends with the separator, then it is prefect.
-+ if len(prefix) > 0 and prefix[-1] == os.path.sep:
-+ return prefix
-+
-+ # We need to loop through all paths or else we can get
-+ # tripped up by "c:\a" and "c:\abc". The common prefix
-+ # is "c:\a" which is a directory and looks good with
-+ # respect to the first directory but it is clear that
-+ # isn't a common directory when the second path is
-+ # examined.
-+ for path in args:
-+ assert len(path) >= len(prefix)
-+ # If the prefix the same length as the path,
-+ # then the prefix must be a directory (since one
-+ # of the arguements should be a directory).
-+ if path == prefix:
-+ continue
-+ # if the character after the prefix in the path
-+ # is the separator, then the prefix appears to be a
-+ # valid a directory as well for the given path
-+ if path[len(prefix)] == os.path.sep:
-+ continue
-+ # Otherwise, the prefix is not a directory, so it needs
-+ # to be shortened to be one
-+ index_sep = prefix.rfind(os.path.sep)
-+ # The use "index_sep + 1" because it includes the final sep
-+ # and it handles the case when the index_sep is -1 as well
-+ prefix = prefix[:index_sep + 1]
-+ # At this point we backed up to a directory bound which is
-+ # common to all paths, so we can quit going through all of
-+ # the paths.
-+ break
-+ return prefix
-+
-+ prefix = _GetCommonBaseDirectory(base_path, path_to_make_relative)
-+ # If the paths had no commonality at all, then return the absolute path
-+ # because it is the best that can be done. If the path had to be relative
-+ # then eventually this absolute path will be discovered (when a build breaks)
-+ # and an appropriate fix can be made, but having this allows for the best
-+ # backward compatibility with the absolute path behavior in the past.
-+ if len(prefix) <= 0:
-+ return path_to_make_relative
-+ # Build a path from the base dir to the common prefix
-+ remaining_base_path = _GetPathAfterPrefix(prefix, base_path)
-+
-+ # The follow handles two case: "" and "foo\\bar"
-+ path_pieces = remaining_base_path.split(os.path.sep)
-+ base_depth_from_prefix = len([d for d in path_pieces if len(d)])
-+ base_to_prefix = (".." + os.path.sep) * base_depth_from_prefix
-+
-+ # Put add in the path from the prefix to the path_to_make_relative
-+ remaining_other_path = _GetPathAfterPrefix(prefix, path_to_make_relative)
-+ return base_to_prefix + remaining_other_path
-+
-+
-+KNOWN_SYSTEM_IDENTIFIERS = set()
-+
-+SYSTEM_IDENTIFIERS = None
-+
-+def SetupSystemIdentifiers(ids):
-+ '''Adds ids to a regexp of known system identifiers.
-+
-+ Can be called many times, ids will be accumulated.
-+
-+ Args:
-+ ids: an iterable of strings
-+ '''
-+ KNOWN_SYSTEM_IDENTIFIERS.update(ids)
-+ global SYSTEM_IDENTIFIERS
-+ SYSTEM_IDENTIFIERS = lazy_re.compile(
-+ ' | '.join([r'\b%s\b' % i for i in KNOWN_SYSTEM_IDENTIFIERS]),
-+ re.VERBOSE)
-+
-+
-+# Matches all of the resource IDs predefined by Windows.
-+SetupSystemIdentifiers((
-+ 'IDOK', 'IDCANCEL', 'IDC_STATIC', 'IDYES', 'IDNO',
-+ 'ID_FILE_NEW', 'ID_FILE_OPEN', 'ID_FILE_CLOSE', 'ID_FILE_SAVE',
-+ 'ID_FILE_SAVE_AS', 'ID_FILE_PAGE_SETUP', 'ID_FILE_PRINT_SETUP',
-+ 'ID_FILE_PRINT', 'ID_FILE_PRINT_DIRECT', 'ID_FILE_PRINT_PREVIEW',
-+ 'ID_FILE_UPDATE', 'ID_FILE_SAVE_COPY_AS', 'ID_FILE_SEND_MAIL',
-+ 'ID_FILE_MRU_FIRST', 'ID_FILE_MRU_LAST',
-+ 'ID_EDIT_CLEAR', 'ID_EDIT_CLEAR_ALL', 'ID_EDIT_COPY',
-+ 'ID_EDIT_CUT', 'ID_EDIT_FIND', 'ID_EDIT_PASTE', 'ID_EDIT_PASTE_LINK',
-+ 'ID_EDIT_PASTE_SPECIAL', 'ID_EDIT_REPEAT', 'ID_EDIT_REPLACE',
-+ 'ID_EDIT_SELECT_ALL', 'ID_EDIT_UNDO', 'ID_EDIT_REDO',
-+ 'VS_VERSION_INFO', 'IDRETRY',
-+ 'ID_APP_ABOUT', 'ID_APP_EXIT',
-+ 'ID_NEXT_PANE', 'ID_PREV_PANE',
-+ 'ID_WINDOW_NEW', 'ID_WINDOW_ARRANGE', 'ID_WINDOW_CASCADE',
-+ 'ID_WINDOW_TILE_HORZ', 'ID_WINDOW_TILE_VERT', 'ID_WINDOW_SPLIT',
-+ 'ATL_IDS_SCSIZE', 'ATL_IDS_SCMOVE', 'ATL_IDS_SCMINIMIZE',
-+ 'ATL_IDS_SCMAXIMIZE', 'ATL_IDS_SCNEXTWINDOW', 'ATL_IDS_SCPREVWINDOW',
-+ 'ATL_IDS_SCCLOSE', 'ATL_IDS_SCRESTORE', 'ATL_IDS_SCTASKLIST',
-+ 'ATL_IDS_MDICHILD', 'ATL_IDS_IDLEMESSAGE', 'ATL_IDS_MRU_FILE' ))
-+
-+
-+# Matches character entities, whether specified by name, decimal or hex.
-+_HTML_ENTITY = lazy_re.compile(
-+ '&(#(?P<decimal>[0-9]+)|#x(?P<hex>[a-fA-F0-9]+)|(?P<named>[a-z0-9]+));',
-+ re.IGNORECASE)
-+
-+# Matches characters that should be HTML-escaped. This is <, > and &, but only
-+# if the & is not the start of an HTML character entity.
-+_HTML_CHARS_TO_ESCAPE = lazy_re.compile(
-+ '"|<|>|&(?!#[0-9]+|#x[0-9a-z]+|[a-z]+;)',
-+ re.IGNORECASE | re.MULTILINE)
-+
-+
-+def ReadFile(filename, encoding):
-+ '''Reads and returns the entire contents of the given file.
-+
-+ Args:
-+ filename: The path to the file.
-+ encoding: A Python codec name or the special value: BINARY to read
-+ the file in binary mode.
-+ '''
-+ if encoding == BINARY:
-+ mode = 'rb'
-+ encoding = None
-+ else:
-+ mode = 'rU'
-+
-+ with io.open(filename, mode, encoding=encoding) as f:
-+ return f.read()
-+
-+
-+def WrapOutputStream(stream, encoding = 'utf-8'):
-+ '''Returns a stream that wraps the provided stream, making it write
-+ characters using the specified encoding.'''
-+ return codecs.getwriter(encoding)(stream)
-+
-+
-+def ChangeStdoutEncoding(encoding = 'utf-8'):
-+ '''Changes STDOUT to print characters using the specified encoding.'''
-+ # If we're unittesting, don't reconfigure.
-+ if isinstance(sys.stdout, StringIO):
-+ return
-+
-+ if sys.version_info.major < 3:
-+ # Python 2 has binary streams by default, so reconfigure directly.
-+ sys.stdout = WrapOutputStream(sys.stdout, encoding)
-+ sys.stderr = WrapOutputStream(sys.stderr, encoding)
-+ elif sys.version_info < (3, 7):
-+ # Python 3 has text streams by default, so we have to detach them first.
-+ sys.stdout = WrapOutputStream(sys.stdout.detach(), encoding)
-+ sys.stderr = WrapOutputStream(sys.stderr.detach(), encoding)
-+ else:
-+ # Python 3.7+ provides an API for this specifically.
-+ sys.stdout.reconfigure(encoding=encoding)
-+ sys.stderr.reconfigure(encoding=encoding)
-+
-+
-+def EscapeHtml(text, escape_quotes = False):
-+ '''Returns 'text' with <, > and & (and optionally ") escaped to named HTML
-+ entities. Any existing named entity or HTML entity defined by decimal or
-+ hex code will be left untouched. This is appropriate for escaping text for
-+ inclusion in HTML, but not for XML.
-+ '''
-+ def Replace(match):
-+ if match.group() == '&': return '&amp;'
-+ elif match.group() == '<': return '&lt;'
-+ elif match.group() == '>': return '&gt;'
-+ elif match.group() == '"':
-+ if escape_quotes: return '&quot;'
-+ else: return match.group()
-+ else: assert False
-+ out = _HTML_CHARS_TO_ESCAPE.sub(Replace, text)
-+ return out
-+
-+
-+def UnescapeHtml(text, replace_nbsp=True):
-+ '''Returns 'text' with all HTML character entities (both named character
-+ entities and those specified by decimal or hexadecimal Unicode ordinal)
-+ replaced by their Unicode characters (or latin1 characters if possible).
-+
-+ The only exception is that &nbsp; will not be escaped if 'replace_nbsp' is
-+ False.
-+ '''
-+ def Replace(match):
-+ groups = match.groupdict()
-+ if groups['hex']:
-+ return six.unichr(int(groups['hex'], 16))
-+ elif groups['decimal']:
-+ return six.unichr(int(groups['decimal'], 10))
-+ else:
-+ name = groups['named']
-+ if name == 'nbsp' and not replace_nbsp:
-+ return match.group() # Don't replace &nbsp;
-+ assert name != None
-+ if name in entities.name2codepoint:
-+ return six.unichr(entities.name2codepoint[name])
-+ else:
-+ return match.group() # Unknown HTML character entity - don't replace
-+
-+ out = _HTML_ENTITY.sub(Replace, text)
-+ return out
-+
-+
-+def EncodeCdata(cdata):
-+ '''Returns the provided cdata in either escaped format or <![CDATA[xxx]]>
-+ format, depending on which is more appropriate for easy editing. The data
-+ is escaped for inclusion in an XML element's body.
-+
-+ Args:
-+ cdata: 'If x < y and y < z then x < z'
-+
-+ Return:
-+ '<![CDATA[If x < y and y < z then x < z]]>'
-+ '''
-+ if cdata.count('<') > 1 or cdata.count('>') > 1 and cdata.count(']]>') == 0:
-+ return '<![CDATA[%s]]>' % cdata
-+ else:
-+ return saxutils.escape(cdata)
-+
-+
-+def FixupNamedParam(function, param_name, param_value):
-+ '''Returns a closure that is identical to 'function' but ensures that the
-+ named parameter 'param_name' is always set to 'param_value' unless explicitly
-+ set by the caller.
-+
-+ Args:
-+ function: callable
-+ param_name: 'bingo'
-+ param_value: 'bongo' (any type)
-+
-+ Return:
-+ callable
-+ '''
-+ def FixupClosure(*args, **kw):
-+ if not param_name in kw:
-+ kw[param_name] = param_value
-+ return function(*args, **kw)
-+ return FixupClosure
-+
-+
-+def PathFromRoot(path):
-+ r'''Takes a path relative to the root directory for GRIT (the one that grit.py
-+ resides in) and returns a path that is either absolute or relative to the
-+ current working directory (i.e .a path you can use to open the file).
-+
-+ Args:
-+ path: 'rel_dir\file.ext'
-+
-+ Return:
-+ 'c:\src\tools\rel_dir\file.ext
-+ '''
-+ return os.path.normpath(os.path.join(_root_dir, path))
-+
-+
-+def ParseGrdForUnittest(body, base_dir=None, predetermined_ids_file=None,
-+ run_gatherers=False):
-+ '''Parse a skeleton .grd file and return it, for use in unit tests.
-+
-+ Args:
-+ body: XML that goes inside the <release> element.
-+ base_dir: The base_dir attribute of the <grit> tag.
-+ '''
-+ from grit import grd_reader
-+ if isinstance(body, six.text_type):
-+ body = body.encode('utf-8')
-+ if base_dir is None:
-+ base_dir = PathFromRoot('.')
-+ lines = [b'<?xml version="1.0" encoding="UTF-8"?>']
-+ lines.append(b'<grit latest_public_release="2" current_release="3" '
-+ b'source_lang_id="en" base_dir="%s">' % base_dir.encode('utf-8'))
-+ if b'<outputs>' in body:
-+ lines.append(body)
-+ else:
-+ lines.append(b' <outputs></outputs>')
-+ lines.append(b' <release seq="3">')
-+ lines.append(body)
-+ lines.append(b' </release>')
-+ lines.append(b'</grit>')
-+ ret = grd_reader.Parse(io.BytesIO(b'\n'.join(lines)), dir='.')
-+ ret.SetOutputLanguage('en')
-+ if run_gatherers:
-+ ret.RunGatherers()
-+ ret.SetPredeterminedIdsFile(predetermined_ids_file)
-+ ret.InitializeIds()
-+ return ret
-+
-+
-+def StripBlankLinesAndComments(text):
-+ '''Strips blank lines and comments from C source code, for unit tests.'''
-+ return '\n'.join(line for line in text.splitlines()
-+ if line and not line.startswith('//'))
-+
-+
-+def dirname(filename):
-+ '''Version of os.path.dirname() that never returns empty paths (returns
-+ '.' if the result of os.path.dirname() is empty).
-+ '''
-+ ret = os.path.dirname(filename)
-+ if ret == '':
-+ ret = '.'
-+ return ret
-+
-+
-+def normpath(path):
-+ '''Version of os.path.normpath that also changes backward slashes to
-+ forward slashes when not running on Windows.
-+ '''
-+ # This is safe to always do because the Windows version of os.path.normpath
-+ # will replace forward slashes with backward slashes.
-+ path = path.replace('\\', '/')
-+ return os.path.normpath(path)
-+
-+
-+_LANGUAGE_SPLIT_RE = lazy_re.compile('-|_|/')
-+
-+
-+def CanonicalLanguage(code):
-+ '''Canonicalizes two-part language codes by using a dash and making the
-+ second part upper case. Returns one-part language codes unchanged.
-+
-+ Args:
-+ code: 'zh_cn'
-+
-+ Return:
-+ code: 'zh-CN'
-+ '''
-+ parts = _LANGUAGE_SPLIT_RE.split(code)
-+ code = [ parts[0] ]
-+ for part in parts[1:]:
-+ code.append(part.upper())
-+ return '-'.join(code)
-+
-+
-+_LANG_TO_CODEPAGE = {
-+ 'en' : 1252,
-+ 'fr' : 1252,
-+ 'it' : 1252,
-+ 'de' : 1252,
-+ 'es' : 1252,
-+ 'nl' : 1252,
-+ 'sv' : 1252,
-+ 'no' : 1252,
-+ 'da' : 1252,
-+ 'fi' : 1252,
-+ 'pt-BR' : 1252,
-+ 'ru' : 1251,
-+ 'ja' : 932,
-+ 'zh-TW' : 950,
-+ 'zh-CN' : 936,
-+ 'ko' : 949,
-+}
-+
-+
-+def LanguageToCodepage(lang):
-+ '''Returns the codepage _number_ that can be used to represent 'lang', which
-+ may be either in formats such as 'en', 'pt_br', 'pt-BR', etc.
-+
-+ The codepage returned will be one of the 'cpXXXX' codepage numbers.
-+
-+ Args:
-+ lang: 'de'
-+
-+ Return:
-+ 1252
-+ '''
-+ lang = CanonicalLanguage(lang)
-+ if lang in _LANG_TO_CODEPAGE:
-+ return _LANG_TO_CODEPAGE[lang]
-+ else:
-+ print("Not sure which codepage to use for %s, assuming cp1252" % lang)
-+ return 1252
-+
-+def NewClassInstance(class_name, class_type):
-+ '''Returns an instance of the class specified in classname
-+
-+ Args:
-+ class_name: the fully qualified, dot separated package + classname,
-+ i.e. "my.package.name.MyClass". Short class names are not supported.
-+ class_type: the class or superclass this object must implement
-+
-+ Return:
-+ An instance of the class, or None if none was found
-+ '''
-+ lastdot = class_name.rfind('.')
-+ module_name = ''
-+ if lastdot >= 0:
-+ module_name = class_name[0:lastdot]
-+ if module_name:
-+ class_name = class_name[lastdot+1:]
-+ module = __import__(module_name, globals(), locals(), [''])
-+ if hasattr(module, class_name):
-+ class_ = getattr(module, class_name)
-+ class_instance = class_()
-+ if isinstance(class_instance, class_type):
-+ return class_instance
-+ return None
-+
-+
-+def FixLineEnd(text, line_end):
-+ # First normalize
-+ text = text.replace('\r\n', '\n')
-+ text = text.replace('\r', '\n')
-+ # Then fix
-+ text = text.replace('\n', line_end)
-+ return text
-+
-+
-+def BoolToString(bool):
-+ if bool:
-+ return 'true'
-+ else:
-+ return 'false'
-+
-+
-+verbose = False
-+extra_verbose = False
-+
-+def IsVerbose():
-+ return verbose
-+
-+def IsExtraVerbose():
-+ return extra_verbose
-+
-+def ParseDefine(define):
-+ '''Parses a define argument and returns the name and value.
-+
-+ The format is either "NAME=VAL" or "NAME", using True as the default value.
-+ Values of "1"/"true" and "0"/"false" are transformed to True and False
-+ respectively.
-+
-+ Args:
-+ define: a string of the form "NAME=VAL" or "NAME".
-+
-+ Returns:
-+ A (name, value) pair. name is a string, value a string or boolean.
-+ '''
-+ parts = [part.strip() for part in define.split('=', 1)]
-+ assert len(parts) >= 1
-+ name = parts[0]
-+ val = True
-+ if len(parts) > 1:
-+ val = parts[1]
-+ if val == "1" or val == "true": val = True
-+ elif val == "0" or val == "false": val = False
-+ return (name, val)
-+
-+
-+class Substituter(object):
-+ '''Finds and substitutes variable names in text strings.
-+
-+ Given a dictionary of variable names and values, prepares to
-+ search for patterns of the form [VAR_NAME] in a text.
-+ The value will be substituted back efficiently.
-+ Also applies to tclib.Message objects.
-+ '''
-+
-+ def __init__(self):
-+ '''Create an empty substituter.'''
-+ self.substitutions_ = {}
-+ self.dirty_ = True
-+
-+ def AddSubstitutions(self, subs):
-+ '''Add new values to the substitutor.
-+
-+ Args:
-+ subs: A dictionary of new substitutions.
-+ '''
-+ self.substitutions_.update(subs)
-+ self.dirty_ = True
-+
-+ def AddMessages(self, messages, lang):
-+ '''Adds substitutions extracted from node.Message objects.
-+
-+ Args:
-+ messages: a list of node.Message objects.
-+ lang: The translation language to use in substitutions.
-+ '''
-+ subs = [(str(msg.attrs['name']), msg.Translate(lang)) for msg in messages]
-+ self.AddSubstitutions(dict(subs))
-+ self.dirty_ = True
-+
-+ def GetExp(self):
-+ '''Obtain a regular expression that will find substitution keys in text.
-+
-+ Create and cache if the substituter has been updated. Use the cached value
-+ otherwise. Keys will be enclosed in [square brackets] in text.
-+
-+ Returns:
-+ A regular expression object.
-+ '''
-+ if self.dirty_:
-+ components = [r'\[%s\]' % (k,) for k in self.substitutions_]
-+ self.exp = re.compile(r'(%s)' % ('|'.join(components),))
-+ self.dirty_ = False
-+ return self.exp
-+
-+ def Substitute(self, text):
-+ '''Substitute the variable values in the given text.
-+
-+ Text of the form [message_name] will be replaced by the message's value.
-+
-+ Args:
-+ text: A string of text.
-+
-+ Returns:
-+ A string of text with substitutions done.
-+ '''
-+ return ''.join([self._SubFragment(f) for f in self.GetExp().split(text)])
-+
-+ def _SubFragment(self, fragment):
-+ '''Utility function for Substitute.
-+
-+ Performs a simple substitution if the fragment is exactly of the form
-+ [message_name].
-+
-+ Args:
-+ fragment: A simple string.
-+
-+ Returns:
-+ A string with the substitution done.
-+ '''
-+ if len(fragment) > 2 and fragment[0] == '[' and fragment[-1] == ']':
-+ sub = self.substitutions_.get(fragment[1:-1], None)
-+ if sub is not None:
-+ return sub
-+ return fragment
-+
-+ def SubstituteMessage(self, msg):
-+ '''Apply substitutions to a tclib.Message object.
-+
-+ Text of the form [message_name] will be replaced by a new placeholder,
-+ whose presentation will take the form the message_name_{UsageCount}, and
-+ whose example will be the message's value. Existing placeholders are
-+ not affected.
-+
-+ Args:
-+ msg: A tclib.Message object.
-+
-+ Returns:
-+ A tclib.Message object, with substitutions done.
-+ '''
-+ from grit import tclib # avoid circular import
-+ counts = {}
-+ text = msg.GetPresentableContent()
-+ placeholders = []
-+ newtext = ''
-+ for f in self.GetExp().split(text):
-+ sub = self._SubFragment(f)
-+ if f != sub:
-+ f = str(f)
-+ count = counts.get(f, 0) + 1
-+ counts[f] = count
-+ name = "%s_%d" % (f[1:-1], count)
-+ placeholders.append(tclib.Placeholder(name, f, sub))
-+ newtext += name
-+ else:
-+ newtext += f
-+ if placeholders:
-+ return tclib.Message(newtext, msg.GetPlaceholders() + placeholders,
-+ msg.GetDescription(), msg.GetMeaning())
-+ else:
-+ return msg
-+
-+
-+class TempDir(object):
-+ '''Creates files with the specified contents in a temporary directory,
-+ for unit testing.
-+ '''
-+
-+ def __init__(self, file_data, mode='w'):
-+ self._tmp_dir_name = tempfile.mkdtemp()
-+ assert not os.listdir(self.GetPath())
-+ for name, contents in file_data.items():
-+ file_path = self.GetPath(name)
-+ dir_path = os.path.split(file_path)[0]
-+ if not os.path.exists(dir_path):
-+ os.makedirs(dir_path)
-+ with open(file_path, mode) as f:
-+ f.write(file_data[name])
-+
-+ def __enter__(self):
-+ return self
-+
-+ def __exit__(self, *exc_info):
-+ self.CleanUp()
-+
-+ def CleanUp(self):
-+ shutil.rmtree(self.GetPath())
-+
-+ def GetPath(self, name=''):
-+ name = os.path.join(self._tmp_dir_name, name)
-+ assert name.startswith(self._tmp_dir_name)
-+ return name
-+
-+ def AsCurrentDir(self):
-+ return self._AsCurrentDirClass(self.GetPath())
-+
-+ class _AsCurrentDirClass(object):
-+ def __init__(self, path):
-+ self.path = path
-+ def __enter__(self):
-+ self.oldpath = os.getcwd()
-+ os.chdir(self.path)
-+ def __exit__(self, *exc_info):
-+ os.chdir(self.oldpath)
-diff --git a/tools/grit/grit/util_unittest.py b/tools/grit/grit/util_unittest.py
-new file mode 100644
-index 0000000000..7d6efaf858
---- /dev/null
-+++ b/tools/grit/grit/util_unittest.py
-@@ -0,0 +1,118 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit test that checks some of util functions.
-+'''
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import unittest
-+
-+import six
-+
-+from grit import util
-+
-+
-+class UtilUnittest(unittest.TestCase):
-+ ''' Tests functions from util
-+ '''
-+
-+ def testNewClassInstance(self):
-+ # Test short class name with no fully qualified package name
-+ # Should fail, it is not supported by the function now (as documented)
-+ cls = util.NewClassInstance('grit.util.TestClassToLoad',
-+ TestBaseClassToLoad)
-+ self.failUnless(cls == None)
-+
-+ # Test non existent class name
-+ cls = util.NewClassInstance('grit.util_unittest.NotExistingClass',
-+ TestBaseClassToLoad)
-+ self.failUnless(cls == None)
-+
-+ # Test valid class name and valid base class
-+ cls = util.NewClassInstance('grit.util_unittest.TestClassToLoad',
-+ TestBaseClassToLoad)
-+ self.failUnless(isinstance(cls, TestBaseClassToLoad))
-+
-+ # Test valid class name with wrong hierarchy
-+ cls = util.NewClassInstance('grit.util_unittest.TestClassNoBase',
-+ TestBaseClassToLoad)
-+ self.failUnless(cls == None)
-+
-+ def testCanonicalLanguage(self):
-+ self.failUnless(util.CanonicalLanguage('en') == 'en')
-+ self.failUnless(util.CanonicalLanguage('pt_br') == 'pt-BR')
-+ self.failUnless(util.CanonicalLanguage('pt-br') == 'pt-BR')
-+ self.failUnless(util.CanonicalLanguage('pt-BR') == 'pt-BR')
-+ self.failUnless(util.CanonicalLanguage('pt/br') == 'pt-BR')
-+ self.failUnless(util.CanonicalLanguage('pt/BR') == 'pt-BR')
-+ self.failUnless(util.CanonicalLanguage('no_no_bokmal') == 'no-NO-BOKMAL')
-+
-+ def testUnescapeHtml(self):
-+ self.failUnless(util.UnescapeHtml('&#1010;') == six.unichr(1010))
-+ self.failUnless(util.UnescapeHtml('&#xABcd;') == six.unichr(43981))
-+
-+ def testRelativePath(self):
-+ """ Verify that MakeRelativePath works in some tricky cases."""
-+
-+ def TestRelativePathCombinations(base_path, other_path, expected_result):
-+ """ Verify that the relative path function works for
-+ the given paths regardless of whether or not they end with
-+ a trailing slash."""
-+ for path1 in [base_path, base_path + os.path.sep]:
-+ for path2 in [other_path, other_path + os.path.sep]:
-+ result = util.MakeRelativePath(path1, path2)
-+ self.failUnless(result == expected_result)
-+
-+ # set-up variables
-+ root_dir = 'c:%sa' % os.path.sep
-+ result1 = '..%sabc' % os.path.sep
-+ path1 = root_dir + 'bc'
-+ result2 = 'bc'
-+ path2 = '%s%s%s' % (root_dir, os.path.sep, result2)
-+ # run the tests
-+ TestRelativePathCombinations(root_dir, path1, result1)
-+ TestRelativePathCombinations(root_dir, path2, result2)
-+
-+ def testReadFile(self):
-+ def Test(data, encoding, expected_result):
-+ with open('testfile', 'wb') as f:
-+ f.write(data)
-+ self.assertEqual(util.ReadFile('testfile', encoding), expected_result)
-+
-+ test_std_newline = b'\xEF\xBB\xBFabc\ndef' # EF BB BF is UTF-8 BOM
-+ newlines = [b'\n', b'\r\n', b'\r']
-+
-+ with util.TempDir({}) as tmp_dir:
-+ with tmp_dir.AsCurrentDir():
-+ for newline in newlines:
-+ test = test_std_newline.replace(b'\n', newline)
-+ Test(test, util.BINARY, test)
-+ # utf-8 doesn't strip BOM
-+ Test(test, 'utf-8', test_std_newline.decode('utf-8'))
-+ # utf-8-sig strips BOM
-+ Test(test, 'utf-8-sig', test_std_newline.decode('utf-8')[1:])
-+ # test another encoding
-+ Test(test, 'cp1252', test_std_newline.decode('cp1252'))
-+ self.assertRaises(UnicodeDecodeError, Test, b'\x80', 'utf-8', None)
-+
-+
-+class TestBaseClassToLoad(object):
-+ pass
-+
-+class TestClassToLoad(TestBaseClassToLoad):
-+ pass
-+
-+class TestClassNoBase(object):
-+ pass
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit/xtb_reader.py b/tools/grit/grit/xtb_reader.py
-new file mode 100644
-index 0000000000..e0f842588a
---- /dev/null
-+++ b/tools/grit/grit/xtb_reader.py
-@@ -0,0 +1,140 @@
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Fast and efficient parser for XTB files.
-+'''
-+
-+from __future__ import print_function
-+
-+import sys
-+import xml.sax
-+import xml.sax.handler
-+
-+import grit.node.base
-+
-+
-+class XtbContentHandler(xml.sax.handler.ContentHandler):
-+ '''A content handler that calls a given callback function for each
-+ translation in the XTB file.
-+ '''
-+
-+ def __init__(self, callback, defs=None, debug=False, target_platform=None):
-+ self.callback = callback
-+ self.debug = debug
-+ # 0 if we are not currently parsing a translation, otherwise the message
-+ # ID of that translation.
-+ self.current_id = 0
-+ # Empty if we are not currently parsing a translation, otherwise the
-+ # parts we have for that translation - a list of tuples
-+ # (is_placeholder, text)
-+ self.current_structure = []
-+ # Set to the language ID when we see the <translationbundle> node.
-+ self.language = ''
-+ # Keep track of the if block we're inside. We can't nest ifs.
-+ self.if_expr = None
-+ # Root defines to be used with if expr.
-+ if defs:
-+ self.defines = defs
-+ else:
-+ self.defines = {}
-+ # Target platform for build.
-+ if target_platform:
-+ self.target_platform = target_platform
-+ else:
-+ self.target_platform = sys.platform
-+
-+ def startElement(self, name, attrs):
-+ if name == 'translation':
-+ assert self.current_id == 0 and len(self.current_structure) == 0, (
-+ "Didn't expect a <translation> element here.")
-+ self.current_id = attrs.getValue('id')
-+ elif name == 'ph':
-+ assert self.current_id != 0, "Didn't expect a <ph> element here."
-+ self.current_structure.append((True, attrs.getValue('name')))
-+ elif name == 'translationbundle':
-+ self.language = attrs.getValue('lang')
-+ elif name in ('if', 'then', 'else'):
-+ assert self.if_expr is None, "Can't nest <if> or use <else> in xtb files"
-+ self.if_expr = attrs.getValue('expr')
-+
-+ def endElement(self, name):
-+ if name == 'translation':
-+ assert self.current_id != 0
-+
-+ defs = self.defines
-+ def pp_ifdef(define):
-+ return define in defs
-+ def pp_if(define):
-+ return define in defs and defs[define]
-+
-+ # If we're in an if block, only call the callback (add the translation)
-+ # if the expression is True.
-+ should_run_callback = True
-+ if self.if_expr:
-+ should_run_callback = grit.node.base.Node.EvaluateExpression(
-+ self.if_expr, self.defines, self.target_platform)
-+ if should_run_callback:
-+ self.callback(self.current_id, self.current_structure)
-+
-+ self.current_id = 0
-+ self.current_structure = []
-+ elif name == 'if':
-+ assert self.if_expr is not None
-+ self.if_expr = None
-+
-+ def characters(self, content):
-+ if self.current_id != 0:
-+ # We are inside a <translation> node so just add the characters to our
-+ # structure.
-+ #
-+ # This naive way of handling characters is OK because in the XTB format,
-+ # <ph> nodes are always empty (always <ph name="XXX"/>) and whitespace
-+ # inside the <translation> node should be preserved.
-+ self.current_structure.append((False, content))
-+
-+
-+class XtbErrorHandler(xml.sax.handler.ErrorHandler):
-+ def error(self, exception):
-+ pass
-+
-+ def fatalError(self, exception):
-+ raise exception
-+
-+ def warning(self, exception):
-+ pass
-+
-+
-+def Parse(xtb_file, callback_function, defs=None, debug=False,
-+ target_platform=None):
-+ '''Parse xtb_file, making a call to callback_function for every translation
-+ in the XTB file.
-+
-+ The callback function must have the signature as described below. The 'parts'
-+ parameter is a list of tuples (is_placeholder, text). The 'text' part is
-+ either the raw text (if is_placeholder is False) or the name of the placeholder
-+ (if is_placeholder is True).
-+
-+ Args:
-+ xtb_file: open('fr.xtb', 'rb')
-+ callback_function: def Callback(msg_id, parts): pass
-+ defs: None, or a dictionary of preprocessor definitions.
-+ debug: Default False. Set True for verbose debug output.
-+ target_platform: None, or a sys.platform-like identifier of the build
-+ target platform.
-+
-+ Return:
-+ The language of the XTB, e.g. 'fr'
-+ '''
-+ # Start by advancing the file pointer past the DOCTYPE thing, as the TC
-+ # uses a path to the DTD that only works in Unix.
-+ # TODO(joi) Remove this ugly hack by getting the TC gang to change the
-+ # XTB files somehow?
-+ front_of_file = xtb_file.read(1024)
-+ xtb_file.seek(front_of_file.find(b'<translationbundle'))
-+
-+ handler = XtbContentHandler(callback=callback_function, defs=defs,
-+ debug=debug, target_platform=target_platform)
-+ xml.sax.parse(xtb_file, handler)
-+ assert handler.language != ''
-+ return handler.language
-diff --git a/tools/grit/grit/xtb_reader_unittest.py b/tools/grit/grit/xtb_reader_unittest.py
-new file mode 100644
-index 0000000000..79c0ac9ef1
---- /dev/null
-+++ b/tools/grit/grit/xtb_reader_unittest.py
-@@ -0,0 +1,110 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Unit tests for grit.xtb_reader'''
-+
-+from __future__ import print_function
-+
-+import io
-+import os
-+import sys
-+if __name__ == '__main__':
-+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-+
-+import unittest
-+
-+from grit import util
-+from grit import xtb_reader
-+from grit.node import empty
-+
-+
-+class XtbReaderUnittest(unittest.TestCase):
-+ def testParsing(self):
-+ xtb_file = io.BytesIO(b'''<?xml version="1.0" encoding="UTF-8"?>
-+ <!DOCTYPE translationbundle>
-+ <translationbundle lang="fr">
-+ <translation id="5282608565720904145">Bingo.</translation>
-+ <translation id="2955977306445326147">Bongo longo.</translation>
-+ <translation id="238824332917605038">Hullo</translation>
-+ <translation id="6629135689895381486"><ph name="PROBLEM_REPORT"/> peut <ph name="START_LINK"/>utilisation excessive de majuscules<ph name="END_LINK"/>.</translation>
-+ <translation id="7729135689895381486">Hello
-+this is another line
-+and another
-+
-+and another after a blank line.</translation>
-+ </translationbundle>''')
-+
-+ messages = []
-+ def Callback(id, structure):
-+ messages.append((id, structure))
-+ xtb_reader.Parse(xtb_file, Callback)
-+ self.failUnless(len(messages[0][1]) == 1)
-+ self.failUnless(messages[3][1][0]) # PROBLEM_REPORT placeholder
-+ self.failUnless(messages[4][0] == '7729135689895381486')
-+ self.failUnless(messages[4][1][7][1] == 'and another after a blank line.')
-+
-+ def testParsingIntoMessages(self):
-+ root = util.ParseGrdForUnittest('''
-+ <messages>
-+ <message name="ID_MEGA">Fantastic!</message>
-+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
-+ </messages>''')
-+
-+ msgs, = root.GetChildrenOfType(empty.MessagesNode)
-+ clique_mega = msgs.children[0].GetCliques()[0]
-+ msg_mega = clique_mega.GetMessage()
-+ clique_hello_user = msgs.children[1].GetCliques()[0]
-+ msg_hello_user = clique_hello_user.GetMessage()
-+
-+ xtb_file = io.BytesIO(b'''<?xml version="1.0" encoding="UTF-8"?>
-+ <!DOCTYPE translationbundle>
-+ <translationbundle lang="is">
-+ <translation id="%s">Meirihattar!</translation>
-+ <translation id="%s">Saelir <ph name="USERNAME"/></translation>
-+ </translationbundle>''' % (
-+ msg_mega.GetId().encode('utf-8'),
-+ msg_hello_user.GetId().encode('utf-8')))
-+
-+ xtb_reader.Parse(xtb_file,
-+ msgs.UberClique().GenerateXtbParserCallback('is'))
-+ self.assertEqual('Meirihattar!',
-+ clique_mega.MessageForLanguage('is').GetRealContent())
-+ self.failUnless('Saelir %s',
-+ clique_hello_user.MessageForLanguage('is').GetRealContent())
-+
-+ def testIfNodesWithUseNameForId(self):
-+ root = util.ParseGrdForUnittest('''
-+ <messages>
-+ <message name="ID_BINGO" use_name_for_id="true">Bingo!</message>
-+ </messages>''')
-+ msgs, = root.GetChildrenOfType(empty.MessagesNode)
-+ clique = msgs.children[0].GetCliques()[0]
-+ msg = clique.GetMessage()
-+
-+ xtb_file = io.BytesIO(b'''<?xml version="1.0" encoding="UTF-8"?>
-+ <!DOCTYPE translationbundle>
-+ <translationbundle lang="is">
-+ <if expr="is_linux">
-+ <translation id="ID_BINGO">Bongo!</translation>
-+ </if>
-+ <if expr="not is_linux">
-+ <translation id="ID_BINGO">Congo!</translation>
-+ </if>
-+ </translationbundle>''')
-+ xtb_reader.Parse(xtb_file,
-+ msgs.UberClique().GenerateXtbParserCallback('is'),
-+ target_platform='darwin')
-+ self.assertEqual('Congo!', clique.MessageForLanguage('is').GetRealContent())
-+
-+ def testParseLargeFile(self):
-+ def Callback(id, structure):
-+ pass
-+ path = util.PathFromRoot('grit/testdata/generated_resources_fr.xtb')
-+ with open(path, 'rb') as xtb:
-+ xtb_reader.Parse(xtb, Callback)
-+
-+
-+if __name__ == '__main__':
-+ unittest.main()
-diff --git a/tools/grit/grit_info.py b/tools/grit/grit_info.py
-new file mode 100644
-index 0000000000..55738f25f6
---- /dev/null
-+++ b/tools/grit/grit_info.py
-@@ -0,0 +1,173 @@
-+#!/usr/bin/env python
-+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+'''Tool to determine inputs and outputs of a grit file.
-+'''
-+
-+from __future__ import print_function
-+
-+import optparse
-+import os
-+import posixpath
-+import sys
-+
-+from grit import grd_reader
-+from grit import util
-+
-+class WrongNumberOfArguments(Exception):
-+ pass
-+
-+
-+def Outputs(filename, defines, ids_file, target_platform=None):
-+ grd = grd_reader.Parse(
-+ filename, defines=defines, tags_to_ignore=set(['messages']),
-+ first_ids_file=ids_file, target_platform=target_platform)
-+
-+ target = []
-+ lang_folders = {}
-+ # Add all explicitly-specified output files
-+ for output in grd.GetOutputFiles():
-+ path = output.GetFilename()
-+ target.append(path)
-+
-+ if path.endswith('.h'):
-+ path, filename = os.path.split(path)
-+ if output.attrs['lang']:
-+ lang_folders[output.attrs['lang']] = os.path.dirname(path)
-+
-+ return [t.replace('\\', '/') for t in target]
-+
-+
-+def GritSourceFiles():
-+ files = []
-+ grit_root_dir = os.path.relpath(os.path.dirname(__file__), os.getcwd())
-+ for root, dirs, filenames in os.walk(grit_root_dir):
-+ grit_src = [os.path.join(root, f) for f in filenames
-+ if f.endswith('.py') and not f.endswith('_unittest.py')]
-+ files.extend(grit_src)
-+ return sorted(files)
-+
-+
-+def Inputs(filename, defines, ids_file, target_platform=None):
-+ grd = grd_reader.Parse(
-+ filename, debug=False, defines=defines, tags_to_ignore=set(['message']),
-+ first_ids_file=ids_file, target_platform=target_platform)
-+ files = set()
-+ for lang, ctx, fallback in grd.GetConfigurations():
-+ # TODO(tdanderson): Refactor all places which perform the action of setting
-+ # output attributes on the root. See crbug.com/503637.
-+ grd.SetOutputLanguage(lang or grd.GetSourceLanguage())
-+ grd.SetOutputContext(ctx)
-+ grd.SetFallbackToDefaultLayout(fallback)
-+ for node in grd.ActiveDescendants():
-+ with node:
-+ if (node.name == 'structure' or node.name == 'skeleton' or
-+ (node.name == 'file' and node.parent and
-+ node.parent.name == 'translations')):
-+ path = node.GetInputPath()
-+ if path is not None:
-+ files.add(grd.ToRealPath(path))
-+
-+ # If it's a flattened node, grab inlined resources too.
-+ if node.name == 'structure' and node.attrs['flattenhtml'] == 'true':
-+ node.RunPreSubstitutionGatherer()
-+ files.update(node.GetHtmlResourceFilenames())
-+ elif node.name == 'grit':
-+ first_ids_file = node.GetFirstIdsFile()
-+ if first_ids_file:
-+ files.add(first_ids_file)
-+ elif node.name == 'include':
-+ files.add(grd.ToRealPath(node.GetInputPath()))
-+ # If it's a flattened node, grab inlined resources too.
-+ if node.attrs['flattenhtml'] == 'true':
-+ files.update(node.GetHtmlResourceFilenames())
-+ elif node.name == 'part':
-+ files.add(util.normpath(os.path.join(os.path.dirname(filename),
-+ node.GetInputPath())))
-+
-+ cwd = os.getcwd()
-+ return [os.path.relpath(f, cwd) for f in sorted(files)]
-+
-+
-+def PrintUsage():
-+ print('USAGE: ./grit_info.py --inputs [-D foo] [-f resource_ids] <grd-file>')
-+ print(' ./grit_info.py --outputs [-D foo] [-f resource_ids] ' +
-+ '<out-prefix> <grd-file>')
-+
-+
-+def DoMain(argv):
-+ os.environ['cwd'] = os.getcwd()
-+
-+ parser = optparse.OptionParser()
-+ parser.add_option("--inputs", action="store_true", dest="inputs")
-+ parser.add_option("--outputs", action="store_true", dest="outputs")
-+ parser.add_option("-D", action="append", dest="defines", default=[])
-+ # grit build also supports '-E KEY=VALUE', support that to share command
-+ # line flags.
-+ parser.add_option("-E", action="append", dest="build_env", default=[])
-+ parser.add_option("-p", action="store", dest="predetermined_ids_file")
-+ parser.add_option("-w", action="append", dest="whitelist_files", default=[])
-+ parser.add_option("-f", dest="ids_file", default="")
-+ parser.add_option("-t", dest="target_platform", default=None)
-+
-+ options, args = parser.parse_args(argv)
-+
-+ defines = {}
-+ for define in options.defines:
-+ name, val = util.ParseDefine(define)
-+ defines[name] = val
-+
-+ for env_pair in options.build_env:
-+ (env_name, env_value) = env_pair.split('=', 1)
-+ os.environ[env_name] = env_value
-+
-+ if options.inputs:
-+ if len(args) > 1:
-+ raise WrongNumberOfArguments("Expected 0 or 1 arguments for --inputs.")
-+
-+ inputs = []
-+ if len(args) == 1:
-+ filename = args[0]
-+ inputs = Inputs(filename, defines, options.ids_file,
-+ options.target_platform)
-+
-+ # Add in the grit source files. If one of these change, we want to re-run
-+ # grit.
-+ inputs.extend(GritSourceFiles())
-+ inputs = [f.replace('\\', '/') for f in inputs]
-+
-+ if len(args) == 1:
-+ # Include grd file as second input (works around gyp expecting it).
-+ inputs.insert(1, args[0])
-+ if options.whitelist_files:
-+ inputs.extend(options.whitelist_files)
-+ return '\n'.join(inputs)
-+ elif options.outputs:
-+ if len(args) != 2:
-+ raise WrongNumberOfArguments(
-+ "Expected exactly 2 arguments for --outputs.")
-+
-+ prefix, filename = args
-+ outputs = [posixpath.join(prefix, f)
-+ for f in Outputs(filename, defines,
-+ options.ids_file, options.target_platform)]
-+ return '\n'.join(outputs)
-+ else:
-+ raise WrongNumberOfArguments("Expected --inputs or --outputs.")
-+
-+
-+def main(argv):
-+ try:
-+ result = DoMain(argv[1:])
-+ except WrongNumberOfArguments as e:
-+ PrintUsage()
-+ print(e)
-+ return 1
-+ print(result)
-+ return 0
-+
-+
-+if __name__ == '__main__':
-+ sys.exit(main(sys.argv))
-diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni
-new file mode 100644
-index 0000000000..fb107ef1a3
---- /dev/null
-+++ b/tools/grit/grit_rule.gni
-@@ -0,0 +1,485 @@
-+# Copyright 2014 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+# Instantiate grit. This will produce a script target to run grit (named
-+# ${target_name}_grit), and a static library that compiles the .cc files.
-+#
-+# In general, code should depend on the static library. However, if the
-+# generated files are only processed by other actions to generate other
-+# files, it is possible to depend on the script target directly.
-+#
-+# Parameters
-+#
-+# source (required)
-+# Path to .grd file.
-+#
-+# enable_input_discovery_for_gn_analyze (default=true)
-+# Runs grit_info.py via exec_script() when compute_inputs_for_analyze=true
-+# in order to discover all files that affect this target.
-+# Turn this off when the .grd file is generated, or an <include> with
-+# flattenhtml=true points to a generated file.
-+# For "gn analyze" to be correct with this arg disabled, all inputs
-+# must be listed via |inputs|.
-+#
-+# inputs (optional)
-+# List of additional files, required for grit to process source file.
-+#
-+# outputs (required)
-+# List of outputs from grit, relative to the target_gen_dir. Grit will
-+# verify at build time that this list is correct and will fail if there
-+# is a mismatch between the outputs specified by the .grd file and the
-+# outputs list here.
-+#
-+# To get this list, you can look in the .grd file for
-+# <output filename="..." and put those filename here. The base directory
-+# of the list in Grit and the output list specified in the GN grit target
-+# are the same (the target_gen_dir) so you can generally copy the names
-+# exactly.
-+#
-+# To get the list of outputs programatically, run:
-+# python tools/grit/grit_info.py --outputs . path/to/your.grd
-+# And strip the leading "./" from the output files.
-+#
-+# defines (optional)
-+# Extra defines to pass to grit (on top of the global grit_defines list).
-+#
-+# grit_flags (optional)
-+# List of strings containing extra command-line flags to pass to Grit.
-+#
-+# resource_ids (optional)
-+# Path to a grit "firstidsfile". Default is
-+# //tools/gritsettings/resource_ids. Set to "" to use the value specified
-+# in the <grit> nodes of the processed files.
-+#
-+# output_dir (optional)
-+# Directory for generated files. If you specify this, you will often
-+# want to specify output_name if the target name is not particularly
-+# unique, since this can cause files from multiple grit targets to
-+# overwrite each other.
-+#
-+# output_name (optional)
-+# Provide an alternate base name for the generated files, like the .d
-+# files. Normally these are based on the target name and go in the
-+# output_dir, but if multiple targets with the same name end up in
-+# the same output_dir, they can collide.
-+#
-+# configs (optional)
-+# List of additional configs to be applied to the generated target.
-+#
-+# deps (optional)
-+# testonly (optional)
-+# visibility (optional)
-+# Normal meaning.
-+#
-+# Example
-+#
-+# grit("my_resources") {
-+# # Source and outputs are required.
-+# source = "myfile.grd"
-+# outputs = [
-+# "foo_strings.h",
-+# "foo_strings.pak",
-+# ]
-+#
-+# grit_flags = [ "-E", "foo=bar" ] # Optional extra flags.
-+# # You can also put deps here if the grit source depends on generated
-+# # files.
-+# }
-+import("//build/config/chrome_build.gni")
-+import("//build/config/chromeos/ui_mode.gni")
-+import("//build/config/compiler/compiler.gni")
-+import("//build/config/compute_inputs_for_analyze.gni")
-+import("//build/config/crypto.gni")
-+import("//build/config/features.gni")
-+import("//build/config/sanitizers/sanitizers.gni")
-+import("//build/config/ui.gni")
-+import("//build/toolchain/gcc_toolchain.gni")
-+
-+declare_args() {
-+ enable_resource_whitelist_generation = is_android && is_official_build
-+}
-+
-+if (enable_resource_whitelist_generation) {
-+ assert(target_os == "android" || target_os == "win",
-+ "unsupported platform for resource whitelist generation")
-+ assert(
-+ symbol_level > 0 && !strip_debug_info && !is_component_build,
-+ "resource whitelist generation only works on non-component builds with debug info enabled.")
-+}
-+
-+grit_defines = []
-+
-+if (is_mac || is_win || is_linux || is_chromeos || is_ios) {
-+ grit_defines += [
-+ "-D",
-+ "scale_factors=2x",
-+ ]
-+}
-+
-+# Mac and iOS want Title Case strings.
-+use_titlecase_in_grd_files = is_apple
-+if (use_titlecase_in_grd_files) {
-+ grit_defines += [
-+ "-D",
-+ "use_titlecase",
-+ ]
-+}
-+
-+if (is_chrome_branded) {
-+ grit_defines += [
-+ "-D",
-+ "_google_chrome",
-+ "-E",
-+ "CHROMIUM_BUILD=google_chrome",
-+ ]
-+} else {
-+ grit_defines += [
-+ "-D",
-+ "_chromium",
-+ "-E",
-+ "CHROMIUM_BUILD=chromium",
-+ ]
-+}
-+
-+if (is_chromeos) {
-+ grit_defines += [
-+ "-D",
-+ "chromeos",
-+ ]
-+}
-+
-+if (chromeos_is_browser_only) {
-+ grit_defines += [
-+ "-D",
-+ "lacros",
-+ ]
-+}
-+
-+if (is_desktop_linux) {
-+ grit_defines += [
-+ "-D",
-+ "desktop_linux",
-+ ]
-+}
-+
-+if (toolkit_views) {
-+ grit_defines += [
-+ "-D",
-+ "toolkit_views",
-+ ]
-+}
-+
-+if (use_aura) {
-+ grit_defines += [
-+ "-D",
-+ "use_aura",
-+ ]
-+}
-+
-+if (use_nss_certs) {
-+ grit_defines += [
-+ "-D",
-+ "use_nss_certs",
-+ ]
-+}
-+
-+if (use_ozone) {
-+ grit_defines += [
-+ "-D",
-+ "use_ozone",
-+ ]
-+}
-+
-+if (is_android) {
-+ grit_defines += [
-+ "-E",
-+ "ANDROID_JAVA_TAGGED_ONLY=true",
-+ ]
-+}
-+
-+# When cross-compiling, explicitly pass the target system to grit.
-+if (current_toolchain != host_toolchain) {
-+ if (is_android) {
-+ grit_defines += [
-+ "-t",
-+ "android",
-+ ]
-+ }
-+ if (is_ios) {
-+ grit_defines += [
-+ "-t",
-+ "ios",
-+ ]
-+ }
-+ if (is_linux || is_chromeos) {
-+ grit_defines += [
-+ "-t",
-+ "linux2",
-+ ]
-+ }
-+ if (is_mac) {
-+ grit_defines += [
-+ "-t",
-+ "darwin",
-+ ]
-+ }
-+ if (is_win) {
-+ grit_defines += [
-+ "-t",
-+ "win32",
-+ ]
-+ }
-+}
-+
-+_strip_resource_files = is_android && is_official_build
-+_js_minifier = "//tools/grit/minify_with_uglify.py"
-+_css_minifier = "//tools/grit/minimize_css.py"
-+
-+grit_resource_id_target = "//tools/gritsettings:default_resource_ids"
-+grit_resource_id_file =
-+ get_label_info(grit_resource_id_target, "target_gen_dir") +
-+ "/default_resource_ids"
-+grit_info_script = "//tools/grit/grit_info.py"
-+
-+# TODO(asvitkine): Add predetermined ids files for other platforms.
-+grit_predetermined_resource_ids_file = ""
-+if (is_mac) {
-+ grit_predetermined_resource_ids_file =
-+ "//tools/gritsettings/startup_resources_mac.txt"
-+}
-+if (is_win) {
-+ grit_predetermined_resource_ids_file =
-+ "//tools/gritsettings/startup_resources_win.txt"
-+}
-+
-+template("grit") {
-+ if (defined(invoker.output_dir)) {
-+ _output_dir = invoker.output_dir
-+ } else {
-+ _output_dir = target_gen_dir
-+ }
-+
-+ _grit_outputs =
-+ get_path_info(rebase_path(invoker.outputs, ".", _output_dir), "abspath")
-+
-+ # Add .info output for all pak files
-+ _pak_info_outputs = []
-+ foreach(output, _grit_outputs) {
-+ if (get_path_info(output, "extension") == "pak") {
-+ _pak_info_outputs += [ output + ".info" ]
-+ }
-+ }
-+
-+ if (defined(invoker.output_name)) {
-+ _grit_output_name = invoker.output_name
-+ } else {
-+ _grit_output_name = target_name
-+ }
-+
-+ _grit_custom_target = target_name + "_grit"
-+ action(_grit_custom_target) {
-+ testonly = defined(invoker.testonly) && invoker.testonly
-+
-+ script = "//tools/grit/grit.py"
-+ depfile = "$target_gen_dir/$target_name.d"
-+
-+ inputs = [ invoker.source ]
-+ deps = [ "//tools/grit:grit_sources" ]
-+ outputs = [ "${depfile}.stamp" ] + _grit_outputs + _pak_info_outputs
-+
-+ _grit_flags = grit_defines
-+
-+ # Add extra defines with -D flags.
-+ if (defined(invoker.defines)) {
-+ foreach(i, invoker.defines) {
-+ _grit_flags += [
-+ "-D",
-+ i,
-+ ]
-+ }
-+ }
-+
-+ if (defined(invoker.grit_flags)) {
-+ _grit_flags += invoker.grit_flags
-+ }
-+
-+ _rebased_source_path = rebase_path(invoker.source, root_build_dir)
-+ _enable_grit_info =
-+ !defined(invoker.enable_input_discovery_for_gn_analyze) ||
-+ invoker.enable_input_discovery_for_gn_analyze
-+ if (_enable_grit_info && compute_inputs_for_analyze) {
-+ # Only call exec_script when the user has explicitly opted into greater
-+ # precision at the expense of performance.
-+ _rel_inputs = exec_script("//tools/grit/grit_info.py",
-+ [
-+ "--inputs",
-+ _rebased_source_path,
-+ ] + _grit_flags,
-+ "list lines")
-+ inputs += rebase_path(_rel_inputs, ".", root_build_dir)
-+ }
-+
-+ args = [
-+ "-i",
-+ _rebased_source_path,
-+ "build",
-+ "-o",
-+ rebase_path(_output_dir, root_build_dir),
-+ "--depdir",
-+ ".",
-+ "--depfile",
-+ rebase_path(depfile, root_build_dir),
-+ "--write-only-new=1",
-+ "--depend-on-stamp",
-+ ] + _grit_flags
-+
-+ # Add brotli executable if using brotli.
-+ if (defined(invoker.use_brotli) && invoker.use_brotli) {
-+ _brotli_target = "//third_party/brotli:brotli($host_toolchain)"
-+ _brotli_executable = get_label_info(_brotli_target, "root_out_dir") +
-+ "/" + get_label_info(_brotli_target, "name")
-+ if (host_os == "win") {
-+ _brotli_executable += ".exe"
-+ }
-+
-+ inputs += [ _brotli_executable ]
-+ args += [
-+ "--brotli",
-+ rebase_path(_brotli_executable, root_build_dir),
-+ ]
-+ }
-+
-+ _resource_ids = grit_resource_id_file
-+ if (defined(invoker.resource_ids)) {
-+ _resource_ids = invoker.resource_ids
-+ }
-+
-+ if (_resource_ids != "") {
-+ inputs += [ _resource_ids ]
-+ args += [
-+ "-f",
-+ rebase_path(_resource_ids, root_build_dir),
-+ ]
-+ if (_resource_ids == grit_resource_id_file) {
-+ deps += [ grit_resource_id_target ]
-+ }
-+ }
-+ if (grit_predetermined_resource_ids_file != "") {
-+ inputs += [ grit_predetermined_resource_ids_file ]
-+ args += [
-+ "-p",
-+ rebase_path(grit_predetermined_resource_ids_file, root_build_dir),
-+ ]
-+ }
-+
-+ # We want to make sure the declared outputs actually match what Grit is
-+ # writing. We write the list to a file (some of the output lists are long
-+ # enough to not fit on a Windows command line) and ask Grit to verify those
-+ # are the actual outputs at runtime.
-+ _asserted_list_file =
-+ "$target_out_dir/${_grit_output_name}_expected_outputs.txt"
-+ write_file(_asserted_list_file,
-+ rebase_path(invoker.outputs, root_build_dir, _output_dir))
-+ inputs += [ _asserted_list_file ]
-+ args += [
-+ "--assert-file-list",
-+ rebase_path(_asserted_list_file, root_build_dir),
-+ ]
-+
-+ if (enable_resource_whitelist_generation) {
-+ _rc_grit_outputs = []
-+ foreach(output, _grit_outputs) {
-+ if (get_path_info(output, "extension") == "rc") {
-+ _rc_grit_outputs += [ output ]
-+ }
-+ }
-+
-+ if (_rc_grit_outputs != []) {
-+ # Resource whitelisting cannot be used with .rc files.
-+ # Make sure that there aren't any .pak outputs which would require
-+ # whitelist annotations.
-+ assert(_pak_info_outputs == [], "can't combine .pak and .rc outputs")
-+ } else {
-+ args += [ "--whitelist-support" ]
-+ }
-+ }
-+ if (_strip_resource_files) {
-+ _js_minifier_command = rebase_path(_js_minifier, root_build_dir)
-+ _css_minifier_command = rebase_path(_css_minifier, root_build_dir)
-+ args += [
-+ "--js-minifier",
-+ _js_minifier_command,
-+ "--css-minifier",
-+ _css_minifier_command,
-+ ]
-+ inputs += [
-+ _js_minifier,
-+ _css_minifier,
-+ ]
-+ }
-+
-+ if (defined(invoker.visibility)) {
-+ # This needs to include both what the invoker specified (since they
-+ # probably include generated headers from this target), as well as the
-+ # generated source set (since there's no guarantee that the visibility
-+ # specified by the invoker includes our target).
-+ #
-+ # Only define visibility at all if the invoker specified it. Otherwise,
-+ # we want to keep the public "no visibility specified" default.
-+ visibility = [ ":${invoker.target_name}" ] + invoker.visibility
-+ }
-+
-+ if (defined(invoker.use_brotli) && invoker.use_brotli) {
-+ if (is_mac && is_asan) {
-+ deps += [ "//tools/grit:brotli_mac_asan_workaround" ]
-+ } else {
-+ deps += [ "//third_party/brotli:brotli($host_toolchain)" ]
-+ }
-+ }
-+ if (defined(invoker.deps)) {
-+ deps += invoker.deps
-+ }
-+ if (defined(invoker.inputs)) {
-+ inputs += invoker.inputs
-+ }
-+ }
-+
-+ # This is the thing that people actually link with, it must be named the
-+ # same as the argument the template was invoked with.
-+ source_set(target_name) {
-+ testonly = defined(invoker.testonly) && invoker.testonly
-+
-+ # Since we generate a file, we need to be run before the targets that
-+ # depend on us.
-+ sources = []
-+ foreach(_output, _grit_outputs) {
-+ _extension = get_path_info(_output, "extension")
-+ if (_extension != "json" && _extension != "gz" && _extension != "pak" &&
-+ _extension != "xml") {
-+ sources += [ _output ]
-+ }
-+ }
-+
-+ # Deps set on the template invocation will go on the action that runs
-+ # grit above rather than this library. This target needs to depend on the
-+ # action publicly so other scripts can take the outputs from the grit
-+ # script as inputs.
-+ public_deps = [ ":$_grit_custom_target" ]
-+
-+ deps = [ "//base" ]
-+
-+ if (defined(invoker.public_configs)) {
-+ public_configs += invoker.public_configs
-+ }
-+
-+ if (defined(invoker.configs)) {
-+ configs += invoker.configs
-+ }
-+
-+ if (defined(invoker.visibility)) {
-+ visibility = invoker.visibility
-+ }
-+ output_name = _grit_output_name
-+ }
-+}
-diff --git a/tools/grit/minify_with_uglify.py b/tools/grit/minify_with_uglify.py
-new file mode 100644
-index 0000000000..788ffa6a75
---- /dev/null
-+++ b/tools/grit/minify_with_uglify.py
-@@ -0,0 +1,44 @@
-+#!/usr/bin/env python
-+# Copyright 2019 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+import tempfile
-+
-+_HERE_PATH = os.path.dirname(__file__)
-+_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..'))
-+sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node'))
-+
-+import node
-+import node_modules
-+
-+def Minify(source):
-+ # Open two temporary files, so that uglify can read the input from one and
-+ # write its output to the other.
-+ with tempfile.NamedTemporaryFile(suffix='.js') as infile, \
-+ tempfile.NamedTemporaryFile(suffix='.js') as outfile:
-+ infile.write(source)
-+ infile.flush();
-+ node.RunNode([
-+ node_modules.PathToUglify(), infile.name, '--output', outfile.name])
-+ result = outfile.read()
-+ return result
-+
-+
-+def main():
-+ orig_stdout = sys.stdout
-+ result = ''
-+ try:
-+ sys.stdout = sys.stderr
-+ result = Minify(sys.stdin.read())
-+ finally:
-+ sys.stdout = orig_stdout
-+ print(result)
-+
-+
-+if __name__ == '__main__':
-+ main()
-diff --git a/tools/grit/minimize_css.py b/tools/grit/minimize_css.py
-new file mode 100644
-index 0000000000..2c3b8aeb1e
---- /dev/null
-+++ b/tools/grit/minimize_css.py
-@@ -0,0 +1,105 @@
-+#!/usr/bin/env python
-+# Copyright 2016 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+import re
-+import sys
-+
-+class CSSMinimizer(object):
-+
-+ INITIAL = 0
-+ MAYBE_COMMENT_START = 1
-+ INSIDE_COMMENT = 2
-+ MAYBE_COMMENT_END = 3
-+ INSIDE_SINGLE_QUOTE = 4
-+ INSIDE_SINGLE_QUOTE_ESCAPE = 5
-+ INSIDE_DOUBLE_QUOTE = 6
-+ INSIDE_DOUBLE_QUOTE_ESCAPE = 7
-+
-+ def __init__(self):
-+ self._output = ''
-+ self._codeblock = ''
-+
-+ def flush_codeblock(self):
-+ stripped = re.sub(r"\s+", ' ', self._codeblock)
-+ stripped = re.sub(r";?\s*(?P<op>[{};])\s*", r'\g<op>', stripped)
-+ self._output += stripped
-+ self._codeblock = ''
-+
-+ def parse(self, content):
-+ state = self.INITIAL
-+ for char in content:
-+ if state == self.INITIAL:
-+ if char == '/':
-+ state = self.MAYBE_COMMENT_START
-+ elif char == "'":
-+ self.flush_codeblock()
-+ self._output += char
-+ state = self.INSIDE_SINGLE_QUOTE
-+ elif char == '"':
-+ self.flush_codeblock()
-+ self._output += char
-+ state = self.INSIDE_DOUBLE_QUOTE
-+ else:
-+ self._codeblock += char
-+ elif state == self.MAYBE_COMMENT_START:
-+ if char == '*':
-+ self.flush_codeblock()
-+ state = self.INSIDE_COMMENT
-+ else:
-+ self._codeblock += '/' + char
-+ state = self.INITIAL
-+ elif state == self.INSIDE_COMMENT:
-+ if char == '*':
-+ state = self.MAYBE_COMMENT_END
-+ else:
-+ pass
-+ elif state == self.MAYBE_COMMENT_END:
-+ if char == '/':
-+ state = self.INITIAL
-+ else:
-+ state = self.INSIDE_COMMENT
-+ elif state == self.INSIDE_SINGLE_QUOTE:
-+ if char == '\\':
-+ self._output += char
-+ state = self.INSIDE_SINGLE_QUOTE_ESCAPE
-+ elif char == "'":
-+ self._output += char
-+ state = self.INITIAL
-+ else:
-+ self._output += char
-+ elif state == self.INSIDE_SINGLE_QUOTE_ESCAPE:
-+ self._output += char
-+ state = self.INSIDE_SINGLE_QUOTE
-+ elif state == self.INSIDE_DOUBLE_QUOTE:
-+ if char == '\\':
-+ self._output += char
-+ state = self.INSIDE_DOUBLE_QUOTE_ESCAPE
-+ elif char == '"':
-+ self._output += char
-+ state = self.INITIAL
-+ else:
-+ self._output += char
-+ elif state == self.INSIDE_DOUBLE_QUOTE_ESCAPE:
-+ self._output += char
-+ state = self.INSIDE_DOUBLE_QUOTE
-+
-+ self.flush_codeblock()
-+ self._output = self._output.strip()
-+ return self._output
-+
-+ @classmethod
-+ def minimize_css(cls, content):
-+ minimizer = CSSMinimizer()
-+ return minimizer.parse(content)
-+
-+def main():
-+ result = ''
-+ try:
-+ result = CSSMinimizer.minimize_css(sys.stdin.read())
-+ finally:
-+ print(result)
-+
-+if __name__ == '__main__':
-+ main()
-diff --git a/tools/grit/minimize_css_unittest.py b/tools/grit/minimize_css_unittest.py
-new file mode 100644
-index 0000000000..cddc313078
---- /dev/null
-+++ b/tools/grit/minimize_css_unittest.py
-@@ -0,0 +1,58 @@
-+#!/usr/bin/env python
-+# Copyright 2016 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+import unittest
-+
-+import minimize_css
-+
-+
-+class CSSMinimizerTest(unittest.TestCase):
-+
-+ def test_simple(self):
-+ source = """
-+ div {
-+ color: blue;
-+ }
-+ """
-+ minimized = minimize_css.CSSMinimizer.minimize_css(source)
-+ self.assertEquals(minimized, "div{color: blue}")
-+
-+ def test_attribute_selectors(self):
-+ source = """
-+ input[type="search" i]::-webkit-textfield-decoration-container {
-+ direction: ltr;
-+ }
-+ """
-+ minimized = minimize_css.CSSMinimizer.minimize_css(source)
-+ self.assertEquals(
-+ minimized,
-+ # pylint: disable=line-too-long
-+ """input[type="search" i]::-webkit-textfield-decoration-container{direction: ltr}""")
-+
-+ def test_strip_comment(self):
-+ source = """
-+ /* header */
-+ html {
-+ /* inside block */
-+ display: block;
-+ }
-+ /* footer */
-+ """
-+ minimized = minimize_css.CSSMinimizer.minimize_css(source)
-+ self.assertEquals(minimized, "html{ display: block}")
-+
-+ def test_no_strip_inside_quotes(self):
-+ source = """div[foo=' bar ']"""
-+ minimized = minimize_css.CSSMinimizer.minimize_css(source)
-+ self.assertEquals(minimized, source)
-+
-+ source = """div[foo=" bar "]"""
-+ minimized = minimize_css.CSSMinimizer.minimize_css(source)
-+ self.assertEquals(minimized, source)
-+
-+ def test_escape_string(self):
-+ source = """content: " <a onclick=\\\"javascript: alert ( 'foobar' ); \\\">";"""
-+ minimized = minimize_css.CSSMinimizer.minimize_css(source)
-+ self.assertEquals(minimized, source)
-diff --git a/tools/grit/pak_util.py b/tools/grit/pak_util.py
-new file mode 100644
-index 0000000000..ede638bbe1
---- /dev/null
-+++ b/tools/grit/pak_util.py
-@@ -0,0 +1,223 @@
-+#!/usr/bin/env python
-+# Copyright 2017 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""A tool for interacting with .pak files.
-+
-+For details on the pak file format, see:
-+https://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
-+"""
-+
-+from __future__ import print_function
-+
-+import argparse
-+import gzip
-+import hashlib
-+import os
-+import shutil
-+import sys
-+import tempfile
-+
-+# Import grit first to get local third_party modules.
-+import grit # pylint: disable=ungrouped-imports,unused-import
-+
-+import six
-+
-+from grit.format import data_pack
-+
-+
-+def _RepackMain(args):
-+ output_info_filepath = args.output_pak_file + '.info'
-+ if args.compress:
-+ # If the file needs to be compressed, call RePack with a tempfile path,
-+ # then compress the tempfile to args.output_pak_file.
-+ temp_outfile = tempfile.NamedTemporaryFile()
-+ out_path = temp_outfile.name
-+ # Strip any non .pak extension from the .info output file path.
-+ splitext = os.path.splitext(args.output_pak_file)
-+ if splitext[1] != '.pak':
-+ output_info_filepath = splitext[0] + '.info'
-+ else:
-+ out_path = args.output_pak_file
-+ data_pack.RePack(out_path, args.input_pak_files, args.whitelist,
-+ args.suppress_removed_key_output,
-+ output_info_filepath=output_info_filepath)
-+ if args.compress:
-+ with open(args.output_pak_file, 'wb') as out:
-+ with gzip.GzipFile(filename='', mode='wb', fileobj=out, mtime=0) as outgz:
-+ shutil.copyfileobj(temp_outfile, outgz)
-+
-+
-+def _ExtractMain(args):
-+ pak = data_pack.ReadDataPack(args.pak_file)
-+ if args.textual_id:
-+ info_dict = data_pack.ReadGrdInfo(args.pak_file)
-+ for resource_id, payload in pak.resources.items():
-+ filename = (
-+ info_dict[resource_id].textual_id
-+ if args.textual_id else str(resource_id))
-+ path = os.path.join(args.output_dir, filename)
-+ with open(path, 'w') as f:
-+ f.write(payload)
-+
-+
-+def _CreateMain(args):
-+ pak = {}
-+ for name in os.listdir(args.input_dir):
-+ try:
-+ resource_id = int(name)
-+ except:
-+ continue
-+ filename = os.path.join(args.input_dir, name)
-+ if os.path.isfile(filename):
-+ with open(filename, 'rb') as f:
-+ pak[resource_id] = f.read()
-+ data_pack.WriteDataPack(pak, args.output_pak_file, data_pack.UTF8)
-+
-+
-+def _PrintMain(args):
-+ pak = data_pack.ReadDataPack(args.pak_file)
-+ if args.textual_id:
-+ info_dict = data_pack.ReadGrdInfo(args.pak_file)
-+ output = args.output
-+ encoding = 'binary'
-+ if pak.encoding == 1:
-+ encoding = 'utf-8'
-+ elif pak.encoding == 2:
-+ encoding = 'utf-16'
-+ else:
-+ encoding = '?' + str(pak.encoding)
-+
-+ output.write('version: {}\n'.format(pak.version))
-+ output.write('encoding: {}\n'.format(encoding))
-+ output.write('num_resources: {}\n'.format(len(pak.resources)))
-+ output.write('num_aliases: {}\n'.format(len(pak.aliases)))
-+ breakdown = ', '.join('{}: {}'.format(*x) for x in pak.sizes)
-+ output.write('total_size: {} ({})\n'.format(pak.sizes.total, breakdown))
-+
-+ try_decode = args.decode and encoding.startswith('utf')
-+ # Print IDs in ascending order, since that's the order in which they appear in
-+ # the file (order is lost by Python dict).
-+ for resource_id in sorted(pak.resources):
-+ data = pak.resources[resource_id]
-+ canonical_id = pak.aliases.get(resource_id, resource_id)
-+ desc = '<data>'
-+ if try_decode:
-+ try:
-+ desc = six.text_type(data, encoding)
-+ if len(desc) > 60:
-+ desc = desc[:60] + u'...'
-+ desc = desc.replace('\n', '\\n')
-+ except UnicodeDecodeError:
-+ pass
-+ sha1 = hashlib.sha1(data).hexdigest()[:10]
-+ if args.textual_id:
-+ textual_id = info_dict[resource_id].textual_id
-+ canonical_textual_id = info_dict[canonical_id].textual_id
-+ output.write(
-+ u'Entry(id={}, canonical_id={}, size={}, sha1={}): {}\n'.format(
-+ textual_id, canonical_textual_id, len(data), sha1,
-+ desc).encode('utf-8'))
-+ else:
-+ output.write(
-+ u'Entry(id={}, canonical_id={}, size={}, sha1={}): {}\n'.format(
-+ resource_id, canonical_id, len(data), sha1, desc).encode('utf-8'))
-+
-+
-+def _ListMain(args):
-+ pak = data_pack.ReadDataPack(args.pak_file)
-+ if args.textual_id or args.path:
-+ info_dict = data_pack.ReadGrdInfo(args.pak_file)
-+ fmt = ''.join([
-+ '{id}', ' = {textual_id}' if args.textual_id else '',
-+ ' @ {path}' if args.path else '', '\n'
-+ ])
-+ for resource_id in sorted(pak.resources):
-+ item = info_dict[resource_id]
-+ args.output.write(
-+ fmt.format(textual_id=item.textual_id, id=item.id, path=item.path))
-+ else:
-+ for resource_id in sorted(pak.resources):
-+ args.output.write('%d\n' % resource_id)
-+
-+
-+def main():
-+ parser = argparse.ArgumentParser(
-+ description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
-+ # Subparsers are required by default under Python 2. Python 3 changed to
-+ # not required, but didn't include a required option until 3.7. Setting
-+ # the required member works in all versions (and setting dest name).
-+ sub_parsers = parser.add_subparsers(dest='action')
-+ sub_parsers.required = True
-+
-+ sub_parser = sub_parsers.add_parser('repack',
-+ help='Combines several .pak files into one.')
-+ sub_parser.add_argument('output_pak_file', help='File to create.')
-+ sub_parser.add_argument('input_pak_files', nargs='+',
-+ help='Input .pak files.')
-+ sub_parser.add_argument('--whitelist',
-+ help='Path to a whitelist used to filter output pak file resource IDs.')
-+ sub_parser.add_argument('--suppress-removed-key-output', action='store_true',
-+ help='Do not log which keys were removed by the whitelist.')
-+ sub_parser.add_argument('--compress', dest='compress', action='store_true',
-+ default=False, help='Compress output_pak_file using gzip.')
-+ sub_parser.set_defaults(func=_RepackMain)
-+
-+ sub_parser = sub_parsers.add_parser('extract', help='Extracts pak file')
-+ sub_parser.add_argument('pak_file')
-+ sub_parser.add_argument('-o', '--output-dir', default='.',
-+ help='Directory to extract to.')
-+ sub_parser.add_argument(
-+ '-t',
-+ '--textual-id',
-+ action='store_true',
-+ help='Use textual resource ID (name) (from .info file) as filenames.')
-+ sub_parser.set_defaults(func=_ExtractMain)
-+
-+ sub_parser = sub_parsers.add_parser('create',
-+ help='Creates pak file from extracted directory.')
-+ sub_parser.add_argument('output_pak_file', help='File to create.')
-+ sub_parser.add_argument('-i', '--input-dir', default='.',
-+ help='Directory to create from.')
-+ sub_parser.set_defaults(func=_CreateMain)
-+
-+ sub_parser = sub_parsers.add_parser('print',
-+ help='Prints all pak IDs and contents. Useful for diffing.')
-+ sub_parser.add_argument('pak_file')
-+ sub_parser.add_argument('--output', type=argparse.FileType('w'),
-+ default=sys.stdout,
-+ help='The resource list path to write (default stdout)')
-+ sub_parser.add_argument('--no-decode', dest='decode', action='store_false',
-+ default=True, help='Do not print entry data.')
-+ sub_parser.add_argument(
-+ '-t',
-+ '--textual-id',
-+ action='store_true',
-+ help='Print textual ID (name) (from .info file) instead of the ID.')
-+ sub_parser.set_defaults(func=_PrintMain)
-+
-+ sub_parser = sub_parsers.add_parser('list-id',
-+ help='Outputs all resource IDs to a file.')
-+ sub_parser.add_argument('pak_file')
-+ sub_parser.add_argument('--output', type=argparse.FileType('w'),
-+ default=sys.stdout,
-+ help='The resource list path to write (default stdout)')
-+ sub_parser.add_argument(
-+ '-t',
-+ '--textual-id',
-+ action='store_true',
-+ help='Print the textual resource ID (from .info file).')
-+ sub_parser.add_argument(
-+ '-p',
-+ '--path',
-+ action='store_true',
-+ help='Print the resource path (from .info file).')
-+ sub_parser.set_defaults(func=_ListMain)
-+
-+ args = parser.parse_args()
-+ args.func(args)
-+
-+
-+if __name__ == '__main__':
-+ main()
-diff --git a/tools/grit/repack.gni b/tools/grit/repack.gni
-new file mode 100644
-index 0000000000..193f2dc43f
---- /dev/null
-+++ b/tools/grit/repack.gni
-@@ -0,0 +1,189 @@
-+# Copyright 2014 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+import("//tools/grit/grit_rule.gni")
-+
-+# This file defines a template to invoke grit repack in a consistent manner.
-+#
-+# Parameters:
-+# sources [required]
-+# List of pak files that need to be combined.
-+#
-+# output [required]
-+# File name (single string) of the output file.
-+#
-+# copy_data_to_bundle [optional]
-+# Whether to define a bundle_data() for the resulting pak.
-+#
-+# bundle_output [optional]
-+# Path of the file in the application bundle, defaults to
-+# {{bundle_resources_dir}}/{{source_file_part}}.
-+#
-+# compress [optional]
-+# Gzip the resulting bundle (and append .gz to the output name).
-+#
-+# deps [optional]
-+# public_deps [optional]
-+# visibility [optional]
-+# Normal meaning.
-+template("repack") {
-+ _copy_data_to_bundle =
-+ defined(invoker.copy_data_to_bundle) && invoker.copy_data_to_bundle
-+ _repack_target_name = target_name
-+ if (_copy_data_to_bundle) {
-+ _repack_target_name = "${target_name}__repack"
-+ }
-+
-+ _compress = defined(invoker.compress) && invoker.compress
-+
-+ action(_repack_target_name) {
-+ forward_variables_from(invoker,
-+ [
-+ "deps",
-+ "public_deps",
-+ "testonly",
-+ "visibility",
-+ ])
-+ if (defined(visibility) && _copy_data_to_bundle) {
-+ visibility += [ ":${invoker.target_name}" ]
-+ }
-+ assert(defined(invoker.sources), "Need sources for $target_name")
-+ assert(defined(invoker.output), "Need output for $target_name")
-+
-+ script = "//tools/grit/pak_util.py"
-+
-+ inputs = invoker.sources
-+ outputs = [
-+ invoker.output,
-+ "${invoker.output}.info",
-+ ]
-+
-+ args = [ "repack" ]
-+ if (defined(invoker.repack_whitelist)) {
-+ inputs += [ invoker.repack_whitelist ]
-+ _rebased_whitelist = rebase_path(invoker.repack_whitelist)
-+ args += [ "--whitelist=$_rebased_whitelist" ]
-+ args += [ "--suppress-removed-key-output" ]
-+ }
-+ args += [ rebase_path(invoker.output, root_build_dir) ]
-+ args += rebase_path(invoker.sources, root_build_dir)
-+ if (_compress) {
-+ args += [ "--compress" ]
-+ }
-+ }
-+
-+ if (_copy_data_to_bundle) {
-+ bundle_data(target_name) {
-+ forward_variables_from(invoker,
-+ [
-+ "testonly",
-+ "visibility",
-+ ])
-+
-+ public_deps = [ ":$_repack_target_name" ]
-+ sources = [ invoker.output ]
-+ if (defined(invoker.bundle_output)) {
-+ outputs = [ invoker.bundle_output ]
-+ } else {
-+ outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
-+ }
-+ }
-+ }
-+}
-+
-+# Repacks a set of .pak files for each locale.
-+#
-+# Parameters:
-+#
-+# input_locales [required]
-+# List of locale names to use as inputs.
-+#
-+# output_locales [required]
-+# A list containing the corresponding output names for each of the
-+# input names. Mac and iOS use different names in some cases.
-+#
-+# source_patterns [required]
-+# The pattern for pak files which need repacked. The filenames always end
-+# with "${locale}.pak".
-+# E.g.:
-+# ${root_gen_dir}/foo_ expands to ${root_gen_dir}/foo_zh-CN.pak
-+# when locale is zh-CN.
-+#
-+# output_dir [optional]
-+# Directory in which to put all pak files.
-+#
-+# deps [optional]
-+# visibility [optional]
-+# testonly [optional]
-+# copy_data_to_bundle [optional]
-+# repack_whitelist [optional]
-+# Normal meaning.
-+template("repack_locales") {
-+ if (defined(invoker.output_dir)) {
-+ _output_dir = invoker.output_dir
-+ } else if (is_ios) {
-+ _output_dir = "$target_gen_dir"
-+ } else {
-+ _output_dir = "$target_gen_dir/$target_name"
-+ }
-+
-+ # GN can't handle invoker.output_locales[foo] (http://crbug.com/614747).
-+ _output_locales = invoker.output_locales
-+
-+ # Collects all targets the loop generates.
-+ _locale_targets = []
-+
-+ # This loop iterates over the input locales and also keeps a counter so it
-+ # can simultaneously iterate over the output locales (using GN's very
-+ # limited looping capabilities).
-+ _current_index = 0
-+ foreach(_input_locale, invoker.input_locales) {
-+ _output_locale = _output_locales[_current_index]
-+
-+ # Compute the name of the target for the current file. Save it for the deps.
-+ _current_name = "${target_name}_${_input_locale}"
-+ _locale_targets += [ ":$_current_name" ]
-+
-+ repack(_current_name) {
-+ forward_variables_from(invoker,
-+ [
-+ "copy_data_to_bundle",
-+ "bundle_output",
-+ "compress",
-+ "deps",
-+ "repack_whitelist",
-+ "testonly",
-+ ])
-+ visibility = [ ":${invoker.target_name}" ]
-+ if (is_ios) {
-+ output = "$_output_dir/${_output_locale}.lproj/locale.pak"
-+ } else {
-+ output = "$_output_dir/${_output_locale}.pak"
-+ }
-+ if (defined(copy_data_to_bundle) && copy_data_to_bundle) {
-+ bundle_output =
-+ "{{bundle_resources_dir}}/${_output_locale}.lproj/locale.pak"
-+ }
-+ sources = []
-+ foreach(_pattern, invoker.source_patterns) {
-+ sources += [ "${_pattern}${_input_locale}.pak" ]
-+ }
-+ }
-+
-+ _current_index = _current_index + 1
-+ }
-+
-+ # The group that external targets depend on which collects all deps.
-+ group(target_name) {
-+ forward_variables_from(invoker,
-+ [
-+ "visibility",
-+ "testonly",
-+ ])
-+ public_deps = _locale_targets
-+ if (!defined(invoker.copy_data_to_bundle) || !invoker.copy_data_to_bundle) {
-+ data_deps = public_deps
-+ }
-+ }
-+}
-diff --git a/tools/grit/setup.py b/tools/grit/setup.py
-new file mode 100644
-index 0000000000..5d86dfc2fc
---- /dev/null
-+++ b/tools/grit/setup.py
-@@ -0,0 +1,46 @@
-+#!/usr/bin/env python3
-+# Copyright 2020 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+"""Install the package!"""
-+
-+from __future__ import absolute_import
-+
-+import setuptools
-+
-+
-+setuptools.setup(
-+ name='grit',
-+ version='0',
-+ entry_points={
-+ 'console_scripts': ['grit = grit.grit_runner:Main'],
-+ },
-+ packages=setuptools.find_packages(),
-+ install_requires=[
-+ 'six >= 1.10',
-+ ],
-+ author='The Chromium Authors',
-+ author_email='chromium-dev@chromium.org',
-+ description='Google Resource and Internationalization Tool for managing '
-+ 'translations & resource files',
-+ license='BSD-3',
-+ url='https://chromium.googlesource.com/chromium/src/tools/grit/',
-+ classifiers=[
-+ 'Development Status :: 6 - Mature',
-+ 'Environment :: Console',
-+ 'Intended Audience :: Developers',
-+ 'License :: OSI Approved :: BSD License',
-+ 'Operating System :: MacOS',
-+ 'Operating System :: Microsoft :: Windows',
-+ 'Operating System :: POSIX :: Linux',
-+ 'Programming Language :: Python',
-+ 'Programming Language :: Python :: 2.7',
-+ 'Programming Language :: Python :: 3',
-+ 'Programming Language :: Python :: 3.6',
-+ 'Programming Language :: Python :: 3.7',
-+ 'Programming Language :: Python :: 3.8',
-+ 'Programming Language :: Python :: 3.9',
-+ 'Topic :: Utilities',
-+ ],
-+)
-diff --git a/tools/grit/stamp_grit_sources.py b/tools/grit/stamp_grit_sources.py
-new file mode 100644
-index 0000000000..bc7265c6cb
---- /dev/null
-+++ b/tools/grit/stamp_grit_sources.py
-@@ -0,0 +1,57 @@
-+# Copyright 2014 The Chromium Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+# This script enumerates the files in the given directory, writing an empty
-+# stamp file and a .d file listing the inputs required to make the stamp. This
-+# allows us to dynamically depend on the grit sources without enumerating the
-+# grit directory for every invocation of grit (which is what adding the source
-+# files to every .grd file's .d file would entail) or shelling out to grit
-+# synchronously during GN execution to get the list (which would be slow).
-+#
-+# Usage:
-+# stamp_grit_sources.py <directory> <stamp-file> <.d-file>
-+
-+from __future__ import print_function
-+
-+import os
-+import sys
-+
-+def GritSourceFiles(grit_root_dir):
-+ files = []
-+ for root, _, filenames in os.walk(grit_root_dir):
-+ grit_src = [os.path.join(root, f) for f in filenames
-+ if f.endswith('.py') and not f.endswith('_unittest.py')]
-+ files.extend(grit_src)
-+ files = [f.replace('\\', '/') for f in files]
-+ return sorted(files)
-+
-+
-+def WriteDepFile(dep_file, stamp_file, source_files):
-+ with open(dep_file, "w") as f:
-+ f.write(stamp_file)
-+ f.write(": ")
-+ f.write(' '.join(source_files))
-+
-+
-+def WriteStampFile(stamp_file):
-+ with open(stamp_file, "w"):
-+ pass
-+
-+
-+def main(argv):
-+ if len(argv) != 4:
-+ print("Error: expecting 3 args.")
-+ return 1
-+
-+ grit_root_dir = sys.argv[1]
-+ stamp_file = sys.argv[2]
-+ dep_file = sys.argv[3]
-+
-+ WriteStampFile(stamp_file)
-+ WriteDepFile(dep_file, stamp_file, GritSourceFiles(grit_root_dir))
-+ return 0
-+
-+
-+if __name__ == '__main__':
-+ sys.exit(main(sys.argv))
-diff --git a/tools/grit/third_party/six/LICENSE b/tools/grit/third_party/six/LICENSE
-new file mode 100644
-index 0000000000..e558f9d494
---- /dev/null
-+++ b/tools/grit/third_party/six/LICENSE
-@@ -0,0 +1,18 @@
-+Copyright (c) 2010-2015 Benjamin Peterson
-+
-+Permission is hereby granted, free of charge, to any person obtaining a copy of
-+this software and associated documentation files (the "Software"), to deal in
-+the Software without restriction, including without limitation the rights to
-+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-+the Software, and to permit persons to whom the Software is furnished to do so,
-+subject to the following conditions:
-+
-+The above copyright notice and this permission notice shall be included in all
-+copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-diff --git a/tools/grit/third_party/six/README b/tools/grit/third_party/six/README
-new file mode 100644
-index 0000000000..ee628a9db6
---- /dev/null
-+++ b/tools/grit/third_party/six/README
-@@ -0,0 +1,16 @@
-+Six is a Python 2 and 3 compatibility library. It provides utility functions
-+for smoothing over the differences between the Python versions with the goal of
-+writing Python code that is compatible on both Python versions. See the
-+documentation for more information on what is provided.
-+
-+Six supports every Python version since 2.6. It is contained in only one Python
-+file, so it can be easily copied into your project. (The copyright and license
-+notice must be retained.)
-+
-+Online documentation is at https://pythonhosted.org/six/.
-+
-+Bugs can be reported to https://bitbucket.org/gutworth/six. The code can also
-+be found there.
-+
-+For questions about six or porting in general, email the python-porting mailing
-+list: https://mail.python.org/mailman/listinfo/python-porting
-diff --git a/tools/grit/third_party/six/README.chromium b/tools/grit/third_party/six/README.chromium
-new file mode 100644
-index 0000000000..100b24d046
---- /dev/null
-+++ b/tools/grit/third_party/six/README.chromium
-@@ -0,0 +1,13 @@
-+Name: six
-+Short Name: six
-+URL: https://bitbucket.org/gutworth/six/commits/tag/1.10.0
-+Version: 1.10.0
-+Revision: 403:e5218c3f66a2
-+License: Apache License, Version 2.0
-+
-+Description:
-+Six is a Python 2 and 3 compatibility library.
-+
-+Local Modifications:
-+- Copied six.py as __init__.py.
-+- Kept LICENSE and README.
-diff --git a/tools/grit/third_party/six/__init__.py b/tools/grit/third_party/six/__init__.py
-new file mode 100644
-index 0000000000..56e4272cb3
---- /dev/null
-+++ b/tools/grit/third_party/six/__init__.py
-@@ -0,0 +1,868 @@
-+# Copyright (c) 2010-2015 Benjamin Peterson
-+#
-+# Permission is hereby granted, free of charge, to any person obtaining a copy
-+# of this software and associated documentation files (the "Software"), to deal
-+# in the Software without restriction, including without limitation the rights
-+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+# copies of the Software, and to permit persons to whom the Software is
-+# furnished to do so, subject to the following conditions:
-+#
-+# The above copyright notice and this permission notice shall be included in all
-+# copies or substantial portions of the Software.
-+#
-+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+# SOFTWARE.
-+
-+"""Utilities for writing code that runs on Python 2 and 3"""
-+
-+from __future__ import absolute_import
-+
-+import functools
-+import itertools
-+import operator
-+import sys
-+import types
-+
-+__author__ = "Benjamin Peterson <benjamin@python.org>"
-+__version__ = "1.10.0"
-+
-+
-+# Useful for very coarse version differentiation.
-+PY2 = sys.version_info[0] == 2
-+PY3 = sys.version_info[0] == 3
-+PY34 = sys.version_info[0:2] >= (3, 4)
-+
-+if PY3:
-+ string_types = str,
-+ integer_types = int,
-+ class_types = type,
-+ text_type = str
-+ binary_type = bytes
-+
-+ MAXSIZE = sys.maxsize
-+else:
-+ string_types = basestring,
-+ integer_types = (int, long)
-+ class_types = (type, types.ClassType)
-+ text_type = unicode
-+ binary_type = str
-+
-+ if sys.platform.startswith("java"):
-+ # Jython always uses 32 bits.
-+ MAXSIZE = int((1 << 31) - 1)
-+ else:
-+ # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
-+ class X(object):
-+
-+ def __len__(self):
-+ return 1 << 31
-+ try:
-+ len(X())
-+ except OverflowError:
-+ # 32-bit
-+ MAXSIZE = int((1 << 31) - 1)
-+ else:
-+ # 64-bit
-+ MAXSIZE = int((1 << 63) - 1)
-+ del X
-+
-+
-+def _add_doc(func, doc):
-+ """Add documentation to a function."""
-+ func.__doc__ = doc
-+
-+
-+def _import_module(name):
-+ """Import module, returning the module after the last dot."""
-+ __import__(name)
-+ return sys.modules[name]
-+
-+
-+class _LazyDescr(object):
-+
-+ def __init__(self, name):
-+ self.name = name
-+
-+ def __get__(self, obj, tp):
-+ result = self._resolve()
-+ setattr(obj, self.name, result) # Invokes __set__.
-+ try:
-+ # This is a bit ugly, but it avoids running this again by
-+ # removing this descriptor.
-+ delattr(obj.__class__, self.name)
-+ except AttributeError:
-+ pass
-+ return result
-+
-+
-+class MovedModule(_LazyDescr):
-+
-+ def __init__(self, name, old, new=None):
-+ super(MovedModule, self).__init__(name)
-+ if PY3:
-+ if new is None:
-+ new = name
-+ self.mod = new
-+ else:
-+ self.mod = old
-+
-+ def _resolve(self):
-+ return _import_module(self.mod)
-+
-+ def __getattr__(self, attr):
-+ _module = self._resolve()
-+ value = getattr(_module, attr)
-+ setattr(self, attr, value)
-+ return value
-+
-+
-+class _LazyModule(types.ModuleType):
-+
-+ def __init__(self, name):
-+ super(_LazyModule, self).__init__(name)
-+ self.__doc__ = self.__class__.__doc__
-+
-+ def __dir__(self):
-+ attrs = ["__doc__", "__name__"]
-+ attrs += [attr.name for attr in self._moved_attributes]
-+ return attrs
-+
-+ # Subclasses should override this
-+ _moved_attributes = []
-+
-+
-+class MovedAttribute(_LazyDescr):
-+
-+ def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
-+ super(MovedAttribute, self).__init__(name)
-+ if PY3:
-+ if new_mod is None:
-+ new_mod = name
-+ self.mod = new_mod
-+ if new_attr is None:
-+ if old_attr is None:
-+ new_attr = name
-+ else:
-+ new_attr = old_attr
-+ self.attr = new_attr
-+ else:
-+ self.mod = old_mod
-+ if old_attr is None:
-+ old_attr = name
-+ self.attr = old_attr
-+
-+ def _resolve(self):
-+ module = _import_module(self.mod)
-+ return getattr(module, self.attr)
-+
-+
-+class _SixMetaPathImporter(object):
-+
-+ """
-+ A meta path importer to import six.moves and its submodules.
-+
-+ This class implements a PEP302 finder and loader. It should be compatible
-+ with Python 2.5 and all existing versions of Python3
-+ """
-+
-+ def __init__(self, six_module_name):
-+ self.name = six_module_name
-+ self.known_modules = {}
-+
-+ def _add_module(self, mod, *fullnames):
-+ for fullname in fullnames:
-+ self.known_modules[self.name + "." + fullname] = mod
-+
-+ def _get_module(self, fullname):
-+ return self.known_modules[self.name + "." + fullname]
-+
-+ def find_module(self, fullname, path=None):
-+ if fullname in self.known_modules:
-+ return self
-+ return None
-+
-+ def __get_module(self, fullname):
-+ try:
-+ return self.known_modules[fullname]
-+ except KeyError:
-+ raise ImportError("This loader does not know module " + fullname)
-+
-+ def load_module(self, fullname):
-+ try:
-+ # in case of a reload
-+ return sys.modules[fullname]
-+ except KeyError:
-+ pass
-+ mod = self.__get_module(fullname)
-+ if isinstance(mod, MovedModule):
-+ mod = mod._resolve()
-+ else:
-+ mod.__loader__ = self
-+ sys.modules[fullname] = mod
-+ return mod
-+
-+ def is_package(self, fullname):
-+ """
-+ Return true, if the named module is a package.
-+
-+ We need this method to get correct spec objects with
-+ Python 3.4 (see PEP451)
-+ """
-+ return hasattr(self.__get_module(fullname), "__path__")
-+
-+ def get_code(self, fullname):
-+ """Return None
-+
-+ Required, if is_package is implemented"""
-+ self.__get_module(fullname) # eventually raises ImportError
-+ return None
-+ get_source = get_code # same as get_code
-+
-+_importer = _SixMetaPathImporter(__name__)
-+
-+
-+class _MovedItems(_LazyModule):
-+
-+ """Lazy loading of moved objects"""
-+ __path__ = [] # mark as package
-+
-+
-+_moved_attributes = [
-+ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
-+ MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
-+ MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
-+ MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
-+ MovedAttribute("intern", "__builtin__", "sys"),
-+ MovedAttribute("map", "itertools", "builtins", "imap", "map"),
-+ MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
-+ MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
-+ MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
-+ MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
-+ MovedAttribute("reduce", "__builtin__", "functools"),
-+ MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
-+ MovedAttribute("StringIO", "StringIO", "io"),
-+ MovedAttribute("UserDict", "UserDict", "collections"),
-+ MovedAttribute("UserList", "UserList", "collections"),
-+ MovedAttribute("UserString", "UserString", "collections"),
-+ MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
-+ MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
-+ MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
-+ MovedModule("builtins", "__builtin__"),
-+ MovedModule("configparser", "ConfigParser"),
-+ MovedModule("copyreg", "copy_reg"),
-+ MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
-+ MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
-+ MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
-+ MovedModule("http_cookies", "Cookie", "http.cookies"),
-+ MovedModule("html_entities", "htmlentitydefs", "html.entities"),
-+ MovedModule("html_parser", "HTMLParser", "html.parser"),
-+ MovedModule("http_client", "httplib", "http.client"),
-+ MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
-+ MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
-+ MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
-+ MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
-+ MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
-+ MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
-+ MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
-+ MovedModule("cPickle", "cPickle", "pickle"),
-+ MovedModule("queue", "Queue"),
-+ MovedModule("reprlib", "repr"),
-+ MovedModule("socketserver", "SocketServer"),
-+ MovedModule("_thread", "thread", "_thread"),
-+ MovedModule("tkinter", "Tkinter"),
-+ MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
-+ MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
-+ MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
-+ MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
-+ MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
-+ MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
-+ MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
-+ MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
-+ MovedModule("tkinter_colorchooser", "tkColorChooser",
-+ "tkinter.colorchooser"),
-+ MovedModule("tkinter_commondialog", "tkCommonDialog",
-+ "tkinter.commondialog"),
-+ MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
-+ MovedModule("tkinter_font", "tkFont", "tkinter.font"),
-+ MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
-+ MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
-+ "tkinter.simpledialog"),
-+ MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
-+ MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
-+ MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
-+ MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
-+ MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
-+ MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
-+]
-+# Add windows specific modules.
-+if sys.platform == "win32":
-+ _moved_attributes += [
-+ MovedModule("winreg", "_winreg"),
-+ ]
-+
-+for attr in _moved_attributes:
-+ setattr(_MovedItems, attr.name, attr)
-+ if isinstance(attr, MovedModule):
-+ _importer._add_module(attr, "moves." + attr.name)
-+del attr
-+
-+_MovedItems._moved_attributes = _moved_attributes
-+
-+moves = _MovedItems(__name__ + ".moves")
-+_importer._add_module(moves, "moves")
-+
-+
-+class Module_six_moves_urllib_parse(_LazyModule):
-+
-+ """Lazy loading of moved objects in six.moves.urllib_parse"""
-+
-+
-+_urllib_parse_moved_attributes = [
-+ MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
-+ MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
-+ MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
-+ MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
-+ MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
-+ MovedAttribute("urljoin", "urlparse", "urllib.parse"),
-+ MovedAttribute("urlparse", "urlparse", "urllib.parse"),
-+ MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
-+ MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
-+ MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
-+ MovedAttribute("quote", "urllib", "urllib.parse"),
-+ MovedAttribute("quote_plus", "urllib", "urllib.parse"),
-+ MovedAttribute("unquote", "urllib", "urllib.parse"),
-+ MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
-+ MovedAttribute("urlencode", "urllib", "urllib.parse"),
-+ MovedAttribute("splitquery", "urllib", "urllib.parse"),
-+ MovedAttribute("splittag", "urllib", "urllib.parse"),
-+ MovedAttribute("splituser", "urllib", "urllib.parse"),
-+ MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
-+ MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
-+ MovedAttribute("uses_params", "urlparse", "urllib.parse"),
-+ MovedAttribute("uses_query", "urlparse", "urllib.parse"),
-+ MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
-+]
-+for attr in _urllib_parse_moved_attributes:
-+ setattr(Module_six_moves_urllib_parse, attr.name, attr)
-+del attr
-+
-+Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
-+
-+_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
-+ "moves.urllib_parse", "moves.urllib.parse")
-+
-+
-+class Module_six_moves_urllib_error(_LazyModule):
-+
-+ """Lazy loading of moved objects in six.moves.urllib_error"""
-+
-+
-+_urllib_error_moved_attributes = [
-+ MovedAttribute("URLError", "urllib2", "urllib.error"),
-+ MovedAttribute("HTTPError", "urllib2", "urllib.error"),
-+ MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
-+]
-+for attr in _urllib_error_moved_attributes:
-+ setattr(Module_six_moves_urllib_error, attr.name, attr)
-+del attr
-+
-+Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
-+
-+_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
-+ "moves.urllib_error", "moves.urllib.error")
-+
-+
-+class Module_six_moves_urllib_request(_LazyModule):
-+
-+ """Lazy loading of moved objects in six.moves.urllib_request"""
-+
-+
-+_urllib_request_moved_attributes = [
-+ MovedAttribute("urlopen", "urllib2", "urllib.request"),
-+ MovedAttribute("install_opener", "urllib2", "urllib.request"),
-+ MovedAttribute("build_opener", "urllib2", "urllib.request"),
-+ MovedAttribute("pathname2url", "urllib", "urllib.request"),
-+ MovedAttribute("url2pathname", "urllib", "urllib.request"),
-+ MovedAttribute("getproxies", "urllib", "urllib.request"),
-+ MovedAttribute("Request", "urllib2", "urllib.request"),
-+ MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
-+ MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
-+ MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("FileHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
-+ MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
-+ MovedAttribute("urlretrieve", "urllib", "urllib.request"),
-+ MovedAttribute("urlcleanup", "urllib", "urllib.request"),
-+ MovedAttribute("URLopener", "urllib", "urllib.request"),
-+ MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
-+ MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
-+]
-+for attr in _urllib_request_moved_attributes:
-+ setattr(Module_six_moves_urllib_request, attr.name, attr)
-+del attr
-+
-+Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
-+
-+_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
-+ "moves.urllib_request", "moves.urllib.request")
-+
-+
-+class Module_six_moves_urllib_response(_LazyModule):
-+
-+ """Lazy loading of moved objects in six.moves.urllib_response"""
-+
-+
-+_urllib_response_moved_attributes = [
-+ MovedAttribute("addbase", "urllib", "urllib.response"),
-+ MovedAttribute("addclosehook", "urllib", "urllib.response"),
-+ MovedAttribute("addinfo", "urllib", "urllib.response"),
-+ MovedAttribute("addinfourl", "urllib", "urllib.response"),
-+]
-+for attr in _urllib_response_moved_attributes:
-+ setattr(Module_six_moves_urllib_response, attr.name, attr)
-+del attr
-+
-+Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
-+
-+_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
-+ "moves.urllib_response", "moves.urllib.response")
-+
-+
-+class Module_six_moves_urllib_robotparser(_LazyModule):
-+
-+ """Lazy loading of moved objects in six.moves.urllib_robotparser"""
-+
-+
-+_urllib_robotparser_moved_attributes = [
-+ MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
-+]
-+for attr in _urllib_robotparser_moved_attributes:
-+ setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
-+del attr
-+
-+Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
-+
-+_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
-+ "moves.urllib_robotparser", "moves.urllib.robotparser")
-+
-+
-+class Module_six_moves_urllib(types.ModuleType):
-+
-+ """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
-+ __path__ = [] # mark as package
-+ parse = _importer._get_module("moves.urllib_parse")
-+ error = _importer._get_module("moves.urllib_error")
-+ request = _importer._get_module("moves.urllib_request")
-+ response = _importer._get_module("moves.urllib_response")
-+ robotparser = _importer._get_module("moves.urllib_robotparser")
-+
-+ def __dir__(self):
-+ return ['parse', 'error', 'request', 'response', 'robotparser']
-+
-+_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
-+ "moves.urllib")
-+
-+
-+def add_move(move):
-+ """Add an item to six.moves."""
-+ setattr(_MovedItems, move.name, move)
-+
-+
-+def remove_move(name):
-+ """Remove item from six.moves."""
-+ try:
-+ delattr(_MovedItems, name)
-+ except AttributeError:
-+ try:
-+ del moves.__dict__[name]
-+ except KeyError:
-+ raise AttributeError("no such move, %r" % (name,))
-+
-+
-+if PY3:
-+ _meth_func = "__func__"
-+ _meth_self = "__self__"
-+
-+ _func_closure = "__closure__"
-+ _func_code = "__code__"
-+ _func_defaults = "__defaults__"
-+ _func_globals = "__globals__"
-+else:
-+ _meth_func = "im_func"
-+ _meth_self = "im_self"
-+
-+ _func_closure = "func_closure"
-+ _func_code = "func_code"
-+ _func_defaults = "func_defaults"
-+ _func_globals = "func_globals"
-+
-+
-+try:
-+ advance_iterator = next
-+except NameError:
-+ def advance_iterator(it):
-+ return it.next()
-+next = advance_iterator
-+
-+
-+try:
-+ callable = callable
-+except NameError:
-+ def callable(obj):
-+ return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
-+
-+
-+if PY3:
-+ def get_unbound_function(unbound):
-+ return unbound
-+
-+ create_bound_method = types.MethodType
-+
-+ def create_unbound_method(func, cls):
-+ return func
-+
-+ Iterator = object
-+else:
-+ def get_unbound_function(unbound):
-+ return unbound.im_func
-+
-+ def create_bound_method(func, obj):
-+ return types.MethodType(func, obj, obj.__class__)
-+
-+ def create_unbound_method(func, cls):
-+ return types.MethodType(func, None, cls)
-+
-+ class Iterator(object):
-+
-+ def next(self):
-+ return type(self).__next__(self)
-+
-+ callable = callable
-+_add_doc(get_unbound_function,
-+ """Get the function out of a possibly unbound function""")
-+
-+
-+get_method_function = operator.attrgetter(_meth_func)
-+get_method_self = operator.attrgetter(_meth_self)
-+get_function_closure = operator.attrgetter(_func_closure)
-+get_function_code = operator.attrgetter(_func_code)
-+get_function_defaults = operator.attrgetter(_func_defaults)
-+get_function_globals = operator.attrgetter(_func_globals)
-+
-+
-+if PY3:
-+ def iterkeys(d, **kw):
-+ return iter(d.keys(**kw))
-+
-+ def itervalues(d, **kw):
-+ return iter(d.values(**kw))
-+
-+ def iteritems(d, **kw):
-+ return iter(d.items(**kw))
-+
-+ def iterlists(d, **kw):
-+ return iter(d.lists(**kw))
-+
-+ viewkeys = operator.methodcaller("keys")
-+
-+ viewvalues = operator.methodcaller("values")
-+
-+ viewitems = operator.methodcaller("items")
-+else:
-+ def iterkeys(d, **kw):
-+ return d.iterkeys(**kw)
-+
-+ def itervalues(d, **kw):
-+ return d.itervalues(**kw)
-+
-+ def iteritems(d, **kw):
-+ return d.iteritems(**kw)
-+
-+ def iterlists(d, **kw):
-+ return d.iterlists(**kw)
-+
-+ viewkeys = operator.methodcaller("viewkeys")
-+
-+ viewvalues = operator.methodcaller("viewvalues")
-+
-+ viewitems = operator.methodcaller("viewitems")
-+
-+_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
-+_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
-+_add_doc(iteritems,
-+ "Return an iterator over the (key, value) pairs of a dictionary.")
-+_add_doc(iterlists,
-+ "Return an iterator over the (key, [values]) pairs of a dictionary.")
-+
-+
-+if PY3:
-+ def b(s):
-+ return s.encode("latin-1")
-+
-+ def u(s):
-+ return s
-+ unichr = chr
-+ import struct
-+ int2byte = struct.Struct(">B").pack
-+ del struct
-+ byte2int = operator.itemgetter(0)
-+ indexbytes = operator.getitem
-+ iterbytes = iter
-+ import io
-+ StringIO = io.StringIO
-+ BytesIO = io.BytesIO
-+ _assertCountEqual = "assertCountEqual"
-+ if sys.version_info[1] <= 1:
-+ _assertRaisesRegex = "assertRaisesRegexp"
-+ _assertRegex = "assertRegexpMatches"
-+ else:
-+ _assertRaisesRegex = "assertRaisesRegex"
-+ _assertRegex = "assertRegex"
-+else:
-+ def b(s):
-+ return s
-+ # Workaround for standalone backslash
-+
-+ def u(s):
-+ return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
-+ unichr = unichr
-+ int2byte = chr
-+
-+ def byte2int(bs):
-+ return ord(bs[0])
-+
-+ def indexbytes(buf, i):
-+ return ord(buf[i])
-+ iterbytes = functools.partial(itertools.imap, ord)
-+ import StringIO
-+ StringIO = BytesIO = StringIO.StringIO
-+ _assertCountEqual = "assertItemsEqual"
-+ _assertRaisesRegex = "assertRaisesRegexp"
-+ _assertRegex = "assertRegexpMatches"
-+_add_doc(b, """Byte literal""")
-+_add_doc(u, """Text literal""")
-+
-+
-+def assertCountEqual(self, *args, **kwargs):
-+ return getattr(self, _assertCountEqual)(*args, **kwargs)
-+
-+
-+def assertRaisesRegex(self, *args, **kwargs):
-+ return getattr(self, _assertRaisesRegex)(*args, **kwargs)
-+
-+
-+def assertRegex(self, *args, **kwargs):
-+ return getattr(self, _assertRegex)(*args, **kwargs)
-+
-+
-+if PY3:
-+ exec_ = getattr(moves.builtins, "exec")
-+
-+ def reraise(tp, value, tb=None):
-+ if value is None:
-+ value = tp()
-+ if value.__traceback__ is not tb:
-+ raise value.with_traceback(tb)
-+ raise value
-+
-+else:
-+ def exec_(_code_, _globs_=None, _locs_=None):
-+ """Execute code in a namespace."""
-+ if _globs_ is None:
-+ frame = sys._getframe(1)
-+ _globs_ = frame.f_globals
-+ if _locs_ is None:
-+ _locs_ = frame.f_locals
-+ del frame
-+ elif _locs_ is None:
-+ _locs_ = _globs_
-+ exec("""exec _code_ in _globs_, _locs_""")
-+
-+ exec_("""def reraise(tp, value, tb=None):
-+ raise tp, value, tb
-+""")
-+
-+
-+if sys.version_info[:2] == (3, 2):
-+ exec_("""def raise_from(value, from_value):
-+ if from_value is None:
-+ raise value
-+ raise value from from_value
-+""")
-+elif sys.version_info[:2] > (3, 2):
-+ exec_("""def raise_from(value, from_value):
-+ raise value from from_value
-+""")
-+else:
-+ def raise_from(value, from_value):
-+ raise value
-+
-+
-+print_ = getattr(moves.builtins, "print", None)
-+if print_ is None:
-+ def print_(*args, **kwargs):
-+ """The new-style print function for Python 2.4 and 2.5."""
-+ fp = kwargs.pop("file", sys.stdout)
-+ if fp is None:
-+ return
-+
-+ def write(data):
-+ if not isinstance(data, basestring):
-+ data = str(data)
-+ # If the file has an encoding, encode unicode with it.
-+ if (isinstance(fp, file) and
-+ isinstance(data, unicode) and
-+ fp.encoding is not None):
-+ errors = getattr(fp, "errors", None)
-+ if errors is None:
-+ errors = "strict"
-+ data = data.encode(fp.encoding, errors)
-+ fp.write(data)
-+ want_unicode = False
-+ sep = kwargs.pop("sep", None)
-+ if sep is not None:
-+ if isinstance(sep, unicode):
-+ want_unicode = True
-+ elif not isinstance(sep, str):
-+ raise TypeError("sep must be None or a string")
-+ end = kwargs.pop("end", None)
-+ if end is not None:
-+ if isinstance(end, unicode):
-+ want_unicode = True
-+ elif not isinstance(end, str):
-+ raise TypeError("end must be None or a string")
-+ if kwargs:
-+ raise TypeError("invalid keyword arguments to print()")
-+ if not want_unicode:
-+ for arg in args:
-+ if isinstance(arg, unicode):
-+ want_unicode = True
-+ break
-+ if want_unicode:
-+ newline = unicode("\n")
-+ space = unicode(" ")
-+ else:
-+ newline = "\n"
-+ space = " "
-+ if sep is None:
-+ sep = space
-+ if end is None:
-+ end = newline
-+ for i, arg in enumerate(args):
-+ if i:
-+ write(sep)
-+ write(arg)
-+ write(end)
-+if sys.version_info[:2] < (3, 3):
-+ _print = print_
-+
-+ def print_(*args, **kwargs):
-+ fp = kwargs.get("file", sys.stdout)
-+ flush = kwargs.pop("flush", False)
-+ _print(*args, **kwargs)
-+ if flush and fp is not None:
-+ fp.flush()
-+
-+_add_doc(reraise, """Reraise an exception.""")
-+
-+if sys.version_info[0:2] < (3, 4):
-+ def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
-+ updated=functools.WRAPPER_UPDATES):
-+ def wrapper(f):
-+ f = functools.wraps(wrapped, assigned, updated)(f)
-+ f.__wrapped__ = wrapped
-+ return f
-+ return wrapper
-+else:
-+ wraps = functools.wraps
-+
-+
-+def with_metaclass(meta, *bases):
-+ """Create a base class with a metaclass."""
-+ # This requires a bit of explanation: the basic idea is to make a dummy
-+ # metaclass for one level of class instantiation that replaces itself with
-+ # the actual metaclass.
-+ class metaclass(meta):
-+
-+ def __new__(cls, name, this_bases, d):
-+ return meta(name, bases, d)
-+ return type.__new__(metaclass, 'temporary_class', (), {})
-+
-+
-+def add_metaclass(metaclass):
-+ """Class decorator for creating a class with a metaclass."""
-+ def wrapper(cls):
-+ orig_vars = cls.__dict__.copy()
-+ slots = orig_vars.get('__slots__')
-+ if slots is not None:
-+ if isinstance(slots, str):
-+ slots = [slots]
-+ for slots_var in slots:
-+ orig_vars.pop(slots_var)
-+ orig_vars.pop('__dict__', None)
-+ orig_vars.pop('__weakref__', None)
-+ return metaclass(cls.__name__, cls.__bases__, orig_vars)
-+ return wrapper
-+
-+
-+def python_2_unicode_compatible(klass):
-+ """
-+ A decorator that defines __unicode__ and __str__ methods under Python 2.
-+ Under Python 3 it does nothing.
-+
-+ To support Python 2 and 3 with a single code base, define a __str__ method
-+ returning text and apply this decorator to the class.
-+ """
-+ if PY2:
-+ if '__str__' not in klass.__dict__:
-+ raise ValueError("@python_2_unicode_compatible cannot be applied "
-+ "to %s because it doesn't define __str__()." %
-+ klass.__name__)
-+ klass.__unicode__ = klass.__str__
-+ klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
-+ return klass
-+
-+
-+# Complete the moves implementation.
-+# This code is at the end of this module to speed up module loading.
-+# Turn this module into a package.
-+__path__ = [] # required for PEP 302 and PEP 451
-+__package__ = __name__ # see PEP 366 @ReservedAssignment
-+if globals().get("__spec__") is not None:
-+ __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
-+# Remove other six meta path importers, since they cause problems. This can
-+# happen if six is removed from sys.modules and then reloaded. (Setuptools does
-+# this for some reason.)
-+if sys.meta_path:
-+ for i, importer in enumerate(sys.meta_path):
-+ # Here's some real nastiness: Another "instance" of the six module might
-+ # be floating around. Therefore, we can't use isinstance() to check for
-+ # the six meta path importer, since the other six instance will have
-+ # inserted an importer with different class.
-+ if (type(importer).__name__ == "_SixMetaPathImporter" and
-+ importer.name == __name__):
-+ del sys.meta_path[i]
-+ break
-+ del i, importer
-+# Finally, add the importer to the meta path import hook.
-+sys.meta_path.append(_importer)
++++ b/tools/generate_stubs/rules.gni
+@@ -0,0 +1,2 @@
++# "empty" file in place of importing new tools/generate_stubs
++# to allow BUILD.gn imports to succeed.
diff --git a/third_party/libwebrtc/moz-patch-stack/0098.patch b/third_party/libwebrtc/moz-patch-stack/0098.patch
index dc3cc7ca1a..6ad5dd698c 100644
--- a/third_party/libwebrtc/moz-patch-stack/0098.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0098.patch
@@ -1,20 +1,64 @@
-From: Michael Froman <mfroman@mozilla.com>
-Date: Wed, 7 Dec 2022 17:09:00 +0000
-Subject: Bug 1744645 - pt1 - add a couple empty gni files to help with
- BUILD.gn corrections. r=ng
+From: Nico Grunbaum <na-g@nostrum.com>
+Date: Wed, 15 Nov 2023 22:33:00 +0000
+Subject: Bug 1863041 - P0 - add device filter control to
+ RTCCameraVideoCapturer;r=pehrsons,webrtc-reviewers
-Differential Revision: https://phabricator.services.mozilla.com/D163991
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/81d86382ee468f3b36deed00d0c9d59eb85524be
+I have filed this bug upstream: https://bugs.chromium.org/p/webrtc/issues/detail?id=15639
+
+Differential Revision: https://phabricator.services.mozilla.com/D193172
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/91a763d768b74acc9cf4828f91a86df4a7b092ce
---
- tools/generate_stubs/rules.gni | 2 ++
- 1 file changed, 2 insertions(+)
- create mode 100644 tools/generate_stubs/rules.gni
+ .../capturer/RTCCameraVideoCapturer.h | 5 ++++-
+ .../capturer/RTCCameraVideoCapturer.m | 17 +++++++++++++++--
+ 2 files changed, 19 insertions(+), 3 deletions(-)
-diff --git a/tools/generate_stubs/rules.gni b/tools/generate_stubs/rules.gni
-new file mode 100644
-index 0000000000..1d9f36eb72
---- /dev/null
-+++ b/tools/generate_stubs/rules.gni
-@@ -0,0 +1,2 @@
-+# "empty" file in place of importing new tools/generate_stubs
-+# to allow BUILD.gn imports to succeed.
+diff --git a/sdk/objc/components/capturer/RTCCameraVideoCapturer.h b/sdk/objc/components/capturer/RTCCameraVideoCapturer.h
+index 370bfa70f0..b1f3f64f74 100644
+--- a/sdk/objc/components/capturer/RTCCameraVideoCapturer.h
++++ b/sdk/objc/components/capturer/RTCCameraVideoCapturer.h
+@@ -26,7 +26,10 @@ NS_EXTENSION_UNAVAILABLE_IOS("Camera not available in app extensions.")
+ @property(readonly, nonatomic) AVCaptureSession *captureSession;
+
+ // Returns list of available capture devices that support video capture.
+-+ (NSArray<AVCaptureDevice *> *)captureDevices;
+++ (NSArray<AVCaptureDevice *> *)captureDevicesWithDeviceTypes:
++ (NSArray<AVCaptureDeviceType> *)deviceTypes;
++// Returns list of default capture devices types
+++ (NSArray<AVCaptureDeviceType> *)defaultCaptureDeviceTypes;
+ // Returns list of formats that are supported by this class for this device.
+ + (NSArray<AVCaptureDeviceFormat *> *)supportedFormatsForDevice:(AVCaptureDevice *)device;
+
+diff --git a/sdk/objc/components/capturer/RTCCameraVideoCapturer.m b/sdk/objc/components/capturer/RTCCameraVideoCapturer.m
+index e7c47b4e99..1361207faf 100644
+--- a/sdk/objc/components/capturer/RTCCameraVideoCapturer.m
++++ b/sdk/objc/components/capturer/RTCCameraVideoCapturer.m
+@@ -117,14 +117,27 @@ const int64_t kNanosecondsPerSecond = 1000000000;
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ }
+
+-+ (NSArray<AVCaptureDevice *> *)captureDevices {
+++ (NSArray<AVCaptureDevice *> *)captureDevicesWithDeviceTypes:
++ (NSArray<AVCaptureDeviceType> *)deviceTypes {
+ AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession
+- discoverySessionWithDeviceTypes:@[ AVCaptureDeviceTypeBuiltInWideAngleCamera ]
++ discoverySessionWithDeviceTypes:deviceTypes
+ mediaType:AVMediaTypeVideo
+ position:AVCaptureDevicePositionUnspecified];
+ return session.devices;
+ }
+
+++ (NSArray<AVCaptureDeviceType> *)defaultCaptureDeviceTypes {
++ NSArray *types = @[ AVCaptureDeviceTypeBuiltInWideAngleCamera ];
++#if !defined(WEBRTC_IOS)
++ if (@available(macOS 14.0, *)) {
++ types = [types arrayByAddingObject:AVCaptureDeviceTypeExternal];
++ } else {
++ types = [types arrayByAddingObject:AVCaptureDeviceTypeExternalUnknown];
++ }
++#endif
++ return types;
++}
++
+ + (NSArray<AVCaptureDeviceFormat *> *)supportedFormatsForDevice:(AVCaptureDevice *)device {
+ // Support opening the device in any format. We make sure it's converted to a format we
+ // can handle, if needed, in the method `-setupVideoDataOutput`.
diff --git a/third_party/libwebrtc/moz-patch-stack/0099.patch b/third_party/libwebrtc/moz-patch-stack/0099.patch
index 6ad5dd698c..7cf1017a12 100644
--- a/third_party/libwebrtc/moz-patch-stack/0099.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0099.patch
@@ -1,64 +1,36 @@
-From: Nico Grunbaum <na-g@nostrum.com>
-Date: Wed, 15 Nov 2023 22:33:00 +0000
-Subject: Bug 1863041 - P0 - add device filter control to
- RTCCameraVideoCapturer;r=pehrsons,webrtc-reviewers
+From: Michael Froman <mfroman@mozilla.com>
+Date: Mon, 4 Dec 2023 12:57:00 -0600
+Subject: Bug 1867099 - (fix-66b7275561) disable wgc capture yellow-line
+ removal. r?ng!
-I have filed this bug upstream: https://bugs.chromium.org/p/webrtc/issues/detail?id=15639
-
-Differential Revision: https://phabricator.services.mozilla.com/D193172
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/91a763d768b74acc9cf4828f91a86df4a7b092ce
+This code won't build until we support building with
+Win 10 SDK v10.0.20348.0 or newer.
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0aac94794aad2ddb637f5076bc08706a11866737
---
- .../capturer/RTCCameraVideoCapturer.h | 5 ++++-
- .../capturer/RTCCameraVideoCapturer.m | 17 +++++++++++++++--
- 2 files changed, 19 insertions(+), 3 deletions(-)
+ modules/desktop_capture/win/wgc_capture_session.cc | 6 ++++++
+ 1 file changed, 6 insertions(+)
-diff --git a/sdk/objc/components/capturer/RTCCameraVideoCapturer.h b/sdk/objc/components/capturer/RTCCameraVideoCapturer.h
-index 370bfa70f0..b1f3f64f74 100644
---- a/sdk/objc/components/capturer/RTCCameraVideoCapturer.h
-+++ b/sdk/objc/components/capturer/RTCCameraVideoCapturer.h
-@@ -26,7 +26,10 @@ NS_EXTENSION_UNAVAILABLE_IOS("Camera not available in app extensions.")
- @property(readonly, nonatomic) AVCaptureSession *captureSession;
-
- // Returns list of available capture devices that support video capture.
--+ (NSArray<AVCaptureDevice *> *)captureDevices;
-++ (NSArray<AVCaptureDevice *> *)captureDevicesWithDeviceTypes:
-+ (NSArray<AVCaptureDeviceType> *)deviceTypes;
-+// Returns list of default capture devices types
-++ (NSArray<AVCaptureDeviceType> *)defaultCaptureDeviceTypes;
- // Returns list of formats that are supported by this class for this device.
- + (NSArray<AVCaptureDeviceFormat *> *)supportedFormatsForDevice:(AVCaptureDevice *)device;
+diff --git a/modules/desktop_capture/win/wgc_capture_session.cc b/modules/desktop_capture/win/wgc_capture_session.cc
+index 8c74c2bf24..86afc52411 100644
+--- a/modules/desktop_capture/win/wgc_capture_session.cc
++++ b/modules/desktop_capture/win/wgc_capture_session.cc
+@@ -188,6 +188,11 @@ HRESULT WgcCaptureSession::StartCapture(const DesktopCaptureOptions& options) {
+ }
+ }
-diff --git a/sdk/objc/components/capturer/RTCCameraVideoCapturer.m b/sdk/objc/components/capturer/RTCCameraVideoCapturer.m
-index e7c47b4e99..1361207faf 100644
---- a/sdk/objc/components/capturer/RTCCameraVideoCapturer.m
-+++ b/sdk/objc/components/capturer/RTCCameraVideoCapturer.m
-@@ -117,14 +117,27 @@ const int64_t kNanosecondsPerSecond = 1000000000;
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
++// Until Mozilla builds with Win 10 SDK v10.0.20348.0 or newer, this
++// code will not build. Once we support the newer SDK, Bug 1868198
++// exists to decide if we ever want to use this code since it is
++// removing an indicator that capture is happening.
++#if !defined(WEBRTC_MOZILLA_BUILD)
+ // By default, the WGC capture API adds a yellow border around the captured
+ // window or display to indicate that a capture is in progress. The section
+ // below is an attempt to remove this yellow border to make the capture
+@@ -199,6 +204,7 @@ HRESULT WgcCaptureSession::StartCapture(const DesktopCaptureOptions& options) {
+ &session3))) {
+ session3->put_IsBorderRequired(false);
+ }
++#endif
--+ (NSArray<AVCaptureDevice *> *)captureDevices {
-++ (NSArray<AVCaptureDevice *> *)captureDevicesWithDeviceTypes:
-+ (NSArray<AVCaptureDeviceType> *)deviceTypes {
- AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession
-- discoverySessionWithDeviceTypes:@[ AVCaptureDeviceTypeBuiltInWideAngleCamera ]
-+ discoverySessionWithDeviceTypes:deviceTypes
- mediaType:AVMediaTypeVideo
- position:AVCaptureDevicePositionUnspecified];
- return session.devices;
- }
+ allow_zero_hertz_ = options.allow_wgc_zero_hertz();
-++ (NSArray<AVCaptureDeviceType> *)defaultCaptureDeviceTypes {
-+ NSArray *types = @[ AVCaptureDeviceTypeBuiltInWideAngleCamera ];
-+#if !defined(WEBRTC_IOS)
-+ if (@available(macOS 14.0, *)) {
-+ types = [types arrayByAddingObject:AVCaptureDeviceTypeExternal];
-+ } else {
-+ types = [types arrayByAddingObject:AVCaptureDeviceTypeExternalUnknown];
-+ }
-+#endif
-+ return types;
-+}
-+
- + (NSArray<AVCaptureDeviceFormat *> *)supportedFormatsForDevice:(AVCaptureDevice *)device {
- // Support opening the device in any format. We make sure it's converted to a format we
- // can handle, if needed, in the method `-setupVideoDataOutput`.
diff --git a/third_party/libwebrtc/moz-patch-stack/0100.patch b/third_party/libwebrtc/moz-patch-stack/0100.patch
index 7cf1017a12..07be6fc934 100644
--- a/third_party/libwebrtc/moz-patch-stack/0100.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0100.patch
@@ -1,36 +1,121 @@
-From: Michael Froman <mfroman@mozilla.com>
-Date: Mon, 4 Dec 2023 12:57:00 -0600
-Subject: Bug 1867099 - (fix-66b7275561) disable wgc capture yellow-line
- removal. r?ng!
+From: Jan Grulich <jgrulich@redhat.com>
+Date: Thu, 30 Nov 2023 11:49:00 +0000
+Subject: Bug 1844020 - Add option to DeviceInfo::GetDeviceName() identifying a
+ placeholder device r=pehrsons,webrtc-reviewers
-This code won't build until we support building with
-Win 10 SDK v10.0.20348.0 or newer.
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0aac94794aad2ddb637f5076bc08706a11866737
+Adds a new parameter "deviceIsPlaceholder" that will be set to true in
+case the returned device is not a real device but a placeholder that is
+just used to inform about camera device existence.
+
+Differential Revision: https://phabricator.services.mozilla.com/D189929
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/ed31b2acb5fbca3e2d0691a64bc52e65952070c0
---
- modules/desktop_capture/win/wgc_capture_session.cc | 6 ++++++
- 1 file changed, 6 insertions(+)
+ modules/video_capture/linux/device_info_pipewire.cc | 4 +++-
+ modules/video_capture/linux/device_info_pipewire.h | 3 ++-
+ modules/video_capture/linux/device_info_v4l2.cc | 3 ++-
+ modules/video_capture/linux/device_info_v4l2.h | 3 ++-
+ modules/video_capture/video_capture.h | 3 ++-
+ modules/video_capture/windows/device_info_ds.cc | 3 ++-
+ modules/video_capture/windows/device_info_ds.h | 3 ++-
+ 7 files changed, 15 insertions(+), 7 deletions(-)
-diff --git a/modules/desktop_capture/win/wgc_capture_session.cc b/modules/desktop_capture/win/wgc_capture_session.cc
-index 8c74c2bf24..86afc52411 100644
---- a/modules/desktop_capture/win/wgc_capture_session.cc
-+++ b/modules/desktop_capture/win/wgc_capture_session.cc
-@@ -188,6 +188,11 @@ HRESULT WgcCaptureSession::StartCapture(const DesktopCaptureOptions& options) {
- }
- }
+diff --git a/modules/video_capture/linux/device_info_pipewire.cc b/modules/video_capture/linux/device_info_pipewire.cc
+index fc0554f384..f9f08a9c27 100644
+--- a/modules/video_capture/linux/device_info_pipewire.cc
++++ b/modules/video_capture/linux/device_info_pipewire.cc
+@@ -50,8 +50,10 @@ int32_t DeviceInfoPipeWire::GetDeviceName(uint32_t deviceNumber,
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8,
+ uint32_t productUniqueIdUTF8Length,
+- pid_t* pid) {
++ pid_t* pid,
++ bool* deviceIsPlaceholder) {
+ RTC_CHECK(pipewire_session_);
++
+ if (deviceNumber >= NumberOfDevices())
+ return -1;
-+// Until Mozilla builds with Win 10 SDK v10.0.20348.0 or newer, this
-+// code will not build. Once we support the newer SDK, Bug 1868198
-+// exists to decide if we ever want to use this code since it is
-+// removing an indicator that capture is happening.
-+#if !defined(WEBRTC_MOZILLA_BUILD)
- // By default, the WGC capture API adds a yellow border around the captured
- // window or display to indicate that a capture is in progress. The section
- // below is an attempt to remove this yellow border to make the capture
-@@ -199,6 +204,7 @@ HRESULT WgcCaptureSession::StartCapture(const DesktopCaptureOptions& options) {
- &session3))) {
- session3->put_IsBorderRequired(false);
- }
-+#endif
+diff --git a/modules/video_capture/linux/device_info_pipewire.h b/modules/video_capture/linux/device_info_pipewire.h
+index 8a33d75892..00715c94bc 100644
+--- a/modules/video_capture/linux/device_info_pipewire.h
++++ b/modules/video_capture/linux/device_info_pipewire.h
+@@ -30,7 +30,8 @@ class DeviceInfoPipeWire : public DeviceInfoImpl {
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8 = nullptr,
+ uint32_t productUniqueIdUTF8Length = 0,
+- pid_t* pid = 0) override;
++ pid_t* pid = 0,
++ bool* deviceIsPlaceholder = 0) override;
+ /*
+ * Fills the membervariable _captureCapabilities with capabilites for the
+ * given device name.
+diff --git a/modules/video_capture/linux/device_info_v4l2.cc b/modules/video_capture/linux/device_info_v4l2.cc
+index 04caaea592..401c38f9c5 100644
+--- a/modules/video_capture/linux/device_info_v4l2.cc
++++ b/modules/video_capture/linux/device_info_v4l2.cc
+@@ -232,7 +232,8 @@ int32_t DeviceInfoV4l2::GetDeviceName(uint32_t deviceNumber,
+ uint32_t deviceUniqueIdUTF8Length,
+ char* /*productUniqueIdUTF8*/,
+ uint32_t /*productUniqueIdUTF8Length*/,
+- pid_t* /*pid*/) {
++ pid_t* /*pid*/,
++ bool* /*deviceIsPlaceholder*/) {
+ // Travel through /dev/video [0-63]
+ uint32_t count = 0;
+ char device[20];
+diff --git a/modules/video_capture/linux/device_info_v4l2.h b/modules/video_capture/linux/device_info_v4l2.h
+index 0bec3eb765..55415845ad 100644
+--- a/modules/video_capture/linux/device_info_v4l2.h
++++ b/modules/video_capture/linux/device_info_v4l2.h
+@@ -36,7 +36,8 @@ class DeviceInfoV4l2 : public DeviceInfoImpl {
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8 = 0,
+ uint32_t productUniqueIdUTF8Length = 0,
+- pid_t* pid=0) override;
++ pid_t* pid = 0,
++ bool* deviceIsPlaceholder = 0) override;
+ /*
+ * Fills the membervariable _captureCapabilities with capabilites for the
+ * given device name.
+diff --git a/modules/video_capture/video_capture.h b/modules/video_capture/video_capture.h
+index 43a6a7f832..f59c34f8b2 100644
+--- a/modules/video_capture/video_capture.h
++++ b/modules/video_capture/video_capture.h
+@@ -74,7 +74,8 @@ class VideoCaptureModule : public RefCountInterface {
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8 = 0,
+ uint32_t productUniqueIdUTF8Length = 0,
+- pid_t* pid = 0) = 0;
++ pid_t* pid = 0,
++ bool* deviceIsPlaceholder = 0) = 0;
- allow_zero_hertz_ = options.allow_wgc_zero_hertz();
+ // Returns the number of capabilities this device.
+ virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8) = 0;
+diff --git a/modules/video_capture/windows/device_info_ds.cc b/modules/video_capture/windows/device_info_ds.cc
+index f6927281f3..8ca741239c 100644
+--- a/modules/video_capture/windows/device_info_ds.cc
++++ b/modules/video_capture/windows/device_info_ds.cc
+@@ -173,7 +173,8 @@ int32_t DeviceInfoDS::GetDeviceName(uint32_t deviceNumber,
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8,
+ uint32_t productUniqueIdUTF8Length,
+- pid_t* pid) {
++ pid_t* pid,
++ bool* deviceIsPlaceholder) {
+ MutexLock lock(&_apiLock);
+ const int32_t result = GetDeviceInfo(
+ deviceNumber, deviceNameUTF8, deviceNameLength, deviceUniqueIdUTF8,
+diff --git a/modules/video_capture/windows/device_info_ds.h b/modules/video_capture/windows/device_info_ds.h
+index e6dfaed366..a9a1449b99 100644
+--- a/modules/video_capture/windows/device_info_ds.h
++++ b/modules/video_capture/windows/device_info_ds.h
+@@ -51,7 +51,8 @@ class DeviceInfoDS : public DeviceInfoImpl {
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8,
+ uint32_t productUniqueIdUTF8Length,
+- pid_t* pid) override;
++ pid_t* pid,
++ bool* deviceIsPlaceholder) override;
+ /*
+ * Display OS /capture device specific settings dialog
diff --git a/third_party/libwebrtc/moz-patch-stack/0101.patch b/third_party/libwebrtc/moz-patch-stack/0101.patch
index 07be6fc934..4955e0efef 100644
--- a/third_party/libwebrtc/moz-patch-stack/0101.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0101.patch
@@ -1,121 +1,107 @@
-From: Jan Grulich <jgrulich@redhat.com>
-Date: Thu, 30 Nov 2023 11:49:00 +0000
-Subject: Bug 1844020 - Add option to DeviceInfo::GetDeviceName() identifying a
- placeholder device r=pehrsons,webrtc-reviewers
+From: Michael Froman <mfroman@mozilla.com>
+Date: Mon, 18 Dec 2023 15:00:00 +0000
+Subject: Bug 1867099 - revert libwebrtc 8602f604e0. r=bwc
-Adds a new parameter "deviceIsPlaceholder" that will be set to true in
-case the returned device is not a real device but a placeholder that is
-just used to inform about camera device existence.
+Upstream 8602f604e0 removed code sending BYEs which breaks some of
+our wpt. They've opened a bug for a real fix here:
+https://bugs.chromium.org/p/webrtc/issues/detail?id=15664
-Differential Revision: https://phabricator.services.mozilla.com/D189929
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/ed31b2acb5fbca3e2d0691a64bc52e65952070c0
+I've opened Bug 1870643 to track the real fix and upstream bug.
+
+Differential Revision: https://phabricator.services.mozilla.com/D196729
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/d92a578327f524ec3e1c144c82492a4c76b8266f
---
- modules/video_capture/linux/device_info_pipewire.cc | 4 +++-
- modules/video_capture/linux/device_info_pipewire.h | 3 ++-
- modules/video_capture/linux/device_info_v4l2.cc | 3 ++-
- modules/video_capture/linux/device_info_v4l2.h | 3 ++-
- modules/video_capture/video_capture.h | 3 ++-
- modules/video_capture/windows/device_info_ds.cc | 3 ++-
- modules/video_capture/windows/device_info_ds.h | 3 ++-
- 7 files changed, 15 insertions(+), 7 deletions(-)
+ call/rtp_video_sender.cc | 1 +
+ modules/rtp_rtcp/source/rtcp_sender.cc | 19 +++++++++++++++++--
+ .../rtp_rtcp/source/rtcp_sender_unittest.cc | 5 +++--
+ modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 1 +
+ modules/rtp_rtcp/source/rtp_rtcp_interface.h | 2 +-
+ 5 files changed, 23 insertions(+), 5 deletions(-)
-diff --git a/modules/video_capture/linux/device_info_pipewire.cc b/modules/video_capture/linux/device_info_pipewire.cc
-index fc0554f384..f9f08a9c27 100644
---- a/modules/video_capture/linux/device_info_pipewire.cc
-+++ b/modules/video_capture/linux/device_info_pipewire.cc
-@@ -50,8 +50,10 @@ int32_t DeviceInfoPipeWire::GetDeviceName(uint32_t deviceNumber,
- uint32_t deviceUniqueIdUTF8Length,
- char* productUniqueIdUTF8,
- uint32_t productUniqueIdUTF8Length,
-- pid_t* pid) {
-+ pid_t* pid,
-+ bool* deviceIsPlaceholder) {
- RTC_CHECK(pipewire_session_);
+diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc
+index 580850359c..ac5540a7f2 100644
+--- a/call/rtp_video_sender.cc
++++ b/call/rtp_video_sender.cc
+@@ -492,6 +492,7 @@ void RtpVideoSender::SetActiveModulesLocked(bool sending) {
+ active_ = sending;
+ for (size_t i = 0; i < rtp_streams_.size(); ++i) {
+ RtpRtcpInterface& rtp_module = *rtp_streams_[i].rtp_rtcp;
++ // Sends a kRtcpByeCode when going from true to false.
+ rtp_module.SetSendingStatus(sending);
+ rtp_module.SetSendingMediaStatus(sending);
+ if (sending) {
+diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc
+index 099b0be1a3..971f49b949 100644
+--- a/modules/rtp_rtcp/source/rtcp_sender.cc
++++ b/modules/rtp_rtcp/source/rtcp_sender.cc
+@@ -212,8 +212,23 @@ bool RTCPSender::Sending() const {
+
+ void RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
+ bool sending) {
+- MutexLock lock(&mutex_rtcp_sender_);
+- sending_ = sending;
++ bool sendRTCPBye = false;
++ {
++ MutexLock lock(&mutex_rtcp_sender_);
+
- if (deviceNumber >= NumberOfDevices())
- return -1;
++ if (method_ != RtcpMode::kOff) {
++ if (sending == false && sending_ == true) {
++ // Trigger RTCP bye
++ sendRTCPBye = true;
++ }
++ }
++ sending_ = sending;
++ }
++ if (sendRTCPBye) {
++ if (SendRTCP(feedback_state, kRtcpBye) != 0) {
++ RTC_LOG(LS_WARNING) << "Failed to send RTCP BYE";
++ }
++ }
+ }
+
+ void RTCPSender::SetNonSenderRttMeasurement(bool enabled) {
+diff --git a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
+index 002a5f86f1..1dcb628722 100644
+--- a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
++++ b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
+@@ -328,12 +328,13 @@ TEST_F(RtcpSenderTest, SendBye) {
+ EXPECT_EQ(kSenderSsrc, parser()->bye()->sender_ssrc());
+ }
+
+-TEST_F(RtcpSenderTest, StopSendingDoesNotTriggersBye) {
++TEST_F(RtcpSenderTest, StopSendingTriggersBye) {
+ auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+ rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+ rtcp_sender->SetSendingStatus(feedback_state(), true);
+ rtcp_sender->SetSendingStatus(feedback_state(), false);
+- EXPECT_EQ(0, parser()->bye()->num_packets());
++ EXPECT_EQ(1, parser()->bye()->num_packets());
++ EXPECT_EQ(kSenderSsrc, parser()->bye()->sender_ssrc());
+ }
+
+ TEST_F(RtcpSenderTest, SendFir) {
+diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+index cca9a40250..a63067141d 100644
+--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
++++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+@@ -296,6 +296,7 @@ RTCPSender::FeedbackState ModuleRtpRtcpImpl::GetFeedbackState() {
-diff --git a/modules/video_capture/linux/device_info_pipewire.h b/modules/video_capture/linux/device_info_pipewire.h
-index 8a33d75892..00715c94bc 100644
---- a/modules/video_capture/linux/device_info_pipewire.h
-+++ b/modules/video_capture/linux/device_info_pipewire.h
-@@ -30,7 +30,8 @@ class DeviceInfoPipeWire : public DeviceInfoImpl {
- uint32_t deviceUniqueIdUTF8Length,
- char* productUniqueIdUTF8 = nullptr,
- uint32_t productUniqueIdUTF8Length = 0,
-- pid_t* pid = 0) override;
-+ pid_t* pid = 0,
-+ bool* deviceIsPlaceholder = 0) override;
- /*
- * Fills the membervariable _captureCapabilities with capabilites for the
- * given device name.
-diff --git a/modules/video_capture/linux/device_info_v4l2.cc b/modules/video_capture/linux/device_info_v4l2.cc
-index 04caaea592..401c38f9c5 100644
---- a/modules/video_capture/linux/device_info_v4l2.cc
-+++ b/modules/video_capture/linux/device_info_v4l2.cc
-@@ -232,7 +232,8 @@ int32_t DeviceInfoV4l2::GetDeviceName(uint32_t deviceNumber,
- uint32_t deviceUniqueIdUTF8Length,
- char* /*productUniqueIdUTF8*/,
- uint32_t /*productUniqueIdUTF8Length*/,
-- pid_t* /*pid*/) {
-+ pid_t* /*pid*/,
-+ bool* /*deviceIsPlaceholder*/) {
- // Travel through /dev/video [0-63]
- uint32_t count = 0;
- char device[20];
-diff --git a/modules/video_capture/linux/device_info_v4l2.h b/modules/video_capture/linux/device_info_v4l2.h
-index 0bec3eb765..55415845ad 100644
---- a/modules/video_capture/linux/device_info_v4l2.h
-+++ b/modules/video_capture/linux/device_info_v4l2.h
-@@ -36,7 +36,8 @@ class DeviceInfoV4l2 : public DeviceInfoImpl {
- uint32_t deviceUniqueIdUTF8Length,
- char* productUniqueIdUTF8 = 0,
- uint32_t productUniqueIdUTF8Length = 0,
-- pid_t* pid=0) override;
-+ pid_t* pid = 0,
-+ bool* deviceIsPlaceholder = 0) override;
- /*
- * Fills the membervariable _captureCapabilities with capabilites for the
- * given device name.
-diff --git a/modules/video_capture/video_capture.h b/modules/video_capture/video_capture.h
-index 43a6a7f832..f59c34f8b2 100644
---- a/modules/video_capture/video_capture.h
-+++ b/modules/video_capture/video_capture.h
-@@ -74,7 +74,8 @@ class VideoCaptureModule : public RefCountInterface {
- uint32_t deviceUniqueIdUTF8Length,
- char* productUniqueIdUTF8 = 0,
- uint32_t productUniqueIdUTF8Length = 0,
-- pid_t* pid = 0) = 0;
-+ pid_t* pid = 0,
-+ bool* deviceIsPlaceholder = 0) = 0;
+ int32_t ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) {
+ if (rtcp_sender_.Sending() != sending) {
++ // Sends RTCP BYE when going from true to false
+ rtcp_sender_.SetSendingStatus(GetFeedbackState(), sending);
+ }
+ return 0;
+diff --git a/modules/rtp_rtcp/source/rtp_rtcp_interface.h b/modules/rtp_rtcp/source/rtp_rtcp_interface.h
+index f196d11b58..bc8da63ab6 100644
+--- a/modules/rtp_rtcp/source/rtp_rtcp_interface.h
++++ b/modules/rtp_rtcp/source/rtp_rtcp_interface.h
+@@ -277,7 +277,7 @@ class RtpRtcpInterface : public RtcpFeedbackSenderInterface {
+ // Returns the FlexFEC SSRC, if there is one.
+ virtual absl::optional<uint32_t> FlexfecSsrc() const = 0;
- // Returns the number of capabilities this device.
- virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8) = 0;
-diff --git a/modules/video_capture/windows/device_info_ds.cc b/modules/video_capture/windows/device_info_ds.cc
-index f6927281f3..8ca741239c 100644
---- a/modules/video_capture/windows/device_info_ds.cc
-+++ b/modules/video_capture/windows/device_info_ds.cc
-@@ -173,7 +173,8 @@ int32_t DeviceInfoDS::GetDeviceName(uint32_t deviceNumber,
- uint32_t deviceUniqueIdUTF8Length,
- char* productUniqueIdUTF8,
- uint32_t productUniqueIdUTF8Length,
-- pid_t* pid) {
-+ pid_t* pid,
-+ bool* deviceIsPlaceholder) {
- MutexLock lock(&_apiLock);
- const int32_t result = GetDeviceInfo(
- deviceNumber, deviceNameUTF8, deviceNameLength, deviceUniqueIdUTF8,
-diff --git a/modules/video_capture/windows/device_info_ds.h b/modules/video_capture/windows/device_info_ds.h
-index e6dfaed366..a9a1449b99 100644
---- a/modules/video_capture/windows/device_info_ds.h
-+++ b/modules/video_capture/windows/device_info_ds.h
-@@ -51,7 +51,8 @@ class DeviceInfoDS : public DeviceInfoImpl {
- uint32_t deviceUniqueIdUTF8Length,
- char* productUniqueIdUTF8,
- uint32_t productUniqueIdUTF8Length,
-- pid_t* pid) override;
-+ pid_t* pid,
-+ bool* deviceIsPlaceholder) override;
+- // Sets sending status.
++ // Sets sending status. Sends kRtcpByeCode when going from true to false.
+ // Returns -1 on failure else 0.
+ virtual int32_t SetSendingStatus(bool sending) = 0;
- /*
- * Display OS /capture device specific settings dialog
diff --git a/third_party/libwebrtc/moz-patch-stack/0102.patch b/third_party/libwebrtc/moz-patch-stack/0102.patch
index d232dcb897..a6da56ee72 100644
--- a/third_party/libwebrtc/moz-patch-stack/0102.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0102.patch
@@ -1,107 +1,33 @@
-From: Michael Froman <mfroman@mozilla.com>
-Date: Mon, 18 Dec 2023 15:00:00 +0000
-Subject: Bug 1867099 - revert libwebrtc 8602f604e0. r=bwc
+From: Andreas Pehrson <apehrson@mozilla.com>
+Date: Fri, 2 Feb 2024 18:43:00 +0000
+Subject: Bug 1878010 - Fix webrtc::VideoCaptureFactory for BSD.
+ r=grulja,gaston,webrtc-reviewers,mjf
-Upstream 8602f604e0 removed code sending BYEs which breaks some of
-our wpt. They've opened a bug for a real fix here:
-https://bugs.chromium.org/p/webrtc/issues/detail?id=15664
-
-I've opened Bug 1870643 to track the real fix and upstream bug.
-
-Differential Revision: https://phabricator.services.mozilla.com/D196729
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/d92a578327f524ec3e1c144c82492a4c76b8266f
+Differential Revision: https://phabricator.services.mozilla.com/D200427
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/f890637efe5abc0020fab83ff2224313cd0c8460
---
- call/rtp_video_sender.cc | 1 +
- modules/rtp_rtcp/source/rtcp_sender.cc | 19 +++++++++++++++++--
- .../rtp_rtcp/source/rtcp_sender_unittest.cc | 5 +++--
- modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 1 +
- modules/rtp_rtcp/source/rtp_rtcp_interface.h | 2 +-
- 5 files changed, 23 insertions(+), 5 deletions(-)
+ modules/video_capture/video_capture_factory.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
-diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc
-index 1ace08fa32..4d99c61bb4 100644
---- a/call/rtp_video_sender.cc
-+++ b/call/rtp_video_sender.cc
-@@ -510,6 +510,7 @@ void RtpVideoSender::SetActiveModulesLocked(
- const bool was_active = rtp_module.Sending();
- const bool should_be_active = active_modules[i];
-
-+ // Sends a kRtcpByeCode when going from true to false.
- rtp_module.SetSendingStatus(active_modules[i]);
-
- if (was_active && !should_be_active) {
-diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc
-index 099b0be1a3..971f49b949 100644
---- a/modules/rtp_rtcp/source/rtcp_sender.cc
-+++ b/modules/rtp_rtcp/source/rtcp_sender.cc
-@@ -212,8 +212,23 @@ bool RTCPSender::Sending() const {
-
- void RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
- bool sending) {
-- MutexLock lock(&mutex_rtcp_sender_);
-- sending_ = sending;
-+ bool sendRTCPBye = false;
-+ {
-+ MutexLock lock(&mutex_rtcp_sender_);
-+
-+ if (method_ != RtcpMode::kOff) {
-+ if (sending == false && sending_ == true) {
-+ // Trigger RTCP bye
-+ sendRTCPBye = true;
-+ }
-+ }
-+ sending_ = sending;
-+ }
-+ if (sendRTCPBye) {
-+ if (SendRTCP(feedback_state, kRtcpBye) != 0) {
-+ RTC_LOG(LS_WARNING) << "Failed to send RTCP BYE";
-+ }
-+ }
- }
-
- void RTCPSender::SetNonSenderRttMeasurement(bool enabled) {
-diff --git a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
-index 002a5f86f1..1dcb628722 100644
---- a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
-+++ b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
-@@ -328,12 +328,13 @@ TEST_F(RtcpSenderTest, SendBye) {
- EXPECT_EQ(kSenderSsrc, parser()->bye()->sender_ssrc());
- }
-
--TEST_F(RtcpSenderTest, StopSendingDoesNotTriggersBye) {
-+TEST_F(RtcpSenderTest, StopSendingTriggersBye) {
- auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
- rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
- rtcp_sender->SetSendingStatus(feedback_state(), true);
- rtcp_sender->SetSendingStatus(feedback_state(), false);
-- EXPECT_EQ(0, parser()->bye()->num_packets());
-+ EXPECT_EQ(1, parser()->bye()->num_packets());
-+ EXPECT_EQ(kSenderSsrc, parser()->bye()->sender_ssrc());
- }
-
- TEST_F(RtcpSenderTest, SendFir) {
-diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
-index cca9a40250..a63067141d 100644
---- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
-+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
-@@ -296,6 +296,7 @@ RTCPSender::FeedbackState ModuleRtpRtcpImpl::GetFeedbackState() {
-
- int32_t ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) {
- if (rtcp_sender_.Sending() != sending) {
-+ // Sends RTCP BYE when going from true to false
- rtcp_sender_.SetSendingStatus(GetFeedbackState(), sending);
- }
- return 0;
-diff --git a/modules/rtp_rtcp/source/rtp_rtcp_interface.h b/modules/rtp_rtcp/source/rtp_rtcp_interface.h
-index f196d11b58..bc8da63ab6 100644
---- a/modules/rtp_rtcp/source/rtp_rtcp_interface.h
-+++ b/modules/rtp_rtcp/source/rtp_rtcp_interface.h
-@@ -277,7 +277,7 @@ class RtpRtcpInterface : public RtcpFeedbackSenderInterface {
- // Returns the FlexFEC SSRC, if there is one.
- virtual absl::optional<uint32_t> FlexfecSsrc() const = 0;
-
-- // Sets sending status.
-+ // Sets sending status. Sends kRtcpByeCode when going from true to false.
- // Returns -1 on failure else 0.
- virtual int32_t SetSendingStatus(bool sending) = 0;
-
+diff --git a/modules/video_capture/video_capture_factory.cc b/modules/video_capture/video_capture_factory.cc
+index e085ac2df8..2790fbbe1c 100644
+--- a/modules/video_capture/video_capture_factory.cc
++++ b/modules/video_capture/video_capture_factory.cc
+@@ -24,7 +24,7 @@ rtc::scoped_refptr<VideoCaptureModule> VideoCaptureFactory::Create(
+ const char* deviceUniqueIdUTF8) {
+ // This is only implemented on pure Linux and WEBRTC_LINUX is defined for
+ // Android as well
+-#if !defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
++#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD)) || defined(WEBRTC_ANDROID)
+ return nullptr;
+ #else
+ return videocapturemodule::VideoCaptureImpl::Create(options,
+@@ -40,7 +40,7 @@ VideoCaptureModule::DeviceInfo* VideoCaptureFactory::CreateDeviceInfo(
+ VideoCaptureOptions* options) {
+ // This is only implemented on pure Linux and WEBRTC_LINUX is defined for
+ // Android as well
+-#if !defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
++#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD)) || defined(WEBRTC_ANDROID)
+ return nullptr;
+ #else
+ return videocapturemodule::VideoCaptureImpl::CreateDeviceInfo(options);
diff --git a/third_party/libwebrtc/moz-patch-stack/0103.patch b/third_party/libwebrtc/moz-patch-stack/0103.patch
index a6da56ee72..9f518a2ac0 100644
--- a/third_party/libwebrtc/moz-patch-stack/0103.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0103.patch
@@ -1,33 +1,74 @@
-From: Andreas Pehrson <apehrson@mozilla.com>
-Date: Fri, 2 Feb 2024 18:43:00 +0000
-Subject: Bug 1878010 - Fix webrtc::VideoCaptureFactory for BSD.
- r=grulja,gaston,webrtc-reviewers,mjf
+From: Dan Baker <dbaker@mozilla.com>
+Date: Thu, 14 Mar 2024 10:51:00 -0600
+Subject: Bug 1883116 - (fix-e79e722834) add enviroment_factory to libwebrtc
+ build and enforce providing clock and task_queue when creating Environment
-Differential Revision: https://phabricator.services.mozilla.com/D200427
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/f890637efe5abc0020fab83ff2224313cd0c8460
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2185cab977988fd4ab03b38dc67f9b06162444da
---
- modules/video_capture/video_capture_factory.cc | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
+ BUILD.gn | 1 +
+ api/environment/environment_factory.cc | 10 ++++++++++
+ api/task_queue/BUILD.gn | 5 +++++
+ 3 files changed, 16 insertions(+)
-diff --git a/modules/video_capture/video_capture_factory.cc b/modules/video_capture/video_capture_factory.cc
-index e085ac2df8..2790fbbe1c 100644
---- a/modules/video_capture/video_capture_factory.cc
-+++ b/modules/video_capture/video_capture_factory.cc
-@@ -24,7 +24,7 @@ rtc::scoped_refptr<VideoCaptureModule> VideoCaptureFactory::Create(
- const char* deviceUniqueIdUTF8) {
- // This is only implemented on pure Linux and WEBRTC_LINUX is defined for
- // Android as well
--#if !defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
-+#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD)) || defined(WEBRTC_ANDROID)
- return nullptr;
- #else
- return videocapturemodule::VideoCaptureImpl::Create(options,
-@@ -40,7 +40,7 @@ VideoCaptureModule::DeviceInfo* VideoCaptureFactory::CreateDeviceInfo(
- VideoCaptureOptions* options) {
- // This is only implemented on pure Linux and WEBRTC_LINUX is defined for
- // Android as well
--#if !defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
-+#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD)) || defined(WEBRTC_ANDROID)
- return nullptr;
- #else
- return videocapturemodule::VideoCaptureImpl::CreateDeviceInfo(options);
+diff --git a/BUILD.gn b/BUILD.gn
+index 7feca08e60..85ead4162f 100644
+--- a/BUILD.gn
++++ b/BUILD.gn
+@@ -580,6 +580,7 @@ if (!build_with_chromium) {
+
+ if (build_with_mozilla) {
+ deps += [
++ "api/environment:environment_factory",
+ "api/video:video_frame",
+ "api/video:video_rtp_headers",
+ "test:rtp_test_utils",
+diff --git a/api/environment/environment_factory.cc b/api/environment/environment_factory.cc
+index c0b681aa08..6f0ec40dbe 100644
+--- a/api/environment/environment_factory.cc
++++ b/api/environment/environment_factory.cc
+@@ -97,12 +97,22 @@ Environment EnvironmentFactory::CreateWithDefaults() && {
+ if (field_trials_ == nullptr) {
+ Set(std::make_unique<FieldTrialBasedConfig>());
+ }
++#if defined(WEBRTC_MOZILLA_BUILD)
++ // We want to use our clock, not GetRealTimeClockRaw, and we avoid
++ // building the code under third_party/libwebrtc/task_queue. To
++ // ensure we're setting up things correctly, namely providing an
++ // Environment object with a preset task_queue_factory and clock,
++ // we'll do a release assert here.
++ RTC_CHECK(clock_);
++ RTC_CHECK(task_queue_factory_);
++#else
+ if (clock_ == nullptr) {
+ Set(Clock::GetRealTimeClock());
+ }
+ if (task_queue_factory_ == nullptr) {
+ Set(CreateDefaultTaskQueueFactory(field_trials_));
+ }
++#endif
+ if (event_log_ == nullptr) {
+ Set(std::make_unique<RtcEventLogNull>());
+ }
+diff --git a/api/task_queue/BUILD.gn b/api/task_queue/BUILD.gn
+index b9bc81171f..c24c22a1f6 100644
+--- a/api/task_queue/BUILD.gn
++++ b/api/task_queue/BUILD.gn
+@@ -88,6 +88,10 @@ rtc_library("task_queue_test") {
+ }
+
+ rtc_library("default_task_queue_factory") {
++# Mozilla - disable this entire target to avoid inclusion of code we want
++# to avoid. Better here than trying to wack-a-mole for places that list
++# it as a dependency.
++if (!build_with_mozilla) {
+ visibility = [ "*" ]
+ if (!is_ios && !is_android) {
+ # Internally webrtc shouldn't rely on any specific TaskQueue implementation
+@@ -126,6 +130,7 @@ rtc_library("default_task_queue_factory") {
+ sources += [ "default_task_queue_factory_stdlib.cc" ]
+ deps += [ "../../rtc_base:rtc_task_queue_stdlib" ]
+ }
++} # of if (!build_with_mozilla) {
+ }
+
+ rtc_library("pending_task_safety_flag") {
diff --git a/third_party/libwebrtc/moz-patch-stack/0104.patch b/third_party/libwebrtc/moz-patch-stack/0104.patch
index fd05008507..1fa5c7fc7a 100644
--- a/third_party/libwebrtc/moz-patch-stack/0104.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0104.patch
@@ -1,68 +1,28 @@
From: Jan Grulich <jgrulich@redhat.com>
-Date: Fri, 2 Feb 2024 11:47:00 +0000
-Subject: Bug 1876896 - WebRTC backport: Allow VideoCaptureModulePipeWire to be
- shared with more consumers r=pehrsons,webrtc-reviewers
+Date: Wed, 6 Mar 2024 10:19:00 +0000
+Subject: Bug 1882438 - WebRTC backport: PipeWire camera - use length of device
+ id instead display name r=pehrsons,webrtc-reviewers
This is a simple backport of an WebRTC upstream change.
-Upstream commit: 958c9ac546f33716d097b5092515dcac705151d3
+Upstream commit: 16ac10d9f75cde959f00df062f544c49941882da
-Differential Revision: https://phabricator.services.mozilla.com/D200142
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2ba2ef65280b2e6f246fed24d6986718981744f5
+Differential Revision: https://phabricator.services.mozilla.com/D203099
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b572eb8b39b03f714234afff4bd80b4612439521
---
- .../video_capture/linux/video_capture_pipewire.cc | 15 ++++++++++++++-
- .../video_capture/linux/video_capture_pipewire.h | 1 +
- 2 files changed, 15 insertions(+), 1 deletion(-)
+ modules/video_capture/linux/device_info_pipewire.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
-diff --git a/modules/video_capture/linux/video_capture_pipewire.cc b/modules/video_capture/linux/video_capture_pipewire.cc
-index 9d47e3ddbf..fb813e331f 100644
---- a/modules/video_capture/linux/video_capture_pipewire.cc
-+++ b/modules/video_capture/linux/video_capture_pipewire.cc
-@@ -48,7 +48,10 @@ VideoType VideoCaptureModulePipeWire::PipeWireRawFormatToVideoType(
+diff --git a/modules/video_capture/linux/device_info_pipewire.cc b/modules/video_capture/linux/device_info_pipewire.cc
+index f9f08a9c27..31d922035b 100644
+--- a/modules/video_capture/linux/device_info_pipewire.cc
++++ b/modules/video_capture/linux/device_info_pipewire.cc
+@@ -96,7 +96,7 @@ int32_t DeviceInfoPipeWire::CreateCapabilityMap(
+ continue;
- VideoCaptureModulePipeWire::VideoCaptureModulePipeWire(
- VideoCaptureOptions* options)
-- : VideoCaptureImpl(), session_(options->pipewire_session()) {}
-+ : VideoCaptureImpl(),
-+ session_(options->pipewire_session()),
-+ initialized_(false),
-+ started_(false) {}
-
- VideoCaptureModulePipeWire::~VideoCaptureModulePipeWire() {
- RTC_DCHECK_RUN_ON(&api_checker_);
-@@ -121,6 +124,14 @@ int32_t VideoCaptureModulePipeWire::StartCapture(
- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- RTC_DCHECK_RUN_ON(&api_checker_);
-
-+ if (initialized_) {
-+ if (capability == _requestedCapability) {
-+ return 0;
-+ } else {
-+ StopCapture();
-+ }
-+ }
-+
- uint8_t buffer[1024] = {};
-
- RTC_LOG(LS_VERBOSE) << "Creating new PipeWire stream for node " << node_id_;
-@@ -171,6 +182,8 @@ int32_t VideoCaptureModulePipeWire::StartCapture(
- }
-
- _requestedCapability = capability;
-+ initialized_ = true;
-+
- return 0;
- }
-
-diff --git a/modules/video_capture/linux/video_capture_pipewire.h b/modules/video_capture/linux/video_capture_pipewire.h
-index 620ee520ca..5d6794ed65 100644
---- a/modules/video_capture/linux/video_capture_pipewire.h
-+++ b/modules/video_capture/linux/video_capture_pipewire.h
-@@ -50,6 +50,7 @@ class VideoCaptureModulePipeWire : public VideoCaptureImpl {
- int node_id_ RTC_GUARDED_BY(capture_checker_);
- VideoCaptureCapability configured_capability_
- RTC_GUARDED_BY(pipewire_checker_);
-+ bool initialized_ RTC_GUARDED_BY(capture_checker_);
- bool started_ RTC_GUARDED_BY(api_lock_);
-
- struct pw_stream* stream_ RTC_GUARDED_BY(pipewire_checker_) = nullptr;
+ _captureCapabilities = node.capabilities();
+- _lastUsedDeviceNameLength = node.display_name().length();
++ _lastUsedDeviceNameLength = node.unique_id().length();
+ _lastUsedDeviceName = static_cast<char*>(
+ realloc(_lastUsedDeviceName, _lastUsedDeviceNameLength + 1));
+ memcpy(_lastUsedDeviceName, deviceUniqueIdUTF8,
diff --git a/third_party/libwebrtc/moz-patch-stack/0105.patch b/third_party/libwebrtc/moz-patch-stack/0105.patch
index 1db996311f..d3ccb0bbd2 100644
--- a/third_party/libwebrtc/moz-patch-stack/0105.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0105.patch
@@ -1,127 +1,27 @@
From: Jan Grulich <jgrulich@redhat.com>
-Date: Tue, 13 Feb 2024 13:12:00 +0000
-Subject: Bug 1879752 - WebRTC backport: Video capture PipeWire - simplify
- thread and lock annotations r=pehrsons,webrtc-reviewers
+Date: Tue, 5 Mar 2024 08:38:00 +0000
+Subject: Bug 1615282 - WebRTC backport: PipeWire capturer - set capturer as
+ failed when session is closed r=pehrsons,webrtc-reviewers
This is a simple backport of an WebRTC upstream change.
-Upstream commit: 541f202354e2b4906935c8db6e54386aa8bc8d1f
+Upstream commit: 058bfe3ae37a7a245f9c8c6c03f4f7ac48fe179d
-Differential Revision: https://phabricator.services.mozilla.com/D201328
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/dc12e6eecaa8dc91ee0a517cfd27570691c441b9
+Differential Revision: https://phabricator.services.mozilla.com/D202788
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/633149c5da9337f67b6659e5d5bead2233027460
---
- .../linux/video_capture_pipewire.cc | 25 ++++++++++++-------
- .../linux/video_capture_pipewire.h | 14 +++++------
- 2 files changed, 22 insertions(+), 17 deletions(-)
+ modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc | 1 +
+ 1 file changed, 1 insertion(+)
-diff --git a/modules/video_capture/linux/video_capture_pipewire.cc b/modules/video_capture/linux/video_capture_pipewire.cc
-index fb813e331f..8af483636a 100644
---- a/modules/video_capture/linux/video_capture_pipewire.cc
-+++ b/modules/video_capture/linux/video_capture_pipewire.cc
-@@ -121,7 +121,6 @@ static spa_pod* BuildFormat(spa_pod_builder* builder,
-
- int32_t VideoCaptureModulePipeWire::StartCapture(
- const VideoCaptureCapability& capability) {
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- RTC_DCHECK_RUN_ON(&api_checker_);
-
- if (initialized_) {
-@@ -134,10 +133,17 @@ int32_t VideoCaptureModulePipeWire::StartCapture(
-
- uint8_t buffer[1024] = {};
-
-+ // We don't want members above to be guarded by capture_checker_ as
-+ // it's meant to be for members that are accessed on the API thread
-+ // only when we are not capturing. The code above can be called many
-+ // times while sharing instance of VideoCapturePipeWire between
-+ // websites and therefore it would not follow the requirements of this
-+ // checker.
-+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
-+ PipeWireThreadLoopLock thread_loop_lock(session_->pw_main_loop_);
-+
- RTC_LOG(LS_VERBOSE) << "Creating new PipeWire stream for node " << node_id_;
-
-- PipeWireThreadLoopLock thread_loop_lock(session_->pw_main_loop_);
-- RTC_CHECK_RUNS_SERIALIZED(&pipewire_checker_);
- pw_properties* reuse_props =
- pw_properties_new_string("pipewire.client.reuse=1");
- stream_ = pw_stream_new(session_->pw_core_, "camera-stream", reuse_props);
-@@ -188,11 +194,13 @@ int32_t VideoCaptureModulePipeWire::StartCapture(
- }
-
- int32_t VideoCaptureModulePipeWire::StopCapture() {
-- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- RTC_DCHECK_RUN_ON(&api_checker_);
-
- PipeWireThreadLoopLock thread_loop_lock(session_->pw_main_loop_);
-- RTC_CHECK_RUNS_SERIALIZED(&pipewire_checker_);
-+ // PipeWireSession is guarded by API checker so just make sure we do
-+ // race detection when the PipeWire loop is locked/stopped to not run
-+ // any callback at this point.
-+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
- if (stream_) {
- pw_stream_destroy(stream_);
- stream_ = nullptr;
-@@ -225,14 +233,14 @@ void VideoCaptureModulePipeWire::OnStreamParamChanged(
- VideoCaptureModulePipeWire* that =
- static_cast<VideoCaptureModulePipeWire*>(data);
- RTC_DCHECK(that);
-- RTC_CHECK_RUNS_SERIALIZED(&that->pipewire_checker_);
-+ RTC_CHECK_RUNS_SERIALIZED(&that->capture_checker_);
-
- if (format && id == SPA_PARAM_Format)
- that->OnFormatChanged(format);
+diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
+index 40764de7ae..81caa9bd2d 100644
+--- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
++++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
+@@ -112,6 +112,7 @@ void BaseCapturerPipeWire::OnScreenCastSessionClosed() {
+ if (!capturer_failed_) {
+ options_.screencast_stream()->StopScreenCastStream();
+ }
++ capturer_failed_ = true;
}
- void VideoCaptureModulePipeWire::OnFormatChanged(const struct spa_pod* format) {
-- RTC_CHECK_RUNS_SERIALIZED(&pipewire_checker_);
-+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
-
- uint32_t media_type, media_subtype;
-
-@@ -331,7 +339,6 @@ void VideoCaptureModulePipeWire::OnStreamStateChanged(
- VideoCaptureModulePipeWire* that =
- static_cast<VideoCaptureModulePipeWire*>(data);
- RTC_DCHECK(that);
-- RTC_CHECK_RUNS_SERIALIZED(&that->capture_checker_);
-
- MutexLock lock(&that->api_lock_);
- switch (state) {
-@@ -374,7 +381,7 @@ static VideoRotation VideorotationFromPipeWireTransform(uint32_t transform) {
- }
-
- void VideoCaptureModulePipeWire::ProcessBuffers() {
-- RTC_CHECK_RUNS_SERIALIZED(&pipewire_checker_);
-+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
-
- while (pw_buffer* buffer = pw_stream_dequeue_buffer(stream_)) {
- struct spa_meta_header* h;
-diff --git a/modules/video_capture/linux/video_capture_pipewire.h b/modules/video_capture/linux/video_capture_pipewire.h
-index 5d6794ed65..eeb3b9497c 100644
---- a/modules/video_capture/linux/video_capture_pipewire.h
-+++ b/modules/video_capture/linux/video_capture_pipewire.h
-@@ -43,18 +43,16 @@ class VideoCaptureModulePipeWire : public VideoCaptureImpl {
- void OnFormatChanged(const struct spa_pod* format);
- void ProcessBuffers();
-
-- rtc::RaceChecker pipewire_checker_;
--
- const rtc::scoped_refptr<PipeWireSession> session_
-- RTC_GUARDED_BY(capture_checker_);
-+ RTC_GUARDED_BY(api_checker_);
-+ bool initialized_ RTC_GUARDED_BY(api_checker_);
-+ bool started_ RTC_GUARDED_BY(api_lock_);
- int node_id_ RTC_GUARDED_BY(capture_checker_);
- VideoCaptureCapability configured_capability_
-- RTC_GUARDED_BY(pipewire_checker_);
-- bool initialized_ RTC_GUARDED_BY(capture_checker_);
-- bool started_ RTC_GUARDED_BY(api_lock_);
-+ RTC_GUARDED_BY(capture_checker_);
-
-- struct pw_stream* stream_ RTC_GUARDED_BY(pipewire_checker_) = nullptr;
-- struct spa_hook stream_listener_ RTC_GUARDED_BY(pipewire_checker_);
-+ struct pw_stream* stream_ RTC_GUARDED_BY(capture_checker_) = nullptr;
-+ struct spa_hook stream_listener_ RTC_GUARDED_BY(capture_checker_);
- };
- } // namespace videocapturemodule
- } // namespace webrtc
+ void BaseCapturerPipeWire::UpdateResolution(uint32_t width, uint32_t height) {
diff --git a/third_party/libwebrtc/moz-patch-stack/0106.patch b/third_party/libwebrtc/moz-patch-stack/0106.patch
index 9f518a2ac0..7fcb865db5 100644
--- a/third_party/libwebrtc/moz-patch-stack/0106.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0106.patch
@@ -1,74 +1,243 @@
-From: Dan Baker <dbaker@mozilla.com>
-Date: Thu, 14 Mar 2024 10:51:00 -0600
-Subject: Bug 1883116 - (fix-e79e722834) add enviroment_factory to libwebrtc
- build and enforce providing clock and task_queue when creating Environment
+From: Jan Grulich <jgrulich@redhat.com>
+Date: Tue, 5 Mar 2024 08:38:00 +0000
+Subject: Bug 1876895 - WebRTC backport: Video capture PipeWire: add support
+ for DMABuf buffer type r=pehrsons,webrtc-reviewers
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2185cab977988fd4ab03b38dc67f9b06162444da
+This is a simple backport of an WebRTC upstream change.
+
+Upstream commit: 334e9133dcdecb5d00d991332e05c7b80ae26578
+
+Differential Revision: https://phabricator.services.mozilla.com/D202929
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e915ae33e90a5e176f9196a67a201b86e22e498b
---
- BUILD.gn | 1 +
- api/environment/environment_factory.cc | 10 ++++++++++
- api/task_queue/BUILD.gn | 5 +++++
- 3 files changed, 16 insertions(+)
+ .../linux/wayland/shared_screencast_stream.cc | 28 -------
+ modules/portal/pipewire_utils.h | 75 +++++++++++++++++++
+ .../linux/video_capture_pipewire.cc | 46 +++++++++---
+ 3 files changed, 110 insertions(+), 39 deletions(-)
-diff --git a/BUILD.gn b/BUILD.gn
-index 7feca08e60..85ead4162f 100644
---- a/BUILD.gn
-+++ b/BUILD.gn
-@@ -580,6 +580,7 @@ if (!build_with_chromium) {
+diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
+index 61c6957d27..473f913466 100644
+--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
++++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
+@@ -14,7 +14,6 @@
+ #include <libdrm/drm_fourcc.h>
+ #include <pipewire/pipewire.h>
+ #include <spa/param/video/format-utils.h>
+-#include <sys/mman.h>
- if (build_with_mozilla) {
- deps += [
-+ "api/environment:environment_factory",
- "api/video:video_frame",
- "api/video:video_rtp_headers",
- "test:rtp_test_utils",
-diff --git a/api/environment/environment_factory.cc b/api/environment/environment_factory.cc
-index c0b681aa08..6f0ec40dbe 100644
---- a/api/environment/environment_factory.cc
-+++ b/api/environment/environment_factory.cc
-@@ -97,12 +97,22 @@ Environment EnvironmentFactory::CreateWithDefaults() && {
- if (field_trials_ == nullptr) {
- Set(std::make_unique<FieldTrialBasedConfig>());
- }
-+#if defined(WEBRTC_MOZILLA_BUILD)
-+ // We want to use our clock, not GetRealTimeClockRaw, and we avoid
-+ // building the code under third_party/libwebrtc/task_queue. To
-+ // ensure we're setting up things correctly, namely providing an
-+ // Environment object with a preset task_queue_factory and clock,
-+ // we'll do a release assert here.
-+ RTC_CHECK(clock_);
-+ RTC_CHECK(task_queue_factory_);
-+#else
- if (clock_ == nullptr) {
- Set(Clock::GetRealTimeClock());
- }
- if (task_queue_factory_ == nullptr) {
- Set(CreateDefaultTaskQueueFactory(field_trials_));
- }
-+#endif
- if (event_log_ == nullptr) {
- Set(std::make_unique<RtcEventLogNull>());
+ #include <vector>
+
+@@ -49,33 +48,6 @@ constexpr int CursorMetaSize(int w, int h) {
+ constexpr PipeWireVersion kDmaBufModifierMinVersion = {0, 3, 33};
+ constexpr PipeWireVersion kDropSingleModifierMinVersion = {0, 3, 40};
+
+-class ScopedBuf {
+- public:
+- ScopedBuf() {}
+- ScopedBuf(uint8_t* map, int map_size, int fd)
+- : map_(map), map_size_(map_size), fd_(fd) {}
+- ~ScopedBuf() {
+- if (map_ != MAP_FAILED) {
+- munmap(map_, map_size_);
+- }
+- }
+-
+- explicit operator bool() { return map_ != MAP_FAILED; }
+-
+- void initialize(uint8_t* map, int map_size, int fd) {
+- map_ = map;
+- map_size_ = map_size;
+- fd_ = fd;
+- }
+-
+- uint8_t* get() { return map_; }
+-
+- protected:
+- uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED);
+- int map_size_;
+- int fd_;
+-};
+-
+ class SharedScreenCastStreamPrivate {
+ public:
+ SharedScreenCastStreamPrivate();
+diff --git a/modules/portal/pipewire_utils.h b/modules/portal/pipewire_utils.h
+index 8344a8cefb..c1327b85c9 100644
+--- a/modules/portal/pipewire_utils.h
++++ b/modules/portal/pipewire_utils.h
+@@ -11,6 +11,21 @@
+ #ifndef MODULES_PORTAL_PIPEWIRE_UTILS_H_
+ #define MODULES_PORTAL_PIPEWIRE_UTILS_H_
+
++#include <errno.h>
++#include <stdint.h>
++#include <sys/ioctl.h>
++#include <sys/mman.h>
++
++// static
++struct dma_buf_sync {
++ uint64_t flags;
++};
++#define DMA_BUF_SYNC_READ (1 << 0)
++#define DMA_BUF_SYNC_START (0 << 2)
++#define DMA_BUF_SYNC_END (1 << 2)
++#define DMA_BUF_BASE 'b'
++#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
++
+ struct pw_thread_loop;
+
+ namespace webrtc {
+@@ -32,6 +47,66 @@ class PipeWireThreadLoopLock {
+ pw_thread_loop* const loop_;
+ };
+
++// We should synchronize DMA Buffer object access from CPU to avoid potential
++// cache incoherency and data loss.
++// See
++// https://01.org/linuxgraphics/gfx-docs/drm/driver-api/dma-buf.html#cpu-access-to-dma-buffer-objects
++static bool SyncDmaBuf(int fd, uint64_t start_or_end) {
++ struct dma_buf_sync sync = {0};
++
++ sync.flags = start_or_end | DMA_BUF_SYNC_READ;
++
++ while (true) {
++ int ret;
++ ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
++ if (ret == -1 && errno == EINTR) {
++ continue;
++ } else if (ret == -1) {
++ return false;
++ } else {
++ break;
++ }
++ }
++
++ return true;
++}
++
++class ScopedBuf {
++ public:
++ ScopedBuf() {}
++ ScopedBuf(uint8_t* map, int map_size, int fd, bool is_dma_buf = false)
++ : map_(map), map_size_(map_size), fd_(fd), is_dma_buf_(is_dma_buf) {}
++ ~ScopedBuf() {
++ if (map_ != MAP_FAILED) {
++ if (is_dma_buf_) {
++ SyncDmaBuf(fd_, DMA_BUF_SYNC_END);
++ }
++ munmap(map_, map_size_);
++ }
++ }
++
++ explicit operator bool() { return map_ != MAP_FAILED; }
++
++ void initialize(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) {
++ map_ = map;
++ map_size_ = map_size;
++ is_dma_buf_ = is_dma_buf;
++ fd_ = fd;
++
++ if (is_dma_buf_) {
++ SyncDmaBuf(fd_, DMA_BUF_SYNC_START);
++ }
++ }
++
++ uint8_t* get() { return map_; }
++
++ protected:
++ uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED);
++ int map_size_;
++ int fd_;
++ bool is_dma_buf_;
++};
++
+ } // namespace webrtc
+
+ #endif // MODULES_PORTAL_PIPEWIRE_UTILS_H_
+diff --git a/modules/video_capture/linux/video_capture_pipewire.cc b/modules/video_capture/linux/video_capture_pipewire.cc
+index 8af483636a..319824d3c5 100644
+--- a/modules/video_capture/linux/video_capture_pipewire.cc
++++ b/modules/video_capture/linux/video_capture_pipewire.cc
+@@ -178,8 +178,7 @@ int32_t VideoCaptureModulePipeWire::StartCapture(
+ int res = pw_stream_connect(
+ stream_, PW_DIRECTION_INPUT, node_id_,
+ static_cast<enum pw_stream_flags>(PW_STREAM_FLAG_AUTOCONNECT |
+- PW_STREAM_FLAG_DONT_RECONNECT |
+- PW_STREAM_FLAG_MAP_BUFFERS),
++ PW_STREAM_FLAG_DONT_RECONNECT),
+ params.data(), params.size());
+ if (res != 0) {
+ RTC_LOG(LS_ERROR) << "Could not connect to camera stream: "
+@@ -312,11 +311,11 @@ void VideoCaptureModulePipeWire::OnFormatChanged(const struct spa_pod* format) {
+ 0);
}
-diff --git a/api/task_queue/BUILD.gn b/api/task_queue/BUILD.gn
-index b9bc81171f..c24c22a1f6 100644
---- a/api/task_queue/BUILD.gn
-+++ b/api/task_queue/BUILD.gn
-@@ -88,6 +88,10 @@ rtc_library("task_queue_test") {
- }
- rtc_library("default_task_queue_factory") {
-+# Mozilla - disable this entire target to avoid inclusion of code we want
-+# to avoid. Better here than trying to wack-a-mole for places that list
-+# it as a dependency.
-+if (!build_with_mozilla) {
- visibility = [ "*" ]
- if (!is_ios && !is_android) {
- # Internally webrtc shouldn't rely on any specific TaskQueue implementation
-@@ -126,6 +130,7 @@ rtc_library("default_task_queue_factory") {
- sources += [ "default_task_queue_factory_stdlib.cc" ]
- deps += [ "../../rtc_base:rtc_task_queue_stdlib" ]
++ const int buffer_types =
++ (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr);
+ spa_pod_builder_add(
+ &builder, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32),
+- SPA_PARAM_BUFFERS_dataType,
+- SPA_POD_CHOICE_FLAGS_Int((1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr)),
+- 0);
++ SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(buffer_types), 0);
+ params.push_back(
+ static_cast<spa_pod*>(spa_pod_builder_pop(&builder, &frame)));
+
+@@ -384,14 +383,15 @@ void VideoCaptureModulePipeWire::ProcessBuffers() {
+ RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
+
+ while (pw_buffer* buffer = pw_stream_dequeue_buffer(stream_)) {
++ spa_buffer* spaBuffer = buffer->buffer;
+ struct spa_meta_header* h;
+ h = static_cast<struct spa_meta_header*>(
+- spa_buffer_find_meta_data(buffer->buffer, SPA_META_Header, sizeof(*h)));
++ spa_buffer_find_meta_data(spaBuffer, SPA_META_Header, sizeof(*h)));
+
+ struct spa_meta_videotransform* videotransform;
+ videotransform =
+ static_cast<struct spa_meta_videotransform*>(spa_buffer_find_meta_data(
+- buffer->buffer, SPA_META_VideoTransform, sizeof(*videotransform)));
++ spaBuffer, SPA_META_VideoTransform, sizeof(*videotransform)));
+ if (videotransform) {
+ VideoRotation rotation =
+ VideorotationFromPipeWireTransform(videotransform->transform);
+@@ -401,11 +401,35 @@ void VideoCaptureModulePipeWire::ProcessBuffers() {
+
+ if (h->flags & SPA_META_HEADER_FLAG_CORRUPTED) {
+ RTC_LOG(LS_INFO) << "Dropping corruped frame.";
+- } else {
+- IncomingFrame(static_cast<unsigned char*>(buffer->buffer->datas[0].data),
+- buffer->buffer->datas[0].chunk->size,
+- configured_capability_);
++ pw_stream_queue_buffer(stream_, buffer);
++ continue;
++ }
++
++ if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf ||
++ spaBuffer->datas[0].type == SPA_DATA_MemFd) {
++ ScopedBuf frame;
++ frame.initialize(
++ static_cast<uint8_t*>(
++ mmap(nullptr,
++ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset,
++ PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0)),
++ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset,
++ spaBuffer->datas[0].fd, spaBuffer->datas[0].type == SPA_DATA_DmaBuf);
++
++ if (!frame) {
++ RTC_LOG(LS_ERROR) << "Failed to mmap the memory: "
++ << std::strerror(errno);
++ return;
++ }
++
++ IncomingFrame(
++ SPA_MEMBER(frame.get(), spaBuffer->datas[0].mapoffset, uint8_t),
++ spaBuffer->datas[0].chunk->size, configured_capability_);
++ } else { // SPA_DATA_MemPtr
++ IncomingFrame(static_cast<uint8_t*>(spaBuffer->datas[0].data),
++ spaBuffer->datas[0].chunk->size, configured_capability_);
+ }
++
+ pw_stream_queue_buffer(stream_, buffer);
}
-+} # of if (!build_with_mozilla) {
}
-
- rtc_library("pending_task_safety_flag") {
diff --git a/third_party/libwebrtc/moz-patch-stack/0107.patch b/third_party/libwebrtc/moz-patch-stack/0107.patch
index 1fa5c7fc7a..b5aad0f88f 100644
--- a/third_party/libwebrtc/moz-patch-stack/0107.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0107.patch
@@ -1,28 +1,39 @@
-From: Jan Grulich <jgrulich@redhat.com>
-Date: Wed, 6 Mar 2024 10:19:00 +0000
-Subject: Bug 1882438 - WebRTC backport: PipeWire camera - use length of device
- id instead display name r=pehrsons,webrtc-reviewers
+From: Andreas Pehrson <apehrson@mozilla.com>
+Date: Wed, 10 Apr 2024 21:54:00 +0000
+Subject: Bug 1888181 - (fix-52fec7d3) Limit scope of race checker in
+ VideoCaptureModuleV4L2::StartCapture. r=mjf
-This is a simple backport of an WebRTC upstream change.
+TSAN detects a race between destroying the scoped race checker in StartCapture
+and creating the scoped race checker in CaptureProcess, because once the capture
+thread has been created (and given its run function) there is no synchronization
+before the run function starts to run.
-Upstream commit: 16ac10d9f75cde959f00df062f544c49941882da
+This patch avoids the race by destroying the StartCapture scoped race checker
+before creating the capture thread.
-Differential Revision: https://phabricator.services.mozilla.com/D203099
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b572eb8b39b03f714234afff4bd80b4612439521
+Differential Revision: https://phabricator.services.mozilla.com/D207203
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b046a1446cee5ab485d4868b3ca9784b16b2d02f
---
- modules/video_capture/linux/device_info_pipewire.cc | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
+ modules/video_capture/linux/video_capture_v4l2.cc | 2 ++
+ 1 file changed, 2 insertions(+)
-diff --git a/modules/video_capture/linux/device_info_pipewire.cc b/modules/video_capture/linux/device_info_pipewire.cc
-index f9f08a9c27..31d922035b 100644
---- a/modules/video_capture/linux/device_info_pipewire.cc
-+++ b/modules/video_capture/linux/device_info_pipewire.cc
-@@ -96,7 +96,7 @@ int32_t DeviceInfoPipeWire::CreateCapabilityMap(
- continue;
+diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc
+index 6d8a5e463f..db2450a2c7 100644
+--- a/modules/video_capture/linux/video_capture_v4l2.cc
++++ b/modules/video_capture/linux/video_capture_v4l2.cc
+@@ -129,6 +129,7 @@ int32_t VideoCaptureModuleV4L2::StartCapture(
+ }
+ }
- _captureCapabilities = node.capabilities();
-- _lastUsedDeviceNameLength = node.display_name().length();
-+ _lastUsedDeviceNameLength = node.unique_id().length();
- _lastUsedDeviceName = static_cast<char*>(
- realloc(_lastUsedDeviceName, _lastUsedDeviceNameLength + 1));
- memcpy(_lastUsedDeviceName, deviceUniqueIdUTF8,
++ {
+ // We don't want members above to be guarded by capture_checker_ as
+ // it's meant to be for members that are accessed on the API thread
+ // only when we are not capturing. The code above can be called many
+@@ -298,6 +299,7 @@ int32_t VideoCaptureModuleV4L2::StartCapture(
+ _requestedCapability = capability;
+ _captureStarted = true;
+ _streaming = true;
++ }
+
+ // start capture thread;
+ if (_captureThread.empty()) {
diff --git a/third_party/libwebrtc/moz-patch-stack/0108.patch b/third_party/libwebrtc/moz-patch-stack/0108.patch
deleted file mode 100644
index d3ccb0bbd2..0000000000
--- a/third_party/libwebrtc/moz-patch-stack/0108.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From: Jan Grulich <jgrulich@redhat.com>
-Date: Tue, 5 Mar 2024 08:38:00 +0000
-Subject: Bug 1615282 - WebRTC backport: PipeWire capturer - set capturer as
- failed when session is closed r=pehrsons,webrtc-reviewers
-
-This is a simple backport of an WebRTC upstream change.
-
-Upstream commit: 058bfe3ae37a7a245f9c8c6c03f4f7ac48fe179d
-
-Differential Revision: https://phabricator.services.mozilla.com/D202788
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/633149c5da9337f67b6659e5d5bead2233027460
----
- modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
-index 40764de7ae..81caa9bd2d 100644
---- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
-+++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
-@@ -112,6 +112,7 @@ void BaseCapturerPipeWire::OnScreenCastSessionClosed() {
- if (!capturer_failed_) {
- options_.screencast_stream()->StopScreenCastStream();
- }
-+ capturer_failed_ = true;
- }
-
- void BaseCapturerPipeWire::UpdateResolution(uint32_t width, uint32_t height) {
diff --git a/third_party/libwebrtc/moz-patch-stack/0109.patch b/third_party/libwebrtc/moz-patch-stack/0109.patch
deleted file mode 100644
index 7fcb865db5..0000000000
--- a/third_party/libwebrtc/moz-patch-stack/0109.patch
+++ /dev/null
@@ -1,243 +0,0 @@
-From: Jan Grulich <jgrulich@redhat.com>
-Date: Tue, 5 Mar 2024 08:38:00 +0000
-Subject: Bug 1876895 - WebRTC backport: Video capture PipeWire: add support
- for DMABuf buffer type r=pehrsons,webrtc-reviewers
-
-This is a simple backport of an WebRTC upstream change.
-
-Upstream commit: 334e9133dcdecb5d00d991332e05c7b80ae26578
-
-Differential Revision: https://phabricator.services.mozilla.com/D202929
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e915ae33e90a5e176f9196a67a201b86e22e498b
----
- .../linux/wayland/shared_screencast_stream.cc | 28 -------
- modules/portal/pipewire_utils.h | 75 +++++++++++++++++++
- .../linux/video_capture_pipewire.cc | 46 +++++++++---
- 3 files changed, 110 insertions(+), 39 deletions(-)
-
-diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
-index 61c6957d27..473f913466 100644
---- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
-+++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
-@@ -14,7 +14,6 @@
- #include <libdrm/drm_fourcc.h>
- #include <pipewire/pipewire.h>
- #include <spa/param/video/format-utils.h>
--#include <sys/mman.h>
-
- #include <vector>
-
-@@ -49,33 +48,6 @@ constexpr int CursorMetaSize(int w, int h) {
- constexpr PipeWireVersion kDmaBufModifierMinVersion = {0, 3, 33};
- constexpr PipeWireVersion kDropSingleModifierMinVersion = {0, 3, 40};
-
--class ScopedBuf {
-- public:
-- ScopedBuf() {}
-- ScopedBuf(uint8_t* map, int map_size, int fd)
-- : map_(map), map_size_(map_size), fd_(fd) {}
-- ~ScopedBuf() {
-- if (map_ != MAP_FAILED) {
-- munmap(map_, map_size_);
-- }
-- }
--
-- explicit operator bool() { return map_ != MAP_FAILED; }
--
-- void initialize(uint8_t* map, int map_size, int fd) {
-- map_ = map;
-- map_size_ = map_size;
-- fd_ = fd;
-- }
--
-- uint8_t* get() { return map_; }
--
-- protected:
-- uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED);
-- int map_size_;
-- int fd_;
--};
--
- class SharedScreenCastStreamPrivate {
- public:
- SharedScreenCastStreamPrivate();
-diff --git a/modules/portal/pipewire_utils.h b/modules/portal/pipewire_utils.h
-index 8344a8cefb..c1327b85c9 100644
---- a/modules/portal/pipewire_utils.h
-+++ b/modules/portal/pipewire_utils.h
-@@ -11,6 +11,21 @@
- #ifndef MODULES_PORTAL_PIPEWIRE_UTILS_H_
- #define MODULES_PORTAL_PIPEWIRE_UTILS_H_
-
-+#include <errno.h>
-+#include <stdint.h>
-+#include <sys/ioctl.h>
-+#include <sys/mman.h>
-+
-+// static
-+struct dma_buf_sync {
-+ uint64_t flags;
-+};
-+#define DMA_BUF_SYNC_READ (1 << 0)
-+#define DMA_BUF_SYNC_START (0 << 2)
-+#define DMA_BUF_SYNC_END (1 << 2)
-+#define DMA_BUF_BASE 'b'
-+#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
-+
- struct pw_thread_loop;
-
- namespace webrtc {
-@@ -32,6 +47,66 @@ class PipeWireThreadLoopLock {
- pw_thread_loop* const loop_;
- };
-
-+// We should synchronize DMA Buffer object access from CPU to avoid potential
-+// cache incoherency and data loss.
-+// See
-+// https://01.org/linuxgraphics/gfx-docs/drm/driver-api/dma-buf.html#cpu-access-to-dma-buffer-objects
-+static bool SyncDmaBuf(int fd, uint64_t start_or_end) {
-+ struct dma_buf_sync sync = {0};
-+
-+ sync.flags = start_or_end | DMA_BUF_SYNC_READ;
-+
-+ while (true) {
-+ int ret;
-+ ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
-+ if (ret == -1 && errno == EINTR) {
-+ continue;
-+ } else if (ret == -1) {
-+ return false;
-+ } else {
-+ break;
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+class ScopedBuf {
-+ public:
-+ ScopedBuf() {}
-+ ScopedBuf(uint8_t* map, int map_size, int fd, bool is_dma_buf = false)
-+ : map_(map), map_size_(map_size), fd_(fd), is_dma_buf_(is_dma_buf) {}
-+ ~ScopedBuf() {
-+ if (map_ != MAP_FAILED) {
-+ if (is_dma_buf_) {
-+ SyncDmaBuf(fd_, DMA_BUF_SYNC_END);
-+ }
-+ munmap(map_, map_size_);
-+ }
-+ }
-+
-+ explicit operator bool() { return map_ != MAP_FAILED; }
-+
-+ void initialize(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) {
-+ map_ = map;
-+ map_size_ = map_size;
-+ is_dma_buf_ = is_dma_buf;
-+ fd_ = fd;
-+
-+ if (is_dma_buf_) {
-+ SyncDmaBuf(fd_, DMA_BUF_SYNC_START);
-+ }
-+ }
-+
-+ uint8_t* get() { return map_; }
-+
-+ protected:
-+ uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED);
-+ int map_size_;
-+ int fd_;
-+ bool is_dma_buf_;
-+};
-+
- } // namespace webrtc
-
- #endif // MODULES_PORTAL_PIPEWIRE_UTILS_H_
-diff --git a/modules/video_capture/linux/video_capture_pipewire.cc b/modules/video_capture/linux/video_capture_pipewire.cc
-index 8af483636a..319824d3c5 100644
---- a/modules/video_capture/linux/video_capture_pipewire.cc
-+++ b/modules/video_capture/linux/video_capture_pipewire.cc
-@@ -178,8 +178,7 @@ int32_t VideoCaptureModulePipeWire::StartCapture(
- int res = pw_stream_connect(
- stream_, PW_DIRECTION_INPUT, node_id_,
- static_cast<enum pw_stream_flags>(PW_STREAM_FLAG_AUTOCONNECT |
-- PW_STREAM_FLAG_DONT_RECONNECT |
-- PW_STREAM_FLAG_MAP_BUFFERS),
-+ PW_STREAM_FLAG_DONT_RECONNECT),
- params.data(), params.size());
- if (res != 0) {
- RTC_LOG(LS_ERROR) << "Could not connect to camera stream: "
-@@ -312,11 +311,11 @@ void VideoCaptureModulePipeWire::OnFormatChanged(const struct spa_pod* format) {
- 0);
- }
-
-+ const int buffer_types =
-+ (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr);
- spa_pod_builder_add(
- &builder, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32),
-- SPA_PARAM_BUFFERS_dataType,
-- SPA_POD_CHOICE_FLAGS_Int((1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr)),
-- 0);
-+ SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(buffer_types), 0);
- params.push_back(
- static_cast<spa_pod*>(spa_pod_builder_pop(&builder, &frame)));
-
-@@ -384,14 +383,15 @@ void VideoCaptureModulePipeWire::ProcessBuffers() {
- RTC_CHECK_RUNS_SERIALIZED(&capture_checker_);
-
- while (pw_buffer* buffer = pw_stream_dequeue_buffer(stream_)) {
-+ spa_buffer* spaBuffer = buffer->buffer;
- struct spa_meta_header* h;
- h = static_cast<struct spa_meta_header*>(
-- spa_buffer_find_meta_data(buffer->buffer, SPA_META_Header, sizeof(*h)));
-+ spa_buffer_find_meta_data(spaBuffer, SPA_META_Header, sizeof(*h)));
-
- struct spa_meta_videotransform* videotransform;
- videotransform =
- static_cast<struct spa_meta_videotransform*>(spa_buffer_find_meta_data(
-- buffer->buffer, SPA_META_VideoTransform, sizeof(*videotransform)));
-+ spaBuffer, SPA_META_VideoTransform, sizeof(*videotransform)));
- if (videotransform) {
- VideoRotation rotation =
- VideorotationFromPipeWireTransform(videotransform->transform);
-@@ -401,11 +401,35 @@ void VideoCaptureModulePipeWire::ProcessBuffers() {
-
- if (h->flags & SPA_META_HEADER_FLAG_CORRUPTED) {
- RTC_LOG(LS_INFO) << "Dropping corruped frame.";
-- } else {
-- IncomingFrame(static_cast<unsigned char*>(buffer->buffer->datas[0].data),
-- buffer->buffer->datas[0].chunk->size,
-- configured_capability_);
-+ pw_stream_queue_buffer(stream_, buffer);
-+ continue;
-+ }
-+
-+ if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf ||
-+ spaBuffer->datas[0].type == SPA_DATA_MemFd) {
-+ ScopedBuf frame;
-+ frame.initialize(
-+ static_cast<uint8_t*>(
-+ mmap(nullptr,
-+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset,
-+ PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0)),
-+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset,
-+ spaBuffer->datas[0].fd, spaBuffer->datas[0].type == SPA_DATA_DmaBuf);
-+
-+ if (!frame) {
-+ RTC_LOG(LS_ERROR) << "Failed to mmap the memory: "
-+ << std::strerror(errno);
-+ return;
-+ }
-+
-+ IncomingFrame(
-+ SPA_MEMBER(frame.get(), spaBuffer->datas[0].mapoffset, uint8_t),
-+ spaBuffer->datas[0].chunk->size, configured_capability_);
-+ } else { // SPA_DATA_MemPtr
-+ IncomingFrame(static_cast<uint8_t*>(spaBuffer->datas[0].data),
-+ spaBuffer->datas[0].chunk->size, configured_capability_);
- }
-+
- pw_stream_queue_buffer(stream_, buffer);
- }
- }
diff --git a/third_party/libwebrtc/moz-patch-stack/0110.patch b/third_party/libwebrtc/moz-patch-stack/0110.patch
deleted file mode 100644
index 282205c5e8..0000000000
--- a/third_party/libwebrtc/moz-patch-stack/0110.patch
+++ /dev/null
@@ -1,207 +0,0 @@
-From: Michael Froman <mjfroman@mac.com>
-Date: Wed, 20 Mar 2024 11:32:05 -0500
-Subject: Bug 1886497 - Cherry-pick upstream libwebrtc commit de3c726121
- r?dbaker
-
-Upstream commit: https://webrtc.googlesource.com/src/+/de3c726121bd097e79a8f1aa43df48aab7e2237f
- Update to vpython 3.11 and remove .vpython (v2.x)
-
- Bug: b/310806212
- Change-Id: I7fdb12ee4f83410bed9358e7249e4601e773056f
- Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/335641
- Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
- Commit-Queue: Christoffer Dewerin <jansson@google.com>
- Cr-Commit-Position: refs/heads/main@{#41607}
----
- .vpython | 76 -------------------------------------------------------
- .vpython3 | 38 ++++++++++++++--------------
- 2 files changed, 19 insertions(+), 95 deletions(-)
- delete mode 100644 .vpython
-
-diff --git a/.vpython b/.vpython
-deleted file mode 100644
-index d226875f02..0000000000
---- a/.vpython
-+++ /dev/null
-@@ -1,76 +0,0 @@
--# This is a vpython "spec" file.
--#
--# It describes patterns for python wheel dependencies of the python scripts in
--# the chromium repo, particularly for dependencies that have compiled components
--# (since pure-python dependencies can be easily vendored into third_party).
--#
--# When vpython is invoked, it finds this file and builds a python VirtualEnv,
--# containing all of the dependencies described in this file, fetching them from
--# CIPD (the "Chrome Infrastructure Package Deployer" service). Unlike `pip`,
--# this never requires the end-user machine to have a working python extension
--# compilation environment. All of these packages are built using:
--# https://chromium.googlesource.com/infra/infra/+/main/infra/tools/dockerbuild/
--#
--# All python scripts in the repo share this same spec, to avoid dependency
--# fragmentation.
--#
--# If you have depot_tools installed in your $PATH, you can invoke python scripts
--# in this repo by running them as you normally would run them, except
--# substituting `vpython` instead of `python` on the command line, e.g.:
--# vpython path/to/script.py some --arguments
--#
--# Read more about `vpython` and how to modify this file here:
--# https://chromium.googlesource.com/infra/infra/+/main/doc/users/vpython.md
--
--python_version: "2.7"
--
--# Used by:
--# third_party/catapult
--wheel: <
-- name: "infra/python/wheels/psutil/${platform}_${py_python}_${py_abi}"
-- version: "version:5.2.2"
-->
--
--# Used by tools_webrtc/perf/process_perf_results.py.
--wheel: <
-- name: "infra/python/wheels/httplib2-py2_py3"
-- version: "version:0.10.3"
-->
--
--# Used by:
--# build/toolchain/win
--wheel: <
-- name: "infra/python/wheels/pypiwin32/${vpython_platform}"
-- version: "version:219"
-- match_tag: <
-- platform: "win32"
-- >
-- match_tag: <
-- platform: "win_amd64"
-- >
-->
--
--wheel: <
-- name: "infra/python/wheels/six-py2_py3"
-- version: "version:1.15.0"
-->
--wheel: <
-- name: "infra/python/wheels/pbr-py2_py3"
-- version: "version:3.0.0"
-->
--wheel: <
-- name: "infra/python/wheels/funcsigs-py2_py3"
-- version: "version:1.0.2"
-->
--wheel: <
-- name: "infra/python/wheels/mock-py2_py3"
-- version: "version:2.0.0"
-->
--wheel: <
-- name: "infra/python/wheels/protobuf-py2_py3"
-- version: "version:3.13.0"
-->
--wheel: <
-- name: "infra/python/wheels/requests-py2_py3"
-- version: "version:2.13.0"
-->
-diff --git a/.vpython3 b/.vpython3
-index 3f571df261..2be8efaa0a 100644
---- a/.vpython3
-+++ b/.vpython3
-@@ -22,24 +22,24 @@
- # Read more about `vpython` and how to modify this file here:
- # https://chromium.googlesource.com/infra/infra/+/main/doc/users/vpython.md
-
--python_version: "3.8"
-+python_version: "3.11"
-
- # Used by:
- # third_party/catapult
- wheel: <
- name: "infra/python/wheels/psutil/${vpython_platform}"
-- version: "version:5.8.0.chromium.2"
-+ version: "version:5.8.0.chromium.3"
- >
-
- # Used by tools_webrtc/perf/process_perf_results.py.
- wheel: <
- name: "infra/python/wheels/httplib2-py3"
-- version: "version:0.19.1"
-+ version: "version:0.22.0"
- >
-
- wheel: <
-- name: "infra/python/wheels/pyparsing-py2_py3"
-- version: "version:2.4.7"
-+ name: "infra/python/wheels/pyparsing-py3"
-+ version: "version:3.1.1"
- >
-
-
-@@ -47,7 +47,7 @@ wheel: <
- # build/toolchain/win
- wheel: <
- name: "infra/python/wheels/pywin32/${vpython_platform}"
-- version: "version:300"
-+ version: "version:306"
- match_tag: <
- platform: "win32"
- >
-@@ -59,48 +59,48 @@ wheel: <
- # GRPC used by iOS test.
- wheel: <
- name: "infra/python/wheels/grpcio/${vpython_platform}"
-- version: "version:1.44.0"
-+ version: "version:1.57.0"
- >
-
- wheel: <
- name: "infra/python/wheels/six-py2_py3"
-- version: "version:1.15.0"
-+ version: "version:1.16.0"
- >
- wheel: <
- name: "infra/python/wheels/pbr-py2_py3"
-- version: "version:3.0.0"
-+ version: "version:5.9.0"
- >
- wheel: <
- name: "infra/python/wheels/funcsigs-py2_py3"
- version: "version:1.0.2"
- >
- wheel: <
-- name: "infra/python/wheels/mock-py2_py3"
-- version: "version:2.0.0"
-+ name: "infra/python/wheels/mock-py3"
-+ version: "version:4.0.3"
- >
- wheel: <
- name: "infra/python/wheels/protobuf-py3"
-- version: "version:3.20.0"
-+ version: "version:4.25.1"
- >
- wheel: <
- name: "infra/python/wheels/requests-py3"
- version: "version:2.31.0"
- >
- wheel: <
-- name: "infra/python/wheels/idna-py2_py3"
-- version: "version:2.8"
-+ name: "infra/python/wheels/idna-py3"
-+ version: "version:3.4"
- >
- wheel: <
-- name: "infra/python/wheels/urllib3-py2_py3"
-- version: "version:1.26.6"
-+ name: "infra/python/wheels/urllib3-py3"
-+ version: "version:2.1.0"
- >
- wheel: <
-- name: "infra/python/wheels/certifi-py2_py3"
-- version: "version:2020.11.8"
-+ name: "infra/python/wheels/certifi-py3"
-+ version: "version:2023.11.17"
- >
- wheel: <
- name: "infra/python/wheels/charset_normalizer-py3"
-- version: "version:2.0.4"
-+ version: "version:3.3.2"
- >
- wheel: <
- name: "infra/python/wheels/brotli/${vpython_platform}"
diff --git a/third_party/libwebrtc/moz-patch-stack/541f202354.no-op-cherry-pick-msg b/third_party/libwebrtc/moz-patch-stack/541f202354.no-op-cherry-pick-msg
deleted file mode 100644
index d8a134c7c8..0000000000
--- a/third_party/libwebrtc/moz-patch-stack/541f202354.no-op-cherry-pick-msg
+++ /dev/null
@@ -1 +0,0 @@
-We cherry-picked this in bug 1879752.
diff --git a/third_party/libwebrtc/moz-patch-stack/74a4038ead.no-op-cherry-pick-msg b/third_party/libwebrtc/moz-patch-stack/74a4038ead.no-op-cherry-pick-msg
new file mode 100644
index 0000000000..b215d689da
--- /dev/null
+++ b/third_party/libwebrtc/moz-patch-stack/74a4038ead.no-op-cherry-pick-msg
@@ -0,0 +1 @@
+We already cherry-picked this when we vendored 6b419a0536.
diff --git a/third_party/libwebrtc/moz-patch-stack/958c9ac546.no-op-cherry-pick-msg b/third_party/libwebrtc/moz-patch-stack/958c9ac546.no-op-cherry-pick-msg
deleted file mode 100644
index 37de73ffe6..0000000000
--- a/third_party/libwebrtc/moz-patch-stack/958c9ac546.no-op-cherry-pick-msg
+++ /dev/null
@@ -1 +0,0 @@
-We cherry-picked this in bug 1876896.
diff --git a/third_party/libwebrtc/moz-patch-stack/de3c726121.no-op-cherry-pick-msg b/third_party/libwebrtc/moz-patch-stack/de3c726121.no-op-cherry-pick-msg
deleted file mode 100644
index f3ae571b0c..0000000000
--- a/third_party/libwebrtc/moz-patch-stack/de3c726121.no-op-cherry-pick-msg
+++ /dev/null
@@ -1 +0,0 @@
-We cherry-picked this in bug 1886497
diff --git a/third_party/libwebrtc/moz.build b/third_party/libwebrtc/moz.build
index 59472bdc9b..68c4cd93c4 100644
--- a/third_party/libwebrtc/moz.build
+++ b/third_party/libwebrtc/moz.build
@@ -76,6 +76,7 @@ DIRS += [
"/third_party/libwebrtc/api/task_queue/default_task_queue_factory_gn",
"/third_party/libwebrtc/api/task_queue/pending_task_safety_flag_gn",
"/third_party/libwebrtc/api/task_queue/task_queue_gn",
+ "/third_party/libwebrtc/api/transport/bandwidth_estimation_settings_gn",
"/third_party/libwebrtc/api/transport/bitrate_settings_gn",
"/third_party/libwebrtc/api/transport/datagram_transport_interface_gn",
"/third_party/libwebrtc/api/transport/field_trial_based_config_gn",
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.cc
index 75f7d3c487..a846d6dff3 100644
--- a/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.cc
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.cc
@@ -15,32 +15,44 @@
#include "absl/types/optional.h"
#include "api/array_view.h"
+#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://www.ietf.org/archive/id/draft-tuexen-tsvwg-sctp-zero-checksum-00.html#section-3
-// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | Type = 0x8001 | Length = 4 |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Type = 0x8001 (suggested) | Length = 8 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Error Detection Method Identifier (EDMID) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ZeroChecksumAcceptableChunkParameter::kType;
absl::optional<ZeroChecksumAcceptableChunkParameter>
ZeroChecksumAcceptableChunkParameter::Parse(
rtc::ArrayView<const uint8_t> data) {
- if (!ParseTLV(data).has_value()) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
return absl::nullopt;
}
- return ZeroChecksumAcceptableChunkParameter();
+
+ ZeroChecksumAlternateErrorDetectionMethod method(reader->Load32<4>());
+ if (method == ZeroChecksumAlternateErrorDetectionMethod::None()) {
+ return absl::nullopt;
+ }
+ return ZeroChecksumAcceptableChunkParameter(method);
}
void ZeroChecksumAcceptableChunkParameter::SerializeTo(
std::vector<uint8_t>& out) const {
- AllocateTLV(out);
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
+ writer.Store32<4>(*error_detection_method_);
}
std::string ZeroChecksumAcceptableChunkParameter::ToString() const {
- return "Zero Checksum Acceptable";
+ rtc::StringBuilder sb;
+ sb << "Zero Checksum Acceptable (" << *error_detection_method_ << ")";
+ return sb.Release();
}
} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.h
index 9ae2ec8280..18c98c95c6 100644
--- a/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.h
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter.h
@@ -19,13 +19,14 @@
#include "api/array_view.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
+#include "net/dcsctp/public/types.h"
namespace dcsctp {
-// https://datatracker.ietf.org/doc/draft-tuexen-tsvwg-sctp-zero-checksum/
+// https://datatracker.ietf.org/doc/draft-ietf-tsvwg-sctp-zero-checksum/
struct ZeroChecksumAcceptableChunkParameterConfig : ParameterConfig {
static constexpr int kType = 0x8001;
- static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 0;
};
@@ -36,13 +37,22 @@ class ZeroChecksumAcceptableChunkParameter
static constexpr int kType =
ZeroChecksumAcceptableChunkParameterConfig::kType;
- ZeroChecksumAcceptableChunkParameter() {}
+ explicit ZeroChecksumAcceptableChunkParameter(
+ ZeroChecksumAlternateErrorDetectionMethod error_detection_method)
+ : error_detection_method_(error_detection_method) {}
static absl::optional<ZeroChecksumAcceptableChunkParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
+
+ ZeroChecksumAlternateErrorDetectionMethod error_detection_method() const {
+ return error_detection_method_;
+ }
+
+ private:
+ ZeroChecksumAlternateErrorDetectionMethod error_detection_method_;
};
} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter_test.cc
index 8a004e1788..861fa4d785 100644
--- a/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter_test.cc
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/zero_checksum_acceptable_chunk_parameter_test.cc
@@ -24,18 +24,28 @@ namespace {
using ::testing::ElementsAre;
TEST(ZeroChecksumAcceptableChunkParameterTest, SerializeAndDeserialize) {
- ZeroChecksumAcceptableChunkParameter parameter;
+ ZeroChecksumAcceptableChunkParameter parameter(
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls());
std::vector<uint8_t> serialized;
parameter.SerializeTo(serialized);
- EXPECT_THAT(serialized, ElementsAre(0x80, 0x01, 0x00, 0x04));
+ EXPECT_THAT(serialized,
+ ElementsAre(0x80, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01));
ASSERT_HAS_VALUE_AND_ASSIGN(
ZeroChecksumAcceptableChunkParameter deserialized,
ZeroChecksumAcceptableChunkParameter::Parse(serialized));
}
+TEST(ZeroChecksumAcceptableChunkParameterTest, FailToDeserializePrevVersion) {
+ // This is how the draft described the chunk as, in version 00.
+ std::vector<uint8_t> invalid = {0x80, 0x01, 0x00, 0x04};
+
+ EXPECT_FALSE(
+ ZeroChecksumAcceptableChunkParameter::Parse(invalid).has_value());
+}
+
TEST(ZeroChecksumAcceptableChunkParameterTest, FailToDeserialize) {
std::vector<uint8_t> invalid = {0x00, 0x00, 0x00, 0x00};
@@ -44,9 +54,10 @@ TEST(ZeroChecksumAcceptableChunkParameterTest, FailToDeserialize) {
}
TEST(ZeroChecksumAcceptableChunkParameterTest, HasToString) {
- ZeroChecksumAcceptableChunkParameter parameter;
+ ZeroChecksumAcceptableChunkParameter parameter(
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls());
- EXPECT_EQ(parameter.ToString(), "Zero Checksum Acceptable");
+ EXPECT_EQ(parameter.ToString(), "Zero Checksum Acceptable (1)");
}
} // namespace
diff --git a/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc
index de407bb4c7..978181fc2a 100644
--- a/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc
+++ b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc
@@ -126,7 +126,9 @@ absl::optional<SctpPacket> SctpPacket::Parse(rtc::ArrayView<const uint8_t> data,
std::vector<uint8_t>(data.begin(), data.end());
if (options.disable_checksum_verification ||
- (options.enable_zero_checksum && common_header.checksum == 0u)) {
+ (options.zero_checksum_alternate_error_detection_method !=
+ ZeroChecksumAlternateErrorDetectionMethod::None() &&
+ common_header.checksum == 0u)) {
// https://www.ietf.org/archive/id/draft-tuexen-tsvwg-sctp-zero-checksum-01.html#section-4.3:
// If an end point has sent the Zero Checksum Acceptable Chunk Parameter in
// an INIT or INIT ACK chunk, it MUST accept SCTP packets using an incorrect
diff --git a/third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc
index fcdd161c0d..aab01df19c 100644
--- a/third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc
+++ b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc
@@ -38,7 +38,8 @@ using ::testing::SizeIs;
constexpr VerificationTag kVerificationTag = VerificationTag(0x12345678);
constexpr DcSctpOptions kVerifyChecksumOptions =
DcSctpOptions{.disable_checksum_verification = false,
- .enable_zero_checksum = false};
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::None()};
TEST(SctpPacketTest, DeserializeSimplePacketFromCapture) {
/*
@@ -208,8 +209,10 @@ TEST(SctpPacketTest, DeserializePacketDontValidateChecksum) {
ASSERT_HAS_VALUE_AND_ASSIGN(
SctpPacket packet,
- SctpPacket::Parse(data, {.disable_checksum_verification = true,
- .enable_zero_checksum = false}));
+ SctpPacket::Parse(
+ data, {.disable_checksum_verification = true,
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::None()}));
EXPECT_EQ(packet.common_header().source_port, 5000);
EXPECT_EQ(packet.common_header().destination_port, 5000);
EXPECT_EQ(packet.common_header().verification_tag,
@@ -375,8 +378,11 @@ TEST(SctpPacketTest, AcceptsZeroSetZeroChecksum) {
ASSERT_HAS_VALUE_AND_ASSIGN(
SctpPacket packet,
- SctpPacket::Parse(data, {.disable_checksum_verification = false,
- .enable_zero_checksum = true}));
+ SctpPacket::Parse(
+ data,
+ {.disable_checksum_verification = false,
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()}));
EXPECT_EQ(packet.common_header().source_port, 5000);
EXPECT_EQ(packet.common_header().destination_port, 5000);
EXPECT_EQ(packet.common_header().verification_tag,
@@ -409,9 +415,13 @@ TEST(SctpPacketTest, RejectsNonZeroIncorrectChecksumWhenZeroChecksumIsActive) {
0x00, 0x00, 0x03, 0x00, 0x00, 0x10, 0x55, 0x08, 0x36, 0x40,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- EXPECT_FALSE(SctpPacket::Parse(data, {.disable_checksum_verification = false,
- .enable_zero_checksum = true})
- .has_value());
+ EXPECT_FALSE(
+ SctpPacket::Parse(
+ data,
+ {.disable_checksum_verification = false,
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()})
+ .has_value());
}
TEST(SctpPacketTest, WritePacketWithCalculatedChecksum) {
diff --git a/third_party/libwebrtc/net/dcsctp/public/dcsctp_options.h b/third_party/libwebrtc/net/dcsctp/public/dcsctp_options.h
index d19798054c..600e8a362e 100644
--- a/third_party/libwebrtc/net/dcsctp/public/dcsctp_options.h
+++ b/third_party/libwebrtc/net/dcsctp/public/dcsctp_options.h
@@ -196,14 +196,13 @@ struct DcSctpOptions {
// Disables SCTP packet crc32 verification. For fuzzers only!
bool disable_checksum_verification = false;
- // Controls the acceptance of zero checksum, as defined in
- // https://datatracker.ietf.org/doc/draft-tuexen-tsvwg-sctp-zero-checksum/
- // This should only be enabled if the packet integrity can be ensured by lower
- // layers, which DTLS will do in WebRTC, as defined by RFC8261.
- //
- // This will also enable sending packets without a checksum value (set to 0)
- // once both peers have negotiated this feature.
- bool enable_zero_checksum = false;
+ // Controls the "zero checksum option" feature, as defined in
+ // https://www.ietf.org/archive/id/draft-ietf-tsvwg-sctp-zero-checksum-06.html.
+ // To have this feature enabled, both peers must be configured to use the
+ // same (defined, not "none") alternate error detection method.
+ ZeroChecksumAlternateErrorDetectionMethod
+ zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::None();
};
} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/public/types.h b/third_party/libwebrtc/net/dcsctp/public/types.h
index 02e2ce1e5e..1565cd7b58 100644
--- a/third_party/libwebrtc/net/dcsctp/public/types.h
+++ b/third_party/libwebrtc/net/dcsctp/public/types.h
@@ -151,6 +151,27 @@ class LifecycleId : public webrtc::StrongAlias<class LifecycleIdTag, uint64_t> {
static constexpr LifecycleId NotSet() { return LifecycleId(0); }
};
+
+// To enable zero checksum feature, both peers must agree on which alternate
+// error detection method that is used. See
+// https://www.ietf.org/archive/id/draft-ietf-tsvwg-sctp-zero-checksum-06.html.
+class ZeroChecksumAlternateErrorDetectionMethod
+ : public webrtc::StrongAlias<
+ class ZeroChecksumAlternateErrorDetectionMethodTag,
+ uint32_t> {
+ public:
+ constexpr explicit ZeroChecksumAlternateErrorDetectionMethod(
+ const UnderlyingType& v)
+ : webrtc::StrongAlias<class ZeroChecksumAlternateErrorDetectionMethodTag,
+ uint32_t>(v) {}
+
+ static constexpr ZeroChecksumAlternateErrorDetectionMethod None() {
+ return ZeroChecksumAlternateErrorDetectionMethod(0);
+ }
+ static constexpr ZeroChecksumAlternateErrorDetectionMethod LowerLayerDtls() {
+ return ZeroChecksumAlternateErrorDetectionMethod(1);
+ }
+};
} // namespace dcsctp
#endif // NET_DCSCTP_PUBLIC_TYPES_H_
diff --git a/third_party/libwebrtc/net/dcsctp/socket/capabilities.h b/third_party/libwebrtc/net/dcsctp/socket/capabilities.h
index 286509a40a..9b1bff0a90 100644
--- a/third_party/libwebrtc/net/dcsctp/socket/capabilities.h
+++ b/third_party/libwebrtc/net/dcsctp/socket/capabilities.h
@@ -21,7 +21,7 @@ struct Capabilities {
bool message_interleaving = false;
// RFC6525 Stream Reconfiguration
bool reconfig = false;
- // https://datatracker.ietf.org/doc/draft-tuexen-tsvwg-sctp-zero-checksum/
+ // https://datatracker.ietf.org/doc/draft-ietf-tsvwg-sctp-zero-checksum/
bool zero_checksum = false;
// Negotiated maximum incoming and outgoing stream count.
uint16_t negotiated_maximum_incoming_streams = 0;
diff --git a/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket.cc b/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket.cc
index 98cd34a111..0667e6f899 100644
--- a/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket.cc
+++ b/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket.cc
@@ -22,7 +22,6 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
-#include "api/task_queue/task_queue_base.h"
#include "net/dcsctp/packet/chunk/abort_chunk.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
@@ -120,8 +119,12 @@ Capabilities ComputeCapabilities(const DcSctpOptions& options,
capabilities.reconfig = true;
}
- if (options.enable_zero_checksum &&
- parameters.get<ZeroChecksumAcceptableChunkParameter>().has_value()) {
+ if (options.zero_checksum_alternate_error_detection_method !=
+ ZeroChecksumAlternateErrorDetectionMethod::None() &&
+ parameters.get<ZeroChecksumAcceptableChunkParameter>().has_value() &&
+ parameters.get<ZeroChecksumAcceptableChunkParameter>()
+ ->error_detection_method() ==
+ options.zero_checksum_alternate_error_detection_method) {
capabilities.zero_checksum = true;
}
@@ -134,6 +137,7 @@ Capabilities ComputeCapabilities(const DcSctpOptions& options,
}
void AddCapabilityParameters(const DcSctpOptions& options,
+ bool support_zero_checksum,
Parameters::Builder& builder) {
std::vector<uint8_t> chunk_types = {ReConfigChunk::kType};
@@ -145,8 +149,11 @@ void AddCapabilityParameters(const DcSctpOptions& options,
chunk_types.push_back(IDataChunk::kType);
chunk_types.push_back(IForwardTsnChunk::kType);
}
- if (options.enable_zero_checksum) {
- builder.Add(ZeroChecksumAcceptableChunkParameter());
+ if (support_zero_checksum) {
+ RTC_DCHECK(options.zero_checksum_alternate_error_detection_method !=
+ ZeroChecksumAlternateErrorDetectionMethod::None());
+ builder.Add(ZeroChecksumAcceptableChunkParameter(
+ options.zero_checksum_alternate_error_detection_method));
}
builder.Add(SupportedExtensionsParameter(std::move(chunk_types)));
}
@@ -282,7 +289,11 @@ void DcSctpSocket::SetState(State state, absl::string_view reason) {
void DcSctpSocket::SendInit() {
Parameters::Builder params_builder;
- AddCapabilityParameters(options_, params_builder);
+ AddCapabilityParameters(
+ options_, /*support_zero_checksum=*/
+ options_.zero_checksum_alternate_error_detection_method !=
+ ZeroChecksumAlternateErrorDetectionMethod::None(),
+ params_builder);
InitChunk init(/*initiate_tag=*/connect_params_.verification_tag,
/*a_rwnd=*/options_.max_receiver_window_buffer_size,
options_.announced_maximum_outgoing_streams,
@@ -1227,7 +1238,7 @@ void DcSctpSocket::HandleInit(const CommonHeader& header,
chunk->initial_tsn(), my_initial_tsn, chunk->a_rwnd(),
tie_tag, capabilities)
.Serialize()));
- AddCapabilityParameters(options_, params_builder);
+ AddCapabilityParameters(options_, capabilities.zero_checksum, params_builder);
InitAckChunk init_ack(/*initiate_tag=*/my_verification_tag,
options_.max_receiver_window_buffer_size,
diff --git a/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket_test.cc b/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket_test.cc
index 413516bae0..dfe8ba60fe 100644
--- a/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket_test.cc
+++ b/third_party/libwebrtc/net/dcsctp/socket/dcsctp_socket_test.cc
@@ -2887,8 +2887,16 @@ TEST_P(DcSctpSocketParametrizedTest, ZeroChecksumMetricsAreSet) {
std::vector<std::pair<bool, bool>> combinations = {
{false, false}, {false, true}, {true, false}, {true, true}};
for (const auto& [a_enable, z_enable] : combinations) {
- DcSctpOptions a_options = {.enable_zero_checksum = a_enable};
- DcSctpOptions z_options = {.enable_zero_checksum = z_enable};
+ DcSctpOptions a_options = {
+ .zero_checksum_alternate_error_detection_method =
+ a_enable
+ ? ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()
+ : ZeroChecksumAlternateErrorDetectionMethod::None()};
+ DcSctpOptions z_options = {
+ .zero_checksum_alternate_error_detection_method =
+ z_enable
+ ? ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()
+ : ZeroChecksumAlternateErrorDetectionMethod::None()};
SocketUnderTest a("A", a_options);
auto z = std::make_unique<SocketUnderTest>("Z", z_options);
@@ -2902,7 +2910,9 @@ TEST_P(DcSctpSocketParametrizedTest, ZeroChecksumMetricsAreSet) {
}
TEST(DcSctpSocketTest, AlwaysSendsInitWithNonZeroChecksum) {
- DcSctpOptions options = {.enable_zero_checksum = true};
+ DcSctpOptions options = {
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()};
SocketUnderTest a("A", options);
a.socket.Connect();
@@ -2916,7 +2926,9 @@ TEST(DcSctpSocketTest, AlwaysSendsInitWithNonZeroChecksum) {
}
TEST(DcSctpSocketTest, MaySendInitAckWithZeroChecksum) {
- DcSctpOptions options = {.enable_zero_checksum = true};
+ DcSctpOptions options = {
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()};
SocketUnderTest a("A", options);
SocketUnderTest z("Z", options);
@@ -2933,7 +2945,9 @@ TEST(DcSctpSocketTest, MaySendInitAckWithZeroChecksum) {
}
TEST(DcSctpSocketTest, AlwaysSendsCookieEchoWithNonZeroChecksum) {
- DcSctpOptions options = {.enable_zero_checksum = true};
+ DcSctpOptions options = {
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()};
SocketUnderTest a("A", options);
SocketUnderTest z("Z", options);
@@ -2951,7 +2965,9 @@ TEST(DcSctpSocketTest, AlwaysSendsCookieEchoWithNonZeroChecksum) {
}
TEST(DcSctpSocketTest, SendsCookieAckWithZeroChecksum) {
- DcSctpOptions options = {.enable_zero_checksum = true};
+ DcSctpOptions options = {
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()};
SocketUnderTest a("A", options);
SocketUnderTest z("Z", options);
@@ -2970,7 +2986,9 @@ TEST(DcSctpSocketTest, SendsCookieAckWithZeroChecksum) {
}
TEST_P(DcSctpSocketParametrizedTest, SendsDataWithZeroChecksum) {
- DcSctpOptions options = {.enable_zero_checksum = true};
+ DcSctpOptions options = {
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()};
SocketUnderTest a("A", options);
auto z = std::make_unique<SocketUnderTest>("Z", options);
@@ -2993,7 +3011,9 @@ TEST_P(DcSctpSocketParametrizedTest, SendsDataWithZeroChecksum) {
}
TEST_P(DcSctpSocketParametrizedTest, AllPacketsAfterConnectHaveZeroChecksum) {
- DcSctpOptions options = {.enable_zero_checksum = true};
+ DcSctpOptions options = {
+ .zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::LowerLayerDtls()};
SocketUnderTest a("A", options);
auto z = std::make_unique<SocketUnderTest>("Z", options);
diff --git a/third_party/libwebrtc/net/dcsctp/socket/heartbeat_handler_test.cc b/third_party/libwebrtc/net/dcsctp/socket/heartbeat_handler_test.cc
index 4475527322..b7f3a60d39 100644
--- a/third_party/libwebrtc/net/dcsctp/socket/heartbeat_handler_test.cc
+++ b/third_party/libwebrtc/net/dcsctp/socket/heartbeat_handler_test.cc
@@ -38,7 +38,8 @@ DcSctpOptions MakeOptions(DurationMs heartbeat_interval) {
DcSctpOptions options;
options.heartbeat_interval_include_rtt = false;
options.heartbeat_interval = heartbeat_interval;
- options.enable_zero_checksum = false;
+ options.zero_checksum_alternate_error_detection_method =
+ ZeroChecksumAlternateErrorDetectionMethod::None();
return options;
}
diff --git a/third_party/libwebrtc/p2p/BUILD.gn b/third_party/libwebrtc/p2p/BUILD.gn
index a663e85e22..05db81ad96 100644
--- a/third_party/libwebrtc/p2p/BUILD.gn
+++ b/third_party/libwebrtc/p2p/BUILD.gn
@@ -18,81 +18,71 @@ group("p2p") {
rtc_library("rtc_p2p") {
visibility = [ "*" ]
sources = [
- "base/active_ice_controller_factory_interface.h",
- "base/active_ice_controller_interface.h",
- "base/async_stun_tcp_socket.cc",
- "base/async_stun_tcp_socket.h",
- "base/basic_async_resolver_factory.cc",
- "base/basic_async_resolver_factory.h",
- "base/basic_ice_controller.cc",
- "base/basic_ice_controller.h",
- "base/basic_packet_socket_factory.cc",
- "base/basic_packet_socket_factory.h",
- "base/candidate_pair_interface.h",
- "base/connection.cc",
- "base/connection.h",
- "base/connection_info.cc",
- "base/connection_info.h",
- "base/default_ice_transport_factory.cc",
- "base/default_ice_transport_factory.h",
- "base/dtls_transport.cc",
- "base/dtls_transport.h",
- "base/dtls_transport_factory.h",
- "base/dtls_transport_internal.cc",
- "base/dtls_transport_internal.h",
- "base/ice_agent_interface.h",
- "base/ice_controller_factory_interface.h",
- "base/ice_controller_interface.cc",
- "base/ice_controller_interface.h",
- "base/ice_credentials_iterator.cc",
- "base/ice_credentials_iterator.h",
- "base/ice_switch_reason.cc",
- "base/ice_switch_reason.h",
- "base/ice_transport_internal.cc",
- "base/ice_transport_internal.h",
- "base/p2p_constants.cc",
- "base/p2p_constants.h",
- "base/p2p_transport_channel.cc",
- "base/p2p_transport_channel.h",
- "base/p2p_transport_channel_ice_field_trials.h",
- "base/packet_transport_internal.cc",
- "base/packet_transport_internal.h",
- "base/port.cc",
- "base/port.h",
- "base/port_allocator.cc",
- "base/port_allocator.h",
- "base/port_interface.cc",
- "base/port_interface.h",
- "base/pseudo_tcp.cc",
- "base/pseudo_tcp.h",
- "base/regathering_controller.cc",
- "base/regathering_controller.h",
- "base/stun_dictionary.cc",
- "base/stun_dictionary.h",
- "base/stun_port.cc",
- "base/stun_port.h",
- "base/stun_request.cc",
- "base/stun_request.h",
- "base/tcp_port.cc",
- "base/tcp_port.h",
- "base/transport_description.cc",
- "base/transport_description.h",
- "base/transport_description_factory.cc",
- "base/transport_description_factory.h",
- "base/transport_info.h",
- "base/turn_port.cc",
- "base/turn_port.h",
- "base/udp_port.h",
- "base/wrapping_active_ice_controller.cc",
- "base/wrapping_active_ice_controller.h",
- "client/basic_port_allocator.cc",
- "client/basic_port_allocator.h",
- "client/relay_port_factory_interface.h",
- "client/turn_port_factory.cc",
- "client/turn_port_factory.h",
+ # TODO(bugs.webrtc.org/15769): Finish cleanup and remove.
+ "base/active_ice_controller_factory_interface.h", # To be removed (Chrome)
+ "base/active_ice_controller_interface.h", # To be removed (Internal)
+ "base/basic_ice_controller.h", # To be removed (Chrome)
+ "base/basic_packet_socket_factory.h", # To be removed
+ "base/candidate_pair_interface.h", # To be removed
+ "base/connection.h", # To be removed
+ "base/connection_info.h", # To be removed
+ "base/default_ice_transport_factory.h", # To be removed (Chrome)
+ "base/dtls_transport.h", # To be removed
+ "base/dtls_transport_internal.h", # To be removed
+ "base/ice_agent_interface.h", # To be removed (Chrome)
+ "base/ice_controller_interface.h", # To be removed (Chrome)
+ "base/ice_credentials_iterator.h", # To be removed
+ "base/ice_switch_reason.h", # To be removed (Chrome)
+ "base/ice_transport_internal.h", # To be removed
+ "base/p2p_constants.h", # To be removed
+ "base/p2p_transport_channel.h", # To be removed (Chrome)
+ "base/p2p_transport_channel_ice_field_trials.h", # To be removed
+ "base/packet_transport_internal.h", # To be removed
+ "base/port.h", # To be removed (Chrome)
+ "base/port_allocator.h", # To be removed (Chrome)
+ "base/port_interface.h", # To be removed
+ "base/pseudo_tcp.h", # To be removed
+ "base/stun_dictionary.h", # To be removed
+ "base/stun_port.h", # To be removed
+ "base/tcp_port.h", # To be removed
+ "base/transport_description.h", # To be removed
+ "base/transport_info.h", # To be removed
+ "base/turn_port.h", # To be removed
+ "client/basic_port_allocator.h", # To be removed
+ "client/turn_port_factory.h", # To be removed
]
deps = [
+ ":active_ice_controller_factory_interface",
+ ":async_stun_tcp_socket",
+ ":basic_async_resolver_factory",
+ ":basic_ice_controller",
+ ":basic_packet_socket_factory",
+ ":candidate_pair_interface",
+ ":connection",
+ ":connection_info",
+ ":dtls_transport",
+ ":dtls_transport_internal",
+ ":ice_agent_interface",
+ ":ice_controller_factory_interface",
+ ":ice_controller_interface",
+ ":ice_credentials_iterator",
+ ":ice_switch_reason",
+ ":ice_transport_internal",
+ ":p2p_constants",
+ ":p2p_transport_channel",
+ ":p2p_transport_channel_ice_field_trials",
+ ":packet_transport_internal",
+ ":port_interface",
+ ":pseudo_tcp",
+ ":regathering_controller",
+ ":relay_port_factory_interface",
+ ":stun_dictionary",
+ ":stun_request",
+ ":tcp_port",
+ ":transport_description",
+ ":udp_port",
+ ":wrapping_active_ice_controller",
"../api:array_view",
"../api:async_dns_resolver",
"../api:candidate",
@@ -108,6 +98,7 @@ rtc_library("rtc_p2p") {
"../api/crypto:options",
"../api/rtc_event_log",
"../api/task_queue",
+ "../api/task_queue:pending_task_safety_flag",
"../api/transport:enums",
"../api/transport:field_trial_based_config",
"../api/transport:stun_types",
@@ -140,6 +131,7 @@ rtc_library("rtc_p2p") {
"../rtc_base:rate_tracker",
"../rtc_base:refcount",
"../rtc_base:rtc_numerics",
+ "../rtc_base:safe_minmax",
"../rtc_base:socket",
"../rtc_base:socket_adapters",
"../rtc_base:socket_address",
@@ -150,21 +142,468 @@ rtc_library("rtc_p2p") {
"../rtc_base:stringutils",
"../rtc_base:threading",
"../rtc_base:timeutils",
+ "../rtc_base:weak_ptr",
"../rtc_base/containers:flat_map",
"../rtc_base/experiments:field_trial_parser",
"../rtc_base/memory:always_valid_pointer",
+ "../rtc_base/network:received_packet",
+ "../rtc_base/network:sent_packet",
+ "../rtc_base/synchronization:mutex",
"../rtc_base/system:no_unique_address",
+ "../rtc_base/system:rtc_export",
+ "../rtc_base/third_party/base64",
+ "../rtc_base/third_party/sigslot",
+ "../system_wrappers:metrics",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/base:core_headers",
+ "//third_party/abseil-cpp/absl/functional:any_invocable",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_source_set("active_ice_controller_factory_interface") {
+ sources = [ "base/active_ice_controller_factory_interface.h" ]
+ deps = [
+ ":active_ice_controller_interface",
+ ":ice_agent_interface",
+ ":ice_controller_factory_interface",
+ ]
+}
+
+rtc_source_set("active_ice_controller_interface") {
+ sources = [ "base/active_ice_controller_interface.h" ]
+ deps = [
+ ":connection",
+ ":ice_switch_reason",
+ ":ice_transport_internal",
+ ":transport_description",
+ "../api:array_view",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
+rtc_library("basic_async_resolver_factory") {
+ sources = [
+ "base/basic_async_resolver_factory.cc",
+ "base/basic_async_resolver_factory.h",
+ ]
+ deps = [
+ "../api:async_dns_resolver",
+ "../rtc_base:async_dns_resolver",
+ "../rtc_base:logging",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+}
- # Needed by pseudo_tcp, which should move to a separate target.
+rtc_library("async_stun_tcp_socket") {
+ sources = [
+ "base/async_stun_tcp_socket.cc",
+ "base/async_stun_tcp_socket.h",
+ ]
+ deps = [
+ "../api:array_view",
+ "../api/transport:stun_types",
+ "../api/units:timestamp",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:async_tcp_socket",
+ "../rtc_base:byte_order",
+ "../rtc_base:checks",
+ "../rtc_base:socket",
+ "../rtc_base:socket_address",
+ "../rtc_base:timeutils",
+ "../rtc_base/network:received_packet",
+ "../rtc_base/network:sent_packet",
+ ]
+}
+
+rtc_library("basic_ice_controller") {
+ sources = [
+ "base/basic_ice_controller.cc",
+ "base/basic_ice_controller.h",
+ ]
+ deps = [
+ ":ice_controller_factory_interface",
+ ":ice_controller_interface",
+ ]
+}
+
+rtc_library("basic_packet_socket_factory") {
+ sources = [
+ "base/basic_packet_socket_factory.cc",
+ "base/basic_packet_socket_factory.h",
+ ]
+ deps = [
+ ":async_stun_tcp_socket",
+ "../api:async_dns_resolver",
+ "../api:packet_socket_factory",
+ "../rtc_base:async_dns_resolver",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:async_tcp_socket",
+ "../rtc_base:async_udp_socket",
+ "../rtc_base:checks",
+ "../rtc_base:logging",
+ "../rtc_base:proxy_info",
+ "../rtc_base:socket",
+ "../rtc_base:socket_adapters",
+ "../rtc_base:socket_address",
+ "../rtc_base:socket_factory",
+ "../rtc_base:ssl",
+ "../rtc_base/system:rtc_export",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+}
+
+rtc_library("basic_port_allocator") {
+ sources = [
+ "client/basic_port_allocator.cc",
+ "client/basic_port_allocator.h",
+ ]
+ deps = [
+ ":basic_packet_socket_factory",
+ ":port",
+ ":port_allocator",
+ ":relay_port_factory_interface",
+ ":rtc_p2p",
+ ":stun_port",
+ ":tcp_port",
+ ":turn_port",
+ ":turn_port_factory",
+ ":udp_port",
+ "../api:field_trials_view",
+ "../api:turn_customizer",
"../api/task_queue:pending_task_safety_flag",
+ "../api/transport:field_trial_based_config",
+ "../api/units:time_delta",
+ "../rtc_base:checks",
+ "../rtc_base:event_tracer",
+ "../rtc_base:logging",
+ "../rtc_base:macromagic",
+ "../rtc_base:network",
+ "../rtc_base:network_constants",
+ "../rtc_base:ssl",
+ "../rtc_base:stringutils",
+ "../rtc_base:threading",
+ "../rtc_base/experiments:field_trial_parser",
+ "../rtc_base/memory:always_valid_pointer",
+ "../rtc_base/network:received_packet",
+ "../rtc_base/system:rtc_export",
+ "../system_wrappers:metrics",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ ]
+}
+
+rtc_source_set("candidate_pair_interface") {
+ sources = [ "base/candidate_pair_interface.h" ]
+}
+
+rtc_library("connection") {
+ sources = [
+ "base/connection.cc",
+ "base/connection.h",
+ ]
+ deps = [
+ ":candidate_pair_interface",
+ ":connection_info",
+ ":ice_credentials_iterator",
+ ":p2p_constants",
+ ":p2p_transport_channel_ice_field_trials",
+ ":port_interface",
+ ":stun_request",
+ ":transport_description",
+ "../api:array_view",
+ "../api:candidate",
+ "../api:field_trials_view",
+ "../api:packet_socket_factory",
+ "../api:rtc_error",
+ "../api:sequence_checker",
+ "../api/task_queue",
+ "../api/transport:enums",
+ "../api/transport:field_trial_based_config",
+ "../api/transport:stun_types",
+ "../api/units:time_delta",
+ "../api/units:timestamp",
+ "../logging:ice_log",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:byte_buffer",
+ "../rtc_base:callback_list",
+ "../rtc_base:checks",
+ "../rtc_base:crc32",
+ "../rtc_base:dscp",
+ "../rtc_base:event_tracer",
+ "../rtc_base:ip_address",
+ "../rtc_base:logging",
+ "../rtc_base:macromagic",
+ "../rtc_base:mdns_responder_interface",
+ "../rtc_base:net_helper",
+ "../rtc_base:network",
+ "../rtc_base:network_constants",
+ "../rtc_base:proxy_info",
+ "../rtc_base:rate_tracker",
+ "../rtc_base:rtc_numerics",
"../rtc_base:safe_minmax",
+ "../rtc_base:socket",
+ "../rtc_base:socket_address",
+ "../rtc_base:ssl",
+ "../rtc_base:stringutils",
+ "../rtc_base:threading",
+ "../rtc_base:timeutils",
"../rtc_base:weak_ptr",
+ "../rtc_base/memory:always_valid_pointer",
"../rtc_base/network:received_packet",
"../rtc_base/network:sent_packet",
- "../rtc_base/synchronization:mutex",
"../rtc_base/system:rtc_export",
"../rtc_base/third_party/base64",
"../rtc_base/third_party/sigslot",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/base:core_headers",
+ "//third_party/abseil-cpp/absl/functional:any_invocable",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("connection_info") {
+ sources = [
+ "base/connection_info.cc",
+ "base/connection_info.h",
+ ]
+ deps = [
+ "../api:candidate",
+ "../api/units:timestamp",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
+rtc_library("default_ice_transport_factory") {
+ sources = [
+ "base/default_ice_transport_factory.cc",
+ "base/default_ice_transport_factory.h",
+ ]
+ deps = [
+ ":basic_ice_controller",
+ ":ice_controller_factory_interface",
+ ":p2p_transport_channel",
+ "../api:ice_transport_interface",
+ "../api:make_ref_counted",
+ "../rtc_base:threading",
+ ]
+}
+
+rtc_library("dtls_transport") {
+ sources = [
+ "base/dtls_transport.cc",
+ "base/dtls_transport.h",
+ ]
+ deps = [
+ ":dtls_transport_internal",
+ ":ice_transport_internal",
+ ":packet_transport_internal",
+ "../api:array_view",
+ "../api:dtls_transport_interface",
+ "../api:sequence_checker",
+ "../api/crypto:options",
+ "../api/rtc_event_log",
+ "../logging:ice_log",
+ "../rtc_base:buffer",
+ "../rtc_base:buffer_queue",
+ "../rtc_base:checks",
+ "../rtc_base:dscp",
+ "../rtc_base:logging",
+ "../rtc_base:ssl",
+ "../rtc_base:stream",
+ "../rtc_base:stringutils",
+ "../rtc_base:threading",
+ "../rtc_base/system:no_unique_address",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ ]
+}
+
+rtc_source_set("dtls_transport_factory") {
+ sources = [ "base/dtls_transport_factory.h" ]
+ deps = [
+ ":dtls_transport_internal",
+ ":ice_transport_internal",
+ ]
+}
+
+rtc_library("dtls_transport_internal") {
+ sources = [
+ "base/dtls_transport_internal.cc",
+ "base/dtls_transport_internal.h",
+ ]
+ deps = [
+ ":ice_transport_internal",
+ ":packet_transport_internal",
+ "../api:dtls_transport_interface",
+ "../api:scoped_refptr",
+ "../api/crypto:options",
+ "../rtc_base:callback_list",
+ "../rtc_base:ssl",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/base:core_headers",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ ]
+}
+
+rtc_source_set("ice_agent_interface") {
+ sources = [ "base/ice_agent_interface.h" ]
+ deps = [
+ ":connection",
+ ":ice_switch_reason",
+ "../api:array_view",
+ ]
+}
+
+rtc_library("ice_controller_interface") {
+ sources = [
+ "base/ice_controller_interface.cc",
+ "base/ice_controller_interface.h",
+ ]
+ deps = [
+ ":connection",
+ ":ice_switch_reason",
+ ":ice_transport_internal",
+ "../rtc_base:checks",
+ "../rtc_base/system:rtc_export",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
+rtc_source_set("ice_controller_factory_interface") {
+ sources = [ "base/ice_controller_factory_interface.h" ]
+ deps = [
+ ":ice_controller_interface",
+ ":ice_transport_internal",
+ ]
+}
+
+rtc_library("ice_credentials_iterator") {
+ sources = [
+ "base/ice_credentials_iterator.cc",
+ "base/ice_credentials_iterator.h",
+ ]
+ deps = [
+ ":p2p_constants",
+ ":transport_description",
+ "../rtc_base:ssl",
+ ]
+}
+
+rtc_library("ice_switch_reason") {
+ sources = [
+ "base/ice_switch_reason.cc",
+ "base/ice_switch_reason.h",
+ ]
+ deps = [ "../rtc_base/system:rtc_export" ]
+}
+
+rtc_library("ice_transport_internal") {
+ sources = [
+ "base/ice_transport_internal.cc",
+ "base/ice_transport_internal.h",
+ ]
+ deps = [
+ ":connection",
+ ":p2p_constants",
+ ":packet_transport_internal",
+ ":port",
+ ":stun_dictionary",
+ ":transport_description",
+ "../api:candidate",
+ "../api:rtc_error",
+ "../api/transport:enums",
+ "../rtc_base:network_constants",
+ "../rtc_base:timeutils",
+ "../rtc_base/system:rtc_export",
+ "../rtc_base/third_party/sigslot",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("p2p_constants") {
+ sources = [
+ "base/p2p_constants.cc",
+ "base/p2p_constants.h",
+ ]
+ deps = [ "../rtc_base/system:rtc_export" ]
+}
+
+rtc_library("p2p_transport_channel") {
+ sources = [
+ "base/p2p_transport_channel.cc",
+ "base/p2p_transport_channel.h",
+ ]
+ deps = [
+ ":active_ice_controller_factory_interface",
+ ":basic_ice_controller",
+ ":candidate_pair_interface",
+ ":connection",
+ ":connection_info",
+ ":ice_agent_interface",
+ ":ice_controller_factory_interface",
+ ":ice_controller_interface",
+ ":ice_switch_reason",
+ ":ice_transport_internal",
+ ":p2p_constants",
+ ":p2p_transport_channel_ice_field_trials",
+ ":port",
+ ":port_allocator",
+ ":port_interface",
+ ":regathering_controller",
+ ":stun_dictionary",
+ ":transport_description",
+ ":wrapping_active_ice_controller",
+ "../api:array_view",
+ "../api:async_dns_resolver",
+ "../api:candidate",
+ "../api:field_trials_view",
+ "../api:ice_transport_interface",
+ "../api:rtc_error",
+ "../api:sequence_checker",
+ "../api/task_queue:pending_task_safety_flag",
+ "../api/transport:enums",
+ "../api/transport:stun_types",
+ "../api/units:time_delta",
+ "../logging:ice_log",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:checks",
+ "../rtc_base:crc32",
+ "../rtc_base:dscp",
+ "../rtc_base:event_tracer",
+ "../rtc_base:ip_address",
+ "../rtc_base:logging",
+ "../rtc_base:macromagic",
+ "../rtc_base:net_helper",
+ "../rtc_base:network",
+ "../rtc_base:network_constants",
+ "../rtc_base:network_route",
+ "../rtc_base:socket",
+ "../rtc_base:socket_address",
+ "../rtc_base:stringutils",
+ "../rtc_base:threading",
+ "../rtc_base:timeutils",
+ "../rtc_base/experiments:field_trial_parser",
+ "../rtc_base/network:sent_packet",
+ "../rtc_base/system:rtc_export",
"../system_wrappers:metrics",
]
absl_deps = [
@@ -172,17 +611,406 @@ rtc_library("rtc_p2p") {
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_source_set("p2p_transport_channel_ice_field_trials") {
+ sources = [ "base/p2p_transport_channel_ice_field_trials.h" ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
+rtc_library("packet_transport_internal") {
+ sources = [
+ "base/packet_transport_internal.cc",
+ "base/packet_transport_internal.h",
+ ]
+ deps = [
+ ":connection",
+ ":port",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:network_route",
+ "../rtc_base:socket",
+ "../rtc_base/system:rtc_export",
+ "../rtc_base/third_party/sigslot",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
+rtc_library("port") {
+ sources = [
+ "base/port.cc",
+ "base/port.h",
+ ]
+ deps = [
+ ":candidate_pair_interface",
+ ":connection",
+ ":connection_info",
+ ":p2p_constants",
+ ":port_interface",
+ ":stun_request",
+ ":transport_description",
+ "../api:array_view",
+ "../api:candidate",
+ "../api:field_trials_view",
+ "../api:packet_socket_factory",
+ "../api:rtc_error",
+ "../api:sequence_checker",
+ "../api/task_queue",
+ "../api/transport:field_trial_based_config",
+ "../api/transport:stun_types",
+ "../api/units:time_delta",
+ "../logging:ice_log",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:byte_buffer",
+ "../rtc_base:callback_list",
+ "../rtc_base:checks",
+ "../rtc_base:crc32",
+ "../rtc_base:dscp",
+ "../rtc_base:event_tracer",
+ "../rtc_base:ip_address",
+ "../rtc_base:logging",
+ "../rtc_base:macromagic",
+ "../rtc_base:mdns_responder_interface",
+ "../rtc_base:net_helper",
+ "../rtc_base:network",
+ "../rtc_base:proxy_info",
+ "../rtc_base:rate_tracker",
+ "../rtc_base:socket_address",
+ "../rtc_base:ssl",
+ "../rtc_base:stringutils",
+ "../rtc_base:timeutils",
+ "../rtc_base:weak_ptr",
+ "../rtc_base/memory:always_valid_pointer",
+ "../rtc_base/network:received_packet",
+ "../rtc_base/network:sent_packet",
+ "../rtc_base/system:rtc_export",
+ "../rtc_base/third_party/sigslot",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/base:core_headers",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/strings:string_view",
"//third_party/abseil-cpp/absl/types:optional",
]
}
+rtc_library("port_allocator") {
+ sources = [
+ "base/port_allocator.cc",
+ "base/port_allocator.h",
+ ]
+ deps = [
+ ":connection",
+ ":ice_credentials_iterator",
+ ":port",
+ ":port_interface",
+ ":transport_description",
+ "../api:candidate",
+ "../api:sequence_checker",
+ "../api/transport:enums",
+ "../rtc_base:checks",
+ "../rtc_base:network",
+ "../rtc_base:proxy_info",
+ "../rtc_base:socket_address",
+ "../rtc_base:ssl",
+ "../rtc_base:threading",
+ "../rtc_base/system:rtc_export",
+ "../rtc_base/third_party/sigslot",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("port_interface") {
+ sources = [
+ "base/port_interface.cc",
+ "base/port_interface.h",
+ ]
+ deps = [
+ ":transport_description",
+ "../api:candidate",
+ "../api:packet_socket_factory",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:callback_list",
+ "../rtc_base:proxy_info",
+ "../rtc_base:socket_address",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("pseudo_tcp") {
+ sources = [
+ "base/pseudo_tcp.cc",
+ "base/pseudo_tcp.h",
+ ]
+ deps = [
+ "../rtc_base:byte_buffer",
+ "../rtc_base:byte_order",
+ "../rtc_base:checks",
+ "../rtc_base:logging",
+ "../rtc_base:safe_minmax",
+ "../rtc_base:socket",
+ "../rtc_base:timeutils",
+ "../rtc_base/synchronization:mutex",
+ "../rtc_base/system:rtc_export",
+ ]
+}
+
+rtc_library("regathering_controller") {
+ sources = [
+ "base/regathering_controller.cc",
+ "base/regathering_controller.h",
+ ]
+ deps = [
+ ":connection",
+ ":ice_transport_internal",
+ ":port_allocator",
+ "../api/task_queue:pending_task_safety_flag",
+ "../api/units:time_delta",
+ "../rtc_base:threading",
+ ]
+}
+
+rtc_library("stun_dictionary") {
+ sources = [
+ "base/stun_dictionary.cc",
+ "base/stun_dictionary.h",
+ ]
+ deps = [
+ "../api:rtc_error",
+ "../api/transport:stun_types",
+ "../rtc_base:logging",
+ ]
+}
+
+rtc_library("stun_port") {
+ sources = [
+ "base/stun_port.cc",
+ "base/stun_port.h",
+ ]
+ deps = [
+ ":connection",
+ ":p2p_constants",
+ ":port",
+ ":port_allocator",
+ ":stun_request",
+ "../api/task_queue:pending_task_safety_flag",
+ "../api/transport:stun_types",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:checks",
+ "../rtc_base:ip_address",
+ "../rtc_base:logging",
+ "../rtc_base:ssl",
+ "../rtc_base:stringutils",
+ "../rtc_base/experiments:field_trial_parser",
+ "../rtc_base/network:received_packet",
+ "../rtc_base/system:rtc_export",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ ]
+}
+
+rtc_library("stun_request") {
+ sources = [
+ "base/stun_request.cc",
+ "base/stun_request.h",
+ ]
+ deps = [
+ "../api/task_queue",
+ "../api/task_queue:pending_task_safety_flag",
+ "../api/transport:stun_types",
+ "../api/units:time_delta",
+ "../rtc_base:checks",
+ "../rtc_base:logging",
+ "../rtc_base:ssl",
+ "../rtc_base:stringutils",
+ "../rtc_base:timeutils",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+}
+
+rtc_library("tcp_port") {
+ sources = [
+ "base/tcp_port.cc",
+ "base/tcp_port.h",
+ ]
+ deps = [
+ ":connection",
+ ":p2p_constants",
+ ":port",
+ "../api/task_queue:pending_task_safety_flag",
+ "../api/units:time_delta",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:checks",
+ "../rtc_base:ip_address",
+ "../rtc_base:logging",
+ "../rtc_base:net_helper",
+ "../rtc_base:rate_tracker",
+ "../rtc_base:threading",
+ "../rtc_base/containers:flat_map",
+ "../rtc_base/network:received_packet",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ ]
+}
+
+rtc_library("transport_description") {
+ sources = [
+ "base/transport_description.cc",
+ "base/transport_description.h",
+ ]
+ deps = [
+ ":p2p_constants",
+ "../api:rtc_error",
+ "../rtc_base:logging",
+ "../rtc_base:macromagic",
+ "../rtc_base:ssl",
+ "../rtc_base:stringutils",
+ "../rtc_base/system:rtc_export",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("transport_description_factory") {
+ sources = [
+ "base/transport_description_factory.cc",
+ "base/transport_description_factory.h",
+ ]
+ deps = [
+ ":ice_credentials_iterator",
+ ":transport_description",
+ "../api:field_trials_view",
+ "../rtc_base:logging",
+ "../rtc_base:ssl",
+ ]
+}
+
+rtc_source_set("transport_info") {
+ sources = [ "base/transport_info.h" ]
+ deps = [
+ ":p2p_constants",
+ ":rtc_p2p",
+ ":transport_description",
+ "../api:candidate",
+ "../rtc_base:ssl",
+ ]
+}
+
+rtc_source_set("udp_port") {
+ sources = [ "base/udp_port.h" ]
+ deps = [ ":stun_port" ]
+}
+
+rtc_library("turn_port") {
+ sources = [
+ "base/turn_port.cc",
+ "base/turn_port.h",
+ ]
+ deps = [
+ ":connection",
+ ":p2p_constants",
+ ":port",
+ ":port_allocator",
+ ":relay_port_factory_interface",
+ "../api:async_dns_resolver",
+ "../api:turn_customizer",
+ "../api/task_queue",
+ "../api/task_queue:pending_task_safety_flag",
+ "../api/transport:stun_types",
+ "../rtc_base:async_packet_socket",
+ "../rtc_base:byte_order",
+ "../rtc_base:checks",
+ "../rtc_base:logging",
+ "../rtc_base:net_helpers",
+ "../rtc_base:socket_address",
+ "../rtc_base:ssl",
+ "../rtc_base:stringutils",
+ "../rtc_base/experiments:field_trial_parser",
+ "../rtc_base/network:received_packet",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("turn_port_factory") {
+ sources = [
+ "client/turn_port_factory.cc",
+ "client/turn_port_factory.h",
+ ]
+ deps = [
+ ":port",
+ ":port_allocator",
+ ":relay_port_factory_interface",
+ ":rtc_p2p",
+ ":turn_port",
+ "../rtc_base:async_packet_socket",
+ ]
+}
+
+rtc_source_set("relay_port_factory_interface") {
+ sources = [ "client/relay_port_factory_interface.h" ]
+ deps = [
+ ":port_interface",
+ "../rtc_base:refcount",
+ ]
+}
+
+rtc_library("wrapping_active_ice_controller") {
+ sources = [
+ "base/wrapping_active_ice_controller.cc",
+ "base/wrapping_active_ice_controller.h",
+ ]
+ deps = [
+ ":active_ice_controller_interface",
+ ":basic_ice_controller",
+ ":connection",
+ ":ice_agent_interface",
+ ":ice_controller_factory_interface",
+ ":ice_controller_interface",
+ ":ice_switch_reason",
+ ":ice_transport_internal",
+ ":transport_description",
+ "../api:sequence_checker",
+ "../api/task_queue:pending_task_safety_flag",
+ "../api/units:time_delta",
+ "../rtc_base:logging",
+ "../rtc_base:macromagic",
+ "../rtc_base:threading",
+ "../rtc_base:timeutils",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
if (rtc_include_tests) {
rtc_library("fake_ice_transport") {
testonly = true
visibility = [ "*" ]
sources = [ "base/fake_ice_transport.h" ]
deps = [
- ":rtc_p2p",
+ ":ice_transport_internal",
"../api:ice_transport_interface",
"../api:libjingle_peerconnection_api",
"../api/task_queue:pending_task_safety_flag",
@@ -202,7 +1030,10 @@ if (rtc_include_tests) {
visibility = [ "*" ]
sources = [ "base/fake_port_allocator.h" ]
deps = [
- ":rtc_p2p",
+ ":basic_packet_socket_factory",
+ ":connection",
+ ":port_allocator",
+ ":udp_port",
"../rtc_base:net_helpers",
"../rtc_base:net_test_helpers",
"../rtc_base:task_queue_for_test",
@@ -228,10 +1059,21 @@ if (rtc_include_tests) {
"base/test_turn_server.h",
]
deps = [
+ ":active_ice_controller_factory_interface",
+ ":active_ice_controller_interface",
+ ":basic_packet_socket_factory",
+ ":connection",
+ ":dtls_transport_internal",
":fake_ice_transport",
":fake_port_allocator",
+ ":ice_agent_interface",
+ ":ice_controller_factory_interface",
+ ":ice_controller_interface",
+ ":ice_switch_reason",
+ ":ice_transport_internal",
":p2p_server_utils",
- ":rtc_p2p",
+ ":packet_transport_internal",
+ ":transport_description",
"../api:dtls_transport_interface",
"../api:libjingle_peerconnection_api",
"../api:mock_async_dns_resolver",
@@ -284,11 +1126,38 @@ if (rtc_include_tests) {
"client/basic_port_allocator_unittest.cc",
]
deps = [
+ ":active_ice_controller_factory_interface",
+ ":active_ice_controller_interface",
+ ":async_stun_tcp_socket",
+ ":basic_ice_controller",
+ ":basic_packet_socket_factory",
+ ":basic_port_allocator",
+ ":connection",
+ ":dtls_transport",
":fake_ice_transport",
":fake_port_allocator",
+ ":ice_credentials_iterator",
+ ":ice_transport_internal",
+ ":p2p_constants",
":p2p_server_utils",
":p2p_test_utils",
+ ":p2p_transport_channel",
+ ":packet_transport_internal",
+ ":port",
+ ":port_allocator",
+ ":port_interface",
+ ":pseudo_tcp",
+ ":regathering_controller",
+ ":relay_port_factory_interface",
":rtc_p2p",
+ ":stun_dictionary",
+ ":stun_port",
+ ":stun_request",
+ ":tcp_port",
+ ":transport_description",
+ ":transport_description_factory",
+ ":turn_port",
+ ":wrapping_active_ice_controller",
"../api:array_view",
"../api:candidate",
"../api:dtls_transport_interface",
@@ -355,7 +1224,8 @@ rtc_library("p2p_server_utils") {
"base/turn_server.h",
]
deps = [
- ":rtc_p2p",
+ ":async_stun_tcp_socket",
+ ":port_interface",
"../api:array_view",
"../api:packet_socket_factory",
"../api:sequence_checker",
@@ -391,7 +1261,6 @@ rtc_library("libstunprober") {
]
deps = [
- ":rtc_p2p",
"../api:array_view",
"../api:async_dns_resolver",
"../api:packet_socket_factory",
@@ -420,9 +1289,9 @@ if (rtc_include_tests) {
sources = [ "stunprober/stun_prober_unittest.cc" ]
deps = [
+ ":basic_packet_socket_factory",
":libstunprober",
":p2p_test_utils",
- ":rtc_p2p",
"../rtc_base:checks",
"../rtc_base:gunit_helpers",
"../rtc_base:ip_address",
diff --git a/third_party/libwebrtc/p2p/base/basic_ice_controller.cc b/third_party/libwebrtc/p2p/base/basic_ice_controller.cc
index 182845cdd7..f5b3eca3a4 100644
--- a/third_party/libwebrtc/p2p/base/basic_ice_controller.cc
+++ b/third_party/libwebrtc/p2p/base/basic_ice_controller.cc
@@ -16,8 +16,8 @@ namespace {
const int kMinImprovement = 10;
bool IsRelayRelay(const cricket::Connection* conn) {
- return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE &&
- conn->remote_candidate().type() == cricket::RELAY_PORT_TYPE;
+ return conn->local_candidate().is_relay() &&
+ conn->remote_candidate().is_relay();
}
bool IsUdp(const cricket::Connection* conn) {
diff --git a/third_party/libwebrtc/p2p/base/basic_ice_controller.h b/third_party/libwebrtc/p2p/base/basic_ice_controller.h
index 724609d2d7..f9f4d45c7a 100644
--- a/third_party/libwebrtc/p2p/base/basic_ice_controller.h
+++ b/third_party/libwebrtc/p2p/base/basic_ice_controller.h
@@ -19,7 +19,6 @@
#include "p2p/base/ice_controller_factory_interface.h"
#include "p2p/base/ice_controller_interface.h"
-#include "p2p/base/p2p_transport_channel.h"
namespace cricket {
diff --git a/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc b/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc
index 6a811af71a..816d964360 100644
--- a/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc
+++ b/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc
@@ -119,11 +119,7 @@ AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
<< socket->GetError();
}
- // If using a proxy, wrap the socket in a proxy socket.
- if (proxy_info.type == PROXY_SOCKS5) {
- socket = new AsyncSocksProxySocket(
- socket, proxy_info.address, proxy_info.username, proxy_info.password);
- } else if (proxy_info.type == PROXY_HTTPS) {
+ if (proxy_info.type == PROXY_HTTPS) {
socket =
new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address,
proxy_info.username, proxy_info.password);
diff --git a/third_party/libwebrtc/p2p/base/candidate_pair_interface.h b/third_party/libwebrtc/p2p/base/candidate_pair_interface.h
index 2b68fd7ea9..a04ab130cf 100644
--- a/third_party/libwebrtc/p2p/base/candidate_pair_interface.h
+++ b/third_party/libwebrtc/p2p/base/candidate_pair_interface.h
@@ -23,6 +23,18 @@ class CandidatePairInterface {
virtual const Candidate& remote_candidate() const = 0;
};
+// Specific implementation of the interface, suitable for being a
+// data member of other structs.
+struct CandidatePair final : public CandidatePairInterface {
+ ~CandidatePair() override = default;
+
+ const Candidate& local_candidate() const override { return local; }
+ const Candidate& remote_candidate() const override { return remote; }
+
+ Candidate local;
+ Candidate remote;
+};
+
} // namespace cricket
#endif // P2P_BASE_CANDIDATE_PAIR_INTERFACE_H_
diff --git a/third_party/libwebrtc/p2p/base/connection.cc b/third_party/libwebrtc/p2p/base/connection.cc
index bf07dec607..93a9a3f791 100644
--- a/third_party/libwebrtc/p2p/base/connection.cc
+++ b/third_party/libwebrtc/p2p/base/connection.cc
@@ -19,25 +19,26 @@
#include <vector>
#include "absl/algorithm/container.h"
-#include "absl/strings/escaping.h"
-#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/units/timestamp.h"
-#include "p2p/base/port_allocator.h"
+#include "p2p/base/p2p_constants.h"
+#include "rtc_base/byte_buffer.h"
#include "rtc_base/checks.h"
-#include "rtc_base/crc32.h"
#include "rtc_base/helpers.h"
#include "rtc_base/logging.h"
-#include "rtc_base/mdns_responder_interface.h"
-#include "rtc_base/message_digest.h"
+#include "rtc_base/net_helper.h"
#include "rtc_base/network.h"
+#include "rtc_base/network/sent_packet.h"
+#include "rtc_base/network_constants.h"
#include "rtc_base/numerics/safe_minmax.h"
+#include "rtc_base/socket.h"
+#include "rtc_base/socket_address.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"
-#include "rtc_base/third_party/base64/base64.h"
+#include "rtc_base/time_utils.h"
namespace cricket {
namespace {
@@ -74,17 +75,16 @@ inline bool TooLongWithoutResponse(
// Helper methods for converting string values of log description fields to
// enum.
-webrtc::IceCandidateType GetCandidateTypeByString(absl::string_view type) {
- if (type == LOCAL_PORT_TYPE) {
- return webrtc::IceCandidateType::kLocal;
- } else if (type == STUN_PORT_TYPE) {
- return webrtc::IceCandidateType::kStun;
- } else if (type == PRFLX_PORT_TYPE) {
+webrtc::IceCandidateType GetRtcEventLogCandidateType(const Candidate& c) {
+ if (c.is_local()) {
+ return webrtc::IceCandidateType::kHost;
+ } else if (c.is_stun()) {
+ return webrtc::IceCandidateType::kSrflx;
+ } else if (c.is_prflx()) {
return webrtc::IceCandidateType::kPrflx;
- } else if (type == RELAY_PORT_TYPE) {
- return webrtc::IceCandidateType::kRelay;
}
- return webrtc::IceCandidateType::kUnknown;
+ RTC_DCHECK(c.is_relay());
+ return webrtc::IceCandidateType::kRelay;
}
webrtc::IceCandidatePairProtocol GetProtocolByString(
@@ -213,7 +213,7 @@ int Connection::ConnectionRequest::resend_delay() {
return CONNECTION_RESPONSE_TIMEOUT;
}
-Connection::Connection(rtc::WeakPtr<Port> port,
+Connection::Connection(rtc::WeakPtr<PortInterface> port,
size_t index,
const Candidate& remote_candidate)
: network_thread_(port->thread()),
@@ -1330,11 +1330,11 @@ std::string Connection::ToString() const {
const Candidate& local = local_candidate();
const Candidate& remote = remote_candidate();
ss << local.id() << ":" << local.component() << ":" << local.generation()
- << ":" << local.type() << ":" << local.protocol() << ":"
+ << ":" << local.type_name() << ":" << local.protocol() << ":"
<< local.address().ToSensitiveString() << "->" << remote.id() << ":"
- << remote.component() << ":" << remote.priority() << ":" << remote.type()
- << ":" << remote.protocol() << ":" << remote.address().ToSensitiveString()
- << "|";
+ << remote.component() << ":" << remote.priority() << ":"
+ << remote.type_name() << ":" << remote.protocol() << ":"
+ << remote.address().ToSensitiveString() << "|";
ss << CONNECT_STATE_ABBREV[connected_] << RECEIVE_STATE_ABBREV[receiving_]
<< WRITE_STATE_ABBREV[write_state_] << ICESTATE[static_cast<int>(state_)]
@@ -1365,16 +1365,13 @@ const webrtc::IceCandidatePairDescription& Connection::ToLogDescription() {
const Candidate& local = local_candidate();
const Candidate& remote = remote_candidate();
const rtc::Network* network = port()->Network();
- log_description_ = webrtc::IceCandidatePairDescription();
- log_description_->local_candidate_type =
- GetCandidateTypeByString(local.type());
+ log_description_ = webrtc::IceCandidatePairDescription(
+ GetRtcEventLogCandidateType(local), GetRtcEventLogCandidateType(remote));
log_description_->local_relay_protocol =
GetProtocolByString(local.relay_protocol());
log_description_->local_network_type = ConvertNetworkType(network->type());
log_description_->local_address_family =
GetAddressFamilyByInt(local.address().family());
- log_description_->remote_candidate_type =
- GetCandidateTypeByString(remote.type());
log_description_->remote_address_family =
GetAddressFamilyByInt(remote.address().family());
log_description_->candidate_pair_protocol =
@@ -1692,10 +1689,9 @@ void Connection::MaybeUpdateLocalCandidate(StunRequest* request,
return;
}
const uint32_t priority = priority_attr->value();
- std::string id = rtc::CreateRandomString(8);
// Create a peer-reflexive candidate based on the local candidate.
- local_candidate_.set_id(id);
+ local_candidate_.generate_id();
local_candidate_.set_type(PRFLX_PORT_TYPE);
// Set the related address and foundation attributes before changing the
// address.
@@ -1784,7 +1780,7 @@ void Connection::ForgetLearnedState() {
pings_since_last_response_.clear();
}
-ProxyConnection::ProxyConnection(rtc::WeakPtr<Port> port,
+ProxyConnection::ProxyConnection(rtc::WeakPtr<PortInterface> port,
size_t index,
const Candidate& remote_candidate)
: Connection(std::move(port), index, remote_candidate) {}
diff --git a/third_party/libwebrtc/p2p/base/connection.h b/third_party/libwebrtc/p2p/base/connection.h
index cf54dc800f..583e62e264 100644
--- a/third_party/libwebrtc/p2p/base/connection.h
+++ b/third_party/libwebrtc/p2p/base/connection.h
@@ -11,19 +11,31 @@
#ifndef P2P_BASE_CONNECTION_H_
#define P2P_BASE_CONNECTION_H_
+#include <stddef.h>
+
+#include <cstdint>
+#include <functional>
#include <memory>
#include <string>
+#include <type_traits>
#include <utility>
#include <vector>
+#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/candidate.h"
+#include "api/rtc_error.h"
+#include "api/sequence_checker.h"
+#include "api/task_queue/task_queue_base.h"
#include "api/transport/stun.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
#include "logging/rtc_event_log/ice_logger.h"
#include "p2p/base/candidate_pair_interface.h"
#include "p2p/base/connection_info.h"
#include "p2p/base/p2p_transport_channel_ice_field_trials.h"
+#include "p2p/base/port_interface.h"
#include "p2p/base/stun_request.h"
#include "p2p/base/transport_description.h"
#include "rtc_base/async_packet_socket.h"
@@ -32,6 +44,8 @@
#include "rtc_base/numerics/event_based_exponential_moving_average.h"
#include "rtc_base/rate_tracker.h"
#include "rtc_base/system/rtc_export.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
+#include "rtc_base/thread_annotations.h"
#include "rtc_base/weak_ptr.h"
namespace cricket {
@@ -40,23 +54,9 @@ namespace cricket {
// adding other flavors in the future.
constexpr int kGoogPingVersion = 1;
-// Connection and Port has circular dependencies.
-// So we use forward declaration rather than include.
-class Port;
-
// Forward declaration so that a ConnectionRequest can contain a Connection.
class Connection;
-struct CandidatePair final : public CandidatePairInterface {
- ~CandidatePair() override = default;
-
- const Candidate& local_candidate() const override { return local; }
- const Candidate& remote_candidate() const override { return remote; }
-
- Candidate local;
- Candidate remote;
-};
-
// Represents a communication link between a port on the local client and a
// port on the remote client.
class RTC_EXPORT Connection : public CandidatePairInterface {
@@ -102,7 +102,7 @@ class RTC_EXPORT Connection : public CandidatePairInterface {
bool writable() const;
bool receiving() const;
- const Port* port() const {
+ const PortInterface* port() const {
RTC_DCHECK_RUN_ON(network_thread_);
return port_.get();
}
@@ -326,8 +326,8 @@ class RTC_EXPORT Connection : public CandidatePairInterface {
void SendResponseMessage(const StunMessage& response);
// An accessor for unit tests.
- Port* PortForTest() { return port_.get(); }
- const Port* PortForTest() const { return port_.get(); }
+ PortInterface* PortForTest() { return port_.get(); }
+ const PortInterface* PortForTest() const { return port_.get(); }
std::unique_ptr<IceMessage> BuildPingRequestForTest() {
RTC_DCHECK_RUN_ON(network_thread_);
@@ -364,7 +364,9 @@ class RTC_EXPORT Connection : public CandidatePairInterface {
class ConnectionRequest;
// Constructs a new connection to the given remote port.
- Connection(rtc::WeakPtr<Port> port, size_t index, const Candidate& candidate);
+ Connection(rtc::WeakPtr<PortInterface> port,
+ size_t index,
+ const Candidate& candidate);
// Called back when StunRequestManager has a stun packet to send
void OnSendStunPacket(const void* data, size_t size, StunRequest* req);
@@ -393,7 +395,7 @@ class RTC_EXPORT Connection : public CandidatePairInterface {
void set_connected(bool value);
// The local port where this connection sends and receives packets.
- Port* port() { return port_.get(); }
+ PortInterface* port() { return port_.get(); }
// NOTE: A pointer to the network thread is held by `port_` so in theory we
// shouldn't need to hold on to this pointer here, but rather defer to
@@ -402,7 +404,7 @@ class RTC_EXPORT Connection : public CandidatePairInterface {
// TODO(tommi): This ^^^ should be fixed.
webrtc::TaskQueueBase* const network_thread_;
const uint32_t id_;
- rtc::WeakPtr<Port> port_;
+ rtc::WeakPtr<PortInterface> port_;
Candidate local_candidate_ RTC_GUARDED_BY(network_thread_);
Candidate remote_candidate_;
@@ -515,7 +517,7 @@ class RTC_EXPORT Connection : public CandidatePairInterface {
// ProxyConnection defers all the interesting work to the port.
class ProxyConnection : public Connection {
public:
- ProxyConnection(rtc::WeakPtr<Port> port,
+ ProxyConnection(rtc::WeakPtr<PortInterface> port,
size_t index,
const Candidate& remote_candidate);
diff --git a/third_party/libwebrtc/p2p/base/fake_port_allocator.h b/third_party/libwebrtc/p2p/base/fake_port_allocator.h
index 0bb7dd0139..a51a7ca4ee 100644
--- a/third_party/libwebrtc/p2p/base/fake_port_allocator.h
+++ b/third_party/libwebrtc/p2p/base/fake_port_allocator.h
@@ -93,6 +93,7 @@ class FakePortAllocatorSession : public PortAllocatorSession {
ice_ufrag,
ice_pwd,
allocator->flags()),
+ allocator_(allocator),
network_thread_(network_thread),
factory_(factory),
ipv4_network_("network",
@@ -110,7 +111,6 @@ class FakePortAllocatorSession : public PortAllocatorSession {
field_trials_(field_trials) {
ipv4_network_.AddIP(rtc::IPAddress(INADDR_LOOPBACK));
ipv6_network_.AddIP(rtc::IPAddress(in6addr_loopback));
- set_ice_tiebreaker(/*kTiebreakerDefault = */ 44444);
}
void SetCandidateFilter(uint32_t filter) override {
@@ -127,7 +127,7 @@ class FakePortAllocatorSession : public PortAllocatorSession {
username(), password(), false,
field_trials_));
RTC_DCHECK(port_);
- port_->SetIceTiebreaker(ice_tiebreaker());
+ port_->SetIceTiebreaker(allocator_->ice_tiebreaker());
port_->SubscribePortDestroyed(
[this](PortInterface* port) { OnPortDestroyed(port); });
AddPort(port_.get());
@@ -199,6 +199,7 @@ class FakePortAllocatorSession : public PortAllocatorSession {
port_.release();
}
+ PortAllocator* allocator_;
rtc::Thread* network_thread_;
rtc::PacketSocketFactory* factory_;
rtc::Network ipv4_network_;
diff --git a/third_party/libwebrtc/p2p/base/p2p_constants.h b/third_party/libwebrtc/p2p/base/p2p_constants.h
index d51ee17a07..c5a2b7058d 100644
--- a/third_party/libwebrtc/p2p/base/p2p_constants.h
+++ b/third_party/libwebrtc/p2p/base/p2p_constants.h
@@ -95,6 +95,8 @@ extern const int CONNECTION_WRITE_TIMEOUT;
// Default value of IceConfig.stun_keepalive_interval;
extern const int STUN_KEEPALIVE_INTERVAL;
+static const int MIN_PINGS_AT_WEAK_PING_INTERVAL = 3;
+
// The following constants are used at the candidate pair level to determine the
// state of a candidate pair.
//
@@ -109,6 +111,19 @@ extern const int CONNECTION_RESPONSE_TIMEOUT;
// it.
extern const int MIN_CONNECTION_LIFETIME;
+// The type preference MUST be an integer from 0 to 126 inclusive.
+// https://datatracker.ietf.org/doc/html/rfc5245#section-4.1.2.1
+enum IcePriorityValue : uint8_t {
+ ICE_TYPE_PREFERENCE_RELAY_TLS = 0,
+ ICE_TYPE_PREFERENCE_RELAY_TCP = 1,
+ ICE_TYPE_PREFERENCE_RELAY_UDP = 2,
+ ICE_TYPE_PREFERENCE_PRFLX_TCP = 80,
+ ICE_TYPE_PREFERENCE_HOST_TCP = 90,
+ ICE_TYPE_PREFERENCE_SRFLX = 100,
+ ICE_TYPE_PREFERENCE_PRFLX = 110,
+ ICE_TYPE_PREFERENCE_HOST = 126
+};
+
} // namespace cricket
#endif // P2P_BASE_P2P_CONSTANTS_H_
diff --git a/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc b/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc
index 35d7f85d69..eb3553b52a 100644
--- a/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc
+++ b/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc
@@ -164,7 +164,7 @@ P2PTransportChannel::P2PTransportChannel(
error_(0),
remote_ice_mode_(ICEMODE_FULL),
ice_role_(ICEROLE_UNKNOWN),
- tiebreaker_(0),
+ ice_tiebreaker_(0),
gathering_state_(kIceGatheringNew),
weak_ping_interval_(GetWeakPingIntervalInFieldTrial(field_trials)),
config_(RECEIVING_TIMEOUT,
@@ -326,7 +326,7 @@ void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) {
return;
}
- tiebreaker_ = tiebreaker;
+ ice_tiebreaker_ = tiebreaker;
}
IceTransportState P2PTransportChannel::GetState() const {
@@ -885,7 +885,6 @@ void P2PTransportChannel::MaybeStartGathering() {
ice_parameters_.ufrag,
ice_parameters_.pwd);
if (pooled_session) {
- pooled_session->set_ice_tiebreaker(tiebreaker_);
AddAllocatorSession(std::move(pooled_session));
PortAllocatorSession* raw_pooled_session =
allocator_sessions_.back().get();
@@ -902,7 +901,6 @@ void P2PTransportChannel::MaybeStartGathering() {
AddAllocatorSession(allocator_->CreateSession(
transport_name(), component(), ice_parameters_.ufrag,
ice_parameters_.pwd));
- allocator_sessions_.back()->set_ice_tiebreaker(tiebreaker_);
allocator_sessions_.back()->StartGettingPorts();
}
}
@@ -930,7 +928,7 @@ void P2PTransportChannel::OnPortReady(PortAllocatorSession* session,
// if one is pending.
port->SetIceRole(ice_role_);
- port->SetIceTiebreaker(tiebreaker_);
+ port->SetIceTiebreaker(ice_tiebreaker_);
ports_.push_back(port);
port->SignalUnknownAddress.connect(this,
&P2PTransportChannel::OnUnknownAddress);
@@ -1418,7 +1416,8 @@ bool P2PTransportChannel::CreateConnection(PortInterface* port,
if ((port->Type() != remote_candidate.type()) &&
(port->Type() == RELAY_PORT_TYPE || remote_candidate.is_relay())) {
RTC_LOG(LS_INFO) << ToString() << ": skip creating connection "
- << port->Type() << " to " << remote_candidate.type();
+ << port->Type() << " to "
+ << remote_candidate.type_name();
return false;
}
}
@@ -1693,7 +1692,7 @@ void P2PTransportChannel::OnStartedPinging() {
regathering_controller_->Start();
}
-bool P2PTransportChannel::IsPortPruned(const Port* port) const {
+bool P2PTransportChannel::IsPortPruned(const PortInterface* port) const {
RTC_DCHECK_RUN_ON(network_thread_);
return !absl::c_linear_search(ports_, port);
}
diff --git a/third_party/libwebrtc/p2p/base/p2p_transport_channel.h b/third_party/libwebrtc/p2p/base/p2p_transport_channel.h
index 47f37c8c67..f7472df38a 100644
--- a/third_party/libwebrtc/p2p/base/p2p_transport_channel.h
+++ b/third_party/libwebrtc/p2p/base/p2p_transport_channel.h
@@ -79,8 +79,6 @@ class RtcEventLog;
namespace cricket {
-static const int MIN_PINGS_AT_WEAK_PING_INTERVAL = 3;
-
bool IceCredentialsChanged(absl::string_view old_ufrag,
absl::string_view old_pwd,
absl::string_view new_ufrag,
@@ -372,7 +370,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal,
}
// Indicates if the given local port has been pruned.
- bool IsPortPruned(const Port* port) const;
+ bool IsPortPruned(const PortInterface* port) const;
// Indicates if the given remote candidate has been pruned.
bool IsRemoteCandidatePruned(const Candidate& cand) const;
@@ -441,7 +439,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal,
RTC_GUARDED_BY(network_thread_);
IceMode remote_ice_mode_ RTC_GUARDED_BY(network_thread_);
IceRole ice_role_ RTC_GUARDED_BY(network_thread_);
- uint64_t tiebreaker_ RTC_GUARDED_BY(network_thread_);
+ uint64_t ice_tiebreaker_ RTC_GUARDED_BY(network_thread_);
IceGatheringState gathering_state_ RTC_GUARDED_BY(network_thread_);
std::unique_ptr<webrtc::BasicRegatheringController> regathering_controller_
RTC_GUARDED_BY(network_thread_);
diff --git a/third_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc b/third_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc
index a0446c7965..b180ab8d2b 100644
--- a/third_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc
+++ b/third_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc
@@ -141,7 +141,6 @@ const cricket::IceParameters kIceParams[4] = {
const uint64_t kLowTiebreaker = 11111;
const uint64_t kHighTiebreaker = 22222;
-const uint64_t kTiebreakerDefault = 44444;
cricket::IceConfig CreateIceConfig(
int receiving_timeout,
@@ -286,14 +285,6 @@ class P2PTransportChannelTestBase : public ::testing::Test,
main_(ss_.get()),
stun_server_(TestStunServer::Create(ss_.get(), kStunAddr, main_)),
turn_server_(&main_, ss_.get(), kTurnUdpIntAddr, kTurnUdpExtAddr),
- socks_server1_(ss_.get(),
- kSocksProxyAddrs[0],
- ss_.get(),
- kSocksProxyAddrs[0]),
- socks_server2_(ss_.get(),
- kSocksProxyAddrs[1],
- ss_.get(),
- kSocksProxyAddrs[1]),
force_relay_(false) {
ep1_.role_ = ICEROLE_CONTROLLING;
ep2_.role_ = ICEROLE_CONTROLLED;
@@ -307,10 +298,6 @@ class P2PTransportChannelTestBase : public ::testing::Test,
&ep2_.network_manager_, socket_factory_.get(), stun_servers,
kTurnUdpIntAddr, rtc::SocketAddress()));
- ep1_.SetIceTiebreaker(kTiebreakerDefault);
- ep1_.allocator_->SetIceTiebreaker(kTiebreakerDefault);
- ep2_.SetIceTiebreaker(kTiebreakerDefault);
- ep2_.allocator_->SetIceTiebreaker(kTiebreakerDefault);
webrtc::metrics::Reset();
}
@@ -330,7 +317,6 @@ class P2PTransportChannelTestBase : public ::testing::Test,
BLOCK_UDP_AND_INCOMING_TCP, // Firewall, UDP in/out and TCP in blocked
BLOCK_ALL_BUT_OUTGOING_HTTP, // Firewall, only TCP out on 80/443
PROXY_HTTPS, // All traffic through HTTPS proxy
- PROXY_SOCKS, // All traffic through SOCKS proxy
NUM_CONFIGS
};
@@ -599,13 +585,13 @@ class P2PTransportChannelTestBase : public ::testing::Test,
return GetEndpoint(endpoint)->SetAllowTcpListen(allow_tcp_listen);
}
- // Return true if the approprite parts of the expected Result, based
+ // Return true if the appropriate parts of the expected Result, based
// on the local and remote candidate of ep1_ch1, match. This can be
// used in an EXPECT_TRUE_WAIT.
bool CheckCandidate1(const Result& expected) {
- const std::string& local_type = LocalCandidate(ep1_ch1())->type();
+ auto local_type = LocalCandidate(ep1_ch1())->type();
const std::string& local_protocol = LocalCandidate(ep1_ch1())->protocol();
- const std::string& remote_type = RemoteCandidate(ep1_ch1())->type();
+ auto remote_type = RemoteCandidate(ep1_ch1())->type();
const std::string& remote_protocol = RemoteCandidate(ep1_ch1())->protocol();
return (local_protocol == expected.controlling_protocol &&
remote_protocol == expected.controlled_protocol &&
@@ -613,7 +599,7 @@ class P2PTransportChannelTestBase : public ::testing::Test,
remote_type == expected.controlled_type);
}
- // EXPECT_EQ on the approprite parts of the expected Result, based
+ // EXPECT_EQ on the appropriate parts of the expected Result, based
// on the local and remote candidate of ep1_ch1. This is like
// CheckCandidate1, except that it will provide more detail about
// what didn't match.
@@ -622,9 +608,9 @@ class P2PTransportChannelTestBase : public ::testing::Test,
return;
}
- const std::string& local_type = LocalCandidate(ep1_ch1())->type();
+ auto local_type = LocalCandidate(ep1_ch1())->type();
const std::string& local_protocol = LocalCandidate(ep1_ch1())->protocol();
- const std::string& remote_type = RemoteCandidate(ep1_ch1())->type();
+ auto remote_type = RemoteCandidate(ep1_ch1())->type();
const std::string& remote_protocol = RemoteCandidate(ep1_ch1())->protocol();
EXPECT_EQ(expected.controlling_type, local_type);
EXPECT_EQ(expected.controlled_type, remote_type);
@@ -632,13 +618,13 @@ class P2PTransportChannelTestBase : public ::testing::Test,
EXPECT_EQ(expected.controlled_protocol, remote_protocol);
}
- // Return true if the approprite parts of the expected Result, based
+ // Return true if the appropriate parts of the expected Result, based
// on the local and remote candidate of ep2_ch1, match. This can be
// used in an EXPECT_TRUE_WAIT.
bool CheckCandidate2(const Result& expected) {
- const std::string& local_type = LocalCandidate(ep2_ch1())->type();
+ auto local_type = LocalCandidate(ep2_ch1())->type();
const std::string& local_protocol = LocalCandidate(ep2_ch1())->protocol();
- const std::string& remote_type = RemoteCandidate(ep2_ch1())->type();
+ auto remote_type = RemoteCandidate(ep2_ch1())->type();
const std::string& remote_protocol = RemoteCandidate(ep2_ch1())->protocol();
return (local_protocol == expected.controlled_protocol &&
remote_protocol == expected.controlling_protocol &&
@@ -646,7 +632,7 @@ class P2PTransportChannelTestBase : public ::testing::Test,
remote_type == expected.controlling_type);
}
- // EXPECT_EQ on the approprite parts of the expected Result, based
+ // EXPECT_EQ on the appropriate parts of the expected Result, based
// on the local and remote candidate of ep2_ch1. This is like
// CheckCandidate2, except that it will provide more detail about
// what didn't match.
@@ -655,9 +641,9 @@ class P2PTransportChannelTestBase : public ::testing::Test,
return;
}
- const std::string& local_type = LocalCandidate(ep2_ch1())->type();
+ auto local_type = LocalCandidate(ep2_ch1())->type();
const std::string& local_protocol = LocalCandidate(ep2_ch1())->protocol();
- const std::string& remote_type = RemoteCandidate(ep2_ch1())->type();
+ auto remote_type = RemoteCandidate(ep2_ch1())->type();
const std::string& remote_protocol = RemoteCandidate(ep2_ch1())->protocol();
EXPECT_EQ(expected.controlled_type, local_type);
EXPECT_EQ(expected.controlling_type, remote_type);
@@ -839,7 +825,7 @@ class P2PTransportChannelTestBase : public ::testing::Test,
// We pass the candidates directly to the other side.
void OnCandidateGathered(IceTransportInternal* ch, const Candidate& c) {
- if (force_relay_ && c.type() != RELAY_PORT_TYPE)
+ if (force_relay_ && !c.is_relay())
return;
if (GetEndpoint(ch)->save_candidates_) {
@@ -1028,8 +1014,6 @@ class P2PTransportChannelTestBase : public ::testing::Test,
PendingTaskSafetyFlag::Create();
TestStunServer::StunServerPtr stun_server_;
TestTurnServer turn_server_;
- rtc::SocksProxyServer socks_server1_;
- rtc::SocksProxyServer socks_server2_;
Endpoint ep1_;
Endpoint ep2_;
RemoteIceParameterSource remote_ice_parameter_source_ = FROM_CANDIDATE;
@@ -1179,7 +1163,6 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase {
case BLOCK_UDP_AND_INCOMING_TCP:
case BLOCK_ALL_BUT_OUTGOING_HTTP:
case PROXY_HTTPS:
- case PROXY_SOCKS:
AddAddress(endpoint, kPublicAddrs[endpoint]);
// Block all UDP
fw()->AddRule(false, rtc::FP_UDP, rtc::FD_ANY, kPublicAddrs[endpoint]);
@@ -1202,13 +1185,6 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase {
fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY,
kPublicAddrs[endpoint]);
SetProxy(endpoint, rtc::PROXY_HTTPS);
- } else if (config == PROXY_SOCKS) {
- // Block all TCP to/from the endpoint except to the proxy server
- fw()->AddRule(true, rtc::FP_TCP, kPublicAddrs[endpoint],
- kSocksProxyAddrs[endpoint]);
- fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY,
- kPublicAddrs[endpoint]);
- SetProxy(endpoint, rtc::PROXY_SOCKS5);
}
break;
default:
@@ -1253,42 +1229,28 @@ class P2PTransportChannelMatrixTest : public P2PTransportChannelTest,
const P2PTransportChannelMatrixTest::Result*
P2PTransportChannelMatrixTest::kMatrix[NUM_CONFIGS][NUM_CONFIGS] = {
// OPEN CONE ADDR PORT SYMM 2CON SCON !UDP !TCP HTTP PRXH
- // PRXS
- /*OP*/ {LULU, LUSU, LUSU, LUSU, LUPU, LUSU, LUPU, LTPT, LTPT, LSRS,
- NULL, LTPT},
+ /*OP*/
+ {LULU, LUSU, LUSU, LUSU, LUPU, LUSU, LUPU, LTPT, LTPT, LSRS, NULL},
/*CO*/
- {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL,
- LTRT},
+ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL},
/*AD*/
- {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL,
- LTRT},
+ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL},
/*PO*/
- {SULU, SUSU, SUSU, SUSU, RUPU, SUSU, RUPU, NULL, NULL, LSRS, NULL,
- LTRT},
+ {SULU, SUSU, SUSU, SUSU, RUPU, SUSU, RUPU, NULL, NULL, LSRS, NULL},
/*SY*/
- {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL,
- LTRT},
+ {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL},
/*2C*/
- {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL,
- LTRT},
+ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL},
/*SC*/
- {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL,
- LTRT},
+ {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL},
/*!U*/
- {LTPT, NULL, NULL, NULL, NULL, NULL, NULL, LTPT, LTPT, LSRS, NULL,
- LTRT},
+ {LTPT, NULL, NULL, NULL, NULL, NULL, NULL, LTPT, LTPT, LSRS, NULL},
/*!T*/
- {PTLT, NULL, NULL, NULL, NULL, NULL, NULL, PTLT, LTRT, LSRS, NULL,
- LTRT},
+ {PTLT, NULL, NULL, NULL, NULL, NULL, NULL, PTLT, LTRT, LSRS, NULL},
/*HT*/
- {LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, NULL,
- LSRS},
+ {LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, NULL},
/*PR*/
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL},
- /*PR*/
- {LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LSRS, NULL,
- LTRT},
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
};
// The actual tests that exercise all the various configurations.
@@ -1316,8 +1278,7 @@ const P2PTransportChannelMatrixTest::Result*
P2P_TEST(x, BLOCK_UDP) \
P2P_TEST(x, BLOCK_UDP_AND_INCOMING_TCP) \
P2P_TEST(x, BLOCK_ALL_BUT_OUTGOING_HTTP) \
- P2P_TEST(x, PROXY_HTTPS) \
- P2P_TEST(x, PROXY_SOCKS)
+ P2P_TEST(x, PROXY_HTTPS)
P2P_TEST_SET(OPEN)
P2P_TEST_SET(NAT_FULL_CONE)
@@ -1330,7 +1291,6 @@ P2P_TEST_SET(BLOCK_UDP)
P2P_TEST_SET(BLOCK_UDP_AND_INCOMING_TCP)
P2P_TEST_SET(BLOCK_ALL_BUT_OUTGOING_HTTP)
P2P_TEST_SET(PROXY_HTTPS)
-P2P_TEST_SET(PROXY_SOCKS)
INSTANTIATE_TEST_SUITE_P(
All,
@@ -1571,16 +1531,16 @@ TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignaling) {
ASSERT_TRUE_WAIT(
(selected_connection = ep1_ch1()->selected_connection()) != nullptr,
kMediumTimeout);
- EXPECT_EQ(PRFLX_PORT_TYPE, selected_connection->remote_candidate().type());
+ EXPECT_TRUE(selected_connection->remote_candidate().is_prflx());
EXPECT_EQ(kIceUfrag[1], selected_connection->remote_candidate().username());
EXPECT_EQ(kIcePwd[1], selected_connection->remote_candidate().password());
EXPECT_EQ(1u, selected_connection->remote_candidate().generation());
ResumeCandidates(1);
// Verify ep1's selected connection is updated to use the 'local' candidate.
- EXPECT_EQ_WAIT(LOCAL_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type(),
- kMediumTimeout);
+ EXPECT_TRUE_WAIT(
+ ep1_ch1()->selected_connection()->remote_candidate().is_local(),
+ kMediumTimeout);
EXPECT_EQ(selected_connection, ep1_ch1()->selected_connection());
DestroyChannels();
}
@@ -1608,15 +1568,15 @@ TEST_F(P2PTransportChannelTest, PeerReflexiveRemoteCandidateIsSanitized) {
// Check the selected candidate pair.
auto pair_ep1 = ep1_ch1()->GetSelectedCandidatePair();
ASSERT_TRUE(pair_ep1.has_value());
- EXPECT_EQ(PRFLX_PORT_TYPE, pair_ep1->remote_candidate().type());
+ EXPECT_TRUE(pair_ep1->remote_candidate().is_prflx());
EXPECT_TRUE(pair_ep1->remote_candidate().address().ipaddr().IsNil());
IceTransportStats ice_transport_stats;
ep1_ch1()->GetStats(&ice_transport_stats);
// Check the candidate pair stats.
ASSERT_EQ(1u, ice_transport_stats.connection_infos.size());
- EXPECT_EQ(PRFLX_PORT_TYPE,
- ice_transport_stats.connection_infos[0].remote_candidate.type());
+ EXPECT_TRUE(
+ ice_transport_stats.connection_infos[0].remote_candidate.is_prflx());
EXPECT_TRUE(ice_transport_stats.connection_infos[0]
.remote_candidate.address()
.ipaddr()
@@ -1626,8 +1586,7 @@ TEST_F(P2PTransportChannelTest, PeerReflexiveRemoteCandidateIsSanitized) {
ResumeCandidates(1);
ASSERT_TRUE_WAIT(
ep1_ch1()->selected_connection() != nullptr &&
- ep1_ch1()->selected_connection()->remote_candidate().type() ==
- LOCAL_PORT_TYPE,
+ ep1_ch1()->selected_connection()->remote_candidate().is_local(),
kMediumTimeout);
// We should be able to reveal the address after it is learnt via
@@ -1636,14 +1595,14 @@ TEST_F(P2PTransportChannelTest, PeerReflexiveRemoteCandidateIsSanitized) {
// Check the selected candidate pair.
auto updated_pair_ep1 = ep1_ch1()->GetSelectedCandidatePair();
ASSERT_TRUE(updated_pair_ep1.has_value());
- EXPECT_EQ(LOCAL_PORT_TYPE, updated_pair_ep1->remote_candidate().type());
+ EXPECT_TRUE(updated_pair_ep1->remote_candidate().is_local());
EXPECT_TRUE(HasRemoteAddress(&updated_pair_ep1.value(), kPublicAddrs[1]));
ep1_ch1()->GetStats(&ice_transport_stats);
// Check the candidate pair stats.
ASSERT_EQ(1u, ice_transport_stats.connection_infos.size());
- EXPECT_EQ(LOCAL_PORT_TYPE,
- ice_transport_stats.connection_infos[0].remote_candidate.type());
+ EXPECT_TRUE(
+ ice_transport_stats.connection_infos[0].remote_candidate.is_local());
EXPECT_TRUE(ice_transport_stats.connection_infos[0]
.remote_candidate.address()
.EqualIPs(kPublicAddrs[1]));
@@ -1679,16 +1638,16 @@ TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignalingWithNAT) {
ASSERT_TRUE_WAIT(
(selected_connection = ep1_ch1()->selected_connection()) != nullptr,
kMediumTimeout);
- EXPECT_EQ(PRFLX_PORT_TYPE, selected_connection->remote_candidate().type());
+ EXPECT_TRUE(selected_connection->remote_candidate().is_prflx());
EXPECT_EQ(kIceUfrag[1], selected_connection->remote_candidate().username());
EXPECT_EQ(kIcePwd[1], selected_connection->remote_candidate().password());
EXPECT_EQ(1u, selected_connection->remote_candidate().generation());
ResumeCandidates(1);
- EXPECT_EQ_WAIT(PRFLX_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type(),
- kMediumTimeout);
+ EXPECT_TRUE_WAIT(
+ ep1_ch1()->selected_connection()->remote_candidate().is_prflx(),
+ kMediumTimeout);
EXPECT_EQ(selected_connection, ep1_ch1()->selected_connection());
DestroyChannels();
}
@@ -1728,9 +1687,9 @@ TEST_F(P2PTransportChannelTest,
// The caller should have the selected connection connected to the peer
// reflexive candidate.
- EXPECT_EQ_WAIT(PRFLX_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type(),
- kDefaultTimeout);
+ EXPECT_TRUE_WAIT(
+ ep1_ch1()->selected_connection()->remote_candidate().is_prflx(),
+ kDefaultTimeout);
const Connection* prflx_selected_connection =
ep1_ch1()->selected_connection();
@@ -1744,9 +1703,9 @@ TEST_F(P2PTransportChannelTest,
// their information to update the peer reflexive candidate.
ResumeCandidates(1);
- EXPECT_EQ_WAIT(RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type(),
- kDefaultTimeout);
+ EXPECT_TRUE_WAIT(
+ ep1_ch1()->selected_connection()->remote_candidate().is_relay(),
+ kDefaultTimeout);
EXPECT_EQ(prflx_selected_connection, ep1_ch1()->selected_connection());
DestroyChannels();
}
@@ -2021,10 +1980,10 @@ TEST_F(P2PTransportChannelTest, TestForceTurn) {
EXPECT_TRUE(ep1_ch1()->selected_connection() &&
ep2_ch1()->selected_connection());
- EXPECT_EQ(RELAY_PORT_TYPE, RemoteCandidate(ep1_ch1())->type());
- EXPECT_EQ(RELAY_PORT_TYPE, LocalCandidate(ep1_ch1())->type());
- EXPECT_EQ(RELAY_PORT_TYPE, RemoteCandidate(ep2_ch1())->type());
- EXPECT_EQ(RELAY_PORT_TYPE, LocalCandidate(ep2_ch1())->type());
+ EXPECT_TRUE(RemoteCandidate(ep1_ch1())->is_relay());
+ EXPECT_TRUE(LocalCandidate(ep1_ch1())->is_relay());
+ EXPECT_TRUE(RemoteCandidate(ep2_ch1())->is_relay());
+ EXPECT_TRUE(LocalCandidate(ep2_ch1())->is_relay());
TestSendRecv(&clock);
DestroyChannels();
@@ -2172,8 +2131,8 @@ TEST_F(P2PTransportChannelTest, TurnToTurnPresumedWritable) {
// Expect that the TURN-TURN candidate pair will be prioritized since it's
// "probably writable".
EXPECT_TRUE_WAIT(ep1_ch1()->selected_connection() != nullptr, kShortTimeout);
- EXPECT_EQ(RELAY_PORT_TYPE, LocalCandidate(ep1_ch1())->type());
- EXPECT_EQ(RELAY_PORT_TYPE, RemoteCandidate(ep1_ch1())->type());
+ EXPECT_TRUE(LocalCandidate(ep1_ch1())->is_relay());
+ EXPECT_TRUE(RemoteCandidate(ep1_ch1())->is_relay());
// Also expect that the channel instantly indicates that it's writable since
// it has a TURN-TURN pair.
EXPECT_TRUE(ep1_ch1()->writable());
@@ -2220,8 +2179,8 @@ TEST_F(P2PTransportChannelTest, TurnToPrflxPresumedWritable) {
EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable(),
kShortTimeout, fake_clock);
ASSERT_NE(nullptr, ep1_ch1()->selected_connection());
- EXPECT_EQ(RELAY_PORT_TYPE, LocalCandidate(ep1_ch1())->type());
- EXPECT_EQ(PRFLX_PORT_TYPE, RemoteCandidate(ep1_ch1())->type());
+ EXPECT_TRUE(LocalCandidate(ep1_ch1())->is_relay());
+ EXPECT_TRUE(RemoteCandidate(ep1_ch1())->is_prflx());
// Make sure that at this point the connection is only presumed writable,
// not fully writable.
EXPECT_FALSE(ep1_ch1()->selected_connection()->writable());
@@ -2265,8 +2224,8 @@ TEST_F(P2PTransportChannelTest, PresumedWritablePreferredOverUnreliable) {
// port available to make a TURN<->TURN pair that's presumed writable.
ep1_ch1()->AddRemoteCandidate(
CreateUdpCandidate(RELAY_PORT_TYPE, "2.2.2.2", 2, 0));
- EXPECT_EQ(RELAY_PORT_TYPE, LocalCandidate(ep1_ch1())->type());
- EXPECT_EQ(RELAY_PORT_TYPE, RemoteCandidate(ep1_ch1())->type());
+ EXPECT_TRUE(LocalCandidate(ep1_ch1())->is_relay());
+ EXPECT_TRUE(RemoteCandidate(ep1_ch1())->is_relay());
EXPECT_TRUE(ep1_ch1()->writable());
EXPECT_TRUE(GetEndpoint(0)->ready_to_send_);
EXPECT_NE(old_selected_connection, ep1_ch1()->selected_connection());
@@ -2293,8 +2252,8 @@ TEST_F(P2PTransportChannelTest, SignalReadyToSendWithPresumedWritable) {
CreateUdpCandidate(RELAY_PORT_TYPE, "1.1.1.1", 1, 0));
// Sanity checking the type of the connection.
EXPECT_TRUE_WAIT(ep1_ch1()->selected_connection() != nullptr, kShortTimeout);
- EXPECT_EQ(RELAY_PORT_TYPE, LocalCandidate(ep1_ch1())->type());
- EXPECT_EQ(RELAY_PORT_TYPE, RemoteCandidate(ep1_ch1())->type());
+ EXPECT_TRUE(LocalCandidate(ep1_ch1())->is_relay());
+ EXPECT_TRUE(RemoteCandidate(ep1_ch1())->is_relay());
// Tell the socket server to block packets (returning EWOULDBLOCK).
virtual_socket_server()->SetSendingBlocked(true);
@@ -2349,8 +2308,8 @@ TEST_F(P2PTransportChannelTest,
ASSERT_NE(nullptr, ep1_ch1()->selected_connection());
- EXPECT_EQ(RELAY_PORT_TYPE, LocalCandidate(ep1_ch1())->type());
- EXPECT_EQ(PRFLX_PORT_TYPE, RemoteCandidate(ep1_ch1())->type());
+ EXPECT_TRUE(LocalCandidate(ep1_ch1())->is_relay());
+ EXPECT_TRUE(RemoteCandidate(ep1_ch1())->is_prflx());
DestroyChannels();
}
@@ -3383,7 +3342,6 @@ class P2PTransportChannelPingTest : public ::testing::Test,
protected:
void PrepareChannel(P2PTransportChannel* ch) {
ch->SetIceRole(ICEROLE_CONTROLLING);
- ch->SetIceTiebreaker(kTiebreakerDefault);
ch->SetIceParameters(kIceParams[0]);
ch->SetRemoteIceParameters(kIceParams[1]);
ch->SignalNetworkRouteChanged.connect(
@@ -3751,7 +3709,6 @@ TEST_F(P2PTransportChannelPingTest, PingingStartedAsSoonAsPossible) {
&field_trials_);
P2PTransportChannel ch("TestChannel", 1, &pa, &field_trials_);
ch.SetIceRole(ICEROLE_CONTROLLING);
- ch.SetIceTiebreaker(kTiebreakerDefault);
ch.SetIceParameters(kIceParams[0]);
ch.MaybeStartGathering();
EXPECT_EQ_WAIT(IceGatheringState::kIceGatheringComplete, ch.gathering_state(),
@@ -5041,22 +4998,22 @@ TEST_F(P2PTransportChannelMostLikelyToWorkFirstTest,
// Relay/Relay should be the first pingable connection.
Connection* conn = FindNextPingableConnectionAndPingIt(&ch);
ASSERT_TRUE(conn != nullptr);
- EXPECT_EQ(conn->local_candidate().type(), RELAY_PORT_TYPE);
- EXPECT_EQ(conn->remote_candidate().type(), RELAY_PORT_TYPE);
+ EXPECT_TRUE(conn->local_candidate().is_relay());
+ EXPECT_TRUE(conn->remote_candidate().is_relay());
// Unless that we have a trigger check waiting to be pinged.
Connection* conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2);
ASSERT_TRUE(conn2 != nullptr);
- EXPECT_EQ(conn2->local_candidate().type(), LOCAL_PORT_TYPE);
- EXPECT_EQ(conn2->remote_candidate().type(), LOCAL_PORT_TYPE);
+ EXPECT_TRUE(conn2->local_candidate().is_local());
+ EXPECT_TRUE(conn2->remote_candidate().is_local());
conn2->ReceivedPing();
EXPECT_EQ(conn2, FindNextPingableConnectionAndPingIt(&ch));
// Make conn3 the selected connection.
Connection* conn3 = WaitForConnectionTo(&ch, "1.1.1.1", 1);
ASSERT_TRUE(conn3 != nullptr);
- EXPECT_EQ(conn3->local_candidate().type(), LOCAL_PORT_TYPE);
- EXPECT_EQ(conn3->remote_candidate().type(), RELAY_PORT_TYPE);
+ EXPECT_TRUE(conn3->local_candidate().is_local());
+ EXPECT_TRUE(conn3->remote_candidate().is_relay());
conn3->ReceivedPingResponse(LOW_RTT, "id");
ASSERT_TRUE(conn3->writable());
conn3->ReceivedPing();
@@ -5266,16 +5223,16 @@ TEST_F(P2PTransportChannelTest,
ASSERT_TRUE_WAIT(
(selected_connection = ep2_ch1()->selected_connection()) != nullptr,
kMediumTimeout);
- EXPECT_EQ(PRFLX_PORT_TYPE, selected_connection->remote_candidate().type());
+ EXPECT_TRUE(selected_connection->remote_candidate().is_prflx());
EXPECT_EQ(kIceUfrag[0], selected_connection->remote_candidate().username());
EXPECT_EQ(kIcePwd[0], selected_connection->remote_candidate().password());
// Set expectation before ep1 signals a hostname candidate.
resolver_fixture.SetAddressToReturn(local_address);
ResumeCandidates(0);
// Verify ep2's selected connection is updated to use the 'local' candidate.
- EXPECT_EQ_WAIT(LOCAL_PORT_TYPE,
- ep2_ch1()->selected_connection()->remote_candidate().type(),
- kMediumTimeout);
+ EXPECT_TRUE_WAIT(
+ ep2_ch1()->selected_connection()->remote_candidate().is_local(),
+ kMediumTimeout);
EXPECT_EQ(selected_connection, ep2_ch1()->selected_connection());
DestroyChannels();
@@ -5328,16 +5285,15 @@ TEST_F(P2PTransportChannelTest,
// There is a caveat in our implementation associated with this expectation.
// See the big comment in P2PTransportChannel::OnUnknownAddress.
ASSERT_TRUE_WAIT(ep2_ch1()->selected_connection() != nullptr, kMediumTimeout);
- EXPECT_EQ(PRFLX_PORT_TYPE,
- ep2_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep2_ch1()->selected_connection()->remote_candidate().is_prflx());
// ep2 should also be able resolve the hostname candidate. The resolved remote
// host candidate should be merged with the prflx remote candidate.
resolver_fixture.FireDelayedResolution();
- EXPECT_EQ_WAIT(LOCAL_PORT_TYPE,
- ep2_ch1()->selected_connection()->remote_candidate().type(),
- kMediumTimeout);
+ EXPECT_TRUE_WAIT(
+ ep2_ch1()->selected_connection()->remote_candidate().is_local(),
+ kMediumTimeout);
EXPECT_EQ(1u, ep2_ch1()->remote_candidates().size());
DestroyChannels();
@@ -5380,10 +5336,8 @@ TEST_F(P2PTransportChannelTest, CanConnectWithHostCandidateWithMdnsName) {
// with a peer reflexive candidate from ep2.
ASSERT_TRUE_WAIT((ep1_ch1()->selected_connection()) != nullptr,
kMediumTimeout);
- EXPECT_EQ(LOCAL_PORT_TYPE,
- ep1_ch1()->selected_connection()->local_candidate().type());
- EXPECT_EQ(PRFLX_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->local_candidate().is_local());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->remote_candidate().is_prflx());
DestroyChannels();
}
@@ -5713,10 +5667,8 @@ TEST_F(P2PTransportChannelTest,
// We should be able to form a srflx-host connection to ep2.
ASSERT_TRUE_WAIT((ep1_ch1()->selected_connection()) != nullptr,
kMediumTimeout);
- EXPECT_EQ(STUN_PORT_TYPE,
- ep1_ch1()->selected_connection()->local_candidate().type());
- EXPECT_EQ(LOCAL_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->local_candidate().is_stun());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->remote_candidate().is_local());
DestroyChannels();
}
@@ -5747,31 +5699,25 @@ TEST_F(P2PTransportChannelTest,
kDefaultTimeout, clock);
ASSERT_TRUE_SIMULATED_WAIT(ep2_ch1()->selected_connection() != nullptr,
kDefaultTimeout, clock);
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->local_candidate().type());
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep2_ch1()->selected_connection()->local_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->local_candidate().is_relay());
+ EXPECT_TRUE(ep2_ch1()->selected_connection()->local_candidate().is_relay());
// Loosen the candidate filter at ep1.
ep1->allocator_->SetCandidateFilter(CF_ALL);
EXPECT_TRUE_SIMULATED_WAIT(
ep1_ch1()->selected_connection() != nullptr &&
- ep1_ch1()->selected_connection()->local_candidate().type() ==
- LOCAL_PORT_TYPE,
+ ep1_ch1()->selected_connection()->local_candidate().is_local(),
kDefaultTimeout, clock);
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->remote_candidate().is_relay());
// Loosen the candidate filter at ep2.
ep2->allocator_->SetCandidateFilter(CF_ALL);
EXPECT_TRUE_SIMULATED_WAIT(
ep2_ch1()->selected_connection() != nullptr &&
- ep2_ch1()->selected_connection()->local_candidate().type() ==
- LOCAL_PORT_TYPE,
+ ep2_ch1()->selected_connection()->local_candidate().is_local(),
kDefaultTimeout, clock);
// We have migrated to a host-host candidate pair.
- EXPECT_EQ(LOCAL_PORT_TYPE,
- ep2_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep2_ch1()->selected_connection()->remote_candidate().is_local());
// Block the traffic over non-relay-to-relay routes and expect a route change.
fw()->AddRule(false, rtc::FP_ANY, kPublicAddrs[0], kPublicAddrs[1]);
@@ -5780,12 +5726,10 @@ TEST_F(P2PTransportChannelTest,
fw()->AddRule(false, rtc::FP_ANY, kPublicAddrs[1], kTurnUdpExtAddr);
// We should be able to reuse the previously gathered relay candidates.
- EXPECT_EQ_SIMULATED_WAIT(
- RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->local_candidate().type(),
+ EXPECT_TRUE_SIMULATED_WAIT(
+ ep1_ch1()->selected_connection()->local_candidate().is_relay(),
kDefaultTimeout, clock);
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->remote_candidate().is_relay());
DestroyChannels();
}
@@ -5824,22 +5768,18 @@ TEST_F(P2PTransportChannelTest,
ep1->allocator_->SetCandidateFilter(kCandidateFilterNoHost);
EXPECT_TRUE_SIMULATED_WAIT(
ep1_ch1()->selected_connection() != nullptr &&
- ep1_ch1()->selected_connection()->local_candidate().type() ==
- STUN_PORT_TYPE,
+ ep1_ch1()->selected_connection()->local_candidate().is_stun(),
kDefaultTimeout, clock);
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->remote_candidate().is_relay());
// Loosen the candidate filter at ep2.
ep2->allocator_->SetCandidateFilter(kCandidateFilterNoHost);
EXPECT_TRUE_SIMULATED_WAIT(
ep2_ch1()->selected_connection() != nullptr &&
- ep2_ch1()->selected_connection()->local_candidate().type() ==
- STUN_PORT_TYPE,
+ ep2_ch1()->selected_connection()->local_candidate().is_stun(),
kDefaultTimeout, clock);
// We have migrated to a srflx-srflx candidate pair.
- EXPECT_EQ(STUN_PORT_TYPE,
- ep2_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep2_ch1()->selected_connection()->remote_candidate().is_stun());
// Block the traffic over non-relay-to-relay routes and expect a route change.
fw()->AddRule(false, rtc::FP_ANY, kPrivateAddrs[0], kPublicAddrs[1]);
@@ -5847,12 +5787,10 @@ TEST_F(P2PTransportChannelTest,
fw()->AddRule(false, rtc::FP_ANY, kPrivateAddrs[0], kTurnUdpExtAddr);
fw()->AddRule(false, rtc::FP_ANY, kPrivateAddrs[1], kTurnUdpExtAddr);
// We should be able to reuse the previously gathered relay candidates.
- EXPECT_EQ_SIMULATED_WAIT(
- RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->local_candidate().type(),
+ EXPECT_TRUE_SIMULATED_WAIT(
+ ep1_ch1()->selected_connection()->local_candidate().is_relay(),
kDefaultTimeout, clock);
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->remote_candidate().is_relay());
DestroyChannels();
}
@@ -5885,13 +5823,11 @@ TEST_F(P2PTransportChannelTest,
ep1->allocator_->SetCandidateFilter(CF_ALL);
// Wait for a period for any potential surfacing of new candidates.
SIMULATED_WAIT(false, kDefaultTimeout, clock);
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep1_ch1()->selected_connection()->local_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->local_candidate().is_relay());
// Loosen the candidate filter at ep2.
ep2->allocator_->SetCandidateFilter(CF_ALL);
- EXPECT_EQ(RELAY_PORT_TYPE,
- ep2_ch1()->selected_connection()->local_candidate().type());
+ EXPECT_TRUE(ep2_ch1()->selected_connection()->local_candidate().is_relay());
DestroyChannels();
}
@@ -5928,21 +5864,18 @@ TEST_F(P2PTransportChannelTest,
ResumeCandidates(1);
ASSERT_TRUE_SIMULATED_WAIT(
ep1_ch1()->selected_connection() != nullptr &&
- LOCAL_PORT_TYPE ==
- ep1_ch1()->selected_connection()->local_candidate().type() &&
+ ep1_ch1()->selected_connection()->local_candidate().is_local() &&
ep2_ch1()->selected_connection() != nullptr &&
- LOCAL_PORT_TYPE ==
- ep1_ch1()->selected_connection()->remote_candidate().type(),
+ ep1_ch1()->selected_connection()->remote_candidate().is_local(),
kDefaultTimeout, clock);
ASSERT_TRUE_SIMULATED_WAIT(ep2_ch1()->selected_connection() != nullptr,
kDefaultTimeout, clock);
// Test that we have a host-host candidate pair selected and the number of
// candidates signaled to the remote peer stays the same.
auto test_invariants = [this]() {
- EXPECT_EQ(LOCAL_PORT_TYPE,
- ep1_ch1()->selected_connection()->local_candidate().type());
- EXPECT_EQ(LOCAL_PORT_TYPE,
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ EXPECT_TRUE(ep1_ch1()->selected_connection()->local_candidate().is_local());
+ EXPECT_TRUE(
+ ep1_ch1()->selected_connection()->remote_candidate().is_local());
EXPECT_THAT(ep2_ch1()->remote_candidates(), SizeIs(3));
};
@@ -6005,11 +5938,9 @@ TEST_F(P2PTransportChannelTest, SurfaceRequiresCoordination) {
ResumeCandidates(1);
ASSERT_TRUE_SIMULATED_WAIT(
ep1_ch1()->selected_connection() != nullptr &&
- RELAY_PORT_TYPE ==
- ep1_ch1()->selected_connection()->local_candidate().type() &&
+ ep1_ch1()->selected_connection()->local_candidate().is_relay() &&
ep2_ch1()->selected_connection() != nullptr &&
- RELAY_PORT_TYPE ==
- ep1_ch1()->selected_connection()->remote_candidate().type(),
+ ep1_ch1()->selected_connection()->remote_candidate().is_relay(),
kDefaultTimeout, clock);
ASSERT_TRUE_SIMULATED_WAIT(ep2_ch1()->selected_connection() != nullptr,
kDefaultTimeout, clock);
@@ -6025,11 +5956,9 @@ TEST_F(P2PTransportChannelTest, SurfaceRequiresCoordination) {
// No p2p connection will be made, it will remain on relay.
EXPECT_TRUE(ep1_ch1()->selected_connection() != nullptr &&
- RELAY_PORT_TYPE ==
- ep1_ch1()->selected_connection()->local_candidate().type() &&
+ ep1_ch1()->selected_connection()->local_candidate().is_relay() &&
ep2_ch1()->selected_connection() != nullptr &&
- RELAY_PORT_TYPE ==
- ep1_ch1()->selected_connection()->remote_candidate().type());
+ ep1_ch1()->selected_connection()->remote_candidate().is_relay());
DestroyChannels();
}
diff --git a/third_party/libwebrtc/p2p/base/port.cc b/third_party/libwebrtc/p2p/base/port.cc
index a3378fe23a..f49bfe524c 100644
--- a/third_party/libwebrtc/p2p/base/port.cc
+++ b/third_party/libwebrtc/p2p/base/port.cc
@@ -10,33 +10,34 @@
#include "p2p/base/port.h"
-#include <math.h>
-
-#include <algorithm>
#include <cstddef>
+#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
-#include "absl/algorithm/container.h"
#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
-#include "p2p/base/connection.h"
-#include "p2p/base/port_allocator.h"
+#include "api/array_view.h"
+#include "api/rtc_error.h"
+#include "api/units/time_delta.h"
+#include "p2p/base/p2p_constants.h"
+#include "p2p/base/stun_request.h"
+#include "rtc_base/byte_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/crc32.h"
#include "rtc_base/helpers.h"
+#include "rtc_base/ip_address.h"
#include "rtc_base/logging.h"
#include "rtc_base/mdns_responder_interface.h"
-#include "rtc_base/message_digest.h"
+#include "rtc_base/net_helper.h"
#include "rtc_base/network.h"
-#include "rtc_base/numerics/safe_minmax.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"
-#include "rtc_base/third_party/base64/base64.h"
+#include "rtc_base/time_utils.h"
#include "rtc_base/trace_event.h"
namespace cricket {
@@ -258,14 +259,18 @@ void Port::AddAddress(const rtc::SocketAddress& address,
absl::string_view url,
bool is_final) {
RTC_DCHECK_RUN_ON(thread_);
- if (protocol == TCP_PROTOCOL_NAME && type == LOCAL_PORT_TYPE) {
- RTC_DCHECK(!tcptype.empty());
- }
std::string foundation =
ComputeFoundation(type, protocol, relay_protocol, base_address);
Candidate c(component_, protocol, address, 0U, username_fragment(), password_,
type, generation_, foundation, network_->id(), network_cost_);
+
+#if RTC_DCHECK_IS_ON
+ if (protocol == TCP_PROTOCOL_NAME && c.is_local()) {
+ RTC_DCHECK(!tcptype.empty());
+ }
+#endif
+
c.set_relay_protocol(relay_protocol);
c.set_priority(
c.GetPriority(type_preference, network_->preference(), relay_preference,
@@ -278,26 +283,24 @@ void Port::AddAddress(const rtc::SocketAddress& address,
c.set_url(url);
c.set_related_address(related_address);
- bool pending = MaybeObfuscateAddress(&c, type, is_final);
+ bool pending = MaybeObfuscateAddress(c, is_final);
if (!pending) {
FinishAddingAddress(c, is_final);
}
}
-bool Port::MaybeObfuscateAddress(Candidate* c,
- absl::string_view type,
- bool is_final) {
+bool Port::MaybeObfuscateAddress(const Candidate& c, bool is_final) {
// TODO(bugs.webrtc.org/9723): Use a config to control the feature of IP
// handling with mDNS.
if (network_->GetMdnsResponder() == nullptr) {
return false;
}
- if (type != LOCAL_PORT_TYPE) {
+ if (!c.is_local()) {
return false;
}
- auto copy = *c;
+ auto copy = c;
auto weak_ptr = weak_factory_.GetWeakPtr();
auto callback = [weak_ptr, copy, is_final](const rtc::IPAddress& addr,
absl::string_view name) mutable {
diff --git a/third_party/libwebrtc/p2p/base/port.h b/third_party/libwebrtc/p2p/base/port.h
index 7b44e534de..a3214af1b8 100644
--- a/third_party/libwebrtc/p2p/base/port.h
+++ b/third_party/libwebrtc/p2p/base/port.h
@@ -11,10 +11,15 @@
#ifndef P2P_BASE_PORT_H_
#define P2P_BASE_PORT_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
+#include <type_traits>
#include <utility>
#include <vector>
@@ -25,6 +30,7 @@
#include "api/field_trials_view.h"
#include "api/packet_socket_factory.h"
#include "api/rtc_error.h"
+#include "api/sequence_checker.h"
#include "api/task_queue/task_queue_base.h"
#include "api/transport/field_trial_based_config.h"
#include "api/transport/stun.h"
@@ -37,18 +43,22 @@
#include "p2p/base/p2p_constants.h"
#include "p2p/base/port_interface.h"
#include "p2p/base/stun_request.h"
+#include "p2p/base/transport_description.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/callback_list.h"
#include "rtc_base/checks.h"
+#include "rtc_base/dscp.h"
#include "rtc_base/memory/always_valid_pointer.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/network.h"
#include "rtc_base/network/received_packet.h"
+#include "rtc_base/network/sent_packet.h"
#include "rtc_base/proxy_info.h"
#include "rtc_base/rate_tracker.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
+#include "rtc_base/thread_annotations.h"
#include "rtc_base/weak_ptr.h"
namespace cricket {
@@ -59,19 +69,6 @@ extern const char TCPTYPE_ACTIVE_STR[];
extern const char TCPTYPE_PASSIVE_STR[];
extern const char TCPTYPE_SIMOPEN_STR[];
-// The type preference MUST be an integer from 0 to 126 inclusive.
-// https://datatracker.ietf.org/doc/html/rfc5245#section-4.1.2.1
-enum IcePriorityValue : uint8_t {
- ICE_TYPE_PREFERENCE_RELAY_TLS = 0,
- ICE_TYPE_PREFERENCE_RELAY_TCP = 1,
- ICE_TYPE_PREFERENCE_RELAY_UDP = 2,
- ICE_TYPE_PREFERENCE_PRFLX_TCP = 80,
- ICE_TYPE_PREFERENCE_HOST_TCP = 90,
- ICE_TYPE_PREFERENCE_SRFLX = 100,
- ICE_TYPE_PREFERENCE_PRFLX = 110,
- ICE_TYPE_PREFERENCE_HOST = 126
-};
-
enum class MdnsNameRegistrationStatus {
// IP concealment with mDNS is not enabled or the name registration process is
// not started yet.
@@ -202,8 +199,8 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
// Note that the port type does NOT uniquely identify different subclasses of
// Port. Use the 2-tuple of the port type AND the protocol (GetProtocol()) to
// uniquely identify subclasses. Whenever a new subclass of Port introduces a
- // conflit in the value of the 2-tuple, make sure that the implementation that
- // relies on this 2-tuple for RTTI is properly changed.
+ // conflict in the value of the 2-tuple, make sure that the implementation
+ // that relies on this 2-tuple for RTTI is properly changed.
const absl::string_view Type() const override;
const rtc::Network* Network() const override;
@@ -227,13 +224,13 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
void CancelPendingTasks();
// The thread on which this port performs its I/O.
- webrtc::TaskQueueBase* thread() { return thread_; }
+ webrtc::TaskQueueBase* thread() override { return thread_; }
// The factory used to create the sockets of this port.
- rtc::PacketSocketFactory* socket_factory() const { return factory_; }
+ rtc::PacketSocketFactory* socket_factory() const override { return factory_; }
// For debugging purposes.
- const std::string& content_name() const { return content_name_; }
+ const std::string& content_name() const override { return content_name_; }
void set_content_name(absl::string_view content_name) {
content_name_ = std::string(content_name);
}
@@ -241,7 +238,7 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
int component() const { return component_; }
void set_component(int component) { component_ = component; }
- bool send_retransmit_count_attribute() const {
+ bool send_retransmit_count_attribute() const override {
return send_retransmit_count_attribute_;
}
void set_send_retransmit_count_attribute(bool enable) {
@@ -249,8 +246,10 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
}
// Identifies the generation that this port was created in.
- uint32_t generation() const { return generation_; }
- void set_generation(uint32_t generation) { generation_ = generation; }
+ uint32_t generation() const override { return generation_; }
+ void set_generation(uint32_t generation) override {
+ generation_ = generation;
+ }
const std::string& username_fragment() const;
const std::string& password() const { return password_; }
@@ -296,11 +295,11 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
// defers the `delete` operation to when the call stack has been unwound.
// Async may be needed when deleting a connection object from within a
// callback.
- void DestroyConnection(Connection* conn) {
+ void DestroyConnection(Connection* conn) override {
DestroyConnectionInternal(conn, false);
}
- void DestroyConnectionAsync(Connection* conn) {
+ void DestroyConnectionAsync(Connection* conn) override {
DestroyConnectionInternal(conn, true);
}
@@ -330,8 +329,8 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
user_agent_ = std::string(user_agent);
proxy_ = proxy;
}
- const std::string& user_agent() { return user_agent_; }
- const rtc::ProxyInfo& proxy() { return proxy_; }
+ const std::string& user_agent() override { return user_agent_; }
+ const rtc::ProxyInfo& proxy() override { return proxy_; }
void EnablePortPackets() override;
@@ -350,12 +349,13 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
// stun username attribute if present.
bool ParseStunUsername(const StunMessage* stun_msg,
std::string* local_username,
- std::string* remote_username) const;
- std::string CreateStunUsername(absl::string_view remote_username) const;
+ std::string* remote_username) const override;
+ std::string CreateStunUsername(
+ absl::string_view remote_username) const override;
bool MaybeIceRoleConflict(const rtc::SocketAddress& addr,
IceMessage* stun_msg,
- absl::string_view remote_ufrag);
+ absl::string_view remote_ufrag) override;
// Called when a packet has been sent to the socket.
// This is made pure virtual to notify subclasses of Port that they MUST
@@ -368,9 +368,9 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
void OnReadyToSend();
// Called when the Connection discovers a local peer reflexive candidate.
- void AddPrflxCandidate(const Candidate& local);
+ void AddPrflxCandidate(const Candidate& local) override;
- int16_t network_cost() const { return network_cost_; }
+ int16_t network_cost() const override { return network_cost_; }
void GetStunStats(absl::optional<StunStats>* stats) override {}
@@ -380,13 +380,14 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
// then the foundation will be different. Two candidate pairs with
// the same foundation pairs are likely to have similar network
// characteristics. Foundations are used in the frozen algorithm.
- std::string ComputeFoundation(absl::string_view type,
- absl::string_view protocol,
- absl::string_view relay_protocol,
- const rtc::SocketAddress& base_address);
+ std::string ComputeFoundation(
+ absl::string_view type,
+ absl::string_view protocol,
+ absl::string_view relay_protocol,
+ const rtc::SocketAddress& base_address) override;
protected:
- virtual void UpdateNetworkCost();
+ void UpdateNetworkCost() override;
rtc::WeakPtr<Port> NewWeakPtr() { return weak_factory_.GetWeakPtr(); }
@@ -438,13 +439,13 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
size_t size,
const rtc::SocketAddress& addr,
std::unique_ptr<IceMessage>* out_msg,
- std::string* out_username);
+ std::string* out_username) override;
// Checks if the address in addr is compatible with the port's ip.
bool IsCompatibleAddress(const rtc::SocketAddress& addr);
// Returns DSCP value packets generated by the port itself should use.
- virtual rtc::DiffServCodePoint StunDscpValue() const;
+ rtc::DiffServCodePoint StunDscpValue() const override;
// Extra work to be done in subclasses when a connection is destroyed.
virtual void HandleConnectionDestroyed(Connection* conn) {}
@@ -524,11 +525,9 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
webrtc::FieldTrialBasedConfig>
field_trials_;
- bool MaybeObfuscateAddress(Candidate* c,
- absl::string_view type,
- bool is_final) RTC_RUN_ON(thread_);
+ bool MaybeObfuscateAddress(const Candidate& c, bool is_final)
+ RTC_RUN_ON(thread_);
- friend class Connection;
webrtc::CallbackList<PortInterface*> port_destroyed_callback_list_;
};
diff --git a/third_party/libwebrtc/p2p/base/port_allocator.cc b/third_party/libwebrtc/p2p/base/port_allocator.cc
index 16f5afe36c..52fc8c1d39 100644
--- a/third_party/libwebrtc/p2p/base/port_allocator.cc
+++ b/third_party/libwebrtc/p2p/base/port_allocator.cc
@@ -11,13 +11,13 @@
#include "p2p/base/port_allocator.h"
#include <iterator>
+#include <optional>
#include <set>
#include <utility>
#include "absl/strings/string_view.h"
#include "p2p/base/ice_credentials_iterator.h"
#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
namespace cricket {
@@ -68,8 +68,7 @@ PortAllocatorSession::PortAllocatorSession(absl::string_view content_name,
content_name_(content_name),
component_(component),
ice_ufrag_(ice_ufrag),
- ice_pwd_(ice_pwd),
- tiebreaker_(0) {
+ ice_pwd_(ice_pwd) {
// Pooled sessions are allowed to be created with empty content name,
// component, ufrag and password.
RTC_DCHECK(ice_ufrag.empty() == ice_pwd.empty());
@@ -101,7 +100,7 @@ PortAllocator::PortAllocator()
step_delay_(kDefaultStepDelay),
allow_tcp_listen_(true),
candidate_filter_(CF_ALL),
- tiebreaker_(0) {
+ tiebreaker_(rtc::CreateRandomId64()) {
// The allocator will be attached to a thread in Initialize.
thread_checker_.Detach();
}
@@ -189,7 +188,6 @@ bool PortAllocator::SetConfiguration(
PortAllocatorSession* pooled_session =
CreateSessionInternal("", 0, iceCredentials.ufrag, iceCredentials.pwd);
pooled_session->set_pooled(true);
- pooled_session->set_ice_tiebreaker(tiebreaker_);
pooled_session->StartGettingPorts();
pooled_sessions_.push_back(
std::unique_ptr<PortAllocatorSession>(pooled_session));
@@ -197,13 +195,6 @@ bool PortAllocator::SetConfiguration(
return true;
}
-void PortAllocator::SetIceTiebreaker(uint64_t tiebreaker) {
- tiebreaker_ = tiebreaker;
- for (auto& pooled_session : pooled_sessions_) {
- pooled_session->set_ice_tiebreaker(tiebreaker_);
- }
-}
-
std::unique_ptr<PortAllocatorSession> PortAllocator::CreateSession(
absl::string_view content_name,
int component,
@@ -213,7 +204,6 @@ std::unique_ptr<PortAllocatorSession> PortAllocator::CreateSession(
auto session = std::unique_ptr<PortAllocatorSession>(
CreateSessionInternal(content_name, component, ice_ufrag, ice_pwd));
session->SetCandidateFilter(candidate_filter());
- session->set_ice_tiebreaker(tiebreaker_);
return session;
}
diff --git a/third_party/libwebrtc/p2p/base/port_allocator.h b/third_party/libwebrtc/p2p/base/port_allocator.h
index 11462f78f2..63ecfc6904 100644
--- a/third_party/libwebrtc/p2p/base/port_allocator.h
+++ b/third_party/libwebrtc/p2p/base/port_allocator.h
@@ -11,18 +11,26 @@
#ifndef P2P_BASE_PORT_ALLOCATOR_H_
#define P2P_BASE_PORT_ALLOCATOR_H_
+#include <stdint.h>
+
#include <deque>
#include <memory>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/candidate.h"
#include "api/sequence_checker.h"
#include "api/transport/enums.h"
#include "p2p/base/port.h"
#include "p2p/base/port_interface.h"
+#include "p2p/base/transport_description.h"
+#include "rtc_base/checks.h"
#include "rtc_base/helpers.h"
+#include "rtc_base/network.h"
#include "rtc_base/proxy_info.h"
+#include "rtc_base/socket_address.h"
#include "rtc_base/ssl_certificate.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
@@ -204,10 +212,6 @@ class RTC_EXPORT PortAllocatorSession : public sigslot::has_slots<> {
const std::string& ice_pwd() const { return ice_pwd_; }
bool pooled() const { return pooled_; }
- // TODO(bugs.webrtc.org/14605): move this to the constructor
- void set_ice_tiebreaker(uint64_t tiebreaker) { tiebreaker_ = tiebreaker; }
- uint64_t ice_tiebreaker() const { return tiebreaker_; }
-
// Setting this filter should affect not only candidates gathered in the
// future, but candidates already gathered and ports already "ready",
// which would be returned by ReadyCandidates() and ReadyPorts().
@@ -324,9 +328,6 @@ class RTC_EXPORT PortAllocatorSession : public sigslot::has_slots<> {
bool pooled_ = false;
- // TODO(bugs.webrtc.org/14605): move this to the constructor
- uint64_t tiebreaker_;
-
// SetIceParameters is an implementation detail which only PortAllocator
// should be able to call.
friend class PortAllocator;
@@ -379,9 +380,6 @@ class RTC_EXPORT PortAllocator : public sigslot::has_slots<> {
const absl::optional<int>&
stun_candidate_keepalive_interval = absl::nullopt);
- void SetIceTiebreaker(uint64_t tiebreaker);
- uint64_t IceTiebreaker() const { return tiebreaker_; }
-
const ServerAddresses& stun_servers() const {
CheckRunOnValidThreadIfInitialized();
return stun_servers_;
@@ -453,6 +451,8 @@ class RTC_EXPORT PortAllocator : public sigslot::has_slots<> {
// 3. mDNS concealment of private IPs is enabled.
Candidate SanitizeCandidate(const Candidate& c) const;
+ uint64_t ice_tiebreaker() const { return tiebreaker_; }
+
uint32_t flags() const {
CheckRunOnValidThreadIfInitialized();
return flags_;
diff --git a/third_party/libwebrtc/p2p/base/port_allocator_unittest.cc b/third_party/libwebrtc/p2p/base/port_allocator_unittest.cc
index 836a2fa494..2df8662f62 100644
--- a/third_party/libwebrtc/p2p/base/port_allocator_unittest.cc
+++ b/third_party/libwebrtc/p2p/base/port_allocator_unittest.cc
@@ -26,7 +26,6 @@ static const char kIceUfrag[] = "UF00";
static const char kIcePwd[] = "TESTICEPWD00000000000000";
static const char kTurnUsername[] = "test";
static const char kTurnPassword[] = "test";
-constexpr uint64_t kTiebreakerDefault = 44444;
class PortAllocatorTest : public ::testing::Test, public sigslot::has_slots<> {
public:
@@ -38,9 +37,7 @@ class PortAllocatorTest : public ::testing::Test, public sigslot::has_slots<> {
allocator_(std::make_unique<cricket::FakePortAllocator>(
rtc::Thread::Current(),
packet_socket_factory_.get(),
- &field_trials_)) {
- allocator_->SetIceTiebreaker(kTiebreakerDefault);
- }
+ &field_trials_)) {}
protected:
void SetConfigurationWithPoolSize(int candidate_pool_size) {
diff --git a/third_party/libwebrtc/p2p/base/port_interface.h b/third_party/libwebrtc/p2p/base/port_interface.h
index fe4b204c95..fb8023b5dd 100644
--- a/third_party/libwebrtc/p2p/base/port_interface.h
+++ b/third_party/libwebrtc/p2p/base/port_interface.h
@@ -11,6 +11,7 @@
#ifndef P2P_BASE_PORT_INTERFACE_H_
#define P2P_BASE_PORT_INTERFACE_H_
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -18,9 +19,11 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/candidate.h"
+#include "api/packet_socket_factory.h"
#include "p2p/base/transport_description.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/callback_list.h"
+#include "rtc_base/proxy_info.h"
#include "rtc_base/socket_address.h"
namespace rtc {
@@ -137,8 +140,80 @@ class PortInterface {
virtual void GetStunStats(absl::optional<StunStats>* stats) = 0;
+ // Removes and deletes a connection object. `DestroyConnection` will
+ // delete the connection object directly whereas `DestroyConnectionAsync`
+ // defers the `delete` operation to when the call stack has been unwound.
+ // Async may be needed when deleting a connection object from within a
+ // callback.
+ virtual void DestroyConnection(Connection* conn) = 0;
+
+ virtual void DestroyConnectionAsync(Connection* conn) = 0;
+
+ // The thread on which this port performs its I/O.
+ virtual webrtc::TaskQueueBase* thread() = 0;
+
+ // The factory used to create the sockets of this port.
+ virtual rtc::PacketSocketFactory* socket_factory() const = 0;
+ virtual const std::string& user_agent() = 0;
+ virtual const rtc::ProxyInfo& proxy() = 0;
+
+ // Identifies the generation that this port was created in.
+ virtual uint32_t generation() const = 0;
+ virtual void set_generation(uint32_t generation) = 0;
+ virtual bool send_retransmit_count_attribute() const = 0;
+ // For debugging purposes.
+ virtual const std::string& content_name() const = 0;
+
+ // Called when the Connection discovers a local peer reflexive candidate.
+ virtual void AddPrflxCandidate(const Candidate& local) = 0;
+
+ // Foundation: An arbitrary string that is the same for two candidates
+ // that have the same type, base IP address, protocol (UDP, TCP,
+ // etc.), and STUN or TURN server. If any of these are different,
+ // then the foundation will be different. Two candidate pairs with
+ // the same foundation pairs are likely to have similar network
+ // characteristics. Foundations are used in the frozen algorithm.
+ virtual std::string ComputeFoundation(
+ absl::string_view type,
+ absl::string_view protocol,
+ absl::string_view relay_protocol,
+ const rtc::SocketAddress& base_address) = 0;
+
protected:
PortInterface();
+ virtual void UpdateNetworkCost() = 0;
+
+ // Returns DSCP value packets generated by the port itself should use.
+ virtual rtc::DiffServCodePoint StunDscpValue() const = 0;
+
+ // If the given data comprises a complete and correct STUN message then the
+ // return value is true, otherwise false. If the message username corresponds
+ // with this port's username fragment, msg will contain the parsed STUN
+ // message. Otherwise, the function may send a STUN response internally.
+ // remote_username contains the remote fragment of the STUN username.
+ virtual bool GetStunMessage(const char* data,
+ size_t size,
+ const rtc::SocketAddress& addr,
+ std::unique_ptr<IceMessage>* out_msg,
+ std::string* out_username) = 0;
+
+ // This method will return local and remote username fragements from the
+ // stun username attribute if present.
+ virtual bool ParseStunUsername(const StunMessage* stun_msg,
+ std::string* local_username,
+ std::string* remote_username) const = 0;
+ virtual std::string CreateStunUsername(
+ absl::string_view remote_username) const = 0;
+
+ virtual bool MaybeIceRoleConflict(const rtc::SocketAddress& addr,
+ IceMessage* stun_msg,
+ absl::string_view remote_ufrag) = 0;
+
+ virtual int16_t network_cost() const = 0;
+
+ // Connection and Port are entangled; functions exposed to Port only
+ // should not be public.
+ friend class Connection;
};
} // namespace cricket
diff --git a/third_party/libwebrtc/p2p/base/port_unittest.cc b/third_party/libwebrtc/p2p/base/port_unittest.cc
index de35d94259..ab3ff86fd1 100644
--- a/third_party/libwebrtc/p2p/base/port_unittest.cc
+++ b/third_party/libwebrtc/p2p/base/port_unittest.cc
@@ -825,9 +825,9 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> {
absl::string_view username,
absl::string_view password,
const webrtc::FieldTrialsView* field_trials = nullptr) {
- auto port = std::make_unique<TestPort>(&main_, "test", &socket_factory_,
- MakeNetwork(addr), 0, 0, username,
- password, field_trials);
+ auto port = std::make_unique<TestPort>(
+ &main_, cricket::LOCAL_PORT_TYPE, &socket_factory_, MakeNetwork(addr),
+ 0, 0, username, password, field_trials);
port->SignalRoleConflict.connect(this, &PortTest::OnRoleConflict);
return port;
}
@@ -845,8 +845,9 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> {
std::unique_ptr<TestPort> CreateTestPort(const rtc::Network* network,
absl::string_view username,
absl::string_view password) {
- auto port = std::make_unique<TestPort>(&main_, "test", &socket_factory_,
- network, 0, 0, username, password);
+ auto port = std::make_unique<TestPort>(&main_, cricket::LOCAL_PORT_TYPE,
+ &socket_factory_, network, 0, 0,
+ username, password);
port->SignalRoleConflict.connect(this, &PortTest::OnRoleConflict);
return port;
}
diff --git a/third_party/libwebrtc/p2p/base/regathering_controller_unittest.cc b/third_party/libwebrtc/p2p/base/regathering_controller_unittest.cc
index 91b7270f77..573c0fd23f 100644
--- a/third_party/libwebrtc/p2p/base/regathering_controller_unittest.cc
+++ b/third_party/libwebrtc/p2p/base/regathering_controller_unittest.cc
@@ -40,7 +40,6 @@ const rtc::SocketAddress kTurnUdpIntAddr("99.99.99.3",
const cricket::RelayCredentials kRelayCredentials("test", "test");
const char kIceUfrag[] = "UF00";
const char kIcePwd[] = "TESTICEPWD00000000000000";
-constexpr uint64_t kTiebreakerDefault = 44444;
} // namespace
@@ -59,7 +58,6 @@ class RegatheringControllerTest : public ::testing::Test,
rtc::Thread::Current(),
packet_socket_factory_.get(),
&field_trials_)) {
- allocator_->SetIceTiebreaker(kTiebreakerDefault);
BasicRegatheringController::Config regathering_config;
regathering_config.regather_on_failed_networks_interval = 0;
regathering_controller_.reset(new BasicRegatheringController(
diff --git a/third_party/libwebrtc/p2p/base/stun_port_unittest.cc b/third_party/libwebrtc/p2p/base/stun_port_unittest.cc
index 9167081afb..7bc151ee03 100644
--- a/third_party/libwebrtc/p2p/base/stun_port_unittest.cc
+++ b/third_party/libwebrtc/p2p/base/stun_port_unittest.cc
@@ -426,7 +426,7 @@ TEST_F(StunPortTest, TestStunCandidateDiscardedWithMdnsObfuscationNotEnabled) {
EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
ASSERT_EQ(1U, port()->Candidates().size());
EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
- EXPECT_EQ(port()->Candidates()[0].type(), cricket::LOCAL_PORT_TYPE);
+ EXPECT_TRUE(port()->Candidates()[0].is_local());
}
// Test that a stun candidate (srflx candidate) is generated whose address is
diff --git a/third_party/libwebrtc/p2p/base/tcp_port.cc b/third_party/libwebrtc/p2p/base/tcp_port.cc
index ce61416979..948849800c 100644
--- a/third_party/libwebrtc/p2p/base/tcp_port.cc
+++ b/third_party/libwebrtc/p2p/base/tcp_port.cc
@@ -134,8 +134,7 @@ Connection* TCPPort::CreateConnection(const Candidate& address,
return NULL;
}
- if ((address.tcptype() == TCPTYPE_ACTIVE_STR &&
- address.type() != PRFLX_PORT_TYPE) ||
+ if ((address.tcptype() == TCPTYPE_ACTIVE_STR && !address.is_prflx()) ||
(address.tcptype().empty() && address.address().port() == 0)) {
// It's active only candidate, we should not try to create connections
// for these candidates.
diff --git a/third_party/libwebrtc/p2p/base/transport_description.h b/third_party/libwebrtc/p2p/base/transport_description.h
index 7d28ad52e9..53a1804933 100644
--- a/third_party/libwebrtc/p2p/base/transport_description.h
+++ b/third_party/libwebrtc/p2p/base/transport_description.h
@@ -25,17 +25,6 @@
namespace cricket {
-// SEC_ENABLED and SEC_REQUIRED should only be used if the session
-// was negotiated over TLS, to protect the inline crypto material
-// exchange.
-// SEC_DISABLED: No crypto in outgoing offer, ignore any supplied crypto.
-// SEC_ENABLED: Crypto in outgoing offer and answer (if supplied in offer).
-// SEC_REQUIRED: Crypto in outgoing offer and answer. Fail any offer with absent
-// or unsupported crypto.
-// TODO(deadbeef): Remove this or rename it to something more appropriate, like
-// SdesPolicy.
-enum SecurePolicy { SEC_DISABLED, SEC_ENABLED, SEC_REQUIRED };
-
// Whether our side of the call is driving the negotiation, or the other side.
enum IceRole { ICEROLE_CONTROLLING = 0, ICEROLE_CONTROLLED, ICEROLE_UNKNOWN };
diff --git a/third_party/libwebrtc/p2p/base/transport_description_factory.cc b/third_party/libwebrtc/p2p/base/transport_description_factory.cc
index 7eb21da166..6e3af94384 100644
--- a/third_party/libwebrtc/p2p/base/transport_description_factory.cc
+++ b/third_party/libwebrtc/p2p/base/transport_description_factory.cc
@@ -23,7 +23,7 @@ namespace cricket {
TransportDescriptionFactory::TransportDescriptionFactory(
const webrtc::FieldTrialsView& field_trials)
- : secure_(SEC_DISABLED), field_trials_(field_trials) {}
+ : field_trials_(field_trials) {}
TransportDescriptionFactory::~TransportDescriptionFactory() = default;
@@ -47,13 +47,15 @@ std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateOffer(
desc->AddOption(ICE_OPTION_RENOMINATION);
}
- // If we are trying to establish a secure transport, add a fingerprint.
- if (secure_ == SEC_ENABLED || secure_ == SEC_REQUIRED) {
- // Fail if we can't create the fingerprint.
- // If we are the initiator set role to "actpass".
- if (!SetSecurityInfo(desc.get(), CONNECTIONROLE_ACTPASS)) {
- return NULL;
- }
+ // If we are not trying to establish a secure transport, don't add a
+ // fingerprint.
+ if (insecure_ && !certificate_) {
+ return desc;
+ }
+ // Fail if we can't create the fingerprint.
+ // If we are the initiator set role to "actpass".
+ if (!SetSecurityInfo(desc.get(), CONNECTIONROLE_ACTPASS)) {
+ return NULL;
}
return desc;
@@ -87,43 +89,49 @@ std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateAnswer(
if (options.enable_ice_renomination) {
desc->AddOption(ICE_OPTION_RENOMINATION);
}
-
- // Negotiate security params.
- if (offer && offer->identity_fingerprint.get()) {
- // The offer supports DTLS, so answer with DTLS, as long as we support it.
- if (secure_ == SEC_ENABLED || secure_ == SEC_REQUIRED) {
- ConnectionRole role = CONNECTIONROLE_NONE;
- // If the offer does not constrain the role, go with preference.
- if (offer->connection_role == CONNECTIONROLE_ACTPASS) {
- role = (options.prefer_passive_role) ? CONNECTIONROLE_PASSIVE
- : CONNECTIONROLE_ACTIVE;
- } else if (offer->connection_role == CONNECTIONROLE_ACTIVE) {
- role = CONNECTIONROLE_PASSIVE;
- } else if (offer->connection_role == CONNECTIONROLE_PASSIVE) {
- role = CONNECTIONROLE_ACTIVE;
- } else if (offer->connection_role == CONNECTIONROLE_NONE) {
- // This case may be reached if a=setup is not present in the SDP.
- RTC_LOG(LS_WARNING) << "Remote offer connection role is NONE, which is "
- "a protocol violation";
- role = (options.prefer_passive_role) ? CONNECTIONROLE_PASSIVE
- : CONNECTIONROLE_ACTIVE;
- } else {
- RTC_LOG(LS_ERROR) << "Remote offer connection role is " << role
- << " which is a protocol violation";
- RTC_DCHECK_NOTREACHED();
- }
-
- if (!SetSecurityInfo(desc.get(), role)) {
- return NULL;
- }
+ // Special affordance for testing: Answer without DTLS params
+ // if we are insecure without a certificate, or if we are
+ // insecure with a non-DTLS offer.
+ if ((!certificate_ || !offer->identity_fingerprint.get()) && insecure()) {
+ return desc;
+ }
+ if (!offer->identity_fingerprint.get()) {
+ if (require_transport_attributes) {
+ // We require DTLS, but the other side didn't offer it. Fail.
+ RTC_LOG(LS_WARNING) << "Failed to create TransportDescription answer "
+ "because of incompatible security settings";
+ return NULL;
}
- } else if (require_transport_attributes && secure_ == SEC_REQUIRED) {
- // We require DTLS, but the other side didn't offer it. Fail.
- RTC_LOG(LS_WARNING) << "Failed to create TransportDescription answer "
- "because of incompatible security settings";
+ // This may be a bundled section, fingerprint may legitimately be missing.
+ return desc;
+ }
+ // Negotiate security params.
+ // The offer supports DTLS, so answer with DTLS.
+ RTC_CHECK(certificate_);
+ ConnectionRole role = CONNECTIONROLE_NONE;
+ // If the offer does not constrain the role, go with preference.
+ if (offer->connection_role == CONNECTIONROLE_ACTPASS) {
+ role = (options.prefer_passive_role) ? CONNECTIONROLE_PASSIVE
+ : CONNECTIONROLE_ACTIVE;
+ } else if (offer->connection_role == CONNECTIONROLE_ACTIVE) {
+ role = CONNECTIONROLE_PASSIVE;
+ } else if (offer->connection_role == CONNECTIONROLE_PASSIVE) {
+ role = CONNECTIONROLE_ACTIVE;
+ } else if (offer->connection_role == CONNECTIONROLE_NONE) {
+ // This case may be reached if a=setup is not present in the SDP.
+ RTC_LOG(LS_WARNING) << "Remote offer connection role is NONE, which is "
+ "a protocol violation";
+ role = (options.prefer_passive_role) ? CONNECTIONROLE_PASSIVE
+ : CONNECTIONROLE_ACTIVE;
+ } else {
+ RTC_LOG(LS_ERROR) << "Remote offer connection role is " << role
+ << " which is a protocol violation";
+ RTC_DCHECK_NOTREACHED();
+ return NULL;
+ }
+ if (!SetSecurityInfo(desc.get(), role)) {
return NULL;
}
-
return desc;
}
diff --git a/third_party/libwebrtc/p2p/base/transport_description_factory.h b/third_party/libwebrtc/p2p/base/transport_description_factory.h
index 11352f88b4..bd0cb9078e 100644
--- a/third_party/libwebrtc/p2p/base/transport_description_factory.h
+++ b/third_party/libwebrtc/p2p/base/transport_description_factory.h
@@ -43,15 +43,12 @@ class TransportDescriptionFactory {
const webrtc::FieldTrialsView& field_trials);
~TransportDescriptionFactory();
- SecurePolicy secure() const { return secure_; }
// The certificate to use when setting up DTLS.
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate() const {
return certificate_;
}
- // Specifies the transport security policy to use.
- void set_secure(SecurePolicy s) { secure_ = s; }
- // Specifies the certificate to use (only used when secure != SEC_DISABLED).
+ // Specifies the certificate to use
void set_certificate(rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
certificate_ = std::move(certificate);
}
@@ -76,12 +73,18 @@ class TransportDescriptionFactory {
IceCredentialsIterator* ice_credentials) const;
const webrtc::FieldTrialsView& trials() const { return field_trials_; }
+ // Functions for disabling encryption - test only!
+ // In insecure mode, the connection will accept a description without
+ // fingerprint, and will generate SDP even if certificate is not set.
+ // If certificate is set, it will accept a description both with and
+ // without fingerprint, but will generate a description with fingerprint.
+ bool insecure() const { return insecure_; }
+ void SetInsecureForTesting() { insecure_ = true; }
private:
bool SetSecurityInfo(TransportDescription* description,
ConnectionRole role) const;
-
- SecurePolicy secure_;
+ bool insecure_ = false;
rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
const webrtc::FieldTrialsView& field_trials_;
};
diff --git a/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc b/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc
index 0da5b7c294..0d38ac6d7b 100644
--- a/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc
+++ b/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc
@@ -33,6 +33,7 @@ using cricket::TransportDescriptionFactory;
using cricket::TransportOptions;
using ::testing::Contains;
using ::testing::Not;
+using ::testing::NotNull;
class TransportDescriptionFactoryTest : public ::testing::Test {
public:
@@ -43,7 +44,11 @@ class TransportDescriptionFactoryTest : public ::testing::Test {
cert1_(rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
new rtc::FakeSSLIdentity("User1")))),
cert2_(rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
- new rtc::FakeSSLIdentity("User2")))) {}
+ new rtc::FakeSSLIdentity("User2")))) {
+ // By default, certificates are supplied.
+ f1_.set_certificate(cert1_);
+ f2_.set_certificate(cert2_);
+ }
void CheckDesc(const TransportDescription* desc,
absl::string_view opt,
@@ -75,7 +80,12 @@ class TransportDescriptionFactoryTest : public ::testing::Test {
// in the offer and answer is changed.
// If `dtls` is true, the test verifies that the finger print is not changed.
void TestIceRestart(bool dtls) {
- SetDtls(dtls);
+ if (dtls) {
+ f1_.set_certificate(cert1_);
+ f2_.set_certificate(cert2_);
+ } else {
+ SetInsecure();
+ }
cricket::TransportOptions options;
// The initial offer / answer exchange.
std::unique_ptr<TransportDescription> offer =
@@ -102,6 +112,8 @@ class TransportDescriptionFactoryTest : public ::testing::Test {
void VerifyUfragAndPasswordChanged(bool dtls,
const TransportDescription* org_desc,
const TransportDescription* restart_desc) {
+ ASSERT_THAT(org_desc, NotNull());
+ ASSERT_THAT(restart_desc, NotNull());
EXPECT_NE(org_desc->ice_pwd, restart_desc->ice_pwd);
EXPECT_NE(org_desc->ice_ufrag, restart_desc->ice_ufrag);
EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
@@ -118,7 +130,9 @@ class TransportDescriptionFactoryTest : public ::testing::Test {
}
void TestIceRenomination(bool dtls) {
- SetDtls(dtls);
+ if (!dtls) {
+ SetInsecureNoDtls();
+ }
cricket::TransportOptions options;
// The initial offer / answer exchange.
@@ -148,16 +162,16 @@ class TransportDescriptionFactoryTest : public ::testing::Test {
}
protected:
- void SetDtls(bool dtls) {
- if (dtls) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f2_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
- f2_.set_certificate(cert2_);
- } else {
- f1_.set_secure(cricket::SEC_DISABLED);
- f2_.set_secure(cricket::SEC_DISABLED);
- }
+ // This will enable responding to non-DTLS requests.
+ void SetInsecure() {
+ f1_.SetInsecureForTesting();
+ f2_.SetInsecureForTesting();
+ }
+ // This will disable the ability to respond to DTLS requests.
+ void SetInsecureNoDtls() {
+ SetInsecure();
+ f1_.set_certificate(nullptr);
+ f2_.set_certificate(nullptr);
}
webrtc::test::ScopedKeyValueConfig field_trials_;
@@ -169,30 +183,18 @@ class TransportDescriptionFactoryTest : public ::testing::Test {
rtc::scoped_refptr<rtc::RTCCertificate> cert2_;
};
-TEST_F(TransportDescriptionFactoryTest, TestOfferDefault) {
- std::unique_ptr<TransportDescription> desc =
- f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
- CheckDesc(desc.get(), "", "", "", "");
-}
-
TEST_F(TransportDescriptionFactoryTest, TestOfferDtls) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
std::string digest_alg;
ASSERT_TRUE(
cert1_->GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg));
std::unique_ptr<TransportDescription> desc =
f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
CheckDesc(desc.get(), "", "", "", digest_alg);
- // Ensure it also works with SEC_REQUIRED.
- f1_.set_secure(cricket::SEC_REQUIRED);
- desc = f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
- CheckDesc(desc.get(), "", "", "", digest_alg);
}
// Test generating an offer with DTLS fails with no identity.
TEST_F(TransportDescriptionFactoryTest, TestOfferDtlsWithNoIdentity) {
- f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(nullptr);
std::unique_ptr<TransportDescription> desc =
f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
ASSERT_TRUE(desc.get() == NULL);
@@ -201,8 +203,6 @@ TEST_F(TransportDescriptionFactoryTest, TestOfferDtlsWithNoIdentity) {
// Test updating an offer with DTLS to pick ICE.
// The ICE credentials should stay the same in the new offer.
TEST_F(TransportDescriptionFactoryTest, TestOfferDtlsReofferDtls) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
std::string digest_alg;
ASSERT_TRUE(
cert1_->GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg));
@@ -215,19 +215,25 @@ TEST_F(TransportDescriptionFactoryTest, TestOfferDtlsReofferDtls) {
}
TEST_F(TransportDescriptionFactoryTest, TestAnswerDefault) {
+ std::string digest_alg;
+ ASSERT_TRUE(
+ cert1_->GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg));
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
ASSERT_TRUE(offer.get() != NULL);
std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
- CheckDesc(desc.get(), "", "", "", "");
+ CheckDesc(desc.get(), "", "", "", digest_alg);
desc = f2_.CreateAnswer(offer.get(), TransportOptions(), true, NULL,
&ice_credentials_);
- CheckDesc(desc.get(), "", "", "", "");
+ CheckDesc(desc.get(), "", "", "", digest_alg);
}
// Test that we can update an answer properly; ICE credentials shouldn't change.
TEST_F(TransportDescriptionFactoryTest, TestReanswer) {
+ std::string digest_alg;
+ ASSERT_TRUE(
+ cert1_->GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg));
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
ASSERT_TRUE(offer.get() != NULL);
@@ -237,13 +243,13 @@ TEST_F(TransportDescriptionFactoryTest, TestReanswer) {
std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
offer.get(), TransportOptions(), true, old_desc.get(), &ice_credentials_);
ASSERT_TRUE(desc.get() != NULL);
- CheckDesc(desc.get(), "", old_desc->ice_ufrag, old_desc->ice_pwd, "");
+ CheckDesc(desc.get(), "", old_desc->ice_ufrag, old_desc->ice_pwd, digest_alg);
}
// Test that we handle answering an offer with DTLS with no DTLS.
TEST_F(TransportDescriptionFactoryTest, TestAnswerDtlsToNoDtls) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
+ f2_.SetInsecureForTesting();
+ f2_.set_certificate(nullptr);
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
ASSERT_TRUE(offer.get() != NULL);
@@ -255,28 +261,25 @@ TEST_F(TransportDescriptionFactoryTest, TestAnswerDtlsToNoDtls) {
// Test that we handle answering an offer without DTLS if we have DTLS enabled,
// but fail if we require DTLS.
TEST_F(TransportDescriptionFactoryTest, TestAnswerNoDtlsToDtls) {
- f2_.set_secure(cricket::SEC_ENABLED);
- f2_.set_certificate(cert2_);
+ f1_.SetInsecureForTesting();
+ f1_.set_certificate(nullptr);
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
ASSERT_TRUE(offer.get() != NULL);
+ // Normal case.
std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
- CheckDesc(desc.get(), "", "", "", "");
- f2_.set_secure(cricket::SEC_REQUIRED);
+ ASSERT_TRUE(desc.get() == NULL);
+ // Insecure case.
+ f2_.SetInsecureForTesting();
desc = f2_.CreateAnswer(offer.get(), TransportOptions(), true, NULL,
&ice_credentials_);
- ASSERT_TRUE(desc.get() == NULL);
+ CheckDesc(desc.get(), "", "", "", "");
}
-// Test that we handle answering an DTLS offer with DTLS, both if we have
-// DTLS enabled and required.
+// Test that we handle answering an DTLS offer with DTLS,
+// even if we don't require DTLS.
TEST_F(TransportDescriptionFactoryTest, TestAnswerDtlsToDtls) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
-
- f2_.set_secure(cricket::SEC_ENABLED);
- f2_.set_certificate(cert2_);
// f2_ produces the answer that is being checked in this test, so the
// answer must contain fingerprint lines with cert2_'s digest algorithm.
std::string digest_alg2;
@@ -289,7 +292,8 @@ TEST_F(TransportDescriptionFactoryTest, TestAnswerDtlsToDtls) {
std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
CheckDesc(desc.get(), "", "", "", digest_alg2);
- f2_.set_secure(cricket::SEC_REQUIRED);
+
+ f2_.SetInsecureForTesting();
desc = f2_.CreateAnswer(offer.get(), TransportOptions(), true, NULL,
&ice_credentials_);
CheckDesc(desc.get(), "", "", "", digest_alg2);
@@ -325,6 +329,7 @@ TEST_F(TransportDescriptionFactoryTest, AddsTrickleIceOption) {
cricket::TransportOptions options;
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(options, nullptr, &ice_credentials_);
+ ASSERT_THAT(offer, NotNull());
EXPECT_TRUE(offer->HasOption("trickle"));
std::unique_ptr<TransportDescription> answer =
f2_.CreateAnswer(offer.get(), options, true, nullptr, &ice_credentials_);
@@ -359,11 +364,6 @@ TEST_F(TransportDescriptionFactoryTest, CreateAnswerIceCredentialsIterator) {
}
TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsActpassOffer) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
-
- f2_.set_secure(cricket::SEC_ENABLED);
- f2_.set_certificate(cert2_);
cricket::TransportOptions options;
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(options, nullptr, &ice_credentials_);
@@ -374,11 +374,6 @@ TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsActpassOffer) {
}
TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsActiveOffer) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
-
- f2_.set_secure(cricket::SEC_ENABLED);
- f2_.set_certificate(cert2_);
cricket::TransportOptions options;
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(options, nullptr, &ice_credentials_);
@@ -390,11 +385,6 @@ TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsActiveOffer) {
}
TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsPassiveOffer) {
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_certificate(cert1_);
-
- f2_.set_secure(cricket::SEC_ENABLED);
- f2_.set_certificate(cert2_);
cricket::TransportOptions options;
std::unique_ptr<TransportDescription> offer =
f1_.CreateOffer(options, nullptr, &ice_credentials_);
diff --git a/third_party/libwebrtc/p2p/base/turn_port.cc b/third_party/libwebrtc/p2p/base/turn_port.cc
index 1fb3b38bfd..bc35a2250a 100644
--- a/third_party/libwebrtc/p2p/base/turn_port.cc
+++ b/third_party/libwebrtc/p2p/base/turn_port.cc
@@ -22,6 +22,7 @@
#include "absl/types/optional.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/transport/stun.h"
+#include "api/turn_customizer.h"
#include "p2p/base/connection.h"
#include "p2p/base/p2p_constants.h"
#include "rtc_base/async_packet_socket.h"
diff --git a/third_party/libwebrtc/p2p/base/turn_port.h b/third_party/libwebrtc/p2p/base/turn_port.h
index b56f862e61..099d8b258a 100644
--- a/third_party/libwebrtc/p2p/base/turn_port.h
+++ b/third_party/libwebrtc/p2p/base/turn_port.h
@@ -25,7 +25,8 @@
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "p2p/base/port.h"
-#include "p2p/client/basic_port_allocator.h"
+#include "p2p/base/port_allocator.h"
+#include "p2p/client/relay_port_factory_interface.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/network/received_packet.h"
#include "rtc_base/ssl_certificate.h"
diff --git a/third_party/libwebrtc/p2p/client/basic_port_allocator.cc b/third_party/libwebrtc/p2p/client/basic_port_allocator.cc
index e95033efeb..cc38a66727 100644
--- a/third_party/libwebrtc/p2p/client/basic_port_allocator.cc
+++ b/third_party/libwebrtc/p2p/client/basic_port_allocator.cc
@@ -1483,7 +1483,7 @@ void AllocationSequence::CreateUDPPorts() {
}
if (port) {
- port->SetIceTiebreaker(session_->ice_tiebreaker());
+ port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
// If shared socket is enabled, STUN candidate will be allocated by the
// UDPPort.
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
@@ -1519,7 +1519,7 @@ void AllocationSequence::CreateTCPPorts() {
session_->allocator()->allow_tcp_listen(),
session_->allocator()->field_trials());
if (port) {
- port->SetIceTiebreaker(session_->ice_tiebreaker());
+ port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
session_->AddAllocatedPort(port.release(), this);
// Since TCPPort is not created using shared socket, `port` will not be
// added to the dequeue.
@@ -1549,7 +1549,7 @@ void AllocationSequence::CreateStunPorts() {
session_->allocator()->stun_candidate_keepalive_interval(),
session_->allocator()->field_trials());
if (port) {
- port->SetIceTiebreaker(session_->ice_tiebreaker());
+ port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
session_->AddAllocatedPort(port.release(), this);
// Since StunPort is not created using shared socket, `port` will not be
// added to the dequeue.
@@ -1652,7 +1652,7 @@ void AllocationSequence::CreateTurnPort(const RelayServerConfig& config,
}
}
RTC_DCHECK(port != NULL);
- port->SetIceTiebreaker(session_->ice_tiebreaker());
+ port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
session_->AddAllocatedPort(port.release(), this);
}
}
diff --git a/third_party/libwebrtc/p2p/client/basic_port_allocator_unittest.cc b/third_party/libwebrtc/p2p/client/basic_port_allocator_unittest.cc
index 0c3bf6bc23..f77040d128 100644
--- a/third_party/libwebrtc/p2p/client/basic_port_allocator_unittest.cc
+++ b/third_party/libwebrtc/p2p/client/basic_port_allocator_unittest.cc
@@ -112,8 +112,6 @@ static const char kTurnPassword[] = "test";
// Add some margin of error for slow bots.
static const int kStunTimeoutMs = cricket::STUN_TOTAL_TIMEOUT;
-constexpr uint64_t kTiebreakerDefault = 44444;
-
namespace {
void CheckStunKeepaliveIntervalOfAllReadyPorts(
@@ -176,7 +174,6 @@ class BasicPortAllocatorTestBase : public ::testing::Test,
&network_manager_, &socket_factory_, stun_servers, &field_trials_);
allocator_->Initialize();
allocator_->set_step_delay(kMinimumStepDelay);
- allocator_->SetIceTiebreaker(kTiebreakerDefault);
webrtc::metrics::Reset();
}
@@ -214,7 +211,6 @@ class BasicPortAllocatorTestBase : public ::testing::Test,
allocator_.reset(
new BasicPortAllocator(&network_manager_, &socket_factory_));
allocator_->Initialize();
- allocator_->SetIceTiebreaker(kTiebreakerDefault);
allocator_->set_step_delay(kMinimumStepDelay);
}
// Endpoint is behind a NAT, with STUN specified.
@@ -299,7 +295,6 @@ class BasicPortAllocatorTestBase : public ::testing::Test,
this, &BasicPortAllocatorTestBase::OnCandidatesRemoved);
session->SignalCandidatesAllocationDone.connect(
this, &BasicPortAllocatorTestBase::OnCandidatesAllocationDone);
- session->set_ice_tiebreaker(kTiebreakerDefault);
return session;
}
@@ -328,17 +323,6 @@ class BasicPortAllocatorTestBase : public ::testing::Test,
});
}
- static int CountCandidates(const std::vector<Candidate>& candidates,
- absl::string_view type,
- absl::string_view proto,
- const SocketAddress& addr) {
- return absl::c_count_if(
- candidates, [type, proto, addr](const Candidate& c) {
- return c.type() == type && c.protocol() == proto &&
- AddressMatch(c.address(), addr);
- });
- }
-
// Find a candidate and return it.
static bool FindCandidate(const std::vector<Candidate>& candidates,
absl::string_view type,
@@ -1237,7 +1221,7 @@ TEST_F(BasicPortAllocatorTest, TestGetAllPortsPortRange) {
int num_nonrelay_candidates = 0;
for (const Candidate& candidate : candidates_) {
// Check the port number for the UDP/STUN/TCP port objects.
- if (candidate.type() != RELAY_PORT_TYPE) {
+ if (!candidate.is_relay()) {
EXPECT_TRUE(CheckPort(candidate.address(), kMinPort, kMaxPort));
++num_nonrelay_candidates;
}
@@ -1272,9 +1256,11 @@ TEST_F(BasicPortAllocatorTest, TestGetAllPortsNoAdapters) {
rtc::SocketAddress(kNatUdpAddr.ipaddr(), 0)));
// Again, two TURN candidates, using UDP/TCP for the first hop to the TURN
// server.
- EXPECT_EQ(2,
- CountCandidates(candidates_, "relay", "udp",
- rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)));
+ rtc::SocketAddress addr(kTurnUdpExtAddr.ipaddr(), 0);
+ EXPECT_EQ(2, absl::c_count_if(candidates_, [&](const Candidate& c) {
+ return c.is_relay() && c.protocol() == "udp" &&
+ AddressMatch(c.address(), addr);
+ }));
}
// Test that when enumeration is disabled, we should not have any ports when
@@ -1548,7 +1534,7 @@ TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithRelayOnly) {
EXPECT_EQ(1U, candidates_.size());
EXPECT_EQ(1U, ports_.size()); // Only Relay port will be in ready state.
- EXPECT_EQ(std::string(RELAY_PORT_TYPE), candidates_[0].type());
+ EXPECT_TRUE(candidates_[0].is_relay());
EXPECT_EQ(
candidates_[0].related_address(),
rtc::EmptySocketAddressWithFamily(candidates_[0].address().family()));
@@ -1565,7 +1551,7 @@ TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithHostOnly) {
EXPECT_EQ(2U, candidates_.size()); // Host UDP/TCP candidates only.
EXPECT_EQ(2U, ports_.size()); // UDP/TCP ports only.
for (const Candidate& candidate : candidates_) {
- EXPECT_EQ(std::string(LOCAL_PORT_TYPE), candidate.type());
+ EXPECT_TRUE(candidate.is_local());
}
}
@@ -1584,7 +1570,7 @@ TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithReflexiveOnly) {
// port with STUN candidate will be sent outside.
EXPECT_EQ(1U, candidates_.size()); // Only STUN candidate.
EXPECT_EQ(1U, ports_.size()); // Only UDP port will be in ready state.
- EXPECT_EQ(std::string(STUN_PORT_TYPE), candidates_[0].type());
+ EXPECT_TRUE(candidates_[0].is_stun());
EXPECT_EQ(
candidates_[0].related_address(),
rtc::EmptySocketAddressWithFamily(candidates_[0].address().family()));
@@ -1603,7 +1589,7 @@ TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithReflexiveOnlyAndNoNAT) {
EXPECT_EQ(2U, candidates_.size()); // Local UDP + TCP candidate.
EXPECT_EQ(2U, ports_.size()); // UDP and TCP ports will be in ready state.
for (const Candidate& candidate : candidates_) {
- EXPECT_EQ(std::string(LOCAL_PORT_TYPE), candidate.type());
+ EXPECT_TRUE(candidate.is_local());
}
}
@@ -2174,7 +2160,7 @@ TEST_F(BasicPortAllocatorTest, TestSetCandidateFilterAfterCandidatesGathered) {
}
for (const Candidate& candidate : candidates) {
// Expect only relay candidates now that the filter is applied.
- EXPECT_EQ(std::string(RELAY_PORT_TYPE), candidate.type());
+ EXPECT_TRUE(candidate.is_relay());
// Expect that the raddr is emptied due to the CF_RELAY filter.
EXPECT_EQ(candidate.related_address(),
rtc::EmptySocketAddressWithFamily(candidate.address().family()));
@@ -2210,21 +2196,21 @@ TEST_F(BasicPortAllocatorTest,
session_->SetCandidateFilter(CF_RELAY);
ASSERT_EQ_SIMULATED_WAIT(1u, candidates_.size(), kDefaultAllocationTimeout,
fake_clock);
- EXPECT_EQ(RELAY_PORT_TYPE, candidates_.back().type());
+ EXPECT_TRUE(candidates_.back().is_relay());
EXPECT_EQ(1u, ports_.size());
// Surface the srflx candidate previously gathered but not signaled.
session_->SetCandidateFilter(CF_RELAY | CF_REFLEXIVE);
ASSERT_EQ_SIMULATED_WAIT(2u, candidates_.size(), kDefaultAllocationTimeout,
fake_clock);
- EXPECT_EQ(STUN_PORT_TYPE, candidates_.back().type());
+ EXPECT_TRUE(candidates_.back().is_stun());
EXPECT_EQ(2u, ports_.size());
// Surface the srflx candidate previously gathered but not signaled.
session_->SetCandidateFilter(CF_ALL);
ASSERT_EQ_SIMULATED_WAIT(3u, candidates_.size(), kDefaultAllocationTimeout,
fake_clock);
- EXPECT_EQ(LOCAL_PORT_TYPE, candidates_.back().type());
+ EXPECT_TRUE(candidates_.back().is_local());
EXPECT_EQ(2u, ports_.size());
}
@@ -2260,21 +2246,21 @@ TEST_F(
session_->SetCandidateFilter(CF_RELAY);
EXPECT_EQ_SIMULATED_WAIT(1u, candidates_.size(), kDefaultAllocationTimeout,
fake_clock);
- EXPECT_EQ(RELAY_PORT_TYPE, candidates_.back().type());
+ EXPECT_TRUE(candidates_.back().is_relay());
EXPECT_EQ(1u, ports_.size());
// Surface the srflx candidate previously gathered but not signaled.
session_->SetCandidateFilter(CF_REFLEXIVE);
EXPECT_EQ_SIMULATED_WAIT(2u, candidates_.size(), kDefaultAllocationTimeout,
fake_clock);
- EXPECT_EQ(STUN_PORT_TYPE, candidates_.back().type());
+ EXPECT_TRUE(candidates_.back().is_stun());
EXPECT_EQ(2u, ports_.size());
// Surface the host candidate previously gathered but not signaled.
session_->SetCandidateFilter(CF_HOST);
EXPECT_EQ_SIMULATED_WAIT(3u, candidates_.size(), kDefaultAllocationTimeout,
fake_clock);
- EXPECT_EQ(LOCAL_PORT_TYPE, candidates_.back().type());
+ EXPECT_TRUE(candidates_.back().is_local());
// We use a shared socket and cricket::UDPPort handles the srflx candidate.
EXPECT_EQ(2u, ports_.size());
}
diff --git a/third_party/libwebrtc/pc/BUILD.gn b/third_party/libwebrtc/pc/BUILD.gn
index e351748485..6f21d00bc9 100644
--- a/third_party/libwebrtc/pc/BUILD.gn
+++ b/third_party/libwebrtc/pc/BUILD.gn
@@ -87,6 +87,7 @@ rtc_source_set("channel") {
"../media:rtp_utils",
"../media:stream_params",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:dtls_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:async_packet_socket",
"../rtc_base:checks",
@@ -134,6 +135,8 @@ rtc_source_set("dtls_srtp_transport") {
"../api:dtls_transport_interface",
"../api:libjingle_peerconnection_api",
"../api:rtc_error",
+ "../p2p:dtls_transport_internal",
+ "../p2p:packet_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:buffer",
"../rtc_base:checks",
@@ -157,6 +160,8 @@ rtc_source_set("dtls_transport") {
"../api:make_ref_counted",
"../api:scoped_refptr",
"../api:sequence_checker",
+ "../p2p:dtls_transport",
+ "../p2p:dtls_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:logging",
@@ -213,7 +218,6 @@ rtc_source_set("jsep_transport") {
":rtp_transport_internal",
":sctp_transport",
":session_description",
- ":srtp_filter",
":srtp_transport",
":transport_stats",
"../api:array_view",
@@ -225,7 +229,14 @@ rtc_source_set("jsep_transport") {
"../api:sequence_checker",
"../api/transport:datagram_transport_interface",
"../media:rtc_data_sctp_transport_internal",
+ "../p2p:dtls_transport",
+ "../p2p:dtls_transport_internal",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:p2p_transport_channel",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_info",
"../rtc_base:checks",
"../rtc_base:copy_on_write_buffer",
"../rtc_base:event_tracer",
@@ -249,6 +260,7 @@ rtc_source_set("jsep_transport_collection") {
":session_description",
"../api:libjingle_peerconnection_api",
"../api:sequence_checker",
+ "../p2p:p2p_constants",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:logging",
@@ -295,7 +307,19 @@ rtc_source_set("jsep_transport_controller") {
"../api/transport:enums",
"../api/transport:sctp_transport_factory_interface",
"../media:rtc_data_sctp_transport_internal",
+ "../p2p:connection",
+ "../p2p:dtls_transport",
+ "../p2p:dtls_transport_factory",
+ "../p2p:dtls_transport_internal",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:p2p_transport_channel",
+ "../p2p:packet_transport_internal",
+ "../p2p:port",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_info",
"../rtc_base:callback_list",
"../rtc_base:checks",
"../rtc_base:copy_on_write_buffer",
@@ -347,7 +371,12 @@ rtc_source_set("media_session") {
"../media:rtc_media_base",
"../media:rtc_sdp_video_format_utils",
"../media:stream_params",
+ "../p2p:ice_credentials_iterator",
+ "../p2p:p2p_constants",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_description_factory",
+ "../p2p:transport_info",
"../rtc_base:checks",
"../rtc_base:logging",
"../rtc_base:ssl",
@@ -396,6 +425,7 @@ rtc_source_set("peer_connection_proxy") {
deps = [
":proxy",
"../api:libjingle_peerconnection_api",
+ "../api/transport:bandwidth_estimation_settings",
]
}
@@ -459,6 +489,7 @@ rtc_source_set("rtp_transport") {
"../media:rtc_media_base",
"../media:rtp_utils",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:packet_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:async_packet_socket",
"../rtc_base:checks",
@@ -484,6 +515,7 @@ rtc_source_set("rtp_transport_internal") {
deps = [
":session_description",
"../call:rtp_receiver",
+ "../p2p:ice_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:callback_list",
"../rtc_base:network_route",
@@ -505,6 +537,7 @@ rtc_source_set("sctp_transport") {
"../api:sequence_checker",
"../api/transport:datagram_transport_interface",
"../media:rtc_data_sctp_transport_internal",
+ "../p2p:dtls_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:logging",
@@ -539,29 +572,6 @@ rtc_source_set("sctp_utils") {
]
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
-rtc_source_set("srtp_filter") {
- visibility = [ ":*" ]
- sources = [
- "srtp_filter.cc",
- "srtp_filter.h",
- ]
- deps = [
- ":session_description",
- "../api:array_view",
- "../api:libjingle_peerconnection_api",
- "../api:sequence_checker",
- "../rtc_base:buffer",
- "../rtc_base:logging",
- "../rtc_base:ssl",
- "../rtc_base:zero_memory",
- "../rtc_base/third_party/base64",
- ]
- absl_deps = [
- "//third_party/abseil-cpp/absl/strings",
- "//third_party/abseil-cpp/absl/types:optional",
- ]
-}
-
rtc_source_set("srtp_session") {
visibility = [ ":*" ]
sources = [
@@ -608,6 +618,7 @@ rtc_source_set("srtp_transport") {
"../media:rtc_media_base",
"../media:rtp_utils",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:packet_transport_internal",
"../p2p:rtc_p2p",
"../rtc_base:async_packet_socket",
"../rtc_base:buffer",
@@ -636,6 +647,10 @@ rtc_source_set("transport_stats") {
deps = [
"../api:dtls_transport_interface",
"../api:libjingle_peerconnection_api",
+ "../p2p:connection",
+ "../p2p:dtls_transport_internal",
+ "../p2p:ice_transport_internal",
+ "../p2p:port",
"../p2p:rtc_p2p",
"../rtc_base:ssl",
]
@@ -693,6 +708,8 @@ rtc_source_set("session_description") {
"../media:rtc_media_base",
"../media:stream_params",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_info",
"../rtc_base:checks",
"../rtc_base:socket_address",
"../rtc_base:stringutils",
@@ -802,6 +819,7 @@ rtc_library("connection_context") {
"../api/transport:sctp_transport_factory_interface",
"../media:rtc_data_sctp_transport_factory",
"../media:rtc_media_base",
+ "../p2p:basic_packet_socket_factory",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:macromagic",
@@ -911,6 +929,11 @@ rtc_source_set("rtc_stats_collector") {
"../modules/audio_device",
"../modules/audio_processing:audio_processing_statistics",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:connection",
+ "../p2p:connection_info",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:port",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:event_tracer",
@@ -945,6 +968,7 @@ rtc_source_set("rtc_stats_traversal") {
"../api:scoped_refptr",
"../rtc_base:checks",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_source_set("sdp_offer_answer") {
@@ -1003,7 +1027,16 @@ rtc_source_set("sdp_offer_answer") {
"../media:rid_description",
"../media:rtc_media_base",
"../media:stream_params",
+ "../p2p:connection",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:p2p_transport_channel",
+ "../p2p:port",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_description_factory",
+ "../p2p:transport_info",
"../rtc_base:checks",
"../rtc_base:event_tracer",
"../rtc_base:logging",
@@ -1108,7 +1141,18 @@ rtc_source_set("peer_connection") {
"../media:rtc_media_config",
"../media:stream_params",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:basic_async_resolver_factory",
+ "../p2p:connection",
+ "../p2p:connection_info",
+ "../p2p:dtls_transport_internal",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:p2p_transport_channel",
+ "../p2p:port",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_info",
"../rtc_base:checks",
"../rtc_base:copy_on_write_buffer",
"../rtc_base:event_tracer",
@@ -1164,6 +1208,7 @@ rtc_source_set("sdp_utils") {
":session_description",
"../api:libjingle_peerconnection_api",
"../p2p:rtc_p2p",
+ "../p2p:transport_info",
"../rtc_base:checks",
"../rtc_base/system:rtc_export",
]
@@ -1199,6 +1244,11 @@ rtc_source_set("legacy_stats_collector") {
"../media:media_channel",
"../media:rtc_media_base",
"../modules/audio_processing:audio_processing_statistics",
+ "../p2p:connection",
+ "../p2p:connection_info",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:port",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:event_tracer",
@@ -1272,7 +1322,15 @@ rtc_source_set("webrtc_sdp") {
"../media:rtc_media_base",
"../media:rtp_utils",
"../media:stream_params",
+ "../p2p:candidate_pair_interface",
+ "../p2p:connection",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
+ "../p2p:port",
+ "../p2p:port_interface",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_info",
"../rtc_base:checks",
"../rtc_base:ip_address",
"../rtc_base:logging",
@@ -1307,6 +1365,8 @@ rtc_source_set("webrtc_session_description_factory") {
"../api:sequence_checker",
"../api/task_queue",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_description_factory",
"../rtc_base:checks",
"../rtc_base:logging",
"../rtc_base:rtc_certificate_generator",
@@ -1333,6 +1393,10 @@ rtc_library("ice_server_parsing") {
deps = [
"../api:libjingle_peerconnection_api",
"../api:rtc_error",
+ "../p2p:connection",
+ "../p2p:port",
+ "../p2p:port_allocator",
+ "../p2p:port_interface",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:ip_address",
@@ -1395,6 +1459,11 @@ rtc_source_set("peer_connection_factory") {
"../call:rtp_interfaces",
"../call:rtp_sender",
"../media:rtc_media_base",
+ "../p2p:basic_packet_socket_factory",
+ "../p2p:basic_port_allocator",
+ "../p2p:connection",
+ "../p2p:default_ice_transport_factory",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
"../pc:audio_track",
"../pc:connection_context",
@@ -1955,7 +2024,6 @@ if (rtc_include_tests && !build_with_chromium) {
"rtp_transport_unittest.cc",
"sctp_transport_unittest.cc",
"session_description_unittest.cc",
- "srtp_filter_unittest.cc",
"srtp_session_unittest.cc",
"srtp_transport_unittest.cc",
"test/rtp_transport_test_util.h",
@@ -1990,7 +2058,6 @@ if (rtc_include_tests && !build_with_chromium) {
":rtp_transport_internal",
":sctp_transport",
":session_description",
- ":srtp_filter",
":srtp_session",
":srtp_transport",
":used_ids",
@@ -2025,10 +2092,18 @@ if (rtc_include_tests && !build_with_chromium) {
"../media:rtc_media_base",
"../media:rtc_media_tests_utils",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:candidate_pair_interface",
+ "../p2p:dtls_transport_factory",
+ "../p2p:dtls_transport_internal",
"../p2p:fake_ice_transport",
"../p2p:fake_port_allocator",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
"../p2p:p2p_test_utils",
+ "../p2p:packet_transport_internal",
"../p2p:rtc_p2p",
+ "../p2p:transport_description",
+ "../p2p:transport_info",
"../rtc_base:async_packet_socket",
"../rtc_base:buffer",
"../rtc_base:byte_order",
@@ -2110,7 +2185,11 @@ if (rtc_include_tests && !build_with_chromium) {
"../media:rtc_media_tests_utils",
"../modules/audio_device:audio_device_api",
"../modules/audio_processing:api",
+ "../p2p:basic_port_allocator",
+ "../p2p:connection",
"../p2p:p2p_test_utils",
+ "../p2p:port_allocator",
+ "../p2p:port_interface",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:gunit_helpers",
@@ -2161,8 +2240,11 @@ if (rtc_include_tests && !build_with_chromium) {
"../api:libjingle_peerconnection_api",
"../api:scoped_refptr",
"../api/units:time_delta",
+ "../p2p:connection",
"../p2p:p2p_server_utils",
"../p2p:p2p_test_utils",
+ "../p2p:port_allocator",
+ "../p2p:port_interface",
"../p2p:rtc_p2p",
"../rtc_base:gunit_helpers",
"../rtc_base:logging",
@@ -2342,8 +2424,19 @@ if (rtc_include_tests && !build_with_chromium) {
"../modules/audio_device:audio_device_api",
"../modules/audio_processing:audio_processing_statistics",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:basic_port_allocator",
+ "../p2p:connection",
+ "../p2p:connection_info",
+ "../p2p:dtls_transport_internal",
"../p2p:fake_port_allocator",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
"../p2p:p2p_server_utils",
+ "../p2p:port",
+ "../p2p:port_allocator",
+ "../p2p:port_interface",
+ "../p2p:transport_description",
+ "../p2p:transport_info",
"../rtc_base:byte_buffer",
"../rtc_base:checks",
"../rtc_base:copy_on_write_buffer",
@@ -2552,10 +2645,17 @@ if (rtc_include_tests && !build_with_chromium) {
"../modules/audio_processing:audio_processing_statistics",
"../modules/audio_processing:audioproc_test_utils",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:basic_port_allocator",
+ "../p2p:connection",
"../p2p:fake_ice_transport",
"../p2p:fake_port_allocator",
+ "../p2p:ice_transport_internal",
+ "../p2p:p2p_constants",
"../p2p:p2p_server_utils",
"../p2p:p2p_test_utils",
+ "../p2p:port",
+ "../p2p:port_allocator",
+ "../p2p:port_interface",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:gunit_helpers",
@@ -2702,8 +2802,10 @@ if (rtc_include_tests && !build_with_chromium) {
"../modules/audio_processing",
"../modules/audio_processing:api",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../p2p:connection",
"../p2p:fake_port_allocator",
"../p2p:p2p_test_utils",
+ "../p2p:port_allocator",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:gunit_helpers",
diff --git a/third_party/libwebrtc/pc/dtls_srtp_transport.h b/third_party/libwebrtc/pc/dtls_srtp_transport.h
index 995809ed4b..654eb2f628 100644
--- a/third_party/libwebrtc/pc/dtls_srtp_transport.h
+++ b/third_party/libwebrtc/pc/dtls_srtp_transport.h
@@ -16,7 +16,6 @@
#include <vector>
#include "absl/types/optional.h"
-#include "api/crypto_params.h"
#include "api/dtls_transport_interface.h"
#include "api/rtc_error.h"
#include "p2p/base/dtls_transport_internal.h"
diff --git a/third_party/libwebrtc/pc/jsep_transport.cc b/third_party/libwebrtc/pc/jsep_transport.cc
index 2398a0ad2d..faff4e8cf4 100644
--- a/third_party/libwebrtc/pc/jsep_transport.cc
+++ b/third_party/libwebrtc/pc/jsep_transport.cc
@@ -36,12 +36,10 @@ JsepTransportDescription::JsepTransportDescription() {}
JsepTransportDescription::JsepTransportDescription(
bool rtcp_mux_enabled,
- const std::vector<CryptoParams>& cryptos,
const std::vector<int>& encrypted_header_extension_ids,
int rtp_abs_sendtime_extn_id,
const TransportDescription& transport_desc)
: rtcp_mux_enabled(rtcp_mux_enabled),
- cryptos(cryptos),
encrypted_header_extension_ids(encrypted_header_extension_ids),
rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id),
transport_desc(transport_desc) {}
@@ -49,7 +47,6 @@ JsepTransportDescription::JsepTransportDescription(
JsepTransportDescription::JsepTransportDescription(
const JsepTransportDescription& from)
: rtcp_mux_enabled(from.rtcp_mux_enabled),
- cryptos(from.cryptos),
encrypted_header_extension_ids(from.encrypted_header_extension_ids),
rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id),
transport_desc(from.transport_desc) {}
@@ -62,7 +59,6 @@ JsepTransportDescription& JsepTransportDescription::operator=(
return *this;
}
rtcp_mux_enabled = from.rtcp_mux_enabled;
- cryptos = from.cryptos;
encrypted_header_extension_ids = from.encrypted_header_extension_ids;
rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id;
transport_desc = from.transport_desc;
@@ -167,17 +163,7 @@ webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
"Failed to setup RTCP mux.");
}
- // If doing SDES, setup the SDES crypto parameters.
- if (sdes_transport_) {
- RTC_DCHECK(!unencrypted_rtp_transport_);
- RTC_DCHECK(!dtls_srtp_transport_);
- if (!SetSdes(jsep_description.cryptos,
- jsep_description.encrypted_header_extension_ids, type,
- ContentSource::CS_LOCAL)) {
- return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
- "Failed to setup SDES crypto parameters.");
- }
- } else if (dtls_srtp_transport_) {
+ if (dtls_srtp_transport_) {
RTC_DCHECK(!unencrypted_rtp_transport_);
RTC_DCHECK(!sdes_transport_);
dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
@@ -254,19 +240,7 @@ webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
"Failed to setup RTCP mux.");
}
- // If doing SDES, setup the SDES crypto parameters.
- if (sdes_transport_) {
- RTC_DCHECK(!unencrypted_rtp_transport_);
- RTC_DCHECK(!dtls_srtp_transport_);
- if (!SetSdes(jsep_description.cryptos,
- jsep_description.encrypted_header_extension_ids, type,
- ContentSource::CS_REMOTE)) {
- return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
- "Failed to setup SDES crypto parameters.");
- }
- sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
- jsep_description.rtp_abs_sendtime_extn_id);
- } else if (dtls_srtp_transport_) {
+ if (dtls_srtp_transport_) {
RTC_DCHECK(!unencrypted_rtp_transport_);
RTC_DCHECK(!sdes_transport_);
dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
@@ -474,51 +448,6 @@ void JsepTransport::ActivateRtcpMux() {
rtcp_mux_active_callback_();
}
-bool JsepTransport::SetSdes(const std::vector<CryptoParams>& cryptos,
- const std::vector<int>& encrypted_extension_ids,
- webrtc::SdpType type,
- ContentSource source) {
- RTC_DCHECK_RUN_ON(network_thread_);
- bool ret = false;
- ret = sdes_negotiator_.Process(cryptos, type, source);
- if (!ret) {
- return ret;
- }
-
- if (source == ContentSource::CS_LOCAL) {
- recv_extension_ids_ = encrypted_extension_ids;
- } else {
- send_extension_ids_ = encrypted_extension_ids;
- }
-
- // If setting an SDES answer succeeded, apply the negotiated parameters
- // to the SRTP transport.
- if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
- if (sdes_negotiator_.send_crypto_suite() &&
- sdes_negotiator_.recv_crypto_suite()) {
- RTC_DCHECK(send_extension_ids_);
- RTC_DCHECK(recv_extension_ids_);
- ret = sdes_transport_->SetRtpParams(
- *(sdes_negotiator_.send_crypto_suite()),
- sdes_negotiator_.send_key().data(),
- static_cast<int>(sdes_negotiator_.send_key().size()),
- *(send_extension_ids_), *(sdes_negotiator_.recv_crypto_suite()),
- sdes_negotiator_.recv_key().data(),
- static_cast<int>(sdes_negotiator_.recv_key().size()),
- *(recv_extension_ids_));
- } else {
- RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
- if (type == SdpType::kAnswer) {
- // Explicitly reset the `sdes_transport_` if no crypto param is
- // provided in the answer. No need to call `ResetParams()` for
- // `sdes_negotiator_` because it resets the params inside `SetAnswer`.
- sdes_transport_->ResetParams();
- }
- }
- }
- return ret;
-}
-
webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
SdpType local_description_type) {
RTC_DCHECK_RUN_ON(network_thread_);
diff --git a/third_party/libwebrtc/pc/jsep_transport.h b/third_party/libwebrtc/pc/jsep_transport.h
index f2643070a1..af0c797fc8 100644
--- a/third_party/libwebrtc/pc/jsep_transport.h
+++ b/third_party/libwebrtc/pc/jsep_transport.h
@@ -19,7 +19,6 @@
#include "absl/types/optional.h"
#include "api/candidate.h"
-#include "api/crypto_params.h"
#include "api/ice_transport_interface.h"
#include "api/jsep.h"
#include "api/rtc_error.h"
@@ -40,7 +39,6 @@
#include "pc/rtp_transport_internal.h"
#include "pc/sctp_transport.h"
#include "pc/session_description.h"
-#include "pc/srtp_filter.h"
#include "pc/srtp_transport.h"
#include "pc/transport_stats.h"
#include "rtc_base/checks.h"
@@ -59,7 +57,6 @@ struct JsepTransportDescription {
JsepTransportDescription();
JsepTransportDescription(
bool rtcp_mux_enabled,
- const std::vector<CryptoParams>& cryptos,
const std::vector<int>& encrypted_header_extension_ids,
int rtp_abs_sendtime_extn_id,
const TransportDescription& transport_description);
@@ -69,7 +66,6 @@ struct JsepTransportDescription {
JsepTransportDescription& operator=(const JsepTransportDescription& from);
bool rtcp_mux_enabled = true;
- std::vector<CryptoParams> cryptos;
std::vector<int> encrypted_header_extension_ids;
int rtp_abs_sendtime_extn_id = -1;
// TODO(zhihuang): Add the ICE and DTLS related variables and methods from
@@ -243,11 +239,6 @@ class JsepTransport {
void ActivateRtcpMux() RTC_RUN_ON(network_thread_);
- bool SetSdes(const std::vector<CryptoParams>& cryptos,
- const std::vector<int>& encrypted_extension_ids,
- webrtc::SdpType type,
- ContentSource source);
-
// Negotiates and sets the DTLS parameters based on the current local and
// remote transport description, such as the DTLS role to use, and whether
// DTLS should be activated.
@@ -310,7 +301,6 @@ class JsepTransport {
const rtc::scoped_refptr<webrtc::SctpTransport> sctp_transport_;
- SrtpFilter sdes_negotiator_ RTC_GUARDED_BY(network_thread_);
RtcpMuxFilter rtcp_mux_negotiator_ RTC_GUARDED_BY(network_thread_);
// Cache the encrypted header extension IDs for SDES negoitation.
diff --git a/third_party/libwebrtc/pc/jsep_transport_controller.cc b/third_party/libwebrtc/pc/jsep_transport_controller.cc
index d5d1cd24a9..d5eb0c633d 100644
--- a/third_party/libwebrtc/pc/jsep_transport_controller.cc
+++ b/third_party/libwebrtc/pc/jsep_transport_controller.cc
@@ -55,6 +55,7 @@ JsepTransportController::JsepTransportController(
}),
config_(std::move(config)),
active_reset_srtp_params_(config.active_reset_srtp_params),
+ ice_tiebreaker_(port_allocator ? port_allocator->ice_tiebreaker() : 0),
bundles_(config.bundle_policy) {
// The `transport_observer` is assumed to be non-null.
RTC_DCHECK(config_.transport_observer);
@@ -62,9 +63,6 @@ JsepTransportController::JsepTransportController(
RTC_DCHECK(config_.ice_transport_factory);
RTC_DCHECK(config_.on_dtls_handshake_error_);
RTC_DCHECK(config_.field_trials);
- if (port_allocator_) {
- port_allocator_->SetIceTiebreaker(ice_tiebreaker_);
- }
}
JsepTransportController::~JsepTransportController() {
@@ -951,8 +949,8 @@ JsepTransportController::CreateJsepTransportDescription(
: content_desc->rtcp_mux();
return cricket::JsepTransportDescription(
- rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids,
- rtp_abs_sendtime_extn_id, transport_info.description);
+ rtcp_mux_enabled, encrypted_extension_ids, rtp_abs_sendtime_extn_id,
+ transport_info.description);
}
std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
@@ -1058,12 +1056,6 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
if (transport) {
return RTCError::OK();
}
- const cricket::MediaContentDescription* content_desc =
- content_info.media_description();
- if (certificate_ && !content_desc->cryptos().empty()) {
- return RTCError(RTCErrorType::INVALID_PARAMETER,
- "SDES and DTLS-SRTP cannot be enabled at the same time.");
- }
rtc::scoped_refptr<IceTransportInterface> ice =
CreateIceTransport(content_info.name, /*rtcp=*/false);
@@ -1090,10 +1082,6 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
<< "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
- } else if (!content_desc->cryptos().empty()) {
- sdes_transport = CreateSdesTransport(
- content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
- RTC_LOG(LS_INFO) << "Creating SdesTransport.";
} else {
RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
dtls_srtp_transport = CreateDtlsSrtpTransport(
@@ -1214,7 +1202,7 @@ void JsepTransportController::OnTransportCandidateGathered_n(
cricket::IceTransportInternal* transport,
const cricket::Candidate& candidate) {
// We should never signal peer-reflexive candidates.
- if (candidate.type() == cricket::PRFLX_PORT_TYPE) {
+ if (candidate.is_prflx()) {
RTC_DCHECK_NOTREACHED();
return;
}
diff --git a/third_party/libwebrtc/pc/jsep_transport_controller.h b/third_party/libwebrtc/pc/jsep_transport_controller.h
index 448844ac79..7f06c22969 100644
--- a/third_party/libwebrtc/pc/jsep_transport_controller.h
+++ b/third_party/libwebrtc/pc/jsep_transport_controller.h
@@ -507,7 +507,7 @@ class JsepTransportController : public sigslot::has_slots<> {
cricket::IceConfig ice_config_;
cricket::IceRole ice_role_ = cricket::ICEROLE_CONTROLLING;
- uint64_t ice_tiebreaker_ = rtc::CreateRandomId64();
+ uint64_t ice_tiebreaker_;
rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
BundleManager bundles_;
diff --git a/third_party/libwebrtc/pc/jsep_transport_unittest.cc b/third_party/libwebrtc/pc/jsep_transport_unittest.cc
index f057d37a0d..18dd2d8896 100644
--- a/third_party/libwebrtc/pc/jsep_transport_unittest.cc
+++ b/third_party/libwebrtc/pc/jsep_transport_unittest.cc
@@ -48,11 +48,6 @@ static const char kIceUfrag2[] = "U002";
static const char kIcePwd2[] = "TESTIEPWD00000000000002";
static const char kTransportName[] = "Test Transport";
-enum class SrtpMode {
- kSdes,
- kDtlsSrtp,
-};
-
struct NegotiateRoleParams {
ConnectionRole local_role;
ConnectionRole remote_role;
@@ -110,8 +105,7 @@ class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> {
// Create a new JsepTransport with a FakeDtlsTransport and a
// FakeIceTransport.
- std::unique_ptr<JsepTransport> CreateJsepTransport2(bool rtcp_mux_enabled,
- SrtpMode srtp_mode) {
+ std::unique_ptr<JsepTransport> CreateJsepTransport2(bool rtcp_mux_enabled) {
auto ice_internal = std::make_unique<FakeIceTransport>(
kTransportName, ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls_transport =
@@ -131,19 +125,8 @@ class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> {
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport;
std::unique_ptr<webrtc::SrtpTransport> sdes_transport;
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport;
- switch (srtp_mode) {
- case SrtpMode::kSdes:
- sdes_transport = CreateSdesTransport(rtp_dtls_transport.get(),
- rtcp_dtls_transport.get());
- sdes_transport_ = sdes_transport.get();
- break;
- case SrtpMode::kDtlsSrtp:
dtls_srtp_transport = CreateDtlsSrtpTransport(
rtp_dtls_transport.get(), rtcp_dtls_transport.get());
- break;
- default:
- RTC_DCHECK_NOTREACHED();
- }
auto jsep_transport = std::make_unique<JsepTransport>(
kTransportName, /*local_certificate=*/nullptr, std::move(ice),
@@ -205,7 +188,7 @@ class JsepTransport2WithRtcpMux : public JsepTransport2Test,
// This test verifies the ICE parameters are properly applied to the transports.
TEST_P(JsepTransport2WithRtcpMux, SetIceParameters) {
bool rtcp_mux_enabled = GetParam();
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
JsepTransportDescription jsep_description;
jsep_description.transport_desc = TransportDescription(kIceUfrag1, kIcePwd1);
@@ -251,7 +234,7 @@ TEST_P(JsepTransport2WithRtcpMux, SetIceParameters) {
// Similarly, test DTLS parameters are properly applied to the transports.
TEST_P(JsepTransport2WithRtcpMux, SetDtlsParameters) {
bool rtcp_mux_enabled = GetParam();
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
// Create certificates.
rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
@@ -302,7 +285,7 @@ TEST_P(JsepTransport2WithRtcpMux, SetDtlsParameters) {
// CONNECTIONROLE_PASSIVE, expecting SSL_CLIENT role.
TEST_P(JsepTransport2WithRtcpMux, SetDtlsParametersWithPassiveAnswer) {
bool rtcp_mux_enabled = GetParam();
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
// Create certificates.
rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
@@ -354,7 +337,7 @@ TEST_P(JsepTransport2WithRtcpMux, SetDtlsParametersWithPassiveAnswer) {
// only starts returning "false" once an ICE restart has been initiated.
TEST_P(JsepTransport2WithRtcpMux, NeedsIceRestart) {
bool rtcp_mux_enabled = GetParam();
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
// Use the same JsepTransportDescription for both offer and answer.
JsepTransportDescription description;
@@ -399,7 +382,7 @@ TEST_P(JsepTransport2WithRtcpMux, NeedsIceRestart) {
TEST_P(JsepTransport2WithRtcpMux, GetStats) {
bool rtcp_mux_enabled = GetParam();
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
size_t expected_stats_size = rtcp_mux_enabled ? 1u : 2u;
TransportStats stats;
@@ -415,7 +398,7 @@ TEST_P(JsepTransport2WithRtcpMux, GetStats) {
// certificate matches the fingerprint.
TEST_P(JsepTransport2WithRtcpMux, VerifyCertificateFingerprint) {
bool rtcp_mux_enabled = GetParam();
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
EXPECT_FALSE(
jsep_transport_->VerifyCertificateFingerprint(nullptr, nullptr).ok());
@@ -489,8 +472,7 @@ TEST_P(JsepTransport2WithRtcpMux, ValidDtlsRoleNegotiation) {
};
for (auto& param : valid_client_params) {
- jsep_transport_ =
- CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
local_description.transport_desc.connection_role = param.local_role;
@@ -535,8 +517,7 @@ TEST_P(JsepTransport2WithRtcpMux, ValidDtlsRoleNegotiation) {
};
for (auto& param : valid_server_params) {
- jsep_transport_ =
- CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
local_description.transport_desc.connection_role = param.local_role;
@@ -607,8 +588,7 @@ TEST_P(JsepTransport2WithRtcpMux, InvalidDtlsRoleNegotiation) {
SdpType::kPrAnswer}};
for (auto& param : duplicate_params) {
- jsep_transport_ =
- CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
local_description.transport_desc.connection_role = param.local_role;
@@ -658,8 +638,7 @@ TEST_P(JsepTransport2WithRtcpMux, InvalidDtlsRoleNegotiation) {
SdpType::kPrAnswer}};
for (auto& param : offerer_without_actpass_params) {
- jsep_transport_ =
- CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
local_description.transport_desc.connection_role = param.local_role;
@@ -705,7 +684,7 @@ TEST_F(JsepTransport2Test, ValidDtlsReofferFromAnswerer) {
rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("testing", rtc::KT_ECDSA));
bool rtcp_mux_enabled = true;
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
JsepTransportDescription local_offer =
@@ -752,7 +731,7 @@ TEST_F(JsepTransport2Test, InvalidDtlsReofferFromAnswerer) {
rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("testing", rtc::KT_ECDSA));
bool rtcp_mux_enabled = true;
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
JsepTransportDescription local_offer =
@@ -798,7 +777,7 @@ TEST_F(JsepTransport2Test, RemoteOfferWithCurrentNegotiatedDtlsRole) {
rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("testing", rtc::KT_ECDSA));
bool rtcp_mux_enabled = true;
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
JsepTransportDescription remote_desc =
@@ -843,7 +822,7 @@ TEST_F(JsepTransport2Test, RemoteOfferThatChangesNegotiatedDtlsRole) {
rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("testing", rtc::KT_ECDSA));
bool rtcp_mux_enabled = true;
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
JsepTransportDescription remote_desc =
@@ -890,7 +869,7 @@ TEST_F(JsepTransport2Test, RemoteOfferThatChangesFingerprintAndDtlsRole) {
rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("testing2", rtc::KT_ECDSA));
bool rtcp_mux_enabled = true;
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
JsepTransportDescription remote_desc =
@@ -943,7 +922,7 @@ TEST_F(JsepTransport2Test, DtlsSetupWithLegacyAsAnswerer) {
rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("testing", rtc::KT_ECDSA));
bool rtcp_mux_enabled = true;
- jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(rtcp_mux_enabled);
jsep_transport_->SetLocalCertificate(certificate);
JsepTransportDescription remote_desc =
@@ -975,8 +954,7 @@ TEST_F(JsepTransport2Test, DtlsSetupWithLegacyAsAnswerer) {
// Tests that when the RTCP mux is successfully negotiated, the RTCP transport
// will be destroyed and the SignalRtpMuxActive will be fired.
TEST_F(JsepTransport2Test, RtcpMuxNegotiation) {
- jsep_transport_ =
- CreateJsepTransport2(/*rtcp_mux_enabled=*/false, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(/*rtcp_mux_enabled=*/false);
JsepTransportDescription local_desc;
local_desc.rtcp_mux_enabled = true;
ASSERT_NE(nullptr, jsep_transport_->rtcp_dtls_transport());
@@ -998,8 +976,7 @@ TEST_F(JsepTransport2Test, RtcpMuxNegotiation) {
EXPECT_TRUE(signal_rtcp_mux_active_received_);
// The remote side doesn't support RTCP-mux.
- jsep_transport_ =
- CreateJsepTransport2(/*rtcp_mux_enabled=*/false, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(/*rtcp_mux_enabled=*/false);
signal_rtcp_mux_active_received_ = false;
remote_desc.rtcp_mux_enabled = false;
ASSERT_TRUE(
@@ -1015,87 +992,10 @@ TEST_F(JsepTransport2Test, RtcpMuxNegotiation) {
EXPECT_FALSE(signal_rtcp_mux_active_received_);
}
-TEST_F(JsepTransport2Test, SdesNegotiation) {
- jsep_transport_ =
- CreateJsepTransport2(/*rtcp_mux_enabled=*/true, SrtpMode::kSdes);
- ASSERT_TRUE(sdes_transport_);
- EXPECT_FALSE(sdes_transport_->IsSrtpActive());
-
- JsepTransportDescription offer_desc;
- offer_desc.cryptos.push_back(cricket::CryptoParams(
- 1, rtc::kCsAesCm128HmacSha1_32, "inline:" + rtc::CreateRandomString(40),
- std::string()));
- ASSERT_TRUE(
- jsep_transport_
- ->SetLocalJsepTransportDescription(offer_desc, SdpType::kOffer)
- .ok());
-
- JsepTransportDescription answer_desc;
- answer_desc.cryptos.push_back(cricket::CryptoParams(
- 1, rtc::kCsAesCm128HmacSha1_32, "inline:" + rtc::CreateRandomString(40),
- std::string()));
- ASSERT_TRUE(
- jsep_transport_
- ->SetRemoteJsepTransportDescription(answer_desc, SdpType::kAnswer)
- .ok());
- EXPECT_TRUE(sdes_transport_->IsSrtpActive());
-}
-
-TEST_F(JsepTransport2Test, SdesNegotiationWithEmptyCryptosInAnswer) {
- jsep_transport_ =
- CreateJsepTransport2(/*rtcp_mux_enabled=*/true, SrtpMode::kSdes);
- ASSERT_TRUE(sdes_transport_);
- EXPECT_FALSE(sdes_transport_->IsSrtpActive());
-
- JsepTransportDescription offer_desc;
- offer_desc.cryptos.push_back(cricket::CryptoParams(
- 1, rtc::kCsAesCm128HmacSha1_32, "inline:" + rtc::CreateRandomString(40),
- std::string()));
- ASSERT_TRUE(
- jsep_transport_
- ->SetLocalJsepTransportDescription(offer_desc, SdpType::kOffer)
- .ok());
-
- JsepTransportDescription answer_desc;
- ASSERT_TRUE(
- jsep_transport_
- ->SetRemoteJsepTransportDescription(answer_desc, SdpType::kAnswer)
- .ok());
- // SRTP is not active because the crypto parameter is answer is empty.
- EXPECT_FALSE(sdes_transport_->IsSrtpActive());
-}
-
-TEST_F(JsepTransport2Test, SdesNegotiationWithMismatchedCryptos) {
- jsep_transport_ =
- CreateJsepTransport2(/*rtcp_mux_enabled=*/true, SrtpMode::kSdes);
- ASSERT_TRUE(sdes_transport_);
- EXPECT_FALSE(sdes_transport_->IsSrtpActive());
-
- JsepTransportDescription offer_desc;
- offer_desc.cryptos.push_back(cricket::CryptoParams(
- 1, rtc::kCsAesCm128HmacSha1_32, "inline:" + rtc::CreateRandomString(40),
- std::string()));
- ASSERT_TRUE(
- jsep_transport_
- ->SetLocalJsepTransportDescription(offer_desc, SdpType::kOffer)
- .ok());
-
- JsepTransportDescription answer_desc;
- answer_desc.cryptos.push_back(cricket::CryptoParams(
- 1, rtc::kCsAesCm128HmacSha1_80, "inline:" + rtc::CreateRandomString(40),
- std::string()));
- // Expected to fail because the crypto parameters don't match.
- ASSERT_FALSE(
- jsep_transport_
- ->SetRemoteJsepTransportDescription(answer_desc, SdpType::kAnswer)
- .ok());
-}
-
// Tests that the remote candidates can be added to the transports after both
// local and remote descriptions are set.
TEST_F(JsepTransport2Test, AddRemoteCandidates) {
- jsep_transport_ =
- CreateJsepTransport2(/*rtcp_mux_enabled=*/true, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(/*rtcp_mux_enabled=*/true);
auto fake_ice_transport = static_cast<FakeIceTransport*>(
jsep_transport_->rtp_dtls_transport()->ice_transport());
@@ -1119,7 +1019,6 @@ TEST_F(JsepTransport2Test, AddRemoteCandidates) {
}
enum class Scenario {
- kSdes,
kDtlsBeforeCallerSendOffer,
kDtlsBeforeCallerSetAnswer,
kDtlsAfterCallerSetAnswer,
@@ -1131,9 +1030,9 @@ class JsepTransport2HeaderExtensionTest
protected:
JsepTransport2HeaderExtensionTest() {}
- void CreateJsepTransportPair(SrtpMode mode) {
- jsep_transport1_ = CreateJsepTransport2(/*rtcp_mux_enabled=*/true, mode);
- jsep_transport2_ = CreateJsepTransport2(/*rtcp_mux_enabled=*/true, mode);
+ void CreateJsepTransportPair() {
+ jsep_transport1_ = CreateJsepTransport2(/*rtcp_mux_enabled=*/true);
+ jsep_transport2_ = CreateJsepTransport2(/*rtcp_mux_enabled=*/true);
auto fake_dtls1 =
static_cast<FakeDtlsTransport*>(jsep_transport1_->rtp_dtls_transport());
@@ -1145,14 +1044,12 @@ class JsepTransport2HeaderExtensionTest
fake_dtls2->fake_ice_transport()->SignalReadPacket.connect(
this, &JsepTransport2HeaderExtensionTest::OnReadPacket2);
- if (mode == SrtpMode::kDtlsSrtp) {
auto cert1 = rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("session1", rtc::KT_DEFAULT));
jsep_transport1_->rtp_dtls_transport()->SetLocalCertificate(cert1);
auto cert2 = rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("session1", rtc::KT_DEFAULT));
jsep_transport2_->rtp_dtls_transport()->SetLocalCertificate(cert2);
- }
}
void OnReadPacket1(rtc::PacketTransportInternal* transport,
@@ -1239,17 +1136,10 @@ class JsepTransport2HeaderExtensionTest
TEST_P(JsepTransport2HeaderExtensionTest, EncryptedHeaderExtensionNegotiation) {
Scenario scenario = std::get<0>(GetParam());
bool use_gcm = std::get<1>(GetParam());
- SrtpMode mode = SrtpMode ::kDtlsSrtp;
- if (scenario == Scenario::kSdes) {
- mode = SrtpMode::kSdes;
- }
- CreateJsepTransportPair(mode);
+ CreateJsepTransportPair();
recv_encrypted_headers1_.push_back(kHeaderExtensionIDs[0]);
recv_encrypted_headers2_.push_back(kHeaderExtensionIDs[1]);
- cricket::CryptoParams sdes_param(1, rtc::kCsAesCm128HmacSha1_80,
- "inline:" + rtc::CreateRandomString(40),
- std::string());
if (use_gcm) {
auto fake_dtls1 =
static_cast<FakeDtlsTransport*>(jsep_transport1_->rtp_dtls_transport());
@@ -1266,9 +1156,6 @@ TEST_P(JsepTransport2HeaderExtensionTest, EncryptedHeaderExtensionNegotiation) {
JsepTransportDescription offer_desc;
offer_desc.encrypted_header_extension_ids = recv_encrypted_headers1_;
- if (scenario == Scenario::kSdes) {
- offer_desc.cryptos.push_back(sdes_param);
- }
ASSERT_TRUE(
jsep_transport1_
->SetLocalJsepTransportDescription(offer_desc, SdpType::kOffer)
@@ -1280,9 +1167,6 @@ TEST_P(JsepTransport2HeaderExtensionTest, EncryptedHeaderExtensionNegotiation) {
JsepTransportDescription answer_desc;
answer_desc.encrypted_header_extension_ids = recv_encrypted_headers2_;
- if (scenario == Scenario::kSdes) {
- answer_desc.cryptos.push_back(sdes_param);
- }
ASSERT_TRUE(
jsep_transport2_
->SetLocalJsepTransportDescription(answer_desc, SdpType::kAnswer)
@@ -1301,8 +1185,7 @@ TEST_P(JsepTransport2HeaderExtensionTest, EncryptedHeaderExtensionNegotiation) {
->SetRemoteJsepTransportDescription(answer_desc, SdpType::kAnswer)
.ok());
- if (scenario == Scenario::kDtlsAfterCallerSetAnswer ||
- scenario == Scenario::kSdes) {
+ if (scenario == Scenario::kDtlsAfterCallerSetAnswer) {
ConnectTransport();
}
EXPECT_TRUE(jsep_transport1_->rtp_transport()->IsSrtpActive());
@@ -1341,7 +1224,6 @@ INSTANTIATE_TEST_SUITE_P(
JsepTransport2Test,
JsepTransport2HeaderExtensionTest,
::testing::Values(
- std::make_tuple(Scenario::kSdes, false),
std::make_tuple(Scenario::kDtlsBeforeCallerSendOffer, true),
std::make_tuple(Scenario::kDtlsBeforeCallerSetAnswer, true),
std::make_tuple(Scenario::kDtlsAfterCallerSetAnswer, true),
@@ -1351,8 +1233,7 @@ INSTANTIATE_TEST_SUITE_P(
// This test verifies the ICE parameters are properly applied to the transports.
TEST_F(JsepTransport2Test, SetIceParametersWithRenomination) {
- jsep_transport_ =
- CreateJsepTransport2(/* rtcp_mux_enabled= */ true, SrtpMode::kDtlsSrtp);
+ jsep_transport_ = CreateJsepTransport2(/* rtcp_mux_enabled= */ true);
JsepTransportDescription jsep_description;
jsep_description.transport_desc = TransportDescription(kIceUfrag1, kIcePwd1);
diff --git a/third_party/libwebrtc/pc/media_session.cc b/third_party/libwebrtc/pc/media_session.cc
index a118beebb0..3928088c7f 100644
--- a/third_party/libwebrtc/pc/media_session.cc
+++ b/third_party/libwebrtc/pc/media_session.cc
@@ -22,7 +22,6 @@
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
-#include "api/crypto_params.h"
#include "media/base/codec.h"
#include "media/base/media_constants.h"
#include "media/base/media_engine.h"
@@ -47,19 +46,6 @@ using webrtc::RTCError;
using webrtc::RTCErrorType;
using webrtc::RtpTransceiverDirection;
-const char kInline[] = "inline:";
-
-void GetSupportedSdesCryptoSuiteNames(
- void (*func)(const webrtc::CryptoOptions&, std::vector<int>*),
- const webrtc::CryptoOptions& crypto_options,
- std::vector<std::string>* names) {
- std::vector<int> crypto_suites;
- func(crypto_options, &crypto_suites);
- for (const auto crypto : crypto_suites) {
- names->push_back(rtc::SrtpCryptoSuiteToName(crypto));
- }
-}
-
webrtc::RtpExtension RtpExtensionFromCapability(
const webrtc::RtpHeaderExtensionCapability& capability) {
return webrtc::RtpExtension(capability.uri,
@@ -167,140 +153,6 @@ bool IsMediaContentOfType(const ContentInfo* content, MediaType media_type) {
return content->media_description()->type() == media_type;
}
-bool CreateCryptoParams(int tag,
- const std::string& cipher,
- CryptoParams* crypto_out) {
- int key_len;
- int salt_len;
- if (!rtc::GetSrtpKeyAndSaltLengths(rtc::SrtpCryptoSuiteFromName(cipher),
- &key_len, &salt_len)) {
- return false;
- }
-
- int master_key_len = key_len + salt_len;
- std::string master_key;
- if (!rtc::CreateRandomData(master_key_len, &master_key)) {
- return false;
- }
-
- RTC_CHECK_EQ(master_key_len, master_key.size());
- std::string key = rtc::Base64::Encode(master_key);
-
- crypto_out->tag = tag;
- crypto_out->crypto_suite = cipher;
- crypto_out->key_params = kInline;
- crypto_out->key_params += key;
- return true;
-}
-
-bool AddCryptoParams(const std::string& crypto_suite,
- CryptoParamsVec* cryptos_out) {
- int size = static_cast<int>(cryptos_out->size());
-
- cryptos_out->resize(size + 1);
- return CreateCryptoParams(size, crypto_suite, &cryptos_out->at(size));
-}
-
-void AddMediaCryptos(const CryptoParamsVec& cryptos,
- MediaContentDescription* media) {
- for (const CryptoParams& crypto : cryptos) {
- media->AddCrypto(crypto);
- }
-}
-
-bool CreateMediaCryptos(const std::vector<std::string>& crypto_suites,
- MediaContentDescription* media) {
- CryptoParamsVec cryptos;
- for (const std::string& crypto_suite : crypto_suites) {
- if (!AddCryptoParams(crypto_suite, &cryptos)) {
- return false;
- }
- }
- AddMediaCryptos(cryptos, media);
- return true;
-}
-
-const CryptoParamsVec* GetCryptos(const ContentInfo* content) {
- if (!content || !content->media_description()) {
- return nullptr;
- }
- return &content->media_description()->cryptos();
-}
-
-bool FindMatchingCrypto(const CryptoParamsVec& cryptos,
- const CryptoParams& crypto,
- CryptoParams* crypto_out) {
- auto it = absl::c_find_if(
- cryptos, [&crypto](const CryptoParams& c) { return crypto.Matches(c); });
- if (it == cryptos.end()) {
- return false;
- }
- *crypto_out = *it;
- return true;
-}
-
-// For audio, HMAC 32 (if enabled) is prefered over HMAC 80 because of the
-// low overhead.
-void GetSupportedAudioSdesCryptoSuites(
- const webrtc::CryptoOptions& crypto_options,
- std::vector<int>* crypto_suites) {
- if (crypto_options.srtp.enable_aes128_sha1_32_crypto_cipher) {
- crypto_suites->push_back(rtc::kSrtpAes128CmSha1_32);
- }
- crypto_suites->push_back(rtc::kSrtpAes128CmSha1_80);
- if (crypto_options.srtp.enable_gcm_crypto_suites) {
- crypto_suites->push_back(rtc::kSrtpAeadAes256Gcm);
- crypto_suites->push_back(rtc::kSrtpAeadAes128Gcm);
- }
-}
-
-void GetSupportedAudioSdesCryptoSuiteNames(
- const webrtc::CryptoOptions& crypto_options,
- std::vector<std::string>* crypto_suite_names) {
- GetSupportedSdesCryptoSuiteNames(GetSupportedAudioSdesCryptoSuites,
- crypto_options, crypto_suite_names);
-}
-
-void GetSupportedVideoSdesCryptoSuites(
- const webrtc::CryptoOptions& crypto_options,
- std::vector<int>* crypto_suites) {
- crypto_suites->push_back(rtc::kSrtpAes128CmSha1_80);
- if (crypto_options.srtp.enable_gcm_crypto_suites) {
- crypto_suites->push_back(rtc::kSrtpAeadAes256Gcm);
- crypto_suites->push_back(rtc::kSrtpAeadAes128Gcm);
- }
-}
-
-void GetSupportedVideoSdesCryptoSuiteNames(
- const webrtc::CryptoOptions& crypto_options,
- std::vector<std::string>* crypto_suite_names) {
- GetSupportedSdesCryptoSuiteNames(GetSupportedVideoSdesCryptoSuites,
- crypto_options, crypto_suite_names);
-}
-
-// Support any GCM cipher (if enabled through options). For video support only
-// 80-bit SHA1 HMAC. For audio 32-bit HMAC is tolerated (if enabled) unless
-// bundle is enabled because it is low overhead.
-// Pick the crypto in the list that is supported.
-bool SelectCrypto(const MediaContentDescription* offer,
- bool bundle,
- const webrtc::CryptoOptions& crypto_options,
- CryptoParams* crypto_out) {
- bool audio = offer->type() == MEDIA_TYPE_AUDIO;
- const CryptoParamsVec& cryptos = offer->cryptos();
-
- for (const CryptoParams& crypto : cryptos) {
- if ((crypto_options.srtp.enable_gcm_crypto_suites &&
- rtc::IsGcmCryptoSuiteName(crypto.crypto_suite)) ||
- rtc::kCsAesCm128HmacSha1_80 == crypto.crypto_suite ||
- (rtc::kCsAesCm128HmacSha1_32 == crypto.crypto_suite && audio &&
- !bundle && crypto_options.srtp.enable_aes128_sha1_32_crypto_cipher)) {
- return CreateCryptoParams(crypto.tag, crypto.crypto_suite, crypto_out);
- }
- }
- return false;
-}
-
// Finds all StreamParams of all media types and attach them to stream_params.
StreamParamsVec GetCurrentStreamParams(
const std::vector<const ContentInfo*>& active_local_contents) {
@@ -496,118 +348,6 @@ bool UpdateTransportInfoForBundle(const ContentGroup& bundle_group,
return true;
}
-// Gets the CryptoParamsVec of the given `content_name` from `sdesc`, and
-// sets it to `cryptos`.
-bool GetCryptosByName(const SessionDescription* sdesc,
- const std::string& content_name,
- CryptoParamsVec* cryptos) {
- if (!sdesc || !cryptos) {
- return false;
- }
- const ContentInfo* content = sdesc->GetContentByName(content_name);
- if (!content || !content->media_description()) {
- return false;
- }
- *cryptos = content->media_description()->cryptos();
- return true;
-}
-
-// Prunes the `target_cryptos` by removing the crypto params (crypto_suite)
-// which are not available in `filter`.
-void PruneCryptos(const CryptoParamsVec& filter,
- CryptoParamsVec* target_cryptos) {
- if (!target_cryptos) {
- return;
- }
-
- target_cryptos->erase(
- std::remove_if(target_cryptos->begin(), target_cryptos->end(),
- // Returns true if the `crypto`'s crypto_suite is not
- // found in `filter`.
- [&filter](const CryptoParams& crypto) {
- for (const CryptoParams& entry : filter) {
- if (entry.crypto_suite == crypto.crypto_suite)
- return false;
- }
- return true;
- }),
- target_cryptos->end());
-}
-
-bool IsRtpContent(SessionDescription* sdesc, const std::string& content_name) {
- bool is_rtp = false;
- ContentInfo* content = sdesc->GetContentByName(content_name);
- if (content && content->media_description()) {
- is_rtp = IsRtpProtocol(content->media_description()->protocol());
- }
- return is_rtp;
-}
-
-// Updates the crypto parameters of the `sdesc` according to the given
-// `bundle_group`. The crypto parameters of all the contents within the
-// `bundle_group` should be updated to use the common subset of the
-// available cryptos.
-bool UpdateCryptoParamsForBundle(const ContentGroup& bundle_group,
- SessionDescription* sdesc) {
- // The bundle should not be empty.
- if (!sdesc || !bundle_group.FirstContentName()) {
- return false;
- }
-
- bool common_cryptos_needed = false;
- // Get the common cryptos.
- const ContentNames& content_names = bundle_group.content_names();
- CryptoParamsVec common_cryptos;
- bool first = true;
- for (const std::string& content_name : content_names) {
- if (!IsRtpContent(sdesc, content_name)) {
- continue;
- }
- // The common cryptos are needed if any of the content does not have DTLS
- // enabled.
- if (!sdesc->GetTransportInfoByName(content_name)->description.secure()) {
- common_cryptos_needed = true;
- }
- if (first) {
- first = false;
- // Initial the common_cryptos with the first content in the bundle group.
- if (!GetCryptosByName(sdesc, content_name, &common_cryptos)) {
- return false;
- }
- if (common_cryptos.empty()) {
- // If there's no crypto params, we should just return.
- return true;
- }
- } else {
- CryptoParamsVec cryptos;
- if (!GetCryptosByName(sdesc, content_name, &cryptos)) {
- return false;
- }
- PruneCryptos(cryptos, &common_cryptos);
- }
- }
-
- if (common_cryptos.empty() && common_cryptos_needed) {
- return false;
- }
-
- // Update to use the common cryptos.
- for (const std::string& content_name : content_names) {
- if (!IsRtpContent(sdesc, content_name)) {
- continue;
- }
- ContentInfo* content = sdesc->GetContentByName(content_name);
- if (IsMediaContent(content)) {
- MediaContentDescription* media_desc = content->media_description();
- if (!media_desc) {
- return false;
- }
- media_desc->set_cryptos(common_cryptos);
- }
- }
- return true;
-}
-
std::vector<const ContentInfo*> GetActiveContents(
const SessionDescription& description,
const MediaSessionOptions& session_options) {
@@ -634,9 +374,6 @@ std::vector<const ContentInfo*> GetActiveContents(
RTCError CreateContentOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
- const SecurePolicy& secure_policy,
- const CryptoParamsVec* current_cryptos,
- const std::vector<std::string>& crypto_suites,
const RtpHeaderExtensions& rtp_extensions,
UniqueRandomIdGenerator* ssrc_generator,
StreamParamsVec* current_streams,
@@ -665,22 +402,6 @@ RTCError CreateContentOffer(
AddSimulcastToMediaDescription(media_description_options, offer);
- if (secure_policy != SEC_DISABLED) {
- if (current_cryptos) {
- AddMediaCryptos(*current_cryptos, offer);
- }
- if (offer->cryptos().empty()) {
- if (!CreateMediaCryptos(crypto_suites, offer)) {
- LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
- "Failed to create crypto parameters");
- }
- }
- }
-
- if (secure_policy == SEC_REQUIRED && offer->cryptos().empty()) {
- LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
- "Failed to create crypto parameters");
- }
return RTCError::OK();
}
@@ -688,9 +409,6 @@ RTCError CreateMediaContentOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const std::vector<Codec>& codecs,
- const SecurePolicy& secure_policy,
- const CryptoParamsVec* current_cryptos,
- const std::vector<std::string>& crypto_suites,
const RtpHeaderExtensions& rtp_extensions,
UniqueRandomIdGenerator* ssrc_generator,
StreamParamsVec* current_streams,
@@ -705,7 +423,6 @@ RTCError CreateMediaContentOffer(
}
return CreateContentOffer(media_description_options, session_options,
- secure_policy, current_cryptos, crypto_suites,
rtp_extensions, ssrc_generator, current_streams,
offer);
}
@@ -1254,17 +971,6 @@ void NegotiateRtpHeaderExtensions(const RtpHeaderExtensions& local_extensions,
const RtpHeaderExtensions& offered_extensions,
webrtc::RtpExtension::Filter filter,
RtpHeaderExtensions* negotiated_extensions) {
- // TransportSequenceNumberV2 is not offered by default. The special logic for
- // the TransportSequenceNumber extensions works as follows:
- // Offer Answer
- // V1 V1 if in local_extensions.
- // V1 and V2 V2 regardless of local_extensions.
- // V2 V2 regardless of local_extensions.
- const webrtc::RtpExtension* transport_sequence_number_v2_offer =
- FindHeaderExtensionByUriDiscardUnsupported(
- offered_extensions,
- webrtc::RtpExtension::kTransportSequenceNumberV2Uri, filter);
-
bool frame_descriptor_in_local = false;
bool dependency_descriptor_in_local = false;
bool abs_capture_time_in_local = false;
@@ -1276,29 +982,16 @@ void NegotiateRtpHeaderExtensions(const RtpHeaderExtensions& local_extensions,
dependency_descriptor_in_local = true;
else if (ours.uri == webrtc::RtpExtension::kAbsoluteCaptureTimeUri)
abs_capture_time_in_local = true;
+
const webrtc::RtpExtension* theirs =
FindHeaderExtensionByUriDiscardUnsupported(offered_extensions, ours.uri,
filter);
if (theirs) {
- if (transport_sequence_number_v2_offer &&
- ours.uri == webrtc::RtpExtension::kTransportSequenceNumberUri) {
- // Don't respond to
- // http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
- // if we get an offer including
- // http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02
- continue;
- } else {
- // We respond with their RTP header extension id.
- negotiated_extensions->push_back(*theirs);
- }
+ // We respond with their RTP header extension id.
+ negotiated_extensions->push_back(*theirs);
}
}
- if (transport_sequence_number_v2_offer) {
- // Respond that we support kTransportSequenceNumberV2Uri.
- negotiated_extensions->push_back(*transport_sequence_number_v2_offer);
- }
-
// Frame descriptors support. If the extension is not present locally, but is
// in the offer, we add it to the list.
if (!dependency_descriptor_in_local) {
@@ -1367,8 +1060,6 @@ bool CreateMediaContentAnswer(
const MediaContentDescription* offer,
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
- const SecurePolicy& sdes_policy,
- const CryptoParamsVec* current_cryptos,
const RtpHeaderExtensions& local_rtp_extensions,
UniqueRandomIdGenerator* ssrc_generator,
bool enable_encrypted_rtp_header_extensions,
@@ -1409,21 +1100,6 @@ bool CreateMediaContentAnswer(
answer->set_remote_estimate(offer->remote_estimate());
- if (sdes_policy != SEC_DISABLED) {
- CryptoParams crypto;
- if (SelectCrypto(offer, bundle_enabled, session_options.crypto_options,
- &crypto)) {
- if (current_cryptos) {
- FindMatchingCrypto(*current_cryptos, crypto, &crypto);
- }
- answer->AddCrypto(crypto);
- }
- }
-
- if (answer->cryptos().empty() && sdes_policy == SEC_REQUIRED) {
- return false;
- }
-
AddSimulcastToMediaDescription(media_description_options, answer);
answer->set_direction(NegotiateRtpTransceiverDirection(
@@ -1462,9 +1138,7 @@ bool IsMediaProtocolSupported(MediaType type,
}
void SetMediaProtocol(bool secure_transport, MediaContentDescription* desc) {
- if (!desc->cryptos().empty())
- desc->set_protocol(kMediaProtocolSavpf);
- else if (secure_transport)
+ if (secure_transport)
desc->set_protocol(kMediaProtocolDtlsSavpf);
else
desc->set_protocol(kMediaProtocolAvpf);
@@ -1486,23 +1160,6 @@ const TransportDescription* GetTransportDescription(
return desc;
}
-// Gets the current DTLS state from the transport description.
-bool IsDtlsActive(const ContentInfo* content,
- const SessionDescription* current_description) {
- if (!content) {
- return false;
- }
-
- size_t msection_index = content - &current_description->contents()[0];
-
- if (current_description->transport_infos().size() <= msection_index) {
- return false;
- }
-
- return current_description->transport_infos()[msection_index]
- .description.secure();
-}
-
webrtc::RTCErrorOr<AudioCodecs> GetNegotiatedCodecsForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
@@ -1867,11 +1524,6 @@ MediaSessionDescriptionFactory::CreateOfferOrError(
RTCErrorType::INTERNAL_ERROR,
"CreateOffer failed to UpdateTransportInfoForBundle");
}
- if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) {
- LOG_AND_RETURN_ERROR(
- RTCErrorType::INTERNAL_ERROR,
- "CreateOffer failed to UpdateCryptoParamsForBundle.");
- }
}
}
@@ -2045,12 +1697,6 @@ MediaSessionDescriptionFactory::CreateAnswerOrError(
RTCErrorType::INTERNAL_ERROR,
"CreateAnswer failed to UpdateTransportInfoForBundle.");
}
-
- if (!UpdateCryptoParamsForBundle(answer_bundle, answer.get())) {
- LOG_AND_RETURN_ERROR(
- RTCErrorType::INTERNAL_ERROR,
- "CreateAnswer failed to UpdateCryptoParamsForBundle.");
- }
}
}
}
@@ -2402,19 +2048,6 @@ RTCError MediaSessionDescriptionFactory::AddRtpContentForOffer(
return error_or_filtered_codecs.MoveError();
}
- cricket::SecurePolicy sdes_policy =
- IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
- : secure();
-
- std::vector<std::string> crypto_suites;
- if (media_description_options.type == MEDIA_TYPE_AUDIO) {
- GetSupportedAudioSdesCryptoSuiteNames(session_options.crypto_options,
- &crypto_suites);
- } else {
- GetSupportedVideoSdesCryptoSuiteNames(session_options.crypto_options,
- &crypto_suites);
- }
-
std::unique_ptr<MediaContentDescription> content_description;
if (media_description_options.type == MEDIA_TYPE_AUDIO) {
content_description = std::make_unique<AudioContentDescription>();
@@ -2424,15 +2057,15 @@ RTCError MediaSessionDescriptionFactory::AddRtpContentForOffer(
auto error = CreateMediaContentOffer(
media_description_options, session_options,
- error_or_filtered_codecs.MoveValue(), sdes_policy,
- GetCryptos(current_content), crypto_suites, header_extensions,
- ssrc_generator(), current_streams, content_description.get(),
+ error_or_filtered_codecs.MoveValue(), header_extensions, ssrc_generator(),
+ current_streams, content_description.get(),
transport_desc_factory_->trials());
if (!error.ok()) {
return error;
}
- bool secure_transport = transport_desc_factory_->secure() != SEC_DISABLED;
+ // Insecure transport should only occur in testing.
+ bool secure_transport = !(transport_desc_factory_->insecure());
SetMediaProtocol(secure_transport, content_description.get());
content_description->set_direction(media_description_options.direction);
@@ -2456,15 +2089,9 @@ RTCError MediaSessionDescriptionFactory::AddDataContentForOffer(
IceCredentialsIterator* ice_credentials) const {
auto data = std::make_unique<SctpDataContentDescription>();
- bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
+ bool secure_transport = true;
- cricket::SecurePolicy sdes_policy =
- IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
- : secure();
std::vector<std::string> crypto_suites;
- // SDES doesn't make sense for SCTP, so we disable it, and we only
- // get SDES crypto suites for RTP-based data channels.
- sdes_policy = cricket::SEC_DISABLED;
// Unlike SetMediaProtocol below, we need to set the protocol
// before we call CreateMediaContentOffer. Otherwise,
// CreateMediaContentOffer won't know this is SCTP and will
@@ -2474,10 +2101,9 @@ RTCError MediaSessionDescriptionFactory::AddDataContentForOffer(
data->set_use_sctpmap(session_options.use_obsolete_sctp_sdp);
data->set_max_message_size(kSctpSendBufferSize);
- auto error = CreateContentOffer(
- media_description_options, session_options, sdes_policy,
- GetCryptos(current_content), crypto_suites, RtpHeaderExtensions(),
- ssrc_generator(), current_streams, data.get());
+ auto error = CreateContentOffer(media_description_options, session_options,
+ RtpHeaderExtensions(), ssrc_generator(),
+ current_streams, data.get());
if (!error.ok()) {
return error;
}
@@ -2546,10 +2172,14 @@ RTCError MediaSessionDescriptionFactory::AddRtpContentForAnswer(
} else {
offer_content_description = offer_content->media_description()->as_video();
}
+ // If this section is part of a bundle, bundle_transport is non-null.
+ // Then require_transport_attributes is false - we can handle sections
+ // without the DTLS parameters. For rejected m-lines it does not matter.
+ // Otherwise, transport attributes MUST be present.
std::unique_ptr<TransportDescription> transport = CreateTransportAnswer(
media_description_options.mid, offer_description,
media_description_options.transport_options, current_description,
- bundle_transport != nullptr, ice_credentials);
+ !offer_content->rejected && bundle_transport == nullptr, ice_credentials);
if (!transport) {
LOG_AND_RETURN_ERROR(
RTCErrorType::INTERNAL_ERROR,
@@ -2590,9 +2220,6 @@ RTCError MediaSessionDescriptionFactory::AddRtpContentForAnswer(
} else {
answer_content = std::make_unique<VideoContentDescription>();
}
- // Do not require or create SDES cryptos if DTLS is used.
- cricket::SecurePolicy sdes_policy =
- transport->secure() ? cricket::SEC_DISABLED : secure();
if (!SetCodecsInAnswer(
offer_content_description, filtered_codecs, media_description_options,
session_options, ssrc_generator(), current_streams,
@@ -2602,7 +2229,6 @@ RTCError MediaSessionDescriptionFactory::AddRtpContentForAnswer(
}
if (!CreateMediaContentAnswer(
offer_content_description, media_description_options, session_options,
- sdes_policy, GetCryptos(current_content),
filtered_rtp_header_extensions(header_extensions), ssrc_generator(),
enable_encrypted_rtp_header_extensions_, current_streams,
bundle_enabled, answer_content.get())) {
@@ -2646,16 +2272,13 @@ RTCError MediaSessionDescriptionFactory::AddDataContentForAnswer(
std::unique_ptr<TransportDescription> data_transport = CreateTransportAnswer(
media_description_options.mid, offer_description,
media_description_options.transport_options, current_description,
- bundle_transport != nullptr, ice_credentials);
+ !offer_content->rejected && bundle_transport == nullptr, ice_credentials);
if (!data_transport) {
LOG_AND_RETURN_ERROR(
RTCErrorType::INTERNAL_ERROR,
"Failed to create transport answer, data transport is missing");
}
- // Do not require or create SDES cryptos if DTLS is used.
- cricket::SecurePolicy sdes_policy =
- data_transport->secure() ? cricket::SEC_DISABLED : secure();
bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
session_options.bundle_enabled;
RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_DATA));
@@ -2680,9 +2303,9 @@ RTCError MediaSessionDescriptionFactory::AddDataContentForAnswer(
}
if (!CreateMediaContentAnswer(
offer_data_description, media_description_options, session_options,
- sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
- ssrc_generator(), enable_encrypted_rtp_header_extensions_,
- current_streams, bundle_enabled, data_answer.get())) {
+ RtpHeaderExtensions(), ssrc_generator(),
+ enable_encrypted_rtp_header_extensions_, current_streams,
+ bundle_enabled, data_answer.get())) {
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
"Failed to create answer");
}
@@ -2721,10 +2344,11 @@ RTCError MediaSessionDescriptionFactory::AddUnsupportedContentForAnswer(
SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const {
std::unique_ptr<TransportDescription> unsupported_transport =
- CreateTransportAnswer(media_description_options.mid, offer_description,
- media_description_options.transport_options,
- current_description, bundle_transport != nullptr,
- ice_credentials);
+ CreateTransportAnswer(
+ media_description_options.mid, offer_description,
+ media_description_options.transport_options, current_description,
+ !offer_content->rejected && bundle_transport == nullptr,
+ ice_credentials);
if (!unsupported_transport) {
LOG_AND_RETURN_ERROR(
RTCErrorType::INTERNAL_ERROR,
diff --git a/third_party/libwebrtc/pc/media_session.h b/third_party/libwebrtc/pc/media_session.h
index 0b3cb67c35..c9fbc4ba63 100644
--- a/third_party/libwebrtc/pc/media_session.h
+++ b/third_party/libwebrtc/pc/media_session.h
@@ -160,8 +160,6 @@ class MediaSessionDescriptionFactory {
const VideoCodecs& recv_codecs);
RtpHeaderExtensions filtered_rtp_header_extensions(
RtpHeaderExtensions extensions) const;
- SecurePolicy secure() const { return secure_; }
- void set_secure(SecurePolicy s) { secure_ = s; }
void set_enable_encrypted_rtp_header_extensions(bool enable) {
enable_encrypted_rtp_header_extensions_ = enable;
@@ -320,9 +318,6 @@ class MediaSessionDescriptionFactory {
webrtc::AlwaysValidPointer<rtc::UniqueRandomIdGenerator> const
ssrc_generator_;
bool enable_encrypted_rtp_header_extensions_ = false;
- // TODO(zhihuang): Rename secure_ to sdec_policy_; rename the related getter
- // and setter.
- SecurePolicy secure_ = SEC_DISABLED;
const TransportDescriptionFactory* transport_desc_factory_;
};
diff --git a/third_party/libwebrtc/pc/media_session_unittest.cc b/third_party/libwebrtc/pc/media_session_unittest.cc
index f4fd09cba0..d00ad1c90e 100644
--- a/third_party/libwebrtc/pc/media_session_unittest.cc
+++ b/third_party/libwebrtc/pc/media_session_unittest.cc
@@ -25,7 +25,6 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/candidate.h"
-#include "api/crypto_params.h"
#include "api/rtp_parameters.h"
#include "media/base/codec.h"
#include "media/base/media_constants.h"
@@ -50,10 +49,6 @@
#include "test/gtest.h"
#include "test/scoped_key_value_config.h"
-#define ASSERT_CRYPTO(cd, s, cs) \
- ASSERT_EQ(s, cd->cryptos().size()); \
- ASSERT_EQ(cs, cd->cryptos()[0].crypto_suite)
-
namespace cricket {
namespace {
@@ -254,12 +249,6 @@ const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
const char* kMediaProtocolsDtls[] = {"TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP",
"UDP/TLS/RTP/SAVPF", "UDP/TLS/RTP/SAVP"};
-// SRTP cipher name negotiated by the tests. This must be updated if the
-// default changes.
-const char* kDefaultSrtpCryptoSuite = kCsAesCm128HmacSha1_80;
-const char* kDefaultSrtpCryptoSuiteGcm = kCsAeadAes256Gcm;
-const uint8_t kDefaultCryptoSuiteSize = 3U;
-
// These constants are used to make the code using "AddMediaDescriptionOptions"
// more readable.
constexpr bool kStopped = true;
@@ -388,17 +377,6 @@ MediaSessionOptions CreateAudioMediaSession() {
return session_options;
}
-// prefers GCM SDES crypto suites by removing non-GCM defaults.
-void PreferGcmCryptoParameters(CryptoParamsVec* cryptos) {
- cryptos->erase(
- std::remove_if(cryptos->begin(), cryptos->end(),
- [](const CryptoParams& crypto) {
- return crypto.crypto_suite != kCsAeadAes256Gcm &&
- crypto.crypto_suite != kCsAeadAes128Gcm;
- }),
- cryptos->end());
-}
-
// TODO(zhihuang): Most of these tests were written while MediaSessionOptions
// was designed for Plan B SDP, where only one audio "m=" section and one video
// "m=" section could be generated, and ordering couldn't be controlled. Many of
@@ -451,18 +429,6 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
return video_streams;
}
- bool CompareCryptoParams(const CryptoParamsVec& c1,
- const CryptoParamsVec& c2) {
- if (c1.size() != c2.size())
- return false;
- for (size_t i = 0; i < c1.size(); ++i)
- if (c1[i].tag != c2[i].tag || c1[i].crypto_suite != c2[i].crypto_suite ||
- c1[i].key_params != c2[i].key_params ||
- c1[i].session_params != c2[i].session_params)
- return false;
- return true;
- }
-
// Returns true if the transport info contains "renomination" as an
// ICE option.
bool GetIceRenomination(const TransportInfo* transport_info) {
@@ -566,50 +532,6 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
}
}
- void TestCryptoWithBundle(bool offer) {
- f1_.set_secure(SEC_ENABLED);
- MediaSessionOptions options;
- AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
- std::unique_ptr<SessionDescription> ref_desc;
- std::unique_ptr<SessionDescription> desc;
- if (offer) {
- options.bundle_enabled = false;
- ref_desc = f1_.CreateOfferOrError(options, nullptr).MoveValue();
- options.bundle_enabled = true;
- desc = f1_.CreateOfferOrError(options, ref_desc.get()).MoveValue();
- } else {
- options.bundle_enabled = true;
- ref_desc = f1_.CreateOfferOrError(options, nullptr).MoveValue();
- desc =
- f1_.CreateAnswerOrError(ref_desc.get(), options, nullptr).MoveValue();
- }
- ASSERT_TRUE(desc);
- const MediaContentDescription* audio_media_desc =
- desc->GetContentDescriptionByName("audio");
- ASSERT_TRUE(audio_media_desc);
- const MediaContentDescription* video_media_desc =
- desc->GetContentDescriptionByName("video");
- ASSERT_TRUE(video_media_desc);
- EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
- video_media_desc->cryptos()));
- ASSERT_CRYPTO(audio_media_desc, offer ? kDefaultCryptoSuiteSize : 1U,
- kDefaultSrtpCryptoSuite);
-
- // Verify the selected crypto is one from the reference audio
- // media content.
- const MediaContentDescription* ref_audio_media_desc =
- ref_desc->GetContentDescriptionByName("audio");
- bool found = false;
- for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
- if (ref_audio_media_desc->cryptos()[i].Matches(
- audio_media_desc->cryptos()[0])) {
- found = true;
- break;
- }
- }
- EXPECT_TRUE(found);
- }
-
// This test that the audio and video media direction is set to
// `expected_direction_in_answer` in an answer if the offer direction is set
// to `direction_in_offer` and the answer is willing to both send and receive.
@@ -650,59 +572,6 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
return true;
}
- void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
- MediaSessionOptions offer_opts;
- AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &offer_opts);
- offer_opts.crypto_options.srtp.enable_gcm_crypto_suites = gcm_offer;
-
- MediaSessionOptions answer_opts;
- AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &answer_opts);
- answer_opts.crypto_options.srtp.enable_gcm_crypto_suites = gcm_answer;
-
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
- std::unique_ptr<SessionDescription> offer =
- f1_.CreateOfferOrError(offer_opts, nullptr).MoveValue();
- ASSERT_TRUE(offer.get());
- if (gcm_offer && gcm_answer) {
- for (ContentInfo& content : offer->contents()) {
- auto cryptos = content.media_description()->cryptos();
- PreferGcmCryptoParameters(&cryptos);
- content.media_description()->set_cryptos(cryptos);
- }
- }
- std::unique_ptr<SessionDescription> answer =
- f2_.CreateAnswerOrError(offer.get(), answer_opts, nullptr).MoveValue();
- const ContentInfo* ac = answer->GetContentByName("audio");
- const ContentInfo* vc = answer->GetContentByName("video");
- ASSERT_TRUE(ac);
- ASSERT_TRUE(vc);
- EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
- EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
- const MediaContentDescription* acd = ac->media_description();
- const MediaContentDescription* vcd = vc->media_description();
- EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
- EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
- EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
- EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
- if (gcm_offer && gcm_answer) {
- ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
- } else {
- ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
- }
- EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
- EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
- EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
- EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
- if (gcm_offer && gcm_answer) {
- ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuiteGcm);
- } else {
- ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
- }
- EXPECT_EQ(kMediaProtocolSavpf, vcd->protocol());
- }
-
void TestTransportSequenceNumberNegotiation(
const RtpHeaderExtensions& local,
const RtpHeaderExtensions& offered,
@@ -768,7 +637,6 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
// Create a typical audio offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
- f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(CreateAudioMediaSession(), nullptr).MoveValue();
ASSERT_TRUE(offer.get());
@@ -783,14 +651,12 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached.
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
- ASSERT_CRYPTO(acd, kDefaultCryptoSuiteSize, kDefaultSrtpCryptoSuite);
- EXPECT_EQ(kMediaProtocolSavpf, acd->protocol());
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, acd->protocol());
}
// Create an offer with just Opus and RED.
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateAudioOfferWithJustOpusAndRed) {
- f1_.set_secure(SEC_ENABLED);
// First, prefer to only use opus and red.
std::vector<webrtc::RtpCodecCapability> preferences;
preferences.push_back(
@@ -819,7 +685,6 @@ TEST_F(MediaSessionDescriptionFactoryTest,
// Create an offer with RED before Opus, which enables RED with Opus encoding.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOfferWithRedForOpus) {
- f1_.set_secure(SEC_ENABLED);
// First, prefer to only use opus and red.
std::vector<webrtc::RtpCodecCapability> preferences;
preferences.push_back(
@@ -850,7 +715,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOfferWithRedForOpus) {
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
- f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(opts, nullptr).MoveValue();
ASSERT_TRUE(offer.get());
@@ -867,15 +731,13 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
- ASSERT_CRYPTO(acd, kDefaultCryptoSuiteSize, kDefaultSrtpCryptoSuite);
- EXPECT_EQ(kMediaProtocolSavpf, acd->protocol());
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, acd->protocol());
EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
EXPECT_EQ(f1_.video_sendrecv_codecs(), vcd->codecs());
EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
- ASSERT_CRYPTO(vcd, kDefaultCryptoSuiteSize, kDefaultSrtpCryptoSuite);
- EXPECT_EQ(kMediaProtocolSavpf, vcd->protocol());
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, vcd->protocol());
}
// Test creating an offer with bundle where the Codecs have the same dynamic
@@ -906,8 +768,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
// after an audio only session has been negotiated.
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateUpdatedVideoOfferWithBundle) {
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
MediaSessionOptions opts;
AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
RtpTransceiverDirection::kRecvOnly, kActive,
@@ -934,10 +794,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
EXPECT_TRUE(vcd);
EXPECT_TRUE(acd);
- ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
- EXPECT_EQ(kMediaProtocolSavpf, acd->protocol());
- ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
- EXPECT_EQ(kMediaProtocolSavpf, vcd->protocol());
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, acd->protocol());
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, vcd->protocol());
}
// Create an SCTP data offer with bundle without error.
@@ -945,7 +803,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
MediaSessionOptions opts;
opts.bundle_enabled = true;
AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
- f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(opts, nullptr).MoveValue();
EXPECT_TRUE(offer.get());
@@ -953,7 +810,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
auto dcd = GetFirstSctpDataContentDescription(offer.get());
ASSERT_TRUE(dcd);
// Since this transport is insecure, the protocol should be "SCTP".
- EXPECT_EQ(kMediaProtocolSctp, dcd->protocol());
+ EXPECT_EQ(kMediaProtocolUdpDtlsSctp, dcd->protocol());
}
// Create an SCTP data offer with bundle without error.
@@ -961,8 +818,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSecureSctpDataOffer) {
MediaSessionOptions opts;
opts.bundle_enabled = true;
AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
- f1_.set_secure(SEC_ENABLED);
- tdf1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(opts, nullptr).MoveValue();
EXPECT_TRUE(offer.get());
@@ -978,19 +833,18 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
MediaSessionOptions opts;
opts.bundle_enabled = true;
AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
- f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer1(
f1_.CreateOfferOrError(opts, nullptr).MoveValue());
ASSERT_TRUE(offer1.get());
const ContentInfo* data = offer1->GetContentByName("data");
ASSERT_TRUE(data);
- ASSERT_EQ(kMediaProtocolSctp, data->media_description()->protocol());
+ ASSERT_EQ(kMediaProtocolUdpDtlsSctp, data->media_description()->protocol());
std::unique_ptr<SessionDescription> offer2(
f1_.CreateOfferOrError(opts, offer1.get()).MoveValue());
data = offer2->GetContentByName("data");
ASSERT_TRUE(data);
- EXPECT_EQ(kMediaProtocolSctp, data->media_description()->protocol());
+ EXPECT_EQ(kMediaProtocolUdpDtlsSctp, data->media_description()->protocol());
}
// Test that if BUNDLE is enabled and all media sections are rejected then the
@@ -1289,8 +1143,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
// Create a typical audio answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(CreateAudioMediaSession(), nullptr).MoveValue();
ASSERT_TRUE(offer.get());
@@ -1308,24 +1160,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
- ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
- EXPECT_EQ(kMediaProtocolSavpf, acd->protocol());
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, acd->protocol());
}
// Create a typical audio answer with GCM ciphers enabled, and ensure it
// matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
MediaSessionOptions opts = CreateAudioMediaSession();
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(opts, nullptr).MoveValue();
ASSERT_TRUE(offer.get());
- for (ContentInfo& content : offer->contents()) {
- auto cryptos = content.media_description()->cryptos();
- PreferGcmCryptoParameters(&cryptos);
- content.media_description()->set_cryptos(cryptos);
- }
std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswerOrError(offer.get(), opts, nullptr).MoveValue();
const ContentInfo* ac = answer->GetContentByName("audio");
@@ -1339,8 +1183,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
- ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
- EXPECT_EQ(kMediaProtocolSavpf, acd->protocol());
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, acd->protocol());
}
// Create an audio answer with no common codecs, and ensure it is rejected.
@@ -1369,8 +1212,6 @@ TEST_F(MediaSessionDescriptionFactoryTest,
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(opts, nullptr).MoveValue();
ASSERT_TRUE(offer.get());
@@ -1389,31 +1230,11 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
- ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
- ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
- EXPECT_EQ(kMediaProtocolSavpf, vcd->protocol());
-}
-
-// Create a typical video answer with GCM ciphers enabled, and ensure it
-// matches what we expect.
-TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
- TestVideoGcmCipher(true, true);
-}
-
-// Create a typical video answer with GCM ciphers enabled for the offer only,
-// and ensure it matches what we expect.
-TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
- TestVideoGcmCipher(true, false);
-}
-
-// Create a typical video answer with GCM ciphers enabled for the answer only,
-// and ensure it matches what we expect.
-TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
- TestVideoGcmCipher(false, true);
+ EXPECT_EQ(kMediaProtocolDtlsSavpf, vcd->protocol());
}
// Create a video answer with no common codecs, and ensure it is rejected.
@@ -1512,13 +1333,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
// and "TCP/DTLS/SCTP" offers.
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateDataAnswerToDifferentOfferedProtos) {
- // Need to enable DTLS offer/answer generation (disabled by default in this
- // test).
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
- tdf1_.set_secure(SEC_ENABLED);
- tdf2_.set_secure(SEC_ENABLED);
-
MediaSessionOptions opts;
AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
std::unique_ptr<SessionDescription> offer =
@@ -1547,13 +1361,6 @@ TEST_F(MediaSessionDescriptionFactoryTest,
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateDataAnswerToOfferWithDefinedMessageSize) {
- // Need to enable DTLS offer/answer generation (disabled by default in this
- // test).
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
- tdf1_.set_secure(SEC_ENABLED);
- tdf2_.set_secure(SEC_ENABLED);
-
MediaSessionOptions opts;
AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
std::unique_ptr<SessionDescription> offer =
@@ -1577,13 +1384,6 @@ TEST_F(MediaSessionDescriptionFactoryTest,
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateDataAnswerToOfferWithZeroMessageSize) {
- // Need to enable DTLS offer/answer generation (disabled by default in this
- // test).
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
- tdf1_.set_secure(SEC_ENABLED);
- tdf2_.set_secure(SEC_ENABLED);
-
MediaSessionOptions opts;
AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
std::unique_ptr<SessionDescription> offer =
@@ -1672,13 +1472,13 @@ TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
RtpTransceiverDirection::kInactive);
}
-// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
+// Test that the media protocol is RTP/AVPF if DTLS is disabled.
TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
MediaSessionOptions opts = CreateAudioMediaSession();
- f1_.set_secure(SEC_DISABLED);
- f2_.set_secure(SEC_DISABLED);
- tdf1_.set_secure(SEC_DISABLED);
- tdf2_.set_secure(SEC_DISABLED);
+ tdf1_.SetInsecureForTesting();
+ tdf1_.set_certificate(nullptr);
+ tdf2_.SetInsecureForTesting();
+ tdf2_.set_certificate(nullptr);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(opts, nullptr).MoveValue();
@@ -1731,30 +1531,72 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
}
// Create a audio/video offer and answer and ensure that the
-// TransportSequenceNumber RTP header extensions are handled correctly. 02 is
-// supported and should take precedence even though not listed among locally
-// supported extensions.
+// TransportSequenceNumber RTP v1 and v2 header extensions are handled
+// correctly.
TEST_F(MediaSessionDescriptionFactoryTest,
- TestOfferAnswerWithTransportSequenceNumberInOffer) {
+ TestOfferAnswerWithTransportSequenceNumberV1LocalAndV1InOffer) {
TestTransportSequenceNumberNegotiation(
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), // Local.
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), // Offer.
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01)); // Expected answer.
}
TEST_F(MediaSessionDescriptionFactoryTest,
- TestOfferAnswerWithTransportSequenceNumber01And02InOffer) {
+ TestOfferAnswerWithTransportSequenceNumberV1LocalAndV1V2InOffer) {
TestTransportSequenceNumberNegotiation(
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), // Local.
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01And02), // Offer.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01)); // Expected answer.
+}
+TEST_F(MediaSessionDescriptionFactoryTest,
+ TestOfferAnswerWithTransportSequenceNumberV1LocalAndV2InOffer) {
+ TestTransportSequenceNumberNegotiation(
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), // Local.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02), // Offer.
+ {}); // Expected answer.
+}
+TEST_F(MediaSessionDescriptionFactoryTest,
+ TestOfferAnswerWithTransportSequenceNumberV2LocalAndV1InOffer) {
+ TestTransportSequenceNumberNegotiation(
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02), // Local.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), // Offer.
+ {}); // Expected answer.
+}
+TEST_F(MediaSessionDescriptionFactoryTest,
+ TestOfferAnswerWithTransportSequenceNumberV2LocalAndV1V2InOffer) {
+ TestTransportSequenceNumberNegotiation(
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02), // Local.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01And02), // Offer.
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02)); // Expected answer.
}
TEST_F(MediaSessionDescriptionFactoryTest,
- TestOfferAnswerWithTransportSequenceNumber02InOffer) {
+ TestOfferAnswerWithTransportSequenceNumberV2LocalAndV2InOffer) {
TestTransportSequenceNumberNegotiation(
- MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), // Local.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02), // Local.
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02), // Offer.
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02)); // Expected answer.
}
+TEST_F(MediaSessionDescriptionFactoryTest,
+ TestOfferAnswerWithTransportSequenceNumberV1V2LocalAndV1InOffer) {
+ TestTransportSequenceNumberNegotiation(
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01And02), // Local.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), // Offer.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01)); // Expected answer.
+}
+TEST_F(MediaSessionDescriptionFactoryTest,
+ TestOfferAnswerWithTransportSequenceNumberV1V2LocalAndV2InOffer) {
+ TestTransportSequenceNumberNegotiation(
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01And02), // Local.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02), // Offer.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02)); // Expected answer.
+}
+TEST_F(MediaSessionDescriptionFactoryTest,
+ TestOfferAnswerWithTransportSequenceNumberV1V2LocalAndV1V2InOffer) {
+ TestTransportSequenceNumberNegotiation(
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01And02), // Local.
+ MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01And02), // Offer.
+ MAKE_VECTOR(
+ kRtpExtensionTransportSequenceNumber01And02)); // Expected answer.
+}
TEST_F(MediaSessionDescriptionFactoryTest,
TestNegotiateFrameDescriptorWhenUnexposedLocally) {
@@ -2468,7 +2310,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
{kMediaStream1}, 1, &opts);
- f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(opts, nullptr).MoveValue();
@@ -2494,11 +2335,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
- ASSERT_CRYPTO(acd, kDefaultCryptoSuiteSize, kDefaultSrtpCryptoSuite);
EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
EXPECT_EQ(f1_.video_sendrecv_codecs(), vcd->codecs());
- ASSERT_CRYPTO(vcd, kDefaultCryptoSuiteSize, kDefaultSrtpCryptoSuite);
const StreamParamsVec& video_streams = vcd->streams();
ASSERT_EQ(1U, video_streams.size());
@@ -2529,10 +2368,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
EXPECT_EQ(acd->codecs(), updated_acd->codecs());
EXPECT_EQ(vcd->type(), updated_vcd->type());
EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
- ASSERT_CRYPTO(updated_acd, kDefaultCryptoSuiteSize, kDefaultSrtpCryptoSuite);
- EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
- ASSERT_CRYPTO(updated_vcd, kDefaultCryptoSuiteSize, kDefaultSrtpCryptoSuite);
- EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
const StreamParamsVec& updated_audio_streams = updated_acd->streams();
ASSERT_EQ(2U, updated_audio_streams.size());
@@ -2753,8 +2588,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
RtpTransceiverDirection::kRecvOnly, kActive,
&offer_opts);
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(offer_opts, nullptr).MoveValue();
@@ -2782,8 +2615,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
ASSERT_TRUE(vc);
const MediaContentDescription* acd = ac->media_description();
const MediaContentDescription* vcd = vc->media_description();
- ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
- ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
@@ -2828,11 +2659,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
const MediaContentDescription* updated_acd = ac->media_description();
const MediaContentDescription* updated_vcd = vc->media_description();
- ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
- EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
- ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
- EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
-
EXPECT_EQ(acd->type(), updated_acd->type());
EXPECT_EQ(acd->codecs(), updated_acd->codecs());
EXPECT_EQ(vcd->type(), updated_vcd->type());
@@ -3774,54 +3600,9 @@ TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfo(false, options, true);
}
-// Create an offer with bundle enabled and verify the crypto parameters are
-// the common set of the available cryptos.
-TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
- TestCryptoWithBundle(true);
-}
-
-// Create an answer with bundle enabled and verify the crypto parameters are
-// the common set of the available cryptos.
-TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
- TestCryptoWithBundle(false);
-}
-
-// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
-// DTLS is not enabled locally.
-TEST_F(MediaSessionDescriptionFactoryTest,
- TestOfferDtlsSavpfWithoutDtlsFailed) {
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
- tdf1_.set_secure(SEC_DISABLED);
- tdf2_.set_secure(SEC_DISABLED);
-
- std::unique_ptr<SessionDescription> offer =
- f1_.CreateOfferOrError(CreateAudioMediaSession(), nullptr).MoveValue();
- ASSERT_TRUE(offer.get());
- ContentInfo* offer_content = offer->GetContentByName("audio");
- ASSERT_TRUE(offer_content);
- MediaContentDescription* offer_audio_desc =
- offer_content->media_description();
- offer_audio_desc->set_protocol(kMediaProtocolDtlsSavpf);
-
- std::unique_ptr<SessionDescription> answer =
- f2_.CreateAnswerOrError(offer.get(), CreateAudioMediaSession(), nullptr)
- .MoveValue();
- ASSERT_TRUE(answer);
- ContentInfo* answer_content = answer->GetContentByName("audio");
- ASSERT_TRUE(answer_content);
-
- ASSERT_TRUE(answer_content->rejected);
-}
-
// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
// UDP/TLS/RTP/SAVPF.
TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
- tdf1_.set_secure(SEC_ENABLED);
- tdf2_.set_secure(SEC_ENABLED);
-
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(CreateAudioMediaSession(), nullptr).MoveValue();
ASSERT_TRUE(offer.get());
@@ -3845,136 +3626,24 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
EXPECT_EQ(kMediaProtocolDtlsSavpf, answer_audio_desc->protocol());
}
-// Test that we include both SDES and DTLS in the offer, but only include SDES
-// in the answer if DTLS isn't negotiated.
-TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
- tdf1_.set_secure(SEC_ENABLED);
- tdf2_.set_secure(SEC_DISABLED);
- MediaSessionOptions options;
- AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
- std::unique_ptr<SessionDescription> offer, answer;
- const MediaContentDescription* audio_media_desc;
- const MediaContentDescription* video_media_desc;
- const TransportDescription* audio_trans_desc;
- const TransportDescription* video_trans_desc;
-
- // Generate an offer with SDES and DTLS support.
- offer = f1_.CreateOfferOrError(options, nullptr).MoveValue();
- ASSERT_TRUE(offer.get());
-
- audio_media_desc = offer->GetContentDescriptionByName("audio");
- ASSERT_TRUE(audio_media_desc);
- video_media_desc = offer->GetContentDescriptionByName("video");
- ASSERT_TRUE(video_media_desc);
- EXPECT_EQ(kDefaultCryptoSuiteSize, audio_media_desc->cryptos().size());
- EXPECT_EQ(kDefaultCryptoSuiteSize, video_media_desc->cryptos().size());
-
- audio_trans_desc = offer->GetTransportDescriptionByName("audio");
- ASSERT_TRUE(audio_trans_desc);
- video_trans_desc = offer->GetTransportDescriptionByName("video");
- ASSERT_TRUE(video_trans_desc);
- ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get());
- ASSERT_TRUE(video_trans_desc->identity_fingerprint.get());
-
- // Generate an answer with only SDES support, since tdf2 has crypto disabled.
- answer = f2_.CreateAnswerOrError(offer.get(), options, nullptr).MoveValue();
- ASSERT_TRUE(answer.get());
-
- audio_media_desc = answer->GetContentDescriptionByName("audio");
- ASSERT_TRUE(audio_media_desc);
- video_media_desc = answer->GetContentDescriptionByName("video");
- ASSERT_TRUE(video_media_desc);
- EXPECT_EQ(1u, audio_media_desc->cryptos().size());
- EXPECT_EQ(1u, video_media_desc->cryptos().size());
-
- audio_trans_desc = answer->GetTransportDescriptionByName("audio");
- ASSERT_TRUE(audio_trans_desc);
- video_trans_desc = answer->GetTransportDescriptionByName("video");
- ASSERT_TRUE(video_trans_desc);
- ASSERT_FALSE(audio_trans_desc->identity_fingerprint.get());
- ASSERT_FALSE(video_trans_desc->identity_fingerprint.get());
-
- // Enable DTLS; the answer should now only have DTLS support.
- tdf2_.set_secure(SEC_ENABLED);
- answer = f2_.CreateAnswerOrError(offer.get(), options, nullptr).MoveValue();
- ASSERT_TRUE(answer.get());
-
- audio_media_desc = answer->GetContentDescriptionByName("audio");
- ASSERT_TRUE(audio_media_desc);
- video_media_desc = answer->GetContentDescriptionByName("video");
- ASSERT_TRUE(video_media_desc);
- EXPECT_TRUE(audio_media_desc->cryptos().empty());
- EXPECT_TRUE(video_media_desc->cryptos().empty());
- EXPECT_EQ(kMediaProtocolSavpf, audio_media_desc->protocol());
- EXPECT_EQ(kMediaProtocolSavpf, video_media_desc->protocol());
-
- audio_trans_desc = answer->GetTransportDescriptionByName("audio");
- ASSERT_TRUE(audio_trans_desc);
- video_trans_desc = answer->GetTransportDescriptionByName("video");
- ASSERT_TRUE(video_trans_desc);
- ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get());
- ASSERT_TRUE(video_trans_desc->identity_fingerprint.get());
-
- // Try creating offer again. DTLS enabled now, crypto's should be empty
- // in new offer.
- offer = f1_.CreateOfferOrError(options, offer.get()).MoveValue();
- ASSERT_TRUE(offer.get());
- audio_media_desc = offer->GetContentDescriptionByName("audio");
- ASSERT_TRUE(audio_media_desc);
- video_media_desc = offer->GetContentDescriptionByName("video");
- ASSERT_TRUE(video_media_desc);
- EXPECT_TRUE(audio_media_desc->cryptos().empty());
- EXPECT_TRUE(video_media_desc->cryptos().empty());
-
- audio_trans_desc = offer->GetTransportDescriptionByName("audio");
- ASSERT_TRUE(audio_trans_desc);
- video_trans_desc = offer->GetTransportDescriptionByName("video");
- ASSERT_TRUE(video_trans_desc);
- ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get());
- ASSERT_TRUE(video_trans_desc->identity_fingerprint.get());
-}
-
-// Test that an answer can't be created if cryptos are required but the offer is
-// unsecure.
-TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
- MediaSessionOptions options = CreateAudioMediaSession();
- f1_.set_secure(SEC_DISABLED);
- tdf1_.set_secure(SEC_DISABLED);
- f2_.set_secure(SEC_REQUIRED);
- tdf1_.set_secure(SEC_ENABLED);
-
- std::unique_ptr<SessionDescription> offer =
- f1_.CreateOfferOrError(options, nullptr).MoveValue();
- ASSERT_TRUE(offer.get());
-
- auto error = f2_.CreateAnswerOrError(offer.get(), options, nullptr);
- EXPECT_FALSE(error.ok());
-}
// Test that we accept a DTLS offer without SDES and create an appropriate
// answer.
TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
+ /* TODO(hta): Figure this one out.
f1_.set_secure(SEC_DISABLED);
f2_.set_secure(SEC_ENABLED);
tdf1_.set_secure(SEC_ENABLED);
tdf2_.set_secure(SEC_ENABLED);
+ */
MediaSessionOptions options;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
- // Generate an offer with DTLS but without SDES.
+ // Generate an offer with DTLS
std::unique_ptr<SessionDescription> offer =
f1_.CreateOfferOrError(options, nullptr).MoveValue();
ASSERT_TRUE(offer.get());
- const AudioContentDescription* audio_offer =
- GetFirstAudioContentDescription(offer.get());
- ASSERT_TRUE(audio_offer->cryptos().empty());
- const VideoContentDescription* video_offer =
- GetFirstVideoContentDescription(offer.get());
- ASSERT_TRUE(video_offer->cryptos().empty());
-
const TransportDescription* audio_offer_trans_desc =
offer->GetTransportDescriptionByName("audio");
ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get());
@@ -4656,14 +4325,10 @@ class MediaProtocolTest : public testing::TestWithParam<const char*> {
MAKE_VECTOR(kAudioCodecs2));
f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2),
MAKE_VECTOR(kVideoCodecs2));
- f1_.set_secure(SEC_ENABLED);
- f2_.set_secure(SEC_ENABLED);
tdf1_.set_certificate(rtc::RTCCertificate::Create(
std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
tdf2_.set_certificate(rtc::RTCCertificate::Create(
std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
- tdf1_.set_secure(SEC_ENABLED);
- tdf2_.set_secure(SEC_ENABLED);
}
protected:
@@ -4710,6 +4375,9 @@ INSTANTIATE_TEST_SUITE_P(MediaProtocolDtlsPatternTest,
TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
webrtc::test::ScopedKeyValueConfig field_trials;
TransportDescriptionFactory tdf(field_trials);
+ tdf.set_certificate(rtc::RTCCertificate::Create(
+ std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id"))));
+
UniqueRandomIdGenerator ssrc_generator;
MediaSessionDescriptionFactory sf(nullptr, false, &ssrc_generator, &tdf);
std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
@@ -4779,6 +4447,9 @@ bool CodecsMatch(const std::vector<Codec>& codecs1,
void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
webrtc::test::ScopedKeyValueConfig field_trials;
TransportDescriptionFactory tdf(field_trials);
+ tdf.set_certificate(rtc::RTCCertificate::Create(
+ std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id"))));
+
UniqueRandomIdGenerator ssrc_generator;
MediaSessionDescriptionFactory sf(nullptr, false, &ssrc_generator, &tdf);
const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
@@ -4879,6 +4550,11 @@ void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
webrtc::test::ScopedKeyValueConfig field_trials;
TransportDescriptionFactory offer_tdf(field_trials);
TransportDescriptionFactory answer_tdf(field_trials);
+ offer_tdf.set_certificate(rtc::RTCCertificate::Create(
+ std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("offer_id"))));
+ answer_tdf.set_certificate(
+ rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
+ new rtc::FakeSSLIdentity("answer_id"))));
UniqueRandomIdGenerator ssrc_generator1, ssrc_generator2;
MediaSessionDescriptionFactory offer_factory(nullptr, false, &ssrc_generator1,
&offer_tdf);
diff --git a/third_party/libwebrtc/pc/peer_connection.cc b/third_party/libwebrtc/pc/peer_connection.cc
index 8c9b0cbab6..76cf13aa18 100644
--- a/third_party/libwebrtc/pc/peer_connection.cc
+++ b/third_party/libwebrtc/pc/peer_connection.cc
@@ -104,13 +104,7 @@ uint32_t ConvertIceTransportTypeToCandidateFilter(
IceCandidatePairType GetIceCandidatePairCounter(
const cricket::Candidate& local,
const cricket::Candidate& remote) {
- const auto& l = local.type();
- const auto& r = remote.type();
- const auto& host = cricket::LOCAL_PORT_TYPE;
- const auto& srflx = cricket::STUN_PORT_TYPE;
- const auto& relay = cricket::RELAY_PORT_TYPE;
- const auto& prflx = cricket::PRFLX_PORT_TYPE;
- if (l == host && r == host) {
+ if (local.is_local() && remote.is_local()) {
bool local_hostname =
!local.address().hostname().empty() && local.address().IsUnresolvedIP();
bool remote_hostname = !remote.address().hostname().empty() &&
@@ -143,34 +137,41 @@ IceCandidatePairType GetIceCandidatePairCounter(
}
}
}
- if (l == host && r == srflx)
- return kIceCandidatePairHostSrflx;
- if (l == host && r == relay)
- return kIceCandidatePairHostRelay;
- if (l == host && r == prflx)
- return kIceCandidatePairHostPrflx;
- if (l == srflx && r == host)
- return kIceCandidatePairSrflxHost;
- if (l == srflx && r == srflx)
- return kIceCandidatePairSrflxSrflx;
- if (l == srflx && r == relay)
- return kIceCandidatePairSrflxRelay;
- if (l == srflx && r == prflx)
- return kIceCandidatePairSrflxPrflx;
- if (l == relay && r == host)
- return kIceCandidatePairRelayHost;
- if (l == relay && r == srflx)
- return kIceCandidatePairRelaySrflx;
- if (l == relay && r == relay)
- return kIceCandidatePairRelayRelay;
- if (l == relay && r == prflx)
- return kIceCandidatePairRelayPrflx;
- if (l == prflx && r == host)
- return kIceCandidatePairPrflxHost;
- if (l == prflx && r == srflx)
- return kIceCandidatePairPrflxSrflx;
- if (l == prflx && r == relay)
- return kIceCandidatePairPrflxRelay;
+
+ if (local.is_local()) {
+ if (remote.is_stun())
+ return kIceCandidatePairHostSrflx;
+ if (remote.is_relay())
+ return kIceCandidatePairHostRelay;
+ if (remote.is_prflx())
+ return kIceCandidatePairHostPrflx;
+ } else if (local.is_stun()) {
+ if (remote.is_local())
+ return kIceCandidatePairSrflxHost;
+ if (remote.is_stun())
+ return kIceCandidatePairSrflxSrflx;
+ if (remote.is_relay())
+ return kIceCandidatePairSrflxRelay;
+ if (remote.is_prflx())
+ return kIceCandidatePairSrflxPrflx;
+ } else if (local.is_relay()) {
+ if (remote.is_local())
+ return kIceCandidatePairRelayHost;
+ if (remote.is_stun())
+ return kIceCandidatePairRelaySrflx;
+ if (remote.is_relay())
+ return kIceCandidatePairRelayRelay;
+ if (remote.is_prflx())
+ return kIceCandidatePairRelayPrflx;
+ } else if (local.is_prflx()) {
+ if (remote.is_local())
+ return kIceCandidatePairPrflxHost;
+ if (remote.is_stun())
+ return kIceCandidatePairPrflxSrflx;
+ if (remote.is_relay())
+ return kIceCandidatePairPrflxRelay;
+ }
+
return kIceCandidatePairMax;
}
@@ -347,15 +348,7 @@ bool DtlsEnabled(const PeerConnectionInterface::RTCConfiguration& configuration,
return false;
// Enable DTLS by default if we have an identity store or a certificate.
- bool default_enabled =
- (dependencies.cert_generator || !configuration.certificates.empty());
-
-#if defined(WEBRTC_FUCHSIA)
- // The `configuration` can override the default value.
- return configuration.enable_dtls_srtp.value_or(default_enabled);
-#else
- return default_enabled;
-#endif
+ return (dependencies.cert_generator || !configuration.certificates.empty());
}
// Calls `ParseIceServersOrError` to extract ice server information from the
@@ -415,9 +408,6 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
int max_ipv6_networks;
bool disable_link_local_networks;
absl::optional<int> screencast_min_bitrate;
-#if defined(WEBRTC_FUCHSIA)
- absl::optional<bool> enable_dtls_srtp;
-#endif
TcpCandidatePolicy tcp_candidate_policy;
CandidateNetworkPolicy candidate_network_policy;
int audio_jitter_buffer_max_packets;
@@ -482,9 +472,6 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
max_ipv6_networks == o.max_ipv6_networks &&
disable_link_local_networks == o.disable_link_local_networks &&
screencast_min_bitrate == o.screencast_min_bitrate &&
-#if defined(WEBRTC_FUCHSIA)
- enable_dtls_srtp == o.enable_dtls_srtp &&
-#endif
ice_candidate_pool_size == o.ice_candidate_pool_size &&
prune_turn_ports == o.prune_turn_ports &&
turn_port_prune_policy == o.turn_port_prune_policy &&
@@ -1694,6 +1681,15 @@ RTCError PeerConnection::SetBitrate(const BitrateSettings& bitrate) {
return RTCError::OK();
}
+void PeerConnection::ReconfigureBandwidthEstimation(
+ const BandwidthEstimationSettings& settings) {
+ worker_thread()->PostTask(SafeTask(worker_thread_safety_, [this, settings]() {
+ RTC_DCHECK_RUN_ON(worker_thread());
+ call_->GetTransportControllerSend()->ReconfigureBandwidthEstimation(
+ settings);
+ }));
+}
+
void PeerConnection::SetAudioPlayout(bool playout) {
if (!worker_thread()->IsCurrent()) {
worker_thread()->BlockingCall(
@@ -2706,9 +2702,7 @@ void PeerConnection::ReportRemoteIceCandidateAdded(
bool PeerConnection::SrtpRequired() const {
RTC_DCHECK_RUN_ON(signaling_thread());
- return (dtls_enabled_ ||
- sdp_handler_->webrtc_session_desc_factory()->SdesPolicy() ==
- cricket::SEC_REQUIRED);
+ return dtls_enabled_;
}
void PeerConnection::OnTransportControllerGatheringState(
diff --git a/third_party/libwebrtc/pc/peer_connection.h b/third_party/libwebrtc/pc/peer_connection.h
index 406bc1cef2..3c923139dc 100644
--- a/third_party/libwebrtc/pc/peer_connection.h
+++ b/third_party/libwebrtc/pc/peer_connection.h
@@ -236,6 +236,8 @@ class PeerConnection : public PeerConnectionInternal,
const std::vector<cricket::Candidate>& candidates) override;
RTCError SetBitrate(const BitrateSettings& bitrate) override;
+ void ReconfigureBandwidthEstimation(
+ const BandwidthEstimationSettings& settings) override;
void SetAudioPlayout(bool playout) override;
void SetAudioRecording(bool recording) override;
diff --git a/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc b/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc
index 3b3f502e1f..1d90e04714 100644
--- a/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc
+++ b/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc
@@ -24,7 +24,6 @@
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/create_peerconnection_factory.h"
#include "api/crypto/crypto_options.h"
-#include "api/crypto_params.h"
#include "api/jsep.h"
#include "api/peer_connection_interface.h"
#include "api/scoped_refptr.h"
@@ -178,13 +177,6 @@ SdpContentPredicate HaveDtlsFingerprint() {
};
}
-SdpContentPredicate HaveSdesCryptos() {
- return [](const cricket::ContentInfo* content,
- const cricket::TransportInfo* transport) {
- return !content->media_description()->cryptos().empty();
- };
-}
-
SdpContentPredicate HaveProtocol(const std::string& protocol) {
return [protocol](const cricket::ContentInfo* content,
const cricket::TransportInfo* transport) {
@@ -192,22 +184,6 @@ SdpContentPredicate HaveProtocol(const std::string& protocol) {
};
}
-SdpContentPredicate HaveSdesGcmCryptos(size_t num_crypto_suites) {
- return [num_crypto_suites](const cricket::ContentInfo* content,
- const cricket::TransportInfo* transport) {
- const auto& cryptos = content->media_description()->cryptos();
- if (cryptos.size() != num_crypto_suites) {
- return false;
- }
- for (size_t i = 0; i < cryptos.size(); ++i) {
- if (cryptos[i].key_params.size() == 67U &&
- cryptos[i].crypto_suite == "AEAD_AES_256_GCM")
- return true;
- }
- return false;
- };
-}
-
class PeerConnectionCryptoTest
: public PeerConnectionCryptoBaseTest,
public ::testing::WithParamInterface<SdpSemantics> {
@@ -215,20 +191,13 @@ class PeerConnectionCryptoTest
PeerConnectionCryptoTest() : PeerConnectionCryptoBaseTest(GetParam()) {}
};
-SdpContentMutator RemoveSdesCryptos() {
- return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
- content->media_description()->set_cryptos({});
- };
-}
-
SdpContentMutator RemoveDtlsFingerprint() {
return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
transport->description.identity_fingerprint.reset();
};
}
-// When DTLS is enabled, the SDP offer/answer should have a DTLS fingerprint and
-// no SDES cryptos.
+// When DTLS is enabled, the SDP offer/answer should have a DTLS fingerprint
TEST_P(PeerConnectionCryptoTest, CorrectCryptoInOfferWhenDtlsEnabled) {
RTCConfiguration config;
auto caller = CreatePeerConnectionWithAudioVideo(config);
@@ -238,7 +207,6 @@ TEST_P(PeerConnectionCryptoTest, CorrectCryptoInOfferWhenDtlsEnabled) {
ASSERT_FALSE(offer->description()->contents().empty());
EXPECT_TRUE(SdpContentsAll(HaveDtlsFingerprint(), offer->description()));
- EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), offer->description()));
EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolDtlsSavpf),
offer->description()));
}
@@ -253,238 +221,10 @@ TEST_P(PeerConnectionCryptoTest, CorrectCryptoInAnswerWhenDtlsEnabled) {
ASSERT_FALSE(answer->description()->contents().empty());
EXPECT_TRUE(SdpContentsAll(HaveDtlsFingerprint(), answer->description()));
- EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), answer->description()));
EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolDtlsSavpf),
answer->description()));
}
-#if defined(WEBRTC_FUCHSIA)
-// When DTLS is disabled, the SDP offer/answer should include SDES cryptos and
-// should not have a DTLS fingerprint.
-TEST_P(PeerConnectionCryptoTest, CorrectCryptoInOfferWhenDtlsDisabled) {
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- ASSERT_TRUE(offer);
-
- ASSERT_FALSE(offer->description()->contents().empty());
- EXPECT_TRUE(SdpContentsAll(HaveSdesCryptos(), offer->description()));
- EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), offer->description()));
- EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolSavpf),
- offer->description()));
-}
-
-TEST_P(PeerConnectionCryptoTest, CorrectCryptoInAnswerWhenDtlsDisabled) {
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- callee->SetRemoteDescription(caller->CreateOffer());
- auto answer = callee->CreateAnswer();
- ASSERT_TRUE(answer);
-
- ASSERT_FALSE(answer->description()->contents().empty());
- EXPECT_TRUE(SdpContentsAll(HaveSdesCryptos(), answer->description()));
- EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), answer->description()));
- EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolSavpf),
- answer->description()));
-}
-
-// When encryption is disabled, the SDP offer/answer should have neither a DTLS
-// fingerprint nor any SDES crypto options.
-TEST_P(PeerConnectionCryptoTest, CorrectCryptoInOfferWhenEncryptionDisabled) {
- PeerConnectionFactoryInterface::Options options;
- options.disable_encryption = true;
- pc_factory_->SetOptions(options);
-
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- ASSERT_TRUE(offer);
-
- ASSERT_FALSE(offer->description()->contents().empty());
- EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), offer->description()));
- EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), offer->description()));
- EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolAvpf),
- offer->description()));
-}
-
-TEST_P(PeerConnectionCryptoTest, CorrectCryptoInAnswerWhenEncryptionDisabled) {
- PeerConnectionFactoryInterface::Options options;
- options.disable_encryption = true;
- pc_factory_->SetOptions(options);
-
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- callee->SetRemoteDescription(caller->CreateOffer());
- auto answer = callee->CreateAnswer();
- ASSERT_TRUE(answer);
-
- ASSERT_FALSE(answer->description()->contents().empty());
- EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), answer->description()));
- EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), answer->description()));
- EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolAvpf),
- answer->description()));
-}
-
-// CryptoOptions has been promoted to RTCConfiguration. As such if it is ever
-// set in the configuration it should overrite the settings set in the factory.
-TEST_P(PeerConnectionCryptoTest, RTCConfigurationCryptoOptionOverridesFactory) {
- PeerConnectionFactoryInterface::Options options;
- options.crypto_options.srtp.enable_gcm_crypto_suites = true;
- pc_factory_->SetOptions(options);
-
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- CryptoOptions crypto_options;
- crypto_options.srtp.enable_gcm_crypto_suites = false;
- config.crypto_options = crypto_options;
- auto caller = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- ASSERT_TRUE(offer);
-
- ASSERT_FALSE(offer->description()->contents().empty());
- // This should exist if GCM is enabled see CorrectCryptoInOfferWithSdesAndGcm
- EXPECT_FALSE(SdpContentsAll(HaveSdesGcmCryptos(3), offer->description()));
-}
-
-// When DTLS is disabled and GCM cipher suites are enabled, the SDP offer/answer
-// should have the correct ciphers in the SDES crypto options.
-// With GCM cipher suites enabled, there will be 3 cryptos in the offer and 1
-// in the answer.
-TEST_P(PeerConnectionCryptoTest, CorrectCryptoInOfferWithSdesAndGcm) {
- PeerConnectionFactoryInterface::Options options;
- options.crypto_options.srtp.enable_gcm_crypto_suites = true;
- pc_factory_->SetOptions(options);
-
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- ASSERT_TRUE(offer);
-
- ASSERT_FALSE(offer->description()->contents().empty());
- EXPECT_TRUE(SdpContentsAll(HaveSdesGcmCryptos(3), offer->description()));
-}
-
-TEST_P(PeerConnectionCryptoTest, CorrectCryptoInAnswerWithSdesAndGcm) {
- PeerConnectionFactoryInterface::Options options;
- options.crypto_options.srtp.enable_gcm_crypto_suites = true;
- pc_factory_->SetOptions(options);
-
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- for (cricket::ContentInfo& content : offer->description()->contents()) {
- auto cryptos = content.media_description()->cryptos();
- cryptos.erase(cryptos.begin()); // Assumes that non-GCM is the default.
- content.media_description()->set_cryptos(cryptos);
- }
-
- callee->SetRemoteDescription(std::move(offer));
- auto answer = callee->CreateAnswer();
- ASSERT_TRUE(answer);
-
- ASSERT_FALSE(answer->description()->contents().empty());
- EXPECT_TRUE(SdpContentsAll(HaveSdesGcmCryptos(1), answer->description()));
-}
-
-TEST_P(PeerConnectionCryptoTest, CanSetSdesGcmRemoteOfferAndLocalAnswer) {
- PeerConnectionFactoryInterface::Options options;
- options.crypto_options.srtp.enable_gcm_crypto_suites = true;
- pc_factory_->SetOptions(options);
-
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- ASSERT_TRUE(offer);
- ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
-
- auto answer = callee->CreateAnswer();
- ASSERT_TRUE(answer);
- ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
-}
-
-// The following group tests that two PeerConnections can successfully exchange
-// an offer/answer when DTLS is off and that they will refuse any offer/answer
-// applied locally/remotely if it does not include SDES cryptos.
-TEST_P(PeerConnectionCryptoTest, ExchangeOfferAnswerWhenSdesOn) {
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOfferAndSetAsLocal();
- ASSERT_TRUE(offer);
- ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
-
- auto answer = callee->CreateAnswerAndSetAsLocal();
- ASSERT_TRUE(answer);
- ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
-}
-TEST_P(PeerConnectionCryptoTest, FailToSetLocalOfferWithNoCryptosWhenSdesOn) {
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- SdpContentsForEach(RemoveSdesCryptos(), offer->description());
-
- EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
-}
-TEST_P(PeerConnectionCryptoTest, FailToSetRemoteOfferWithNoCryptosWhenSdesOn) {
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOffer();
- SdpContentsForEach(RemoveSdesCryptos(), offer->description());
-
- EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
-}
-TEST_P(PeerConnectionCryptoTest, FailToSetLocalAnswerWithNoCryptosWhenSdesOn) {
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
- auto answer = callee->CreateAnswer();
- SdpContentsForEach(RemoveSdesCryptos(), answer->description());
-
- EXPECT_FALSE(callee->SetLocalDescription(std::move(answer)));
-}
-TEST_P(PeerConnectionCryptoTest, FailToSetRemoteAnswerWithNoCryptosWhenSdesOn) {
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
- auto answer = callee->CreateAnswerAndSetAsLocal();
- SdpContentsForEach(RemoveSdesCryptos(), answer->description());
-
- EXPECT_FALSE(caller->SetRemoteDescription(std::move(answer)));
-}
-#endif
-
// The following group tests that two PeerConnections can successfully exchange
// an offer/answer when DTLS is on and that they will refuse any offer/answer
// applied locally/remotely if it does not include a DTLS fingerprint.
@@ -545,28 +285,6 @@ TEST_P(PeerConnectionCryptoTest,
EXPECT_FALSE(caller->SetRemoteDescription(std::move(answer)));
}
-#if defined(WEBRTC_FUCHSIA)
-// Test that an offer/answer can be exchanged when encryption is disabled.
-TEST_P(PeerConnectionCryptoTest, ExchangeOfferAnswerWhenNoEncryption) {
- PeerConnectionFactoryInterface::Options options;
- options.disable_encryption = true;
- pc_factory_->SetOptions(options);
-
- RTCConfiguration config;
- config.enable_dtls_srtp.emplace(false);
- auto caller = CreatePeerConnectionWithAudioVideo(config);
- auto callee = CreatePeerConnectionWithAudioVideo(config);
-
- auto offer = caller->CreateOfferAndSetAsLocal();
- ASSERT_TRUE(offer);
- ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
-
- auto answer = callee->CreateAnswerAndSetAsLocal();
- ASSERT_TRUE(answer);
- ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
-}
-#endif
-
// Tests that a DTLS call can be established when the certificate is specified
// in the PeerConnection config and no certificate generator is specified.
TEST_P(PeerConnectionCryptoTest,
diff --git a/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc b/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc
index 4a93e915df..06299d7029 100644
--- a/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc
+++ b/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc
@@ -9,6 +9,7 @@
*/
#include <string>
+#include <string_view>
#include <vector>
#include "absl/strings/match.h"
@@ -41,6 +42,7 @@
#include "pc/test/simulcast_layer_util.h"
#include "rtc_base/gunit.h"
#include "rtc_base/physical_socket_server.h"
+#include "rtc_base/thread.h"
#include "test/gmock.h"
#include "test/gtest.h"
@@ -269,6 +271,34 @@ class PeerConnectionEncodingsIntegrationTest : public ::testing::Test {
return num_sending_layers == num_active_layers;
}
+ int EncodedFrames(rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper,
+ std::string_view rid) {
+ rtc::scoped_refptr<const RTCStatsReport> report = GetStats(pc_wrapper);
+ std::vector<const RTCOutboundRtpStreamStats*> outbound_rtps =
+ report->GetStatsOfType<RTCOutboundRtpStreamStats>();
+ for (const auto* outbound_rtp : outbound_rtps) {
+ if (outbound_rtp->rid.value_or("") == rid) {
+ return outbound_rtp->frames_encoded.value_or(0);
+ }
+ }
+ return 0;
+ }
+
+ bool EncodingIsActive(
+ rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper,
+ std::string_view rid) {
+ rtc::scoped_refptr<const RTCStatsReport> report = GetStats(pc_wrapper);
+ std::vector<const RTCOutboundRtpStreamStats*> outbound_rtps =
+ report->GetStatsOfType<RTCOutboundRtpStreamStats>();
+ for (const auto* outbound_rtp : outbound_rtps) {
+ if (outbound_rtp->rid.value_or("") == rid) {
+ return *outbound_rtp->active;
+ }
+ }
+ RTC_CHECK(false) << "Rid not found: " << rid;
+ return false;
+ }
+
bool HasOutboundRtpWithRidAndScalabilityMode(
rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper,
absl::string_view rid,
@@ -1964,6 +1994,65 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, Simulcast) {
EXPECT_THAT(*outbound_rtps[2]->scalability_mode, StrEq("L1T3"));
}
+TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
+ SimulcastEncodingStopWhenRtpEncodingChangeToInactive) {
+ rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
+ if (SkipTestDueToAv1Missing(local_pc_wrapper)) {
+ return;
+ }
+ rtc::scoped_refptr<PeerConnectionTestWrapper> remote_pc_wrapper = CreatePc();
+ ExchangeIceCandidates(local_pc_wrapper, remote_pc_wrapper);
+
+ std::vector<cricket::SimulcastLayer> layers =
+ CreateLayers({"q", "h", "f"}, /*active=*/true);
+ rtc::scoped_refptr<RtpTransceiverInterface> transceiver =
+ AddTransceiverWithSimulcastLayers(local_pc_wrapper, remote_pc_wrapper,
+ layers);
+ std::vector<RtpCodecCapability> codecs =
+ GetCapabilitiesAndRestrictToCodec(local_pc_wrapper, codec_name_);
+ transceiver->SetCodecPreferences(codecs);
+
+ rtc::scoped_refptr<RtpSenderInterface> sender = transceiver->sender();
+ RtpParameters parameters = sender->GetParameters();
+ ASSERT_THAT(parameters.encodings, SizeIs(3));
+ ASSERT_EQ(parameters.encodings[0].rid, "q");
+ parameters.encodings[0].scalability_mode = "L1T3";
+ parameters.encodings[0].scale_resolution_down_by = 4;
+ ASSERT_EQ(parameters.encodings[1].rid, "h");
+ parameters.encodings[1].scalability_mode = "L1T3";
+ parameters.encodings[1].scale_resolution_down_by = 2;
+ ASSERT_EQ(parameters.encodings[2].rid, "f");
+ parameters.encodings[2].scalability_mode = "L1T3";
+ parameters.encodings[2].scale_resolution_down_by = 1;
+ sender->SetParameters(parameters);
+
+ NegotiateWithSimulcastTweaks(local_pc_wrapper, remote_pc_wrapper);
+ local_pc_wrapper->WaitForConnection();
+ remote_pc_wrapper->WaitForConnection();
+
+ ASSERT_TRUE_WAIT(EncodedFrames(local_pc_wrapper, "f") > 1,
+ kLongTimeoutForRampingUp.ms());
+
+ // Switch higest layer to Inactive.
+ parameters = sender->GetParameters();
+ ASSERT_THAT(parameters.encodings, SizeIs(3));
+ parameters.encodings[2].active = false;
+ sender->SetParameters(parameters);
+ ASSERT_TRUE_WAIT(!EncodingIsActive(local_pc_wrapper, "f"),
+ kDefaultTimeout.ms());
+
+ int encoded_frames_f = EncodedFrames(local_pc_wrapper, "f");
+ int encoded_frames_h = EncodedFrames(local_pc_wrapper, "h");
+ int encoded_frames_q = EncodedFrames(local_pc_wrapper, "q");
+
+ // Wait until the encoder has encoded another 10 frames on lower layers.
+ ASSERT_TRUE_WAIT(EncodedFrames(local_pc_wrapper, "q") > encoded_frames_q + 10,
+ kDefaultTimeout.ms());
+ ASSERT_TRUE_WAIT(EncodedFrames(local_pc_wrapper, "h") > encoded_frames_h + 10,
+ kDefaultTimeout.ms());
+ EXPECT_LE(EncodedFrames(local_pc_wrapper, "f") - encoded_frames_f, 2);
+}
+
INSTANTIATE_TEST_SUITE_P(StandardPath,
PeerConnectionEncodingsIntegrationParameterizedTest,
::testing::Values("VP8",
diff --git a/third_party/libwebrtc/pc/peer_connection_ice_unittest.cc b/third_party/libwebrtc/pc/peer_connection_ice_unittest.cc
index 492e108cbc..267cca4959 100644
--- a/third_party/libwebrtc/pc/peer_connection_ice_unittest.cc
+++ b/third_party/libwebrtc/pc/peer_connection_ice_unittest.cc
@@ -94,7 +94,6 @@ using ::testing::Values;
constexpr int kIceCandidatesTimeout = 10000;
constexpr int64_t kWaitTimeout = 10000;
-constexpr uint64_t kTiebreakerDefault = 44444;
class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
public:
@@ -362,7 +361,7 @@ class PeerConnectionIceTest
<< " != " << b.address().ToString();
}
if (a.type() != b.type()) {
- failure_info << "\ntype: " << a.type() << " != " << b.type();
+ failure_info << "\ntype: " << a.type_name() << " != " << b.type_name();
}
std::string failure_info_str = failure_info.str();
if (failure_info_str.empty()) {
@@ -1448,7 +1447,6 @@ class PeerConnectionIceConfigTest : public ::testing::Test {
packet_socket_factory_.get(),
&field_trials_));
port_allocator_ = port_allocator.get();
- port_allocator_->SetIceTiebreaker(kTiebreakerDefault);
PeerConnectionDependencies pc_dependencies(&observer_);
pc_dependencies.allocator = std::move(port_allocator);
auto result = pc_factory_->CreatePeerConnectionOrError(
diff --git a/third_party/libwebrtc/pc/peer_connection_integrationtest.cc b/third_party/libwebrtc/pc/peer_connection_integrationtest.cc
index c960a36b5e..24ca52f619 100644
--- a/third_party/libwebrtc/pc/peer_connection_integrationtest.cc
+++ b/third_party/libwebrtc/pc/peer_connection_integrationtest.cc
@@ -275,26 +275,6 @@ TEST_P(PeerConnectionIntegrationTest, EndToEndCallWithDtls) {
ASSERT_TRUE(ExpectNewFrames(media_expectations));
}
-#if defined(WEBRTC_FUCHSIA)
-// Uses SDES instead of DTLS for key agreement.
-TEST_P(PeerConnectionIntegrationTest, EndToEndCallWithSdes) {
- PeerConnectionInterface::RTCConfiguration sdes_config;
- sdes_config.enable_dtls_srtp.emplace(false);
- ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(sdes_config, sdes_config));
- ConnectFakeSignaling();
-
- // Do normal offer/answer and wait for some frames to be received in each
- // direction.
- caller()->AddAudioVideoTracks();
- callee()->AddAudioVideoTracks();
- caller()->CreateAndSetAndSignalOffer();
- ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
- MediaExpectations media_expectations;
- media_expectations.ExpectBidirectionalAudioAndVideo();
- ASSERT_TRUE(ExpectNewFrames(media_expectations));
-}
-#endif
-
// Basic end-to-end test specifying the `enable_encrypted_rtp_header_extensions`
// option to offer encrypted versions of all header extensions alongside the
// unencrypted versions.
@@ -3087,25 +3067,23 @@ TEST_P(PeerConnectionIntegrationTest, RegatherAfterChangingIceTransportType) {
// `WebRTC.PeerConnection.CandidatePairType_UDP` in this test since this
// metric is only populated when we reach kIceConnectionComplete in the
// current implementation.
- EXPECT_EQ(cricket::RELAY_PORT_TYPE,
- caller()->last_candidate_gathered().type());
- EXPECT_EQ(cricket::RELAY_PORT_TYPE,
- callee()->last_candidate_gathered().type());
+ EXPECT_TRUE(caller()->last_candidate_gathered().is_relay());
+ EXPECT_TRUE(callee()->last_candidate_gathered().is_relay());
// Loosen the caller's candidate filter.
caller_config = caller()->pc()->GetConfiguration();
caller_config.type = PeerConnectionInterface::kAll;
caller()->pc()->SetConfiguration(caller_config);
// We should have gathered a new host candidate.
- EXPECT_EQ_WAIT(cricket::LOCAL_PORT_TYPE,
- caller()->last_candidate_gathered().type(), kDefaultTimeout);
+ EXPECT_TRUE_WAIT(caller()->last_candidate_gathered().is_local(),
+ kDefaultTimeout);
// Loosen the callee's candidate filter.
callee_config = callee()->pc()->GetConfiguration();
callee_config.type = PeerConnectionInterface::kAll;
callee()->pc()->SetConfiguration(callee_config);
- EXPECT_EQ_WAIT(cricket::LOCAL_PORT_TYPE,
- callee()->last_candidate_gathered().type(), kDefaultTimeout);
+ EXPECT_TRUE_WAIT(callee()->last_candidate_gathered().is_local(),
+ kDefaultTimeout);
// Create an offer and verify that it does not contain an ICE restart (i.e new
// ice credentials).
diff --git a/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc b/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc
index 61794bb0f9..71c85d4c6f 100644
--- a/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc
+++ b/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc
@@ -114,7 +114,6 @@ static const char kVideoTracks[][32] = {"videotrack0", "videotrack1"};
static const char kRecvonly[] = "recvonly";
static const char kSendrecv[] = "sendrecv";
-constexpr uint64_t kTiebreakerDefault = 44444;
// Reference SDP with a MediaStream with label "stream1" and audio track with
// id "audio_1" and a video track with id "video_1;
@@ -420,29 +419,6 @@ static const char kSdpStringMs1Video1[] =
"a=ssrc:4 cname:stream1\r\n"
"a=ssrc:4 msid:stream1 videotrack1\r\n";
-static const char kDtlsSdesFallbackSdp[] =
- "v=0\r\n"
- "o=xxxxxx 7 2 IN IP4 0.0.0.0\r\n"
- "s=-\r\n"
- "c=IN IP4 0.0.0.0\r\n"
- "t=0 0\r\n"
- "a=group:BUNDLE audio\r\n"
- "a=msid-semantic: WMS\r\n"
- "m=audio 1 RTP/SAVPF 0\r\n"
- "a=sendrecv\r\n"
- "a=rtcp-mux\r\n"
- "a=mid:audio\r\n"
- "a=ssrc:1 cname:stream1\r\n"
- "a=ice-ufrag:e5785931\r\n"
- "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
- "a=rtpmap:0 pcmu/8000\r\n"
- "a=fingerprint:sha-1 "
- "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
- "a=setup:actpass\r\n"
- "a=crypto:0 AES_CM_128_HMAC_SHA1_80 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n";
-
class RtcEventLogOutputNull final : public RtcEventLogOutput {
public:
bool IsActive() const override { return true; }
@@ -734,7 +710,6 @@ class PeerConnectionInterfaceBaseTest : public ::testing::Test {
std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get()),
&field_trials_));
port_allocator_ = port_allocator.get();
- port_allocator_->SetIceTiebreaker(kTiebreakerDefault);
// Create certificate generator unless DTLS constraint is explicitly set to
// false.
@@ -1662,7 +1637,7 @@ TEST_P(PeerConnectionInterfaceTest, AddTrackWithoutStream) {
// Test that we can call GetStats() after AddTrack but before connecting
// the PeerConnection to a peer.
TEST_P(PeerConnectionInterfaceTest, AddTrackBeforeConnecting) {
- CreatePeerConnectionWithoutDtls();
+ CreatePeerConnection();
rtc::scoped_refptr<AudioTrackInterface> audio_track(
CreateAudioTrack("audio_track"));
rtc::scoped_refptr<VideoTrackInterface> video_track(
@@ -1673,7 +1648,7 @@ TEST_P(PeerConnectionInterfaceTest, AddTrackBeforeConnecting) {
}
TEST_P(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddTrack) {
- CreatePeerConnectionWithoutDtls();
+ CreatePeerConnection();
rtc::scoped_refptr<AudioTrackInterface> audio_track(
CreateAudioTrack("audio_track"));
rtc::scoped_refptr<VideoTrackInterface> video_track(
@@ -1695,7 +1670,7 @@ TEST_P(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddTrack) {
// Don't run under Unified Plan since the stream API is not available.
TEST_F(PeerConnectionInterfaceTestPlanB, AttachmentIdIsSetOnAddStream) {
- CreatePeerConnectionWithoutDtls();
+ CreatePeerConnection();
AddVideoStream(kStreamId1);
auto senders = pc_->GetSenders();
ASSERT_EQ(1u, senders.size());
@@ -2130,24 +2105,6 @@ TEST_P(PeerConnectionInterfaceTest, ReceiveFireFoxOffer) {
#endif
}
-// Test that fallback from DTLS to SDES is not supported.
-// The fallback was previously supported but was removed to simplify the code
-// and because it's non-standard.
-TEST_P(PeerConnectionInterfaceTest, DtlsSdesFallbackNotSupported) {
- RTCConfiguration rtc_config;
- CreatePeerConnection(rtc_config);
- // Wait for fake certificate to be generated. Previously, this is what caused
- // the "a=crypto" lines to be rejected.
- AddAudioTrack("audio_label");
- AddVideoTrack("video_label");
- ASSERT_NE(nullptr, fake_certificate_generator_);
- EXPECT_EQ_WAIT(1, fake_certificate_generator_->generated_certificates(),
- kTimeout);
- std::unique_ptr<SessionDescriptionInterface> desc(
- CreateSessionDescription(SdpType::kOffer, kDtlsSdesFallbackSdp, nullptr));
- EXPECT_FALSE(DoSetSessionDescription(std::move(desc), /*local=*/false));
-}
-
// Test that we can create an audio only offer and receive an answer with a
// limited set of audio codecs and receive an updated offer with more audio
// codecs, where the added codecs are not supported.
diff --git a/third_party/libwebrtc/pc/peer_connection_proxy.h b/third_party/libwebrtc/pc/peer_connection_proxy.h
index 6db27f2dd5..aaccfe45d0 100644
--- a/third_party/libwebrtc/pc/peer_connection_proxy.h
+++ b/third_party/libwebrtc/pc/peer_connection_proxy.h
@@ -16,6 +16,7 @@
#include <vector>
#include "api/peer_connection_interface.h"
+#include "api/transport/bandwidth_estimation_settings.h"
#include "pc/proxy.h"
namespace webrtc {
@@ -137,6 +138,9 @@ PROXY_METHOD2(void,
std::function<void(RTCError)>)
PROXY_METHOD1(bool, RemoveIceCandidates, const std::vector<cricket::Candidate>&)
PROXY_METHOD1(RTCError, SetBitrate, const BitrateSettings&)
+PROXY_METHOD1(void,
+ ReconfigureBandwidthEstimation,
+ const BandwidthEstimationSettings&)
PROXY_METHOD1(void, SetAudioPlayout, bool)
PROXY_METHOD1(void, SetAudioRecording, bool)
// This method will be invoked on the network thread. See
diff --git a/third_party/libwebrtc/pc/rtc_stats_collector.cc b/third_party/libwebrtc/pc/rtc_stats_collector.cc
index a5a3067fa1..a49e8ef0b2 100644
--- a/third_party/libwebrtc/pc/rtc_stats_collector.cc
+++ b/third_party/libwebrtc/pc/rtc_stats_collector.cc
@@ -72,7 +72,7 @@ namespace {
const char kDirectionInbound = 'I';
const char kDirectionOutbound = 'O';
-const char* kAudioPlayoutSingletonId = "AP";
+static constexpr char kAudioPlayoutSingletonId[] = "AP";
// TODO(https://crbug.com/webrtc/10656): Consider making IDs less predictable.
std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) {
@@ -164,19 +164,6 @@ std::string RTCMediaSourceStatsIDFromKindAndAttachment(
return sb.str();
}
-const char* CandidateTypeToRTCIceCandidateType(const cricket::Candidate& c) {
- if (c.is_local())
- return "host";
- if (c.is_stun())
- return "srflx";
- if (c.is_prflx())
- return "prflx";
- if (c.is_relay())
- return "relay";
- RTC_DCHECK_NOTREACHED();
- return nullptr;
-}
-
const char* DataStateToRTCDataChannelState(
DataChannelInterface::DataState state) {
switch (state) {
@@ -961,12 +948,10 @@ const std::string& ProduceIceCandidateStats(Timestamp timestamp,
if (is_local) {
candidate_stats->network_type =
NetworkTypeToStatsType(candidate.network_type());
- const std::string& candidate_type = candidate.type();
const std::string& relay_protocol = candidate.relay_protocol();
const std::string& url = candidate.url();
- if (candidate_type == cricket::RELAY_PORT_TYPE ||
- (candidate_type == cricket::PRFLX_PORT_TYPE &&
- !relay_protocol.empty())) {
+ if (candidate.is_relay() ||
+ (candidate.is_prflx() && !relay_protocol.empty())) {
RTC_DCHECK(relay_protocol.compare("udp") == 0 ||
relay_protocol.compare("tcp") == 0 ||
relay_protocol.compare("tls") == 0);
@@ -974,7 +959,7 @@ const std::string& ProduceIceCandidateStats(Timestamp timestamp,
if (!url.empty()) {
candidate_stats->url = url;
}
- } else if (candidate_type == cricket::STUN_PORT_TYPE) {
+ } else if (candidate.is_stun()) {
if (!url.empty()) {
candidate_stats->url = url;
}
@@ -1000,8 +985,7 @@ const std::string& ProduceIceCandidateStats(Timestamp timestamp,
candidate_stats->address = candidate.address().ipaddr().ToString();
candidate_stats->port = static_cast<int32_t>(candidate.address().port());
candidate_stats->protocol = candidate.protocol();
- candidate_stats->candidate_type =
- CandidateTypeToRTCIceCandidateType(candidate);
+ candidate_stats->candidate_type = candidate.type_name();
candidate_stats->priority = static_cast<int32_t>(candidate.priority());
candidate_stats->foundation = candidate.foundation();
auto related_address = candidate.related_address();
diff --git a/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc b/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc
index 61b3bca1db..98cbd2d7e3 100644
--- a/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc
+++ b/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc
@@ -23,6 +23,7 @@
#include <vector>
#include "absl/strings/str_replace.h"
+#include "absl/types/optional.h"
#include "api/candidate.h"
#include "api/dtls_transport_interface.h"
#include "api/media_stream_interface.h"
@@ -211,7 +212,7 @@ std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
int port,
const std::string& protocol,
const rtc::AdapterType adapter_type,
- const std::string& candidate_type,
+ const absl::string_view candidate_type,
uint32_t priority,
const rtc::AdapterType underlying_type_for_vpn =
rtc::ADAPTER_TYPE_UNKNOWN) {
@@ -3723,7 +3724,7 @@ class RTCTestStats : public RTCStats {
RTCTestStats(const std::string& id, Timestamp timestamp)
: RTCStats(id, timestamp) {}
- RTCStatsMember<int32_t> dummy_stat;
+ absl::optional<int32_t> dummy_stat;
};
WEBRTC_RTCSTATS_IMPL(RTCTestStats,
diff --git a/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc b/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc
index 002f9d34b5..de8e6e3f67 100644
--- a/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc
+++ b/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc
@@ -18,6 +18,7 @@
#include "absl/algorithm/container.h"
#include "absl/strings/match.h"
+#include "absl/types/optional.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/audio_options.h"
@@ -212,14 +213,14 @@ class RTCStatsVerifier {
}
template <typename T>
- void MarkAttributeTested(const RTCStatsMember<T>& field,
+ void MarkAttributeTested(const absl::optional<T>& field,
bool test_successful) {
untested_attribute_names_.erase(stats_->GetAttribute(field).name());
all_tests_successful_ &= test_successful;
}
template <typename T>
- void TestAttributeIsDefined(const RTCStatsMember<T>& field) {
+ void TestAttributeIsDefined(const absl::optional<T>& field) {
EXPECT_TRUE(field.has_value())
<< stats_->type() << "." << stats_->GetAttribute(field).name() << "["
<< stats_->id() << "] was undefined.";
@@ -227,7 +228,7 @@ class RTCStatsVerifier {
}
template <typename T>
- void TestAttributeIsUndefined(const RTCStatsMember<T>& field) {
+ void TestAttributeIsUndefined(const absl::optional<T>& field) {
Attribute attribute = stats_->GetAttribute(field);
EXPECT_FALSE(field.has_value())
<< stats_->type() << "." << attribute.name() << "[" << stats_->id()
@@ -236,7 +237,7 @@ class RTCStatsVerifier {
}
template <typename T>
- void TestAttributeIsPositive(const RTCStatsMember<T>& field) {
+ void TestAttributeIsPositive(const absl::optional<T>& field) {
Attribute attribute = stats_->GetAttribute(field);
EXPECT_TRUE(field.has_value()) << stats_->type() << "." << attribute.name()
<< "[" << stats_->id() << "] was undefined.";
@@ -252,7 +253,7 @@ class RTCStatsVerifier {
}
template <typename T>
- void TestAttributeIsNonNegative(const RTCStatsMember<T>& field) {
+ void TestAttributeIsNonNegative(const absl::optional<T>& field) {
Attribute attribute = stats_->GetAttribute(field);
EXPECT_TRUE(field.has_value()) << stats_->type() << "." << attribute.name()
<< "[" << stats_->id() << "] was undefined.";
@@ -268,13 +269,13 @@ class RTCStatsVerifier {
}
template <typename T>
- void TestAttributeIsIDReference(const RTCStatsMember<T>& field,
+ void TestAttributeIsIDReference(const absl::optional<T>& field,
const char* expected_type) {
TestAttributeIsIDReference(field, expected_type, false);
}
template <typename T>
- void TestAttributeIsOptionalIDReference(const RTCStatsMember<T>& field,
+ void TestAttributeIsOptionalIDReference(const absl::optional<T>& field,
const char* expected_type) {
TestAttributeIsIDReference(field, expected_type, true);
}
@@ -291,7 +292,7 @@ class RTCStatsVerifier {
private:
template <typename T>
- void TestAttributeIsIDReference(const RTCStatsMember<T>& field,
+ void TestAttributeIsIDReference(const absl::optional<T>& field,
const char* expected_type,
bool optional) {
if (optional && !field.has_value()) {
diff --git a/third_party/libwebrtc/pc/rtc_stats_traversal.cc b/third_party/libwebrtc/pc/rtc_stats_traversal.cc
index dfd0570b8f..e9d11b5ae5 100644
--- a/third_party/libwebrtc/pc/rtc_stats_traversal.cc
+++ b/third_party/libwebrtc/pc/rtc_stats_traversal.cc
@@ -15,6 +15,7 @@
#include <utility>
#include <vector>
+#include "absl/types/optional.h"
#include "api/stats/rtcstats_objects.h"
#include "rtc_base/checks.h"
@@ -42,7 +43,7 @@ void TraverseAndTakeVisitedStats(RTCStatsReport* report,
}
}
-void AddIdIfDefined(const RTCStatsMember<std::string>& id,
+void AddIdIfDefined(const absl::optional<std::string>& id,
std::vector<const std::string*>* neighbor_ids) {
if (id.has_value())
neighbor_ids->push_back(&(*id));
diff --git a/third_party/libwebrtc/pc/rtp_receiver.cc b/third_party/libwebrtc/pc/rtp_receiver.cc
index a2b3353c0e..9431aab10a 100644
--- a/third_party/libwebrtc/pc/rtp_receiver.cc
+++ b/third_party/libwebrtc/pc/rtp_receiver.cc
@@ -12,6 +12,7 @@
#include <stddef.h>
+#include <atomic>
#include <utility>
#include <vector>
@@ -22,8 +23,10 @@
namespace webrtc {
// This function is only expected to be called on the signalling thread.
+// On the other hand, some test or even production setups may use
+// several signaling threads.
int RtpReceiverInternal::GenerateUniqueId() {
- static int g_unique_id = 0;
+ static std::atomic<int> g_unique_id{0};
return ++g_unique_id;
}
diff --git a/third_party/libwebrtc/pc/rtp_transceiver.cc b/third_party/libwebrtc/pc/rtp_transceiver.cc
index 34d744a3bb..de31b2e36a 100644
--- a/third_party/libwebrtc/pc/rtp_transceiver.cc
+++ b/third_party/libwebrtc/pc/rtp_transceiver.cc
@@ -171,6 +171,35 @@ RtpTransceiver::RtpTransceiver(
: media_engine()->voice().send_codecs());
senders_.push_back(sender);
receivers_.push_back(receiver);
+
+ // Set default header extensions depending on whether simulcast/SVC is used.
+ RtpParameters parameters = sender->internal()->GetParametersInternal();
+ bool uses_simulcast = parameters.encodings.size() > 1;
+ bool uses_svc = !parameters.encodings.empty() &&
+ parameters.encodings[0].scalability_mode.has_value() &&
+ parameters.encodings[0].scalability_mode !=
+ ScalabilityModeToString(ScalabilityMode::kL1T1);
+ if (uses_simulcast || uses_svc) {
+ // Enable DD and VLA extensions, can be deactivated by the API.
+ // Skip this if the GFD extension was enabled via field trial
+ // for backward compability reasons.
+ bool uses_gfd =
+ absl::c_find_if(
+ header_extensions_to_negotiate_,
+ [](const RtpHeaderExtensionCapability& ext) {
+ return ext.uri == RtpExtension::kGenericFrameDescriptorUri00 &&
+ ext.direction != webrtc::RtpTransceiverDirection::kStopped;
+ }) != header_extensions_to_negotiate_.end();
+ if (!uses_gfd) {
+ for (RtpHeaderExtensionCapability& ext :
+ header_extensions_to_negotiate_) {
+ if (ext.uri == RtpExtension::kVideoLayersAllocationUri ||
+ ext.uri == RtpExtension::kDependencyDescriptorUri) {
+ ext.direction = RtpTransceiverDirection::kSendRecv;
+ }
+ }
+ }
+ }
}
RtpTransceiver::~RtpTransceiver() {
diff --git a/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc b/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc
index d75e964509..b6dc7b2bb9 100644
--- a/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc
+++ b/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc
@@ -481,6 +481,81 @@ TEST_F(RtpTransceiverTestForHeaderExtensions,
RtpTransceiverDirection::kStopped)));
}
+TEST_F(RtpTransceiverTestForHeaderExtensions,
+ SimulcastOrSvcEnablesExtensionsByDefault) {
+ std::vector<RtpHeaderExtensionCapability> extensions = {
+ {RtpExtension::kDependencyDescriptorUri, 1,
+ RtpTransceiverDirection::kStopped},
+ {RtpExtension::kVideoLayersAllocationUri, 2,
+ RtpTransceiverDirection::kStopped},
+ };
+
+ // Default is stopped.
+ auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+ auto transceiver = rtc::make_ref_counted<RtpTransceiver>(
+ RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+ rtc::Thread::Current(), sender),
+ RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+ rtc::Thread::Current(), rtc::Thread::Current(), receiver_),
+ context(), extensions,
+ /* on_negotiation_needed= */ [] {});
+ std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions =
+ transceiver->GetHeaderExtensionsToNegotiate();
+ ASSERT_EQ(header_extensions.size(), 2u);
+ EXPECT_EQ(header_extensions[0].uri, RtpExtension::kDependencyDescriptorUri);
+ EXPECT_EQ(header_extensions[0].direction, RtpTransceiverDirection::kStopped);
+ EXPECT_EQ(header_extensions[1].uri, RtpExtension::kVideoLayersAllocationUri);
+ EXPECT_EQ(header_extensions[1].direction, RtpTransceiverDirection::kStopped);
+
+ // Simulcast, i.e. more than one encoding.
+ RtpParameters simulcast_parameters;
+ simulcast_parameters.encodings.resize(2);
+ auto simulcast_sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+ EXPECT_CALL(*simulcast_sender, GetParametersInternal())
+ .WillRepeatedly(Return(simulcast_parameters));
+ auto simulcast_transceiver = rtc::make_ref_counted<RtpTransceiver>(
+ RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+ rtc::Thread::Current(), simulcast_sender),
+ RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+ rtc::Thread::Current(), rtc::Thread::Current(), receiver_),
+ context(), extensions,
+ /* on_negotiation_needed= */ [] {});
+ auto simulcast_extensions =
+ simulcast_transceiver->GetHeaderExtensionsToNegotiate();
+ ASSERT_EQ(simulcast_extensions.size(), 2u);
+ EXPECT_EQ(simulcast_extensions[0].uri,
+ RtpExtension::kDependencyDescriptorUri);
+ EXPECT_EQ(simulcast_extensions[0].direction,
+ RtpTransceiverDirection::kSendRecv);
+ EXPECT_EQ(simulcast_extensions[1].uri,
+ RtpExtension::kVideoLayersAllocationUri);
+ EXPECT_EQ(simulcast_extensions[1].direction,
+ RtpTransceiverDirection::kSendRecv);
+
+ // SVC, a single encoding with a scalabilityMode other than L1T1.
+ webrtc::RtpParameters svc_parameters;
+ svc_parameters.encodings.resize(1);
+ svc_parameters.encodings[0].scalability_mode = "L3T3";
+
+ auto svc_sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+ EXPECT_CALL(*svc_sender, GetParametersInternal())
+ .WillRepeatedly(Return(svc_parameters));
+ auto svc_transceiver = rtc::make_ref_counted<RtpTransceiver>(
+ RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+ rtc::Thread::Current(), svc_sender),
+ RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+ rtc::Thread::Current(), rtc::Thread::Current(), receiver_),
+ context(), extensions,
+ /* on_negotiation_needed= */ [] {});
+ std::vector<webrtc::RtpHeaderExtensionCapability> svc_extensions =
+ svc_transceiver->GetHeaderExtensionsToNegotiate();
+ ASSERT_EQ(svc_extensions.size(), 2u);
+ EXPECT_EQ(svc_extensions[0].uri, RtpExtension::kDependencyDescriptorUri);
+ EXPECT_EQ(svc_extensions[0].direction, RtpTransceiverDirection::kSendRecv);
+ EXPECT_EQ(svc_extensions[1].uri, RtpExtension::kVideoLayersAllocationUri);
+ EXPECT_EQ(svc_extensions[1].direction, RtpTransceiverDirection::kSendRecv);
+}
+
} // namespace
} // namespace webrtc
diff --git a/third_party/libwebrtc/pc/sdp_offer_answer.cc b/third_party/libwebrtc/pc/sdp_offer_answer.cc
index 67c8d10241..95d54978c7 100644
--- a/third_party/libwebrtc/pc/sdp_offer_answer.cc
+++ b/third_party/libwebrtc/pc/sdp_offer_answer.cc
@@ -99,7 +99,7 @@ const char kSdpWithoutIceUfragPwd[] =
"Called with SDP without ice-ufrag and ice-pwd.";
const char kSdpWithoutDtlsFingerprint[] =
"Called with SDP without DTLS fingerprint.";
-const char kSdpWithoutSdesCrypto[] = "Called with SDP without SDES crypto.";
+const char kSdpWithoutCrypto[] = "Called with SDP without crypto setup.";
const char kSessionError[] = "Session error code: ";
const char kSessionErrorDesc[] = "Session error description: ";
@@ -271,7 +271,7 @@ bool MediaSectionsHaveSameCount(const SessionDescription& desc1,
const SessionDescription& desc2) {
return desc1.contents().size() == desc2.contents().size();
}
-// Checks that each non-rejected content has SDES crypto keys or a DTLS
+// Checks that each non-rejected content has a DTLS
// fingerprint, unless it's in a BUNDLE group, in which case only the
// BUNDLE-tag section (first media section/description in the BUNDLE group)
// needs a ufrag and pwd. Mismatches, such as replying with a DTLS fingerprint
@@ -285,9 +285,6 @@ RTCError VerifyCrypto(const SessionDescription* desc,
if (content_info.rejected) {
continue;
}
-#if !defined(WEBRTC_FUCHSIA)
- RTC_CHECK(dtls_enabled) << "SDES protocol is only allowed in Fuchsia";
-#endif
const std::string& mid = content_info.name;
auto it = bundle_groups_by_mid.find(mid);
const cricket::ContentGroup* bundle =
@@ -313,10 +310,7 @@ RTCError VerifyCrypto(const SessionDescription* desc,
kSdpWithoutDtlsFingerprint);
}
} else {
- if (media->cryptos().empty()) {
- LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
- kSdpWithoutSdesCrypto);
- }
+ LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, kSdpWithoutCrypto);
}
}
return RTCError::OK();
@@ -1396,7 +1390,9 @@ void SdpOfferAnswerHandler::Initialize(
pc_->trials());
if (pc_->options()->disable_encryption) {
- webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED);
+ RTC_LOG(LS_INFO)
+ << "Disabling encryption. This should only be done in tests.";
+ webrtc_session_desc_factory_->SetInsecureForTesting();
}
webrtc_session_desc_factory_->set_enable_encrypted_rtp_header_extensions(
@@ -3554,8 +3550,7 @@ RTCError SdpOfferAnswerHandler::ValidateSessionDescription(
// Verify crypto settings.
std::string crypto_error;
- if (webrtc_session_desc_factory_->SdesPolicy() == cricket::SEC_REQUIRED ||
- pc_->dtls_enabled()) {
+ if (pc_->dtls_enabled()) {
RTCError crypto_error = VerifyCrypto(
sdesc->description(), pc_->dtls_enabled(), bundle_groups_by_mid);
if (!crypto_error.ok()) {
@@ -4302,11 +4297,13 @@ void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanOffer(
GetMediaDescriptionOptionsForRejectedData(mid));
} else {
const auto data_mid = pc_->sctp_mid();
- RTC_CHECK(data_mid);
- if (mid == data_mid.value()) {
+ if (data_mid.has_value() && mid == data_mid.value()) {
session_options->media_description_options.push_back(
GetMediaDescriptionOptionsForActiveData(mid));
} else {
+ if (!data_mid.has_value()) {
+ RTC_LOG(LS_ERROR) << "Datachannel transport not available: " << mid;
+ }
session_options->media_description_options.push_back(
GetMediaDescriptionOptionsForRejectedData(mid));
}
diff --git a/third_party/libwebrtc/pc/session_description.h b/third_party/libwebrtc/pc/session_description.h
index 6ef9c316e1..fe037a5786 100644
--- a/third_party/libwebrtc/pc/session_description.h
+++ b/third_party/libwebrtc/pc/session_description.h
@@ -23,7 +23,6 @@
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
-#include "api/crypto_params.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
#include "api/rtp_transceiver_direction.h"
@@ -43,7 +42,6 @@
namespace cricket {
-using CryptoParamsVec = std::vector<CryptoParams>;
using RtpHeaderExtensions = std::vector<webrtc::RtpExtension>;
// Options to control how session descriptions are generated.
@@ -123,12 +121,6 @@ class MediaContentDescription {
bandwidth_type_ = bandwidth_type;
}
- const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
- void AddCrypto(const CryptoParams& params) { cryptos_.push_back(params); }
- void set_cryptos(const std::vector<CryptoParams>& cryptos) {
- cryptos_ = cryptos;
- }
-
// List of RTP header extensions. URIs are **NOT** guaranteed to be unique
// as they can appear twice when both encrypted and non-encrypted extensions
// are present.
@@ -268,7 +260,6 @@ class MediaContentDescription {
int bandwidth_ = kAutoBandwidth;
std::string bandwidth_type_ = kApplicationSpecificBandwidth;
- std::vector<CryptoParams> cryptos_;
std::vector<webrtc::RtpExtension> rtp_header_extensions_;
bool rtp_header_extensions_set_ = false;
StreamParamsVec send_streams_;
diff --git a/third_party/libwebrtc/pc/srtp_filter.cc b/third_party/libwebrtc/pc/srtp_filter.cc
deleted file mode 100644
index b8be63cd22..0000000000
--- a/third_party/libwebrtc/pc/srtp_filter.cc
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright 2009 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "pc/srtp_filter.h"
-
-#include <string.h>
-
-#include <string>
-
-#include "absl/strings/match.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/ssl_stream_adapter.h"
-#include "rtc_base/third_party/base64/base64.h"
-#include "rtc_base/zero_memory.h"
-
-namespace cricket {
-
-SrtpFilter::SrtpFilter() {}
-
-SrtpFilter::~SrtpFilter() {}
-
-bool SrtpFilter::IsActive() const {
- return state_ >= ST_ACTIVE;
-}
-
-bool SrtpFilter::Process(const std::vector<CryptoParams>& cryptos,
- webrtc::SdpType type,
- ContentSource source) {
- bool ret = false;
- switch (type) {
- case webrtc::SdpType::kOffer:
- ret = SetOffer(cryptos, source);
- break;
- case webrtc::SdpType::kPrAnswer:
- ret = SetProvisionalAnswer(cryptos, source);
- break;
- case webrtc::SdpType::kAnswer:
- ret = SetAnswer(cryptos, source);
- break;
- default:
- break;
- }
-
- if (!ret) {
- return false;
- }
-
- return true;
-}
-
-bool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
- ContentSource source) {
- if (!ExpectOffer(source)) {
- RTC_LOG(LS_ERROR) << "Wrong state to update SRTP offer";
- return false;
- }
- return StoreParams(offer_params, source);
-}
-
-bool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
- ContentSource source) {
- return DoSetAnswer(answer_params, source, true);
-}
-
-bool SrtpFilter::SetProvisionalAnswer(
- const std::vector<CryptoParams>& answer_params,
- ContentSource source) {
- return DoSetAnswer(answer_params, source, false);
-}
-
-bool SrtpFilter::ExpectOffer(ContentSource source) {
- return ((state_ == ST_INIT) || (state_ == ST_ACTIVE) ||
- (state_ == ST_SENTOFFER && source == CS_LOCAL) ||
- (state_ == ST_SENTUPDATEDOFFER && source == CS_LOCAL) ||
- (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) ||
- (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE));
-}
-
-bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
- ContentSource source) {
- offer_params_ = params;
- if (state_ == ST_INIT) {
- state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
- } else if (state_ == ST_ACTIVE) {
- state_ =
- (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER;
- }
- return true;
-}
-
-bool SrtpFilter::ExpectAnswer(ContentSource source) {
- return ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
- (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) ||
- (state_ == ST_SENTUPDATEDOFFER && source == CS_REMOTE) ||
- (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_LOCAL) ||
- (state_ == ST_SENTPRANSWER_NO_CRYPTO && source == CS_LOCAL) ||
- (state_ == ST_SENTPRANSWER && source == CS_LOCAL) ||
- (state_ == ST_RECEIVEDPRANSWER_NO_CRYPTO && source == CS_REMOTE) ||
- (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE));
-}
-
-bool SrtpFilter::DoSetAnswer(const std::vector<CryptoParams>& answer_params,
- ContentSource source,
- bool final) {
- if (!ExpectAnswer(source)) {
- RTC_LOG(LS_ERROR) << "Invalid state for SRTP answer";
- return false;
- }
-
- // If the answer doesn't requests crypto complete the negotiation of an
- // unencrypted session.
- // Otherwise, finalize the parameters and apply them.
- if (answer_params.empty()) {
- if (final) {
- return ResetParams();
- } else {
- // Need to wait for the final answer to decide if
- // we should go to Active state.
- state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO
- : ST_RECEIVEDPRANSWER_NO_CRYPTO;
- return true;
- }
- }
- CryptoParams selected_params;
- if (!NegotiateParams(answer_params, &selected_params))
- return false;
-
- const CryptoParams& new_send_params =
- (source == CS_REMOTE) ? selected_params : answer_params[0];
- const CryptoParams& new_recv_params =
- (source == CS_REMOTE) ? answer_params[0] : selected_params;
- if (!ApplySendParams(new_send_params) || !ApplyRecvParams(new_recv_params)) {
- return false;
- }
- applied_send_params_ = new_send_params;
- applied_recv_params_ = new_recv_params;
-
- if (final) {
- offer_params_.clear();
- state_ = ST_ACTIVE;
- } else {
- state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER;
- }
- return true;
-}
-
-bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
- CryptoParams* selected_params) {
- // We're processing an accept. We should have exactly one set of params,
- // unless the offer didn't mention crypto, in which case we shouldn't be here.
- bool ret = (answer_params.size() == 1U && !offer_params_.empty());
- if (ret) {
- // We should find a match between the answer params and the offered params.
- std::vector<CryptoParams>::const_iterator it;
- for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
- if (answer_params[0].Matches(*it)) {
- break;
- }
- }
-
- if (it != offer_params_.end()) {
- *selected_params = *it;
- } else {
- ret = false;
- }
- }
-
- if (!ret) {
- RTC_LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
- }
- return ret;
-}
-
-bool SrtpFilter::ResetParams() {
- offer_params_.clear();
- applied_send_params_ = CryptoParams();
- applied_recv_params_ = CryptoParams();
- send_crypto_suite_ = absl::nullopt;
- recv_crypto_suite_ = absl::nullopt;
- send_key_.Clear();
- recv_key_.Clear();
- state_ = ST_INIT;
- return true;
-}
-
-bool SrtpFilter::ApplySendParams(const CryptoParams& send_params) {
- if (applied_send_params_.crypto_suite == send_params.crypto_suite &&
- applied_send_params_.key_params == send_params.key_params) {
- RTC_LOG(LS_INFO) << "Applying the same SRTP send parameters again. No-op.";
-
- // We do not want to reset the ROC if the keys are the same. So just return.
- return true;
- }
-
- send_crypto_suite_ = rtc::SrtpCryptoSuiteFromName(send_params.crypto_suite);
- if (send_crypto_suite_ == rtc::kSrtpInvalidCryptoSuite) {
- RTC_LOG(LS_WARNING) << "Unknown crypto suite(s) received:"
- " send crypto_suite "
- << send_params.crypto_suite;
- return false;
- }
-
- int send_key_len, send_salt_len;
- if (!rtc::GetSrtpKeyAndSaltLengths(*send_crypto_suite_, &send_key_len,
- &send_salt_len)) {
- RTC_LOG(LS_ERROR) << "Could not get lengths for crypto suite(s):"
- " send crypto_suite "
- << send_params.crypto_suite;
- return false;
- }
-
- send_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(send_key_len + send_salt_len);
- return ParseKeyParams(send_params.key_params, send_key_.data(),
- send_key_.size());
-}
-
-bool SrtpFilter::ApplyRecvParams(const CryptoParams& recv_params) {
- if (applied_recv_params_.crypto_suite == recv_params.crypto_suite &&
- applied_recv_params_.key_params == recv_params.key_params) {
- RTC_LOG(LS_INFO) << "Applying the same SRTP recv parameters again. No-op.";
-
- // We do not want to reset the ROC if the keys are the same. So just return.
- return true;
- }
-
- recv_crypto_suite_ = rtc::SrtpCryptoSuiteFromName(recv_params.crypto_suite);
- if (recv_crypto_suite_ == rtc::kSrtpInvalidCryptoSuite) {
- RTC_LOG(LS_WARNING) << "Unknown crypto suite(s) received:"
- " recv crypto_suite "
- << recv_params.crypto_suite;
- return false;
- }
-
- int recv_key_len, recv_salt_len;
- if (!rtc::GetSrtpKeyAndSaltLengths(*recv_crypto_suite_, &recv_key_len,
- &recv_salt_len)) {
- RTC_LOG(LS_ERROR) << "Could not get lengths for crypto suite(s):"
- " recv crypto_suite "
- << recv_params.crypto_suite;
- return false;
- }
-
- recv_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(recv_key_len + recv_salt_len);
- return ParseKeyParams(recv_params.key_params, recv_key_.data(),
- recv_key_.size());
-}
-
-bool SrtpFilter::ParseKeyParams(const std::string& key_params,
- uint8_t* key,
- size_t len) {
- // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
-
- // Fail if key-method is wrong.
- if (!absl::StartsWith(key_params, "inline:")) {
- return false;
- }
-
- // Fail if base64 decode fails, or the key is the wrong size.
- std::string key_b64(key_params.substr(7)), key_str;
- if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str,
- nullptr) ||
- key_str.size() != len) {
- return false;
- }
-
- memcpy(key, key_str.c_str(), len);
- // TODO(bugs.webrtc.org/8905): Switch to ZeroOnFreeBuffer for storing
- // sensitive data.
- rtc::ExplicitZeroMemory(&key_str[0], key_str.size());
- return true;
-}
-
-} // namespace cricket
diff --git a/third_party/libwebrtc/pc/srtp_filter.h b/third_party/libwebrtc/pc/srtp_filter.h
deleted file mode 100644
index 59c43f624b..0000000000
--- a/third_party/libwebrtc/pc/srtp_filter.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2009 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef PC_SRTP_FILTER_H_
-#define PC_SRTP_FILTER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <list>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "absl/types/optional.h"
-#include "api/array_view.h"
-#include "api/crypto_params.h"
-#include "api/jsep.h"
-#include "api/sequence_checker.h"
-#include "pc/session_description.h"
-#include "rtc_base/buffer.h"
-#include "rtc_base/ssl_stream_adapter.h"
-
-// Forward declaration to avoid pulling in libsrtp headers here
-struct srtp_event_data_t;
-struct srtp_ctx_t_;
-
-namespace cricket {
-
-// A helper class used to negotiate SDES crypto params.
-// TODO(zhihuang): Find a better name for this class, like "SdesNegotiator".
-class SrtpFilter {
- public:
- enum Mode { PROTECT, UNPROTECT };
- enum Error {
- ERROR_NONE,
- ERROR_FAIL,
- ERROR_AUTH,
- ERROR_REPLAY,
- };
-
- SrtpFilter();
- ~SrtpFilter();
-
- // Whether the filter is active (i.e. crypto has been properly negotiated).
- bool IsActive() const;
-
- // Handle the offer/answer negotiation of the crypto parameters internally.
- // TODO(zhihuang): Make SetOffer/ProvisionalAnswer/Answer private as helper
- // methods once start using Process.
- bool Process(const std::vector<CryptoParams>& cryptos,
- webrtc::SdpType type,
- ContentSource source);
-
- // Indicates which crypto algorithms and keys were contained in the offer.
- // offer_params should contain a list of available parameters to use, or none,
- // if crypto is not desired. This must be called before SetAnswer.
- bool SetOffer(const std::vector<CryptoParams>& offer_params,
- ContentSource source);
- // Same as SetAnwer. But multiple calls are allowed to SetProvisionalAnswer
- // after a call to SetOffer.
- bool SetProvisionalAnswer(const std::vector<CryptoParams>& answer_params,
- ContentSource source);
- // Indicates which crypto algorithms and keys were contained in the answer.
- // answer_params should contain the negotiated parameters, which may be none,
- // if crypto was not desired or could not be negotiated (and not required).
- // This must be called after SetOffer. If crypto negotiation completes
- // successfully, this will advance the filter to the active state.
- bool SetAnswer(const std::vector<CryptoParams>& answer_params,
- ContentSource source);
-
- bool ResetParams();
-
- static bool ParseKeyParams(const std::string& params,
- uint8_t* key,
- size_t len);
-
- absl::optional<int> send_crypto_suite() { return send_crypto_suite_; }
- absl::optional<int> recv_crypto_suite() { return recv_crypto_suite_; }
-
- rtc::ArrayView<const uint8_t> send_key() { return send_key_; }
- rtc::ArrayView<const uint8_t> recv_key() { return recv_key_; }
-
- protected:
- bool ExpectOffer(ContentSource source);
-
- bool StoreParams(const std::vector<CryptoParams>& params,
- ContentSource source);
-
- bool ExpectAnswer(ContentSource source);
-
- bool DoSetAnswer(const std::vector<CryptoParams>& answer_params,
- ContentSource source,
- bool final);
-
- bool NegotiateParams(const std::vector<CryptoParams>& answer_params,
- CryptoParams* selected_params);
-
- private:
- bool ApplySendParams(const CryptoParams& send_params);
-
- bool ApplyRecvParams(const CryptoParams& recv_params);
-
- enum State {
- ST_INIT, // SRTP filter unused.
- ST_SENTOFFER, // Offer with SRTP parameters sent.
- ST_RECEIVEDOFFER, // Offer with SRTP parameters received.
- ST_SENTPRANSWER_NO_CRYPTO, // Sent provisional answer without crypto.
- // Received provisional answer without crypto.
- ST_RECEIVEDPRANSWER_NO_CRYPTO,
- ST_ACTIVE, // Offer and answer set.
- // SRTP filter is active but new parameters are offered.
- // When the answer is set, the state transitions to ST_ACTIVE or ST_INIT.
- ST_SENTUPDATEDOFFER,
- // SRTP filter is active but new parameters are received.
- // When the answer is set, the state transitions back to ST_ACTIVE.
- ST_RECEIVEDUPDATEDOFFER,
- // SRTP filter is active but the sent answer is only provisional.
- // When the final answer is set, the state transitions to ST_ACTIVE or
- // ST_INIT.
- ST_SENTPRANSWER,
- // SRTP filter is active but the received answer is only provisional.
- // When the final answer is set, the state transitions to ST_ACTIVE or
- // ST_INIT.
- ST_RECEIVEDPRANSWER
- };
- State state_ = ST_INIT;
- std::vector<CryptoParams> offer_params_;
- CryptoParams applied_send_params_;
- CryptoParams applied_recv_params_;
- absl::optional<int> send_crypto_suite_;
- absl::optional<int> recv_crypto_suite_;
- rtc::ZeroOnFreeBuffer<uint8_t> send_key_;
- rtc::ZeroOnFreeBuffer<uint8_t> recv_key_;
-};
-
-} // namespace cricket
-
-#endif // PC_SRTP_FILTER_H_
diff --git a/third_party/libwebrtc/pc/srtp_filter_unittest.cc b/third_party/libwebrtc/pc/srtp_filter_unittest.cc
deleted file mode 100644
index fed023199f..0000000000
--- a/third_party/libwebrtc/pc/srtp_filter_unittest.cc
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright 2004 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "pc/srtp_filter.h"
-
-#include <string.h>
-
-#include "api/crypto_params.h"
-#include "rtc_base/ssl_stream_adapter.h"
-#include "test/gtest.h"
-
-using cricket::CryptoParams;
-using cricket::CS_LOCAL;
-using cricket::CS_REMOTE;
-
-namespace rtc {
-
-static const char kTestKeyParams1[] =
- "inline:WVNfX19zZW1jdGwgKCkgewkyMjA7fQp9CnVubGVz";
-static const char kTestKeyParams2[] =
- "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
-static const char kTestKeyParams3[] =
- "inline:1234X19zZW1jdGwgKCkgewkyMjA7fQp9CnVubGVz";
-static const char kTestKeyParams4[] =
- "inline:4567QCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
-static const char kTestKeyParamsGcm1[] =
- "inline:e166KFlKzJsGW0d5apX+rrI05vxbrvMJEzFI14aTDCa63IRTlLK4iH66uOI=";
-static const char kTestKeyParamsGcm2[] =
- "inline:6X0oCd55zfz4VgtOwsuqcFq61275PDYN5uwuu3p7ZUHbfUY2FMpdP4m2PEo=";
-static const char kTestKeyParamsGcm3[] =
- "inline:YKlABGZWMgX32xuMotrG0v0T7G83veegaVzubQ==";
-static const char kTestKeyParamsGcm4[] =
- "inline:gJ6tWoUym2v+/F6xjr7xaxiS3QbJJozl3ZD/0A==";
-static const cricket::CryptoParams kTestCryptoParams1(1,
- "AES_CM_128_HMAC_SHA1_80",
- kTestKeyParams1,
- "");
-static const cricket::CryptoParams kTestCryptoParams2(1,
- "AES_CM_128_HMAC_SHA1_80",
- kTestKeyParams2,
- "");
-static const cricket::CryptoParams kTestCryptoParamsGcm1(1,
- "AEAD_AES_256_GCM",
- kTestKeyParamsGcm1,
- "");
-static const cricket::CryptoParams kTestCryptoParamsGcm2(1,
- "AEAD_AES_256_GCM",
- kTestKeyParamsGcm2,
- "");
-static const cricket::CryptoParams kTestCryptoParamsGcm3(1,
- "AEAD_AES_128_GCM",
- kTestKeyParamsGcm3,
- "");
-static const cricket::CryptoParams kTestCryptoParamsGcm4(1,
- "AEAD_AES_128_GCM",
- kTestKeyParamsGcm4,
- "");
-
-class SrtpFilterTest : public ::testing::Test {
- protected:
- SrtpFilterTest() {}
- static std::vector<CryptoParams> MakeVector(const CryptoParams& params) {
- std::vector<CryptoParams> vec;
- vec.push_back(params);
- return vec;
- }
-
- void TestSetParams(const std::vector<CryptoParams>& params1,
- const std::vector<CryptoParams>& params2) {
- EXPECT_TRUE(f1_.SetOffer(params1, CS_LOCAL));
- EXPECT_TRUE(f2_.SetOffer(params1, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_FALSE(f2_.IsActive());
- EXPECT_TRUE(f2_.SetAnswer(params2, CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(params2, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f2_.IsActive());
- }
-
- void VerifyKeysAreEqual(ArrayView<const uint8_t> key1,
- ArrayView<const uint8_t> key2) {
- EXPECT_EQ(key1.size(), key2.size());
- EXPECT_EQ(0, memcmp(key1.data(), key2.data(), key1.size()));
- }
-
- void VerifyCryptoParamsMatch(const std::string& cs1, const std::string& cs2) {
- EXPECT_EQ(rtc::SrtpCryptoSuiteFromName(cs1), f1_.send_crypto_suite());
- EXPECT_EQ(rtc::SrtpCryptoSuiteFromName(cs2), f2_.send_crypto_suite());
- VerifyKeysAreEqual(f1_.send_key(), f2_.recv_key());
- VerifyKeysAreEqual(f2_.send_key(), f1_.recv_key());
- }
-
- cricket::SrtpFilter f1_;
- cricket::SrtpFilter f2_;
-};
-
-// Test that we can set up the session and keys properly.
-TEST_F(SrtpFilterTest, TestGoodSetupOneCryptoSuite) {
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
-}
-
-TEST_F(SrtpFilterTest, TestGoodSetupOneCryptoSuiteGcm) {
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParamsGcm1), CS_LOCAL));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParamsGcm2), CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
-}
-
-// Test that we can set up things with multiple params.
-TEST_F(SrtpFilterTest, TestGoodSetupMultipleCryptoSuites) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- offer.push_back(kTestCryptoParams1);
- offer[1].tag = 2;
- offer[1].crypto_suite = kCsAesCm128HmacSha1_32;
- answer[0].tag = 2;
- answer[0].crypto_suite = kCsAesCm128HmacSha1_32;
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
-}
-
-TEST_F(SrtpFilterTest, TestGoodSetupMultipleCryptoSuitesGcm) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParamsGcm1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParamsGcm3));
- offer.push_back(kTestCryptoParamsGcm4);
- offer[1].tag = 2;
- answer[0].tag = 2;
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
-}
-
-// Test that we handle the cases where crypto is not desired.
-TEST_F(SrtpFilterTest, TestGoodSetupNoCryptoSuites) {
- std::vector<CryptoParams> offer, answer;
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we handle the cases where crypto is not desired by the remote side.
-TEST_F(SrtpFilterTest, TestGoodSetupNoAnswerCryptoSuites) {
- std::vector<CryptoParams> answer;
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail if we call the functions the wrong way.
-TEST_F(SrtpFilterTest, TestBadSetup) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_LOCAL));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we can set offer multiple times from the same source.
-TEST_F(SrtpFilterTest, TestGoodSetupMultipleOffers) {
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
-
- EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
- EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_FALSE(f2_.IsActive());
- EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
- EXPECT_TRUE(f2_.IsActive());
- EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
- EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
-}
-// Test that we can't set offer multiple times from different sources.
-TEST_F(SrtpFilterTest, TestBadSetupMultipleOffers) {
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_FALSE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams1), CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
- EXPECT_FALSE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
- EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
-
- EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_FALSE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_FALSE(f2_.IsActive());
- EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
- EXPECT_TRUE(f2_.IsActive());
- EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_FALSE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
-}
-
-// Test that we fail if we have params in the answer when none were offered.
-TEST_F(SrtpFilterTest, TestNoAnswerCryptoSuites) {
- std::vector<CryptoParams> offer;
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail if we have too many params in our answer.
-TEST_F(SrtpFilterTest, TestMultipleAnswerCryptoSuites) {
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer.push_back(kTestCryptoParams2);
- answer[1].tag = 2;
- answer[1].crypto_suite = kCsAesCm128HmacSha1_32;
- EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail if we don't support the crypto suite.
-TEST_F(SrtpFilterTest, TestInvalidCryptoSuite) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- offer[0].crypto_suite = answer[0].crypto_suite = "FOO";
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail if we can't agree on a tag.
-TEST_F(SrtpFilterTest, TestNoMatchingTag) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer[0].tag = 99;
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail if we can't agree on a crypto suite.
-TEST_F(SrtpFilterTest, TestNoMatchingCryptoSuite) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer[0].tag = 2;
- answer[0].crypto_suite = "FOO";
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail keys with bad base64 content.
-TEST_F(SrtpFilterTest, TestInvalidKeyData) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer[0].key_params = "inline:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail keys with the wrong key-method.
-TEST_F(SrtpFilterTest, TestWrongKeyMethod) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer[0].key_params = "outline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail keys of the wrong length.
-TEST_F(SrtpFilterTest, TestKeyTooShort) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer[0].key_params = "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtx";
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail keys of the wrong length.
-TEST_F(SrtpFilterTest, TestKeyTooLong) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer[0].key_params = "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBRABCD";
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we fail keys with lifetime or MKI set (since we don't support)
-TEST_F(SrtpFilterTest, TestUnsupportedOptions) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- answer[0].key_params =
- "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:4";
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
-}
-
-// Test that we can encrypt/decrypt after negotiating AES_CM_128_HMAC_SHA1_80.
-TEST_F(SrtpFilterTest, TestProtect_AES_CM_128_HMAC_SHA1_80) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- offer.push_back(kTestCryptoParams1);
- offer[1].tag = 2;
- offer[1].crypto_suite = kCsAesCm128HmacSha1_32;
- TestSetParams(offer, answer);
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-}
-
-// Test that we can encrypt/decrypt after negotiating AES_CM_128_HMAC_SHA1_32.
-TEST_F(SrtpFilterTest, TestProtect_AES_CM_128_HMAC_SHA1_32) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
- offer.push_back(kTestCryptoParams1);
- offer[1].tag = 2;
- offer[1].crypto_suite = kCsAesCm128HmacSha1_32;
- answer[0].tag = 2;
- answer[0].crypto_suite = kCsAesCm128HmacSha1_32;
- TestSetParams(offer, answer);
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_32, kCsAesCm128HmacSha1_32);
-}
-
-// Test that we can change encryption parameters.
-TEST_F(SrtpFilterTest, TestChangeParameters) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
-
- TestSetParams(offer, answer);
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-
- // Change the key parameters and crypto_suite.
- offer[0].key_params = kTestKeyParams3;
- offer[0].crypto_suite = kCsAesCm128HmacSha1_32;
- answer[0].key_params = kTestKeyParams4;
- answer[0].crypto_suite = kCsAesCm128HmacSha1_32;
-
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f1_.IsActive());
-
- // Test that the old keys are valid until the negotiation is complete.
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-
- // Complete the negotiation and test that we can still understand each other.
- EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
-
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_32, kCsAesCm128HmacSha1_32);
-}
-
-// Test that we can send and receive provisional answers with crypto enabled.
-// Also test that we can change the crypto.
-TEST_F(SrtpFilterTest, TestProvisionalAnswer) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- offer.push_back(kTestCryptoParams1);
- offer[1].tag = 2;
- offer[1].crypto_suite = kCsAesCm128HmacSha1_32;
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
-
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_FALSE(f2_.IsActive());
- EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f2_.IsActive());
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-
- answer[0].key_params = kTestKeyParams4;
- answer[0].tag = 2;
- answer[0].crypto_suite = kCsAesCm128HmacSha1_32;
- EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f2_.IsActive());
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_32, kCsAesCm128HmacSha1_32);
-}
-
-// Test that a provisional answer doesn't need to contain a crypto.
-TEST_F(SrtpFilterTest, TestProvisionalAnswerWithoutCrypto) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer;
-
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_FALSE(f2_.IsActive());
- EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_FALSE(f2_.IsActive());
-
- answer.push_back(kTestCryptoParams2);
- EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f2_.IsActive());
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-}
-
-// Test that if we get a new local offer after a provisional answer
-// with no crypto, that we are in an inactive state.
-TEST_F(SrtpFilterTest, TestLocalOfferAfterProvisionalAnswerWithoutCrypto) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer;
-
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
- EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_FALSE(f2_.IsActive());
- // The calls to set an offer after a provisional answer fail, so the
- // state doesn't change.
- EXPECT_FALSE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_FALSE(f2_.SetOffer(offer, CS_REMOTE));
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_FALSE(f2_.IsActive());
-
- answer.push_back(kTestCryptoParams2);
- EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f2_.IsActive());
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-}
-
-// Test that we can disable encryption.
-TEST_F(SrtpFilterTest, TestDisableEncryption) {
- std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
- std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
-
- TestSetParams(offer, answer);
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-
- offer.clear();
- answer.clear();
- EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
- EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
- EXPECT_TRUE(f1_.IsActive());
- EXPECT_TRUE(f2_.IsActive());
-
- // Test that the old keys are valid until the negotiation is complete.
- VerifyCryptoParamsMatch(kCsAesCm128HmacSha1_80, kCsAesCm128HmacSha1_80);
-
- // Complete the negotiation.
- EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
- EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
-
- EXPECT_FALSE(f1_.IsActive());
- EXPECT_FALSE(f2_.IsActive());
-}
-
-} // namespace rtc
diff --git a/third_party/libwebrtc/pc/srtp_transport.h b/third_party/libwebrtc/pc/srtp_transport.h
index 29721f3b68..bad4adc135 100644
--- a/third_party/libwebrtc/pc/srtp_transport.h
+++ b/third_party/libwebrtc/pc/srtp_transport.h
@@ -19,7 +19,6 @@
#include <vector>
#include "absl/types/optional.h"
-#include "api/crypto_params.h"
#include "api/field_trials_view.h"
#include "api/rtc_error.h"
#include "p2p/base/packet_transport_internal.h"
@@ -154,8 +153,6 @@ class SrtpTransport : public RtpTransport {
std::unique_ptr<cricket::SrtpSession> send_rtcp_session_;
std::unique_ptr<cricket::SrtpSession> recv_rtcp_session_;
- absl::optional<cricket::CryptoParams> send_params_;
- absl::optional<cricket::CryptoParams> recv_params_;
absl::optional<int> send_crypto_suite_;
absl::optional<int> recv_crypto_suite_;
rtc::ZeroOnFreeBuffer<uint8_t> send_key_;
diff --git a/third_party/libwebrtc/pc/test/fake_peer_connection_base.h b/third_party/libwebrtc/pc/test/fake_peer_connection_base.h
index 1615088e99..9e4ed6d175 100644
--- a/third_party/libwebrtc/pc/test/fake_peer_connection_base.h
+++ b/third_party/libwebrtc/pc/test/fake_peer_connection_base.h
@@ -197,6 +197,9 @@ class FakePeerConnectionBase : public PeerConnectionInternal {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
+ void ReconfigureBandwidthEstimation(
+ const BandwidthEstimationSettings& settings) override {}
+
void SetAudioPlayout(bool playout) override {}
void SetAudioRecording(bool recording) override {}
diff --git a/third_party/libwebrtc/pc/test/mock_peer_connection_internal.h b/third_party/libwebrtc/pc/test/mock_peer_connection_internal.h
index 5fd7a50b4f..b5f47cc46a 100644
--- a/third_party/libwebrtc/pc/test/mock_peer_connection_internal.h
+++ b/third_party/libwebrtc/pc/test/mock_peer_connection_internal.h
@@ -170,6 +170,10 @@ class MockPeerConnectionInternal : public PeerConnectionInternal {
(const std::vector<cricket::Candidate>&),
(override));
MOCK_METHOD(RTCError, SetBitrate, (const BitrateSettings&), (override));
+ MOCK_METHOD(void,
+ ReconfigureBandwidthEstimation,
+ (const BandwidthEstimationSettings&),
+ (override));
MOCK_METHOD(void, SetAudioPlayout, (bool), (override));
MOCK_METHOD(void, SetAudioRecording, (bool), (override));
MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>,
diff --git a/third_party/libwebrtc/pc/test/svc_e2e_tests.cc b/third_party/libwebrtc/pc/test/svc_e2e_tests.cc
index b2382d700f..678c36b586 100644
--- a/third_party/libwebrtc/pc/test/svc_e2e_tests.cc
+++ b/third_party/libwebrtc/pc/test/svc_e2e_tests.cc
@@ -454,6 +454,7 @@ INSTANTIATE_TEST_SUITE_P(
Values(UseDependencyDescriptor::Disabled,
UseDependencyDescriptor::Enabled)),
SvcTestNameGenerator);
+#endif
INSTANTIATE_TEST_SUITE_P(
SvcTestAV1,
@@ -503,6 +504,4 @@ INSTANTIATE_TEST_SUITE_P(
Values(UseDependencyDescriptor::Enabled)),
SvcTestNameGenerator);
-#endif
-
} // namespace webrtc
diff --git a/third_party/libwebrtc/pc/used_ids.h b/third_party/libwebrtc/pc/used_ids.h
index 6b342cbea8..42ef00a7c0 100644
--- a/third_party/libwebrtc/pc/used_ids.h
+++ b/third_party/libwebrtc/pc/used_ids.h
@@ -147,15 +147,15 @@ class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
private:
// Returns the first unused id in reverse order from the max id of one byte
- // header extensions. This hopefully reduce the risk of more collisions. We
+ // header extensions. This hopefully reduces the risk of more collisions. We
// want to change the default ids as little as possible. If no unused id is
// found and two byte header extensions are enabled (i.e.,
- // `extmap_allow_mixed_` is true), search for unused ids from 15 to 255.
+ // `extmap_allow_mixed_` is true), search for unused ids from 16 to 255.
int FindUnusedId() override {
if (next_extension_id_ <=
webrtc::RtpExtension::kOneByteHeaderExtensionMaxId) {
// First search in reverse order from the max id of one byte header
- // extensions.
+ // extensions (14).
while (IsIdUsed(next_extension_id_) &&
next_extension_id_ >= min_allowed_id_) {
--next_extension_id_;
@@ -165,9 +165,10 @@ class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
if (id_domain_ == IdDomain::kTwoByteAllowed) {
if (next_extension_id_ < min_allowed_id_) {
// We have searched among all one-byte IDs without finding an unused ID,
- // continue at the first two-byte ID.
+ // continue at the first two-byte ID (16; avoid 15 since it is somewhat
+ // special per https://www.rfc-editor.org/rfc/rfc8285#section-4.2
next_extension_id_ =
- webrtc::RtpExtension::kOneByteHeaderExtensionMaxId + 1;
+ webrtc::RtpExtension::kOneByteHeaderExtensionMaxId + 2;
}
if (next_extension_id_ >
diff --git a/third_party/libwebrtc/pc/used_ids_unittest.cc b/third_party/libwebrtc/pc/used_ids_unittest.cc
index 6362f2773a..df3790b52c 100644
--- a/third_party/libwebrtc/pc/used_ids_unittest.cc
+++ b/third_party/libwebrtc/pc/used_ids_unittest.cc
@@ -119,7 +119,8 @@ TEST_F(UsedRtpHeaderExtensionIdsTest, TwoByteIdsAllowed) {
UsedRtpHeaderExtensionIds::IdDomain::kTwoByteAllowed);
// Fill all one byte IDs.
- for (int i = 1; i < 15; ++i) {
+ for (int i = 1; i <= webrtc::RtpExtension::kOneByteHeaderExtensionMaxId;
+ ++i) {
webrtc::RtpExtension id("", i);
used_ids.FindAndSetIdUsed(&id);
}
@@ -131,11 +132,11 @@ TEST_F(UsedRtpHeaderExtensionIdsTest, TwoByteIdsAllowed) {
// Expect to reassign to two-byte header extension IDs.
used_ids.FindAndSetIdUsed(&id1_collision);
- EXPECT_EQ(id1_collision.id, 15);
+ EXPECT_EQ(id1_collision.id, 16);
used_ids.FindAndSetIdUsed(&id2_collision);
- EXPECT_EQ(id2_collision.id, 16);
+ EXPECT_EQ(id2_collision.id, 17);
used_ids.FindAndSetIdUsed(&id3_collision);
- EXPECT_EQ(id3_collision.id, 17);
+ EXPECT_EQ(id3_collision.id, 18);
}
// Death tests.
diff --git a/third_party/libwebrtc/pc/webrtc_sdp.cc b/third_party/libwebrtc/pc/webrtc_sdp.cc
index 88f1ce0d1b..ea9c8580cd 100644
--- a/third_party/libwebrtc/pc/webrtc_sdp.cc
+++ b/third_party/libwebrtc/pc/webrtc_sdp.cc
@@ -29,7 +29,6 @@
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "api/candidate.h"
-#include "api/crypto_params.h"
#include "api/jsep_ice_candidate.h"
#include "api/jsep_session_description.h"
#include "api/media_types.h"
@@ -74,7 +73,6 @@ using cricket::AudioContentDescription;
using cricket::Candidate;
using cricket::Candidates;
using cricket::ContentInfo;
-using cricket::CryptoParams;
using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
using cricket::ICE_CANDIDATE_COMPONENT_RTP;
using cricket::kApplicationSpecificBandwidth;
@@ -157,7 +155,6 @@ static const char kSsrcAttributeMsid[] = "msid";
static const char kDefaultMsid[] = "default";
static const char kNoStreamMsid[] = "-";
static const char kAttributeSsrcGroup[] = "ssrc-group";
-static const char kAttributeCrypto[] = "crypto";
static const char kAttributeCandidate[] = "candidate";
static const char kAttributeCandidateTyp[] = "typ";
static const char kAttributeCandidateRaddr[] = "raddr";
@@ -340,9 +337,6 @@ static bool ParseSsrcAttribute(absl::string_view line,
static bool ParseSsrcGroupAttribute(absl::string_view line,
SsrcGroupVec* ssrc_groups,
SdpParseError* error);
-static bool ParseCryptoAttribute(absl::string_view line,
- MediaContentDescription* media_desc,
- SdpParseError* error);
static bool ParseRtpmapAttribute(absl::string_view line,
const cricket::MediaType media_type,
const std::vector<int>& payload_types,
@@ -1126,7 +1120,7 @@ bool ParseCandidate(absl::string_view message,
return ParseFailed(first_line, "Unsupported transport type.", error);
}
- std::string candidate_type;
+ absl::string_view candidate_type;
const absl::string_view type = fields[7];
if (type == kCandidateHost) {
candidate_type = cricket::LOCAL_PORT_TYPE;
@@ -1668,18 +1662,6 @@ void BuildRtpContentAttributes(const MediaContentDescription* media_desc,
AddLine(os.str(), message);
}
- // RFC 4568
- // a=crypto:<tag> <crypto-suite> <key-params> [<session-params>]
- for (const CryptoParams& crypto_params : media_desc->cryptos()) {
- InitAttrLine(kAttributeCrypto, &os);
- os << kSdpDelimiterColon << crypto_params.tag << " "
- << crypto_params.crypto_suite << " " << crypto_params.key_params;
- if (!crypto_params.session_params.empty()) {
- os << " " << crypto_params.session_params;
- }
- AddLine(os.str(), message);
- }
-
// RFC 4566
// a=rtpmap:<payload type> <encoding name>/<clock rate>
// [/<encodingparameters>]
@@ -2359,6 +2341,7 @@ static bool ParseMsidAttribute(absl::string_view line,
// Note that JSEP stipulates not sending msid-appdata so
// a=msid:<stream id> <track id>
// is supported for backward compability reasons only.
+ // RFC 8830 section 2 states that duplicate a=msid:stream track is illegal.
std::vector<std::string> fields;
size_t num_fields = rtc::tokenize(line.substr(kLinePrefixLength),
kSdpDelimiterSpaceChar, &fields);
@@ -2615,6 +2598,25 @@ static void BackfillCodecParameters(std::vector<cricket::Codec>& codecs) {
if (!codec.GetParam(cricket::kH264FmtpPacketizationMode, &unused_value)) {
codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
}
+ } else if (absl::EqualsIgnoreCase(cricket::kAv1CodecName, codec.name)) {
+ // https://aomediacodec.github.io/av1-rtp-spec/#72-sdp-parameters
+ if (!codec.GetParam(cricket::kAv1FmtpProfile, &unused_value)) {
+ codec.SetParam(cricket::kAv1FmtpProfile, "0");
+ }
+ if (!codec.GetParam(cricket::kAv1FmtpLevelIdx, &unused_value)) {
+ codec.SetParam(cricket::kAv1FmtpLevelIdx, "5");
+ }
+ if (!codec.GetParam(cricket::kAv1FmtpTier, &unused_value)) {
+ codec.SetParam(cricket::kAv1FmtpTier, "0");
+ }
+ } else if (absl::EqualsIgnoreCase(cricket::kH265CodecName, codec.name)) {
+ // https://datatracker.ietf.org/doc/html/draft-aboba-avtcore-hevc-webrtc
+ if (!codec.GetParam(cricket::kH265FmtpLevelId, &unused_value)) {
+ codec.SetParam(cricket::kH265FmtpLevelId, "93");
+ }
+ if (!codec.GetParam(cricket::kH265FmtpTxMode, &unused_value)) {
+ codec.SetParam(cricket::kH265FmtpTxMode, "SRST");
+ }
}
}
}
@@ -2669,6 +2671,21 @@ static std::unique_ptr<MediaContentDescription> ParseContentDescription(
return media_desc;
}
+bool HasDuplicateMsidLines(cricket::SessionDescription* desc) {
+ std::set<std::pair<std::string, std::string>> seen_msids;
+ for (const cricket::ContentInfo& content : desc->contents()) {
+ for (const cricket::StreamParams& stream :
+ content.media_description()->streams()) {
+ auto msid = std::pair(stream.first_stream_id(), stream.id);
+ if (seen_msids.find(msid) != seen_msids.end()) {
+ return true;
+ }
+ seen_msids.insert(std::move(msid));
+ }
+ }
+ return false;
+}
+
bool ParseMediaDescription(
absl::string_view message,
const TransportDescription& session_td,
@@ -2851,6 +2868,11 @@ bool ParseMediaDescription(
// Create TransportInfo with the media level "ice-pwd" and "ice-ufrag".
desc->AddTransportInfo(TransportInfo(content_name, transport));
}
+ // Apply whole-description sanity checks
+ if (HasDuplicateMsidLines(desc)) {
+ ParseFailed(message, *pos, "Duplicate a=msid lines detected", error);
+ return false;
+ }
desc->set_msid_signaling(msid_signaling);
@@ -3206,10 +3228,6 @@ bool ParseContent(absl::string_view message,
if (!ParseSsrcAttribute(*line, &ssrc_infos, msid_signaling, error)) {
return false;
}
- } else if (HasAttribute(*line, kAttributeCrypto)) {
- if (!ParseCryptoAttribute(*line, media_desc, error)) {
- return false;
- }
} else if (HasAttribute(*line, kAttributeRtpmap)) {
if (!ParseRtpmapAttribute(*line, media_type, payload_types, media_desc,
error)) {
@@ -3537,37 +3555,6 @@ bool ParseSsrcGroupAttribute(absl::string_view line,
return true;
}
-bool ParseCryptoAttribute(absl::string_view line,
- MediaContentDescription* media_desc,
- SdpParseError* error) {
- std::vector<absl::string_view> fields =
- rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar);
- // RFC 4568
- // a=crypto:<tag> <crypto-suite> <key-params> [<session-params>]
- const size_t expected_min_fields = 3;
- if (fields.size() < expected_min_fields) {
- return ParseFailedExpectMinFieldNum(line, expected_min_fields, error);
- }
- std::string tag_value;
- if (!GetValue(fields[0], kAttributeCrypto, &tag_value, error)) {
- return false;
- }
- int tag = 0;
- if (!GetValueFromString(line, tag_value, &tag, error)) {
- return false;
- }
- const absl::string_view crypto_suite = fields[1];
- const absl::string_view key_params = fields[2];
- absl::string_view session_params;
- if (fields.size() > 3) {
- session_params = fields[3];
- }
-
- media_desc->AddCrypto(
- CryptoParams(tag, crypto_suite, key_params, session_params));
- return true;
-}
-
// Updates or creates a new codec entry in the audio description with according
// to `name`, `clockrate`, `bitrate`, and `channels`.
void UpdateCodec(int payload_type,
diff --git a/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc b/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc
index eb9bc729c6..999f0b6b26 100644
--- a/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc
+++ b/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc
@@ -25,7 +25,6 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
-#include "api/crypto_params.h"
#include "api/jsep_session_description.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
@@ -59,7 +58,6 @@ using cricket::AudioContentDescription;
using cricket::Candidate;
using cricket::ContentGroup;
using cricket::ContentInfo;
-using cricket::CryptoParams;
using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
using cricket::ICE_CANDIDATE_COMPONENT_RTP;
using cricket::kFecSsrcGroupSemantics;
@@ -102,13 +100,6 @@ static const char kCandidateFoundation1[] = "a0+B/1";
static const char kCandidateFoundation2[] = "a0+B/2";
static const char kCandidateFoundation3[] = "a0+B/3";
static const char kCandidateFoundation4[] = "a0+B/4";
-static const char kAttributeCryptoVoice[] =
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n";
-static const char kAttributeCryptoVideo[] =
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n";
static const char kFingerprint[] =
"a=fingerprint:sha-1 "
"4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n";
@@ -141,10 +132,6 @@ struct CodecParams {
int maxaveragebitrate;
};
-// TODO(deadbeef): In these reference strings, use "a=fingerprint" by default
-// instead of "a=crypto", and have an explicit test for adding "a=crypto".
-// Currently it's the other way around.
-
// Reference sdp string
static const char kSdpFullString[] =
"v=0\r\n"
@@ -171,14 +158,13 @@ static const char kSdpFullString[] =
"raddr 192.168.1.5 rport 2348 "
"generation 2\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
"a=mid:audio_content_name\r\n"
"a=sendrecv\r\n"
"a=msid:local_stream_1 audio_track_id_1\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -199,11 +185,11 @@ static const char kSdpFullString[] =
"a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
"generation 2\r\n"
"a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
"a=mid:video_content_name\r\n"
"a=sendrecv\r\n"
"a=msid:local_stream_1 video_track_id_1\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=ssrc-group:FEC 2 3\r\n"
"a=ssrc:2 cname:stream_1_cname\r\n"
@@ -221,14 +207,14 @@ static const char kSdpString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name\r\n"
"a=sendrecv\r\n"
"a=msid:local_stream_1 audio_track_id_1\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -237,11 +223,12 @@ static const char kSdpString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:video_content_name\r\n"
"a=sendrecv\r\n"
"a=msid:local_stream_1 video_track_id_1\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=ssrc-group:FEC 2 3\r\n"
"a=ssrc:2 cname:stream_1_cname\r\n"
@@ -253,6 +240,9 @@ static const char kSdpSctpDataChannelString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_data\r\n"
"a=ice-pwd:pwd_data\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:data_content_name\r\n"
"a=sctpmap:5000 webrtc-datachannel 1024\r\n";
@@ -265,6 +255,9 @@ static const char kSdpSctpDataChannelStringWithSctpPort[] =
"c=IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_data\r\n"
"a=ice-pwd:pwd_data\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:data_content_name\r\n";
// draft-ietf-mmusic-sctp-sdp-26
@@ -274,6 +267,9 @@ static const char kSdpSctpDataChannelStringWithSctpColonPort[] =
"c=IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_data\r\n"
"a=ice-pwd:pwd_data\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:data_content_name\r\n";
static const char kSdpSctpDataChannelWithCandidatesString[] =
@@ -288,6 +284,9 @@ static const char kSdpSctpDataChannelWithCandidatesString[] =
"generation 2\r\n"
"a=ice-ufrag:ufrag_data\r\n"
"a=ice-pwd:pwd_data\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:data_content_name\r\n"
"a=sctpmap:5000 webrtc-datachannel 1024\r\n";
@@ -316,6 +315,9 @@ static const char kSdpAudioString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name\r\n"
"a=sendrecv\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
@@ -327,6 +329,9 @@ static const char kSdpVideoString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:video_content_name\r\n"
"a=sendrecv\r\n"
"a=rtpmap:120 VP8/90000\r\n"
@@ -360,14 +365,14 @@ static const char kBundleOnlySdpFullString[] =
"raddr 192.168.1.5 rport 2348 "
"generation 2\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name\r\n"
"a=msid:local_stream_1 audio_track_id_1\r\n"
"a=sendrecv\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -379,9 +384,9 @@ static const char kBundleOnlySdpFullString[] =
"a=mid:video_content_name\r\n"
"a=msid:local_stream_1 video_track_id_1\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
"a=ssrc-group:FEC 2 3\r\n"
"a=ssrc:2 cname:stream_1_cname\r\n"
"a=ssrc:3 cname:stream_1_cname\r\n";
@@ -413,13 +418,13 @@ static const char kPlanBSdpFullString[] =
"raddr 192.168.1.5 rport 2348 "
"generation 2\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name\r\n"
"a=sendrecv\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -443,10 +448,11 @@ static const char kPlanBSdpFullString[] =
"a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
"generation 2\r\n"
"a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:video_content_name\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=ssrc-group:FEC 2 3\r\n"
"a=ssrc:2 cname:stream_1_cname\r\n"
@@ -486,14 +492,14 @@ static const char kUnifiedPlanSdpFullString[] =
"raddr 192.168.1.5 rport 2348 "
"generation 2\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name\r\n"
"a=msid:local_stream_1 audio_track_id_1\r\n"
"a=sendrecv\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -515,11 +521,12 @@ static const char kUnifiedPlanSdpFullString[] =
"a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
"generation 2\r\n"
"a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:video_content_name\r\n"
"a=msid:local_stream_1 video_track_id_1\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=ssrc-group:FEC 2 3\r\n"
"a=ssrc:2 cname:stream_1_cname\r\n"
@@ -529,14 +536,14 @@ static const char kUnifiedPlanSdpFullString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_voice_2\r\na=ice-pwd:pwd_voice_2\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name_2\r\n"
"a=msid:local_stream_2 audio_track_id_2\r\n"
"a=sendrecv\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -546,11 +553,12 @@ static const char kUnifiedPlanSdpFullString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_video_2\r\na=ice-pwd:pwd_video_2\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:video_content_name_2\r\n"
"a=msid:local_stream_2 video_track_id_2\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=ssrc:5 cname:stream_2_cname\r\n"
// Video track 3, stream 2.
@@ -558,11 +566,12 @@ static const char kUnifiedPlanSdpFullString[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_video_3\r\na=ice-pwd:pwd_video_3\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:video_content_name_3\r\n"
"a=msid:local_stream_2 video_track_id_3\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=ssrc:6 cname:stream_2_cname\r\n";
@@ -599,14 +608,14 @@ static const char kUnifiedPlanSdpFullStringWithSpecialMsid[] =
"raddr 192.168.1.5 rport 2348 "
"generation 2\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name\r\n"
"a=sendrecv\r\n"
"a=msid:local_stream_1 audio_track_id_1\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -617,15 +626,15 @@ static const char kUnifiedPlanSdpFullStringWithSpecialMsid[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_voice_2\r\na=ice-pwd:pwd_voice_2\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name_2\r\n"
"a=sendrecv\r\n"
"a=msid:local_stream_1 audio_track_id_2\r\n"
"a=msid:local_stream_2 audio_track_id_2\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -638,14 +647,14 @@ static const char kUnifiedPlanSdpFullStringWithSpecialMsid[] =
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
"a=ice-ufrag:ufrag_voice_3\r\na=ice-pwd:pwd_voice_3\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name_3\r\n"
"a=sendrecv\r\n"
"a=msid:- audio_track_id_3\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -678,14 +687,14 @@ static const char kUnifiedPlanSdpFullStringNoSsrc[] =
"raddr 192.168.1.5 rport 2348 "
"generation 2\r\n"
"a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:audio_content_name\r\n"
"a=msid:local_stream_1 audio_track_id_1\r\n"
"a=sendrecv\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -706,11 +715,12 @@ static const char kUnifiedPlanSdpFullStringNoSsrc[] =
"a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
"generation 2\r\n"
"a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
+ "a=fingerprint:sha-1 "
+ "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
+
"a=mid:video_content_name\r\n"
"a=msid:local_stream_1 video_track_id_1\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
// Audio track 2, stream 2.
"m=audio 9 RTP/SAVPF 111 103 104\r\n"
@@ -722,9 +732,6 @@ static const char kUnifiedPlanSdpFullStringNoSsrc[] =
"a=sendrecv\r\n"
"a=rtcp-mux\r\n"
"a=rtcp-rsize\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
- "dummy_session_params\r\n"
"a=rtpmap:111 opus/48000/2\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
"a=rtpmap:104 ISAC/32000\r\n"
@@ -736,8 +743,6 @@ static const char kUnifiedPlanSdpFullStringNoSsrc[] =
"a=mid:video_content_name_2\r\n"
"a=msid:local_stream_2 video_track_id_2\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n"
// Video track 3, stream 2.
"m=video 9 RTP/SAVPF 120\r\n"
@@ -747,8 +752,6 @@ static const char kUnifiedPlanSdpFullStringNoSsrc[] =
"a=mid:video_content_name_3\r\n"
"a=msid:local_stream_2 video_track_id_3\r\n"
"a=sendrecv\r\n"
- "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
"a=rtpmap:120 VP8/90000\r\n";
// One candidate reference string as per W3c spec.
@@ -945,6 +948,14 @@ static void ReplaceRejected(bool audio_rejected,
}
}
+static TransportDescription MakeTransportDescription(std::string ufrag,
+ std::string pwd) {
+ rtc::SSLFingerprint fingerprint(rtc::DIGEST_SHA_1, kIdentityDigest);
+ return TransportDescription(std::vector<std::string>(), ufrag, pwd,
+ cricket::ICEMODE_FULL,
+ cricket::CONNECTIONROLE_NONE, &fingerprint);
+}
+
// WebRtcSdpTest
class WebRtcSdpTest : public ::testing::Test {
@@ -982,11 +993,12 @@ class WebRtcSdpTest : public ::testing::Test {
desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp,
absl::WrapUnique(video_desc_));
- // TransportInfo
+ // TransportInfo, with fingerprint
+ rtc::SSLFingerprint fingerprint(rtc::DIGEST_SHA_1, kIdentityDigest);
desc_.AddTransportInfo(TransportInfo(
- kAudioContentName, TransportDescription(kUfragVoice, kPwdVoice)));
+ kAudioContentName, MakeTransportDescription(kUfragVoice, kPwdVoice)));
desc_.AddTransportInfo(TransportInfo(
- kVideoContentName, TransportDescription(kUfragVideo, kPwdVideo)));
+ kVideoContentName, MakeTransportDescription(kUfragVideo, kPwdVideo)));
// v4 host
int port = 1234;
@@ -1186,8 +1198,9 @@ class WebRtcSdpTest : public ::testing::Test {
audio_desc_2->AddStream(audio_track_2);
desc_.AddContent(kAudioContentName2, MediaProtocolType::kRtp,
absl::WrapUnique(audio_desc_2));
- desc_.AddTransportInfo(TransportInfo(
- kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2)));
+ desc_.AddTransportInfo(
+ TransportInfo(kAudioContentName2,
+ MakeTransportDescription(kUfragVoice2, kPwdVoice2)));
// Video track 2, in stream 2.
VideoContentDescription* video_desc_2 = CreateVideoContentDescription();
StreamParams video_track_2;
@@ -1200,8 +1213,9 @@ class WebRtcSdpTest : public ::testing::Test {
video_desc_2->AddStream(video_track_2);
desc_.AddContent(kVideoContentName2, MediaProtocolType::kRtp,
absl::WrapUnique(video_desc_2));
- desc_.AddTransportInfo(TransportInfo(
- kVideoContentName2, TransportDescription(kUfragVideo2, kPwdVideo2)));
+ desc_.AddTransportInfo(
+ TransportInfo(kVideoContentName2,
+ MakeTransportDescription(kUfragVideo2, kPwdVideo2)));
// Video track 3, in stream 2.
VideoContentDescription* video_desc_3 = CreateVideoContentDescription();
@@ -1215,8 +1229,9 @@ class WebRtcSdpTest : public ::testing::Test {
video_desc_3->AddStream(video_track_3);
desc_.AddContent(kVideoContentName3, MediaProtocolType::kRtp,
absl::WrapUnique(video_desc_3));
- desc_.AddTransportInfo(TransportInfo(
- kVideoContentName3, TransportDescription(kUfragVideo3, kPwdVideo3)));
+ desc_.AddTransportInfo(
+ TransportInfo(kVideoContentName3,
+ MakeTransportDescription(kUfragVideo3, kPwdVideo3)));
desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection |
cricket::kMsidSignalingSemantic);
@@ -1230,10 +1245,6 @@ class WebRtcSdpTest : public ::testing::Test {
AudioContentDescription* audio = new AudioContentDescription();
audio->set_rtcp_mux(true);
audio->set_rtcp_reduced_size(true);
- audio->AddCrypto(CryptoParams(
- 1, "AES_CM_128_HMAC_SHA1_32",
- "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32",
- "dummy_session_params"));
audio->set_protocol(cricket::kMediaProtocolSavpf);
audio->AddCodec(cricket::CreateAudioCodec(111, "opus", 48000, 2));
audio->AddCodec(cricket::CreateAudioCodec(103, "ISAC", 16000, 1));
@@ -1260,8 +1271,9 @@ class WebRtcSdpTest : public ::testing::Test {
audio_desc_2->AddStream(audio_track_2);
desc_.AddContent(kAudioContentName2, MediaProtocolType::kRtp,
absl::WrapUnique(audio_desc_2));
- desc_.AddTransportInfo(TransportInfo(
- kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2)));
+ desc_.AddTransportInfo(
+ TransportInfo(kAudioContentName2,
+ MakeTransportDescription(kUfragVoice2, kPwdVoice2)));
// Audio track 3 has no stream ids.
AudioContentDescription* audio_desc_3 = CreateAudioContentDescription();
@@ -1273,8 +1285,9 @@ class WebRtcSdpTest : public ::testing::Test {
audio_desc_3->AddStream(audio_track_3);
desc_.AddContent(kAudioContentName3, MediaProtocolType::kRtp,
absl::WrapUnique(audio_desc_3));
- desc_.AddTransportInfo(TransportInfo(
- kAudioContentName3, TransportDescription(kUfragVoice3, kPwdVoice3)));
+ desc_.AddTransportInfo(
+ TransportInfo(kAudioContentName3,
+ MakeTransportDescription(kUfragVoice3, kPwdVoice3)));
desc_.set_msid_signaling(msid_signaling);
ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
jdesc_.session_version()));
@@ -1308,9 +1321,6 @@ class WebRtcSdpTest : public ::testing::Test {
// configuration.
VideoContentDescription* CreateVideoContentDescription() {
VideoContentDescription* video = new VideoContentDescription();
- video->AddCrypto(CryptoParams(
- 1, "AES_CM_128_HMAC_SHA1_80",
- "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32", ""));
video->set_protocol(cricket::kMediaProtocolSavpf);
video->AddCodec(cricket::CreateVideoCodec(120, "VP8"));
return video;
@@ -1331,20 +1341,6 @@ class WebRtcSdpTest : public ::testing::Test {
// rtcp_reduced_size
EXPECT_EQ(cd1->rtcp_reduced_size(), cd2->rtcp_reduced_size());
- // cryptos
- EXPECT_EQ(cd1->cryptos().size(), cd2->cryptos().size());
- if (cd1->cryptos().size() != cd2->cryptos().size()) {
- ADD_FAILURE();
- return;
- }
- for (size_t i = 0; i < cd1->cryptos().size(); ++i) {
- const CryptoParams c1 = cd1->cryptos().at(i);
- const CryptoParams c2 = cd2->cryptos().at(i);
- EXPECT_TRUE(c1.Matches(c2));
- EXPECT_EQ(c1.key_params, c2.key_params);
- EXPECT_EQ(c1.session_params, c2.session_params);
- }
-
// protocol
// Use an equivalence class here, for old and new versions of the
// protocol description.
@@ -1497,8 +1493,14 @@ class WebRtcSdpTest : public ::testing::Test {
EXPECT_EQ(transport1.description.ice_mode,
transport2.description.ice_mode);
if (transport1.description.identity_fingerprint) {
- EXPECT_EQ(*transport1.description.identity_fingerprint,
- *transport2.description.identity_fingerprint);
+ if (!transport2.description.identity_fingerprint) {
+ ADD_FAILURE() << "transport[" << i
+ << "]: left transport has fingerprint, right transport "
+ "does not have it";
+ } else {
+ EXPECT_EQ(*transport1.description.identity_fingerprint,
+ *transport2.description.identity_fingerprint);
+ }
} else {
EXPECT_EQ(transport1.description.identity_fingerprint.get(),
transport2.description.identity_fingerprint.get());
@@ -1559,7 +1561,7 @@ class WebRtcSdpTest : public ::testing::Test {
RTC_DCHECK_NOTREACHED();
}
TransportInfo transport_info(content_name,
- TransportDescription(ufrag, pwd));
+ MakeTransportDescription(ufrag, pwd));
SessionDescription* desc =
const_cast<SessionDescription*>(jdesc->description());
desc->RemoveTransportInfoByName(content_name);
@@ -1598,22 +1600,6 @@ class WebRtcSdpTest : public ::testing::Test {
desc_.AddTransportInfo(transport_info);
}
- void AddFingerprint() {
- desc_.RemoveTransportInfoByName(kAudioContentName);
- desc_.RemoveTransportInfoByName(kVideoContentName);
- rtc::SSLFingerprint fingerprint(rtc::DIGEST_SHA_1, kIdentityDigest);
- desc_.AddTransportInfo(TransportInfo(
- kAudioContentName,
- TransportDescription(std::vector<std::string>(), kUfragVoice, kPwdVoice,
- cricket::ICEMODE_FULL,
- cricket::CONNECTIONROLE_NONE, &fingerprint)));
- desc_.AddTransportInfo(TransportInfo(
- kVideoContentName,
- TransportDescription(std::vector<std::string>(), kUfragVideo, kPwdVideo,
- cricket::ICEMODE_FULL,
- cricket::CONNECTIONROLE_NONE, &fingerprint)));
- }
-
void AddExtmap(bool encrypted) {
audio_desc_ = new AudioContentDescription(*audio_desc_);
video_desc_ = new VideoContentDescription(*video_desc_);
@@ -1629,11 +1615,6 @@ class WebRtcSdpTest : public ::testing::Test {
absl::WrapUnique(video_desc_));
}
- void RemoveCryptos() {
- audio_desc_->set_cryptos(std::vector<CryptoParams>());
- video_desc_->set_cryptos(std::vector<CryptoParams>());
- }
-
// Removes everything in StreamParams from the session description that is
// used for a=ssrc lines.
void RemoveSsrcSignalingFromStreamParams() {
@@ -1730,7 +1711,7 @@ class WebRtcSdpTest : public ::testing::Test {
desc_.AddContent(kDataContentName, MediaProtocolType::kSctp,
std::move(data));
desc_.AddTransportInfo(TransportInfo(
- kDataContentName, TransportDescription(kUfragData, kPwdData)));
+ kDataContentName, MakeTransportDescription(kUfragData, kPwdData)));
}
bool TestDeserializeDirection(RtpTransceiverDirection direction) {
@@ -2035,39 +2016,6 @@ TEST_F(WebRtcSdpTest, SerializeSessionDescriptionEmpty) {
EXPECT_EQ("", webrtc::SdpSerialize(jdesc_empty));
}
-// This tests serialization of SDP with a=crypto and a=fingerprint, as would be
-// the case in a DTLS offer.
-TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithFingerprint) {
- AddFingerprint();
- JsepSessionDescription jdesc_with_fingerprint(kDummyType);
- MakeDescriptionWithoutCandidates(&jdesc_with_fingerprint);
- std::string message = webrtc::SdpSerialize(jdesc_with_fingerprint);
-
- std::string sdp_with_fingerprint = kSdpString;
- InjectAfter(kAttributeIcePwdVoice, kFingerprint, &sdp_with_fingerprint);
- InjectAfter(kAttributeIcePwdVideo, kFingerprint, &sdp_with_fingerprint);
-
- EXPECT_EQ(sdp_with_fingerprint, message);
-}
-
-// This tests serialization of SDP with a=fingerprint with no a=crypto, as would
-// be the case in a DTLS answer.
-TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithFingerprintNoCryptos) {
- AddFingerprint();
- RemoveCryptos();
- JsepSessionDescription jdesc_with_fingerprint(kDummyType);
- MakeDescriptionWithoutCandidates(&jdesc_with_fingerprint);
- std::string message = webrtc::SdpSerialize(jdesc_with_fingerprint);
-
- std::string sdp_with_fingerprint = kSdpString;
- Replace(kAttributeCryptoVoice, "", &sdp_with_fingerprint);
- Replace(kAttributeCryptoVideo, "", &sdp_with_fingerprint);
- InjectAfter(kAttributeIcePwdVoice, kFingerprint, &sdp_with_fingerprint);
- InjectAfter(kAttributeIcePwdVideo, kFingerprint, &sdp_with_fingerprint);
-
- EXPECT_EQ(sdp_with_fingerprint, message);
-}
-
TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithoutCandidates) {
// JsepSessionDescription with desc but without candidates.
JsepSessionDescription jdesc_no_candidates(kDummyType);
@@ -2461,8 +2409,6 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutRtpmapButWithFmtp) {
// Ensure that we can deserialize SDP with a=fingerprint properly.
TEST_F(WebRtcSdpTest, DeserializeJsepSessionDescriptionWithFingerprint) {
- // Add a DTLS a=fingerprint attribute to our session description.
- AddFingerprint();
JsepSessionDescription new_jdesc(kDummyType);
ASSERT_TRUE(new_jdesc.Initialize(desc_.Clone(), jdesc_.session_id(),
jdesc_.session_version()));
@@ -3177,8 +3123,6 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithInvalidAttributeValue) {
// ssrc
ExpectParseFailure("a=ssrc:1", "a=ssrc:badvalue");
ExpectParseFailure("a=ssrc-group:FEC 2 3", "a=ssrc-group:FEC badvalue 3");
- // crypto
- ExpectParseFailure("a=crypto:1 ", "a=crypto:badvalue ");
// rtpmap
ExpectParseFailure("a=rtpmap:111 ", "a=rtpmap:badvalue ");
ExpectParseFailure("opus/48000/2", "opus/badvalue/2");
@@ -3564,7 +3508,6 @@ TEST_F(WebRtcSdpTest, RoundTripSdpWithSctpDataChannelsWithCandidates) {
}
TEST_F(WebRtcSdpTest, SerializeDtlsSetupAttribute) {
- AddFingerprint();
TransportInfo audio_transport_info =
*(desc_.GetTransportInfoByName(kAudioContentName));
EXPECT_EQ(cricket::CONNECTIONROLE_NONE,
@@ -3590,9 +3533,6 @@ TEST_F(WebRtcSdpTest, SerializeDtlsSetupAttribute) {
std::string message = webrtc::SdpSerialize(jdesc_);
std::string sdp_with_dtlssetup = kSdpFullString;
- // Fingerprint attribute is necessary to add DTLS setup attribute.
- InjectAfter(kAttributeIcePwdVoice, kFingerprint, &sdp_with_dtlssetup);
- InjectAfter(kAttributeIcePwdVideo, kFingerprint, &sdp_with_dtlssetup);
// Now adding `setup` attribute.
InjectAfter(kFingerprint, "a=setup:active\r\n", &sdp_with_dtlssetup);
EXPECT_EQ(sdp_with_dtlssetup, message);
@@ -4331,6 +4271,27 @@ TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithMissingStreamId) {
EXPECT_FALSE(SdpDeserialize(sdp, &jdesc_output));
}
+TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithDuplicateStreamIdAndTrackId) {
+ std::string sdp =
+ "v=0\r\n"
+ "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
+ "s=-\r\n"
+ "t=0 0\r\n"
+ "m=audio 9 RTP/SAVPF 111\r\n"
+ "a=mid:0\r\n"
+ "c=IN IP4 0.0.0.0\r\n"
+ "a=rtpmap:111 opus/48000/2\r\n"
+ "a=msid:stream_id track_id\r\n"
+ "m=audio 9 RTP/SAVPF 111\r\n"
+ "a=mid:1\r\n"
+ "c=IN IP4 0.0.0.0\r\n"
+ "a=rtpmap:111 opus/48000/2\r\n"
+ "a=msid:stream_id track_id\r\n";
+
+ JsepSessionDescription jdesc_output(kDummyType);
+ EXPECT_FALSE(SdpDeserialize(sdp, &jdesc_output));
+}
+
// Tests that if both session-level address and media-level address exist, use
// the media-level address.
TEST_F(WebRtcSdpTest, ParseConnectionData) {
@@ -5121,13 +5082,15 @@ TEST_F(WebRtcSdpTest, BackfillsDefaultFmtpValues) {
"a=setup:actpass\r\n"
"a=ice-ufrag:ETEn\r\n"
"a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n"
- "m=video 9 UDP/TLS/RTP/SAVPF 96 97\r\n"
+ "m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99\r\n"
"c=IN IP4 0.0.0.0\r\n"
"a=rtcp-mux\r\n"
"a=sendonly\r\n"
"a=mid:0\r\n"
"a=rtpmap:96 H264/90000\r\n"
"a=rtpmap:97 VP9/90000\r\n"
+ "a=rtpmap:98 AV1/90000\r\n"
+ "a=rtpmap:99 H265/90000\r\n"
"a=ssrc:1234 cname:test\r\n";
JsepSessionDescription jdesc(kDummyType);
EXPECT_TRUE(SdpDeserialize(sdp, &jdesc));
@@ -5136,7 +5099,7 @@ TEST_F(WebRtcSdpTest, BackfillsDefaultFmtpValues) {
const auto* description = content.media_description();
ASSERT_NE(description, nullptr);
const std::vector<cricket::Codec> codecs = description->codecs();
- ASSERT_EQ(codecs.size(), 2u);
+ ASSERT_EQ(codecs.size(), 4u);
std::string value;
EXPECT_EQ(codecs[0].name, "H264");
@@ -5146,4 +5109,18 @@ TEST_F(WebRtcSdpTest, BackfillsDefaultFmtpValues) {
EXPECT_EQ(codecs[1].name, "VP9");
EXPECT_TRUE(codecs[1].GetParam("profile-id", &value));
EXPECT_EQ(value, "0");
+
+ EXPECT_EQ(codecs[2].name, "AV1");
+ EXPECT_TRUE(codecs[2].GetParam("profile", &value));
+ EXPECT_EQ(value, "0");
+ EXPECT_TRUE(codecs[2].GetParam("level-idx", &value));
+ EXPECT_EQ(value, "5");
+ EXPECT_TRUE(codecs[2].GetParam("tier", &value));
+ EXPECT_EQ(value, "0");
+
+ EXPECT_EQ(codecs[3].name, "H265");
+ EXPECT_TRUE(codecs[3].GetParam("level-id", &value));
+ EXPECT_EQ(value, "93");
+ EXPECT_TRUE(codecs[3].GetParam("tx-mode", &value));
+ EXPECT_EQ(value, "SRST");
}
diff --git a/third_party/libwebrtc/pc/webrtc_session_description_factory.cc b/third_party/libwebrtc/pc/webrtc_session_description_factory.cc
index 42a8da3e70..9919260aa3 100644
--- a/third_party/libwebrtc/pc/webrtc_session_description_factory.cc
+++ b/third_party/libwebrtc/pc/webrtc_session_description_factory.cc
@@ -128,13 +128,10 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
RTC_DCHECK(signaling_thread_);
if (!dtls_enabled) {
- SetSdesPolicy(cricket::SEC_REQUIRED);
- RTC_LOG(LS_VERBOSE) << "DTLS-SRTP disabled.";
+ RTC_LOG(LS_INFO) << "DTLS-SRTP disabled";
+ transport_desc_factory_.SetInsecureForTesting();
return;
}
-
- // SRTP-SDES is disabled if DTLS is on.
- SetSdesPolicy(cricket::SEC_DISABLED);
if (certificate) {
// Use `certificate`.
certificate_request_state_ = CERTIFICATE_WAITING;
@@ -142,31 +139,32 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
RTC_LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter.";
RTC_LOG(LS_INFO) << "Using certificate supplied to the constructor.";
SetCertificate(certificate);
- } else {
- // Generate certificate.
- certificate_request_state_ = CERTIFICATE_WAITING;
-
- auto callback = [weak_ptr = weak_factory_.GetWeakPtr()](
- rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
- if (!weak_ptr) {
- return;
- }
- if (certificate) {
- weak_ptr->SetCertificate(std::move(certificate));
- } else {
- weak_ptr->OnCertificateRequestFailed();
- }
- };
+ return;
+ }
+ // Generate certificate.
+ RTC_DCHECK(cert_generator_);
+ certificate_request_state_ = CERTIFICATE_WAITING;
+
+ auto callback = [weak_ptr = weak_factory_.GetWeakPtr()](
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
+ if (!weak_ptr) {
+ return;
+ }
+ if (certificate) {
+ weak_ptr->SetCertificate(std::move(certificate));
+ } else {
+ weak_ptr->OnCertificateRequestFailed();
+ }
+ };
- rtc::KeyParams key_params = rtc::KeyParams();
- RTC_LOG(LS_VERBOSE)
- << "DTLS-SRTP enabled; sending DTLS identity request (key type: "
- << key_params.type() << ").";
+ rtc::KeyParams key_params = rtc::KeyParams();
+ RTC_LOG(LS_VERBOSE)
+ << "DTLS-SRTP enabled; sending DTLS identity request (key type: "
+ << key_params.type() << ").";
- // Request certificate. This happens asynchronously on a different thread.
- cert_generator_->GenerateCertificateAsync(key_params, absl::nullopt,
- std::move(callback));
- }
+ // Request certificate. This happens asynchronously on a different thread.
+ cert_generator_->GenerateCertificateAsync(key_params, absl::nullopt,
+ std::move(callback));
}
WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
@@ -258,15 +256,6 @@ void WebRtcSessionDescriptionFactory::CreateAnswer(
}
}
-void WebRtcSessionDescriptionFactory::SetSdesPolicy(
- cricket::SecurePolicy secure_policy) {
- session_desc_factory_.set_secure(secure_policy);
-}
-
-cricket::SecurePolicy WebRtcSessionDescriptionFactory::SdesPolicy() const {
- return session_desc_factory_.secure();
-}
-
void WebRtcSessionDescriptionFactory::InternalCreateOffer(
CreateSessionDescriptionRequest request) {
if (sdp_info_->local_description()) {
@@ -450,7 +439,6 @@ void WebRtcSessionDescriptionFactory::SetCertificate(
on_certificate_ready_(certificate);
transport_desc_factory_.set_certificate(std::move(certificate));
- transport_desc_factory_.set_secure(cricket::SEC_ENABLED);
while (!create_session_description_requests_.empty()) {
if (create_session_description_requests_.front().type ==
@@ -462,4 +450,5 @@ void WebRtcSessionDescriptionFactory::SetCertificate(
create_session_description_requests_.pop();
}
}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/pc/webrtc_session_description_factory.h b/third_party/libwebrtc/pc/webrtc_session_description_factory.h
index 22ead41d9b..eed922eda7 100644
--- a/third_party/libwebrtc/pc/webrtc_session_description_factory.h
+++ b/third_party/libwebrtc/pc/webrtc_session_description_factory.h
@@ -73,9 +73,6 @@ class WebRtcSessionDescriptionFactory {
void CreateAnswer(CreateSessionDescriptionObserver* observer,
const cricket::MediaSessionOptions& session_options);
- void SetSdesPolicy(cricket::SecurePolicy secure_policy);
- cricket::SecurePolicy SdesPolicy() const;
-
void set_enable_encrypted_rtp_header_extensions(bool enable) {
session_desc_factory_.set_enable_encrypted_rtp_header_extensions(enable);
}
@@ -88,6 +85,9 @@ class WebRtcSessionDescriptionFactory {
bool waiting_for_certificate_for_testing() const {
return certificate_request_state_ == CERTIFICATE_WAITING;
}
+ void SetInsecureForTesting() {
+ transport_desc_factory_.SetInsecureForTesting();
+ }
private:
enum CertificateRequestState {
@@ -144,6 +144,7 @@ class WebRtcSessionDescriptionFactory {
std::function<void(const rtc::scoped_refptr<rtc::RTCCertificate>&)>
on_certificate_ready_;
+
rtc::WeakPtrFactory<WebRtcSessionDescriptionFactory> weak_factory_{this};
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/rtc_base/BUILD.gn b/third_party/libwebrtc/rtc_base/BUILD.gn
index 57a9c11f01..eb88039d33 100644
--- a/third_party/libwebrtc/rtc_base/BUILD.gn
+++ b/third_party/libwebrtc/rtc_base/BUILD.gn
@@ -1120,6 +1120,7 @@ rtc_library("socket") {
]
deps = [
":buffer",
+ ":checks",
":macromagic",
":socket_address",
"../api/units:timestamp",
@@ -1756,6 +1757,7 @@ rtc_library("rtc_base_tests_utils") {
":async_socket",
":async_tcp_socket",
":async_udp_socket",
+ ":buffer",
":byte_buffer",
":checks",
":ip_address",
@@ -1775,6 +1777,7 @@ rtc_library("rtc_base_tests_utils") {
":stringutils",
":threading",
":timeutils",
+ "../api:array_view",
"../api:make_ref_counted",
"../api:refcountedbase",
"../api:scoped_refptr",
@@ -1890,6 +1893,7 @@ if (rtc_include_tests) {
":threading",
":timeutils",
"../api/units:time_delta",
+ "../api/units:timestamp",
"../system_wrappers",
"../test:field_trial",
"../test:fileutils",
@@ -2122,7 +2126,6 @@ if (rtc_include_tests) {
"nat_unittest.cc",
"network_route_unittest.cc",
"network_unittest.cc",
- "proxy_unittest.cc",
"rolling_accumulator_unittest.cc",
"rtc_certificate_generator_unittest.cc",
"rtc_certificate_unittest.cc",
diff --git a/third_party/libwebrtc/rtc_base/ip_address.h b/third_party/libwebrtc/rtc_base/ip_address.h
index 897e165565..c015206ab3 100644
--- a/third_party/libwebrtc/rtc_base/ip_address.h
+++ b/third_party/libwebrtc/rtc_base/ip_address.h
@@ -162,8 +162,8 @@ RTC_EXPORT bool IPFromString(absl::string_view str,
int flags,
InterfaceAddress* out);
bool IPIsAny(const IPAddress& ip);
-bool IPIsLoopback(const IPAddress& ip);
-bool IPIsLinkLocal(const IPAddress& ip);
+RTC_EXPORT bool IPIsLoopback(const IPAddress& ip);
+RTC_EXPORT bool IPIsLinkLocal(const IPAddress& ip);
// Identify a private network address like "192.168.111.222"
// (see https://en.wikipedia.org/wiki/Private_network )
bool IPIsPrivateNetwork(const IPAddress& ip);
diff --git a/third_party/libwebrtc/rtc_base/nat_server.cc b/third_party/libwebrtc/rtc_base/nat_server.cc
index c274cedf18..f21d404bd3 100644
--- a/third_party/libwebrtc/rtc_base/nat_server.cc
+++ b/third_party/libwebrtc/rtc_base/nat_server.cc
@@ -11,8 +11,10 @@
#include "rtc_base/nat_server.h"
#include <cstddef>
+#include <cstdint>
#include <memory>
+#include "api/array_view.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/nat_socket_factory.h"
@@ -97,8 +99,9 @@ class NATProxyServerSocket : public AsyncProxyServerSocket {
}
SocketAddress dest_addr;
- size_t address_length = UnpackAddressFromNAT(data, *len, &dest_addr);
-
+ size_t address_length = UnpackAddressFromNAT(
+ MakeArrayView(reinterpret_cast<const uint8_t*>(data), *len),
+ &dest_addr);
*len -= address_length;
if (*len > 0) {
memmove(data, data + address_length, *len);
@@ -171,15 +174,12 @@ NATServer::~NATServer() {
void NATServer::OnInternalUDPPacket(AsyncPacketSocket* socket,
const rtc::ReceivedPacket& packet) {
RTC_DCHECK(internal_socket_thread_.IsCurrent());
- const char* buf = reinterpret_cast<const char*>(packet.payload().data());
- size_t size = packet.payload().size();
- const SocketAddress& addr = packet.source_address();
// Read the intended destination from the wire.
SocketAddress dest_addr;
- size_t length = UnpackAddressFromNAT(buf, size, &dest_addr);
+ size_t length = UnpackAddressFromNAT(packet.payload(), &dest_addr);
// Find the translation for these addresses (allocating one if necessary).
- SocketAddressPair route(addr, dest_addr);
+ SocketAddressPair route(packet.source_address(), dest_addr);
InternalMap::iterator iter = int_map_->find(route);
if (iter == int_map_->end()) {
Translate(route);
@@ -192,6 +192,8 @@ void NATServer::OnInternalUDPPacket(AsyncPacketSocket* socket,
// Send the packet to its intended destination.
rtc::PacketOptions options;
+ const char* buf = reinterpret_cast<const char*>(packet.payload().data());
+ size_t size = packet.payload().size();
iter->second->socket->SendTo(buf + length, size - length, dest_addr, options);
}
diff --git a/third_party/libwebrtc/rtc_base/nat_socket_factory.cc b/third_party/libwebrtc/rtc_base/nat_socket_factory.cc
index 83ec2bc327..66e4f84cd7 100644
--- a/third_party/libwebrtc/rtc_base/nat_socket_factory.cc
+++ b/third_party/libwebrtc/rtc_base/nat_socket_factory.cc
@@ -10,7 +10,9 @@
#include "rtc_base/nat_socket_factory.h"
+#include "api/units/timestamp.h"
#include "rtc_base/arraysize.h"
+#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/nat_server.h"
@@ -47,21 +49,20 @@ size_t PackAddressForNAT(char* buf,
// Decodes the remote address from a packet that has been encoded with the nat's
// quasi-STUN format. Returns the length of the address (i.e., the offset into
// data where the original packet starts).
-size_t UnpackAddressFromNAT(const char* buf,
- size_t buf_size,
+size_t UnpackAddressFromNAT(rtc::ArrayView<const uint8_t> buf,
SocketAddress* remote_addr) {
- RTC_DCHECK(buf_size >= 8);
- RTC_DCHECK(buf[0] == 0);
+ RTC_CHECK(buf.size() >= 8);
+ RTC_DCHECK(buf.data()[0] == 0);
int family = buf[1];
uint16_t port =
- NetworkToHost16(*(reinterpret_cast<const uint16_t*>(&buf[2])));
+ NetworkToHost16(*(reinterpret_cast<const uint16_t*>(&buf.data()[2])));
if (family == AF_INET) {
- const in_addr* v4addr = reinterpret_cast<const in_addr*>(&buf[4]);
+ const in_addr* v4addr = reinterpret_cast<const in_addr*>(&buf.data()[4]);
*remote_addr = SocketAddress(IPAddress(*v4addr), port);
return kNATEncodedIPv4AddressSize;
} else if (family == AF_INET6) {
- RTC_DCHECK(buf_size >= 20);
- const in6_addr* v6addr = reinterpret_cast<const in6_addr*>(&buf[4]);
+ RTC_DCHECK(buf.size() >= 20);
+ const in6_addr* v6addr = reinterpret_cast<const in6_addr*>(&buf.data()[4]);
*remote_addr = SocketAddress(IPAddress(*v6addr), port);
return kNATEncodedIPv6AddressSize;
}
@@ -76,14 +77,9 @@ class NATSocket : public Socket, public sigslot::has_slots<> {
family_(family),
type_(type),
connected_(false),
- socket_(nullptr),
- buf_(nullptr),
- size_(0) {}
+ socket_(nullptr) {}
- ~NATSocket() override {
- delete socket_;
- delete[] buf_;
- }
+ ~NATSocket() override { delete socket_; }
SocketAddress GetLocalAddress() const override {
return (socket_) ? socket_->GetLocalAddress() : SocketAddress();
@@ -165,23 +161,21 @@ class NATSocket : public Socket, public sigslot::has_slots<> {
}
// Make sure we have enough room to read the requested amount plus the
// largest possible header address.
- SocketAddress remote_addr;
- Grow(size + kNATEncodedIPv6AddressSize);
+ buf_.EnsureCapacity(size + kNATEncodedIPv6AddressSize);
// Read the packet from the socket.
- int result = socket_->RecvFrom(buf_, size_, &remote_addr, timestamp);
+ Socket::ReceiveBuffer receive_buffer(buf_);
+ int result = socket_->RecvFrom(receive_buffer);
if (result >= 0) {
- RTC_DCHECK(remote_addr == server_addr_);
-
- // TODO: we need better framing so we know how many bytes we can
- // return before we need to read the next address. For UDP, this will be
- // fine as long as the reader always reads everything in the packet.
- RTC_DCHECK((size_t)result < size_);
+ RTC_DCHECK(receive_buffer.source_address == server_addr_);
+ *timestamp =
+ receive_buffer.arrival_time.value_or(webrtc::Timestamp::Micros(0))
+ .us();
// Decode the wire packet into the actual results.
SocketAddress real_remote_addr;
- size_t addrlength = UnpackAddressFromNAT(buf_, result, &real_remote_addr);
- memcpy(data, buf_ + addrlength, result - addrlength);
+ size_t addrlength = UnpackAddressFromNAT(buf_, &real_remote_addr);
+ memcpy(data, buf_.data() + addrlength, result - addrlength);
// Make sure this packet should be delivered before returning it.
if (!connected_ || (real_remote_addr == remote_addr_)) {
@@ -285,15 +279,6 @@ class NATSocket : public Socket, public sigslot::has_slots<> {
return result;
}
- // Makes sure the buffer is at least the given size.
- void Grow(size_t new_size) {
- if (size_ < new_size) {
- delete[] buf_;
- size_ = new_size;
- buf_ = new char[size_];
- }
- }
-
// Sends the destination address to the server to tell it to connect.
void SendConnectRequest() {
char buf[kNATEncodedIPv6AddressSize];
@@ -323,8 +308,7 @@ class NATSocket : public Socket, public sigslot::has_slots<> {
Socket* socket_;
// Need to hold error in case it occurs before the socket is created.
int error_ = 0;
- char* buf_;
- size_t size_;
+ Buffer buf_;
};
// NATSocketFactory
diff --git a/third_party/libwebrtc/rtc_base/nat_socket_factory.h b/third_party/libwebrtc/rtc_base/nat_socket_factory.h
index f803496b05..5adcaa5dfd 100644
--- a/third_party/libwebrtc/rtc_base/nat_socket_factory.h
+++ b/third_party/libwebrtc/rtc_base/nat_socket_factory.h
@@ -13,10 +13,13 @@
#include <stddef.h>
+#include <cstdint>
#include <map>
#include <memory>
#include <set>
+#include "api/array_view.h"
+#include "rtc_base/buffer.h"
#include "rtc_base/nat_server.h"
#include "rtc_base/nat_types.h"
#include "rtc_base/socket.h"
@@ -172,8 +175,7 @@ class NATSocketServer : public SocketServer, public NATInternalSocketFactory {
size_t PackAddressForNAT(char* buf,
size_t buf_size,
const SocketAddress& remote_addr);
-size_t UnpackAddressFromNAT(const char* buf,
- size_t buf_size,
+size_t UnpackAddressFromNAT(rtc::ArrayView<const uint8_t> buf,
SocketAddress* remote_addr);
} // namespace rtc
diff --git a/third_party/libwebrtc/rtc_base/nat_unittest.cc b/third_party/libwebrtc/rtc_base/nat_unittest.cc
index 742e0d6ee7..978a30aefe 100644
--- a/third_party/libwebrtc/rtc_base/nat_unittest.cc
+++ b/third_party/libwebrtc/rtc_base/nat_unittest.cc
@@ -233,12 +233,12 @@ bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
const char* buf = "hello other socket";
size_t len = strlen(buf);
int sent = client->SendTo(buf, len, server->GetLocalAddress());
- SocketAddress addr;
- const size_t kRecvBufSize = 64;
- char recvbuf[kRecvBufSize];
+
Thread::Current()->SleepMs(100);
- int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr, nullptr);
- return received == sent && ::memcmp(buf, recvbuf, len) == 0;
+ rtc::Buffer payload;
+ Socket::ReceiveBuffer receive_buffer(payload);
+ int received = server->RecvFrom(receive_buffer);
+ return received == sent && ::memcmp(buf, payload.data(), len) == 0;
}
void TestPhysicalInternal(const SocketAddress& int_addr) {
diff --git a/third_party/libwebrtc/rtc_base/physical_socket_server.cc b/third_party/libwebrtc/rtc_base/physical_socket_server.cc
index 95ba130e91..a5fe32722b 100644
--- a/third_party/libwebrtc/rtc_base/physical_socket_server.cc
+++ b/third_party/libwebrtc/rtc_base/physical_socket_server.cc
@@ -435,6 +435,31 @@ int PhysicalSocket::RecvFrom(void* buffer,
SocketAddress* out_addr,
int64_t* timestamp) {
int received = DoReadFromSocket(buffer, length, out_addr, timestamp);
+
+ UpdateLastError();
+ int error = GetError();
+ bool success = (received >= 0) || IsBlockingError(error);
+ if (udp_ || success) {
+ EnableEvents(DE_READ);
+ }
+ if (!success) {
+ RTC_LOG_F(LS_VERBOSE) << "Error = " << error;
+ }
+ return received;
+}
+
+int PhysicalSocket::RecvFrom(ReceiveBuffer& buffer) {
+ int64_t timestamp = -1;
+ static constexpr int BUF_SIZE = 64 * 1024;
+ buffer.payload.EnsureCapacity(BUF_SIZE);
+
+ int received =
+ DoReadFromSocket(buffer.payload.data(), buffer.payload.capacity(),
+ &buffer.source_address, &timestamp);
+ buffer.payload.SetSize(received > 0 ? received : 0);
+ if (received > 0 && timestamp != -1) {
+ buffer.arrival_time = webrtc::Timestamp::Micros(timestamp);
+ }
UpdateLastError();
int error = GetError();
bool success = (received >= 0) || IsBlockingError(error);
diff --git a/third_party/libwebrtc/rtc_base/physical_socket_server.h b/third_party/libwebrtc/rtc_base/physical_socket_server.h
index 584f42a188..2af563a3ca 100644
--- a/third_party/libwebrtc/rtc_base/physical_socket_server.h
+++ b/third_party/libwebrtc/rtc_base/physical_socket_server.h
@@ -188,10 +188,12 @@ class PhysicalSocket : public Socket, public sigslot::has_slots<> {
const SocketAddress& addr) override;
int Recv(void* buffer, size_t length, int64_t* timestamp) override;
+ // TODO(webrtc:15368): Deprecate and remove.
int RecvFrom(void* buffer,
size_t length,
SocketAddress* out_addr,
int64_t* timestamp) override;
+ int RecvFrom(ReceiveBuffer& buffer) override;
int Listen(int backlog) override;
Socket* Accept(SocketAddress* out_addr) override;
diff --git a/third_party/libwebrtc/rtc_base/proxy_server.cc b/third_party/libwebrtc/rtc_base/proxy_server.cc
index 84c96213c3..f8fe23da2a 100644
--- a/third_party/libwebrtc/rtc_base/proxy_server.cc
+++ b/third_party/libwebrtc/rtc_base/proxy_server.cc
@@ -149,8 +149,4 @@ void ProxyBinding::Destroy() {
SignalDestroyed(this);
}
-AsyncProxyServerSocket* SocksProxyServer::WrapSocket(Socket* socket) {
- return new AsyncSocksProxyServerSocket(socket);
-}
-
} // namespace rtc
diff --git a/third_party/libwebrtc/rtc_base/proxy_server.h b/third_party/libwebrtc/rtc_base/proxy_server.h
index 0b9b655a5e..033dd82118 100644
--- a/third_party/libwebrtc/rtc_base/proxy_server.h
+++ b/third_party/libwebrtc/rtc_base/proxy_server.h
@@ -89,22 +89,6 @@ class ProxyServer : public sigslot::has_slots<> {
std::vector<std::unique_ptr<ProxyBinding>> bindings_;
};
-// SocksProxyServer is a simple extension of ProxyServer to implement SOCKS.
-class SocksProxyServer : public ProxyServer {
- public:
- SocksProxyServer(SocketFactory* int_factory,
- const SocketAddress& int_addr,
- SocketFactory* ext_factory,
- const SocketAddress& ext_ip)
- : ProxyServer(int_factory, int_addr, ext_factory, ext_ip) {}
-
- SocksProxyServer(const SocksProxyServer&) = delete;
- SocksProxyServer& operator=(const SocksProxyServer&) = delete;
-
- protected:
- AsyncProxyServerSocket* WrapSocket(Socket* socket) override;
-};
-
} // namespace rtc
#endif // RTC_BASE_PROXY_SERVER_H_
diff --git a/third_party/libwebrtc/rtc_base/proxy_unittest.cc b/third_party/libwebrtc/rtc_base/proxy_unittest.cc
deleted file mode 100644
index 9e3898e430..0000000000
--- a/third_party/libwebrtc/rtc_base/proxy_unittest.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2009 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <memory>
-#include <string>
-
-#include "rtc_base/gunit.h"
-#include "rtc_base/proxy_server.h"
-#include "rtc_base/socket_adapters.h"
-#include "rtc_base/test_client.h"
-#include "rtc_base/test_echo_server.h"
-#include "rtc_base/virtual_socket_server.h"
-
-using rtc::Socket;
-using rtc::SocketAddress;
-
-static const SocketAddress kSocksProxyIntAddr("1.2.3.4", 1080);
-static const SocketAddress kSocksProxyExtAddr("1.2.3.5", 0);
-static const SocketAddress kBogusProxyIntAddr("1.2.3.4", 999);
-
-// Sets up a virtual socket server and a SOCKS5 proxy server.
-class ProxyTest : public ::testing::Test {
- public:
- ProxyTest() : ss_(new rtc::VirtualSocketServer()), thread_(ss_.get()) {
- socks_.reset(new rtc::SocksProxyServer(ss_.get(), kSocksProxyIntAddr,
- ss_.get(), kSocksProxyExtAddr));
- }
-
- rtc::SocketServer* ss() { return ss_.get(); }
-
- private:
- std::unique_ptr<rtc::SocketServer> ss_;
- rtc::AutoSocketServerThread thread_;
- std::unique_ptr<rtc::SocksProxyServer> socks_;
-};
-
-// Tests whether we can use a SOCKS5 proxy to connect to a server.
-TEST_F(ProxyTest, TestSocks5Connect) {
- rtc::Socket* socket =
- ss()->CreateSocket(kSocksProxyIntAddr.family(), SOCK_STREAM);
- rtc::AsyncSocksProxySocket* proxy_socket = new rtc::AsyncSocksProxySocket(
- socket, kSocksProxyIntAddr, "", rtc::CryptString());
- // TODO: IPv6-ize these tests when proxy supports IPv6.
-
- rtc::TestEchoServer server(rtc::Thread::Current(),
- SocketAddress(INADDR_ANY, 0));
-
- std::unique_ptr<rtc::AsyncTCPSocket> packet_socket(
- rtc::AsyncTCPSocket::Create(proxy_socket, SocketAddress(INADDR_ANY, 0),
- server.address()));
- EXPECT_TRUE(packet_socket != nullptr);
- rtc::TestClient client(std::move(packet_socket));
-
- EXPECT_EQ(Socket::CS_CONNECTING, proxy_socket->GetState());
- EXPECT_TRUE(client.CheckConnected());
- EXPECT_EQ(Socket::CS_CONNECTED, proxy_socket->GetState());
- EXPECT_EQ(server.address(), client.remote_address());
- client.Send("foo", 3);
- EXPECT_TRUE(client.CheckNextPacket("foo", 3, nullptr));
- EXPECT_TRUE(client.CheckNoPacket());
-}
diff --git a/third_party/libwebrtc/rtc_base/server_socket_adapters.cc b/third_party/libwebrtc/rtc_base/server_socket_adapters.cc
index 0bef752f1e..5a4db26dd2 100644
--- a/third_party/libwebrtc/rtc_base/server_socket_adapters.cc
+++ b/third_party/libwebrtc/rtc_base/server_socket_adapters.cc
@@ -55,135 +55,4 @@ void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
BufferInput(false);
}
-AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(Socket* socket)
- : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
- BufferInput(true);
-}
-
-void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
- RTC_DCHECK(state_ < SS_CONNECT_PENDING);
-
- ByteBufferReader response(
- rtc::MakeArrayView(reinterpret_cast<const uint8_t*>(data), *len));
- if (state_ == SS_HELLO) {
- HandleHello(&response);
- } else if (state_ == SS_AUTH) {
- HandleAuth(&response);
- } else if (state_ == SS_CONNECT) {
- HandleConnect(&response);
- }
-
- // Consume parsed data
- *len = response.Length();
- if (response.Length() > 0) {
- memmove(data, response.DataView().data(), *len);
- }
-}
-
-void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
- BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
-}
-
-void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
- uint8_t ver, num_methods;
- if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) {
- Error(0);
- return;
- }
-
- if (ver != 5) {
- Error(0);
- return;
- }
-
- // Handle either no-auth (0) or user/pass auth (2)
- uint8_t method = 0xFF;
- if (num_methods > 0 && !request->ReadUInt8(&method)) {
- Error(0);
- return;
- }
-
- SendHelloReply(method);
- if (method == 0) {
- state_ = SS_CONNECT;
- } else if (method == 2) {
- state_ = SS_AUTH;
- } else {
- state_ = SS_ERROR;
- }
-}
-
-void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
- ByteBufferWriter response;
- response.WriteUInt8(5); // Socks Version
- response.WriteUInt8(method); // Auth method
- DirectSend(response);
-}
-
-void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
- uint8_t ver, user_len, pass_len;
- std::string user, pass;
- if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) ||
- !request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) ||
- !request->ReadString(&pass, pass_len)) {
- Error(0);
- return;
- }
-
- SendAuthReply(0);
- state_ = SS_CONNECT;
-}
-
-void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
- ByteBufferWriter response;
- response.WriteUInt8(1); // Negotiation Version
- response.WriteUInt8(result);
- DirectSend(response);
-}
-
-void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
- uint8_t ver, command, reserved, addr_type;
- uint32_t ip;
- uint16_t port;
- if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) ||
- !request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) ||
- !request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) {
- Error(0);
- return;
- }
-
- if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) {
- Error(0);
- return;
- }
-
- SignalConnectRequest(this, SocketAddress(ip, port));
- state_ = SS_CONNECT_PENDING;
-}
-
-void AsyncSocksProxyServerSocket::SendConnectResult(int result,
- const SocketAddress& addr) {
- if (state_ != SS_CONNECT_PENDING)
- return;
-
- ByteBufferWriter response;
- response.WriteUInt8(5); // Socks version
- response.WriteUInt8((result != 0)); // 0x01 is generic error
- response.WriteUInt8(0); // reserved
- response.WriteUInt8(1); // IPv4 address
- response.WriteUInt32(addr.ip());
- response.WriteUInt16(addr.port());
- DirectSend(response);
- BufferInput(false);
- state_ = SS_TUNNEL;
-}
-
-void AsyncSocksProxyServerSocket::Error(int error) {
- state_ = SS_ERROR;
- BufferInput(false);
- Close();
- SetError(SOCKET_EACCES);
- SignalCloseEvent(this, error);
-}
-
} // namespace rtc
diff --git a/third_party/libwebrtc/rtc_base/server_socket_adapters.h b/third_party/libwebrtc/rtc_base/server_socket_adapters.h
index b18c7a6a65..05dcd292f8 100644
--- a/third_party/libwebrtc/rtc_base/server_socket_adapters.h
+++ b/third_party/libwebrtc/rtc_base/server_socket_adapters.h
@@ -38,40 +38,6 @@ class AsyncSSLServerSocket : public BufferedReadAdapter {
void ProcessInput(char* data, size_t* len) override;
};
-// Implements a proxy server socket for the SOCKS protocol.
-class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
- public:
- explicit AsyncSocksProxyServerSocket(Socket* socket);
-
- AsyncSocksProxyServerSocket(const AsyncSocksProxyServerSocket&) = delete;
- AsyncSocksProxyServerSocket& operator=(const AsyncSocksProxyServerSocket&) =
- delete;
-
- private:
- void ProcessInput(char* data, size_t* len) override;
- void DirectSend(const ByteBufferWriter& buf);
-
- void HandleHello(ByteBufferReader* request);
- void SendHelloReply(uint8_t method);
- void HandleAuth(ByteBufferReader* request);
- void SendAuthReply(uint8_t result);
- void HandleConnect(ByteBufferReader* request);
- void SendConnectResult(int result, const SocketAddress& addr) override;
-
- void Error(int error);
-
- static const int kBufferSize = 1024;
- enum State {
- SS_HELLO,
- SS_AUTH,
- SS_CONNECT,
- SS_CONNECT_PENDING,
- SS_TUNNEL,
- SS_ERROR
- };
- State state_;
-};
-
} // namespace rtc
#endif // RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
diff --git a/third_party/libwebrtc/rtc_base/socket.h b/third_party/libwebrtc/rtc_base/socket.h
index fac75aca94..98e468e754 100644
--- a/third_party/libwebrtc/rtc_base/socket.h
+++ b/third_party/libwebrtc/rtc_base/socket.h
@@ -14,6 +14,7 @@
#include <errno.h>
#include "absl/types/optional.h"
+#include "rtc_base/checks.h"
#if defined(WEBRTC_POSIX)
#include <arpa/inet.h>
@@ -86,11 +87,11 @@ inline bool IsBlockingError(int e) {
class RTC_EXPORT Socket {
public:
struct ReceiveBuffer {
- ReceiveBuffer(rtc::Buffer& payload) : payload(payload) {}
+ ReceiveBuffer(Buffer& payload) : payload(payload) {}
absl::optional<webrtc::Timestamp> arrival_time;
SocketAddress source_address;
- rtc::Buffer& payload;
+ Buffer& payload;
};
virtual ~Socket() {}
@@ -111,10 +112,14 @@ class RTC_EXPORT Socket {
virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr) = 0;
// `timestamp` is in units of microseconds.
virtual int Recv(void* pv, size_t cb, int64_t* timestamp) = 0;
+ // TODO(webrtc:15368): Deprecate and remove.
virtual int RecvFrom(void* pv,
size_t cb,
SocketAddress* paddr,
- int64_t* timestamp) = 0;
+ int64_t* timestamp) {
+ // Not implemented. Use RecvFrom(ReceiveBuffer& buffer).
+ RTC_CHECK_NOTREACHED();
+ }
// Intended to replace RecvFrom(void* ...).
// Default implementation calls RecvFrom(void* ...) with 64Kbyte buffer.
// Returns number of bytes received or a negative value on error.
diff --git a/third_party/libwebrtc/rtc_base/socket_adapters.cc b/third_party/libwebrtc/rtc_base/socket_adapters.cc
index a1eee5bd67..f6fa182f5d 100644
--- a/third_party/libwebrtc/rtc_base/socket_adapters.cc
+++ b/third_party/libwebrtc/rtc_base/socket_adapters.cc
@@ -469,198 +469,4 @@ void AsyncHttpsProxySocket::Error(int error) {
SignalCloseEvent(this, error);
}
-///////////////////////////////////////////////////////////////////////////////
-
-AsyncSocksProxySocket::AsyncSocksProxySocket(Socket* socket,
- const SocketAddress& proxy,
- absl::string_view username,
- const CryptString& password)
- : BufferedReadAdapter(socket, 1024),
- state_(SS_ERROR),
- proxy_(proxy),
- user_(username),
- pass_(password) {}
-
-AsyncSocksProxySocket::~AsyncSocksProxySocket() = default;
-
-int AsyncSocksProxySocket::Connect(const SocketAddress& addr) {
- int ret;
- dest_ = addr;
- state_ = SS_INIT;
- BufferInput(true);
- ret = BufferedReadAdapter::Connect(proxy_);
- // TODO: Set state_ appropriately if Connect fails.
- return ret;
-}
-
-SocketAddress AsyncSocksProxySocket::GetRemoteAddress() const {
- return dest_;
-}
-
-int AsyncSocksProxySocket::Close() {
- state_ = SS_ERROR;
- dest_.Clear();
- return BufferedReadAdapter::Close();
-}
-
-Socket::ConnState AsyncSocksProxySocket::GetState() const {
- if (state_ < SS_TUNNEL) {
- return CS_CONNECTING;
- } else if (state_ == SS_TUNNEL) {
- return CS_CONNECTED;
- } else {
- return CS_CLOSED;
- }
-}
-
-void AsyncSocksProxySocket::OnConnectEvent(Socket* socket) {
- SendHello();
-}
-
-void AsyncSocksProxySocket::ProcessInput(char* data, size_t* len) {
- RTC_DCHECK(state_ < SS_TUNNEL);
-
- ByteBufferReader response(
- rtc::MakeArrayView(reinterpret_cast<uint8_t*>(data), *len));
-
- if (state_ == SS_HELLO) {
- uint8_t ver, method;
- if (!response.ReadUInt8(&ver) || !response.ReadUInt8(&method))
- return;
-
- if (ver != 5) {
- Error(0);
- return;
- }
-
- if (method == 0) {
- SendConnect();
- } else if (method == 2) {
- SendAuth();
- } else {
- Error(0);
- return;
- }
- } else if (state_ == SS_AUTH) {
- uint8_t ver, status;
- if (!response.ReadUInt8(&ver) || !response.ReadUInt8(&status))
- return;
-
- if ((ver != 1) || (status != 0)) {
- Error(SOCKET_EACCES);
- return;
- }
-
- SendConnect();
- } else if (state_ == SS_CONNECT) {
- uint8_t ver, rep, rsv, atyp;
- if (!response.ReadUInt8(&ver) || !response.ReadUInt8(&rep) ||
- !response.ReadUInt8(&rsv) || !response.ReadUInt8(&atyp))
- return;
-
- if ((ver != 5) || (rep != 0)) {
- Error(0);
- return;
- }
-
- uint16_t port;
- if (atyp == 1) {
- uint32_t addr;
- if (!response.ReadUInt32(&addr) || !response.ReadUInt16(&port))
- return;
- RTC_LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
- } else if (atyp == 3) {
- uint8_t length;
- std::string addr;
- if (!response.ReadUInt8(&length) || !response.ReadString(&addr, length) ||
- !response.ReadUInt16(&port))
- return;
- RTC_LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
- } else if (atyp == 4) {
- std::string addr;
- if (!response.ReadString(&addr, 16) || !response.ReadUInt16(&port))
- return;
- RTC_LOG(LS_VERBOSE) << "Bound on <IPV6>:" << port;
- } else {
- Error(0);
- return;
- }
-
- state_ = SS_TUNNEL;
- }
-
- // Consume parsed data
- *len = response.Length();
- memmove(data, response.Data(), *len);
-
- if (state_ != SS_TUNNEL)
- return;
-
- bool remainder = (*len > 0);
- BufferInput(false);
- SignalConnectEvent(this);
-
- // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
- if (remainder)
- SignalReadEvent(this); // TODO: signal this??
-}
-
-void AsyncSocksProxySocket::SendHello() {
- ByteBufferWriter request;
- request.WriteUInt8(5); // Socks Version
- if (user_.empty()) {
- request.WriteUInt8(1); // Authentication Mechanisms
- request.WriteUInt8(0); // No authentication
- } else {
- request.WriteUInt8(2); // Authentication Mechanisms
- request.WriteUInt8(0); // No authentication
- request.WriteUInt8(2); // Username/Password
- }
- DirectSend(request.Data(), request.Length());
- state_ = SS_HELLO;
-}
-
-void AsyncSocksProxySocket::SendAuth() {
- ByteBufferWriterT<ZeroOnFreeBuffer<char>> request;
- request.WriteUInt8(1); // Negotiation Version
- request.WriteUInt8(static_cast<uint8_t>(user_.size()));
- request.WriteString(user_); // Username
- request.WriteUInt8(static_cast<uint8_t>(pass_.GetLength()));
- size_t len = pass_.GetLength() + 1;
- char* sensitive = new char[len];
- pass_.CopyTo(sensitive, true);
- request.WriteString(std::string(sensitive, pass_.GetLength())); // Password
- ExplicitZeroMemory(sensitive, len);
- delete[] sensitive;
- DirectSend(request.Data(), request.Length());
- state_ = SS_AUTH;
-}
-
-void AsyncSocksProxySocket::SendConnect() {
- ByteBufferWriter request;
- request.WriteUInt8(5); // Socks Version
- request.WriteUInt8(1); // CONNECT
- request.WriteUInt8(0); // Reserved
- if (dest_.IsUnresolvedIP()) {
- std::string hostname = dest_.hostname();
- request.WriteUInt8(3); // DOMAINNAME
- request.WriteUInt8(static_cast<uint8_t>(hostname.size()));
- request.WriteString(hostname); // Destination Hostname
- } else {
- request.WriteUInt8(1); // IPV4
- request.WriteUInt32(dest_.ip()); // Destination IP
- }
- request.WriteUInt16(dest_.port()); // Destination Port
- DirectSend(request.Data(), request.Length());
- state_ = SS_CONNECT;
-}
-
-void AsyncSocksProxySocket::Error(int error) {
- state_ = SS_ERROR;
- BufferInput(false);
- Close();
- SetError(SOCKET_EACCES);
- SignalCloseEvent(this, error);
-}
-
} // namespace rtc
diff --git a/third_party/libwebrtc/rtc_base/socket_adapters.h b/third_party/libwebrtc/rtc_base/socket_adapters.h
index e78ee18a27..e67c8d4db9 100644
--- a/third_party/libwebrtc/rtc_base/socket_adapters.h
+++ b/third_party/libwebrtc/rtc_base/socket_adapters.h
@@ -137,42 +137,6 @@ class AsyncHttpsProxySocket : public BufferedReadAdapter {
std::string unknown_mechanisms_;
};
-///////////////////////////////////////////////////////////////////////////////
-
-// Implements a socket adapter that speaks the SOCKS proxy protocol.
-class AsyncSocksProxySocket : public BufferedReadAdapter {
- public:
- AsyncSocksProxySocket(Socket* socket,
- const SocketAddress& proxy,
- absl::string_view username,
- const CryptString& password);
- ~AsyncSocksProxySocket() override;
-
- AsyncSocksProxySocket(const AsyncSocksProxySocket&) = delete;
- AsyncSocksProxySocket& operator=(const AsyncSocksProxySocket&) = delete;
-
- int Connect(const SocketAddress& addr) override;
- SocketAddress GetRemoteAddress() const override;
- int Close() override;
- ConnState GetState() const override;
-
- protected:
- void OnConnectEvent(Socket* socket) override;
- void ProcessInput(char* data, size_t* len) override;
-
- void SendHello();
- void SendConnect();
- void SendAuth();
- void Error(int error);
-
- private:
- enum State { SS_INIT, SS_HELLO, SS_AUTH, SS_CONNECT, SS_TUNNEL, SS_ERROR };
- State state_;
- SocketAddress proxy_, dest_;
- std::string user_;
- CryptString pass_;
-};
-
} // namespace rtc
#endif // RTC_BASE_SOCKET_ADAPTERS_H_
diff --git a/third_party/libwebrtc/rtc_base/socket_unittest.cc b/third_party/libwebrtc/rtc_base/socket_unittest.cc
index f5ef2a33fc..5314128d0a 100644
--- a/third_party/libwebrtc/rtc_base/socket_unittest.cc
+++ b/third_party/libwebrtc/rtc_base/socket_unittest.cc
@@ -20,6 +20,7 @@
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
+#include "api/units/timestamp.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/async_udp_socket.h"
@@ -1092,11 +1093,11 @@ void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {
int64_t send_time_1 = TimeMicros();
socket->SendTo("foo", 3, address);
- int64_t recv_timestamp_1;
// Wait until data is available.
EXPECT_TRUE_WAIT(sink.Check(socket.get(), SSE_READ), kTimeout);
- char buffer[3];
- ASSERT_GT(socket->RecvFrom(buffer, 3, nullptr, &recv_timestamp_1), 0);
+ rtc::Buffer buffer;
+ Socket::ReceiveBuffer receive_buffer_1(buffer);
+ ASSERT_GT(socket->RecvFrom(receive_buffer_1), 0);
const int64_t kTimeBetweenPacketsMs = 100;
Thread::SleepMs(kTimeBetweenPacketsMs);
@@ -1105,11 +1106,12 @@ void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {
socket->SendTo("bar", 3, address);
// Wait until data is available.
EXPECT_TRUE_WAIT(sink.Check(socket.get(), SSE_READ), kTimeout);
- int64_t recv_timestamp_2;
- ASSERT_GT(socket->RecvFrom(buffer, 3, nullptr, &recv_timestamp_2), 0);
+ Socket::ReceiveBuffer receive_buffer_2(buffer);
+ ASSERT_GT(socket->RecvFrom(receive_buffer_2), 0);
int64_t system_time_diff = send_time_2 - send_time_1;
- int64_t recv_timestamp_diff = recv_timestamp_2 - recv_timestamp_1;
+ int64_t recv_timestamp_diff =
+ receive_buffer_2.arrival_time->us() - receive_buffer_1.arrival_time->us();
// Compare against the system time at the point of sending, because
// SleepMs may not sleep for exactly the requested time.
EXPECT_NEAR(system_time_diff, recv_timestamp_diff, 10000);
diff --git a/third_party/libwebrtc/rtc_base/system/file_wrapper_unittest.cc b/third_party/libwebrtc/rtc_base/system/file_wrapper_unittest.cc
index 980b565c73..b83c1df933 100644
--- a/third_party/libwebrtc/rtc_base/system/file_wrapper_unittest.cc
+++ b/third_party/libwebrtc/rtc_base/system/file_wrapper_unittest.cc
@@ -21,7 +21,8 @@ TEST(FileWrapper, FileSize) {
std::string test_name =
std::string(test_info->test_case_name()) + "_" + test_info->name();
std::replace(test_name.begin(), test_name.end(), '/', '_');
- const std::string temp_filename = test::OutputPath() + test_name;
+ const std::string temp_filename =
+ test::OutputPathWithRandomDirectory() + test_name;
// Write
{
diff --git a/third_party/libwebrtc/rtc_tools/network_tester/BUILD.gn b/third_party/libwebrtc/rtc_tools/network_tester/BUILD.gn
index e44681441a..da62266520 100644
--- a/third_party/libwebrtc/rtc_tools/network_tester/BUILD.gn
+++ b/third_party/libwebrtc/rtc_tools/network_tester/BUILD.gn
@@ -44,6 +44,7 @@ if (rtc_enable_protobuf) {
"../../api/task_queue:default_task_queue_factory",
"../../api/task_queue:pending_task_safety_flag",
"../../api/units:timestamp",
+ "../../p2p:basic_packet_socket_factory",
"../../p2p:rtc_p2p",
"../../rtc_base:async_packet_socket",
"../../rtc_base:checks",
diff --git a/third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/converter.cc b/third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/converter.cc
index 90d568f30f..3c72bfcfeb 100644
--- a/third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/converter.cc
+++ b/third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/converter.cc
@@ -231,12 +231,10 @@ bool Convert(std::string inputfile,
{IceCandidatePairConfigType::kNumValues, "NUM_VALUES"}};
static const std::map<IceCandidateType, std::string>
- candidate_type_name{{IceCandidateType::kUnknown, "UNKNOWN"},
- {IceCandidateType::kLocal, "LOCAL"},
- {IceCandidateType::kStun, "STUN"},
+ candidate_type_name{{IceCandidateType::kHost, "LOCAL"},
+ {IceCandidateType::kSrflx, "STUN"},
{IceCandidateType::kPrflx, "PRFLX"},
- {IceCandidateType::kRelay, "RELAY"},
- {IceCandidateType::kNumValues, "NUM_VALUES"}};
+ {IceCandidateType::kRelay, "RELAY"}};
static const std::map<IceCandidatePairProtocol, std::string>
protocol_name{{IceCandidatePairProtocol::kUnknown, "UNKNOWN"},
diff --git a/third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer.cc b/third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer.cc
index 1d8d5f12c0..0c7775e39f 100644
--- a/third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer.cc
+++ b/third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer.cc
@@ -238,7 +238,9 @@ TimeSeries CreateRtcpTypeTimeSeries(const std::vector<T>& rtcp_list,
const char kUnknownEnumValue[] = "unknown";
+// TODO(tommi): This should be "host".
const char kIceCandidateTypeLocal[] = "local";
+// TODO(tommi): This should be "srflx".
const char kIceCandidateTypeStun[] = "stun";
const char kIceCandidateTypePrflx[] = "prflx";
const char kIceCandidateTypeRelay[] = "relay";
@@ -257,17 +259,18 @@ const char kNetworkTypeWifi[] = "wifi";
const char kNetworkTypeVpn[] = "vpn";
const char kNetworkTypeCellular[] = "cellular";
-std::string GetIceCandidateTypeAsString(webrtc::IceCandidateType type) {
+absl::string_view GetIceCandidateTypeAsString(IceCandidateType type) {
switch (type) {
- case webrtc::IceCandidateType::kLocal:
+ case IceCandidateType::kHost:
return kIceCandidateTypeLocal;
- case webrtc::IceCandidateType::kStun:
+ case IceCandidateType::kSrflx:
return kIceCandidateTypeStun;
- case webrtc::IceCandidateType::kPrflx:
+ case IceCandidateType::kPrflx:
return kIceCandidateTypePrflx;
- case webrtc::IceCandidateType::kRelay:
+ case IceCandidateType::kRelay:
return kIceCandidateTypeRelay;
default:
+ RTC_DCHECK_NOTREACHED();
return kUnknownEnumValue;
}
}
@@ -323,18 +326,15 @@ std::string GetCandidatePairLogDescriptionAsString(
// and a remote relay candidate using TCP as the relay protocol on a cell
// network, when the candidate pair communicates over UDP using IPv4.
rtc::StringBuilder ss;
- std::string local_candidate_type =
- GetIceCandidateTypeAsString(config.local_candidate_type);
- std::string remote_candidate_type =
- GetIceCandidateTypeAsString(config.remote_candidate_type);
- if (config.local_candidate_type == webrtc::IceCandidateType::kRelay) {
- local_candidate_type +=
- "(" + GetProtocolAsString(config.local_relay_protocol) + ")";
- }
- ss << local_candidate_type << ":"
- << GetNetworkTypeAsString(config.local_network_type) << ":"
+ ss << GetIceCandidateTypeAsString(config.local_candidate_type);
+
+ if (config.local_candidate_type == IceCandidateType::kRelay) {
+ ss << "(" << GetProtocolAsString(config.local_relay_protocol) << ")";
+ }
+
+ ss << ":" << GetNetworkTypeAsString(config.local_network_type) << ":"
<< GetAddressFamilyAsString(config.local_address_family) << "->"
- << remote_candidate_type << ":"
+ << GetIceCandidateTypeAsString(config.remote_candidate_type) << ":"
<< GetAddressFamilyAsString(config.remote_address_family) << "@"
<< GetProtocolAsString(config.candidate_pair_protocol);
return ss.Release();
diff --git a/third_party/libwebrtc/sdk/BUILD.gn b/third_party/libwebrtc/sdk/BUILD.gn
index 586d4d1911..e973448f05 100644
--- a/third_party/libwebrtc/sdk/BUILD.gn
+++ b/third_party/libwebrtc/sdk/BUILD.gn
@@ -996,6 +996,12 @@ if (is_ios || is_mac) {
"objc/api/peerconnection/RTCRtcpParameters+Private.h",
"objc/api/peerconnection/RTCRtcpParameters.h",
"objc/api/peerconnection/RTCRtcpParameters.mm",
+ "objc/api/peerconnection/RTCRtpCapabilities+Private.h",
+ "objc/api/peerconnection/RTCRtpCapabilities.h",
+ "objc/api/peerconnection/RTCRtpCapabilities.mm",
+ "objc/api/peerconnection/RTCRtpCodecCapability+Private.h",
+ "objc/api/peerconnection/RTCRtpCodecCapability.h",
+ "objc/api/peerconnection/RTCRtpCodecCapability.mm",
"objc/api/peerconnection/RTCRtpCodecParameters+Private.h",
"objc/api/peerconnection/RTCRtpCodecParameters.h",
"objc/api/peerconnection/RTCRtpCodecParameters.mm",
@@ -1005,6 +1011,9 @@ if (is_ios || is_mac) {
"objc/api/peerconnection/RTCRtpHeaderExtension+Private.h",
"objc/api/peerconnection/RTCRtpHeaderExtension.h",
"objc/api/peerconnection/RTCRtpHeaderExtension.mm",
+ "objc/api/peerconnection/RTCRtpHeaderExtensionCapability+Private.h",
+ "objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h",
+ "objc/api/peerconnection/RTCRtpHeaderExtensionCapability.mm",
"objc/api/peerconnection/RTCRtpParameters+Private.h",
"objc/api/peerconnection/RTCRtpParameters.h",
"objc/api/peerconnection/RTCRtpParameters.mm",
@@ -1314,9 +1323,12 @@ if (is_ios || is_mac) {
"objc/api/peerconnection/RTCPeerConnectionFactory.h",
"objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h",
"objc/api/peerconnection/RTCRtcpParameters.h",
+ "objc/api/peerconnection/RTCRtpCapabilities.h",
+ "objc/api/peerconnection/RTCRtpCodecCapability.h",
"objc/api/peerconnection/RTCRtpCodecParameters.h",
"objc/api/peerconnection/RTCRtpEncodingParameters.h",
"objc/api/peerconnection/RTCRtpHeaderExtension.h",
+ "objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h",
"objc/api/peerconnection/RTCRtpParameters.h",
"objc/api/peerconnection/RTCRtpReceiver.h",
"objc/api/peerconnection/RTCRtpSender.h",
@@ -1428,9 +1440,12 @@ if (is_ios || is_mac) {
"objc/api/peerconnection/RTCPeerConnectionFactory.h",
"objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h",
"objc/api/peerconnection/RTCRtcpParameters.h",
+ "objc/api/peerconnection/RTCRtpCapabilities.h",
+ "objc/api/peerconnection/RTCRtpCodecCapability.h",
"objc/api/peerconnection/RTCRtpCodecParameters.h",
"objc/api/peerconnection/RTCRtpEncodingParameters.h",
"objc/api/peerconnection/RTCRtpHeaderExtension.h",
+ "objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h",
"objc/api/peerconnection/RTCRtpParameters.h",
"objc/api/peerconnection/RTCRtpReceiver.h",
"objc/api/peerconnection/RTCRtpSender.h",
diff --git a/third_party/libwebrtc/sdk/android/api/org/webrtc/Dav1dDecoder.java b/third_party/libwebrtc/sdk/android/api/org/webrtc/Dav1dDecoder.java
index ecb16bc3a1..2a79988470 100644
--- a/third_party/libwebrtc/sdk/android/api/org/webrtc/Dav1dDecoder.java
+++ b/third_party/libwebrtc/sdk/android/api/org/webrtc/Dav1dDecoder.java
@@ -12,7 +12,7 @@ package org.webrtc;
public class Dav1dDecoder extends WrappedNativeVideoDecoder {
@Override
- public long createNativeVideoDecoder() {
+ public long createNative(long webrtcEnvRef) {
return nativeCreateDecoder();
}
diff --git a/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp8Decoder.java b/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp8Decoder.java
index 54ad0aa137..7d3e95973d 100644
--- a/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp8Decoder.java
+++ b/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp8Decoder.java
@@ -12,9 +12,9 @@ package org.webrtc;
public class LibvpxVp8Decoder extends WrappedNativeVideoDecoder {
@Override
- public long createNativeVideoDecoder() {
- return nativeCreateDecoder();
+ public long createNative(long webrtcEnvRef) {
+ return nativeCreateDecoder(webrtcEnvRef);
}
- static native long nativeCreateDecoder();
+ static native long nativeCreateDecoder(long webrtcEnvRef);
}
diff --git a/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp9Decoder.java b/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp9Decoder.java
index 90a24433a3..34718cfa8c 100644
--- a/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp9Decoder.java
+++ b/third_party/libwebrtc/sdk/android/api/org/webrtc/LibvpxVp9Decoder.java
@@ -12,7 +12,7 @@ package org.webrtc;
public class LibvpxVp9Decoder extends WrappedNativeVideoDecoder {
@Override
- public long createNativeVideoDecoder() {
+ public long createNative(long webrtcEnvRef) {
return nativeCreateDecoder();
}
diff --git a/third_party/libwebrtc/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java b/third_party/libwebrtc/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java
index 2ac42e834e..1b1cd44a92 100644
--- a/third_party/libwebrtc/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java
+++ b/third_party/libwebrtc/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java
@@ -11,7 +11,6 @@
package org.webrtc;
import androidx.annotation.Nullable;
-import java.util.Arrays;
import java.util.List;
public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
@@ -26,16 +25,14 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
@Nullable
@Override
public VideoDecoder createDecoder(VideoCodecInfo info) {
- long nativeDecoder = nativeCreateDecoder(nativeFactory, info);
- if (nativeDecoder == 0) {
+ if (!nativeIsSupported(nativeFactory, info)) {
Logging.w(TAG, "Trying to create decoder for unsupported format. " + info);
return null;
}
-
return new WrappedNativeVideoDecoder() {
@Override
- public long createNativeVideoDecoder() {
- return nativeDecoder;
+ public long createNative(long webrtcEnvRef) {
+ return nativeCreate(nativeFactory, webrtcEnvRef, info);
}
};
}
@@ -47,7 +44,10 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
private static native long nativeCreateFactory();
- private static native long nativeCreateDecoder(long factory, VideoCodecInfo videoCodecInfo);
+ private static native boolean nativeIsSupported(long factory, VideoCodecInfo info);
+
+ private static native long nativeCreate(
+ long factory, long webrtcEnvRef, VideoCodecInfo info);
private static native List<VideoCodecInfo> nativeGetSupportedCodecs(long factory);
}
diff --git a/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoder.java b/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoder.java
index a80fa4fef2..195daf5260 100644
--- a/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoder.java
+++ b/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoder.java
@@ -56,11 +56,11 @@ public interface VideoDecoder {
* decoder (e.g., an Android platform decoder), or alternatively 2) a native
* decoder (e.g., a software decoder or a C++ decoder adapter).
*
- * For case 1), createNativeVideoDecoder() should return zero.
+ * For case 1), createNative() should return zero.
* In this case, we expect the native library to call the decoder through
* JNI using the Java interface declared below.
*
- * For case 2), createNativeVideoDecoder() should return a non-zero value.
+ * For case 2), createNative() should return a non-zero value.
* In this case, we expect the native library to treat the returned value as
* a raw pointer of type webrtc::VideoDecoder* (ownership is transferred to
* the caller). The native library should then directly call the
@@ -69,7 +69,7 @@ public interface VideoDecoder {
* UnsupportedOperationException.
*/
@CalledByNative
- default long createNativeVideoDecoder() {
+ default long createNative(long webrtcEnvRef) {
return 0;
}
diff --git a/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoderFallback.java b/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoderFallback.java
index ddfa3ecd40..1e7bae9b27 100644
--- a/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoderFallback.java
+++ b/third_party/libwebrtc/sdk/android/api/org/webrtc/VideoDecoderFallback.java
@@ -23,9 +23,10 @@ public class VideoDecoderFallback extends WrappedNativeVideoDecoder {
}
@Override
- public long createNativeVideoDecoder() {
- return nativeCreateDecoder(fallback, primary);
+ public long createNative(long webrtcEnvRef) {
+ return nativeCreate(webrtcEnvRef, fallback, primary);
}
- private static native long nativeCreateDecoder(VideoDecoder fallback, VideoDecoder primary);
+ private static native long nativeCreate(
+ long webrtcEnvRef, VideoDecoder fallback, VideoDecoder primary);
}
diff --git a/third_party/libwebrtc/sdk/android/api/org/webrtc/WrappedNativeVideoDecoder.java b/third_party/libwebrtc/sdk/android/api/org/webrtc/WrappedNativeVideoDecoder.java
index 027120e48e..d762e757e4 100644
--- a/third_party/libwebrtc/sdk/android/api/org/webrtc/WrappedNativeVideoDecoder.java
+++ b/third_party/libwebrtc/sdk/android/api/org/webrtc/WrappedNativeVideoDecoder.java
@@ -14,7 +14,7 @@ package org.webrtc;
* Wraps a native webrtc::VideoDecoder.
*/
public abstract class WrappedNativeVideoDecoder implements VideoDecoder {
- @Override public abstract long createNativeVideoDecoder();
+ @Override public abstract long createNative(long webrtcEnvRef);
@Override
public final VideoCodecStatus initDecode(Settings settings, Callback decodeCallback) {
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h
index 5575af98c9..17777f6d5d 100644
--- a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h
@@ -14,6 +14,7 @@
NS_ASSUME_NONNULL_BEGIN
+@class RTC_OBJC_TYPE(RTCRtpCapabilities);
@class RTC_OBJC_TYPE(RTCAudioSource);
@class RTC_OBJC_TYPE(RTCAudioTrack);
@class RTC_OBJC_TYPE(RTCConfiguration);
@@ -51,6 +52,18 @@ RTC_OBJC_EXPORT
decoderFactory:(nullable id<RTC_OBJC_TYPE(RTCVideoDecoderFactory)>)decoderFactory
audioDevice:(nullable id<RTC_OBJC_TYPE(RTCAudioDevice)>)audioDevice;
+/**
+ * Valid kind values are kRTCMediaStreamTrackKindAudio and
+ * kRTCMediaStreamTrackKindVideo.
+ */
+- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpSenderCapabilitiesForKind:(NSString *)kind;
+
+/**
+ * Valid kind values are kRTCMediaStreamTrackKindAudio and
+ * kRTCMediaStreamTrackKindVideo.
+ */
+- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpReceiverCapabilitiesForKind:(NSString *)kind;
+
/** Initialize an RTCAudioSource with constraints. */
- (RTC_OBJC_TYPE(RTCAudioSource) *)audioSourceWithConstraints:
(nullable RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints;
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm
index 445006f0d0..64be41ae15 100644
--- a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm
@@ -13,6 +13,7 @@
#import "RTCPeerConnectionFactory+Native.h"
#import "RTCPeerConnectionFactory+Private.h"
#import "RTCPeerConnectionFactoryOptions+Private.h"
+#import "RTCRtpCapabilities+Private.h"
#import "RTCAudioSource+Private.h"
#import "RTCAudioTrack+Private.h"
@@ -38,6 +39,7 @@
#include "api/transport/field_trial_based_config.h"
#import "components/video_codec/RTCVideoDecoderFactoryH264.h"
#import "components/video_codec/RTCVideoEncoderFactoryH264.h"
+#include "media/base/media_constants.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/audio_processing/include/audio_processing.h"
@@ -214,6 +216,20 @@
return self;
}
+- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpSenderCapabilitiesForKind:(NSString *)kind {
+ cricket::MediaType mediaType = [[self class] mediaTypeForKind:kind];
+
+ webrtc::RtpCapabilities rtpCapabilities = _nativeFactory->GetRtpSenderCapabilities(mediaType);
+ return [[RTC_OBJC_TYPE(RTCRtpCapabilities) alloc] initWithNativeRtpCapabilities:rtpCapabilities];
+}
+
+- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpReceiverCapabilitiesForKind:(NSString *)kind {
+ cricket::MediaType mediaType = [[self class] mediaTypeForKind:kind];
+
+ webrtc::RtpCapabilities rtpCapabilities = _nativeFactory->GetRtpReceiverCapabilities(mediaType);
+ return [[RTC_OBJC_TYPE(RTCRtpCapabilities) alloc] initWithNativeRtpCapabilities:rtpCapabilities];
+}
+
- (RTC_OBJC_TYPE(RTCAudioSource) *)audioSourceWithConstraints:
(nullable RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints {
std::unique_ptr<webrtc::MediaConstraints> nativeConstraints;
@@ -338,4 +354,17 @@
return _networkThread.get();
}
+#pragma mark - Private
+
++ (cricket::MediaType)mediaTypeForKind:(NSString *)kind {
+ if (kind == kRTCMediaStreamTrackKindAudio) {
+ return cricket::MEDIA_TYPE_AUDIO;
+ } else if (kind == kRTCMediaStreamTrackKindVideo) {
+ return cricket::MEDIA_TYPE_VIDEO;
+ } else {
+ RTC_DCHECK_NOTREACHED();
+ return cricket::MEDIA_TYPE_UNSUPPORTED;
+ }
+}
+
@end
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h
new file mode 100644
index 0000000000..be51993f2f
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import "RTCRtpCapabilities.h"
+
+#include "api/rtp_parameters.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RTC_OBJC_TYPE (RTCRtpCapabilities)()
+
+/**
+ * The native RtpCapabilities representation of this RTCRtpCapabilities
+ * object. This is needed to pass to the underlying C++ APIs.
+ */
+@property(nonatomic, readonly) webrtc::RtpCapabilities nativeRtpCapabilities;
+
+/**
+ * Initialize an RTCRtpCapabilities from a native RtpCapabilities.
+ */
+- (instancetype)initWithNativeRtpCapabilities:(const webrtc::RtpCapabilities &)rtpCapabilities;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.h
new file mode 100644
index 0000000000..7e898b5a80
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "RTCMacros.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class RTC_OBJC_TYPE(RTCRtpCodecCapability);
+@class RTC_OBJC_TYPE(RTCRtpHeaderExtensionCapability);
+
+RTC_OBJC_EXPORT
+@interface RTC_OBJC_TYPE (RTCRtpCapabilities) : NSObject
+
+@property(nonatomic, copy) NSArray<RTC_OBJC_TYPE(RTCRtpCodecCapability) *> *codecs;
+@property(nonatomic, copy)
+ NSArray<RTC_OBJC_TYPE(RTCRtpHeaderExtensionCapability) *> *headerExtensions;
+
+- (instancetype)init;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.mm b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.mm
new file mode 100644
index 0000000000..85537a91ad
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCapabilities.mm
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import "RTCRtpCapabilities+Private.h"
+
+#import "RTCRtpCodecCapability+Private.h"
+#import "RTCRtpHeaderExtensionCapability+Private.h"
+
+#import "base/RTCLogging.h"
+#import "helpers/NSString+StdString.h"
+
+@implementation RTC_OBJC_TYPE (RTCRtpCapabilities)
+
+@synthesize codecs = _codecs;
+@synthesize headerExtensions = _headerExtensions;
+
+- (instancetype)init {
+ webrtc::RtpCapabilities nativeRtpCapabilities;
+ return [self initWithNativeRtpCapabilities:nativeRtpCapabilities];
+}
+
+- (instancetype)initWithNativeRtpCapabilities:
+ (const webrtc::RtpCapabilities &)nativeRtpCapabilities {
+ if (self = [super init]) {
+ NSMutableArray *codecs = [[NSMutableArray alloc] init];
+ for (const auto &codec : nativeRtpCapabilities.codecs) {
+ [codecs addObject:[[RTC_OBJC_TYPE(RTCRtpCodecCapability) alloc]
+ initWithNativeRtpCodecCapability:codec]];
+ }
+ _codecs = codecs;
+
+ NSMutableArray *headerExtensions = [[NSMutableArray alloc] init];
+ for (const auto &headerExtension : nativeRtpCapabilities.header_extensions) {
+ [headerExtensions addObject:[[RTC_OBJC_TYPE(RTCRtpHeaderExtensionCapability) alloc]
+ initWithNativeRtpHeaderExtensionCapability:headerExtension]];
+ }
+ _headerExtensions = headerExtensions;
+ }
+ return self;
+}
+
+- (webrtc::RtpCapabilities)nativeRtpCapabilities {
+ webrtc::RtpCapabilities rtpCapabilities;
+ for (RTC_OBJC_TYPE(RTCRtpCodecCapability) * codec in _codecs) {
+ rtpCapabilities.codecs.push_back(codec.nativeRtpCodecCapability);
+ }
+ for (RTC_OBJC_TYPE(RTCRtpHeaderExtensionCapability) * headerExtension in _headerExtensions) {
+ rtpCapabilities.header_extensions.push_back(headerExtension.nativeRtpHeaderExtensionCapability);
+ }
+ return rtpCapabilities;
+}
+
+@end
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h
new file mode 100644
index 0000000000..6af13b3b23
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import "RTCRtpCodecCapability.h"
+
+#include "api/rtp_parameters.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RTC_OBJC_TYPE (RTCRtpCodecCapability)()
+
+/**
+ * The native RtpCodecCapability representation of this RTCRtpCodecCapability
+ * object. This is needed to pass to the underlying C++ APIs.
+ */
+@property(nonatomic, readonly) webrtc::RtpCodecCapability nativeRtpCodecCapability;
+
+/**
+ * Initialize an RTCRtpCodecCapability from a native RtpCodecCapability.
+ */
+- (instancetype)initWithNativeRtpCodecCapability:
+ (const webrtc::RtpCodecCapability &)nativeRtpCodecCapability;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.h
new file mode 100644
index 0000000000..5604148e5d
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "RTCMacros.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+RTC_OBJC_EXPORT
+@interface RTC_OBJC_TYPE (RTCRtpCodecCapability) : NSObject
+
+/** The preferred RTP payload type. */
+@property(nonatomic, readonly, nullable) NSNumber *preferredPayloadType;
+
+/**
+ * The codec MIME subtype. Valid types are listed in:
+ * http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-2
+ *
+ * Several supported types are represented by the constants above.
+ */
+@property(nonatomic, readonly) NSString *name;
+
+/**
+ * The media type of this codec. Equivalent to MIME top-level type.
+ *
+ * Valid values are kRTCMediaStreamTrackKindAudio and
+ * kRTCMediaStreamTrackKindVideo.
+ */
+@property(nonatomic, readonly) NSString *kind;
+
+/** The codec clock rate expressed in Hertz. */
+@property(nonatomic, readonly, nullable) NSNumber *clockRate;
+
+/**
+ * The number of audio channels (mono=1, stereo=2).
+ * Set to null for video codecs.
+ **/
+@property(nonatomic, readonly, nullable) NSNumber *numChannels;
+
+/** The "format specific parameters" field from the "a=fmtp" line in the SDP */
+@property(nonatomic, readonly) NSDictionary<NSString *, NSString *> *parameters;
+
+/** The MIME type of the codec. */
+@property(nonatomic, readonly) NSString *mimeType;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm
new file mode 100644
index 0000000000..2dc1e5dc4b
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import "RTCRtpCodecCapability+Private.h"
+
+#import "RTCMediaStreamTrack.h"
+#import "helpers/NSString+StdString.h"
+
+#include "media/base/media_constants.h"
+#include "rtc_base/checks.h"
+
+@implementation RTC_OBJC_TYPE (RTCRtpCodecCapability)
+
+@synthesize preferredPayloadType = _preferredPayloadType;
+@synthesize name = _name;
+@synthesize kind = _kind;
+@synthesize clockRate = _clockRate;
+@synthesize numChannels = _numChannels;
+@synthesize parameters = _parameters;
+@synthesize mimeType = _mimeType;
+
+- (instancetype)init {
+ webrtc::RtpCodecCapability rtpCodecCapability;
+ return [self initWithNativeRtpCodecCapability:rtpCodecCapability];
+}
+
+- (instancetype)initWithNativeRtpCodecCapability:
+ (const webrtc::RtpCodecCapability &)nativeRtpCodecCapability {
+ if (self = [super init]) {
+ if (nativeRtpCodecCapability.preferred_payload_type) {
+ _preferredPayloadType =
+ [NSNumber numberWithInt:*nativeRtpCodecCapability.preferred_payload_type];
+ }
+ _name = [NSString stringForStdString:nativeRtpCodecCapability.name];
+ switch (nativeRtpCodecCapability.kind) {
+ case cricket::MEDIA_TYPE_AUDIO:
+ _kind = kRTCMediaStreamTrackKindAudio;
+ break;
+ case cricket::MEDIA_TYPE_VIDEO:
+ _kind = kRTCMediaStreamTrackKindVideo;
+ break;
+ case cricket::MEDIA_TYPE_DATA:
+ RTC_DCHECK_NOTREACHED();
+ break;
+ case cricket::MEDIA_TYPE_UNSUPPORTED:
+ RTC_DCHECK_NOTREACHED();
+ break;
+ }
+ if (nativeRtpCodecCapability.clock_rate) {
+ _clockRate = [NSNumber numberWithInt:*nativeRtpCodecCapability.clock_rate];
+ }
+ if (nativeRtpCodecCapability.num_channels) {
+ _numChannels = [NSNumber numberWithInt:*nativeRtpCodecCapability.num_channels];
+ }
+ NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
+ for (const auto &parameter : nativeRtpCodecCapability.parameters) {
+ [parameters setObject:[NSString stringForStdString:parameter.second]
+ forKey:[NSString stringForStdString:parameter.first]];
+ }
+ _parameters = parameters;
+ _mimeType = [NSString stringForStdString:nativeRtpCodecCapability.mime_type()];
+ }
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"RTC_OBJC_TYPE(RTCRtpCodecCapability) {\n "
+ @"preferredPayloadType: %@\n name: %@\n kind: %@\n "
+ @"clockRate: %@\n numChannels: %@\n parameters: %@\n "
+ @"mimeType: %@\n}",
+ _preferredPayloadType,
+ _name,
+ _kind,
+ _clockRate,
+ _numChannels,
+ _parameters,
+ _mimeType];
+}
+
+- (webrtc::RtpCodecCapability)nativeRtpCodecCapability {
+ webrtc::RtpCodecCapability rtpCodecCapability;
+ if (_preferredPayloadType != nil) {
+ rtpCodecCapability.preferred_payload_type = absl::optional<int>(_preferredPayloadType.intValue);
+ }
+ rtpCodecCapability.name = [NSString stdStringForString:_name];
+ // NSString pointer comparison is safe here since "kind" is readonly and only
+ // populated above.
+ if (_kind == kRTCMediaStreamTrackKindAudio) {
+ rtpCodecCapability.kind = cricket::MEDIA_TYPE_AUDIO;
+ } else if (_kind == kRTCMediaStreamTrackKindVideo) {
+ rtpCodecCapability.kind = cricket::MEDIA_TYPE_VIDEO;
+ } else {
+ RTC_DCHECK_NOTREACHED();
+ }
+ if (_clockRate != nil) {
+ rtpCodecCapability.clock_rate = absl::optional<int>(_clockRate.intValue);
+ }
+ if (_numChannels != nil) {
+ rtpCodecCapability.num_channels = absl::optional<int>(_numChannels.intValue);
+ }
+ for (NSString *paramKey in _parameters.allKeys) {
+ std::string key = [NSString stdStringForString:paramKey];
+ std::string value = [NSString stdStringForString:_parameters[paramKey]];
+ rtpCodecCapability.parameters[key] = value;
+ }
+ return rtpCodecCapability;
+}
+
+@end
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability+Private.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability+Private.h
new file mode 100644
index 0000000000..4e800bc996
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability+Private.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import "RTCRtpHeaderExtensionCapability.h"
+
+#include "api/rtp_parameters.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RTC_OBJC_TYPE (RTCRtpHeaderExtensionCapability)()
+
+/**
+* The native RtpHeaderExtensionCapability representation of this
+* RTCRtpHeaderExtensionCapability object. This is needed to pass to the underlying C++ APIs.
+*/
+@property(nonatomic,
+ readonly) webrtc::RtpHeaderExtensionCapability nativeRtpHeaderExtensionCapability;
+
+/**
+ * Initialize an RTCRtpHeaderExtensionCapability from a native RtpHeaderExtensionCapability.
+ */
+- (instancetype)initWithNativeRtpHeaderExtensionCapability:
+ (const webrtc::RtpHeaderExtensionCapability &)rtpHeaderExtensionCapability;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h
new file mode 100644
index 0000000000..7a5d442e6a
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "RTCMacros.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+RTC_OBJC_EXPORT
+@interface RTC_OBJC_TYPE (RTCRtpHeaderExtensionCapability) : NSObject
+
+/** The URI of the RTP header extension, as defined in RFC5285. */
+@property(nonatomic, readonly, copy) NSString *uri;
+
+/** The value put in the RTP packet to identify the header extension. */
+@property(nonatomic, readonly, nullable) NSNumber* preferredId;
+
+/** Whether the header extension is encrypted or not. */
+@property(nonatomic, readonly, getter=isPreferredEncrypted) BOOL preferredEncrypted;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.mm b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.mm
new file mode 100644
index 0000000000..c9af744a92
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpHeaderExtensionCapability.mm
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import "RTCRtpHeaderExtensionCapability+Private.h"
+
+#import "helpers/NSString+StdString.h"
+
+@implementation RTC_OBJC_TYPE (RTCRtpHeaderExtensionCapability)
+
+@synthesize uri = _uri;
+@synthesize preferredId = _preferredId;
+@synthesize preferredEncrypted = _preferredEncrypted;
+
+- (instancetype)init {
+ webrtc::RtpHeaderExtensionCapability nativeRtpHeaderExtensionCapability;
+ return [self initWithNativeRtpHeaderExtensionCapability:nativeRtpHeaderExtensionCapability];
+}
+
+- (instancetype)initWithNativeRtpHeaderExtensionCapability:
+ (const webrtc::RtpHeaderExtensionCapability &)nativeRtpHeaderExtensionCapability {
+ if (self = [super init]) {
+ _uri = [NSString stringForStdString:nativeRtpHeaderExtensionCapability.uri];
+ if (nativeRtpHeaderExtensionCapability.preferred_id) {
+ _preferredId = [NSNumber numberWithInt:*nativeRtpHeaderExtensionCapability.preferred_id];
+ }
+ _preferredEncrypted = nativeRtpHeaderExtensionCapability.preferred_encrypt;
+ }
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"RTC_OBJC_TYPE(RTCRtpHeaderExtensionCapability) {\n uri: "
+ @"%@\n preferredId: %@\n preferredEncrypted: %d\n}",
+ _uri,
+ _preferredId,
+ _preferredEncrypted];
+}
+
+- (webrtc::RtpHeaderExtensionCapability)nativeRtpHeaderExtensionCapability {
+ webrtc::RtpHeaderExtensionCapability rtpHeaderExtensionCapability;
+ rtpHeaderExtensionCapability.uri = [NSString stdStringForString:_uri];
+ if (_preferredId != nil) {
+ rtpHeaderExtensionCapability.preferred_id = absl::optional<int>(_preferredId.intValue);
+ }
+ rtpHeaderExtensionCapability.preferred_encrypt = _preferredEncrypted;
+ return rtpHeaderExtensionCapability;
+}
+
+@end
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.h b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.h
index fd59013639..1701f680a4 100644
--- a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.h
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.h
@@ -46,6 +46,7 @@ RTC_OBJC_EXPORT
@end
@class RTC_OBJC_TYPE(RTCRtpTransceiver);
+@class RTC_OBJC_TYPE(RTCRtpCodecCapability);
/** The RTCRtpTransceiver maps to the RTCRtpTransceiver defined by the
* WebRTC specification. A transceiver represents a combination of an RTCRtpSender
@@ -118,6 +119,12 @@ RTC_OBJC_EXPORT
*/
- (void)stopInternal;
+/** The setCodecPreferences method overrides the default codec preferences used
+ * by WebRTC for this transceiver.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-setcodecpreferences
+ */
+- (void)setCodecPreferences:(NSArray<RTC_OBJC_TYPE(RTCRtpCodecCapability) *> *)codecs;
+
/** An update of directionality does not take effect immediately. Instead,
* future calls to createOffer and createAnswer mark the corresponding media
* descriptions as sendrecv, sendonly, recvonly, or inactive.
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm
index ae1cf79864..eb0ad96738 100644
--- a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm
+++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm
@@ -10,6 +10,7 @@
#import "RTCRtpTransceiver+Private.h"
+#import "RTCRtpCodecCapability+Private.h"
#import "RTCRtpEncodingParameters+Private.h"
#import "RTCRtpParameters+Private.h"
#import "RTCRtpReceiver+Private.h"
@@ -17,6 +18,8 @@
#import "base/RTCLogging.h"
#import "helpers/NSString+StdString.h"
+#include "api/rtp_parameters.h"
+
NSString *const kRTCRtpTransceiverErrorDomain = @"org.webrtc.RTCRtpTranceiver";
@implementation RTC_OBJC_TYPE (RTCRtpTransceiverInit)
@@ -105,6 +108,14 @@ NSString *const kRTCRtpTransceiverErrorDomain = @"org.webrtc.RTCRtpTranceiver";
_nativeRtpTransceiver->StopInternal();
}
+- (void)setCodecPreferences:(NSArray<RTC_OBJC_TYPE(RTCRtpCodecCapability) *> *)codecs {
+ std::vector<webrtc::RtpCodecCapability> codecCapabilities;
+ for (RTC_OBJC_TYPE(RTCRtpCodecCapability) * rtpCodecCapability in codecs) {
+ codecCapabilities.push_back(rtpCodecCapability.nativeRtpCodecCapability);
+ }
+ _nativeRtpTransceiver->SetCodecPreferences(codecCapabilities);
+}
+
- (NSString *)description {
return [NSString
stringWithFormat:@"RTC_OBJC_TYPE(RTCRtpTransceiver) {\n sender: %@\n receiver: %@\n}",
diff --git a/third_party/libwebrtc/sdk/objc/unittests/RTCPeerConnectionFactory_xctest.m b/third_party/libwebrtc/sdk/objc/unittests/RTCPeerConnectionFactory_xctest.m
index 56c74971b6..7d42b6bdbb 100644
--- a/third_party/libwebrtc/sdk/objc/unittests/RTCPeerConnectionFactory_xctest.m
+++ b/third_party/libwebrtc/sdk/objc/unittests/RTCPeerConnectionFactory_xctest.m
@@ -8,6 +8,9 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#import "base/RTCVideoDecoderFactory.h"
+#import "base/RTCVideoEncoderFactory.h"
+
#import "api/peerconnection/RTCAudioSource.h"
#import "api/peerconnection/RTCConfiguration.h"
#import "api/peerconnection/RTCDataChannel.h"
@@ -16,6 +19,8 @@
#import "api/peerconnection/RTCMediaStreamTrack.h"
#import "api/peerconnection/RTCPeerConnection.h"
#import "api/peerconnection/RTCPeerConnectionFactory.h"
+#import "api/peerconnection/RTCRtpCapabilities.h"
+#import "api/peerconnection/RTCRtpCodecCapability.h"
#import "api/peerconnection/RTCRtpReceiver.h"
#import "api/peerconnection/RTCRtpSender.h"
#import "api/peerconnection/RTCRtpTransceiver.h"
@@ -25,6 +30,40 @@
#import <XCTest/XCTest.h>
+@interface MockVideoEncoderDecoderFactory
+ : NSObject <RTC_OBJC_TYPE (RTCVideoEncoderFactory), RTC_OBJC_TYPE (RTCVideoDecoderFactory)>
+- (instancetype)initWithSupportedCodecs:
+ (nonnull NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)supportedCodecs;
+@end
+
+@implementation MockVideoEncoderDecoderFactory {
+ NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *_supportedCodecs;
+}
+
+- (instancetype)initWithSupportedCodecs:
+ (nonnull NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)supportedCodecs {
+ if (self = [super init]) {
+ _supportedCodecs = supportedCodecs;
+ }
+ return self;
+}
+
+- (nullable id<RTC_OBJC_TYPE(RTCVideoEncoder)>)createEncoder:
+ (nonnull RTC_OBJC_TYPE(RTCVideoCodecInfo) *)info {
+ return nil;
+}
+
+- (nullable id<RTC_OBJC_TYPE(RTCVideoDecoder)>)createDecoder:
+ (nonnull RTC_OBJC_TYPE(RTCVideoCodecInfo) *)info {
+ return nil;
+}
+
+- (nonnull NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)supportedCodecs {
+ return _supportedCodecs;
+}
+
+@end
+
@interface RTCPeerConnectionFactoryTests : XCTestCase
@end
@@ -325,6 +364,148 @@
}
}
+- (void)testSenderCapabilities {
+ @autoreleasepool {
+ RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory;
+ MockVideoEncoderDecoderFactory *encoder;
+ MockVideoEncoderDecoderFactory *decoder;
+
+ NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *supportedCodecs = @[
+ [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithName:@"VP8"],
+ [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithName:@"H264"]
+ ];
+
+ encoder = [[MockVideoEncoderDecoderFactory alloc] initWithSupportedCodecs:supportedCodecs];
+ decoder = [[MockVideoEncoderDecoderFactory alloc] initWithSupportedCodecs:supportedCodecs];
+ factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] initWithEncoderFactory:encoder
+ decoderFactory:decoder];
+
+ RTC_OBJC_TYPE(RTCRtpCapabilities) *capabilities =
+ [factory rtpSenderCapabilitiesForKind:kRTCMediaStreamTrackKindVideo];
+ NSMutableArray<NSString *> *codecNames = [NSMutableArray new];
+ for (RTC_OBJC_TYPE(RTCRtpCodecCapability) * codec in capabilities.codecs) {
+ [codecNames addObject:codec.name];
+ }
+
+ XCTAssertTrue([codecNames containsObject:@"VP8"]);
+ XCTAssertTrue([codecNames containsObject:@"H264"]);
+ factory = nil;
+ }
+}
+
+- (void)testReceiverCapabilities {
+ @autoreleasepool {
+ RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory;
+ MockVideoEncoderDecoderFactory *encoder;
+ MockVideoEncoderDecoderFactory *decoder;
+
+ NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *supportedCodecs = @[
+ [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithName:@"VP8"],
+ [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithName:@"H264"]
+ ];
+
+ encoder = [[MockVideoEncoderDecoderFactory alloc] initWithSupportedCodecs:supportedCodecs];
+ decoder = [[MockVideoEncoderDecoderFactory alloc] initWithSupportedCodecs:supportedCodecs];
+ factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] initWithEncoderFactory:encoder
+ decoderFactory:decoder];
+
+ RTC_OBJC_TYPE(RTCRtpCapabilities) *capabilities =
+ [factory rtpReceiverCapabilitiesForKind:kRTCMediaStreamTrackKindVideo];
+ NSMutableArray<NSString *> *codecNames = [NSMutableArray new];
+ for (RTC_OBJC_TYPE(RTCRtpCodecCapability) * codec in capabilities.codecs) {
+ [codecNames addObject:codec.name];
+ }
+
+ XCTAssertTrue([codecNames containsObject:@"VP8"]);
+ XCTAssertTrue([codecNames containsObject:@"H264"]);
+ factory = nil;
+ }
+}
+
+- (void)testSetCodecPreferences {
+ @autoreleasepool {
+ RTC_OBJC_TYPE(RTCConfiguration) *config = [[RTC_OBJC_TYPE(RTCConfiguration) alloc] init];
+ RTC_OBJC_TYPE(RTCMediaConstraints) *constraints =
+ [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:nil
+ optionalConstraints:nil];
+ RTC_OBJC_TYPE(RTCRtpTransceiverInit) *init =
+ [[RTC_OBJC_TYPE(RTCRtpTransceiverInit) alloc] init];
+
+ NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *supportedCodecs = @[
+ [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithName:@"VP8"],
+ [[RTC_OBJC_TYPE(RTCVideoCodecInfo) alloc] initWithName:@"H264"]
+ ];
+
+ MockVideoEncoderDecoderFactory *encoder =
+ [[MockVideoEncoderDecoderFactory alloc] initWithSupportedCodecs:supportedCodecs];
+ MockVideoEncoderDecoderFactory *decoder =
+ [[MockVideoEncoderDecoderFactory alloc] initWithSupportedCodecs:supportedCodecs];
+
+ RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory;
+ RTC_OBJC_TYPE(RTCPeerConnection) * peerConnection;
+ RTC_OBJC_TYPE(RTCRtpTransceiver) * tranceiver;
+ factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] initWithEncoderFactory:encoder
+ decoderFactory:decoder];
+
+ peerConnection = [factory peerConnectionWithConfiguration:config
+ constraints:constraints
+ delegate:nil];
+ tranceiver = [peerConnection addTransceiverOfType:RTCRtpMediaTypeVideo init:init];
+ XCTAssertNotNil(tranceiver);
+
+ RTC_OBJC_TYPE(RTCRtpCapabilities) *capabilities =
+ [factory rtpReceiverCapabilitiesForKind:kRTCMediaStreamTrackKindVideo];
+
+ RTC_OBJC_TYPE(RTCRtpCodecCapability) * targetCodec;
+ for (RTC_OBJC_TYPE(RTCRtpCodecCapability) * codec in capabilities.codecs) {
+ if ([codec.name isEqual:@"VP8"]) {
+ targetCodec = codec;
+ break;
+ }
+ }
+ XCTAssertNotNil(targetCodec);
+
+ [tranceiver setCodecPreferences:@[ targetCodec ]];
+
+ @autoreleasepool {
+ dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+
+ __block BOOL completed = NO;
+ [peerConnection
+ offerForConstraints:constraints
+ completionHandler:^(RTC_OBJC_TYPE(RTCSessionDescription) *_Nullable sdp,
+ NSError *_Nullable error) {
+ XCTAssertNil(error);
+ XCTAssertNotNil(sdp);
+
+ NSArray<NSString *> *rtpMaps = [self rtpMapsFromSDP:sdp.sdp];
+ XCTAssertEqual(1, rtpMaps.count);
+
+ XCTAssertNotNil(targetCodec.preferredPayloadType);
+ XCTAssertNotNil(targetCodec.clockRate);
+
+ NSString *expected =
+ [NSString stringWithFormat:@"a=rtpmap:%i VP8/%i",
+ targetCodec.preferredPayloadType.intValue,
+ targetCodec.clockRate.intValue];
+
+ XCTAssertTrue([expected isEqualToString:rtpMaps[0]]);
+
+ completed = YES;
+ dispatch_semaphore_signal(semaphore);
+ }];
+
+ [peerConnection close];
+ peerConnection = nil;
+ factory = nil;
+ tranceiver = nil;
+
+ dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 15.0 * NSEC_PER_SEC));
+ XCTAssertTrue(completed);
+ }
+ }
+}
+
- (bool)negotiatePeerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)pc1
withPeerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)pc2
negotiationTimeout:(NSTimeInterval)timeout {
@@ -377,4 +558,16 @@
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)));
}
+- (NSArray<NSString *> *)rtpMapsFromSDP:(NSString *)sdp {
+ NSMutableArray<NSString *> *rtpMaps = [NSMutableArray new];
+ NSArray *sdpLines =
+ [sdp componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+ for (NSString *line in sdpLines) {
+ if ([line hasPrefix:@"a=rtpmap"]) {
+ [rtpMaps addObject:line];
+ }
+ }
+ return rtpMaps;
+}
+
@end
diff --git a/third_party/libwebrtc/stats/BUILD.gn b/third_party/libwebrtc/stats/BUILD.gn
index 8993272921..1ca584d6a2 100644
--- a/third_party/libwebrtc/stats/BUILD.gn
+++ b/third_party/libwebrtc/stats/BUILD.gn
@@ -18,7 +18,6 @@ rtc_library("rtc_stats") {
sources = [
"attribute.cc",
"rtc_stats.cc",
- "rtc_stats_member.cc",
"rtc_stats_report.cc",
"rtcstats_objects.cc",
]
@@ -46,6 +45,7 @@ rtc_library("rtc_stats_test_utils") {
"../rtc_base:checks",
"../rtc_base/system:rtc_export",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
if (rtc_include_tests && !build_with_chromium) {
@@ -75,5 +75,7 @@ if (rtc_include_tests && !build_with_chromium) {
"//testing/android/native_test:native_test_support",
]
}
+
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
}
diff --git a/third_party/libwebrtc/stats/attribute.cc b/third_party/libwebrtc/stats/attribute.cc
index fab948b1bd..cf49cb2311 100644
--- a/third_party/libwebrtc/stats/attribute.cc
+++ b/third_party/libwebrtc/stats/attribute.cc
@@ -25,12 +25,12 @@ namespace {
struct VisitIsSequence {
// Any type of vector is a sequence.
template <typename T>
- bool operator()(const RTCStatsMember<std::vector<T>>* attribute) {
+ bool operator()(const absl::optional<std::vector<T>>* attribute) {
return true;
}
// Any other type is not.
template <typename T>
- bool operator()(const RTCStatsMember<T>* attribute) {
+ bool operator()(const absl::optional<T>* attribute) {
return false;
}
};
@@ -62,7 +62,7 @@ struct VisitToString {
// Vector attributes.
template <typename T>
- std::string operator()(const RTCStatsMember<std::vector<T>>* attribute) {
+ std::string operator()(const absl::optional<std::vector<T>>* attribute) {
rtc::StringBuilder sb;
sb << "[";
const char* separator = "";
@@ -84,7 +84,7 @@ struct VisitToString {
// Map attributes.
template <typename T>
std::string operator()(
- const RTCStatsMember<std::map<std::string, T>>* attribute) {
+ const absl::optional<std::map<std::string, T>>* attribute) {
rtc::StringBuilder sb;
sb << "{";
const char* separator = "";
@@ -106,21 +106,18 @@ struct VisitToString {
}
// Simple attributes.
template <typename T>
- std::string operator()(const RTCStatsMember<T>* attribute) {
+ std::string operator()(const absl::optional<T>* attribute) {
return ValueToString(attribute->value());
}
};
struct VisitIsEqual {
template <typename T>
- bool operator()(const RTCStatsMember<T>* attribute) {
+ bool operator()(const absl::optional<T>* attribute) {
if (!other.holds_alternative<T>()) {
return false;
}
- absl::optional<T> attribute_as_optional =
- attribute->has_value() ? absl::optional<T>(attribute->value())
- : absl::nullopt;
- return attribute_as_optional == other.as_optional<T>();
+ return *attribute == other.as_optional<T>();
}
const Attribute& other;
@@ -146,7 +143,7 @@ bool Attribute::is_sequence() const {
}
bool Attribute::is_string() const {
- return absl::holds_alternative<const RTCStatsMember<std::string>*>(
+ return absl::holds_alternative<const absl::optional<std::string>*>(
attribute_);
}
diff --git a/third_party/libwebrtc/stats/rtc_stats_member.cc b/third_party/libwebrtc/stats/rtc_stats_member.cc
deleted file mode 100644
index 3f91988ed0..0000000000
--- a/third_party/libwebrtc/stats/rtc_stats_member.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2023 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "api/stats/rtc_stats_member.h"
-
-namespace webrtc {
-
-#define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str) \
- template <> \
- RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() { \
- return type; \
- } \
- template <> \
- bool RTCStatsMember<T>::is_sequence() const { \
- return is_seq; \
- } \
- template <> \
- bool RTCStatsMember<T>::is_string() const { \
- return is_str; \
- } \
- template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
-
-WEBRTC_DEFINE_RTCSTATSMEMBER(bool, kBool, false, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t, kInt32, false, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t, kUint32, false, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t, kInt64, false, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t, kUint64, false, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(double, kDouble, false, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::string, kString, false, true);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>, kSequenceBool, true, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>, kSequenceInt32, true, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
- kSequenceUint32,
- true,
- false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>, kSequenceInt64, true, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
- kSequenceUint64,
- true,
- false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>, kSequenceDouble, true, false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
- kSequenceString,
- true,
- false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64,
- kMapStringUint64,
- false,
- false);
-WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble,
- kMapStringDouble,
- false,
- false);
-
-} // namespace webrtc
diff --git a/third_party/libwebrtc/stats/rtc_stats_report_unittest.cc b/third_party/libwebrtc/stats/rtc_stats_report_unittest.cc
index b3ac0a2db4..f11ff52e53 100644
--- a/third_party/libwebrtc/stats/rtc_stats_report_unittest.cc
+++ b/third_party/libwebrtc/stats/rtc_stats_report_unittest.cc
@@ -10,6 +10,7 @@
#include "api/stats/rtc_stats_report.h"
+#include "absl/types/optional.h"
#include "api/stats/attribute.h"
#include "api/stats/rtc_stats.h"
#include "rtc_base/checks.h"
@@ -24,7 +25,7 @@ class RTCTestStats1 : public RTCStats {
RTCTestStats1(const std::string& id, Timestamp timestamp)
: RTCStats(id, timestamp) {}
- RTCStatsMember<int32_t> integer;
+ absl::optional<int32_t> integer;
};
WEBRTC_RTCSTATS_IMPL(RTCTestStats1,
@@ -39,7 +40,7 @@ class RTCTestStats2 : public RTCStats {
RTCTestStats2(const std::string& id, Timestamp timestamp)
: RTCStats(id, timestamp) {}
- RTCStatsMember<double> number;
+ absl::optional<double> number;
};
WEBRTC_RTCSTATS_IMPL(RTCTestStats2,
@@ -54,7 +55,7 @@ class RTCTestStats3 : public RTCStats {
RTCTestStats3(const std::string& id, Timestamp timestamp)
: RTCStats(id, timestamp) {}
- RTCStatsMember<std::string> string;
+ absl::optional<std::string> string;
};
WEBRTC_RTCSTATS_IMPL(RTCTestStats3,
diff --git a/third_party/libwebrtc/stats/rtc_stats_unittest.cc b/third_party/libwebrtc/stats/rtc_stats_unittest.cc
index fd90692875..555360f07f 100644
--- a/third_party/libwebrtc/stats/rtc_stats_unittest.cc
+++ b/third_party/libwebrtc/stats/rtc_stats_unittest.cc
@@ -15,6 +15,7 @@
#include <cstring>
#include <iostream>
+#include "absl/types/optional.h"
#include "rtc_base/checks.h"
#include "rtc_base/strings/json.h"
#include "stats/test/rtc_test_stats.h"
@@ -46,7 +47,7 @@ class RTCChildStats : public RTCStats {
RTCChildStats(const std::string& id, Timestamp timestamp)
: RTCStats(id, timestamp) {}
- RTCStatsMember<int32_t> child_int;
+ absl::optional<int32_t> child_int;
};
WEBRTC_RTCSTATS_IMPL(RTCChildStats,
@@ -61,7 +62,7 @@ class RTCGrandChildStats : public RTCChildStats {
RTCGrandChildStats(const std::string& id, Timestamp timestamp)
: RTCChildStats(id, timestamp) {}
- RTCStatsMember<int32_t> grandchild_int;
+ absl::optional<int32_t> grandchild_int;
};
WEBRTC_RTCSTATS_IMPL(RTCGrandChildStats,
@@ -166,7 +167,8 @@ TEST(RTCStatsTest, EqualityOperator) {
stats_with_all_values.m_map_string_double = std::map<std::string, double>();
EXPECT_NE(stats_with_all_values, empty_stats);
EXPECT_EQ(stats_with_all_values, stats_with_all_values);
- EXPECT_NE(stats_with_all_values.m_int32, stats_with_all_values.m_uint32);
+ EXPECT_NE(stats_with_all_values.GetAttribute(stats_with_all_values.m_int32),
+ stats_with_all_values.GetAttribute(stats_with_all_values.m_uint32));
RTCTestStats one_member_different[] = {
stats_with_all_values, stats_with_all_values, stats_with_all_values,
@@ -392,71 +394,42 @@ TEST(RTCStatsTest, RTCStatsPrintsValidJson) {
TEST(RTCStatsTest, IsSequence) {
RTCTestStats stats("statsId", Timestamp::Micros(42));
- EXPECT_FALSE(stats.m_bool.is_sequence());
- EXPECT_FALSE(stats.m_int32.is_sequence());
- EXPECT_FALSE(stats.m_uint32.is_sequence());
- EXPECT_FALSE(stats.m_int64.is_sequence());
- EXPECT_FALSE(stats.m_uint64.is_sequence());
- EXPECT_FALSE(stats.m_double.is_sequence());
- EXPECT_FALSE(stats.m_string.is_sequence());
- EXPECT_TRUE(stats.m_sequence_bool.is_sequence());
- EXPECT_TRUE(stats.m_sequence_int32.is_sequence());
- EXPECT_TRUE(stats.m_sequence_uint32.is_sequence());
- EXPECT_TRUE(stats.m_sequence_int64.is_sequence());
- EXPECT_TRUE(stats.m_sequence_uint64.is_sequence());
- EXPECT_TRUE(stats.m_sequence_double.is_sequence());
- EXPECT_TRUE(stats.m_sequence_string.is_sequence());
- EXPECT_FALSE(stats.m_map_string_uint64.is_sequence());
- EXPECT_FALSE(stats.m_map_string_double.is_sequence());
-}
-
-TEST(RTCStatsTest, Type) {
- RTCTestStats stats("statsId", Timestamp::Micros(42));
- EXPECT_EQ(RTCStatsMemberInterface::kBool, stats.m_bool.type());
- EXPECT_EQ(RTCStatsMemberInterface::kInt32, stats.m_int32.type());
- EXPECT_EQ(RTCStatsMemberInterface::kUint32, stats.m_uint32.type());
- EXPECT_EQ(RTCStatsMemberInterface::kInt64, stats.m_int64.type());
- EXPECT_EQ(RTCStatsMemberInterface::kUint64, stats.m_uint64.type());
- EXPECT_EQ(RTCStatsMemberInterface::kDouble, stats.m_double.type());
- EXPECT_EQ(RTCStatsMemberInterface::kString, stats.m_string.type());
- EXPECT_EQ(RTCStatsMemberInterface::kSequenceBool,
- stats.m_sequence_bool.type());
- EXPECT_EQ(RTCStatsMemberInterface::kSequenceInt32,
- stats.m_sequence_int32.type());
- EXPECT_EQ(RTCStatsMemberInterface::kSequenceUint32,
- stats.m_sequence_uint32.type());
- EXPECT_EQ(RTCStatsMemberInterface::kSequenceInt64,
- stats.m_sequence_int64.type());
- EXPECT_EQ(RTCStatsMemberInterface::kSequenceUint64,
- stats.m_sequence_uint64.type());
- EXPECT_EQ(RTCStatsMemberInterface::kSequenceDouble,
- stats.m_sequence_double.type());
- EXPECT_EQ(RTCStatsMemberInterface::kSequenceString,
- stats.m_sequence_string.type());
- EXPECT_EQ(RTCStatsMemberInterface::kMapStringUint64,
- stats.m_map_string_uint64.type());
- EXPECT_EQ(RTCStatsMemberInterface::kMapStringDouble,
- stats.m_map_string_double.type());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_bool).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_int32).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_uint32).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_int64).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_uint64).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_double).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_string).is_sequence());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_bool).is_sequence());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_int32).is_sequence());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_uint32).is_sequence());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_int64).is_sequence());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_uint64).is_sequence());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_double).is_sequence());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_string).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_uint64).is_sequence());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_double).is_sequence());
}
TEST(RTCStatsTest, IsString) {
RTCTestStats stats("statsId", Timestamp::Micros(42));
- EXPECT_TRUE(stats.m_string.is_string());
- EXPECT_FALSE(stats.m_bool.is_string());
- EXPECT_FALSE(stats.m_int32.is_string());
- EXPECT_FALSE(stats.m_uint32.is_string());
- EXPECT_FALSE(stats.m_int64.is_string());
- EXPECT_FALSE(stats.m_uint64.is_string());
- EXPECT_FALSE(stats.m_double.is_string());
- EXPECT_FALSE(stats.m_sequence_bool.is_string());
- EXPECT_FALSE(stats.m_sequence_int32.is_string());
- EXPECT_FALSE(stats.m_sequence_uint32.is_string());
- EXPECT_FALSE(stats.m_sequence_int64.is_string());
- EXPECT_FALSE(stats.m_sequence_uint64.is_string());
- EXPECT_FALSE(stats.m_sequence_double.is_string());
- EXPECT_FALSE(stats.m_sequence_string.is_string());
- EXPECT_FALSE(stats.m_map_string_uint64.is_string());
- EXPECT_FALSE(stats.m_map_string_double.is_string());
+ EXPECT_TRUE(stats.GetAttribute(stats.m_string).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_bool).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_int32).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_uint32).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_int64).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_uint64).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_double).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_bool).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_int32).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_uint32).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_int64).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_uint64).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_double).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_string).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_uint64).is_string());
+ EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_double).is_string());
}
TEST(RTCStatsTest, AttributeToString) {
diff --git a/third_party/libwebrtc/stats/test/rtc_test_stats.h b/third_party/libwebrtc/stats/test/rtc_test_stats.h
index 05c0904c02..ff1a06f97c 100644
--- a/third_party/libwebrtc/stats/test/rtc_test_stats.h
+++ b/third_party/libwebrtc/stats/test/rtc_test_stats.h
@@ -16,6 +16,7 @@
#include <string>
#include <vector>
+#include "absl/types/optional.h"
#include "api/stats/rtc_stats.h"
#include "rtc_base/system/rtc_export.h"
@@ -27,22 +28,22 @@ class RTC_EXPORT RTCTestStats : public RTCStats {
RTCTestStats(const std::string& id, Timestamp timestamp);
~RTCTestStats() override;
- RTCStatsMember<bool> m_bool;
- RTCStatsMember<int32_t> m_int32;
- RTCStatsMember<uint32_t> m_uint32;
- RTCStatsMember<int64_t> m_int64;
- RTCStatsMember<uint64_t> m_uint64;
- RTCStatsMember<double> m_double;
- RTCStatsMember<std::string> m_string;
- RTCStatsMember<std::vector<bool>> m_sequence_bool;
- RTCStatsMember<std::vector<int32_t>> m_sequence_int32;
- RTCStatsMember<std::vector<uint32_t>> m_sequence_uint32;
- RTCStatsMember<std::vector<int64_t>> m_sequence_int64;
- RTCStatsMember<std::vector<uint64_t>> m_sequence_uint64;
- RTCStatsMember<std::vector<double>> m_sequence_double;
- RTCStatsMember<std::vector<std::string>> m_sequence_string;
- RTCStatsMember<std::map<std::string, uint64_t>> m_map_string_uint64;
- RTCStatsMember<std::map<std::string, double>> m_map_string_double;
+ absl::optional<bool> m_bool;
+ absl::optional<int32_t> m_int32;
+ absl::optional<uint32_t> m_uint32;
+ absl::optional<int64_t> m_int64;
+ absl::optional<uint64_t> m_uint64;
+ absl::optional<double> m_double;
+ absl::optional<std::string> m_string;
+ absl::optional<std::vector<bool>> m_sequence_bool;
+ absl::optional<std::vector<int32_t>> m_sequence_int32;
+ absl::optional<std::vector<uint32_t>> m_sequence_uint32;
+ absl::optional<std::vector<int64_t>> m_sequence_int64;
+ absl::optional<std::vector<uint64_t>> m_sequence_uint64;
+ absl::optional<std::vector<double>> m_sequence_double;
+ absl::optional<std::vector<std::string>> m_sequence_string;
+ absl::optional<std::map<std::string, uint64_t>> m_map_string_uint64;
+ absl::optional<std::map<std::string, double>> m_map_string_double;
};
} // namespace webrtc
diff --git a/third_party/libwebrtc/test/BUILD.gn b/third_party/libwebrtc/test/BUILD.gn
index 75d8d9f3a8..bf98ec7d3a 100644
--- a/third_party/libwebrtc/test/BUILD.gn
+++ b/third_party/libwebrtc/test/BUILD.gn
@@ -735,6 +735,8 @@ if (rtc_include_tests) {
"../api:mock_video_encoder",
"../api:scoped_refptr",
"../api:simulcast_test_fixture_api",
+ "../api/environment",
+ "../api/environment:environment_factory",
"../api/task_queue",
"../api/task_queue:task_queue_test",
"../api/test/video:function_video_factory",
@@ -867,6 +869,7 @@ rtc_library("fileutils") {
":fileutils_override_api",
":fileutils_override_impl",
"../rtc_base:checks",
+ "../rtc_base:ssl",
"../rtc_base:stringutils",
]
absl_deps = [
@@ -956,6 +959,7 @@ rtc_library("fileutils_unittests") {
":fileutils",
":test_support",
"../rtc_base:checks",
+ "../rtc_base:ssl",
]
absl_deps = [
"//third_party/abseil-cpp/absl/strings:strings",
@@ -1107,28 +1111,6 @@ rtc_source_set("test_renderer") {
}
}
-rtc_library("mock_frame_transformer") {
- visibility = [ "*" ]
- testonly = true
- sources = [ "mock_frame_transformer.h" ]
- deps = [
- "../api:frame_transformer_interface",
- "../test:test_support",
- ]
-}
-
-rtc_library("mock_transformable_frame") {
- visibility = [ "*" ]
-
- testonly = true
- sources = [ "mock_transformable_frame.h" ]
-
- deps = [
- "../api:frame_transformer_interface",
- "../test:test_support",
- ]
-}
-
if (is_mac) {
rtc_library("test_renderer_objc") {
testonly = true
diff --git a/third_party/libwebrtc/test/call_test.cc b/third_party/libwebrtc/test/call_test.cc
index 6cdd8da133..f26a44a341 100644
--- a/third_party/libwebrtc/test/call_test.cc
+++ b/third_party/libwebrtc/test/call_test.cc
@@ -657,9 +657,7 @@ void CallTest::StartVideoSources() {
void CallTest::StartVideoStreams() {
StartVideoSources();
for (size_t i = 0; i < video_send_streams_.size(); ++i) {
- std::vector<bool> active_rtp_streams(
- video_send_configs_[i].rtp.ssrcs.size(), true);
- video_send_streams_[i]->StartPerRtpStream(active_rtp_streams);
+ video_send_streams_[i]->Start();
}
for (VideoReceiveStreamInterface* video_recv_stream : video_receive_streams_)
video_recv_stream->Start();
diff --git a/third_party/libwebrtc/test/fuzzers/BUILD.gn b/third_party/libwebrtc/test/fuzzers/BUILD.gn
index 083c20c6f4..642b0c8e08 100644
--- a/third_party/libwebrtc/test/fuzzers/BUILD.gn
+++ b/third_party/libwebrtc/test/fuzzers/BUILD.gn
@@ -132,6 +132,11 @@ if (rtc_use_h265) {
"../../modules/video_coding/",
]
}
+
+ webrtc_fuzzer_test("h265_depacketizer_fuzzer") {
+ sources = [ "h265_depacketizer_fuzzer.cc" ]
+ deps = [ "../../modules/rtp_rtcp" ]
+ }
}
webrtc_fuzzer_test("forward_error_correction_fuzzer") {
@@ -471,6 +476,7 @@ webrtc_fuzzer_test("stun_validator_fuzzer") {
webrtc_fuzzer_test("pseudotcp_parser_fuzzer") {
sources = [ "pseudotcp_parser_fuzzer.cc" ]
deps = [
+ "../../p2p:pseudo_tcp",
"../../p2p:rtc_p2p",
"../../rtc_base:threading",
]
diff --git a/third_party/libwebrtc/test/fuzzers/h265_depacketizer_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/h265_depacketizer_fuzzer.cc
new file mode 100644
index 0000000000..00025ef887
--- /dev/null
+++ b/third_party/libwebrtc/test/fuzzers/h265_depacketizer_fuzzer.cc
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ if (size > 200000)
+ return;
+ VideoRtpDepacketizerH265 depacketizer;
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(data, size));
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/test/fuzzers/neteq_signal_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/neteq_signal_fuzzer.cc
index 485c38085e..3b1f70cdb4 100644
--- a/third_party/libwebrtc/test/fuzzers/neteq_signal_fuzzer.cc
+++ b/third_party/libwebrtc/test/fuzzers/neteq_signal_fuzzer.cc
@@ -179,7 +179,6 @@ void FuzzOneInputTest(const uint8_t* data, size_t size) {
// Configure NetEq and the NetEqTest object.
NetEqTest::Callbacks callbacks;
NetEq::Config config;
- config.enable_post_decode_vad = true;
config.enable_fast_accelerate = true;
auto codecs = NetEqTest::StandardDecoderMap();
// rate_types contains the payload types that will be used for encoding.
diff --git a/third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc
index ddf2ca9d3d..97b0ce2c03 100644
--- a/third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc
+++ b/third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc
@@ -1,75 +1,75 @@
-/*
- * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#include <stddef.h>
-#include <stdint.h>
-
-#include "api/video/video_frame_type.h"
-#include "modules/rtp_rtcp/source/rtp_format.h"
-#include "modules/rtp_rtcp/source/rtp_format_h264.h"
-#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
-#include "rtc_base/checks.h"
-#include "test/fuzzers/fuzz_data_helper.h"
-
-namespace webrtc {
-void FuzzOneInput(const uint8_t* data, size_t size) {
- test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
-
- RtpPacketizer::PayloadSizeLimits limits;
- limits.max_payload_len = 1200;
- // Read uint8_t to be sure reduction_lens are much smaller than
- // max_payload_len and thus limits structure is valid.
- limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
- limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
- limits.single_packet_reduction_len =
- fuzz_input.ReadOrDefaultValue<uint8_t>(0);
- const H264PacketizationMode kPacketizationModes[] = {
- H264PacketizationMode::NonInterleaved,
- H264PacketizationMode::SingleNalUnit};
-
- H264PacketizationMode packetization_mode =
- fuzz_input.SelectOneOf(kPacketizationModes);
-
- // Main function under test: RtpPacketizerH264's constructor.
- RtpPacketizerH264 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
- limits, packetization_mode);
-
- size_t num_packets = packetizer.NumPackets();
- if (num_packets == 0) {
- return;
- }
- // When packetization was successful, validate NextPacket function too.
- // While at it, check that packets respect the payload size limits.
- RtpPacketToSend rtp_packet(nullptr);
- // Single packet.
- if (num_packets == 1) {
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.single_packet_reduction_len);
- return;
- }
- // First packet.
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.first_packet_reduction_len);
- // Middle packets.
- for (size_t i = 1; i < num_packets - 1; ++i) {
- rtp_packet.Clear();
- RTC_CHECK(packetizer.NextPacket(&rtp_packet))
- << "Failed to get packet#" << i;
- RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
- << "Packet #" << i << " exceeds it's limit";
- }
- // Last packet.
- rtp_packet.Clear();
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.last_packet_reduction_len);
-}
-} // namespace webrtc
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include <stddef.h>
+#include <stdint.h>
+
+#include "api/video/video_frame_type.h"
+#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_format_h264.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/checks.h"
+#include "test/fuzzers/fuzz_data_helper.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
+
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 1200;
+ // Read uint8_t to be sure reduction_lens are much smaller than
+ // max_payload_len and thus limits structure is valid.
+ limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.single_packet_reduction_len =
+ fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ const H264PacketizationMode kPacketizationModes[] = {
+ H264PacketizationMode::NonInterleaved,
+ H264PacketizationMode::SingleNalUnit};
+
+ H264PacketizationMode packetization_mode =
+ fuzz_input.SelectOneOf(kPacketizationModes);
+
+ // Main function under test: RtpPacketizerH264's constructor.
+ RtpPacketizerH264 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
+ limits, packetization_mode);
+
+ size_t num_packets = packetizer.NumPackets();
+ if (num_packets == 0) {
+ return;
+ }
+ // When packetization was successful, validate NextPacket function too.
+ // While at it, check that packets respect the payload size limits.
+ RtpPacketToSend rtp_packet(nullptr);
+ // Single packet.
+ if (num_packets == 1) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.single_packet_reduction_len);
+ return;
+ }
+ // First packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.first_packet_reduction_len);
+ // Middle packets.
+ for (size_t i = 1; i < num_packets - 1; ++i) {
+ rtp_packet.Clear();
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet))
+ << "Failed to get packet#" << i;
+ RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
+ << "Packet #" << i << " exceeds it's limit";
+ }
+ // Last packet.
+ rtp_packet.Clear();
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.last_packet_reduction_len);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc
index c3c055de0f..93706e9253 100644
--- a/third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc
+++ b/third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc
@@ -1,73 +1,73 @@
-/*
- * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#include <stddef.h>
-#include <stdint.h>
-
-#include "api/video/video_frame_type.h"
-#include "modules/rtp_rtcp/source/rtp_format.h"
-#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
-#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
-#include "rtc_base/checks.h"
-#include "test/fuzzers/fuzz_data_helper.h"
-
-namespace webrtc {
-void FuzzOneInput(const uint8_t* data, size_t size) {
- test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
-
- RtpPacketizer::PayloadSizeLimits limits;
- limits.max_payload_len = 1200;
- // Read uint8_t to be sure reduction_lens are much smaller than
- // max_payload_len and thus limits structure is valid.
- limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
- limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
- limits.single_packet_reduction_len =
- fuzz_input.ReadOrDefaultValue<uint8_t>(0);
-
- RTPVideoHeaderVP8 hdr_info;
- hdr_info.InitRTPVideoHeaderVP8();
- uint16_t picture_id = fuzz_input.ReadOrDefaultValue<uint16_t>(0);
- hdr_info.pictureId =
- picture_id >= 0x8000 ? kNoPictureId : picture_id & 0x7fff;
-
- // Main function under test: RtpPacketizerVp8's constructor.
- RtpPacketizerVp8 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
- limits, hdr_info);
-
- size_t num_packets = packetizer.NumPackets();
- if (num_packets == 0) {
- return;
- }
- // When packetization was successful, validate NextPacket function too.
- // While at it, check that packets respect the payload size limits.
- RtpPacketToSend rtp_packet(nullptr);
- // Single packet.
- if (num_packets == 1) {
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.single_packet_reduction_len);
- return;
- }
- // First packet.
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.first_packet_reduction_len);
- // Middle packets.
- for (size_t i = 1; i < num_packets - 1; ++i) {
- RTC_CHECK(packetizer.NextPacket(&rtp_packet))
- << "Failed to get packet#" << i;
- RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
- << "Packet #" << i << " exceeds it's limit";
- }
- // Last packet.
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.last_packet_reduction_len);
-}
-} // namespace webrtc
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include <stddef.h>
+#include <stdint.h>
+
+#include "api/video/video_frame_type.h"
+#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/checks.h"
+#include "test/fuzzers/fuzz_data_helper.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
+
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 1200;
+ // Read uint8_t to be sure reduction_lens are much smaller than
+ // max_payload_len and thus limits structure is valid.
+ limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.single_packet_reduction_len =
+ fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+
+ RTPVideoHeaderVP8 hdr_info;
+ hdr_info.InitRTPVideoHeaderVP8();
+ uint16_t picture_id = fuzz_input.ReadOrDefaultValue<uint16_t>(0);
+ hdr_info.pictureId =
+ picture_id >= 0x8000 ? kNoPictureId : picture_id & 0x7fff;
+
+ // Main function under test: RtpPacketizerVp8's constructor.
+ RtpPacketizerVp8 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
+ limits, hdr_info);
+
+ size_t num_packets = packetizer.NumPackets();
+ if (num_packets == 0) {
+ return;
+ }
+ // When packetization was successful, validate NextPacket function too.
+ // While at it, check that packets respect the payload size limits.
+ RtpPacketToSend rtp_packet(nullptr);
+ // Single packet.
+ if (num_packets == 1) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.single_packet_reduction_len);
+ return;
+ }
+ // First packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.first_packet_reduction_len);
+ // Middle packets.
+ for (size_t i = 1; i < num_packets - 1; ++i) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet))
+ << "Failed to get packet#" << i;
+ RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
+ << "Packet #" << i << " exceeds it's limit";
+ }
+ // Last packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.last_packet_reduction_len);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc
index 3b5e67f697..d95114eaef 100644
--- a/third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc
+++ b/third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc
@@ -1,73 +1,73 @@
-/*
- * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#include <stddef.h>
-#include <stdint.h>
-
-#include "api/video/video_frame_type.h"
-#include "modules/rtp_rtcp/source/rtp_format.h"
-#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
-#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
-#include "rtc_base/checks.h"
-#include "test/fuzzers/fuzz_data_helper.h"
-
-namespace webrtc {
-void FuzzOneInput(const uint8_t* data, size_t size) {
- test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
-
- RtpPacketizer::PayloadSizeLimits limits;
- limits.max_payload_len = 1200;
- // Read uint8_t to be sure reduction_lens are much smaller than
- // max_payload_len and thus limits structure is valid.
- limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
- limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
- limits.single_packet_reduction_len =
- fuzz_input.ReadOrDefaultValue<uint8_t>(0);
-
- RTPVideoHeaderVP9 hdr_info;
- hdr_info.InitRTPVideoHeaderVP9();
- uint16_t picture_id = fuzz_input.ReadOrDefaultValue<uint16_t>(0);
- hdr_info.picture_id =
- picture_id >= 0x8000 ? kNoPictureId : picture_id & 0x7fff;
-
- // Main function under test: RtpPacketizerVp9's constructor.
- RtpPacketizerVp9 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
- limits, hdr_info);
-
- size_t num_packets = packetizer.NumPackets();
- if (num_packets == 0) {
- return;
- }
- // When packetization was successful, validate NextPacket function too.
- // While at it, check that packets respect the payload size limits.
- RtpPacketToSend rtp_packet(nullptr);
- // Single packet.
- if (num_packets == 1) {
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.single_packet_reduction_len);
- return;
- }
- // First packet.
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.first_packet_reduction_len);
- // Middle packets.
- for (size_t i = 1; i < num_packets - 1; ++i) {
- RTC_CHECK(packetizer.NextPacket(&rtp_packet))
- << "Failed to get packet#" << i;
- RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
- << "Packet #" << i << " exceeds it's limit";
- }
- // Last packet.
- RTC_CHECK(packetizer.NextPacket(&rtp_packet));
- RTC_CHECK_LE(rtp_packet.payload_size(),
- limits.max_payload_len - limits.last_packet_reduction_len);
-}
-} // namespace webrtc
+/*
+ * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include <stddef.h>
+#include <stdint.h>
+
+#include "api/video/video_frame_type.h"
+#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/checks.h"
+#include "test/fuzzers/fuzz_data_helper.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
+
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 1200;
+ // Read uint8_t to be sure reduction_lens are much smaller than
+ // max_payload_len and thus limits structure is valid.
+ limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.single_packet_reduction_len =
+ fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+
+ RTPVideoHeaderVP9 hdr_info;
+ hdr_info.InitRTPVideoHeaderVP9();
+ uint16_t picture_id = fuzz_input.ReadOrDefaultValue<uint16_t>(0);
+ hdr_info.picture_id =
+ picture_id >= 0x8000 ? kNoPictureId : picture_id & 0x7fff;
+
+ // Main function under test: RtpPacketizerVp9's constructor.
+ RtpPacketizerVp9 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
+ limits, hdr_info);
+
+ size_t num_packets = packetizer.NumPackets();
+ if (num_packets == 0) {
+ return;
+ }
+ // When packetization was successful, validate NextPacket function too.
+ // While at it, check that packets respect the payload size limits.
+ RtpPacketToSend rtp_packet(nullptr);
+ // Single packet.
+ if (num_packets == 1) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.single_packet_reduction_len);
+ return;
+ }
+ // First packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.first_packet_reduction_len);
+ // Middle packets.
+ for (size_t i = 1; i < num_packets - 1; ++i) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet))
+ << "Failed to get packet#" << i;
+ RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
+ << "Packet #" << i << " exceeds it's limit";
+ }
+ // Last packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.last_packet_reduction_len);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/test/mock_audio_encoder.h b/third_party/libwebrtc/test/mock_audio_encoder.h
index 1f4510e885..30518e8f49 100644
--- a/third_party/libwebrtc/test/mock_audio_encoder.h
+++ b/third_party/libwebrtc/test/mock_audio_encoder.h
@@ -33,6 +33,10 @@ class MockAudioEncoder : public AudioEncoder {
GetFrameLengthRange,
(),
(const, override));
+ MOCK_METHOD((absl::optional<std::pair<DataRate, DataRate>>),
+ GetBitrateRange,
+ (),
+ (const, override));
MOCK_METHOD(void, Reset, (), (override));
MOCK_METHOD(bool, SetFec, (bool enable), (override));
diff --git a/third_party/libwebrtc/test/mock_transformable_frame.h b/third_party/libwebrtc/test/mock_transformable_frame.h
deleted file mode 100644
index 26eb6b7030..0000000000
--- a/third_party/libwebrtc/test/mock_transformable_frame.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef TEST_MOCK_TRANSFORMABLE_FRAME_H_
-#define TEST_MOCK_TRANSFORMABLE_FRAME_H_
-
-#include "api/frame_transformer_interface.h"
-#include "test/gmock.h"
-
-namespace webrtc {
-
-class MockTransformableAudioFrame : public TransformableAudioFrameInterface {
- public:
- MOCK_METHOD(rtc::ArrayView<const uint8_t>, GetData, (), (const, override));
- MOCK_METHOD(rtc::ArrayView<const uint32_t>,
- GetContributingSources,
- (),
- (const, override));
- MOCK_METHOD(absl::optional<uint64_t>,
- AbsoluteCaptureTimestamp,
- (),
- (const, override));
- MOCK_METHOD(void, SetData, (rtc::ArrayView<const uint8_t>), (override));
- MOCK_METHOD(uint8_t, GetPayloadType, (), (const, override));
- MOCK_METHOD(uint32_t, GetSsrc, (), (const, override));
- MOCK_METHOD(uint32_t, GetTimestamp, (), (const, override));
- MOCK_METHOD(void, SetRTPTimestamp, (uint32_t), (override));
- MOCK_METHOD(Direction, GetDirection, (), (const, override));
- MOCK_METHOD(std::string, GetMimeType, (), (const, override));
-};
-
-} // namespace webrtc
-
-#endif // TEST_MOCK_TRANSFORMABLE_FRAME_H_
diff --git a/third_party/libwebrtc/test/network/BUILD.gn b/third_party/libwebrtc/test/network/BUILD.gn
index 6df563d31d..e9bd263ed9 100644
--- a/third_party/libwebrtc/test/network/BUILD.gn
+++ b/third_party/libwebrtc/test/network/BUILD.gn
@@ -56,6 +56,7 @@ rtc_library("emulated_network") {
"../../api/units:time_delta",
"../../api/units:timestamp",
"../../call:simulated_network",
+ "../../p2p:basic_packet_socket_factory",
"../../p2p:p2p_server_utils",
"../../p2p:rtc_p2p",
"../../rtc_base:async_packet_socket",
@@ -128,6 +129,8 @@ if (rtc_include_tests && !build_with_chromium) {
"../../call:simulated_network",
"../../media:rtc_audio_video",
"../../modules/audio_device:test_audio_device_module",
+ "../../p2p:basic_packet_socket_factory",
+ "../../p2p:basic_port_allocator",
"../../p2p:rtc_p2p",
"../../pc:pc_test_utils",
"../../pc:peerconnection_wrapper",
diff --git a/third_party/libwebrtc/test/pc/e2e/BUILD.gn b/third_party/libwebrtc/test/pc/e2e/BUILD.gn
index 0eb7aa2c68..22c9ee48d2 100644
--- a/third_party/libwebrtc/test/pc/e2e/BUILD.gn
+++ b/third_party/libwebrtc/test/pc/e2e/BUILD.gn
@@ -109,6 +109,7 @@ if (!build_with_chromium) {
"../../../api/video_codecs:builtin_video_encoder_factory",
"../../../modules/audio_device:test_audio_device_module",
"../../../modules/audio_processing/aec_dump",
+ "../../../p2p:basic_port_allocator",
"../../../p2p:rtc_p2p",
"../../../rtc_base:threading",
"analyzer/video:quality_analyzing_video_encoder",
@@ -576,6 +577,7 @@ if (!build_with_chromium) {
"../../../media:media_constants",
"../../../media:rid_description",
"../../../media:rtc_media_base",
+ "../../../p2p:p2p_constants",
"../../../p2p:rtc_p2p",
"../../../pc:sdp_utils",
"../../../pc:session_description",
diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/BUILD.gn b/third_party/libwebrtc/test/pc/e2e/analyzer/video/BUILD.gn
index 17876e54be..6adfc50049 100644
--- a/third_party/libwebrtc/test/pc/e2e/analyzer/video/BUILD.gn
+++ b/third_party/libwebrtc/test/pc/e2e/analyzer/video/BUILD.gn
@@ -130,6 +130,7 @@ rtc_library("quality_analyzing_video_decoder") {
":encoded_image_data_injector_api",
":simulcast_dummy_buffer_helper",
"../../../../../api:video_quality_analyzer_api",
+ "../../../../../api/environment",
"../../../../../api/video:encoded_image",
"../../../../../api/video:video_frame",
"../../../../../api/video_codecs:video_codecs_api",
diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.cc
index e17b5d5d83..3cd179370f 100644
--- a/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.cc
+++ b/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.cc
@@ -259,10 +259,10 @@ QualityAnalyzingVideoDecoderFactory::GetSupportedFormats() const {
return delegate_->GetSupportedFormats();
}
-std::unique_ptr<VideoDecoder>
-QualityAnalyzingVideoDecoderFactory::CreateVideoDecoder(
+std::unique_ptr<VideoDecoder> QualityAnalyzingVideoDecoderFactory::Create(
+ const Environment& env,
const SdpVideoFormat& format) {
- std::unique_ptr<VideoDecoder> decoder = delegate_->CreateVideoDecoder(format);
+ std::unique_ptr<VideoDecoder> decoder = delegate_->Create(env, format);
return std::make_unique<QualityAnalyzingVideoDecoder>(
peer_name_, std::move(decoder), extractor_, analyzer_);
}
diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h b/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h
index 2f0c2b9d5d..daa919d7e4 100644
--- a/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h
+++ b/third_party/libwebrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h
@@ -18,6 +18,7 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
+#include "api/environment/environment.h"
#include "api/test/video_quality_analyzer_interface.h"
#include "api/video/encoded_image.h"
#include "api/video/video_frame.h"
@@ -136,8 +137,8 @@ class QualityAnalyzingVideoDecoderFactory : public VideoDecoderFactory {
// Methods of VideoDecoderFactory interface.
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
- std::unique_ptr<VideoDecoder> CreateVideoDecoder(
- const SdpVideoFormat& format) override;
+ std::unique_ptr<VideoDecoder> Create(const Environment& env,
+ const SdpVideoFormat& format) override;
private:
const std::string peer_name_;
diff --git a/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc
index 257fecf309..3c4f6cabe1 100644
--- a/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc
+++ b/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc
@@ -27,11 +27,6 @@ using ::webrtc::test::Unit;
constexpr TimeDelta kStatsWaitTimeout = TimeDelta::Seconds(1);
-// Field trial which controls whether to report standard-compliant bytes
-// sent/received per stream. If enabled, padding and headers are not included
-// in bytes sent or received.
-constexpr char kUseStandardBytesStats[] = "WebRTC-UseStandardBytesStats";
-
} // namespace
NetworkQualityMetricsReporter::NetworkQualityMetricsReporter(
@@ -107,11 +102,6 @@ void NetworkQualityMetricsReporter::StopAndReportResults() {
ReportStats(alice_network_label_, alice_stats, alice_packets_loss);
ReportStats(bob_network_label_, bob_stats, bob_packets_loss);
- if (!webrtc::field_trial::IsEnabled(kUseStandardBytesStats)) {
- RTC_LOG(LS_ERROR)
- << "Non-standard GetStats; \"payload\" counts include RTP headers";
- }
-
MutexLock lock(&lock_);
for (const auto& pair : pc_stats_) {
ReportPCStats(pair.first, pair.second);
diff --git a/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.h b/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.h
index 1348a58943..fd523cc48d 100644
--- a/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.h
+++ b/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.h
@@ -48,8 +48,6 @@ class NetworkQualityMetricsReporter
private:
struct PCStats {
- // TODO(nisse): Separate audio and video counters. Depends on standard stat
- // counters, enabled by field trial "WebRTC-UseStandardBytesStats".
DataSize payload_received = DataSize::Zero();
DataSize payload_sent = DataSize::Zero();
};
diff --git a/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc b/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc
index 90f201facd..3a6b808167 100644
--- a/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc
+++ b/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc
@@ -73,8 +73,6 @@ constexpr TimeDelta kQuickTestModeRunDuration = TimeDelta::Millis(100);
// Field trials to enable Flex FEC advertising and receiving.
constexpr char kFlexFecEnabledFieldTrials[] =
"WebRTC-FlexFEC-03-Advertised/Enabled/WebRTC-FlexFEC-03/Enabled/";
-constexpr char kUseStandardsBytesStats[] =
- "WebRTC-UseStandardBytesStats/Enabled/";
class FixturePeerConnectionObserver : public MockPeerConnectionObserver {
public:
@@ -439,8 +437,7 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
std::string PeerConnectionE2EQualityTest::GetFieldTrials(
const RunParams& run_params) {
- std::vector<absl::string_view> default_field_trials = {
- kUseStandardsBytesStats};
+ std::vector<absl::string_view> default_field_trials = {};
if (run_params.enable_flex_fec_support) {
default_field_trials.push_back(kFlexFecEnabledFieldTrials);
}
diff --git a/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc
index b965a7acd8..706224ce08 100644
--- a/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc
+++ b/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc
@@ -51,11 +51,6 @@ using NetworkLayerStats =
constexpr TimeDelta kStatsWaitTimeout = TimeDelta::Seconds(1);
-// Field trial which controls whether to report standard-compliant bytes
-// sent/received per stream. If enabled, padding and headers are not included
-// in bytes sent or received.
-constexpr char kUseStandardBytesStats[] = "WebRTC-UseStandardBytesStats";
-
EmulatedNetworkStats PopulateStats(std::vector<EmulatedEndpoint*> endpoints,
NetworkEmulationManager* network_emulation) {
rtc::Event stats_loaded;
@@ -325,11 +320,6 @@ void StatsBasedNetworkQualityMetricsReporter::OnStatsReports(
void StatsBasedNetworkQualityMetricsReporter::StopAndReportResults() {
Timestamp end_time = clock_->CurrentTime();
- if (!webrtc::field_trial::IsEnabled(kUseStandardBytesStats)) {
- RTC_LOG(LS_ERROR)
- << "Non-standard GetStats; \"payload\" counts include RTP headers";
- }
-
std::map<std::string, NetworkLayerStats> stats = collector_.GetStats();
for (const auto& entry : stats) {
LogNetworkLayerStats(entry.first, entry.second);
diff --git a/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.h b/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.h
index 60daf40c8c..ba6bf04e18 100644
--- a/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.h
+++ b/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.h
@@ -70,9 +70,6 @@ class StatsBasedNetworkQualityMetricsReporter
private:
struct PCStats {
- // TODO(bugs.webrtc.org/10525): Separate audio and video counters. Depends
- // on standard stat counters, enabled by field trial
- // "WebRTC-UseStandardBytesStats".
DataSize payload_received = DataSize::Zero();
DataSize payload_sent = DataSize::Zero();
diff --git a/third_party/libwebrtc/test/peer_scenario/BUILD.gn b/third_party/libwebrtc/test/peer_scenario/BUILD.gn
index 18f81a56e6..e1d164a47d 100644
--- a/third_party/libwebrtc/test/peer_scenario/BUILD.gn
+++ b/third_party/libwebrtc/test/peer_scenario/BUILD.gn
@@ -53,7 +53,9 @@ if (rtc_include_tests) {
"../../media:rtp_utils",
"../../modules/audio_device:test_audio_device_module",
"../../modules/rtp_rtcp:rtp_rtcp_format",
+ "../../p2p:basic_port_allocator",
"../../p2p:rtc_p2p",
+ "../../p2p:transport_description",
"../../pc:channel",
"../../pc:jsep_transport_controller",
"../../pc:pc_test_utils",
diff --git a/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc b/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc
index 1397b32fe3..3ba4fdb677 100644
--- a/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc
+++ b/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc
@@ -370,10 +370,13 @@ void PeerScenarioClient::CreateAndSetSdp(
void PeerScenarioClient::SetSdpOfferAndGetAnswer(
std::string remote_offer,
+ std::function<void()> remote_description_set,
std::function<void(std::string)> answer_handler) {
if (!signaling_thread_->IsCurrent()) {
- signaling_thread_->PostTask(
- [=] { SetSdpOfferAndGetAnswer(remote_offer, answer_handler); });
+ signaling_thread_->PostTask([=] {
+ SetSdpOfferAndGetAnswer(remote_offer, remote_description_set,
+ answer_handler);
+ });
return;
}
RTC_DCHECK_RUN_ON(signaling_thread_);
@@ -381,6 +384,11 @@ void PeerScenarioClient::SetSdpOfferAndGetAnswer(
CreateSessionDescription(SdpType::kOffer, remote_offer),
rtc::make_ref_counted<LambdaSetRemoteDescriptionObserver>([=](RTCError) {
RTC_DCHECK_RUN_ON(signaling_thread_);
+ if (remote_description_set) {
+ // Allow the caller to modify transceivers
+ // before creating the answer.
+ remote_description_set();
+ }
peer_connection_->CreateAnswer(
rtc::make_ref_counted<LambdaCreateSessionDescriptionObserver>(
[=](std::unique_ptr<SessionDescriptionInterface> answer) {
diff --git a/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.h b/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.h
index e863757759..cb025e9879 100644
--- a/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.h
+++ b/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.h
@@ -147,6 +147,7 @@ class PeerScenarioClient {
std::function<void(SessionDescriptionInterface*)> munge_offer,
std::function<void(std::string)> offer_handler);
void SetSdpOfferAndGetAnswer(std::string remote_offer,
+ std::function<void()> remote_description_set,
std::function<void(std::string)> answer_handler);
void SetSdpAnswer(
std::string remote_answer,
diff --git a/third_party/libwebrtc/test/peer_scenario/signaling_route.cc b/third_party/libwebrtc/test/peer_scenario/signaling_route.cc
index eeec7c8657..8688c1abd8 100644
--- a/third_party/libwebrtc/test/peer_scenario/signaling_route.cc
+++ b/third_party/libwebrtc/test/peer_scenario/signaling_route.cc
@@ -59,6 +59,7 @@ void StartSdpNegotiation(
CrossTrafficRoute* ret_route,
std::function<void(SessionDescriptionInterface* offer)> munge_offer,
std::function<void(SessionDescriptionInterface*)> modify_offer,
+ std::function<void()> callee_remote_description_set,
std::function<void(const SessionDescriptionInterface&)> exchange_finished) {
caller->CreateAndSetSdp(munge_offer, [=](std::string sdp_offer) {
if (modify_offer) {
@@ -67,11 +68,14 @@ void StartSdpNegotiation(
RTC_CHECK(offer->ToString(&sdp_offer));
}
send_route->NetworkDelayedAction(kSdpPacketSize, [=] {
- callee->SetSdpOfferAndGetAnswer(sdp_offer, [=](std::string answer) {
- ret_route->NetworkDelayedAction(kSdpPacketSize, [=] {
- caller->SetSdpAnswer(std::move(answer), std::move(exchange_finished));
- });
- });
+ callee->SetSdpOfferAndGetAnswer(
+ sdp_offer, std::move(callee_remote_description_set),
+ [=](std::string answer) {
+ ret_route->NetworkDelayedAction(kSdpPacketSize, [=] {
+ caller->SetSdpAnswer(std::move(answer),
+ std::move(exchange_finished));
+ });
+ });
});
});
}
@@ -92,22 +96,39 @@ void SignalingRoute::StartIceSignaling() {
}
void SignalingRoute::NegotiateSdp(
+ std::function<void(SessionDescriptionInterface* offer)> munge_offer,
+ std::function<void(SessionDescriptionInterface* offer)> modify_offer,
+ std::function<void()> callee_remote_description_set,
+ std::function<void(const SessionDescriptionInterface& answer)>
+ exchange_finished) {
+ StartSdpNegotiation(caller_, callee_, send_route_, ret_route_, munge_offer,
+ modify_offer, callee_remote_description_set,
+ exchange_finished);
+}
+
+void SignalingRoute::NegotiateSdp(
std::function<void(SessionDescriptionInterface*)> munge_offer,
std::function<void(SessionDescriptionInterface*)> modify_offer,
std::function<void(const SessionDescriptionInterface&)> exchange_finished) {
- StartSdpNegotiation(caller_, callee_, send_route_, ret_route_, munge_offer,
- modify_offer, exchange_finished);
+ NegotiateSdp(munge_offer, modify_offer, {}, exchange_finished);
}
void SignalingRoute::NegotiateSdp(
std::function<void(SessionDescriptionInterface*)> modify_offer,
std::function<void(const SessionDescriptionInterface&)> exchange_finished) {
- NegotiateSdp({}, modify_offer, exchange_finished);
+ NegotiateSdp({}, modify_offer, {}, exchange_finished);
+}
+
+void SignalingRoute::NegotiateSdp(
+ std::function<void()> remote_description_set,
+ std::function<void(const SessionDescriptionInterface& answer)>
+ exchange_finished) {
+ NegotiateSdp({}, {}, remote_description_set, exchange_finished);
}
void SignalingRoute::NegotiateSdp(
std::function<void(const SessionDescriptionInterface&)> exchange_finished) {
- NegotiateSdp({}, {}, exchange_finished);
+ NegotiateSdp({}, {}, {}, exchange_finished);
}
} // namespace test
diff --git a/third_party/libwebrtc/test/peer_scenario/signaling_route.h b/third_party/libwebrtc/test/peer_scenario/signaling_route.h
index a95ae5c9f7..9b317d2552 100644
--- a/third_party/libwebrtc/test/peer_scenario/signaling_route.h
+++ b/third_party/libwebrtc/test/peer_scenario/signaling_route.h
@@ -35,12 +35,21 @@ class SignalingRoute {
// The `munge_offer` callback is used to modify an offer between its creation
// and set local description. This behavior is forbidden according to the spec
// but available here in order to allow test coverage on corner cases.
- // The `exchange_finished` callback is called with the answer produced after
- // SDP negotations has completed.
+ // `callee_remote_description_set` is invoked when callee has applied the
+ // offer but not yet created an answer. The purpose is to allow tests to
+ // modify transceivers created from the offer. The `exchange_finished`
+ // callback is called with the answer produced after SDP negotations has
+ // completed.
// TODO(srte): Handle lossy links.
void NegotiateSdp(
std::function<void(SessionDescriptionInterface* offer)> munge_offer,
std::function<void(SessionDescriptionInterface* offer)> modify_offer,
+ std::function<void()> callee_remote_description_set,
+ std::function<void(const SessionDescriptionInterface& answer)>
+ exchange_finished);
+ void NegotiateSdp(
+ std::function<void(SessionDescriptionInterface* offer)> munge_offer,
+ std::function<void(SessionDescriptionInterface* offer)> modify_offer,
std::function<void(const SessionDescriptionInterface& answer)>
exchange_finished);
void NegotiateSdp(
@@ -48,6 +57,10 @@ class SignalingRoute {
std::function<void(const SessionDescriptionInterface& answer)>
exchange_finished);
void NegotiateSdp(
+ std::function<void()> remote_description_set,
+ std::function<void(const SessionDescriptionInterface& answer)>
+ exchange_finished);
+ void NegotiateSdp(
std::function<void(const SessionDescriptionInterface& answer)>
exchange_finished);
SignalingRoute reverse() {
diff --git a/third_party/libwebrtc/test/peer_scenario/tests/bwe_ramp_up_test.cc b/third_party/libwebrtc/test/peer_scenario/tests/bwe_ramp_up_test.cc
index a7a17bbfd1..f8eaa47858 100644
--- a/third_party/libwebrtc/test/peer_scenario/tests/bwe_ramp_up_test.cc
+++ b/third_party/libwebrtc/test/peer_scenario/tests/bwe_ramp_up_test.cc
@@ -25,6 +25,9 @@ namespace webrtc {
namespace test {
using ::testing::SizeIs;
+using ::testing::Test;
+using ::testing::ValuesIn;
+using ::testing::WithParamInterface;
rtc::scoped_refptr<const RTCStatsReport> GetStatsAndProcess(
PeerScenario& s,
@@ -124,5 +127,152 @@ TEST(BweRampupTest, RampUpWithUndemuxableRtpPackets) {
// ensure BWE has increased beyond noise levels.
EXPECT_GT(final_bwe, initial_bwe + DataRate::KilobitsPerSec(345));
}
+
+struct InitialProbeTestParams {
+ DataRate network_capacity;
+ DataRate expected_bwe_min;
+};
+class BweRampupWithInitialProbeTest
+ : public Test,
+ public WithParamInterface<InitialProbeTestParams> {};
+
+INSTANTIATE_TEST_SUITE_P(
+ BweRampupWithInitialProbeTest,
+ BweRampupWithInitialProbeTest,
+ ValuesIn<InitialProbeTestParams>(
+ {{
+ .network_capacity = DataRate::KilobitsPerSec(3000),
+ .expected_bwe_min = DataRate::KilobitsPerSec(2500),
+ },
+ {
+ .network_capacity = webrtc::DataRate::KilobitsPerSec(500),
+ .expected_bwe_min = webrtc::DataRate::KilobitsPerSec(400),
+ }}));
+
+// Test that caller and callee BWE rampup even if no media packets are sent.
+// - BandWidthEstimationSettings.allow_probe_without_media must be set.
+// - A Video RtpTransceiver with RTX support needs to be negotiated.
+TEST_P(BweRampupWithInitialProbeTest, BweRampUpBothDirectionsWithoutMedia) {
+ PeerScenario s(*::testing::UnitTest::GetInstance()->current_test_info());
+ InitialProbeTestParams test_params = GetParam();
+
+ PeerScenarioClient* caller = s.CreateClient({});
+ PeerScenarioClient* callee = s.CreateClient({});
+
+ auto video_result = caller->pc()->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
+ ASSERT_EQ(video_result.error().type(), RTCErrorType::NONE);
+
+ caller->pc()->ReconfigureBandwidthEstimation(
+ {.allow_probe_without_media = true});
+ callee->pc()->ReconfigureBandwidthEstimation(
+ {.allow_probe_without_media = true});
+
+ auto node_builder =
+ s.net()->NodeBuilder().capacity_kbps(test_params.network_capacity.kbps());
+ auto caller_node = node_builder.Build().node;
+ auto callee_node = node_builder.Build().node;
+ s.net()->CreateRoute(caller->endpoint(), {caller_node}, callee->endpoint());
+ s.net()->CreateRoute(callee->endpoint(), {callee_node}, caller->endpoint());
+
+ auto signaling =
+ s.ConnectSignaling(caller, callee, {caller_node}, {callee_node});
+ signaling.StartIceSignaling();
+
+ std::atomic<bool> offer_exchange_done(false);
+ signaling.NegotiateSdp(
+ [&]() {
+ // When remote description has been set, a transceiver is created.
+ // Set the diretion to sendrecv so that it can be used for BWE probing
+ // from callee -> caller.
+ ASSERT_THAT(callee->pc()->GetTransceivers(), SizeIs(1));
+ ASSERT_TRUE(
+ callee->pc()
+ ->GetTransceivers()[0]
+ ->SetDirectionWithError(RtpTransceiverDirection::kSendRecv)
+ .ok());
+ },
+ [&](const SessionDescriptionInterface& answer) {
+ offer_exchange_done = true;
+ });
+ // Wait for SDP negotiation.
+ s.WaitAndProcess(&offer_exchange_done);
+
+ // Test that 1s after offer/answer exchange finish, we have a BWE estimate,
+ // even though no video frames have been sent.
+ s.ProcessMessages(TimeDelta::Seconds(1));
+
+ auto callee_inbound_stats =
+ GetStatsAndProcess(s, callee)->GetStatsOfType<RTCInboundRtpStreamStats>();
+ ASSERT_THAT(callee_inbound_stats, SizeIs(1));
+ ASSERT_EQ(*callee_inbound_stats[0]->frames_received, 0u);
+ auto caller_inbound_stats =
+ GetStatsAndProcess(s, caller)->GetStatsOfType<RTCInboundRtpStreamStats>();
+ ASSERT_THAT(caller_inbound_stats, SizeIs(1));
+ ASSERT_EQ(*caller_inbound_stats[0]->frames_received, 0u);
+
+ DataRate caller_bwe = GetAvailableSendBitrate(GetStatsAndProcess(s, caller));
+ EXPECT_GT(caller_bwe.kbps(), test_params.expected_bwe_min.kbps());
+ EXPECT_LE(caller_bwe.kbps(), test_params.network_capacity.kbps());
+ DataRate callee_bwe = GetAvailableSendBitrate(GetStatsAndProcess(s, callee));
+ EXPECT_GT(callee_bwe.kbps(), test_params.expected_bwe_min.kbps());
+ EXPECT_LE(callee_bwe.kbps(), test_params.network_capacity.kbps());
+}
+
+// Test that we can reconfigure bandwidth estimation and send new BWE probes.
+// In this test, camera is stopped, and some times later, the app want to get a
+// new BWE estimate.
+TEST(BweRampupTest, CanReconfigureBweAfterStopingVideo) {
+ PeerScenario s(*::testing::UnitTest::GetInstance()->current_test_info());
+ PeerScenarioClient* caller = s.CreateClient({});
+ PeerScenarioClient* callee = s.CreateClient({});
+
+ auto node_builder = s.net()->NodeBuilder().capacity_kbps(1000);
+ auto caller_node = node_builder.Build().node;
+ auto callee_node = node_builder.Build().node;
+ s.net()->CreateRoute(caller->endpoint(), {caller_node}, callee->endpoint());
+ s.net()->CreateRoute(callee->endpoint(), {callee_node}, caller->endpoint());
+
+ PeerScenarioClient::VideoSendTrack track = caller->CreateVideo("VIDEO", {});
+
+ auto signaling =
+ s.ConnectSignaling(caller, callee, {caller_node}, {callee_node});
+
+ signaling.StartIceSignaling();
+
+ std::atomic<bool> offer_exchange_done(false);
+ signaling.NegotiateSdp([&](const SessionDescriptionInterface& answer) {
+ offer_exchange_done = true;
+ });
+ // Wait for SDP negotiation.
+ s.WaitAndProcess(&offer_exchange_done);
+
+ // Send a TCP messages to the receiver using the same downlink node.
+ // This is done just to force a lower BWE than the link capacity.
+ webrtc::TcpMessageRoute* tcp_route = s.net()->CreateTcpRoute(
+ s.net()->CreateRoute({caller_node}), s.net()->CreateRoute({callee_node}));
+ DataRate bwe_before_restart = DataRate::Zero();
+
+ std::atomic<bool> message_delivered(false);
+ tcp_route->SendMessage(
+ /*size=*/5'00'000,
+ /*on_received=*/[&]() { message_delivered = true; });
+ s.WaitAndProcess(&message_delivered);
+ bwe_before_restart = GetAvailableSendBitrate(GetStatsAndProcess(s, caller));
+
+ // Camera is stopped.
+ track.capturer->Stop();
+ s.ProcessMessages(TimeDelta::Seconds(2));
+
+ // Some time later, the app is interested in restarting BWE since we may want
+ // to resume video eventually.
+ caller->pc()->ReconfigureBandwidthEstimation(
+ {.allow_probe_without_media = true});
+ s.ProcessMessages(TimeDelta::Seconds(1));
+ DataRate bwe_after_restart =
+ GetAvailableSendBitrate(GetStatsAndProcess(s, caller));
+ EXPECT_GT(bwe_after_restart.kbps(), bwe_before_restart.kbps() + 300);
+ EXPECT_LT(bwe_after_restart.kbps(), 1000);
+}
+
} // namespace test
} // namespace webrtc
diff --git a/third_party/libwebrtc/test/peer_scenario/tests/unsignaled_stream_test.cc b/third_party/libwebrtc/test/peer_scenario/tests/unsignaled_stream_test.cc
index 4f478b4b2a..dced274e68 100644
--- a/third_party/libwebrtc/test/peer_scenario/tests/unsignaled_stream_test.cc
+++ b/third_party/libwebrtc/test/peer_scenario/tests/unsignaled_stream_test.cc
@@ -98,7 +98,6 @@ TEST_P(UnsignaledStreamTest, ReplacesUnsignaledStreamOnCompletedSignaling) {
PeerScenarioClient::Config config = PeerScenarioClient::Config();
// Disable encryption so that we can inject a fake early media packet without
// triggering srtp failures.
- config.disable_encryption = true;
auto* caller = s.CreateClient(config);
auto* callee = s.CreateClient(config);
diff --git a/third_party/libwebrtc/test/scenario/video_stream.cc b/third_party/libwebrtc/test/scenario/video_stream.cc
index 654aed7c6c..c3f0da7cb7 100644
--- a/third_party/libwebrtc/test/scenario/video_stream.cc
+++ b/third_party/libwebrtc/test/scenario/video_stream.cc
@@ -491,10 +491,6 @@ void SendVideoStream::UpdateConfig(
void SendVideoStream::UpdateActiveLayers(std::vector<bool> active_layers) {
sender_->task_queue_.PostTask([=] {
MutexLock lock(&mutex_);
- if (config_.encoder.codec ==
- VideoStreamConfig::Encoder::Codec::kVideoCodecVP8) {
- send_stream_->StartPerRtpStream(active_layers);
- }
VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config_);
RTC_CHECK_EQ(encoder_config.simulcast_layers.size(), active_layers.size());
for (size_t i = 0; i < encoder_config.simulcast_layers.size(); ++i)
diff --git a/third_party/libwebrtc/test/testsupport/file_utils.cc b/third_party/libwebrtc/test/testsupport/file_utils.cc
index 47fed9ac05..afabbaad3f 100644
--- a/third_party/libwebrtc/test/testsupport/file_utils.cc
+++ b/third_party/libwebrtc/test/testsupport/file_utils.cc
@@ -36,7 +36,7 @@
#include <sys/stat.h> // To check for directory existence.
#ifndef S_ISDIR // Not defined in stat.h on Windows.
-#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
+#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#include <stdio.h>
@@ -54,6 +54,7 @@
#include "absl/strings/string_view.h"
#include "rtc_base/checks.h"
+#include "rtc_base/helpers.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"
#include "test/testsupport/file_utils_override.h"
@@ -94,6 +95,13 @@ std::string OutputPath() {
return webrtc::test::internal::OutputPath();
}
+std::string OutputPathWithRandomDirectory() {
+ std::string path = webrtc::test::internal::OutputPath();
+ std::string rand_dir = path + rtc::CreateRandomUuid();
+
+ return CreateDir(rand_dir) ? rand_dir + std::string(kPathDelimiter) : path;
+}
+
std::string WorkingDir() {
return webrtc::test::internal::WorkingDir();
}
@@ -229,7 +237,12 @@ std::string ResourcePath(absl::string_view name, absl::string_view extension) {
std::string JoinFilename(absl::string_view dir, absl::string_view name) {
RTC_CHECK(!dir.empty()) << "Special cases not implemented.";
rtc::StringBuilder os;
- os << dir << kPathDelimiter << name;
+ os << dir;
+ // If the directory path already ends with a path delimiter don't append it
+ if (dir.back() != kPathDelimiter.back()) {
+ os << kPathDelimiter;
+ }
+ os << name;
return os.Release();
}
diff --git a/third_party/libwebrtc/test/testsupport/file_utils.h b/third_party/libwebrtc/test/testsupport/file_utils.h
index ab80ca4454..120c6cb279 100644
--- a/third_party/libwebrtc/test/testsupport/file_utils.h
+++ b/third_party/libwebrtc/test/testsupport/file_utils.h
@@ -42,6 +42,11 @@ ABSL_CONST_INIT extern const absl::string_view kPathDelimiter;
// found, the current working directory ("./") is returned as a fallback.
std::string OutputPath();
+// Same as the above but appends a randomly named folder at the end of the path
+// Primerly used to provide a solution for stress testing environments to
+// prevent colission of files and folders.
+std::string OutputPathWithRandomDirectory();
+
// Generates an empty file with a unique name in the specified directory and
// returns the file name and path.
// TODO(titovartem) rename to TempFile and next method to TempFilename
diff --git a/third_party/libwebrtc/test/testsupport/file_utils_unittest.cc b/third_party/libwebrtc/test/testsupport/file_utils_unittest.cc
index b9de01d09d..1101a63352 100644
--- a/third_party/libwebrtc/test/testsupport/file_utils_unittest.cc
+++ b/third_party/libwebrtc/test/testsupport/file_utils_unittest.cc
@@ -19,6 +19,7 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "rtc_base/checks.h"
+#include "rtc_base/helpers.h"
#include "test/gmock.h"
#include "test/gtest.h"
@@ -119,6 +120,28 @@ TEST_F(FileUtilsTest, OutputPathFromRootWorkingDir) {
ASSERT_THAT(result, EndsWith(expected_end));
}
+TEST_F(FileUtilsTest, RandomOutputPathFromUnchangedWorkingDir) {
+ rtc::SetRandomTestMode(true);
+ std::string fixed_first_uuid = "def01482-f829-429a-bfd4-841706e92cdd";
+ std::string expected_end = ExpectedRootDirByPlatform() + fixed_first_uuid +
+ std::string(kPathDelimiter);
+ std::string result = webrtc::test::OutputPathWithRandomDirectory();
+
+ ASSERT_THAT(result, EndsWith(expected_end));
+}
+
+TEST_F(FileUtilsTest, RandomOutputPathFromRootWorkingDir) {
+ ASSERT_EQ(0, chdir(kPathDelimiter.data()));
+
+ rtc::SetRandomTestMode(true);
+ std::string fixed_first_uuid = "def01482-f829-429a-bfd4-841706e92cdd";
+ std::string expected_end = ExpectedRootDirByPlatform() + fixed_first_uuid +
+ std::string(kPathDelimiter);
+ std::string result = webrtc::test::OutputPathWithRandomDirectory();
+
+ ASSERT_THAT(result, EndsWith(expected_end));
+}
+
TEST_F(FileUtilsTest, TempFilename) {
std::string temp_filename = webrtc::test::TempFilename(
webrtc::test::OutputPath(), "TempFilenameTest");
@@ -147,7 +170,8 @@ TEST_F(FileUtilsTest, GenerateTempFilename) {
#define MAYBE_CreateDir CreateDir
#endif
TEST_F(FileUtilsTest, MAYBE_CreateDir) {
- std::string directory = "fileutils-unittest-empty-dir";
+ std::string directory =
+ test::OutputPathWithRandomDirectory() + "fileutils-unittest-empty-dir";
// Make sure it's removed if a previous test has failed:
remove(directory.c_str());
ASSERT_TRUE(webrtc::test::CreateDir(directory));
@@ -231,7 +255,7 @@ TEST_F(FileUtilsTest, WriteReadDeleteFilesAndDirs) {
// Create an empty temporary directory for this test.
const std::string temp_directory =
- OutputPath() + Path("TempFileUtilsTestReadDirectory/");
+ OutputPathWithRandomDirectory() + Path("TempFileUtilsTestReadDirectory/");
CreateDir(temp_directory);
EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries));
EXPECT_TRUE(DirExists(temp_directory));
@@ -273,5 +297,15 @@ TEST_F(FileUtilsTest, DirNameStopsAtRoot) {
EXPECT_EQ(Path("/"), DirName(Path("/")));
}
+TEST_F(FileUtilsTest, JoinFilenameDoesNotAppendExtraPathDelimiterIfExists) {
+ EXPECT_EQ(JoinFilename(Path("/some/path/"), "file.txt"),
+ Path("/some/path/file.txt"));
+}
+
+TEST_F(FileUtilsTest, JoinFilenameAppendsPathDelimiterIfMissing) {
+ EXPECT_EQ(JoinFilename(Path("/some/path"), "file.txt"),
+ Path("/some/path/file.txt"));
+}
+
} // namespace test
} // namespace webrtc
diff --git a/third_party/libwebrtc/test/testsupport/test_artifacts.cc b/third_party/libwebrtc/test/testsupport/test_artifacts.cc
index 6f062e5fe4..b0ab046e63 100644
--- a/third_party/libwebrtc/test/testsupport/test_artifacts.cc
+++ b/third_party/libwebrtc/test/testsupport/test_artifacts.cc
@@ -20,7 +20,7 @@
namespace {
const std::string& DefaultArtifactPath() {
- static const std::string path = webrtc::test::OutputPath();
+ static const std::string path = webrtc::test::OutputPathWithRandomDirectory();
return path;
}
} // namespace
@@ -55,8 +55,11 @@ bool WriteToTestArtifactsDir(const char* filename,
return false;
}
- FileWrapper output = FileWrapper::OpenWriteOnly(
- JoinFilename(absl::GetFlag(FLAGS_test_artifacts_dir), filename));
+ std::string full_path =
+ JoinFilename(absl::GetFlag(FLAGS_test_artifacts_dir), filename);
+ FileWrapper output = FileWrapper::OpenWriteOnly(full_path);
+
+ RTC_LOG(LS_INFO) << "Writing test artifacts in: " << full_path;
return output.is_open() && output.Write(buffer, length);
}
diff --git a/third_party/libwebrtc/test/video_codec_tester.cc b/third_party/libwebrtc/test/video_codec_tester.cc
index f5fdc07a6b..9aef46d44e 100644
--- a/third_party/libwebrtc/test/video_codec_tester.cc
+++ b/third_party/libwebrtc/test/video_codec_tester.cc
@@ -772,10 +772,12 @@ class VideoCodecAnalyzer : public VideoCodecTester::VideoCodecStats {
class Decoder : public DecodedImageCallback {
public:
- Decoder(VideoDecoderFactory* decoder_factory,
+ Decoder(const Environment& env,
+ VideoDecoderFactory* decoder_factory,
const DecoderSettings& decoder_settings,
VideoCodecAnalyzer* analyzer)
- : decoder_factory_(decoder_factory),
+ : env_(env),
+ decoder_factory_(decoder_factory),
analyzer_(analyzer),
pacer_(decoder_settings.pacing_settings) {
RTC_CHECK(analyzer_) << "Analyzer must be provided";
@@ -792,7 +794,7 @@ class Decoder : public DecodedImageCallback {
}
void Initialize(const SdpVideoFormat& sdp_video_format) {
- decoder_ = decoder_factory_->CreateVideoDecoder(sdp_video_format);
+ decoder_ = decoder_factory_->Create(env_, sdp_video_format);
RTC_CHECK(decoder_) << "Could not create decoder for video format "
<< sdp_video_format.ToString();
@@ -863,6 +865,7 @@ class Decoder : public DecodedImageCallback {
return WEBRTC_VIDEO_CODEC_OK;
}
+ const Environment env_;
VideoDecoderFactory* decoder_factory_;
std::unique_ptr<VideoDecoder> decoder_;
VideoCodecAnalyzer* const analyzer_;
@@ -982,7 +985,8 @@ class Encoder : public EncodedImageCallback {
// layer >X receive encoded lower layers.
int num_spatial_layers =
ScalabilityModeToNumSpatialLayers(last_superframe_->scalability_mode);
- for (int sidx = *last_superframe_->encoded_frame.SpatialIndex() + 1;
+ for (int sidx =
+ last_superframe_->encoded_frame.SpatialIndex().value_or(0) + 1;
sidx < num_spatial_layers; ++sidx) {
last_superframe_->encoded_frame.SetSpatialIndex(sidx);
DeliverEncodedFrame(last_superframe_->encoded_frame);
@@ -1108,8 +1112,6 @@ class Encoder : public EncodedImageCallback {
int result = encoder_->InitEncode(&vc, ves);
RTC_CHECK(result == WEBRTC_VIDEO_CODEC_OK);
-
- SetRates(es);
}
void SetRates(const EncodingSettings& es) {
@@ -1258,6 +1260,29 @@ void ConfigureSimulcast(VideoCodec* vc) {
}
}
+void SetDefaultCodecSpecificSettings(VideoCodec* vc, int num_temporal_layers) {
+ switch (vc->codecType) {
+ case kVideoCodecVP8:
+ *(vc->VP8()) = VideoEncoder::GetDefaultVp8Settings();
+ vc->VP8()->SetNumberOfTemporalLayers(num_temporal_layers);
+ break;
+ case kVideoCodecVP9: {
+ *(vc->VP9()) = VideoEncoder::GetDefaultVp9Settings();
+ vc->VP9()->SetNumberOfTemporalLayers(num_temporal_layers);
+ } break;
+ case kVideoCodecH264: {
+ *(vc->H264()) = VideoEncoder::GetDefaultH264Settings();
+ vc->H264()->SetNumberOfTemporalLayers(num_temporal_layers);
+ } break;
+ case kVideoCodecAV1:
+ case kVideoCodecH265:
+ break;
+ case kVideoCodecGeneric:
+ case kVideoCodecMultiplex:
+ RTC_CHECK_NOTREACHED();
+ }
+}
+
std::tuple<std::vector<DataRate>, ScalabilityMode>
SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
ScalabilityMode scalability_mode,
@@ -1269,11 +1294,11 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
int num_temporal_layers =
ScalabilityModeToNumTemporalLayers(scalability_mode);
- if (bitrates_kbps.size() > 1 ||
- (num_spatial_layers == 1 && num_temporal_layers == 1)) {
- RTC_CHECK(bitrates_kbps.size() ==
- static_cast<size_t>(num_spatial_layers * num_temporal_layers))
- << "bitrates must be provided for all layers";
+ int num_bitrates = static_cast<int>(bitrates_kbps.size());
+ RTC_CHECK(num_bitrates == 1 || num_bitrates == num_spatial_layers ||
+ num_bitrates == num_spatial_layers * num_temporal_layers);
+
+ if (num_bitrates == num_spatial_layers * num_temporal_layers) {
std::vector<DataRate> bitrates;
for (const auto& bitrate_kbps : bitrates_kbps) {
bitrates.push_back(DataRate::KilobitsPerSec(bitrate_kbps));
@@ -1281,59 +1306,93 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
return std::make_tuple(bitrates, scalability_mode);
}
+ int total_bitrate_kbps =
+ std::accumulate(bitrates_kbps.begin(), bitrates_kbps.end(), 0);
+
VideoCodec vc;
vc.codecType = PayloadStringToCodecType(codec_type);
vc.width = width;
vc.height = height;
- vc.startBitrate = bitrates_kbps.front();
- vc.maxBitrate = bitrates_kbps.front();
+ vc.startBitrate = total_bitrate_kbps;
+ vc.maxBitrate = total_bitrate_kbps;
vc.minBitrate = 0;
vc.maxFramerate = static_cast<uint32_t>(framerate_fps);
vc.numberOfSimulcastStreams = 0;
vc.mode = webrtc::VideoCodecMode::kRealtimeVideo;
vc.SetScalabilityMode(scalability_mode);
+ SetDefaultCodecSpecificSettings(&vc, num_temporal_layers);
- switch (vc.codecType) {
- case kVideoCodecVP8:
- // TODO(webrtc:14852): Configure simulcast.
- *(vc.VP8()) = VideoEncoder::GetDefaultVp8Settings();
- vc.VP8()->SetNumberOfTemporalLayers(num_temporal_layers);
- ConfigureSimulcast(&vc);
- break;
- case kVideoCodecVP9: {
- *(vc.VP9()) = VideoEncoder::GetDefaultVp9Settings();
- vc.VP9()->SetNumberOfTemporalLayers(num_temporal_layers);
- const std::vector<SpatialLayer> spatialLayers = GetVp9SvcConfig(vc);
- for (size_t i = 0; i < spatialLayers.size(); ++i) {
- vc.spatialLayers[i] = spatialLayers[i];
- vc.spatialLayers[i].active = true;
- }
- } break;
- case kVideoCodecAV1: {
- bool result =
- SetAv1SvcConfig(vc, num_spatial_layers, num_temporal_layers);
- RTC_CHECK(result) << "SetAv1SvcConfig failed";
- } break;
- case kVideoCodecH264: {
- *(vc.H264()) = VideoEncoder::GetDefaultH264Settings();
- vc.H264()->SetNumberOfTemporalLayers(num_temporal_layers);
- ConfigureSimulcast(&vc);
- } break;
- case kVideoCodecH265:
- break;
- case kVideoCodecGeneric:
- case kVideoCodecMultiplex:
- RTC_CHECK_NOTREACHED();
- }
+ if (num_bitrates == num_spatial_layers) {
+ switch (vc.codecType) {
+ case kVideoCodecVP8:
+ case kVideoCodecH264:
+ case kVideoCodecH265:
+ vc.numberOfSimulcastStreams = num_spatial_layers;
+ for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
+ SimulcastStream* ss = &vc.simulcastStream[sidx];
+ ss->width = width >> (num_spatial_layers - sidx - 1);
+ ss->height = height >> (num_spatial_layers - sidx - 1);
+ ss->maxFramerate = vc.maxFramerate;
+ ss->numberOfTemporalLayers = num_temporal_layers;
+ ss->maxBitrate = bitrates_kbps[sidx];
+ ss->targetBitrate = bitrates_kbps[sidx];
+ ss->minBitrate = 0;
+ ss->qpMax = 0;
+ ss->active = true;
+ }
+ break;
+ case kVideoCodecVP9:
+ case kVideoCodecAV1:
+ for (int sidx = num_spatial_layers - 1; sidx >= 0; --sidx) {
+ SpatialLayer* ss = &vc.spatialLayers[sidx];
+ ss->width = width >> (num_spatial_layers - sidx - 1);
+ ss->height = height >> (num_spatial_layers - sidx - 1);
+ ss->maxFramerate = vc.maxFramerate;
+ ss->numberOfTemporalLayers = num_temporal_layers;
+ ss->maxBitrate = bitrates_kbps[sidx];
+ ss->targetBitrate = bitrates_kbps[sidx];
+ ss->minBitrate = 0;
+ ss->qpMax = 0;
+ ss->active = true;
+ }
+ break;
+ case kVideoCodecGeneric:
+ case kVideoCodecMultiplex:
+ RTC_CHECK_NOTREACHED();
+ }
+ } else {
+ switch (vc.codecType) {
+ case kVideoCodecVP8:
+ case kVideoCodecH264:
+ case kVideoCodecH265:
+ ConfigureSimulcast(&vc);
+ break;
+ case kVideoCodecVP9: {
+ const std::vector<SpatialLayer> spatialLayers = GetVp9SvcConfig(vc);
+ for (size_t i = 0; i < spatialLayers.size(); ++i) {
+ vc.spatialLayers[i] = spatialLayers[i];
+ vc.spatialLayers[i].active = true;
+ }
+ } break;
+ case kVideoCodecAV1: {
+ bool result =
+ SetAv1SvcConfig(vc, num_spatial_layers, num_temporal_layers);
+ RTC_CHECK(result) << "SetAv1SvcConfig failed";
+ } break;
+ case kVideoCodecGeneric:
+ case kVideoCodecMultiplex:
+ RTC_CHECK_NOTREACHED();
+ }
- if (*vc.GetScalabilityMode() != scalability_mode) {
- RTC_LOG(LS_WARNING) << "Scalability mode changed from "
- << ScalabilityModeToString(scalability_mode) << " to "
- << ScalabilityModeToString(*vc.GetScalabilityMode());
- num_spatial_layers =
- ScalabilityModeToNumSpatialLayers(*vc.GetScalabilityMode());
- num_temporal_layers =
- ScalabilityModeToNumTemporalLayers(*vc.GetScalabilityMode());
+ if (*vc.GetScalabilityMode() != scalability_mode) {
+ RTC_LOG(LS_WARNING) << "Scalability mode changed from "
+ << ScalabilityModeToString(scalability_mode) << " to "
+ << ScalabilityModeToString(*vc.GetScalabilityMode());
+ num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(*vc.GetScalabilityMode());
+ num_temporal_layers =
+ ScalabilityModeToNumTemporalLayers(*vc.GetScalabilityMode());
+ }
}
std::unique_ptr<VideoBitrateAllocator> bitrate_allocator =
@@ -1341,7 +1400,7 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
vc);
VideoBitrateAllocation bitrate_allocation =
bitrate_allocator->Allocate(VideoBitrateAllocationParameters(
- 1000 * bitrates_kbps.front(), framerate_fps));
+ 1000 * total_bitrate_kbps, framerate_fps));
std::vector<DataRate> bitrates;
for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
@@ -1476,13 +1535,14 @@ std::map<uint32_t, EncodingSettings> VideoCodecTester::CreateEncodingSettings(
}
std::unique_ptr<VideoCodecTester::VideoCodecStats>
-VideoCodecTester::RunDecodeTest(CodedVideoSource* video_source,
+VideoCodecTester::RunDecodeTest(const Environment& env,
+ CodedVideoSource* video_source,
VideoDecoderFactory* decoder_factory,
const DecoderSettings& decoder_settings,
const SdpVideoFormat& sdp_video_format) {
std::unique_ptr<VideoCodecAnalyzer> analyzer =
std::make_unique<VideoCodecAnalyzer>(/*video_source=*/nullptr);
- Decoder decoder(decoder_factory, decoder_settings, analyzer.get());
+ Decoder decoder(env, decoder_factory, decoder_settings, analyzer.get());
decoder.Initialize(sdp_video_format);
while (auto frame = video_source->PullFrame()) {
@@ -1522,6 +1582,7 @@ VideoCodecTester::RunEncodeTest(
std::unique_ptr<VideoCodecTester::VideoCodecStats>
VideoCodecTester::RunEncodeDecodeTest(
+ const Environment& env,
const VideoSourceSettings& source_settings,
VideoEncoderFactory* encoder_factory,
VideoDecoderFactory* decoder_factory,
@@ -1539,8 +1600,8 @@ VideoCodecTester::RunEncodeDecodeTest(
ScalabilityModeToNumSpatialLayers(frame_settings.scalability_mode);
std::vector<std::unique_ptr<Decoder>> decoders;
for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
- auto decoder = std::make_unique<Decoder>(decoder_factory, decoder_settings,
- analyzer.get());
+ auto decoder = std::make_unique<Decoder>(env, decoder_factory,
+ decoder_settings, analyzer.get());
decoder->Initialize(frame_settings.sdp_video_format);
decoders.push_back(std::move(decoder));
}
diff --git a/third_party/libwebrtc/test/video_codec_tester.h b/third_party/libwebrtc/test/video_codec_tester.h
index 87cc5f76f8..00b6093dca 100644
--- a/third_party/libwebrtc/test/video_codec_tester.h
+++ b/third_party/libwebrtc/test/video_codec_tester.h
@@ -199,6 +199,7 @@ class VideoCodecTester {
// Decodes video, collects and returns decode metrics.
static std::unique_ptr<VideoCodecStats> RunDecodeTest(
+ const Environment& env,
CodedVideoSource* video_source,
VideoDecoderFactory* decoder_factory,
const DecoderSettings& decoder_settings,
@@ -213,6 +214,7 @@ class VideoCodecTester {
// Encodes and decodes video, collects and returns encode and decode metrics.
static std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest(
+ const Environment& env,
const VideoSourceSettings& source_settings,
VideoEncoderFactory* encoder_factory,
VideoDecoderFactory* decoder_factory,
diff --git a/third_party/libwebrtc/test/video_codec_tester_unittest.cc b/third_party/libwebrtc/test/video_codec_tester_unittest.cc
index df5dca90a2..fdd7b37a00 100644
--- a/third_party/libwebrtc/test/video_codec_tester_unittest.cc
+++ b/third_party/libwebrtc/test/video_codec_tester_unittest.cc
@@ -17,6 +17,8 @@
#include <utility>
#include <vector>
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/test/mock_video_decoder.h"
#include "api/test/mock_video_decoder_factory.h"
#include "api/test/mock_video_encoder.h"
@@ -44,13 +46,12 @@ namespace {
using ::testing::_;
using ::testing::ElementsAre;
using ::testing::Field;
-using ::testing::Invoke;
-using ::testing::InvokeWithoutArgs;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SizeIs;
using ::testing::UnorderedElementsAreArray;
using ::testing::Values;
+using ::testing::WithoutArgs;
using VideoCodecStats = VideoCodecTester::VideoCodecStats;
using VideoSourceSettings = VideoCodecTester::VideoSourceSettings;
@@ -200,30 +201,27 @@ class VideoCodecTesterTest : public ::testing::Test {
});
NiceMock<MockVideoDecoderFactory> decoder_factory;
- ON_CALL(decoder_factory, CreateVideoDecoder)
- .WillByDefault([&](const SdpVideoFormat&) {
- // Video codec tester destroyes decoder at the end of test. Test
- // decoder collects stats which we need to access after test. To keep
- // the decode alive we wrap it into a wrapper and pass the wrapper to
- // the tester.
- class DecoderWrapper : public TestVideoDecoder {
- public:
- explicit DecoderWrapper(TestVideoDecoder* decoder)
- : decoder_(decoder) {}
- int32_t Decode(const EncodedImage& encoded_frame,
- int64_t render_time_ms) {
- return decoder_->Decode(encoded_frame, render_time_ms);
- }
- int32_t RegisterDecodeCompleteCallback(
- DecodedImageCallback* callback) {
- return decoder_->RegisterDecodeCompleteCallback(callback);
- }
- TestVideoDecoder* decoder_;
- };
- decoders_.push_back(std::make_unique<NiceMock<TestVideoDecoder>>());
- return std::make_unique<NiceMock<DecoderWrapper>>(
- decoders_.back().get());
- });
+ ON_CALL(decoder_factory, Create).WillByDefault(WithoutArgs([&] {
+ // Video codec tester destroyes decoder at the end of test. Test
+ // decoder collects stats which we need to access after test. To keep
+ // the decode alive we wrap it into a wrapper and pass the wrapper to
+ // the tester.
+ class DecoderWrapper : public TestVideoDecoder {
+ public:
+ explicit DecoderWrapper(TestVideoDecoder* decoder)
+ : decoder_(decoder) {}
+ int32_t Decode(const EncodedImage& encoded_frame,
+ int64_t render_time_ms) {
+ return decoder_->Decode(encoded_frame, render_time_ms);
+ }
+ int32_t RegisterDecodeCompleteCallback(DecodedImageCallback* callback) {
+ return decoder_->RegisterDecodeCompleteCallback(callback);
+ }
+ TestVideoDecoder* decoder_;
+ };
+ decoders_.push_back(std::make_unique<NiceMock<TestVideoDecoder>>());
+ return std::make_unique<NiceMock<DecoderWrapper>>(decoders_.back().get());
+ }));
int num_spatial_layers =
ScalabilityModeToNumSpatialLayers(scalability_mode);
@@ -252,7 +250,7 @@ class VideoCodecTesterTest : public ::testing::Test {
std::unique_ptr<VideoCodecStats> stats =
VideoCodecTester::RunEncodeDecodeTest(
- video_source_settings, &encoder_factory, &decoder_factory,
+ env_, video_source_settings, &encoder_factory, &decoder_factory,
EncoderSettings{}, DecoderSettings{}, encoding_settings);
remove(yuv_path.c_str());
@@ -260,6 +258,7 @@ class VideoCodecTesterTest : public ::testing::Test {
}
protected:
+ const Environment env_ = CreateEnvironment();
std::vector<std::unique_ptr<TestVideoDecoder>> decoders_;
};
@@ -605,6 +604,7 @@ class VideoCodecTesterTestPacing
void TearDown() override { remove(source_yuv_file_path_.c_str()); }
protected:
+ const Environment env_ = CreateEnvironment();
std::string source_yuv_file_path_;
};
@@ -644,15 +644,14 @@ TEST_P(VideoCodecTesterTestPacing, PaceDecode) {
MockCodedVideoSource video_source(kNumFrames, kTargetFramerate);
NiceMock<MockVideoDecoderFactory> decoder_factory;
- ON_CALL(decoder_factory, CreateVideoDecoder(_))
- .WillByDefault([](const SdpVideoFormat&) {
- return std::make_unique<NiceMock<MockVideoDecoder>>();
- });
+ ON_CALL(decoder_factory, Create).WillByDefault(WithoutArgs([] {
+ return std::make_unique<NiceMock<MockVideoDecoder>>();
+ }));
DecoderSettings decoder_settings;
decoder_settings.pacing_settings = pacing_settings;
std::vector<Frame> frames =
- VideoCodecTester::RunDecodeTest(&video_source, &decoder_factory,
+ VideoCodecTester::RunDecodeTest(env_, &video_source, &decoder_factory,
decoder_settings, SdpVideoFormat("VP8"))
->Slice(/*filter=*/{}, /*merge=*/false);
ASSERT_THAT(frames, SizeIs(kNumFrames));
@@ -676,5 +675,137 @@ INSTANTIATE_TEST_SUITE_P(
std::make_tuple(PacingSettings{.mode = PacingMode::kConstantRate,
.constant_rate = Frequency::Hertz(20)},
/*expected_delta_ms=*/50)));
+
+struct EncodingSettingsTestParameters {
+ std::string codec_type;
+ std::string scalability_mode;
+ std::vector<int> bitrate_kbps;
+ std::vector<int> expected_bitrate_kbps;
+};
+
+class VideoCodecTesterTestEncodingSettings
+ : public ::testing::TestWithParam<EncodingSettingsTestParameters> {};
+
+TEST_P(VideoCodecTesterTestEncodingSettings, CreateEncodingSettings) {
+ EncodingSettingsTestParameters test_params = GetParam();
+ std::map<uint32_t, EncodingSettings> encoding_settings =
+ VideoCodecTester::CreateEncodingSettings(
+ test_params.codec_type, test_params.scalability_mode, /*width=*/1280,
+ /*height=*/720, test_params.bitrate_kbps, /*framerate_fps=*/30,
+ /*num_frames=*/1);
+ ASSERT_THAT(encoding_settings, SizeIs(1));
+ const std::map<LayerId, LayerSettings>& layers_settings =
+ encoding_settings.begin()->second.layers_settings;
+ std::vector<int> configured_bitrate_kbps;
+ std::transform(layers_settings.begin(), layers_settings.end(),
+ std::back_inserter(configured_bitrate_kbps),
+ [](const auto& layer_settings) {
+ return layer_settings.second.bitrate.kbps();
+ });
+ EXPECT_EQ(configured_bitrate_kbps, test_params.expected_bitrate_kbps);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ Vp8,
+ VideoCodecTesterTestEncodingSettings,
+ Values(EncodingSettingsTestParameters{.codec_type = "VP8",
+ .scalability_mode = "L1T1",
+ .bitrate_kbps = {1},
+ .expected_bitrate_kbps = {1}},
+ EncodingSettingsTestParameters{.codec_type = "VP8",
+ .scalability_mode = "L1T1",
+ .bitrate_kbps = {10000},
+ .expected_bitrate_kbps = {10000}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP8",
+ .scalability_mode = "L1T3",
+ .bitrate_kbps = {1000},
+ .expected_bitrate_kbps = {400, 200, 400}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP8",
+ .scalability_mode = "S3T3",
+ .bitrate_kbps = {100},
+ .expected_bitrate_kbps = {40, 20, 40, 0, 0, 0, 0, 0, 0}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP8",
+ .scalability_mode = "S3T3",
+ .bitrate_kbps = {10000},
+ .expected_bitrate_kbps = {60, 30, 60, 200, 100, 200, 1000, 500,
+ 1000}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP8",
+ .scalability_mode = "S3T3",
+ .bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
+ .expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
+ 900}}));
+
+INSTANTIATE_TEST_SUITE_P(
+ Vp9,
+ VideoCodecTesterTestEncodingSettings,
+ Values(EncodingSettingsTestParameters{.codec_type = "VP9",
+ .scalability_mode = "L1T1",
+ .bitrate_kbps = {1},
+ .expected_bitrate_kbps = {1}},
+ EncodingSettingsTestParameters{.codec_type = "VP9",
+ .scalability_mode = "L1T1",
+ .bitrate_kbps = {10000},
+ .expected_bitrate_kbps = {10000}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP9",
+ .scalability_mode = "L1T3",
+ .bitrate_kbps = {1000},
+ .expected_bitrate_kbps = {540, 163, 297}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP9",
+ .scalability_mode = "L3T3",
+ .bitrate_kbps = {100},
+ .expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP9",
+ .scalability_mode = "L3T3",
+ .bitrate_kbps = {10000},
+ .expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249,
+ 452}},
+ EncodingSettingsTestParameters{
+ .codec_type = "VP9",
+ .scalability_mode = "L3T3",
+ .bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
+ .expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
+ 900}}));
+
+INSTANTIATE_TEST_SUITE_P(
+ Av1,
+ VideoCodecTesterTestEncodingSettings,
+ Values(EncodingSettingsTestParameters{.codec_type = "AV1",
+ .scalability_mode = "L1T1",
+ .bitrate_kbps = {1},
+ .expected_bitrate_kbps = {1}},
+ EncodingSettingsTestParameters{.codec_type = "AV1",
+ .scalability_mode = "L1T1",
+ .bitrate_kbps = {10000},
+ .expected_bitrate_kbps = {10000}},
+ EncodingSettingsTestParameters{
+ .codec_type = "AV1",
+ .scalability_mode = "L1T3",
+ .bitrate_kbps = {1000},
+ .expected_bitrate_kbps = {540, 163, 297}},
+ EncodingSettingsTestParameters{
+ .codec_type = "AV1",
+ .scalability_mode = "L3T3",
+ .bitrate_kbps = {100},
+ .expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}},
+ EncodingSettingsTestParameters{
+ .codec_type = "AV1",
+ .scalability_mode = "L3T3",
+ .bitrate_kbps = {10000},
+ .expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249,
+ 452}},
+ EncodingSettingsTestParameters{
+ .codec_type = "AV1",
+ .scalability_mode = "L3T3",
+ .bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
+ .expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
+ 900}}));
+
} // namespace test
} // namespace webrtc
diff --git a/third_party/libwebrtc/video/BUILD.gn b/third_party/libwebrtc/video/BUILD.gn
index 2d6d8ab10c..b97d4af5bb 100644
--- a/third_party/libwebrtc/video/BUILD.gn
+++ b/third_party/libwebrtc/video/BUILD.gn
@@ -519,6 +519,7 @@ if (rtc_include_tests) {
"../api:rtc_event_log_output_file",
"../api:test_dependency_factory",
"../api:video_quality_test_fixture_api",
+ "../api/environment",
"../api/numerics",
"../api/rtc_event_log:rtc_event_log_factory",
"../api/task_queue",
@@ -830,6 +831,7 @@ if (rtc_include_tests) {
"../api:libjingle_peerconnection_api",
"../api:mock_fec_controller_override",
"../api:mock_frame_decryptor",
+ "../api:mock_frame_transformer",
"../api:mock_video_codec_factory",
"../api:mock_video_decoder",
"../api:mock_video_encoder",
@@ -947,7 +949,6 @@ if (rtc_include_tests) {
"../test:fileutils",
"../test:frame_generator_capturer",
"../test:frame_utils",
- "../test:mock_frame_transformer",
"../test:mock_transport",
"../test:null_transport",
"../test:rtp_test_utils",
diff --git a/third_party/libwebrtc/video/end_to_end_tests/codec_tests.cc b/third_party/libwebrtc/video/end_to_end_tests/codec_tests.cc
index 60a0bc8a15..e9ec7d541f 100644
--- a/third_party/libwebrtc/video/end_to_end_tests/codec_tests.cc
+++ b/third_party/libwebrtc/video/end_to_end_tests/codec_tests.cc
@@ -196,9 +196,11 @@ TEST_F(CodecEndToEndTest, SendsAndReceivesMultiplex) {
&internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
});
test::FunctionVideoDecoderFactory decoder_factory(
- [&internal_decoder_factory]() {
+ [&internal_decoder_factory](const Environment& env,
+ const SdpVideoFormat& /*format*/) {
return std::make_unique<MultiplexDecoderAdapter>(
- &internal_decoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
+ env, &internal_decoder_factory,
+ SdpVideoFormat(cricket::kVp9CodecName));
});
CodecObserver test(5, kVideoRotation_0, absl::nullopt, "multiplex",
@@ -215,9 +217,11 @@ TEST_F(CodecEndToEndTest, SendsAndReceivesMultiplexVideoRotation90) {
&internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
});
test::FunctionVideoDecoderFactory decoder_factory(
- [&internal_decoder_factory]() {
+ [&internal_decoder_factory](const Environment& env,
+ const SdpVideoFormat& /*format*/) {
return std::make_unique<MultiplexDecoderAdapter>(
- &internal_decoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
+ env, &internal_decoder_factory,
+ SdpVideoFormat(cricket::kVp9CodecName));
});
CodecObserver test(5, kVideoRotation_90, absl::nullopt, "multiplex",
&encoder_factory, &decoder_factory);
diff --git a/third_party/libwebrtc/video/end_to_end_tests/multi_codec_receive_tests.cc b/third_party/libwebrtc/video/end_to_end_tests/multi_codec_receive_tests.cc
index 307b5085c9..e236af007b 100644
--- a/third_party/libwebrtc/video/end_to_end_tests/multi_codec_receive_tests.cc
+++ b/third_party/libwebrtc/video/end_to_end_tests/multi_codec_receive_tests.cc
@@ -213,7 +213,8 @@ void MultiCodecReceiveTest::RunTestWithCodecs(
return nullptr;
});
test::FunctionVideoDecoderFactory decoder_factory(
- [](const SdpVideoFormat& format) -> std::unique_ptr<VideoDecoder> {
+ [](const Environment& env,
+ const SdpVideoFormat& format) -> std::unique_ptr<VideoDecoder> {
if (format.name == "VP8") {
return VP8Decoder::Create();
}
diff --git a/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc b/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc
index 077f522d41..ae78ef8eef 100644
--- a/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc
+++ b/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc
@@ -302,8 +302,12 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
frames_decryptable_(false),
absolute_capture_time_interpolator_(clock) {
packet_sequence_checker_.Detach();
- if (packet_router_)
- packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(), config_.rtp.remb);
+ if (packet_router_) {
+ // Do not register as REMB candidate, this is only done when starting to
+ // receive.
+ packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(),
+ /*remb_candidate=*/false);
+ }
RTC_DCHECK(config_.rtp.rtcp_mode != RtcpMode::kOff)
<< "A stream should not be configured with RTCP disabled. This value is "
@@ -814,6 +818,7 @@ void RtpVideoStreamReceiver2::OnInsertedPacket(
if (packet->is_last_packet_in_frame()) {
auto depacketizer_it = payload_type_map_.find(first_packet->payload_type);
RTC_CHECK(depacketizer_it != payload_type_map_.end());
+ RTC_CHECK(depacketizer_it->second);
rtc::scoped_refptr<EncodedImageBuffer> bitstream =
depacketizer_it->second->AssembleFrame(payloads);
@@ -1278,11 +1283,23 @@ void RtpVideoStreamReceiver2::SignalNetworkState(NetworkState state) {
void RtpVideoStreamReceiver2::StartReceive() {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ if (!receiving_ && packet_router_) {
+ // Change REMB candidate egibility.
+ packet_router_->RemoveReceiveRtpModule(rtp_rtcp_.get());
+ packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(),
+ /*remb_candidate=*/config_.rtp.remb);
+ }
receiving_ = true;
}
void RtpVideoStreamReceiver2::StopReceive() {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ if (receiving_ && packet_router_) {
+ // Change REMB candidate egibility.
+ packet_router_->RemoveReceiveRtpModule(rtp_rtcp_.get());
+ packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(),
+ /*remb_candidate=*/false);
+ }
receiving_ = false;
}
diff --git a/third_party/libwebrtc/video/rtp_video_stream_receiver2_unittest.cc b/third_party/libwebrtc/video/rtp_video_stream_receiver2_unittest.cc
index f039bf29b1..6962540152 100644
--- a/third_party/libwebrtc/video/rtp_video_stream_receiver2_unittest.cc
+++ b/third_party/libwebrtc/video/rtp_video_stream_receiver2_unittest.cc
@@ -14,6 +14,7 @@
#include <utility>
#include "api/task_queue/task_queue_base.h"
+#include "api/test/mock_frame_transformer.h"
#include "api/video/video_codec_type.h"
#include "api/video/video_frame_type.h"
#include "call/test/mock_rtp_packet_sink_interface.h"
@@ -35,7 +36,6 @@
#include "system_wrappers/include/clock.h"
#include "test/gmock.h"
#include "test/gtest.h"
-#include "test/mock_frame_transformer.h"
#include "test/mock_transport.h"
#include "test/rtcp_packet_parser.h"
#include "test/scoped_key_value_config.h"
diff --git a/third_party/libwebrtc/video/video_quality_test.cc b/third_party/libwebrtc/video/video_quality_test.cc
index 99b722322a..c8331bffec 100644
--- a/third_party/libwebrtc/video/video_quality_test.cc
+++ b/third_party/libwebrtc/video/video_quality_test.cc
@@ -294,15 +294,16 @@ void PressEnterToContinue(TaskQueueBase* /*task_queue*/) {
} // namespace
std::unique_ptr<VideoDecoder> VideoQualityTest::CreateVideoDecoder(
+ const Environment& env,
const SdpVideoFormat& format) {
std::unique_ptr<VideoDecoder> decoder;
if (format.name == "multiplex") {
decoder = std::make_unique<MultiplexDecoderAdapter>(
- decoder_factory_.get(), SdpVideoFormat(cricket::kVp9CodecName));
+ env, decoder_factory_.get(), SdpVideoFormat(cricket::kVp9CodecName));
} else if (format.name == "FakeCodec") {
decoder = webrtc::FakeVideoDecoderFactory::CreateVideoDecoder();
} else {
- decoder = decoder_factory_->CreateVideoDecoder(format);
+ decoder = decoder_factory_->Create(env, format);
}
if (!params_.logging.encoded_frame_base_path.empty()) {
rtc::StringBuilder str;
@@ -375,9 +376,10 @@ VideoQualityTest::VideoQualityTest(
std::unique_ptr<InjectionComponents> injection_components)
: clock_(Clock::GetRealTimeClock()),
task_queue_factory_(CreateDefaultTaskQueueFactory()),
- video_decoder_factory_([this](const SdpVideoFormat& format) {
- return this->CreateVideoDecoder(format);
- }),
+ video_decoder_factory_(
+ [this](const Environment& env, const SdpVideoFormat& format) {
+ return this->CreateVideoDecoder(env, format);
+ }),
video_encoder_factory_([this](const SdpVideoFormat& format) {
return this->CreateVideoEncoder(format, nullptr);
}),
diff --git a/third_party/libwebrtc/video/video_quality_test.h b/third_party/libwebrtc/video/video_quality_test.h
index 63fa4813f0..c5e63ddf48 100644
--- a/third_party/libwebrtc/video/video_quality_test.h
+++ b/third_party/libwebrtc/video/video_quality_test.h
@@ -15,6 +15,7 @@
#include <string>
#include <vector>
+#include "api/environment/environment.h"
#include "api/fec_controller.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
#include "api/task_queue/task_queue_base.h"
@@ -79,6 +80,7 @@ class VideoQualityTest : public test::CallTest,
size_t video_idx);
void SetupThumbnailCapturers(size_t num_thumbnail_streams);
std::unique_ptr<VideoDecoder> CreateVideoDecoder(
+ const Environment& env,
const SdpVideoFormat& format);
std::unique_ptr<VideoEncoder> CreateVideoEncoder(const SdpVideoFormat& format,
VideoAnalyzer* analyzer);
diff --git a/third_party/libwebrtc/video/video_receive_stream2.cc b/third_party/libwebrtc/video/video_receive_stream2.cc
index 8675ab9979..ce65ec4186 100644
--- a/third_party/libwebrtc/video/video_receive_stream2.cc
+++ b/third_party/libwebrtc/video/video_receive_stream2.cc
@@ -520,7 +520,7 @@ void VideoReceiveStream2::CreateAndRegisterExternalDecoder(
TRACE_EVENT0("webrtc",
"VideoReceiveStream2::CreateAndRegisterExternalDecoder");
std::unique_ptr<VideoDecoder> video_decoder =
- config_.decoder_factory->CreateVideoDecoder(decoder.video_format);
+ config_.decoder_factory->Create(env_, decoder.video_format);
// If we still have no valid decoder, we have to create a "Null" decoder
// that ignores all calls. The reason we can get into this state is that the
// old decoder factory interface doesn't have a way to query supported
diff --git a/third_party/libwebrtc/video/video_receive_stream2_unittest.cc b/third_party/libwebrtc/video/video_receive_stream2_unittest.cc
index 50e00aa31b..221d17b5be 100644
--- a/third_party/libwebrtc/video/video_receive_stream2_unittest.cc
+++ b/third_party/libwebrtc/video/video_receive_stream2_unittest.cc
@@ -205,10 +205,9 @@ class VideoReceiveStream2Test : public ::testing::TestWithParam<bool> {
time_controller_.GetMainThread()),
h264_decoder_factory_(&mock_decoder_) {
// By default, mock decoder factory is backed by VideoDecoderProxyFactory.
- ON_CALL(mock_h264_decoder_factory_, CreateVideoDecoder)
- .WillByDefault(
- Invoke(&h264_decoder_factory_,
- &test::VideoDecoderProxyFactory::CreateVideoDecoder));
+ ON_CALL(mock_h264_decoder_factory_, Create)
+ .WillByDefault(Invoke(&h264_decoder_factory_,
+ &test::VideoDecoderProxyFactory::Create));
// By default, mock decode will wrap the fake decoder.
ON_CALL(mock_decoder_, Configure)
@@ -459,7 +458,7 @@ TEST_P(VideoReceiveStream2Test, LazyDecoderCreation) {
rtppacket.SetTimestamp(0);
// No decoders are created by default.
- EXPECT_CALL(mock_h264_decoder_factory_, CreateVideoDecoder(_)).Times(0);
+ EXPECT_CALL(mock_h264_decoder_factory_, Create).Times(0);
video_receive_stream_->Start();
time_controller_.AdvanceTime(TimeDelta::Zero());
@@ -467,9 +466,8 @@ TEST_P(VideoReceiveStream2Test, LazyDecoderCreation) {
testing::Mock::VerifyAndClearExpectations(&mock_h264_decoder_factory_));
// Verify that the decoder is created when we receive payload data and tries
// to decode a frame.
- EXPECT_CALL(
- mock_h264_decoder_factory_,
- CreateVideoDecoder(Field(&SdpVideoFormat::name, testing::Eq("H264"))));
+ EXPECT_CALL(mock_h264_decoder_factory_,
+ Create(_, Field(&SdpVideoFormat::name, Eq("H264"))));
EXPECT_CALL(mock_decoder_, Configure);
EXPECT_CALL(mock_decoder_, RegisterDecodeCompleteCallback);
EXPECT_CALL(mock_decoder_, Decode(_, _));
diff --git a/third_party/libwebrtc/video/video_send_stream_impl.cc b/third_party/libwebrtc/video/video_send_stream_impl.cc
index 23dbb7177f..ec63b51816 100644
--- a/third_party/libwebrtc/video/video_send_stream_impl.cc
+++ b/third_party/libwebrtc/video/video_send_stream_impl.cc
@@ -362,6 +362,15 @@ std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
encoder_selector);
}
+bool HasActiveEncodings(const VideoEncoderConfig& config) {
+ for (const VideoStream& stream : config.simulcast_layers) {
+ if (stream.active) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace
PacingConfig::PacingConfig(const FieldTrialsView& field_trials)
@@ -438,6 +447,7 @@ VideoSendStreamImpl::VideoSendStreamImpl(
timed_out_(false),
bitrate_allocator_(bitrate_allocator),
+ has_active_encodings_(HasActiveEncodings(encoder_config)),
disable_padding_(true),
max_padding_bitrate_(0),
encoder_min_bitrate_bps_(0),
@@ -512,6 +522,7 @@ VideoSendStreamImpl::~VideoSendStreamImpl() {
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_LOG(LS_INFO) << "~VideoSendStreamImpl: " << config_.ToString();
RTC_DCHECK(!started());
+ RTC_DCHECK(!IsRunning());
transport_->DestroyRtpVideoSender(rtp_video_sender_);
}
@@ -545,6 +556,13 @@ void VideoSendStreamImpl::ReconfigureVideoEncoder(
RTC_DCHECK_EQ(content_type_, config.content_type);
RTC_LOG(LS_VERBOSE) << "Encoder config: " << config.ToString()
<< " VideoSendStream config: " << config_.ToString();
+
+ has_active_encodings_ = HasActiveEncodings(config);
+ if (has_active_encodings_ && rtp_video_sender_->IsActive() && !IsRunning()) {
+ StartupVideoSendStream();
+ } else if (!has_active_encodings_ && IsRunning()) {
+ StopVideoSendStream();
+ }
video_stream_encoder_->ConfigureEncoder(
std::move(config),
config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp),
@@ -609,40 +627,24 @@ bool VideoSendStreamImpl::started() {
}
void VideoSendStreamImpl::Start() {
- const std::vector<bool> active_layers(config_.rtp.ssrcs.size(), true);
- StartPerRtpStream(active_layers);
-}
-
-void VideoSendStreamImpl::StartPerRtpStream(
- const std::vector<bool> active_layers) {
RTC_DCHECK_RUN_ON(&thread_checker_);
-
- rtc::StringBuilder active_layers_string;
- active_layers_string << "{";
- for (size_t i = 0; i < active_layers.size(); ++i) {
- if (active_layers[i]) {
- active_layers_string << "1";
- } else {
- active_layers_string << "0";
- }
- if (i < active_layers.size() - 1) {
- active_layers_string << ", ";
- }
- }
- active_layers_string << "}";
- RTC_LOG(LS_INFO) << "StartPerRtpStream: " << active_layers_string.str();
-
- bool previously_active = rtp_video_sender_->IsActive();
- rtp_video_sender_->SetActiveModules(active_layers);
- if (!rtp_video_sender_->IsActive() && previously_active) {
- StopVideoSendStream();
- } else if (rtp_video_sender_->IsActive() && !previously_active) {
+ // This sender is allowed to send RTP packets. Start monitoring and allocating
+ // a rate if there is also active encodings. (has_active_encodings_).
+ rtp_video_sender_->SetSending(true);
+ if (!IsRunning() && has_active_encodings_) {
StartupVideoSendStream();
}
}
+bool VideoSendStreamImpl::IsRunning() const {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ return check_encoder_activity_task_.Running();
+}
+
void VideoSendStreamImpl::StartupVideoSendStream() {
RTC_DCHECK_RUN_ON(&thread_checker_);
+ RTC_DCHECK(rtp_video_sender_->IsActive());
+ RTC_DCHECK(has_active_encodings_);
bitrate_allocator_->AddObserver(this, GetAllocationConfig());
// Start monitoring encoder activity.
@@ -679,8 +681,10 @@ void VideoSendStreamImpl::Stop() {
return;
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
- rtp_video_sender_->Stop();
- StopVideoSendStream();
+ rtp_video_sender_->SetSending(false);
+ if (IsRunning()) {
+ StopVideoSendStream();
+ }
}
void VideoSendStreamImpl::StopVideoSendStream() {
@@ -761,7 +765,7 @@ void VideoSendStreamImpl::OnVideoLayersAllocationUpdated(
void VideoSendStreamImpl::SignalEncoderActive() {
RTC_DCHECK_RUN_ON(&thread_checker_);
- if (rtp_video_sender_->IsActive()) {
+ if (IsRunning()) {
RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
bitrate_allocator_->AddObserver(this, GetAllocationConfig());
}
@@ -805,7 +809,9 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
double stream_bitrate_priority_sum = 0;
for (const auto& stream : streams) {
// We don't want to allocate more bitrate than needed to inactive streams.
- encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
+ if (stream.active) {
+ encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
+ }
if (stream.bitrate_priority) {
RTC_DCHECK_GT(*stream.bitrate_priority, 0);
stream_bitrate_priority_sum += *stream.bitrate_priority;
@@ -833,7 +839,7 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
rtp_video_sender_->SetEncodingData(streams[0].width, streams[0].height,
num_temporal_layers);
- if (rtp_video_sender_->IsActive()) {
+ if (IsRunning()) {
// The send stream is started already. Update the allocator with new
// bitrate limits.
bitrate_allocator_->AddObserver(this, GetAllocationConfig());
diff --git a/third_party/libwebrtc/video/video_send_stream_impl.h b/third_party/libwebrtc/video/video_send_stream_impl.h
index 758e12c095..8cff4b8822 100644
--- a/third_party/libwebrtc/video/video_send_stream_impl.h
+++ b/third_party/libwebrtc/video/video_send_stream_impl.h
@@ -96,7 +96,6 @@ class VideoSendStreamImpl : public webrtc::VideoSendStream,
// webrtc::VideoSendStream implementation.
void Start() override;
- void StartPerRtpStream(std::vector<bool> active_layers) override;
void Stop() override;
bool started() override;
@@ -182,6 +181,9 @@ class VideoSendStreamImpl : public webrtc::VideoSendStream,
void ConfigureSsrcs();
void SignalEncoderTimedOut();
void SignalEncoderActive();
+ // A video send stream is running if VideoSendStream::Start has been invoked
+ // and there is an active encoding.
+ bool IsRunning() const;
MediaStreamAllocationConfig GetAllocationConfig() const
RTC_RUN_ON(thread_checker_);
@@ -212,6 +214,7 @@ class VideoSendStreamImpl : public webrtc::VideoSendStream,
BitrateAllocatorInterface* const bitrate_allocator_;
+ bool has_active_encodings_ RTC_GUARDED_BY(thread_checker_);
bool disable_padding_ RTC_GUARDED_BY(thread_checker_);
int max_padding_bitrate_ RTC_GUARDED_BY(thread_checker_);
int encoder_min_bitrate_bps_ RTC_GUARDED_BY(thread_checker_);
diff --git a/third_party/libwebrtc/video/video_send_stream_impl_unittest.cc b/third_party/libwebrtc/video/video_send_stream_impl_unittest.cc
index ba492ae66f..f6b43cb958 100644
--- a/third_party/libwebrtc/video/video_send_stream_impl_unittest.cc
+++ b/third_party/libwebrtc/video/video_send_stream_impl_unittest.cc
@@ -54,6 +54,7 @@
#include "video/send_delay_stats.h"
#include "video/send_statistics_proxy.h"
#include "video/test/mock_video_stream_encoder.h"
+#include "video/video_stream_encoder.h"
#include "video/video_stream_encoder_interface.h"
namespace webrtc {
@@ -69,10 +70,13 @@ namespace internal {
namespace {
using ::testing::_;
using ::testing::AllOf;
+using ::testing::AnyNumber;
using ::testing::Field;
using ::testing::Invoke;
+using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
+using ::testing::SaveArg;
constexpr int64_t kDefaultInitialBitrateBps = 333000;
const double kDefaultBitratePriority = 0.5;
@@ -85,8 +89,7 @@ std::string GetAlrProbingExperimentString() {
}
class MockRtpVideoSender : public RtpVideoSenderInterface {
public:
- MOCK_METHOD(void, SetActiveModules, (const std::vector<bool>&), (override));
- MOCK_METHOD(void, Stop, (), (override));
+ MOCK_METHOD(void, SetSending, (bool sending), (override));
MOCK_METHOD(bool, IsActive, (), (override));
MOCK_METHOD(void, OnNetworkAvailability, (bool), (override));
MOCK_METHOD((std::map<uint32_t, RtpState>),
@@ -156,37 +159,31 @@ class VideoSendStreamImplTest : public ::testing::Test {
.WillRepeatedly(Return(&packet_router_));
EXPECT_CALL(transport_controller_, CreateRtpVideoSender)
.WillRepeatedly(Return(&rtp_video_sender_));
- ON_CALL(rtp_video_sender_, Stop()).WillByDefault(::testing::Invoke([&] {
- active_modules_.clear();
+ ON_CALL(rtp_video_sender_, IsActive()).WillByDefault(Invoke([&]() {
+ return rtp_sending_;
}));
- ON_CALL(rtp_video_sender_, IsActive())
- .WillByDefault(::testing::Invoke([&]() {
- for (bool enabled : active_modules_) {
- if (enabled)
- return true;
- }
- return false;
- }));
- ON_CALL(rtp_video_sender_, SetActiveModules)
- .WillByDefault(::testing::SaveArg<0>(&active_modules_));
+ ON_CALL(rtp_video_sender_, SetSending)
+ .WillByDefault(SaveArg<0>(&rtp_sending_));
}
~VideoSendStreamImplTest() {}
- std::unique_ptr<VideoSendStreamImpl> CreateVideoSendStreamImpl(
- int initial_encoder_max_bitrate,
- double initial_encoder_bitrate_priority,
- VideoEncoderConfig::ContentType content_type,
- absl::optional<std::string> codec = std::nullopt) {
- EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_))
- .WillOnce(Return(123000));
-
+ VideoEncoderConfig TestVideoEncoderConfig(
+ VideoEncoderConfig::ContentType content_type =
+ VideoEncoderConfig::ContentType::kRealtimeVideo,
+ int initial_encoder_max_bitrate = kDefaultInitialBitrateBps,
+ double initial_encoder_bitrate_priority = kDefaultBitratePriority) {
VideoEncoderConfig encoder_config;
encoder_config.max_bitrate_bps = initial_encoder_max_bitrate;
encoder_config.bitrate_priority = initial_encoder_bitrate_priority;
encoder_config.content_type = content_type;
- if (codec) {
- config_.rtp.payload_name = *codec;
- }
+ encoder_config.simulcast_layers.push_back(VideoStream());
+ encoder_config.simulcast_layers.back().active = true;
+ return encoder_config;
+ }
+
+ std::unique_ptr<VideoSendStreamImpl> CreateVideoSendStreamImpl(
+ VideoEncoderConfig encoder_config) {
+ EXPECT_CALL(bitrate_allocator_, GetStartBitrate).WillOnce(Return(123000));
std::map<uint32_t, RtpState> suspended_ssrcs;
std::map<uint32_t, RtpPayloadState> suspended_payload_states;
@@ -200,7 +197,7 @@ class VideoSendStreamImplTest : public ::testing::Test {
/*num_cpu_cores=*/1, time_controller_.GetTaskQueueFactory(),
/*call_stats=*/nullptr, &transport_controller_,
/*metronome=*/nullptr, &bitrate_allocator_, &send_delay_stats_,
- /*event_log=*/nullptr, config_.Copy(), encoder_config.Copy(),
+ /*event_log=*/nullptr, config_.Copy(), std::move(encoder_config),
suspended_ssrcs, suspended_payload_states,
/*fec_controller=*/nullptr, field_trials_,
std::move(video_stream_encoder));
@@ -221,7 +218,7 @@ class VideoSendStreamImplTest : public ::testing::Test {
NiceMock<MockBitrateAllocator> bitrate_allocator_;
NiceMock<MockVideoStreamEncoder>* video_stream_encoder_ = nullptr;
NiceMock<MockRtpVideoSender> rtp_video_sender_;
- std::vector<bool> active_modules_;
+ bool rtp_sending_ = false;
RtcEventLogNull event_log_;
VideoSendStream::Config config_;
@@ -231,23 +228,97 @@ class VideoSendStreamImplTest : public ::testing::Test {
PacketRouter packet_router_;
};
-TEST_F(VideoSendStreamImplTest, RegistersAsBitrateObserverOnStart) {
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo);
- const bool kSuspend = false;
- config_.suspend_below_min_bitrate = kSuspend;
+TEST_F(VideoSendStreamImplTest,
+ NotRegistersAsBitrateObserverOnStartIfNoActiveEncodings) {
+ VideoEncoderConfig encoder_config = TestVideoEncoderConfig();
+ encoder_config.simulcast_layers[0].active = false;
+ auto vss_impl = CreateVideoSendStreamImpl(std::move(encoder_config));
+ EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _)).Times(0);
+ EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(0);
+
+ vss_impl->Start();
+ time_controller_.AdvanceTime(TimeDelta::Zero());
+ vss_impl->Stop();
+}
+
+TEST_F(VideoSendStreamImplTest,
+ RegistersAsBitrateObserverOnStartIfHasActiveEncodings) {
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
+
+ EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _));
+ vss_impl->Start();
+ time_controller_.AdvanceTime(TimeDelta::Zero());
+
+ EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
+ vss_impl->Stop();
+}
+
+TEST_F(VideoSendStreamImplTest,
+ DeRegistersAsBitrateObserverIfNoActiveEncodings) {
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
+ EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _));
+ vss_impl->Start();
+ time_controller_.AdvanceTime(TimeDelta::Zero());
+
+ EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
+ VideoEncoderConfig no_active_encodings = TestVideoEncoderConfig();
+ no_active_encodings.simulcast_layers[0].active = false;
+
+ vss_impl->ReconfigureVideoEncoder(std::move(no_active_encodings));
+
+ time_controller_.AdvanceTime(TimeDelta::Zero());
+ ::testing::Mock::VerifyAndClearExpectations(&bitrate_allocator_);
+
+ vss_impl->Stop();
+}
+
+TEST_F(VideoSendStreamImplTest,
+ DoNotRegistersAsBitrateObserverOnStrayEncodedImage) {
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
+
+ EncodedImage encoded_image;
+ CodecSpecificInfo codec_specific;
+ ON_CALL(rtp_video_sender_, OnEncodedImage)
+ .WillByDefault(Return(
+ EncodedImageCallback::Result(EncodedImageCallback::Result::OK)));
+
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
- .WillOnce(Invoke(
- [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
- EXPECT_EQ(config.min_bitrate_bps, 0u);
- EXPECT_EQ(config.max_bitrate_bps, kDefaultInitialBitrateBps);
- EXPECT_EQ(config.pad_up_bitrate_bps, 0u);
- EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
- EXPECT_EQ(config.bitrate_priority, kDefaultBitratePriority);
- }));
- vss_impl->StartPerRtpStream({true});
+ .Times(AnyNumber());
+ vss_impl->Start();
+ time_controller_.AdvanceTime(TimeDelta::Zero());
+
+ // VideoSendStreamImpl gets an allocated bitrate.
+ const uint32_t kBitrateBps = 100000;
+ EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
+ .Times(1)
+ .WillOnce(Return(kBitrateBps));
+ static_cast<BitrateAllocatorObserver*>(vss_impl.get())
+ ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
+ // A frame is encoded.
+ encoder_queue_->PostTask([&] {
+ static_cast<EncodedImageCallback*>(vss_impl.get())
+ ->OnEncodedImage(encoded_image, &codec_specific);
+ });
+
+ // Expect allocation to be removed if encoder stop producing frames.
EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
+ time_controller_.AdvanceTime(TimeDelta::Seconds(5));
+ Mock::VerifyAndClearExpectations(&bitrate_allocator_);
+
+ EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _)).Times(0);
+
+ VideoEncoderConfig no_active_encodings = TestVideoEncoderConfig();
+ no_active_encodings.simulcast_layers[0].active = false;
+ vss_impl->ReconfigureVideoEncoder(std::move(no_active_encodings));
+
+ // Expect that allocation in not resumed if a stray encoded image is received.
+ encoder_queue_->PostTask([&] {
+ static_cast<EncodedImageCallback*>(vss_impl.get())
+ ->OnEncodedImage(encoded_image, &codec_specific);
+ });
+
+ time_controller_.AdvanceTime(TimeDelta::Zero());
+
vss_impl->Stop();
}
@@ -259,11 +330,9 @@ TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChange) {
config_.rtp.ssrcs.emplace_back(1);
config_.rtp.ssrcs.emplace_back(2);
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo);
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
// QVGA + VGA configuration matching defaults in
// media/engine/simulcast.cc.
@@ -326,9 +395,8 @@ TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChangeWithAlr) {
config_.rtp.ssrcs.emplace_back(2);
auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kScreen);
- vss_impl->StartPerRtpStream({true});
+ TestVideoEncoderConfig(VideoEncoderConfig::ContentType::kScreen));
+ vss_impl->Start();
// Simulcast screenshare.
VideoStream low_stream;
@@ -388,11 +456,9 @@ TEST_F(VideoSendStreamImplTest,
config_.rtp.ssrcs.emplace_back(1);
config_.rtp.ssrcs.emplace_back(2);
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo);
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
// 2-layer video simulcast.
VideoStream low_stream;
low_stream.width = 320;
@@ -451,31 +517,28 @@ TEST_F(VideoSendStreamImplTest, SetsScreensharePacingFactorWithFeedback) {
SetPacingFactor(kAlrProbingExperimentPaceMultiplier))
.Times(1);
auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kScreen);
- vss_impl->StartPerRtpStream({true});
+ TestVideoEncoderConfig(VideoEncoderConfig::ContentType::kScreen));
+ vss_impl->Start();
vss_impl->Stop();
}
TEST_F(VideoSendStreamImplTest, DoesNotSetPacingFactorWithoutFeedback) {
test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kScreen);
+ TestVideoEncoderConfig(VideoEncoderConfig::ContentType::kScreen));
EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
vss_impl->Stop();
}
TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationWhenEnabled) {
auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kScreen);
+ TestVideoEncoderConfig(VideoEncoderConfig::ContentType::kScreen));
EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
VideoStreamEncoderInterface::EncoderSink* const sink =
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get());
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
// Populate a test instance of video bitrate allocation.
VideoBitrateAllocation alloc;
alloc.SetBitrate(0, 0, 10000);
@@ -515,9 +578,8 @@ TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationWhenEnabled) {
TEST_F(VideoSendStreamImplTest, ThrottlesVideoBitrateAllocationWhenTooSimilar) {
auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kScreen);
- vss_impl->StartPerRtpStream({true});
+ TestVideoEncoderConfig(VideoEncoderConfig::ContentType::kScreen));
+ vss_impl->Start();
// Unpause encoder, to allows allocations to be passed through.
const uint32_t kBitrateBps = 100000;
EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
@@ -574,10 +636,9 @@ TEST_F(VideoSendStreamImplTest, ThrottlesVideoBitrateAllocationWhenTooSimilar) {
TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationOnLayerChange) {
auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kScreen);
+ TestVideoEncoderConfig(VideoEncoderConfig::ContentType::kScreen));
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
// Unpause encoder, to allows allocations to be passed through.
const uint32_t kBitrateBps = 100000;
EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
@@ -616,9 +677,8 @@ TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationOnLayerChange) {
TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationAfterTimeout) {
auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kScreen);
- vss_impl->StartPerRtpStream({true});
+ TestVideoEncoderConfig(VideoEncoderConfig::ContentType::kScreen));
+ vss_impl->Start();
const uint32_t kBitrateBps = 100000;
// Unpause encoder, to allows allocations to be passed through.
EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
@@ -720,15 +780,13 @@ TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationAfterTimeout) {
}
TEST_F(VideoSendStreamImplTest, PriorityBitrateConfigInactiveByDefault) {
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo);
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
EXPECT_CALL(
bitrate_allocator_,
AddObserver(
vss_impl.get(),
Field(&MediaStreamAllocationConfig::priority_bitrate_bps, 0)));
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
vss_impl->Stop();
}
@@ -736,15 +794,14 @@ TEST_F(VideoSendStreamImplTest, PriorityBitrateConfigInactiveByDefault) {
TEST_F(VideoSendStreamImplTest, PriorityBitrateConfigAffectsAV1) {
test::ScopedFieldTrials override_priority_bitrate(
"WebRTC-AV1-OverridePriorityBitrate/bitrate:20000/");
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo, "AV1");
+ config_.rtp.payload_name = "AV1";
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
EXPECT_CALL(
bitrate_allocator_,
AddObserver(
vss_impl.get(),
Field(&MediaStreamAllocationConfig::priority_bitrate_bps, 20000)));
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
vss_impl->Stop();
}
@@ -765,16 +822,15 @@ TEST_F(VideoSendStreamImplTest,
test::ScopedFieldTrials override_priority_bitrate(
"WebRTC-AV1-OverridePriorityBitrate/bitrate:20000/");
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo, "AV1");
+ config_.rtp.payload_name = "AV1";
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
EXPECT_CALL(
bitrate_allocator_,
AddObserver(
vss_impl.get(),
Field(&MediaStreamAllocationConfig::priority_bitrate_bps, 20000)))
.Times(2);
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
encoder_queue_->PostTask([&] {
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
@@ -794,10 +850,9 @@ TEST_F(VideoSendStreamImplTest, CallsVideoStreamEncoderOnBitrateUpdate) {
config_.suspend_below_min_bitrate = kSuspend;
config_.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
1);
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo);
- vss_impl->StartPerRtpStream({true});
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
+
+ vss_impl->Start();
VideoStream qvga_stream;
qvga_stream.width = 320;
qvga_stream.height = 180;
@@ -893,9 +948,7 @@ TEST_F(VideoSendStreamImplTest, CallsVideoStreamEncoderOnBitrateUpdate) {
TEST_F(VideoSendStreamImplTest, DisablesPaddingOnPausedEncoder) {
int padding_bitrate = 0;
- std::unique_ptr<VideoSendStreamImpl> vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo);
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
// Capture padding bitrate for testing.
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
@@ -928,7 +981,7 @@ TEST_F(VideoSendStreamImplTest, DisablesPaddingOnPausedEncoder) {
int min_transmit_bitrate_bps = 30000;
config_.rtp.ssrcs.emplace_back(1);
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
// Starts without padding.
EXPECT_EQ(0, padding_bitrate);
encoder_queue_->PostTask([&] {
@@ -972,11 +1025,9 @@ TEST_F(VideoSendStreamImplTest, DisablesPaddingOnPausedEncoder) {
}
TEST_F(VideoSendStreamImplTest, KeepAliveOnDroppedFrame) {
- std::unique_ptr<VideoSendStreamImpl> vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
- VideoEncoderConfig::ContentType::kRealtimeVideo);
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig());
EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(0);
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
const uint32_t kBitrateBps = 100000;
EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
.Times(1)
@@ -1015,13 +1066,12 @@ TEST_F(VideoSendStreamImplTest, ConfiguresBitratesForSvc) {
config_.rtp.extensions.emplace_back(
RtpExtension::kTransportSequenceNumberUri, 1);
config_.periodic_alr_bandwidth_probing = test_config.alr;
- auto vss_impl = CreateVideoSendStreamImpl(
- kDefaultInitialBitrateBps, kDefaultBitratePriority,
+ auto vss_impl = CreateVideoSendStreamImpl(TestVideoEncoderConfig(
test_config.screenshare
? VideoEncoderConfig::ContentType::kScreen
- : VideoEncoderConfig::ContentType::kRealtimeVideo);
+ : VideoEncoderConfig::ContentType::kRealtimeVideo));
- vss_impl->StartPerRtpStream({true});
+ vss_impl->Start();
// Svc
VideoStream stream;
@@ -1100,7 +1150,7 @@ TEST_F(VideoSendStreamImplTest, ConfiguresBitratesForSvc) {
->OnEncodedImage(encoded_image, &codec_specific);
});
time_controller_.AdvanceTime(TimeDelta::Zero());
- ::testing::Mock::VerifyAndClearExpectations(&bitrate_allocator_);
+ Mock::VerifyAndClearExpectations(&bitrate_allocator_);
vss_impl->Stop();
}
diff --git a/third_party/libwebrtc/video/video_stream_encoder.cc b/third_party/libwebrtc/video/video_stream_encoder.cc
index d74f440996..afefa0b33f 100644
--- a/third_party/libwebrtc/video/video_stream_encoder.cc
+++ b/third_party/libwebrtc/video/video_stream_encoder.cc
@@ -937,6 +937,8 @@ void VideoStreamEncoder::ConfigureEncoder(VideoEncoderConfig config,
void VideoStreamEncoder::ReconfigureEncoder() {
// Running on the encoder queue.
RTC_DCHECK(pending_encoder_reconfiguration_);
+ RTC_LOG(LS_INFO) << "[VSE] " << __func__
+ << " [encoder_config=" << encoder_config_.ToString() << "]";
bool encoder_reset_required = false;
if (pending_encoder_creation_) {
@@ -1154,37 +1156,38 @@ void VideoStreamEncoder::ReconfigureEncoder() {
char log_stream_buf[4 * 1024];
rtc::SimpleStringBuilder log_stream(log_stream_buf);
- log_stream << "ReconfigureEncoder:\n";
- log_stream << "Simulcast streams:\n";
+ log_stream << "ReconfigureEncoder: simulcast streams: ";
for (size_t i = 0; i < codec.numberOfSimulcastStreams; ++i) {
- log_stream << i << ": " << codec.simulcastStream[i].width << "x"
- << codec.simulcastStream[i].height
- << " min_kbps: " << codec.simulcastStream[i].minBitrate
- << " target_kbps: " << codec.simulcastStream[i].targetBitrate
- << " max_kbps: " << codec.simulcastStream[i].maxBitrate
- << " max_fps: " << codec.simulcastStream[i].maxFramerate
- << " max_qp: " << codec.simulcastStream[i].qpMax
- << " num_tl: " << codec.simulcastStream[i].numberOfTemporalLayers
- << " active: "
- << (codec.simulcastStream[i].active ? "true" : "false") << "\n";
+ log_stream << "{" << i << ": " << codec.simulcastStream[i].width << "x"
+ << codec.simulcastStream[i].height << " "
+ << ScalabilityModeToString(
+ codec.simulcastStream[i].GetScalabilityMode())
+ << ", min_kbps: " << codec.simulcastStream[i].minBitrate
+ << ", target_kbps: " << codec.simulcastStream[i].targetBitrate
+ << ", max_kbps: " << codec.simulcastStream[i].maxBitrate
+ << ", max_fps: " << codec.simulcastStream[i].maxFramerate
+ << ", max_qp: " << codec.simulcastStream[i].qpMax << ", num_tl: "
+ << codec.simulcastStream[i].numberOfTemporalLayers
+ << ", active: "
+ << (codec.simulcastStream[i].active ? "true" : "false") << "}";
}
if (encoder_config_.codec_type == kVideoCodecVP9 ||
encoder_config_.codec_type == kVideoCodecAV1) {
- log_stream << "Spatial layers:\n";
+ log_stream << ", spatial layers: ";
for (int i = 0; i < GetNumSpatialLayers(codec); ++i) {
- log_stream << i << ": " << codec.spatialLayers[i].width << "x"
+ log_stream << "{" << i << ": " << codec.spatialLayers[i].width << "x"
<< codec.spatialLayers[i].height
- << " min_kbps: " << codec.spatialLayers[i].minBitrate
- << " target_kbps: " << codec.spatialLayers[i].targetBitrate
- << " max_kbps: " << codec.spatialLayers[i].maxBitrate
- << " max_fps: " << codec.spatialLayers[i].maxFramerate
- << " max_qp: " << codec.spatialLayers[i].qpMax
- << " num_tl: " << codec.spatialLayers[i].numberOfTemporalLayers
- << " active: "
- << (codec.spatialLayers[i].active ? "true" : "false") << "\n";
+ << ", min_kbps: " << codec.spatialLayers[i].minBitrate
+ << ", target_kbps: " << codec.spatialLayers[i].targetBitrate
+ << ", max_kbps: " << codec.spatialLayers[i].maxBitrate
+ << ", max_fps: " << codec.spatialLayers[i].maxFramerate
+ << ", max_qp: " << codec.spatialLayers[i].qpMax << ", num_tl: "
+ << codec.spatialLayers[i].numberOfTemporalLayers
+ << ", active: "
+ << (codec.spatialLayers[i].active ? "true" : "false") << "}";
}
}
- RTC_LOG(LS_INFO) << log_stream.str();
+ RTC_LOG(LS_INFO) << "[VSE] " << log_stream.str();
codec.startBitrate = std::max(encoder_target_bitrate_bps_.value_or(0) / 1000,
codec.minBitrate);
@@ -1319,7 +1322,7 @@ void VideoStreamEncoder::ReconfigureEncoder() {
<< " max frame rate " << codec.maxFramerate
<< " max payload size " << max_data_payload_length_;
} else {
- RTC_LOG(LS_ERROR) << "Failed to configure encoder.";
+ RTC_LOG(LS_ERROR) << "[VSE] Failed to configure encoder.";
rate_allocator_ = nullptr;
}
@@ -1917,7 +1920,7 @@ void VideoStreamEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
stream_resource_manager_.ConfigureQualityScaler(info);
stream_resource_manager_.ConfigureBandwidthQualityScaler(info);
- RTC_LOG(LS_INFO) << "Encoder info changed to " << info.ToString();
+ RTC_LOG(LS_INFO) << "[VSE] Encoder info changed to " << info.ToString();
}
if (bitrate_adjuster_) {
@@ -2102,6 +2105,8 @@ EncodedImage VideoStreamEncoder::AugmentEncodedImage(
.Parse(codec_type, stream_idx, image_copy.data(), image_copy.size())
.value_or(-1);
}
+ TRACE_EVENT2("webrtc", "VideoStreamEncoder::AugmentEncodedImage",
+ "stream_idx", stream_idx, "qp", image_copy.qp_);
RTC_LOG(LS_VERBOSE) << __func__ << " ntp time " << encoded_image.NtpTimeMs()
<< " stream_idx " << stream_idx << " qp "
<< image_copy.qp_;
diff --git a/third_party/moz.build b/third_party/moz.build
index 27d7794efd..62bb10a1e7 100644
--- a/third_party/moz.build
+++ b/third_party/moz.build
@@ -91,3 +91,5 @@ with Files('wasm2c/**'):
with Files('libsrtp/**'):
BUG_COMPONENT = ('Core', 'WebRTC: Networking')
+with Files("perfetto/**"):
+ BUG_COMPONENT = ("Core", "Performance")
diff --git a/third_party/perfetto/LICENSE b/third_party/perfetto/LICENSE
new file mode 100644
index 0000000000..bb056df223
--- /dev/null
+++ b/third_party/perfetto/LICENSE
@@ -0,0 +1,189 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ Copyright (c) 2017, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ 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.
+
+
diff --git a/third_party/perfetto/moz.build b/third_party/perfetto/moz.build
new file mode 100644
index 0000000000..31bd762c64
--- /dev/null
+++ b/third_party/perfetto/moz.build
@@ -0,0 +1,19 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXPORTS.perfetto += [
+ 'sdk/perfetto.h'
+]
+
+SOURCES += [
+ 'sdk/perfetto.cc'
+]
+
+LOCAL_INCLUDES += [
+ '/third_party/perfetto/sdk',
+]
+
+FINAL_LIBRARY = 'xul'
diff --git a/third_party/perfetto/moz.yaml b/third_party/perfetto/moz.yaml
new file mode 100644
index 0000000000..50c7151faa
--- /dev/null
+++ b/third_party/perfetto/moz.yaml
@@ -0,0 +1,44 @@
+# Version of this schema
+schema: 1
+
+bugzilla:
+ # Bugzilla product and component for this directory and subdirectories
+ product: "Core"
+ component: "Performance"
+
+origin:
+ name: "perfetto"
+ description: "C++ SDK for userspace performance tracing on Linux and Android."
+
+ url: "https://perfetto.dev"
+ license: Apache-2.0
+
+ release: v44.0 (2024-04-10T09:26:48+00:00).
+ revision: v44.0
+
+updatebot:
+ maintainer-phab: denispal
+ maintainer-bz: dpalmeiro@mozilla.com
+ tasks:
+ - type: vendoring
+ enabled: true
+ frequency: release
+
+vendoring:
+ url: https://github.com/google/perfetto
+ source-hosting: github
+ tracking: tag
+ keep:
+ - moz.build
+ - moz_attributes.patch
+ skip-vendoring-steps:
+ - update-moz-build
+ exclude:
+ - '**'
+ include:
+ - sdk/
+ - LICENSE
+ # Add an implicit attribute to EventFinalizer() and use the
+ # asan declarations from "mozilla/MemoryChecking.h".
+ patches:
+ - moz_attributes.patch
diff --git a/third_party/perfetto/moz_attributes.patch b/third_party/perfetto/moz_attributes.patch
new file mode 100644
index 0000000000..883c1dbea6
--- /dev/null
+++ b/third_party/perfetto/moz_attributes.patch
@@ -0,0 +1,31 @@
+diff --git a/sdk/perfetto.h b/sdk/perfetto.h
+index 411806567..b64f864a9 100644
+--- a/sdk/perfetto.h
++++ b/sdk/perfetto.h
+@@ -365,8 +365,7 @@
+
+ #if defined(__clang__)
+ #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+-extern "C" void __asan_poison_memory_region(void const volatile*, size_t);
+-extern "C" void __asan_unpoison_memory_region(void const volatile*, size_t);
++#include "mozilla/MemoryChecking.h"
+ #define PERFETTO_ASAN_POISON(a, s) __asan_poison_memory_region((a), (s))
+ #define PERFETTO_ASAN_UNPOISON(a, s) __asan_unpoison_memory_region((a), (s))
+ #else
+@@ -19479,6 +19478,7 @@ class TrackEventDataSource
+ #define PERFETTO_INTERNAL_EVENT_FINALIZER_KEYWORD default
+ #endif
+
++#include <mozilla/Attributes.h>
+ #define PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER(category) \
+ struct PERFETTO_UID(ScopedEvent) { \
+ struct EventFinalizer { \
+@@ -19489,7 +19489,7 @@ class TrackEventDataSource
+ /* TrackEventArgumentFunction in |__VA_ARGS__|. This is required so */ \
+ /* that the scoped event is exactly ONE line and can't escape the */ \
+ /* scope if used in a single line if statement. */ \
+- EventFinalizer(...) {} \
++ MOZ_IMPLICIT EventFinalizer(...) {} \
+ ~EventFinalizer() { TRACE_EVENT_END(category); } \
+ \
+ EventFinalizer(const EventFinalizer&) = delete; \
diff --git a/third_party/perfetto/sdk/perfetto.cc b/third_party/perfetto/sdk/perfetto.cc
new file mode 100644
index 0000000000..7d0c4e86cf
--- /dev/null
+++ b/third_party/perfetto/sdk/perfetto.cc
@@ -0,0 +1,64804 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// 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
+//
+// http://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.
+//
+// This file is automatically generated by gen_amalgamated. Do not edit.
+
+// gen_amalgamated: predefined macros
+#if !defined(PERFETTO_IMPLEMENTATION)
+#define PERFETTO_IMPLEMENTATION
+#endif
+#include "perfetto.h"
+// gen_amalgamated begin source: src/base/default_platform.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/platform.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_PLATFORM_H_
+#define INCLUDE_PERFETTO_EXT_BASE_PLATFORM_H_
+
+namespace perfetto {
+namespace base {
+namespace platform {
+
+// Executed before entering a syscall (e.g. poll, read, write etc) which might
+// block.
+// This is overridden in Google internal builds for dealing with userspace
+// scheduling.
+void BeforeMaybeBlockingSyscall();
+
+// Executed after entering a syscall (e.g. poll, read, write etc) which might
+// block.
+// This is overridden in Google internal builds for dealing with userspace
+// scheduling.
+void AfterMaybeBlockingSyscall();
+
+} // namespace platform
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_PLATFORM_H_
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/platform.h"
+
+namespace perfetto {
+namespace base {
+namespace platform {
+
+// This is a no-op outside of Google3 where we have some custom logic to deal
+// with the userspace scheduler.
+void BeforeMaybeBlockingSyscall() {}
+
+// This is a no-op outside of Google3 where we have some custom logic to deal
+// with the userspace scheduler.
+void AfterMaybeBlockingSyscall() {}
+
+} // namespace platform
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/android_utils.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/android_utils.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_ANDROID_UTILS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_ANDROID_UTILS_H_
+
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+// Returns the value of the Android system property named `name`. If the
+// property does not exist, returns an empty string (a non-existing property is
+// the same as a property with an empty value for this API).
+std::string GetAndroidProp(const char* name);
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_ANDROID_UTILS_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/android_utils.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#include <string>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/system_properties.h>
+#endif
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+std::string GetAndroidProp(const char* name) {
+ std::string ret;
+#if __ANDROID_API__ >= 26
+ const prop_info* pi = __system_property_find(name);
+ if (!pi) {
+ return ret;
+ }
+ __system_property_read_callback(
+ pi,
+ [](void* dst_void, const char*, const char* value, uint32_t) {
+ std::string& dst = *static_cast<std::string*>(dst_void);
+ dst = value;
+ },
+ &ret);
+#else // __ANDROID_API__ < 26
+ char value_buf[PROP_VALUE_MAX];
+ int len = __system_property_get(name, value_buf);
+ if (len > 0 && static_cast<size_t>(len) < sizeof(value_buf)) {
+ ret = std::string(value_buf, static_cast<size_t>(len));
+ }
+#endif
+ return ret;
+}
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/base64.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/base64.h
+// gen_amalgamated begin header: include/perfetto/ext/base/string_view.h
+// gen_amalgamated begin header: include/perfetto/ext/base/hash.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_HASH_H_
+#define INCLUDE_PERFETTO_EXT_BASE_HASH_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+namespace perfetto {
+namespace base {
+
+// A helper class which computes a 64-bit hash of the input data.
+// The algorithm used is FNV-1a as it is fast and easy to implement and has
+// relatively few collisions.
+// WARNING: This hash function should not be used for any cryptographic purpose.
+class Hasher {
+ public:
+ // Creates an empty hash object
+ Hasher() {}
+
+ // Hashes a numeric value.
+ template <
+ typename T,
+ typename std::enable_if<std::is_arithmetic<T>::value, bool>::type = true>
+ void Update(T data) {
+ Update(reinterpret_cast<const char*>(&data), sizeof(data));
+ }
+
+ // Using the loop instead of "Update(str, strlen(str))" to avoid looping twice
+ void Update(const char* str) {
+ for (const auto* p = str; *p; ++p)
+ Update(*p);
+ }
+
+ // Hashes a byte array.
+ void Update(const char* data, size_t size) {
+ for (size_t i = 0; i < size; i++) {
+ result_ ^= static_cast<uint8_t>(data[i]);
+ // Note: Arithmetic overflow of unsigned integers is well defined in C++
+ // standard unlike signed integers.
+ // https://stackoverflow.com/a/41280273
+ result_ *= kFnv1a64Prime;
+ }
+ }
+
+ // Allow hashing anything that has a |data| field, a |size| field,
+ // and has the kHashable trait (e.g., base::StringView).
+ template <typename T, typename = std::enable_if<T::kHashable>>
+ void Update(const T& t) {
+ Update(t.data(), t.size());
+ }
+
+ void Update(const std::string& s) { Update(s.data(), s.size()); }
+
+ uint64_t digest() const { return result_; }
+
+ // Usage:
+ // uint64_t hashed_value = Hash::Combine(33, false, "ABC", 458L, 3u, 'x');
+ template <typename... Ts>
+ static uint64_t Combine(Ts&&... args) {
+ Hasher hasher;
+ hasher.UpdateAll(std::forward<Ts>(args)...);
+ return hasher.digest();
+ }
+
+ // `hasher.UpdateAll(33, false, "ABC")` is shorthand for:
+ // `hasher.Update(33); hasher.Update(false); hasher.Update("ABC");`
+ void UpdateAll() {}
+
+ template <typename T, typename... Ts>
+ void UpdateAll(T&& arg, Ts&&... args) {
+ Update(arg);
+ UpdateAll(std::forward<Ts>(args)...);
+ }
+
+ private:
+ static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325;
+ static constexpr uint64_t kFnv1a64Prime = 0x100000001b3;
+
+ uint64_t result_ = kFnv1a64OffsetBasis;
+};
+
+// This is for using already-hashed key into std::unordered_map and avoid the
+// cost of re-hashing. Example:
+// unordered_map<uint64_t, Value, AlreadyHashed> my_map.
+template <typename T>
+struct AlreadyHashed {
+ size_t operator()(const T& x) const { return static_cast<size_t>(x); }
+};
+
+// base::Hash uses base::Hasher for integer values and falls base to std::hash
+// for other types. This is needed as std::hash for integers is just the
+// identity function and Perfetto uses open-addressing hash table, which are
+// very sensitive to hash quality and are known to degrade in performance
+// when using std::hash.
+template <typename T>
+struct Hash {
+ // Version for ints, using base::Hasher.
+ template <typename U = T>
+ auto operator()(const U& x) ->
+ typename std::enable_if<std::is_arithmetic<U>::value, size_t>::type
+ const {
+ Hasher hash;
+ hash.Update(x);
+ return static_cast<size_t>(hash.digest());
+ }
+
+ // Version for non-ints, falling back to std::hash.
+ template <typename U = T>
+ auto operator()(const U& x) ->
+ typename std::enable_if<!std::is_arithmetic<U>::value, size_t>::type
+ const {
+ return std::hash<U>()(x);
+ }
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_HASH_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_
+#define INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_
+
+#include <string.h>
+
+#include <algorithm>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+
+namespace perfetto {
+namespace base {
+
+// A string-like object that refers to a non-owned piece of memory.
+// Strings are internally NOT null terminated.
+class StringView {
+ public:
+ // Allow hashing with base::Hash.
+ static constexpr bool kHashable = true;
+ static constexpr size_t npos = static_cast<size_t>(-1);
+
+ StringView() : data_(nullptr), size_(0) {}
+ StringView(const StringView&) = default;
+ StringView& operator=(const StringView&) = default;
+ StringView(const char* data, size_t size) : data_(data), size_(size) {
+ PERFETTO_DCHECK(size == 0 || data != nullptr);
+ }
+
+ // Allow implicit conversion from any class that has a |data| and |size| field
+ // and has the kConvertibleToStringView trait (e.g., protozero::ConstChars).
+ template <typename T, typename = std::enable_if<T::kConvertibleToStringView>>
+ StringView(const T& x) : StringView(x.data, x.size) {
+ PERFETTO_DCHECK(x.size == 0 || x.data != nullptr);
+ }
+
+ // Creates a StringView from a null-terminated C string.
+ // Deliberately not "explicit".
+ StringView(const char* cstr) : data_(cstr), size_(strlen(cstr)) {
+ PERFETTO_DCHECK(cstr != nullptr);
+ }
+
+ // This instead has to be explicit, as creating a StringView out of a
+ // std::string can be subtle.
+ explicit StringView(const std::string& str)
+ : data_(str.data()), size_(str.size()) {}
+
+ bool empty() const { return size_ == 0; }
+ size_t size() const { return size_; }
+ const char* data() const { return data_; }
+ const char* begin() const { return data_; }
+ const char* end() const { return data_ + size_; }
+
+ char at(size_t pos) const {
+ PERFETTO_DCHECK(pos < size_);
+ return data_[pos];
+ }
+
+ size_t find(char c, size_t start_pos = 0) const {
+ for (size_t i = start_pos; i < size_; ++i) {
+ if (data_[i] == c)
+ return i;
+ }
+ return npos;
+ }
+
+ size_t find(const StringView& str, size_t start_pos = 0) const {
+ if (start_pos > size())
+ return npos;
+ auto it = std::search(begin() + start_pos, end(), str.begin(), str.end());
+ size_t pos = static_cast<size_t>(it - begin());
+ return pos + str.size() <= size() ? pos : npos;
+ }
+
+ size_t find(const char* str, size_t start_pos = 0) const {
+ return find(StringView(str), start_pos);
+ }
+
+ size_t rfind(char c) const {
+ for (size_t i = size_; i > 0; --i) {
+ if (data_[i - 1] == c)
+ return i - 1;
+ }
+ return npos;
+ }
+
+ StringView substr(size_t pos, size_t count = npos) const {
+ if (pos >= size_)
+ return StringView("", 0);
+ size_t rcount = std::min(count, size_ - pos);
+ return StringView(data_ + pos, rcount);
+ }
+
+ bool CaseInsensitiveEq(const StringView& other) const {
+ if (size() != other.size())
+ return false;
+ if (size() == 0)
+ return true;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return _strnicmp(data(), other.data(), size()) == 0;
+#else
+ return strncasecmp(data(), other.data(), size()) == 0;
+#endif
+ }
+
+ bool StartsWith(const StringView& other) const {
+ if (other.size() == 0)
+ return true;
+ if (size() == 0)
+ return false;
+ if (other.size() > size())
+ return false;
+ return memcmp(data(), other.data(), other.size()) == 0;
+ }
+
+ bool EndsWith(const StringView& other) const {
+ if (other.size() == 0)
+ return true;
+ if (size() == 0)
+ return false;
+ if (other.size() > size())
+ return false;
+ size_t off = size() - other.size();
+ return memcmp(data() + off, other.data(), other.size()) == 0;
+ }
+
+ std::string ToStdString() const {
+ return size_ == 0 ? "" : std::string(data_, size_);
+ }
+
+ uint64_t Hash() const {
+ base::Hasher hasher;
+ hasher.Update(data_, size_);
+ return hasher.digest();
+ }
+
+ private:
+ const char* data_ = nullptr;
+ size_t size_ = 0;
+};
+
+inline bool operator==(const StringView& x, const StringView& y) {
+ if (x.size() != y.size())
+ return false;
+ if (x.size() == 0)
+ return true;
+ return memcmp(x.data(), y.data(), x.size()) == 0;
+}
+
+inline bool operator!=(const StringView& x, const StringView& y) {
+ return !(x == y);
+}
+
+inline bool operator<(const StringView& x, const StringView& y) {
+ auto size = std::min(x.size(), y.size());
+ if (size == 0)
+ return x.size() < y.size();
+ int result = memcmp(x.data(), y.data(), size);
+ return result < 0 || (result == 0 && x.size() < y.size());
+}
+
+inline bool operator>=(const StringView& x, const StringView& y) {
+ return !(x < y);
+}
+
+inline bool operator>(const StringView& x, const StringView& y) {
+ return y < x;
+}
+
+inline bool operator<=(const StringView& x, const StringView& y) {
+ return !(y < x);
+}
+
+} // namespace base
+} // namespace perfetto
+
+template <>
+struct std::hash<::perfetto::base::StringView> {
+ size_t operator()(const ::perfetto::base::StringView& sv) const {
+ return static_cast<size_t>(sv.Hash());
+ }
+};
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_
+// gen_amalgamated begin header: include/perfetto/ext/base/utils.h
+// gen_amalgamated begin header: include/perfetto/ext/base/sys_types.h
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_SYS_TYPES_H_
+#define INCLUDE_PERFETTO_EXT_BASE_SYS_TYPES_H_
+
+// This headers deals with sys types commonly used in the codebase that are
+// missing on Windows.
+
+#include <sys/types.h>
+#include <cstdint>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
+// MinGW has these. clang-cl and MSVC, which use just the Windows SDK, don't.
+using uid_t = int;
+using pid_t = int;
+#endif // !GCC
+
+#if defined(_WIN64)
+using ssize_t = int64_t;
+#else
+using ssize_t = long;
+#endif // _WIN64
+
+#endif // OS_WIN
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && !defined(AID_SHELL)
+// From libcutils' android_filesystem_config.h .
+#define AID_SHELL 2000
+#endif
+
+namespace perfetto {
+namespace base {
+
+// The machine ID used in the tracing core.
+using MachineID = uint32_t;
+// The default value reserved for the host trace.
+constexpr MachineID kDefaultMachineID = 0;
+
+constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
+constexpr pid_t kInvalidPid = static_cast<pid_t>(-1);
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_SYS_TYPES_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_UTILS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_UTILS_H_
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// Even if Windows has errno.h, the all syscall-restart behavior does not apply.
+// Trying to handle EINTR can cause more harm than good if errno is left stale.
+// Chromium does the same.
+#define PERFETTO_EINTR(x) (x)
+#else
+#define PERFETTO_EINTR(x) \
+ ([&] { \
+ decltype(x) eintr_wrapper_result; \
+ do { \
+ eintr_wrapper_result = (x); \
+ } while (eintr_wrapper_result == -1 && errno == EINTR); \
+ return eintr_wrapper_result; \
+ }())
+#endif
+
+namespace perfetto {
+namespace base {
+
+namespace internal {
+extern std::atomic<uint32_t> g_cached_page_size;
+uint32_t GetSysPageSizeSlowpath();
+} // namespace internal
+
+// Returns the system's page size. Use this when dealing with mmap, madvise and
+// similar mm-related syscalls.
+// This function might be called in hot paths. Avoid calling getpagesize() all
+// the times, in many implementations getpagesize() calls sysconf() which is
+// not cheap.
+inline uint32_t GetSysPageSize() {
+ const uint32_t page_size =
+ internal::g_cached_page_size.load(std::memory_order_relaxed);
+ return page_size != 0 ? page_size : internal::GetSysPageSizeSlowpath();
+}
+
+template <typename T, size_t TSize>
+constexpr size_t ArraySize(const T (&)[TSize]) {
+ return TSize;
+}
+
+// Function object which invokes 'free' on its parameter, which must be
+// a pointer. Can be used to store malloc-allocated pointers in std::unique_ptr:
+//
+// std::unique_ptr<int, base::FreeDeleter> foo_ptr(
+// static_cast<int*>(malloc(sizeof(int))));
+struct FreeDeleter {
+ inline void operator()(void* ptr) const { free(ptr); }
+};
+
+template <typename T>
+constexpr T AssumeLittleEndian(T value) {
+#if !PERFETTO_IS_LITTLE_ENDIAN()
+ static_assert(false, "Unimplemented on big-endian archs");
+#endif
+ return value;
+}
+
+// Round up |size| to a multiple of |alignment| (must be a power of two).
+inline constexpr size_t AlignUp(size_t size, size_t alignment) {
+ return (size + alignment - 1) & ~(alignment - 1);
+}
+
+// TODO(primiano): clean this up and move all existing usages to the constexpr
+// version above.
+template <size_t alignment>
+constexpr size_t AlignUp(size_t size) {
+ static_assert((alignment & (alignment - 1)) == 0, "alignment must be a pow2");
+ return AlignUp(size, alignment);
+}
+
+inline bool IsAgain(int err) {
+ return err == EAGAIN || err == EWOULDBLOCK;
+}
+
+// setenv(2)-equivalent. Deals with Windows vs Posix discrepancies.
+void SetEnv(const std::string& key, const std::string& value);
+
+// unsetenv(2)-equivalent. Deals with Windows vs Posix discrepancies.
+void UnsetEnv(const std::string& key);
+
+// Calls mallopt(M_PURGE, 0) on Android. Does nothing on other platforms.
+// This forces the allocator to release freed memory. This is used to work
+// around various Scudo inefficiencies. See b/170217718.
+void MaybeReleaseAllocatorMemToOS();
+
+// geteuid() on POSIX OSes, returns 0 on Windows (See comment in utils.cc).
+uid_t GetCurrentUserId();
+
+// Forks the process.
+// Parent: prints the PID of the child, calls |parent_cb| and exits from the
+// process with its return value.
+// Child: redirects stdio onto /dev/null, chdirs into / and returns.
+void Daemonize(std::function<int()> parent_cb);
+
+// Returns the path of the current executable, e.g. /foo/bar/exe.
+std::string GetCurExecutablePath();
+
+// Returns the directory where the current executable lives in, e.g. /foo/bar.
+// This is independent of cwd().
+std::string GetCurExecutableDir();
+
+// Memory returned by AlignedAlloc() must be freed via AlignedFree() not just
+// free. It makes a difference on Windows where _aligned_malloc() and
+// _aligned_free() must be paired.
+// Prefer using the AlignedAllocTyped() below which takes care of the pairing.
+void* AlignedAlloc(size_t alignment, size_t size);
+void AlignedFree(void*);
+
+// A RAII version of the above, which takes care of pairing Aligned{Alloc,Free}.
+template <typename T>
+struct AlignedDeleter {
+ inline void operator()(T* ptr) const { AlignedFree(ptr); }
+};
+
+// The remove_extent<T> here and below is to allow defining unique_ptr<T[]>.
+// As per https://en.cppreference.com/w/cpp/memory/unique_ptr the Deleter takes
+// always a T*, not a T[]*.
+template <typename T>
+using AlignedUniquePtr =
+ std::unique_ptr<T, AlignedDeleter<typename std::remove_extent<T>::type>>;
+
+template <typename T>
+AlignedUniquePtr<T> AlignedAllocTyped(size_t n_membs) {
+ using TU = typename std::remove_extent<T>::type;
+ return AlignedUniquePtr<T>(
+ static_cast<TU*>(AlignedAlloc(alignof(TU), sizeof(TU) * n_membs)));
+}
+
+// A RAII wrapper to invoke a function when leaving a function/scope.
+template <typename Func>
+class OnScopeExitWrapper {
+ public:
+ explicit OnScopeExitWrapper(Func f) : f_(std::move(f)), active_(true) {}
+ OnScopeExitWrapper(OnScopeExitWrapper&& other) noexcept
+ : f_(std::move(other.f_)), active_(other.active_) {
+ other.active_ = false;
+ }
+ ~OnScopeExitWrapper() {
+ if (active_)
+ f_();
+ }
+
+ private:
+ Func f_;
+ bool active_;
+};
+
+template <typename Func>
+PERFETTO_WARN_UNUSED_RESULT OnScopeExitWrapper<Func> OnScopeExit(Func f) {
+ return OnScopeExitWrapper<Func>(std::move(f));
+}
+
+// Returns a xxd-style hex dump (hex + ascii chars) of the input data.
+std::string HexDump(const void* data, size_t len, size_t bytes_per_line = 16);
+inline std::string HexDump(const std::string& data,
+ size_t bytes_per_line = 16) {
+ return HexDump(data.data(), data.size(), bytes_per_line);
+}
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_UTILS_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_BASE64_H_
+#define INCLUDE_PERFETTO_EXT_BASE_BASE64_H_
+
+#include <optional>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h" // For ssize_t.
+
+namespace perfetto {
+namespace base {
+
+// Returns the length of the destination string (included '=' padding).
+// Does NOT include the size of the string null terminator.
+inline size_t Base64EncSize(size_t src_size) {
+ return (src_size + 2) / 3 * 4;
+}
+
+// Returns the upper bound on the length of the destination buffer.
+// The actual decoded length might be <= the number returned here.
+inline size_t Base64DecSize(size_t src_size) {
+ return (src_size + 3) / 4 * 3;
+}
+
+// Does NOT null-terminate |dst|.
+ssize_t Base64Encode(const void* src,
+ size_t src_size,
+ char* dst,
+ size_t dst_size);
+
+std::string Base64Encode(const void* src, size_t src_size);
+
+inline std::string Base64Encode(StringView sv) {
+ return Base64Encode(sv.data(), sv.size());
+}
+
+// Returns -1 in case of failure.
+ssize_t Base64Decode(const char* src,
+ size_t src_size,
+ uint8_t* dst,
+ size_t dst_size);
+
+std::optional<std::string> Base64Decode(const char* src, size_t src_size);
+
+inline std::optional<std::string> Base64Decode(StringView sv) {
+ return Base64Decode(sv.data(), sv.size());
+}
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_BASE64_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/base64.h"
+
+namespace perfetto {
+namespace base {
+
+namespace {
+
+constexpr char kPadding = '=';
+
+constexpr char kEncTable[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static_assert(sizeof(kEncTable) == (1u << 6) + sizeof('\0'), "Bad table size");
+
+// Maps an ASCII character to its 6-bit value. It only contains translations
+// from '+' to 'z'. Supports the standard (+/) and URL-safe (-_) alphabets.
+constexpr uint8_t kX = 0xff; // Value used for invalid characters
+constexpr uint8_t kDecTable[] = {
+ 62, kX, 62, kX, 63, 52, 53, 54, 55, 56, // 00 - 09
+ 57, 58, 59, 60, 61, kX, kX, kX, 0, kX, // 10 - 19
+ kX, kX, 0, 1, 2, 3, 4, 5, 6, 7, // 20 - 29
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // 30 - 39
+ 18, 19, 20, 21, 22, 23, 24, 25, kX, kX, // 40 - 49
+ kX, kX, 63, kX, 26, 27, 28, 29, 30, 31, // 50 - 59
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, // 60 - 69
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 70 - 79
+};
+constexpr char kMinDecChar = '+';
+constexpr char kMaxDecChar = 'z';
+static_assert(kMaxDecChar - kMinDecChar <= sizeof(kDecTable), "Bad table size");
+
+inline uint8_t DecodeChar(char c) {
+ if (c < kMinDecChar || c > kMaxDecChar)
+ return kX;
+ return kDecTable[c - kMinDecChar];
+}
+
+} // namespace
+
+ssize_t Base64Encode(const void* src,
+ size_t src_size,
+ char* dst,
+ size_t dst_size) {
+ const size_t padded_dst_size = Base64EncSize(src_size);
+ if (dst_size < padded_dst_size)
+ return -1; // Not enough space in output.
+
+ const uint8_t* rd = static_cast<const uint8_t*>(src);
+ const uint8_t* const end = rd + src_size;
+ size_t wr_size = 0;
+ while (rd < end) {
+ uint8_t s[3]{};
+ s[0] = *(rd++);
+ dst[wr_size++] = kEncTable[s[0] >> 2];
+
+ uint8_t carry0 = static_cast<uint8_t>((s[0] & 0x03) << 4);
+ if (PERFETTO_LIKELY(rd < end)) {
+ s[1] = *(rd++);
+ dst[wr_size++] = kEncTable[carry0 | (s[1] >> 4)];
+ } else {
+ dst[wr_size++] = kEncTable[carry0];
+ dst[wr_size++] = kPadding;
+ dst[wr_size++] = kPadding;
+ break;
+ }
+
+ uint8_t carry1 = static_cast<uint8_t>((s[1] & 0x0f) << 2);
+ if (PERFETTO_LIKELY(rd < end)) {
+ s[2] = *(rd++);
+ dst[wr_size++] = kEncTable[carry1 | (s[2] >> 6)];
+ } else {
+ dst[wr_size++] = kEncTable[carry1];
+ dst[wr_size++] = kPadding;
+ break;
+ }
+
+ dst[wr_size++] = kEncTable[s[2] & 0x3f];
+ }
+ PERFETTO_DCHECK(wr_size == padded_dst_size);
+ return static_cast<ssize_t>(padded_dst_size);
+}
+
+std::string Base64Encode(const void* src, size_t src_size) {
+ std::string dst;
+ dst.resize(Base64EncSize(src_size));
+ auto res = Base64Encode(src, src_size, &dst[0], dst.size());
+ PERFETTO_CHECK(res == static_cast<ssize_t>(dst.size()));
+ return dst;
+}
+
+ssize_t Base64Decode(const char* src,
+ size_t src_size,
+ uint8_t* dst,
+ size_t dst_size) {
+ const size_t min_dst_size = Base64DecSize(src_size);
+ if (dst_size < min_dst_size)
+ return -1;
+
+ const char* rd = src;
+ const char* const end = src + src_size;
+ size_t wr_size = 0;
+
+ char s[4]{};
+ while (rd < end) {
+ uint8_t d[4];
+ for (uint32_t j = 0; j < 4; j++) {
+ // Padding is only feasible for the last 2 chars of each group of 4.
+ s[j] = rd < end ? *(rd++) : (j < 2 ? '\0' : kPadding);
+ d[j] = DecodeChar(s[j]);
+ if (d[j] == kX)
+ return -1; // Invalid input char.
+ }
+ dst[wr_size] = static_cast<uint8_t>((d[0] << 2) | (d[1] >> 4));
+ dst[wr_size + 1] = static_cast<uint8_t>((d[1] << 4) | (d[2] >> 2));
+ dst[wr_size + 2] = static_cast<uint8_t>((d[2] << 6) | (d[3]));
+ wr_size += 3;
+ }
+
+ PERFETTO_CHECK(wr_size <= dst_size);
+ wr_size -= (s[3] == kPadding ? 1 : 0) + (s[2] == kPadding ? 1 : 0);
+ return static_cast<ssize_t>(wr_size);
+}
+
+std::optional<std::string> Base64Decode(const char* src, size_t src_size) {
+ std::string dst;
+ dst.resize(Base64DecSize(src_size));
+ auto res = Base64Decode(src, src_size, reinterpret_cast<uint8_t*>(&dst[0]),
+ dst.size());
+ if (res < 0)
+ return std::nullopt; // Decoding error.
+
+ PERFETTO_CHECK(res <= static_cast<ssize_t>(dst.size()));
+ dst.resize(static_cast<size_t>(res));
+ return std::make_optional(dst);
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/crash_keys.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/crash_keys.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_CRASH_KEYS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_CRASH_KEYS_H_
+
+#include <algorithm>
+#include <atomic>
+
+#include <stdint.h>
+#include <string.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+
+// Crash keys are very simple global variables with static-storage that
+// are reported on crash time for managed crashes (CHECK/FATAL/Watchdog).
+// - Translation units can define a CrashKey and register it at some point
+// during initialization.
+// - CrashKey instances must be long-lived. They should really be just global
+// static variable in the anonymous namespace.
+// Example:
+// subsystem_1.cc
+// CrashKey g_client_id("ipc_client_id");
+// ...
+// OnIpcReceived(client_id) {
+// g_client_id.Set(client_id);
+// ... // Process the IPC
+// g_client_id.Clear();
+// }
+// Or equivalently:
+// OnIpcReceived(client_id) {
+// auto scoped_key = g_client_id.SetScoped(client_id);
+// ... // Process the IPC
+// }
+//
+// If a crash happens while processing the IPC, the crash report will
+// have a line "ipc_client_id: 42".
+//
+// Thread safety considerations:
+// CrashKeys can be registered and set/cleared from any thread.
+// There is no compelling use-case to have full acquire/release consistency when
+// setting a key. This means that if a thread crashes immediately after a
+// crash key has been set on another thread, the value printed on the crash
+// report could be incomplete. The code guarantees defined behavior and does
+// not rely on null-terminated string (in the worst case 32 bytes of random
+// garbage will be printed out).
+
+// The tests live in logging_unittest.cc.
+
+namespace perfetto {
+namespace base {
+
+constexpr size_t kCrashKeyMaxStrSize = 32;
+
+// CrashKey instances must be long lived
+class CrashKey {
+ public:
+ class ScopedClear {
+ public:
+ explicit ScopedClear(CrashKey* k) : key_(k) {}
+ ~ScopedClear() {
+ if (key_)
+ key_->Clear();
+ }
+ ScopedClear(const ScopedClear&) = delete;
+ ScopedClear& operator=(const ScopedClear&) = delete;
+ ScopedClear& operator=(ScopedClear&&) = delete;
+ ScopedClear(ScopedClear&& other) noexcept : key_(other.key_) {
+ other.key_ = nullptr;
+ }
+
+ private:
+ CrashKey* key_;
+ };
+
+ // constexpr so it can be used in the anon namespace without requiring a
+ // global constructor.
+ // |name| must be a long-lived string.
+ constexpr explicit CrashKey(const char* name)
+ : registered_{}, type_(Type::kUnset), name_(name), str_value_{} {}
+ CrashKey(const CrashKey&) = delete;
+ CrashKey& operator=(const CrashKey&) = delete;
+ CrashKey(CrashKey&&) = delete;
+ CrashKey& operator=(CrashKey&&) = delete;
+
+ enum class Type : uint8_t { kUnset = 0, kInt, kStr };
+
+ void Clear() {
+ int_value_.store(0, std::memory_order_relaxed);
+ type_.store(Type::kUnset, std::memory_order_relaxed);
+ }
+
+ void Set(int64_t value) {
+ int_value_.store(value, std::memory_order_relaxed);
+ type_.store(Type::kInt, std::memory_order_relaxed);
+ if (PERFETTO_UNLIKELY(!registered_.load(std::memory_order_relaxed)))
+ Register();
+ }
+
+ void Set(StringView sv) {
+ size_t len = std::min(sv.size(), sizeof(str_value_) - 1);
+ for (size_t i = 0; i < len; ++i)
+ str_value_[i].store(sv.data()[i], std::memory_order_relaxed);
+ str_value_[len].store('\0', std::memory_order_relaxed);
+ type_.store(Type::kStr, std::memory_order_relaxed);
+ if (PERFETTO_UNLIKELY(!registered_.load(std::memory_order_relaxed)))
+ Register();
+ }
+
+ ScopedClear SetScoped(int64_t value) PERFETTO_WARN_UNUSED_RESULT {
+ Set(value);
+ return ScopedClear(this);
+ }
+
+ ScopedClear SetScoped(StringView sv) PERFETTO_WARN_UNUSED_RESULT {
+ Set(sv);
+ return ScopedClear(this);
+ }
+
+ void Register();
+
+ int64_t int_value() const {
+ return int_value_.load(std::memory_order_relaxed);
+ }
+ size_t ToString(char* dst, size_t len);
+
+ private:
+ std::atomic<bool> registered_;
+ std::atomic<Type> type_;
+ const char* const name_;
+ union {
+ std::atomic<char> str_value_[kCrashKeyMaxStrSize];
+ std::atomic<int64_t> int_value_;
+ };
+};
+
+// Fills |dst| with a string containing one line for each crash key
+// (excluding the unset ones).
+// Returns number of chars written, without counting the NUL terminator.
+// This is used in logging.cc when emitting the crash report abort message.
+size_t SerializeCrashKeys(char* dst, size_t len);
+
+void UnregisterAllCrashKeysForTesting();
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_CRASH_KEYS_H_
+// gen_amalgamated begin header: include/perfetto/ext/base/string_utils.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cinttypes>
+#include <optional>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+
+namespace perfetto {
+namespace base {
+
+inline char Lowercase(char c) {
+ return ('A' <= c && c <= 'Z') ? static_cast<char>(c - ('A' - 'a')) : c;
+}
+
+inline char Uppercase(char c) {
+ return ('a' <= c && c <= 'z') ? static_cast<char>(c + ('A' - 'a')) : c;
+}
+
+inline std::optional<uint32_t> CStringToUInt32(const char* s, int base = 10) {
+ char* endptr = nullptr;
+ auto value = static_cast<uint32_t>(strtoul(s, &endptr, base));
+ return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
+}
+
+inline std::optional<int32_t> CStringToInt32(const char* s, int base = 10) {
+ char* endptr = nullptr;
+ auto value = static_cast<int32_t>(strtol(s, &endptr, base));
+ return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
+}
+
+// Note: it saturates to 7fffffffffffffff if parsing a hex number >= 0x8000...
+inline std::optional<int64_t> CStringToInt64(const char* s, int base = 10) {
+ char* endptr = nullptr;
+ auto value = static_cast<int64_t>(strtoll(s, &endptr, base));
+ return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
+}
+
+inline std::optional<uint64_t> CStringToUInt64(const char* s, int base = 10) {
+ char* endptr = nullptr;
+ auto value = static_cast<uint64_t>(strtoull(s, &endptr, base));
+ return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
+}
+
+double StrToD(const char* nptr, char** endptr);
+
+inline std::optional<double> CStringToDouble(const char* s) {
+ char* endptr = nullptr;
+ double value = StrToD(s, &endptr);
+ std::optional<double> result(std::nullopt);
+ if (*s != '\0' && *endptr == '\0')
+ result = value;
+ return result;
+}
+
+inline std::optional<uint32_t> StringToUInt32(const std::string& s,
+ int base = 10) {
+ return CStringToUInt32(s.c_str(), base);
+}
+
+inline std::optional<int32_t> StringToInt32(const std::string& s,
+ int base = 10) {
+ return CStringToInt32(s.c_str(), base);
+}
+
+inline std::optional<uint64_t> StringToUInt64(const std::string& s,
+ int base = 10) {
+ return CStringToUInt64(s.c_str(), base);
+}
+
+inline std::optional<int64_t> StringToInt64(const std::string& s,
+ int base = 10) {
+ return CStringToInt64(s.c_str(), base);
+}
+
+inline std::optional<double> StringToDouble(const std::string& s) {
+ return CStringToDouble(s.c_str());
+}
+
+bool StartsWith(const std::string& str, const std::string& prefix);
+bool EndsWith(const std::string& str, const std::string& suffix);
+bool StartsWithAny(const std::string& str,
+ const std::vector<std::string>& prefixes);
+bool Contains(const std::string& haystack, const std::string& needle);
+bool Contains(const std::string& haystack, char needle);
+size_t Find(const StringView& needle, const StringView& haystack);
+bool CaseInsensitiveEqual(const std::string& first, const std::string& second);
+std::string Join(const std::vector<std::string>& parts,
+ const std::string& delim);
+std::vector<std::string> SplitString(const std::string& text,
+ const std::string& delimiter);
+std::string StripPrefix(const std::string& str, const std::string& prefix);
+std::string StripSuffix(const std::string& str, const std::string& suffix);
+std::string TrimWhitespace(const std::string& str);
+std::string ToLower(const std::string& str);
+std::string ToUpper(const std::string& str);
+std::string StripChars(const std::string& str,
+ const std::string& chars,
+ char replacement);
+std::string ToHex(const char* data, size_t size);
+inline std::string ToHex(const std::string& s) {
+ return ToHex(s.c_str(), s.size());
+}
+std::string IntToHexString(uint32_t number);
+std::string Uint64ToHexString(uint64_t number);
+std::string Uint64ToHexStringNoPrefix(uint64_t number);
+std::string ReplaceAll(std::string str,
+ const std::string& to_replace,
+ const std::string& replacement);
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+bool WideToUTF8(const std::wstring& source, std::string& output);
+bool UTF8ToWide(const std::string& source, std::wstring& output);
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+// A BSD-style strlcpy without the return value.
+// Copies at most |dst_size|-1 characters. Unlike strncpy, it always \0
+// terminates |dst|, as long as |dst_size| is not 0.
+// Unlike strncpy and like strlcpy it does not zero-pad the rest of |dst|.
+// Returns nothing. The BSD strlcpy returns the size of |src|, which might
+// be > |dst_size|. Anecdotal experience suggests people assume the return value
+// is the number of bytes written in |dst|. That assumption can lead to
+// dangerous bugs.
+// In order to avoid being subtly uncompliant with strlcpy AND avoid misuse,
+// the choice here is to return nothing.
+inline void StringCopy(char* dst, const char* src, size_t dst_size) {
+ for (size_t i = 0; i < dst_size; ++i) {
+ if ((dst[i] = src[i]) == '\0') {
+ return; // We hit and copied the null terminator.
+ }
+ }
+
+ // We were left off at dst_size. We over copied 1 byte. Null terminate.
+ if (PERFETTO_LIKELY(dst_size > 0))
+ dst[dst_size - 1] = 0;
+}
+
+// Like snprintf() but returns the number of chars *actually* written (without
+// counting the null terminator) NOT "the number of chars which would have been
+// written to the final string if enough space had been available".
+// This should be used in almost all cases when the caller uses the return value
+// of snprintf(). If the return value is not used, there is no benefit in using
+// this wrapper, as this just calls snprintf() and mangles the return value.
+// It always null-terminates |dst| (even in case of errors), unless
+// |dst_size| == 0.
+// Examples:
+// SprintfTrunc(x, 4, "123whatever"): returns 3 and writes "123\0".
+// SprintfTrunc(x, 4, "123"): returns 3 and writes "123\0".
+// SprintfTrunc(x, 3, "123"): returns 2 and writes "12\0".
+// SprintfTrunc(x, 2, "123"): returns 1 and writes "1\0".
+// SprintfTrunc(x, 1, "123"): returns 0 and writes "\0".
+// SprintfTrunc(x, 0, "123"): returns 0 and writes nothing.
+// NOTE: This means that the caller has no way to tell when truncation happens
+// vs the edge case of *just* fitting in the buffer.
+size_t SprintfTrunc(char* dst, size_t dst_size, const char* fmt, ...)
+ PERFETTO_PRINTF_FORMAT(3, 4);
+
+// Line number starts from 1
+struct LineWithOffset {
+ base::StringView line;
+ uint32_t line_offset;
+ uint32_t line_num;
+};
+
+// For given string and offset Pfinds a line with character for
+// which offset points, what number is this line (starts from 1), and the offset
+// inside this line. returns std::nullopt if the offset points to
+// line break character or exceeds string length.
+std::optional<LineWithOffset> FindLineWithOffset(base::StringView str,
+ uint32_t offset);
+
+// A helper class to facilitate construction and usage of write-once stack
+// strings.
+// Example usage:
+// StackString<32> x("format %d %s", 42, string_arg);
+// TakeString(x.c_str() | x.string_view() | x.ToStdString());
+// Rather than char x[32] + sprintf.
+// Advantages:
+// - Avoids useless zero-fills caused by people doing `char buf[32] {}` (mainly
+// by fearing unknown snprintf failure modes).
+// - Makes the code more robust in case of snprintf truncations (len() and
+// string_view() will return the truncated length, unlike snprintf).
+template <size_t N>
+class StackString {
+ public:
+ explicit PERFETTO_PRINTF_FORMAT(/* 1=this */ 2, 3)
+ StackString(const char* fmt, ...) {
+ buf_[0] = '\0';
+ va_list args;
+ va_start(args, fmt);
+ int res = vsnprintf(buf_, sizeof(buf_), fmt, args);
+ va_end(args);
+ buf_[sizeof(buf_) - 1] = '\0';
+ len_ = res < 0 ? 0 : std::min(static_cast<size_t>(res), sizeof(buf_) - 1);
+ }
+
+ StringView string_view() const { return StringView(buf_, len_); }
+ std::string ToStdString() const { return std::string(buf_, len_); }
+ const char* c_str() const { return buf_; }
+ size_t len() const { return len_; }
+ char* mutable_data() { return buf_; }
+
+ private:
+ char buf_[N];
+ size_t len_ = 0; // Does not include the \0.
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/crash_keys.h"
+
+#include <string.h>
+
+#include <atomic>
+#include <cinttypes>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+namespace base {
+
+namespace {
+
+constexpr size_t kMaxKeys = 32;
+
+std::atomic<CrashKey*> g_keys[kMaxKeys]{};
+std::atomic<uint32_t> g_num_keys{};
+} // namespace
+
+void CrashKey::Register() {
+ // If doesn't matter if we fail below. If there are no slots left, don't
+ // keep trying re-registering on every Set(), the outcome won't change.
+
+ // If two threads raced on the Register(), avoid registering the key twice.
+ if (registered_.exchange(true))
+ return;
+
+ uint32_t slot = g_num_keys.fetch_add(1);
+ if (slot >= kMaxKeys) {
+ PERFETTO_LOG("Too many crash keys registered");
+ return;
+ }
+ g_keys[slot].store(this);
+}
+
+// Returns the number of chars written, without counting the \0.
+size_t CrashKey::ToString(char* dst, size_t len) {
+ if (len > 0)
+ *dst = '\0';
+ switch (type_.load(std::memory_order_relaxed)) {
+ case Type::kUnset:
+ break;
+ case Type::kInt:
+ return SprintfTrunc(dst, len, "%s: %" PRId64 "\n", name_,
+ int_value_.load(std::memory_order_relaxed));
+ case Type::kStr:
+ char buf[sizeof(str_value_)];
+ for (size_t i = 0; i < sizeof(str_value_); i++)
+ buf[i] = str_value_[i].load(std::memory_order_relaxed);
+
+ // Don't assume |str_value_| is properly null-terminated.
+ return SprintfTrunc(dst, len, "%s: %.*s\n", name_, int(sizeof(buf)), buf);
+ }
+ return 0;
+}
+
+void UnregisterAllCrashKeysForTesting() {
+ g_num_keys.store(0);
+ for (auto& key : g_keys)
+ key.store(nullptr);
+}
+
+size_t SerializeCrashKeys(char* dst, size_t len) {
+ size_t written = 0;
+ uint32_t num_keys = g_num_keys.load();
+ if (len > 0)
+ *dst = '\0';
+ for (uint32_t i = 0; i < num_keys && written < len; i++) {
+ CrashKey* key = g_keys[i].load();
+ if (!key)
+ continue; // Can happen if we hit this between the add and the store.
+ written += key->ToString(dst + written, len - written);
+ }
+ PERFETTO_DCHECK(written <= len);
+ PERFETTO_DCHECK(len == 0 || dst[written] == '\0');
+ return written;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/ctrl_c_handler.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/ctrl_c_handler.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_
+#define INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_
+
+namespace perfetto {
+namespace base {
+
+// On Linux/Android/Mac: installs SIGINT + SIGTERM signal handlers.
+// On Windows: installs a SetConsoleCtrlHandler() handler.
+// The passed handler must be async safe.
+using CtrlCHandlerFunction = void (*)();
+void InstallCtrlCHandler(CtrlCHandlerFunction);
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/ctrl_c_handler.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#include <io.h>
+#else
+#include <signal.h>
+#include <unistd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+namespace {
+CtrlCHandlerFunction g_handler = nullptr;
+}
+
+void InstallCtrlCHandler(CtrlCHandlerFunction handler) {
+ PERFETTO_CHECK(g_handler == nullptr);
+ g_handler = handler;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ auto trampoline = [](DWORD type) -> int {
+ if (type == CTRL_C_EVENT) {
+ g_handler();
+ return true;
+ }
+ return false;
+ };
+ ::SetConsoleCtrlHandler(trampoline, true);
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ // Setup signal handler.
+ struct sigaction sa {};
+
+// Glibc headers for sa_sigaction trigger this.
+#pragma GCC diagnostic push
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
+#endif
+ sa.sa_handler = [](int) { g_handler(); };
+ sa.sa_flags = static_cast<decltype(sa.sa_flags)>(SA_RESETHAND | SA_RESTART);
+#pragma GCC diagnostic pop
+ sigaction(SIGINT, &sa, nullptr);
+ sigaction(SIGTERM, &sa, nullptr);
+#else
+ // Do nothing on NaCL and Fuchsia.
+ ignore_result(handler);
+#endif
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/event_fd.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/event_fd.h
+// gen_amalgamated begin header: include/perfetto/ext/base/scoped_file.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_
+#define INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#include <stdio.h>
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <dirent.h> // For DIR* / opendir().
+#endif
+
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+
+namespace perfetto {
+namespace base {
+
+namespace internal {
+// Used for the most common cases of ScopedResource where there is only one
+// invalid value.
+template <typename T, T InvalidValue>
+struct DefaultValidityChecker {
+ static bool IsValid(T t) { return t != InvalidValue; }
+};
+} // namespace internal
+
+// RAII classes for auto-releasing fds and dirs.
+// if T is a pointer type, InvalidValue must be nullptr. Doing otherwise
+// causes weird unexpected behaviors (See https://godbolt.org/z/5nGMW4).
+template <typename T,
+ int (*CloseFunction)(T),
+ T InvalidValue,
+ bool CheckClose = true,
+ class Checker = internal::DefaultValidityChecker<T, InvalidValue>>
+class ScopedResource {
+ public:
+ using ValidityChecker = Checker;
+ static constexpr T kInvalid = InvalidValue;
+
+ explicit ScopedResource(T t = InvalidValue) : t_(t) {}
+ ScopedResource(ScopedResource&& other) noexcept {
+ t_ = other.t_;
+ other.t_ = InvalidValue;
+ }
+ ScopedResource& operator=(ScopedResource&& other) {
+ reset(other.t_);
+ other.t_ = InvalidValue;
+ return *this;
+ }
+ T get() const { return t_; }
+ T operator*() const { return t_; }
+ explicit operator bool() const { return Checker::IsValid(t_); }
+ void reset(T r = InvalidValue) {
+ if (Checker::IsValid(t_)) {
+ int res = CloseFunction(t_);
+ if (CheckClose)
+ PERFETTO_CHECK(res == 0);
+ }
+ t_ = r;
+ }
+ T release() {
+ T t = t_;
+ t_ = InvalidValue;
+ return t;
+ }
+ ~ScopedResource() { reset(InvalidValue); }
+
+ private:
+ ScopedResource(const ScopedResource&) = delete;
+ ScopedResource& operator=(const ScopedResource&) = delete;
+ T t_;
+};
+
+// Declared in file_utils.h. Forward declared to avoid #include cycles.
+int PERFETTO_EXPORT_COMPONENT CloseFile(int fd);
+
+// Use this for file resources obtained via open() and similar APIs.
+using ScopedFile = ScopedResource<int, CloseFile, -1>;
+using ScopedFstream = ScopedResource<FILE*, fclose, nullptr>;
+
+// Use this for resources that are HANDLE on Windows. See comments in
+// platform_handle.h
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using ScopedPlatformHandle = ScopedResource<PlatformHandle,
+ ClosePlatformHandle,
+ /*InvalidValue=*/nullptr,
+ /*CheckClose=*/true,
+ PlatformHandleChecker>;
+#else
+// On non-windows systems we alias ScopedPlatformHandle to ScopedFile because
+// they are really the same. This is to allow assignments between the two in
+// Linux-specific code paths that predate ScopedPlatformHandle.
+static_assert(std::is_same<int, PlatformHandle>::value, "");
+using ScopedPlatformHandle = ScopedFile;
+
+// DIR* does not exist on Windows.
+using ScopedDir = ScopedResource<DIR*, closedir, nullptr>;
+#endif
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_
+#define INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+
+namespace perfetto {
+namespace base {
+
+// A waitable event that can be used with poll/select.
+// This is really a wrapper around eventfd_create with a pipe-based fallback
+// for other platforms where eventfd is not supported.
+class EventFd {
+ public:
+ EventFd();
+ ~EventFd();
+ EventFd(EventFd&&) noexcept = default;
+ EventFd& operator=(EventFd&&) = default;
+
+ // The non-blocking file descriptor that can be polled to wait for the event.
+ PlatformHandle fd() const { return event_handle_.get(); }
+
+ // Can be called from any thread.
+ void Notify();
+
+ // Can be called from any thread. If more Notify() are queued a Clear() call
+ // can clear all of them (up to 16 per call).
+ void Clear();
+
+ private:
+ // The eventfd, when eventfd is supported, otherwise this is the read end of
+ // the pipe for fallback mode.
+ ScopedPlatformHandle event_handle_;
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // On Mac and other non-Linux UNIX platforms a pipe-based fallback is used.
+ // The write end of the wakeup pipe.
+ ScopedFile write_fd_;
+#endif
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_
+// gen_amalgamated begin header: include/perfetto/ext/base/pipe.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
+#define INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+
+namespace perfetto {
+namespace base {
+
+class Pipe {
+ public:
+ enum Flags {
+ kBothBlock = 0,
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ kBothNonBlock,
+ kRdNonBlock,
+ kWrNonBlock,
+#endif
+ };
+
+ static Pipe Create(Flags = kBothBlock);
+
+ Pipe();
+ Pipe(Pipe&&) noexcept;
+ Pipe& operator=(Pipe&&);
+
+ ScopedPlatformHandle rd;
+ ScopedPlatformHandle wr;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#include <errno.h>
+#include <stdint.h>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#include <synchapi.h>
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/eventfd.h>
+#include <unistd.h>
+#else // Mac, Fuchsia and other non-Linux UNIXes
+#include <unistd.h>
+#endif
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/event_fd.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/pipe.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+EventFd::~EventFd() = default;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+EventFd::EventFd() {
+ event_handle_.reset(
+ CreateEventA(/*lpEventAttributes=*/nullptr, /*bManualReset=*/true,
+ /*bInitialState=*/false, /*bInitialState=*/nullptr));
+}
+
+void EventFd::Notify() {
+ if (!SetEvent(event_handle_.get())) // 0: fail, !0: success, unlike UNIX.
+ PERFETTO_DFATAL("EventFd::Notify()");
+}
+
+void EventFd::Clear() {
+ if (!ResetEvent(event_handle_.get())) // 0: fail, !0: success, unlike UNIX.
+ PERFETTO_DFATAL("EventFd::Clear()");
+}
+
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+EventFd::EventFd() {
+ event_handle_.reset(eventfd(/*initval=*/0, EFD_CLOEXEC | EFD_NONBLOCK));
+ PERFETTO_CHECK(event_handle_);
+}
+
+void EventFd::Notify() {
+ const uint64_t value = 1;
+ ssize_t ret = write(event_handle_.get(), &value, sizeof(value));
+ if (ret <= 0 && errno != EAGAIN)
+ PERFETTO_DFATAL("EventFd::Notify()");
+}
+
+void EventFd::Clear() {
+ uint64_t value;
+ ssize_t ret =
+ PERFETTO_EINTR(read(event_handle_.get(), &value, sizeof(value)));
+ if (ret <= 0 && errno != EAGAIN)
+ PERFETTO_DFATAL("EventFd::Clear()");
+}
+
+#else
+
+EventFd::EventFd() {
+ // Make the pipe non-blocking so that we never block the waking thread (either
+ // the main thread or another one) when scheduling a wake-up.
+ Pipe pipe = Pipe::Create(Pipe::kBothNonBlock);
+ event_handle_ = ScopedPlatformHandle(std::move(pipe.rd).release());
+ write_fd_ = std::move(pipe.wr);
+}
+
+void EventFd::Notify() {
+ const uint64_t value = 1;
+ ssize_t ret = write(write_fd_.get(), &value, sizeof(uint8_t));
+ if (ret <= 0 && errno != EAGAIN)
+ PERFETTO_DFATAL("EventFd::Notify()");
+}
+
+void EventFd::Clear() {
+ // Drain the byte(s) written to the wake-up pipe. We can potentially read
+ // more than one byte if several wake-ups have been scheduled.
+ char buffer[16];
+ ssize_t ret =
+ PERFETTO_EINTR(read(event_handle_.get(), &buffer[0], sizeof(buffer)));
+ if (ret <= 0 && errno != EAGAIN)
+ PERFETTO_DFATAL("EventFd::Clear()");
+}
+#endif
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/file_utils.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/file_utils.h
+// gen_amalgamated begin header: include/perfetto/base/status.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_STATUS_H_
+#define INCLUDE_PERFETTO_BASE_STATUS_H_
+
+#include <optional>
+#include <string>
+#include <string_view>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+// Represents either the success or the failure message of a function.
+// This can used as the return type of functions which would usually return an
+// bool for success or int for errno but also wants to add some string context
+// (ususally for logging).
+//
+// Similar to absl::Status, an optional "payload" can also be included with more
+// context about the error. This allows passing additional metadata about the
+// error (e.g. location of errors, potential mitigations etc).
+class PERFETTO_EXPORT_COMPONENT Status {
+ public:
+ Status() : ok_(true) {}
+ explicit Status(std::string msg) : ok_(false), message_(std::move(msg)) {
+ PERFETTO_CHECK(!message_.empty());
+ }
+
+ // Copy operations.
+ Status(const Status&) = default;
+ Status& operator=(const Status&) = default;
+
+ // Move operations. The moved-from state is valid but unspecified.
+ Status(Status&&) noexcept = default;
+ Status& operator=(Status&&) = default;
+
+ bool ok() const { return ok_; }
+
+ // When ok() is false this returns the error message. Returns the empty string
+ // otherwise.
+ const std::string& message() const { return message_; }
+ const char* c_message() const { return message_.c_str(); }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Payload Management APIs
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Payloads can be attached to error statuses to provide additional context.
+ //
+ // Payloads are (key, value) pairs, where the key is a string acting as a
+ // unique "type URL" and the value is an opaque string. The "type URL" should
+ // be unique, follow the format of a URL and, ideally, documentation on how to
+ // interpret its associated data should be available.
+ //
+ // To attach a payload to a status object, call `Status::SetPayload()`.
+ // Similarly, to extract the payload from a status, call
+ // `Status::GetPayload()`.
+ //
+ // Note: the payload APIs are only meaningful to call when the status is an
+ // error. Otherwise, all methods are noops.
+
+ // Gets the payload for the given |type_url| if one exists.
+ //
+ // Will always return std::nullopt if |ok()|.
+ std::optional<std::string_view> GetPayload(std::string_view type_url) const;
+
+ // Sets the payload for the given key. The key should
+ //
+ // Will always do nothing if |ok()|.
+ void SetPayload(std::string_view type_url, std::string value);
+
+ // Erases the payload for the given string and returns true if the payload
+ // existed and was erased.
+ //
+ // Will always do nothing if |ok()|.
+ bool ErasePayload(std::string_view type_url);
+
+ private:
+ struct Payload {
+ std::string type_url;
+ std::string payload;
+ };
+
+ bool ok_ = false;
+ std::string message_;
+ std::vector<Payload> payloads_;
+};
+
+// Returns a status object which represents the Ok status.
+inline Status OkStatus() {
+ return Status();
+}
+
+PERFETTO_PRINTF_FORMAT(1, 2) Status ErrStatus(const char* format, ...);
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_STATUS_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
+
+#include <fcntl.h> // For mode_t & O_RDONLY/RDWR. Exists also on Windows.
+#include <stddef.h>
+
+#include <optional>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/status.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using FileOpenMode = int;
+inline constexpr char kDevNull[] = "NUL";
+#else
+using FileOpenMode = mode_t;
+inline constexpr char kDevNull[] = "/dev/null";
+#endif
+
+constexpr FileOpenMode kFileModeInvalid = static_cast<FileOpenMode>(-1);
+
+bool ReadPlatformHandle(PlatformHandle, std::string* out);
+bool ReadFileDescriptor(int fd, std::string* out);
+bool ReadFileStream(FILE* f, std::string* out);
+bool ReadFile(const std::string& path, std::string* out);
+
+// A wrapper around read(2). It deals with Linux vs Windows includes. It also
+// deals with handling EINTR. Has the same semantics of UNIX's read(2).
+ssize_t Read(int fd, void* dst, size_t dst_size);
+
+// Call write until all data is written or an error is detected.
+//
+// man 2 write:
+// If a write() is interrupted by a signal handler before any bytes are
+// written, then the call fails with the error EINTR; if it is
+// interrupted after at least one byte has been written, the call
+// succeeds, and returns the number of bytes written.
+ssize_t WriteAll(int fd, const void* buf, size_t count);
+
+ssize_t WriteAllHandle(PlatformHandle, const void* buf, size_t count);
+
+ScopedFile OpenFile(const std::string& path,
+ int flags,
+ FileOpenMode = kFileModeInvalid);
+ScopedFstream OpenFstream(const char* path, const char* mode);
+
+// This is an alias for close(). It's to avoid leaking Windows.h in headers.
+// Exported because ScopedFile is used in the /include/ext API by Chromium
+// component builds.
+int PERFETTO_EXPORT_COMPONENT CloseFile(int fd);
+
+bool FlushFile(int fd);
+
+// Returns true if mkdir succeeds, false if it fails (see errno in that case).
+bool Mkdir(const std::string& path);
+
+// Calls rmdir() on UNIX, _rmdir() on Windows.
+bool Rmdir(const std::string& path);
+
+// Wrapper around access(path, F_OK).
+bool FileExists(const std::string& path);
+
+// Gets the extension for a filename. If the file has two extensions, returns
+// only the last one (foo.pb.gz => .gz). Returns empty string if there is no
+// extension.
+std::string GetFileExtension(const std::string& filename);
+
+// Puts the path to all files under |dir_path| in |output|, recursively walking
+// subdirectories. File paths are relative to |dir_path|. Only files are
+// included, not directories. Path separator is always '/', even on windows (not
+// '\').
+base::Status ListFilesRecursive(const std::string& dir_path,
+ std::vector<std::string>& output);
+
+// Sets |path|'s owner group to |group_name| and permission mode bits to
+// |mode_bits|.
+base::Status SetFilePermissions(const std::string& path,
+ const std::string& group_name,
+ const std::string& mode_bits);
+
+// Returns the size of the file located at |path|, or nullopt in case of error.
+std::optional<uint64_t> GetFileSize(const std::string& path);
+
+// Returns the size of the open file |fd|, or nullopt in case of error.
+std::optional<uint64_t> GetFileSize(PlatformHandle fd);
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <algorithm>
+#include <deque>
+#include <optional>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+// gen_amalgamated expanded: #include "perfetto/base/status.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/platform.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#include <direct.h>
+#include <io.h>
+#include <stringapiset.h>
+#else
+#include <dirent.h>
+#include <unistd.h>
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#define PERFETTO_SET_FILE_PERMISSIONS
+#include <fcntl.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+namespace {
+constexpr size_t kBufSize = 2048;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// Wrap FindClose to: (1) make the return unix-style; (2) deal with stdcall.
+int CloseFindHandle(HANDLE h) {
+ return FindClose(h) ? 0 : -1;
+}
+
+std::optional<std::wstring> ToUtf16(const std::string str) {
+ int len = MultiByteToWideChar(CP_UTF8, 0, str.data(),
+ static_cast<int>(str.size()), nullptr, 0);
+ if (len < 0) {
+ return std::nullopt;
+ }
+ std::vector<wchar_t> tmp;
+ tmp.resize(static_cast<std::vector<wchar_t>::size_type>(len));
+ len =
+ MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()),
+ tmp.data(), static_cast<int>(tmp.size()));
+ if (len < 0) {
+ return std::nullopt;
+ }
+ PERFETTO_CHECK(static_cast<std::vector<wchar_t>::size_type>(len) ==
+ tmp.size());
+ return std::wstring(tmp.data(), tmp.size());
+}
+
+#endif
+
+} // namespace
+
+ssize_t Read(int fd, void* dst, size_t dst_size) {
+ ssize_t ret;
+ platform::BeforeMaybeBlockingSyscall();
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ ret = _read(fd, dst, static_cast<unsigned>(dst_size));
+#else
+ ret = PERFETTO_EINTR(read(fd, dst, dst_size));
+#endif
+ platform::AfterMaybeBlockingSyscall();
+ return ret;
+}
+
+bool ReadFileDescriptor(int fd, std::string* out) {
+ // Do not override existing data in string.
+ size_t i = out->size();
+
+ struct stat buf {};
+ if (fstat(fd, &buf) != -1) {
+ if (buf.st_size > 0)
+ out->resize(i + static_cast<size_t>(buf.st_size));
+ }
+
+ ssize_t bytes_read;
+ for (;;) {
+ if (out->size() < i + kBufSize)
+ out->resize(out->size() + kBufSize);
+
+ bytes_read = Read(fd, &((*out)[i]), kBufSize);
+ if (bytes_read > 0) {
+ i += static_cast<size_t>(bytes_read);
+ } else {
+ out->resize(i);
+ return bytes_read == 0;
+ }
+ }
+}
+
+bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // Do not override existing data in string.
+ size_t i = out->size();
+
+ for (;;) {
+ if (out->size() < i + kBufSize)
+ out->resize(out->size() + kBufSize);
+ DWORD bytes_read = 0;
+ auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
+ if (res && bytes_read > 0) {
+ i += static_cast<size_t>(bytes_read);
+ } else {
+ out->resize(i);
+ const bool is_eof = res && bytes_read == 0;
+ auto err = res ? 0 : GetLastError();
+ // The "Broken pipe" error on Windows is slighly different than Unix:
+ // On Unix: a "broken pipe" error can happen only on the writer side. On
+ // the reader there is no broken pipe, just a EOF.
+ // On windows: the reader also sees a broken pipe error.
+ // Here we normalize on the Unix behavior, treating broken pipe as EOF.
+ return is_eof || err == ERROR_BROKEN_PIPE;
+ }
+ }
+#else
+ return ReadFileDescriptor(h, out);
+#endif
+}
+
+bool ReadFileStream(FILE* f, std::string* out) {
+ return ReadFileDescriptor(fileno(f), out);
+}
+
+bool ReadFile(const std::string& path, std::string* out) {
+ base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
+ if (!fd)
+ return false;
+
+ return ReadFileDescriptor(*fd, out);
+}
+
+ssize_t WriteAll(int fd, const void* buf, size_t count) {
+ size_t written = 0;
+ while (written < count) {
+ // write() on windows takes an unsigned int size.
+ uint32_t bytes_left = static_cast<uint32_t>(
+ std::min(count - written, static_cast<size_t>(UINT32_MAX)));
+ platform::BeforeMaybeBlockingSyscall();
+ ssize_t wr = PERFETTO_EINTR(
+ write(fd, static_cast<const char*>(buf) + written, bytes_left));
+ platform::AfterMaybeBlockingSyscall();
+ if (wr == 0)
+ break;
+ if (wr < 0)
+ return wr;
+ written += static_cast<size_t>(wr);
+ }
+ return static_cast<ssize_t>(written);
+}
+
+ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ DWORD wsize = 0;
+ if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
+ return wsize;
+ } else {
+ return -1;
+ }
+#else
+ return WriteAll(h, buf, count);
+#endif
+}
+
+bool FlushFile(int fd) {
+ PERFETTO_DCHECK(fd != 0);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ return !PERFETTO_EINTR(fdatasync(fd));
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return !PERFETTO_EINTR(_commit(fd));
+#else
+ return !PERFETTO_EINTR(fsync(fd));
+#endif
+}
+
+bool Mkdir(const std::string& path) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return _mkdir(path.c_str()) == 0;
+#else
+ return mkdir(path.c_str(), 0755) == 0;
+#endif
+}
+
+bool Rmdir(const std::string& path) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return _rmdir(path.c_str()) == 0;
+#else
+ return rmdir(path.c_str()) == 0;
+#endif
+}
+
+int CloseFile(int fd) {
+ return close(fd);
+}
+
+ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
+ // If a new file might be created, ensure that the permissions for the new
+ // file are explicitly specified.
+ PERFETTO_CHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // Always use O_BINARY on Windows, to avoid silly EOL translations.
+ ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
+#else
+ // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
+ ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
+#endif
+ return fd;
+}
+
+ScopedFstream OpenFstream(const char* path, const char* mode) {
+ ScopedFstream file;
+// On Windows fopen interprets filename using the ANSI or OEM codepage but
+// sqlite3_value_text returns a UTF-8 string. To make sure we interpret the
+// filename correctly we use _wfopen and a UTF-16 string on windows.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ auto w_path = ToUtf16(path);
+ auto w_mode = ToUtf16(mode);
+ if (w_path && w_mode) {
+ file.reset(_wfopen(w_path->c_str(), w_mode->c_str()));
+ }
+#else
+ file.reset(fopen(path, mode));
+#endif
+ return file;
+}
+
+bool FileExists(const std::string& path) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return _access(path.c_str(), 0) == 0;
+#else
+ return access(path.c_str(), F_OK) == 0;
+#endif
+}
+
+// Declared in base/platform_handle.h.
+int ClosePlatformHandle(PlatformHandle handle) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // Make the return value UNIX-style.
+ return CloseHandle(handle) ? 0 : -1;
+#else
+ return close(handle);
+#endif
+}
+
+base::Status ListFilesRecursive(const std::string& dir_path,
+ std::vector<std::string>& output) {
+ std::string root_dir_path = dir_path;
+ if (root_dir_path.back() == '\\') {
+ root_dir_path.back() = '/';
+ } else if (root_dir_path.back() != '/') {
+ root_dir_path.push_back('/');
+ }
+
+ // dir_queue contains full paths to the directories. The paths include the
+ // root_dir_path at the beginning and the trailing slash at the end.
+ std::deque<std::string> dir_queue;
+ dir_queue.push_back(root_dir_path);
+
+ while (!dir_queue.empty()) {
+ const std::string cur_dir = std::move(dir_queue.front());
+ dir_queue.pop_front();
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+ return base::ErrStatus("ListFilesRecursive not supported yet");
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ std::string glob_path = cur_dir + "*";
+ // + 1 because we also have to count the NULL terminator.
+ if (glob_path.length() + 1 > MAX_PATH)
+ return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
+ WIN32_FIND_DATAA ffd;
+
+ base::ScopedResource<HANDLE, CloseFindHandle, nullptr, false,
+ base::PlatformHandleChecker>
+ hFind(FindFirstFileA(glob_path.c_str(), &ffd));
+ if (!hFind) {
+ // For empty directories, there should be at least one entry '.'.
+ // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
+ // couldn't be accessed.
+ return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
+ }
+ do {
+ if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
+ continue;
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ std::string subdir_path = cur_dir + ffd.cFileName + '/';
+ dir_queue.push_back(subdir_path);
+ } else {
+ const std::string full_path = cur_dir + ffd.cFileName;
+ PERFETTO_CHECK(full_path.length() > root_dir_path.length());
+ output.push_back(full_path.substr(root_dir_path.length()));
+ }
+ } while (FindNextFileA(*hFind, &ffd));
+#else
+ ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
+ if (!dir) {
+ return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
+ }
+ for (auto* dirent = readdir(dir.get()); dirent != nullptr;
+ dirent = readdir(dir.get())) {
+ if (strcmp(dirent->d_name, ".") == 0 ||
+ strcmp(dirent->d_name, "..") == 0) {
+ continue;
+ }
+ if (dirent->d_type == DT_DIR) {
+ dir_queue.push_back(cur_dir + dirent->d_name + '/');
+ } else if (dirent->d_type == DT_REG) {
+ const std::string full_path = cur_dir + dirent->d_name;
+ PERFETTO_CHECK(full_path.length() > root_dir_path.length());
+ output.push_back(full_path.substr(root_dir_path.length()));
+ }
+ }
+#endif
+ }
+ return base::OkStatus();
+}
+
+std::string GetFileExtension(const std::string& filename) {
+ auto ext_idx = filename.rfind('.');
+ if (ext_idx == std::string::npos)
+ return std::string();
+ return filename.substr(ext_idx);
+}
+
+base::Status SetFilePermissions(const std::string& file_path,
+ const std::string& group_name_or_id,
+ const std::string& mode_bits) {
+#ifdef PERFETTO_SET_FILE_PERMISSIONS
+ PERFETTO_CHECK(!file_path.empty());
+ PERFETTO_CHECK(!group_name_or_id.empty());
+
+ // Default |group_id| to -1 for not changing the group ownership.
+ gid_t group_id = static_cast<gid_t>(-1);
+ auto maybe_group_id = base::StringToUInt32(group_name_or_id);
+ if (maybe_group_id) { // A numerical group ID.
+ group_id = *maybe_group_id;
+ } else { // A group name.
+ struct group* file_group = nullptr;
+ // Query the group ID of |group|.
+ do {
+ file_group = getgrnam(group_name_or_id.c_str());
+ } while (file_group == nullptr && errno == EINTR);
+ if (file_group == nullptr) {
+ return base::ErrStatus("Failed to get group information of %s ",
+ group_name_or_id.c_str());
+ }
+ group_id = file_group->gr_gid;
+ }
+
+ if (PERFETTO_EINTR(chown(file_path.c_str(), geteuid(), group_id))) {
+ return base::ErrStatus("Failed to chown %s ", file_path.c_str());
+ }
+
+ // |mode| accepts values like "0660" as "rw-rw----" mode bits.
+ auto mode_value = base::StringToInt32(mode_bits, 8);
+ if (!(mode_bits.size() == 4 && mode_value.has_value())) {
+ return base::ErrStatus(
+ "The chmod mode bits must be a 4-digit octal number, e.g. 0660");
+ }
+ if (PERFETTO_EINTR(
+ chmod(file_path.c_str(), static_cast<mode_t>(mode_value.value())))) {
+ return base::ErrStatus("Failed to chmod %s", file_path.c_str());
+ }
+ return base::OkStatus();
+#else
+ base::ignore_result(file_path);
+ base::ignore_result(group_name_or_id);
+ base::ignore_result(mode_bits);
+ return base::ErrStatus(
+ "Setting file permissions is not supported on this platform");
+#endif
+}
+
+std::optional<uint64_t> GetFileSize(const std::string& file_path) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // This does not use base::OpenFile to avoid getting an exclusive lock.
+ base::ScopedPlatformHandle fd(
+ CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
+#else
+ base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
+#endif
+ if (!fd) {
+ return std::nullopt;
+ }
+ return GetFileSize(*fd);
+}
+
+std::optional<uint64_t> GetFileSize(PlatformHandle fd) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ LARGE_INTEGER file_size;
+ file_size.QuadPart = 0;
+ if (!GetFileSizeEx(fd, &file_size)) {
+ return std::nullopt;
+ }
+ static_assert(sizeof(decltype(file_size.QuadPart)) <= sizeof(uint64_t));
+ return static_cast<uint64_t>(file_size.QuadPart);
+#else
+ struct stat buf {};
+ if (fstat(fd, &buf) == -1) {
+ return std::nullopt;
+ }
+ static_assert(sizeof(decltype(buf.st_size)) <= sizeof(uint64_t));
+ return static_cast<uint64_t>(buf.st_size);
+#endif
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/getopt_compat.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/getopt_compat.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_
+#define INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_
+
+#include <cstddef> // For std::nullptr_t
+
+// No translation units other than base/getopt.h and getopt_compat_unittest.cc
+// should directly include this file. Use base/getopt.h instead.
+
+namespace perfetto {
+namespace base {
+namespace getopt_compat {
+
+// A tiny getopt() replacement for Windows, which doesn't have <getopt.h>.
+// This implementation is based on the subset of features that we use in the
+// Perfetto codebase. It doesn't even try to deal with the full surface of GNU's
+// getopt().
+// Limitations:
+// - getopt_long_only() is not supported.
+// - optional_argument is not supported. That is extremely subtle and caused us
+// problems in the past with GNU's getopt.
+// - It does not reorder non-option arguments. It behaves like MacOS getopt, or
+// GNU's when POSIXLY_CORRECT=1.
+// - Doesn't expose optopt or opterr.
+// - option.flag and longindex are not supported and must be nullptr.
+
+enum {
+ no_argument = 0,
+ required_argument = 1,
+};
+
+struct option {
+ const char* name;
+ int has_arg;
+ std::nullptr_t flag; // Only nullptr is supported.
+ int val;
+};
+
+extern char* optarg;
+extern int optind;
+extern int optopt;
+extern int opterr;
+
+int getopt_long(int argc,
+ char** argv,
+ const char* shortopts,
+ const option* longopts,
+ std::nullptr_t /*longindex is not supported*/);
+
+int getopt(int argc, char** argv, const char* shortopts);
+
+} // namespace getopt_compat
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/getopt_compat.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+namespace getopt_compat {
+
+char* optarg = nullptr;
+int optind = 0;
+int optopt = 0;
+int opterr = 1;
+
+namespace {
+
+char* nextchar = nullptr;
+
+const option* LookupLongOpt(const std::vector<option>& opts,
+ const char* name,
+ size_t len) {
+ for (const option& opt : opts) {
+ if (strncmp(opt.name, name, len) == 0 && strlen(opt.name) == len)
+ return &opt;
+ }
+ return nullptr;
+}
+
+const option* LookupShortOpt(const std::vector<option>& opts, char c) {
+ for (const option& opt : opts) {
+ if (!*opt.name && opt.val == c)
+ return &opt;
+ }
+ return nullptr;
+}
+
+bool ParseOpts(const char* shortopts,
+ const option* longopts,
+ std::vector<option>* res) {
+ // Parse long options first.
+ for (const option* lopt = longopts; lopt && lopt->name; lopt++) {
+ PERFETTO_CHECK(lopt->flag == nullptr);
+ PERFETTO_CHECK(lopt->has_arg == no_argument ||
+ lopt->has_arg == required_argument);
+ res->emplace_back(*lopt);
+ }
+
+ // Merge short options.
+ for (const char* sopt = shortopts; sopt && *sopt;) {
+ const size_t idx = static_cast<size_t>(sopt - shortopts);
+ char c = *sopt++;
+ bool valid = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9');
+ if (!valid) {
+ fprintf(stderr,
+ "Error parsing shortopts. Unexpected char '%c' at offset %zu\n",
+ c, idx);
+ return false;
+ }
+ res->emplace_back();
+ option& opt = res->back();
+ opt.name = "";
+ opt.val = c;
+ opt.has_arg = no_argument;
+ if (*sopt == ':') {
+ opt.has_arg = required_argument;
+ ++sopt;
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+int getopt_long(int argc,
+ char** argv,
+ const char* shortopts,
+ const option* longopts,
+ std::nullptr_t /*longind*/) {
+ std::vector<option> opts;
+ optarg = nullptr;
+
+ if (optind == 0)
+ optind = 1;
+
+ if (optind >= argc)
+ return -1;
+
+ if (!ParseOpts(shortopts, longopts, &opts))
+ return '?';
+
+ char* arg = argv[optind];
+ optopt = 0;
+
+ if (!nextchar) {
+ // If |nextchar| is null we are NOT in the middle of a short option and we
+ // should parse the next argv.
+ if (strncmp(arg, "--", 2) == 0 && strlen(arg) > 2) {
+ // A --long option.
+ arg += 2;
+ char* sep = strchr(arg, '=');
+ optind++;
+
+ size_t len = sep ? static_cast<size_t>(sep - arg) : strlen(arg);
+ const option* opt = LookupLongOpt(opts, arg, len);
+
+ if (!opt) {
+ if (opterr)
+ fprintf(stderr, "unrecognized option '--%s'\n", arg);
+ return '?';
+ }
+
+ optopt = opt->val;
+ if (opt->has_arg == no_argument) {
+ if (sep) {
+ fprintf(stderr, "option '--%s' doesn't allow an argument\n", arg);
+ return '?';
+ } else {
+ return opt->val;
+ }
+ } else if (opt->has_arg == required_argument) {
+ if (sep) {
+ optarg = sep + 1;
+ return opt->val;
+ } else if (optind >= argc) {
+ if (opterr)
+ fprintf(stderr, "option '--%s' requires an argument\n", arg);
+ return '?';
+ } else {
+ optarg = argv[optind++];
+ return opt->val;
+ }
+ }
+ // has_arg must be either |no_argument| or |required_argument|. We
+ // shoulnd't get here unless the check in ParseOpts() has a bug.
+ PERFETTO_CHECK(false);
+ } // if (arg ~= "--*").
+
+ if (strlen(arg) > 1 && arg[0] == '-' && arg[1] != '-') {
+ // A sequence of short options. Parsing logic continues below.
+ nextchar = &arg[1];
+ }
+ } // if(!nextchar)
+
+ if (nextchar) {
+ // At this point either:
+ // 1. This is the first char of a sequence of short options, and we fell
+ // through here from the lines above.
+ // 2. This is the N (>1) char of a sequence of short options, and we got
+ // here from a new getopt() call to getopt().
+ const char cur_char = *nextchar;
+ PERFETTO_CHECK(cur_char != '\0');
+
+ // Advance the option char in any case, before we start reasoning on them.
+ // if we got to the end of the "-abc" sequence, increment optind so the next
+ // getopt() call resumes from the next argv argument.
+ if (*(++nextchar) == '\0') {
+ nextchar = nullptr;
+ ++optind;
+ }
+
+ const option* opt = LookupShortOpt(opts, cur_char);
+ optopt = cur_char;
+ if (!opt) {
+ if (opterr)
+ fprintf(stderr, "invalid option -- '%c'\n", cur_char);
+ return '?';
+ }
+ if (opt->has_arg == no_argument) {
+ return cur_char;
+ } else if (opt->has_arg == required_argument) {
+ // This is a subtle getopt behavior. Say you call `tar -fx`, there are
+ // two cases:
+ // 1. If 'f' is no_argument then 'x' (and anything else after) is
+ // interpreted as an independent argument (like `tar -f -x`).
+ // 2. If 'f' is required_argument, than everything else after the 'f'
+ // is interpreted as the option argument (like `tar -f x`)
+ if (!nextchar) {
+ // Case 1.
+ if (optind >= argc) {
+ if (opterr)
+ fprintf(stderr, "option requires an argument -- '%c'\n", cur_char);
+ return '?';
+ } else {
+ optarg = argv[optind++];
+ return cur_char;
+ }
+ } else {
+ // Case 2.
+ optarg = nextchar;
+ nextchar = nullptr;
+ optind++;
+ return cur_char;
+ }
+ }
+ PERFETTO_CHECK(false);
+ } // if (nextchar)
+
+ // If we get here, we found the first non-option argument. Stop here.
+
+ if (strcmp(arg, "--") == 0)
+ optind++;
+
+ return -1;
+}
+
+int getopt(int argc, char** argv, const char* shortopts) {
+ return getopt_long(argc, argv, shortopts, nullptr, nullptr);
+}
+
+} // namespace getopt_compat
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/logging.cc
+// gen_amalgamated begin header: src/base/log_ring_buffer.h
+// gen_amalgamated begin header: include/perfetto/ext/base/thread_annotations.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_THREAD_ANNOTATIONS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_THREAD_ANNOTATIONS_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+// Windows TSAN doesn't currently support these annotations.
+#if defined(THREAD_SANITIZER) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+extern "C" {
+void AnnotateBenignRaceSized(const char* file,
+ int line,
+ const volatile void* address,
+ size_t size,
+ const char* description);
+}
+
+#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description) \
+ AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, size, description);
+#else // defined(ADDRESS_SANITIZER)
+#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description)
+#endif // defined(ADDRESS_SANITIZER)
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_THREAD_ANNOTATIONS_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_BASE_LOG_RING_BUFFER_H_
+#define SRC_BASE_LOG_RING_BUFFER_H_
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include <array>
+#include <atomic>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_annotations.h"
+
+namespace perfetto {
+namespace base {
+
+// Defined out of line because a static constexpr requires static storage if
+// ODR-used, not worth adding a .cc file just for tests.
+constexpr size_t kLogRingBufEntries = 8;
+constexpr size_t kLogRingBufMsgLen = 256;
+
+// A static non-allocating ring-buffer to hold the most recent log events.
+// This class is really an implementation detail of logging.cc. The only reason
+// why is fully defined in a dedicated header is for allowing unittesting,
+// without leaking extra headers into logging.h (which is a high-fanout header).
+// This is used to report the last logs in a crash report when a CHECK/FATAL
+// is encountered.
+// This class has just an Append() method to insert events into the buffer and
+// a Read() to read the events in FIFO order. Read() is non-destructive.
+//
+// Thread safety considerations:
+// - The Append() method can be called concurrently by several threads, unless
+// there are > kLogRingBufEntries concurrent threads. Even if that happens,
+// case some events will contain a mix of strings but the behavior of
+// futher Append() and Read() is still defined.
+// - The Read() method is not thread safe but it's fine in practice. Even if
+// it's called concurrently with other Append(), it only causes some partial
+// events to be emitted in output.
+// In both cases, we never rely purely on \0, all operations are size-bound.
+//
+// See logging_unittest.cc for tests.
+class LogRingBuffer {
+ public:
+ LogRingBuffer() = default;
+ LogRingBuffer(const LogRingBuffer&) = delete;
+ LogRingBuffer& operator=(const LogRingBuffer&) = delete;
+ LogRingBuffer(LogRingBuffer&&) = delete;
+ LogRingBuffer& operator=(LogRingBuffer&&) = delete;
+
+ // This takes three arguments because it fits its only caller (logging.cc).
+ // The args are just concatenated together (plus one space before the msg).
+ void Append(StringView tstamp, StringView source, StringView log_msg) {
+ // Reserve atomically a slot in the ring buffer, so any concurrent Append()
+ // won't overlap (unless too many concurrent Append() happen together).
+ // There is no strict synchronization here, |event_slot_| is atomic only for
+ // the sake of avoiding colliding on the same slot but does NOT guarantee
+ // full consistency and integrity of the log messages written in each slot.
+ // A release-store (or acq+rel) won't be enough for full consistency. Two
+ // threads that race on Append() and take the N+1 and N+2 slots could finish
+ // the write in reverse order. So Read() would need to synchronize with
+ // something else (either a per-slot atomic flag or with a second atomic
+ // counter which is incremented after the snprintf). Both options increase
+ // the cost of Append() with no huge benefits (90% of the perfetto services
+ // where we use it is single thread, and the log ring buffer is disabled
+ // on non-standalone builds like the SDK).
+ uint32_t slot = event_slot_.fetch_add(1, std::memory_order_relaxed);
+ slot = slot % kLogRingBufEntries;
+
+ char* const msg = events_[slot];
+ PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(msg, kLogRingBufMsgLen,
+ "see comments in log_ring_buffer.h")
+ snprintf(msg, kLogRingBufMsgLen, "%.*s%.*s %.*s",
+ static_cast<int>(tstamp.size()), tstamp.data(),
+ static_cast<int>(source.size()), source.data(),
+ static_cast<int>(log_msg.size()), log_msg.data());
+ }
+
+ // Reads back the buffer in FIFO order, up to |len - 1| characters at most
+ // (the -1 is because a NUL terminator is always appended, unless |len| == 0).
+ // The string written in |dst| is guaranteed to be NUL-terminated, even if
+ // |len| < buffer contents length.
+ // Returns the number of bytes written in output, excluding the \0 terminator.
+ size_t Read(char* dst, size_t len) {
+ if (len == 0)
+ return 0;
+ // This is a relaxed-load because we don't need to fully synchronize on the
+ // writing path for the reasons described in the fetch_add() above.
+ const uint32_t event_slot = event_slot_.load(std::memory_order_relaxed);
+ size_t dst_written = 0;
+ for (uint32_t pos = 0; pos < kLogRingBufEntries; ++pos) {
+ const uint32_t slot = (event_slot + pos) % kLogRingBufEntries;
+ const char* src = events_[slot];
+ if (*src == '\0')
+ continue; // Empty slot. Skip.
+ char* const wptr = dst + dst_written;
+ // |src| might not be null terminated. This can happen if some
+ // thread-race happened. Limit the copy length.
+ const size_t limit = std::min(len - dst_written, kLogRingBufMsgLen);
+ for (size_t i = 0; i < limit; ++i) {
+ const char c = src[i];
+ ++dst_written;
+ if (c == '\0' || i == limit - 1) {
+ wptr[i] = '\n';
+ break;
+ }
+ // Skip non-printable ASCII characters to avoid confusing crash reports.
+ // Note that this deliberately mangles \n. Log messages should not have
+ // a \n in the middle and are NOT \n terminated. The trailing \n between
+ // each line is appended by the if () branch above.
+ const bool is_printable = c >= ' ' && c <= '~';
+ wptr[i] = is_printable ? c : '?';
+ }
+ }
+ // Ensure that the output string is null-terminated.
+ PERFETTO_DCHECK(dst_written <= len);
+ if (dst_written == len) {
+ // In case of truncation we replace the last char with \0. But the return
+ // value is the number of chars without \0, hence the --.
+ dst[--dst_written] = '\0';
+ } else {
+ dst[dst_written] = '\0';
+ }
+ return dst_written;
+ }
+
+ private:
+ using EventBuf = char[kLogRingBufMsgLen];
+ EventBuf events_[kLogRingBufEntries]{};
+
+ static_assert((kLogRingBufEntries & (kLogRingBufEntries - 1)) == 0,
+ "kLogRingBufEntries must be a power of two");
+
+ // A monotonically increasing counter incremented on each event written.
+ // It determines which of the kLogRingBufEntries indexes in |events_| should
+ // be used next.
+ // It grows >> kLogRingBufEntries, it's supposed to be always used
+ // mod(kLogRingBufEntries). A static_assert in the .cc file ensures that
+ // kLogRingBufEntries is a power of two so wraps are aligned.
+ std::atomic<uint32_t> event_slot_{};
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // SRC_BASE_LOG_RING_BUFFER_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <unistd.h> // For isatty()
+#endif
+
+#include <atomic>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/crash_keys.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+// gen_amalgamated expanded: #include "src/base/log_ring_buffer.h"
+
+#if PERFETTO_ENABLE_LOG_RING_BUFFER() && PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <android/set_abort_message.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+namespace {
+const char kReset[] = "\x1b[0m";
+const char kDefault[] = "\x1b[39m";
+const char kDim[] = "\x1b[2m";
+const char kRed[] = "\x1b[31m";
+const char kBoldGreen[] = "\x1b[1m\x1b[32m";
+const char kLightGray[] = "\x1b[90m";
+
+std::atomic<LogMessageCallback> g_log_callback{};
+
+#if PERFETTO_BUILDFLAG(PERFETTO_STDERR_CRASH_DUMP)
+// __attribute__((constructor)) causes a static initializer that automagically
+// early runs this function before the main().
+void PERFETTO_EXPORT_COMPONENT __attribute__((constructor))
+InitDebugCrashReporter() {
+ // This function is defined in debug_crash_stack_trace.cc.
+ // The dynamic initializer is in logging.cc because logging.cc is included
+ // in virtually any target that depends on base. Having it in
+ // debug_crash_stack_trace.cc would require figuring out -Wl,whole-archive
+ // which is not worth it.
+ EnableStacktraceOnCrashForDebug();
+}
+#endif
+
+#if PERFETTO_ENABLE_LOG_RING_BUFFER()
+LogRingBuffer g_log_ring_buffer{};
+
+// This is global to avoid allocating memory or growing too much the stack
+// in MaybeSerializeLastLogsForCrashReporting(), which is called from
+// arbitrary code paths hitting PERFETTO_CHECK()/FATAL().
+char g_crash_buf[kLogRingBufEntries * kLogRingBufMsgLen];
+#endif
+
+} // namespace
+
+void SetLogMessageCallback(LogMessageCallback callback) {
+ g_log_callback.store(callback, std::memory_order_relaxed);
+}
+
+void LogMessage(LogLev level,
+ const char* fname,
+ int line,
+ const char* fmt,
+ ...) {
+ char stack_buf[512];
+ std::unique_ptr<char[]> large_buf;
+ char* log_msg = &stack_buf[0];
+ size_t log_msg_len = 0;
+
+ // By default use a stack allocated buffer because most log messages are quite
+ // short. In rare cases they can be larger (e.g. --help). In those cases we
+ // pay the cost of allocating the buffer on the heap.
+ for (size_t max_len = sizeof(stack_buf);;) {
+ va_list args;
+ va_start(args, fmt);
+ int res = vsnprintf(log_msg, max_len, fmt, args);
+ va_end(args);
+
+ // If for any reason the print fails, overwrite the message but still print
+ // it. The code below will attach the filename and line, which is still
+ // useful.
+ if (res < 0) {
+ snprintf(log_msg, max_len, "%s", "[printf format error]");
+ break;
+ }
+
+ // if res == max_len, vsnprintf saturated the input buffer. Retry with a
+ // larger buffer in that case (within reasonable limits).
+ if (res < static_cast<int>(max_len) || max_len >= 128 * 1024) {
+ // In case of truncation vsnprintf returns the len that "would have been
+ // written if the string was longer", not the actual chars written.
+ log_msg_len = std::min(static_cast<size_t>(res), max_len - 1);
+ break;
+ }
+ max_len *= 4;
+ large_buf.reset(new char[max_len]);
+ log_msg = &large_buf[0];
+ }
+
+ LogMessageCallback cb = g_log_callback.load(std::memory_order_relaxed);
+ if (cb) {
+ cb({level, line, fname, log_msg});
+ return;
+ }
+
+ const char* color = kDefault;
+ switch (level) {
+ case kLogDebug:
+ color = kDim;
+ break;
+ case kLogInfo:
+ color = kDefault;
+ break;
+ case kLogImportant:
+ color = kBoldGreen;
+ break;
+ case kLogError:
+ color = kRed;
+ break;
+ }
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
+ static const bool use_colors = isatty(STDERR_FILENO);
+#else
+ static const bool use_colors = false;
+#endif
+
+ // Formats file.cc:line as a space-padded fixed width string. If the file name
+ // |fname| is too long, truncate it on the left-hand side.
+ StackString<10> line_str("%d", line);
+
+ // 24 will be the width of the file.cc:line column in the log event.
+ static constexpr size_t kMaxNameAndLine = 24;
+ size_t fname_len = strlen(fname);
+ size_t fname_max = kMaxNameAndLine - line_str.len() - 2; // 2 = ':' + '\0'.
+ size_t fname_offset = fname_len <= fname_max ? 0 : fname_len - fname_max;
+ StackString<kMaxNameAndLine> file_and_line(
+ "%*s:%s", static_cast<int>(fname_max), &fname[fname_offset],
+ line_str.c_str());
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // Logcat has already timestamping, don't re-emit it.
+ __android_log_print(int{ANDROID_LOG_DEBUG} + level, "perfetto", "%s %s",
+ file_and_line.c_str(), log_msg);
+#endif
+
+ // When printing on stderr, print also the timestamp. We don't really care
+ // about the actual time. We just need some reference clock that can be used
+ // to correlated events across differrent processses (e.g. traced and
+ // traced_probes). The wall time % 1000 is good enough.
+ uint32_t t_ms = static_cast<uint32_t>(GetWallTimeMs().count());
+ uint32_t t_sec = t_ms / 1000;
+ t_ms -= t_sec * 1000;
+ t_sec = t_sec % 1000;
+ StackString<32> timestamp("[%03u.%03u] ", t_sec, t_ms);
+
+ if (use_colors) {
+ fprintf(stderr, "%s%s%s%s %s%s%s\n", kLightGray, timestamp.c_str(),
+ file_and_line.c_str(), kReset, color, log_msg, kReset);
+ } else {
+ fprintf(stderr, "%s%s %s\n", timestamp.c_str(), file_and_line.c_str(),
+ log_msg);
+ }
+
+#if PERFETTO_ENABLE_LOG_RING_BUFFER()
+ // Append the message to the ring buffer for crash reporting postmortems.
+ StringView timestamp_sv = timestamp.string_view();
+ StringView file_and_line_sv = file_and_line.string_view();
+ StringView log_msg_sv(log_msg, static_cast<size_t>(log_msg_len));
+ g_log_ring_buffer.Append(timestamp_sv, file_and_line_sv, log_msg_sv);
+#else
+ ignore_result(log_msg_len);
+#endif
+}
+
+#if PERFETTO_ENABLE_LOG_RING_BUFFER()
+void MaybeSerializeLastLogsForCrashReporting() {
+ // Keep this function minimal. This is called from the watchdog thread, often
+ // when the system is thrashing.
+
+ // This is racy because two threads could hit a CHECK/FATAL at the same time.
+ // But if that happens we have bigger problems, not worth designing around it.
+ // The behaviour is still defined in the race case (the string attached to
+ // the crash report will contain a mixture of log strings).
+ size_t wr = 0;
+ wr += SerializeCrashKeys(&g_crash_buf[wr], sizeof(g_crash_buf) - wr);
+ wr += g_log_ring_buffer.Read(&g_crash_buf[wr], sizeof(g_crash_buf) - wr);
+
+ // Read() null-terminates the string properly. This is just to avoid UB when
+ // two threads race on each other (T1 writes a shorter string, T2
+ // overwrites the \0 writing a longer string. T1 continues here before T2
+ // finishes writing the longer string with the \0 -> boom.
+ g_crash_buf[sizeof(g_crash_buf) - 1] = '\0';
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // android_set_abort_message() will cause debuggerd to report the message
+ // in the tombstone and in the crash log in logcat.
+ // NOTE: android_set_abort_message() can be called only once. This should
+ // be called only when we are sure we are about to crash.
+ android_set_abort_message(g_crash_buf);
+#else
+ // Print out the message on stderr on Linux/Mac/Win.
+ fputs("\n-----BEGIN PERFETTO PRE-CRASH LOG-----\n", stderr);
+ fputs(g_crash_buf, stderr);
+ fputs("\n-----END PERFETTO PRE-CRASH LOG-----\n", stderr);
+#endif
+}
+#endif // PERFETTO_ENABLE_LOG_RING_BUFFER
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/metatrace.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/metatrace.h
+// gen_amalgamated begin header: include/perfetto/ext/base/metatrace_events.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_METATRACE_EVENTS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_METATRACE_EVENTS_H_
+
+#include <stdint.h>
+
+namespace perfetto {
+namespace metatrace {
+
+enum Tags : uint32_t {
+ TAG_NONE = 0,
+ TAG_ANY = uint32_t(-1),
+ TAG_FTRACE = 1 << 0,
+ TAG_PROC_POLLERS = 1 << 1,
+ TAG_TRACE_WRITER = 1 << 2,
+ TAG_TRACE_SERVICE = 1 << 3,
+ TAG_PRODUCER = 1 << 4,
+};
+
+// The macros below generate matching enums and arrays of string literals.
+// This is to avoid maintaining string maps manually.
+
+// clang-format off
+
+// DO NOT remove or reshuffle items in this list, only append. The ID of these
+// events are an ABI, the trace processor relies on these to open old traces.
+#define PERFETTO_METATRACE_EVENTS(F) \
+ F(EVENT_ZERO_UNUSED), \
+ F(FTRACE_CPU_READER_READ), /*unused*/ \
+ F(FTRACE_DRAIN_CPUS), /*unused*/ \
+ F(FTRACE_UNBLOCK_READERS), /*unused*/ \
+ F(FTRACE_CPU_READ_NONBLOCK), /*unused*/ \
+ F(FTRACE_CPU_READ_BLOCK), /*unused*/ \
+ F(FTRACE_CPU_SPLICE_NONBLOCK), /*unused*/ \
+ F(FTRACE_CPU_SPLICE_BLOCK), /*unused*/ \
+ F(FTRACE_CPU_WAIT_CMD), /*unused*/ \
+ F(FTRACE_CPU_RUN_CYCLE), /*unused*/ \
+ F(FTRACE_CPU_FLUSH), \
+ F(FTRACE_CPU_BUFFER_WATERMARK), \
+ F(READ_SYS_STATS), \
+ F(PS_WRITE_ALL_PROCESSES), \
+ F(PS_ON_PIDS), \
+ F(PS_ON_RENAME_PIDS), \
+ F(PS_WRITE_ALL_PROCESS_STATS), \
+ F(TRACE_WRITER_COMMIT_STARTUP_WRITER_BATCH), \
+ F(FTRACE_READ_TICK), \
+ F(FTRACE_CPU_READ_CYCLE), \
+ F(FTRACE_CPU_READ_BATCH), \
+ F(KALLSYMS_PARSE), \
+ F(PROFILER_READ_TICK), \
+ F(PROFILER_READ_CPU), \
+ F(PROFILER_UNWIND_TICK), \
+ F(PROFILER_UNWIND_SAMPLE), \
+ F(PROFILER_UNWIND_INITIAL_ATTEMPT), \
+ F(PROFILER_UNWIND_ATTEMPT), \
+ F(PROFILER_MAPS_PARSE), \
+ F(PROFILER_MAPS_REPARSE), \
+ F(PROFILER_UNWIND_CACHE_CLEAR)
+
+// Append only, see above.
+//
+// Values that aren't used as counters:
+// * FTRACE_SERVICE_COMMIT_DATA is a bit-packed representation of an event, see
+// tracing_service_impl.cc for the format.
+// * PROFILER_UNWIND_CURRENT_PID represents the PID that is being unwound.
+//
+#define PERFETTO_METATRACE_COUNTERS(F) \
+ F(COUNTER_ZERO_UNUSED),\
+ F(FTRACE_PAGES_DRAINED), \
+ F(PS_PIDS_SCANNED), \
+ F(TRACE_SERVICE_COMMIT_DATA), \
+ F(PROFILER_UNWIND_QUEUE_SZ), \
+ F(PROFILER_UNWIND_CURRENT_PID)
+
+// clang-format on
+
+#define PERFETTO_METATRACE_IDENTITY(name) name
+#define PERFETTO_METATRACE_TOSTRING(name) #name
+
+enum Events : uint16_t {
+ PERFETTO_METATRACE_EVENTS(PERFETTO_METATRACE_IDENTITY),
+ EVENTS_MAX
+};
+constexpr char const* kEventNames[] = {
+ PERFETTO_METATRACE_EVENTS(PERFETTO_METATRACE_TOSTRING)};
+
+enum Counters : uint16_t {
+ PERFETTO_METATRACE_COUNTERS(PERFETTO_METATRACE_IDENTITY),
+ COUNTERS_MAX
+};
+constexpr char const* kCounterNames[] = {
+ PERFETTO_METATRACE_COUNTERS(PERFETTO_METATRACE_TOSTRING)};
+
+inline void SuppressUnusedVarsInAmalgamatedBuild() {
+ (void)kCounterNames;
+ (void)kEventNames;
+}
+
+} // namespace metatrace
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_METATRACE_EVENTS_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_METATRACE_H_
+#define INCLUDE_PERFETTO_EXT_BASE_METATRACE_H_
+
+#include <array>
+#include <atomic>
+#include <functional>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/metatrace_events.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+// A facility to trace execution of the perfetto codebase itself.
+// The meta-tracing framework is organized into three layers:
+//
+// 1. A static ring-buffer in base/ (this file) that supports concurrent writes
+// and a single reader.
+// The responsibility of this layer is to store events and counters as
+// efficiently as possible without re-entering any tracing code.
+// This is really a static-storage-based ring-buffer based on a POD array.
+// This layer does NOT deal with serializing the meta-trace buffer.
+// It posts a task when it's half full and expects something outside of
+// base/ to drain the ring-buffer and serialize it, eventually writing it
+// into the trace itself, before it gets 100% full.
+//
+// 2. A class in tracing/core which takes care of serializing the meta-trace
+// buffer into the trace using a TraceWriter. See metatrace_writer.h .
+//
+// 3. A data source in traced_probes that, when be enabled via the trace config,
+// injects metatrace events into the trace. See metatrace_data_source.h .
+//
+// The available events and tags are defined in metatrace_events.h .
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+namespace metatrace {
+
+// Meta-tracing is organized in "tags" that can be selectively enabled. This is
+// to enable meta-tracing only of one sub-system. This word has one "enabled"
+// bit for each tag. 0 -> meta-tracing off.
+extern std::atomic<uint32_t> g_enabled_tags;
+
+// Time of the Enable() call. Used as a reference for keeping delta timestmaps
+// in Record.
+extern std::atomic<uint64_t> g_enabled_timestamp;
+
+// Enables meta-tracing for one or more tags. Once enabled it will discard any
+// further Enable() calls and return false until disabled,
+// |read_task| is a closure that will be called enqueued |task_runner| when the
+// meta-tracing ring buffer is half full. The task is expected to read the ring
+// buffer using RingBuffer::GetReadIterator() and serialize the contents onto a
+// file or into the trace itself.
+// Must be called on the |task_runner| passed.
+// |task_runner| must have static lifetime.
+bool Enable(std::function<void()> read_task, base::TaskRunner*, uint32_t tags);
+
+// Disables meta-tracing.
+// Must be called on the same |task_runner| as Enable().
+void Disable();
+
+inline uint64_t TraceTimeNowNs() {
+ return static_cast<uint64_t>(base::GetBootTimeNs().count());
+}
+
+// Returns a relaxed view of whether metatracing is enabled for the given tag.
+// Useful for skipping unnecessary argument computation if metatracing is off.
+inline bool IsEnabled(uint32_t tag) {
+ auto enabled_tags = g_enabled_tags.load(std::memory_order_relaxed);
+ return PERFETTO_UNLIKELY((enabled_tags & tag) != 0);
+}
+
+// Holds the data for a metatrace event or counter.
+struct Record {
+ static constexpr uint16_t kTypeMask = 0x8000;
+ static constexpr uint16_t kTypeCounter = 0x8000;
+ static constexpr uint16_t kTypeEvent = 0;
+
+ uint64_t timestamp_ns() const {
+ auto base_ns = g_enabled_timestamp.load(std::memory_order_relaxed);
+ PERFETTO_DCHECK(base_ns);
+ return base_ns + ((static_cast<uint64_t>(timestamp_ns_high) << 32) |
+ timestamp_ns_low);
+ }
+
+ void set_timestamp(uint64_t ts) {
+ auto t_start = g_enabled_timestamp.load(std::memory_order_relaxed);
+ uint64_t diff = ts - t_start;
+ PERFETTO_DCHECK(diff < (1ull << 48));
+ timestamp_ns_low = static_cast<uint32_t>(diff);
+ timestamp_ns_high = static_cast<uint16_t>(diff >> 32);
+ }
+
+ // We can't just memset() this class because on MSVC std::atomic<> is not
+ // trivially constructible anymore. Also std::atomic<> has a deleted copy
+ // constructor so we cant just do "*this = Record()" either.
+ // See http://bit.ly/339Jlzd .
+ void clear() {
+ this->~Record();
+ new (this) Record();
+ }
+
+ // This field holds the type (counter vs event) in the MSB and event ID (as
+ // defined in metatrace_events.h) in the lowest 15 bits. It is also used also
+ // as a linearization point: this is always written after all the other
+ // fields with a release-store. This is so the reader can determine whether it
+ // can safely process the other event fields after a load-acquire.
+ std::atomic<uint16_t> type_and_id{};
+
+ // Timestamp is stored as a 48-bits value diffed against g_enabled_timestamp.
+ // This gives us 78 hours from Enabled().
+ uint16_t timestamp_ns_high = 0;
+ uint32_t timestamp_ns_low = 0;
+
+ uint32_t thread_id = 0;
+
+ union {
+ // Only one of the two elements can be zero initialized, clang complains
+ // about "initializing multiple members of union" otherwise.
+ uint32_t duration_ns = 0; // If type == event.
+ int32_t counter_value; // If type == counter.
+ };
+};
+
+// Hold the meta-tracing data into a statically allocated array.
+// This class uses static storage (as opposite to being a singleton) to:
+// - Have the guarantee of always valid storage, so that meta-tracing can be
+// safely used in any part of the codebase, including base/ itself.
+// - Avoid barriers that thread-safe static locals would require.
+class RingBuffer {
+ public:
+ static constexpr size_t kCapacity = 4096; // 4096 * 16 bytes = 64K.
+
+ // This iterator is not idempotent and will bump the read index in the buffer
+ // at the end of the reads. There can be only one reader at any time.
+ // Usage: for (auto it = RingBuffer::GetReadIterator(); it; ++it) { it->... }
+ class ReadIterator {
+ public:
+ ReadIterator(ReadIterator&& other) {
+ PERFETTO_DCHECK(other.valid_);
+ cur_ = other.cur_;
+ end_ = other.end_;
+ valid_ = other.valid_;
+ other.valid_ = false;
+ }
+
+ ~ReadIterator() {
+ if (!valid_)
+ return;
+ PERFETTO_DCHECK(cur_ >= RingBuffer::rd_index_);
+ PERFETTO_DCHECK(cur_ <= RingBuffer::wr_index_);
+ RingBuffer::rd_index_.store(cur_, std::memory_order_release);
+ }
+
+ explicit operator bool() const { return cur_ < end_; }
+ const Record* operator->() const { return RingBuffer::At(cur_); }
+ const Record& operator*() const { return *operator->(); }
+
+ // This is for ++it. it++ is deliberately not supported.
+ ReadIterator& operator++() {
+ PERFETTO_DCHECK(cur_ < end_);
+ // Once a record has been read, mark it as free clearing its type_and_id,
+ // so if we encounter it in another read iteration while being written
+ // we know it's not fully written yet.
+ // The memory_order_relaxed below is enough because:
+ // - The reader is single-threaded and doesn't re-read the same records.
+ // - Before starting a read batch, the reader has an acquire barrier on
+ // |rd_index_|.
+ // - After terminating a read batch, the ~ReadIterator dtor updates the
+ // |rd_index_| with a release-store.
+ // - Reader and writer are typically kCapacity/2 apart. So unless an
+ // overrun happens a writer won't reuse a newly released record any time
+ // soon. If an overrun happens, everything is busted regardless.
+ At(cur_)->type_and_id.store(0, std::memory_order_relaxed);
+ ++cur_;
+ return *this;
+ }
+
+ private:
+ friend class RingBuffer;
+ ReadIterator(uint64_t begin, uint64_t end)
+ : cur_(begin), end_(end), valid_(true) {}
+ ReadIterator& operator=(const ReadIterator&) = delete;
+ ReadIterator(const ReadIterator&) = delete;
+
+ uint64_t cur_;
+ uint64_t end_;
+ bool valid_;
+ };
+
+ static Record* At(uint64_t index) {
+ // Doesn't really have to be pow2, but if not the compiler will emit
+ // arithmetic operations to compute the modulo instead of a bitwise AND.
+ static_assert(!(kCapacity & (kCapacity - 1)), "kCapacity must be pow2");
+ PERFETTO_DCHECK(index >= rd_index_);
+ PERFETTO_DCHECK(index <= wr_index_);
+ return &records_[index % kCapacity];
+ }
+
+ // Must be called on the same task runner passed to Enable()
+ static ReadIterator GetReadIterator() {
+ PERFETTO_DCHECK(RingBuffer::IsOnValidTaskRunner());
+ return ReadIterator(rd_index_.load(std::memory_order_acquire),
+ wr_index_.load(std::memory_order_acquire));
+ }
+
+ static Record* AppendNewRecord();
+ static void Reset();
+
+ static bool has_overruns() {
+ return has_overruns_.load(std::memory_order_acquire);
+ }
+
+ // Can temporarily return a value >= kCapacity but is eventually consistent.
+ // This would happen in case of overruns until threads hit the --wr_index_
+ // in AppendNewRecord().
+ static uint64_t GetSizeForTesting() {
+ auto wr_index = wr_index_.load(std::memory_order_relaxed);
+ auto rd_index = rd_index_.load(std::memory_order_relaxed);
+ PERFETTO_DCHECK(wr_index >= rd_index);
+ return wr_index - rd_index;
+ }
+
+ private:
+ friend class ReadIterator;
+
+ // Returns true if the caller is on the task runner passed to Enable().
+ // Used only for DCHECKs.
+ static bool IsOnValidTaskRunner();
+
+ static std::array<Record, kCapacity> records_;
+ static std::atomic<bool> read_task_queued_;
+ static std::atomic<uint64_t> wr_index_;
+ static std::atomic<uint64_t> rd_index_;
+ static std::atomic<bool> has_overruns_;
+ static Record bankruptcy_record_; // Used in case of overruns.
+};
+
+inline void TraceCounter(uint32_t tag, uint16_t id, int32_t value) {
+ // memory_order_relaxed is okay because the storage has static lifetime.
+ // It is safe to accidentally log an event soon after disabling.
+ auto enabled_tags = g_enabled_tags.load(std::memory_order_relaxed);
+ if (PERFETTO_LIKELY((enabled_tags & tag) == 0))
+ return;
+ Record* record = RingBuffer::AppendNewRecord();
+ record->thread_id = static_cast<uint32_t>(base::GetThreadId());
+ record->set_timestamp(TraceTimeNowNs());
+ record->counter_value = value;
+ record->type_and_id.store(Record::kTypeCounter | id,
+ std::memory_order_release);
+}
+
+class ScopedEvent {
+ public:
+ ScopedEvent(uint32_t tag, uint16_t event_id) {
+ auto enabled_tags = g_enabled_tags.load(std::memory_order_relaxed);
+ if (PERFETTO_LIKELY((enabled_tags & tag) == 0))
+ return;
+ event_id_ = event_id;
+ record_ = RingBuffer::AppendNewRecord();
+ record_->thread_id = static_cast<uint32_t>(base::GetThreadId());
+ record_->set_timestamp(TraceTimeNowNs());
+ }
+
+ ~ScopedEvent() {
+ if (PERFETTO_LIKELY(!record_))
+ return;
+ auto now = TraceTimeNowNs();
+ record_->duration_ns = static_cast<uint32_t>(now - record_->timestamp_ns());
+ record_->type_and_id.store(Record::kTypeEvent | event_id_,
+ std::memory_order_release);
+ }
+
+ private:
+ Record* record_ = nullptr;
+ uint16_t event_id_ = 0;
+ ScopedEvent(const ScopedEvent&) = delete;
+ ScopedEvent& operator=(const ScopedEvent&) = delete;
+};
+
+// Boilerplate to derive a unique variable name for the event.
+#define PERFETTO_METATRACE_UID2(a, b) a##b
+#define PERFETTO_METATRACE_UID(x) PERFETTO_METATRACE_UID2(metatrace_, x)
+
+#define PERFETTO_METATRACE_SCOPED(TAG, ID) \
+ ::perfetto::metatrace::ScopedEvent PERFETTO_METATRACE_UID(__COUNTER__)( \
+ ::perfetto::metatrace::TAG, ::perfetto::metatrace::ID)
+
+#define PERFETTO_METATRACE_COUNTER(TAG, ID, VALUE) \
+ ::perfetto::metatrace::TraceCounter(::perfetto::metatrace::TAG, \
+ ::perfetto::metatrace::ID, \
+ static_cast<int32_t>(VALUE))
+
+} // namespace metatrace
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_METATRACE_H_
+// gen_amalgamated begin header: include/perfetto/base/task_runner.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_
+#define INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_
+
+#include <stdint.h>
+
+#include <functional>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+
+namespace perfetto {
+namespace base {
+
+// A generic interface to allow the library clients to interleave the execution
+// of the tracing internals in their runtime environment.
+// The expectation is that all tasks, which are queued either via PostTask() or
+// AddFileDescriptorWatch(), are executed on the same sequence (either on the
+// same thread, or on a thread pool that gives sequencing guarantees).
+//
+// Tasks are never executed synchronously inside PostTask and there is a full
+// memory barrier between tasks.
+//
+// All methods of this interface can be called from any thread.
+class PERFETTO_EXPORT_COMPONENT TaskRunner {
+ public:
+ virtual ~TaskRunner();
+
+ // Schedule a task for immediate execution. Immediate tasks are always
+ // executed in the order they are posted. Can be called from any thread.
+ virtual void PostTask(std::function<void()>) = 0;
+
+ // Schedule a task for execution after |delay_ms|. Note that there is no
+ // strict ordering guarantee between immediate and delayed tasks. Can be
+ // called from any thread.
+ virtual void PostDelayedTask(std::function<void()>, uint32_t delay_ms) = 0;
+
+ // Schedule a task to run when the handle becomes readable. The same handle
+ // can only be monitored by one function. Note that this function only needs
+ // to be implemented on platforms where the built-in ipc framework is used.
+ // Can be called from any thread.
+ // TODO(skyostil): Refactor this out of the shared interface.
+ virtual void AddFileDescriptorWatch(PlatformHandle,
+ std::function<void()>) = 0;
+
+ // Remove a previously scheduled watch for the handle. If this is run on the
+ // target thread of this TaskRunner, guarantees that the task registered to
+ // this handle will not be executed after this function call.
+ // Can be called from any thread.
+ virtual void RemoveFileDescriptorWatch(PlatformHandle) = 0;
+
+ // Checks if the current thread is the same thread where the TaskRunner's task
+ // run. This allows single threaded task runners (like the ones used in
+ // perfetto) to inform the caller that anything posted will run on the same
+ // thread/sequence. This can allow some callers to skip PostTask and instead
+ // directly execute the code. Can be called from any thread.
+ virtual bool RunsTasksOnCurrentThread() const = 0;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/metatrace.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_annotations.h"
+
+namespace perfetto {
+namespace metatrace {
+
+std::atomic<uint32_t> g_enabled_tags{0};
+std::atomic<uint64_t> g_enabled_timestamp{0};
+
+// static members
+std::array<Record, RingBuffer::kCapacity> RingBuffer::records_;
+std::atomic<bool> RingBuffer::read_task_queued_;
+std::atomic<uint64_t> RingBuffer::wr_index_;
+std::atomic<uint64_t> RingBuffer::rd_index_;
+std::atomic<bool> RingBuffer::has_overruns_;
+Record RingBuffer::bankruptcy_record_;
+
+namespace {
+
+// std::function<> is not trivially de/constructible. This struct wraps it in a
+// heap-allocated struct to avoid static initializers.
+struct Delegate {
+ static Delegate* GetInstance() {
+ static Delegate* instance = new Delegate();
+ return instance;
+ }
+
+ base::TaskRunner* task_runner = nullptr;
+ std::function<void()> read_task;
+};
+
+} // namespace
+
+bool Enable(std::function<void()> read_task,
+ base::TaskRunner* task_runner,
+ uint32_t tags) {
+ PERFETTO_DCHECK(read_task);
+ PERFETTO_DCHECK(task_runner->RunsTasksOnCurrentThread());
+ if (g_enabled_tags.load(std::memory_order_acquire))
+ return false;
+
+ Delegate* dg = Delegate::GetInstance();
+ dg->task_runner = task_runner;
+ dg->read_task = std::move(read_task);
+ RingBuffer::Reset();
+ g_enabled_timestamp.store(TraceTimeNowNs(), std::memory_order_relaxed);
+ g_enabled_tags.store(tags, std::memory_order_release);
+ return true;
+}
+
+void Disable() {
+ g_enabled_tags.store(0, std::memory_order_release);
+ Delegate* dg = Delegate::GetInstance();
+ PERFETTO_DCHECK(!dg->task_runner ||
+ dg->task_runner->RunsTasksOnCurrentThread());
+ dg->task_runner = nullptr;
+ dg->read_task = nullptr;
+}
+
+// static
+void RingBuffer::Reset() {
+ bankruptcy_record_.clear();
+ for (Record& record : records_)
+ record.clear();
+ wr_index_ = 0;
+ rd_index_ = 0;
+ has_overruns_ = false;
+ read_task_queued_ = false;
+}
+
+// static
+Record* RingBuffer::AppendNewRecord() {
+ auto wr_index = wr_index_.fetch_add(1, std::memory_order_acq_rel);
+
+ // rd_index can only monotonically increase, we don't care if we read an
+ // older value, we'll just hit the slow-path a bit earlier if it happens.
+ auto rd_index = rd_index_.load(std::memory_order_relaxed);
+
+ PERFETTO_DCHECK(wr_index >= rd_index);
+ auto size = wr_index - rd_index;
+ if (PERFETTO_LIKELY(size < kCapacity / 2))
+ return At(wr_index);
+
+ // Slow-path: Enqueue the read task and handle overruns.
+ bool expected = false;
+ if (RingBuffer::read_task_queued_.compare_exchange_strong(expected, true)) {
+ Delegate* dg = Delegate::GetInstance();
+ if (dg->task_runner) {
+ dg->task_runner->PostTask([] {
+ // Meta-tracing might have been disabled in the meantime.
+ auto read_task = Delegate::GetInstance()->read_task;
+ if (read_task)
+ read_task();
+ RingBuffer::read_task_queued_ = false;
+ });
+ }
+ }
+
+ if (PERFETTO_LIKELY(size < kCapacity))
+ return At(wr_index);
+
+ has_overruns_.store(true, std::memory_order_release);
+ wr_index_.fetch_sub(1, std::memory_order_acq_rel);
+
+ // In the case of overflows, threads will race writing on the same memory
+ // location and TSan will rightly complain. This is fine though because nobody
+ // will read the bankruptcy record and it's designed to contain garbage.
+ PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(&bankruptcy_record_, sizeof(Record),
+ "nothing reads bankruptcy_record_")
+ return &bankruptcy_record_;
+}
+
+// static
+bool RingBuffer::IsOnValidTaskRunner() {
+ auto* task_runner = Delegate::GetInstance()->task_runner;
+ return task_runner && task_runner->RunsTasksOnCurrentThread();
+}
+
+} // namespace metatrace
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/paged_memory.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/paged_memory.h
+// gen_amalgamated begin header: include/perfetto/ext/base/container_annotations.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_CONTAINER_ANNOTATIONS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_CONTAINER_ANNOTATIONS_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+// Windows ASAN doesn't currently support these annotations.
+#if defined(ADDRESS_SANITIZER) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !defined(ADDRESS_SANITIZER_WITHOUT_INSTRUMENTATION)
+
+#include <sanitizer/common_interface_defs.h>
+
+#define ANNOTATE_NEW_BUFFER(buffer, capacity, new_size) \
+ if (buffer) { \
+ __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
+ (buffer) + (capacity), \
+ (buffer) + (new_size)); \
+ }
+#define ANNOTATE_DELETE_BUFFER(buffer, capacity, old_size) \
+ if (buffer) { \
+ __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
+ (buffer) + (old_size), \
+ (buffer) + (capacity)); \
+ }
+#define ANNOTATE_CHANGE_SIZE(buffer, capacity, old_size, new_size) \
+ if (buffer) { \
+ __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
+ (buffer) + (old_size), \
+ (buffer) + (new_size)); \
+ }
+#define ANNOTATE_CHANGE_CAPACITY(buffer, old_capacity, buffer_size, \
+ new_capacity) \
+ ANNOTATE_DELETE_BUFFER(buffer, old_capacity, buffer_size); \
+ ANNOTATE_NEW_BUFFER(buffer, new_capacity, buffer_size);
+// Annotations require buffers to begin on an 8-byte boundary.
+#else // defined(ADDRESS_SANITIZER)
+#define ANNOTATE_NEW_BUFFER(buffer, capacity, new_size)
+#define ANNOTATE_DELETE_BUFFER(buffer, capacity, old_size)
+#define ANNOTATE_CHANGE_SIZE(buffer, capacity, old_size, new_size)
+#define ANNOTATE_CHANGE_CAPACITY(buffer, old_capacity, buffer_size, \
+ new_capacity)
+#endif // defined(ADDRESS_SANITIZER)
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_CONTAINER_ANNOTATIONS_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
+#define INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
+
+#include <cstddef>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/container_annotations.h"
+
+// We need to track the committed size on windows and when ASAN is enabled.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || defined(ADDRESS_SANITIZER)
+#define TRACK_COMMITTED_SIZE() 1
+#else
+#define TRACK_COMMITTED_SIZE() 0
+#endif
+
+namespace perfetto {
+namespace base {
+
+class PagedMemory {
+ public:
+ // Initializes an invalid PagedMemory pointing to nullptr.
+ PagedMemory();
+
+ ~PagedMemory();
+
+ PagedMemory(PagedMemory&& other) noexcept;
+ PagedMemory& operator=(PagedMemory&& other);
+
+ enum AllocationFlags {
+ // By default, Allocate() crashes if the underlying mmap fails (e.g., if out
+ // of virtual address space). When this flag is provided, an invalid
+ // PagedMemory pointing to nullptr is returned in this case instead.
+ kMayFail = 1 << 0,
+
+ // By default, Allocate() commits the allocated memory immediately. When
+ // this flag is provided, the memory virtual address space may only be
+ // reserved and the user should call EnsureCommitted() before writing to
+ // memory addresses.
+ kDontCommit = 1 << 1,
+ };
+
+ // Allocates |size| bytes using mmap(MAP_ANONYMOUS). The returned memory is
+ // guaranteed to be page-aligned and guaranteed to be zeroed.
+ // For |flags|, see the AllocationFlags enum above.
+ static PagedMemory Allocate(size_t size, int flags = 0);
+
+ // Hint to the OS that the memory range is not needed and can be discarded.
+ // The memory remains accessible and its contents may be retained, or they
+ // may be zeroed. This function may be a NOP on some platforms. Returns true
+ // if implemented.
+ bool AdviseDontNeed(void* p, size_t size);
+
+ // Ensures that at least the first |committed_size| bytes of the allocated
+ // memory region are committed. The implementation may commit memory in larger
+ // chunks above |committed_size|. Crashes if the memory couldn't be committed.
+#if TRACK_COMMITTED_SIZE()
+ void EnsureCommitted(size_t committed_size);
+#else // TRACK_COMMITTED_SIZE()
+ void EnsureCommitted(size_t /*committed_size*/) {}
+#endif // TRACK_COMMITTED_SIZE()
+
+ inline void* Get() const noexcept { return p_; }
+ inline bool IsValid() const noexcept { return !!p_; }
+ inline size_t size() const noexcept { return size_; }
+
+ private:
+ PagedMemory(char* p, size_t size);
+
+ PagedMemory(const PagedMemory&) = delete;
+ // Defaulted for implementation of move constructor + assignment.
+ PagedMemory& operator=(const PagedMemory&) = default;
+
+ char* p_ = nullptr;
+
+ // The size originally passed to Allocate(). The actual virtual memory
+ // reservation will be larger due to: (i) guard pages; (ii) rounding up to
+ // the system page size.
+ size_t size_ = 0;
+
+#if TRACK_COMMITTED_SIZE()
+ size_t committed_size_ = 0u;
+#endif // TRACK_COMMITTED_SIZE()
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/paged_memory.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <sys/mman.h>
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/container_annotations.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+namespace {
+
+#if TRACK_COMMITTED_SIZE()
+constexpr size_t kCommitChunkSize = 4 * 1024 * 1024; // 4MB
+#endif
+
+size_t RoundUpToSysPageSize(size_t req_size) {
+ const size_t page_size = GetSysPageSize();
+ return (req_size + page_size - 1) & ~(page_size - 1);
+}
+
+size_t GuardSize() {
+ return GetSysPageSize();
+}
+
+} // namespace
+
+// static
+PagedMemory PagedMemory::Allocate(size_t req_size, int flags) {
+ size_t rounded_up_size = RoundUpToSysPageSize(req_size);
+ PERFETTO_CHECK(rounded_up_size >= req_size);
+ size_t outer_size = rounded_up_size + GuardSize() * 2;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ void* ptr = VirtualAlloc(nullptr, outer_size, MEM_RESERVE, PAGE_NOACCESS);
+ if (!ptr && (flags & kMayFail))
+ return PagedMemory();
+ PERFETTO_CHECK(ptr);
+ char* usable_region = reinterpret_cast<char*>(ptr) + GuardSize();
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ void* ptr = mmap(nullptr, outer_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (ptr == MAP_FAILED && (flags & kMayFail))
+ return PagedMemory();
+ PERFETTO_CHECK(ptr && ptr != MAP_FAILED);
+ char* usable_region = reinterpret_cast<char*>(ptr) + GuardSize();
+ int res = mprotect(ptr, GuardSize(), PROT_NONE);
+ res |= mprotect(usable_region + rounded_up_size, GuardSize(), PROT_NONE);
+ PERFETTO_CHECK(res == 0);
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+ auto memory = PagedMemory(usable_region, req_size);
+#if TRACK_COMMITTED_SIZE()
+ size_t initial_commit = req_size;
+ if (flags & kDontCommit)
+ initial_commit = std::min(initial_commit, kCommitChunkSize);
+ memory.EnsureCommitted(initial_commit);
+#endif // TRACK_COMMITTED_SIZE()
+ return memory;
+}
+
+PagedMemory::PagedMemory() {}
+
+// clang-format off
+PagedMemory::PagedMemory(char* p, size_t size) : p_(p), size_(size) {
+ ANNOTATE_NEW_BUFFER(p_, size_, committed_size_)
+}
+
+PagedMemory::PagedMemory(PagedMemory&& other) noexcept {
+ *this = other;
+ other.p_ = nullptr;
+}
+// clang-format on
+
+PagedMemory& PagedMemory::operator=(PagedMemory&& other) {
+ this->~PagedMemory();
+ new (this) PagedMemory(std::move(other));
+ return *this;
+}
+
+PagedMemory::~PagedMemory() {
+ if (!p_)
+ return;
+ PERFETTO_CHECK(size_);
+ char* start = p_ - GuardSize();
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ BOOL res = VirtualFree(start, 0, MEM_RELEASE);
+ PERFETTO_CHECK(res != 0);
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ const size_t outer_size = RoundUpToSysPageSize(size_) + GuardSize() * 2;
+ int res = munmap(start, outer_size);
+ PERFETTO_CHECK(res == 0);
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ ANNOTATE_DELETE_BUFFER(p_, size_, committed_size_)
+}
+
+bool PagedMemory::AdviseDontNeed(void* p, size_t size) {
+ PERFETTO_DCHECK(p_);
+ PERFETTO_DCHECK(p >= p_);
+ PERFETTO_DCHECK(static_cast<char*>(p) + size <= p_ + size_);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+ // Discarding pages on Windows has more CPU cost than is justified for the
+ // possible memory savings.
+ return false;
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
+ // PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+ // http://man7.org/linux/man-pages/man2/madvise.2.html
+ int res = madvise(p, size, MADV_DONTNEED);
+ PERFETTO_DCHECK(res == 0);
+ return true;
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
+ // PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+}
+
+#if TRACK_COMMITTED_SIZE()
+void PagedMemory::EnsureCommitted(size_t committed_size) {
+ PERFETTO_DCHECK(committed_size <= size_);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (committed_size_ >= committed_size)
+ return;
+ // Rounding up.
+ size_t delta = committed_size - committed_size_;
+ size_t num_additional_chunks =
+ (delta + kCommitChunkSize - 1) / kCommitChunkSize;
+ PERFETTO_DCHECK(num_additional_chunks * kCommitChunkSize >= delta);
+ // Don't commit more than the total size.
+ size_t commit_size = std::min(num_additional_chunks * kCommitChunkSize,
+ size_ - committed_size_);
+ void* res = VirtualAlloc(p_ + committed_size_, commit_size, MEM_COMMIT,
+ PAGE_READWRITE);
+ PERFETTO_CHECK(res);
+ ANNOTATE_CHANGE_SIZE(p_, size_, committed_size_,
+ committed_size_ + commit_size)
+ committed_size_ += commit_size;
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // mmap commits automatically as needed, so we only track here for ASAN.
+ committed_size = std::max(committed_size_, committed_size);
+ ANNOTATE_CHANGE_SIZE(p_, size_, committed_size_, committed_size)
+ committed_size_ = committed_size;
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+}
+#endif // TRACK_COMMITTED_SIZE()
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/periodic_task.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/periodic_task.h
+// gen_amalgamated begin header: include/perfetto/ext/base/thread_checker.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_
+#define INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <pthread.h>
+#endif
+#include <atomic>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using ThreadID = unsigned long;
+#else
+using ThreadID = pthread_t;
+#endif
+
+class PERFETTO_EXPORT_COMPONENT ThreadChecker {
+ public:
+ ThreadChecker();
+ ~ThreadChecker();
+ ThreadChecker(const ThreadChecker&);
+ ThreadChecker& operator=(const ThreadChecker&);
+ bool CalledOnValidThread() const PERFETTO_WARN_UNUSED_RESULT;
+ void DetachFromThread();
+
+ private:
+ mutable std::atomic<ThreadID> thread_id_;
+};
+
+#if PERFETTO_DCHECK_IS_ON() && !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
+// TODO(primiano) Use Chromium's thread checker in Chromium.
+#define PERFETTO_THREAD_CHECKER(name) base::ThreadChecker name;
+#define PERFETTO_DCHECK_THREAD(name) \
+ PERFETTO_DCHECK((name).CalledOnValidThread())
+#define PERFETTO_DETACH_FROM_THREAD(name) (name).DetachFromThread()
+#else
+#define PERFETTO_THREAD_CHECKER(name)
+#define PERFETTO_DCHECK_THREAD(name)
+#define PERFETTO_DETACH_FROM_THREAD(name)
+#endif // PERFETTO_DCHECK_IS_ON()
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_
+// gen_amalgamated begin header: include/perfetto/ext/base/weak_ptr.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
+#define INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+
+#include <memory>
+
+namespace perfetto {
+namespace base {
+
+// A simple WeakPtr for single-threaded cases.
+// Generally keep the WeakPtrFactory as last fields in classes: it makes the
+// WeakPtr(s) invalidate as first thing in the class dtor.
+// Usage:
+// class MyClass {
+// MyClass() : weak_factory_(this) {}
+// WeakPtr<MyClass> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
+//
+// private:
+// WeakPtrFactory<MyClass> weak_factory_;
+// }
+//
+// int main() {
+// std::unique_ptr<MyClass> foo(new MyClass);
+// auto wptr = foo.GetWeakPtr();
+// ASSERT_TRUE(wptr);
+// ASSERT_EQ(foo.get(), wptr->get());
+// foo.reset();
+// ASSERT_FALSE(wptr);
+// ASSERT_EQ(nullptr, wptr->get());
+// }
+
+template <typename T>
+class WeakPtrFactory; // Forward declaration, defined below.
+
+template <typename T>
+class WeakPtr {
+ public:
+ WeakPtr() {}
+ WeakPtr(const WeakPtr&) = default;
+ WeakPtr& operator=(const WeakPtr&) = default;
+ WeakPtr(WeakPtr&&) = default;
+ WeakPtr& operator=(WeakPtr&&) = default;
+
+ T* get() const {
+ PERFETTO_DCHECK_THREAD(thread_checker);
+ return handle_ ? *handle_.get() : nullptr;
+ }
+ T* operator->() const { return get(); }
+ T& operator*() const { return *get(); }
+
+ explicit operator bool() const { return !!get(); }
+
+ private:
+ friend class WeakPtrFactory<T>;
+ explicit WeakPtr(const std::shared_ptr<T*>& handle) : handle_(handle) {}
+
+ std::shared_ptr<T*> handle_;
+ PERFETTO_THREAD_CHECKER(thread_checker)
+};
+
+template <typename T>
+class WeakPtrFactory {
+ public:
+ explicit WeakPtrFactory(T* owner) : weak_ptr_(std::make_shared<T*>(owner)) {
+ PERFETTO_DCHECK_THREAD(thread_checker);
+ }
+
+ ~WeakPtrFactory() {
+ PERFETTO_DCHECK_THREAD(thread_checker);
+ *(weak_ptr_.handle_.get()) = nullptr;
+ }
+
+ // Can be safely called on any thread, since it simply copies |weak_ptr_|.
+ // Note that any accesses to the returned pointer need to be made on the
+ // thread that created/reset the factory.
+ WeakPtr<T> GetWeakPtr() const { return weak_ptr_; }
+
+ // Reset the factory to a new owner & thread. May only be called before any
+ // weak pointers were passed out. Future weak pointers will be valid on the
+ // calling thread.
+ void Reset(T* owner) {
+ // Reset thread checker to current thread.
+ PERFETTO_DETACH_FROM_THREAD(thread_checker);
+ PERFETTO_DCHECK_THREAD(thread_checker);
+
+ // We should not have passed out any weak pointers yet at this point.
+ PERFETTO_DCHECK(weak_ptr_.handle_.use_count() == 1);
+
+ weak_ptr_ = WeakPtr<T>(std::make_shared<T*>(owner));
+ }
+
+ private:
+ WeakPtrFactory(const WeakPtrFactory&) = delete;
+ WeakPtrFactory& operator=(const WeakPtrFactory&) = delete;
+
+ WeakPtr<T> weak_ptr_;
+ PERFETTO_THREAD_CHECKER(thread_checker)
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
+#define INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
+
+#include <functional>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+
+namespace perfetto {
+namespace base {
+
+class TaskRunner;
+
+// A periodic task utility class. It wraps the logic necessary to do periodic
+// tasks using a TaskRunner, taking care of subtleties like ensuring that
+// outstanding tasks are cancelled after reset/dtor.
+// Tasks are aligned on wall time (unless they are |one_shot|). This is to
+// ensure that when using multiple periodic tasks, they happen at the same time,
+// minimizing context switches.
+// On Linux/Android it also supports suspend-aware mode (via timerfd). On other
+// operating systems it falls back to PostDelayedTask, which is not
+// suspend-aware.
+// TODO(primiano): this should probably become a periodic timer scheduler, so we
+// can use one FD for everything rather than one FD per task. For now we take
+// the hit of a FD-per-task to keep this low-risk.
+// TODO(primiano): consider renaming this class to TimerTask. When |one_shot|
+// is set, the "Periodic" part of the class name becomes a lie.
+class PeriodicTask {
+ public:
+ explicit PeriodicTask(base::TaskRunner*);
+ ~PeriodicTask(); // Calls Reset().
+
+ struct Args {
+ uint32_t period_ms = 0;
+ std::function<void()> task = nullptr;
+ bool start_first_task_immediately = false;
+ bool use_suspend_aware_timer = false;
+ bool one_shot = false;
+ };
+
+ void Start(Args);
+
+ // Safe to be called multiple times, even without calling Start():
+ void Reset();
+
+ // No copy or move. WeakPtr-wrapped pointers to |this| are posted on the
+ // task runner, this class is not easily movable.
+ PeriodicTask(const PeriodicTask&) = delete;
+ PeriodicTask& operator=(const PeriodicTask&) = delete;
+ PeriodicTask(PeriodicTask&&) = delete;
+ PeriodicTask& operator=(PeriodicTask&&) = delete;
+
+ base::PlatformHandle timer_fd_for_testing() { return *timer_fd_; }
+
+ private:
+ static void RunTaskAndPostNext(base::WeakPtr<PeriodicTask>,
+ uint32_t generation);
+ void PostNextTask();
+ void ResetTimerFd();
+
+ base::TaskRunner* const task_runner_;
+ Args args_;
+ uint32_t generation_ = 0;
+ base::ScopedPlatformHandle timer_fd_;
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+ base::WeakPtrFactory<PeriodicTask> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/periodic_task.h"
+
+#include <limits>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ (PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && __ANDROID_API__ >= 19)
+#include <sys/timerfd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+namespace {
+
+uint32_t GetNextDelayMs(const TimeMillis& now_ms,
+ const PeriodicTask::Args& args) {
+ if (args.one_shot)
+ return args.period_ms;
+
+ return args.period_ms -
+ static_cast<uint32_t>(now_ms.count() % args.period_ms);
+}
+
+ScopedPlatformHandle CreateTimerFd(const PeriodicTask::Args& args) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ (PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && __ANDROID_API__ >= 19)
+ ScopedPlatformHandle tfd(
+ timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK));
+ uint32_t phase_ms = GetNextDelayMs(GetBootTimeMs(), args);
+
+ struct itimerspec its {};
+ // The "1 +" is to make sure that we never pass a zero it_value in the
+ // unlikely case of phase_ms being 0. That would cause the timer to be
+ // considered disarmed by timerfd_settime.
+ its.it_value.tv_sec = static_cast<time_t>(phase_ms / 1000u);
+ its.it_value.tv_nsec = 1 + static_cast<long>((phase_ms % 1000u) * 1000000u);
+ if (args.one_shot) {
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 0;
+ } else {
+ const uint32_t period_ms = args.period_ms;
+ its.it_interval.tv_sec = static_cast<time_t>(period_ms / 1000u);
+ its.it_interval.tv_nsec = static_cast<long>((period_ms % 1000u) * 1000000u);
+ }
+ if (timerfd_settime(*tfd, 0, &its, nullptr) < 0)
+ return ScopedPlatformHandle();
+ return tfd;
+#else
+ ignore_result(args);
+ return ScopedPlatformHandle();
+#endif
+}
+
+} // namespace
+
+PeriodicTask::PeriodicTask(TaskRunner* task_runner)
+ : task_runner_(task_runner), weak_ptr_factory_(this) {}
+
+PeriodicTask::~PeriodicTask() {
+ Reset();
+}
+
+void PeriodicTask::Start(Args args) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ Reset();
+ if (args.period_ms == 0 || !args.task) {
+ PERFETTO_DCHECK(args.period_ms > 0);
+ PERFETTO_DCHECK(args.task);
+ return;
+ }
+ args_ = std::move(args);
+ if (args_.use_suspend_aware_timer) {
+ timer_fd_ = CreateTimerFd(args_);
+ if (timer_fd_) {
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->AddFileDescriptorWatch(
+ *timer_fd_,
+ std::bind(PeriodicTask::RunTaskAndPostNext, weak_this, generation_));
+ } else {
+ PERFETTO_DPLOG("timerfd not supported, falling back on PostDelayedTask");
+ }
+ } // if (use_suspend_aware_timer).
+
+ if (!timer_fd_)
+ PostNextTask();
+
+ if (args_.start_first_task_immediately)
+ args_.task();
+}
+
+void PeriodicTask::PostNextTask() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(args_.period_ms > 0);
+ PERFETTO_DCHECK(!timer_fd_);
+ uint32_t delay_ms = GetNextDelayMs(GetWallTimeMs(), args_);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostDelayedTask(
+ std::bind(PeriodicTask::RunTaskAndPostNext, weak_this, generation_),
+ delay_ms);
+}
+
+// static
+// This function can be called in two ways (both from the TaskRunner):
+// 1. When using a timerfd, this task is registered as a FD watch.
+// 2. When using PostDelayedTask, this is the task posted on the TaskRunner.
+void PeriodicTask::RunTaskAndPostNext(WeakPtr<PeriodicTask> thiz,
+ uint32_t generation) {
+ if (!thiz || !thiz->args_.task || generation != thiz->generation_)
+ return; // Destroyed or Reset() in the meanwhile.
+ PERFETTO_DCHECK_THREAD(thiz->thread_checker_);
+ if (thiz->timer_fd_) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ PERFETTO_FATAL("timerfd for periodic tasks unsupported on Windows");
+#else
+ // If we are using a timerfd there is no need to repeatedly call
+ // PostDelayedTask(). The kernel will wakeup the timer fd periodically. We
+ // just need to read() it.
+ uint64_t ignored = 0;
+ errno = 0;
+ auto rsize = Read(*thiz->timer_fd_, &ignored, sizeof(&ignored));
+ if (rsize != sizeof(uint64_t)) {
+ if (errno == EAGAIN)
+ return; // A spurious wakeup. Rare, but can happen, just ignore.
+ PERFETTO_PLOG("read(timerfd) failed, falling back on PostDelayedTask");
+ thiz->ResetTimerFd();
+ }
+#endif
+ }
+
+ // Create a copy of the task to deal with either:
+ // 1. one_shot causing a Reset().
+ // 2. task() invoking internally Reset().
+ // That would cause a reset of the args_.task itself, which would invalidate
+ // the task bind state while we are invoking it.
+ auto task = thiz->args_.task;
+
+ // The repetition of the if() is to deal with the ResetTimerFd() case above.
+ if (thiz->args_.one_shot) {
+ thiz->Reset();
+ } else if (!thiz->timer_fd_) {
+ thiz->PostNextTask();
+ }
+
+ task();
+}
+
+void PeriodicTask::Reset() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ ++generation_;
+ args_ = Args();
+ PERFETTO_DCHECK(!args_.task);
+ ResetTimerFd();
+}
+
+void PeriodicTask::ResetTimerFd() {
+ if (!timer_fd_)
+ return;
+ task_runner_->RemoveFileDescriptorWatch(*timer_fd_);
+ timer_fd_.reset();
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/pipe.cc
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/pipe.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#include <fcntl.h> // For O_BINARY (Windows) and F_SETxx (UNIX)
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#include <namedpipeapi.h>
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+Pipe::Pipe() = default;
+Pipe::Pipe(Pipe&&) noexcept = default;
+Pipe& Pipe::operator=(Pipe&&) = default;
+
+Pipe Pipe::Create(Flags flags) {
+ PlatformHandle fds[2];
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ PERFETTO_CHECK(::CreatePipe(&fds[0], &fds[1], /*lpPipeAttributes=*/nullptr,
+ 0 /*default size*/));
+#else
+ PERFETTO_CHECK(pipe(fds) == 0);
+ PERFETTO_CHECK(fcntl(fds[0], F_SETFD, FD_CLOEXEC) == 0);
+ PERFETTO_CHECK(fcntl(fds[1], F_SETFD, FD_CLOEXEC) == 0);
+#endif
+ Pipe p;
+ p.rd.reset(fds[0]);
+ p.wr.reset(fds[1]);
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (flags == kBothNonBlock || flags == kRdNonBlock) {
+ int cur_flags = fcntl(*p.rd, F_GETFL, 0);
+ PERFETTO_CHECK(cur_flags >= 0);
+ PERFETTO_CHECK(fcntl(*p.rd, F_SETFL, cur_flags | O_NONBLOCK) == 0);
+ }
+
+ if (flags == kBothNonBlock || flags == kWrNonBlock) {
+ int cur_flags = fcntl(*p.wr, F_GETFL, 0);
+ PERFETTO_CHECK(cur_flags >= 0);
+ PERFETTO_CHECK(fcntl(*p.wr, F_SETFL, cur_flags | O_NONBLOCK) == 0);
+ }
+#else
+ PERFETTO_CHECK(flags == kBothBlock);
+#endif
+ return p;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/scoped_mmap.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/scoped_mmap.h
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_SCOPED_MMAP_H_
+#define INCLUDE_PERFETTO_EXT_BASE_SCOPED_MMAP_H_
+
+#include <cstddef>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#define PERFETTO_HAS_MMAP() 1
+#else
+#define PERFETTO_HAS_MMAP() 0
+#endif
+
+namespace perfetto::base {
+
+// RAII wrapper that holds ownership of an mmap()d area and of a file. Calls
+// unmap() and close() on destruction.
+class ScopedMmap {
+ public:
+ // Creates a memory mapping for the first `length` bytes of `file`.
+ static ScopedMmap FromHandle(base::ScopedPlatformHandle file, size_t length);
+
+ ScopedMmap() {}
+ ~ScopedMmap();
+ ScopedMmap(ScopedMmap&& other) noexcept;
+
+ ScopedMmap& operator=(ScopedMmap&& other) noexcept;
+
+ // Returns a pointer to the mapped memory area. Only valid if `IsValid()` is
+ // true.
+ void* data() const { return ptr_; }
+
+ // Returns true if this object contains a successfully mapped area.
+ bool IsValid() const { return ptr_ != nullptr; }
+
+ // Returns the length of the mapped area.
+ size_t length() const { return length_; }
+
+ // Unmaps the area and closes the file. Returns false if this held a mmap()d
+ // area and unmapping failed. In any case, after this method, `IsValid()` will
+ // return false.
+ bool reset() noexcept;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ // Takes ownership of an mmap()d area that starts at `data`, `size` bytes
+ // long. `data` should not be MAP_FAILED.
+ static ScopedMmap InheritMmappedRange(void* data, size_t size);
+#endif
+
+ private:
+ ScopedMmap(const ScopedMmap&) = delete;
+ ScopedMmap& operator=(const ScopedMmap&) = delete;
+
+ size_t length_ = 0;
+ void* ptr_ = nullptr;
+ ScopedPlatformHandle file_;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ ScopedPlatformHandle map_;
+#endif
+};
+
+// Tries to open `fname` and maps its first `length` bytes in memory.
+ScopedMmap ReadMmapFilePart(const char* fname, size_t length);
+
+// Tries to open `fname` and maps the whole file into memory.
+ScopedMmap ReadMmapWholeFile(const char* fname);
+
+} // namespace perfetto::base
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_SCOPED_MMAP_H_
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_mmap.h"
+
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <sys/mman.h>
+#include <unistd.h>
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#endif
+
+namespace perfetto::base {
+namespace {
+
+ScopedPlatformHandle OpenFileForMmap(const char* fname) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ return OpenFile(fname, O_RDONLY);
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // This does not use base::OpenFile to avoid getting an exclusive lock.
+ return ScopedPlatformHandle(CreateFileA(fname, GENERIC_READ, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, nullptr));
+#else
+ // mmap is not supported. Do not even open the file.
+ base::ignore_result(fname);
+ return ScopedPlatformHandle();
+#endif
+}
+
+} // namespace
+
+ScopedMmap::ScopedMmap(ScopedMmap&& other) noexcept {
+ *this = std::move(other);
+}
+
+ScopedMmap& ScopedMmap::operator=(ScopedMmap&& other) noexcept {
+ if (this == &other) {
+ return *this;
+ }
+ reset();
+ std::swap(ptr_, other.ptr_);
+ std::swap(length_, other.length_);
+ std::swap(file_, other.file_);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ std::swap(map_, other.map_);
+#endif
+ return *this;
+}
+
+ScopedMmap::~ScopedMmap() {
+ reset();
+}
+
+// static
+ScopedMmap ScopedMmap::FromHandle(base::ScopedPlatformHandle file,
+ size_t length) {
+ ScopedMmap ret;
+ if (!file) {
+ return ret;
+ }
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ void* ptr = mmap(nullptr, length, PROT_READ, MAP_PRIVATE, *file, 0);
+ if (ptr != MAP_FAILED) {
+ ret.ptr_ = ptr;
+ ret.length_ = length;
+ ret.file_ = std::move(file);
+ }
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ ScopedPlatformHandle map(
+ CreateFileMapping(*file, nullptr, PAGE_READONLY, 0, 0, nullptr));
+ if (!map) {
+ return ret;
+ }
+ void* ptr = MapViewOfFile(*map, FILE_MAP_READ, 0, 0, length);
+ if (ptr != nullptr) {
+ ret.ptr_ = ptr;
+ ret.length_ = length;
+ ret.file_ = std::move(file);
+ ret.map_ = std::move(map);
+ }
+#else
+ base::ignore_result(length);
+#endif
+ return ret;
+}
+
+bool ScopedMmap::reset() noexcept {
+ bool ret = true;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ if (ptr_ != nullptr) {
+ ret = munmap(ptr_, length_) == 0;
+ }
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (ptr_ != nullptr) {
+ ret = UnmapViewOfFile(ptr_);
+ }
+ map_.reset();
+#endif
+ ptr_ = nullptr;
+ length_ = 0;
+ file_.reset();
+ return ret;
+}
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+// static
+ScopedMmap ScopedMmap::InheritMmappedRange(void* data, size_t size) {
+ ScopedMmap ret;
+ ret.ptr_ = data;
+ ret.length_ = size;
+ return ret;
+}
+#endif
+
+ScopedMmap ReadMmapFilePart(const char* fname, size_t length) {
+ return ScopedMmap::FromHandle(OpenFileForMmap(fname), length);
+}
+
+ScopedMmap ReadMmapWholeFile(const char* fname) {
+ ScopedPlatformHandle file = OpenFileForMmap(fname);
+ if (!file) {
+ return ScopedMmap();
+ }
+ std::optional<uint64_t> file_size = GetFileSize(file.get());
+ if (!file_size.has_value()) {
+ return ScopedMmap();
+ }
+ size_t size = static_cast<size_t>(*file_size);
+ if (static_cast<uint64_t>(size) != *file_size) {
+ return ScopedMmap();
+ }
+ return ScopedMmap::FromHandle(std::move(file), size);
+}
+
+} // namespace perfetto::base
+// gen_amalgamated begin source: src/base/status.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/status.h"
+
+#include <stdarg.h>
+#include <algorithm>
+
+namespace perfetto {
+namespace base {
+
+Status ErrStatus(const char* format, ...) {
+ char buffer[1024];
+ va_list ap;
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_end(ap);
+ Status status(buffer);
+ return status;
+}
+
+std::optional<std::string_view> Status::GetPayload(
+ std::string_view type_url) const {
+ if (ok()) {
+ return std::nullopt;
+ }
+ for (const auto& kv : payloads_) {
+ if (kv.type_url == type_url) {
+ return kv.payload;
+ }
+ }
+ return std::nullopt;
+}
+
+void Status::SetPayload(std::string_view type_url, std::string value) {
+ if (ok()) {
+ return;
+ }
+ for (auto& kv : payloads_) {
+ if (kv.type_url == type_url) {
+ kv.payload = value;
+ return;
+ }
+ }
+ payloads_.push_back(Payload{std::string(type_url), std::move(value)});
+}
+
+bool Status::ErasePayload(std::string_view type_url) {
+ if (ok()) {
+ return false;
+ }
+ auto it = std::remove_if(
+ payloads_.begin(), payloads_.end(),
+ [type_url](const Payload& p) { return p.type_url == type_url; });
+ bool erased = it != payloads_.end();
+ payloads_.erase(it, payloads_.end());
+ return erased;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/string_splitter.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/string_splitter.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
+#define INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
+
+#include <string>
+
+namespace perfetto {
+namespace base {
+
+// C++ version of strtok(). Splits a string without making copies or any heap
+// allocations. Destructs the original string passed in input.
+// Supports the special case of using \0 as a delimiter.
+// The token returned in output are valid as long as the input string is valid.
+class StringSplitter {
+ public:
+ // Whether an empty string (two delimiters side-to-side) is a valid token.
+ enum class EmptyTokenMode {
+ DISALLOW_EMPTY_TOKENS,
+ ALLOW_EMPTY_TOKENS,
+
+ DEFAULT = DISALLOW_EMPTY_TOKENS,
+ };
+
+ // Can take ownership of the string if passed via std::move(), e.g.:
+ // StringSplitter(std::move(str), '\n');
+ StringSplitter(std::string,
+ char delimiter,
+ EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT);
+
+ // Splits a C-string. The input string will be forcefully null-terminated (so
+ // str[size - 1] should be == '\0' or the last char will be truncated).
+ StringSplitter(char* str,
+ size_t size,
+ char delimiter,
+ EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT);
+
+ // Splits the current token from an outer StringSplitter instance. This is to
+ // chain splitters as follows:
+ // for (base::StringSplitter lines(x, '\n'); ss.Next();)
+ // for (base::StringSplitter words(&lines, ' '); words.Next();)
+ StringSplitter(StringSplitter*,
+ char delimiter,
+ EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT);
+
+ // Returns true if a token is found (in which case it will be stored in
+ // cur_token()), false if no more tokens are found.
+ bool Next();
+
+ // Returns the current token iff last call to Next() returned true. In this
+ // case it guarantees that the returned string is always null terminated.
+ // In all other cases (before the 1st call to Next() and after Next() returns
+ // false) returns nullptr.
+ char* cur_token() { return cur_; }
+
+ // Returns the length of the current token (excluding the null terminator).
+ size_t cur_token_size() const { return cur_size_; }
+
+ private:
+ StringSplitter(const StringSplitter&) = delete;
+ StringSplitter& operator=(const StringSplitter&) = delete;
+ void Initialize(char* str, size_t size);
+
+ std::string str_;
+ char* cur_;
+ size_t cur_size_;
+ char* next_;
+ char* end_; // STL-style, points one past the last char.
+ const char delimiter_;
+ const EmptyTokenMode empty_token_mode_;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_splitter.h"
+
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+StringSplitter::StringSplitter(std::string str,
+ char delimiter,
+ EmptyTokenMode empty_token_mode)
+ : str_(std::move(str)),
+ delimiter_(delimiter),
+ empty_token_mode_(empty_token_mode) {
+ // It's legal to access str[str.size()] in C++11 (it always returns \0),
+ // hence the +1 (which becomes just size() after the -1 in Initialize()).
+ Initialize(&str_[0], str_.size() + 1);
+}
+
+StringSplitter::StringSplitter(char* str,
+ size_t size,
+ char delimiter,
+ EmptyTokenMode empty_token_mode)
+ : delimiter_(delimiter), empty_token_mode_(empty_token_mode) {
+ Initialize(str, size);
+}
+
+StringSplitter::StringSplitter(StringSplitter* outer,
+ char delimiter,
+ EmptyTokenMode empty_token_mode)
+ : delimiter_(delimiter), empty_token_mode_(empty_token_mode) {
+ Initialize(outer->cur_token(), outer->cur_token_size() + 1);
+}
+
+void StringSplitter::Initialize(char* str, size_t size) {
+ PERFETTO_DCHECK(!size || str);
+ next_ = str;
+ end_ = str + size;
+ cur_ = nullptr;
+ cur_size_ = 0;
+ if (size)
+ next_[size - 1] = '\0';
+}
+
+bool StringSplitter::Next() {
+ for (; next_ < end_; next_++) {
+ if (*next_ == delimiter_ &&
+ empty_token_mode_ == EmptyTokenMode::DISALLOW_EMPTY_TOKENS) {
+ // If empty tokens are disallowed, find fist non-delimiter character.
+ continue;
+ }
+ cur_ = next_;
+ for (;; next_++) {
+ if (*next_ == delimiter_) {
+ cur_size_ = static_cast<size_t>(next_ - cur_);
+ *(next_++) = '\0';
+ break;
+ }
+ if (*next_ == '\0') {
+ cur_size_ = static_cast<size_t>(next_ - cur_);
+ next_ = end_;
+ break;
+ }
+ }
+ if (*cur_ || empty_token_mode_ == EmptyTokenMode::ALLOW_EMPTY_TOKENS)
+ return true;
+ break;
+ }
+ cur_ = nullptr;
+ cur_size_ = 0;
+ return false;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/string_utils.cc
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+
+#include <locale.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <algorithm>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <xlocale.h>
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#endif
+
+#include <cinttypes>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+// Locale-independant as possible version of strtod.
+double StrToD(const char* nptr, char** endptr) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ static auto c_locale = newlocale(LC_ALL, "C", nullptr);
+ return strtod_l(nptr, endptr, c_locale);
+#else
+ return strtod(nptr, endptr);
+#endif
+}
+
+bool StartsWith(const std::string& str, const std::string& prefix) {
+ return str.compare(0, prefix.length(), prefix) == 0;
+}
+
+bool StartsWithAny(const std::string& str,
+ const std::vector<std::string>& prefixes) {
+ return std::any_of(
+ prefixes.begin(), prefixes.end(),
+ [&str](const std::string& prefix) { return StartsWith(str, prefix); });
+}
+
+bool EndsWith(const std::string& str, const std::string& suffix) {
+ if (suffix.size() > str.size())
+ return false;
+ return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+}
+
+bool Contains(const std::string& haystack, const std::string& needle) {
+ return haystack.find(needle) != std::string::npos;
+}
+
+bool Contains(const std::string& haystack, const char needle) {
+ return haystack.find(needle) != std::string::npos;
+}
+
+size_t Find(const StringView& needle, const StringView& haystack) {
+ if (needle.empty())
+ return 0;
+ if (needle.size() > haystack.size())
+ return std::string::npos;
+ for (size_t i = 0; i < haystack.size() - (needle.size() - 1); ++i) {
+ if (strncmp(haystack.data() + i, needle.data(), needle.size()) == 0)
+ return i;
+ }
+ return std::string::npos;
+}
+
+bool CaseInsensitiveEqual(const std::string& first, const std::string& second) {
+ return first.size() == second.size() &&
+ std::equal(
+ first.begin(), first.end(), second.begin(),
+ [](char a, char b) { return Lowercase(a) == Lowercase(b); });
+}
+
+std::string Join(const std::vector<std::string>& parts,
+ const std::string& delim) {
+ std::string acc;
+ for (size_t i = 0; i < parts.size(); ++i) {
+ acc += parts[i];
+ if (i + 1 != parts.size()) {
+ acc += delim;
+ }
+ }
+ return acc;
+}
+
+std::vector<std::string> SplitString(const std::string& text,
+ const std::string& delimiter) {
+ PERFETTO_CHECK(!delimiter.empty());
+
+ std::vector<std::string> output;
+ size_t start = 0;
+ size_t next;
+ for (;;) {
+ next = std::min(text.find(delimiter, start), text.size());
+ if (next > start)
+ output.emplace_back(&text[start], next - start);
+ start = next + delimiter.size();
+ if (start >= text.size())
+ break;
+ }
+ return output;
+}
+
+std::string TrimWhitespace(const std::string& str) {
+ std::string whitespaces = "\t\n ";
+
+ size_t front_idx = str.find_first_not_of(whitespaces);
+ std::string front_trimmed =
+ front_idx == std::string::npos ? "" : str.substr(front_idx);
+
+ size_t end_idx = front_trimmed.find_last_not_of(whitespaces);
+ return end_idx == std::string::npos ? ""
+ : front_trimmed.substr(0, end_idx + 1);
+}
+
+std::string StripPrefix(const std::string& str, const std::string& prefix) {
+ return StartsWith(str, prefix) ? str.substr(prefix.size()) : str;
+}
+
+std::string StripSuffix(const std::string& str, const std::string& suffix) {
+ return EndsWith(str, suffix) ? str.substr(0, str.size() - suffix.size())
+ : str;
+}
+
+std::string ToUpper(const std::string& str) {
+ // Don't use toupper(), it depends on the locale.
+ std::string res(str);
+ auto end = res.end();
+ for (auto c = res.begin(); c != end; ++c)
+ *c = Uppercase(*c);
+ return res;
+}
+
+std::string ToLower(const std::string& str) {
+ // Don't use tolower(), it depends on the locale.
+ std::string res(str);
+ auto end = res.end();
+ for (auto c = res.begin(); c != end; ++c)
+ *c = Lowercase(*c);
+ return res;
+}
+
+std::string ToHex(const char* data, size_t size) {
+ std::string hex(2 * size + 1, 'x');
+ for (size_t i = 0; i < size; ++i) {
+ // snprintf prints 3 characters, the two hex digits and a null byte. As we
+ // write left to right, we keep overwriting the nullbytes, except for the
+ // last call to snprintf.
+ snprintf(&(hex[2 * i]), 3, "%02hhx", data[i]);
+ }
+ // Remove the trailing nullbyte produced by the last snprintf.
+ hex.resize(2 * size);
+ return hex;
+}
+
+std::string IntToHexString(uint32_t number) {
+ size_t max_size = 11; // Max uint32 is 0xFFFFFFFF + 1 for null byte.
+ std::string buf;
+ buf.resize(max_size);
+ size_t final_len = SprintfTrunc(&buf[0], max_size, "0x%02x", number);
+ buf.resize(static_cast<size_t>(final_len)); // Cuts off the final null byte.
+ return buf;
+}
+
+std::string Uint64ToHexString(uint64_t number) {
+ return "0x" + Uint64ToHexStringNoPrefix(number);
+}
+
+std::string Uint64ToHexStringNoPrefix(uint64_t number) {
+ size_t max_size = 17; // Max uint64 is FFFFFFFFFFFFFFFF + 1 for null byte.
+ std::string buf;
+ buf.resize(max_size);
+ size_t final_len = SprintfTrunc(&buf[0], max_size, "%" PRIx64 "", number);
+ buf.resize(static_cast<size_t>(final_len)); // Cuts off the final null byte.
+ return buf;
+}
+
+std::string StripChars(const std::string& str,
+ const std::string& chars,
+ char replacement) {
+ std::string res(str);
+ const char* start = res.c_str();
+ const char* remove = chars.c_str();
+ for (const char* c = strpbrk(start, remove); c; c = strpbrk(c + 1, remove))
+ res[static_cast<uintptr_t>(c - start)] = replacement;
+ return res;
+}
+
+std::string ReplaceAll(std::string str,
+ const std::string& to_replace,
+ const std::string& replacement) {
+ PERFETTO_CHECK(!to_replace.empty());
+ size_t pos = 0;
+ while ((pos = str.find(to_replace, pos)) != std::string::npos) {
+ str.replace(pos, to_replace.length(), replacement);
+ pos += replacement.length();
+ }
+ return str;
+}
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+bool WideToUTF8(const std::wstring& source, std::string& output) {
+ if (source.empty() ||
+ source.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
+ return false;
+ }
+ int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0],
+ static_cast<int>(source.size()), nullptr, 0,
+ nullptr, nullptr);
+ output.assign(static_cast<size_t>(size), '\0');
+ if (::WideCharToMultiByte(CP_UTF8, 0, &source[0],
+ static_cast<int>(source.size()), &output[0], size,
+ nullptr, nullptr) != size) {
+ return false;
+ }
+ return true;
+}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+bool UTF8ToWide(const std::string& source, std::wstring& output) {
+ if (source.empty() ||
+ source.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
+ return false;
+ }
+ int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0],
+ static_cast<int>(source.size()), nullptr, 0);
+ output.assign(static_cast<size_t>(size), L'\0');
+ if (::MultiByteToWideChar(CP_UTF8, 0, &source[0],
+ static_cast<int>(source.size()), &output[0],
+ size) != size) {
+ return false;
+ }
+ return true;
+}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+size_t SprintfTrunc(char* dst, size_t dst_size, const char* fmt, ...) {
+ if (PERFETTO_UNLIKELY(dst_size) == 0)
+ return 0;
+
+ va_list args;
+ va_start(args, fmt);
+ int src_size = vsnprintf(dst, dst_size, fmt, args);
+ va_end(args);
+
+ if (PERFETTO_UNLIKELY(src_size) <= 0) {
+ dst[0] = '\0';
+ return 0;
+ }
+
+ size_t res;
+ if (PERFETTO_LIKELY(src_size < static_cast<int>(dst_size))) {
+ // Most common case.
+ res = static_cast<size_t>(src_size);
+ } else {
+ // Truncation case.
+ res = dst_size - 1;
+ }
+
+ PERFETTO_DCHECK(res < dst_size);
+ PERFETTO_DCHECK(dst[res] == '\0');
+ return res;
+}
+
+std::optional<LineWithOffset> FindLineWithOffset(base::StringView str,
+ uint32_t offset) {
+ static constexpr char kNewLine = '\n';
+ uint32_t line_offset = 0;
+ uint32_t line_count = 1;
+ for (uint32_t i = 0; i < str.size(); ++i) {
+ if (str.at(i) == kNewLine) {
+ line_offset = i + 1;
+ line_count++;
+ continue;
+ }
+ if (i == offset) {
+ size_t end_offset = str.find(kNewLine, i);
+ if (end_offset == std::string::npos) {
+ end_offset = str.size();
+ }
+ base::StringView line = str.substr(line_offset, end_offset - line_offset);
+ return LineWithOffset{line, offset - line_offset, line_count};
+ }
+ }
+ return std::nullopt;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/string_view.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+
+namespace perfetto {
+namespace base {
+
+// Without ignoring this warning we get the message:
+// error: out-of-line definition of constexpr static data member is redundant
+// in C++17 and is deprecated
+// when using clang-cl in Windows.
+#if defined(__GNUC__) // GCC & clang
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated"
+#endif // __GNUC__
+
+// static
+constexpr size_t StringView::npos;
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/temp_file.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/temp_file.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_TEMP_FILE_H_
+#define INCLUDE_PERFETTO_EXT_BASE_TEMP_FILE_H_
+
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+
+namespace perfetto {
+namespace base {
+
+std::string GetSysTempDir();
+
+class TempFile {
+ public:
+ static TempFile CreateUnlinked();
+ static TempFile Create();
+
+ TempFile(TempFile&&) noexcept;
+ TempFile& operator=(TempFile&&);
+ ~TempFile();
+
+ const std::string& path() const { return path_; }
+ int fd() const { return *fd_; }
+ int operator*() const { return *fd_; }
+
+ // Unlinks the file from the filesystem but keeps the fd() open.
+ // It is safe to call this multiple times.
+ void Unlink();
+
+ // Releases the underlying file descriptor. Will unlink the file from the
+ // filesystem if it was created via CreateUnlinked().
+ ScopedFile ReleaseFD();
+
+ private:
+ TempFile();
+ TempFile(const TempFile&) = delete;
+ TempFile& operator=(const TempFile&) = delete;
+
+ ScopedFile fd_;
+ std::string path_;
+};
+
+class TempDir {
+ public:
+ static TempDir Create();
+
+ TempDir(TempDir&&) noexcept;
+ TempDir& operator=(TempDir&&);
+ ~TempDir();
+
+ const std::string& path() const { return path_; }
+
+ private:
+ TempDir();
+ TempDir(const TempDir&) = delete;
+ TempDir& operator=(const TempDir&) = delete;
+
+ std::string path_;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_TEMP_FILE_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/temp_file.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#include <direct.h>
+#include <fileapi.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+namespace {
+std::string GetTempFilePathWin() {
+ std::string tmplt = GetSysTempDir() + "\\perfetto-XXXXXX";
+ StackString<255> name("%s\\perfetto-XXXXXX", GetSysTempDir().c_str());
+ PERFETTO_CHECK(_mktemp_s(name.mutable_data(), name.len() + 1) == 0);
+ return name.ToStdString();
+}
+} // namespace
+#endif
+
+std::string GetSysTempDir() {
+ const char* tmpdir = nullptr;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if ((tmpdir = getenv("TMP")))
+ return tmpdir;
+ if ((tmpdir = getenv("TEMP")))
+ return tmpdir;
+ return "C:\\TEMP";
+#else
+ if ((tmpdir = getenv("TMPDIR")))
+ return base::StripSuffix(tmpdir, "/");
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ return "/data/local/tmp";
+#else
+ return "/tmp";
+#endif // !OS_ANDROID
+#endif // !OS_WIN
+}
+
+// static
+TempFile TempFile::Create() {
+ TempFile temp_file;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ temp_file.path_ = GetTempFilePathWin();
+ // Several tests want to read-back the temp file while still open. On Windows,
+ // that requires FILE_SHARE_READ. FILE_SHARE_READ is NOT settable when using
+ // the POSIX-compat equivalent function _open(). Hence the CreateFileA +
+ // _open_osfhandle dance here.
+ HANDLE h =
+ ::CreateFileA(temp_file.path_.c_str(), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_TEMPORARY, nullptr);
+ PERFETTO_CHECK(PlatformHandleChecker::IsValid(h));
+ // According to MSDN, when using _open_osfhandle the caller must not call
+ // CloseHandle(). Ownership is moved to the file descriptor, which then needs
+ // to be closed with just with _close().
+ temp_file.fd_.reset(_open_osfhandle(reinterpret_cast<intptr_t>(h), 0));
+#else
+ temp_file.path_ = GetSysTempDir() + "/perfetto-XXXXXXXX";
+ temp_file.fd_.reset(mkstemp(&temp_file.path_[0]));
+#endif
+ if (PERFETTO_UNLIKELY(!temp_file.fd_)) {
+ PERFETTO_FATAL("Could not create temp file %s", temp_file.path_.c_str());
+ }
+ return temp_file;
+}
+
+// static
+TempFile TempFile::CreateUnlinked() {
+ TempFile temp_file = TempFile::Create();
+ temp_file.Unlink();
+ return temp_file;
+}
+
+TempFile::TempFile() = default;
+
+TempFile::~TempFile() {
+ Unlink();
+}
+
+ScopedFile TempFile::ReleaseFD() {
+ Unlink();
+ return std::move(fd_);
+}
+
+void TempFile::Unlink() {
+ if (path_.empty())
+ return;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // If the FD is still open DeleteFile will mark the file as pending deletion
+ // and delete it only when the process exists.
+ PERFETTO_CHECK(DeleteFileA(path_.c_str()));
+#else
+ PERFETTO_CHECK(unlink(path_.c_str()) == 0);
+#endif
+ path_.clear();
+}
+
+TempFile::TempFile(TempFile&&) noexcept = default;
+TempFile& TempFile::operator=(TempFile&&) = default;
+
+// static
+TempDir TempDir::Create() {
+ TempDir temp_dir;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ temp_dir.path_ = GetTempFilePathWin();
+ PERFETTO_CHECK(_mkdir(temp_dir.path_.c_str()) == 0);
+#else
+ temp_dir.path_ = GetSysTempDir() + "/perfetto-XXXXXXXX";
+ PERFETTO_CHECK(mkdtemp(&temp_dir.path_[0]));
+#endif
+ return temp_dir;
+}
+
+TempDir::TempDir() = default;
+TempDir::TempDir(TempDir&&) noexcept = default;
+TempDir& TempDir::operator=(TempDir&&) = default;
+
+TempDir::~TempDir() {
+ if (path_.empty())
+ return; // For objects that get std::move()d.
+ PERFETTO_CHECK(Rmdir(path_));
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/thread_checker.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+namespace {
+constexpr ThreadID kDetached{};
+
+ThreadID CurrentThreadId() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return ::GetCurrentThreadId();
+#else
+ return pthread_self();
+#endif
+}
+} // namespace
+
+ThreadChecker::ThreadChecker() {
+ thread_id_.store(CurrentThreadId());
+}
+
+ThreadChecker::~ThreadChecker() = default;
+
+ThreadChecker::ThreadChecker(const ThreadChecker& other) {
+ thread_id_ = other.thread_id_.load();
+}
+
+ThreadChecker& ThreadChecker::operator=(const ThreadChecker& other) {
+ thread_id_ = other.thread_id_.load();
+ return *this;
+}
+
+bool ThreadChecker::CalledOnValidThread() const {
+ auto self = CurrentThreadId();
+
+ // Will re-attach if previously detached using DetachFromThread().
+ auto prev_value = kDetached;
+ if (thread_id_.compare_exchange_strong(prev_value, self))
+ return true;
+ return prev_value == self;
+}
+
+void ThreadChecker::DetachFromThread() {
+ thread_id_.store(kDetached);
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/thread_utils.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/thread_utils.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
+
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <pthread.h>
+#include <string.h>
+#include <algorithm>
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/prctl.h>
+#endif
+
+// Internal implementation utils that aren't as widely useful/supported as
+// base/thread_utils.h.
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+// Sets the "comm" of the calling thread to the first 15 chars of the given
+// string.
+inline bool MaybeSetThreadName(const std::string& name) {
+ char buf[16] = {};
+ StringCopy(buf, name.c_str(), sizeof(buf));
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ return pthread_setname_np(buf) == 0;
+#else
+ return pthread_setname_np(pthread_self(), buf) == 0;
+#endif
+}
+
+inline bool GetThreadName(std::string& out_result) {
+ char buf[16] = {};
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ if (prctl(PR_GET_NAME, buf) != 0)
+ return false;
+#else
+ if (pthread_getname_np(pthread_self(), buf, sizeof(buf)) != 0)
+ return false;
+#endif
+ out_result = std::string(buf);
+ return true;
+}
+
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+PERFETTO_EXPORT_COMPONENT bool MaybeSetThreadName(const std::string& name);
+PERFETTO_EXPORT_COMPONENT bool GetThreadName(std::string& out_result);
+
+#else
+inline bool MaybeSetThreadName(const std::string&) {
+ return false;
+}
+inline bool GetThreadName(std::string&) {
+ return false;
+}
+#endif
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_utils.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+#include <zircon/process.h>
+#include <zircon/syscalls.h>
+#include <zircon/types.h>
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+static PlatformThreadId ResolveThreadId() {
+ zx_info_handle_basic_t basic;
+ return (zx_object_get_info(zx_thread_self(), ZX_INFO_HANDLE_BASIC, &basic,
+ sizeof(basic), nullptr, nullptr) == ZX_OK)
+ ? basic.koid
+ : ZX_KOID_INVALID;
+}
+PlatformThreadId GetThreadId() {
+ thread_local static PlatformThreadId thread_id = ResolveThreadId();
+ return thread_id;
+}
+
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
+ PCWSTR lpThreadDescription);
+
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+typedef HRESULT(WINAPI* GetThreadDescription)(HANDLE hThread,
+ PWSTR* ppszThreadDescription);
+
+bool MaybeSetThreadName(const std::string& name) {
+ // The SetThreadDescription API works even if no debugger is attached.
+ static auto set_thread_description_func =
+ reinterpret_cast<SetThreadDescription>(
+ reinterpret_cast<void*>(::GetProcAddress(
+ ::GetModuleHandleA("Kernel32.dll"), "SetThreadDescription")));
+ if (!set_thread_description_func) {
+ return false;
+ }
+ std::wstring wide_thread_name;
+ if (!UTF8ToWide(name, wide_thread_name)) {
+ return false;
+ }
+ HRESULT result = set_thread_description_func(::GetCurrentThread(),
+ wide_thread_name.c_str());
+ return !FAILED(result);
+}
+
+bool GetThreadName(std::string& out_result) {
+ static auto get_thread_description_func =
+ reinterpret_cast<GetThreadDescription>(
+ reinterpret_cast<void*>(::GetProcAddress(
+ ::GetModuleHandleA("Kernel32.dll"), "GetThreadDescription")));
+ if (!get_thread_description_func) {
+ return false;
+ }
+ wchar_t* wide_thread_name;
+ HRESULT result =
+ get_thread_description_func(::GetCurrentThread(), &wide_thread_name);
+ if (SUCCEEDED(result)) {
+ bool success = WideToUTF8(std::wstring(wide_thread_name), out_result);
+ LocalFree(wide_thread_name);
+ return success;
+ }
+ return false;
+}
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/time.cc
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#include <atomic>
+
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#else
+#include <unistd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if !PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_ARM64)
+namespace {
+
+// Returns the current value of the performance counter.
+int64_t QPCNowRaw() {
+ LARGE_INTEGER perf_counter_now = {};
+ // According to the MSDN documentation for QueryPerformanceCounter(), this
+ // will never fail on systems that run XP or later.
+ // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
+ ::QueryPerformanceCounter(&perf_counter_now);
+ return perf_counter_now.QuadPart;
+}
+
+double TSCTicksPerSecond() {
+ // The value returned by QueryPerformanceFrequency() cannot be used as the TSC
+ // frequency, because there is no guarantee that the TSC frequency is equal to
+ // the performance counter frequency.
+ // The TSC frequency is cached in a static variable because it takes some time
+ // to compute it.
+ static std::atomic<double> tsc_ticks_per_second = 0;
+ double value = tsc_ticks_per_second.load(std::memory_order_relaxed);
+ if (value != 0)
+ return value;
+
+ // Increase the thread priority to reduces the chances of having a context
+ // switch during a reading of the TSC and the performance counter.
+ const int previous_priority = ::GetThreadPriority(::GetCurrentThread());
+ ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+
+ // The first time that this function is called, make an initial reading of the
+ // TSC and the performance counter. Initialization of static variable is
+ // thread-safe. Threads can race initializing tsc_initial vs
+ // perf_counter_initial, although they should be storing very similar values.
+
+ static const uint64_t tsc_initial = __rdtsc();
+ static const int64_t perf_counter_initial = QPCNowRaw();
+
+ // Make a another reading of the TSC and the performance counter every time
+ // that this function is called.
+ const uint64_t tsc_now = __rdtsc();
+ const int64_t perf_counter_now = QPCNowRaw();
+
+ // Reset the thread priority.
+ ::SetThreadPriority(::GetCurrentThread(), previous_priority);
+
+ // Make sure that at least 50 ms elapsed between the 2 readings. The first
+ // time that this function is called, we don't expect this to be the case.
+ // Note: The longer the elapsed time between the 2 readings is, the more
+ // accurate the computed TSC frequency will be. The 50 ms value was
+ // chosen because local benchmarks show that it allows us to get a
+ // stddev of less than 1 tick/us between multiple runs.
+ // Note: According to the MSDN documentation for QueryPerformanceFrequency(),
+ // this will never fail on systems that run XP or later.
+ // https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
+ LARGE_INTEGER perf_counter_frequency = {};
+ ::QueryPerformanceFrequency(&perf_counter_frequency);
+ PERFETTO_CHECK(perf_counter_now >= perf_counter_initial);
+ const int64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
+ const double elapsed_time_seconds =
+ static_cast<double>(perf_counter_ticks) /
+ static_cast<double>(perf_counter_frequency.QuadPart);
+
+ constexpr double kMinimumEvaluationPeriodSeconds = 0.05;
+ if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
+ return 0;
+
+ // Compute the frequency of the TSC.
+ PERFETTO_CHECK(tsc_now >= tsc_initial);
+ const uint64_t tsc_ticks = tsc_now - tsc_initial;
+ // Racing with another thread to write |tsc_ticks_per_second| is benign
+ // because both threads will write a valid result.
+ tsc_ticks_per_second.store(
+ static_cast<double>(tsc_ticks) / elapsed_time_seconds,
+ std::memory_order_relaxed);
+
+ return tsc_ticks_per_second.load(std::memory_order_relaxed);
+}
+
+} // namespace
+#endif // !PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_ARM64)
+
+TimeNanos GetWallTimeNs() {
+ LARGE_INTEGER freq;
+ ::QueryPerformanceFrequency(&freq);
+ LARGE_INTEGER counter;
+ ::QueryPerformanceCounter(&counter);
+ double elapsed_nanoseconds = (1e9 * static_cast<double>(counter.QuadPart)) /
+ static_cast<double>(freq.QuadPart);
+ return TimeNanos(static_cast<uint64_t>(elapsed_nanoseconds));
+}
+
+TimeNanos GetThreadCPUTimeNs() {
+#if PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_ARM64)
+ // QueryThreadCycleTime versus TSCTicksPerSecond doesn't have much relation to
+ // actual elapsed time on Windows on Arm, because QueryThreadCycleTime is
+ // backed by the actual number of CPU cycles executed, rather than a
+ // constant-rate timer like Intel. To work around this, use GetThreadTimes
+ // (which isn't as accurate but is meaningful as a measure of elapsed
+ // per-thread time).
+ FILETIME dummy, kernel_ftime, user_ftime;
+ ::GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &kernel_ftime,
+ &user_ftime);
+ uint64_t kernel_time =
+ kernel_ftime.dwHighDateTime * 0x100000000 + kernel_ftime.dwLowDateTime;
+ uint64_t user_time =
+ user_ftime.dwHighDateTime * 0x100000000 + user_ftime.dwLowDateTime;
+
+ return TimeNanos((kernel_time + user_time) * 100);
+#else // !PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_ARM64)
+ // Get the number of TSC ticks used by the current thread.
+ ULONG64 thread_cycle_time = 0;
+ ::QueryThreadCycleTime(GetCurrentThread(), &thread_cycle_time);
+
+ // Get the frequency of the TSC.
+ const double tsc_ticks_per_second = TSCTicksPerSecond();
+ if (tsc_ticks_per_second == 0)
+ return TimeNanos();
+
+ // Return the CPU time of the current thread.
+ const double thread_time_seconds =
+ static_cast<double>(thread_cycle_time) / tsc_ticks_per_second;
+ constexpr int64_t kNanosecondsPerSecond = 1000 * 1000 * 1000;
+ return TimeNanos(
+ static_cast<int64_t>(thread_time_seconds * kNanosecondsPerSecond));
+#endif // !PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_ARM64)
+}
+
+void SleepMicroseconds(unsigned interval_us) {
+ // The Windows Sleep function takes a millisecond count. Round up so that
+ // short sleeps don't turn into a busy wait. Note that the sleep granularity
+ // on Windows can dynamically vary from 1 ms to ~16 ms, so don't count on this
+ // being a short sleep.
+ ::Sleep(static_cast<DWORD>((interval_us + 999) / 1000));
+}
+
+void InitializeTime() {
+#if !PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_ARM64)
+ // Make an early first call to TSCTicksPerSecond() to start 50 ms elapsed time
+ // (see comment in TSCTicksPerSecond()).
+ TSCTicksPerSecond();
+#endif // !PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_ARM64)
+}
+
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+void SleepMicroseconds(unsigned interval_us) {
+ ::usleep(static_cast<useconds_t>(interval_us));
+}
+
+void InitializeTime() {}
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+std::string GetTimeFmt(const std::string& fmt) {
+ time_t raw_time;
+ time(&raw_time);
+ struct tm* local_tm;
+ local_tm = localtime(&raw_time);
+ char buf[128];
+ PERFETTO_CHECK(strftime(buf, 80, fmt.c_str(), local_tm) > 0);
+ return buf;
+}
+
+std::optional<int32_t> GetTimezoneOffsetMins() {
+ std::string tz = GetTimeFmt("%z");
+ if (tz.size() != 5 || (tz[0] != '+' && tz[0] != '-'))
+ return std::nullopt;
+ char sign = '\0';
+ int32_t hh = 0;
+ int32_t mm = 0;
+ if (sscanf(tz.c_str(), "%c%2d%2d", &sign, &hh, &mm) != 3)
+ return std::nullopt;
+ return (hh * 60 + mm) * (sign == '-' ? -1 : 1);
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/utils.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/pipe.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+#include <limits.h>
+#include <stdlib.h> // For _exit()
+#include <unistd.h> // For getpagesize() and geteuid() & fork()
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <mach-o/dyld.h>
+#include <mach/vm_page_size.h>
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#include <io.h>
+#include <malloc.h> // For _aligned_malloc().
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <dlfcn.h>
+#include <malloc.h>
+
+#ifdef M_PURGE
+#define PERFETTO_M_PURGE M_PURGE
+#else
+// Only available in in-tree builds and on newer SDKs.
+#define PERFETTO_M_PURGE -101
+#endif // M_PURGE
+
+#ifdef M_PURGE_ALL
+#define PERFETTO_M_PURGE_ALL M_PURGE_ALL
+#else
+// Only available in in-tree builds and on newer SDKs.
+#define PERFETTO_M_PURGE_ALL -104
+#endif // M_PURGE
+
+namespace {
+extern "C" {
+using MalloptType = int (*)(int, int);
+}
+} // namespace
+#endif // OS_ANDROID
+
+namespace {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_X64_CPU_OPT)
+
+// Preserve the %rbx register via %rdi to work around a clang bug
+// https://bugs.llvm.org/show_bug.cgi?id=17907 (%rbx in an output constraint
+// is not considered a clobbered register).
+#define PERFETTO_GETCPUID(a, b, c, d, a_inp, c_inp) \
+ asm("mov %%rbx, %%rdi\n" \
+ "cpuid\n" \
+ "xchg %%rdi, %%rbx\n" \
+ : "=a"(a), "=D"(b), "=c"(c), "=d"(d) \
+ : "a"(a_inp), "2"(c_inp))
+
+uint32_t GetXCR0EAX() {
+ uint32_t eax = 0, edx = 0;
+ asm("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
+ return eax;
+}
+
+// If we are building with -msse4 check that the CPU actually supports it.
+// This file must be kept in sync with gn/standalone/BUILD.gn.
+void PERFETTO_EXPORT_COMPONENT __attribute__((constructor))
+CheckCpuOptimizations() {
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+ PERFETTO_GETCPUID(eax, ebx, ecx, edx, 1, 0);
+
+ static constexpr uint64_t xcr0_xmm_mask = 0x2;
+ static constexpr uint64_t xcr0_ymm_mask = 0x4;
+ static constexpr uint64_t xcr0_avx_mask = xcr0_xmm_mask | xcr0_ymm_mask;
+
+ const bool have_popcnt = ecx & (1u << 23);
+ const bool have_sse4_2 = ecx & (1u << 20);
+ const bool have_avx =
+ // Does the OS save/restore XMM and YMM state?
+ (ecx & (1u << 27)) && // OS support XGETBV.
+ (ecx & (1u << 28)) && // AVX supported in hardware
+ ((GetXCR0EAX() & xcr0_avx_mask) == xcr0_avx_mask);
+
+ // Get level 7 features (eax = 7 and ecx= 0), to check for AVX2 support.
+ // (See Intel 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 2A: Instruction Set Reference, A-M CPUID).
+ PERFETTO_GETCPUID(eax, ebx, ecx, edx, 7, 0);
+ const bool have_avx2 = have_avx && ((ebx >> 5) & 0x1);
+ const bool have_bmi = (ebx >> 3) & 0x1;
+ const bool have_bmi2 = (ebx >> 8) & 0x1;
+
+ if (!have_sse4_2 || !have_popcnt || !have_avx2 || !have_bmi || !have_bmi2) {
+ fprintf(
+ stderr,
+ "This executable requires a x86_64 cpu that supports SSE4.2, BMI2 and "
+ "AVX2.\n"
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ "On MacOS, this might be caused by running x86_64 binaries on arm64.\n"
+ "See https://github.com/google/perfetto/issues/294 for more.\n"
+#endif
+ "Rebuild with enable_perfetto_x64_cpu_opt=false.\n");
+ _exit(126);
+ }
+}
+#endif
+
+} // namespace
+
+namespace perfetto {
+namespace base {
+
+namespace internal {
+
+std::atomic<uint32_t> g_cached_page_size{0};
+
+uint32_t GetSysPageSizeSlowpath() {
+ uint32_t page_size = 0;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ const int page_size_int = getpagesize();
+ // If sysconf() fails for obscure reasons (e.g. SELinux denial) assume the
+ // page size is 4KB. This is to avoid regressing subtle SDK usages, as old
+ // versions of this code had a static constant baked in.
+ page_size = static_cast<uint32_t>(page_size_int > 0 ? page_size_int : 4096);
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ page_size = static_cast<uint32_t>(vm_page_size);
+#else
+ page_size = 4096;
+#endif
+
+ PERFETTO_CHECK(page_size > 0 && page_size % 4096 == 0);
+
+ // Races here are fine because any thread will write the same value.
+ g_cached_page_size.store(page_size, std::memory_order_relaxed);
+ return page_size;
+}
+
+} // namespace internal
+
+void MaybeReleaseAllocatorMemToOS() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // mallopt() on Android requires SDK level 26. Many targets and embedders
+ // still depend on a lower SDK level. Given mallopt() is a quite simple API,
+ // use reflection to do this rather than bumping the SDK level for all
+ // embedders. This keeps the behavior of standalone builds aligned with
+ // in-tree builds.
+ static MalloptType mallopt_fn =
+ reinterpret_cast<MalloptType>(dlsym(RTLD_DEFAULT, "mallopt"));
+ if (!mallopt_fn)
+ return;
+ if (mallopt_fn(PERFETTO_M_PURGE_ALL, 0) == 0) {
+ mallopt_fn(PERFETTO_M_PURGE, 0);
+ }
+#endif
+}
+
+uid_t GetCurrentUserId() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ return geteuid();
+#else
+ // TODO(primiano): On Windows we could hash the current user SID and derive a
+ // numeric user id [1]. It is not clear whether we need that. Right now that
+ // would not bring any benefit. Returning 0 unil we can prove we need it.
+ // [1]:https://android-review.googlesource.com/c/platform/external/perfetto/+/1513879/25/src/base/utils.cc
+ return 0;
+#endif
+}
+
+void SetEnv(const std::string& key, const std::string& value) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ PERFETTO_CHECK(::_putenv_s(key.c_str(), value.c_str()) == 0);
+#else
+ PERFETTO_CHECK(::setenv(key.c_str(), value.c_str(), /*overwrite=*/true) == 0);
+#endif
+}
+
+void UnsetEnv(const std::string& key) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ PERFETTO_CHECK(::_putenv_s(key.c_str(), "") == 0);
+#else
+ PERFETTO_CHECK(::unsetenv(key.c_str()) == 0);
+#endif
+}
+
+void Daemonize(std::function<int()> parent_cb) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ Pipe pipe = Pipe::Create(Pipe::kBothBlock);
+ pid_t pid;
+ switch (pid = fork()) {
+ case -1:
+ PERFETTO_FATAL("fork");
+ case 0: {
+ PERFETTO_CHECK(setsid() != -1);
+ base::ignore_result(chdir("/"));
+ base::ScopedFile null = base::OpenFile("/dev/null", O_RDONLY);
+ PERFETTO_CHECK(null);
+ PERFETTO_CHECK(dup2(*null, STDIN_FILENO) != -1);
+ PERFETTO_CHECK(dup2(*null, STDOUT_FILENO) != -1);
+ PERFETTO_CHECK(dup2(*null, STDERR_FILENO) != -1);
+ // Do not accidentally close stdin/stdout/stderr.
+ if (*null <= 2)
+ null.release();
+ WriteAll(*pipe.wr, "1", 1);
+ break;
+ }
+ default: {
+ // Wait for the child process to have reached the setsid() call. This is
+ // to avoid that 'adb shell perfetto -D' destroys the terminal (hence
+ // sending a SIGHUP to the child) before the child has detached from the
+ // terminal (see b/238644870).
+
+ // This is to unblock the read() below (with EOF, which will fail the
+ // CHECK) in the unlikely case of the child crashing before WriteAll("1").
+ pipe.wr.reset();
+ char one = '\0';
+ PERFETTO_CHECK(Read(*pipe.rd, &one, sizeof(one)) == 1 && one == '1');
+ printf("%d\n", pid);
+ int err = parent_cb();
+ exit(err);
+ }
+ }
+#else
+ // Avoid -Wunreachable warnings.
+ if (reinterpret_cast<intptr_t>(&Daemonize) != 16)
+ PERFETTO_FATAL("--background is only supported on Linux/Android/Mac");
+ ignore_result(parent_cb);
+#endif // OS_WIN
+}
+
+std::string GetCurExecutablePath() {
+ std::string self_path;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+ char buf[PATH_MAX];
+ ssize_t size = readlink("/proc/self/exe", buf, sizeof(buf));
+ PERFETTO_CHECK(size != -1);
+ // readlink does not null terminate.
+ self_path = std::string(buf, static_cast<size_t>(size));
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ uint32_t size = 0;
+ PERFETTO_CHECK(_NSGetExecutablePath(nullptr, &size));
+ self_path.resize(size);
+ PERFETTO_CHECK(_NSGetExecutablePath(&self_path[0], &size) == 0);
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ char buf[MAX_PATH];
+ auto len = ::GetModuleFileNameA(nullptr /*current*/, buf, sizeof(buf));
+ self_path = std::string(buf, len);
+#else
+ PERFETTO_FATAL(
+ "GetCurExecutableDir() not implemented on the current platform");
+#endif
+ return self_path;
+}
+
+std::string GetCurExecutableDir() {
+ auto path = GetCurExecutablePath();
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // Paths in Windows can have both kinds of slashes (mingw vs msvc).
+ path = path.substr(0, path.find_last_of('\\'));
+#endif
+ path = path.substr(0, path.find_last_of('/'));
+ return path;
+}
+
+void* AlignedAlloc(size_t alignment, size_t size) {
+ void* res = nullptr;
+ alignment = AlignUp<sizeof(void*)>(alignment); // At least pointer size.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // Window's _aligned_malloc() has a nearly identically signature to Unix's
+ // aligned_alloc() but its arguments are obviously swapped.
+ res = _aligned_malloc(size, alignment);
+#else
+ // aligned_alloc() has been introduced in Android only in API 28.
+ // Also NaCl and Fuchsia seems to have only posix_memalign().
+ ignore_result(posix_memalign(&res, alignment, size));
+#endif
+ PERFETTO_CHECK(res);
+ return res;
+}
+
+void AlignedFree(void* ptr) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ _aligned_free(ptr); // MSDN says it is fine to pass nullptr.
+#else
+ free(ptr);
+#endif
+}
+
+std::string HexDump(const void* data_void, size_t len, size_t bytes_per_line) {
+ const char* data = reinterpret_cast<const char*>(data_void);
+ std::string res;
+ static const size_t kPadding = bytes_per_line * 3 + 12;
+ std::unique_ptr<char[]> line(new char[bytes_per_line * 4 + 128]);
+ for (size_t i = 0; i < len; i += bytes_per_line) {
+ char* wptr = line.get();
+ wptr += base::SprintfTrunc(wptr, 19, "%08zX: ", i);
+ for (size_t j = i; j < i + bytes_per_line && j < len; j++) {
+ wptr += base::SprintfTrunc(wptr, 4, "%02X ",
+ static_cast<unsigned>(data[j]) & 0xFF);
+ }
+ for (size_t j = static_cast<size_t>(wptr - line.get()); j < kPadding; ++j)
+ *(wptr++) = ' ';
+ for (size_t j = i; j < i + bytes_per_line && j < len; j++) {
+ char c = data[j];
+ *(wptr++) = (c >= 32 && c < 127) ? c : '.';
+ }
+ *(wptr++) = '\n';
+ *(wptr++) = '\0';
+ res.append(line.get());
+ }
+ return res;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/uuid.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/uuid.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_UUID_H_
+#define INCLUDE_PERFETTO_EXT_BASE_UUID_H_
+
+#include <string.h>
+#include <array>
+#include <cstdint>
+#include <optional>
+#include <string>
+
+namespace perfetto {
+namespace base {
+
+class Uuid {
+ public:
+ explicit Uuid(const std::string& s);
+ explicit Uuid(int64_t lsb, int64_t msb);
+ Uuid();
+
+ std::array<uint8_t, 16>* data() { return &data_; }
+ const std::array<uint8_t, 16>* data() const { return &data_; }
+
+ bool operator==(const Uuid& other) const { return data_ == other.data_; }
+
+ bool operator!=(const Uuid& other) const { return !(*this == other); }
+
+ explicit operator bool() const { return *this != Uuid(); }
+
+ int64_t msb() const {
+ int64_t result;
+ memcpy(&result, data_.data() + 8, 8);
+ return result;
+ }
+
+ int64_t lsb() const {
+ int64_t result;
+ memcpy(&result, data_.data(), 8);
+ return result;
+ }
+
+ void set_lsb_msb(int64_t lsb, int64_t msb) {
+ set_lsb(lsb);
+ set_msb(msb);
+ }
+ void set_msb(int64_t msb) { memcpy(data_.data() + 8, &msb, 8); }
+ void set_lsb(int64_t lsb) { memcpy(data_.data(), &lsb, 8); }
+
+ std::string ToString() const;
+ std::string ToPrettyString() const;
+
+ private:
+ std::array<uint8_t, 16> data_{};
+};
+
+Uuid Uuidv4();
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_UUID_H_
+// gen_amalgamated begin header: include/perfetto/ext/base/no_destructor.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_NO_DESTRUCTOR_H_
+#define INCLUDE_PERFETTO_EXT_BASE_NO_DESTRUCTOR_H_
+
+#include <new>
+#include <utility>
+
+namespace perfetto {
+namespace base {
+
+// Wrapper that can hold an object of type T, without invoking the contained
+// object's destructor when being destroyed. Useful for creating statics while
+// avoiding static destructors.
+//
+// Stores the object inline, and therefore doesn't incur memory allocation and
+// pointer indirection overheads.
+//
+// Example of use:
+//
+// const std::string& GetStr() {
+// static base::NoDestructor<std::string> s("hello");
+// return s.ref();
+// }
+//
+template <typename T>
+class NoDestructor {
+ public:
+ // Forward arguments to T's constructor. Note that this doesn't cover
+ // construction from initializer lists.
+ template <typename... Args>
+ explicit NoDestructor(Args&&... args) {
+ new (storage_) T(std::forward<Args>(args)...);
+ }
+
+ NoDestructor(const NoDestructor&) = delete;
+ NoDestructor& operator=(const NoDestructor&) = delete;
+ NoDestructor(NoDestructor&&) = delete;
+ NoDestructor& operator=(NoDestructor&&) = delete;
+
+ ~NoDestructor() = default;
+
+ /* To avoid type-punned pointer strict aliasing warnings on GCC6 and below
+ * these need to be split over two lines. If they are collapsed onto one line.
+ * return reinterpret_cast<const T*>(storage_);
+ * The error fires.
+ */
+ const T& ref() const {
+ auto* const cast = reinterpret_cast<const T*>(storage_);
+ return *cast;
+ }
+ T& ref() {
+ auto* const cast = reinterpret_cast<T*>(storage_);
+ return *cast;
+ }
+
+ private:
+ alignas(T) char storage_[sizeof(T)];
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_NO_DESTRUCTOR_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/uuid.h"
+
+#include <mutex>
+#include <random>
+
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/no_destructor.h"
+
+namespace perfetto {
+namespace base {
+namespace {
+
+constexpr char kHexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+} // namespace
+
+// A globally unique 128-bit number.
+// In the early days of perfetto we were (sorta) respecting rfc4122. Later we
+// started replacing the LSB of the UUID with the statsd subscription ID in
+// other parts of the codebase (see perfetto_cmd.cc) for the convenience of
+// trace lookups, so rfc4122 made no sense as it just reduced entropy.
+Uuid Uuidv4() {
+ // Mix different sources of entropy to reduce the chances of collisions.
+ // Only using boot time is not enough. Under the assumption that most traces
+ // are started around the same time at boot, within a 1s window, the birthday
+ // paradox gives a chance of 90% collisions with 70k traces over a 1e9 space
+ // (Number of ns in a 1s window).
+ // &kHexmap >> 14 is used to feed use indirectly ASLR as a source of entropy.
+ // We deliberately don't use /dev/urandom as that might block for
+ // unpredictable time if the system is idle.
+ // The UUID does NOT need to be cryptographically secure, but random enough
+ // to avoid collisions across a large number of devices.
+ static std::minstd_rand rng(
+ static_cast<uint32_t>(static_cast<uint64_t>(GetBootTimeNs().count()) ^
+ static_cast<uint64_t>(GetWallTimeNs().count()) ^
+ (reinterpret_cast<uintptr_t>(&kHexmap) >> 14)));
+ Uuid uuid;
+ auto& data = *uuid.data();
+
+ // std::random is not thread safe and users of this class might mistakenly
+ // assume Uuidv4() is thread_safe because from the outside looks like a
+ // local object.
+ static base::NoDestructor<std::mutex> rand_mutex;
+ std::unique_lock<std::mutex> rand_lock(rand_mutex.ref());
+
+ for (size_t i = 0; i < sizeof(data);) {
+ // Note: the 32-th bit of rng() is always 0 as minstd_rand operates modulo
+ // 2**31. Fill in blocks of 16b rather than 32b to not lose 1b of entropy.
+ const auto rnd_data = static_cast<uint16_t>(rng());
+ memcpy(&data[i], &rnd_data, sizeof(rnd_data));
+ i += sizeof(rnd_data);
+ }
+
+ return uuid;
+}
+
+Uuid::Uuid() {}
+
+Uuid::Uuid(const std::string& s) {
+ PERFETTO_CHECK(s.size() == data_.size());
+ memcpy(data_.data(), s.data(), s.size());
+}
+
+Uuid::Uuid(int64_t lsb, int64_t msb) {
+ set_lsb_msb(lsb, msb);
+}
+
+std::string Uuid::ToString() const {
+ return std::string(reinterpret_cast<const char*>(data_.data()), data_.size());
+}
+
+std::string Uuid::ToPrettyString() const {
+ std::string s(data_.size() * 2 + 4, '-');
+ // Format is 123e4567-e89b-12d3-a456-426655443322.
+ size_t j = 0;
+ for (size_t i = 0; i < data_.size(); ++i) {
+ if (i == 4 || i == 6 || i == 8 || i == 10)
+ j++;
+ s[2 * i + j] = kHexmap[(data_[data_.size() - i - 1] & 0xf0) >> 4];
+ s[2 * i + 1 + j] = kHexmap[(data_[data_.size() - i - 1] & 0x0f)];
+ }
+ return s;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/virtual_destructors.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+
+// This translation unit contains the definitions for the destructor of pure
+// virtual interfaces for the current build target. The alternative would be
+// introducing a one-liner .cc file for each pure virtual interface, which is
+// overkill. This is for compliance with -Wweak-vtables.
+
+namespace perfetto {
+namespace base {
+
+TaskRunner::~TaskRunner() = default;
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/waitable_event.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/waitable_event.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_WAITABLE_EVENT_H_
+#define INCLUDE_PERFETTO_EXT_BASE_WAITABLE_EVENT_H_
+
+#include <condition_variable>
+#include <mutex>
+
+namespace perfetto {
+namespace base {
+
+// A waitable event for cross-thread synchronization.
+// All methods on this class can be called from any thread.
+class WaitableEvent {
+ public:
+ WaitableEvent();
+ ~WaitableEvent();
+ WaitableEvent(const WaitableEvent&) = delete;
+ WaitableEvent operator=(const WaitableEvent&) = delete;
+
+ // Synchronously block until the event is notified `notification` times.
+ void Wait(uint64_t notifications = 1);
+
+ // Signal the event, waking up blocked waiters.
+ void Notify();
+
+ private:
+ std::mutex mutex_;
+ std::condition_variable event_;
+ uint64_t notifications_ = 0;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_WAITABLE_EVENT_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/waitable_event.h"
+
+namespace perfetto {
+namespace base {
+
+WaitableEvent::WaitableEvent() = default;
+WaitableEvent::~WaitableEvent() = default;
+
+void WaitableEvent::Wait(uint64_t notifications) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ return event_.wait(lock, [&] { return notifications_ >= notifications; });
+}
+
+void WaitableEvent::Notify() {
+ std::unique_lock<std::mutex> lock(mutex_);
+ notifications_++;
+ event_.notify_all();
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/watchdog_posix.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/watchdog.h
+// gen_amalgamated begin header: include/perfetto/ext/base/watchdog_noop.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_NOOP_H_
+#define INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_NOOP_H_
+
+#include <stdint.h>
+
+namespace perfetto {
+namespace base {
+
+enum class WatchdogCrashReason; // Defined in watchdog.h.
+
+class Watchdog {
+ public:
+ class Timer {
+ public:
+ // Define an empty dtor to avoid "unused variable" errors on the call site.
+ Timer() {}
+ Timer(const Timer&) {}
+ ~Timer() {}
+ };
+ static Watchdog* GetInstance() {
+ static Watchdog* watchdog = new Watchdog();
+ return watchdog;
+ }
+ Timer CreateFatalTimer(uint32_t /*ms*/, WatchdogCrashReason) {
+ return Timer();
+ }
+ void Start() {}
+ void SetMemoryLimit(uint64_t /*bytes*/, uint32_t /*window_ms*/) {}
+ void SetCpuLimit(uint32_t /*percentage*/, uint32_t /*window_ms*/) {}
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_NOOP_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_H_
+#define INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_H_
+
+#include <functional>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+// The POSIX watchdog is only supported on Linux and Android in non-embedder
+// builds.
+#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
+// gen_amalgamated expanded: #include "perfetto/ext/base/watchdog_posix.h"
+#else
+// gen_amalgamated expanded: #include "perfetto/ext/base/watchdog_noop.h"
+#endif
+
+namespace perfetto {
+namespace base {
+
+// Used only to add more details to crash reporting.
+enum class WatchdogCrashReason {
+ kUnspecified = 0,
+ kCpuGuardrail = 1,
+ kMemGuardrail = 2,
+ kTaskRunnerHung = 3,
+ kTraceDidntStop = 4,
+};
+
+// Make the limits more relaxed on desktop, where multi-GB traces are likely.
+// Multi-GB traces can take bursts of cpu time to write into disk at the end of
+// the trace.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+constexpr uint32_t kWatchdogDefaultCpuLimit = 75;
+constexpr uint32_t kWatchdogDefaultCpuWindow = 5 * 60 * 1000; // 5 minutes.
+#else
+constexpr uint32_t kWatchdogDefaultCpuLimit = 90;
+constexpr uint32_t kWatchdogDefaultCpuWindow = 10 * 60 * 1000; // 10 minutes.
+#endif
+
+// The default memory margin we give to our processes. This is used as as a
+// constant to put on top of the trace buffers.
+constexpr uint64_t kWatchdogDefaultMemorySlack = 32 * 1024 * 1024; // 32 MiB.
+constexpr uint32_t kWatchdogDefaultMemoryWindow = 30 * 1000; // 30 seconds.
+
+inline void RunTaskWithWatchdogGuard(const std::function<void()>& task) {
+ // Maximum time a single task can take in a TaskRunner before the
+ // program suicides.
+ constexpr int64_t kWatchdogMillis = 30000; // 30s
+
+ Watchdog::Timer handle = base::Watchdog::GetInstance()->CreateFatalTimer(
+ kWatchdogMillis, WatchdogCrashReason::kTaskRunnerHung);
+ task();
+
+ // Suppress unused variable warnings in the client library amalgamated build.
+ (void)kWatchdogDefaultCpuLimit;
+ (void)kWatchdogDefaultCpuWindow;
+ (void)kWatchdogDefaultMemorySlack;
+ (void)kWatchdogDefaultMemoryWindow;
+}
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/platform.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/watchdog.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
+
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <sys/timerfd.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cinttypes>
+#include <fstream>
+#include <thread>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/crash_keys.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+namespace {
+
+constexpr uint32_t kDefaultPollingInterval = 30 * 1000;
+
+base::CrashKey g_crash_key_reason("wdog_reason");
+
+bool IsMultipleOf(uint32_t number, uint32_t divisor) {
+ return number >= divisor && number % divisor == 0;
+}
+
+double MeanForArray(const uint64_t array[], size_t size) {
+ uint64_t total = 0;
+ for (size_t i = 0; i < size; i++) {
+ total += array[i];
+ }
+ return static_cast<double>(total / size);
+}
+
+} // namespace
+
+bool ReadProcStat(int fd, ProcStat* out) {
+ char c[512];
+ size_t c_pos = 0;
+ while (c_pos < sizeof(c) - 1) {
+ ssize_t rd = PERFETTO_EINTR(read(fd, c + c_pos, sizeof(c) - c_pos));
+ if (rd < 0) {
+ PERFETTO_ELOG("Failed to read stat file to enforce resource limits.");
+ return false;
+ }
+ if (rd == 0)
+ break;
+ c_pos += static_cast<size_t>(rd);
+ }
+ PERFETTO_CHECK(c_pos < sizeof(c));
+ c[c_pos] = '\0';
+
+ if (sscanf(c,
+ "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu "
+ "%lu %*d %*d %*d %*d %*d %*d %*u %*u %ld",
+ &out->utime, &out->stime, &out->rss_pages) != 3) {
+ PERFETTO_ELOG("Invalid stat format: %s", c);
+ return false;
+ }
+ return true;
+}
+
+Watchdog::Watchdog(uint32_t polling_interval_ms)
+ : polling_interval_ms_(polling_interval_ms) {}
+
+Watchdog::~Watchdog() {
+ if (!thread_.joinable()) {
+ PERFETTO_DCHECK(!enabled_);
+ return;
+ }
+ PERFETTO_DCHECK(enabled_);
+ enabled_ = false;
+
+ // Rearm the timer to 1ns from now. This will cause the watchdog thread to
+ // wakeup from the poll() and see |enabled_| == false.
+ // This code path is used only in tests. In production code the watchdog is
+ // a singleton and is never destroyed.
+ struct itimerspec ts {};
+ ts.it_value.tv_sec = 0;
+ ts.it_value.tv_nsec = 1;
+ timerfd_settime(*timer_fd_, /*flags=*/0, &ts, nullptr);
+
+ thread_.join();
+}
+
+Watchdog* Watchdog::GetInstance() {
+ static Watchdog* watchdog = new Watchdog(kDefaultPollingInterval);
+ return watchdog;
+}
+
+// Can be called from any thread.
+Watchdog::Timer Watchdog::CreateFatalTimer(uint32_t ms,
+ WatchdogCrashReason crash_reason) {
+ if (!enabled_.load(std::memory_order_relaxed))
+ return Watchdog::Timer(this, 0, crash_reason);
+
+ return Watchdog::Timer(this, ms, crash_reason);
+}
+
+// Can be called from any thread.
+void Watchdog::AddFatalTimer(TimerData timer) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ timers_.emplace_back(std::move(timer));
+ RearmTimerFd_Locked();
+}
+
+// Can be called from any thread.
+void Watchdog::RemoveFatalTimer(TimerData timer) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ for (auto it = timers_.begin(); it != timers_.end(); it++) {
+ if (*it == timer) {
+ timers_.erase(it);
+ break; // Remove only one. Doesn't matter which one.
+ }
+ }
+ RearmTimerFd_Locked();
+}
+
+void Watchdog::RearmTimerFd_Locked() {
+ if (!enabled_)
+ return;
+ auto it = std::min_element(timers_.begin(), timers_.end());
+
+ // We use one timerfd to handle all the oustanding |timers_|. Keep it armed
+ // to the task expiring soonest.
+ struct itimerspec ts {};
+ if (it != timers_.end()) {
+ ts.it_value = ToPosixTimespec(it->deadline);
+ }
+ // If |timers_| is empty (it == end()) |ts.it_value| will remain
+ // zero-initialized and that will disarm the timer in the call below.
+ int res = timerfd_settime(*timer_fd_, TFD_TIMER_ABSTIME, &ts, nullptr);
+ PERFETTO_DCHECK(res == 0);
+}
+
+void Watchdog::Start() {
+ std::lock_guard<std::mutex> guard(mutex_);
+ if (thread_.joinable()) {
+ PERFETTO_DCHECK(enabled_);
+ } else {
+ PERFETTO_DCHECK(!enabled_);
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // Kick the thread to start running but only on Android or Linux.
+ timer_fd_.reset(
+ timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK));
+ if (!timer_fd_) {
+ PERFETTO_PLOG(
+ "timerfd_create failed, the Perfetto watchdog is not available");
+ return;
+ }
+ enabled_ = true;
+ RearmTimerFd_Locked(); // Deal with timers created before Start().
+ thread_ = std::thread(&Watchdog::ThreadMain, this);
+#endif
+ }
+}
+
+void Watchdog::SetMemoryLimit(uint64_t bytes, uint32_t window_ms) {
+ // Update the fields under the lock.
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ PERFETTO_CHECK(IsMultipleOf(window_ms, polling_interval_ms_) || bytes == 0);
+
+ size_t size = bytes == 0 ? 0 : window_ms / polling_interval_ms_ + 1;
+ memory_window_bytes_.Reset(size);
+ memory_limit_bytes_ = bytes;
+}
+
+void Watchdog::SetCpuLimit(uint32_t percentage, uint32_t window_ms) {
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ PERFETTO_CHECK(percentage <= 100);
+ PERFETTO_CHECK(IsMultipleOf(window_ms, polling_interval_ms_) ||
+ percentage == 0);
+
+ size_t size = percentage == 0 ? 0 : window_ms / polling_interval_ms_ + 1;
+ cpu_window_time_ticks_.Reset(size);
+ cpu_limit_percentage_ = percentage;
+}
+
+void Watchdog::ThreadMain() {
+ // Register crash keys explicitly to avoid running out of slots at crash time.
+ g_crash_key_reason.Register();
+
+ base::ScopedFile stat_fd(base::OpenFile("/proc/self/stat", O_RDONLY));
+ if (!stat_fd) {
+ PERFETTO_ELOG("Failed to open stat file to enforce resource limits.");
+ return;
+ }
+
+ PERFETTO_DCHECK(timer_fd_);
+
+ constexpr uint8_t kFdCount = 1;
+ struct pollfd fds[kFdCount]{};
+ fds[0].fd = *timer_fd_;
+ fds[0].events = POLLIN;
+
+ for (;;) {
+ // We use the poll() timeout to drive the periodic ticks for the cpu/memory
+ // checks. The only other case when the poll() unblocks is when we crash
+ // (or have to quit via enabled_ == false, but that happens only in tests).
+ platform::BeforeMaybeBlockingSyscall();
+ auto ret = poll(fds, kFdCount, static_cast<int>(polling_interval_ms_));
+ platform::AfterMaybeBlockingSyscall();
+ if (!enabled_)
+ return;
+ if (ret < 0) {
+ if (errno == ENOMEM || errno == EINTR) {
+ // Should happen extremely rarely.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ continue;
+ }
+ PERFETTO_FATAL("watchdog poll() failed");
+ }
+
+ // If we get here either:
+ // 1. poll() timed out, in which case we should process cpu/mem guardrails.
+ // 2. A timer expired, in which case we shall crash.
+
+ uint64_t expired = 0; // Must be exactly 8 bytes.
+ auto res = PERFETTO_EINTR(read(*timer_fd_, &expired, sizeof(expired)));
+ PERFETTO_DCHECK((res < 0 && (errno == EAGAIN)) ||
+ (res == sizeof(expired) && expired > 0));
+ const auto now = GetWallTimeMs();
+
+ // Check if any of the timers expired.
+ int tid_to_kill = 0;
+ WatchdogCrashReason crash_reason{};
+ std::unique_lock<std::mutex> guard(mutex_);
+ for (const auto& timer : timers_) {
+ if (now >= timer.deadline) {
+ tid_to_kill = timer.thread_id;
+ crash_reason = timer.crash_reason;
+ break;
+ }
+ }
+ guard.unlock();
+
+ if (tid_to_kill)
+ SerializeLogsAndKillThread(tid_to_kill, crash_reason);
+
+ // Check CPU and memory guardrails (if enabled).
+ lseek(stat_fd.get(), 0, SEEK_SET);
+ ProcStat stat;
+ if (!ReadProcStat(stat_fd.get(), &stat))
+ continue;
+ uint64_t cpu_time = stat.utime + stat.stime;
+ uint64_t rss_bytes =
+ static_cast<uint64_t>(stat.rss_pages) * base::GetSysPageSize();
+
+ bool threshold_exceeded = false;
+ guard.lock();
+ if (CheckMemory_Locked(rss_bytes)) {
+ threshold_exceeded = true;
+ crash_reason = WatchdogCrashReason::kMemGuardrail;
+ } else if (CheckCpu_Locked(cpu_time)) {
+ threshold_exceeded = true;
+ crash_reason = WatchdogCrashReason::kCpuGuardrail;
+ }
+ guard.unlock();
+
+ if (threshold_exceeded)
+ SerializeLogsAndKillThread(getpid(), crash_reason);
+ }
+}
+
+void Watchdog::SerializeLogsAndKillThread(int tid,
+ WatchdogCrashReason crash_reason) {
+ g_crash_key_reason.Set(static_cast<int>(crash_reason));
+
+ // We are about to die. Serialize the logs into the crash buffer so the
+ // debuggerd crash handler picks them up and attaches to the bugreport.
+ // In the case of a PERFETTO_CHECK/PERFETTO_FATAL this is done in logging.h.
+ // But in the watchdog case, we don't hit that codepath and must do ourselves.
+ MaybeSerializeLastLogsForCrashReporting();
+
+ // Send a SIGABRT to the thread that armed the timer. This is to see the
+ // callstack of the thread that is stuck in a long task rather than the
+ // watchdog thread.
+ if (syscall(__NR_tgkill, getpid(), tid, SIGABRT) < 0) {
+ // At this point the process must die. If for any reason the tgkill doesn't
+ // work (e.g. the thread has disappeared), force a crash from here.
+ abort();
+ }
+
+ if (disable_kill_failsafe_for_testing_)
+ return;
+
+ // The tgkill() above will take some milliseconds to cause a crash, as it
+ // involves the kernel to queue the SIGABRT on the target thread (often the
+ // main thread, which is != watchdog thread) and do a scheduling round.
+ // If something goes wrong though (the target thread has signals masked or
+ // is stuck in an uninterruptible+wakekill syscall) force quit from this
+ // thread.
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ abort();
+}
+
+bool Watchdog::CheckMemory_Locked(uint64_t rss_bytes) {
+ if (memory_limit_bytes_ == 0)
+ return false;
+
+ // Add the current stat value to the ring buffer and check that the mean
+ // remains under our threshold.
+ if (memory_window_bytes_.Push(rss_bytes)) {
+ if (memory_window_bytes_.Mean() >
+ static_cast<double>(memory_limit_bytes_)) {
+ PERFETTO_ELOG(
+ "Memory watchdog trigger. Memory window of %f bytes is above the "
+ "%" PRIu64 " bytes limit.",
+ memory_window_bytes_.Mean(), memory_limit_bytes_);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Watchdog::CheckCpu_Locked(uint64_t cpu_time) {
+ if (cpu_limit_percentage_ == 0)
+ return false;
+
+ // Add the cpu time to the ring buffer.
+ if (cpu_window_time_ticks_.Push(cpu_time)) {
+ // Compute the percentage over the whole window and check that it remains
+ // under the threshold.
+ uint64_t difference_ticks = cpu_window_time_ticks_.NewestWhenFull() -
+ cpu_window_time_ticks_.OldestWhenFull();
+ double window_interval_ticks =
+ (static_cast<double>(WindowTimeForRingBuffer(cpu_window_time_ticks_)) /
+ 1000.0) *
+ static_cast<double>(sysconf(_SC_CLK_TCK));
+ double percentage = static_cast<double>(difference_ticks) /
+ static_cast<double>(window_interval_ticks) * 100;
+ if (percentage > cpu_limit_percentage_) {
+ PERFETTO_ELOG("CPU watchdog trigger. %f%% CPU use is above the %" PRIu32
+ "%% CPU limit.",
+ percentage, cpu_limit_percentage_);
+ return true;
+ }
+ }
+ return false;
+}
+
+uint32_t Watchdog::WindowTimeForRingBuffer(const WindowedInterval& window) {
+ return static_cast<uint32_t>(window.size() - 1) * polling_interval_ms_;
+}
+
+bool Watchdog::WindowedInterval::Push(uint64_t sample) {
+ // Add the sample to the current position in the ring buffer.
+ buffer_[position_] = sample;
+
+ // Update the position with next one circularily.
+ position_ = (position_ + 1) % size_;
+
+ // Set the filled flag the first time we wrap.
+ filled_ = filled_ || position_ == 0;
+ return filled_;
+}
+
+double Watchdog::WindowedInterval::Mean() const {
+ return MeanForArray(buffer_.get(), size_);
+}
+
+void Watchdog::WindowedInterval::Clear() {
+ position_ = 0;
+ buffer_.reset(new uint64_t[size_]());
+}
+
+void Watchdog::WindowedInterval::Reset(size_t new_size) {
+ position_ = 0;
+ size_ = new_size;
+ buffer_.reset(new_size == 0 ? nullptr : new uint64_t[new_size]());
+}
+
+Watchdog::Timer::Timer(Watchdog* watchdog,
+ uint32_t ms,
+ WatchdogCrashReason crash_reason)
+ : watchdog_(watchdog) {
+ if (!ms)
+ return; // No-op timer created when the watchdog is disabled.
+ timer_data_.deadline = GetWallTimeMs() + std::chrono::milliseconds(ms);
+ timer_data_.thread_id = GetThreadId();
+ timer_data_.crash_reason = crash_reason;
+ PERFETTO_DCHECK(watchdog_);
+ watchdog_->AddFatalTimer(timer_data_);
+}
+
+Watchdog::Timer::~Timer() {
+ if (timer_data_.deadline.count())
+ watchdog_->RemoveFatalTimer(timer_data_);
+}
+
+Watchdog::Timer::Timer(Timer&& other) noexcept {
+ watchdog_ = std::move(other.watchdog_);
+ other.watchdog_ = nullptr;
+ timer_data_ = std::move(other.timer_data_);
+ other.timer_data_ = TimerData();
+}
+
+} // namespace base
+} // namespace perfetto
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
+// gen_amalgamated begin source: src/base/thread_task_runner.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/thread_task_runner.h
+// gen_amalgamated begin header: include/perfetto/ext/base/unix_task_runner.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_UNIX_TASK_RUNNER_H_
+#define INCLUDE_PERFETTO_EXT_BASE_UNIX_TASK_RUNNER_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/event_fd.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+
+#include <chrono>
+#include <deque>
+#include <map>
+#include <mutex>
+#include <vector>
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <poll.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+// Runs a task runner on the current thread.
+//
+// Implementation note: we currently assume (and enforce in debug builds) that
+// Run() is called from the thread that constructed the UnixTaskRunner. This is
+// not strictly necessary, and we could instead track the thread that invokes
+// Run(). However, a related property that *might* be important to enforce is
+// that the destructor runs on the task-running thread. Otherwise, if there are
+// still-pending tasks at the time of destruction, we would destroy those
+// outside of the task thread (which might be unexpected to the caller). On the
+// other hand, the std::function task interface discourages use of any
+// resource-owning tasks (as the callable needs to be copyable), so this might
+// not be important in practice.
+//
+// TODO(rsavitski): consider adding a thread-check in the destructor, after
+// auditing existing usages.
+// TODO(primiano): rename this to TaskRunnerImpl. The "Unix" part is misleading
+// now as it supports also Windows.
+class UnixTaskRunner : public TaskRunner {
+ public:
+ UnixTaskRunner();
+ ~UnixTaskRunner() override;
+
+ // Start executing tasks. Doesn't return until Quit() is called. Run() may be
+ // called multiple times on the same task runner.
+ void Run();
+ void Quit();
+
+ // Checks whether there are any pending immediate tasks to run. Note that
+ // delayed tasks don't count even if they are due to run.
+ bool IsIdleForTesting();
+
+ // TaskRunner implementation:
+ void PostTask(std::function<void()>) override;
+ void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
+ void AddFileDescriptorWatch(PlatformHandle, std::function<void()>) override;
+ void RemoveFileDescriptorWatch(PlatformHandle) override;
+ bool RunsTasksOnCurrentThread() const override;
+
+ // Returns true if the task runner is quitting, or has quit and hasn't been
+ // restarted since. Exposed primarily for ThreadTaskRunner, not necessary for
+ // normal use of this class.
+ bool QuitCalled();
+
+ private:
+ void WakeUp();
+ void UpdateWatchTasksLocked();
+ int GetDelayMsToNextTaskLocked() const;
+ void RunImmediateAndDelayedTask();
+ void PostFileDescriptorWatches(uint64_t windows_wait_result);
+ void RunFileDescriptorWatch(PlatformHandle);
+
+ ThreadChecker thread_checker_;
+ PlatformThreadId created_thread_id_ = GetThreadId();
+
+ EventFd event_;
+
+// The array of fds/handles passed to poll(2) / WaitForMultipleObjects().
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ std::vector<PlatformHandle> poll_fds_;
+#else
+ std::vector<struct pollfd> poll_fds_;
+#endif
+
+ // --- Begin lock-protected members ---
+
+ std::mutex lock_;
+
+ std::deque<std::function<void()>> immediate_tasks_;
+ std::multimap<TimeMillis, std::function<void()>> delayed_tasks_;
+ bool quit_ = false;
+
+ struct WatchTask {
+ std::function<void()> callback;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // On UNIX systems we make the FD number negative in |poll_fds_| to avoid
+ // polling it again until the queued task runs. On Windows we can't do that.
+ // Instead we keep track of its state here.
+ bool pending = false;
+#else
+ size_t poll_fd_index; // Index into |poll_fds_|.
+#endif
+ };
+
+ std::map<PlatformHandle, WatchTask> watch_tasks_;
+ bool watch_tasks_changed_ = false;
+
+ // --- End lock-protected members ---
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_UNIX_TASK_RUNNER_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
+#define INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
+
+#include <functional>
+#include <thread>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_task_runner.h"
+
+namespace perfetto {
+namespace base {
+
+// A UnixTaskRunner backed by a dedicated task thread. Shuts down the runner and
+// joins the thread upon destruction. Can be moved to transfer ownership.
+//
+// Guarantees that:
+// * the UnixTaskRunner will be constructed and destructed on the task thread.
+// * the task thread will live for the lifetime of the UnixTaskRunner.
+//
+class PERFETTO_EXPORT_COMPONENT ThreadTaskRunner : public TaskRunner {
+ public:
+ static ThreadTaskRunner CreateAndStart(const std::string& name = "") {
+ return ThreadTaskRunner(name);
+ }
+
+ ThreadTaskRunner(const ThreadTaskRunner&) = delete;
+ ThreadTaskRunner& operator=(const ThreadTaskRunner&) = delete;
+
+ ThreadTaskRunner(ThreadTaskRunner&&) noexcept;
+ ThreadTaskRunner& operator=(ThreadTaskRunner&&);
+ ~ThreadTaskRunner() override;
+
+ // Executes the given function on the task runner thread and blocks the caller
+ // thread until the function has run.
+ void PostTaskAndWaitForTesting(std::function<void()>);
+
+ // Can be called from another thread to get the CPU time of the thread the
+ // task-runner is executing on.
+ uint64_t GetThreadCPUTimeNsForTesting();
+
+ // Returns a pointer to the UnixTaskRunner, which is valid for the lifetime of
+ // this ThreadTaskRunner object (unless this object is moved-from, in which
+ // case the pointer remains valid for the lifetime of the new owning
+ // ThreadTaskRunner).
+ //
+ // Warning: do not call Quit() on the returned runner pointer, the termination
+ // should be handled exclusively by this class' destructor.
+ UnixTaskRunner* get() const { return task_runner_; }
+
+ // TaskRunner implementation.
+ // These methods just proxy to the underlying task_runner_.
+ void PostTask(std::function<void()>) override;
+ void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
+ void AddFileDescriptorWatch(PlatformHandle, std::function<void()>) override;
+ void RemoveFileDescriptorWatch(PlatformHandle) override;
+ bool RunsTasksOnCurrentThread() const override;
+
+ private:
+ explicit ThreadTaskRunner(const std::string& name);
+ void RunTaskThread(std::function<void(UnixTaskRunner*)> initializer);
+
+ std::thread thread_;
+ std::string name_;
+ UnixTaskRunner* task_runner_ = nullptr;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_task_runner.h"
+
+#include <condition_variable>
+#include <functional>
+#include <mutex>
+#include <thread>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_task_runner.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/prctl.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+ThreadTaskRunner::ThreadTaskRunner(ThreadTaskRunner&& other) noexcept
+ : thread_(std::move(other.thread_)), task_runner_(other.task_runner_) {
+ other.task_runner_ = nullptr;
+}
+
+ThreadTaskRunner& ThreadTaskRunner::operator=(ThreadTaskRunner&& other) {
+ this->~ThreadTaskRunner();
+ new (this) ThreadTaskRunner(std::move(other));
+ return *this;
+}
+
+ThreadTaskRunner::~ThreadTaskRunner() {
+ if (task_runner_) {
+ PERFETTO_CHECK(!task_runner_->QuitCalled());
+ task_runner_->Quit();
+
+ PERFETTO_DCHECK(thread_.joinable());
+ }
+ if (thread_.joinable())
+ thread_.join();
+}
+
+ThreadTaskRunner::ThreadTaskRunner(const std::string& name) : name_(name) {
+ std::mutex init_lock;
+ std::condition_variable init_cv;
+
+ std::function<void(UnixTaskRunner*)> initializer =
+ [this, &init_lock, &init_cv](UnixTaskRunner* task_runner) {
+ std::lock_guard<std::mutex> lock(init_lock);
+ task_runner_ = task_runner;
+ // Notify while still holding the lock, as init_cv ceases to exist as
+ // soon as the main thread observes a non-null task_runner_, and it can
+ // wake up spuriously (i.e. before the notify if we had unlocked before
+ // notifying).
+ init_cv.notify_one();
+ };
+
+ thread_ = std::thread(&ThreadTaskRunner::RunTaskThread, this,
+ std::move(initializer));
+
+ std::unique_lock<std::mutex> lock(init_lock);
+ init_cv.wait(lock, [this] { return !!task_runner_; });
+}
+
+void ThreadTaskRunner::RunTaskThread(
+ std::function<void(UnixTaskRunner*)> initializer) {
+ if (!name_.empty()) {
+ base::MaybeSetThreadName(name_);
+ }
+
+ UnixTaskRunner task_runner;
+ task_runner.PostTask(std::bind(std::move(initializer), &task_runner));
+ task_runner.Run();
+}
+
+void ThreadTaskRunner::PostTaskAndWaitForTesting(std::function<void()> fn) {
+ std::mutex mutex;
+ std::condition_variable cv;
+
+ std::unique_lock<std::mutex> lock(mutex);
+ bool done = false;
+ task_runner_->PostTask([&mutex, &cv, &done, &fn] {
+ fn();
+
+ std::lock_guard<std::mutex> inner_lock(mutex);
+ done = true;
+ cv.notify_one();
+ });
+ cv.wait(lock, [&done] { return done; });
+}
+
+uint64_t ThreadTaskRunner::GetThreadCPUTimeNsForTesting() {
+ uint64_t thread_time_ns = 0;
+ PostTaskAndWaitForTesting([&thread_time_ns] {
+ thread_time_ns = static_cast<uint64_t>(base::GetThreadCPUTimeNs().count());
+ });
+ return thread_time_ns;
+}
+
+void ThreadTaskRunner::PostTask(std::function<void()> task) {
+ task_runner_->PostTask(std::move(task));
+}
+
+void ThreadTaskRunner::PostDelayedTask(std::function<void()> task,
+ uint32_t delay_ms) {
+ task_runner_->PostDelayedTask(std::move(task), delay_ms);
+}
+
+void ThreadTaskRunner::AddFileDescriptorWatch(
+ PlatformHandle handle,
+ std::function<void()> watch_task) {
+ task_runner_->AddFileDescriptorWatch(handle, std::move(watch_task));
+}
+
+void ThreadTaskRunner::RemoveFileDescriptorWatch(PlatformHandle handle) {
+ task_runner_->RemoveFileDescriptorWatch(handle);
+}
+
+bool ThreadTaskRunner::RunsTasksOnCurrentThread() const {
+ return task_runner_->RunsTasksOnCurrentThread();
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/unix_task_runner.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/platform.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_task_runner.h"
+
+#include <errno.h>
+#include <stdlib.h>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#include <synchapi.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/watchdog.h"
+
+namespace perfetto {
+namespace base {
+
+UnixTaskRunner::UnixTaskRunner() {
+ AddFileDescriptorWatch(event_.fd(), [] {
+ // Not reached -- see PostFileDescriptorWatches().
+ PERFETTO_DFATAL("Should be unreachable.");
+ });
+}
+
+UnixTaskRunner::~UnixTaskRunner() = default;
+
+void UnixTaskRunner::WakeUp() {
+ event_.Notify();
+}
+
+void UnixTaskRunner::Run() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ created_thread_id_ = GetThreadId();
+ quit_ = false;
+ for (;;) {
+ int poll_timeout_ms;
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ if (quit_)
+ return;
+ poll_timeout_ms = GetDelayMsToNextTaskLocked();
+ UpdateWatchTasksLocked();
+ }
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ DWORD timeout =
+ poll_timeout_ms >= 0 ? static_cast<DWORD>(poll_timeout_ms) : INFINITE;
+ DWORD ret =
+ WaitForMultipleObjects(static_cast<DWORD>(poll_fds_.size()),
+ &poll_fds_[0], /*bWaitAll=*/false, timeout);
+ // Unlike poll(2), WaitForMultipleObjects() returns only *one* handle in the
+ // set, even when >1 is signalled. In order to avoid starvation,
+ // PostFileDescriptorWatches() will WaitForSingleObject() each other handle
+ // to ensure fairness. |ret| here is passed just to avoid an extra
+ // WaitForSingleObject() for the one handle that WaitForMultipleObject()
+ // returned.
+ PostFileDescriptorWatches(ret);
+#else
+ platform::BeforeMaybeBlockingSyscall();
+ int ret = PERFETTO_EINTR(poll(
+ &poll_fds_[0], static_cast<nfds_t>(poll_fds_.size()), poll_timeout_ms));
+ platform::AfterMaybeBlockingSyscall();
+ PERFETTO_CHECK(ret >= 0);
+ PostFileDescriptorWatches(0 /*ignored*/);
+#endif
+
+ // To avoid starvation we always interleave all types of tasks -- immediate,
+ // delayed and file descriptor watches.
+ RunImmediateAndDelayedTask();
+ }
+}
+
+void UnixTaskRunner::Quit() {
+ std::lock_guard<std::mutex> lock(lock_);
+ quit_ = true;
+ WakeUp();
+}
+
+bool UnixTaskRunner::QuitCalled() {
+ std::lock_guard<std::mutex> lock(lock_);
+ return quit_;
+}
+
+bool UnixTaskRunner::IsIdleForTesting() {
+ std::lock_guard<std::mutex> lock(lock_);
+ return immediate_tasks_.empty();
+}
+
+void UnixTaskRunner::UpdateWatchTasksLocked() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (!watch_tasks_changed_)
+ return;
+ watch_tasks_changed_ = false;
+#endif
+ poll_fds_.clear();
+ for (auto& it : watch_tasks_) {
+ PlatformHandle handle = it.first;
+ WatchTask& watch_task = it.second;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (!watch_task.pending)
+ poll_fds_.push_back(handle);
+#else
+ watch_task.poll_fd_index = poll_fds_.size();
+ poll_fds_.push_back({handle, POLLIN | POLLHUP, 0});
+#endif
+ }
+}
+
+void UnixTaskRunner::RunImmediateAndDelayedTask() {
+ // If locking overhead becomes an issue, add a separate work queue.
+ std::function<void()> immediate_task;
+ std::function<void()> delayed_task;
+ TimeMillis now = GetWallTimeMs();
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ if (!immediate_tasks_.empty()) {
+ immediate_task = std::move(immediate_tasks_.front());
+ immediate_tasks_.pop_front();
+ }
+ if (!delayed_tasks_.empty()) {
+ auto it = delayed_tasks_.begin();
+ if (now >= it->first) {
+ delayed_task = std::move(it->second);
+ delayed_tasks_.erase(it);
+ }
+ }
+ }
+
+ errno = 0;
+ if (immediate_task)
+ RunTaskWithWatchdogGuard(immediate_task);
+ errno = 0;
+ if (delayed_task)
+ RunTaskWithWatchdogGuard(delayed_task);
+}
+
+void UnixTaskRunner::PostFileDescriptorWatches(uint64_t windows_wait_result) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (size_t i = 0; i < poll_fds_.size(); i++) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ const PlatformHandle handle = poll_fds_[i];
+ // |windows_wait_result| is the result of WaitForMultipleObjects() call. If
+ // one of the objects was signalled, it will have a value between
+ // [0, poll_fds_.size()].
+ if (i != windows_wait_result &&
+ WaitForSingleObject(handle, 0) != WAIT_OBJECT_0) {
+ continue;
+ }
+#else
+ base::ignore_result(windows_wait_result);
+ const PlatformHandle handle = poll_fds_[i].fd;
+ if (!(poll_fds_[i].revents & (POLLIN | POLLHUP)))
+ continue;
+ poll_fds_[i].revents = 0;
+#endif
+
+ // The wake-up event is handled inline to avoid an infinite recursion of
+ // posted tasks.
+ if (handle == event_.fd()) {
+ event_.Clear();
+ continue;
+ }
+
+ // Binding to |this| is safe since we are the only object executing the
+ // task.
+ PostTask(std::bind(&UnixTaskRunner::RunFileDescriptorWatch, this, handle));
+
+ // Flag the task as pending.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // On Windows this is done by marking the WatchTask entry as pending. This
+ // is more expensive than Linux as requires rebuilding the |poll_fds_|
+ // vector on each call. There doesn't seem to be a good alternative though.
+ auto it = watch_tasks_.find(handle);
+ PERFETTO_CHECK(it != watch_tasks_.end());
+ PERFETTO_DCHECK(!it->second.pending);
+ it->second.pending = true;
+#else
+ // On UNIX systems instead, we just make the fd negative while its task is
+ // pending. This makes poll(2) ignore the fd.
+ PERFETTO_DCHECK(poll_fds_[i].fd >= 0);
+ poll_fds_[i].fd = -poll_fds_[i].fd;
+#endif
+ }
+}
+
+void UnixTaskRunner::RunFileDescriptorWatch(PlatformHandle fd) {
+ std::function<void()> task;
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ auto it = watch_tasks_.find(fd);
+ if (it == watch_tasks_.end())
+ return;
+ WatchTask& watch_task = it->second;
+
+ // Make poll(2) pay attention to the fd again. Since another thread may have
+ // updated this watch we need to refresh the set first.
+ UpdateWatchTasksLocked();
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // On Windows we manually track the presence of outstanding tasks for the
+ // watch. The UpdateWatchTasksLocked() in the Run() loop will re-add the
+ // task to the |poll_fds_| vector.
+ PERFETTO_DCHECK(watch_task.pending);
+ watch_task.pending = false;
+#else
+ size_t fd_index = watch_task.poll_fd_index;
+ PERFETTO_DCHECK(fd_index < poll_fds_.size());
+ PERFETTO_DCHECK(::abs(poll_fds_[fd_index].fd) == fd);
+ poll_fds_[fd_index].fd = fd;
+#endif
+ task = watch_task.callback;
+ }
+ errno = 0;
+ RunTaskWithWatchdogGuard(task);
+}
+
+int UnixTaskRunner::GetDelayMsToNextTaskLocked() const {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!immediate_tasks_.empty())
+ return 0;
+ if (!delayed_tasks_.empty()) {
+ TimeMillis diff = delayed_tasks_.begin()->first - GetWallTimeMs();
+ return std::max(0, static_cast<int>(diff.count()));
+ }
+ return -1;
+}
+
+void UnixTaskRunner::PostTask(std::function<void()> task) {
+ bool was_empty;
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ was_empty = immediate_tasks_.empty();
+ immediate_tasks_.push_back(std::move(task));
+ }
+ if (was_empty)
+ WakeUp();
+}
+
+void UnixTaskRunner::PostDelayedTask(std::function<void()> task,
+ uint32_t delay_ms) {
+ TimeMillis runtime = GetWallTimeMs() + TimeMillis(delay_ms);
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ delayed_tasks_.insert(std::make_pair(runtime, std::move(task)));
+ }
+ WakeUp();
+}
+
+void UnixTaskRunner::AddFileDescriptorWatch(PlatformHandle fd,
+ std::function<void()> task) {
+ PERFETTO_DCHECK(PlatformHandleChecker::IsValid(fd));
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ PERFETTO_DCHECK(!watch_tasks_.count(fd));
+ WatchTask& watch_task = watch_tasks_[fd];
+ watch_task.callback = std::move(task);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ watch_task.pending = false;
+#else
+ watch_task.poll_fd_index = SIZE_MAX;
+#endif
+ watch_tasks_changed_ = true;
+ }
+ WakeUp();
+}
+
+void UnixTaskRunner::RemoveFileDescriptorWatch(PlatformHandle fd) {
+ PERFETTO_DCHECK(PlatformHandleChecker::IsValid(fd));
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ PERFETTO_DCHECK(watch_tasks_.count(fd));
+ watch_tasks_.erase(fd);
+ watch_tasks_changed_ = true;
+ }
+ // No need to schedule a wake-up for this.
+}
+
+bool UnixTaskRunner::RunsTasksOnCurrentThread() const {
+ return GetThreadId() == created_thread_id_;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/subprocess.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/subprocess.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_SUBPROCESS_H_
+#define INCLUDE_PERFETTO_EXT_BASE_SUBPROCESS_H_
+
+#include <condition_variable>
+#include <functional>
+#include <initializer_list>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <thread>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+// gen_amalgamated expanded: #include "perfetto/base/proc_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/event_fd.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/pipe.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+
+namespace perfetto {
+namespace base {
+
+// Handles creation and lifecycle management of subprocesses, taking care of
+// all subtleties involved in handling processes on UNIX.
+// This class allows to deal with macro two use-cases:
+// 1) fork() + exec() equivalent: for spawning a brand new process image.
+// This happens when |args.exec_cmd| is not empty.
+// This is safe to use even in a multi-threaded environment.
+// 2) fork(): for spawning a process and running a function.
+// This happens when |args.posix_entrypoint_for_testing| is not empty.
+// This is intended only for tests as it is extremely subtle.
+// This mode must be used with extreme care. Before the entrypoint is
+// invoked all file descriptors other than stdin/out/err and the ones
+// specified in |args.preserve_fds| will be closed, to avoid each process
+// retaining a dupe of other subprocesses pipes. This however means that
+// any non trivial calls (including logging) must be avoided as they might
+// refer to FDs that are now closed. The entrypoint should really be used
+// just to signal a pipe or similar for synchronizing sequencing in tests.
+
+//
+// This class allows to control stdin/out/err pipe redirection and takes care
+// of keeping all the pipes pumped (stdin) / drained (stdout/err), in a similar
+// fashion of python's subprocess.Communicate()
+// stdin: is always piped and closed once the |args.input| buffer is written.
+// stdout/err can be either:
+// - dup()ed onto the parent process stdout/err.
+// - redirected onto /dev/null.
+// - piped onto a buffer (see output() method). There is only one output
+// buffer in total. If both stdout and stderr are set to kBuffer mode, they
+// will be merged onto the same. There doesn't seem any use case where they
+// are needed distinctly.
+//
+// Some caveats worth mentioning:
+// - It always waitpid()s, to avoid leaving zombies around. If the process is
+// not terminated by the time the destructor is reached, the dtor will
+// send a SIGKILL and wait for the termination.
+// - After fork()-ing it will close all file descriptors, preserving only
+// stdin/out/err and the fds listed in |args.preserve_fds|.
+// - On Linux/Android, the child process will be SIGKILL-ed if the calling
+// thread exists, even if the Subprocess is std::move()-d onto another thread.
+// This happens by virtue PR_SET_PDEATHSIG, which is used to avoid that
+// child processes are leaked in the case of a crash of the parent (frequent
+// in tests). However, the child process might still be leaked if execing
+// a setuid/setgid binary (see man 2 prctl).
+//
+// Usage:
+// base::Subprocess p({"/bin/cat", "-"});
+// (or equivalently:
+// base::Subprocess p;
+// p.args.exec_cmd.push_back("/bin/cat");
+// p.args.exec_cmd.push_back("-");
+// )
+// p.args.stdout_mode = base::Subprocess::kBuffer;
+// p.args.stderr_mode = base::Subprocess::kInherit;
+// p.args.input = "stdin contents";
+// p.Call();
+// (or equivalently:
+// p.Start();
+// p.Wait();
+// )
+// EXPECT_EQ(p.status(), base::Subprocess::kTerminated);
+// EXPECT_EQ(p.returncode(), 0);
+class Subprocess {
+ public:
+ enum Status {
+ kNotStarted = 0, // Before calling Start() or Call().
+ kRunning, // After calling Start(), before Wait().
+ kTerminated, // The subprocess terminated, either successfully or not.
+ // This includes crashes or other signals on UNIX.
+ };
+
+ enum class OutputMode {
+ kInherit = 0, // Inherit's the caller process stdout/stderr.
+ kDevNull, // dup() onto /dev/null.
+ kBuffer, // dup() onto a pipe and move it into the output() buffer.
+ kFd, // dup() onto the passed args.fd.
+ };
+
+ enum class InputMode {
+ kBuffer = 0, // dup() onto a pipe and write args.input on it.
+ kDevNull, // dup() onto /dev/null.
+ };
+
+ // Input arguments for configuring the subprocess behavior.
+ struct Args {
+ Args(std::initializer_list<std::string> _cmd = {}) : exec_cmd(_cmd) {}
+ Args(Args&&) noexcept;
+ Args& operator=(Args&&);
+ // If non-empty this will cause an exec() when Start()/Call() are called.
+ std::vector<std::string> exec_cmd;
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // If non-empty, it changes the argv[0] argument passed to exec. If
+ // unset, argv[0] == exec_cmd[0]. This is to handle cases like:
+ // exec_cmd = {"/proc/self/exec"}, argv0: "my_custom_test_override".
+ std::string posix_argv0_override_for_testing;
+
+ // If non-empty this will be invoked on the fork()-ed child process, after
+ // stdin/out/err has been redirected and all other file descriptor are
+ // closed. It is valid to specify both |exec_cmd| AND
+ // |posix_entrypoint_for_testing|. In this case the latter will be invoked
+ // just before the exec() call, but after having closed all fds % stdin/o/e.
+ // This is for synchronization barriers in tests.
+ std::function<void()> posix_entrypoint_for_testing;
+
+ // When set, will will move the process to the given process group. If set
+ // and zero, it will create a new process group. Effectively this calls
+ // setpgid(0 /*self_pid*/, posix_proc_group_id).
+ // This can be used to avoid that subprocesses receive CTRL-C from the
+ // terminal, while still living in the same session.
+ std::optional<pid_t> posix_proc_group_id{};
+#endif
+
+ // If non-empty, replaces the environment passed to exec().
+ std::vector<std::string> env;
+
+ // The file descriptors in this list will not be closed.
+ std::vector<int> preserve_fds;
+
+ // The data to push in the child process stdin, if input_mode ==
+ // InputMode::kBuffer.
+ std::string input;
+
+ InputMode stdin_mode = InputMode::kBuffer;
+ OutputMode stdout_mode = OutputMode::kInherit;
+ OutputMode stderr_mode = OutputMode::kInherit;
+
+ base::ScopedPlatformHandle out_fd;
+
+ // Returns " ".join(exec_cmd), quoting arguments.
+ std::string GetCmdString() const;
+ };
+
+ struct ResourceUsage {
+ uint32_t cpu_utime_ms = 0;
+ uint32_t cpu_stime_ms = 0;
+ uint32_t max_rss_kb = 0;
+ uint32_t min_page_faults = 0;
+ uint32_t maj_page_faults = 0;
+ uint32_t vol_ctx_switch = 0;
+ uint32_t invol_ctx_switch = 0;
+
+ uint32_t cpu_time_ms() const { return cpu_utime_ms + cpu_stime_ms; }
+ };
+
+ explicit Subprocess(std::initializer_list<std::string> exec_cmd = {});
+ Subprocess(Subprocess&&) noexcept;
+ Subprocess& operator=(Subprocess&&);
+ ~Subprocess(); // It will KillAndWaitForTermination() if still alive.
+
+ // Starts the subprocess but doesn't wait for its termination. The caller
+ // is expected to either call Wait() or Poll() after this call.
+ void Start();
+
+ // Wait for process termination. Can be called more than once.
+ // Args:
+ // |timeout_ms| = 0: wait indefinitely.
+ // |timeout_ms| > 0: wait for at most |timeout_ms|.
+ // Returns:
+ // True: The process terminated. See status() and returncode().
+ // False: Timeout reached, the process is still running. In this case the
+ // process will be left in the kRunning state.
+ bool Wait(int timeout_ms = 0);
+
+ // Equivalent of Start() + Wait();
+ // Returns true if the process exited cleanly with return code 0. False in
+ // any othe case.
+ bool Call(int timeout_ms = 0);
+
+ Status Poll();
+
+ // Sends a signal (SIGKILL if not specified) and wait for process termination.
+ void KillAndWaitForTermination(int sig_num = 0);
+
+ PlatformProcessId pid() const { return s_->pid; }
+
+ // The accessors below are updated only after a call to Poll(), Wait() or
+ // KillAndWaitForTermination().
+ // In most cases you want to call Poll() rather than these accessors.
+
+ Status status() const { return s_->status; }
+ int returncode() const { return s_->returncode; }
+ bool timed_out() const { return s_->timed_out; }
+
+ // This contains both stdout and stderr (if the corresponding _mode ==
+ // OutputMode::kBuffer). It's non-const so the caller can std::move() it.
+ std::string& output() { return s_->output; }
+ const std::string& output() const { return s_->output; }
+
+ const ResourceUsage& posix_rusage() const { return *s_->rusage; }
+
+ Args args;
+
+ private:
+ // The signal/exit code used when killing the process in case of a timeout.
+ static const int kTimeoutSignal;
+
+ Subprocess(const Subprocess&) = delete;
+ Subprocess& operator=(const Subprocess&) = delete;
+
+ // This is to deal robustly with the move operators, without having to
+ // manually maintain member-wise move instructions.
+ struct MovableState {
+ base::Pipe stdin_pipe;
+ base::Pipe stdouterr_pipe;
+ PlatformProcessId pid;
+ Status status = kNotStarted;
+ int returncode = -1;
+ std::string output; // Stdin+stderr. Only when OutputMode::kBuffer.
+ std::unique_ptr<ResourceUsage> rusage{new ResourceUsage()};
+ bool timed_out = false;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ std::thread stdouterr_thread;
+ std::thread stdin_thread;
+ ScopedPlatformHandle win_proc_handle;
+ ScopedPlatformHandle win_thread_handle;
+
+ base::EventFd stdouterr_done_event;
+ std::mutex mutex; // Protects locked_outerr_buf and the two pipes.
+ std::string locked_outerr_buf;
+#else
+ base::Pipe exit_status_pipe;
+ size_t input_written = 0;
+ std::thread waitpid_thread;
+#endif
+ };
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ static void StdinThread(MovableState*, std::string input);
+ static void StdoutErrThread(MovableState*);
+#else
+ void TryPushStdin();
+ void TryReadStdoutAndErr();
+ void TryReadExitStatus();
+ bool PollInternal(int poll_timeout_ms);
+#endif
+
+ std::unique_ptr<MovableState> s_;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_SUBPROCESS_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/subprocess.h"
+
+#include <tuple>
+
+// This file contains only the common bits (ctors / dtors / move operators).
+// The rest lives in subprocess_posix.cc and subprocess_windows.cc.
+
+namespace perfetto {
+namespace base {
+
+Subprocess::Args::Args(Args&&) noexcept = default;
+Subprocess::Args& Subprocess::Args::operator=(Args&&) = default;
+
+Subprocess::Subprocess(std::initializer_list<std::string> a)
+ : args(a), s_(new MovableState()) {}
+
+Subprocess::Subprocess(Subprocess&& other) noexcept {
+ static_assert(sizeof(Subprocess) ==
+ sizeof(std::tuple<std::unique_ptr<MovableState>, Args>),
+ "base::Subprocess' move ctor needs updating");
+ s_ = std::move(other.s_);
+ args = std::move(other.args);
+
+ // Reset the state of the moved-from object.
+ other.s_.reset(new MovableState());
+ other.~Subprocess();
+ new (&other) Subprocess();
+}
+
+Subprocess& Subprocess::operator=(Subprocess&& other) {
+ this->~Subprocess();
+ new (this) Subprocess(std::move(other));
+ return *this;
+}
+
+Subprocess::~Subprocess() {
+ if (s_->status == kRunning)
+ KillAndWaitForTermination();
+}
+
+bool Subprocess::Call(int timeout_ms) {
+ PERFETTO_CHECK(s_->status == kNotStarted);
+ Start();
+
+ if (!Wait(timeout_ms)) {
+ s_->timed_out = true;
+ KillAndWaitForTermination(kTimeoutSignal);
+ }
+ PERFETTO_DCHECK(s_->status != kRunning);
+ return s_->status == kTerminated && s_->returncode == 0;
+}
+
+std::string Subprocess::Args::GetCmdString() const {
+ std::string str;
+ for (size_t i = 0; i < exec_cmd.size(); i++) {
+ str += i > 0 ? " \"" : "";
+ str += exec_cmd[i];
+ str += i > 0 ? "\"" : "";
+ }
+ return str;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/subprocess_posix.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/subprocess.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <thread>
+#include <tuple>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/prctl.h>
+#endif
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+// In MacOS this is not defined in any header.
+extern "C" char** environ;
+
+namespace perfetto {
+namespace base {
+
+namespace {
+
+struct ChildProcessArgs {
+ Subprocess::Args* create_args;
+ const char* exec_cmd = nullptr;
+ std::vector<char*> argv;
+ std::vector<char*> env;
+ int stdin_pipe_rd = -1;
+ int stdouterr_pipe_wr = -1;
+};
+
+// Don't add any dynamic allocation in this function. This will be invoked
+// under a fork(), potentially in a state where the allocator lock is held.
+void __attribute__((noreturn)) ChildProcess(ChildProcessArgs* args) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // In no case we want a child process to outlive its parent process. This is
+ // relevant for tests, so that a test failure/crash doesn't leave child
+ // processes around that get reparented to init.
+ prctl(PR_SET_PDEATHSIG, SIGKILL);
+#endif
+
+ auto die = [args](const char* err) __attribute__((noreturn)) {
+ base::ignore_result(write(args->stdouterr_pipe_wr, err, strlen(err)));
+ base::ignore_result(write(args->stdouterr_pipe_wr, "\n", 1));
+ // From https://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
+ // "In particular, the value 128 is used to indicate failure to execute
+ // another program in a subprocess. This convention is not universally
+ // obeyed, but it is a good idea to follow it in your programs."
+ _exit(128);
+ };
+
+ if (args->create_args->posix_proc_group_id.has_value()) {
+ if (setpgid(0 /*self*/, args->create_args->posix_proc_group_id.value())) {
+ die("setpgid() failed");
+ }
+ }
+
+ auto set_fd_close_on_exec = [&die](int fd, bool close_on_exec) {
+ int flags = fcntl(fd, F_GETFD, 0);
+ if (flags < 0)
+ die("fcntl(F_GETFD) failed");
+ flags = close_on_exec ? (flags | FD_CLOEXEC) : (flags & ~FD_CLOEXEC);
+ if (fcntl(fd, F_SETFD, flags) < 0)
+ die("fcntl(F_SETFD) failed");
+ };
+
+ if (getppid() == 1)
+ die("terminating because parent process died");
+
+ switch (args->create_args->stdin_mode) {
+ case Subprocess::InputMode::kBuffer:
+ if (dup2(args->stdin_pipe_rd, STDIN_FILENO) == -1)
+ die("Failed to dup2(STDIN)");
+ close(args->stdin_pipe_rd);
+ break;
+ case Subprocess::InputMode::kDevNull:
+ if (dup2(open("/dev/null", O_RDONLY), STDIN_FILENO) == -1)
+ die("Failed to dup2(STDOUT)");
+ break;
+ }
+
+ switch (args->create_args->stdout_mode) {
+ case Subprocess::OutputMode::kInherit:
+ break;
+ case Subprocess::OutputMode::kDevNull: {
+ if (dup2(open("/dev/null", O_RDWR), STDOUT_FILENO) == -1)
+ die("Failed to dup2(STDOUT)");
+ break;
+ }
+ case Subprocess::OutputMode::kBuffer:
+ if (dup2(args->stdouterr_pipe_wr, STDOUT_FILENO) == -1)
+ die("Failed to dup2(STDOUT)");
+ break;
+ case Subprocess::OutputMode::kFd:
+ if (dup2(*args->create_args->out_fd, STDOUT_FILENO) == -1)
+ die("Failed to dup2(STDOUT)");
+ break;
+ }
+
+ switch (args->create_args->stderr_mode) {
+ case Subprocess::OutputMode::kInherit:
+ break;
+ case Subprocess::OutputMode::kDevNull: {
+ if (dup2(open("/dev/null", O_RDWR), STDERR_FILENO) == -1)
+ die("Failed to dup2(STDERR)");
+ break;
+ }
+ case Subprocess::OutputMode::kBuffer:
+ if (dup2(args->stdouterr_pipe_wr, STDERR_FILENO) == -1)
+ die("Failed to dup2(STDERR)");
+ break;
+ case Subprocess::OutputMode::kFd:
+ if (dup2(*args->create_args->out_fd, STDERR_FILENO) == -1)
+ die("Failed to dup2(STDERR)");
+ break;
+ }
+
+ // Close all FDs % stdin/out/err and the ones that the client explicitly
+ // asked to retain. The reason for this is twofold:
+ // 1. For exec-only (i.e. entrypoint == empty) cases: it avoids leaking FDs
+ // that didn't get marked as O_CLOEXEC by accident.
+ // 2. In fork() mode (entrypoint not empty) avoids retaining a dup of eventfds
+ // that would prevent the parent process to receive EOFs (tests usually use
+ // pipes as a synchronization mechanism between subprocesses).
+ const auto& preserve_fds = args->create_args->preserve_fds;
+ for (int i = 0; i < 512; i++) {
+ if (i != STDIN_FILENO && i != STDERR_FILENO && i != STDOUT_FILENO &&
+ i != args->stdouterr_pipe_wr &&
+ !std::count(preserve_fds.begin(), preserve_fds.end(), i)) {
+ close(i);
+ }
+ }
+
+ // Clears O_CLOEXEC from stdin/out/err and the |preserve_fds| list. These are
+ // the only FDs that we want to be preserved after the exec().
+ set_fd_close_on_exec(STDIN_FILENO, false);
+ set_fd_close_on_exec(STDOUT_FILENO, false);
+ set_fd_close_on_exec(STDERR_FILENO, false);
+
+ for (auto fd : preserve_fds)
+ set_fd_close_on_exec(fd, false);
+
+ // If the caller specified a std::function entrypoint, run that first.
+ if (args->create_args->posix_entrypoint_for_testing)
+ args->create_args->posix_entrypoint_for_testing();
+
+ // If the caller specified only an entrypoint, without any args, exit now.
+ // Otherwise proceed with the exec() below.
+ if (!args->exec_cmd)
+ _exit(0);
+
+ // If |args[0]| is a path use execv() (which takes a path), othewise use
+ // exevp(), which uses the shell and follows PATH.
+ if (strchr(args->exec_cmd, '/')) {
+ char** env = args->env.empty() ? environ : args->env.data();
+ execve(args->exec_cmd, args->argv.data(), env);
+ } else {
+ // There is no execvpe() on Mac.
+ if (!args->env.empty())
+ die("A full path is required for |exec_cmd| when setting |env|");
+ execvp(args->exec_cmd, args->argv.data());
+ }
+
+ // Reached only if execv fails.
+ die("execve() failed");
+}
+
+} // namespace
+
+// static
+const int Subprocess::kTimeoutSignal = SIGKILL;
+
+void Subprocess::Start() {
+ ChildProcessArgs proc_args;
+ proc_args.create_args = &args;
+
+ // Setup argv.
+ if (!args.exec_cmd.empty()) {
+ proc_args.exec_cmd = args.exec_cmd[0].c_str();
+ for (const std::string& arg : args.exec_cmd)
+ proc_args.argv.push_back(const_cast<char*>(arg.c_str()));
+ proc_args.argv.push_back(nullptr);
+
+ if (!args.posix_argv0_override_for_testing.empty()) {
+ proc_args.argv[0] =
+ const_cast<char*>(args.posix_argv0_override_for_testing.c_str());
+ }
+ }
+
+ // Setup env.
+ if (!args.env.empty()) {
+ for (const std::string& str : args.env)
+ proc_args.env.push_back(const_cast<char*>(str.c_str()));
+ proc_args.env.push_back(nullptr);
+ }
+
+ // Setup the pipes for stdin/err redirection.
+ if (args.stdin_mode == InputMode::kBuffer) {
+ s_->stdin_pipe = base::Pipe::Create(base::Pipe::kWrNonBlock);
+ proc_args.stdin_pipe_rd = *s_->stdin_pipe.rd;
+ }
+ s_->stdouterr_pipe = base::Pipe::Create(base::Pipe::kRdNonBlock);
+ proc_args.stdouterr_pipe_wr = *s_->stdouterr_pipe.wr;
+
+ // Spawn the child process that will exec().
+ s_->pid = fork();
+ PERFETTO_CHECK(s_->pid >= 0);
+ if (s_->pid == 0) {
+ // Close the parent-ends of the pipes.
+ s_->stdin_pipe.wr.reset();
+ s_->stdouterr_pipe.rd.reset();
+ ChildProcess(&proc_args);
+ // ChildProcess() doesn't return, not even in case of failures.
+ PERFETTO_FATAL("not reached");
+ }
+
+ s_->status = kRunning;
+
+ // Close the child-end of the pipes.
+ // Deliberately NOT closing the s_->stdin_pipe.rd. This is to avoid crashing
+ // with a SIGPIPE if the process exits without consuming its stdin, while
+ // the parent tries to write() on the other end of the stdin pipe.
+ s_->stdouterr_pipe.wr.reset();
+ proc_args.create_args->out_fd.reset();
+
+ // Spawn a thread that is blocked on waitpid() and writes the termination
+ // status onto a pipe. The problem here is that waipid() doesn't have a
+ // timeout option and can't be passed to poll(). The alternative would be
+ // using a SIGCHLD handler, but anecdotally signal handlers introduce more
+ // problems than what they solve.
+ s_->exit_status_pipe = base::Pipe::Create(base::Pipe::kRdNonBlock);
+
+ // Both ends of the pipe are closed after the thread.join().
+ int pid = s_->pid;
+ int exit_status_pipe_wr = s_->exit_status_pipe.wr.release();
+ auto* rusage = s_->rusage.get();
+ s_->waitpid_thread = std::thread([pid, exit_status_pipe_wr, rusage] {
+ int pid_stat = -1;
+ struct rusage usg {};
+ int wait_res = PERFETTO_EINTR(wait4(pid, &pid_stat, 0, &usg));
+ PERFETTO_CHECK(wait_res == pid);
+
+ auto tv_to_ms = [](const struct timeval& tv) {
+ return static_cast<uint32_t>(tv.tv_sec * 1000 + tv.tv_usec / 1000);
+ };
+ rusage->cpu_utime_ms = tv_to_ms(usg.ru_utime);
+ rusage->cpu_stime_ms = tv_to_ms(usg.ru_stime);
+ rusage->max_rss_kb = static_cast<uint32_t>(usg.ru_maxrss) / 1000;
+ rusage->min_page_faults = static_cast<uint32_t>(usg.ru_minflt);
+ rusage->maj_page_faults = static_cast<uint32_t>(usg.ru_majflt);
+ rusage->vol_ctx_switch = static_cast<uint32_t>(usg.ru_nvcsw);
+ rusage->invol_ctx_switch = static_cast<uint32_t>(usg.ru_nivcsw);
+
+ base::ignore_result(PERFETTO_EINTR(
+ write(exit_status_pipe_wr, &pid_stat, sizeof(pid_stat))));
+ PERFETTO_CHECK(close(exit_status_pipe_wr) == 0 || errno == EINTR);
+ });
+}
+
+Subprocess::Status Subprocess::Poll() {
+ if (s_->status != kRunning)
+ return s_->status; // Nothing to poll.
+ while (PollInternal(0 /* don't block*/)) {
+ }
+ return s_->status;
+}
+
+// |timeout_ms| semantic:
+// -1: Block indefinitely.
+// 0: Don't block, return immediately.
+// >0: Block for at most X ms.
+// Returns:
+// True: Read at least one fd (so there might be more queued).
+// False: if all fds reached quiescent (no data to read/write).
+bool Subprocess::PollInternal(int poll_timeout_ms) {
+ struct pollfd fds[3]{};
+ size_t num_fds = 0;
+ if (s_->exit_status_pipe.rd) {
+ fds[num_fds].fd = *s_->exit_status_pipe.rd;
+ fds[num_fds].events = POLLIN;
+ num_fds++;
+ }
+ if (s_->stdouterr_pipe.rd) {
+ fds[num_fds].fd = *s_->stdouterr_pipe.rd;
+ fds[num_fds].events = POLLIN;
+ num_fds++;
+ }
+ if (s_->stdin_pipe.wr) {
+ fds[num_fds].fd = *s_->stdin_pipe.wr;
+ fds[num_fds].events = POLLOUT;
+ num_fds++;
+ }
+
+ if (num_fds == 0)
+ return false;
+
+ auto nfds = static_cast<nfds_t>(num_fds);
+ int poll_res = PERFETTO_EINTR(poll(fds, nfds, poll_timeout_ms));
+ PERFETTO_CHECK(poll_res >= 0);
+
+ TryReadStdoutAndErr();
+ TryPushStdin();
+ TryReadExitStatus();
+
+ return poll_res > 0;
+}
+
+bool Subprocess::Wait(int timeout_ms) {
+ PERFETTO_CHECK(s_->status != kNotStarted);
+
+ // Break out of the loop only after both conditions are satisfied:
+ // - All stdout/stderr data has been read (if kBuffer).
+ // - The process exited.
+ // Note that the two events can happen arbitrary order. After the process
+ // exits, there might be still data in the pipe buffer, which we want to
+ // read fully.
+ //
+ // Instead, don't wait on the stdin to be fully written. The child process
+ // might exit prematurely (or crash). If that happens, we can end up in a
+ // state where the write(stdin_pipe_.wr) will never unblock.
+
+ const int64_t t_start = base::GetWallTimeMs().count();
+ while (s_->exit_status_pipe.rd || s_->stdouterr_pipe.rd) {
+ int poll_timeout_ms = -1; // Block until a FD is ready.
+ if (timeout_ms > 0) {
+ const int64_t now = GetWallTimeMs().count();
+ poll_timeout_ms = timeout_ms - static_cast<int>(now - t_start);
+ if (poll_timeout_ms <= 0)
+ return false;
+ }
+ PollInternal(poll_timeout_ms);
+ } // while(...)
+ return true;
+}
+
+void Subprocess::TryReadExitStatus() {
+ if (!s_->exit_status_pipe.rd)
+ return;
+
+ int pid_stat = -1;
+ int64_t rsize = PERFETTO_EINTR(
+ read(*s_->exit_status_pipe.rd, &pid_stat, sizeof(pid_stat)));
+ if (rsize < 0 && errno == EAGAIN)
+ return;
+
+ if (rsize > 0) {
+ PERFETTO_CHECK(rsize == sizeof(pid_stat));
+ } else if (rsize < 0) {
+ PERFETTO_PLOG("Subprocess read(s_->exit_status_pipe) failed");
+ }
+ s_->waitpid_thread.join();
+ s_->exit_status_pipe.rd.reset();
+
+ s_->status = kTerminated;
+ if (WIFEXITED(pid_stat)) {
+ s_->returncode = WEXITSTATUS(pid_stat);
+ } else if (WIFSIGNALED(pid_stat)) {
+ s_->returncode = 128 + WTERMSIG(pid_stat); // Follow bash convention.
+ } else {
+ PERFETTO_FATAL("waitpid() returned an unexpected value (0x%x)", pid_stat);
+ }
+}
+
+// If the stidn pipe is still open, push input data and close it at the end.
+void Subprocess::TryPushStdin() {
+ if (!s_->stdin_pipe.wr)
+ return;
+
+ PERFETTO_DCHECK(args.input.empty() || s_->input_written < args.input.size());
+ if (!args.input.empty()) {
+ int64_t wsize =
+ PERFETTO_EINTR(write(*s_->stdin_pipe.wr, &args.input[s_->input_written],
+ args.input.size() - s_->input_written));
+ if (wsize < 0 && errno == EAGAIN)
+ return;
+
+ if (wsize >= 0) {
+ // Whether write() can return 0 is one of the greatest mysteries of UNIX.
+ // Just ignore it.
+ s_->input_written += static_cast<size_t>(wsize);
+ } else {
+ PERFETTO_PLOG("Subprocess write(stdin) failed");
+ s_->stdin_pipe.wr.reset();
+ }
+ }
+ PERFETTO_DCHECK(s_->input_written <= args.input.size());
+ if (s_->input_written == args.input.size())
+ s_->stdin_pipe.wr.reset(); // Close stdin.
+}
+
+void Subprocess::TryReadStdoutAndErr() {
+ if (!s_->stdouterr_pipe.rd)
+ return;
+ char buf[4096];
+ int64_t rsize =
+ PERFETTO_EINTR(read(*s_->stdouterr_pipe.rd, buf, sizeof(buf)));
+ if (rsize < 0 && errno == EAGAIN)
+ return;
+
+ if (rsize > 0) {
+ s_->output.append(buf, static_cast<size_t>(rsize));
+ } else if (rsize == 0 /* EOF */) {
+ s_->stdouterr_pipe.rd.reset();
+ } else {
+ PERFETTO_PLOG("Subprocess read(stdout/err) failed");
+ s_->stdouterr_pipe.rd.reset();
+ }
+}
+
+void Subprocess::KillAndWaitForTermination(int sig_num) {
+ kill(s_->pid, sig_num ? sig_num : SIGKILL);
+ Wait();
+ // TryReadExitStatus must have joined the thread.
+ PERFETTO_DCHECK(!s_->waitpid_thread.joinable());
+}
+
+} // namespace base
+} // namespace perfetto
+
+#endif // PERFETTO_OS_LINUX || PERFETTO_OS_ANDROID || PERFETTO_OS_APPLE
+// gen_amalgamated begin source: src/base/subprocess_windows.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/subprocess.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+#include <stdio.h>
+
+#include <algorithm>
+#include <mutex>
+#include <tuple>
+
+#include <Windows.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/pipe.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+// static
+const int Subprocess::kTimeoutSignal = static_cast<int>(STATUS_TIMEOUT);
+
+void Subprocess::Start() {
+ if (args.exec_cmd.empty()) {
+ PERFETTO_ELOG("Subprocess.exec_cmd cannot be empty on Windows");
+ return;
+ }
+
+ // Quote arguments but only when ambiguous. When quoting, CreateProcess()
+ // assumes that the command is an absolute path and does not search in the
+ // %PATH%. If non quoted, instead, CreateProcess() tries both. This is to
+ // allow Subprocess("cmd.exe", "/c", "shell command").
+ std::string cmd;
+ for (const auto& part : args.exec_cmd) {
+ if (part.find(" ") != std::string::npos) {
+ cmd += "\"" + part + "\" ";
+ } else {
+ cmd += part + " ";
+ }
+ }
+ // Remove trailing space.
+ if (!cmd.empty())
+ cmd.resize(cmd.size() - 1);
+
+ if (args.stdin_mode == InputMode::kBuffer) {
+ s_->stdin_pipe = Pipe::Create();
+ // Allow the child process to inherit the other end of the pipe.
+ PERFETTO_CHECK(
+ ::SetHandleInformation(*s_->stdin_pipe.rd, HANDLE_FLAG_INHERIT, 1));
+ }
+
+ if (args.stderr_mode == OutputMode::kBuffer ||
+ args.stdout_mode == OutputMode::kBuffer) {
+ s_->stdouterr_pipe = Pipe::Create();
+ PERFETTO_CHECK(
+ ::SetHandleInformation(*s_->stdouterr_pipe.wr, HANDLE_FLAG_INHERIT, 1));
+ }
+
+ ScopedPlatformHandle nul_handle;
+ if (args.stderr_mode == OutputMode::kDevNull ||
+ args.stdout_mode == OutputMode::kDevNull) {
+ nul_handle.reset(::CreateFileA(
+ "NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
+ PERFETTO_CHECK(::SetHandleInformation(*nul_handle, HANDLE_FLAG_INHERIT, 1));
+ }
+
+ PROCESS_INFORMATION proc_info{};
+ STARTUPINFOA start_info{};
+ start_info.cb = sizeof(STARTUPINFOA);
+
+ if (args.stderr_mode == OutputMode::kInherit) {
+ start_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+ } else if (args.stderr_mode == OutputMode::kBuffer) {
+ start_info.hStdError = *s_->stdouterr_pipe.wr;
+ } else if (args.stderr_mode == OutputMode::kDevNull) {
+ start_info.hStdError = *nul_handle;
+ } else if (args.stderr_mode == OutputMode::kFd) {
+ PERFETTO_CHECK(
+ ::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
+ start_info.hStdError = *args.out_fd;
+ } else {
+ PERFETTO_CHECK(false);
+ }
+
+ if (args.stdout_mode == OutputMode::kInherit) {
+ start_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+ } else if (args.stdout_mode == OutputMode::kBuffer) {
+ start_info.hStdOutput = *s_->stdouterr_pipe.wr;
+ } else if (args.stdout_mode == OutputMode::kDevNull) {
+ start_info.hStdOutput = *nul_handle;
+ } else if (args.stdout_mode == OutputMode::kFd) {
+ PERFETTO_CHECK(
+ ::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
+ start_info.hStdOutput = *args.out_fd;
+ } else {
+ PERFETTO_CHECK(false);
+ }
+
+ if (args.stdin_mode == InputMode::kBuffer) {
+ start_info.hStdInput = *s_->stdin_pipe.rd;
+ } else if (args.stdin_mode == InputMode::kDevNull) {
+ start_info.hStdInput = *nul_handle;
+ }
+
+ start_info.dwFlags |= STARTF_USESTDHANDLES;
+
+ // Create the child process.
+ bool success =
+ ::CreateProcessA(nullptr, // App name. Needs to be null to use PATH.
+ &cmd[0], // Command line.
+ nullptr, // Process security attributes.
+ nullptr, // Primary thread security attributes.
+ true, // Handles are inherited.
+ 0, // Flags.
+ nullptr, // Use parent's environment.
+ nullptr, // Use parent's current directory.
+ &start_info, // STARTUPINFO pointer.
+ &proc_info); // Receives PROCESS_INFORMATION.
+
+ // Close on our side the pipe ends that we passed to the child process.
+ s_->stdin_pipe.rd.reset();
+ s_->stdouterr_pipe.wr.reset();
+ args.out_fd.reset();
+
+ if (!success) {
+ s_->returncode = ERROR_FILE_NOT_FOUND;
+ s_->status = kTerminated;
+ s_->stdin_pipe.wr.reset();
+ s_->stdouterr_pipe.rd.reset();
+ PERFETTO_ELOG("CreateProcess failed: %lx, cmd: %s", GetLastError(),
+ &cmd[0]);
+ return;
+ }
+
+ s_->pid = proc_info.dwProcessId;
+ s_->win_proc_handle = ScopedPlatformHandle(proc_info.hProcess);
+ s_->win_thread_handle = ScopedPlatformHandle(proc_info.hThread);
+ s_->status = kRunning;
+
+ MovableState* s = s_.get();
+ if (args.stdin_mode == InputMode::kBuffer) {
+ s_->stdin_thread = std::thread(&Subprocess::StdinThread, s, args.input);
+ }
+
+ if (args.stderr_mode == OutputMode::kBuffer ||
+ args.stdout_mode == OutputMode::kBuffer) {
+ PERFETTO_DCHECK(s_->stdouterr_pipe.rd);
+ s_->stdouterr_thread = std::thread(&Subprocess::StdoutErrThread, s);
+ }
+}
+
+// static
+void Subprocess::StdinThread(MovableState* s, std::string input) {
+ size_t input_written = 0;
+ while (input_written < input.size()) {
+ DWORD wsize = 0;
+ if (::WriteFile(*s->stdin_pipe.wr, input.data() + input_written,
+ static_cast<DWORD>(input.size() - input_written), &wsize,
+ nullptr)) {
+ input_written += wsize;
+ } else {
+ // ERROR_BROKEN_PIPE is WAI when the child just closes stdin and stops
+ // accepting input.
+ auto err = ::GetLastError();
+ if (err != ERROR_BROKEN_PIPE)
+ PERFETTO_PLOG("Subprocess WriteFile(stdin) failed %lx", err);
+ break;
+ }
+ } // while(...)
+ std::unique_lock<std::mutex> lock(s->mutex);
+ s->stdin_pipe.wr.reset();
+}
+
+// static
+void Subprocess::StdoutErrThread(MovableState* s) {
+ char buf[4096];
+ for (;;) {
+ DWORD rsize = 0;
+ bool res =
+ ::ReadFile(*s->stdouterr_pipe.rd, buf, sizeof(buf), &rsize, nullptr);
+ if (!res) {
+ auto err = GetLastError();
+ if (err != ERROR_BROKEN_PIPE)
+ PERFETTO_PLOG("Subprocess ReadFile(stdouterr) failed %ld", err);
+ }
+
+ if (rsize > 0) {
+ std::unique_lock<std::mutex> lock(s->mutex);
+ s->locked_outerr_buf.append(buf, static_cast<size_t>(rsize));
+ } else { // EOF or some error.
+ break;
+ }
+ } // For(..)
+
+ // Close the stdouterr_pipe. The main loop looks at the pipe closure to
+ // determine whether the stdout/err thread has completed.
+ {
+ std::unique_lock<std::mutex> lock(s->mutex);
+ s->stdouterr_pipe.rd.reset();
+ }
+ s->stdouterr_done_event.Notify();
+}
+
+Subprocess::Status Subprocess::Poll() {
+ if (s_->status != kRunning)
+ return s_->status; // Nothing to poll.
+ Wait(1 /*ms*/);
+ return s_->status;
+}
+
+bool Subprocess::Wait(int timeout_ms) {
+ PERFETTO_CHECK(s_->status != kNotStarted);
+ const bool wait_forever = timeout_ms == 0;
+ const int64_t wait_start_ms = base::GetWallTimeMs().count();
+
+ // Break out of the loop only after both conditions are satisfied:
+ // - All stdout/stderr data has been read (if OutputMode::kBuffer).
+ // - The process exited.
+ // Note that the two events can happen arbitrary order. After the process
+ // exits, there might be still data in the pipe buffer, which we want to
+ // read fully.
+ // Note also that stdout/err might be "complete" before starting, if neither
+ // is operating in OutputMode::kBuffer mode. In that case we just want to wait
+ // for the process termination.
+ //
+ // Instead, don't wait on the stdin to be fully written. The child process
+ // might exit prematurely (or crash). If that happens, we can end up in a
+ // state where the write(stdin_pipe_.wr) will never unblock.
+ bool stdouterr_complete = false;
+ for (;;) {
+ HANDLE wait_handles[2]{};
+ DWORD num_handles = 0;
+
+ // Check if the process exited.
+ bool process_exited = !s_->win_proc_handle;
+ if (!process_exited) {
+ DWORD exit_code = STILL_ACTIVE;
+ PERFETTO_CHECK(::GetExitCodeProcess(*s_->win_proc_handle, &exit_code));
+ if (exit_code != STILL_ACTIVE) {
+ s_->returncode = static_cast<int>(exit_code);
+ s_->status = kTerminated;
+ s_->win_proc_handle.reset();
+ s_->win_thread_handle.reset();
+ process_exited = true;
+ }
+ } else {
+ PERFETTO_DCHECK(s_->status != kRunning);
+ }
+ if (!process_exited) {
+ wait_handles[num_handles++] = *s_->win_proc_handle;
+ }
+
+ // Check if there is more output and if the stdout/err pipe has been closed.
+ {
+ std::unique_lock<std::mutex> lock(s_->mutex);
+ // Move the output from the internal buffer shared with the
+ // stdouterr_thread to the final buffer exposed to the client.
+ if (!s_->locked_outerr_buf.empty()) {
+ s_->output.append(std::move(s_->locked_outerr_buf));
+ s_->locked_outerr_buf.clear();
+ }
+ stdouterr_complete = !s_->stdouterr_pipe.rd;
+ if (!stdouterr_complete) {
+ wait_handles[num_handles++] = s_->stdouterr_done_event.fd();
+ }
+ } // lock(s_->mutex)
+
+ if (num_handles == 0) {
+ PERFETTO_DCHECK(process_exited && stdouterr_complete);
+ break;
+ }
+
+ DWORD wait_ms; // Note: DWORD is unsigned.
+ if (wait_forever) {
+ wait_ms = INFINITE;
+ } else {
+ const int64_t now = GetWallTimeMs().count();
+ const int64_t wait_left_ms = timeout_ms - (now - wait_start_ms);
+ if (wait_left_ms <= 0)
+ return false; // Timed out
+ wait_ms = static_cast<DWORD>(wait_left_ms);
+ }
+
+ auto wait_res =
+ ::WaitForMultipleObjects(num_handles, wait_handles, false, wait_ms);
+ PERFETTO_CHECK(wait_res != WAIT_FAILED);
+ }
+
+ PERFETTO_DCHECK(!s_->win_proc_handle);
+ PERFETTO_DCHECK(!s_->win_thread_handle);
+
+ if (s_->stdin_thread.joinable()) // Might not exist if CreateProcess failed.
+ s_->stdin_thread.join();
+ if (s_->stdouterr_thread.joinable())
+ s_->stdouterr_thread.join();
+
+ // The stdin pipe is closed by the dedicated stdin thread. However if that is
+ // not started (e.g. because of no redirection) force close it now. Needs to
+ // happen after the join() to be thread safe.
+ s_->stdin_pipe.wr.reset();
+ s_->stdouterr_pipe.rd.reset();
+
+ return true;
+}
+
+void Subprocess::KillAndWaitForTermination(int exit_code) {
+ auto code = exit_code ? static_cast<DWORD>(exit_code) : STATUS_CONTROL_C_EXIT;
+ ::TerminateProcess(*s_->win_proc_handle, code);
+ Wait();
+ // TryReadExitStatus must have joined the threads.
+ PERFETTO_DCHECK(!s_->stdin_thread.joinable());
+ PERFETTO_DCHECK(!s_->stdouterr_thread.joinable());
+}
+
+} // namespace base
+} // namespace perfetto
+
+#endif // PERFETTO_OS_WIN
+// gen_amalgamated begin source: src/protozero/field.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+#if !PERFETTO_IS_LITTLE_ENDIAN()
+// The memcpy() for fixed32/64 below needs to be adjusted if we want to
+// support big endian CPUs. There doesn't seem to be a compelling need today.
+#error Unimplemented for big endian archs.
+#endif
+
+namespace protozero {
+
+template <typename Container>
+void Field::SerializeAndAppendToInternal(Container* dst) const {
+ namespace pu = proto_utils;
+ size_t initial_size = dst->size();
+ dst->resize(initial_size + pu::kMaxSimpleFieldEncodedSize + size_);
+ uint8_t* start = reinterpret_cast<uint8_t*>(&(*dst)[initial_size]);
+ uint8_t* wptr = start;
+ switch (type_) {
+ case static_cast<int>(pu::ProtoWireType::kVarInt): {
+ wptr = pu::WriteVarInt(pu::MakeTagVarInt(id_), wptr);
+ wptr = pu::WriteVarInt(int_value_, wptr);
+ break;
+ }
+ case static_cast<int>(pu::ProtoWireType::kFixed32): {
+ wptr = pu::WriteVarInt(pu::MakeTagFixed<uint32_t>(id_), wptr);
+ uint32_t value32 = static_cast<uint32_t>(int_value_);
+ memcpy(wptr, &value32, sizeof(value32));
+ wptr += sizeof(uint32_t);
+ break;
+ }
+ case static_cast<int>(pu::ProtoWireType::kFixed64): {
+ wptr = pu::WriteVarInt(pu::MakeTagFixed<uint64_t>(id_), wptr);
+ memcpy(wptr, &int_value_, sizeof(int_value_));
+ wptr += sizeof(uint64_t);
+ break;
+ }
+ case static_cast<int>(pu::ProtoWireType::kLengthDelimited): {
+ ConstBytes payload = as_bytes();
+ wptr = pu::WriteVarInt(pu::MakeTagLengthDelimited(id_), wptr);
+ wptr = pu::WriteVarInt(payload.size, wptr);
+ memcpy(wptr, payload.data, payload.size);
+ wptr += payload.size;
+ break;
+ }
+ default:
+ PERFETTO_FATAL("Unknown field type %u", type_);
+ }
+ size_t written_size = static_cast<size_t>(wptr - start);
+ PERFETTO_DCHECK(written_size > 0 && written_size < pu::kMaxMessageLength);
+ PERFETTO_DCHECK(initial_size + written_size <= dst->size());
+ dst->resize(initial_size + written_size);
+}
+
+void Field::SerializeAndAppendTo(std::string* dst) const {
+ SerializeAndAppendToInternal(dst);
+}
+
+void Field::SerializeAndAppendTo(std::vector<uint8_t>* dst) const {
+ SerializeAndAppendToInternal(dst);
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/gen_field_helpers.cc
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+
+namespace protozero {
+namespace internal {
+namespace gen_helpers {
+
+void DeserializeString(const protozero::Field& field, std::string* dst) {
+ field.get(dst);
+}
+
+template bool DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt,
+ uint64_t>(const protozero::Field& field,
+ std::vector<uint64_t>* dst);
+
+template bool DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt,
+ int64_t>(const protozero::Field& field,
+ std::vector<int64_t>* dst);
+
+template bool DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt,
+ uint32_t>(const protozero::Field& field,
+ std::vector<uint32_t>* dst);
+
+template bool DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt,
+ int32_t>(const protozero::Field& field,
+ std::vector<int32_t>* dst);
+
+void SerializeTinyVarInt(uint32_t field_id, bool value, Message* msg) {
+ msg->AppendTinyVarInt(field_id, value);
+}
+
+template void SerializeExtendedVarInt<uint64_t>(uint32_t field_id,
+ uint64_t value,
+ Message* msg);
+
+template void SerializeExtendedVarInt<uint32_t>(uint32_t field_id,
+ uint32_t value,
+ Message* msg);
+
+template void SerializeFixed<double>(uint32_t field_id,
+ double value,
+ Message* msg);
+
+template void SerializeFixed<float>(uint32_t field_id,
+ float value,
+ Message* msg);
+
+template void SerializeFixed<uint64_t>(uint32_t field_id,
+ uint64_t value,
+ Message* msg);
+
+template void SerializeFixed<int64_t>(uint32_t field_id,
+ int64_t value,
+ Message* msg);
+
+template void SerializeFixed<uint32_t>(uint32_t field_id,
+ uint32_t value,
+ Message* msg);
+
+template void SerializeFixed<int32_t>(uint32_t field_id,
+ int32_t value,
+ Message* msg);
+
+void SerializeString(uint32_t field_id,
+ const std::string& value,
+ Message* msg) {
+ msg->AppendString(field_id, value);
+}
+
+void SerializeUnknownFields(const std::string& unknown_fields, Message* msg) {
+ msg->AppendRawProtoBytes(unknown_fields.data(), unknown_fields.size());
+}
+
+MessageSerializer::MessageSerializer() = default;
+
+MessageSerializer::~MessageSerializer() = default;
+
+std::vector<uint8_t> MessageSerializer::SerializeAsArray() {
+ return msg_.SerializeAsArray();
+}
+
+std::string MessageSerializer::SerializeAsString() {
+ return msg_.SerializeAsString();
+}
+
+template bool EqualsField<std::string>(const std::string&, const std::string&);
+
+} // namespace gen_helpers
+} // namespace internal
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/message.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+
+#include <atomic>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_arena.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+
+#if !PERFETTO_IS_LITTLE_ENDIAN()
+// The memcpy() for float and double below needs to be adjusted if we want to
+// support big endian CPUs. There doesn't seem to be a compelling need today.
+#error Unimplemented for big endian archs.
+#endif
+
+namespace protozero {
+
+namespace {
+
+constexpr int kBytesToCompact = proto_utils::kMessageLengthFieldSize - 1u;
+
+#if PERFETTO_DCHECK_IS_ON()
+std::atomic<uint32_t> g_generation;
+#endif
+
+} // namespace
+
+// Do NOT put any code in the constructor or use default initialization.
+// Use the Reset() method below instead.
+
+// This method is called to initialize both root and nested messages.
+void Message::Reset(ScatteredStreamWriter* stream_writer, MessageArena* arena) {
+// Older versions of libstdcxx don't have is_trivially_constructible.
+#if !defined(__GLIBCXX__) || __GLIBCXX__ >= 20170516
+ static_assert(std::is_trivially_constructible<Message>::value,
+ "Message must be trivially constructible");
+#endif
+
+ static_assert(std::is_trivially_destructible<Message>::value,
+ "Message must be trivially destructible");
+ stream_writer_ = stream_writer;
+ arena_ = arena;
+ size_ = 0;
+ size_field_ = nullptr;
+ nested_message_ = nullptr;
+ message_state_ = MessageState::kNotFinalized;
+#if PERFETTO_DCHECK_IS_ON()
+ handle_ = nullptr;
+ generation_ = g_generation.fetch_add(1, std::memory_order_relaxed);
+#endif
+}
+
+void Message::AppendString(uint32_t field_id, const char* str) {
+ AppendBytes(field_id, str, strlen(str));
+}
+
+void Message::AppendBytes(uint32_t field_id, const void* src, size_t size) {
+ PERFETTO_DCHECK(field_id);
+ if (nested_message_)
+ EndNestedMessage();
+
+ PERFETTO_DCHECK(size < proto_utils::kMaxMessageLength);
+ // Write the proto preamble (field id, type and length of the field).
+ uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
+ uint8_t* pos = buffer;
+ pos = proto_utils::WriteVarInt(proto_utils::MakeTagLengthDelimited(field_id),
+ pos);
+ pos = proto_utils::WriteVarInt(static_cast<uint32_t>(size), pos);
+ WriteToStream(buffer, pos);
+
+ const uint8_t* src_u8 = reinterpret_cast<const uint8_t*>(src);
+ WriteToStream(src_u8, src_u8 + size);
+}
+
+size_t Message::AppendScatteredBytes(uint32_t field_id,
+ ContiguousMemoryRange* ranges,
+ size_t num_ranges) {
+ PERFETTO_DCHECK(field_id);
+ if (nested_message_)
+ EndNestedMessage();
+
+ size_t size = 0;
+ for (size_t i = 0; i < num_ranges; ++i) {
+ size += ranges[i].size();
+ }
+
+ PERFETTO_DCHECK(size < proto_utils::kMaxMessageLength);
+
+ uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
+ uint8_t* pos = buffer;
+ pos = proto_utils::WriteVarInt(proto_utils::MakeTagLengthDelimited(field_id),
+ pos);
+ pos = proto_utils::WriteVarInt(static_cast<uint32_t>(size), pos);
+ WriteToStream(buffer, pos);
+
+ for (size_t i = 0; i < num_ranges; ++i) {
+ auto& range = ranges[i];
+ WriteToStream(range.begin, range.end);
+ }
+
+ return size;
+}
+
+uint32_t Message::Finalize() {
+ if (is_finalized())
+ return size_;
+
+ if (nested_message_)
+ EndNestedMessage();
+
+ // Write the length of the nested message a posteriori, using a leading-zero
+ // redundant varint encoding. This can be nullptr for the root message, among
+ // many reasons, because the TraceWriterImpl delegate is keeping track of the
+ // root fragment size independently.
+ if (size_field_) {
+ PERFETTO_DCHECK(!is_finalized());
+ PERFETTO_DCHECK(size_ < proto_utils::kMaxMessageLength);
+ //
+ // Normally the size of a protozero message is written with 4 bytes just
+ // before the contents of the message itself:
+ //
+ // size message data
+ // [aa bb cc dd] [01 23 45 67 ...]
+ //
+ // We always reserve 4 bytes for the size, because the real size of the
+ // message isn't known until the call to Finalize(). This is possible
+ // because we can use leading zero redundant varint coding to expand any
+ // size smaller than 256 MiB to 4 bytes.
+ //
+ // However this is wasteful for short, frequently written messages, so the
+ // code below uses a 1 byte size field when possible. This is done by
+ // shifting the already-written data (which should still be in the cache)
+ // back by 3 bytes, resulting in this layout:
+ //
+ // size message data
+ // [aa] [01 23 45 67 ...]
+ //
+ // We can only do this optimization if the message is contained in a single
+ // chunk (since we can't modify previously committed chunks). We can check
+ // this by verifying that the size field is immediately before the message
+ // in memory and is fully contained by the current chunk.
+ //
+ if (PERFETTO_LIKELY(size_ <= proto_utils::kMaxOneByteMessageLength &&
+ size_field_ ==
+ stream_writer_->write_ptr() - size_ -
+ proto_utils::kMessageLengthFieldSize &&
+ size_field_ >= stream_writer_->cur_range().begin)) {
+ stream_writer_->Rewind(size_, kBytesToCompact);
+ PERFETTO_DCHECK(size_field_ == stream_writer_->write_ptr() - size_ - 1u);
+ *size_field_ = static_cast<uint8_t>(size_);
+ message_state_ = MessageState::kFinalizedWithCompaction;
+ } else {
+ proto_utils::WriteRedundantVarInt(size_, size_field_);
+ message_state_ = MessageState::kFinalized;
+ }
+ size_field_ = nullptr;
+ } else {
+ message_state_ = MessageState::kFinalized;
+ }
+
+#if PERFETTO_DCHECK_IS_ON()
+ if (handle_)
+ handle_->reset_message();
+#endif
+
+ return size_;
+}
+
+Message* Message::BeginNestedMessageInternal(uint32_t field_id) {
+ PERFETTO_DCHECK(field_id);
+ if (nested_message_)
+ EndNestedMessage();
+
+ // Write the proto preamble for the nested message.
+ uint8_t data[proto_utils::kMaxTagEncodedSize];
+ uint8_t* data_end = proto_utils::WriteVarInt(
+ proto_utils::MakeTagLengthDelimited(field_id), data);
+ WriteToStream(data, data_end);
+
+ Message* message = arena_->NewMessage();
+ message->Reset(stream_writer_, arena_);
+
+ // The length of the nested message cannot be known upfront. So right now
+ // just reserve the bytes to encode the size after the nested message is done.
+ message->set_size_field(
+ stream_writer_->ReserveBytes(proto_utils::kMessageLengthFieldSize));
+ size_ += proto_utils::kMessageLengthFieldSize;
+
+ nested_message_ = message;
+ return message;
+}
+
+void Message::EndNestedMessage() {
+ size_ += nested_message_->Finalize();
+ if (nested_message_->message_state_ ==
+ MessageState::kFinalizedWithCompaction) {
+ size_ -= kBytesToCompact;
+ }
+ arena_->DeleteLastMessage(nested_message_);
+ nested_message_ = nullptr;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/message_arena.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message_arena.h"
+
+#include <atomic>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+
+namespace protozero {
+
+MessageArena::MessageArena() {
+ // The code below assumes that there is always at least one block.
+ blocks_.emplace_front();
+ static_assert(
+ std::alignment_of<decltype(blocks_.front().storage[0])>::value >=
+ alignof(Message),
+ "MessageArea's storage is not properly aligned");
+}
+
+MessageArena::~MessageArena() = default;
+
+Message* MessageArena::NewMessage() {
+ PERFETTO_DCHECK(!blocks_.empty()); // Should never become empty.
+
+ Block* block = &blocks_.front();
+ if (PERFETTO_UNLIKELY(block->entries >= Block::kCapacity)) {
+ blocks_.emplace_front();
+ block = &blocks_.front();
+ }
+ const auto idx = block->entries++;
+ void* storage = &block->storage[idx];
+ PERFETTO_ASAN_UNPOISON(storage, sizeof(Message));
+ return new (storage) Message();
+}
+
+void MessageArena::DeleteLastMessageInternal() {
+ PERFETTO_DCHECK(!blocks_.empty()); // Should never be empty, see below.
+ Block* block = &blocks_.front();
+ PERFETTO_DCHECK(block->entries > 0);
+
+ // This is the reason why there is no ~Message() call here.
+ // MessageArea::Reset() (see header) also relies on dtor being trivial.
+ static_assert(std::is_trivially_destructible<Message>::value,
+ "Message must be trivially destructible");
+
+ --block->entries;
+ PERFETTO_ASAN_POISON(&block->storage[block->entries], sizeof(Message));
+
+ // Don't remove the first block to avoid malloc/free calls when the root
+ // message is reset. Hitting the allocator all the times is a waste of time.
+ if (block->entries == 0 && std::next(blocks_.cbegin()) != blocks_.cend()) {
+ blocks_.pop_front();
+ }
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/packed_repeated_fields.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace protozero {
+
+void PackedBufferBase::GrowSlowpath() {
+ size_t write_off = static_cast<size_t>(write_ptr_ - storage_begin_);
+ size_t old_size = static_cast<size_t>(storage_end_ - storage_begin_);
+ size_t new_size = old_size < 65536 ? (old_size * 2) : (old_size * 3 / 2);
+ new_size = perfetto::base::AlignUp<4096>(new_size);
+ std::unique_ptr<uint8_t[]> new_buf(new uint8_t[new_size]);
+ memcpy(new_buf.get(), storage_begin_, old_size);
+ heap_buf_ = std::move(new_buf);
+ storage_begin_ = heap_buf_.get();
+ storage_end_ = storage_begin_ + new_size;
+ write_ptr_ = storage_begin_ + write_off;
+}
+
+void PackedBufferBase::Reset() {
+ heap_buf_.reset();
+ storage_begin_ = reinterpret_cast<uint8_t*>(&stack_buf_[0]);
+ storage_end_ = reinterpret_cast<uint8_t*>(&stack_buf_[kOnStackStorageSize]);
+ write_ptr_ = storage_begin_;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/proto_decoder.cc
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+
+#include <string.h>
+
+#include <cinttypes>
+#include <limits>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace protozero {
+
+using namespace proto_utils;
+
+#if !PERFETTO_IS_LITTLE_ENDIAN()
+#error Unimplemented for big endian archs.
+#endif
+
+namespace {
+
+struct ParseFieldResult {
+ enum ParseResult { kAbort, kSkip, kOk };
+ ParseResult parse_res;
+ const uint8_t* next;
+ Field field;
+};
+
+// Parses one field and returns the field itself and a pointer to the next
+// field to parse. If parsing fails, the returned |next| == |buffer|.
+ParseFieldResult ParseOneField(const uint8_t* const buffer,
+ const uint8_t* const end) {
+ ParseFieldResult res{ParseFieldResult::kAbort, buffer, Field{}};
+
+ // The first byte of a proto field is structured as follows:
+ // The least 3 significant bits determine the field type.
+ // The most 5 significant bits determine the field id. If MSB == 1, the
+ // field id continues on the next bytes following the VarInt encoding.
+ const uint8_t kFieldTypeNumBits = 3;
+ const uint64_t kFieldTypeMask = (1 << kFieldTypeNumBits) - 1; // 0000 0111;
+ const uint8_t* pos = buffer;
+
+ // If we've already hit the end, just return an invalid field.
+ if (PERFETTO_UNLIKELY(pos >= end))
+ return res;
+
+ uint64_t preamble = 0;
+ if (PERFETTO_LIKELY(*pos < 0x80)) { // Fastpath for fields with ID < 16.
+ preamble = *(pos++);
+ } else {
+ const uint8_t* next = ParseVarInt(pos, end, &preamble);
+ if (PERFETTO_UNLIKELY(pos == next))
+ return res;
+ pos = next;
+ }
+
+ uint32_t field_id = static_cast<uint32_t>(preamble >> kFieldTypeNumBits);
+ if (field_id == 0 || pos >= end)
+ return res;
+
+ auto field_type = static_cast<uint8_t>(preamble & kFieldTypeMask);
+ const uint8_t* new_pos = pos;
+ uint64_t int_value = 0;
+ uint64_t size = 0;
+
+ switch (field_type) {
+ case static_cast<uint8_t>(ProtoWireType::kVarInt): {
+ new_pos = ParseVarInt(pos, end, &int_value);
+
+ // new_pos not being greater than pos means ParseVarInt could not fully
+ // parse the number. This is because we are out of space in the buffer.
+ // Set the id to zero and return but don't update the offset so a future
+ // read can read this field.
+ if (PERFETTO_UNLIKELY(new_pos == pos))
+ return res;
+
+ break;
+ }
+
+ case static_cast<uint8_t>(ProtoWireType::kLengthDelimited): {
+ uint64_t payload_length;
+ new_pos = ParseVarInt(pos, end, &payload_length);
+ if (PERFETTO_UNLIKELY(new_pos == pos))
+ return res;
+
+ // ParseVarInt guarantees that |new_pos| <= |end| when it succeeds;
+ if (payload_length > static_cast<uint64_t>(end - new_pos))
+ return res;
+
+ const uintptr_t payload_start = reinterpret_cast<uintptr_t>(new_pos);
+ int_value = payload_start;
+ size = payload_length;
+ new_pos += payload_length;
+ break;
+ }
+
+ case static_cast<uint8_t>(ProtoWireType::kFixed64): {
+ new_pos = pos + sizeof(uint64_t);
+ if (PERFETTO_UNLIKELY(new_pos > end))
+ return res;
+ memcpy(&int_value, pos, sizeof(uint64_t));
+ break;
+ }
+
+ case static_cast<uint8_t>(ProtoWireType::kFixed32): {
+ new_pos = pos + sizeof(uint32_t);
+ if (PERFETTO_UNLIKELY(new_pos > end))
+ return res;
+ memcpy(&int_value, pos, sizeof(uint32_t));
+ break;
+ }
+
+ default:
+ PERFETTO_DLOG("Invalid proto field type: %u", field_type);
+ return res;
+ }
+
+ res.next = new_pos;
+
+ if (PERFETTO_UNLIKELY(field_id > Field::kMaxId)) {
+ PERFETTO_DLOG("Skipping field %" PRIu32 " because its id > %" PRIu32,
+ field_id, Field::kMaxId);
+ res.parse_res = ParseFieldResult::kSkip;
+ return res;
+ }
+
+ if (PERFETTO_UNLIKELY(size > proto_utils::kMaxMessageLength)) {
+ PERFETTO_DLOG("Skipping field %" PRIu32 " because it's too big (%" PRIu64
+ " KB)",
+ field_id, size / 1024);
+ res.parse_res = ParseFieldResult::kSkip;
+ return res;
+ }
+
+ res.parse_res = ParseFieldResult::kOk;
+ res.field.initialize(field_id, field_type, int_value,
+ static_cast<uint32_t>(size));
+ return res;
+}
+
+} // namespace
+
+Field ProtoDecoder::FindField(uint32_t field_id) {
+ Field res{};
+ auto old_position = read_ptr_;
+ read_ptr_ = begin_;
+ for (auto f = ReadField(); f.valid(); f = ReadField()) {
+ if (f.id() == field_id) {
+ res = f;
+ break;
+ }
+ }
+ read_ptr_ = old_position;
+ return res;
+}
+
+Field ProtoDecoder::ReadField() {
+ ParseFieldResult res;
+ do {
+ res = ParseOneField(read_ptr_, end_);
+ read_ptr_ = res.next;
+ } while (PERFETTO_UNLIKELY(res.parse_res == ParseFieldResult::kSkip));
+ return res.field;
+}
+
+void TypedProtoDecoderBase::ParseAllFields() {
+ const uint8_t* cur = begin_;
+ ParseFieldResult res;
+ for (;;) {
+ res = ParseOneField(cur, end_);
+ PERFETTO_DCHECK(res.parse_res != ParseFieldResult::kOk || res.next != cur);
+ cur = res.next;
+ if (PERFETTO_UNLIKELY(res.parse_res == ParseFieldResult::kSkip))
+ continue;
+ if (PERFETTO_UNLIKELY(res.parse_res == ParseFieldResult::kAbort))
+ break;
+
+ PERFETTO_DCHECK(res.parse_res == ParseFieldResult::kOk);
+ PERFETTO_DCHECK(res.field.valid());
+ auto field_id = res.field.id();
+ if (PERFETTO_UNLIKELY(field_id >= num_fields_))
+ continue;
+
+ // There are two reasons why we might want to expand the heap capacity:
+ // 1. We are writing a non-repeated field, which has an id >
+ // INITIAL_STACK_CAPACITY. In this case ExpandHeapStorage() ensures to
+ // allocate at least (num_fields_ + 1) slots.
+ // 2. We are writing a repeated field but ran out of capacity.
+ if (PERFETTO_UNLIKELY(field_id >= size_ || size_ >= capacity_))
+ ExpandHeapStorage();
+
+ PERFETTO_DCHECK(field_id < size_);
+ Field* fld = &fields_[field_id];
+ if (PERFETTO_LIKELY(!fld->valid())) {
+ // This is the first time we see this field.
+ *fld = std::move(res.field);
+ } else {
+ // Repeated field case.
+ // In this case we need to:
+ // 1. Append the last value of the field to end of the repeated field
+ // storage.
+ // 2. Replace the default instance at offset |field_id| with the current
+ // value. This is because in case of repeated field a call to Get(X) is
+ // supposed to return the last value of X, not the first one.
+ // This is so that the RepeatedFieldIterator will iterate in the right
+ // order, see comments on RepeatedFieldIterator.
+ if (num_fields_ > size_) {
+ ExpandHeapStorage();
+ fld = &fields_[field_id];
+ }
+
+ PERFETTO_DCHECK(size_ < capacity_);
+ fields_[size_++] = *fld;
+ *fld = std::move(res.field);
+ }
+ }
+ read_ptr_ = res.next;
+}
+
+void TypedProtoDecoderBase::ExpandHeapStorage() {
+ // When we expand the heap we must ensure that we have at very last capacity
+ // to deal with all known fields plus at least one repeated field. We go +2048
+ // here based on observations on a large 4GB android trace. This is to avoid
+ // trivial re-allocations when dealing with repeated fields of a message that
+ // has > INITIAL_STACK_CAPACITY fields.
+ const uint32_t min_capacity = num_fields_ + 2048; // Any num >= +1 will do.
+ const uint32_t new_capacity = std::max(capacity_ * 2, min_capacity);
+ PERFETTO_CHECK(new_capacity > size_ && new_capacity > num_fields_);
+ std::unique_ptr<Field[]> new_storage(new Field[new_capacity]);
+
+ static_assert(std::is_trivially_constructible<Field>::value,
+ "Field must be trivially constructible");
+ static_assert(std::is_trivially_copyable<Field>::value,
+ "Field must be trivially copyable");
+
+ // Zero-initialize the slots for known field IDs slots, as they can be
+ // randomly accessed. Instead, there is no need to initialize the repeated
+ // slots, because they are written linearly with no gaps and are always
+ // initialized before incrementing |size_|.
+ const uint32_t new_size = std::max(size_, num_fields_);
+ memset(&new_storage[size_], 0, sizeof(Field) * (new_size - size_));
+
+ memcpy(&new_storage[0], fields_, sizeof(Field) * size_);
+
+ heap_storage_ = std::move(new_storage);
+ fields_ = &heap_storage_[0];
+ capacity_ = new_capacity;
+ size_ = new_size;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/scattered_heap_buffer.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+
+#include <algorithm>
+
+namespace protozero {
+
+ScatteredHeapBuffer::Slice::Slice()
+ : buffer_(nullptr), size_(0u), unused_bytes_(0u) {}
+
+ScatteredHeapBuffer::Slice::Slice(size_t size)
+ : buffer_(std::unique_ptr<uint8_t[]>(new uint8_t[size])),
+ size_(size),
+ unused_bytes_(size) {
+ PERFETTO_DCHECK(size);
+ Clear();
+}
+
+ScatteredHeapBuffer::Slice::Slice(Slice&& slice) noexcept = default;
+
+ScatteredHeapBuffer::Slice::~Slice() = default;
+
+ScatteredHeapBuffer::Slice& ScatteredHeapBuffer::Slice::operator=(Slice&&) =
+ default;
+
+void ScatteredHeapBuffer::Slice::Clear() {
+ unused_bytes_ = size_;
+#if PERFETTO_DCHECK_IS_ON()
+ memset(start(), 0xff, size_);
+#endif // PERFETTO_DCHECK_IS_ON()
+}
+
+ScatteredHeapBuffer::ScatteredHeapBuffer(size_t initial_slice_size_bytes,
+ size_t maximum_slice_size_bytes)
+ : next_slice_size_(initial_slice_size_bytes),
+ maximum_slice_size_(maximum_slice_size_bytes) {
+ PERFETTO_DCHECK(next_slice_size_ && maximum_slice_size_);
+ PERFETTO_DCHECK(maximum_slice_size_ >= initial_slice_size_bytes);
+}
+
+ScatteredHeapBuffer::~ScatteredHeapBuffer() = default;
+
+protozero::ContiguousMemoryRange ScatteredHeapBuffer::GetNewBuffer() {
+ PERFETTO_CHECK(writer_);
+ AdjustUsedSizeOfCurrentSlice();
+
+ if (cached_slice_.start()) {
+ slices_.push_back(std::move(cached_slice_));
+ PERFETTO_DCHECK(!cached_slice_.start());
+ } else {
+ slices_.emplace_back(next_slice_size_);
+ }
+ next_slice_size_ = std::min(maximum_slice_size_, next_slice_size_ * 2);
+ return slices_.back().GetTotalRange();
+}
+
+const std::vector<ScatteredHeapBuffer::Slice>&
+ScatteredHeapBuffer::GetSlices() {
+ AdjustUsedSizeOfCurrentSlice();
+ return slices_;
+}
+
+std::vector<uint8_t> ScatteredHeapBuffer::StitchSlices() {
+ size_t stitched_size = 0u;
+ const auto& slices = GetSlices();
+ for (const auto& slice : slices)
+ stitched_size += slice.size() - slice.unused_bytes();
+
+ std::vector<uint8_t> buffer;
+ buffer.reserve(stitched_size);
+ for (const auto& slice : slices) {
+ auto used_range = slice.GetUsedRange();
+ buffer.insert(buffer.end(), used_range.begin, used_range.end);
+ }
+ return buffer;
+}
+
+std::vector<protozero::ContiguousMemoryRange> ScatteredHeapBuffer::GetRanges() {
+ std::vector<protozero::ContiguousMemoryRange> ranges;
+ for (const auto& slice : GetSlices())
+ ranges.push_back(slice.GetUsedRange());
+ return ranges;
+}
+
+void ScatteredHeapBuffer::AdjustUsedSizeOfCurrentSlice() {
+ if (!slices_.empty())
+ slices_.back().set_unused_bytes(writer_->bytes_available());
+}
+
+size_t ScatteredHeapBuffer::GetTotalSize() {
+ size_t total_size = 0;
+ for (auto& slice : slices_) {
+ total_size += slice.size();
+ }
+ return total_size;
+}
+
+void ScatteredHeapBuffer::Reset() {
+ if (slices_.empty())
+ return;
+ cached_slice_ = std::move(slices_.front());
+ cached_slice_.Clear();
+ slices_.clear();
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/scattered_stream_null_delegate.cc
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_null_delegate.h"
+
+namespace protozero {
+
+// An implementation of ScatteredStreamWriter::Delegate which always returns
+// the same piece of memory.
+// This is used when we need to no-op the writers (e.g. during teardown or in
+// case of resource exhaustion), avoiding that the clients have to deal with
+// nullptr checks.
+ScatteredStreamWriterNullDelegate::ScatteredStreamWriterNullDelegate(
+ size_t chunk_size)
+ : chunk_size_(chunk_size),
+ chunk_(std::unique_ptr<uint8_t[]>(new uint8_t[chunk_size_])) {}
+
+ScatteredStreamWriterNullDelegate::~ScatteredStreamWriterNullDelegate() {}
+
+ContiguousMemoryRange ScatteredStreamWriterNullDelegate::GetNewBuffer() {
+ return {chunk_.get(), chunk_.get() + chunk_size_};
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/scattered_stream_writer.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"
+
+#include <algorithm>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace protozero {
+
+ScatteredStreamWriter::Delegate::~Delegate() {}
+
+uint8_t* ScatteredStreamWriter::Delegate::AnnotatePatch(uint8_t* patch_addr) {
+ // In most cases, a patch is transparent. The caller can write directly into
+ // `to_patch`, because its memory is not going away. TraceWriterImpl, however,
+ // requires a more complicated logic, because the chunks might be copied
+ // earlier.
+ return patch_addr;
+}
+
+ScatteredStreamWriter::ScatteredStreamWriter(Delegate* delegate)
+ : delegate_(delegate),
+ cur_range_({nullptr, nullptr}),
+ write_ptr_(nullptr) {}
+
+ScatteredStreamWriter::~ScatteredStreamWriter() {}
+
+void ScatteredStreamWriter::Reset(ContiguousMemoryRange range) {
+ written_previously_ += static_cast<uint64_t>(write_ptr_ - cur_range_.begin);
+ cur_range_ = range;
+ write_ptr_ = range.begin;
+ PERFETTO_DCHECK(!write_ptr_ || write_ptr_ < cur_range_.end);
+}
+
+void ScatteredStreamWriter::Extend() {
+ Reset(delegate_->GetNewBuffer());
+}
+
+void ScatteredStreamWriter::WriteBytesSlowPath(const uint8_t* src,
+ size_t size) {
+ size_t bytes_left = size;
+ while (bytes_left > 0) {
+ if (write_ptr_ >= cur_range_.end)
+ Extend();
+ const size_t burst_size = std::min(bytes_available(), bytes_left);
+ WriteBytesUnsafe(src, burst_size);
+ bytes_left -= burst_size;
+ src += burst_size;
+ }
+}
+
+// TODO(primiano): perf optimization: I suspect that at the end this will always
+// be called with |size| == 4, in which case we might just hardcode it.
+uint8_t* ScatteredStreamWriter::ReserveBytes(size_t size) {
+ if (write_ptr_ + size > cur_range_.end) {
+ // Assume the reservations are always < Delegate::GetNewBuffer().size(),
+ // so that one single call to Extend() will definitely give enough headroom.
+ Extend();
+ PERFETTO_DCHECK(write_ptr_ + size <= cur_range_.end);
+ }
+ uint8_t* begin = write_ptr_;
+ write_ptr_ += size;
+#if PERFETTO_DCHECK_IS_ON()
+ // In the past, the service had a matching DCHECK in
+ // TraceBuffer::TryPatchChunkContents, which was assuming that service and all
+ // producers are built with matching DCHECK levels. This turned out to be a
+ // source of problems and was removed in b/197340286. This memset is useless
+ // these days and is here only to maintain ABI compatibility between producers
+ // that use a v20+ SDK and older versions of the service that were built in
+ // debug mode. At some point around 2023 it should be safe to remove it.
+ // (running a debug version of traced in production seems a bad idea
+ // regardless).
+ memset(begin, 0, size);
+#endif
+ return begin;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/static_buffer.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/static_buffer.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace protozero {
+
+StaticBufferDelegate::~StaticBufferDelegate() = default;
+
+ContiguousMemoryRange StaticBufferDelegate::GetNewBuffer() {
+ if (get_new_buffer_called_once_) {
+ // This is the 2nd time GetNewBuffer is called. The estimate is wrong. We
+ // shouldn't try to grow the buffer after the initial call.
+ PERFETTO_FATAL("Static buffer too small");
+ }
+ get_new_buffer_called_once_ = true;
+ return range_;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/virtual_destructors.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+
+namespace protozero {
+
+CppMessageObj::~CppMessageObj() = default;
+MessageFinalizationListener::~MessageFinalizationListener() = default;
+
+} // namespace protozero
+// gen_amalgamated begin source: gen/protos/perfetto/common/android_energy_consumer_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_energy_consumer_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidEnergyConsumerDescriptor::AndroidEnergyConsumerDescriptor() = default;
+AndroidEnergyConsumerDescriptor::~AndroidEnergyConsumerDescriptor() = default;
+AndroidEnergyConsumerDescriptor::AndroidEnergyConsumerDescriptor(const AndroidEnergyConsumerDescriptor&) = default;
+AndroidEnergyConsumerDescriptor& AndroidEnergyConsumerDescriptor::operator=(const AndroidEnergyConsumerDescriptor&) = default;
+AndroidEnergyConsumerDescriptor::AndroidEnergyConsumerDescriptor(AndroidEnergyConsumerDescriptor&&) noexcept = default;
+AndroidEnergyConsumerDescriptor& AndroidEnergyConsumerDescriptor::operator=(AndroidEnergyConsumerDescriptor&&) = default;
+
+bool AndroidEnergyConsumerDescriptor::operator==(const AndroidEnergyConsumerDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(energy_consumers_, other.energy_consumers_);
+}
+
+int AndroidEnergyConsumerDescriptor::energy_consumers_size() const { return static_cast<int>(energy_consumers_.size()); }
+void AndroidEnergyConsumerDescriptor::clear_energy_consumers() { energy_consumers_.clear(); }
+AndroidEnergyConsumer* AndroidEnergyConsumerDescriptor::add_energy_consumers() { energy_consumers_.emplace_back(); return &energy_consumers_.back(); }
+bool AndroidEnergyConsumerDescriptor::ParseFromArray(const void* raw, size_t size) {
+ energy_consumers_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* energy_consumers */:
+ energy_consumers_.emplace_back();
+ energy_consumers_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidEnergyConsumerDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidEnergyConsumerDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidEnergyConsumerDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: energy_consumers
+ for (auto& it : energy_consumers_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+AndroidEnergyConsumer::AndroidEnergyConsumer() = default;
+AndroidEnergyConsumer::~AndroidEnergyConsumer() = default;
+AndroidEnergyConsumer::AndroidEnergyConsumer(const AndroidEnergyConsumer&) = default;
+AndroidEnergyConsumer& AndroidEnergyConsumer::operator=(const AndroidEnergyConsumer&) = default;
+AndroidEnergyConsumer::AndroidEnergyConsumer(AndroidEnergyConsumer&&) noexcept = default;
+AndroidEnergyConsumer& AndroidEnergyConsumer::operator=(AndroidEnergyConsumer&&) = default;
+
+bool AndroidEnergyConsumer::operator==(const AndroidEnergyConsumer& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(energy_consumer_id_, other.energy_consumer_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(ordinal_, other.ordinal_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_, other.type_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool AndroidEnergyConsumer::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* energy_consumer_id */:
+ field.get(&energy_consumer_id_);
+ break;
+ case 2 /* ordinal */:
+ field.get(&ordinal_);
+ break;
+ case 3 /* type */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &type_);
+ break;
+ case 4 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidEnergyConsumer::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidEnergyConsumer::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidEnergyConsumer::Serialize(::protozero::Message* msg) const {
+ // Field 1: energy_consumer_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, energy_consumer_id_, msg);
+ }
+
+ // Field 2: ordinal
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, ordinal_, msg);
+ }
+
+ // Field 3: type
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, type_, msg);
+ }
+
+ // Field 4: name
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeString(4, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/android_log_constants.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_log_constants.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/builtin_clock.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/commit_data_request.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/commit_data_request.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+CommitDataRequest::CommitDataRequest() = default;
+CommitDataRequest::~CommitDataRequest() = default;
+CommitDataRequest::CommitDataRequest(const CommitDataRequest&) = default;
+CommitDataRequest& CommitDataRequest::operator=(const CommitDataRequest&) = default;
+CommitDataRequest::CommitDataRequest(CommitDataRequest&&) noexcept = default;
+CommitDataRequest& CommitDataRequest::operator=(CommitDataRequest&&) = default;
+
+bool CommitDataRequest::operator==(const CommitDataRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_to_move_, other.chunks_to_move_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_to_patch_, other.chunks_to_patch_)
+ && ::protozero::internal::gen_helpers::EqualsField(flush_request_id_, other.flush_request_id_);
+}
+
+int CommitDataRequest::chunks_to_move_size() const { return static_cast<int>(chunks_to_move_.size()); }
+void CommitDataRequest::clear_chunks_to_move() { chunks_to_move_.clear(); }
+CommitDataRequest_ChunksToMove* CommitDataRequest::add_chunks_to_move() { chunks_to_move_.emplace_back(); return &chunks_to_move_.back(); }
+int CommitDataRequest::chunks_to_patch_size() const { return static_cast<int>(chunks_to_patch_.size()); }
+void CommitDataRequest::clear_chunks_to_patch() { chunks_to_patch_.clear(); }
+CommitDataRequest_ChunkToPatch* CommitDataRequest::add_chunks_to_patch() { chunks_to_patch_.emplace_back(); return &chunks_to_patch_.back(); }
+bool CommitDataRequest::ParseFromArray(const void* raw, size_t size) {
+ chunks_to_move_.clear();
+ chunks_to_patch_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* chunks_to_move */:
+ chunks_to_move_.emplace_back();
+ chunks_to_move_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* chunks_to_patch */:
+ chunks_to_patch_.emplace_back();
+ chunks_to_patch_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* flush_request_id */:
+ field.get(&flush_request_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CommitDataRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CommitDataRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CommitDataRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: chunks_to_move
+ for (auto& it : chunks_to_move_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: chunks_to_patch
+ for (auto& it : chunks_to_patch_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 3: flush_request_id
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, flush_request_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+CommitDataRequest_ChunkToPatch::CommitDataRequest_ChunkToPatch() = default;
+CommitDataRequest_ChunkToPatch::~CommitDataRequest_ChunkToPatch() = default;
+CommitDataRequest_ChunkToPatch::CommitDataRequest_ChunkToPatch(const CommitDataRequest_ChunkToPatch&) = default;
+CommitDataRequest_ChunkToPatch& CommitDataRequest_ChunkToPatch::operator=(const CommitDataRequest_ChunkToPatch&) = default;
+CommitDataRequest_ChunkToPatch::CommitDataRequest_ChunkToPatch(CommitDataRequest_ChunkToPatch&&) noexcept = default;
+CommitDataRequest_ChunkToPatch& CommitDataRequest_ChunkToPatch::operator=(CommitDataRequest_ChunkToPatch&&) = default;
+
+bool CommitDataRequest_ChunkToPatch::operator==(const CommitDataRequest_ChunkToPatch& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_buffer_, other.target_buffer_)
+ && ::protozero::internal::gen_helpers::EqualsField(writer_id_, other.writer_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunk_id_, other.chunk_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(patches_, other.patches_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_more_patches_, other.has_more_patches_);
+}
+
+int CommitDataRequest_ChunkToPatch::patches_size() const { return static_cast<int>(patches_.size()); }
+void CommitDataRequest_ChunkToPatch::clear_patches() { patches_.clear(); }
+CommitDataRequest_ChunkToPatch_Patch* CommitDataRequest_ChunkToPatch::add_patches() { patches_.emplace_back(); return &patches_.back(); }
+bool CommitDataRequest_ChunkToPatch::ParseFromArray(const void* raw, size_t size) {
+ patches_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* target_buffer */:
+ field.get(&target_buffer_);
+ break;
+ case 2 /* writer_id */:
+ field.get(&writer_id_);
+ break;
+ case 3 /* chunk_id */:
+ field.get(&chunk_id_);
+ break;
+ case 4 /* patches */:
+ patches_.emplace_back();
+ patches_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* has_more_patches */:
+ field.get(&has_more_patches_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CommitDataRequest_ChunkToPatch::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CommitDataRequest_ChunkToPatch::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CommitDataRequest_ChunkToPatch::Serialize(::protozero::Message* msg) const {
+ // Field 1: target_buffer
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, target_buffer_, msg);
+ }
+
+ // Field 2: writer_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, writer_id_, msg);
+ }
+
+ // Field 3: chunk_id
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, chunk_id_, msg);
+ }
+
+ // Field 4: patches
+ for (auto& it : patches_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: has_more_patches
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, has_more_patches_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+CommitDataRequest_ChunkToPatch_Patch::CommitDataRequest_ChunkToPatch_Patch() = default;
+CommitDataRequest_ChunkToPatch_Patch::~CommitDataRequest_ChunkToPatch_Patch() = default;
+CommitDataRequest_ChunkToPatch_Patch::CommitDataRequest_ChunkToPatch_Patch(const CommitDataRequest_ChunkToPatch_Patch&) = default;
+CommitDataRequest_ChunkToPatch_Patch& CommitDataRequest_ChunkToPatch_Patch::operator=(const CommitDataRequest_ChunkToPatch_Patch&) = default;
+CommitDataRequest_ChunkToPatch_Patch::CommitDataRequest_ChunkToPatch_Patch(CommitDataRequest_ChunkToPatch_Patch&&) noexcept = default;
+CommitDataRequest_ChunkToPatch_Patch& CommitDataRequest_ChunkToPatch_Patch::operator=(CommitDataRequest_ChunkToPatch_Patch&&) = default;
+
+bool CommitDataRequest_ChunkToPatch_Patch::operator==(const CommitDataRequest_ChunkToPatch_Patch& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(offset_, other.offset_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_, other.data_);
+}
+
+bool CommitDataRequest_ChunkToPatch_Patch::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* offset */:
+ field.get(&offset_);
+ break;
+ case 2 /* data */:
+ field.get(&data_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CommitDataRequest_ChunkToPatch_Patch::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CommitDataRequest_ChunkToPatch_Patch::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CommitDataRequest_ChunkToPatch_Patch::Serialize(::protozero::Message* msg) const {
+ // Field 1: offset
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, offset_, msg);
+ }
+
+ // Field 2: data
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, data_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+CommitDataRequest_ChunksToMove::CommitDataRequest_ChunksToMove() = default;
+CommitDataRequest_ChunksToMove::~CommitDataRequest_ChunksToMove() = default;
+CommitDataRequest_ChunksToMove::CommitDataRequest_ChunksToMove(const CommitDataRequest_ChunksToMove&) = default;
+CommitDataRequest_ChunksToMove& CommitDataRequest_ChunksToMove::operator=(const CommitDataRequest_ChunksToMove&) = default;
+CommitDataRequest_ChunksToMove::CommitDataRequest_ChunksToMove(CommitDataRequest_ChunksToMove&&) noexcept = default;
+CommitDataRequest_ChunksToMove& CommitDataRequest_ChunksToMove::operator=(CommitDataRequest_ChunksToMove&&) = default;
+
+bool CommitDataRequest_ChunksToMove::operator==(const CommitDataRequest_ChunksToMove& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(page_, other.page_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunk_, other.chunk_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_buffer_, other.target_buffer_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_, other.data_);
+}
+
+bool CommitDataRequest_ChunksToMove::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* page */:
+ field.get(&page_);
+ break;
+ case 2 /* chunk */:
+ field.get(&chunk_);
+ break;
+ case 3 /* target_buffer */:
+ field.get(&target_buffer_);
+ break;
+ case 4 /* data */:
+ field.get(&data_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CommitDataRequest_ChunksToMove::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CommitDataRequest_ChunksToMove::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CommitDataRequest_ChunksToMove::Serialize(::protozero::Message* msg) const {
+ // Field 1: page
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, page_, msg);
+ }
+
+ // Field 2: chunk
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, chunk_, msg);
+ }
+
+ // Field 3: target_buffer
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, target_buffer_, msg);
+ }
+
+ // Field 4: data
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeString(4, data_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/data_source_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+DataSourceDescriptor::DataSourceDescriptor() = default;
+DataSourceDescriptor::~DataSourceDescriptor() = default;
+DataSourceDescriptor::DataSourceDescriptor(const DataSourceDescriptor&) = default;
+DataSourceDescriptor& DataSourceDescriptor::operator=(const DataSourceDescriptor&) = default;
+DataSourceDescriptor::DataSourceDescriptor(DataSourceDescriptor&&) noexcept = default;
+DataSourceDescriptor& DataSourceDescriptor::operator=(DataSourceDescriptor&&) = default;
+
+bool DataSourceDescriptor::operator==(const DataSourceDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(id_, other.id_)
+ && ::protozero::internal::gen_helpers::EqualsField(will_notify_on_stop_, other.will_notify_on_stop_)
+ && ::protozero::internal::gen_helpers::EqualsField(will_notify_on_start_, other.will_notify_on_start_)
+ && ::protozero::internal::gen_helpers::EqualsField(handles_incremental_state_clear_, other.handles_incremental_state_clear_)
+ && ::protozero::internal::gen_helpers::EqualsField(no_flush_, other.no_flush_)
+ && ::protozero::internal::gen_helpers::EqualsField(gpu_counter_descriptor_, other.gpu_counter_descriptor_)
+ && ::protozero::internal::gen_helpers::EqualsField(track_event_descriptor_, other.track_event_descriptor_)
+ && ::protozero::internal::gen_helpers::EqualsField(ftrace_descriptor_, other.ftrace_descriptor_);
+}
+
+bool DataSourceDescriptor::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 7 /* id */:
+ field.get(&id_);
+ break;
+ case 2 /* will_notify_on_stop */:
+ field.get(&will_notify_on_stop_);
+ break;
+ case 3 /* will_notify_on_start */:
+ field.get(&will_notify_on_start_);
+ break;
+ case 4 /* handles_incremental_state_clear */:
+ field.get(&handles_incremental_state_clear_);
+ break;
+ case 9 /* no_flush */:
+ field.get(&no_flush_);
+ break;
+ case 5 /* gpu_counter_descriptor */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &gpu_counter_descriptor_);
+ break;
+ case 6 /* track_event_descriptor */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &track_event_descriptor_);
+ break;
+ case 8 /* ftrace_descriptor */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &ftrace_descriptor_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DataSourceDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DataSourceDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DataSourceDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 7: id
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, id_, msg);
+ }
+
+ // Field 2: will_notify_on_stop
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, will_notify_on_stop_, msg);
+ }
+
+ // Field 3: will_notify_on_start
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, will_notify_on_start_, msg);
+ }
+
+ // Field 4: handles_incremental_state_clear
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, handles_incremental_state_clear_, msg);
+ }
+
+ // Field 9: no_flush
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, no_flush_, msg);
+ }
+
+ // Field 5: gpu_counter_descriptor
+ if (_has_field_[5]) {
+ msg->AppendString(5, gpu_counter_descriptor_);
+ }
+
+ // Field 6: track_event_descriptor
+ if (_has_field_[6]) {
+ msg->AppendString(6, track_event_descriptor_);
+ }
+
+ // Field 8: ftrace_descriptor
+ if (_has_field_[8]) {
+ msg->AppendString(8, ftrace_descriptor_);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+OneofOptions::OneofOptions() = default;
+OneofOptions::~OneofOptions() = default;
+OneofOptions::OneofOptions(const OneofOptions&) = default;
+OneofOptions& OneofOptions::operator=(const OneofOptions&) = default;
+OneofOptions::OneofOptions(OneofOptions&&) noexcept = default;
+OneofOptions& OneofOptions::operator=(OneofOptions&&) = default;
+
+bool OneofOptions::operator==(const OneofOptions& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool OneofOptions::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string OneofOptions::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> OneofOptions::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void OneofOptions::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+EnumValueDescriptorProto::EnumValueDescriptorProto() = default;
+EnumValueDescriptorProto::~EnumValueDescriptorProto() = default;
+EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto&) = default;
+EnumValueDescriptorProto& EnumValueDescriptorProto::operator=(const EnumValueDescriptorProto&) = default;
+EnumValueDescriptorProto::EnumValueDescriptorProto(EnumValueDescriptorProto&&) noexcept = default;
+EnumValueDescriptorProto& EnumValueDescriptorProto::operator=(EnumValueDescriptorProto&&) = default;
+
+bool EnumValueDescriptorProto::operator==(const EnumValueDescriptorProto& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(number_, other.number_);
+}
+
+bool EnumValueDescriptorProto::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* number */:
+ field.get(&number_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string EnumValueDescriptorProto::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> EnumValueDescriptorProto::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void EnumValueDescriptorProto::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: number
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, number_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+EnumDescriptorProto::EnumDescriptorProto() = default;
+EnumDescriptorProto::~EnumDescriptorProto() = default;
+EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto&) = default;
+EnumDescriptorProto& EnumDescriptorProto::operator=(const EnumDescriptorProto&) = default;
+EnumDescriptorProto::EnumDescriptorProto(EnumDescriptorProto&&) noexcept = default;
+EnumDescriptorProto& EnumDescriptorProto::operator=(EnumDescriptorProto&&) = default;
+
+bool EnumDescriptorProto::operator==(const EnumDescriptorProto& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(value_, other.value_)
+ && ::protozero::internal::gen_helpers::EqualsField(reserved_name_, other.reserved_name_);
+}
+
+int EnumDescriptorProto::value_size() const { return static_cast<int>(value_.size()); }
+void EnumDescriptorProto::clear_value() { value_.clear(); }
+EnumValueDescriptorProto* EnumDescriptorProto::add_value() { value_.emplace_back(); return &value_.back(); }
+bool EnumDescriptorProto::ParseFromArray(const void* raw, size_t size) {
+ value_.clear();
+ reserved_name_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* value */:
+ value_.emplace_back();
+ value_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* reserved_name */:
+ reserved_name_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &reserved_name_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string EnumDescriptorProto::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> EnumDescriptorProto::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void EnumDescriptorProto::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: value
+ for (auto& it : value_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 5: reserved_name
+ for (auto& it : reserved_name_) {
+ ::protozero::internal::gen_helpers::SerializeString(5, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+OneofDescriptorProto::OneofDescriptorProto() = default;
+OneofDescriptorProto::~OneofDescriptorProto() = default;
+OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto&) = default;
+OneofDescriptorProto& OneofDescriptorProto::operator=(const OneofDescriptorProto&) = default;
+OneofDescriptorProto::OneofDescriptorProto(OneofDescriptorProto&&) noexcept = default;
+OneofDescriptorProto& OneofDescriptorProto::operator=(OneofDescriptorProto&&) = default;
+
+bool OneofDescriptorProto::operator==(const OneofDescriptorProto& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(options_, other.options_);
+}
+
+bool OneofDescriptorProto::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* options */:
+ (*options_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string OneofDescriptorProto::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> OneofDescriptorProto::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void OneofDescriptorProto::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: options
+ if (_has_field_[2]) {
+ (*options_).Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FieldDescriptorProto::FieldDescriptorProto() = default;
+FieldDescriptorProto::~FieldDescriptorProto() = default;
+FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto&) = default;
+FieldDescriptorProto& FieldDescriptorProto::operator=(const FieldDescriptorProto&) = default;
+FieldDescriptorProto::FieldDescriptorProto(FieldDescriptorProto&&) noexcept = default;
+FieldDescriptorProto& FieldDescriptorProto::operator=(FieldDescriptorProto&&) = default;
+
+bool FieldDescriptorProto::operator==(const FieldDescriptorProto& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(number_, other.number_)
+ && ::protozero::internal::gen_helpers::EqualsField(label_, other.label_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_, other.type_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_name_, other.type_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(extendee_, other.extendee_)
+ && ::protozero::internal::gen_helpers::EqualsField(default_value_, other.default_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(options_, other.options_)
+ && ::protozero::internal::gen_helpers::EqualsField(oneof_index_, other.oneof_index_);
+}
+
+bool FieldDescriptorProto::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 3 /* number */:
+ field.get(&number_);
+ break;
+ case 4 /* label */:
+ field.get(&label_);
+ break;
+ case 5 /* type */:
+ field.get(&type_);
+ break;
+ case 6 /* type_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &type_name_);
+ break;
+ case 2 /* extendee */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &extendee_);
+ break;
+ case 7 /* default_value */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &default_value_);
+ break;
+ case 8 /* options */:
+ (*options_).ParseFromArray(field.data(), field.size());
+ break;
+ case 9 /* oneof_index */:
+ field.get(&oneof_index_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FieldDescriptorProto::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FieldDescriptorProto::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FieldDescriptorProto::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 3: number
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, number_, msg);
+ }
+
+ // Field 4: label
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, label_, msg);
+ }
+
+ // Field 5: type
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, type_, msg);
+ }
+
+ // Field 6: type_name
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeString(6, type_name_, msg);
+ }
+
+ // Field 2: extendee
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, extendee_, msg);
+ }
+
+ // Field 7: default_value
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeString(7, default_value_, msg);
+ }
+
+ // Field 8: options
+ if (_has_field_[8]) {
+ (*options_).Serialize(msg->BeginNestedMessage<::protozero::Message>(8));
+ }
+
+ // Field 9: oneof_index
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, oneof_index_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FieldOptions::FieldOptions() = default;
+FieldOptions::~FieldOptions() = default;
+FieldOptions::FieldOptions(const FieldOptions&) = default;
+FieldOptions& FieldOptions::operator=(const FieldOptions&) = default;
+FieldOptions::FieldOptions(FieldOptions&&) noexcept = default;
+FieldOptions& FieldOptions::operator=(FieldOptions&&) = default;
+
+bool FieldOptions::operator==(const FieldOptions& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(packed_, other.packed_)
+ && ::protozero::internal::gen_helpers::EqualsField(uninterpreted_option_, other.uninterpreted_option_);
+}
+
+int FieldOptions::uninterpreted_option_size() const { return static_cast<int>(uninterpreted_option_.size()); }
+void FieldOptions::clear_uninterpreted_option() { uninterpreted_option_.clear(); }
+UninterpretedOption* FieldOptions::add_uninterpreted_option() { uninterpreted_option_.emplace_back(); return &uninterpreted_option_.back(); }
+bool FieldOptions::ParseFromArray(const void* raw, size_t size) {
+ uninterpreted_option_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 2 /* packed */:
+ field.get(&packed_);
+ break;
+ case 999 /* uninterpreted_option */:
+ uninterpreted_option_.emplace_back();
+ uninterpreted_option_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FieldOptions::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FieldOptions::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FieldOptions::Serialize(::protozero::Message* msg) const {
+ // Field 2: packed
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, packed_, msg);
+ }
+
+ // Field 999: uninterpreted_option
+ for (auto& it : uninterpreted_option_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(999));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UninterpretedOption::UninterpretedOption() = default;
+UninterpretedOption::~UninterpretedOption() = default;
+UninterpretedOption::UninterpretedOption(const UninterpretedOption&) = default;
+UninterpretedOption& UninterpretedOption::operator=(const UninterpretedOption&) = default;
+UninterpretedOption::UninterpretedOption(UninterpretedOption&&) noexcept = default;
+UninterpretedOption& UninterpretedOption::operator=(UninterpretedOption&&) = default;
+
+bool UninterpretedOption::operator==(const UninterpretedOption& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(identifier_value_, other.identifier_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(positive_int_value_, other.positive_int_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(negative_int_value_, other.negative_int_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(double_value_, other.double_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(string_value_, other.string_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(aggregate_value_, other.aggregate_value_);
+}
+
+int UninterpretedOption::name_size() const { return static_cast<int>(name_.size()); }
+void UninterpretedOption::clear_name() { name_.clear(); }
+UninterpretedOption_NamePart* UninterpretedOption::add_name() { name_.emplace_back(); return &name_.back(); }
+bool UninterpretedOption::ParseFromArray(const void* raw, size_t size) {
+ name_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 2 /* name */:
+ name_.emplace_back();
+ name_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* identifier_value */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &identifier_value_);
+ break;
+ case 4 /* positive_int_value */:
+ field.get(&positive_int_value_);
+ break;
+ case 5 /* negative_int_value */:
+ field.get(&negative_int_value_);
+ break;
+ case 6 /* double_value */:
+ field.get(&double_value_);
+ break;
+ case 7 /* string_value */:
+ field.get(&string_value_);
+ break;
+ case 8 /* aggregate_value */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &aggregate_value_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UninterpretedOption::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UninterpretedOption::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UninterpretedOption::Serialize(::protozero::Message* msg) const {
+ // Field 2: name
+ for (auto& it : name_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 3: identifier_value
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, identifier_value_, msg);
+ }
+
+ // Field 4: positive_int_value
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, positive_int_value_, msg);
+ }
+
+ // Field 5: negative_int_value
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, negative_int_value_, msg);
+ }
+
+ // Field 6: double_value
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(6, double_value_, msg);
+ }
+
+ // Field 7: string_value
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeString(7, string_value_, msg);
+ }
+
+ // Field 8: aggregate_value
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeString(8, aggregate_value_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UninterpretedOption_NamePart::UninterpretedOption_NamePart() = default;
+UninterpretedOption_NamePart::~UninterpretedOption_NamePart() = default;
+UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart&) = default;
+UninterpretedOption_NamePart& UninterpretedOption_NamePart::operator=(const UninterpretedOption_NamePart&) = default;
+UninterpretedOption_NamePart::UninterpretedOption_NamePart(UninterpretedOption_NamePart&&) noexcept = default;
+UninterpretedOption_NamePart& UninterpretedOption_NamePart::operator=(UninterpretedOption_NamePart&&) = default;
+
+bool UninterpretedOption_NamePart::operator==(const UninterpretedOption_NamePart& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_part_, other.name_part_)
+ && ::protozero::internal::gen_helpers::EqualsField(is_extension_, other.is_extension_);
+}
+
+bool UninterpretedOption_NamePart::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name_part */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_part_);
+ break;
+ case 2 /* is_extension */:
+ field.get(&is_extension_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UninterpretedOption_NamePart::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UninterpretedOption_NamePart::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UninterpretedOption_NamePart::Serialize(::protozero::Message* msg) const {
+ // Field 1: name_part
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_part_, msg);
+ }
+
+ // Field 2: is_extension
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, is_extension_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DescriptorProto::DescriptorProto() = default;
+DescriptorProto::~DescriptorProto() = default;
+DescriptorProto::DescriptorProto(const DescriptorProto&) = default;
+DescriptorProto& DescriptorProto::operator=(const DescriptorProto&) = default;
+DescriptorProto::DescriptorProto(DescriptorProto&&) noexcept = default;
+DescriptorProto& DescriptorProto::operator=(DescriptorProto&&) = default;
+
+bool DescriptorProto::operator==(const DescriptorProto& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_, other.field_)
+ && ::protozero::internal::gen_helpers::EqualsField(extension_, other.extension_)
+ && ::protozero::internal::gen_helpers::EqualsField(nested_type_, other.nested_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(enum_type_, other.enum_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(oneof_decl_, other.oneof_decl_)
+ && ::protozero::internal::gen_helpers::EqualsField(reserved_range_, other.reserved_range_)
+ && ::protozero::internal::gen_helpers::EqualsField(reserved_name_, other.reserved_name_);
+}
+
+int DescriptorProto::field_size() const { return static_cast<int>(field_.size()); }
+void DescriptorProto::clear_field() { field_.clear(); }
+FieldDescriptorProto* DescriptorProto::add_field() { field_.emplace_back(); return &field_.back(); }
+int DescriptorProto::extension_size() const { return static_cast<int>(extension_.size()); }
+void DescriptorProto::clear_extension() { extension_.clear(); }
+FieldDescriptorProto* DescriptorProto::add_extension() { extension_.emplace_back(); return &extension_.back(); }
+int DescriptorProto::nested_type_size() const { return static_cast<int>(nested_type_.size()); }
+void DescriptorProto::clear_nested_type() { nested_type_.clear(); }
+DescriptorProto* DescriptorProto::add_nested_type() { nested_type_.emplace_back(); return &nested_type_.back(); }
+int DescriptorProto::enum_type_size() const { return static_cast<int>(enum_type_.size()); }
+void DescriptorProto::clear_enum_type() { enum_type_.clear(); }
+EnumDescriptorProto* DescriptorProto::add_enum_type() { enum_type_.emplace_back(); return &enum_type_.back(); }
+int DescriptorProto::oneof_decl_size() const { return static_cast<int>(oneof_decl_.size()); }
+void DescriptorProto::clear_oneof_decl() { oneof_decl_.clear(); }
+OneofDescriptorProto* DescriptorProto::add_oneof_decl() { oneof_decl_.emplace_back(); return &oneof_decl_.back(); }
+int DescriptorProto::reserved_range_size() const { return static_cast<int>(reserved_range_.size()); }
+void DescriptorProto::clear_reserved_range() { reserved_range_.clear(); }
+DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() { reserved_range_.emplace_back(); return &reserved_range_.back(); }
+bool DescriptorProto::ParseFromArray(const void* raw, size_t size) {
+ field_.clear();
+ extension_.clear();
+ nested_type_.clear();
+ enum_type_.clear();
+ oneof_decl_.clear();
+ reserved_range_.clear();
+ reserved_name_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* field */:
+ field_.emplace_back();
+ field_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* extension */:
+ extension_.emplace_back();
+ extension_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* nested_type */:
+ nested_type_.emplace_back();
+ nested_type_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 4 /* enum_type */:
+ enum_type_.emplace_back();
+ enum_type_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 8 /* oneof_decl */:
+ oneof_decl_.emplace_back();
+ oneof_decl_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 9 /* reserved_range */:
+ reserved_range_.emplace_back();
+ reserved_range_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 10 /* reserved_name */:
+ reserved_name_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &reserved_name_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DescriptorProto::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DescriptorProto::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DescriptorProto::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: field
+ for (auto& it : field_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 6: extension
+ for (auto& it : extension_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 3: nested_type
+ for (auto& it : nested_type_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 4: enum_type
+ for (auto& it : enum_type_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 8: oneof_decl
+ for (auto& it : oneof_decl_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(8));
+ }
+
+ // Field 9: reserved_range
+ for (auto& it : reserved_range_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(9));
+ }
+
+ // Field 10: reserved_name
+ for (auto& it : reserved_name_) {
+ ::protozero::internal::gen_helpers::SerializeString(10, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange() = default;
+DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() = default;
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange&) = default;
+DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::operator=(const DescriptorProto_ReservedRange&) = default;
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&&) noexcept = default;
+DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::operator=(DescriptorProto_ReservedRange&&) = default;
+
+bool DescriptorProto_ReservedRange::operator==(const DescriptorProto_ReservedRange& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(start_, other.start_)
+ && ::protozero::internal::gen_helpers::EqualsField(end_, other.end_);
+}
+
+bool DescriptorProto_ReservedRange::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* start */:
+ field.get(&start_);
+ break;
+ case 2 /* end */:
+ field.get(&end_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DescriptorProto_ReservedRange::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DescriptorProto_ReservedRange::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DescriptorProto_ReservedRange::Serialize(::protozero::Message* msg) const {
+ // Field 1: start
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, start_, msg);
+ }
+
+ // Field 2: end
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, end_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FileDescriptorProto::FileDescriptorProto() = default;
+FileDescriptorProto::~FileDescriptorProto() = default;
+FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto&) = default;
+FileDescriptorProto& FileDescriptorProto::operator=(const FileDescriptorProto&) = default;
+FileDescriptorProto::FileDescriptorProto(FileDescriptorProto&&) noexcept = default;
+FileDescriptorProto& FileDescriptorProto::operator=(FileDescriptorProto&&) = default;
+
+bool FileDescriptorProto::operator==(const FileDescriptorProto& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(package_, other.package_)
+ && ::protozero::internal::gen_helpers::EqualsField(dependency_, other.dependency_)
+ && ::protozero::internal::gen_helpers::EqualsField(public_dependency_, other.public_dependency_)
+ && ::protozero::internal::gen_helpers::EqualsField(weak_dependency_, other.weak_dependency_)
+ && ::protozero::internal::gen_helpers::EqualsField(message_type_, other.message_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(enum_type_, other.enum_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(extension_, other.extension_);
+}
+
+int FileDescriptorProto::message_type_size() const { return static_cast<int>(message_type_.size()); }
+void FileDescriptorProto::clear_message_type() { message_type_.clear(); }
+DescriptorProto* FileDescriptorProto::add_message_type() { message_type_.emplace_back(); return &message_type_.back(); }
+int FileDescriptorProto::enum_type_size() const { return static_cast<int>(enum_type_.size()); }
+void FileDescriptorProto::clear_enum_type() { enum_type_.clear(); }
+EnumDescriptorProto* FileDescriptorProto::add_enum_type() { enum_type_.emplace_back(); return &enum_type_.back(); }
+int FileDescriptorProto::extension_size() const { return static_cast<int>(extension_.size()); }
+void FileDescriptorProto::clear_extension() { extension_.clear(); }
+FieldDescriptorProto* FileDescriptorProto::add_extension() { extension_.emplace_back(); return &extension_.back(); }
+bool FileDescriptorProto::ParseFromArray(const void* raw, size_t size) {
+ dependency_.clear();
+ public_dependency_.clear();
+ weak_dependency_.clear();
+ message_type_.clear();
+ enum_type_.clear();
+ extension_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* package */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &package_);
+ break;
+ case 3 /* dependency */:
+ dependency_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &dependency_.back());
+ break;
+ case 10 /* public_dependency */:
+ public_dependency_.emplace_back();
+ field.get(&public_dependency_.back());
+ break;
+ case 11 /* weak_dependency */:
+ weak_dependency_.emplace_back();
+ field.get(&weak_dependency_.back());
+ break;
+ case 4 /* message_type */:
+ message_type_.emplace_back();
+ message_type_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* enum_type */:
+ enum_type_.emplace_back();
+ enum_type_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 7 /* extension */:
+ extension_.emplace_back();
+ extension_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FileDescriptorProto::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FileDescriptorProto::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FileDescriptorProto::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: package
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, package_, msg);
+ }
+
+ // Field 3: dependency
+ for (auto& it : dependency_) {
+ ::protozero::internal::gen_helpers::SerializeString(3, it, msg);
+ }
+
+ // Field 10: public_dependency
+ for (auto& it : public_dependency_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, it, msg);
+ }
+
+ // Field 11: weak_dependency
+ for (auto& it : weak_dependency_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, it, msg);
+ }
+
+ // Field 4: message_type
+ for (auto& it : message_type_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: enum_type
+ for (auto& it : enum_type_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 7: extension
+ for (auto& it : extension_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(7));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FileDescriptorSet::FileDescriptorSet() = default;
+FileDescriptorSet::~FileDescriptorSet() = default;
+FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet&) = default;
+FileDescriptorSet& FileDescriptorSet::operator=(const FileDescriptorSet&) = default;
+FileDescriptorSet::FileDescriptorSet(FileDescriptorSet&&) noexcept = default;
+FileDescriptorSet& FileDescriptorSet::operator=(FileDescriptorSet&&) = default;
+
+bool FileDescriptorSet::operator==(const FileDescriptorSet& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(file_, other.file_);
+}
+
+int FileDescriptorSet::file_size() const { return static_cast<int>(file_.size()); }
+void FileDescriptorSet::clear_file() { file_.clear(); }
+FileDescriptorProto* FileDescriptorSet::add_file() { file_.emplace_back(); return &file_.back(); }
+bool FileDescriptorSet::ParseFromArray(const void* raw, size_t size) {
+ file_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* file */:
+ file_.emplace_back();
+ file_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FileDescriptorSet::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FileDescriptorSet::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FileDescriptorSet::Serialize(::protozero::Message* msg) const {
+ // Field 1: file
+ for (auto& it : file_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/ftrace_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/ftrace_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+FtraceDescriptor::FtraceDescriptor() = default;
+FtraceDescriptor::~FtraceDescriptor() = default;
+FtraceDescriptor::FtraceDescriptor(const FtraceDescriptor&) = default;
+FtraceDescriptor& FtraceDescriptor::operator=(const FtraceDescriptor&) = default;
+FtraceDescriptor::FtraceDescriptor(FtraceDescriptor&&) noexcept = default;
+FtraceDescriptor& FtraceDescriptor::operator=(FtraceDescriptor&&) = default;
+
+bool FtraceDescriptor::operator==(const FtraceDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(atrace_categories_, other.atrace_categories_);
+}
+
+int FtraceDescriptor::atrace_categories_size() const { return static_cast<int>(atrace_categories_.size()); }
+void FtraceDescriptor::clear_atrace_categories() { atrace_categories_.clear(); }
+FtraceDescriptor_AtraceCategory* FtraceDescriptor::add_atrace_categories() { atrace_categories_.emplace_back(); return &atrace_categories_.back(); }
+bool FtraceDescriptor::ParseFromArray(const void* raw, size_t size) {
+ atrace_categories_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* atrace_categories */:
+ atrace_categories_.emplace_back();
+ atrace_categories_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FtraceDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FtraceDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FtraceDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: atrace_categories
+ for (auto& it : atrace_categories_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FtraceDescriptor_AtraceCategory::FtraceDescriptor_AtraceCategory() = default;
+FtraceDescriptor_AtraceCategory::~FtraceDescriptor_AtraceCategory() = default;
+FtraceDescriptor_AtraceCategory::FtraceDescriptor_AtraceCategory(const FtraceDescriptor_AtraceCategory&) = default;
+FtraceDescriptor_AtraceCategory& FtraceDescriptor_AtraceCategory::operator=(const FtraceDescriptor_AtraceCategory&) = default;
+FtraceDescriptor_AtraceCategory::FtraceDescriptor_AtraceCategory(FtraceDescriptor_AtraceCategory&&) noexcept = default;
+FtraceDescriptor_AtraceCategory& FtraceDescriptor_AtraceCategory::operator=(FtraceDescriptor_AtraceCategory&&) = default;
+
+bool FtraceDescriptor_AtraceCategory::operator==(const FtraceDescriptor_AtraceCategory& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(description_, other.description_);
+}
+
+bool FtraceDescriptor_AtraceCategory::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* description */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &description_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FtraceDescriptor_AtraceCategory::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FtraceDescriptor_AtraceCategory::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FtraceDescriptor_AtraceCategory::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: description
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, description_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/gpu_counter_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/gpu_counter_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+GpuCounterDescriptor::GpuCounterDescriptor() = default;
+GpuCounterDescriptor::~GpuCounterDescriptor() = default;
+GpuCounterDescriptor::GpuCounterDescriptor(const GpuCounterDescriptor&) = default;
+GpuCounterDescriptor& GpuCounterDescriptor::operator=(const GpuCounterDescriptor&) = default;
+GpuCounterDescriptor::GpuCounterDescriptor(GpuCounterDescriptor&&) noexcept = default;
+GpuCounterDescriptor& GpuCounterDescriptor::operator=(GpuCounterDescriptor&&) = default;
+
+bool GpuCounterDescriptor::operator==(const GpuCounterDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(specs_, other.specs_)
+ && ::protozero::internal::gen_helpers::EqualsField(blocks_, other.blocks_)
+ && ::protozero::internal::gen_helpers::EqualsField(min_sampling_period_ns_, other.min_sampling_period_ns_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_sampling_period_ns_, other.max_sampling_period_ns_)
+ && ::protozero::internal::gen_helpers::EqualsField(supports_instrumented_sampling_, other.supports_instrumented_sampling_);
+}
+
+int GpuCounterDescriptor::specs_size() const { return static_cast<int>(specs_.size()); }
+void GpuCounterDescriptor::clear_specs() { specs_.clear(); }
+GpuCounterDescriptor_GpuCounterSpec* GpuCounterDescriptor::add_specs() { specs_.emplace_back(); return &specs_.back(); }
+int GpuCounterDescriptor::blocks_size() const { return static_cast<int>(blocks_.size()); }
+void GpuCounterDescriptor::clear_blocks() { blocks_.clear(); }
+GpuCounterDescriptor_GpuCounterBlock* GpuCounterDescriptor::add_blocks() { blocks_.emplace_back(); return &blocks_.back(); }
+bool GpuCounterDescriptor::ParseFromArray(const void* raw, size_t size) {
+ specs_.clear();
+ blocks_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* specs */:
+ specs_.emplace_back();
+ specs_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* blocks */:
+ blocks_.emplace_back();
+ blocks_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* min_sampling_period_ns */:
+ field.get(&min_sampling_period_ns_);
+ break;
+ case 4 /* max_sampling_period_ns */:
+ field.get(&max_sampling_period_ns_);
+ break;
+ case 5 /* supports_instrumented_sampling */:
+ field.get(&supports_instrumented_sampling_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GpuCounterDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GpuCounterDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GpuCounterDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: specs
+ for (auto& it : specs_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: blocks
+ for (auto& it : blocks_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 3: min_sampling_period_ns
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, min_sampling_period_ns_, msg);
+ }
+
+ // Field 4: max_sampling_period_ns
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, max_sampling_period_ns_, msg);
+ }
+
+ // Field 5: supports_instrumented_sampling
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, supports_instrumented_sampling_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GpuCounterDescriptor_GpuCounterBlock::GpuCounterDescriptor_GpuCounterBlock() = default;
+GpuCounterDescriptor_GpuCounterBlock::~GpuCounterDescriptor_GpuCounterBlock() = default;
+GpuCounterDescriptor_GpuCounterBlock::GpuCounterDescriptor_GpuCounterBlock(const GpuCounterDescriptor_GpuCounterBlock&) = default;
+GpuCounterDescriptor_GpuCounterBlock& GpuCounterDescriptor_GpuCounterBlock::operator=(const GpuCounterDescriptor_GpuCounterBlock&) = default;
+GpuCounterDescriptor_GpuCounterBlock::GpuCounterDescriptor_GpuCounterBlock(GpuCounterDescriptor_GpuCounterBlock&&) noexcept = default;
+GpuCounterDescriptor_GpuCounterBlock& GpuCounterDescriptor_GpuCounterBlock::operator=(GpuCounterDescriptor_GpuCounterBlock&&) = default;
+
+bool GpuCounterDescriptor_GpuCounterBlock::operator==(const GpuCounterDescriptor_GpuCounterBlock& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(block_id_, other.block_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(block_capacity_, other.block_capacity_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(description_, other.description_)
+ && ::protozero::internal::gen_helpers::EqualsField(counter_ids_, other.counter_ids_);
+}
+
+bool GpuCounterDescriptor_GpuCounterBlock::ParseFromArray(const void* raw, size_t size) {
+ counter_ids_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* block_id */:
+ field.get(&block_id_);
+ break;
+ case 2 /* block_capacity */:
+ field.get(&block_capacity_);
+ break;
+ case 3 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 4 /* description */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &description_);
+ break;
+ case 5 /* counter_ids */:
+ counter_ids_.emplace_back();
+ field.get(&counter_ids_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GpuCounterDescriptor_GpuCounterBlock::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GpuCounterDescriptor_GpuCounterBlock::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GpuCounterDescriptor_GpuCounterBlock::Serialize(::protozero::Message* msg) const {
+ // Field 1: block_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, block_id_, msg);
+ }
+
+ // Field 2: block_capacity
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, block_capacity_, msg);
+ }
+
+ // Field 3: name
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, name_, msg);
+ }
+
+ // Field 4: description
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeString(4, description_, msg);
+ }
+
+ // Field 5: counter_ids
+ for (auto& it : counter_ids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GpuCounterDescriptor_GpuCounterSpec::GpuCounterDescriptor_GpuCounterSpec() = default;
+GpuCounterDescriptor_GpuCounterSpec::~GpuCounterDescriptor_GpuCounterSpec() = default;
+GpuCounterDescriptor_GpuCounterSpec::GpuCounterDescriptor_GpuCounterSpec(const GpuCounterDescriptor_GpuCounterSpec&) = default;
+GpuCounterDescriptor_GpuCounterSpec& GpuCounterDescriptor_GpuCounterSpec::operator=(const GpuCounterDescriptor_GpuCounterSpec&) = default;
+GpuCounterDescriptor_GpuCounterSpec::GpuCounterDescriptor_GpuCounterSpec(GpuCounterDescriptor_GpuCounterSpec&&) noexcept = default;
+GpuCounterDescriptor_GpuCounterSpec& GpuCounterDescriptor_GpuCounterSpec::operator=(GpuCounterDescriptor_GpuCounterSpec&&) = default;
+
+bool GpuCounterDescriptor_GpuCounterSpec::operator==(const GpuCounterDescriptor_GpuCounterSpec& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(counter_id_, other.counter_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(description_, other.description_)
+ && ::protozero::internal::gen_helpers::EqualsField(int_peak_value_, other.int_peak_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(double_peak_value_, other.double_peak_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(numerator_units_, other.numerator_units_)
+ && ::protozero::internal::gen_helpers::EqualsField(denominator_units_, other.denominator_units_)
+ && ::protozero::internal::gen_helpers::EqualsField(select_by_default_, other.select_by_default_)
+ && ::protozero::internal::gen_helpers::EqualsField(groups_, other.groups_);
+}
+
+bool GpuCounterDescriptor_GpuCounterSpec::ParseFromArray(const void* raw, size_t size) {
+ numerator_units_.clear();
+ denominator_units_.clear();
+ groups_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* counter_id */:
+ field.get(&counter_id_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 3 /* description */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &description_);
+ break;
+ case 5 /* int_peak_value */:
+ field.get(&int_peak_value_);
+ break;
+ case 6 /* double_peak_value */:
+ field.get(&double_peak_value_);
+ break;
+ case 7 /* numerator_units */:
+ numerator_units_.emplace_back();
+ field.get(&numerator_units_.back());
+ break;
+ case 8 /* denominator_units */:
+ denominator_units_.emplace_back();
+ field.get(&denominator_units_.back());
+ break;
+ case 9 /* select_by_default */:
+ field.get(&select_by_default_);
+ break;
+ case 10 /* groups */:
+ groups_.emplace_back();
+ field.get(&groups_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GpuCounterDescriptor_GpuCounterSpec::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GpuCounterDescriptor_GpuCounterSpec::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GpuCounterDescriptor_GpuCounterSpec::Serialize(::protozero::Message* msg) const {
+ // Field 1: counter_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, counter_id_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ // Field 3: description
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, description_, msg);
+ }
+
+ // Field 5: int_peak_value
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, int_peak_value_, msg);
+ }
+
+ // Field 6: double_peak_value
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(6, double_peak_value_, msg);
+ }
+
+ // Field 7: numerator_units
+ for (auto& it : numerator_units_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, it, msg);
+ }
+
+ // Field 8: denominator_units
+ for (auto& it : denominator_units_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, it, msg);
+ }
+
+ // Field 9: select_by_default
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, select_by_default_, msg);
+ }
+
+ // Field 10: groups
+ for (auto& it : groups_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/interceptor_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/interceptor_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+InterceptorDescriptor::InterceptorDescriptor() = default;
+InterceptorDescriptor::~InterceptorDescriptor() = default;
+InterceptorDescriptor::InterceptorDescriptor(const InterceptorDescriptor&) = default;
+InterceptorDescriptor& InterceptorDescriptor::operator=(const InterceptorDescriptor&) = default;
+InterceptorDescriptor::InterceptorDescriptor(InterceptorDescriptor&&) noexcept = default;
+InterceptorDescriptor& InterceptorDescriptor::operator=(InterceptorDescriptor&&) = default;
+
+bool InterceptorDescriptor::operator==(const InterceptorDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool InterceptorDescriptor::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string InterceptorDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> InterceptorDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void InterceptorDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/observable_events.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/observable_events.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ObservableEvents::ObservableEvents() = default;
+ObservableEvents::~ObservableEvents() = default;
+ObservableEvents::ObservableEvents(const ObservableEvents&) = default;
+ObservableEvents& ObservableEvents::operator=(const ObservableEvents&) = default;
+ObservableEvents::ObservableEvents(ObservableEvents&&) noexcept = default;
+ObservableEvents& ObservableEvents::operator=(ObservableEvents&&) = default;
+
+bool ObservableEvents::operator==(const ObservableEvents& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(instance_state_changes_, other.instance_state_changes_)
+ && ::protozero::internal::gen_helpers::EqualsField(all_data_sources_started_, other.all_data_sources_started_)
+ && ::protozero::internal::gen_helpers::EqualsField(clone_trigger_hit_, other.clone_trigger_hit_);
+}
+
+int ObservableEvents::instance_state_changes_size() const { return static_cast<int>(instance_state_changes_.size()); }
+void ObservableEvents::clear_instance_state_changes() { instance_state_changes_.clear(); }
+ObservableEvents_DataSourceInstanceStateChange* ObservableEvents::add_instance_state_changes() { instance_state_changes_.emplace_back(); return &instance_state_changes_.back(); }
+bool ObservableEvents::ParseFromArray(const void* raw, size_t size) {
+ instance_state_changes_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* instance_state_changes */:
+ instance_state_changes_.emplace_back();
+ instance_state_changes_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* all_data_sources_started */:
+ field.get(&all_data_sources_started_);
+ break;
+ case 3 /* clone_trigger_hit */:
+ (*clone_trigger_hit_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ObservableEvents::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ObservableEvents::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ObservableEvents::Serialize(::protozero::Message* msg) const {
+ // Field 1: instance_state_changes
+ for (auto& it : instance_state_changes_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: all_data_sources_started
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, all_data_sources_started_, msg);
+ }
+
+ // Field 3: clone_trigger_hit
+ if (_has_field_[3]) {
+ (*clone_trigger_hit_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ObservableEvents_CloneTriggerHit::ObservableEvents_CloneTriggerHit() = default;
+ObservableEvents_CloneTriggerHit::~ObservableEvents_CloneTriggerHit() = default;
+ObservableEvents_CloneTriggerHit::ObservableEvents_CloneTriggerHit(const ObservableEvents_CloneTriggerHit&) = default;
+ObservableEvents_CloneTriggerHit& ObservableEvents_CloneTriggerHit::operator=(const ObservableEvents_CloneTriggerHit&) = default;
+ObservableEvents_CloneTriggerHit::ObservableEvents_CloneTriggerHit(ObservableEvents_CloneTriggerHit&&) noexcept = default;
+ObservableEvents_CloneTriggerHit& ObservableEvents_CloneTriggerHit::operator=(ObservableEvents_CloneTriggerHit&&) = default;
+
+bool ObservableEvents_CloneTriggerHit::operator==(const ObservableEvents_CloneTriggerHit& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(tracing_session_id_, other.tracing_session_id_);
+}
+
+bool ObservableEvents_CloneTriggerHit::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* tracing_session_id */:
+ field.get(&tracing_session_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ObservableEvents_CloneTriggerHit::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ObservableEvents_CloneTriggerHit::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ObservableEvents_CloneTriggerHit::Serialize(::protozero::Message* msg) const {
+ // Field 1: tracing_session_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, tracing_session_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ObservableEvents_DataSourceInstanceStateChange::ObservableEvents_DataSourceInstanceStateChange() = default;
+ObservableEvents_DataSourceInstanceStateChange::~ObservableEvents_DataSourceInstanceStateChange() = default;
+ObservableEvents_DataSourceInstanceStateChange::ObservableEvents_DataSourceInstanceStateChange(const ObservableEvents_DataSourceInstanceStateChange&) = default;
+ObservableEvents_DataSourceInstanceStateChange& ObservableEvents_DataSourceInstanceStateChange::operator=(const ObservableEvents_DataSourceInstanceStateChange&) = default;
+ObservableEvents_DataSourceInstanceStateChange::ObservableEvents_DataSourceInstanceStateChange(ObservableEvents_DataSourceInstanceStateChange&&) noexcept = default;
+ObservableEvents_DataSourceInstanceStateChange& ObservableEvents_DataSourceInstanceStateChange::operator=(ObservableEvents_DataSourceInstanceStateChange&&) = default;
+
+bool ObservableEvents_DataSourceInstanceStateChange::operator==(const ObservableEvents_DataSourceInstanceStateChange& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_name_, other.producer_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_name_, other.data_source_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(state_, other.state_);
+}
+
+bool ObservableEvents_DataSourceInstanceStateChange::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* producer_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &producer_name_);
+ break;
+ case 2 /* data_source_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &data_source_name_);
+ break;
+ case 3 /* state */:
+ field.get(&state_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ObservableEvents_DataSourceInstanceStateChange::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ObservableEvents_DataSourceInstanceStateChange::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ObservableEvents_DataSourceInstanceStateChange::Serialize(::protozero::Message* msg) const {
+ // Field 1: producer_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, producer_name_, msg);
+ }
+
+ // Field 2: data_source_name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, data_source_name_, msg);
+ }
+
+ // Field 3: state
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, state_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/perf_events.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/perf_events.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+PerfEvents::PerfEvents() = default;
+PerfEvents::~PerfEvents() = default;
+PerfEvents::PerfEvents(const PerfEvents&) = default;
+PerfEvents& PerfEvents::operator=(const PerfEvents&) = default;
+PerfEvents::PerfEvents(PerfEvents&&) noexcept = default;
+PerfEvents& PerfEvents::operator=(PerfEvents&&) = default;
+
+bool PerfEvents::operator==(const PerfEvents& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool PerfEvents::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PerfEvents::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PerfEvents::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PerfEvents::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+PerfEvents_RawEvent::PerfEvents_RawEvent() = default;
+PerfEvents_RawEvent::~PerfEvents_RawEvent() = default;
+PerfEvents_RawEvent::PerfEvents_RawEvent(const PerfEvents_RawEvent&) = default;
+PerfEvents_RawEvent& PerfEvents_RawEvent::operator=(const PerfEvents_RawEvent&) = default;
+PerfEvents_RawEvent::PerfEvents_RawEvent(PerfEvents_RawEvent&&) noexcept = default;
+PerfEvents_RawEvent& PerfEvents_RawEvent::operator=(PerfEvents_RawEvent&&) = default;
+
+bool PerfEvents_RawEvent::operator==(const PerfEvents_RawEvent& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_, other.type_)
+ && ::protozero::internal::gen_helpers::EqualsField(config_, other.config_)
+ && ::protozero::internal::gen_helpers::EqualsField(config1_, other.config1_)
+ && ::protozero::internal::gen_helpers::EqualsField(config2_, other.config2_);
+}
+
+bool PerfEvents_RawEvent::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* type */:
+ field.get(&type_);
+ break;
+ case 2 /* config */:
+ field.get(&config_);
+ break;
+ case 3 /* config1 */:
+ field.get(&config1_);
+ break;
+ case 4 /* config2 */:
+ field.get(&config2_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PerfEvents_RawEvent::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PerfEvents_RawEvent::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PerfEvents_RawEvent::Serialize(::protozero::Message* msg) const {
+ // Field 1: type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, type_, msg);
+ }
+
+ // Field 2: config
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, config_, msg);
+ }
+
+ // Field 3: config1
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, config1_, msg);
+ }
+
+ // Field 4: config2
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, config2_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+PerfEvents_Tracepoint::PerfEvents_Tracepoint() = default;
+PerfEvents_Tracepoint::~PerfEvents_Tracepoint() = default;
+PerfEvents_Tracepoint::PerfEvents_Tracepoint(const PerfEvents_Tracepoint&) = default;
+PerfEvents_Tracepoint& PerfEvents_Tracepoint::operator=(const PerfEvents_Tracepoint&) = default;
+PerfEvents_Tracepoint::PerfEvents_Tracepoint(PerfEvents_Tracepoint&&) noexcept = default;
+PerfEvents_Tracepoint& PerfEvents_Tracepoint::operator=(PerfEvents_Tracepoint&&) = default;
+
+bool PerfEvents_Tracepoint::operator==(const PerfEvents_Tracepoint& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(filter_, other.filter_);
+}
+
+bool PerfEvents_Tracepoint::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* filter */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &filter_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PerfEvents_Tracepoint::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PerfEvents_Tracepoint::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PerfEvents_Tracepoint::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: filter
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, filter_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+PerfEvents_Timebase::PerfEvents_Timebase() = default;
+PerfEvents_Timebase::~PerfEvents_Timebase() = default;
+PerfEvents_Timebase::PerfEvents_Timebase(const PerfEvents_Timebase&) = default;
+PerfEvents_Timebase& PerfEvents_Timebase::operator=(const PerfEvents_Timebase&) = default;
+PerfEvents_Timebase::PerfEvents_Timebase(PerfEvents_Timebase&&) noexcept = default;
+PerfEvents_Timebase& PerfEvents_Timebase::operator=(PerfEvents_Timebase&&) = default;
+
+bool PerfEvents_Timebase::operator==(const PerfEvents_Timebase& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(frequency_, other.frequency_)
+ && ::protozero::internal::gen_helpers::EqualsField(period_, other.period_)
+ && ::protozero::internal::gen_helpers::EqualsField(counter_, other.counter_)
+ && ::protozero::internal::gen_helpers::EqualsField(tracepoint_, other.tracepoint_)
+ && ::protozero::internal::gen_helpers::EqualsField(raw_event_, other.raw_event_)
+ && ::protozero::internal::gen_helpers::EqualsField(timestamp_clock_, other.timestamp_clock_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool PerfEvents_Timebase::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 2 /* frequency */:
+ field.get(&frequency_);
+ break;
+ case 1 /* period */:
+ field.get(&period_);
+ break;
+ case 4 /* counter */:
+ field.get(&counter_);
+ break;
+ case 3 /* tracepoint */:
+ (*tracepoint_).ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* raw_event */:
+ (*raw_event_).ParseFromArray(field.data(), field.size());
+ break;
+ case 11 /* timestamp_clock */:
+ field.get(&timestamp_clock_);
+ break;
+ case 10 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PerfEvents_Timebase::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PerfEvents_Timebase::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PerfEvents_Timebase::Serialize(::protozero::Message* msg) const {
+ // Field 2: frequency
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, frequency_, msg);
+ }
+
+ // Field 1: period
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, period_, msg);
+ }
+
+ // Field 4: counter
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, counter_, msg);
+ }
+
+ // Field 3: tracepoint
+ if (_has_field_[3]) {
+ (*tracepoint_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 5: raw_event
+ if (_has_field_[5]) {
+ (*raw_event_).Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 11: timestamp_clock
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, timestamp_clock_, msg);
+ }
+
+ // Field 10: name
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeString(10, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/protolog_common.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/protolog_common.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/sys_stats_counters.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/sys_stats_counters.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/trace_stats.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/trace_stats.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TraceStats::TraceStats() = default;
+TraceStats::~TraceStats() = default;
+TraceStats::TraceStats(const TraceStats&) = default;
+TraceStats& TraceStats::operator=(const TraceStats&) = default;
+TraceStats::TraceStats(TraceStats&&) noexcept = default;
+TraceStats& TraceStats::operator=(TraceStats&&) = default;
+
+bool TraceStats::operator==(const TraceStats& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffer_stats_, other.buffer_stats_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunk_payload_histogram_def_, other.chunk_payload_histogram_def_)
+ && ::protozero::internal::gen_helpers::EqualsField(writer_stats_, other.writer_stats_)
+ && ::protozero::internal::gen_helpers::EqualsField(producers_connected_, other.producers_connected_)
+ && ::protozero::internal::gen_helpers::EqualsField(producers_seen_, other.producers_seen_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_sources_registered_, other.data_sources_registered_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_sources_seen_, other.data_sources_seen_)
+ && ::protozero::internal::gen_helpers::EqualsField(tracing_sessions_, other.tracing_sessions_)
+ && ::protozero::internal::gen_helpers::EqualsField(total_buffers_, other.total_buffers_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_discarded_, other.chunks_discarded_)
+ && ::protozero::internal::gen_helpers::EqualsField(patches_discarded_, other.patches_discarded_)
+ && ::protozero::internal::gen_helpers::EqualsField(invalid_packets_, other.invalid_packets_)
+ && ::protozero::internal::gen_helpers::EqualsField(filter_stats_, other.filter_stats_)
+ && ::protozero::internal::gen_helpers::EqualsField(flushes_requested_, other.flushes_requested_)
+ && ::protozero::internal::gen_helpers::EqualsField(flushes_succeeded_, other.flushes_succeeded_)
+ && ::protozero::internal::gen_helpers::EqualsField(flushes_failed_, other.flushes_failed_)
+ && ::protozero::internal::gen_helpers::EqualsField(final_flush_outcome_, other.final_flush_outcome_);
+}
+
+int TraceStats::buffer_stats_size() const { return static_cast<int>(buffer_stats_.size()); }
+void TraceStats::clear_buffer_stats() { buffer_stats_.clear(); }
+TraceStats_BufferStats* TraceStats::add_buffer_stats() { buffer_stats_.emplace_back(); return &buffer_stats_.back(); }
+int TraceStats::writer_stats_size() const { return static_cast<int>(writer_stats_.size()); }
+void TraceStats::clear_writer_stats() { writer_stats_.clear(); }
+TraceStats_WriterStats* TraceStats::add_writer_stats() { writer_stats_.emplace_back(); return &writer_stats_.back(); }
+bool TraceStats::ParseFromArray(const void* raw, size_t size) {
+ buffer_stats_.clear();
+ chunk_payload_histogram_def_.clear();
+ writer_stats_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* buffer_stats */:
+ buffer_stats_.emplace_back();
+ buffer_stats_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 17 /* chunk_payload_histogram_def */:
+ chunk_payload_histogram_def_.emplace_back();
+ field.get(&chunk_payload_histogram_def_.back());
+ break;
+ case 18 /* writer_stats */:
+ writer_stats_.emplace_back();
+ writer_stats_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* producers_connected */:
+ field.get(&producers_connected_);
+ break;
+ case 3 /* producers_seen */:
+ field.get(&producers_seen_);
+ break;
+ case 4 /* data_sources_registered */:
+ field.get(&data_sources_registered_);
+ break;
+ case 5 /* data_sources_seen */:
+ field.get(&data_sources_seen_);
+ break;
+ case 6 /* tracing_sessions */:
+ field.get(&tracing_sessions_);
+ break;
+ case 7 /* total_buffers */:
+ field.get(&total_buffers_);
+ break;
+ case 8 /* chunks_discarded */:
+ field.get(&chunks_discarded_);
+ break;
+ case 9 /* patches_discarded */:
+ field.get(&patches_discarded_);
+ break;
+ case 10 /* invalid_packets */:
+ field.get(&invalid_packets_);
+ break;
+ case 11 /* filter_stats */:
+ (*filter_stats_).ParseFromArray(field.data(), field.size());
+ break;
+ case 12 /* flushes_requested */:
+ field.get(&flushes_requested_);
+ break;
+ case 13 /* flushes_succeeded */:
+ field.get(&flushes_succeeded_);
+ break;
+ case 14 /* flushes_failed */:
+ field.get(&flushes_failed_);
+ break;
+ case 15 /* final_flush_outcome */:
+ field.get(&final_flush_outcome_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceStats::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceStats::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceStats::Serialize(::protozero::Message* msg) const {
+ // Field 1: buffer_stats
+ for (auto& it : buffer_stats_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 17: chunk_payload_histogram_def
+ for (auto& it : chunk_payload_histogram_def_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, it, msg);
+ }
+
+ // Field 18: writer_stats
+ for (auto& it : writer_stats_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(18));
+ }
+
+ // Field 2: producers_connected
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, producers_connected_, msg);
+ }
+
+ // Field 3: producers_seen
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, producers_seen_, msg);
+ }
+
+ // Field 4: data_sources_registered
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, data_sources_registered_, msg);
+ }
+
+ // Field 5: data_sources_seen
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, data_sources_seen_, msg);
+ }
+
+ // Field 6: tracing_sessions
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, tracing_sessions_, msg);
+ }
+
+ // Field 7: total_buffers
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, total_buffers_, msg);
+ }
+
+ // Field 8: chunks_discarded
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, chunks_discarded_, msg);
+ }
+
+ // Field 9: patches_discarded
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, patches_discarded_, msg);
+ }
+
+ // Field 10: invalid_packets
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, invalid_packets_, msg);
+ }
+
+ // Field 11: filter_stats
+ if (_has_field_[11]) {
+ (*filter_stats_).Serialize(msg->BeginNestedMessage<::protozero::Message>(11));
+ }
+
+ // Field 12: flushes_requested
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(12, flushes_requested_, msg);
+ }
+
+ // Field 13: flushes_succeeded
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, flushes_succeeded_, msg);
+ }
+
+ // Field 14: flushes_failed
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(14, flushes_failed_, msg);
+ }
+
+ // Field 15: final_flush_outcome
+ if (_has_field_[15]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(15, final_flush_outcome_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceStats_FilterStats::TraceStats_FilterStats() = default;
+TraceStats_FilterStats::~TraceStats_FilterStats() = default;
+TraceStats_FilterStats::TraceStats_FilterStats(const TraceStats_FilterStats&) = default;
+TraceStats_FilterStats& TraceStats_FilterStats::operator=(const TraceStats_FilterStats&) = default;
+TraceStats_FilterStats::TraceStats_FilterStats(TraceStats_FilterStats&&) noexcept = default;
+TraceStats_FilterStats& TraceStats_FilterStats::operator=(TraceStats_FilterStats&&) = default;
+
+bool TraceStats_FilterStats::operator==(const TraceStats_FilterStats& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(input_packets_, other.input_packets_)
+ && ::protozero::internal::gen_helpers::EqualsField(input_bytes_, other.input_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(output_bytes_, other.output_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(errors_, other.errors_)
+ && ::protozero::internal::gen_helpers::EqualsField(time_taken_ns_, other.time_taken_ns_)
+ && ::protozero::internal::gen_helpers::EqualsField(bytes_discarded_per_buffer_, other.bytes_discarded_per_buffer_);
+}
+
+bool TraceStats_FilterStats::ParseFromArray(const void* raw, size_t size) {
+ bytes_discarded_per_buffer_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* input_packets */:
+ field.get(&input_packets_);
+ break;
+ case 2 /* input_bytes */:
+ field.get(&input_bytes_);
+ break;
+ case 3 /* output_bytes */:
+ field.get(&output_bytes_);
+ break;
+ case 4 /* errors */:
+ field.get(&errors_);
+ break;
+ case 5 /* time_taken_ns */:
+ field.get(&time_taken_ns_);
+ break;
+ case 20 /* bytes_discarded_per_buffer */:
+ bytes_discarded_per_buffer_.emplace_back();
+ field.get(&bytes_discarded_per_buffer_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceStats_FilterStats::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceStats_FilterStats::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceStats_FilterStats::Serialize(::protozero::Message* msg) const {
+ // Field 1: input_packets
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, input_packets_, msg);
+ }
+
+ // Field 2: input_bytes
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, input_bytes_, msg);
+ }
+
+ // Field 3: output_bytes
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, output_bytes_, msg);
+ }
+
+ // Field 4: errors
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, errors_, msg);
+ }
+
+ // Field 5: time_taken_ns
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, time_taken_ns_, msg);
+ }
+
+ // Field 20: bytes_discarded_per_buffer
+ for (auto& it : bytes_discarded_per_buffer_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(20, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceStats_WriterStats::TraceStats_WriterStats() = default;
+TraceStats_WriterStats::~TraceStats_WriterStats() = default;
+TraceStats_WriterStats::TraceStats_WriterStats(const TraceStats_WriterStats&) = default;
+TraceStats_WriterStats& TraceStats_WriterStats::operator=(const TraceStats_WriterStats&) = default;
+TraceStats_WriterStats::TraceStats_WriterStats(TraceStats_WriterStats&&) noexcept = default;
+TraceStats_WriterStats& TraceStats_WriterStats::operator=(TraceStats_WriterStats&&) = default;
+
+bool TraceStats_WriterStats::operator==(const TraceStats_WriterStats& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(sequence_id_, other.sequence_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffer_, other.buffer_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunk_payload_histogram_counts_, other.chunk_payload_histogram_counts_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunk_payload_histogram_sum_, other.chunk_payload_histogram_sum_);
+}
+
+bool TraceStats_WriterStats::ParseFromArray(const void* raw, size_t size) {
+ chunk_payload_histogram_counts_.clear();
+ chunk_payload_histogram_sum_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* sequence_id */:
+ field.get(&sequence_id_);
+ break;
+ case 4 /* buffer */:
+ field.get(&buffer_);
+ break;
+ case 2 /* chunk_payload_histogram_counts */:
+ if (!::protozero::internal::gen_helpers::DeserializePackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(field, &chunk_payload_histogram_counts_)) {
+ packed_error = true;}
+ break;
+ case 3 /* chunk_payload_histogram_sum */:
+ if (!::protozero::internal::gen_helpers::DeserializePackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int64_t>(field, &chunk_payload_histogram_sum_)) {
+ packed_error = true;}
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceStats_WriterStats::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceStats_WriterStats::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceStats_WriterStats::Serialize(::protozero::Message* msg) const {
+ // Field 1: sequence_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, sequence_id_, msg);
+ }
+
+ // Field 4: buffer
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, buffer_, msg);
+ }
+
+ // Field 2: chunk_payload_histogram_counts
+ {
+ ::protozero::PackedVarInt pack;
+ for (auto& it : chunk_payload_histogram_counts_)
+ pack.Append(it);
+ msg->AppendBytes(2, pack.data(), pack.size());
+ }
+
+ // Field 3: chunk_payload_histogram_sum
+ {
+ ::protozero::PackedVarInt pack;
+ for (auto& it : chunk_payload_histogram_sum_)
+ pack.Append(it);
+ msg->AppendBytes(3, pack.data(), pack.size());
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceStats_BufferStats::TraceStats_BufferStats() = default;
+TraceStats_BufferStats::~TraceStats_BufferStats() = default;
+TraceStats_BufferStats::TraceStats_BufferStats(const TraceStats_BufferStats&) = default;
+TraceStats_BufferStats& TraceStats_BufferStats::operator=(const TraceStats_BufferStats&) = default;
+TraceStats_BufferStats::TraceStats_BufferStats(TraceStats_BufferStats&&) noexcept = default;
+TraceStats_BufferStats& TraceStats_BufferStats::operator=(TraceStats_BufferStats&&) = default;
+
+bool TraceStats_BufferStats::operator==(const TraceStats_BufferStats& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffer_size_, other.buffer_size_)
+ && ::protozero::internal::gen_helpers::EqualsField(bytes_written_, other.bytes_written_)
+ && ::protozero::internal::gen_helpers::EqualsField(bytes_overwritten_, other.bytes_overwritten_)
+ && ::protozero::internal::gen_helpers::EqualsField(bytes_read_, other.bytes_read_)
+ && ::protozero::internal::gen_helpers::EqualsField(padding_bytes_written_, other.padding_bytes_written_)
+ && ::protozero::internal::gen_helpers::EqualsField(padding_bytes_cleared_, other.padding_bytes_cleared_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_written_, other.chunks_written_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_rewritten_, other.chunks_rewritten_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_overwritten_, other.chunks_overwritten_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_discarded_, other.chunks_discarded_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_read_, other.chunks_read_)
+ && ::protozero::internal::gen_helpers::EqualsField(chunks_committed_out_of_order_, other.chunks_committed_out_of_order_)
+ && ::protozero::internal::gen_helpers::EqualsField(write_wrap_count_, other.write_wrap_count_)
+ && ::protozero::internal::gen_helpers::EqualsField(patches_succeeded_, other.patches_succeeded_)
+ && ::protozero::internal::gen_helpers::EqualsField(patches_failed_, other.patches_failed_)
+ && ::protozero::internal::gen_helpers::EqualsField(readaheads_succeeded_, other.readaheads_succeeded_)
+ && ::protozero::internal::gen_helpers::EqualsField(readaheads_failed_, other.readaheads_failed_)
+ && ::protozero::internal::gen_helpers::EqualsField(abi_violations_, other.abi_violations_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_writer_packet_loss_, other.trace_writer_packet_loss_);
+}
+
+bool TraceStats_BufferStats::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 12 /* buffer_size */:
+ field.get(&buffer_size_);
+ break;
+ case 1 /* bytes_written */:
+ field.get(&bytes_written_);
+ break;
+ case 13 /* bytes_overwritten */:
+ field.get(&bytes_overwritten_);
+ break;
+ case 14 /* bytes_read */:
+ field.get(&bytes_read_);
+ break;
+ case 15 /* padding_bytes_written */:
+ field.get(&padding_bytes_written_);
+ break;
+ case 16 /* padding_bytes_cleared */:
+ field.get(&padding_bytes_cleared_);
+ break;
+ case 2 /* chunks_written */:
+ field.get(&chunks_written_);
+ break;
+ case 10 /* chunks_rewritten */:
+ field.get(&chunks_rewritten_);
+ break;
+ case 3 /* chunks_overwritten */:
+ field.get(&chunks_overwritten_);
+ break;
+ case 18 /* chunks_discarded */:
+ field.get(&chunks_discarded_);
+ break;
+ case 17 /* chunks_read */:
+ field.get(&chunks_read_);
+ break;
+ case 11 /* chunks_committed_out_of_order */:
+ field.get(&chunks_committed_out_of_order_);
+ break;
+ case 4 /* write_wrap_count */:
+ field.get(&write_wrap_count_);
+ break;
+ case 5 /* patches_succeeded */:
+ field.get(&patches_succeeded_);
+ break;
+ case 6 /* patches_failed */:
+ field.get(&patches_failed_);
+ break;
+ case 7 /* readaheads_succeeded */:
+ field.get(&readaheads_succeeded_);
+ break;
+ case 8 /* readaheads_failed */:
+ field.get(&readaheads_failed_);
+ break;
+ case 9 /* abi_violations */:
+ field.get(&abi_violations_);
+ break;
+ case 19 /* trace_writer_packet_loss */:
+ field.get(&trace_writer_packet_loss_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceStats_BufferStats::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceStats_BufferStats::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceStats_BufferStats::Serialize(::protozero::Message* msg) const {
+ // Field 12: buffer_size
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(12, buffer_size_, msg);
+ }
+
+ // Field 1: bytes_written
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, bytes_written_, msg);
+ }
+
+ // Field 13: bytes_overwritten
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, bytes_overwritten_, msg);
+ }
+
+ // Field 14: bytes_read
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(14, bytes_read_, msg);
+ }
+
+ // Field 15: padding_bytes_written
+ if (_has_field_[15]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(15, padding_bytes_written_, msg);
+ }
+
+ // Field 16: padding_bytes_cleared
+ if (_has_field_[16]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(16, padding_bytes_cleared_, msg);
+ }
+
+ // Field 2: chunks_written
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, chunks_written_, msg);
+ }
+
+ // Field 10: chunks_rewritten
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, chunks_rewritten_, msg);
+ }
+
+ // Field 3: chunks_overwritten
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, chunks_overwritten_, msg);
+ }
+
+ // Field 18: chunks_discarded
+ if (_has_field_[18]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(18, chunks_discarded_, msg);
+ }
+
+ // Field 17: chunks_read
+ if (_has_field_[17]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, chunks_read_, msg);
+ }
+
+ // Field 11: chunks_committed_out_of_order
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, chunks_committed_out_of_order_, msg);
+ }
+
+ // Field 4: write_wrap_count
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, write_wrap_count_, msg);
+ }
+
+ // Field 5: patches_succeeded
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, patches_succeeded_, msg);
+ }
+
+ // Field 6: patches_failed
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, patches_failed_, msg);
+ }
+
+ // Field 7: readaheads_succeeded
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, readaheads_succeeded_, msg);
+ }
+
+ // Field 8: readaheads_failed
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, readaheads_failed_, msg);
+ }
+
+ // Field 9: abi_violations
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, abi_violations_, msg);
+ }
+
+ // Field 19: trace_writer_packet_loss
+ if (_has_field_[19]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(19, trace_writer_packet_loss_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/tracing_service_capabilities.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_capabilities.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/observable_events.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TracingServiceCapabilities::TracingServiceCapabilities() = default;
+TracingServiceCapabilities::~TracingServiceCapabilities() = default;
+TracingServiceCapabilities::TracingServiceCapabilities(const TracingServiceCapabilities&) = default;
+TracingServiceCapabilities& TracingServiceCapabilities::operator=(const TracingServiceCapabilities&) = default;
+TracingServiceCapabilities::TracingServiceCapabilities(TracingServiceCapabilities&&) noexcept = default;
+TracingServiceCapabilities& TracingServiceCapabilities::operator=(TracingServiceCapabilities&&) = default;
+
+bool TracingServiceCapabilities::operator==(const TracingServiceCapabilities& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_query_capabilities_, other.has_query_capabilities_)
+ && ::protozero::internal::gen_helpers::EqualsField(observable_events_, other.observable_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_trace_config_output_path_, other.has_trace_config_output_path_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_clone_session_, other.has_clone_session_);
+}
+
+bool TracingServiceCapabilities::ParseFromArray(const void* raw, size_t size) {
+ observable_events_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* has_query_capabilities */:
+ field.get(&has_query_capabilities_);
+ break;
+ case 2 /* observable_events */:
+ observable_events_.emplace_back();
+ field.get(&observable_events_.back());
+ break;
+ case 3 /* has_trace_config_output_path */:
+ field.get(&has_trace_config_output_path_);
+ break;
+ case 4 /* has_clone_session */:
+ field.get(&has_clone_session_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TracingServiceCapabilities::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TracingServiceCapabilities::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TracingServiceCapabilities::Serialize(::protozero::Message* msg) const {
+ // Field 1: has_query_capabilities
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, has_query_capabilities_, msg);
+ }
+
+ // Field 2: observable_events
+ for (auto& it : observable_events_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ // Field 3: has_trace_config_output_path
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, has_trace_config_output_path_, msg);
+ }
+
+ // Field 4: has_clone_session
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, has_clone_session_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/tracing_service_state.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_state.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/track_event_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/gpu_counter_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/ftrace_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TracingServiceState::TracingServiceState() = default;
+TracingServiceState::~TracingServiceState() = default;
+TracingServiceState::TracingServiceState(const TracingServiceState&) = default;
+TracingServiceState& TracingServiceState::operator=(const TracingServiceState&) = default;
+TracingServiceState::TracingServiceState(TracingServiceState&&) noexcept = default;
+TracingServiceState& TracingServiceState::operator=(TracingServiceState&&) = default;
+
+bool TracingServiceState::operator==(const TracingServiceState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(producers_, other.producers_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_sources_, other.data_sources_)
+ && ::protozero::internal::gen_helpers::EqualsField(tracing_sessions_, other.tracing_sessions_)
+ && ::protozero::internal::gen_helpers::EqualsField(supports_tracing_sessions_, other.supports_tracing_sessions_)
+ && ::protozero::internal::gen_helpers::EqualsField(num_sessions_, other.num_sessions_)
+ && ::protozero::internal::gen_helpers::EqualsField(num_sessions_started_, other.num_sessions_started_)
+ && ::protozero::internal::gen_helpers::EqualsField(tracing_service_version_, other.tracing_service_version_);
+}
+
+int TracingServiceState::producers_size() const { return static_cast<int>(producers_.size()); }
+void TracingServiceState::clear_producers() { producers_.clear(); }
+TracingServiceState_Producer* TracingServiceState::add_producers() { producers_.emplace_back(); return &producers_.back(); }
+int TracingServiceState::data_sources_size() const { return static_cast<int>(data_sources_.size()); }
+void TracingServiceState::clear_data_sources() { data_sources_.clear(); }
+TracingServiceState_DataSource* TracingServiceState::add_data_sources() { data_sources_.emplace_back(); return &data_sources_.back(); }
+int TracingServiceState::tracing_sessions_size() const { return static_cast<int>(tracing_sessions_.size()); }
+void TracingServiceState::clear_tracing_sessions() { tracing_sessions_.clear(); }
+TracingServiceState_TracingSession* TracingServiceState::add_tracing_sessions() { tracing_sessions_.emplace_back(); return &tracing_sessions_.back(); }
+bool TracingServiceState::ParseFromArray(const void* raw, size_t size) {
+ producers_.clear();
+ data_sources_.clear();
+ tracing_sessions_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* producers */:
+ producers_.emplace_back();
+ producers_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* data_sources */:
+ data_sources_.emplace_back();
+ data_sources_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* tracing_sessions */:
+ tracing_sessions_.emplace_back();
+ tracing_sessions_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 7 /* supports_tracing_sessions */:
+ field.get(&supports_tracing_sessions_);
+ break;
+ case 3 /* num_sessions */:
+ field.get(&num_sessions_);
+ break;
+ case 4 /* num_sessions_started */:
+ field.get(&num_sessions_started_);
+ break;
+ case 5 /* tracing_service_version */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &tracing_service_version_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TracingServiceState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TracingServiceState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TracingServiceState::Serialize(::protozero::Message* msg) const {
+ // Field 1: producers
+ for (auto& it : producers_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: data_sources
+ for (auto& it : data_sources_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 6: tracing_sessions
+ for (auto& it : tracing_sessions_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 7: supports_tracing_sessions
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(7, supports_tracing_sessions_, msg);
+ }
+
+ // Field 3: num_sessions
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, num_sessions_, msg);
+ }
+
+ // Field 4: num_sessions_started
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, num_sessions_started_, msg);
+ }
+
+ // Field 5: tracing_service_version
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeString(5, tracing_service_version_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TracingServiceState_TracingSession::TracingServiceState_TracingSession() = default;
+TracingServiceState_TracingSession::~TracingServiceState_TracingSession() = default;
+TracingServiceState_TracingSession::TracingServiceState_TracingSession(const TracingServiceState_TracingSession&) = default;
+TracingServiceState_TracingSession& TracingServiceState_TracingSession::operator=(const TracingServiceState_TracingSession&) = default;
+TracingServiceState_TracingSession::TracingServiceState_TracingSession(TracingServiceState_TracingSession&&) noexcept = default;
+TracingServiceState_TracingSession& TracingServiceState_TracingSession::operator=(TracingServiceState_TracingSession&&) = default;
+
+bool TracingServiceState_TracingSession::operator==(const TracingServiceState_TracingSession& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(id_, other.id_)
+ && ::protozero::internal::gen_helpers::EqualsField(consumer_uid_, other.consumer_uid_)
+ && ::protozero::internal::gen_helpers::EqualsField(state_, other.state_)
+ && ::protozero::internal::gen_helpers::EqualsField(unique_session_name_, other.unique_session_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffer_size_kb_, other.buffer_size_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(duration_ms_, other.duration_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(num_data_sources_, other.num_data_sources_)
+ && ::protozero::internal::gen_helpers::EqualsField(start_realtime_ns_, other.start_realtime_ns_)
+ && ::protozero::internal::gen_helpers::EqualsField(bugreport_score_, other.bugreport_score_)
+ && ::protozero::internal::gen_helpers::EqualsField(bugreport_filename_, other.bugreport_filename_)
+ && ::protozero::internal::gen_helpers::EqualsField(is_started_, other.is_started_);
+}
+
+bool TracingServiceState_TracingSession::ParseFromArray(const void* raw, size_t size) {
+ buffer_size_kb_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* id */:
+ field.get(&id_);
+ break;
+ case 2 /* consumer_uid */:
+ field.get(&consumer_uid_);
+ break;
+ case 3 /* state */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &state_);
+ break;
+ case 4 /* unique_session_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &unique_session_name_);
+ break;
+ case 5 /* buffer_size_kb */:
+ buffer_size_kb_.emplace_back();
+ field.get(&buffer_size_kb_.back());
+ break;
+ case 6 /* duration_ms */:
+ field.get(&duration_ms_);
+ break;
+ case 7 /* num_data_sources */:
+ field.get(&num_data_sources_);
+ break;
+ case 8 /* start_realtime_ns */:
+ field.get(&start_realtime_ns_);
+ break;
+ case 9 /* bugreport_score */:
+ field.get(&bugreport_score_);
+ break;
+ case 10 /* bugreport_filename */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &bugreport_filename_);
+ break;
+ case 11 /* is_started */:
+ field.get(&is_started_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TracingServiceState_TracingSession::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TracingServiceState_TracingSession::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TracingServiceState_TracingSession::Serialize(::protozero::Message* msg) const {
+ // Field 1: id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, id_, msg);
+ }
+
+ // Field 2: consumer_uid
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, consumer_uid_, msg);
+ }
+
+ // Field 3: state
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, state_, msg);
+ }
+
+ // Field 4: unique_session_name
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeString(4, unique_session_name_, msg);
+ }
+
+ // Field 5: buffer_size_kb
+ for (auto& it : buffer_size_kb_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, it, msg);
+ }
+
+ // Field 6: duration_ms
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, duration_ms_, msg);
+ }
+
+ // Field 7: num_data_sources
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, num_data_sources_, msg);
+ }
+
+ // Field 8: start_realtime_ns
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, start_realtime_ns_, msg);
+ }
+
+ // Field 9: bugreport_score
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, bugreport_score_, msg);
+ }
+
+ // Field 10: bugreport_filename
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeString(10, bugreport_filename_, msg);
+ }
+
+ // Field 11: is_started
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(11, is_started_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TracingServiceState_DataSource::TracingServiceState_DataSource() = default;
+TracingServiceState_DataSource::~TracingServiceState_DataSource() = default;
+TracingServiceState_DataSource::TracingServiceState_DataSource(const TracingServiceState_DataSource&) = default;
+TracingServiceState_DataSource& TracingServiceState_DataSource::operator=(const TracingServiceState_DataSource&) = default;
+TracingServiceState_DataSource::TracingServiceState_DataSource(TracingServiceState_DataSource&&) noexcept = default;
+TracingServiceState_DataSource& TracingServiceState_DataSource::operator=(TracingServiceState_DataSource&&) = default;
+
+bool TracingServiceState_DataSource::operator==(const TracingServiceState_DataSource& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(ds_descriptor_, other.ds_descriptor_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_id_, other.producer_id_);
+}
+
+bool TracingServiceState_DataSource::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* ds_descriptor */:
+ (*ds_descriptor_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* producer_id */:
+ field.get(&producer_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TracingServiceState_DataSource::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TracingServiceState_DataSource::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TracingServiceState_DataSource::Serialize(::protozero::Message* msg) const {
+ // Field 1: ds_descriptor
+ if (_has_field_[1]) {
+ (*ds_descriptor_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: producer_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, producer_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TracingServiceState_Producer::TracingServiceState_Producer() = default;
+TracingServiceState_Producer::~TracingServiceState_Producer() = default;
+TracingServiceState_Producer::TracingServiceState_Producer(const TracingServiceState_Producer&) = default;
+TracingServiceState_Producer& TracingServiceState_Producer::operator=(const TracingServiceState_Producer&) = default;
+TracingServiceState_Producer::TracingServiceState_Producer(TracingServiceState_Producer&&) noexcept = default;
+TracingServiceState_Producer& TracingServiceState_Producer::operator=(TracingServiceState_Producer&&) = default;
+
+bool TracingServiceState_Producer::operator==(const TracingServiceState_Producer& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(id_, other.id_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_, other.pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(uid_, other.uid_)
+ && ::protozero::internal::gen_helpers::EqualsField(sdk_version_, other.sdk_version_);
+}
+
+bool TracingServiceState_Producer::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* id */:
+ field.get(&id_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 5 /* pid */:
+ field.get(&pid_);
+ break;
+ case 3 /* uid */:
+ field.get(&uid_);
+ break;
+ case 4 /* sdk_version */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &sdk_version_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TracingServiceState_Producer::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TracingServiceState_Producer::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TracingServiceState_Producer::Serialize(::protozero::Message* msg) const {
+ // Field 1: id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, id_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ // Field 5: pid
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, pid_, msg);
+ }
+
+ // Field 3: uid
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, uid_, msg);
+ }
+
+ // Field 4: sdk_version
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeString(4, sdk_version_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/track_event_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/common/track_event_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TrackEventDescriptor::TrackEventDescriptor() = default;
+TrackEventDescriptor::~TrackEventDescriptor() = default;
+TrackEventDescriptor::TrackEventDescriptor(const TrackEventDescriptor&) = default;
+TrackEventDescriptor& TrackEventDescriptor::operator=(const TrackEventDescriptor&) = default;
+TrackEventDescriptor::TrackEventDescriptor(TrackEventDescriptor&&) noexcept = default;
+TrackEventDescriptor& TrackEventDescriptor::operator=(TrackEventDescriptor&&) = default;
+
+bool TrackEventDescriptor::operator==(const TrackEventDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(available_categories_, other.available_categories_);
+}
+
+int TrackEventDescriptor::available_categories_size() const { return static_cast<int>(available_categories_.size()); }
+void TrackEventDescriptor::clear_available_categories() { available_categories_.clear(); }
+TrackEventCategory* TrackEventDescriptor::add_available_categories() { available_categories_.emplace_back(); return &available_categories_.back(); }
+bool TrackEventDescriptor::ParseFromArray(const void* raw, size_t size) {
+ available_categories_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* available_categories */:
+ available_categories_.emplace_back();
+ available_categories_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackEventDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackEventDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackEventDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: available_categories
+ for (auto& it : available_categories_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TrackEventCategory::TrackEventCategory() = default;
+TrackEventCategory::~TrackEventCategory() = default;
+TrackEventCategory::TrackEventCategory(const TrackEventCategory&) = default;
+TrackEventCategory& TrackEventCategory::operator=(const TrackEventCategory&) = default;
+TrackEventCategory::TrackEventCategory(TrackEventCategory&&) noexcept = default;
+TrackEventCategory& TrackEventCategory::operator=(TrackEventCategory&&) = default;
+
+bool TrackEventCategory::operator==(const TrackEventCategory& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(description_, other.description_)
+ && ::protozero::internal::gen_helpers::EqualsField(tags_, other.tags_);
+}
+
+bool TrackEventCategory::ParseFromArray(const void* raw, size_t size) {
+ tags_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* description */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &description_);
+ break;
+ case 3 /* tags */:
+ tags_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &tags_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackEventCategory::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackEventCategory::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackEventCategory::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: description
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, description_, msg);
+ }
+
+ // Field 3: tags
+ for (auto& it : tags_) {
+ ::protozero::internal::gen_helpers::SerializeString(3, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_game_intervention_list_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_game_intervention_list_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidGameInterventionListConfig::AndroidGameInterventionListConfig() = default;
+AndroidGameInterventionListConfig::~AndroidGameInterventionListConfig() = default;
+AndroidGameInterventionListConfig::AndroidGameInterventionListConfig(const AndroidGameInterventionListConfig&) = default;
+AndroidGameInterventionListConfig& AndroidGameInterventionListConfig::operator=(const AndroidGameInterventionListConfig&) = default;
+AndroidGameInterventionListConfig::AndroidGameInterventionListConfig(AndroidGameInterventionListConfig&&) noexcept = default;
+AndroidGameInterventionListConfig& AndroidGameInterventionListConfig::operator=(AndroidGameInterventionListConfig&&) = default;
+
+bool AndroidGameInterventionListConfig::operator==(const AndroidGameInterventionListConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(package_name_filter_, other.package_name_filter_);
+}
+
+bool AndroidGameInterventionListConfig::ParseFromArray(const void* raw, size_t size) {
+ package_name_filter_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* package_name_filter */:
+ package_name_filter_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &package_name_filter_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidGameInterventionListConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidGameInterventionListConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidGameInterventionListConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: package_name_filter
+ for (auto& it : package_name_filter_) {
+ ::protozero::internal::gen_helpers::SerializeString(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_input_event_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_input_event_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidInputEventConfig::AndroidInputEventConfig() = default;
+AndroidInputEventConfig::~AndroidInputEventConfig() = default;
+AndroidInputEventConfig::AndroidInputEventConfig(const AndroidInputEventConfig&) = default;
+AndroidInputEventConfig& AndroidInputEventConfig::operator=(const AndroidInputEventConfig&) = default;
+AndroidInputEventConfig::AndroidInputEventConfig(AndroidInputEventConfig&&) noexcept = default;
+AndroidInputEventConfig& AndroidInputEventConfig::operator=(AndroidInputEventConfig&&) = default;
+
+bool AndroidInputEventConfig::operator==(const AndroidInputEventConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(mode_, other.mode_)
+ && ::protozero::internal::gen_helpers::EqualsField(rules_, other.rules_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_dispatcher_input_events_, other.trace_dispatcher_input_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_dispatcher_window_dispatch_, other.trace_dispatcher_window_dispatch_);
+}
+
+int AndroidInputEventConfig::rules_size() const { return static_cast<int>(rules_.size()); }
+void AndroidInputEventConfig::clear_rules() { rules_.clear(); }
+AndroidInputEventConfig_TraceRule* AndroidInputEventConfig::add_rules() { rules_.emplace_back(); return &rules_.back(); }
+bool AndroidInputEventConfig::ParseFromArray(const void* raw, size_t size) {
+ rules_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* mode */:
+ field.get(&mode_);
+ break;
+ case 2 /* rules */:
+ rules_.emplace_back();
+ rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* trace_dispatcher_input_events */:
+ field.get(&trace_dispatcher_input_events_);
+ break;
+ case 4 /* trace_dispatcher_window_dispatch */:
+ field.get(&trace_dispatcher_window_dispatch_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidInputEventConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidInputEventConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidInputEventConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: mode
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, mode_, msg);
+ }
+
+ // Field 2: rules
+ for (auto& it : rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 3: trace_dispatcher_input_events
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, trace_dispatcher_input_events_, msg);
+ }
+
+ // Field 4: trace_dispatcher_window_dispatch
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, trace_dispatcher_window_dispatch_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+AndroidInputEventConfig_TraceRule::AndroidInputEventConfig_TraceRule() = default;
+AndroidInputEventConfig_TraceRule::~AndroidInputEventConfig_TraceRule() = default;
+AndroidInputEventConfig_TraceRule::AndroidInputEventConfig_TraceRule(const AndroidInputEventConfig_TraceRule&) = default;
+AndroidInputEventConfig_TraceRule& AndroidInputEventConfig_TraceRule::operator=(const AndroidInputEventConfig_TraceRule&) = default;
+AndroidInputEventConfig_TraceRule::AndroidInputEventConfig_TraceRule(AndroidInputEventConfig_TraceRule&&) noexcept = default;
+AndroidInputEventConfig_TraceRule& AndroidInputEventConfig_TraceRule::operator=(AndroidInputEventConfig_TraceRule&&) = default;
+
+bool AndroidInputEventConfig_TraceRule::operator==(const AndroidInputEventConfig_TraceRule& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_level_, other.trace_level_)
+ && ::protozero::internal::gen_helpers::EqualsField(match_all_packages_, other.match_all_packages_)
+ && ::protozero::internal::gen_helpers::EqualsField(match_any_packages_, other.match_any_packages_)
+ && ::protozero::internal::gen_helpers::EqualsField(match_secure_, other.match_secure_)
+ && ::protozero::internal::gen_helpers::EqualsField(match_ime_connection_active_, other.match_ime_connection_active_);
+}
+
+bool AndroidInputEventConfig_TraceRule::ParseFromArray(const void* raw, size_t size) {
+ match_all_packages_.clear();
+ match_any_packages_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_level */:
+ field.get(&trace_level_);
+ break;
+ case 2 /* match_all_packages */:
+ match_all_packages_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &match_all_packages_.back());
+ break;
+ case 3 /* match_any_packages */:
+ match_any_packages_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &match_any_packages_.back());
+ break;
+ case 4 /* match_secure */:
+ field.get(&match_secure_);
+ break;
+ case 5 /* match_ime_connection_active */:
+ field.get(&match_ime_connection_active_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidInputEventConfig_TraceRule::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidInputEventConfig_TraceRule::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidInputEventConfig_TraceRule::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_level
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, trace_level_, msg);
+ }
+
+ // Field 2: match_all_packages
+ for (auto& it : match_all_packages_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 3: match_any_packages
+ for (auto& it : match_any_packages_) {
+ ::protozero::internal::gen_helpers::SerializeString(3, it, msg);
+ }
+
+ // Field 4: match_secure
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, match_secure_, msg);
+ }
+
+ // Field 5: match_ime_connection_active
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, match_ime_connection_active_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_log_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_log_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_log_constants.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidLogConfig::AndroidLogConfig() = default;
+AndroidLogConfig::~AndroidLogConfig() = default;
+AndroidLogConfig::AndroidLogConfig(const AndroidLogConfig&) = default;
+AndroidLogConfig& AndroidLogConfig::operator=(const AndroidLogConfig&) = default;
+AndroidLogConfig::AndroidLogConfig(AndroidLogConfig&&) noexcept = default;
+AndroidLogConfig& AndroidLogConfig::operator=(AndroidLogConfig&&) = default;
+
+bool AndroidLogConfig::operator==(const AndroidLogConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(log_ids_, other.log_ids_)
+ && ::protozero::internal::gen_helpers::EqualsField(min_prio_, other.min_prio_)
+ && ::protozero::internal::gen_helpers::EqualsField(filter_tags_, other.filter_tags_);
+}
+
+bool AndroidLogConfig::ParseFromArray(const void* raw, size_t size) {
+ log_ids_.clear();
+ filter_tags_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* log_ids */:
+ log_ids_.emplace_back();
+ field.get(&log_ids_.back());
+ break;
+ case 3 /* min_prio */:
+ field.get(&min_prio_);
+ break;
+ case 4 /* filter_tags */:
+ filter_tags_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &filter_tags_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidLogConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidLogConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidLogConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: log_ids
+ for (auto& it : log_ids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ // Field 3: min_prio
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, min_prio_, msg);
+ }
+
+ // Field 4: filter_tags
+ for (auto& it : filter_tags_) {
+ ::protozero::internal::gen_helpers::SerializeString(4, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_polled_state_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_polled_state_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidPolledStateConfig::AndroidPolledStateConfig() = default;
+AndroidPolledStateConfig::~AndroidPolledStateConfig() = default;
+AndroidPolledStateConfig::AndroidPolledStateConfig(const AndroidPolledStateConfig&) = default;
+AndroidPolledStateConfig& AndroidPolledStateConfig::operator=(const AndroidPolledStateConfig&) = default;
+AndroidPolledStateConfig::AndroidPolledStateConfig(AndroidPolledStateConfig&&) noexcept = default;
+AndroidPolledStateConfig& AndroidPolledStateConfig::operator=(AndroidPolledStateConfig&&) = default;
+
+bool AndroidPolledStateConfig::operator==(const AndroidPolledStateConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(poll_ms_, other.poll_ms_);
+}
+
+bool AndroidPolledStateConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* poll_ms */:
+ field.get(&poll_ms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidPolledStateConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidPolledStateConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidPolledStateConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: poll_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, poll_ms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidSdkSyspropGuardConfig::AndroidSdkSyspropGuardConfig() = default;
+AndroidSdkSyspropGuardConfig::~AndroidSdkSyspropGuardConfig() = default;
+AndroidSdkSyspropGuardConfig::AndroidSdkSyspropGuardConfig(const AndroidSdkSyspropGuardConfig&) = default;
+AndroidSdkSyspropGuardConfig& AndroidSdkSyspropGuardConfig::operator=(const AndroidSdkSyspropGuardConfig&) = default;
+AndroidSdkSyspropGuardConfig::AndroidSdkSyspropGuardConfig(AndroidSdkSyspropGuardConfig&&) noexcept = default;
+AndroidSdkSyspropGuardConfig& AndroidSdkSyspropGuardConfig::operator=(AndroidSdkSyspropGuardConfig&&) = default;
+
+bool AndroidSdkSyspropGuardConfig::operator==(const AndroidSdkSyspropGuardConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(surfaceflinger_skia_track_events_, other.surfaceflinger_skia_track_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(hwui_skia_track_events_, other.hwui_skia_track_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(hwui_package_name_filter_, other.hwui_package_name_filter_);
+}
+
+bool AndroidSdkSyspropGuardConfig::ParseFromArray(const void* raw, size_t size) {
+ hwui_package_name_filter_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* surfaceflinger_skia_track_events */:
+ field.get(&surfaceflinger_skia_track_events_);
+ break;
+ case 2 /* hwui_skia_track_events */:
+ field.get(&hwui_skia_track_events_);
+ break;
+ case 3 /* hwui_package_name_filter */:
+ hwui_package_name_filter_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &hwui_package_name_filter_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidSdkSyspropGuardConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidSdkSyspropGuardConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidSdkSyspropGuardConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: surfaceflinger_skia_track_events
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, surfaceflinger_skia_track_events_, msg);
+ }
+
+ // Field 2: hwui_skia_track_events
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, hwui_skia_track_events_, msg);
+ }
+
+ // Field 3: hwui_package_name_filter
+ for (auto& it : hwui_package_name_filter_) {
+ ::protozero::internal::gen_helpers::SerializeString(3, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_system_property_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_system_property_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidSystemPropertyConfig::AndroidSystemPropertyConfig() = default;
+AndroidSystemPropertyConfig::~AndroidSystemPropertyConfig() = default;
+AndroidSystemPropertyConfig::AndroidSystemPropertyConfig(const AndroidSystemPropertyConfig&) = default;
+AndroidSystemPropertyConfig& AndroidSystemPropertyConfig::operator=(const AndroidSystemPropertyConfig&) = default;
+AndroidSystemPropertyConfig::AndroidSystemPropertyConfig(AndroidSystemPropertyConfig&&) noexcept = default;
+AndroidSystemPropertyConfig& AndroidSystemPropertyConfig::operator=(AndroidSystemPropertyConfig&&) = default;
+
+bool AndroidSystemPropertyConfig::operator==(const AndroidSystemPropertyConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(poll_ms_, other.poll_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(property_name_, other.property_name_);
+}
+
+bool AndroidSystemPropertyConfig::ParseFromArray(const void* raw, size_t size) {
+ property_name_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* poll_ms */:
+ field.get(&poll_ms_);
+ break;
+ case 2 /* property_name */:
+ property_name_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &property_name_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidSystemPropertyConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidSystemPropertyConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidSystemPropertyConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: poll_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, poll_ms_, msg);
+ }
+
+ // Field 2: property_name
+ for (auto& it : property_name_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/network_trace_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/network_trace_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+NetworkPacketTraceConfig::NetworkPacketTraceConfig() = default;
+NetworkPacketTraceConfig::~NetworkPacketTraceConfig() = default;
+NetworkPacketTraceConfig::NetworkPacketTraceConfig(const NetworkPacketTraceConfig&) = default;
+NetworkPacketTraceConfig& NetworkPacketTraceConfig::operator=(const NetworkPacketTraceConfig&) = default;
+NetworkPacketTraceConfig::NetworkPacketTraceConfig(NetworkPacketTraceConfig&&) noexcept = default;
+NetworkPacketTraceConfig& NetworkPacketTraceConfig::operator=(NetworkPacketTraceConfig&&) = default;
+
+bool NetworkPacketTraceConfig::operator==(const NetworkPacketTraceConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(poll_ms_, other.poll_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(aggregation_threshold_, other.aggregation_threshold_)
+ && ::protozero::internal::gen_helpers::EqualsField(intern_limit_, other.intern_limit_)
+ && ::protozero::internal::gen_helpers::EqualsField(drop_local_port_, other.drop_local_port_)
+ && ::protozero::internal::gen_helpers::EqualsField(drop_remote_port_, other.drop_remote_port_)
+ && ::protozero::internal::gen_helpers::EqualsField(drop_tcp_flags_, other.drop_tcp_flags_);
+}
+
+bool NetworkPacketTraceConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* poll_ms */:
+ field.get(&poll_ms_);
+ break;
+ case 2 /* aggregation_threshold */:
+ field.get(&aggregation_threshold_);
+ break;
+ case 3 /* intern_limit */:
+ field.get(&intern_limit_);
+ break;
+ case 4 /* drop_local_port */:
+ field.get(&drop_local_port_);
+ break;
+ case 5 /* drop_remote_port */:
+ field.get(&drop_remote_port_);
+ break;
+ case 6 /* drop_tcp_flags */:
+ field.get(&drop_tcp_flags_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string NetworkPacketTraceConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> NetworkPacketTraceConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void NetworkPacketTraceConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: poll_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, poll_ms_, msg);
+ }
+
+ // Field 2: aggregation_threshold
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, aggregation_threshold_, msg);
+ }
+
+ // Field 3: intern_limit
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, intern_limit_, msg);
+ }
+
+ // Field 4: drop_local_port
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, drop_local_port_, msg);
+ }
+
+ // Field 5: drop_remote_port
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, drop_remote_port_, msg);
+ }
+
+ // Field 6: drop_tcp_flags
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(6, drop_tcp_flags_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/packages_list_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/packages_list_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+PackagesListConfig::PackagesListConfig() = default;
+PackagesListConfig::~PackagesListConfig() = default;
+PackagesListConfig::PackagesListConfig(const PackagesListConfig&) = default;
+PackagesListConfig& PackagesListConfig::operator=(const PackagesListConfig&) = default;
+PackagesListConfig::PackagesListConfig(PackagesListConfig&&) noexcept = default;
+PackagesListConfig& PackagesListConfig::operator=(PackagesListConfig&&) = default;
+
+bool PackagesListConfig::operator==(const PackagesListConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(package_name_filter_, other.package_name_filter_);
+}
+
+bool PackagesListConfig::ParseFromArray(const void* raw, size_t size) {
+ package_name_filter_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* package_name_filter */:
+ package_name_filter_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &package_name_filter_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PackagesListConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PackagesListConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PackagesListConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: package_name_filter
+ for (auto& it : package_name_filter_) {
+ ::protozero::internal::gen_helpers::SerializeString(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/protolog_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/protolog_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/protolog_common.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ProtoLogGroup::ProtoLogGroup() = default;
+ProtoLogGroup::~ProtoLogGroup() = default;
+ProtoLogGroup::ProtoLogGroup(const ProtoLogGroup&) = default;
+ProtoLogGroup& ProtoLogGroup::operator=(const ProtoLogGroup&) = default;
+ProtoLogGroup::ProtoLogGroup(ProtoLogGroup&&) noexcept = default;
+ProtoLogGroup& ProtoLogGroup::operator=(ProtoLogGroup&&) = default;
+
+bool ProtoLogGroup::operator==(const ProtoLogGroup& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(group_name_, other.group_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(log_from_, other.log_from_)
+ && ::protozero::internal::gen_helpers::EqualsField(collect_stacktrace_, other.collect_stacktrace_);
+}
+
+bool ProtoLogGroup::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* group_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &group_name_);
+ break;
+ case 2 /* log_from */:
+ field.get(&log_from_);
+ break;
+ case 3 /* collect_stacktrace */:
+ field.get(&collect_stacktrace_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ProtoLogGroup::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ProtoLogGroup::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ProtoLogGroup::Serialize(::protozero::Message* msg) const {
+ // Field 1: group_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, group_name_, msg);
+ }
+
+ // Field 2: log_from
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, log_from_, msg);
+ }
+
+ // Field 3: collect_stacktrace
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, collect_stacktrace_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ProtoLogConfig::ProtoLogConfig() = default;
+ProtoLogConfig::~ProtoLogConfig() = default;
+ProtoLogConfig::ProtoLogConfig(const ProtoLogConfig&) = default;
+ProtoLogConfig& ProtoLogConfig::operator=(const ProtoLogConfig&) = default;
+ProtoLogConfig::ProtoLogConfig(ProtoLogConfig&&) noexcept = default;
+ProtoLogConfig& ProtoLogConfig::operator=(ProtoLogConfig&&) = default;
+
+bool ProtoLogConfig::operator==(const ProtoLogConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(group_overrides_, other.group_overrides_)
+ && ::protozero::internal::gen_helpers::EqualsField(tracing_mode_, other.tracing_mode_);
+}
+
+int ProtoLogConfig::group_overrides_size() const { return static_cast<int>(group_overrides_.size()); }
+void ProtoLogConfig::clear_group_overrides() { group_overrides_.clear(); }
+ProtoLogGroup* ProtoLogConfig::add_group_overrides() { group_overrides_.emplace_back(); return &group_overrides_.back(); }
+bool ProtoLogConfig::ParseFromArray(const void* raw, size_t size) {
+ group_overrides_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* group_overrides */:
+ group_overrides_.emplace_back();
+ group_overrides_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* tracing_mode */:
+ field.get(&tracing_mode_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ProtoLogConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ProtoLogConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ProtoLogConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: group_overrides
+ for (auto& it : group_overrides_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: tracing_mode
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, tracing_mode_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/surfaceflinger_layers_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_layers_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+SurfaceFlingerLayersConfig::SurfaceFlingerLayersConfig() = default;
+SurfaceFlingerLayersConfig::~SurfaceFlingerLayersConfig() = default;
+SurfaceFlingerLayersConfig::SurfaceFlingerLayersConfig(const SurfaceFlingerLayersConfig&) = default;
+SurfaceFlingerLayersConfig& SurfaceFlingerLayersConfig::operator=(const SurfaceFlingerLayersConfig&) = default;
+SurfaceFlingerLayersConfig::SurfaceFlingerLayersConfig(SurfaceFlingerLayersConfig&&) noexcept = default;
+SurfaceFlingerLayersConfig& SurfaceFlingerLayersConfig::operator=(SurfaceFlingerLayersConfig&&) = default;
+
+bool SurfaceFlingerLayersConfig::operator==(const SurfaceFlingerLayersConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(mode_, other.mode_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_flags_, other.trace_flags_);
+}
+
+bool SurfaceFlingerLayersConfig::ParseFromArray(const void* raw, size_t size) {
+ trace_flags_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* mode */:
+ field.get(&mode_);
+ break;
+ case 2 /* trace_flags */:
+ trace_flags_.emplace_back();
+ field.get(&trace_flags_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SurfaceFlingerLayersConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SurfaceFlingerLayersConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SurfaceFlingerLayersConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: mode
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, mode_, msg);
+ }
+
+ // Field 2: trace_flags
+ for (auto& it : trace_flags_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/surfaceflinger_transactions_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+SurfaceFlingerTransactionsConfig::SurfaceFlingerTransactionsConfig() = default;
+SurfaceFlingerTransactionsConfig::~SurfaceFlingerTransactionsConfig() = default;
+SurfaceFlingerTransactionsConfig::SurfaceFlingerTransactionsConfig(const SurfaceFlingerTransactionsConfig&) = default;
+SurfaceFlingerTransactionsConfig& SurfaceFlingerTransactionsConfig::operator=(const SurfaceFlingerTransactionsConfig&) = default;
+SurfaceFlingerTransactionsConfig::SurfaceFlingerTransactionsConfig(SurfaceFlingerTransactionsConfig&&) noexcept = default;
+SurfaceFlingerTransactionsConfig& SurfaceFlingerTransactionsConfig::operator=(SurfaceFlingerTransactionsConfig&&) = default;
+
+bool SurfaceFlingerTransactionsConfig::operator==(const SurfaceFlingerTransactionsConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(mode_, other.mode_);
+}
+
+bool SurfaceFlingerTransactionsConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* mode */:
+ field.get(&mode_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SurfaceFlingerTransactionsConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SurfaceFlingerTransactionsConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SurfaceFlingerTransactionsConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: mode
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, mode_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/ftrace/ftrace_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+FtraceConfig::FtraceConfig() = default;
+FtraceConfig::~FtraceConfig() = default;
+FtraceConfig::FtraceConfig(const FtraceConfig&) = default;
+FtraceConfig& FtraceConfig::operator=(const FtraceConfig&) = default;
+FtraceConfig::FtraceConfig(FtraceConfig&&) noexcept = default;
+FtraceConfig& FtraceConfig::operator=(FtraceConfig&&) = default;
+
+bool FtraceConfig::operator==(const FtraceConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(ftrace_events_, other.ftrace_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(atrace_categories_, other.atrace_categories_)
+ && ::protozero::internal::gen_helpers::EqualsField(atrace_apps_, other.atrace_apps_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffer_size_kb_, other.buffer_size_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(drain_period_ms_, other.drain_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(drain_buffer_percent_, other.drain_buffer_percent_)
+ && ::protozero::internal::gen_helpers::EqualsField(compact_sched_, other.compact_sched_)
+ && ::protozero::internal::gen_helpers::EqualsField(print_filter_, other.print_filter_)
+ && ::protozero::internal::gen_helpers::EqualsField(symbolize_ksyms_, other.symbolize_ksyms_)
+ && ::protozero::internal::gen_helpers::EqualsField(ksyms_mem_policy_, other.ksyms_mem_policy_)
+ && ::protozero::internal::gen_helpers::EqualsField(initialize_ksyms_synchronously_for_testing_, other.initialize_ksyms_synchronously_for_testing_)
+ && ::protozero::internal::gen_helpers::EqualsField(throttle_rss_stat_, other.throttle_rss_stat_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_generic_events_, other.disable_generic_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(syscall_events_, other.syscall_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(enable_function_graph_, other.enable_function_graph_)
+ && ::protozero::internal::gen_helpers::EqualsField(function_filters_, other.function_filters_)
+ && ::protozero::internal::gen_helpers::EqualsField(function_graph_roots_, other.function_graph_roots_)
+ && ::protozero::internal::gen_helpers::EqualsField(preserve_ftrace_buffer_, other.preserve_ftrace_buffer_)
+ && ::protozero::internal::gen_helpers::EqualsField(use_monotonic_raw_clock_, other.use_monotonic_raw_clock_)
+ && ::protozero::internal::gen_helpers::EqualsField(instance_name_, other.instance_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffer_size_lower_bound_, other.buffer_size_lower_bound_);
+}
+
+bool FtraceConfig::ParseFromArray(const void* raw, size_t size) {
+ ftrace_events_.clear();
+ atrace_categories_.clear();
+ atrace_apps_.clear();
+ syscall_events_.clear();
+ function_filters_.clear();
+ function_graph_roots_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* ftrace_events */:
+ ftrace_events_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &ftrace_events_.back());
+ break;
+ case 2 /* atrace_categories */:
+ atrace_categories_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &atrace_categories_.back());
+ break;
+ case 3 /* atrace_apps */:
+ atrace_apps_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &atrace_apps_.back());
+ break;
+ case 10 /* buffer_size_kb */:
+ field.get(&buffer_size_kb_);
+ break;
+ case 11 /* drain_period_ms */:
+ field.get(&drain_period_ms_);
+ break;
+ case 26 /* drain_buffer_percent */:
+ field.get(&drain_buffer_percent_);
+ break;
+ case 12 /* compact_sched */:
+ (*compact_sched_).ParseFromArray(field.data(), field.size());
+ break;
+ case 22 /* print_filter */:
+ (*print_filter_).ParseFromArray(field.data(), field.size());
+ break;
+ case 13 /* symbolize_ksyms */:
+ field.get(&symbolize_ksyms_);
+ break;
+ case 17 /* ksyms_mem_policy */:
+ field.get(&ksyms_mem_policy_);
+ break;
+ case 14 /* initialize_ksyms_synchronously_for_testing */:
+ field.get(&initialize_ksyms_synchronously_for_testing_);
+ break;
+ case 15 /* throttle_rss_stat */:
+ field.get(&throttle_rss_stat_);
+ break;
+ case 16 /* disable_generic_events */:
+ field.get(&disable_generic_events_);
+ break;
+ case 18 /* syscall_events */:
+ syscall_events_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &syscall_events_.back());
+ break;
+ case 19 /* enable_function_graph */:
+ field.get(&enable_function_graph_);
+ break;
+ case 20 /* function_filters */:
+ function_filters_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &function_filters_.back());
+ break;
+ case 21 /* function_graph_roots */:
+ function_graph_roots_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &function_graph_roots_.back());
+ break;
+ case 23 /* preserve_ftrace_buffer */:
+ field.get(&preserve_ftrace_buffer_);
+ break;
+ case 24 /* use_monotonic_raw_clock */:
+ field.get(&use_monotonic_raw_clock_);
+ break;
+ case 25 /* instance_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &instance_name_);
+ break;
+ case 27 /* buffer_size_lower_bound */:
+ field.get(&buffer_size_lower_bound_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FtraceConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FtraceConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FtraceConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: ftrace_events
+ for (auto& it : ftrace_events_) {
+ ::protozero::internal::gen_helpers::SerializeString(1, it, msg);
+ }
+
+ // Field 2: atrace_categories
+ for (auto& it : atrace_categories_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 3: atrace_apps
+ for (auto& it : atrace_apps_) {
+ ::protozero::internal::gen_helpers::SerializeString(3, it, msg);
+ }
+
+ // Field 10: buffer_size_kb
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, buffer_size_kb_, msg);
+ }
+
+ // Field 11: drain_period_ms
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, drain_period_ms_, msg);
+ }
+
+ // Field 26: drain_buffer_percent
+ if (_has_field_[26]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(26, drain_buffer_percent_, msg);
+ }
+
+ // Field 12: compact_sched
+ if (_has_field_[12]) {
+ (*compact_sched_).Serialize(msg->BeginNestedMessage<::protozero::Message>(12));
+ }
+
+ // Field 22: print_filter
+ if (_has_field_[22]) {
+ (*print_filter_).Serialize(msg->BeginNestedMessage<::protozero::Message>(22));
+ }
+
+ // Field 13: symbolize_ksyms
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(13, symbolize_ksyms_, msg);
+ }
+
+ // Field 17: ksyms_mem_policy
+ if (_has_field_[17]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, ksyms_mem_policy_, msg);
+ }
+
+ // Field 14: initialize_ksyms_synchronously_for_testing
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(14, initialize_ksyms_synchronously_for_testing_, msg);
+ }
+
+ // Field 15: throttle_rss_stat
+ if (_has_field_[15]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(15, throttle_rss_stat_, msg);
+ }
+
+ // Field 16: disable_generic_events
+ if (_has_field_[16]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(16, disable_generic_events_, msg);
+ }
+
+ // Field 18: syscall_events
+ for (auto& it : syscall_events_) {
+ ::protozero::internal::gen_helpers::SerializeString(18, it, msg);
+ }
+
+ // Field 19: enable_function_graph
+ if (_has_field_[19]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(19, enable_function_graph_, msg);
+ }
+
+ // Field 20: function_filters
+ for (auto& it : function_filters_) {
+ ::protozero::internal::gen_helpers::SerializeString(20, it, msg);
+ }
+
+ // Field 21: function_graph_roots
+ for (auto& it : function_graph_roots_) {
+ ::protozero::internal::gen_helpers::SerializeString(21, it, msg);
+ }
+
+ // Field 23: preserve_ftrace_buffer
+ if (_has_field_[23]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(23, preserve_ftrace_buffer_, msg);
+ }
+
+ // Field 24: use_monotonic_raw_clock
+ if (_has_field_[24]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(24, use_monotonic_raw_clock_, msg);
+ }
+
+ // Field 25: instance_name
+ if (_has_field_[25]) {
+ ::protozero::internal::gen_helpers::SerializeString(25, instance_name_, msg);
+ }
+
+ // Field 27: buffer_size_lower_bound
+ if (_has_field_[27]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(27, buffer_size_lower_bound_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FtraceConfig_PrintFilter::FtraceConfig_PrintFilter() = default;
+FtraceConfig_PrintFilter::~FtraceConfig_PrintFilter() = default;
+FtraceConfig_PrintFilter::FtraceConfig_PrintFilter(const FtraceConfig_PrintFilter&) = default;
+FtraceConfig_PrintFilter& FtraceConfig_PrintFilter::operator=(const FtraceConfig_PrintFilter&) = default;
+FtraceConfig_PrintFilter::FtraceConfig_PrintFilter(FtraceConfig_PrintFilter&&) noexcept = default;
+FtraceConfig_PrintFilter& FtraceConfig_PrintFilter::operator=(FtraceConfig_PrintFilter&&) = default;
+
+bool FtraceConfig_PrintFilter::operator==(const FtraceConfig_PrintFilter& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(rules_, other.rules_);
+}
+
+int FtraceConfig_PrintFilter::rules_size() const { return static_cast<int>(rules_.size()); }
+void FtraceConfig_PrintFilter::clear_rules() { rules_.clear(); }
+FtraceConfig_PrintFilter_Rule* FtraceConfig_PrintFilter::add_rules() { rules_.emplace_back(); return &rules_.back(); }
+bool FtraceConfig_PrintFilter::ParseFromArray(const void* raw, size_t size) {
+ rules_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* rules */:
+ rules_.emplace_back();
+ rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FtraceConfig_PrintFilter::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FtraceConfig_PrintFilter::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FtraceConfig_PrintFilter::Serialize(::protozero::Message* msg) const {
+ // Field 1: rules
+ for (auto& it : rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FtraceConfig_PrintFilter_Rule::FtraceConfig_PrintFilter_Rule() = default;
+FtraceConfig_PrintFilter_Rule::~FtraceConfig_PrintFilter_Rule() = default;
+FtraceConfig_PrintFilter_Rule::FtraceConfig_PrintFilter_Rule(const FtraceConfig_PrintFilter_Rule&) = default;
+FtraceConfig_PrintFilter_Rule& FtraceConfig_PrintFilter_Rule::operator=(const FtraceConfig_PrintFilter_Rule&) = default;
+FtraceConfig_PrintFilter_Rule::FtraceConfig_PrintFilter_Rule(FtraceConfig_PrintFilter_Rule&&) noexcept = default;
+FtraceConfig_PrintFilter_Rule& FtraceConfig_PrintFilter_Rule::operator=(FtraceConfig_PrintFilter_Rule&&) = default;
+
+bool FtraceConfig_PrintFilter_Rule::operator==(const FtraceConfig_PrintFilter_Rule& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(prefix_, other.prefix_)
+ && ::protozero::internal::gen_helpers::EqualsField(atrace_msg_, other.atrace_msg_)
+ && ::protozero::internal::gen_helpers::EqualsField(allow_, other.allow_);
+}
+
+bool FtraceConfig_PrintFilter_Rule::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* prefix */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &prefix_);
+ break;
+ case 3 /* atrace_msg */:
+ (*atrace_msg_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* allow */:
+ field.get(&allow_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FtraceConfig_PrintFilter_Rule::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FtraceConfig_PrintFilter_Rule::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FtraceConfig_PrintFilter_Rule::Serialize(::protozero::Message* msg) const {
+ // Field 1: prefix
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, prefix_, msg);
+ }
+
+ // Field 3: atrace_msg
+ if (_has_field_[3]) {
+ (*atrace_msg_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 2: allow
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, allow_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FtraceConfig_PrintFilter_Rule_AtraceMessage::FtraceConfig_PrintFilter_Rule_AtraceMessage() = default;
+FtraceConfig_PrintFilter_Rule_AtraceMessage::~FtraceConfig_PrintFilter_Rule_AtraceMessage() = default;
+FtraceConfig_PrintFilter_Rule_AtraceMessage::FtraceConfig_PrintFilter_Rule_AtraceMessage(const FtraceConfig_PrintFilter_Rule_AtraceMessage&) = default;
+FtraceConfig_PrintFilter_Rule_AtraceMessage& FtraceConfig_PrintFilter_Rule_AtraceMessage::operator=(const FtraceConfig_PrintFilter_Rule_AtraceMessage&) = default;
+FtraceConfig_PrintFilter_Rule_AtraceMessage::FtraceConfig_PrintFilter_Rule_AtraceMessage(FtraceConfig_PrintFilter_Rule_AtraceMessage&&) noexcept = default;
+FtraceConfig_PrintFilter_Rule_AtraceMessage& FtraceConfig_PrintFilter_Rule_AtraceMessage::operator=(FtraceConfig_PrintFilter_Rule_AtraceMessage&&) = default;
+
+bool FtraceConfig_PrintFilter_Rule_AtraceMessage::operator==(const FtraceConfig_PrintFilter_Rule_AtraceMessage& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_, other.type_)
+ && ::protozero::internal::gen_helpers::EqualsField(prefix_, other.prefix_);
+}
+
+bool FtraceConfig_PrintFilter_Rule_AtraceMessage::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* type */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &type_);
+ break;
+ case 2 /* prefix */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &prefix_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FtraceConfig_PrintFilter_Rule_AtraceMessage::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FtraceConfig_PrintFilter_Rule_AtraceMessage::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FtraceConfig_PrintFilter_Rule_AtraceMessage::Serialize(::protozero::Message* msg) const {
+ // Field 1: type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, type_, msg);
+ }
+
+ // Field 2: prefix
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, prefix_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FtraceConfig_CompactSchedConfig::FtraceConfig_CompactSchedConfig() = default;
+FtraceConfig_CompactSchedConfig::~FtraceConfig_CompactSchedConfig() = default;
+FtraceConfig_CompactSchedConfig::FtraceConfig_CompactSchedConfig(const FtraceConfig_CompactSchedConfig&) = default;
+FtraceConfig_CompactSchedConfig& FtraceConfig_CompactSchedConfig::operator=(const FtraceConfig_CompactSchedConfig&) = default;
+FtraceConfig_CompactSchedConfig::FtraceConfig_CompactSchedConfig(FtraceConfig_CompactSchedConfig&&) noexcept = default;
+FtraceConfig_CompactSchedConfig& FtraceConfig_CompactSchedConfig::operator=(FtraceConfig_CompactSchedConfig&&) = default;
+
+bool FtraceConfig_CompactSchedConfig::operator==(const FtraceConfig_CompactSchedConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(enabled_, other.enabled_);
+}
+
+bool FtraceConfig_CompactSchedConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* enabled */:
+ field.get(&enabled_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FtraceConfig_CompactSchedConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FtraceConfig_CompactSchedConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FtraceConfig_CompactSchedConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: enabled
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, enabled_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/gpu/gpu_counter_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/gpu_counter_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+GpuCounterConfig::GpuCounterConfig() = default;
+GpuCounterConfig::~GpuCounterConfig() = default;
+GpuCounterConfig::GpuCounterConfig(const GpuCounterConfig&) = default;
+GpuCounterConfig& GpuCounterConfig::operator=(const GpuCounterConfig&) = default;
+GpuCounterConfig::GpuCounterConfig(GpuCounterConfig&&) noexcept = default;
+GpuCounterConfig& GpuCounterConfig::operator=(GpuCounterConfig&&) = default;
+
+bool GpuCounterConfig::operator==(const GpuCounterConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(counter_period_ns_, other.counter_period_ns_)
+ && ::protozero::internal::gen_helpers::EqualsField(counter_ids_, other.counter_ids_)
+ && ::protozero::internal::gen_helpers::EqualsField(instrumented_sampling_, other.instrumented_sampling_)
+ && ::protozero::internal::gen_helpers::EqualsField(fix_gpu_clock_, other.fix_gpu_clock_);
+}
+
+bool GpuCounterConfig::ParseFromArray(const void* raw, size_t size) {
+ counter_ids_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* counter_period_ns */:
+ field.get(&counter_period_ns_);
+ break;
+ case 2 /* counter_ids */:
+ counter_ids_.emplace_back();
+ field.get(&counter_ids_.back());
+ break;
+ case 3 /* instrumented_sampling */:
+ field.get(&instrumented_sampling_);
+ break;
+ case 4 /* fix_gpu_clock */:
+ field.get(&fix_gpu_clock_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GpuCounterConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GpuCounterConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GpuCounterConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: counter_period_ns
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, counter_period_ns_, msg);
+ }
+
+ // Field 2: counter_ids
+ for (auto& it : counter_ids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ // Field 3: instrumented_sampling
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, instrumented_sampling_, msg);
+ }
+
+ // Field 4: fix_gpu_clock
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, fix_gpu_clock_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/gpu/vulkan_memory_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/vulkan_memory_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+VulkanMemoryConfig::VulkanMemoryConfig() = default;
+VulkanMemoryConfig::~VulkanMemoryConfig() = default;
+VulkanMemoryConfig::VulkanMemoryConfig(const VulkanMemoryConfig&) = default;
+VulkanMemoryConfig& VulkanMemoryConfig::operator=(const VulkanMemoryConfig&) = default;
+VulkanMemoryConfig::VulkanMemoryConfig(VulkanMemoryConfig&&) noexcept = default;
+VulkanMemoryConfig& VulkanMemoryConfig::operator=(VulkanMemoryConfig&&) = default;
+
+bool VulkanMemoryConfig::operator==(const VulkanMemoryConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(track_driver_memory_usage_, other.track_driver_memory_usage_)
+ && ::protozero::internal::gen_helpers::EqualsField(track_device_memory_usage_, other.track_device_memory_usage_);
+}
+
+bool VulkanMemoryConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* track_driver_memory_usage */:
+ field.get(&track_driver_memory_usage_);
+ break;
+ case 2 /* track_device_memory_usage */:
+ field.get(&track_device_memory_usage_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string VulkanMemoryConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> VulkanMemoryConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void VulkanMemoryConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: track_driver_memory_usage
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, track_driver_memory_usage_, msg);
+ }
+
+ // Field 2: track_device_memory_usage
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, track_device_memory_usage_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/inode_file/inode_file_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/inode_file/inode_file_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+InodeFileConfig::InodeFileConfig() = default;
+InodeFileConfig::~InodeFileConfig() = default;
+InodeFileConfig::InodeFileConfig(const InodeFileConfig&) = default;
+InodeFileConfig& InodeFileConfig::operator=(const InodeFileConfig&) = default;
+InodeFileConfig::InodeFileConfig(InodeFileConfig&&) noexcept = default;
+InodeFileConfig& InodeFileConfig::operator=(InodeFileConfig&&) = default;
+
+bool InodeFileConfig::operator==(const InodeFileConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_interval_ms_, other.scan_interval_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_delay_ms_, other.scan_delay_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_batch_size_, other.scan_batch_size_)
+ && ::protozero::internal::gen_helpers::EqualsField(do_not_scan_, other.do_not_scan_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_mount_points_, other.scan_mount_points_)
+ && ::protozero::internal::gen_helpers::EqualsField(mount_point_mapping_, other.mount_point_mapping_);
+}
+
+int InodeFileConfig::mount_point_mapping_size() const { return static_cast<int>(mount_point_mapping_.size()); }
+void InodeFileConfig::clear_mount_point_mapping() { mount_point_mapping_.clear(); }
+InodeFileConfig_MountPointMappingEntry* InodeFileConfig::add_mount_point_mapping() { mount_point_mapping_.emplace_back(); return &mount_point_mapping_.back(); }
+bool InodeFileConfig::ParseFromArray(const void* raw, size_t size) {
+ scan_mount_points_.clear();
+ mount_point_mapping_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* scan_interval_ms */:
+ field.get(&scan_interval_ms_);
+ break;
+ case 2 /* scan_delay_ms */:
+ field.get(&scan_delay_ms_);
+ break;
+ case 3 /* scan_batch_size */:
+ field.get(&scan_batch_size_);
+ break;
+ case 4 /* do_not_scan */:
+ field.get(&do_not_scan_);
+ break;
+ case 5 /* scan_mount_points */:
+ scan_mount_points_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &scan_mount_points_.back());
+ break;
+ case 6 /* mount_point_mapping */:
+ mount_point_mapping_.emplace_back();
+ mount_point_mapping_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string InodeFileConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> InodeFileConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void InodeFileConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: scan_interval_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, scan_interval_ms_, msg);
+ }
+
+ // Field 2: scan_delay_ms
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, scan_delay_ms_, msg);
+ }
+
+ // Field 3: scan_batch_size
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, scan_batch_size_, msg);
+ }
+
+ // Field 4: do_not_scan
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, do_not_scan_, msg);
+ }
+
+ // Field 5: scan_mount_points
+ for (auto& it : scan_mount_points_) {
+ ::protozero::internal::gen_helpers::SerializeString(5, it, msg);
+ }
+
+ // Field 6: mount_point_mapping
+ for (auto& it : mount_point_mapping_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+InodeFileConfig_MountPointMappingEntry::InodeFileConfig_MountPointMappingEntry() = default;
+InodeFileConfig_MountPointMappingEntry::~InodeFileConfig_MountPointMappingEntry() = default;
+InodeFileConfig_MountPointMappingEntry::InodeFileConfig_MountPointMappingEntry(const InodeFileConfig_MountPointMappingEntry&) = default;
+InodeFileConfig_MountPointMappingEntry& InodeFileConfig_MountPointMappingEntry::operator=(const InodeFileConfig_MountPointMappingEntry&) = default;
+InodeFileConfig_MountPointMappingEntry::InodeFileConfig_MountPointMappingEntry(InodeFileConfig_MountPointMappingEntry&&) noexcept = default;
+InodeFileConfig_MountPointMappingEntry& InodeFileConfig_MountPointMappingEntry::operator=(InodeFileConfig_MountPointMappingEntry&&) = default;
+
+bool InodeFileConfig_MountPointMappingEntry::operator==(const InodeFileConfig_MountPointMappingEntry& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(mountpoint_, other.mountpoint_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_roots_, other.scan_roots_);
+}
+
+bool InodeFileConfig_MountPointMappingEntry::ParseFromArray(const void* raw, size_t size) {
+ scan_roots_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* mountpoint */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &mountpoint_);
+ break;
+ case 2 /* scan_roots */:
+ scan_roots_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &scan_roots_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string InodeFileConfig_MountPointMappingEntry::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> InodeFileConfig_MountPointMappingEntry::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void InodeFileConfig_MountPointMappingEntry::Serialize(::protozero::Message* msg) const {
+ // Field 1: mountpoint
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, mountpoint_, msg);
+ }
+
+ // Field 2: scan_roots
+ for (auto& it : scan_roots_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/interceptors/console_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ConsoleConfig::ConsoleConfig() = default;
+ConsoleConfig::~ConsoleConfig() = default;
+ConsoleConfig::ConsoleConfig(const ConsoleConfig&) = default;
+ConsoleConfig& ConsoleConfig::operator=(const ConsoleConfig&) = default;
+ConsoleConfig::ConsoleConfig(ConsoleConfig&&) noexcept = default;
+ConsoleConfig& ConsoleConfig::operator=(ConsoleConfig&&) = default;
+
+bool ConsoleConfig::operator==(const ConsoleConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(output_, other.output_)
+ && ::protozero::internal::gen_helpers::EqualsField(enable_colors_, other.enable_colors_);
+}
+
+bool ConsoleConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* output */:
+ field.get(&output_);
+ break;
+ case 2 /* enable_colors */:
+ field.get(&enable_colors_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ConsoleConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ConsoleConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ConsoleConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: output
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, output_, msg);
+ }
+
+ // Field 2: enable_colors
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, enable_colors_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/power/android_power_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/power/android_power_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+AndroidPowerConfig::AndroidPowerConfig() = default;
+AndroidPowerConfig::~AndroidPowerConfig() = default;
+AndroidPowerConfig::AndroidPowerConfig(const AndroidPowerConfig&) = default;
+AndroidPowerConfig& AndroidPowerConfig::operator=(const AndroidPowerConfig&) = default;
+AndroidPowerConfig::AndroidPowerConfig(AndroidPowerConfig&&) noexcept = default;
+AndroidPowerConfig& AndroidPowerConfig::operator=(AndroidPowerConfig&&) = default;
+
+bool AndroidPowerConfig::operator==(const AndroidPowerConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(battery_poll_ms_, other.battery_poll_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(battery_counters_, other.battery_counters_)
+ && ::protozero::internal::gen_helpers::EqualsField(collect_power_rails_, other.collect_power_rails_)
+ && ::protozero::internal::gen_helpers::EqualsField(collect_energy_estimation_breakdown_, other.collect_energy_estimation_breakdown_)
+ && ::protozero::internal::gen_helpers::EqualsField(collect_entity_state_residency_, other.collect_entity_state_residency_);
+}
+
+bool AndroidPowerConfig::ParseFromArray(const void* raw, size_t size) {
+ battery_counters_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* battery_poll_ms */:
+ field.get(&battery_poll_ms_);
+ break;
+ case 2 /* battery_counters */:
+ battery_counters_.emplace_back();
+ field.get(&battery_counters_.back());
+ break;
+ case 3 /* collect_power_rails */:
+ field.get(&collect_power_rails_);
+ break;
+ case 4 /* collect_energy_estimation_breakdown */:
+ field.get(&collect_energy_estimation_breakdown_);
+ break;
+ case 5 /* collect_entity_state_residency */:
+ field.get(&collect_entity_state_residency_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AndroidPowerConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AndroidPowerConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AndroidPowerConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: battery_poll_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, battery_poll_ms_, msg);
+ }
+
+ // Field 2: battery_counters
+ for (auto& it : battery_counters_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ // Field 3: collect_power_rails
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, collect_power_rails_, msg);
+ }
+
+ // Field 4: collect_energy_estimation_breakdown
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, collect_energy_estimation_breakdown_, msg);
+ }
+
+ // Field 5: collect_entity_state_residency
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, collect_entity_state_residency_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/process_stats/process_stats_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ProcessStatsConfig::ProcessStatsConfig() = default;
+ProcessStatsConfig::~ProcessStatsConfig() = default;
+ProcessStatsConfig::ProcessStatsConfig(const ProcessStatsConfig&) = default;
+ProcessStatsConfig& ProcessStatsConfig::operator=(const ProcessStatsConfig&) = default;
+ProcessStatsConfig::ProcessStatsConfig(ProcessStatsConfig&&) noexcept = default;
+ProcessStatsConfig& ProcessStatsConfig::operator=(ProcessStatsConfig&&) = default;
+
+bool ProcessStatsConfig::operator==(const ProcessStatsConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(quirks_, other.quirks_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_all_processes_on_start_, other.scan_all_processes_on_start_)
+ && ::protozero::internal::gen_helpers::EqualsField(record_thread_names_, other.record_thread_names_)
+ && ::protozero::internal::gen_helpers::EqualsField(proc_stats_poll_ms_, other.proc_stats_poll_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(proc_stats_cache_ttl_ms_, other.proc_stats_cache_ttl_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(resolve_process_fds_, other.resolve_process_fds_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_smaps_rollup_, other.scan_smaps_rollup_)
+ && ::protozero::internal::gen_helpers::EqualsField(record_process_age_, other.record_process_age_)
+ && ::protozero::internal::gen_helpers::EqualsField(record_process_runtime_, other.record_process_runtime_);
+}
+
+bool ProcessStatsConfig::ParseFromArray(const void* raw, size_t size) {
+ quirks_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* quirks */:
+ quirks_.emplace_back();
+ field.get(&quirks_.back());
+ break;
+ case 2 /* scan_all_processes_on_start */:
+ field.get(&scan_all_processes_on_start_);
+ break;
+ case 3 /* record_thread_names */:
+ field.get(&record_thread_names_);
+ break;
+ case 4 /* proc_stats_poll_ms */:
+ field.get(&proc_stats_poll_ms_);
+ break;
+ case 6 /* proc_stats_cache_ttl_ms */:
+ field.get(&proc_stats_cache_ttl_ms_);
+ break;
+ case 9 /* resolve_process_fds */:
+ field.get(&resolve_process_fds_);
+ break;
+ case 10 /* scan_smaps_rollup */:
+ field.get(&scan_smaps_rollup_);
+ break;
+ case 11 /* record_process_age */:
+ field.get(&record_process_age_);
+ break;
+ case 12 /* record_process_runtime */:
+ field.get(&record_process_runtime_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ProcessStatsConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ProcessStatsConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ProcessStatsConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: quirks
+ for (auto& it : quirks_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ // Field 2: scan_all_processes_on_start
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, scan_all_processes_on_start_, msg);
+ }
+
+ // Field 3: record_thread_names
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, record_thread_names_, msg);
+ }
+
+ // Field 4: proc_stats_poll_ms
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, proc_stats_poll_ms_, msg);
+ }
+
+ // Field 6: proc_stats_cache_ttl_ms
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, proc_stats_cache_ttl_ms_, msg);
+ }
+
+ // Field 9: resolve_process_fds
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, resolve_process_fds_, msg);
+ }
+
+ // Field 10: scan_smaps_rollup
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(10, scan_smaps_rollup_, msg);
+ }
+
+ // Field 11: record_process_age
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(11, record_process_age_, msg);
+ }
+
+ // Field 12: record_process_runtime
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(12, record_process_runtime_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/profiling/heapprofd_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+HeapprofdConfig::HeapprofdConfig() = default;
+HeapprofdConfig::~HeapprofdConfig() = default;
+HeapprofdConfig::HeapprofdConfig(const HeapprofdConfig&) = default;
+HeapprofdConfig& HeapprofdConfig::operator=(const HeapprofdConfig&) = default;
+HeapprofdConfig::HeapprofdConfig(HeapprofdConfig&&) noexcept = default;
+HeapprofdConfig& HeapprofdConfig::operator=(HeapprofdConfig&&) = default;
+
+bool HeapprofdConfig::operator==(const HeapprofdConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(sampling_interval_bytes_, other.sampling_interval_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(adaptive_sampling_shmem_threshold_, other.adaptive_sampling_shmem_threshold_)
+ && ::protozero::internal::gen_helpers::EqualsField(adaptive_sampling_max_sampling_interval_bytes_, other.adaptive_sampling_max_sampling_interval_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_cmdline_, other.process_cmdline_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_, other.pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_installed_by_, other.target_installed_by_)
+ && ::protozero::internal::gen_helpers::EqualsField(heaps_, other.heaps_)
+ && ::protozero::internal::gen_helpers::EqualsField(exclude_heaps_, other.exclude_heaps_)
+ && ::protozero::internal::gen_helpers::EqualsField(stream_allocations_, other.stream_allocations_)
+ && ::protozero::internal::gen_helpers::EqualsField(heap_sampling_intervals_, other.heap_sampling_intervals_)
+ && ::protozero::internal::gen_helpers::EqualsField(all_heaps_, other.all_heaps_)
+ && ::protozero::internal::gen_helpers::EqualsField(all_, other.all_)
+ && ::protozero::internal::gen_helpers::EqualsField(min_anonymous_memory_kb_, other.min_anonymous_memory_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_heapprofd_memory_kb_, other.max_heapprofd_memory_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_heapprofd_cpu_secs_, other.max_heapprofd_cpu_secs_)
+ && ::protozero::internal::gen_helpers::EqualsField(skip_symbol_prefix_, other.skip_symbol_prefix_)
+ && ::protozero::internal::gen_helpers::EqualsField(continuous_dump_config_, other.continuous_dump_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(shmem_size_bytes_, other.shmem_size_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(block_client_, other.block_client_)
+ && ::protozero::internal::gen_helpers::EqualsField(block_client_timeout_us_, other.block_client_timeout_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(no_startup_, other.no_startup_)
+ && ::protozero::internal::gen_helpers::EqualsField(no_running_, other.no_running_)
+ && ::protozero::internal::gen_helpers::EqualsField(dump_at_max_, other.dump_at_max_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_fork_teardown_, other.disable_fork_teardown_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_vfork_detection_, other.disable_vfork_detection_);
+}
+
+bool HeapprofdConfig::ParseFromArray(const void* raw, size_t size) {
+ process_cmdline_.clear();
+ pid_.clear();
+ target_installed_by_.clear();
+ heaps_.clear();
+ exclude_heaps_.clear();
+ heap_sampling_intervals_.clear();
+ skip_symbol_prefix_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* sampling_interval_bytes */:
+ field.get(&sampling_interval_bytes_);
+ break;
+ case 24 /* adaptive_sampling_shmem_threshold */:
+ field.get(&adaptive_sampling_shmem_threshold_);
+ break;
+ case 25 /* adaptive_sampling_max_sampling_interval_bytes */:
+ field.get(&adaptive_sampling_max_sampling_interval_bytes_);
+ break;
+ case 2 /* process_cmdline */:
+ process_cmdline_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &process_cmdline_.back());
+ break;
+ case 4 /* pid */:
+ pid_.emplace_back();
+ field.get(&pid_.back());
+ break;
+ case 26 /* target_installed_by */:
+ target_installed_by_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &target_installed_by_.back());
+ break;
+ case 20 /* heaps */:
+ heaps_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &heaps_.back());
+ break;
+ case 27 /* exclude_heaps */:
+ exclude_heaps_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &exclude_heaps_.back());
+ break;
+ case 23 /* stream_allocations */:
+ field.get(&stream_allocations_);
+ break;
+ case 22 /* heap_sampling_intervals */:
+ heap_sampling_intervals_.emplace_back();
+ field.get(&heap_sampling_intervals_.back());
+ break;
+ case 21 /* all_heaps */:
+ field.get(&all_heaps_);
+ break;
+ case 5 /* all */:
+ field.get(&all_);
+ break;
+ case 15 /* min_anonymous_memory_kb */:
+ field.get(&min_anonymous_memory_kb_);
+ break;
+ case 16 /* max_heapprofd_memory_kb */:
+ field.get(&max_heapprofd_memory_kb_);
+ break;
+ case 17 /* max_heapprofd_cpu_secs */:
+ field.get(&max_heapprofd_cpu_secs_);
+ break;
+ case 7 /* skip_symbol_prefix */:
+ skip_symbol_prefix_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &skip_symbol_prefix_.back());
+ break;
+ case 6 /* continuous_dump_config */:
+ (*continuous_dump_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 8 /* shmem_size_bytes */:
+ field.get(&shmem_size_bytes_);
+ break;
+ case 9 /* block_client */:
+ field.get(&block_client_);
+ break;
+ case 14 /* block_client_timeout_us */:
+ field.get(&block_client_timeout_us_);
+ break;
+ case 10 /* no_startup */:
+ field.get(&no_startup_);
+ break;
+ case 11 /* no_running */:
+ field.get(&no_running_);
+ break;
+ case 13 /* dump_at_max */:
+ field.get(&dump_at_max_);
+ break;
+ case 18 /* disable_fork_teardown */:
+ field.get(&disable_fork_teardown_);
+ break;
+ case 19 /* disable_vfork_detection */:
+ field.get(&disable_vfork_detection_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string HeapprofdConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> HeapprofdConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void HeapprofdConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: sampling_interval_bytes
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, sampling_interval_bytes_, msg);
+ }
+
+ // Field 24: adaptive_sampling_shmem_threshold
+ if (_has_field_[24]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(24, adaptive_sampling_shmem_threshold_, msg);
+ }
+
+ // Field 25: adaptive_sampling_max_sampling_interval_bytes
+ if (_has_field_[25]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(25, adaptive_sampling_max_sampling_interval_bytes_, msg);
+ }
+
+ // Field 2: process_cmdline
+ for (auto& it : process_cmdline_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 4: pid
+ for (auto& it : pid_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, it, msg);
+ }
+
+ // Field 26: target_installed_by
+ for (auto& it : target_installed_by_) {
+ ::protozero::internal::gen_helpers::SerializeString(26, it, msg);
+ }
+
+ // Field 20: heaps
+ for (auto& it : heaps_) {
+ ::protozero::internal::gen_helpers::SerializeString(20, it, msg);
+ }
+
+ // Field 27: exclude_heaps
+ for (auto& it : exclude_heaps_) {
+ ::protozero::internal::gen_helpers::SerializeString(27, it, msg);
+ }
+
+ // Field 23: stream_allocations
+ if (_has_field_[23]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(23, stream_allocations_, msg);
+ }
+
+ // Field 22: heap_sampling_intervals
+ for (auto& it : heap_sampling_intervals_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(22, it, msg);
+ }
+
+ // Field 21: all_heaps
+ if (_has_field_[21]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(21, all_heaps_, msg);
+ }
+
+ // Field 5: all
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, all_, msg);
+ }
+
+ // Field 15: min_anonymous_memory_kb
+ if (_has_field_[15]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(15, min_anonymous_memory_kb_, msg);
+ }
+
+ // Field 16: max_heapprofd_memory_kb
+ if (_has_field_[16]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(16, max_heapprofd_memory_kb_, msg);
+ }
+
+ // Field 17: max_heapprofd_cpu_secs
+ if (_has_field_[17]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, max_heapprofd_cpu_secs_, msg);
+ }
+
+ // Field 7: skip_symbol_prefix
+ for (auto& it : skip_symbol_prefix_) {
+ ::protozero::internal::gen_helpers::SerializeString(7, it, msg);
+ }
+
+ // Field 6: continuous_dump_config
+ if (_has_field_[6]) {
+ (*continuous_dump_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 8: shmem_size_bytes
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, shmem_size_bytes_, msg);
+ }
+
+ // Field 9: block_client
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, block_client_, msg);
+ }
+
+ // Field 14: block_client_timeout_us
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(14, block_client_timeout_us_, msg);
+ }
+
+ // Field 10: no_startup
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(10, no_startup_, msg);
+ }
+
+ // Field 11: no_running
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(11, no_running_, msg);
+ }
+
+ // Field 13: dump_at_max
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(13, dump_at_max_, msg);
+ }
+
+ // Field 18: disable_fork_teardown
+ if (_has_field_[18]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(18, disable_fork_teardown_, msg);
+ }
+
+ // Field 19: disable_vfork_detection
+ if (_has_field_[19]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(19, disable_vfork_detection_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+HeapprofdConfig_ContinuousDumpConfig::HeapprofdConfig_ContinuousDumpConfig() = default;
+HeapprofdConfig_ContinuousDumpConfig::~HeapprofdConfig_ContinuousDumpConfig() = default;
+HeapprofdConfig_ContinuousDumpConfig::HeapprofdConfig_ContinuousDumpConfig(const HeapprofdConfig_ContinuousDumpConfig&) = default;
+HeapprofdConfig_ContinuousDumpConfig& HeapprofdConfig_ContinuousDumpConfig::operator=(const HeapprofdConfig_ContinuousDumpConfig&) = default;
+HeapprofdConfig_ContinuousDumpConfig::HeapprofdConfig_ContinuousDumpConfig(HeapprofdConfig_ContinuousDumpConfig&&) noexcept = default;
+HeapprofdConfig_ContinuousDumpConfig& HeapprofdConfig_ContinuousDumpConfig::operator=(HeapprofdConfig_ContinuousDumpConfig&&) = default;
+
+bool HeapprofdConfig_ContinuousDumpConfig::operator==(const HeapprofdConfig_ContinuousDumpConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(dump_phase_ms_, other.dump_phase_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(dump_interval_ms_, other.dump_interval_ms_);
+}
+
+bool HeapprofdConfig_ContinuousDumpConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 5 /* dump_phase_ms */:
+ field.get(&dump_phase_ms_);
+ break;
+ case 6 /* dump_interval_ms */:
+ field.get(&dump_interval_ms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string HeapprofdConfig_ContinuousDumpConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> HeapprofdConfig_ContinuousDumpConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void HeapprofdConfig_ContinuousDumpConfig::Serialize(::protozero::Message* msg) const {
+ // Field 5: dump_phase_ms
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, dump_phase_ms_, msg);
+ }
+
+ // Field 6: dump_interval_ms
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, dump_interval_ms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/profiling/java_hprof_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+JavaHprofConfig::JavaHprofConfig() = default;
+JavaHprofConfig::~JavaHprofConfig() = default;
+JavaHprofConfig::JavaHprofConfig(const JavaHprofConfig&) = default;
+JavaHprofConfig& JavaHprofConfig::operator=(const JavaHprofConfig&) = default;
+JavaHprofConfig::JavaHprofConfig(JavaHprofConfig&&) noexcept = default;
+JavaHprofConfig& JavaHprofConfig::operator=(JavaHprofConfig&&) = default;
+
+bool JavaHprofConfig::operator==(const JavaHprofConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_cmdline_, other.process_cmdline_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_, other.pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_installed_by_, other.target_installed_by_)
+ && ::protozero::internal::gen_helpers::EqualsField(continuous_dump_config_, other.continuous_dump_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(min_anonymous_memory_kb_, other.min_anonymous_memory_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(dump_smaps_, other.dump_smaps_)
+ && ::protozero::internal::gen_helpers::EqualsField(ignored_types_, other.ignored_types_);
+}
+
+bool JavaHprofConfig::ParseFromArray(const void* raw, size_t size) {
+ process_cmdline_.clear();
+ pid_.clear();
+ target_installed_by_.clear();
+ ignored_types_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* process_cmdline */:
+ process_cmdline_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &process_cmdline_.back());
+ break;
+ case 2 /* pid */:
+ pid_.emplace_back();
+ field.get(&pid_.back());
+ break;
+ case 7 /* target_installed_by */:
+ target_installed_by_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &target_installed_by_.back());
+ break;
+ case 3 /* continuous_dump_config */:
+ (*continuous_dump_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 4 /* min_anonymous_memory_kb */:
+ field.get(&min_anonymous_memory_kb_);
+ break;
+ case 5 /* dump_smaps */:
+ field.get(&dump_smaps_);
+ break;
+ case 6 /* ignored_types */:
+ ignored_types_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &ignored_types_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string JavaHprofConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> JavaHprofConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void JavaHprofConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: process_cmdline
+ for (auto& it : process_cmdline_) {
+ ::protozero::internal::gen_helpers::SerializeString(1, it, msg);
+ }
+
+ // Field 2: pid
+ for (auto& it : pid_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ // Field 7: target_installed_by
+ for (auto& it : target_installed_by_) {
+ ::protozero::internal::gen_helpers::SerializeString(7, it, msg);
+ }
+
+ // Field 3: continuous_dump_config
+ if (_has_field_[3]) {
+ (*continuous_dump_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 4: min_anonymous_memory_kb
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, min_anonymous_memory_kb_, msg);
+ }
+
+ // Field 5: dump_smaps
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, dump_smaps_, msg);
+ }
+
+ // Field 6: ignored_types
+ for (auto& it : ignored_types_) {
+ ::protozero::internal::gen_helpers::SerializeString(6, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+JavaHprofConfig_ContinuousDumpConfig::JavaHprofConfig_ContinuousDumpConfig() = default;
+JavaHprofConfig_ContinuousDumpConfig::~JavaHprofConfig_ContinuousDumpConfig() = default;
+JavaHprofConfig_ContinuousDumpConfig::JavaHprofConfig_ContinuousDumpConfig(const JavaHprofConfig_ContinuousDumpConfig&) = default;
+JavaHprofConfig_ContinuousDumpConfig& JavaHprofConfig_ContinuousDumpConfig::operator=(const JavaHprofConfig_ContinuousDumpConfig&) = default;
+JavaHprofConfig_ContinuousDumpConfig::JavaHprofConfig_ContinuousDumpConfig(JavaHprofConfig_ContinuousDumpConfig&&) noexcept = default;
+JavaHprofConfig_ContinuousDumpConfig& JavaHprofConfig_ContinuousDumpConfig::operator=(JavaHprofConfig_ContinuousDumpConfig&&) = default;
+
+bool JavaHprofConfig_ContinuousDumpConfig::operator==(const JavaHprofConfig_ContinuousDumpConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(dump_phase_ms_, other.dump_phase_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(dump_interval_ms_, other.dump_interval_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(scan_pids_only_on_start_, other.scan_pids_only_on_start_);
+}
+
+bool JavaHprofConfig_ContinuousDumpConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* dump_phase_ms */:
+ field.get(&dump_phase_ms_);
+ break;
+ case 2 /* dump_interval_ms */:
+ field.get(&dump_interval_ms_);
+ break;
+ case 3 /* scan_pids_only_on_start */:
+ field.get(&scan_pids_only_on_start_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string JavaHprofConfig_ContinuousDumpConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> JavaHprofConfig_ContinuousDumpConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void JavaHprofConfig_ContinuousDumpConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: dump_phase_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, dump_phase_ms_, msg);
+ }
+
+ // Field 2: dump_interval_ms
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, dump_interval_ms_, msg);
+ }
+
+ // Field 3: scan_pids_only_on_start
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, scan_pids_only_on_start_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/profiling/perf_event_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/perf_events.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+PerfEventConfig::PerfEventConfig() = default;
+PerfEventConfig::~PerfEventConfig() = default;
+PerfEventConfig::PerfEventConfig(const PerfEventConfig&) = default;
+PerfEventConfig& PerfEventConfig::operator=(const PerfEventConfig&) = default;
+PerfEventConfig::PerfEventConfig(PerfEventConfig&&) noexcept = default;
+PerfEventConfig& PerfEventConfig::operator=(PerfEventConfig&&) = default;
+
+bool PerfEventConfig::operator==(const PerfEventConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(timebase_, other.timebase_)
+ && ::protozero::internal::gen_helpers::EqualsField(callstack_sampling_, other.callstack_sampling_)
+ && ::protozero::internal::gen_helpers::EqualsField(ring_buffer_read_period_ms_, other.ring_buffer_read_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(ring_buffer_pages_, other.ring_buffer_pages_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_enqueued_footprint_kb_, other.max_enqueued_footprint_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_daemon_memory_kb_, other.max_daemon_memory_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(remote_descriptor_timeout_ms_, other.remote_descriptor_timeout_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(unwind_state_clear_period_ms_, other.unwind_state_clear_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_installed_by_, other.target_installed_by_)
+ && ::protozero::internal::gen_helpers::EqualsField(all_cpus_, other.all_cpus_)
+ && ::protozero::internal::gen_helpers::EqualsField(sampling_frequency_, other.sampling_frequency_)
+ && ::protozero::internal::gen_helpers::EqualsField(kernel_frames_, other.kernel_frames_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_pid_, other.target_pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_cmdline_, other.target_cmdline_)
+ && ::protozero::internal::gen_helpers::EqualsField(exclude_pid_, other.exclude_pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(exclude_cmdline_, other.exclude_cmdline_)
+ && ::protozero::internal::gen_helpers::EqualsField(additional_cmdline_count_, other.additional_cmdline_count_);
+}
+
+bool PerfEventConfig::ParseFromArray(const void* raw, size_t size) {
+ target_installed_by_.clear();
+ target_pid_.clear();
+ target_cmdline_.clear();
+ exclude_pid_.clear();
+ exclude_cmdline_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 15 /* timebase */:
+ (*timebase_).ParseFromArray(field.data(), field.size());
+ break;
+ case 16 /* callstack_sampling */:
+ (*callstack_sampling_).ParseFromArray(field.data(), field.size());
+ break;
+ case 8 /* ring_buffer_read_period_ms */:
+ field.get(&ring_buffer_read_period_ms_);
+ break;
+ case 3 /* ring_buffer_pages */:
+ field.get(&ring_buffer_pages_);
+ break;
+ case 17 /* max_enqueued_footprint_kb */:
+ field.get(&max_enqueued_footprint_kb_);
+ break;
+ case 13 /* max_daemon_memory_kb */:
+ field.get(&max_daemon_memory_kb_);
+ break;
+ case 9 /* remote_descriptor_timeout_ms */:
+ field.get(&remote_descriptor_timeout_ms_);
+ break;
+ case 10 /* unwind_state_clear_period_ms */:
+ field.get(&unwind_state_clear_period_ms_);
+ break;
+ case 18 /* target_installed_by */:
+ target_installed_by_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &target_installed_by_.back());
+ break;
+ case 1 /* all_cpus */:
+ field.get(&all_cpus_);
+ break;
+ case 2 /* sampling_frequency */:
+ field.get(&sampling_frequency_);
+ break;
+ case 12 /* kernel_frames */:
+ field.get(&kernel_frames_);
+ break;
+ case 4 /* target_pid */:
+ target_pid_.emplace_back();
+ field.get(&target_pid_.back());
+ break;
+ case 5 /* target_cmdline */:
+ target_cmdline_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &target_cmdline_.back());
+ break;
+ case 6 /* exclude_pid */:
+ exclude_pid_.emplace_back();
+ field.get(&exclude_pid_.back());
+ break;
+ case 7 /* exclude_cmdline */:
+ exclude_cmdline_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &exclude_cmdline_.back());
+ break;
+ case 11 /* additional_cmdline_count */:
+ field.get(&additional_cmdline_count_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PerfEventConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PerfEventConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PerfEventConfig::Serialize(::protozero::Message* msg) const {
+ // Field 15: timebase
+ if (_has_field_[15]) {
+ (*timebase_).Serialize(msg->BeginNestedMessage<::protozero::Message>(15));
+ }
+
+ // Field 16: callstack_sampling
+ if (_has_field_[16]) {
+ (*callstack_sampling_).Serialize(msg->BeginNestedMessage<::protozero::Message>(16));
+ }
+
+ // Field 8: ring_buffer_read_period_ms
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, ring_buffer_read_period_ms_, msg);
+ }
+
+ // Field 3: ring_buffer_pages
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, ring_buffer_pages_, msg);
+ }
+
+ // Field 17: max_enqueued_footprint_kb
+ if (_has_field_[17]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, max_enqueued_footprint_kb_, msg);
+ }
+
+ // Field 13: max_daemon_memory_kb
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, max_daemon_memory_kb_, msg);
+ }
+
+ // Field 9: remote_descriptor_timeout_ms
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, remote_descriptor_timeout_ms_, msg);
+ }
+
+ // Field 10: unwind_state_clear_period_ms
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, unwind_state_clear_period_ms_, msg);
+ }
+
+ // Field 18: target_installed_by
+ for (auto& it : target_installed_by_) {
+ ::protozero::internal::gen_helpers::SerializeString(18, it, msg);
+ }
+
+ // Field 1: all_cpus
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, all_cpus_, msg);
+ }
+
+ // Field 2: sampling_frequency
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, sampling_frequency_, msg);
+ }
+
+ // Field 12: kernel_frames
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(12, kernel_frames_, msg);
+ }
+
+ // Field 4: target_pid
+ for (auto& it : target_pid_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, it, msg);
+ }
+
+ // Field 5: target_cmdline
+ for (auto& it : target_cmdline_) {
+ ::protozero::internal::gen_helpers::SerializeString(5, it, msg);
+ }
+
+ // Field 6: exclude_pid
+ for (auto& it : exclude_pid_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, it, msg);
+ }
+
+ // Field 7: exclude_cmdline
+ for (auto& it : exclude_cmdline_) {
+ ::protozero::internal::gen_helpers::SerializeString(7, it, msg);
+ }
+
+ // Field 11: additional_cmdline_count
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, additional_cmdline_count_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+PerfEventConfig_CallstackSampling::PerfEventConfig_CallstackSampling() = default;
+PerfEventConfig_CallstackSampling::~PerfEventConfig_CallstackSampling() = default;
+PerfEventConfig_CallstackSampling::PerfEventConfig_CallstackSampling(const PerfEventConfig_CallstackSampling&) = default;
+PerfEventConfig_CallstackSampling& PerfEventConfig_CallstackSampling::operator=(const PerfEventConfig_CallstackSampling&) = default;
+PerfEventConfig_CallstackSampling::PerfEventConfig_CallstackSampling(PerfEventConfig_CallstackSampling&&) noexcept = default;
+PerfEventConfig_CallstackSampling& PerfEventConfig_CallstackSampling::operator=(PerfEventConfig_CallstackSampling&&) = default;
+
+bool PerfEventConfig_CallstackSampling::operator==(const PerfEventConfig_CallstackSampling& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(scope_, other.scope_)
+ && ::protozero::internal::gen_helpers::EqualsField(kernel_frames_, other.kernel_frames_)
+ && ::protozero::internal::gen_helpers::EqualsField(user_frames_, other.user_frames_);
+}
+
+bool PerfEventConfig_CallstackSampling::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* scope */:
+ (*scope_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* kernel_frames */:
+ field.get(&kernel_frames_);
+ break;
+ case 3 /* user_frames */:
+ field.get(&user_frames_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PerfEventConfig_CallstackSampling::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PerfEventConfig_CallstackSampling::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PerfEventConfig_CallstackSampling::Serialize(::protozero::Message* msg) const {
+ // Field 1: scope
+ if (_has_field_[1]) {
+ (*scope_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: kernel_frames
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, kernel_frames_, msg);
+ }
+
+ // Field 3: user_frames
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, user_frames_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+PerfEventConfig_Scope::PerfEventConfig_Scope() = default;
+PerfEventConfig_Scope::~PerfEventConfig_Scope() = default;
+PerfEventConfig_Scope::PerfEventConfig_Scope(const PerfEventConfig_Scope&) = default;
+PerfEventConfig_Scope& PerfEventConfig_Scope::operator=(const PerfEventConfig_Scope&) = default;
+PerfEventConfig_Scope::PerfEventConfig_Scope(PerfEventConfig_Scope&&) noexcept = default;
+PerfEventConfig_Scope& PerfEventConfig_Scope::operator=(PerfEventConfig_Scope&&) = default;
+
+bool PerfEventConfig_Scope::operator==(const PerfEventConfig_Scope& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_pid_, other.target_pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_cmdline_, other.target_cmdline_)
+ && ::protozero::internal::gen_helpers::EqualsField(exclude_pid_, other.exclude_pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(exclude_cmdline_, other.exclude_cmdline_)
+ && ::protozero::internal::gen_helpers::EqualsField(additional_cmdline_count_, other.additional_cmdline_count_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_shard_count_, other.process_shard_count_);
+}
+
+bool PerfEventConfig_Scope::ParseFromArray(const void* raw, size_t size) {
+ target_pid_.clear();
+ target_cmdline_.clear();
+ exclude_pid_.clear();
+ exclude_cmdline_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* target_pid */:
+ target_pid_.emplace_back();
+ field.get(&target_pid_.back());
+ break;
+ case 2 /* target_cmdline */:
+ target_cmdline_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &target_cmdline_.back());
+ break;
+ case 3 /* exclude_pid */:
+ exclude_pid_.emplace_back();
+ field.get(&exclude_pid_.back());
+ break;
+ case 4 /* exclude_cmdline */:
+ exclude_cmdline_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &exclude_cmdline_.back());
+ break;
+ case 5 /* additional_cmdline_count */:
+ field.get(&additional_cmdline_count_);
+ break;
+ case 6 /* process_shard_count */:
+ field.get(&process_shard_count_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PerfEventConfig_Scope::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PerfEventConfig_Scope::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PerfEventConfig_Scope::Serialize(::protozero::Message* msg) const {
+ // Field 1: target_pid
+ for (auto& it : target_pid_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ // Field 2: target_cmdline
+ for (auto& it : target_cmdline_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 3: exclude_pid
+ for (auto& it : exclude_pid_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, it, msg);
+ }
+
+ // Field 4: exclude_cmdline
+ for (auto& it : exclude_cmdline_) {
+ ::protozero::internal::gen_helpers::SerializeString(4, it, msg);
+ }
+
+ // Field 5: additional_cmdline_count
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, additional_cmdline_count_, msg);
+ }
+
+ // Field 6: process_shard_count
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, process_shard_count_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/statsd/atom_ids.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/atom_ids.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/statsd/statsd_tracing_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/statsd_tracing_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/atom_ids.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+StatsdPullAtomConfig::StatsdPullAtomConfig() = default;
+StatsdPullAtomConfig::~StatsdPullAtomConfig() = default;
+StatsdPullAtomConfig::StatsdPullAtomConfig(const StatsdPullAtomConfig&) = default;
+StatsdPullAtomConfig& StatsdPullAtomConfig::operator=(const StatsdPullAtomConfig&) = default;
+StatsdPullAtomConfig::StatsdPullAtomConfig(StatsdPullAtomConfig&&) noexcept = default;
+StatsdPullAtomConfig& StatsdPullAtomConfig::operator=(StatsdPullAtomConfig&&) = default;
+
+bool StatsdPullAtomConfig::operator==(const StatsdPullAtomConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(pull_atom_id_, other.pull_atom_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(raw_pull_atom_id_, other.raw_pull_atom_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(pull_frequency_ms_, other.pull_frequency_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(packages_, other.packages_);
+}
+
+bool StatsdPullAtomConfig::ParseFromArray(const void* raw, size_t size) {
+ pull_atom_id_.clear();
+ raw_pull_atom_id_.clear();
+ packages_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* pull_atom_id */:
+ pull_atom_id_.emplace_back();
+ field.get(&pull_atom_id_.back());
+ break;
+ case 2 /* raw_pull_atom_id */:
+ raw_pull_atom_id_.emplace_back();
+ field.get(&raw_pull_atom_id_.back());
+ break;
+ case 3 /* pull_frequency_ms */:
+ field.get(&pull_frequency_ms_);
+ break;
+ case 4 /* packages */:
+ packages_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &packages_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string StatsdPullAtomConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> StatsdPullAtomConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void StatsdPullAtomConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: pull_atom_id
+ for (auto& it : pull_atom_id_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ // Field 2: raw_pull_atom_id
+ for (auto& it : raw_pull_atom_id_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ // Field 3: pull_frequency_ms
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, pull_frequency_ms_, msg);
+ }
+
+ // Field 4: packages
+ for (auto& it : packages_) {
+ ::protozero::internal::gen_helpers::SerializeString(4, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+StatsdTracingConfig::StatsdTracingConfig() = default;
+StatsdTracingConfig::~StatsdTracingConfig() = default;
+StatsdTracingConfig::StatsdTracingConfig(const StatsdTracingConfig&) = default;
+StatsdTracingConfig& StatsdTracingConfig::operator=(const StatsdTracingConfig&) = default;
+StatsdTracingConfig::StatsdTracingConfig(StatsdTracingConfig&&) noexcept = default;
+StatsdTracingConfig& StatsdTracingConfig::operator=(StatsdTracingConfig&&) = default;
+
+bool StatsdTracingConfig::operator==(const StatsdTracingConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(push_atom_id_, other.push_atom_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(raw_push_atom_id_, other.raw_push_atom_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(pull_config_, other.pull_config_);
+}
+
+int StatsdTracingConfig::pull_config_size() const { return static_cast<int>(pull_config_.size()); }
+void StatsdTracingConfig::clear_pull_config() { pull_config_.clear(); }
+StatsdPullAtomConfig* StatsdTracingConfig::add_pull_config() { pull_config_.emplace_back(); return &pull_config_.back(); }
+bool StatsdTracingConfig::ParseFromArray(const void* raw, size_t size) {
+ push_atom_id_.clear();
+ raw_push_atom_id_.clear();
+ pull_config_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* push_atom_id */:
+ push_atom_id_.emplace_back();
+ field.get(&push_atom_id_.back());
+ break;
+ case 2 /* raw_push_atom_id */:
+ raw_push_atom_id_.emplace_back();
+ field.get(&raw_push_atom_id_.back());
+ break;
+ case 3 /* pull_config */:
+ pull_config_.emplace_back();
+ pull_config_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string StatsdTracingConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> StatsdTracingConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void StatsdTracingConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: push_atom_id
+ for (auto& it : push_atom_id_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ // Field 2: raw_push_atom_id
+ for (auto& it : raw_push_atom_id_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ // Field 3: pull_config
+ for (auto& it : pull_config_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/sys_stats/sys_stats_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/sys_stats_counters.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+SysStatsConfig::SysStatsConfig() = default;
+SysStatsConfig::~SysStatsConfig() = default;
+SysStatsConfig::SysStatsConfig(const SysStatsConfig&) = default;
+SysStatsConfig& SysStatsConfig::operator=(const SysStatsConfig&) = default;
+SysStatsConfig::SysStatsConfig(SysStatsConfig&&) noexcept = default;
+SysStatsConfig& SysStatsConfig::operator=(SysStatsConfig&&) = default;
+
+bool SysStatsConfig::operator==(const SysStatsConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(meminfo_period_ms_, other.meminfo_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(meminfo_counters_, other.meminfo_counters_)
+ && ::protozero::internal::gen_helpers::EqualsField(vmstat_period_ms_, other.vmstat_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(vmstat_counters_, other.vmstat_counters_)
+ && ::protozero::internal::gen_helpers::EqualsField(stat_period_ms_, other.stat_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(stat_counters_, other.stat_counters_)
+ && ::protozero::internal::gen_helpers::EqualsField(devfreq_period_ms_, other.devfreq_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(cpufreq_period_ms_, other.cpufreq_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(buddyinfo_period_ms_, other.buddyinfo_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(diskstat_period_ms_, other.diskstat_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(psi_period_ms_, other.psi_period_ms_);
+}
+
+bool SysStatsConfig::ParseFromArray(const void* raw, size_t size) {
+ meminfo_counters_.clear();
+ vmstat_counters_.clear();
+ stat_counters_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* meminfo_period_ms */:
+ field.get(&meminfo_period_ms_);
+ break;
+ case 2 /* meminfo_counters */:
+ meminfo_counters_.emplace_back();
+ field.get(&meminfo_counters_.back());
+ break;
+ case 3 /* vmstat_period_ms */:
+ field.get(&vmstat_period_ms_);
+ break;
+ case 4 /* vmstat_counters */:
+ vmstat_counters_.emplace_back();
+ field.get(&vmstat_counters_.back());
+ break;
+ case 5 /* stat_period_ms */:
+ field.get(&stat_period_ms_);
+ break;
+ case 6 /* stat_counters */:
+ stat_counters_.emplace_back();
+ field.get(&stat_counters_.back());
+ break;
+ case 7 /* devfreq_period_ms */:
+ field.get(&devfreq_period_ms_);
+ break;
+ case 8 /* cpufreq_period_ms */:
+ field.get(&cpufreq_period_ms_);
+ break;
+ case 9 /* buddyinfo_period_ms */:
+ field.get(&buddyinfo_period_ms_);
+ break;
+ case 10 /* diskstat_period_ms */:
+ field.get(&diskstat_period_ms_);
+ break;
+ case 11 /* psi_period_ms */:
+ field.get(&psi_period_ms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SysStatsConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SysStatsConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SysStatsConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: meminfo_period_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, meminfo_period_ms_, msg);
+ }
+
+ // Field 2: meminfo_counters
+ for (auto& it : meminfo_counters_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, it, msg);
+ }
+
+ // Field 3: vmstat_period_ms
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, vmstat_period_ms_, msg);
+ }
+
+ // Field 4: vmstat_counters
+ for (auto& it : vmstat_counters_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, it, msg);
+ }
+
+ // Field 5: stat_period_ms
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, stat_period_ms_, msg);
+ }
+
+ // Field 6: stat_counters
+ for (auto& it : stat_counters_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, it, msg);
+ }
+
+ // Field 7: devfreq_period_ms
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, devfreq_period_ms_, msg);
+ }
+
+ // Field 8: cpufreq_period_ms
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, cpufreq_period_ms_, msg);
+ }
+
+ // Field 9: buddyinfo_period_ms
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, buddyinfo_period_ms_, msg);
+ }
+
+ // Field 10: diskstat_period_ms
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, diskstat_period_ms_, msg);
+ }
+
+ // Field 11: psi_period_ms
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, psi_period_ms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/system_info/system_info.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/system_info/system_info.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+SystemInfoConfig::SystemInfoConfig() = default;
+SystemInfoConfig::~SystemInfoConfig() = default;
+SystemInfoConfig::SystemInfoConfig(const SystemInfoConfig&) = default;
+SystemInfoConfig& SystemInfoConfig::operator=(const SystemInfoConfig&) = default;
+SystemInfoConfig::SystemInfoConfig(SystemInfoConfig&&) noexcept = default;
+SystemInfoConfig& SystemInfoConfig::operator=(SystemInfoConfig&&) = default;
+
+bool SystemInfoConfig::operator==(const SystemInfoConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool SystemInfoConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SystemInfoConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SystemInfoConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SystemInfoConfig::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/track_event/track_event_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/track_event/track_event_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TrackEventConfig::TrackEventConfig() = default;
+TrackEventConfig::~TrackEventConfig() = default;
+TrackEventConfig::TrackEventConfig(const TrackEventConfig&) = default;
+TrackEventConfig& TrackEventConfig::operator=(const TrackEventConfig&) = default;
+TrackEventConfig::TrackEventConfig(TrackEventConfig&&) noexcept = default;
+TrackEventConfig& TrackEventConfig::operator=(TrackEventConfig&&) = default;
+
+bool TrackEventConfig::operator==(const TrackEventConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(disabled_categories_, other.disabled_categories_)
+ && ::protozero::internal::gen_helpers::EqualsField(enabled_categories_, other.enabled_categories_)
+ && ::protozero::internal::gen_helpers::EqualsField(disabled_tags_, other.disabled_tags_)
+ && ::protozero::internal::gen_helpers::EqualsField(enabled_tags_, other.enabled_tags_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_incremental_timestamps_, other.disable_incremental_timestamps_)
+ && ::protozero::internal::gen_helpers::EqualsField(timestamp_unit_multiplier_, other.timestamp_unit_multiplier_)
+ && ::protozero::internal::gen_helpers::EqualsField(filter_debug_annotations_, other.filter_debug_annotations_)
+ && ::protozero::internal::gen_helpers::EqualsField(enable_thread_time_sampling_, other.enable_thread_time_sampling_)
+ && ::protozero::internal::gen_helpers::EqualsField(filter_dynamic_event_names_, other.filter_dynamic_event_names_);
+}
+
+bool TrackEventConfig::ParseFromArray(const void* raw, size_t size) {
+ disabled_categories_.clear();
+ enabled_categories_.clear();
+ disabled_tags_.clear();
+ enabled_tags_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* disabled_categories */:
+ disabled_categories_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &disabled_categories_.back());
+ break;
+ case 2 /* enabled_categories */:
+ enabled_categories_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &enabled_categories_.back());
+ break;
+ case 3 /* disabled_tags */:
+ disabled_tags_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &disabled_tags_.back());
+ break;
+ case 4 /* enabled_tags */:
+ enabled_tags_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &enabled_tags_.back());
+ break;
+ case 5 /* disable_incremental_timestamps */:
+ field.get(&disable_incremental_timestamps_);
+ break;
+ case 6 /* timestamp_unit_multiplier */:
+ field.get(&timestamp_unit_multiplier_);
+ break;
+ case 7 /* filter_debug_annotations */:
+ field.get(&filter_debug_annotations_);
+ break;
+ case 8 /* enable_thread_time_sampling */:
+ field.get(&enable_thread_time_sampling_);
+ break;
+ case 9 /* filter_dynamic_event_names */:
+ field.get(&filter_dynamic_event_names_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackEventConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackEventConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackEventConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: disabled_categories
+ for (auto& it : disabled_categories_) {
+ ::protozero::internal::gen_helpers::SerializeString(1, it, msg);
+ }
+
+ // Field 2: enabled_categories
+ for (auto& it : enabled_categories_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 3: disabled_tags
+ for (auto& it : disabled_tags_) {
+ ::protozero::internal::gen_helpers::SerializeString(3, it, msg);
+ }
+
+ // Field 4: enabled_tags
+ for (auto& it : enabled_tags_) {
+ ::protozero::internal::gen_helpers::SerializeString(4, it, msg);
+ }
+
+ // Field 5: disable_incremental_timestamps
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, disable_incremental_timestamps_, msg);
+ }
+
+ // Field 6: timestamp_unit_multiplier
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, timestamp_unit_multiplier_, msg);
+ }
+
+ // Field 7: filter_debug_annotations
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(7, filter_debug_annotations_, msg);
+ }
+
+ // Field 8: enable_thread_time_sampling
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(8, enable_thread_time_sampling_, msg);
+ }
+
+ // Field 9: filter_dynamic_event_names
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, filter_dynamic_event_names_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/chrome/chrome_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/chrome_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeConfig::ChromeConfig() = default;
+ChromeConfig::~ChromeConfig() = default;
+ChromeConfig::ChromeConfig(const ChromeConfig&) = default;
+ChromeConfig& ChromeConfig::operator=(const ChromeConfig&) = default;
+ChromeConfig::ChromeConfig(ChromeConfig&&) noexcept = default;
+ChromeConfig& ChromeConfig::operator=(ChromeConfig&&) = default;
+
+bool ChromeConfig::operator==(const ChromeConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_config_, other.trace_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(privacy_filtering_enabled_, other.privacy_filtering_enabled_)
+ && ::protozero::internal::gen_helpers::EqualsField(convert_to_legacy_json_, other.convert_to_legacy_json_)
+ && ::protozero::internal::gen_helpers::EqualsField(client_priority_, other.client_priority_)
+ && ::protozero::internal::gen_helpers::EqualsField(json_agent_label_filter_, other.json_agent_label_filter_);
+}
+
+bool ChromeConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &trace_config_);
+ break;
+ case 2 /* privacy_filtering_enabled */:
+ field.get(&privacy_filtering_enabled_);
+ break;
+ case 3 /* convert_to_legacy_json */:
+ field.get(&convert_to_legacy_json_);
+ break;
+ case 4 /* client_priority */:
+ field.get(&client_priority_);
+ break;
+ case 5 /* json_agent_label_filter */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &json_agent_label_filter_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_config
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, trace_config_, msg);
+ }
+
+ // Field 2: privacy_filtering_enabled
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, privacy_filtering_enabled_, msg);
+ }
+
+ // Field 3: convert_to_legacy_json
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, convert_to_legacy_json_, msg);
+ }
+
+ // Field 4: client_priority
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, client_priority_, msg);
+ }
+
+ // Field 5: json_agent_label_filter
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeString(5, json_agent_label_filter_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/chrome/scenario_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/scenario_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/system_info/system_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/track_event/track_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/test_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/sys_stats_counters.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/perf_events.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/statsd_tracing_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/atom_ids.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/power/android_power_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/inode_file/inode_file_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/vulkan_memory_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/gpu_counter_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/etw/etw_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/v8_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/chrome_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_layers_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/protolog_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/protolog_common.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/packages_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/network_trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_system_property_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_polled_state_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_log_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_log_constants.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_input_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_game_intervention_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TracingTriggerRulesConfig::TracingTriggerRulesConfig() = default;
+TracingTriggerRulesConfig::~TracingTriggerRulesConfig() = default;
+TracingTriggerRulesConfig::TracingTriggerRulesConfig(const TracingTriggerRulesConfig&) = default;
+TracingTriggerRulesConfig& TracingTriggerRulesConfig::operator=(const TracingTriggerRulesConfig&) = default;
+TracingTriggerRulesConfig::TracingTriggerRulesConfig(TracingTriggerRulesConfig&&) noexcept = default;
+TracingTriggerRulesConfig& TracingTriggerRulesConfig::operator=(TracingTriggerRulesConfig&&) = default;
+
+bool TracingTriggerRulesConfig::operator==(const TracingTriggerRulesConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(rules_, other.rules_);
+}
+
+int TracingTriggerRulesConfig::rules_size() const { return static_cast<int>(rules_.size()); }
+void TracingTriggerRulesConfig::clear_rules() { rules_.clear(); }
+TriggerRule* TracingTriggerRulesConfig::add_rules() { rules_.emplace_back(); return &rules_.back(); }
+bool TracingTriggerRulesConfig::ParseFromArray(const void* raw, size_t size) {
+ rules_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* rules */:
+ rules_.emplace_back();
+ rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TracingTriggerRulesConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TracingTriggerRulesConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TracingTriggerRulesConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: rules
+ for (auto& it : rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TriggerRule::TriggerRule() = default;
+TriggerRule::~TriggerRule() = default;
+TriggerRule::TriggerRule(const TriggerRule&) = default;
+TriggerRule& TriggerRule::operator=(const TriggerRule&) = default;
+TriggerRule::TriggerRule(TriggerRule&&) noexcept = default;
+TriggerRule& TriggerRule::operator=(TriggerRule&&) = default;
+
+bool TriggerRule::operator==(const TriggerRule& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(trigger_chance_, other.trigger_chance_)
+ && ::protozero::internal::gen_helpers::EqualsField(delay_ms_, other.delay_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(activation_delay_ms_, other.activation_delay_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(manual_trigger_name_, other.manual_trigger_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(histogram_, other.histogram_)
+ && ::protozero::internal::gen_helpers::EqualsField(repeating_interval_, other.repeating_interval_);
+}
+
+bool TriggerRule::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* trigger_chance */:
+ field.get(&trigger_chance_);
+ break;
+ case 3 /* delay_ms */:
+ field.get(&delay_ms_);
+ break;
+ case 8 /* activation_delay_ms */:
+ field.get(&activation_delay_ms_);
+ break;
+ case 4 /* manual_trigger_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &manual_trigger_name_);
+ break;
+ case 5 /* histogram */:
+ (*histogram_).ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* repeating_interval */:
+ (*repeating_interval_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TriggerRule::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TriggerRule::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TriggerRule::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: trigger_chance
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(2, trigger_chance_, msg);
+ }
+
+ // Field 3: delay_ms
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, delay_ms_, msg);
+ }
+
+ // Field 8: activation_delay_ms
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, activation_delay_ms_, msg);
+ }
+
+ // Field 4: manual_trigger_name
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeString(4, manual_trigger_name_, msg);
+ }
+
+ // Field 5: histogram
+ if (_has_field_[5]) {
+ (*histogram_).Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 6: repeating_interval
+ if (_has_field_[6]) {
+ (*repeating_interval_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TriggerRule_RepeatingInterval::TriggerRule_RepeatingInterval() = default;
+TriggerRule_RepeatingInterval::~TriggerRule_RepeatingInterval() = default;
+TriggerRule_RepeatingInterval::TriggerRule_RepeatingInterval(const TriggerRule_RepeatingInterval&) = default;
+TriggerRule_RepeatingInterval& TriggerRule_RepeatingInterval::operator=(const TriggerRule_RepeatingInterval&) = default;
+TriggerRule_RepeatingInterval::TriggerRule_RepeatingInterval(TriggerRule_RepeatingInterval&&) noexcept = default;
+TriggerRule_RepeatingInterval& TriggerRule_RepeatingInterval::operator=(TriggerRule_RepeatingInterval&&) = default;
+
+bool TriggerRule_RepeatingInterval::operator==(const TriggerRule_RepeatingInterval& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(period_ms_, other.period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(randomized_, other.randomized_);
+}
+
+bool TriggerRule_RepeatingInterval::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* period_ms */:
+ field.get(&period_ms_);
+ break;
+ case 2 /* randomized */:
+ field.get(&randomized_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TriggerRule_RepeatingInterval::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TriggerRule_RepeatingInterval::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TriggerRule_RepeatingInterval::Serialize(::protozero::Message* msg) const {
+ // Field 1: period_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, period_ms_, msg);
+ }
+
+ // Field 2: randomized
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, randomized_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TriggerRule_HistogramTrigger::TriggerRule_HistogramTrigger() = default;
+TriggerRule_HistogramTrigger::~TriggerRule_HistogramTrigger() = default;
+TriggerRule_HistogramTrigger::TriggerRule_HistogramTrigger(const TriggerRule_HistogramTrigger&) = default;
+TriggerRule_HistogramTrigger& TriggerRule_HistogramTrigger::operator=(const TriggerRule_HistogramTrigger&) = default;
+TriggerRule_HistogramTrigger::TriggerRule_HistogramTrigger(TriggerRule_HistogramTrigger&&) noexcept = default;
+TriggerRule_HistogramTrigger& TriggerRule_HistogramTrigger::operator=(TriggerRule_HistogramTrigger&&) = default;
+
+bool TriggerRule_HistogramTrigger::operator==(const TriggerRule_HistogramTrigger& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(histogram_name_, other.histogram_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(min_value_, other.min_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_value_, other.max_value_);
+}
+
+bool TriggerRule_HistogramTrigger::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* histogram_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &histogram_name_);
+ break;
+ case 2 /* min_value */:
+ field.get(&min_value_);
+ break;
+ case 3 /* max_value */:
+ field.get(&max_value_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TriggerRule_HistogramTrigger::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TriggerRule_HistogramTrigger::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TriggerRule_HistogramTrigger::Serialize(::protozero::Message* msg) const {
+ // Field 1: histogram_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, histogram_name_, msg);
+ }
+
+ // Field 2: min_value
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, min_value_, msg);
+ }
+
+ // Field 3: max_value
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, max_value_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChromeFieldTracingConfig::ChromeFieldTracingConfig() = default;
+ChromeFieldTracingConfig::~ChromeFieldTracingConfig() = default;
+ChromeFieldTracingConfig::ChromeFieldTracingConfig(const ChromeFieldTracingConfig&) = default;
+ChromeFieldTracingConfig& ChromeFieldTracingConfig::operator=(const ChromeFieldTracingConfig&) = default;
+ChromeFieldTracingConfig::ChromeFieldTracingConfig(ChromeFieldTracingConfig&&) noexcept = default;
+ChromeFieldTracingConfig& ChromeFieldTracingConfig::operator=(ChromeFieldTracingConfig&&) = default;
+
+bool ChromeFieldTracingConfig::operator==(const ChromeFieldTracingConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(scenarios_, other.scenarios_);
+}
+
+int ChromeFieldTracingConfig::scenarios_size() const { return static_cast<int>(scenarios_.size()); }
+void ChromeFieldTracingConfig::clear_scenarios() { scenarios_.clear(); }
+ScenarioConfig* ChromeFieldTracingConfig::add_scenarios() { scenarios_.emplace_back(); return &scenarios_.back(); }
+bool ChromeFieldTracingConfig::ParseFromArray(const void* raw, size_t size) {
+ scenarios_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* scenarios */:
+ scenarios_.emplace_back();
+ scenarios_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeFieldTracingConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeFieldTracingConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeFieldTracingConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: scenarios
+ for (auto& it : scenarios_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ScenarioConfig::ScenarioConfig() = default;
+ScenarioConfig::~ScenarioConfig() = default;
+ScenarioConfig::ScenarioConfig(const ScenarioConfig&) = default;
+ScenarioConfig& ScenarioConfig::operator=(const ScenarioConfig&) = default;
+ScenarioConfig::ScenarioConfig(ScenarioConfig&&) noexcept = default;
+ScenarioConfig& ScenarioConfig::operator=(ScenarioConfig&&) = default;
+
+bool ScenarioConfig::operator==(const ScenarioConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(scenario_name_, other.scenario_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(start_rules_, other.start_rules_)
+ && ::protozero::internal::gen_helpers::EqualsField(stop_rules_, other.stop_rules_)
+ && ::protozero::internal::gen_helpers::EqualsField(upload_rules_, other.upload_rules_)
+ && ::protozero::internal::gen_helpers::EqualsField(setup_rules_, other.setup_rules_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_config_, other.trace_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(nested_scenarios_, other.nested_scenarios_);
+}
+
+int ScenarioConfig::start_rules_size() const { return static_cast<int>(start_rules_.size()); }
+void ScenarioConfig::clear_start_rules() { start_rules_.clear(); }
+TriggerRule* ScenarioConfig::add_start_rules() { start_rules_.emplace_back(); return &start_rules_.back(); }
+int ScenarioConfig::stop_rules_size() const { return static_cast<int>(stop_rules_.size()); }
+void ScenarioConfig::clear_stop_rules() { stop_rules_.clear(); }
+TriggerRule* ScenarioConfig::add_stop_rules() { stop_rules_.emplace_back(); return &stop_rules_.back(); }
+int ScenarioConfig::upload_rules_size() const { return static_cast<int>(upload_rules_.size()); }
+void ScenarioConfig::clear_upload_rules() { upload_rules_.clear(); }
+TriggerRule* ScenarioConfig::add_upload_rules() { upload_rules_.emplace_back(); return &upload_rules_.back(); }
+int ScenarioConfig::setup_rules_size() const { return static_cast<int>(setup_rules_.size()); }
+void ScenarioConfig::clear_setup_rules() { setup_rules_.clear(); }
+TriggerRule* ScenarioConfig::add_setup_rules() { setup_rules_.emplace_back(); return &setup_rules_.back(); }
+int ScenarioConfig::nested_scenarios_size() const { return static_cast<int>(nested_scenarios_.size()); }
+void ScenarioConfig::clear_nested_scenarios() { nested_scenarios_.clear(); }
+NestedScenarioConfig* ScenarioConfig::add_nested_scenarios() { nested_scenarios_.emplace_back(); return &nested_scenarios_.back(); }
+bool ScenarioConfig::ParseFromArray(const void* raw, size_t size) {
+ start_rules_.clear();
+ stop_rules_.clear();
+ upload_rules_.clear();
+ setup_rules_.clear();
+ nested_scenarios_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* scenario_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &scenario_name_);
+ break;
+ case 2 /* start_rules */:
+ start_rules_.emplace_back();
+ start_rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* stop_rules */:
+ stop_rules_.emplace_back();
+ stop_rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 4 /* upload_rules */:
+ upload_rules_.emplace_back();
+ upload_rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* setup_rules */:
+ setup_rules_.emplace_back();
+ setup_rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* trace_config */:
+ (*trace_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 7 /* nested_scenarios */:
+ nested_scenarios_.emplace_back();
+ nested_scenarios_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ScenarioConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ScenarioConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ScenarioConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: scenario_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, scenario_name_, msg);
+ }
+
+ // Field 2: start_rules
+ for (auto& it : start_rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 3: stop_rules
+ for (auto& it : stop_rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 4: upload_rules
+ for (auto& it : upload_rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: setup_rules
+ for (auto& it : setup_rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 6: trace_config
+ if (_has_field_[6]) {
+ (*trace_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 7: nested_scenarios
+ for (auto& it : nested_scenarios_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(7));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+NestedScenarioConfig::NestedScenarioConfig() = default;
+NestedScenarioConfig::~NestedScenarioConfig() = default;
+NestedScenarioConfig::NestedScenarioConfig(const NestedScenarioConfig&) = default;
+NestedScenarioConfig& NestedScenarioConfig::operator=(const NestedScenarioConfig&) = default;
+NestedScenarioConfig::NestedScenarioConfig(NestedScenarioConfig&&) noexcept = default;
+NestedScenarioConfig& NestedScenarioConfig::operator=(NestedScenarioConfig&&) = default;
+
+bool NestedScenarioConfig::operator==(const NestedScenarioConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(scenario_name_, other.scenario_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(start_rules_, other.start_rules_)
+ && ::protozero::internal::gen_helpers::EqualsField(stop_rules_, other.stop_rules_)
+ && ::protozero::internal::gen_helpers::EqualsField(upload_rules_, other.upload_rules_);
+}
+
+int NestedScenarioConfig::start_rules_size() const { return static_cast<int>(start_rules_.size()); }
+void NestedScenarioConfig::clear_start_rules() { start_rules_.clear(); }
+TriggerRule* NestedScenarioConfig::add_start_rules() { start_rules_.emplace_back(); return &start_rules_.back(); }
+int NestedScenarioConfig::stop_rules_size() const { return static_cast<int>(stop_rules_.size()); }
+void NestedScenarioConfig::clear_stop_rules() { stop_rules_.clear(); }
+TriggerRule* NestedScenarioConfig::add_stop_rules() { stop_rules_.emplace_back(); return &stop_rules_.back(); }
+int NestedScenarioConfig::upload_rules_size() const { return static_cast<int>(upload_rules_.size()); }
+void NestedScenarioConfig::clear_upload_rules() { upload_rules_.clear(); }
+TriggerRule* NestedScenarioConfig::add_upload_rules() { upload_rules_.emplace_back(); return &upload_rules_.back(); }
+bool NestedScenarioConfig::ParseFromArray(const void* raw, size_t size) {
+ start_rules_.clear();
+ stop_rules_.clear();
+ upload_rules_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* scenario_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &scenario_name_);
+ break;
+ case 2 /* start_rules */:
+ start_rules_.emplace_back();
+ start_rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* stop_rules */:
+ stop_rules_.emplace_back();
+ stop_rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 4 /* upload_rules */:
+ upload_rules_.emplace_back();
+ upload_rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string NestedScenarioConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> NestedScenarioConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void NestedScenarioConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: scenario_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, scenario_name_, msg);
+ }
+
+ // Field 2: start_rules
+ for (auto& it : start_rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 3: stop_rules
+ for (auto& it : stop_rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 4: upload_rules
+ for (auto& it : upload_rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/chrome/v8_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/v8_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+V8Config::V8Config() = default;
+V8Config::~V8Config() = default;
+V8Config::V8Config(const V8Config&) = default;
+V8Config& V8Config::operator=(const V8Config&) = default;
+V8Config::V8Config(V8Config&&) noexcept = default;
+V8Config& V8Config::operator=(V8Config&&) = default;
+
+bool V8Config::operator==(const V8Config& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(log_script_sources_, other.log_script_sources_)
+ && ::protozero::internal::gen_helpers::EqualsField(log_instructions_, other.log_instructions_);
+}
+
+bool V8Config::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* log_script_sources */:
+ field.get(&log_script_sources_);
+ break;
+ case 2 /* log_instructions */:
+ field.get(&log_instructions_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string V8Config::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> V8Config::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void V8Config::Serialize(::protozero::Message* msg) const {
+ // Field 1: log_script_sources
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, log_script_sources_, msg);
+ }
+
+ // Field 2: log_instructions
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, log_instructions_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/data_source_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/system_info/system_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/test_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/chrome_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+DataSourceConfig::DataSourceConfig() = default;
+DataSourceConfig::~DataSourceConfig() = default;
+DataSourceConfig::DataSourceConfig(const DataSourceConfig&) = default;
+DataSourceConfig& DataSourceConfig::operator=(const DataSourceConfig&) = default;
+DataSourceConfig::DataSourceConfig(DataSourceConfig&&) noexcept = default;
+DataSourceConfig& DataSourceConfig::operator=(DataSourceConfig&&) = default;
+
+bool DataSourceConfig::operator==(const DataSourceConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_buffer_, other.target_buffer_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_duration_ms_, other.trace_duration_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(prefer_suspend_clock_for_duration_, other.prefer_suspend_clock_for_duration_)
+ && ::protozero::internal::gen_helpers::EqualsField(stop_timeout_ms_, other.stop_timeout_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(enable_extra_guardrails_, other.enable_extra_guardrails_)
+ && ::protozero::internal::gen_helpers::EqualsField(session_initiator_, other.session_initiator_)
+ && ::protozero::internal::gen_helpers::EqualsField(tracing_session_id_, other.tracing_session_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(ftrace_config_, other.ftrace_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(inode_file_config_, other.inode_file_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_stats_config_, other.process_stats_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(sys_stats_config_, other.sys_stats_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(heapprofd_config_, other.heapprofd_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(java_hprof_config_, other.java_hprof_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_power_config_, other.android_power_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_log_config_, other.android_log_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(gpu_counter_config_, other.gpu_counter_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_game_intervention_list_config_, other.android_game_intervention_list_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(packages_list_config_, other.packages_list_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(perf_event_config_, other.perf_event_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(vulkan_memory_config_, other.vulkan_memory_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(track_event_config_, other.track_event_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_polled_state_config_, other.android_polled_state_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_system_property_config_, other.android_system_property_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(statsd_tracing_config_, other.statsd_tracing_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(system_info_config_, other.system_info_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_config_, other.chrome_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(v8_config_, other.v8_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(interceptor_config_, other.interceptor_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(network_packet_trace_config_, other.network_packet_trace_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(surfaceflinger_layers_config_, other.surfaceflinger_layers_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(surfaceflinger_transactions_config_, other.surfaceflinger_transactions_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_sdk_sysprop_guard_config_, other.android_sdk_sysprop_guard_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(etw_config_, other.etw_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(protolog_config_, other.protolog_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_input_event_config_, other.android_input_event_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(legacy_config_, other.legacy_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(for_testing_, other.for_testing_);
+}
+
+bool DataSourceConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* target_buffer */:
+ field.get(&target_buffer_);
+ break;
+ case 3 /* trace_duration_ms */:
+ field.get(&trace_duration_ms_);
+ break;
+ case 122 /* prefer_suspend_clock_for_duration */:
+ field.get(&prefer_suspend_clock_for_duration_);
+ break;
+ case 7 /* stop_timeout_ms */:
+ field.get(&stop_timeout_ms_);
+ break;
+ case 6 /* enable_extra_guardrails */:
+ field.get(&enable_extra_guardrails_);
+ break;
+ case 8 /* session_initiator */:
+ field.get(&session_initiator_);
+ break;
+ case 4 /* tracing_session_id */:
+ field.get(&tracing_session_id_);
+ break;
+ case 100 /* ftrace_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &ftrace_config_);
+ break;
+ case 102 /* inode_file_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &inode_file_config_);
+ break;
+ case 103 /* process_stats_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &process_stats_config_);
+ break;
+ case 104 /* sys_stats_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &sys_stats_config_);
+ break;
+ case 105 /* heapprofd_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &heapprofd_config_);
+ break;
+ case 110 /* java_hprof_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &java_hprof_config_);
+ break;
+ case 106 /* android_power_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &android_power_config_);
+ break;
+ case 107 /* android_log_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &android_log_config_);
+ break;
+ case 108 /* gpu_counter_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &gpu_counter_config_);
+ break;
+ case 116 /* android_game_intervention_list_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &android_game_intervention_list_config_);
+ break;
+ case 109 /* packages_list_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &packages_list_config_);
+ break;
+ case 111 /* perf_event_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &perf_event_config_);
+ break;
+ case 112 /* vulkan_memory_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &vulkan_memory_config_);
+ break;
+ case 113 /* track_event_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &track_event_config_);
+ break;
+ case 114 /* android_polled_state_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &android_polled_state_config_);
+ break;
+ case 118 /* android_system_property_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &android_system_property_config_);
+ break;
+ case 117 /* statsd_tracing_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &statsd_tracing_config_);
+ break;
+ case 119 /* system_info_config */:
+ (*system_info_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 101 /* chrome_config */:
+ (*chrome_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 127 /* v8_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &v8_config_);
+ break;
+ case 115 /* interceptor_config */:
+ (*interceptor_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 120 /* network_packet_trace_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &network_packet_trace_config_);
+ break;
+ case 121 /* surfaceflinger_layers_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &surfaceflinger_layers_config_);
+ break;
+ case 123 /* surfaceflinger_transactions_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &surfaceflinger_transactions_config_);
+ break;
+ case 124 /* android_sdk_sysprop_guard_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &android_sdk_sysprop_guard_config_);
+ break;
+ case 125 /* etw_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &etw_config_);
+ break;
+ case 126 /* protolog_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &protolog_config_);
+ break;
+ case 128 /* android_input_event_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &android_input_event_config_);
+ break;
+ case 1000 /* legacy_config */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &legacy_config_);
+ break;
+ case 1001 /* for_testing */:
+ (*for_testing_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DataSourceConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DataSourceConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DataSourceConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: target_buffer
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, target_buffer_, msg);
+ }
+
+ // Field 3: trace_duration_ms
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, trace_duration_ms_, msg);
+ }
+
+ // Field 122: prefer_suspend_clock_for_duration
+ if (_has_field_[122]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(122, prefer_suspend_clock_for_duration_, msg);
+ }
+
+ // Field 7: stop_timeout_ms
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, stop_timeout_ms_, msg);
+ }
+
+ // Field 6: enable_extra_guardrails
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(6, enable_extra_guardrails_, msg);
+ }
+
+ // Field 8: session_initiator
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, session_initiator_, msg);
+ }
+
+ // Field 4: tracing_session_id
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, tracing_session_id_, msg);
+ }
+
+ // Field 100: ftrace_config
+ if (_has_field_[100]) {
+ msg->AppendString(100, ftrace_config_);
+ }
+
+ // Field 102: inode_file_config
+ if (_has_field_[102]) {
+ msg->AppendString(102, inode_file_config_);
+ }
+
+ // Field 103: process_stats_config
+ if (_has_field_[103]) {
+ msg->AppendString(103, process_stats_config_);
+ }
+
+ // Field 104: sys_stats_config
+ if (_has_field_[104]) {
+ msg->AppendString(104, sys_stats_config_);
+ }
+
+ // Field 105: heapprofd_config
+ if (_has_field_[105]) {
+ msg->AppendString(105, heapprofd_config_);
+ }
+
+ // Field 110: java_hprof_config
+ if (_has_field_[110]) {
+ msg->AppendString(110, java_hprof_config_);
+ }
+
+ // Field 106: android_power_config
+ if (_has_field_[106]) {
+ msg->AppendString(106, android_power_config_);
+ }
+
+ // Field 107: android_log_config
+ if (_has_field_[107]) {
+ msg->AppendString(107, android_log_config_);
+ }
+
+ // Field 108: gpu_counter_config
+ if (_has_field_[108]) {
+ msg->AppendString(108, gpu_counter_config_);
+ }
+
+ // Field 116: android_game_intervention_list_config
+ if (_has_field_[116]) {
+ msg->AppendString(116, android_game_intervention_list_config_);
+ }
+
+ // Field 109: packages_list_config
+ if (_has_field_[109]) {
+ msg->AppendString(109, packages_list_config_);
+ }
+
+ // Field 111: perf_event_config
+ if (_has_field_[111]) {
+ msg->AppendString(111, perf_event_config_);
+ }
+
+ // Field 112: vulkan_memory_config
+ if (_has_field_[112]) {
+ msg->AppendString(112, vulkan_memory_config_);
+ }
+
+ // Field 113: track_event_config
+ if (_has_field_[113]) {
+ msg->AppendString(113, track_event_config_);
+ }
+
+ // Field 114: android_polled_state_config
+ if (_has_field_[114]) {
+ msg->AppendString(114, android_polled_state_config_);
+ }
+
+ // Field 118: android_system_property_config
+ if (_has_field_[118]) {
+ msg->AppendString(118, android_system_property_config_);
+ }
+
+ // Field 117: statsd_tracing_config
+ if (_has_field_[117]) {
+ msg->AppendString(117, statsd_tracing_config_);
+ }
+
+ // Field 119: system_info_config
+ if (_has_field_[119]) {
+ (*system_info_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(119));
+ }
+
+ // Field 101: chrome_config
+ if (_has_field_[101]) {
+ (*chrome_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(101));
+ }
+
+ // Field 127: v8_config
+ if (_has_field_[127]) {
+ msg->AppendString(127, v8_config_);
+ }
+
+ // Field 115: interceptor_config
+ if (_has_field_[115]) {
+ (*interceptor_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(115));
+ }
+
+ // Field 120: network_packet_trace_config
+ if (_has_field_[120]) {
+ msg->AppendString(120, network_packet_trace_config_);
+ }
+
+ // Field 121: surfaceflinger_layers_config
+ if (_has_field_[121]) {
+ msg->AppendString(121, surfaceflinger_layers_config_);
+ }
+
+ // Field 123: surfaceflinger_transactions_config
+ if (_has_field_[123]) {
+ msg->AppendString(123, surfaceflinger_transactions_config_);
+ }
+
+ // Field 124: android_sdk_sysprop_guard_config
+ if (_has_field_[124]) {
+ msg->AppendString(124, android_sdk_sysprop_guard_config_);
+ }
+
+ // Field 125: etw_config
+ if (_has_field_[125]) {
+ msg->AppendString(125, etw_config_);
+ }
+
+ // Field 126: protolog_config
+ if (_has_field_[126]) {
+ msg->AppendString(126, protolog_config_);
+ }
+
+ // Field 128: android_input_event_config
+ if (_has_field_[128]) {
+ msg->AppendString(128, android_input_event_config_);
+ }
+
+ // Field 1000: legacy_config
+ if (_has_field_[1000]) {
+ ::protozero::internal::gen_helpers::SerializeString(1000, legacy_config_, msg);
+ }
+
+ // Field 1001: for_testing
+ if (_has_field_[1001]) {
+ (*for_testing_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1001));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/etw/etw_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/etw/etw_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+EtwConfig::EtwConfig() = default;
+EtwConfig::~EtwConfig() = default;
+EtwConfig::EtwConfig(const EtwConfig&) = default;
+EtwConfig& EtwConfig::operator=(const EtwConfig&) = default;
+EtwConfig::EtwConfig(EtwConfig&&) noexcept = default;
+EtwConfig& EtwConfig::operator=(EtwConfig&&) = default;
+
+bool EtwConfig::operator==(const EtwConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(kernel_flags_, other.kernel_flags_);
+}
+
+bool EtwConfig::ParseFromArray(const void* raw, size_t size) {
+ kernel_flags_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* kernel_flags */:
+ kernel_flags_.emplace_back();
+ field.get(&kernel_flags_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string EtwConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> EtwConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void EtwConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: kernel_flags
+ for (auto& it : kernel_flags_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/interceptor_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+InterceptorConfig::InterceptorConfig() = default;
+InterceptorConfig::~InterceptorConfig() = default;
+InterceptorConfig::InterceptorConfig(const InterceptorConfig&) = default;
+InterceptorConfig& InterceptorConfig::operator=(const InterceptorConfig&) = default;
+InterceptorConfig::InterceptorConfig(InterceptorConfig&&) noexcept = default;
+InterceptorConfig& InterceptorConfig::operator=(InterceptorConfig&&) = default;
+
+bool InterceptorConfig::operator==(const InterceptorConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(console_config_, other.console_config_);
+}
+
+bool InterceptorConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 100 /* console_config */:
+ (*console_config_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string InterceptorConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> InterceptorConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void InterceptorConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 100: console_config
+ if (_has_field_[100]) {
+ (*console_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(100));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/stress_test_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/stress_test_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/system_info/system_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/track_event/track_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/test_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/sys_stats_counters.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/perf_events.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/statsd_tracing_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/atom_ids.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/power/android_power_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/inode_file/inode_file_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/vulkan_memory_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/gpu_counter_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/etw/etw_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/v8_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/chrome_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_layers_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/protolog_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/protolog_common.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/packages_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/network_trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_system_property_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_polled_state_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_log_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_log_constants.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_input_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_game_intervention_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+StressTestConfig::StressTestConfig() = default;
+StressTestConfig::~StressTestConfig() = default;
+StressTestConfig::StressTestConfig(const StressTestConfig&) = default;
+StressTestConfig& StressTestConfig::operator=(const StressTestConfig&) = default;
+StressTestConfig::StressTestConfig(StressTestConfig&&) noexcept = default;
+StressTestConfig& StressTestConfig::operator=(StressTestConfig&&) = default;
+
+bool StressTestConfig::operator==(const StressTestConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_config_, other.trace_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(shmem_size_kb_, other.shmem_size_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(shmem_page_size_kb_, other.shmem_page_size_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(num_processes_, other.num_processes_)
+ && ::protozero::internal::gen_helpers::EqualsField(num_threads_, other.num_threads_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_events_, other.max_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(nesting_, other.nesting_)
+ && ::protozero::internal::gen_helpers::EqualsField(steady_state_timings_, other.steady_state_timings_)
+ && ::protozero::internal::gen_helpers::EqualsField(burst_period_ms_, other.burst_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(burst_duration_ms_, other.burst_duration_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(burst_timings_, other.burst_timings_);
+}
+
+bool StressTestConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_config */:
+ (*trace_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* shmem_size_kb */:
+ field.get(&shmem_size_kb_);
+ break;
+ case 3 /* shmem_page_size_kb */:
+ field.get(&shmem_page_size_kb_);
+ break;
+ case 4 /* num_processes */:
+ field.get(&num_processes_);
+ break;
+ case 5 /* num_threads */:
+ field.get(&num_threads_);
+ break;
+ case 6 /* max_events */:
+ field.get(&max_events_);
+ break;
+ case 7 /* nesting */:
+ field.get(&nesting_);
+ break;
+ case 8 /* steady_state_timings */:
+ (*steady_state_timings_).ParseFromArray(field.data(), field.size());
+ break;
+ case 9 /* burst_period_ms */:
+ field.get(&burst_period_ms_);
+ break;
+ case 10 /* burst_duration_ms */:
+ field.get(&burst_duration_ms_);
+ break;
+ case 11 /* burst_timings */:
+ (*burst_timings_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string StressTestConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> StressTestConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void StressTestConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_config
+ if (_has_field_[1]) {
+ (*trace_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: shmem_size_kb
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, shmem_size_kb_, msg);
+ }
+
+ // Field 3: shmem_page_size_kb
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, shmem_page_size_kb_, msg);
+ }
+
+ // Field 4: num_processes
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, num_processes_, msg);
+ }
+
+ // Field 5: num_threads
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, num_threads_, msg);
+ }
+
+ // Field 6: max_events
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, max_events_, msg);
+ }
+
+ // Field 7: nesting
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, nesting_, msg);
+ }
+
+ // Field 8: steady_state_timings
+ if (_has_field_[8]) {
+ (*steady_state_timings_).Serialize(msg->BeginNestedMessage<::protozero::Message>(8));
+ }
+
+ // Field 9: burst_period_ms
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, burst_period_ms_, msg);
+ }
+
+ // Field 10: burst_duration_ms
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, burst_duration_ms_, msg);
+ }
+
+ // Field 11: burst_timings
+ if (_has_field_[11]) {
+ (*burst_timings_).Serialize(msg->BeginNestedMessage<::protozero::Message>(11));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+StressTestConfig_WriterTiming::StressTestConfig_WriterTiming() = default;
+StressTestConfig_WriterTiming::~StressTestConfig_WriterTiming() = default;
+StressTestConfig_WriterTiming::StressTestConfig_WriterTiming(const StressTestConfig_WriterTiming&) = default;
+StressTestConfig_WriterTiming& StressTestConfig_WriterTiming::operator=(const StressTestConfig_WriterTiming&) = default;
+StressTestConfig_WriterTiming::StressTestConfig_WriterTiming(StressTestConfig_WriterTiming&&) noexcept = default;
+StressTestConfig_WriterTiming& StressTestConfig_WriterTiming::operator=(StressTestConfig_WriterTiming&&) = default;
+
+bool StressTestConfig_WriterTiming::operator==(const StressTestConfig_WriterTiming& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(payload_mean_, other.payload_mean_)
+ && ::protozero::internal::gen_helpers::EqualsField(payload_stddev_, other.payload_stddev_)
+ && ::protozero::internal::gen_helpers::EqualsField(rate_mean_, other.rate_mean_)
+ && ::protozero::internal::gen_helpers::EqualsField(rate_stddev_, other.rate_stddev_)
+ && ::protozero::internal::gen_helpers::EqualsField(payload_write_time_ms_, other.payload_write_time_ms_);
+}
+
+bool StressTestConfig_WriterTiming::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* payload_mean */:
+ field.get(&payload_mean_);
+ break;
+ case 2 /* payload_stddev */:
+ field.get(&payload_stddev_);
+ break;
+ case 3 /* rate_mean */:
+ field.get(&rate_mean_);
+ break;
+ case 4 /* rate_stddev */:
+ field.get(&rate_stddev_);
+ break;
+ case 5 /* payload_write_time_ms */:
+ field.get(&payload_write_time_ms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string StressTestConfig_WriterTiming::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> StressTestConfig_WriterTiming::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void StressTestConfig_WriterTiming::Serialize(::protozero::Message* msg) const {
+ // Field 1: payload_mean
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(1, payload_mean_, msg);
+ }
+
+ // Field 2: payload_stddev
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(2, payload_stddev_, msg);
+ }
+
+ // Field 3: rate_mean
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(3, rate_mean_, msg);
+ }
+
+ // Field 4: rate_stddev
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(4, rate_stddev_, msg);
+ }
+
+ // Field 5: payload_write_time_ms
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, payload_write_time_ms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/test_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/test_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TestConfig::TestConfig() = default;
+TestConfig::~TestConfig() = default;
+TestConfig::TestConfig(const TestConfig&) = default;
+TestConfig& TestConfig::operator=(const TestConfig&) = default;
+TestConfig::TestConfig(TestConfig&&) noexcept = default;
+TestConfig& TestConfig::operator=(TestConfig&&) = default;
+
+bool TestConfig::operator==(const TestConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(message_count_, other.message_count_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_messages_per_second_, other.max_messages_per_second_)
+ && ::protozero::internal::gen_helpers::EqualsField(seed_, other.seed_)
+ && ::protozero::internal::gen_helpers::EqualsField(message_size_, other.message_size_)
+ && ::protozero::internal::gen_helpers::EqualsField(send_batch_on_register_, other.send_batch_on_register_)
+ && ::protozero::internal::gen_helpers::EqualsField(dummy_fields_, other.dummy_fields_);
+}
+
+bool TestConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* message_count */:
+ field.get(&message_count_);
+ break;
+ case 2 /* max_messages_per_second */:
+ field.get(&max_messages_per_second_);
+ break;
+ case 3 /* seed */:
+ field.get(&seed_);
+ break;
+ case 4 /* message_size */:
+ field.get(&message_size_);
+ break;
+ case 5 /* send_batch_on_register */:
+ field.get(&send_batch_on_register_);
+ break;
+ case 6 /* dummy_fields */:
+ (*dummy_fields_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TestConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TestConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TestConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: message_count
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, message_count_, msg);
+ }
+
+ // Field 2: max_messages_per_second
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, max_messages_per_second_, msg);
+ }
+
+ // Field 3: seed
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, seed_, msg);
+ }
+
+ // Field 4: message_size
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, message_size_, msg);
+ }
+
+ // Field 5: send_batch_on_register
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, send_batch_on_register_, msg);
+ }
+
+ // Field 6: dummy_fields
+ if (_has_field_[6]) {
+ (*dummy_fields_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TestConfig_DummyFields::TestConfig_DummyFields() = default;
+TestConfig_DummyFields::~TestConfig_DummyFields() = default;
+TestConfig_DummyFields::TestConfig_DummyFields(const TestConfig_DummyFields&) = default;
+TestConfig_DummyFields& TestConfig_DummyFields::operator=(const TestConfig_DummyFields&) = default;
+TestConfig_DummyFields::TestConfig_DummyFields(TestConfig_DummyFields&&) noexcept = default;
+TestConfig_DummyFields& TestConfig_DummyFields::operator=(TestConfig_DummyFields&&) = default;
+
+bool TestConfig_DummyFields::operator==(const TestConfig_DummyFields& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_uint32_, other.field_uint32_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_int32_, other.field_int32_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_uint64_, other.field_uint64_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_int64_, other.field_int64_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_fixed64_, other.field_fixed64_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_sfixed64_, other.field_sfixed64_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_fixed32_, other.field_fixed32_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_sfixed32_, other.field_sfixed32_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_double_, other.field_double_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_float_, other.field_float_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_sint64_, other.field_sint64_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_sint32_, other.field_sint32_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_string_, other.field_string_)
+ && ::protozero::internal::gen_helpers::EqualsField(field_bytes_, other.field_bytes_);
+}
+
+bool TestConfig_DummyFields::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* field_uint32 */:
+ field.get(&field_uint32_);
+ break;
+ case 2 /* field_int32 */:
+ field.get(&field_int32_);
+ break;
+ case 3 /* field_uint64 */:
+ field.get(&field_uint64_);
+ break;
+ case 4 /* field_int64 */:
+ field.get(&field_int64_);
+ break;
+ case 5 /* field_fixed64 */:
+ field.get(&field_fixed64_);
+ break;
+ case 6 /* field_sfixed64 */:
+ field.get(&field_sfixed64_);
+ break;
+ case 7 /* field_fixed32 */:
+ field.get(&field_fixed32_);
+ break;
+ case 8 /* field_sfixed32 */:
+ field.get(&field_sfixed32_);
+ break;
+ case 9 /* field_double */:
+ field.get(&field_double_);
+ break;
+ case 10 /* field_float */:
+ field.get(&field_float_);
+ break;
+ case 11 /* field_sint64 */:
+ field.get_signed(&field_sint64_);
+ break;
+ case 12 /* field_sint32 */:
+ field.get_signed(&field_sint32_);
+ break;
+ case 13 /* field_string */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &field_string_);
+ break;
+ case 14 /* field_bytes */:
+ field.get(&field_bytes_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TestConfig_DummyFields::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TestConfig_DummyFields::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TestConfig_DummyFields::Serialize(::protozero::Message* msg) const {
+ // Field 1: field_uint32
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, field_uint32_, msg);
+ }
+
+ // Field 2: field_int32
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, field_int32_, msg);
+ }
+
+ // Field 3: field_uint64
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, field_uint64_, msg);
+ }
+
+ // Field 4: field_int64
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, field_int64_, msg);
+ }
+
+ // Field 5: field_fixed64
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(5, field_fixed64_, msg);
+ }
+
+ // Field 6: field_sfixed64
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(6, field_sfixed64_, msg);
+ }
+
+ // Field 7: field_fixed32
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(7, field_fixed32_, msg);
+ }
+
+ // Field 8: field_sfixed32
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(8, field_sfixed32_, msg);
+ }
+
+ // Field 9: field_double
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(9, field_double_, msg);
+ }
+
+ // Field 10: field_float
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(10, field_float_, msg);
+ }
+
+ // Field 11: field_sint64
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeSignedVarInt(11, field_sint64_, msg);
+ }
+
+ // Field 12: field_sint32
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeSignedVarInt(12, field_sint32_, msg);
+ }
+
+ // Field 13: field_string
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeString(13, field_string_, msg);
+ }
+
+ // Field 14: field_bytes
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeString(14, field_bytes_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/trace_config.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/system_info/system_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/track_event/track_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/test_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/sys_stats_counters.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/perf_events.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/statsd_tracing_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/atom_ids.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/power/android_power_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/inode_file/inode_file_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/vulkan_memory_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/gpu_counter_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/etw/etw_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/v8_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/chrome_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_layers_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/protolog_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/protolog_common.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/packages_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/network_trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_system_property_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_polled_state_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_log_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_log_constants.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_input_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_game_intervention_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TraceConfig::TraceConfig() = default;
+TraceConfig::~TraceConfig() = default;
+TraceConfig::TraceConfig(const TraceConfig&) = default;
+TraceConfig& TraceConfig::operator=(const TraceConfig&) = default;
+TraceConfig::TraceConfig(TraceConfig&&) noexcept = default;
+TraceConfig& TraceConfig::operator=(TraceConfig&&) = default;
+
+bool TraceConfig::operator==(const TraceConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffers_, other.buffers_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_sources_, other.data_sources_)
+ && ::protozero::internal::gen_helpers::EqualsField(builtin_data_sources_, other.builtin_data_sources_)
+ && ::protozero::internal::gen_helpers::EqualsField(duration_ms_, other.duration_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(prefer_suspend_clock_for_duration_, other.prefer_suspend_clock_for_duration_)
+ && ::protozero::internal::gen_helpers::EqualsField(enable_extra_guardrails_, other.enable_extra_guardrails_)
+ && ::protozero::internal::gen_helpers::EqualsField(lockdown_mode_, other.lockdown_mode_)
+ && ::protozero::internal::gen_helpers::EqualsField(producers_, other.producers_)
+ && ::protozero::internal::gen_helpers::EqualsField(statsd_metadata_, other.statsd_metadata_)
+ && ::protozero::internal::gen_helpers::EqualsField(write_into_file_, other.write_into_file_)
+ && ::protozero::internal::gen_helpers::EqualsField(output_path_, other.output_path_)
+ && ::protozero::internal::gen_helpers::EqualsField(file_write_period_ms_, other.file_write_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_file_size_bytes_, other.max_file_size_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(guardrail_overrides_, other.guardrail_overrides_)
+ && ::protozero::internal::gen_helpers::EqualsField(deferred_start_, other.deferred_start_)
+ && ::protozero::internal::gen_helpers::EqualsField(flush_period_ms_, other.flush_period_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(flush_timeout_ms_, other.flush_timeout_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_stop_timeout_ms_, other.data_source_stop_timeout_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(notify_traceur_, other.notify_traceur_)
+ && ::protozero::internal::gen_helpers::EqualsField(bugreport_score_, other.bugreport_score_)
+ && ::protozero::internal::gen_helpers::EqualsField(bugreport_filename_, other.bugreport_filename_)
+ && ::protozero::internal::gen_helpers::EqualsField(trigger_config_, other.trigger_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(activate_triggers_, other.activate_triggers_)
+ && ::protozero::internal::gen_helpers::EqualsField(incremental_state_config_, other.incremental_state_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(allow_user_build_tracing_, other.allow_user_build_tracing_)
+ && ::protozero::internal::gen_helpers::EqualsField(unique_session_name_, other.unique_session_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(compression_type_, other.compression_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(incident_report_config_, other.incident_report_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(statsd_logging_, other.statsd_logging_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_uuid_msb_, other.trace_uuid_msb_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_uuid_lsb_, other.trace_uuid_lsb_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_filter_, other.trace_filter_)
+ && ::protozero::internal::gen_helpers::EqualsField(android_report_config_, other.android_report_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(cmd_trace_start_delay_, other.cmd_trace_start_delay_);
+}
+
+int TraceConfig::buffers_size() const { return static_cast<int>(buffers_.size()); }
+void TraceConfig::clear_buffers() { buffers_.clear(); }
+TraceConfig_BufferConfig* TraceConfig::add_buffers() { buffers_.emplace_back(); return &buffers_.back(); }
+int TraceConfig::data_sources_size() const { return static_cast<int>(data_sources_.size()); }
+void TraceConfig::clear_data_sources() { data_sources_.clear(); }
+TraceConfig_DataSource* TraceConfig::add_data_sources() { data_sources_.emplace_back(); return &data_sources_.back(); }
+int TraceConfig::producers_size() const { return static_cast<int>(producers_.size()); }
+void TraceConfig::clear_producers() { producers_.clear(); }
+TraceConfig_ProducerConfig* TraceConfig::add_producers() { producers_.emplace_back(); return &producers_.back(); }
+bool TraceConfig::ParseFromArray(const void* raw, size_t size) {
+ buffers_.clear();
+ data_sources_.clear();
+ producers_.clear();
+ activate_triggers_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* buffers */:
+ buffers_.emplace_back();
+ buffers_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* data_sources */:
+ data_sources_.emplace_back();
+ data_sources_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 20 /* builtin_data_sources */:
+ (*builtin_data_sources_).ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* duration_ms */:
+ field.get(&duration_ms_);
+ break;
+ case 36 /* prefer_suspend_clock_for_duration */:
+ field.get(&prefer_suspend_clock_for_duration_);
+ break;
+ case 4 /* enable_extra_guardrails */:
+ field.get(&enable_extra_guardrails_);
+ break;
+ case 5 /* lockdown_mode */:
+ field.get(&lockdown_mode_);
+ break;
+ case 6 /* producers */:
+ producers_.emplace_back();
+ producers_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 7 /* statsd_metadata */:
+ (*statsd_metadata_).ParseFromArray(field.data(), field.size());
+ break;
+ case 8 /* write_into_file */:
+ field.get(&write_into_file_);
+ break;
+ case 29 /* output_path */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &output_path_);
+ break;
+ case 9 /* file_write_period_ms */:
+ field.get(&file_write_period_ms_);
+ break;
+ case 10 /* max_file_size_bytes */:
+ field.get(&max_file_size_bytes_);
+ break;
+ case 11 /* guardrail_overrides */:
+ (*guardrail_overrides_).ParseFromArray(field.data(), field.size());
+ break;
+ case 12 /* deferred_start */:
+ field.get(&deferred_start_);
+ break;
+ case 13 /* flush_period_ms */:
+ field.get(&flush_period_ms_);
+ break;
+ case 14 /* flush_timeout_ms */:
+ field.get(&flush_timeout_ms_);
+ break;
+ case 23 /* data_source_stop_timeout_ms */:
+ field.get(&data_source_stop_timeout_ms_);
+ break;
+ case 16 /* notify_traceur */:
+ field.get(&notify_traceur_);
+ break;
+ case 30 /* bugreport_score */:
+ field.get(&bugreport_score_);
+ break;
+ case 38 /* bugreport_filename */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &bugreport_filename_);
+ break;
+ case 17 /* trigger_config */:
+ (*trigger_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 18 /* activate_triggers */:
+ activate_triggers_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &activate_triggers_.back());
+ break;
+ case 21 /* incremental_state_config */:
+ (*incremental_state_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 19 /* allow_user_build_tracing */:
+ field.get(&allow_user_build_tracing_);
+ break;
+ case 22 /* unique_session_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &unique_session_name_);
+ break;
+ case 24 /* compression_type */:
+ field.get(&compression_type_);
+ break;
+ case 25 /* incident_report_config */:
+ (*incident_report_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 31 /* statsd_logging */:
+ field.get(&statsd_logging_);
+ break;
+ case 27 /* trace_uuid_msb */:
+ field.get(&trace_uuid_msb_);
+ break;
+ case 28 /* trace_uuid_lsb */:
+ field.get(&trace_uuid_lsb_);
+ break;
+ case 33 /* trace_filter */:
+ (*trace_filter_).ParseFromArray(field.data(), field.size());
+ break;
+ case 34 /* android_report_config */:
+ (*android_report_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 35 /* cmd_trace_start_delay */:
+ (*cmd_trace_start_delay_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: buffers
+ for (auto& it : buffers_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: data_sources
+ for (auto& it : data_sources_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 20: builtin_data_sources
+ if (_has_field_[20]) {
+ (*builtin_data_sources_).Serialize(msg->BeginNestedMessage<::protozero::Message>(20));
+ }
+
+ // Field 3: duration_ms
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, duration_ms_, msg);
+ }
+
+ // Field 36: prefer_suspend_clock_for_duration
+ if (_has_field_[36]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(36, prefer_suspend_clock_for_duration_, msg);
+ }
+
+ // Field 4: enable_extra_guardrails
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, enable_extra_guardrails_, msg);
+ }
+
+ // Field 5: lockdown_mode
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, lockdown_mode_, msg);
+ }
+
+ // Field 6: producers
+ for (auto& it : producers_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 7: statsd_metadata
+ if (_has_field_[7]) {
+ (*statsd_metadata_).Serialize(msg->BeginNestedMessage<::protozero::Message>(7));
+ }
+
+ // Field 8: write_into_file
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(8, write_into_file_, msg);
+ }
+
+ // Field 29: output_path
+ if (_has_field_[29]) {
+ ::protozero::internal::gen_helpers::SerializeString(29, output_path_, msg);
+ }
+
+ // Field 9: file_write_period_ms
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, file_write_period_ms_, msg);
+ }
+
+ // Field 10: max_file_size_bytes
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, max_file_size_bytes_, msg);
+ }
+
+ // Field 11: guardrail_overrides
+ if (_has_field_[11]) {
+ (*guardrail_overrides_).Serialize(msg->BeginNestedMessage<::protozero::Message>(11));
+ }
+
+ // Field 12: deferred_start
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(12, deferred_start_, msg);
+ }
+
+ // Field 13: flush_period_ms
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, flush_period_ms_, msg);
+ }
+
+ // Field 14: flush_timeout_ms
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(14, flush_timeout_ms_, msg);
+ }
+
+ // Field 23: data_source_stop_timeout_ms
+ if (_has_field_[23]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(23, data_source_stop_timeout_ms_, msg);
+ }
+
+ // Field 16: notify_traceur
+ if (_has_field_[16]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(16, notify_traceur_, msg);
+ }
+
+ // Field 30: bugreport_score
+ if (_has_field_[30]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(30, bugreport_score_, msg);
+ }
+
+ // Field 38: bugreport_filename
+ if (_has_field_[38]) {
+ ::protozero::internal::gen_helpers::SerializeString(38, bugreport_filename_, msg);
+ }
+
+ // Field 17: trigger_config
+ if (_has_field_[17]) {
+ (*trigger_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(17));
+ }
+
+ // Field 18: activate_triggers
+ for (auto& it : activate_triggers_) {
+ ::protozero::internal::gen_helpers::SerializeString(18, it, msg);
+ }
+
+ // Field 21: incremental_state_config
+ if (_has_field_[21]) {
+ (*incremental_state_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(21));
+ }
+
+ // Field 19: allow_user_build_tracing
+ if (_has_field_[19]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(19, allow_user_build_tracing_, msg);
+ }
+
+ // Field 22: unique_session_name
+ if (_has_field_[22]) {
+ ::protozero::internal::gen_helpers::SerializeString(22, unique_session_name_, msg);
+ }
+
+ // Field 24: compression_type
+ if (_has_field_[24]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(24, compression_type_, msg);
+ }
+
+ // Field 25: incident_report_config
+ if (_has_field_[25]) {
+ (*incident_report_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(25));
+ }
+
+ // Field 31: statsd_logging
+ if (_has_field_[31]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(31, statsd_logging_, msg);
+ }
+
+ // Field 27: trace_uuid_msb
+ if (_has_field_[27]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(27, trace_uuid_msb_, msg);
+ }
+
+ // Field 28: trace_uuid_lsb
+ if (_has_field_[28]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(28, trace_uuid_lsb_, msg);
+ }
+
+ // Field 33: trace_filter
+ if (_has_field_[33]) {
+ (*trace_filter_).Serialize(msg->BeginNestedMessage<::protozero::Message>(33));
+ }
+
+ // Field 34: android_report_config
+ if (_has_field_[34]) {
+ (*android_report_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(34));
+ }
+
+ // Field 35: cmd_trace_start_delay
+ if (_has_field_[35]) {
+ (*cmd_trace_start_delay_).Serialize(msg->BeginNestedMessage<::protozero::Message>(35));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_CmdTraceStartDelay::TraceConfig_CmdTraceStartDelay() = default;
+TraceConfig_CmdTraceStartDelay::~TraceConfig_CmdTraceStartDelay() = default;
+TraceConfig_CmdTraceStartDelay::TraceConfig_CmdTraceStartDelay(const TraceConfig_CmdTraceStartDelay&) = default;
+TraceConfig_CmdTraceStartDelay& TraceConfig_CmdTraceStartDelay::operator=(const TraceConfig_CmdTraceStartDelay&) = default;
+TraceConfig_CmdTraceStartDelay::TraceConfig_CmdTraceStartDelay(TraceConfig_CmdTraceStartDelay&&) noexcept = default;
+TraceConfig_CmdTraceStartDelay& TraceConfig_CmdTraceStartDelay::operator=(TraceConfig_CmdTraceStartDelay&&) = default;
+
+bool TraceConfig_CmdTraceStartDelay::operator==(const TraceConfig_CmdTraceStartDelay& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(min_delay_ms_, other.min_delay_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_delay_ms_, other.max_delay_ms_);
+}
+
+bool TraceConfig_CmdTraceStartDelay::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* min_delay_ms */:
+ field.get(&min_delay_ms_);
+ break;
+ case 2 /* max_delay_ms */:
+ field.get(&max_delay_ms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_CmdTraceStartDelay::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_CmdTraceStartDelay::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_CmdTraceStartDelay::Serialize(::protozero::Message* msg) const {
+ // Field 1: min_delay_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, min_delay_ms_, msg);
+ }
+
+ // Field 2: max_delay_ms
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, max_delay_ms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_AndroidReportConfig::TraceConfig_AndroidReportConfig() = default;
+TraceConfig_AndroidReportConfig::~TraceConfig_AndroidReportConfig() = default;
+TraceConfig_AndroidReportConfig::TraceConfig_AndroidReportConfig(const TraceConfig_AndroidReportConfig&) = default;
+TraceConfig_AndroidReportConfig& TraceConfig_AndroidReportConfig::operator=(const TraceConfig_AndroidReportConfig&) = default;
+TraceConfig_AndroidReportConfig::TraceConfig_AndroidReportConfig(TraceConfig_AndroidReportConfig&&) noexcept = default;
+TraceConfig_AndroidReportConfig& TraceConfig_AndroidReportConfig::operator=(TraceConfig_AndroidReportConfig&&) = default;
+
+bool TraceConfig_AndroidReportConfig::operator==(const TraceConfig_AndroidReportConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(reporter_service_package_, other.reporter_service_package_)
+ && ::protozero::internal::gen_helpers::EqualsField(reporter_service_class_, other.reporter_service_class_)
+ && ::protozero::internal::gen_helpers::EqualsField(skip_report_, other.skip_report_)
+ && ::protozero::internal::gen_helpers::EqualsField(use_pipe_in_framework_for_testing_, other.use_pipe_in_framework_for_testing_);
+}
+
+bool TraceConfig_AndroidReportConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* reporter_service_package */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &reporter_service_package_);
+ break;
+ case 2 /* reporter_service_class */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &reporter_service_class_);
+ break;
+ case 3 /* skip_report */:
+ field.get(&skip_report_);
+ break;
+ case 4 /* use_pipe_in_framework_for_testing */:
+ field.get(&use_pipe_in_framework_for_testing_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_AndroidReportConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_AndroidReportConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_AndroidReportConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: reporter_service_package
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, reporter_service_package_, msg);
+ }
+
+ // Field 2: reporter_service_class
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, reporter_service_class_, msg);
+ }
+
+ // Field 3: skip_report
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, skip_report_, msg);
+ }
+
+ // Field 4: use_pipe_in_framework_for_testing
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, use_pipe_in_framework_for_testing_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_TraceFilter::TraceConfig_TraceFilter() = default;
+TraceConfig_TraceFilter::~TraceConfig_TraceFilter() = default;
+TraceConfig_TraceFilter::TraceConfig_TraceFilter(const TraceConfig_TraceFilter&) = default;
+TraceConfig_TraceFilter& TraceConfig_TraceFilter::operator=(const TraceConfig_TraceFilter&) = default;
+TraceConfig_TraceFilter::TraceConfig_TraceFilter(TraceConfig_TraceFilter&&) noexcept = default;
+TraceConfig_TraceFilter& TraceConfig_TraceFilter::operator=(TraceConfig_TraceFilter&&) = default;
+
+bool TraceConfig_TraceFilter::operator==(const TraceConfig_TraceFilter& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(bytecode_, other.bytecode_)
+ && ::protozero::internal::gen_helpers::EqualsField(bytecode_v2_, other.bytecode_v2_)
+ && ::protozero::internal::gen_helpers::EqualsField(string_filter_chain_, other.string_filter_chain_);
+}
+
+bool TraceConfig_TraceFilter::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* bytecode */:
+ field.get(&bytecode_);
+ break;
+ case 2 /* bytecode_v2 */:
+ field.get(&bytecode_v2_);
+ break;
+ case 3 /* string_filter_chain */:
+ (*string_filter_chain_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_TraceFilter::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_TraceFilter::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_TraceFilter::Serialize(::protozero::Message* msg) const {
+ // Field 1: bytecode
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, bytecode_, msg);
+ }
+
+ // Field 2: bytecode_v2
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, bytecode_v2_, msg);
+ }
+
+ // Field 3: string_filter_chain
+ if (_has_field_[3]) {
+ (*string_filter_chain_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_TraceFilter_StringFilterChain::TraceConfig_TraceFilter_StringFilterChain() = default;
+TraceConfig_TraceFilter_StringFilterChain::~TraceConfig_TraceFilter_StringFilterChain() = default;
+TraceConfig_TraceFilter_StringFilterChain::TraceConfig_TraceFilter_StringFilterChain(const TraceConfig_TraceFilter_StringFilterChain&) = default;
+TraceConfig_TraceFilter_StringFilterChain& TraceConfig_TraceFilter_StringFilterChain::operator=(const TraceConfig_TraceFilter_StringFilterChain&) = default;
+TraceConfig_TraceFilter_StringFilterChain::TraceConfig_TraceFilter_StringFilterChain(TraceConfig_TraceFilter_StringFilterChain&&) noexcept = default;
+TraceConfig_TraceFilter_StringFilterChain& TraceConfig_TraceFilter_StringFilterChain::operator=(TraceConfig_TraceFilter_StringFilterChain&&) = default;
+
+bool TraceConfig_TraceFilter_StringFilterChain::operator==(const TraceConfig_TraceFilter_StringFilterChain& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(rules_, other.rules_);
+}
+
+int TraceConfig_TraceFilter_StringFilterChain::rules_size() const { return static_cast<int>(rules_.size()); }
+void TraceConfig_TraceFilter_StringFilterChain::clear_rules() { rules_.clear(); }
+TraceConfig_TraceFilter_StringFilterRule* TraceConfig_TraceFilter_StringFilterChain::add_rules() { rules_.emplace_back(); return &rules_.back(); }
+bool TraceConfig_TraceFilter_StringFilterChain::ParseFromArray(const void* raw, size_t size) {
+ rules_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* rules */:
+ rules_.emplace_back();
+ rules_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_TraceFilter_StringFilterChain::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_TraceFilter_StringFilterChain::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_TraceFilter_StringFilterChain::Serialize(::protozero::Message* msg) const {
+ // Field 1: rules
+ for (auto& it : rules_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_TraceFilter_StringFilterRule::TraceConfig_TraceFilter_StringFilterRule() = default;
+TraceConfig_TraceFilter_StringFilterRule::~TraceConfig_TraceFilter_StringFilterRule() = default;
+TraceConfig_TraceFilter_StringFilterRule::TraceConfig_TraceFilter_StringFilterRule(const TraceConfig_TraceFilter_StringFilterRule&) = default;
+TraceConfig_TraceFilter_StringFilterRule& TraceConfig_TraceFilter_StringFilterRule::operator=(const TraceConfig_TraceFilter_StringFilterRule&) = default;
+TraceConfig_TraceFilter_StringFilterRule::TraceConfig_TraceFilter_StringFilterRule(TraceConfig_TraceFilter_StringFilterRule&&) noexcept = default;
+TraceConfig_TraceFilter_StringFilterRule& TraceConfig_TraceFilter_StringFilterRule::operator=(TraceConfig_TraceFilter_StringFilterRule&&) = default;
+
+bool TraceConfig_TraceFilter_StringFilterRule::operator==(const TraceConfig_TraceFilter_StringFilterRule& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(policy_, other.policy_)
+ && ::protozero::internal::gen_helpers::EqualsField(regex_pattern_, other.regex_pattern_)
+ && ::protozero::internal::gen_helpers::EqualsField(atrace_payload_starts_with_, other.atrace_payload_starts_with_);
+}
+
+bool TraceConfig_TraceFilter_StringFilterRule::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* policy */:
+ field.get(&policy_);
+ break;
+ case 2 /* regex_pattern */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &regex_pattern_);
+ break;
+ case 3 /* atrace_payload_starts_with */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &atrace_payload_starts_with_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_TraceFilter_StringFilterRule::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_TraceFilter_StringFilterRule::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_TraceFilter_StringFilterRule::Serialize(::protozero::Message* msg) const {
+ // Field 1: policy
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, policy_, msg);
+ }
+
+ // Field 2: regex_pattern
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, regex_pattern_, msg);
+ }
+
+ // Field 3: atrace_payload_starts_with
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, atrace_payload_starts_with_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_IncidentReportConfig::TraceConfig_IncidentReportConfig() = default;
+TraceConfig_IncidentReportConfig::~TraceConfig_IncidentReportConfig() = default;
+TraceConfig_IncidentReportConfig::TraceConfig_IncidentReportConfig(const TraceConfig_IncidentReportConfig&) = default;
+TraceConfig_IncidentReportConfig& TraceConfig_IncidentReportConfig::operator=(const TraceConfig_IncidentReportConfig&) = default;
+TraceConfig_IncidentReportConfig::TraceConfig_IncidentReportConfig(TraceConfig_IncidentReportConfig&&) noexcept = default;
+TraceConfig_IncidentReportConfig& TraceConfig_IncidentReportConfig::operator=(TraceConfig_IncidentReportConfig&&) = default;
+
+bool TraceConfig_IncidentReportConfig::operator==(const TraceConfig_IncidentReportConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(destination_package_, other.destination_package_)
+ && ::protozero::internal::gen_helpers::EqualsField(destination_class_, other.destination_class_)
+ && ::protozero::internal::gen_helpers::EqualsField(privacy_level_, other.privacy_level_)
+ && ::protozero::internal::gen_helpers::EqualsField(skip_incidentd_, other.skip_incidentd_)
+ && ::protozero::internal::gen_helpers::EqualsField(skip_dropbox_, other.skip_dropbox_);
+}
+
+bool TraceConfig_IncidentReportConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* destination_package */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &destination_package_);
+ break;
+ case 2 /* destination_class */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &destination_class_);
+ break;
+ case 3 /* privacy_level */:
+ field.get(&privacy_level_);
+ break;
+ case 5 /* skip_incidentd */:
+ field.get(&skip_incidentd_);
+ break;
+ case 4 /* skip_dropbox */:
+ field.get(&skip_dropbox_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_IncidentReportConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_IncidentReportConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_IncidentReportConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: destination_package
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, destination_package_, msg);
+ }
+
+ // Field 2: destination_class
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, destination_class_, msg);
+ }
+
+ // Field 3: privacy_level
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, privacy_level_, msg);
+ }
+
+ // Field 5: skip_incidentd
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, skip_incidentd_, msg);
+ }
+
+ // Field 4: skip_dropbox
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, skip_dropbox_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_IncrementalStateConfig::TraceConfig_IncrementalStateConfig() = default;
+TraceConfig_IncrementalStateConfig::~TraceConfig_IncrementalStateConfig() = default;
+TraceConfig_IncrementalStateConfig::TraceConfig_IncrementalStateConfig(const TraceConfig_IncrementalStateConfig&) = default;
+TraceConfig_IncrementalStateConfig& TraceConfig_IncrementalStateConfig::operator=(const TraceConfig_IncrementalStateConfig&) = default;
+TraceConfig_IncrementalStateConfig::TraceConfig_IncrementalStateConfig(TraceConfig_IncrementalStateConfig&&) noexcept = default;
+TraceConfig_IncrementalStateConfig& TraceConfig_IncrementalStateConfig::operator=(TraceConfig_IncrementalStateConfig&&) = default;
+
+bool TraceConfig_IncrementalStateConfig::operator==(const TraceConfig_IncrementalStateConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(clear_period_ms_, other.clear_period_ms_);
+}
+
+bool TraceConfig_IncrementalStateConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* clear_period_ms */:
+ field.get(&clear_period_ms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_IncrementalStateConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_IncrementalStateConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_IncrementalStateConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: clear_period_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, clear_period_ms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_TriggerConfig::TraceConfig_TriggerConfig() = default;
+TraceConfig_TriggerConfig::~TraceConfig_TriggerConfig() = default;
+TraceConfig_TriggerConfig::TraceConfig_TriggerConfig(const TraceConfig_TriggerConfig&) = default;
+TraceConfig_TriggerConfig& TraceConfig_TriggerConfig::operator=(const TraceConfig_TriggerConfig&) = default;
+TraceConfig_TriggerConfig::TraceConfig_TriggerConfig(TraceConfig_TriggerConfig&&) noexcept = default;
+TraceConfig_TriggerConfig& TraceConfig_TriggerConfig::operator=(TraceConfig_TriggerConfig&&) = default;
+
+bool TraceConfig_TriggerConfig::operator==(const TraceConfig_TriggerConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trigger_mode_, other.trigger_mode_)
+ && ::protozero::internal::gen_helpers::EqualsField(use_clone_snapshot_if_available_, other.use_clone_snapshot_if_available_)
+ && ::protozero::internal::gen_helpers::EqualsField(triggers_, other.triggers_)
+ && ::protozero::internal::gen_helpers::EqualsField(trigger_timeout_ms_, other.trigger_timeout_ms_);
+}
+
+int TraceConfig_TriggerConfig::triggers_size() const { return static_cast<int>(triggers_.size()); }
+void TraceConfig_TriggerConfig::clear_triggers() { triggers_.clear(); }
+TraceConfig_TriggerConfig_Trigger* TraceConfig_TriggerConfig::add_triggers() { triggers_.emplace_back(); return &triggers_.back(); }
+bool TraceConfig_TriggerConfig::ParseFromArray(const void* raw, size_t size) {
+ triggers_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trigger_mode */:
+ field.get(&trigger_mode_);
+ break;
+ case 5 /* use_clone_snapshot_if_available */:
+ field.get(&use_clone_snapshot_if_available_);
+ break;
+ case 2 /* triggers */:
+ triggers_.emplace_back();
+ triggers_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 3 /* trigger_timeout_ms */:
+ field.get(&trigger_timeout_ms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_TriggerConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_TriggerConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_TriggerConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: trigger_mode
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, trigger_mode_, msg);
+ }
+
+ // Field 5: use_clone_snapshot_if_available
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, use_clone_snapshot_if_available_, msg);
+ }
+
+ // Field 2: triggers
+ for (auto& it : triggers_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 3: trigger_timeout_ms
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, trigger_timeout_ms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_TriggerConfig_Trigger::TraceConfig_TriggerConfig_Trigger() = default;
+TraceConfig_TriggerConfig_Trigger::~TraceConfig_TriggerConfig_Trigger() = default;
+TraceConfig_TriggerConfig_Trigger::TraceConfig_TriggerConfig_Trigger(const TraceConfig_TriggerConfig_Trigger&) = default;
+TraceConfig_TriggerConfig_Trigger& TraceConfig_TriggerConfig_Trigger::operator=(const TraceConfig_TriggerConfig_Trigger&) = default;
+TraceConfig_TriggerConfig_Trigger::TraceConfig_TriggerConfig_Trigger(TraceConfig_TriggerConfig_Trigger&&) noexcept = default;
+TraceConfig_TriggerConfig_Trigger& TraceConfig_TriggerConfig_Trigger::operator=(TraceConfig_TriggerConfig_Trigger&&) = default;
+
+bool TraceConfig_TriggerConfig_Trigger::operator==(const TraceConfig_TriggerConfig_Trigger& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_name_regex_, other.producer_name_regex_)
+ && ::protozero::internal::gen_helpers::EqualsField(stop_delay_ms_, other.stop_delay_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_per_24_h_, other.max_per_24_h_)
+ && ::protozero::internal::gen_helpers::EqualsField(skip_probability_, other.skip_probability_);
+}
+
+bool TraceConfig_TriggerConfig_Trigger::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* producer_name_regex */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &producer_name_regex_);
+ break;
+ case 3 /* stop_delay_ms */:
+ field.get(&stop_delay_ms_);
+ break;
+ case 4 /* max_per_24_h */:
+ field.get(&max_per_24_h_);
+ break;
+ case 5 /* skip_probability */:
+ field.get(&skip_probability_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_TriggerConfig_Trigger::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_TriggerConfig_Trigger::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_TriggerConfig_Trigger::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ // Field 2: producer_name_regex
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, producer_name_regex_, msg);
+ }
+
+ // Field 3: stop_delay_ms
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, stop_delay_ms_, msg);
+ }
+
+ // Field 4: max_per_24_h
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, max_per_24_h_, msg);
+ }
+
+ // Field 5: skip_probability
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(5, skip_probability_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_GuardrailOverrides::TraceConfig_GuardrailOverrides() = default;
+TraceConfig_GuardrailOverrides::~TraceConfig_GuardrailOverrides() = default;
+TraceConfig_GuardrailOverrides::TraceConfig_GuardrailOverrides(const TraceConfig_GuardrailOverrides&) = default;
+TraceConfig_GuardrailOverrides& TraceConfig_GuardrailOverrides::operator=(const TraceConfig_GuardrailOverrides&) = default;
+TraceConfig_GuardrailOverrides::TraceConfig_GuardrailOverrides(TraceConfig_GuardrailOverrides&&) noexcept = default;
+TraceConfig_GuardrailOverrides& TraceConfig_GuardrailOverrides::operator=(TraceConfig_GuardrailOverrides&&) = default;
+
+bool TraceConfig_GuardrailOverrides::operator==(const TraceConfig_GuardrailOverrides& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_upload_per_day_bytes_, other.max_upload_per_day_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(max_tracing_buffer_size_kb_, other.max_tracing_buffer_size_kb_);
+}
+
+bool TraceConfig_GuardrailOverrides::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* max_upload_per_day_bytes */:
+ field.get(&max_upload_per_day_bytes_);
+ break;
+ case 2 /* max_tracing_buffer_size_kb */:
+ field.get(&max_tracing_buffer_size_kb_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_GuardrailOverrides::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_GuardrailOverrides::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_GuardrailOverrides::Serialize(::protozero::Message* msg) const {
+ // Field 1: max_upload_per_day_bytes
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, max_upload_per_day_bytes_, msg);
+ }
+
+ // Field 2: max_tracing_buffer_size_kb
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, max_tracing_buffer_size_kb_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_StatsdMetadata::TraceConfig_StatsdMetadata() = default;
+TraceConfig_StatsdMetadata::~TraceConfig_StatsdMetadata() = default;
+TraceConfig_StatsdMetadata::TraceConfig_StatsdMetadata(const TraceConfig_StatsdMetadata&) = default;
+TraceConfig_StatsdMetadata& TraceConfig_StatsdMetadata::operator=(const TraceConfig_StatsdMetadata&) = default;
+TraceConfig_StatsdMetadata::TraceConfig_StatsdMetadata(TraceConfig_StatsdMetadata&&) noexcept = default;
+TraceConfig_StatsdMetadata& TraceConfig_StatsdMetadata::operator=(TraceConfig_StatsdMetadata&&) = default;
+
+bool TraceConfig_StatsdMetadata::operator==(const TraceConfig_StatsdMetadata& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(triggering_alert_id_, other.triggering_alert_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(triggering_config_uid_, other.triggering_config_uid_)
+ && ::protozero::internal::gen_helpers::EqualsField(triggering_config_id_, other.triggering_config_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(triggering_subscription_id_, other.triggering_subscription_id_);
+}
+
+bool TraceConfig_StatsdMetadata::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* triggering_alert_id */:
+ field.get(&triggering_alert_id_);
+ break;
+ case 2 /* triggering_config_uid */:
+ field.get(&triggering_config_uid_);
+ break;
+ case 3 /* triggering_config_id */:
+ field.get(&triggering_config_id_);
+ break;
+ case 4 /* triggering_subscription_id */:
+ field.get(&triggering_subscription_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_StatsdMetadata::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_StatsdMetadata::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_StatsdMetadata::Serialize(::protozero::Message* msg) const {
+ // Field 1: triggering_alert_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, triggering_alert_id_, msg);
+ }
+
+ // Field 2: triggering_config_uid
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, triggering_config_uid_, msg);
+ }
+
+ // Field 3: triggering_config_id
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, triggering_config_id_, msg);
+ }
+
+ // Field 4: triggering_subscription_id
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, triggering_subscription_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_ProducerConfig::TraceConfig_ProducerConfig() = default;
+TraceConfig_ProducerConfig::~TraceConfig_ProducerConfig() = default;
+TraceConfig_ProducerConfig::TraceConfig_ProducerConfig(const TraceConfig_ProducerConfig&) = default;
+TraceConfig_ProducerConfig& TraceConfig_ProducerConfig::operator=(const TraceConfig_ProducerConfig&) = default;
+TraceConfig_ProducerConfig::TraceConfig_ProducerConfig(TraceConfig_ProducerConfig&&) noexcept = default;
+TraceConfig_ProducerConfig& TraceConfig_ProducerConfig::operator=(TraceConfig_ProducerConfig&&) = default;
+
+bool TraceConfig_ProducerConfig::operator==(const TraceConfig_ProducerConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_name_, other.producer_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(shm_size_kb_, other.shm_size_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(page_size_kb_, other.page_size_kb_);
+}
+
+bool TraceConfig_ProducerConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* producer_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &producer_name_);
+ break;
+ case 2 /* shm_size_kb */:
+ field.get(&shm_size_kb_);
+ break;
+ case 3 /* page_size_kb */:
+ field.get(&page_size_kb_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_ProducerConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_ProducerConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_ProducerConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: producer_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, producer_name_, msg);
+ }
+
+ // Field 2: shm_size_kb
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, shm_size_kb_, msg);
+ }
+
+ // Field 3: page_size_kb
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, page_size_kb_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_BuiltinDataSource::TraceConfig_BuiltinDataSource() = default;
+TraceConfig_BuiltinDataSource::~TraceConfig_BuiltinDataSource() = default;
+TraceConfig_BuiltinDataSource::TraceConfig_BuiltinDataSource(const TraceConfig_BuiltinDataSource&) = default;
+TraceConfig_BuiltinDataSource& TraceConfig_BuiltinDataSource::operator=(const TraceConfig_BuiltinDataSource&) = default;
+TraceConfig_BuiltinDataSource::TraceConfig_BuiltinDataSource(TraceConfig_BuiltinDataSource&&) noexcept = default;
+TraceConfig_BuiltinDataSource& TraceConfig_BuiltinDataSource::operator=(TraceConfig_BuiltinDataSource&&) = default;
+
+bool TraceConfig_BuiltinDataSource::operator==(const TraceConfig_BuiltinDataSource& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_clock_snapshotting_, other.disable_clock_snapshotting_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_trace_config_, other.disable_trace_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_system_info_, other.disable_system_info_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_service_events_, other.disable_service_events_)
+ && ::protozero::internal::gen_helpers::EqualsField(primary_trace_clock_, other.primary_trace_clock_)
+ && ::protozero::internal::gen_helpers::EqualsField(snapshot_interval_ms_, other.snapshot_interval_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(prefer_suspend_clock_for_snapshot_, other.prefer_suspend_clock_for_snapshot_)
+ && ::protozero::internal::gen_helpers::EqualsField(disable_chunk_usage_histograms_, other.disable_chunk_usage_histograms_);
+}
+
+bool TraceConfig_BuiltinDataSource::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* disable_clock_snapshotting */:
+ field.get(&disable_clock_snapshotting_);
+ break;
+ case 2 /* disable_trace_config */:
+ field.get(&disable_trace_config_);
+ break;
+ case 3 /* disable_system_info */:
+ field.get(&disable_system_info_);
+ break;
+ case 4 /* disable_service_events */:
+ field.get(&disable_service_events_);
+ break;
+ case 5 /* primary_trace_clock */:
+ field.get(&primary_trace_clock_);
+ break;
+ case 6 /* snapshot_interval_ms */:
+ field.get(&snapshot_interval_ms_);
+ break;
+ case 7 /* prefer_suspend_clock_for_snapshot */:
+ field.get(&prefer_suspend_clock_for_snapshot_);
+ break;
+ case 8 /* disable_chunk_usage_histograms */:
+ field.get(&disable_chunk_usage_histograms_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_BuiltinDataSource::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_BuiltinDataSource::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_BuiltinDataSource::Serialize(::protozero::Message* msg) const {
+ // Field 1: disable_clock_snapshotting
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, disable_clock_snapshotting_, msg);
+ }
+
+ // Field 2: disable_trace_config
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, disable_trace_config_, msg);
+ }
+
+ // Field 3: disable_system_info
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, disable_system_info_, msg);
+ }
+
+ // Field 4: disable_service_events
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, disable_service_events_, msg);
+ }
+
+ // Field 5: primary_trace_clock
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, primary_trace_clock_, msg);
+ }
+
+ // Field 6: snapshot_interval_ms
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, snapshot_interval_ms_, msg);
+ }
+
+ // Field 7: prefer_suspend_clock_for_snapshot
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(7, prefer_suspend_clock_for_snapshot_, msg);
+ }
+
+ // Field 8: disable_chunk_usage_histograms
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(8, disable_chunk_usage_histograms_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_DataSource::TraceConfig_DataSource() = default;
+TraceConfig_DataSource::~TraceConfig_DataSource() = default;
+TraceConfig_DataSource::TraceConfig_DataSource(const TraceConfig_DataSource&) = default;
+TraceConfig_DataSource& TraceConfig_DataSource::operator=(const TraceConfig_DataSource&) = default;
+TraceConfig_DataSource::TraceConfig_DataSource(TraceConfig_DataSource&&) noexcept = default;
+TraceConfig_DataSource& TraceConfig_DataSource::operator=(TraceConfig_DataSource&&) = default;
+
+bool TraceConfig_DataSource::operator==(const TraceConfig_DataSource& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(config_, other.config_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_name_filter_, other.producer_name_filter_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_name_regex_filter_, other.producer_name_regex_filter_);
+}
+
+bool TraceConfig_DataSource::ParseFromArray(const void* raw, size_t size) {
+ producer_name_filter_.clear();
+ producer_name_regex_filter_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* config */:
+ (*config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* producer_name_filter */:
+ producer_name_filter_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &producer_name_filter_.back());
+ break;
+ case 3 /* producer_name_regex_filter */:
+ producer_name_regex_filter_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &producer_name_regex_filter_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_DataSource::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_DataSource::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_DataSource::Serialize(::protozero::Message* msg) const {
+ // Field 1: config
+ if (_has_field_[1]) {
+ (*config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: producer_name_filter
+ for (auto& it : producer_name_filter_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 3: producer_name_regex_filter
+ for (auto& it : producer_name_regex_filter_) {
+ ::protozero::internal::gen_helpers::SerializeString(3, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TraceConfig_BufferConfig::TraceConfig_BufferConfig() = default;
+TraceConfig_BufferConfig::~TraceConfig_BufferConfig() = default;
+TraceConfig_BufferConfig::TraceConfig_BufferConfig(const TraceConfig_BufferConfig&) = default;
+TraceConfig_BufferConfig& TraceConfig_BufferConfig::operator=(const TraceConfig_BufferConfig&) = default;
+TraceConfig_BufferConfig::TraceConfig_BufferConfig(TraceConfig_BufferConfig&&) noexcept = default;
+TraceConfig_BufferConfig& TraceConfig_BufferConfig::operator=(TraceConfig_BufferConfig&&) = default;
+
+bool TraceConfig_BufferConfig::operator==(const TraceConfig_BufferConfig& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(size_kb_, other.size_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(fill_policy_, other.fill_policy_)
+ && ::protozero::internal::gen_helpers::EqualsField(transfer_on_clone_, other.transfer_on_clone_)
+ && ::protozero::internal::gen_helpers::EqualsField(clear_before_clone_, other.clear_before_clone_);
+}
+
+bool TraceConfig_BufferConfig::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* size_kb */:
+ field.get(&size_kb_);
+ break;
+ case 4 /* fill_policy */:
+ field.get(&fill_policy_);
+ break;
+ case 5 /* transfer_on_clone */:
+ field.get(&transfer_on_clone_);
+ break;
+ case 6 /* clear_before_clone */:
+ field.get(&clear_before_clone_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TraceConfig_BufferConfig::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TraceConfig_BufferConfig::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TraceConfig_BufferConfig::Serialize(::protozero::Message* msg) const {
+ // Field 1: size_kb
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, size_kb_, msg);
+ }
+
+ // Field 4: fill_policy
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, fill_policy_, msg);
+ }
+
+ // Field 5: transfer_on_clone
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, transfer_on_clone_, msg);
+ }
+
+ // Field 6: clear_before_clone
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(6, clear_before_clone_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/common/android_energy_consumer_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/android_log_constants.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/builtin_clock.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/commit_data_request.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/data_source_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/ftrace_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/gpu_counter_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/interceptor_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/observable_events.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/perf_events.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/protolog_common.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/sys_stats_counters.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/trace_stats.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/tracing_service_capabilities.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/tracing_service_state.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/common/track_event_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/android_game_intervention_list.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/android_input_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/android_log.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/android_system_property.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/camera_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/frame_timeline_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/gpu_mem_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/graphics_frame_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/initial_display_state.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/network_trace.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/packages_list.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/protolog.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/shell_transition.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/surfaceflinger_common.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/surfaceflinger_layers.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/android/surfaceflinger_transactions.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/chrome/chrome_metadata.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/chrome/v8.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/gpu/gpu_log.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/profiling/deobfuscation.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/profiling/heap_graph.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/profiling/profile_common.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/profiling/profile_packet.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/profiling/smaps.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_active_processes.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_application_state_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_content_settings_event_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_frame_reporter.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_latency_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_message_pump.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_user_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_window_handle_event_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/counter_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/debug_annotation.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/log_message.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/pixel_modem.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/process_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/range_of_interest.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/screenshot.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/source_location.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/task_execution.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/thread_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/track_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/track_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/interned_data/interned_data.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_active_processes.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_active_processes.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeActiveProcesses::ChromeActiveProcesses() = default;
+ChromeActiveProcesses::~ChromeActiveProcesses() = default;
+ChromeActiveProcesses::ChromeActiveProcesses(const ChromeActiveProcesses&) = default;
+ChromeActiveProcesses& ChromeActiveProcesses::operator=(const ChromeActiveProcesses&) = default;
+ChromeActiveProcesses::ChromeActiveProcesses(ChromeActiveProcesses&&) noexcept = default;
+ChromeActiveProcesses& ChromeActiveProcesses::operator=(ChromeActiveProcesses&&) = default;
+
+bool ChromeActiveProcesses::operator==(const ChromeActiveProcesses& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_, other.pid_);
+}
+
+bool ChromeActiveProcesses::ParseFromArray(const void* raw, size_t size) {
+ pid_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* pid */:
+ pid_.emplace_back();
+ field.get(&pid_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeActiveProcesses::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeActiveProcesses::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeActiveProcesses::Serialize(::protozero::Message* msg) const {
+ // Field 1: pid
+ for (auto& it : pid_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_application_state_info.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_application_state_info.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeApplicationStateInfo::ChromeApplicationStateInfo() = default;
+ChromeApplicationStateInfo::~ChromeApplicationStateInfo() = default;
+ChromeApplicationStateInfo::ChromeApplicationStateInfo(const ChromeApplicationStateInfo&) = default;
+ChromeApplicationStateInfo& ChromeApplicationStateInfo::operator=(const ChromeApplicationStateInfo&) = default;
+ChromeApplicationStateInfo::ChromeApplicationStateInfo(ChromeApplicationStateInfo&&) noexcept = default;
+ChromeApplicationStateInfo& ChromeApplicationStateInfo::operator=(ChromeApplicationStateInfo&&) = default;
+
+bool ChromeApplicationStateInfo::operator==(const ChromeApplicationStateInfo& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(application_state_, other.application_state_);
+}
+
+bool ChromeApplicationStateInfo::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* application_state */:
+ field.get(&application_state_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeApplicationStateInfo::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeApplicationStateInfo::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeApplicationStateInfo::Serialize(::protozero::Message* msg) const {
+ // Field 1: application_state
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, application_state_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/source_location.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+CompositorTimingHistory::CompositorTimingHistory() = default;
+CompositorTimingHistory::~CompositorTimingHistory() = default;
+CompositorTimingHistory::CompositorTimingHistory(const CompositorTimingHistory&) = default;
+CompositorTimingHistory& CompositorTimingHistory::operator=(const CompositorTimingHistory&) = default;
+CompositorTimingHistory::CompositorTimingHistory(CompositorTimingHistory&&) noexcept = default;
+CompositorTimingHistory& CompositorTimingHistory::operator=(CompositorTimingHistory&&) = default;
+
+bool CompositorTimingHistory::operator==(const CompositorTimingHistory& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_main_frame_queue_critical_estimate_delta_us_, other.begin_main_frame_queue_critical_estimate_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_main_frame_queue_not_critical_estimate_delta_us_, other.begin_main_frame_queue_not_critical_estimate_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_main_frame_start_to_ready_to_commit_estimate_delta_us_, other.begin_main_frame_start_to_ready_to_commit_estimate_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(commit_to_ready_to_activate_estimate_delta_us_, other.commit_to_ready_to_activate_estimate_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(prepare_tiles_estimate_delta_us_, other.prepare_tiles_estimate_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(activate_estimate_delta_us_, other.activate_estimate_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(draw_estimate_delta_us_, other.draw_estimate_delta_us_);
+}
+
+bool CompositorTimingHistory::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* begin_main_frame_queue_critical_estimate_delta_us */:
+ field.get(&begin_main_frame_queue_critical_estimate_delta_us_);
+ break;
+ case 2 /* begin_main_frame_queue_not_critical_estimate_delta_us */:
+ field.get(&begin_main_frame_queue_not_critical_estimate_delta_us_);
+ break;
+ case 3 /* begin_main_frame_start_to_ready_to_commit_estimate_delta_us */:
+ field.get(&begin_main_frame_start_to_ready_to_commit_estimate_delta_us_);
+ break;
+ case 4 /* commit_to_ready_to_activate_estimate_delta_us */:
+ field.get(&commit_to_ready_to_activate_estimate_delta_us_);
+ break;
+ case 5 /* prepare_tiles_estimate_delta_us */:
+ field.get(&prepare_tiles_estimate_delta_us_);
+ break;
+ case 6 /* activate_estimate_delta_us */:
+ field.get(&activate_estimate_delta_us_);
+ break;
+ case 7 /* draw_estimate_delta_us */:
+ field.get(&draw_estimate_delta_us_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CompositorTimingHistory::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CompositorTimingHistory::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CompositorTimingHistory::Serialize(::protozero::Message* msg) const {
+ // Field 1: begin_main_frame_queue_critical_estimate_delta_us
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, begin_main_frame_queue_critical_estimate_delta_us_, msg);
+ }
+
+ // Field 2: begin_main_frame_queue_not_critical_estimate_delta_us
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, begin_main_frame_queue_not_critical_estimate_delta_us_, msg);
+ }
+
+ // Field 3: begin_main_frame_start_to_ready_to_commit_estimate_delta_us
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, begin_main_frame_start_to_ready_to_commit_estimate_delta_us_, msg);
+ }
+
+ // Field 4: commit_to_ready_to_activate_estimate_delta_us
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, commit_to_ready_to_activate_estimate_delta_us_, msg);
+ }
+
+ // Field 5: prepare_tiles_estimate_delta_us
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, prepare_tiles_estimate_delta_us_, msg);
+ }
+
+ // Field 6: activate_estimate_delta_us
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, activate_estimate_delta_us_, msg);
+ }
+
+ // Field 7: draw_estimate_delta_us
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, draw_estimate_delta_us_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+BeginFrameSourceState::BeginFrameSourceState() = default;
+BeginFrameSourceState::~BeginFrameSourceState() = default;
+BeginFrameSourceState::BeginFrameSourceState(const BeginFrameSourceState&) = default;
+BeginFrameSourceState& BeginFrameSourceState::operator=(const BeginFrameSourceState&) = default;
+BeginFrameSourceState::BeginFrameSourceState(BeginFrameSourceState&&) noexcept = default;
+BeginFrameSourceState& BeginFrameSourceState::operator=(BeginFrameSourceState&&) = default;
+
+bool BeginFrameSourceState::operator==(const BeginFrameSourceState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(source_id_, other.source_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(paused_, other.paused_)
+ && ::protozero::internal::gen_helpers::EqualsField(num_observers_, other.num_observers_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_begin_frame_args_, other.last_begin_frame_args_);
+}
+
+bool BeginFrameSourceState::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* source_id */:
+ field.get(&source_id_);
+ break;
+ case 2 /* paused */:
+ field.get(&paused_);
+ break;
+ case 3 /* num_observers */:
+ field.get(&num_observers_);
+ break;
+ case 4 /* last_begin_frame_args */:
+ (*last_begin_frame_args_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string BeginFrameSourceState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> BeginFrameSourceState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void BeginFrameSourceState::Serialize(::protozero::Message* msg) const {
+ // Field 1: source_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, source_id_, msg);
+ }
+
+ // Field 2: paused
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, paused_, msg);
+ }
+
+ // Field 3: num_observers
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, num_observers_, msg);
+ }
+
+ // Field 4: last_begin_frame_args
+ if (_has_field_[4]) {
+ (*last_begin_frame_args_).Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+BeginFrameArgs::BeginFrameArgs() = default;
+BeginFrameArgs::~BeginFrameArgs() = default;
+BeginFrameArgs::BeginFrameArgs(const BeginFrameArgs&) = default;
+BeginFrameArgs& BeginFrameArgs::operator=(const BeginFrameArgs&) = default;
+BeginFrameArgs::BeginFrameArgs(BeginFrameArgs&&) noexcept = default;
+BeginFrameArgs& BeginFrameArgs::operator=(BeginFrameArgs&&) = default;
+
+bool BeginFrameArgs::operator==(const BeginFrameArgs& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_, other.type_)
+ && ::protozero::internal::gen_helpers::EqualsField(source_id_, other.source_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(sequence_number_, other.sequence_number_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_time_us_, other.frame_time_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(deadline_us_, other.deadline_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(interval_delta_us_, other.interval_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(on_critical_path_, other.on_critical_path_)
+ && ::protozero::internal::gen_helpers::EqualsField(animate_only_, other.animate_only_)
+ && ::protozero::internal::gen_helpers::EqualsField(source_location_iid_, other.source_location_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(source_location_, other.source_location_)
+ && ::protozero::internal::gen_helpers::EqualsField(frames_throttled_since_last_, other.frames_throttled_since_last_);
+}
+
+bool BeginFrameArgs::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* type */:
+ field.get(&type_);
+ break;
+ case 2 /* source_id */:
+ field.get(&source_id_);
+ break;
+ case 3 /* sequence_number */:
+ field.get(&sequence_number_);
+ break;
+ case 4 /* frame_time_us */:
+ field.get(&frame_time_us_);
+ break;
+ case 5 /* deadline_us */:
+ field.get(&deadline_us_);
+ break;
+ case 6 /* interval_delta_us */:
+ field.get(&interval_delta_us_);
+ break;
+ case 7 /* on_critical_path */:
+ field.get(&on_critical_path_);
+ break;
+ case 8 /* animate_only */:
+ field.get(&animate_only_);
+ break;
+ case 9 /* source_location_iid */:
+ field.get(&source_location_iid_);
+ break;
+ case 10 /* source_location */:
+ (*source_location_).ParseFromArray(field.data(), field.size());
+ break;
+ case 12 /* frames_throttled_since_last */:
+ field.get(&frames_throttled_since_last_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string BeginFrameArgs::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> BeginFrameArgs::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void BeginFrameArgs::Serialize(::protozero::Message* msg) const {
+ // Field 1: type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, type_, msg);
+ }
+
+ // Field 2: source_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, source_id_, msg);
+ }
+
+ // Field 3: sequence_number
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, sequence_number_, msg);
+ }
+
+ // Field 4: frame_time_us
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, frame_time_us_, msg);
+ }
+
+ // Field 5: deadline_us
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, deadline_us_, msg);
+ }
+
+ // Field 6: interval_delta_us
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, interval_delta_us_, msg);
+ }
+
+ // Field 7: on_critical_path
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(7, on_critical_path_, msg);
+ }
+
+ // Field 8: animate_only
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(8, animate_only_, msg);
+ }
+
+ // Field 9: source_location_iid
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, source_location_iid_, msg);
+ }
+
+ // Field 10: source_location
+ if (_has_field_[10]) {
+ (*source_location_).Serialize(msg->BeginNestedMessage<::protozero::Message>(10));
+ }
+
+ // Field 12: frames_throttled_since_last
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(12, frames_throttled_since_last_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+BeginFrameObserverState::BeginFrameObserverState() = default;
+BeginFrameObserverState::~BeginFrameObserverState() = default;
+BeginFrameObserverState::BeginFrameObserverState(const BeginFrameObserverState&) = default;
+BeginFrameObserverState& BeginFrameObserverState::operator=(const BeginFrameObserverState&) = default;
+BeginFrameObserverState::BeginFrameObserverState(BeginFrameObserverState&&) noexcept = default;
+BeginFrameObserverState& BeginFrameObserverState::operator=(BeginFrameObserverState&&) = default;
+
+bool BeginFrameObserverState::operator==(const BeginFrameObserverState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(dropped_begin_frame_args_, other.dropped_begin_frame_args_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_begin_frame_args_, other.last_begin_frame_args_);
+}
+
+bool BeginFrameObserverState::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* dropped_begin_frame_args */:
+ field.get(&dropped_begin_frame_args_);
+ break;
+ case 2 /* last_begin_frame_args */:
+ (*last_begin_frame_args_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string BeginFrameObserverState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> BeginFrameObserverState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void BeginFrameObserverState::Serialize(::protozero::Message* msg) const {
+ // Field 1: dropped_begin_frame_args
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, dropped_begin_frame_args_, msg);
+ }
+
+ // Field 2: last_begin_frame_args
+ if (_has_field_[2]) {
+ (*last_begin_frame_args_).Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+BeginImplFrameArgs::BeginImplFrameArgs() = default;
+BeginImplFrameArgs::~BeginImplFrameArgs() = default;
+BeginImplFrameArgs::BeginImplFrameArgs(const BeginImplFrameArgs&) = default;
+BeginImplFrameArgs& BeginImplFrameArgs::operator=(const BeginImplFrameArgs&) = default;
+BeginImplFrameArgs::BeginImplFrameArgs(BeginImplFrameArgs&&) noexcept = default;
+BeginImplFrameArgs& BeginImplFrameArgs::operator=(BeginImplFrameArgs&&) = default;
+
+bool BeginImplFrameArgs::operator==(const BeginImplFrameArgs& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(updated_at_us_, other.updated_at_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(finished_at_us_, other.finished_at_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(state_, other.state_)
+ && ::protozero::internal::gen_helpers::EqualsField(current_args_, other.current_args_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_args_, other.last_args_)
+ && ::protozero::internal::gen_helpers::EqualsField(timestamps_in_us_, other.timestamps_in_us_);
+}
+
+bool BeginImplFrameArgs::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* updated_at_us */:
+ field.get(&updated_at_us_);
+ break;
+ case 2 /* finished_at_us */:
+ field.get(&finished_at_us_);
+ break;
+ case 3 /* state */:
+ field.get(&state_);
+ break;
+ case 4 /* current_args */:
+ (*current_args_).ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* last_args */:
+ (*last_args_).ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* timestamps_in_us */:
+ (*timestamps_in_us_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string BeginImplFrameArgs::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> BeginImplFrameArgs::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void BeginImplFrameArgs::Serialize(::protozero::Message* msg) const {
+ // Field 1: updated_at_us
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, updated_at_us_, msg);
+ }
+
+ // Field 2: finished_at_us
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, finished_at_us_, msg);
+ }
+
+ // Field 3: state
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, state_, msg);
+ }
+
+ // Field 4: current_args
+ if (_has_field_[4]) {
+ (*current_args_).Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: last_args
+ if (_has_field_[5]) {
+ (*last_args_).Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 6: timestamps_in_us
+ if (_has_field_[6]) {
+ (*timestamps_in_us_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+BeginImplFrameArgs_TimestampsInUs::BeginImplFrameArgs_TimestampsInUs() = default;
+BeginImplFrameArgs_TimestampsInUs::~BeginImplFrameArgs_TimestampsInUs() = default;
+BeginImplFrameArgs_TimestampsInUs::BeginImplFrameArgs_TimestampsInUs(const BeginImplFrameArgs_TimestampsInUs&) = default;
+BeginImplFrameArgs_TimestampsInUs& BeginImplFrameArgs_TimestampsInUs::operator=(const BeginImplFrameArgs_TimestampsInUs&) = default;
+BeginImplFrameArgs_TimestampsInUs::BeginImplFrameArgs_TimestampsInUs(BeginImplFrameArgs_TimestampsInUs&&) noexcept = default;
+BeginImplFrameArgs_TimestampsInUs& BeginImplFrameArgs_TimestampsInUs::operator=(BeginImplFrameArgs_TimestampsInUs&&) = default;
+
+bool BeginImplFrameArgs_TimestampsInUs::operator==(const BeginImplFrameArgs_TimestampsInUs& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(interval_delta_, other.interval_delta_)
+ && ::protozero::internal::gen_helpers::EqualsField(now_to_deadline_delta_, other.now_to_deadline_delta_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_time_to_now_delta_, other.frame_time_to_now_delta_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_time_to_deadline_delta_, other.frame_time_to_deadline_delta_)
+ && ::protozero::internal::gen_helpers::EqualsField(now_, other.now_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_time_, other.frame_time_)
+ && ::protozero::internal::gen_helpers::EqualsField(deadline_, other.deadline_);
+}
+
+bool BeginImplFrameArgs_TimestampsInUs::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* interval_delta */:
+ field.get(&interval_delta_);
+ break;
+ case 2 /* now_to_deadline_delta */:
+ field.get(&now_to_deadline_delta_);
+ break;
+ case 3 /* frame_time_to_now_delta */:
+ field.get(&frame_time_to_now_delta_);
+ break;
+ case 4 /* frame_time_to_deadline_delta */:
+ field.get(&frame_time_to_deadline_delta_);
+ break;
+ case 5 /* now */:
+ field.get(&now_);
+ break;
+ case 6 /* frame_time */:
+ field.get(&frame_time_);
+ break;
+ case 7 /* deadline */:
+ field.get(&deadline_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string BeginImplFrameArgs_TimestampsInUs::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> BeginImplFrameArgs_TimestampsInUs::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void BeginImplFrameArgs_TimestampsInUs::Serialize(::protozero::Message* msg) const {
+ // Field 1: interval_delta
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, interval_delta_, msg);
+ }
+
+ // Field 2: now_to_deadline_delta
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, now_to_deadline_delta_, msg);
+ }
+
+ // Field 3: frame_time_to_now_delta
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, frame_time_to_now_delta_, msg);
+ }
+
+ // Field 4: frame_time_to_deadline_delta
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, frame_time_to_deadline_delta_, msg);
+ }
+
+ // Field 5: now
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, now_, msg);
+ }
+
+ // Field 6: frame_time
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, frame_time_, msg);
+ }
+
+ // Field 7: deadline
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, deadline_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChromeCompositorStateMachine::ChromeCompositorStateMachine() = default;
+ChromeCompositorStateMachine::~ChromeCompositorStateMachine() = default;
+ChromeCompositorStateMachine::ChromeCompositorStateMachine(const ChromeCompositorStateMachine&) = default;
+ChromeCompositorStateMachine& ChromeCompositorStateMachine::operator=(const ChromeCompositorStateMachine&) = default;
+ChromeCompositorStateMachine::ChromeCompositorStateMachine(ChromeCompositorStateMachine&&) noexcept = default;
+ChromeCompositorStateMachine& ChromeCompositorStateMachine::operator=(ChromeCompositorStateMachine&&) = default;
+
+bool ChromeCompositorStateMachine::operator==(const ChromeCompositorStateMachine& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(major_state_, other.major_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(minor_state_, other.minor_state_);
+}
+
+bool ChromeCompositorStateMachine::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* major_state */:
+ (*major_state_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* minor_state */:
+ (*minor_state_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeCompositorStateMachine::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeCompositorStateMachine::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeCompositorStateMachine::Serialize(::protozero::Message* msg) const {
+ // Field 1: major_state
+ if (_has_field_[1]) {
+ (*major_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: minor_state
+ if (_has_field_[2]) {
+ (*minor_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChromeCompositorStateMachine_MinorState::ChromeCompositorStateMachine_MinorState() = default;
+ChromeCompositorStateMachine_MinorState::~ChromeCompositorStateMachine_MinorState() = default;
+ChromeCompositorStateMachine_MinorState::ChromeCompositorStateMachine_MinorState(const ChromeCompositorStateMachine_MinorState&) = default;
+ChromeCompositorStateMachine_MinorState& ChromeCompositorStateMachine_MinorState::operator=(const ChromeCompositorStateMachine_MinorState&) = default;
+ChromeCompositorStateMachine_MinorState::ChromeCompositorStateMachine_MinorState(ChromeCompositorStateMachine_MinorState&&) noexcept = default;
+ChromeCompositorStateMachine_MinorState& ChromeCompositorStateMachine_MinorState::operator=(ChromeCompositorStateMachine_MinorState&&) = default;
+
+bool ChromeCompositorStateMachine_MinorState::operator==(const ChromeCompositorStateMachine_MinorState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(commit_count_, other.commit_count_)
+ && ::protozero::internal::gen_helpers::EqualsField(current_frame_number_, other.current_frame_number_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_frame_number_submit_performed_, other.last_frame_number_submit_performed_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_frame_number_draw_performed_, other.last_frame_number_draw_performed_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_frame_number_begin_main_frame_sent_, other.last_frame_number_begin_main_frame_sent_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_draw_, other.did_draw_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_send_begin_main_frame_for_current_frame_, other.did_send_begin_main_frame_for_current_frame_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_notify_begin_main_frame_not_expected_until_, other.did_notify_begin_main_frame_not_expected_until_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_notify_begin_main_frame_not_expected_soon_, other.did_notify_begin_main_frame_not_expected_soon_)
+ && ::protozero::internal::gen_helpers::EqualsField(wants_begin_main_frame_not_expected_, other.wants_begin_main_frame_not_expected_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_commit_during_frame_, other.did_commit_during_frame_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_invalidate_layer_tree_frame_sink_, other.did_invalidate_layer_tree_frame_sink_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_perform_impl_side_invalidaion_, other.did_perform_impl_side_invalidaion_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_prepare_tiles_, other.did_prepare_tiles_)
+ && ::protozero::internal::gen_helpers::EqualsField(consecutive_checkerboard_animations_, other.consecutive_checkerboard_animations_)
+ && ::protozero::internal::gen_helpers::EqualsField(pending_submit_frames_, other.pending_submit_frames_)
+ && ::protozero::internal::gen_helpers::EqualsField(submit_frames_with_current_layer_tree_frame_sink_, other.submit_frames_with_current_layer_tree_frame_sink_)
+ && ::protozero::internal::gen_helpers::EqualsField(needs_redraw_, other.needs_redraw_)
+ && ::protozero::internal::gen_helpers::EqualsField(needs_prepare_tiles_, other.needs_prepare_tiles_)
+ && ::protozero::internal::gen_helpers::EqualsField(needs_begin_main_frame_, other.needs_begin_main_frame_)
+ && ::protozero::internal::gen_helpers::EqualsField(needs_one_begin_impl_frame_, other.needs_one_begin_impl_frame_)
+ && ::protozero::internal::gen_helpers::EqualsField(visible_, other.visible_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_frame_source_paused_, other.begin_frame_source_paused_)
+ && ::protozero::internal::gen_helpers::EqualsField(can_draw_, other.can_draw_)
+ && ::protozero::internal::gen_helpers::EqualsField(resourceless_draw_, other.resourceless_draw_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_pending_tree_, other.has_pending_tree_)
+ && ::protozero::internal::gen_helpers::EqualsField(pending_tree_is_ready_for_activation_, other.pending_tree_is_ready_for_activation_)
+ && ::protozero::internal::gen_helpers::EqualsField(active_tree_needs_first_draw_, other.active_tree_needs_first_draw_)
+ && ::protozero::internal::gen_helpers::EqualsField(active_tree_is_ready_to_draw_, other.active_tree_is_ready_to_draw_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_create_and_initialize_first_layer_tree_frame_sink_, other.did_create_and_initialize_first_layer_tree_frame_sink_)
+ && ::protozero::internal::gen_helpers::EqualsField(tree_priority_, other.tree_priority_)
+ && ::protozero::internal::gen_helpers::EqualsField(scroll_handler_state_, other.scroll_handler_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(critical_begin_main_frame_to_activate_is_fast_, other.critical_begin_main_frame_to_activate_is_fast_)
+ && ::protozero::internal::gen_helpers::EqualsField(main_thread_missed_last_deadline_, other.main_thread_missed_last_deadline_)
+ && ::protozero::internal::gen_helpers::EqualsField(video_needs_begin_frames_, other.video_needs_begin_frames_)
+ && ::protozero::internal::gen_helpers::EqualsField(defer_begin_main_frame_, other.defer_begin_main_frame_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_commit_had_no_updates_, other.last_commit_had_no_updates_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_draw_in_last_frame_, other.did_draw_in_last_frame_)
+ && ::protozero::internal::gen_helpers::EqualsField(did_submit_in_last_frame_, other.did_submit_in_last_frame_)
+ && ::protozero::internal::gen_helpers::EqualsField(needs_impl_side_invalidation_, other.needs_impl_side_invalidation_)
+ && ::protozero::internal::gen_helpers::EqualsField(current_pending_tree_is_impl_side_, other.current_pending_tree_is_impl_side_)
+ && ::protozero::internal::gen_helpers::EqualsField(previous_pending_tree_was_impl_side_, other.previous_pending_tree_was_impl_side_)
+ && ::protozero::internal::gen_helpers::EqualsField(processing_animation_worklets_for_active_tree_, other.processing_animation_worklets_for_active_tree_)
+ && ::protozero::internal::gen_helpers::EqualsField(processing_animation_worklets_for_pending_tree_, other.processing_animation_worklets_for_pending_tree_)
+ && ::protozero::internal::gen_helpers::EqualsField(processing_paint_worklets_for_pending_tree_, other.processing_paint_worklets_for_pending_tree_);
+}
+
+bool ChromeCompositorStateMachine_MinorState::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* commit_count */:
+ field.get(&commit_count_);
+ break;
+ case 2 /* current_frame_number */:
+ field.get(&current_frame_number_);
+ break;
+ case 3 /* last_frame_number_submit_performed */:
+ field.get(&last_frame_number_submit_performed_);
+ break;
+ case 4 /* last_frame_number_draw_performed */:
+ field.get(&last_frame_number_draw_performed_);
+ break;
+ case 5 /* last_frame_number_begin_main_frame_sent */:
+ field.get(&last_frame_number_begin_main_frame_sent_);
+ break;
+ case 6 /* did_draw */:
+ field.get(&did_draw_);
+ break;
+ case 7 /* did_send_begin_main_frame_for_current_frame */:
+ field.get(&did_send_begin_main_frame_for_current_frame_);
+ break;
+ case 8 /* did_notify_begin_main_frame_not_expected_until */:
+ field.get(&did_notify_begin_main_frame_not_expected_until_);
+ break;
+ case 9 /* did_notify_begin_main_frame_not_expected_soon */:
+ field.get(&did_notify_begin_main_frame_not_expected_soon_);
+ break;
+ case 10 /* wants_begin_main_frame_not_expected */:
+ field.get(&wants_begin_main_frame_not_expected_);
+ break;
+ case 11 /* did_commit_during_frame */:
+ field.get(&did_commit_during_frame_);
+ break;
+ case 12 /* did_invalidate_layer_tree_frame_sink */:
+ field.get(&did_invalidate_layer_tree_frame_sink_);
+ break;
+ case 13 /* did_perform_impl_side_invalidaion */:
+ field.get(&did_perform_impl_side_invalidaion_);
+ break;
+ case 14 /* did_prepare_tiles */:
+ field.get(&did_prepare_tiles_);
+ break;
+ case 15 /* consecutive_checkerboard_animations */:
+ field.get(&consecutive_checkerboard_animations_);
+ break;
+ case 16 /* pending_submit_frames */:
+ field.get(&pending_submit_frames_);
+ break;
+ case 17 /* submit_frames_with_current_layer_tree_frame_sink */:
+ field.get(&submit_frames_with_current_layer_tree_frame_sink_);
+ break;
+ case 18 /* needs_redraw */:
+ field.get(&needs_redraw_);
+ break;
+ case 19 /* needs_prepare_tiles */:
+ field.get(&needs_prepare_tiles_);
+ break;
+ case 20 /* needs_begin_main_frame */:
+ field.get(&needs_begin_main_frame_);
+ break;
+ case 21 /* needs_one_begin_impl_frame */:
+ field.get(&needs_one_begin_impl_frame_);
+ break;
+ case 22 /* visible */:
+ field.get(&visible_);
+ break;
+ case 23 /* begin_frame_source_paused */:
+ field.get(&begin_frame_source_paused_);
+ break;
+ case 24 /* can_draw */:
+ field.get(&can_draw_);
+ break;
+ case 25 /* resourceless_draw */:
+ field.get(&resourceless_draw_);
+ break;
+ case 26 /* has_pending_tree */:
+ field.get(&has_pending_tree_);
+ break;
+ case 27 /* pending_tree_is_ready_for_activation */:
+ field.get(&pending_tree_is_ready_for_activation_);
+ break;
+ case 28 /* active_tree_needs_first_draw */:
+ field.get(&active_tree_needs_first_draw_);
+ break;
+ case 29 /* active_tree_is_ready_to_draw */:
+ field.get(&active_tree_is_ready_to_draw_);
+ break;
+ case 30 /* did_create_and_initialize_first_layer_tree_frame_sink */:
+ field.get(&did_create_and_initialize_first_layer_tree_frame_sink_);
+ break;
+ case 31 /* tree_priority */:
+ field.get(&tree_priority_);
+ break;
+ case 32 /* scroll_handler_state */:
+ field.get(&scroll_handler_state_);
+ break;
+ case 33 /* critical_begin_main_frame_to_activate_is_fast */:
+ field.get(&critical_begin_main_frame_to_activate_is_fast_);
+ break;
+ case 34 /* main_thread_missed_last_deadline */:
+ field.get(&main_thread_missed_last_deadline_);
+ break;
+ case 36 /* video_needs_begin_frames */:
+ field.get(&video_needs_begin_frames_);
+ break;
+ case 37 /* defer_begin_main_frame */:
+ field.get(&defer_begin_main_frame_);
+ break;
+ case 38 /* last_commit_had_no_updates */:
+ field.get(&last_commit_had_no_updates_);
+ break;
+ case 39 /* did_draw_in_last_frame */:
+ field.get(&did_draw_in_last_frame_);
+ break;
+ case 40 /* did_submit_in_last_frame */:
+ field.get(&did_submit_in_last_frame_);
+ break;
+ case 41 /* needs_impl_side_invalidation */:
+ field.get(&needs_impl_side_invalidation_);
+ break;
+ case 42 /* current_pending_tree_is_impl_side */:
+ field.get(&current_pending_tree_is_impl_side_);
+ break;
+ case 43 /* previous_pending_tree_was_impl_side */:
+ field.get(&previous_pending_tree_was_impl_side_);
+ break;
+ case 44 /* processing_animation_worklets_for_active_tree */:
+ field.get(&processing_animation_worklets_for_active_tree_);
+ break;
+ case 45 /* processing_animation_worklets_for_pending_tree */:
+ field.get(&processing_animation_worklets_for_pending_tree_);
+ break;
+ case 46 /* processing_paint_worklets_for_pending_tree */:
+ field.get(&processing_paint_worklets_for_pending_tree_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeCompositorStateMachine_MinorState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeCompositorStateMachine_MinorState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeCompositorStateMachine_MinorState::Serialize(::protozero::Message* msg) const {
+ // Field 1: commit_count
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, commit_count_, msg);
+ }
+
+ // Field 2: current_frame_number
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, current_frame_number_, msg);
+ }
+
+ // Field 3: last_frame_number_submit_performed
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, last_frame_number_submit_performed_, msg);
+ }
+
+ // Field 4: last_frame_number_draw_performed
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, last_frame_number_draw_performed_, msg);
+ }
+
+ // Field 5: last_frame_number_begin_main_frame_sent
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, last_frame_number_begin_main_frame_sent_, msg);
+ }
+
+ // Field 6: did_draw
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(6, did_draw_, msg);
+ }
+
+ // Field 7: did_send_begin_main_frame_for_current_frame
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(7, did_send_begin_main_frame_for_current_frame_, msg);
+ }
+
+ // Field 8: did_notify_begin_main_frame_not_expected_until
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(8, did_notify_begin_main_frame_not_expected_until_, msg);
+ }
+
+ // Field 9: did_notify_begin_main_frame_not_expected_soon
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, did_notify_begin_main_frame_not_expected_soon_, msg);
+ }
+
+ // Field 10: wants_begin_main_frame_not_expected
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(10, wants_begin_main_frame_not_expected_, msg);
+ }
+
+ // Field 11: did_commit_during_frame
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(11, did_commit_during_frame_, msg);
+ }
+
+ // Field 12: did_invalidate_layer_tree_frame_sink
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(12, did_invalidate_layer_tree_frame_sink_, msg);
+ }
+
+ // Field 13: did_perform_impl_side_invalidaion
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(13, did_perform_impl_side_invalidaion_, msg);
+ }
+
+ // Field 14: did_prepare_tiles
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(14, did_prepare_tiles_, msg);
+ }
+
+ // Field 15: consecutive_checkerboard_animations
+ if (_has_field_[15]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(15, consecutive_checkerboard_animations_, msg);
+ }
+
+ // Field 16: pending_submit_frames
+ if (_has_field_[16]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(16, pending_submit_frames_, msg);
+ }
+
+ // Field 17: submit_frames_with_current_layer_tree_frame_sink
+ if (_has_field_[17]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, submit_frames_with_current_layer_tree_frame_sink_, msg);
+ }
+
+ // Field 18: needs_redraw
+ if (_has_field_[18]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(18, needs_redraw_, msg);
+ }
+
+ // Field 19: needs_prepare_tiles
+ if (_has_field_[19]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(19, needs_prepare_tiles_, msg);
+ }
+
+ // Field 20: needs_begin_main_frame
+ if (_has_field_[20]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(20, needs_begin_main_frame_, msg);
+ }
+
+ // Field 21: needs_one_begin_impl_frame
+ if (_has_field_[21]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(21, needs_one_begin_impl_frame_, msg);
+ }
+
+ // Field 22: visible
+ if (_has_field_[22]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(22, visible_, msg);
+ }
+
+ // Field 23: begin_frame_source_paused
+ if (_has_field_[23]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(23, begin_frame_source_paused_, msg);
+ }
+
+ // Field 24: can_draw
+ if (_has_field_[24]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(24, can_draw_, msg);
+ }
+
+ // Field 25: resourceless_draw
+ if (_has_field_[25]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(25, resourceless_draw_, msg);
+ }
+
+ // Field 26: has_pending_tree
+ if (_has_field_[26]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(26, has_pending_tree_, msg);
+ }
+
+ // Field 27: pending_tree_is_ready_for_activation
+ if (_has_field_[27]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(27, pending_tree_is_ready_for_activation_, msg);
+ }
+
+ // Field 28: active_tree_needs_first_draw
+ if (_has_field_[28]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(28, active_tree_needs_first_draw_, msg);
+ }
+
+ // Field 29: active_tree_is_ready_to_draw
+ if (_has_field_[29]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(29, active_tree_is_ready_to_draw_, msg);
+ }
+
+ // Field 30: did_create_and_initialize_first_layer_tree_frame_sink
+ if (_has_field_[30]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(30, did_create_and_initialize_first_layer_tree_frame_sink_, msg);
+ }
+
+ // Field 31: tree_priority
+ if (_has_field_[31]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(31, tree_priority_, msg);
+ }
+
+ // Field 32: scroll_handler_state
+ if (_has_field_[32]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(32, scroll_handler_state_, msg);
+ }
+
+ // Field 33: critical_begin_main_frame_to_activate_is_fast
+ if (_has_field_[33]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(33, critical_begin_main_frame_to_activate_is_fast_, msg);
+ }
+
+ // Field 34: main_thread_missed_last_deadline
+ if (_has_field_[34]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(34, main_thread_missed_last_deadline_, msg);
+ }
+
+ // Field 36: video_needs_begin_frames
+ if (_has_field_[36]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(36, video_needs_begin_frames_, msg);
+ }
+
+ // Field 37: defer_begin_main_frame
+ if (_has_field_[37]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(37, defer_begin_main_frame_, msg);
+ }
+
+ // Field 38: last_commit_had_no_updates
+ if (_has_field_[38]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(38, last_commit_had_no_updates_, msg);
+ }
+
+ // Field 39: did_draw_in_last_frame
+ if (_has_field_[39]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(39, did_draw_in_last_frame_, msg);
+ }
+
+ // Field 40: did_submit_in_last_frame
+ if (_has_field_[40]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(40, did_submit_in_last_frame_, msg);
+ }
+
+ // Field 41: needs_impl_side_invalidation
+ if (_has_field_[41]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(41, needs_impl_side_invalidation_, msg);
+ }
+
+ // Field 42: current_pending_tree_is_impl_side
+ if (_has_field_[42]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(42, current_pending_tree_is_impl_side_, msg);
+ }
+
+ // Field 43: previous_pending_tree_was_impl_side
+ if (_has_field_[43]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(43, previous_pending_tree_was_impl_side_, msg);
+ }
+
+ // Field 44: processing_animation_worklets_for_active_tree
+ if (_has_field_[44]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(44, processing_animation_worklets_for_active_tree_, msg);
+ }
+
+ // Field 45: processing_animation_worklets_for_pending_tree
+ if (_has_field_[45]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(45, processing_animation_worklets_for_pending_tree_, msg);
+ }
+
+ // Field 46: processing_paint_worklets_for_pending_tree
+ if (_has_field_[46]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(46, processing_paint_worklets_for_pending_tree_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChromeCompositorStateMachine_MajorState::ChromeCompositorStateMachine_MajorState() = default;
+ChromeCompositorStateMachine_MajorState::~ChromeCompositorStateMachine_MajorState() = default;
+ChromeCompositorStateMachine_MajorState::ChromeCompositorStateMachine_MajorState(const ChromeCompositorStateMachine_MajorState&) = default;
+ChromeCompositorStateMachine_MajorState& ChromeCompositorStateMachine_MajorState::operator=(const ChromeCompositorStateMachine_MajorState&) = default;
+ChromeCompositorStateMachine_MajorState::ChromeCompositorStateMachine_MajorState(ChromeCompositorStateMachine_MajorState&&) noexcept = default;
+ChromeCompositorStateMachine_MajorState& ChromeCompositorStateMachine_MajorState::operator=(ChromeCompositorStateMachine_MajorState&&) = default;
+
+bool ChromeCompositorStateMachine_MajorState::operator==(const ChromeCompositorStateMachine_MajorState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(next_action_, other.next_action_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_impl_frame_state_, other.begin_impl_frame_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_main_frame_state_, other.begin_main_frame_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(layer_tree_frame_sink_state_, other.layer_tree_frame_sink_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(forced_redraw_state_, other.forced_redraw_state_);
+}
+
+bool ChromeCompositorStateMachine_MajorState::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* next_action */:
+ field.get(&next_action_);
+ break;
+ case 2 /* begin_impl_frame_state */:
+ field.get(&begin_impl_frame_state_);
+ break;
+ case 3 /* begin_main_frame_state */:
+ field.get(&begin_main_frame_state_);
+ break;
+ case 4 /* layer_tree_frame_sink_state */:
+ field.get(&layer_tree_frame_sink_state_);
+ break;
+ case 5 /* forced_redraw_state */:
+ field.get(&forced_redraw_state_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeCompositorStateMachine_MajorState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeCompositorStateMachine_MajorState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeCompositorStateMachine_MajorState::Serialize(::protozero::Message* msg) const {
+ // Field 1: next_action
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, next_action_, msg);
+ }
+
+ // Field 2: begin_impl_frame_state
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, begin_impl_frame_state_, msg);
+ }
+
+ // Field 3: begin_main_frame_state
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, begin_main_frame_state_, msg);
+ }
+
+ // Field 4: layer_tree_frame_sink_state
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, layer_tree_frame_sink_state_, msg);
+ }
+
+ // Field 5: forced_redraw_state
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, forced_redraw_state_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChromeCompositorSchedulerState::ChromeCompositorSchedulerState() = default;
+ChromeCompositorSchedulerState::~ChromeCompositorSchedulerState() = default;
+ChromeCompositorSchedulerState::ChromeCompositorSchedulerState(const ChromeCompositorSchedulerState&) = default;
+ChromeCompositorSchedulerState& ChromeCompositorSchedulerState::operator=(const ChromeCompositorSchedulerState&) = default;
+ChromeCompositorSchedulerState::ChromeCompositorSchedulerState(ChromeCompositorSchedulerState&&) noexcept = default;
+ChromeCompositorSchedulerState& ChromeCompositorSchedulerState::operator=(ChromeCompositorSchedulerState&&) = default;
+
+bool ChromeCompositorSchedulerState::operator==(const ChromeCompositorSchedulerState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(state_machine_, other.state_machine_)
+ && ::protozero::internal::gen_helpers::EqualsField(observing_begin_frame_source_, other.observing_begin_frame_source_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_impl_frame_deadline_task_, other.begin_impl_frame_deadline_task_)
+ && ::protozero::internal::gen_helpers::EqualsField(pending_begin_frame_task_, other.pending_begin_frame_task_)
+ && ::protozero::internal::gen_helpers::EqualsField(skipped_last_frame_missed_exceeded_deadline_, other.skipped_last_frame_missed_exceeded_deadline_)
+ && ::protozero::internal::gen_helpers::EqualsField(inside_action_, other.inside_action_)
+ && ::protozero::internal::gen_helpers::EqualsField(deadline_mode_, other.deadline_mode_)
+ && ::protozero::internal::gen_helpers::EqualsField(deadline_us_, other.deadline_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(deadline_scheduled_at_us_, other.deadline_scheduled_at_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(now_us_, other.now_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(now_to_deadline_delta_us_, other.now_to_deadline_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(now_to_deadline_scheduled_at_delta_us_, other.now_to_deadline_scheduled_at_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_impl_frame_args_, other.begin_impl_frame_args_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_frame_observer_state_, other.begin_frame_observer_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(begin_frame_source_state_, other.begin_frame_source_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(compositor_timing_history_, other.compositor_timing_history_);
+}
+
+bool ChromeCompositorSchedulerState::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* state_machine */:
+ (*state_machine_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* observing_begin_frame_source */:
+ field.get(&observing_begin_frame_source_);
+ break;
+ case 3 /* begin_impl_frame_deadline_task */:
+ field.get(&begin_impl_frame_deadline_task_);
+ break;
+ case 4 /* pending_begin_frame_task */:
+ field.get(&pending_begin_frame_task_);
+ break;
+ case 5 /* skipped_last_frame_missed_exceeded_deadline */:
+ field.get(&skipped_last_frame_missed_exceeded_deadline_);
+ break;
+ case 7 /* inside_action */:
+ field.get(&inside_action_);
+ break;
+ case 8 /* deadline_mode */:
+ field.get(&deadline_mode_);
+ break;
+ case 9 /* deadline_us */:
+ field.get(&deadline_us_);
+ break;
+ case 10 /* deadline_scheduled_at_us */:
+ field.get(&deadline_scheduled_at_us_);
+ break;
+ case 11 /* now_us */:
+ field.get(&now_us_);
+ break;
+ case 12 /* now_to_deadline_delta_us */:
+ field.get(&now_to_deadline_delta_us_);
+ break;
+ case 13 /* now_to_deadline_scheduled_at_delta_us */:
+ field.get(&now_to_deadline_scheduled_at_delta_us_);
+ break;
+ case 14 /* begin_impl_frame_args */:
+ (*begin_impl_frame_args_).ParseFromArray(field.data(), field.size());
+ break;
+ case 15 /* begin_frame_observer_state */:
+ (*begin_frame_observer_state_).ParseFromArray(field.data(), field.size());
+ break;
+ case 16 /* begin_frame_source_state */:
+ (*begin_frame_source_state_).ParseFromArray(field.data(), field.size());
+ break;
+ case 17 /* compositor_timing_history */:
+ (*compositor_timing_history_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeCompositorSchedulerState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeCompositorSchedulerState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeCompositorSchedulerState::Serialize(::protozero::Message* msg) const {
+ // Field 1: state_machine
+ if (_has_field_[1]) {
+ (*state_machine_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: observing_begin_frame_source
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, observing_begin_frame_source_, msg);
+ }
+
+ // Field 3: begin_impl_frame_deadline_task
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, begin_impl_frame_deadline_task_, msg);
+ }
+
+ // Field 4: pending_begin_frame_task
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, pending_begin_frame_task_, msg);
+ }
+
+ // Field 5: skipped_last_frame_missed_exceeded_deadline
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, skipped_last_frame_missed_exceeded_deadline_, msg);
+ }
+
+ // Field 7: inside_action
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, inside_action_, msg);
+ }
+
+ // Field 8: deadline_mode
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, deadline_mode_, msg);
+ }
+
+ // Field 9: deadline_us
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, deadline_us_, msg);
+ }
+
+ // Field 10: deadline_scheduled_at_us
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, deadline_scheduled_at_us_, msg);
+ }
+
+ // Field 11: now_us
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, now_us_, msg);
+ }
+
+ // Field 12: now_to_deadline_delta_us
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(12, now_to_deadline_delta_us_, msg);
+ }
+
+ // Field 13: now_to_deadline_scheduled_at_delta_us
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, now_to_deadline_scheduled_at_delta_us_, msg);
+ }
+
+ // Field 14: begin_impl_frame_args
+ if (_has_field_[14]) {
+ (*begin_impl_frame_args_).Serialize(msg->BeginNestedMessage<::protozero::Message>(14));
+ }
+
+ // Field 15: begin_frame_observer_state
+ if (_has_field_[15]) {
+ (*begin_frame_observer_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(15));
+ }
+
+ // Field 16: begin_frame_source_state
+ if (_has_field_[16]) {
+ (*begin_frame_source_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(16));
+ }
+
+ // Field 17: compositor_timing_history
+ if (_has_field_[17]) {
+ (*compositor_timing_history_).Serialize(msg->BeginNestedMessage<::protozero::Message>(17));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_content_settings_event_info.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_content_settings_event_info.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeContentSettingsEventInfo::ChromeContentSettingsEventInfo() = default;
+ChromeContentSettingsEventInfo::~ChromeContentSettingsEventInfo() = default;
+ChromeContentSettingsEventInfo::ChromeContentSettingsEventInfo(const ChromeContentSettingsEventInfo&) = default;
+ChromeContentSettingsEventInfo& ChromeContentSettingsEventInfo::operator=(const ChromeContentSettingsEventInfo&) = default;
+ChromeContentSettingsEventInfo::ChromeContentSettingsEventInfo(ChromeContentSettingsEventInfo&&) noexcept = default;
+ChromeContentSettingsEventInfo& ChromeContentSettingsEventInfo::operator=(ChromeContentSettingsEventInfo&&) = default;
+
+bool ChromeContentSettingsEventInfo::operator==(const ChromeContentSettingsEventInfo& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(number_of_exceptions_, other.number_of_exceptions_);
+}
+
+bool ChromeContentSettingsEventInfo::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* number_of_exceptions */:
+ field.get(&number_of_exceptions_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeContentSettingsEventInfo::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeContentSettingsEventInfo::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeContentSettingsEventInfo::Serialize(::protozero::Message* msg) const {
+ // Field 1: number_of_exceptions
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, number_of_exceptions_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_frame_reporter.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_frame_reporter.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeFrameReporter::ChromeFrameReporter() = default;
+ChromeFrameReporter::~ChromeFrameReporter() = default;
+ChromeFrameReporter::ChromeFrameReporter(const ChromeFrameReporter&) = default;
+ChromeFrameReporter& ChromeFrameReporter::operator=(const ChromeFrameReporter&) = default;
+ChromeFrameReporter::ChromeFrameReporter(ChromeFrameReporter&&) noexcept = default;
+ChromeFrameReporter& ChromeFrameReporter::operator=(ChromeFrameReporter&&) = default;
+
+bool ChromeFrameReporter::operator==(const ChromeFrameReporter& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(state_, other.state_)
+ && ::protozero::internal::gen_helpers::EqualsField(reason_, other.reason_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_source_, other.frame_source_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_sequence_, other.frame_sequence_)
+ && ::protozero::internal::gen_helpers::EqualsField(affects_smoothness_, other.affects_smoothness_)
+ && ::protozero::internal::gen_helpers::EqualsField(scroll_state_, other.scroll_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_main_animation_, other.has_main_animation_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_compositor_animation_, other.has_compositor_animation_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_smooth_input_main_, other.has_smooth_input_main_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_missing_content_, other.has_missing_content_)
+ && ::protozero::internal::gen_helpers::EqualsField(layer_tree_host_id_, other.layer_tree_host_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_high_latency_, other.has_high_latency_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_type_, other.frame_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(high_latency_contribution_stage_, other.high_latency_contribution_stage_);
+}
+
+bool ChromeFrameReporter::ParseFromArray(const void* raw, size_t size) {
+ high_latency_contribution_stage_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* state */:
+ field.get(&state_);
+ break;
+ case 2 /* reason */:
+ field.get(&reason_);
+ break;
+ case 3 /* frame_source */:
+ field.get(&frame_source_);
+ break;
+ case 4 /* frame_sequence */:
+ field.get(&frame_sequence_);
+ break;
+ case 5 /* affects_smoothness */:
+ field.get(&affects_smoothness_);
+ break;
+ case 6 /* scroll_state */:
+ field.get(&scroll_state_);
+ break;
+ case 7 /* has_main_animation */:
+ field.get(&has_main_animation_);
+ break;
+ case 8 /* has_compositor_animation */:
+ field.get(&has_compositor_animation_);
+ break;
+ case 9 /* has_smooth_input_main */:
+ field.get(&has_smooth_input_main_);
+ break;
+ case 10 /* has_missing_content */:
+ field.get(&has_missing_content_);
+ break;
+ case 11 /* layer_tree_host_id */:
+ field.get(&layer_tree_host_id_);
+ break;
+ case 12 /* has_high_latency */:
+ field.get(&has_high_latency_);
+ break;
+ case 13 /* frame_type */:
+ field.get(&frame_type_);
+ break;
+ case 14 /* high_latency_contribution_stage */:
+ high_latency_contribution_stage_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &high_latency_contribution_stage_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeFrameReporter::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeFrameReporter::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeFrameReporter::Serialize(::protozero::Message* msg) const {
+ // Field 1: state
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, state_, msg);
+ }
+
+ // Field 2: reason
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, reason_, msg);
+ }
+
+ // Field 3: frame_source
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, frame_source_, msg);
+ }
+
+ // Field 4: frame_sequence
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, frame_sequence_, msg);
+ }
+
+ // Field 5: affects_smoothness
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, affects_smoothness_, msg);
+ }
+
+ // Field 6: scroll_state
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, scroll_state_, msg);
+ }
+
+ // Field 7: has_main_animation
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(7, has_main_animation_, msg);
+ }
+
+ // Field 8: has_compositor_animation
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(8, has_compositor_animation_, msg);
+ }
+
+ // Field 9: has_smooth_input_main
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, has_smooth_input_main_, msg);
+ }
+
+ // Field 10: has_missing_content
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(10, has_missing_content_, msg);
+ }
+
+ // Field 11: layer_tree_host_id
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, layer_tree_host_id_, msg);
+ }
+
+ // Field 12: has_high_latency
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(12, has_high_latency_, msg);
+ }
+
+ // Field 13: frame_type
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, frame_type_, msg);
+ }
+
+ // Field 14: high_latency_contribution_stage
+ for (auto& it : high_latency_contribution_stage_) {
+ ::protozero::internal::gen_helpers::SerializeString(14, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_histogram_sample.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_histogram_sample.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeHistogramSample::ChromeHistogramSample() = default;
+ChromeHistogramSample::~ChromeHistogramSample() = default;
+ChromeHistogramSample::ChromeHistogramSample(const ChromeHistogramSample&) = default;
+ChromeHistogramSample& ChromeHistogramSample::operator=(const ChromeHistogramSample&) = default;
+ChromeHistogramSample::ChromeHistogramSample(ChromeHistogramSample&&) noexcept = default;
+ChromeHistogramSample& ChromeHistogramSample::operator=(ChromeHistogramSample&&) = default;
+
+bool ChromeHistogramSample::operator==(const ChromeHistogramSample& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_hash_, other.name_hash_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(sample_, other.sample_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_iid_, other.name_iid_);
+}
+
+bool ChromeHistogramSample::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name_hash */:
+ field.get(&name_hash_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 3 /* sample */:
+ field.get(&sample_);
+ break;
+ case 4 /* name_iid */:
+ field.get(&name_iid_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeHistogramSample::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeHistogramSample::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeHistogramSample::Serialize(::protozero::Message* msg) const {
+ // Field 1: name_hash
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, name_hash_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ // Field 3: sample
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, sample_, msg);
+ }
+
+ // Field 4: name_iid
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, name_iid_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+HistogramName::HistogramName() = default;
+HistogramName::~HistogramName() = default;
+HistogramName::HistogramName(const HistogramName&) = default;
+HistogramName& HistogramName::operator=(const HistogramName&) = default;
+HistogramName::HistogramName(HistogramName&&) noexcept = default;
+HistogramName& HistogramName::operator=(HistogramName&&) = default;
+
+bool HistogramName::operator==(const HistogramName& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool HistogramName::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string HistogramName::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> HistogramName::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void HistogramName::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_keyed_service.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_keyed_service.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeKeyedService::ChromeKeyedService() = default;
+ChromeKeyedService::~ChromeKeyedService() = default;
+ChromeKeyedService::ChromeKeyedService(const ChromeKeyedService&) = default;
+ChromeKeyedService& ChromeKeyedService::operator=(const ChromeKeyedService&) = default;
+ChromeKeyedService::ChromeKeyedService(ChromeKeyedService&&) noexcept = default;
+ChromeKeyedService& ChromeKeyedService::operator=(ChromeKeyedService&&) = default;
+
+bool ChromeKeyedService::operator==(const ChromeKeyedService& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool ChromeKeyedService::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeKeyedService::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeKeyedService::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeKeyedService::Serialize(::protozero::Message* msg) const {
+ // Field 1: name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_latency_info.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_latency_info.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeLatencyInfo::ChromeLatencyInfo() = default;
+ChromeLatencyInfo::~ChromeLatencyInfo() = default;
+ChromeLatencyInfo::ChromeLatencyInfo(const ChromeLatencyInfo&) = default;
+ChromeLatencyInfo& ChromeLatencyInfo::operator=(const ChromeLatencyInfo&) = default;
+ChromeLatencyInfo::ChromeLatencyInfo(ChromeLatencyInfo&&) noexcept = default;
+ChromeLatencyInfo& ChromeLatencyInfo::operator=(ChromeLatencyInfo&&) = default;
+
+bool ChromeLatencyInfo::operator==(const ChromeLatencyInfo& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_id_, other.trace_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(step_, other.step_)
+ && ::protozero::internal::gen_helpers::EqualsField(frame_tree_node_id_, other.frame_tree_node_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(component_info_, other.component_info_)
+ && ::protozero::internal::gen_helpers::EqualsField(is_coalesced_, other.is_coalesced_)
+ && ::protozero::internal::gen_helpers::EqualsField(gesture_scroll_id_, other.gesture_scroll_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(touch_id_, other.touch_id_);
+}
+
+int ChromeLatencyInfo::component_info_size() const { return static_cast<int>(component_info_.size()); }
+void ChromeLatencyInfo::clear_component_info() { component_info_.clear(); }
+ChromeLatencyInfo_ComponentInfo* ChromeLatencyInfo::add_component_info() { component_info_.emplace_back(); return &component_info_.back(); }
+bool ChromeLatencyInfo::ParseFromArray(const void* raw, size_t size) {
+ component_info_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_id */:
+ field.get(&trace_id_);
+ break;
+ case 2 /* step */:
+ field.get(&step_);
+ break;
+ case 3 /* frame_tree_node_id */:
+ field.get(&frame_tree_node_id_);
+ break;
+ case 4 /* component_info */:
+ component_info_.emplace_back();
+ component_info_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* is_coalesced */:
+ field.get(&is_coalesced_);
+ break;
+ case 6 /* gesture_scroll_id */:
+ field.get(&gesture_scroll_id_);
+ break;
+ case 7 /* touch_id */:
+ field.get(&touch_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeLatencyInfo::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeLatencyInfo::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeLatencyInfo::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, trace_id_, msg);
+ }
+
+ // Field 2: step
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, step_, msg);
+ }
+
+ // Field 3: frame_tree_node_id
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, frame_tree_node_id_, msg);
+ }
+
+ // Field 4: component_info
+ for (auto& it : component_info_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: is_coalesced
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, is_coalesced_, msg);
+ }
+
+ // Field 6: gesture_scroll_id
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, gesture_scroll_id_, msg);
+ }
+
+ // Field 7: touch_id
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, touch_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChromeLatencyInfo_ComponentInfo::ChromeLatencyInfo_ComponentInfo() = default;
+ChromeLatencyInfo_ComponentInfo::~ChromeLatencyInfo_ComponentInfo() = default;
+ChromeLatencyInfo_ComponentInfo::ChromeLatencyInfo_ComponentInfo(const ChromeLatencyInfo_ComponentInfo&) = default;
+ChromeLatencyInfo_ComponentInfo& ChromeLatencyInfo_ComponentInfo::operator=(const ChromeLatencyInfo_ComponentInfo&) = default;
+ChromeLatencyInfo_ComponentInfo::ChromeLatencyInfo_ComponentInfo(ChromeLatencyInfo_ComponentInfo&&) noexcept = default;
+ChromeLatencyInfo_ComponentInfo& ChromeLatencyInfo_ComponentInfo::operator=(ChromeLatencyInfo_ComponentInfo&&) = default;
+
+bool ChromeLatencyInfo_ComponentInfo::operator==(const ChromeLatencyInfo_ComponentInfo& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(component_type_, other.component_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(time_us_, other.time_us_);
+}
+
+bool ChromeLatencyInfo_ComponentInfo::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* component_type */:
+ field.get(&component_type_);
+ break;
+ case 2 /* time_us */:
+ field.get(&time_us_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeLatencyInfo_ComponentInfo::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeLatencyInfo_ComponentInfo::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeLatencyInfo_ComponentInfo::Serialize(::protozero::Message* msg) const {
+ // Field 1: component_type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, component_type_, msg);
+ }
+
+ // Field 2: time_us
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, time_us_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeLegacyIpc::ChromeLegacyIpc() = default;
+ChromeLegacyIpc::~ChromeLegacyIpc() = default;
+ChromeLegacyIpc::ChromeLegacyIpc(const ChromeLegacyIpc&) = default;
+ChromeLegacyIpc& ChromeLegacyIpc::operator=(const ChromeLegacyIpc&) = default;
+ChromeLegacyIpc::ChromeLegacyIpc(ChromeLegacyIpc&&) noexcept = default;
+ChromeLegacyIpc& ChromeLegacyIpc::operator=(ChromeLegacyIpc&&) = default;
+
+bool ChromeLegacyIpc::operator==(const ChromeLegacyIpc& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(message_class_, other.message_class_)
+ && ::protozero::internal::gen_helpers::EqualsField(message_line_, other.message_line_);
+}
+
+bool ChromeLegacyIpc::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* message_class */:
+ field.get(&message_class_);
+ break;
+ case 2 /* message_line */:
+ field.get(&message_line_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeLegacyIpc::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeLegacyIpc::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeLegacyIpc::Serialize(::protozero::Message* msg) const {
+ // Field 1: message_class
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, message_class_, msg);
+ }
+
+ // Field 2: message_line
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, message_line_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_message_pump.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_message_pump.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeMessagePump::ChromeMessagePump() = default;
+ChromeMessagePump::~ChromeMessagePump() = default;
+ChromeMessagePump::ChromeMessagePump(const ChromeMessagePump&) = default;
+ChromeMessagePump& ChromeMessagePump::operator=(const ChromeMessagePump&) = default;
+ChromeMessagePump::ChromeMessagePump(ChromeMessagePump&&) noexcept = default;
+ChromeMessagePump& ChromeMessagePump::operator=(ChromeMessagePump&&) = default;
+
+bool ChromeMessagePump::operator==(const ChromeMessagePump& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(sent_messages_in_queue_, other.sent_messages_in_queue_)
+ && ::protozero::internal::gen_helpers::EqualsField(io_handler_location_iid_, other.io_handler_location_iid_);
+}
+
+bool ChromeMessagePump::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* sent_messages_in_queue */:
+ field.get(&sent_messages_in_queue_);
+ break;
+ case 2 /* io_handler_location_iid */:
+ field.get(&io_handler_location_iid_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeMessagePump::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeMessagePump::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeMessagePump::Serialize(::protozero::Message* msg) const {
+ // Field 1: sent_messages_in_queue
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, sent_messages_in_queue_, msg);
+ }
+
+ // Field 2: io_handler_location_iid
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, io_handler_location_iid_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_mojo_event_info.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_mojo_event_info.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeMojoEventInfo::ChromeMojoEventInfo() = default;
+ChromeMojoEventInfo::~ChromeMojoEventInfo() = default;
+ChromeMojoEventInfo::ChromeMojoEventInfo(const ChromeMojoEventInfo&) = default;
+ChromeMojoEventInfo& ChromeMojoEventInfo::operator=(const ChromeMojoEventInfo&) = default;
+ChromeMojoEventInfo::ChromeMojoEventInfo(ChromeMojoEventInfo&&) noexcept = default;
+ChromeMojoEventInfo& ChromeMojoEventInfo::operator=(ChromeMojoEventInfo&&) = default;
+
+bool ChromeMojoEventInfo::operator==(const ChromeMojoEventInfo& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(watcher_notify_interface_tag_, other.watcher_notify_interface_tag_)
+ && ::protozero::internal::gen_helpers::EqualsField(ipc_hash_, other.ipc_hash_)
+ && ::protozero::internal::gen_helpers::EqualsField(mojo_interface_tag_, other.mojo_interface_tag_)
+ && ::protozero::internal::gen_helpers::EqualsField(mojo_interface_method_iid_, other.mojo_interface_method_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(is_reply_, other.is_reply_)
+ && ::protozero::internal::gen_helpers::EqualsField(payload_size_, other.payload_size_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_num_bytes_, other.data_num_bytes_);
+}
+
+bool ChromeMojoEventInfo::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* watcher_notify_interface_tag */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &watcher_notify_interface_tag_);
+ break;
+ case 2 /* ipc_hash */:
+ field.get(&ipc_hash_);
+ break;
+ case 3 /* mojo_interface_tag */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &mojo_interface_tag_);
+ break;
+ case 4 /* mojo_interface_method_iid */:
+ field.get(&mojo_interface_method_iid_);
+ break;
+ case 5 /* is_reply */:
+ field.get(&is_reply_);
+ break;
+ case 6 /* payload_size */:
+ field.get(&payload_size_);
+ break;
+ case 7 /* data_num_bytes */:
+ field.get(&data_num_bytes_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeMojoEventInfo::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeMojoEventInfo::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeMojoEventInfo::Serialize(::protozero::Message* msg) const {
+ // Field 1: watcher_notify_interface_tag
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, watcher_notify_interface_tag_, msg);
+ }
+
+ // Field 2: ipc_hash
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, ipc_hash_, msg);
+ }
+
+ // Field 3: mojo_interface_tag
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, mojo_interface_tag_, msg);
+ }
+
+ // Field 4: mojo_interface_method_iid
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, mojo_interface_method_iid_, msg);
+ }
+
+ // Field 5: is_reply
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, is_reply_, msg);
+ }
+
+ // Field 6: payload_size
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, payload_size_, msg);
+ }
+
+ // Field 7: data_num_bytes
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, data_num_bytes_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeProcessDescriptor::ChromeProcessDescriptor() = default;
+ChromeProcessDescriptor::~ChromeProcessDescriptor() = default;
+ChromeProcessDescriptor::ChromeProcessDescriptor(const ChromeProcessDescriptor&) = default;
+ChromeProcessDescriptor& ChromeProcessDescriptor::operator=(const ChromeProcessDescriptor&) = default;
+ChromeProcessDescriptor::ChromeProcessDescriptor(ChromeProcessDescriptor&&) noexcept = default;
+ChromeProcessDescriptor& ChromeProcessDescriptor::operator=(ChromeProcessDescriptor&&) = default;
+
+bool ChromeProcessDescriptor::operator==(const ChromeProcessDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_type_, other.process_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_priority_, other.process_priority_)
+ && ::protozero::internal::gen_helpers::EqualsField(legacy_sort_index_, other.legacy_sort_index_)
+ && ::protozero::internal::gen_helpers::EqualsField(host_app_package_name_, other.host_app_package_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(crash_trace_id_, other.crash_trace_id_);
+}
+
+bool ChromeProcessDescriptor::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* process_type */:
+ field.get(&process_type_);
+ break;
+ case 2 /* process_priority */:
+ field.get(&process_priority_);
+ break;
+ case 3 /* legacy_sort_index */:
+ field.get(&legacy_sort_index_);
+ break;
+ case 4 /* host_app_package_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &host_app_package_name_);
+ break;
+ case 5 /* crash_trace_id */:
+ field.get(&crash_trace_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeProcessDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeProcessDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeProcessDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: process_type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, process_type_, msg);
+ }
+
+ // Field 2: process_priority
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, process_priority_, msg);
+ }
+
+ // Field 3: legacy_sort_index
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, legacy_sort_index_, msg);
+ }
+
+ // Field 4: host_app_package_name
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeString(4, host_app_package_name_, msg);
+ }
+
+ // Field 5: crash_trace_id
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, crash_trace_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeRendererSchedulerState::ChromeRendererSchedulerState() = default;
+ChromeRendererSchedulerState::~ChromeRendererSchedulerState() = default;
+ChromeRendererSchedulerState::ChromeRendererSchedulerState(const ChromeRendererSchedulerState&) = default;
+ChromeRendererSchedulerState& ChromeRendererSchedulerState::operator=(const ChromeRendererSchedulerState&) = default;
+ChromeRendererSchedulerState::ChromeRendererSchedulerState(ChromeRendererSchedulerState&&) noexcept = default;
+ChromeRendererSchedulerState& ChromeRendererSchedulerState::operator=(ChromeRendererSchedulerState&&) = default;
+
+bool ChromeRendererSchedulerState::operator==(const ChromeRendererSchedulerState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(rail_mode_, other.rail_mode_)
+ && ::protozero::internal::gen_helpers::EqualsField(is_backgrounded_, other.is_backgrounded_)
+ && ::protozero::internal::gen_helpers::EqualsField(is_hidden_, other.is_hidden_);
+}
+
+bool ChromeRendererSchedulerState::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* rail_mode */:
+ field.get(&rail_mode_);
+ break;
+ case 2 /* is_backgrounded */:
+ field.get(&is_backgrounded_);
+ break;
+ case 3 /* is_hidden */:
+ field.get(&is_hidden_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeRendererSchedulerState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeRendererSchedulerState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeRendererSchedulerState::Serialize(::protozero::Message* msg) const {
+ // Field 1: rail_mode
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, rail_mode_, msg);
+ }
+
+ // Field 2: is_backgrounded
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, is_backgrounded_, msg);
+ }
+
+ // Field 3: is_hidden
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, is_hidden_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeThreadDescriptor::ChromeThreadDescriptor() = default;
+ChromeThreadDescriptor::~ChromeThreadDescriptor() = default;
+ChromeThreadDescriptor::ChromeThreadDescriptor(const ChromeThreadDescriptor&) = default;
+ChromeThreadDescriptor& ChromeThreadDescriptor::operator=(const ChromeThreadDescriptor&) = default;
+ChromeThreadDescriptor::ChromeThreadDescriptor(ChromeThreadDescriptor&&) noexcept = default;
+ChromeThreadDescriptor& ChromeThreadDescriptor::operator=(ChromeThreadDescriptor&&) = default;
+
+bool ChromeThreadDescriptor::operator==(const ChromeThreadDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_type_, other.thread_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(legacy_sort_index_, other.legacy_sort_index_);
+}
+
+bool ChromeThreadDescriptor::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* thread_type */:
+ field.get(&thread_type_);
+ break;
+ case 2 /* legacy_sort_index */:
+ field.get(&legacy_sort_index_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeThreadDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeThreadDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeThreadDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: thread_type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, thread_type_, msg);
+ }
+
+ // Field 2: legacy_sort_index
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, legacy_sort_index_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_user_event.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_user_event.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeUserEvent::ChromeUserEvent() = default;
+ChromeUserEvent::~ChromeUserEvent() = default;
+ChromeUserEvent::ChromeUserEvent(const ChromeUserEvent&) = default;
+ChromeUserEvent& ChromeUserEvent::operator=(const ChromeUserEvent&) = default;
+ChromeUserEvent::ChromeUserEvent(ChromeUserEvent&&) noexcept = default;
+ChromeUserEvent& ChromeUserEvent::operator=(ChromeUserEvent&&) = default;
+
+bool ChromeUserEvent::operator==(const ChromeUserEvent& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(action_, other.action_)
+ && ::protozero::internal::gen_helpers::EqualsField(action_hash_, other.action_hash_);
+}
+
+bool ChromeUserEvent::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* action */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &action_);
+ break;
+ case 2 /* action_hash */:
+ field.get(&action_hash_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeUserEvent::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeUserEvent::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeUserEvent::Serialize(::protozero::Message* msg) const {
+ // Field 1: action
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, action_, msg);
+ }
+
+ // Field 2: action_hash
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, action_hash_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/chrome_window_handle_event_info.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_window_handle_event_info.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ChromeWindowHandleEventInfo::ChromeWindowHandleEventInfo() = default;
+ChromeWindowHandleEventInfo::~ChromeWindowHandleEventInfo() = default;
+ChromeWindowHandleEventInfo::ChromeWindowHandleEventInfo(const ChromeWindowHandleEventInfo&) = default;
+ChromeWindowHandleEventInfo& ChromeWindowHandleEventInfo::operator=(const ChromeWindowHandleEventInfo&) = default;
+ChromeWindowHandleEventInfo::ChromeWindowHandleEventInfo(ChromeWindowHandleEventInfo&&) noexcept = default;
+ChromeWindowHandleEventInfo& ChromeWindowHandleEventInfo::operator=(ChromeWindowHandleEventInfo&&) = default;
+
+bool ChromeWindowHandleEventInfo::operator==(const ChromeWindowHandleEventInfo& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(dpi_, other.dpi_)
+ && ::protozero::internal::gen_helpers::EqualsField(message_id_, other.message_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(hwnd_ptr_, other.hwnd_ptr_);
+}
+
+bool ChromeWindowHandleEventInfo::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* dpi */:
+ field.get(&dpi_);
+ break;
+ case 2 /* message_id */:
+ field.get(&message_id_);
+ break;
+ case 3 /* hwnd_ptr */:
+ field.get(&hwnd_ptr_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChromeWindowHandleEventInfo::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChromeWindowHandleEventInfo::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChromeWindowHandleEventInfo::Serialize(::protozero::Message* msg) const {
+ // Field 1: dpi
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, dpi_, msg);
+ }
+
+ // Field 2: message_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, message_id_, msg);
+ }
+
+ // Field 3: hwnd_ptr
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(3, hwnd_ptr_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/counter_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+CounterDescriptor::CounterDescriptor() = default;
+CounterDescriptor::~CounterDescriptor() = default;
+CounterDescriptor::CounterDescriptor(const CounterDescriptor&) = default;
+CounterDescriptor& CounterDescriptor::operator=(const CounterDescriptor&) = default;
+CounterDescriptor::CounterDescriptor(CounterDescriptor&&) noexcept = default;
+CounterDescriptor& CounterDescriptor::operator=(CounterDescriptor&&) = default;
+
+bool CounterDescriptor::operator==(const CounterDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_, other.type_)
+ && ::protozero::internal::gen_helpers::EqualsField(categories_, other.categories_)
+ && ::protozero::internal::gen_helpers::EqualsField(unit_, other.unit_)
+ && ::protozero::internal::gen_helpers::EqualsField(unit_name_, other.unit_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(unit_multiplier_, other.unit_multiplier_)
+ && ::protozero::internal::gen_helpers::EqualsField(is_incremental_, other.is_incremental_);
+}
+
+bool CounterDescriptor::ParseFromArray(const void* raw, size_t size) {
+ categories_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* type */:
+ field.get(&type_);
+ break;
+ case 2 /* categories */:
+ categories_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &categories_.back());
+ break;
+ case 3 /* unit */:
+ field.get(&unit_);
+ break;
+ case 6 /* unit_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &unit_name_);
+ break;
+ case 4 /* unit_multiplier */:
+ field.get(&unit_multiplier_);
+ break;
+ case 5 /* is_incremental */:
+ field.get(&is_incremental_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CounterDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CounterDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CounterDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, type_, msg);
+ }
+
+ // Field 2: categories
+ for (auto& it : categories_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 3: unit
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, unit_, msg);
+ }
+
+ // Field 6: unit_name
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeString(6, unit_name_, msg);
+ }
+
+ // Field 4: unit_multiplier
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, unit_multiplier_, msg);
+ }
+
+ // Field 5: is_incremental
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(5, is_incremental_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/debug_annotation.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+DebugAnnotationValueTypeName::DebugAnnotationValueTypeName() = default;
+DebugAnnotationValueTypeName::~DebugAnnotationValueTypeName() = default;
+DebugAnnotationValueTypeName::DebugAnnotationValueTypeName(const DebugAnnotationValueTypeName&) = default;
+DebugAnnotationValueTypeName& DebugAnnotationValueTypeName::operator=(const DebugAnnotationValueTypeName&) = default;
+DebugAnnotationValueTypeName::DebugAnnotationValueTypeName(DebugAnnotationValueTypeName&&) noexcept = default;
+DebugAnnotationValueTypeName& DebugAnnotationValueTypeName::operator=(DebugAnnotationValueTypeName&&) = default;
+
+bool DebugAnnotationValueTypeName::operator==(const DebugAnnotationValueTypeName& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool DebugAnnotationValueTypeName::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DebugAnnotationValueTypeName::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DebugAnnotationValueTypeName::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DebugAnnotationValueTypeName::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DebugAnnotationName::DebugAnnotationName() = default;
+DebugAnnotationName::~DebugAnnotationName() = default;
+DebugAnnotationName::DebugAnnotationName(const DebugAnnotationName&) = default;
+DebugAnnotationName& DebugAnnotationName::operator=(const DebugAnnotationName&) = default;
+DebugAnnotationName::DebugAnnotationName(DebugAnnotationName&&) noexcept = default;
+DebugAnnotationName& DebugAnnotationName::operator=(DebugAnnotationName&&) = default;
+
+bool DebugAnnotationName::operator==(const DebugAnnotationName& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool DebugAnnotationName::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DebugAnnotationName::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DebugAnnotationName::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DebugAnnotationName::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DebugAnnotation::DebugAnnotation() = default;
+DebugAnnotation::~DebugAnnotation() = default;
+DebugAnnotation::DebugAnnotation(const DebugAnnotation&) = default;
+DebugAnnotation& DebugAnnotation::operator=(const DebugAnnotation&) = default;
+DebugAnnotation::DebugAnnotation(DebugAnnotation&&) noexcept = default;
+DebugAnnotation& DebugAnnotation::operator=(DebugAnnotation&&) = default;
+
+bool DebugAnnotation::operator==(const DebugAnnotation& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_iid_, other.name_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(bool_value_, other.bool_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(uint_value_, other.uint_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(int_value_, other.int_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(double_value_, other.double_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(pointer_value_, other.pointer_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(nested_value_, other.nested_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(legacy_json_value_, other.legacy_json_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(string_value_, other.string_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(string_value_iid_, other.string_value_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(proto_type_name_, other.proto_type_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(proto_type_name_iid_, other.proto_type_name_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(proto_value_, other.proto_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(dict_entries_, other.dict_entries_)
+ && ::protozero::internal::gen_helpers::EqualsField(array_values_, other.array_values_);
+}
+
+int DebugAnnotation::dict_entries_size() const { return static_cast<int>(dict_entries_.size()); }
+void DebugAnnotation::clear_dict_entries() { dict_entries_.clear(); }
+DebugAnnotation* DebugAnnotation::add_dict_entries() { dict_entries_.emplace_back(); return &dict_entries_.back(); }
+int DebugAnnotation::array_values_size() const { return static_cast<int>(array_values_.size()); }
+void DebugAnnotation::clear_array_values() { array_values_.clear(); }
+DebugAnnotation* DebugAnnotation::add_array_values() { array_values_.emplace_back(); return &array_values_.back(); }
+bool DebugAnnotation::ParseFromArray(const void* raw, size_t size) {
+ dict_entries_.clear();
+ array_values_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name_iid */:
+ field.get(&name_iid_);
+ break;
+ case 10 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 2 /* bool_value */:
+ field.get(&bool_value_);
+ break;
+ case 3 /* uint_value */:
+ field.get(&uint_value_);
+ break;
+ case 4 /* int_value */:
+ field.get(&int_value_);
+ break;
+ case 5 /* double_value */:
+ field.get(&double_value_);
+ break;
+ case 7 /* pointer_value */:
+ field.get(&pointer_value_);
+ break;
+ case 8 /* nested_value */:
+ (*nested_value_).ParseFromArray(field.data(), field.size());
+ break;
+ case 9 /* legacy_json_value */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &legacy_json_value_);
+ break;
+ case 6 /* string_value */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &string_value_);
+ break;
+ case 17 /* string_value_iid */:
+ field.get(&string_value_iid_);
+ break;
+ case 16 /* proto_type_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &proto_type_name_);
+ break;
+ case 13 /* proto_type_name_iid */:
+ field.get(&proto_type_name_iid_);
+ break;
+ case 14 /* proto_value */:
+ field.get(&proto_value_);
+ break;
+ case 11 /* dict_entries */:
+ dict_entries_.emplace_back();
+ dict_entries_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 12 /* array_values */:
+ array_values_.emplace_back();
+ array_values_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DebugAnnotation::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DebugAnnotation::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DebugAnnotation::Serialize(::protozero::Message* msg) const {
+ // Field 1: name_iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, name_iid_, msg);
+ }
+
+ // Field 10: name
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeString(10, name_, msg);
+ }
+
+ // Field 2: bool_value
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, bool_value_, msg);
+ }
+
+ // Field 3: uint_value
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, uint_value_, msg);
+ }
+
+ // Field 4: int_value
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, int_value_, msg);
+ }
+
+ // Field 5: double_value
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(5, double_value_, msg);
+ }
+
+ // Field 7: pointer_value
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, pointer_value_, msg);
+ }
+
+ // Field 8: nested_value
+ if (_has_field_[8]) {
+ (*nested_value_).Serialize(msg->BeginNestedMessage<::protozero::Message>(8));
+ }
+
+ // Field 9: legacy_json_value
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeString(9, legacy_json_value_, msg);
+ }
+
+ // Field 6: string_value
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeString(6, string_value_, msg);
+ }
+
+ // Field 17: string_value_iid
+ if (_has_field_[17]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, string_value_iid_, msg);
+ }
+
+ // Field 16: proto_type_name
+ if (_has_field_[16]) {
+ ::protozero::internal::gen_helpers::SerializeString(16, proto_type_name_, msg);
+ }
+
+ // Field 13: proto_type_name_iid
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, proto_type_name_iid_, msg);
+ }
+
+ // Field 14: proto_value
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeString(14, proto_value_, msg);
+ }
+
+ // Field 11: dict_entries
+ for (auto& it : dict_entries_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(11));
+ }
+
+ // Field 12: array_values
+ for (auto& it : array_values_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(12));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DebugAnnotation_NestedValue::DebugAnnotation_NestedValue() = default;
+DebugAnnotation_NestedValue::~DebugAnnotation_NestedValue() = default;
+DebugAnnotation_NestedValue::DebugAnnotation_NestedValue(const DebugAnnotation_NestedValue&) = default;
+DebugAnnotation_NestedValue& DebugAnnotation_NestedValue::operator=(const DebugAnnotation_NestedValue&) = default;
+DebugAnnotation_NestedValue::DebugAnnotation_NestedValue(DebugAnnotation_NestedValue&&) noexcept = default;
+DebugAnnotation_NestedValue& DebugAnnotation_NestedValue::operator=(DebugAnnotation_NestedValue&&) = default;
+
+bool DebugAnnotation_NestedValue::operator==(const DebugAnnotation_NestedValue& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(nested_type_, other.nested_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(dict_keys_, other.dict_keys_)
+ && ::protozero::internal::gen_helpers::EqualsField(dict_values_, other.dict_values_)
+ && ::protozero::internal::gen_helpers::EqualsField(array_values_, other.array_values_)
+ && ::protozero::internal::gen_helpers::EqualsField(int_value_, other.int_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(double_value_, other.double_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(bool_value_, other.bool_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(string_value_, other.string_value_);
+}
+
+int DebugAnnotation_NestedValue::dict_values_size() const { return static_cast<int>(dict_values_.size()); }
+void DebugAnnotation_NestedValue::clear_dict_values() { dict_values_.clear(); }
+DebugAnnotation_NestedValue* DebugAnnotation_NestedValue::add_dict_values() { dict_values_.emplace_back(); return &dict_values_.back(); }
+int DebugAnnotation_NestedValue::array_values_size() const { return static_cast<int>(array_values_.size()); }
+void DebugAnnotation_NestedValue::clear_array_values() { array_values_.clear(); }
+DebugAnnotation_NestedValue* DebugAnnotation_NestedValue::add_array_values() { array_values_.emplace_back(); return &array_values_.back(); }
+bool DebugAnnotation_NestedValue::ParseFromArray(const void* raw, size_t size) {
+ dict_keys_.clear();
+ dict_values_.clear();
+ array_values_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* nested_type */:
+ field.get(&nested_type_);
+ break;
+ case 2 /* dict_keys */:
+ dict_keys_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &dict_keys_.back());
+ break;
+ case 3 /* dict_values */:
+ dict_values_.emplace_back();
+ dict_values_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 4 /* array_values */:
+ array_values_.emplace_back();
+ array_values_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* int_value */:
+ field.get(&int_value_);
+ break;
+ case 6 /* double_value */:
+ field.get(&double_value_);
+ break;
+ case 7 /* bool_value */:
+ field.get(&bool_value_);
+ break;
+ case 8 /* string_value */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &string_value_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DebugAnnotation_NestedValue::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DebugAnnotation_NestedValue::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DebugAnnotation_NestedValue::Serialize(::protozero::Message* msg) const {
+ // Field 1: nested_type
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, nested_type_, msg);
+ }
+
+ // Field 2: dict_keys
+ for (auto& it : dict_keys_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 3: dict_values
+ for (auto& it : dict_values_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 4: array_values
+ for (auto& it : array_values_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: int_value
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, int_value_, msg);
+ }
+
+ // Field 6: double_value
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(6, double_value_, msg);
+ }
+
+ // Field 7: bool_value
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(7, bool_value_, msg);
+ }
+
+ // Field 8: string_value
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeString(8, string_value_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/log_message.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/log_message.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+LogMessageBody::LogMessageBody() = default;
+LogMessageBody::~LogMessageBody() = default;
+LogMessageBody::LogMessageBody(const LogMessageBody&) = default;
+LogMessageBody& LogMessageBody::operator=(const LogMessageBody&) = default;
+LogMessageBody::LogMessageBody(LogMessageBody&&) noexcept = default;
+LogMessageBody& LogMessageBody::operator=(LogMessageBody&&) = default;
+
+bool LogMessageBody::operator==(const LogMessageBody& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(body_, other.body_);
+}
+
+bool LogMessageBody::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* body */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &body_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string LogMessageBody::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> LogMessageBody::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void LogMessageBody::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: body
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, body_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+LogMessage::LogMessage() = default;
+LogMessage::~LogMessage() = default;
+LogMessage::LogMessage(const LogMessage&) = default;
+LogMessage& LogMessage::operator=(const LogMessage&) = default;
+LogMessage::LogMessage(LogMessage&&) noexcept = default;
+LogMessage& LogMessage::operator=(LogMessage&&) = default;
+
+bool LogMessage::operator==(const LogMessage& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(source_location_iid_, other.source_location_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(body_iid_, other.body_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(prio_, other.prio_);
+}
+
+bool LogMessage::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* source_location_iid */:
+ field.get(&source_location_iid_);
+ break;
+ case 2 /* body_iid */:
+ field.get(&body_iid_);
+ break;
+ case 3 /* prio */:
+ field.get(&prio_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string LogMessage::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> LogMessage::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void LogMessage::Serialize(::protozero::Message* msg) const {
+ // Field 1: source_location_iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, source_location_iid_, msg);
+ }
+
+ // Field 2: body_iid
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, body_iid_, msg);
+ }
+
+ // Field 3: prio
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, prio_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/pixel_modem.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/pixel_modem.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+PixelModemEventInsight::PixelModemEventInsight() = default;
+PixelModemEventInsight::~PixelModemEventInsight() = default;
+PixelModemEventInsight::PixelModemEventInsight(const PixelModemEventInsight&) = default;
+PixelModemEventInsight& PixelModemEventInsight::operator=(const PixelModemEventInsight&) = default;
+PixelModemEventInsight::PixelModemEventInsight(PixelModemEventInsight&&) noexcept = default;
+PixelModemEventInsight& PixelModemEventInsight::operator=(PixelModemEventInsight&&) = default;
+
+bool PixelModemEventInsight::operator==(const PixelModemEventInsight& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(detokenized_message_, other.detokenized_message_);
+}
+
+bool PixelModemEventInsight::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* detokenized_message */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &detokenized_message_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string PixelModemEventInsight::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> PixelModemEventInsight::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void PixelModemEventInsight::Serialize(::protozero::Message* msg) const {
+ // Field 1: detokenized_message
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, detokenized_message_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/process_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ProcessDescriptor::ProcessDescriptor() = default;
+ProcessDescriptor::~ProcessDescriptor() = default;
+ProcessDescriptor::ProcessDescriptor(const ProcessDescriptor&) = default;
+ProcessDescriptor& ProcessDescriptor::operator=(const ProcessDescriptor&) = default;
+ProcessDescriptor::ProcessDescriptor(ProcessDescriptor&&) noexcept = default;
+ProcessDescriptor& ProcessDescriptor::operator=(ProcessDescriptor&&) = default;
+
+bool ProcessDescriptor::operator==(const ProcessDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_, other.pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(cmdline_, other.cmdline_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_name_, other.process_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_priority_, other.process_priority_)
+ && ::protozero::internal::gen_helpers::EqualsField(start_timestamp_ns_, other.start_timestamp_ns_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_process_type_, other.chrome_process_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(legacy_sort_index_, other.legacy_sort_index_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_labels_, other.process_labels_);
+}
+
+bool ProcessDescriptor::ParseFromArray(const void* raw, size_t size) {
+ cmdline_.clear();
+ process_labels_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* pid */:
+ field.get(&pid_);
+ break;
+ case 2 /* cmdline */:
+ cmdline_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &cmdline_.back());
+ break;
+ case 6 /* process_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &process_name_);
+ break;
+ case 5 /* process_priority */:
+ field.get(&process_priority_);
+ break;
+ case 7 /* start_timestamp_ns */:
+ field.get(&start_timestamp_ns_);
+ break;
+ case 4 /* chrome_process_type */:
+ field.get(&chrome_process_type_);
+ break;
+ case 3 /* legacy_sort_index */:
+ field.get(&legacy_sort_index_);
+ break;
+ case 8 /* process_labels */:
+ process_labels_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &process_labels_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ProcessDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ProcessDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ProcessDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: pid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, pid_, msg);
+ }
+
+ // Field 2: cmdline
+ for (auto& it : cmdline_) {
+ ::protozero::internal::gen_helpers::SerializeString(2, it, msg);
+ }
+
+ // Field 6: process_name
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeString(6, process_name_, msg);
+ }
+
+ // Field 5: process_priority
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, process_priority_, msg);
+ }
+
+ // Field 7: start_timestamp_ns
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, start_timestamp_ns_, msg);
+ }
+
+ // Field 4: chrome_process_type
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, chrome_process_type_, msg);
+ }
+
+ // Field 3: legacy_sort_index
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, legacy_sort_index_, msg);
+ }
+
+ // Field 8: process_labels
+ for (auto& it : process_labels_) {
+ ::protozero::internal::gen_helpers::SerializeString(8, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/range_of_interest.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/range_of_interest.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TrackEventRangeOfInterest::TrackEventRangeOfInterest() = default;
+TrackEventRangeOfInterest::~TrackEventRangeOfInterest() = default;
+TrackEventRangeOfInterest::TrackEventRangeOfInterest(const TrackEventRangeOfInterest&) = default;
+TrackEventRangeOfInterest& TrackEventRangeOfInterest::operator=(const TrackEventRangeOfInterest&) = default;
+TrackEventRangeOfInterest::TrackEventRangeOfInterest(TrackEventRangeOfInterest&&) noexcept = default;
+TrackEventRangeOfInterest& TrackEventRangeOfInterest::operator=(TrackEventRangeOfInterest&&) = default;
+
+bool TrackEventRangeOfInterest::operator==(const TrackEventRangeOfInterest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(start_us_, other.start_us_);
+}
+
+bool TrackEventRangeOfInterest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* start_us */:
+ field.get(&start_us_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackEventRangeOfInterest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackEventRangeOfInterest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackEventRangeOfInterest::Serialize(::protozero::Message* msg) const {
+ // Field 1: start_us
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, start_us_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/screenshot.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/screenshot.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+Screenshot::Screenshot() = default;
+Screenshot::~Screenshot() = default;
+Screenshot::Screenshot(const Screenshot&) = default;
+Screenshot& Screenshot::operator=(const Screenshot&) = default;
+Screenshot::Screenshot(Screenshot&&) noexcept = default;
+Screenshot& Screenshot::operator=(Screenshot&&) = default;
+
+bool Screenshot::operator==(const Screenshot& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(jpg_image_, other.jpg_image_);
+}
+
+bool Screenshot::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* jpg_image */:
+ field.get(&jpg_image_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string Screenshot::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> Screenshot::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void Screenshot::Serialize(::protozero::Message* msg) const {
+ // Field 1: jpg_image
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, jpg_image_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/source_location.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/source_location.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+SourceLocation::SourceLocation() = default;
+SourceLocation::~SourceLocation() = default;
+SourceLocation::SourceLocation(const SourceLocation&) = default;
+SourceLocation& SourceLocation::operator=(const SourceLocation&) = default;
+SourceLocation::SourceLocation(SourceLocation&&) noexcept = default;
+SourceLocation& SourceLocation::operator=(SourceLocation&&) = default;
+
+bool SourceLocation::operator==(const SourceLocation& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(file_name_, other.file_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(function_name_, other.function_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(line_number_, other.line_number_);
+}
+
+bool SourceLocation::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* file_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &file_name_);
+ break;
+ case 3 /* function_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &function_name_);
+ break;
+ case 4 /* line_number */:
+ field.get(&line_number_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SourceLocation::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SourceLocation::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SourceLocation::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: file_name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, file_name_, msg);
+ }
+
+ // Field 3: function_name
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, function_name_, msg);
+ }
+
+ // Field 4: line_number
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, line_number_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UnsymbolizedSourceLocation::UnsymbolizedSourceLocation() = default;
+UnsymbolizedSourceLocation::~UnsymbolizedSourceLocation() = default;
+UnsymbolizedSourceLocation::UnsymbolizedSourceLocation(const UnsymbolizedSourceLocation&) = default;
+UnsymbolizedSourceLocation& UnsymbolizedSourceLocation::operator=(const UnsymbolizedSourceLocation&) = default;
+UnsymbolizedSourceLocation::UnsymbolizedSourceLocation(UnsymbolizedSourceLocation&&) noexcept = default;
+UnsymbolizedSourceLocation& UnsymbolizedSourceLocation::operator=(UnsymbolizedSourceLocation&&) = default;
+
+bool UnsymbolizedSourceLocation::operator==(const UnsymbolizedSourceLocation& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(mapping_id_, other.mapping_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(rel_pc_, other.rel_pc_);
+}
+
+bool UnsymbolizedSourceLocation::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* mapping_id */:
+ field.get(&mapping_id_);
+ break;
+ case 3 /* rel_pc */:
+ field.get(&rel_pc_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UnsymbolizedSourceLocation::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UnsymbolizedSourceLocation::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UnsymbolizedSourceLocation::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: mapping_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, mapping_id_, msg);
+ }
+
+ // Field 3: rel_pc
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, rel_pc_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/task_execution.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/task_execution.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TaskExecution::TaskExecution() = default;
+TaskExecution::~TaskExecution() = default;
+TaskExecution::TaskExecution(const TaskExecution&) = default;
+TaskExecution& TaskExecution::operator=(const TaskExecution&) = default;
+TaskExecution::TaskExecution(TaskExecution&&) noexcept = default;
+TaskExecution& TaskExecution::operator=(TaskExecution&&) = default;
+
+bool TaskExecution::operator==(const TaskExecution& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(posted_from_iid_, other.posted_from_iid_);
+}
+
+bool TaskExecution::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* posted_from_iid */:
+ field.get(&posted_from_iid_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TaskExecution::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TaskExecution::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TaskExecution::Serialize(::protozero::Message* msg) const {
+ // Field 1: posted_from_iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, posted_from_iid_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/thread_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+ThreadDescriptor::ThreadDescriptor() = default;
+ThreadDescriptor::~ThreadDescriptor() = default;
+ThreadDescriptor::ThreadDescriptor(const ThreadDescriptor&) = default;
+ThreadDescriptor& ThreadDescriptor::operator=(const ThreadDescriptor&) = default;
+ThreadDescriptor::ThreadDescriptor(ThreadDescriptor&&) noexcept = default;
+ThreadDescriptor& ThreadDescriptor::operator=(ThreadDescriptor&&) = default;
+
+bool ThreadDescriptor::operator==(const ThreadDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_, other.pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(tid_, other.tid_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_name_, other.thread_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_thread_type_, other.chrome_thread_type_)
+ && ::protozero::internal::gen_helpers::EqualsField(reference_timestamp_us_, other.reference_timestamp_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(reference_thread_time_us_, other.reference_thread_time_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(reference_thread_instruction_count_, other.reference_thread_instruction_count_)
+ && ::protozero::internal::gen_helpers::EqualsField(legacy_sort_index_, other.legacy_sort_index_);
+}
+
+bool ThreadDescriptor::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* pid */:
+ field.get(&pid_);
+ break;
+ case 2 /* tid */:
+ field.get(&tid_);
+ break;
+ case 5 /* thread_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &thread_name_);
+ break;
+ case 4 /* chrome_thread_type */:
+ field.get(&chrome_thread_type_);
+ break;
+ case 6 /* reference_timestamp_us */:
+ field.get(&reference_timestamp_us_);
+ break;
+ case 7 /* reference_thread_time_us */:
+ field.get(&reference_thread_time_us_);
+ break;
+ case 8 /* reference_thread_instruction_count */:
+ field.get(&reference_thread_instruction_count_);
+ break;
+ case 3 /* legacy_sort_index */:
+ field.get(&legacy_sort_index_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ThreadDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ThreadDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ThreadDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: pid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, pid_, msg);
+ }
+
+ // Field 2: tid
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, tid_, msg);
+ }
+
+ // Field 5: thread_name
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeString(5, thread_name_, msg);
+ }
+
+ // Field 4: chrome_thread_type
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, chrome_thread_type_, msg);
+ }
+
+ // Field 6: reference_timestamp_us
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, reference_timestamp_us_, msg);
+ }
+
+ // Field 7: reference_thread_time_us
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(7, reference_thread_time_us_, msg);
+ }
+
+ // Field 8: reference_thread_instruction_count
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, reference_thread_instruction_count_, msg);
+ }
+
+ // Field 3: legacy_sort_index
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, legacy_sort_index_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/track_descriptor.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+TrackDescriptor::TrackDescriptor() = default;
+TrackDescriptor::~TrackDescriptor() = default;
+TrackDescriptor::TrackDescriptor(const TrackDescriptor&) = default;
+TrackDescriptor& TrackDescriptor::operator=(const TrackDescriptor&) = default;
+TrackDescriptor::TrackDescriptor(TrackDescriptor&&) noexcept = default;
+TrackDescriptor& TrackDescriptor::operator=(TrackDescriptor&&) = default;
+
+bool TrackDescriptor::operator==(const TrackDescriptor& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(uuid_, other.uuid_)
+ && ::protozero::internal::gen_helpers::EqualsField(parent_uuid_, other.parent_uuid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(process_, other.process_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_process_, other.chrome_process_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_, other.thread_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_thread_, other.chrome_thread_)
+ && ::protozero::internal::gen_helpers::EqualsField(counter_, other.counter_)
+ && ::protozero::internal::gen_helpers::EqualsField(disallow_merging_with_system_tracks_, other.disallow_merging_with_system_tracks_);
+}
+
+bool TrackDescriptor::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* uuid */:
+ field.get(&uuid_);
+ break;
+ case 5 /* parent_uuid */:
+ field.get(&parent_uuid_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 3 /* process */:
+ (*process_).ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* chrome_process */:
+ (*chrome_process_).ParseFromArray(field.data(), field.size());
+ break;
+ case 4 /* thread */:
+ (*thread_).ParseFromArray(field.data(), field.size());
+ break;
+ case 7 /* chrome_thread */:
+ (*chrome_thread_).ParseFromArray(field.data(), field.size());
+ break;
+ case 8 /* counter */:
+ (*counter_).ParseFromArray(field.data(), field.size());
+ break;
+ case 9 /* disallow_merging_with_system_tracks */:
+ field.get(&disallow_merging_with_system_tracks_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackDescriptor::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackDescriptor::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackDescriptor::Serialize(::protozero::Message* msg) const {
+ // Field 1: uuid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, uuid_, msg);
+ }
+
+ // Field 5: parent_uuid
+ if (_has_field_[5]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(5, parent_uuid_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ // Field 3: process
+ if (_has_field_[3]) {
+ (*process_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 6: chrome_process
+ if (_has_field_[6]) {
+ (*chrome_process_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 4: thread
+ if (_has_field_[4]) {
+ (*thread_).Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 7: chrome_thread
+ if (_has_field_[7]) {
+ (*chrome_thread_).Serialize(msg->BeginNestedMessage<::protozero::Message>(7));
+ }
+
+ // Field 8: counter
+ if (_has_field_[8]) {
+ (*counter_).Serialize(msg->BeginNestedMessage<::protozero::Message>(8));
+ }
+
+ // Field 9: disallow_merging_with_system_tracks
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, disallow_merging_with_system_tracks_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/trace/track_event/track_event.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/source_location.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/screenshot.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/pixel_modem.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_window_handle_event_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_user_event.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_mojo_event_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_message_pump.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_latency_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_keyed_service.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_histogram_sample.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_frame_reporter.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_content_settings_event_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_application_state_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/chrome_active_processes.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/task_execution.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/log_message.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+EventName::EventName() = default;
+EventName::~EventName() = default;
+EventName::EventName(const EventName&) = default;
+EventName& EventName::operator=(const EventName&) = default;
+EventName::EventName(EventName&&) noexcept = default;
+EventName& EventName::operator=(EventName&&) = default;
+
+bool EventName::operator==(const EventName& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool EventName::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string EventName::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> EventName::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void EventName::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+EventCategory::EventCategory() = default;
+EventCategory::~EventCategory() = default;
+EventCategory::EventCategory(const EventCategory&) = default;
+EventCategory& EventCategory::operator=(const EventCategory&) = default;
+EventCategory::EventCategory(EventCategory&&) noexcept = default;
+EventCategory& EventCategory::operator=(EventCategory&&) = default;
+
+bool EventCategory::operator==(const EventCategory& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(iid_, other.iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool EventCategory::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* iid */:
+ field.get(&iid_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string EventCategory::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> EventCategory::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void EventCategory::Serialize(::protozero::Message* msg) const {
+ // Field 1: iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, iid_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TrackEventDefaults::TrackEventDefaults() = default;
+TrackEventDefaults::~TrackEventDefaults() = default;
+TrackEventDefaults::TrackEventDefaults(const TrackEventDefaults&) = default;
+TrackEventDefaults& TrackEventDefaults::operator=(const TrackEventDefaults&) = default;
+TrackEventDefaults::TrackEventDefaults(TrackEventDefaults&&) noexcept = default;
+TrackEventDefaults& TrackEventDefaults::operator=(TrackEventDefaults&&) = default;
+
+bool TrackEventDefaults::operator==(const TrackEventDefaults& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(track_uuid_, other.track_uuid_)
+ && ::protozero::internal::gen_helpers::EqualsField(extra_counter_track_uuids_, other.extra_counter_track_uuids_)
+ && ::protozero::internal::gen_helpers::EqualsField(extra_double_counter_track_uuids_, other.extra_double_counter_track_uuids_);
+}
+
+bool TrackEventDefaults::ParseFromArray(const void* raw, size_t size) {
+ extra_counter_track_uuids_.clear();
+ extra_double_counter_track_uuids_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 11 /* track_uuid */:
+ field.get(&track_uuid_);
+ break;
+ case 31 /* extra_counter_track_uuids */:
+ extra_counter_track_uuids_.emplace_back();
+ field.get(&extra_counter_track_uuids_.back());
+ break;
+ case 45 /* extra_double_counter_track_uuids */:
+ extra_double_counter_track_uuids_.emplace_back();
+ field.get(&extra_double_counter_track_uuids_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackEventDefaults::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackEventDefaults::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackEventDefaults::Serialize(::protozero::Message* msg) const {
+ // Field 11: track_uuid
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, track_uuid_, msg);
+ }
+
+ // Field 31: extra_counter_track_uuids
+ for (auto& it : extra_counter_track_uuids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(31, it, msg);
+ }
+
+ // Field 45: extra_double_counter_track_uuids
+ for (auto& it : extra_double_counter_track_uuids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(45, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TrackEvent::TrackEvent() = default;
+TrackEvent::~TrackEvent() = default;
+TrackEvent::TrackEvent(const TrackEvent&) = default;
+TrackEvent& TrackEvent::operator=(const TrackEvent&) = default;
+TrackEvent::TrackEvent(TrackEvent&&) noexcept = default;
+TrackEvent& TrackEvent::operator=(TrackEvent&&) = default;
+
+bool TrackEvent::operator==(const TrackEvent& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(category_iids_, other.category_iids_)
+ && ::protozero::internal::gen_helpers::EqualsField(categories_, other.categories_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_iid_, other.name_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_)
+ && ::protozero::internal::gen_helpers::EqualsField(type_, other.type_)
+ && ::protozero::internal::gen_helpers::EqualsField(track_uuid_, other.track_uuid_)
+ && ::protozero::internal::gen_helpers::EqualsField(counter_value_, other.counter_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(double_counter_value_, other.double_counter_value_)
+ && ::protozero::internal::gen_helpers::EqualsField(extra_counter_track_uuids_, other.extra_counter_track_uuids_)
+ && ::protozero::internal::gen_helpers::EqualsField(extra_counter_values_, other.extra_counter_values_)
+ && ::protozero::internal::gen_helpers::EqualsField(extra_double_counter_track_uuids_, other.extra_double_counter_track_uuids_)
+ && ::protozero::internal::gen_helpers::EqualsField(extra_double_counter_values_, other.extra_double_counter_values_)
+ && ::protozero::internal::gen_helpers::EqualsField(flow_ids_old_, other.flow_ids_old_)
+ && ::protozero::internal::gen_helpers::EqualsField(flow_ids_, other.flow_ids_)
+ && ::protozero::internal::gen_helpers::EqualsField(terminating_flow_ids_old_, other.terminating_flow_ids_old_)
+ && ::protozero::internal::gen_helpers::EqualsField(terminating_flow_ids_, other.terminating_flow_ids_)
+ && ::protozero::internal::gen_helpers::EqualsField(debug_annotations_, other.debug_annotations_)
+ && ::protozero::internal::gen_helpers::EqualsField(task_execution_, other.task_execution_)
+ && ::protozero::internal::gen_helpers::EqualsField(log_message_, other.log_message_)
+ && ::protozero::internal::gen_helpers::EqualsField(cc_scheduler_state_, other.cc_scheduler_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_user_event_, other.chrome_user_event_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_keyed_service_, other.chrome_keyed_service_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_legacy_ipc_, other.chrome_legacy_ipc_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_histogram_sample_, other.chrome_histogram_sample_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_latency_info_, other.chrome_latency_info_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_frame_reporter_, other.chrome_frame_reporter_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_application_state_info_, other.chrome_application_state_info_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_renderer_scheduler_state_, other.chrome_renderer_scheduler_state_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_window_handle_event_info_, other.chrome_window_handle_event_info_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_content_settings_event_info_, other.chrome_content_settings_event_info_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_active_processes_, other.chrome_active_processes_)
+ && ::protozero::internal::gen_helpers::EqualsField(screenshot_, other.screenshot_)
+ && ::protozero::internal::gen_helpers::EqualsField(pixel_modem_event_insight_, other.pixel_modem_event_insight_)
+ && ::protozero::internal::gen_helpers::EqualsField(source_location_, other.source_location_)
+ && ::protozero::internal::gen_helpers::EqualsField(source_location_iid_, other.source_location_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_message_pump_, other.chrome_message_pump_)
+ && ::protozero::internal::gen_helpers::EqualsField(chrome_mojo_event_info_, other.chrome_mojo_event_info_)
+ && ::protozero::internal::gen_helpers::EqualsField(timestamp_delta_us_, other.timestamp_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(timestamp_absolute_us_, other.timestamp_absolute_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_time_delta_us_, other.thread_time_delta_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_time_absolute_us_, other.thread_time_absolute_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_instruction_count_delta_, other.thread_instruction_count_delta_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_instruction_count_absolute_, other.thread_instruction_count_absolute_)
+ && ::protozero::internal::gen_helpers::EqualsField(legacy_event_, other.legacy_event_);
+}
+
+int TrackEvent::debug_annotations_size() const { return static_cast<int>(debug_annotations_.size()); }
+void TrackEvent::clear_debug_annotations() { debug_annotations_.clear(); }
+DebugAnnotation* TrackEvent::add_debug_annotations() { debug_annotations_.emplace_back(); return &debug_annotations_.back(); }
+bool TrackEvent::ParseFromArray(const void* raw, size_t size) {
+ category_iids_.clear();
+ categories_.clear();
+ extra_counter_track_uuids_.clear();
+ extra_counter_values_.clear();
+ extra_double_counter_track_uuids_.clear();
+ extra_double_counter_values_.clear();
+ flow_ids_old_.clear();
+ flow_ids_.clear();
+ terminating_flow_ids_old_.clear();
+ terminating_flow_ids_.clear();
+ debug_annotations_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 3 /* category_iids */:
+ category_iids_.emplace_back();
+ field.get(&category_iids_.back());
+ break;
+ case 22 /* categories */:
+ categories_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &categories_.back());
+ break;
+ case 10 /* name_iid */:
+ field.get(&name_iid_);
+ break;
+ case 23 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ case 9 /* type */:
+ field.get(&type_);
+ break;
+ case 11 /* track_uuid */:
+ field.get(&track_uuid_);
+ break;
+ case 30 /* counter_value */:
+ field.get(&counter_value_);
+ break;
+ case 44 /* double_counter_value */:
+ field.get(&double_counter_value_);
+ break;
+ case 31 /* extra_counter_track_uuids */:
+ extra_counter_track_uuids_.emplace_back();
+ field.get(&extra_counter_track_uuids_.back());
+ break;
+ case 12 /* extra_counter_values */:
+ extra_counter_values_.emplace_back();
+ field.get(&extra_counter_values_.back());
+ break;
+ case 45 /* extra_double_counter_track_uuids */:
+ extra_double_counter_track_uuids_.emplace_back();
+ field.get(&extra_double_counter_track_uuids_.back());
+ break;
+ case 46 /* extra_double_counter_values */:
+ extra_double_counter_values_.emplace_back();
+ field.get(&extra_double_counter_values_.back());
+ break;
+ case 36 /* flow_ids_old */:
+ flow_ids_old_.emplace_back();
+ field.get(&flow_ids_old_.back());
+ break;
+ case 47 /* flow_ids */:
+ flow_ids_.emplace_back();
+ field.get(&flow_ids_.back());
+ break;
+ case 42 /* terminating_flow_ids_old */:
+ terminating_flow_ids_old_.emplace_back();
+ field.get(&terminating_flow_ids_old_.back());
+ break;
+ case 48 /* terminating_flow_ids */:
+ terminating_flow_ids_.emplace_back();
+ field.get(&terminating_flow_ids_.back());
+ break;
+ case 4 /* debug_annotations */:
+ debug_annotations_.emplace_back();
+ debug_annotations_.back().ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* task_execution */:
+ (*task_execution_).ParseFromArray(field.data(), field.size());
+ break;
+ case 21 /* log_message */:
+ (*log_message_).ParseFromArray(field.data(), field.size());
+ break;
+ case 24 /* cc_scheduler_state */:
+ (*cc_scheduler_state_).ParseFromArray(field.data(), field.size());
+ break;
+ case 25 /* chrome_user_event */:
+ (*chrome_user_event_).ParseFromArray(field.data(), field.size());
+ break;
+ case 26 /* chrome_keyed_service */:
+ (*chrome_keyed_service_).ParseFromArray(field.data(), field.size());
+ break;
+ case 27 /* chrome_legacy_ipc */:
+ (*chrome_legacy_ipc_).ParseFromArray(field.data(), field.size());
+ break;
+ case 28 /* chrome_histogram_sample */:
+ (*chrome_histogram_sample_).ParseFromArray(field.data(), field.size());
+ break;
+ case 29 /* chrome_latency_info */:
+ (*chrome_latency_info_).ParseFromArray(field.data(), field.size());
+ break;
+ case 32 /* chrome_frame_reporter */:
+ (*chrome_frame_reporter_).ParseFromArray(field.data(), field.size());
+ break;
+ case 39 /* chrome_application_state_info */:
+ (*chrome_application_state_info_).ParseFromArray(field.data(), field.size());
+ break;
+ case 40 /* chrome_renderer_scheduler_state */:
+ (*chrome_renderer_scheduler_state_).ParseFromArray(field.data(), field.size());
+ break;
+ case 41 /* chrome_window_handle_event_info */:
+ (*chrome_window_handle_event_info_).ParseFromArray(field.data(), field.size());
+ break;
+ case 43 /* chrome_content_settings_event_info */:
+ (*chrome_content_settings_event_info_).ParseFromArray(field.data(), field.size());
+ break;
+ case 49 /* chrome_active_processes */:
+ (*chrome_active_processes_).ParseFromArray(field.data(), field.size());
+ break;
+ case 50 /* screenshot */:
+ (*screenshot_).ParseFromArray(field.data(), field.size());
+ break;
+ case 51 /* pixel_modem_event_insight */:
+ (*pixel_modem_event_insight_).ParseFromArray(field.data(), field.size());
+ break;
+ case 33 /* source_location */:
+ (*source_location_).ParseFromArray(field.data(), field.size());
+ break;
+ case 34 /* source_location_iid */:
+ field.get(&source_location_iid_);
+ break;
+ case 35 /* chrome_message_pump */:
+ (*chrome_message_pump_).ParseFromArray(field.data(), field.size());
+ break;
+ case 38 /* chrome_mojo_event_info */:
+ (*chrome_mojo_event_info_).ParseFromArray(field.data(), field.size());
+ break;
+ case 1 /* timestamp_delta_us */:
+ field.get(&timestamp_delta_us_);
+ break;
+ case 16 /* timestamp_absolute_us */:
+ field.get(&timestamp_absolute_us_);
+ break;
+ case 2 /* thread_time_delta_us */:
+ field.get(&thread_time_delta_us_);
+ break;
+ case 17 /* thread_time_absolute_us */:
+ field.get(&thread_time_absolute_us_);
+ break;
+ case 8 /* thread_instruction_count_delta */:
+ field.get(&thread_instruction_count_delta_);
+ break;
+ case 20 /* thread_instruction_count_absolute */:
+ field.get(&thread_instruction_count_absolute_);
+ break;
+ case 6 /* legacy_event */:
+ (*legacy_event_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackEvent::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackEvent::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackEvent::Serialize(::protozero::Message* msg) const {
+ // Field 3: category_iids
+ for (auto& it : category_iids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, it, msg);
+ }
+
+ // Field 22: categories
+ for (auto& it : categories_) {
+ ::protozero::internal::gen_helpers::SerializeString(22, it, msg);
+ }
+
+ // Field 10: name_iid
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, name_iid_, msg);
+ }
+
+ // Field 23: name
+ if (_has_field_[23]) {
+ ::protozero::internal::gen_helpers::SerializeString(23, name_, msg);
+ }
+
+ // Field 9: type
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(9, type_, msg);
+ }
+
+ // Field 11: track_uuid
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, track_uuid_, msg);
+ }
+
+ // Field 30: counter_value
+ if (_has_field_[30]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(30, counter_value_, msg);
+ }
+
+ // Field 44: double_counter_value
+ if (_has_field_[44]) {
+ ::protozero::internal::gen_helpers::SerializeFixed(44, double_counter_value_, msg);
+ }
+
+ // Field 31: extra_counter_track_uuids
+ for (auto& it : extra_counter_track_uuids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(31, it, msg);
+ }
+
+ // Field 12: extra_counter_values
+ for (auto& it : extra_counter_values_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(12, it, msg);
+ }
+
+ // Field 45: extra_double_counter_track_uuids
+ for (auto& it : extra_double_counter_track_uuids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(45, it, msg);
+ }
+
+ // Field 46: extra_double_counter_values
+ for (auto& it : extra_double_counter_values_) {
+ ::protozero::internal::gen_helpers::SerializeFixed(46, it, msg);
+ }
+
+ // Field 36: flow_ids_old
+ for (auto& it : flow_ids_old_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(36, it, msg);
+ }
+
+ // Field 47: flow_ids
+ for (auto& it : flow_ids_) {
+ ::protozero::internal::gen_helpers::SerializeFixed(47, it, msg);
+ }
+
+ // Field 42: terminating_flow_ids_old
+ for (auto& it : terminating_flow_ids_old_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(42, it, msg);
+ }
+
+ // Field 48: terminating_flow_ids
+ for (auto& it : terminating_flow_ids_) {
+ ::protozero::internal::gen_helpers::SerializeFixed(48, it, msg);
+ }
+
+ // Field 4: debug_annotations
+ for (auto& it : debug_annotations_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: task_execution
+ if (_has_field_[5]) {
+ (*task_execution_).Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 21: log_message
+ if (_has_field_[21]) {
+ (*log_message_).Serialize(msg->BeginNestedMessage<::protozero::Message>(21));
+ }
+
+ // Field 24: cc_scheduler_state
+ if (_has_field_[24]) {
+ (*cc_scheduler_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(24));
+ }
+
+ // Field 25: chrome_user_event
+ if (_has_field_[25]) {
+ (*chrome_user_event_).Serialize(msg->BeginNestedMessage<::protozero::Message>(25));
+ }
+
+ // Field 26: chrome_keyed_service
+ if (_has_field_[26]) {
+ (*chrome_keyed_service_).Serialize(msg->BeginNestedMessage<::protozero::Message>(26));
+ }
+
+ // Field 27: chrome_legacy_ipc
+ if (_has_field_[27]) {
+ (*chrome_legacy_ipc_).Serialize(msg->BeginNestedMessage<::protozero::Message>(27));
+ }
+
+ // Field 28: chrome_histogram_sample
+ if (_has_field_[28]) {
+ (*chrome_histogram_sample_).Serialize(msg->BeginNestedMessage<::protozero::Message>(28));
+ }
+
+ // Field 29: chrome_latency_info
+ if (_has_field_[29]) {
+ (*chrome_latency_info_).Serialize(msg->BeginNestedMessage<::protozero::Message>(29));
+ }
+
+ // Field 32: chrome_frame_reporter
+ if (_has_field_[32]) {
+ (*chrome_frame_reporter_).Serialize(msg->BeginNestedMessage<::protozero::Message>(32));
+ }
+
+ // Field 39: chrome_application_state_info
+ if (_has_field_[39]) {
+ (*chrome_application_state_info_).Serialize(msg->BeginNestedMessage<::protozero::Message>(39));
+ }
+
+ // Field 40: chrome_renderer_scheduler_state
+ if (_has_field_[40]) {
+ (*chrome_renderer_scheduler_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(40));
+ }
+
+ // Field 41: chrome_window_handle_event_info
+ if (_has_field_[41]) {
+ (*chrome_window_handle_event_info_).Serialize(msg->BeginNestedMessage<::protozero::Message>(41));
+ }
+
+ // Field 43: chrome_content_settings_event_info
+ if (_has_field_[43]) {
+ (*chrome_content_settings_event_info_).Serialize(msg->BeginNestedMessage<::protozero::Message>(43));
+ }
+
+ // Field 49: chrome_active_processes
+ if (_has_field_[49]) {
+ (*chrome_active_processes_).Serialize(msg->BeginNestedMessage<::protozero::Message>(49));
+ }
+
+ // Field 50: screenshot
+ if (_has_field_[50]) {
+ (*screenshot_).Serialize(msg->BeginNestedMessage<::protozero::Message>(50));
+ }
+
+ // Field 51: pixel_modem_event_insight
+ if (_has_field_[51]) {
+ (*pixel_modem_event_insight_).Serialize(msg->BeginNestedMessage<::protozero::Message>(51));
+ }
+
+ // Field 33: source_location
+ if (_has_field_[33]) {
+ (*source_location_).Serialize(msg->BeginNestedMessage<::protozero::Message>(33));
+ }
+
+ // Field 34: source_location_iid
+ if (_has_field_[34]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(34, source_location_iid_, msg);
+ }
+
+ // Field 35: chrome_message_pump
+ if (_has_field_[35]) {
+ (*chrome_message_pump_).Serialize(msg->BeginNestedMessage<::protozero::Message>(35));
+ }
+
+ // Field 38: chrome_mojo_event_info
+ if (_has_field_[38]) {
+ (*chrome_mojo_event_info_).Serialize(msg->BeginNestedMessage<::protozero::Message>(38));
+ }
+
+ // Field 1: timestamp_delta_us
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, timestamp_delta_us_, msg);
+ }
+
+ // Field 16: timestamp_absolute_us
+ if (_has_field_[16]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(16, timestamp_absolute_us_, msg);
+ }
+
+ // Field 2: thread_time_delta_us
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, thread_time_delta_us_, msg);
+ }
+
+ // Field 17: thread_time_absolute_us
+ if (_has_field_[17]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(17, thread_time_absolute_us_, msg);
+ }
+
+ // Field 8: thread_instruction_count_delta
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, thread_instruction_count_delta_, msg);
+ }
+
+ // Field 20: thread_instruction_count_absolute
+ if (_has_field_[20]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(20, thread_instruction_count_absolute_, msg);
+ }
+
+ // Field 6: legacy_event
+ if (_has_field_[6]) {
+ (*legacy_event_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+TrackEvent_LegacyEvent::TrackEvent_LegacyEvent() = default;
+TrackEvent_LegacyEvent::~TrackEvent_LegacyEvent() = default;
+TrackEvent_LegacyEvent::TrackEvent_LegacyEvent(const TrackEvent_LegacyEvent&) = default;
+TrackEvent_LegacyEvent& TrackEvent_LegacyEvent::operator=(const TrackEvent_LegacyEvent&) = default;
+TrackEvent_LegacyEvent::TrackEvent_LegacyEvent(TrackEvent_LegacyEvent&&) noexcept = default;
+TrackEvent_LegacyEvent& TrackEvent_LegacyEvent::operator=(TrackEvent_LegacyEvent&&) = default;
+
+bool TrackEvent_LegacyEvent::operator==(const TrackEvent_LegacyEvent& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_iid_, other.name_iid_)
+ && ::protozero::internal::gen_helpers::EqualsField(phase_, other.phase_)
+ && ::protozero::internal::gen_helpers::EqualsField(duration_us_, other.duration_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_duration_us_, other.thread_duration_us_)
+ && ::protozero::internal::gen_helpers::EqualsField(thread_instruction_delta_, other.thread_instruction_delta_)
+ && ::protozero::internal::gen_helpers::EqualsField(unscoped_id_, other.unscoped_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(local_id_, other.local_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(global_id_, other.global_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(id_scope_, other.id_scope_)
+ && ::protozero::internal::gen_helpers::EqualsField(use_async_tts_, other.use_async_tts_)
+ && ::protozero::internal::gen_helpers::EqualsField(bind_id_, other.bind_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(bind_to_enclosing_, other.bind_to_enclosing_)
+ && ::protozero::internal::gen_helpers::EqualsField(flow_direction_, other.flow_direction_)
+ && ::protozero::internal::gen_helpers::EqualsField(instant_event_scope_, other.instant_event_scope_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_override_, other.pid_override_)
+ && ::protozero::internal::gen_helpers::EqualsField(tid_override_, other.tid_override_);
+}
+
+bool TrackEvent_LegacyEvent::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* name_iid */:
+ field.get(&name_iid_);
+ break;
+ case 2 /* phase */:
+ field.get(&phase_);
+ break;
+ case 3 /* duration_us */:
+ field.get(&duration_us_);
+ break;
+ case 4 /* thread_duration_us */:
+ field.get(&thread_duration_us_);
+ break;
+ case 15 /* thread_instruction_delta */:
+ field.get(&thread_instruction_delta_);
+ break;
+ case 6 /* unscoped_id */:
+ field.get(&unscoped_id_);
+ break;
+ case 10 /* local_id */:
+ field.get(&local_id_);
+ break;
+ case 11 /* global_id */:
+ field.get(&global_id_);
+ break;
+ case 7 /* id_scope */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &id_scope_);
+ break;
+ case 9 /* use_async_tts */:
+ field.get(&use_async_tts_);
+ break;
+ case 8 /* bind_id */:
+ field.get(&bind_id_);
+ break;
+ case 12 /* bind_to_enclosing */:
+ field.get(&bind_to_enclosing_);
+ break;
+ case 13 /* flow_direction */:
+ field.get(&flow_direction_);
+ break;
+ case 14 /* instant_event_scope */:
+ field.get(&instant_event_scope_);
+ break;
+ case 18 /* pid_override */:
+ field.get(&pid_override_);
+ break;
+ case 19 /* tid_override */:
+ field.get(&tid_override_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string TrackEvent_LegacyEvent::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> TrackEvent_LegacyEvent::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void TrackEvent_LegacyEvent::Serialize(::protozero::Message* msg) const {
+ // Field 1: name_iid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, name_iid_, msg);
+ }
+
+ // Field 2: phase
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, phase_, msg);
+ }
+
+ // Field 3: duration_us
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, duration_us_, msg);
+ }
+
+ // Field 4: thread_duration_us
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, thread_duration_us_, msg);
+ }
+
+ // Field 15: thread_instruction_delta
+ if (_has_field_[15]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(15, thread_instruction_delta_, msg);
+ }
+
+ // Field 6: unscoped_id
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(6, unscoped_id_, msg);
+ }
+
+ // Field 10: local_id
+ if (_has_field_[10]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(10, local_id_, msg);
+ }
+
+ // Field 11: global_id
+ if (_has_field_[11]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(11, global_id_, msg);
+ }
+
+ // Field 7: id_scope
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeString(7, id_scope_, msg);
+ }
+
+ // Field 9: use_async_tts
+ if (_has_field_[9]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(9, use_async_tts_, msg);
+ }
+
+ // Field 8: bind_id
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(8, bind_id_, msg);
+ }
+
+ // Field 12: bind_to_enclosing
+ if (_has_field_[12]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(12, bind_to_enclosing_, msg);
+ }
+
+ // Field 13: flow_direction
+ if (_has_field_[13]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(13, flow_direction_, msg);
+ }
+
+ // Field 14: instant_event_scope
+ if (_has_field_[14]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(14, instant_event_scope_, msg);
+ }
+
+ // Field 18: pid_override
+ if (_has_field_[18]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(18, pid_override_, msg);
+ }
+
+ // Field 19: tid_override
+ if (_has_field_[19]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(19, tid_override_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_game_intervention_list_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_input_event_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_log_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_polled_state_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_sdk_sysprop_guard_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/android_system_property_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/network_trace_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/packages_list_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/protolog_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/surfaceflinger_layers_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/android/surfaceflinger_transactions_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/ftrace/ftrace_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/gpu/gpu_counter_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/gpu/vulkan_memory_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/inode_file/inode_file_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/interceptors/console_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/power/android_power_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/process_stats/process_stats_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/profiling/heapprofd_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/profiling/java_hprof_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/profiling/perf_event_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/statsd/atom_ids.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/statsd/statsd_tracing_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/system_info/system_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/track_event/track_event_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/chrome/chrome_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/chrome/scenario_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/chrome/v8_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/data_source_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/etw/etw_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/interceptor_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/stress_test_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/test_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/config/trace_config.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/clock_snapshot.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/trace_uuid.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/trigger.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/system_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/etw/etw.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/etw/etw_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/etw/etw_event_bundle.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/filesystem/inode_file_map.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ftrace_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/test_bundle_wrapper.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/generic.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/android_fs.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/binder.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/block.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/cgroup.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/clk.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/cma.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/compaction.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/cpuhp.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/cros_ec.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/dma_fence.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/dpu.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/drm.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ext4.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/f2fs.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/fastrpc.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/fence.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/filemap.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ftrace.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/g2d.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/gpu_mem.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/gpu_scheduler.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/hyp.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/i2c.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ion.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ipi.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/irq.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/kmem.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/kvm.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/lwis.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/mali.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/mdss.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/mm_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/net.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/oom.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/panel.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/perf_trace_counters.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/power.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/printk.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/raw_syscalls.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/regulator.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/rpm.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/samsung.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/sched.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/scm.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/sde.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/signal.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/skb.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/sock.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/sync.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/synthetic.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/systrace.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/task.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/tcp.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/thermal.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/trusty.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/ufs.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/v4l2.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/virtio_gpu.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/virtio_video.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/vmscan.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ftrace/workqueue.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/perfetto/tracing_service_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/power/android_energy_estimation_breakdown.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/power/android_entity_state_residency.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/power/battery_counters.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/power/power_rails.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ps/process_stats.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ps/process_tree.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/statsd/statsd_atom.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/sys_stats/sys_stats.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/system_info/cpu_info.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/translation/translation_table.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/remote_clock_sync.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/trace_packet_defaults.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/test_event.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/test_extensions.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/trace_packet.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/trace.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/extension_descriptor.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/memory_graph.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: gen/protos/perfetto/trace/ui_state.pbzero.cc
+// Intentionally empty (crbug.com/998165)
+// gen_amalgamated begin source: src/tracing/trace_writer_base.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+
+namespace perfetto {
+
+// This destructor needs to be defined in a dedicated translation unit and
+// cannot be merged together with the other ones in virtual_destructors.cc.
+// This is because trace_writer_base.h/cc is part of a separate target
+// (src/public:common) that is linked also by other part of the codebase.
+
+TraceWriterBase::~TraceWriterBase() = default;
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/clock_snapshots.cc
+// gen_amalgamated begin header: include/perfetto/tracing/core/clock_snapshots.h
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_CLOCK_SNAPSHOTS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_CLOCK_SNAPSHOTS_H_
+
+#include <cstdint>
+#include <vector>
+
+namespace perfetto {
+struct ClockReading {
+ ClockReading(uint32_t _clock_id, uint64_t _timestamp)
+ : clock_id(_clock_id), timestamp(_timestamp) {}
+ ClockReading() = default;
+
+ // Identifier of the clock domain (of type protos::pbzero::BuiltinClock).
+ uint32_t clock_id = 0;
+ // Clock reading as uint64_t.
+ uint64_t timestamp = 0;
+};
+
+using ClockSnapshotVector = std::vector<ClockReading>;
+
+// Takes snapshots of clock readings of all supported built-in clocks.
+ClockSnapshotVector CaptureClockSnapshots();
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_CLOCK_SNAPSHOTS_H_
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/core/clock_snapshots.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.pbzero.h"
+
+namespace perfetto {
+
+ClockSnapshotVector CaptureClockSnapshots() {
+ ClockSnapshotVector snapshot_data;
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+ struct {
+ clockid_t id;
+ protos::pbzero::BuiltinClock type;
+ struct timespec ts;
+ } clocks[] = {
+ {CLOCK_BOOTTIME, protos::pbzero::BUILTIN_CLOCK_BOOTTIME, {0, 0}},
+ {CLOCK_REALTIME_COARSE,
+ protos::pbzero::BUILTIN_CLOCK_REALTIME_COARSE,
+ {0, 0}},
+ {CLOCK_MONOTONIC_COARSE,
+ protos::pbzero::BUILTIN_CLOCK_MONOTONIC_COARSE,
+ {0, 0}},
+ {CLOCK_REALTIME, protos::pbzero::BUILTIN_CLOCK_REALTIME, {0, 0}},
+ {CLOCK_MONOTONIC, protos::pbzero::BUILTIN_CLOCK_MONOTONIC, {0, 0}},
+ {CLOCK_MONOTONIC_RAW,
+ protos::pbzero::BUILTIN_CLOCK_MONOTONIC_RAW,
+ {0, 0}},
+ };
+ // First snapshot all the clocks as atomically as we can.
+ for (auto& clock : clocks) {
+ if (clock_gettime(clock.id, &clock.ts) == -1)
+ PERFETTO_DLOG("clock_gettime failed for clock %d", clock.id);
+ }
+ for (auto& clock : clocks) {
+ snapshot_data.push_back(ClockReading(
+ static_cast<uint32_t>(clock.type),
+ static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count())));
+ }
+#else // OS_APPLE || OS_WIN && OS_NACL
+ auto wall_time_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
+ // The default trace clock is boot time, so we always need to emit a path to
+ // it. However since we don't actually have a boot time source on these
+ // platforms, pretend that wall time equals boot time.
+ snapshot_data.push_back(
+ ClockReading(protos::pbzero::BUILTIN_CLOCK_BOOTTIME, wall_time_ns));
+ snapshot_data.push_back(
+ ClockReading(protos::pbzero::BUILTIN_CLOCK_MONOTONIC, wall_time_ns));
+#endif
+
+ return snapshot_data;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/id_allocator.cc
+// gen_amalgamated begin header: src/tracing/core/id_allocator.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_CORE_ID_ALLOCATOR_H_
+#define SRC_TRACING_CORE_ID_ALLOCATOR_H_
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+namespace perfetto {
+
+// Handles assigment of IDs (int types) from a fixed-size pool.
+// Zero is not considered a valid ID.
+// The base class takes always a uint32_t and the derived class casts and checks
+// bounds at compile time. This is to avoid bloating code with different
+// instances of the main class for each size.
+class IdAllocatorGeneric {
+ public:
+ // |max_id| is inclusive.
+ explicit IdAllocatorGeneric(uint32_t max_id);
+ ~IdAllocatorGeneric();
+
+ // Returns an ID in the range [1, max_id] or 0 if no more ids are available.
+ uint32_t AllocateGeneric();
+ void FreeGeneric(uint32_t);
+
+ bool IsEmpty() const;
+
+ private:
+ IdAllocatorGeneric(const IdAllocatorGeneric&) = delete;
+ IdAllocatorGeneric& operator=(const IdAllocatorGeneric&) = delete;
+
+ const uint32_t max_id_;
+ uint32_t last_id_ = 0;
+ std::vector<bool> ids_;
+};
+
+template <typename T = uint32_t>
+class IdAllocator : public IdAllocatorGeneric {
+ public:
+ explicit IdAllocator(T end) : IdAllocatorGeneric(end) {
+ static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
+ "T must be an unsigned integer");
+ static_assert(sizeof(T) <= sizeof(uint32_t), "T is too big");
+ }
+
+ T Allocate() { return static_cast<T>(AllocateGeneric()); }
+
+ // Tries to allocate `n` IDs. Returns a vector of `n` valid IDs or an empty
+ // vector, if not enough IDs are available.
+ std::vector<T> AllocateMultiple(size_t n) {
+ std::vector<T> res;
+ res.reserve(n);
+ for (size_t i = 0; i < n; i++) {
+ T id = Allocate();
+ if (id) {
+ res.push_back(id);
+ } else {
+ for (T free_id : res) {
+ Free(free_id);
+ }
+ return {};
+ }
+ }
+ return res;
+ }
+
+ void Free(T id) { FreeGeneric(id); }
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_CORE_ID_ALLOCATOR_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/core/id_allocator.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+
+IdAllocatorGeneric::IdAllocatorGeneric(uint32_t max_id) : max_id_(max_id) {
+ PERFETTO_DCHECK(max_id > 1);
+}
+
+IdAllocatorGeneric::~IdAllocatorGeneric() = default;
+
+uint32_t IdAllocatorGeneric::AllocateGeneric() {
+ for (uint32_t ignored = 1; ignored <= max_id_; ignored++) {
+ last_id_ = last_id_ < max_id_ ? last_id_ + 1 : 1;
+ const auto id = last_id_;
+
+ // 0 is never a valid ID. So if we are looking for |id| == N and there are
+ // N or less elements in the vector, they must necessarily be all < N.
+ // e.g. if |id| == 4 and size() == 4, the vector will contain IDs 0,1,2,3.
+ if (id >= ids_.size()) {
+ ids_.resize(id + 1);
+ ids_[id] = true;
+ return id;
+ }
+
+ if (!ids_[id]) {
+ ids_[id] = true;
+ return id;
+ }
+ }
+ return 0;
+}
+
+void IdAllocatorGeneric::FreeGeneric(uint32_t id) {
+ if (id == 0 || id >= ids_.size() || !ids_[id]) {
+ PERFETTO_DFATAL("Invalid id.");
+ return;
+ }
+ ids_[id] = false;
+}
+
+bool IdAllocatorGeneric::IsEmpty() const {
+ for (auto id : ids_) {
+ if (id)
+ return false;
+ }
+ return true;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/in_process_shared_memory.cc
+// gen_amalgamated begin header: src/tracing/core/in_process_shared_memory.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/shared_memory.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_H_
+
+#include <stddef.h>
+
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+
+namespace perfetto {
+
+// An abstract interface that models the shared memory region shared between
+// Service and Producer. The concrete implementation of this is up to the
+// transport layer. This can be as simple as a malloc()-ed buffer, if both
+// Producer and Service are hosted in the same process, or some posix shared
+// memory for the out-of-process case (see src/unix_rpc).
+// Both this class and the Factory are subclassed by the transport layer, which
+// will attach platform specific fields to it (e.g., a unix file descriptor).
+class PERFETTO_EXPORT_COMPONENT SharedMemory {
+ public:
+ class PERFETTO_EXPORT_COMPONENT Factory {
+ public:
+ virtual ~Factory();
+ virtual std::unique_ptr<SharedMemory> CreateSharedMemory(size_t) = 0;
+ };
+
+ // The transport layer is expected to tear down the resource associated to
+ // this object region when destroyed.
+ virtual ~SharedMemory();
+
+ virtual void* start() const = 0;
+ virtual size_t size() const = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_H_
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_CORE_IN_PROCESS_SHARED_MEMORY_H_
+#define SRC_TRACING_CORE_IN_PROCESS_SHARED_MEMORY_H_
+
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/paged_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+
+namespace perfetto {
+
+// An implementation of the ShareMemory interface that allocates memory that can
+// only be shared intra-process.
+class InProcessSharedMemory : public SharedMemory {
+ public:
+ static constexpr size_t kDefaultSize = 128 * 1024;
+
+ // Default ctor used for intra-process shmem between a producer and the
+ // service.
+ explicit InProcessSharedMemory(size_t size)
+ : mem_(base::PagedMemory::Allocate(size)) {}
+ ~InProcessSharedMemory() override;
+
+ static std::unique_ptr<InProcessSharedMemory> Create(
+ size_t size = kDefaultSize) {
+ return std::make_unique<InProcessSharedMemory>(size);
+ }
+
+ // SharedMemory implementation.
+ void* start() const override;
+ size_t size() const override;
+
+ class Factory : public SharedMemory::Factory {
+ public:
+ ~Factory() override;
+ std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override {
+ return InProcessSharedMemory::Create(size);
+ }
+ };
+
+ private:
+ base::PagedMemory mem_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_CORE_IN_PROCESS_SHARED_MEMORY_H_
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/core/in_process_shared_memory.h"
+
+namespace perfetto {
+
+InProcessSharedMemory::~InProcessSharedMemory() = default;
+InProcessSharedMemory::Factory::~Factory() = default;
+
+void* InProcessSharedMemory::start() const {
+ return mem_.Get();
+}
+size_t InProcessSharedMemory::size() const {
+ return mem_.size();
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/null_trace_writer.cc
+// gen_amalgamated begin header: src/tracing/core/null_trace_writer.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/trace_writer.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/basic_types.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_BASIC_TYPES_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_BASIC_TYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+
+namespace perfetto {
+
+// Unique within the scope of the tracing service.
+using TracingSessionID = uint64_t;
+
+// Unique within the scope of the tracing service.
+using ProducerID = uint16_t;
+
+// Unique within the scope of the tracing service.
+using DataSourceInstanceID = uint64_t;
+
+// Unique within the scope of a Producer.
+using WriterID = uint16_t;
+
+// Unique within the scope of the tracing service.
+using FlushRequestID = uint64_t;
+
+// Combines Producer and Writer ID in one word which can be used as key for
+// hashtables and other data structures.
+using ProducerAndWriterID = uint32_t;
+
+inline ProducerAndWriterID MkProducerAndWriterID(ProducerID p, WriterID w) {
+ static_assert(
+ sizeof(ProducerID) + sizeof(WriterID) == sizeof(ProducerAndWriterID),
+ "MkProducerAndWriterID() and GetProducerAndWriterID() need updating");
+ return (static_cast<ProducerAndWriterID>(p) << (sizeof(WriterID) * 8)) | w;
+}
+
+inline void GetProducerAndWriterID(ProducerAndWriterID x,
+ ProducerID* p,
+ WriterID* w) {
+ static constexpr auto mask = (1ull << (sizeof(WriterID) * 8)) - 1;
+ *w = static_cast<WriterID>(x & mask);
+ *p = static_cast<ProducerID>(x >> (sizeof(WriterID) * 8));
+}
+
+// We need one FD per producer and we are not going to be able to keep > 64k FDs
+// open in the service.
+static constexpr ProducerID kMaxProducerID = static_cast<ProducerID>(-1);
+
+// 1024 Writers per producer seems a resonable bound. This reduces the ability
+// to memory-DoS the service by having to keep track of too many writer IDs.
+static constexpr WriterID kMaxWriterID = static_cast<WriterID>((1 << 10) - 1);
+
+// Unique within the scope of a {ProducerID, WriterID} tuple.
+using ChunkID = uint32_t;
+static constexpr ChunkID kMaxChunkID = static_cast<ChunkID>(-1);
+
+// Unique within the scope of the tracing service.
+using BufferID = uint16_t;
+
+// Target buffer ID for SharedMemoryArbiter. Values up to max uint16_t are
+// equivalent to a bound BufferID. Values above max uint16_t are reservation IDs
+// for the target buffer of a startup trace writer. Reservation IDs will be
+// translated to actual BufferIDs after they are bound by
+// SharedMemoryArbiter::BindStartupTargetBuffer().
+// TODO(mohitms): Delete this type and use `struct {uint16 ; uint16;}` instead.
+using MaybeUnboundBufferID = uint32_t;
+
+// Keep this in sync with SharedMemoryABI::PageHeader::target_buffer.
+static constexpr BufferID kMaxTraceBufferID = static_cast<BufferID>(-1);
+
+// Unique within the scope of a tracing session.
+using PacketSequenceID = uint32_t;
+// Used for extra packets emitted by the service, such as statistics.
+static constexpr PacketSequenceID kServicePacketSequenceID = 1;
+static constexpr PacketSequenceID kMaxPacketSequenceID =
+ static_cast<PacketSequenceID>(-1);
+
+constexpr uint32_t kDefaultFlushTimeoutMs = 5000;
+
+// The special id 0xffff..ffff represents the tracing session with the highest
+// bugreport score. This is used for CloneSession(kBugreportSessionId).
+constexpr TracingSessionID kBugreportSessionId =
+ static_cast<TracingSessionID>(-1);
+
+// The ID of a machine in a multi-machine tracing session.
+using MachineID = base::MachineID;
+constexpr MachineID kDefaultMachineID = base::kDefaultMachineID;
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_BASIC_TYPES_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_WRITER_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_WRITER_H_
+
+#include <functional>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+
+namespace perfetto {
+
+namespace protos {
+namespace pbzero {
+class TracePacket;
+} // namespace pbzero
+} // namespace protos
+
+// See comments in include/perfetto/tracing/trace_writer_base.h
+class PERFETTO_EXPORT_COMPONENT TraceWriter : public TraceWriterBase {
+ public:
+ using TracePacketHandle =
+ protozero::MessageHandle<protos::pbzero::TracePacket>;
+
+ TraceWriter();
+ ~TraceWriter() override;
+
+ virtual WriterID writer_id() const = 0;
+
+ private:
+ TraceWriter(const TraceWriter&) = delete;
+ TraceWriter& operator=(const TraceWriter&) = delete;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_WRITER_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_CORE_NULL_TRACE_WRITER_H_
+#define SRC_TRACING_CORE_NULL_TRACE_WRITER_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/root_message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_null_delegate.h"
+
+namespace perfetto {
+
+// A specialization of TraceWriter which no-ops all the writes routing them
+// into a fixed region of memory
+// See //include/perfetto/ext/tracing/core/trace_writer.h for docs.
+class NullTraceWriter : public TraceWriter {
+ public:
+ NullTraceWriter();
+ ~NullTraceWriter() override;
+
+ // TraceWriter implementation. See documentation in trace_writer.h.
+ // TracePacketHandle is defined in trace_writer.h
+ TracePacketHandle NewTracePacket() override;
+ void FinishTracePacket() override;
+ void Flush(std::function<void()> callback = {}) override;
+ WriterID writer_id() const override;
+ uint64_t written() const override;
+
+ private:
+ NullTraceWriter(const NullTraceWriter&) = delete;
+ NullTraceWriter& operator=(const NullTraceWriter&) = delete;
+
+ protozero::ScatteredStreamWriterNullDelegate delegate_;
+ protozero::ScatteredStreamWriter stream_;
+
+ // The packet returned via NewTracePacket(). It is owned by this class,
+ // TracePacketHandle has just a pointer to it.
+ std::unique_ptr<protozero::RootMessage<protos::pbzero::TracePacket>>
+ cur_packet_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_CORE_NULL_TRACE_WRITER_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/core/null_trace_writer.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+
+NullTraceWriter::NullTraceWriter() : delegate_(4096), stream_(&delegate_) {
+ cur_packet_.reset(new protozero::RootMessage<protos::pbzero::TracePacket>());
+ cur_packet_->Finalize(); // To avoid the DCHECK in NewTracePacket().
+}
+
+NullTraceWriter::~NullTraceWriter() {}
+
+void NullTraceWriter::Flush(std::function<void()> callback) {
+ // Flush() cannot be called in the middle of a TracePacket.
+ PERFETTO_CHECK(cur_packet_->is_finalized());
+
+ if (callback)
+ callback();
+}
+
+NullTraceWriter::TracePacketHandle NullTraceWriter::NewTracePacket() {
+ // If we hit this, the caller is calling NewTracePacket() without having
+ // finalized the previous packet.
+ PERFETTO_DCHECK(cur_packet_->is_finalized());
+ cur_packet_->Reset(&stream_);
+ return TraceWriter::TracePacketHandle(cur_packet_.get());
+}
+
+void NullTraceWriter::FinishTracePacket() {
+ cur_packet_->Finalize();
+}
+
+WriterID NullTraceWriter::writer_id() const {
+ return 0;
+}
+
+uint64_t NullTraceWriter::written() const {
+ return 0;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/shared_memory_abi.cc
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/shared_memory_abi.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ABI_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ABI_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+#include <atomic>
+#include <bitset>
+#include <thread>
+#include <type_traits>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+
+// This file defines the binary interface of the memory buffers shared between
+// Producer and Service. This is a long-term stable ABI and has to be backwards
+// compatible to deal with mismatching Producer and Service versions.
+//
+// Overview
+// --------
+// SMB := "Shared Memory Buffer".
+// In the most typical case of a multi-process architecture (i.e. Producer and
+// Service are hosted by different processes), a Producer means almost always
+// a "client process producing data" (almost: in some cases a process might host
+// > 1 Producer, if it links two libraries, independent of each other, that both
+// use Perfetto tracing).
+// The Service has one SMB for each Producer.
+// A producer has one or (typically) more data sources. They all share the same
+// SMB.
+// The SMB is a staging area to decouple data sources living in the Producer
+// and allow them to do non-blocking async writes.
+// The SMB is *not* the ultimate logging buffer seen by the Consumer. That one
+// is larger (~MBs) and not shared with Producers.
+// Each SMB is small, typically few KB. Its size is configurable by the producer
+// within a max limit of ~MB (see kMaxShmSize in tracing_service_impl.cc).
+// The SMB is partitioned into fixed-size Page(s). The size of the Pages are
+// determined by each Producer at connection time and cannot be changed.
+// Hence, different producers can have SMB(s) that have a different Page size
+// from each other, but the page size will be constant throughout all the
+// lifetime of the SMB.
+// Page(s) are partitioned by the Producer into variable size Chunk(s):
+//
+// +------------+ +--------------------------+
+// | Producer 1 | <-> | SMB 1 [~32K - 1MB] |
+// +------------+ +--------+--------+--------+
+// | Page | Page | Page |
+// +--------+--------+--------+
+// | Chunk | | Chunk |
+// +--------+ Chunk +--------+ <----+
+// | Chunk | | Chunk | |
+// +--------+--------+--------+ +---------------------+
+// | Service |
+// +------------+ +--------------------------+ +---------------------+
+// | Producer 2 | <-> | SMB 2 [~32K - 1MB] | /| large ring buffers |
+// +------------+ +--------+--------+--------+ <--+ | (100K - several MB) |
+// | Page | Page | Page | +---------------------+
+// +--------+--------+--------+
+// | Chunk | | Chunk |
+// +--------+ Chunk +--------+
+// | Chunk | | Chunk |
+// +--------+--------+--------+
+//
+// * Sizes of both SMB and ring buffers are purely indicative and decided at
+// configuration time by the Producer (for SMB sizes) and the Consumer (for the
+// final ring buffer size).
+
+// Page
+// ----
+// A page is a portion of the shared memory buffer and defines the granularity
+// of the interaction between the Producer and tracing Service. When scanning
+// the shared memory buffer to determine if something should be moved to the
+// central logging buffers, the Service most of the times looks at and moves
+// whole pages. Similarly, the Producer sends an IPC to invite the Service to
+// drain the shared memory buffer only when a whole page is filled.
+// Having fixed the total SMB size (hence the total memory overhead), the page
+// size is a triangular tradeoff between:
+// 1) IPC traffic: smaller pages -> more IPCs.
+// 2) Producer lock freedom: larger pages -> larger chunks -> data sources can
+// write more data without needing to swap chunks and synchronize.
+// 3) Risk of write-starving the SMB: larger pages -> higher chance that the
+// Service won't manage to drain them and the SMB remains full.
+// The page size, on the other side, has no implications on wasted memory due to
+// fragmentations (see Chunk below).
+// The size of the page is chosen by the Service at connection time and stays
+// fixed throughout all the lifetime of the Producer. Different producers (i.e.
+// ~ different client processes) can use different page sizes.
+// The page size must be an integer multiple of 4k (this is to allow VM page
+// stealing optimizations) and obviously has to be an integer divisor of the
+// total SMB size.
+
+// Chunk
+// -----
+// A chunk is a portion of a Page which is written and handled by a Producer.
+// A chunk contains a linear sequence of TracePacket(s) (the root proto).
+// A chunk cannot be written concurrently by two data sources. Protobufs must be
+// encoded as contiguous byte streams and cannot be interleaved. Therefore, on
+// the Producer side, a chunk is almost always owned exclusively by one thread
+// (% extremely peculiar slow-path cases).
+// Chunks are essentially single-writer single-thread lock-free arenas. Locking
+// happens only when a Chunk is full and a new one needs to be acquired.
+// Locking happens only within the scope of a Producer process. There is no
+// inter-process locking. The Producer cannot lock the Service and viceversa.
+// In the worst case, any of the two can starve the SMB, by marking all chunks
+// as either being read or written. But that has the only side effect of
+// losing the trace data.
+// The Producer can decide to partition each page into a number of limited
+// configurations (e.g., 1 page == 1 chunk, 1 page == 2 chunks and so on).
+
+// TracePacket
+// -----------
+// Is the atom of tracing. Putting aside pages and chunks a trace is merely a
+// sequence of TracePacket(s). TracePacket is the root protobuf message.
+// A TracePacket can span across several chunks (hence even across several
+// pages). A TracePacket can therefore be >> chunk size, >> page size and even
+// >> SMB size. The Chunk header carries metadata to deal with the TracePacket
+// splitting case.
+
+// Use only explicitly-sized types below. DO NOT use size_t or any architecture
+// dependent size (e.g. size_t) in the struct fields. This buffer will be read
+// and written by processes that have a different bitness in the same OS.
+// Instead it's fine to assume little-endianess. Big-endian is a dream we are
+// not currently pursuing.
+
+class SharedMemoryABI {
+ public:
+ static constexpr size_t kMinPageSize = 4 * 1024;
+
+ // This is due to Chunk::size being 16 bits.
+ static constexpr size_t kMaxPageSize = 64 * 1024;
+
+ // "14" is the max number that can be encoded in a 32 bit atomic word using
+ // 2 state bits per Chunk and leaving 4 bits for the page layout.
+ // See PageLayout below.
+ static constexpr size_t kMaxChunksPerPage = 14;
+
+ // Each TracePacket fragment in the Chunk is prefixed by a VarInt stating its
+ // size that is up to 4 bytes long. Since the size is often known after the
+ // fragment has been filled, the VarInt is often redundantly encoded (see
+ // proto_utils.h) to be exactly 4 bytes.
+ static constexpr size_t kPacketHeaderSize = 4;
+
+ // TraceWriter specifies this invalid packet/fragment size to signal to the
+ // service that a packet should be discarded, because the TraceWriter couldn't
+ // write its remaining fragments (e.g. because the SMB was exhausted).
+ static constexpr size_t kPacketSizeDropPacket =
+ protozero::proto_utils::kMaxMessageLength;
+
+ // Chunk states and transitions:
+ // kChunkFree <----------------+
+ // | (Producer) |
+ // V |
+ // kChunkBeingWritten |
+ // | (Producer) |
+ // V |
+ // kChunkComplete |
+ // | (Service) |
+ // V |
+ // kChunkBeingRead |
+ // | (Service) |
+ // +------------------------+
+ //
+ // The ABI has an "emulation mode" for transports where shared memory isn't
+ // supported. In this mode, kChunkBeingRead is skipped. A chunk in the
+ // kChunkComplete state is released as free after the producer serializes
+ // chunk content to the protobuf message.
+ enum ChunkState : uint32_t {
+ // The Chunk is free. The Service shall never touch it, the Producer can
+ // acquire it and transition it into kChunkBeingWritten.
+ kChunkFree = 0,
+
+ // The Chunk is being used by the Producer and is not complete yet.
+ // The Service shall never touch kChunkBeingWritten pages.
+ kChunkBeingWritten = 1,
+
+ // The Service is moving the page into its non-shared ring buffer. The
+ // Producer shall never touch kChunkBeingRead pages.
+ kChunkBeingRead = 2,
+
+ // The Producer is done writing the page and won't touch it again. The
+ // Service can now move it to its non-shared ring buffer.
+ // kAllChunksComplete relies on this being == 3.
+ kChunkComplete = 3,
+ };
+ static constexpr const char* kChunkStateStr[] = {"Free", "BeingWritten",
+ "BeingRead", "Complete"};
+
+ enum PageLayout : uint32_t {
+ // The page is fully free and has not been partitioned yet.
+ kPageNotPartitioned = 0,
+
+ // TODO(primiano): Aligning a chunk @ 16 bytes could allow to use faster
+ // intrinsics based on quad-word moves. Do the math and check what is the
+ // fragmentation loss.
+
+ // align4(X) := the largest integer N s.t. (N % 4) == 0 && N <= X.
+ // 8 == sizeof(PageHeader).
+ kPageDiv1 = 1, // Only one chunk of size: PAGE_SIZE - 8.
+ kPageDiv2 = 2, // Two chunks of size: align4((PAGE_SIZE - 8) / 2).
+ kPageDiv4 = 3, // Four chunks of size: align4((PAGE_SIZE - 8) / 4).
+ kPageDiv7 = 4, // Seven chunks of size: align4((PAGE_SIZE - 8) / 7).
+ kPageDiv14 = 5, // Fourteen chunks of size: align4((PAGE_SIZE - 8) / 14).
+
+ // The rationale for 7 and 14 above is to maximize the page usage for the
+ // likely case of |page_size| == 4096:
+ // (((4096 - 8) / 14) % 4) == 0, while (((4096 - 8) / 16 % 4)) == 3. So
+ // Div16 would waste 3 * 16 = 48 bytes per page for chunk alignment gaps.
+
+ kPageDivReserved1 = 6,
+ kPageDivReserved2 = 7,
+ kNumPageLayouts = 8,
+ };
+
+ // Keep this consistent with the PageLayout enum above.
+ static constexpr uint32_t kNumChunksForLayout[] = {0, 1, 2, 4, 7, 14, 0, 0};
+
+ enum class ShmemMode {
+ // The default mode, where the shared buffer is visible to both the producer
+ // and the service.
+ kDefault,
+
+ // The emulation mode, used for producer ports without shared memory. The
+ // state transitions are all done in the producer process.
+ kShmemEmulation,
+ };
+
+ // Layout of a Page.
+ // +===================================================+
+ // | Page header [8 bytes] |
+ // | Tells how many chunks there are, how big they are |
+ // | and their state (free, read, write, complete). |
+ // +===================================================+
+ // +***************************************************+
+ // | Chunk #0 header [8 bytes] |
+ // | Tells how many packets there are and whether the |
+ // | whether the 1st and last ones are fragmented. |
+ // | Also has a chunk id to reassemble fragments. |
+ // +***************************************************+
+ // +---------------------------------------------------+
+ // | Packet #0 size [varint, up to 4 bytes] |
+ // + - - - - - - - - - - - - - - - - - - - - - - - - - +
+ // | Packet #0 payload |
+ // | A TracePacket protobuf message |
+ // +---------------------------------------------------+
+ // ...
+ // + . . . . . . . . . . . . . . . . . . . . . . . . . +
+ // | Optional padding to maintain aligment |
+ // + . . . . . . . . . . . . . . . . . . . . . . . . . +
+ // +---------------------------------------------------+
+ // | Packet #N size [varint, up to 4 bytes] |
+ // + - - - - - - - - - - - - - - - - - - - - - - - - - +
+ // | Packet #N payload |
+ // | A TracePacket protobuf message |
+ // +---------------------------------------------------+
+ // ...
+ // +***************************************************+
+ // | Chunk #M header [8 bytes] |
+ // ...
+
+ // Alignment applies to start offset only. The Chunk size is *not* aligned.
+ static constexpr uint32_t kChunkAlignment = 4;
+ static constexpr uint32_t kChunkShift = 2;
+ static constexpr uint32_t kChunkMask = 0x3;
+ static constexpr uint32_t kLayoutMask = 0x70000000;
+ static constexpr uint32_t kLayoutShift = 28;
+ static constexpr uint32_t kAllChunksMask = 0x0FFFFFFF;
+
+ // This assumes that kChunkComplete == 3.
+ static constexpr uint32_t kAllChunksComplete = 0x0FFFFFFF;
+ static constexpr uint32_t kAllChunksFree = 0;
+ static constexpr size_t kInvalidPageIdx = static_cast<size_t>(-1);
+
+ // There is one page header per page, at the beginning of the page.
+ struct PageHeader {
+ // |layout| bits:
+ // [31] [30:28] [27:26] ... [1:0]
+ // | | | | |
+ // | | | | +---------- ChunkState[0]
+ // | | | +--------------- ChunkState[12..1]
+ // | | +--------------------- ChunkState[13]
+ // | +----------------------------- PageLayout (0 == page fully free)
+ // +------------------------------------ Reserved for future use
+ std::atomic<uint32_t> layout;
+
+ // If we'll ever going to use this in the future it might come handy
+ // reviving the kPageBeingPartitioned logic (look in git log, it was there
+ // at some point in the past).
+ uint32_t reserved;
+ };
+
+ // There is one Chunk header per chunk (hence PageLayout per page) at the
+ // beginning of each chunk.
+ struct ChunkHeader {
+ enum Flags : uint8_t {
+ // If set, the first TracePacket in the chunk is partial and continues
+ // from |chunk_id| - 1 (within the same |writer_id|).
+ kFirstPacketContinuesFromPrevChunk = 1 << 0,
+
+ // If set, the last TracePacket in the chunk is partial and continues on
+ // |chunk_id| + 1 (within the same |writer_id|).
+ kLastPacketContinuesOnNextChunk = 1 << 1,
+
+ // If set, the last (fragmented) TracePacket in the chunk has holes (even
+ // if the chunk is marked as kChunkComplete) that need to be patched
+ // out-of-band before the chunk can be read.
+ kChunkNeedsPatching = 1 << 2,
+ };
+
+ struct Packets {
+ // Number of valid TracePacket protobuf messages contained in the chunk.
+ // Each TracePacket is prefixed by its own size. This field is
+ // monotonically updated by the Producer with release store semantic when
+ // the packet at position |count| is started. This last packet may not be
+ // considered complete until |count| is incremented for the subsequent
+ // packet or the chunk is completed.
+ uint16_t count : 10;
+ static constexpr size_t kMaxCount = (1 << 10) - 1;
+
+ // See Flags above.
+ uint16_t flags : 6;
+ };
+
+ // A monotonic counter of the chunk within the scoped of a |writer_id|.
+ // The tuple (ProducerID, WriterID, ChunkID) allows to figure out if two
+ // chunks are contiguous (and hence a trace packets spanning across them can
+ // be glued) or we had some holes due to the ring buffer wrapping.
+ // This is set only when transitioning from kChunkFree to kChunkBeingWritten
+ // and remains unchanged throughout the remaining lifetime of the chunk.
+ std::atomic<uint32_t> chunk_id;
+
+ // ID of the writer, unique within the producer.
+ // Like |chunk_id|, this is set only when transitioning from kChunkFree to
+ // kChunkBeingWritten.
+ std::atomic<uint16_t> writer_id;
+
+ // There is no ProducerID here. The service figures that out from the IPC
+ // channel, which is unspoofable.
+
+ // Updated with release-store semantics.
+ std::atomic<Packets> packets;
+ };
+
+ class Chunk {
+ public:
+ Chunk(); // Constructs an invalid chunk.
+
+ // Chunk is move-only, to document the scope of the Acquire/Release
+ // TryLock operations below.
+ Chunk(const Chunk&) = delete;
+ Chunk operator=(const Chunk&) = delete;
+ Chunk(Chunk&&) noexcept;
+ Chunk& operator=(Chunk&&);
+
+ uint8_t* begin() const { return begin_; }
+ uint8_t* end() const { return begin_ + size_; }
+
+ // Size, including Chunk header.
+ size_t size() const { return size_; }
+
+ // Begin of the first packet (or packet fragment).
+ uint8_t* payload_begin() const { return begin_ + sizeof(ChunkHeader); }
+ size_t payload_size() const {
+ PERFETTO_DCHECK(size_ >= sizeof(ChunkHeader));
+ return size_ - sizeof(ChunkHeader);
+ }
+
+ bool is_valid() const { return begin_ && size_; }
+
+ // Index of the chunk within the page [0..13] (13 comes from kPageDiv14).
+ uint8_t chunk_idx() const { return chunk_idx_; }
+
+ ChunkHeader* header() { return reinterpret_cast<ChunkHeader*>(begin_); }
+
+ uint16_t writer_id() {
+ return header()->writer_id.load(std::memory_order_relaxed);
+ }
+
+ // Returns the count of packets and the flags with acquire-load semantics.
+ std::pair<uint16_t, uint8_t> GetPacketCountAndFlags() {
+ auto packets = header()->packets.load(std::memory_order_acquire);
+ const uint16_t packets_count = packets.count;
+ const uint8_t packets_flags = packets.flags;
+ return std::make_pair(packets_count, packets_flags);
+ }
+
+ // Increases |packets.count| with release semantics (note, however, that the
+ // packet count is incremented *before* starting writing a packet). Returns
+ // the new packet count. The increment is atomic but NOT race-free (i.e. no
+ // CAS). Only the Producer is supposed to perform this increment, and it's
+ // supposed to do that in a thread-safe way (holding a lock). A Chunk cannot
+ // be shared by multiple Producer threads without locking. The packet count
+ // is cleared by TryAcquireChunk(), when passing the new header for the
+ // chunk.
+ uint16_t IncrementPacketCount() {
+ ChunkHeader* chunk_header = header();
+ auto packets = chunk_header->packets.load(std::memory_order_relaxed);
+ packets.count++;
+ chunk_header->packets.store(packets, std::memory_order_release);
+ return packets.count;
+ }
+
+ // Flags are cleared by TryAcquireChunk(), by passing the new header for
+ // the chunk, or through ClearNeedsPatchingFlag.
+ void SetFlag(ChunkHeader::Flags flag) {
+ ChunkHeader* chunk_header = header();
+ auto packets = chunk_header->packets.load(std::memory_order_relaxed);
+ packets.flags |= flag;
+ chunk_header->packets.store(packets, std::memory_order_release);
+ }
+
+ // This flag can only be cleared by the producer while it is still holding
+ // on to the chunk - i.e. while the chunk is still in state
+ // ChunkState::kChunkBeingWritten and hasn't been transitioned to
+ // ChunkState::kChunkComplete. This is ok, because the service is oblivious
+ // to the needs patching flag before the chunk is released as complete.
+ void ClearNeedsPatchingFlag() {
+ ChunkHeader* chunk_header = header();
+ auto packets = chunk_header->packets.load(std::memory_order_relaxed);
+ packets.flags &= ~ChunkHeader::kChunkNeedsPatching;
+ chunk_header->packets.store(packets, std::memory_order_release);
+ }
+
+ private:
+ friend class SharedMemoryABI;
+ Chunk(uint8_t* begin, uint16_t size, uint8_t chunk_idx);
+
+ // Don't add extra fields, keep the move operator fast.
+ uint8_t* begin_ = nullptr;
+ uint16_t size_ = 0;
+ uint8_t chunk_idx_ = 0;
+
+ public:
+ static constexpr size_t kMaxSize = 1ULL << sizeof(size_) * 8;
+ };
+
+ // Construct an instance from an existing shared memory buffer.
+ SharedMemoryABI(uint8_t* start,
+ size_t size,
+ size_t page_size,
+ ShmemMode mode);
+ SharedMemoryABI();
+
+ void Initialize(uint8_t* start,
+ size_t size,
+ size_t page_size,
+ ShmemMode mode);
+
+ uint8_t* start() const { return start_; }
+ uint8_t* end() const { return start_ + size_; }
+ size_t size() const { return size_; }
+ size_t page_size() const { return page_size_; }
+ size_t num_pages() const { return num_pages_; }
+ bool is_valid() { return num_pages() > 0; }
+
+ uint8_t* page_start(size_t page_idx) {
+ PERFETTO_DCHECK(page_idx < num_pages_);
+ return start_ + page_size_ * page_idx;
+ }
+
+ PageHeader* page_header(size_t page_idx) {
+ return reinterpret_cast<PageHeader*>(page_start(page_idx));
+ }
+
+ // Returns true if the page is fully clear and has not been partitioned yet.
+ // The state of the page can change at any point after this returns (or even
+ // before). The Producer should use this only as a hint to decide out whether
+ // it should TryPartitionPage() or acquire an individual chunk.
+ bool is_page_free(size_t page_idx) {
+ return page_header(page_idx)->layout.load(std::memory_order_relaxed) == 0;
+ }
+
+ // Returns true if all chunks in the page are kChunkComplete. As above, this
+ // is advisory only. The Service is supposed to use this only to decide
+ // whether to TryAcquireAllChunksForReading() or not.
+ bool is_page_complete(size_t page_idx) {
+ auto layout = page_header(page_idx)->layout.load(std::memory_order_relaxed);
+ const uint32_t num_chunks = GetNumChunksForLayout(layout);
+ if (num_chunks == 0)
+ return false; // Non partitioned pages cannot be complete.
+ return (layout & kAllChunksMask) ==
+ (kAllChunksComplete & ((1 << (num_chunks * kChunkShift)) - 1));
+ }
+
+ // For testing / debugging only.
+ std::string page_header_dbg(size_t page_idx) {
+ uint32_t x = page_header(page_idx)->layout.load(std::memory_order_relaxed);
+ return std::bitset<32>(x).to_string();
+ }
+
+ // Returns the page layout, which is a bitmap that specifies the chunking
+ // layout of the page and each chunk's current state. Reads with an
+ // acquire-load semantic to ensure a producer's writes corresponding to an
+ // update of the layout (e.g. clearing a chunk's header) are observed
+ // consistently.
+ uint32_t GetPageLayout(size_t page_idx) {
+ return page_header(page_idx)->layout.load(std::memory_order_acquire);
+ }
+
+ // Returns a bitmap in which each bit is set if the corresponding Chunk exists
+ // in the page (according to the page layout) and is free. If the page is not
+ // partitioned it returns 0 (as if the page had no free chunks).
+ uint32_t GetFreeChunks(size_t page_idx);
+
+ // Tries to atomically partition a page with the given |layout|. Returns true
+ // if the page was free and has been partitioned with the given |layout|,
+ // false if the page wasn't free anymore by the time we got there.
+ // If succeeds all the chunks are atomically set in the kChunkFree state.
+ bool TryPartitionPage(size_t page_idx, PageLayout layout);
+
+ // Tries to atomically mark a single chunk within the page as
+ // kChunkBeingWritten. Returns an invalid chunk if the page is not partitioned
+ // or the chunk is not in the kChunkFree state. If succeeds sets the chunk
+ // header to |header|.
+ Chunk TryAcquireChunkForWriting(size_t page_idx,
+ size_t chunk_idx,
+ const ChunkHeader* header) {
+ return TryAcquireChunk(page_idx, chunk_idx, kChunkBeingWritten, header);
+ }
+
+ // Similar to TryAcquireChunkForWriting. Fails if the chunk isn't in the
+ // kChunkComplete state.
+ Chunk TryAcquireChunkForReading(size_t page_idx, size_t chunk_idx) {
+ return TryAcquireChunk(page_idx, chunk_idx, kChunkBeingRead, nullptr);
+ }
+
+ // The caller must have successfully TryAcquireAllChunksForReading() or it
+ // needs to guarantee that the chunk is already in the kChunkBeingWritten
+ // state.
+ Chunk GetChunkUnchecked(size_t page_idx,
+ uint32_t page_layout,
+ size_t chunk_idx);
+
+ // Creates a Chunk by adopting the given buffer (|data| and |size|) and chunk
+ // index. This is used for chunk data passed over the wire (e.g. tcp or
+ // vsock). The chunk should *not* be freed to the shared memory.
+ static Chunk MakeChunkFromSerializedData(uint8_t* data,
+ uint16_t size,
+ uint8_t chunk_idx) {
+ return Chunk(data, size, chunk_idx);
+ }
+
+ // Puts a chunk into the kChunkComplete state. Returns the page index.
+ size_t ReleaseChunkAsComplete(Chunk chunk) {
+ return ReleaseChunk(std::move(chunk), kChunkComplete);
+ }
+
+ // Puts a chunk into the kChunkFree state. Returns the page index.
+ size_t ReleaseChunkAsFree(Chunk chunk) {
+ return ReleaseChunk(std::move(chunk), kChunkFree);
+ }
+
+ ChunkState GetChunkState(size_t page_idx, size_t chunk_idx) {
+ PageHeader* phdr = page_header(page_idx);
+ uint32_t layout = phdr->layout.load(std::memory_order_relaxed);
+ return GetChunkStateFromLayout(layout, chunk_idx);
+ }
+
+ std::pair<size_t, size_t> GetPageAndChunkIndex(const Chunk& chunk);
+
+ uint16_t GetChunkSizeForLayout(uint32_t page_layout) const {
+ return chunk_sizes_[(page_layout & kLayoutMask) >> kLayoutShift];
+ }
+
+ static ChunkState GetChunkStateFromLayout(uint32_t page_layout,
+ size_t chunk_idx) {
+ return static_cast<ChunkState>((page_layout >> (chunk_idx * kChunkShift)) &
+ kChunkMask);
+ }
+
+ static constexpr uint32_t GetNumChunksForLayout(uint32_t page_layout) {
+ return kNumChunksForLayout[(page_layout & kLayoutMask) >> kLayoutShift];
+ }
+
+ // Returns a bitmap in which each bit is set if the corresponding Chunk exists
+ // in the page (according to the page layout) and is not free. If the page is
+ // not partitioned it returns 0 (as if the page had no used chunks). Bit N
+ // corresponds to Chunk N.
+ static uint32_t GetUsedChunks(uint32_t page_layout) {
+ const uint32_t num_chunks = GetNumChunksForLayout(page_layout);
+ uint32_t res = 0;
+ for (uint32_t i = 0; i < num_chunks; i++) {
+ res |= ((page_layout & kChunkMask) != kChunkFree) ? (1 << i) : 0;
+ page_layout >>= kChunkShift;
+ }
+ return res;
+ }
+
+ private:
+ SharedMemoryABI(const SharedMemoryABI&) = delete;
+ SharedMemoryABI& operator=(const SharedMemoryABI&) = delete;
+
+ Chunk TryAcquireChunk(size_t page_idx,
+ size_t chunk_idx,
+ ChunkState,
+ const ChunkHeader*);
+ size_t ReleaseChunk(Chunk chunk, ChunkState);
+
+ uint8_t* start_ = nullptr;
+ size_t size_ = 0;
+ size_t page_size_ = 0;
+ bool use_shmem_emulation_ = false;
+ size_t num_pages_ = 0;
+ std::array<uint16_t, kNumPageLayouts> chunk_sizes_;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ABI_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <sys/mman.h>
+#endif
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+
+namespace perfetto {
+
+namespace {
+
+constexpr int kRetryAttempts = 64;
+
+inline void WaitBeforeNextAttempt(int attempt) {
+ if (attempt < kRetryAttempts / 2) {
+ std::this_thread::yield();
+ } else {
+ base::SleepMicroseconds((unsigned(attempt) / 10) * 1000);
+ }
+}
+
+// Returns the largest 4-bytes aligned chunk size <= |page_size| / |divider|
+// for each divider in PageLayout.
+constexpr size_t GetChunkSize(size_t page_size, size_t divider) {
+ return ((page_size - sizeof(SharedMemoryABI::PageHeader)) / divider) & ~3UL;
+}
+
+// Initializer for the const |chunk_sizes_| array.
+std::array<uint16_t, SharedMemoryABI::kNumPageLayouts> InitChunkSizes(
+ size_t page_size) {
+ static_assert(SharedMemoryABI::kNumPageLayouts ==
+ base::ArraySize(SharedMemoryABI::kNumChunksForLayout),
+ "kNumPageLayouts out of date");
+ std::array<uint16_t, SharedMemoryABI::kNumPageLayouts> res = {};
+ for (size_t i = 0; i < SharedMemoryABI::kNumPageLayouts; i++) {
+ size_t num_chunks = SharedMemoryABI::kNumChunksForLayout[i];
+ size_t size = num_chunks == 0 ? 0 : GetChunkSize(page_size, num_chunks);
+ PERFETTO_CHECK(size <= std::numeric_limits<uint16_t>::max());
+ res[i] = static_cast<uint16_t>(size);
+ }
+ return res;
+}
+
+inline void ClearChunkHeader(SharedMemoryABI::ChunkHeader* header) {
+ header->writer_id.store(0u, std::memory_order_relaxed);
+ header->chunk_id.store(0u, std::memory_order_relaxed);
+ header->packets.store({}, std::memory_order_release);
+}
+
+} // namespace
+
+SharedMemoryABI::SharedMemoryABI() = default;
+
+SharedMemoryABI::SharedMemoryABI(uint8_t* start,
+ size_t size,
+ size_t page_size,
+ ShmemMode mode) {
+ Initialize(start, size, page_size, mode);
+}
+
+void SharedMemoryABI::Initialize(uint8_t* start,
+ size_t size,
+ size_t page_size,
+ ShmemMode mode) {
+ start_ = start;
+ size_ = size;
+ page_size_ = page_size;
+ use_shmem_emulation_ = mode == ShmemMode::kShmemEmulation;
+ num_pages_ = size / page_size;
+ chunk_sizes_ = InitChunkSizes(page_size);
+ static_assert(sizeof(PageHeader) == 8, "PageHeader size");
+ static_assert(sizeof(ChunkHeader) == 8, "ChunkHeader size");
+ static_assert(sizeof(ChunkHeader::chunk_id) == sizeof(ChunkID),
+ "ChunkID size");
+
+ static_assert(sizeof(ChunkHeader::Packets) == 2, "ChunkHeader::Packets size");
+ static_assert(alignof(ChunkHeader) == kChunkAlignment,
+ "ChunkHeader alignment");
+
+ // In theory std::atomic does not guarantee that the underlying type
+ // consists only of the actual atomic word. Theoretically it could have
+ // locks or other state. In practice most implementations just implement
+ // them without extra state. The code below overlays the atomic into the
+ // SMB, hence relies on this implementation detail. This should be fine
+ // pragmatically (Chrome's base makes the same assumption), but let's have a
+ // check for this.
+ static_assert(sizeof(std::atomic<uint32_t>) == sizeof(uint32_t) &&
+ sizeof(std::atomic<uint16_t>) == sizeof(uint16_t),
+ "Incompatible STL <atomic> implementation");
+
+ // Chec that the kAllChunks(Complete,Free) are consistent with the
+ // ChunkState enum values.
+
+ // These must be zero because rely on zero-initialized memory being
+ // interpreted as "free".
+ static_assert(kChunkFree == 0 && kAllChunksFree == 0,
+ "kChunkFree/kAllChunksFree and must be 0");
+
+ static_assert((kAllChunksComplete & kChunkMask) == kChunkComplete,
+ "kAllChunksComplete out of sync with kChunkComplete");
+
+ // Check the consistency of the kMax... constants.
+ static_assert(sizeof(ChunkHeader::writer_id) == sizeof(WriterID),
+ "WriterID size");
+ ChunkHeader chunk_header{};
+ chunk_header.chunk_id.store(static_cast<uint32_t>(-1));
+ PERFETTO_CHECK(chunk_header.chunk_id.load() == kMaxChunkID);
+
+ chunk_header.writer_id.store(static_cast<uint16_t>(-1));
+ PERFETTO_CHECK(kMaxWriterID <= chunk_header.writer_id.load());
+
+ PERFETTO_CHECK(page_size >= kMinPageSize);
+ PERFETTO_CHECK(page_size <= kMaxPageSize);
+ PERFETTO_CHECK(page_size % kMinPageSize == 0);
+ PERFETTO_CHECK(reinterpret_cast<uintptr_t>(start) % kMinPageSize == 0);
+ PERFETTO_CHECK(size % page_size == 0);
+}
+
+SharedMemoryABI::Chunk SharedMemoryABI::GetChunkUnchecked(size_t page_idx,
+ uint32_t page_layout,
+ size_t chunk_idx) {
+ const size_t num_chunks = GetNumChunksForLayout(page_layout);
+ PERFETTO_DCHECK(chunk_idx < num_chunks);
+ // Compute the chunk virtual address and write it into |chunk|.
+ const uint16_t chunk_size = GetChunkSizeForLayout(page_layout);
+ size_t chunk_offset_in_page = sizeof(PageHeader) + chunk_idx * chunk_size;
+
+ Chunk chunk(page_start(page_idx) + chunk_offset_in_page, chunk_size,
+ static_cast<uint8_t>(chunk_idx));
+ PERFETTO_DCHECK(chunk.end() <= end());
+ return chunk;
+}
+
+SharedMemoryABI::Chunk SharedMemoryABI::TryAcquireChunk(
+ size_t page_idx,
+ size_t chunk_idx,
+ ChunkState desired_chunk_state,
+ const ChunkHeader* header) {
+ PERFETTO_DCHECK(desired_chunk_state == kChunkBeingRead ||
+ desired_chunk_state == kChunkBeingWritten);
+ PageHeader* phdr = page_header(page_idx);
+ for (int attempt = 0; attempt < kRetryAttempts; attempt++) {
+ uint32_t layout = phdr->layout.load(std::memory_order_acquire);
+ const size_t num_chunks = GetNumChunksForLayout(layout);
+
+ // The page layout has changed (or the page is free).
+ if (chunk_idx >= num_chunks)
+ return Chunk();
+
+ // Verify that the chunk is still in a state that allows the transition to
+ // |desired_chunk_state|. The only allowed transitions are:
+ // 1. kChunkFree -> kChunkBeingWritten (Producer).
+ // 2. kChunkComplete -> kChunkBeingRead (Service).
+ ChunkState expected_chunk_state =
+ desired_chunk_state == kChunkBeingWritten ? kChunkFree : kChunkComplete;
+ auto cur_chunk_state = (layout >> (chunk_idx * kChunkShift)) & kChunkMask;
+ if (cur_chunk_state != expected_chunk_state)
+ return Chunk();
+
+ uint32_t next_layout = layout;
+ next_layout &= ~(kChunkMask << (chunk_idx * kChunkShift));
+ next_layout |= (desired_chunk_state << (chunk_idx * kChunkShift));
+ if (phdr->layout.compare_exchange_strong(layout, next_layout,
+ std::memory_order_acq_rel)) {
+ // Compute the chunk virtual address and write it into |chunk|.
+ Chunk chunk = GetChunkUnchecked(page_idx, layout, chunk_idx);
+ if (desired_chunk_state == kChunkBeingWritten) {
+ PERFETTO_DCHECK(header);
+ ChunkHeader* new_header = chunk.header();
+ new_header->writer_id.store(header->writer_id,
+ std::memory_order_relaxed);
+ new_header->chunk_id.store(header->chunk_id, std::memory_order_relaxed);
+ new_header->packets.store(header->packets, std::memory_order_release);
+ }
+ return chunk;
+ }
+ WaitBeforeNextAttempt(attempt);
+ }
+ return Chunk(); // All our attempts failed.
+}
+
+bool SharedMemoryABI::TryPartitionPage(size_t page_idx, PageLayout layout) {
+ PERFETTO_DCHECK(layout >= kPageDiv1 && layout <= kPageDiv14);
+ uint32_t expected_layout = 0; // Free page.
+ uint32_t next_layout = (layout << kLayoutShift) & kLayoutMask;
+ PageHeader* phdr = page_header(page_idx);
+ if (!phdr->layout.compare_exchange_strong(expected_layout, next_layout,
+ std::memory_order_acq_rel)) {
+ return false;
+ }
+ return true;
+}
+
+uint32_t SharedMemoryABI::GetFreeChunks(size_t page_idx) {
+ uint32_t layout =
+ page_header(page_idx)->layout.load(std::memory_order_relaxed);
+ const uint32_t num_chunks = GetNumChunksForLayout(layout);
+ uint32_t res = 0;
+ for (uint32_t i = 0; i < num_chunks; i++) {
+ res |= ((layout & kChunkMask) == kChunkFree) ? (1 << i) : 0;
+ layout >>= kChunkShift;
+ }
+ return res;
+}
+
+size_t SharedMemoryABI::ReleaseChunk(Chunk chunk,
+ ChunkState desired_chunk_state) {
+ PERFETTO_DCHECK(desired_chunk_state == kChunkComplete ||
+ desired_chunk_state == kChunkFree);
+
+ size_t page_idx;
+ size_t chunk_idx;
+ std::tie(page_idx, chunk_idx) = GetPageAndChunkIndex(chunk);
+
+ // Reset header fields, so that the service can identify when the chunk's
+ // header has been initialized by the producer.
+ if (desired_chunk_state == kChunkFree)
+ ClearChunkHeader(chunk.header());
+
+ for (int attempt = 0; attempt < kRetryAttempts; attempt++) {
+ PageHeader* phdr = page_header(page_idx);
+ uint32_t layout = phdr->layout.load(std::memory_order_relaxed);
+ const size_t page_chunk_size = GetChunkSizeForLayout(layout);
+
+ // TODO(primiano): this should not be a CHECK, because a malicious producer
+ // could crash us by putting the chunk in an invalid state. This should
+ // gracefully fail. Keep a CHECK until then.
+ PERFETTO_CHECK(chunk.size() == page_chunk_size);
+ const uint32_t chunk_state = GetChunkStateFromLayout(layout, chunk_idx);
+
+ // Verify that the chunk is still in a state that allows the transition to
+ // |desired_chunk_state|. The only allowed transitions are:
+ // 1. kChunkBeingWritten -> kChunkComplete (Producer).
+ // 2. kChunkBeingRead -> kChunkFree (Service).
+ // Or in the emulation mode, the allowed transitions are:
+ // 1. kChunkBeingWritten -> kChunkComplete (Producer).
+ // 2. kChunkComplete -> kChunkFree (Producer).
+ ChunkState expected_chunk_state;
+ if (desired_chunk_state == kChunkComplete) {
+ expected_chunk_state = kChunkBeingWritten;
+ } else {
+ expected_chunk_state =
+ use_shmem_emulation_ ? kChunkComplete : kChunkBeingRead;
+ }
+
+ // TODO(primiano): should not be a CHECK (same rationale of comment above).
+ PERFETTO_CHECK(chunk_state == expected_chunk_state);
+ uint32_t next_layout = layout;
+ next_layout &= ~(kChunkMask << (chunk_idx * kChunkShift));
+ next_layout |= (desired_chunk_state << (chunk_idx * kChunkShift));
+
+ // If we are freeing a chunk and all the other chunks in the page are free
+ // we should de-partition the page and mark it as clear.
+ if ((next_layout & kAllChunksMask) == kAllChunksFree)
+ next_layout = 0;
+
+ if (phdr->layout.compare_exchange_strong(layout, next_layout,
+ std::memory_order_acq_rel)) {
+ return page_idx;
+ }
+ WaitBeforeNextAttempt(attempt);
+ }
+ // Too much contention on this page. Give up. This page will be left pending
+ // forever but there isn't much more we can do at this point.
+ PERFETTO_DFATAL("Too much contention on page.");
+ return kInvalidPageIdx;
+}
+
+SharedMemoryABI::Chunk::Chunk() = default;
+
+SharedMemoryABI::Chunk::Chunk(uint8_t* begin, uint16_t size, uint8_t chunk_idx)
+ : begin_(begin), size_(size), chunk_idx_(chunk_idx) {
+ PERFETTO_CHECK(reinterpret_cast<uintptr_t>(begin) % kChunkAlignment == 0);
+ PERFETTO_CHECK(size > 0);
+}
+
+SharedMemoryABI::Chunk::Chunk(Chunk&& o) noexcept {
+ *this = std::move(o);
+}
+
+SharedMemoryABI::Chunk& SharedMemoryABI::Chunk::operator=(Chunk&& o) {
+ begin_ = o.begin_;
+ size_ = o.size_;
+ chunk_idx_ = o.chunk_idx_;
+ o.begin_ = nullptr;
+ o.size_ = 0;
+ o.chunk_idx_ = 0;
+ return *this;
+}
+
+std::pair<size_t, size_t> SharedMemoryABI::GetPageAndChunkIndex(
+ const Chunk& chunk) {
+ PERFETTO_DCHECK(chunk.is_valid());
+ PERFETTO_DCHECK(chunk.begin() >= start_);
+ PERFETTO_DCHECK(chunk.end() <= start_ + size_);
+
+ // TODO(primiano): The divisions below could be avoided if we cached
+ // |page_shift_|.
+ const uintptr_t rel_addr = static_cast<uintptr_t>(chunk.begin() - start_);
+ const size_t page_idx = rel_addr / page_size_;
+ const size_t offset = rel_addr % page_size_;
+ PERFETTO_DCHECK(offset >= sizeof(PageHeader));
+ PERFETTO_DCHECK(offset % kChunkAlignment == 0);
+ PERFETTO_DCHECK((offset - sizeof(PageHeader)) % chunk.size() == 0);
+ const size_t chunk_idx = (offset - sizeof(PageHeader)) / chunk.size();
+ PERFETTO_DCHECK(chunk_idx < kMaxChunksPerPage);
+ PERFETTO_DCHECK(chunk_idx < GetNumChunksForLayout(GetPageLayout(page_idx)));
+ return std::make_pair(page_idx, chunk_idx);
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/shared_memory_arbiter_impl.cc
+// gen_amalgamated begin header: src/tracing/core/shared_memory_arbiter_impl.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/shared_memory_arbiter.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/tracing_service.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/trace_packet.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/slice.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICE_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICE_H_
+
+#include <stddef.h>
+#include <string.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+
+// A simple wrapper around a virtually contiguous memory range that contains a
+// TracePacket, or just a portion of it.
+struct Slice {
+ Slice() : start(nullptr), size(0) {}
+ Slice(const void* st, size_t sz) : start(st), size(sz) {}
+ Slice(Slice&& other) noexcept = default;
+
+ // Create a Slice which owns |size| bytes of memory.
+ static Slice Allocate(size_t size) {
+ Slice slice;
+ slice.own_data_.reset(new uint8_t[size]);
+ slice.start = &slice.own_data_[0];
+ slice.size = size;
+ return slice;
+ }
+
+ static Slice TakeOwnership(std::unique_ptr<uint8_t[]> buf, size_t size) {
+ Slice slice;
+ slice.own_data_ = std::move(buf);
+ slice.start = &slice.own_data_[0];
+ slice.size = size;
+ return slice;
+ }
+
+ uint8_t* own_data() {
+ PERFETTO_DCHECK(own_data_);
+ return own_data_.get();
+ }
+
+ const void* start;
+ size_t size;
+
+ private:
+ Slice(const Slice&) = delete;
+ void operator=(const Slice&) = delete;
+
+ std::unique_ptr<uint8_t[]> own_data_;
+};
+
+// TODO(primiano): most TracePacket(s) fit in a slice or two. We need something
+// a bit more clever here that has inline capacity for 2 slices and then uses a
+// std::forward_list or a std::vector for the less likely cases.
+using Slices = std::vector<Slice>;
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICE_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
+
+#include <stddef.h>
+#include <memory>
+#include <optional>
+#include <tuple>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/slice.h"
+
+namespace perfetto {
+
+// A wrapper around a byte buffer that contains a protobuf-encoded TracePacket
+// (see trace_packet.proto). The TracePacket is decoded only if the Consumer
+// requests that. This is to allow Consumer(s) to just stream the packet over
+// the network or save it to a file without wasting time decoding it and without
+// needing to depend on libprotobuf or the trace_packet.pb.h header.
+// If the packets are saved / streamed and not just consumed locally, consumers
+// should ensure to preserve the unknown fields in the proto. A consumer, in
+// fact, might have an older version .proto which is newer on the producer.
+class PERFETTO_EXPORT_COMPONENT TracePacket {
+ public:
+ using const_iterator = Slices::const_iterator;
+
+ // The field id of protos::Trace::packet, static_assert()-ed in the unittest.
+ static constexpr uint32_t kPacketFieldNumber = 1;
+
+ // Maximum size of the preamble returned by GetProtoPreamble().
+ static constexpr size_t kMaxPreambleBytes = 8;
+
+ TracePacket();
+ ~TracePacket();
+ TracePacket(TracePacket&&) noexcept;
+ TracePacket& operator=(TracePacket&&);
+
+ // Accesses all the raw slices in the packet, for saving them to file/network.
+ const Slices& slices() const { return slices_; }
+
+ // Mutator, used only by the service and tests.
+ void AddSlice(Slice);
+
+ // Does not copy / take ownership of the memory of the slice. The TracePacket
+ // will be valid only as long as the original buffer is valid.
+ void AddSlice(const void* start, size_t size);
+
+ // Total size of all slices.
+ size_t size() const { return size_; }
+
+ // Generates a protobuf preamble suitable to represent this packet as a
+ // repeated field within a root trace.proto message.
+ // Returns a pointer to a buffer, owned by this class, containing the preamble
+ // and its size.
+ std::tuple<char*, size_t> GetProtoPreamble();
+
+ // Returns the raw protobuf bytes of the slices, all stitched together into
+ // a string. Only for testing.
+ std::string GetRawBytesForTesting();
+
+ // Remembers the buffer index where this packet was taken from. This is
+ // usually populated for packets from a TraceBuffer, not synthetic ones.
+ std::optional<uint32_t> buffer_index_for_stats() const {
+ if (buffer_index_for_stats_ == 0)
+ return std::nullopt;
+ return buffer_index_for_stats_ - 1;
+ }
+ void set_buffer_index_for_stats(uint32_t v) {
+ buffer_index_for_stats_ = v + 1;
+ }
+
+ private:
+ TracePacket(const TracePacket&) = delete;
+ TracePacket& operator=(const TracePacket&) = delete;
+
+ Slices slices_; // Not owned.
+ size_t size_ = 0; // SUM(slice.size for slice in slices_).
+
+ // Internally we store index+1, and use 0 for the "not set" case.
+ uint32_t buffer_index_for_stats_ = 0;
+ char preamble_[kMaxPreambleBytes]; // Deliberately not initialized.
+
+ // Remember to update the move operators and their unittest if adding new
+ // fields. ConsumerIPCClientImpl::OnReadBuffersResponse() relies on
+ // std::move(TracePacket) to clear up the moved-from instance.
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
+
+#include <stdint.h>
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_packet.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/clock_snapshots.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/flush_flags.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+class Consumer;
+class Producer;
+class SharedMemoryArbiter;
+class TraceWriter;
+class ClientIdentity;
+
+// TODO: for the moment this assumes that all the calls happen on the same
+// thread/sequence. Not sure this will be the case long term in Chrome.
+
+// The API for the Producer port of the Service.
+// Subclassed by:
+// 1. The tracing_service_impl.cc business logic when returning it in response
+// to the ConnectProducer() method.
+// 2. The transport layer (e.g., src/ipc) when the producer and
+// the service don't talk locally but via some IPC mechanism.
+class PERFETTO_EXPORT_COMPONENT ProducerEndpoint {
+ public:
+ virtual ~ProducerEndpoint();
+
+ // Disconnects the endpoint from the service, while keeping the shared memory
+ // valid. After calling this, the endpoint will no longer call any methods
+ // on the Producer.
+ virtual void Disconnect() = 0;
+
+ // Called by the Producer to (un)register data sources. Data sources are
+ // identified by their name (i.e. DataSourceDescriptor.name)
+ virtual void RegisterDataSource(const DataSourceDescriptor&) = 0;
+ virtual void UpdateDataSource(const DataSourceDescriptor&) = 0;
+ virtual void UnregisterDataSource(const std::string& name) = 0;
+
+ // Associate the trace writer with the given |writer_id| with
+ // |target_buffer|. The service may use this information to retrieve and
+ // copy uncommitted chunks written by the trace writer into its associated
+ // buffer, e.g. when a producer process crashes or when a flush is
+ // necessary.
+ virtual void RegisterTraceWriter(uint32_t writer_id,
+ uint32_t target_buffer) = 0;
+
+ // Remove the association of the trace writer previously created via
+ // RegisterTraceWriter.
+ virtual void UnregisterTraceWriter(uint32_t writer_id) = 0;
+
+ // Called by the Producer to signal that some pages in the shared memory
+ // buffer (shared between Service and Producer) have changed.
+ // When the Producer and the Service are hosted in the same process and
+ // hence potentially live on the same task runner, This method must call
+ // TracingServiceImpl's CommitData synchronously, without any PostTask()s,
+ // if on the same thread. This is to avoid a deadlock where the Producer
+ // exhausts its SMB and stalls waiting for the service to catch up with
+ // reads, but the Service never gets to that because it lives on the same
+ // thread.
+ using CommitDataCallback = std::function<void()>;
+ virtual void CommitData(const CommitDataRequest&,
+ CommitDataCallback callback = {}) = 0;
+
+ virtual SharedMemory* shared_memory() const = 0;
+
+ // Size of shared memory buffer pages. It's always a multiple of 4K.
+ // See shared_memory_abi.h
+ virtual size_t shared_buffer_page_size_kb() const = 0;
+
+ // Creates a trace writer, which allows to create events, handling the
+ // underying shared memory buffer and signalling to the Service. This method
+ // is thread-safe but the returned object is not. A TraceWriter should be
+ // used only from a single thread, or the caller has to handle sequencing
+ // via a mutex or equivalent. This method can only be called if
+ // TracingService::ConnectProducer was called with |in_process=true|.
+ // Args:
+ // |target_buffer| is the target buffer ID where the data produced by the
+ // writer should be stored by the tracing service. This value is passed
+ // upon creation of the data source (StartDataSource()) in the
+ // DataSourceConfig.target_buffer().
+ virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
+ BufferID target_buffer,
+ BufferExhaustedPolicy buffer_exhausted_policy =
+ BufferExhaustedPolicy::kDefault) = 0;
+
+ // TODO(eseckler): Also expose CreateStartupTraceWriter() ?
+
+ // In some cases you can access the producer's SharedMemoryArbiter (for
+ // example if TracingService::ConnectProducer is called with
+ // |in_process=true|). The SharedMemoryArbiter can be used to create
+ // TraceWriters which is able to directly commit chunks. For the
+ // |in_process=true| case this can be done without going through an IPC layer.
+ virtual SharedMemoryArbiter* MaybeSharedMemoryArbiter() = 0;
+
+ // Whether the service accepted a shared memory buffer provided by the
+ // producer.
+ virtual bool IsShmemProvidedByProducer() const = 0;
+
+ // Called in response to a Producer::Flush(request_id) call after all data
+ // for the flush request has been committed.
+ virtual void NotifyFlushComplete(FlushRequestID) = 0;
+
+ // Called in response to one or more Producer::StartDataSource(),
+ // if the data source registered setting the flag
+ // DataSourceDescriptor.will_notify_on_start.
+ virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0;
+
+ // Called in response to one or more Producer::StopDataSource(),
+ // if the data source registered setting the flag
+ // DataSourceDescriptor.will_notify_on_stop.
+ virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0;
+
+ // This informs the service to activate any of these triggers if any tracing
+ // session was waiting for them.
+ virtual void ActivateTriggers(const std::vector<std::string>&) = 0;
+
+ // Emits a synchronization barrier to linearize with the service. When
+ // |callback| is invoked, the caller has the guarantee that the service has
+ // seen and processed all the requests sent by this producer prior to the
+ // Sync() call. Used mainly in tests.
+ virtual void Sync(std::function<void()> callback) = 0;
+}; // class ProducerEndpoint.
+
+// The API for the Consumer port of the Service.
+// Subclassed by:
+// 1. The tracing_service_impl.cc business logic when returning it in response
+// to
+// the ConnectConsumer() method.
+// 2. The transport layer (e.g., src/ipc) when the consumer and
+// the service don't talk locally but via some IPC mechanism.
+class PERFETTO_EXPORT_COMPONENT ConsumerEndpoint {
+ public:
+ virtual ~ConsumerEndpoint();
+
+ // Enables tracing with the given TraceConfig. The ScopedFile argument is
+ // used only when TraceConfig.write_into_file == true.
+ // If TraceConfig.deferred_start == true data sources are configured via
+ // SetupDataSource() but are not started until StartTracing() is called.
+ // This is to support pre-initialization and fast triggering of traces.
+ // The ScopedFile argument is used only when TraceConfig.write_into_file
+ // == true.
+ virtual void EnableTracing(const TraceConfig&,
+ base::ScopedFile = base::ScopedFile()) = 0;
+
+ // Update the trace config of an existing tracing session; only a subset
+ // of options can be changed mid-session. Currently the only
+ // supported functionality is expanding the list of producer_name_filters()
+ // (or removing the filter entirely) for existing data sources.
+ virtual void ChangeTraceConfig(const TraceConfig&) = 0;
+
+ // Starts all data sources configured in the trace config. This is used only
+ // after calling EnableTracing() with TraceConfig.deferred_start=true.
+ // It's a no-op if called after a regular EnableTracing(), without setting
+ // deferred_start.
+ virtual void StartTracing() = 0;
+
+ virtual void DisableTracing() = 0;
+
+ // Clones an existing tracing session and attaches to it. The session is
+ // cloned in read-only mode and can only be used to read a snapshot of an
+ // existing tracing session. Will invoke Consumer::OnSessionCloned().
+ // If TracingSessionID == kBugreportSessionId (0xff...ff) the session with the
+ // highest bugreport score is cloned (if any exists).
+ struct CloneSessionArgs {
+ // If set, the trace filter will not have effect on the cloned session.
+ // Used for bugreports.
+ bool skip_trace_filter = false;
+
+ // If set, affects the generation of the FlushFlags::CloneTarget to be set
+ // to kBugreport when requesting the flush to the producers.
+ bool for_bugreport = false;
+ };
+ virtual void CloneSession(TracingSessionID, CloneSessionArgs) = 0;
+
+ // Requests all data sources to flush their data immediately and invokes the
+ // passed callback once all of them have acked the flush (in which case
+ // the callback argument |success| will be true) or |timeout_ms| are elapsed
+ // (in which case |success| will be false).
+ // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or,
+ // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is
+ // used.
+ using FlushCallback = std::function<void(bool /*success*/)>;
+ virtual void Flush(uint32_t timeout_ms,
+ FlushCallback callback,
+ FlushFlags) = 0;
+
+ // This is required for legacy out-of-repo clients like arctraceservice which
+ // use the 2-version parameter.
+ inline void Flush(uint32_t timeout_ms, FlushCallback callback) {
+ Flush(timeout_ms, std::move(callback), FlushFlags());
+ }
+
+ // Tracing data will be delivered invoking Consumer::OnTraceData().
+ virtual void ReadBuffers() = 0;
+
+ virtual void FreeBuffers() = 0;
+
+ // Will call OnDetach().
+ virtual void Detach(const std::string& key) = 0;
+
+ // Will call OnAttach().
+ virtual void Attach(const std::string& key) = 0;
+
+ // Will call OnTraceStats().
+ virtual void GetTraceStats() = 0;
+
+ // Start or stop observing events of selected types. |events_mask| specifies
+ // the types of events to observe in a bitmask of ObservableEvents::Type.
+ // To disable observing, pass 0.
+ // Will call OnObservableEvents() repeatedly whenever an event of an enabled
+ // ObservableEventType occurs.
+ // TODO(eseckler): Extend this to support producers & data sources.
+ virtual void ObserveEvents(uint32_t events_mask) = 0;
+
+ // Used to obtain the list of connected data sources and other info about
+ // the tracing service.
+ struct QueryServiceStateArgs {
+ // If set, only the TracingServiceState.tracing_sessions is filled.
+ bool sessions_only = false;
+ };
+ using QueryServiceStateCallback =
+ std::function<void(bool success, const TracingServiceState&)>;
+ virtual void QueryServiceState(QueryServiceStateArgs,
+ QueryServiceStateCallback) = 0;
+
+ // Used for feature detection. Makes sense only when the consumer and the
+ // service talk over IPC and can be from different versions.
+ using QueryCapabilitiesCallback =
+ std::function<void(const TracingServiceCapabilities&)>;
+ virtual void QueryCapabilities(QueryCapabilitiesCallback) = 0;
+
+ // If any tracing session with TraceConfig.bugreport_score > 0 is running,
+ // this will pick the highest-score one, stop it and save it into a fixed
+ // path (See kBugreportTracePath).
+ // The callback is invoked when the file has been saved, in case of success,
+ // or whenever an error occurs.
+ // Args:
+ // - success: if true, an eligible trace was found and saved into file.
+ // If false, either there was no eligible trace running or
+ // something else failed (See |msg|).
+ // - msg: human readable diagnostic messages to debug failures.
+ using SaveTraceForBugreportCallback =
+ std::function<void(bool /*success*/, const std::string& /*msg*/)>;
+ virtual void SaveTraceForBugreport(SaveTraceForBugreportCallback) = 0;
+}; // class ConsumerEndpoint.
+
+struct PERFETTO_EXPORT_COMPONENT TracingServiceInitOpts {
+ // Function used by tracing service to compress packets. Takes a pointer to
+ // a vector of TracePackets and replaces the packets in the vector with
+ // compressed ones.
+ using CompressorFn = void (*)(std::vector<TracePacket>*);
+ CompressorFn compressor_fn = nullptr;
+
+ // Whether the relay endpoint is enabled on producer transport(s).
+ bool enable_relay_endpoint = false;
+};
+
+// The API for the Relay port of the Service. Subclassed by the
+// tracing_service_impl.cc business logic when returning it in response to the
+// ConnectRelayClient() method.
+class PERFETTO_EXPORT_COMPONENT RelayEndpoint {
+ public:
+ virtual ~RelayEndpoint();
+
+ // A snapshot of client and host clocks.
+ struct SyncClockSnapshot {
+ ClockSnapshotVector client_clock_snapshots;
+ ClockSnapshotVector host_clock_snapshots;
+ };
+
+ enum class SyncMode : uint32_t { PING = 1, UPDATE = 2 };
+ virtual void SyncClocks(SyncMode sync_mode,
+ ClockSnapshotVector client_clocks,
+ ClockSnapshotVector host_clocks) = 0;
+ virtual void Disconnect() = 0;
+};
+
+// The public API of the tracing Service business logic.
+//
+// Exposed to:
+// 1. The transport layer (e.g., src/unix_rpc/unix_service_host.cc),
+// which forwards commands received from a remote producer or consumer to
+// the actual service implementation.
+// 2. Tests.
+//
+// Subclassed by:
+// The service business logic in src/core/tracing_service_impl.cc.
+class PERFETTO_EXPORT_COMPONENT TracingService {
+ public:
+ using ProducerEndpoint = perfetto::ProducerEndpoint;
+ using ConsumerEndpoint = perfetto::ConsumerEndpoint;
+ using RelayEndpoint = perfetto::RelayEndpoint;
+ using InitOpts = TracingServiceInitOpts;
+
+ // Default sizes used by the service implementation and client library.
+ static constexpr size_t kDefaultShmPageSize = 4096ul;
+ static constexpr size_t kDefaultShmSize = 256 * 1024ul;
+
+ enum class ProducerSMBScrapingMode {
+ // Use service's default setting for SMB scraping. Currently, the default
+ // mode is to disable SMB scraping, but this may change in the future.
+ kDefault,
+
+ // Enable scraping of uncommitted chunks in producers' shared memory
+ // buffers.
+ kEnabled,
+
+ // Disable scraping of uncommitted chunks in producers' shared memory
+ // buffers.
+ kDisabled
+ };
+
+ // Implemented in src/core/tracing_service_impl.cc . CompressorFn can be
+ // nullptr, in which case TracingService will not support compression.
+ static std::unique_ptr<TracingService> CreateInstance(
+ std::unique_ptr<SharedMemory::Factory>,
+ base::TaskRunner*,
+ InitOpts init_opts = {});
+
+ virtual ~TracingService();
+
+ // Connects a Producer instance and obtains a ProducerEndpoint, which is
+ // essentially a 1:1 channel between one Producer and the Service.
+ //
+ // The caller has to guarantee that the passed Producer will be alive as long
+ // as the returned ProducerEndpoint is alive. Both the passed Producer and the
+ // returned ProducerEndpoint must live on the same task runner of the service,
+ // specifically:
+ // 1) The Service will call Producer::* methods on the Service's task runner.
+ // 2) The Producer should call ProducerEndpoint::* methods only on the
+ // service's task runner, except for ProducerEndpoint::CreateTraceWriter(),
+ // which can be called on any thread. To disconnect just destroy the
+ // returned ProducerEndpoint object. It is safe to destroy the Producer
+ // once the Producer::OnDisconnect() has been invoked.
+ //
+ // |uid| is the trusted user id of the producer process, used by the consumers
+ // for validating the origin of trace data. |shared_memory_size_hint_bytes|
+ // and |shared_memory_page_size_hint_bytes| are optional hints on the size of
+ // the shared memory buffer and its pages. The service can ignore the hints
+ // (e.g., if the hints are unreasonably large or other sizes were configured
+ // in a tracing session's config). |in_process| enables the ProducerEndpoint
+ // to manage its own shared memory and enables use of
+ // |ProducerEndpoint::CreateTraceWriter|.
+ //
+ // The producer can optionally provide a non-null |shm|, which the service
+ // will adopt for the connection to the producer, provided it is correctly
+ // sized. In this case, |shared_memory_page_size_hint_bytes| indicates the
+ // page size used in this SMB. The producer can use this mechanism to record
+ // tracing data to an SMB even before the tracing session is started by the
+ // service. This is used in Chrome to implement startup tracing. If the buffer
+ // is incorrectly sized, the service will discard the SMB and allocate a new
+ // one, provided to the producer via ProducerEndpoint::shared_memory() after
+ // OnTracingSetup(). To verify that the service accepted the SMB, the producer
+ // may check via ProducerEndpoint::IsShmemProvidedByProducer(). If the service
+ // accepted the SMB, the producer can then commit any data that is already in
+ // the SMB after the tracing session was started by the service via
+ // Producer::StartDataSource(). The |shm| will also be rejected when
+ // connecting to a service that is too old (pre Android-11).
+ //
+ // Can return null in the unlikely event that service has too many producers
+ // connected.
+ virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
+ Producer*,
+ const ClientIdentity& client_identity,
+ const std::string& name,
+ size_t shared_memory_size_hint_bytes = 0,
+ bool in_process = false,
+ ProducerSMBScrapingMode smb_scraping_mode =
+ ProducerSMBScrapingMode::kDefault,
+ size_t shared_memory_page_size_hint_bytes = 0,
+ std::unique_ptr<SharedMemory> shm = nullptr,
+ const std::string& sdk_version = {}) = 0;
+
+ // Connects a Consumer instance and obtains a ConsumerEndpoint, which is
+ // essentially a 1:1 channel between one Consumer and the Service.
+ // The caller has to guarantee that the passed Consumer will be alive as long
+ // as the returned ConsumerEndpoint is alive.
+ // To disconnect just destroy the returned ConsumerEndpoint object. It is safe
+ // to destroy the Consumer once the Consumer::OnDisconnect() has been invoked.
+ virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(Consumer*,
+ uid_t) = 0;
+
+ // Enable/disable scraping of chunks in the shared memory buffer. If enabled,
+ // the service will copy uncommitted but non-empty chunks from the SMB when
+ // flushing (e.g. to handle unresponsive producers or producers unable to
+ // flush their active chunks), on producer disconnect (e.g. to recover data
+ // from crashed producers), and after disabling a tracing session (e.g. to
+ // gather data from producers that didn't stop their data sources in time).
+ //
+ // This feature is currently used by Chrome.
+ virtual void SetSMBScrapingEnabled(bool enabled) = 0;
+
+ using RelayClientID = std::pair<base::MachineID, /*client ID*/ uint64_t>;
+ // Connects a remote RelayClient instance and obtains a RelayEndpoint, which
+ // is a 1:1 channel between one RelayClient and the Service. To disconnect
+ // just call Disconnect() of the RelayEndpoint instance. The relay client is
+ // connected using an identifier of MachineID and client ID. The service
+ // doesn't hold an object that represents the client because the relay port
+ // only has a client-to-host SyncClock() method.
+ //
+ // TODO(chinglinyu): connect the relay client using a RelayClient* object when
+ // we need host-to-client RPC method.
+ virtual std::unique_ptr<RelayEndpoint> ConnectRelayClient(RelayClientID) = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
+
+#include <stddef.h>
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}
+
+class SharedMemory;
+class TraceWriter;
+
+// Used by the Producer-side of the transport layer to vend TraceWriters
+// from the SharedMemory it receives from the Service-side.
+class PERFETTO_EXPORT_COMPONENT SharedMemoryArbiter {
+ public:
+ using ShmemMode = SharedMemoryABI::ShmemMode;
+
+ virtual ~SharedMemoryArbiter();
+
+ // Creates a new TraceWriter and assigns it a new WriterID. The WriterID is
+ // written in each chunk header owned by a given TraceWriter and is used by
+ // the Service to reconstruct TracePackets written by the same TraceWriter.
+ // Returns null impl of TraceWriter if all WriterID slots are exhausted. The
+ // writer will commit to the provided |target_buffer|. If the arbiter was
+ // created via CreateUnbound() or CreateStartupTraceWriter() is later used,
+ // only BufferExhaustedPolicy::kDrop is supported.
+ virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
+ BufferID target_buffer,
+ BufferExhaustedPolicy buffer_exhausted_policy =
+ BufferExhaustedPolicy::kDefault) = 0;
+
+ // Creates a TraceWriter that will commit to the target buffer with the given
+ // reservation ID (creating a new reservation for this ID if none exists yet).
+ // The buffer reservation should be bound to an actual BufferID via
+ // BindStartupTargetBuffer() once the actual BufferID is known. Calling this
+ // method may transition the arbiter into unbound state (see state diagram in
+ // SharedMemoryArbiterImpl's class comment) and requires that all (past and
+ // future) TraceWriters are created with BufferExhaustedPolicy::kDrop.
+ //
+ // While any unbound buffer reservation exists, all commits will be buffered
+ // until all reservations were bound. Thus, until all reservations are bound,
+ // the data written to the SMB will not be consumed by the service - the SMB
+ // size should be chosen with this in mind. Startup writers always use
+ // BufferExhaustedPolicy::kDrop, as we cannot feasibly stall while not
+ // flushing to the service.
+ //
+ // The |target_buffer_reservation_id| should be greater than 0 but can
+ // otherwise be freely chosen by the producer and is only used to translate
+ // packets into the actual buffer id once
+ // BindStartupTargetBuffer(reservation_id) is called. For example, Chrome uses
+ // startup tracing not only for the first, but also subsequent tracing
+ // sessions (to enable tracing in the browser process before it instructs the
+ // tracing service to start tracing asynchronously, minimizing trace data loss
+ // in the meantime), and increments the reservation ID between sessions.
+ // Similarly, if more than a single target buffer per session is required
+ // (e.g. for two different data sources), different reservation IDs should be
+ // chosen for different target buffers.
+ virtual std::unique_ptr<TraceWriter> CreateStartupTraceWriter(
+ uint16_t target_buffer_reservation_id) = 0;
+
+ // Should only be called on unbound SharedMemoryArbiters. Binds the arbiter to
+ // the provided ProducerEndpoint and TaskRunner. Should be called only once
+ // and on the provided |TaskRunner|. Usually called by the producer (i.e., no
+ // specific data source) once it connects to the service. Both the endpoint
+ // and task runner should remain valid for the remainder of the arbiter's
+ // lifetime.
+ virtual void BindToProducerEndpoint(TracingService::ProducerEndpoint*,
+ base::TaskRunner*) = 0;
+
+ // Binds commits from TraceWriters created via CreateStartupTraceWriter() with
+ // the given |target_buffer_reservation_id| to |target_buffer_id|. May only be
+ // called once per |target_buffer_reservation_id|. Should be called on the
+ // arbiter's TaskRunner, and after BindToProducerEndpoint() was called.
+ // Usually, it is called by a specific data source, after it received its
+ // configuration (including the target buffer ID) from the service.
+ virtual void BindStartupTargetBuffer(uint16_t target_buffer_reservation_id,
+ BufferID target_buffer_id) = 0;
+
+ // Treat the reservation as resolved to an invalid buffer. Commits for this
+ // reservation will be flushed to the service ASAP. The service will free
+ // committed chunks but otherwise ignore them. The producer can call this
+ // method, for example, if connection to the tracing service failed or the
+ // session was stopped concurrently before the connection was established.
+ virtual void AbortStartupTracingForReservation(
+ uint16_t target_buffer_reservation_id) = 0;
+
+ // Notifies the service that all data for the given FlushRequestID has been
+ // committed in the shared memory buffer. Should only be called while bound.
+ virtual void NotifyFlushComplete(FlushRequestID) = 0;
+
+ // Sets the duration during which commits are batched. Args:
+ // |batch_commits_duration_ms|: The length of the period, during which commits
+ // by all trace writers are accumulated, before being sent to the service.
+ // When the period ends, all accumulated commits are flushed. On the first
+ // commit after the last flush, another delayed flush is scheduled to run in
+ // |batch_commits_duration_ms|. If an immediate flush occurs (via
+ // FlushPendingCommitDataRequests()) during a batching period, any
+ // accumulated commits up to that point will be sent to the service
+ // immediately. And when the batching period ends, the commits that occurred
+ // after the immediate flush will also be sent to the service.
+ //
+ // If the duration has already been set to a non-zero value before this method
+ // is called, and there is already a scheduled flush with the previously-set
+ // duration, the new duration will take effect after the scheduled flush
+ // occurs.
+ //
+ // If |batch_commits_duration_ms| is non-zero, batched data that hasn't been
+ // sent could be lost at the end of a tracing session. To avoid this,
+ // producers should make sure that FlushPendingCommitDataRequests is called
+ // after the last TraceWriter write and before the service has stopped
+ // listening for commits from the tracing session's data sources (i.e.
+ // data sources should stop asynchronously, see
+ // DataSourceDescriptor.will_notify_on_stop=true).
+ virtual void SetBatchCommitsDuration(uint32_t batch_commits_duration_ms) = 0;
+
+ // Called to enable direct producer-side patching of chunks that have not yet
+ // been committed to the service. The return value indicates whether direct
+ // patching was successfully enabled. It will be true if
+ // SharedMemoryArbiter::SetDirectSMBPatchingSupportedByService has been called
+ // and false otherwise.
+ virtual bool EnableDirectSMBPatching() = 0;
+
+ // When the producer and service live in separate processes, this method
+ // should be called if the producer receives an
+ // InitializeConnectionResponse.direct_smb_patching_supported set to true by
+ // the service (see producer_port.proto) .
+ //
+ // In the in-process case, the service will always support direct SMB patching
+ // and this method should always be called.
+ virtual void SetDirectSMBPatchingSupportedByService() = 0;
+
+ // Forces an immediate commit of the completed packets, without waiting for
+ // the next task or for a batching period to end. Should only be called while
+ // bound.
+ virtual void FlushPendingCommitDataRequests(
+ std::function<void()> callback = {}) = 0;
+
+ // Attempts to shut down this arbiter. This function prevents new trace
+ // writers from being created for this this arbiter, but if there are any
+ // existing trace writers, the shutdown cannot proceed and this funtion
+ // returns false. The caller should not delete the arbiter before all of its
+ // associated trace writers have been destroyed and this function returns
+ // true.
+ virtual bool TryShutdown() = 0;
+
+ // Create a bound arbiter instance. Args:
+ // |SharedMemory|: the shared memory buffer to use.
+ // |page_size|: a multiple of 4KB that defines the granularity of tracing
+ // pages. See tradeoff considerations in shared_memory_abi.h.
+ // |ProducerEndpoint|: The service's producer endpoint used e.g. to commit
+ // chunks and register trace writers.
+ // |TaskRunner|: Task runner for perfetto's main thread, which executes the
+ // OnPagesCompleteCallback and IPC calls to the |ProducerEndpoint|.
+ //
+ // Implemented in src/core/shared_memory_arbiter_impl.cc.
+ static std::unique_ptr<SharedMemoryArbiter> CreateInstance(
+ SharedMemory*,
+ size_t page_size,
+ ShmemMode,
+ TracingService::ProducerEndpoint*,
+ base::TaskRunner*);
+
+ // Create an unbound arbiter instance, which should later be bound to a
+ // ProducerEndpoint and TaskRunner by calling BindToProducerEndpoint(). The
+ // returned arbiter will ONLY support trace writers with
+ // BufferExhaustedPolicy::kDrop.
+ //
+ // An unbound SharedMemoryArbiter can be used to write to a producer-created
+ // SharedMemory buffer before the producer connects to the tracing service.
+ // The producer can then pass this SMB to the service when it connects (see
+ // TracingService::ConnectProducer).
+ //
+ // To trace into the SMB before the service starts the tracing session, trace
+ // writers can be obtained via CreateStartupTraceWriter() and later associated
+ // with a target buffer via BindStartupTargetBuffer(), once the target buffer
+ // is known.
+ //
+ // Implemented in src/core/shared_memory_arbiter_impl.cc. See CreateInstance()
+ // for comments about the arguments.
+ static std::unique_ptr<SharedMemoryArbiter>
+ CreateUnboundInstance(SharedMemory*, size_t page_size, ShmemMode mode);
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_
+#define SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_
+
+#include <stdint.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "src/tracing/core/id_allocator.h"
+
+namespace perfetto {
+
+class PatchList;
+class Patch;
+class TraceWriter;
+class TraceWriterImpl;
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+// This class handles the shared memory buffer on the producer side. It is used
+// to obtain thread-local chunks and to partition pages from several threads.
+// There is one arbiter instance per Producer.
+// This class is thread-safe and uses locks to do so. Data sources are supposed
+// to interact with this sporadically, only when they run out of space on their
+// current thread-local chunk.
+//
+// The arbiter can become "unbound" as a consequence of:
+// (a) being created without an endpoint
+// (b) CreateStartupTraceWriter calls after creation (whether created with or
+// without endpoint).
+//
+// Entering the unbound state is only supported if all trace writers are created
+// in kDrop mode. In the unbound state, the arbiter buffers commit messages
+// until all trace writers are bound to a target buffer.
+//
+// The following state transitions are possible:
+//
+// CreateInstance()
+// |
+// | CreateUnboundInstance()
+// | |
+// | |
+// | V
+// | [ !fully_bound_, !endpoint_, 0 unbound buffer reservations ]
+// | | |
+// | | | CreateStartupTraceWriter(buf)
+// | | | buffer reservations += buf
+// | | |
+// | | | ----
+// | | | | | CreateStartupTraceWriter(buf)
+// | | | | | buffer reservations += buf
+// | | V | V
+// | | [ !fully_bound_, !endpoint_, >=1 unbound buffer reservations ]
+// | | |
+// | | BindToProducerEndpoint() |
+// | | |
+// | | BindToProducerEndpoint() |
+// | | V
+// | | [ !fully_bound_, endpoint_, >=1 unbound buffer reservations ]
+// | | A | A | A
+// | | | | | | |
+// | | | ---- | |
+// | | | CreateStartupTraceWriter(buf) | |
+// | | | buffer reservations += buf | |
+// | | | | |
+// | | | CreateStartupTraceWriter(buf) | |
+// | | | where buf is not yet bound | |
+// | | | buffer reservations += buf | | (yes)
+// | | | | |
+// | | | BindStartupTargetBuffer(buf, id) |-----
+// | | | buffer reservations -= buf | reservations > 0?
+// | | | |
+// | | | | (no)
+// | V | V
+// --> [ fully_bound_, endpoint_, 0 unbound buffer reservations ]
+// | A
+// | | CreateStartupTraceWriter(buf)
+// | | where buf is already bound
+// ----
+class SharedMemoryArbiterImpl : public SharedMemoryArbiter {
+ public:
+ // See SharedMemoryArbiter::CreateInstance(). |start|, |size| define the
+ // boundaries of the shared memory buffer. ProducerEndpoint and TaskRunner may
+ // be |nullptr| if created unbound, see
+ // SharedMemoryArbiter::CreateUnboundInstance().
+
+ // SharedMemoryArbiterImpl(void* start,
+ // size_t size,
+ // size_t page_size,
+ // TracingService::ProducerEndpoint*
+ // producer_endpoint, base::TaskRunner* task_runner) :
+ // SharedMemoryArbiterImpl(start, size, page_size, false, producer_endpoint,
+ // task_runner) {
+ // }
+
+ SharedMemoryArbiterImpl(void* start,
+ size_t size,
+ ShmemMode mode,
+ size_t page_size,
+ TracingService::ProducerEndpoint*,
+ base::TaskRunner*);
+
+ // Returns a new Chunk to write tracing data. Depending on the provided
+ // BufferExhaustedPolicy, this may return an invalid chunk if no valid free
+ // chunk could be found in the SMB.
+ SharedMemoryABI::Chunk GetNewChunk(const SharedMemoryABI::ChunkHeader&,
+ BufferExhaustedPolicy);
+
+ // Puts back a Chunk that has been completed and sends a request to the
+ // service to move it to the central tracing buffer. |target_buffer| is the
+ // absolute trace buffer ID where the service should move the chunk onto (the
+ // producer is just to copy back the same number received in the
+ // DataSourceConfig upon the StartDataSource() reques).
+ // PatchList is a pointer to the list of patches for previous chunks. The
+ // first patched entries will be removed from the patched list and sent over
+ // to the service in the same CommitData() IPC request.
+ void ReturnCompletedChunk(SharedMemoryABI::Chunk,
+ MaybeUnboundBufferID target_buffer,
+ PatchList*);
+
+ // Send a request to the service to apply completed patches from |patch_list|.
+ // |writer_id| is the ID of the TraceWriter that calls this method,
+ // |target_buffer| is the global trace buffer ID of its target buffer.
+ void SendPatches(WriterID writer_id,
+ MaybeUnboundBufferID target_buffer,
+ PatchList* patch_list);
+
+ SharedMemoryABI* shmem_abi_for_testing() { return &shmem_abi_; }
+
+ static void set_default_layout_for_testing(SharedMemoryABI::PageLayout l) {
+ default_page_layout = l;
+ }
+
+ static SharedMemoryABI::PageLayout default_page_layout_for_testing() {
+ return default_page_layout;
+ }
+
+ // SharedMemoryArbiter implementation.
+ // See include/perfetto/tracing/core/shared_memory_arbiter.h for comments.
+ std::unique_ptr<TraceWriter> CreateTraceWriter(
+ BufferID target_buffer,
+ BufferExhaustedPolicy = BufferExhaustedPolicy::kDefault) override;
+ std::unique_ptr<TraceWriter> CreateStartupTraceWriter(
+ uint16_t target_buffer_reservation_id) override;
+ void BindToProducerEndpoint(TracingService::ProducerEndpoint*,
+ base::TaskRunner*) override;
+ void BindStartupTargetBuffer(uint16_t target_buffer_reservation_id,
+ BufferID target_buffer_id) override;
+ void AbortStartupTracingForReservation(
+ uint16_t target_buffer_reservation_id) override;
+ void NotifyFlushComplete(FlushRequestID) override;
+
+ void SetBatchCommitsDuration(uint32_t batch_commits_duration_ms) override;
+
+ bool EnableDirectSMBPatching() override;
+
+ void SetDirectSMBPatchingSupportedByService() override;
+
+ void FlushPendingCommitDataRequests(
+ std::function<void()> callback = {}) override;
+ bool TryShutdown() override;
+
+ base::TaskRunner* task_runner() const { return task_runner_; }
+ size_t page_size() const { return shmem_abi_.page_size(); }
+ size_t num_pages() const { return shmem_abi_.num_pages(); }
+
+ base::WeakPtr<SharedMemoryArbiterImpl> GetWeakPtr() const {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ private:
+ friend class TraceWriterImpl;
+ friend class StartupTraceWriterTest;
+ friend class SharedMemoryArbiterImplTest;
+
+ struct TargetBufferReservation {
+ bool resolved = false;
+ BufferID target_buffer = kInvalidBufferId;
+ };
+
+ // Placeholder for the actual target buffer ID of a startup target buffer
+ // reservation ID in |target_buffer_reservations_|.
+ static constexpr BufferID kInvalidBufferId = 0;
+
+ static SharedMemoryABI::PageLayout default_page_layout;
+
+ SharedMemoryArbiterImpl(const SharedMemoryArbiterImpl&) = delete;
+ SharedMemoryArbiterImpl& operator=(const SharedMemoryArbiterImpl&) = delete;
+
+ void UpdateCommitDataRequest(SharedMemoryABI::Chunk chunk,
+ WriterID writer_id,
+ MaybeUnboundBufferID target_buffer,
+ PatchList* patch_list);
+
+ // Search the chunks that are being batched in |commit_data_req_| for a chunk
+ // that needs patching and that matches the provided |writer_id| and
+ // |patch.chunk_id|. If found, apply |patch| to that chunk, and if
+ // |chunk_needs_more_patching| is true, clear the needs patching flag of the
+ // chunk and mark it as complete - to allow the service to read it (and other
+ // chunks after it) during scraping. Returns true if the patch was applied,
+ // false otherwise.
+ //
+ // Note: the caller must be holding |lock_| for the duration of the call.
+ bool TryDirectPatchLocked(WriterID writer_id,
+ const Patch& patch,
+ bool chunk_needs_more_patching);
+ std::unique_ptr<TraceWriter> CreateTraceWriterInternal(
+ MaybeUnboundBufferID target_buffer,
+ BufferExhaustedPolicy);
+
+ // Called by the TraceWriter destructor.
+ void ReleaseWriterID(WriterID);
+
+ void BindStartupTargetBufferImpl(std::unique_lock<std::mutex> scoped_lock,
+ uint16_t target_buffer_reservation_id,
+ BufferID target_buffer_id);
+
+ // If any flush callbacks were queued up while the arbiter or any target
+ // buffer reservation was unbound, this wraps the pending callbacks into a new
+ // std::function and returns it. Otherwise returns an invalid std::function.
+ std::function<void()> TakePendingFlushCallbacksLocked();
+
+ // Replace occurrences of target buffer reservation IDs in |commit_data_req_|
+ // with their respective actual BufferIDs if they were already bound. Returns
+ // true iff all occurrences were replaced.
+ bool ReplaceCommitPlaceholderBufferIdsLocked();
+
+ // Update and return |fully_bound_| based on the arbiter's |pending_writers_|
+ // state.
+ bool UpdateFullyBoundLocked();
+
+ // Only accessed on |task_runner_| after the producer endpoint was bound.
+ TracingService::ProducerEndpoint* producer_endpoint_ = nullptr;
+
+ // Set to true when this instance runs in a emulation mode for a producer
+ // endpoint that doesn't support shared memory (e.g. vsock).
+ const bool use_shmem_emulation_ = false;
+
+ // --- Begin lock-protected members ---
+
+ std::mutex lock_;
+
+ base::TaskRunner* task_runner_ = nullptr;
+ SharedMemoryABI shmem_abi_;
+ size_t page_idx_ = 0;
+ std::unique_ptr<CommitDataRequest> commit_data_req_;
+ size_t bytes_pending_commit_ = 0; // SUM(chunk.size() : commit_data_req_).
+ IdAllocator<WriterID> active_writer_ids_;
+ bool did_shutdown_ = false;
+
+ // Whether the arbiter itself and all startup target buffer reservations are
+ // bound. Note that this can become false again later if a new target buffer
+ // reservation is created by calling CreateStartupTraceWriter() with a new
+ // reservation id.
+ bool fully_bound_;
+
+ // Whether the arbiter was always bound. If false, the arbiter was unbound at
+ // one point in time.
+ bool was_always_bound_;
+
+ // Whether all created trace writers were created with kDrop policy.
+ bool all_writers_have_drop_policy_ = true;
+
+ // IDs of writers and their assigned target buffers that should be registered
+ // with the service after the arbiter and/or their startup target buffer is
+ // bound.
+ std::map<WriterID, MaybeUnboundBufferID> pending_writers_;
+
+ // Callbacks for flush requests issued while the arbiter or a target buffer
+ // reservation was unbound.
+ std::vector<std::function<void()>> pending_flush_callbacks_;
+
+ // See SharedMemoryArbiter::SetBatchCommitsDuration.
+ uint32_t batch_commits_duration_ms_ = 0;
+
+ // See SharedMemoryArbiter::EnableDirectSMBPatching.
+ bool direct_patching_enabled_ = false;
+
+ // See SharedMemoryArbiter::SetDirectSMBPatchingSupportedByService.
+ bool direct_patching_supported_by_service_ = false;
+
+ // Indicates whether we have already scheduled a delayed flush for the
+ // purposes of batching. Set to true at the beginning of a batching period and
+ // cleared at the end of the period. Immediate flushes that happen during a
+ // batching period will empty the |commit_data_req| (triggering an immediate
+ // IPC to the service), but will not clear this flag and the
+ // previously-scheduled delayed flush will still occur at the end of the
+ // batching period.
+ bool delayed_flush_scheduled_ = false;
+
+ // Stores target buffer reservations for writers created via
+ // CreateStartupTraceWriter(). A bound reservation sets
+ // TargetBufferReservation::resolved to true and is associated with the actual
+ // BufferID supplied in BindStartupTargetBuffer().
+ //
+ // TODO(eseckler): Clean up entries from this map. This would probably require
+ // a method in SharedMemoryArbiter that allows a producer to invalidate a
+ // reservation ID.
+ std::map<MaybeUnboundBufferID, TargetBufferReservation>
+ target_buffer_reservations_;
+
+ // --- End lock-protected members ---
+
+ // Keep at the end.
+ base::WeakPtrFactory<SharedMemoryArbiterImpl> weak_ptr_factory_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/commit_data_request.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_COMMIT_DATA_REQUEST_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_COMMIT_DATA_REQUEST_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/commit_data_request.gen.h"
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_COMMIT_DATA_REQUEST_H_
+// gen_amalgamated begin header: src/tracing/core/trace_writer_impl.h
+// gen_amalgamated begin header: src/tracing/core/patch_list.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_CORE_PATCH_LIST_H_
+#define SRC_TRACING_CORE_PATCH_LIST_H_
+
+#include <array>
+#include <forward_list>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+
+namespace perfetto {
+
+// Used to handle the backfilling of the headers (the |size_field|) of nested
+// messages when a proto is fragmented over several chunks. These patches are
+// sent out-of-band to the tracing service, after having returned the initial
+// chunks of the fragment.
+// TODO(crbug.com/904477): Re-disable the move constructors when all usses of
+// this class have been fixed.
+class Patch {
+ public:
+ using PatchContent = std::array<uint8_t, SharedMemoryABI::kPacketHeaderSize>;
+ Patch(ChunkID c, uint16_t o) : chunk_id(c), offset(o) {}
+ Patch(const Patch&) = default; // For tests.
+
+ const ChunkID chunk_id;
+ const uint16_t offset;
+ PatchContent size_field{};
+
+ // |size_field| contains a varint. Any varint must start with != 0. Even in
+ // the case we want to encode a size == 0, protozero will write a redundant
+ // varint for that, that is [0x80, 0x80, 0x80, 0x00]. So the first byte is 0
+ // iff we never wrote any varint into that.
+ bool is_patched() const { return size_field[0] != 0; }
+
+ // For tests.
+ bool operator==(const Patch& o) const {
+ return chunk_id == o.chunk_id && offset == o.offset &&
+ size_field == o.size_field;
+ }
+
+ private:
+ Patch& operator=(const Patch&) = delete;
+};
+
+// Note: the protozero::Message(s) will take pointers to the |size_field| of
+// these entries. This container must guarantee that the Patch objects are never
+// moved around (i.e. cannot be a vector because of reallocations can change
+// addresses of pre-existing entries).
+class PatchList {
+ public:
+ using ListType = std::forward_list<Patch>;
+ using value_type = ListType::value_type; // For gtest.
+ using const_iterator = ListType::const_iterator; // For gtest.
+
+ PatchList() : last_(list_.before_begin()) {}
+
+ Patch* emplace_back(ChunkID chunk_id, uint16_t offset) {
+ last_ = list_.emplace_after(last_, chunk_id, offset);
+ return &*last_;
+ }
+
+ void pop_front() {
+ PERFETTO_DCHECK(!list_.empty());
+ list_.pop_front();
+ if (empty())
+ last_ = list_.before_begin();
+ }
+
+ const Patch& front() const {
+ PERFETTO_DCHECK(!list_.empty());
+ return list_.front();
+ }
+
+ const Patch& back() const {
+ PERFETTO_DCHECK(!list_.empty());
+ return *last_;
+ }
+
+ ListType::const_iterator begin() const { return list_.begin(); }
+ ListType::const_iterator end() const { return list_.end(); }
+ bool empty() const { return list_.empty(); }
+
+ private:
+ ListType list_;
+ ListType::iterator last_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_CORE_PATCH_LIST_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
+#define SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/proc_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/root_message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
+// gen_amalgamated expanded: #include "src/tracing/core/patch_list.h"
+
+namespace perfetto {
+
+class SharedMemoryArbiterImpl;
+
+// See //include/perfetto/ext/tracing/core/trace_writer.h for docs.
+//
+// Locking will happen only when a chunk is exhausted and a new one is
+// acquired from the arbiter.
+//
+// TODO: TraceWriter needs to keep the shared memory buffer alive (refcount?).
+// Otherwise if the shared memory buffer goes away (e.g. the Service crashes)
+// the TraceWriter will keep writing into unmapped memory.
+//
+class TraceWriterImpl : public TraceWriter,
+ public protozero::MessageFinalizationListener,
+ public protozero::ScatteredStreamWriter::Delegate {
+ public:
+ // TracePacketHandle is defined in trace_writer.h
+ TraceWriterImpl(SharedMemoryArbiterImpl*,
+ WriterID,
+ MaybeUnboundBufferID buffer_id,
+ BufferExhaustedPolicy);
+ ~TraceWriterImpl() override;
+
+ // TraceWriter implementation. See documentation in trace_writer.h.
+ TracePacketHandle NewTracePacket() override;
+ void FinishTracePacket() override;
+ // Commits the data pending for the current chunk into the shared memory
+ // buffer and sends a CommitDataRequest() to the service.
+ // TODO(primiano): right now the |callback| will be called on the IPC thread.
+ // This is fine in the current single-thread scenario, but long-term
+ // trace_writer_impl.cc should be smarter and post it on the right thread.
+ void Flush(std::function<void()> callback = {}) override;
+ WriterID writer_id() const override;
+ uint64_t written() const override {
+ return protobuf_stream_writer_.written();
+ }
+
+ void ResetChunkForTesting() {
+ cur_chunk_ = SharedMemoryABI::Chunk();
+ cur_chunk_packet_count_inflated_ = false;
+ }
+ bool drop_packets_for_testing() const { return drop_packets_; }
+
+ private:
+ TraceWriterImpl(const TraceWriterImpl&) = delete;
+ TraceWriterImpl& operator=(const TraceWriterImpl&) = delete;
+
+ // ScatteredStreamWriter::Delegate implementation.
+ protozero::ContiguousMemoryRange GetNewBuffer() override;
+ uint8_t* AnnotatePatch(uint8_t*) override;
+
+ // MessageFinalizationListener implementation.
+ void OnMessageFinalized(protozero::Message*) override;
+
+ // Writes the size of the current fragment into the chunk.
+ //
+ // The size of nested messages inside TracePacket is written by
+ // by the user, but the size of the TracePacket fragments is written by
+ // TraceWriterImpl.
+ void FinalizeFragmentIfRequired();
+
+ // Returns |cur_chunk_| (for which is_valid() must be true) to the
+ // |shmem_arbiter|.
+ void ReturnCompletedChunk();
+
+ // The per-producer arbiter that coordinates access to the shared memory
+ // buffer from several threads.
+ SharedMemoryArbiterImpl* const shmem_arbiter_;
+
+ // ID of the current writer.
+ const WriterID id_;
+
+ // This is copied into the commit request by SharedMemoryArbiter. See comments
+ // in data_source_config.proto for |target_buffer|. If this is a reservation
+ // for a buffer ID in case of a startup trace writer, SharedMemoryArbiterImpl
+ // will also translate the reservation ID to the actual buffer ID.
+ const MaybeUnboundBufferID target_buffer_;
+
+ // Whether GetNewChunk() should stall or return an invalid chunk if the SMB is
+ // exhausted.
+ const BufferExhaustedPolicy buffer_exhausted_policy_;
+
+ // Monotonic (% wrapping) sequence id of the chunk. Together with the WriterID
+ // this allows the Service to reconstruct the linear sequence of packets.
+ ChunkID next_chunk_id_ = 0;
+
+ // The chunk we are holding onto (if any).
+ SharedMemoryABI::Chunk cur_chunk_;
+
+ // Passed to protozero message to write directly into |cur_chunk_|. It
+ // keeps track of the write pointer. It calls us back (GetNewBuffer()) when
+ // |cur_chunk_| is filled.
+ protozero::ScatteredStreamWriter protobuf_stream_writer_;
+
+ // The packet returned via NewTracePacket(). Its owned by this class,
+ // TracePacketHandle has just a pointer to it.
+ //
+ // The caller of NewTracePacket can use TakeStreamWriter() and use the stream
+ // writer directly: in that case:
+ // * cur_packet_->size() is not up to date. Only the stream writer has the
+ // correct information.
+ // * cur_packet_->nested_message() is always nullptr.
+ // * cur_packet_->size_field() is still used to track the start of the current
+ // fragment.
+ std::unique_ptr<protozero::RootMessage<protos::pbzero::TracePacket>>
+ cur_packet_;
+
+ // The start address of |cur_packet_| within |cur_chunk_|. Used to figure out
+ // fragments sizes when a TracePacket write is interrupted by GetNewBuffer().
+ uint8_t* cur_fragment_start_ = nullptr;
+
+ // true if we received a call to GetNewBuffer() after NewTracePacket(),
+ // false if GetNewBuffer() happened during NewTracePacket() prologue, while
+ // starting the TracePacket header.
+ bool fragmenting_packet_ = false;
+
+ // Set to |true| when the current chunk contains the maximum number of packets
+ // a chunk can contain. When this is |true|, the next packet requires starting
+ // a new chunk.
+ bool reached_max_packets_per_chunk_ = false;
+
+ // If we fail to acquire a new chunk when the arbiter operates in
+ // SharedMemory::BufferExhaustedPolicy::kDrop mode, the trace writer enters a
+ // mode in which data is written to a local garbage chunk and dropped.
+ bool drop_packets_ = false;
+
+ // Whether the trace writer should try to acquire a new chunk from the SMB
+ // when the next TracePacket is started because it filled the garbage chunk at
+ // least once since the last attempt.
+ bool retry_new_chunk_after_packet_ = false;
+
+ // Set to true if `cur_chunk_` has a packet counter that's inflated by one.
+ // The count may be inflated to convince the tracing service scraping logic
+ // that the last packet has been completed. When this is true, cur_chunk_
+ // should have at least `kExtraRoomForInflatedPacket` bytes free.
+ bool cur_chunk_packet_count_inflated_ = false;
+
+ // Points to the size field of the still open fragment we're writing to the
+ // current chunk. If the chunk was already returned, this is reset to
+ // |nullptr|. If the fragment is finalized, this is reset to |nullptr|.
+ //
+ // Note: for nested messages the field is tracked somewhere else
+ // (protozero::Message::size_field_ or PerfettoPbMsg::size_field). For the
+ // root message, protozero::Message::size_field_ is nullptr and this is used
+ // instead. This is because at the root level we deal with fragments, not
+ // logical messages.
+ uint8_t* cur_fragment_size_field_ = nullptr;
+
+ // When a packet is fragmented across different chunks, the |size_field| of
+ // the outstanding nested protobuf messages is redirected onto Patch entries
+ // in this list at the time the Chunk is returned (because at that point we
+ // have to release the ownership of the current Chunk). This list will be
+ // later sent out-of-band to the tracing service, who will patch the required
+ // chunks, if they are still around.
+ PatchList patch_list_;
+
+ // PID of the process that created the trace writer. Used for a DCHECK that
+ // aims to detect unsupported process forks while tracing.
+ const base::PlatformProcessId process_id_;
+
+ // True for the first packet on sequence. See the comment for
+ // TracePacket.first_packet_on_sequence for more details.
+ bool first_packet_on_sequence_ = true;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/core/shared_memory_arbiter_impl.h"
+
+#include <algorithm>
+#include <limits>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/commit_data_request.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "src/tracing/core/null_trace_writer.h"
+// gen_amalgamated expanded: #include "src/tracing/core/trace_writer_impl.h"
+
+namespace perfetto {
+
+using Chunk = SharedMemoryABI::Chunk;
+
+namespace {
+static_assert(sizeof(BufferID) == sizeof(uint16_t),
+ "The MaybeUnboundBufferID logic requires BufferID not to grow "
+ "above uint16_t.");
+
+MaybeUnboundBufferID MakeTargetBufferIdForReservation(uint16_t reservation_id) {
+ // Reservation IDs are stored in the upper bits.
+ PERFETTO_CHECK(reservation_id > 0);
+ return static_cast<MaybeUnboundBufferID>(reservation_id) << 16;
+}
+
+bool IsReservationTargetBufferId(MaybeUnboundBufferID buffer_id) {
+ return (buffer_id >> 16) > 0;
+}
+} // namespace
+
+// static
+SharedMemoryABI::PageLayout SharedMemoryArbiterImpl::default_page_layout =
+ SharedMemoryABI::PageLayout::kPageDiv1;
+
+// static
+std::unique_ptr<SharedMemoryArbiter> SharedMemoryArbiter::CreateInstance(
+ SharedMemory* shared_memory,
+ size_t page_size,
+ ShmemMode mode,
+ TracingService::ProducerEndpoint* producer_endpoint,
+ base::TaskRunner* task_runner) {
+ return std::unique_ptr<SharedMemoryArbiterImpl>(new SharedMemoryArbiterImpl(
+ shared_memory->start(), shared_memory->size(), mode, page_size,
+ producer_endpoint, task_runner));
+}
+
+// static
+std::unique_ptr<SharedMemoryArbiter> SharedMemoryArbiter::CreateUnboundInstance(
+ SharedMemory* shared_memory,
+ size_t page_size,
+ ShmemMode mode) {
+ return std::unique_ptr<SharedMemoryArbiterImpl>(new SharedMemoryArbiterImpl(
+ shared_memory->start(), shared_memory->size(), mode, page_size,
+ /*producer_endpoint=*/nullptr, /*task_runner=*/nullptr));
+}
+
+SharedMemoryArbiterImpl::SharedMemoryArbiterImpl(
+ void* start,
+ size_t size,
+ ShmemMode mode,
+ size_t page_size,
+ TracingService::ProducerEndpoint* producer_endpoint,
+ base::TaskRunner* task_runner)
+ : producer_endpoint_(producer_endpoint),
+ use_shmem_emulation_(mode == ShmemMode::kShmemEmulation),
+ task_runner_(task_runner),
+ shmem_abi_(reinterpret_cast<uint8_t*>(start), size, page_size, mode),
+ active_writer_ids_(kMaxWriterID),
+ fully_bound_(task_runner && producer_endpoint),
+ was_always_bound_(fully_bound_),
+ weak_ptr_factory_(this) {}
+
+Chunk SharedMemoryArbiterImpl::GetNewChunk(
+ const SharedMemoryABI::ChunkHeader& header,
+ BufferExhaustedPolicy buffer_exhausted_policy) {
+ int stall_count = 0;
+ unsigned stall_interval_us = 0;
+ bool task_runner_runs_on_current_thread = false;
+ static const unsigned kMaxStallIntervalUs = 100000;
+ static const int kLogAfterNStalls = 3;
+ static const int kFlushCommitsAfterEveryNStalls = 2;
+ static const int kAssertAtNStalls = 200;
+
+ for (;;) {
+ // TODO(primiano): Probably this lock is not really required and this code
+ // could be rewritten leveraging only the Try* atomic operations in
+ // SharedMemoryABI. But let's not be too adventurous for the moment.
+ {
+ std::unique_lock<std::mutex> scoped_lock(lock_);
+
+ // If ever unbound, we do not support stalling. In theory, we could
+ // support stalling for TraceWriters created after the arbiter and startup
+ // buffer reservations were bound, but to avoid raciness between the
+ // creation of startup writers and binding, we categorically forbid kStall
+ // mode.
+ PERFETTO_DCHECK(was_always_bound_ ||
+ buffer_exhausted_policy == BufferExhaustedPolicy::kDrop);
+
+ task_runner_runs_on_current_thread =
+ task_runner_ && task_runner_->RunsTasksOnCurrentThread();
+
+ // If more than half of the SMB.size() is filled with completed chunks for
+ // which we haven't notified the service yet (i.e. they are still enqueued
+ // in |commit_data_req_|), force a synchronous CommitDataRequest() even if
+ // we acquire a chunk, to reduce the likeliness of stalling the writer.
+ //
+ // We can only do this if we're writing on the same thread that we access
+ // the producer endpoint on, since we cannot notify the producer endpoint
+ // to commit synchronously on a different thread. Attempting to flush
+ // synchronously on another thread will lead to subtle bugs caused by
+ // out-of-order commit requests (crbug.com/919187#c28).
+ bool should_commit_synchronously =
+ task_runner_runs_on_current_thread &&
+ buffer_exhausted_policy == BufferExhaustedPolicy::kStall &&
+ commit_data_req_ && bytes_pending_commit_ >= shmem_abi_.size() / 2;
+
+ const size_t initial_page_idx = page_idx_;
+ for (size_t i = 0; i < shmem_abi_.num_pages(); i++) {
+ page_idx_ = (initial_page_idx + i) % shmem_abi_.num_pages();
+ bool is_new_page = false;
+
+ // TODO(primiano): make the page layout dynamic.
+ auto layout = SharedMemoryArbiterImpl::default_page_layout;
+
+ if (shmem_abi_.is_page_free(page_idx_)) {
+ // TODO(primiano): Use the |size_hint| here to decide the layout.
+ is_new_page = shmem_abi_.TryPartitionPage(page_idx_, layout);
+ }
+ uint32_t free_chunks;
+ if (is_new_page) {
+ free_chunks = (1 << SharedMemoryABI::kNumChunksForLayout[layout]) - 1;
+ } else {
+ free_chunks = shmem_abi_.GetFreeChunks(page_idx_);
+ }
+
+ for (uint32_t chunk_idx = 0; free_chunks;
+ chunk_idx++, free_chunks >>= 1) {
+ if (!(free_chunks & 1))
+ continue;
+ // We found a free chunk.
+ Chunk chunk = shmem_abi_.TryAcquireChunkForWriting(
+ page_idx_, chunk_idx, &header);
+ if (!chunk.is_valid())
+ continue;
+ if (stall_count > kLogAfterNStalls) {
+ PERFETTO_LOG("Recovered from stall after %d iterations",
+ stall_count);
+ }
+
+ if (should_commit_synchronously) {
+ // We can't flush while holding the lock.
+ scoped_lock.unlock();
+ FlushPendingCommitDataRequests();
+ return chunk;
+ } else {
+ return chunk;
+ }
+ }
+ }
+ } // scoped_lock
+
+ if (buffer_exhausted_policy == BufferExhaustedPolicy::kDrop) {
+ PERFETTO_DLOG("Shared memory buffer exhausted, returning invalid Chunk!");
+ return Chunk();
+ }
+
+ // Stalling is not supported if we were ever unbound (see earlier comment).
+ PERFETTO_CHECK(was_always_bound_);
+
+ // All chunks are taken (either kBeingWritten by us or kBeingRead by the
+ // Service).
+ if (stall_count++ == kLogAfterNStalls) {
+ PERFETTO_LOG("Shared memory buffer overrun! Stalling");
+ }
+
+ if (stall_count == kAssertAtNStalls) {
+ PERFETTO_FATAL(
+ "Shared memory buffer max stall count exceeded; possible deadlock");
+ }
+
+ // If the IPC thread itself is stalled because the current process has
+ // filled up the SMB, we need to make sure that the service can process and
+ // purge the chunks written by our process, by flushing any pending commit
+ // requests. Because other threads in our process can continue to
+ // concurrently grab, fill and commit any chunks purged by the service, it
+ // is possible that the SMB remains full and the IPC thread remains stalled,
+ // needing to flush the concurrently queued up commits again. This is
+ // particularly likely with in-process perfetto service where the IPC thread
+ // is the service thread. To avoid remaining stalled forever in such a
+ // situation, we attempt to flush periodically after every N stalls.
+ if (stall_count % kFlushCommitsAfterEveryNStalls == 0 &&
+ task_runner_runs_on_current_thread) {
+ // TODO(primiano): sending the IPC synchronously is a temporary workaround
+ // until the backpressure logic in probes_producer is sorted out. Until
+ // then the risk is that we stall the message loop waiting for the tracing
+ // service to consume the shared memory buffer (SMB) and, for this reason,
+ // never run the task that tells the service to purge the SMB. This must
+ // happen iff we are on the IPC thread, not doing this will cause
+ // deadlocks, doing this on the wrong thread causes out-of-order data
+ // commits (crbug.com/919187#c28).
+ FlushPendingCommitDataRequests();
+ } else {
+ base::SleepMicroseconds(stall_interval_us);
+ stall_interval_us =
+ std::min(kMaxStallIntervalUs, (stall_interval_us + 1) * 8);
+ }
+ }
+}
+
+void SharedMemoryArbiterImpl::ReturnCompletedChunk(
+ Chunk chunk,
+ MaybeUnboundBufferID target_buffer,
+ PatchList* patch_list) {
+ PERFETTO_DCHECK(chunk.is_valid());
+ const WriterID writer_id = chunk.writer_id();
+ UpdateCommitDataRequest(std::move(chunk), writer_id, target_buffer,
+ patch_list);
+}
+
+void SharedMemoryArbiterImpl::SendPatches(WriterID writer_id,
+ MaybeUnboundBufferID target_buffer,
+ PatchList* patch_list) {
+ PERFETTO_DCHECK(!patch_list->empty() && patch_list->front().is_patched());
+ UpdateCommitDataRequest(Chunk(), writer_id, target_buffer, patch_list);
+}
+
+void SharedMemoryArbiterImpl::UpdateCommitDataRequest(
+ Chunk chunk,
+ WriterID writer_id,
+ MaybeUnboundBufferID target_buffer,
+ PatchList* patch_list) {
+ // Note: chunk will be invalid if the call came from SendPatches().
+ base::TaskRunner* task_runner_to_post_delayed_callback_on = nullptr;
+ // The delay with which the flush will be posted.
+ uint32_t flush_delay_ms = 0;
+ base::WeakPtr<SharedMemoryArbiterImpl> weak_this;
+ {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+
+ if (!commit_data_req_) {
+ commit_data_req_.reset(new CommitDataRequest());
+
+ // Flushing the commit is only supported while we're |fully_bound_|. If we
+ // aren't, we'll flush when |fully_bound_| is updated.
+ if (fully_bound_ && !delayed_flush_scheduled_) {
+ weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_to_post_delayed_callback_on = task_runner_;
+ flush_delay_ms = batch_commits_duration_ms_;
+ delayed_flush_scheduled_ = true;
+ }
+ }
+
+ CommitDataRequest::ChunksToMove* ctm = nullptr; // Set if chunk is valid.
+ // If a valid chunk is specified, return it and attach it to the request.
+ if (chunk.is_valid()) {
+ PERFETTO_DCHECK(chunk.writer_id() == writer_id);
+ uint8_t chunk_idx = chunk.chunk_idx();
+ bytes_pending_commit_ += chunk.size();
+ size_t page_idx;
+
+ ctm = commit_data_req_->add_chunks_to_move();
+ // If the chunk needs patching, it should not be marked as complete yet,
+ // because this would indicate to the service that the producer will not
+ // be writing to it anymore, while the producer might still apply patches
+ // to the chunk later on. In particular, when re-reading (e.g. because of
+ // periodic scraping) a completed chunk, the service expects the flags of
+ // that chunk not to be removed between reads. So, let's say the producer
+ // marked the chunk as complete here and the service then read it for the
+ // first time. If the producer then fully patched the chunk, thus removing
+ // the kChunkNeedsPatching flag, and the service re-read the chunk after
+ // the patching, the service would be thrown off by the removed flag.
+ if (direct_patching_enabled_ &&
+ (chunk.GetPacketCountAndFlags().second &
+ SharedMemoryABI::ChunkHeader::kChunkNeedsPatching)) {
+ page_idx = shmem_abi_.GetPageAndChunkIndex(std::move(chunk)).first;
+ } else {
+ // If the chunk doesn't need patching, we can mark it as complete
+ // immediately. This allows the service to read it in full while
+ // scraping, which would not be the case if the chunk was left in a
+ // kChunkBeingWritten state.
+ page_idx = shmem_abi_.ReleaseChunkAsComplete(std::move(chunk));
+ }
+
+ // DO NOT access |chunk| after this point, it has been std::move()-d
+ // above.
+ ctm->set_page(static_cast<uint32_t>(page_idx));
+ ctm->set_chunk(chunk_idx);
+ ctm->set_target_buffer(target_buffer);
+ }
+
+ // Process the completed patches for previous chunks from the |patch_list|.
+ CommitDataRequest::ChunkToPatch* last_patch_req = nullptr;
+ while (!patch_list->empty() && patch_list->front().is_patched()) {
+ Patch curr_patch = patch_list->front();
+ patch_list->pop_front();
+ // Patches for the same chunk are contiguous in the |patch_list|. So, to
+ // determine if there are any other patches that apply to the chunk that
+ // is being patched, check if the next patch in the |patch_list| applies
+ // to the same chunk.
+ bool chunk_needs_more_patching =
+ !patch_list->empty() &&
+ patch_list->front().chunk_id == curr_patch.chunk_id;
+
+ if (direct_patching_enabled_ &&
+ TryDirectPatchLocked(writer_id, curr_patch,
+ chunk_needs_more_patching)) {
+ continue;
+ }
+
+ // The chunk that this patch applies to has already been released to the
+ // service, so it cannot be patches here. Add the patch to the commit data
+ // request, so that it can be sent to the service and applied there.
+ if (!last_patch_req ||
+ last_patch_req->chunk_id() != curr_patch.chunk_id) {
+ last_patch_req = commit_data_req_->add_chunks_to_patch();
+ last_patch_req->set_writer_id(writer_id);
+ last_patch_req->set_chunk_id(curr_patch.chunk_id);
+ last_patch_req->set_target_buffer(target_buffer);
+ }
+ auto* patch = last_patch_req->add_patches();
+ patch->set_offset(curr_patch.offset);
+ patch->set_data(&curr_patch.size_field[0], curr_patch.size_field.size());
+ }
+
+ // Patches are enqueued in the |patch_list| in order and are notified to
+ // the service when the chunk is returned. The only case when the current
+ // patch list is incomplete is if there is an unpatched entry at the head of
+ // the |patch_list| that belongs to the same ChunkID as the last one we are
+ // about to send to the service.
+ if (last_patch_req && !patch_list->empty() &&
+ patch_list->front().chunk_id == last_patch_req->chunk_id()) {
+ last_patch_req->set_has_more_patches(true);
+ }
+
+ // If the buffer is filling up or if we are given a patch for a chunk
+ // that was already sent to the service, we don't want to wait for the next
+ // delayed flush to happen and we flush immediately. Otherwise, if we
+ // accumulate the patch and a crash occurs before the patch is sent, the
+ // service will not know of the patch and won't be able to reconstruct the
+ // trace.
+ if (fully_bound_ &&
+ (last_patch_req || bytes_pending_commit_ >= shmem_abi_.size() / 2)) {
+ weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_to_post_delayed_callback_on = task_runner_;
+ flush_delay_ms = 0;
+ }
+ } // scoped_lock(lock_)
+
+ // We shouldn't post tasks while locked.
+ // |task_runner_to_post_delayed_callback_on| remains valid after unlocking,
+ // because |task_runner_| is never reset.
+ if (task_runner_to_post_delayed_callback_on) {
+ task_runner_to_post_delayed_callback_on->PostDelayedTask(
+ [weak_this] {
+ if (!weak_this)
+ return;
+ {
+ std::lock_guard<std::mutex> scoped_lock(weak_this->lock_);
+ // Clear |delayed_flush_scheduled_|, allowing the next call to
+ // UpdateCommitDataRequest to start another batching period.
+ weak_this->delayed_flush_scheduled_ = false;
+ }
+ weak_this->FlushPendingCommitDataRequests();
+ },
+ flush_delay_ms);
+ }
+}
+
+bool SharedMemoryArbiterImpl::TryDirectPatchLocked(
+ WriterID writer_id,
+ const Patch& patch,
+ bool chunk_needs_more_patching) {
+ // Search the chunks that are being batched in |commit_data_req_| for a chunk
+ // that needs patching and that matches the provided |writer_id| and
+ // |patch.chunk_id|. Iterate |commit_data_req_| in reverse, since
+ // |commit_data_req_| is appended to at the end with newly-returned chunks,
+ // and patches are more likely to apply to chunks that have been returned
+ // recently.
+ SharedMemoryABI::Chunk chunk;
+ bool chunk_found = false;
+ auto& chunks_to_move = commit_data_req_->chunks_to_move();
+ for (auto ctm_it = chunks_to_move.rbegin(); ctm_it != chunks_to_move.rend();
+ ++ctm_it) {
+ uint32_t layout = shmem_abi_.GetPageLayout(ctm_it->page());
+ auto chunk_state =
+ shmem_abi_.GetChunkStateFromLayout(layout, ctm_it->chunk());
+ // Note: the subset of |commit_data_req_| chunks that still need patching is
+ // also the subset of chunks that are still being written to. The rest of
+ // the chunks in |commit_data_req_| do not need patching and have already
+ // been marked as complete.
+ if (chunk_state != SharedMemoryABI::kChunkBeingWritten)
+ continue;
+
+ chunk =
+ shmem_abi_.GetChunkUnchecked(ctm_it->page(), layout, ctm_it->chunk());
+ if (chunk.writer_id() == writer_id &&
+ chunk.header()->chunk_id.load(std::memory_order_relaxed) ==
+ patch.chunk_id) {
+ chunk_found = true;
+ break;
+ }
+ }
+
+ if (!chunk_found) {
+ // The chunk has already been committed to the service and the patch cannot
+ // be applied in the producer.
+ return false;
+ }
+
+ // Apply the patch.
+ size_t page_idx;
+ uint8_t chunk_idx;
+ std::tie(page_idx, chunk_idx) = shmem_abi_.GetPageAndChunkIndex(chunk);
+ PERFETTO_DCHECK(shmem_abi_.GetChunkState(page_idx, chunk_idx) ==
+ SharedMemoryABI::ChunkState::kChunkBeingWritten);
+ auto chunk_begin = chunk.payload_begin();
+ uint8_t* ptr = chunk_begin + patch.offset;
+ PERFETTO_CHECK(ptr <= chunk.end() - SharedMemoryABI::kPacketHeaderSize);
+ // DCHECK that we are writing into a zero-filled size field and not into
+ // valid data. It relies on ScatteredStreamWriter::ReserveBytes() to
+ // zero-fill reservations in debug builds.
+ const char zero[SharedMemoryABI::kPacketHeaderSize]{};
+ PERFETTO_DCHECK(memcmp(ptr, &zero, SharedMemoryABI::kPacketHeaderSize) == 0);
+
+ memcpy(ptr, &patch.size_field[0], SharedMemoryABI::kPacketHeaderSize);
+
+ if (!chunk_needs_more_patching) {
+ // Mark that the chunk doesn't need more patching and mark it as complete,
+ // as the producer will not write to it anymore. This allows the service to
+ // read the chunk in full while scraping, which would not be the case if the
+ // chunk was left in a kChunkBeingWritten state.
+ chunk.ClearNeedsPatchingFlag();
+ shmem_abi_.ReleaseChunkAsComplete(std::move(chunk));
+ }
+
+ return true;
+}
+
+void SharedMemoryArbiterImpl::SetBatchCommitsDuration(
+ uint32_t batch_commits_duration_ms) {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ batch_commits_duration_ms_ = batch_commits_duration_ms;
+}
+
+bool SharedMemoryArbiterImpl::EnableDirectSMBPatching() {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ if (!direct_patching_supported_by_service_) {
+ return false;
+ }
+
+ return direct_patching_enabled_ = true;
+}
+
+void SharedMemoryArbiterImpl::SetDirectSMBPatchingSupportedByService() {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ direct_patching_supported_by_service_ = true;
+}
+
+// This function is quite subtle. When making changes keep in mind these two
+// challenges:
+// 1) If the producer stalls and we happen to be on the |task_runner_| IPC
+// thread (or, for in-process cases, on the same thread where
+// TracingServiceImpl lives), the CommitData() call must be synchronous and
+// not posted, to avoid deadlocks.
+// 2) When different threads hit this function, we must guarantee that we don't
+// accidentally make commits out of order. See commit 4e4fe8f56ef and
+// crbug.com/919187 for more context.
+void SharedMemoryArbiterImpl::FlushPendingCommitDataRequests(
+ std::function<void()> callback) {
+ std::unique_ptr<CommitDataRequest> req;
+ {
+ std::unique_lock<std::mutex> scoped_lock(lock_);
+
+ // Flushing is only supported while |fully_bound_|, and there may still be
+ // unbound startup trace writers. If so, skip the commit for now - it'll be
+ // done when |fully_bound_| is updated.
+ if (!fully_bound_) {
+ if (callback)
+ pending_flush_callbacks_.push_back(callback);
+ return;
+ }
+
+ // May be called by TraceWriterImpl on any thread.
+ base::TaskRunner* task_runner = task_runner_;
+ if (!task_runner->RunsTasksOnCurrentThread()) {
+ // We shouldn't post a task while holding a lock. |task_runner| remains
+ // valid after unlocking, because |task_runner_| is never reset.
+ scoped_lock.unlock();
+
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner->PostTask([weak_this, callback] {
+ if (weak_this)
+ weak_this->FlushPendingCommitDataRequests(std::move(callback));
+ });
+ return;
+ }
+
+ // |commit_data_req_| could have become a nullptr, for example when a forced
+ // sync flush happens in GetNewChunk().
+ if (commit_data_req_) {
+ // Make sure any placeholder buffer IDs from StartupWriters are replaced
+ // before sending the request.
+ bool all_placeholders_replaced =
+ ReplaceCommitPlaceholderBufferIdsLocked();
+ // We're |fully_bound_|, thus all writers are bound and all placeholders
+ // should have been replaced.
+ PERFETTO_DCHECK(all_placeholders_replaced);
+
+ // In order to allow patching in the producer we delay the kChunkComplete
+ // transition and keep batched chunks in the kChunkBeingWritten state.
+ // Since we are about to notify the service of all batched chunks, it will
+ // not be possible to apply any more patches to them and we need to move
+ // them to kChunkComplete - otherwise the service won't look at them.
+ for (auto& ctm : *commit_data_req_->mutable_chunks_to_move()) {
+ uint32_t layout = shmem_abi_.GetPageLayout(ctm.page());
+ auto chunk_state =
+ shmem_abi_.GetChunkStateFromLayout(layout, ctm.chunk());
+ // Note: the subset of |commit_data_req_| chunks that still need
+ // patching is also the subset of chunks that are still being written
+ // to. The rest of the chunks in |commit_data_req_| do not need patching
+ // and have already been marked as complete.
+ if (chunk_state == SharedMemoryABI::kChunkBeingWritten) {
+ auto chunk =
+ shmem_abi_.GetChunkUnchecked(ctm.page(), layout, ctm.chunk());
+ shmem_abi_.ReleaseChunkAsComplete(std::move(chunk));
+ }
+
+ if (use_shmem_emulation_) {
+ // When running in the emulation mode:
+ // 1. serialize the chunk data to |ctm| as we won't modify the chunk
+ // anymore.
+ // 2. free the chunk as the service won't be able to do this.
+ auto chunk =
+ shmem_abi_.GetChunkUnchecked(ctm.page(), layout, ctm.chunk());
+ PERFETTO_CHECK(chunk.is_valid());
+ ctm.set_data(chunk.begin(), chunk.size());
+ shmem_abi_.ReleaseChunkAsFree(std::move(chunk));
+ }
+ }
+
+ req = std::move(commit_data_req_);
+ bytes_pending_commit_ = 0;
+ }
+ } // scoped_lock
+
+ if (req) {
+ producer_endpoint_->CommitData(*req, callback);
+ } else if (callback) {
+ // If |req| was nullptr, it means that an enqueued deferred commit was
+ // executed just before this. At this point send an empty commit request
+ // to the service, just to linearize with it and give the guarantee to the
+ // caller that the data has been flushed into the service.
+ producer_endpoint_->CommitData(CommitDataRequest(), std::move(callback));
+ }
+}
+
+bool SharedMemoryArbiterImpl::TryShutdown() {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ did_shutdown_ = true;
+ // Shutdown is safe if there are no active trace writers for this arbiter.
+ return active_writer_ids_.IsEmpty();
+}
+
+std::unique_ptr<TraceWriter> SharedMemoryArbiterImpl::CreateTraceWriter(
+ BufferID target_buffer,
+ BufferExhaustedPolicy buffer_exhausted_policy) {
+ PERFETTO_CHECK(target_buffer > 0);
+ return CreateTraceWriterInternal(target_buffer, buffer_exhausted_policy);
+}
+
+std::unique_ptr<TraceWriter> SharedMemoryArbiterImpl::CreateStartupTraceWriter(
+ uint16_t target_buffer_reservation_id) {
+ return CreateTraceWriterInternal(
+ MakeTargetBufferIdForReservation(target_buffer_reservation_id),
+ BufferExhaustedPolicy::kDrop);
+}
+
+void SharedMemoryArbiterImpl::BindToProducerEndpoint(
+ TracingService::ProducerEndpoint* producer_endpoint,
+ base::TaskRunner* task_runner) {
+ PERFETTO_DCHECK(producer_endpoint && task_runner);
+ PERFETTO_DCHECK(task_runner->RunsTasksOnCurrentThread());
+
+ bool should_flush = false;
+ std::function<void()> flush_callback;
+ {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ PERFETTO_CHECK(!fully_bound_);
+ PERFETTO_CHECK(!producer_endpoint_ && !task_runner_);
+
+ producer_endpoint_ = producer_endpoint;
+ task_runner_ = task_runner;
+
+ // Now that we're bound to a task runner, also reset the WeakPtrFactory to
+ // it. Because this code runs on the task runner, the factory's weak
+ // pointers will be valid on it.
+ weak_ptr_factory_.Reset(this);
+
+ // All writers registered so far should be startup trace writers, since
+ // the producer cannot feasibly know the target buffer for any future
+ // session yet.
+ for (const auto& entry : pending_writers_) {
+ PERFETTO_CHECK(IsReservationTargetBufferId(entry.second));
+ }
+
+ // If all buffer reservations are bound, we can flush pending commits.
+ if (UpdateFullyBoundLocked()) {
+ should_flush = true;
+ flush_callback = TakePendingFlushCallbacksLocked();
+ }
+ } // scoped_lock
+
+ // Attempt to flush any pending commits (and run pending flush callbacks). If
+ // there are none, this will have no effect. If we ended up in a race that
+ // changed |fully_bound_| back to false, the commit will happen once we become
+ // |fully_bound_| again.
+ if (should_flush)
+ FlushPendingCommitDataRequests(flush_callback);
+}
+
+void SharedMemoryArbiterImpl::BindStartupTargetBuffer(
+ uint16_t target_buffer_reservation_id,
+ BufferID target_buffer_id) {
+ PERFETTO_DCHECK(target_buffer_id > 0);
+
+ std::unique_lock<std::mutex> scoped_lock(lock_);
+
+ // We should already be bound to an endpoint.
+ PERFETTO_CHECK(producer_endpoint_);
+ PERFETTO_CHECK(task_runner_);
+ PERFETTO_CHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ BindStartupTargetBufferImpl(std::move(scoped_lock),
+ target_buffer_reservation_id, target_buffer_id);
+}
+
+void SharedMemoryArbiterImpl::AbortStartupTracingForReservation(
+ uint16_t target_buffer_reservation_id) {
+ std::unique_lock<std::mutex> scoped_lock(lock_);
+
+ // If we are already bound to an arbiter, we may need to flush after aborting
+ // the session, and thus should be running on the arbiter's task runner.
+ if (task_runner_ && !task_runner_->RunsTasksOnCurrentThread()) {
+ // We shouldn't post tasks while locked.
+ auto* task_runner = task_runner_;
+ scoped_lock.unlock();
+
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner->PostTask([weak_this, target_buffer_reservation_id]() {
+ if (!weak_this)
+ return;
+ weak_this->AbortStartupTracingForReservation(
+ target_buffer_reservation_id);
+ });
+ return;
+ }
+
+ // Bind the target buffer reservation to an invalid buffer (ID 0), so that
+ // existing commits, as well as future commits (of currently acquired chunks),
+ // will be released as free free by the service but otherwise ignored (i.e.
+ // not copied into any valid target buffer).
+ BindStartupTargetBufferImpl(std::move(scoped_lock),
+ target_buffer_reservation_id,
+ /*target_buffer_id=*/kInvalidBufferId);
+}
+
+void SharedMemoryArbiterImpl::BindStartupTargetBufferImpl(
+ std::unique_lock<std::mutex> scoped_lock,
+ uint16_t target_buffer_reservation_id,
+ BufferID target_buffer_id) {
+ // We should already be bound to an endpoint if the target buffer is valid.
+ PERFETTO_DCHECK((producer_endpoint_ && task_runner_) ||
+ target_buffer_id == kInvalidBufferId);
+
+ PERFETTO_DLOG("Binding startup target buffer reservation %" PRIu16
+ " to buffer %" PRIu16,
+ target_buffer_reservation_id, target_buffer_id);
+
+ MaybeUnboundBufferID reserved_id =
+ MakeTargetBufferIdForReservation(target_buffer_reservation_id);
+
+ bool should_flush = false;
+ std::function<void()> flush_callback;
+ std::vector<std::pair<WriterID, BufferID>> writers_to_register;
+
+ TargetBufferReservation& reservation =
+ target_buffer_reservations_[reserved_id];
+ PERFETTO_CHECK(!reservation.resolved);
+ reservation.resolved = true;
+ reservation.target_buffer = target_buffer_id;
+
+ // Collect trace writers associated with the reservation.
+ for (auto it = pending_writers_.begin(); it != pending_writers_.end();) {
+ if (it->second == reserved_id) {
+ // No need to register writers that have an invalid target buffer.
+ if (target_buffer_id != kInvalidBufferId) {
+ writers_to_register.push_back(
+ std::make_pair(it->first, target_buffer_id));
+ }
+ it = pending_writers_.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ // If all buffer reservations are bound, we can flush pending commits.
+ if (UpdateFullyBoundLocked()) {
+ should_flush = true;
+ flush_callback = TakePendingFlushCallbacksLocked();
+ }
+
+ scoped_lock.unlock();
+
+ // Register any newly bound trace writers with the service.
+ for (const auto& writer_and_target_buffer : writers_to_register) {
+ producer_endpoint_->RegisterTraceWriter(writer_and_target_buffer.first,
+ writer_and_target_buffer.second);
+ }
+
+ // Attempt to flush any pending commits (and run pending flush callbacks). If
+ // there are none, this will have no effect. If we ended up in a race that
+ // changed |fully_bound_| back to false, the commit will happen once we become
+ // |fully_bound_| again.
+ if (should_flush)
+ FlushPendingCommitDataRequests(flush_callback);
+}
+
+std::function<void()>
+SharedMemoryArbiterImpl::TakePendingFlushCallbacksLocked() {
+ if (pending_flush_callbacks_.empty())
+ return std::function<void()>();
+
+ std::vector<std::function<void()>> pending_flush_callbacks;
+ pending_flush_callbacks.swap(pending_flush_callbacks_);
+ // Capture the callback list into the lambda by copy.
+ return [pending_flush_callbacks]() {
+ for (auto& callback : pending_flush_callbacks)
+ callback();
+ };
+}
+
+void SharedMemoryArbiterImpl::NotifyFlushComplete(FlushRequestID req_id) {
+ base::TaskRunner* task_runner_to_commit_on = nullptr;
+
+ {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ // If a commit_data_req_ exists it means that somebody else already posted a
+ // FlushPendingCommitDataRequests() task.
+ if (!commit_data_req_) {
+ commit_data_req_.reset(new CommitDataRequest());
+
+ // Flushing the commit is only supported while we're |fully_bound_|. If we
+ // aren't, we'll flush when |fully_bound_| is updated.
+ if (fully_bound_)
+ task_runner_to_commit_on = task_runner_;
+ } else {
+ // If there is another request queued and that also contains is a reply
+ // to a flush request, reply with the highest id.
+ req_id = std::max(req_id, commit_data_req_->flush_request_id());
+ }
+ commit_data_req_->set_flush_request_id(req_id);
+ } // scoped_lock
+
+ // We shouldn't post tasks while locked. |task_runner_to_commit_on|
+ // remains valid after unlocking, because |task_runner_| is never reset.
+ if (task_runner_to_commit_on) {
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_to_commit_on->PostTask([weak_this] {
+ if (weak_this)
+ weak_this->FlushPendingCommitDataRequests();
+ });
+ }
+}
+
+std::unique_ptr<TraceWriter> SharedMemoryArbiterImpl::CreateTraceWriterInternal(
+ MaybeUnboundBufferID target_buffer,
+ BufferExhaustedPolicy buffer_exhausted_policy) {
+ WriterID id;
+ base::TaskRunner* task_runner_to_register_on = nullptr;
+
+ {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ if (did_shutdown_)
+ return std::unique_ptr<TraceWriter>(new NullTraceWriter());
+
+ id = active_writer_ids_.Allocate();
+ if (!id)
+ return std::unique_ptr<TraceWriter>(new NullTraceWriter());
+
+ PERFETTO_DCHECK(!pending_writers_.count(id));
+
+ if (IsReservationTargetBufferId(target_buffer)) {
+ // If the reservation is new, mark it as unbound in
+ // |target_buffer_reservations_|. Otherwise, if the reservation was
+ // already bound, choose the bound buffer ID now.
+ auto it_and_inserted = target_buffer_reservations_.insert(
+ {target_buffer, TargetBufferReservation()});
+ if (it_and_inserted.first->second.resolved)
+ target_buffer = it_and_inserted.first->second.target_buffer;
+ }
+
+ if (IsReservationTargetBufferId(target_buffer)) {
+ // The arbiter and/or startup buffer reservations are not bound yet, so
+ // buffer the registration of the writer until after we're bound.
+ pending_writers_[id] = target_buffer;
+
+ // Mark the arbiter as not fully bound, since we now have at least one
+ // unbound trace writer / target buffer reservation.
+ fully_bound_ = false;
+ was_always_bound_ = false;
+ } else if (target_buffer != kInvalidBufferId) {
+ // Trace writer is bound, so arbiter should be bound to an endpoint, too.
+ PERFETTO_CHECK(producer_endpoint_ && task_runner_);
+ task_runner_to_register_on = task_runner_;
+ }
+
+ // All trace writers must use kDrop policy if the arbiter ever becomes
+ // unbound.
+ bool uses_drop_policy =
+ buffer_exhausted_policy == BufferExhaustedPolicy::kDrop;
+ all_writers_have_drop_policy_ &= uses_drop_policy;
+ PERFETTO_DCHECK(fully_bound_ || uses_drop_policy);
+ PERFETTO_CHECK(fully_bound_ || all_writers_have_drop_policy_);
+ PERFETTO_CHECK(was_always_bound_ || uses_drop_policy);
+ } // scoped_lock
+
+ // We shouldn't post tasks while locked. |task_runner_to_register_on|
+ // remains valid after unlocking, because |task_runner_| is never reset.
+ if (task_runner_to_register_on) {
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_to_register_on->PostTask([weak_this, id, target_buffer] {
+ if (weak_this)
+ weak_this->producer_endpoint_->RegisterTraceWriter(id, target_buffer);
+ });
+ }
+
+ return std::unique_ptr<TraceWriter>(
+ new TraceWriterImpl(this, id, target_buffer, buffer_exhausted_policy));
+}
+
+void SharedMemoryArbiterImpl::ReleaseWriterID(WriterID id) {
+ base::TaskRunner* task_runner = nullptr;
+ {
+ std::lock_guard<std::mutex> scoped_lock(lock_);
+ active_writer_ids_.Free(id);
+
+ auto it = pending_writers_.find(id);
+ if (it != pending_writers_.end()) {
+ // Writer hasn't been bound yet and thus also not yet registered with the
+ // service.
+ pending_writers_.erase(it);
+ return;
+ }
+
+ // A trace writer from an aborted session may be destroyed before the
+ // arbiter is bound to a task runner. In that case, it was never registered
+ // with the service.
+ if (!task_runner_)
+ return;
+
+ task_runner = task_runner_;
+ } // scoped_lock
+
+ // We shouldn't post tasks while locked. |task_runner| remains valid after
+ // unlocking, because |task_runner_| is never reset.
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner->PostTask([weak_this, id] {
+ if (weak_this)
+ weak_this->producer_endpoint_->UnregisterTraceWriter(id);
+ });
+}
+
+bool SharedMemoryArbiterImpl::ReplaceCommitPlaceholderBufferIdsLocked() {
+ if (!commit_data_req_)
+ return true;
+
+ bool all_placeholders_replaced = true;
+ for (auto& chunk : *commit_data_req_->mutable_chunks_to_move()) {
+ if (!IsReservationTargetBufferId(chunk.target_buffer()))
+ continue;
+ const auto it = target_buffer_reservations_.find(chunk.target_buffer());
+ PERFETTO_DCHECK(it != target_buffer_reservations_.end());
+ if (!it->second.resolved) {
+ all_placeholders_replaced = false;
+ continue;
+ }
+ chunk.set_target_buffer(it->second.target_buffer);
+ }
+ for (auto& chunk : *commit_data_req_->mutable_chunks_to_patch()) {
+ if (!IsReservationTargetBufferId(chunk.target_buffer()))
+ continue;
+ const auto it = target_buffer_reservations_.find(chunk.target_buffer());
+ PERFETTO_DCHECK(it != target_buffer_reservations_.end());
+ if (!it->second.resolved) {
+ all_placeholders_replaced = false;
+ continue;
+ }
+ chunk.set_target_buffer(it->second.target_buffer);
+ }
+ return all_placeholders_replaced;
+}
+
+bool SharedMemoryArbiterImpl::UpdateFullyBoundLocked() {
+ if (!producer_endpoint_) {
+ PERFETTO_DCHECK(!fully_bound_);
+ return false;
+ }
+ // We're fully bound if all target buffer reservations have a valid associated
+ // BufferID.
+ fully_bound_ = std::none_of(
+ target_buffer_reservations_.begin(), target_buffer_reservations_.end(),
+ [](std::pair<MaybeUnboundBufferID, TargetBufferReservation> entry) {
+ return !entry.second.resolved;
+ });
+ if (!fully_bound_)
+ was_always_bound_ = false;
+ return fully_bound_;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/trace_packet.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_packet.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+
+TracePacket::TracePacket() = default;
+TracePacket::~TracePacket() = default;
+
+TracePacket::TracePacket(TracePacket&& other) noexcept {
+ *this = std::move(other);
+}
+
+TracePacket& TracePacket::operator=(TracePacket&& other) {
+ slices_ = std::move(other.slices_);
+ other.slices_.clear();
+ size_ = other.size_;
+ other.size_ = 0;
+ buffer_index_for_stats_ = other.buffer_index_for_stats_;
+ other.buffer_index_for_stats_ = 0;
+ return *this;
+}
+
+void TracePacket::AddSlice(Slice slice) {
+ size_ += slice.size;
+ slices_.push_back(std::move(slice));
+}
+
+void TracePacket::AddSlice(const void* start, size_t size) {
+ size_ += size;
+ slices_.emplace_back(start, size);
+}
+
+std::tuple<char*, size_t> TracePacket::GetProtoPreamble() {
+ using protozero::proto_utils::MakeTagLengthDelimited;
+ using protozero::proto_utils::WriteVarInt;
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(&preamble_[0]);
+
+ constexpr uint8_t tag = MakeTagLengthDelimited(kPacketFieldNumber);
+ static_assert(tag < 0x80, "TracePacket tag should fit in one byte");
+ *(ptr++) = tag;
+
+ ptr = WriteVarInt(size(), ptr);
+ size_t preamble_size = reinterpret_cast<uintptr_t>(ptr) -
+ reinterpret_cast<uintptr_t>(&preamble_[0]);
+ PERFETTO_DCHECK(preamble_size <= sizeof(preamble_));
+ return std::make_tuple(&preamble_[0], preamble_size);
+}
+
+std::string TracePacket::GetRawBytesForTesting() {
+ std::string data;
+ data.resize(size());
+ size_t pos = 0;
+ for (const Slice& slice : slices()) {
+ PERFETTO_CHECK(pos + slice.size <= data.size());
+ memcpy(&data[pos], slice.start, slice.size);
+ pos += slice.size;
+ }
+ return data;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/trace_writer_impl.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/core/trace_writer_impl.h"
+
+#include <string.h>
+
+#include <algorithm>
+#include <type_traits>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_annotations.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/root_message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/static_buffer.h"
+// gen_amalgamated expanded: #include "src/tracing/core/shared_memory_arbiter_impl.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+using protozero::proto_utils::kMessageLengthFieldSize;
+using protozero::proto_utils::WriteRedundantVarInt;
+using ChunkHeader = perfetto::SharedMemoryABI::ChunkHeader;
+
+namespace perfetto {
+
+namespace {
+constexpr size_t kPacketHeaderSize = SharedMemoryABI::kPacketHeaderSize;
+// The -1 is because we want to leave extra room to inflate the counter.
+constexpr size_t kMaxPacketsPerChunk = ChunkHeader::Packets::kMaxCount - 1;
+// When the packet count in a chunk is inflated, TraceWriter is always going to
+// leave this kExtraRoomForInflatedPacket bytes to write an empty trace packet
+// if it needs to.
+constexpr size_t kExtraRoomForInflatedPacket = 1;
+uint8_t g_garbage_chunk[1024];
+} // namespace
+
+TraceWriterImpl::TraceWriterImpl(SharedMemoryArbiterImpl* shmem_arbiter,
+ WriterID id,
+ MaybeUnboundBufferID target_buffer,
+ BufferExhaustedPolicy buffer_exhausted_policy)
+ : shmem_arbiter_(shmem_arbiter),
+ id_(id),
+ target_buffer_(target_buffer),
+ buffer_exhausted_policy_(buffer_exhausted_policy),
+ protobuf_stream_writer_(this),
+ process_id_(base::GetProcessId()) {
+ // TODO(primiano): we could handle the case of running out of TraceWriterID(s)
+ // more gracefully and always return a no-op TracePacket in NewTracePacket().
+ PERFETTO_CHECK(id_ != 0);
+
+ cur_packet_.reset(new protozero::RootMessage<protos::pbzero::TracePacket>());
+ cur_packet_->Finalize(); // To avoid the CHECK in NewTracePacket().
+}
+
+TraceWriterImpl::~TraceWriterImpl() {
+ if (cur_chunk_.is_valid()) {
+ cur_packet_->Finalize();
+ Flush();
+ }
+ // This call may cause the shared memory arbiter (and the underlying memory)
+ // to get asynchronously deleted if this was the last trace writer targeting
+ // the arbiter and the arbiter was marked for shutdown.
+ shmem_arbiter_->ReleaseWriterID(id_);
+}
+
+void TraceWriterImpl::ReturnCompletedChunk() {
+ PERFETTO_DCHECK(cur_chunk_.is_valid());
+ if (cur_chunk_packet_count_inflated_) {
+ uint8_t zero_size = 0;
+ static_assert(sizeof zero_size == kExtraRoomForInflatedPacket);
+ PERFETTO_CHECK(protobuf_stream_writer_.bytes_available() != 0);
+ protobuf_stream_writer_.WriteBytesUnsafe(&zero_size, sizeof zero_size);
+ cur_chunk_packet_count_inflated_ = false;
+ }
+ shmem_arbiter_->ReturnCompletedChunk(std::move(cur_chunk_), target_buffer_,
+ &patch_list_);
+}
+
+void TraceWriterImpl::Flush(std::function<void()> callback) {
+ // Flush() cannot be called in the middle of a TracePacket.
+ PERFETTO_CHECK(cur_packet_->is_finalized());
+ // cur_packet_ is finalized: that means that the size is correct for all the
+ // nested submessages. The root fragment size however is not handled by
+ // protozero::Message::Finalize() and must be filled here.
+ FinalizeFragmentIfRequired();
+
+ if (cur_chunk_.is_valid()) {
+ ReturnCompletedChunk();
+ } else {
+ // When in stall mode, all patches should have been returned with the last
+ // chunk, since the last packet was completed. In drop_packets_ mode, this
+ // may not be the case because the packet may have been fragmenting when
+ // SMB exhaustion occurred and |cur_chunk_| became invalid. In this case,
+ // drop_packets_ should be true.
+ PERFETTO_DCHECK(patch_list_.empty() || drop_packets_);
+ }
+
+ // Always issue the Flush request, even if there is nothing to flush, just
+ // for the sake of getting the callback posted back.
+ shmem_arbiter_->FlushPendingCommitDataRequests(callback);
+ protobuf_stream_writer_.Reset({nullptr, nullptr});
+}
+
+TraceWriterImpl::TracePacketHandle TraceWriterImpl::NewTracePacket() {
+ // If we hit this, the caller is calling NewTracePacket() without having
+ // finalized the previous packet.
+ PERFETTO_CHECK(cur_packet_->is_finalized());
+ // If we hit this, this trace writer was created in a different process. This
+ // likely means that the process forked while tracing was active, and the
+ // forked child process tried to emit a trace event. This is not supported, as
+ // it would lead to two processes writing to the same tracing SMB.
+ PERFETTO_DCHECK(process_id_ == base::GetProcessId());
+
+ // Before starting a new packet, make sure that the last fragment size has ben
+ // written correctly. The root fragment size is not written by
+ // protozero::Message::Finalize().
+ FinalizeFragmentIfRequired();
+
+ fragmenting_packet_ = false;
+
+ // Reserve space for the size of the message. Note: this call might re-enter
+ // into this class invoking GetNewBuffer() if there isn't enough space or if
+ // this is the very first call to NewTracePacket().
+ static_assert(kPacketHeaderSize == kMessageLengthFieldSize,
+ "The packet header must match the Message header size");
+
+ bool was_dropping_packets = drop_packets_;
+
+ // It doesn't make sense to begin a packet that is going to fragment
+ // immediately after (8 is just an arbitrary estimation on the minimum size of
+ // a realistic packet).
+ bool chunk_too_full =
+ protobuf_stream_writer_.bytes_available() < kPacketHeaderSize + 8;
+ if (chunk_too_full || reached_max_packets_per_chunk_ ||
+ retry_new_chunk_after_packet_) {
+ protobuf_stream_writer_.Reset(GetNewBuffer());
+ }
+
+ // Send any completed patches to the service to facilitate trace data
+ // recovery by the service. This should only happen when we're completing
+ // the first packet in a chunk which was a continuation from the previous
+ // chunk, i.e. at most once per chunk.
+ if (!patch_list_.empty() && patch_list_.front().is_patched()) {
+ shmem_arbiter_->SendPatches(id_, target_buffer_, &patch_list_);
+ }
+
+ cur_packet_->Reset(&protobuf_stream_writer_);
+ uint8_t* header = protobuf_stream_writer_.ReserveBytes(kPacketHeaderSize);
+ memset(header, 0, kPacketHeaderSize);
+ cur_fragment_size_field_ = header;
+
+ TracePacketHandle handle(cur_packet_.get());
+ cur_fragment_start_ = protobuf_stream_writer_.write_ptr();
+ fragmenting_packet_ = true;
+
+ if (PERFETTO_LIKELY(!drop_packets_)) {
+ uint16_t new_packet_count;
+ if (cur_chunk_packet_count_inflated_) {
+ new_packet_count =
+ cur_chunk_.header()->packets.load(std::memory_order_relaxed).count;
+ cur_chunk_packet_count_inflated_ = false;
+ } else {
+ new_packet_count = cur_chunk_.IncrementPacketCount();
+ }
+ reached_max_packets_per_chunk_ = new_packet_count == kMaxPacketsPerChunk;
+
+ if (PERFETTO_UNLIKELY(was_dropping_packets)) {
+ // We've succeeded to get a new chunk from the SMB after we entered
+ // drop_packets_ mode. Record a marker into the new packet to indicate the
+ // data loss.
+ cur_packet_->set_previous_packet_dropped(true);
+ }
+ }
+
+ if (PERFETTO_UNLIKELY(first_packet_on_sequence_)) {
+ cur_packet_->set_first_packet_on_sequence(true);
+ first_packet_on_sequence_ = false;
+ }
+
+ handle.set_finalization_listener(this);
+
+ return handle;
+}
+
+// Called by the Message. We can get here in two cases:
+// 1. In the middle of writing a Message,
+// when |fragmenting_packet_| == true. In this case we want to update the
+// chunk header with a partial packet and start a new partial packet in the
+// new chunk.
+// 2. While calling ReserveBytes() for the packet header in NewTracePacket().
+// In this case |fragmenting_packet_| == false and we just want a new chunk
+// without creating any fragments.
+protozero::ContiguousMemoryRange TraceWriterImpl::GetNewBuffer() {
+ if (fragmenting_packet_ && drop_packets_) {
+ // We can't write the remaining data of the fragmenting packet to a new
+ // chunk, because we have already lost some of its data in the garbage
+ // chunk. Thus, we will wrap around in the garbage chunk, wait until the
+ // current packet was completed, and then attempt to get a new chunk from
+ // the SMB again. Instead, if |drop_packets_| is true and
+ // |fragmenting_packet_| is false, we try to acquire a valid chunk because
+ // the SMB exhaustion might be resolved.
+ retry_new_chunk_after_packet_ = true;
+ cur_fragment_size_field_ = nullptr;
+ cur_fragment_start_ = &g_garbage_chunk[0];
+ return protozero::ContiguousMemoryRange{
+ &g_garbage_chunk[0], &g_garbage_chunk[0] + sizeof(g_garbage_chunk)};
+ }
+
+ // Attempt to grab the next chunk before finalizing the current one, so that
+ // we know whether we need to start dropping packets before writing the
+ // current packet fragment's header.
+ ChunkHeader::Packets packets = {};
+ if (fragmenting_packet_) {
+ packets.count = 1;
+ packets.flags = ChunkHeader::kFirstPacketContinuesFromPrevChunk;
+ }
+
+ // The memory order of the stores below doesn't really matter. This |header|
+ // is just a local temporary object. The GetNewChunk() call below will copy it
+ // into the shared buffer with the proper barriers.
+ ChunkHeader header = {};
+ header.writer_id.store(id_, std::memory_order_relaxed);
+ header.chunk_id.store(next_chunk_id_, std::memory_order_relaxed);
+ header.packets.store(packets, std::memory_order_relaxed);
+
+ SharedMemoryABI::Chunk new_chunk =
+ shmem_arbiter_->GetNewChunk(header, buffer_exhausted_policy_);
+ if (!new_chunk.is_valid()) {
+ // Shared memory buffer exhausted, switch into |drop_packets_| mode. We'll
+ // drop data until the garbage chunk has been filled once and then retry.
+
+ // If we started a packet in one of the previous (valid) chunks, we need to
+ // tell the service to discard it.
+ if (fragmenting_packet_) {
+ // We can only end up here if the previous chunk was a valid chunk,
+ // because we never try to acquire a new chunk in |drop_packets_| mode
+ // while fragmenting.
+ PERFETTO_DCHECK(!drop_packets_);
+
+ // Backfill the last fragment's header with an invalid size (too large),
+ // so that the service's TraceBuffer throws out the incomplete packet.
+ // It'll restart reading from the next chunk we submit.
+ WriteRedundantVarInt(SharedMemoryABI::kPacketSizeDropPacket,
+ cur_fragment_size_field_);
+
+ // Reset the size field, since we should not write the current packet's
+ // size anymore after this.
+ cur_fragment_size_field_ = nullptr;
+
+ // We don't set kLastPacketContinuesOnNextChunk or kChunkNeedsPatching on
+ // the last chunk, because its last fragment will be discarded anyway.
+ // However, the current packet fragment points to a valid |cur_chunk_| and
+ // may have non-finalized nested messages which will continue in the
+ // garbage chunk and currently still point into |cur_chunk_|. As we are
+ // about to return |cur_chunk_|, we need to invalidate the size fields of
+ // those nested messages. Normally we move them in the |patch_list_| (see
+ // below) but in this case, it doesn't make sense to send patches for a
+ // fragment that will be discarded for sure. Thus, we clean up any size
+ // field references into |cur_chunk_|.
+ for (auto* nested_msg = cur_packet_->nested_message(); nested_msg;
+ nested_msg = nested_msg->nested_message()) {
+ uint8_t* const cur_hdr = nested_msg->size_field();
+
+ // If this is false the protozero Message has already been instructed to
+ // write, upon Finalize(), its size into the patch list.
+ bool size_field_points_within_chunk =
+ cur_hdr >= cur_chunk_.payload_begin() &&
+ cur_hdr + kMessageLengthFieldSize <= cur_chunk_.end();
+
+ if (size_field_points_within_chunk)
+ nested_msg->set_size_field(nullptr);
+ }
+ } else if (!drop_packets_ && cur_fragment_size_field_) {
+ // If we weren't dropping packets before, we should indicate to the
+ // service that we're about to lose data. We do this by invalidating the
+ // size of the last packet in |cur_chunk_|. The service will record
+ // statistics about packets with kPacketSizeDropPacket size.
+ PERFETTO_DCHECK(cur_packet_->is_finalized());
+ PERFETTO_DCHECK(cur_chunk_.is_valid());
+
+ // |cur_fragment_size_field_| should point within |cur_chunk_|'s payload.
+ PERFETTO_DCHECK(cur_fragment_size_field_ >= cur_chunk_.payload_begin() &&
+ cur_fragment_size_field_ + kMessageLengthFieldSize <=
+ cur_chunk_.end());
+
+ WriteRedundantVarInt(SharedMemoryABI::kPacketSizeDropPacket,
+ cur_fragment_size_field_);
+ }
+
+ if (cur_chunk_.is_valid()) {
+ ReturnCompletedChunk();
+ }
+
+ drop_packets_ = true;
+ cur_chunk_ = SharedMemoryABI::Chunk(); // Reset to an invalid chunk.
+ cur_chunk_packet_count_inflated_ = false;
+ reached_max_packets_per_chunk_ = false;
+ retry_new_chunk_after_packet_ = false;
+ cur_fragment_size_field_ = nullptr;
+ cur_fragment_start_ = &g_garbage_chunk[0];
+
+ PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(&g_garbage_chunk,
+ sizeof(g_garbage_chunk),
+ "nobody reads the garbage chunk")
+ return protozero::ContiguousMemoryRange{
+ &g_garbage_chunk[0], &g_garbage_chunk[0] + sizeof(g_garbage_chunk)};
+ } // if (!new_chunk.is_valid())
+
+ PERFETTO_DCHECK(new_chunk.is_valid());
+
+ if (fragmenting_packet_) {
+ // We should not be fragmenting a packet after we exited drop_packets_ mode,
+ // because we only retry to get a new chunk when a fresh packet is started.
+ PERFETTO_DCHECK(!drop_packets_);
+
+ uint8_t* const wptr = protobuf_stream_writer_.write_ptr();
+ PERFETTO_DCHECK(wptr >= cur_fragment_start_);
+ uint32_t partial_size = static_cast<uint32_t>(wptr - cur_fragment_start_);
+ PERFETTO_DCHECK(partial_size < cur_chunk_.size());
+
+ // Backfill the packet header with the fragment size.
+ PERFETTO_DCHECK(partial_size > 0);
+ cur_chunk_.SetFlag(ChunkHeader::kLastPacketContinuesOnNextChunk);
+ WriteRedundantVarInt(partial_size, cur_fragment_size_field_);
+
+ // Descend in the stack of non-finalized nested submessages (if any) and
+ // detour their |size_field| into the |patch_list_|. At this point we have
+ // to release the chunk and they cannot write anymore into that.
+ for (auto* nested_msg = cur_packet_->nested_message(); nested_msg;
+ nested_msg = nested_msg->nested_message()) {
+ uint8_t* cur_hdr = nested_msg->size_field();
+
+ // If this is false the protozero Message has already been instructed to
+ // write, upon Finalize(), its size into the patch list.
+ bool size_field_points_within_chunk =
+ cur_hdr >= cur_chunk_.payload_begin() &&
+ cur_hdr + kMessageLengthFieldSize <= cur_chunk_.end();
+
+ if (size_field_points_within_chunk) {
+ cur_hdr = TraceWriterImpl::AnnotatePatch(cur_hdr);
+ nested_msg->set_size_field(cur_hdr);
+ } else {
+#if PERFETTO_DCHECK_IS_ON()
+ // Ensure that the size field of the message points to an element of the
+ // patch list.
+ auto patch_it = std::find_if(
+ patch_list_.begin(), patch_list_.end(),
+ [cur_hdr](const Patch& p) { return &p.size_field[0] == cur_hdr; });
+ PERFETTO_DCHECK(patch_it != patch_list_.end());
+#endif
+ }
+ } // for(nested_msg)
+ } // if(fragmenting_packet)
+
+ if (cur_chunk_.is_valid()) {
+ // ReturnCompletedChunk will consume the first patched entries from
+ // |patch_list_| and shrink it.
+ ReturnCompletedChunk();
+ }
+
+ // Switch to the new chunk.
+ drop_packets_ = false;
+ reached_max_packets_per_chunk_ = false;
+ retry_new_chunk_after_packet_ = false;
+ next_chunk_id_++;
+ cur_chunk_ = std::move(new_chunk);
+ cur_chunk_packet_count_inflated_ = false;
+ cur_fragment_size_field_ = nullptr;
+
+ uint8_t* payload_begin = cur_chunk_.payload_begin();
+ if (fragmenting_packet_) {
+ cur_fragment_size_field_ = payload_begin;
+ memset(payload_begin, 0, kPacketHeaderSize);
+ payload_begin += kPacketHeaderSize;
+ cur_fragment_start_ = payload_begin;
+ }
+
+ return protozero::ContiguousMemoryRange{payload_begin, cur_chunk_.end()};
+}
+
+void TraceWriterImpl::FinishTracePacket() {
+ // If we hit this, this trace writer was created in a different process. This
+ // likely means that the process forked while tracing was active, and the
+ // forked child process tried to emit a trace event. This is not supported, as
+ // it would lead to two processes writing to the same tracing SMB.
+ PERFETTO_DCHECK(process_id_ == base::GetProcessId());
+
+ FinalizeFragmentIfRequired();
+
+ cur_packet_->Reset(&protobuf_stream_writer_);
+ cur_packet_->Finalize(); // To avoid the CHECK in NewTracePacket().
+
+ // cur_chunk_packet_count_inflated_ can be true if FinishTracePacket() is
+ // called multiple times.
+ if (cur_chunk_.is_valid() && !cur_chunk_packet_count_inflated_) {
+ if (protobuf_stream_writer_.bytes_available() <
+ kExtraRoomForInflatedPacket) {
+ ReturnCompletedChunk();
+ } else {
+ cur_chunk_packet_count_inflated_ = true;
+ cur_chunk_.IncrementPacketCount();
+ }
+ }
+
+ // Send any completed patches to the service to facilitate trace data
+ // recovery by the service. This should only happen when we're completing
+ // the first packet in a chunk which was a continuation from the previous
+ // chunk, i.e. at most once per chunk.
+ if (!patch_list_.empty() && patch_list_.front().is_patched()) {
+ shmem_arbiter_->SendPatches(id_, target_buffer_, &patch_list_);
+ }
+}
+
+void TraceWriterImpl::FinalizeFragmentIfRequired() {
+ if (!cur_fragment_size_field_) {
+ return;
+ }
+ uint8_t* const wptr = protobuf_stream_writer_.write_ptr();
+ PERFETTO_DCHECK(wptr >= cur_fragment_start_);
+ uint32_t partial_size = static_cast<uint32_t>(wptr - cur_fragment_start_);
+
+ // cur_fragment_size_field_, if not nullptr, is always inside or immediately
+ // before protobuf_stream_writer_.cur_range().
+ if (partial_size < protozero::proto_utils::kMaxOneByteMessageLength &&
+ cur_fragment_size_field_ >= protobuf_stream_writer_.cur_range().begin) {
+ // This handles compaction of the root message. For nested messages, the
+ // compaction is handled by protozero::Message::Finalize().
+ protobuf_stream_writer_.Rewind(
+ partial_size, protozero::proto_utils::kMessageLengthFieldSize - 1u);
+ *cur_fragment_size_field_ = static_cast<uint8_t>(partial_size);
+ } else {
+ WriteRedundantVarInt(partial_size, cur_fragment_size_field_);
+ }
+ cur_fragment_size_field_ = nullptr;
+}
+
+uint8_t* TraceWriterImpl::AnnotatePatch(uint8_t* to_patch) {
+ if (!cur_chunk_.is_valid()) {
+ return nullptr;
+ }
+ auto offset = static_cast<uint16_t>(to_patch - cur_chunk_.payload_begin());
+ const ChunkID cur_chunk_id =
+ cur_chunk_.header()->chunk_id.load(std::memory_order_relaxed);
+ static_assert(kPatchSize == sizeof(Patch::PatchContent),
+ "Patch size mismatch");
+ Patch* patch = patch_list_.emplace_back(cur_chunk_id, offset);
+ // Check that the flag is not already set before setting it. This is not
+ // necessary, but it makes the code faster.
+ if (!(cur_chunk_.GetPacketCountAndFlags().second &
+ ChunkHeader::kChunkNeedsPatching)) {
+ cur_chunk_.SetFlag(ChunkHeader::kChunkNeedsPatching);
+ }
+ return &patch->size_field[0];
+}
+
+void TraceWriterImpl::OnMessageFinalized(protozero::Message*) {
+ TraceWriterImpl::FinishTracePacket();
+}
+
+WriterID TraceWriterImpl::writer_id() const {
+ return id_;
+}
+
+// Base class definitions.
+TraceWriter::TraceWriter() = default;
+TraceWriter::~TraceWriter() = default;
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/core/virtual_destructors.cc
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/consumer.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/observable_events.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_OBSERVABLE_EVENTS_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_OBSERVABLE_EVENTS_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/observable_events.gen.h"
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_OBSERVABLE_EVENTS_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_CONSUMER_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_CONSUMER_H_
+
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/uuid.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/observable_events.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+namespace perfetto {
+
+class TracePacket;
+
+class PERFETTO_EXPORT_COMPONENT Consumer {
+ public:
+ virtual ~Consumer();
+
+ // Called by Service (or more typically by the transport layer, on behalf of
+ // the remote Service), once the Consumer <> Service connection has been
+ // established.
+ virtual void OnConnect() = 0;
+
+ // Called by the Service or by the transport layer if the connection with the
+ // service drops, either voluntarily (e.g., by destroying the ConsumerEndpoint
+ // obtained through Service::ConnectConsumer()) or involuntarily (e.g., if the
+ // Service process crashes).
+ virtual void OnDisconnect() = 0;
+
+ // Called by the Service after the tracing session has ended. This can happen
+ // for a variety of reasons:
+ // - The consumer explicitly called DisableTracing()
+ // - The TraceConfig's |duration_ms| has been reached.
+ // - The TraceConfig's |max_file_size_bytes| has been reached.
+ // - An error occurred while trying to enable tracing. In this case |error|
+ // is non-empty.
+ virtual void OnTracingDisabled(const std::string& error) = 0;
+
+ // Called back by the Service (or transport layer) after invoking
+ // TracingService::ConsumerEndpoint::ReadBuffers(). This function can be
+ // called more than once. Each invocation can carry one or more
+ // TracePacket(s). Upon the last call, |has_more| is set to true (i.e.
+ // |has_more| is a !EOF).
+ virtual void OnTraceData(std::vector<TracePacket>, bool has_more) = 0;
+
+ // Called back by the Service (or transport layer) after invoking
+ // TracingService::ConsumerEndpoint::Detach().
+ // The consumer can disconnect at this point and the trace session will keep
+ // on going. A new consumer can later re-attach passing back the same |key|
+ // passed to Detach(), but only if the two requests come from the same uid.
+ virtual void OnDetach(bool success) = 0;
+
+ // Called back by the Service (or transport layer) after invoking
+ // TracingService::ConsumerEndpoint::Attach().
+ virtual void OnAttach(bool success, const TraceConfig&) = 0;
+
+ // Called back by the Service (or transport layer) after invoking
+ // TracingService::ConsumerEndpoint::GetTraceStats().
+ virtual void OnTraceStats(bool success, const TraceStats&) = 0;
+
+ // Called back by the Service (or transport layer) after invoking
+ // TracingService::ConsumerEndpoint::ObserveEvents() whenever one or more
+ // ObservableEvents of enabled event types occur.
+ virtual void OnObservableEvents(const ObservableEvents&) = 0;
+
+ // Called back by the Service (or transport layer) after invoking
+ // TracingService::ConsumerEndpoint::CloneSession().
+ // TODO(primiano): make pure virtual after various 3way patches.
+ struct OnSessionClonedArgs {
+ bool success;
+ std::string error;
+ base::Uuid uuid; // UUID of the cloned session.
+ };
+ virtual void OnSessionCloned(const OnSessionClonedArgs&);
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_CONSUMER_H_
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/producer.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_PRODUCER_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_PRODUCER_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/flush_flags.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+namespace perfetto {
+
+class SharedMemory;
+
+// A Producer is an entity that connects to the write-only port of the Service
+// and exposes the ability to produce performance data on-demand. The lifecycle
+// of a Producer is as follows:
+// 1. The producer connects to the service and advertises its data sources
+// (e.g., the ability to get kernel ftraces, to list process stats).
+// 2. The service acknowledges the connection and sends over the SharedMemory
+// region that will be used to exchange data (together with the signalling
+// API TracingService::ProducerEndpoint::OnPageAcquired()/OnPageReleased()).
+// 3. At some point later on, the Service asks the Producer to turn on some of
+// the previously registered data sources, together with some configuration
+// parameters. This happens via the StartDataSource() callback.
+// 4. In response to that the Producer will spawn an instance of the given data
+// source and inject its data into the shared memory buffer (obtained during
+// OnConnect).
+// This interface is subclassed by:
+// 1. The actual producer code in the clients e.g., the ftrace reader process.
+// 2. The transport layer when interposing RPC between service and producers.
+class PERFETTO_EXPORT_COMPONENT Producer {
+ public:
+ virtual ~Producer();
+
+ // Called by Service (or more typically by the transport layer, on behalf of
+ // the remote Service), once the Producer <> Service connection has been
+ // established.
+ virtual void OnConnect() = 0;
+
+ // Called by the Service or by the transport layer if the connection with the
+ // service drops, either voluntarily (e.g., by destroying the ProducerEndpoint
+ // obtained through Service::ConnectProducer()) or involuntarily (e.g., if the
+ // Service process crashes).
+ // The Producer is expected to tear down all its data sources if this happens.
+ // Once this call returns it is possible to safely destroy the Producer
+ // instance.
+ virtual void OnDisconnect() = 0;
+
+ // Called by the Service after OnConnect but before the first DataSource is
+ // created. Can be used for any setup required before tracing begins.
+ virtual void OnTracingSetup() = 0;
+
+ // Called by muxer once StartupTracing is started. It will be called before
+ // SetupStartupTracingBlocking is returned.
+ virtual void OnStartupTracingSetup() {}
+
+ // The lifecycle methods below are always called in the following sequence:
+ // SetupDataSource -> StartDataSource -> StopDataSource.
+ // Or, in the edge case where a trace is aborted immediately:
+ // SetupDataSource -> StopDataSource.
+ // The Setup+Start call sequence is always guaranateed, regardless of the
+ // TraceConfig.deferred_start flags.
+ // Called by the Service to configure one of the data sources previously
+ // registered through TracingService::ProducerEndpoint::RegisterDataSource().
+ // This method is always called before StartDataSource. There is always a
+ // SetupDataSource() call before each StartDataSource() call.
+ // Args:
+ // - DataSourceInstanceID is an identifier chosen by the Service that should
+ // be assigned to the newly created data source instance. It is used to
+ // match the StopDataSource() request below.
+ // - DataSourceConfig is the configuration for the new data source (e.g.,
+ // tells which trace categories to enable).
+ virtual void SetupDataSource(DataSourceInstanceID,
+ const DataSourceConfig&) = 0;
+
+ // Called by the Service to turn on one of the data sources previously
+ // registered through TracingService::ProducerEndpoint::RegisterDataSource()
+ // and initialized through SetupDataSource().
+ // Both arguments are guaranteed to be identical to the ones passed to the
+ // prior SetupDataSource() call.
+ virtual void StartDataSource(DataSourceInstanceID,
+ const DataSourceConfig&) = 0;
+
+ // Called by the Service to shut down an existing data source instance.
+ virtual void StopDataSource(DataSourceInstanceID) = 0;
+
+ // Called by the service to request the Producer to commit the data of the
+ // given data sources and return their chunks into the shared memory buffer.
+ // The Producer is expected to invoke NotifyFlushComplete(FlushRequestID) on
+ // the Service after the data has been committed. The producer has to either
+ // reply to the flush requests in order, or can just reply to the latest one
+ // Upon seeing a NotifyFlushComplete(N), the service will assume that all
+ // flushes < N have also been committed.
+ virtual void Flush(FlushRequestID,
+ const DataSourceInstanceID* data_source_ids,
+ size_t num_data_sources,
+ FlushFlags) = 0;
+
+ // Called by the service to instruct the given data sources to stop referring
+ // to any trace contents emitted so far. The intent is that after processing
+ // this call, the rest of the trace should be parsable even if all of the
+ // packets emitted so far have been lost (for example due to ring buffer
+ // overwrites).
+ //
+ // Called only for Producers with active data sources that have opted in by
+ // setting |handles_incremental_state_clear| in their DataSourceDescriptor.
+ //
+ // The way this call is handled is up to the individual Producer
+ // implementation. Some might wish to emit invalidation markers in the trace
+ // (see TracePacket.incremental_state_cleared for an existing field), and
+ // handle them when parsing the trace.
+ virtual void ClearIncrementalState(
+ const DataSourceInstanceID* data_source_ids,
+ size_t num_data_sources) = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_PRODUCER_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/consumer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/producer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_state.gen.h"
+
+// This translation unit contains the definitions for the destructor of pure
+// virtual interfaces for the current build target. The alternative would be
+// introducing a one-liner .cc file for each pure virtual interface, which is
+// overkill. This is for compliance with -Wweak-vtables.
+
+namespace perfetto {
+
+Consumer::~Consumer() = default;
+Producer::~Producer() = default;
+TracingService::~TracingService() = default;
+ConsumerEndpoint::~ConsumerEndpoint() = default;
+ProducerEndpoint::~ProducerEndpoint() = default;
+RelayEndpoint::~RelayEndpoint() = default;
+SharedMemory::~SharedMemory() = default;
+SharedMemory::Factory::~Factory() = default;
+SharedMemoryArbiter::~SharedMemoryArbiter() = default;
+
+// TODO(primiano): make pure virtual after various 3way patches.
+void Consumer::OnSessionCloned(const OnSessionClonedArgs&) {}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/console_interceptor.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/console_interceptor.h"
+
+#include <stdarg.h>
+
+#include <algorithm>
+#include <cmath>
+#include <optional>
+#include <tuple>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/interceptor_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+
+// sRGB color.
+struct ConsoleColor {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+};
+
+namespace {
+
+int g_output_fd_for_testing;
+
+// Google Turbo colormap.
+constexpr std::array<ConsoleColor, 16> kTurboColors = {{
+ ConsoleColor{0x30, 0x12, 0x3b},
+ ConsoleColor{0x40, 0x40, 0xa1},
+ ConsoleColor{0x46, 0x6b, 0xe3},
+ ConsoleColor{0x41, 0x93, 0xfe},
+ ConsoleColor{0x28, 0xbb, 0xeb},
+ ConsoleColor{0x17, 0xdc, 0xc2},
+ ConsoleColor{0x32, 0xf1, 0x97},
+ ConsoleColor{0x6d, 0xfd, 0x62},
+ ConsoleColor{0xa4, 0xfc, 0x3b},
+ ConsoleColor{0xcd, 0xeb, 0x34},
+ ConsoleColor{0xed, 0xcf, 0x39},
+ ConsoleColor{0xfd, 0xab, 0x33},
+ ConsoleColor{0xfa, 0x7d, 0x20},
+ ConsoleColor{0xea, 0x50, 0x0d},
+ ConsoleColor{0xd0, 0x2f, 0x04},
+ ConsoleColor{0xa9, 0x15, 0x01},
+}};
+
+constexpr size_t kHueBits = 4;
+constexpr uint32_t kMaxHue = kTurboColors.size() << kHueBits;
+constexpr uint8_t kLightness = 128u;
+constexpr ConsoleColor kWhiteColor{0xff, 0xff, 0xff};
+
+const char kDim[] = "\x1b[90m";
+const char kDefault[] = "\x1b[39m";
+const char kReset[] = "\x1b[0m";
+
+#define FMT_RGB_SET "\x1b[38;2;%d;%d;%dm"
+#define FMT_RGB_SET_BG "\x1b[48;2;%d;%d;%dm"
+
+ConsoleColor Mix(ConsoleColor a, ConsoleColor b, uint8_t ratio) {
+ return {
+ static_cast<uint8_t>(a.r + (((b.r - a.r) * ratio) >> 8)),
+ static_cast<uint8_t>(a.g + (((b.g - a.g) * ratio) >> 8)),
+ static_cast<uint8_t>(a.b + (((b.b - a.b) * ratio) >> 8)),
+ };
+}
+
+ConsoleColor HueToRGB(uint32_t hue) {
+ PERFETTO_DCHECK(hue < kMaxHue);
+ uint32_t c1 = hue >> kHueBits;
+ uint32_t c2 =
+ std::min(static_cast<uint32_t>(kTurboColors.size() - 1), c1 + 1u);
+ uint32_t ratio = hue & ((1 << kHueBits) - 1);
+ return Mix(kTurboColors[c1], kTurboColors[c2],
+ static_cast<uint8_t>(ratio | (ratio << kHueBits)));
+}
+
+uint32_t CounterToHue(uint32_t counter) {
+ // We split the hue space into 8 segments, reversing the order of bits so
+ // successive counter values will be far from each other.
+ uint32_t reversed =
+ ((counter & 0x7) >> 2) | ((counter & 0x3)) | ((counter & 0x1) << 2);
+ return reversed * kMaxHue / 8;
+}
+
+} // namespace
+
+class ConsoleInterceptor::Delegate : public TrackEventStateTracker::Delegate {
+ public:
+ explicit Delegate(InterceptorContext&);
+ ~Delegate() override;
+
+ TrackEventStateTracker::SessionState* GetSessionState() override;
+ void OnTrackUpdated(TrackEventStateTracker::Track&) override;
+ void OnTrackEvent(const TrackEventStateTracker::Track&,
+ const TrackEventStateTracker::ParsedTrackEvent&) override;
+
+ private:
+ using SelfHandle = LockedHandle<ConsoleInterceptor>;
+
+ InterceptorContext& context_;
+ std::optional<SelfHandle> locked_self_;
+};
+
+ConsoleInterceptor::~ConsoleInterceptor() = default;
+
+ConsoleInterceptor::ThreadLocalState::ThreadLocalState(
+ ThreadLocalStateArgs& args) {
+ if (auto self = args.GetInterceptorLocked()) {
+ start_time_ns = self->start_time_ns_;
+ use_colors = self->use_colors_;
+ fd = self->fd_;
+ }
+}
+
+ConsoleInterceptor::ThreadLocalState::~ThreadLocalState() = default;
+
+ConsoleInterceptor::Delegate::Delegate(InterceptorContext& context)
+ : context_(context) {}
+ConsoleInterceptor::Delegate::~Delegate() = default;
+
+TrackEventStateTracker::SessionState*
+ConsoleInterceptor::Delegate::GetSessionState() {
+ // When the session state is retrieved for the first time, it is cached (and
+ // kept locked) until we return from OnTracePacket. This avoids having to lock
+ // and unlock the instance multiple times per invocation.
+ if (locked_self_.has_value())
+ return &locked_self_.value()->session_state_;
+ locked_self_ =
+ std::make_optional<SelfHandle>(context_.GetInterceptorLocked());
+ return &locked_self_.value()->session_state_;
+}
+
+void ConsoleInterceptor::Delegate::OnTrackUpdated(
+ TrackEventStateTracker::Track& track) {
+ auto track_color = HueToRGB(CounterToHue(track.index));
+ std::array<char, 16> title;
+ if (!track.name.empty()) {
+ snprintf(title.data(), title.size(), "%s", track.name.c_str());
+ } else if (track.pid && track.tid) {
+ snprintf(title.data(), title.size(), "%u:%u",
+ static_cast<uint32_t>(track.pid),
+ static_cast<uint32_t>(track.tid));
+ } else if (track.pid) {
+ snprintf(title.data(), title.size(), "%" PRId64, track.pid);
+ } else {
+ snprintf(title.data(), title.size(), "%" PRIu64, track.uuid);
+ }
+ int title_width = static_cast<int>(title.size());
+
+ auto& tls = context_.GetThreadLocalState();
+ std::array<char, 128> message_prefix{};
+ size_t written = 0;
+ if (tls.use_colors) {
+ written = base::SprintfTrunc(message_prefix.data(), message_prefix.size(),
+ FMT_RGB_SET_BG " %s%s %-*.*s", track_color.r,
+ track_color.g, track_color.b, kReset, kDim,
+ title_width, title_width, title.data());
+ } else {
+ written = base::SprintfTrunc(message_prefix.data(), message_prefix.size(),
+ "%-*.*s", title_width + 2, title_width,
+ title.data());
+ }
+ track.user_data.assign(
+ message_prefix.begin(),
+ message_prefix.begin() + static_cast<ssize_t>(written));
+}
+
+void ConsoleInterceptor::Delegate::OnTrackEvent(
+ const TrackEventStateTracker::Track& track,
+ const TrackEventStateTracker::ParsedTrackEvent& event) {
+ // Start printing.
+ auto& tls = context_.GetThreadLocalState();
+ tls.buffer_pos = 0;
+
+ // Print timestamp and track identifier.
+ SetColor(context_, kDim);
+ Printf(context_, "[%7.3lf] %.*s",
+ static_cast<double>(event.timestamp_ns - tls.start_time_ns) / 1e9,
+ static_cast<int>(track.user_data.size()), track.user_data.data());
+
+ // Print category.
+ Printf(context_, "%-5.*s ",
+ std::min(5, static_cast<int>(event.category.size)),
+ event.category.data);
+
+ // Print stack depth.
+ for (size_t i = 0; i < event.stack_depth; i++) {
+ Printf(context_, "- ");
+ }
+
+ // Print slice name.
+ auto slice_color = HueToRGB(event.name_hash % kMaxHue);
+ auto highlight_color = Mix(slice_color, kWhiteColor, kLightness);
+ if (event.track_event.type() == protos::pbzero::TrackEvent::TYPE_SLICE_END) {
+ SetColor(context_, kDefault);
+ Printf(context_, "} ");
+ }
+ SetColor(context_, highlight_color);
+ Printf(context_, "%.*s", static_cast<int>(event.name.size), event.name.data);
+ SetColor(context_, kReset);
+ if (event.track_event.type() ==
+ protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN) {
+ SetColor(context_, kDefault);
+ Printf(context_, " {");
+ }
+
+ // Print annotations.
+ if (event.track_event.has_debug_annotations()) {
+ PrintDebugAnnotations(context_, event.track_event, slice_color,
+ highlight_color);
+ }
+
+ // TODO(skyostil): Print typed arguments.
+
+ // Print duration for longer events.
+ constexpr uint64_t kNsPerMillisecond = 1000000u;
+ if (event.duration_ns >= 10 * kNsPerMillisecond) {
+ SetColor(context_, kDim);
+ Printf(context_, " +%" PRIu64 "ms", event.duration_ns / kNsPerMillisecond);
+ }
+ SetColor(context_, kReset);
+ Printf(context_, "\n");
+}
+
+// static
+void ConsoleInterceptor::Register() {
+ perfetto::protos::gen::InterceptorDescriptor desc;
+ desc.set_name("console");
+ Interceptor<ConsoleInterceptor>::Register(desc);
+}
+
+// static
+void ConsoleInterceptor::SetOutputFdForTesting(int fd) {
+ g_output_fd_for_testing = fd;
+}
+
+void ConsoleInterceptor::OnSetup(const SetupArgs& args) {
+ int fd = STDOUT_FILENO;
+ if (g_output_fd_for_testing)
+ fd = g_output_fd_for_testing;
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+ bool use_colors = isatty(fd);
+#else
+ bool use_colors = false;
+#endif
+ const protos::gen::ConsoleConfig& config =
+ args.config.interceptor_config().console_config();
+ if (config.has_enable_colors())
+ use_colors = config.enable_colors();
+ if (config.output() == protos::gen::ConsoleConfig::OUTPUT_STDOUT) {
+ fd = STDOUT_FILENO;
+ } else if (config.output() == protos::gen::ConsoleConfig::OUTPUT_STDERR) {
+ fd = STDERR_FILENO;
+ }
+ fd_ = fd;
+ use_colors_ = use_colors;
+}
+
+void ConsoleInterceptor::OnStart(const StartArgs&) {
+ start_time_ns_ = internal::TrackEventInternal::GetTimeNs();
+}
+
+void ConsoleInterceptor::OnStop(const StopArgs&) {}
+
+// static
+void ConsoleInterceptor::OnTracePacket(InterceptorContext context) {
+ {
+ auto& tls = context.GetThreadLocalState();
+ Delegate delegate(context);
+ perfetto::protos::pbzero::TracePacket::Decoder packet(
+ context.packet_data.data, context.packet_data.size);
+ TrackEventStateTracker::ProcessTracePacket(delegate, tls.sequence_state,
+ packet);
+ } // (Potential) lock scope for session state.
+ Flush(context);
+}
+
+// static
+void ConsoleInterceptor::Printf(InterceptorContext& context,
+ const char* format,
+ ...) {
+ auto& tls = context.GetThreadLocalState();
+ ssize_t remaining = static_cast<ssize_t>(tls.message_buffer.size()) -
+ static_cast<ssize_t>(tls.buffer_pos);
+ int written = 0;
+ if (remaining > 0) {
+ va_list args;
+ va_start(args, format);
+ written = vsnprintf(&tls.message_buffer[tls.buffer_pos],
+ static_cast<size_t>(remaining), format, args);
+ PERFETTO_DCHECK(written >= 0);
+ va_end(args);
+ }
+
+ // In case of buffer overflow, flush to the fd and write the latest message to
+ // it directly instead.
+ if (remaining <= 0 || written > remaining) {
+ FILE* output = (tls.fd == STDOUT_FILENO) ? stdout : stderr;
+ if (g_output_fd_for_testing) {
+ output = fdopen(dup(g_output_fd_for_testing), "w");
+ }
+ Flush(context);
+ va_list args;
+ va_start(args, format);
+ vfprintf(output, format, args);
+ va_end(args);
+ if (g_output_fd_for_testing) {
+ fclose(output);
+ }
+ } else if (written > 0) {
+ tls.buffer_pos += static_cast<size_t>(written);
+ }
+}
+
+// static
+void ConsoleInterceptor::Flush(InterceptorContext& context) {
+ auto& tls = context.GetThreadLocalState();
+ ssize_t res = base::WriteAll(tls.fd, &tls.message_buffer[0], tls.buffer_pos);
+ PERFETTO_DCHECK(res == static_cast<ssize_t>(tls.buffer_pos));
+ tls.buffer_pos = 0;
+}
+
+// static
+void ConsoleInterceptor::SetColor(InterceptorContext& context,
+ const ConsoleColor& color) {
+ auto& tls = context.GetThreadLocalState();
+ if (!tls.use_colors)
+ return;
+ Printf(context, FMT_RGB_SET, color.r, color.g, color.b);
+}
+
+// static
+void ConsoleInterceptor::SetColor(InterceptorContext& context,
+ const char* color) {
+ auto& tls = context.GetThreadLocalState();
+ if (!tls.use_colors)
+ return;
+ Printf(context, "%s", color);
+}
+
+// static
+void ConsoleInterceptor::PrintDebugAnnotations(
+ InterceptorContext& context,
+ const protos::pbzero::TrackEvent_Decoder& track_event,
+ const ConsoleColor& slice_color,
+ const ConsoleColor& highlight_color) {
+ SetColor(context, slice_color);
+ Printf(context, "(");
+
+ bool is_first = true;
+ for (auto it = track_event.debug_annotations(); it; it++) {
+ perfetto::protos::pbzero::DebugAnnotation::Decoder annotation(*it);
+ SetColor(context, slice_color);
+ if (!is_first)
+ Printf(context, ", ");
+
+ PrintDebugAnnotationName(context, annotation);
+ Printf(context, ":");
+
+ SetColor(context, highlight_color);
+ PrintDebugAnnotationValue(context, annotation);
+
+ is_first = false;
+ }
+ SetColor(context, slice_color);
+ Printf(context, ")");
+}
+
+// static
+void ConsoleInterceptor::PrintDebugAnnotationName(
+ InterceptorContext& context,
+ const perfetto::protos::pbzero::DebugAnnotation::Decoder& annotation) {
+ auto& tls = context.GetThreadLocalState();
+ protozero::ConstChars name{};
+ if (annotation.name_iid()) {
+ name.data =
+ tls.sequence_state.debug_annotation_names[annotation.name_iid()].data();
+ name.size =
+ tls.sequence_state.debug_annotation_names[annotation.name_iid()].size();
+ } else if (annotation.has_name()) {
+ name.data = annotation.name().data;
+ name.size = annotation.name().size;
+ }
+ Printf(context, "%.*s", static_cast<int>(name.size), name.data);
+}
+
+// static
+void ConsoleInterceptor::PrintDebugAnnotationValue(
+ InterceptorContext& context,
+ const perfetto::protos::pbzero::DebugAnnotation::Decoder& annotation) {
+ if (annotation.has_bool_value()) {
+ Printf(context, "%s", annotation.bool_value() ? "true" : "false");
+ } else if (annotation.has_uint_value()) {
+ Printf(context, "%" PRIu64, annotation.uint_value());
+ } else if (annotation.has_int_value()) {
+ Printf(context, "%" PRId64, annotation.int_value());
+ } else if (annotation.has_double_value()) {
+ Printf(context, "%f", annotation.double_value());
+ } else if (annotation.has_string_value()) {
+ Printf(context, "%.*s", static_cast<int>(annotation.string_value().size),
+ annotation.string_value().data);
+ } else if (annotation.has_pointer_value()) {
+ Printf(context, "%p", reinterpret_cast<void*>(annotation.pointer_value()));
+ } else if (annotation.has_legacy_json_value()) {
+ Printf(context, "%.*s",
+ static_cast<int>(annotation.legacy_json_value().size),
+ annotation.legacy_json_value().data);
+ } else if (annotation.has_dict_entries()) {
+ Printf(context, "{");
+ bool is_first = true;
+ for (auto it = annotation.dict_entries(); it; ++it) {
+ if (!is_first)
+ Printf(context, ", ");
+ perfetto::protos::pbzero::DebugAnnotation::Decoder key_value(*it);
+ PrintDebugAnnotationName(context, key_value);
+ Printf(context, ":");
+ PrintDebugAnnotationValue(context, key_value);
+ is_first = false;
+ }
+ Printf(context, "}");
+ } else if (annotation.has_array_values()) {
+ Printf(context, "[");
+ bool is_first = true;
+ for (auto it = annotation.array_values(); it; ++it) {
+ if (!is_first)
+ Printf(context, ", ");
+ perfetto::protos::pbzero::DebugAnnotation::Decoder key_value(*it);
+ PrintDebugAnnotationValue(context, key_value);
+ is_first = false;
+ }
+ Printf(context, "]");
+ } else {
+ Printf(context, "{}");
+ }
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/data_source.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/data_source.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+
+namespace perfetto {
+
+DataSourceBase::StopArgs::~StopArgs() = default;
+DataSourceBase::FlushArgs::~FlushArgs() = default;
+DataSourceBase::~DataSourceBase() = default;
+void DataSourceBase::OnSetup(const SetupArgs&) {}
+void DataSourceBase::OnStart(const StartArgs&) {}
+void DataSourceBase::OnStop(const StopArgs&) {}
+void DataSourceBase::WillClearIncrementalState(
+ const ClearIncrementalStateArgs&) {}
+void DataSourceBase::OnFlush(const FlushArgs&) {}
+
+bool DataSourceBase::CanAdoptStartupSession(
+ const DataSourceConfig& startup_config,
+ const DataSourceConfig& service_config) {
+ // Clear target buffer and tracing-service provided fields for comparison of
+ // configs for startup tracing, since these fields are not available when
+ // setting up data sources for startup tracing.
+ DataSourceConfig startup_config_stripped = startup_config;
+ DataSourceConfig service_config_stripped = service_config;
+
+ startup_config_stripped.set_target_buffer(0);
+ startup_config_stripped.set_tracing_session_id(0);
+ startup_config_stripped.set_session_initiator(
+ DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED);
+ startup_config_stripped.set_trace_duration_ms(0);
+ startup_config_stripped.set_stop_timeout_ms(0);
+ startup_config_stripped.set_enable_extra_guardrails(false);
+
+ service_config_stripped.set_target_buffer(0);
+ service_config_stripped.set_tracing_session_id(0);
+ service_config_stripped.set_session_initiator(
+ DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED);
+ service_config_stripped.set_trace_duration_ms(0);
+ service_config_stripped.set_stop_timeout_ms(0);
+ service_config_stripped.set_enable_extra_guardrails(false);
+
+ return startup_config_stripped == service_config_stripped;
+}
+
+namespace internal {
+
+void DataSourceType::PopulateTlsInst(
+ DataSourceInstanceThreadLocalState* tls_inst,
+ DataSourceState* instance_state,
+ uint32_t instance_index) {
+ auto* tracing_impl = TracingMuxer::Get();
+ tls_inst->muxer_id_for_testing = instance_state->muxer_id_for_testing;
+ tls_inst->backend_id = instance_state->backend_id;
+ tls_inst->backend_connection_id = instance_state->backend_connection_id;
+ tls_inst->buffer_id = instance_state->buffer_id;
+ tls_inst->startup_target_buffer_reservation =
+ instance_state->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed);
+ tls_inst->data_source_instance_id = instance_state->data_source_instance_id;
+ tls_inst->is_intercepted = instance_state->interceptor_id != 0;
+ tls_inst->trace_writer = tracing_impl->CreateTraceWriter(
+ &state_, instance_index, instance_state, buffer_exhausted_policy_);
+ if (create_incremental_state_fn_) {
+ PERFETTO_DCHECK(!tls_inst->incremental_state);
+ CreateIncrementalState(tls_inst, instance_index);
+ }
+ if (create_custom_tls_fn_) {
+ tls_inst->data_source_custom_tls =
+ create_custom_tls_fn_(tls_inst, instance_index, user_arg_);
+ }
+ // Even in the case of out-of-IDs, SharedMemoryArbiterImpl returns a
+ // NullTraceWriter. The returned pointer should never be null.
+ PERFETTO_DCHECK(tls_inst->trace_writer);
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/debug_annotation.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/debug_annotation.h"
+
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_value.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+
+namespace perfetto {
+
+DebugAnnotation::~DebugAnnotation() = default;
+
+void DebugAnnotation::WriteIntoTracedValue(TracedValue context) const {
+ Add(context.annotation_);
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/event_context.cc
+// gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_interned_fields.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_interned_data_index.h"
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNED_FIELDS_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNED_FIELDS_H_
+
+namespace perfetto {
+namespace internal {
+
+// These helpers are exposed here to allow Chromium-without-client library
+// to share the interning buffers with Perfetto internals (e.g.
+// perfetto::TracedValue implementation).
+
+struct PERFETTO_EXPORT_COMPONENT InternedEventCategory
+ : public TrackEventInternedDataIndex<
+ InternedEventCategory,
+ perfetto::protos::pbzero::InternedData::kEventCategoriesFieldNumber,
+ const char*,
+ SmallInternedDataTraits> {
+ ~InternedEventCategory() override;
+
+ static void Add(protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value,
+ size_t length);
+};
+
+struct PERFETTO_EXPORT_COMPONENT InternedEventName
+ : public TrackEventInternedDataIndex<
+ InternedEventName,
+ perfetto::protos::pbzero::InternedData::kEventNamesFieldNumber,
+ const char*,
+ SmallInternedDataTraits> {
+ ~InternedEventName() override;
+
+ static void Add(protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value);
+};
+
+struct PERFETTO_EXPORT_COMPONENT InternedDebugAnnotationName
+ : public TrackEventInternedDataIndex<
+ InternedDebugAnnotationName,
+ perfetto::protos::pbzero::InternedData::
+ kDebugAnnotationNamesFieldNumber,
+ const char*,
+ SmallInternedDataTraits> {
+ ~InternedDebugAnnotationName() override;
+
+ static void Add(protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value);
+};
+
+struct PERFETTO_EXPORT_COMPONENT InternedDebugAnnotationValueTypeName
+ : public TrackEventInternedDataIndex<
+ InternedDebugAnnotationValueTypeName,
+ perfetto::protos::pbzero::InternedData::
+ kDebugAnnotationValueTypeNamesFieldNumber,
+ const char*,
+ SmallInternedDataTraits> {
+ ~InternedDebugAnnotationValueTypeName() override;
+
+ static void Add(protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value);
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNED_FIELDS_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/event_context.h"
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_interned_fields.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+
+EventContext::EventContext(
+ TraceWriterBase* trace_writer,
+ EventContext::TracePacketHandle trace_packet,
+ internal::TrackEventIncrementalState* incremental_state,
+ internal::TrackEventTlsState* tls_state)
+ : trace_writer_(trace_writer),
+ trace_packet_(std::move(trace_packet)),
+ event_(trace_packet_->set_track_event()),
+ incremental_state_(incremental_state),
+ tls_state_(tls_state) {}
+
+EventContext::~EventContext() {
+ if (!trace_packet_)
+ return;
+
+ // When the track event is finalized (i.e., the context is destroyed), we
+ // should flush any newly seen interned data to the trace. The data has
+ // earlier been written to a heap allocated protobuf message
+ // (|serialized_interned_data|). Here we just need to flush it to the main
+ // trace.
+ auto& serialized_interned_data = incremental_state_->serialized_interned_data;
+ if (PERFETTO_UNLIKELY(!serialized_interned_data.empty())) {
+ auto ranges = serialized_interned_data.GetRanges();
+ trace_packet_->AppendScatteredBytes(
+ perfetto::protos::pbzero::TracePacket::kInternedDataFieldNumber,
+ &ranges[0], ranges.size());
+
+ // Reset the message but keep one buffer allocated for future use.
+ serialized_interned_data.Reset();
+ }
+}
+
+protos::pbzero::DebugAnnotation* EventContext::AddDebugAnnotation(
+ const char* name) {
+ auto annotation = event()->add_debug_annotations();
+ annotation->set_name_iid(
+ internal::InternedDebugAnnotationName::Get(this, name));
+ return annotation;
+}
+
+protos::pbzero::DebugAnnotation* EventContext::AddDebugAnnotation(
+ ::perfetto::DynamicString name) {
+ auto annotation = event()->add_debug_annotations();
+ annotation->set_name(name.value);
+ return annotation;
+}
+
+TrackEventTlsStateUserData* EventContext::GetTlsUserData(const void* key) {
+ PERFETTO_CHECK(tls_state_);
+ PERFETTO_CHECK(key);
+ auto it = tls_state_->user_data.find(key);
+ if (it != tls_state_->user_data.end()) {
+ return it->second.get();
+ }
+ return nullptr;
+}
+
+void EventContext::SetTlsUserData(
+ const void* key,
+ std::unique_ptr<TrackEventTlsStateUserData> data) {
+ PERFETTO_CHECK(tls_state_);
+ PERFETTO_CHECK(key);
+ tls_state_->user_data[key] = std::move(data);
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/interceptor.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h"
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"
+
+namespace perfetto {
+
+InterceptorBase::~InterceptorBase() = default;
+InterceptorBase::ThreadLocalState::~ThreadLocalState() = default;
+
+// static
+void InterceptorBase::RegisterImpl(
+ const InterceptorDescriptor& descriptor,
+ std::function<std::unique_ptr<InterceptorBase>()> factory,
+ InterceptorBase::TLSFactory tls_factory,
+ InterceptorBase::TracePacketCallback on_trace_packet) {
+ auto* tracing_impl = internal::TracingMuxer::Get();
+ tracing_impl->RegisterInterceptor(descriptor, factory, tls_factory,
+ on_trace_packet);
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/checked_scope.cc
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/checked_scope.h"
+
+#include <utility>
+
+namespace perfetto {
+namespace internal {
+
+#if PERFETTO_DCHECK_IS_ON()
+CheckedScope::CheckedScope(CheckedScope* parent_scope)
+ : parent_scope_(parent_scope) {
+ if (parent_scope_) {
+ PERFETTO_DCHECK(parent_scope_->is_active());
+ parent_scope_->set_is_active(false);
+ }
+}
+
+CheckedScope::~CheckedScope() {
+ Reset();
+}
+
+void CheckedScope::Reset() {
+ if (!is_active_) {
+ // The only case when inactive scope could be destroyed is when Reset() was
+ // called explicitly or the contents of the object were moved away.
+ PERFETTO_DCHECK(deleted_);
+ return;
+ }
+ is_active_ = false;
+ deleted_ = true;
+ if (parent_scope_)
+ parent_scope_->set_is_active(true);
+}
+
+CheckedScope::CheckedScope(CheckedScope&& other) {
+ *this = std::move(other);
+}
+
+CheckedScope& CheckedScope::operator=(CheckedScope&& other) {
+ is_active_ = other.is_active_;
+ parent_scope_ = other.parent_scope_;
+ deleted_ = other.deleted_;
+
+ other.is_active_ = false;
+ other.parent_scope_ = nullptr;
+ other.deleted_ = true;
+
+ return *this;
+}
+#endif
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/interceptor_trace_writer.cc
+// gen_amalgamated begin header: include/perfetto/tracing/internal/interceptor_trace_writer.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_INTERCEPTOR_TRACE_WRITER_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_INTERCEPTOR_TRACE_WRITER_H_
+
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace internal {
+
+// A heap-backed trace writer used to reroute trace packets to an interceptor.
+class InterceptorTraceWriter : public TraceWriterBase {
+ public:
+ InterceptorTraceWriter(std::unique_ptr<InterceptorBase::ThreadLocalState> tls,
+ InterceptorBase::TracePacketCallback packet_callback,
+ DataSourceStaticState* static_state,
+ uint32_t instance_index);
+ ~InterceptorTraceWriter() override;
+
+ // TraceWriterBase implementation.
+ protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket()
+ override;
+ void FinishTracePacket() override;
+ void Flush(std::function<void()> callback = {}) override;
+ uint64_t written() const override;
+
+ private:
+ std::unique_ptr<InterceptorBase::ThreadLocalState> tls_;
+ InterceptorBase::TracePacketCallback packet_callback_;
+
+ protozero::HeapBuffered<protos::pbzero::TracePacket> cur_packet_;
+ uint64_t bytes_written_ = 0;
+
+ // Static state of the data source we are intercepting.
+ DataSourceStaticState* const static_state_;
+
+ // Index of the data source tracing session which we are intercepting
+ // (0...kMaxDataSourceInstances - 1). Used to look up this interceptor's
+ // session state (i.e., the Interceptor class instance) in the
+ // DataSourceStaticState::instances array.
+ const uint32_t instance_index_;
+
+ const uint32_t sequence_id_;
+
+ static std::atomic<uint32_t> next_sequence_id_;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_INTERCEPTOR_TRACE_WRITER_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/interceptor_trace_writer.h"
+
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+
+namespace perfetto {
+namespace internal {
+
+// static
+std::atomic<uint32_t> InterceptorTraceWriter::next_sequence_id_{};
+
+InterceptorTraceWriter::InterceptorTraceWriter(
+ std::unique_ptr<InterceptorBase::ThreadLocalState> tls,
+ InterceptorBase::TracePacketCallback packet_callback,
+ DataSourceStaticState* static_state,
+ uint32_t instance_index)
+ : tls_(std::move(tls)),
+ packet_callback_(std::move(packet_callback)),
+ static_state_(static_state),
+ instance_index_(instance_index),
+ sequence_id_(++next_sequence_id_) {}
+
+InterceptorTraceWriter::~InterceptorTraceWriter() = default;
+
+protozero::MessageHandle<protos::pbzero::TracePacket>
+InterceptorTraceWriter::NewTracePacket() {
+ Flush();
+ auto packet = TraceWriter::TracePacketHandle(cur_packet_.get());
+ packet->set_trusted_packet_sequence_id(sequence_id_);
+ return packet;
+}
+
+void InterceptorTraceWriter::Flush(std::function<void()> callback) {
+ if (!cur_packet_.empty()) {
+ InterceptorBase::TracePacketCallbackArgs args{};
+ args.static_state = static_state_;
+ args.instance_index = instance_index_;
+ args.tls = tls_.get();
+
+ const auto& slices = cur_packet_.GetSlices();
+ if (slices.size() == 1) {
+ // Fast path: the current packet fits into a single slice.
+ auto slice_range = slices.begin()->GetUsedRange();
+ args.packet_data = protozero::ConstBytes{
+ slice_range.begin,
+ static_cast<size_t>(slice_range.end - slice_range.begin)};
+ bytes_written_ += static_cast<uint64_t>(args.packet_data.size);
+ packet_callback_(std::move(args));
+ } else {
+ // Fallback: stitch together multiple slices.
+ auto stitched_data = cur_packet_.SerializeAsArray();
+ args.packet_data =
+ protozero::ConstBytes{stitched_data.data(), stitched_data.size()};
+ bytes_written_ += static_cast<uint64_t>(stitched_data.size());
+ packet_callback_(std::move(args));
+ }
+ cur_packet_.Reset();
+ }
+ if (callback)
+ callback();
+}
+
+void InterceptorTraceWriter::FinishTracePacket() {}
+
+uint64_t InterceptorTraceWriter::written() const {
+ return bytes_written_;
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/tracing_backend_fake.cc
+// gen_amalgamated begin header: include/perfetto/tracing/internal/tracing_backend_fake.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_BACKEND_FAKE_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_BACKEND_FAKE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"
+
+namespace perfetto {
+namespace internal {
+
+// A built-in implementation of TracingBackend that fails any attempt to create
+// a tracing session.
+class PERFETTO_EXPORT_COMPONENT TracingBackendFake : public TracingBackend {
+ public:
+ static TracingBackend* GetInstance();
+
+ // TracingBackend implementation.
+ std::unique_ptr<ProducerEndpoint> ConnectProducer(
+ const ConnectProducerArgs&) override;
+ std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
+ const ConnectConsumerArgs&) override;
+
+ private:
+ TracingBackendFake();
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_BACKEND_FAKE_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_backend_fake.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/consumer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/producer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+
+namespace perfetto {
+namespace internal {
+
+namespace {
+
+class UnsupportedProducerEndpoint : public ProducerEndpoint {
+ public:
+ UnsupportedProducerEndpoint(Producer* producer, base::TaskRunner* task_runner)
+ : producer_(producer), task_runner_(task_runner) {
+ // The SDK will attempt to reconnect the producer, so instead we allow it
+ // to connect successfully, but never start any sessions.
+ auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_ptr] {
+ if (weak_ptr && weak_ptr->connected_)
+ weak_ptr->producer_->OnConnect();
+ });
+ }
+ ~UnsupportedProducerEndpoint() override { Disconnect(); }
+
+ void Disconnect() override {
+ if (!connected_)
+ return;
+ connected_ = false;
+ producer_->OnDisconnect();
+ }
+
+ void RegisterDataSource(const DataSourceDescriptor&) override {}
+ void UpdateDataSource(const DataSourceDescriptor&) override {}
+ void UnregisterDataSource(const std::string& /*name*/) override {}
+
+ void RegisterTraceWriter(uint32_t /*writer_id*/,
+ uint32_t /*target_buffer*/) override {}
+ void UnregisterTraceWriter(uint32_t /*writer_id*/) override {}
+
+ void CommitData(const CommitDataRequest&,
+ CommitDataCallback callback) override {
+ if (connected_) {
+ callback();
+ }
+ }
+
+ SharedMemory* shared_memory() const override { return nullptr; }
+ size_t shared_buffer_page_size_kb() const override { return 0; }
+
+ std::unique_ptr<TraceWriter> CreateTraceWriter(
+ BufferID /*target_buffer*/,
+ BufferExhaustedPolicy) override {
+ return nullptr;
+ }
+
+ SharedMemoryArbiter* MaybeSharedMemoryArbiter() override { return nullptr; }
+ bool IsShmemProvidedByProducer() const override { return false; }
+
+ void NotifyFlushComplete(FlushRequestID) override {}
+ void NotifyDataSourceStarted(DataSourceInstanceID) override {}
+ void NotifyDataSourceStopped(DataSourceInstanceID) override {}
+ void ActivateTriggers(const std::vector<std::string>&) override {}
+
+ void Sync(std::function<void()> callback) override {
+ if (connected_) {
+ callback();
+ }
+ }
+
+ private:
+ Producer* const producer_;
+ base::TaskRunner* const task_runner_;
+ bool connected_ = true;
+ base::WeakPtrFactory<UnsupportedProducerEndpoint> weak_ptr_factory_{
+ this}; // Keep last.
+};
+
+class UnsupportedConsumerEndpoint : public ConsumerEndpoint {
+ public:
+ UnsupportedConsumerEndpoint(Consumer* consumer, base::TaskRunner* task_runner)
+ : consumer_(consumer), task_runner_(task_runner) {
+ // The SDK will not to reconnect the consumer, so we just disconnect it
+ // immediately, which will cancel the tracing session.
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this] {
+ if (weak_this)
+ weak_this->consumer_->OnDisconnect();
+ });
+ }
+ ~UnsupportedConsumerEndpoint() override = default;
+
+ void EnableTracing(const TraceConfig&, base::ScopedFile) override {}
+ void ChangeTraceConfig(const TraceConfig&) override {}
+
+ void StartTracing() override {}
+ void DisableTracing() override {}
+
+ void Flush(uint32_t /*timeout_ms*/,
+ FlushCallback callback,
+ FlushFlags) override {
+ callback(/*success=*/false);
+ }
+
+ void ReadBuffers() override {}
+ void FreeBuffers() override {}
+
+ void Detach(const std::string& /*key*/) override {}
+ void Attach(const std::string& /*key*/) override {}
+
+ void GetTraceStats() override {}
+ void ObserveEvents(uint32_t /*events_mask*/) override {}
+ void QueryServiceState(QueryServiceStateArgs,
+ QueryServiceStateCallback) override {}
+ void QueryCapabilities(QueryCapabilitiesCallback) override {}
+
+ void SaveTraceForBugreport(SaveTraceForBugreportCallback) override {}
+ void CloneSession(TracingSessionID, CloneSessionArgs) override {}
+
+ private:
+ Consumer* const consumer_;
+ base::TaskRunner* const task_runner_;
+ base::WeakPtrFactory<UnsupportedConsumerEndpoint> weak_ptr_factory_{
+ this}; // Keep last.
+};
+
+} // namespace
+
+// static
+TracingBackend* TracingBackendFake::GetInstance() {
+ static auto* instance = new TracingBackendFake();
+ return instance;
+}
+
+TracingBackendFake::TracingBackendFake() = default;
+
+std::unique_ptr<ProducerEndpoint> TracingBackendFake::ConnectProducer(
+ const ConnectProducerArgs& args) {
+ return std::unique_ptr<ProducerEndpoint>(
+ new UnsupportedProducerEndpoint(args.producer, args.task_runner));
+}
+
+std::unique_ptr<ConsumerEndpoint> TracingBackendFake::ConnectConsumer(
+ const ConnectConsumerArgs& args) {
+ return std::unique_ptr<ConsumerEndpoint>(
+ new UnsupportedConsumerEndpoint(args.consumer, args.task_runner));
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/tracing_muxer_fake.cc
+// gen_amalgamated begin header: src/tracing/internal/tracing_muxer_fake.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_INTERNAL_TRACING_MUXER_FAKE_H_
+#define SRC_TRACING_INTERNAL_TRACING_MUXER_FAKE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"
+
+namespace perfetto {
+namespace internal {
+
+// An always-fail implementation of TracingMuxer. Before tracing has been
+// initialiazed, all muxer operations will route here and fail with a helpful
+// error message. This is to avoid introducing null checks in
+// performance-critical parts of the codebase.
+class TracingMuxerFake : public TracingMuxer {
+ class FakePlatform : public Platform {
+ public:
+ ~FakePlatform() override;
+ ThreadLocalObject* GetOrCreateThreadLocalObject() override;
+ std::unique_ptr<base::TaskRunner> CreateTaskRunner(
+ const CreateTaskRunnerArgs&) override;
+ std::string GetCurrentProcessName() override;
+
+ static FakePlatform instance;
+ };
+
+ public:
+ TracingMuxerFake() : TracingMuxer(&FakePlatform::instance) {}
+ ~TracingMuxerFake() override;
+
+ static constexpr TracingMuxerFake* Get() {
+#if PERFETTO_HAS_NO_DESTROY()
+ return &instance;
+#else
+ return nullptr;
+#endif
+ }
+
+ // TracingMuxer implementation.
+ bool RegisterDataSource(const DataSourceDescriptor&,
+ DataSourceFactory,
+ DataSourceParams,
+ bool,
+ DataSourceStaticState*) override;
+ void UpdateDataSourceDescriptor(const DataSourceDescriptor&,
+ const DataSourceStaticState*) override;
+ std::unique_ptr<TraceWriterBase> CreateTraceWriter(
+ DataSourceStaticState*,
+ uint32_t data_source_instance_index,
+ DataSourceState*,
+ BufferExhaustedPolicy buffer_exhausted_policy) override;
+ void DestroyStoppedTraceWritersForCurrentThread() override;
+ void RegisterInterceptor(const InterceptorDescriptor&,
+ InterceptorFactory,
+ InterceptorBase::TLSFactory,
+ InterceptorBase::TracePacketCallback) override;
+ void ActivateTriggers(const std::vector<std::string>&, uint32_t) override;
+
+ private:
+ static TracingMuxerFake instance;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // SRC_TRACING_INTERNAL_TRACING_MUXER_FAKE_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/internal/tracing_muxer_fake.h"
+
+namespace perfetto {
+namespace internal {
+namespace {
+
+PERFETTO_NORETURN void FailUninitialized() {
+ PERFETTO_FATAL(
+ "Tracing not initialized. Call perfetto::Tracing::Initialize() first.");
+}
+
+} // namespace
+
+#if PERFETTO_HAS_NO_DESTROY()
+// static
+PERFETTO_NO_DESTROY TracingMuxerFake::FakePlatform
+ TracingMuxerFake::FakePlatform::instance{};
+// static
+PERFETTO_NO_DESTROY TracingMuxerFake TracingMuxerFake::instance{};
+#endif // PERFETTO_HAS_NO_DESTROY()
+
+TracingMuxerFake::~TracingMuxerFake() = default;
+
+TracingMuxerFake::FakePlatform::~FakePlatform() = default;
+
+Platform::ThreadLocalObject*
+TracingMuxerFake::FakePlatform::GetOrCreateThreadLocalObject() {
+ FailUninitialized();
+}
+
+std::unique_ptr<base::TaskRunner>
+TracingMuxerFake::FakePlatform::CreateTaskRunner(const CreateTaskRunnerArgs&) {
+ FailUninitialized();
+}
+
+std::string TracingMuxerFake::FakePlatform::GetCurrentProcessName() {
+ FailUninitialized();
+}
+
+bool TracingMuxerFake::RegisterDataSource(const DataSourceDescriptor&,
+ DataSourceFactory,
+ DataSourceParams,
+ bool,
+ DataSourceStaticState*) {
+ FailUninitialized();
+}
+
+void TracingMuxerFake::UpdateDataSourceDescriptor(
+ const DataSourceDescriptor&,
+ const DataSourceStaticState*) {
+ FailUninitialized();
+}
+
+std::unique_ptr<TraceWriterBase> TracingMuxerFake::CreateTraceWriter(
+ DataSourceStaticState*,
+ uint32_t,
+ DataSourceState*,
+ BufferExhaustedPolicy) {
+ FailUninitialized();
+}
+
+void TracingMuxerFake::DestroyStoppedTraceWritersForCurrentThread() {
+ FailUninitialized();
+}
+
+void TracingMuxerFake::RegisterInterceptor(
+ const InterceptorDescriptor&,
+ InterceptorFactory,
+ InterceptorBase::TLSFactory,
+ InterceptorBase::TracePacketCallback) {
+ FailUninitialized();
+}
+
+void TracingMuxerFake::ActivateTriggers(const std::vector<std::string>&,
+ uint32_t) {
+ FailUninitialized();
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/tracing_muxer_impl.cc
+// gen_amalgamated begin header: src/tracing/internal/tracing_muxer_impl.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
+#define SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+#include <atomic>
+#include <bitset>
+#include <functional>
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
+#include <utility>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/consumer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/producer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/backend_type.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/trace_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/interceptor_descriptor.gen.h"
+
+namespace perfetto {
+
+class ConsumerEndpoint;
+class DataSourceBase;
+class ProducerEndpoint;
+class TraceWriterBase;
+class TracingBackend;
+class TracingSession;
+struct TracingInitArgs;
+
+namespace base {
+class TaskRunner;
+}
+
+namespace shlib {
+void ResetForTesting();
+}
+
+namespace test {
+class TracingMuxerImplInternalsForTest;
+}
+
+namespace internal {
+
+struct DataSourceStaticState;
+
+// This class acts as a bridge between the public API and the TracingBackend(s).
+// It exposes a simplified view of the world to the API methods handling all the
+// bookkeeping to map data source instances and trace writers to the various
+// backends. It deals with N data sources, M backends (1 backend == 1 tracing
+// service == 1 producer connection) and T concurrent tracing sessions.
+//
+// Handing data source registration and start/stop flows [producer side]:
+// ----------------------------------------------------------------------
+// 1. The API client subclasses perfetto::DataSource and calls
+// DataSource::Register<MyDataSource>(). In turn this calls into the
+// TracingMuxer.
+// 2. The tracing muxer iterates through all the backends (1 backend == 1
+// service == 1 producer connection) and registers the data source on each
+// backend.
+// 3. When any (services behind a) backend starts tracing and requests to start
+// that specific data source, the TracingMuxerImpl constructs a new instance
+// of MyDataSource and calls the OnStart() method.
+//
+// Controlling trace and retrieving trace data [consumer side]:
+// ------------------------------------------------------------
+// 1. The API client calls Tracing::NewTrace(), returns a RAII TracingSession
+// object.
+// 2. NewTrace() calls into internal::TracingMuxer(Impl). TracingMuxer
+// subclasses the TracingSession object (TracingSessionImpl) and returns it.
+// 3. The tracing muxer identifies the backend (according to the args passed to
+// NewTrace), creates a new Consumer and connects to it.
+// 4. When the API client calls Start()/Stop()/ReadTrace() methods, the
+// TracingMuxer forwards them to the consumer associated to the
+// TracingSession. Likewise for callbacks coming from the consumer-side of
+// the service.
+class TracingMuxerImpl : public TracingMuxer {
+ public:
+ // This is different than TracingSessionID because it's global across all
+ // backends. TracingSessionID is global only within the scope of one service.
+ using TracingSessionGlobalID = uint64_t;
+
+ struct RegisteredDataSource {
+ DataSourceDescriptor descriptor;
+ DataSourceFactory factory{};
+ bool supports_multiple_instances = false;
+ bool requires_callbacks_under_lock = false;
+ bool no_flush = false;
+ DataSourceStaticState* static_state = nullptr;
+ };
+
+ static void InitializeInstance(const TracingInitArgs&);
+ static void ResetForTesting();
+ static void Shutdown();
+
+ // TracingMuxer implementation.
+ bool RegisterDataSource(const DataSourceDescriptor&,
+ DataSourceFactory,
+ DataSourceParams,
+ bool no_flush,
+ DataSourceStaticState*) override;
+ void UpdateDataSourceDescriptor(const DataSourceDescriptor&,
+ const DataSourceStaticState*) override;
+ std::unique_ptr<TraceWriterBase> CreateTraceWriter(
+ DataSourceStaticState*,
+ uint32_t data_source_instance_index,
+ DataSourceState*,
+ BufferExhaustedPolicy buffer_exhausted_policy) override;
+ void DestroyStoppedTraceWritersForCurrentThread() override;
+ void RegisterInterceptor(const InterceptorDescriptor&,
+ InterceptorFactory,
+ InterceptorBase::TLSFactory,
+ InterceptorBase::TracePacketCallback) override;
+
+ void ActivateTriggers(const std::vector<std::string>&, uint32_t) override;
+
+ std::unique_ptr<TracingSession> CreateTracingSession(
+ BackendType,
+ TracingConsumerBackend* (*system_backend_factory)());
+ std::unique_ptr<StartupTracingSession> CreateStartupTracingSession(
+ const TraceConfig& config,
+ Tracing::SetupStartupTracingOpts);
+ std::unique_ptr<StartupTracingSession> CreateStartupTracingSessionBlocking(
+ const TraceConfig& config,
+ Tracing::SetupStartupTracingOpts);
+
+ // Producer-side bookkeeping methods.
+ void UpdateDataSourcesOnAllBackends();
+ void SetupDataSource(TracingBackendId,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID,
+ const DataSourceConfig&);
+ void StartDataSource(TracingBackendId, DataSourceInstanceID);
+ void StopDataSource_AsyncBegin(TracingBackendId, DataSourceInstanceID);
+ void ClearDataSourceIncrementalState(TracingBackendId, DataSourceInstanceID);
+ void SyncProducersForTesting();
+
+ // Consumer-side bookkeeping methods.
+ void SetupTracingSession(TracingSessionGlobalID,
+ const std::shared_ptr<TraceConfig>&,
+ base::ScopedFile trace_fd = base::ScopedFile());
+ void StartTracingSession(TracingSessionGlobalID);
+ void ChangeTracingSessionConfig(TracingSessionGlobalID, const TraceConfig&);
+ void StopTracingSession(TracingSessionGlobalID);
+ void DestroyTracingSession(TracingSessionGlobalID);
+ void FlushTracingSession(TracingSessionGlobalID,
+ uint32_t,
+ std::function<void(bool)>);
+ void ReadTracingSessionData(
+ TracingSessionGlobalID,
+ std::function<void(TracingSession::ReadTraceCallbackArgs)>);
+ void GetTraceStats(TracingSessionGlobalID,
+ TracingSession::GetTraceStatsCallback);
+ void QueryServiceState(TracingSessionGlobalID,
+ TracingSession::QueryServiceStateCallback);
+
+ // Sets the batching period to |batch_commits_duration_ms| on the backends
+ // with type |backend_type|.
+ void SetBatchCommitsDurationForTesting(uint32_t batch_commits_duration_ms,
+ BackendType backend_type);
+
+ // Enables direct SMB patching on the backends with type |backend_type| (see
+ // SharedMemoryArbiter::EnableDirectSMBPatching). Returns true if the
+ // operation succeeded for all backends with type |backend_type|, false
+ // otherwise.
+ bool EnableDirectSMBPatchingForTesting(BackendType backend_type);
+
+ void SetMaxProducerReconnectionsForTesting(uint32_t count);
+
+ private:
+ friend class test::TracingMuxerImplInternalsForTest;
+ friend void shlib::ResetForTesting();
+
+ // For each TracingBackend we create and register one ProducerImpl instance.
+ // This talks to the producer-side of the service, gets start/stop requests
+ // from it and routes them to the registered data sources.
+ // One ProducerImpl == one backend == one tracing service.
+ // This class is needed to disambiguate callbacks coming from different
+ // services. TracingMuxerImpl can't directly implement the Producer interface
+ // because the Producer virtual methods don't allow to identify the service.
+ class ProducerImpl : public Producer {
+ public:
+ ProducerImpl(TracingMuxerImpl*,
+ TracingBackendId,
+ uint32_t shmem_batch_commits_duration_ms,
+ bool shmem_direct_patching_enabled);
+ ~ProducerImpl() override;
+
+ void Initialize(std::unique_ptr<ProducerEndpoint> endpoint);
+ void RegisterDataSource(const DataSourceDescriptor&,
+ DataSourceFactory,
+ DataSourceStaticState*);
+ void DisposeConnection();
+
+ // perfetto::Producer implementation.
+ void OnConnect() override;
+ void OnDisconnect() override;
+ void OnTracingSetup() override;
+ void OnStartupTracingSetup() override;
+ void SetupDataSource(DataSourceInstanceID,
+ const DataSourceConfig&) override;
+ void StartDataSource(DataSourceInstanceID,
+ const DataSourceConfig&) override;
+ void StopDataSource(DataSourceInstanceID) override;
+ void Flush(FlushRequestID,
+ const DataSourceInstanceID*,
+ size_t,
+ FlushFlags) override;
+ void ClearIncrementalState(const DataSourceInstanceID*, size_t) override;
+
+ bool SweepDeadServices();
+ void SendOnConnectTriggers();
+ void NotifyFlushForDataSourceDone(DataSourceInstanceID, FlushRequestID);
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+ TracingMuxerImpl* muxer_;
+ TracingBackendId const backend_id_;
+ bool connected_ = false;
+ bool did_setup_tracing_ = false;
+ bool did_setup_startup_tracing_ = false;
+ std::atomic<uint32_t> connection_id_{0};
+ uint16_t last_startup_target_buffer_reservation_ = 0;
+ bool is_producer_provided_smb_ = false;
+ bool producer_provided_smb_failed_ = false;
+
+ const uint32_t shmem_batch_commits_duration_ms_ = 0;
+ const bool shmem_direct_patching_enabled_ = false;
+
+ // Set of data sources that have been actually registered on this producer.
+ // This can be a subset of the global |data_sources_|, because data sources
+ // can register before the producer is fully connected.
+ std::bitset<kMaxDataSources> registered_data_sources_{};
+
+ // A collection of disconnected service endpoints. Since trace writers on
+ // arbitrary threads might continue writing data to disconnected services,
+ // we keep the old services around and periodically try to clean up ones
+ // that no longer have any writers (see SweepDeadServices).
+ std::list<std::shared_ptr<ProducerEndpoint>> dead_services_;
+
+ // Triggers that should be sent when the service connects (trigger_name,
+ // expiration).
+ std::list<std::pair<std::string, base::TimeMillis>> on_connect_triggers_;
+
+ std::map<FlushRequestID, std::set<DataSourceInstanceID>> pending_flushes_;
+
+ // The currently active service endpoint is maintained as an atomic shared
+ // pointer so it won't get deleted from underneath threads that are creating
+ // trace writers. At any given time one endpoint can be shared (and thus
+ // kept alive) by the |service_| pointer, an entry in |dead_services_| and
+ // as a pointer on the stack in CreateTraceWriter() (on an arbitrary
+ // thread). The endpoint is never shared outside ProducerImpl itself.
+ //
+ // WARNING: Any *write* access to this variable or any *read* access from a
+ // non-muxer thread must be done through std::atomic_{load,store} to avoid
+ // data races.
+ std::shared_ptr<ProducerEndpoint> service_; // Keep last.
+ };
+
+ // For each TracingSession created by the API client (Tracing::NewTrace() we
+ // create and register one ConsumerImpl instance.
+ // This talks to the consumer-side of the service, gets end-of-trace and
+ // on-trace-data callbacks and routes them to the API client callbacks.
+ // This class is needed to disambiguate callbacks coming from different
+ // tracing sessions.
+ class ConsumerImpl : public Consumer {
+ public:
+ ConsumerImpl(TracingMuxerImpl*, BackendType, TracingSessionGlobalID);
+ ~ConsumerImpl() override;
+
+ void Initialize(std::unique_ptr<ConsumerEndpoint> endpoint);
+
+ // perfetto::Consumer implementation.
+ void OnConnect() override;
+ void OnDisconnect() override;
+ void OnTracingDisabled(const std::string& error) override;
+ void OnTraceData(std::vector<TracePacket>, bool has_more) override;
+ void OnDetach(bool success) override;
+ void OnAttach(bool success, const TraceConfig&) override;
+ void OnTraceStats(bool success, const TraceStats&) override;
+ void OnObservableEvents(const ObservableEvents&) override;
+ void OnSessionCloned(const OnSessionClonedArgs&) override;
+
+ void NotifyStartComplete();
+ void NotifyError(const TracingError&);
+ void NotifyStopComplete();
+
+ // Will eventually inform the |muxer_| when it is safe to remove |this|.
+ void Disconnect();
+
+ TracingMuxerImpl* muxer_;
+ BackendType const backend_type_;
+ TracingSessionGlobalID const session_id_;
+ bool connected_ = false;
+
+ // This is to handle the case where the Setup call from the API client
+ // arrives before the consumer has connected. In this case we keep around
+ // the config and check if we have it after connection.
+ bool start_pending_ = false;
+
+ // Similarly if the session is stopped before the consumer was connected, we
+ // need to wait until the session has started before stopping it.
+ bool stop_pending_ = false;
+
+ // Similarly we need to buffer a call to get trace statistics if the
+ // consumer wasn't connected yet.
+ bool get_trace_stats_pending_ = false;
+
+ // Whether this session was already stopped. This will happen in response to
+ // Stop{,Blocking}, but also if the service stops the session for us
+ // automatically (e.g., when there are no data sources).
+ bool stopped_ = false;
+
+ // shared_ptr because it's posted across threads. This is to avoid copying
+ // it more than once.
+ std::shared_ptr<TraceConfig> trace_config_;
+ base::ScopedFile trace_fd_;
+
+ // If the API client passes a callback to start, we should invoke this when
+ // NotifyStartComplete() is invoked.
+ std::function<void()> start_complete_callback_;
+
+ // An internal callback used to implement StartBlocking().
+ std::function<void()> blocking_start_complete_callback_;
+
+ // If the API client passes a callback to get notification about the
+ // errors, we should invoke this when NotifyError() is invoked.
+ std::function<void(TracingError)> error_callback_;
+
+ // If the API client passes a callback to stop, we should invoke this when
+ // OnTracingDisabled() is invoked.
+ std::function<void()> stop_complete_callback_;
+
+ // An internal callback used to implement StopBlocking().
+ std::function<void()> blocking_stop_complete_callback_;
+
+ // Callback passed to ReadTrace().
+ std::function<void(TracingSession::ReadTraceCallbackArgs)>
+ read_trace_callback_;
+
+ // Callback passed to GetTraceStats().
+ TracingSession::GetTraceStatsCallback get_trace_stats_callback_;
+
+ // Callback for a pending call to QueryServiceState().
+ TracingSession::QueryServiceStateCallback query_service_state_callback_;
+
+ // The states of all data sources in this tracing session. |true| means the
+ // data source has started tracing.
+ using DataSourceHandle = std::pair<std::string, std::string>;
+ std::map<DataSourceHandle, bool> data_source_states_;
+
+ std::unique_ptr<ConsumerEndpoint> service_; // Keep before last.
+ PERFETTO_THREAD_CHECKER(thread_checker_) // Keep last.
+ };
+
+ // This object is returned to API clients when they call
+ // Tracing::CreateTracingSession().
+ class TracingSessionImpl : public TracingSession {
+ public:
+ TracingSessionImpl(TracingMuxerImpl*, TracingSessionGlobalID, BackendType);
+ ~TracingSessionImpl() override;
+ void Setup(const TraceConfig&, int fd) override;
+ void Start() override;
+ void StartBlocking() override;
+ void SetOnStartCallback(std::function<void()>) override;
+ void SetOnErrorCallback(std::function<void(TracingError)>) override;
+ void Stop() override;
+ void StopBlocking() override;
+ void Flush(std::function<void(bool)>, uint32_t timeout_ms) override;
+ void ReadTrace(ReadTraceCallback) override;
+ void SetOnStopCallback(std::function<void()>) override;
+ void GetTraceStats(GetTraceStatsCallback) override;
+ void QueryServiceState(QueryServiceStateCallback) override;
+ void ChangeTraceConfig(const TraceConfig&) override;
+
+ private:
+ TracingMuxerImpl* const muxer_;
+ TracingSessionGlobalID const session_id_;
+ BackendType const backend_type_;
+ };
+
+ // This object is returned to API clients when they call
+ // Tracing::SetupStartupTracing().
+ class StartupTracingSessionImpl : public StartupTracingSession {
+ public:
+ StartupTracingSessionImpl(TracingMuxerImpl*,
+ TracingSessionGlobalID,
+ BackendType);
+ ~StartupTracingSessionImpl() override;
+ void Abort() override;
+ void AbortBlocking() override;
+
+ private:
+ TracingMuxerImpl* const muxer_;
+ TracingSessionGlobalID const session_id_;
+ BackendType backend_type_;
+ };
+
+ struct RegisteredInterceptor {
+ protos::gen::InterceptorDescriptor descriptor;
+ InterceptorFactory factory{};
+ InterceptorBase::TLSFactory tls_factory{};
+ InterceptorBase::TracePacketCallback packet_callback{};
+ };
+
+ struct RegisteredStartupSession {
+ TracingSessionID session_id = 0;
+ int num_unbound_data_sources = 0;
+
+ bool is_aborting = false;
+ int num_aborting_data_sources = 0;
+
+ std::function<void()> on_aborted;
+ std::function<void()> on_adopted;
+ };
+
+ struct RegisteredProducerBackend {
+ // Backends are supposed to have static lifetime.
+ TracingProducerBackend* backend = nullptr;
+ TracingBackendId id = 0;
+ BackendType type{};
+
+ TracingBackend::ConnectProducerArgs producer_conn_args;
+ std::unique_ptr<ProducerImpl> producer;
+
+ std::vector<RegisteredStartupSession> startup_sessions;
+ };
+
+ struct RegisteredConsumerBackend {
+ // Backends are supposed to have static lifetime.
+ TracingConsumerBackend* backend = nullptr;
+ BackendType type{};
+ // The calling code can request more than one concurrently active tracing
+ // session for the same backend. We need to create one consumer per session.
+ std::vector<std::unique_ptr<ConsumerImpl>> consumers;
+ };
+
+ void UpdateDataSourceOnAllBackends(RegisteredDataSource& rds,
+ bool is_changed);
+ explicit TracingMuxerImpl(const TracingInitArgs&);
+ void Initialize(const TracingInitArgs& args);
+ void AddBackends(const TracingInitArgs& args);
+ void AddConsumerBackend(TracingConsumerBackend* backend, BackendType type);
+ void AddProducerBackend(TracingProducerBackend* backend,
+ BackendType type,
+ const TracingInitArgs& args);
+ ConsumerImpl* FindConsumer(TracingSessionGlobalID session_id);
+ std::pair<ConsumerImpl*, RegisteredConsumerBackend*> FindConsumerAndBackend(
+ TracingSessionGlobalID session_id);
+ RegisteredProducerBackend* FindProducerBackendById(TracingBackendId id);
+ RegisteredProducerBackend* FindProducerBackendByType(BackendType type);
+ RegisteredConsumerBackend* FindConsumerBackendByType(BackendType type);
+ void InitializeConsumer(TracingSessionGlobalID session_id);
+ void OnConsumerDisconnected(ConsumerImpl* consumer);
+ void OnProducerDisconnected(ProducerImpl* producer);
+ // Test only method.
+ void SweepDeadBackends();
+
+ struct FindDataSourceRes {
+ FindDataSourceRes() = default;
+ FindDataSourceRes(DataSourceStaticState* a,
+ DataSourceState* b,
+ uint32_t c,
+ bool d)
+ : static_state(a),
+ internal_state(b),
+ instance_idx(c),
+ requires_callbacks_under_lock(d) {}
+ explicit operator bool() const { return !!internal_state; }
+
+ DataSourceStaticState* static_state = nullptr;
+ DataSourceState* internal_state = nullptr;
+ uint32_t instance_idx = 0;
+ bool requires_callbacks_under_lock = false;
+ };
+ FindDataSourceRes FindDataSource(TracingBackendId, DataSourceInstanceID);
+
+ FindDataSourceRes SetupDataSourceImpl(
+ const RegisteredDataSource&,
+ TracingBackendId,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID,
+ const DataSourceConfig&,
+ TracingSessionGlobalID startup_session_id);
+ void StartDataSourceImpl(const FindDataSourceRes&);
+ void StopDataSource_AsyncBeginImpl(const FindDataSourceRes&);
+ void StopDataSource_AsyncEnd(TracingBackendId,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID,
+ const FindDataSourceRes&);
+ bool FlushDataSource_AsyncBegin(TracingBackendId,
+ DataSourceInstanceID,
+ FlushRequestID,
+ FlushFlags);
+ void FlushDataSource_AsyncEnd(TracingBackendId,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID,
+ const FindDataSourceRes&,
+ FlushRequestID);
+ void AbortStartupTracingSession(TracingSessionGlobalID, BackendType);
+ // When ResetForTesting() is executed, `cb` will be called on the calling
+ // thread and on the muxer thread.
+ void AppendResetForTestingCallback(std::function<void()> cb);
+
+ // WARNING: If you add new state here, be sure to update ResetForTesting.
+ std::unique_ptr<base::TaskRunner> task_runner_;
+ std::vector<RegisteredDataSource> data_sources_;
+ // These lists can only have one backend per BackendType. The elements are
+ // sorted by BackendType priority (see BackendTypePriority). They always
+ // contain a fake low-priority kUnspecifiedBackend at the end.
+ std::list<RegisteredProducerBackend> producer_backends_;
+ std::list<RegisteredConsumerBackend> consumer_backends_;
+ std::vector<RegisteredInterceptor> interceptors_;
+ TracingPolicy* policy_ = nullptr;
+
+ // Learn more at TracingInitArgs::supports_multiple_data_source_instances
+ bool supports_multiple_data_source_instances_ = true;
+
+ std::atomic<TracingSessionGlobalID> next_tracing_session_id_{};
+ std::atomic<uint32_t> next_data_source_index_{};
+ uint32_t muxer_id_for_testing_{};
+
+ // Maximum number of times we will try to reconnect producer backend.
+ // Should only be modified for testing purposes.
+ std::atomic<uint32_t> max_producer_reconnections_{100u};
+
+ // Test only member.
+ // After ResetForTesting() is called, holds tracing backends which needs to be
+ // kept alive until all inbound references have gone away. See
+ // SweepDeadBackends().
+ std::list<RegisteredProducerBackend> dead_backends_;
+
+ // Test only member.
+ // Executes these cleanup functions on the calling thread and on the muxer
+ // thread when ResetForTesting() is called.
+ std::list<std::function<void()>> reset_callbacks_;
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/trace_stats.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_STATS_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_STATS_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/trace_stats.gen.h"
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_STATS_H_
+// gen_amalgamated begin header: include/perfetto/tracing/core/tracing_service_state.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_state.gen.h"
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/internal/tracing_muxer_impl.h"
+
+#include <algorithm>
+#include <atomic>
+#include <mutex>
+#include <optional>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/waitable_event.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_packet.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_stats.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/tracing_service_state.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/data_source.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/interceptor_trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_backend_fake.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"
+// gen_amalgamated expanded: #include "src/tracing/core/null_trace_writer.h"
+// gen_amalgamated expanded: #include "src/tracing/internal/tracing_muxer_fake.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <io.h> // For dup()
+#else
+#include <unistd.h> // For dup()
+#endif
+
+namespace perfetto {
+namespace internal {
+
+namespace {
+
+using RegisteredDataSource = TracingMuxerImpl::RegisteredDataSource;
+
+// A task runner which prevents calls to DataSource::Trace() while an operation
+// is in progress. Used to guard against unexpected re-entrancy where the
+// user-provided task runner implementation tries to enter a trace point under
+// the hood.
+class NonReentrantTaskRunner : public base::TaskRunner {
+ public:
+ NonReentrantTaskRunner(TracingMuxer* muxer,
+ std::unique_ptr<base::TaskRunner> task_runner)
+ : muxer_(muxer), task_runner_(std::move(task_runner)) {}
+
+ // base::TaskRunner implementation.
+ void PostTask(std::function<void()> task) override {
+ CallWithGuard([&] { task_runner_->PostTask(std::move(task)); });
+ }
+
+ void PostDelayedTask(std::function<void()> task, uint32_t delay_ms) override {
+ CallWithGuard(
+ [&] { task_runner_->PostDelayedTask(std::move(task), delay_ms); });
+ }
+
+ void AddFileDescriptorWatch(base::PlatformHandle fd,
+ std::function<void()> callback) override {
+ CallWithGuard(
+ [&] { task_runner_->AddFileDescriptorWatch(fd, std::move(callback)); });
+ }
+
+ void RemoveFileDescriptorWatch(base::PlatformHandle fd) override {
+ CallWithGuard([&] { task_runner_->RemoveFileDescriptorWatch(fd); });
+ }
+
+ bool RunsTasksOnCurrentThread() const override {
+ bool result;
+ CallWithGuard([&] { result = task_runner_->RunsTasksOnCurrentThread(); });
+ return result;
+ }
+
+ private:
+ template <typename T>
+ void CallWithGuard(T lambda) const {
+ auto* root_tls = muxer_->GetOrCreateTracingTLS();
+ if (PERFETTO_UNLIKELY(root_tls->is_in_trace_point)) {
+ lambda();
+ return;
+ }
+ ScopedReentrancyAnnotator scoped_annotator(*root_tls);
+ lambda();
+ }
+
+ TracingMuxer* const muxer_;
+ std::unique_ptr<base::TaskRunner> task_runner_;
+};
+
+class StopArgsImpl : public DataSourceBase::StopArgs {
+ public:
+ std::function<void()> HandleStopAsynchronously() const override {
+ auto closure = std::move(async_stop_closure);
+ async_stop_closure = std::function<void()>();
+ return closure;
+ }
+
+ mutable std::function<void()> async_stop_closure;
+};
+
+class FlushArgsImpl : public DataSourceBase::FlushArgs {
+ public:
+ std::function<void()> HandleFlushAsynchronously() const override {
+ auto closure = std::move(async_flush_closure);
+ async_flush_closure = std::function<void()>();
+ return closure;
+ }
+
+ mutable std::function<void()> async_flush_closure;
+};
+
+// Holds an earlier TracingMuxerImpl instance after ResetForTesting() is called.
+static TracingMuxerImpl* g_prev_instance{};
+
+template <typename RegisteredBackend>
+struct CompareBackendByType {
+ static int BackendTypePriority(BackendType type) {
+ switch (type) {
+ case kSystemBackend:
+ return 0;
+ case kInProcessBackend:
+ return 1;
+ case kCustomBackend:
+ return 2;
+ // The UnspecifiedBackend has the highest priority so that
+ // TracingBackendFake is the last one on the backend lists.
+ case kUnspecifiedBackend:
+ break;
+ }
+ return 3;
+ }
+ bool operator()(BackendType type, const RegisteredBackend& b) {
+ return BackendTypePriority(type) < BackendTypePriority(b.type);
+ }
+};
+
+} // namespace
+
+// ----- Begin of TracingMuxerImpl::ProducerImpl
+TracingMuxerImpl::ProducerImpl::ProducerImpl(
+ TracingMuxerImpl* muxer,
+ TracingBackendId backend_id,
+ uint32_t shmem_batch_commits_duration_ms,
+ bool shmem_direct_patching_enabled)
+ : muxer_(muxer),
+ backend_id_(backend_id),
+ shmem_batch_commits_duration_ms_(shmem_batch_commits_duration_ms),
+ shmem_direct_patching_enabled_(shmem_direct_patching_enabled) {}
+
+TracingMuxerImpl::ProducerImpl::~ProducerImpl() {
+ muxer_ = nullptr;
+}
+
+void TracingMuxerImpl::ProducerImpl::Initialize(
+ std::unique_ptr<ProducerEndpoint> endpoint) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(!connected_);
+ connection_id_.fetch_add(1, std::memory_order_relaxed);
+ is_producer_provided_smb_ = endpoint->shared_memory();
+ last_startup_target_buffer_reservation_ = 0;
+
+ // Adopt the endpoint into a shared pointer so that we can safely share it
+ // across threads that create trace writers. The custom deleter function
+ // ensures that the endpoint is always destroyed on the muxer's thread. (Note
+ // that |task_runner| is assumed to outlive tracing sessions on all threads.)
+ auto* task_runner = muxer_->task_runner_.get();
+ auto deleter = [task_runner](ProducerEndpoint* e) {
+ if (task_runner->RunsTasksOnCurrentThread()) {
+ delete e;
+ return;
+ }
+ task_runner->PostTask([e] { delete e; });
+ };
+ std::shared_ptr<ProducerEndpoint> service(endpoint.release(), deleter);
+ // This atomic store is needed because another thread might be concurrently
+ // creating a trace writer using the previous (disconnected) |service_|. See
+ // CreateTraceWriter().
+ std::atomic_store(&service_, std::move(service));
+ // Don't try to use the service here since it may not have connected yet. See
+ // OnConnect().
+}
+
+void TracingMuxerImpl::ProducerImpl::OnConnect() {
+ PERFETTO_DLOG("Producer connected");
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(!connected_);
+ if (is_producer_provided_smb_ && !service_->IsShmemProvidedByProducer()) {
+ PERFETTO_ELOG(
+ "The service likely doesn't support producer-provided SMBs. Preventing "
+ "future attempts to use producer-provided SMB again with this "
+ "backend.");
+ producer_provided_smb_failed_ = true;
+ // Will call OnDisconnect() and cause a reconnect without producer-provided
+ // SMB.
+ service_->Disconnect();
+ return;
+ }
+ connected_ = true;
+ muxer_->UpdateDataSourcesOnAllBackends();
+ SendOnConnectTriggers();
+}
+
+void TracingMuxerImpl::ProducerImpl::OnDisconnect() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ // If we're being destroyed, bail out.
+ if (!muxer_)
+ return;
+ connected_ = false;
+ // Active data sources for this producer will be stopped by
+ // DestroyStoppedTraceWritersForCurrentThread() since the reconnected producer
+ // will have a different connection id (even before it has finished
+ // connecting).
+ registered_data_sources_.reset();
+ DisposeConnection();
+
+ // Try reconnecting the producer.
+ muxer_->OnProducerDisconnected(this);
+}
+
+void TracingMuxerImpl::ProducerImpl::DisposeConnection() {
+ // Keep the old service around as a dead connection in case it has active
+ // trace writers. If any tracing sessions were created, we can't clear
+ // |service_| here because other threads may be concurrently creating new
+ // trace writers. Any reconnection attempt will atomically swap the new
+ // service in place of the old one.
+ if (did_setup_tracing_ || did_setup_startup_tracing_) {
+ dead_services_.push_back(service_);
+ } else {
+ service_.reset();
+ }
+}
+
+void TracingMuxerImpl::ProducerImpl::OnTracingSetup() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ did_setup_tracing_ = true;
+ service_->MaybeSharedMemoryArbiter()->SetBatchCommitsDuration(
+ shmem_batch_commits_duration_ms_);
+ if (shmem_direct_patching_enabled_) {
+ service_->MaybeSharedMemoryArbiter()->EnableDirectSMBPatching();
+ }
+}
+
+void TracingMuxerImpl::ProducerImpl::OnStartupTracingSetup() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ did_setup_startup_tracing_ = true;
+}
+
+void TracingMuxerImpl::ProducerImpl::SetupDataSource(
+ DataSourceInstanceID id,
+ const DataSourceConfig& cfg) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!muxer_)
+ return;
+ muxer_->SetupDataSource(
+ backend_id_, connection_id_.load(std::memory_order_relaxed), id, cfg);
+}
+
+void TracingMuxerImpl::ProducerImpl::StartDataSource(DataSourceInstanceID id,
+ const DataSourceConfig&) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!muxer_)
+ return;
+ muxer_->StartDataSource(backend_id_, id);
+ service_->NotifyDataSourceStarted(id);
+}
+
+void TracingMuxerImpl::ProducerImpl::StopDataSource(DataSourceInstanceID id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!muxer_)
+ return;
+ muxer_->StopDataSource_AsyncBegin(backend_id_, id);
+}
+
+void TracingMuxerImpl::ProducerImpl::Flush(
+ FlushRequestID flush_id,
+ const DataSourceInstanceID* instances,
+ size_t instance_count,
+ FlushFlags flush_flags) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ bool all_handled = true;
+ if (muxer_) {
+ for (size_t i = 0; i < instance_count; i++) {
+ DataSourceInstanceID ds_id = instances[i];
+ bool handled = muxer_->FlushDataSource_AsyncBegin(backend_id_, ds_id,
+ flush_id, flush_flags);
+ if (!handled) {
+ pending_flushes_[flush_id].insert(ds_id);
+ all_handled = false;
+ }
+ }
+ }
+
+ if (all_handled) {
+ service_->NotifyFlushComplete(flush_id);
+ }
+}
+
+void TracingMuxerImpl::ProducerImpl::ClearIncrementalState(
+ const DataSourceInstanceID* instances,
+ size_t instance_count) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!muxer_)
+ return;
+ for (size_t inst_idx = 0; inst_idx < instance_count; inst_idx++) {
+ muxer_->ClearDataSourceIncrementalState(backend_id_, instances[inst_idx]);
+ }
+}
+
+bool TracingMuxerImpl::ProducerImpl::SweepDeadServices() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto is_unused = [](const std::shared_ptr<ProducerEndpoint>& endpoint) {
+ auto* arbiter = endpoint->MaybeSharedMemoryArbiter();
+ return !arbiter || arbiter->TryShutdown();
+ };
+ for (auto it = dead_services_.begin(); it != dead_services_.end();) {
+ auto next_it = it;
+ next_it++;
+ if (is_unused(*it)) {
+ dead_services_.erase(it);
+ }
+ it = next_it;
+ }
+ return dead_services_.empty();
+}
+
+void TracingMuxerImpl::ProducerImpl::SendOnConnectTriggers() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ base::TimeMillis now = base::GetWallTimeMs();
+ std::vector<std::string> triggers;
+ while (!on_connect_triggers_.empty()) {
+ // Skip if we passed TTL.
+ if (on_connect_triggers_.front().second > now) {
+ triggers.push_back(std::move(on_connect_triggers_.front().first));
+ }
+ on_connect_triggers_.pop_front();
+ }
+ if (!triggers.empty()) {
+ service_->ActivateTriggers(triggers);
+ }
+}
+
+void TracingMuxerImpl::ProducerImpl::NotifyFlushForDataSourceDone(
+ DataSourceInstanceID ds_id,
+ FlushRequestID flush_id) {
+ if (!connected_) {
+ return;
+ }
+
+ {
+ auto it = pending_flushes_.find(flush_id);
+ if (it == pending_flushes_.end()) {
+ return;
+ }
+ std::set<DataSourceInstanceID>& ds_ids = it->second;
+ ds_ids.erase(ds_id);
+ }
+
+ std::optional<DataSourceInstanceID> biggest_flush_id;
+ for (auto it = pending_flushes_.begin(); it != pending_flushes_.end();) {
+ if (it->second.empty()) {
+ biggest_flush_id = it->first;
+ it = pending_flushes_.erase(it);
+ } else {
+ break;
+ }
+ }
+
+ if (biggest_flush_id) {
+ service_->NotifyFlushComplete(*biggest_flush_id);
+ }
+}
+
+// ----- End of TracingMuxerImpl::ProducerImpl methods.
+
+// ----- Begin of TracingMuxerImpl::ConsumerImpl
+TracingMuxerImpl::ConsumerImpl::ConsumerImpl(TracingMuxerImpl* muxer,
+ BackendType backend_type,
+ TracingSessionGlobalID session_id)
+ : muxer_(muxer), backend_type_(backend_type), session_id_(session_id) {}
+
+TracingMuxerImpl::ConsumerImpl::~ConsumerImpl() {
+ muxer_ = nullptr;
+}
+
+void TracingMuxerImpl::ConsumerImpl::Initialize(
+ std::unique_ptr<ConsumerEndpoint> endpoint) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ service_ = std::move(endpoint);
+ // Don't try to use the service here since it may not have connected yet. See
+ // OnConnect().
+}
+
+void TracingMuxerImpl::ConsumerImpl::OnConnect() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(!connected_);
+ connected_ = true;
+
+ // Observe data source instance events so we get notified when tracing starts.
+ service_->ObserveEvents(ObservableEvents::TYPE_DATA_SOURCES_INSTANCES |
+ ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
+
+ // If the API client configured and started tracing before we connected,
+ // tell the backend about it now.
+ if (trace_config_)
+ muxer_->SetupTracingSession(session_id_, trace_config_);
+ if (start_pending_)
+ muxer_->StartTracingSession(session_id_);
+ if (get_trace_stats_pending_) {
+ auto callback = std::move(get_trace_stats_callback_);
+ get_trace_stats_callback_ = nullptr;
+ muxer_->GetTraceStats(session_id_, std::move(callback));
+ }
+ if (query_service_state_callback_) {
+ auto callback = std::move(query_service_state_callback_);
+ query_service_state_callback_ = nullptr;
+ muxer_->QueryServiceState(session_id_, std::move(callback));
+ }
+ if (stop_pending_)
+ muxer_->StopTracingSession(session_id_);
+}
+
+void TracingMuxerImpl::ConsumerImpl::OnDisconnect() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ // If we're being destroyed, bail out.
+ if (!muxer_)
+ return;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ if (!connected_ && backend_type_ == kSystemBackend) {
+ PERFETTO_ELOG(
+ "Unable to connect to the system tracing service as a consumer. On "
+ "Android, use the \"perfetto\" command line tool instead to start "
+ "system-wide tracing sessions");
+ }
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+ // Notify the client about disconnection.
+ NotifyError(TracingError{TracingError::kDisconnected, "Peer disconnected"});
+
+ // Make sure the client doesn't hang in a blocking start/stop because of the
+ // disconnection.
+ NotifyStartComplete();
+ NotifyStopComplete();
+
+ // It shouldn't be necessary to call StopTracingSession. If we get this call
+ // it means that the service did shutdown before us, so there is no point
+ // trying it to ask it to stop the session. We should just remember to cleanup
+ // the consumer vector.
+ connected_ = false;
+
+ // Notify the muxer that it is safe to destroy |this|. This is needed because
+ // the ConsumerEndpoint stored in |service_| requires that |this| be safe to
+ // access until OnDisconnect() is called.
+ muxer_->OnConsumerDisconnected(this);
+}
+
+void TracingMuxerImpl::ConsumerImpl::Disconnect() {
+ // This is weird and deserves a comment.
+ //
+ // When we called the ConnectConsumer method on the service it returns
+ // us a ConsumerEndpoint which we stored in |service_|, however this
+ // ConsumerEndpoint holds a pointer to the ConsumerImpl pointed to by
+ // |this|. Part of the API contract to TracingService::ConnectConsumer is that
+ // the ConsumerImpl pointer has to be valid until the
+ // ConsumerImpl::OnDisconnect method is called. Therefore we reset the
+ // ConsumerEndpoint |service_|. Eventually this will call
+ // ConsumerImpl::OnDisconnect and we will inform the muxer it is safe to
+ // call the destructor of |this|.
+ service_.reset();
+}
+
+void TracingMuxerImpl::ConsumerImpl::OnTracingDisabled(
+ const std::string& error) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(!stopped_);
+ stopped_ = true;
+
+ if (!error.empty())
+ NotifyError(TracingError{TracingError::kTracingFailed, error});
+
+ // If we're still waiting for the start event, fire it now. This may happen if
+ // there are no active data sources in the session.
+ NotifyStartComplete();
+ NotifyStopComplete();
+}
+
+void TracingMuxerImpl::ConsumerImpl::NotifyStartComplete() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (start_complete_callback_) {
+ muxer_->task_runner_->PostTask(std::move(start_complete_callback_));
+ start_complete_callback_ = nullptr;
+ }
+ if (blocking_start_complete_callback_) {
+ muxer_->task_runner_->PostTask(
+ std::move(blocking_start_complete_callback_));
+ blocking_start_complete_callback_ = nullptr;
+ }
+}
+
+void TracingMuxerImpl::ConsumerImpl::NotifyError(const TracingError& error) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (error_callback_) {
+ muxer_->task_runner_->PostTask(
+ std::bind(std::move(error_callback_), error));
+ }
+}
+
+void TracingMuxerImpl::ConsumerImpl::NotifyStopComplete() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (stop_complete_callback_) {
+ muxer_->task_runner_->PostTask(std::move(stop_complete_callback_));
+ stop_complete_callback_ = nullptr;
+ }
+ if (blocking_stop_complete_callback_) {
+ muxer_->task_runner_->PostTask(std::move(blocking_stop_complete_callback_));
+ blocking_stop_complete_callback_ = nullptr;
+ }
+}
+
+void TracingMuxerImpl::ConsumerImpl::OnTraceData(
+ std::vector<TracePacket> packets,
+ bool has_more) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!read_trace_callback_)
+ return;
+
+ size_t capacity = 0;
+ for (const auto& packet : packets) {
+ // 16 is an over-estimation of the proto preamble size
+ capacity += packet.size() + 16;
+ }
+
+ // The shared_ptr is to avoid making a copy of the buffer when PostTask-ing.
+ std::shared_ptr<std::vector<char>> buf(new std::vector<char>());
+ buf->reserve(capacity);
+ for (auto& packet : packets) {
+ char* start;
+ size_t size;
+ std::tie(start, size) = packet.GetProtoPreamble();
+ buf->insert(buf->end(), start, start + size);
+ for (auto& slice : packet.slices()) {
+ const auto* slice_data = reinterpret_cast<const char*>(slice.start);
+ buf->insert(buf->end(), slice_data, slice_data + slice.size);
+ }
+ }
+
+ auto callback = read_trace_callback_;
+ muxer_->task_runner_->PostTask([callback, buf, has_more] {
+ TracingSession::ReadTraceCallbackArgs callback_arg{};
+ callback_arg.data = buf->empty() ? nullptr : &(*buf)[0];
+ callback_arg.size = buf->size();
+ callback_arg.has_more = has_more;
+ callback(callback_arg);
+ });
+
+ if (!has_more)
+ read_trace_callback_ = nullptr;
+}
+
+void TracingMuxerImpl::ConsumerImpl::OnObservableEvents(
+ const ObservableEvents& events) {
+ if (events.instance_state_changes_size()) {
+ for (const auto& state_change : events.instance_state_changes()) {
+ DataSourceHandle handle{state_change.producer_name(),
+ state_change.data_source_name()};
+ data_source_states_[handle] =
+ state_change.state() ==
+ ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED;
+ }
+ }
+
+ if (events.instance_state_changes_size() ||
+ events.all_data_sources_started()) {
+ // Data sources are first reported as being stopped before starting, so once
+ // all the data sources we know about have started we can declare tracing
+ // begun. In the case where there are no matching data sources for the
+ // session, the service will report the all_data_sources_started() event
+ // without adding any instances (only since Android S / Perfetto v10.0).
+ if (start_complete_callback_ || blocking_start_complete_callback_) {
+ bool all_data_sources_started = std::all_of(
+ data_source_states_.cbegin(), data_source_states_.cend(),
+ [](std::pair<DataSourceHandle, bool> state) { return state.second; });
+ if (all_data_sources_started)
+ NotifyStartComplete();
+ }
+ }
+}
+
+void TracingMuxerImpl::ConsumerImpl::OnSessionCloned(
+ const OnSessionClonedArgs&) {
+ // CloneSession is not exposed in the SDK. This should never happen.
+ PERFETTO_DCHECK(false);
+}
+
+void TracingMuxerImpl::ConsumerImpl::OnTraceStats(
+ bool success,
+ const TraceStats& trace_stats) {
+ if (!get_trace_stats_callback_)
+ return;
+ TracingSession::GetTraceStatsCallbackArgs callback_arg{};
+ callback_arg.success = success;
+ callback_arg.trace_stats_data = trace_stats.SerializeAsArray();
+ muxer_->task_runner_->PostTask(
+ std::bind(std::move(get_trace_stats_callback_), std::move(callback_arg)));
+ get_trace_stats_callback_ = nullptr;
+}
+
+// The callbacks below are not used.
+void TracingMuxerImpl::ConsumerImpl::OnDetach(bool) {}
+void TracingMuxerImpl::ConsumerImpl::OnAttach(bool, const TraceConfig&) {}
+// ----- End of TracingMuxerImpl::ConsumerImpl
+
+// ----- Begin of TracingMuxerImpl::TracingSessionImpl
+
+// TracingSessionImpl is the RAII object returned to API clients when they
+// invoke Tracing::CreateTracingSession. They use it for starting/stopping
+// tracing.
+
+TracingMuxerImpl::TracingSessionImpl::TracingSessionImpl(
+ TracingMuxerImpl* muxer,
+ TracingSessionGlobalID session_id,
+ BackendType backend_type)
+ : muxer_(muxer), session_id_(session_id), backend_type_(backend_type) {}
+
+// Can be destroyed from any thread.
+TracingMuxerImpl::TracingSessionImpl::~TracingSessionImpl() {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask(
+ [muxer, session_id] { muxer->DestroyTracingSession(session_id); });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::Setup(const TraceConfig& cfg,
+ int fd) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ std::shared_ptr<TraceConfig> trace_config(new TraceConfig(cfg));
+ if (fd >= 0) {
+ base::ignore_result(backend_type_); // For -Wunused in the amalgamation.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (backend_type_ != kInProcessBackend) {
+ PERFETTO_FATAL(
+ "Passing a file descriptor to TracingSession::Setup() is only "
+ "supported with the kInProcessBackend on Windows. Use "
+ "TracingSession::ReadTrace() instead");
+ }
+#endif
+ trace_config->set_write_into_file(true);
+ fd = dup(fd);
+ }
+ muxer->task_runner_->PostTask([muxer, session_id, trace_config, fd] {
+ muxer->SetupTracingSession(session_id, trace_config, base::ScopedFile(fd));
+ });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::Start() {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask(
+ [muxer, session_id] { muxer->StartTracingSession(session_id); });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::ChangeTraceConfig(
+ const TraceConfig& cfg) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, cfg] {
+ muxer->ChangeTracingSessionConfig(session_id, cfg);
+ });
+}
+
+// Can be called from any thread except the service thread.
+void TracingMuxerImpl::TracingSessionImpl::StartBlocking() {
+ PERFETTO_DCHECK(!muxer_->task_runner_->RunsTasksOnCurrentThread());
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ base::WaitableEvent tracing_started;
+ muxer->task_runner_->PostTask([muxer, session_id, &tracing_started] {
+ auto* consumer = muxer->FindConsumer(session_id);
+ if (!consumer) {
+ // TODO(skyostil): Signal an error to the user.
+ tracing_started.Notify();
+ return;
+ }
+ PERFETTO_DCHECK(!consumer->blocking_start_complete_callback_);
+ consumer->blocking_start_complete_callback_ = [&] {
+ tracing_started.Notify();
+ };
+ muxer->StartTracingSession(session_id);
+ });
+ tracing_started.Wait();
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::Flush(
+ std::function<void(bool)> user_callback,
+ uint32_t timeout_ms) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, timeout_ms, user_callback] {
+ auto* consumer = muxer->FindConsumer(session_id);
+ if (!consumer) {
+ std::move(user_callback)(false);
+ return;
+ }
+ muxer->FlushTracingSession(session_id, timeout_ms,
+ std::move(user_callback));
+ });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::Stop() {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask(
+ [muxer, session_id] { muxer->StopTracingSession(session_id); });
+}
+
+// Can be called from any thread except the service thread.
+void TracingMuxerImpl::TracingSessionImpl::StopBlocking() {
+ PERFETTO_DCHECK(!muxer_->task_runner_->RunsTasksOnCurrentThread());
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ base::WaitableEvent tracing_stopped;
+ muxer->task_runner_->PostTask([muxer, session_id, &tracing_stopped] {
+ auto* consumer = muxer->FindConsumer(session_id);
+ if (!consumer) {
+ // TODO(skyostil): Signal an error to the user.
+ tracing_stopped.Notify();
+ return;
+ }
+ PERFETTO_DCHECK(!consumer->blocking_stop_complete_callback_);
+ consumer->blocking_stop_complete_callback_ = [&] {
+ tracing_stopped.Notify();
+ };
+ muxer->StopTracingSession(session_id);
+ });
+ tracing_stopped.Wait();
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::ReadTrace(ReadTraceCallback cb) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, cb] {
+ muxer->ReadTracingSessionData(session_id, std::move(cb));
+ });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::SetOnStartCallback(
+ std::function<void()> cb) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, cb] {
+ auto* consumer = muxer->FindConsumer(session_id);
+ if (!consumer)
+ return;
+ consumer->start_complete_callback_ = cb;
+ });
+}
+
+// Can be called from any thread
+void TracingMuxerImpl::TracingSessionImpl::SetOnErrorCallback(
+ std::function<void(TracingError)> cb) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, cb] {
+ auto* consumer = muxer->FindConsumer(session_id);
+ if (!consumer) {
+ // Notify the client about concurrent disconnection of the session.
+ if (cb)
+ cb(TracingError{TracingError::kDisconnected, "Peer disconnected"});
+ return;
+ }
+ consumer->error_callback_ = cb;
+ });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::SetOnStopCallback(
+ std::function<void()> cb) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, cb] {
+ auto* consumer = muxer->FindConsumer(session_id);
+ if (!consumer)
+ return;
+ consumer->stop_complete_callback_ = cb;
+ });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::GetTraceStats(
+ GetTraceStatsCallback cb) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, cb] {
+ muxer->GetTraceStats(session_id, std::move(cb));
+ });
+}
+
+// Can be called from any thread.
+void TracingMuxerImpl::TracingSessionImpl::QueryServiceState(
+ QueryServiceStateCallback cb) {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ muxer->task_runner_->PostTask([muxer, session_id, cb] {
+ muxer->QueryServiceState(session_id, std::move(cb));
+ });
+}
+
+// ----- End of TracingMuxerImpl::TracingSessionImpl
+
+// ----- Begin of TracingMuxerImpl::StartupTracingSessionImpl
+
+TracingMuxerImpl::StartupTracingSessionImpl::StartupTracingSessionImpl(
+ TracingMuxerImpl* muxer,
+ TracingSessionGlobalID session_id,
+ BackendType backend_type)
+ : muxer_(muxer), session_id_(session_id), backend_type_(backend_type) {}
+
+// Can be destroyed from any thread.
+TracingMuxerImpl::StartupTracingSessionImpl::~StartupTracingSessionImpl() =
+ default;
+
+void TracingMuxerImpl::StartupTracingSessionImpl::Abort() {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ auto backend_type = backend_type_;
+ muxer->task_runner_->PostTask([muxer, session_id, backend_type] {
+ muxer->AbortStartupTracingSession(session_id, backend_type);
+ });
+}
+
+// Must not be called from the SDK's internal thread.
+void TracingMuxerImpl::StartupTracingSessionImpl::AbortBlocking() {
+ auto* muxer = muxer_;
+ auto session_id = session_id_;
+ auto backend_type = backend_type_;
+ PERFETTO_CHECK(!muxer->task_runner_->RunsTasksOnCurrentThread());
+ base::WaitableEvent event;
+ muxer->task_runner_->PostTask([muxer, session_id, backend_type, &event] {
+ muxer->AbortStartupTracingSession(session_id, backend_type);
+ event.Notify();
+ });
+ event.Wait();
+}
+
+// ----- End of TracingMuxerImpl::StartupTracingSessionImpl
+
+// static
+TracingMuxer* TracingMuxer::instance_ = TracingMuxerFake::Get();
+
+// This is called by perfetto::Tracing::Initialize().
+// Can be called on any thread. Typically, but not necessarily, that will be
+// the embedder's main thread.
+TracingMuxerImpl::TracingMuxerImpl(const TracingInitArgs& args)
+ : TracingMuxer(args.platform ? args.platform
+ : Platform::GetDefaultPlatform()) {
+ PERFETTO_DETACH_FROM_THREAD(thread_checker_);
+ instance_ = this;
+
+ // Create the thread where muxer, producers and service will live.
+ Platform::CreateTaskRunnerArgs tr_args{/*name_for_debugging=*/"TracingMuxer"};
+ task_runner_.reset(new NonReentrantTaskRunner(
+ this, platform_->CreateTaskRunner(std::move(tr_args))));
+
+ // Run the initializer on that thread.
+ task_runner_->PostTask([this, args] {
+ Initialize(args);
+ AddBackends(args);
+ });
+}
+
+void TracingMuxerImpl::Initialize(const TracingInitArgs& args) {
+ PERFETTO_DCHECK_THREAD(thread_checker_); // Rebind the thread checker.
+
+ policy_ = args.tracing_policy;
+ supports_multiple_data_source_instances_ =
+ args.supports_multiple_data_source_instances;
+
+ // Fallback backend for producer creation for an unsupported backend type.
+ PERFETTO_CHECK(producer_backends_.empty());
+ AddProducerBackend(internal::TracingBackendFake::GetInstance(),
+ BackendType::kUnspecifiedBackend, args);
+ // Fallback backend for consumer creation for an unsupported backend type.
+ // This backend simply fails any attempt to start a tracing session.
+ PERFETTO_CHECK(consumer_backends_.empty());
+ AddConsumerBackend(internal::TracingBackendFake::GetInstance(),
+ BackendType::kUnspecifiedBackend);
+}
+
+void TracingMuxerImpl::AddConsumerBackend(TracingConsumerBackend* backend,
+ BackendType type) {
+ if (!backend) {
+ // We skip the log in release builds because the *_backend_fake.cc code
+ // has already an ELOG before returning a nullptr.
+ PERFETTO_DLOG("Consumer backend creation failed, type %d",
+ static_cast<int>(type));
+ return;
+ }
+ // Keep the backends sorted by type.
+ auto it =
+ std::upper_bound(consumer_backends_.begin(), consumer_backends_.end(),
+ type, CompareBackendByType<RegisteredConsumerBackend>());
+ it = consumer_backends_.emplace(it);
+
+ RegisteredConsumerBackend& rb = *it;
+ rb.backend = backend;
+ rb.type = type;
+}
+
+void TracingMuxerImpl::AddProducerBackend(TracingProducerBackend* backend,
+ BackendType type,
+ const TracingInitArgs& args) {
+ if (!backend) {
+ // We skip the log in release builds because the *_backend_fake.cc code
+ // has already an ELOG before returning a nullptr.
+ PERFETTO_DLOG("Producer backend creation failed, type %d",
+ static_cast<int>(type));
+ return;
+ }
+ TracingBackendId backend_id = producer_backends_.size();
+ // Keep the backends sorted by type.
+ auto it =
+ std::upper_bound(producer_backends_.begin(), producer_backends_.end(),
+ type, CompareBackendByType<RegisteredProducerBackend>());
+ it = producer_backends_.emplace(it);
+
+ RegisteredProducerBackend& rb = *it;
+ rb.backend = backend;
+ rb.id = backend_id;
+ rb.type = type;
+ rb.producer.reset(new ProducerImpl(this, backend_id,
+ args.shmem_batch_commits_duration_ms,
+ args.shmem_direct_patching_enabled));
+ rb.producer_conn_args.producer = rb.producer.get();
+ rb.producer_conn_args.producer_name = platform_->GetCurrentProcessName();
+ rb.producer_conn_args.task_runner = task_runner_.get();
+ rb.producer_conn_args.shmem_size_hint_bytes = args.shmem_size_hint_kb * 1024;
+ rb.producer_conn_args.shmem_page_size_hint_bytes =
+ args.shmem_page_size_hint_kb * 1024;
+ rb.producer_conn_args.create_socket_async = args.create_socket_async;
+ rb.producer->Initialize(rb.backend->ConnectProducer(rb.producer_conn_args));
+}
+
+TracingMuxerImpl::RegisteredProducerBackend*
+TracingMuxerImpl::FindProducerBackendById(TracingBackendId id) {
+ for (RegisteredProducerBackend& b : producer_backends_) {
+ if (b.id == id) {
+ return &b;
+ }
+ }
+ return nullptr;
+}
+
+TracingMuxerImpl::RegisteredProducerBackend*
+TracingMuxerImpl::FindProducerBackendByType(BackendType type) {
+ for (RegisteredProducerBackend& b : producer_backends_) {
+ if (b.type == type) {
+ return &b;
+ }
+ }
+ return nullptr;
+}
+
+TracingMuxerImpl::RegisteredConsumerBackend*
+TracingMuxerImpl::FindConsumerBackendByType(BackendType type) {
+ for (RegisteredConsumerBackend& b : consumer_backends_) {
+ if (b.type == type) {
+ return &b;
+ }
+ }
+ return nullptr;
+}
+
+void TracingMuxerImpl::AddBackends(const TracingInitArgs& args) {
+ if (args.backends & kSystemBackend) {
+ PERFETTO_CHECK(args.system_producer_backend_factory_);
+ if (FindProducerBackendByType(kSystemBackend) == nullptr) {
+ AddProducerBackend(args.system_producer_backend_factory_(),
+ kSystemBackend, args);
+ }
+ if (args.enable_system_consumer) {
+ PERFETTO_CHECK(args.system_consumer_backend_factory_);
+ if (FindConsumerBackendByType(kSystemBackend) == nullptr) {
+ AddConsumerBackend(args.system_consumer_backend_factory_(),
+ kSystemBackend);
+ }
+ }
+ }
+
+ if (args.backends & kInProcessBackend) {
+ TracingBackend* b = nullptr;
+ if (FindProducerBackendByType(kInProcessBackend) == nullptr) {
+ if (!b) {
+ PERFETTO_CHECK(args.in_process_backend_factory_);
+ b = args.in_process_backend_factory_();
+ }
+ AddProducerBackend(b, kInProcessBackend, args);
+ }
+ if (FindConsumerBackendByType(kInProcessBackend) == nullptr) {
+ if (!b) {
+ PERFETTO_CHECK(args.in_process_backend_factory_);
+ b = args.in_process_backend_factory_();
+ }
+ AddConsumerBackend(b, kInProcessBackend);
+ }
+ }
+
+ if (args.backends & kCustomBackend) {
+ PERFETTO_CHECK(args.custom_backend);
+ if (FindProducerBackendByType(kCustomBackend) == nullptr) {
+ AddProducerBackend(args.custom_backend, kCustomBackend, args);
+ }
+ if (FindConsumerBackendByType(kCustomBackend) == nullptr) {
+ AddConsumerBackend(args.custom_backend, kCustomBackend);
+ }
+ }
+
+ if (args.backends & ~(kSystemBackend | kInProcessBackend | kCustomBackend)) {
+ PERFETTO_FATAL("Unsupported tracing backend type");
+ }
+}
+
+// Can be called from any thread (but not concurrently).
+bool TracingMuxerImpl::RegisterDataSource(
+ const DataSourceDescriptor& descriptor,
+ DataSourceFactory factory,
+ DataSourceParams params,
+ bool no_flush,
+ DataSourceStaticState* static_state) {
+ // Ignore repeated registrations.
+ if (static_state->index != kMaxDataSources)
+ return true;
+
+ uint32_t new_index = next_data_source_index_++;
+ if (new_index >= kMaxDataSources) {
+ PERFETTO_DLOG(
+ "RegisterDataSource failed: too many data sources already registered");
+ return false;
+ }
+
+ // Initialize the static state.
+ static_assert(sizeof(static_state->instances[0]) >= sizeof(DataSourceState),
+ "instances[] size mismatch");
+ for (size_t i = 0; i < static_state->instances.size(); i++)
+ new (&static_state->instances[i]) DataSourceState{};
+
+ static_state->index = new_index;
+
+ // Generate a semi-unique id for this data source.
+ base::Hasher hash;
+ hash.Update(reinterpret_cast<intptr_t>(static_state));
+ hash.Update(base::GetWallTimeNs().count());
+ static_state->id = hash.digest() ? hash.digest() : 1;
+
+ task_runner_->PostTask([this, descriptor, factory, static_state, params,
+ no_flush] {
+ data_sources_.emplace_back();
+ RegisteredDataSource& rds = data_sources_.back();
+ rds.descriptor = descriptor;
+ rds.factory = factory;
+ rds.supports_multiple_instances =
+ supports_multiple_data_source_instances_ &&
+ params.supports_multiple_instances;
+ rds.requires_callbacks_under_lock = params.requires_callbacks_under_lock;
+ rds.static_state = static_state;
+ rds.no_flush = no_flush;
+
+ UpdateDataSourceOnAllBackends(rds, /*is_changed=*/false);
+ });
+ return true;
+}
+
+// Can be called from any thread (but not concurrently).
+void TracingMuxerImpl::UpdateDataSourceDescriptor(
+ const DataSourceDescriptor& descriptor,
+ const DataSourceStaticState* static_state) {
+ task_runner_->PostTask([this, descriptor, static_state] {
+ for (auto& rds : data_sources_) {
+ if (rds.static_state == static_state) {
+ PERFETTO_CHECK(rds.descriptor.name() == descriptor.name());
+ rds.descriptor = descriptor;
+ rds.descriptor.set_id(static_state->id);
+ UpdateDataSourceOnAllBackends(rds, /*is_changed=*/true);
+ return;
+ }
+ }
+ });
+}
+
+// Can be called from any thread (but not concurrently).
+void TracingMuxerImpl::RegisterInterceptor(
+ const InterceptorDescriptor& descriptor,
+ InterceptorFactory factory,
+ InterceptorBase::TLSFactory tls_factory,
+ InterceptorBase::TracePacketCallback packet_callback) {
+ task_runner_->PostTask([this, descriptor, factory, tls_factory,
+ packet_callback] {
+ // Ignore repeated registrations.
+ for (const auto& interceptor : interceptors_) {
+ if (interceptor.descriptor.name() == descriptor.name()) {
+ PERFETTO_DCHECK(interceptor.tls_factory == tls_factory);
+ PERFETTO_DCHECK(interceptor.packet_callback == packet_callback);
+ return;
+ }
+ }
+ // Only allow certain interceptors for now.
+ if (descriptor.name() != "test_interceptor" &&
+ descriptor.name() != "console" && descriptor.name() != "etwexport") {
+ PERFETTO_ELOG(
+ "Interceptors are experimental. If you want to use them, please "
+ "get in touch with the project maintainers "
+ "(https://perfetto.dev/docs/contributing/"
+ "getting-started#community).");
+ return;
+ }
+ interceptors_.emplace_back();
+ RegisteredInterceptor& interceptor = interceptors_.back();
+ interceptor.descriptor = descriptor;
+ interceptor.factory = factory;
+ interceptor.tls_factory = tls_factory;
+ interceptor.packet_callback = packet_callback;
+ });
+}
+
+void TracingMuxerImpl::ActivateTriggers(
+ const std::vector<std::string>& triggers,
+ uint32_t ttl_ms) {
+ base::TimeMillis expire_time =
+ base::GetWallTimeMs() + base::TimeMillis(ttl_ms);
+ task_runner_->PostTask([this, triggers, expire_time] {
+ for (RegisteredProducerBackend& backend : producer_backends_) {
+ if (backend.producer->connected_) {
+ backend.producer->service_->ActivateTriggers(triggers);
+ } else {
+ for (const std::string& trigger : triggers) {
+ backend.producer->on_connect_triggers_.emplace_back(trigger,
+ expire_time);
+ }
+ }
+ }
+ });
+}
+
+// Checks if there is any matching startup tracing data source instance for a
+// new SetupDataSource call. If so, moves the data source to this tracing
+// session (and its target buffer) and returns true, otherwise returns false.
+static bool MaybeAdoptStartupTracingInDataSource(
+ TracingBackendId backend_id,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID instance_id,
+ const DataSourceConfig& cfg,
+ const std::vector<RegisteredDataSource>& data_sources) {
+ for (const auto& rds : data_sources) {
+ DataSourceStaticState* static_state = rds.static_state;
+ for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
+ auto* internal_state = static_state->TryGet(i);
+
+ if (internal_state &&
+ internal_state->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed) &&
+ internal_state->data_source_instance_id == 0 &&
+ internal_state->backend_id == backend_id &&
+ internal_state->backend_connection_id == backend_connection_id &&
+ internal_state->config &&
+ internal_state->data_source->CanAdoptStartupSession(
+ *internal_state->config, cfg)) {
+ PERFETTO_DLOG("Setting up data source %" PRIu64
+ " %s by adopting it from a startup tracing session",
+ instance_id, cfg.name().c_str());
+
+ std::lock_guard<std::recursive_mutex> lock(internal_state->lock);
+ // Set the associations. The actual takeover happens in
+ // StartDataSource().
+ internal_state->data_source_instance_id = instance_id;
+ internal_state->buffer_id =
+ static_cast<internal::BufferId>(cfg.target_buffer());
+ internal_state->config.reset(new DataSourceConfig(cfg));
+
+ // TODO(eseckler): Should the data souce config provided by the service
+ // be allowed to specify additional interceptors / additional data
+ // source params?
+
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Called by the service of one of the backends.
+void TracingMuxerImpl::SetupDataSource(TracingBackendId backend_id,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID instance_id,
+ const DataSourceConfig& cfg) {
+ PERFETTO_DLOG("Setting up data source %" PRIu64 " %s", instance_id,
+ cfg.name().c_str());
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ // First check if there is any matching startup tracing data source instance.
+ if (MaybeAdoptStartupTracingInDataSource(backend_id, backend_connection_id,
+ instance_id, cfg, data_sources_)) {
+ return;
+ }
+
+ for (const auto& rds : data_sources_) {
+ if (rds.descriptor.name() != cfg.name())
+ continue;
+ DataSourceStaticState& static_state = *rds.static_state;
+
+ // If this data source is already active for this exact config, don't start
+ // another instance. This happens when we have several data sources with the
+ // same name, in which case the service sends one SetupDataSource event for
+ // each one. Since we can't map which event maps to which data source, we
+ // ensure each event only starts one data source instance.
+ // TODO(skyostil): Register a unique id with each data source to the service
+ // to disambiguate.
+ bool active_for_config = false;
+ for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
+ if (!static_state.TryGet(i))
+ continue;
+ auto* internal_state =
+ reinterpret_cast<DataSourceState*>(&static_state.instances[i]);
+ if (internal_state->backend_id == backend_id &&
+ internal_state->backend_connection_id == backend_connection_id &&
+ internal_state->config && *internal_state->config == cfg) {
+ active_for_config = true;
+ break;
+ }
+ }
+ if (active_for_config) {
+ PERFETTO_DLOG(
+ "Data source %s is already active with this config, skipping",
+ cfg.name().c_str());
+ continue;
+ }
+
+ SetupDataSourceImpl(rds, backend_id, backend_connection_id, instance_id,
+ cfg, /*startup_session_id=*/0);
+ return;
+ }
+}
+
+TracingMuxerImpl::FindDataSourceRes TracingMuxerImpl::SetupDataSourceImpl(
+ const RegisteredDataSource& rds,
+ TracingBackendId backend_id,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID instance_id,
+ const DataSourceConfig& cfg,
+ TracingSessionGlobalID startup_session_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ DataSourceStaticState& static_state = *rds.static_state;
+
+ // If any bit is set in `static_state.valid_instances` then at least one
+ // other instance of data source is running.
+ if (!rds.supports_multiple_instances &&
+ static_state.valid_instances.load(std::memory_order_acquire) != 0) {
+ PERFETTO_ELOG(
+ "Failed to setup data source because some another instance of this "
+ "data source is already active");
+ return FindDataSourceRes();
+ }
+
+ for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
+ // Find a free slot.
+ if (static_state.TryGet(i))
+ continue;
+
+ auto* internal_state =
+ reinterpret_cast<DataSourceState*>(&static_state.instances[i]);
+ std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
+ static_assert(
+ std::is_same<decltype(internal_state->data_source_instance_id),
+ DataSourceInstanceID>::value,
+ "data_source_instance_id type mismatch");
+ internal_state->muxer_id_for_testing = muxer_id_for_testing_;
+ RegisteredProducerBackend& backend = *FindProducerBackendById(backend_id);
+
+ if (startup_session_id) {
+ uint16_t& last_reservation =
+ backend.producer->last_startup_target_buffer_reservation_;
+ if (last_reservation == std::numeric_limits<uint16_t>::max()) {
+ PERFETTO_ELOG(
+ "Startup buffer reservations exhausted, dropping data source");
+ return FindDataSourceRes();
+ }
+ internal_state->startup_target_buffer_reservation.store(
+ ++last_reservation, std::memory_order_relaxed);
+ } else {
+ internal_state->startup_target_buffer_reservation.store(
+ 0, std::memory_order_relaxed);
+ }
+
+ internal_state->backend_id = backend_id;
+ internal_state->backend_connection_id = backend_connection_id;
+ internal_state->data_source_instance_id = instance_id;
+ internal_state->buffer_id =
+ static_cast<internal::BufferId>(cfg.target_buffer());
+ internal_state->config.reset(new DataSourceConfig(cfg));
+ internal_state->startup_session_id = startup_session_id;
+ internal_state->data_source = rds.factory();
+ internal_state->interceptor = nullptr;
+ internal_state->interceptor_id = 0;
+
+ if (cfg.has_interceptor_config()) {
+ for (size_t j = 0; j < interceptors_.size(); j++) {
+ if (cfg.interceptor_config().name() ==
+ interceptors_[j].descriptor.name()) {
+ PERFETTO_DLOG("Intercepting data source %" PRIu64
+ " \"%s\" into \"%s\"",
+ instance_id, cfg.name().c_str(),
+ cfg.interceptor_config().name().c_str());
+ internal_state->interceptor_id = static_cast<uint32_t>(j + 1);
+ internal_state->interceptor = interceptors_[j].factory();
+ internal_state->interceptor->OnSetup({cfg});
+ break;
+ }
+ }
+ if (!internal_state->interceptor_id) {
+ PERFETTO_ELOG("Unknown interceptor configured for data source: %s",
+ cfg.interceptor_config().name().c_str());
+ }
+ }
+
+ // This must be made at the end. See matching acquire-load in
+ // DataSource::Trace().
+ static_state.valid_instances.fetch_or(1 << i, std::memory_order_release);
+
+ DataSourceBase::SetupArgs setup_args;
+ setup_args.config = &cfg;
+ setup_args.backend_type = backend.type;
+ setup_args.internal_instance_index = i;
+
+ if (!rds.requires_callbacks_under_lock)
+ lock.unlock();
+ internal_state->data_source->OnSetup(setup_args);
+
+ return FindDataSourceRes(&static_state, internal_state, i,
+ rds.requires_callbacks_under_lock);
+ }
+ PERFETTO_ELOG(
+ "Maximum number of data source instances exhausted. "
+ "Dropping data source %" PRIu64,
+ instance_id);
+ return FindDataSourceRes();
+}
+
+// Called by the service of one of the backends.
+void TracingMuxerImpl::StartDataSource(TracingBackendId backend_id,
+ DataSourceInstanceID instance_id) {
+ PERFETTO_DLOG("Starting data source %" PRIu64, instance_id);
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto ds = FindDataSource(backend_id, instance_id);
+ if (!ds) {
+ PERFETTO_ELOG("Could not find data source to start");
+ return;
+ }
+
+ // Check if the data source was already started for startup tracing.
+ uint16_t startup_reservation =
+ ds.internal_state->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed);
+ if (startup_reservation) {
+ RegisteredProducerBackend& backend = *FindProducerBackendById(backend_id);
+ TracingSessionGlobalID session_id = ds.internal_state->startup_session_id;
+ auto session_it = std::find_if(
+ backend.startup_sessions.begin(), backend.startup_sessions.end(),
+ [session_id](const RegisteredStartupSession& session) {
+ return session.session_id == session_id;
+ });
+ PERFETTO_DCHECK(session_it != backend.startup_sessions.end());
+
+ if (session_it->is_aborting) {
+ PERFETTO_DLOG("Data source %" PRIu64
+ " was already aborted for startup tracing, not starting it",
+ instance_id);
+ return;
+ }
+
+ PERFETTO_DLOG(
+ "Data source %" PRIu64
+ " was already started for startup tracing, binding its target buffer",
+ instance_id);
+
+ backend.producer->service_->MaybeSharedMemoryArbiter()
+ ->BindStartupTargetBuffer(startup_reservation,
+ ds.internal_state->buffer_id);
+
+ // The reservation ID can be used even after binding it, so there's no need
+ // for any barriers here - we just need atomicity.
+ ds.internal_state->startup_target_buffer_reservation.store(
+ 0, std::memory_order_relaxed);
+
+ // TODO(eseckler): Should we reset incremental state at this point, or
+ // notify the data source some other way?
+
+ // The session should not have been fully bound yet (or aborted).
+ PERFETTO_DCHECK(session_it->num_unbound_data_sources > 0);
+
+ session_it->num_unbound_data_sources--;
+ if (session_it->num_unbound_data_sources == 0) {
+ if (session_it->on_adopted)
+ task_runner_->PostTask(session_it->on_adopted);
+ backend.startup_sessions.erase(session_it);
+ }
+ return;
+ }
+
+ StartDataSourceImpl(ds);
+}
+
+void TracingMuxerImpl::StartDataSourceImpl(const FindDataSourceRes& ds) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ DataSourceBase::StartArgs start_args{};
+ start_args.internal_instance_index = ds.instance_idx;
+
+ std::unique_lock<std::recursive_mutex> lock(ds.internal_state->lock);
+ if (ds.internal_state->interceptor)
+ ds.internal_state->interceptor->OnStart({});
+ ds.internal_state->trace_lambda_enabled.store(true,
+ std::memory_order_relaxed);
+ PERFETTO_DCHECK(ds.internal_state->data_source != nullptr);
+
+ if (!ds.requires_callbacks_under_lock)
+ lock.unlock();
+ ds.internal_state->data_source->OnStart(start_args);
+}
+
+// Called by the service of one of the backends.
+void TracingMuxerImpl::StopDataSource_AsyncBegin(
+ TracingBackendId backend_id,
+ DataSourceInstanceID instance_id) {
+ PERFETTO_DLOG("Stopping data source %" PRIu64, instance_id);
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto ds = FindDataSource(backend_id, instance_id);
+ if (!ds) {
+ PERFETTO_ELOG("Could not find data source to stop");
+ return;
+ }
+
+ StopDataSource_AsyncBeginImpl(ds);
+}
+
+void TracingMuxerImpl::StopDataSource_AsyncBeginImpl(
+ const FindDataSourceRes& ds) {
+ TracingBackendId backend_id = ds.internal_state->backend_id;
+ uint32_t backend_connection_id = ds.internal_state->backend_connection_id;
+ DataSourceInstanceID instance_id = ds.internal_state->data_source_instance_id;
+
+ StopArgsImpl stop_args{};
+ stop_args.internal_instance_index = ds.instance_idx;
+ stop_args.async_stop_closure = [this, backend_id, backend_connection_id,
+ instance_id, ds] {
+ // TracingMuxerImpl is long lived, capturing |this| is okay.
+ // The notification closure can be moved out of the StopArgs by the
+ // embedder to handle stop asynchronously. The embedder might then
+ // call the closure on a different thread than the current one, hence
+ // this nested PostTask().
+ task_runner_->PostTask(
+ [this, backend_id, backend_connection_id, instance_id, ds] {
+ StopDataSource_AsyncEnd(backend_id, backend_connection_id,
+ instance_id, ds);
+ });
+ };
+
+ {
+ std::unique_lock<std::recursive_mutex> lock(ds.internal_state->lock);
+
+ // Don't call OnStop again if the datasource is already stopping.
+ if (ds.internal_state->async_stop_in_progress)
+ return;
+ ds.internal_state->async_stop_in_progress = true;
+
+ if (ds.internal_state->interceptor)
+ ds.internal_state->interceptor->OnStop({});
+
+ if (!ds.requires_callbacks_under_lock)
+ lock.unlock();
+ ds.internal_state->data_source->OnStop(stop_args);
+ }
+
+ // If the embedder hasn't called StopArgs.HandleStopAsynchronously() run the
+ // async closure here. In theory we could avoid the PostTask and call
+ // straight into CompleteDataSourceAsyncStop(). We keep that to reduce
+ // divergencies between the deferred-stop vs non-deferred-stop code paths.
+ if (stop_args.async_stop_closure)
+ std::move(stop_args.async_stop_closure)();
+}
+
+void TracingMuxerImpl::StopDataSource_AsyncEnd(TracingBackendId backend_id,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID instance_id,
+ const FindDataSourceRes& ds) {
+ PERFETTO_DLOG("Ending async stop of data source %" PRIu64, instance_id);
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ // Check that the data source instance is still active and was not modified
+ // while it was being stopped.
+ if (!ds.static_state->TryGet(ds.instance_idx) ||
+ ds.internal_state->backend_id != backend_id ||
+ ds.internal_state->backend_connection_id != backend_connection_id ||
+ ds.internal_state->data_source_instance_id != instance_id) {
+ PERFETTO_ELOG(
+ "Async stop of data source %" PRIu64
+ " failed. This might be due to calling the async_stop_closure twice.",
+ instance_id);
+ return;
+ }
+
+ const uint32_t mask = ~(1 << ds.instance_idx);
+ ds.static_state->valid_instances.fetch_and(mask, std::memory_order_acq_rel);
+
+ // Take the mutex to prevent that the data source is in the middle of
+ // a Trace() execution where it called GetDataSourceLocked() while we
+ // destroy it.
+ uint16_t startup_buffer_reservation;
+ TracingSessionGlobalID startup_session_id;
+ {
+ std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
+ ds.internal_state->trace_lambda_enabled.store(false,
+ std::memory_order_relaxed);
+ ds.internal_state->data_source.reset();
+ ds.internal_state->interceptor.reset();
+ ds.internal_state->config.reset();
+ ds.internal_state->async_stop_in_progress = false;
+ startup_buffer_reservation =
+ ds.internal_state->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed);
+ startup_session_id = ds.internal_state->startup_session_id;
+ }
+
+ // The other fields of internal_state are deliberately *not* cleared.
+ // See races-related comments of DataSource::Trace().
+
+ TracingMuxer::generation_++;
+
+ // |producer_backends_| is append-only, Backend instances are always valid.
+ PERFETTO_CHECK(backend_id < producer_backends_.size());
+ RegisteredProducerBackend& backend = *FindProducerBackendById(backend_id);
+ ProducerImpl* producer = backend.producer.get();
+ if (!producer)
+ return;
+
+ // If the data source instance still has a startup buffer reservation, it was
+ // only active for startup tracing and never started by the service. Discard
+ // the startup buffer reservation.
+ if (startup_buffer_reservation) {
+ PERFETTO_DCHECK(startup_session_id);
+
+ if (producer->service_ && producer->service_->MaybeSharedMemoryArbiter()) {
+ producer->service_->MaybeSharedMemoryArbiter()
+ ->AbortStartupTracingForReservation(startup_buffer_reservation);
+ }
+
+ auto session_it = std::find_if(
+ backend.startup_sessions.begin(), backend.startup_sessions.end(),
+ [startup_session_id](const RegisteredStartupSession& session) {
+ return session.session_id == startup_session_id;
+ });
+
+ // Session should not be removed until abortion of all data source instances
+ // is complete.
+ PERFETTO_DCHECK(session_it != backend.startup_sessions.end());
+
+ session_it->num_aborting_data_sources--;
+ if (session_it->num_aborting_data_sources == 0) {
+ if (session_it->on_aborted)
+ task_runner_->PostTask(session_it->on_aborted);
+
+ backend.startup_sessions.erase(session_it);
+ }
+ }
+
+ if (producer->connected_ &&
+ backend.producer->connection_id_.load(std::memory_order_relaxed) ==
+ backend_connection_id) {
+ // Flush any commits that might have been batched by SharedMemoryArbiter.
+ producer->service_->MaybeSharedMemoryArbiter()
+ ->FlushPendingCommitDataRequests();
+ if (instance_id)
+ producer->service_->NotifyDataSourceStopped(instance_id);
+ }
+ producer->SweepDeadServices();
+}
+
+void TracingMuxerImpl::ClearDataSourceIncrementalState(
+ TracingBackendId backend_id,
+ DataSourceInstanceID instance_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Clearing incremental state for data source %" PRIu64,
+ instance_id);
+ auto ds = FindDataSource(backend_id, instance_id);
+ if (!ds) {
+ PERFETTO_ELOG("Could not find data source to clear incremental state for");
+ return;
+ }
+
+ DataSourceBase::ClearIncrementalStateArgs clear_incremental_state_args;
+ clear_incremental_state_args.internal_instance_index = ds.instance_idx;
+ {
+ std::unique_lock<std::recursive_mutex> lock;
+ if (ds.requires_callbacks_under_lock)
+ lock = std::unique_lock<std::recursive_mutex>(ds.internal_state->lock);
+ ds.internal_state->data_source->WillClearIncrementalState(
+ clear_incremental_state_args);
+ }
+
+ // Make DataSource::TraceContext::GetIncrementalState() eventually notice that
+ // the incremental state should be cleared.
+ ds.static_state->incremental_state_generation.fetch_add(
+ 1, std::memory_order_relaxed);
+}
+
+bool TracingMuxerImpl::FlushDataSource_AsyncBegin(
+ TracingBackendId backend_id,
+ DataSourceInstanceID instance_id,
+ FlushRequestID flush_id,
+ FlushFlags flush_flags) {
+ PERFETTO_DLOG("Flushing data source %" PRIu64, instance_id);
+ auto ds = FindDataSource(backend_id, instance_id);
+ if (!ds) {
+ PERFETTO_ELOG("Could not find data source to flush");
+ return true;
+ }
+
+ uint32_t backend_connection_id = ds.internal_state->backend_connection_id;
+
+ FlushArgsImpl flush_args;
+ flush_args.flush_flags = flush_flags;
+ flush_args.internal_instance_index = ds.instance_idx;
+ flush_args.async_flush_closure = [this, backend_id, backend_connection_id,
+ instance_id, ds, flush_id] {
+ // TracingMuxerImpl is long lived, capturing |this| is okay.
+ // The notification closure can be moved out of the StopArgs by the
+ // embedder to handle stop asynchronously. The embedder might then
+ // call the closure on a different thread than the current one, hence
+ // this nested PostTask().
+ task_runner_->PostTask(
+ [this, backend_id, backend_connection_id, instance_id, ds, flush_id] {
+ FlushDataSource_AsyncEnd(backend_id, backend_connection_id,
+ instance_id, ds, flush_id);
+ });
+ };
+ {
+ std::unique_lock<std::recursive_mutex> lock;
+ if (ds.requires_callbacks_under_lock)
+ lock = std::unique_lock<std::recursive_mutex>(ds.internal_state->lock);
+ ds.internal_state->data_source->OnFlush(flush_args);
+ }
+
+ // |async_flush_closure| is moved out of |flush_args| if the producer
+ // requested to handle the flush asynchronously.
+ bool handled = static_cast<bool>(flush_args.async_flush_closure);
+ return handled;
+}
+
+void TracingMuxerImpl::FlushDataSource_AsyncEnd(
+ TracingBackendId backend_id,
+ uint32_t backend_connection_id,
+ DataSourceInstanceID instance_id,
+ const FindDataSourceRes& ds,
+ FlushRequestID flush_id) {
+ PERFETTO_DLOG("Ending async flush of data source %" PRIu64, instance_id);
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ // Check that the data source instance is still active and was not modified
+ // while it was being flushed.
+ if (!ds.static_state->TryGet(ds.instance_idx) ||
+ ds.internal_state->backend_id != backend_id ||
+ ds.internal_state->backend_connection_id != backend_connection_id ||
+ ds.internal_state->data_source_instance_id != instance_id) {
+ PERFETTO_ELOG("Async flush of data source %" PRIu64
+ " failed. This might be due to the data source being stopped "
+ "in the meantime",
+ instance_id);
+ return;
+ }
+
+ // |producer_backends_| is append-only, Backend instances are always valid.
+ PERFETTO_CHECK(backend_id < producer_backends_.size());
+ RegisteredProducerBackend& backend = *FindProducerBackendById(backend_id);
+
+ ProducerImpl* producer = backend.producer.get();
+ if (!producer)
+ return;
+
+ // If the tracing service disconnects and reconnects while a data source is
+ // handling a flush request, there's no point is sending the flush reply to
+ // the newly reconnected producer.
+ if (producer->connected_ &&
+ backend.producer->connection_id_.load(std::memory_order_relaxed) ==
+ backend_connection_id) {
+ producer->NotifyFlushForDataSourceDone(instance_id, flush_id);
+ }
+}
+
+void TracingMuxerImpl::SyncProducersForTesting() {
+ std::mutex mutex;
+ std::condition_variable cv;
+
+ // IPC-based producers don't report connection errors explicitly for each
+ // command, but instead with an asynchronous callback
+ // (ProducerImpl::OnDisconnected). This means that the sync command below
+ // may have completed but failed to reach the service because of a
+ // disconnection, but we can't tell until the disconnection message comes
+ // through. To guard against this, we run two whole rounds of sync round-trips
+ // before returning; the first one will detect any disconnected producers and
+ // the second one will ensure any reconnections have completed and all data
+ // sources are registered in the service again.
+ for (size_t i = 0; i < 2; i++) {
+ size_t countdown = std::numeric_limits<size_t>::max();
+ task_runner_->PostTask([this, &mutex, &cv, &countdown] {
+ {
+ std::unique_lock<std::mutex> countdown_lock(mutex);
+ countdown = producer_backends_.size();
+ }
+ for (auto& backend : producer_backends_) {
+ auto* producer = backend.producer.get();
+ producer->service_->Sync([&mutex, &cv, &countdown] {
+ std::unique_lock<std::mutex> countdown_lock(mutex);
+ countdown--;
+ cv.notify_one();
+ });
+ }
+ });
+
+ {
+ std::unique_lock<std::mutex> countdown_lock(mutex);
+ cv.wait(countdown_lock, [&countdown] { return !countdown; });
+ }
+ }
+
+ // Check that all producers are indeed connected.
+ bool done = false;
+ bool all_producers_connected = true;
+ task_runner_->PostTask([this, &mutex, &cv, &done, &all_producers_connected] {
+ for (auto& backend : producer_backends_)
+ all_producers_connected &= backend.producer->connected_;
+ std::unique_lock<std::mutex> lock(mutex);
+ done = true;
+ cv.notify_one();
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&done] { return done; });
+ }
+ PERFETTO_DCHECK(all_producers_connected);
+}
+
+void TracingMuxerImpl::DestroyStoppedTraceWritersForCurrentThread() {
+ // Iterate across all possible data source types.
+ auto cur_generation = generation_.load(std::memory_order_acquire);
+ auto* root_tls = GetOrCreateTracingTLS();
+
+ auto destroy_stopped_instances = [](DataSourceThreadLocalState& tls) {
+ // |tls| has a vector of per-data-source-instance thread-local state.
+ DataSourceStaticState* static_state = tls.static_state;
+ if (!static_state)
+ return; // Slot not used.
+
+ // Iterate across all possible instances for this data source.
+ for (uint32_t inst = 0; inst < kMaxDataSourceInstances; inst++) {
+ DataSourceInstanceThreadLocalState& ds_tls = tls.per_instance[inst];
+ if (!ds_tls.trace_writer)
+ continue;
+
+ DataSourceState* ds_state = static_state->TryGet(inst);
+ if (ds_state &&
+ ds_state->muxer_id_for_testing == ds_tls.muxer_id_for_testing &&
+ ds_state->backend_id == ds_tls.backend_id &&
+ ds_state->backend_connection_id == ds_tls.backend_connection_id &&
+ ds_state->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed) ==
+ ds_tls.startup_target_buffer_reservation &&
+ ds_state->buffer_id == ds_tls.buffer_id &&
+ ds_state->data_source_instance_id == ds_tls.data_source_instance_id) {
+ continue;
+ }
+
+ // The DataSource instance has been destroyed or recycled.
+ ds_tls.Reset(); // Will also destroy the |ds_tls.trace_writer|.
+ }
+ };
+
+ for (size_t ds_idx = 0; ds_idx < kMaxDataSources; ds_idx++) {
+ // |tls| has a vector of per-data-source-instance thread-local state.
+ DataSourceThreadLocalState& tls = root_tls->data_sources_tls[ds_idx];
+ destroy_stopped_instances(tls);
+ }
+ destroy_stopped_instances(root_tls->track_event_tls);
+ root_tls->generation = cur_generation;
+}
+
+// Called both when a new data source is registered or when a new backend
+// connects. In both cases we want to be sure we reflected the data source
+// registrations on the backends.
+void TracingMuxerImpl::UpdateDataSourcesOnAllBackends() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (RegisteredDataSource& rds : data_sources_) {
+ UpdateDataSourceOnAllBackends(rds, /*is_changed=*/false);
+ }
+}
+
+void TracingMuxerImpl::UpdateDataSourceOnAllBackends(RegisteredDataSource& rds,
+ bool is_changed) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (RegisteredProducerBackend& backend : producer_backends_) {
+ // We cannot call RegisterDataSource on the backend before it connects.
+ if (!backend.producer->connected_)
+ continue;
+
+ PERFETTO_DCHECK(rds.static_state->index < kMaxDataSources);
+ bool is_registered = backend.producer->registered_data_sources_.test(
+ rds.static_state->index);
+ if (is_registered && !is_changed)
+ continue;
+
+ if (!rds.descriptor.no_flush()) {
+ rds.descriptor.set_no_flush(rds.no_flush);
+ }
+ rds.descriptor.set_will_notify_on_start(true);
+ rds.descriptor.set_will_notify_on_stop(true);
+ rds.descriptor.set_handles_incremental_state_clear(true);
+ rds.descriptor.set_id(rds.static_state->id);
+ if (is_registered) {
+ backend.producer->service_->UpdateDataSource(rds.descriptor);
+ } else {
+ backend.producer->service_->RegisterDataSource(rds.descriptor);
+ }
+ backend.producer->registered_data_sources_.set(rds.static_state->index);
+ }
+}
+
+void TracingMuxerImpl::SetupTracingSession(
+ TracingSessionGlobalID session_id,
+ const std::shared_ptr<TraceConfig>& trace_config,
+ base::ScopedFile trace_fd) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_CHECK(!trace_fd || trace_config->write_into_file());
+
+ auto* consumer = FindConsumer(session_id);
+ if (!consumer)
+ return;
+
+ consumer->trace_config_ = trace_config;
+ if (trace_fd)
+ consumer->trace_fd_ = std::move(trace_fd);
+
+ if (!consumer->connected_)
+ return;
+
+ // Only used in the deferred start mode.
+ if (trace_config->deferred_start()) {
+ consumer->service_->EnableTracing(*trace_config,
+ std::move(consumer->trace_fd_));
+ }
+}
+
+void TracingMuxerImpl::StartTracingSession(TracingSessionGlobalID session_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto* consumer = FindConsumer(session_id);
+
+ if (!consumer)
+ return;
+
+ if (!consumer->trace_config_) {
+ PERFETTO_ELOG("Must call Setup(config) first");
+ return;
+ }
+
+ if (!consumer->connected_) {
+ consumer->start_pending_ = true;
+ return;
+ }
+
+ consumer->start_pending_ = false;
+ if (consumer->trace_config_->deferred_start()) {
+ consumer->service_->StartTracing();
+ } else {
+ consumer->service_->EnableTracing(*consumer->trace_config_,
+ std::move(consumer->trace_fd_));
+ }
+
+ // TODO implement support for the deferred-start + fast-triggering case.
+}
+
+void TracingMuxerImpl::ChangeTracingSessionConfig(
+ TracingSessionGlobalID session_id,
+ const TraceConfig& trace_config) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto* consumer = FindConsumer(session_id);
+
+ if (!consumer)
+ return;
+
+ if (!consumer->trace_config_) {
+ // Changing the config is only supported for started sessions.
+ PERFETTO_ELOG("Must call Setup(config) and Start() first");
+ return;
+ }
+
+ consumer->trace_config_ = std::make_shared<TraceConfig>(trace_config);
+ if (consumer->connected_)
+ consumer->service_->ChangeTraceConfig(trace_config);
+}
+
+void TracingMuxerImpl::FlushTracingSession(TracingSessionGlobalID session_id,
+ uint32_t timeout_ms,
+ std::function<void(bool)> callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto* consumer = FindConsumer(session_id);
+ if (!consumer || consumer->start_pending_ || consumer->stop_pending_ ||
+ !consumer->trace_config_) {
+ PERFETTO_ELOG("Flush() can be called only after Start() and before Stop()");
+ std::move(callback)(false);
+ return;
+ }
+
+ // For now we don't want to expose the flush reason to the consumer-side SDK
+ // users to avoid misuses until there is a strong need.
+ consumer->service_->Flush(timeout_ms, std::move(callback),
+ FlushFlags(FlushFlags::Initiator::kConsumerSdk,
+ FlushFlags::Reason::kExplicit));
+}
+
+void TracingMuxerImpl::StopTracingSession(TracingSessionGlobalID session_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto* consumer = FindConsumer(session_id);
+ if (!consumer)
+ return;
+
+ if (consumer->start_pending_) {
+ // If the session hasn't started yet, wait until it does before stopping.
+ consumer->stop_pending_ = true;
+ return;
+ }
+
+ consumer->stop_pending_ = false;
+ if (consumer->stopped_) {
+ // If the session was already stopped (e.g., it failed to start), don't try
+ // stopping again.
+ consumer->NotifyStopComplete();
+ } else if (!consumer->trace_config_) {
+ PERFETTO_ELOG("Must call Setup(config) and Start() first");
+ return;
+ } else {
+ consumer->service_->DisableTracing();
+ }
+
+ consumer->trace_config_.reset();
+}
+
+void TracingMuxerImpl::DestroyTracingSession(
+ TracingSessionGlobalID session_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (RegisteredConsumerBackend& backend : consumer_backends_) {
+ // We need to find the consumer (if any) and call Disconnect as we destroy
+ // the tracing session. We can't call Disconnect() inside this for loop
+ // because in the in-process case this will end up to a synchronous call to
+ // OnConsumerDisconnect which will invalidate all the iterators to
+ // |backend.consumers|.
+ ConsumerImpl* consumer = nullptr;
+ for (auto& con : backend.consumers) {
+ if (con->session_id_ == session_id) {
+ consumer = con.get();
+ break;
+ }
+ }
+ if (consumer) {
+ // We broke out of the loop above on the assumption that each backend will
+ // only have a single consumer per session. This DCHECK ensures that
+ // this is the case.
+ PERFETTO_DCHECK(
+ std::count_if(backend.consumers.begin(), backend.consumers.end(),
+ [session_id](const std::unique_ptr<ConsumerImpl>& con) {
+ return con->session_id_ == session_id;
+ }) == 1u);
+ consumer->Disconnect();
+ }
+ }
+}
+
+void TracingMuxerImpl::ReadTracingSessionData(
+ TracingSessionGlobalID session_id,
+ std::function<void(TracingSession::ReadTraceCallbackArgs)> callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto* consumer = FindConsumer(session_id);
+ if (!consumer) {
+ // TODO(skyostil): Signal an error to the user.
+ TracingSession::ReadTraceCallbackArgs callback_arg{};
+ callback(callback_arg);
+ return;
+ }
+ PERFETTO_DCHECK(!consumer->read_trace_callback_);
+ consumer->read_trace_callback_ = std::move(callback);
+ consumer->service_->ReadBuffers();
+}
+
+void TracingMuxerImpl::GetTraceStats(
+ TracingSessionGlobalID session_id,
+ TracingSession::GetTraceStatsCallback callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto* consumer = FindConsumer(session_id);
+ if (!consumer) {
+ TracingSession::GetTraceStatsCallbackArgs callback_arg{};
+ callback_arg.success = false;
+ callback(std::move(callback_arg));
+ return;
+ }
+ PERFETTO_DCHECK(!consumer->get_trace_stats_callback_);
+ consumer->get_trace_stats_callback_ = std::move(callback);
+ if (!consumer->connected_) {
+ consumer->get_trace_stats_pending_ = true;
+ return;
+ }
+ consumer->get_trace_stats_pending_ = false;
+ consumer->service_->GetTraceStats();
+}
+
+void TracingMuxerImpl::QueryServiceState(
+ TracingSessionGlobalID session_id,
+ TracingSession::QueryServiceStateCallback callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto* consumer = FindConsumer(session_id);
+ if (!consumer) {
+ TracingSession::QueryServiceStateCallbackArgs callback_arg{};
+ callback_arg.success = false;
+ callback(std::move(callback_arg));
+ return;
+ }
+ PERFETTO_DCHECK(!consumer->query_service_state_callback_);
+ if (!consumer->connected_) {
+ consumer->query_service_state_callback_ = std::move(callback);
+ return;
+ }
+ auto callback_wrapper = [callback](bool success,
+ protos::gen::TracingServiceState state) {
+ TracingSession::QueryServiceStateCallbackArgs callback_arg{};
+ callback_arg.success = success;
+ callback_arg.service_state_data = state.SerializeAsArray();
+ callback(std::move(callback_arg));
+ };
+ consumer->service_->QueryServiceState({}, std::move(callback_wrapper));
+}
+
+void TracingMuxerImpl::SetBatchCommitsDurationForTesting(
+ uint32_t batch_commits_duration_ms,
+ BackendType backend_type) {
+ for (RegisteredProducerBackend& backend : producer_backends_) {
+ if (backend.producer && backend.producer->connected_ &&
+ backend.type == backend_type) {
+ backend.producer->service_->MaybeSharedMemoryArbiter()
+ ->SetBatchCommitsDuration(batch_commits_duration_ms);
+ }
+ }
+}
+
+bool TracingMuxerImpl::EnableDirectSMBPatchingForTesting(
+ BackendType backend_type) {
+ for (RegisteredProducerBackend& backend : producer_backends_) {
+ if (backend.producer && backend.producer->connected_ &&
+ backend.type == backend_type &&
+ !backend.producer->service_->MaybeSharedMemoryArbiter()
+ ->EnableDirectSMBPatching()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+TracingMuxerImpl::ConsumerImpl* TracingMuxerImpl::FindConsumer(
+ TracingSessionGlobalID session_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ return FindConsumerAndBackend(session_id).first;
+}
+
+std::pair<TracingMuxerImpl::ConsumerImpl*,
+ TracingMuxerImpl::RegisteredConsumerBackend*>
+TracingMuxerImpl::FindConsumerAndBackend(TracingSessionGlobalID session_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (RegisteredConsumerBackend& backend : consumer_backends_) {
+ for (auto& consumer : backend.consumers) {
+ if (consumer->session_id_ == session_id) {
+ return {consumer.get(), &backend};
+ }
+ }
+ }
+ return {nullptr, nullptr};
+}
+
+void TracingMuxerImpl::InitializeConsumer(TracingSessionGlobalID session_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto res = FindConsumerAndBackend(session_id);
+ if (!res.first || !res.second)
+ return;
+ TracingMuxerImpl::ConsumerImpl* consumer = res.first;
+ RegisteredConsumerBackend& backend = *res.second;
+
+ TracingBackend::ConnectConsumerArgs conn_args;
+ conn_args.consumer = consumer;
+ conn_args.task_runner = task_runner_.get();
+ consumer->Initialize(backend.backend->ConnectConsumer(conn_args));
+}
+
+void TracingMuxerImpl::OnConsumerDisconnected(ConsumerImpl* consumer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (RegisteredConsumerBackend& backend : consumer_backends_) {
+ auto pred = [consumer](const std::unique_ptr<ConsumerImpl>& con) {
+ return con.get() == consumer;
+ };
+ backend.consumers.erase(std::remove_if(backend.consumers.begin(),
+ backend.consumers.end(), pred),
+ backend.consumers.end());
+ }
+}
+
+void TracingMuxerImpl::SetMaxProducerReconnectionsForTesting(uint32_t count) {
+ max_producer_reconnections_.store(count);
+}
+
+void TracingMuxerImpl::OnProducerDisconnected(ProducerImpl* producer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (RegisteredProducerBackend& backend : producer_backends_) {
+ if (backend.producer.get() != producer)
+ continue;
+
+ // The tracing service is disconnected. It does not make sense to keep
+ // tracing (we wouldn't be able to commit). On reconnection, the tracing
+ // service will restart the data sources.
+ for (const auto& rds : data_sources_) {
+ DataSourceStaticState* static_state = rds.static_state;
+ for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
+ auto* internal_state = static_state->TryGet(i);
+ if (internal_state && internal_state->backend_id == backend.id &&
+ internal_state->backend_connection_id ==
+ backend.producer->connection_id_.load(
+ std::memory_order_relaxed)) {
+ StopDataSource_AsyncBeginImpl(
+ FindDataSourceRes(static_state, internal_state, i,
+ rds.requires_callbacks_under_lock));
+ }
+ }
+ }
+
+ // Try reconnecting the disconnected producer. If the connection succeeds,
+ // all the data sources will be automatically re-registered.
+ if (producer->connection_id_.load(std::memory_order_relaxed) >
+ max_producer_reconnections_.load()) {
+ // Avoid reconnecting a failing producer too many times. Instead we just
+ // leak the producer instead of trying to avoid further complicating
+ // cross-thread trace writer creation.
+ PERFETTO_ELOG("Producer disconnected too many times; not reconnecting");
+ continue;
+ }
+
+ backend.producer->Initialize(
+ backend.backend->ConnectProducer(backend.producer_conn_args));
+ // Don't use producer-provided SMBs for the next connection unless startup
+ // tracing requires it again.
+ backend.producer_conn_args.use_producer_provided_smb = false;
+ }
+}
+
+void TracingMuxerImpl::SweepDeadBackends() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (auto it = dead_backends_.begin(); it != dead_backends_.end();) {
+ auto next_it = it;
+ next_it++;
+ if (it->producer->SweepDeadServices())
+ dead_backends_.erase(it);
+ it = next_it;
+ }
+}
+
+TracingMuxerImpl::FindDataSourceRes TracingMuxerImpl::FindDataSource(
+ TracingBackendId backend_id,
+ DataSourceInstanceID instance_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ RegisteredProducerBackend& backend = *FindProducerBackendById(backend_id);
+ for (const auto& rds : data_sources_) {
+ DataSourceStaticState* static_state = rds.static_state;
+ for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
+ auto* internal_state = static_state->TryGet(i);
+ if (internal_state && internal_state->backend_id == backend_id &&
+ internal_state->backend_connection_id ==
+ backend.producer->connection_id_.load(
+ std::memory_order_relaxed) &&
+ internal_state->data_source_instance_id == instance_id) {
+ return FindDataSourceRes(static_state, internal_state, i,
+ rds.requires_callbacks_under_lock);
+ }
+ }
+ }
+ return FindDataSourceRes();
+}
+
+// Can be called from any thread.
+std::unique_ptr<TraceWriterBase> TracingMuxerImpl::CreateTraceWriter(
+ DataSourceStaticState* static_state,
+ uint32_t data_source_instance_index,
+ DataSourceState* data_source,
+ BufferExhaustedPolicy buffer_exhausted_policy) {
+ if (PERFETTO_UNLIKELY(data_source->interceptor_id)) {
+ // If the session is being intercepted, return a heap-backed trace writer
+ // instead. This is safe because all the data given to the interceptor is
+ // either thread-local (|instance_index|), statically allocated
+ // (|static_state|) or constant after initialization (|interceptor|). Access
+ // to the interceptor instance itself through |data_source| is protected by
+ // a statically allocated lock (similarly to the data source instance).
+ auto& interceptor = interceptors_[data_source->interceptor_id - 1];
+ return std::unique_ptr<TraceWriterBase>(new InterceptorTraceWriter(
+ interceptor.tls_factory(static_state, data_source_instance_index),
+ interceptor.packet_callback, static_state, data_source_instance_index));
+ }
+ ProducerImpl* producer =
+ FindProducerBackendById(data_source->backend_id)->producer.get();
+ // Atomically load the current service endpoint. We keep the pointer as a
+ // shared pointer on the stack to guard against it from being concurrently
+ // modified on the thread by ProducerImpl::Initialize() swapping in a
+ // reconnected service on the muxer task runner thread.
+ //
+ // The endpoint may also be concurrently modified by SweepDeadServices()
+ // clearing out old disconnected services. We guard against that by
+ // SharedMemoryArbiter keeping track of any outstanding trace writers. After
+ // shutdown has started, the trace writer created below will be a null one
+ // which will drop any written data. See SharedMemoryArbiter::TryShutdown().
+ //
+ // We use an atomic pointer instead of holding a lock because
+ // CreateTraceWriter posts tasks under the hood.
+ std::shared_ptr<ProducerEndpoint> service =
+ std::atomic_load(&producer->service_);
+
+ // The service may have been disconnected and reconnected concurrently after
+ // the data source was enabled, in which case we may not have an arbiter, or
+ // would be creating a TraceWriter for the wrong (a newer) connection / SMB.
+ // Instead, early-out now. A relaxed load is fine here because the atomic_load
+ // above ensures that the |service| isn't newer.
+ if (producer->connection_id_.load(std::memory_order_relaxed) !=
+ data_source->backend_connection_id) {
+ return std::unique_ptr<TraceWriter>(new NullTraceWriter());
+ }
+
+ // We just need a relaxed atomic read here: We can use the reservation ID even
+ // after the buffer was bound, we just need to be sure to read it atomically.
+ uint16_t startup_buffer_reservation =
+ data_source->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed);
+ if (startup_buffer_reservation) {
+ return service->MaybeSharedMemoryArbiter()->CreateStartupTraceWriter(
+ startup_buffer_reservation);
+ }
+ return service->CreateTraceWriter(data_source->buffer_id,
+ buffer_exhausted_policy);
+}
+
+// This is called via the public API Tracing::NewTrace().
+// Can be called from any thread.
+std::unique_ptr<TracingSession> TracingMuxerImpl::CreateTracingSession(
+ BackendType requested_backend_type,
+ TracingConsumerBackend* (*system_backend_factory)()) {
+ TracingSessionGlobalID session_id = ++next_tracing_session_id_;
+
+ // |backend_type| can only specify one backend, not an OR-ed mask.
+ PERFETTO_CHECK((requested_backend_type & (requested_backend_type - 1)) == 0);
+
+ // Capturing |this| is fine because the TracingMuxer is a leaky singleton.
+ task_runner_->PostTask([this, requested_backend_type, session_id,
+ system_backend_factory] {
+ if (requested_backend_type == kSystemBackend && system_backend_factory &&
+ !FindConsumerBackendByType(kSystemBackend)) {
+ AddConsumerBackend(system_backend_factory(), kSystemBackend);
+ }
+ for (RegisteredConsumerBackend& backend : consumer_backends_) {
+ if (requested_backend_type && backend.type &&
+ backend.type != requested_backend_type) {
+ continue;
+ }
+
+ // Create the consumer now, even if we have to ask the embedder below, so
+ // that any other tasks executing after this one can find the consumer and
+ // change its pending attributes.
+ backend.consumers.emplace_back(
+ new ConsumerImpl(this, backend.type, session_id));
+
+ // The last registered backend in |consumer_backends_| is the unsupported
+ // backend without a valid type.
+ if (!backend.type) {
+ PERFETTO_ELOG(
+ "No tracing backend ready for type=%d, consumer will disconnect",
+ requested_backend_type);
+ InitializeConsumer(session_id);
+ return;
+ }
+
+ // Check if the embedder wants to be asked for permission before
+ // connecting the consumer.
+ if (!policy_) {
+ InitializeConsumer(session_id);
+ return;
+ }
+
+ BackendType type = backend.type;
+ TracingPolicy::ShouldAllowConsumerSessionArgs args;
+ args.backend_type = backend.type;
+ args.result_callback = [this, type, session_id](bool allow) {
+ task_runner_->PostTask([this, type, session_id, allow] {
+ if (allow) {
+ InitializeConsumer(session_id);
+ return;
+ }
+
+ PERFETTO_ELOG(
+ "Consumer session for backend type type=%d forbidden, "
+ "consumer will disconnect",
+ type);
+
+ auto* consumer = FindConsumer(session_id);
+ if (!consumer)
+ return;
+
+ consumer->OnDisconnect();
+ });
+ };
+ policy_->ShouldAllowConsumerSession(args);
+ return;
+ }
+ PERFETTO_DFATAL("Not reached");
+ });
+
+ return std::unique_ptr<TracingSession>(
+ new TracingSessionImpl(this, session_id, requested_backend_type));
+}
+
+// static
+// This is called via the public API Tracing::SetupStartupTracing().
+// Can be called from any thread.
+std::unique_ptr<StartupTracingSession>
+TracingMuxerImpl::CreateStartupTracingSession(
+ const TraceConfig& config,
+ Tracing::SetupStartupTracingOpts opts) {
+ BackendType backend_type = opts.backend;
+ // |backend_type| can only specify one backend, not an OR-ed mask.
+ PERFETTO_CHECK((backend_type & (backend_type - 1)) == 0);
+ // The in-process backend doesn't support startup tracing.
+ PERFETTO_CHECK(backend_type != BackendType::kInProcessBackend);
+
+ TracingSessionGlobalID session_id = ++next_tracing_session_id_;
+
+ // Capturing |this| is fine because the TracingMuxer is a leaky singleton.
+ task_runner_->PostTask([this, config, opts, backend_type, session_id] {
+ for (RegisteredProducerBackend& backend : producer_backends_) {
+ if (backend_type && backend.type && backend.type != backend_type) {
+ continue;
+ }
+
+ TracingBackendId backend_id = backend.id;
+
+ // The last registered backend in |producer_backends_| is the unsupported
+ // backend without a valid type.
+ if (!backend.type) {
+ PERFETTO_ELOG(
+ "No tracing backend initialized for type=%d, startup tracing "
+ "failed",
+ backend_type);
+ if (opts.on_setup)
+ opts.on_setup(Tracing::OnStartupTracingSetupCallbackArgs{
+ 0 /* num_data_sources_started */});
+ return;
+ }
+
+ if (!backend.producer->service_ ||
+ !backend.producer->service_->shared_memory()) {
+ // If we unsuccessfully attempted to use a producer-provided SMB in the
+ // past, don't try again.
+ if (backend.producer->producer_provided_smb_failed_) {
+ PERFETTO_ELOG(
+ "Backend %zu doesn't seem to support producer-provided "
+ "SMBs, startup tracing failed",
+ backend_id);
+ if (opts.on_setup)
+ opts.on_setup(Tracing::OnStartupTracingSetupCallbackArgs{
+ 0 /* num_data_sources_started */});
+ return;
+ }
+
+ PERFETTO_DLOG("Reconnecting backend %zu for startup tracing",
+ backend_id);
+ backend.producer_conn_args.use_producer_provided_smb = true;
+ backend.producer->service_->Disconnect(); // Causes a reconnect.
+ PERFETTO_DCHECK(backend.producer->service_ &&
+ backend.producer->service_->MaybeSharedMemoryArbiter());
+ }
+
+ RegisteredStartupSession session;
+ session.session_id = session_id;
+ session.on_aborted = opts.on_aborted;
+ session.on_adopted = opts.on_adopted;
+
+ for (const TraceConfig::DataSource& ds_cfg : config.data_sources()) {
+ // Find all matching data sources and start one instance of each.
+ for (const auto& rds : data_sources_) {
+ if (rds.descriptor.name() != ds_cfg.config().name())
+ continue;
+
+ PERFETTO_DLOG(
+ "Setting up data source %s for startup tracing with target "
+ "buffer reservation %" PRIi32,
+ rds.descriptor.name().c_str(),
+ backend.producer->last_startup_target_buffer_reservation_ + 1u);
+ auto ds = SetupDataSourceImpl(
+ rds, backend_id,
+ backend.producer->connection_id_.load(std::memory_order_relaxed),
+ /*instance_id=*/0, ds_cfg.config(),
+ /*startup_session_id=*/session_id);
+ if (ds) {
+ StartDataSourceImpl(ds);
+ session.num_unbound_data_sources++;
+ }
+ }
+ }
+
+ int num_ds = session.num_unbound_data_sources;
+ auto on_setup = opts.on_setup;
+ if (on_setup) {
+ backend.producer->OnStartupTracingSetup();
+ task_runner_->PostTask([on_setup, num_ds] {
+ on_setup(Tracing::OnStartupTracingSetupCallbackArgs{num_ds});
+ });
+ }
+
+ if (num_ds > 0) {
+ backend.startup_sessions.push_back(std::move(session));
+
+ if (opts.timeout_ms > 0) {
+ task_runner_->PostDelayedTask(
+ [this, session_id, backend_type] {
+ AbortStartupTracingSession(session_id, backend_type);
+ },
+ opts.timeout_ms);
+ }
+ }
+ return;
+ }
+ PERFETTO_DFATAL("Invalid startup tracing session backend");
+ });
+
+ return std::unique_ptr<StartupTracingSession>(
+ new StartupTracingSessionImpl(this, session_id, backend_type));
+}
+
+// Must not be called from the SDK's internal thread.
+std::unique_ptr<StartupTracingSession>
+TracingMuxerImpl::CreateStartupTracingSessionBlocking(
+ const TraceConfig& config,
+ Tracing::SetupStartupTracingOpts opts) {
+ auto previous_on_setup = std::move(opts.on_setup);
+ PERFETTO_CHECK(!task_runner_->RunsTasksOnCurrentThread());
+ base::WaitableEvent event;
+ // It is safe to capture by reference because once on_setup is called only
+ // once before this method returns.
+ opts.on_setup = [&](Tracing::OnStartupTracingSetupCallbackArgs args) {
+ if (previous_on_setup) {
+ previous_on_setup(std::move(args));
+ }
+ event.Notify();
+ };
+ auto session = CreateStartupTracingSession(config, std::move(opts));
+ event.Wait();
+ return session;
+}
+
+void TracingMuxerImpl::AbortStartupTracingSession(
+ TracingSessionGlobalID session_id,
+ BackendType backend_type) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ for (RegisteredProducerBackend& backend : producer_backends_) {
+ if (backend_type != backend.type)
+ continue;
+
+ auto session_it = std::find_if(
+ backend.startup_sessions.begin(), backend.startup_sessions.end(),
+ [session_id](const RegisteredStartupSession& session) {
+ return session.session_id == session_id;
+ });
+
+ // The startup session may have already been aborted or fully adopted.
+ if (session_it == backend.startup_sessions.end())
+ return;
+ if (session_it->is_aborting)
+ return;
+
+ session_it->is_aborting = true;
+
+ // Iterate all data sources and abort them if they weren't adopted yet.
+ for (const auto& rds : data_sources_) {
+ DataSourceStaticState* static_state = rds.static_state;
+ for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
+ auto* internal_state = static_state->TryGet(i);
+ if (internal_state &&
+ internal_state->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed) &&
+ internal_state->data_source_instance_id == 0 &&
+ internal_state->startup_session_id == session_id) {
+ PERFETTO_DLOG(
+ "Aborting startup tracing for data source %s (target buffer "
+ "reservation %" PRIu16 ")",
+ rds.descriptor.name().c_str(),
+ internal_state->startup_target_buffer_reservation.load(
+ std::memory_order_relaxed));
+
+ // Abort the instance asynchronously by stopping it. From this point
+ // onwards, the service will not be able to adopt it via
+ // StartDataSource().
+ session_it->num_aborting_data_sources++;
+ StopDataSource_AsyncBeginImpl(
+ FindDataSourceRes(static_state, internal_state, i,
+ rds.requires_callbacks_under_lock));
+ }
+ }
+ }
+
+ // If we did everything right, we should have aborted all still-unbound data
+ // source instances.
+ PERFETTO_DCHECK(session_it->num_unbound_data_sources ==
+ session_it->num_aborting_data_sources);
+
+ if (session_it->num_aborting_data_sources == 0) {
+ if (session_it->on_aborted)
+ task_runner_->PostTask(session_it->on_aborted);
+
+ backend.startup_sessions.erase(session_it);
+ }
+ return;
+ }
+ // We might reach here in tests because when we start a trace, we post the
+ // Task(AbortStartupTrace, delay=timeout). When we do
+ // perfetto::ResetForTesting, we sweep dead backends, and we are not able to
+ // kill those delayed tasks because TaskRunner doesn't have support for
+ // deleting scheduled future tasks and TaskRunner doesn't have any API for us
+ // to wait for the completion of all the scheduled tasks (apart from
+ // deleting the TaskRunner) and we want to avoid doing that because we need
+ // a long running TaskRunner in muxer.
+ PERFETTO_DLOG("Invalid startup tracing session backend");
+}
+
+void TracingMuxerImpl::InitializeInstance(const TracingInitArgs& args) {
+ if (instance_ != TracingMuxerFake::Get()) {
+ // The tracing muxer was already initialized. We might need to initialize
+ // additional backends that were not configured earlier.
+ auto* muxer = static_cast<TracingMuxerImpl*>(instance_);
+ muxer->task_runner_->PostTask([muxer, args] { muxer->AddBackends(args); });
+ return;
+ }
+ // If we previously had a TracingMuxerImpl instance which was reset,
+ // reinitialize and reuse it instead of trying to create a new one. See
+ // ResetForTesting().
+ if (g_prev_instance) {
+ auto* muxer = g_prev_instance;
+ g_prev_instance = nullptr;
+ instance_ = muxer;
+ muxer->task_runner_->PostTask([muxer, args] {
+ muxer->Initialize(args);
+ muxer->AddBackends(args);
+ });
+ } else {
+ new TracingMuxerImpl(args);
+ }
+}
+
+// static
+void TracingMuxerImpl::ResetForTesting() {
+ // Ideally we'd tear down the entire TracingMuxerImpl, but the lifetimes of
+ // various objects make that a non-starter. In particular:
+ //
+ // 1) Any thread that has entered a trace event has a TraceWriter, which holds
+ // a reference back to ProducerImpl::service_.
+ //
+ // 2) ProducerImpl::service_ has a reference back to the ProducerImpl.
+ //
+ // 3) ProducerImpl holds reference to TracingMuxerImpl::task_runner_, which in
+ // turn depends on TracingMuxerImpl itself.
+ //
+ // Because of this, it's not safe to deallocate TracingMuxerImpl until all
+ // threads have dropped their TraceWriters. Since we can't really ask the
+ // caller to guarantee this, we'll instead reset enough of the muxer's state
+ // so that it can be reinitialized later and ensure all necessary objects from
+ // the old state remain alive until all references have gone away.
+ auto* muxer = reinterpret_cast<TracingMuxerImpl*>(instance_);
+
+ base::WaitableEvent reset_done;
+ auto do_reset = [muxer, &reset_done] {
+ muxer->DestroyStoppedTraceWritersForCurrentThread();
+ // Unregister all data sources so they don't interfere with any future
+ // tracing sessions.
+ for (RegisteredDataSource& rds : muxer->data_sources_) {
+ for (RegisteredProducerBackend& backend : muxer->producer_backends_) {
+ if (!backend.producer->service_ || !backend.producer->connected_)
+ continue;
+ backend.producer->service_->UnregisterDataSource(rds.descriptor.name());
+ }
+ }
+ for (auto& backend : muxer->consumer_backends_) {
+ // Check that no consumer session is currently active on any backend.
+ for (auto& consumer : backend.consumers)
+ PERFETTO_CHECK(!consumer->service_);
+ }
+ for (auto& backend : muxer->producer_backends_) {
+ backend.producer->muxer_ = nullptr;
+ backend.producer->DisposeConnection();
+ muxer->dead_backends_.push_back(std::move(backend));
+ }
+ muxer->consumer_backends_.clear();
+ muxer->producer_backends_.clear();
+ muxer->interceptors_.clear();
+
+ for (auto& ds : muxer->data_sources_) {
+ ds.static_state->ResetForTesting();
+ }
+
+ muxer->data_sources_.clear();
+ muxer->next_data_source_index_ = 0;
+
+ // Free all backends without active trace writers or other inbound
+ // references. Note that even if all the backends get swept, the muxer still
+ // needs to stay around since |task_runner_| is assumed to be long-lived.
+ muxer->SweepDeadBackends();
+
+ // Make sure we eventually discard any per-thread trace writers from the
+ // previous instance.
+ muxer->muxer_id_for_testing_++;
+
+ g_prev_instance = muxer;
+ instance_ = TracingMuxerFake::Get();
+
+ // Call the user provided cleanups on the muxer thread.
+ for (auto& cb : muxer->reset_callbacks_) {
+ cb();
+ }
+
+ reset_done.Notify();
+ };
+
+ // Some tests run the muxer and the test on the same thread. In these cases,
+ // we can reset synchronously.
+ if (muxer->task_runner_->RunsTasksOnCurrentThread()) {
+ do_reset();
+ } else {
+ muxer->DestroyStoppedTraceWritersForCurrentThread();
+ muxer->task_runner_->PostTask(std::move(do_reset));
+ reset_done.Wait();
+ // Call the user provided cleanups also on this thread.
+ for (auto& cb : muxer->reset_callbacks_) {
+ cb();
+ }
+ }
+ muxer->reset_callbacks_.clear();
+}
+
+// static
+void TracingMuxerImpl::Shutdown() {
+ auto* muxer = reinterpret_cast<TracingMuxerImpl*>(instance_);
+
+ // Shutting down on the muxer thread would lead to a deadlock.
+ PERFETTO_CHECK(!muxer->task_runner_->RunsTasksOnCurrentThread());
+ muxer->DestroyStoppedTraceWritersForCurrentThread();
+
+ std::unique_ptr<base::TaskRunner> owned_task_runner(
+ muxer->task_runner_.get());
+ base::WaitableEvent shutdown_done;
+ owned_task_runner->PostTask([muxer, &shutdown_done] {
+ // Check that no consumer session is currently active on any backend.
+ // Producers will be automatically disconnected as a part of deleting the
+ // muxer below.
+ for (auto& backend : muxer->consumer_backends_) {
+ for (auto& consumer : backend.consumers) {
+ PERFETTO_CHECK(!consumer->service_);
+ }
+ }
+ // Make sure no trace writers are lingering around on the muxer thread. Note
+ // that we can't do this for any arbitrary thread in the process; it is the
+ // caller's responsibility to clean them up before shutting down Perfetto.
+ muxer->DestroyStoppedTraceWritersForCurrentThread();
+ // The task runner must be deleted outside the muxer thread. This is done by
+ // `owned_task_runner` above.
+ muxer->task_runner_.release();
+ auto* platform = muxer->platform_;
+ delete muxer;
+ instance_ = TracingMuxerFake::Get();
+ platform->Shutdown();
+ shutdown_done.Notify();
+ });
+ shutdown_done.Wait();
+}
+
+void TracingMuxerImpl::AppendResetForTestingCallback(std::function<void()> cb) {
+ reset_callbacks_.push_back(std::move(cb));
+}
+
+TracingMuxer::~TracingMuxer() = default;
+
+static_assert(std::is_same<internal::BufferId, BufferID>::value,
+ "public's BufferId and tracing/core's BufferID diverged");
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/track_event_internal.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/proc_utils.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_interned_fields.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_category_registry.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_interned_data_index.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/track_event_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
+
+using perfetto::protos::pbzero::ClockSnapshot;
+
+namespace perfetto {
+
+TrackEventSessionObserver::~TrackEventSessionObserver() = default;
+void TrackEventSessionObserver::OnSetup(const DataSourceBase::SetupArgs&) {}
+void TrackEventSessionObserver::OnStart(const DataSourceBase::StartArgs&) {}
+void TrackEventSessionObserver::OnStop(const DataSourceBase::StopArgs&) {}
+void TrackEventSessionObserver::WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs&) {}
+
+TrackEventTlsStateUserData::~TrackEventTlsStateUserData() = default;
+
+namespace internal {
+
+BaseTrackEventInternedDataIndex::~BaseTrackEventInternedDataIndex() = default;
+
+namespace {
+
+static constexpr const char kLegacySlowPrefix[] = "disabled-by-default-";
+static constexpr const char kSlowTag[] = "slow";
+static constexpr const char kDebugTag[] = "debug";
+static constexpr const char kFilteredEventName[] = "FILTERED";
+
+constexpr auto kClockIdIncremental =
+ TrackEventIncrementalState::kClockIdIncremental;
+
+constexpr auto kClockIdAbsolute = TrackEventIncrementalState::kClockIdAbsolute;
+
+class TrackEventSessionObserverRegistry {
+ public:
+ static TrackEventSessionObserverRegistry* GetInstance() {
+ static TrackEventSessionObserverRegistry* instance =
+ new TrackEventSessionObserverRegistry(); // leaked
+ return instance;
+ }
+
+ void AddObserverForRegistry(const TrackEventCategoryRegistry& registry,
+ TrackEventSessionObserver* observer) {
+ std::unique_lock<std::recursive_mutex> lock(mutex_);
+ observers_.emplace_back(&registry, observer);
+ }
+
+ void RemoveObserverForRegistry(const TrackEventCategoryRegistry& registry,
+ TrackEventSessionObserver* observer) {
+ std::unique_lock<std::recursive_mutex> lock(mutex_);
+ observers_.erase(std::remove(observers_.begin(), observers_.end(),
+ RegisteredObserver(&registry, observer)),
+ observers_.end());
+ }
+
+ void ForEachObserverForRegistry(
+ const TrackEventCategoryRegistry& registry,
+ std::function<void(TrackEventSessionObserver*)> callback) {
+ std::unique_lock<std::recursive_mutex> lock(mutex_);
+ for (auto& registered_observer : observers_) {
+ if (&registry == registered_observer.registry) {
+ callback(registered_observer.observer);
+ }
+ }
+ }
+
+ private:
+ struct RegisteredObserver {
+ RegisteredObserver(const TrackEventCategoryRegistry* r,
+ TrackEventSessionObserver* o)
+ : registry(r), observer(o) {}
+ bool operator==(const RegisteredObserver& other) {
+ return registry == other.registry && observer == other.observer;
+ }
+ const TrackEventCategoryRegistry* registry;
+ TrackEventSessionObserver* observer;
+ };
+
+ std::recursive_mutex mutex_;
+ std::vector<RegisteredObserver> observers_;
+};
+
+enum class MatchType { kExact, kPattern };
+
+bool NameMatchesPattern(const std::string& pattern,
+ const std::string& name,
+ MatchType match_type) {
+ // To avoid pulling in all of std::regex, for now we only support a single "*"
+ // wildcard at the end of the pattern.
+ size_t i = pattern.find('*');
+ if (i != std::string::npos) {
+ PERFETTO_DCHECK(i == pattern.size() - 1);
+ if (match_type != MatchType::kPattern)
+ return false;
+ return name.substr(0, i) == pattern.substr(0, i);
+ }
+ return name == pattern;
+}
+
+bool NameMatchesPatternList(const std::vector<std::string>& patterns,
+ const std::string& name,
+ MatchType match_type) {
+ for (const auto& pattern : patterns) {
+ if (NameMatchesPattern(pattern, name, match_type))
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+// static
+const Track TrackEventInternal::kDefaultTrack{};
+
+// static
+std::atomic<int> TrackEventInternal::session_count_{};
+
+// static
+bool TrackEventInternal::Initialize(
+ const TrackEventCategoryRegistry& registry,
+ bool (*register_data_source)(const DataSourceDescriptor&)) {
+ DataSourceDescriptor dsd;
+ dsd.set_name("track_event");
+
+ protozero::HeapBuffered<protos::pbzero::TrackEventDescriptor> ted;
+ for (size_t i = 0; i < registry.category_count(); i++) {
+ auto category = registry.GetCategory(i);
+ // Don't register group categories.
+ if (category->IsGroup())
+ continue;
+ auto cat = ted->add_available_categories();
+ cat->set_name(category->name);
+ if (category->description)
+ cat->set_description(category->description);
+ for (const auto& tag : category->tags) {
+ if (tag)
+ cat->add_tags(tag);
+ }
+ // Disabled-by-default categories get a "slow" tag.
+ if (!strncmp(category->name, kLegacySlowPrefix, strlen(kLegacySlowPrefix)))
+ cat->add_tags(kSlowTag);
+ }
+ dsd.set_track_event_descriptor_raw(ted.SerializeAsString());
+
+ return register_data_source(dsd);
+}
+
+// static
+bool TrackEventInternal::AddSessionObserver(
+ const TrackEventCategoryRegistry& registry,
+ TrackEventSessionObserver* observer) {
+ TrackEventSessionObserverRegistry::GetInstance()->AddObserverForRegistry(
+ registry, observer);
+ return true;
+}
+
+// static
+void TrackEventInternal::RemoveSessionObserver(
+ const TrackEventCategoryRegistry& registry,
+ TrackEventSessionObserver* observer) {
+ TrackEventSessionObserverRegistry::GetInstance()->RemoveObserverForRegistry(
+ registry, observer);
+}
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+static constexpr protos::pbzero::BuiltinClock kDefaultTraceClock =
+ protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
+#else
+static constexpr protos::pbzero::BuiltinClock kDefaultTraceClock =
+ protos::pbzero::BUILTIN_CLOCK_MONOTONIC;
+#endif
+
+// static
+protos::pbzero::BuiltinClock TrackEventInternal::clock_ = kDefaultTraceClock;
+
+// static
+bool TrackEventInternal::disallow_merging_with_system_tracks_ = false;
+
+// static
+void TrackEventInternal::EnableTracing(
+ const TrackEventCategoryRegistry& registry,
+ const protos::gen::TrackEventConfig& config,
+ const DataSourceBase::SetupArgs& args) {
+ for (size_t i = 0; i < registry.category_count(); i++) {
+ if (IsCategoryEnabled(registry, config, *registry.GetCategory(i)))
+ registry.EnableCategoryForInstance(i, args.internal_instance_index);
+ }
+ TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
+ registry, [&](TrackEventSessionObserver* o) { o->OnSetup(args); });
+}
+
+// static
+void TrackEventInternal::OnStart(const TrackEventCategoryRegistry& registry,
+ const DataSourceBase::StartArgs& args) {
+ session_count_.fetch_add(1);
+ TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
+ registry, [&](TrackEventSessionObserver* o) { o->OnStart(args); });
+}
+
+// static
+void TrackEventInternal::OnStop(const TrackEventCategoryRegistry& registry,
+ const DataSourceBase::StopArgs& args) {
+ TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
+ registry, [&](TrackEventSessionObserver* o) { o->OnStop(args); });
+}
+
+// static
+void TrackEventInternal::DisableTracing(
+ const TrackEventCategoryRegistry& registry,
+ uint32_t internal_instance_index) {
+ for (size_t i = 0; i < registry.category_count(); i++)
+ registry.DisableCategoryForInstance(i, internal_instance_index);
+}
+
+// static
+void TrackEventInternal::WillClearIncrementalState(
+ const TrackEventCategoryRegistry& registry,
+ const DataSourceBase::ClearIncrementalStateArgs& args) {
+ TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
+ registry, [&](TrackEventSessionObserver* o) {
+ o->WillClearIncrementalState(args);
+ });
+}
+
+// static
+bool TrackEventInternal::IsCategoryEnabled(
+ const TrackEventCategoryRegistry& registry,
+ const protos::gen::TrackEventConfig& config,
+ const Category& category) {
+ // If this is a group category, check if any of its constituent categories are
+ // enabled. If so, then this one is enabled too.
+ if (category.IsGroup()) {
+ bool result = false;
+ category.ForEachGroupMember([&](const char* member_name, size_t name_size) {
+ for (size_t i = 0; i < registry.category_count(); i++) {
+ const auto ref_category = registry.GetCategory(i);
+ // Groups can't refer to other groups.
+ if (ref_category->IsGroup())
+ continue;
+ // Require an exact match.
+ if (ref_category->name_size() != name_size ||
+ strncmp(ref_category->name, member_name, name_size)) {
+ continue;
+ }
+ if (IsCategoryEnabled(registry, config, *ref_category)) {
+ result = true;
+ // Break ForEachGroupMember() loop.
+ return false;
+ }
+ break;
+ }
+ // No match? Must be a dynamic category.
+ DynamicCategory dyn_category(std::string(member_name, name_size));
+ Category ref_category{Category::FromDynamicCategory(dyn_category)};
+ if (IsCategoryEnabled(registry, config, ref_category)) {
+ result = true;
+ // Break ForEachGroupMember() loop.
+ return false;
+ }
+ // No match found => keep iterating.
+ return true;
+ });
+ return result;
+ }
+
+ auto has_matching_tag = [&](std::function<bool(const char*)> matcher) {
+ for (const auto& tag : category.tags) {
+ if (!tag)
+ break;
+ if (matcher(tag))
+ return true;
+ }
+ // Legacy "disabled-by-default" categories automatically get the "slow" tag.
+ if (!strncmp(category.name, kLegacySlowPrefix, strlen(kLegacySlowPrefix)) &&
+ matcher(kSlowTag)) {
+ return true;
+ }
+ return false;
+ };
+
+ // First try exact matches, then pattern matches.
+ const std::array<MatchType, 2> match_types = {
+ {MatchType::kExact, MatchType::kPattern}};
+ for (auto match_type : match_types) {
+ // 1. Enabled categories.
+ if (NameMatchesPatternList(config.enabled_categories(), category.name,
+ match_type)) {
+ return true;
+ }
+
+ // 2. Enabled tags.
+ if (has_matching_tag([&](const char* tag) {
+ return NameMatchesPatternList(config.enabled_tags(), tag, match_type);
+ })) {
+ return true;
+ }
+
+ // 2.5. A special case for Chrome's legacy disabled-by-default categories.
+ // We treat them as having a "slow" tag with one exception: they can be
+ // enabled by a pattern if the pattern starts with "disabled-by-default-"
+ // itself.
+ if (match_type == MatchType::kExact &&
+ !strncmp(category.name, kLegacySlowPrefix, strlen(kLegacySlowPrefix))) {
+ for (const auto& pattern : config.enabled_categories()) {
+ if (!strncmp(pattern.c_str(), kLegacySlowPrefix,
+ strlen(kLegacySlowPrefix)) &&
+ NameMatchesPattern(pattern, category.name, MatchType::kPattern)) {
+ return true;
+ }
+ }
+ }
+
+ // 3. Disabled categories.
+ if (NameMatchesPatternList(config.disabled_categories(), category.name,
+ match_type)) {
+ return false;
+ }
+
+ // 4. Disabled tags.
+ if (has_matching_tag([&](const char* tag) {
+ if (config.disabled_tags_size()) {
+ return NameMatchesPatternList(config.disabled_tags(), tag,
+ match_type);
+ } else {
+ // The "slow" and "debug" tags are disabled by default.
+ return NameMatchesPattern(kSlowTag, tag, match_type) ||
+ NameMatchesPattern(kDebugTag, tag, match_type);
+ }
+ })) {
+ return false;
+ }
+ }
+
+ // If nothing matched, enable the category by default.
+ return true;
+}
+
+// static
+uint64_t TrackEventInternal::GetTimeNs() {
+ if (GetClockId() == protos::pbzero::BUILTIN_CLOCK_BOOTTIME)
+ return static_cast<uint64_t>(perfetto::base::GetBootTimeNs().count());
+ else if (GetClockId() == protos::pbzero::BUILTIN_CLOCK_MONOTONIC)
+ return static_cast<uint64_t>(perfetto::base::GetWallTimeNs().count());
+ PERFETTO_DCHECK(GetClockId() == protos::pbzero::BUILTIN_CLOCK_MONOTONIC_RAW);
+ return static_cast<uint64_t>(perfetto::base::GetWallTimeRawNs().count());
+}
+
+// static
+TraceTimestamp TrackEventInternal::GetTraceTime() {
+ return {kClockIdIncremental, GetTimeNs()};
+}
+
+// static
+int TrackEventInternal::GetSessionCount() {
+ return session_count_.load();
+}
+
+// static
+void TrackEventInternal::ResetIncrementalState(
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ const TrackEventTlsState& tls_state,
+ const TraceTimestamp& timestamp) {
+ auto sequence_timestamp = timestamp;
+ if (timestamp.clock_id != kClockIdIncremental) {
+ sequence_timestamp = TrackEventInternal::GetTraceTime();
+ }
+
+ incr_state->last_timestamp_ns = sequence_timestamp.value;
+ auto default_track = ThreadTrack::Current();
+ auto ts_unit_multiplier = tls_state.timestamp_unit_multiplier;
+ auto thread_time_counter_track =
+ CounterTrack("thread_time", default_track)
+ .set_is_incremental(true)
+ .set_unit_multiplier(static_cast<int64_t>(ts_unit_multiplier))
+ .set_type(protos::gen::CounterDescriptor::COUNTER_THREAD_TIME_NS);
+ {
+ // Mark any incremental state before this point invalid. Also set up
+ // defaults so that we don't need to repeat constant data for each packet.
+ auto packet = NewTracePacket(
+ trace_writer, incr_state, tls_state, timestamp,
+ protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
+ auto defaults = packet->set_trace_packet_defaults();
+ defaults->set_timestamp_clock_id(tls_state.default_clock);
+ // Establish the default track for this event sequence.
+ auto track_defaults = defaults->set_track_event_defaults();
+ track_defaults->set_track_uuid(default_track.uuid);
+ if (tls_state.enable_thread_time_sampling) {
+ track_defaults->add_extra_counter_track_uuids(
+ thread_time_counter_track.uuid);
+ }
+
+ if (tls_state.default_clock != static_cast<uint32_t>(GetClockId())) {
+ ClockSnapshot* clocks = packet->set_clock_snapshot();
+ // Trace clock.
+ ClockSnapshot::Clock* trace_clock = clocks->add_clocks();
+ trace_clock->set_clock_id(static_cast<uint32_t>(GetClockId()));
+ trace_clock->set_timestamp(sequence_timestamp.value);
+
+ if (PERFETTO_LIKELY(tls_state.default_clock == kClockIdIncremental)) {
+ // Delta-encoded incremental clock in nanoseconds by default but
+ // configurable by |tls_state.timestamp_unit_multiplier|.
+ ClockSnapshot::Clock* clock_incremental = clocks->add_clocks();
+ clock_incremental->set_clock_id(kClockIdIncremental);
+ clock_incremental->set_timestamp(sequence_timestamp.value /
+ ts_unit_multiplier);
+ clock_incremental->set_is_incremental(true);
+ clock_incremental->set_unit_multiplier_ns(ts_unit_multiplier);
+ }
+ if (ts_unit_multiplier > 1) {
+ // absolute clock with custom timestamp_unit_multiplier.
+ ClockSnapshot::Clock* absolute_clock = clocks->add_clocks();
+ absolute_clock->set_clock_id(kClockIdAbsolute);
+ absolute_clock->set_timestamp(sequence_timestamp.value /
+ ts_unit_multiplier);
+ absolute_clock->set_is_incremental(false);
+ absolute_clock->set_unit_multiplier_ns(ts_unit_multiplier);
+ }
+ }
+ }
+
+ // Every thread should write a descriptor for its default track, because most
+ // trace points won't explicitly reference it. We also write the process
+ // descriptor from every thread that writes trace events to ensure it gets
+ // emitted at least once.
+ WriteTrackDescriptor(default_track, trace_writer, incr_state, tls_state,
+ sequence_timestamp);
+
+ WriteTrackDescriptor(ProcessTrack::Current(), trace_writer, incr_state,
+ tls_state, sequence_timestamp);
+
+ if (tls_state.enable_thread_time_sampling) {
+ WriteTrackDescriptor(thread_time_counter_track, trace_writer, incr_state,
+ tls_state, sequence_timestamp);
+ }
+}
+
+// static
+protozero::MessageHandle<protos::pbzero::TracePacket>
+TrackEventInternal::NewTracePacket(TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ const TrackEventTlsState& tls_state,
+ TraceTimestamp timestamp,
+ uint32_t seq_flags) {
+ if (PERFETTO_UNLIKELY(tls_state.default_clock != kClockIdIncremental &&
+ timestamp.clock_id == kClockIdIncremental)) {
+ timestamp.clock_id = tls_state.default_clock;
+ }
+ auto packet = trace_writer->NewTracePacket();
+ auto ts_unit_multiplier = tls_state.timestamp_unit_multiplier;
+ if (PERFETTO_LIKELY(timestamp.clock_id == kClockIdIncremental)) {
+ if (PERFETTO_LIKELY(incr_state->last_timestamp_ns <= timestamp.value)) {
+ // No need to set the clock id here, since kClockIdIncremental is the
+ // clock id assumed by default.
+ auto time_diff_ns = timestamp.value - incr_state->last_timestamp_ns;
+ auto time_diff_units = time_diff_ns / ts_unit_multiplier;
+ packet->set_timestamp(time_diff_units);
+ incr_state->last_timestamp_ns += time_diff_units * ts_unit_multiplier;
+ } else {
+ packet->set_timestamp(timestamp.value / ts_unit_multiplier);
+ packet->set_timestamp_clock_id(ts_unit_multiplier == 1
+ ? static_cast<uint32_t>(GetClockId())
+ : kClockIdAbsolute);
+ }
+ } else if (PERFETTO_LIKELY(timestamp.clock_id == tls_state.default_clock)) {
+ packet->set_timestamp(timestamp.value / ts_unit_multiplier);
+ } else {
+ packet->set_timestamp(timestamp.value);
+ packet->set_timestamp_clock_id(timestamp.clock_id);
+ }
+ packet->set_sequence_flags(seq_flags);
+ return packet;
+}
+
+// static
+void TrackEventInternal::WriteEventName(StaticString event_name,
+ perfetto::EventContext& event_ctx,
+ const TrackEventTlsState&) {
+ if (PERFETTO_LIKELY(event_name.value != nullptr)) {
+ size_t name_iid = InternedEventName::Get(&event_ctx, event_name.value);
+ event_ctx.event()->set_name_iid(name_iid);
+ }
+}
+
+// static
+void TrackEventInternal::WriteEventName(perfetto::DynamicString event_name,
+ perfetto::EventContext& event_ctx,
+ const TrackEventTlsState& tls_state) {
+ if (PERFETTO_UNLIKELY(tls_state.filter_dynamic_event_names)) {
+ event_ctx.event()->set_name(kFilteredEventName,
+ sizeof(kFilteredEventName) - 1);
+ } else {
+ event_ctx.event()->set_name(event_name.value, event_name.length);
+ }
+}
+
+// static
+EventContext TrackEventInternal::WriteEvent(
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ TrackEventTlsState& tls_state,
+ const Category* category,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TraceTimestamp& timestamp,
+ bool on_current_thread_track) {
+ PERFETTO_DCHECK(!incr_state->was_cleared);
+ auto packet = NewTracePacket(trace_writer, incr_state, tls_state, timestamp);
+ EventContext ctx(trace_writer, std::move(packet), incr_state, &tls_state);
+
+ auto track_event = ctx.event();
+ if (type != protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
+ track_event->set_type(type);
+
+ if (tls_state.enable_thread_time_sampling && on_current_thread_track) {
+ int64_t thread_time_ns = base::GetThreadCPUTimeNs().count();
+ auto thread_time_delta_ns =
+ thread_time_ns - incr_state->last_thread_time_ns;
+ incr_state->last_thread_time_ns = thread_time_ns;
+ track_event->add_extra_counter_values(
+ thread_time_delta_ns /
+ static_cast<int64_t>(tls_state.timestamp_unit_multiplier));
+ }
+
+ // We assume that |category| points to the string with static lifetime.
+ // This means we can use their addresses as interning keys.
+ // TODO(skyostil): Intern categories at compile time.
+ if (category && type != protos::pbzero::TrackEvent::TYPE_SLICE_END &&
+ type != protos::pbzero::TrackEvent::TYPE_COUNTER) {
+ category->ForEachGroupMember(
+ [&](const char* member_name, size_t name_size) {
+ size_t category_iid =
+ InternedEventCategory::Get(&ctx, member_name, name_size);
+ track_event->add_category_iids(category_iid);
+ return true;
+ });
+ }
+ return ctx;
+}
+
+// static
+protos::pbzero::DebugAnnotation* TrackEventInternal::AddDebugAnnotation(
+ perfetto::EventContext* event_ctx,
+ const char* name) {
+ auto annotation = event_ctx->event()->add_debug_annotations();
+ annotation->set_name_iid(InternedDebugAnnotationName::Get(event_ctx, name));
+ return annotation;
+}
+
+// static
+protos::pbzero::DebugAnnotation* TrackEventInternal::AddDebugAnnotation(
+ perfetto::EventContext* event_ctx,
+ perfetto::DynamicString name) {
+ auto annotation = event_ctx->event()->add_debug_annotations();
+ annotation->set_name(name.value);
+ return annotation;
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/track_event_interned_fields.cc
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_interned_fields.h"
+
+namespace perfetto {
+namespace internal {
+
+InternedEventCategory::~InternedEventCategory() = default;
+
+// static
+void InternedEventCategory::Add(protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value,
+ size_t length) {
+ auto category = interned_data->add_event_categories();
+ category->set_iid(iid);
+ category->set_name(value, length);
+}
+
+InternedEventName::~InternedEventName() = default;
+
+// static
+void InternedEventName::Add(protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value) {
+ auto name = interned_data->add_event_names();
+ name->set_iid(iid);
+ name->set_name(value);
+}
+
+InternedDebugAnnotationName::~InternedDebugAnnotationName() = default;
+
+// static
+void InternedDebugAnnotationName::Add(
+ protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value) {
+ auto name = interned_data->add_debug_annotation_names();
+ name->set_iid(iid);
+ name->set_name(value);
+}
+
+InternedDebugAnnotationValueTypeName::~InternedDebugAnnotationValueTypeName() =
+ default;
+
+// static
+void InternedDebugAnnotationValueTypeName::Add(
+ protos::pbzero::InternedData* interned_data,
+ size_t iid,
+ const char* value) {
+ auto name = interned_data->add_debug_annotation_value_type_names();
+ name->set_iid(iid);
+ name->set_name(value);
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/platform.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_tls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+
+namespace perfetto {
+
+PlatformThreadLocalObject::~PlatformThreadLocalObject() = default;
+Platform::~Platform() = default;
+
+void Platform::Shutdown() {}
+
+base::PlatformThreadId Platform::GetCurrentThreadId() {
+ return base::GetThreadId();
+}
+
+// static
+std::unique_ptr<PlatformThreadLocalObject>
+PlatformThreadLocalObject::CreateInstance() {
+ return std::unique_ptr<PlatformThreadLocalObject>(new internal::TracingTLS());
+}
+
+// static
+base::PlatformProcessId Platform::process_id_ = 0;
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/traced_value.cc
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_value.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/debug_annotation.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_interned_fields.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+
+namespace perfetto {
+
+namespace internal {
+
+TracedValue CreateTracedValueFromProto(
+ protos::pbzero::DebugAnnotation* annotation,
+ EventContext* event_context) {
+ return TracedValue::CreateFromProto(annotation, event_context);
+}
+
+} // namespace internal
+
+// static
+TracedValue TracedValue::CreateFromProto(
+ protos::pbzero::DebugAnnotation* annotation,
+ EventContext* event_context) {
+ return TracedValue(annotation, event_context, nullptr);
+}
+
+TracedValue::TracedValue(TracedValue&&) = default;
+TracedValue::~TracedValue() = default;
+
+void TracedValue::WriteInt64(int64_t value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_int_value(value);
+}
+
+void TracedValue::WriteUInt64(uint64_t value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_uint_value(value);
+}
+
+void TracedValue::WriteDouble(double value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_double_value(value);
+}
+
+void TracedValue::WriteBoolean(bool value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_bool_value(value);
+}
+
+void TracedValue::WriteString(const char* value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_string_value(value);
+}
+
+void TracedValue::WriteString(const char* value, size_t len) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_string_value(value, len);
+}
+
+void TracedValue::WriteString(const std::string& value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_string_value(value);
+}
+
+void TracedValue::WriteString(std::string_view value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_string_value(value.data(), value.size());
+}
+
+void TracedValue::WritePointer(const void* value) && {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ annotation_->set_pointer_value(reinterpret_cast<uint64_t>(value));
+}
+
+TracedDictionary TracedValue::WriteDictionary() && {
+ // Note: this passes |checked_scope_.is_active_| bit to the parent to be
+ // picked up later by the new TracedDictionary.
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ checked_scope_.Reset();
+
+ PERFETTO_DCHECK(!annotation_->is_finalized());
+ return TracedDictionary(annotation_,
+ protos::pbzero::DebugAnnotation::kDictEntries,
+ event_context_, checked_scope_.parent_scope());
+}
+
+TracedArray TracedValue::WriteArray() && {
+ // Note: this passes |checked_scope_.is_active_| bit to the parent to be
+ // picked up later by the new TracedDictionary.
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ checked_scope_.Reset();
+
+ PERFETTO_DCHECK(!annotation_->is_finalized());
+ return TracedArray(annotation_, event_context_,
+ checked_scope_.parent_scope());
+}
+
+protozero::Message* TracedValue::WriteProtoInternal(const char* name) {
+ if (event_context_) {
+ annotation_->set_proto_type_name_iid(
+ internal::InternedDebugAnnotationValueTypeName::Get(event_context_,
+ name));
+ } else {
+ annotation_->set_proto_type_name(name);
+ }
+ return annotation_->template BeginNestedMessage<protozero::Message>(
+ protos::pbzero::DebugAnnotation::kProtoValueFieldNumber);
+}
+
+TracedArray::TracedArray(TracedValue annotation)
+ : TracedArray(std::move(annotation).WriteArray()) {}
+
+TracedValue TracedArray::AppendItem() {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ return TracedValue(annotation_->add_array_values(), event_context_,
+ &checked_scope_);
+}
+
+TracedDictionary TracedArray::AppendDictionary() {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ return AppendItem().WriteDictionary();
+}
+
+TracedArray TracedArray::AppendArray() {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ return AppendItem().WriteArray();
+}
+
+TracedDictionary::TracedDictionary(TracedValue annotation)
+ : TracedDictionary(std::move(annotation).WriteDictionary()) {}
+
+TracedValue TracedDictionary::AddItem(StaticString key) {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ protos::pbzero::DebugAnnotation* item =
+ message_->BeginNestedMessage<protos::pbzero::DebugAnnotation>(field_id_);
+ item->set_name(key.value);
+ return TracedValue(item, event_context_, &checked_scope_);
+}
+
+TracedValue TracedDictionary::AddItem(DynamicString key) {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ protos::pbzero::DebugAnnotation* item =
+ message_->BeginNestedMessage<protos::pbzero::DebugAnnotation>(field_id_);
+ item->set_name(key.value);
+ return TracedValue(item, event_context_, &checked_scope_);
+}
+
+TracedDictionary TracedDictionary::AddDictionary(StaticString key) {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ return AddItem(key).WriteDictionary();
+}
+
+TracedDictionary TracedDictionary::AddDictionary(DynamicString key) {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ return AddItem(key).WriteDictionary();
+}
+
+TracedArray TracedDictionary::AddArray(StaticString key) {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ return AddItem(key).WriteArray();
+}
+
+TracedArray TracedDictionary::AddArray(DynamicString key) {
+ PERFETTO_DCHECK(checked_scope_.is_active());
+ return AddItem(key).WriteArray();
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/tracing.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing.h"
+
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/no_destructor.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/waitable_event.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+// gen_amalgamated expanded: #include "src/tracing/internal/tracing_muxer_impl.h"
+
+namespace perfetto {
+namespace {
+bool g_was_initialized = false;
+
+// Wrapped in a function to avoid global constructor
+std::mutex& InitializedMutex() {
+ static base::NoDestructor<std::mutex> initialized_mutex;
+ return initialized_mutex.ref();
+}
+} // namespace
+
+// static
+void Tracing::InitializeInternal(const TracingInitArgs& args) {
+ base::InitializeTime();
+ std::unique_lock<std::mutex> lock(InitializedMutex());
+ // If it's the first time Initialize is called, set some global params.
+ if (!g_was_initialized) {
+ // Make sure the headers and implementation files agree on the build config.
+ PERFETTO_CHECK(args.dcheck_is_on_ == PERFETTO_DCHECK_IS_ON());
+ if (args.log_message_callback) {
+ base::SetLogMessageCallback(args.log_message_callback);
+ }
+
+ if (args.use_monotonic_clock) {
+ PERFETTO_CHECK(!args.use_monotonic_raw_clock);
+ internal::TrackEventInternal::SetClockId(
+ protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+ } else if (args.use_monotonic_raw_clock) {
+ internal::TrackEventInternal::SetClockId(
+ protos::pbzero::BUILTIN_CLOCK_MONOTONIC_RAW);
+ }
+
+ if (args.disallow_merging_with_system_tracks) {
+ internal::TrackEventInternal::SetDisallowMergingWithSystemTracks(true);
+ }
+ }
+
+ internal::TracingMuxerImpl::InitializeInstance(args);
+ internal::TrackRegistry::InitializeInstance();
+ g_was_initialized = true;
+}
+
+// static
+bool Tracing::IsInitialized() {
+ std::unique_lock<std::mutex> lock(InitializedMutex());
+ return g_was_initialized;
+}
+
+// static
+void Tracing::Shutdown() {
+ std::unique_lock<std::mutex> lock(InitializedMutex());
+ if (!g_was_initialized)
+ return;
+ internal::TracingMuxerImpl::Shutdown();
+ g_was_initialized = false;
+}
+
+// static
+void Tracing::ResetForTesting() {
+ std::unique_lock<std::mutex> lock(InitializedMutex());
+ if (!g_was_initialized)
+ return;
+ base::SetLogMessageCallback(nullptr);
+ internal::TracingMuxerImpl::ResetForTesting();
+ internal::TrackRegistry::ResetForTesting();
+ g_was_initialized = false;
+}
+
+// static
+std::unique_ptr<TracingSession> Tracing::NewTraceInternal(
+ BackendType backend,
+ TracingConsumerBackend* (*system_backend_factory)()) {
+ return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
+ ->CreateTracingSession(backend, system_backend_factory);
+}
+
+// static
+std::unique_ptr<StartupTracingSession> Tracing::SetupStartupTracing(
+ const TraceConfig& config,
+ Tracing::SetupStartupTracingOpts opts) {
+ return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
+ ->CreateStartupTracingSession(config, std::move(opts));
+}
+
+// static
+std::unique_ptr<StartupTracingSession> Tracing::SetupStartupTracingBlocking(
+ const TraceConfig& config,
+ Tracing::SetupStartupTracingOpts opts) {
+ return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
+ ->CreateStartupTracingSessionBlocking(config, std::move(opts));
+}
+
+// static
+void Tracing::ActivateTriggers(const std::vector<std::string>& triggers,
+ uint32_t ttl_ms) {
+ internal::TracingMuxer::Get()->ActivateTriggers(triggers, ttl_ms);
+}
+
+TracingSession::~TracingSession() = default;
+
+// Can be called from any thread.
+bool TracingSession::FlushBlocking(uint32_t timeout_ms) {
+ std::atomic<bool> flush_result;
+ base::WaitableEvent flush_ack;
+
+ // The non blocking Flush() can be called on any thread. It does the PostTask
+ // internally.
+ Flush(
+ [&flush_ack, &flush_result](bool res) {
+ flush_result = res;
+ flush_ack.Notify();
+ },
+ timeout_ms);
+ flush_ack.Wait();
+ return flush_result;
+}
+
+std::vector<char> TracingSession::ReadTraceBlocking() {
+ std::vector<char> raw_trace;
+ std::mutex mutex;
+ std::condition_variable cv;
+
+ bool all_read = false;
+
+ ReadTrace([&mutex, &raw_trace, &all_read, &cv](ReadTraceCallbackArgs cb) {
+ raw_trace.insert(raw_trace.end(), cb.data, cb.data + cb.size);
+ std::unique_lock<std::mutex> lock(mutex);
+ all_read = !cb.has_more;
+ if (all_read)
+ cv.notify_one();
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&all_read] { return all_read; });
+ }
+ return raw_trace;
+}
+
+TracingSession::GetTraceStatsCallbackArgs
+TracingSession::GetTraceStatsBlocking() {
+ std::mutex mutex;
+ std::condition_variable cv;
+ GetTraceStatsCallbackArgs result;
+ bool stats_read = false;
+
+ GetTraceStats(
+ [&mutex, &result, &stats_read, &cv](GetTraceStatsCallbackArgs args) {
+ result = std::move(args);
+ std::unique_lock<std::mutex> lock(mutex);
+ stats_read = true;
+ cv.notify_one();
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&stats_read] { return stats_read; });
+ }
+ return result;
+}
+
+TracingSession::QueryServiceStateCallbackArgs
+TracingSession::QueryServiceStateBlocking() {
+ std::mutex mutex;
+ std::condition_variable cv;
+ QueryServiceStateCallbackArgs result;
+ bool status_read = false;
+
+ QueryServiceState(
+ [&mutex, &result, &status_read, &cv](QueryServiceStateCallbackArgs args) {
+ result = std::move(args);
+ std::unique_lock<std::mutex> lock(mutex);
+ status_read = true;
+ cv.notify_one();
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&status_read] { return status_read; });
+ }
+ return result;
+}
+
+StartupTracingSession::~StartupTracingSession() = default;
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/tracing_policy.cc
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_policy.h"
+
+namespace perfetto {
+
+TracingPolicy::~TracingPolicy() = default;
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/track.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/track.h"
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_splitter.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/uuid.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_data_source.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
+
+namespace perfetto {
+
+// static
+uint64_t Track::process_uuid;
+
+protos::gen::TrackDescriptor Track::Serialize() const {
+ protos::gen::TrackDescriptor desc;
+ desc.set_uuid(uuid);
+ if (parent_uuid)
+ desc.set_parent_uuid(parent_uuid);
+ return desc;
+}
+
+void Track::Serialize(protos::pbzero::TrackDescriptor* desc) const {
+ auto bytes = Serialize().SerializeAsString();
+ desc->AppendRawProtoBytes(bytes.data(), bytes.size());
+}
+
+protos::gen::TrackDescriptor ProcessTrack::Serialize() const {
+ auto desc = Track::Serialize();
+ auto pd = desc.mutable_process();
+ pd->set_pid(static_cast<int32_t>(pid));
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ std::string cmdline;
+ if (base::ReadFile("/proc/self/cmdline", &cmdline)) {
+ // Since cmdline is a zero-terminated list of arguments, this ends up
+ // writing just the first element, i.e., the process name, into the process
+ // name field.
+ pd->set_process_name(cmdline.c_str());
+ base::StringSplitter splitter(std::move(cmdline), '\0');
+ while (splitter.Next()) {
+ pd->add_cmdline(
+ std::string(splitter.cur_token(), splitter.cur_token_size()));
+ }
+ }
+ // TODO(skyostil): Record command line on Windows and Mac.
+#endif
+ return desc;
+}
+
+void ProcessTrack::Serialize(protos::pbzero::TrackDescriptor* desc) const {
+ auto bytes = Serialize().SerializeAsString();
+ desc->AppendRawProtoBytes(bytes.data(), bytes.size());
+}
+
+protos::gen::TrackDescriptor ThreadTrack::Serialize() const {
+ auto desc = Track::Serialize();
+ auto td = desc.mutable_thread();
+ td->set_pid(static_cast<int32_t>(pid));
+ td->set_tid(static_cast<int32_t>(tid));
+ if (disallow_merging_with_system_tracks) {
+ desc.set_disallow_merging_with_system_tracks(true);
+ }
+ std::string thread_name;
+ if (base::GetThreadName(thread_name))
+ td->set_thread_name(thread_name);
+ return desc;
+}
+
+// static
+ThreadTrack ThreadTrack::Current() {
+ return ThreadTrack(
+ internal::TracingMuxer::Get()->GetCurrentThreadId(),
+ internal::TrackEventInternal::GetDisallowMergingWithSystemTracks());
+}
+
+// static
+ThreadTrack ThreadTrack::ForThread(base::PlatformThreadId tid_) {
+ return ThreadTrack(
+ tid_, internal::TrackEventInternal::GetDisallowMergingWithSystemTracks());
+}
+
+void ThreadTrack::Serialize(protos::pbzero::TrackDescriptor* desc) const {
+ auto bytes = Serialize().SerializeAsString();
+ desc->AppendRawProtoBytes(bytes.data(), bytes.size());
+}
+
+protos::gen::TrackDescriptor CounterTrack::Serialize() const {
+ auto desc = Track::Serialize();
+ desc.set_name(name_);
+ auto* counter = desc.mutable_counter();
+ if (category_)
+ counter->add_categories(category_);
+ if (unit_ != perfetto::protos::pbzero::CounterDescriptor::UNIT_UNSPECIFIED)
+ counter->set_unit(static_cast<protos::gen::CounterDescriptor_Unit>(unit_));
+ {
+ // if |type| is set, we don't want to emit |unit_name|. Trace processor
+ // infers the track name from the type in that case.
+ if (type_ !=
+ perfetto::protos::gen::CounterDescriptor::COUNTER_UNSPECIFIED) {
+ counter->set_type(type_);
+ } else if (unit_name_) {
+ counter->set_unit_name(unit_name_);
+ }
+ }
+ if (unit_multiplier_ != 1)
+ counter->set_unit_multiplier(unit_multiplier_);
+ if (is_incremental_)
+ counter->set_is_incremental(is_incremental_);
+ return desc;
+}
+
+void CounterTrack::Serialize(protos::pbzero::TrackDescriptor* desc) const {
+ auto bytes = Serialize().SerializeAsString();
+ desc->AppendRawProtoBytes(bytes.data(), bytes.size());
+}
+
+namespace internal {
+namespace {
+
+uint64_t GetProcessStartTime() {
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ std::string stat;
+ if (!base::ReadFile("/proc/self/stat", &stat))
+ return 0u;
+ // The stat file is a single line split into space-separated fields as "pid
+ // (comm) state ppid ...". However because the command name can contain any
+ // characters (including parentheses and spaces), we need to skip past it
+ // before parsing the rest of the fields. To do that, we look for the last
+ // instance of ") " (parentheses followed by space) and parse forward from
+ // that point.
+ size_t comm_end = stat.rfind(") ");
+ if (comm_end == std::string::npos)
+ return 0u;
+ stat = stat.substr(comm_end + strlen(") "));
+ base::StringSplitter splitter(stat, ' ');
+ for (size_t skip = 0; skip < 20; skip++) {
+ if (!splitter.Next())
+ return 0u;
+ }
+ return base::CStringToUInt64(splitter.cur_token()).value_or(0u);
+#else
+ return 0;
+#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+}
+
+} // namespace
+
+// static
+TrackRegistry* TrackRegistry::instance_;
+
+TrackRegistry::TrackRegistry() = default;
+TrackRegistry::~TrackRegistry() = default;
+
+// static
+void TrackRegistry::InitializeInstance() {
+ if (instance_)
+ return;
+ instance_ = new TrackRegistry();
+ Track::process_uuid = ComputeProcessUuid();
+}
+
+// static
+uint64_t TrackRegistry::ComputeProcessUuid() {
+ // Use the process start time + pid as the unique identifier for this process.
+ // This ensures that if there are two independent copies of the Perfetto SDK
+ // in the same process (e.g., one in the app and another in a system
+ // framework), events emitted by each will be consistently interleaved on
+ // common thread and process tracks.
+ if (uint64_t start_time = GetProcessStartTime()) {
+ base::Hasher hash;
+ hash.Update(start_time);
+ hash.Update(Platform::GetCurrentProcessId());
+ return hash.digest();
+ }
+ // Fall back to a randomly generated identifier.
+ static uint64_t random_once = static_cast<uint64_t>(base::Uuidv4().lsb());
+ return random_once;
+}
+
+void TrackRegistry::ResetForTesting() {
+ instance_->tracks_.clear();
+}
+
+void TrackRegistry::UpdateTrack(Track track,
+ const std::string& serialized_desc) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ tracks_[track.uuid] = std::move(serialized_desc);
+}
+
+void TrackRegistry::UpdateTrackImpl(
+ Track track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> fill_function) {
+ constexpr size_t kInitialSliceSize = 32;
+ constexpr size_t kMaximumSliceSize = 4096;
+ protozero::HeapBuffered<protos::pbzero::TrackDescriptor> new_descriptor(
+ kInitialSliceSize, kMaximumSliceSize);
+ fill_function(new_descriptor.get());
+ auto serialized_desc = new_descriptor.SerializeAsString();
+ UpdateTrack(track, serialized_desc);
+}
+
+void TrackRegistry::EraseTrack(Track track) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ tracks_.erase(track.uuid);
+}
+
+// static
+void TrackRegistry::WriteTrackDescriptor(
+ const SerializedTrackDescriptor& desc,
+ protozero::MessageHandle<protos::pbzero::TracePacket> packet) {
+ packet->AppendString(
+ perfetto::protos::pbzero::TracePacket::kTrackDescriptorFieldNumber, desc);
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/track_event_category_registry.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_category_registry.h"
+
+namespace perfetto {
+
+// static
+Category Category::FromDynamicCategory(const char* name) {
+ if (GetNthNameSize(1, name, name)) {
+ Category group(Group(name));
+ PERFETTO_DCHECK(group.name);
+ return group;
+ }
+ Category category(name);
+ PERFETTO_DCHECK(category.name);
+ return category;
+}
+
+Category Category::FromDynamicCategory(
+ const DynamicCategory& dynamic_category) {
+ return FromDynamicCategory(dynamic_category.name.c_str());
+}
+
+namespace internal {
+
+perfetto::DynamicCategory NullCategory(const perfetto::DynamicCategory&) {
+ return perfetto::DynamicCategory{};
+}
+
+void TrackEventCategoryRegistry::EnableCategoryForInstance(
+ size_t category_index,
+ uint32_t instance_index) const {
+ PERFETTO_DCHECK(instance_index < kMaxDataSourceInstances);
+ PERFETTO_DCHECK(category_index < category_count_);
+ // Matches the acquire_load in DataSource::Trace().
+ state_storage_[category_index].fetch_or(
+ static_cast<uint8_t>(1u << instance_index), std::memory_order_release);
+}
+
+void TrackEventCategoryRegistry::DisableCategoryForInstance(
+ size_t category_index,
+ uint32_t instance_index) const {
+ PERFETTO_DCHECK(instance_index < kMaxDataSourceInstances);
+ PERFETTO_DCHECK(category_index < category_count_);
+ // Matches the acquire_load in DataSource::Trace().
+ state_storage_[category_index].fetch_and(
+ static_cast<uint8_t>(~(1u << instance_index)), std::memory_order_release);
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/track_event_legacy.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_legacy.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+
+// gen_amalgamated expanded: #include "perfetto/tracing/track.h"
+
+namespace perfetto {
+namespace legacy {
+
+template <>
+ThreadTrack ConvertThreadId(const PerfettoLegacyCurrentThreadId&) {
+ // Because of the short-circuit in PERFETTO_INTERNAL_LEGACY_EVENT, we should
+ // never get here.
+ PERFETTO_DCHECK(false);
+ return ThreadTrack::Current();
+}
+
+} // namespace legacy
+
+namespace internal {
+
+void LegacyTraceId::Write(protos::pbzero::TrackEvent::LegacyEvent* event,
+ uint32_t event_flags) const {
+ // Legacy flow events always use bind_id.
+ if (event_flags &
+ (legacy::kTraceEventFlagFlowOut | legacy::kTraceEventFlagFlowIn)) {
+ // Flow bind_ids don't have scopes, so we need to mangle in-process ones to
+ // avoid collisions.
+ if (id_flags_ & legacy::kTraceEventFlagHasLocalId) {
+ event->set_bind_id(raw_id_ ^ ProcessTrack::Current().uuid);
+ } else {
+ event->set_bind_id(raw_id_);
+ }
+ return;
+ }
+
+ uint32_t scope_flags = id_flags_ & (legacy::kTraceEventFlagHasId |
+ legacy::kTraceEventFlagHasLocalId |
+ legacy::kTraceEventFlagHasGlobalId);
+ uint64_t id = raw_id_;
+ if (scope_ && scope_flags != legacy::kTraceEventFlagHasGlobalId) {
+ id = base::Hasher::Combine(id, scope_);
+ }
+
+ switch (scope_flags) {
+ case legacy::kTraceEventFlagHasId:
+ event->set_unscoped_id(id);
+ break;
+ case legacy::kTraceEventFlagHasLocalId:
+ event->set_local_id(id);
+ break;
+ case legacy::kTraceEventFlagHasGlobalId:
+ event->set_global_id(id);
+ break;
+ }
+ if (scope_)
+ event->set_id_scope(scope_);
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/track_event_state_tracker.cc
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_state_tracker.h"
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/interceptor_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+
+using internal::TrackEventIncrementalState;
+
+TrackEventStateTracker::~TrackEventStateTracker() = default;
+TrackEventStateTracker::Delegate::~Delegate() = default;
+
+// static
+void TrackEventStateTracker::ProcessTracePacket(
+ Delegate& delegate,
+ SequenceState& sequence_state,
+ const protos::pbzero::TracePacket_Decoder& packet) {
+ UpdateIncrementalState(delegate, sequence_state, packet);
+
+ if (!packet.has_track_event())
+ return;
+ perfetto::protos::pbzero::TrackEvent::Decoder track_event(
+ packet.track_event());
+
+ auto clock_id = packet.timestamp_clock_id();
+ if (!packet.has_timestamp_clock_id())
+ clock_id = sequence_state.default_clock_id;
+ uint64_t timestamp = packet.timestamp();
+ // TODO(mohitms): Incorporate unit multiplier as well.
+ if (clock_id == internal::TrackEventIncrementalState::kClockIdIncremental) {
+ timestamp += sequence_state.most_recent_absolute_time_ns;
+ sequence_state.most_recent_absolute_time_ns = timestamp;
+ }
+
+ Track* track = &sequence_state.track;
+ if (track_event.has_track_uuid()) {
+ auto* session_state = delegate.GetSessionState();
+ if (!session_state)
+ return; // Tracing must have ended.
+ track = &session_state->tracks[track_event.track_uuid()];
+ }
+
+ // We only log the first category of each event.
+ protozero::ConstChars category{};
+ uint64_t category_iid = 0;
+ if (auto iid_it = track_event.category_iids()) {
+ category_iid = *iid_it;
+ category.data = sequence_state.event_categories[category_iid].data();
+ category.size = sequence_state.event_categories[category_iid].size();
+ } else if (auto cat_it = track_event.categories()) {
+ category.data = reinterpret_cast<const char*>(cat_it->data());
+ category.size = cat_it->size();
+ }
+
+ protozero::ConstChars name{};
+ uint64_t name_iid = track_event.name_iid();
+ uint64_t name_hash = 0;
+ uint64_t duration = 0;
+ if (name_iid) {
+ name.data = sequence_state.event_names[name_iid].data();
+ name.size = sequence_state.event_names[name_iid].size();
+ } else if (track_event.has_name()) {
+ name.data = track_event.name().data;
+ name.size = track_event.name().size;
+ }
+
+ if (name.data) {
+ base::Hasher hash;
+ hash.Update(name.data, name.size);
+ name_hash = hash.digest();
+ }
+
+ size_t depth = track->stack.size();
+ switch (track_event.type()) {
+ case protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN: {
+ StackFrame frame;
+ frame.timestamp = timestamp;
+ frame.name_hash = name_hash;
+ if (track_event.has_track_uuid()) {
+ frame.name = name.ToStdString();
+ frame.category = category.ToStdString();
+ } else {
+ frame.name_iid = name_iid;
+ frame.category_iid = category_iid;
+ }
+ track->stack.push_back(std::move(frame));
+ break;
+ }
+ case protos::pbzero::TrackEvent::TYPE_SLICE_END:
+ if (!track->stack.empty()) {
+ const auto& prev_frame = track->stack.back();
+ if (prev_frame.name_iid) {
+ name.data = sequence_state.event_names[prev_frame.name_iid].data();
+ name.size = sequence_state.event_names[prev_frame.name_iid].size();
+ } else {
+ name.data = prev_frame.name.data();
+ name.size = prev_frame.name.size();
+ }
+ name_hash = prev_frame.name_hash;
+ if (prev_frame.category_iid) {
+ category.data =
+ sequence_state.event_categories[prev_frame.category_iid].data();
+ category.size =
+ sequence_state.event_categories[prev_frame.category_iid].size();
+ } else {
+ category.data = prev_frame.category.data();
+ category.size = prev_frame.category.size();
+ }
+ duration = timestamp - prev_frame.timestamp;
+ depth--;
+ }
+ break;
+ case protos::pbzero::TrackEvent::TYPE_INSTANT:
+ break;
+ case protos::pbzero::TrackEvent::TYPE_COUNTER:
+ case protos::pbzero::TrackEvent::TYPE_UNSPECIFIED:
+ // TODO(skyostil): Support counters.
+ return;
+ }
+
+ ParsedTrackEvent parsed_event{track_event};
+ parsed_event.timestamp_ns = timestamp;
+ parsed_event.duration_ns = duration;
+ parsed_event.stack_depth = depth;
+ parsed_event.category = category;
+ parsed_event.name = name;
+ parsed_event.name_hash = name_hash;
+ delegate.OnTrackEvent(*track, parsed_event);
+
+ if (track_event.type() == protos::pbzero::TrackEvent::TYPE_SLICE_END &&
+ !track->stack.empty()) {
+ track->stack.pop_back();
+ }
+}
+
+// static
+void TrackEventStateTracker::UpdateIncrementalState(
+ Delegate& delegate,
+ SequenceState& sequence_state,
+ const protos::pbzero::TracePacket_Decoder& packet) {
+#if PERFETTO_DCHECK_IS_ON()
+ if (!sequence_state.sequence_id) {
+ sequence_state.sequence_id = packet.trusted_packet_sequence_id();
+ } else {
+ PERFETTO_DCHECK(sequence_state.sequence_id ==
+ packet.trusted_packet_sequence_id());
+ }
+#endif
+
+ perfetto::protos::pbzero::ClockSnapshot::Decoder snapshot(
+ packet.clock_snapshot());
+ for (auto it = snapshot.clocks(); it; ++it) {
+ perfetto::protos::pbzero::ClockSnapshot::Clock::Decoder clock(*it);
+ // TODO(mohitms) : Handle the incremental clock other than default one.
+ if (clock.is_incremental() &&
+ clock.clock_id() ==
+ internal::TrackEventIncrementalState::kClockIdIncremental) {
+ sequence_state.most_recent_absolute_time_ns =
+ clock.timestamp() * clock.unit_multiplier_ns();
+ break;
+ }
+ }
+
+ if (packet.sequence_flags() &
+ perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
+ // Convert any existing event names and categories on the stack to
+ // non-interned strings so we can look up their names even after the
+ // incremental state is gone.
+ for (auto& frame : sequence_state.track.stack) {
+ if (frame.name_iid) {
+ frame.name = sequence_state.event_names[frame.name_iid];
+ frame.name_iid = 0u;
+ }
+ if (frame.category_iid) {
+ frame.category = sequence_state.event_categories[frame.category_iid];
+ frame.category_iid = 0u;
+ }
+ }
+ sequence_state.event_names.clear();
+ sequence_state.event_categories.clear();
+ sequence_state.debug_annotation_names.clear();
+ sequence_state.track.uuid = 0u;
+ sequence_state.track.index = 0u;
+ }
+ if (packet.has_interned_data()) {
+ perfetto::protos::pbzero::InternedData::Decoder interned_data(
+ packet.interned_data());
+ for (auto it = interned_data.event_names(); it; it++) {
+ perfetto::protos::pbzero::EventName::Decoder entry(*it);
+ sequence_state.event_names[entry.iid()] = entry.name().ToStdString();
+ }
+ for (auto it = interned_data.event_categories(); it; it++) {
+ perfetto::protos::pbzero::EventCategory::Decoder entry(*it);
+ sequence_state.event_categories[entry.iid()] = entry.name().ToStdString();
+ }
+ for (auto it = interned_data.debug_annotation_names(); it; it++) {
+ perfetto::protos::pbzero::DebugAnnotationName::Decoder entry(*it);
+ sequence_state.debug_annotation_names[entry.iid()] =
+ entry.name().ToStdString();
+ }
+ }
+ if (packet.has_trace_packet_defaults()) {
+ perfetto::protos::pbzero::TracePacketDefaults::Decoder defaults(
+ packet.trace_packet_defaults());
+ if (defaults.has_track_event_defaults()) {
+ perfetto::protos::pbzero::TrackEventDefaults::Decoder
+ track_event_defaults(defaults.track_event_defaults());
+ sequence_state.track.uuid = track_event_defaults.track_uuid();
+ if (defaults.has_timestamp_clock_id())
+ sequence_state.default_clock_id = defaults.timestamp_clock_id();
+ }
+ }
+ if (packet.has_track_descriptor()) {
+ perfetto::protos::pbzero::TrackDescriptor::Decoder track_descriptor(
+ packet.track_descriptor());
+ auto* session_state = delegate.GetSessionState();
+ auto& track = session_state->tracks[track_descriptor.uuid()];
+ if (!track.index)
+ track.index = static_cast<uint32_t>(session_state->tracks.size() + 1);
+ track.uuid = track_descriptor.uuid();
+
+ track.name = track_descriptor.name().ToStdString();
+ track.pid = 0;
+ track.tid = 0;
+ if (track_descriptor.has_process()) {
+ perfetto::protos::pbzero::ProcessDescriptor::Decoder process(
+ track_descriptor.process());
+ track.pid = process.pid();
+ if (track.name.empty())
+ track.name = process.process_name().ToStdString();
+ } else if (track_descriptor.has_thread()) {
+ perfetto::protos::pbzero::ThreadDescriptor::Decoder thread(
+ track_descriptor.thread());
+ track.pid = thread.pid();
+ track.tid = thread.tid();
+ if (track.name.empty())
+ track.name = thread.thread_name().ToStdString();
+ }
+ delegate.OnTrackUpdated(track);
+
+ // Mirror properties to the default track of the sequence. Note that
+ // this does not catch updates to the default track written through other
+ // sequences.
+ if (track.uuid == sequence_state.track.uuid) {
+ sequence_state.track.index = track.index;
+ sequence_state.track.name = track.name;
+ sequence_state.track.pid = track.pid;
+ sequence_state.track.tid = track.tid;
+ sequence_state.track.user_data = track.user_data;
+ }
+ }
+}
+
+TrackEventStateTracker::ParsedTrackEvent::ParsedTrackEvent(
+ const perfetto::protos::pbzero::TrackEvent::Decoder& track_event_)
+ : track_event(track_event_) {}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/virtual_destructors.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_tls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"
+
+// This translation unit contains the definitions for the destructor of pure
+// virtual interfaces for the src/public:public target. The alternative would be
+// introducing a one-liner .cc file for each pure virtual interface, which is
+// overkill. This is for compliance with -Wweak-vtables.
+
+namespace perfetto {
+namespace internal {
+
+TracingTLS::~TracingTLS() {
+ // Avoid entering trace points while the thread is being torn down.
+ // This is the problem: when a thread exits, the at-thread-exit destroys the
+ // TracingTLS. As part of that the various TraceWriter for the active data
+ // sources are destroyd. A TraceWriter dtor will issue a PostTask on the IPC
+ // thread to issue a final flush and unregister its ID with the service.
+ // The PostTask, in chromium, might have a trace event that will try to
+ // re-enter the tracing system.
+ // We fix this by resetting the TLS key to the TracingTLS object that is
+ // being destroyed in the platform impl (platform_posix.cc,
+ // platform_windows.cc, chromium's platform.cc). We carefully rely on the fact
+ // that all the tracing path that will be invoked during thread exit will
+ // early out if |is_in_trace_point| == true and will not depend on the other
+ // TLS state that has been destroyed.
+ is_in_trace_point = true;
+}
+
+} // namespace internal
+
+TracingProducerBackend::~TracingProducerBackend() = default;
+TracingConsumerBackend::~TracingConsumerBackend() = default;
+TracingBackend::~TracingBackend() = default;
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/android_stats/statsd_logging_helper.cc
+// gen_amalgamated begin header: src/android_stats/statsd_logging_helper.h
+// gen_amalgamated begin header: src/android_stats/perfetto_atoms.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_ANDROID_STATS_PERFETTO_ATOMS_H_
+#define SRC_ANDROID_STATS_PERFETTO_ATOMS_H_
+
+namespace perfetto {
+
+// This must match the values of the PerfettoUploadEvent enum in:
+// frameworks/proto_logging/stats/atoms.proto
+enum class PerfettoStatsdAtom {
+ kUndefined = 0,
+
+ // Checkpoints inside perfetto_cmd before tracing is finished.
+ kTraceBegin = 1,
+ kBackgroundTraceBegin = 2,
+ kOnConnect = 3,
+
+ // Guardrails inside perfetto_cmd before tracing is finished.
+ kOnTimeout = 16,
+ kCmdUserBuildTracingNotAllowed = 43,
+
+ // Checkpoints inside traced.
+ kTracedEnableTracing = 37,
+ kTracedStartTracing = 38,
+ kTracedDisableTracing = 39,
+ kTracedNotifyTracingDisabled = 40,
+
+ // Trigger checkpoints inside traced.
+ // These atoms are special because, along with the UUID,
+ // they log the trigger name.
+ kTracedTriggerStartTracing = 41,
+ kTracedTriggerStopTracing = 42,
+ kTracedTriggerCloneSnapshot = 53,
+
+ // Guardrails inside traced.
+ kTracedEnableTracingExistingTraceSession = 18,
+ kTracedEnableTracingTooLongTrace = 19,
+ kTracedEnableTracingInvalidTriggerTimeout = 20,
+ kTracedEnableTracingDurationWithTrigger = 21,
+ kTracedEnableTracingStopTracingWriteIntoFile = 22,
+ kTracedEnableTracingDuplicateTriggerName = 23,
+ kTracedEnableTracingInvalidDeferredStart = 24,
+ kTracedEnableTracingInvalidBufferSize = 25,
+ kTracedEnableTracingBufferSizeTooLarge = 26,
+ kTracedEnableTracingTooManyBuffers = 27,
+ kTracedEnableTracingDuplicateSessionName = 28,
+ kTracedEnableTracingSessionNameTooRecent = 29,
+ kTracedEnableTracingTooManySessionsForUid = 30,
+ kTracedEnableTracingTooManyConcurrentSessions = 31,
+ kTracedEnableTracingInvalidFdOutputFile = 32,
+ kTracedEnableTracingFailedToCreateFile = 33,
+ kTracedEnableTracingOom = 34,
+ kTracedEnableTracingUnknown = 35,
+ kTracedStartTracingInvalidSessionState = 36,
+ kTracedEnableTracingInvalidFilter = 47,
+ kTracedEnableTracingOobTargetBuffer = 48,
+ kTracedEnableTracingInvalidTriggerMode = 52,
+ kTracedEnableTracingInvalidBrFilename = 54,
+
+ // Checkpoints inside perfetto_cmd after tracing has finished.
+ kOnTracingDisabled = 4,
+ kFinalizeTraceAndExit = 11,
+ kCmdFwReportBegin = 49,
+ // Will be removed once incidentd is no longer used.
+ kUploadIncidentBegin = 8,
+ kNotUploadingEmptyTrace = 17,
+
+ // Guardrails inside perfetto_cmd after tracing has finished.
+ kCmdFwReportEmptyTrace = 50,
+ // Will be removed once incidentd is no longer used.
+ kUploadIncidentFailure = 10,
+
+ // "Successful" terminal states inside perfetto_cmd.
+ kCmdFwReportHandoff = 51,
+
+ // Deprecated as "success" is misleading; it simply means we were
+ // able to communicate with incidentd. Will be removed once
+ // incidentd is no longer used.
+ kUploadIncidentSuccess = 9,
+
+ // Contained trigger begin/success/failure. Replaced by
+ // |PerfettoTriggerAtom| to allow aggregation using a count metric
+ // and reduce spam.
+ // reserved 12, 13, 14;
+
+ // Contained that a guardrail in perfetto_cmd was hit. Replaced with
+ // kCmd* guardrails.
+ // reserved 15;
+
+ // Contained status of Dropbox uploads. Removed as Perfetto no
+ // longer supports uploading traces using Dropbox.
+ // reserved 5, 6, 7;
+
+ // Contained status of guardrail state initalization and upload limit in
+ // perfetto_cmd. Removed as perfetto no longer manages stateful guardrails
+ // reserved 44, 45, 46;
+};
+
+// This must match the values of the PerfettoTrigger::TriggerType enum in:
+// frameworks/proto_logging/stats/atoms.proto
+enum PerfettoTriggerAtom {
+ kUndefined = 0,
+
+ kCmdTrigger = 1,
+ kCmdTriggerFail = 2,
+
+ kTriggerPerfettoTrigger = 3,
+ kTriggerPerfettoTriggerFail = 4,
+
+ kTracedLimitProbability = 5,
+ kTracedLimitMaxPer24h = 6,
+
+ kProbesProducerTrigger = 7,
+ kProbesProducerTriggerFail = 8,
+};
+
+} // namespace perfetto
+
+#endif // SRC_ANDROID_STATS_PERFETTO_ATOMS_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_ANDROID_STATS_STATSD_LOGGING_HELPER_H_
+#define SRC_ANDROID_STATS_STATSD_LOGGING_HELPER_H_
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "src/android_stats/perfetto_atoms.h"
+
+namespace perfetto {
+namespace android_stats {
+
+// Functions in this file are only active on built in the Android
+// tree. On other platforms (including Android standalone and Chromium
+// on Android) these functions are a noop.
+
+// Logs the upload event to statsd if built in the Android tree.
+void MaybeLogUploadEvent(PerfettoStatsdAtom atom,
+ int64_t uuid_lsb,
+ int64_t uuid_msb,
+ const std::string& trigger_name = "");
+
+// Logs the trigger events to statsd if built in the Android tree.
+void MaybeLogTriggerEvent(PerfettoTriggerAtom atom, const std::string& trigger);
+
+// Logs the trigger events to statsd if built in the Android tree.
+void MaybeLogTriggerEvents(PerfettoTriggerAtom atom,
+ const std::vector<std::string>& triggers);
+
+} // namespace android_stats
+} // namespace perfetto
+
+#endif // SRC_ANDROID_STATS_STATSD_LOGGING_HELPER_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/android_stats/statsd_logging_helper.h"
+
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+ PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+// gen_amalgamated expanded: #include "src/android_internal/lazy_library_loader.h" // nogncheck
+// gen_amalgamated expanded: #include "src/android_internal/statsd_logging.h" // nogncheck
+#endif
+
+namespace perfetto {
+namespace android_stats {
+
+// Make sure we don't accidentally log on non-Android tree build. Note that even
+// removing this ifdef still doesn't make uploads work on OS_ANDROID.
+// PERFETTO_LAZY_LOAD will return a nullptr on non-Android and non-in-tree
+// builds as libperfetto_android_internal will not be available.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+ PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+
+void MaybeLogUploadEvent(PerfettoStatsdAtom atom,
+ int64_t uuid_lsb,
+ int64_t uuid_msb,
+ const std::string& trigger_name) {
+ PERFETTO_LAZY_LOAD(android_internal::StatsdLogUploadEvent, log_event_fn);
+ if (log_event_fn) {
+ log_event_fn(atom, uuid_lsb, uuid_msb, trigger_name.c_str());
+ }
+}
+
+void MaybeLogTriggerEvent(PerfettoTriggerAtom atom,
+ const std::string& trigger_name) {
+ PERFETTO_LAZY_LOAD(android_internal::StatsdLogTriggerEvent, log_event_fn);
+ if (log_event_fn) {
+ log_event_fn(atom, trigger_name.c_str());
+ }
+}
+
+void MaybeLogTriggerEvents(PerfettoTriggerAtom atom,
+ const std::vector<std::string>& triggers) {
+ PERFETTO_LAZY_LOAD(android_internal::StatsdLogTriggerEvent, log_event_fn);
+ if (log_event_fn) {
+ for (const std::string& trigger_name : triggers) {
+ log_event_fn(atom, trigger_name.c_str());
+ }
+ }
+}
+
+#else
+void MaybeLogUploadEvent(PerfettoStatsdAtom,
+ int64_t,
+ int64_t,
+ const std::string&) {}
+void MaybeLogTriggerEvent(PerfettoTriggerAtom, const std::string&) {}
+void MaybeLogTriggerEvents(PerfettoTriggerAtom,
+ const std::vector<std::string>&) {}
+#endif
+
+} // namespace android_stats
+} // namespace perfetto
+// gen_amalgamated begin source: src/base/version.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/version.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_VERSION_H_
+#define INCLUDE_PERFETTO_EXT_BASE_VERSION_H_
+
+namespace perfetto {
+namespace base {
+
+// The returned pointer is a static string and safe to pass around.
+// Returns a human readable string currently of the approximate form:
+// Perfetto v42.1-deadbeef0 (deadbeef03c641e4b4ea9cf38e9b5696670175a9)
+// However you should not depend on the format of this string.
+// It maybe not be possible to determine the version. In which case the
+// string will be of the approximate form:
+// Perfetto v0.0 (unknown)
+const char* GetVersionString();
+
+// The returned pointer is a static string and safe to pass around.
+// Returns the short code used to identity the version:
+// v42.1-deadbeef0
+// It maybe not be possible to determine the version. In which case
+// this returns nullptr.
+// This can be compared with equality to other
+// version codes to detect matched builds (for example to see if
+// trace_processor_shell and the UI were built at the same revision)
+// but you should not attempt to parse it as the format may change
+// without warning.
+const char* GetVersionCode();
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_VERSION_H_
+// gen_amalgamated begin header: gen/perfetto_version.gen.h
+// Generated by write_version_header.py
+
+#ifndef GEN_PERFETTO_VERSION_GEN_H_
+#define GEN_PERFETTO_VERSION_GEN_H_
+
+#define PERFETTO_VERSION_STRING() "v44.0-94bdc3da5"
+#define PERFETTO_VERSION_SCM_REVISION() "94bdc3da58ad5343e7db3c40fba76309103e342a"
+
+#endif // GEN_PERFETTO_VERSION_GEN_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/version.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#include <stdio.h>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
+// gen_amalgamated expanded: #include "perfetto_version.gen.h"
+#else
+#define PERFETTO_VERSION_STRING() nullptr
+#define PERFETTO_VERSION_SCM_REVISION() "unknown"
+#endif
+
+namespace perfetto {
+namespace base {
+
+const char* GetVersionCode() {
+ return PERFETTO_VERSION_STRING();
+}
+
+const char* GetVersionString() {
+ static const char* version_str = [] {
+ static constexpr size_t kMaxLen = 256;
+ const char* version_code = PERFETTO_VERSION_STRING();
+ if (version_code == nullptr) {
+ version_code = "v0.0";
+ }
+ char* version = new char[kMaxLen + 1];
+ snprintf(version, kMaxLen, "Perfetto %s (%s)", version_code,
+ PERFETTO_VERSION_SCM_REVISION());
+ return version;
+ }();
+ return version_str;
+}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/protozero/filtering/filter_bytecode_parser.cc
+// gen_amalgamated begin header: src/protozero/filtering/filter_bytecode_parser.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_PARSER_H_
+#define SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_PARSER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <optional>
+#include <vector>
+
+namespace protozero {
+
+// Loads the proto-encoded bytecode in memory and allows fast lookups for tuples
+// (msg_index, field_id) to tell if a given field should be allowed or not and,
+// in the case of nested fields, what is the next message index to recurse into.
+// This class does two things:
+// 1. Expands the array of varint from the proto into a vector<uint32_t>. This
+// is to avoid performing varint decoding on every lookup, at the cost of
+// some extra memory (2KB-4KB). Note that the expanded vector is not just a
+// 1:1 copy of the proto one (more below). This is to avoid O(Fields) linear
+// lookup complexity.
+// 2. Creates an index of offsets to remember the start word for each message.
+// This is so we can jump to O(1) to the N-th message when recursing into a
+// nested fields, without having to scan and find the (N-1)-th END_OF_MESSAGE
+// marker.
+// Overall lookups are O(1) for field ids < 128 (kDirectlyIndexLimit) and O(N),
+// with N being the number of allowed field ranges for other fields.
+// See comments around |word_| below for the structure of the word vector.
+class FilterBytecodeParser {
+ public:
+ // Result of a Query() operation
+ struct QueryResult {
+ bool allowed; // Whether the field is allowed at all or no.
+
+ // If |allowed|==true && nested_msg_field() == true, this tells the message
+ // index of the nested field that should be used when recursing in the
+ // parser.
+ uint32_t nested_msg_index;
+
+ // If |allowed|==true, specifies if the field is of a simple type (varint,
+ // fixed32/64, string or byte).
+ bool simple_field() const { return nested_msg_index == kSimpleField; }
+
+ // If |allowed|==true, specifies if this field is a string field that needs
+ // to be filtered.
+ bool filter_string_field() const {
+ return nested_msg_index == kFilterStringField;
+ }
+
+ // If |allowed|==true, specifies if the field is a nested field that needs
+ // recursion. The caller is expected to use |nested_msg_index| for the next
+ // Query() calls.
+ bool nested_msg_field() const {
+ static_assert(kFilterStringField < kSimpleField,
+ "kFilterStringField < kSimpleField");
+ return nested_msg_index < kFilterStringField;
+ }
+ };
+
+ // Loads a filter. The filter data consists of a sequence of varints which
+ // contains the filter opcodes and a final checksum.
+ bool Load(const void* filter_data, size_t len);
+
+ // Checks wheter a given field is allowed or not.
+ // msg_index = 0 is the index of the root message, where all queries should
+ // start from (typically perfetto.protos.Trace).
+ QueryResult Query(uint32_t msg_index, uint32_t field_id) const;
+
+ void Reset();
+ void set_suppress_logs_for_fuzzer(bool x) { suppress_logs_for_fuzzer_ = x; }
+
+ private:
+ static constexpr uint32_t kDirectlyIndexLimit = 128;
+ static constexpr uint32_t kAllowed = 1u << 31u;
+ static constexpr uint32_t kSimpleField = 0x7fffffff;
+ static constexpr uint32_t kFilterStringField = 0x7ffffffe;
+
+ bool LoadInternal(const uint8_t* filter_data, size_t len);
+
+ // The state of all fields for all messages is stored in one contiguous array.
+ // This is to avoid memory fragmentation and allocator overhead.
+ // We expect a high number of messages (hundreds), but each message is small.
+ // For each message we store two sets of uint32:
+ // 1. A set of "directly indexed" fields, for field ids < 128.
+ // 2. The remainder is a set of ranges.
+ // So each message descriptor consists of a sequence of words as follows:
+ //
+ // [0] -> how many directly indexed fields are stored next (up to 128)
+ //
+ // [1..N] -> One word per field id (See "field state" below).
+ //
+ // [N + 1] -> Start of field id range 1
+ // [N + 2] -> End of field id range 1 (exclusive, STL-style).
+ // [N + 3] -> Field state for fields in range 1 (below)
+ //
+ // [N + 4] -> Start of field id range 2
+ // [N + 5] -> End of field id range 2 (exclusive, STL-style).
+ // [N + 6] -> Field state for fields in range 2 (below)
+
+ // The "field state" word is as follows:
+ // Bit 31: 1 if the field is allowed, 0 if disallowed.
+ // Only directly indexed fields can be 0 (it doesn't make sense to add
+ // a range and then say "btw it's NOT allowed".. don't add it then.
+ // 0 is only used for filling gaps in the directly indexed bucket.
+ // Bits [30..0] (only when MSB == allowed):
+ // 0x7fffffff: The field is "simple" (varint, fixed32/64, string, bytes) and
+ // can be directly passed through in output. No recursion is needed.
+ // 0x7ffffffe: The field is string field which needs to be filtered.
+ // [0, 7ffffffd]: The field is a nested submessage. The value is the index
+ // that must be passed as first argument to the next Query() calls.
+ // Note that the message index is purely a monotonic counter in the
+ std::vector<uint32_t> words_;
+
+ // One entry for each message index stored in the filter plus a sentinel at
+ // the end. Maps each message index to the offset in |words_| where the
+ // Nth message start.
+ // message_offset_.size() - 2 == the max message id that can be parsed.
+ std::vector<uint32_t> message_offset_;
+
+ bool suppress_logs_for_fuzzer_ = false;
+};
+
+} // namespace protozero
+
+#endif // SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_PARSER_H_
+// gen_amalgamated begin header: src/protozero/filtering/filter_bytecode_common.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_COMMON_H_
+#define SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_COMMON_H_
+
+#include <stdint.h>
+
+namespace protozero {
+
+enum FilterOpcode : uint32_t {
+ // The immediate value is 0 in this case.
+ kFilterOpcode_EndOfMessage = 0,
+
+ // The immediate value is the id of the allowed field.
+ kFilterOpcode_SimpleField = 1,
+
+ // The immediate value is the start of the range. The next word (without
+ // any shifting) is the length of the range.
+ kFilterOpcode_SimpleFieldRange = 2,
+
+ // The immediate value is the id of the allowed field. The next word
+ // (without any shifting) is the index of the filter that should be used to
+ // recurse into the nested message.
+ kFilterOpcode_NestedField = 3,
+
+ // The imediate value is the id of the allowed field. The behaviour of this
+ // opcode is the same as kFilterOpcode_SimpleField, with the further semantic
+ // that the field is a string and needs to be processed using the string
+ // filtering fules.
+ kFilterOpcode_FilterString = 4,
+};
+
+} // namespace protozero
+
+#endif // SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_COMMON_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/protozero/filtering/filter_bytecode_parser.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "src/protozero/filtering/filter_bytecode_common.h"
+
+namespace protozero {
+
+void FilterBytecodeParser::Reset() {
+ bool suppress = suppress_logs_for_fuzzer_;
+ *this = FilterBytecodeParser();
+ suppress_logs_for_fuzzer_ = suppress;
+}
+
+bool FilterBytecodeParser::Load(const void* filter_data, size_t len) {
+ Reset();
+ bool res = LoadInternal(static_cast<const uint8_t*>(filter_data), len);
+ // If load fails, don't leave the parser in a half broken state.
+ if (!res)
+ Reset();
+ return res;
+}
+
+bool FilterBytecodeParser::LoadInternal(const uint8_t* bytecode_data,
+ size_t len) {
+ // First unpack the varints into a plain uint32 vector, so it's easy to
+ // iterate through them and look ahead.
+ std::vector<uint32_t> words;
+ bool packed_parse_err = false;
+ words.reserve(len); // An overestimation, but avoids reallocations.
+ using BytecodeDecoder =
+ PackedRepeatedFieldIterator<proto_utils::ProtoWireType::kVarInt,
+ uint32_t>;
+ for (BytecodeDecoder it(bytecode_data, len, &packed_parse_err); it; ++it)
+ words.emplace_back(*it);
+
+ if (packed_parse_err || words.empty())
+ return false;
+
+ perfetto::base::Hasher hasher;
+ for (size_t i = 0; i < words.size() - 1; ++i)
+ hasher.Update(words[i]);
+
+ uint32_t expected_csum = static_cast<uint32_t>(hasher.digest());
+ if (expected_csum != words.back()) {
+ if (!suppress_logs_for_fuzzer_) {
+ PERFETTO_ELOG("Filter bytecode checksum failed. Expected: %x, actual: %x",
+ expected_csum, words.back());
+ }
+ return false;
+ }
+
+ words.pop_back(); // Pop the checksum.
+
+ // Temporay storage for each message. Cleared on every END_OF_MESSAGE.
+ std::vector<uint32_t> direct_indexed_fields;
+ std::vector<uint32_t> ranges;
+ uint32_t max_msg_index = 0;
+
+ auto add_directly_indexed_field = [&](uint32_t field_id, uint32_t msg_id) {
+ PERFETTO_DCHECK(field_id > 0 && field_id < kDirectlyIndexLimit);
+ direct_indexed_fields.resize(std::max(direct_indexed_fields.size(),
+ static_cast<size_t>(field_id) + 1));
+ direct_indexed_fields[field_id] = kAllowed | msg_id;
+ };
+
+ auto add_range = [&](uint32_t id_start, uint32_t id_end, uint32_t msg_id) {
+ PERFETTO_DCHECK(id_end > id_start);
+ PERFETTO_DCHECK(id_start >= kDirectlyIndexLimit);
+ ranges.emplace_back(id_start);
+ ranges.emplace_back(id_end);
+ ranges.emplace_back(kAllowed | msg_id);
+ };
+
+ bool is_eom = true;
+ for (size_t i = 0; i < words.size(); ++i) {
+ const uint32_t word = words[i];
+ const bool has_next_word = i < words.size() - 1;
+ const uint32_t opcode = word & 0x7u;
+ const uint32_t field_id = word >> 3;
+
+ is_eom = opcode == kFilterOpcode_EndOfMessage;
+ if (field_id == 0 && opcode != kFilterOpcode_EndOfMessage) {
+ PERFETTO_DLOG("bytecode error @ word %zu, invalid field id (0)", i);
+ return false;
+ }
+
+ if (opcode == kFilterOpcode_SimpleField ||
+ opcode == kFilterOpcode_NestedField ||
+ opcode == kFilterOpcode_FilterString) {
+ // Field words are organized as follow:
+ // MSB: 1 if allowed, 0 if not allowed.
+ // Remaining bits:
+ // Message index in the case of nested (non-simple) messages.
+ // 0x7f..e in the case of string fields which need filtering.
+ // 0x7f..f in the case of simple fields.
+ uint32_t msg_id;
+ if (opcode == kFilterOpcode_SimpleField) {
+ msg_id = kSimpleField;
+ } else if (opcode == kFilterOpcode_FilterString) {
+ msg_id = kFilterStringField;
+ } else { // FILTER_OPCODE_NESTED_FIELD
+ // The next word in the bytecode contains the message index.
+ if (!has_next_word) {
+ PERFETTO_DLOG("bytecode error @ word %zu: unterminated nested field",
+ i);
+ return false;
+ }
+ msg_id = words[++i];
+ max_msg_index = std::max(max_msg_index, msg_id);
+ }
+
+ if (field_id < kDirectlyIndexLimit) {
+ add_directly_indexed_field(field_id, msg_id);
+ } else {
+ // In the case of a large field id (rare) we waste an extra word and
+ // represent it as a range. Doesn't make sense to introduce extra
+ // complexity to deal with rare cases like this.
+ add_range(field_id, field_id + 1, msg_id);
+ }
+ } else if (opcode == kFilterOpcode_SimpleFieldRange) {
+ if (!has_next_word) {
+ PERFETTO_DLOG("bytecode error @ word %zu: unterminated range", i);
+ return false;
+ }
+ const uint32_t range_len = words[++i];
+ const uint32_t range_end = field_id + range_len; // STL-style, excl.
+ uint32_t id = field_id;
+
+ // Here's the subtle complexity: at the bytecode level, we don't know
+ // anything about the kDirectlyIndexLimit. It is legit to define a range
+ // that spans across the direct-indexing threshold (e.g. 126-132). In that
+ // case we want to add all the elements < the indexing to the O(1) bucket
+ // and add only the remaining range as a non-indexed range.
+ for (; id < range_end && id < kDirectlyIndexLimit; ++id)
+ add_directly_indexed_field(id, kAllowed | kSimpleField);
+ PERFETTO_DCHECK(id >= kDirectlyIndexLimit || id == range_end);
+ if (id < range_end)
+ add_range(id, range_end, kSimpleField);
+ } else if (opcode == kFilterOpcode_EndOfMessage) {
+ // For each message append:
+ // 1. The "header" word telling how many directly indexed fields there
+ // are.
+ // 2. The words for the directly indexed fields (id < 128).
+ // 3. The rest of the fields, encoded as ranges.
+ // Also update the |message_offset_| index to remember the word offset for
+ // the current message.
+ message_offset_.emplace_back(static_cast<uint32_t>(words_.size()));
+ words_.emplace_back(static_cast<uint32_t>(direct_indexed_fields.size()));
+ words_.insert(words_.end(), direct_indexed_fields.begin(),
+ direct_indexed_fields.end());
+ words_.insert(words_.end(), ranges.begin(), ranges.end());
+ direct_indexed_fields.clear();
+ ranges.clear();
+ } else {
+ PERFETTO_DLOG("bytecode error @ word %zu: invalid opcode (%x)", i, word);
+ return false;
+ }
+ } // (for word in bytecode).
+
+ if (!is_eom) {
+ PERFETTO_DLOG(
+ "bytecode error: end of message not the last word in the bytecode");
+ return false;
+ }
+
+ if (max_msg_index > 0 && max_msg_index >= message_offset_.size()) {
+ PERFETTO_DLOG(
+ "bytecode error: a message index (%u) is out of range "
+ "(num_messages=%zu)",
+ max_msg_index, message_offset_.size());
+ return false;
+ }
+
+ // Add a final entry to |message_offset_| so we can tell where the last
+ // message ends without an extra branch in the Query() hotpath.
+ message_offset_.emplace_back(static_cast<uint32_t>(words_.size()));
+
+ return true;
+}
+
+FilterBytecodeParser::QueryResult FilterBytecodeParser::Query(
+ uint32_t msg_index,
+ uint32_t field_id) const {
+ FilterBytecodeParser::QueryResult res{false, 0u};
+ if (static_cast<uint64_t>(msg_index) + 1 >=
+ static_cast<uint64_t>(message_offset_.size())) {
+ return res;
+ }
+ const uint32_t start_offset = message_offset_[msg_index];
+ // These are DCHECKs and not just CHECKS because the |words_| is populated
+ // by the LoadInternal call above. These cannot be violated with a malformed
+ // bytecode.
+ PERFETTO_DCHECK(start_offset < words_.size());
+ const uint32_t* word = &words_[start_offset];
+ const uint32_t end_off = message_offset_[msg_index + 1];
+ const uint32_t* const end = words_.data() + end_off;
+ PERFETTO_DCHECK(end > word && end <= words_.data() + words_.size());
+ const uint32_t num_directly_indexed = *(word++);
+ PERFETTO_DCHECK(num_directly_indexed <= kDirectlyIndexLimit);
+ PERFETTO_DCHECK(word + num_directly_indexed <= end);
+ uint32_t field_state = 0;
+ if (PERFETTO_LIKELY(field_id < num_directly_indexed)) {
+ PERFETTO_DCHECK(&word[field_id] < end);
+ field_state = word[field_id];
+ } else {
+ for (word = word + num_directly_indexed; word + 2 < end;) {
+ const uint32_t range_start = *(word++);
+ const uint32_t range_end = *(word++);
+ const uint32_t range_state = *(word++);
+ if (field_id >= range_start && field_id < range_end) {
+ field_state = range_state;
+ break;
+ }
+ } // for (word in ranges)
+ } // if (field_id >= num_directly_indexed)
+
+ res.allowed = (field_state & kAllowed) != 0;
+ res.nested_msg_index = field_state & ~kAllowed;
+ PERFETTO_DCHECK(!res.nested_msg_field() ||
+ res.nested_msg_index < message_offset_.size() - 1);
+ return res;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/filtering/string_filter.cc
+// gen_amalgamated begin header: src/protozero/filtering/string_filter.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_PROTOZERO_FILTERING_STRING_FILTER_H_
+#define SRC_PROTOZERO_FILTERING_STRING_FILTER_H_
+
+#include <regex>
+#include <string>
+#include <string_view>
+
+namespace protozero {
+
+// Performs filtering of strings in an "iptables" style. See the comments in
+// |TraceConfig.TraceFilter| for information on how this class works.
+class StringFilter {
+ public:
+ enum class Policy {
+ kMatchRedactGroups = 1,
+ kAtraceMatchRedactGroups = 2,
+ kMatchBreak = 3,
+ kAtraceMatchBreak = 4,
+ kAtraceRepeatedSearchRedactGroups = 5,
+ };
+
+ // Adds a new rule for filtering strings.
+ void AddRule(Policy policy,
+ std::string_view pattern,
+ std::string atrace_payload_starts_with);
+
+ // Tries to filter the given string. Returns true if the string was modified
+ // in any way, false otherwise.
+ bool MaybeFilter(char* ptr, size_t len) const {
+ if (len == 0 || rules_.empty()) {
+ return false;
+ }
+ return MaybeFilterInternal(ptr, len);
+ }
+
+ private:
+ struct Rule {
+ Policy policy;
+ std::regex pattern;
+ std::string atrace_payload_starts_with;
+ };
+
+ bool MaybeFilterInternal(char* ptr, size_t len) const;
+
+ std::vector<Rule> rules_;
+};
+
+} // namespace protozero
+
+#endif // SRC_PROTOZERO_FILTERING_STRING_FILTER_H_
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/protozero/filtering/string_filter.h"
+
+#include <cstring>
+#include <regex>
+#include <string_view>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+// gen_amalgamated expanded: #include "perfetto/public/compiler.h"
+
+namespace protozero {
+namespace {
+
+using Matches = std::match_results<char*>;
+
+static constexpr std::string_view kRedacted = "P60REDACTED";
+static constexpr char kRedactedDash = '-';
+
+// Returns a pointer to the first character after the tgid pipe character in
+// the atrace string given by [ptr, end). Returns null if no such character
+// exists.
+//
+// Examples:
+// E|1024 -> nullptr
+// foobarbaz -> nullptr
+// B|1024|x -> pointer to x
+const char* FindAtracePayloadPtr(const char* ptr, const char* end) {
+ // Don't even bother checking any strings which are so short that they could
+ // not contain a post-tgid section. This filters out strings like "E|" which
+ // emitted by Bionic.
+ //
+ // Also filter out any other strings starting with "E" as they never contain
+ // anything past the tgid: this removes >half of the strings for ~zero cost.
+ static constexpr size_t kEarliestSecondPipeIndex = 2;
+ const char* search_start = ptr + kEarliestSecondPipeIndex;
+ if (search_start >= end || *ptr == 'E') {
+ return nullptr;
+ }
+
+ // We skipped past the first '|' character by starting at the character at
+ // index 2. Just find the next pipe character (i.e. the one after tgid) using
+ // memchr.
+ const char* pipe = static_cast<const char*>(
+ memchr(search_start, '|', size_t(end - search_start)));
+ return pipe ? pipe + 1 : nullptr;
+}
+
+bool StartsWith(const char* ptr,
+ const char* end,
+ const std::string& starts_with) {
+ // Verify that the atrace string has enough characters to match against all
+ // the characters in the "starts with" string. If it does, memcmp to check if
+ // all the characters match and return true if they do.
+ return ptr + starts_with.size() <= end &&
+ memcmp(ptr, starts_with.data(), starts_with.size()) == 0;
+}
+
+void RedactMatches(const Matches& matches) {
+ // Go through every group in the matches.
+ for (size_t i = 1; i < matches.size(); ++i) {
+ const auto& match = matches[i];
+ PERFETTO_CHECK(match.second >= match.first);
+
+ // Overwrite the match with characters from |kRedacted|. If match is
+ // smaller, we will not use all of |kRedacted| but that's fine (i.e. we
+ // will overwrite with a truncated |kRedacted|).
+ size_t match_len = static_cast<size_t>(match.second - match.first);
+ size_t redacted_len = std::min(match_len, kRedacted.size());
+ memcpy(match.first, kRedacted.data(), redacted_len);
+
+ // Overwrite any characters after |kRedacted| with |kRedactedDash|.
+ memset(match.first + redacted_len, kRedactedDash, match_len - redacted_len);
+ }
+}
+
+} // namespace
+
+void StringFilter::AddRule(Policy policy,
+ std::string_view pattern_str,
+ std::string atrace_payload_starts_with) {
+ rules_.emplace_back(StringFilter::Rule{
+ policy,
+ std::regex(pattern_str.begin(), pattern_str.end(),
+ std::regex::ECMAScript | std::regex_constants::optimize),
+ std::move(atrace_payload_starts_with)});
+}
+
+bool StringFilter::MaybeFilterInternal(char* ptr, size_t len) const {
+ std::match_results<char*> matches;
+ bool atrace_find_tried = false;
+ const char* atrace_payload_ptr = nullptr;
+ for (const Rule& rule : rules_) {
+ switch (rule.policy) {
+ case Policy::kMatchRedactGroups:
+ case Policy::kMatchBreak:
+ if (std::regex_match(ptr, ptr + len, matches, rule.pattern)) {
+ if (rule.policy == Policy::kMatchBreak) {
+ return false;
+ }
+ RedactMatches(matches);
+ return true;
+ }
+ break;
+ case Policy::kAtraceMatchRedactGroups:
+ case Policy::kAtraceMatchBreak:
+ atrace_payload_ptr = atrace_find_tried
+ ? atrace_payload_ptr
+ : FindAtracePayloadPtr(ptr, ptr + len);
+ atrace_find_tried = true;
+ if (atrace_payload_ptr &&
+ StartsWith(atrace_payload_ptr, ptr + len,
+ rule.atrace_payload_starts_with) &&
+ std::regex_match(ptr, ptr + len, matches, rule.pattern)) {
+ if (rule.policy == Policy::kAtraceMatchBreak) {
+ return false;
+ }
+ RedactMatches(matches);
+ return true;
+ }
+ break;
+ case Policy::kAtraceRepeatedSearchRedactGroups:
+ atrace_payload_ptr = atrace_find_tried
+ ? atrace_payload_ptr
+ : FindAtracePayloadPtr(ptr, ptr + len);
+ atrace_find_tried = true;
+ if (atrace_payload_ptr && StartsWith(atrace_payload_ptr, ptr + len,
+ rule.atrace_payload_starts_with)) {
+ auto beg = std::regex_iterator<char*>(ptr, ptr + len, rule.pattern);
+ auto end = std::regex_iterator<char*>();
+ bool has_any_matches = beg != end;
+ for (auto it = std::move(beg); it != end; ++it) {
+ RedactMatches(*it);
+ }
+ if (has_any_matches) {
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/protozero/filtering/message_filter.cc
+// gen_amalgamated begin header: src/protozero/filtering/message_filter.h
+// gen_amalgamated begin header: src/protozero/filtering/message_tokenizer.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_PROTOZERO_FILTERING_MESSAGE_TOKENIZER_H_
+#define SRC_PROTOZERO_FILTERING_MESSAGE_TOKENIZER_H_
+
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace protozero {
+
+// A helper class for schema-less tokenizing of protobuf messages.
+// This class takes a stream of proto-encoded bytes, pushed one by one in input
+// via Push(octet), and returns a stream of tokens (each Push() call can return
+// 0 or 1 token).
+// A "token" contains metadata about a field, specifically: its ID, its wire
+// type and:
+// - For varint and fixed32/64 fields: its payload.
+// - For string and bytes fields: the length of its payload.
+// In this case the caller is supposed to "eat" those N bytes before calling
+// Push() again.
+// Note that this class cannot differentiate between a string/bytes field or
+// a submessage, because they are encoded in the same way. The caller is
+// supposed to know whether a field can be recursed into by just keep calling
+// Push() or is a string that should be skipped.
+// This is inline to allow the compiler to see through the Push method and
+// avoid a function call for each byte.
+class MessageTokenizer {
+ public:
+ struct Token {
+ uint32_t field_id; // 0 == not valid.
+ proto_utils::ProtoWireType type;
+
+ // For kLengthDelimited, |value| represent the length of the payload.
+ uint64_t value;
+
+ inline bool valid() const { return field_id != 0; }
+ bool operator==(const Token& o) const {
+ return field_id == o.field_id && type == o.type && value == o.value;
+ }
+ };
+
+ // Pushes a byte in input and returns a token, only when getting to the last
+ // byte of each field. Specifically:
+ // - For varint and fixed32 fields, the Token is returned after the last byte
+ // of the numeric payload is pushed.
+ // - For length-delimited fields, this returns after the last byte of the
+ // length is pushed (i.e. right before the payload starts). The caller is
+ // expected to either skip the next |value| bytes (in the case of a string
+ // or bytes fields) or keep calling Push, in the case of a submessage.
+ inline Token Push(uint8_t octet) {
+ using protozero::proto_utils::ProtoWireType;
+
+ // Parsing a fixed32/64 field is the only case where we don't have to do
+ // any varint decoding. This is why this block is before the remaining
+ // switch statement below (all the rest is a varint).
+ if (PERFETTO_UNLIKELY(state_ == kFixedIntValue)) {
+ PERFETTO_DCHECK(fixed_int_bits_ == 32 || fixed_int_bits_ == 64);
+ fixed_int_value_ |= static_cast<uint64_t>(octet) << fixed_int_shift_;
+ fixed_int_shift_ += 8;
+ if (fixed_int_shift_ < fixed_int_bits_)
+ return Token{}; // Intermediate byte of a fixed32/64.
+ auto wire_type = fixed_int_bits_ == 32 ? ProtoWireType::kFixed32
+ : ProtoWireType::kFixed64;
+ uint64_t fixed_int_value = fixed_int_value_;
+ fixed_int_value_ = fixed_int_shift_ = fixed_int_bits_ = 0;
+ state_ = kFieldPreamble;
+ return Token{field_id_, wire_type, fixed_int_value};
+ }
+
+ // At this point either we are: (i) parsing a field preamble; (ii) parsing a
+ // varint field paylod; (iii) parsing the length of a length-delimited
+ // field. In all cases, we need to decode a varint before proceeding.
+ varint_ |= static_cast<uint64_t>(octet & 0x7F) << varint_shift_;
+ if (octet & 0x80) {
+ varint_shift_ += 7;
+ if (PERFETTO_UNLIKELY(varint_shift_ >= 64)) {
+ varint_shift_ = 0;
+ state_ = kInvalidVarInt;
+ }
+ return Token{}; // Still parsing a varint.
+ }
+
+ uint64_t varint = varint_;
+ varint_ = 0;
+ varint_shift_ = 0;
+
+ switch (state_) {
+ case kFieldPreamble: {
+ auto field_type = static_cast<uint32_t>(varint & 7u); // 7 = 0..0111
+ field_id_ = static_cast<uint32_t>(varint >> 3);
+
+ // The field type is legit, now check it's well formed and within
+ // boundaries.
+ if (field_type == static_cast<uint32_t>(ProtoWireType::kVarInt)) {
+ state_ = kVarIntValue;
+ } else if (field_type ==
+ static_cast<uint32_t>(ProtoWireType::kFixed32) ||
+ field_type ==
+ static_cast<uint32_t>(ProtoWireType::kFixed64)) {
+ state_ = kFixedIntValue;
+ fixed_int_shift_ = 0;
+ fixed_int_value_ = 0;
+ fixed_int_bits_ =
+ field_type == static_cast<uint32_t>(ProtoWireType::kFixed32) ? 32
+ : 64;
+ } else if (field_type ==
+ static_cast<uint32_t>(ProtoWireType::kLengthDelimited)) {
+ state_ = kLenDelimited;
+ } else {
+ state_ = kInvalidFieldType;
+ }
+ return Token{};
+ }
+
+ case kVarIntValue: {
+ // Return the varint field payload and go back to the next field.
+ state_ = kFieldPreamble;
+ return Token{field_id_, ProtoWireType::kVarInt, varint};
+ }
+
+ case kLenDelimited: {
+ const auto payload_len = varint;
+ if (payload_len > protozero::proto_utils::kMaxMessageLength) {
+ state_ = kMessageTooBig;
+ return Token{};
+ }
+ state_ = kFieldPreamble;
+ // At this point the caller is expected to consume the next
+ // |payload_len| bytes.
+ return Token{field_id_, ProtoWireType::kLengthDelimited, payload_len};
+ }
+
+ case kFixedIntValue:
+ // Unreacheable because of the if before the switch.
+ PERFETTO_DCHECK(false);
+ break;
+
+ // Unrecoverable error states.
+ case kInvalidFieldType:
+ case kMessageTooBig:
+ case kInvalidVarInt:
+ break;
+ } // switch(state_)
+
+ return Token{}; // Keep GCC happy.
+ }
+
+ // Returns true if the tokenizer FSM has reached quiescence (i.e. if we are
+ // NOT in the middle of parsing a field).
+ bool idle() const {
+ return state_ == kFieldPreamble && varint_shift_ == 0 &&
+ fixed_int_shift_ == 0;
+ }
+
+ // Only for reporting parser errors in the trace.
+ uint32_t state() const { return static_cast<uint32_t>(state_); }
+
+ private:
+ enum State {
+ kFieldPreamble = 0, // Parsing the varint for the field preamble.
+ kVarIntValue = 1, // Parsing the payload of a varint field.
+ kFixedIntValue = 2, // Parsing the payload of a fixed32/64 field.
+ kLenDelimited = 3, // Parsing the length of a length-delimited field.
+
+ // Unrecoverable error states:
+ kInvalidFieldType = 4, // Encountered an invalid field type.
+ kMessageTooBig = 5, // Size of the length delimited message was too big.
+ kInvalidVarInt = 6, // Varint larger than 64 bits.
+ };
+
+ State state_ = kFieldPreamble;
+ uint32_t field_id_ = 0;
+ uint64_t varint_ = 0;
+ uint32_t varint_shift_ = 0;
+ uint32_t fixed_int_shift_ = 0;
+ uint32_t fixed_int_bits_ = 0;
+ uint64_t fixed_int_value_ = 0;
+};
+
+} // namespace protozero
+
+#endif // SRC_PROTOZERO_FILTERING_MESSAGE_TOKENIZER_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_PROTOZERO_FILTERING_MESSAGE_FILTER_H_
+#define SRC_PROTOZERO_FILTERING_MESSAGE_FILTER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+// gen_amalgamated expanded: #include "src/protozero/filtering/filter_bytecode_parser.h"
+// gen_amalgamated expanded: #include "src/protozero/filtering/message_tokenizer.h"
+// gen_amalgamated expanded: #include "src/protozero/filtering/string_filter.h"
+
+namespace protozero {
+
+// A class to filter binary-encoded proto messages using an allow-list of field
+// ids, also known as "filter bytecode". The filter determines which fields are
+// allowed to be passed through in output and strips all the other fields.
+// See go/trace-filtering for full design.
+// This class takes in input:
+// 1) The filter bytecode, loaded once via the LoadFilterBytecode() method.
+// 2) A proto-encoded binary message. The message doesn't have to be contiguous,
+// it can be passed as an array of arbitrarily chunked fragments.
+// The FilterMessage*() method returns in output a proto message, stripping out
+// all unknown fields. If the input is malformed (e.g., unknown proto field wire
+// types, lengths out of bound) the whole filtering failed and the |error| flag
+// of the FilteredMessage object is set to true.
+// The filtering operation is based on rewriting a copy of the message into a
+// self-allocated buffer, which is then returned in the output. The input buffer
+// is NOT altered.
+// Note also that the process of rewriting the protos gets rid of most redundant
+// varint encoding (if present). So even if all fields are allow-listed, the
+// output might NOT be bitwise identical to the input (but it will be
+// semantically equivalent).
+// Furthermore the enable_field_usage_tracking() method allows to keep track of
+// a histogram of allowed / denied fields. It slows down filtering and is
+// intended only on host tools.
+class MessageFilter {
+ public:
+ class Config {
+ public:
+ bool LoadFilterBytecode(const void* filter_data, size_t len);
+ bool SetFilterRoot(std::initializer_list<uint32_t> field_ids);
+
+ const FilterBytecodeParser& filter() const { return filter_; }
+ const StringFilter& string_filter() const { return string_filter_; }
+ StringFilter& string_filter() { return string_filter_; }
+ uint32_t root_msg_index() const { return root_msg_index_; }
+
+ private:
+ FilterBytecodeParser filter_;
+ StringFilter string_filter_;
+ uint32_t root_msg_index_ = 0;
+ };
+
+ MessageFilter();
+ explicit MessageFilter(Config);
+ ~MessageFilter();
+
+ struct InputSlice {
+ const void* data;
+ size_t len;
+ };
+
+ struct FilteredMessage {
+ FilteredMessage(std::unique_ptr<uint8_t[]> d, size_t s)
+ : data(std::move(d)), size(s) {}
+ std::unique_ptr<uint8_t[]> data;
+ size_t size; // The used bytes in |data|. This is <= sizeof(data).
+ bool error = false;
+ };
+
+ // Loads the filter bytecode that will be used to filter any subsequent
+ // message. Must be called before the first call to FilterMessage*().
+ // |filter_data| must point to a byte buffer for a proto-encoded ProtoFilter
+ // message (see proto_filter.proto).
+ bool LoadFilterBytecode(const void* filter_data, size_t len) {
+ return config_.LoadFilterBytecode(filter_data, len);
+ }
+
+ // This affects the filter starting point of the subsequent FilterMessage*()
+ // calls. By default the filtering process starts from the message @ index 0,
+ // the root message passed to proto_filter when generating the bytecode
+ // (in typical tracing use-cases, this is perfetto.protos.Trace). However, the
+ // caller (TracingServiceImpl) might want to filter packets from the 2nd level
+ // (perfetto.protos.TracePacket) because the root level is pre-pended after
+ // the fact. This call allows to change the root message for the filter.
+ // The argument |field_ids| is an array of proto field ids and determines the
+ // path to the new root. For instance, in the case of [1,2,3] SetFilterRoot
+ // will identify the sub-message for the field "root.1.2.3" and use that.
+ // In order for this to succeed all the fields in the path must be allowed
+ // in the filter and must be a nested message type.
+ bool SetFilterRoot(std::initializer_list<uint32_t> field_ids) {
+ return config_.SetFilterRoot(field_ids);
+ }
+
+ // Takes an input message, fragmented in arbitrary slices, and returns a
+ // filtered message in output.
+ FilteredMessage FilterMessageFragments(const InputSlice*, size_t num_slices);
+
+ // Helper for tests, where the input is a contiguous buffer.
+ FilteredMessage FilterMessage(const void* data, size_t len) {
+ InputSlice slice{data, len};
+ return FilterMessageFragments(&slice, 1);
+ }
+
+ // When enabled returns a map of "field path" to "usage counter".
+ // The key (std::string) is a binary buffer (i.e. NOT an ASCII/UTF-8 string)
+ // which contains a varint for each field. Consider the following:
+ // message Root { Sub1 f1 = 1; };
+ // message Sub1 { Sub2 f2 = 7;}
+ // message Sub2 { string f3 = 5; }
+ // The field .f1.f2.f3 will be encoded as \x01\0x07\x05.
+ // The value is the number of times that field has been encountered. If the
+ // field is not allow-listed in the bytecode (the field is stripped in output)
+ // the count will be negative.
+ void enable_field_usage_tracking(bool x) { track_field_usage_ = x; }
+ const std::unordered_map<std::string, int32_t>& field_usage() const {
+ return field_usage_;
+ }
+
+ const Config& config() const { return config_; }
+
+ // Retuns the helper class used to perform string filtering.
+ StringFilter& string_filter() { return config_.string_filter(); }
+
+ private:
+ // This is called by FilterMessageFragments().
+ // Inlining allows the compiler turn the per-byte call/return into a for loop,
+ // while, at the same time, keeping the code easy to read and reason about.
+ // It gives a 20-25% speedup (265ms vs 215ms for a 25MB trace).
+ void FilterOneByte(uint8_t octet) PERFETTO_ALWAYS_INLINE;
+
+ // No-inline because this is a slowpath (only when usage tracking is enabled).
+ void IncrementCurrentFieldUsage(uint32_t field_id,
+ bool allowed) PERFETTO_NO_INLINE;
+
+ // Gets into an error state which swallows all the input and emits no output.
+ void SetUnrecoverableErrorState();
+
+ // We keep track of the nest of messages in a stack. Each StackState
+ // object corresponds to a level of nesting in the proto message structure.
+ // Every time a new field of type len-delimited that has a corresponding
+ // sub-message in the bytecode is encountered, a new StackState is pushed in
+ // |stack_|. stack_[0] is a sentinel to prevent over-popping without adding
+ // extra branches in the fastpath.
+ // |stack_|. stack_[1] is the state of the root message.
+ struct StackState {
+ uint32_t in_bytes = 0; // Number of input bytes processed.
+
+ // When |in_bytes| reaches this value, the current state should be popped.
+ // This is set when recursing into nested submessages. This is 0 only for
+ // stack_[0] (we don't know the size of the root message upfront).
+ uint32_t in_bytes_limit = 0;
+
+ // This is set when a len-delimited message is encountered, either a string
+ // or a nested submessage that is NOT allow-listed in the bytecode.
+ // This causes input bytes to be consumed without being parsed from the
+ // input stream. If |passthrough_eaten_bytes| == true, they will be copied
+ // as-is in output (e.g. in the case of an allowed string/bytes field).
+ uint32_t eat_next_bytes = 0;
+
+ // Keeps tracks of the stream_writer output counter (out_.written()) then
+ // the StackState is pushed. This is used to work out, when popping, how
+ // many bytes have been written for the current submessage.
+ uint32_t out_bytes_written_at_start = 0;
+
+ uint32_t field_id = 0; // The proto field id for the current message.
+ uint32_t msg_index = 0; // The index of the message filter in the bytecode.
+
+ // This is a pointer to the proto preamble for the current submessage
+ // (it's nullptr for stack_[0] and non-null elsewhere). This will be filled
+ // with the actual size of the message (out_.written() -
+ // |out_bytes_written_at_start|) when finishing (popping) the message.
+ // This must be filled using WriteRedundantVarint(). Note that the
+ // |size_field_len| is variable and depends on the actual length of the
+ // input message. If the output message has roughly the same size of the
+ // input message, the length will not be redundant.
+ // In other words: the length of the field is reserved when the submessage
+ // starts. At that point we know the upper-bound for the output message
+ // (a filtered submessage can be <= the original one, but not >). So we
+ // reserve as many bytes it takes to write the input length in varint.
+ // Then, when the message is finalized and we know the actual output size
+ // we backfill the field.
+ // Consider the example of a submessage where the input size = 130 (>127,
+ // 2 varint bytes) and the output is 120 bytes. The length will be 2 bytes
+ // wide even though could have been encoded with just one byte.
+ uint8_t* size_field = nullptr;
+ uint32_t size_field_len = 0;
+
+ // The pointer to the start of the string to update the string if it is
+ // filtered.
+ uint8_t* filter_string_ptr = nullptr;
+
+ // How |eat_next_bytes| should be handled. It seems that keeping this field
+ // at the end rather than next to |eat_next_bytes| makes the filter a little
+ // (but measurably) faster. (likely something related with struct layout vs
+ // cache sizes).
+ enum FilterAction {
+ kDrop,
+ kPassthrough,
+ kFilterString,
+ };
+ FilterAction action = FilterAction::kDrop;
+ };
+
+ uint32_t out_written() { return static_cast<uint32_t>(out_ - &out_buf_[0]); }
+
+ Config config_;
+
+ std::unique_ptr<uint8_t[]> out_buf_;
+ uint8_t* out_ = nullptr;
+ uint8_t* out_end_ = nullptr;
+
+ MessageTokenizer tokenizer_;
+ std::vector<StackState> stack_;
+
+ bool error_ = false;
+ bool track_field_usage_ = false;
+ std::unordered_map<std::string, int32_t> field_usage_;
+};
+
+} // namespace protozero
+
+#endif // SRC_PROTOZERO_FILTERING_MESSAGE_FILTER_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/protozero/filtering/message_filter.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "src/protozero/filtering/string_filter.h"
+
+namespace protozero {
+
+namespace {
+
+// Inline helpers to append proto fields in output. They are the equivalent of
+// the protozero::Message::AppendXXX() fields but don't require building and
+// maintaining a full protozero::Message object or dealing with scattered
+// output slices.
+// All these functions assume there is enough space in the output buffer, which
+// should be always the case assuming that we don't end up generating more
+// output than input.
+
+inline void AppendVarInt(uint32_t field_id, uint64_t value, uint8_t** out) {
+ *out = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), *out);
+ *out = proto_utils::WriteVarInt(value, *out);
+}
+
+// For fixed32 / fixed64.
+template <typename INT_T /* uint32_t | uint64_t*/>
+inline void AppendFixed(uint32_t field_id, INT_T value, uint8_t** out) {
+ *out = proto_utils::WriteVarInt(proto_utils::MakeTagFixed<INT_T>(field_id),
+ *out);
+ memcpy(*out, &value, sizeof(value));
+ *out += sizeof(value);
+}
+
+// For length-delimited (string, bytes) fields. Note: this function appends only
+// the proto preamble and the varint field that states the length of the payload
+// not the payload itself.
+// In the case of submessages, the caller needs to re-write the length at the
+// end in the in the returned memory area.
+// The problem here is that, because of filtering, the length of a submessage
+// might be < original length (the original length is still an upper-bound).
+// Returns a pair with: (1) the pointer where the final length should be written
+// into, (2) the length of the size field.
+// The caller must write a redundant varint to match the original size (i.e.
+// needs to use WriteRedundantVarInt()).
+inline std::pair<uint8_t*, uint32_t> AppendLenDelim(uint32_t field_id,
+ uint32_t len,
+ uint8_t** out) {
+ *out = proto_utils::WriteVarInt(proto_utils::MakeTagLengthDelimited(field_id),
+ *out);
+ uint8_t* size_field_start = *out;
+ *out = proto_utils::WriteVarInt(len, *out);
+ const size_t size_field_len = static_cast<size_t>(*out - size_field_start);
+ return std::make_pair(size_field_start, size_field_len);
+}
+} // namespace
+
+MessageFilter::MessageFilter(Config config) : config_(std::move(config)) {
+ // Push a state on the stack for the implicit root message.
+ stack_.emplace_back();
+}
+
+MessageFilter::MessageFilter() : MessageFilter(Config()) {}
+
+MessageFilter::~MessageFilter() = default;
+
+bool MessageFilter::Config::LoadFilterBytecode(const void* filter_data,
+ size_t len) {
+ return filter_.Load(filter_data, len);
+}
+
+bool MessageFilter::Config::SetFilterRoot(
+ std::initializer_list<uint32_t> field_ids) {
+ uint32_t root_msg_idx = 0;
+ for (uint32_t field_id : field_ids) {
+ auto res = filter_.Query(root_msg_idx, field_id);
+ if (!res.allowed || !res.nested_msg_field())
+ return false;
+ root_msg_idx = res.nested_msg_index;
+ }
+ root_msg_index_ = root_msg_idx;
+ return true;
+}
+
+MessageFilter::FilteredMessage MessageFilter::FilterMessageFragments(
+ const InputSlice* slices,
+ size_t num_slices) {
+ // First compute the upper bound for the output. The filtered message cannot
+ // be > the original message.
+ uint32_t total_len = 0;
+ for (size_t i = 0; i < num_slices; ++i)
+ total_len += slices[i].len;
+ out_buf_.reset(new uint8_t[total_len]);
+ out_ = out_buf_.get();
+ out_end_ = out_ + total_len;
+
+ // Reset the parser state.
+ tokenizer_ = MessageTokenizer();
+ error_ = false;
+ stack_.clear();
+ stack_.resize(2);
+ // stack_[0] is a sentinel and should never be hit in nominal cases. If we
+ // end up there we will just keep consuming the input stream and detecting
+ // at the end, without hurting the fastpath.
+ stack_[0].in_bytes_limit = UINT32_MAX;
+ stack_[0].eat_next_bytes = UINT32_MAX;
+ // stack_[1] is the actual root message.
+ stack_[1].in_bytes_limit = total_len;
+ stack_[1].msg_index = config_.root_msg_index();
+
+ // Process the input data and write the output.
+ for (size_t slice_idx = 0; slice_idx < num_slices; ++slice_idx) {
+ const InputSlice& slice = slices[slice_idx];
+ const uint8_t* data = static_cast<const uint8_t*>(slice.data);
+ for (size_t i = 0; i < slice.len; ++i)
+ FilterOneByte(data[i]);
+ }
+
+ // Construct the output object.
+ PERFETTO_CHECK(out_ >= out_buf_.get() && out_ <= out_end_);
+ auto used_size = static_cast<size_t>(out_ - out_buf_.get());
+ FilteredMessage res{std::move(out_buf_), used_size};
+ res.error = error_;
+ if (stack_.size() != 1 || !tokenizer_.idle() ||
+ stack_[0].in_bytes != total_len) {
+ res.error = true;
+ }
+ return res;
+}
+
+void MessageFilter::FilterOneByte(uint8_t octet) {
+ PERFETTO_DCHECK(!stack_.empty());
+
+ auto* state = &stack_.back();
+ StackState next_state{};
+ bool push_next_state = false;
+
+ if (state->eat_next_bytes > 0) {
+ // This is the case where the previous tokenizer_.Push() call returned a
+ // length delimited message which is NOT a submessage (a string or a bytes
+ // field). We just want to consume it, and pass it through/filter strings
+ // if the field was allowed.
+ --state->eat_next_bytes;
+ if (state->action == StackState::kPassthrough) {
+ *(out_++) = octet;
+ } else if (state->action == StackState::kFilterString) {
+ *(out_++) = octet;
+ if (state->eat_next_bytes == 0) {
+ config_.string_filter().MaybeFilter(
+ reinterpret_cast<char*>(state->filter_string_ptr),
+ static_cast<size_t>(out_ - state->filter_string_ptr));
+ }
+ }
+ } else {
+ MessageTokenizer::Token token = tokenizer_.Push(octet);
+ // |token| will not be valid() in most cases and this is WAI. When pushing
+ // a varint field, only the last byte yields a token, all the other bytes
+ // return an invalid token, they just update the internal tokenizer state.
+ if (token.valid()) {
+ auto filter = config_.filter().Query(state->msg_index, token.field_id);
+ switch (token.type) {
+ case proto_utils::ProtoWireType::kVarInt:
+ if (filter.allowed && filter.simple_field())
+ AppendVarInt(token.field_id, token.value, &out_);
+ break;
+ case proto_utils::ProtoWireType::kFixed32:
+ if (filter.allowed && filter.simple_field())
+ AppendFixed(token.field_id, static_cast<uint32_t>(token.value),
+ &out_);
+ break;
+ case proto_utils::ProtoWireType::kFixed64:
+ if (filter.allowed && filter.simple_field())
+ AppendFixed(token.field_id, static_cast<uint64_t>(token.value),
+ &out_);
+ break;
+ case proto_utils::ProtoWireType::kLengthDelimited:
+ // Here we have two cases:
+ // A. A simple string/bytes field: we just want to consume the next
+ // bytes (the string payload), optionally passing them through in
+ // output if the field is allowed.
+ // B. This is a nested submessage. In this case we want to recurse and
+ // push a new state on the stack.
+ // Note that we can't tell the difference between a
+ // "non-allowed string" and a "non-allowed submessage". But it doesn't
+ // matter because in both cases we just want to skip the next N bytes.
+ const auto submessage_len = static_cast<uint32_t>(token.value);
+ auto in_bytes_left = state->in_bytes_limit - state->in_bytes - 1;
+ if (PERFETTO_UNLIKELY(submessage_len > in_bytes_left)) {
+ // This is a malicious / malformed string/bytes/submessage that
+ // claims to be larger than the outer message that contains it.
+ return SetUnrecoverableErrorState();
+ }
+
+ if (filter.allowed && filter.nested_msg_field() &&
+ submessage_len > 0) {
+ // submessage_len == 0 is the edge case of a message with a 0-len
+ // (but present) submessage. In this case, if allowed, we don't want
+ // to push any further state (doing so would desync the FSM) but we
+ // still want to emit it.
+ // At this point |submessage_len| is only an upper bound. The
+ // final message written in output can be <= the one in input,
+ // only some of its fields might be allowed (also remember that
+ // this class implicitly removes redundancy varint encoding of
+ // len-delimited field lengths). The final length varint (the
+ // return value of AppendLenDelim()) will be filled when popping
+ // from |stack_|.
+ auto size_field =
+ AppendLenDelim(token.field_id, submessage_len, &out_);
+ push_next_state = true;
+ next_state.field_id = token.field_id;
+ next_state.msg_index = filter.nested_msg_index;
+ next_state.in_bytes_limit = submessage_len;
+ next_state.size_field = size_field.first;
+ next_state.size_field_len = size_field.second;
+ next_state.out_bytes_written_at_start = out_written();
+ } else {
+ // A string or bytes field, or a 0 length submessage.
+ state->eat_next_bytes = submessage_len;
+ if (filter.allowed && filter.filter_string_field()) {
+ state->action = StackState::kFilterString;
+ AppendLenDelim(token.field_id, submessage_len, &out_);
+ state->filter_string_ptr = out_;
+ } else if (filter.allowed) {
+ state->action = StackState::kPassthrough;
+ AppendLenDelim(token.field_id, submessage_len, &out_);
+ } else {
+ state->action = StackState::kDrop;
+ }
+ }
+ break;
+ } // switch(type)
+
+ if (PERFETTO_UNLIKELY(track_field_usage_)) {
+ IncrementCurrentFieldUsage(token.field_id, filter.allowed);
+ }
+ } // if (token.valid)
+ } // if (eat_next_bytes == 0)
+
+ ++state->in_bytes;
+ while (state->in_bytes >= state->in_bytes_limit) {
+ PERFETTO_DCHECK(state->in_bytes == state->in_bytes_limit);
+ push_next_state = false;
+
+ // We can't possibly write more than we read.
+ const uint32_t msg_bytes_written = static_cast<uint32_t>(
+ out_written() - state->out_bytes_written_at_start);
+ PERFETTO_DCHECK(msg_bytes_written <= state->in_bytes_limit);
+
+ // Backfill the length field of the
+ proto_utils::WriteRedundantVarInt(msg_bytes_written, state->size_field,
+ state->size_field_len);
+
+ const uint32_t in_bytes_processes_for_last_msg = state->in_bytes;
+ stack_.pop_back();
+ PERFETTO_CHECK(!stack_.empty());
+ state = &stack_.back();
+ state->in_bytes += in_bytes_processes_for_last_msg;
+ if (PERFETTO_UNLIKELY(!tokenizer_.idle())) {
+ // If we hit this case, it means that we got to the end of a submessage
+ // while decoding a field. We can't recover from this and we don't want to
+ // propagate a broken sub-message.
+ return SetUnrecoverableErrorState();
+ }
+ }
+
+ if (push_next_state) {
+ PERFETTO_DCHECK(tokenizer_.idle());
+ stack_.emplace_back(std::move(next_state));
+ state = &stack_.back();
+ }
+}
+
+void MessageFilter::SetUnrecoverableErrorState() {
+ error_ = true;
+ stack_.clear();
+ stack_.resize(1);
+ auto& state = stack_[0];
+ state.eat_next_bytes = UINT32_MAX;
+ state.in_bytes_limit = UINT32_MAX;
+ state.action = StackState::kDrop;
+ out_ = out_buf_.get(); // Reset the write pointer.
+}
+
+void MessageFilter::IncrementCurrentFieldUsage(uint32_t field_id,
+ bool allowed) {
+ // Slowpath. Used mainly in offline tools and tests to workout used fields in
+ // a proto.
+ PERFETTO_DCHECK(track_field_usage_);
+
+ // Field path contains a concatenation of varints, one for each nesting level.
+ // e.g. y in message Root { Sub x = 2; }; message Sub { SubSub y = 7; }
+ // is encoded as [varint(2) + varint(7)].
+ // We use varint to take the most out of SSO (small string opt). In most cases
+ // the path will fit in the on-stack 22 bytes, requiring no heap.
+ std::string field_path;
+
+ auto append_field_id = [&field_path](uint32_t id) {
+ uint8_t buf[10];
+ uint8_t* end = proto_utils::WriteVarInt(id, buf);
+ field_path.append(reinterpret_cast<char*>(buf),
+ static_cast<size_t>(end - buf));
+ };
+
+ // Append all the ancestors IDs from the state stack.
+ // The first entry of the stack has always ID 0 and we skip it (we don't know
+ // the ID of the root message itself).
+ PERFETTO_DCHECK(stack_.size() >= 2 && stack_[1].field_id == 0);
+ for (size_t i = 2; i < stack_.size(); ++i)
+ append_field_id(stack_[i].field_id);
+ // Append the id of the field in the current message.
+ append_field_id(field_id);
+ field_usage_[field_path] += allowed ? 1 : -1;
+}
+
+} // namespace protozero
+// gen_amalgamated begin source: src/tracing/service/metatrace_writer.cc
+// gen_amalgamated begin header: src/tracing/service/metatrace_writer.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_SERVICE_METATRACE_WRITER_H_
+#define SRC_TRACING_SERVICE_METATRACE_WRITER_H_
+
+#include <functional>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/metatrace.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}
+
+class TraceWriter;
+
+// Complements the base::metatrace infrastructure.
+// It hooks a callback to metatrace::Enable() and writes metatrace events into
+// a TraceWriter whenever the metatrace ring buffer is half full.
+// It is safe to create and attempt to start multiple instances of this class,
+// however only the first one will succeed because the metatrace framework
+// doesn't support multiple instances.
+// This class is defined here (instead of directly in src/probes/) so it can
+// be reused by other components (e.g. heapprofd).
+class MetatraceWriter {
+ public:
+ static constexpr char kDataSourceName[] = "perfetto.metatrace";
+
+ MetatraceWriter();
+ ~MetatraceWriter();
+
+ MetatraceWriter(const MetatraceWriter&) = delete;
+ MetatraceWriter& operator=(const MetatraceWriter&) = delete;
+ MetatraceWriter(MetatraceWriter&&) = delete;
+ MetatraceWriter& operator=(MetatraceWriter&&) = delete;
+
+ void Enable(base::TaskRunner*, std::unique_ptr<TraceWriter>, uint32_t tags);
+ void Disable();
+ void WriteAllAndFlushTraceWriter(std::function<void()> callback);
+
+ private:
+ void WriteAllAvailableEvents();
+
+ bool started_ = false;
+ base::TaskRunner* task_runner_ = nullptr;
+ std::unique_ptr<TraceWriter> trace_writer_;
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+ base::WeakPtrFactory<MetatraceWriter> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_SERVICE_METATRACE_WRITER_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/service/metatrace_writer.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_descriptor.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+
+MetatraceWriter::MetatraceWriter() : weak_ptr_factory_(this) {}
+
+MetatraceWriter::~MetatraceWriter() {
+ Disable();
+}
+
+void MetatraceWriter::Enable(base::TaskRunner* task_runner,
+ std::unique_ptr<TraceWriter> trace_writer,
+ uint32_t tags) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (started_) {
+ PERFETTO_DFATAL_OR_ELOG("Metatrace already started from this instance");
+ return;
+ }
+ task_runner_ = task_runner;
+ trace_writer_ = std::move(trace_writer);
+ auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
+ bool enabled = metatrace::Enable(
+ [weak_ptr] {
+ if (weak_ptr)
+ weak_ptr->WriteAllAvailableEvents();
+ },
+ task_runner, tags);
+ if (!enabled)
+ return;
+ started_ = true;
+}
+
+void MetatraceWriter::Disable() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!started_)
+ return;
+ metatrace::Disable();
+ started_ = false;
+ trace_writer_.reset();
+}
+
+void MetatraceWriter::WriteAllAvailableEvents() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!started_)
+ return;
+ for (auto it = metatrace::RingBuffer::GetReadIterator(); it; ++it) {
+ auto type_and_id = it->type_and_id.load(std::memory_order_acquire);
+ if (type_and_id == 0)
+ break; // Stop at the first incomplete event.
+
+ auto packet = trace_writer_->NewTracePacket();
+ packet->set_timestamp(it->timestamp_ns());
+ auto* evt = packet->set_perfetto_metatrace();
+ uint16_t type = type_and_id & metatrace::Record::kTypeMask;
+ uint16_t id = type_and_id & ~metatrace::Record::kTypeMask;
+ if (type == metatrace::Record::kTypeCounter) {
+ evt->set_counter_id(id);
+ evt->set_counter_value(it->counter_value);
+ } else {
+ evt->set_event_id(id);
+ evt->set_event_duration_ns(it->duration_ns);
+ }
+
+ evt->set_thread_id(static_cast<uint32_t>(it->thread_id));
+
+ if (metatrace::RingBuffer::has_overruns())
+ evt->set_has_overruns(true);
+ }
+ // The |it| destructor will automatically update the read index position in
+ // the meta-trace ring buffer.
+}
+
+void MetatraceWriter::WriteAllAndFlushTraceWriter(
+ std::function<void()> callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!started_)
+ return;
+ WriteAllAvailableEvents();
+ trace_writer_->Flush(std::move(callback));
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/service/packet_stream_validator.cc
+// gen_amalgamated begin header: src/tracing/service/packet_stream_validator.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_SERVICE_PACKET_STREAM_VALIDATOR_H_
+#define SRC_TRACING_SERVICE_PACKET_STREAM_VALIDATOR_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/slice.h"
+
+namespace perfetto {
+
+// Checks that the stream of trace packets sent by the producer is well formed.
+// This includes:
+//
+// - Checking that the packets are not truncated.
+// - There are no dangling bytes left over in the packets.
+// - Any trusted fields (e.g., uid) are not set.
+//
+// Note that we only validate top-level fields in the trace proto; sub-messages
+// are simply skipped.
+class PacketStreamValidator {
+ public:
+ PacketStreamValidator() = delete;
+
+ static bool Validate(const Slices&);
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_SERVICE_PACKET_STREAM_VALIDATOR_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/service/packet_stream_validator.h"
+
+#include <stddef.h>
+
+#include <cinttypes>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+
+namespace {
+
+using protozero::proto_utils::ProtoWireType;
+
+const uint32_t kReservedFieldIds[] = {
+ protos::pbzero::TracePacket::kTrustedUidFieldNumber,
+ protos::pbzero::TracePacket::kTrustedPacketSequenceIdFieldNumber,
+ protos::pbzero::TracePacket::kTraceConfigFieldNumber,
+ protos::pbzero::TracePacket::kTraceStatsFieldNumber,
+ protos::pbzero::TracePacket::kCompressedPacketsFieldNumber,
+ protos::pbzero::TracePacket::kSynchronizationMarkerFieldNumber,
+ protos::pbzero::TracePacket::kTrustedPidFieldNumber,
+ protos::pbzero::TracePacket::kMachineIdFieldNumber,
+};
+
+// This translation unit is quite subtle and perf-sensitive. Remember to check
+// BM_PacketStreamValidator in perfetto_benchmarks when making changes.
+
+// Checks that a packet, spread over several slices, is well-formed and doesn't
+// contain reserved top-level fields.
+// The checking logic is based on a state-machine that skips the fields' payload
+// and operates as follows:
+// +-------------------------------+ <-------------------------+
+// +----------> | Read field preamble (varint) | <----------------------+ |
+// | +-------------------------------+ | |
+// | | | | | |
+// | <Varint> <Fixed 32/64> <Length-delimited field> | |
+// | V | V | |
+// | +------------------+ | +--------------+ | |
+// | | Read field value | | | Read length | | |
+// | | (another varint) | | | (varint) | | |
+// | +------------------+ | +--------------+ | |
+// | | V V | |
+// +-----------+ +----------------+ +-----------------+ | |
+// | Skip 4/8 Bytes | | Skip $len Bytes |-------+ |
+// +----------------+ +-----------------+ |
+// | |
+// +------------------------------------------+
+class ProtoFieldParserFSM {
+ public:
+ // This method effectively continuously parses varints (either for the field
+ // preamble or the payload or the submessage length) and tells the caller
+ // (the Validate() method) how many bytes to skip until the next field.
+ size_t Push(uint8_t octet) {
+ varint_ |= static_cast<uint64_t>(octet & 0x7F) << varint_shift_;
+ if (octet & 0x80) {
+ varint_shift_ += 7;
+ if (varint_shift_ >= 64) {
+ // Do not invoke UB on next call.
+ varint_shift_ = 0;
+ state_ = kInvalidVarInt;
+ }
+ return 0;
+ }
+ uint64_t varint = varint_;
+ varint_ = 0;
+ varint_shift_ = 0;
+
+ switch (state_) {
+ case kFieldPreamble: {
+ uint64_t field_type = varint & 7; // 7 = 0..0111
+ auto field_id = static_cast<uint32_t>(varint >> 3);
+ // Check if the field id is reserved, go into an error state if it is.
+ for (size_t i = 0; i < base::ArraySize(kReservedFieldIds); ++i) {
+ if (field_id == kReservedFieldIds[i]) {
+ state_ = kWroteReservedField;
+ return 0;
+ }
+ }
+ // The field type is legit, now check it's well formed and within
+ // boundaries.
+ if (field_type == static_cast<uint64_t>(ProtoWireType::kVarInt)) {
+ state_ = kVarIntValue;
+ } else if (field_type ==
+ static_cast<uint64_t>(ProtoWireType::kFixed32)) {
+ return 4;
+ } else if (field_type ==
+ static_cast<uint64_t>(ProtoWireType::kFixed64)) {
+ return 8;
+ } else if (field_type ==
+ static_cast<uint64_t>(ProtoWireType::kLengthDelimited)) {
+ state_ = kLenDelimitedLen;
+ } else {
+ state_ = kUnknownFieldType;
+ }
+ return 0;
+ }
+
+ case kVarIntValue: {
+ // Consume the int field payload and go back to the next field.
+ state_ = kFieldPreamble;
+ return 0;
+ }
+
+ case kLenDelimitedLen: {
+ if (varint > protozero::proto_utils::kMaxMessageLength) {
+ state_ = kMessageTooBig;
+ return 0;
+ }
+ state_ = kFieldPreamble;
+ return static_cast<size_t>(varint);
+ }
+
+ case kWroteReservedField:
+ case kUnknownFieldType:
+ case kMessageTooBig:
+ case kInvalidVarInt:
+ // Persistent error states.
+ return 0;
+
+ } // switch(state_)
+ return 0; // To keep GCC happy.
+ }
+
+ // Queried at the end of the all payload. A message is well-formed only
+ // if the FSM is back to the state where it should parse the next field and
+ // hasn't started parsing any preamble.
+ bool valid() const { return state_ == kFieldPreamble && varint_shift_ == 0; }
+ int state() const { return static_cast<int>(state_); }
+
+ private:
+ enum State {
+ kFieldPreamble = 0, // Parsing the varint for the field preamble.
+ kVarIntValue, // Parsing the varint value for the field payload.
+ kLenDelimitedLen, // Parsing the length of the length-delimited field.
+
+ // Error states:
+ kWroteReservedField, // Tried to set a reserved field id.
+ kUnknownFieldType, // Encountered an invalid field type.
+ kMessageTooBig, // Size of the length delimited message was too big.
+ kInvalidVarInt, // VarInt larger than 64 bits.
+ };
+
+ State state_ = kFieldPreamble;
+ uint64_t varint_ = 0;
+ uint32_t varint_shift_ = 0;
+};
+
+} // namespace
+
+// static
+bool PacketStreamValidator::Validate(const Slices& slices) {
+ ProtoFieldParserFSM parser;
+ size_t skip_bytes = 0;
+ for (const Slice& slice : slices) {
+ for (size_t i = 0; i < slice.size;) {
+ const size_t skip_bytes_cur_slice = std::min(skip_bytes, slice.size - i);
+ if (skip_bytes_cur_slice > 0) {
+ i += skip_bytes_cur_slice;
+ skip_bytes -= skip_bytes_cur_slice;
+ } else {
+ uint8_t octet = *(reinterpret_cast<const uint8_t*>(slice.start) + i);
+ skip_bytes = parser.Push(octet);
+ i++;
+ }
+ }
+ }
+ if (skip_bytes == 0 && parser.valid())
+ return true;
+
+ PERFETTO_DLOG("Packet validation error (state %d, skip = %zu)",
+ parser.state(), skip_bytes);
+ return false;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/service/trace_buffer.cc
+// gen_amalgamated begin header: src/tracing/service/trace_buffer.h
+// gen_amalgamated begin header: include/perfetto/ext/base/flat_hash_map.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_FLAT_HASH_MAP_H_
+#define INCLUDE_PERFETTO_EXT_BASE_FLAT_HASH_MAP_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/hash.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+namespace perfetto {
+namespace base {
+
+// An open-addressing hashmap implementation.
+// Pointers are not stable, neither for keys nor values.
+// Has similar performances of a RobinHood hash (without the complications)
+// and 2x an unordered map.
+// Doc: http://go/perfetto-hashtables .
+//
+// When used to implement a string pool in TraceProcessor, the performance
+// characteristics obtained by replaying the set of strings seeen in a 4GB trace
+// (226M strings, 1M unique) are the following (see flat_hash_map_benchmark.cc):
+// This(Linear+AppendOnly) 879,383,676 ns 258.013M insertions/s
+// This(LinearProbe): 909,206,047 ns 249.546M insertions/s
+// This(QuadraticProbe): 1,083,844,388 ns 209.363M insertions/s
+// std::unordered_map: 6,203,351,870 ns 36.5811M insertions/s
+// tsl::robin_map: 931,403,397 ns 243.622M insertions/s
+// absl::flat_hash_map: 998,013,459 ns 227.379M insertions/s
+// FollyF14FastMap: 1,181,480,602 ns 192.074M insertions/s
+
+// The structs below define the probing algorithm used to probe slots upon a
+// collision. They are guaranteed to visit all slots as our table size is always
+// a power of two (see https://en.wikipedia.org/wiki/Quadratic_probing).
+
+// Linear probing can be faster if the hashing is well distributed and the load
+// is not high. For TraceProcessor's StringPool this is the fastest. It can
+// degenerate badly if the hashing doesn't spread (e.g., if using directly pids
+// as keys, with a no-op hashing function).
+struct LinearProbe {
+ static inline size_t Calc(size_t key_hash, size_t step, size_t capacity) {
+ return (key_hash + step) & (capacity - 1); // Linear probe
+ }
+};
+
+// Generates the sequence: 0, 3, 10, 21, 36, 55, ...
+// Can be a bit (~5%) slower than LinearProbe because it's less cache hot, but
+// avoids degenerating badly if the hash function is bad and causes clusters.
+// A good default choice unless benchmarks prove otherwise.
+struct QuadraticProbe {
+ static inline size_t Calc(size_t key_hash, size_t step, size_t capacity) {
+ return (key_hash + 2 * step * step + step) & (capacity - 1);
+ }
+};
+
+// Tends to perform in the middle between linear and quadratic.
+// It's a bit more cache-effective than the QuadraticProbe but can create more
+// clustering if the hash function doesn't spread well.
+// Generates the sequence: 0, 1, 3, 6, 10, 15, 21, ...
+struct QuadraticHalfProbe {
+ static inline size_t Calc(size_t key_hash, size_t step, size_t capacity) {
+ return (key_hash + (step * step + step) / 2) & (capacity - 1);
+ }
+};
+
+template <typename Key,
+ typename Value,
+ typename Hasher = base::Hash<Key>,
+ typename Probe = QuadraticProbe,
+ bool AppendOnly = false>
+class FlatHashMap {
+ public:
+ class Iterator {
+ public:
+ explicit Iterator(const FlatHashMap* map) : map_(map) { FindNextNonFree(); }
+ ~Iterator() = default;
+ Iterator(const Iterator&) = default;
+ Iterator& operator=(const Iterator&) = default;
+ Iterator(Iterator&&) noexcept = default;
+ Iterator& operator=(Iterator&&) noexcept = default;
+
+ Key& key() { return map_->keys_[idx_]; }
+ Value& value() { return map_->values_[idx_]; }
+ const Key& key() const { return map_->keys_[idx_]; }
+ const Value& value() const { return map_->values_[idx_]; }
+
+ explicit operator bool() const { return idx_ != kEnd; }
+ Iterator& operator++() {
+ PERFETTO_DCHECK(idx_ < map_->capacity_);
+ ++idx_;
+ FindNextNonFree();
+ return *this;
+ }
+
+ private:
+ static constexpr size_t kEnd = std::numeric_limits<size_t>::max();
+
+ void FindNextNonFree() {
+ const auto& tags = map_->tags_;
+ for (; idx_ < map_->capacity_; idx_++) {
+ if (tags[idx_] != kFreeSlot && (AppendOnly || tags[idx_] != kTombstone))
+ return;
+ }
+ idx_ = kEnd;
+ }
+
+ const FlatHashMap* map_ = nullptr;
+ size_t idx_ = 0;
+ }; // Iterator
+
+ static constexpr int kDefaultLoadLimitPct = 75;
+ explicit FlatHashMap(size_t initial_capacity = 0,
+ int load_limit_pct = kDefaultLoadLimitPct)
+ : load_limit_percent_(load_limit_pct) {
+ if (initial_capacity > 0)
+ Reset(initial_capacity);
+ }
+
+ // We are calling Clear() so that the destructors for the inserted entries are
+ // called (unless they are trivial, in which case it will be a no-op).
+ ~FlatHashMap() { Clear(); }
+
+ FlatHashMap(FlatHashMap&& other) noexcept {
+ tags_ = std::move(other.tags_);
+ keys_ = std::move(other.keys_);
+ values_ = std::move(other.values_);
+ capacity_ = other.capacity_;
+ size_ = other.size_;
+ max_probe_length_ = other.max_probe_length_;
+ load_limit_ = other.load_limit_;
+ load_limit_percent_ = other.load_limit_percent_;
+
+ new (&other) FlatHashMap();
+ }
+
+ FlatHashMap& operator=(FlatHashMap&& other) noexcept {
+ this->~FlatHashMap();
+ new (this) FlatHashMap(std::move(other));
+ return *this;
+ }
+
+ FlatHashMap(const FlatHashMap&) = delete;
+ FlatHashMap& operator=(const FlatHashMap&) = delete;
+
+ std::pair<Value*, bool> Insert(Key key, Value value) {
+ const size_t key_hash = Hasher{}(key);
+ const uint8_t tag = HashToTag(key_hash);
+ static constexpr size_t kSlotNotFound = std::numeric_limits<size_t>::max();
+
+ // This for loop does in reality at most two attempts:
+ // The first iteration either:
+ // - Early-returns, because the key exists already,
+ // - Finds an insertion slot and proceeds because the load is < limit.
+ // The second iteration is only hit in the unlikely case of this insertion
+ // bringing the table beyond the target |load_limit_| (or the edge case
+ // of the HT being full, if |load_limit_pct_| = 100).
+ // We cannot simply pre-grow the table before insertion, because we must
+ // guarantee that calling Insert() with a key that already exists doesn't
+ // invalidate iterators.
+ size_t insertion_slot;
+ size_t probe_len;
+ for (;;) {
+ PERFETTO_DCHECK((capacity_ & (capacity_ - 1)) == 0); // Must be a pow2.
+ insertion_slot = kSlotNotFound;
+ // Start the iteration at the desired slot (key_hash % capacity_)
+ // searching either for a free slot or a tombstone. In the worst case we
+ // might end up scanning the whole array of slots. The Probe functions are
+ // guaranteed to visit all the slots within |capacity_| steps. If we find
+ // a free slot, we can stop the search immediately (a free slot acts as an
+ // "end of chain for entries having the same hash". If we find a
+ // tombstones (a deleted slot) we remember its position, but have to keep
+ // searching until a free slot to make sure we don't insert a duplicate
+ // key.
+ for (probe_len = 0; probe_len < capacity_;) {
+ const size_t idx = Probe::Calc(key_hash, probe_len, capacity_);
+ PERFETTO_DCHECK(idx < capacity_);
+ const uint8_t tag_idx = tags_[idx];
+ ++probe_len;
+ if (tag_idx == kFreeSlot) {
+ // Rationale for "insertion_slot == kSlotNotFound": if we encountered
+ // a tombstone while iterating we should reuse that rather than
+ // taking another slot.
+ if (AppendOnly || insertion_slot == kSlotNotFound)
+ insertion_slot = idx;
+ break;
+ }
+ // We should never encounter tombstones in AppendOnly mode.
+ PERFETTO_DCHECK(!(tag_idx == kTombstone && AppendOnly));
+ if (!AppendOnly && tag_idx == kTombstone) {
+ insertion_slot = idx;
+ continue;
+ }
+ if (tag_idx == tag && keys_[idx] == key) {
+ // The key is already in the map.
+ return std::make_pair(&values_[idx], false);
+ }
+ } // for (idx)
+
+ // If we got to this point the key does not exist (otherwise we would have
+ // hit the return above) and we are going to insert a new entry.
+ // Before doing so, ensure we stay under the target load limit.
+ if (PERFETTO_UNLIKELY(size_ >= load_limit_)) {
+ MaybeGrowAndRehash(/*grow=*/true);
+ continue;
+ }
+ PERFETTO_DCHECK(insertion_slot != kSlotNotFound);
+ break;
+ } // for (attempt)
+
+ PERFETTO_CHECK(insertion_slot < capacity_);
+
+ // We found a free slot (or a tombstone). Proceed with the insertion.
+ Value* value_idx = &values_[insertion_slot];
+ new (&keys_[insertion_slot]) Key(std::move(key));
+ new (value_idx) Value(std::move(value));
+ tags_[insertion_slot] = tag;
+ PERFETTO_DCHECK(probe_len > 0 && probe_len <= capacity_);
+ max_probe_length_ = std::max(max_probe_length_, probe_len);
+ size_++;
+
+ return std::make_pair(value_idx, true);
+ }
+
+ Value* Find(const Key& key) const {
+ const size_t idx = FindInternal(key);
+ if (idx == kNotFound)
+ return nullptr;
+ return &values_[idx];
+ }
+
+ bool Erase(const Key& key) {
+ if (AppendOnly)
+ PERFETTO_FATAL("Erase() not supported because AppendOnly=true");
+ size_t idx = FindInternal(key);
+ if (idx == kNotFound)
+ return false;
+ EraseInternal(idx);
+ return true;
+ }
+
+ void Clear() {
+ // Avoid trivial heap operations on zero-capacity std::move()-d objects.
+ if (PERFETTO_UNLIKELY(capacity_ == 0))
+ return;
+
+ for (size_t i = 0; i < capacity_; ++i) {
+ const uint8_t tag = tags_[i];
+ if (tag != kFreeSlot && tag != kTombstone)
+ EraseInternal(i);
+ }
+ // Clear all tombstones. We really need to do this for AppendOnly.
+ MaybeGrowAndRehash(/*grow=*/false);
+ }
+
+ Value& operator[](Key key) {
+ auto it_and_inserted = Insert(std::move(key), Value{});
+ return *it_and_inserted.first;
+ }
+
+ Iterator GetIterator() { return Iterator(this); }
+ const Iterator GetIterator() const { return Iterator(this); }
+
+ size_t size() const { return size_; }
+ size_t capacity() const { return capacity_; }
+
+ // "protected" here is only for the flat_hash_map_benchmark.cc. Everything
+ // below is by all means private.
+ protected:
+ enum ReservedTags : uint8_t { kFreeSlot = 0, kTombstone = 1 };
+ static constexpr size_t kNotFound = std::numeric_limits<size_t>::max();
+
+ size_t FindInternal(const Key& key) const {
+ const size_t key_hash = Hasher{}(key);
+ const uint8_t tag = HashToTag(key_hash);
+ PERFETTO_DCHECK((capacity_ & (capacity_ - 1)) == 0); // Must be a pow2.
+ PERFETTO_DCHECK(max_probe_length_ <= capacity_);
+ for (size_t i = 0; i < max_probe_length_; ++i) {
+ const size_t idx = Probe::Calc(key_hash, i, capacity_);
+ const uint8_t tag_idx = tags_[idx];
+
+ if (tag_idx == kFreeSlot)
+ return kNotFound;
+ // HashToTag() never returns kTombstone, so the tag-check below cannot
+ // possibly match. Also we just want to skip tombstones.
+ if (tag_idx == tag && keys_[idx] == key) {
+ PERFETTO_DCHECK(tag_idx > kTombstone);
+ return idx;
+ }
+ } // for (idx)
+ return kNotFound;
+ }
+
+ void EraseInternal(size_t idx) {
+ PERFETTO_DCHECK(tags_[idx] > kTombstone);
+ PERFETTO_DCHECK(size_ > 0);
+ tags_[idx] = kTombstone;
+ keys_[idx].~Key();
+ values_[idx].~Value();
+ size_--;
+ }
+
+ PERFETTO_NO_INLINE void MaybeGrowAndRehash(bool grow) {
+ PERFETTO_DCHECK(size_ <= capacity_);
+ const size_t old_capacity = capacity_;
+
+ // Grow quickly up to 1MB, then chill.
+ const size_t old_size_bytes = old_capacity * (sizeof(Key) + sizeof(Value));
+ const size_t grow_factor = old_size_bytes < (1024u * 1024u) ? 8 : 2;
+ const size_t new_capacity =
+ grow ? std::max(old_capacity * grow_factor, size_t(1024))
+ : old_capacity;
+
+ auto old_tags(std::move(tags_));
+ auto old_keys(std::move(keys_));
+ auto old_values(std::move(values_));
+ size_t old_size = size_;
+
+ // This must be a CHECK (i.e. not just a DCHECK) to prevent UAF attacks on
+ // 32-bit archs that try to double the size of the table until wrapping.
+ PERFETTO_CHECK(new_capacity >= old_capacity);
+ Reset(new_capacity);
+
+ size_t new_size = 0; // Recompute the size.
+ for (size_t i = 0; i < old_capacity; ++i) {
+ const uint8_t old_tag = old_tags[i];
+ if (old_tag != kFreeSlot && old_tag != kTombstone) {
+ Insert(std::move(old_keys[i]), std::move(old_values[i]));
+ old_keys[i].~Key(); // Destroy the old objects.
+ old_values[i].~Value();
+ new_size++;
+ }
+ }
+ PERFETTO_DCHECK(new_size == old_size);
+ size_ = new_size;
+ }
+
+ // Doesn't call destructors. Use Clear() for that.
+ PERFETTO_NO_INLINE void Reset(size_t n) {
+ PERFETTO_DCHECK((n & (n - 1)) == 0); // Must be a pow2.
+
+ capacity_ = n;
+ max_probe_length_ = 0;
+ size_ = 0;
+ load_limit_ = n * static_cast<size_t>(load_limit_percent_) / 100;
+ load_limit_ = std::min(load_limit_, n);
+
+ tags_.reset(new uint8_t[n]);
+ memset(&tags_[0], 0, n); // Clear all tags.
+ keys_ = AlignedAllocTyped<Key[]>(n); // Deliberately not 0-initialized.
+ values_ = AlignedAllocTyped<Value[]>(n); // Deliberately not 0-initialized.
+ }
+
+ static inline uint8_t HashToTag(size_t full_hash) {
+ uint8_t tag = full_hash >> (sizeof(full_hash) * 8 - 8);
+ // Ensure the hash is always >= 2. We use 0, 1 for kFreeSlot and kTombstone.
+ tag += (tag <= kTombstone) << 1;
+ PERFETTO_DCHECK(tag > kTombstone);
+ return tag;
+ }
+
+ size_t capacity_ = 0;
+ size_t size_ = 0;
+ size_t max_probe_length_ = 0;
+ size_t load_limit_ = 0; // Updated every time |capacity_| changes.
+ int load_limit_percent_ =
+ kDefaultLoadLimitPct; // Load factor limit in % of |capacity_|.
+
+ // These arrays have always the |capacity_| elements.
+ // Note: AlignedUniquePtr just allocates memory, doesn't invoke any ctor/dtor.
+ std::unique_ptr<uint8_t[]> tags_;
+ AlignedUniquePtr<Key[]> keys_;
+ AlignedUniquePtr<Value[]> values_;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_FLAT_HASH_MAP_H_
+// gen_amalgamated begin header: include/perfetto/ext/tracing/core/client_identity.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_CLIENT_IDENTITY_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_CLIENT_IDENTITY_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+
+namespace perfetto {
+
+// This class groups data fields of a connected client that can get passed in
+// the tracing core to be emitted to trace packets.
+class ClientIdentity {
+ public:
+ ClientIdentity() = default;
+ ClientIdentity(uid_t uid, pid_t pid, MachineID machine_id = kDefaultMachineID)
+ : uid_(uid), pid_(pid), machine_id_(machine_id) {}
+
+ bool has_uid() const { return uid_ != base::kInvalidUid; }
+ uid_t uid() const { return uid_; }
+
+ bool has_pid() const { return pid_ != base::kInvalidPid; }
+ pid_t pid() const { return pid_; }
+
+ bool has_non_default_machine_id() const {
+ return machine_id_ != kDefaultMachineID;
+ }
+ base::MachineID machine_id() const { return machine_id_; }
+
+ private:
+ uid_t uid_ = base::kInvalidUid;
+ pid_t pid_ = base::kInvalidPid;
+ MachineID machine_id_ = kDefaultMachineID;
+};
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_CLIENT_IDENTITY_H_
+// gen_amalgamated begin header: src/tracing/service/histogram.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_SERVICE_HISTOGRAM_H_
+#define SRC_TRACING_SERVICE_HISTOGRAM_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+
+using HistValue = int64_t;
+
+// Usage:
+// Histogram<10, 100, 1000> h; // A histogram with 3 + 1 (overflow) bucket.
+// h.Add(value);
+// h.GetBucketSum(0); // Returns SUM(x) for 0 < x <= 10
+// h.GetBucketSum(1); // Returns SUM(x) for 10 < x <= 100
+// h.GetBucketSum(2); // Returns SUM(x) for 100 < x <= 1000
+// h.GetBucketSum(3); // Returns SUM(x) for x > 1000
+// Likewise h.GetBucketCount(x) returns the COUNT(x).
+template <HistValue... thresholds>
+class Histogram {
+ public:
+ // 1+ is for the overflow bucket (anything > the last threshold).
+ static constexpr size_t kNumBuckets = 1 + sizeof...(thresholds);
+
+ void Add(HistValue value) {
+ size_t bucket = BucketForValue(value);
+ bucket_sum_[bucket] += value;
+ ++bucket_count_[bucket];
+ }
+
+ static constexpr size_t num_buckets() { return kNumBuckets; }
+
+ HistValue GetBucketThres(size_t n) const {
+ PERFETTO_DCHECK(n < kNumBuckets);
+ return bucket_thres_[n];
+ }
+
+ uint64_t GetBucketCount(size_t n) const {
+ PERFETTO_DCHECK(n < kNumBuckets);
+ return bucket_count_[n];
+ }
+
+ HistValue GetBucketSum(size_t n) const {
+ PERFETTO_DCHECK(n < kNumBuckets);
+ return bucket_sum_[n];
+ }
+
+ void Merge(const Histogram& other) {
+ for (size_t i = 0; i < kNumBuckets; ++i) {
+ bucket_sum_[i] += other.bucket_sum_[i];
+ bucket_count_[i] += other.bucket_count_[i];
+ }
+ }
+
+ private:
+ static size_t BucketForValue(HistValue value) {
+ for (size_t i = 0; i < kNumBuckets - 1; i++) {
+ if (value <= bucket_thres_[i])
+ return i;
+ }
+ return kNumBuckets - 1;
+ }
+
+ static constexpr HistValue bucket_thres_[kNumBuckets]{
+ thresholds..., std::numeric_limits<HistValue>::max()};
+
+ HistValue bucket_sum_[kNumBuckets]{};
+ uint64_t bucket_count_[kNumBuckets]{};
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_SERVICE_HISTOGRAM_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_SERVICE_TRACE_BUFFER_H_
+#define SRC_TRACING_SERVICE_TRACE_BUFFER_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include <array>
+#include <limits>
+#include <map>
+#include <tuple>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/flat_hash_map.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/paged_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_annotations.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/client_identity.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/slice.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_stats.h"
+// gen_amalgamated expanded: #include "src/tracing/service/histogram.h"
+
+namespace perfetto {
+
+class TracePacket;
+
+// The main buffer, owned by the tracing service, where all the trace data is
+// ultimately stored into. The service will own several instances of this class,
+// at least one per active consumer (as defined in the |buffers| section of
+// trace_config.proto) and will copy chunks from the producer's shared memory
+// buffers into here when a CommitData IPC is received.
+//
+// Writing into the buffer
+// -----------------------
+// Data is copied from the SMB(s) using CopyChunkUntrusted(). The buffer will
+// hence contain data coming from different producers and different writer
+// sequences, more specifically:
+// - The service receives data by several producer(s), identified by their ID.
+// - Each producer writes several sequences identified by the same WriterID.
+// (they correspond to TraceWriter instances in the producer).
+// - Each Writer writes, in order, several chunks.
+// - Each chunk contains zero, one, or more TracePacket(s), or even just
+// fragments of packets (when they span across several chunks).
+//
+// So at any point in time, the buffer will contain a variable number of logical
+// sequences identified by the {ProducerID, WriterID} tuple. Any given chunk
+// will only contain packets (or fragments) belonging to the same sequence.
+//
+// The buffer operates by default as a ring buffer.
+// It has two overwrite policies:
+// 1. kOverwrite (default): if the write pointer reaches the read pointer, old
+// unread chunks will be overwritten by new chunks.
+// 2. kDiscard: if the write pointer reaches the read pointer, unread chunks
+// are preserved and the new chunks are discarded. Any future write becomes
+// a no-op, even if the reader manages to fully catch up. This is because
+// once a chunk is discarded, the sequence of packets is broken and trying
+// to recover would be too hard (also due to the fact that, at the same
+// time, we allow out-of-order commits and chunk re-writes).
+//
+// Chunks are (over)written in the same order of the CopyChunkUntrusted() calls.
+// When overwriting old content, entire chunks are overwritten or clobbered.
+// The buffer never leaves a partial chunk around. Chunks' payload is copied
+// as-is, but their header is not and is repacked in order to keep the
+// ProducerID around.
+//
+// Chunks are stored in the buffer next to each other. Each chunk is prefixed by
+// an inline header (ChunkRecord), which contains most of the fields of the
+// SharedMemoryABI ChunkHeader + the ProducerID + the size of the payload.
+// It's a conventional binary object stream essentially, where each ChunkRecord
+// tells where it ends and hence where to find the next one, like this:
+//
+// .-------------------------. 16 byte boundary
+// | ChunkRecord: 16 bytes |
+// | - chunk id: 4 bytes |
+// | - producer id: 2 bytes |
+// | - writer id: 2 bytes |
+// | - #fragments: 2 bytes |
+// +-----+ - record size: 2 bytes |
+// | | - flags+pad: 4 bytes |
+// | +-------------------------+
+// | | |
+// | : Chunk payload :
+// | | |
+// | +-------------------------+
+// | | Optional padding |
+// +---> +-------------------------+ 16 byte boundary
+// | ChunkRecord |
+// : :
+// Chunks stored in the buffer are always rounded up to 16 bytes (that is
+// sizeof(ChunkRecord)), in order to avoid further inner fragmentation.
+// Special "padding" chunks can be put in the buffer, e.g. in the case when we
+// try to write a chunk of size N while the write pointer is at the end of the
+// buffer, but the write pointer is < N bytes from the end (and hence needs to
+// wrap over).
+// Because of this, the buffer is self-describing: the contents of the buffer
+// can be reconstructed by just looking at the buffer content (this will be
+// quite useful in future to recover the buffer from crash reports).
+//
+// However, in order to keep some operations (patching and reading) fast, a
+// lookaside index is maintained (in |index_|), keeping each chunk in the buffer
+// indexed by their {ProducerID, WriterID, ChunkID} tuple.
+//
+// Patching data out-of-band
+// -------------------------
+// This buffer also supports patching chunks' payload out-of-band, after they
+// have been stored. This is to allow producers to backfill the "size" fields
+// of the protos that spawn across several chunks, when the previous chunks are
+// returned to the service. The MaybePatchChunkContents() deals with the fact
+// that a chunk might have been lost (because of wrapping) by the time the OOB
+// IPC comes.
+//
+// Reading from the buffer
+// -----------------------
+// This class supports one reader only (the consumer). Reads are NOT idempotent
+// as they move the read cursors around. Reading back the buffer is the most
+// conceptually complex part. The ReadNextTracePacket() method operates with
+// whole packet granularity. Packets are returned only when all their fragments
+// are available.
+// This class takes care of:
+// - Gluing packets within the same sequence, even if they are not stored
+// adjacently in the buffer.
+// - Re-ordering chunks within a sequence (using the ChunkID, which wraps).
+// - Detecting holes in packet fragments (because of loss of chunks).
+// Reads guarantee that packets for the same sequence are read in FIFO order
+// (according to their ChunkID), but don't give any guarantee about the read
+// order of packets from different sequences, see comments in
+// ReadNextTracePacket() below.
+class TraceBuffer {
+ public:
+ static const size_t InlineChunkHeaderSize; // For test/fake_packet.{cc,h}.
+
+ // See comment in the header above.
+ enum OverwritePolicy { kOverwrite, kDiscard };
+
+ // Argument for out-of-band patches applied through TryPatchChunkContents().
+ struct Patch {
+ // From SharedMemoryABI::kPacketHeaderSize.
+ static constexpr size_t kSize = 4;
+
+ size_t offset_untrusted;
+ std::array<uint8_t, kSize> data;
+ };
+
+ // Identifiers that are constant for a packet sequence.
+ struct PacketSequenceProperties {
+ ProducerID producer_id_trusted;
+ ClientIdentity client_identity_trusted;
+ WriterID writer_id;
+
+ uid_t producer_uid_trusted() const { return client_identity_trusted.uid(); }
+ pid_t producer_pid_trusted() const { return client_identity_trusted.pid(); }
+ };
+
+ // Holds the "used chunk" stats for each <Producer, Writer> tuple.
+ struct WriterStats {
+ Histogram<8, 32, 128, 512, 1024, 2048, 4096, 8192, 12288, 16384>
+ used_chunk_hist;
+ };
+
+ using WriterStatsMap = base::FlatHashMap<ProducerAndWriterID,
+ WriterStats,
+ std::hash<ProducerAndWriterID>,
+ base::QuadraticProbe,
+ /*AppendOnly=*/true>;
+
+ // Can return nullptr if the memory allocation fails.
+ static std::unique_ptr<TraceBuffer> Create(size_t size_in_bytes,
+ OverwritePolicy = kOverwrite);
+
+ ~TraceBuffer();
+
+ // Copies a Chunk from a producer Shared Memory Buffer into the trace buffer.
+ // |src| points to the first packet in the SharedMemoryABI's chunk shared with
+ // an untrusted producer. "untrusted" here means: the producer might be
+ // malicious and might change |src| concurrently while we read it (internally
+ // this method memcpy()-s first the chunk before processing it). None of the
+ // arguments should be trusted, unless otherwise stated. We can trust that
+ // |src| points to a valid memory area, but not its contents.
+ //
+ // This method may be called multiple times for the same chunk. In this case,
+ // the original chunk's payload will be overridden and its number of fragments
+ // and flags adjusted to match |num_fragments| and |chunk_flags|. The service
+ // may use this to insert partial chunks (|chunk_complete = false|) before the
+ // producer has committed them.
+ //
+ // If |chunk_complete| is |false|, the TraceBuffer will only consider the
+ // first |num_fragments - 1| packets to be complete, since the producer may
+ // not have finished writing the latest packet. Reading from a sequence will
+ // also not progress past any incomplete chunks until they were rewritten with
+ // |chunk_complete = true|, e.g. after a producer's commit.
+ //
+ // TODO(eseckler): Pass in a PacketStreamProperties instead of individual IDs.
+ void CopyChunkUntrusted(ProducerID producer_id_trusted,
+ const ClientIdentity& client_identity_trusted,
+
+ WriterID writer_id,
+ ChunkID chunk_id,
+ uint16_t num_fragments,
+ uint8_t chunk_flags,
+ bool chunk_complete,
+ const uint8_t* src,
+ size_t size);
+
+ // Applies a batch of |patches| to the given chunk, if the given chunk is
+ // still in the buffer. Does nothing if the given ChunkID is gone.
+ // Returns true if the chunk has been found and patched, false otherwise.
+ // |other_patches_pending| is used to determine whether this is the only
+ // batch of patches for the chunk or there is more.
+ // If |other_patches_pending| == false, the chunk is marked as ready to be
+ // consumed. If true, the state of the chunk is not altered.
+ //
+ // Note: If the producer is batching commits (see shared_memory_arbiter.h), it
+ // will also attempt to do patching locally. Namely, if nested messages are
+ // completed while the chunk on which they started is being batched (i.e.
+ // before it has been committed to the service), the producer will apply the
+ // respective patches to the batched chunk. These patches will not be sent to
+ // the service - i.e. only the patches that the producer did not manage to
+ // apply before committing the chunk will be applied here.
+ bool TryPatchChunkContents(ProducerID,
+ WriterID,
+ ChunkID,
+ const Patch* patches,
+ size_t patches_size,
+ bool other_patches_pending);
+
+ // To read the contents of the buffer the caller needs to:
+ // BeginRead()
+ // while (ReadNextTracePacket(packet_fragments)) { ... }
+ // No other calls to any other method should be interleaved between
+ // BeginRead() and ReadNextTracePacket().
+ // Reads in the TraceBuffer are NOT idempotent.
+ void BeginRead();
+
+ // Returns the next packet in the buffer, if any, and the producer_id,
+ // producer_uid, and writer_id of the producer/writer that wrote it (as passed
+ // in the CopyChunkUntrusted() call). Returns false if no packets can be read
+ // at this point. If a packet was read successfully,
+ // |previous_packet_on_sequence_dropped| is set to |true| if the previous
+ // packet on the sequence was dropped from the buffer before it could be read
+ // (e.g. because its chunk was overridden due to the ring buffer wrapping or
+ // due to an ABI violation), and to |false| otherwise.
+ //
+ // This function returns only complete packets. Specifically:
+ // When there is at least one complete packet in the buffer, this function
+ // returns true and populates the TracePacket argument with the boundaries of
+ // each fragment for one packet.
+ // TracePacket will have at least one slice when this function returns true.
+ // When there are no whole packets eligible to read (e.g. we are still missing
+ // fragments) this function returns false.
+ // This function guarantees also that packets for a given
+ // {ProducerID, WriterID} are read in FIFO order.
+ // This function does not guarantee any ordering w.r.t. packets belonging to
+ // different WriterID(s). For instance, given the following packets copied
+ // into the buffer:
+ // {ProducerID: 1, WriterID: 1}: P1 P2 P3
+ // {ProducerID: 1, WriterID: 2}: P4 P5 P6
+ // {ProducerID: 2, WriterID: 1}: P7 P8 P9
+ // The following read sequence is possible:
+ // P1, P4, P7, P2, P3, P5, P8, P9, P6
+ // But the following is guaranteed to NOT happen:
+ // P1, P5, P7, P4 (P4 cannot come after P5)
+ bool ReadNextTracePacket(TracePacket*,
+ PacketSequenceProperties* sequence_properties,
+ bool* previous_packet_on_sequence_dropped);
+
+ // Creates a read-only clone of the trace buffer. The read iterators of the
+ // new buffer will be reset, as if no Read() had been called. Calls to
+ // CopyChunkUntrusted() and TryPatchChunkContents() on the returned cloned
+ // TraceBuffer will CHECK().
+ std::unique_ptr<TraceBuffer> CloneReadOnly() const;
+
+ void set_read_only() { read_only_ = true; }
+ const WriterStatsMap& writer_stats() const { return writer_stats_; }
+ const TraceStats::BufferStats& stats() const { return stats_; }
+ size_t size() const { return size_; }
+ size_t used_size() const { return used_size_; }
+ OverwritePolicy overwrite_policy() const { return overwrite_policy_; }
+ bool has_data() const { return has_data_; }
+
+ private:
+ friend class TraceBufferTest;
+
+ // ChunkRecord is a Chunk header stored inline in the |data_| buffer, before
+ // the chunk payload (the packets' data). The |data_| buffer looks like this:
+ // +---------------+------------------++---------------+-----------------+
+ // | ChunkRecord 1 | Chunk payload 1 || ChunkRecord 2 | Chunk payload 2 | ...
+ // +---------------+------------------++---------------+-----------------+
+ // Most of the ChunkRecord fields are copied from SharedMemoryABI::ChunkHeader
+ // (the chunk header used in the shared memory buffers).
+ // A ChunkRecord can be a special "padding" record. In this case its payload
+ // should be ignored and the record should be just skipped.
+ //
+ // Full page move optimization:
+ // This struct has to be exactly (sizeof(PageHeader) + sizeof(ChunkHeader))
+ // (from shared_memory_abi.h) to allow full page move optimizations
+ // (TODO(primiano): not implemented yet). In the special case of moving a full
+ // 4k page that contains only one chunk, in fact, we can just ask the kernel
+ // to move the full SHM page (see SPLICE_F_{GIFT,MOVE}) and overlay the
+ // ChunkRecord on top of the moved SMB's header (page + chunk header).
+ // This special requirement is covered by static_assert(s) in the .cc file.
+ struct ChunkRecord {
+ explicit ChunkRecord(size_t sz) : flags{0}, is_padding{0} {
+ PERFETTO_DCHECK(sz >= sizeof(ChunkRecord) &&
+ sz % sizeof(ChunkRecord) == 0 && sz <= kMaxSize);
+ size = static_cast<decltype(size)>(sz);
+ }
+
+ bool is_valid() const { return size != 0; }
+
+ // Keep this structure packed and exactly 16 bytes (128 bits) big.
+
+ // [32 bits] Monotonic counter within the same writer_id.
+ ChunkID chunk_id = 0;
+
+ // [16 bits] ID of the Producer from which the Chunk was copied from.
+ ProducerID producer_id = 0;
+
+ // [16 bits] Unique per Producer (but not within the service).
+ // If writer_id == kWriterIdPadding the record should just be skipped.
+ WriterID writer_id = 0;
+
+ // Number of fragments contained in the chunk.
+ uint16_t num_fragments = 0;
+
+ // Size in bytes, including sizeof(ChunkRecord) itself.
+ uint16_t size;
+
+ uint8_t flags : 6; // See SharedMemoryABI::ChunkHeader::flags.
+ static constexpr size_t kFlagsBitMask = (1 << 6) - 1;
+
+ uint8_t is_padding : 1;
+ uint8_t unused_flag : 1;
+
+ // Not strictly needed, can be reused for more fields in the future. But
+ // right now helps to spot chunks in hex dumps.
+ char unused[3] = {'C', 'H', 'U'};
+
+ static constexpr size_t kMaxSize =
+ std::numeric_limits<decltype(size)>::max();
+ };
+
+ // Lookaside index entry. This serves two purposes:
+ // 1) Allow a fast lookup of ChunkRecord by their ID (the tuple
+ // {ProducerID, WriterID, ChunkID}). This is used when applying out-of-band
+ // patches to the contents of the chunks after they have been copied into
+ // the TraceBuffer.
+ // 2) keep the chunks ordered by their ID. This is used when reading back.
+ // 3) Keep metadata about the status of the chunk, e.g. whether the contents
+ // have been read already and should be skipped in a future read pass.
+ // This struct should not have any field that is essential for reconstructing
+ // the contents of the buffer from a crash dump.
+ struct ChunkMeta {
+ // Key used for sorting in the map.
+ struct Key {
+ Key(ProducerID p, WriterID w, ChunkID c)
+ : producer_id{p}, writer_id{w}, chunk_id{c} {}
+
+ Key(const Key&) noexcept = default;
+ Key& operator=(const Key&) = default;
+
+ explicit Key(const ChunkRecord& cr)
+ : Key(cr.producer_id, cr.writer_id, cr.chunk_id) {}
+
+ // Note that this sorting doesn't keep into account the fact that ChunkID
+ // will wrap over at some point. The extra logic in SequenceIterator deals
+ // with that.
+ bool operator<(const Key& other) const {
+ return std::tie(producer_id, writer_id, chunk_id) <
+ std::tie(other.producer_id, other.writer_id, other.chunk_id);
+ }
+
+ bool operator==(const Key& other) const {
+ return std::tie(producer_id, writer_id, chunk_id) ==
+ std::tie(other.producer_id, other.writer_id, other.chunk_id);
+ }
+
+ bool operator!=(const Key& other) const { return !(*this == other); }
+
+ // These fields should match at all times the corresponding fields in
+ // the |chunk_record|. They are copied here purely for efficiency to avoid
+ // dereferencing the buffer all the time.
+ ProducerID producer_id;
+ WriterID writer_id;
+ ChunkID chunk_id;
+ };
+
+ enum IndexFlags : uint8_t {
+ // If set, the chunk state was kChunkComplete at the time it was copied.
+ // If unset, the chunk was still kChunkBeingWritten while copied. When
+ // reading from the chunk's sequence, the sequence will not advance past
+ // this chunk until this flag is set.
+ kComplete = 1 << 0,
+
+ // If set, we skipped the last packet that we read from this chunk e.g.
+ // because we it was a continuation from a previous chunk that was dropped
+ // or due to an ABI violation.
+ kLastReadPacketSkipped = 1 << 1
+ };
+
+ ChunkMeta(uint32_t _record_off,
+ uint16_t _num_fragments,
+ bool complete,
+ uint8_t _flags,
+ const ClientIdentity& client_identity)
+ : record_off{_record_off},
+ client_identity_trusted(client_identity),
+ flags{_flags},
+ num_fragments{_num_fragments} {
+ if (complete)
+ index_flags = kComplete;
+ }
+
+ ChunkMeta(const ChunkMeta&) noexcept = default;
+
+ bool is_complete() const { return index_flags & kComplete; }
+
+ void set_complete(bool complete) {
+ if (complete) {
+ index_flags |= kComplete;
+ } else {
+ index_flags &= ~kComplete;
+ }
+ }
+
+ bool last_read_packet_skipped() const {
+ return index_flags & kLastReadPacketSkipped;
+ }
+
+ void set_last_read_packet_skipped(bool skipped) {
+ if (skipped) {
+ index_flags |= kLastReadPacketSkipped;
+ } else {
+ index_flags &= ~kLastReadPacketSkipped;
+ }
+ }
+
+ const uint32_t record_off; // Offset of ChunkRecord within |data_|.
+ const ClientIdentity client_identity_trusted;
+ // Flags set by TraceBuffer to track the state of the chunk in the index.
+ uint8_t index_flags = 0;
+
+ // Correspond to |chunk_record->flags| and |chunk_record->num_fragments|.
+ // Copied here for performance reasons (avoids having to dereference
+ // |chunk_record| while iterating over ChunkMeta) and to aid debugging in
+ // case the buffer gets corrupted.
+ uint8_t flags = 0; // See SharedMemoryABI::ChunkHeader::flags.
+ uint16_t num_fragments = 0; // Total number of packet fragments.
+
+ uint16_t num_fragments_read = 0; // Number of fragments already read.
+
+ // The start offset of the next fragment (the |num_fragments_read|-th) to be
+ // read. This is the offset in bytes from the beginning of the ChunkRecord's
+ // payload (the 1st fragment starts at |chunk_record| +
+ // sizeof(ChunkRecord)).
+ uint16_t cur_fragment_offset = 0;
+ };
+
+ using ChunkMap = std::map<ChunkMeta::Key, ChunkMeta>;
+
+ // Allows to iterate over a sub-sequence of |index_| for all keys belonging to
+ // the same {ProducerID,WriterID}. Furthermore takes into account the wrapping
+ // of ChunkID. Instances are valid only as long as the |index_| is not altered
+ // (can be used safely only between adjacent ReadNextTracePacket() calls).
+ // The order of the iteration will proceed in the following order:
+ // |wrapping_id| + 1 -> |seq_end|, |seq_begin| -> |wrapping_id|.
+ // Practical example:
+ // - Assume that kMaxChunkID == 7
+ // - Assume that we have all 8 chunks in the range (0..7).
+ // - Hence, |seq_begin| == c0, |seq_end| == c7
+ // - Assume |wrapping_id| = 4 (c4 is the last chunk copied over
+ // through a CopyChunkUntrusted()).
+ // The resulting iteration order will be: c5, c6, c7, c0, c1, c2, c3, c4.
+ struct SequenceIterator {
+ // Points to the 1st key (the one with the numerically min ChunkID).
+ ChunkMap::iterator seq_begin;
+
+ // Points one past the last key (the one with the numerically max ChunkID).
+ ChunkMap::iterator seq_end;
+
+ // Current iterator, always >= seq_begin && <= seq_end.
+ ChunkMap::iterator cur;
+
+ // The latest ChunkID written. Determines the start/end of the sequence.
+ ChunkID wrapping_id;
+
+ bool is_valid() const { return cur != seq_end; }
+
+ ProducerID producer_id() const {
+ PERFETTO_DCHECK(is_valid());
+ return cur->first.producer_id;
+ }
+
+ WriterID writer_id() const {
+ PERFETTO_DCHECK(is_valid());
+ return cur->first.writer_id;
+ }
+
+ ChunkID chunk_id() const {
+ PERFETTO_DCHECK(is_valid());
+ return cur->first.chunk_id;
+ }
+
+ ChunkMeta& operator*() {
+ PERFETTO_DCHECK(is_valid());
+ return cur->second;
+ }
+
+ // Moves |cur| to the next chunk in the index.
+ // is_valid() will become false after calling this, if this was the last
+ // entry of the sequence.
+ void MoveNext();
+
+ void MoveToEnd() { cur = seq_end; }
+ };
+
+ enum class ReadAheadResult {
+ kSucceededReturnSlices,
+ kFailedMoveToNextSequence,
+ kFailedStayOnSameSequence,
+ };
+
+ enum class ReadPacketResult {
+ kSucceeded,
+ kFailedInvalidPacket,
+ kFailedEmptyPacket,
+ };
+
+ explicit TraceBuffer(OverwritePolicy);
+ TraceBuffer(const TraceBuffer&) = delete;
+ TraceBuffer& operator=(const TraceBuffer&) = delete;
+
+ // Not using the implicit copy ctor to avoid unintended copies.
+ // This tagged ctor should be used only for Clone().
+ struct CloneCtor {};
+ TraceBuffer(CloneCtor, const TraceBuffer&);
+
+ bool Initialize(size_t size);
+
+ // Returns an object that allows to iterate over chunks in the |index_| that
+ // have the same {ProducerID, WriterID} of
+ // |seq_begin.first.{producer,writer}_id|. |seq_begin| must be an iterator to
+ // the first entry in the |index_| that has a different {ProducerID, WriterID}
+ // from the previous one. It is valid for |seq_begin| to be == index_.end()
+ // (i.e. if the index is empty). The iteration takes care of ChunkID wrapping,
+ // by using |last_chunk_id_|.
+ SequenceIterator GetReadIterForSequence(ChunkMap::iterator seq_begin);
+
+ // Used as a last resort when a buffer corruption is detected.
+ void ClearContentsAndResetRWCursors();
+
+ // Adds a padding record of the given size (must be a multiple of
+ // sizeof(ChunkRecord)).
+ void AddPaddingRecord(size_t);
+
+ // Look for contiguous fragment of the same packet starting from |read_iter_|.
+ // If a contiguous packet is found, all the fragments are pushed into
+ // TracePacket and the function returns kSucceededReturnSlices. If not, the
+ // function returns either kFailedMoveToNextSequence or
+ // kFailedStayOnSameSequence, telling the caller to continue looking for
+ // packets.
+ ReadAheadResult ReadAhead(TracePacket*);
+
+ // Deletes (by marking the record invalid and removing form the index) all
+ // chunks from |wptr_| to |wptr_| + |bytes_to_clear|.
+ // Returns:
+ // * The size of the gap left between the next valid Chunk and the end of
+ // the deletion range.
+ // * 0 if no next valid chunk exists (if the buffer is still zeroed).
+ // * -1 if the buffer |overwrite_policy_| == kDiscard and the deletion would
+ // cause unread chunks to be overwritten. In this case the buffer is left
+ // untouched.
+ // Graphically, assume the initial situation is the following (|wptr_| = 10).
+ // |0 |10 (wptr_) |30 |40 |60
+ // +---------+-----------------+---------+-------------------+---------+
+ // | Chunk 1 | Chunk 2 | Chunk 3 | Chunk 4 | Chunk 5 |
+ // +---------+-----------------+---------+-------------------+---------+
+ // |_________Deletion range_______|~~return value~~|
+ //
+ // A call to DeleteNextChunksFor(32) will remove chunks 2,3,4 and return 18
+ // (60 - 42), the distance between chunk 5 and the end of the deletion range.
+ ssize_t DeleteNextChunksFor(size_t bytes_to_clear);
+
+ // Decodes the boundaries of the next packet (or a fragment) pointed by
+ // ChunkMeta and pushes that into |TracePacket|. It also increments the
+ // |num_fragments_read| counter.
+ // TracePacket can be nullptr, in which case the read state is still advanced.
+ // When TracePacket is not nullptr, ProducerID must also be not null and will
+ // be updated with the ProducerID that originally wrote the chunk.
+ ReadPacketResult ReadNextPacketInChunk(ProducerAndWriterID,
+ ChunkMeta*,
+ TracePacket*);
+
+ void DcheckIsAlignedAndWithinBounds(const uint8_t* ptr) const {
+ PERFETTO_DCHECK(ptr >= begin() && ptr <= end() - sizeof(ChunkRecord));
+ PERFETTO_DCHECK(
+ (reinterpret_cast<uintptr_t>(ptr) & (alignof(ChunkRecord) - 1)) == 0);
+ }
+
+ ChunkRecord* GetChunkRecordAt(uint8_t* ptr) {
+ DcheckIsAlignedAndWithinBounds(ptr);
+ // We may be accessing a new (empty) record.
+ EnsureCommitted(static_cast<size_t>(ptr + sizeof(ChunkRecord) - begin()));
+ return reinterpret_cast<ChunkRecord*>(ptr);
+ }
+
+ void EnsureCommitted(size_t size) {
+ PERFETTO_DCHECK(size <= size_);
+ data_.EnsureCommitted(size);
+ used_size_ = std::max(used_size_, size);
+ }
+
+ void DiscardWrite();
+
+ // |src| can be nullptr (in which case |size| must be ==
+ // record.size - sizeof(ChunkRecord)), for the case of writing a padding
+ // record. |wptr_| is NOT advanced by this function, the caller must do that.
+ void WriteChunkRecord(uint8_t* wptr,
+ const ChunkRecord& record,
+ const uint8_t* src,
+ size_t size) {
+ // Note: |record.size| will be slightly bigger than |size| because of the
+ // ChunkRecord header and rounding, to ensure that all ChunkRecord(s) are
+ // multiple of sizeof(ChunkRecord). The invariant is:
+ // record.size >= |size| + sizeof(ChunkRecord) (== if no rounding).
+ PERFETTO_DCHECK(size <= ChunkRecord::kMaxSize);
+ PERFETTO_DCHECK(record.size >= sizeof(record));
+ PERFETTO_DCHECK(record.size % sizeof(record) == 0);
+ PERFETTO_DCHECK(record.size >= size + sizeof(record));
+ DcheckIsAlignedAndWithinBounds(wptr);
+
+ // We may be writing to this area for the first time.
+ EnsureCommitted(static_cast<size_t>(wptr + record.size - begin()));
+
+ // Deliberately not a *D*CHECK.
+ PERFETTO_CHECK(wptr + sizeof(record) + size <= end());
+ memcpy(wptr, &record, sizeof(record));
+ if (PERFETTO_LIKELY(src)) {
+ // If the producer modifies the data in the shared memory buffer while we
+ // are copying it to the central buffer, TSAN will (rightfully) flag that
+ // as a race. However the entire purpose of copying the data into the
+ // central buffer is that we can validate it without worrying that the
+ // producer changes it from under our feet, so this race is benign. The
+ // alternative would be to try computing which part of the buffer is safe
+ // to read (assuming a well-behaving client), but the risk of introducing
+ // a bug that way outweighs the benefit.
+ PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(
+ src, size, "Benign race when copying chunk from shared memory.")
+ memcpy(wptr + sizeof(record), src, size);
+ } else {
+ PERFETTO_DCHECK(size == record.size - sizeof(record));
+ }
+ const size_t rounding_size = record.size - sizeof(record) - size;
+ memset(wptr + sizeof(record) + size, 0, rounding_size);
+ }
+
+ uint32_t GetOffset(const void* _addr) {
+ const uintptr_t addr = reinterpret_cast<uintptr_t>(_addr);
+ const uintptr_t buf_start = reinterpret_cast<uintptr_t>(begin());
+ PERFETTO_DCHECK(addr >= buf_start && addr < buf_start + size_);
+ return static_cast<uint32_t>(addr - buf_start);
+ }
+
+ uint8_t* begin() const { return reinterpret_cast<uint8_t*>(data_.Get()); }
+ uint8_t* end() const { return begin() + size_; }
+ size_t size_to_end() const { return static_cast<size_t>(end() - wptr_); }
+
+ base::PagedMemory data_;
+ size_t size_ = 0; // Size in bytes of |data_|.
+
+ // High watermark. The number of bytes (<= |size_|) written into the buffer
+ // before the first wraparound. This increases as data is written into the
+ // buffer and then saturates at |size_|. Used for CloneReadOnly().
+ size_t used_size_ = 0;
+
+ size_t max_chunk_size_ = 0; // Max size in bytes allowed for a chunk.
+ uint8_t* wptr_ = nullptr; // Write pointer.
+
+ // An index that keeps track of the positions and metadata of each
+ // ChunkRecord.
+ ChunkMap index_;
+
+ // Read iterator used for ReadNext(). It is reset by calling BeginRead().
+ // It becomes invalid after any call to methods that alters the |index_|.
+ SequenceIterator read_iter_;
+
+ // See comments at the top of the file.
+ OverwritePolicy overwrite_policy_ = kOverwrite;
+
+ // This buffer is a read-only snapshot obtained via Clone(). If this is true
+ // calls to CopyChunkUntrusted() and TryPatchChunkContents() will CHECK().
+ bool read_only_ = false;
+
+ // Only used when |overwrite_policy_ == kDiscard|. This is set the first time
+ // a write fails because it would overwrite unread chunks.
+ bool discard_writes_ = false;
+
+ // Keeps track of the highest ChunkID written for a given sequence, taking
+ // into account a potential overflow of ChunkIDs. In the case of overflow,
+ // stores the highest ChunkID written since the overflow.
+ //
+ // TODO(primiano): should clean up keys from this map. Right now it grows
+ // without bounds (although realistically is not a problem unless we have too
+ // many producers/writers within the same trace session).
+ std::map<std::pair<ProducerID, WriterID>, ChunkID> last_chunk_id_written_;
+
+ // Statistics about buffer usage.
+ TraceStats::BufferStats stats_;
+
+ // Per-{Producer, Writer} statistics.
+ WriterStatsMap writer_stats_;
+
+ // Set to true upon the very first call to CopyChunkUntrusted() and never
+ // cleared. This is used to tell if the buffer has never been used since its
+ // creation (which in turn is used to optimize `clear_before_clone`).
+ bool has_data_ = false;
+
+#if PERFETTO_DCHECK_IS_ON()
+ bool changed_since_last_read_ = false;
+#endif
+
+ // When true disable some DCHECKs that have been put in place to detect
+ // bugs in the producers. This is for tests that feed malicious inputs and
+ // hence mimic a buggy producer.
+ bool suppress_client_dchecks_for_testing_ = false;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_SERVICE_TRACE_BUFFER_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/service/trace_buffer.h"
+
+#include <limits>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/client_identity.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_packet.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+#define TRACE_BUFFER_VERBOSE_LOGGING() 0 // Set to 1 when debugging unittests.
+#if TRACE_BUFFER_VERBOSE_LOGGING()
+#define TRACE_BUFFER_DLOG PERFETTO_DLOG
+#else
+#define TRACE_BUFFER_DLOG(...) void()
+#endif
+
+namespace perfetto {
+
+namespace {
+constexpr uint8_t kFirstPacketContinuesFromPrevChunk =
+ SharedMemoryABI::ChunkHeader::kFirstPacketContinuesFromPrevChunk;
+constexpr uint8_t kLastPacketContinuesOnNextChunk =
+ SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk;
+constexpr uint8_t kChunkNeedsPatching =
+ SharedMemoryABI::ChunkHeader::kChunkNeedsPatching;
+} // namespace.
+
+const size_t TraceBuffer::InlineChunkHeaderSize = sizeof(ChunkRecord);
+
+// static
+std::unique_ptr<TraceBuffer> TraceBuffer::Create(size_t size_in_bytes,
+ OverwritePolicy pol) {
+ std::unique_ptr<TraceBuffer> trace_buffer(new TraceBuffer(pol));
+ if (!trace_buffer->Initialize(size_in_bytes))
+ return nullptr;
+ return trace_buffer;
+}
+
+TraceBuffer::TraceBuffer(OverwritePolicy pol) : overwrite_policy_(pol) {
+ // See comments in ChunkRecord for the rationale of this.
+ static_assert(sizeof(ChunkRecord) == sizeof(SharedMemoryABI::PageHeader) +
+ sizeof(SharedMemoryABI::ChunkHeader),
+ "ChunkRecord out of sync with the layout of SharedMemoryABI");
+}
+
+TraceBuffer::~TraceBuffer() = default;
+
+bool TraceBuffer::Initialize(size_t size) {
+ static_assert(
+ SharedMemoryABI::kMinPageSize % sizeof(ChunkRecord) == 0,
+ "sizeof(ChunkRecord) must be an integer divider of a page size");
+ auto max_size = std::numeric_limits<decltype(ChunkMeta::record_off)>::max();
+ PERFETTO_CHECK(size <= static_cast<size_t>(max_size));
+ data_ = base::PagedMemory::Allocate(
+ size, base::PagedMemory::kMayFail | base::PagedMemory::kDontCommit);
+ if (!data_.IsValid()) {
+ PERFETTO_ELOG("Trace buffer allocation failed (size: %zu)", size);
+ return false;
+ }
+ size_ = size;
+ used_size_ = 0;
+ stats_.set_buffer_size(size);
+ max_chunk_size_ = std::min(size, ChunkRecord::kMaxSize);
+ wptr_ = begin();
+ index_.clear();
+ last_chunk_id_written_.clear();
+ read_iter_ = GetReadIterForSequence(index_.end());
+ return true;
+}
+
+// Note: |src| points to a shmem region that is shared with the producer. Assume
+// that the producer is malicious and will change the content of |src|
+// while we execute here. Don't do any processing on it other than memcpy().
+void TraceBuffer::CopyChunkUntrusted(
+ ProducerID producer_id_trusted,
+ const ClientIdentity& client_identity_trusted,
+ WriterID writer_id,
+ ChunkID chunk_id,
+ uint16_t num_fragments,
+ uint8_t chunk_flags,
+ bool chunk_complete,
+ const uint8_t* src,
+ size_t size) {
+ PERFETTO_CHECK(!read_only_);
+
+ // |record_size| = |size| + sizeof(ChunkRecord), rounded up to avoid to end
+ // up in a fragmented state where size_to_end() < sizeof(ChunkRecord).
+ const size_t record_size =
+ base::AlignUp<sizeof(ChunkRecord)>(size + sizeof(ChunkRecord));
+ TRACE_BUFFER_DLOG("CopyChunk @ %" PRIdPTR ", size=%zu", wptr_ - begin(), record_size);
+ if (PERFETTO_UNLIKELY(record_size > max_chunk_size_)) {
+ stats_.set_abi_violations(stats_.abi_violations() + 1);
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+ return;
+ }
+
+ has_data_ = true;
+#if PERFETTO_DCHECK_IS_ON()
+ changed_since_last_read_ = true;
+#endif
+
+ // If the chunk hasn't been completed, we should only consider the first
+ // |num_fragments - 1| packets complete. For simplicity, we simply disregard
+ // the last one when we copy the chunk.
+ if (PERFETTO_UNLIKELY(!chunk_complete)) {
+ if (num_fragments > 0) {
+ num_fragments--;
+ // These flags should only affect the last packet in the chunk. We clear
+ // them, so that TraceBuffer is able to look at the remaining packets in
+ // this chunk.
+ chunk_flags &= ~kLastPacketContinuesOnNextChunk;
+ chunk_flags &= ~kChunkNeedsPatching;
+ }
+ }
+
+ ChunkRecord record(record_size);
+ record.producer_id = producer_id_trusted;
+ record.chunk_id = chunk_id;
+ record.writer_id = writer_id;
+ record.num_fragments = num_fragments;
+ record.flags = chunk_flags & ChunkRecord::kFlagsBitMask;
+ ChunkMeta::Key key(record);
+
+ // Check whether we have already copied the same chunk previously. This may
+ // happen if the service scrapes chunks in a potentially incomplete state
+ // before receiving commit requests for them from the producer. Note that the
+ // service may scrape and thus override chunks in arbitrary order since the
+ // chunks aren't ordered in the SMB.
+ const auto it = index_.find(key);
+ if (PERFETTO_UNLIKELY(it != index_.end())) {
+ ChunkMeta* record_meta = &it->second;
+ ChunkRecord* prev = GetChunkRecordAt(begin() + record_meta->record_off);
+
+ // Verify that the old chunk's metadata corresponds to the new one.
+ // Overridden chunks should never change size, since the page layout is
+ // fixed per writer. The number of fragments should also never decrease and
+ // flags should not be removed.
+ if (PERFETTO_UNLIKELY(ChunkMeta::Key(*prev) != key ||
+ prev->size != record_size ||
+ prev->num_fragments > num_fragments ||
+ (prev->flags & chunk_flags) != prev->flags)) {
+ stats_.set_abi_violations(stats_.abi_violations() + 1);
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+ return;
+ }
+
+ // If this chunk was previously copied with the same number of fragments and
+ // the number didn't change, there's no need to copy it again. If the
+ // previous chunk was complete already, this should always be the case.
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_ ||
+ !record_meta->is_complete() ||
+ (chunk_complete && prev->num_fragments == num_fragments));
+ if (prev->num_fragments == num_fragments) {
+ TRACE_BUFFER_DLOG(" skipping recommit of identical chunk");
+ return;
+ }
+
+ // If we've already started reading from chunk N+1 following this chunk N,
+ // don't override chunk N. Otherwise we may end up reading a packet from
+ // chunk N after having read from chunk N+1, thereby violating sequential
+ // read of packets. This shouldn't happen if the producer is well-behaved,
+ // because it shouldn't start chunk N+1 before completing chunk N.
+ ChunkMeta::Key subsequent_key = key;
+ static_assert(std::numeric_limits<ChunkID>::max() == kMaxChunkID,
+ "ChunkID wraps");
+ subsequent_key.chunk_id++;
+ const auto subsequent_it = index_.find(subsequent_key);
+ if (subsequent_it != index_.end() &&
+ subsequent_it->second.num_fragments_read > 0) {
+ stats_.set_abi_violations(stats_.abi_violations() + 1);
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+ return;
+ }
+
+ // We should not have read past the last packet.
+ if (record_meta->num_fragments_read > prev->num_fragments) {
+ PERFETTO_ELOG(
+ "TraceBuffer read too many fragments from an incomplete chunk");
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+ return;
+ }
+
+ uint8_t* wptr = reinterpret_cast<uint8_t*>(prev);
+ TRACE_BUFFER_DLOG(" overriding chunk @ %" PRIdPTR ", size=%zu", wptr - begin(),
+ record_size);
+
+ // Update chunk meta data stored in the index, as it may have changed.
+ record_meta->num_fragments = num_fragments;
+ record_meta->flags = chunk_flags;
+ record_meta->set_complete(chunk_complete);
+
+ // Override the ChunkRecord contents at the original |wptr|.
+ TRACE_BUFFER_DLOG(" copying @ [%" PRIdPTR " - %" PRIdPTR "] %zu", wptr - begin(),
+ uintptr_t(wptr - begin()) + record_size, record_size);
+ WriteChunkRecord(wptr, record, src, size);
+ TRACE_BUFFER_DLOG("Chunk raw: %s",
+ base::HexDump(wptr, record_size).c_str());
+ stats_.set_chunks_rewritten(stats_.chunks_rewritten() + 1);
+ return;
+ }
+
+ if (PERFETTO_UNLIKELY(discard_writes_))
+ return DiscardWrite();
+
+ // If there isn't enough room from the given write position. Write a padding
+ // record to clear the end of the buffer and wrap back.
+ const size_t cached_size_to_end = size_to_end();
+ if (PERFETTO_UNLIKELY(record_size > cached_size_to_end)) {
+ ssize_t res = DeleteNextChunksFor(cached_size_to_end);
+ if (res == -1)
+ return DiscardWrite();
+ PERFETTO_DCHECK(static_cast<size_t>(res) <= cached_size_to_end);
+ AddPaddingRecord(cached_size_to_end);
+ wptr_ = begin();
+ stats_.set_write_wrap_count(stats_.write_wrap_count() + 1);
+ PERFETTO_DCHECK(size_to_end() >= record_size);
+ }
+
+ // At this point either |wptr_| points to an untouched part of the buffer
+ // (i.e. *wptr_ == 0) or we are about to overwrite one or more ChunkRecord(s).
+ // In the latter case we need to first figure out where the next valid
+ // ChunkRecord is (if it exists) and add padding between the new record.
+ // Example ((w) == write cursor):
+ //
+ // Initial state (wtpr_ == 0):
+ // |0 (w) |10 |30 |50
+ // +---------+-----------------+--------------------+--------------------+
+ // | Chunk 1 | Chunk 2 | Chunk 3 | Chunk 4 |
+ // +---------+-----------------+--------------------+--------------------+
+ //
+ // Let's assume we now want now write a 5th Chunk of size == 35. The final
+ // state should look like this:
+ // |0 |35 (w) |50
+ // +---------------------------------+---------------+--------------------+
+ // | Chunk 5 | Padding Chunk | Chunk 4 |
+ // +---------------------------------+---------------+--------------------+
+
+ // Deletes all chunks from |wptr_| to |wptr_| + |record_size|.
+ ssize_t del_res = DeleteNextChunksFor(record_size);
+ if (del_res == -1)
+ return DiscardWrite();
+ size_t padding_size = static_cast<size_t>(del_res);
+
+ // Now first insert the new chunk. At the end, if necessary, add the padding.
+ stats_.set_chunks_written(stats_.chunks_written() + 1);
+ stats_.set_bytes_written(stats_.bytes_written() + record_size);
+
+ uint32_t chunk_off = GetOffset(GetChunkRecordAt(wptr_));
+ auto it_and_inserted =
+ index_.emplace(key, ChunkMeta(chunk_off, num_fragments, chunk_complete,
+ chunk_flags, client_identity_trusted));
+ PERFETTO_DCHECK(it_and_inserted.second);
+ TRACE_BUFFER_DLOG(" copying @ [%" PRIdPTR " - %" PRIdPTR "] %zu", wptr_ - begin(),
+ uintptr_t(wptr_ - begin()) + record_size, record_size);
+ WriteChunkRecord(wptr_, record, src, size);
+ TRACE_BUFFER_DLOG("Chunk raw: %s", base::HexDump(wptr_, record_size).c_str());
+ wptr_ += record_size;
+ if (wptr_ >= end()) {
+ PERFETTO_DCHECK(padding_size == 0);
+ wptr_ = begin();
+ stats_.set_write_wrap_count(stats_.write_wrap_count() + 1);
+ }
+ DcheckIsAlignedAndWithinBounds(wptr_);
+
+ // Chunks may be received out of order, so only update last_chunk_id if the
+ // new chunk_id is larger. But take into account overflows by only selecting
+ // the new ID if its distance to the latest ID is smaller than half the number
+ // space.
+ //
+ // This accounts for both the case where the new ID has just overflown and
+ // last_chunk_id be updated even though it's smaller (e.g. |chunk_id| = 1 and
+ // |last_chunk_id| = kMaxChunkId; chunk_id - last_chunk_id = 0) and the case
+ // where the new ID is an out-of-order ID right after an overflow and
+ // last_chunk_id shouldn't be updated even though it's larger (e.g. |chunk_id|
+ // = kMaxChunkId and |last_chunk_id| = 1; chunk_id - last_chunk_id =
+ // kMaxChunkId - 1).
+ auto producer_and_writer_id = std::make_pair(producer_id_trusted, writer_id);
+ ChunkID& last_chunk_id = last_chunk_id_written_[producer_and_writer_id];
+ static_assert(std::numeric_limits<ChunkID>::max() == kMaxChunkID,
+ "This code assumes that ChunkID wraps at kMaxChunkID");
+ if (chunk_id - last_chunk_id < kMaxChunkID / 2) {
+ last_chunk_id = chunk_id;
+ } else {
+ stats_.set_chunks_committed_out_of_order(
+ stats_.chunks_committed_out_of_order() + 1);
+ }
+
+ if (padding_size)
+ AddPaddingRecord(padding_size);
+}
+
+ssize_t TraceBuffer::DeleteNextChunksFor(size_t bytes_to_clear) {
+ PERFETTO_CHECK(!discard_writes_);
+
+ // Find the position of the first chunk which begins at or after
+ // (|wptr_| + |bytes|). Note that such a chunk might not exist and we might
+ // either reach the end of the buffer or a zeroed region of the buffer.
+ uint8_t* next_chunk_ptr = wptr_;
+ uint8_t* search_end = wptr_ + bytes_to_clear;
+ TRACE_BUFFER_DLOG("Delete [%zu %zu]", wptr_ - begin(), search_end - begin());
+ DcheckIsAlignedAndWithinBounds(wptr_);
+ PERFETTO_DCHECK(search_end <= end());
+ std::vector<ChunkMap::iterator> index_delete;
+ uint64_t chunks_overwritten = stats_.chunks_overwritten();
+ uint64_t bytes_overwritten = stats_.bytes_overwritten();
+ uint64_t padding_bytes_cleared = stats_.padding_bytes_cleared();
+ while (next_chunk_ptr < search_end) {
+ const ChunkRecord& next_chunk = *GetChunkRecordAt(next_chunk_ptr);
+ TRACE_BUFFER_DLOG(
+ " scanning chunk [%zu %zu] (valid=%d)", next_chunk_ptr - begin(),
+ next_chunk_ptr - begin() + next_chunk.size, next_chunk.is_valid());
+
+ // We just reached the untouched part of the buffer, it's going to be all
+ // zeroes from here to end().
+ // Optimization: if during Initialize() we fill the buffer with padding
+ // records we could get rid of this branch.
+ if (PERFETTO_UNLIKELY(!next_chunk.is_valid())) {
+ // This should happen only at the first iteration. The zeroed area can
+ // only begin precisely at the |wptr_|, not after. Otherwise it means that
+ // we wrapped but screwed up the ChunkRecord chain.
+ PERFETTO_DCHECK(next_chunk_ptr == wptr_);
+ return 0;
+ }
+
+ // Remove |next_chunk| from the index, unless it's a padding record (padding
+ // records are not part of the index).
+ if (PERFETTO_LIKELY(!next_chunk.is_padding)) {
+ ChunkMeta::Key key(next_chunk);
+ auto it = index_.find(key);
+ bool will_remove = false;
+ if (PERFETTO_LIKELY(it != index_.end())) {
+ const ChunkMeta& meta = it->second;
+ if (PERFETTO_UNLIKELY(meta.num_fragments_read < meta.num_fragments)) {
+ if (overwrite_policy_ == kDiscard)
+ return -1;
+ chunks_overwritten++;
+ bytes_overwritten += next_chunk.size;
+ }
+ index_delete.push_back(it);
+ will_remove = true;
+ }
+ TRACE_BUFFER_DLOG(
+ " del index {%" PRIu32 ",%" PRIu32 ",%u} @ [%" PRIdPTR " - %" PRIdPTR "] %d",
+ key.producer_id, key.writer_id, key.chunk_id,
+ next_chunk_ptr - begin(), next_chunk_ptr - begin() + next_chunk.size,
+ will_remove);
+ PERFETTO_DCHECK(will_remove);
+ } else {
+ padding_bytes_cleared += next_chunk.size;
+ }
+
+ next_chunk_ptr += next_chunk.size;
+
+ // We should never hit this, unless we managed to screw up while writing
+ // to the buffer and breaking the ChunkRecord(s) chain.
+ // TODO(primiano): Write more meaningful logging with the status of the
+ // buffer, to get more actionable bugs in case we hit this.
+ PERFETTO_CHECK(next_chunk_ptr <= end());
+ }
+
+ // Remove from the index.
+ for (auto it : index_delete) {
+ index_.erase(it);
+ }
+ stats_.set_chunks_overwritten(chunks_overwritten);
+ stats_.set_bytes_overwritten(bytes_overwritten);
+ stats_.set_padding_bytes_cleared(padding_bytes_cleared);
+
+ PERFETTO_DCHECK(next_chunk_ptr >= search_end && next_chunk_ptr <= end());
+ return static_cast<ssize_t>(next_chunk_ptr - search_end);
+}
+
+void TraceBuffer::AddPaddingRecord(size_t size) {
+ PERFETTO_DCHECK(size >= sizeof(ChunkRecord) && size <= ChunkRecord::kMaxSize);
+ ChunkRecord record(size);
+ record.is_padding = 1;
+ TRACE_BUFFER_DLOG("AddPaddingRecord @ [%" PRIdPTR " - %" PRIdPTR "] %zu", wptr_ - begin(),
+ uintptr_t(wptr_ - begin()) + size, size);
+ WriteChunkRecord(wptr_, record, nullptr, size - sizeof(ChunkRecord));
+ stats_.set_padding_bytes_written(stats_.padding_bytes_written() + size);
+ // |wptr_| is deliberately not advanced when writing a padding record.
+}
+
+bool TraceBuffer::TryPatchChunkContents(ProducerID producer_id,
+ WriterID writer_id,
+ ChunkID chunk_id,
+ const Patch* patches,
+ size_t patches_size,
+ bool other_patches_pending) {
+ PERFETTO_CHECK(!read_only_);
+ ChunkMeta::Key key(producer_id, writer_id, chunk_id);
+ auto it = index_.find(key);
+ if (it == index_.end()) {
+ stats_.set_patches_failed(stats_.patches_failed() + 1);
+ return false;
+ }
+ ChunkMeta& chunk_meta = it->second;
+
+ // Check that the index is consistent with the actual ProducerID/WriterID
+ // stored in the ChunkRecord.
+
+ ChunkRecord* chunk_record = GetChunkRecordAt(begin() + chunk_meta.record_off);
+ PERFETTO_DCHECK(ChunkMeta::Key(*chunk_record) == key);
+ uint8_t* chunk_begin = reinterpret_cast<uint8_t*>(chunk_record);
+ PERFETTO_DCHECK(chunk_begin >= begin());
+ uint8_t* chunk_end = chunk_begin + chunk_record->size;
+ PERFETTO_DCHECK(chunk_end <= end());
+
+ static_assert(Patch::kSize == SharedMemoryABI::kPacketHeaderSize,
+ "Patch::kSize out of sync with SharedMemoryABI");
+
+ for (size_t i = 0; i < patches_size; i++) {
+ uint8_t* ptr =
+ chunk_begin + sizeof(ChunkRecord) + patches[i].offset_untrusted;
+ TRACE_BUFFER_DLOG("PatchChunk {%" PRIu32 ",%" PRIu32
+ ",%u} size=%zu @ %zu with {%02x %02x %02x %02x} cur "
+ "{%02x %02x %02x %02x}",
+ producer_id, writer_id, chunk_id, chunk_end - chunk_begin,
+ patches[i].offset_untrusted, patches[i].data[0],
+ patches[i].data[1], patches[i].data[2],
+ patches[i].data[3], ptr[0], ptr[1], ptr[2], ptr[3]);
+ if (ptr < chunk_begin + sizeof(ChunkRecord) ||
+ ptr > chunk_end - Patch::kSize) {
+ // Either the IPC was so slow and in the meantime the writer managed to
+ // wrap over |chunk_id| or the producer sent a malicious IPC.
+ stats_.set_patches_failed(stats_.patches_failed() + 1);
+ return false;
+ }
+
+ memcpy(ptr, &patches[i].data[0], Patch::kSize);
+ }
+ TRACE_BUFFER_DLOG("Chunk raw (after patch): %s",
+ base::HexDump(chunk_begin, chunk_record->size).c_str());
+
+ stats_.set_patches_succeeded(stats_.patches_succeeded() + patches_size);
+ if (!other_patches_pending) {
+ chunk_meta.flags &= ~kChunkNeedsPatching;
+ chunk_record->flags = chunk_meta.flags & ChunkRecord::kFlagsBitMask;
+ }
+ return true;
+}
+
+void TraceBuffer::BeginRead() {
+ read_iter_ = GetReadIterForSequence(index_.begin());
+#if PERFETTO_DCHECK_IS_ON()
+ changed_since_last_read_ = false;
+#endif
+}
+
+TraceBuffer::SequenceIterator TraceBuffer::GetReadIterForSequence(
+ ChunkMap::iterator seq_begin) {
+ SequenceIterator iter;
+ iter.seq_begin = seq_begin;
+ if (seq_begin == index_.end()) {
+ iter.cur = iter.seq_end = index_.end();
+ return iter;
+ }
+
+#if PERFETTO_DCHECK_IS_ON()
+ // Either |seq_begin| is == index_.begin() or the item immediately before must
+ // belong to a different {ProducerID, WriterID} sequence.
+ if (seq_begin != index_.begin() && seq_begin != index_.end()) {
+ auto prev_it = seq_begin;
+ prev_it--;
+ PERFETTO_DCHECK(
+ seq_begin == index_.begin() ||
+ std::tie(prev_it->first.producer_id, prev_it->first.writer_id) <
+ std::tie(seq_begin->first.producer_id, seq_begin->first.writer_id));
+ }
+#endif
+
+ // Find the first entry that has a greater {ProducerID, WriterID} (or just
+ // index_.end() if we reached the end).
+ ChunkMeta::Key key = seq_begin->first; // Deliberate copy.
+ key.chunk_id = kMaxChunkID;
+ iter.seq_end = index_.upper_bound(key);
+ PERFETTO_DCHECK(iter.seq_begin != iter.seq_end);
+
+ // Now find the first entry between [seq_begin, seq_end) that is
+ // > last_chunk_id_written_. This is where we the sequence will start (see
+ // notes about wrapping of IDs in the header).
+ auto producer_and_writer_id = std::make_pair(key.producer_id, key.writer_id);
+ PERFETTO_DCHECK(last_chunk_id_written_.count(producer_and_writer_id));
+ iter.wrapping_id = last_chunk_id_written_[producer_and_writer_id];
+ key.chunk_id = iter.wrapping_id;
+ iter.cur = index_.upper_bound(key);
+ if (iter.cur == iter.seq_end)
+ iter.cur = iter.seq_begin;
+ return iter;
+}
+
+void TraceBuffer::SequenceIterator::MoveNext() {
+ // Stop iterating when we reach the end of the sequence.
+ // Note: |seq_begin| might be == |seq_end|.
+ if (cur == seq_end || cur->first.chunk_id == wrapping_id) {
+ cur = seq_end;
+ return;
+ }
+
+ // If the current chunk wasn't completed yet, we shouldn't advance past it as
+ // it may be rewritten with additional packets.
+ if (!cur->second.is_complete()) {
+ cur = seq_end;
+ return;
+ }
+
+ ChunkID last_chunk_id = cur->first.chunk_id;
+ if (++cur == seq_end)
+ cur = seq_begin;
+
+ // There may be a missing chunk in the sequence of chunks, in which case the
+ // next chunk's ID won't follow the last one's. If so, skip the rest of the
+ // sequence. We'll return to it later once the hole is filled.
+ if (last_chunk_id + 1 != cur->first.chunk_id)
+ cur = seq_end;
+}
+
+bool TraceBuffer::ReadNextTracePacket(
+ TracePacket* packet,
+ PacketSequenceProperties* sequence_properties,
+ bool* previous_packet_on_sequence_dropped) {
+ // Note: MoveNext() moves only within the next chunk within the same
+ // {ProducerID, WriterID} sequence. Here we want to:
+ // - return the next patched+complete packet in the current sequence, if any.
+ // - return the first patched+complete packet in the next sequence, if any.
+ // - return false if none of the above is found.
+ TRACE_BUFFER_DLOG("ReadNextTracePacket()");
+
+ // Just in case we forget to initialize these below.
+ *sequence_properties = {0, ClientIdentity(), 0};
+ *previous_packet_on_sequence_dropped = false;
+
+ // At the start of each sequence iteration, we consider the last read packet
+ // dropped. While iterating over the chunks in the sequence, we update this
+ // flag based on our knowledge about the last packet that was read from each
+ // chunk (|last_read_packet_skipped| in ChunkMeta).
+ bool previous_packet_dropped = true;
+
+#if PERFETTO_DCHECK_IS_ON()
+ PERFETTO_DCHECK(!changed_since_last_read_);
+#endif
+ for (;; read_iter_.MoveNext()) {
+ if (PERFETTO_UNLIKELY(!read_iter_.is_valid())) {
+ // We ran out of chunks in the current {ProducerID, WriterID} sequence or
+ // we just reached the index_.end().
+
+ if (PERFETTO_UNLIKELY(read_iter_.seq_end == index_.end()))
+ return false;
+
+ // We reached the end of sequence, move to the next one.
+ // Note: ++read_iter_.seq_end might become index_.end(), but
+ // GetReadIterForSequence() knows how to deal with that.
+ read_iter_ = GetReadIterForSequence(read_iter_.seq_end);
+ PERFETTO_DCHECK(read_iter_.is_valid() && read_iter_.cur != index_.end());
+ previous_packet_dropped = true;
+ }
+
+ ChunkMeta* chunk_meta = &*read_iter_;
+
+ // If the chunk has holes that are awaiting to be patched out-of-band,
+ // skip the current sequence and move to the next one.
+ if (chunk_meta->flags & kChunkNeedsPatching) {
+ read_iter_.MoveToEnd();
+ continue;
+ }
+
+ const ProducerID trusted_producer_id = read_iter_.producer_id();
+ const WriterID writer_id = read_iter_.writer_id();
+ const ProducerAndWriterID producer_and_writer_id =
+ MkProducerAndWriterID(trusted_producer_id, writer_id);
+ const ClientIdentity& client_identity = chunk_meta->client_identity_trusted;
+
+ // At this point we have a chunk in |chunk_meta| that has not been fully
+ // read. We don't know yet whether we have enough data to read the full
+ // packet (in the case it's fragmented over several chunks) and we are about
+ // to find that out. Specifically:
+ // A) If the first fragment is unread and is a fragment continuing from a
+ // previous chunk, it means we have missed the previous ChunkID. In
+ // fact, if this wasn't the case, a previous call to ReadNext() shouldn't
+ // have moved the cursor to this chunk.
+ // B) Any fragment > 0 && < last is always readable. By definition an inner
+ // packet is never fragmented and hence doesn't require neither stitching
+ // nor any out-of-band patching. The same applies to the last packet
+ // iff it doesn't continue on the next chunk.
+ // C) If the last packet (which might be also the only packet in the chunk)
+ // is a fragment and continues on the next chunk, we peek at the next
+ // chunks and, if we have all of them, mark as read and move the cursor.
+ //
+ // +---------------+ +-------------------+ +---------------+
+ // | ChunkID: 1 | | ChunkID: 2 | | ChunkID: 3 |
+ // |---------------+ +-------------------+ +---------------+
+ // | Packet 1 | | | | ... Packet 3 |
+ // | Packet 2 | | ... Packet 3 ... | | Packet 4 |
+ // | Packet 3 ... | | | | Packet 5 ... |
+ // +---------------+ +-------------------+ +---------------+
+
+ PERFETTO_DCHECK(chunk_meta->num_fragments_read <=
+ chunk_meta->num_fragments);
+
+ // If we didn't read any packets from this chunk, the last packet was from
+ // the previous chunk we iterated over; so don't update
+ // |previous_packet_dropped| in this case.
+ if (chunk_meta->num_fragments_read > 0)
+ previous_packet_dropped = chunk_meta->last_read_packet_skipped();
+
+ while (chunk_meta->num_fragments_read < chunk_meta->num_fragments) {
+ enum { kSkip = 0, kReadOnePacket, kTryReadAhead } action;
+ if (chunk_meta->num_fragments_read == 0) {
+ if (chunk_meta->flags & kFirstPacketContinuesFromPrevChunk) {
+ action = kSkip; // Case A.
+ } else if (chunk_meta->num_fragments == 1 &&
+ (chunk_meta->flags & kLastPacketContinuesOnNextChunk)) {
+ action = kTryReadAhead; // Case C.
+ } else {
+ action = kReadOnePacket; // Case B.
+ }
+ } else if (chunk_meta->num_fragments_read <
+ chunk_meta->num_fragments - 1 ||
+ !(chunk_meta->flags & kLastPacketContinuesOnNextChunk)) {
+ action = kReadOnePacket; // Case B.
+ } else {
+ action = kTryReadAhead; // Case C.
+ }
+
+ TRACE_BUFFER_DLOG(" chunk %u, packet %hu of %hu, action=%d",
+ read_iter_.chunk_id(), chunk_meta->num_fragments_read,
+ chunk_meta->num_fragments, action);
+
+ if (action == kSkip) {
+ // This fragment will be skipped forever, not just in this ReadPacket()
+ // iteration. This happens by virtue of ReadNextPacketInChunk()
+ // incrementing the |num_fragments_read| and marking the fragment as
+ // read even if we didn't really.
+ ReadNextPacketInChunk(producer_and_writer_id, chunk_meta, nullptr);
+ chunk_meta->set_last_read_packet_skipped(true);
+ previous_packet_dropped = true;
+ continue;
+ }
+
+ if (action == kReadOnePacket) {
+ // The easy peasy case B.
+ ReadPacketResult result =
+ ReadNextPacketInChunk(producer_and_writer_id, chunk_meta, packet);
+
+ if (PERFETTO_LIKELY(result == ReadPacketResult::kSucceeded)) {
+ *sequence_properties = {trusted_producer_id, client_identity,
+ writer_id};
+ *previous_packet_on_sequence_dropped = previous_packet_dropped;
+ return true;
+ } else if (result == ReadPacketResult::kFailedEmptyPacket) {
+ // We can ignore and skip empty packets.
+ PERFETTO_DCHECK(packet->slices().empty());
+ continue;
+ }
+
+ // In extremely rare cases (producer bugged / malicious) the chunk might
+ // contain an invalid fragment. In such case we don't want to stall the
+ // sequence but just skip the chunk and move on. ReadNextPacketInChunk()
+ // marks the chunk as fully read, so we don't attempt to read from it
+ // again in a future call to ReadBuffers(). It also already records an
+ // abi violation for this.
+ PERFETTO_DCHECK(result == ReadPacketResult::kFailedInvalidPacket);
+ chunk_meta->set_last_read_packet_skipped(true);
+ previous_packet_dropped = true;
+ break;
+ }
+
+ PERFETTO_DCHECK(action == kTryReadAhead);
+ ReadAheadResult ra_res = ReadAhead(packet);
+ if (ra_res == ReadAheadResult::kSucceededReturnSlices) {
+ stats_.set_readaheads_succeeded(stats_.readaheads_succeeded() + 1);
+ *sequence_properties = {trusted_producer_id, client_identity,
+ writer_id};
+ *previous_packet_on_sequence_dropped = previous_packet_dropped;
+ return true;
+ }
+
+ if (ra_res == ReadAheadResult::kFailedMoveToNextSequence) {
+ // readahead didn't find a contiguous packet sequence. We'll try again
+ // on the next ReadPacket() call.
+ stats_.set_readaheads_failed(stats_.readaheads_failed() + 1);
+
+ // TODO(primiano): optimization: this MoveToEnd() is the reason why
+ // MoveNext() (that is called in the outer for(;;MoveNext)) needs to
+ // deal gracefully with the case of |cur|==|seq_end|. Maybe we can do
+ // something to avoid that check by reshuffling the code here?
+ read_iter_.MoveToEnd();
+
+ // This break will go back to beginning of the for(;;MoveNext()). That
+ // will move to the next sequence because we set the read iterator to
+ // its end.
+ break;
+ }
+
+ PERFETTO_DCHECK(ra_res == ReadAheadResult::kFailedStayOnSameSequence);
+
+ // In this case ReadAhead() might advance |read_iter_|, so we need to
+ // re-cache the |chunk_meta| pointer to point to the current chunk.
+ chunk_meta = &*read_iter_;
+ chunk_meta->set_last_read_packet_skipped(true);
+ previous_packet_dropped = true;
+ } // while(...) [iterate over packet fragments for the current chunk].
+ } // for(;;MoveNext()) [iterate over chunks].
+}
+
+TraceBuffer::ReadAheadResult TraceBuffer::ReadAhead(TracePacket* packet) {
+ static_assert(static_cast<ChunkID>(kMaxChunkID + 1) == 0,
+ "relying on kMaxChunkID to wrap naturally");
+ TRACE_BUFFER_DLOG(" readahead start @ chunk %u", read_iter_.chunk_id());
+ ChunkID next_chunk_id = read_iter_.chunk_id() + 1;
+ SequenceIterator it = read_iter_;
+ for (it.MoveNext(); it.is_valid(); it.MoveNext(), next_chunk_id++) {
+ // We should stay within the same sequence while iterating here.
+ PERFETTO_DCHECK(it.producer_id() == read_iter_.producer_id() &&
+ it.writer_id() == read_iter_.writer_id());
+
+ TRACE_BUFFER_DLOG(" expected chunk ID: %u, actual ID: %u", next_chunk_id,
+ it.chunk_id());
+
+ if (PERFETTO_UNLIKELY((*it).num_fragments == 0))
+ continue;
+
+ // If we miss the next chunk, stop looking in the current sequence and
+ // try another sequence. This chunk might come in the near future.
+ // The second condition is the edge case of a buggy/malicious
+ // producer. The ChunkID is contiguous but its flags don't make sense.
+ if (it.chunk_id() != next_chunk_id ||
+ PERFETTO_UNLIKELY(
+ !((*it).flags & kFirstPacketContinuesFromPrevChunk))) {
+ return ReadAheadResult::kFailedMoveToNextSequence;
+ }
+
+ // If the chunk is contiguous but has not been patched yet move to the next
+ // sequence and try coming back here on the next ReadNextTracePacket() call.
+ // TODO(primiano): add a test to cover this, it's a subtle case.
+ if ((*it).flags & kChunkNeedsPatching)
+ return ReadAheadResult::kFailedMoveToNextSequence;
+
+ // This is the case of an intermediate chunk which contains only one
+ // fragment which continues on the next chunk. This is the case for large
+ // packets, e.g.: [Packet0, Packet1(0)] [Packet1(1)] [Packet1(2), ...]
+ // (Packet1(X) := fragment X of Packet1).
+ if ((*it).num_fragments == 1 &&
+ ((*it).flags & kLastPacketContinuesOnNextChunk)) {
+ continue;
+ }
+
+ // We made it! We got all fragments for the packet without holes.
+ TRACE_BUFFER_DLOG(" readahead success @ chunk %u", it.chunk_id());
+ PERFETTO_DCHECK(((*it).num_fragments == 1 &&
+ !((*it).flags & kLastPacketContinuesOnNextChunk)) ||
+ (*it).num_fragments > 1);
+
+ // Now let's re-iterate over the [read_iter_, it] sequence and mark
+ // all the fragments as read.
+ bool packet_corruption = false;
+ for (;;) {
+ PERFETTO_DCHECK(read_iter_.is_valid());
+ TRACE_BUFFER_DLOG(" commit chunk %u", read_iter_.chunk_id());
+ if (PERFETTO_LIKELY((*read_iter_).num_fragments > 0)) {
+ // In the unlikely case of a corrupted packet (corrupted or empty
+ // fragment), invalidate the all stitching and move on to the next chunk
+ // in the same sequence, if any.
+ auto pw_id = MkProducerAndWriterID(it.producer_id(), it.writer_id());
+ packet_corruption |=
+ ReadNextPacketInChunk(pw_id, &*read_iter_, packet) ==
+ ReadPacketResult::kFailedInvalidPacket;
+ }
+ if (read_iter_.cur == it.cur)
+ break;
+ read_iter_.MoveNext();
+ } // for(;;)
+ PERFETTO_DCHECK(read_iter_.cur == it.cur);
+
+ if (PERFETTO_UNLIKELY(packet_corruption)) {
+ // ReadNextPacketInChunk() already records an abi violation for this case.
+ *packet = TracePacket(); // clear.
+ return ReadAheadResult::kFailedStayOnSameSequence;
+ }
+
+ return ReadAheadResult::kSucceededReturnSlices;
+ } // for(it...) [readahead loop]
+ return ReadAheadResult::kFailedMoveToNextSequence;
+}
+
+TraceBuffer::ReadPacketResult TraceBuffer::ReadNextPacketInChunk(
+ ProducerAndWriterID producer_and_writer_id,
+ ChunkMeta* const chunk_meta,
+ TracePacket* packet) {
+ PERFETTO_DCHECK(chunk_meta->num_fragments_read < chunk_meta->num_fragments);
+ PERFETTO_DCHECK(!(chunk_meta->flags & kChunkNeedsPatching));
+
+ const uint8_t* record_begin = begin() + chunk_meta->record_off;
+ DcheckIsAlignedAndWithinBounds(record_begin);
+ auto* chunk_record = reinterpret_cast<const ChunkRecord*>(record_begin);
+ const uint8_t* record_end = record_begin + chunk_record->size;
+ const uint8_t* packets_begin = record_begin + sizeof(ChunkRecord);
+ const uint8_t* packet_begin = packets_begin + chunk_meta->cur_fragment_offset;
+
+ if (PERFETTO_UNLIKELY(packet_begin < packets_begin ||
+ packet_begin >= record_end)) {
+ // The producer has a bug or is malicious and did declare that the chunk
+ // contains more packets beyond its boundaries.
+ stats_.set_abi_violations(stats_.abi_violations() + 1);
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+ chunk_meta->cur_fragment_offset = 0;
+ chunk_meta->num_fragments_read = chunk_meta->num_fragments;
+ if (PERFETTO_LIKELY(chunk_meta->is_complete())) {
+ stats_.set_chunks_read(stats_.chunks_read() + 1);
+ stats_.set_bytes_read(stats_.bytes_read() + chunk_record->size);
+ }
+ return ReadPacketResult::kFailedInvalidPacket;
+ }
+
+ // A packet (or a fragment) starts with a varint stating its size, followed
+ // by its content. The varint shouldn't be larger than 4 bytes (just in case
+ // the producer is using a redundant encoding)
+ uint64_t packet_size = 0;
+ const uint8_t* header_end =
+ std::min(packet_begin + protozero::proto_utils::kMessageLengthFieldSize,
+ record_end);
+ const uint8_t* packet_data = protozero::proto_utils::ParseVarInt(
+ packet_begin, header_end, &packet_size);
+
+ const uint8_t* next_packet = packet_data + packet_size;
+ if (PERFETTO_UNLIKELY(next_packet <= packet_begin ||
+ next_packet > record_end)) {
+ // In BufferExhaustedPolicy::kDrop mode, TraceWriter may abort a fragmented
+ // packet by writing an invalid size in the last fragment's header. We
+ // should handle this case without recording an ABI violation (since Android
+ // R).
+ if (packet_size != SharedMemoryABI::kPacketSizeDropPacket) {
+ stats_.set_abi_violations(stats_.abi_violations() + 1);
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+ } else {
+ stats_.set_trace_writer_packet_loss(stats_.trace_writer_packet_loss() +
+ 1);
+ }
+ chunk_meta->cur_fragment_offset = 0;
+ chunk_meta->num_fragments_read = chunk_meta->num_fragments;
+ if (PERFETTO_LIKELY(chunk_meta->is_complete())) {
+ stats_.set_chunks_read(stats_.chunks_read() + 1);
+ stats_.set_bytes_read(stats_.bytes_read() + chunk_record->size);
+ }
+ return ReadPacketResult::kFailedInvalidPacket;
+ }
+
+ chunk_meta->cur_fragment_offset =
+ static_cast<uint16_t>(next_packet - packets_begin);
+ chunk_meta->num_fragments_read++;
+
+ if (PERFETTO_UNLIKELY(chunk_meta->num_fragments_read ==
+ chunk_meta->num_fragments &&
+ chunk_meta->is_complete())) {
+ stats_.set_chunks_read(stats_.chunks_read() + 1);
+ stats_.set_bytes_read(stats_.bytes_read() + chunk_record->size);
+ auto* writer_stats = writer_stats_.Insert(producer_and_writer_id, {}).first;
+ writer_stats->used_chunk_hist.Add(chunk_meta->cur_fragment_offset);
+ } else {
+ // We have at least one more packet to parse. It should be within the chunk.
+ if (chunk_meta->cur_fragment_offset + sizeof(ChunkRecord) >=
+ chunk_record->size) {
+ PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+ }
+ }
+
+ chunk_meta->set_last_read_packet_skipped(false);
+
+ if (PERFETTO_UNLIKELY(packet_size == 0))
+ return ReadPacketResult::kFailedEmptyPacket;
+
+ if (PERFETTO_LIKELY(packet))
+ packet->AddSlice(packet_data, static_cast<size_t>(packet_size));
+
+ return ReadPacketResult::kSucceeded;
+}
+
+void TraceBuffer::DiscardWrite() {
+ PERFETTO_DCHECK(overwrite_policy_ == kDiscard);
+ discard_writes_ = true;
+ stats_.set_chunks_discarded(stats_.chunks_discarded() + 1);
+ TRACE_BUFFER_DLOG(" discarding write");
+}
+
+std::unique_ptr<TraceBuffer> TraceBuffer::CloneReadOnly() const {
+ std::unique_ptr<TraceBuffer> buf(new TraceBuffer(CloneCtor(), *this));
+ if (!buf->data_.IsValid())
+ return nullptr; // PagedMemory::Allocate() failed. We are out of memory.
+ return buf;
+}
+
+TraceBuffer::TraceBuffer(CloneCtor, const TraceBuffer& src)
+ : overwrite_policy_(src.overwrite_policy_),
+ read_only_(true),
+ discard_writes_(src.discard_writes_) {
+ if (!Initialize(src.data_.size()))
+ return; // TraceBuffer::Clone() will check |data_| and return nullptr.
+
+ // The assignments below must be done after Initialize().
+
+ EnsureCommitted(src.used_size_);
+ memcpy(data_.Get(), src.data_.Get(), src.used_size_);
+ last_chunk_id_written_ = src.last_chunk_id_written_;
+
+ stats_ = src.stats_;
+ stats_.set_bytes_read(0);
+ stats_.set_chunks_read(0);
+ stats_.set_readaheads_failed(0);
+ stats_.set_readaheads_succeeded(0);
+
+ // Copy the index of chunk metadata and reset the read states.
+ index_ = ChunkMap(src.index_);
+ for (auto& kv : index_) {
+ ChunkMeta& chunk_meta = kv.second;
+ chunk_meta.num_fragments_read = 0;
+ chunk_meta.cur_fragment_offset = 0;
+ chunk_meta.set_last_read_packet_skipped(false);
+ }
+ read_iter_ = SequenceIterator();
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/service/tracing_service_impl.cc
+// gen_amalgamated begin header: src/tracing/service/tracing_service_impl.h
+// gen_amalgamated begin header: include/perfetto/ext/base/circular_queue.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_CIRCULAR_QUEUE_H_
+#define INCLUDE_PERFETTO_EXT_BASE_CIRCULAR_QUEUE_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <cstddef>
+#include <iterator>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+// CircularQueue is a push-back-only / pop-front-only queue with the following
+// characteristics:
+// - The storage is based on a flat circular buffer. Beginning and end wrap
+// as necessary, to keep pushes and pops O(1) as long as capacity expansion is
+// not required.
+// - Capacity is automatically expanded like in a std::vector. Expansion has a
+// O(N) cost.
+// - It allows random access, allowing in-place std::sort.
+// - Iterators are not stable. Mutating the container invalidates all iterators.
+// - It doesn't bother with const-correctness.
+//
+// Implementation details:
+// Internally, |begin|, |end| and iterators use 64-bit monotonic indexes, which
+// are incremented as if the queue was backed by unlimited storage.
+// Even assuming that elements are inserted and removed every nanosecond, 64 bit
+// is enough for 584 years.
+// Wrapping happens only when addressing elements in the underlying circular
+// storage. This limits the complexity and avoiding dealing with modular
+// arithmetic all over the places.
+template <class T>
+class CircularQueue {
+ public:
+ class Iterator {
+ public:
+ using difference_type = ptrdiff_t;
+ using value_type = T;
+ using pointer = T*;
+ using reference = T&;
+ using iterator_category = std::random_access_iterator_tag;
+
+ Iterator(CircularQueue* queue, uint64_t pos, uint32_t generation)
+ : queue_(queue),
+ pos_(pos)
+#if PERFETTO_DCHECK_IS_ON()
+ ,
+ generation_(generation)
+#endif
+ {
+ ignore_result(generation);
+ }
+
+ Iterator(const Iterator&) noexcept = default;
+ Iterator& operator=(const Iterator&) noexcept = default;
+ Iterator(Iterator&&) noexcept = default;
+ Iterator& operator=(Iterator&&) noexcept = default;
+
+ T* operator->() const {
+#if PERFETTO_DCHECK_IS_ON()
+ PERFETTO_DCHECK(generation_ == queue_->generation());
+#endif
+ return queue_->Get(pos_);
+ }
+
+ T& operator*() const { return *(operator->()); }
+
+ value_type& operator[](difference_type i) { return *(*this + i); }
+
+ Iterator& operator++() {
+ Add(1);
+ return *this;
+ }
+
+ Iterator operator++(int) {
+ Iterator ret = *this;
+ Add(1);
+ return ret;
+ }
+
+ Iterator& operator--() {
+ Add(-1);
+ return *this;
+ }
+
+ Iterator operator--(int) {
+ Iterator ret = *this;
+ Add(-1);
+ return ret;
+ }
+
+ friend Iterator operator+(const Iterator& iter, difference_type offset) {
+ Iterator ret = iter;
+ ret.Add(offset);
+ return ret;
+ }
+
+ Iterator& operator+=(difference_type offset) {
+ Add(offset);
+ return *this;
+ }
+
+ friend Iterator operator-(const Iterator& iter, difference_type offset) {
+ Iterator ret = iter;
+ ret.Add(-offset);
+ return ret;
+ }
+
+ Iterator& operator-=(difference_type offset) {
+ Add(-offset);
+ return *this;
+ }
+
+ friend ptrdiff_t operator-(const Iterator& lhs, const Iterator& rhs) {
+ return static_cast<ptrdiff_t>(lhs.pos_) -
+ static_cast<ptrdiff_t>(rhs.pos_);
+ }
+
+ friend bool operator==(const Iterator& lhs, const Iterator& rhs) {
+ return lhs.pos_ == rhs.pos_;
+ }
+
+ friend bool operator!=(const Iterator& lhs, const Iterator& rhs) {
+ return lhs.pos_ != rhs.pos_;
+ }
+
+ friend bool operator<(const Iterator& lhs, const Iterator& rhs) {
+ return lhs.pos_ < rhs.pos_;
+ }
+
+ friend bool operator<=(const Iterator& lhs, const Iterator& rhs) {
+ return lhs.pos_ <= rhs.pos_;
+ }
+
+ friend bool operator>(const Iterator& lhs, const Iterator& rhs) {
+ return lhs.pos_ > rhs.pos_;
+ }
+
+ friend bool operator>=(const Iterator& lhs, const Iterator& rhs) {
+ return lhs.pos_ >= rhs.pos_;
+ }
+
+ private:
+ inline void Add(difference_type offset) {
+ pos_ = static_cast<uint64_t>(static_cast<difference_type>(pos_) + offset);
+ PERFETTO_DCHECK(pos_ <= queue_->end_);
+ }
+
+ CircularQueue* queue_;
+ uint64_t pos_;
+
+#if PERFETTO_DCHECK_IS_ON()
+ uint32_t generation_;
+#endif
+ };
+
+ explicit CircularQueue(size_t initial_capacity = 1024) {
+ Grow(initial_capacity);
+ }
+
+ CircularQueue(CircularQueue&& other) noexcept
+ : entries_(std::move(other.entries_)),
+ capacity_(other.capacity_),
+ begin_(other.begin_),
+ end_(other.end_) {
+ increment_generation();
+ new (&other) CircularQueue(); // Reset the old queue so it's still usable.
+ }
+
+ CircularQueue& operator=(CircularQueue&& other) noexcept {
+ this->~CircularQueue(); // Destroy the current state.
+ new (this) CircularQueue(std::move(other)); // Use the move ctor above.
+ return *this;
+ }
+
+ explicit CircularQueue(const CircularQueue& other) noexcept {
+ Grow(other.capacity());
+ for (const auto& e : const_cast<CircularQueue&>(other))
+ emplace_back(e);
+ PERFETTO_DCHECK(size() == other.size());
+ }
+
+ CircularQueue& operator=(const CircularQueue& other) noexcept {
+ this->~CircularQueue(); // Destroy the current state.
+ new (this) CircularQueue(other); // Use the copy ctor above.
+ return *this;
+ }
+
+ ~CircularQueue() {
+ if (!entries_) {
+ PERFETTO_DCHECK(empty());
+ return;
+ }
+ clear(); // Invoke destructors on all alive entries.
+ PERFETTO_DCHECK(empty());
+ }
+
+ template <typename... Args>
+ void emplace_back(Args&&... args) {
+ increment_generation();
+ if (PERFETTO_UNLIKELY(size() >= capacity_))
+ Grow();
+ T* slot = Get(end_++);
+ new (slot) T(std::forward<Args>(args)...);
+ }
+
+ void erase_front(size_t n) {
+ increment_generation();
+ for (; n && (begin_ < end_); --n) {
+ Get(begin_)->~T();
+ begin_++; // This needs to be its own statement, Get() checks begin_.
+ }
+ }
+
+ void pop_front() { erase_front(1); }
+
+ void clear() { erase_front(size()); }
+
+ void shrink_to_fit() {
+ // We only bother shrinking if we can fit in quarter of the capacity we are
+ // currently using. Moreover, don't bother shrinking below 4096 elements as
+ // that will cause a lot of reallocations for little benefit.
+ if (size() > capacity() / 2 || capacity() <= 4096) {
+ return;
+ }
+ ChangeCapacity(capacity() / 2);
+ }
+
+ T& at(size_t idx) {
+ PERFETTO_DCHECK(idx < size());
+ return *Get(begin_ + idx);
+ }
+
+ Iterator begin() { return Iterator(this, begin_, generation()); }
+ Iterator end() { return Iterator(this, end_, generation()); }
+ T& front() { return *begin(); }
+ T& back() { return *(end() - 1); }
+
+ bool empty() const { return size() == 0; }
+
+ size_t size() const {
+ PERFETTO_DCHECK(end_ - begin_ <= capacity_);
+ return static_cast<size_t>(end_ - begin_);
+ }
+
+ size_t capacity() const { return capacity_; }
+
+#if PERFETTO_DCHECK_IS_ON()
+ uint32_t generation() const { return generation_; }
+ void increment_generation() { ++generation_; }
+#else
+ uint32_t generation() const { return 0; }
+ void increment_generation() {}
+#endif
+
+ private:
+ void Grow(size_t new_capacity = 0) {
+ // Capacity must be always a power of two. This allows Get() to use a simple
+ // bitwise-AND for handling the wrapping instead of a full division.
+ new_capacity = new_capacity ? new_capacity : capacity_ * 2;
+ PERFETTO_CHECK((new_capacity & (new_capacity - 1)) == 0); // Must be pow2.
+
+ // On 32-bit systems this might hit the 4GB wall and overflow. We can't do
+ // anything other than crash in this case.
+ PERFETTO_CHECK(new_capacity > capacity_);
+
+ ChangeCapacity(new_capacity);
+ }
+
+ void ChangeCapacity(size_t new_capacity) {
+ // We should still have enough space to fit all the elements in the queue.
+ PERFETTO_CHECK(new_capacity >= size());
+
+ AlignedUniquePtr<T[]> new_vec = AlignedAllocTyped<T[]>(new_capacity);
+
+ // Move all elements in the expanded array.
+ size_t new_size = 0;
+ for (uint64_t i = begin_; i < end_; i++)
+ new (&new_vec[new_size++]) T(std::move(*Get(i))); // Placement move ctor.
+
+ // Even if all the elements are std::move()-d and likely empty, we are still
+ // required to call the dtor for them.
+ for (uint64_t i = begin_; i < end_; i++)
+ Get(i)->~T();
+
+ begin_ = 0;
+ end_ = new_size;
+ capacity_ = new_capacity;
+ entries_ = std::move(new_vec);
+ }
+
+ inline T* Get(uint64_t pos) {
+ PERFETTO_DCHECK(pos >= begin_ && pos < end_);
+ PERFETTO_DCHECK((capacity_ & (capacity_ - 1)) == 0); // Must be a pow2.
+ auto index = static_cast<size_t>(pos & (capacity_ - 1));
+ return &entries_[index];
+ }
+
+ // Underlying storage. It's raw malloc-ed rather than being a unique_ptr<T[]>
+ // to allow having uninitialized entries inside it.
+ AlignedUniquePtr<T[]> entries_;
+ size_t capacity_ = 0; // Number of allocated slots (NOT bytes) in |entries_|.
+
+ // The |begin_| and |end_| indexes are monotonic and never wrap. Modular arith
+ // is used only when dereferencing entries in the vector.
+ uint64_t begin_ = 0;
+ uint64_t end_ = 0;
+
+// Generation is used in debug builds only for checking iterator validity.
+#if PERFETTO_DCHECK_IS_ON()
+ uint32_t generation_ = 0;
+#endif
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_CIRCULAR_QUEUE_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_SERVICE_TRACING_SERVICE_IMPL_H_
+#define SRC_TRACING_SERVICE_TRACING_SERVICE_IMPL_H_
+
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <memory>
+#include <optional>
+#include <random>
+#include <set>
+#include <utility>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/status.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/circular_queue.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/periodic_task.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/uuid.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/client_identity.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/commit_data_request.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/observable_events.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_stats.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/trace_config.h"
+// gen_amalgamated expanded: #include "src/android_stats/perfetto_atoms.h"
+// gen_amalgamated expanded: #include "src/tracing/core/id_allocator.h"
+
+namespace protozero {
+class MessageFilter;
+}
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+namespace protos {
+namespace gen {
+enum TraceStats_FinalFlushOutcome : int;
+}
+} // namespace protos
+
+class Consumer;
+class Producer;
+class SharedMemory;
+class SharedMemoryArbiterImpl;
+class TraceBuffer;
+class TracePacket;
+
+// The tracing service business logic.
+class TracingServiceImpl : public TracingService {
+ private:
+ struct DataSourceInstance;
+
+ public:
+ static constexpr size_t kMaxShmSize = 32 * 1024 * 1024ul;
+ static constexpr uint32_t kDataSourceStopTimeoutMs = 5000;
+ static constexpr uint8_t kSyncMarker[] = {0x82, 0x47, 0x7a, 0x76, 0xb2, 0x8d,
+ 0x42, 0xba, 0x81, 0xdc, 0x33, 0x32,
+ 0x6d, 0x57, 0xa0, 0x79};
+ static constexpr size_t kMaxTracePacketSliceSize =
+ 128 * 1024 - 512; // This is ipc::kIPCBufferSize - 512, see assertion in
+ // tracing_integration_test.cc and b/195065199
+
+ // This is a rough threshold to determine how many bytes to read from the
+ // buffers on each iteration when writing into a file. Since filtering and
+ // compression allocate memory, this effectively limits the amount of memory
+ // allocated.
+ static constexpr size_t kWriteIntoFileChunkSize = 1024 * 1024ul;
+
+ // The implementation behind the service endpoint exposed to each producer.
+ class ProducerEndpointImpl : public TracingService::ProducerEndpoint {
+ public:
+ ProducerEndpointImpl(ProducerID,
+ const ClientIdentity& client_identity,
+ TracingServiceImpl*,
+ base::TaskRunner*,
+ Producer*,
+ const std::string& producer_name,
+ const std::string& sdk_version,
+ bool in_process,
+ bool smb_scraping_enabled);
+ ~ProducerEndpointImpl() override;
+
+ // TracingService::ProducerEndpoint implementation.
+ void Disconnect() override;
+ void RegisterDataSource(const DataSourceDescriptor&) override;
+ void UpdateDataSource(const DataSourceDescriptor&) override;
+ void UnregisterDataSource(const std::string& name) override;
+ void RegisterTraceWriter(uint32_t writer_id,
+ uint32_t target_buffer) override;
+ void UnregisterTraceWriter(uint32_t writer_id) override;
+ void CommitData(const CommitDataRequest&, CommitDataCallback) override;
+ void SetupSharedMemory(std::unique_ptr<SharedMemory>,
+ size_t page_size_bytes,
+ bool provided_by_producer);
+ std::unique_ptr<TraceWriter> CreateTraceWriter(
+ BufferID,
+ BufferExhaustedPolicy) override;
+ SharedMemoryArbiter* MaybeSharedMemoryArbiter() override;
+ bool IsShmemProvidedByProducer() const override;
+ void NotifyFlushComplete(FlushRequestID) override;
+ void NotifyDataSourceStarted(DataSourceInstanceID) override;
+ void NotifyDataSourceStopped(DataSourceInstanceID) override;
+ SharedMemory* shared_memory() const override;
+ size_t shared_buffer_page_size_kb() const override;
+ void ActivateTriggers(const std::vector<std::string>&) override;
+ void Sync(std::function<void()> callback) override;
+
+ void OnTracingSetup();
+ void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&);
+ void StartDataSource(DataSourceInstanceID, const DataSourceConfig&);
+ void StopDataSource(DataSourceInstanceID);
+ void Flush(FlushRequestID,
+ const std::vector<DataSourceInstanceID>&,
+ FlushFlags);
+ void OnFreeBuffers(const std::vector<BufferID>& target_buffers);
+ void ClearIncrementalState(const std::vector<DataSourceInstanceID>&);
+
+ bool is_allowed_target_buffer(BufferID buffer_id) const {
+ return allowed_target_buffers_.count(buffer_id);
+ }
+
+ std::optional<BufferID> buffer_id_for_writer(WriterID writer_id) const {
+ const auto it = writers_.find(writer_id);
+ if (it != writers_.end())
+ return it->second;
+ return std::nullopt;
+ }
+
+ uid_t uid() const { return client_identity_.uid(); }
+ pid_t pid() const { return client_identity_.pid(); }
+ const ClientIdentity& client_identity() const { return client_identity_; }
+
+ private:
+ friend class TracingServiceImpl;
+ friend class TracingServiceImplTest;
+ friend class TracingIntegrationTest;
+ ProducerEndpointImpl(const ProducerEndpointImpl&) = delete;
+ ProducerEndpointImpl& operator=(const ProducerEndpointImpl&) = delete;
+
+ ProducerID const id_;
+ ClientIdentity const client_identity_;
+ TracingServiceImpl* const service_;
+ base::TaskRunner* const task_runner_;
+ Producer* producer_;
+ std::unique_ptr<SharedMemory> shared_memory_;
+ size_t shared_buffer_page_size_kb_ = 0;
+ SharedMemoryABI shmem_abi_;
+ size_t shmem_size_hint_bytes_ = 0;
+ size_t shmem_page_size_hint_bytes_ = 0;
+ bool is_shmem_provided_by_producer_ = false;
+ const std::string name_;
+ std::string sdk_version_;
+ bool in_process_;
+ bool smb_scraping_enabled_;
+
+ // Set of the global target_buffer IDs that the producer is configured to
+ // write into in any active tracing session.
+ std::set<BufferID> allowed_target_buffers_;
+
+ // Maps registered TraceWriter IDs to their target buffers as registered by
+ // the producer. Note that producers aren't required to register their
+ // writers, so we may see commits of chunks with WriterIDs that aren't
+ // contained in this map. However, if a producer does register a writer, the
+ // service will prevent the writer from writing into any other buffer than
+ // the one associated with it here. The BufferIDs stored in this map are
+ // untrusted, so need to be verified against |allowed_target_buffers_|
+ // before use.
+ std::map<WriterID, BufferID> writers_;
+
+ // This is used only in in-process configurations.
+ // SharedMemoryArbiterImpl methods themselves are thread-safe.
+ std::unique_ptr<SharedMemoryArbiterImpl> inproc_shmem_arbiter_;
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+ base::WeakPtrFactory<ProducerEndpointImpl> weak_ptr_factory_; // Keep last.
+ };
+
+ // The implementation behind the service endpoint exposed to each consumer.
+ class ConsumerEndpointImpl : public TracingService::ConsumerEndpoint {
+ public:
+ ConsumerEndpointImpl(TracingServiceImpl*,
+ base::TaskRunner*,
+ Consumer*,
+ uid_t uid);
+ ~ConsumerEndpointImpl() override;
+
+ void NotifyOnTracingDisabled(const std::string& error);
+ void NotifyCloneSnapshotTrigger();
+
+ // TracingService::ConsumerEndpoint implementation.
+ void EnableTracing(const TraceConfig&, base::ScopedFile) override;
+ void ChangeTraceConfig(const TraceConfig& cfg) override;
+ void StartTracing() override;
+ void DisableTracing() override;
+ void ReadBuffers() override;
+ void FreeBuffers() override;
+ void Flush(uint32_t timeout_ms, FlushCallback, FlushFlags) override;
+ void Detach(const std::string& key) override;
+ void Attach(const std::string& key) override;
+ void GetTraceStats() override;
+ void ObserveEvents(uint32_t enabled_event_types) override;
+ void QueryServiceState(QueryServiceStateArgs,
+ QueryServiceStateCallback) override;
+ void QueryCapabilities(QueryCapabilitiesCallback) override;
+ void SaveTraceForBugreport(SaveTraceForBugreportCallback) override;
+ void CloneSession(TracingSessionID, CloneSessionArgs) override;
+
+ // Will queue a task to notify the consumer about the state change.
+ void OnDataSourceInstanceStateChange(const ProducerEndpointImpl&,
+ const DataSourceInstance&);
+ void OnAllDataSourcesStarted();
+
+ base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ private:
+ friend class TracingServiceImpl;
+ ConsumerEndpointImpl(const ConsumerEndpointImpl&) = delete;
+ ConsumerEndpointImpl& operator=(const ConsumerEndpointImpl&) = delete;
+
+ // Returns a pointer to an ObservableEvents object that the caller can fill
+ // and schedules a task to send the ObservableEvents to the consumer.
+ ObservableEvents* AddObservableEvents();
+
+ base::TaskRunner* const task_runner_;
+ TracingServiceImpl* const service_;
+ Consumer* const consumer_;
+ uid_t const uid_;
+ TracingSessionID tracing_session_id_ = 0;
+
+ // Whether the consumer is interested in DataSourceInstance state change
+ // events.
+ uint32_t observable_events_mask_ = 0;
+
+ // ObservableEvents that will be sent to the consumer. If set, a task to
+ // flush the events to the consumer has been queued.
+ std::unique_ptr<ObservableEvents> observable_events_;
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+ base::WeakPtrFactory<ConsumerEndpointImpl> weak_ptr_factory_; // Keep last.
+ };
+
+ class RelayEndpointImpl : public TracingService::RelayEndpoint {
+ public:
+ using SyncMode = RelayEndpoint::SyncMode;
+
+ struct SyncedClockSnapshots {
+ SyncedClockSnapshots(SyncMode _sync_mode,
+ ClockSnapshotVector _client_clocks,
+ ClockSnapshotVector _host_clocks)
+ : sync_mode(_sync_mode),
+ client_clocks(std::move(_client_clocks)),
+ host_clocks(std::move(_host_clocks)) {}
+ SyncMode sync_mode;
+ ClockSnapshotVector client_clocks;
+ ClockSnapshotVector host_clocks;
+ };
+
+ explicit RelayEndpointImpl(RelayClientID relay_client_id,
+ TracingServiceImpl* service);
+ ~RelayEndpointImpl() override;
+ void SyncClocks(SyncMode sync_mode,
+ ClockSnapshotVector client_clocks,
+ ClockSnapshotVector host_clocks) override;
+ void Disconnect() override;
+
+ MachineID machine_id() const { return relay_client_id_.first; }
+
+ base::CircularQueue<SyncedClockSnapshots>& synced_clocks() {
+ return synced_clocks_;
+ }
+
+ private:
+ RelayEndpointImpl(const RelayEndpointImpl&) = delete;
+ RelayEndpointImpl& operator=(const RelayEndpointImpl&) = delete;
+
+ RelayClientID relay_client_id_;
+ TracingServiceImpl* const service_;
+ base::CircularQueue<SyncedClockSnapshots> synced_clocks_;
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+ };
+
+ explicit TracingServiceImpl(std::unique_ptr<SharedMemory::Factory>,
+ base::TaskRunner*,
+ InitOpts = {});
+ ~TracingServiceImpl() override;
+
+ // Called by ProducerEndpointImpl.
+ void DisconnectProducer(ProducerID);
+ void RegisterDataSource(ProducerID, const DataSourceDescriptor&);
+ void UpdateDataSource(ProducerID, const DataSourceDescriptor&);
+ void UnregisterDataSource(ProducerID, const std::string& name);
+ void CopyProducerPageIntoLogBuffer(ProducerID,
+ const ClientIdentity&,
+ WriterID,
+ ChunkID,
+ BufferID,
+ uint16_t num_fragments,
+ uint8_t chunk_flags,
+ bool chunk_complete,
+ const uint8_t* src,
+ size_t size);
+ void ApplyChunkPatches(ProducerID,
+ const std::vector<CommitDataRequest::ChunkToPatch>&);
+ void NotifyFlushDoneForProducer(ProducerID, FlushRequestID);
+ void NotifyDataSourceStarted(ProducerID, DataSourceInstanceID);
+ void NotifyDataSourceStopped(ProducerID, DataSourceInstanceID);
+ void ActivateTriggers(ProducerID, const std::vector<std::string>& triggers);
+
+ // Called by ConsumerEndpointImpl.
+ bool DetachConsumer(ConsumerEndpointImpl*, const std::string& key);
+ bool AttachConsumer(ConsumerEndpointImpl*, const std::string& key);
+ void DisconnectConsumer(ConsumerEndpointImpl*);
+ base::Status EnableTracing(ConsumerEndpointImpl*,
+ const TraceConfig&,
+ base::ScopedFile);
+ void ChangeTraceConfig(ConsumerEndpointImpl*, const TraceConfig&);
+
+ base::Status StartTracing(TracingSessionID);
+ void DisableTracing(TracingSessionID, bool disable_immediately = false);
+ void Flush(TracingSessionID tsid,
+ uint32_t timeout_ms,
+ ConsumerEndpoint::FlushCallback,
+ FlushFlags);
+ void FlushAndDisableTracing(TracingSessionID);
+ void FlushAndCloneSession(ConsumerEndpointImpl*,
+ TracingSessionID,
+ bool skip_filter,
+ bool for_bugreport);
+
+ // Starts reading the internal tracing buffers from the tracing session `tsid`
+ // and sends them to `*consumer` (which must be != nullptr).
+ //
+ // Only reads a limited amount of data in one call. If there's more data,
+ // immediately schedules itself on a PostTask.
+ //
+ // Returns false in case of error.
+ bool ReadBuffersIntoConsumer(TracingSessionID tsid,
+ ConsumerEndpointImpl* consumer);
+
+ // Reads all the tracing buffers from the tracing session `tsid` and writes
+ // them into the associated file.
+ //
+ // Reads all the data in the buffers (or until the file is full) before
+ // returning.
+ //
+ // If the tracing session write_period_ms is 0, the file is full or there has
+ // been an error, flushes the file and closes it. Otherwise, schedules itself
+ // to be executed after write_period_ms.
+ //
+ // Returns false in case of error.
+ bool ReadBuffersIntoFile(TracingSessionID);
+
+ void FreeBuffers(TracingSessionID);
+
+ // Service implementation.
+ std::unique_ptr<TracingService::ProducerEndpoint> ConnectProducer(
+ Producer*,
+ const ClientIdentity& client_identity,
+ const std::string& producer_name,
+ size_t shared_memory_size_hint_bytes = 0,
+ bool in_process = false,
+ ProducerSMBScrapingMode smb_scraping_mode =
+ ProducerSMBScrapingMode::kDefault,
+ size_t shared_memory_page_size_hint_bytes = 0,
+ std::unique_ptr<SharedMemory> shm = nullptr,
+ const std::string& sdk_version = {}) override;
+
+ std::unique_ptr<TracingService::ConsumerEndpoint> ConnectConsumer(
+ Consumer*,
+ uid_t) override;
+
+ std::unique_ptr<TracingService::RelayEndpoint> ConnectRelayClient(
+ RelayClientID) override;
+
+ void DisconnectRelayClient(RelayClientID);
+
+ // Set whether SMB scraping should be enabled by default or not. Producers can
+ // override this setting for their own SMBs.
+ void SetSMBScrapingEnabled(bool enabled) override {
+ smb_scraping_enabled_ = enabled;
+ }
+
+ // Exposed mainly for testing.
+ size_t num_producers() const { return producers_.size(); }
+ ProducerEndpointImpl* GetProducer(ProducerID) const;
+
+ private:
+ friend class TracingServiceImplTest;
+ friend class TracingIntegrationTest;
+
+ static constexpr int64_t kOneDayInNs = 24ll * 60 * 60 * 1000 * 1000 * 1000;
+
+ struct TriggerHistory {
+ int64_t timestamp_ns;
+ uint64_t name_hash;
+
+ bool operator<(const TriggerHistory& other) const {
+ return timestamp_ns < other.timestamp_ns;
+ }
+ };
+
+ struct RegisteredDataSource {
+ ProducerID producer_id;
+ DataSourceDescriptor descriptor;
+ };
+
+ // Represents an active data source for a tracing session.
+ struct DataSourceInstance {
+ DataSourceInstance(DataSourceInstanceID id,
+ const DataSourceConfig& cfg,
+ const std::string& ds_name,
+ bool notify_on_start,
+ bool notify_on_stop,
+ bool handles_incremental_state_invalidation,
+ bool no_flush_)
+ : instance_id(id),
+ config(cfg),
+ data_source_name(ds_name),
+ will_notify_on_start(notify_on_start),
+ will_notify_on_stop(notify_on_stop),
+ handles_incremental_state_clear(
+ handles_incremental_state_invalidation),
+ no_flush(no_flush_) {}
+ DataSourceInstance(const DataSourceInstance&) = delete;
+ DataSourceInstance& operator=(const DataSourceInstance&) = delete;
+
+ DataSourceInstanceID instance_id;
+ DataSourceConfig config;
+ std::string data_source_name;
+ bool will_notify_on_start;
+ bool will_notify_on_stop;
+ bool handles_incremental_state_clear;
+ bool no_flush;
+
+ enum DataSourceInstanceState {
+ CONFIGURED,
+ STARTING,
+ STARTED,
+ STOPPING,
+ STOPPED
+ };
+ DataSourceInstanceState state = CONFIGURED;
+ };
+
+ struct PendingFlush {
+ std::set<ProducerID> producers;
+ ConsumerEndpoint::FlushCallback callback;
+ explicit PendingFlush(decltype(callback) cb) : callback(std::move(cb)) {}
+ };
+
+ using PendingCloneID = uint64_t;
+
+ struct PendingClone {
+ size_t pending_flush_cnt = 0;
+ // This vector might not be populated all at once. Some buffers might be
+ // nullptr while flushing is not done.
+ std::vector<std::unique_ptr<TraceBuffer>> buffers;
+ bool flush_failed = false;
+ base::WeakPtr<ConsumerEndpointImpl> weak_consumer;
+ bool skip_trace_filter = false;
+ };
+
+ // Holds the state of a tracing session. A tracing session is uniquely bound
+ // a specific Consumer. Each Consumer can own one or more sessions.
+ struct TracingSession {
+ enum State {
+ DISABLED = 0,
+ CONFIGURED,
+ STARTED,
+ DISABLING_WAITING_STOP_ACKS,
+ CLONED_READ_ONLY,
+ };
+
+ TracingSession(TracingSessionID,
+ ConsumerEndpointImpl*,
+ const TraceConfig&,
+ base::TaskRunner*);
+ TracingSession(TracingSession&&) = delete;
+ TracingSession& operator=(TracingSession&&) = delete;
+
+ size_t num_buffers() const { return buffers_index.size(); }
+
+ uint32_t delay_to_next_write_period_ms() const {
+ PERFETTO_DCHECK(write_period_ms > 0);
+ return write_period_ms -
+ static_cast<uint32_t>(base::GetWallTimeMs().count() %
+ write_period_ms);
+ }
+
+ uint32_t flush_timeout_ms() {
+ uint32_t timeout_ms = config.flush_timeout_ms();
+ return timeout_ms ? timeout_ms : kDefaultFlushTimeoutMs;
+ }
+
+ uint32_t data_source_stop_timeout_ms() {
+ uint32_t timeout_ms = config.data_source_stop_timeout_ms();
+ return timeout_ms ? timeout_ms : kDataSourceStopTimeoutMs;
+ }
+
+ PacketSequenceID GetPacketSequenceID(MachineID machine_id,
+ ProducerID producer_id,
+ WriterID writer_id) {
+ auto key = std::make_tuple(machine_id, producer_id, writer_id);
+ auto it = packet_sequence_ids.find(key);
+ if (it != packet_sequence_ids.end())
+ return it->second;
+ // We shouldn't run out of sequence IDs (producer ID is 16 bit, writer IDs
+ // are limited to 1024).
+ static_assert(kMaxPacketSequenceID > kMaxProducerID * kMaxWriterID,
+ "PacketSequenceID value space doesn't cover service "
+ "sequence ID and all producer/writer ID combinations!");
+ PERFETTO_DCHECK(last_packet_sequence_id < kMaxPacketSequenceID);
+ PacketSequenceID sequence_id = ++last_packet_sequence_id;
+ packet_sequence_ids[key] = sequence_id;
+ return sequence_id;
+ }
+
+ DataSourceInstance* GetDataSourceInstance(
+ ProducerID producer_id,
+ DataSourceInstanceID instance_id) {
+ for (auto& inst_kv : data_source_instances) {
+ if (inst_kv.first != producer_id ||
+ inst_kv.second.instance_id != instance_id) {
+ continue;
+ }
+ return &inst_kv.second;
+ }
+ return nullptr;
+ }
+
+ bool AllDataSourceInstancesStarted() {
+ return std::all_of(
+ data_source_instances.begin(), data_source_instances.end(),
+ [](decltype(data_source_instances)::const_reference x) {
+ return x.second.state == DataSourceInstance::STARTED;
+ });
+ }
+
+ bool AllDataSourceInstancesStopped() {
+ return std::all_of(
+ data_source_instances.begin(), data_source_instances.end(),
+ [](decltype(data_source_instances)::const_reference x) {
+ return x.second.state == DataSourceInstance::STOPPED;
+ });
+ }
+
+ // Checks whether |clone_uid| is allowed to clone the current tracing
+ // session.
+ bool IsCloneAllowed(uid_t clone_uid) const;
+
+ const TracingSessionID id;
+
+ // The consumer that started the session.
+ // Can be nullptr if the consumer detached from the session.
+ ConsumerEndpointImpl* consumer_maybe_null;
+
+ // Unix uid of the consumer. This is valid even after the consumer detaches
+ // and does not change for the entire duration of the session. It is used to
+ // prevent that a consumer re-attaches to a session from a different uid.
+ uid_t const consumer_uid;
+
+ // The list of triggers this session received while alive and the time they
+ // were received at. This is used to insert 'fake' packets back to the
+ // consumer so they can tell when some event happened. The order matches the
+ // order they were received.
+ struct TriggerInfo {
+ uint64_t boot_time_ns;
+ std::string trigger_name;
+ std::string producer_name;
+ uid_t producer_uid;
+ };
+ std::vector<TriggerInfo> received_triggers;
+
+ // The trace config provided by the Consumer when calling
+ // EnableTracing(), plus any updates performed by ChangeTraceConfig.
+ TraceConfig config;
+
+ // List of data source instances that have been enabled on the various
+ // producers for this tracing session.
+ std::multimap<ProducerID, DataSourceInstance> data_source_instances;
+
+ // For each Flush(N) request, keeps track of the set of producers for which
+ // we are still awaiting a NotifyFlushComplete(N) ack.
+ std::map<FlushRequestID, PendingFlush> pending_flushes;
+
+ // For each Clone request, keeps track of the flushes acknowledgement that
+ // we are still waiting for.
+ std::map<PendingCloneID, PendingClone> pending_clones;
+
+ PendingCloneID last_pending_clone_id_ = 0;
+
+ // Maps a per-trace-session buffer index into the corresponding global
+ // BufferID (shared namespace amongst all consumers). This vector has as
+ // many entries as |config.buffers_size()|.
+ std::vector<BufferID> buffers_index;
+
+ std::map<std::tuple<MachineID, ProducerID, WriterID>, PacketSequenceID>
+ packet_sequence_ids;
+ PacketSequenceID last_packet_sequence_id = kServicePacketSequenceID;
+
+ // Whether we should emit the trace stats next time we reach EOF while
+ // performing ReadBuffers.
+ bool should_emit_stats = false;
+
+ // Whether we should emit the sync marker the next time ReadBuffers() is
+ // called.
+ bool should_emit_sync_marker = false;
+
+ // Whether we put the initial packets (trace config, system info,
+ // etc.) into the trace output yet.
+ bool did_emit_initial_packets = false;
+
+ // Whether we emitted clock offsets for relay clients yet.
+ bool did_emit_remote_clock_sync_ = false;
+
+ // Whether we should compress TracePackets after reading them.
+ bool compress_deflate = false;
+
+ // The number of received triggers we've emitted into the trace output.
+ size_t num_triggers_emitted_into_trace = 0;
+
+ // Packets that failed validation of the TrustedPacket.
+ uint64_t invalid_packets = 0;
+
+ // Flush() stats. See comments in trace_stats.proto for more.
+ uint64_t flushes_requested = 0;
+ uint64_t flushes_succeeded = 0;
+ uint64_t flushes_failed = 0;
+
+ // Outcome of the final Flush() done by FlushAndDisableTracing().
+ protos::gen::TraceStats_FinalFlushOutcome final_flush_outcome{};
+
+ // Set to true on the first call to MaybeNotifyAllDataSourcesStarted().
+ bool did_notify_all_data_source_started = false;
+
+ // Stores all lifecycle events of a particular type (i.e. associated with a
+ // single field id in the TracingServiceEvent proto).
+ struct LifecycleEvent {
+ LifecycleEvent(uint32_t f_id, uint32_t m_size = 1)
+ : field_id(f_id), max_size(m_size), timestamps(m_size) {}
+
+ // The field id of the event in the TracingServiceEvent proto.
+ uint32_t field_id;
+
+ // Stores the max size of |timestamps|. Set to 1 by default (in
+ // the constructor) but can be overriden in TraceSession constructor
+ // if a larger size is required.
+ uint32_t max_size;
+
+ // Stores the timestamps emitted for each event type (in nanoseconds).
+ // Emitted into the trace and cleared when the consumer next calls
+ // ReadBuffers.
+ base::CircularQueue<int64_t> timestamps;
+ };
+ std::vector<LifecycleEvent> lifecycle_events;
+
+ using ClockSnapshotData = ClockSnapshotVector;
+
+ // Initial clock snapshot, captured at trace start time (when state goes to
+ // TracingSession::STARTED). Emitted into the trace when the consumer first
+ // calls ReadBuffers().
+ ClockSnapshotData initial_clock_snapshot;
+
+ // Stores clock snapshots to emit into the trace as a ring buffer. This
+ // buffer is populated both periodically and when lifecycle events happen
+ // but only when significant clock drift is detected. Emitted into the trace
+ // and cleared when the consumer next calls ReadBuffers().
+ base::CircularQueue<ClockSnapshotData> clock_snapshot_ring_buffer;
+
+ State state = DISABLED;
+
+ // If the consumer detached the session, this variable defines the key used
+ // for identifying the session later when reattaching.
+ std::string detach_key;
+
+ // This is set when the Consumer calls sets |write_into_file| == true in the
+ // TraceConfig. In this case this represents the file we should stream the
+ // trace packets into, rather than returning it to the consumer via
+ // OnTraceData().
+ base::ScopedFile write_into_file;
+ uint32_t write_period_ms = 0;
+ uint64_t max_file_size_bytes = 0;
+ uint64_t bytes_written_into_file = 0;
+
+ // Periodic task for snapshotting service events (e.g. clocks, sync markers
+ // etc)
+ base::PeriodicTask snapshot_periodic_task;
+
+ // Deferred task that stops the trace when |duration_ms| expires. This is
+ // to handle the case of |prefer_suspend_clock_for_duration| which cannot
+ // use PostDelayedTask.
+ base::PeriodicTask timed_stop_task;
+
+ // When non-NULL the packets should be post-processed using the filter.
+ std::unique_ptr<protozero::MessageFilter> trace_filter;
+ uint64_t filter_input_packets = 0;
+ uint64_t filter_input_bytes = 0;
+ uint64_t filter_output_bytes = 0;
+ uint64_t filter_errors = 0;
+ uint64_t filter_time_taken_ns = 0;
+ std::vector<uint64_t> filter_bytes_discarded_per_buffer;
+
+ // A randomly generated trace identifier. Note that this does NOT always
+ // match the requested TraceConfig.trace_uuid_msb/lsb. Spcifically, it does
+ // until a gap-less snapshot is requested. Each snapshot re-generates the
+ // uuid to avoid emitting two different traces with the same uuid.
+ base::Uuid trace_uuid;
+
+ // NOTE: when adding new fields here consider whether that state should be
+ // copied over in DoCloneSession() or not. Ask yourself: is this a
+ // "runtime state" (e.g. active data sources) or a "trace (meta)data state"?
+ // If the latter, it should be handled by DoCloneSession()).
+ };
+
+ TracingServiceImpl(const TracingServiceImpl&) = delete;
+ TracingServiceImpl& operator=(const TracingServiceImpl&) = delete;
+
+ DataSourceInstance* SetupDataSource(const TraceConfig::DataSource&,
+ const TraceConfig::ProducerConfig&,
+ const RegisteredDataSource&,
+ TracingSession*);
+
+ // Returns the next available ProducerID that is not in |producers_|.
+ ProducerID GetNextProducerID();
+
+ // Returns a pointer to the |tracing_sessions_| entry or nullptr if the
+ // session doesn't exists.
+ TracingSession* GetTracingSession(TracingSessionID);
+
+ // Returns a pointer to the tracing session that has the highest
+ // TraceConfig.bugreport_score, if any, or nullptr.
+ TracingSession* FindTracingSessionWithMaxBugreportScore();
+
+ // Returns a pointer to the |tracing_sessions_| entry, matching the given
+ // uid and detach key, or nullptr if no such session exists.
+ TracingSession* GetDetachedSession(uid_t, const std::string& key);
+
+ // Update the memory guard rail by using the latest information from the
+ // shared memory and trace buffers.
+ void UpdateMemoryGuardrail();
+
+ void StartDataSourceInstance(ProducerEndpointImpl*,
+ TracingSession*,
+ DataSourceInstance*);
+ void StopDataSourceInstance(ProducerEndpointImpl*,
+ TracingSession*,
+ DataSourceInstance*,
+ bool disable_immediately);
+ void PeriodicSnapshotTask(TracingSessionID);
+ void MaybeSnapshotClocksIntoRingBuffer(TracingSession*);
+ bool SnapshotClocks(TracingSession::ClockSnapshotData*);
+ void SnapshotLifecyleEvent(TracingSession*,
+ uint32_t field_id,
+ bool snapshot_clocks);
+ void EmitClockSnapshot(TracingSession*,
+ TracingSession::ClockSnapshotData,
+ std::vector<TracePacket>*);
+ void EmitSyncMarker(std::vector<TracePacket>*);
+ void EmitStats(TracingSession*, std::vector<TracePacket>*);
+ TraceStats GetTraceStats(TracingSession*);
+ void EmitLifecycleEvents(TracingSession*, std::vector<TracePacket>*);
+ void EmitUuid(TracingSession*, std::vector<TracePacket>*);
+ void MaybeEmitTraceConfig(TracingSession*, std::vector<TracePacket>*);
+ void EmitSystemInfo(std::vector<TracePacket>*);
+ void MaybeEmitReceivedTriggers(TracingSession*, std::vector<TracePacket>*);
+ void MaybeEmitRemoteClockSync(TracingSession*, std::vector<TracePacket>*);
+ void MaybeNotifyAllDataSourcesStarted(TracingSession*);
+ void OnFlushTimeout(TracingSessionID, FlushRequestID);
+ void OnDisableTracingTimeout(TracingSessionID);
+ void DisableTracingNotifyConsumerAndFlushFile(TracingSession*);
+ void PeriodicFlushTask(TracingSessionID, bool post_next_only);
+ void CompleteFlush(TracingSessionID tsid,
+ ConsumerEndpoint::FlushCallback callback,
+ bool success);
+ void ScrapeSharedMemoryBuffers(TracingSession*, ProducerEndpointImpl*);
+ void PeriodicClearIncrementalStateTask(TracingSessionID, bool post_next_only);
+ TraceBuffer* GetBufferByID(BufferID);
+ void FlushDataSourceInstances(
+ TracingSession*,
+ uint32_t timeout_ms,
+ const std::map<ProducerID, std::vector<DataSourceInstanceID>>&,
+ ConsumerEndpoint::FlushCallback,
+ FlushFlags);
+ std::map<ProducerID, std::vector<DataSourceInstanceID>>
+ GetFlushableDataSourceInstancesForBuffers(TracingSession*,
+ const std::set<BufferID>&);
+ bool DoCloneBuffers(TracingSession*,
+ const std::set<BufferID>&,
+ std::vector<std::unique_ptr<TraceBuffer>>*);
+ base::Status FinishCloneSession(ConsumerEndpointImpl*,
+ TracingSessionID,
+ std::vector<std::unique_ptr<TraceBuffer>>,
+ bool skip_filter,
+ bool final_flush_outcome,
+ base::Uuid*);
+ void OnFlushDoneForClone(TracingSessionID src_tsid,
+ PendingCloneID clone_id,
+ const std::set<BufferID>& buf_ids,
+ bool final_flush_outcome);
+
+ // Returns true if `*tracing_session` is waiting for a trigger that hasn't
+ // happened.
+ static bool IsWaitingForTrigger(TracingSession* tracing_session);
+
+ // Reads the buffers from `*tracing_session` and returns them (along with some
+ // metadata packets).
+ //
+ // The function stops when the cumulative size of the return packets exceeds
+ // `threshold` (so it's not a strict upper bound) and sets `*has_more` to
+ // true, or when there are no more packets (and sets `*has_more` to false).
+ std::vector<TracePacket> ReadBuffers(TracingSession* tracing_session,
+ size_t threshold,
+ bool* has_more);
+
+ // If `*tracing_session` has a filter, applies it to `*packets`. Doesn't
+ // change the number of `*packets`, only their content.
+ void MaybeFilterPackets(TracingSession* tracing_session,
+ std::vector<TracePacket>* packets);
+
+ // If `*tracing_session` has compression enabled, compress `*packets`.
+ void MaybeCompressPackets(TracingSession* tracing_session,
+ std::vector<TracePacket>* packets);
+
+ // If `*tracing_session` is configured to write into a file, writes `packets`
+ // into the file.
+ //
+ // Returns true if the file should be closed (because it's full or there has
+ // been an error), false otherwise.
+ bool WriteIntoFile(TracingSession* tracing_session,
+ std::vector<TracePacket> packets);
+ void OnStartTriggersTimeout(TracingSessionID tsid);
+ void MaybeLogUploadEvent(const TraceConfig&,
+ const base::Uuid&,
+ PerfettoStatsdAtom atom,
+ const std::string& trigger_name = "");
+ void MaybeLogTriggerEvent(const TraceConfig&,
+ PerfettoTriggerAtom atom,
+ const std::string& trigger_name);
+ size_t PurgeExpiredAndCountTriggerInWindow(int64_t now_ns,
+ uint64_t trigger_name_hash);
+ static void StopOnDurationMsExpiry(base::WeakPtr<TracingServiceImpl>,
+ TracingSessionID);
+
+ base::TaskRunner* const task_runner_;
+ const InitOpts init_opts_;
+ std::unique_ptr<SharedMemory::Factory> shm_factory_;
+ ProducerID last_producer_id_ = 0;
+ DataSourceInstanceID last_data_source_instance_id_ = 0;
+ TracingSessionID last_tracing_session_id_ = 0;
+ FlushRequestID last_flush_request_id_ = 0;
+ uid_t uid_ = 0;
+
+ // Buffer IDs are global across all consumers (because a Producer can produce
+ // data for more than one trace session, hence more than one consumer).
+ IdAllocator<BufferID> buffer_ids_;
+
+ std::multimap<std::string /*name*/, RegisteredDataSource> data_sources_;
+ std::map<ProducerID, ProducerEndpointImpl*> producers_;
+ std::set<ConsumerEndpointImpl*> consumers_;
+ std::map<RelayClientID, RelayEndpointImpl*> relay_clients_;
+ std::map<TracingSessionID, TracingSession> tracing_sessions_;
+ std::map<BufferID, std::unique_ptr<TraceBuffer>> buffers_;
+ std::map<std::string, int64_t> session_to_last_trace_s_;
+
+ // Contains timestamps of triggers.
+ // The queue is sorted by timestamp and invocations older than
+ // |trigger_window_ns_| are purged when a trigger happens.
+ base::CircularQueue<TriggerHistory> trigger_history_;
+
+ bool smb_scraping_enabled_ = false;
+ bool lockdown_mode_ = false;
+ uint32_t min_write_period_ms_ = 100; // Overridable for testing.
+ int64_t trigger_window_ns_ = kOneDayInNs; // Overridable for testing.
+
+ std::minstd_rand trigger_probability_rand_;
+ std::uniform_real_distribution<> trigger_probability_dist_;
+ double trigger_rnd_override_for_testing_ = 0; // Overridable for testing.
+
+ uint8_t sync_marker_packet_[32]; // Lazily initialized.
+ size_t sync_marker_packet_size_ = 0;
+
+ // Stats.
+ uint64_t chunks_discarded_ = 0;
+ uint64_t patches_discarded_ = 0;
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+
+ base::WeakPtrFactory<TracingServiceImpl>
+ weak_ptr_factory_; // Keep at the end.
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_SERVICE_TRACING_SERVICE_IMPL_H_
+// gen_amalgamated begin header: include/perfetto/tracing/core/tracing_service_capabilities.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_CAPABILITIES_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_CAPABILITIES_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_capabilities.gen.h"
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_CAPABILITIES_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/service/tracing_service_impl.h"
+
+#include <limits.h>
+#include <string.h>
+
+#include <cinttypes>
+#include <cstdint>
+#include <limits>
+#include <optional>
+#include <regex>
+#include <unordered_set>
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/client_identity.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/clock_snapshots.h"
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+#include <sys/uio.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+ PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+// gen_amalgamated expanded: #include "src/android_internal/lazy_library_loader.h" // nogncheck
+// gen_amalgamated expanded: #include "src/android_internal/tracing_service_proxy.h" // nogncheck
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#define PERFETTO_HAS_CHMOD
+#include <sys/stat.h>
+#endif
+
+#include <algorithm>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/status.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/android_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/metatrace.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/uuid.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/version.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/watchdog.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/consumer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/observable_events.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/producer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_packet.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/static_buffer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/tracing_service_capabilities.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/tracing_service_state.h"
+// gen_amalgamated expanded: #include "src/android_stats/statsd_logging_helper.h"
+// gen_amalgamated expanded: #include "src/protozero/filtering/message_filter.h"
+// gen_amalgamated expanded: #include "src/protozero/filtering/string_filter.h"
+// gen_amalgamated expanded: #include "src/tracing/core/shared_memory_arbiter_impl.h"
+// gen_amalgamated expanded: #include "src/tracing/service/packet_stream_validator.h"
+// gen_amalgamated expanded: #include "src/tracing/service/trace_buffer.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/trace_stats.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/remote_clock_sync.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/system_info.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_uuid.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trigger.pbzero.h"
+
+// General note: this class must assume that Producers are malicious and will
+// try to crash / exploit this class. We can trust pointers because they come
+// from the IPC layer, but we should never assume that that the producer calls
+// come in the right order or their arguments are sane / within bounds.
+
+// This is a macro because we want the call-site line number for the ELOG.
+#define PERFETTO_SVC_ERR(...) \
+ (PERFETTO_ELOG(__VA_ARGS__), ::perfetto::base::ErrStatus(__VA_ARGS__))
+
+namespace perfetto {
+
+namespace {
+constexpr int kMaxBuffersPerConsumer = 128;
+constexpr uint32_t kDefaultSnapshotsIntervalMs = 10 * 1000;
+constexpr int kDefaultWriteIntoFilePeriodMs = 5000;
+constexpr int kMaxConcurrentTracingSessions = 15;
+constexpr int kMaxConcurrentTracingSessionsPerUid = 5;
+constexpr int kMaxConcurrentTracingSessionsForStatsdUid = 10;
+constexpr int64_t kMinSecondsBetweenTracesGuardrail = 5 * 60;
+
+constexpr uint32_t kMillisPerHour = 3600000;
+constexpr uint32_t kMillisPerDay = kMillisPerHour * 24;
+constexpr uint32_t kMaxTracingDurationMillis = 7 * 24 * kMillisPerHour;
+
+// These apply only if enable_extra_guardrails is true.
+constexpr uint32_t kGuardrailsMaxTracingBufferSizeKb = 128 * 1024;
+constexpr uint32_t kGuardrailsMaxTracingDurationMillis = 24 * kMillisPerHour;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+struct iovec {
+ void* iov_base; // Address
+ size_t iov_len; // Block size
+};
+
+// Simple implementation of writev. Note that this does not give the atomicity
+// guarantees of a real writev, but we don't depend on these (we aren't writing
+// to the same file from another thread).
+ssize_t writev(int fd, const struct iovec* iov, int iovcnt) {
+ ssize_t total_size = 0;
+ for (int i = 0; i < iovcnt; ++i) {
+ ssize_t current_size = base::WriteAll(fd, iov[i].iov_base, iov[i].iov_len);
+ if (current_size != static_cast<ssize_t>(iov[i].iov_len))
+ return -1;
+ total_size += current_size;
+ }
+ return total_size;
+}
+
+#define IOV_MAX 1024 // Linux compatible limit.
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
+ // PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+
+// Partially encodes a CommitDataRequest in an int32 for the purposes of
+// metatracing. Note that it encodes only the bottom 10 bits of the producer id
+// (which is technically 16 bits wide).
+//
+// Format (by bit range):
+// [ 31 ][ 30 ][ 29:20 ][ 19:10 ][ 9:0]
+// [unused][has flush id][num chunks to patch][num chunks to move][producer id]
+int32_t EncodeCommitDataRequest(ProducerID producer_id,
+ const CommitDataRequest& req_untrusted) {
+ uint32_t cmov = static_cast<uint32_t>(req_untrusted.chunks_to_move_size());
+ uint32_t cpatch = static_cast<uint32_t>(req_untrusted.chunks_to_patch_size());
+ uint32_t has_flush_id = req_untrusted.flush_request_id() != 0;
+
+ uint32_t mask = (1 << 10) - 1;
+ uint32_t acc = 0;
+ acc |= has_flush_id << 30;
+ acc |= (cpatch & mask) << 20;
+ acc |= (cmov & mask) << 10;
+ acc |= (producer_id & mask);
+ return static_cast<int32_t>(acc);
+}
+
+void SerializeAndAppendPacket(std::vector<TracePacket>* packets,
+ std::vector<uint8_t> packet) {
+ Slice slice = Slice::Allocate(packet.size());
+ memcpy(slice.own_data(), packet.data(), packet.size());
+ packets->emplace_back();
+ packets->back().AddSlice(std::move(slice));
+}
+
+std::tuple<size_t /*shm_size*/, size_t /*page_size*/> EnsureValidShmSizes(
+ size_t shm_size,
+ size_t page_size) {
+ // Theoretically the max page size supported by the ABI is 64KB.
+ // However, the current implementation of TraceBuffer (the non-shared
+ // userspace buffer where the service copies data) supports at most
+ // 32K. Setting 64K "works" from the producer<>consumer viewpoint
+ // but then causes the data to be discarded when copying it into
+ // TraceBuffer.
+ constexpr size_t kMaxPageSize = 32 * 1024;
+ static_assert(kMaxPageSize <= SharedMemoryABI::kMaxPageSize, "");
+
+ if (page_size == 0)
+ page_size = TracingServiceImpl::kDefaultShmPageSize;
+ if (shm_size == 0)
+ shm_size = TracingServiceImpl::kDefaultShmSize;
+
+ page_size = std::min<size_t>(page_size, kMaxPageSize);
+ shm_size = std::min<size_t>(shm_size, TracingServiceImpl::kMaxShmSize);
+
+ // The tracing page size has to be multiple of 4K. On some systems (e.g. Mac
+ // on Arm64) the system page size can be larger (e.g., 16K). That doesn't
+ // matter here, because the tracing page size is just a logical partitioning
+ // and does not have any dependencies on kernel mm syscalls (read: it's fine
+ // to have trace page sizes of 4K on a system where the kernel page size is
+ // 16K).
+ bool page_size_is_valid = page_size >= SharedMemoryABI::kMinPageSize;
+ page_size_is_valid &= page_size % SharedMemoryABI::kMinPageSize == 0;
+
+ // Only allow power of two numbers of pages, i.e. 1, 2, 4, 8 pages.
+ size_t num_pages = page_size / SharedMemoryABI::kMinPageSize;
+ page_size_is_valid &= (num_pages & (num_pages - 1)) == 0;
+
+ if (!page_size_is_valid || shm_size < page_size ||
+ shm_size % page_size != 0) {
+ return std::make_tuple(TracingServiceImpl::kDefaultShmSize,
+ TracingServiceImpl::kDefaultShmPageSize);
+ }
+ return std::make_tuple(shm_size, page_size);
+}
+
+bool NameMatchesFilter(const std::string& name,
+ const std::vector<std::string>& name_filter,
+ const std::vector<std::string>& name_regex_filter) {
+ bool filter_is_set = !name_filter.empty() || !name_regex_filter.empty();
+ if (!filter_is_set)
+ return true;
+ bool filter_matches = std::find(name_filter.begin(), name_filter.end(),
+ name) != name_filter.end();
+ bool filter_regex_matches =
+ std::find_if(name_regex_filter.begin(), name_regex_filter.end(),
+ [&](const std::string& regex) {
+ return std::regex_match(
+ name, std::regex(regex, std::regex::extended));
+ }) != name_regex_filter.end();
+ return filter_matches || filter_regex_matches;
+}
+
+// Used when TraceConfig.write_into_file == true and output_path is not empty.
+base::ScopedFile CreateTraceFile(const std::string& path, bool overwrite) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+ PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+ // This is NOT trying to preserve any security property, SELinux does that.
+ // It just improves the actionability of the error when people try to save the
+ // trace in a location that is not SELinux-allowed (a generic "permission
+ // denied" vs "don't put it here, put it there").
+ // These are the only SELinux approved dir for trace files that are created
+ // directly by traced.
+ static const char* kTraceDirBasePath = "/data/misc/perfetto-traces/";
+ if (!base::StartsWith(path, kTraceDirBasePath)) {
+ PERFETTO_ELOG("Invalid output_path %s. On Android it must be within %s.",
+ path.c_str(), kTraceDirBasePath);
+ return base::ScopedFile();
+ }
+#endif
+ // O_CREAT | O_EXCL will fail if the file exists already.
+ const int flags = O_RDWR | O_CREAT | (overwrite ? O_TRUNC : O_EXCL);
+ auto fd = base::OpenFile(path, flags, 0600);
+ if (fd) {
+#if defined(PERFETTO_HAS_CHMOD)
+ // Passing 0644 directly above won't work because of umask.
+ PERFETTO_CHECK(fchmod(*fd, 0644) == 0);
+#endif
+ } else {
+ PERFETTO_PLOG("Failed to create %s", path.c_str());
+ }
+ return fd;
+}
+
+bool ShouldLogEvent(const TraceConfig& cfg) {
+ switch (cfg.statsd_logging()) {
+ case TraceConfig::STATSD_LOGGING_ENABLED:
+ return true;
+ case TraceConfig::STATSD_LOGGING_DISABLED:
+ return false;
+ case TraceConfig::STATSD_LOGGING_UNSPECIFIED:
+ break;
+ }
+ // For backward compatibility with older versions of perfetto_cmd.
+ return cfg.enable_extra_guardrails();
+}
+
+// Appends `data` (which has `size` bytes), to `*packet`. Splits the data in
+// slices no larger than `max_slice_size`.
+void AppendOwnedSlicesToPacket(std::unique_ptr<uint8_t[]> data,
+ size_t size,
+ size_t max_slice_size,
+ perfetto::TracePacket* packet) {
+ if (size <= max_slice_size) {
+ packet->AddSlice(Slice::TakeOwnership(std::move(data), size));
+ return;
+ }
+ uint8_t* src_ptr = data.get();
+ for (size_t size_left = size; size_left > 0;) {
+ const size_t slice_size = std::min(size_left, max_slice_size);
+
+ Slice slice = Slice::Allocate(slice_size);
+ memcpy(slice.own_data(), src_ptr, slice_size);
+ packet->AddSlice(std::move(slice));
+
+ src_ptr += slice_size;
+ size_left -= slice_size;
+ }
+}
+
+using TraceFilter = protos::gen::TraceConfig::TraceFilter;
+std::optional<protozero::StringFilter::Policy> ConvertPolicy(
+ TraceFilter::StringFilterPolicy policy) {
+ switch (policy) {
+ case TraceFilter::SFP_UNSPECIFIED:
+ return std::nullopt;
+ case TraceFilter::SFP_MATCH_REDACT_GROUPS:
+ return protozero::StringFilter::Policy::kMatchRedactGroups;
+ case TraceFilter::SFP_ATRACE_MATCH_REDACT_GROUPS:
+ return protozero::StringFilter::Policy::kAtraceMatchRedactGroups;
+ case TraceFilter::SFP_MATCH_BREAK:
+ return protozero::StringFilter::Policy::kMatchBreak;
+ case TraceFilter::SFP_ATRACE_MATCH_BREAK:
+ return protozero::StringFilter::Policy::kAtraceMatchBreak;
+ case TraceFilter::SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS:
+ return protozero::StringFilter::Policy::kAtraceRepeatedSearchRedactGroups;
+ }
+ return std::nullopt;
+}
+
+} // namespace
+
+// static
+std::unique_ptr<TracingService> TracingService::CreateInstance(
+ std::unique_ptr<SharedMemory::Factory> shm_factory,
+ base::TaskRunner* task_runner,
+ InitOpts init_opts) {
+ return std::unique_ptr<TracingService>(
+ new TracingServiceImpl(std::move(shm_factory), task_runner, init_opts));
+}
+
+TracingServiceImpl::TracingServiceImpl(
+ std::unique_ptr<SharedMemory::Factory> shm_factory,
+ base::TaskRunner* task_runner,
+ InitOpts init_opts)
+ : task_runner_(task_runner),
+ init_opts_(init_opts),
+ shm_factory_(std::move(shm_factory)),
+ uid_(base::GetCurrentUserId()),
+ buffer_ids_(kMaxTraceBufferID),
+ trigger_probability_rand_(
+ static_cast<uint32_t>(base::GetWallTimeNs().count())),
+ weak_ptr_factory_(this) {
+ PERFETTO_DCHECK(task_runner_);
+}
+
+TracingServiceImpl::~TracingServiceImpl() {
+ // TODO(fmayer): handle teardown of all Producer.
+}
+
+std::unique_ptr<TracingService::ProducerEndpoint>
+TracingServiceImpl::ConnectProducer(Producer* producer,
+ const ClientIdentity& client_identity,
+ const std::string& producer_name,
+ size_t shared_memory_size_hint_bytes,
+ bool in_process,
+ ProducerSMBScrapingMode smb_scraping_mode,
+ size_t shared_memory_page_size_hint_bytes,
+ std::unique_ptr<SharedMemory> shm,
+ const std::string& sdk_version) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto uid = client_identity.uid();
+ if (lockdown_mode_ && uid != base::GetCurrentUserId()) {
+ PERFETTO_DLOG("Lockdown mode. Rejecting producer with UID %ld",
+ static_cast<unsigned long>(uid));
+ return nullptr;
+ }
+
+ if (producers_.size() >= kMaxProducerID) {
+ PERFETTO_DFATAL("Too many producers.");
+ return nullptr;
+ }
+ const ProducerID id = GetNextProducerID();
+ PERFETTO_DLOG("Producer %" PRIu16 " connected, uid=%d", id,
+ static_cast<int>(uid));
+ bool smb_scraping_enabled = smb_scraping_enabled_;
+ switch (smb_scraping_mode) {
+ case ProducerSMBScrapingMode::kDefault:
+ break;
+ case ProducerSMBScrapingMode::kEnabled:
+ smb_scraping_enabled = true;
+ break;
+ case ProducerSMBScrapingMode::kDisabled:
+ smb_scraping_enabled = false;
+ break;
+ }
+
+ std::unique_ptr<ProducerEndpointImpl> endpoint(new ProducerEndpointImpl(
+ id, client_identity, this, task_runner_, producer, producer_name,
+ sdk_version, in_process, smb_scraping_enabled));
+ auto it_and_inserted = producers_.emplace(id, endpoint.get());
+ PERFETTO_DCHECK(it_and_inserted.second);
+ endpoint->shmem_size_hint_bytes_ = shared_memory_size_hint_bytes;
+ endpoint->shmem_page_size_hint_bytes_ = shared_memory_page_size_hint_bytes;
+
+ // Producer::OnConnect() should run before Producer::OnTracingSetup(). The
+ // latter may be posted by SetupSharedMemory() below, so post OnConnect() now.
+ auto weak_ptr = endpoint->weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_ptr] {
+ if (weak_ptr)
+ weak_ptr->producer_->OnConnect();
+ });
+
+ if (shm) {
+ // The producer supplied an SMB. This is used only by Chrome; in the most
+ // common cases the SMB is created by the service and passed via
+ // OnTracingSetup(). Verify that it is correctly sized before we attempt to
+ // use it. The transport layer has to verify the integrity of the SMB (e.g.
+ // ensure that the producer can't resize if after the fact).
+ size_t shm_size, page_size;
+ std::tie(shm_size, page_size) =
+ EnsureValidShmSizes(shm->size(), endpoint->shmem_page_size_hint_bytes_);
+ if (shm_size == shm->size() &&
+ page_size == endpoint->shmem_page_size_hint_bytes_) {
+ PERFETTO_DLOG(
+ "Adopting producer-provided SMB of %zu kB for producer \"%s\"",
+ shm_size / 1024, endpoint->name_.c_str());
+ endpoint->SetupSharedMemory(std::move(shm), page_size,
+ /*provided_by_producer=*/true);
+ } else {
+ PERFETTO_LOG(
+ "Discarding incorrectly sized producer-provided SMB for producer "
+ "\"%s\", falling back to service-provided SMB. Requested sizes: %zu "
+ "B total, %zu B page size; suggested corrected sizes: %zu B total, "
+ "%zu B page size",
+ endpoint->name_.c_str(), shm->size(),
+ endpoint->shmem_page_size_hint_bytes_, shm_size, page_size);
+ shm.reset();
+ }
+ }
+
+ return std::unique_ptr<ProducerEndpoint>(std::move(endpoint));
+}
+
+void TracingServiceImpl::DisconnectProducer(ProducerID id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Producer %" PRIu16 " disconnected", id);
+ PERFETTO_DCHECK(producers_.count(id));
+
+ // Scrape remaining chunks for this producer to ensure we don't lose data.
+ if (auto* producer = GetProducer(id)) {
+ for (auto& session_id_and_session : tracing_sessions_)
+ ScrapeSharedMemoryBuffers(&session_id_and_session.second, producer);
+ }
+
+ for (auto it = data_sources_.begin(); it != data_sources_.end();) {
+ auto next = it;
+ next++;
+ if (it->second.producer_id == id)
+ UnregisterDataSource(id, it->second.descriptor.name());
+ it = next;
+ }
+
+ producers_.erase(id);
+ UpdateMemoryGuardrail();
+}
+
+TracingServiceImpl::ProducerEndpointImpl* TracingServiceImpl::GetProducer(
+ ProducerID id) const {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto it = producers_.find(id);
+ if (it == producers_.end())
+ return nullptr;
+ return it->second;
+}
+
+std::unique_ptr<TracingService::ConsumerEndpoint>
+TracingServiceImpl::ConnectConsumer(Consumer* consumer, uid_t uid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Consumer %p connected from UID %" PRIu64,
+ reinterpret_cast<void*>(consumer), static_cast<uint64_t>(uid));
+ std::unique_ptr<ConsumerEndpointImpl> endpoint(
+ new ConsumerEndpointImpl(this, task_runner_, consumer, uid));
+ auto it_and_inserted = consumers_.emplace(endpoint.get());
+ PERFETTO_DCHECK(it_and_inserted.second);
+ // Consumer might go away before we're able to send the connect notification,
+ // if that is the case just bail out.
+ auto weak_ptr = endpoint->weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_ptr] {
+ if (weak_ptr)
+ weak_ptr->consumer_->OnConnect();
+ });
+ return std::unique_ptr<ConsumerEndpoint>(std::move(endpoint));
+}
+
+void TracingServiceImpl::DisconnectConsumer(ConsumerEndpointImpl* consumer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Consumer %p disconnected", reinterpret_cast<void*>(consumer));
+ PERFETTO_DCHECK(consumers_.count(consumer));
+
+ // TODO(primiano) : Check that this is safe (what happens if there are
+ // ReadBuffers() calls posted in the meantime? They need to become noop).
+ if (consumer->tracing_session_id_)
+ FreeBuffers(consumer->tracing_session_id_); // Will also DisableTracing().
+ consumers_.erase(consumer);
+
+ // At this point no more pointers to |consumer| should be around.
+ PERFETTO_DCHECK(!std::any_of(
+ tracing_sessions_.begin(), tracing_sessions_.end(),
+ [consumer](const std::pair<const TracingSessionID, TracingSession>& kv) {
+ return kv.second.consumer_maybe_null == consumer;
+ }));
+}
+
+bool TracingServiceImpl::DetachConsumer(ConsumerEndpointImpl* consumer,
+ const std::string& key) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Consumer %p detached", reinterpret_cast<void*>(consumer));
+ PERFETTO_DCHECK(consumers_.count(consumer));
+
+ TracingSessionID tsid = consumer->tracing_session_id_;
+ TracingSession* tracing_session;
+ if (!tsid || !(tracing_session = GetTracingSession(tsid)))
+ return false;
+
+ if (GetDetachedSession(consumer->uid_, key)) {
+ PERFETTO_ELOG("Another session has been detached with the same key \"%s\"",
+ key.c_str());
+ return false;
+ }
+
+ PERFETTO_DCHECK(tracing_session->consumer_maybe_null == consumer);
+ tracing_session->consumer_maybe_null = nullptr;
+ tracing_session->detach_key = key;
+ consumer->tracing_session_id_ = 0;
+ return true;
+}
+
+std::unique_ptr<TracingService::RelayEndpoint>
+TracingServiceImpl::ConnectRelayClient(RelayClientID relay_client_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto endpoint = std::make_unique<RelayEndpointImpl>(relay_client_id, this);
+ relay_clients_[relay_client_id] = endpoint.get();
+
+ return std::move(endpoint);
+}
+
+void TracingServiceImpl::DisconnectRelayClient(RelayClientID relay_client_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ if (relay_clients_.find(relay_client_id) == relay_clients_.end())
+ return;
+ relay_clients_.erase(relay_client_id);
+}
+
+bool TracingServiceImpl::AttachConsumer(ConsumerEndpointImpl* consumer,
+ const std::string& key) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Consumer %p attaching to session %s",
+ reinterpret_cast<void*>(consumer), key.c_str());
+ PERFETTO_DCHECK(consumers_.count(consumer));
+
+ if (consumer->tracing_session_id_) {
+ PERFETTO_ELOG(
+ "Cannot reattach consumer to session %s"
+ " while it already attached tracing session ID %" PRIu64,
+ key.c_str(), consumer->tracing_session_id_);
+ return false;
+ }
+
+ auto* tracing_session = GetDetachedSession(consumer->uid_, key);
+ if (!tracing_session) {
+ PERFETTO_ELOG(
+ "Failed to attach consumer, session '%s' not found for uid %d",
+ key.c_str(), static_cast<int>(consumer->uid_));
+ return false;
+ }
+
+ consumer->tracing_session_id_ = tracing_session->id;
+ tracing_session->consumer_maybe_null = consumer;
+ tracing_session->detach_key.clear();
+ return true;
+}
+
+base::Status TracingServiceImpl::EnableTracing(ConsumerEndpointImpl* consumer,
+ const TraceConfig& cfg,
+ base::ScopedFile fd) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ // If the producer is specifying a UUID, respect that (at least for the first
+ // snapshot). Otherwise generate a new UUID.
+ base::Uuid uuid(cfg.trace_uuid_lsb(), cfg.trace_uuid_msb());
+ if (!uuid)
+ uuid = base::Uuidv4();
+
+ PERFETTO_DLOG("Enabling tracing for consumer %p, UUID: %s",
+ reinterpret_cast<void*>(consumer),
+ uuid.ToPrettyString().c_str());
+ MaybeLogUploadEvent(cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracing);
+ if (cfg.lockdown_mode() == TraceConfig::LOCKDOWN_SET)
+ lockdown_mode_ = true;
+ if (cfg.lockdown_mode() == TraceConfig::LOCKDOWN_CLEAR)
+ lockdown_mode_ = false;
+
+ // Scope |tracing_session| to this block to prevent accidental use of a null
+ // pointer later in this function.
+ {
+ TracingSession* tracing_session =
+ GetTracingSession(consumer->tracing_session_id_);
+ if (tracing_session) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingExistingTraceSession);
+ return PERFETTO_SVC_ERR(
+ "A Consumer is trying to EnableTracing() but another tracing "
+ "session is already active (forgot a call to FreeBuffers() ?)");
+ }
+ }
+
+ const uint32_t max_duration_ms = cfg.enable_extra_guardrails()
+ ? kGuardrailsMaxTracingDurationMillis
+ : kMaxTracingDurationMillis;
+ if (cfg.duration_ms() > max_duration_ms) {
+ MaybeLogUploadEvent(cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingTooLongTrace);
+ return PERFETTO_SVC_ERR("Requested too long trace (%" PRIu32
+ "ms > %" PRIu32 " ms)",
+ cfg.duration_ms(), max_duration_ms);
+ }
+
+ const bool has_trigger_config =
+ GetTriggerMode(cfg) != TraceConfig::TriggerConfig::UNSPECIFIED;
+ if (has_trigger_config &&
+ (cfg.trigger_config().trigger_timeout_ms() == 0 ||
+ cfg.trigger_config().trigger_timeout_ms() > max_duration_ms)) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingInvalidTriggerTimeout);
+ return PERFETTO_SVC_ERR(
+ "Traces with START_TRACING triggers must provide a positive "
+ "trigger_timeout_ms < 7 days (received %" PRIu32 "ms)",
+ cfg.trigger_config().trigger_timeout_ms());
+ }
+
+ // This check has been introduced in May 2023 after finding b/274931668.
+ if (static_cast<int>(cfg.trigger_config().trigger_mode()) >
+ TraceConfig::TriggerConfig::TriggerMode_MAX) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingInvalidTriggerMode);
+ return PERFETTO_SVC_ERR(
+ "The trace config specified an invalid trigger_mode");
+ }
+
+ if (cfg.trigger_config().use_clone_snapshot_if_available() &&
+ cfg.trigger_config().trigger_mode() !=
+ TraceConfig::TriggerConfig::STOP_TRACING) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingInvalidTriggerMode);
+ return PERFETTO_SVC_ERR(
+ "trigger_mode must be STOP_TRACING when "
+ "use_clone_snapshot_if_available=true");
+ }
+
+ if (has_trigger_config && cfg.duration_ms() != 0) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingDurationWithTrigger);
+ return PERFETTO_SVC_ERR(
+ "duration_ms was set, this must not be set for traces with triggers.");
+ }
+
+ for (char c : cfg.bugreport_filename()) {
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.')) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingInvalidBrFilename);
+ return PERFETTO_SVC_ERR(
+ "bugreport_filename contains invalid chars. Use [a-zA-Z0-9-_.]+");
+ }
+ }
+
+ if ((GetTriggerMode(cfg) == TraceConfig::TriggerConfig::STOP_TRACING ||
+ GetTriggerMode(cfg) == TraceConfig::TriggerConfig::CLONE_SNAPSHOT) &&
+ cfg.write_into_file()) {
+ // We don't support this usecase because there are subtle assumptions which
+ // break around TracingServiceEvents and windowed sorting (i.e. if we don't
+ // drain the events in ReadBuffersIntoFile because we are waiting for
+ // STOP_TRACING, we can end up queueing up a lot of TracingServiceEvents and
+ // emitting them wildy out of order breaking windowed sorting in trace
+ // processor).
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingStopTracingWriteIntoFile);
+ return PERFETTO_SVC_ERR(
+ "Specifying trigger mode STOP_TRACING/CLONE_SNAPSHOT and "
+ "write_into_file together is unsupported");
+ }
+
+ std::unordered_set<std::string> triggers;
+ for (const auto& trigger : cfg.trigger_config().triggers()) {
+ if (!triggers.insert(trigger.name()).second) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingDuplicateTriggerName);
+ return PERFETTO_SVC_ERR("Duplicate trigger name: %s",
+ trigger.name().c_str());
+ }
+ }
+
+ if (cfg.enable_extra_guardrails()) {
+ if (cfg.deferred_start()) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingInvalidDeferredStart);
+ return PERFETTO_SVC_ERR(
+ "deferred_start=true is not supported in unsupervised traces");
+ }
+ uint64_t buf_size_sum = 0;
+ for (const auto& buf : cfg.buffers()) {
+ if (buf.size_kb() % 4 != 0) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingInvalidBufferSize);
+ return PERFETTO_SVC_ERR(
+ "buffers.size_kb must be a multiple of 4, got %" PRIu32,
+ buf.size_kb());
+ }
+ buf_size_sum += buf.size_kb();
+ }
+
+ uint32_t max_tracing_buffer_size_kb =
+ std::max(kGuardrailsMaxTracingBufferSizeKb,
+ cfg.guardrail_overrides().max_tracing_buffer_size_kb());
+ if (buf_size_sum > max_tracing_buffer_size_kb) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingBufferSizeTooLarge);
+ return PERFETTO_SVC_ERR("Requested too large trace buffer (%" PRIu64
+ "kB > %" PRIu32 " kB)",
+ buf_size_sum, max_tracing_buffer_size_kb);
+ }
+ }
+
+ if (cfg.buffers_size() > kMaxBuffersPerConsumer) {
+ MaybeLogUploadEvent(cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingTooManyBuffers);
+ return PERFETTO_SVC_ERR("Too many buffers configured (%d)",
+ cfg.buffers_size());
+ }
+ // Check that the config specifies all buffers for its data sources. This
+ // is also checked in SetupDataSource, but it is simpler to return a proper
+ // error to the consumer from here (and there will be less state to undo).
+ for (const TraceConfig::DataSource& cfg_data_source : cfg.data_sources()) {
+ size_t num_buffers = static_cast<size_t>(cfg.buffers_size());
+ size_t target_buffer = cfg_data_source.config().target_buffer();
+ if (target_buffer >= num_buffers) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingOobTargetBuffer);
+ return PERFETTO_SVC_ERR(
+ "Data source \"%s\" specified an out of bounds target_buffer (%zu >= "
+ "%zu)",
+ cfg_data_source.config().name().c_str(), target_buffer, num_buffers);
+ }
+ }
+
+ if (!cfg.unique_session_name().empty()) {
+ const std::string& name = cfg.unique_session_name();
+ for (auto& kv : tracing_sessions_) {
+ if (kv.second.state == TracingSession::CLONED_READ_ONLY)
+ continue; // Don't consider cloned sessions in uniqueness checks.
+ if (kv.second.config.unique_session_name() == name) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingDuplicateSessionName);
+ static const char fmt[] =
+ "A trace with this unique session name (%s) already exists";
+ // This happens frequently, don't make it an "E"LOG.
+ PERFETTO_LOG(fmt, name.c_str());
+ return base::ErrStatus(fmt, name.c_str());
+ }
+ }
+ }
+
+ if (cfg.enable_extra_guardrails()) {
+ // unique_session_name can be empty
+ const std::string& name = cfg.unique_session_name();
+ int64_t now_s = base::GetBootTimeS().count();
+
+ // Remove any entries where the time limit has passed so this map doesn't
+ // grow indefinitely:
+ std::map<std::string, int64_t>& sessions = session_to_last_trace_s_;
+ for (auto it = sessions.cbegin(); it != sessions.cend();) {
+ if (now_s - it->second > kMinSecondsBetweenTracesGuardrail) {
+ it = sessions.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ int64_t& previous_s = session_to_last_trace_s_[name];
+ if (previous_s == 0) {
+ previous_s = now_s;
+ } else {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingSessionNameTooRecent);
+ return PERFETTO_SVC_ERR(
+ "A trace with unique session name \"%s\" began less than %" PRId64
+ "s ago (%" PRId64 "s)",
+ name.c_str(), kMinSecondsBetweenTracesGuardrail, now_s - previous_s);
+ }
+ }
+
+ const int sessions_for_uid = static_cast<int>(std::count_if(
+ tracing_sessions_.begin(), tracing_sessions_.end(),
+ [consumer](const decltype(tracing_sessions_)::value_type& s) {
+ return s.second.consumer_uid == consumer->uid_;
+ }));
+
+ int per_uid_limit = kMaxConcurrentTracingSessionsPerUid;
+ if (consumer->uid_ == 1066 /* AID_STATSD*/) {
+ per_uid_limit = kMaxConcurrentTracingSessionsForStatsdUid;
+ }
+ if (sessions_for_uid >= per_uid_limit) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingTooManySessionsForUid);
+ return PERFETTO_SVC_ERR(
+ "Too many concurrent tracing sesions (%d) for uid %d limit is %d",
+ sessions_for_uid, static_cast<int>(consumer->uid_), per_uid_limit);
+ }
+
+ // TODO(primiano): This is a workaround to prevent that a producer gets stuck
+ // in a state where it stalls by design by having more TraceWriterImpl
+ // instances than free pages in the buffer. This is really a bug in
+ // trace_probes and the way it handles stalls in the shmem buffer.
+ if (tracing_sessions_.size() >= kMaxConcurrentTracingSessions) {
+ MaybeLogUploadEvent(
+ cfg, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingTooManyConcurrentSessions);
+ return PERFETTO_SVC_ERR("Too many concurrent tracing sesions (%zu)",
+ tracing_sessions_.size());
+ }
+
+ // If the trace config provides a filter bytecode, setup the filter now.
+ // If the filter loading fails, abort the tracing session rather than running
+ // unfiltered.
+ std::unique_ptr<protozero::MessageFilter> trace_filter;
+ if (cfg.has_trace_filter()) {
+ const auto& filt = cfg.trace_filter();
+ trace_filter.reset(new protozero::MessageFilter());
+
+ protozero::StringFilter& string_filter = trace_filter->string_filter();
+ for (const auto& rule : filt.string_filter_chain().rules()) {
+ auto opt_policy = ConvertPolicy(rule.policy());
+ if (!opt_policy.has_value()) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingInvalidFilter);
+ return PERFETTO_SVC_ERR(
+ "Trace filter has invalid string filtering rules, aborting");
+ }
+ string_filter.AddRule(*opt_policy, rule.regex_pattern(),
+ rule.atrace_payload_starts_with());
+ }
+
+ const std::string& bytecode_v1 = filt.bytecode();
+ const std::string& bytecode_v2 = filt.bytecode_v2();
+ const std::string& bytecode =
+ bytecode_v2.empty() ? bytecode_v1 : bytecode_v2;
+ if (!trace_filter->LoadFilterBytecode(bytecode.data(), bytecode.size())) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingInvalidFilter);
+ return PERFETTO_SVC_ERR("Trace filter bytecode invalid, aborting");
+ }
+
+ // The filter is created using perfetto.protos.Trace as root message
+ // (because that makes it possible to play around with the `proto_filter`
+ // tool on actual traces). Here in the service, however, we deal with
+ // perfetto.protos.TracePacket(s), which are one level down (Trace.packet).
+ // The IPC client (or the write_into_filte logic in here) are responsible
+ // for pre-pending the packet preamble (See GetProtoPreamble() calls), but
+ // the preamble is not there at ReadBuffer time. Hence we change the root of
+ // the filtering to start at the Trace.packet level.
+ if (!trace_filter->SetFilterRoot({TracePacket::kPacketFieldNumber})) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingInvalidFilter);
+ return PERFETTO_SVC_ERR("Failed to set filter root.");
+ }
+ }
+
+ const TracingSessionID tsid = ++last_tracing_session_id_;
+ TracingSession* tracing_session =
+ &tracing_sessions_
+ .emplace(std::piecewise_construct, std::forward_as_tuple(tsid),
+ std::forward_as_tuple(tsid, consumer, cfg, task_runner_))
+ .first->second;
+
+ tracing_session->trace_uuid = uuid;
+
+ if (trace_filter)
+ tracing_session->trace_filter = std::move(trace_filter);
+
+ if (cfg.write_into_file()) {
+ if (!fd ^ !cfg.output_path().empty()) {
+ MaybeLogUploadEvent(
+ tracing_session->config, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingInvalidFdOutputFile);
+ tracing_sessions_.erase(tsid);
+ return PERFETTO_SVC_ERR(
+ "When write_into_file==true either a FD needs to be passed or "
+ "output_path must be populated (but not both)");
+ }
+ if (!cfg.output_path().empty()) {
+ fd = CreateTraceFile(cfg.output_path(), /*overwrite=*/false);
+ if (!fd) {
+ MaybeLogUploadEvent(
+ tracing_session->config, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingFailedToCreateFile);
+ tracing_sessions_.erase(tsid);
+ return PERFETTO_SVC_ERR("Failed to create the trace file %s",
+ cfg.output_path().c_str());
+ }
+ }
+ tracing_session->write_into_file = std::move(fd);
+ uint32_t write_period_ms = cfg.file_write_period_ms();
+ if (write_period_ms == 0)
+ write_period_ms = kDefaultWriteIntoFilePeriodMs;
+ if (write_period_ms < min_write_period_ms_)
+ write_period_ms = min_write_period_ms_;
+ tracing_session->write_period_ms = write_period_ms;
+ tracing_session->max_file_size_bytes = cfg.max_file_size_bytes();
+ tracing_session->bytes_written_into_file = 0;
+ }
+
+ if (cfg.compression_type() == TraceConfig::COMPRESSION_TYPE_DEFLATE) {
+ if (init_opts_.compressor_fn) {
+ tracing_session->compress_deflate = true;
+ } else {
+ PERFETTO_LOG(
+ "COMPRESSION_TYPE_DEFLATE is not supported in the current build "
+ "configuration. Skipping compression");
+ }
+ }
+
+ // Initialize the log buffers.
+ bool did_allocate_all_buffers = true;
+ bool invalid_buffer_config = false;
+
+ // Allocate the trace buffers. Also create a map to translate a consumer
+ // relative index (TraceConfig.DataSourceConfig.target_buffer) into the
+ // corresponding BufferID, which is a global ID namespace for the service and
+ // all producers.
+ size_t total_buf_size_kb = 0;
+ const size_t num_buffers = static_cast<size_t>(cfg.buffers_size());
+ tracing_session->buffers_index.reserve(num_buffers);
+ for (size_t i = 0; i < num_buffers; i++) {
+ const TraceConfig::BufferConfig& buffer_cfg = cfg.buffers()[i];
+ BufferID global_id = buffer_ids_.Allocate();
+ if (!global_id) {
+ did_allocate_all_buffers = false; // We ran out of IDs.
+ break;
+ }
+ tracing_session->buffers_index.push_back(global_id);
+ // TraceBuffer size is limited to 32-bit.
+ const uint32_t buf_size_kb = buffer_cfg.size_kb();
+ const uint64_t buf_size_bytes = buf_size_kb * static_cast<uint64_t>(1024);
+ const size_t buf_size = static_cast<size_t>(buf_size_bytes);
+ if (buf_size_bytes == 0 ||
+ buf_size_bytes > std::numeric_limits<uint32_t>::max() ||
+ buf_size != buf_size_bytes) {
+ invalid_buffer_config = true;
+ did_allocate_all_buffers = false;
+ break;
+ }
+ total_buf_size_kb += buf_size_kb;
+ TraceBuffer::OverwritePolicy policy =
+ buffer_cfg.fill_policy() == TraceConfig::BufferConfig::DISCARD
+ ? TraceBuffer::kDiscard
+ : TraceBuffer::kOverwrite;
+ auto it_and_inserted =
+ buffers_.emplace(global_id, TraceBuffer::Create(buf_size, policy));
+ PERFETTO_DCHECK(it_and_inserted.second); // buffers_.count(global_id) == 0.
+ std::unique_ptr<TraceBuffer>& trace_buffer = it_and_inserted.first->second;
+ if (!trace_buffer) {
+ did_allocate_all_buffers = false;
+ break;
+ }
+ }
+
+ // This can happen if either:
+ // - All the kMaxTraceBufferID slots are taken.
+ // - OOM, or, more realistically, we exhausted virtual memory.
+ // - The buffer size in the config is invalid.
+ // In any case, free all the previously allocated buffers and abort.
+ if (!did_allocate_all_buffers) {
+ for (BufferID global_id : tracing_session->buffers_index) {
+ buffer_ids_.Free(global_id);
+ buffers_.erase(global_id);
+ }
+ MaybeLogUploadEvent(tracing_session->config, uuid,
+ PerfettoStatsdAtom::kTracedEnableTracingOom);
+ tracing_sessions_.erase(tsid);
+ if (invalid_buffer_config) {
+ return PERFETTO_SVC_ERR(
+ "Failed to allocate tracing buffers: Invalid buffer sizes");
+ }
+ return PERFETTO_SVC_ERR(
+ "Failed to allocate tracing buffers: OOM or too many buffers");
+ }
+
+ UpdateMemoryGuardrail();
+
+ consumer->tracing_session_id_ = tsid;
+
+ // Setup the data sources on the producers without starting them.
+ for (const TraceConfig::DataSource& cfg_data_source : cfg.data_sources()) {
+ // Scan all the registered data sources with a matching name.
+ auto range = data_sources_.equal_range(cfg_data_source.config().name());
+ for (auto it = range.first; it != range.second; it++) {
+ TraceConfig::ProducerConfig producer_config;
+ for (const auto& config : cfg.producers()) {
+ if (GetProducer(it->second.producer_id)->name_ ==
+ config.producer_name()) {
+ producer_config = config;
+ break;
+ }
+ }
+ SetupDataSource(cfg_data_source, producer_config, it->second,
+ tracing_session);
+ }
+ }
+
+ bool has_start_trigger = false;
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ switch (GetTriggerMode(cfg)) {
+ case TraceConfig::TriggerConfig::UNSPECIFIED:
+ // no triggers are specified so this isn't a trace that is using triggers.
+ PERFETTO_DCHECK(!has_trigger_config);
+ break;
+ case TraceConfig::TriggerConfig::START_TRACING:
+ // For traces which use START_TRACE triggers we need to ensure that the
+ // tracing session will be cleaned up when it times out.
+ has_start_trigger = true;
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid]() {
+ if (weak_this)
+ weak_this->OnStartTriggersTimeout(tsid);
+ },
+ cfg.trigger_config().trigger_timeout_ms());
+ break;
+ case TraceConfig::TriggerConfig::STOP_TRACING:
+ case TraceConfig::TriggerConfig::CLONE_SNAPSHOT:
+ // Update the tracing_session's duration_ms to ensure that if no trigger
+ // is received the session will end and be cleaned up equal to the
+ // timeout.
+ //
+ // TODO(nuskos): Refactor this so that rather then modifying the config we
+ // have a field we look at on the tracing_session.
+ tracing_session->config.set_duration_ms(
+ cfg.trigger_config().trigger_timeout_ms());
+ break;
+
+ // The case of unknown modes (coming from future versions of the service)
+ // is handled few lines above (search for TriggerMode_MAX).
+ }
+
+ tracing_session->state = TracingSession::CONFIGURED;
+ PERFETTO_LOG(
+ "Configured tracing session %" PRIu64
+ ", #sources:%zu, duration:%d ms%s, #buffers:%d, total "
+ "buffer size:%zu KB, total sessions:%zu, uid:%d session name: \"%s\"",
+ tsid, cfg.data_sources().size(), tracing_session->config.duration_ms(),
+ tracing_session->config.prefer_suspend_clock_for_duration()
+ ? " (suspend_clock)"
+ : "",
+ cfg.buffers_size(), total_buf_size_kb, tracing_sessions_.size(),
+ static_cast<unsigned int>(consumer->uid_),
+ cfg.unique_session_name().c_str());
+
+ // Start the data sources, unless this is a case of early setup + fast
+ // triggering, either through TraceConfig.deferred_start or
+ // TraceConfig.trigger_config(). If both are specified which ever one occurs
+ // first will initiate the trace.
+ if (!cfg.deferred_start() && !has_start_trigger)
+ return StartTracing(tsid);
+
+ return base::OkStatus();
+}
+
+void TracingServiceImpl::ChangeTraceConfig(ConsumerEndpointImpl* consumer,
+ const TraceConfig& updated_cfg) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session =
+ GetTracingSession(consumer->tracing_session_id_);
+ PERFETTO_DCHECK(tracing_session);
+
+ if ((tracing_session->state != TracingSession::STARTED) &&
+ (tracing_session->state != TracingSession::CONFIGURED)) {
+ PERFETTO_ELOG(
+ "ChangeTraceConfig() was called for a tracing session which isn't "
+ "running.");
+ return;
+ }
+
+ // We only support updating producer_name_{,regex}_filter (and pass-through
+ // configs) for now; null out any changeable fields and make sure the rest are
+ // identical.
+ TraceConfig new_config_copy(updated_cfg);
+ for (auto& ds_cfg : *new_config_copy.mutable_data_sources()) {
+ ds_cfg.clear_producer_name_filter();
+ ds_cfg.clear_producer_name_regex_filter();
+ }
+
+ TraceConfig current_config_copy(tracing_session->config);
+ for (auto& ds_cfg : *current_config_copy.mutable_data_sources()) {
+ ds_cfg.clear_producer_name_filter();
+ ds_cfg.clear_producer_name_regex_filter();
+ }
+
+ if (new_config_copy != current_config_copy) {
+ PERFETTO_LOG(
+ "ChangeTraceConfig() was called with a config containing unsupported "
+ "changes; only adding to the producer_name_{,regex}_filter is "
+ "currently supported and will have an effect.");
+ }
+
+ for (TraceConfig::DataSource& cfg_data_source :
+ *tracing_session->config.mutable_data_sources()) {
+ // Find the updated producer_filter in the new config.
+ std::vector<std::string> new_producer_name_filter;
+ std::vector<std::string> new_producer_name_regex_filter;
+ bool found_data_source = false;
+ for (const auto& it : updated_cfg.data_sources()) {
+ if (cfg_data_source.config().name() == it.config().name()) {
+ new_producer_name_filter = it.producer_name_filter();
+ new_producer_name_regex_filter = it.producer_name_regex_filter();
+ found_data_source = true;
+ break;
+ }
+ }
+
+ // Bail out if data source not present in the new config.
+ if (!found_data_source) {
+ PERFETTO_ELOG(
+ "ChangeTraceConfig() called without a current data source also "
+ "present in the new config: %s",
+ cfg_data_source.config().name().c_str());
+ continue;
+ }
+
+ // TODO(oysteine): Just replacing the filter means that if
+ // there are any filter entries which were present in the original config,
+ // but removed from the config passed to ChangeTraceConfig, any matching
+ // producers will keep producing but newly added producers after this
+ // point will never start.
+ *cfg_data_source.mutable_producer_name_filter() = new_producer_name_filter;
+ *cfg_data_source.mutable_producer_name_regex_filter() =
+ new_producer_name_regex_filter;
+
+ // Get the list of producers that are already set up.
+ std::unordered_set<uint16_t> set_up_producers;
+ auto& ds_instances = tracing_session->data_source_instances;
+ for (auto instance_it = ds_instances.begin();
+ instance_it != ds_instances.end(); ++instance_it) {
+ set_up_producers.insert(instance_it->first);
+ }
+
+ // Scan all the registered data sources with a matching name.
+ auto range = data_sources_.equal_range(cfg_data_source.config().name());
+ for (auto it = range.first; it != range.second; it++) {
+ ProducerEndpointImpl* producer = GetProducer(it->second.producer_id);
+ PERFETTO_DCHECK(producer);
+
+ // Check if the producer name of this data source is present
+ // in the name filters. We currently only support new filters, not
+ // removing old ones.
+ if (!NameMatchesFilter(producer->name_, new_producer_name_filter,
+ new_producer_name_regex_filter)) {
+ continue;
+ }
+
+ // If this producer is already set up, we assume that all datasources
+ // in it started already.
+ if (set_up_producers.count(it->second.producer_id))
+ continue;
+
+ // If it wasn't previously setup, set it up now.
+ // (The per-producer config is optional).
+ TraceConfig::ProducerConfig producer_config;
+ for (const auto& config : tracing_session->config.producers()) {
+ if (producer->name_ == config.producer_name()) {
+ producer_config = config;
+ break;
+ }
+ }
+
+ DataSourceInstance* ds_inst = SetupDataSource(
+ cfg_data_source, producer_config, it->second, tracing_session);
+
+ if (ds_inst && tracing_session->state == TracingSession::STARTED)
+ StartDataSourceInstance(producer, tracing_session, ds_inst);
+ }
+ }
+}
+
+base::Status TracingServiceImpl::StartTracing(TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session) {
+ return PERFETTO_SVC_ERR(
+ "StartTracing() failed, invalid session ID %" PRIu64, tsid);
+ }
+
+ MaybeLogUploadEvent(tracing_session->config, tracing_session->trace_uuid,
+ PerfettoStatsdAtom::kTracedStartTracing);
+
+ if (tracing_session->state != TracingSession::CONFIGURED) {
+ MaybeLogUploadEvent(
+ tracing_session->config, tracing_session->trace_uuid,
+ PerfettoStatsdAtom::kTracedStartTracingInvalidSessionState);
+ return PERFETTO_SVC_ERR("StartTracing() failed, invalid session state: %d",
+ tracing_session->state);
+ }
+
+ tracing_session->state = TracingSession::STARTED;
+
+ // We store the start of trace snapshot separately as it's important to make
+ // sure we can interpret all the data in the trace and storing it in the ring
+ // buffer means it could be overwritten by a later snapshot.
+ if (!tracing_session->config.builtin_data_sources()
+ .disable_clock_snapshotting()) {
+ SnapshotClocks(&tracing_session->initial_clock_snapshot);
+ }
+
+ // We don't snapshot the clocks here because we just did this above.
+ SnapshotLifecyleEvent(
+ tracing_session,
+ protos::pbzero::TracingServiceEvent::kTracingStartedFieldNumber,
+ false /* snapshot_clocks */);
+
+ // Periodically snapshot clocks, stats, sync markers while the trace is
+ // active. The snapshots are emitted on the future ReadBuffers() calls, which
+ // means that:
+ // (a) If we're streaming to a file (or to a consumer) while tracing, we
+ // write snapshots periodically into the trace.
+ // (b) If ReadBuffers() is only called after tracing ends, we emit the latest
+ // snapshot into the trace. For clock snapshots, we keep track of the
+ // snapshot recorded at the beginning of the session
+ // (initial_clock_snapshot above), as well as the most recent sampled
+ // snapshots that showed significant new drift between different clocks.
+ // The latter clock snapshots are sampled periodically and at lifecycle
+ // events.
+ base::PeriodicTask::Args snapshot_task_args;
+ snapshot_task_args.start_first_task_immediately = true;
+ snapshot_task_args.use_suspend_aware_timer =
+ tracing_session->config.builtin_data_sources()
+ .prefer_suspend_clock_for_snapshot();
+ snapshot_task_args.task = [weak_this, tsid] {
+ if (weak_this)
+ weak_this->PeriodicSnapshotTask(tsid);
+ };
+ snapshot_task_args.period_ms =
+ tracing_session->config.builtin_data_sources().snapshot_interval_ms();
+ if (!snapshot_task_args.period_ms)
+ snapshot_task_args.period_ms = kDefaultSnapshotsIntervalMs;
+ tracing_session->snapshot_periodic_task.Start(snapshot_task_args);
+
+ // Trigger delayed task if the trace is time limited.
+ const uint32_t trace_duration_ms = tracing_session->config.duration_ms();
+ if (trace_duration_ms > 0) {
+ auto stop_task =
+ std::bind(&TracingServiceImpl::StopOnDurationMsExpiry, weak_this, tsid);
+ if (tracing_session->config.prefer_suspend_clock_for_duration()) {
+ base::PeriodicTask::Args stop_args;
+ stop_args.use_suspend_aware_timer = true;
+ stop_args.period_ms = trace_duration_ms;
+ stop_args.one_shot = true;
+ stop_args.task = std::move(stop_task);
+ tracing_session->timed_stop_task.Start(stop_args);
+ } else {
+ task_runner_->PostDelayedTask(std::move(stop_task), trace_duration_ms);
+ }
+ } // if (trace_duration_ms > 0).
+
+ // Start the periodic drain tasks if we should to save the trace into a file.
+ if (tracing_session->config.write_into_file()) {
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ if (weak_this)
+ weak_this->ReadBuffersIntoFile(tsid);
+ },
+ tracing_session->delay_to_next_write_period_ms());
+ }
+
+ // Start the periodic flush tasks if the config specified a flush period.
+ if (tracing_session->config.flush_period_ms())
+ PeriodicFlushTask(tsid, /*post_next_only=*/true);
+
+ // Start the periodic incremental state clear tasks if the config specified a
+ // period.
+ if (tracing_session->config.incremental_state_config().clear_period_ms()) {
+ PeriodicClearIncrementalStateTask(tsid, /*post_next_only=*/true);
+ }
+
+ for (auto& [prod_id, data_source] : tracing_session->data_source_instances) {
+ ProducerEndpointImpl* producer = GetProducer(prod_id);
+ if (!producer) {
+ PERFETTO_DFATAL("Producer does not exist.");
+ continue;
+ }
+ StartDataSourceInstance(producer, tracing_session, &data_source);
+ }
+
+ MaybeNotifyAllDataSourcesStarted(tracing_session);
+ return base::OkStatus();
+}
+
+// static
+void TracingServiceImpl::StopOnDurationMsExpiry(
+ base::WeakPtr<TracingServiceImpl> weak_this,
+ TracingSessionID tsid) {
+ // Skip entirely the flush if the trace session doesn't exist anymore.
+ // This is to prevent misleading error messages to be logged.
+ if (!weak_this)
+ return;
+ auto* tracing_session_ptr = weak_this->GetTracingSession(tsid);
+ if (!tracing_session_ptr)
+ return;
+ // If this trace was using STOP_TRACING triggers and we've seen
+ // one, then the trigger overrides the normal timeout. In this
+ // case we just return and let the other task clean up this trace.
+ if (GetTriggerMode(tracing_session_ptr->config) ==
+ TraceConfig::TriggerConfig::STOP_TRACING &&
+ !tracing_session_ptr->received_triggers.empty())
+ return;
+ // In all other cases (START_TRACING or no triggers) we flush
+ // after |trace_duration_ms| unconditionally.
+ weak_this->FlushAndDisableTracing(tsid);
+}
+
+void TracingServiceImpl::StartDataSourceInstance(
+ ProducerEndpointImpl* producer,
+ TracingSession* tracing_session,
+ TracingServiceImpl::DataSourceInstance* instance) {
+ PERFETTO_DCHECK(instance->state == DataSourceInstance::CONFIGURED);
+ if (instance->will_notify_on_start) {
+ instance->state = DataSourceInstance::STARTING;
+ } else {
+ instance->state = DataSourceInstance::STARTED;
+ }
+ if (tracing_session->consumer_maybe_null) {
+ tracing_session->consumer_maybe_null->OnDataSourceInstanceStateChange(
+ *producer, *instance);
+ }
+ producer->StartDataSource(instance->instance_id, instance->config);
+
+ // If all data sources are started, notify the consumer.
+ if (instance->state == DataSourceInstance::STARTED)
+ MaybeNotifyAllDataSourcesStarted(tracing_session);
+}
+
+// DisableTracing just stops the data sources but doesn't free up any buffer.
+// This is to allow the consumer to freeze the buffers (by stopping the trace)
+// and then drain the buffers. The actual teardown of the TracingSession happens
+// in FreeBuffers().
+void TracingServiceImpl::DisableTracing(TracingSessionID tsid,
+ bool disable_immediately) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session) {
+ // Can happen if the consumer calls this before EnableTracing() or after
+ // FreeBuffers().
+ PERFETTO_DLOG("DisableTracing() failed, invalid session ID %" PRIu64, tsid);
+ return;
+ }
+
+ MaybeLogUploadEvent(tracing_session->config, tracing_session->trace_uuid,
+ PerfettoStatsdAtom::kTracedDisableTracing);
+
+ switch (tracing_session->state) {
+ // Spurious call to DisableTracing() while already disabled, nothing to do.
+ case TracingSession::DISABLED:
+ PERFETTO_DCHECK(tracing_session->AllDataSourceInstancesStopped());
+ return;
+
+ case TracingSession::CLONED_READ_ONLY:
+ PERFETTO_DLOG("DisableTracing() cannot be called on a cloned session");
+ return;
+
+ // This is either:
+ // A) The case of a graceful DisableTracing() call followed by a call to
+ // FreeBuffers(), iff |disable_immediately| == true. In this case we want
+ // to forcefully transition in the disabled state without waiting for the
+ // outstanding acks because the buffers are going to be destroyed soon.
+ // B) A spurious call, iff |disable_immediately| == false, in which case
+ // there is nothing to do.
+ case TracingSession::DISABLING_WAITING_STOP_ACKS:
+ PERFETTO_DCHECK(!tracing_session->AllDataSourceInstancesStopped());
+ if (disable_immediately)
+ DisableTracingNotifyConsumerAndFlushFile(tracing_session);
+ return;
+
+ // Continues below.
+ case TracingSession::CONFIGURED:
+ // If the session didn't even start there is no need to orchestrate a
+ // graceful stop of data sources.
+ disable_immediately = true;
+ break;
+
+ // This is the nominal case, continues below.
+ case TracingSession::STARTED:
+ break;
+ }
+
+ for (auto& data_source_inst : tracing_session->data_source_instances) {
+ const ProducerID producer_id = data_source_inst.first;
+ DataSourceInstance& instance = data_source_inst.second;
+ ProducerEndpointImpl* producer = GetProducer(producer_id);
+ PERFETTO_DCHECK(producer);
+ PERFETTO_DCHECK(instance.state == DataSourceInstance::CONFIGURED ||
+ instance.state == DataSourceInstance::STARTING ||
+ instance.state == DataSourceInstance::STARTED);
+ StopDataSourceInstance(producer, tracing_session, &instance,
+ disable_immediately);
+ }
+
+ // If the periodic task is running, we can stop the periodic snapshot timer
+ // here instead of waiting until FreeBuffers to prevent useless snapshots
+ // which won't be read.
+ tracing_session->snapshot_periodic_task.Reset();
+
+ // Either this request is flagged with |disable_immediately| or there are no
+ // data sources that are requesting a final handshake. In both cases just mark
+ // the session as disabled immediately, notify the consumer and flush the
+ // trace file (if used).
+ if (tracing_session->AllDataSourceInstancesStopped())
+ return DisableTracingNotifyConsumerAndFlushFile(tracing_session);
+
+ tracing_session->state = TracingSession::DISABLING_WAITING_STOP_ACKS;
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ if (weak_this)
+ weak_this->OnDisableTracingTimeout(tsid);
+ },
+ tracing_session->data_source_stop_timeout_ms());
+
+ // Deliberately NOT removing the session from |tracing_session_|, it's still
+ // needed to call ReadBuffers(). FreeBuffers() will erase() the session.
+}
+
+void TracingServiceImpl::NotifyDataSourceStarted(
+ ProducerID producer_id,
+ DataSourceInstanceID instance_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (auto& kv : tracing_sessions_) {
+ TracingSession& tracing_session = kv.second;
+ DataSourceInstance* instance =
+ tracing_session.GetDataSourceInstance(producer_id, instance_id);
+
+ if (!instance)
+ continue;
+
+ // If the tracing session was already stopped, ignore this notification.
+ if (tracing_session.state != TracingSession::STARTED)
+ continue;
+
+ if (instance->state != DataSourceInstance::STARTING) {
+ PERFETTO_ELOG("Started data source instance in incorrect state: %d",
+ instance->state);
+ continue;
+ }
+
+ instance->state = DataSourceInstance::STARTED;
+
+ ProducerEndpointImpl* producer = GetProducer(producer_id);
+ PERFETTO_DCHECK(producer);
+ if (tracing_session.consumer_maybe_null) {
+ tracing_session.consumer_maybe_null->OnDataSourceInstanceStateChange(
+ *producer, *instance);
+ }
+
+ // If all data sources are started, notify the consumer.
+ MaybeNotifyAllDataSourcesStarted(&tracing_session);
+ } // for (tracing_session)
+}
+
+void TracingServiceImpl::MaybeNotifyAllDataSourcesStarted(
+ TracingSession* tracing_session) {
+ if (!tracing_session->consumer_maybe_null)
+ return;
+
+ if (!tracing_session->AllDataSourceInstancesStarted())
+ return;
+
+ // In some rare cases, we can get in this state more than once. Consider the
+ // following scenario: 3 data sources are registered -> trace starts ->
+ // all 3 data sources ack -> OnAllDataSourcesStarted() is called.
+ // Imagine now that a 4th data source registers while the trace is ongoing.
+ // This would hit the AllDataSourceInstancesStarted() condition again.
+ // In this case, however, we don't want to re-notify the consumer again.
+ // That would be unexpected (even if, perhaps, technically correct) and
+ // trigger bugs in the consumer.
+ if (tracing_session->did_notify_all_data_source_started)
+ return;
+
+ PERFETTO_DLOG("All data sources started");
+
+ SnapshotLifecyleEvent(
+ tracing_session,
+ protos::pbzero::TracingServiceEvent::kAllDataSourcesStartedFieldNumber,
+ true /* snapshot_clocks */);
+
+ tracing_session->did_notify_all_data_source_started = true;
+ tracing_session->consumer_maybe_null->OnAllDataSourcesStarted();
+}
+
+void TracingServiceImpl::NotifyDataSourceStopped(
+ ProducerID producer_id,
+ DataSourceInstanceID instance_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (auto& kv : tracing_sessions_) {
+ TracingSession& tracing_session = kv.second;
+ DataSourceInstance* instance =
+ tracing_session.GetDataSourceInstance(producer_id, instance_id);
+
+ if (!instance)
+ continue;
+
+ if (instance->state != DataSourceInstance::STOPPING) {
+ PERFETTO_ELOG("Stopped data source instance in incorrect state: %d",
+ instance->state);
+ continue;
+ }
+
+ instance->state = DataSourceInstance::STOPPED;
+
+ ProducerEndpointImpl* producer = GetProducer(producer_id);
+ PERFETTO_DCHECK(producer);
+ if (tracing_session.consumer_maybe_null) {
+ tracing_session.consumer_maybe_null->OnDataSourceInstanceStateChange(
+ *producer, *instance);
+ }
+
+ if (!tracing_session.AllDataSourceInstancesStopped())
+ continue;
+
+ if (tracing_session.state != TracingSession::DISABLING_WAITING_STOP_ACKS)
+ continue;
+
+ // All data sources acked the termination.
+ DisableTracingNotifyConsumerAndFlushFile(&tracing_session);
+ } // for (tracing_session)
+}
+
+void TracingServiceImpl::ActivateTriggers(
+ ProducerID producer_id,
+ const std::vector<std::string>& triggers) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto* producer = GetProducer(producer_id);
+ PERFETTO_DCHECK(producer);
+
+ int64_t now_ns = base::GetBootTimeNs().count();
+ for (const auto& trigger_name : triggers) {
+ PERFETTO_DLOG("Received ActivateTriggers request for \"%s\"",
+ trigger_name.c_str());
+ base::Hasher hash;
+ hash.Update(trigger_name.c_str(), trigger_name.size());
+ std::string triggered_session_name;
+ base::Uuid triggered_session_uuid;
+ TracingSessionID triggered_session_id = 0;
+ auto trigger_mode = TraceConfig::TriggerConfig::UNSPECIFIED;
+
+ uint64_t trigger_name_hash = hash.digest();
+ size_t count_in_window =
+ PurgeExpiredAndCountTriggerInWindow(now_ns, trigger_name_hash);
+
+ bool trigger_matched = false;
+ bool trigger_activated = false;
+ for (auto& id_and_tracing_session : tracing_sessions_) {
+ auto& tracing_session = id_and_tracing_session.second;
+ TracingSessionID tsid = id_and_tracing_session.first;
+ auto iter = std::find_if(
+ tracing_session.config.trigger_config().triggers().begin(),
+ tracing_session.config.trigger_config().triggers().end(),
+ [&trigger_name](const TraceConfig::TriggerConfig::Trigger& trigger) {
+ return trigger.name() == trigger_name;
+ });
+ if (iter == tracing_session.config.trigger_config().triggers().end())
+ continue;
+ if (tracing_session.state == TracingSession::CLONED_READ_ONLY)
+ continue;
+
+ // If this trigger requires a certain producer to have sent it
+ // (non-empty producer_name()) ensure the producer who sent this trigger
+ // matches.
+ if (!iter->producer_name_regex().empty() &&
+ !std::regex_match(
+ producer->name_,
+ std::regex(iter->producer_name_regex(), std::regex::extended))) {
+ continue;
+ }
+
+ // Use a random number between 0 and 1 to check if we should allow this
+ // trigger through or not.
+ double trigger_rnd =
+ trigger_rnd_override_for_testing_ > 0
+ ? trigger_rnd_override_for_testing_
+ : trigger_probability_dist_(trigger_probability_rand_);
+ PERFETTO_DCHECK(trigger_rnd >= 0 && trigger_rnd < 1);
+ if (trigger_rnd < iter->skip_probability()) {
+ MaybeLogTriggerEvent(tracing_session.config,
+ PerfettoTriggerAtom::kTracedLimitProbability,
+ trigger_name);
+ continue;
+ }
+
+ // If we already triggered more times than the limit, silently ignore
+ // this trigger.
+ if (iter->max_per_24_h() > 0 && count_in_window >= iter->max_per_24_h()) {
+ MaybeLogTriggerEvent(tracing_session.config,
+ PerfettoTriggerAtom::kTracedLimitMaxPer24h,
+ trigger_name);
+ continue;
+ }
+ trigger_matched = true;
+ triggered_session_id = tracing_session.id;
+ triggered_session_name = tracing_session.config.unique_session_name();
+ triggered_session_uuid.set_lsb_msb(tracing_session.trace_uuid.lsb(),
+ tracing_session.trace_uuid.msb());
+ trigger_mode = GetTriggerMode(tracing_session.config);
+
+ const bool triggers_already_received =
+ !tracing_session.received_triggers.empty();
+ tracing_session.received_triggers.push_back(
+ {static_cast<uint64_t>(now_ns), iter->name(), producer->name_,
+ producer->uid()});
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ switch (trigger_mode) {
+ case TraceConfig::TriggerConfig::START_TRACING:
+ // If the session has already been triggered and moved past
+ // CONFIGURED then we don't need to repeat StartTracing. This would
+ // work fine (StartTracing would return false) but would add error
+ // logs.
+ if (tracing_session.state != TracingSession::CONFIGURED)
+ break;
+
+ trigger_activated = true;
+ MaybeLogUploadEvent(
+ tracing_session.config, tracing_session.trace_uuid,
+ PerfettoStatsdAtom::kTracedTriggerStartTracing, iter->name());
+
+ // We override the trace duration to be the trigger's requested
+ // value, this ensures that the trace will end after this amount
+ // of time has passed.
+ tracing_session.config.set_duration_ms(iter->stop_delay_ms());
+ StartTracing(tsid);
+ break;
+ case TraceConfig::TriggerConfig::STOP_TRACING:
+ // Only stop the trace once to avoid confusing log messages. I.E.
+ // when we've already hit the first trigger we've already Posted the
+ // task to FlushAndDisable. So all future triggers will just break
+ // out.
+ if (triggers_already_received)
+ break;
+
+ trigger_activated = true;
+ MaybeLogUploadEvent(
+ tracing_session.config, tracing_session.trace_uuid,
+ PerfettoStatsdAtom::kTracedTriggerStopTracing, iter->name());
+
+ // Now that we've seen a trigger we need to stop, flush, and disable
+ // this session after the configured |stop_delay_ms|.
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ // Skip entirely the flush if the trace session doesn't exist
+ // anymore. This is to prevent misleading error messages to be
+ // logged.
+ if (weak_this && weak_this->GetTracingSession(tsid))
+ weak_this->FlushAndDisableTracing(tsid);
+ },
+ // If this trigger is zero this will immediately executable and
+ // will happen shortly.
+ iter->stop_delay_ms());
+ break;
+
+ case TraceConfig::TriggerConfig::CLONE_SNAPSHOT:
+ trigger_activated = true;
+ MaybeLogUploadEvent(
+ tracing_session.config, tracing_session.trace_uuid,
+ PerfettoStatsdAtom::kTracedTriggerCloneSnapshot, iter->name());
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ if (!weak_this)
+ return;
+ auto* tsess = weak_this->GetTracingSession(tsid);
+ if (!tsess || !tsess->consumer_maybe_null)
+ return;
+ tsess->consumer_maybe_null->NotifyCloneSnapshotTrigger();
+ },
+ iter->stop_delay_ms());
+ break;
+
+ case TraceConfig::TriggerConfig::UNSPECIFIED:
+ PERFETTO_ELOG("Trigger activated but trigger mode unspecified.");
+ break;
+ }
+ } // for (.. : tracing_sessions_)
+
+ if (trigger_matched) {
+ trigger_history_.emplace_back(TriggerHistory{now_ns, trigger_name_hash});
+ }
+
+ if (trigger_activated) {
+ // Log only the trigger that actually caused a trace stop/start, don't log
+ // the follow-up ones, even if they matched.
+ PERFETTO_LOG(
+ "Trace trigger activated: trigger_name=\"%s\" trigger_mode=%d "
+ "trace_name=\"%s\" trace_uuid=\"%s\" tsid=%" PRIu64,
+ trigger_name.c_str(), trigger_mode, triggered_session_name.c_str(),
+ triggered_session_uuid.ToPrettyString().c_str(),
+ triggered_session_id);
+ }
+ } // for (trigger_name : triggers)
+}
+
+// Always invoked TraceConfig.data_source_stop_timeout_ms (by default
+// kDataSourceStopTimeoutMs) after DisableTracing(). In nominal conditions all
+// data sources should have acked the stop and this will early out.
+void TracingServiceImpl::OnDisableTracingTimeout(TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session ||
+ tracing_session->state != TracingSession::DISABLING_WAITING_STOP_ACKS) {
+ return; // Tracing session was successfully disabled.
+ }
+
+ PERFETTO_ILOG("Timeout while waiting for ACKs for tracing session %" PRIu64,
+ tsid);
+ PERFETTO_DCHECK(!tracing_session->AllDataSourceInstancesStopped());
+ DisableTracingNotifyConsumerAndFlushFile(tracing_session);
+}
+
+void TracingServiceImpl::DisableTracingNotifyConsumerAndFlushFile(
+ TracingSession* tracing_session) {
+ PERFETTO_DCHECK(tracing_session->state != TracingSession::DISABLED);
+ for (auto& inst_kv : tracing_session->data_source_instances) {
+ if (inst_kv.second.state == DataSourceInstance::STOPPED)
+ continue;
+ inst_kv.second.state = DataSourceInstance::STOPPED;
+ ProducerEndpointImpl* producer = GetProducer(inst_kv.first);
+ PERFETTO_DCHECK(producer);
+ if (tracing_session->consumer_maybe_null) {
+ tracing_session->consumer_maybe_null->OnDataSourceInstanceStateChange(
+ *producer, inst_kv.second);
+ }
+ }
+ tracing_session->state = TracingSession::DISABLED;
+
+ // Scrape any remaining chunks that weren't flushed by the producers.
+ for (auto& producer_id_and_producer : producers_)
+ ScrapeSharedMemoryBuffers(tracing_session, producer_id_and_producer.second);
+
+ SnapshotLifecyleEvent(
+ tracing_session,
+ protos::pbzero::TracingServiceEvent::kTracingDisabledFieldNumber,
+ true /* snapshot_clocks */);
+
+ if (tracing_session->write_into_file) {
+ tracing_session->write_period_ms = 0;
+ ReadBuffersIntoFile(tracing_session->id);
+ }
+
+ MaybeLogUploadEvent(tracing_session->config, tracing_session->trace_uuid,
+ PerfettoStatsdAtom::kTracedNotifyTracingDisabled);
+
+ if (tracing_session->consumer_maybe_null)
+ tracing_session->consumer_maybe_null->NotifyOnTracingDisabled("");
+}
+
+void TracingServiceImpl::Flush(TracingSessionID tsid,
+ uint32_t timeout_ms,
+ ConsumerEndpoint::FlushCallback callback,
+ FlushFlags flush_flags) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session) {
+ PERFETTO_DLOG("Flush() failed, invalid session ID %" PRIu64, tsid);
+ return;
+ }
+
+ std::map<ProducerID, std::vector<DataSourceInstanceID>> data_source_instances;
+ for (const auto& [producer_id, ds_inst] :
+ tracing_session->data_source_instances) {
+ if (ds_inst.no_flush)
+ continue;
+ data_source_instances[producer_id].push_back(ds_inst.instance_id);
+ }
+ FlushDataSourceInstances(tracing_session, timeout_ms, data_source_instances,
+ std::move(callback), flush_flags);
+}
+
+void TracingServiceImpl::FlushDataSourceInstances(
+ TracingSession* tracing_session,
+ uint32_t timeout_ms,
+ const std::map<ProducerID, std::vector<DataSourceInstanceID>>&
+ data_source_instances,
+ ConsumerEndpoint::FlushCallback callback,
+ FlushFlags flush_flags) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!timeout_ms)
+ timeout_ms = tracing_session->flush_timeout_ms();
+
+ if (tracing_session->pending_flushes.size() > 1000) {
+ PERFETTO_ELOG("Too many flushes (%zu) pending for the tracing session",
+ tracing_session->pending_flushes.size());
+ callback(false);
+ return;
+ }
+
+ if (tracing_session->state != TracingSession::STARTED) {
+ PERFETTO_LOG("Flush() called, but tracing has not been started");
+ callback(false);
+ return;
+ }
+
+ ++tracing_session->flushes_requested;
+ FlushRequestID flush_request_id = ++last_flush_request_id_;
+ PendingFlush& pending_flush =
+ tracing_session->pending_flushes
+ .emplace_hint(tracing_session->pending_flushes.end(),
+ flush_request_id, PendingFlush(std::move(callback)))
+ ->second;
+
+ // Send a flush request to each producer involved in the tracing session. In
+ // order to issue a flush request we have to build a map of all data source
+ // instance ids enabled for each producer.
+
+ for (const auto& [producer_id, data_sources] : data_source_instances) {
+ ProducerEndpointImpl* producer = GetProducer(producer_id);
+ producer->Flush(flush_request_id, data_sources, flush_flags);
+ pending_flush.producers.insert(producer_id);
+ }
+
+ // If there are no producers to flush (realistically this happens only in
+ // some tests) fire OnFlushTimeout() straight away, without waiting.
+ if (data_source_instances.empty())
+ timeout_ms = 0;
+
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid = tracing_session->id, flush_request_id] {
+ if (weak_this)
+ weak_this->OnFlushTimeout(tsid, flush_request_id);
+ },
+ timeout_ms);
+}
+
+void TracingServiceImpl::NotifyFlushDoneForProducer(
+ ProducerID producer_id,
+ FlushRequestID flush_request_id) {
+ for (auto& kv : tracing_sessions_) {
+ // Remove all pending flushes <= |flush_request_id| for |producer_id|.
+ auto& pending_flushes = kv.second.pending_flushes;
+ auto end_it = pending_flushes.upper_bound(flush_request_id);
+ for (auto it = pending_flushes.begin(); it != end_it;) {
+ PendingFlush& pending_flush = it->second;
+ pending_flush.producers.erase(producer_id);
+ if (pending_flush.producers.empty()) {
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ TracingSessionID tsid = kv.first;
+ auto callback = std::move(pending_flush.callback);
+ task_runner_->PostTask([weak_this, tsid, callback]() {
+ if (weak_this) {
+ weak_this->CompleteFlush(tsid, std::move(callback),
+ /*success=*/true);
+ }
+ });
+ it = pending_flushes.erase(it);
+ } else {
+ it++;
+ }
+ } // for (pending_flushes)
+ } // for (tracing_session)
+}
+
+void TracingServiceImpl::OnFlushTimeout(TracingSessionID tsid,
+ FlushRequestID flush_request_id) {
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session)
+ return;
+ auto it = tracing_session->pending_flushes.find(flush_request_id);
+ if (it == tracing_session->pending_flushes.end())
+ return; // Nominal case: flush was completed and acked on time.
+
+ // If there were no producers to flush, consider it a success.
+ bool success = it->second.producers.empty();
+ auto callback = std::move(it->second.callback);
+ tracing_session->pending_flushes.erase(it);
+ CompleteFlush(tsid, std::move(callback), success);
+}
+
+void TracingServiceImpl::CompleteFlush(TracingSessionID tsid,
+ ConsumerEndpoint::FlushCallback callback,
+ bool success) {
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session) {
+ callback(false);
+ return;
+ }
+ // Producers may not have been able to flush all their data, even if they
+ // indicated flush completion. If possible, also collect uncommitted chunks
+ // to make sure we have everything they wrote so far.
+ for (auto& producer_id_and_producer : producers_) {
+ ScrapeSharedMemoryBuffers(tracing_session, producer_id_and_producer.second);
+ }
+ SnapshotLifecyleEvent(
+ tracing_session,
+ protos::pbzero::TracingServiceEvent::kAllDataSourcesFlushedFieldNumber,
+ true /* snapshot_clocks */);
+
+ tracing_session->flushes_succeeded += success ? 1 : 0;
+ tracing_session->flushes_failed += success ? 0 : 1;
+ callback(success);
+}
+
+void TracingServiceImpl::ScrapeSharedMemoryBuffers(
+ TracingSession* tracing_session,
+ ProducerEndpointImpl* producer) {
+ if (!producer->smb_scraping_enabled_)
+ return;
+
+ // Can't copy chunks if we don't know about any trace writers.
+ if (producer->writers_.empty())
+ return;
+
+ // Performance optimization: On flush or session disconnect, this method is
+ // called for each producer. If the producer doesn't participate in the
+ // session, there's no need to scape its chunks right now. We can tell if a
+ // producer participates in the session by checking if the producer is allowed
+ // to write into the session's log buffers.
+ const auto& session_buffers = tracing_session->buffers_index;
+ bool producer_in_session =
+ std::any_of(session_buffers.begin(), session_buffers.end(),
+ [producer](BufferID buffer_id) {
+ return producer->allowed_target_buffers_.count(buffer_id);
+ });
+ if (!producer_in_session)
+ return;
+
+ PERFETTO_DLOG("Scraping SMB for producer %" PRIu16, producer->id_);
+
+ // Find and copy any uncommitted chunks from the SMB.
+ //
+ // In nominal conditions, the page layout of the used SMB pages should never
+ // change because the service is the only one who is supposed to modify used
+ // pages (to make them free again).
+ //
+ // However, the code here needs to deal with the case of a malicious producer
+ // altering the SMB in unpredictable ways. Thankfully the SMB size is
+ // immutable, so a chunk will always point to some valid memory, even if the
+ // producer alters the intended layout and chunk header concurrently.
+ // Ultimately a malicious producer altering the SMB's chunk layout while we
+ // are iterating in this function is not any different from the case of a
+ // malicious producer asking to commit a chunk made of random data, which is
+ // something this class has to deal with regardless.
+ //
+ // The only legitimate mutations that can happen from sane producers,
+ // concurrently to this function, are:
+ // A. free pages being partitioned,
+ // B. free chunks being migrated to kChunkBeingWritten,
+ // C. kChunkBeingWritten chunks being migrated to kChunkCompleted.
+
+ SharedMemoryABI* abi = &producer->shmem_abi_;
+ // num_pages() is immutable after the SMB is initialized and cannot be changed
+ // even by a producer even if malicious.
+ for (size_t page_idx = 0; page_idx < abi->num_pages(); page_idx++) {
+ uint32_t layout = abi->GetPageLayout(page_idx);
+
+ uint32_t used_chunks = abi->GetUsedChunks(layout); // Returns a bitmap.
+ // Skip empty pages.
+ if (used_chunks == 0)
+ continue;
+
+ // Scrape the chunks that are currently used. These should be either in
+ // state kChunkBeingWritten or kChunkComplete.
+ for (uint32_t chunk_idx = 0; used_chunks; chunk_idx++, used_chunks >>= 1) {
+ if (!(used_chunks & 1))
+ continue;
+
+ SharedMemoryABI::ChunkState state =
+ SharedMemoryABI::GetChunkStateFromLayout(layout, chunk_idx);
+ PERFETTO_DCHECK(state == SharedMemoryABI::kChunkBeingWritten ||
+ state == SharedMemoryABI::kChunkComplete);
+ bool chunk_complete = state == SharedMemoryABI::kChunkComplete;
+
+ SharedMemoryABI::Chunk chunk =
+ abi->GetChunkUnchecked(page_idx, layout, chunk_idx);
+
+ uint16_t packet_count;
+ uint8_t flags;
+ // GetPacketCountAndFlags has acquire_load semantics.
+ std::tie(packet_count, flags) = chunk.GetPacketCountAndFlags();
+
+ // It only makes sense to copy an incomplete chunk if there's at least
+ // one full packet available. (The producer may not have completed the
+ // last packet in it yet, so we need at least 2.)
+ if (!chunk_complete && packet_count < 2)
+ continue;
+
+ // At this point, it is safe to access the remaining header fields of
+ // the chunk. Even if the chunk was only just transferred from
+ // kChunkFree into kChunkBeingWritten state, the header should be
+ // written completely once the packet count increased above 1 (it was
+ // reset to 0 by the service when the chunk was freed).
+
+ WriterID writer_id = chunk.writer_id();
+ std::optional<BufferID> target_buffer_id =
+ producer->buffer_id_for_writer(writer_id);
+
+ // We can only scrape this chunk if we know which log buffer to copy it
+ // into.
+ if (!target_buffer_id)
+ continue;
+
+ // Skip chunks that don't belong to the requested tracing session.
+ bool target_buffer_belongs_to_session =
+ std::find(session_buffers.begin(), session_buffers.end(),
+ *target_buffer_id) != session_buffers.end();
+ if (!target_buffer_belongs_to_session)
+ continue;
+
+ uint32_t chunk_id =
+ chunk.header()->chunk_id.load(std::memory_order_relaxed);
+
+ CopyProducerPageIntoLogBuffer(
+ producer->id_, producer->client_identity_, writer_id, chunk_id,
+ *target_buffer_id, packet_count, flags, chunk_complete,
+ chunk.payload_begin(), chunk.payload_size());
+ }
+ }
+}
+
+void TracingServiceImpl::FlushAndDisableTracing(TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Triggering final flush for %" PRIu64, tsid);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ Flush(
+ tsid, 0,
+ [weak_this, tsid](bool success) {
+ // This was a DLOG up to Jun 2021 (v16, Android S).
+ PERFETTO_LOG("FlushAndDisableTracing(%" PRIu64 ") done, success=%d",
+ tsid, success);
+ if (!weak_this)
+ return;
+ TracingSession* session = weak_this->GetTracingSession(tsid);
+ if (!session) {
+ return;
+ }
+ session->final_flush_outcome = success
+ ? TraceStats::FINAL_FLUSH_SUCCEEDED
+ : TraceStats::FINAL_FLUSH_FAILED;
+ if (session->consumer_maybe_null) {
+ // If the consumer is still attached, just disable the session but
+ // give it a chance to read the contents.
+ weak_this->DisableTracing(tsid);
+ } else {
+ // If the consumer detached, destroy the session. If the consumer did
+ // start the session in long-tracing mode, the service will have saved
+ // the contents to the passed file. If not, the contents will be
+ // destroyed.
+ weak_this->FreeBuffers(tsid);
+ }
+ },
+ FlushFlags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceStop));
+}
+
+void TracingServiceImpl::PeriodicFlushTask(TracingSessionID tsid,
+ bool post_next_only) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session || tracing_session->state != TracingSession::STARTED)
+ return;
+
+ uint32_t flush_period_ms = tracing_session->config.flush_period_ms();
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ if (weak_this)
+ weak_this->PeriodicFlushTask(tsid, /*post_next_only=*/false);
+ },
+ flush_period_ms - static_cast<uint32_t>(base::GetWallTimeMs().count() %
+ flush_period_ms));
+
+ if (post_next_only)
+ return;
+
+ PERFETTO_DLOG("Triggering periodic flush for trace session %" PRIu64, tsid);
+ Flush(
+ tsid, 0,
+ [](bool success) {
+ if (!success)
+ PERFETTO_ELOG("Periodic flush timed out");
+ },
+ FlushFlags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kPeriodic));
+}
+
+void TracingServiceImpl::PeriodicClearIncrementalStateTask(
+ TracingSessionID tsid,
+ bool post_next_only) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session || tracing_session->state != TracingSession::STARTED)
+ return;
+
+ uint32_t clear_period_ms =
+ tracing_session->config.incremental_state_config().clear_period_ms();
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ if (weak_this)
+ weak_this->PeriodicClearIncrementalStateTask(
+ tsid, /*post_next_only=*/false);
+ },
+ clear_period_ms - static_cast<uint32_t>(base::GetWallTimeMs().count() %
+ clear_period_ms));
+
+ if (post_next_only)
+ return;
+
+ PERFETTO_DLOG(
+ "Performing periodic incremental state clear for trace session %" PRIu64,
+ tsid);
+
+ // Queue the IPCs to producers with active data sources that opted in.
+ std::map<ProducerID, std::vector<DataSourceInstanceID>> clear_map;
+ for (const auto& kv : tracing_session->data_source_instances) {
+ ProducerID producer_id = kv.first;
+ const DataSourceInstance& data_source = kv.second;
+ if (data_source.handles_incremental_state_clear) {
+ clear_map[producer_id].push_back(data_source.instance_id);
+ }
+ }
+
+ for (const auto& kv : clear_map) {
+ ProducerID producer_id = kv.first;
+ const std::vector<DataSourceInstanceID>& data_sources = kv.second;
+ ProducerEndpointImpl* producer = GetProducer(producer_id);
+ if (!producer) {
+ PERFETTO_DFATAL("Producer does not exist.");
+ continue;
+ }
+ producer->ClearIncrementalState(data_sources);
+ }
+}
+
+bool TracingServiceImpl::ReadBuffersIntoConsumer(
+ TracingSessionID tsid,
+ ConsumerEndpointImpl* consumer) {
+ PERFETTO_DCHECK(consumer);
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session) {
+ PERFETTO_DLOG(
+ "Cannot ReadBuffersIntoConsumer(): no tracing session is active");
+ return false;
+ }
+
+ if (tracing_session->write_into_file) {
+ // If the consumer enabled tracing and asked to save the contents into the
+ // passed file makes little sense to also try to read the buffers over IPC,
+ // as that would just steal data from the periodic draining task.
+ PERFETTO_ELOG("Consumer trying to read from write_into_file session.");
+ return false;
+ }
+
+ if (IsWaitingForTrigger(tracing_session))
+ return false;
+
+ // This is a rough threshold to determine how much to read from the buffer in
+ // each task. This is to avoid executing a single huge sending task for too
+ // long and risk to hit the watchdog. This is *not* an upper bound: we just
+ // stop accumulating new packets and PostTask *after* we cross this threshold.
+ // This constant essentially balances the PostTask and IPC overhead vs the
+ // responsiveness of the service. An extremely small value will cause one IPC
+ // and one PostTask for each slice but will keep the service extremely
+ // responsive. An extremely large value will batch the send for the full
+ // buffer in one large task, will hit the blocking send() once the socket
+ // buffers are full and hang the service for a bit (until the consumer
+ // catches up).
+ static constexpr size_t kApproxBytesPerTask = 32768;
+ bool has_more;
+ std::vector<TracePacket> packets =
+ ReadBuffers(tracing_session, kApproxBytesPerTask, &has_more);
+
+ if (has_more) {
+ auto weak_consumer = consumer->weak_ptr_factory_.GetWeakPtr();
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, weak_consumer, tsid] {
+ if (!weak_this || !weak_consumer)
+ return;
+ weak_this->ReadBuffersIntoConsumer(tsid, weak_consumer.get());
+ });
+ }
+
+ // Keep this as tail call, just in case the consumer re-enters.
+ consumer->consumer_->OnTraceData(std::move(packets), has_more);
+ return true;
+}
+
+bool TracingServiceImpl::ReadBuffersIntoFile(TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session) {
+ // This will be hit systematically from the PostDelayedTask. Avoid logging,
+ // it would be just spam.
+ return false;
+ }
+
+ // This can happen if the file is closed by a previous task because it reaches
+ // |max_file_size_bytes|.
+ if (!tracing_session->write_into_file)
+ return false;
+
+ if (IsWaitingForTrigger(tracing_session))
+ return false;
+
+ // ReadBuffers() can allocate memory internally, for filtering. By limiting
+ // the data that ReadBuffers() reads to kWriteIntoChunksSize per iteration,
+ // we limit the amount of memory used on each iteration.
+ //
+ // It would be tempting to split this into multiple tasks like in
+ // ReadBuffersIntoConsumer, but that's not currently possible.
+ // ReadBuffersIntoFile has to read the whole available data before returning,
+ // to support the disable_immediately=true code paths.
+ bool has_more = true;
+ bool stop_writing_into_file = false;
+ do {
+ std::vector<TracePacket> packets =
+ ReadBuffers(tracing_session, kWriteIntoFileChunkSize, &has_more);
+
+ stop_writing_into_file = WriteIntoFile(tracing_session, std::move(packets));
+ } while (has_more && !stop_writing_into_file);
+
+ if (stop_writing_into_file || tracing_session->write_period_ms == 0) {
+ // Ensure all data was written to the file before we close it.
+ base::FlushFile(tracing_session->write_into_file.get());
+ tracing_session->write_into_file.reset();
+ tracing_session->write_period_ms = 0;
+ if (tracing_session->state == TracingSession::STARTED)
+ DisableTracing(tsid);
+ return true;
+ }
+
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ if (weak_this)
+ weak_this->ReadBuffersIntoFile(tsid);
+ },
+ tracing_session->delay_to_next_write_period_ms());
+ return true;
+}
+
+bool TracingServiceImpl::IsWaitingForTrigger(TracingSession* tracing_session) {
+ // Ignore the logic below for cloned tracing sessions. In this case we
+ // actually want to read the (cloned) trace buffers even if no trigger was
+ // hit.
+ if (tracing_session->state == TracingSession::CLONED_READ_ONLY) {
+ return false;
+ }
+
+ // When a tracing session is waiting for a trigger, it is considered empty. If
+ // a tracing session finishes and moves into DISABLED without ever receiving a
+ // trigger, the trace should never return any data. This includes the
+ // synthetic packets like TraceConfig and Clock snapshots. So we bail out
+ // early and let the consumer know there is no data.
+ if (!tracing_session->config.trigger_config().triggers().empty() &&
+ tracing_session->received_triggers.empty()) {
+ PERFETTO_DLOG(
+ "ReadBuffers(): tracing session has not received a trigger yet.");
+ return true;
+ }
+
+ // Traces with CLONE_SNAPSHOT triggers are a special case of the above. They
+ // can be read only via a CloneSession() request. This is to keep the
+ // behavior consistent with the STOP_TRACING+triggers case and avoid periodic
+ // finalizations and uploads of the main CLONE_SNAPSHOT triggers.
+ if (GetTriggerMode(tracing_session->config) ==
+ TraceConfig::TriggerConfig::CLONE_SNAPSHOT) {
+ PERFETTO_DLOG(
+ "ReadBuffers(): skipping because the tracing session has "
+ "CLONE_SNAPSHOT triggers defined");
+ return true;
+ }
+
+ return false;
+}
+
+std::vector<TracePacket> TracingServiceImpl::ReadBuffers(
+ TracingSession* tracing_session,
+ size_t threshold,
+ bool* has_more) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(tracing_session);
+ *has_more = false;
+
+ std::vector<TracePacket> packets;
+ packets.reserve(1024); // Just an educated guess to avoid trivial expansions.
+
+ if (!tracing_session->initial_clock_snapshot.empty()) {
+ EmitClockSnapshot(tracing_session,
+ std::move(tracing_session->initial_clock_snapshot),
+ &packets);
+ }
+
+ for (auto& snapshot : tracing_session->clock_snapshot_ring_buffer) {
+ PERFETTO_DCHECK(!snapshot.empty());
+ EmitClockSnapshot(tracing_session, std::move(snapshot), &packets);
+ }
+ tracing_session->clock_snapshot_ring_buffer.clear();
+
+ if (tracing_session->should_emit_sync_marker) {
+ EmitSyncMarker(&packets);
+ tracing_session->should_emit_sync_marker = false;
+ }
+
+ if (!tracing_session->config.builtin_data_sources().disable_trace_config()) {
+ MaybeEmitTraceConfig(tracing_session, &packets);
+ MaybeEmitReceivedTriggers(tracing_session, &packets);
+ }
+ if (!tracing_session->did_emit_initial_packets) {
+ EmitUuid(tracing_session, &packets);
+ if (!tracing_session->config.builtin_data_sources().disable_system_info())
+ EmitSystemInfo(&packets);
+ }
+ tracing_session->did_emit_initial_packets = true;
+
+ // Note that in the proto comment, we guarantee that the tracing_started
+ // lifecycle event will be emitted before any data packets so make sure to
+ // keep this before reading the tracing buffers.
+ if (!tracing_session->config.builtin_data_sources().disable_service_events())
+ EmitLifecycleEvents(tracing_session, &packets);
+
+ // In a multi-machine tracing session, emit clock synchronization messages for
+ // remote machines.
+ if (!relay_clients_.empty())
+ MaybeEmitRemoteClockSync(tracing_session, &packets);
+
+ size_t packets_bytes = 0; // SUM(slice.size() for each slice in |packets|).
+
+ // Add up size for packets added by the Maybe* calls above.
+ for (const TracePacket& packet : packets) {
+ packets_bytes += packet.size();
+ }
+
+ bool did_hit_threshold = false;
+
+ for (size_t buf_idx = 0;
+ buf_idx < tracing_session->num_buffers() && !did_hit_threshold;
+ buf_idx++) {
+ auto tbuf_iter = buffers_.find(tracing_session->buffers_index[buf_idx]);
+ if (tbuf_iter == buffers_.end()) {
+ PERFETTO_DFATAL("Buffer not found.");
+ continue;
+ }
+ TraceBuffer& tbuf = *tbuf_iter->second;
+ tbuf.BeginRead();
+ while (!did_hit_threshold) {
+ TracePacket packet;
+ TraceBuffer::PacketSequenceProperties sequence_properties{};
+ bool previous_packet_dropped;
+ if (!tbuf.ReadNextTracePacket(&packet, &sequence_properties,
+ &previous_packet_dropped)) {
+ break;
+ }
+ packet.set_buffer_index_for_stats(static_cast<uint32_t>(buf_idx));
+ PERFETTO_DCHECK(sequence_properties.producer_id_trusted != 0);
+ PERFETTO_DCHECK(sequence_properties.writer_id != 0);
+ PERFETTO_DCHECK(sequence_properties.client_identity_trusted.has_uid());
+ // Not checking sequence_properties.client_identity_trusted.has_pid():
+ // it is false if the platform doesn't support it.
+
+ PERFETTO_DCHECK(packet.size() > 0);
+ if (!PacketStreamValidator::Validate(packet.slices())) {
+ tracing_session->invalid_packets++;
+ PERFETTO_DLOG("Dropping invalid packet");
+ continue;
+ }
+
+ // Append a slice with the trusted field data. This can't be spoofed
+ // because above we validated that the existing slices don't contain any
+ // trusted fields. For added safety we append instead of prepending
+ // because according to protobuf semantics, if the same field is
+ // encountered multiple times the last instance takes priority. Note that
+ // truncated packets are also rejected, so the producer can't give us a
+ // partial packet (e.g., a truncated string) which only becomes valid when
+ // the trusted data is appended here.
+ Slice slice = Slice::Allocate(32);
+ protozero::StaticBuffered<protos::pbzero::TracePacket> trusted_packet(
+ slice.own_data(), slice.size);
+ const auto& client_identity_trusted =
+ sequence_properties.client_identity_trusted;
+ trusted_packet->set_trusted_uid(
+ static_cast<int32_t>(client_identity_trusted.uid()));
+ trusted_packet->set_trusted_packet_sequence_id(
+ tracing_session->GetPacketSequenceID(
+ client_identity_trusted.machine_id(),
+ sequence_properties.producer_id_trusted,
+ sequence_properties.writer_id));
+ if (client_identity_trusted.has_pid()) {
+ // Not supported on all platforms.
+ trusted_packet->set_trusted_pid(
+ static_cast<int32_t>(client_identity_trusted.pid()));
+ }
+ if (client_identity_trusted.has_non_default_machine_id()) {
+ trusted_packet->set_machine_id(client_identity_trusted.machine_id());
+ }
+ if (previous_packet_dropped)
+ trusted_packet->set_previous_packet_dropped(previous_packet_dropped);
+ slice.size = trusted_packet.Finalize();
+ packet.AddSlice(std::move(slice));
+
+ // Append the packet (inclusive of the trusted uid) to |packets|.
+ packets_bytes += packet.size();
+ did_hit_threshold = packets_bytes >= threshold;
+ packets.emplace_back(std::move(packet));
+ } // for(packets...)
+ } // for(buffers...)
+
+ *has_more = did_hit_threshold;
+
+ // Only emit the "read complete" lifetime event when there is no more trace
+ // data available to read. These events are used as safe points to limit
+ // sorting in trace processor: the code shouldn't emit the event unless the
+ // buffers are empty.
+ if (!*has_more && !tracing_session->config.builtin_data_sources()
+ .disable_service_events()) {
+ // We don't bother snapshotting clocks here because we wouldn't be able to
+ // emit it and we shouldn't have significant drift from the last snapshot in
+ // any case.
+ SnapshotLifecyleEvent(tracing_session,
+ protos::pbzero::TracingServiceEvent::
+ kReadTracingBuffersCompletedFieldNumber,
+ false /* snapshot_clocks */);
+ EmitLifecycleEvents(tracing_session, &packets);
+ }
+
+ // Only emit the stats when there is no more trace data is available to read.
+ // That way, any problems that occur while reading from the buffers are
+ // reflected in the emitted stats. This is particularly important for use
+ // cases where ReadBuffers is only ever called after the tracing session is
+ // stopped.
+ if (!*has_more && tracing_session->should_emit_stats) {
+ EmitStats(tracing_session, &packets);
+ tracing_session->should_emit_stats = false;
+ }
+
+ MaybeFilterPackets(tracing_session, &packets);
+
+ MaybeCompressPackets(tracing_session, &packets);
+
+ if (!*has_more) {
+ // We've observed some extremely high memory usage by scudo after
+ // MaybeFilterPackets in the past. The original bug (b/195145848) is fixed
+ // now, but this code asks scudo to release memory just in case.
+ base::MaybeReleaseAllocatorMemToOS();
+ }
+
+ return packets;
+}
+
+void TracingServiceImpl::MaybeFilterPackets(TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ // If the tracing session specified a filter, run all packets through the
+ // filter and replace them with the filter results.
+ // The process below mantains the cardinality of input packets. Even if an
+ // entire packet is filtered out, we emit a zero-sized TracePacket proto. That
+ // makes debugging and reasoning about the trace stats easier.
+ // This place swaps the contents of each |packets| entry in place.
+ if (!tracing_session->trace_filter) {
+ return;
+ }
+ protozero::MessageFilter& trace_filter = *tracing_session->trace_filter;
+ // The filter root should be reset from protos.Trace to protos.TracePacket
+ // by the earlier call to SetFilterRoot() in EnableTracing().
+ PERFETTO_DCHECK(trace_filter.config().root_msg_index() != 0);
+ std::vector<protozero::MessageFilter::InputSlice> filter_input;
+ auto start = base::GetWallTimeNs();
+ for (TracePacket& packet : *packets) {
+ const auto& packet_slices = packet.slices();
+ const size_t input_packet_size = packet.size();
+ filter_input.clear();
+ filter_input.resize(packet_slices.size());
+ ++tracing_session->filter_input_packets;
+ tracing_session->filter_input_bytes += input_packet_size;
+ for (size_t i = 0; i < packet_slices.size(); ++i)
+ filter_input[i] = {packet_slices[i].start, packet_slices[i].size};
+ auto filtered_packet = trace_filter.FilterMessageFragments(
+ &filter_input[0], filter_input.size());
+
+ // Replace the packet in-place with the filtered one (unless failed).
+ std::optional<uint32_t> maybe_buffer_idx = packet.buffer_index_for_stats();
+ packet = TracePacket();
+ if (filtered_packet.error) {
+ ++tracing_session->filter_errors;
+ PERFETTO_DLOG("Trace packet filtering failed @ packet %" PRIu64,
+ tracing_session->filter_input_packets);
+ continue;
+ }
+ tracing_session->filter_output_bytes += filtered_packet.size;
+ if (maybe_buffer_idx.has_value()) {
+ // Keep the per-buffer stats updated. Also propagate the
+ // buffer_index_for_stats in the output packet to allow accounting by
+ // other parts of the ReadBuffer pipeline.
+ uint32_t buffer_idx = maybe_buffer_idx.value();
+ packet.set_buffer_index_for_stats(buffer_idx);
+ auto& vec = tracing_session->filter_bytes_discarded_per_buffer;
+ if (static_cast<size_t>(buffer_idx) >= vec.size())
+ vec.resize(buffer_idx + 1);
+ PERFETTO_DCHECK(input_packet_size >= filtered_packet.size);
+ size_t bytes_filtered_out = input_packet_size - filtered_packet.size;
+ vec[buffer_idx] += bytes_filtered_out;
+ }
+ AppendOwnedSlicesToPacket(std::move(filtered_packet.data),
+ filtered_packet.size, kMaxTracePacketSliceSize,
+ &packet);
+ }
+ auto end = base::GetWallTimeNs();
+ tracing_session->filter_time_taken_ns +=
+ static_cast<uint64_t>((end - start).count());
+}
+
+void TracingServiceImpl::MaybeCompressPackets(
+ TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ if (!tracing_session->compress_deflate) {
+ return;
+ }
+
+ init_opts_.compressor_fn(packets);
+}
+
+bool TracingServiceImpl::WriteIntoFile(TracingSession* tracing_session,
+ std::vector<TracePacket> packets) {
+ if (!tracing_session->write_into_file) {
+ return false;
+ }
+ const uint64_t max_size = tracing_session->max_file_size_bytes
+ ? tracing_session->max_file_size_bytes
+ : std::numeric_limits<size_t>::max();
+
+ size_t total_slices = 0;
+ for (const TracePacket& packet : packets) {
+ total_slices += packet.slices().size();
+ }
+ // When writing into a file, the file should look like a root trace.proto
+ // message. Each packet should be prepended with a proto preamble stating
+ // its field id (within trace.proto) and size. Hence the addition below.
+ const size_t max_iovecs = total_slices + packets.size();
+
+ size_t num_iovecs = 0;
+ bool stop_writing_into_file = false;
+ std::unique_ptr<struct iovec[]> iovecs(new struct iovec[max_iovecs]);
+ size_t num_iovecs_at_last_packet = 0;
+ uint64_t bytes_about_to_be_written = 0;
+ for (TracePacket& packet : packets) {
+ std::tie(iovecs[num_iovecs].iov_base, iovecs[num_iovecs].iov_len) =
+ packet.GetProtoPreamble();
+ bytes_about_to_be_written += iovecs[num_iovecs].iov_len;
+ num_iovecs++;
+ for (const Slice& slice : packet.slices()) {
+ // writev() doesn't change the passed pointer. However, struct iovec
+ // take a non-const ptr because it's the same struct used by readv().
+ // Hence the const_cast here.
+ char* start = static_cast<char*>(const_cast<void*>(slice.start));
+ bytes_about_to_be_written += slice.size;
+ iovecs[num_iovecs++] = {start, slice.size};
+ }
+
+ if (tracing_session->bytes_written_into_file + bytes_about_to_be_written >=
+ max_size) {
+ stop_writing_into_file = true;
+ num_iovecs = num_iovecs_at_last_packet;
+ break;
+ }
+
+ num_iovecs_at_last_packet = num_iovecs;
+ }
+ PERFETTO_DCHECK(num_iovecs <= max_iovecs);
+ int fd = *tracing_session->write_into_file;
+
+ uint64_t total_wr_size = 0;
+
+ // writev() can take at most IOV_MAX entries per call. Batch them.
+ constexpr size_t kIOVMax = IOV_MAX;
+ for (size_t i = 0; i < num_iovecs; i += kIOVMax) {
+ int iov_batch_size = static_cast<int>(std::min(num_iovecs - i, kIOVMax));
+ ssize_t wr_size = PERFETTO_EINTR(writev(fd, &iovecs[i], iov_batch_size));
+ if (wr_size <= 0) {
+ PERFETTO_PLOG("writev() failed");
+ stop_writing_into_file = true;
+ break;
+ }
+ total_wr_size += static_cast<size_t>(wr_size);
+ }
+
+ tracing_session->bytes_written_into_file += total_wr_size;
+
+ PERFETTO_DLOG("Draining into file, written: %" PRIu64 " KB, stop: %d",
+ (total_wr_size + 1023) / 1024, stop_writing_into_file);
+ return stop_writing_into_file;
+}
+
+void TracingServiceImpl::FreeBuffers(TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Freeing buffers for session %" PRIu64, tsid);
+ TracingSession* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session) {
+ PERFETTO_DLOG("FreeBuffers() failed, invalid session ID %" PRIu64, tsid);
+ return; // TODO(primiano): signal failure?
+ }
+ DisableTracing(tsid, /*disable_immediately=*/true);
+
+ PERFETTO_DCHECK(tracing_session->AllDataSourceInstancesStopped());
+ tracing_session->data_source_instances.clear();
+
+ for (auto& producer_entry : producers_) {
+ ProducerEndpointImpl* producer = producer_entry.second;
+ producer->OnFreeBuffers(tracing_session->buffers_index);
+ }
+
+ for (BufferID buffer_id : tracing_session->buffers_index) {
+ buffer_ids_.Free(buffer_id);
+ PERFETTO_DCHECK(buffers_.count(buffer_id) == 1);
+ buffers_.erase(buffer_id);
+ }
+ bool notify_traceur =
+ tracing_session->config.notify_traceur() &&
+ tracing_session->state != TracingSession::CLONED_READ_ONLY;
+ bool is_long_trace =
+ (tracing_session->config.write_into_file() &&
+ tracing_session->config.file_write_period_ms() < kMillisPerDay);
+ tracing_sessions_.erase(tsid);
+ tracing_session = nullptr;
+ UpdateMemoryGuardrail();
+
+ PERFETTO_LOG("Tracing session %" PRIu64 " ended, total sessions:%zu", tsid,
+ tracing_sessions_.size());
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) && \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ if (notify_traceur && is_long_trace) {
+ PERFETTO_LAZY_LOAD(android_internal::NotifyTraceSessionEnded, notify_fn);
+ if (!notify_fn || !notify_fn(/*session_stolen=*/false))
+ PERFETTO_ELOG("Failed to notify Traceur long tracing has ended");
+ }
+#else
+ base::ignore_result(notify_traceur);
+ base::ignore_result(is_long_trace);
+#endif
+}
+
+void TracingServiceImpl::RegisterDataSource(ProducerID producer_id,
+ const DataSourceDescriptor& desc) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (desc.name().empty()) {
+ PERFETTO_DLOG("Received RegisterDataSource() with empty name");
+ return;
+ }
+
+ ProducerEndpointImpl* producer = GetProducer(producer_id);
+ if (!producer) {
+ PERFETTO_DFATAL("Producer not found.");
+ return;
+ }
+
+ // Check that the producer doesn't register two data sources with the same ID.
+ // Note that we tolerate |id| == 0 because until Android T / v22 the |id|
+ // field didn't exist.
+ for (const auto& kv : data_sources_) {
+ if (desc.id() && kv.second.producer_id == producer_id &&
+ kv.second.descriptor.id() == desc.id()) {
+ PERFETTO_ELOG(
+ "Failed to register data source \"%s\". A data source with the same "
+ "id %" PRIu64 " (name=\"%s\") is already registered for producer %d",
+ desc.name().c_str(), desc.id(), kv.second.descriptor.name().c_str(),
+ producer_id);
+ return;
+ }
+ }
+
+ PERFETTO_DLOG("Producer %" PRIu16 " registered data source \"%s\"",
+ producer_id, desc.name().c_str());
+
+ auto reg_ds = data_sources_.emplace(desc.name(),
+ RegisteredDataSource{producer_id, desc});
+
+ // If there are existing tracing sessions, we need to check if the new
+ // data source is enabled by any of them.
+ for (auto& iter : tracing_sessions_) {
+ TracingSession& tracing_session = iter.second;
+ if (tracing_session.state != TracingSession::STARTED &&
+ tracing_session.state != TracingSession::CONFIGURED) {
+ continue;
+ }
+
+ TraceConfig::ProducerConfig producer_config;
+ for (const auto& config : tracing_session.config.producers()) {
+ if (producer->name_ == config.producer_name()) {
+ producer_config = config;
+ break;
+ }
+ }
+ for (const TraceConfig::DataSource& cfg_data_source :
+ tracing_session.config.data_sources()) {
+ if (cfg_data_source.config().name() != desc.name())
+ continue;
+ DataSourceInstance* ds_inst = SetupDataSource(
+ cfg_data_source, producer_config, reg_ds->second, &tracing_session);
+ if (ds_inst && tracing_session.state == TracingSession::STARTED)
+ StartDataSourceInstance(producer, &tracing_session, ds_inst);
+ }
+ } // for(iter : tracing_sessions_)
+}
+
+void TracingServiceImpl::UpdateDataSource(
+ ProducerID producer_id,
+ const DataSourceDescriptor& new_desc) {
+ if (new_desc.id() == 0) {
+ PERFETTO_ELOG("UpdateDataSource() must have a non-zero id");
+ return;
+ }
+
+ // If this producer has already registered a matching descriptor name and id,
+ // just update the descriptor.
+ RegisteredDataSource* data_source = nullptr;
+ auto range = data_sources_.equal_range(new_desc.name());
+ for (auto it = range.first; it != range.second; ++it) {
+ if (it->second.producer_id == producer_id &&
+ it->second.descriptor.id() == new_desc.id()) {
+ data_source = &it->second;
+ break;
+ }
+ }
+
+ if (!data_source) {
+ PERFETTO_ELOG(
+ "UpdateDataSource() failed, could not find an existing data source "
+ "with name=\"%s\" id=%" PRIu64,
+ new_desc.name().c_str(), new_desc.id());
+ return;
+ }
+
+ data_source->descriptor = new_desc;
+}
+
+void TracingServiceImpl::StopDataSourceInstance(ProducerEndpointImpl* producer,
+ TracingSession* tracing_session,
+ DataSourceInstance* instance,
+ bool disable_immediately) {
+ const DataSourceInstanceID ds_inst_id = instance->instance_id;
+ if (instance->will_notify_on_stop && !disable_immediately) {
+ instance->state = DataSourceInstance::STOPPING;
+ } else {
+ instance->state = DataSourceInstance::STOPPED;
+ }
+ if (tracing_session->consumer_maybe_null) {
+ tracing_session->consumer_maybe_null->OnDataSourceInstanceStateChange(
+ *producer, *instance);
+ }
+ producer->StopDataSource(ds_inst_id);
+}
+
+void TracingServiceImpl::UnregisterDataSource(ProducerID producer_id,
+ const std::string& name) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Producer %" PRIu16 " unregistered data source \"%s\"",
+ producer_id, name.c_str());
+ PERFETTO_CHECK(producer_id);
+ ProducerEndpointImpl* producer = GetProducer(producer_id);
+ PERFETTO_DCHECK(producer);
+ for (auto& kv : tracing_sessions_) {
+ auto& ds_instances = kv.second.data_source_instances;
+ bool removed = false;
+ for (auto it = ds_instances.begin(); it != ds_instances.end();) {
+ if (it->first == producer_id && it->second.data_source_name == name) {
+ DataSourceInstanceID ds_inst_id = it->second.instance_id;
+ if (it->second.state != DataSourceInstance::STOPPED) {
+ if (it->second.state != DataSourceInstance::STOPPING) {
+ StopDataSourceInstance(producer, &kv.second, &it->second,
+ /* disable_immediately = */ false);
+ }
+
+ // Mark the instance as stopped immediately, since we are
+ // unregistering it below.
+ //
+ // The StopDataSourceInstance above might have set the state to
+ // STOPPING so this condition isn't an else.
+ if (it->second.state == DataSourceInstance::STOPPING)
+ NotifyDataSourceStopped(producer_id, ds_inst_id);
+ }
+ it = ds_instances.erase(it);
+ removed = true;
+ } else {
+ ++it;
+ }
+ } // for (data_source_instances)
+ if (removed)
+ MaybeNotifyAllDataSourcesStarted(&kv.second);
+ } // for (tracing_session)
+
+ for (auto it = data_sources_.begin(); it != data_sources_.end(); ++it) {
+ if (it->second.producer_id == producer_id &&
+ it->second.descriptor.name() == name) {
+ data_sources_.erase(it);
+ return;
+ }
+ }
+
+ PERFETTO_DFATAL(
+ "Tried to unregister a non-existent data source \"%s\" for "
+ "producer %" PRIu16,
+ name.c_str(), producer_id);
+}
+
+TracingServiceImpl::DataSourceInstance* TracingServiceImpl::SetupDataSource(
+ const TraceConfig::DataSource& cfg_data_source,
+ const TraceConfig::ProducerConfig& producer_config,
+ const RegisteredDataSource& data_source,
+ TracingSession* tracing_session) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ ProducerEndpointImpl* producer = GetProducer(data_source.producer_id);
+ PERFETTO_DCHECK(producer);
+ // An existing producer that is not ftrace could have registered itself as
+ // ftrace, we must not enable it in that case.
+ if (lockdown_mode_ && producer->uid() != uid_) {
+ PERFETTO_DLOG("Lockdown mode: not enabling producer %hu", producer->id_);
+ return nullptr;
+ }
+ // TODO(primiano): Add tests for registration ordering (data sources vs
+ // consumers).
+ if (!NameMatchesFilter(producer->name_,
+ cfg_data_source.producer_name_filter(),
+ cfg_data_source.producer_name_regex_filter())) {
+ PERFETTO_DLOG("Data source: %s is filtered out for producer: %s",
+ cfg_data_source.config().name().c_str(),
+ producer->name_.c_str());
+ return nullptr;
+ }
+
+ auto relative_buffer_id = cfg_data_source.config().target_buffer();
+ if (relative_buffer_id >= tracing_session->num_buffers()) {
+ PERFETTO_LOG(
+ "The TraceConfig for DataSource %s specified a target_buffer out of "
+ "bound (%d). Skipping it.",
+ cfg_data_source.config().name().c_str(), relative_buffer_id);
+ return nullptr;
+ }
+
+ // Create a copy of the DataSourceConfig specified in the trace config. This
+ // will be passed to the producer after translating the |target_buffer| id.
+ // The |target_buffer| parameter passed by the consumer in the trace config is
+ // relative to the buffers declared in the same trace config. This has to be
+ // translated to the global BufferID before passing it to the producers, which
+ // don't know anything about tracing sessions and consumers.
+
+ DataSourceInstanceID inst_id = ++last_data_source_instance_id_;
+ auto insert_iter = tracing_session->data_source_instances.emplace(
+ std::piecewise_construct, //
+ std::forward_as_tuple(producer->id_),
+ std::forward_as_tuple(
+ inst_id,
+ cfg_data_source.config(), // Deliberate copy.
+ data_source.descriptor.name(),
+ data_source.descriptor.will_notify_on_start(),
+ data_source.descriptor.will_notify_on_stop(),
+ data_source.descriptor.handles_incremental_state_clear(),
+ data_source.descriptor.no_flush()));
+ DataSourceInstance* ds_instance = &insert_iter->second;
+
+ // New data source instance starts out in CONFIGURED state.
+ if (tracing_session->consumer_maybe_null) {
+ tracing_session->consumer_maybe_null->OnDataSourceInstanceStateChange(
+ *producer, *ds_instance);
+ }
+
+ DataSourceConfig& ds_config = ds_instance->config;
+ ds_config.set_trace_duration_ms(tracing_session->config.duration_ms());
+
+ // Rationale for `if (prefer) set_prefer(true)`, rather than `set(prefer)`:
+ // ComputeStartupConfigHash() in tracing_muxer_impl.cc compares hashes of the
+ // DataSourceConfig and expects to know (and clear) the fields generated by
+ // the tracing service. Unconditionally adding a new field breaks backward
+ // compatibility of startup tracing with older SDKs, because the serialization
+ // also propagates unkonwn fields, breaking the hash matching check.
+ if (tracing_session->config.prefer_suspend_clock_for_duration())
+ ds_config.set_prefer_suspend_clock_for_duration(true);
+
+ ds_config.set_stop_timeout_ms(tracing_session->data_source_stop_timeout_ms());
+ ds_config.set_enable_extra_guardrails(
+ tracing_session->config.enable_extra_guardrails());
+ if (tracing_session->consumer_uid == 1066 /* AID_STATSD */ &&
+ tracing_session->config.statsd_metadata().triggering_config_uid() !=
+ 2000 /* AID_SHELL */
+ && tracing_session->config.statsd_metadata().triggering_config_uid() !=
+ 0 /* AID_ROOT */) {
+ // StatsD can be triggered either by shell, root or an app that has DUMP and
+ // USAGE_STATS permission. When triggered by shell or root, we do not want
+ // to consider the trace a trusted system trace, as it was initiated by the
+ // user. Otherwise, it has to come from an app with DUMP and
+ // PACKAGE_USAGE_STATS, which has to be preinstalled and trusted by the
+ // system.
+ // Check for shell / root: https://bit.ly/3b7oZNi
+ // Check for DUMP or PACKAGE_USAGE_STATS: https://bit.ly/3ep0NrR
+ ds_config.set_session_initiator(
+ DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM);
+ } else {
+ // Unset in case the consumer set it.
+ // We need to be able to trust this field.
+ ds_config.set_session_initiator(
+ DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED);
+ }
+ ds_config.set_tracing_session_id(tracing_session->id);
+ BufferID global_id = tracing_session->buffers_index[relative_buffer_id];
+ PERFETTO_DCHECK(global_id);
+ ds_config.set_target_buffer(global_id);
+
+ PERFETTO_DLOG("Setting up data source %s with target buffer %" PRIu16,
+ ds_config.name().c_str(), global_id);
+ if (!producer->shared_memory()) {
+ // Determine the SMB page size. Must be an integer multiple of 4k.
+ // As for the SMB size below, the decision tree is as follows:
+ // 1. Give priority to what is defined in the trace config.
+ // 2. If unset give priority to the hint passed by the producer.
+ // 3. Keep within bounds and ensure it's a multiple of 4k.
+ size_t page_size = producer_config.page_size_kb() * 1024;
+ if (page_size == 0)
+ page_size = producer->shmem_page_size_hint_bytes_;
+
+ // Determine the SMB size. Must be an integer multiple of the SMB page size.
+ // The decision tree is as follows:
+ // 1. Give priority to what defined in the trace config.
+ // 2. If unset give priority to the hint passed by the producer.
+ // 3. Keep within bounds and ensure it's a multiple of the page size.
+ size_t shm_size = producer_config.shm_size_kb() * 1024;
+ if (shm_size == 0)
+ shm_size = producer->shmem_size_hint_bytes_;
+
+ auto valid_sizes = EnsureValidShmSizes(shm_size, page_size);
+ if (valid_sizes != std::tie(shm_size, page_size)) {
+ PERFETTO_DLOG(
+ "Invalid configured SMB sizes: shm_size %zu page_size %zu. Falling "
+ "back to shm_size %zu page_size %zu.",
+ shm_size, page_size, std::get<0>(valid_sizes),
+ std::get<1>(valid_sizes));
+ }
+ std::tie(shm_size, page_size) = valid_sizes;
+
+ // TODO(primiano): right now Create() will suicide in case of OOM if the
+ // mmap fails. We should instead gracefully fail the request and tell the
+ // client to go away.
+ PERFETTO_DLOG("Creating SMB of %zu KB for producer \"%s\"", shm_size / 1024,
+ producer->name_.c_str());
+ auto shared_memory = shm_factory_->CreateSharedMemory(shm_size);
+ producer->SetupSharedMemory(std::move(shared_memory), page_size,
+ /*provided_by_producer=*/false);
+ }
+ producer->SetupDataSource(inst_id, ds_config);
+ return ds_instance;
+}
+
+// Note: all the fields % *_trusted ones are untrusted, as in, the Producer
+// might be lying / returning garbage contents. |src| and |size| can be trusted
+// in terms of being a valid pointer, but not the contents.
+void TracingServiceImpl::CopyProducerPageIntoLogBuffer(
+ ProducerID producer_id_trusted,
+ const ClientIdentity& client_identity_trusted,
+ WriterID writer_id,
+ ChunkID chunk_id,
+ BufferID buffer_id,
+ uint16_t num_fragments,
+ uint8_t chunk_flags,
+ bool chunk_complete,
+ const uint8_t* src,
+ size_t size) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ ProducerEndpointImpl* producer = GetProducer(producer_id_trusted);
+ if (!producer) {
+ PERFETTO_DFATAL("Producer not found.");
+ chunks_discarded_++;
+ return;
+ }
+
+ TraceBuffer* buf = GetBufferByID(buffer_id);
+ if (!buf) {
+ PERFETTO_DLOG("Could not find target buffer %" PRIu16
+ " for producer %" PRIu16,
+ buffer_id, producer_id_trusted);
+ chunks_discarded_++;
+ return;
+ }
+
+ // Verify that the producer is actually allowed to write into the target
+ // buffer specified in the request. This prevents a malicious producer from
+ // injecting data into a log buffer that belongs to a tracing session the
+ // producer is not part of.
+ if (!producer->is_allowed_target_buffer(buffer_id)) {
+ PERFETTO_ELOG("Producer %" PRIu16
+ " tried to write into forbidden target buffer %" PRIu16,
+ producer_id_trusted, buffer_id);
+ PERFETTO_DFATAL("Forbidden target buffer");
+ chunks_discarded_++;
+ return;
+ }
+
+ // If the writer was registered by the producer, it should only write into the
+ // buffer it was registered with.
+ std::optional<BufferID> associated_buffer =
+ producer->buffer_id_for_writer(writer_id);
+ if (associated_buffer && *associated_buffer != buffer_id) {
+ PERFETTO_ELOG("Writer %" PRIu16 " of producer %" PRIu16
+ " was registered to write into target buffer %" PRIu16
+ ", but tried to write into buffer %" PRIu16,
+ writer_id, producer_id_trusted, *associated_buffer,
+ buffer_id);
+ PERFETTO_DFATAL("Wrong target buffer");
+ chunks_discarded_++;
+ return;
+ }
+
+ buf->CopyChunkUntrusted(producer_id_trusted, client_identity_trusted,
+ writer_id, chunk_id, num_fragments, chunk_flags,
+ chunk_complete, src, size);
+}
+
+void TracingServiceImpl::ApplyChunkPatches(
+ ProducerID producer_id_trusted,
+ const std::vector<CommitDataRequest::ChunkToPatch>& chunks_to_patch) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ for (const auto& chunk : chunks_to_patch) {
+ const ChunkID chunk_id = static_cast<ChunkID>(chunk.chunk_id());
+ const WriterID writer_id = static_cast<WriterID>(chunk.writer_id());
+ TraceBuffer* buf =
+ GetBufferByID(static_cast<BufferID>(chunk.target_buffer()));
+ static_assert(std::numeric_limits<ChunkID>::max() == kMaxChunkID,
+ "Add a '|| chunk_id > kMaxChunkID' below if this fails");
+ if (!writer_id || writer_id > kMaxWriterID || !buf) {
+ // This can genuinely happen when the trace is stopped. The producers
+ // might see the stop signal with some delay and try to keep sending
+ // patches left soon after.
+ PERFETTO_DLOG(
+ "Received invalid chunks_to_patch request from Producer: %" PRIu16
+ ", BufferID: %" PRIu32 " ChunkdID: %" PRIu32 " WriterID: %" PRIu16,
+ producer_id_trusted, chunk.target_buffer(), chunk_id, writer_id);
+ patches_discarded_ += static_cast<uint64_t>(chunk.patches_size());
+ continue;
+ }
+
+ // Note, there's no need to validate that the producer is allowed to write
+ // to the specified buffer ID (or that it's the correct buffer ID for a
+ // registered TraceWriter). That's because TraceBuffer uses the producer ID
+ // and writer ID to look up the chunk to patch. If the producer specifies an
+ // incorrect buffer, this lookup will fail and TraceBuffer will ignore the
+ // patches. Because the producer ID is trusted, there's also no way for a
+ // malicious producer to patch another producer's data.
+
+ // Speculate on the fact that there are going to be a limited amount of
+ // patches per request, so we can allocate the |patches| array on the stack.
+ std::array<TraceBuffer::Patch, 1024> patches; // Uninitialized.
+ if (chunk.patches().size() > patches.size()) {
+ PERFETTO_ELOG("Too many patches (%zu) batched in the same request",
+ patches.size());
+ PERFETTO_DFATAL("Too many patches");
+ patches_discarded_ += static_cast<uint64_t>(chunk.patches_size());
+ continue;
+ }
+
+ size_t i = 0;
+ for (const auto& patch : chunk.patches()) {
+ const std::string& patch_data = patch.data();
+ if (patch_data.size() != patches[i].data.size()) {
+ PERFETTO_ELOG("Received patch from producer: %" PRIu16
+ " of unexpected size %zu",
+ producer_id_trusted, patch_data.size());
+ patches_discarded_++;
+ continue;
+ }
+ patches[i].offset_untrusted = patch.offset();
+ memcpy(&patches[i].data[0], patch_data.data(), patches[i].data.size());
+ i++;
+ }
+ buf->TryPatchChunkContents(producer_id_trusted, writer_id, chunk_id,
+ &patches[0], i, chunk.has_more_patches());
+ }
+}
+
+TracingServiceImpl::TracingSession* TracingServiceImpl::GetDetachedSession(
+ uid_t uid,
+ const std::string& key) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ for (auto& kv : tracing_sessions_) {
+ TracingSession* session = &kv.second;
+ if (session->consumer_uid == uid && session->detach_key == key) {
+ PERFETTO_DCHECK(session->consumer_maybe_null == nullptr);
+ return session;
+ }
+ }
+ return nullptr;
+}
+
+TracingServiceImpl::TracingSession* TracingServiceImpl::GetTracingSession(
+ TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto it = tsid ? tracing_sessions_.find(tsid) : tracing_sessions_.end();
+ if (it == tracing_sessions_.end())
+ return nullptr;
+ return &it->second;
+}
+
+TracingServiceImpl::TracingSession*
+TracingServiceImpl::FindTracingSessionWithMaxBugreportScore() {
+ TracingSession* max_session = nullptr;
+ for (auto& session_id_and_session : tracing_sessions_) {
+ auto& session = session_id_and_session.second;
+ const int32_t score = session.config.bugreport_score();
+ // Exclude sessions with 0 (or below) score. By default tracing sessions
+ // should NOT be eligible to be attached to bugreports.
+ if (score <= 0 || session.state != TracingSession::STARTED)
+ continue;
+
+ if (!max_session || score > max_session->config.bugreport_score())
+ max_session = &session;
+ }
+ return max_session;
+}
+
+ProducerID TracingServiceImpl::GetNextProducerID() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_CHECK(producers_.size() < kMaxProducerID);
+ do {
+ ++last_producer_id_;
+ } while (producers_.count(last_producer_id_) || last_producer_id_ == 0);
+ PERFETTO_DCHECK(last_producer_id_ > 0 && last_producer_id_ <= kMaxProducerID);
+ return last_producer_id_;
+}
+
+TraceBuffer* TracingServiceImpl::GetBufferByID(BufferID buffer_id) {
+ auto buf_iter = buffers_.find(buffer_id);
+ if (buf_iter == buffers_.end())
+ return nullptr;
+ return &*buf_iter->second;
+}
+
+void TracingServiceImpl::OnStartTriggersTimeout(TracingSessionID tsid) {
+ // Skip entirely the flush if the trace session doesn't exist anymore.
+ // This is to prevent misleading error messages to be logged.
+ //
+ // if the trace has started from the trigger we rely on
+ // the |stop_delay_ms| from the trigger so don't flush and
+ // disable if we've moved beyond a CONFIGURED state
+ auto* tracing_session_ptr = GetTracingSession(tsid);
+ if (tracing_session_ptr &&
+ tracing_session_ptr->state == TracingSession::CONFIGURED) {
+ PERFETTO_DLOG("Disabling TracingSession %" PRIu64
+ " since no triggers activated.",
+ tsid);
+ // No data should be returned from ReadBuffers() regardless of if we
+ // call FreeBuffers() or DisableTracing(). This is because in
+ // STOP_TRACING we need this promise in either case, and using
+ // DisableTracing() allows a graceful shutdown. Consumers can follow
+ // their normal path and check the buffers through ReadBuffers() and
+ // the code won't hang because the tracing session will still be
+ // alive just disabled.
+ DisableTracing(tsid);
+ }
+}
+
+void TracingServiceImpl::UpdateMemoryGuardrail() {
+#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
+ uint64_t total_buffer_bytes = 0;
+
+ // Sum up all the shared memory buffers.
+ for (const auto& id_to_producer : producers_) {
+ if (id_to_producer.second->shared_memory())
+ total_buffer_bytes += id_to_producer.second->shared_memory()->size();
+ }
+
+ // Sum up all the trace buffers.
+ for (const auto& id_to_buffer : buffers_) {
+ total_buffer_bytes += id_to_buffer.second->size();
+ }
+
+ // Sum up all the cloned traced buffers.
+ for (const auto& id_to_ts : tracing_sessions_) {
+ const TracingSession& ts = id_to_ts.second;
+ for (const auto& id_to_pending_clone : ts.pending_clones) {
+ const PendingClone& pending_clone = id_to_pending_clone.second;
+ for (const std::unique_ptr<TraceBuffer>& buf : pending_clone.buffers) {
+ if (buf) {
+ total_buffer_bytes += buf->size();
+ }
+ }
+ }
+ }
+
+ // Set the guard rail to 32MB + the sum of all the buffers over a 30 second
+ // interval.
+ uint64_t guardrail = base::kWatchdogDefaultMemorySlack + total_buffer_bytes;
+ base::Watchdog::GetInstance()->SetMemoryLimit(guardrail, 30 * 1000);
+#endif
+}
+
+void TracingServiceImpl::PeriodicSnapshotTask(TracingSessionID tsid) {
+ auto* tracing_session = GetTracingSession(tsid);
+ if (!tracing_session)
+ return;
+ if (tracing_session->state != TracingSession::STARTED)
+ return;
+ tracing_session->should_emit_sync_marker = true;
+ tracing_session->should_emit_stats = true;
+ MaybeSnapshotClocksIntoRingBuffer(tracing_session);
+}
+
+void TracingServiceImpl::SnapshotLifecyleEvent(TracingSession* tracing_session,
+ uint32_t field_id,
+ bool snapshot_clocks) {
+ // field_id should be an id of a field in TracingServiceEvent.
+ auto& lifecycle_events = tracing_session->lifecycle_events;
+ auto event_it =
+ std::find_if(lifecycle_events.begin(), lifecycle_events.end(),
+ [field_id](const TracingSession::LifecycleEvent& event) {
+ return event.field_id == field_id;
+ });
+
+ TracingSession::LifecycleEvent* event;
+ if (event_it == lifecycle_events.end()) {
+ lifecycle_events.emplace_back(field_id);
+ event = &lifecycle_events.back();
+ } else {
+ event = &*event_it;
+ }
+
+ // Snapshot the clocks before capturing the timestamp for the event so we can
+ // use this snapshot to resolve the event timestamp if necessary.
+ if (snapshot_clocks)
+ MaybeSnapshotClocksIntoRingBuffer(tracing_session);
+
+ // Erase before emplacing to prevent a unncessary doubling of memory if
+ // not needed.
+ if (event->timestamps.size() >= event->max_size) {
+ event->timestamps.erase_front(1 + event->timestamps.size() -
+ event->max_size);
+ }
+ event->timestamps.emplace_back(base::GetBootTimeNs().count());
+}
+
+void TracingServiceImpl::MaybeSnapshotClocksIntoRingBuffer(
+ TracingSession* tracing_session) {
+ if (tracing_session->config.builtin_data_sources()
+ .disable_clock_snapshotting()) {
+ return;
+ }
+
+ // We are making an explicit copy of the latest snapshot (if it exists)
+ // because SnapshotClocks reads this data and computes the drift based on its
+ // content. If the clock drift is high enough, it will update the contents of
+ // |snapshot| and return true. Otherwise, it will return false.
+ TracingSession::ClockSnapshotData snapshot =
+ tracing_session->clock_snapshot_ring_buffer.empty()
+ ? TracingSession::ClockSnapshotData()
+ : tracing_session->clock_snapshot_ring_buffer.back();
+ bool did_update = SnapshotClocks(&snapshot);
+ if (did_update) {
+ // This means clocks drifted enough since last snapshot. See the comment
+ // in SnapshotClocks.
+ auto* snapshot_buffer = &tracing_session->clock_snapshot_ring_buffer;
+
+ // Erase before emplacing to prevent a unncessary doubling of memory if
+ // not needed.
+ static constexpr uint32_t kClockSnapshotRingBufferSize = 16;
+ if (snapshot_buffer->size() >= kClockSnapshotRingBufferSize) {
+ snapshot_buffer->erase_front(1 + snapshot_buffer->size() -
+ kClockSnapshotRingBufferSize);
+ }
+ snapshot_buffer->emplace_back(std::move(snapshot));
+ }
+}
+
+// Returns true when the data in |snapshot_data| is updated with the new state
+// of the clocks and false otherwise.
+bool TracingServiceImpl::SnapshotClocks(
+ TracingSession::ClockSnapshotData* snapshot_data) {
+ // Minimum drift that justifies replacing a prior clock snapshot that hasn't
+ // been emitted into the trace yet (see comment below).
+ static constexpr int64_t kSignificantDriftNs = 10 * 1000 * 1000; // 10 ms
+
+ TracingSession::ClockSnapshotData new_snapshot_data = CaptureClockSnapshots();
+ // If we're about to update a session's latest clock snapshot that hasn't been
+ // emitted into the trace yet, check whether the clocks have drifted enough to
+ // warrant overriding the current snapshot values. The older snapshot would be
+ // valid for a larger part of the currently buffered trace data because the
+ // clock sync protocol in trace processor uses the latest clock <= timestamp
+ // to translate times (see https://perfetto.dev/docs/concepts/clock-sync), so
+ // we try to keep it if we can.
+ if (!snapshot_data->empty()) {
+ PERFETTO_DCHECK(snapshot_data->size() == new_snapshot_data.size());
+ PERFETTO_DCHECK((*snapshot_data)[0].clock_id ==
+ protos::gen::BUILTIN_CLOCK_BOOTTIME);
+
+ bool update_snapshot = false;
+ uint64_t old_boot_ns = (*snapshot_data)[0].timestamp;
+ uint64_t new_boot_ns = new_snapshot_data[0].timestamp;
+ int64_t boot_diff =
+ static_cast<int64_t>(new_boot_ns) - static_cast<int64_t>(old_boot_ns);
+
+ for (size_t i = 1; i < snapshot_data->size(); i++) {
+ uint64_t old_ns = (*snapshot_data)[i].timestamp;
+ uint64_t new_ns = new_snapshot_data[i].timestamp;
+
+ int64_t diff =
+ static_cast<int64_t>(new_ns) - static_cast<int64_t>(old_ns);
+
+ // Compare the boottime delta against the delta of this clock.
+ if (std::abs(boot_diff - diff) >= kSignificantDriftNs) {
+ update_snapshot = true;
+ break;
+ }
+ }
+ if (!update_snapshot)
+ return false;
+ snapshot_data->clear();
+ }
+
+ *snapshot_data = std::move(new_snapshot_data);
+ return true;
+}
+
+void TracingServiceImpl::EmitClockSnapshot(
+ TracingSession* tracing_session,
+ TracingSession::ClockSnapshotData snapshot_data,
+ std::vector<TracePacket>* packets) {
+ PERFETTO_DCHECK(!tracing_session->config.builtin_data_sources()
+ .disable_clock_snapshotting());
+
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ auto* snapshot = packet->set_clock_snapshot();
+
+ protos::gen::BuiltinClock trace_clock =
+ tracing_session->config.builtin_data_sources().primary_trace_clock();
+ if (!trace_clock)
+ trace_clock = protos::gen::BUILTIN_CLOCK_BOOTTIME;
+ snapshot->set_primary_trace_clock(
+ static_cast<protos::pbzero::BuiltinClock>(trace_clock));
+
+ for (auto& clock_id_and_ts : snapshot_data) {
+ auto* c = snapshot->add_clocks();
+ c->set_clock_id(clock_id_and_ts.clock_id);
+ c->set_timestamp(clock_id_and_ts.timestamp);
+ }
+
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+ SerializeAndAppendPacket(packets, packet.SerializeAsArray());
+}
+
+void TracingServiceImpl::EmitSyncMarker(std::vector<TracePacket>* packets) {
+ // The sync marks are used to tokenize large traces efficiently.
+ // See description in trace_packet.proto.
+ if (sync_marker_packet_size_ == 0) {
+ // The marker ABI expects that the marker is written after the uid.
+ // Protozero guarantees that fields are written in the same order of the
+ // calls. The ResynchronizeTraceStreamUsingSyncMarker test verifies the ABI.
+ protozero::StaticBuffered<protos::pbzero::TracePacket> packet(
+ &sync_marker_packet_[0], sizeof(sync_marker_packet_));
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+
+ // Keep this last.
+ packet->set_synchronization_marker(kSyncMarker, sizeof(kSyncMarker));
+ sync_marker_packet_size_ = packet.Finalize();
+ }
+ packets->emplace_back();
+ packets->back().AddSlice(&sync_marker_packet_[0], sync_marker_packet_size_);
+}
+
+void TracingServiceImpl::EmitStats(TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+ GetTraceStats(tracing_session).Serialize(packet->set_trace_stats());
+ SerializeAndAppendPacket(packets, packet.SerializeAsArray());
+}
+
+TraceStats TracingServiceImpl::GetTraceStats(TracingSession* tracing_session) {
+ TraceStats trace_stats;
+ trace_stats.set_producers_connected(static_cast<uint32_t>(producers_.size()));
+ trace_stats.set_producers_seen(last_producer_id_);
+ trace_stats.set_data_sources_registered(
+ static_cast<uint32_t>(data_sources_.size()));
+ trace_stats.set_data_sources_seen(last_data_source_instance_id_);
+ trace_stats.set_tracing_sessions(
+ static_cast<uint32_t>(tracing_sessions_.size()));
+ trace_stats.set_total_buffers(static_cast<uint32_t>(buffers_.size()));
+ trace_stats.set_chunks_discarded(chunks_discarded_);
+ trace_stats.set_patches_discarded(patches_discarded_);
+ trace_stats.set_invalid_packets(tracing_session->invalid_packets);
+ trace_stats.set_flushes_requested(tracing_session->flushes_requested);
+ trace_stats.set_flushes_succeeded(tracing_session->flushes_succeeded);
+ trace_stats.set_flushes_failed(tracing_session->flushes_failed);
+ trace_stats.set_final_flush_outcome(tracing_session->final_flush_outcome);
+
+ if (tracing_session->trace_filter) {
+ auto* filt_stats = trace_stats.mutable_filter_stats();
+ filt_stats->set_input_packets(tracing_session->filter_input_packets);
+ filt_stats->set_input_bytes(tracing_session->filter_input_bytes);
+ filt_stats->set_output_bytes(tracing_session->filter_output_bytes);
+ filt_stats->set_errors(tracing_session->filter_errors);
+ filt_stats->set_time_taken_ns(tracing_session->filter_time_taken_ns);
+ for (uint64_t value : tracing_session->filter_bytes_discarded_per_buffer)
+ filt_stats->add_bytes_discarded_per_buffer(value);
+ }
+
+ for (BufferID buf_id : tracing_session->buffers_index) {
+ TraceBuffer* buf = GetBufferByID(buf_id);
+ if (!buf) {
+ PERFETTO_DFATAL("Buffer not found.");
+ continue;
+ }
+ *trace_stats.add_buffer_stats() = buf->stats();
+ } // for (buf in session).
+
+ if (!tracing_session->config.builtin_data_sources()
+ .disable_chunk_usage_histograms()) {
+ // Emit chunk usage stats broken down by sequence ID (i.e. by trace-writer).
+ // Writer stats are updated by each TraceBuffer object at ReadBuffers time,
+ // and there can be >1 buffer per session. A trace writer never writes to
+ // more than one buffer (it's technically allowed but doesn't happen in the
+ // current impl of the tracing SDK).
+
+ bool has_written_bucket_definition = false;
+ uint32_t buf_idx = static_cast<uint32_t>(-1);
+ for (const BufferID buf_id : tracing_session->buffers_index) {
+ ++buf_idx;
+ const TraceBuffer* buf = GetBufferByID(buf_id);
+ if (!buf)
+ continue;
+ for (auto it = buf->writer_stats().GetIterator(); it; ++it) {
+ const auto& hist = it.value().used_chunk_hist;
+ ProducerID p;
+ WriterID w;
+ GetProducerAndWriterID(it.key(), &p, &w);
+ if (!has_written_bucket_definition) {
+ // Serialize one-off the histogram bucket definition, which is the
+ // same for all entries in the map.
+ has_written_bucket_definition = true;
+ // The -1 in the loop below is to skip the implicit overflow bucket.
+ for (size_t i = 0; i < hist.num_buckets() - 1; ++i) {
+ trace_stats.add_chunk_payload_histogram_def(hist.GetBucketThres(i));
+ }
+ } // if(!has_written_bucket_definition)
+ auto* wri_stats = trace_stats.add_writer_stats();
+ wri_stats->set_sequence_id(
+ tracing_session->GetPacketSequenceID(kDefaultMachineID, p, w));
+ wri_stats->set_buffer(buf_idx);
+ for (size_t i = 0; i < hist.num_buckets(); ++i) {
+ wri_stats->add_chunk_payload_histogram_counts(hist.GetBucketCount(i));
+ wri_stats->add_chunk_payload_histogram_sum(hist.GetBucketSum(i));
+ }
+ } // for each sequence (writer).
+ } // for each buffer.
+ } // if (!disable_chunk_usage_histograms)
+
+ return trace_stats;
+}
+
+void TracingServiceImpl::EmitUuid(TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+ auto* uuid = packet->set_trace_uuid();
+ uuid->set_lsb(tracing_session->trace_uuid.lsb());
+ uuid->set_msb(tracing_session->trace_uuid.msb());
+ SerializeAndAppendPacket(packets, packet.SerializeAsArray());
+}
+
+void TracingServiceImpl::MaybeEmitTraceConfig(
+ TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ if (tracing_session->did_emit_initial_packets)
+ return;
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+ tracing_session->config.Serialize(packet->set_trace_config());
+ SerializeAndAppendPacket(packets, packet.SerializeAsArray());
+}
+
+void TracingServiceImpl::EmitSystemInfo(std::vector<TracePacket>* packets) {
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ auto* info = packet->set_system_info();
+ info->set_tracing_service_version(base::GetVersionString());
+
+ std::optional<int32_t> tzoff = base::GetTimezoneOffsetMins();
+ if (tzoff.has_value())
+ info->set_timezone_off_mins(*tzoff);
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+ struct utsname uname_info;
+ if (uname(&uname_info) == 0) {
+ auto* utsname_info = info->set_utsname();
+ utsname_info->set_sysname(uname_info.sysname);
+ utsname_info->set_version(uname_info.version);
+ utsname_info->set_machine(uname_info.machine);
+ utsname_info->set_release(uname_info.release);
+ }
+ info->set_page_size(static_cast<uint32_t>(sysconf(_SC_PAGESIZE)));
+ info->set_num_cpus(static_cast<uint32_t>(sysconf(_SC_NPROCESSORS_CONF)));
+#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ std::string fingerprint_value = base::GetAndroidProp("ro.build.fingerprint");
+ if (!fingerprint_value.empty()) {
+ info->set_android_build_fingerprint(fingerprint_value);
+ } else {
+ PERFETTO_ELOG("Unable to read ro.build.fingerprint");
+ }
+
+ std::string sdk_str_value = base::GetAndroidProp("ro.build.version.sdk");
+ std::optional<uint64_t> sdk_value = base::StringToUInt64(sdk_str_value);
+ if (sdk_value.has_value()) {
+ info->set_android_sdk_version(*sdk_value);
+ } else {
+ PERFETTO_ELOG("Unable to read ro.build.version.sdk");
+ }
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+ SerializeAndAppendPacket(packets, packet.SerializeAsArray());
+}
+
+void TracingServiceImpl::EmitLifecycleEvents(
+ TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ using TimestampedPacket =
+ std::pair<int64_t /* ts */, std::vector<uint8_t> /* serialized packet */>;
+
+ std::vector<TimestampedPacket> timestamped_packets;
+ for (auto& event : tracing_session->lifecycle_events) {
+ for (int64_t ts : event.timestamps) {
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ packet->set_timestamp(static_cast<uint64_t>(ts));
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+
+ auto* service_event = packet->set_service_event();
+ service_event->AppendVarInt(event.field_id, 1);
+ timestamped_packets.emplace_back(ts, packet.SerializeAsArray());
+ }
+ event.timestamps.clear();
+ }
+
+ // We sort by timestamp here to ensure that the "sequence" of lifecycle
+ // packets has monotonic timestamps like other sequences in the trace.
+ // Note that these events could still be out of order with respect to other
+ // events on the service packet sequence (e.g. trigger received packets).
+ std::sort(timestamped_packets.begin(), timestamped_packets.end(),
+ [](const TimestampedPacket& a, const TimestampedPacket& b) {
+ return a.first < b.first;
+ });
+
+ for (auto& pair : timestamped_packets)
+ SerializeAndAppendPacket(packets, std::move(pair.second));
+}
+
+void TracingServiceImpl::MaybeEmitRemoteClockSync(
+ TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ if (tracing_session->did_emit_remote_clock_sync_)
+ return;
+
+ std::unordered_set<MachineID> did_emit_machines;
+ for (const auto& id_and_relay_client : relay_clients_) {
+ const auto& relay_client = id_and_relay_client.second;
+ auto machine_id = relay_client->machine_id();
+ if (did_emit_machines.find(machine_id) != did_emit_machines.end())
+ continue; // Already emitted for the machine (e.g. multiple clients).
+
+ auto& sync_clock_snapshots = relay_client->synced_clocks();
+ if (sync_clock_snapshots.empty()) {
+ PERFETTO_DLOG("Clock not synchronized for machine ID = %" PRIu32,
+ machine_id);
+ continue;
+ }
+
+ // Don't emit twice for the same machine.
+ did_emit_machines.insert(machine_id);
+
+ protozero::HeapBuffered<protos::pbzero::TracePacket> sync_packet;
+ sync_packet->set_machine_id(machine_id);
+ sync_packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ auto* remote_clock_sync = sync_packet->set_remote_clock_sync();
+ for (const auto& sync_exchange : relay_client->synced_clocks()) {
+ auto* sync_exchange_msg = remote_clock_sync->add_synced_clocks();
+
+ auto* client_snapshots = sync_exchange_msg->set_client_clocks();
+ for (const auto& client_clock : sync_exchange.client_clocks) {
+ auto* clock = client_snapshots->add_clocks();
+ clock->set_clock_id(client_clock.clock_id);
+ clock->set_timestamp(client_clock.timestamp);
+ }
+
+ auto* host_snapshots = sync_exchange_msg->set_host_clocks();
+ for (const auto& host_clock : sync_exchange.host_clocks) {
+ auto* clock = host_snapshots->add_clocks();
+ clock->set_clock_id(host_clock.clock_id);
+ clock->set_timestamp(host_clock.timestamp);
+ }
+ }
+
+ SerializeAndAppendPacket(packets, sync_packet.SerializeAsArray());
+ }
+
+ tracing_session->did_emit_remote_clock_sync_ = true;
+}
+
+void TracingServiceImpl::MaybeEmitReceivedTriggers(
+ TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ PERFETTO_DCHECK(tracing_session->num_triggers_emitted_into_trace <=
+ tracing_session->received_triggers.size());
+ for (size_t i = tracing_session->num_triggers_emitted_into_trace;
+ i < tracing_session->received_triggers.size(); ++i) {
+ const auto& info = tracing_session->received_triggers[i];
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ auto* trigger = packet->set_trigger();
+ trigger->set_trigger_name(info.trigger_name);
+ trigger->set_producer_name(info.producer_name);
+ trigger->set_trusted_producer_uid(static_cast<int32_t>(info.producer_uid));
+
+ packet->set_timestamp(info.boot_time_ns);
+ packet->set_trusted_uid(static_cast<int32_t>(uid_));
+ packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+ SerializeAndAppendPacket(packets, packet.SerializeAsArray());
+ ++tracing_session->num_triggers_emitted_into_trace;
+ }
+}
+
+void TracingServiceImpl::MaybeLogUploadEvent(const TraceConfig& cfg,
+ const base::Uuid& uuid,
+ PerfettoStatsdAtom atom,
+ const std::string& trigger_name) {
+ if (!ShouldLogEvent(cfg))
+ return;
+
+ PERFETTO_DCHECK(uuid); // The UUID must be set at this point.
+ android_stats::MaybeLogUploadEvent(atom, uuid.lsb(), uuid.msb(),
+ trigger_name);
+}
+
+void TracingServiceImpl::MaybeLogTriggerEvent(const TraceConfig& cfg,
+ PerfettoTriggerAtom atom,
+ const std::string& trigger_name) {
+ if (!ShouldLogEvent(cfg))
+ return;
+ android_stats::MaybeLogTriggerEvent(atom, trigger_name);
+}
+
+size_t TracingServiceImpl::PurgeExpiredAndCountTriggerInWindow(
+ int64_t now_ns,
+ uint64_t trigger_name_hash) {
+ PERFETTO_DCHECK(
+ std::is_sorted(trigger_history_.begin(), trigger_history_.end()));
+ size_t remove_count = 0;
+ size_t trigger_count = 0;
+ for (const TriggerHistory& h : trigger_history_) {
+ if (h.timestamp_ns < now_ns - trigger_window_ns_) {
+ remove_count++;
+ } else if (h.name_hash == trigger_name_hash) {
+ trigger_count++;
+ }
+ }
+ trigger_history_.erase_front(remove_count);
+ return trigger_count;
+}
+
+void TracingServiceImpl::FlushAndCloneSession(ConsumerEndpointImpl* consumer,
+ TracingSessionID tsid,
+ bool skip_trace_filter,
+ bool for_bugreport) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto clone_target = FlushFlags::CloneTarget::kUnknown;
+
+ if (tsid == kBugreportSessionId) {
+ // This branch is only here to support the legacy protocol where we could
+ // clone only a single session using the magic ID kBugreportSessionId.
+ // The newer perfetto --clone-all-for-bugreport first queries the existing
+ // sessions and then issues individual clone requests specifying real
+ // session IDs, setting args.{for_bugreport,skip_trace_filter}=true.
+ PERFETTO_LOG("Looking for sessions for bugreport");
+ TracingSession* session = FindTracingSessionWithMaxBugreportScore();
+ if (!session) {
+ consumer->consumer_->OnSessionCloned(
+ {false, "No tracing sessions eligible for bugreport found", {}});
+ return;
+ }
+ tsid = session->id;
+ clone_target = FlushFlags::CloneTarget::kBugreport;
+ skip_trace_filter = true;
+ for_bugreport = true;
+ } else if (for_bugreport) {
+ clone_target = FlushFlags::CloneTarget::kBugreport;
+ }
+
+ TracingSession* session = GetTracingSession(tsid);
+ if (!session) {
+ consumer->consumer_->OnSessionCloned(
+ {false, "Tracing session not found", {}});
+ return;
+ }
+
+ // If any of the buffers are marked as clear_before_clone, reset them before
+ // issuing the Flush(kCloneReason).
+ size_t buf_idx = 0;
+ for (BufferID src_buf_id : session->buffers_index) {
+ if (!session->config.buffers()[buf_idx++].clear_before_clone())
+ continue;
+ auto buf_iter = buffers_.find(src_buf_id);
+ PERFETTO_CHECK(buf_iter != buffers_.end());
+ std::unique_ptr<TraceBuffer>& buf = buf_iter->second;
+
+ // No need to reset the buffer if nothing has been written into it yet.
+ // This is the canonical case if producers behive nicely and don't timeout
+ // the handling of writes during the flush.
+ // This check avoids a useless re-mmap upon every Clone() if the buffer is
+ // already empty (when used in combination with `transfer_on_clone`).
+ if (!buf->has_data())
+ continue;
+
+ // Some leftover data was left in the buffer. Recreate it to empty it.
+ const auto buf_policy = buf->overwrite_policy();
+ const auto buf_size = buf->size();
+ std::unique_ptr<TraceBuffer> old_buf = std::move(buf);
+ buf = TraceBuffer::Create(buf_size, buf_policy);
+ if (!buf) {
+ // This is extremely rare but could happen on 32-bit. If the new buffer
+ // allocation failed, put back the buffer where it was and fail the clone.
+ // We cannot leave the original tracing session buffer-less as it would
+ // cause crashes when data sources commit new data.
+ buf = std::move(old_buf);
+ consumer->consumer_->OnSessionCloned(
+ {false, "Buffer allocation failed while attempting to clone", {}});
+ return;
+ }
+ }
+
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ auto weak_consumer = consumer->GetWeakPtr();
+
+ const PendingCloneID clone_id = session->last_pending_clone_id_++;
+
+ auto& clone_op = session->pending_clones[clone_id];
+ clone_op.pending_flush_cnt = 0;
+ clone_op.buffers =
+ std::vector<std::unique_ptr<TraceBuffer>>(session->buffers_index.size());
+ clone_op.weak_consumer = weak_consumer;
+ clone_op.skip_trace_filter = skip_trace_filter;
+
+ // Issue separate flush requests for separate buffer groups. The buffer marked
+ // as transfer_on_clone will be flushed and cloned separately: even if they're
+ // slower (like in the case of Winscope tracing), they will not delay the
+ // snapshot of the other buffers.
+ //
+ // In the future we might want to split the buffer into more groups and maybe
+ // allow this to be configurable.
+ std::array<std::set<BufferID>, 2> bufs_groups;
+ for (size_t i = 0; i < session->buffers_index.size(); i++) {
+ if (session->config.buffers()[i].transfer_on_clone()) {
+ bufs_groups[0].insert(session->buffers_index[i]);
+ } else {
+ bufs_groups[1].insert(session->buffers_index[i]);
+ }
+ }
+
+ clone_op.pending_flush_cnt = bufs_groups.size();
+ for (const std::set<BufferID>& buf_group : bufs_groups) {
+ FlushDataSourceInstances(
+ session, 0,
+ GetFlushableDataSourceInstancesForBuffers(session, buf_group),
+ [tsid, clone_id, buf_group, weak_this](bool final_flush) {
+ if (!weak_this)
+ return;
+ weak_this->OnFlushDoneForClone(tsid, clone_id, buf_group,
+ final_flush);
+ },
+ FlushFlags(FlushFlags::Initiator::kTraced,
+ FlushFlags::Reason::kTraceClone, clone_target));
+ }
+}
+
+std::map<ProducerID, std::vector<DataSourceInstanceID>>
+TracingServiceImpl::GetFlushableDataSourceInstancesForBuffers(
+ TracingSession* session,
+ const std::set<BufferID>& bufs) {
+ std::map<ProducerID, std::vector<DataSourceInstanceID>> data_source_instances;
+
+ for (const auto& [producer_id, ds_inst] : session->data_source_instances) {
+ // TODO(ddiproietto): Consider if we should skip instances if ds_inst.state
+ // != DataSourceInstance::STARTED
+ if (ds_inst.no_flush) {
+ continue;
+ }
+ if (!bufs.count(static_cast<BufferID>(ds_inst.config.target_buffer()))) {
+ continue;
+ }
+ data_source_instances[producer_id].push_back(ds_inst.instance_id);
+ }
+
+ return data_source_instances;
+}
+
+void TracingServiceImpl::OnFlushDoneForClone(TracingSessionID tsid,
+ PendingCloneID clone_id,
+ const std::set<BufferID>& buf_ids,
+ bool final_flush_outcome) {
+ TracingSession* src = GetTracingSession(tsid);
+ // The session might be gone by the time we try to clone it.
+ if (!src) {
+ return;
+ }
+
+ auto it = src->pending_clones.find(clone_id);
+ if (it == src->pending_clones.end()) {
+ return;
+ }
+ auto& clone_op = it->second;
+
+ if (final_flush_outcome == false) {
+ clone_op.flush_failed = true;
+ }
+
+ base::Status result;
+ base::Uuid uuid;
+
+ // First clone the flushed TraceBuffer(s). This can fail because of ENOMEM. If
+ // it happens bail out early before creating any session.
+ if (!DoCloneBuffers(src, buf_ids, &clone_op.buffers)) {
+ result = PERFETTO_SVC_ERR("Buffer allocation failed");
+ }
+
+ if (result.ok()) {
+ UpdateMemoryGuardrail();
+
+ if (--clone_op.pending_flush_cnt != 0) {
+ // Wait for more pending flushes.
+ return;
+ }
+
+ PERFETTO_LOG("FlushAndCloneSession(%" PRIu64 ") started, success=%d", tsid,
+ final_flush_outcome);
+
+ if (clone_op.weak_consumer) {
+ result = FinishCloneSession(
+ &*clone_op.weak_consumer, tsid, std::move(clone_op.buffers),
+ clone_op.skip_trace_filter, !clone_op.flush_failed, &uuid);
+ }
+ } // if (result.ok())
+
+ if (clone_op.weak_consumer) {
+ clone_op.weak_consumer->consumer_->OnSessionCloned(
+ {result.ok(), result.message(), uuid});
+ }
+
+ src->pending_clones.erase(it);
+ UpdateMemoryGuardrail();
+}
+
+bool TracingServiceImpl::DoCloneBuffers(
+ TracingSession* src,
+ const std::set<BufferID>& buf_ids,
+ std::vector<std::unique_ptr<TraceBuffer>>* buf_snaps) {
+ PERFETTO_DCHECK(src->num_buffers() == src->config.buffers().size());
+ buf_snaps->resize(src->buffers_index.size());
+
+ for (size_t buf_idx = 0; buf_idx < src->buffers_index.size(); buf_idx++) {
+ BufferID src_buf_id = src->buffers_index[buf_idx];
+ if (buf_ids.count(src_buf_id) == 0)
+ continue;
+ auto buf_iter = buffers_.find(src_buf_id);
+ PERFETTO_CHECK(buf_iter != buffers_.end());
+ std::unique_ptr<TraceBuffer>& src_buf = buf_iter->second;
+ std::unique_ptr<TraceBuffer> new_buf;
+ if (src->config.buffers()[buf_idx].transfer_on_clone()) {
+ const auto buf_policy = src_buf->overwrite_policy();
+ const auto buf_size = src_buf->size();
+ new_buf = std::move(src_buf);
+ src_buf = TraceBuffer::Create(buf_size, buf_policy);
+ if (!src_buf) {
+ // If the allocation fails put the buffer back and let the code below
+ // handle the failure gracefully.
+ src_buf = std::move(new_buf);
+ }
+ } else {
+ new_buf = src_buf->CloneReadOnly();
+ }
+ if (!new_buf.get()) {
+ return false;
+ }
+ (*buf_snaps)[buf_idx] = std::move(new_buf);
+ }
+ return true;
+}
+
+base::Status TracingServiceImpl::FinishCloneSession(
+ ConsumerEndpointImpl* consumer,
+ TracingSessionID src_tsid,
+ std::vector<std::unique_ptr<TraceBuffer>> buf_snaps,
+ bool skip_trace_filter,
+ bool final_flush_outcome,
+ base::Uuid* new_uuid) {
+ PERFETTO_DLOG("CloneSession(%" PRIu64
+ ", skip_trace_filter=%d) started, consumer uid: %d",
+ src_tsid, skip_trace_filter, static_cast<int>(consumer->uid_));
+
+ TracingSession* src = GetTracingSession(src_tsid);
+
+ // The session might be gone by the time we try to clone it.
+ if (!src)
+ return PERFETTO_SVC_ERR("session not found");
+
+ if (consumer->tracing_session_id_) {
+ return PERFETTO_SVC_ERR(
+ "The consumer is already attached to another tracing session");
+ }
+
+ // Skip the UID check for sessions marked with a bugreport_score > 0.
+ // Those sessions, by design, can be stolen by any other consumer for the
+ // sake of creating snapshots for bugreports.
+ if (!src->IsCloneAllowed(consumer->uid_)) {
+ return PERFETTO_SVC_ERR("Not allowed to clone a session from another UID");
+ }
+
+ std::vector<BufferID> buf_ids =
+ buffer_ids_.AllocateMultiple(buf_snaps.size());
+ if (buf_ids.size() != buf_snaps.size()) {
+ return PERFETTO_SVC_ERR("Buffer id allocation failed");
+ }
+
+ PERFETTO_CHECK(std::none_of(
+ buf_snaps.begin(), buf_snaps.end(),
+ [](const std::unique_ptr<TraceBuffer>& buf) { return buf == nullptr; }));
+
+ const TracingSessionID tsid = ++last_tracing_session_id_;
+ TracingSession* cloned_session =
+ &tracing_sessions_
+ .emplace(
+ std::piecewise_construct, std::forward_as_tuple(tsid),
+ std::forward_as_tuple(tsid, consumer, src->config, task_runner_))
+ .first->second;
+
+ // Generate a new UUID for the cloned session, but preserve the LSB. In some
+ // contexts the LSB is used to tie the trace back to the statsd subscription
+ // that triggered it. See the corresponding code in perfetto_cmd.cc which
+ // reads at triggering_subscription_id().
+ const int64_t orig_uuid_lsb = src->trace_uuid.lsb();
+ cloned_session->state = TracingSession::CLONED_READ_ONLY;
+ cloned_session->trace_uuid = base::Uuidv4();
+ cloned_session->trace_uuid.set_lsb(orig_uuid_lsb);
+ *new_uuid = cloned_session->trace_uuid;
+
+ for (size_t i = 0; i < buf_snaps.size(); i++) {
+ BufferID buf_global_id = buf_ids[i];
+ std::unique_ptr<TraceBuffer>& buf = buf_snaps[i];
+ // This is only needed for transfer_on_clone. Other buffers are already
+ // marked as read-only by CloneReadOnly(). We cannot do this early because
+ // in case of an allocation failure we will put std::move() the original
+ // buffer back in its place and in that case should not be made read-only.
+ buf->set_read_only();
+ buffers_.emplace(buf_global_id, std::move(buf));
+ cloned_session->buffers_index.emplace_back(buf_global_id);
+ }
+ UpdateMemoryGuardrail();
+
+ // Copy over relevant state that we want to persist in the cloned session.
+ // Mostly stats and metadata that is emitted in the trace file by the service.
+ // Also clear the received trigger list in the main tracing session. A
+ // CLONE_SNAPSHOT session can go in ring buffer mode for several hours and get
+ // snapshotted several times. This causes two issues with `received_triggers`:
+ // 1. Adding noise in the cloned trace emitting triggers that happened too
+ // far back (see b/290799105).
+ // 2. Bloating memory (see b/290798988).
+ cloned_session->should_emit_stats = true;
+ cloned_session->received_triggers = std::move(src->received_triggers);
+ src->received_triggers.clear();
+ src->num_triggers_emitted_into_trace = 0;
+ cloned_session->lifecycle_events =
+ std::vector<TracingSession::LifecycleEvent>(src->lifecycle_events);
+ cloned_session->initial_clock_snapshot = src->initial_clock_snapshot;
+ cloned_session->clock_snapshot_ring_buffer = src->clock_snapshot_ring_buffer;
+ cloned_session->invalid_packets = src->invalid_packets;
+ cloned_session->flushes_requested = src->flushes_requested;
+ cloned_session->flushes_succeeded = src->flushes_succeeded;
+ cloned_session->flushes_failed = src->flushes_failed;
+ cloned_session->compress_deflate = src->compress_deflate;
+ if (src->trace_filter && !skip_trace_filter) {
+ // Copy the trace filter, unless it's a clone-for-bugreport (b/317065412).
+ cloned_session->trace_filter.reset(
+ new protozero::MessageFilter(src->trace_filter->config()));
+ }
+
+ SnapshotLifecyleEvent(
+ cloned_session,
+ protos::pbzero::TracingServiceEvent::kTracingDisabledFieldNumber,
+ true /* snapshot_clocks */);
+
+ PERFETTO_DLOG("Consumer (uid:%d) cloned tracing session %" PRIu64
+ " -> %" PRIu64,
+ static_cast<int>(consumer->uid_), src_tsid, tsid);
+
+ consumer->tracing_session_id_ = tsid;
+ cloned_session->final_flush_outcome = final_flush_outcome
+ ? TraceStats::FINAL_FLUSH_SUCCEEDED
+ : TraceStats::FINAL_FLUSH_FAILED;
+ return base::OkStatus();
+}
+
+bool TracingServiceImpl::TracingSession::IsCloneAllowed(uid_t clone_uid) const {
+ if (clone_uid == 0)
+ return true; // Root is always allowed to clone everything.
+ if (clone_uid == this->consumer_uid)
+ return true; // Allow cloning if the uids match.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // On Android allow shell to clone sessions marked as exported for bugreport.
+ // Dumpstate (invoked by adb bugreport) invokes commands as shell.
+ if (clone_uid == AID_SHELL && this->config.bugreport_score() > 0)
+ return true;
+#endif
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TracingServiceImpl::ConsumerEndpointImpl implementation
+////////////////////////////////////////////////////////////////////////////////
+
+TracingServiceImpl::ConsumerEndpointImpl::ConsumerEndpointImpl(
+ TracingServiceImpl* service,
+ base::TaskRunner* task_runner,
+ Consumer* consumer,
+ uid_t uid)
+ : task_runner_(task_runner),
+ service_(service),
+ consumer_(consumer),
+ uid_(uid),
+ weak_ptr_factory_(this) {}
+
+TracingServiceImpl::ConsumerEndpointImpl::~ConsumerEndpointImpl() {
+ service_->DisconnectConsumer(this);
+ consumer_->OnDisconnect();
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::NotifyOnTracingDisabled(
+ const std::string& error) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, error /* deliberate copy */] {
+ if (weak_this)
+ weak_this->consumer_->OnTracingDisabled(error);
+ });
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::EnableTracing(
+ const TraceConfig& cfg,
+ base::ScopedFile fd) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto status = service_->EnableTracing(this, cfg, std::move(fd));
+ if (!status.ok())
+ NotifyOnTracingDisabled(status.message());
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::ChangeTraceConfig(
+ const TraceConfig& cfg) {
+ if (!tracing_session_id_) {
+ PERFETTO_LOG(
+ "Consumer called ChangeTraceConfig() but tracing was "
+ "not active");
+ return;
+ }
+ service_->ChangeTraceConfig(this, cfg);
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::StartTracing() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!tracing_session_id_) {
+ PERFETTO_LOG("Consumer called StartTracing() but tracing was not active");
+ return;
+ }
+ service_->StartTracing(tracing_session_id_);
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::DisableTracing() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!tracing_session_id_) {
+ PERFETTO_LOG("Consumer called DisableTracing() but tracing was not active");
+ return;
+ }
+ service_->DisableTracing(tracing_session_id_);
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::ReadBuffers() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!tracing_session_id_) {
+ PERFETTO_LOG("Consumer called ReadBuffers() but tracing was not active");
+ consumer_->OnTraceData({}, /* has_more = */ false);
+ return;
+ }
+ if (!service_->ReadBuffersIntoConsumer(tracing_session_id_, this)) {
+ consumer_->OnTraceData({}, /* has_more = */ false);
+ }
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::FreeBuffers() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!tracing_session_id_) {
+ PERFETTO_LOG("Consumer called FreeBuffers() but tracing was not active");
+ return;
+ }
+ service_->FreeBuffers(tracing_session_id_);
+ tracing_session_id_ = 0;
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::Flush(uint32_t timeout_ms,
+ FlushCallback callback,
+ FlushFlags flush_flags) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!tracing_session_id_) {
+ PERFETTO_LOG("Consumer called Flush() but tracing was not active");
+ return;
+ }
+ service_->Flush(tracing_session_id_, timeout_ms, callback, flush_flags);
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::Detach(const std::string& key) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ bool success = service_->DetachConsumer(this, key);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, success] {
+ if (weak_this)
+ weak_this->consumer_->OnDetach(success);
+ });
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::Attach(const std::string& key) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ bool success = service_->AttachConsumer(this, key);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, success] {
+ if (!weak_this)
+ return;
+ Consumer* consumer = weak_this->consumer_;
+ TracingSession* session =
+ weak_this->service_->GetTracingSession(weak_this->tracing_session_id_);
+ if (!session) {
+ consumer->OnAttach(false, TraceConfig());
+ return;
+ }
+ consumer->OnAttach(success, session->config);
+ });
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::GetTraceStats() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ bool success = false;
+ TraceStats stats;
+ TracingSession* session = service_->GetTracingSession(tracing_session_id_);
+ if (session) {
+ success = true;
+ stats = service_->GetTraceStats(session);
+ }
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, success, stats] {
+ if (weak_this)
+ weak_this->consumer_->OnTraceStats(success, stats);
+ });
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::ObserveEvents(
+ uint32_t events_mask) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ observable_events_mask_ = events_mask;
+ TracingSession* session = service_->GetTracingSession(tracing_session_id_);
+ if (!session)
+ return;
+
+ if (observable_events_mask_ & ObservableEvents::TYPE_DATA_SOURCES_INSTANCES) {
+ // Issue initial states.
+ for (const auto& kv : session->data_source_instances) {
+ ProducerEndpointImpl* producer = service_->GetProducer(kv.first);
+ PERFETTO_DCHECK(producer);
+ OnDataSourceInstanceStateChange(*producer, kv.second);
+ }
+ }
+
+ // If the ObserveEvents() call happens after data sources have acked already
+ // notify immediately.
+ if (observable_events_mask_ &
+ ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED) {
+ service_->MaybeNotifyAllDataSourcesStarted(session);
+ }
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::OnDataSourceInstanceStateChange(
+ const ProducerEndpointImpl& producer,
+ const DataSourceInstance& instance) {
+ if (!(observable_events_mask_ &
+ ObservableEvents::TYPE_DATA_SOURCES_INSTANCES)) {
+ return;
+ }
+
+ if (instance.state != DataSourceInstance::CONFIGURED &&
+ instance.state != DataSourceInstance::STARTED &&
+ instance.state != DataSourceInstance::STOPPED) {
+ return;
+ }
+
+ auto* observable_events = AddObservableEvents();
+ auto* change = observable_events->add_instance_state_changes();
+ change->set_producer_name(producer.name_);
+ change->set_data_source_name(instance.data_source_name);
+ if (instance.state == DataSourceInstance::STARTED) {
+ change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
+ } else {
+ change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
+ }
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::OnAllDataSourcesStarted() {
+ if (!(observable_events_mask_ &
+ ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED)) {
+ return;
+ }
+ auto* observable_events = AddObservableEvents();
+ observable_events->set_all_data_sources_started(true);
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::NotifyCloneSnapshotTrigger() {
+ if (!(observable_events_mask_ & ObservableEvents::TYPE_CLONE_TRIGGER_HIT)) {
+ return;
+ }
+ auto* observable_events = AddObservableEvents();
+ auto* clone_trig = observable_events->mutable_clone_trigger_hit();
+ clone_trig->set_tracing_session_id(static_cast<int64_t>(tracing_session_id_));
+}
+
+ObservableEvents*
+TracingServiceImpl::ConsumerEndpointImpl::AddObservableEvents() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!observable_events_) {
+ observable_events_.reset(new ObservableEvents());
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this] {
+ if (!weak_this)
+ return;
+
+ // Move into a temporary to allow reentrancy in OnObservableEvents.
+ auto observable_events = std::move(weak_this->observable_events_);
+ weak_this->consumer_->OnObservableEvents(*observable_events);
+ });
+ }
+ return observable_events_.get();
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::QueryServiceState(
+ QueryServiceStateArgs args,
+ QueryServiceStateCallback callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingServiceState svc_state;
+
+ const auto& sessions = service_->tracing_sessions_;
+ svc_state.set_tracing_service_version(base::GetVersionString());
+ svc_state.set_num_sessions(static_cast<int>(sessions.size()));
+
+ int num_started = 0;
+ for (const auto& kv : sessions)
+ num_started += kv.second.state == TracingSession::State::STARTED ? 1 : 0;
+ svc_state.set_num_sessions_started(num_started);
+
+ for (const auto& kv : service_->producers_) {
+ if (args.sessions_only)
+ break;
+ auto* producer = svc_state.add_producers();
+ producer->set_id(static_cast<int>(kv.first));
+ producer->set_name(kv.second->name_);
+ producer->set_sdk_version(kv.second->sdk_version_);
+ producer->set_uid(static_cast<int32_t>(kv.second->uid()));
+ producer->set_pid(static_cast<int32_t>(kv.second->pid()));
+ }
+
+ for (const auto& kv : service_->data_sources_) {
+ if (args.sessions_only)
+ break;
+ const auto& registered_data_source = kv.second;
+ auto* data_source = svc_state.add_data_sources();
+ *data_source->mutable_ds_descriptor() = registered_data_source.descriptor;
+ data_source->set_producer_id(
+ static_cast<int>(registered_data_source.producer_id));
+ }
+
+ svc_state.set_supports_tracing_sessions(true);
+ for (const auto& kv : service_->tracing_sessions_) {
+ const TracingSession& s = kv.second;
+ if (!s.IsCloneAllowed(uid_))
+ continue;
+ auto* session = svc_state.add_tracing_sessions();
+ session->set_id(s.id);
+ session->set_consumer_uid(static_cast<int>(s.consumer_uid));
+ session->set_duration_ms(s.config.duration_ms());
+ session->set_num_data_sources(
+ static_cast<uint32_t>(s.data_source_instances.size()));
+ session->set_unique_session_name(s.config.unique_session_name());
+ if (s.config.has_bugreport_score())
+ session->set_bugreport_score(s.config.bugreport_score());
+ if (s.config.has_bugreport_filename())
+ session->set_bugreport_filename(s.config.bugreport_filename());
+ for (const auto& snap_kv : s.initial_clock_snapshot) {
+ if (snap_kv.clock_id == protos::pbzero::BUILTIN_CLOCK_REALTIME)
+ session->set_start_realtime_ns(static_cast<int64_t>(snap_kv.timestamp));
+ }
+ for (const auto& buf : s.config.buffers())
+ session->add_buffer_size_kb(buf.size_kb());
+
+ switch (s.state) {
+ case TracingSession::State::DISABLED:
+ session->set_state("DISABLED");
+ break;
+ case TracingSession::State::CONFIGURED:
+ session->set_state("CONFIGURED");
+ break;
+ case TracingSession::State::STARTED:
+ session->set_is_started(true);
+ session->set_state("STARTED");
+ break;
+ case TracingSession::State::DISABLING_WAITING_STOP_ACKS:
+ session->set_state("STOP_WAIT");
+ break;
+ case TracingSession::State::CLONED_READ_ONLY:
+ session->set_state("CLONED_READ_ONLY");
+ break;
+ }
+ }
+ callback(/*success=*/true, svc_state);
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::QueryCapabilities(
+ QueryCapabilitiesCallback callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ TracingServiceCapabilities caps;
+ caps.set_has_query_capabilities(true);
+ caps.set_has_trace_config_output_path(true);
+ caps.set_has_clone_session(true);
+ caps.add_observable_events(ObservableEvents::TYPE_DATA_SOURCES_INSTANCES);
+ caps.add_observable_events(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
+ caps.add_observable_events(ObservableEvents::TYPE_CLONE_TRIGGER_HIT);
+ static_assert(
+ ObservableEvents::Type_MAX == ObservableEvents::TYPE_CLONE_TRIGGER_HIT,
+ "");
+ callback(caps);
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::SaveTraceForBugreport(
+ SaveTraceForBugreportCallback consumer_callback) {
+ consumer_callback(false,
+ "SaveTraceForBugreport is deprecated. Use "
+ "CloneSession(kBugreportSessionId) instead.");
+}
+
+void TracingServiceImpl::ConsumerEndpointImpl::CloneSession(
+ TracingSessionID tsid,
+ CloneSessionArgs args) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ // FlushAndCloneSession will call OnSessionCloned after the async flush.
+ service_->FlushAndCloneSession(this, tsid, args.skip_trace_filter,
+ args.for_bugreport);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TracingServiceImpl::ProducerEndpointImpl implementation
+////////////////////////////////////////////////////////////////////////////////
+
+TracingServiceImpl::ProducerEndpointImpl::ProducerEndpointImpl(
+ ProducerID id,
+ const ClientIdentity& client_identity,
+ TracingServiceImpl* service,
+ base::TaskRunner* task_runner,
+ Producer* producer,
+ const std::string& producer_name,
+ const std::string& sdk_version,
+ bool in_process,
+ bool smb_scraping_enabled)
+ : id_(id),
+ client_identity_(client_identity),
+ service_(service),
+ task_runner_(task_runner),
+ producer_(producer),
+ name_(producer_name),
+ sdk_version_(sdk_version),
+ in_process_(in_process),
+ smb_scraping_enabled_(smb_scraping_enabled),
+ weak_ptr_factory_(this) {}
+
+TracingServiceImpl::ProducerEndpointImpl::~ProducerEndpointImpl() {
+ service_->DisconnectProducer(id_);
+ producer_->OnDisconnect();
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::Disconnect() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ // Disconnection is only supported via destroying the ProducerEndpoint.
+ PERFETTO_FATAL("Not supported");
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::RegisterDataSource(
+ const DataSourceDescriptor& desc) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ service_->RegisterDataSource(id_, desc);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::UpdateDataSource(
+ const DataSourceDescriptor& desc) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ service_->UpdateDataSource(id_, desc);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::UnregisterDataSource(
+ const std::string& name) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ service_->UnregisterDataSource(id_, name);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::RegisterTraceWriter(
+ uint32_t writer_id,
+ uint32_t target_buffer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ writers_[static_cast<WriterID>(writer_id)] =
+ static_cast<BufferID>(target_buffer);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::UnregisterTraceWriter(
+ uint32_t writer_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ writers_.erase(static_cast<WriterID>(writer_id));
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::CommitData(
+ const CommitDataRequest& req_untrusted,
+ CommitDataCallback callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ if (metatrace::IsEnabled(metatrace::TAG_TRACE_SERVICE)) {
+ PERFETTO_METATRACE_COUNTER(TAG_TRACE_SERVICE, TRACE_SERVICE_COMMIT_DATA,
+ EncodeCommitDataRequest(id_, req_untrusted));
+ }
+
+ if (!shared_memory_) {
+ PERFETTO_DLOG(
+ "Attempted to commit data before the shared memory was allocated.");
+ return;
+ }
+ PERFETTO_DCHECK(shmem_abi_.is_valid());
+ for (const auto& entry : req_untrusted.chunks_to_move()) {
+ const uint32_t page_idx = entry.page();
+ if (page_idx >= shmem_abi_.num_pages())
+ continue; // A buggy or malicious producer.
+
+ SharedMemoryABI::Chunk chunk;
+ bool commit_data_over_ipc = entry.has_data();
+ if (PERFETTO_UNLIKELY(commit_data_over_ipc)) {
+ // Chunk data is passed over the wire. Create a chunk using the serialized
+ // protobuf message.
+ const std::string& data = entry.data();
+ if (data.size() > SharedMemoryABI::Chunk::kMaxSize) {
+ PERFETTO_DFATAL("IPC data commit too large: %zu", data.size());
+ continue; // A malicious or buggy producer
+ }
+ // |data| is not altered, but we need to const_cast becasue Chunk data
+ // members are non-const.
+ chunk = SharedMemoryABI::MakeChunkFromSerializedData(
+ reinterpret_cast<uint8_t*>(const_cast<char*>(data.data())),
+ static_cast<uint16_t>(entry.data().size()),
+ static_cast<uint8_t>(entry.chunk()));
+ } else
+ chunk = shmem_abi_.TryAcquireChunkForReading(page_idx, entry.chunk());
+ if (!chunk.is_valid()) {
+ PERFETTO_DLOG("Asked to move chunk %d:%d, but it's not complete",
+ entry.page(), entry.chunk());
+ continue;
+ }
+
+ // TryAcquireChunkForReading() has load-acquire semantics. Once acquired,
+ // the ABI contract expects the producer to not touch the chunk anymore
+ // (until the service marks that as free). This is why all the reads below
+ // are just memory_order_relaxed. Also, the code here assumes that all this
+ // data can be malicious and just gives up if anything is malformed.
+ BufferID buffer_id = static_cast<BufferID>(entry.target_buffer());
+ const SharedMemoryABI::ChunkHeader& chunk_header = *chunk.header();
+ WriterID writer_id = chunk_header.writer_id.load(std::memory_order_relaxed);
+ ChunkID chunk_id = chunk_header.chunk_id.load(std::memory_order_relaxed);
+ auto packets = chunk_header.packets.load(std::memory_order_relaxed);
+ uint16_t num_fragments = packets.count;
+ uint8_t chunk_flags = packets.flags;
+
+ service_->CopyProducerPageIntoLogBuffer(
+ id_, client_identity_, writer_id, chunk_id, buffer_id, num_fragments,
+ chunk_flags,
+ /*chunk_complete=*/true, chunk.payload_begin(), chunk.payload_size());
+
+ if (!commit_data_over_ipc) {
+ // This one has release-store semantics.
+ shmem_abi_.ReleaseChunkAsFree(std::move(chunk));
+ }
+ } // for(chunks_to_move)
+
+ service_->ApplyChunkPatches(id_, req_untrusted.chunks_to_patch());
+
+ if (req_untrusted.flush_request_id()) {
+ service_->NotifyFlushDoneForProducer(id_, req_untrusted.flush_request_id());
+ }
+
+ // Keep this invocation last. ProducerIPCService::CommitData() relies on this
+ // callback being invoked within the same callstack and not posted. If this
+ // changes, the code there needs to be changed accordingly.
+ if (callback)
+ callback();
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::SetupSharedMemory(
+ std::unique_ptr<SharedMemory> shared_memory,
+ size_t page_size_bytes,
+ bool provided_by_producer) {
+ PERFETTO_DCHECK(!shared_memory_ && !shmem_abi_.is_valid());
+ PERFETTO_DCHECK(page_size_bytes % 1024 == 0);
+
+ shared_memory_ = std::move(shared_memory);
+ shared_buffer_page_size_kb_ = page_size_bytes / 1024;
+ is_shmem_provided_by_producer_ = provided_by_producer;
+
+ shmem_abi_.Initialize(reinterpret_cast<uint8_t*>(shared_memory_->start()),
+ shared_memory_->size(),
+ shared_buffer_page_size_kb() * 1024,
+ SharedMemoryABI::ShmemMode::kDefault);
+ if (in_process_) {
+ inproc_shmem_arbiter_.reset(new SharedMemoryArbiterImpl(
+ shared_memory_->start(), shared_memory_->size(),
+ SharedMemoryABI::ShmemMode::kDefault,
+ shared_buffer_page_size_kb_ * 1024, this, task_runner_));
+ inproc_shmem_arbiter_->SetDirectSMBPatchingSupportedByService();
+ }
+
+ OnTracingSetup();
+ service_->UpdateMemoryGuardrail();
+}
+
+SharedMemory* TracingServiceImpl::ProducerEndpointImpl::shared_memory() const {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ return shared_memory_.get();
+}
+
+size_t TracingServiceImpl::ProducerEndpointImpl::shared_buffer_page_size_kb()
+ const {
+ return shared_buffer_page_size_kb_;
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::ActivateTriggers(
+ const std::vector<std::string>& triggers) {
+ service_->ActivateTriggers(id_, triggers);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::StopDataSource(
+ DataSourceInstanceID ds_inst_id) {
+ // TODO(primiano): When we'll support tearing down the SMB, at this point we
+ // should send the Producer a TearDownTracing if all its data sources have
+ // been disabled (see b/77532839 and aosp/655179 PS1).
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, ds_inst_id] {
+ if (weak_this)
+ weak_this->producer_->StopDataSource(ds_inst_id);
+ });
+}
+
+SharedMemoryArbiter*
+TracingServiceImpl::ProducerEndpointImpl::MaybeSharedMemoryArbiter() {
+ if (!inproc_shmem_arbiter_) {
+ PERFETTO_FATAL(
+ "The in-process SharedMemoryArbiter can only be used when "
+ "CreateProducer has been called with in_process=true and after tracing "
+ "has started.");
+ }
+
+ PERFETTO_DCHECK(in_process_);
+ return inproc_shmem_arbiter_.get();
+}
+
+bool TracingServiceImpl::ProducerEndpointImpl::IsShmemProvidedByProducer()
+ const {
+ return is_shmem_provided_by_producer_;
+}
+
+// Can be called on any thread.
+std::unique_ptr<TraceWriter>
+TracingServiceImpl::ProducerEndpointImpl::CreateTraceWriter(
+ BufferID buf_id,
+ BufferExhaustedPolicy buffer_exhausted_policy) {
+ PERFETTO_DCHECK(MaybeSharedMemoryArbiter());
+ return MaybeSharedMemoryArbiter()->CreateTraceWriter(buf_id,
+ buffer_exhausted_policy);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::NotifyFlushComplete(
+ FlushRequestID id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(MaybeSharedMemoryArbiter());
+ return MaybeSharedMemoryArbiter()->NotifyFlushComplete(id);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::OnTracingSetup() {
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this] {
+ if (weak_this)
+ weak_this->producer_->OnTracingSetup();
+ });
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::Flush(
+ FlushRequestID flush_request_id,
+ const std::vector<DataSourceInstanceID>& data_sources,
+ FlushFlags flush_flags) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask(
+ [weak_this, flush_request_id, data_sources, flush_flags] {
+ if (weak_this) {
+ weak_this->producer_->Flush(flush_request_id, data_sources.data(),
+ data_sources.size(), flush_flags);
+ }
+ });
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::SetupDataSource(
+ DataSourceInstanceID ds_id,
+ const DataSourceConfig& config) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ allowed_target_buffers_.insert(static_cast<BufferID>(config.target_buffer()));
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, ds_id, config] {
+ if (weak_this)
+ weak_this->producer_->SetupDataSource(ds_id, std::move(config));
+ });
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::StartDataSource(
+ DataSourceInstanceID ds_id,
+ const DataSourceConfig& config) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, ds_id, config] {
+ if (weak_this)
+ weak_this->producer_->StartDataSource(ds_id, std::move(config));
+ });
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::NotifyDataSourceStarted(
+ DataSourceInstanceID data_source_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ service_->NotifyDataSourceStarted(id_, data_source_id);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::NotifyDataSourceStopped(
+ DataSourceInstanceID data_source_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ service_->NotifyDataSourceStopped(id_, data_source_id);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::OnFreeBuffers(
+ const std::vector<BufferID>& target_buffers) {
+ if (allowed_target_buffers_.empty())
+ return;
+ for (BufferID buffer : target_buffers)
+ allowed_target_buffers_.erase(buffer);
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::ClearIncrementalState(
+ const std::vector<DataSourceInstanceID>& data_sources) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this, data_sources] {
+ if (weak_this) {
+ base::StringView producer_name(weak_this->name_);
+ weak_this->producer_->ClearIncrementalState(data_sources.data(),
+ data_sources.size());
+ }
+ });
+}
+
+void TracingServiceImpl::ProducerEndpointImpl::Sync(
+ std::function<void()> callback) {
+ task_runner_->PostTask(callback);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TracingServiceImpl::TracingSession implementation
+////////////////////////////////////////////////////////////////////////////////
+
+TracingServiceImpl::TracingSession::TracingSession(
+ TracingSessionID session_id,
+ ConsumerEndpointImpl* consumer,
+ const TraceConfig& new_config,
+ base::TaskRunner* task_runner)
+ : id(session_id),
+ consumer_maybe_null(consumer),
+ consumer_uid(consumer->uid_),
+ config(new_config),
+ snapshot_periodic_task(task_runner),
+ timed_stop_task(task_runner) {
+ // all_data_sources_flushed is special because we store up to 64 events of
+ // this type. Other events will go through the default case in
+ // SnapshotLifecycleEvent() where they will be given a max history of 1.
+ lifecycle_events.emplace_back(
+ protos::pbzero::TracingServiceEvent::kAllDataSourcesFlushedFieldNumber,
+ 64 /* max_size */);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TracingServiceImpl::RelayEndpointImpl implementation
+////////////////////////////////////////////////////////////////////////////////
+TracingServiceImpl::RelayEndpointImpl::RelayEndpointImpl(
+ RelayClientID relay_client_id,
+ TracingServiceImpl* service)
+ : relay_client_id_(relay_client_id), service_(service) {}
+TracingServiceImpl::RelayEndpointImpl::~RelayEndpointImpl() = default;
+
+void TracingServiceImpl::RelayEndpointImpl::SyncClocks(
+ SyncMode sync_mode,
+ ClockSnapshotVector client_clocks,
+ ClockSnapshotVector host_clocks) {
+ // We keep only the most recent 5 clock sync snapshots.
+ static constexpr size_t kNumSyncClocks = 5;
+ if (synced_clocks_.size() >= kNumSyncClocks)
+ synced_clocks_.pop_front();
+
+ synced_clocks_.emplace_back(sync_mode, std::move(client_clocks),
+ std::move(host_clocks));
+}
+
+void TracingServiceImpl::RelayEndpointImpl::Disconnect() {
+ service_->DisconnectRelayClient(relay_client_id_);
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/in_process_tracing_backend.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/in_process_tracing_backend.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/paged_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/client_identity.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+
+// gen_amalgamated expanded: #include "src/tracing/core/in_process_shared_memory.h"
+
+// TODO(primiano): When the in-process backend is used, we should never end up
+// in a situation where the thread where the TracingService and Producer live
+// writes a packet and hence can get into the GetNewChunk() stall.
+// This would happen only if the API client code calls Trace() from one of the
+// callbacks it receives (e.g. OnStart(), OnStop()). We should either cause a
+// hard crash or ignore traces from that thread if that happens, because it
+// will deadlock (the Service will never free up the SMB because won't ever get
+// to run the task).
+
+namespace perfetto {
+namespace internal {
+
+// static
+TracingBackend* InProcessTracingBackend::GetInstance() {
+ static auto* instance = new InProcessTracingBackend();
+ return instance;
+}
+
+InProcessTracingBackend::InProcessTracingBackend() = default;
+InProcessTracingBackend::~InProcessTracingBackend() = default;
+
+std::unique_ptr<ProducerEndpoint> InProcessTracingBackend::ConnectProducer(
+ const ConnectProducerArgs& args) {
+ PERFETTO_DCHECK(args.task_runner->RunsTasksOnCurrentThread());
+ return GetOrCreateService(args.task_runner)
+ ->ConnectProducer(args.producer, ClientIdentity(/*uid=*/0, /*pid=*/0),
+ args.producer_name, args.shmem_size_hint_bytes,
+ /*in_process=*/true,
+ TracingService::ProducerSMBScrapingMode::kEnabled,
+ args.shmem_page_size_hint_bytes);
+}
+
+std::unique_ptr<ConsumerEndpoint> InProcessTracingBackend::ConnectConsumer(
+ const ConnectConsumerArgs& args) {
+ return GetOrCreateService(args.task_runner)
+ ->ConnectConsumer(args.consumer, /*uid=*/0);
+}
+
+TracingService* InProcessTracingBackend::GetOrCreateService(
+ base::TaskRunner* task_runner) {
+ if (!service_) {
+ std::unique_ptr<InProcessSharedMemory::Factory> shm(
+ new InProcessSharedMemory::Factory());
+ service_ = TracingService::CreateInstance(std::move(shm), task_runner);
+ service_->SetSMBScrapingEnabled(true);
+ }
+ return service_.get();
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: gen/protos/perfetto/ipc/consumer_port.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/consumer_port.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/system_info/system_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/track_event/track_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/test_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/sys_stats_counters.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/perf_events.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/statsd_tracing_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/atom_ids.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/power/android_power_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/inode_file/inode_file_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/vulkan_memory_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/gpu_counter_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/etw/etw_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/v8_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/chrome_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_layers_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/protolog_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/protolog_common.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/packages_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/network_trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_system_property_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_polled_state_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_log_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_log_constants.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_input_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_game_intervention_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/trace_stats.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_capabilities.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/observable_events.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_state.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/track_event_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/gpu_counter_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/ftrace_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/observable_events.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+CloneSessionResponse::CloneSessionResponse() = default;
+CloneSessionResponse::~CloneSessionResponse() = default;
+CloneSessionResponse::CloneSessionResponse(const CloneSessionResponse&) = default;
+CloneSessionResponse& CloneSessionResponse::operator=(const CloneSessionResponse&) = default;
+CloneSessionResponse::CloneSessionResponse(CloneSessionResponse&&) noexcept = default;
+CloneSessionResponse& CloneSessionResponse::operator=(CloneSessionResponse&&) = default;
+
+bool CloneSessionResponse::operator==(const CloneSessionResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(success_, other.success_)
+ && ::protozero::internal::gen_helpers::EqualsField(error_, other.error_)
+ && ::protozero::internal::gen_helpers::EqualsField(uuid_msb_, other.uuid_msb_)
+ && ::protozero::internal::gen_helpers::EqualsField(uuid_lsb_, other.uuid_lsb_);
+}
+
+bool CloneSessionResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* success */:
+ field.get(&success_);
+ break;
+ case 2 /* error */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &error_);
+ break;
+ case 3 /* uuid_msb */:
+ field.get(&uuid_msb_);
+ break;
+ case 4 /* uuid_lsb */:
+ field.get(&uuid_lsb_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CloneSessionResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CloneSessionResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CloneSessionResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: success
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, success_, msg);
+ }
+
+ // Field 2: error
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, error_, msg);
+ }
+
+ // Field 3: uuid_msb
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, uuid_msb_, msg);
+ }
+
+ // Field 4: uuid_lsb
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, uuid_lsb_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+CloneSessionRequest::CloneSessionRequest() = default;
+CloneSessionRequest::~CloneSessionRequest() = default;
+CloneSessionRequest::CloneSessionRequest(const CloneSessionRequest&) = default;
+CloneSessionRequest& CloneSessionRequest::operator=(const CloneSessionRequest&) = default;
+CloneSessionRequest::CloneSessionRequest(CloneSessionRequest&&) noexcept = default;
+CloneSessionRequest& CloneSessionRequest::operator=(CloneSessionRequest&&) = default;
+
+bool CloneSessionRequest::operator==(const CloneSessionRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(session_id_, other.session_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(skip_trace_filter_, other.skip_trace_filter_)
+ && ::protozero::internal::gen_helpers::EqualsField(for_bugreport_, other.for_bugreport_);
+}
+
+bool CloneSessionRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* session_id */:
+ field.get(&session_id_);
+ break;
+ case 2 /* skip_trace_filter */:
+ field.get(&skip_trace_filter_);
+ break;
+ case 3 /* for_bugreport */:
+ field.get(&for_bugreport_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CloneSessionRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CloneSessionRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CloneSessionRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: session_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, session_id_, msg);
+ }
+
+ // Field 2: skip_trace_filter
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, skip_trace_filter_, msg);
+ }
+
+ // Field 3: for_bugreport
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, for_bugreport_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+SaveTraceForBugreportResponse::SaveTraceForBugreportResponse() = default;
+SaveTraceForBugreportResponse::~SaveTraceForBugreportResponse() = default;
+SaveTraceForBugreportResponse::SaveTraceForBugreportResponse(const SaveTraceForBugreportResponse&) = default;
+SaveTraceForBugreportResponse& SaveTraceForBugreportResponse::operator=(const SaveTraceForBugreportResponse&) = default;
+SaveTraceForBugreportResponse::SaveTraceForBugreportResponse(SaveTraceForBugreportResponse&&) noexcept = default;
+SaveTraceForBugreportResponse& SaveTraceForBugreportResponse::operator=(SaveTraceForBugreportResponse&&) = default;
+
+bool SaveTraceForBugreportResponse::operator==(const SaveTraceForBugreportResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(success_, other.success_)
+ && ::protozero::internal::gen_helpers::EqualsField(msg_, other.msg_);
+}
+
+bool SaveTraceForBugreportResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* success */:
+ field.get(&success_);
+ break;
+ case 2 /* msg */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &msg_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SaveTraceForBugreportResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SaveTraceForBugreportResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SaveTraceForBugreportResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: success
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, success_, msg);
+ }
+
+ // Field 2: msg
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, msg_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+SaveTraceForBugreportRequest::SaveTraceForBugreportRequest() = default;
+SaveTraceForBugreportRequest::~SaveTraceForBugreportRequest() = default;
+SaveTraceForBugreportRequest::SaveTraceForBugreportRequest(const SaveTraceForBugreportRequest&) = default;
+SaveTraceForBugreportRequest& SaveTraceForBugreportRequest::operator=(const SaveTraceForBugreportRequest&) = default;
+SaveTraceForBugreportRequest::SaveTraceForBugreportRequest(SaveTraceForBugreportRequest&&) noexcept = default;
+SaveTraceForBugreportRequest& SaveTraceForBugreportRequest::operator=(SaveTraceForBugreportRequest&&) = default;
+
+bool SaveTraceForBugreportRequest::operator==(const SaveTraceForBugreportRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool SaveTraceForBugreportRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SaveTraceForBugreportRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SaveTraceForBugreportRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SaveTraceForBugreportRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+QueryCapabilitiesResponse::QueryCapabilitiesResponse() = default;
+QueryCapabilitiesResponse::~QueryCapabilitiesResponse() = default;
+QueryCapabilitiesResponse::QueryCapabilitiesResponse(const QueryCapabilitiesResponse&) = default;
+QueryCapabilitiesResponse& QueryCapabilitiesResponse::operator=(const QueryCapabilitiesResponse&) = default;
+QueryCapabilitiesResponse::QueryCapabilitiesResponse(QueryCapabilitiesResponse&&) noexcept = default;
+QueryCapabilitiesResponse& QueryCapabilitiesResponse::operator=(QueryCapabilitiesResponse&&) = default;
+
+bool QueryCapabilitiesResponse::operator==(const QueryCapabilitiesResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(capabilities_, other.capabilities_);
+}
+
+bool QueryCapabilitiesResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* capabilities */:
+ (*capabilities_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string QueryCapabilitiesResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> QueryCapabilitiesResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void QueryCapabilitiesResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: capabilities
+ if (_has_field_[1]) {
+ (*capabilities_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+QueryCapabilitiesRequest::QueryCapabilitiesRequest() = default;
+QueryCapabilitiesRequest::~QueryCapabilitiesRequest() = default;
+QueryCapabilitiesRequest::QueryCapabilitiesRequest(const QueryCapabilitiesRequest&) = default;
+QueryCapabilitiesRequest& QueryCapabilitiesRequest::operator=(const QueryCapabilitiesRequest&) = default;
+QueryCapabilitiesRequest::QueryCapabilitiesRequest(QueryCapabilitiesRequest&&) noexcept = default;
+QueryCapabilitiesRequest& QueryCapabilitiesRequest::operator=(QueryCapabilitiesRequest&&) = default;
+
+bool QueryCapabilitiesRequest::operator==(const QueryCapabilitiesRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool QueryCapabilitiesRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string QueryCapabilitiesRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> QueryCapabilitiesRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void QueryCapabilitiesRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+QueryServiceStateResponse::QueryServiceStateResponse() = default;
+QueryServiceStateResponse::~QueryServiceStateResponse() = default;
+QueryServiceStateResponse::QueryServiceStateResponse(const QueryServiceStateResponse&) = default;
+QueryServiceStateResponse& QueryServiceStateResponse::operator=(const QueryServiceStateResponse&) = default;
+QueryServiceStateResponse::QueryServiceStateResponse(QueryServiceStateResponse&&) noexcept = default;
+QueryServiceStateResponse& QueryServiceStateResponse::operator=(QueryServiceStateResponse&&) = default;
+
+bool QueryServiceStateResponse::operator==(const QueryServiceStateResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(service_state_, other.service_state_);
+}
+
+bool QueryServiceStateResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* service_state */:
+ (*service_state_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string QueryServiceStateResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> QueryServiceStateResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void QueryServiceStateResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: service_state
+ if (_has_field_[1]) {
+ (*service_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+QueryServiceStateRequest::QueryServiceStateRequest() = default;
+QueryServiceStateRequest::~QueryServiceStateRequest() = default;
+QueryServiceStateRequest::QueryServiceStateRequest(const QueryServiceStateRequest&) = default;
+QueryServiceStateRequest& QueryServiceStateRequest::operator=(const QueryServiceStateRequest&) = default;
+QueryServiceStateRequest::QueryServiceStateRequest(QueryServiceStateRequest&&) noexcept = default;
+QueryServiceStateRequest& QueryServiceStateRequest::operator=(QueryServiceStateRequest&&) = default;
+
+bool QueryServiceStateRequest::operator==(const QueryServiceStateRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(sessions_only_, other.sessions_only_);
+}
+
+bool QueryServiceStateRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* sessions_only */:
+ field.get(&sessions_only_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string QueryServiceStateRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> QueryServiceStateRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void QueryServiceStateRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: sessions_only
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, sessions_only_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ObserveEventsResponse::ObserveEventsResponse() = default;
+ObserveEventsResponse::~ObserveEventsResponse() = default;
+ObserveEventsResponse::ObserveEventsResponse(const ObserveEventsResponse&) = default;
+ObserveEventsResponse& ObserveEventsResponse::operator=(const ObserveEventsResponse&) = default;
+ObserveEventsResponse::ObserveEventsResponse(ObserveEventsResponse&&) noexcept = default;
+ObserveEventsResponse& ObserveEventsResponse::operator=(ObserveEventsResponse&&) = default;
+
+bool ObserveEventsResponse::operator==(const ObserveEventsResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(events_, other.events_);
+}
+
+bool ObserveEventsResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* events */:
+ (*events_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ObserveEventsResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ObserveEventsResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ObserveEventsResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: events
+ if (_has_field_[1]) {
+ (*events_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ObserveEventsRequest::ObserveEventsRequest() = default;
+ObserveEventsRequest::~ObserveEventsRequest() = default;
+ObserveEventsRequest::ObserveEventsRequest(const ObserveEventsRequest&) = default;
+ObserveEventsRequest& ObserveEventsRequest::operator=(const ObserveEventsRequest&) = default;
+ObserveEventsRequest::ObserveEventsRequest(ObserveEventsRequest&&) noexcept = default;
+ObserveEventsRequest& ObserveEventsRequest::operator=(ObserveEventsRequest&&) = default;
+
+bool ObserveEventsRequest::operator==(const ObserveEventsRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(events_to_observe_, other.events_to_observe_);
+}
+
+bool ObserveEventsRequest::ParseFromArray(const void* raw, size_t size) {
+ events_to_observe_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* events_to_observe */:
+ events_to_observe_.emplace_back();
+ field.get(&events_to_observe_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ObserveEventsRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ObserveEventsRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ObserveEventsRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: events_to_observe
+ for (auto& it : events_to_observe_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetTraceStatsResponse::GetTraceStatsResponse() = default;
+GetTraceStatsResponse::~GetTraceStatsResponse() = default;
+GetTraceStatsResponse::GetTraceStatsResponse(const GetTraceStatsResponse&) = default;
+GetTraceStatsResponse& GetTraceStatsResponse::operator=(const GetTraceStatsResponse&) = default;
+GetTraceStatsResponse::GetTraceStatsResponse(GetTraceStatsResponse&&) noexcept = default;
+GetTraceStatsResponse& GetTraceStatsResponse::operator=(GetTraceStatsResponse&&) = default;
+
+bool GetTraceStatsResponse::operator==(const GetTraceStatsResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_stats_, other.trace_stats_);
+}
+
+bool GetTraceStatsResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_stats */:
+ (*trace_stats_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetTraceStatsResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetTraceStatsResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetTraceStatsResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_stats
+ if (_has_field_[1]) {
+ (*trace_stats_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetTraceStatsRequest::GetTraceStatsRequest() = default;
+GetTraceStatsRequest::~GetTraceStatsRequest() = default;
+GetTraceStatsRequest::GetTraceStatsRequest(const GetTraceStatsRequest&) = default;
+GetTraceStatsRequest& GetTraceStatsRequest::operator=(const GetTraceStatsRequest&) = default;
+GetTraceStatsRequest::GetTraceStatsRequest(GetTraceStatsRequest&&) noexcept = default;
+GetTraceStatsRequest& GetTraceStatsRequest::operator=(GetTraceStatsRequest&&) = default;
+
+bool GetTraceStatsRequest::operator==(const GetTraceStatsRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool GetTraceStatsRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetTraceStatsRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetTraceStatsRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetTraceStatsRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+AttachResponse::AttachResponse() = default;
+AttachResponse::~AttachResponse() = default;
+AttachResponse::AttachResponse(const AttachResponse&) = default;
+AttachResponse& AttachResponse::operator=(const AttachResponse&) = default;
+AttachResponse::AttachResponse(AttachResponse&&) noexcept = default;
+AttachResponse& AttachResponse::operator=(AttachResponse&&) = default;
+
+bool AttachResponse::operator==(const AttachResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_config_, other.trace_config_);
+}
+
+bool AttachResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_config */:
+ (*trace_config_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AttachResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AttachResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AttachResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_config
+ if (_has_field_[1]) {
+ (*trace_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+AttachRequest::AttachRequest() = default;
+AttachRequest::~AttachRequest() = default;
+AttachRequest::AttachRequest(const AttachRequest&) = default;
+AttachRequest& AttachRequest::operator=(const AttachRequest&) = default;
+AttachRequest::AttachRequest(AttachRequest&&) noexcept = default;
+AttachRequest& AttachRequest::operator=(AttachRequest&&) = default;
+
+bool AttachRequest::operator==(const AttachRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(key_, other.key_);
+}
+
+bool AttachRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* key */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &key_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string AttachRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> AttachRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void AttachRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: key
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, key_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DetachResponse::DetachResponse() = default;
+DetachResponse::~DetachResponse() = default;
+DetachResponse::DetachResponse(const DetachResponse&) = default;
+DetachResponse& DetachResponse::operator=(const DetachResponse&) = default;
+DetachResponse::DetachResponse(DetachResponse&&) noexcept = default;
+DetachResponse& DetachResponse::operator=(DetachResponse&&) = default;
+
+bool DetachResponse::operator==(const DetachResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool DetachResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DetachResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DetachResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DetachResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DetachRequest::DetachRequest() = default;
+DetachRequest::~DetachRequest() = default;
+DetachRequest::DetachRequest(const DetachRequest&) = default;
+DetachRequest& DetachRequest::operator=(const DetachRequest&) = default;
+DetachRequest::DetachRequest(DetachRequest&&) noexcept = default;
+DetachRequest& DetachRequest::operator=(DetachRequest&&) = default;
+
+bool DetachRequest::operator==(const DetachRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(key_, other.key_);
+}
+
+bool DetachRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* key */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &key_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DetachRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DetachRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DetachRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: key
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, key_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FlushResponse::FlushResponse() = default;
+FlushResponse::~FlushResponse() = default;
+FlushResponse::FlushResponse(const FlushResponse&) = default;
+FlushResponse& FlushResponse::operator=(const FlushResponse&) = default;
+FlushResponse::FlushResponse(FlushResponse&&) noexcept = default;
+FlushResponse& FlushResponse::operator=(FlushResponse&&) = default;
+
+bool FlushResponse::operator==(const FlushResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool FlushResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FlushResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FlushResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FlushResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FlushRequest::FlushRequest() = default;
+FlushRequest::~FlushRequest() = default;
+FlushRequest::FlushRequest(const FlushRequest&) = default;
+FlushRequest& FlushRequest::operator=(const FlushRequest&) = default;
+FlushRequest::FlushRequest(FlushRequest&&) noexcept = default;
+FlushRequest& FlushRequest::operator=(FlushRequest&&) = default;
+
+bool FlushRequest::operator==(const FlushRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(timeout_ms_, other.timeout_ms_)
+ && ::protozero::internal::gen_helpers::EqualsField(flags_, other.flags_);
+}
+
+bool FlushRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* timeout_ms */:
+ field.get(&timeout_ms_);
+ break;
+ case 2 /* flags */:
+ field.get(&flags_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FlushRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FlushRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FlushRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: timeout_ms
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, timeout_ms_, msg);
+ }
+
+ // Field 2: flags
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, flags_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FreeBuffersResponse::FreeBuffersResponse() = default;
+FreeBuffersResponse::~FreeBuffersResponse() = default;
+FreeBuffersResponse::FreeBuffersResponse(const FreeBuffersResponse&) = default;
+FreeBuffersResponse& FreeBuffersResponse::operator=(const FreeBuffersResponse&) = default;
+FreeBuffersResponse::FreeBuffersResponse(FreeBuffersResponse&&) noexcept = default;
+FreeBuffersResponse& FreeBuffersResponse::operator=(FreeBuffersResponse&&) = default;
+
+bool FreeBuffersResponse::operator==(const FreeBuffersResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool FreeBuffersResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FreeBuffersResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FreeBuffersResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FreeBuffersResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+FreeBuffersRequest::FreeBuffersRequest() = default;
+FreeBuffersRequest::~FreeBuffersRequest() = default;
+FreeBuffersRequest::FreeBuffersRequest(const FreeBuffersRequest&) = default;
+FreeBuffersRequest& FreeBuffersRequest::operator=(const FreeBuffersRequest&) = default;
+FreeBuffersRequest::FreeBuffersRequest(FreeBuffersRequest&&) noexcept = default;
+FreeBuffersRequest& FreeBuffersRequest::operator=(FreeBuffersRequest&&) = default;
+
+bool FreeBuffersRequest::operator==(const FreeBuffersRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(buffer_ids_, other.buffer_ids_);
+}
+
+bool FreeBuffersRequest::ParseFromArray(const void* raw, size_t size) {
+ buffer_ids_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* buffer_ids */:
+ buffer_ids_.emplace_back();
+ field.get(&buffer_ids_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string FreeBuffersRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> FreeBuffersRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void FreeBuffersRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: buffer_ids
+ for (auto& it : buffer_ids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ReadBuffersResponse::ReadBuffersResponse() = default;
+ReadBuffersResponse::~ReadBuffersResponse() = default;
+ReadBuffersResponse::ReadBuffersResponse(const ReadBuffersResponse&) = default;
+ReadBuffersResponse& ReadBuffersResponse::operator=(const ReadBuffersResponse&) = default;
+ReadBuffersResponse::ReadBuffersResponse(ReadBuffersResponse&&) noexcept = default;
+ReadBuffersResponse& ReadBuffersResponse::operator=(ReadBuffersResponse&&) = default;
+
+bool ReadBuffersResponse::operator==(const ReadBuffersResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(slices_, other.slices_);
+}
+
+int ReadBuffersResponse::slices_size() const { return static_cast<int>(slices_.size()); }
+void ReadBuffersResponse::clear_slices() { slices_.clear(); }
+ReadBuffersResponse_Slice* ReadBuffersResponse::add_slices() { slices_.emplace_back(); return &slices_.back(); }
+bool ReadBuffersResponse::ParseFromArray(const void* raw, size_t size) {
+ slices_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 2 /* slices */:
+ slices_.emplace_back();
+ slices_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ReadBuffersResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ReadBuffersResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ReadBuffersResponse::Serialize(::protozero::Message* msg) const {
+ // Field 2: slices
+ for (auto& it : slices_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ReadBuffersResponse_Slice::ReadBuffersResponse_Slice() = default;
+ReadBuffersResponse_Slice::~ReadBuffersResponse_Slice() = default;
+ReadBuffersResponse_Slice::ReadBuffersResponse_Slice(const ReadBuffersResponse_Slice&) = default;
+ReadBuffersResponse_Slice& ReadBuffersResponse_Slice::operator=(const ReadBuffersResponse_Slice&) = default;
+ReadBuffersResponse_Slice::ReadBuffersResponse_Slice(ReadBuffersResponse_Slice&&) noexcept = default;
+ReadBuffersResponse_Slice& ReadBuffersResponse_Slice::operator=(ReadBuffersResponse_Slice&&) = default;
+
+bool ReadBuffersResponse_Slice::operator==(const ReadBuffersResponse_Slice& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_, other.data_)
+ && ::protozero::internal::gen_helpers::EqualsField(last_slice_for_packet_, other.last_slice_for_packet_);
+}
+
+bool ReadBuffersResponse_Slice::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data */:
+ field.get(&data_);
+ break;
+ case 2 /* last_slice_for_packet */:
+ field.get(&last_slice_for_packet_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ReadBuffersResponse_Slice::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ReadBuffersResponse_Slice::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ReadBuffersResponse_Slice::Serialize(::protozero::Message* msg) const {
+ // Field 1: data
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, data_, msg);
+ }
+
+ // Field 2: last_slice_for_packet
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, last_slice_for_packet_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ReadBuffersRequest::ReadBuffersRequest() = default;
+ReadBuffersRequest::~ReadBuffersRequest() = default;
+ReadBuffersRequest::ReadBuffersRequest(const ReadBuffersRequest&) = default;
+ReadBuffersRequest& ReadBuffersRequest::operator=(const ReadBuffersRequest&) = default;
+ReadBuffersRequest::ReadBuffersRequest(ReadBuffersRequest&&) noexcept = default;
+ReadBuffersRequest& ReadBuffersRequest::operator=(ReadBuffersRequest&&) = default;
+
+bool ReadBuffersRequest::operator==(const ReadBuffersRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool ReadBuffersRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ReadBuffersRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ReadBuffersRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ReadBuffersRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DisableTracingResponse::DisableTracingResponse() = default;
+DisableTracingResponse::~DisableTracingResponse() = default;
+DisableTracingResponse::DisableTracingResponse(const DisableTracingResponse&) = default;
+DisableTracingResponse& DisableTracingResponse::operator=(const DisableTracingResponse&) = default;
+DisableTracingResponse::DisableTracingResponse(DisableTracingResponse&&) noexcept = default;
+DisableTracingResponse& DisableTracingResponse::operator=(DisableTracingResponse&&) = default;
+
+bool DisableTracingResponse::operator==(const DisableTracingResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool DisableTracingResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DisableTracingResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DisableTracingResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DisableTracingResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+DisableTracingRequest::DisableTracingRequest() = default;
+DisableTracingRequest::~DisableTracingRequest() = default;
+DisableTracingRequest::DisableTracingRequest(const DisableTracingRequest&) = default;
+DisableTracingRequest& DisableTracingRequest::operator=(const DisableTracingRequest&) = default;
+DisableTracingRequest::DisableTracingRequest(DisableTracingRequest&&) noexcept = default;
+DisableTracingRequest& DisableTracingRequest::operator=(DisableTracingRequest&&) = default;
+
+bool DisableTracingRequest::operator==(const DisableTracingRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool DisableTracingRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string DisableTracingRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> DisableTracingRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void DisableTracingRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChangeTraceConfigResponse::ChangeTraceConfigResponse() = default;
+ChangeTraceConfigResponse::~ChangeTraceConfigResponse() = default;
+ChangeTraceConfigResponse::ChangeTraceConfigResponse(const ChangeTraceConfigResponse&) = default;
+ChangeTraceConfigResponse& ChangeTraceConfigResponse::operator=(const ChangeTraceConfigResponse&) = default;
+ChangeTraceConfigResponse::ChangeTraceConfigResponse(ChangeTraceConfigResponse&&) noexcept = default;
+ChangeTraceConfigResponse& ChangeTraceConfigResponse::operator=(ChangeTraceConfigResponse&&) = default;
+
+bool ChangeTraceConfigResponse::operator==(const ChangeTraceConfigResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool ChangeTraceConfigResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChangeTraceConfigResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChangeTraceConfigResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChangeTraceConfigResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ChangeTraceConfigRequest::ChangeTraceConfigRequest() = default;
+ChangeTraceConfigRequest::~ChangeTraceConfigRequest() = default;
+ChangeTraceConfigRequest::ChangeTraceConfigRequest(const ChangeTraceConfigRequest&) = default;
+ChangeTraceConfigRequest& ChangeTraceConfigRequest::operator=(const ChangeTraceConfigRequest&) = default;
+ChangeTraceConfigRequest::ChangeTraceConfigRequest(ChangeTraceConfigRequest&&) noexcept = default;
+ChangeTraceConfigRequest& ChangeTraceConfigRequest::operator=(ChangeTraceConfigRequest&&) = default;
+
+bool ChangeTraceConfigRequest::operator==(const ChangeTraceConfigRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_config_, other.trace_config_);
+}
+
+bool ChangeTraceConfigRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_config */:
+ (*trace_config_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ChangeTraceConfigRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ChangeTraceConfigRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ChangeTraceConfigRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_config
+ if (_has_field_[1]) {
+ (*trace_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+StartTracingResponse::StartTracingResponse() = default;
+StartTracingResponse::~StartTracingResponse() = default;
+StartTracingResponse::StartTracingResponse(const StartTracingResponse&) = default;
+StartTracingResponse& StartTracingResponse::operator=(const StartTracingResponse&) = default;
+StartTracingResponse::StartTracingResponse(StartTracingResponse&&) noexcept = default;
+StartTracingResponse& StartTracingResponse::operator=(StartTracingResponse&&) = default;
+
+bool StartTracingResponse::operator==(const StartTracingResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool StartTracingResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string StartTracingResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> StartTracingResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void StartTracingResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+StartTracingRequest::StartTracingRequest() = default;
+StartTracingRequest::~StartTracingRequest() = default;
+StartTracingRequest::StartTracingRequest(const StartTracingRequest&) = default;
+StartTracingRequest& StartTracingRequest::operator=(const StartTracingRequest&) = default;
+StartTracingRequest::StartTracingRequest(StartTracingRequest&&) noexcept = default;
+StartTracingRequest& StartTracingRequest::operator=(StartTracingRequest&&) = default;
+
+bool StartTracingRequest::operator==(const StartTracingRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool StartTracingRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string StartTracingRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> StartTracingRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void StartTracingRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+EnableTracingResponse::EnableTracingResponse() = default;
+EnableTracingResponse::~EnableTracingResponse() = default;
+EnableTracingResponse::EnableTracingResponse(const EnableTracingResponse&) = default;
+EnableTracingResponse& EnableTracingResponse::operator=(const EnableTracingResponse&) = default;
+EnableTracingResponse::EnableTracingResponse(EnableTracingResponse&&) noexcept = default;
+EnableTracingResponse& EnableTracingResponse::operator=(EnableTracingResponse&&) = default;
+
+bool EnableTracingResponse::operator==(const EnableTracingResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(disabled_, other.disabled_)
+ && ::protozero::internal::gen_helpers::EqualsField(error_, other.error_);
+}
+
+bool EnableTracingResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* disabled */:
+ field.get(&disabled_);
+ break;
+ case 3 /* error */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &error_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string EnableTracingResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> EnableTracingResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void EnableTracingResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: disabled
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, disabled_, msg);
+ }
+
+ // Field 3: error
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, error_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+EnableTracingRequest::EnableTracingRequest() = default;
+EnableTracingRequest::~EnableTracingRequest() = default;
+EnableTracingRequest::EnableTracingRequest(const EnableTracingRequest&) = default;
+EnableTracingRequest& EnableTracingRequest::operator=(const EnableTracingRequest&) = default;
+EnableTracingRequest::EnableTracingRequest(EnableTracingRequest&&) noexcept = default;
+EnableTracingRequest& EnableTracingRequest::operator=(EnableTracingRequest&&) = default;
+
+bool EnableTracingRequest::operator==(const EnableTracingRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_config_, other.trace_config_)
+ && ::protozero::internal::gen_helpers::EqualsField(attach_notification_only_, other.attach_notification_only_);
+}
+
+bool EnableTracingRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_config */:
+ (*trace_config_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* attach_notification_only */:
+ field.get(&attach_notification_only_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string EnableTracingRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> EnableTracingRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void EnableTracingRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_config
+ if (_has_field_[1]) {
+ (*trace_config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: attach_notification_only
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, attach_notification_only_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/ipc/producer_port.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/producer_port.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/track_event_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/gpu_counter_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/ftrace_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/system_info/system_info.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/track_event/track_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/test_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/sys_stats_counters.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/perf_events.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/statsd_tracing_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/statsd/atom_ids.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/power/android_power_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptor_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/interceptors/console_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/inode_file/inode_file_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/vulkan_memory_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/gpu/gpu_counter_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/etw/etw_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/v8_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/chrome/chrome_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/surfaceflinger_layers_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/protolog_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/protolog_common.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/packages_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/network_trace_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_system_property_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_polled_state_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_log_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/android_log_constants.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_input_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/android/android_game_intervention_list_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/commit_data_request.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+SyncResponse::SyncResponse() = default;
+SyncResponse::~SyncResponse() = default;
+SyncResponse::SyncResponse(const SyncResponse&) = default;
+SyncResponse& SyncResponse::operator=(const SyncResponse&) = default;
+SyncResponse::SyncResponse(SyncResponse&&) noexcept = default;
+SyncResponse& SyncResponse::operator=(SyncResponse&&) = default;
+
+bool SyncResponse::operator==(const SyncResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool SyncResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SyncResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SyncResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SyncResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+SyncRequest::SyncRequest() = default;
+SyncRequest::~SyncRequest() = default;
+SyncRequest::SyncRequest(const SyncRequest&) = default;
+SyncRequest& SyncRequest::operator=(const SyncRequest&) = default;
+SyncRequest::SyncRequest(SyncRequest&&) noexcept = default;
+SyncRequest& SyncRequest::operator=(SyncRequest&&) = default;
+
+bool SyncRequest::operator==(const SyncRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool SyncRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SyncRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SyncRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SyncRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandResponse::GetAsyncCommandResponse() = default;
+GetAsyncCommandResponse::~GetAsyncCommandResponse() = default;
+GetAsyncCommandResponse::GetAsyncCommandResponse(const GetAsyncCommandResponse&) = default;
+GetAsyncCommandResponse& GetAsyncCommandResponse::operator=(const GetAsyncCommandResponse&) = default;
+GetAsyncCommandResponse::GetAsyncCommandResponse(GetAsyncCommandResponse&&) noexcept = default;
+GetAsyncCommandResponse& GetAsyncCommandResponse::operator=(GetAsyncCommandResponse&&) = default;
+
+bool GetAsyncCommandResponse::operator==(const GetAsyncCommandResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(setup_tracing_, other.setup_tracing_)
+ && ::protozero::internal::gen_helpers::EqualsField(setup_data_source_, other.setup_data_source_)
+ && ::protozero::internal::gen_helpers::EqualsField(start_data_source_, other.start_data_source_)
+ && ::protozero::internal::gen_helpers::EqualsField(stop_data_source_, other.stop_data_source_)
+ && ::protozero::internal::gen_helpers::EqualsField(flush_, other.flush_)
+ && ::protozero::internal::gen_helpers::EqualsField(clear_incremental_state_, other.clear_incremental_state_);
+}
+
+bool GetAsyncCommandResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 3 /* setup_tracing */:
+ (*setup_tracing_).ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* setup_data_source */:
+ (*setup_data_source_).ParseFromArray(field.data(), field.size());
+ break;
+ case 1 /* start_data_source */:
+ (*start_data_source_).ParseFromArray(field.data(), field.size());
+ break;
+ case 2 /* stop_data_source */:
+ (*stop_data_source_).ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* flush */:
+ (*flush_).ParseFromArray(field.data(), field.size());
+ break;
+ case 7 /* clear_incremental_state */:
+ (*clear_incremental_state_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandResponse::Serialize(::protozero::Message* msg) const {
+ // Field 3: setup_tracing
+ if (_has_field_[3]) {
+ (*setup_tracing_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 6: setup_data_source
+ if (_has_field_[6]) {
+ (*setup_data_source_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 1: start_data_source
+ if (_has_field_[1]) {
+ (*start_data_source_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ // Field 2: stop_data_source
+ if (_has_field_[2]) {
+ (*stop_data_source_).Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ // Field 5: flush
+ if (_has_field_[5]) {
+ (*flush_).Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 7: clear_incremental_state
+ if (_has_field_[7]) {
+ (*clear_incremental_state_).Serialize(msg->BeginNestedMessage<::protozero::Message>(7));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandResponse_ClearIncrementalState::GetAsyncCommandResponse_ClearIncrementalState() = default;
+GetAsyncCommandResponse_ClearIncrementalState::~GetAsyncCommandResponse_ClearIncrementalState() = default;
+GetAsyncCommandResponse_ClearIncrementalState::GetAsyncCommandResponse_ClearIncrementalState(const GetAsyncCommandResponse_ClearIncrementalState&) = default;
+GetAsyncCommandResponse_ClearIncrementalState& GetAsyncCommandResponse_ClearIncrementalState::operator=(const GetAsyncCommandResponse_ClearIncrementalState&) = default;
+GetAsyncCommandResponse_ClearIncrementalState::GetAsyncCommandResponse_ClearIncrementalState(GetAsyncCommandResponse_ClearIncrementalState&&) noexcept = default;
+GetAsyncCommandResponse_ClearIncrementalState& GetAsyncCommandResponse_ClearIncrementalState::operator=(GetAsyncCommandResponse_ClearIncrementalState&&) = default;
+
+bool GetAsyncCommandResponse_ClearIncrementalState::operator==(const GetAsyncCommandResponse_ClearIncrementalState& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_ids_, other.data_source_ids_);
+}
+
+bool GetAsyncCommandResponse_ClearIncrementalState::ParseFromArray(const void* raw, size_t size) {
+ data_source_ids_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data_source_ids */:
+ data_source_ids_.emplace_back();
+ field.get(&data_source_ids_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandResponse_ClearIncrementalState::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandResponse_ClearIncrementalState::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandResponse_ClearIncrementalState::Serialize(::protozero::Message* msg) const {
+ // Field 1: data_source_ids
+ for (auto& it : data_source_ids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandResponse_Flush::GetAsyncCommandResponse_Flush() = default;
+GetAsyncCommandResponse_Flush::~GetAsyncCommandResponse_Flush() = default;
+GetAsyncCommandResponse_Flush::GetAsyncCommandResponse_Flush(const GetAsyncCommandResponse_Flush&) = default;
+GetAsyncCommandResponse_Flush& GetAsyncCommandResponse_Flush::operator=(const GetAsyncCommandResponse_Flush&) = default;
+GetAsyncCommandResponse_Flush::GetAsyncCommandResponse_Flush(GetAsyncCommandResponse_Flush&&) noexcept = default;
+GetAsyncCommandResponse_Flush& GetAsyncCommandResponse_Flush::operator=(GetAsyncCommandResponse_Flush&&) = default;
+
+bool GetAsyncCommandResponse_Flush::operator==(const GetAsyncCommandResponse_Flush& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_ids_, other.data_source_ids_)
+ && ::protozero::internal::gen_helpers::EqualsField(request_id_, other.request_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(flags_, other.flags_);
+}
+
+bool GetAsyncCommandResponse_Flush::ParseFromArray(const void* raw, size_t size) {
+ data_source_ids_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data_source_ids */:
+ data_source_ids_.emplace_back();
+ field.get(&data_source_ids_.back());
+ break;
+ case 2 /* request_id */:
+ field.get(&request_id_);
+ break;
+ case 3 /* flags */:
+ field.get(&flags_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandResponse_Flush::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandResponse_Flush::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandResponse_Flush::Serialize(::protozero::Message* msg) const {
+ // Field 1: data_source_ids
+ for (auto& it : data_source_ids_) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, it, msg);
+ }
+
+ // Field 2: request_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, request_id_, msg);
+ }
+
+ // Field 3: flags
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(3, flags_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandResponse_StopDataSource::GetAsyncCommandResponse_StopDataSource() = default;
+GetAsyncCommandResponse_StopDataSource::~GetAsyncCommandResponse_StopDataSource() = default;
+GetAsyncCommandResponse_StopDataSource::GetAsyncCommandResponse_StopDataSource(const GetAsyncCommandResponse_StopDataSource&) = default;
+GetAsyncCommandResponse_StopDataSource& GetAsyncCommandResponse_StopDataSource::operator=(const GetAsyncCommandResponse_StopDataSource&) = default;
+GetAsyncCommandResponse_StopDataSource::GetAsyncCommandResponse_StopDataSource(GetAsyncCommandResponse_StopDataSource&&) noexcept = default;
+GetAsyncCommandResponse_StopDataSource& GetAsyncCommandResponse_StopDataSource::operator=(GetAsyncCommandResponse_StopDataSource&&) = default;
+
+bool GetAsyncCommandResponse_StopDataSource::operator==(const GetAsyncCommandResponse_StopDataSource& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(instance_id_, other.instance_id_);
+}
+
+bool GetAsyncCommandResponse_StopDataSource::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* instance_id */:
+ field.get(&instance_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandResponse_StopDataSource::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandResponse_StopDataSource::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandResponse_StopDataSource::Serialize(::protozero::Message* msg) const {
+ // Field 1: instance_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, instance_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandResponse_StartDataSource::GetAsyncCommandResponse_StartDataSource() = default;
+GetAsyncCommandResponse_StartDataSource::~GetAsyncCommandResponse_StartDataSource() = default;
+GetAsyncCommandResponse_StartDataSource::GetAsyncCommandResponse_StartDataSource(const GetAsyncCommandResponse_StartDataSource&) = default;
+GetAsyncCommandResponse_StartDataSource& GetAsyncCommandResponse_StartDataSource::operator=(const GetAsyncCommandResponse_StartDataSource&) = default;
+GetAsyncCommandResponse_StartDataSource::GetAsyncCommandResponse_StartDataSource(GetAsyncCommandResponse_StartDataSource&&) noexcept = default;
+GetAsyncCommandResponse_StartDataSource& GetAsyncCommandResponse_StartDataSource::operator=(GetAsyncCommandResponse_StartDataSource&&) = default;
+
+bool GetAsyncCommandResponse_StartDataSource::operator==(const GetAsyncCommandResponse_StartDataSource& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(new_instance_id_, other.new_instance_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(config_, other.config_);
+}
+
+bool GetAsyncCommandResponse_StartDataSource::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* new_instance_id */:
+ field.get(&new_instance_id_);
+ break;
+ case 2 /* config */:
+ (*config_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandResponse_StartDataSource::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandResponse_StartDataSource::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandResponse_StartDataSource::Serialize(::protozero::Message* msg) const {
+ // Field 1: new_instance_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, new_instance_id_, msg);
+ }
+
+ // Field 2: config
+ if (_has_field_[2]) {
+ (*config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandResponse_SetupDataSource::GetAsyncCommandResponse_SetupDataSource() = default;
+GetAsyncCommandResponse_SetupDataSource::~GetAsyncCommandResponse_SetupDataSource() = default;
+GetAsyncCommandResponse_SetupDataSource::GetAsyncCommandResponse_SetupDataSource(const GetAsyncCommandResponse_SetupDataSource&) = default;
+GetAsyncCommandResponse_SetupDataSource& GetAsyncCommandResponse_SetupDataSource::operator=(const GetAsyncCommandResponse_SetupDataSource&) = default;
+GetAsyncCommandResponse_SetupDataSource::GetAsyncCommandResponse_SetupDataSource(GetAsyncCommandResponse_SetupDataSource&&) noexcept = default;
+GetAsyncCommandResponse_SetupDataSource& GetAsyncCommandResponse_SetupDataSource::operator=(GetAsyncCommandResponse_SetupDataSource&&) = default;
+
+bool GetAsyncCommandResponse_SetupDataSource::operator==(const GetAsyncCommandResponse_SetupDataSource& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(new_instance_id_, other.new_instance_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(config_, other.config_);
+}
+
+bool GetAsyncCommandResponse_SetupDataSource::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* new_instance_id */:
+ field.get(&new_instance_id_);
+ break;
+ case 2 /* config */:
+ (*config_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandResponse_SetupDataSource::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandResponse_SetupDataSource::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandResponse_SetupDataSource::Serialize(::protozero::Message* msg) const {
+ // Field 1: new_instance_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, new_instance_id_, msg);
+ }
+
+ // Field 2: config
+ if (_has_field_[2]) {
+ (*config_).Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandResponse_SetupTracing::GetAsyncCommandResponse_SetupTracing() = default;
+GetAsyncCommandResponse_SetupTracing::~GetAsyncCommandResponse_SetupTracing() = default;
+GetAsyncCommandResponse_SetupTracing::GetAsyncCommandResponse_SetupTracing(const GetAsyncCommandResponse_SetupTracing&) = default;
+GetAsyncCommandResponse_SetupTracing& GetAsyncCommandResponse_SetupTracing::operator=(const GetAsyncCommandResponse_SetupTracing&) = default;
+GetAsyncCommandResponse_SetupTracing::GetAsyncCommandResponse_SetupTracing(GetAsyncCommandResponse_SetupTracing&&) noexcept = default;
+GetAsyncCommandResponse_SetupTracing& GetAsyncCommandResponse_SetupTracing::operator=(GetAsyncCommandResponse_SetupTracing&&) = default;
+
+bool GetAsyncCommandResponse_SetupTracing::operator==(const GetAsyncCommandResponse_SetupTracing& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(shared_buffer_page_size_kb_, other.shared_buffer_page_size_kb_)
+ && ::protozero::internal::gen_helpers::EqualsField(shm_key_windows_, other.shm_key_windows_);
+}
+
+bool GetAsyncCommandResponse_SetupTracing::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* shared_buffer_page_size_kb */:
+ field.get(&shared_buffer_page_size_kb_);
+ break;
+ case 2 /* shm_key_windows */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &shm_key_windows_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandResponse_SetupTracing::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandResponse_SetupTracing::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandResponse_SetupTracing::Serialize(::protozero::Message* msg) const {
+ // Field 1: shared_buffer_page_size_kb
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, shared_buffer_page_size_kb_, msg);
+ }
+
+ // Field 2: shm_key_windows
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, shm_key_windows_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+GetAsyncCommandRequest::GetAsyncCommandRequest() = default;
+GetAsyncCommandRequest::~GetAsyncCommandRequest() = default;
+GetAsyncCommandRequest::GetAsyncCommandRequest(const GetAsyncCommandRequest&) = default;
+GetAsyncCommandRequest& GetAsyncCommandRequest::operator=(const GetAsyncCommandRequest&) = default;
+GetAsyncCommandRequest::GetAsyncCommandRequest(GetAsyncCommandRequest&&) noexcept = default;
+GetAsyncCommandRequest& GetAsyncCommandRequest::operator=(GetAsyncCommandRequest&&) = default;
+
+bool GetAsyncCommandRequest::operator==(const GetAsyncCommandRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool GetAsyncCommandRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string GetAsyncCommandRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> GetAsyncCommandRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void GetAsyncCommandRequest::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ActivateTriggersResponse::ActivateTriggersResponse() = default;
+ActivateTriggersResponse::~ActivateTriggersResponse() = default;
+ActivateTriggersResponse::ActivateTriggersResponse(const ActivateTriggersResponse&) = default;
+ActivateTriggersResponse& ActivateTriggersResponse::operator=(const ActivateTriggersResponse&) = default;
+ActivateTriggersResponse::ActivateTriggersResponse(ActivateTriggersResponse&&) noexcept = default;
+ActivateTriggersResponse& ActivateTriggersResponse::operator=(ActivateTriggersResponse&&) = default;
+
+bool ActivateTriggersResponse::operator==(const ActivateTriggersResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool ActivateTriggersResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ActivateTriggersResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ActivateTriggersResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ActivateTriggersResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+ActivateTriggersRequest::ActivateTriggersRequest() = default;
+ActivateTriggersRequest::~ActivateTriggersRequest() = default;
+ActivateTriggersRequest::ActivateTriggersRequest(const ActivateTriggersRequest&) = default;
+ActivateTriggersRequest& ActivateTriggersRequest::operator=(const ActivateTriggersRequest&) = default;
+ActivateTriggersRequest::ActivateTriggersRequest(ActivateTriggersRequest&&) noexcept = default;
+ActivateTriggersRequest& ActivateTriggersRequest::operator=(ActivateTriggersRequest&&) = default;
+
+bool ActivateTriggersRequest::operator==(const ActivateTriggersRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trigger_names_, other.trigger_names_);
+}
+
+bool ActivateTriggersRequest::ParseFromArray(const void* raw, size_t size) {
+ trigger_names_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trigger_names */:
+ trigger_names_.emplace_back();
+ ::protozero::internal::gen_helpers::DeserializeString(field, &trigger_names_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string ActivateTriggersRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> ActivateTriggersRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void ActivateTriggersRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: trigger_names
+ for (auto& it : trigger_names_) {
+ ::protozero::internal::gen_helpers::SerializeString(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+NotifyDataSourceStoppedResponse::NotifyDataSourceStoppedResponse() = default;
+NotifyDataSourceStoppedResponse::~NotifyDataSourceStoppedResponse() = default;
+NotifyDataSourceStoppedResponse::NotifyDataSourceStoppedResponse(const NotifyDataSourceStoppedResponse&) = default;
+NotifyDataSourceStoppedResponse& NotifyDataSourceStoppedResponse::operator=(const NotifyDataSourceStoppedResponse&) = default;
+NotifyDataSourceStoppedResponse::NotifyDataSourceStoppedResponse(NotifyDataSourceStoppedResponse&&) noexcept = default;
+NotifyDataSourceStoppedResponse& NotifyDataSourceStoppedResponse::operator=(NotifyDataSourceStoppedResponse&&) = default;
+
+bool NotifyDataSourceStoppedResponse::operator==(const NotifyDataSourceStoppedResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool NotifyDataSourceStoppedResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string NotifyDataSourceStoppedResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> NotifyDataSourceStoppedResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void NotifyDataSourceStoppedResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+NotifyDataSourceStoppedRequest::NotifyDataSourceStoppedRequest() = default;
+NotifyDataSourceStoppedRequest::~NotifyDataSourceStoppedRequest() = default;
+NotifyDataSourceStoppedRequest::NotifyDataSourceStoppedRequest(const NotifyDataSourceStoppedRequest&) = default;
+NotifyDataSourceStoppedRequest& NotifyDataSourceStoppedRequest::operator=(const NotifyDataSourceStoppedRequest&) = default;
+NotifyDataSourceStoppedRequest::NotifyDataSourceStoppedRequest(NotifyDataSourceStoppedRequest&&) noexcept = default;
+NotifyDataSourceStoppedRequest& NotifyDataSourceStoppedRequest::operator=(NotifyDataSourceStoppedRequest&&) = default;
+
+bool NotifyDataSourceStoppedRequest::operator==(const NotifyDataSourceStoppedRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_id_, other.data_source_id_);
+}
+
+bool NotifyDataSourceStoppedRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data_source_id */:
+ field.get(&data_source_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string NotifyDataSourceStoppedRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> NotifyDataSourceStoppedRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void NotifyDataSourceStoppedRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: data_source_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, data_source_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+NotifyDataSourceStartedResponse::NotifyDataSourceStartedResponse() = default;
+NotifyDataSourceStartedResponse::~NotifyDataSourceStartedResponse() = default;
+NotifyDataSourceStartedResponse::NotifyDataSourceStartedResponse(const NotifyDataSourceStartedResponse&) = default;
+NotifyDataSourceStartedResponse& NotifyDataSourceStartedResponse::operator=(const NotifyDataSourceStartedResponse&) = default;
+NotifyDataSourceStartedResponse::NotifyDataSourceStartedResponse(NotifyDataSourceStartedResponse&&) noexcept = default;
+NotifyDataSourceStartedResponse& NotifyDataSourceStartedResponse::operator=(NotifyDataSourceStartedResponse&&) = default;
+
+bool NotifyDataSourceStartedResponse::operator==(const NotifyDataSourceStartedResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool NotifyDataSourceStartedResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string NotifyDataSourceStartedResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> NotifyDataSourceStartedResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void NotifyDataSourceStartedResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+NotifyDataSourceStartedRequest::NotifyDataSourceStartedRequest() = default;
+NotifyDataSourceStartedRequest::~NotifyDataSourceStartedRequest() = default;
+NotifyDataSourceStartedRequest::NotifyDataSourceStartedRequest(const NotifyDataSourceStartedRequest&) = default;
+NotifyDataSourceStartedRequest& NotifyDataSourceStartedRequest::operator=(const NotifyDataSourceStartedRequest&) = default;
+NotifyDataSourceStartedRequest::NotifyDataSourceStartedRequest(NotifyDataSourceStartedRequest&&) noexcept = default;
+NotifyDataSourceStartedRequest& NotifyDataSourceStartedRequest::operator=(NotifyDataSourceStartedRequest&&) = default;
+
+bool NotifyDataSourceStartedRequest::operator==(const NotifyDataSourceStartedRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_id_, other.data_source_id_);
+}
+
+bool NotifyDataSourceStartedRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data_source_id */:
+ field.get(&data_source_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string NotifyDataSourceStartedRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> NotifyDataSourceStartedRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void NotifyDataSourceStartedRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: data_source_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, data_source_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+CommitDataResponse::CommitDataResponse() = default;
+CommitDataResponse::~CommitDataResponse() = default;
+CommitDataResponse::CommitDataResponse(const CommitDataResponse&) = default;
+CommitDataResponse& CommitDataResponse::operator=(const CommitDataResponse&) = default;
+CommitDataResponse::CommitDataResponse(CommitDataResponse&&) noexcept = default;
+CommitDataResponse& CommitDataResponse::operator=(CommitDataResponse&&) = default;
+
+bool CommitDataResponse::operator==(const CommitDataResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool CommitDataResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string CommitDataResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> CommitDataResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void CommitDataResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UnregisterTraceWriterResponse::UnregisterTraceWriterResponse() = default;
+UnregisterTraceWriterResponse::~UnregisterTraceWriterResponse() = default;
+UnregisterTraceWriterResponse::UnregisterTraceWriterResponse(const UnregisterTraceWriterResponse&) = default;
+UnregisterTraceWriterResponse& UnregisterTraceWriterResponse::operator=(const UnregisterTraceWriterResponse&) = default;
+UnregisterTraceWriterResponse::UnregisterTraceWriterResponse(UnregisterTraceWriterResponse&&) noexcept = default;
+UnregisterTraceWriterResponse& UnregisterTraceWriterResponse::operator=(UnregisterTraceWriterResponse&&) = default;
+
+bool UnregisterTraceWriterResponse::operator==(const UnregisterTraceWriterResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool UnregisterTraceWriterResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UnregisterTraceWriterResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UnregisterTraceWriterResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UnregisterTraceWriterResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UnregisterTraceWriterRequest::UnregisterTraceWriterRequest() = default;
+UnregisterTraceWriterRequest::~UnregisterTraceWriterRequest() = default;
+UnregisterTraceWriterRequest::UnregisterTraceWriterRequest(const UnregisterTraceWriterRequest&) = default;
+UnregisterTraceWriterRequest& UnregisterTraceWriterRequest::operator=(const UnregisterTraceWriterRequest&) = default;
+UnregisterTraceWriterRequest::UnregisterTraceWriterRequest(UnregisterTraceWriterRequest&&) noexcept = default;
+UnregisterTraceWriterRequest& UnregisterTraceWriterRequest::operator=(UnregisterTraceWriterRequest&&) = default;
+
+bool UnregisterTraceWriterRequest::operator==(const UnregisterTraceWriterRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_writer_id_, other.trace_writer_id_);
+}
+
+bool UnregisterTraceWriterRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_writer_id */:
+ field.get(&trace_writer_id_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UnregisterTraceWriterRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UnregisterTraceWriterRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UnregisterTraceWriterRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_writer_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, trace_writer_id_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+RegisterTraceWriterResponse::RegisterTraceWriterResponse() = default;
+RegisterTraceWriterResponse::~RegisterTraceWriterResponse() = default;
+RegisterTraceWriterResponse::RegisterTraceWriterResponse(const RegisterTraceWriterResponse&) = default;
+RegisterTraceWriterResponse& RegisterTraceWriterResponse::operator=(const RegisterTraceWriterResponse&) = default;
+RegisterTraceWriterResponse::RegisterTraceWriterResponse(RegisterTraceWriterResponse&&) noexcept = default;
+RegisterTraceWriterResponse& RegisterTraceWriterResponse::operator=(RegisterTraceWriterResponse&&) = default;
+
+bool RegisterTraceWriterResponse::operator==(const RegisterTraceWriterResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool RegisterTraceWriterResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string RegisterTraceWriterResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> RegisterTraceWriterResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void RegisterTraceWriterResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+RegisterTraceWriterRequest::RegisterTraceWriterRequest() = default;
+RegisterTraceWriterRequest::~RegisterTraceWriterRequest() = default;
+RegisterTraceWriterRequest::RegisterTraceWriterRequest(const RegisterTraceWriterRequest&) = default;
+RegisterTraceWriterRequest& RegisterTraceWriterRequest::operator=(const RegisterTraceWriterRequest&) = default;
+RegisterTraceWriterRequest::RegisterTraceWriterRequest(RegisterTraceWriterRequest&&) noexcept = default;
+RegisterTraceWriterRequest& RegisterTraceWriterRequest::operator=(RegisterTraceWriterRequest&&) = default;
+
+bool RegisterTraceWriterRequest::operator==(const RegisterTraceWriterRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(trace_writer_id_, other.trace_writer_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(target_buffer_, other.target_buffer_);
+}
+
+bool RegisterTraceWriterRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* trace_writer_id */:
+ field.get(&trace_writer_id_);
+ break;
+ case 2 /* target_buffer */:
+ field.get(&target_buffer_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string RegisterTraceWriterRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> RegisterTraceWriterRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void RegisterTraceWriterRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: trace_writer_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, trace_writer_id_, msg);
+ }
+
+ // Field 2: target_buffer
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, target_buffer_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UnregisterDataSourceResponse::UnregisterDataSourceResponse() = default;
+UnregisterDataSourceResponse::~UnregisterDataSourceResponse() = default;
+UnregisterDataSourceResponse::UnregisterDataSourceResponse(const UnregisterDataSourceResponse&) = default;
+UnregisterDataSourceResponse& UnregisterDataSourceResponse::operator=(const UnregisterDataSourceResponse&) = default;
+UnregisterDataSourceResponse::UnregisterDataSourceResponse(UnregisterDataSourceResponse&&) noexcept = default;
+UnregisterDataSourceResponse& UnregisterDataSourceResponse::operator=(UnregisterDataSourceResponse&&) = default;
+
+bool UnregisterDataSourceResponse::operator==(const UnregisterDataSourceResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool UnregisterDataSourceResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UnregisterDataSourceResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UnregisterDataSourceResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UnregisterDataSourceResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UnregisterDataSourceRequest::UnregisterDataSourceRequest() = default;
+UnregisterDataSourceRequest::~UnregisterDataSourceRequest() = default;
+UnregisterDataSourceRequest::UnregisterDataSourceRequest(const UnregisterDataSourceRequest&) = default;
+UnregisterDataSourceRequest& UnregisterDataSourceRequest::operator=(const UnregisterDataSourceRequest&) = default;
+UnregisterDataSourceRequest::UnregisterDataSourceRequest(UnregisterDataSourceRequest&&) noexcept = default;
+UnregisterDataSourceRequest& UnregisterDataSourceRequest::operator=(UnregisterDataSourceRequest&&) = default;
+
+bool UnregisterDataSourceRequest::operator==(const UnregisterDataSourceRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_name_, other.data_source_name_);
+}
+
+bool UnregisterDataSourceRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data_source_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &data_source_name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UnregisterDataSourceRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UnregisterDataSourceRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UnregisterDataSourceRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: data_source_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, data_source_name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UpdateDataSourceResponse::UpdateDataSourceResponse() = default;
+UpdateDataSourceResponse::~UpdateDataSourceResponse() = default;
+UpdateDataSourceResponse::UpdateDataSourceResponse(const UpdateDataSourceResponse&) = default;
+UpdateDataSourceResponse& UpdateDataSourceResponse::operator=(const UpdateDataSourceResponse&) = default;
+UpdateDataSourceResponse::UpdateDataSourceResponse(UpdateDataSourceResponse&&) noexcept = default;
+UpdateDataSourceResponse& UpdateDataSourceResponse::operator=(UpdateDataSourceResponse&&) = default;
+
+bool UpdateDataSourceResponse::operator==(const UpdateDataSourceResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool UpdateDataSourceResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UpdateDataSourceResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UpdateDataSourceResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UpdateDataSourceResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+UpdateDataSourceRequest::UpdateDataSourceRequest() = default;
+UpdateDataSourceRequest::~UpdateDataSourceRequest() = default;
+UpdateDataSourceRequest::UpdateDataSourceRequest(const UpdateDataSourceRequest&) = default;
+UpdateDataSourceRequest& UpdateDataSourceRequest::operator=(const UpdateDataSourceRequest&) = default;
+UpdateDataSourceRequest::UpdateDataSourceRequest(UpdateDataSourceRequest&&) noexcept = default;
+UpdateDataSourceRequest& UpdateDataSourceRequest::operator=(UpdateDataSourceRequest&&) = default;
+
+bool UpdateDataSourceRequest::operator==(const UpdateDataSourceRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_descriptor_, other.data_source_descriptor_);
+}
+
+bool UpdateDataSourceRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data_source_descriptor */:
+ (*data_source_descriptor_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string UpdateDataSourceRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> UpdateDataSourceRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void UpdateDataSourceRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: data_source_descriptor
+ if (_has_field_[1]) {
+ (*data_source_descriptor_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+RegisterDataSourceResponse::RegisterDataSourceResponse() = default;
+RegisterDataSourceResponse::~RegisterDataSourceResponse() = default;
+RegisterDataSourceResponse::RegisterDataSourceResponse(const RegisterDataSourceResponse&) = default;
+RegisterDataSourceResponse& RegisterDataSourceResponse::operator=(const RegisterDataSourceResponse&) = default;
+RegisterDataSourceResponse::RegisterDataSourceResponse(RegisterDataSourceResponse&&) noexcept = default;
+RegisterDataSourceResponse& RegisterDataSourceResponse::operator=(RegisterDataSourceResponse&&) = default;
+
+bool RegisterDataSourceResponse::operator==(const RegisterDataSourceResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(error_, other.error_);
+}
+
+bool RegisterDataSourceResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* error */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &error_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string RegisterDataSourceResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> RegisterDataSourceResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void RegisterDataSourceResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: error
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, error_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+RegisterDataSourceRequest::RegisterDataSourceRequest() = default;
+RegisterDataSourceRequest::~RegisterDataSourceRequest() = default;
+RegisterDataSourceRequest::RegisterDataSourceRequest(const RegisterDataSourceRequest&) = default;
+RegisterDataSourceRequest& RegisterDataSourceRequest::operator=(const RegisterDataSourceRequest&) = default;
+RegisterDataSourceRequest::RegisterDataSourceRequest(RegisterDataSourceRequest&&) noexcept = default;
+RegisterDataSourceRequest& RegisterDataSourceRequest::operator=(RegisterDataSourceRequest&&) = default;
+
+bool RegisterDataSourceRequest::operator==(const RegisterDataSourceRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_source_descriptor_, other.data_source_descriptor_);
+}
+
+bool RegisterDataSourceRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* data_source_descriptor */:
+ (*data_source_descriptor_).ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string RegisterDataSourceRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> RegisterDataSourceRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void RegisterDataSourceRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: data_source_descriptor
+ if (_has_field_[1]) {
+ (*data_source_descriptor_).Serialize(msg->BeginNestedMessage<::protozero::Message>(1));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+InitializeConnectionResponse::InitializeConnectionResponse() = default;
+InitializeConnectionResponse::~InitializeConnectionResponse() = default;
+InitializeConnectionResponse::InitializeConnectionResponse(const InitializeConnectionResponse&) = default;
+InitializeConnectionResponse& InitializeConnectionResponse::operator=(const InitializeConnectionResponse&) = default;
+InitializeConnectionResponse::InitializeConnectionResponse(InitializeConnectionResponse&&) noexcept = default;
+InitializeConnectionResponse& InitializeConnectionResponse::operator=(InitializeConnectionResponse&&) = default;
+
+bool InitializeConnectionResponse::operator==(const InitializeConnectionResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(using_shmem_provided_by_producer_, other.using_shmem_provided_by_producer_)
+ && ::protozero::internal::gen_helpers::EqualsField(direct_smb_patching_supported_, other.direct_smb_patching_supported_)
+ && ::protozero::internal::gen_helpers::EqualsField(use_shmem_emulation_, other.use_shmem_emulation_);
+}
+
+bool InitializeConnectionResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* using_shmem_provided_by_producer */:
+ field.get(&using_shmem_provided_by_producer_);
+ break;
+ case 2 /* direct_smb_patching_supported */:
+ field.get(&direct_smb_patching_supported_);
+ break;
+ case 3 /* use_shmem_emulation */:
+ field.get(&use_shmem_emulation_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string InitializeConnectionResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> InitializeConnectionResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void InitializeConnectionResponse::Serialize(::protozero::Message* msg) const {
+ // Field 1: using_shmem_provided_by_producer
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, using_shmem_provided_by_producer_, msg);
+ }
+
+ // Field 2: direct_smb_patching_supported
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, direct_smb_patching_supported_, msg);
+ }
+
+ // Field 3: use_shmem_emulation
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(3, use_shmem_emulation_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+InitializeConnectionRequest::InitializeConnectionRequest() = default;
+InitializeConnectionRequest::~InitializeConnectionRequest() = default;
+InitializeConnectionRequest::InitializeConnectionRequest(const InitializeConnectionRequest&) = default;
+InitializeConnectionRequest& InitializeConnectionRequest::operator=(const InitializeConnectionRequest&) = default;
+InitializeConnectionRequest::InitializeConnectionRequest(InitializeConnectionRequest&&) noexcept = default;
+InitializeConnectionRequest& InitializeConnectionRequest::operator=(InitializeConnectionRequest&&) = default;
+
+bool InitializeConnectionRequest::operator==(const InitializeConnectionRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(shared_memory_page_size_hint_bytes_, other.shared_memory_page_size_hint_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(shared_memory_size_hint_bytes_, other.shared_memory_size_hint_bytes_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_name_, other.producer_name_)
+ && ::protozero::internal::gen_helpers::EqualsField(smb_scraping_mode_, other.smb_scraping_mode_)
+ && ::protozero::internal::gen_helpers::EqualsField(producer_provided_shmem_, other.producer_provided_shmem_)
+ && ::protozero::internal::gen_helpers::EqualsField(sdk_version_, other.sdk_version_)
+ && ::protozero::internal::gen_helpers::EqualsField(shm_key_windows_, other.shm_key_windows_);
+}
+
+bool InitializeConnectionRequest::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* shared_memory_page_size_hint_bytes */:
+ field.get(&shared_memory_page_size_hint_bytes_);
+ break;
+ case 2 /* shared_memory_size_hint_bytes */:
+ field.get(&shared_memory_size_hint_bytes_);
+ break;
+ case 3 /* producer_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &producer_name_);
+ break;
+ case 4 /* smb_scraping_mode */:
+ field.get(&smb_scraping_mode_);
+ break;
+ case 6 /* producer_provided_shmem */:
+ field.get(&producer_provided_shmem_);
+ break;
+ case 8 /* sdk_version */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &sdk_version_);
+ break;
+ case 7 /* shm_key_windows */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &shm_key_windows_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string InitializeConnectionRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> InitializeConnectionRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void InitializeConnectionRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: shared_memory_page_size_hint_bytes
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, shared_memory_page_size_hint_bytes_, msg);
+ }
+
+ // Field 2: shared_memory_size_hint_bytes
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, shared_memory_size_hint_bytes_, msg);
+ }
+
+ // Field 3: producer_name
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, producer_name_, msg);
+ }
+
+ // Field 4: smb_scraping_mode
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(4, smb_scraping_mode_, msg);
+ }
+
+ // Field 6: producer_provided_shmem
+ if (_has_field_[6]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(6, producer_provided_shmem_, msg);
+ }
+
+ // Field 8: sdk_version
+ if (_has_field_[8]) {
+ ::protozero::internal::gen_helpers::SerializeString(8, sdk_version_, msg);
+ }
+
+ // Field 7: shm_key_windows
+ if (_has_field_[7]) {
+ ::protozero::internal::gen_helpers::SerializeString(7, shm_key_windows_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/ipc/relay_port.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/relay_port.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+SyncClockResponse::SyncClockResponse() = default;
+SyncClockResponse::~SyncClockResponse() = default;
+SyncClockResponse::SyncClockResponse(const SyncClockResponse&) = default;
+SyncClockResponse& SyncClockResponse::operator=(const SyncClockResponse&) = default;
+SyncClockResponse::SyncClockResponse(SyncClockResponse&&) noexcept = default;
+SyncClockResponse& SyncClockResponse::operator=(SyncClockResponse&&) = default;
+
+bool SyncClockResponse::operator==(const SyncClockResponse& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_);
+}
+
+bool SyncClockResponse::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SyncClockResponse::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SyncClockResponse::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SyncClockResponse::Serialize(::protozero::Message* msg) const {
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+SyncClockRequest::SyncClockRequest() = default;
+SyncClockRequest::~SyncClockRequest() = default;
+SyncClockRequest::SyncClockRequest(const SyncClockRequest&) = default;
+SyncClockRequest& SyncClockRequest::operator=(const SyncClockRequest&) = default;
+SyncClockRequest::SyncClockRequest(SyncClockRequest&&) noexcept = default;
+SyncClockRequest& SyncClockRequest::operator=(SyncClockRequest&&) = default;
+
+bool SyncClockRequest::operator==(const SyncClockRequest& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(phase_, other.phase_)
+ && ::protozero::internal::gen_helpers::EqualsField(clocks_, other.clocks_);
+}
+
+int SyncClockRequest::clocks_size() const { return static_cast<int>(clocks_.size()); }
+void SyncClockRequest::clear_clocks() { clocks_.clear(); }
+SyncClockRequest_Clock* SyncClockRequest::add_clocks() { clocks_.emplace_back(); return &clocks_.back(); }
+bool SyncClockRequest::ParseFromArray(const void* raw, size_t size) {
+ clocks_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* phase */:
+ field.get(&phase_);
+ break;
+ case 2 /* clocks */:
+ clocks_.emplace_back();
+ clocks_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SyncClockRequest::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SyncClockRequest::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SyncClockRequest::Serialize(::protozero::Message* msg) const {
+ // Field 1: phase
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, phase_, msg);
+ }
+
+ // Field 2: clocks
+ for (auto& it : clocks_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(2));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+SyncClockRequest_Clock::SyncClockRequest_Clock() = default;
+SyncClockRequest_Clock::~SyncClockRequest_Clock() = default;
+SyncClockRequest_Clock::SyncClockRequest_Clock(const SyncClockRequest_Clock&) = default;
+SyncClockRequest_Clock& SyncClockRequest_Clock::operator=(const SyncClockRequest_Clock&) = default;
+SyncClockRequest_Clock::SyncClockRequest_Clock(SyncClockRequest_Clock&&) noexcept = default;
+SyncClockRequest_Clock& SyncClockRequest_Clock::operator=(SyncClockRequest_Clock&&) = default;
+
+bool SyncClockRequest_Clock::operator==(const SyncClockRequest_Clock& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(clock_id_, other.clock_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(timestamp_, other.timestamp_);
+}
+
+bool SyncClockRequest_Clock::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* clock_id */:
+ field.get(&clock_id_);
+ break;
+ case 2 /* timestamp */:
+ field.get(&timestamp_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string SyncClockRequest_Clock::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> SyncClockRequest_Clock::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void SyncClockRequest_Clock::Serialize(::protozero::Message* msg) const {
+ // Field 1: clock_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, clock_id_, msg);
+ }
+
+ // Field 2: timestamp
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, timestamp_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: gen/protos/perfetto/ipc/wire_protocol.gen.cc
+// gen_amalgamated expanded: #include "perfetto/protozero/gen_field_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/wire_protocol.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+IPCFrame::IPCFrame() = default;
+IPCFrame::~IPCFrame() = default;
+IPCFrame::IPCFrame(const IPCFrame&) = default;
+IPCFrame& IPCFrame::operator=(const IPCFrame&) = default;
+IPCFrame::IPCFrame(IPCFrame&&) noexcept = default;
+IPCFrame& IPCFrame::operator=(IPCFrame&&) = default;
+
+bool IPCFrame::operator==(const IPCFrame& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(request_id_, other.request_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(msg_bind_service_, other.msg_bind_service_)
+ && ::protozero::internal::gen_helpers::EqualsField(msg_bind_service_reply_, other.msg_bind_service_reply_)
+ && ::protozero::internal::gen_helpers::EqualsField(msg_invoke_method_, other.msg_invoke_method_)
+ && ::protozero::internal::gen_helpers::EqualsField(msg_invoke_method_reply_, other.msg_invoke_method_reply_)
+ && ::protozero::internal::gen_helpers::EqualsField(msg_request_error_, other.msg_request_error_)
+ && ::protozero::internal::gen_helpers::EqualsField(set_peer_identity_, other.set_peer_identity_)
+ && ::protozero::internal::gen_helpers::EqualsField(data_for_testing_, other.data_for_testing_);
+}
+
+bool IPCFrame::ParseFromArray(const void* raw, size_t size) {
+ data_for_testing_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 2 /* request_id */:
+ field.get(&request_id_);
+ break;
+ case 3 /* msg_bind_service */:
+ (*msg_bind_service_).ParseFromArray(field.data(), field.size());
+ break;
+ case 4 /* msg_bind_service_reply */:
+ (*msg_bind_service_reply_).ParseFromArray(field.data(), field.size());
+ break;
+ case 5 /* msg_invoke_method */:
+ (*msg_invoke_method_).ParseFromArray(field.data(), field.size());
+ break;
+ case 6 /* msg_invoke_method_reply */:
+ (*msg_invoke_method_reply_).ParseFromArray(field.data(), field.size());
+ break;
+ case 7 /* msg_request_error */:
+ (*msg_request_error_).ParseFromArray(field.data(), field.size());
+ break;
+ case 8 /* set_peer_identity */:
+ (*set_peer_identity_).ParseFromArray(field.data(), field.size());
+ break;
+ case 1 /* data_for_testing */:
+ data_for_testing_.emplace_back();
+ field.get(&data_for_testing_.back());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame::Serialize(::protozero::Message* msg) const {
+ // Field 2: request_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, request_id_, msg);
+ }
+
+ // Field 3: msg_bind_service
+ if (_has_field_[3]) {
+ (*msg_bind_service_).Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ // Field 4: msg_bind_service_reply
+ if (_has_field_[4]) {
+ (*msg_bind_service_reply_).Serialize(msg->BeginNestedMessage<::protozero::Message>(4));
+ }
+
+ // Field 5: msg_invoke_method
+ if (_has_field_[5]) {
+ (*msg_invoke_method_).Serialize(msg->BeginNestedMessage<::protozero::Message>(5));
+ }
+
+ // Field 6: msg_invoke_method_reply
+ if (_has_field_[6]) {
+ (*msg_invoke_method_reply_).Serialize(msg->BeginNestedMessage<::protozero::Message>(6));
+ }
+
+ // Field 7: msg_request_error
+ if (_has_field_[7]) {
+ (*msg_request_error_).Serialize(msg->BeginNestedMessage<::protozero::Message>(7));
+ }
+
+ // Field 8: set_peer_identity
+ if (_has_field_[8]) {
+ (*set_peer_identity_).Serialize(msg->BeginNestedMessage<::protozero::Message>(8));
+ }
+
+ // Field 1: data_for_testing
+ for (auto& it : data_for_testing_) {
+ ::protozero::internal::gen_helpers::SerializeString(1, it, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+IPCFrame_SetPeerIdentity::IPCFrame_SetPeerIdentity() = default;
+IPCFrame_SetPeerIdentity::~IPCFrame_SetPeerIdentity() = default;
+IPCFrame_SetPeerIdentity::IPCFrame_SetPeerIdentity(const IPCFrame_SetPeerIdentity&) = default;
+IPCFrame_SetPeerIdentity& IPCFrame_SetPeerIdentity::operator=(const IPCFrame_SetPeerIdentity&) = default;
+IPCFrame_SetPeerIdentity::IPCFrame_SetPeerIdentity(IPCFrame_SetPeerIdentity&&) noexcept = default;
+IPCFrame_SetPeerIdentity& IPCFrame_SetPeerIdentity::operator=(IPCFrame_SetPeerIdentity&&) = default;
+
+bool IPCFrame_SetPeerIdentity::operator==(const IPCFrame_SetPeerIdentity& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(pid_, other.pid_)
+ && ::protozero::internal::gen_helpers::EqualsField(uid_, other.uid_)
+ && ::protozero::internal::gen_helpers::EqualsField(machine_id_hint_, other.machine_id_hint_);
+}
+
+bool IPCFrame_SetPeerIdentity::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* pid */:
+ field.get(&pid_);
+ break;
+ case 2 /* uid */:
+ field.get(&uid_);
+ break;
+ case 3 /* machine_id_hint */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &machine_id_hint_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame_SetPeerIdentity::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame_SetPeerIdentity::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame_SetPeerIdentity::Serialize(::protozero::Message* msg) const {
+ // Field 1: pid
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, pid_, msg);
+ }
+
+ // Field 2: uid
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, uid_, msg);
+ }
+
+ // Field 3: machine_id_hint
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, machine_id_hint_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+IPCFrame_RequestError::IPCFrame_RequestError() = default;
+IPCFrame_RequestError::~IPCFrame_RequestError() = default;
+IPCFrame_RequestError::IPCFrame_RequestError(const IPCFrame_RequestError&) = default;
+IPCFrame_RequestError& IPCFrame_RequestError::operator=(const IPCFrame_RequestError&) = default;
+IPCFrame_RequestError::IPCFrame_RequestError(IPCFrame_RequestError&&) noexcept = default;
+IPCFrame_RequestError& IPCFrame_RequestError::operator=(IPCFrame_RequestError&&) = default;
+
+bool IPCFrame_RequestError::operator==(const IPCFrame_RequestError& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(error_, other.error_);
+}
+
+bool IPCFrame_RequestError::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* error */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &error_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame_RequestError::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame_RequestError::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame_RequestError::Serialize(::protozero::Message* msg) const {
+ // Field 1: error
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, error_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+IPCFrame_InvokeMethodReply::IPCFrame_InvokeMethodReply() = default;
+IPCFrame_InvokeMethodReply::~IPCFrame_InvokeMethodReply() = default;
+IPCFrame_InvokeMethodReply::IPCFrame_InvokeMethodReply(const IPCFrame_InvokeMethodReply&) = default;
+IPCFrame_InvokeMethodReply& IPCFrame_InvokeMethodReply::operator=(const IPCFrame_InvokeMethodReply&) = default;
+IPCFrame_InvokeMethodReply::IPCFrame_InvokeMethodReply(IPCFrame_InvokeMethodReply&&) noexcept = default;
+IPCFrame_InvokeMethodReply& IPCFrame_InvokeMethodReply::operator=(IPCFrame_InvokeMethodReply&&) = default;
+
+bool IPCFrame_InvokeMethodReply::operator==(const IPCFrame_InvokeMethodReply& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(success_, other.success_)
+ && ::protozero::internal::gen_helpers::EqualsField(has_more_, other.has_more_)
+ && ::protozero::internal::gen_helpers::EqualsField(reply_proto_, other.reply_proto_);
+}
+
+bool IPCFrame_InvokeMethodReply::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* success */:
+ field.get(&success_);
+ break;
+ case 2 /* has_more */:
+ field.get(&has_more_);
+ break;
+ case 3 /* reply_proto */:
+ field.get(&reply_proto_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame_InvokeMethodReply::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame_InvokeMethodReply::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame_InvokeMethodReply::Serialize(::protozero::Message* msg) const {
+ // Field 1: success
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, success_, msg);
+ }
+
+ // Field 2: has_more
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(2, has_more_, msg);
+ }
+
+ // Field 3: reply_proto
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, reply_proto_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+IPCFrame_InvokeMethod::IPCFrame_InvokeMethod() = default;
+IPCFrame_InvokeMethod::~IPCFrame_InvokeMethod() = default;
+IPCFrame_InvokeMethod::IPCFrame_InvokeMethod(const IPCFrame_InvokeMethod&) = default;
+IPCFrame_InvokeMethod& IPCFrame_InvokeMethod::operator=(const IPCFrame_InvokeMethod&) = default;
+IPCFrame_InvokeMethod::IPCFrame_InvokeMethod(IPCFrame_InvokeMethod&&) noexcept = default;
+IPCFrame_InvokeMethod& IPCFrame_InvokeMethod::operator=(IPCFrame_InvokeMethod&&) = default;
+
+bool IPCFrame_InvokeMethod::operator==(const IPCFrame_InvokeMethod& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(service_id_, other.service_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(method_id_, other.method_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(args_proto_, other.args_proto_)
+ && ::protozero::internal::gen_helpers::EqualsField(drop_reply_, other.drop_reply_);
+}
+
+bool IPCFrame_InvokeMethod::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* service_id */:
+ field.get(&service_id_);
+ break;
+ case 2 /* method_id */:
+ field.get(&method_id_);
+ break;
+ case 3 /* args_proto */:
+ field.get(&args_proto_);
+ break;
+ case 4 /* drop_reply */:
+ field.get(&drop_reply_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame_InvokeMethod::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame_InvokeMethod::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame_InvokeMethod::Serialize(::protozero::Message* msg) const {
+ // Field 1: service_id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, service_id_, msg);
+ }
+
+ // Field 2: method_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, method_id_, msg);
+ }
+
+ // Field 3: args_proto
+ if (_has_field_[3]) {
+ ::protozero::internal::gen_helpers::SerializeString(3, args_proto_, msg);
+ }
+
+ // Field 4: drop_reply
+ if (_has_field_[4]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(4, drop_reply_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+IPCFrame_BindServiceReply::IPCFrame_BindServiceReply() = default;
+IPCFrame_BindServiceReply::~IPCFrame_BindServiceReply() = default;
+IPCFrame_BindServiceReply::IPCFrame_BindServiceReply(const IPCFrame_BindServiceReply&) = default;
+IPCFrame_BindServiceReply& IPCFrame_BindServiceReply::operator=(const IPCFrame_BindServiceReply&) = default;
+IPCFrame_BindServiceReply::IPCFrame_BindServiceReply(IPCFrame_BindServiceReply&&) noexcept = default;
+IPCFrame_BindServiceReply& IPCFrame_BindServiceReply::operator=(IPCFrame_BindServiceReply&&) = default;
+
+bool IPCFrame_BindServiceReply::operator==(const IPCFrame_BindServiceReply& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(success_, other.success_)
+ && ::protozero::internal::gen_helpers::EqualsField(service_id_, other.service_id_)
+ && ::protozero::internal::gen_helpers::EqualsField(methods_, other.methods_);
+}
+
+int IPCFrame_BindServiceReply::methods_size() const { return static_cast<int>(methods_.size()); }
+void IPCFrame_BindServiceReply::clear_methods() { methods_.clear(); }
+IPCFrame_BindServiceReply_MethodInfo* IPCFrame_BindServiceReply::add_methods() { methods_.emplace_back(); return &methods_.back(); }
+bool IPCFrame_BindServiceReply::ParseFromArray(const void* raw, size_t size) {
+ methods_.clear();
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* success */:
+ field.get(&success_);
+ break;
+ case 2 /* service_id */:
+ field.get(&service_id_);
+ break;
+ case 3 /* methods */:
+ methods_.emplace_back();
+ methods_.back().ParseFromArray(field.data(), field.size());
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame_BindServiceReply::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame_BindServiceReply::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame_BindServiceReply::Serialize(::protozero::Message* msg) const {
+ // Field 1: success
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeTinyVarInt(1, success_, msg);
+ }
+
+ // Field 2: service_id
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(2, service_id_, msg);
+ }
+
+ // Field 3: methods
+ for (auto& it : methods_) {
+ it.Serialize(msg->BeginNestedMessage<::protozero::Message>(3));
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+IPCFrame_BindServiceReply_MethodInfo::IPCFrame_BindServiceReply_MethodInfo() = default;
+IPCFrame_BindServiceReply_MethodInfo::~IPCFrame_BindServiceReply_MethodInfo() = default;
+IPCFrame_BindServiceReply_MethodInfo::IPCFrame_BindServiceReply_MethodInfo(const IPCFrame_BindServiceReply_MethodInfo&) = default;
+IPCFrame_BindServiceReply_MethodInfo& IPCFrame_BindServiceReply_MethodInfo::operator=(const IPCFrame_BindServiceReply_MethodInfo&) = default;
+IPCFrame_BindServiceReply_MethodInfo::IPCFrame_BindServiceReply_MethodInfo(IPCFrame_BindServiceReply_MethodInfo&&) noexcept = default;
+IPCFrame_BindServiceReply_MethodInfo& IPCFrame_BindServiceReply_MethodInfo::operator=(IPCFrame_BindServiceReply_MethodInfo&&) = default;
+
+bool IPCFrame_BindServiceReply_MethodInfo::operator==(const IPCFrame_BindServiceReply_MethodInfo& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(id_, other.id_)
+ && ::protozero::internal::gen_helpers::EqualsField(name_, other.name_);
+}
+
+bool IPCFrame_BindServiceReply_MethodInfo::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* id */:
+ field.get(&id_);
+ break;
+ case 2 /* name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame_BindServiceReply_MethodInfo::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame_BindServiceReply_MethodInfo::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame_BindServiceReply_MethodInfo::Serialize(::protozero::Message* msg) const {
+ // Field 1: id
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeVarInt(1, id_, msg);
+ }
+
+ // Field 2: name
+ if (_has_field_[2]) {
+ ::protozero::internal::gen_helpers::SerializeString(2, name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+
+IPCFrame_BindService::IPCFrame_BindService() = default;
+IPCFrame_BindService::~IPCFrame_BindService() = default;
+IPCFrame_BindService::IPCFrame_BindService(const IPCFrame_BindService&) = default;
+IPCFrame_BindService& IPCFrame_BindService::operator=(const IPCFrame_BindService&) = default;
+IPCFrame_BindService::IPCFrame_BindService(IPCFrame_BindService&&) noexcept = default;
+IPCFrame_BindService& IPCFrame_BindService::operator=(IPCFrame_BindService&&) = default;
+
+bool IPCFrame_BindService::operator==(const IPCFrame_BindService& other) const {
+ return ::protozero::internal::gen_helpers::EqualsField(unknown_fields_, other.unknown_fields_)
+ && ::protozero::internal::gen_helpers::EqualsField(service_name_, other.service_name_);
+}
+
+bool IPCFrame_BindService::ParseFromArray(const void* raw, size_t size) {
+ unknown_fields_.clear();
+ bool packed_error = false;
+
+ ::protozero::ProtoDecoder dec(raw, size);
+ for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
+ if (field.id() < _has_field_.size()) {
+ _has_field_.set(field.id());
+ }
+ switch (field.id()) {
+ case 1 /* service_name */:
+ ::protozero::internal::gen_helpers::DeserializeString(field, &service_name_);
+ break;
+ default:
+ field.SerializeAndAppendTo(&unknown_fields_);
+ break;
+ }
+ }
+ return !packed_error && !dec.bytes_left();
+}
+
+std::string IPCFrame_BindService::SerializeAsString() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsString();
+}
+
+std::vector<uint8_t> IPCFrame_BindService::SerializeAsArray() const {
+ ::protozero::internal::gen_helpers::MessageSerializer msg;
+ Serialize(msg.get());
+ return msg.SerializeAsArray();
+}
+
+void IPCFrame_BindService::Serialize(::protozero::Message* msg) const {
+ // Field 1: service_name
+ if (_has_field_[1]) {
+ ::protozero::internal::gen_helpers::SerializeString(1, service_name_, msg);
+ }
+
+ protozero::internal::gen_helpers::SerializeUnknownFields(unknown_fields_, msg);
+}
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+// gen_amalgamated begin source: src/base/unix_socket.cc
+// gen_amalgamated begin header: include/perfetto/ext/base/unix_socket.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
+#define INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+
+struct msghdr;
+
+namespace perfetto {
+namespace base {
+
+// Define the ScopedSocketHandle type.
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+int CloseSocket(SocketHandle); // A wrapper around ::closesocket().
+using ScopedSocketHandle =
+ ScopedResource<SocketHandle, CloseSocket, static_cast<SocketHandle>(-1)>;
+#else
+using ScopedSocketHandle = ScopedFile;
+#endif
+
+class TaskRunner;
+
+// Use arbitrarily high values to avoid that some code accidentally ends up
+// assuming that these enum values match the sysroot's SOCK_xxx defines rather
+// than using MkSockType() / MkSockFamily().
+enum class SockType { kStream = 100, kDgram, kSeqPacket };
+enum class SockFamily { kUnspec = 0, kUnix = 200, kInet, kInet6, kVsock };
+
+// Controls the getsockopt(SO_PEERCRED) behavior, which allows to obtain the
+// peer credentials.
+enum class SockPeerCredMode {
+ // Obtain the peer credentials immediately after connection and cache them.
+ kReadOnConnect = 0,
+
+ // Don't read peer credentials at all. Calls to peer_uid()/peer_pid() will
+ // hit a DCHECK and return kInvalidUid/Pid in release builds.
+ kIgnore = 1,
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+ kDefault = kIgnore,
+#else
+ kDefault = kReadOnConnect,
+#endif
+};
+
+// Returns the socket family from the full addres that perfetto uses.
+// Addr can be:
+// - /path/to/socket : for linked AF_UNIX sockets.
+// - @abstract_name : for abstract AF_UNIX sockets.
+// - 1.2.3.4:8080 : for Inet sockets.
+// - [::1]:8080 : for Inet6 sockets.
+// - vsock://-1:3000 : for VM sockets.
+SockFamily GetSockFamily(const char* addr);
+
+// Returns whether inter-process shared memory is supported for the socket.
+inline bool SockShmemSupported(SockFamily sock_family) {
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return sock_family == SockFamily::kUnix;
+#else
+ base::ignore_result(sock_family);
+ // On Windows shm is negotiated by sharing an unguessable token
+ // over TCP sockets. In theory works on any socket type, in practice
+ // we need to tell the difference between a local and a remote
+ // connection. For now we assume everything is local.
+ // See comments on r.android.com/2951909 .
+ return true;
+#endif
+}
+inline bool SockShmemSupported(const char* addr) {
+ return SockShmemSupported(GetSockFamily(addr));
+}
+
+// UnixSocketRaw is a basic wrapper around sockets. It exposes wrapper
+// methods that take care of most common pitfalls (e.g., marking fd as
+// O_CLOEXEC, avoiding SIGPIPE, properly handling partial writes). It is used as
+// a building block for the more sophisticated UnixSocket class which depends
+// on base::TaskRunner.
+class UnixSocketRaw {
+ public:
+ // Creates a new unconnected unix socket.
+ static UnixSocketRaw CreateMayFail(SockFamily family, SockType type);
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // Crates a pair of connected sockets.
+ static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePairPosix(SockFamily,
+ SockType);
+#endif
+
+ // Creates an uninitialized unix socket.
+ UnixSocketRaw();
+
+ // Creates a unix socket adopting an existing file descriptor. This is
+ // typically used to inherit fds from init via environment variables.
+ UnixSocketRaw(ScopedSocketHandle, SockFamily, SockType);
+
+ ~UnixSocketRaw() = default;
+ UnixSocketRaw(UnixSocketRaw&&) noexcept = default;
+ UnixSocketRaw& operator=(UnixSocketRaw&&) = default;
+
+ bool Bind(const std::string& socket_name);
+ bool Listen();
+ bool Connect(const std::string& socket_name);
+ bool SetTxTimeout(uint32_t timeout_ms);
+ bool SetRxTimeout(uint32_t timeout_ms);
+ void Shutdown();
+ void SetBlocking(bool);
+ void DcheckIsBlocking(bool expected) const; // No-op on release and Win.
+ void SetRetainOnExec(bool retain);
+ std::string GetSockAddr() const;
+ SockType type() const { return type_; }
+ SockFamily family() const { return family_; }
+ SocketHandle fd() const { return *fd_; }
+ explicit operator bool() const { return !!fd_; }
+
+ // This is the handle that passed to TaskRunner.AddFileDescriptorWatch().
+ // On UNIX this is just the socket FD. On Windows, we need to create a
+ // dedicated event object.
+ PlatformHandle watch_handle() const {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return *event_handle_;
+#else
+ return *fd_;
+#endif
+ }
+
+ ScopedSocketHandle ReleaseFd() { return std::move(fd_); }
+
+ // |send_fds| and |num_fds| are ignored on Windows.
+ ssize_t Send(const void* msg,
+ size_t len,
+ const int* send_fds = nullptr,
+ size_t num_fds = 0);
+
+ ssize_t SendStr(const std::string& str) {
+ return Send(str.data(), str.size());
+ }
+
+ // |fd_vec| and |max_files| are ignored on Windows.
+ ssize_t Receive(void* msg,
+ size_t len,
+ ScopedFile* fd_vec = nullptr,
+ size_t max_files = 0);
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // UNIX-specific helpers to deal with SCM_RIGHTS.
+
+ // Re-enter sendmsg until all the data has been sent or an error occurs.
+ // TODO(fmayer): Figure out how to do timeouts here for heapprofd.
+ ssize_t SendMsgAllPosix(struct msghdr* msg);
+
+ // Exposed for testing only.
+ // Update msghdr so subsequent sendmsg will send data that remains after n
+ // bytes have already been sent.
+ static void ShiftMsgHdrPosix(size_t n, struct msghdr* msg);
+#endif
+
+ private:
+ UnixSocketRaw(SockFamily, SockType);
+
+ UnixSocketRaw(const UnixSocketRaw&) = delete;
+ UnixSocketRaw& operator=(const UnixSocketRaw&) = delete;
+
+ ScopedSocketHandle fd_;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ ScopedPlatformHandle event_handle_;
+#endif
+ SockFamily family_ = SockFamily::kUnix;
+ SockType type_ = SockType::kStream;
+ uint32_t tx_timeout_ms_ = 0;
+};
+
+// A non-blocking UNIX domain socket. Allows also to transfer file descriptors.
+// None of the methods in this class are blocking.
+// The main design goal is making strong guarantees on the EventListener
+// callbacks, in order to avoid ending in some undefined state.
+// In case of any error it will aggressively just shut down the socket and
+// notify the failure with OnConnect(false) or OnDisconnect() depending on the
+// state of the socket (see below).
+// EventListener callbacks stop happening as soon as the instance is destroyed.
+//
+// Lifecycle of a client socket:
+//
+// Connect()
+// |
+// +------------------+------------------+
+// | (success) | (failure or Shutdown())
+// V V
+// OnConnect(true) OnConnect(false)
+// |
+// V
+// OnDataAvailable()
+// |
+// V
+// OnDisconnect() (failure or shutdown)
+//
+//
+// Lifecycle of a server socket:
+//
+// Listen() --> returns false in case of errors.
+// |
+// V
+// OnNewIncomingConnection(new_socket)
+//
+// (|new_socket| inherits the same EventListener)
+// |
+// V
+// OnDataAvailable()
+// | (failure or Shutdown())
+// V
+// OnDisconnect()
+class PERFETTO_EXPORT_COMPONENT UnixSocket {
+ public:
+ class EventListener {
+ public:
+ EventListener() = default;
+ virtual ~EventListener();
+
+ EventListener(const EventListener&) = delete;
+ EventListener& operator=(const EventListener&) = delete;
+
+ EventListener(EventListener&&) noexcept = default;
+ EventListener& operator=(EventListener&&) noexcept = default;
+
+ // After Listen().
+ // |self| may be null if the connection was not accepted via a listen
+ // socket.
+ virtual void OnNewIncomingConnection(
+ UnixSocket* self,
+ std::unique_ptr<UnixSocket> new_connection);
+
+ // After Connect(), whether successful or not.
+ virtual void OnConnect(UnixSocket* self, bool connected);
+
+ // After a successful Connect() or OnNewIncomingConnection(). Either the
+ // other endpoint did disconnect or some other error happened.
+ virtual void OnDisconnect(UnixSocket* self);
+
+ // Whenever there is data available to Receive(). Note that spurious FD
+ // watch events are possible, so it is possible that Receive() soon after
+ // OnDataAvailable() returns 0 (just ignore those).
+ virtual void OnDataAvailable(UnixSocket* self);
+ };
+
+ enum class State {
+ kDisconnected = 0, // Failed connection, peer disconnection or Shutdown().
+ kConnecting, // Soon after Connect(), before it either succeeds or fails.
+ kConnected, // After a successful Connect().
+ kListening // After Listen(), until Shutdown().
+ };
+
+ // Creates a socket and starts listening. If SockFamily::kUnix and
+ // |socket_name| starts with a '@', an abstract UNIX dmoain socket will be
+ // created instead of a filesystem-linked UNIX socket (Linux/Android only).
+ // If SockFamily::kInet, |socket_name| is host:port (e.g., "1.2.3.4:8000").
+ // If SockFamily::kInet6, |socket_name| is [host]:port (e.g., "[::1]:8000").
+ // Returns nullptr if the socket creation or bind fails. If listening fails,
+ // (e.g. if another socket with the same name is already listening) the
+ // returned socket will have is_listening() == false.
+ static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name,
+ EventListener*,
+ TaskRunner*,
+ SockFamily,
+ SockType);
+
+ // Attaches to a pre-existing socket. The socket must have been created in
+ // SOCK_STREAM mode and the caller must have called bind() on it.
+ static std::unique_ptr<UnixSocket> Listen(ScopedSocketHandle,
+ EventListener*,
+ TaskRunner*,
+ SockFamily,
+ SockType);
+
+ // Creates a Unix domain socket and connects to the listening endpoint.
+ // Returns always an instance. EventListener::OnConnect(bool success) will
+ // be called always, whether the connection succeeded or not.
+ static std::unique_ptr<UnixSocket> Connect(
+ const std::string& socket_name,
+ EventListener*,
+ TaskRunner*,
+ SockFamily,
+ SockType,
+ SockPeerCredMode = SockPeerCredMode::kDefault);
+
+ // Constructs a UnixSocket using the given connected socket.
+ static std::unique_ptr<UnixSocket> AdoptConnected(
+ ScopedSocketHandle,
+ EventListener*,
+ TaskRunner*,
+ SockFamily,
+ SockType,
+ SockPeerCredMode = SockPeerCredMode::kDefault);
+
+ UnixSocket(const UnixSocket&) = delete;
+ UnixSocket& operator=(const UnixSocket&) = delete;
+ // Cannot be easily moved because of tasks from the FileDescriptorWatch.
+ UnixSocket(UnixSocket&&) = delete;
+ UnixSocket& operator=(UnixSocket&&) = delete;
+
+ // This class gives the hard guarantee that no callback is called on the
+ // passed EventListener immediately after the object has been destroyed.
+ // Any queued callback will be silently dropped.
+ ~UnixSocket();
+
+ // Shuts down the current connection, if any. If the socket was Listen()-ing,
+ // stops listening. The socket goes back to kNotInitialized state, so it can
+ // be reused with Listen() or Connect().
+ void Shutdown(bool notify);
+
+ void SetTxTimeout(uint32_t timeout_ms) {
+ PERFETTO_CHECK(sock_raw_.SetTxTimeout(timeout_ms));
+ }
+ void SetRxTimeout(uint32_t timeout_ms) {
+ PERFETTO_CHECK(sock_raw_.SetRxTimeout(timeout_ms));
+ }
+
+ std::string GetSockAddr() const { return sock_raw_.GetSockAddr(); }
+
+ // Returns true is the message was queued, false if there was no space in the
+ // output buffer, in which case the client should retry or give up.
+ // If any other error happens the socket will be shutdown and
+ // EventListener::OnDisconnect() will be called.
+ // If the socket is not connected, Send() will just return false.
+ // Does not append a null string terminator to msg in any case.
+ bool Send(const void* msg, size_t len, const int* send_fds, size_t num_fds);
+
+ inline bool Send(const void* msg, size_t len, int send_fd = -1) {
+ if (send_fd != -1)
+ return Send(msg, len, &send_fd, 1);
+ return Send(msg, len, nullptr, 0);
+ }
+
+ inline bool SendStr(const std::string& msg) {
+ return Send(msg.data(), msg.size(), -1);
+ }
+
+ // Returns the number of bytes (<= |len|) written in |msg| or 0 if there
+ // is no data in the buffer to read or an error occurs (in which case a
+ // EventListener::OnDisconnect() will follow).
+ // If the ScopedFile pointer is not null and a FD is received, it moves the
+ // received FD into that. If a FD is received but the ScopedFile pointer is
+ // null, the FD will be automatically closed.
+ size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1);
+
+ inline size_t Receive(void* msg, size_t len) {
+ return Receive(msg, len, nullptr, 0);
+ }
+
+ // Only for tests. This is slower than Receive() as it requires a heap
+ // allocation and a copy for the std::string. Guarantees that the returned
+ // string is null terminated even if the underlying message sent by the peer
+ // is not.
+ std::string ReceiveString(size_t max_length = 1024);
+
+ bool is_connected() const { return state_ == State::kConnected; }
+ bool is_listening() const { return state_ == State::kListening; }
+ SocketHandle fd() const { return sock_raw_.fd(); }
+ SockFamily family() const { return sock_raw_.family(); }
+
+ // User ID of the peer, as returned by the kernel. If the client disconnects
+ // and the socket goes into the kDisconnected state, it retains the uid of
+ // the last peer.
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+ uid_t peer_uid_posix(bool skip_check_for_testing = false) const {
+ PERFETTO_DCHECK((!is_listening() && peer_uid_ != kInvalidUid) ||
+ skip_check_for_testing);
+
+ return peer_uid_;
+ }
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // Process ID of the peer, as returned by the kernel. If the client
+ // disconnects and the socket goes into the kDisconnected state, it
+ // retains the pid of the last peer.
+ //
+ // This is only available on Linux / Android.
+ pid_t peer_pid_linux(bool skip_check_for_testing = false) const {
+ PERFETTO_DCHECK((!is_listening() && peer_pid_ != kInvalidPid) ||
+ skip_check_for_testing);
+ return peer_pid_;
+ }
+#endif
+
+ // This makes the UnixSocket unusable.
+ UnixSocketRaw ReleaseSocket();
+
+ private:
+ UnixSocket(EventListener*,
+ TaskRunner*,
+ SockFamily,
+ SockType,
+ SockPeerCredMode);
+ UnixSocket(EventListener*,
+ TaskRunner*,
+ ScopedSocketHandle,
+ State,
+ SockFamily,
+ SockType,
+ SockPeerCredMode);
+
+ // Called once by the corresponding public static factory methods.
+ void DoConnect(const std::string& socket_name);
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ void ReadPeerCredentialsPosix();
+#endif
+
+ void OnEvent();
+ void NotifyConnectionState(bool success);
+
+ UnixSocketRaw sock_raw_;
+ State state_ = State::kDisconnected;
+ SockPeerCredMode peer_cred_mode_ = SockPeerCredMode::kDefault;
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+ uid_t peer_uid_ = kInvalidUid;
+#endif
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ pid_t peer_pid_ = kInvalidPid;
+#endif
+ EventListener* const event_listener_;
+ TaskRunner* const task_runner_;
+ WeakPtrFactory<UnixSocket> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
+// gen_amalgamated begin header: src/base/vm_sockets.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_BASE_VM_SOCKETS_H_
+#define SRC_BASE_VM_SOCKETS_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+#include <sys/socket.h>
+
+#ifdef AF_VSOCK
+// Use system vm_socket.h if avaialbe.
+#include <linux/vm_sockets.h>
+#else // defined(AF_SOCK)
+// Fallback and use the stripped copy from the UAPI vm_sockets.h.
+
+#include <stdint.h> // For uint8_t.
+
+#define AF_VSOCK 40
+
+struct sockaddr_vm {
+ sa_family_t svm_family;
+ unsigned short svm_reserved1;
+ unsigned int svm_port;
+ unsigned int svm_cid;
+ uint8_t svm_flags;
+ unsigned char svm_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) -
+ sizeof(unsigned short) - sizeof(unsigned int) -
+ sizeof(unsigned int) - sizeof(uint8_t)];
+};
+
+#endif // defined(AF_SOCK)
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||
+ // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+
+#endif // SRC_BASE_VM_SOCKETS_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// The include order matters on these three Windows header groups.
+#include <Windows.h>
+
+#include <WS2tcpip.h>
+#include <WinSock2.h>
+
+#include <afunix.h>
+#else
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <sys/ucred.h>
+#endif
+
+#include <algorithm>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+// Use a local stripped copy of vm_sockets.h from UAPI.
+// gen_amalgamated expanded: #include "src/base/vm_sockets.h"
+#endif
+
+namespace perfetto {
+namespace base {
+
+// The CMSG_* macros use NULL instead of nullptr.
+// Note: MSVC doesn't have #pragma GCC diagnostic, hence the if __GNUC__.
+#if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif
+
+namespace {
+
+// Android takes an int instead of socklen_t for the control buffer size.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+using CBufLenType = size_t;
+#else
+using CBufLenType = socklen_t;
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+constexpr char kVsockNamePrefix[] = "vsock://";
+#endif
+
+// A wrapper around variable-size sockaddr structs.
+// This is solving the following problem: when calling connect() or bind(), the
+// caller needs to take care to allocate the right struct (sockaddr_un for
+// AF_UNIX, sockaddr_in for AF_INET). Those structs have different sizes and,
+// more importantly, are bigger than the base struct sockaddr.
+struct SockaddrAny {
+ SockaddrAny() : size() {}
+ SockaddrAny(const void* addr, socklen_t sz)
+ : data(new char[static_cast<size_t>(sz)]), size(sz) {
+ memcpy(data.get(), addr, static_cast<size_t>(size));
+ }
+
+ const struct sockaddr* addr() const {
+ return reinterpret_cast<const struct sockaddr*>(data.get());
+ }
+
+ std::unique_ptr<char[]> data;
+ socklen_t size;
+};
+
+inline int MkSockFamily(SockFamily family) {
+ switch (family) {
+ case SockFamily::kUnix:
+ return AF_UNIX;
+ case SockFamily::kInet:
+ return AF_INET;
+ case SockFamily::kInet6:
+ return AF_INET6;
+ case SockFamily::kVsock:
+#ifdef AF_VSOCK
+ return AF_VSOCK;
+#else
+ return AF_UNSPEC; // Return AF_UNSPEC on unsupported platforms.
+#endif
+ case SockFamily::kUnspec:
+ return AF_UNSPEC;
+ }
+ PERFETTO_CHECK(false); // For GCC.
+}
+
+inline int MkSockType(SockType type) {
+#if defined(SOCK_CLOEXEC)
+ constexpr int kSockCloExec = SOCK_CLOEXEC;
+#else
+ constexpr int kSockCloExec = 0;
+#endif
+ switch (type) {
+ case SockType::kStream:
+ return SOCK_STREAM | kSockCloExec;
+ case SockType::kDgram:
+ return SOCK_DGRAM | kSockCloExec;
+ case SockType::kSeqPacket:
+ return SOCK_SEQPACKET | kSockCloExec;
+ }
+ PERFETTO_CHECK(false); // For GCC.
+}
+
+SockaddrAny MakeSockAddr(SockFamily family, const std::string& socket_name) {
+ switch (family) {
+ case SockFamily::kUnix: {
+ struct sockaddr_un saddr {};
+ const size_t name_len = socket_name.size();
+ if (name_len + 1 /* for trailing \0 */ >= sizeof(saddr.sun_path)) {
+ errno = ENAMETOOLONG;
+ return SockaddrAny();
+ }
+ memcpy(saddr.sun_path, socket_name.data(), name_len);
+ if (saddr.sun_path[0] == '@') {
+ saddr.sun_path[0] = '\0';
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // The MSDN blog claims that abstract (non-filesystem based) AF_UNIX
+ // socket are supported, but that doesn't seem true.
+ PERFETTO_ELOG(
+ "Abstract AF_UNIX sockets are not supported on Windows, see "
+ "https://github.com/microsoft/WSL/issues/4240");
+ return SockaddrAny();
+#endif
+ }
+ saddr.sun_family = AF_UNIX;
+ auto size = static_cast<socklen_t>(
+ __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1);
+
+ // Abstract sockets do NOT require a trailing null terminator (which is
+ // instad mandatory for filesystem sockets). Any byte up to `size`,
+ // including '\0' will become part of the socket name.
+ if (saddr.sun_path[0] == '\0')
+ --size;
+ PERFETTO_CHECK(static_cast<size_t>(size) <= sizeof(saddr));
+ return SockaddrAny(&saddr, size);
+ }
+ case SockFamily::kInet: {
+ auto parts = SplitString(socket_name, ":");
+ PERFETTO_CHECK(parts.size() == 2);
+ struct addrinfo* addr_info = nullptr;
+ struct addrinfo hints {};
+ hints.ai_family = AF_INET;
+ PERFETTO_CHECK(getaddrinfo(parts[0].c_str(), parts[1].c_str(), &hints,
+ &addr_info) == 0);
+ PERFETTO_CHECK(addr_info->ai_family == AF_INET);
+ SockaddrAny res(addr_info->ai_addr,
+ static_cast<socklen_t>(addr_info->ai_addrlen));
+ freeaddrinfo(addr_info);
+ return res;
+ }
+ case SockFamily::kInet6: {
+ auto parts = SplitString(socket_name, "]");
+ PERFETTO_CHECK(parts.size() == 2);
+ auto address = SplitString(parts[0], "[");
+ PERFETTO_CHECK(address.size() == 1);
+ auto port = SplitString(parts[1], ":");
+ PERFETTO_CHECK(port.size() == 1);
+ struct addrinfo* addr_info = nullptr;
+ struct addrinfo hints {};
+ hints.ai_family = AF_INET6;
+ PERFETTO_CHECK(getaddrinfo(address[0].c_str(), port[0].c_str(), &hints,
+ &addr_info) == 0);
+ PERFETTO_CHECK(addr_info->ai_family == AF_INET6);
+ SockaddrAny res(addr_info->ai_addr,
+ static_cast<socklen_t>(addr_info->ai_addrlen));
+ freeaddrinfo(addr_info);
+ return res;
+ }
+ case SockFamily::kVsock: {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ PERFETTO_CHECK(StartsWith(socket_name, kVsockNamePrefix));
+ auto address_port = StripPrefix(socket_name, kVsockNamePrefix);
+ auto parts = SplitString(address_port, ":");
+ PERFETTO_CHECK(parts.size() == 2);
+ sockaddr_vm addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.svm_family = AF_VSOCK;
+ addr.svm_cid = *base::StringToUInt32(parts[0]);
+ addr.svm_port = *base::StringToUInt32(parts[1]);
+ SockaddrAny res(&addr, sizeof(addr));
+ return res;
+#else
+ errno = ENOTSOCK;
+ return SockaddrAny();
+#endif
+ }
+ case SockFamily::kUnspec:
+ errno = ENOTSOCK;
+ return SockaddrAny();
+ }
+ PERFETTO_CHECK(false); // For GCC.
+}
+
+ScopedSocketHandle CreateSocketHandle(SockFamily family, SockType type) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ static bool init_winsock_once = [] {
+ WSADATA ignored{};
+ return WSAStartup(MAKEWORD(2, 2), &ignored) == 0;
+ }();
+ PERFETTO_CHECK(init_winsock_once);
+#endif
+ return ScopedSocketHandle(socket(MkSockFamily(family), MkSockType(type), 0));
+}
+
+} // namespace
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+int CloseSocket(SocketHandle s) {
+ return ::closesocket(s);
+}
+#endif
+
+SockFamily GetSockFamily(const char* addr) {
+ if (strlen(addr) == 0)
+ return SockFamily::kUnspec;
+
+ if (addr[0] == '@')
+ return SockFamily::kUnix; // Abstract AF_UNIX sockets.
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ // Vsock address starts with vsock://.
+ if (strncmp(addr, kVsockNamePrefix, strlen(kVsockNamePrefix)) == 0)
+ return SockFamily::kVsock;
+#endif
+
+ // If `addr` ends in :NNNN it's either a kInet or kInet6 socket.
+ const char* col = strrchr(addr, ':');
+ if (col && CStringToInt32(col + 1).has_value()) {
+ return addr[0] == '[' ? SockFamily::kInet6 : SockFamily::kInet;
+ }
+
+ return SockFamily::kUnix; // For anything else assume it's a linked AF_UNIX.
+}
+
+// +-----------------------+
+// | UnixSocketRaw methods |
+// +-----------------------+
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// static
+void UnixSocketRaw::ShiftMsgHdrPosix(size_t n, struct msghdr* msg) {
+ using LenType = decltype(msg->msg_iovlen); // Mac and Linux don't agree.
+ for (LenType i = 0; i < msg->msg_iovlen; ++i) {
+ struct iovec* vec = &msg->msg_iov[i];
+ if (n < vec->iov_len) {
+ // We sent a part of this iovec.
+ vec->iov_base = reinterpret_cast<char*>(vec->iov_base) + n;
+ vec->iov_len -= n;
+ msg->msg_iov = vec;
+ msg->msg_iovlen -= i;
+ return;
+ }
+ // We sent the whole iovec.
+ n -= vec->iov_len;
+ }
+ // We sent all the iovecs.
+ PERFETTO_CHECK(n == 0);
+ msg->msg_iovlen = 0;
+ msg->msg_iov = nullptr;
+}
+
+// static
+std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePairPosix(
+ SockFamily family,
+ SockType type) {
+ int fds[2];
+ if (socketpair(MkSockFamily(family), MkSockType(type), 0, fds) != 0) {
+ return std::make_pair(UnixSocketRaw(), UnixSocketRaw());
+ }
+ return std::make_pair(UnixSocketRaw(ScopedFile(fds[0]), family, type),
+ UnixSocketRaw(ScopedFile(fds[1]), family, type));
+}
+#endif
+
+// static
+UnixSocketRaw UnixSocketRaw::CreateMayFail(SockFamily family, SockType type) {
+ auto fd = CreateSocketHandle(family, type);
+ if (!fd)
+ return UnixSocketRaw();
+ return UnixSocketRaw(std::move(fd), family, type);
+}
+
+UnixSocketRaw::UnixSocketRaw() = default;
+
+UnixSocketRaw::UnixSocketRaw(SockFamily family, SockType type)
+ : UnixSocketRaw(CreateSocketHandle(family, type), family, type) {}
+
+UnixSocketRaw::UnixSocketRaw(ScopedSocketHandle fd,
+ SockFamily family,
+ SockType type)
+ : fd_(std::move(fd)), family_(family), type_(type) {
+ PERFETTO_CHECK(fd_);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ const int no_sigpipe = 1;
+ setsockopt(*fd_, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, sizeof(no_sigpipe));
+#endif
+
+ if (family == SockFamily::kInet || family == SockFamily::kInet6 ||
+ family == SockFamily::kVsock) {
+ int flag = 1;
+ // The reinterpret_cast<const char*> is needed for Windows, where the 4th
+ // arg is a const char* (on other POSIX system is a const void*).
+ PERFETTO_CHECK(!setsockopt(*fd_, SOL_SOCKET, SO_REUSEADDR,
+ reinterpret_cast<const char*>(&flag),
+ sizeof(flag)));
+ }
+
+ if (family == SockFamily::kInet || family == SockFamily::kInet6) {
+ int flag = 1;
+ // Disable Nagle's algorithm, optimize for low-latency.
+ // See https://github.com/google/perfetto/issues/70.
+ setsockopt(*fd_, IPPROTO_TCP, TCP_NODELAY,
+ reinterpret_cast<const char*>(&flag), sizeof(flag));
+ }
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // We use one event handle for all socket events, to stay consistent to what
+ // we do on UNIX with the base::TaskRunner's poll().
+ event_handle_.reset(WSACreateEvent());
+ PERFETTO_CHECK(event_handle_);
+#else
+ // There is no reason why a socket should outlive the process in case of
+ // exec() by default, this is just working around a broken unix design.
+ SetRetainOnExec(false);
+#endif
+}
+
+void UnixSocketRaw::SetBlocking(bool is_blocking) {
+ PERFETTO_DCHECK(fd_);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ unsigned long flag = is_blocking ? 0 : 1; // FIONBIO has reverse logic.
+ if (is_blocking) {
+ // When switching between non-blocking -> blocking mode, we need to reset
+ // the event handle registration, otherwise the call will fail.
+ PERFETTO_CHECK(WSAEventSelect(*fd_, *event_handle_, 0) == 0);
+ }
+ PERFETTO_CHECK(ioctlsocket(*fd_, static_cast<long>(FIONBIO), &flag) == 0);
+ if (!is_blocking) {
+ PERFETTO_CHECK(
+ WSAEventSelect(*fd_, *event_handle_,
+ FD_ACCEPT | FD_CONNECT | FD_READ | FD_CLOSE) == 0);
+ }
+#else
+ int flags = fcntl(*fd_, F_GETFL, 0);
+ if (!is_blocking) {
+ flags |= O_NONBLOCK;
+ } else {
+ flags &= ~static_cast<int>(O_NONBLOCK);
+ }
+ int fcntl_res = fcntl(*fd_, F_SETFL, flags);
+ PERFETTO_CHECK(fcntl_res == 0);
+#endif
+}
+
+void UnixSocketRaw::SetRetainOnExec(bool retain) {
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+ PERFETTO_DCHECK(fd_);
+ int flags = fcntl(*fd_, F_GETFD, 0);
+ if (retain) {
+ flags &= ~static_cast<int>(FD_CLOEXEC);
+ } else {
+ flags |= FD_CLOEXEC;
+ }
+ int fcntl_res = fcntl(*fd_, F_SETFD, flags);
+ PERFETTO_CHECK(fcntl_res == 0);
+#else
+ ignore_result(retain);
+#endif
+}
+
+void UnixSocketRaw::DcheckIsBlocking(bool expected) const {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ ignore_result(expected);
+#else
+ PERFETTO_DCHECK(fd_);
+ bool is_blocking = (fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0;
+ PERFETTO_DCHECK(is_blocking == expected);
+#endif
+}
+
+bool UnixSocketRaw::Bind(const std::string& socket_name) {
+ PERFETTO_DCHECK(fd_);
+ SockaddrAny addr = MakeSockAddr(family_, socket_name);
+ if (addr.size == 0)
+ return false;
+
+ if (bind(*fd_, addr.addr(), addr.size)) {
+ PERFETTO_DPLOG("bind(%s)", socket_name.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+bool UnixSocketRaw::Listen() {
+ PERFETTO_DCHECK(fd_);
+ PERFETTO_DCHECK(type_ == SockType::kStream || type_ == SockType::kSeqPacket);
+ return listen(*fd_, SOMAXCONN) == 0;
+}
+
+bool UnixSocketRaw::Connect(const std::string& socket_name) {
+ PERFETTO_DCHECK(fd_);
+ SockaddrAny addr = MakeSockAddr(family_, socket_name);
+ if (addr.size == 0)
+ return false;
+
+ int res = PERFETTO_EINTR(connect(*fd_, addr.addr(), addr.size));
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ bool continue_async = WSAGetLastError() == WSAEWOULDBLOCK;
+#else
+ bool continue_async = errno == EINPROGRESS;
+#endif
+ if (res && !continue_async)
+ return false;
+
+ return true;
+}
+
+void UnixSocketRaw::Shutdown() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // Somebody felt very strongly about the naming of this constant.
+ shutdown(*fd_, SD_BOTH);
+#else
+ shutdown(*fd_, SHUT_RDWR);
+#endif
+ fd_.reset();
+}
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+ssize_t UnixSocketRaw::Send(const void* msg,
+ size_t len,
+ const int* /*send_fds*/,
+ size_t num_fds) {
+ PERFETTO_DCHECK(num_fds == 0);
+ return sendto(*fd_, static_cast<const char*>(msg), static_cast<int>(len), 0,
+ nullptr, 0);
+}
+
+ssize_t UnixSocketRaw::Receive(void* msg,
+ size_t len,
+ ScopedFile* /*fd_vec*/,
+ size_t /*max_files*/) {
+ return recv(*fd_, static_cast<char*>(msg), static_cast<int>(len), 0);
+}
+
+#else
+// For the interested reader, Linux kernel dive to verify this is not only a
+// theoretical possibility: sock_stream_sendmsg, if sock_alloc_send_pskb returns
+// NULL [1] (which it does when it gets interrupted [2]), returns early with the
+// amount of bytes already sent.
+//
+// [1]:
+// https://elixir.bootlin.com/linux/v4.18.10/source/net/unix/af_unix.c#L1872
+// [2]: https://elixir.bootlin.com/linux/v4.18.10/source/net/core/sock.c#L2101
+ssize_t UnixSocketRaw::SendMsgAllPosix(struct msghdr* msg) {
+ // This does not make sense on non-blocking sockets.
+ PERFETTO_DCHECK(fd_);
+
+ const bool is_blocking_with_timeout =
+ tx_timeout_ms_ > 0 && ((fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0);
+ const int64_t start_ms = GetWallTimeMs().count();
+
+ // Waits until some space is available in the tx buffer.
+ // Returns true if some buffer space is available, false if times out.
+ auto poll_or_timeout = [&] {
+ PERFETTO_DCHECK(is_blocking_with_timeout);
+ const int64_t deadline = start_ms + tx_timeout_ms_;
+ const int64_t now_ms = GetWallTimeMs().count();
+ if (now_ms >= deadline)
+ return false; // Timed out
+ const int timeout_ms = static_cast<int>(deadline - now_ms);
+ pollfd pfd{*fd_, POLLOUT, 0};
+ return PERFETTO_EINTR(poll(&pfd, 1, timeout_ms)) > 0;
+ };
+
+// We implement blocking sends that require a timeout as non-blocking + poll.
+// This is because SO_SNDTIMEO doesn't work as expected (b/193234818). On linux
+// we can just pass MSG_DONTWAIT to force the send to be non-blocking. On Mac,
+// instead we need to flip the O_NONBLOCK flag back and forth.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ // MSG_NOSIGNAL is not supported on Mac OS X, but in that case the socket is
+ // created with SO_NOSIGPIPE (See InitializeSocket()).
+ int send_flags = 0;
+
+ if (is_blocking_with_timeout)
+ SetBlocking(false);
+
+ auto reset_nonblock_on_exit = OnScopeExit([&] {
+ if (is_blocking_with_timeout)
+ SetBlocking(true);
+ });
+#else
+ int send_flags = MSG_NOSIGNAL | (is_blocking_with_timeout ? MSG_DONTWAIT : 0);
+#endif
+
+ ssize_t total_sent = 0;
+ while (msg->msg_iov) {
+ ssize_t send_res = PERFETTO_EINTR(sendmsg(*fd_, msg, send_flags));
+ if (send_res == -1 && IsAgain(errno)) {
+ if (is_blocking_with_timeout && poll_or_timeout()) {
+ continue; // Tx buffer unblocked, repeat the loop.
+ }
+ return total_sent;
+ } else if (send_res <= 0) {
+ return send_res; // An error occurred.
+ } else {
+ total_sent += send_res;
+ ShiftMsgHdrPosix(static_cast<size_t>(send_res), msg);
+ // Only send the ancillary data with the first sendmsg call.
+ msg->msg_control = nullptr;
+ msg->msg_controllen = 0;
+ }
+ }
+ return total_sent;
+}
+
+ssize_t UnixSocketRaw::Send(const void* msg,
+ size_t len,
+ const int* send_fds,
+ size_t num_fds) {
+ PERFETTO_DCHECK(fd_);
+ msghdr msg_hdr = {};
+ iovec iov = {const_cast<void*>(msg), len};
+ msg_hdr.msg_iov = &iov;
+ msg_hdr.msg_iovlen = 1;
+ alignas(cmsghdr) char control_buf[256];
+
+ if (num_fds > 0) {
+ const auto raw_ctl_data_sz = num_fds * sizeof(int);
+ const CBufLenType control_buf_len =
+ static_cast<CBufLenType>(CMSG_SPACE(raw_ctl_data_sz));
+ PERFETTO_CHECK(control_buf_len <= sizeof(control_buf));
+ memset(control_buf, 0, sizeof(control_buf));
+ msg_hdr.msg_control = control_buf;
+ msg_hdr.msg_controllen = control_buf_len; // used by CMSG_FIRSTHDR
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = static_cast<CBufLenType>(CMSG_LEN(raw_ctl_data_sz));
+ memcpy(CMSG_DATA(cmsg), send_fds, num_fds * sizeof(int));
+ // note: if we were to send multiple cmsghdr structures, then
+ // msg_hdr.msg_controllen would need to be adjusted, see "man 3 cmsg".
+ }
+
+ return SendMsgAllPosix(&msg_hdr);
+}
+
+ssize_t UnixSocketRaw::Receive(void* msg,
+ size_t len,
+ ScopedFile* fd_vec,
+ size_t max_files) {
+ PERFETTO_DCHECK(fd_);
+ msghdr msg_hdr = {};
+ iovec iov = {msg, len};
+ msg_hdr.msg_iov = &iov;
+ msg_hdr.msg_iovlen = 1;
+ alignas(cmsghdr) char control_buf[256];
+
+ if (max_files > 0) {
+ msg_hdr.msg_control = control_buf;
+ msg_hdr.msg_controllen =
+ static_cast<CBufLenType>(CMSG_SPACE(max_files * sizeof(int)));
+ PERFETTO_CHECK(msg_hdr.msg_controllen <= sizeof(control_buf));
+ }
+ const ssize_t sz = PERFETTO_EINTR(recvmsg(*fd_, &msg_hdr, 0));
+ if (sz <= 0) {
+ return sz;
+ }
+ PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
+
+ int* fds = nullptr;
+ uint32_t fds_len = 0;
+
+ if (max_files > 0) {
+ for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr); cmsg;
+ cmsg = CMSG_NXTHDR(&msg_hdr, cmsg)) {
+ const size_t payload_len = cmsg->cmsg_len - CMSG_LEN(0);
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ PERFETTO_DCHECK(payload_len % sizeof(int) == 0u);
+ PERFETTO_CHECK(fds == nullptr);
+ fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+ fds_len = static_cast<uint32_t>(payload_len / sizeof(int));
+ }
+ }
+ }
+
+ if (msg_hdr.msg_flags & MSG_TRUNC || msg_hdr.msg_flags & MSG_CTRUNC) {
+ for (size_t i = 0; fds && i < fds_len; ++i)
+ close(fds[i]);
+ PERFETTO_ELOG(
+ "Socket message truncated. This might be due to a SELinux denial on "
+ "fd:use.");
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ for (size_t i = 0; fds && i < fds_len; ++i) {
+ if (i < max_files)
+ fd_vec[i].reset(fds[i]);
+ else
+ close(fds[i]);
+ }
+
+ return sz;
+}
+#endif // OS_WIN
+
+bool UnixSocketRaw::SetTxTimeout(uint32_t timeout_ms) {
+ PERFETTO_DCHECK(fd_);
+ // On Unix-based systems, SO_SNDTIMEO isn't used for Send() because it's
+ // unreliable (b/193234818). Instead we use non-blocking sendmsg() + poll().
+ // See SendMsgAllPosix(). We still make the setsockopt call because
+ // SO_SNDTIMEO also affects connect().
+ tx_timeout_ms_ = timeout_ms;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ DWORD timeout = timeout_ms;
+ ignore_result(tx_timeout_ms_);
+#else
+ struct timeval timeout {};
+ uint32_t timeout_sec = timeout_ms / 1000;
+ timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
+ timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
+ (timeout_ms - (timeout_sec * 1000)) * 1000);
+#endif
+ return setsockopt(*fd_, SOL_SOCKET, SO_SNDTIMEO,
+ reinterpret_cast<const char*>(&timeout),
+ sizeof(timeout)) == 0;
+}
+
+bool UnixSocketRaw::SetRxTimeout(uint32_t timeout_ms) {
+ PERFETTO_DCHECK(fd_);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ DWORD timeout = timeout_ms;
+#else
+ struct timeval timeout {};
+ uint32_t timeout_sec = timeout_ms / 1000;
+ timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
+ timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
+ (timeout_ms - (timeout_sec * 1000)) * 1000);
+#endif
+ return setsockopt(*fd_, SOL_SOCKET, SO_RCVTIMEO,
+ reinterpret_cast<const char*>(&timeout),
+ sizeof(timeout)) == 0;
+}
+
+std::string UnixSocketRaw::GetSockAddr() const {
+ struct sockaddr_storage stg {};
+ socklen_t slen = sizeof(stg);
+ PERFETTO_CHECK(
+ getsockname(*fd_, reinterpret_cast<struct sockaddr*>(&stg), &slen) == 0);
+ char addr[255]{};
+
+ if (stg.ss_family == AF_UNIX) {
+ auto* saddr = reinterpret_cast<struct sockaddr_un*>(&stg);
+ static_assert(sizeof(addr) >= sizeof(saddr->sun_path), "addr too small");
+ memcpy(addr, saddr->sun_path, sizeof(saddr->sun_path));
+ addr[0] = addr[0] == '\0' ? '@' : addr[0];
+ addr[sizeof(saddr->sun_path) - 1] = '\0';
+ return std::string(addr);
+ }
+
+ if (stg.ss_family == AF_INET) {
+ auto* saddr = reinterpret_cast<struct sockaddr_in*>(&stg);
+ PERFETTO_CHECK(inet_ntop(AF_INET, &saddr->sin_addr, addr, sizeof(addr)));
+ uint16_t port = ntohs(saddr->sin_port);
+ base::StackString<255> addr_and_port("%s:%" PRIu16, addr, port);
+ return addr_and_port.ToStdString();
+ }
+
+ if (stg.ss_family == AF_INET6) {
+ auto* saddr = reinterpret_cast<struct sockaddr_in6*>(&stg);
+ PERFETTO_CHECK(inet_ntop(AF_INET6, &saddr->sin6_addr, addr, sizeof(addr)));
+ auto port = ntohs(saddr->sin6_port);
+ base::StackString<255> addr_and_port("[%s]:%" PRIu16, addr, port);
+ return addr_and_port.ToStdString();
+ }
+
+#if defined(AF_VSOCK) && (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID))
+ if (stg.ss_family == AF_VSOCK) {
+ auto* saddr = reinterpret_cast<struct sockaddr_vm*>(&stg);
+ base::StackString<255> addr_and_port("%s%d:%d", kVsockNamePrefix,
+ saddr->svm_cid, saddr->svm_port);
+ return addr_and_port.ToStdString();
+ }
+#endif
+
+ PERFETTO_FATAL("GetSockAddr() unsupported on family %d", stg.ss_family);
+}
+
+#if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#pragma GCC diagnostic pop
+#endif
+
+// +--------------------+
+// | UnixSocket methods |
+// +--------------------+
+
+// TODO(primiano): Add ThreadChecker to methods of this class.
+
+// static
+std::unique_ptr<UnixSocket> UnixSocket::Listen(const std::string& socket_name,
+ EventListener* event_listener,
+ TaskRunner* task_runner,
+ SockFamily sock_family,
+ SockType sock_type) {
+ auto sock_raw = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
+ if (!sock_raw || !sock_raw.Bind(socket_name))
+ return nullptr;
+
+ // Forward the call to the Listen() overload below.
+ return Listen(sock_raw.ReleaseFd(), event_listener, task_runner, sock_family,
+ sock_type);
+}
+
+// static
+std::unique_ptr<UnixSocket> UnixSocket::Listen(ScopedSocketHandle fd,
+ EventListener* event_listener,
+ TaskRunner* task_runner,
+ SockFamily sock_family,
+ SockType sock_type) {
+ return std::unique_ptr<UnixSocket>(new UnixSocket(
+ event_listener, task_runner, std::move(fd), State::kListening,
+ sock_family, sock_type, SockPeerCredMode::kDefault));
+}
+
+// static
+std::unique_ptr<UnixSocket> UnixSocket::Connect(
+ const std::string& socket_name,
+ EventListener* event_listener,
+ TaskRunner* task_runner,
+ SockFamily sock_family,
+ SockType sock_type,
+ SockPeerCredMode peer_cred_mode) {
+ std::unique_ptr<UnixSocket> sock(new UnixSocket(
+ event_listener, task_runner, sock_family, sock_type, peer_cred_mode));
+ sock->DoConnect(socket_name);
+ return sock;
+}
+
+// static
+std::unique_ptr<UnixSocket> UnixSocket::AdoptConnected(
+ ScopedSocketHandle fd,
+ EventListener* event_listener,
+ TaskRunner* task_runner,
+ SockFamily sock_family,
+ SockType sock_type,
+ SockPeerCredMode peer_cred_mode) {
+ return std::unique_ptr<UnixSocket>(new UnixSocket(
+ event_listener, task_runner, std::move(fd), State::kConnected,
+ sock_family, sock_type, peer_cred_mode));
+}
+
+UnixSocket::UnixSocket(EventListener* event_listener,
+ TaskRunner* task_runner,
+ SockFamily sock_family,
+ SockType sock_type,
+ SockPeerCredMode peer_cred_mode)
+ : UnixSocket(event_listener,
+ task_runner,
+ ScopedSocketHandle(),
+ State::kDisconnected,
+ sock_family,
+ sock_type,
+ peer_cred_mode) {}
+
+UnixSocket::UnixSocket(EventListener* event_listener,
+ TaskRunner* task_runner,
+ ScopedSocketHandle adopt_fd,
+ State adopt_state,
+ SockFamily sock_family,
+ SockType sock_type,
+ SockPeerCredMode peer_cred_mode)
+ : peer_cred_mode_(peer_cred_mode),
+ event_listener_(event_listener),
+ task_runner_(task_runner),
+ weak_ptr_factory_(this) {
+ state_ = State::kDisconnected;
+ if (adopt_state == State::kDisconnected) {
+ PERFETTO_DCHECK(!adopt_fd);
+ sock_raw_ = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
+ if (!sock_raw_)
+ return;
+ } else if (adopt_state == State::kConnected) {
+ PERFETTO_DCHECK(adopt_fd);
+ sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
+ state_ = State::kConnected;
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
+ ReadPeerCredentialsPosix();
+#endif
+ } else if (adopt_state == State::kListening) {
+ // We get here from Listen().
+
+ // |adopt_fd| might genuinely be invalid if the bind() failed.
+ if (!adopt_fd)
+ return;
+
+ sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
+ if (!sock_raw_.Listen()) {
+ PERFETTO_DPLOG("listen() failed");
+ return;
+ }
+ state_ = State::kListening;
+ } else {
+ PERFETTO_FATAL("Unexpected adopt_state"); // Unfeasible.
+ }
+
+ PERFETTO_CHECK(sock_raw_);
+
+ sock_raw_.SetBlocking(false);
+
+ WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
+
+ task_runner_->AddFileDescriptorWatch(sock_raw_.watch_handle(), [weak_ptr] {
+ if (weak_ptr)
+ weak_ptr->OnEvent();
+ });
+}
+
+UnixSocket::~UnixSocket() {
+ // The implicit dtor of |weak_ptr_factory_| will no-op pending callbacks.
+ Shutdown(true);
+}
+
+UnixSocketRaw UnixSocket::ReleaseSocket() {
+ // This will invalidate any pending calls to OnEvent.
+ state_ = State::kDisconnected;
+ if (sock_raw_)
+ task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
+
+ return std::move(sock_raw_);
+}
+
+// Called only by the Connect() static constructor.
+void UnixSocket::DoConnect(const std::string& socket_name) {
+ PERFETTO_DCHECK(state_ == State::kDisconnected);
+
+ // This is the only thing that can gracefully fail in the ctor.
+ if (!sock_raw_)
+ return NotifyConnectionState(false);
+
+ if (!sock_raw_.Connect(socket_name))
+ return NotifyConnectionState(false);
+
+ // At this point either connect() succeeded or started asynchronously
+ // (errno = EINPROGRESS).
+ state_ = State::kConnecting;
+
+ // Even if the socket is non-blocking, connecting to a UNIX socket can be
+ // acknowledged straight away rather than returning EINPROGRESS.
+ // The decision here is to deal with the two cases uniformly, at the cost of
+ // delaying the straight-away-connect() case by one task, to avoid depending
+ // on implementation details of UNIX socket on the various OSes.
+ // Posting the OnEvent() below emulates a wakeup of the FD watch. OnEvent(),
+ // which knows how to deal with spurious wakeups, will poll the SO_ERROR and
+ // evolve, if necessary, the state into either kConnected or kDisconnected.
+ WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_ptr] {
+ if (weak_ptr)
+ weak_ptr->OnEvent();
+ });
+}
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+void UnixSocket::ReadPeerCredentialsPosix() {
+ // Peer credentials are supported only on AF_UNIX sockets.
+ if (sock_raw_.family() != SockFamily::kUnix)
+ return;
+ PERFETTO_CHECK(peer_cred_mode_ != SockPeerCredMode::kIgnore);
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ struct ucred user_cred;
+ socklen_t len = sizeof(user_cred);
+ int fd = sock_raw_.fd();
+ int res = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &user_cred, &len);
+ PERFETTO_CHECK(res == 0);
+ peer_uid_ = user_cred.uid;
+ peer_pid_ = user_cred.pid;
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ struct xucred user_cred;
+ socklen_t len = sizeof(user_cred);
+ int res = getsockopt(sock_raw_.fd(), 0, LOCAL_PEERCRED, &user_cred, &len);
+ PERFETTO_CHECK(res == 0 && user_cred.cr_version == XUCRED_VERSION);
+ peer_uid_ = static_cast<uid_t>(user_cred.cr_uid);
+ // There is no pid in the LOCAL_PEERCREDS for MacOS / FreeBSD.
+#endif
+}
+#endif // !OS_WIN
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+void UnixSocket::OnEvent() {
+ WSANETWORKEVENTS evts{};
+ PERFETTO_CHECK(WSAEnumNetworkEvents(sock_raw_.fd(), sock_raw_.watch_handle(),
+ &evts) == 0);
+ if (state_ == State::kDisconnected)
+ return; // Some spurious event, typically queued just before Shutdown().
+
+ if (state_ == State::kConnecting && (evts.lNetworkEvents & FD_CONNECT)) {
+ PERFETTO_DCHECK(sock_raw_);
+ int err = evts.iErrorCode[FD_CONNECT_BIT];
+ if (err) {
+ PERFETTO_DPLOG("Connection error: %d", err);
+ Shutdown(false);
+ event_listener_->OnConnect(this, false /* connected */);
+ return;
+ }
+
+ // kReadOnConnect is not supported on Windows.
+ PERFETTO_DCHECK(peer_cred_mode_ != SockPeerCredMode::kReadOnConnect);
+ state_ = State::kConnected;
+ event_listener_->OnConnect(this, true /* connected */);
+ }
+
+ // This is deliberately NOT an else-if. When a client socket connects and
+ // there is already data queued, the following will happen within the same
+ // OnEvent() call:
+ // 1. The block above will transition kConnecting -> kConnected.
+ // 2. This block will cause an OnDataAvailable() call.
+ // Unlike UNIX, where poll() keeps signalling the event until the client
+ // does a recv(), Windows is more picky and stops signalling the event until
+ // the next call to recv() is made. In other words, in Windows we cannot
+ // miss an OnDataAvailable() call or the event pump will stop.
+ if (state_ == State::kConnected) {
+ if (evts.lNetworkEvents & FD_READ) {
+ event_listener_->OnDataAvailable(this);
+ // TODO(primiano): I am very conflicted here. Because of the behavior
+ // described above, if the event listener doesn't do a Recv() call in
+ // the OnDataAvailable() callback, WinSock won't notify the event ever
+ // again. On one side, I don't see any reason why a client should decide
+ // to not do a Recv() in OnDataAvailable. On the other side, the
+ // behavior here diverges from UNIX, where OnDataAvailable() would be
+ // re-posted immediately. In both cases, not doing a Recv() in
+ // OnDataAvailable, leads to something bad (getting stuck on Windows,
+ // getting in a hot loop on Linux), so doesn't feel we should worry too
+ // much about this. If we wanted to keep the behavrior consistent, here
+ // we should do something like: `if (sock_raw_)
+ // sock_raw_.SetBlocking(false)` (Note that the socket might be closed
+ // by the time we come back here, hence the if part).
+ return;
+ }
+ // Could read EOF and disconnect here.
+ if (evts.lNetworkEvents & FD_CLOSE) {
+ Shutdown(true);
+ return;
+ }
+ }
+
+ // New incoming connection.
+ if (state_ == State::kListening && (evts.lNetworkEvents & FD_ACCEPT)) {
+ // There could be more than one incoming connection behind each FD watch
+ // notification. Drain'em all.
+ for (;;) {
+ // Note: right now we don't need the remote endpoint, hence we pass
+ // nullptr to |addr| and |addrlen|. If we ever need to do so, be
+ // extremely careful. Windows' WinSock API will happily write more than
+ // |addrlen| (hence corrupt the stack) if the |addr| argument passed is
+ // not big enough (e.g. passing a struct sockaddr_in to a AF_UNIX
+ // socket, where sizeof(sockaddr_un) is >> sizef(sockaddr_in)). It seems
+ // a Windows / CRT bug in the AF_UNIX implementation.
+ ScopedSocketHandle new_fd(accept(sock_raw_.fd(), nullptr, nullptr));
+ if (!new_fd)
+ return;
+ std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
+ event_listener_, task_runner_, std::move(new_fd), State::kConnected,
+ sock_raw_.family(), sock_raw_.type(), peer_cred_mode_));
+ event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
+ }
+ }
+}
+#else
+void UnixSocket::OnEvent() {
+ if (state_ == State::kDisconnected)
+ return; // Some spurious event, typically queued just before Shutdown().
+
+ if (state_ == State::kConnected)
+ return event_listener_->OnDataAvailable(this);
+
+ if (state_ == State::kConnecting) {
+ PERFETTO_DCHECK(sock_raw_);
+ int sock_err = EINVAL;
+ socklen_t err_len = sizeof(sock_err);
+ int res =
+ getsockopt(sock_raw_.fd(), SOL_SOCKET, SO_ERROR, &sock_err, &err_len);
+
+ if (res == 0 && sock_err == EINPROGRESS)
+ return; // Not connected yet, just a spurious FD watch wakeup.
+ if (res == 0 && sock_err == 0) {
+ if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
+ ReadPeerCredentialsPosix();
+ state_ = State::kConnected;
+ return event_listener_->OnConnect(this, true /* connected */);
+ }
+ PERFETTO_DLOG("Connection error: %s", strerror(sock_err));
+ Shutdown(false);
+ return event_listener_->OnConnect(this, false /* connected */);
+ }
+
+ // New incoming connection.
+ if (state_ == State::kListening) {
+ // There could be more than one incoming connection behind each FD watch
+ // notification. Drain'em all.
+ for (;;) {
+ ScopedFile new_fd(
+ PERFETTO_EINTR(accept(sock_raw_.fd(), nullptr, nullptr)));
+ if (!new_fd)
+ return;
+ std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
+ event_listener_, task_runner_, std::move(new_fd), State::kConnected,
+ sock_raw_.family(), sock_raw_.type(), peer_cred_mode_));
+ event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
+ }
+ }
+}
+#endif
+
+bool UnixSocket::Send(const void* msg,
+ size_t len,
+ const int* send_fds,
+ size_t num_fds) {
+ if (state_ != State::kConnected) {
+ errno = ENOTCONN;
+ return false;
+ }
+
+ sock_raw_.SetBlocking(true);
+ const ssize_t sz = sock_raw_.Send(msg, len, send_fds, num_fds);
+ sock_raw_.SetBlocking(false);
+
+ if (sz == static_cast<ssize_t>(len)) {
+ return true;
+ }
+
+ // If we ever decide to support non-blocking sends again, here we should
+ // watch for both EAGAIN and EWOULDBLOCK (see base::IsAgain()).
+
+ // If sendmsg() succeeds but the returned size is >= 0 and < |len| it means
+ // that the endpoint disconnected in the middle of the read, and we managed
+ // to send only a portion of the buffer.
+ // If sz < 0, either the other endpoint disconnected (ECONNRESET) or some
+ // other error happened. In both cases we should just give up.
+ PERFETTO_DPLOG("sendmsg() failed");
+ Shutdown(true);
+ return false;
+}
+
+void UnixSocket::Shutdown(bool notify) {
+ WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
+ if (notify) {
+ if (state_ == State::kConnected) {
+ task_runner_->PostTask([weak_ptr] {
+ if (weak_ptr)
+ weak_ptr->event_listener_->OnDisconnect(weak_ptr.get());
+ });
+ } else if (state_ == State::kConnecting) {
+ task_runner_->PostTask([weak_ptr] {
+ if (weak_ptr)
+ weak_ptr->event_listener_->OnConnect(weak_ptr.get(), false);
+ });
+ }
+ }
+
+ if (sock_raw_) {
+ task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
+ sock_raw_.Shutdown();
+ }
+ state_ = State::kDisconnected;
+}
+
+size_t UnixSocket::Receive(void* msg,
+ size_t len,
+ ScopedFile* fd_vec,
+ size_t max_files) {
+ if (state_ != State::kConnected)
+ return 0;
+
+ const ssize_t sz = sock_raw_.Receive(msg, len, fd_vec, max_files);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ bool async_would_block = WSAGetLastError() == WSAEWOULDBLOCK;
+#else
+ bool async_would_block = IsAgain(errno);
+#endif
+ if (sz < 0 && async_would_block)
+ return 0;
+
+ if (sz <= 0) {
+ Shutdown(true);
+ return 0;
+ }
+ PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
+ return static_cast<size_t>(sz);
+}
+
+std::string UnixSocket::ReceiveString(size_t max_length) {
+ std::unique_ptr<char[]> buf(new char[max_length + 1]);
+ size_t rsize = Receive(buf.get(), max_length);
+ PERFETTO_CHECK(rsize <= max_length);
+ buf[rsize] = '\0';
+ return std::string(buf.get());
+}
+
+void UnixSocket::NotifyConnectionState(bool success) {
+ if (!success)
+ Shutdown(false);
+
+ WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_ptr, success] {
+ if (weak_ptr)
+ weak_ptr->event_listener_->OnConnect(weak_ptr.get(), success);
+ });
+}
+
+UnixSocket::EventListener::~EventListener() {}
+void UnixSocket::EventListener::OnNewIncomingConnection(
+ UnixSocket*,
+ std::unique_ptr<UnixSocket>) {}
+void UnixSocket::EventListener::OnConnect(UnixSocket*, bool) {}
+void UnixSocket::EventListener::OnDisconnect(UnixSocket*) {}
+void UnixSocket::EventListener::OnDataAvailable(UnixSocket*) {}
+
+} // namespace base
+} // namespace perfetto
+// gen_amalgamated begin source: src/ipc/buffered_frame_deserializer.cc
+// gen_amalgamated begin header: src/ipc/buffered_frame_deserializer.h
+// gen_amalgamated begin header: include/perfetto/ext/ipc/basic_types.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_BASIC_TYPES_H_
+#define INCLUDE_PERFETTO_EXT_IPC_BASIC_TYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+
+namespace perfetto {
+namespace ipc {
+
+using ProtoMessage = ::protozero::CppMessageObj;
+using ServiceID = uint32_t;
+using MethodID = uint32_t;
+using ClientID = uint64_t;
+using RequestID = uint64_t;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// AF_UNIX on Windows is supported only on Windows 10 from build 17063.
+// Also it doesn't bring major advantages compared to a TCP socket.
+// See go/perfetto-win .
+constexpr bool kUseTCPSocket = true;
+#else
+// Android, Linux, Mac, Fuchsia use local sockets.
+constexpr bool kUseTCPSocket = false;
+#endif
+
+// This determines the maximum size allowed for an IPC message. Trying to send
+// or receive a larger message will hit DCHECK(s) and auto-disconnect.
+constexpr size_t kIPCBufferSize = 128 * 1024;
+
+constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_BASIC_TYPES_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_IPC_BUFFERED_FRAME_DESERIALIZER_H_
+#define SRC_IPC_BUFFERED_FRAME_DESERIALIZER_H_
+
+#include <stddef.h>
+
+#include <list>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/paged_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+
+namespace perfetto {
+
+namespace protos {
+namespace gen {
+class IPCFrame;
+} // namespace gen
+} // namespace protos
+
+namespace ipc {
+
+using Frame = ::perfetto::protos::gen::IPCFrame;
+
+// Deserializes incoming frames, taking care of buffering and tokenization.
+// Used by both host and client to decode incoming frames.
+//
+// Which problem does it solve?
+// ----------------------------
+// The wire protocol is as follows:
+// [32-bit frame size][proto-encoded Frame], e.g:
+// [06 00 00 00][00 11 22 33 44 55 66]
+// [02 00 00 00][AA BB]
+// [04 00 00 00][CC DD EE FF]
+// However, given that the socket works in SOCK_STREAM mode, the recv() calls
+// might see the following:
+// 06 00 00
+// 00 00 11 22 33 44 55
+// 66 02 00 00 00 ...
+// This class takes care of buffering efficiently the data received, without
+// making any assumption on how the incoming data will be chunked by the socket.
+// For instance, it is possible that a recv() doesn't produce any frame (because
+// it received only a part of the frame) or produces more than one frame.
+//
+// Usage
+// -----
+// Both host and client use this as follows:
+//
+// auto buf = rpc_frame_decoder.BeginReceive();
+// size_t rsize = socket.recv(buf.first, buf.second);
+// rpc_frame_decoder.EndReceive(rsize);
+// while (Frame frame = rpc_frame_decoder.PopNextFrame()) {
+// ... process |frame|
+// }
+//
+// Design goals:
+// -------------
+// - Optimize for the realistic case of each recv() receiving one or more
+// whole frames. In this case no memmove is performed.
+// - Guarantee that frames lay in a virtually contiguous memory area.
+// This allows to use the protobuf-lite deserialization API (scattered
+// deserialization is supported only by libprotobuf-full).
+// - Put a hard boundary to the size of the incoming buffer. This is to prevent
+// that a malicious sends an abnormally large frame and OOMs us.
+// - Simplicity: just use a linear mmap region. No reallocations or scattering.
+// Takes care of madvise()-ing unused memory.
+
+class BufferedFrameDeserializer {
+ public:
+ struct ReceiveBuffer {
+ char* data;
+ size_t size;
+ };
+
+ // |max_capacity| is overridable only for tests.
+ explicit BufferedFrameDeserializer(size_t max_capacity = kIPCBufferSize);
+ ~BufferedFrameDeserializer();
+
+ // This function doesn't really belong here as it does Serialization, unlike
+ // the rest of this class. However it is so small and has so many dependencies
+ // in common that doesn't justify having its own class.
+ static std::string Serialize(const Frame&);
+
+ // Returns a buffer that can be passed to recv(). The buffer is deliberately
+ // not initialized.
+ ReceiveBuffer BeginReceive();
+
+ // Must be called soon after BeginReceive().
+ // |recv_size| is the number of valid bytes that have been written into the
+ // buffer previously returned by BeginReceive() (the return value of recv()).
+ // Returns false if a header > |max_capacity| is received, in which case the
+ // caller is expected to shutdown the socket and terminate the ipc.
+ bool EndReceive(size_t recv_size) PERFETTO_WARN_UNUSED_RESULT;
+
+ // Decodes and returns the next decoded frame in the buffer if any, nullptr
+ // if no further frames have been decoded.
+ std::unique_ptr<Frame> PopNextFrame();
+
+ size_t capacity() const { return capacity_; }
+ size_t size() const { return size_; }
+
+ private:
+ BufferedFrameDeserializer(const BufferedFrameDeserializer&) = delete;
+ BufferedFrameDeserializer& operator=(const BufferedFrameDeserializer&) =
+ delete;
+
+ // If a valid frame is decoded it is added to |decoded_frames_|.
+ void DecodeFrame(const char*, size_t);
+
+ char* buf() { return reinterpret_cast<char*>(buf_.Get()); }
+
+ base::PagedMemory buf_;
+ const size_t capacity_ = 0; // sizeof(|buf_|).
+
+ // THe number of bytes in |buf_| that contain valid data (as a result of
+ // EndReceive()). This is always <= |capacity_|.
+ size_t size_ = 0;
+
+ std::list<std::unique_ptr<Frame>> decoded_frames_;
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // SRC_IPC_BUFFERED_FRAME_DESERIALIZER_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/ipc/buffered_frame_deserializer.h"
+
+#include <algorithm>
+#include <cinttypes>
+#include <type_traits>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/wire_protocol.gen.h"
+
+namespace perfetto {
+namespace ipc {
+
+namespace {
+
+// The header is just the number of bytes of the Frame protobuf message.
+constexpr size_t kHeaderSize = sizeof(uint32_t);
+} // namespace
+
+BufferedFrameDeserializer::BufferedFrameDeserializer(size_t max_capacity)
+ : capacity_(max_capacity) {
+ PERFETTO_CHECK(max_capacity % base::GetSysPageSize() == 0);
+ PERFETTO_CHECK(max_capacity >= base::GetSysPageSize());
+}
+
+BufferedFrameDeserializer::~BufferedFrameDeserializer() = default;
+
+BufferedFrameDeserializer::ReceiveBuffer
+BufferedFrameDeserializer::BeginReceive() {
+ // Upon the first recv initialize the buffer to the max message size but
+ // release the physical memory for all but the first page. The kernel will
+ // automatically give us physical pages back as soon as we page-fault on them.
+ if (!buf_.IsValid()) {
+ PERFETTO_DCHECK(size_ == 0);
+ // TODO(eseckler): Don't commit all of the buffer at once on Windows.
+ buf_ = base::PagedMemory::Allocate(capacity_);
+
+ // Surely we are going to use at least the first page, but we may not need
+ // the rest for a bit.
+ const auto page_size = base::GetSysPageSize();
+ buf_.AdviseDontNeed(buf() + page_size, capacity_ - page_size);
+ }
+
+ PERFETTO_CHECK(capacity_ > size_);
+ return ReceiveBuffer{buf() + size_, capacity_ - size_};
+}
+
+bool BufferedFrameDeserializer::EndReceive(size_t recv_size) {
+ const auto page_size = base::GetSysPageSize();
+ PERFETTO_CHECK(recv_size + size_ <= capacity_);
+ size_ += recv_size;
+
+ // At this point the contents buf_ can contain:
+ // A) Only a fragment of the header (the size of the frame). E.g.,
+ // 03 00 00 (the header is 4 bytes, one is missing).
+ //
+ // B) A header and a part of the frame. E.g.,
+ // 05 00 00 00 11 22 33
+ // [ header, size=5 ] [ Partial frame ]
+ //
+ // C) One or more complete header+frame. E.g.,
+ // 05 00 00 00 11 22 33 44 55 03 00 00 00 AA BB CC
+ // [ header, size=5 ] [ Whole frame ] [ header, size=3 ] [ Whole frame ]
+ //
+ // D) Some complete header+frame(s) and a partial header or frame (C + A/B).
+ //
+ // C Is the more likely case and the one we are optimizing for. A, B, D can
+ // happen because of the streaming nature of the socket.
+ // The invariant of this function is that, when it returns, buf_ is either
+ // empty (we drained all the complete frames) or starts with the header of the
+ // next, still incomplete, frame.
+
+ size_t consumed_size = 0;
+ for (;;) {
+ if (size_ < consumed_size + kHeaderSize)
+ break; // Case A, not enough data to read even the header.
+
+ // Read the header into |payload_size|.
+ uint32_t payload_size = 0;
+ const char* rd_ptr = buf() + consumed_size;
+ memcpy(base::AssumeLittleEndian(&payload_size), rd_ptr, kHeaderSize);
+
+ // Saturate the |payload_size| to prevent overflows. The > capacity_ check
+ // below will abort the parsing.
+ size_t next_frame_size =
+ std::min(static_cast<size_t>(payload_size), capacity_);
+ next_frame_size += kHeaderSize;
+ rd_ptr += kHeaderSize;
+
+ if (size_ < consumed_size + next_frame_size) {
+ // Case B. We got the header but not the whole frame.
+ if (next_frame_size > capacity_) {
+ // The caller is expected to shut down the socket and give up at this
+ // point. If it doesn't do that and insists going on at some point it
+ // will hit the capacity check in BeginReceive().
+ PERFETTO_LOG("IPC Frame too large (size %zu)", next_frame_size);
+ return false;
+ }
+ break;
+ }
+
+ // Case C. We got at least one header and whole frame.
+ DecodeFrame(rd_ptr, payload_size);
+ consumed_size += next_frame_size;
+ }
+
+ PERFETTO_DCHECK(consumed_size <= size_);
+ if (consumed_size > 0) {
+ // Shift out the consumed data from the buffer. In the typical case (C)
+ // there is nothing to shift really, just setting size_ = 0 is enough.
+ // Shifting is only for the (unlikely) case D.
+ size_ -= consumed_size;
+ if (size_ > 0) {
+ // Case D. We consumed some frames but there is a leftover at the end of
+ // the buffer. Shift out the consumed bytes, so that on the next round
+ // |buf_| starts with the header of the next unconsumed frame.
+ const char* move_begin = buf() + consumed_size;
+ PERFETTO_CHECK(move_begin > buf());
+ PERFETTO_CHECK(move_begin + size_ <= buf() + capacity_);
+ memmove(buf(), move_begin, size_);
+ }
+ // If we just finished decoding a large frame that used more than one page,
+ // release the extra memory in the buffer. Large frames should be quite
+ // rare.
+ if (consumed_size > page_size) {
+ size_t size_rounded_up = (size_ / page_size + 1) * page_size;
+ if (size_rounded_up < capacity_) {
+ char* madvise_begin = buf() + size_rounded_up;
+ const size_t madvise_size = capacity_ - size_rounded_up;
+ PERFETTO_CHECK(madvise_begin > buf() + size_);
+ PERFETTO_CHECK(madvise_begin + madvise_size <= buf() + capacity_);
+ buf_.AdviseDontNeed(madvise_begin, madvise_size);
+ }
+ }
+ }
+ // At this point |size_| == 0 for case C, > 0 for cases A, B, D.
+ return true;
+}
+
+std::unique_ptr<Frame> BufferedFrameDeserializer::PopNextFrame() {
+ if (decoded_frames_.empty())
+ return nullptr;
+ std::unique_ptr<Frame> frame = std::move(decoded_frames_.front());
+ decoded_frames_.pop_front();
+ return frame;
+}
+
+void BufferedFrameDeserializer::DecodeFrame(const char* data, size_t size) {
+ if (size == 0)
+ return;
+ std::unique_ptr<Frame> frame(new Frame);
+ if (frame->ParseFromArray(data, size))
+ decoded_frames_.push_back(std::move(frame));
+}
+
+// static
+std::string BufferedFrameDeserializer::Serialize(const Frame& frame) {
+ std::vector<uint8_t> payload = frame.SerializeAsArray();
+ const uint32_t payload_size = static_cast<uint32_t>(payload.size());
+ std::string buf;
+ buf.resize(kHeaderSize + payload_size);
+ memcpy(&buf[0], base::AssumeLittleEndian(&payload_size), kHeaderSize);
+ memcpy(&buf[kHeaderSize], payload.data(), payload.size());
+ return buf;
+}
+
+} // namespace ipc
+} // namespace perfetto
+// gen_amalgamated begin source: src/ipc/deferred.cc
+// gen_amalgamated begin header: include/perfetto/ext/ipc/deferred.h
+// gen_amalgamated begin header: include/perfetto/ext/ipc/async_result.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_ASYNC_RESULT_H_
+#define INCLUDE_PERFETTO_EXT_IPC_ASYNC_RESULT_H_
+
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+
+namespace perfetto {
+namespace ipc {
+
+// Wraps the result of an asynchronous invocation. This is the equivalent of a
+// std::pair<unique_ptr<T>, bool> with syntactic sugar. It is used as callback
+// argument by Deferred<T>. T is a ProtoMessage subclass (i.e. generated .pb.h).
+template <typename T>
+class AsyncResult {
+ public:
+ static AsyncResult Create() {
+ return AsyncResult(std::unique_ptr<T>(new T()));
+ }
+
+ AsyncResult(std::unique_ptr<T> msg = nullptr,
+ bool has_more = false,
+ int fd = -1)
+ : msg_(std::move(msg)), has_more_(has_more), fd_(fd) {
+ static_assert(std::is_base_of<ProtoMessage, T>::value, "T->ProtoMessage");
+ }
+ AsyncResult(AsyncResult&&) noexcept = default;
+ AsyncResult& operator=(AsyncResult&&) = default;
+
+ bool success() const { return !!msg_; }
+ explicit operator bool() const { return success(); }
+
+ bool has_more() const { return has_more_; }
+ void set_has_more(bool has_more) { has_more_ = has_more; }
+
+ void set_msg(std::unique_ptr<T> msg) { msg_ = std::move(msg); }
+ T* release_msg() { return msg_.release(); }
+ T* operator->() { return msg_.get(); }
+ T& operator*() { return *msg_; }
+
+ void set_fd(int fd) { fd_ = fd; }
+ int fd() const { return fd_; }
+
+ private:
+ std::unique_ptr<T> msg_;
+ bool has_more_ = false;
+
+ // Optional. Only for messages that convey a file descriptor, for sharing
+ // memory across processes.
+ int fd_ = -1;
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_ASYNC_RESULT_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_DEFERRED_H_
+#define INCLUDE_PERFETTO_EXT_IPC_DEFERRED_H_
+
+#include <functional>
+#include <memory>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/async_result.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+
+namespace perfetto {
+namespace ipc {
+
+// This class is a wrapper for a callback handling async results.
+// The problem this is solving is the following: For each result argument of the
+// methods generated from the .proto file:
+// - The client wants to see something on which it can Bind() a callback, which
+// is invoked asynchronously once reply is received from the host.
+// - The host wants to expose something to user code that implements the IPC
+// methods to allow them to provide an asynchronous reply back to the client.
+// Eventually even more than once, for the case streaming replies.
+//
+// In both cases we want to make sure that callbacks don't get lost along the
+// way. To address this, this class will automatically reject the callbacks
+// if they are not resolved at destructor time (or the object is std::move()'d).
+//
+// The client is supposed to use this class as follows:
+// class GreeterProxy {
+// void SayHello(const HelloRequest&, Deferred<HelloReply> reply)
+// }
+// ...
+// Deferred<HelloReply> reply;
+// reply.Bind([] (AsyncResult<HelloReply> reply) {
+// std::cout << reply.success() ? reply->message : "failure";
+// });
+// host_proxy_instance.SayHello(req, std::move(reply));
+//
+// The host instead is supposed to use this as follows:
+// class GreeterImpl : public Greeter {
+// void SayHello(const HelloRequest& req, Deferred<HelloReply> reply) {
+// AsyncResult<HelloReply> reply = AsyncResult<HelloReply>::Create();
+// reply->set_greeting("Hello " + req.name)
+// reply.Resolve(std::move(reply));
+// }
+// }
+// Or for more complex cases, the deferred object can be std::move()'d outside
+// and the reply can continue asynchronously later.
+
+template <typename T>
+class Deferred;
+
+class DeferredBase {
+ public:
+ explicit DeferredBase(
+ std::function<void(AsyncResult<ProtoMessage>)> callback = nullptr);
+
+ ~DeferredBase();
+ DeferredBase(DeferredBase&&) noexcept;
+ DeferredBase& operator=(DeferredBase&&);
+ void Bind(std::function<void(AsyncResult<ProtoMessage>)> callback);
+ bool IsBound() const;
+ void Resolve(AsyncResult<ProtoMessage>);
+ void Reject();
+
+ protected:
+ template <typename T>
+ friend class Deferred;
+ void Move(DeferredBase&);
+
+ std::function<void(AsyncResult<ProtoMessage>)> callback_;
+};
+
+template <typename T> // T : ProtoMessage subclass
+class Deferred : public DeferredBase {
+ public:
+ explicit Deferred(std::function<void(AsyncResult<T>)> callback = nullptr) {
+ Bind(std::move(callback));
+ }
+
+ // This move constructor (and the similar one in DeferredBase) is meant to be
+ // called only by the autogenerated code. The caller has to guarantee that the
+ // moved-from and moved-to types match. The behavior is otherwise undefined.
+ explicit Deferred(DeferredBase&& other) {
+ callback_ = std::move(other.callback_);
+ other.callback_ = nullptr;
+ }
+
+ void Bind(std::function<void(AsyncResult<T>)> callback) {
+ if (!callback)
+ return;
+
+ // Here we need a callback adapter to downcast the callback to a generic
+ // callback that takes an AsyncResult<ProtoMessage>, so that it can be
+ // stored in the base class |callback_|.
+ auto callback_adapter = [callback](
+ AsyncResult<ProtoMessage> async_result_base) {
+ // Upcast the async_result from <ProtoMessage> -> <T : ProtoMessage>.
+ static_assert(std::is_base_of<ProtoMessage, T>::value, "T:ProtoMessage");
+ AsyncResult<T> async_result(
+ std::unique_ptr<T>(static_cast<T*>(async_result_base.release_msg())),
+ async_result_base.has_more(), async_result_base.fd());
+ callback(std::move(async_result));
+ };
+ DeferredBase::Bind(callback_adapter);
+ }
+
+ // If no more messages are expected, |callback_| is released.
+ void Resolve(AsyncResult<T> async_result) {
+ // Convert the |async_result| to the generic base one (T -> ProtoMessage).
+ AsyncResult<ProtoMessage> async_result_base(
+ std::unique_ptr<ProtoMessage>(async_result.release_msg()),
+ async_result.has_more(), async_result.fd());
+ DeferredBase::Resolve(std::move(async_result_base));
+ }
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_DEFERRED_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace ipc {
+
+DeferredBase::DeferredBase(
+ std::function<void(AsyncResult<ProtoMessage>)> callback)
+ : callback_(std::move(callback)) {}
+
+DeferredBase::~DeferredBase() {
+ if (callback_)
+ Reject();
+}
+
+// Can't just use "= default" here because the default move operator for
+// std::function doesn't necessarily swap and hence can leave a copy of the
+// bind state around, which is undesirable.
+DeferredBase::DeferredBase(DeferredBase&& other) noexcept {
+ Move(other);
+}
+
+DeferredBase& DeferredBase::operator=(DeferredBase&& other) {
+ if (callback_)
+ Reject();
+ Move(other);
+ return *this;
+}
+
+void DeferredBase::Move(DeferredBase& other) {
+ callback_ = std::move(other.callback_);
+ other.callback_ = nullptr;
+}
+
+void DeferredBase::Bind(
+ std::function<void(AsyncResult<ProtoMessage>)> callback) {
+ callback_ = std::move(callback);
+}
+
+bool DeferredBase::IsBound() const {
+ return !!callback_;
+}
+
+void DeferredBase::Resolve(AsyncResult<ProtoMessage> async_result) {
+ if (!callback_) {
+ PERFETTO_DFATAL("No callback set.");
+ return;
+ }
+ bool has_more = async_result.has_more();
+ callback_(std::move(async_result));
+ if (!has_more)
+ callback_ = nullptr;
+}
+
+// Resolves with a nullptr |msg_|, signalling failure to |callback_|.
+void DeferredBase::Reject() {
+ Resolve(AsyncResult<ProtoMessage>());
+}
+
+} // namespace ipc
+} // namespace perfetto
+// gen_amalgamated begin source: src/ipc/virtual_destructors.cc
+// gen_amalgamated begin header: include/perfetto/ext/ipc/client.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
+#define INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
+
+#include <functional>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+namespace ipc {
+class ServiceProxy;
+
+// The client-side class that talks to the host over the socket and multiplexes
+// requests coming from the various autogenerated ServiceProxy stubs.
+// This is meant to be used by the user code as follows:
+// auto client = Client::CreateInstance("socket_name", task_runner);
+// std::unique_ptr<GreeterService> svc(new GreeterService());
+// client.BindService(svc);
+// svc.OnConnect([] () {
+// svc.SayHello(..., ...);
+// });
+class Client {
+ public:
+ // struct ConnArgs is used for creating a client in 2 connection modes:
+ // 1. Connect using a socket name with the option to retry the connection on
+ // connection failure.
+ // 2. Adopt a connected socket.
+ struct ConnArgs {
+ ConnArgs(const char* sock_name, bool sock_retry)
+ : socket_name(sock_name), retry(sock_retry) {}
+ explicit ConnArgs(base::ScopedSocketHandle sock_fd)
+ : socket_fd(std::move(sock_fd)) {}
+
+ // Disallow copy. Only supports move.
+ ConnArgs(const ConnArgs& other) = delete;
+ ConnArgs(ConnArgs&& other) = default;
+
+ base::ScopedSocketHandle socket_fd;
+ const char* socket_name = nullptr;
+ bool retry = false; // Only for connecting with |socket_name|.
+ std::function<int(void)> receive_shmem_fd_cb_fuchsia;
+ };
+
+ static std::unique_ptr<Client> CreateInstance(ConnArgs, base::TaskRunner*);
+ virtual ~Client();
+
+ virtual void BindService(base::WeakPtr<ServiceProxy>) = 0;
+
+ // There is no need to call this method explicitly. Destroying the
+ // ServiceProxy instance is sufficient and will automatically unbind it. This
+ // method is exposed only for the ServiceProxy destructor.
+ virtual void UnbindService(ServiceID) = 0;
+
+ // Returns (with move semantics) the last file descriptor received on the IPC
+ // channel. No buffering is performed: if a service sends two file descriptors
+ // and the caller doesn't read them immediately, the first one will be
+ // automatically closed when the second is received (and will hit a DCHECK in
+ // debug builds).
+ virtual base::ScopedFile TakeReceivedFD() = 0;
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
+// gen_amalgamated begin header: include/perfetto/ext/ipc/host.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_HOST_H_
+#define INCLUDE_PERFETTO_EXT_IPC_HOST_H_
+
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+namespace ipc {
+
+class Service;
+
+// The host-side of the IPC layer. This class acts as a registry and request
+// dispatcher. It listen on the UnixSocket |socket_name| for incoming requests
+// (coming Client instances) and dispatches their requests to the various
+// Services exposed.
+class Host {
+ public:
+ // Creates an instance and starts listening on the given |socket_name|.
+ // Returns nullptr if listening on the socket fails.
+ static std::unique_ptr<Host> CreateInstance(const char* socket_name,
+ base::TaskRunner*);
+
+ // Like the above but takes a file descriptor to a pre-bound unix socket.
+ // Returns nullptr if listening on the socket fails.
+ static std::unique_ptr<Host> CreateInstance(base::ScopedSocketHandle,
+ base::TaskRunner*);
+
+ // Creates a Host which is not backed by a POSIX listening socket.
+ // Instead, it accepts sockets passed in via AdoptConnectedSocket_Fuchsia().
+ // See go/fuchsetto for more details.
+ static std::unique_ptr<Host> CreateInstance_Fuchsia(base::TaskRunner*);
+
+ virtual ~Host();
+
+ // Registers a new service and makes it available to remote IPC peers.
+ // All the exposed Service instances will be destroyed when destroying the
+ // Host instance if ExposeService succeeds and returns true, or immediately
+ // after the call in case of failure.
+ // Returns true if the register has been successfully registered, false in
+ // case of errors (e.g., another service with the same name is already
+ // registered).
+ virtual bool ExposeService(std::unique_ptr<Service>) = 0;
+
+ // Accepts a pre-connected socket handle and a callback used to send a
+ // shared memory FD to the remote client.
+ // The callback returns false if the FD could not be sent.
+ // Should only be used in conjunction with CreateInstance_Fuchsia().
+ virtual void AdoptConnectedSocket_Fuchsia(
+ base::ScopedSocketHandle,
+ std::function<bool(int)> send_fd_cb) = 0;
+
+ // Overrides the default send timeout for the per-connection sockets.
+ virtual void SetSocketSendTimeoutMs(uint32_t timeout_ms) = 0;
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_HOST_H_
+// gen_amalgamated begin header: include/perfetto/ext/ipc/service.h
+// gen_amalgamated begin header: include/perfetto/ext/ipc/client_info.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
+#define INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+
+namespace perfetto {
+namespace ipc {
+
+// Passed to Service(s) to identify remote clients.
+class ClientInfo {
+ public:
+ ClientInfo() = default;
+ ClientInfo(ClientID client_id,
+ uid_t uid,
+ pid_t pid,
+ base::MachineID machine_id)
+ : client_id_(client_id), uid_(uid), pid_(pid), machine_id_(machine_id) {}
+
+ bool operator==(const ClientInfo& other) const {
+ return std::tie(client_id_, uid_, pid_, machine_id_) ==
+ std::tie(other.client_id_, other.uid_, other.pid_,
+ other.machine_id_);
+ }
+ bool operator!=(const ClientInfo& other) const { return !(*this == other); }
+
+ // For map<> and other sorted containers.
+ bool operator<(const ClientInfo& other) const {
+ PERFETTO_DCHECK(client_id_ != other.client_id_ || *this == other);
+ return client_id_ < other.client_id_;
+ }
+
+ bool is_valid() const { return client_id_ != 0; }
+
+ // A monotonic counter.
+ ClientID client_id() const { return client_id_; }
+
+ // Posix User ID. Comes from the kernel, can be trusted.
+ uid_t uid() const { return uid_; }
+
+ // Posix process ID. Comes from the kernel and can be trusted.
+ int32_t pid() const { return pid_; }
+
+ // An integral ID that identifies the machine the client is on.
+ base::MachineID machine_id() const { return machine_id_; }
+
+ private:
+ ClientID client_id_ = 0;
+ // The following fields are emitted to trace packets and should be kept in
+ // sync with perfetto::ClientIdentity.
+ uid_t uid_ = kInvalidUid;
+ pid_t pid_ = base::kInvalidPid;
+ base::MachineID machine_id_ = base::kDefaultMachineID;
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_SERVICE_H_
+#define INCLUDE_PERFETTO_EXT_IPC_SERVICE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/client_info.h"
+
+namespace perfetto {
+namespace ipc {
+
+class ServiceDescriptor;
+
+// The base class for all the autogenerated host-side service interfaces.
+class Service {
+ public:
+ virtual ~Service();
+
+ // Overridden by the auto-generated class. Provides the list of methods and
+ // the protobuf (de)serialization functions for their arguments.
+ virtual const ServiceDescriptor& GetDescriptor() = 0;
+
+ // Invoked when a remote client disconnects. Use client_info() to obtain
+ // details about the client that disconnected.
+ virtual void OnClientDisconnected() {}
+
+ // Returns the ClientInfo for the current IPC request. Returns an invalid
+ // ClientInfo if called outside the scope of an IPC method.
+ const ClientInfo& client_info() {
+ PERFETTO_DCHECK(client_info_.is_valid());
+ return client_info_;
+ }
+
+ base::ScopedFile TakeReceivedFD() {
+ if (received_fd_)
+ return std::move(*received_fd_);
+ return base::ScopedFile();
+ }
+
+ bool use_shmem_emulation() { return use_shmem_emulation_; }
+
+ private:
+ friend class HostImpl;
+ ClientInfo client_info_;
+ // This is a pointer because the received fd needs to remain owned by the
+ // ClientConnection, as we will provide it to all method invocations
+ // for that client until one of them calls Service::TakeReceivedFD.
+ //
+ // Different clients might have sent different FDs so this cannot be owned
+ // here.
+ //
+ // Note that this means that there can always only be one outstanding
+ // invocation per client that supplies an FD and the client needs to
+ // wait for this one to return before calling another one.
+ base::ScopedFile* received_fd_;
+
+ // Whether the socket needs to emulate shared memory buffer. Set by HostImpl
+ // when the service is exposed.
+ bool use_shmem_emulation_ = false;
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_SERVICE_H_
+// gen_amalgamated begin header: include/perfetto/ext/ipc/service_proxy.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_SERVICE_PROXY_H_
+#define INCLUDE_PERFETTO_EXT_IPC_SERVICE_PROXY_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+
+#include <assert.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+
+namespace perfetto {
+namespace ipc {
+
+class Client;
+class ServiceDescriptor;
+
+// The base class for the client-side autogenerated stubs that forward method
+// invocations to the host. All the methods of this class are meant to be called
+// only by the autogenerated code.
+class PERFETTO_EXPORT_COMPONENT ServiceProxy {
+ public:
+ class EventListener {
+ public:
+ virtual ~EventListener();
+
+ // Called once after Client::BindService() if the ServiceProxy has been
+ // successfully bound to the host. It is possible to start sending IPC
+ // requests soon after this.
+ virtual void OnConnect() {}
+
+ // Called if the connection fails to be established or drops after having
+ // been established.
+ virtual void OnDisconnect() {}
+ };
+
+ // Guarantees that no callback will happen after this object has been
+ // destroyed. The caller has to guarantee that the |event_listener| stays
+ // alive at least as long as the ServiceProxy instance.
+ explicit ServiceProxy(EventListener*);
+ virtual ~ServiceProxy();
+
+ void InitializeBinding(base::WeakPtr<Client>,
+ ServiceID,
+ std::map<std::string, MethodID>);
+
+ // Called by the IPC methods in the autogenerated classes.
+ void BeginInvoke(const std::string& method_name,
+ const ProtoMessage& request,
+ DeferredBase reply,
+ int fd = -1);
+
+ // Called by ClientImpl.
+ // |reply_args| == nullptr means request failure.
+ void EndInvoke(RequestID,
+ std::unique_ptr<ProtoMessage> reply_arg,
+ bool has_more);
+
+ // Called by ClientImpl.
+ void OnConnect(bool success);
+ void OnDisconnect();
+ bool connected() const { return service_id_ != 0; }
+
+ base::WeakPtr<ServiceProxy> GetWeakPtr() const;
+
+ // Implemented by the autogenerated class.
+ virtual const ServiceDescriptor& GetDescriptor() = 0;
+
+ private:
+ base::WeakPtr<Client> client_;
+ ServiceID service_id_ = 0;
+ std::map<std::string, MethodID> remote_method_ids_;
+ std::map<RequestID, DeferredBase> pending_callbacks_;
+ EventListener* const event_listener_;
+ base::WeakPtrFactory<ServiceProxy> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_SERVICE_PROXY_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/client.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/host.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+
+// This translation unit contains the definitions for the destructor of pure
+// virtual interfaces for the current build target. The alternative would be
+// introducing a one-liner .cc file for each pure virtual interface, which is
+// overkill. This is for compliance with -Wweak-vtables.
+
+namespace perfetto {
+namespace ipc {
+
+Client::~Client() = default;
+Host::~Host() = default;
+Service::~Service() = default;
+ServiceProxy::EventListener::~EventListener() = default;
+
+} // namespace ipc
+} // namespace perfetto
+// gen_amalgamated begin source: src/ipc/client_impl.cc
+// gen_amalgamated begin header: src/ipc/client_impl.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_IPC_CLIENT_IMPL_H_
+#define SRC_IPC_CLIENT_IMPL_H_
+
+#include <list>
+#include <map>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/client.h"
+// gen_amalgamated expanded: #include "src/ipc/buffered_frame_deserializer.h"
+
+namespace perfetto {
+
+namespace protos {
+namespace gen {
+class IPCFrame_BindServiceReply;
+class IPCFrame_InvokeMethodReply;
+} // namespace gen
+} // namespace protos
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+namespace ipc {
+
+class ServiceDescriptor;
+
+class ClientImpl : public Client, public base::UnixSocket::EventListener {
+ public:
+ ClientImpl(ConnArgs, base::TaskRunner*);
+ ~ClientImpl() override;
+
+ // Client implementation.
+ void BindService(base::WeakPtr<ServiceProxy>) override;
+ void UnbindService(ServiceID) override;
+ base::ScopedFile TakeReceivedFD() override;
+
+ // base::UnixSocket::EventListener implementation.
+ void OnConnect(base::UnixSocket*, bool connected) override;
+ void OnDisconnect(base::UnixSocket*) override;
+ void OnDataAvailable(base::UnixSocket*) override;
+
+ RequestID BeginInvoke(ServiceID,
+ const std::string& method_name,
+ MethodID remote_method_id,
+ const ProtoMessage& method_args,
+ bool drop_reply,
+ base::WeakPtr<ServiceProxy>,
+ int fd = -1);
+
+ base::UnixSocket* GetUnixSocketForTesting() { return sock_.get(); }
+
+ private:
+ struct QueuedRequest {
+ QueuedRequest();
+ int type = 0; // From Frame::msg_case(), see wire_protocol.proto.
+ RequestID request_id = 0;
+ base::WeakPtr<ServiceProxy> service_proxy;
+
+ // Only for type == kMsgInvokeMethod.
+ std::string method_name;
+ };
+
+ ClientImpl(const ClientImpl&) = delete;
+ ClientImpl& operator=(const ClientImpl&) = delete;
+
+ void TryConnect();
+ bool SendFrame(const Frame&, int fd = -1);
+ void OnFrameReceived(const Frame&);
+ void OnBindServiceReply(QueuedRequest,
+ const protos::gen::IPCFrame_BindServiceReply&);
+ void OnInvokeMethodReply(QueuedRequest,
+ const protos::gen::IPCFrame_InvokeMethodReply&);
+
+ bool invoking_method_reply_ = false;
+ const char* socket_name_ = nullptr;
+ bool socket_retry_ = false;
+ uint32_t socket_backoff_ms_ = 0;
+ std::unique_ptr<base::UnixSocket> sock_;
+ base::TaskRunner* const task_runner_;
+ RequestID last_request_id_ = 0;
+ BufferedFrameDeserializer frame_deserializer_;
+ base::ScopedFile received_fd_;
+ std::map<RequestID, QueuedRequest> queued_requests_;
+ std::map<ServiceID, base::WeakPtr<ServiceProxy>> service_bindings_;
+
+ // Queue of calls to BindService() that happened before the socket connected.
+ std::list<base::WeakPtr<ServiceProxy>> queued_bindings_;
+
+ base::WeakPtrFactory<Client> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // SRC_IPC_CLIENT_IMPL_H_
+// gen_amalgamated begin header: include/perfetto/ext/ipc/service_descriptor.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_SERVICE_DESCRIPTOR_H_
+#define INCLUDE_PERFETTO_EXT_IPC_SERVICE_DESCRIPTOR_H_
+
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+
+namespace perfetto {
+namespace ipc {
+
+class Service;
+
+// This is a pure data structure which holds factory methods and strings for the
+// services and their methods that get generated in the .h/.cc files.
+// Each autogenerated class has a GetDescriptor() method that returns one
+// instance of these and allows both client and hosts to map service and method
+// names to IDs and provide function pointers to the protobuf decoder fuctions.
+class ServiceDescriptor {
+ public:
+ struct Method {
+ const char* name;
+
+ // DecoderFunc is pointer to a function that takes a string in input
+ // containing protobuf encoded data and returns a decoded protobuf message.
+ using DecoderFunc = std::unique_ptr<ProtoMessage> (*)(const std::string&);
+
+ // Function pointer to decode the request argument of the method.
+ DecoderFunc request_proto_decoder;
+
+ // Function pointer to decoded the reply argument of the method.
+ DecoderFunc reply_proto_decoder;
+
+ // Function pointer that dispatches the generic request to the corresponding
+ // method implementation.
+ using InvokerFunc = void (*)(Service*,
+ const ProtoMessage& /* request_args */,
+ DeferredBase /* deferred_reply */);
+ InvokerFunc invoker;
+ };
+
+ const char* service_name = nullptr;
+
+ // Note that methods order is not stable. Client and Host might have different
+ // method indexes, depending on their versions. The Client can't just rely
+ // on the indexes and has to keep a [string -> remote index] translation map.
+ std::vector<Method> methods;
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_SERVICE_DESCRIPTOR_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/ipc/client_impl.h"
+
+#include <fcntl.h>
+
+#include <cinttypes>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/wire_protocol.gen.h"
+
+// TODO(primiano): Add ThreadChecker everywhere.
+
+// TODO(primiano): Add timeouts.
+
+namespace perfetto {
+namespace ipc {
+
+namespace {
+constexpr base::SockFamily kClientSockFamily =
+ kUseTCPSocket ? base::SockFamily::kInet : base::SockFamily::kUnix;
+} // namespace
+
+// static
+std::unique_ptr<Client> Client::CreateInstance(ConnArgs conn_args,
+ base::TaskRunner* task_runner) {
+ std::unique_ptr<Client> client(
+ new ClientImpl(std::move(conn_args), task_runner));
+ return client;
+}
+
+ClientImpl::ClientImpl(ConnArgs conn_args, base::TaskRunner* task_runner)
+ : socket_name_(conn_args.socket_name),
+ socket_retry_(conn_args.retry),
+ task_runner_(task_runner),
+ weak_ptr_factory_(this) {
+ if (conn_args.socket_fd) {
+ // Create the client using a connected socket. This code path will never hit
+ // OnConnect().
+ sock_ = base::UnixSocket::AdoptConnected(
+ std::move(conn_args.socket_fd), this, task_runner_, kClientSockFamily,
+ base::SockType::kStream, base::SockPeerCredMode::kIgnore);
+ } else {
+ // Connect using the socket name.
+ TryConnect();
+ }
+}
+
+ClientImpl::~ClientImpl() {
+ // Ensure we are not destroyed in the middle of invoking a reply.
+ PERFETTO_DCHECK(!invoking_method_reply_);
+ OnDisconnect(
+ nullptr); // The base::UnixSocket* ptr is not used in OnDisconnect().
+}
+
+void ClientImpl::TryConnect() {
+ PERFETTO_DCHECK(socket_name_);
+ sock_ = base::UnixSocket::Connect(
+ socket_name_, this, task_runner_, base::GetSockFamily(socket_name_),
+ base::SockType::kStream, base::SockPeerCredMode::kIgnore);
+}
+
+void ClientImpl::BindService(base::WeakPtr<ServiceProxy> service_proxy) {
+ if (!service_proxy)
+ return;
+ if (!sock_->is_connected()) {
+ queued_bindings_.emplace_back(service_proxy);
+ return;
+ }
+ RequestID request_id = ++last_request_id_;
+ Frame frame;
+ frame.set_request_id(request_id);
+ Frame::BindService* req = frame.mutable_msg_bind_service();
+ const char* const service_name = service_proxy->GetDescriptor().service_name;
+ req->set_service_name(service_name);
+ if (!SendFrame(frame)) {
+ PERFETTO_DLOG("BindService(%s) failed", service_name);
+ return service_proxy->OnConnect(false /* success */);
+ }
+ QueuedRequest qr;
+ qr.type = Frame::kMsgBindServiceFieldNumber;
+ qr.request_id = request_id;
+ qr.service_proxy = service_proxy;
+ queued_requests_.emplace(request_id, std::move(qr));
+}
+
+void ClientImpl::UnbindService(ServiceID service_id) {
+ service_bindings_.erase(service_id);
+}
+
+RequestID ClientImpl::BeginInvoke(ServiceID service_id,
+ const std::string& method_name,
+ MethodID remote_method_id,
+ const ProtoMessage& method_args,
+ bool drop_reply,
+ base::WeakPtr<ServiceProxy> service_proxy,
+ int fd) {
+ RequestID request_id = ++last_request_id_;
+ Frame frame;
+ frame.set_request_id(request_id);
+ Frame::InvokeMethod* req = frame.mutable_msg_invoke_method();
+ req->set_service_id(service_id);
+ req->set_method_id(remote_method_id);
+ req->set_drop_reply(drop_reply);
+ req->set_args_proto(method_args.SerializeAsString());
+ if (!SendFrame(frame, fd)) {
+ PERFETTO_DLOG("BeginInvoke() failed while sending the frame");
+ return 0;
+ }
+ if (drop_reply)
+ return 0;
+ QueuedRequest qr;
+ qr.type = Frame::kMsgInvokeMethodFieldNumber;
+ qr.request_id = request_id;
+ qr.method_name = method_name;
+ qr.service_proxy = std::move(service_proxy);
+ queued_requests_.emplace(request_id, std::move(qr));
+ return request_id;
+}
+
+bool ClientImpl::SendFrame(const Frame& frame, int fd) {
+ // Serialize the frame into protobuf, add the size header, and send it.
+ std::string buf = BufferedFrameDeserializer::Serialize(frame);
+
+ // TODO(primiano): this should do non-blocking I/O. But then what if the
+ // socket buffer is full? We might want to either drop the request or throttle
+ // the send and PostTask the reply later? Right now we are making Send()
+ // blocking as a workaround. Propagate bakpressure to the caller instead.
+ bool res = sock_->Send(buf.data(), buf.size(), fd);
+ PERFETTO_CHECK(res || !sock_->is_connected());
+ return res;
+}
+
+void ClientImpl::OnConnect(base::UnixSocket*, bool connected) {
+ if (!connected && socket_retry_) {
+ socket_backoff_ms_ =
+ (socket_backoff_ms_ < 10000) ? socket_backoff_ms_ + 1000 : 30000;
+ PERFETTO_DLOG(
+ "Connection to traced's UNIX socket failed, retrying in %u seconds",
+ socket_backoff_ms_ / 1000);
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ task_runner_->PostDelayedTask(
+ [weak_this] {
+ if (weak_this)
+ static_cast<ClientImpl&>(*weak_this).TryConnect();
+ },
+ socket_backoff_ms_);
+ return;
+ }
+
+ // Drain the BindService() calls that were queued before establishing the
+ // connection with the host. Note that if we got disconnected, the call to
+ // OnConnect below might delete |this|, so move everything on the stack first.
+ auto queued_bindings = std::move(queued_bindings_);
+ queued_bindings_.clear();
+ for (base::WeakPtr<ServiceProxy>& service_proxy : queued_bindings) {
+ if (connected) {
+ BindService(service_proxy);
+ } else if (service_proxy) {
+ service_proxy->OnConnect(false /* success */);
+ }
+ }
+ // Don't access |this| below here.
+}
+
+void ClientImpl::OnDisconnect(base::UnixSocket*) {
+ for (const auto& it : service_bindings_) {
+ base::WeakPtr<ServiceProxy> service_proxy = it.second;
+ task_runner_->PostTask([service_proxy] {
+ if (service_proxy)
+ service_proxy->OnDisconnect();
+ });
+ }
+ for (const auto& it : queued_requests_) {
+ const QueuedRequest& queued_request = it.second;
+ if (queued_request.type != Frame::kMsgBindServiceFieldNumber) {
+ continue;
+ }
+ base::WeakPtr<ServiceProxy> service_proxy = queued_request.service_proxy;
+ task_runner_->PostTask([service_proxy] {
+ if (service_proxy)
+ service_proxy->OnConnect(false);
+ });
+ }
+ service_bindings_.clear();
+ queued_bindings_.clear();
+}
+
+void ClientImpl::OnDataAvailable(base::UnixSocket*) {
+ size_t rsize;
+ do {
+ auto buf = frame_deserializer_.BeginReceive();
+ base::ScopedFile fd;
+ rsize = sock_->Receive(buf.data, buf.size, &fd);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ PERFETTO_DCHECK(!fd);
+#else
+ if (fd) {
+ PERFETTO_DCHECK(!received_fd_);
+ int res = fcntl(*fd, F_SETFD, FD_CLOEXEC);
+ PERFETTO_DCHECK(res == 0);
+ received_fd_ = std::move(fd);
+ }
+#endif
+ if (!frame_deserializer_.EndReceive(rsize)) {
+ // The endpoint tried to send a frame that is way too large.
+ return sock_->Shutdown(true); // In turn will trigger an OnDisconnect().
+ // TODO(fmayer): check this.
+ }
+ } while (rsize > 0);
+
+ while (std::unique_ptr<Frame> frame = frame_deserializer_.PopNextFrame())
+ OnFrameReceived(*frame);
+}
+
+void ClientImpl::OnFrameReceived(const Frame& frame) {
+ auto queued_requests_it = queued_requests_.find(frame.request_id());
+ if (queued_requests_it == queued_requests_.end()) {
+ PERFETTO_DLOG("OnFrameReceived(): got invalid request_id=%" PRIu64,
+ static_cast<uint64_t>(frame.request_id()));
+ return;
+ }
+ QueuedRequest req = std::move(queued_requests_it->second);
+ queued_requests_.erase(queued_requests_it);
+
+ if (req.type == Frame::kMsgBindServiceFieldNumber &&
+ frame.has_msg_bind_service_reply()) {
+ return OnBindServiceReply(std::move(req), frame.msg_bind_service_reply());
+ }
+ if (req.type == Frame::kMsgInvokeMethodFieldNumber &&
+ frame.has_msg_invoke_method_reply()) {
+ return OnInvokeMethodReply(std::move(req), frame.msg_invoke_method_reply());
+ }
+ if (frame.has_msg_request_error()) {
+ PERFETTO_DLOG("Host error: %s", frame.msg_request_error().error().c_str());
+ return;
+ }
+
+ PERFETTO_DLOG(
+ "OnFrameReceived() request type=%d, received unknown frame in reply to "
+ "request_id=%" PRIu64,
+ req.type, static_cast<uint64_t>(frame.request_id()));
+}
+
+void ClientImpl::OnBindServiceReply(QueuedRequest req,
+ const Frame::BindServiceReply& reply) {
+ base::WeakPtr<ServiceProxy>& service_proxy = req.service_proxy;
+ if (!service_proxy)
+ return;
+ const char* svc_name = service_proxy->GetDescriptor().service_name;
+ if (!reply.success()) {
+ PERFETTO_DLOG("BindService(): unknown service_name=\"%s\"", svc_name);
+ return service_proxy->OnConnect(false /* success */);
+ }
+
+ auto prev_service = service_bindings_.find(reply.service_id());
+ if (prev_service != service_bindings_.end() && prev_service->second.get()) {
+ PERFETTO_DLOG(
+ "BindService(): Trying to bind service \"%s\" but another service "
+ "named \"%s\" is already bound with the same ID.",
+ svc_name, prev_service->second->GetDescriptor().service_name);
+ return service_proxy->OnConnect(false /* success */);
+ }
+
+ // Build the method [name] -> [remote_id] map.
+ std::map<std::string, MethodID> methods;
+ for (const auto& method : reply.methods()) {
+ if (method.name().empty() || method.id() <= 0) {
+ PERFETTO_DLOG("OnBindServiceReply(): invalid method \"%s\" -> %" PRIu64,
+ method.name().c_str(), static_cast<uint64_t>(method.id()));
+ continue;
+ }
+ methods[method.name()] = method.id();
+ }
+ service_proxy->InitializeBinding(weak_ptr_factory_.GetWeakPtr(),
+ reply.service_id(), std::move(methods));
+ service_bindings_[reply.service_id()] = service_proxy;
+ service_proxy->OnConnect(true /* success */);
+}
+
+void ClientImpl::OnInvokeMethodReply(QueuedRequest req,
+ const Frame::InvokeMethodReply& reply) {
+ base::WeakPtr<ServiceProxy> service_proxy = req.service_proxy;
+ if (!service_proxy)
+ return;
+ std::unique_ptr<ProtoMessage> decoded_reply;
+ if (reply.success()) {
+ // If this becomes a hotspot, optimize by maintaining a dedicated hashtable.
+ for (const auto& method : service_proxy->GetDescriptor().methods) {
+ if (req.method_name == method.name) {
+ decoded_reply = method.reply_proto_decoder(reply.reply_proto());
+ break;
+ }
+ }
+ }
+ const RequestID request_id = req.request_id;
+ invoking_method_reply_ = true;
+ service_proxy->EndInvoke(request_id, std::move(decoded_reply),
+ reply.has_more());
+ invoking_method_reply_ = false;
+
+ // If this is a streaming method and future replies will be resolved, put back
+ // the |req| with the callback into the set of active requests.
+ if (reply.has_more())
+ queued_requests_.emplace(request_id, std::move(req));
+}
+
+ClientImpl::QueuedRequest::QueuedRequest() = default;
+
+base::ScopedFile ClientImpl::TakeReceivedFD() {
+ return std::move(received_fd_);
+}
+
+} // namespace ipc
+} // namespace perfetto
+// gen_amalgamated begin source: src/ipc/service_proxy.cc
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_descriptor.h"
+// gen_amalgamated expanded: #include "src/ipc/client_impl.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/wire_protocol.gen.h"
+
+namespace perfetto {
+namespace ipc {
+
+ServiceProxy::ServiceProxy(EventListener* event_listener)
+ : event_listener_(event_listener), weak_ptr_factory_(this) {}
+
+ServiceProxy::~ServiceProxy() {
+ if (client_ && connected())
+ client_->UnbindService(service_id_);
+}
+
+void ServiceProxy::InitializeBinding(
+ base::WeakPtr<Client> client,
+ ServiceID service_id,
+ std::map<std::string, MethodID> remote_method_ids) {
+ client_ = std::move(client);
+ service_id_ = service_id;
+ remote_method_ids_ = std::move(remote_method_ids);
+}
+
+void ServiceProxy::BeginInvoke(const std::string& method_name,
+ const ProtoMessage& request,
+ DeferredBase reply,
+ int fd) {
+ // |reply| will auto-resolve if it gets out of scope early.
+ if (!connected()) {
+ PERFETTO_DFATAL("Not connected.");
+ return;
+ }
+ if (!client_)
+ return; // The Client object has been destroyed in the meantime.
+
+ auto remote_method_it = remote_method_ids_.find(method_name);
+ RequestID request_id = 0;
+ const bool drop_reply = !reply.IsBound();
+ if (remote_method_it != remote_method_ids_.end()) {
+ request_id =
+ static_cast<ClientImpl*>(client_.get())
+ ->BeginInvoke(service_id_, method_name, remote_method_it->second,
+ request, drop_reply, weak_ptr_factory_.GetWeakPtr(),
+ fd);
+ } else {
+ PERFETTO_DLOG("Cannot find method \"%s\" on the host", method_name.c_str());
+ }
+
+ // When passing |drop_reply| == true, the returned |request_id| should be 0.
+ PERFETTO_DCHECK(!drop_reply || !request_id);
+
+ if (!request_id)
+ return;
+ PERFETTO_DCHECK(pending_callbacks_.count(request_id) == 0);
+ pending_callbacks_.emplace(request_id, std::move(reply));
+}
+
+void ServiceProxy::EndInvoke(RequestID request_id,
+ std::unique_ptr<ProtoMessage> result,
+ bool has_more) {
+ auto callback_it = pending_callbacks_.find(request_id);
+ if (callback_it == pending_callbacks_.end()) {
+ // Either we are getting a reply for a method we never invoked, or we are
+ // getting a reply to a method marked drop_reply (that has been invoked
+ // without binding any callback in the Defererd response object).
+ PERFETTO_DFATAL("Unexpected reply received.");
+ return;
+ }
+ DeferredBase& reply_callback = callback_it->second;
+ AsyncResult<ProtoMessage> reply(std::move(result), has_more);
+ reply_callback.Resolve(std::move(reply));
+ if (!has_more)
+ pending_callbacks_.erase(callback_it);
+}
+
+void ServiceProxy::OnConnect(bool success) {
+ if (success) {
+ PERFETTO_DCHECK(service_id_);
+ return event_listener_->OnConnect();
+ }
+ return event_listener_->OnDisconnect();
+}
+
+void ServiceProxy::OnDisconnect() {
+ pending_callbacks_.clear(); // Will Reject() all the pending callbacks.
+ event_listener_->OnDisconnect();
+}
+
+base::WeakPtr<ServiceProxy> ServiceProxy::GetWeakPtr() const {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+} // namespace ipc
+} // namespace perfetto
+// gen_amalgamated begin source: src/ipc/host_impl.cc
+// gen_amalgamated begin header: src/ipc/host_impl.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_IPC_HOST_IMPL_H_
+#define SRC_IPC_HOST_IMPL_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/host.h"
+// gen_amalgamated expanded: #include "src/ipc/buffered_frame_deserializer.h"
+
+namespace perfetto {
+namespace ipc {
+
+constexpr uint32_t kDefaultIpcTxTimeoutMs = 10000;
+
+class HostImpl : public Host, public base::UnixSocket::EventListener {
+ public:
+ HostImpl(const char* socket_name, base::TaskRunner*);
+ HostImpl(base::ScopedSocketHandle, base::TaskRunner*);
+ HostImpl(base::TaskRunner* task_runner);
+ ~HostImpl() override;
+
+ // Host implementation.
+ bool ExposeService(std::unique_ptr<Service>) override;
+ void AdoptConnectedSocket_Fuchsia(
+ base::ScopedSocketHandle,
+ std::function<bool(int)> send_fd_cb) override;
+ void SetSocketSendTimeoutMs(uint32_t timeout_ms) override;
+
+ // base::UnixSocket::EventListener implementation.
+ void OnNewIncomingConnection(base::UnixSocket*,
+ std::unique_ptr<base::UnixSocket>) override;
+ void OnDisconnect(base::UnixSocket*) override;
+ void OnDataAvailable(base::UnixSocket*) override;
+
+ const base::UnixSocket* sock() const { return sock_.get(); }
+
+ private:
+ // Owns the per-client receive buffer (BufferedFrameDeserializer).
+ struct ClientConnection {
+ ~ClientConnection();
+ ClientID id;
+ std::unique_ptr<base::UnixSocket> sock;
+ BufferedFrameDeserializer frame_deserializer;
+ base::ScopedFile received_fd;
+ std::function<bool(int)> send_fd_cb_fuchsia;
+ // Peer identity set using IPCFrame sent by the client. These 3 fields
+ // should be used only for non-AF_UNIX connections AF_UNIX connections
+ // should only rely on the peer identity obtained from the socket.
+ uid_t uid_override = base::kInvalidUid;
+ pid_t pid_override = base::kInvalidPid;
+
+ // |machine_id| is mapped from machine_id_hint (or socket hostname if
+ // |the client doesn't support machine_id_hint).
+ base::MachineID machine_id = base::kDefaultMachineID;
+
+ pid_t GetLinuxPeerPid() const;
+ uid_t GetPosixPeerUid() const;
+ base::MachineID GetMachineID() const { return machine_id; }
+ };
+ struct ExposedService {
+ ExposedService(ServiceID, const std::string&, std::unique_ptr<Service>);
+ ~ExposedService();
+ ExposedService(ExposedService&&) noexcept;
+ ExposedService& operator=(ExposedService&&);
+
+ ServiceID id;
+ std::string name;
+ std::unique_ptr<Service> instance;
+ };
+
+ HostImpl(const HostImpl&) = delete;
+ HostImpl& operator=(const HostImpl&) = delete;
+
+ bool Initialize(const char* socket_name);
+ void OnReceivedFrame(ClientConnection*, const Frame&);
+ void OnBindService(ClientConnection*, const Frame&);
+ void OnInvokeMethod(ClientConnection*, const Frame&);
+ void OnSetPeerIdentity(ClientConnection*, const Frame&);
+
+ void ReplyToMethodInvocation(ClientID, RequestID, AsyncResult<ProtoMessage>);
+ const ExposedService* GetServiceByName(const std::string&);
+
+ static void SendFrame(ClientConnection*, const Frame&, int fd = -1);
+
+ base::TaskRunner* const task_runner_;
+ std::map<ServiceID, ExposedService> services_;
+ std::unique_ptr<base::UnixSocket> sock_; // The listening socket.
+ std::map<ClientID, std::unique_ptr<ClientConnection>> clients_;
+ std::map<base::UnixSocket*, ClientConnection*> clients_by_socket_;
+ ServiceID last_service_id_ = 0;
+ ClientID last_client_id_ = 0;
+ uint32_t socket_tx_timeout_ms_ = kDefaultIpcTxTimeoutMs;
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+ base::WeakPtrFactory<HostImpl> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace ipc
+} // namespace perfetto
+
+#endif // SRC_IPC_HOST_IMPL_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/ipc/host_impl.h"
+
+#include <algorithm>
+#include <cinttypes>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/crash_keys.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_descriptor.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/wire_protocol.gen.h"
+
+// TODO(primiano): put limits on #connections/uid and req. queue (b/69093705).
+
+namespace perfetto {
+namespace ipc {
+
+namespace {
+
+constexpr base::SockFamily kHostSockFamily =
+ kUseTCPSocket ? base::SockFamily::kInet : base::SockFamily::kUnix;
+
+base::CrashKey g_crash_key_uid("ipc_uid");
+
+base::MachineID GenerateMachineID(base::UnixSocket* sock,
+ const std::string& machine_id_hint) {
+ // The special value of base::kDefaultMachineID is reserved for local
+ // producers.
+ if (!sock->is_connected() || sock->family() == base::SockFamily::kUnix)
+ return base::kDefaultMachineID;
+
+ base::Hasher hasher;
+ // Use the hint from the client, or fallback to hostname if the client
+ // doesn't provide a hint.
+ if (!machine_id_hint.empty()) {
+ hasher.Update(machine_id_hint);
+ } else {
+ // Use the socket address without the port number part as the hint.
+ auto host_id = sock->GetSockAddr();
+ auto pos = std::string::npos;
+ switch (sock->family()) {
+ case base::SockFamily::kInet:
+ PERFETTO_FALLTHROUGH;
+ case base::SockFamily::kInet6:
+ PERFETTO_FALLTHROUGH;
+ case base::SockFamily::kVsock:
+ pos = host_id.rfind(":");
+ if (pos != std::string::npos)
+ host_id.resize(pos);
+ break;
+ case base::SockFamily::kUnspec:
+ PERFETTO_FALLTHROUGH;
+ case base::SockFamily::kUnix:
+ PERFETTO_DFATAL("Should be unreachable.");
+ return base::kDefaultMachineID;
+ }
+ hasher.Update(host_id);
+ }
+
+ // Take the lower 32-bit from the hash.
+ uint32_t digest = static_cast<uint32_t>(hasher.digest());
+ // Avoid the extremely unlikely case that the hasher digest happens to be 0.
+ return digest == base::kDefaultMachineID ? 1 : digest;
+}
+} // namespace
+
+uid_t HostImpl::ClientConnection::GetPosixPeerUid() const {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ if (sock->family() == base::SockFamily::kUnix)
+ return sock->peer_uid_posix();
+#endif
+
+ // For non-unix sockets, check if the UID is set in OnSetPeerIdentity().
+ if (uid_override != base::kInvalidUid)
+ return uid_override;
+ // Must be != kInvalidUid or the PacketValidator will fail.
+ return 0;
+}
+
+pid_t HostImpl::ClientConnection::GetLinuxPeerPid() const {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ if (sock->family() == base::SockFamily::kUnix)
+ return sock->peer_pid_linux();
+#endif
+
+ // For non-unix sockets, return the PID set in OnSetPeerIdentity().
+ return pid_override;
+}
+
+// static
+std::unique_ptr<Host> Host::CreateInstance(const char* socket_name,
+ base::TaskRunner* task_runner) {
+ std::unique_ptr<HostImpl> host(new HostImpl(socket_name, task_runner));
+ if (!host->sock() || !host->sock()->is_listening())
+ return nullptr;
+ return std::unique_ptr<Host>(std::move(host));
+}
+
+// static
+std::unique_ptr<Host> Host::CreateInstance(base::ScopedSocketHandle socket_fd,
+ base::TaskRunner* task_runner) {
+ std::unique_ptr<HostImpl> host(
+ new HostImpl(std::move(socket_fd), task_runner));
+ if (!host->sock() || !host->sock()->is_listening())
+ return nullptr;
+ return std::unique_ptr<Host>(std::move(host));
+}
+
+// static
+std::unique_ptr<Host> Host::CreateInstance_Fuchsia(
+ base::TaskRunner* task_runner) {
+ return std::unique_ptr<HostImpl>(new HostImpl(task_runner));
+}
+
+HostImpl::HostImpl(base::ScopedSocketHandle socket_fd,
+ base::TaskRunner* task_runner)
+ : task_runner_(task_runner), weak_ptr_factory_(this) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ sock_ = base::UnixSocket::Listen(std::move(socket_fd), this, task_runner_,
+ kHostSockFamily, base::SockType::kStream);
+}
+
+HostImpl::HostImpl(const char* socket_name, base::TaskRunner* task_runner)
+ : task_runner_(task_runner), weak_ptr_factory_(this) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ sock_ = base::UnixSocket::Listen(socket_name, this, task_runner_,
+ base::GetSockFamily(socket_name),
+ base::SockType::kStream);
+ if (!sock_) {
+ PERFETTO_PLOG("Failed to create %s", socket_name);
+ }
+}
+
+HostImpl::HostImpl(base::TaskRunner* task_runner)
+ : task_runner_(task_runner), weak_ptr_factory_(this) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+}
+
+HostImpl::~HostImpl() = default;
+
+bool HostImpl::ExposeService(std::unique_ptr<Service> service) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ const std::string& service_name = service->GetDescriptor().service_name;
+ if (GetServiceByName(service_name)) {
+ PERFETTO_DLOG("Duplicate ExposeService(): %s", service_name.c_str());
+ return false;
+ }
+ service->use_shmem_emulation_ =
+ sock() && !base::SockShmemSupported(sock()->family());
+ ServiceID sid = ++last_service_id_;
+ ExposedService exposed_service(sid, service_name, std::move(service));
+ services_.emplace(sid, std::move(exposed_service));
+ return true;
+}
+
+void HostImpl::AdoptConnectedSocket_Fuchsia(
+ base::ScopedSocketHandle connected_socket,
+ std::function<bool(int)> send_fd_cb) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DCHECK(connected_socket);
+ // Should not be used in conjunction with listen sockets.
+ PERFETTO_DCHECK(!sock_);
+
+ auto unix_socket = base::UnixSocket::AdoptConnected(
+ std::move(connected_socket), this, task_runner_, kHostSockFamily,
+ base::SockType::kStream);
+
+ auto* unix_socket_ptr = unix_socket.get();
+ OnNewIncomingConnection(nullptr, std::move(unix_socket));
+ ClientConnection* client_connection = clients_by_socket_[unix_socket_ptr];
+ client_connection->send_fd_cb_fuchsia = std::move(send_fd_cb);
+ PERFETTO_DCHECK(client_connection->send_fd_cb_fuchsia);
+}
+
+void HostImpl::SetSocketSendTimeoutMs(uint32_t timeout_ms) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ // Should be less than the watchdog period (30s).
+ socket_tx_timeout_ms_ = timeout_ms;
+}
+
+void HostImpl::OnNewIncomingConnection(
+ base::UnixSocket*,
+ std::unique_ptr<base::UnixSocket> new_conn) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ std::unique_ptr<ClientConnection> client(new ClientConnection());
+ ClientID client_id = ++last_client_id_;
+ clients_by_socket_[new_conn.get()] = client.get();
+ client->id = client_id;
+ client->sock = std::move(new_conn);
+ client->sock->SetTxTimeout(socket_tx_timeout_ms_);
+ clients_[client_id] = std::move(client);
+}
+
+void HostImpl::OnDataAvailable(base::UnixSocket* sock) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto it = clients_by_socket_.find(sock);
+ if (it == clients_by_socket_.end())
+ return;
+ ClientConnection* client = it->second;
+ BufferedFrameDeserializer& frame_deserializer = client->frame_deserializer;
+
+ auto peer_uid = client->GetPosixPeerUid();
+ auto scoped_key = g_crash_key_uid.SetScoped(static_cast<int64_t>(peer_uid));
+
+ size_t rsize;
+ do {
+ auto buf = frame_deserializer.BeginReceive();
+ base::ScopedFile fd;
+ rsize = client->sock->Receive(buf.data, buf.size, &fd);
+ if (fd) {
+ PERFETTO_DCHECK(!client->received_fd);
+ client->received_fd = std::move(fd);
+ }
+ if (!frame_deserializer.EndReceive(rsize))
+ return OnDisconnect(client->sock.get());
+ } while (rsize > 0);
+
+ for (;;) {
+ std::unique_ptr<Frame> frame = frame_deserializer.PopNextFrame();
+ if (!frame)
+ break;
+ OnReceivedFrame(client, *frame);
+ }
+}
+
+void HostImpl::OnReceivedFrame(ClientConnection* client,
+ const Frame& req_frame) {
+ if (req_frame.has_msg_bind_service())
+ return OnBindService(client, req_frame);
+ if (req_frame.has_msg_invoke_method())
+ return OnInvokeMethod(client, req_frame);
+ if (req_frame.has_set_peer_identity())
+ return OnSetPeerIdentity(client, req_frame);
+
+ PERFETTO_DLOG("Received invalid RPC frame from client %" PRIu64, client->id);
+ Frame reply_frame;
+ reply_frame.set_request_id(req_frame.request_id());
+ reply_frame.mutable_msg_request_error()->set_error("unknown request");
+ SendFrame(client, reply_frame);
+}
+
+void HostImpl::OnBindService(ClientConnection* client, const Frame& req_frame) {
+ // Binding a service doesn't do anything major. It just returns back the
+ // service id and its method map.
+ const Frame::BindService& req = req_frame.msg_bind_service();
+ Frame reply_frame;
+ reply_frame.set_request_id(req_frame.request_id());
+ auto* reply = reply_frame.mutable_msg_bind_service_reply();
+ const ExposedService* service = GetServiceByName(req.service_name());
+ if (service) {
+ reply->set_success(true);
+ reply->set_service_id(service->id);
+ uint32_t method_id = 1; // method ids start at index 1.
+ for (const auto& desc_method : service->instance->GetDescriptor().methods) {
+ Frame::BindServiceReply::MethodInfo* method_info = reply->add_methods();
+ method_info->set_name(desc_method.name);
+ method_info->set_id(method_id++);
+ }
+ }
+ SendFrame(client, reply_frame);
+}
+
+void HostImpl::OnInvokeMethod(ClientConnection* client,
+ const Frame& req_frame) {
+ const Frame::InvokeMethod& req = req_frame.msg_invoke_method();
+ Frame reply_frame;
+ RequestID request_id = req_frame.request_id();
+ reply_frame.set_request_id(request_id);
+ reply_frame.mutable_msg_invoke_method_reply()->set_success(false);
+ auto svc_it = services_.find(req.service_id());
+ if (svc_it == services_.end())
+ return SendFrame(client, reply_frame); // |success| == false by default.
+
+ Service* service = svc_it->second.instance.get();
+ const ServiceDescriptor& svc = service->GetDescriptor();
+ const auto& methods = svc.methods;
+ const uint32_t method_id = req.method_id();
+ if (method_id == 0 || method_id > methods.size())
+ return SendFrame(client, reply_frame);
+
+ const ServiceDescriptor::Method& method = methods[method_id - 1];
+ std::unique_ptr<ProtoMessage> decoded_req_args(
+ method.request_proto_decoder(req.args_proto()));
+ if (!decoded_req_args)
+ return SendFrame(client, reply_frame);
+
+ Deferred<ProtoMessage> deferred_reply;
+ base::WeakPtr<HostImpl> host_weak_ptr = weak_ptr_factory_.GetWeakPtr();
+ ClientID client_id = client->id;
+
+ if (!req.drop_reply()) {
+ deferred_reply.Bind([host_weak_ptr, client_id,
+ request_id](AsyncResult<ProtoMessage> reply) {
+ if (!host_weak_ptr)
+ return; // The reply came too late, the HostImpl has gone.
+ host_weak_ptr->ReplyToMethodInvocation(client_id, request_id,
+ std::move(reply));
+ });
+ }
+
+ auto peer_uid = client->GetPosixPeerUid();
+ auto scoped_key = g_crash_key_uid.SetScoped(static_cast<int64_t>(peer_uid));
+ service->client_info_ = ClientInfo(
+ client->id, peer_uid, client->GetLinuxPeerPid(), client->GetMachineID());
+ service->received_fd_ = &client->received_fd;
+ method.invoker(service, *decoded_req_args, std::move(deferred_reply));
+ service->received_fd_ = nullptr;
+ service->client_info_ = ClientInfo();
+}
+
+void HostImpl::OnSetPeerIdentity(ClientConnection* client,
+ const Frame& req_frame) {
+ if (client->sock->family() == base::SockFamily::kUnix) {
+ PERFETTO_DLOG("SetPeerIdentity is ignored for unix socket connections.");
+ return;
+ }
+
+ // This is can only be set once by the relay service.
+ if (client->pid_override != base::kInvalidPid ||
+ client->uid_override != base::kInvalidUid) {
+ PERFETTO_DLOG("Already received SetPeerIdentity.");
+ return;
+ }
+
+ const auto& set_peer_identity = req_frame.set_peer_identity();
+ client->pid_override = set_peer_identity.pid();
+ client->uid_override = static_cast<uid_t>(set_peer_identity.uid());
+
+ client->machine_id = GenerateMachineID(client->sock.get(),
+ set_peer_identity.machine_id_hint());
+}
+
+void HostImpl::ReplyToMethodInvocation(ClientID client_id,
+ RequestID request_id,
+ AsyncResult<ProtoMessage> reply) {
+ auto client_iter = clients_.find(client_id);
+ if (client_iter == clients_.end())
+ return; // client has disconnected by the time we got the async reply.
+
+ ClientConnection* client = client_iter->second.get();
+ Frame reply_frame;
+ reply_frame.set_request_id(request_id);
+
+ // TODO(fmayer): add a test to guarantee that the reply is consumed within the
+ // same call stack and not kept around. ConsumerIPCService::OnTraceData()
+ // relies on this behavior.
+ auto* reply_frame_data = reply_frame.mutable_msg_invoke_method_reply();
+ reply_frame_data->set_has_more(reply.has_more());
+ if (reply.success()) {
+ std::string reply_proto = reply->SerializeAsString();
+ reply_frame_data->set_reply_proto(reply_proto);
+ reply_frame_data->set_success(true);
+ }
+ SendFrame(client, reply_frame, reply.fd());
+}
+
+// static
+void HostImpl::SendFrame(ClientConnection* client, const Frame& frame, int fd) {
+ auto peer_uid = client->GetPosixPeerUid();
+ auto scoped_key = g_crash_key_uid.SetScoped(static_cast<int64_t>(peer_uid));
+
+ std::string buf = BufferedFrameDeserializer::Serialize(frame);
+
+ // On Fuchsia, |send_fd_cb_fuchsia_| is used to send the FD to the client
+ // and therefore must be set.
+ PERFETTO_DCHECK(!PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA) ||
+ client->send_fd_cb_fuchsia);
+ if (client->send_fd_cb_fuchsia && fd != base::ScopedFile::kInvalid) {
+ if (!client->send_fd_cb_fuchsia(fd)) {
+ client->sock->Shutdown(true);
+ return;
+ }
+ fd = base::ScopedFile::kInvalid;
+ }
+
+ // When a new Client connects in OnNewClientConnection we set a timeout on
+ // Send (see call to SetTxTimeout).
+ //
+ // The old behaviour was to do a blocking I/O call, which caused crashes from
+ // misbehaving producers (see b/169051440).
+ bool res = client->sock->Send(buf.data(), buf.size(), fd);
+ // If we timeout |res| will be false, but the UnixSocket will have called
+ // UnixSocket::ShutDown() and thus |is_connected()| is false.
+ PERFETTO_CHECK(res || !client->sock->is_connected());
+}
+
+void HostImpl::OnDisconnect(base::UnixSocket* sock) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ auto it = clients_by_socket_.find(sock);
+ if (it == clients_by_socket_.end())
+ return;
+ auto* client = it->second;
+ ClientID client_id = client->id;
+
+ ClientInfo client_info(client_id, client->GetPosixPeerUid(),
+ client->GetLinuxPeerPid(), client->GetMachineID());
+
+ clients_by_socket_.erase(it);
+ PERFETTO_DCHECK(clients_.count(client_id));
+ clients_.erase(client_id);
+
+ for (const auto& service_it : services_) {
+ Service& service = *service_it.second.instance;
+ service.client_info_ = client_info;
+ service.OnClientDisconnected();
+ service.client_info_ = ClientInfo();
+ }
+}
+
+const HostImpl::ExposedService* HostImpl::GetServiceByName(
+ const std::string& name) {
+ // This could be optimized by using another map<name,ServiceID>. However this
+ // is used only by Bind/ExposeService that are quite rare (once per client
+ // connection and once per service instance), not worth it.
+ for (const auto& it : services_) {
+ if (it.second.name == name)
+ return &it.second;
+ }
+ return nullptr;
+}
+
+HostImpl::ExposedService::ExposedService(ServiceID id_,
+ const std::string& name_,
+ std::unique_ptr<Service> instance_)
+ : id(id_), name(name_), instance(std::move(instance_)) {}
+
+HostImpl::ExposedService::ExposedService(ExposedService&&) noexcept = default;
+HostImpl::ExposedService& HostImpl::ExposedService::operator=(
+ HostImpl::ExposedService&&) = default;
+HostImpl::ExposedService::~ExposedService() = default;
+
+HostImpl::ClientConnection::~ClientConnection() = default;
+
+} // namespace ipc
+} // namespace perfetto
+// gen_amalgamated begin source: gen/protos/perfetto/ipc/consumer_port.ipc.cc
+// gen_amalgamated begin header: gen/protos/perfetto/ipc/consumer_port.ipc.h
+// DO NOT EDIT. Autogenerated by Perfetto IPC
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_CONSUMER_PORT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_CONSUMER_PORT_PROTO_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/consumer_port.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/observable_events.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_state.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/tracing_service_capabilities.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/trace_stats.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class ConsumerPort : public ::perfetto::ipc::Service {
+ private:
+ static ::perfetto::ipc::ServiceDescriptor* NewDescriptor();
+
+ public:
+ ~ConsumerPort() override;
+
+ static const ::perfetto::ipc::ServiceDescriptor& GetDescriptorStatic();
+
+ // Service implementation.
+ const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+ // Methods from the .proto file
+ using DeferredEnableTracingResponse = ::perfetto::ipc::Deferred<EnableTracingResponse>;
+ virtual void EnableTracing(const EnableTracingRequest&, DeferredEnableTracingResponse) = 0;
+
+ using DeferredDisableTracingResponse = ::perfetto::ipc::Deferred<DisableTracingResponse>;
+ virtual void DisableTracing(const DisableTracingRequest&, DeferredDisableTracingResponse) = 0;
+
+ using DeferredReadBuffersResponse = ::perfetto::ipc::Deferred<ReadBuffersResponse>;
+ virtual void ReadBuffers(const ReadBuffersRequest&, DeferredReadBuffersResponse) = 0;
+
+ using DeferredFreeBuffersResponse = ::perfetto::ipc::Deferred<FreeBuffersResponse>;
+ virtual void FreeBuffers(const FreeBuffersRequest&, DeferredFreeBuffersResponse) = 0;
+
+ using DeferredFlushResponse = ::perfetto::ipc::Deferred<FlushResponse>;
+ virtual void Flush(const FlushRequest&, DeferredFlushResponse) = 0;
+
+ using DeferredStartTracingResponse = ::perfetto::ipc::Deferred<StartTracingResponse>;
+ virtual void StartTracing(const StartTracingRequest&, DeferredStartTracingResponse) = 0;
+
+ using DeferredChangeTraceConfigResponse = ::perfetto::ipc::Deferred<ChangeTraceConfigResponse>;
+ virtual void ChangeTraceConfig(const ChangeTraceConfigRequest&, DeferredChangeTraceConfigResponse) = 0;
+
+ using DeferredDetachResponse = ::perfetto::ipc::Deferred<DetachResponse>;
+ virtual void Detach(const DetachRequest&, DeferredDetachResponse) = 0;
+
+ using DeferredAttachResponse = ::perfetto::ipc::Deferred<AttachResponse>;
+ virtual void Attach(const AttachRequest&, DeferredAttachResponse) = 0;
+
+ using DeferredGetTraceStatsResponse = ::perfetto::ipc::Deferred<GetTraceStatsResponse>;
+ virtual void GetTraceStats(const GetTraceStatsRequest&, DeferredGetTraceStatsResponse) = 0;
+
+ using DeferredObserveEventsResponse = ::perfetto::ipc::Deferred<ObserveEventsResponse>;
+ virtual void ObserveEvents(const ObserveEventsRequest&, DeferredObserveEventsResponse) = 0;
+
+ using DeferredQueryServiceStateResponse = ::perfetto::ipc::Deferred<QueryServiceStateResponse>;
+ virtual void QueryServiceState(const QueryServiceStateRequest&, DeferredQueryServiceStateResponse) = 0;
+
+ using DeferredQueryCapabilitiesResponse = ::perfetto::ipc::Deferred<QueryCapabilitiesResponse>;
+ virtual void QueryCapabilities(const QueryCapabilitiesRequest&, DeferredQueryCapabilitiesResponse) = 0;
+
+ using DeferredSaveTraceForBugreportResponse = ::perfetto::ipc::Deferred<SaveTraceForBugreportResponse>;
+ virtual void SaveTraceForBugreport(const SaveTraceForBugreportRequest&, DeferredSaveTraceForBugreportResponse) = 0;
+
+ using DeferredCloneSessionResponse = ::perfetto::ipc::Deferred<CloneSessionResponse>;
+ virtual void CloneSession(const CloneSessionRequest&, DeferredCloneSessionResponse) = 0;
+
+};
+
+
+class ConsumerPortProxy : public ::perfetto::ipc::ServiceProxy {
+ public:
+ explicit ConsumerPortProxy(::perfetto::ipc::ServiceProxy::EventListener*);
+ ~ConsumerPortProxy() override;
+
+ // ServiceProxy implementation.
+ const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+ // Methods from the .proto file
+ using DeferredEnableTracingResponse = ::perfetto::ipc::Deferred<EnableTracingResponse>;
+ void EnableTracing(const EnableTracingRequest&, DeferredEnableTracingResponse, int fd = -1);
+
+ using DeferredDisableTracingResponse = ::perfetto::ipc::Deferred<DisableTracingResponse>;
+ void DisableTracing(const DisableTracingRequest&, DeferredDisableTracingResponse, int fd = -1);
+
+ using DeferredReadBuffersResponse = ::perfetto::ipc::Deferred<ReadBuffersResponse>;
+ void ReadBuffers(const ReadBuffersRequest&, DeferredReadBuffersResponse, int fd = -1);
+
+ using DeferredFreeBuffersResponse = ::perfetto::ipc::Deferred<FreeBuffersResponse>;
+ void FreeBuffers(const FreeBuffersRequest&, DeferredFreeBuffersResponse, int fd = -1);
+
+ using DeferredFlushResponse = ::perfetto::ipc::Deferred<FlushResponse>;
+ void Flush(const FlushRequest&, DeferredFlushResponse, int fd = -1);
+
+ using DeferredStartTracingResponse = ::perfetto::ipc::Deferred<StartTracingResponse>;
+ void StartTracing(const StartTracingRequest&, DeferredStartTracingResponse, int fd = -1);
+
+ using DeferredChangeTraceConfigResponse = ::perfetto::ipc::Deferred<ChangeTraceConfigResponse>;
+ void ChangeTraceConfig(const ChangeTraceConfigRequest&, DeferredChangeTraceConfigResponse, int fd = -1);
+
+ using DeferredDetachResponse = ::perfetto::ipc::Deferred<DetachResponse>;
+ void Detach(const DetachRequest&, DeferredDetachResponse, int fd = -1);
+
+ using DeferredAttachResponse = ::perfetto::ipc::Deferred<AttachResponse>;
+ void Attach(const AttachRequest&, DeferredAttachResponse, int fd = -1);
+
+ using DeferredGetTraceStatsResponse = ::perfetto::ipc::Deferred<GetTraceStatsResponse>;
+ void GetTraceStats(const GetTraceStatsRequest&, DeferredGetTraceStatsResponse, int fd = -1);
+
+ using DeferredObserveEventsResponse = ::perfetto::ipc::Deferred<ObserveEventsResponse>;
+ void ObserveEvents(const ObserveEventsRequest&, DeferredObserveEventsResponse, int fd = -1);
+
+ using DeferredQueryServiceStateResponse = ::perfetto::ipc::Deferred<QueryServiceStateResponse>;
+ void QueryServiceState(const QueryServiceStateRequest&, DeferredQueryServiceStateResponse, int fd = -1);
+
+ using DeferredQueryCapabilitiesResponse = ::perfetto::ipc::Deferred<QueryCapabilitiesResponse>;
+ void QueryCapabilities(const QueryCapabilitiesRequest&, DeferredQueryCapabilitiesResponse, int fd = -1);
+
+ using DeferredSaveTraceForBugreportResponse = ::perfetto::ipc::Deferred<SaveTraceForBugreportResponse>;
+ void SaveTraceForBugreport(const SaveTraceForBugreportRequest&, DeferredSaveTraceForBugreportResponse, int fd = -1);
+
+ using DeferredCloneSessionResponse = ::perfetto::ipc::Deferred<CloneSessionResponse>;
+ void CloneSession(const CloneSessionRequest&, DeferredCloneSessionResponse, int fd = -1);
+
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_CONSUMER_PORT_PROTO_H_
+// gen_amalgamated begin header: include/perfetto/ext/ipc/codegen_helpers.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// This file is only meant to be included in autogenerated .cc files.
+
+#ifndef INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
+#define INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
+
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+
+// A templated protobuf message decoder. Returns nullptr in case of failure.
+template <typename T>
+::std::unique_ptr<::perfetto::ipc::ProtoMessage> _IPC_Decoder(
+ const std::string& proto_data) {
+ ::std::unique_ptr<::perfetto::ipc::ProtoMessage> msg(new T());
+ if (msg->ParseFromString(proto_data))
+ return msg;
+ return nullptr;
+}
+
+// Templated method dispatcher. Used to obtain a function pointer to a given
+// IPC method (Method) of a given service (TSvc) that can be invoked by the
+// host-side machinery starting from a generic Service pointer and a generic
+// ProtoMessage request argument.
+template <typename TSvc, // Type of the actual Service subclass.
+ typename TReq, // Type of the request argument.
+ typename TReply, // Type of the reply argument.
+ void (TSvc::*Method)(const TReq&, ::perfetto::ipc::Deferred<TReply>)>
+void _IPC_Invoker(::perfetto::ipc::Service* s,
+ const ::perfetto::ipc::ProtoMessage& req,
+ ::perfetto::ipc::DeferredBase reply) {
+ (*static_cast<TSvc*>(s).*Method)(
+ static_cast<const TReq&>(req),
+ ::perfetto::ipc::Deferred<TReply>(::std::move(reply)));
+}
+
+#endif // INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
+// DO NOT EDIT. Autogenerated by Perfetto IPC
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/consumer_port.ipc.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/codegen_helpers.h"
+
+#include <memory>
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+::perfetto::ipc::ServiceDescriptor* ConsumerPort::NewDescriptor() {
+ auto* desc = new ::perfetto::ipc::ServiceDescriptor();
+ desc->service_name = "ConsumerPort";
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "EnableTracing",
+ &_IPC_Decoder<EnableTracingRequest>,
+ &_IPC_Decoder<EnableTracingResponse>,
+ &_IPC_Invoker<ConsumerPort, EnableTracingRequest, EnableTracingResponse, &ConsumerPort::EnableTracing>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "DisableTracing",
+ &_IPC_Decoder<DisableTracingRequest>,
+ &_IPC_Decoder<DisableTracingResponse>,
+ &_IPC_Invoker<ConsumerPort, DisableTracingRequest, DisableTracingResponse, &ConsumerPort::DisableTracing>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "ReadBuffers",
+ &_IPC_Decoder<ReadBuffersRequest>,
+ &_IPC_Decoder<ReadBuffersResponse>,
+ &_IPC_Invoker<ConsumerPort, ReadBuffersRequest, ReadBuffersResponse, &ConsumerPort::ReadBuffers>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "FreeBuffers",
+ &_IPC_Decoder<FreeBuffersRequest>,
+ &_IPC_Decoder<FreeBuffersResponse>,
+ &_IPC_Invoker<ConsumerPort, FreeBuffersRequest, FreeBuffersResponse, &ConsumerPort::FreeBuffers>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "Flush",
+ &_IPC_Decoder<FlushRequest>,
+ &_IPC_Decoder<FlushResponse>,
+ &_IPC_Invoker<ConsumerPort, FlushRequest, FlushResponse, &ConsumerPort::Flush>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "StartTracing",
+ &_IPC_Decoder<StartTracingRequest>,
+ &_IPC_Decoder<StartTracingResponse>,
+ &_IPC_Invoker<ConsumerPort, StartTracingRequest, StartTracingResponse, &ConsumerPort::StartTracing>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "ChangeTraceConfig",
+ &_IPC_Decoder<ChangeTraceConfigRequest>,
+ &_IPC_Decoder<ChangeTraceConfigResponse>,
+ &_IPC_Invoker<ConsumerPort, ChangeTraceConfigRequest, ChangeTraceConfigResponse, &ConsumerPort::ChangeTraceConfig>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "Detach",
+ &_IPC_Decoder<DetachRequest>,
+ &_IPC_Decoder<DetachResponse>,
+ &_IPC_Invoker<ConsumerPort, DetachRequest, DetachResponse, &ConsumerPort::Detach>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "Attach",
+ &_IPC_Decoder<AttachRequest>,
+ &_IPC_Decoder<AttachResponse>,
+ &_IPC_Invoker<ConsumerPort, AttachRequest, AttachResponse, &ConsumerPort::Attach>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "GetTraceStats",
+ &_IPC_Decoder<GetTraceStatsRequest>,
+ &_IPC_Decoder<GetTraceStatsResponse>,
+ &_IPC_Invoker<ConsumerPort, GetTraceStatsRequest, GetTraceStatsResponse, &ConsumerPort::GetTraceStats>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "ObserveEvents",
+ &_IPC_Decoder<ObserveEventsRequest>,
+ &_IPC_Decoder<ObserveEventsResponse>,
+ &_IPC_Invoker<ConsumerPort, ObserveEventsRequest, ObserveEventsResponse, &ConsumerPort::ObserveEvents>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "QueryServiceState",
+ &_IPC_Decoder<QueryServiceStateRequest>,
+ &_IPC_Decoder<QueryServiceStateResponse>,
+ &_IPC_Invoker<ConsumerPort, QueryServiceStateRequest, QueryServiceStateResponse, &ConsumerPort::QueryServiceState>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "QueryCapabilities",
+ &_IPC_Decoder<QueryCapabilitiesRequest>,
+ &_IPC_Decoder<QueryCapabilitiesResponse>,
+ &_IPC_Invoker<ConsumerPort, QueryCapabilitiesRequest, QueryCapabilitiesResponse, &ConsumerPort::QueryCapabilities>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "SaveTraceForBugreport",
+ &_IPC_Decoder<SaveTraceForBugreportRequest>,
+ &_IPC_Decoder<SaveTraceForBugreportResponse>,
+ &_IPC_Invoker<ConsumerPort, SaveTraceForBugreportRequest, SaveTraceForBugreportResponse, &ConsumerPort::SaveTraceForBugreport>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "CloneSession",
+ &_IPC_Decoder<CloneSessionRequest>,
+ &_IPC_Decoder<CloneSessionResponse>,
+ &_IPC_Invoker<ConsumerPort, CloneSessionRequest, CloneSessionResponse, &ConsumerPort::CloneSession>});
+ desc->methods.shrink_to_fit();
+ return desc;
+}
+
+
+const ::perfetto::ipc::ServiceDescriptor& ConsumerPort::GetDescriptorStatic() {
+ static auto* instance = NewDescriptor();
+ return *instance;
+}
+
+// Host-side definitions.
+ConsumerPort::~ConsumerPort() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& ConsumerPort::GetDescriptor() {
+ return GetDescriptorStatic();
+}
+
+// Client-side definitions.
+ConsumerPortProxy::ConsumerPortProxy(::perfetto::ipc::ServiceProxy::EventListener* event_listener)
+ : ::perfetto::ipc::ServiceProxy(event_listener) {}
+
+ConsumerPortProxy::~ConsumerPortProxy() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& ConsumerPortProxy::GetDescriptor() {
+ return ConsumerPort::GetDescriptorStatic();
+}
+
+void ConsumerPortProxy::EnableTracing(const EnableTracingRequest& request, DeferredEnableTracingResponse reply, int fd) {
+ BeginInvoke("EnableTracing", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::DisableTracing(const DisableTracingRequest& request, DeferredDisableTracingResponse reply, int fd) {
+ BeginInvoke("DisableTracing", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::ReadBuffers(const ReadBuffersRequest& request, DeferredReadBuffersResponse reply, int fd) {
+ BeginInvoke("ReadBuffers", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::FreeBuffers(const FreeBuffersRequest& request, DeferredFreeBuffersResponse reply, int fd) {
+ BeginInvoke("FreeBuffers", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::Flush(const FlushRequest& request, DeferredFlushResponse reply, int fd) {
+ BeginInvoke("Flush", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::StartTracing(const StartTracingRequest& request, DeferredStartTracingResponse reply, int fd) {
+ BeginInvoke("StartTracing", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::ChangeTraceConfig(const ChangeTraceConfigRequest& request, DeferredChangeTraceConfigResponse reply, int fd) {
+ BeginInvoke("ChangeTraceConfig", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::Detach(const DetachRequest& request, DeferredDetachResponse reply, int fd) {
+ BeginInvoke("Detach", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::Attach(const AttachRequest& request, DeferredAttachResponse reply, int fd) {
+ BeginInvoke("Attach", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::GetTraceStats(const GetTraceStatsRequest& request, DeferredGetTraceStatsResponse reply, int fd) {
+ BeginInvoke("GetTraceStats", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::ObserveEvents(const ObserveEventsRequest& request, DeferredObserveEventsResponse reply, int fd) {
+ BeginInvoke("ObserveEvents", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::QueryServiceState(const QueryServiceStateRequest& request, DeferredQueryServiceStateResponse reply, int fd) {
+ BeginInvoke("QueryServiceState", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::QueryCapabilities(const QueryCapabilitiesRequest& request, DeferredQueryCapabilitiesResponse reply, int fd) {
+ BeginInvoke("QueryCapabilities", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::SaveTraceForBugreport(const SaveTraceForBugreportRequest& request, DeferredSaveTraceForBugreportResponse reply, int fd) {
+ BeginInvoke("SaveTraceForBugreport", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ConsumerPortProxy::CloneSession(const CloneSessionRequest& request, DeferredCloneSessionResponse reply, int fd) {
+ BeginInvoke("CloneSession", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+// gen_amalgamated begin source: gen/protos/perfetto/ipc/producer_port.ipc.cc
+// gen_amalgamated begin header: gen/protos/perfetto/ipc/producer_port.ipc.h
+// DO NOT EDIT. Autogenerated by Perfetto IPC
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_PRODUCER_PORT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_PRODUCER_PORT_PROTO_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/producer_port.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/commit_data_request.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class ProducerPort : public ::perfetto::ipc::Service {
+ private:
+ static ::perfetto::ipc::ServiceDescriptor* NewDescriptor();
+
+ public:
+ ~ProducerPort() override;
+
+ static const ::perfetto::ipc::ServiceDescriptor& GetDescriptorStatic();
+
+ // Service implementation.
+ const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+ // Methods from the .proto file
+ using DeferredInitializeConnectionResponse = ::perfetto::ipc::Deferred<InitializeConnectionResponse>;
+ virtual void InitializeConnection(const InitializeConnectionRequest&, DeferredInitializeConnectionResponse) = 0;
+
+ using DeferredRegisterDataSourceResponse = ::perfetto::ipc::Deferred<RegisterDataSourceResponse>;
+ virtual void RegisterDataSource(const RegisterDataSourceRequest&, DeferredRegisterDataSourceResponse) = 0;
+
+ using DeferredUnregisterDataSourceResponse = ::perfetto::ipc::Deferred<UnregisterDataSourceResponse>;
+ virtual void UnregisterDataSource(const UnregisterDataSourceRequest&, DeferredUnregisterDataSourceResponse) = 0;
+
+ using DeferredCommitDataResponse = ::perfetto::ipc::Deferred<CommitDataResponse>;
+ virtual void CommitData(const CommitDataRequest&, DeferredCommitDataResponse) = 0;
+
+ using DeferredGetAsyncCommandResponse = ::perfetto::ipc::Deferred<GetAsyncCommandResponse>;
+ virtual void GetAsyncCommand(const GetAsyncCommandRequest&, DeferredGetAsyncCommandResponse) = 0;
+
+ using DeferredRegisterTraceWriterResponse = ::perfetto::ipc::Deferred<RegisterTraceWriterResponse>;
+ virtual void RegisterTraceWriter(const RegisterTraceWriterRequest&, DeferredRegisterTraceWriterResponse) = 0;
+
+ using DeferredUnregisterTraceWriterResponse = ::perfetto::ipc::Deferred<UnregisterTraceWriterResponse>;
+ virtual void UnregisterTraceWriter(const UnregisterTraceWriterRequest&, DeferredUnregisterTraceWriterResponse) = 0;
+
+ using DeferredNotifyDataSourceStartedResponse = ::perfetto::ipc::Deferred<NotifyDataSourceStartedResponse>;
+ virtual void NotifyDataSourceStarted(const NotifyDataSourceStartedRequest&, DeferredNotifyDataSourceStartedResponse) = 0;
+
+ using DeferredNotifyDataSourceStoppedResponse = ::perfetto::ipc::Deferred<NotifyDataSourceStoppedResponse>;
+ virtual void NotifyDataSourceStopped(const NotifyDataSourceStoppedRequest&, DeferredNotifyDataSourceStoppedResponse) = 0;
+
+ using DeferredActivateTriggersResponse = ::perfetto::ipc::Deferred<ActivateTriggersResponse>;
+ virtual void ActivateTriggers(const ActivateTriggersRequest&, DeferredActivateTriggersResponse) = 0;
+
+ using DeferredSyncResponse = ::perfetto::ipc::Deferred<SyncResponse>;
+ virtual void Sync(const SyncRequest&, DeferredSyncResponse) = 0;
+
+ using DeferredUpdateDataSourceResponse = ::perfetto::ipc::Deferred<UpdateDataSourceResponse>;
+ virtual void UpdateDataSource(const UpdateDataSourceRequest&, DeferredUpdateDataSourceResponse) = 0;
+
+};
+
+
+class ProducerPortProxy : public ::perfetto::ipc::ServiceProxy {
+ public:
+ explicit ProducerPortProxy(::perfetto::ipc::ServiceProxy::EventListener*);
+ ~ProducerPortProxy() override;
+
+ // ServiceProxy implementation.
+ const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+ // Methods from the .proto file
+ using DeferredInitializeConnectionResponse = ::perfetto::ipc::Deferred<InitializeConnectionResponse>;
+ void InitializeConnection(const InitializeConnectionRequest&, DeferredInitializeConnectionResponse, int fd = -1);
+
+ using DeferredRegisterDataSourceResponse = ::perfetto::ipc::Deferred<RegisterDataSourceResponse>;
+ void RegisterDataSource(const RegisterDataSourceRequest&, DeferredRegisterDataSourceResponse, int fd = -1);
+
+ using DeferredUnregisterDataSourceResponse = ::perfetto::ipc::Deferred<UnregisterDataSourceResponse>;
+ void UnregisterDataSource(const UnregisterDataSourceRequest&, DeferredUnregisterDataSourceResponse, int fd = -1);
+
+ using DeferredCommitDataResponse = ::perfetto::ipc::Deferred<CommitDataResponse>;
+ void CommitData(const CommitDataRequest&, DeferredCommitDataResponse, int fd = -1);
+
+ using DeferredGetAsyncCommandResponse = ::perfetto::ipc::Deferred<GetAsyncCommandResponse>;
+ void GetAsyncCommand(const GetAsyncCommandRequest&, DeferredGetAsyncCommandResponse, int fd = -1);
+
+ using DeferredRegisterTraceWriterResponse = ::perfetto::ipc::Deferred<RegisterTraceWriterResponse>;
+ void RegisterTraceWriter(const RegisterTraceWriterRequest&, DeferredRegisterTraceWriterResponse, int fd = -1);
+
+ using DeferredUnregisterTraceWriterResponse = ::perfetto::ipc::Deferred<UnregisterTraceWriterResponse>;
+ void UnregisterTraceWriter(const UnregisterTraceWriterRequest&, DeferredUnregisterTraceWriterResponse, int fd = -1);
+
+ using DeferredNotifyDataSourceStartedResponse = ::perfetto::ipc::Deferred<NotifyDataSourceStartedResponse>;
+ void NotifyDataSourceStarted(const NotifyDataSourceStartedRequest&, DeferredNotifyDataSourceStartedResponse, int fd = -1);
+
+ using DeferredNotifyDataSourceStoppedResponse = ::perfetto::ipc::Deferred<NotifyDataSourceStoppedResponse>;
+ void NotifyDataSourceStopped(const NotifyDataSourceStoppedRequest&, DeferredNotifyDataSourceStoppedResponse, int fd = -1);
+
+ using DeferredActivateTriggersResponse = ::perfetto::ipc::Deferred<ActivateTriggersResponse>;
+ void ActivateTriggers(const ActivateTriggersRequest&, DeferredActivateTriggersResponse, int fd = -1);
+
+ using DeferredSyncResponse = ::perfetto::ipc::Deferred<SyncResponse>;
+ void Sync(const SyncRequest&, DeferredSyncResponse, int fd = -1);
+
+ using DeferredUpdateDataSourceResponse = ::perfetto::ipc::Deferred<UpdateDataSourceResponse>;
+ void UpdateDataSource(const UpdateDataSourceRequest&, DeferredUpdateDataSourceResponse, int fd = -1);
+
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_PRODUCER_PORT_PROTO_H_
+// DO NOT EDIT. Autogenerated by Perfetto IPC
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/producer_port.ipc.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/codegen_helpers.h"
+
+#include <memory>
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+::perfetto::ipc::ServiceDescriptor* ProducerPort::NewDescriptor() {
+ auto* desc = new ::perfetto::ipc::ServiceDescriptor();
+ desc->service_name = "ProducerPort";
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "InitializeConnection",
+ &_IPC_Decoder<InitializeConnectionRequest>,
+ &_IPC_Decoder<InitializeConnectionResponse>,
+ &_IPC_Invoker<ProducerPort, InitializeConnectionRequest, InitializeConnectionResponse, &ProducerPort::InitializeConnection>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "RegisterDataSource",
+ &_IPC_Decoder<RegisterDataSourceRequest>,
+ &_IPC_Decoder<RegisterDataSourceResponse>,
+ &_IPC_Invoker<ProducerPort, RegisterDataSourceRequest, RegisterDataSourceResponse, &ProducerPort::RegisterDataSource>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "UnregisterDataSource",
+ &_IPC_Decoder<UnregisterDataSourceRequest>,
+ &_IPC_Decoder<UnregisterDataSourceResponse>,
+ &_IPC_Invoker<ProducerPort, UnregisterDataSourceRequest, UnregisterDataSourceResponse, &ProducerPort::UnregisterDataSource>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "CommitData",
+ &_IPC_Decoder<CommitDataRequest>,
+ &_IPC_Decoder<CommitDataResponse>,
+ &_IPC_Invoker<ProducerPort, CommitDataRequest, CommitDataResponse, &ProducerPort::CommitData>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "GetAsyncCommand",
+ &_IPC_Decoder<GetAsyncCommandRequest>,
+ &_IPC_Decoder<GetAsyncCommandResponse>,
+ &_IPC_Invoker<ProducerPort, GetAsyncCommandRequest, GetAsyncCommandResponse, &ProducerPort::GetAsyncCommand>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "RegisterTraceWriter",
+ &_IPC_Decoder<RegisterTraceWriterRequest>,
+ &_IPC_Decoder<RegisterTraceWriterResponse>,
+ &_IPC_Invoker<ProducerPort, RegisterTraceWriterRequest, RegisterTraceWriterResponse, &ProducerPort::RegisterTraceWriter>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "UnregisterTraceWriter",
+ &_IPC_Decoder<UnregisterTraceWriterRequest>,
+ &_IPC_Decoder<UnregisterTraceWriterResponse>,
+ &_IPC_Invoker<ProducerPort, UnregisterTraceWriterRequest, UnregisterTraceWriterResponse, &ProducerPort::UnregisterTraceWriter>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "NotifyDataSourceStarted",
+ &_IPC_Decoder<NotifyDataSourceStartedRequest>,
+ &_IPC_Decoder<NotifyDataSourceStartedResponse>,
+ &_IPC_Invoker<ProducerPort, NotifyDataSourceStartedRequest, NotifyDataSourceStartedResponse, &ProducerPort::NotifyDataSourceStarted>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "NotifyDataSourceStopped",
+ &_IPC_Decoder<NotifyDataSourceStoppedRequest>,
+ &_IPC_Decoder<NotifyDataSourceStoppedResponse>,
+ &_IPC_Invoker<ProducerPort, NotifyDataSourceStoppedRequest, NotifyDataSourceStoppedResponse, &ProducerPort::NotifyDataSourceStopped>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "ActivateTriggers",
+ &_IPC_Decoder<ActivateTriggersRequest>,
+ &_IPC_Decoder<ActivateTriggersResponse>,
+ &_IPC_Invoker<ProducerPort, ActivateTriggersRequest, ActivateTriggersResponse, &ProducerPort::ActivateTriggers>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "Sync",
+ &_IPC_Decoder<SyncRequest>,
+ &_IPC_Decoder<SyncResponse>,
+ &_IPC_Invoker<ProducerPort, SyncRequest, SyncResponse, &ProducerPort::Sync>});
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "UpdateDataSource",
+ &_IPC_Decoder<UpdateDataSourceRequest>,
+ &_IPC_Decoder<UpdateDataSourceResponse>,
+ &_IPC_Invoker<ProducerPort, UpdateDataSourceRequest, UpdateDataSourceResponse, &ProducerPort::UpdateDataSource>});
+ desc->methods.shrink_to_fit();
+ return desc;
+}
+
+
+const ::perfetto::ipc::ServiceDescriptor& ProducerPort::GetDescriptorStatic() {
+ static auto* instance = NewDescriptor();
+ return *instance;
+}
+
+// Host-side definitions.
+ProducerPort::~ProducerPort() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& ProducerPort::GetDescriptor() {
+ return GetDescriptorStatic();
+}
+
+// Client-side definitions.
+ProducerPortProxy::ProducerPortProxy(::perfetto::ipc::ServiceProxy::EventListener* event_listener)
+ : ::perfetto::ipc::ServiceProxy(event_listener) {}
+
+ProducerPortProxy::~ProducerPortProxy() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& ProducerPortProxy::GetDescriptor() {
+ return ProducerPort::GetDescriptorStatic();
+}
+
+void ProducerPortProxy::InitializeConnection(const InitializeConnectionRequest& request, DeferredInitializeConnectionResponse reply, int fd) {
+ BeginInvoke("InitializeConnection", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::RegisterDataSource(const RegisterDataSourceRequest& request, DeferredRegisterDataSourceResponse reply, int fd) {
+ BeginInvoke("RegisterDataSource", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::UnregisterDataSource(const UnregisterDataSourceRequest& request, DeferredUnregisterDataSourceResponse reply, int fd) {
+ BeginInvoke("UnregisterDataSource", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::CommitData(const CommitDataRequest& request, DeferredCommitDataResponse reply, int fd) {
+ BeginInvoke("CommitData", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::GetAsyncCommand(const GetAsyncCommandRequest& request, DeferredGetAsyncCommandResponse reply, int fd) {
+ BeginInvoke("GetAsyncCommand", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::RegisterTraceWriter(const RegisterTraceWriterRequest& request, DeferredRegisterTraceWriterResponse reply, int fd) {
+ BeginInvoke("RegisterTraceWriter", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::UnregisterTraceWriter(const UnregisterTraceWriterRequest& request, DeferredUnregisterTraceWriterResponse reply, int fd) {
+ BeginInvoke("UnregisterTraceWriter", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::NotifyDataSourceStarted(const NotifyDataSourceStartedRequest& request, DeferredNotifyDataSourceStartedResponse reply, int fd) {
+ BeginInvoke("NotifyDataSourceStarted", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::NotifyDataSourceStopped(const NotifyDataSourceStoppedRequest& request, DeferredNotifyDataSourceStoppedResponse reply, int fd) {
+ BeginInvoke("NotifyDataSourceStopped", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::ActivateTriggers(const ActivateTriggersRequest& request, DeferredActivateTriggersResponse reply, int fd) {
+ BeginInvoke("ActivateTriggers", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::Sync(const SyncRequest& request, DeferredSyncResponse reply, int fd) {
+ BeginInvoke("Sync", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+
+void ProducerPortProxy::UpdateDataSource(const UpdateDataSourceRequest& request, DeferredUpdateDataSourceResponse reply, int fd) {
+ BeginInvoke("UpdateDataSource", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+// gen_amalgamated begin source: gen/protos/perfetto/ipc/relay_port.ipc.cc
+// gen_amalgamated begin header: gen/protos/perfetto/ipc/relay_port.ipc.h
+// DO NOT EDIT. Autogenerated by Perfetto IPC
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_RELAY_PORT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_RELAY_PORT_PROTO_H_
+
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/deferred.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/relay_port.gen.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class RelayPort : public ::perfetto::ipc::Service {
+ private:
+ static ::perfetto::ipc::ServiceDescriptor* NewDescriptor();
+
+ public:
+ ~RelayPort() override;
+
+ static const ::perfetto::ipc::ServiceDescriptor& GetDescriptorStatic();
+
+ // Service implementation.
+ const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+ // Methods from the .proto file
+ using DeferredSyncClockResponse = ::perfetto::ipc::Deferred<SyncClockResponse>;
+ virtual void SyncClock(const SyncClockRequest&, DeferredSyncClockResponse) = 0;
+
+};
+
+
+class RelayPortProxy : public ::perfetto::ipc::ServiceProxy {
+ public:
+ explicit RelayPortProxy(::perfetto::ipc::ServiceProxy::EventListener*);
+ ~RelayPortProxy() override;
+
+ // ServiceProxy implementation.
+ const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+ // Methods from the .proto file
+ using DeferredSyncClockResponse = ::perfetto::ipc::Deferred<SyncClockResponse>;
+ void SyncClock(const SyncClockRequest&, DeferredSyncClockResponse, int fd = -1);
+
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_RELAY_PORT_PROTO_H_
+// DO NOT EDIT. Autogenerated by Perfetto IPC
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/relay_port.ipc.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/codegen_helpers.h"
+
+#include <memory>
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+::perfetto::ipc::ServiceDescriptor* RelayPort::NewDescriptor() {
+ auto* desc = new ::perfetto::ipc::ServiceDescriptor();
+ desc->service_name = "RelayPort";
+
+ desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+ "SyncClock",
+ &_IPC_Decoder<SyncClockRequest>,
+ &_IPC_Decoder<SyncClockResponse>,
+ &_IPC_Invoker<RelayPort, SyncClockRequest, SyncClockResponse, &RelayPort::SyncClock>});
+ desc->methods.shrink_to_fit();
+ return desc;
+}
+
+
+const ::perfetto::ipc::ServiceDescriptor& RelayPort::GetDescriptorStatic() {
+ static auto* instance = NewDescriptor();
+ return *instance;
+}
+
+// Host-side definitions.
+RelayPort::~RelayPort() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& RelayPort::GetDescriptor() {
+ return GetDescriptorStatic();
+}
+
+// Client-side definitions.
+RelayPortProxy::RelayPortProxy(::perfetto::ipc::ServiceProxy::EventListener* event_listener)
+ : ::perfetto::ipc::ServiceProxy(event_listener) {}
+
+RelayPortProxy::~RelayPortProxy() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& RelayPortProxy::GetDescriptor() {
+ return RelayPort::GetDescriptorStatic();
+}
+
+void RelayPortProxy::SyncClock(const SyncClockRequest& request, DeferredSyncClockResponse reply, int fd) {
+ BeginInvoke("SyncClock", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+ fd);
+}
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+// gen_amalgamated begin source: src/tracing/ipc/default_socket.cc
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/default_socket.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+
+#include <stdlib.h>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <unistd.h>
+#endif
+
+namespace perfetto {
+namespace {
+
+const char* kRunPerfettoBaseDir = "/run/perfetto/";
+
+// On Linux and CrOS, check /run/perfetto/ before using /tmp/ as the socket
+// base directory.
+bool UseRunPerfettoBaseDir() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
+ // Note that the trailing / in |kRunPerfettoBaseDir| ensures we are checking
+ // against a directory, not a file.
+ int res = PERFETTO_EINTR(access(kRunPerfettoBaseDir, X_OK));
+ if (!res)
+ return true;
+
+ // If the path doesn't exist (ENOENT), fail silently to the caller. Otherwise,
+ // fail with an explicit error message.
+ if (errno != ENOENT
+#if PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
+ // access(2) won't return EPERM, but Chromium sandbox returns EPERM if the
+ // sandbox doesn't allow the call (e.g. in the child processes).
+ && errno != EPERM
+#endif
+ ) {
+ PERFETTO_PLOG("%s exists but cannot be accessed. Falling back on /tmp/ ",
+ kRunPerfettoBaseDir);
+ }
+ return false;
+#else
+ base::ignore_result(kRunPerfettoBaseDir);
+ return false;
+#endif
+}
+
+} // anonymous namespace
+
+const char* GetProducerSocket() {
+ const char* name = getenv("PERFETTO_PRODUCER_SOCK_NAME");
+ if (name == nullptr) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ name = "127.0.0.1:32278";
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ name = "/dev/socket/traced_producer";
+#else
+ // Use /run/perfetto if it exists. Then fallback to /tmp.
+ static const char* producer_socket =
+ UseRunPerfettoBaseDir() ? "/run/perfetto/traced-producer.sock"
+ : "/tmp/perfetto-producer";
+ name = producer_socket;
+#endif
+ }
+ base::ignore_result(UseRunPerfettoBaseDir); // Silence unused func warnings.
+ return name;
+}
+
+const char* GetRelaySocket() {
+ // The relay socket is optional and is connected only when the env var is set.
+ return getenv("PERFETTO_RELAY_SOCK_NAME");
+}
+
+std::vector<std::string> TokenizeProducerSockets(
+ const char* producer_socket_names) {
+ return base::SplitString(producer_socket_names, ",");
+}
+
+const char* GetConsumerSocket() {
+ const char* name = getenv("PERFETTO_CONSUMER_SOCK_NAME");
+ if (name == nullptr) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ name = "127.0.0.1:32279";
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ name = "/dev/socket/traced_consumer";
+#else
+ // Use /run/perfetto if it exists. Then fallback to /tmp.
+ static const char* consumer_socket =
+ UseRunPerfettoBaseDir() ? "/run/perfetto/traced-consumer.sock"
+ : "/tmp/perfetto-consumer";
+ name = consumer_socket;
+#endif
+ }
+ return name;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/ipc/memfd.cc
+// gen_amalgamated begin header: src/tracing/ipc/memfd.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_MEMFD_H_
+#define SRC_TRACING_IPC_MEMFD_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+
+// Some android build bots use a sysroot that doesn't support memfd when
+// compiling for the host, so we define the flags we need ourselves.
+
+// from memfd.h
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 0x0001U
+#define MFD_ALLOW_SEALING 0x0002U
+#endif
+
+// from fcntl.h
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS 1033
+#define F_GET_SEALS 1034
+#define F_SEAL_SEAL 0x0001
+#define F_SEAL_SHRINK 0x0002
+#define F_SEAL_GROW 0x0004
+#define F_SEAL_WRITE 0x0008
+#endif
+
+namespace perfetto {
+
+// Whether the operating system supports memfd.
+bool HasMemfdSupport();
+
+// Call memfd(2) if available on platform and return the fd as result. This call
+// also makes a kernel version check for safety on older kernels (b/116769556).
+// Returns an invalid ScopedFile on failure.
+base::ScopedFile CreateMemfd(const char* name, unsigned int flags);
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_IPC_MEMFD_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/memfd.h"
+
+#include <errno.h>
+
+#define PERFETTO_MEMFD_ENABLED() \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
+
+#if PERFETTO_MEMFD_ENABLED()
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+// Some android build bots use a sysroot that doesn't support memfd when
+// compiling for the host, so we redefine it if necessary.
+#if !defined(__NR_memfd_create)
+#if defined(__x86_64__)
+#define __NR_memfd_create 319
+#elif defined(__i386__)
+#define __NR_memfd_create 356
+#elif defined(__aarch64__)
+#define __NR_memfd_create 279
+#elif defined(__arm__)
+#define __NR_memfd_create 385
+#else
+#error "unsupported sysroot without memfd support"
+#endif
+#endif // !defined(__NR_memfd_create)
+
+namespace perfetto {
+bool HasMemfdSupport() {
+ static bool kSupportsMemfd = [] {
+ // Check kernel version supports memfd_create(). Some older kernels segfault
+ // executing memfd_create() rather than returning ENOSYS (b/116769556).
+ static constexpr int kRequiredMajor = 3;
+ static constexpr int kRequiredMinor = 17;
+ struct utsname uts;
+ int major, minor;
+ if (uname(&uts) == 0 && strcmp(uts.sysname, "Linux") == 0 &&
+ sscanf(uts.release, "%d.%d", &major, &minor) == 2 &&
+ ((major < kRequiredMajor ||
+ (major == kRequiredMajor && minor < kRequiredMinor)))) {
+ return false;
+ }
+
+ base::ScopedFile fd;
+ fd.reset(static_cast<int>(syscall(__NR_memfd_create, "perfetto_shmem",
+ MFD_CLOEXEC | MFD_ALLOW_SEALING)));
+ return !!fd;
+ }();
+ return kSupportsMemfd;
+}
+
+base::ScopedFile CreateMemfd(const char* name, unsigned int flags) {
+ if (!HasMemfdSupport()) {
+ errno = ENOSYS;
+ return base::ScopedFile();
+ }
+ return base::ScopedFile(
+ static_cast<int>(syscall(__NR_memfd_create, name, flags)));
+}
+} // namespace perfetto
+
+#else // PERFETTO_MEMFD_ENABLED()
+
+namespace perfetto {
+bool HasMemfdSupport() {
+ return false;
+}
+base::ScopedFile CreateMemfd(const char*, unsigned int) {
+ errno = ENOSYS;
+ return base::ScopedFile();
+}
+} // namespace perfetto
+
+#endif // PERFETTO_MEMFD_ENABLED()
+// gen_amalgamated begin source: src/tracing/ipc/posix_shared_memory.cc
+// gen_amalgamated begin header: src/tracing/ipc/posix_shared_memory.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
+#define SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+
+#include <stddef.h>
+
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+
+namespace perfetto {
+
+// Implements the SharedMemory and its factory for the posix-based transport.
+class PosixSharedMemory : public SharedMemory {
+ public:
+ class Factory : public SharedMemory::Factory {
+ public:
+ ~Factory() override;
+ std::unique_ptr<SharedMemory> CreateSharedMemory(size_t) override;
+ };
+
+ // Create a brand new SHM region.
+ static std::unique_ptr<PosixSharedMemory> Create(size_t size);
+
+ // Mmaps a file descriptor to an existing SHM region. If
+ // |require_seals_if_supported| is true and the system supports
+ // memfd_create(), the FD is required to be a sealed memfd with F_SEAL_SEAL,
+ // F_SEAL_GROW, and F_SEAL_SHRINK seals set (otherwise, nullptr is returned).
+ // May also return nullptr if mapping fails for another reason (e.g. OOM).
+ static std::unique_ptr<PosixSharedMemory> AttachToFd(
+ base::ScopedFile,
+ bool require_seals_if_supported = true);
+
+ ~PosixSharedMemory() override;
+
+ int fd() const { return fd_.get(); }
+
+ // SharedMemory implementation.
+ void* start() const override { return start_; }
+ size_t size() const override { return size_; }
+
+ private:
+ static std::unique_ptr<PosixSharedMemory> MapFD(base::ScopedFile, size_t);
+
+ PosixSharedMemory(void* start, size_t size, base::ScopedFile);
+ PosixSharedMemory(const PosixSharedMemory&) = delete;
+ PosixSharedMemory& operator=(const PosixSharedMemory&) = delete;
+
+ void* const start_;
+ const size_t size_;
+ base::ScopedFile fd_;
+};
+
+} // namespace perfetto
+
+#endif // OS_LINUX || OS_ANDROID || OS_APPLE
+#endif // SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/posix_shared_memory.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <memory>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/temp_file.h"
+// gen_amalgamated expanded: #include "src/tracing/ipc/memfd.h"
+
+namespace perfetto {
+
+namespace {
+int kFileSeals = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL;
+} // namespace
+
+// static
+std::unique_ptr<PosixSharedMemory> PosixSharedMemory::Create(size_t size) {
+ base::ScopedFile fd =
+ CreateMemfd("perfetto_shmem", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ bool is_memfd = !!fd;
+
+ // In-tree builds only allow mem_fd, so we can inspect the seals to verify the
+ // fd is appropriately sealed. We'll crash in the PERFETTO_CHECK(fd) below if
+ // memfd_create failed.
+#if !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+ if (!fd) {
+ // TODO: if this fails on Android we should fall back on ashmem.
+ PERFETTO_DPLOG("memfd_create() failed");
+ fd = base::TempFile::CreateUnlinked().ReleaseFD();
+ }
+#endif
+
+ PERFETTO_CHECK(fd);
+ int res = ftruncate(fd.get(), static_cast<off_t>(size));
+ PERFETTO_CHECK(res == 0);
+
+ if (is_memfd) {
+ // When memfd is supported, file seals should be, too.
+ res = fcntl(*fd, F_ADD_SEALS, kFileSeals);
+ PERFETTO_DCHECK(res == 0);
+ }
+
+ return MapFD(std::move(fd), size);
+}
+
+// static
+std::unique_ptr<PosixSharedMemory> PosixSharedMemory::AttachToFd(
+ base::ScopedFile fd,
+ bool require_seals_if_supported) {
+ bool requires_seals = require_seals_if_supported;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+ // In-tree kernels all support memfd.
+ PERFETTO_CHECK(HasMemfdSupport());
+#else
+ // In out-of-tree builds, we only require seals if the kernel supports memfd.
+ if (requires_seals)
+ requires_seals = HasMemfdSupport();
+#endif
+
+ if (requires_seals) {
+ // If the system supports memfd, we require a sealed memfd.
+ int res = fcntl(*fd, F_GET_SEALS);
+ if (res == -1 || (res & kFileSeals) != kFileSeals) {
+ PERFETTO_PLOG("Couldn't verify file seals on shmem FD");
+ return nullptr;
+ }
+ }
+
+ struct stat stat_buf = {};
+ int res = fstat(fd.get(), &stat_buf);
+ PERFETTO_CHECK(res == 0 && stat_buf.st_size > 0);
+ return MapFD(std::move(fd), static_cast<size_t>(stat_buf.st_size));
+}
+
+// static
+std::unique_ptr<PosixSharedMemory> PosixSharedMemory::MapFD(base::ScopedFile fd,
+ size_t size) {
+ PERFETTO_DCHECK(fd);
+ PERFETTO_DCHECK(size > 0);
+ void* start =
+ mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
+ PERFETTO_CHECK(start != MAP_FAILED);
+ return std::unique_ptr<PosixSharedMemory>(
+ new PosixSharedMemory(start, size, std::move(fd)));
+}
+
+PosixSharedMemory::PosixSharedMemory(void* start,
+ size_t size,
+ base::ScopedFile fd)
+ : start_(start), size_(size), fd_(std::move(fd)) {}
+
+PosixSharedMemory::~PosixSharedMemory() {
+ munmap(start(), size());
+}
+
+PosixSharedMemory::Factory::~Factory() {}
+
+std::unique_ptr<SharedMemory> PosixSharedMemory::Factory::CreateSharedMemory(
+ size_t size) {
+ return PosixSharedMemory::Create(size);
+}
+
+} // namespace perfetto
+
+#endif // OS_LINUX || OS_ANDROID || OS_APPLE
+// gen_amalgamated begin source: src/tracing/ipc/shared_memory_windows.cc
+// gen_amalgamated begin header: src/tracing/ipc/shared_memory_windows.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_SHARED_MEMORY_WINDOWS_H_
+#define SRC_TRACING_IPC_SHARED_MEMORY_WINDOWS_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+
+namespace perfetto {
+
+// Implements the SharedMemory and its factory for the Windows IPC transport.
+// This used only for standalone builds and NOT in chromium, which instead uses
+// a custom Mojo wrapper (MojoSharedMemory in chromium's //services/tracing/).
+class SharedMemoryWindows : public SharedMemory {
+ public:
+ class Factory : public SharedMemory::Factory {
+ public:
+ ~Factory() override;
+ std::unique_ptr<SharedMemory> CreateSharedMemory(size_t) override;
+ };
+
+ // Create a brand new SHM region.
+ enum Flags { kNone = 0, kInheritableHandles };
+ static std::unique_ptr<SharedMemoryWindows> Create(
+ size_t size, Flags flags=Flags::kNone);
+ static std::unique_ptr<SharedMemoryWindows> Attach(const std::string& key);
+ static std::unique_ptr<SharedMemoryWindows> AttachToHandleWithKey(
+ base::ScopedPlatformHandle fd, const std::string& key);
+ ~SharedMemoryWindows() override;
+ const std::string& key() const { return key_; }
+ const base::ScopedPlatformHandle& handle() const { return handle_; }
+
+ // SharedMemory implementation.
+ void* start() const override { return start_; }
+ size_t size() const override { return size_; }
+
+ private:
+ SharedMemoryWindows(void* start,
+ size_t size,
+ std::string,
+ base::ScopedPlatformHandle);
+ SharedMemoryWindows(const SharedMemoryWindows&) = delete;
+ SharedMemoryWindows& operator=(const SharedMemoryWindows&) = delete;
+
+ void* const start_;
+ const size_t size_;
+ std::string key_;
+ base::ScopedPlatformHandle handle_;
+};
+
+} // namespace perfetto
+
+#endif // OS_WIN
+
+#endif // SRC_TRACING_IPC_SHARED_MEMORY_WINDOWS_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/shared_memory_windows.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+#include <memory>
+#include <random>
+
+#include <Windows.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+
+// static
+std::unique_ptr<SharedMemoryWindows> SharedMemoryWindows::Create(
+ size_t size, Flags flags) {
+ base::ScopedPlatformHandle shmem_handle;
+ std::random_device rnd_dev;
+ uint64_t rnd_key = (static_cast<uint64_t>(rnd_dev()) << 32) | rnd_dev();
+ std::string key = "perfetto_shm_" + base::Uint64ToHexStringNoPrefix(rnd_key);
+
+ SECURITY_ATTRIBUTES security_attributes = {};
+ security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ if (flags & Flags::kInheritableHandles)
+ security_attributes.bInheritHandle = TRUE;
+
+ shmem_handle.reset(CreateFileMappingA(
+ INVALID_HANDLE_VALUE, // Use paging file.
+ &security_attributes,
+ PAGE_READWRITE,
+ static_cast<DWORD>(size >> 32), // maximum object size (high-order DWORD)
+ static_cast<DWORD>(size), // maximum object size (low-order DWORD)
+ key.c_str()));
+
+ if (!shmem_handle) {
+ PERFETTO_PLOG("CreateFileMapping() call failed");
+ return nullptr;
+ }
+ void* start =
+ MapViewOfFile(*shmem_handle, FILE_MAP_ALL_ACCESS, /*offsetHigh=*/0,
+ /*offsetLow=*/0, size);
+ if (!start) {
+ PERFETTO_PLOG("MapViewOfFile() failed");
+ return nullptr;
+ }
+
+ return std::unique_ptr<SharedMemoryWindows>(new SharedMemoryWindows(
+ start, size, std::move(key), std::move(shmem_handle)));
+}
+
+// static
+std::unique_ptr<SharedMemoryWindows> SharedMemoryWindows::Attach(
+ const std::string& key) {
+ base::ScopedPlatformHandle shmem_handle;
+ shmem_handle.reset(
+ OpenFileMappingA(FILE_MAP_ALL_ACCESS, /*inherit=*/false, key.c_str()));
+ if (!shmem_handle) {
+ PERFETTO_PLOG("Failed to OpenFileMapping()");
+ return nullptr;
+ }
+
+ void* start =
+ MapViewOfFile(*shmem_handle, FILE_MAP_ALL_ACCESS, /*offsetHigh=*/0,
+ /*offsetLow=*/0, /*dwNumberOfBytesToMap=*/0);
+ if (!start) {
+ PERFETTO_PLOG("MapViewOfFile() failed");
+ return nullptr;
+ }
+
+ MEMORY_BASIC_INFORMATION info{};
+ if (!VirtualQuery(start, &info, sizeof(info))) {
+ PERFETTO_PLOG("VirtualQuery() failed");
+ return nullptr;
+ }
+ size_t size = info.RegionSize;
+ return std::unique_ptr<SharedMemoryWindows>(
+ new SharedMemoryWindows(start, size, key, std::move(shmem_handle)));
+}
+
+// static
+std::unique_ptr<SharedMemoryWindows> SharedMemoryWindows::AttachToHandleWithKey(
+ base::ScopedPlatformHandle shmem_handle, const std::string& key) {
+ void* start =
+ MapViewOfFile(*shmem_handle, FILE_MAP_ALL_ACCESS, /*offsetHigh=*/0,
+ /*offsetLow=*/0, /*dwNumberOfBytesToMap=*/0);
+ if (!start) {
+ PERFETTO_PLOG("MapViewOfFile() failed");
+ return nullptr;
+ }
+
+ MEMORY_BASIC_INFORMATION info{};
+ if (!VirtualQuery(start, &info, sizeof(info))) {
+ PERFETTO_PLOG("VirtualQuery() failed");
+ return nullptr;
+ }
+ size_t size = info.RegionSize;
+
+ return std::unique_ptr<SharedMemoryWindows>(
+ new SharedMemoryWindows(start, size, key, std::move(shmem_handle)));
+}
+
+SharedMemoryWindows::SharedMemoryWindows(void* start,
+ size_t size,
+ std::string key,
+ base::ScopedPlatformHandle handle)
+ : start_(start),
+ size_(size),
+ key_(std::move(key)),
+ handle_(std::move(handle)) {}
+
+SharedMemoryWindows::~SharedMemoryWindows() {
+ if (start_)
+ UnmapViewOfFile(start_);
+}
+
+SharedMemoryWindows::Factory::~Factory() = default;
+
+std::unique_ptr<SharedMemory> SharedMemoryWindows::Factory::CreateSharedMemory(
+ size_t size) {
+ return SharedMemoryWindows::Create(size);
+}
+
+} // namespace perfetto
+
+#endif // !OS_WIN
+// gen_amalgamated begin source: src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+// gen_amalgamated begin header: src/tracing/ipc/consumer/consumer_ipc_client_impl.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
+
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+
+namespace perfetto {
+
+class Consumer;
+
+// Allows to connect to a remote Service through a UNIX domain socket.
+// Exposed to:
+// Consumer(s) of the tracing library.
+// Implemented in:
+// src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+class PERFETTO_EXPORT_COMPONENT ConsumerIPCClient {
+ public:
+ // Connects to the producer port of the Service listening on the given
+ // |service_sock_name|. If the connection is successful, the OnConnect()
+ // method will be invoked asynchronously on the passed Consumer interface.
+ // If the connection fails, OnDisconnect() will be invoked instead.
+ // The returned ConsumerEndpoint serves also to delimit the scope of the
+ // callbacks invoked on the Consumer interface: no more Consumer callbacks are
+ // invoked immediately after its destruction and any pending callback will be
+ // dropped.
+ static std::unique_ptr<TracingService::ConsumerEndpoint>
+ Connect(const char* service_sock_name, Consumer*, base::TaskRunner*);
+
+ protected:
+ ConsumerIPCClient() = delete;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_CONSUMER_CONSUMER_IPC_CLIENT_IMPL_H_
+#define SRC_TRACING_IPC_CONSUMER_CONSUMER_IPC_CLIENT_IMPL_H_
+
+#include <stdint.h>
+
+#include <list>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_packet.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/consumer_port.ipc.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+namespace ipc {
+class Client;
+} // namespace ipc
+
+class Consumer;
+
+// Exposes a Service endpoint to Consumer(s), proxying all requests through a
+// IPC channel to the remote Service. This class is the glue layer between the
+// generic Service interface exposed to the clients of the library and the
+// actual IPC transport.
+class ConsumerIPCClientImpl : public TracingService::ConsumerEndpoint,
+ public ipc::ServiceProxy::EventListener {
+ public:
+ ConsumerIPCClientImpl(const char* service_sock_name,
+ Consumer*,
+ base::TaskRunner*);
+ ~ConsumerIPCClientImpl() override;
+
+ // TracingService::ConsumerEndpoint implementation.
+ // These methods are invoked by the actual Consumer(s) code by clients of the
+ // tracing library, which know nothing about the IPC transport.
+ void EnableTracing(const TraceConfig&, base::ScopedFile) override;
+ void StartTracing() override;
+ void ChangeTraceConfig(const TraceConfig&) override;
+ void DisableTracing() override;
+ void ReadBuffers() override;
+ void FreeBuffers() override;
+ void Flush(uint32_t timeout_ms, FlushCallback, FlushFlags) override;
+ void Detach(const std::string& key) override;
+ void Attach(const std::string& key) override;
+ void GetTraceStats() override;
+ void ObserveEvents(uint32_t enabled_event_types) override;
+ void QueryServiceState(QueryServiceStateArgs,
+ QueryServiceStateCallback) override;
+ void QueryCapabilities(QueryCapabilitiesCallback) override;
+ void SaveTraceForBugreport(SaveTraceForBugreportCallback) override;
+ void CloneSession(TracingSessionID, CloneSessionArgs) override;
+
+ // ipc::ServiceProxy::EventListener implementation.
+ // These methods are invoked by the IPC layer, which knows nothing about
+ // tracing, consumers and consumers.
+ void OnConnect() override;
+ void OnDisconnect() override;
+
+ private:
+ struct PendingQueryServiceRequest {
+ QueryServiceStateCallback callback;
+
+ // All the replies will be appended here until |has_more| == false.
+ std::vector<uint8_t> merged_resp;
+ };
+
+ // List because we need stable iterators.
+ using PendingQueryServiceRequests = std::list<PendingQueryServiceRequest>;
+
+ void OnReadBuffersResponse(
+ ipc::AsyncResult<protos::gen::ReadBuffersResponse>);
+ void OnEnableTracingResponse(
+ ipc::AsyncResult<protos::gen::EnableTracingResponse>);
+ void OnQueryServiceStateResponse(
+ ipc::AsyncResult<protos::gen::QueryServiceStateResponse>,
+ PendingQueryServiceRequests::iterator);
+
+ // TODO(primiano): think to dtor order, do we rely on any specific sequence?
+ Consumer* const consumer_;
+
+ // The object that owns the client socket and takes care of IPC traffic.
+ std::unique_ptr<ipc::Client> ipc_channel_;
+
+ // The proxy interface for the consumer port of the service. It is bound
+ // to |ipc_channel_| and (de)serializes method invocations over the wire.
+ protos::gen::ConsumerPortProxy consumer_port_;
+
+ bool connected_ = false;
+
+ PendingQueryServiceRequests pending_query_svc_reqs_;
+
+ // When a packet is too big to fit into a ReadBuffersResponse IPC, the service
+ // will chunk it into several IPCs, each containing few slices of the packet
+ // (a packet's slice is always guaranteed to be << kIPCBufferSize). When
+ // chunking happens this field accumulates the slices received until the
+ // one with |last_slice_for_packet| == true is received.
+ TracePacket partial_packet_;
+
+ // Keep last.
+ base::WeakPtrFactory<ConsumerIPCClientImpl> weak_ptr_factory_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_IPC_CONSUMER_CONSUMER_IPC_CLIENT_IMPL_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/consumer/consumer_ipc_client_impl.h"
+
+#include <string.h>
+
+#include <cinttypes>
+
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/client.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/consumer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/observable_events.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_stats.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/trace_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/tracing_service_state.h"
+
+// TODO(fmayer): Add a test to check to what happens when ConsumerIPCClientImpl
+// gets destroyed w.r.t. the Consumer pointer. Also think to lifetime of the
+// Consumer* during the callbacks.
+
+namespace perfetto {
+
+// static. (Declared in include/tracing/ipc/consumer_ipc_client.h).
+std::unique_ptr<TracingService::ConsumerEndpoint> ConsumerIPCClient::Connect(
+ const char* service_sock_name,
+ Consumer* consumer,
+ base::TaskRunner* task_runner) {
+ return std::unique_ptr<TracingService::ConsumerEndpoint>(
+ new ConsumerIPCClientImpl(service_sock_name, consumer, task_runner));
+}
+
+ConsumerIPCClientImpl::ConsumerIPCClientImpl(const char* service_sock_name,
+ Consumer* consumer,
+ base::TaskRunner* task_runner)
+ : consumer_(consumer),
+ ipc_channel_(
+ ipc::Client::CreateInstance({service_sock_name, /*sock_retry=*/false},
+ task_runner)),
+ consumer_port_(this /* event_listener */),
+ weak_ptr_factory_(this) {
+ ipc_channel_->BindService(consumer_port_.GetWeakPtr());
+}
+
+ConsumerIPCClientImpl::~ConsumerIPCClientImpl() = default;
+
+// Called by the IPC layer if the BindService() succeeds.
+void ConsumerIPCClientImpl::OnConnect() {
+ connected_ = true;
+ consumer_->OnConnect();
+}
+
+void ConsumerIPCClientImpl::OnDisconnect() {
+ PERFETTO_DLOG("Tracing service connection failure");
+ connected_ = false;
+ consumer_->OnDisconnect(); // Note: may delete |this|.
+}
+
+void ConsumerIPCClientImpl::EnableTracing(const TraceConfig& trace_config,
+ base::ScopedFile fd) {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot EnableTracing(), not connected to tracing service");
+ return;
+ }
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (fd) {
+ consumer_->OnTracingDisabled(
+ "Passing FDs for write_into_file is not supported on Windows");
+ return;
+ }
+#endif
+
+ protos::gen::EnableTracingRequest req;
+ *req.mutable_trace_config() = trace_config;
+ ipc::Deferred<protos::gen::EnableTracingResponse> async_response;
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ async_response.Bind(
+ [weak_this](
+ ipc::AsyncResult<protos::gen::EnableTracingResponse> response) {
+ if (weak_this)
+ weak_this->OnEnableTracingResponse(std::move(response));
+ });
+
+ // |fd| will be closed when this function returns, but it's fine because the
+ // IPC layer dup()'s it when sending the IPC.
+ consumer_port_.EnableTracing(req, std::move(async_response), *fd);
+}
+
+void ConsumerIPCClientImpl::ChangeTraceConfig(const TraceConfig& trace_config) {
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot ChangeTraceConfig(), not connected to tracing service");
+ return;
+ }
+
+ ipc::Deferred<protos::gen::ChangeTraceConfigResponse> async_response;
+ async_response.Bind(
+ [](ipc::AsyncResult<protos::gen::ChangeTraceConfigResponse> response) {
+ if (!response)
+ PERFETTO_DLOG("ChangeTraceConfig() failed");
+ });
+ protos::gen::ChangeTraceConfigRequest req;
+ *req.mutable_trace_config() = trace_config;
+ consumer_port_.ChangeTraceConfig(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::StartTracing() {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot StartTracing(), not connected to tracing service");
+ return;
+ }
+
+ ipc::Deferred<protos::gen::StartTracingResponse> async_response;
+ async_response.Bind(
+ [](ipc::AsyncResult<protos::gen::StartTracingResponse> response) {
+ if (!response)
+ PERFETTO_DLOG("StartTracing() failed");
+ });
+ protos::gen::StartTracingRequest req;
+ consumer_port_.StartTracing(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::DisableTracing() {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot DisableTracing(), not connected to tracing service");
+ return;
+ }
+
+ ipc::Deferred<protos::gen::DisableTracingResponse> async_response;
+ async_response.Bind(
+ [](ipc::AsyncResult<protos::gen::DisableTracingResponse> response) {
+ if (!response)
+ PERFETTO_DLOG("DisableTracing() failed");
+ });
+ consumer_port_.DisableTracing(protos::gen::DisableTracingRequest(),
+ std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::ReadBuffers() {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot ReadBuffers(), not connected to tracing service");
+ return;
+ }
+
+ ipc::Deferred<protos::gen::ReadBuffersResponse> async_response;
+
+ // The IPC layer guarantees that callbacks are destroyed after this object
+ // is destroyed (by virtue of destroying the |consumer_port_|). In turn the
+ // contract of this class expects the caller to not destroy the Consumer class
+ // before having destroyed this class. Hence binding |this| here is safe.
+ async_response.Bind(
+ [this](ipc::AsyncResult<protos::gen::ReadBuffersResponse> response) {
+ OnReadBuffersResponse(std::move(response));
+ });
+ consumer_port_.ReadBuffers(protos::gen::ReadBuffersRequest(),
+ std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::OnReadBuffersResponse(
+ ipc::AsyncResult<protos::gen::ReadBuffersResponse> response) {
+ if (!response) {
+ PERFETTO_DLOG("ReadBuffers() failed");
+ return;
+ }
+ std::vector<TracePacket> trace_packets;
+ for (auto& resp_slice : response->slices()) {
+ const std::string& slice_data = resp_slice.data();
+ Slice slice = Slice::Allocate(slice_data.size());
+ memcpy(slice.own_data(), slice_data.data(), slice.size);
+ partial_packet_.AddSlice(std::move(slice));
+ if (resp_slice.last_slice_for_packet())
+ trace_packets.emplace_back(std::move(partial_packet_));
+ }
+ if (!trace_packets.empty() || !response.has_more())
+ consumer_->OnTraceData(std::move(trace_packets), response.has_more());
+}
+
+void ConsumerIPCClientImpl::OnEnableTracingResponse(
+ ipc::AsyncResult<protos::gen::EnableTracingResponse> response) {
+ std::string error;
+ // |response| might be empty when the request gets rejected (if the connection
+ // with the service is dropped all outstanding requests are auto-rejected).
+ if (!response) {
+ error =
+ "EnableTracing IPC request rejected. This is likely due to a loss of "
+ "the traced connection";
+ } else {
+ error = response->error();
+ }
+ if (!response || response->disabled())
+ consumer_->OnTracingDisabled(error);
+}
+
+void ConsumerIPCClientImpl::FreeBuffers() {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot FreeBuffers(), not connected to tracing service");
+ return;
+ }
+
+ protos::gen::FreeBuffersRequest req;
+ ipc::Deferred<protos::gen::FreeBuffersResponse> async_response;
+ async_response.Bind(
+ [](ipc::AsyncResult<protos::gen::FreeBuffersResponse> response) {
+ if (!response)
+ PERFETTO_DLOG("FreeBuffers() failed");
+ });
+ consumer_port_.FreeBuffers(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::Flush(uint32_t timeout_ms,
+ FlushCallback callback,
+ FlushFlags flush_flags) {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot Flush(), not connected to tracing service");
+ return callback(/*success=*/false);
+ }
+
+ protos::gen::FlushRequest req;
+ req.set_timeout_ms(static_cast<uint32_t>(timeout_ms));
+ req.set_flags(flush_flags.flags());
+ ipc::Deferred<protos::gen::FlushResponse> async_response;
+ async_response.Bind(
+ [callback](ipc::AsyncResult<protos::gen::FlushResponse> response) {
+ callback(!!response);
+ });
+ consumer_port_.Flush(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::Detach(const std::string& key) {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot Detach(), not connected to tracing service");
+ return;
+ }
+
+ protos::gen::DetachRequest req;
+ req.set_key(key);
+ ipc::Deferred<protos::gen::DetachResponse> async_response;
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+
+ async_response.Bind(
+ [weak_this](ipc::AsyncResult<protos::gen::DetachResponse> response) {
+ if (weak_this)
+ weak_this->consumer_->OnDetach(!!response);
+ });
+ consumer_port_.Detach(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::Attach(const std::string& key) {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot Attach(), not connected to tracing service");
+ return;
+ }
+
+ {
+ protos::gen::AttachRequest req;
+ req.set_key(key);
+ ipc::Deferred<protos::gen::AttachResponse> async_response;
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+
+ async_response.Bind(
+ [weak_this](ipc::AsyncResult<protos::gen::AttachResponse> response) {
+ if (!weak_this)
+ return;
+ if (!response) {
+ weak_this->consumer_->OnAttach(/*success=*/false, TraceConfig());
+ return;
+ }
+ const TraceConfig& trace_config = response->trace_config();
+
+ // If attached successfully, also attach to the end-of-trace
+ // notificaton callback, via EnableTracing(attach_notification_only).
+ protos::gen::EnableTracingRequest enable_req;
+ enable_req.set_attach_notification_only(true);
+ ipc::Deferred<protos::gen::EnableTracingResponse> enable_resp;
+ enable_resp.Bind(
+ [weak_this](
+ ipc::AsyncResult<protos::gen::EnableTracingResponse> resp) {
+ if (weak_this)
+ weak_this->OnEnableTracingResponse(std::move(resp));
+ });
+ weak_this->consumer_port_.EnableTracing(enable_req,
+ std::move(enable_resp));
+
+ weak_this->consumer_->OnAttach(/*success=*/true, trace_config);
+ });
+ consumer_port_.Attach(req, std::move(async_response));
+ }
+}
+
+void ConsumerIPCClientImpl::GetTraceStats() {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot GetTraceStats(), not connected to tracing service");
+ return;
+ }
+
+ protos::gen::GetTraceStatsRequest req;
+ ipc::Deferred<protos::gen::GetTraceStatsResponse> async_response;
+
+ // The IPC layer guarantees that callbacks are destroyed after this object
+ // is destroyed (by virtue of destroying the |consumer_port_|). In turn the
+ // contract of this class expects the caller to not destroy the Consumer class
+ // before having destroyed this class. Hence binding |this| here is safe.
+ async_response.Bind(
+ [this](ipc::AsyncResult<protos::gen::GetTraceStatsResponse> response) {
+ if (!response) {
+ consumer_->OnTraceStats(/*success=*/false, TraceStats());
+ return;
+ }
+ consumer_->OnTraceStats(/*success=*/true, response->trace_stats());
+ });
+ consumer_port_.GetTraceStats(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::ObserveEvents(uint32_t enabled_event_types) {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot ObserveEvents(), not connected to tracing service");
+ return;
+ }
+
+ protos::gen::ObserveEventsRequest req;
+ for (uint32_t i = 0; i < 32; i++) {
+ const uint32_t event_id = 1u << i;
+ if (enabled_event_types & event_id)
+ req.add_events_to_observe(static_cast<ObservableEvents::Type>(event_id));
+ }
+
+ ipc::Deferred<protos::gen::ObserveEventsResponse> async_response;
+ // The IPC layer guarantees that callbacks are destroyed after this object
+ // is destroyed (by virtue of destroying the |consumer_port_|). In turn the
+ // contract of this class expects the caller to not destroy the Consumer class
+ // before having destroyed this class. Hence binding |this| here is safe.
+ async_response.Bind(
+ [this](ipc::AsyncResult<protos::gen::ObserveEventsResponse> response) {
+ // Skip empty response, which the service sends to close the stream.
+ if (!response.has_more()) {
+ PERFETTO_DCHECK(!response.success());
+ return;
+ }
+ consumer_->OnObservableEvents(response->events());
+ });
+ consumer_port_.ObserveEvents(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::QueryServiceState(
+ QueryServiceStateArgs args,
+ QueryServiceStateCallback callback) {
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot QueryServiceState(), not connected to tracing service");
+ return;
+ }
+
+ auto it = pending_query_svc_reqs_.insert(pending_query_svc_reqs_.end(),
+ {std::move(callback), {}});
+ protos::gen::QueryServiceStateRequest req;
+ req.set_sessions_only(args.sessions_only);
+ ipc::Deferred<protos::gen::QueryServiceStateResponse> async_response;
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ async_response.Bind(
+ [weak_this,
+ it](ipc::AsyncResult<protos::gen::QueryServiceStateResponse> response) {
+ if (weak_this)
+ weak_this->OnQueryServiceStateResponse(std::move(response), it);
+ });
+ consumer_port_.QueryServiceState(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::OnQueryServiceStateResponse(
+ ipc::AsyncResult<protos::gen::QueryServiceStateResponse> response,
+ PendingQueryServiceRequests::iterator req_it) {
+ PERFETTO_DCHECK(req_it->callback);
+
+ if (!response) {
+ auto callback = std::move(req_it->callback);
+ pending_query_svc_reqs_.erase(req_it);
+ callback(false, TracingServiceState());
+ return;
+ }
+
+ // The QueryServiceState response can be split in several chunks if the
+ // service has several data sources. The client is supposed to merge all the
+ // replies. The easiest way to achieve this is to re-serialize the partial
+ // response and then re-decode the merged result in one shot.
+ std::vector<uint8_t>& merged_resp = req_it->merged_resp;
+ std::vector<uint8_t> part = response->service_state().SerializeAsArray();
+ merged_resp.insert(merged_resp.end(), part.begin(), part.end());
+
+ if (response.has_more())
+ return;
+
+ // All replies have been received. Decode the merged result and reply to the
+ // callback.
+ protos::gen::TracingServiceState svc_state;
+ bool ok = svc_state.ParseFromArray(merged_resp.data(), merged_resp.size());
+ if (!ok)
+ PERFETTO_ELOG("Failed to decode merged QueryServiceStateResponse");
+ auto callback = std::move(req_it->callback);
+ pending_query_svc_reqs_.erase(req_it);
+ callback(ok, std::move(svc_state));
+}
+
+void ConsumerIPCClientImpl::QueryCapabilities(
+ QueryCapabilitiesCallback callback) {
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot QueryCapabilities(), not connected to tracing service");
+ return;
+ }
+
+ protos::gen::QueryCapabilitiesRequest req;
+ ipc::Deferred<protos::gen::QueryCapabilitiesResponse> async_response;
+ async_response.Bind(
+ [callback](
+ ipc::AsyncResult<protos::gen::QueryCapabilitiesResponse> response) {
+ if (!response) {
+ // If the IPC fails, we are talking to an older version of the service
+ // that didn't support QueryCapabilities at all. In this case return
+ // an empty capabilities message.
+ callback(TracingServiceCapabilities());
+ } else {
+ callback(response->capabilities());
+ }
+ });
+ consumer_port_.QueryCapabilities(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::SaveTraceForBugreport(
+ SaveTraceForBugreportCallback callback) {
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot SaveTraceForBugreport(), not connected to tracing service");
+ return;
+ }
+
+ protos::gen::SaveTraceForBugreportRequest req;
+ ipc::Deferred<protos::gen::SaveTraceForBugreportResponse> async_response;
+ async_response.Bind(
+ [callback](ipc::AsyncResult<protos::gen::SaveTraceForBugreportResponse>
+ response) {
+ if (!response) {
+ // If the IPC fails, we are talking to an older version of the service
+ // that didn't support SaveTraceForBugreport at all.
+ callback(
+ false,
+ "The tracing service doesn't support SaveTraceForBugreport()");
+ } else {
+ callback(response->success(), response->msg());
+ }
+ });
+ consumer_port_.SaveTraceForBugreport(req, std::move(async_response));
+}
+
+void ConsumerIPCClientImpl::CloneSession(TracingSessionID tsid,
+ CloneSessionArgs args) {
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot CloneSession(), not connected to tracing service");
+ return;
+ }
+
+ protos::gen::CloneSessionRequest req;
+ req.set_session_id(tsid);
+ req.set_skip_trace_filter(args.skip_trace_filter);
+ req.set_for_bugreport(args.for_bugreport);
+ ipc::Deferred<protos::gen::CloneSessionResponse> async_response;
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+
+ async_response.Bind(
+ [weak_this](
+ ipc::AsyncResult<protos::gen::CloneSessionResponse> response) {
+ if (!weak_this)
+ return;
+ if (!response) {
+ // If the IPC fails, we are talking to an older version of the service
+ // that didn't support CloneSession at all.
+ weak_this->consumer_->OnSessionCloned(
+ {false, "CloneSession IPC not supported", {}});
+ } else {
+ base::Uuid uuid(response->uuid_lsb(), response->uuid_msb());
+ weak_this->consumer_->OnSessionCloned(
+ {response->success(), response->error(), uuid});
+ }
+ });
+ consumer_port_.CloneSession(req, std::move(async_response));
+}
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/ipc/producer/producer_ipc_client_impl.cc
+// gen_amalgamated begin header: src/tracing/ipc/producer/producer_ipc_client_impl.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/ipc/producer_ipc_client.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
+
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/client.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"
+
+namespace perfetto {
+
+class Producer;
+
+// Allows to connect to a remote Service through a UNIX domain socket.
+// Exposed to:
+// Producer(s) of the tracing library.
+// Implemented in:
+// src/tracing/ipc/producer/producer_ipc_client_impl.cc
+class PERFETTO_EXPORT_COMPONENT ProducerIPCClient {
+ public:
+ enum class ConnectionFlags {
+ // Fails immediately with OnConnect(false) if the service connection cannot
+ // be established.
+ kDefault = 0,
+
+ // Keeps retrying with exponential backoff indefinitely. The caller will
+ // never see an OnConnect(false).
+ kRetryIfUnreachable = 1,
+ };
+
+ // Connects to the producer port of the Service listening on the given
+ // |service_sock_name|. If the connection is successful, the OnConnect()
+ // method will be invoked asynchronously on the passed Producer interface. If
+ // the connection fails, OnDisconnect() will be invoked instead. The returned
+ // ProducerEndpoint serves also to delimit the scope of the callbacks invoked
+ // on the Producer interface: no more Producer callbacks are invoked
+ // immediately after its destruction and any pending callback will be dropped.
+ // To provide a producer-allocated shared memory buffer, both |shm| and
+ // |shm_arbiter| should be set. |shm_arbiter| should be an unbound
+ // SharedMemoryArbiter instance. When |shm| and |shm_arbiter| are provided,
+ // the service will attempt to adopt the provided SMB. If this fails, the
+ // ProducerEndpoint will disconnect, but the SMB and arbiter will remain valid
+ // until the client is destroyed.
+ //
+ // TODO(eseckler): Support adoption failure more gracefully.
+ // TODO(primiano): move all the existing use cases to the Connect(ConnArgs)
+ // below. Also move the functionality of ConnectionFlags into ConnArgs.
+ static std::unique_ptr<TracingService::ProducerEndpoint> Connect(
+ const char* service_sock_name,
+ Producer*,
+ const std::string& producer_name,
+ base::TaskRunner*,
+ TracingService::ProducerSMBScrapingMode smb_scraping_mode =
+ TracingService::ProducerSMBScrapingMode::kDefault,
+ size_t shared_memory_size_hint_bytes = 0,
+ size_t shared_memory_page_size_hint_bytes = 0,
+ std::unique_ptr<SharedMemory> shm = nullptr,
+ std::unique_ptr<SharedMemoryArbiter> shm_arbiter = nullptr,
+ ConnectionFlags = ConnectionFlags::kDefault);
+
+ // Overload of Connect() to support adopting a connected socket using
+ // ipc::Client::ConnArgs.
+ static std::unique_ptr<TracingService::ProducerEndpoint> Connect(
+ ipc::Client::ConnArgs,
+ Producer*,
+ const std::string& producer_name,
+ base::TaskRunner*,
+ TracingService::ProducerSMBScrapingMode smb_scraping_mode =
+ TracingService::ProducerSMBScrapingMode::kDefault,
+ size_t shared_memory_size_hint_bytes = 0,
+ size_t shared_memory_page_size_hint_bytes = 0,
+ std::unique_ptr<SharedMemory> shm = nullptr,
+ std::unique_ptr<SharedMemoryArbiter> shm_arbiter = nullptr,
+ CreateSocketAsync create_socket_async = nullptr);
+
+ protected:
+ ProducerIPCClient() = delete;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_PRODUCER_PRODUCER_IPC_CLIENT_IMPL_H_
+#define SRC_TRACING_IPC_PRODUCER_PRODUCER_IPC_CLIENT_IMPL_H_
+
+#include <stdint.h>
+
+#include <set>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/client.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service_proxy.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/producer_port.ipc.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+class Producer;
+class SharedMemoryArbiter;
+
+// Exposes a Service endpoint to Producer(s), proxying all requests through a
+// IPC channel to the remote Service. This class is the glue layer between the
+// generic Service interface exposed to the clients of the library and the
+// actual IPC transport.
+// If create_socket_async is set, it will be called to create and connect to a
+// socket to the service. If unset, the producer will create and connect itself.
+class ProducerIPCClientImpl : public TracingService::ProducerEndpoint,
+ public ipc::ServiceProxy::EventListener {
+ public:
+ ProducerIPCClientImpl(ipc::Client::ConnArgs,
+ Producer*,
+ const std::string& producer_name,
+ base::TaskRunner*,
+ TracingService::ProducerSMBScrapingMode,
+ size_t shared_memory_size_hint_bytes,
+ size_t shared_memory_page_size_hint_bytes,
+ std::unique_ptr<SharedMemory> shm,
+ std::unique_ptr<SharedMemoryArbiter> shm_arbiter,
+ CreateSocketAsync create_socket_async);
+ ~ProducerIPCClientImpl() override;
+
+ // TracingService::ProducerEndpoint implementation.
+ // These methods are invoked by the actual Producer(s) code by clients of the
+ // tracing library, which know nothing about the IPC transport.
+ void Disconnect() override;
+ void RegisterDataSource(const DataSourceDescriptor&) override;
+ void UpdateDataSource(const DataSourceDescriptor&) override;
+ void UnregisterDataSource(const std::string& name) override;
+ void RegisterTraceWriter(uint32_t writer_id, uint32_t target_buffer) override;
+ void UnregisterTraceWriter(uint32_t writer_id) override;
+ void CommitData(const CommitDataRequest&, CommitDataCallback) override;
+ void NotifyDataSourceStarted(DataSourceInstanceID) override;
+ void NotifyDataSourceStopped(DataSourceInstanceID) override;
+ void ActivateTriggers(const std::vector<std::string>&) override;
+ void Sync(std::function<void()> callback) override;
+
+ std::unique_ptr<TraceWriter> CreateTraceWriter(
+ BufferID target_buffer,
+ BufferExhaustedPolicy) override;
+ SharedMemoryArbiter* MaybeSharedMemoryArbiter() override;
+ bool IsShmemProvidedByProducer() const override;
+ void NotifyFlushComplete(FlushRequestID) override;
+ SharedMemory* shared_memory() const override;
+ size_t shared_buffer_page_size_kb() const override;
+
+ // ipc::ServiceProxy::EventListener implementation.
+ // These methods are invoked by the IPC layer, which knows nothing about
+ // tracing, producers and consumers.
+ void OnConnect() override;
+ void OnDisconnect() override;
+
+ ipc::Client* GetClientForTesting() { return ipc_channel_.get(); }
+
+ private:
+ // Drops the provider connection if a protocol error was detected while
+ // processing an IPC command.
+ void ScheduleDisconnect();
+
+ // Invoked soon after having established the connection with the service.
+ void OnConnectionInitialized(bool connection_succeeded,
+ bool using_shmem_provided_by_producer,
+ bool direct_smb_patching_supported,
+ bool use_shmem_emulation);
+
+ // Invoked when the remote Service sends an IPC to tell us to do something
+ // (e.g. start/stop a data source).
+ void OnServiceRequest(const protos::gen::GetAsyncCommandResponse&);
+
+ // TODO think to destruction order, do we rely on any specific dtor sequence?
+ Producer* const producer_;
+ base::TaskRunner* const task_runner_;
+
+ // A callback used to receive the shmem region out of band of the socket.
+ std::function<int(void)> receive_shmem_fd_cb_fuchsia_;
+
+ // The object that owns the client socket and takes care of IPC traffic.
+ std::unique_ptr<ipc::Client> ipc_channel_;
+
+ // The proxy interface for the producer port of the service. It is bound
+ // to |ipc_channel_| and (de)serializes method invocations over the wire.
+ std::unique_ptr<protos::gen::ProducerPortProxy> producer_port_;
+
+ std::unique_ptr<SharedMemory> shared_memory_;
+ std::unique_ptr<SharedMemoryArbiter> shared_memory_arbiter_;
+ size_t shared_buffer_page_size_kb_ = 0;
+ std::set<DataSourceInstanceID> data_sources_setup_;
+ bool connected_ = false;
+ std::string const name_;
+ size_t shared_memory_page_size_hint_bytes_ = 0;
+ size_t shared_memory_size_hint_bytes_ = 0;
+ TracingService::ProducerSMBScrapingMode const smb_scraping_mode_;
+ bool is_shmem_provided_by_producer_ = false;
+ bool direct_smb_patching_supported_ = false;
+ bool use_shmem_emulation_ = false;
+ std::vector<std::function<void()>> pending_sync_reqs_;
+ base::WeakPtrFactory<ProducerIPCClientImpl> weak_factory_{this};
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_IPC_PRODUCER_PRODUCER_IPC_CLIENT_IMPL_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/producer/producer_ipc_client_impl.h"
+
+#include <cinttypes>
+
+#include <string.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/version.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/client.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/commit_data_request.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/producer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_writer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/trace_config.h"
+// gen_amalgamated expanded: #include "src/tracing/core/in_process_shared_memory.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// gen_amalgamated expanded: #include "src/tracing/ipc/shared_memory_windows.h"
+#else
+// gen_amalgamated expanded: #include "src/tracing/ipc/posix_shared_memory.h"
+#endif
+
+// TODO(fmayer): think to what happens when ProducerIPCClientImpl gets destroyed
+// w.r.t. the Producer pointer. Also think to lifetime of the Producer* during
+// the callbacks.
+
+namespace perfetto {
+
+// static. (Declared in include/tracing/ipc/producer_ipc_client.h).
+std::unique_ptr<TracingService::ProducerEndpoint> ProducerIPCClient::Connect(
+ const char* service_sock_name,
+ Producer* producer,
+ const std::string& producer_name,
+ base::TaskRunner* task_runner,
+ TracingService::ProducerSMBScrapingMode smb_scraping_mode,
+ size_t shared_memory_size_hint_bytes,
+ size_t shared_memory_page_size_hint_bytes,
+ std::unique_ptr<SharedMemory> shm,
+ std::unique_ptr<SharedMemoryArbiter> shm_arbiter,
+ ConnectionFlags conn_flags) {
+ return std::unique_ptr<TracingService::ProducerEndpoint>(
+ new ProducerIPCClientImpl(
+ {service_sock_name,
+ conn_flags ==
+ ProducerIPCClient::ConnectionFlags::kRetryIfUnreachable},
+ producer, producer_name, task_runner, smb_scraping_mode,
+ shared_memory_size_hint_bytes, shared_memory_page_size_hint_bytes,
+ std::move(shm), std::move(shm_arbiter), nullptr));
+}
+
+// static. (Declared in include/tracing/ipc/producer_ipc_client.h).
+std::unique_ptr<TracingService::ProducerEndpoint> ProducerIPCClient::Connect(
+ ipc::Client::ConnArgs conn_args,
+ Producer* producer,
+ const std::string& producer_name,
+ base::TaskRunner* task_runner,
+ TracingService::ProducerSMBScrapingMode smb_scraping_mode,
+ size_t shared_memory_size_hint_bytes,
+ size_t shared_memory_page_size_hint_bytes,
+ std::unique_ptr<SharedMemory> shm,
+ std::unique_ptr<SharedMemoryArbiter> shm_arbiter,
+ CreateSocketAsync create_socket_async) {
+ return std::unique_ptr<TracingService::ProducerEndpoint>(
+ new ProducerIPCClientImpl(
+ std::move(conn_args), producer, producer_name, task_runner,
+ smb_scraping_mode, shared_memory_size_hint_bytes,
+ shared_memory_page_size_hint_bytes, std::move(shm),
+ std::move(shm_arbiter), create_socket_async));
+}
+
+ProducerIPCClientImpl::ProducerIPCClientImpl(
+ ipc::Client::ConnArgs conn_args,
+ Producer* producer,
+ const std::string& producer_name,
+ base::TaskRunner* task_runner,
+ TracingService::ProducerSMBScrapingMode smb_scraping_mode,
+ size_t shared_memory_size_hint_bytes,
+ size_t shared_memory_page_size_hint_bytes,
+ std::unique_ptr<SharedMemory> shm,
+ std::unique_ptr<SharedMemoryArbiter> shm_arbiter,
+ CreateSocketAsync create_socket_async)
+ : producer_(producer),
+ task_runner_(task_runner),
+ receive_shmem_fd_cb_fuchsia_(
+ std::move(conn_args.receive_shmem_fd_cb_fuchsia)),
+ producer_port_(
+ new protos::gen::ProducerPortProxy(this /* event_listener */)),
+ shared_memory_(std::move(shm)),
+ shared_memory_arbiter_(std::move(shm_arbiter)),
+ name_(producer_name),
+ shared_memory_page_size_hint_bytes_(shared_memory_page_size_hint_bytes),
+ shared_memory_size_hint_bytes_(shared_memory_size_hint_bytes),
+ smb_scraping_mode_(smb_scraping_mode) {
+ // Check for producer-provided SMB (used by Chrome for startup tracing).
+ if (shared_memory_) {
+ // We also expect a valid (unbound) arbiter. Bind it to this endpoint now.
+ PERFETTO_CHECK(shared_memory_arbiter_);
+ shared_memory_arbiter_->BindToProducerEndpoint(this, task_runner_);
+
+ // If the service accepts our SMB, then it must match our requested page
+ // layout. The protocol doesn't allow the service to change the size and
+ // layout when the SMB is provided by the producer.
+ shared_buffer_page_size_kb_ = shared_memory_page_size_hint_bytes_ / 1024;
+ }
+
+ if (create_socket_async) {
+ PERFETTO_DCHECK(conn_args.socket_name);
+ auto weak_this = weak_factory_.GetWeakPtr();
+ create_socket_async(
+ [weak_this, task_runner = task_runner_](base::SocketHandle fd) {
+ task_runner->PostTask([weak_this, fd] {
+ base::ScopedSocketHandle handle(fd);
+ if (!weak_this) {
+ return;
+ }
+ ipc::Client::ConnArgs args(std::move(handle));
+ weak_this->ipc_channel_ = ipc::Client::CreateInstance(
+ std::move(args), weak_this->task_runner_);
+ weak_this->ipc_channel_->BindService(
+ weak_this->producer_port_->GetWeakPtr());
+ });
+ });
+ } else {
+ ipc_channel_ =
+ ipc::Client::CreateInstance(std::move(conn_args), task_runner);
+ ipc_channel_->BindService(producer_port_->GetWeakPtr());
+ }
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+}
+
+ProducerIPCClientImpl::~ProducerIPCClientImpl() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+}
+
+void ProducerIPCClientImpl::Disconnect() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!producer_port_)
+ return;
+ // Reset the producer port so that no further IPCs are received and IPC
+ // callbacks are no longer executed. Also reset the IPC channel so that the
+ // service is notified of the disconnection.
+ producer_port_.reset();
+ ipc_channel_.reset();
+ // Perform disconnect synchronously.
+ OnDisconnect();
+}
+
+// Called by the IPC layer if the BindService() succeeds.
+void ProducerIPCClientImpl::OnConnect() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ connected_ = true;
+
+ // The IPC layer guarantees that any outstanding callback will be dropped on
+ // the floor if producer_port_ is destroyed between the request and the reply.
+ // Binding |this| is hence safe.
+ ipc::Deferred<protos::gen::InitializeConnectionResponse> on_init;
+ on_init.Bind(
+ [this](ipc::AsyncResult<protos::gen::InitializeConnectionResponse> resp) {
+ OnConnectionInitialized(
+ resp.success(),
+ resp.success() ? resp->using_shmem_provided_by_producer() : false,
+ resp.success() ? resp->direct_smb_patching_supported() : false,
+ resp.success() ? resp->use_shmem_emulation() : false);
+ });
+ protos::gen::InitializeConnectionRequest req;
+ req.set_producer_name(name_);
+ req.set_shared_memory_size_hint_bytes(
+ static_cast<uint32_t>(shared_memory_size_hint_bytes_));
+ req.set_shared_memory_page_size_hint_bytes(
+ static_cast<uint32_t>(shared_memory_page_size_hint_bytes_));
+ switch (smb_scraping_mode_) {
+ case TracingService::ProducerSMBScrapingMode::kDefault:
+ // No need to set the mode, it defaults to use the service default if
+ // unspecified.
+ break;
+ case TracingService::ProducerSMBScrapingMode::kEnabled:
+ req.set_smb_scraping_mode(
+ protos::gen::InitializeConnectionRequest::SMB_SCRAPING_ENABLED);
+ break;
+ case TracingService::ProducerSMBScrapingMode::kDisabled:
+ req.set_smb_scraping_mode(
+ protos::gen::InitializeConnectionRequest::SMB_SCRAPING_DISABLED);
+ break;
+ }
+
+ int shm_fd = -1;
+ if (shared_memory_) {
+ req.set_producer_provided_shmem(true);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ auto key = static_cast<SharedMemoryWindows*>(shared_memory_.get())->key();
+ req.set_shm_key_windows(key);
+#else
+ shm_fd = static_cast<PosixSharedMemory*>(shared_memory_.get())->fd();
+#endif
+ }
+
+ req.set_sdk_version(base::GetVersionString());
+ producer_port_->InitializeConnection(req, std::move(on_init), shm_fd);
+
+ // Create the back channel to receive commands from the Service.
+ ipc::Deferred<protos::gen::GetAsyncCommandResponse> on_cmd;
+ on_cmd.Bind(
+ [this](ipc::AsyncResult<protos::gen::GetAsyncCommandResponse> resp) {
+ if (!resp)
+ return; // The IPC channel was closed and |resp| was auto-rejected.
+ OnServiceRequest(*resp);
+ });
+ producer_port_->GetAsyncCommand(protos::gen::GetAsyncCommandRequest(),
+ std::move(on_cmd));
+
+ // If there are pending Sync() requests, send them now.
+ for (const auto& pending_sync : pending_sync_reqs_)
+ Sync(std::move(pending_sync));
+ pending_sync_reqs_.clear();
+}
+
+void ProducerIPCClientImpl::OnDisconnect() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ PERFETTO_DLOG("Tracing service connection failure");
+ connected_ = false;
+ data_sources_setup_.clear();
+ producer_->OnDisconnect(); // Note: may delete |this|.
+}
+
+void ProducerIPCClientImpl::ScheduleDisconnect() {
+ // |ipc_channel| doesn't allow disconnection in the middle of handling
+ // an IPC call, so the connection drop must take place over two phases.
+
+ // First, synchronously drop the |producer_port_| so that no more IPC
+ // messages are handled.
+ producer_port_.reset();
+
+ // Then schedule an async task for performing the remainder of the
+ // disconnection operations outside the context of the IPC method handler.
+ auto weak_this = weak_factory_.GetWeakPtr();
+ task_runner_->PostTask([weak_this]() {
+ if (weak_this) {
+ weak_this->Disconnect();
+ }
+ });
+}
+
+void ProducerIPCClientImpl::OnConnectionInitialized(
+ bool connection_succeeded,
+ bool using_shmem_provided_by_producer,
+ bool direct_smb_patching_supported,
+ bool use_shmem_emulation) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ // If connection_succeeded == false, the OnDisconnect() call will follow next
+ // and there we'll notify the |producer_|. TODO: add a test for this.
+ if (!connection_succeeded)
+ return;
+ is_shmem_provided_by_producer_ = using_shmem_provided_by_producer;
+ direct_smb_patching_supported_ = direct_smb_patching_supported;
+ // The tracing service may reject using shared memory and tell the client to
+ // commit data over the socket. This can happen when the client connects to
+ // the service via a relay service:
+ // client <-Unix socket-> relay service <- vsock -> tracing service.
+ use_shmem_emulation_ = use_shmem_emulation;
+ producer_->OnConnect();
+
+ // Bail out if the service failed to adopt our producer-allocated SMB.
+ // TODO(eseckler): Handle adoption failure more gracefully.
+ if (shared_memory_ && !is_shmem_provided_by_producer_) {
+ PERFETTO_DLOG("Service failed adopt producer-provided SMB, disconnecting.");
+ Disconnect();
+ return;
+ }
+}
+
+void ProducerIPCClientImpl::OnServiceRequest(
+ const protos::gen::GetAsyncCommandResponse& cmd) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+
+ // This message is sent only when connecting to a service running Android Q+.
+ // See comment below in kStartDataSource.
+ if (cmd.has_setup_data_source()) {
+ const auto& req = cmd.setup_data_source();
+ const DataSourceInstanceID dsid = req.new_instance_id();
+ data_sources_setup_.insert(dsid);
+ producer_->SetupDataSource(dsid, req.config());
+ return;
+ }
+
+ if (cmd.has_start_data_source()) {
+ const auto& req = cmd.start_data_source();
+ const DataSourceInstanceID dsid = req.new_instance_id();
+ const DataSourceConfig& cfg = req.config();
+ if (!data_sources_setup_.count(dsid)) {
+ // When connecting with an older (Android P) service, the service will not
+ // send a SetupDataSource message. We synthesize it here in that case.
+ producer_->SetupDataSource(dsid, cfg);
+ }
+ producer_->StartDataSource(dsid, cfg);
+ return;
+ }
+
+ if (cmd.has_stop_data_source()) {
+ const DataSourceInstanceID dsid = cmd.stop_data_source().instance_id();
+ producer_->StopDataSource(dsid);
+ data_sources_setup_.erase(dsid);
+ return;
+ }
+
+ if (cmd.has_setup_tracing()) {
+ std::unique_ptr<SharedMemory> ipc_shared_memory;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ const std::string& shm_key = cmd.setup_tracing().shm_key_windows();
+ if (!shm_key.empty())
+ ipc_shared_memory = SharedMemoryWindows::Attach(shm_key);
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+ // On Fuchsia, the embedder is responsible for routing the shared memory
+ // FD, which is provided to this code via a blocking callback.
+ PERFETTO_CHECK(receive_shmem_fd_cb_fuchsia_);
+
+ base::ScopedFile shmem_fd(receive_shmem_fd_cb_fuchsia_());
+ if (!shmem_fd) {
+ // Failure to get a shared memory buffer is a protocol violation and
+ // therefore we should drop the Protocol connection.
+ PERFETTO_ELOG("Could not get shared memory FD from embedder.");
+ ScheduleDisconnect();
+ return;
+ }
+
+ ipc_shared_memory =
+ PosixSharedMemory::AttachToFd(std::move(shmem_fd),
+ /*require_seals_if_supported=*/false);
+#else
+ base::ScopedFile shmem_fd = ipc_channel_->TakeReceivedFD();
+ if (shmem_fd) {
+ // TODO(primiano): handle mmap failure in case of OOM.
+ ipc_shared_memory =
+ PosixSharedMemory::AttachToFd(std::move(shmem_fd),
+ /*require_seals_if_supported=*/false);
+ }
+#endif
+ if (use_shmem_emulation_) {
+ PERFETTO_CHECK(!ipc_shared_memory);
+ // Need to create an emulated shmem buffer when the transport deosn't
+ // support it.
+ // TODO(chinglinyu): Let the tracing service decide on the shmem size and
+ // propagate the size in InitializeConnectionResponse.
+ ipc_shared_memory = InProcessSharedMemory::Create(
+ /*size=*/InProcessSharedMemory::kDefaultSize);
+ }
+ if (ipc_shared_memory) {
+ auto shmem_mode = use_shmem_emulation_
+ ? SharedMemoryABI::ShmemMode::kShmemEmulation
+ : SharedMemoryABI::ShmemMode::kDefault;
+ // This is the nominal case used in most configurations, where the service
+ // provides the SMB.
+ PERFETTO_CHECK(!is_shmem_provided_by_producer_ && !shared_memory_);
+ shared_memory_ = std::move(ipc_shared_memory);
+ shared_buffer_page_size_kb_ =
+ cmd.setup_tracing().shared_buffer_page_size_kb();
+ shared_memory_arbiter_ = SharedMemoryArbiter::CreateInstance(
+ shared_memory_.get(), shared_buffer_page_size_kb_ * 1024, shmem_mode,
+ this, task_runner_);
+ if (direct_smb_patching_supported_)
+ shared_memory_arbiter_->SetDirectSMBPatchingSupportedByService();
+ } else {
+ // Producer-provided SMB (used by Chrome for startup tracing).
+ PERFETTO_CHECK(is_shmem_provided_by_producer_ && shared_memory_ &&
+ shared_memory_arbiter_);
+ }
+ producer_->OnTracingSetup();
+ return;
+ }
+
+ if (cmd.has_flush()) {
+ // This cast boilerplate is required only because protobuf uses its own
+ // uint64 and not stdint's uint64_t. On some 64 bit archs they differ on the
+ // type (long vs long long) even though they have the same size.
+ const auto* data_source_ids = cmd.flush().data_source_ids().data();
+ static_assert(sizeof(data_source_ids[0]) == sizeof(DataSourceInstanceID),
+ "data_source_ids should be 64-bit");
+
+ FlushFlags flags(cmd.flush().flags());
+ producer_->Flush(
+ cmd.flush().request_id(),
+ reinterpret_cast<const DataSourceInstanceID*>(data_source_ids),
+ static_cast<size_t>(cmd.flush().data_source_ids().size()), flags);
+ return;
+ }
+
+ if (cmd.has_clear_incremental_state()) {
+ const auto* data_source_ids =
+ cmd.clear_incremental_state().data_source_ids().data();
+ static_assert(sizeof(data_source_ids[0]) == sizeof(DataSourceInstanceID),
+ "data_source_ids should be 64-bit");
+ producer_->ClearIncrementalState(
+ reinterpret_cast<const DataSourceInstanceID*>(data_source_ids),
+ static_cast<size_t>(
+ cmd.clear_incremental_state().data_source_ids().size()));
+ return;
+ }
+
+ PERFETTO_DFATAL("Unknown async request received from tracing service");
+}
+
+void ProducerIPCClientImpl::RegisterDataSource(
+ const DataSourceDescriptor& descriptor) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot RegisterDataSource(), not connected to tracing service");
+ }
+ protos::gen::RegisterDataSourceRequest req;
+ *req.mutable_data_source_descriptor() = descriptor;
+ ipc::Deferred<protos::gen::RegisterDataSourceResponse> async_response;
+ async_response.Bind(
+ [](ipc::AsyncResult<protos::gen::RegisterDataSourceResponse> response) {
+ if (!response)
+ PERFETTO_DLOG("RegisterDataSource() failed: connection reset");
+ });
+ producer_port_->RegisterDataSource(req, std::move(async_response));
+}
+
+void ProducerIPCClientImpl::UpdateDataSource(
+ const DataSourceDescriptor& descriptor) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot UpdateDataSource(), not connected to tracing service");
+ }
+ protos::gen::UpdateDataSourceRequest req;
+ *req.mutable_data_source_descriptor() = descriptor;
+ ipc::Deferred<protos::gen::UpdateDataSourceResponse> async_response;
+ async_response.Bind(
+ [](ipc::AsyncResult<protos::gen::UpdateDataSourceResponse> response) {
+ if (!response)
+ PERFETTO_DLOG("UpdateDataSource() failed: connection reset");
+ });
+ producer_port_->UpdateDataSource(req, std::move(async_response));
+}
+
+void ProducerIPCClientImpl::UnregisterDataSource(const std::string& name) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot UnregisterDataSource(), not connected to tracing service");
+ return;
+ }
+ protos::gen::UnregisterDataSourceRequest req;
+ req.set_data_source_name(name);
+ producer_port_->UnregisterDataSource(
+ req, ipc::Deferred<protos::gen::UnregisterDataSourceResponse>());
+}
+
+void ProducerIPCClientImpl::RegisterTraceWriter(uint32_t writer_id,
+ uint32_t target_buffer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot RegisterTraceWriter(), not connected to tracing service");
+ return;
+ }
+ protos::gen::RegisterTraceWriterRequest req;
+ req.set_trace_writer_id(writer_id);
+ req.set_target_buffer(target_buffer);
+ producer_port_->RegisterTraceWriter(
+ req, ipc::Deferred<protos::gen::RegisterTraceWriterResponse>());
+}
+
+void ProducerIPCClientImpl::UnregisterTraceWriter(uint32_t writer_id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot UnregisterTraceWriter(), not connected to tracing service");
+ return;
+ }
+ protos::gen::UnregisterTraceWriterRequest req;
+ req.set_trace_writer_id(writer_id);
+ producer_port_->UnregisterTraceWriter(
+ req, ipc::Deferred<protos::gen::UnregisterTraceWriterResponse>());
+}
+
+void ProducerIPCClientImpl::CommitData(const CommitDataRequest& req,
+ CommitDataCallback callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG("Cannot CommitData(), not connected to tracing service");
+ return;
+ }
+ ipc::Deferred<protos::gen::CommitDataResponse> async_response;
+ // TODO(primiano): add a test that destroys ProducerIPCClientImpl soon after
+ // this call and checks that the callback is dropped.
+ if (callback) {
+ async_response.Bind(
+ [callback](ipc::AsyncResult<protos::gen::CommitDataResponse> response) {
+ if (!response) {
+ PERFETTO_DLOG("CommitData() failed: connection reset");
+ return;
+ }
+ callback();
+ });
+ }
+ producer_port_->CommitData(req, std::move(async_response));
+}
+
+void ProducerIPCClientImpl::NotifyDataSourceStarted(DataSourceInstanceID id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot NotifyDataSourceStarted(), not connected to tracing service");
+ return;
+ }
+ protos::gen::NotifyDataSourceStartedRequest req;
+ req.set_data_source_id(id);
+ producer_port_->NotifyDataSourceStarted(
+ req, ipc::Deferred<protos::gen::NotifyDataSourceStartedResponse>());
+}
+
+void ProducerIPCClientImpl::NotifyDataSourceStopped(DataSourceInstanceID id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot NotifyDataSourceStopped(), not connected to tracing service");
+ return;
+ }
+ protos::gen::NotifyDataSourceStoppedRequest req;
+ req.set_data_source_id(id);
+ producer_port_->NotifyDataSourceStopped(
+ req, ipc::Deferred<protos::gen::NotifyDataSourceStoppedResponse>());
+}
+
+void ProducerIPCClientImpl::ActivateTriggers(
+ const std::vector<std::string>& triggers) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ PERFETTO_DLOG(
+ "Cannot ActivateTriggers(), not connected to tracing service");
+ return;
+ }
+ protos::gen::ActivateTriggersRequest proto_req;
+ for (const auto& name : triggers) {
+ *proto_req.add_trigger_names() = name;
+ }
+ producer_port_->ActivateTriggers(
+ proto_req, ipc::Deferred<protos::gen::ActivateTriggersResponse>());
+}
+
+void ProducerIPCClientImpl::Sync(std::function<void()> callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
+ if (!connected_) {
+ pending_sync_reqs_.emplace_back(std::move(callback));
+ return;
+ }
+ ipc::Deferred<protos::gen::SyncResponse> resp;
+ resp.Bind([callback](ipc::AsyncResult<protos::gen::SyncResponse>) {
+ // Here we ACK the callback even if the service replies with a failure
+ // (i.e. the service is too old and doesn't understand Sync()). In that
+ // case the service has still seen the request, the IPC roundtrip is
+ // still a (weaker) linearization fence.
+ callback();
+ });
+ producer_port_->Sync(protos::gen::SyncRequest(), std::move(resp));
+}
+
+std::unique_ptr<TraceWriter> ProducerIPCClientImpl::CreateTraceWriter(
+ BufferID target_buffer,
+ BufferExhaustedPolicy buffer_exhausted_policy) {
+ // This method can be called by different threads. |shared_memory_arbiter_| is
+ // thread-safe but be aware of accessing any other state in this function.
+ return shared_memory_arbiter_->CreateTraceWriter(target_buffer,
+ buffer_exhausted_policy);
+}
+
+SharedMemoryArbiter* ProducerIPCClientImpl::MaybeSharedMemoryArbiter() {
+ return shared_memory_arbiter_.get();
+}
+
+bool ProducerIPCClientImpl::IsShmemProvidedByProducer() const {
+ return is_shmem_provided_by_producer_;
+}
+
+void ProducerIPCClientImpl::NotifyFlushComplete(FlushRequestID req_id) {
+ return shared_memory_arbiter_->NotifyFlushComplete(req_id);
+}
+
+SharedMemory* ProducerIPCClientImpl::shared_memory() const {
+ return shared_memory_.get();
+}
+
+size_t ProducerIPCClientImpl::shared_buffer_page_size_kb() const {
+ return shared_buffer_page_size_kb_;
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/ipc/service/consumer_ipc_service.cc
+// gen_amalgamated begin header: src/tracing/ipc/service/consumer_ipc_service.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_SERVICE_CONSUMER_IPC_SERVICE_H_
+#define SRC_TRACING_IPC_SERVICE_CONSUMER_IPC_SERVICE_H_
+
+#include <list>
+#include <map>
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/consumer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/consumer_port.ipc.h"
+
+namespace perfetto {
+
+namespace ipc {
+class Host;
+} // namespace ipc
+
+// Implements the Consumer port of the IPC service. This class proxies requests
+// and responses between the core service logic (|svc_|) and remote Consumer(s)
+// on the IPC socket, through the methods overriddden from ConsumerPort.
+class ConsumerIPCService : public protos::gen::ConsumerPort {
+ public:
+ explicit ConsumerIPCService(TracingService* core_service);
+ ~ConsumerIPCService() override;
+
+ // ConsumerPort implementation (from .proto IPC definition).
+ void EnableTracing(const protos::gen::EnableTracingRequest&,
+ DeferredEnableTracingResponse) override;
+ void StartTracing(const protos::gen::StartTracingRequest&,
+ DeferredStartTracingResponse) override;
+ void ChangeTraceConfig(const protos::gen::ChangeTraceConfigRequest&,
+ DeferredChangeTraceConfigResponse) override;
+ void DisableTracing(const protos::gen::DisableTracingRequest&,
+ DeferredDisableTracingResponse) override;
+ void ReadBuffers(const protos::gen::ReadBuffersRequest&,
+ DeferredReadBuffersResponse) override;
+ void FreeBuffers(const protos::gen::FreeBuffersRequest&,
+ DeferredFreeBuffersResponse) override;
+ void Flush(const protos::gen::FlushRequest&, DeferredFlushResponse) override;
+ void Detach(const protos::gen::DetachRequest&,
+ DeferredDetachResponse) override;
+ void Attach(const protos::gen::AttachRequest&,
+ DeferredAttachResponse) override;
+ void GetTraceStats(const protos::gen::GetTraceStatsRequest&,
+ DeferredGetTraceStatsResponse) override;
+ void ObserveEvents(const protos::gen::ObserveEventsRequest&,
+ DeferredObserveEventsResponse) override;
+ void QueryServiceState(const protos::gen::QueryServiceStateRequest&,
+ DeferredQueryServiceStateResponse) override;
+ void QueryCapabilities(const protos::gen::QueryCapabilitiesRequest&,
+ DeferredQueryCapabilitiesResponse) override;
+ void SaveTraceForBugreport(const protos::gen::SaveTraceForBugreportRequest&,
+ DeferredSaveTraceForBugreportResponse) override;
+ void CloneSession(const protos::gen::CloneSessionRequest&,
+ DeferredCloneSessionResponse) override;
+ void OnClientDisconnected() override;
+
+ private:
+ // Acts like a Consumer with the core Service business logic (which doesn't
+ // know anything about the remote transport), but all it does is proxying
+ // methods to the remote Consumer on the other side of the IPC channel.
+ class RemoteConsumer : public Consumer {
+ public:
+ RemoteConsumer();
+ ~RemoteConsumer() override;
+
+ // These methods are called by the |core_service_| business logic. There is
+ // no connection here, these methods are posted straight away.
+ void OnConnect() override;
+ void OnDisconnect() override;
+ void OnTracingDisabled(const std::string& error) override;
+ void OnTraceData(std::vector<TracePacket>, bool has_more) override;
+ void OnDetach(bool) override;
+ void OnAttach(bool, const TraceConfig&) override;
+ void OnTraceStats(bool, const TraceStats&) override;
+ void OnObservableEvents(const ObservableEvents&) override;
+ void OnSessionCloned(const OnSessionClonedArgs&) override;
+
+ void CloseObserveEventsResponseStream();
+
+ // The interface obtained from the core service business logic through
+ // TracingService::ConnectConsumer(this). This allows to invoke methods for
+ // a specific Consumer on the Service business logic.
+ std::unique_ptr<TracingService::ConsumerEndpoint> service_endpoint;
+
+ // After ReadBuffers() is invoked, this binds the async callback that
+ // allows to stream trace packets back to the client.
+ DeferredReadBuffersResponse read_buffers_response;
+
+ // After EnableTracing() is invoked, this binds the async callback that
+ // allows to send the OnTracingDisabled notification.
+ DeferredEnableTracingResponse enable_tracing_response;
+
+ // After Detach() is invoked, this binds the async callback that allows to
+ // send the session id to the consumer.
+ DeferredDetachResponse detach_response;
+
+ // As above, but for the Attach() case.
+ DeferredAttachResponse attach_response;
+
+ // As above, but for GetTraceStats().
+ DeferredGetTraceStatsResponse get_trace_stats_response;
+
+ // As above, but for CloneSession().
+ DeferredCloneSessionResponse clone_session_response;
+
+ // After ObserveEvents() is invoked, this binds the async callback that
+ // allows to stream ObservableEvents back to the client.
+ DeferredObserveEventsResponse observe_events_response;
+ };
+
+ // This has to be a container that doesn't invalidate iterators.
+ using PendingFlushResponses = std::list<DeferredFlushResponse>;
+ using PendingQuerySvcResponses = std::list<DeferredQueryServiceStateResponse>;
+ using PendingQueryCapabilitiesResponses =
+ std::list<DeferredQueryCapabilitiesResponse>;
+ using PendingSaveTraceForBugreportResponses =
+ std::list<DeferredSaveTraceForBugreportResponse>;
+
+ ConsumerIPCService(const ConsumerIPCService&) = delete;
+ ConsumerIPCService& operator=(const ConsumerIPCService&) = delete;
+
+ // Returns the ConsumerEndpoint in the core business logic that corresponds to
+ // the current IPC request.
+ RemoteConsumer* GetConsumerForCurrentRequest();
+
+ void OnFlushCallback(bool success, PendingFlushResponses::iterator);
+ void OnQueryServiceCallback(bool success,
+ const TracingServiceState&,
+ PendingQuerySvcResponses::iterator);
+ void OnQueryCapabilitiesCallback(const TracingServiceCapabilities&,
+ PendingQueryCapabilitiesResponses::iterator);
+ void OnSaveTraceForBugreportCallback(
+ bool success,
+ const std::string& msg,
+ PendingSaveTraceForBugreportResponses::iterator);
+
+ TracingService* const core_service_;
+
+ // Maps IPC clients to ConsumerEndpoint instances registered on the
+ // |core_service_| business logic.
+ std::map<ipc::ClientID, std::unique_ptr<RemoteConsumer>> consumers_;
+
+ PendingFlushResponses pending_flush_responses_;
+ PendingQuerySvcResponses pending_query_service_responses_;
+ PendingQueryCapabilitiesResponses pending_query_capabilities_responses_;
+ PendingSaveTraceForBugreportResponses pending_bugreport_responses_;
+
+ base::WeakPtrFactory<ConsumerIPCService> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_IPC_SERVICE_CONSUMER_IPC_SERVICE_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/service/consumer_ipc_service.h"
+
+#include <cinttypes>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/host.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/shared_memory_abi.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/slice.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_packet.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/trace_stats.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/trace_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/tracing_service_capabilities.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/tracing_service_state.h"
+
+namespace perfetto {
+
+ConsumerIPCService::ConsumerIPCService(TracingService* core_service)
+ : core_service_(core_service), weak_ptr_factory_(this) {}
+
+ConsumerIPCService::~ConsumerIPCService() = default;
+
+ConsumerIPCService::RemoteConsumer*
+ConsumerIPCService::GetConsumerForCurrentRequest() {
+ const ipc::ClientID ipc_client_id = ipc::Service::client_info().client_id();
+ const uid_t uid = ipc::Service::client_info().uid();
+ PERFETTO_CHECK(ipc_client_id);
+ auto it = consumers_.find(ipc_client_id);
+ if (it == consumers_.end()) {
+ auto* remote_consumer = new RemoteConsumer();
+ consumers_[ipc_client_id].reset(remote_consumer);
+ remote_consumer->service_endpoint =
+ core_service_->ConnectConsumer(remote_consumer, uid);
+ return remote_consumer;
+ }
+ return it->second.get();
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::OnClientDisconnected() {
+ ipc::ClientID client_id = ipc::Service::client_info().client_id();
+ consumers_.erase(client_id);
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::EnableTracing(
+ const protos::gen::EnableTracingRequest& req,
+ DeferredEnableTracingResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ if (req.attach_notification_only()) {
+ remote_consumer->enable_tracing_response = std::move(resp);
+ return;
+ }
+ const TraceConfig& trace_config = req.trace_config();
+ base::ScopedFile fd;
+ if (trace_config.write_into_file() && trace_config.output_path().empty())
+ fd = ipc::Service::TakeReceivedFD();
+ remote_consumer->service_endpoint->EnableTracing(trace_config, std::move(fd));
+ remote_consumer->enable_tracing_response = std::move(resp);
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::StartTracing(const protos::gen::StartTracingRequest&,
+ DeferredStartTracingResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ remote_consumer->service_endpoint->StartTracing();
+ resp.Resolve(ipc::AsyncResult<protos::gen::StartTracingResponse>::Create());
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::ChangeTraceConfig(
+ const protos::gen::ChangeTraceConfigRequest& req,
+ DeferredChangeTraceConfigResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ remote_consumer->service_endpoint->ChangeTraceConfig(req.trace_config());
+ resp.Resolve(
+ ipc::AsyncResult<protos::gen::ChangeTraceConfigResponse>::Create());
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::DisableTracing(
+ const protos::gen::DisableTracingRequest&,
+ DeferredDisableTracingResponse resp) {
+ GetConsumerForCurrentRequest()->service_endpoint->DisableTracing();
+ resp.Resolve(ipc::AsyncResult<protos::gen::DisableTracingResponse>::Create());
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::ReadBuffers(const protos::gen::ReadBuffersRequest&,
+ DeferredReadBuffersResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ remote_consumer->read_buffers_response = std::move(resp);
+ remote_consumer->service_endpoint->ReadBuffers();
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::FreeBuffers(const protos::gen::FreeBuffersRequest&,
+ DeferredFreeBuffersResponse resp) {
+ GetConsumerForCurrentRequest()->service_endpoint->FreeBuffers();
+ resp.Resolve(ipc::AsyncResult<protos::gen::FreeBuffersResponse>::Create());
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::Flush(const protos::gen::FlushRequest& req,
+ DeferredFlushResponse resp) {
+ auto it = pending_flush_responses_.insert(pending_flush_responses_.end(),
+ std::move(resp));
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ auto callback = [weak_this, it](bool success) {
+ if (weak_this)
+ weak_this->OnFlushCallback(success, std::move(it));
+ };
+ FlushFlags flags(req.flags());
+ GetConsumerForCurrentRequest()->service_endpoint->Flush(
+ req.timeout_ms(), std::move(callback), flags);
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::Detach(const protos::gen::DetachRequest& req,
+ DeferredDetachResponse resp) {
+ // OnDetach() will resolve the |detach_response|.
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ remote_consumer->detach_response = std::move(resp);
+ remote_consumer->service_endpoint->Detach(req.key());
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::Attach(const protos::gen::AttachRequest& req,
+ DeferredAttachResponse resp) {
+ // OnAttach() will resolve the |attach_response|.
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ remote_consumer->attach_response = std::move(resp);
+ remote_consumer->service_endpoint->Attach(req.key());
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::GetTraceStats(const protos::gen::GetTraceStatsRequest&,
+ DeferredGetTraceStatsResponse resp) {
+ // OnTraceStats() will resolve the |get_trace_stats_response|.
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ remote_consumer->get_trace_stats_response = std::move(resp);
+ remote_consumer->service_endpoint->GetTraceStats();
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::ObserveEvents(
+ const protos::gen::ObserveEventsRequest& req,
+ DeferredObserveEventsResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+
+ // If there's a prior stream, close it so that client can clean it up.
+ remote_consumer->CloseObserveEventsResponseStream();
+
+ remote_consumer->observe_events_response = std::move(resp);
+
+ uint32_t events_mask = 0;
+ for (const auto& type : req.events_to_observe()) {
+ events_mask |= static_cast<uint32_t>(type);
+ }
+ remote_consumer->service_endpoint->ObserveEvents(events_mask);
+
+ // If no events are to be observed, close the stream immediately so that the
+ // client can clean up.
+ if (events_mask == 0)
+ remote_consumer->CloseObserveEventsResponseStream();
+}
+
+// Called by the IPC layer.
+void ConsumerIPCService::QueryServiceState(
+ const protos::gen::QueryServiceStateRequest& req,
+ DeferredQueryServiceStateResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ auto it = pending_query_service_responses_.insert(
+ pending_query_service_responses_.end(), std::move(resp));
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ auto callback = [weak_this, it](bool success,
+ const TracingServiceState& svc_state) {
+ if (weak_this)
+ weak_this->OnQueryServiceCallback(success, svc_state, std::move(it));
+ };
+ ConsumerEndpoint::QueryServiceStateArgs args;
+ args.sessions_only = req.sessions_only();
+ remote_consumer->service_endpoint->QueryServiceState(args, callback);
+}
+
+// Called by the service in response to service_endpoint->QueryServiceState().
+void ConsumerIPCService::OnQueryServiceCallback(
+ bool success,
+ const TracingServiceState& svc_state,
+ PendingQuerySvcResponses::iterator pending_response_it) {
+ DeferredQueryServiceStateResponse response(std::move(*pending_response_it));
+ pending_query_service_responses_.erase(pending_response_it);
+ if (!success) {
+ response.Reject();
+ return;
+ }
+
+ // The TracingServiceState object might be too big to fit into a single IPC
+ // message because it contains the DataSourceDescriptor of each data source.
+ // Here we split it in chunks to fit in the IPC limit, observing the
+ // following rule: each chunk must be invididually a valid TracingServiceState
+ // message; all the chunks concatenated together must form the original
+ // message. This is to deal with the legacy API that was just sending one
+ // whole message (failing in presence of too many data sources, b/153142114).
+ // The message is split as follows: we take the whole TracingServiceState,
+ // take out the data sources section (which is a top-level repeated field)
+ // and re-add them one-by-one. If, in the process of appending, the IPC msg
+ // size is reached, a new chunk is created. This assumes that the rest of
+ // TracingServiceState fits in one IPC message and each DataSourceDescriptor
+ // fits in the worst case in a dedicated message (which is true, because
+ // otherwise the RegisterDataSource() which passes the descriptor in the first
+ // place would fail).
+
+ std::vector<uint8_t> chunked_reply;
+
+ // Transmits the current chunk and starts a new one.
+ bool sent_eof = false;
+ auto send_chunked_reply = [&chunked_reply, &response,
+ &sent_eof](bool has_more) {
+ PERFETTO_CHECK(!sent_eof);
+ sent_eof = !has_more;
+ auto resp =
+ ipc::AsyncResult<protos::gen::QueryServiceStateResponse>::Create();
+ resp.set_has_more(has_more);
+ PERFETTO_CHECK(resp->mutable_service_state()->ParseFromArray(
+ chunked_reply.data(), chunked_reply.size()));
+ chunked_reply.clear();
+ response.Resolve(std::move(resp));
+ };
+
+ // Create a copy of the whole response and cut away the data_sources section.
+ protos::gen::TracingServiceState svc_state_copy = svc_state;
+ auto data_sources = std::move(*svc_state_copy.mutable_data_sources());
+ chunked_reply = svc_state_copy.SerializeAsArray();
+
+ // Now re-add them fitting within the IPC message limits (- some margin for
+ // the outer IPC frame).
+ constexpr size_t kMaxMsgSize = ipc::kIPCBufferSize - 128;
+ for (const auto& data_source : data_sources) {
+ protos::gen::TracingServiceState tmp;
+ tmp.mutable_data_sources()->emplace_back(std::move(data_source));
+ std::vector<uint8_t> chunk = tmp.SerializeAsArray();
+ if (chunked_reply.size() + chunk.size() < kMaxMsgSize) {
+ chunked_reply.insert(chunked_reply.end(), chunk.begin(), chunk.end());
+ } else {
+ send_chunked_reply(/*has_more=*/true);
+ chunked_reply = std::move(chunk);
+ }
+ }
+
+ PERFETTO_DCHECK(!chunked_reply.empty());
+ send_chunked_reply(/*has_more=*/false);
+ PERFETTO_CHECK(sent_eof);
+}
+
+// Called by the service in response to a service_endpoint->Flush() request.
+void ConsumerIPCService::OnFlushCallback(
+ bool success,
+ PendingFlushResponses::iterator pending_response_it) {
+ DeferredFlushResponse response(std::move(*pending_response_it));
+ pending_flush_responses_.erase(pending_response_it);
+ if (success) {
+ response.Resolve(ipc::AsyncResult<protos::gen::FlushResponse>::Create());
+ } else {
+ response.Reject();
+ }
+}
+
+void ConsumerIPCService::QueryCapabilities(
+ const protos::gen::QueryCapabilitiesRequest&,
+ DeferredQueryCapabilitiesResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ auto it = pending_query_capabilities_responses_.insert(
+ pending_query_capabilities_responses_.end(), std::move(resp));
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ auto callback = [weak_this, it](const TracingServiceCapabilities& caps) {
+ if (weak_this)
+ weak_this->OnQueryCapabilitiesCallback(caps, std::move(it));
+ };
+ remote_consumer->service_endpoint->QueryCapabilities(callback);
+}
+
+// Called by the service in response to service_endpoint->QueryCapabilities().
+void ConsumerIPCService::OnQueryCapabilitiesCallback(
+ const TracingServiceCapabilities& caps,
+ PendingQueryCapabilitiesResponses::iterator pending_response_it) {
+ DeferredQueryCapabilitiesResponse response(std::move(*pending_response_it));
+ pending_query_capabilities_responses_.erase(pending_response_it);
+ auto resp =
+ ipc::AsyncResult<protos::gen::QueryCapabilitiesResponse>::Create();
+ *resp->mutable_capabilities() = caps;
+ response.Resolve(std::move(resp));
+}
+
+void ConsumerIPCService::SaveTraceForBugreport(
+ const protos::gen::SaveTraceForBugreportRequest&,
+ DeferredSaveTraceForBugreportResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ auto it = pending_bugreport_responses_.insert(
+ pending_bugreport_responses_.end(), std::move(resp));
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ auto callback = [weak_this, it](bool success, const std::string& msg) {
+ if (weak_this)
+ weak_this->OnSaveTraceForBugreportCallback(success, msg, std::move(it));
+ };
+ remote_consumer->service_endpoint->SaveTraceForBugreport(callback);
+}
+
+void ConsumerIPCService::CloneSession(
+ const protos::gen::CloneSessionRequest& req,
+ DeferredCloneSessionResponse resp) {
+ RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
+ remote_consumer->clone_session_response = std::move(resp);
+ ConsumerEndpoint::CloneSessionArgs args;
+ args.skip_trace_filter = req.skip_trace_filter();
+ args.for_bugreport = req.for_bugreport();
+ remote_consumer->service_endpoint->CloneSession(req.session_id(),
+ std::move(args));
+}
+
+// Called by the service in response to
+// service_endpoint->SaveTraceForBugreport().
+void ConsumerIPCService::OnSaveTraceForBugreportCallback(
+ bool success,
+ const std::string& msg,
+ PendingSaveTraceForBugreportResponses::iterator pending_response_it) {
+ DeferredSaveTraceForBugreportResponse response(
+ std::move(*pending_response_it));
+ pending_bugreport_responses_.erase(pending_response_it);
+ auto resp =
+ ipc::AsyncResult<protos::gen::SaveTraceForBugreportResponse>::Create();
+ resp->set_success(success);
+ resp->set_msg(msg);
+ response.Resolve(std::move(resp));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RemoteConsumer methods
+////////////////////////////////////////////////////////////////////////////////
+
+ConsumerIPCService::RemoteConsumer::RemoteConsumer() = default;
+ConsumerIPCService::RemoteConsumer::~RemoteConsumer() = default;
+
+// Invoked by the |core_service_| business logic after the ConnectConsumer()
+// call. There is nothing to do here, we really expected the ConnectConsumer()
+// to just work in the local case.
+void ConsumerIPCService::RemoteConsumer::OnConnect() {}
+
+// Invoked by the |core_service_| business logic after we destroy the
+// |service_endpoint| (in the RemoteConsumer dtor).
+void ConsumerIPCService::RemoteConsumer::OnDisconnect() {}
+
+void ConsumerIPCService::RemoteConsumer::OnTracingDisabled(
+ const std::string& error) {
+ if (enable_tracing_response.IsBound()) {
+ auto result =
+ ipc::AsyncResult<protos::gen::EnableTracingResponse>::Create();
+ result->set_disabled(true);
+ if (!error.empty())
+ result->set_error(error);
+ enable_tracing_response.Resolve(std::move(result));
+ }
+}
+
+void ConsumerIPCService::RemoteConsumer::OnTraceData(
+ std::vector<TracePacket> trace_packets,
+ bool has_more) {
+ if (!read_buffers_response.IsBound())
+ return;
+
+ auto result = ipc::AsyncResult<protos::gen::ReadBuffersResponse>::Create();
+
+ // A TracePacket might be too big to fit into a single IPC message (max
+ // kIPCBufferSize). However a TracePacket is made of slices and each slice
+ // is way smaller than kIPCBufferSize (a slice size is effectively bounded by
+ // the max chunk size of the SharedMemoryABI). When sending a TracePacket,
+ // if its slices don't fit within one IPC, chunk them over several contiguous
+ // IPCs using the |last_slice_for_packet| for glueing on the other side.
+ static_assert(ipc::kIPCBufferSize >= SharedMemoryABI::kMaxPageSize * 2,
+ "kIPCBufferSize too small given the max possible slice size");
+
+ auto send_ipc_reply = [this, &result](bool more) {
+ result.set_has_more(more);
+ read_buffers_response.Resolve(std::move(result));
+ result = ipc::AsyncResult<protos::gen::ReadBuffersResponse>::Create();
+ };
+
+ size_t approx_reply_size = 0;
+ for (const TracePacket& trace_packet : trace_packets) {
+ size_t num_slices_left_for_packet = trace_packet.slices().size();
+ for (const Slice& slice : trace_packet.slices()) {
+ // Check if this slice would cause the IPC to overflow its max size and,
+ // if that is the case, split the IPCs. The "16" and "64" below are
+ // over-estimations of, respectively:
+ // 16: the preamble that prefixes each slice (there are 2 x size fields
+ // in the proto + the |last_slice_for_packet| bool).
+ // 64: the overhead of the IPC InvokeMethodReply + wire_protocol's frame.
+ // If these estimations are wrong, BufferedFrameDeserializer::Serialize()
+ // will hit a DCHECK anyways.
+ const size_t approx_slice_size = slice.size + 16;
+ if (approx_reply_size + approx_slice_size > ipc::kIPCBufferSize - 64) {
+ // If we hit this CHECK we got a single slice that is > kIPCBufferSize.
+ PERFETTO_CHECK(result->slices_size() > 0);
+ send_ipc_reply(/*has_more=*/true);
+ approx_reply_size = 0;
+ }
+ approx_reply_size += approx_slice_size;
+
+ auto* res_slice = result->add_slices();
+ res_slice->set_last_slice_for_packet(--num_slices_left_for_packet == 0);
+ res_slice->set_data(slice.start, slice.size);
+ }
+ }
+ send_ipc_reply(has_more);
+}
+
+void ConsumerIPCService::RemoteConsumer::OnDetach(bool success) {
+ if (!success) {
+ std::move(detach_response).Reject();
+ return;
+ }
+ auto resp = ipc::AsyncResult<protos::gen::DetachResponse>::Create();
+ std::move(detach_response).Resolve(std::move(resp));
+}
+
+void ConsumerIPCService::RemoteConsumer::OnAttach(
+ bool success,
+ const TraceConfig& trace_config) {
+ if (!success) {
+ std::move(attach_response).Reject();
+ return;
+ }
+ auto response = ipc::AsyncResult<protos::gen::AttachResponse>::Create();
+ *response->mutable_trace_config() = trace_config;
+ std::move(attach_response).Resolve(std::move(response));
+}
+
+void ConsumerIPCService::RemoteConsumer::OnTraceStats(bool success,
+ const TraceStats& stats) {
+ if (!success) {
+ std::move(get_trace_stats_response).Reject();
+ return;
+ }
+ auto response =
+ ipc::AsyncResult<protos::gen::GetTraceStatsResponse>::Create();
+ *response->mutable_trace_stats() = stats;
+ std::move(get_trace_stats_response).Resolve(std::move(response));
+}
+
+void ConsumerIPCService::RemoteConsumer::OnObservableEvents(
+ const ObservableEvents& events) {
+ if (!observe_events_response.IsBound())
+ return;
+
+ auto result = ipc::AsyncResult<protos::gen::ObserveEventsResponse>::Create();
+ result.set_has_more(true);
+ *result->mutable_events() = events;
+ observe_events_response.Resolve(std::move(result));
+}
+
+void ConsumerIPCService::RemoteConsumer::CloseObserveEventsResponseStream() {
+ if (!observe_events_response.IsBound())
+ return;
+
+ auto result = ipc::AsyncResult<protos::gen::ObserveEventsResponse>::Create();
+ result.set_has_more(false);
+ observe_events_response.Resolve(std::move(result));
+}
+
+void ConsumerIPCService::RemoteConsumer::OnSessionCloned(
+ const OnSessionClonedArgs& args) {
+ if (!clone_session_response.IsBound())
+ return;
+
+ auto resp = ipc::AsyncResult<protos::gen::CloneSessionResponse>::Create();
+ resp->set_success(args.success);
+ resp->set_error(args.error);
+ resp->set_uuid_msb(args.uuid.msb());
+ resp->set_uuid_lsb(args.uuid.lsb());
+ std::move(clone_session_response).Resolve(std::move(resp));
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/ipc/service/producer_ipc_service.cc
+// gen_amalgamated begin header: src/tracing/ipc/service/producer_ipc_service.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_SERVICE_PRODUCER_IPC_SERVICE_H_
+#define SRC_TRACING_IPC_SERVICE_PRODUCER_IPC_SERVICE_H_
+
+#include <list>
+#include <map>
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/producer.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/producer_port.ipc.h"
+
+namespace perfetto {
+
+namespace ipc {
+class Host;
+} // namespace ipc
+
+// Implements the Producer port of the IPC service. This class proxies requests
+// and responses between the core service logic (|svc_|) and remote Producer(s)
+// on the IPC socket, through the methods overriddden from ProducerPort.
+class ProducerIPCService : public protos::gen::ProducerPort {
+ public:
+ explicit ProducerIPCService(TracingService* core_service);
+ ~ProducerIPCService() override;
+
+ // ProducerPort implementation (from .proto IPC definition).
+ void InitializeConnection(const protos::gen::InitializeConnectionRequest&,
+ DeferredInitializeConnectionResponse) override;
+ void RegisterDataSource(const protos::gen::RegisterDataSourceRequest&,
+ DeferredRegisterDataSourceResponse) override;
+ void UpdateDataSource(const protos::gen::UpdateDataSourceRequest&,
+ DeferredUpdateDataSourceResponse) override;
+ void UnregisterDataSource(const protos::gen::UnregisterDataSourceRequest&,
+ DeferredUnregisterDataSourceResponse) override;
+ void RegisterTraceWriter(const protos::gen::RegisterTraceWriterRequest&,
+ DeferredRegisterTraceWriterResponse) override;
+ void UnregisterTraceWriter(const protos::gen::UnregisterTraceWriterRequest&,
+ DeferredUnregisterTraceWriterResponse) override;
+ void CommitData(const protos::gen::CommitDataRequest&,
+ DeferredCommitDataResponse) override;
+ void NotifyDataSourceStarted(
+ const protos::gen::NotifyDataSourceStartedRequest&,
+ DeferredNotifyDataSourceStartedResponse) override;
+ void NotifyDataSourceStopped(
+ const protos::gen::NotifyDataSourceStoppedRequest&,
+ DeferredNotifyDataSourceStoppedResponse) override;
+ void ActivateTriggers(const protos::gen::ActivateTriggersRequest&,
+ DeferredActivateTriggersResponse) override;
+
+ void GetAsyncCommand(const protos::gen::GetAsyncCommandRequest&,
+ DeferredGetAsyncCommandResponse) override;
+ void Sync(const protos::gen::SyncRequest&, DeferredSyncResponse) override;
+ void OnClientDisconnected() override;
+
+ private:
+ // Acts like a Producer with the core Service business logic (which doesn't
+ // know anything about the remote transport), but all it does is proxying
+ // methods to the remote Producer on the other side of the IPC channel.
+ class RemoteProducer : public Producer {
+ public:
+ RemoteProducer();
+ ~RemoteProducer() override;
+
+ // These methods are called by the |core_service_| business logic. There is
+ // no connection here, these methods are posted straight away.
+ void OnConnect() override;
+ void OnDisconnect() override;
+ void SetupDataSource(DataSourceInstanceID,
+ const DataSourceConfig&) override;
+ void StartDataSource(DataSourceInstanceID,
+ const DataSourceConfig&) override;
+ void StopDataSource(DataSourceInstanceID) override;
+ void OnTracingSetup() override;
+ void Flush(FlushRequestID,
+ const DataSourceInstanceID* data_source_ids,
+ size_t num_data_sources,
+ FlushFlags) override;
+
+ void ClearIncrementalState(const DataSourceInstanceID* data_source_ids,
+ size_t num_data_sources) override;
+
+ void SendSetupTracing();
+
+ // The interface obtained from the core service business logic through
+ // Service::ConnectProducer(this). This allows to invoke methods for a
+ // specific Producer on the Service business logic.
+ std::unique_ptr<TracingService::ProducerEndpoint> service_endpoint;
+
+ // The back-channel (based on a never ending stream request) that allows us
+ // to send asynchronous commands to the remote Producer (e.g. start/stop a
+ // data source).
+ DeferredGetAsyncCommandResponse async_producer_commands;
+
+ // Set if the service calls OnTracingSetup() before the
+ // |async_producer_commands| was bound by the service. In this case, we
+ // forward the SetupTracing command when it is bound later.
+ bool send_setup_tracing_on_async_commands_bound = false;
+ };
+
+ ProducerIPCService(const ProducerIPCService&) = delete;
+ ProducerIPCService& operator=(const ProducerIPCService&) = delete;
+
+ // Returns the ProducerEndpoint in the core business logic that corresponds to
+ // the current IPC request.
+ RemoteProducer* GetProducerForCurrentRequest();
+
+ TracingService* const core_service_;
+
+ // Maps IPC clients to ProducerEndpoint instances registered on the
+ // |core_service_| business logic.
+ std::map<ipc::ClientID, std::unique_ptr<RemoteProducer>> producers_;
+
+ // List because pointers need to be stable.
+ std::list<DeferredSyncResponse> pending_syncs_;
+
+ base::WeakPtrFactory<ProducerIPCService> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_IPC_SERVICE_PRODUCER_IPC_SERVICE_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/service/producer_ipc_service.h"
+
+#include <cinttypes>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/host.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/client_identity.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/commit_data_request.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_descriptor.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// gen_amalgamated expanded: #include "src/tracing/ipc/shared_memory_windows.h"
+#else
+// gen_amalgamated expanded: #include "src/tracing/ipc/posix_shared_memory.h"
+#endif
+
+// The remote Producer(s) are not trusted. All the methods from the ProducerPort
+// IPC layer (e.g. RegisterDataSource()) must assume that the remote Producer is
+// compromised.
+
+namespace perfetto {
+
+ProducerIPCService::ProducerIPCService(TracingService* core_service)
+ : core_service_(core_service), weak_ptr_factory_(this) {}
+
+ProducerIPCService::~ProducerIPCService() = default;
+
+ProducerIPCService::RemoteProducer*
+ProducerIPCService::GetProducerForCurrentRequest() {
+ const ipc::ClientID ipc_client_id = ipc::Service::client_info().client_id();
+ PERFETTO_CHECK(ipc_client_id);
+ auto it = producers_.find(ipc_client_id);
+ if (it == producers_.end())
+ return nullptr;
+ return it->second.get();
+}
+
+// Called by the remote Producer through the IPC channel soon after connecting.
+void ProducerIPCService::InitializeConnection(
+ const protos::gen::InitializeConnectionRequest& req,
+ DeferredInitializeConnectionResponse response) {
+ const auto& client_info = ipc::Service::client_info();
+ const ipc::ClientID ipc_client_id = client_info.client_id();
+ PERFETTO_CHECK(ipc_client_id);
+
+ if (producers_.count(ipc_client_id) > 0) {
+ PERFETTO_DLOG(
+ "The remote Producer is trying to re-initialize the connection");
+ return response.Reject();
+ }
+
+ // Create a new entry.
+ std::unique_ptr<RemoteProducer> producer(new RemoteProducer());
+
+ TracingService::ProducerSMBScrapingMode smb_scraping_mode =
+ TracingService::ProducerSMBScrapingMode::kDefault;
+ switch (req.smb_scraping_mode()) {
+ case protos::gen::InitializeConnectionRequest::SMB_SCRAPING_UNSPECIFIED:
+ break;
+ case protos::gen::InitializeConnectionRequest::SMB_SCRAPING_DISABLED:
+ smb_scraping_mode = TracingService::ProducerSMBScrapingMode::kDisabled;
+ break;
+ case protos::gen::InitializeConnectionRequest::SMB_SCRAPING_ENABLED:
+ smb_scraping_mode = TracingService::ProducerSMBScrapingMode::kEnabled;
+ break;
+ }
+
+ // If the producer provided an SMB, tell the service to attempt to adopt it.
+ std::unique_ptr<SharedMemory> shmem;
+ if (req.producer_provided_shmem()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (!req.has_shm_key_windows() || req.shm_key_windows().empty()) {
+ PERFETTO_ELOG(
+ "shm_key_windows must be non-empty when "
+ "producer_provided_shmem = true");
+ } else {
+ shmem = SharedMemoryWindows::Attach(req.shm_key_windows());
+ // Attach() does error logging if something fails, no need to extra ELOGs.
+ }
+#else
+ base::ScopedFile shmem_fd = ipc::Service::TakeReceivedFD();
+
+ if (shmem_fd) {
+ shmem = PosixSharedMemory::AttachToFd(
+ std::move(shmem_fd), /*require_seals_if_supported=*/true);
+ if (!shmem) {
+ PERFETTO_ELOG(
+ "Couldn't map producer-provided SMB, falling back to "
+ "service-provided SMB");
+ }
+ } else {
+ PERFETTO_DLOG(
+ "InitializeConnectionRequest's producer_provided_shmem flag is set "
+ "but the producer didn't provide an FD");
+ }
+#endif
+ }
+
+ // Copy the data fields to be emitted to trace packets into ClientIdentity.
+ ClientIdentity client_identity(client_info.uid(), client_info.pid(),
+ client_info.machine_id());
+ // ConnectProducer will call OnConnect() on the next task.
+ producer->service_endpoint = core_service_->ConnectProducer(
+ producer.get(), client_identity, req.producer_name(),
+ req.shared_memory_size_hint_bytes(),
+ /*in_process=*/false, smb_scraping_mode,
+ req.shared_memory_page_size_hint_bytes(), std::move(shmem),
+ req.sdk_version());
+
+ // Could happen if the service has too many producers connected.
+ if (!producer->service_endpoint) {
+ response.Reject();
+ return;
+ }
+
+ bool use_shmem_emulation = ipc::Service::use_shmem_emulation();
+ bool using_producer_shmem =
+ !use_shmem_emulation &&
+ producer->service_endpoint->IsShmemProvidedByProducer();
+
+ producers_.emplace(ipc_client_id, std::move(producer));
+ // Because of the std::move() |producer| is invalid after this point.
+
+ auto async_res =
+ ipc::AsyncResult<protos::gen::InitializeConnectionResponse>::Create();
+ async_res->set_using_shmem_provided_by_producer(using_producer_shmem);
+ async_res->set_direct_smb_patching_supported(true);
+ async_res->set_use_shmem_emulation(use_shmem_emulation);
+ response.Resolve(std::move(async_res));
+}
+
+// Called by the remote Producer through the IPC channel.
+void ProducerIPCService::RegisterDataSource(
+ const protos::gen::RegisterDataSourceRequest& req,
+ DeferredRegisterDataSourceResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked RegisterDataSource() before InitializeConnection()");
+ if (response.IsBound())
+ response.Reject();
+ return;
+ }
+
+ const DataSourceDescriptor& dsd = req.data_source_descriptor();
+ GetProducerForCurrentRequest()->service_endpoint->RegisterDataSource(dsd);
+
+ // RegisterDataSource doesn't expect any meaningful response.
+ if (response.IsBound()) {
+ response.Resolve(
+ ipc::AsyncResult<protos::gen::RegisterDataSourceResponse>::Create());
+ }
+}
+
+// Called by the remote Producer through the IPC channel.
+void ProducerIPCService::UpdateDataSource(
+ const protos::gen::UpdateDataSourceRequest& req,
+ DeferredUpdateDataSourceResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked UpdateDataSource() before InitializeConnection()");
+ if (response.IsBound())
+ response.Reject();
+ return;
+ }
+
+ const DataSourceDescriptor& dsd = req.data_source_descriptor();
+ GetProducerForCurrentRequest()->service_endpoint->UpdateDataSource(dsd);
+
+ // UpdateDataSource doesn't expect any meaningful response.
+ if (response.IsBound()) {
+ response.Resolve(
+ ipc::AsyncResult<protos::gen::UpdateDataSourceResponse>::Create());
+ }
+}
+
+// Called by the IPC layer.
+void ProducerIPCService::OnClientDisconnected() {
+ ipc::ClientID client_id = ipc::Service::client_info().client_id();
+ PERFETTO_DLOG("Client %" PRIu64 " disconnected", client_id);
+ producers_.erase(client_id);
+}
+
+// TODO(fmayer): test what happens if we receive the following tasks, in order:
+// RegisterDataSource, UnregisterDataSource, OnDataSourceRegistered.
+// which essentially means that the client posted back to back a
+// ReqisterDataSource and UnregisterDataSource speculating on the next id.
+// Called by the remote Service through the IPC channel.
+void ProducerIPCService::UnregisterDataSource(
+ const protos::gen::UnregisterDataSourceRequest& req,
+ DeferredUnregisterDataSourceResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked UnregisterDataSource() before "
+ "InitializeConnection()");
+ if (response.IsBound())
+ response.Reject();
+ return;
+ }
+ producer->service_endpoint->UnregisterDataSource(req.data_source_name());
+
+ // UnregisterDataSource doesn't expect any meaningful response.
+ if (response.IsBound()) {
+ response.Resolve(
+ ipc::AsyncResult<protos::gen::UnregisterDataSourceResponse>::Create());
+ }
+}
+
+void ProducerIPCService::RegisterTraceWriter(
+ const protos::gen::RegisterTraceWriterRequest& req,
+ DeferredRegisterTraceWriterResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked RegisterTraceWriter() before "
+ "InitializeConnection()");
+ if (response.IsBound())
+ response.Reject();
+ return;
+ }
+ producer->service_endpoint->RegisterTraceWriter(req.trace_writer_id(),
+ req.target_buffer());
+
+ // RegisterTraceWriter doesn't expect any meaningful response.
+ if (response.IsBound()) {
+ response.Resolve(
+ ipc::AsyncResult<protos::gen::RegisterTraceWriterResponse>::Create());
+ }
+}
+
+void ProducerIPCService::UnregisterTraceWriter(
+ const protos::gen::UnregisterTraceWriterRequest& req,
+ DeferredUnregisterTraceWriterResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked UnregisterTraceWriter() before "
+ "InitializeConnection()");
+ if (response.IsBound())
+ response.Reject();
+ return;
+ }
+ producer->service_endpoint->UnregisterTraceWriter(req.trace_writer_id());
+
+ // UnregisterTraceWriter doesn't expect any meaningful response.
+ if (response.IsBound()) {
+ response.Resolve(
+ ipc::AsyncResult<protos::gen::UnregisterTraceWriterResponse>::Create());
+ }
+}
+
+void ProducerIPCService::CommitData(const protos::gen::CommitDataRequest& req,
+ DeferredCommitDataResponse resp) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked CommitData() before InitializeConnection()");
+ if (resp.IsBound())
+ resp.Reject();
+ return;
+ }
+
+ // We don't want to send a response if the client didn't attach a callback to
+ // the original request. Doing so would generate unnecessary wakeups and
+ // context switches.
+ std::function<void()> callback;
+ if (resp.IsBound()) {
+ // Capturing |resp| by reference here speculates on the fact that
+ // CommitData() in tracing_service_impl.cc invokes the passed callback
+ // inline, without posting it. If that assumption changes this code needs to
+ // wrap the response in a shared_ptr (C+11 lambdas don't support move) and
+ // use a weak ptr in the caller.
+ callback = [&resp] {
+ resp.Resolve(ipc::AsyncResult<protos::gen::CommitDataResponse>::Create());
+ };
+ }
+ producer->service_endpoint->CommitData(req, callback);
+}
+
+void ProducerIPCService::NotifyDataSourceStarted(
+ const protos::gen::NotifyDataSourceStartedRequest& request,
+ DeferredNotifyDataSourceStartedResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked NotifyDataSourceStarted() before "
+ "InitializeConnection()");
+ if (response.IsBound())
+ response.Reject();
+ return;
+ }
+ producer->service_endpoint->NotifyDataSourceStarted(request.data_source_id());
+
+ // NotifyDataSourceStopped shouldn't expect any meaningful response, avoid
+ // a useless IPC in that case.
+ if (response.IsBound()) {
+ response.Resolve(ipc::AsyncResult<
+ protos::gen::NotifyDataSourceStartedResponse>::Create());
+ }
+}
+
+void ProducerIPCService::NotifyDataSourceStopped(
+ const protos::gen::NotifyDataSourceStoppedRequest& request,
+ DeferredNotifyDataSourceStoppedResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked NotifyDataSourceStopped() before "
+ "InitializeConnection()");
+ if (response.IsBound())
+ response.Reject();
+ return;
+ }
+ producer->service_endpoint->NotifyDataSourceStopped(request.data_source_id());
+
+ // NotifyDataSourceStopped shouldn't expect any meaningful response, avoid
+ // a useless IPC in that case.
+ if (response.IsBound()) {
+ response.Resolve(ipc::AsyncResult<
+ protos::gen::NotifyDataSourceStoppedResponse>::Create());
+ }
+}
+
+void ProducerIPCService::ActivateTriggers(
+ const protos::gen::ActivateTriggersRequest& proto_req,
+ DeferredActivateTriggersResponse resp) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked ActivateTriggers() before InitializeConnection()");
+ if (resp.IsBound())
+ resp.Reject();
+ return;
+ }
+ std::vector<std::string> triggers;
+ for (const auto& name : proto_req.trigger_names()) {
+ triggers.push_back(name);
+ }
+ producer->service_endpoint->ActivateTriggers(triggers);
+ // ActivateTriggers shouldn't expect any meaningful response, avoid
+ // a useless IPC in that case.
+ if (resp.IsBound()) {
+ resp.Resolve(
+ ipc::AsyncResult<protos::gen::ActivateTriggersResponse>::Create());
+ }
+}
+
+void ProducerIPCService::GetAsyncCommand(
+ const protos::gen::GetAsyncCommandRequest&,
+ DeferredGetAsyncCommandResponse response) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG(
+ "Producer invoked GetAsyncCommand() before "
+ "InitializeConnection()");
+ return response.Reject();
+ }
+ // Keep the back channel open, without ever resolving the ipc::Deferred fully,
+ // to send async commands to the RemoteProducer (e.g., starting/stopping a
+ // data source).
+ producer->async_producer_commands = std::move(response);
+
+ // Service may already have issued the OnTracingSetup() event, in which case
+ // we should forward it to the producer now.
+ if (producer->send_setup_tracing_on_async_commands_bound)
+ producer->SendSetupTracing();
+}
+
+void ProducerIPCService::Sync(const protos::gen::SyncRequest&,
+ DeferredSyncResponse resp) {
+ RemoteProducer* producer = GetProducerForCurrentRequest();
+ if (!producer) {
+ PERFETTO_DLOG("Producer invoked Sync() before InitializeConnection()");
+ return resp.Reject();
+ }
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ auto resp_it = pending_syncs_.insert(pending_syncs_.end(), std::move(resp));
+ auto callback = [weak_this, resp_it]() {
+ if (!weak_this)
+ return;
+ auto pending_resp = std::move(*resp_it);
+ weak_this->pending_syncs_.erase(resp_it);
+ pending_resp.Resolve(ipc::AsyncResult<protos::gen::SyncResponse>::Create());
+ };
+ producer->service_endpoint->Sync(callback);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RemoteProducer methods
+////////////////////////////////////////////////////////////////////////////////
+
+ProducerIPCService::RemoteProducer::RemoteProducer() = default;
+ProducerIPCService::RemoteProducer::~RemoteProducer() = default;
+
+// Invoked by the |core_service_| business logic after the ConnectProducer()
+// call. There is nothing to do here, we really expected the ConnectProducer()
+// to just work in the local case.
+void ProducerIPCService::RemoteProducer::OnConnect() {}
+
+// Invoked by the |core_service_| business logic after we destroy the
+// |service_endpoint| (in the RemoteProducer dtor).
+void ProducerIPCService::RemoteProducer::OnDisconnect() {}
+
+// Invoked by the |core_service_| business logic when it wants to create a new
+// data source.
+void ProducerIPCService::RemoteProducer::SetupDataSource(
+ DataSourceInstanceID dsid,
+ const DataSourceConfig& cfg) {
+ if (!async_producer_commands.IsBound()) {
+ PERFETTO_DLOG(
+ "The Service tried to create a new data source but the remote Producer "
+ "has not yet initialized the connection");
+ return;
+ }
+ auto cmd = ipc::AsyncResult<protos::gen::GetAsyncCommandResponse>::Create();
+ cmd.set_has_more(true);
+ cmd->mutable_setup_data_source()->set_new_instance_id(dsid);
+ *cmd->mutable_setup_data_source()->mutable_config() = cfg;
+ async_producer_commands.Resolve(std::move(cmd));
+}
+
+// Invoked by the |core_service_| business logic when it wants to start a new
+// data source.
+void ProducerIPCService::RemoteProducer::StartDataSource(
+ DataSourceInstanceID dsid,
+ const DataSourceConfig& cfg) {
+ if (!async_producer_commands.IsBound()) {
+ PERFETTO_DLOG(
+ "The Service tried to start a new data source but the remote Producer "
+ "has not yet initialized the connection");
+ return;
+ }
+ auto cmd = ipc::AsyncResult<protos::gen::GetAsyncCommandResponse>::Create();
+ cmd.set_has_more(true);
+ cmd->mutable_start_data_source()->set_new_instance_id(dsid);
+ *cmd->mutable_start_data_source()->mutable_config() = cfg;
+ async_producer_commands.Resolve(std::move(cmd));
+}
+
+void ProducerIPCService::RemoteProducer::StopDataSource(
+ DataSourceInstanceID dsid) {
+ if (!async_producer_commands.IsBound()) {
+ PERFETTO_DLOG(
+ "The Service tried to stop a data source but the remote Producer "
+ "has not yet initialized the connection");
+ return;
+ }
+ auto cmd = ipc::AsyncResult<protos::gen::GetAsyncCommandResponse>::Create();
+ cmd.set_has_more(true);
+ cmd->mutable_stop_data_source()->set_instance_id(dsid);
+ async_producer_commands.Resolve(std::move(cmd));
+}
+
+void ProducerIPCService::RemoteProducer::OnTracingSetup() {
+ if (!async_producer_commands.IsBound()) {
+ // Service may call this before the producer issued GetAsyncCommand.
+ send_setup_tracing_on_async_commands_bound = true;
+ return;
+ }
+ SendSetupTracing();
+}
+
+void ProducerIPCService::RemoteProducer::SendSetupTracing() {
+ PERFETTO_CHECK(async_producer_commands.IsBound());
+ PERFETTO_CHECK(service_endpoint->shared_memory());
+ auto cmd = ipc::AsyncResult<protos::gen::GetAsyncCommandResponse>::Create();
+ cmd.set_has_more(true);
+ auto setup_tracing = cmd->mutable_setup_tracing();
+ if (!service_endpoint->IsShmemProvidedByProducer()) {
+ // Nominal case (% Chrome): service provides SMB.
+ setup_tracing->set_shared_buffer_page_size_kb(
+ static_cast<uint32_t>(service_endpoint->shared_buffer_page_size_kb()));
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ const std::string& shm_key =
+ static_cast<SharedMemoryWindows*>(service_endpoint->shared_memory())
+ ->key();
+ setup_tracing->set_shm_key_windows(shm_key);
+#else
+ const int shm_fd =
+ static_cast<PosixSharedMemory*>(service_endpoint->shared_memory())
+ ->fd();
+ cmd.set_fd(shm_fd);
+#endif
+ }
+ async_producer_commands.Resolve(std::move(cmd));
+}
+
+void ProducerIPCService::RemoteProducer::Flush(
+ FlushRequestID flush_request_id,
+ const DataSourceInstanceID* data_source_ids,
+ size_t num_data_sources,
+ FlushFlags flush_flags) {
+ if (!async_producer_commands.IsBound()) {
+ PERFETTO_DLOG(
+ "The Service tried to request a flush but the remote Producer has not "
+ "yet initialized the connection");
+ return;
+ }
+ auto cmd = ipc::AsyncResult<protos::gen::GetAsyncCommandResponse>::Create();
+ cmd.set_has_more(true);
+ for (size_t i = 0; i < num_data_sources; i++)
+ cmd->mutable_flush()->add_data_source_ids(data_source_ids[i]);
+ cmd->mutable_flush()->set_request_id(flush_request_id);
+ cmd->mutable_flush()->set_flags(flush_flags.flags());
+ async_producer_commands.Resolve(std::move(cmd));
+}
+
+void ProducerIPCService::RemoteProducer::ClearIncrementalState(
+ const DataSourceInstanceID* data_source_ids,
+ size_t num_data_sources) {
+ if (!async_producer_commands.IsBound()) {
+ PERFETTO_DLOG(
+ "The Service tried to request an incremental state invalidation, but "
+ "the remote Producer has not yet initialized the connection");
+ return;
+ }
+ auto cmd = ipc::AsyncResult<protos::gen::GetAsyncCommandResponse>::Create();
+ cmd.set_has_more(true);
+ for (size_t i = 0; i < num_data_sources; i++)
+ cmd->mutable_clear_incremental_state()->add_data_source_ids(
+ data_source_ids[i]);
+ async_producer_commands.Resolve(std::move(cmd));
+}
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/ipc/service/relay_ipc_service.cc
+// gen_amalgamated begin header: src/tracing/ipc/service/relay_ipc_service.h
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_SERVICE_RELAY_IPC_SERVICE_H_
+#define SRC_TRACING_IPC_SERVICE_RELAY_IPC_SERVICE_H_
+
+#include <limits>
+#include <list>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/flat_hash_map.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/ipc/relay_port.ipc.h"
+
+namespace perfetto {
+
+// Implements the RelayPort IPC service.
+class RelayIPCService : public protos::gen::RelayPort {
+ public:
+ explicit RelayIPCService(TracingService* core_service);
+ ~RelayIPCService() override = default;
+
+ void OnClientDisconnected() override;
+ void SyncClock(const protos::gen::SyncClockRequest&,
+ DeferredSyncClockResponse) override;
+
+ private:
+ TracingService* const core_service_;
+
+ using ClockSnapshots =
+ base::FlatHashMap<uint32_t, std::pair<uint64_t, uint64_t>>;
+ struct ClockSnapshotRecords {
+ base::MachineID machine_id = base::kDefaultMachineID;
+
+ // Keep track of most recent clock snapshots, ordered by local timestamps
+ // (CLOCK_BOOTTIME).
+ std::list<ClockSnapshots> clock_snapshots;
+
+ uint64_t min_rtt = std::numeric_limits<uint64_t>::max();
+ };
+
+ TracingService::RelayEndpoint* GetRelayEndpoint(ipc::ClientID);
+
+ base::FlatHashMap<ipc::ClientID,
+ std::unique_ptr<TracingService::RelayEndpoint>>
+ relay_endpoints_;
+
+ base::WeakPtrFactory<RelayIPCService> weak_ptr_factory_; // Keep last.
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_IPC_SERVICE_RELAY_IPC_SERVICE_H_
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/service/relay_ipc_service.h"
+
+#include <cinttypes>
+#include <utility>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/clock_snapshots.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+namespace perfetto {
+
+RelayIPCService::RelayIPCService(TracingService* core_service)
+ : core_service_(core_service), weak_ptr_factory_(this) {}
+
+TracingService::RelayEndpoint* RelayIPCService::GetRelayEndpoint(
+ ipc::ClientID client_id) {
+ auto* endpoint = relay_endpoints_.Find(client_id);
+ if (!endpoint)
+ return nullptr;
+ return endpoint->get();
+}
+
+void RelayIPCService::OnClientDisconnected() {
+ auto client_id = ipc::Service::client_info().client_id();
+ PERFETTO_DLOG("Relay endpoint %" PRIu64 "disconnected ", client_id);
+
+ auto* endpoint = GetRelayEndpoint(client_id);
+ if (!endpoint)
+ return;
+
+ endpoint->Disconnect();
+ relay_endpoints_.Erase(client_id);
+}
+
+void RelayIPCService::SyncClock(const protos::gen::SyncClockRequest& req,
+ DeferredSyncClockResponse resp) {
+ auto host_clock_snapshots = CaptureClockSnapshots();
+
+ // Send the response to client to reduce RTT.
+ auto async_resp = ipc::AsyncResult<protos::gen::SyncClockResponse>::Create();
+ resp.Resolve(std::move(async_resp));
+
+ ClockSnapshotVector client_clock_snapshots;
+ for (size_t i = 0; i < req.clocks().size(); i++) {
+ auto& client_clock = req.clocks()[i];
+ client_clock_snapshots.emplace_back(client_clock.clock_id(),
+ client_clock.timestamp());
+ }
+
+ // Handle the request in the core service.
+ auto machine_id = ipc::Service::client_info().machine_id();
+ auto client_id = ipc::Service::client_info().client_id();
+ auto* endpoint = GetRelayEndpoint(client_id);
+ if (!endpoint) {
+ auto ep = core_service_->ConnectRelayClient(
+ std::make_pair(machine_id, client_id));
+ endpoint = ep.get();
+ relay_endpoints_.Insert(client_id, std::move(ep));
+ }
+
+ RelayEndpoint::SyncMode mode = req.phase() == SyncClockRequest::PING
+ ? RelayEndpoint::SyncMode::PING
+ : RelayEndpoint::SyncMode::UPDATE;
+ endpoint->SyncClocks(mode, std::move(client_clock_snapshots),
+ std::move(host_clock_snapshots));
+}
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/ipc/service/service_ipc_host_impl.cc
+// gen_amalgamated begin header: src/tracing/ipc/service/service_ipc_host_impl.h
+// gen_amalgamated begin header: include/perfetto/ext/tracing/ipc/service_ipc_host.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_IPC_SERVICE_IPC_HOST_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_IPC_SERVICE_IPC_HOST_H_
+
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/unix_socket.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/default_socket.h"
+
+namespace perfetto {
+namespace base {
+class TaskRunner;
+} // namespace base.
+
+namespace ipc {
+class Host;
+} // namespace ipc
+
+// Creates an instance of the service (business logic + UNIX socket transport).
+// Exposed to:
+// The code in the tracing client that will host the service e.g., traced.
+// Implemented in:
+// src/tracing/ipc/service/service_ipc_host_impl.cc
+class PERFETTO_EXPORT_COMPONENT ServiceIPCHost {
+ public:
+ static std::unique_ptr<ServiceIPCHost> CreateInstance(
+ base::TaskRunner*,
+ TracingService::InitOpts = {});
+ virtual ~ServiceIPCHost();
+
+ // The overload to wrap the multi-value producer socket name in the
+ // single-value variant for compatibility in tests.
+ bool Start(const char* producer_socket_name,
+ const char* consumer_socket_name) {
+ return Start(TokenizeProducerSockets(producer_socket_name),
+ consumer_socket_name);
+ }
+ // Start listening on the Producer & Consumer ports. Returns false in case of
+ // failure (e.g., something else is listening on |socket_name|).
+ virtual bool Start(const std::vector<std::string>& producer_socket_names,
+ const char* consumer_socket_name) = 0;
+
+ // Like the above, but takes two file descriptors to already bound sockets.
+ // This is used when building as part of the Android tree, where init opens
+ // and binds the socket beore exec()-ing us.
+ virtual bool Start(base::ScopedSocketHandle producer_socket_fd,
+ base::ScopedSocketHandle consumer_socket_fd) = 0;
+
+ // Allows callers to supply preconstructed Hosts.
+ virtual bool Start(std::unique_ptr<ipc::Host> producer_host,
+ std::unique_ptr<ipc::Host> consumer_host) = 0;
+
+ virtual TracingService* service() const = 0;
+
+ protected:
+ ServiceIPCHost();
+
+ private:
+ ServiceIPCHost(const ServiceIPCHost&) = delete;
+ ServiceIPCHost& operator=(const ServiceIPCHost&) = delete;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_IPC_SERVICE_IPC_HOST_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef SRC_TRACING_IPC_SERVICE_SERVICE_IPC_HOST_IMPL_H_
+#define SRC_TRACING_IPC_SERVICE_SERVICE_IPC_HOST_IMPL_H_
+
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/ipc/service_ipc_host.h"
+
+namespace perfetto {
+
+namespace ipc {
+class Host;
+}
+
+// The implementation of the IPC host for the tracing service. This class does
+// very few things: it mostly initializes the IPC transport. The actual
+// implementation of the IPC <> Service business logic glue lives in
+// producer_ipc_service.cc and consumer_ipc_service.cc.
+class ServiceIPCHostImpl : public ServiceIPCHost {
+ public:
+ explicit ServiceIPCHostImpl(base::TaskRunner*,
+ TracingService::InitOpts init_opts = {});
+ ~ServiceIPCHostImpl() override;
+
+ // ServiceIPCHost implementation.
+ bool Start(const std::vector<std::string>& producer_socket_names,
+ const char* consumer_socket_name) override;
+ bool Start(base::ScopedSocketHandle producer_socket_fd,
+ base::ScopedSocketHandle consumer_socket_fd) override;
+ bool Start(std::unique_ptr<ipc::Host> producer_host,
+ std::unique_ptr<ipc::Host> consumer_host) override;
+
+ TracingService* service() const override;
+
+ private:
+ bool DoStart();
+ void Shutdown();
+
+ base::TaskRunner* const task_runner_;
+ const TracingService::InitOpts init_opts_;
+ std::unique_ptr<TracingService> svc_; // The service business logic.
+
+ // The IPC hosts that listen on the Producer sockets. They own the
+ // PosixServiceProducerPort instances which deal with all producers' IPC(s).
+ // Note that there can be multiple producer sockets if it's specified in the
+ // producer socket name (e.g. for listening both on vsock for VMs and AF_UNIX
+ // for processes on the same machine).
+ std::vector<std::unique_ptr<ipc::Host>> producer_ipc_ports_;
+
+ // As above, but for the Consumer port.
+ std::unique_ptr<ipc::Host> consumer_ipc_port_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_IPC_SERVICE_SERVICE_IPC_HOST_IMPL_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "src/tracing/ipc/service/service_ipc_host_impl.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/ipc/host.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "src/tracing/ipc/service/consumer_ipc_service.h"
+// gen_amalgamated expanded: #include "src/tracing/ipc/service/producer_ipc_service.h"
+// gen_amalgamated expanded: #include "src/tracing/ipc/service/relay_ipc_service.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// gen_amalgamated expanded: #include "src/tracing/ipc/shared_memory_windows.h"
+#else
+// gen_amalgamated expanded: #include "src/tracing/ipc/posix_shared_memory.h"
+#endif
+
+namespace perfetto {
+
+namespace {
+constexpr uint32_t kProducerSocketTxTimeoutMs = 10;
+}
+
+// TODO(fmayer): implement per-uid connection limit (b/69093705).
+
+// Implements the publicly exposed factory method declared in
+// include/tracing/posix_ipc/posix_service_host.h.
+std::unique_ptr<ServiceIPCHost> ServiceIPCHost::CreateInstance(
+ base::TaskRunner* task_runner,
+ TracingService::InitOpts init_opts) {
+ return std::unique_ptr<ServiceIPCHost>(
+ new ServiceIPCHostImpl(task_runner, init_opts));
+}
+
+ServiceIPCHostImpl::ServiceIPCHostImpl(base::TaskRunner* task_runner,
+ TracingService::InitOpts init_opts)
+ : task_runner_(task_runner), init_opts_(init_opts) {}
+
+ServiceIPCHostImpl::~ServiceIPCHostImpl() {}
+
+bool ServiceIPCHostImpl::Start(
+ const std::vector<std::string>& producer_socket_names,
+ const char* consumer_socket_name) {
+ PERFETTO_CHECK(!svc_); // Check if already started.
+
+ // Initialize the IPC transport.
+ for (const auto& producer_socket_name : producer_socket_names)
+ producer_ipc_ports_.emplace_back(
+ ipc::Host::CreateInstance(producer_socket_name.c_str(), task_runner_));
+ consumer_ipc_port_ =
+ ipc::Host::CreateInstance(consumer_socket_name, task_runner_);
+ return DoStart();
+}
+
+bool ServiceIPCHostImpl::Start(base::ScopedSocketHandle producer_socket_fd,
+ base::ScopedSocketHandle consumer_socket_fd) {
+ PERFETTO_CHECK(!svc_); // Check if already started.
+
+ // Initialize the IPC transport.
+ producer_ipc_ports_.emplace_back(
+ ipc::Host::CreateInstance(std::move(producer_socket_fd), task_runner_));
+ consumer_ipc_port_ =
+ ipc::Host::CreateInstance(std::move(consumer_socket_fd), task_runner_);
+ return DoStart();
+}
+
+bool ServiceIPCHostImpl::Start(std::unique_ptr<ipc::Host> producer_host,
+ std::unique_ptr<ipc::Host> consumer_host) {
+ PERFETTO_CHECK(!svc_); // Check if already started.
+ PERFETTO_DCHECK(producer_host);
+ PERFETTO_DCHECK(consumer_host);
+
+ // Initialize the IPC transport.
+ producer_ipc_ports_.emplace_back(std::move(producer_host));
+ consumer_ipc_port_ = std::move(consumer_host);
+
+ return DoStart();
+}
+
+bool ServiceIPCHostImpl::DoStart() {
+ // Create and initialize the platform-independent tracing business logic.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ std::unique_ptr<SharedMemory::Factory> shm_factory(
+ new SharedMemoryWindows::Factory());
+#else
+ std::unique_ptr<SharedMemory::Factory> shm_factory(
+ new PosixSharedMemory::Factory());
+#endif
+ svc_ = TracingService::CreateInstance(std::move(shm_factory), task_runner_,
+ init_opts_);
+
+ if (producer_ipc_ports_.empty() || !consumer_ipc_port_) {
+ Shutdown();
+ return false;
+ }
+
+ // Lower the timeout for blocking socket sends to producers as we shouldn't
+ // normally exhaust the kernel send buffer unless the producer is
+ // unresponsive. We'll drop the connection if the timeout is hit (see
+ // UnixSocket::Send). Context in b/236813972, b/193234818.
+ // Consumer port continues using the default timeout (10s) as there are
+ // generally fewer consumer processes, and they're better behaved. Also the
+ // consumer port ipcs might exhaust the send buffer under normal operation
+ // due to large messages such as ReadBuffersResponse.
+ for (auto& producer_ipc_port : producer_ipc_ports_)
+ producer_ipc_port->SetSocketSendTimeoutMs(kProducerSocketTxTimeoutMs);
+
+ // TODO(fmayer): add a test that destroyes the ServiceIPCHostImpl soon after
+ // Start() and checks that no spurious callbacks are issued.
+ for (auto& producer_ipc_port : producer_ipc_ports_) {
+ bool producer_service_exposed = producer_ipc_port->ExposeService(
+ std::unique_ptr<ipc::Service>(new ProducerIPCService(svc_.get())));
+ PERFETTO_CHECK(producer_service_exposed);
+
+ if (!init_opts_.enable_relay_endpoint)
+ continue;
+ // Expose a secondary service for sync with remote relay service
+ // if requested.
+ bool relay_service_exposed = producer_ipc_port->ExposeService(
+ std::unique_ptr<ipc::Service>(new RelayIPCService(svc_.get())));
+ PERFETTO_CHECK(relay_service_exposed);
+ }
+
+ bool consumer_service_exposed = consumer_ipc_port_->ExposeService(
+ std::unique_ptr<ipc::Service>(new ConsumerIPCService(svc_.get())));
+ PERFETTO_CHECK(consumer_service_exposed);
+
+ return true;
+}
+
+TracingService* ServiceIPCHostImpl::service() const {
+ return svc_.get();
+}
+
+void ServiceIPCHostImpl::Shutdown() {
+ // TODO(primiano): add a test that causes the Shutdown() and checks that no
+ // spurious callbacks are issued.
+ producer_ipc_ports_.clear();
+ consumer_ipc_port_.reset();
+ svc_.reset();
+}
+
+// Definitions for the base class ctor/dtor.
+ServiceIPCHost::ServiceIPCHost() = default;
+ServiceIPCHost::~ServiceIPCHost() = default;
+
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/internal/system_tracing_backend.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/system_tracing_backend.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/core/tracing_service.h"
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/default_socket.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_SYSTEM_CONSUMER)
+// gen_amalgamated expanded: #include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// gen_amalgamated expanded: #include "src/tracing/ipc/shared_memory_windows.h"
+#else
+// gen_amalgamated expanded: #include "src/tracing/ipc/posix_shared_memory.h"
+#endif
+
+namespace perfetto {
+namespace internal {
+
+// static
+TracingProducerBackend* SystemProducerTracingBackend::GetInstance() {
+ static auto* instance = new SystemProducerTracingBackend();
+ return instance;
+}
+
+SystemProducerTracingBackend::SystemProducerTracingBackend() {}
+
+std::unique_ptr<ProducerEndpoint> SystemProducerTracingBackend::ConnectProducer(
+ const ConnectProducerArgs& args) {
+ PERFETTO_DCHECK(args.task_runner->RunsTasksOnCurrentThread());
+
+ std::unique_ptr<SharedMemory> shm;
+ std::unique_ptr<SharedMemoryArbiter> arbiter;
+ uint32_t shmem_size_hint = args.shmem_size_hint_bytes;
+ uint32_t shmem_page_size_hint = args.shmem_page_size_hint_bytes;
+ if (args.use_producer_provided_smb) {
+ if (shmem_size_hint == 0)
+ shmem_size_hint = TracingService::kDefaultShmSize;
+ if (shmem_page_size_hint == 0)
+ shmem_page_size_hint = TracingService::kDefaultShmPageSize;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ shm = SharedMemoryWindows::Create(shmem_size_hint);
+#else
+ shm = PosixSharedMemory::Create(shmem_size_hint);
+#endif
+ arbiter = SharedMemoryArbiter::CreateUnboundInstance(
+ shm.get(), shmem_page_size_hint, SharedMemoryABI::ShmemMode::kDefault);
+ }
+
+ ipc::Client::ConnArgs conn_args(GetProducerSocket(), true);
+ auto endpoint = ProducerIPCClient::Connect(
+ std::move(conn_args), args.producer, args.producer_name, args.task_runner,
+ TracingService::ProducerSMBScrapingMode::kEnabled, shmem_size_hint,
+ shmem_page_size_hint, std::move(shm), std::move(arbiter),
+ args.create_socket_async);
+ PERFETTO_CHECK(endpoint);
+ return endpoint;
+}
+
+// static
+TracingConsumerBackend* SystemConsumerTracingBackend::GetInstance() {
+ static auto* instance = new SystemConsumerTracingBackend();
+ return instance;
+}
+
+SystemConsumerTracingBackend::SystemConsumerTracingBackend() {}
+
+std::unique_ptr<ConsumerEndpoint> SystemConsumerTracingBackend::ConnectConsumer(
+ const ConnectConsumerArgs& args) {
+#if PERFETTO_BUILDFLAG(PERFETTO_SYSTEM_CONSUMER)
+ auto endpoint = ConsumerIPCClient::Connect(GetConsumerSocket(), args.consumer,
+ args.task_runner);
+ PERFETTO_CHECK(endpoint);
+ return endpoint;
+#else
+ base::ignore_result(args);
+ PERFETTO_FATAL("System backend consumer support disabled");
+ return nullptr;
+#endif
+}
+
+} // namespace internal
+} // namespace perfetto
+// gen_amalgamated begin source: src/tracing/platform_posix.cc
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h"
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_tls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace perfetto {
+
+namespace {
+
+class PlatformPosix : public Platform {
+ public:
+ PlatformPosix();
+ ~PlatformPosix() override;
+
+ ThreadLocalObject* GetOrCreateThreadLocalObject() override;
+
+ std::unique_ptr<base::TaskRunner> CreateTaskRunner(
+ const CreateTaskRunnerArgs&) override;
+ std::string GetCurrentProcessName() override;
+ void Shutdown() override;
+
+ private:
+ pthread_key_t tls_key_{};
+};
+
+PlatformPosix* g_instance = nullptr;
+
+using ThreadLocalObject = Platform::ThreadLocalObject;
+
+PlatformPosix::PlatformPosix() {
+ PERFETTO_CHECK(!g_instance);
+ g_instance = this;
+ auto tls_dtor = [](void* obj) {
+ // The Posix TLS implementation resets the key before calling this dtor.
+ // Here we re-reset it to the object we are about to delete. This is to
+ // handle re-entrant usages of tracing in the PostTask done during the dtor
+ // (see comments in TracingTLS::~TracingTLS()). Chromium's platform
+ // implementation (which does NOT use this platform impl) has a similar
+ // workaround (https://crrev.com/c/2748300).
+ pthread_setspecific(g_instance->tls_key_, obj);
+ delete static_cast<ThreadLocalObject*>(obj);
+ pthread_setspecific(g_instance->tls_key_, nullptr);
+ };
+ PERFETTO_CHECK(pthread_key_create(&tls_key_, tls_dtor) == 0);
+}
+
+PlatformPosix::~PlatformPosix() {
+ // pthread_key_delete doesn't call destructors, so do it manually for the
+ // calling thread.
+ void* tls_ptr = pthread_getspecific(tls_key_);
+ delete static_cast<ThreadLocalObject*>(tls_ptr);
+
+ pthread_key_delete(tls_key_);
+ g_instance = nullptr;
+}
+
+void PlatformPosix::Shutdown() {
+ PERFETTO_CHECK(g_instance == this);
+ delete this;
+ PERFETTO_CHECK(!g_instance);
+ // We're not clearing out the instance in GetDefaultPlatform() since it's not
+ // possible to re-initialize Perfetto after calling this function anyway.
+}
+
+ThreadLocalObject* PlatformPosix::GetOrCreateThreadLocalObject() {
+ // In chromium this should be implemented using base::ThreadLocalStorage.
+ void* tls_ptr = pthread_getspecific(tls_key_);
+
+ // This is needed to handle re-entrant calls during TLS dtor.
+ // See comments in platform.cc and aosp/1712371 .
+ ThreadLocalObject* tls = static_cast<ThreadLocalObject*>(tls_ptr);
+ if (!tls) {
+ tls = ThreadLocalObject::CreateInstance().release();
+ pthread_setspecific(tls_key_, tls);
+ }
+ return tls;
+}
+
+std::unique_ptr<base::TaskRunner> PlatformPosix::CreateTaskRunner(
+ const CreateTaskRunnerArgs& args) {
+ return std::unique_ptr<base::TaskRunner>(new base::ThreadTaskRunner(
+ base::ThreadTaskRunner::CreateAndStart(args.name_for_debugging)));
+}
+
+std::string PlatformPosix::GetCurrentProcessName() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ std::string cmdline;
+ base::ReadFile("/proc/self/cmdline", &cmdline);
+ return cmdline.substr(0, cmdline.find('\0'));
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ return std::string(getprogname());
+#else
+ return "unknown_producer";
+#endif
+}
+
+} // namespace
+
+// static
+Platform* Platform::GetDefaultPlatform() {
+ static PlatformPosix* instance = new PlatformPosix();
+ return instance;
+}
+
+} // namespace perfetto
+#endif // OS_LINUX || OS_ANDROID || OS_APPLE || OS_FUCHSIA
+// gen_amalgamated begin source: src/tracing/platform_windows.cc
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+#include <Windows.h>
+
+// gen_amalgamated expanded: #include "perfetto/ext/base/thread_task_runner.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_tls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
+
+// Thread Termination Callbacks.
+// Windows doesn't support a per-thread destructor with its
+// TLS primitives. So, we build it manually by inserting a
+// function to be called on each thread's exit.
+// This magic is from chromium's base/threading/thread_local_storage_win.cc
+// which in turn is from http://www.codeproject.com/threads/tls.asp.
+
+#ifdef _WIN64
+#pragma comment(linker, "/INCLUDE:_tls_used")
+#pragma comment(linker, "/INCLUDE:perfetto_thread_callback_base")
+#else
+#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_perfetto_thread_callback_base")
+#endif
+
+namespace perfetto {
+
+namespace {
+
+class PlatformWindows : public Platform {
+ public:
+ static PlatformWindows* instance;
+ PlatformWindows();
+ ~PlatformWindows() override;
+
+ ThreadLocalObject* GetOrCreateThreadLocalObject() override;
+ std::unique_ptr<base::TaskRunner> CreateTaskRunner(
+ const CreateTaskRunnerArgs&) override;
+ std::string GetCurrentProcessName() override;
+ void OnThreadExit();
+
+ private:
+ DWORD tls_key_{};
+};
+
+using ThreadLocalObject = Platform::ThreadLocalObject;
+
+// static
+PlatformWindows* PlatformWindows::instance = nullptr;
+
+PlatformWindows::PlatformWindows() {
+ instance = this;
+ tls_key_ = ::TlsAlloc();
+ PERFETTO_CHECK(tls_key_ != TLS_OUT_OF_INDEXES);
+}
+
+PlatformWindows::~PlatformWindows() {
+ ::TlsFree(tls_key_);
+ instance = nullptr;
+}
+
+void PlatformWindows::OnThreadExit() {
+ auto tls = static_cast<ThreadLocalObject*>(::TlsGetValue(tls_key_));
+ if (tls) {
+ // At this point we rely on the TLS object to be still set to the TracingTLS
+ // we are deleting. See comments in TracingTLS::~TracingTLS().
+ delete tls;
+ }
+}
+
+ThreadLocalObject* PlatformWindows::GetOrCreateThreadLocalObject() {
+ void* tls_ptr = ::TlsGetValue(tls_key_);
+
+ auto* tls = static_cast<ThreadLocalObject*>(tls_ptr);
+ if (!tls) {
+ tls = ThreadLocalObject::CreateInstance().release();
+ ::TlsSetValue(tls_key_, tls);
+ }
+ return tls;
+}
+
+std::unique_ptr<base::TaskRunner> PlatformWindows::CreateTaskRunner(
+ const CreateTaskRunnerArgs& args) {
+ return std::unique_ptr<base::TaskRunner>(new base::ThreadTaskRunner(
+ base::ThreadTaskRunner::CreateAndStart(args.name_for_debugging)));
+}
+
+std::string PlatformWindows::GetCurrentProcessName() {
+ char buf[MAX_PATH];
+ auto len = ::GetModuleFileNameA(nullptr /*current*/, buf, sizeof(buf));
+ std::string name(buf, static_cast<size_t>(len));
+ size_t sep = name.find_last_of('\\');
+ if (sep != std::string::npos)
+ name = name.substr(sep + 1);
+ return name;
+}
+
+} // namespace
+
+// static
+Platform* Platform::GetDefaultPlatform() {
+ static PlatformWindows* thread_safe_init_instance = new PlatformWindows();
+ return thread_safe_init_instance;
+}
+
+} // namespace perfetto
+
+// -----------------------
+// Thread-local destructor
+// -----------------------
+
+// .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are
+// called automatically by the OS loader code (not the CRT) when the module is
+// loaded and on thread creation. They are NOT called if the module has been
+// loaded by a LoadLibrary() call. It must have implicitly been loaded at
+// process startup.
+// See VC\crt\src\tlssup.c for reference.
+
+// extern "C" suppresses C++ name mangling so we know the symbol name for the
+// linker /INCLUDE:symbol pragma above.
+extern "C" {
+// The linker must not discard perfetto_thread_callback_base. (We force a
+// reference to this variable with a linker /INCLUDE:symbol pragma to ensure
+// that.) If this variable is discarded, the OnThreadExit function will never be
+// called.
+
+void NTAPI PerfettoOnThreadExit(PVOID, DWORD, PVOID);
+void NTAPI PerfettoOnThreadExit(PVOID, DWORD reason, PVOID) {
+ if (reason == DLL_THREAD_DETACH || reason == DLL_PROCESS_DETACH) {
+ if (perfetto::PlatformWindows::instance)
+ perfetto::PlatformWindows::instance->OnThreadExit();
+ }
+}
+
+#ifdef _WIN64
+
+// .CRT section is merged with .rdata on x64 so it must be constant data.
+#pragma const_seg(".CRT$XLP")
+
+// When defining a const variable, it must have external linkage to be sure the
+// linker doesn't discard it.
+extern const PIMAGE_TLS_CALLBACK perfetto_thread_callback_base;
+const PIMAGE_TLS_CALLBACK perfetto_thread_callback_base = PerfettoOnThreadExit;
+
+// Reset the default section.
+#pragma const_seg()
+
+#else // _WIN64
+
+#pragma data_seg(".CRT$XLP")
+PIMAGE_TLS_CALLBACK perfetto_thread_callback_base = PerfettoOnThreadExit;
+// Reset the default section.
+#pragma data_seg()
+
+#endif // _WIN64
+
+} // extern "C"
+
+#endif // OS_WIN
+
diff --git a/third_party/perfetto/sdk/perfetto.h b/third_party/perfetto/sdk/perfetto.h
new file mode 100644
index 0000000000..72f1187a28
--- /dev/null
+++ b/third_party/perfetto/sdk/perfetto.h
@@ -0,0 +1,164605 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// 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
+//
+// http://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.
+//
+// This file is automatically generated by gen_amalgamated. Do not edit.
+
+// gen_amalgamated begin header: include/perfetto/tracing.h
+// gen_amalgamated begin header: include/perfetto/base/time.h
+// gen_amalgamated begin header: include/perfetto/base/build_config.h
+// gen_amalgamated begin header: gen/build_config/perfetto_build_flags.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// Generated by write_buildflag_header.py
+
+// fix_include_guards: off
+#ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
+#define GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
+
+// clang-format off
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_IPC() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_ON() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_OFF() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERBOSE_LOGS() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TRACED_PERF() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_HEAPPROFD() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STDERR_CRASH_DUMP() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_X64_CPU_OPT() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LLVM_DEMANGLE() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_SYSTEM_CONSUMER() (1)
+
+// clang-format on
+#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
+#define INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
+
+// Allows to define build flags that give a compiler error if the header that
+// defined the flag is not included, instead of silently ignoring the #if block.
+#define PERFETTO_BUILDFLAG_CAT_INDIRECT(a, b) a##b
+#define PERFETTO_BUILDFLAG_CAT(a, b) PERFETTO_BUILDFLAG_CAT_INDIRECT(a, b)
+#define PERFETTO_BUILDFLAG(flag) \
+ (PERFETTO_BUILDFLAG_CAT(PERFETTO_BUILDFLAG_DEFINE_, flag)())
+
+#if defined(__ANDROID__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#elif defined(__APPLE__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+// Include TARGET_OS_IPHONE when on __APPLE__ systems.
+#include <TargetConditionals.h>
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#endif
+#elif defined(__linux__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#elif defined(_WIN32)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#elif defined(__EMSCRIPTEN__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#elif defined(__Fuchsia__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#elif defined(__native_client__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 1
+#else
+#error OS not supported (see build_config.h)
+#endif
+
+#if defined(__clang__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0
+#elif defined(__GNUC__) // Careful: Clang also defines this!
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0
+#elif defined(_MSC_VER)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0
+#endif
+
+#if defined(PERFETTO_BUILD_WITH_ANDROID_USERDEBUG)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 0
+#endif
+
+// Processor architecture detection. For more info on what's defined, see:
+// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+// http://www.agner.org/optimize/calling_conventions.pdf
+// or with gcc, run: "echo | gcc -E -dM -"
+#if defined(__aarch64__) || defined(_M_ARM64)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_ARM64() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ARCH_CPU_ARM64() 0
+#endif
+
+// perfetto_build_flags.h contains the tweakable build flags defined via GN.
+// - In GN builds (e.g., standalone, chromium, v8) this file is generated at
+// build time via the gen_rule //gn/gen_buildflags.
+// - In Android in-tree builds, this file is generated by tools/gen_android_bp
+// and checked in into include/perfetto/base/build_configs/android_tree/. The
+// default cflags add this path to the default include path.
+// - Similarly, in bazel builds, this file is generated by tools/gen_bazel and
+// checked in into include/perfetto/base/build_configs/bazel/.
+// - In amalgamated builds, this file is generated by tools/gen_amalgamated and
+// added to the amalgamated headers.
+// gen_amalgamated expanded: #include "perfetto_build_flags.h" // no-include-violation-check
+
+#endif // INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
+// gen_amalgamated begin header: include/perfetto/base/logging.h
+// gen_amalgamated begin header: include/perfetto/base/compiler.h
+// gen_amalgamated begin header: include/perfetto/public/compiler.h
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PUBLIC_COMPILER_H_
+#define INCLUDE_PERFETTO_PUBLIC_COMPILER_H_
+
+#include <stddef.h>
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_LIKELY(_x) __builtin_expect(!!(_x), 1)
+#define PERFETTO_UNLIKELY(_x) __builtin_expect(!!(_x), 0)
+#else
+#define PERFETTO_LIKELY(_x) (_x)
+#define PERFETTO_UNLIKELY(_x) (_x)
+#endif
+
+// PERFETTO_STATIC_CAST(TYPE, VAL): avoids the -Wold-style-cast warning when
+// writing code that needs to be compiled as C and C++.
+#ifdef __cplusplus
+#define PERFETTO_STATIC_CAST(TYPE, VAL) static_cast<TYPE>(VAL)
+#else
+#define PERFETTO_STATIC_CAST(TYPE, VAL) ((TYPE)(VAL))
+#endif
+
+// PERFETTO_REINTERPRET_CAST(TYPE, VAL): avoids the -Wold-style-cast warning
+// when writing code that needs to be compiled as C and C++.
+#ifdef __cplusplus
+#define PERFETTO_REINTERPRET_CAST(TYPE, VAL) reinterpret_cast<TYPE>(VAL)
+#else
+#define PERFETTO_REINTERPRET_CAST(TYPE, VAL) ((TYPE)(VAL))
+#endif
+
+// PERFETTO_NULL: avoids the -Wzero-as-null-pointer-constant warning when
+// writing code that needs to be compiled as C and C++.
+#ifdef __cplusplus
+#define PERFETTO_NULL nullptr
+#else
+#define PERFETTO_NULL NULL
+#endif
+
+#endif // INCLUDE_PERFETTO_PUBLIC_COMPILER_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_COMPILER_H_
+#define INCLUDE_PERFETTO_BASE_COMPILER_H_
+
+#include <stddef.h>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/public/compiler.h"
+
+// __has_attribute is supported only by clang and recent versions of GCC.
+// Add a layer to wrap the __has_attribute macro.
+#if defined(__has_attribute)
+#define PERFETTO_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define PERFETTO_HAS_ATTRIBUTE(x) 0
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define PERFETTO_WARN_UNUSED_RESULT
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_UNUSED __attribute__((unused))
+#else
+#define PERFETTO_UNUSED
+#endif
+
+#if defined(__clang__)
+#define PERFETTO_ALWAYS_INLINE __attribute__((__always_inline__))
+#define PERFETTO_NO_INLINE __attribute__((__noinline__))
+#else
+// GCC is too pedantic and often fails with the error:
+// "always_inline function might not be inlinable"
+#define PERFETTO_ALWAYS_INLINE
+#define PERFETTO_NO_INLINE
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_NORETURN __attribute__((__noreturn__))
+#else
+#define PERFETTO_NORETURN __declspec(noreturn)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__
+#else
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() \
+ static_assert(false, "Not implemented for this compiler")
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_PRINTF_FORMAT(x, y) \
+ __attribute__((__format__(__printf__, x, y)))
+#else
+#define PERFETTO_PRINTF_FORMAT(x, y)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_POPCOUNT(x) __builtin_popcountll(x)
+#else
+#include <intrin.h>
+#define PERFETTO_POPCOUNT(x) __popcnt64(x)
+#endif
+
+#if defined(__clang__)
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+#include "mozilla/MemoryChecking.h"
+#define PERFETTO_ASAN_POISON(a, s) __asan_poison_memory_region((a), (s))
+#define PERFETTO_ASAN_UNPOISON(a, s) __asan_unpoison_memory_region((a), (s))
+#else
+#define PERFETTO_ASAN_POISON(addr, size)
+#define PERFETTO_ASAN_UNPOISON(addr, size)
+#endif // __has_feature(address_sanitizer)
+#else
+#define PERFETTO_ASAN_POISON(addr, size)
+#define PERFETTO_ASAN_UNPOISON(addr, size)
+#endif // __clang__
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_IS_LITTLE_ENDIAN() __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#else
+// Assume all MSVC targets are little endian.
+#define PERFETTO_IS_LITTLE_ENDIAN() 1
+#endif
+
+// This is used for exporting xxxMain() symbols (e.g., PerfettoCmdMain,
+// ProbesMain) from libperfetto.so when the GN arg monolithic_binaries = false.
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_EXPORT_ENTRYPOINT __attribute__((visibility("default")))
+#else
+// TODO(primiano): on Windows this should be a pair of dllexport/dllimport. But
+// that requires a -DXXX_IMPLEMENTATION depending on whether we are on the
+// impl-site or call-site. Right now it's not worth the trouble as we
+// force-export the xxxMain() symbols only on Android, where we pack all the
+// code for N binaries into one .so to save binary size. On Windows we support
+// only monolithic binaries, as they are easier to deal with.
+#define PERFETTO_EXPORT_ENTRYPOINT
+#endif
+
+// Disables thread safety analysis for functions where the compiler can't
+// accurate figure out which locks are being held.
+#if defined(__clang__)
+#define PERFETTO_NO_THREAD_SAFETY_ANALYSIS \
+ __attribute__((no_thread_safety_analysis))
+#else
+#define PERFETTO_NO_THREAD_SAFETY_ANALYSIS
+#endif
+
+// Disables undefined behavior analysis for a function.
+#if defined(__clang__)
+#define PERFETTO_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
+#else
+#define PERFETTO_NO_SANITIZE_UNDEFINED
+#endif
+
+// Avoid calling the exit-time destructor on an object with static lifetime.
+#if PERFETTO_HAS_ATTRIBUTE(no_destroy)
+#define PERFETTO_HAS_NO_DESTROY() 1
+#define PERFETTO_NO_DESTROY __attribute__((no_destroy))
+#else
+#define PERFETTO_HAS_NO_DESTROY() 0
+#define PERFETTO_NO_DESTROY
+#endif
+
+// Macro for telling -Wimplicit-fallthrough that a fallthrough is intentional.
+#define PERFETTO_FALLTHROUGH [[fallthrough]]
+
+namespace perfetto {
+namespace base {
+
+template <typename... T>
+inline void ignore_result(const T&...) {}
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_COMPILER_H_
+// gen_amalgamated begin header: include/perfetto/base/export.h
+// gen_amalgamated begin header: include/perfetto/public/abi/export.h
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PUBLIC_ABI_EXPORT_H_
+#define INCLUDE_PERFETTO_PUBLIC_ABI_EXPORT_H_
+
+#ifdef _WIN32
+#define PERFETTO_INTERNAL_DLL_EXPORT __declspec(dllexport)
+#define PERFETTO_INTERNAL_DLL_IMPORT __declspec(dllimport)
+#else
+#define PERFETTO_INTERNAL_DLL_EXPORT __attribute__((visibility("default")))
+#define PERFETTO_INTERNAL_DLL_IMPORT
+#endif
+
+// PERFETTO_SDK_EXPORT: Exports a symbol from the perfetto SDK shared library.
+//
+// This is controlled by two defines (that likely come from the compiler command
+// line):
+// * PERFETTO_SDK_DISABLE_SHLIB_EXPORT: If this is defined, no export
+// annotations are added. This might be useful when static linking.
+// * PERFETTO_SDK_SHLIB_IMPLEMENTATION: This must be defined when compiling the
+// shared library itself (in order to export the symbols), but must be
+// undefined when compiling objects that use the shared library (in order to
+// import the symbols).
+#if !defined(PERFETTO_SDK_DISABLE_SHLIB_EXPORT)
+#if defined(PERFETTO_SHLIB_SDK_IMPLEMENTATION)
+#define PERFETTO_SDK_EXPORT PERFETTO_INTERNAL_DLL_EXPORT
+#else
+#define PERFETTO_SDK_EXPORT PERFETTO_INTERNAL_DLL_IMPORT
+#endif
+#else // defined(PERFETTO_SDK_DISABLE_SHLIB_EXPORT)
+#define PERFETTO_SDK_EXPORT
+#endif // defined(PERFETTO_SDK_DISABLE_SHLIB_EXPORT)
+
+#endif // INCLUDE_PERFETTO_PUBLIC_ABI_EXPORT_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_EXPORT_H_
+#define INCLUDE_PERFETTO_BASE_EXPORT_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/public/abi/export.h"
+
+// PERFETTO_EXPORT_COMPONENT: Exports a symbol among C++ components when
+// building with is_component = true (mostly used by chromium build).
+#if PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)
+
+#if defined(PERFETTO_IMPLEMENTATION)
+#define PERFETTO_EXPORT_COMPONENT PERFETTO_INTERNAL_DLL_EXPORT
+#else
+#define PERFETTO_EXPORT_COMPONENT PERFETTO_INTERNAL_DLL_IMPORT
+#endif
+
+#else // !PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)
+
+#if !defined(PERFETTO_EXPORT_COMPONENT)
+#define PERFETTO_EXPORT_COMPONENT
+#endif // !defined(PERFETTO_EXPORT_COMPONENT)
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)
+
+#endif // INCLUDE_PERFETTO_BASE_EXPORT_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_LOGGING_H_
+#define INCLUDE_PERFETTO_BASE_LOGGING_H_
+
+#include <errno.h>
+#include <string.h> // For strerror.
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+#if defined(__GNUC__) || defined(__clang__)
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_ON)
+#define PERFETTO_DCHECK_IS_ON() 1
+#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_OFF)
+#define PERFETTO_DCHECK_IS_ON() 0
+#elif defined(DCHECK_ALWAYS_ON) || \
+ (!defined(NDEBUG) && (PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
+ PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) || \
+ PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)))
+#define PERFETTO_DCHECK_IS_ON() 1
+#else
+#define PERFETTO_DCHECK_IS_ON() 0
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON)
+#define PERFETTO_DLOG_IS_ON() 1
+#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_OFF)
+#define PERFETTO_DLOG_IS_ON() 0
+#else
+#define PERFETTO_DLOG_IS_ON() PERFETTO_DCHECK_IS_ON()
+#endif
+
+#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+#error "Async-safe logging is limited to Android tree builds"
+#endif
+// For binaries which need a very lightweight logging implementation.
+// Note that this header is incompatible with android/log.h.
+#include <async_safe/log.h>
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+// Normal android logging.
+#include <android/log.h>
+#endif
+
+// Enable the "Print the most recent PERFETTO_LOG(s) before crashing" feature
+// on Android in-tree builds and on standalone builds (mainly for testing).
+// This is deliberately no PERFETTO_OS_ANDROID because we don't want this
+// feature when perfetto is embedded in other Android projects (e.g. SDK).
+// TODO(b/203795298): TFLite is using the client library in blaze builds and is
+// targeting API 19. For now disable the feature based on API level.
+#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
+#define PERFETTO_ENABLE_LOG_RING_BUFFER() 0
+#elif PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+#define PERFETTO_ENABLE_LOG_RING_BUFFER() 1
+#elif PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) && \
+ (!PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ (defined(__ANDROID_API__) && __ANDROID_API__ >= 21))
+#define PERFETTO_ENABLE_LOG_RING_BUFFER() 1
+#else
+#define PERFETTO_ENABLE_LOG_RING_BUFFER() 0
+#endif
+
+namespace perfetto {
+namespace base {
+
+// Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c .
+constexpr const char* StrEnd(const char* s) {
+ return *s ? StrEnd(s + 1) : s;
+}
+
+constexpr const char* BasenameRecursive(const char* s,
+ const char* begin,
+ const char* end) {
+ return (*s == '/' && s < end)
+ ? (s + 1)
+ : ((s > begin) ? BasenameRecursive(s - 1, begin, end) : s);
+}
+
+constexpr const char* Basename(const char* str) {
+ return BasenameRecursive(StrEnd(str), str, StrEnd(str));
+}
+
+enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError };
+
+struct LogMessageCallbackArgs {
+ LogLev level;
+ int line;
+ const char* filename;
+ const char* message;
+};
+
+using LogMessageCallback = void (*)(LogMessageCallbackArgs);
+
+// This is not thread safe and must be called before using tracing from other
+// threads.
+PERFETTO_EXPORT_COMPONENT void SetLogMessageCallback(
+ LogMessageCallback callback);
+
+PERFETTO_EXPORT_COMPONENT void LogMessage(LogLev,
+ const char* fname,
+ int line,
+ const char* fmt,
+ ...) PERFETTO_PRINTF_FORMAT(4, 5);
+
+// This is defined in debug_crash_stack_trace.cc, but that is only linked in
+// standalone && debug builds, see enable_perfetto_stderr_crash_dump in
+// perfetto.gni.
+PERFETTO_EXPORT_COMPONENT void EnableStacktraceOnCrashForDebug();
+
+#if PERFETTO_ENABLE_LOG_RING_BUFFER()
+// Gets a snapshot of the logs from the internal log ring buffer and:
+// - On Android in-tree builds: Passes that to android_set_abort_message().
+// That will attach the logs to the crash report.
+// - On standalone builds (all otther OSes) prints that on stderr.
+// This function must called only once, right before inducing a crash (This is
+// because android_set_abort_message() can only be called once).
+PERFETTO_EXPORT_COMPONENT void MaybeSerializeLastLogsForCrashReporting();
+#else
+inline void MaybeSerializeLastLogsForCrashReporting() {}
+#endif
+
+#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
+#define PERFETTO_XLOG(level, fmt, ...) \
+ do { \
+ async_safe_format_log((ANDROID_LOG_DEBUG + level), "perfetto", \
+ "%s:%d " fmt, ::perfetto::base::Basename(__FILE__), \
+ __LINE__, ##__VA_ARGS__); \
+ } while (0)
+#elif defined(PERFETTO_DISABLE_LOG)
+#define PERFETTO_XLOG(level, fmt, ...) ::perfetto::base::ignore_result(level, \
+ fmt, ##__VA_ARGS__)
+#else
+#define PERFETTO_XLOG(level, fmt, ...) \
+ ::perfetto::base::LogMessage(level, ::perfetto::base::Basename(__FILE__), \
+ __LINE__, fmt, ##__VA_ARGS__)
+#endif
+
+#if defined(_MSC_VER)
+#define PERFETTO_IMMEDIATE_CRASH() \
+ do { \
+ ::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \
+ __debugbreak(); \
+ __assume(0); \
+ } while (0)
+#else
+#define PERFETTO_IMMEDIATE_CRASH() \
+ do { \
+ ::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \
+ __builtin_trap(); \
+ __builtin_unreachable(); \
+ } while (0)
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
+#define PERFETTO_LOG(fmt, ...) \
+ PERFETTO_XLOG(::perfetto::base::kLogInfo, fmt, ##__VA_ARGS__)
+#else // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
+#define PERFETTO_LOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
+#endif // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
+
+#define PERFETTO_ILOG(fmt, ...) \
+ PERFETTO_XLOG(::perfetto::base::kLogImportant, fmt, ##__VA_ARGS__)
+#define PERFETTO_ELOG(fmt, ...) \
+ PERFETTO_XLOG(::perfetto::base::kLogError, fmt, ##__VA_ARGS__)
+#define PERFETTO_FATAL(fmt, ...) \
+ do { \
+ PERFETTO_PLOG(fmt, ##__VA_ARGS__); \
+ PERFETTO_IMMEDIATE_CRASH(); \
+ } while (0)
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_PLOG(x, ...) \
+ PERFETTO_ELOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
+#else
+// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
+#define PERFETTO_PLOG PERFETTO_ELOG
+#endif
+
+#define PERFETTO_CHECK(x) \
+ do { \
+ if (PERFETTO_UNLIKELY(!(x))) { \
+ PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \
+ PERFETTO_IMMEDIATE_CRASH(); \
+ } \
+ } while (0)
+
+#if PERFETTO_DLOG_IS_ON()
+
+#define PERFETTO_DLOG(fmt, ...) \
+ PERFETTO_XLOG(::perfetto::base::kLogDebug, fmt, ##__VA_ARGS__)
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_DPLOG(x, ...) \
+ PERFETTO_DLOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
+#else
+// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
+#define PERFETTO_DPLOG PERFETTO_DLOG
+#endif
+
+#else // PERFETTO_DLOG_IS_ON()
+
+#define PERFETTO_DLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
+#define PERFETTO_DPLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
+
+#endif // PERFETTO_DLOG_IS_ON()
+
+#if PERFETTO_DCHECK_IS_ON()
+
+#define PERFETTO_DCHECK(x) PERFETTO_CHECK(x)
+#define PERFETTO_DFATAL(...) PERFETTO_FATAL(__VA_ARGS__)
+#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__)
+
+#else // PERFETTO_DCHECK_IS_ON()
+
+#define PERFETTO_DCHECK(x) \
+ do { \
+ } while (false && (x))
+
+#define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__)
+#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__)
+
+#endif // PERFETTO_DCHECK_IS_ON()
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_LOGGING_H_
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_TIME_H_
+#define INCLUDE_PERFETTO_BASE_TIME_H_
+
+#include <time.h>
+
+#include <chrono>
+#include <optional>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <mach/mach_init.h>
+#include <mach/mach_port.h>
+#include <mach/mach_time.h>
+#include <mach/thread_act.h>
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+#include <emscripten/emscripten.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+using TimeSeconds = std::chrono::seconds;
+using TimeMillis = std::chrono::milliseconds;
+using TimeNanos = std::chrono::nanoseconds;
+
+inline TimeNanos FromPosixTimespec(const struct timespec& ts) {
+ return TimeNanos(ts.tv_sec * 1000000000LL + ts.tv_nsec);
+}
+
+void SleepMicroseconds(unsigned interval_us);
+void InitializeTime();
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+TimeNanos GetWallTimeNs();
+TimeNanos GetThreadCPUTimeNs();
+inline TimeNanos GetWallTimeRawNs() {
+ return GetWallTimeNs();
+}
+
+// TODO: Clock that counts time during suspend is not implemented on Windows.
+inline TimeNanos GetBootTimeNs() {
+ return GetWallTimeNs();
+}
+
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+
+inline TimeNanos GetWallTimeNs() {
+ auto init_timebase_info = []() -> mach_timebase_info_data_t {
+ mach_timebase_info_data_t timebase_info;
+ mach_timebase_info(&timebase_info);
+ return timebase_info;
+ };
+
+ static mach_timebase_info_data_t timebase_info = init_timebase_info();
+ uint64_t mach_time = mach_absolute_time();
+
+ // Take the fast path when the conversion is 1:1. The result will for sure fit
+ // into an int_64 because we're going from nanoseconds to microseconds.
+ if (timebase_info.numer == timebase_info.denom) {
+ return TimeNanos(mach_time);
+ }
+
+ // Nanoseconds is mach_time * timebase.numer // timebase.denom. Divide first
+ // to reduce the chance of overflow. Also stash the remainder right now,
+ // a likely byproduct of the division.
+ uint64_t nanoseconds = mach_time / timebase_info.denom;
+ const uint64_t mach_time_remainder = mach_time % timebase_info.denom;
+
+ // Now multiply, keeping an eye out for overflow.
+ PERFETTO_CHECK(!__builtin_umulll_overflow(nanoseconds, timebase_info.numer,
+ &nanoseconds));
+
+ // By dividing first we lose precision. Regain it by adding back the
+ // nanoseconds from the remainder, with an eye out for overflow.
+ uint64_t least_significant_nanoseconds =
+ (mach_time_remainder * timebase_info.numer) / timebase_info.denom;
+ PERFETTO_CHECK(!__builtin_uaddll_overflow(
+ nanoseconds, least_significant_nanoseconds, &nanoseconds));
+
+ return TimeNanos(nanoseconds);
+}
+
+inline TimeNanos GetWallTimeRawNs() {
+ return GetWallTimeNs();
+}
+
+// TODO: Clock that counts time during suspend is not implemented on Mac.
+inline TimeNanos GetBootTimeNs() {
+ return GetWallTimeNs();
+}
+
+// Before MacOS 10.12 clock_gettime() was not implemented.
+#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101200
+inline TimeNanos GetThreadCPUTimeNs() {
+ mach_port_t this_thread = mach_thread_self();
+ mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
+ thread_basic_info_data_t info{};
+ kern_return_t kr =
+ thread_info(this_thread, THREAD_BASIC_INFO,
+ reinterpret_cast<thread_info_t>(&info), &count);
+ mach_port_deallocate(mach_task_self(), this_thread);
+
+ if (kr != KERN_SUCCESS) {
+ PERFETTO_DFATAL("Failed to get CPU time.");
+ return TimeNanos(0);
+ }
+ return TimeNanos(info.user_time.seconds * 1000000000LL +
+ info.user_time.microseconds * 1000LL +
+ info.system_time.seconds * 1000000000LL +
+ info.system_time.microseconds * 1000LL);
+}
+#else
+inline TimeNanos GetThreadCPUTimeNs() {
+ struct timespec ts = {};
+ PERFETTO_CHECK(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0);
+ return FromPosixTimespec(ts);
+}
+#endif
+
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+
+inline TimeNanos GetWallTimeNs() {
+ return TimeNanos(static_cast<uint64_t>(emscripten_get_now()) * 1000000);
+}
+
+inline TimeNanos GetWallTimeRawNs() {
+ return GetWallTimeNs();
+}
+
+inline TimeNanos GetThreadCPUTimeNs() {
+ return TimeNanos(0);
+}
+
+// TODO: Clock that counts time during suspend is not implemented on WASM.
+inline TimeNanos GetBootTimeNs() {
+ return GetWallTimeNs();
+}
+
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+
+// Tracing time doesn't need to work on NaCl since its going away shortly. We
+// just need to compile on it. The only function NaCl could support is
+// GetWallTimeNs(), but to prevent false hope we leave it unimplemented.
+
+inline TimeNanos GetWallTimeNs() {
+ return TimeNanos(0);
+}
+
+inline TimeNanos GetWallTimeRawNs() {
+ return TimeNanos(0);
+}
+
+inline TimeNanos GetThreadCPUTimeNs() {
+ return TimeNanos(0);
+}
+
+inline TimeNanos GetBootTimeNs() {
+ return TimeNanos(0);
+}
+
+#else // posix
+
+constexpr clockid_t kWallTimeClockSource = CLOCK_MONOTONIC;
+
+inline TimeNanos GetTimeInternalNs(clockid_t clk_id) {
+ struct timespec ts = {};
+ PERFETTO_CHECK(clock_gettime(clk_id, &ts) == 0);
+ return FromPosixTimespec(ts);
+}
+
+// Return ns from boot. Conversely to GetWallTimeNs, this clock counts also time
+// during suspend (when supported).
+inline TimeNanos GetBootTimeNs() {
+ // Determine if CLOCK_BOOTTIME is available on the first call.
+ static const clockid_t kBootTimeClockSource = [] {
+ struct timespec ts = {};
+ int res = clock_gettime(CLOCK_BOOTTIME, &ts);
+ return res == 0 ? CLOCK_BOOTTIME : kWallTimeClockSource;
+ }();
+ return GetTimeInternalNs(kBootTimeClockSource);
+}
+
+inline TimeNanos GetWallTimeNs() {
+ return GetTimeInternalNs(kWallTimeClockSource);
+}
+
+inline TimeNanos GetWallTimeRawNs() {
+ return GetTimeInternalNs(CLOCK_MONOTONIC_RAW);
+}
+
+inline TimeNanos GetThreadCPUTimeNs() {
+ return GetTimeInternalNs(CLOCK_THREAD_CPUTIME_ID);
+}
+#endif
+
+inline TimeSeconds GetBootTimeS() {
+ return std::chrono::duration_cast<TimeSeconds>(GetBootTimeNs());
+}
+
+inline TimeMillis GetBootTimeMs() {
+ return std::chrono::duration_cast<TimeMillis>(GetBootTimeNs());
+}
+
+inline TimeMillis GetWallTimeMs() {
+ return std::chrono::duration_cast<TimeMillis>(GetWallTimeNs());
+}
+
+inline TimeSeconds GetWallTimeS() {
+ return std::chrono::duration_cast<TimeSeconds>(GetWallTimeNs());
+}
+
+inline struct timespec ToPosixTimespec(TimeMillis time) {
+ struct timespec ts {};
+ const long time_s = static_cast<long>(time.count() / 1000);
+ ts.tv_sec = time_s;
+ ts.tv_nsec = (static_cast<long>(time.count()) - time_s * 1000L) * 1000000L;
+ return ts;
+}
+
+std::string GetTimeFmt(const std::string& fmt);
+
+inline int64_t TimeGm(struct tm* tms) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ return static_cast<int64_t>(_mkgmtime(tms));
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+ // NaCL has no timegm.
+ if (tms) // Kinda if (true), but avoids "mark as noreturn" errors.
+ PERFETTO_FATAL("timegm not supported");
+ return -1;
+#else
+ return static_cast<int64_t>(timegm(tms));
+#endif
+}
+
+// Creates a time_t-compatible timestamp (seconds since epoch) from a tuple of
+// y-m-d-h-m-s. It's a saner version of timegm(). Some remarks:
+// The year is just the actual year (it's Y-1900 in timegm()).
+// The month ranges 1-12 (it's 0-11 in timegm()).
+inline int64_t MkTime(int year, int month, int day, int h, int m, int s) {
+ PERFETTO_DCHECK(year >= 1900);
+ PERFETTO_DCHECK(month > 0 && month <= 12);
+ PERFETTO_DCHECK(day > 0 && day <= 31);
+ struct tm tms {};
+ tms.tm_year = year - 1900;
+ tms.tm_mon = month - 1;
+ tms.tm_mday = day;
+ tms.tm_hour = h;
+ tms.tm_min = m;
+ tms.tm_sec = s;
+ return TimeGm(&tms);
+}
+
+std::optional<int32_t> GetTimezoneOffsetMins();
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_TIME_H_
+// gen_amalgamated begin header: include/perfetto/tracing/buffer_exhausted_policy.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
+#define INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
+
+namespace perfetto {
+
+// Determines how SharedMemoryArbiterImpl::GetNewChunk() behaves when no free
+// chunks are available.
+enum class BufferExhaustedPolicy {
+ // SharedMemoryArbiterImpl::GetNewChunk() will stall if no free SMB chunk is
+ // available and wait for the tracing service to free one. Note that this
+ // requires that messages the arbiter sends to the tracing service (from any
+ // TraceWriter thread) will be received by it, even if all TraceWriter threads
+ // are stalled.
+ kStall,
+
+ // SharedMemoryArbiterImpl::GetNewChunk() will return an invalid chunk if no
+ // free SMB chunk is available. In this case, the TraceWriter will fall back
+ // to a garbage chunk and drop written data until acquiring a future chunk
+ // succeeds again.
+ kDrop,
+
+ // TODO(eseckler): Switch to kDrop by default and change the Android code to
+ // explicitly request kStall instead.
+ kDefault = kStall
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
+// gen_amalgamated begin header: include/perfetto/tracing/console_interceptor.h
+// gen_amalgamated begin header: include/perfetto/tracing/interceptor.h
+// gen_amalgamated begin header: include/perfetto/protozero/field.h
+// gen_amalgamated begin header: include/perfetto/protozero/contiguous_memory_range.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
+#define INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+namespace protozero {
+
+// Keep this struct trivially constructible (no ctors, no default initializers).
+struct ContiguousMemoryRange {
+ uint8_t* begin;
+ uint8_t* end; // STL style: one byte past the end of the buffer.
+
+ inline bool is_valid() const { return begin != nullptr; }
+ inline void reset() { begin = nullptr; }
+ inline size_t size() const { return static_cast<size_t>(end - begin); }
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
+// gen_amalgamated begin header: include/perfetto/protozero/proto_utils.h
+// gen_amalgamated begin header: include/perfetto/public/pb_utils.h
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PUBLIC_PB_UTILS_H_
+#define INCLUDE_PERFETTO_PUBLIC_PB_UTILS_H_
+
+#include <assert.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/public/compiler.h"
+
+// Type of fields that can be found in a protobuf serialized message.
+enum PerfettoPbWireType {
+ PERFETTO_PB_WIRE_TYPE_VARINT = 0,
+ PERFETTO_PB_WIRE_TYPE_FIXED64 = 1,
+ PERFETTO_PB_WIRE_TYPE_DELIMITED = 2,
+ PERFETTO_PB_WIRE_TYPE_FIXED32 = 5,
+};
+
+// Creates a field tag, which encodes the field type and the field id.
+static inline uint32_t PerfettoPbMakeTag(int32_t field_id,
+ enum PerfettoPbWireType wire_type) {
+ return ((PERFETTO_STATIC_CAST(uint32_t, field_id)) << 3) |
+ PERFETTO_STATIC_CAST(uint32_t, wire_type);
+}
+
+enum {
+ // Maximum bytes size of a 64-bit integer encoded as a VarInt.
+ PERFETTO_PB_VARINT_MAX_SIZE_64 = 10,
+ // Maximum bytes size of a 32-bit integer encoded as a VarInt.
+ PERFETTO_PB_VARINT_MAX_SIZE_32 = 5,
+};
+
+// Encodes `value` as a VarInt into `*dst`.
+//
+// `dst` must point into a buffer big enough to represent `value`:
+// PERFETTO_PB_VARINT_MAX_SIZE_* can help.
+static inline uint8_t* PerfettoPbWriteVarInt(uint64_t value, uint8_t* dst) {
+ uint8_t byte;
+ while (value >= 0x80) {
+ byte = (value & 0x7f) | 0x80;
+ *dst++ = byte;
+ value >>= 7;
+ }
+ byte = value & 0x7f;
+ *dst++ = byte;
+
+ return dst;
+}
+
+// Encodes `value` as a fixed32 (little endian) into `*dst`.
+//
+// `dst` must point into a buffer with at least 4 bytes of space.
+static inline uint8_t* PerfettoPbWriteFixed32(uint32_t value, uint8_t* buf) {
+ buf[0] = PERFETTO_STATIC_CAST(uint8_t, value);
+ buf[1] = PERFETTO_STATIC_CAST(uint8_t, value >> 8);
+ buf[2] = PERFETTO_STATIC_CAST(uint8_t, value >> 16);
+ buf[3] = PERFETTO_STATIC_CAST(uint8_t, value >> 24);
+ return buf + 4;
+}
+
+// Encodes `value` as a fixed32 (little endian) into `*dst`.
+//
+// `dst` must point into a buffer with at least 8 bytes of space.
+static inline uint8_t* PerfettoPbWriteFixed64(uint64_t value, uint8_t* buf) {
+ buf[0] = PERFETTO_STATIC_CAST(uint8_t, value);
+ buf[1] = PERFETTO_STATIC_CAST(uint8_t, value >> 8);
+ buf[2] = PERFETTO_STATIC_CAST(uint8_t, value >> 16);
+ buf[3] = PERFETTO_STATIC_CAST(uint8_t, value >> 24);
+ buf[4] = PERFETTO_STATIC_CAST(uint8_t, value >> 32);
+ buf[5] = PERFETTO_STATIC_CAST(uint8_t, value >> 40);
+ buf[6] = PERFETTO_STATIC_CAST(uint8_t, value >> 48);
+ buf[7] = PERFETTO_STATIC_CAST(uint8_t, value >> 56);
+ return buf + 8;
+}
+
+// Parses a VarInt from the encoded buffer [start, end). |end| is STL-style and
+// points one byte past the end of buffer.
+// The parsed int value is stored in the output arg |value|. Returns a pointer
+// to the next unconsumed byte (so start < retval <= end) or |start| if the
+// VarInt could not be fully parsed because there was not enough space in the
+// buffer.
+static inline const uint8_t* PerfettoPbParseVarInt(const uint8_t* start,
+ const uint8_t* end,
+ uint64_t* out_value) {
+ const uint8_t* pos = start;
+ uint64_t value = 0;
+ for (uint32_t shift = 0; pos < end && shift < 64u; shift += 7) {
+ // Cache *pos into |cur_byte| to prevent that the compiler dereferences the
+ // pointer twice (here and in the if() below) due to char* aliasing rules.
+ uint8_t cur_byte = *pos++;
+ value |= PERFETTO_STATIC_CAST(uint64_t, cur_byte & 0x7f) << shift;
+ if ((cur_byte & 0x80) == 0) {
+ // In valid cases we get here.
+ *out_value = value;
+ return pos;
+ }
+ }
+ *out_value = 0;
+ return start;
+}
+
+static inline uint32_t PerfettoPbZigZagEncode32(int32_t value) {
+#if defined(__cplusplus) || \
+ (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
+ // Right-shift of negative values is implementation specific.
+ // Assert the implementation does what we expect, which is that shifting an
+ // positive int32_t by 31 gives an all 0 bitmap, and a negative int32_t gives
+ // an all 1 bitmap.
+ static_assert(
+ PERFETTO_STATIC_CAST(uint32_t, INT32_C(-1) >> 31) == ~UINT32_C(0),
+ "implementation does not support assumed rightshift");
+ static_assert(PERFETTO_STATIC_CAST(uint32_t, INT32_C(1) >> 31) == UINT32_C(0),
+ "implementation does not support assumed rightshift");
+#endif
+
+ return (PERFETTO_STATIC_CAST(uint32_t, value) << 1) ^
+ PERFETTO_STATIC_CAST(uint32_t, value >> 31);
+}
+
+static inline uint64_t PerfettoPbZigZagEncode64(int64_t value) {
+#if defined(__cplusplus) || \
+ (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
+ // Right-shift of negative values is implementation specific.
+ // Assert the implementation does what we expect, which is that shifting an
+ // positive int64_t by 63 gives an all 0 bitmap, and a negative int64_t gives
+ // an all 1 bitmap.
+ static_assert(
+ PERFETTO_STATIC_CAST(uint64_t, INT64_C(-1) >> 63) == ~UINT64_C(0),
+ "implementation does not support assumed rightshift");
+ static_assert(PERFETTO_STATIC_CAST(uint64_t, INT64_C(1) >> 63) == UINT64_C(0),
+ "implementation does not support assumed rightshift");
+#endif
+
+ return (PERFETTO_STATIC_CAST(uint64_t, value) << 1) ^
+ PERFETTO_STATIC_CAST(uint64_t, value >> 63);
+}
+
+static inline int32_t PerfettoPbZigZagDecode32(uint32_t value) {
+ uint32_t mask =
+ PERFETTO_STATIC_CAST(uint32_t, -PERFETTO_STATIC_CAST(int32_t, value & 1));
+ return PERFETTO_STATIC_CAST(int32_t, ((value >> 1) ^ mask));
+}
+
+static inline int64_t PerfettoPbZigZagDecode64(uint64_t value) {
+ uint64_t mask =
+ PERFETTO_STATIC_CAST(uint64_t, -PERFETTO_STATIC_CAST(int64_t, value & 1));
+ return PERFETTO_STATIC_CAST(int64_t, ((value >> 1) ^ mask));
+}
+
+#endif // INCLUDE_PERFETTO_PUBLIC_PB_UTILS_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
+#define INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
+
+#include <stddef.h>
+
+#include <cinttypes>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/public/pb_utils.h"
+
+// Helper macro for the constexpr functions containing
+// the switch statement: if C++14 is supported, this macro
+// resolves to `constexpr` and just `inline` otherwise.
+#if __cpp_constexpr >= 201304
+#define PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE constexpr
+#else
+#define PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE inline
+#endif
+
+namespace protozero {
+namespace proto_utils {
+
+// See https://developers.google.com/protocol-buffers/docs/encoding wire types.
+// This is a type encoded into the proto that provides just enough info to
+// find the length of the following value.
+enum class ProtoWireType : uint32_t {
+ kVarInt = 0,
+ kFixed64 = 1,
+ kLengthDelimited = 2,
+ kFixed32 = 5,
+};
+
+// This is the type defined in the proto for each field. This information
+// is used to decide the translation strategy when writing the trace.
+enum class ProtoSchemaType {
+ kUnknown = 0,
+ kDouble,
+ kFloat,
+ kInt64,
+ kUint64,
+ kInt32,
+ kFixed64,
+ kFixed32,
+ kBool,
+ kString,
+ kGroup, // Deprecated (proto2 only)
+ kMessage,
+ kBytes,
+ kUint32,
+ kEnum,
+ kSfixed32,
+ kSfixed64,
+ kSint32,
+ kSint64,
+};
+
+inline const char* ProtoSchemaToString(ProtoSchemaType v) {
+ switch (v) {
+ case ProtoSchemaType::kUnknown:
+ return "unknown";
+ case ProtoSchemaType::kDouble:
+ return "double";
+ case ProtoSchemaType::kFloat:
+ return "float";
+ case ProtoSchemaType::kInt64:
+ return "int64";
+ case ProtoSchemaType::kUint64:
+ return "uint64";
+ case ProtoSchemaType::kInt32:
+ return "int32";
+ case ProtoSchemaType::kFixed64:
+ return "fixed64";
+ case ProtoSchemaType::kFixed32:
+ return "fixed32";
+ case ProtoSchemaType::kBool:
+ return "bool";
+ case ProtoSchemaType::kString:
+ return "string";
+ case ProtoSchemaType::kGroup:
+ return "group";
+ case ProtoSchemaType::kMessage:
+ return "message";
+ case ProtoSchemaType::kBytes:
+ return "bytes";
+ case ProtoSchemaType::kUint32:
+ return "uint32";
+ case ProtoSchemaType::kEnum:
+ return "enum";
+ case ProtoSchemaType::kSfixed32:
+ return "sfixed32";
+ case ProtoSchemaType::kSfixed64:
+ return "sfixed64";
+ case ProtoSchemaType::kSint32:
+ return "sint32";
+ case ProtoSchemaType::kSint64:
+ return "sint64";
+ }
+ // For gcc:
+ PERFETTO_DCHECK(false);
+ return "";
+}
+
+// Maximum message size supported: 256 MiB (4 x 7-bit due to varint encoding).
+constexpr size_t kMessageLengthFieldSize = 4;
+constexpr size_t kMaxMessageLength = (1u << (kMessageLengthFieldSize * 7)) - 1;
+constexpr size_t kMaxOneByteMessageLength = (1 << 7) - 1;
+
+// Field tag is encoded as 32-bit varint (5 bytes at most).
+// Largest value of simple (not length-delimited) field is 64-bit varint
+// (10 bytes at most). 15 bytes buffer is enough to store a simple field.
+constexpr size_t kMaxTagEncodedSize = 5;
+constexpr size_t kMaxSimpleFieldEncodedSize = kMaxTagEncodedSize + 10;
+
+// Proto types: (int|uint|sint)(32|64), bool, enum.
+constexpr uint32_t MakeTagVarInt(uint32_t field_id) {
+ return (field_id << 3) | static_cast<uint32_t>(ProtoWireType::kVarInt);
+}
+
+// Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float.
+template <typename T>
+constexpr uint32_t MakeTagFixed(uint32_t field_id) {
+ static_assert(sizeof(T) == 8 || sizeof(T) == 4, "Value must be 4 or 8 bytes");
+ return (field_id << 3) |
+ static_cast<uint32_t>((sizeof(T) == 8 ? ProtoWireType::kFixed64
+ : ProtoWireType::kFixed32));
+}
+
+// Proto types: string, bytes, embedded messages.
+constexpr uint32_t MakeTagLengthDelimited(uint32_t field_id) {
+ return (field_id << 3) |
+ static_cast<uint32_t>(ProtoWireType::kLengthDelimited);
+}
+
+// Proto types: sint64, sint32.
+template <typename T>
+inline typename std::make_unsigned<T>::type ZigZagEncode(T value) {
+ using UnsignedType = typename std::make_unsigned<T>::type;
+
+ // Right-shift of negative values is implementation specific.
+ // Assert the implementation does what we expect, which is that shifting any
+ // positive value by sizeof(T) * 8 - 1 gives an all 0 bitmap, and a negative
+ // value gives an all 1 bitmap.
+ constexpr uint64_t kUnsignedZero = 0u;
+ constexpr int64_t kNegativeOne = -1;
+ constexpr int64_t kPositiveOne = 1;
+ static_assert(static_cast<uint64_t>(kNegativeOne >> 63) == ~kUnsignedZero,
+ "implementation does not support assumed rightshift");
+ static_assert(static_cast<uint64_t>(kPositiveOne >> 63) == kUnsignedZero,
+ "implementation does not support assumed rightshift");
+
+ return (static_cast<UnsignedType>(value) << 1) ^
+ static_cast<UnsignedType>(value >> (sizeof(T) * 8 - 1));
+}
+
+// Proto types: sint64, sint32.
+template <typename T>
+inline typename std::make_signed<T>::type ZigZagDecode(T value) {
+ using UnsignedType = typename std::make_unsigned<T>::type;
+ using SignedType = typename std::make_signed<T>::type;
+ auto u_value = static_cast<UnsignedType>(value);
+ auto mask = static_cast<UnsignedType>(-static_cast<SignedType>(u_value & 1));
+ return static_cast<SignedType>((u_value >> 1) ^ mask);
+}
+
+template <typename T>
+auto ExtendValueForVarIntSerialization(T value) -> typename std::make_unsigned<
+ typename std::conditional<std::is_unsigned<T>::value, T, int64_t>::type>::
+ type {
+ // If value is <= 0 we must first sign extend to int64_t (see [1]).
+ // Finally we always cast to an unsigned value to to avoid arithmetic
+ // (sign expanding) shifts in the while loop.
+ // [1]: "If you use int32 or int64 as the type for a negative number, the
+ // resulting varint is always ten bytes long".
+ // - developers.google.com/protocol-buffers/docs/encoding
+ // So for each input type we do the following casts:
+ // uintX_t -> uintX_t -> uintX_t
+ // int8_t -> int64_t -> uint64_t
+ // int16_t -> int64_t -> uint64_t
+ // int32_t -> int64_t -> uint64_t
+ // int64_t -> int64_t -> uint64_t
+ using MaybeExtendedType =
+ typename std::conditional<std::is_unsigned<T>::value, T, int64_t>::type;
+ using UnsignedType = typename std::make_unsigned<MaybeExtendedType>::type;
+
+ MaybeExtendedType extended_value = static_cast<MaybeExtendedType>(value);
+ UnsignedType unsigned_value = static_cast<UnsignedType>(extended_value);
+
+ return unsigned_value;
+}
+
+template <typename T>
+inline uint8_t* WriteVarInt(T value, uint8_t* target) {
+ auto unsigned_value = ExtendValueForVarIntSerialization(value);
+
+ while (unsigned_value >= 0x80) {
+ *target++ = static_cast<uint8_t>(unsigned_value) | 0x80;
+ unsigned_value >>= 7;
+ }
+ *target = static_cast<uint8_t>(unsigned_value);
+ return target + 1;
+}
+
+// Writes a fixed-size redundant encoding of the given |value|. This is
+// used to backfill fixed-size reservations for the length field using a
+// non-canonical varint encoding (e.g. \x81\x80\x80\x00 instead of \x01).
+// See https://github.com/google/protobuf/issues/1530.
+// This is used mainly in two cases:
+// 1) At trace writing time, when starting a nested messages. The size of a
+// nested message is not known until all its field have been written.
+// |kMessageLengthFieldSize| bytes are reserved to encode the size field and
+// backfilled at the end.
+// 2) When rewriting a message at trace filtering time, in protozero/filtering.
+// At that point we know only the upper bound of the length (a filtered
+// message is <= the original one) and we backfill after the message has been
+// filtered.
+inline void WriteRedundantVarInt(uint32_t value,
+ uint8_t* buf,
+ size_t size = kMessageLengthFieldSize) {
+ for (size_t i = 0; i < size; ++i) {
+ const uint8_t msb = (i < size - 1) ? 0x80 : 0;
+ buf[i] = static_cast<uint8_t>(value) | msb;
+ value >>= 7;
+ }
+}
+
+template <uint32_t field_id>
+void StaticAssertSingleBytePreamble() {
+ static_assert(field_id < 16,
+ "Proto field id too big to fit in a single byte preamble");
+}
+
+// Parses a VarInt from the encoded buffer [start, end). |end| is STL-style and
+// points one byte past the end of buffer.
+// The parsed int value is stored in the output arg |value|. Returns a pointer
+// to the next unconsumed byte (so start < retval <= end) or |start| if the
+// VarInt could not be fully parsed because there was not enough space in the
+// buffer.
+inline const uint8_t* ParseVarInt(const uint8_t* start,
+ const uint8_t* end,
+ uint64_t* out_value) {
+ return PerfettoPbParseVarInt(start, end, out_value);
+}
+
+enum class RepetitionType {
+ kNotRepeated,
+ kRepeatedPacked,
+ kRepeatedNotPacked,
+};
+
+// Provide a common base struct for all templated FieldMetadata types to allow
+// simple checks if a given type is a FieldMetadata or not.
+struct FieldMetadataBase {
+ constexpr FieldMetadataBase() = default;
+};
+
+template <uint32_t field_id,
+ RepetitionType repetition_type,
+ ProtoSchemaType proto_schema_type,
+ typename CppFieldType,
+ typename MessageType>
+struct FieldMetadata : public FieldMetadataBase {
+ constexpr FieldMetadata() = default;
+
+ static constexpr int kFieldId = field_id;
+ // Whether this field is repeated, packed (repeated [packed-true]) or not
+ // (optional).
+ static constexpr RepetitionType kRepetitionType = repetition_type;
+ // Proto type of this field (e.g. int64, fixed32 or nested message).
+ static constexpr ProtoSchemaType kProtoFieldType = proto_schema_type;
+ // C++ type of this field (for nested messages - C++ protozero class).
+ using cpp_field_type = CppFieldType;
+ // Protozero message which this field belongs to.
+ using message_type = MessageType;
+};
+
+} // namespace proto_utils
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_FIELD_H_
+#define INCLUDE_PERFETTO_PROTOZERO_FIELD_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace protozero {
+
+struct ConstBytes {
+ std::string ToStdString() const {
+ return std::string(reinterpret_cast<const char*>(data), size);
+ }
+
+ const uint8_t* data;
+ size_t size;
+};
+
+struct ConstChars {
+ // Allow implicit conversion to perfetto's base::StringView without depending
+ // on perfetto/base or viceversa.
+ static constexpr bool kConvertibleToStringView = true;
+ std::string ToStdString() const { return std::string(data, size); }
+
+ const char* data;
+ size_t size;
+};
+
+// A protobuf field decoded by the protozero proto decoders. It exposes
+// convenience accessors with minimal debug checks.
+// This class is used both by the iterator-based ProtoDecoder and by the
+// one-shot TypedProtoDecoder.
+// If the field is not valid the accessors consistently return zero-integers or
+// null strings.
+class Field {
+ public:
+ bool valid() const { return id_ != 0; }
+ uint32_t id() const { return id_; }
+ explicit operator bool() const { return valid(); }
+
+ proto_utils::ProtoWireType type() const {
+ auto res = static_cast<proto_utils::ProtoWireType>(type_);
+ PERFETTO_DCHECK(res == proto_utils::ProtoWireType::kVarInt ||
+ res == proto_utils::ProtoWireType::kLengthDelimited ||
+ res == proto_utils::ProtoWireType::kFixed32 ||
+ res == proto_utils::ProtoWireType::kFixed64);
+ return res;
+ }
+
+ bool as_bool() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
+ return static_cast<bool>(int_value_);
+ }
+
+ uint32_t as_uint32() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
+ type() == proto_utils::ProtoWireType::kFixed32);
+ return static_cast<uint32_t>(int_value_);
+ }
+
+ int32_t as_int32() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
+ type() == proto_utils::ProtoWireType::kFixed32);
+ return static_cast<int32_t>(int_value_);
+ }
+
+ int32_t as_sint32() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
+ return proto_utils::ZigZagDecode(static_cast<uint32_t>(int_value_));
+ }
+
+ uint64_t as_uint64() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
+ type() == proto_utils::ProtoWireType::kFixed32 ||
+ type() == proto_utils::ProtoWireType::kFixed64);
+ return int_value_;
+ }
+
+ int64_t as_int64() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
+ type() == proto_utils::ProtoWireType::kFixed32 ||
+ type() == proto_utils::ProtoWireType::kFixed64);
+ return static_cast<int64_t>(int_value_);
+ }
+
+ int64_t as_sint64() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
+ return proto_utils::ZigZagDecode(static_cast<uint64_t>(int_value_));
+ }
+
+ float as_float() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed32);
+ float res;
+ uint32_t value32 = static_cast<uint32_t>(int_value_);
+ memcpy(&res, &value32, sizeof(res));
+ return res;
+ }
+
+ double as_double() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed64);
+ double res;
+ memcpy(&res, &int_value_, sizeof(res));
+ return res;
+ }
+
+ ConstChars as_string() const {
+ PERFETTO_DCHECK(!valid() ||
+ type() == proto_utils::ProtoWireType::kLengthDelimited);
+ return ConstChars{reinterpret_cast<const char*>(data()), size_};
+ }
+
+ std::string as_std_string() const { return as_string().ToStdString(); }
+
+ ConstBytes as_bytes() const {
+ PERFETTO_DCHECK(!valid() ||
+ type() == proto_utils::ProtoWireType::kLengthDelimited);
+ return ConstBytes{data(), size_};
+ }
+
+ const uint8_t* data() const {
+ PERFETTO_DCHECK(!valid() ||
+ type() == proto_utils::ProtoWireType::kLengthDelimited);
+ return reinterpret_cast<const uint8_t*>(int_value_);
+ }
+
+ size_t size() const {
+ PERFETTO_DCHECK(!valid() ||
+ type() == proto_utils::ProtoWireType::kLengthDelimited);
+ return size_;
+ }
+
+ uint64_t raw_int_value() const { return int_value_; }
+
+ void initialize(uint32_t id,
+ uint8_t type,
+ uint64_t int_value,
+ uint32_t size) {
+ id_ = id & kMaxId;
+ type_ = type;
+ int_value_ = int_value;
+ size_ = size;
+ }
+
+ // For use with templates. This is used by RepeatedFieldIterator::operator*().
+ void get(bool* val) const { *val = as_bool(); }
+ void get(uint32_t* val) const { *val = as_uint32(); }
+ void get(int32_t* val) const { *val = as_int32(); }
+ void get(uint64_t* val) const { *val = as_uint64(); }
+ void get(int64_t* val) const { *val = as_int64(); }
+ void get(float* val) const { *val = as_float(); }
+ void get(double* val) const { *val = as_double(); }
+ void get(std::string* val) const { *val = as_std_string(); }
+ void get(ConstChars* val) const { *val = as_string(); }
+ void get(ConstBytes* val) const { *val = as_bytes(); }
+ void get_signed(int32_t* val) const { *val = as_sint32(); }
+ void get_signed(int64_t* val) const { *val = as_sint64(); }
+
+ // For enum types.
+ template <typename T,
+ typename = typename std::enable_if<std::is_enum<T>::value, T>::type>
+ void get(T* val) const {
+ *val = static_cast<T>(as_int32());
+ }
+
+ // Serializes the field back into a proto-encoded byte stream and appends it
+ // to |dst|. |dst| is resized accordingly.
+ void SerializeAndAppendTo(std::string* dst) const;
+
+ // Serializes the field back into a proto-encoded byte stream and appends it
+ // to |dst|. |dst| is resized accordingly.
+ void SerializeAndAppendTo(std::vector<uint8_t>* dst) const;
+
+ static constexpr uint32_t kMaxId = (1 << 24) - 1; // See id_ : 24 below.
+ private:
+ template <typename Container>
+ void SerializeAndAppendToInternal(Container* dst) const;
+
+ // Fields are deliberately not initialized to keep the class trivially
+ // constructible. It makes a large perf difference for ProtoDecoder.
+ uint64_t int_value_; // In kLengthDelimited this contains the data() addr.
+ uint32_t size_; // Only valid when when type == kLengthDelimited.
+
+ // Note: MSVC and clang-cl require bit-fields to be of the same type, hence
+ // the `: 8` below rather than uint8_t.
+ uint32_t id_ : 24; // Proto field ordinal.
+ uint32_t type_ : 8; // proto_utils::ProtoWireType.
+};
+// The Field struct is used in a lot of perf-sensitive contexts.
+static_assert(sizeof(Field) == 16, "Field struct too big");
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_FIELD_H_
+// gen_amalgamated begin header: include/perfetto/tracing/core/forward_decls.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_
+
+// Forward declares classes that are generated at build-time from protos.
+// First of all, why are we forward declaring at all?
+// 1. Chromium diverges from the Google style guide on this, because forward
+// declarations typically make build times faster, and that's a desirable
+// property for a large and complex codebase.
+// 2. Adding #include to build-time-generated headers from headers typically
+// creates subtle build errors that are hard to spot in GN. This is because
+// once a standard header (say foo.h) has an #include "protos/foo.gen.h",
+// the build target that depends on foo.h needs to depend on the genrule
+// that generates foo.gen.h. This is achievable using public_deps in GN but
+// is not testable / enforceable, hence too easy to get wrong.
+
+// Historically the classes below used to be generated from the corresponding
+// .proto(s) at CL *check-in* time (!= build time) in the ::perfetto namespace.
+// Nowadays we have code everywhere that assume the right class is
+// ::perfetto::TraceConfig or the like. Back then other headers could just
+// forward declared ::perfetto::TraceConfig. These days, the real class is
+// ::perfetto::protos::gen::TraceConfig and core/trace_config.h aliases that as
+// using ::perfetto::TraceConfig = ::perfetto::protos::gen::TraceConfig.
+// In C++ one cannot forward declare a type alias (but only the aliased type).
+// Hence this header, which should be used every time one wants to forward
+// declare classes like TraceConfig.
+
+// The overall plan is that, when one of the classes below is needed:
+// The .h file includes this file.
+// The .cc file includes perfetto/tracing/core/trace_config.h (or equiv). That
+// header will pull the full declaration from trace_config.gen.h and will also
+// setup the alias in the ::perfetto namespace.
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class ChromeConfig;
+class CommitDataRequest;
+class DataSourceConfig;
+class DataSourceDescriptor;
+class ObservableEvents;
+class TraceConfig;
+class TraceStats;
+class TracingServiceCapabilities;
+class TracingServiceState;
+class SyncClockRequest;
+class SyncClockResponse;
+
+} // namespace gen
+} // namespace protos
+
+using ChromeConfig = ::perfetto::protos::gen::ChromeConfig;
+using CommitDataRequest = ::perfetto::protos::gen::CommitDataRequest;
+using DataSourceConfig = ::perfetto::protos::gen::DataSourceConfig;
+using DataSourceDescriptor = ::perfetto::protos::gen::DataSourceDescriptor;
+using ObservableEvents = ::perfetto::protos::gen::ObservableEvents;
+using TraceConfig = ::perfetto::protos::gen::TraceConfig;
+using TraceStats = ::perfetto::protos::gen::TraceStats;
+using TracingServiceCapabilities =
+ ::perfetto::protos::gen::TracingServiceCapabilities;
+using TracingServiceState = ::perfetto::protos::gen::TracingServiceState;
+using SyncClockRequest = ::perfetto::protos::gen::SyncClockRequest;
+using SyncClockResponse = ::perfetto::protos::gen::SyncClockResponse;
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/basic_types.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace perfetto {
+namespace internal {
+
+// A static_assert in tracing_muxer_impl.cc guarantees that this stays in sync
+// with the definition in tracing/core/basic_types.h
+using BufferId = uint16_t;
+
+// This is an id of a backend in the TracingMuxer::producer_backends_ list.
+// Backends are only added and never removed.
+using TracingBackendId = size_t;
+
+// Max numbers of data sources that can be registered in a process.
+constexpr size_t kMaxDataSources = 32;
+
+// Max instances for each data source type. This typically matches the
+// "max number of concurrent tracing sessions". However remember that a data
+// source can be instantiated more than once within one tracing session by
+// creating two entries for it in the trace config.
+constexpr size_t kMaxDataSourceInstances = 8;
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/data_source_internal.h
+// gen_amalgamated begin header: include/perfetto/tracing/core/data_source_config.h
+// gen_amalgamated begin header: gen/protos/perfetto/config/data_source_config.gen.h
+// gen_amalgamated begin header: include/perfetto/protozero/cpp_message_obj.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_
+#define INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace protozero {
+
+// Base class for generated .gen.h classes, which are full C++ objects that
+// support both ser and deserialization (but are not zero-copy).
+// This is only used by the "cpp" targets not the "pbzero" ones.
+class PERFETTO_EXPORT_COMPONENT CppMessageObj {
+ public:
+ virtual ~CppMessageObj();
+ virtual std::string SerializeAsString() const = 0;
+ virtual std::vector<uint8_t> SerializeAsArray() const = 0;
+ virtual bool ParseFromArray(const void*, size_t) = 0;
+
+ bool ParseFromString(const std::string& str) {
+ return ParseFromArray(str.data(), str.size());
+ }
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_
+// gen_amalgamated begin header: include/perfetto/protozero/copyable_ptr.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
+#define INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
+
+#include <memory>
+
+namespace protozero {
+
+// This class is essentially a std::vector<T> of fixed size = 1.
+// It's a pointer wrapper with deep copying and deep equality comparison.
+// At all effects this wrapper behaves like the underlying T, with the exception
+// of the heap indirection.
+// Conversely to a std::unique_ptr, the pointer will be always valid, never
+// null. The problem it solves is the following: when generating C++ classes
+// from proto files, we want to keep each header hermetic (i.e. not #include
+// headers of dependent types). As such we can't directly instantiate T
+// field members but we can instead rely on pointers, so only the .cc file needs
+// to see the actual definition of T. If the generated classes were move-only we
+// could just use a unique_ptr there. But they aren't, hence this wrapper.
+// Converesely to unique_ptr, this wrapper:
+// - Default constructs the T instance in its constructor.
+// - Implements deep comparison in operator== instead of pointer comparison.
+template <typename T>
+class CopyablePtr {
+ public:
+ CopyablePtr() : ptr_(new T()) {}
+ ~CopyablePtr() = default;
+
+ // Copy operators.
+ CopyablePtr(const CopyablePtr& other) : ptr_(new T(*other.ptr_)) {}
+ CopyablePtr& operator=(const CopyablePtr& other) {
+ *ptr_ = *other.ptr_;
+ return *this;
+ }
+
+ // Move operators.
+ CopyablePtr(CopyablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {
+ other.ptr_.reset(new T());
+ }
+
+ CopyablePtr& operator=(CopyablePtr&& other) {
+ ptr_ = std::move(other.ptr_);
+ other.ptr_.reset(new T());
+ return *this;
+ }
+
+ T* get() { return ptr_.get(); }
+ const T* get() const { return ptr_.get(); }
+
+ T* operator->() { return ptr_.get(); }
+ const T* operator->() const { return ptr_.get(); }
+
+ T& operator*() { return *ptr_; }
+ const T& operator*() const { return *ptr_; }
+
+ friend bool operator==(const CopyablePtr& lhs, const CopyablePtr& rhs) {
+ return *lhs == *rhs;
+ }
+
+ friend bool operator!=(const CopyablePtr& lhs, const CopyablePtr& rhs) {
+ // In theory the underlying type might have a special operator!=
+ // implementation which is not just !(x == y). Respect that.
+ return *lhs != *rhs;
+ }
+
+ private:
+ std::unique_ptr<T> ptr_;
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class DataSourceConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+class InterceptorConfig;
+class ConsoleConfig;
+class ChromeConfig;
+class SystemInfoConfig;
+enum DataSourceConfig_SessionInitiator : int;
+enum ConsoleConfig_Output : int;
+enum ChromeConfig_ClientPriority : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum DataSourceConfig_SessionInitiator : int {
+ DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED = 0,
+ DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM = 1,
+};
+
+class PERFETTO_EXPORT_COMPONENT DataSourceConfig : public ::protozero::CppMessageObj {
+ public:
+ using SessionInitiator = DataSourceConfig_SessionInitiator;
+ static constexpr auto SESSION_INITIATOR_UNSPECIFIED = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED;
+ static constexpr auto SESSION_INITIATOR_TRUSTED_SYSTEM = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM;
+ static constexpr auto SessionInitiator_MIN = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED;
+ static constexpr auto SessionInitiator_MAX = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM;
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kTargetBufferFieldNumber = 2,
+ kTraceDurationMsFieldNumber = 3,
+ kPreferSuspendClockForDurationFieldNumber = 122,
+ kStopTimeoutMsFieldNumber = 7,
+ kEnableExtraGuardrailsFieldNumber = 6,
+ kSessionInitiatorFieldNumber = 8,
+ kTracingSessionIdFieldNumber = 4,
+ kFtraceConfigFieldNumber = 100,
+ kInodeFileConfigFieldNumber = 102,
+ kProcessStatsConfigFieldNumber = 103,
+ kSysStatsConfigFieldNumber = 104,
+ kHeapprofdConfigFieldNumber = 105,
+ kJavaHprofConfigFieldNumber = 110,
+ kAndroidPowerConfigFieldNumber = 106,
+ kAndroidLogConfigFieldNumber = 107,
+ kGpuCounterConfigFieldNumber = 108,
+ kAndroidGameInterventionListConfigFieldNumber = 116,
+ kPackagesListConfigFieldNumber = 109,
+ kPerfEventConfigFieldNumber = 111,
+ kVulkanMemoryConfigFieldNumber = 112,
+ kTrackEventConfigFieldNumber = 113,
+ kAndroidPolledStateConfigFieldNumber = 114,
+ kAndroidSystemPropertyConfigFieldNumber = 118,
+ kStatsdTracingConfigFieldNumber = 117,
+ kSystemInfoConfigFieldNumber = 119,
+ kChromeConfigFieldNumber = 101,
+ kV8ConfigFieldNumber = 127,
+ kInterceptorConfigFieldNumber = 115,
+ kNetworkPacketTraceConfigFieldNumber = 120,
+ kSurfaceflingerLayersConfigFieldNumber = 121,
+ kSurfaceflingerTransactionsConfigFieldNumber = 123,
+ kAndroidSdkSyspropGuardConfigFieldNumber = 124,
+ kEtwConfigFieldNumber = 125,
+ kProtologConfigFieldNumber = 126,
+ kAndroidInputEventConfigFieldNumber = 128,
+ kLegacyConfigFieldNumber = 1000,
+ kForTestingFieldNumber = 1001,
+ };
+
+ DataSourceConfig();
+ ~DataSourceConfig() override;
+ DataSourceConfig(DataSourceConfig&&) noexcept;
+ DataSourceConfig& operator=(DataSourceConfig&&);
+ DataSourceConfig(const DataSourceConfig&);
+ DataSourceConfig& operator=(const DataSourceConfig&);
+ bool operator==(const DataSourceConfig&) const;
+ bool operator!=(const DataSourceConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_target_buffer() const { return _has_field_[2]; }
+ uint32_t target_buffer() const { return target_buffer_; }
+ void set_target_buffer(uint32_t value) { target_buffer_ = value; _has_field_.set(2); }
+
+ bool has_trace_duration_ms() const { return _has_field_[3]; }
+ uint32_t trace_duration_ms() const { return trace_duration_ms_; }
+ void set_trace_duration_ms(uint32_t value) { trace_duration_ms_ = value; _has_field_.set(3); }
+
+ bool has_prefer_suspend_clock_for_duration() const { return _has_field_[122]; }
+ bool prefer_suspend_clock_for_duration() const { return prefer_suspend_clock_for_duration_; }
+ void set_prefer_suspend_clock_for_duration(bool value) { prefer_suspend_clock_for_duration_ = value; _has_field_.set(122); }
+
+ bool has_stop_timeout_ms() const { return _has_field_[7]; }
+ uint32_t stop_timeout_ms() const { return stop_timeout_ms_; }
+ void set_stop_timeout_ms(uint32_t value) { stop_timeout_ms_ = value; _has_field_.set(7); }
+
+ bool has_enable_extra_guardrails() const { return _has_field_[6]; }
+ bool enable_extra_guardrails() const { return enable_extra_guardrails_; }
+ void set_enable_extra_guardrails(bool value) { enable_extra_guardrails_ = value; _has_field_.set(6); }
+
+ bool has_session_initiator() const { return _has_field_[8]; }
+ DataSourceConfig_SessionInitiator session_initiator() const { return session_initiator_; }
+ void set_session_initiator(DataSourceConfig_SessionInitiator value) { session_initiator_ = value; _has_field_.set(8); }
+
+ bool has_tracing_session_id() const { return _has_field_[4]; }
+ uint64_t tracing_session_id() const { return tracing_session_id_; }
+ void set_tracing_session_id(uint64_t value) { tracing_session_id_ = value; _has_field_.set(4); }
+
+ const std::string& ftrace_config_raw() const { return ftrace_config_; }
+ void set_ftrace_config_raw(const std::string& raw) { ftrace_config_ = raw; _has_field_.set(100); }
+
+ const std::string& inode_file_config_raw() const { return inode_file_config_; }
+ void set_inode_file_config_raw(const std::string& raw) { inode_file_config_ = raw; _has_field_.set(102); }
+
+ const std::string& process_stats_config_raw() const { return process_stats_config_; }
+ void set_process_stats_config_raw(const std::string& raw) { process_stats_config_ = raw; _has_field_.set(103); }
+
+ const std::string& sys_stats_config_raw() const { return sys_stats_config_; }
+ void set_sys_stats_config_raw(const std::string& raw) { sys_stats_config_ = raw; _has_field_.set(104); }
+
+ const std::string& heapprofd_config_raw() const { return heapprofd_config_; }
+ void set_heapprofd_config_raw(const std::string& raw) { heapprofd_config_ = raw; _has_field_.set(105); }
+
+ const std::string& java_hprof_config_raw() const { return java_hprof_config_; }
+ void set_java_hprof_config_raw(const std::string& raw) { java_hprof_config_ = raw; _has_field_.set(110); }
+
+ const std::string& android_power_config_raw() const { return android_power_config_; }
+ void set_android_power_config_raw(const std::string& raw) { android_power_config_ = raw; _has_field_.set(106); }
+
+ const std::string& android_log_config_raw() const { return android_log_config_; }
+ void set_android_log_config_raw(const std::string& raw) { android_log_config_ = raw; _has_field_.set(107); }
+
+ const std::string& gpu_counter_config_raw() const { return gpu_counter_config_; }
+ void set_gpu_counter_config_raw(const std::string& raw) { gpu_counter_config_ = raw; _has_field_.set(108); }
+
+ const std::string& android_game_intervention_list_config_raw() const { return android_game_intervention_list_config_; }
+ void set_android_game_intervention_list_config_raw(const std::string& raw) { android_game_intervention_list_config_ = raw; _has_field_.set(116); }
+
+ const std::string& packages_list_config_raw() const { return packages_list_config_; }
+ void set_packages_list_config_raw(const std::string& raw) { packages_list_config_ = raw; _has_field_.set(109); }
+
+ const std::string& perf_event_config_raw() const { return perf_event_config_; }
+ void set_perf_event_config_raw(const std::string& raw) { perf_event_config_ = raw; _has_field_.set(111); }
+
+ const std::string& vulkan_memory_config_raw() const { return vulkan_memory_config_; }
+ void set_vulkan_memory_config_raw(const std::string& raw) { vulkan_memory_config_ = raw; _has_field_.set(112); }
+
+ const std::string& track_event_config_raw() const { return track_event_config_; }
+ void set_track_event_config_raw(const std::string& raw) { track_event_config_ = raw; _has_field_.set(113); }
+
+ const std::string& android_polled_state_config_raw() const { return android_polled_state_config_; }
+ void set_android_polled_state_config_raw(const std::string& raw) { android_polled_state_config_ = raw; _has_field_.set(114); }
+
+ const std::string& android_system_property_config_raw() const { return android_system_property_config_; }
+ void set_android_system_property_config_raw(const std::string& raw) { android_system_property_config_ = raw; _has_field_.set(118); }
+
+ const std::string& statsd_tracing_config_raw() const { return statsd_tracing_config_; }
+ void set_statsd_tracing_config_raw(const std::string& raw) { statsd_tracing_config_ = raw; _has_field_.set(117); }
+
+ bool has_system_info_config() const { return _has_field_[119]; }
+ const SystemInfoConfig& system_info_config() const { return *system_info_config_; }
+ SystemInfoConfig* mutable_system_info_config() { _has_field_.set(119); return system_info_config_.get(); }
+
+ bool has_chrome_config() const { return _has_field_[101]; }
+ const ChromeConfig& chrome_config() const { return *chrome_config_; }
+ ChromeConfig* mutable_chrome_config() { _has_field_.set(101); return chrome_config_.get(); }
+
+ const std::string& v8_config_raw() const { return v8_config_; }
+ void set_v8_config_raw(const std::string& raw) { v8_config_ = raw; _has_field_.set(127); }
+
+ bool has_interceptor_config() const { return _has_field_[115]; }
+ const InterceptorConfig& interceptor_config() const { return *interceptor_config_; }
+ InterceptorConfig* mutable_interceptor_config() { _has_field_.set(115); return interceptor_config_.get(); }
+
+ const std::string& network_packet_trace_config_raw() const { return network_packet_trace_config_; }
+ void set_network_packet_trace_config_raw(const std::string& raw) { network_packet_trace_config_ = raw; _has_field_.set(120); }
+
+ const std::string& surfaceflinger_layers_config_raw() const { return surfaceflinger_layers_config_; }
+ void set_surfaceflinger_layers_config_raw(const std::string& raw) { surfaceflinger_layers_config_ = raw; _has_field_.set(121); }
+
+ const std::string& surfaceflinger_transactions_config_raw() const { return surfaceflinger_transactions_config_; }
+ void set_surfaceflinger_transactions_config_raw(const std::string& raw) { surfaceflinger_transactions_config_ = raw; _has_field_.set(123); }
+
+ const std::string& android_sdk_sysprop_guard_config_raw() const { return android_sdk_sysprop_guard_config_; }
+ void set_android_sdk_sysprop_guard_config_raw(const std::string& raw) { android_sdk_sysprop_guard_config_ = raw; _has_field_.set(124); }
+
+ const std::string& etw_config_raw() const { return etw_config_; }
+ void set_etw_config_raw(const std::string& raw) { etw_config_ = raw; _has_field_.set(125); }
+
+ const std::string& protolog_config_raw() const { return protolog_config_; }
+ void set_protolog_config_raw(const std::string& raw) { protolog_config_ = raw; _has_field_.set(126); }
+
+ const std::string& android_input_event_config_raw() const { return android_input_event_config_; }
+ void set_android_input_event_config_raw(const std::string& raw) { android_input_event_config_ = raw; _has_field_.set(128); }
+
+ bool has_legacy_config() const { return _has_field_[1000]; }
+ const std::string& legacy_config() const { return legacy_config_; }
+ void set_legacy_config(const std::string& value) { legacy_config_ = value; _has_field_.set(1000); }
+
+ bool has_for_testing() const { return _has_field_[1001]; }
+ const TestConfig& for_testing() const { return *for_testing_; }
+ TestConfig* mutable_for_testing() { _has_field_.set(1001); return for_testing_.get(); }
+
+ private:
+ std::string name_{};
+ uint32_t target_buffer_{};
+ uint32_t trace_duration_ms_{};
+ bool prefer_suspend_clock_for_duration_{};
+ uint32_t stop_timeout_ms_{};
+ bool enable_extra_guardrails_{};
+ DataSourceConfig_SessionInitiator session_initiator_{};
+ uint64_t tracing_session_id_{};
+ std::string ftrace_config_; // [lazy=true]
+ std::string inode_file_config_; // [lazy=true]
+ std::string process_stats_config_; // [lazy=true]
+ std::string sys_stats_config_; // [lazy=true]
+ std::string heapprofd_config_; // [lazy=true]
+ std::string java_hprof_config_; // [lazy=true]
+ std::string android_power_config_; // [lazy=true]
+ std::string android_log_config_; // [lazy=true]
+ std::string gpu_counter_config_; // [lazy=true]
+ std::string android_game_intervention_list_config_; // [lazy=true]
+ std::string packages_list_config_; // [lazy=true]
+ std::string perf_event_config_; // [lazy=true]
+ std::string vulkan_memory_config_; // [lazy=true]
+ std::string track_event_config_; // [lazy=true]
+ std::string android_polled_state_config_; // [lazy=true]
+ std::string android_system_property_config_; // [lazy=true]
+ std::string statsd_tracing_config_; // [lazy=true]
+ ::protozero::CopyablePtr<SystemInfoConfig> system_info_config_;
+ ::protozero::CopyablePtr<ChromeConfig> chrome_config_;
+ std::string v8_config_; // [lazy=true]
+ ::protozero::CopyablePtr<InterceptorConfig> interceptor_config_;
+ std::string network_packet_trace_config_; // [lazy=true]
+ std::string surfaceflinger_layers_config_; // [lazy=true]
+ std::string surfaceflinger_transactions_config_; // [lazy=true]
+ std::string android_sdk_sysprop_guard_config_; // [lazy=true]
+ std::string etw_config_; // [lazy=true]
+ std::string protolog_config_; // [lazy=true]
+ std::string android_input_event_config_; // [lazy=true]
+ std::string legacy_config_{};
+ ::protozero::CopyablePtr<TestConfig> for_testing_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<1002> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h"
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
+// gen_amalgamated begin header: include/perfetto/tracing/trace_writer_base.h
+// gen_amalgamated begin header: include/perfetto/protozero/message_handle.h
+// gen_amalgamated begin header: include/perfetto/protozero/message.h
+// gen_amalgamated begin header: include/perfetto/protozero/scattered_stream_writer.h
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_
+#define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <algorithm>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h"
+
+namespace protozero {
+
+// This class deals with the following problem: append-only proto messages want
+// to write a stream of bytes, without caring about the implementation of the
+// underlying buffer (which concretely will be either the trace ring buffer
+// or a heap-allocated buffer). The main deal is: proto messages don't know in
+// advance what their size will be.
+// Due to the tracing buffer being split into fixed-size chunks, on some
+// occasions, these writes need to be spread over two (or more) non-contiguous
+// chunks of memory. Similarly, when the buffer is backed by the heap, we want
+// to avoid realloc() calls, as they might cause a full copy of the contents
+// of the buffer.
+// The purpose of this class is to abstract away the non-contiguous write logic.
+// This class knows how to deal with writes as long as they fall in the same
+// ContiguousMemoryRange and defers the chunk-chaining logic to the Delegate.
+class PERFETTO_EXPORT_COMPONENT ScatteredStreamWriter {
+ public:
+ class PERFETTO_EXPORT_COMPONENT Delegate {
+ public:
+ static constexpr size_t kPatchSize = 4;
+ virtual ~Delegate();
+
+ // Returns a new chunk for writing.
+ virtual ContiguousMemoryRange GetNewBuffer() = 0;
+
+ // Signals the delegate that the location pointed by `to_patch` (which must
+ // be in the last chunk returned by GetNewBuffer()), kPatchSize long, needs
+ // to be updated later (after potentially multiple GetNewBuffer calls).
+ //
+ // The caller must write to the returned location later. If the returned
+ // pointer is nullptr, the caller should not write anything.
+ //
+ // The implementation considers the patch ready to apply when the caller
+ // writes the first byte a value that's different than 0 (the
+ // implementation periodically checks for this).
+ virtual uint8_t* AnnotatePatch(uint8_t* patch_addr);
+ };
+
+ explicit ScatteredStreamWriter(Delegate* delegate);
+ ~ScatteredStreamWriter();
+
+ inline void WriteByte(uint8_t value) {
+ if (write_ptr_ >= cur_range_.end)
+ Extend();
+ *write_ptr_++ = value;
+ }
+
+ // Assumes that the caller checked that there is enough headroom.
+ // TODO(primiano): perf optimization, this is a tracing hot path. The
+ // compiler can make strong optimization on std::copy if the size arg is a
+ // constexpr. Make a templated variant of this for fixed-size writes.
+ // TODO(primiano): restrict / noalias might also help.
+ inline void WriteBytesUnsafe(const uint8_t* src, size_t size) {
+ uint8_t* const end = write_ptr_ + size;
+ assert(end <= cur_range_.end);
+ std::copy(src, src + size, write_ptr_);
+ write_ptr_ = end;
+ }
+
+ inline void WriteBytes(const uint8_t* src,
+ size_t size) PERFETTO_NO_SANITIZE_UNDEFINED {
+ // If the stream writer hasn't been initialized, constructing the end
+ // pointer below invokes undefined behavior because `write_ptr_` is null.
+ // Since this function is on the hot path, we suppress the warning instead
+ // of adding a conditional branch.
+ uint8_t* const end = write_ptr_ + size;
+ if (PERFETTO_LIKELY(end <= cur_range_.end))
+ return WriteBytesUnsafe(src, size);
+ WriteBytesSlowPath(src, size);
+ }
+
+ void WriteBytesSlowPath(const uint8_t* src, size_t size);
+
+ // Reserves a fixed amount of bytes to be backfilled later. The reserved range
+ // is guaranteed to be contiguous and not span across chunks. |size| has to be
+ // <= than the size of a new buffer returned by the Delegate::GetNewBuffer().
+ uint8_t* ReserveBytes(size_t size);
+
+ // Fast (but unsafe) version of the above. The caller must have previously
+ // checked that there are at least |size| contiguous bytes available.
+ // Returns only the start pointer of the reservation.
+ uint8_t* ReserveBytesUnsafe(size_t size) {
+ uint8_t* begin = write_ptr_;
+ write_ptr_ += size;
+ assert(write_ptr_ <= cur_range_.end);
+ return begin;
+ }
+
+ // Shifts the previously written `size` bytes backwards in memory by `offset`
+ // bytes, moving the write pointer back accordingly. The shifted result must
+ // still be fully contained by the current range.
+ void Rewind(size_t size, size_t offset) {
+ uint8_t* src = write_ptr_ - size;
+ uint8_t* dst = src - offset;
+ PERFETTO_DCHECK(src >= cur_range_.begin);
+ PERFETTO_DCHECK(src + size <= cur_range_.end);
+ PERFETTO_DCHECK(dst >= cur_range_.begin);
+ PERFETTO_DCHECK(dst + size <= cur_range_.end);
+ memmove(dst, src, size);
+ write_ptr_ -= offset;
+ }
+
+ // Resets the buffer boundaries and the write pointer to the given |range|.
+ // Subsequent WriteByte(s) will write into |range|.
+ void Reset(ContiguousMemoryRange range);
+
+ // Commits the current chunk and gets a new chunk from the delegate.
+ void Extend();
+
+ // Number of contiguous free bytes in |cur_range_| that can be written without
+ // requesting a new buffer.
+ size_t bytes_available() const {
+ return static_cast<size_t>(cur_range_.end - write_ptr_);
+ }
+
+ ContiguousMemoryRange cur_range() const { return cur_range_; }
+
+ uint8_t* write_ptr() const { return write_ptr_; }
+
+ void set_write_ptr(uint8_t* write_ptr) {
+ assert(cur_range_.begin <= write_ptr && write_ptr <= cur_range_.end);
+ write_ptr_ = write_ptr;
+ }
+
+ uint64_t written() const {
+ return written_previously_ +
+ static_cast<uint64_t>(write_ptr_ - cur_range_.begin);
+ }
+
+ uint64_t written_previously() const { return written_previously_; }
+
+ uint8_t* AnnotatePatch(uint8_t* patch_addr) {
+ return delegate_->AnnotatePatch(patch_addr);
+ }
+
+ private:
+ ScatteredStreamWriter(const ScatteredStreamWriter&) = delete;
+ ScatteredStreamWriter& operator=(const ScatteredStreamWriter&) = delete;
+
+ Delegate* const delegate_;
+ ContiguousMemoryRange cur_range_;
+ uint8_t* write_ptr_;
+ uint64_t written_previously_ = 0;
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
+#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"
+
+namespace perfetto {
+namespace shm_fuzz {
+class FakeProducer;
+} // namespace shm_fuzz
+} // namespace perfetto
+
+namespace protozero {
+
+class MessageArena;
+class MessageHandleBase;
+
+// Base class extended by the proto C++ stubs generated by the ProtoZero
+// compiler. This class provides the minimal runtime required to support
+// append-only operations and is designed for performance. None of the methods
+// require any dynamic memory allocation, unless more than 16 nested messages
+// are created via BeginNestedMessage() calls.
+class PERFETTO_EXPORT_COMPONENT Message {
+ public:
+ friend class MessageHandleBase;
+
+ // The ctor is deliberately a no-op to avoid forwarding args from all
+ // subclasses. The real initialization is performed by Reset().
+ // Nested messages are allocated via placement new by MessageArena and
+ // implictly destroyed when the RootMessage's arena goes away. This is
+ // fine as long as all the fields are PODs, which is checked by the
+ // static_assert()s in the Reset() method.
+ Message() = default;
+
+ // Clears up the state, allowing the message to be reused as a fresh one.
+ void Reset(ScatteredStreamWriter*, MessageArena*);
+
+ // Commits all the changes to the buffer (backfills the size field of this and
+ // all nested messages) and seals the message. Returns the size of the message
+ // (and all nested sub-messages), without taking into account any chunking.
+ // Finalize is idempotent and can be called several times w/o side effects.
+ // Short messages may be compacted in memory into the size field, since their
+ // size can be represented with fewer than
+ // proto_utils::kMessageLengthFieldSize bytes.
+ uint32_t Finalize();
+
+ // Optional. If is_valid() == true, the corresponding memory region (its
+ // length == proto_utils::kMessageLengthFieldSize) is backfilled with the size
+ // of this message. This is the mechanism used by messages to backfill their
+ // corresponding size field in the parent message. In most cases this is only
+ // used for nested messages and the ScatteredStreamWriter::Delegate (e.g.
+ // TraceWriterImpl), takes case of the outer message.
+ uint8_t* size_field() const { return size_field_; }
+ void set_size_field(uint8_t* size_field) { size_field_ = size_field; }
+
+ Message* nested_message() { return nested_message_; }
+
+ bool is_finalized() const {
+ return message_state_ != MessageState::kNotFinalized;
+ }
+
+#if PERFETTO_DCHECK_IS_ON()
+ void set_handle(MessageHandleBase* handle) { handle_ = handle; }
+#endif
+
+ // Proto types: uint64, uint32, int64, int32, bool, enum.
+ template <typename T>
+ void AppendVarInt(uint32_t field_id, T value) {
+ if (nested_message_)
+ EndNestedMessage();
+
+ uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
+ uint8_t* pos = buffer;
+
+ pos = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), pos);
+ // WriteVarInt encodes signed values in two's complement form.
+ pos = proto_utils::WriteVarInt(value, pos);
+ WriteToStream(buffer, pos);
+ }
+
+ // Proto types: sint64, sint32.
+ template <typename T>
+ void AppendSignedVarInt(uint32_t field_id, T value) {
+ AppendVarInt(field_id, proto_utils::ZigZagEncode(value));
+ }
+
+ // Proto types: bool, enum (small).
+ // Faster version of AppendVarInt for tiny numbers.
+ void AppendTinyVarInt(uint32_t field_id, int32_t value) {
+ PERFETTO_DCHECK(0 <= value && value < 0x80);
+ if (nested_message_)
+ EndNestedMessage();
+
+ uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
+ uint8_t* pos = buffer;
+ // MakeTagVarInt gets super optimized here for constexpr.
+ pos = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), pos);
+ *pos++ = static_cast<uint8_t>(value);
+ WriteToStream(buffer, pos);
+ }
+
+ // Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float.
+ template <typename T>
+ void AppendFixed(uint32_t field_id, T value) {
+ if (nested_message_)
+ EndNestedMessage();
+
+ uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize];
+ uint8_t* pos = buffer;
+
+ pos = proto_utils::WriteVarInt(proto_utils::MakeTagFixed<T>(field_id), pos);
+ memcpy(pos, &value, sizeof(T));
+ pos += sizeof(T);
+ // TODO: Optimize memcpy performance, see http://crbug.com/624311 .
+ WriteToStream(buffer, pos);
+ }
+
+ void AppendString(uint32_t field_id, const char* str);
+
+ void AppendString(uint32_t field_id, const std::string& str) {
+ AppendBytes(field_id, str.data(), str.size());
+ }
+
+ void AppendBytes(uint32_t field_id, const void* value, size_t size);
+
+ // Append raw bytes for a field, using the supplied |ranges| to
+ // copy from |num_ranges| individual buffers.
+ size_t AppendScatteredBytes(uint32_t field_id,
+ ContiguousMemoryRange* ranges,
+ size_t num_ranges);
+
+ // Begins a nested message. The returned object is owned by the MessageArena
+ // of the root message. The nested message ends either when Finalize() is
+ // called or when any other Append* method is called in the parent class.
+ // The template argument T is supposed to be a stub class auto generated from
+ // a .proto, hence a subclass of Message.
+ template <class T>
+ T* BeginNestedMessage(uint32_t field_id) {
+ // This is to prevent subclasses (which should be autogenerated, though), to
+ // introduce extra state fields (which wouldn't be initialized by Reset()).
+ static_assert(std::is_base_of<Message, T>::value,
+ "T must be a subclass of Message");
+ static_assert(sizeof(T) == sizeof(Message),
+ "Message subclasses cannot introduce extra state.");
+ return static_cast<T*>(BeginNestedMessageInternal(field_id));
+ }
+
+ // Gives read-only access to the underlying stream_writer. This is used only
+ // by few internals to query the state of the underlying buffer. It is almost
+ // always a bad idea to poke at the stream_writer() internals.
+ const ScatteredStreamWriter* stream_writer() const { return stream_writer_; }
+
+ // Appends some raw bytes to the message. The use-case for this is preserving
+ // unknown fields in the decode -> re-encode path of xxx.gen.cc classes
+ // generated by the cppgen_plugin.cc.
+ // The caller needs to guarantee that the appended data is properly
+ // proto-encoded and each field has a proto preamble.
+ void AppendRawProtoBytes(const void* data, size_t size) {
+ if (nested_message_)
+ EndNestedMessage();
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(data);
+ WriteToStream(src, src + size);
+ }
+
+ private:
+ Message(const Message&) = delete;
+ Message& operator=(const Message&) = delete;
+
+ Message* BeginNestedMessageInternal(uint32_t field_id);
+
+ // Called by Finalize and Append* methods.
+ void EndNestedMessage();
+
+ void WriteToStream(const uint8_t* src_begin, const uint8_t* src_end) {
+ PERFETTO_DCHECK(!is_finalized());
+ PERFETTO_DCHECK(src_begin <= src_end);
+ const uint32_t size = static_cast<uint32_t>(src_end - src_begin);
+ stream_writer_->WriteBytes(src_begin, size);
+ size_ += size;
+ }
+
+ // Only POD fields are allowed. This class's dtor is never called.
+ // See the comment on the static_assert in the corresponding .cc file.
+
+ // The stream writer interface used for the serialization.
+ ScatteredStreamWriter* stream_writer_;
+
+ // The storage used to allocate nested Message objects.
+ // This is owned by RootMessage<T>.
+ MessageArena* arena_;
+
+ // Pointer to the last child message created through BeginNestedMessage(), if
+ // any, nullptr otherwise. There is no need to keep track of more than one
+ // message per nesting level as the proto-zero API contract mandates that
+ // nested fields can be filled only in a stacked fashion. In other words,
+ // nested messages are finalized and sealed when any other field is set in the
+ // parent message (or the parent message itself is finalized) and cannot be
+ // accessed anymore afterwards.
+ Message* nested_message_;
+
+ // [optional] Pointer to a non-aligned pre-reserved var-int slot of
+ // kMessageLengthFieldSize bytes. When set, the Finalize() method will write
+ // the size of proto-encoded message in the pointed memory region.
+ uint8_t* size_field_;
+
+ // Keeps track of the size of the current message.
+ uint32_t size_;
+
+ enum class MessageState : uint8_t {
+ // Message is still being written to.
+ kNotFinalized,
+ // Finalized, no more changes to the message are allowed. This is to DCHECK
+ // attempts of writing to a message which has been Finalize()-d.
+ kFinalized,
+ // Finalized, and additionally the message data has been partially or fully
+ // compacted into the last 3 bytes of `size_field_`. See the comment in
+ // Finalize().
+ kFinalizedWithCompaction,
+ };
+
+ MessageState message_state_;
+
+#if PERFETTO_DCHECK_IS_ON()
+ // Current generation of message. Incremented on Reset.
+ // Used to detect stale handles.
+ uint32_t generation_;
+
+ MessageHandleBase* handle_;
+#endif
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
+#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
+
+#include <functional>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"
+
+namespace protozero {
+
+class Message;
+
+class PERFETTO_EXPORT_COMPONENT MessageFinalizationListener {
+ public:
+ virtual ~MessageFinalizationListener();
+ virtual void OnMessageFinalized(Message* message) = 0;
+};
+
+// MessageHandle allows to decouple the lifetime of a proto message
+// from the underlying storage. It gives the following guarantees:
+// - The underlying message is finalized (if still alive) if the handle goes
+// out of scope.
+// - In Debug / DCHECK_ALWAYS_ON builds, the handle becomes null once the
+// message is finalized. This is to enforce the append-only API. For instance
+// when adding two repeated messages, the addition of the 2nd one forces
+// the finalization of the first.
+// Think about this as a WeakPtr<Message> which calls
+// Message::Finalize() when going out of scope.
+
+class PERFETTO_EXPORT_COMPONENT MessageHandleBase {
+ public:
+ ~MessageHandleBase() {
+ if (message_) {
+#if PERFETTO_DCHECK_IS_ON()
+ PERFETTO_DCHECK(generation_ == message_->generation_);
+#endif
+ FinalizeMessage();
+ }
+ }
+
+ // Move-only type.
+ MessageHandleBase(MessageHandleBase&& other) noexcept {
+ Move(std::move(other));
+ }
+
+ MessageHandleBase& operator=(MessageHandleBase&& other) noexcept {
+ // If the current handle was pointing to a message and is being reset to a
+ // new one, finalize the old message. However, if the other message is the
+ // same as the one we point to, don't finalize.
+ if (message_ && message_ != other.message_)
+ FinalizeMessage();
+ Move(std::move(other));
+ return *this;
+ }
+
+ explicit operator bool() const {
+#if PERFETTO_DCHECK_IS_ON()
+ PERFETTO_DCHECK(!message_ || generation_ == message_->generation_);
+#endif
+ return !!message_;
+ }
+
+ void set_finalization_listener(MessageFinalizationListener* listener) {
+ listener_ = listener;
+ }
+
+ // Returns a (non-owned, it should not be deleted) pointer to the
+ // ScatteredStreamWriter used to write the message data. The Message becomes
+ // unusable after this point.
+ //
+ // The caller can now write directly, without using protozero::Message.
+ ScatteredStreamWriter* TakeStreamWriter() {
+ ScatteredStreamWriter* stream_writer = message_->stream_writer_;
+#if PERFETTO_DCHECK_IS_ON()
+ message_->set_handle(nullptr);
+#endif
+ message_ = nullptr;
+ listener_ = nullptr;
+ return stream_writer;
+ }
+
+ protected:
+ explicit MessageHandleBase(Message* message = nullptr) : message_(message) {
+#if PERFETTO_DCHECK_IS_ON()
+ generation_ = message_ ? message->generation_ : 0;
+ if (message_)
+ message_->set_handle(this);
+#endif
+ }
+
+ Message* operator->() const {
+#if PERFETTO_DCHECK_IS_ON()
+ PERFETTO_DCHECK(!message_ || generation_ == message_->generation_);
+#endif
+ return message_;
+ }
+ Message& operator*() const { return *(operator->()); }
+
+ private:
+ friend class Message;
+ MessageHandleBase(const MessageHandleBase&) = delete;
+ MessageHandleBase& operator=(const MessageHandleBase&) = delete;
+
+ void reset_message() {
+ // This is called by Message::Finalize().
+ PERFETTO_DCHECK(message_->is_finalized());
+ message_ = nullptr;
+ listener_ = nullptr;
+ }
+
+ void Move(MessageHandleBase&& other) {
+ message_ = other.message_;
+ other.message_ = nullptr;
+ listener_ = other.listener_;
+ other.listener_ = nullptr;
+#if PERFETTO_DCHECK_IS_ON()
+ if (message_) {
+ generation_ = message_->generation_;
+ message_->set_handle(this);
+ }
+#endif
+ }
+
+ void FinalizeMessage() {
+ // |message_| and |listener_| may be cleared by reset_message() during
+ // Message::Finalize().
+ auto* listener = listener_;
+ auto* message = message_;
+ message->Finalize();
+ if (listener)
+ listener->OnMessageFinalized(message);
+ }
+
+ Message* message_;
+ MessageFinalizationListener* listener_ = nullptr;
+#if PERFETTO_DCHECK_IS_ON()
+ uint32_t generation_;
+#endif
+};
+
+template <typename T>
+class MessageHandle : public MessageHandleBase {
+ public:
+ MessageHandle() : MessageHandle(nullptr) {}
+ explicit MessageHandle(T* message) : MessageHandleBase(message) {}
+
+ explicit operator bool() const { return MessageHandleBase::operator bool(); }
+
+ T& operator*() const {
+ return static_cast<T&>(MessageHandleBase::operator*());
+ }
+
+ T* operator->() const {
+ return static_cast<T*>(MessageHandleBase::operator->());
+ }
+
+ T* get() const { return static_cast<T*>(MessageHandleBase::operator->()); }
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
+#define INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+
+namespace perfetto {
+
+namespace protos {
+namespace pbzero {
+class TracePacket;
+} // namespace pbzero
+} // namespace protos
+
+// This is a single-thread write interface that allows to write protobufs
+// directly into the tracing shared buffer without making any copies.
+// The idea is that each data source creates one (or more) TraceWriter for each
+// thread it wants to write from. Each TraceWriter will get its own dedicated
+// chunk and will write into the shared buffer without any locking most of the
+// time.
+
+class TraceWriterBase {
+ public:
+ virtual ~TraceWriterBase();
+
+ // Creates a new trace packet and returns a handle to a protozero Message that
+ // will write to it. The message will be finalized either by calling directly
+ // handle.Finalize() or by letting the handle go out of scope (the message
+ // should be finalized before a new call to NewTracePacket is made). The
+ // returned handle can be std::move()'d but cannot be used after either: (i)
+ // the TraceWriter instance is destroyed, (ii) a subsequence NewTracePacket()
+ // call is made on the same TraceWriter instance.
+ //
+ // The caller can use protozero::MessageHandle::TakeStreamWriter() to write.
+ //
+ // The caller must call ->Finalize() on the returned trace packet (the handle
+ // destructor will take care of that) or explicitly call FinishTracePacket (if
+ // using TakeStreamWriter) before calling any method on the same TraceWriter
+ // instance.
+ //
+ // The returned packet handle is always valid, but note that, when using
+ // BufferExhaustedPolicy::kDrop and the SMB is exhausted, it may be assigned
+ // a garbage chunk and any trace data written into it will be lost. For more
+ // details on buffer size choices: https://perfetto.dev/docs/concepts/buffers.
+ virtual protozero::MessageHandle<protos::pbzero::TracePacket>
+ NewTracePacket() = 0;
+
+ // Tells the TraceWriterBase that the previous packet started with
+ // NewTracePacket() is finished.
+ //
+ // Calling this is optional: the TraceWriterBase can realize that the previous
+ // packet is finished when the next NewTracePacket() is called. It is still
+ // useful, because the next NewTracePacket may not happen for a while.
+ virtual void FinishTracePacket() = 0;
+
+ // Commits the data pending for the current chunk. This can be called
+ // only if the handle returned by NewTracePacket() has been destroyed (i.e. we
+ // cannot Flush() while writing a TracePacket).
+ //
+ // Note: Flush() also happens implicitly when destroying the TraceWriter.
+ //
+ // |callback| is an optional callback. When non-null it will request the
+ // service to ACK the flush and will be invoked after the service has
+ // acknowledged it. The callback might be NEVER INVOKED if the service crashes
+ // or the IPC connection is dropped. The callback should be used only by tests
+ // and best-effort features (logging).
+ virtual void Flush(std::function<void()> callback = {}) = 0;
+
+ // Bytes written since creation. Not reset when new chunks are acquired.
+ virtual uint64_t written() const = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <mutex>
+
+// No perfetto headers (other than tracing/api and protozero) should be here.
+// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+
+namespace perfetto {
+
+class DataSourceBase;
+class InterceptorBase;
+class TraceWriterBase;
+
+namespace internal {
+
+class TracingTLS;
+
+// This maintains the internal state of a data source instance that is used only
+// to implement the tracing mechanics and is not exposed to the API client.
+// There is one of these object per DataSource instance (up to
+// kMaxDataSourceInstances).
+struct DataSourceState {
+ // This boolean flag determines whether the DataSource::Trace() method should
+ // do something or be a no-op. This flag doesn't give the full guarantee
+ // that tracing data will be visible in the trace, it just makes it so that
+ // the client attemps writing trace data and interacting with the service.
+ // For instance, when a tracing session ends the service will reject data
+ // commits that arrive too late even if the producer hasn't received the stop
+ // IPC message.
+ // This flag is set right before calling OnStart() and cleared right before
+ // calling OnStop(), unless using HandleStopAsynchronously() (see comments
+ // in data_source.h).
+ // Keep this flag as the first field. This allows the compiler to directly
+ // dereference the DataSourceState* pointer in the trace fast-path without
+ // doing extra pointr arithmetic.
+ std::atomic<bool> trace_lambda_enabled{false};
+
+ // The overall TracingMuxerImpl instance id, which gets incremented by
+ // ResetForTesting.
+ uint32_t muxer_id_for_testing = 0;
+
+ // The central buffer id that all TraceWriter(s) created by this data source
+ // must target.
+ BufferId buffer_id = 0;
+
+ // The index within TracingMuxerImpl.backends_. Practically it allows to
+ // lookup the Producer object, and hence the IPC channel, for this data
+ // source.
+ TracingBackendId backend_id = 0;
+
+ // Each backend may connect to the tracing service multiple times if a
+ // disconnection occurs. This counter is used to uniquely identify each
+ // connection so that trace writers don't get reused across connections.
+ uint32_t backend_connection_id = 0;
+
+ // The instance id as assigned by the tracing service. Note that because a
+ // process can be connected to >1 services, this ID is not globally unique but
+ // is only unique within the scope of its backend.
+ // Only the tuple (backend_id, data_source_instance_id) is globally unique.
+ uint64_t data_source_instance_id = 0;
+
+ // Set to a non-0 target buffer reservation ID iff startup tracing is
+ // currently enabled for this data source.
+ std::atomic<uint16_t> startup_target_buffer_reservation{0};
+
+ // If the data source was originally started for startup tracing, this is set
+ // to the startup session's ID.
+ uint64_t startup_session_id = 0;
+
+ // The trace config used by this instance. This is used to de-duplicate
+ // instances for data sources with identical names (e.g., track event).
+ // We store it as a pointer to be able to free memory after the datasource
+ // is stopped.
+ std::unique_ptr<DataSourceConfig> config;
+
+ // If this data source is being intercepted (see Interceptor), this field
+ // contains the non-zero id of a registered interceptor which should receive
+ // trace packets for this session. Note: interceptor id 1 refers to the first
+ // element of TracingMuxerImpl::interceptors_ with successive numbers using
+ // the following slots.
+ uint32_t interceptor_id = 0;
+
+ // This is set to true when the datasource is in the process of async stop.
+ // The flag is checked by the tracing muxer to avoid calling OnStop for the
+ // second time.
+ bool async_stop_in_progress = false;
+
+ // This lock is not held to implement Trace() and it's used only if the trace
+ // code wants to access its own data source state.
+ // This is to prevent that accessing the data source on an arbitrary embedder
+ // thread races with the internal IPC thread destroying the data source
+ // because of a end-of-tracing notification from the service.
+ // This lock is also used to protect access to a possible interceptor for this
+ // data source session.
+ std::recursive_mutex lock;
+ std::unique_ptr<DataSourceBase> data_source;
+ std::unique_ptr<InterceptorBase> interceptor;
+};
+
+// This is to allow lazy-initialization and avoid static initializers and
+// at-exit destructors. All the entries are initialized via placement-new when
+// DataSource::Register() is called, see TracingMuxerImpl::RegisterDataSource().
+struct DataSourceStateStorage {
+ alignas(DataSourceState) char storage[sizeof(DataSourceState)]{};
+};
+
+// Per-DataSource-type global state.
+struct DataSourceStaticState {
+ // System-wide unique id of the data source.
+ uint64_t id = 0;
+
+ // Unique index of the data source, assigned at registration time.
+ uint32_t index = kMaxDataSources;
+
+ // A bitmap that tells about the validity of each |instances| entry. When the
+ // i-th bit of the bitmap it's set, instances[i] is valid.
+ std::atomic<uint32_t> valid_instances{};
+ std::array<DataSourceStateStorage, kMaxDataSourceInstances> instances{};
+
+ // Incremented whenever incremental state should be reset for any instance of
+ // this data source.
+ std::atomic<uint32_t> incremental_state_generation{};
+
+ // Can be used with a cached |valid_instances| bitmap.
+ DataSourceState* TryGetCached(uint32_t cached_bitmap, size_t n) {
+ return cached_bitmap & (1 << n)
+ ? reinterpret_cast<DataSourceState*>(&instances[n])
+ : nullptr;
+ }
+
+ DataSourceState* TryGet(size_t n) {
+ return TryGetCached(valid_instances.load(std::memory_order_acquire), n);
+ }
+
+ void CompilerAsserts() {
+ static_assert(sizeof(valid_instances.load()) * 8 >= kMaxDataSourceInstances,
+ "kMaxDataSourceInstances too high");
+ }
+
+ void ResetForTesting() {
+ id = 0;
+ index = kMaxDataSources;
+ valid_instances.store(0, std::memory_order_release);
+ instances = {};
+ incremental_state_generation.store(0, std::memory_order_release);
+ }
+};
+
+// Per-DataSource-instance thread-local state.
+struct DataSourceInstanceThreadLocalState {
+ void Reset() { *this = DataSourceInstanceThreadLocalState{}; }
+
+ std::unique_ptr<TraceWriterBase> trace_writer;
+ using ObjectWithDeleter = std::unique_ptr<void, void (*)(void*)>;
+ ObjectWithDeleter incremental_state = {nullptr, [](void*) {}};
+ ObjectWithDeleter data_source_custom_tls = {nullptr, [](void*) {}};
+ uint32_t incremental_state_generation = 0;
+ uint32_t muxer_id_for_testing = 0;
+ TracingBackendId backend_id = 0;
+ uint32_t backend_connection_id = 0;
+ BufferId buffer_id = 0;
+ uint64_t data_source_instance_id = 0;
+ bool is_intercepted = false;
+ uint64_t last_empty_packet_position = 0;
+ uint16_t startup_target_buffer_reservation = 0;
+};
+
+// Per-DataSource-type thread-local state.
+struct DataSourceThreadLocalState {
+ DataSourceStaticState* static_state = nullptr;
+
+ // Pointer to the parent tls object that holds us. Used to retrieve the
+ // generation, which is per-global-TLS and not per data-source.
+ TracingTLS* root_tls = nullptr;
+
+ // One entry per each data source instance.
+ std::array<DataSourceInstanceThreadLocalState, kMaxDataSourceInstances>
+ per_instance{};
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
+// gen_amalgamated begin header: include/perfetto/tracing/locked_handle.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
+#define INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
+
+#include <mutex>
+
+namespace perfetto {
+
+// This is used for GetDataSourceLocked(), in the (rare) case where the
+// tracing code wants to access the state of its data source from the Trace()
+// method.
+template <typename T>
+class LockedHandle {
+ public:
+ LockedHandle(std::unique_lock<std::recursive_mutex> lock, T* obj)
+ : lock_(std::move(lock)), obj_(obj) {}
+ LockedHandle() = default; // For the invalid case.
+ LockedHandle(LockedHandle&&) = default;
+ LockedHandle& operator=(LockedHandle&&) = default;
+
+ bool valid() const { return obj_; }
+ explicit operator bool() const { return valid(); }
+
+ T* operator->() {
+ assert(valid());
+ return obj_;
+ }
+
+ T& operator*() { return *(this->operator->()); }
+
+ private:
+ std::unique_lock<std::recursive_mutex> lock_;
+ T* obj_ = nullptr;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
+#define INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
+
+// An interceptor is used to redirect trace packets written by a data source
+// into a custom backend instead of the normal Perfetto tracing service. For
+// example, the console interceptor prints all trace packets to the console as
+// they are generated. Another potential use is exporting trace data to another
+// tracing service such as Android ATrace or Windows ETW.
+//
+// An interceptor is defined by subclassing the perfetto::Interceptor template:
+//
+// class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
+// public:
+// ~MyInterceptor() override = default;
+//
+// // This function is called for each intercepted trace packet. |context|
+// // contains information about the trace packet as well as other state
+// // tracked by the interceptor (e.g., see ThreadLocalState).
+// //
+// // Intercepted trace data is provided in the form of serialized protobuf
+// // bytes, accessed through the |context.packet_data| field.
+// //
+// // Warning: this function can be called on any thread at any time. See
+// // below for how to safely access shared interceptor data from here.
+// static void OnTracePacket(InterceptorContext context) {
+// perfetto::protos::pbzero::TracePacket::Decoder packet(
+// context.packet_data.data, context.packet_data.size);
+// // ... Write |packet| to the desired destination ...
+// }
+// };
+//
+// An interceptor should be registered before any tracing sessions are started.
+// Note that the interceptor also needs to be activated through the trace config
+// as shown below.
+//
+// perfetto::InterceptorDescriptor desc;
+// desc.set_name("my_interceptor");
+// MyInterceptor::Register(desc);
+//
+// Finally, an interceptor is enabled through the trace config like this:
+//
+// perfetto::TraceConfig cfg;
+// auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+// ds_cfg->set_name("data_source_to_intercept"); // e.g. "track_event"
+// ds_cfg->mutable_interceptor_config()->set_name("my_interceptor");
+//
+// Once an interceptor is enabled, all data from the affected data sources is
+// sent to the interceptor instead of the main tracing buffer.
+//
+// Interceptor state
+// =================
+//
+// Besides the serialized trace packet data, the |OnTracePacket| interceptor
+// function can access three other types of state:
+//
+// 1. Global state: this is no different from a normal static function, but care
+// must be taken because |OnTracePacket| can be called concurrently on any
+// thread at any time.
+//
+// 2. Per-data source instance state: since the interceptor class is
+// automatically instantiated for each intercepted data source, its fields
+// can be used to store per-instance data such as the trace config. This data
+// can be maintained through the OnSetup/OnStart/OnStop callbacks:
+//
+// class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
+// public:
+// void OnSetup(const SetupArgs& args) override {
+// enable_foo_ = args.config.interceptor_config().enable_foo();
+// }
+//
+// bool enable_foo_{};
+// };
+//
+// In the interceptor function this data must be accessed through a scoped
+// lock for safety:
+//
+// class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
+// ...
+// static void OnTracePacket(InterceptorContext context) {
+// auto my_interceptor = context.GetInterceptorLocked();
+// if (my_interceptor) {
+// // Access fields of MyInterceptor here.
+// if (my_interceptor->enable_foo_) { ... }
+// }
+// ...
+// }
+// };
+//
+// Since accessing this data involves holding a lock, it should be done
+// sparingly.
+//
+// 3. Per-thread/TraceWriter state: many data sources use interning to avoid
+// repeating common data in the trace. Since the interning dictionaries are
+// typically kept individually for each TraceWriter sequence (i.e., per
+// thread), an interceptor can declare a data structure with lifetime
+// matching the TraceWriter:
+//
+// class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
+// public:
+// struct ThreadLocalState
+// : public perfetto::InterceptorBase::ThreadLocalState {
+// ThreadLocalState(ThreadLocalStateArgs&) override = default;
+// ~ThreadLocalState() override = default;
+//
+// std::map<size_t, std::string> event_names;
+// };
+// };
+//
+// This per-thread state can then be accessed and maintained in
+// |OnTracePacket| like this:
+//
+// class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
+// ...
+// static void OnTracePacket(InterceptorContext context) {
+// // Updating interned data.
+// auto& tls = context.GetThreadLocalState();
+// if (parsed_packet.sequence_flags() & perfetto::protos::pbzero::
+// TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
+// tls.event_names.clear();
+// }
+// for (const auto& entry : parsed_packet.interned_data().event_names())
+// tls.event_names[entry.iid()] = entry.name();
+//
+// // Looking up interned data.
+// if (parsed_packet.has_track_event()) {
+// size_t name_iid = parsed_packet.track_event().name_iid();
+// const std::string& event_name = tls.event_names[name_iid];
+// }
+// ...
+// }
+// };
+//
+
+#include <functional>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/locked_handle.h"
+
+namespace {
+class MockTracingMuxer;
+}
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class DataSourceConfig;
+class InterceptorDescriptor;
+} // namespace gen
+} // namespace protos
+
+using protos::gen::InterceptorDescriptor;
+
+namespace internal {
+class InterceptorTraceWriter;
+class InterceptorTraceWriterTest;
+class TracingMuxer;
+class TracingMuxerFake;
+class TracingMuxerImpl;
+} // namespace internal
+
+// A virtual base class for interceptors. Users should derive from the templated
+// subclass below instead of this one.
+class PERFETTO_EXPORT_COMPONENT InterceptorBase {
+ public:
+ virtual ~InterceptorBase();
+
+ // A virtual base class for thread-local state needed by the interceptor.
+ // To define your own state, subclass this with the same name in the
+ // interceptor class. A reference to the state can then be looked up through
+ // context.GetThreadLocalState() in the trace packet interceptor function.
+ class PERFETTO_EXPORT_COMPONENT ThreadLocalState {
+ public:
+ virtual ~ThreadLocalState();
+ };
+
+ struct SetupArgs {
+ const DataSourceConfig& config;
+ };
+ struct StartArgs {};
+ struct StopArgs {};
+
+ // Called when an intercepted data source is set up. Both the interceptor's
+ // and the data source's configuration is available in
+ // |SetupArgs|. Called on an internal Perfetto service thread, but not
+ // concurrently.
+ virtual void OnSetup(const SetupArgs&) {}
+
+ // Called when an intercepted data source starts. Called on an internal
+ // Perfetto service thread, but not concurrently.
+ virtual void OnStart(const StartArgs&) {}
+
+ // Called when an intercepted data source stops. Called on an internal
+ // Perfetto service thread, but not concurrently.
+ virtual void OnStop(const StopArgs&) {}
+
+ private:
+ friend class internal::InterceptorTraceWriter;
+ friend class internal::InterceptorTraceWriterTest;
+ friend class internal::TracingMuxer;
+ friend class internal::TracingMuxerFake;
+ friend class internal::TracingMuxerImpl;
+ friend MockTracingMuxer;
+ template <class T>
+ friend class Interceptor;
+
+ // Data passed from DataSource::Trace() into the interceptor.
+ struct TracePacketCallbackArgs {
+ internal::DataSourceStaticState* static_state;
+ uint32_t instance_index;
+ protozero::ConstBytes packet_data;
+ ThreadLocalState* tls;
+ };
+
+ // These callback functions are defined as stateless to avoid accidentally
+ // introducing cross-thread data races.
+ using TLSFactory = std::unique_ptr<ThreadLocalState> (*)(
+ internal::DataSourceStaticState*,
+ uint32_t data_source_instance_index);
+ using TracePacketCallback = void (*)(TracePacketCallbackArgs);
+
+ static void RegisterImpl(
+ const InterceptorDescriptor& descriptor,
+ std::function<std::unique_ptr<InterceptorBase>()> factory,
+ InterceptorBase::TLSFactory tls_factory,
+ InterceptorBase::TracePacketCallback on_trace_packet);
+};
+
+// Templated interceptor instantiation. See above for usage.
+template <class InterceptorType>
+class PERFETTO_EXPORT_COMPONENT Interceptor : public InterceptorBase {
+ public:
+ // A context object provided to the ThreadLocalState constructor. Provides
+ // access to the per-instance interceptor object.
+ class ThreadLocalStateArgs {
+ public:
+ ~ThreadLocalStateArgs() = default;
+
+ ThreadLocalStateArgs(const ThreadLocalStateArgs&) = delete;
+ ThreadLocalStateArgs& operator=(const ThreadLocalStateArgs&) = delete;
+
+ ThreadLocalStateArgs(ThreadLocalStateArgs&&) noexcept = default;
+ ThreadLocalStateArgs& operator=(ThreadLocalStateArgs&&) noexcept = default;
+
+ // Return a locked reference to the interceptor session. The session object
+ // will remain valid as long as the returned handle is in scope.
+ LockedHandle<InterceptorType> GetInterceptorLocked() {
+ auto* internal_state = static_state_->TryGet(data_source_instance_index_);
+ if (!internal_state)
+ return LockedHandle<InterceptorType>();
+ std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
+ return LockedHandle<InterceptorType>(
+ std::move(lock),
+ static_cast<InterceptorType*>(internal_state->interceptor.get()));
+ }
+
+ private:
+ friend class Interceptor<InterceptorType>;
+ friend class InterceptorContext;
+ friend class TracingMuxerImpl;
+
+ ThreadLocalStateArgs(internal::DataSourceStaticState* static_state,
+ uint32_t data_source_instance_index)
+ : static_state_(static_state),
+ data_source_instance_index_(data_source_instance_index) {}
+
+ internal::DataSourceStaticState* const static_state_;
+ const uint32_t data_source_instance_index_;
+ };
+
+ // A context object provided to each call into |OnTracePacket|. Contains the
+ // intercepted serialized trace packet data.
+ class InterceptorContext {
+ public:
+ InterceptorContext(InterceptorContext&&) noexcept = default;
+ ~InterceptorContext() = default;
+
+ // Return a locked reference to the interceptor session. The session object
+ // will remain valid as long as the returned handle is in scope.
+ LockedHandle<InterceptorType> GetInterceptorLocked() {
+ return tls_args_.GetInterceptorLocked();
+ }
+
+ // Return the thread-local state for this interceptor. See
+ // InterceptorBase::ThreadLocalState.
+ typename InterceptorType::ThreadLocalState& GetThreadLocalState() {
+ return static_cast<typename InterceptorType::ThreadLocalState&>(*tls_);
+ }
+
+ // A buffer containing the serialized TracePacket protocol buffer message.
+ // This memory is only valid during the call to OnTracePacket.
+ protozero::ConstBytes packet_data;
+
+ private:
+ friend class Interceptor<InterceptorType>;
+ InterceptorContext(TracePacketCallbackArgs args)
+ : packet_data(args.packet_data),
+ tls_args_(args.static_state, args.instance_index),
+ tls_(args.tls) {}
+ InterceptorContext(const InterceptorContext&) = delete;
+ InterceptorContext& operator=(const InterceptorContext&) = delete;
+
+ ThreadLocalStateArgs tls_args_;
+ InterceptorBase::ThreadLocalState* const tls_;
+ };
+
+ // Register the interceptor for use in tracing sessions.
+ // The optional |constructor_args| will be passed to the interceptor when it
+ // is constructed.
+ template <class... Args>
+ static void Register(const InterceptorDescriptor& descriptor,
+ const Args&... constructor_args) {
+ auto factory = [constructor_args...]() {
+ return std::unique_ptr<InterceptorBase>(
+ new InterceptorType(constructor_args...));
+ };
+ auto tls_factory = [](internal::DataSourceStaticState* static_state,
+ uint32_t data_source_instance_index) {
+ // Don't bother allocating TLS state unless the interceptor is actually
+ // using it.
+ if (std::is_same<typename InterceptorType::ThreadLocalState,
+ InterceptorBase::ThreadLocalState>::value) {
+ return std::unique_ptr<InterceptorBase::ThreadLocalState>(nullptr);
+ }
+ ThreadLocalStateArgs args(static_state, data_source_instance_index);
+ return std::unique_ptr<InterceptorBase::ThreadLocalState>(
+ new typename InterceptorType::ThreadLocalState(args));
+ };
+ auto on_trace_packet = [](TracePacketCallbackArgs args) {
+ InterceptorType::OnTracePacket(InterceptorContext(std::move(args)));
+ };
+ RegisterImpl(descriptor, std::move(factory), std::move(tls_factory),
+ std::move(on_trace_packet));
+ }
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
+// gen_amalgamated begin header: include/perfetto/tracing/track_event_state_tracker.h
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/track_event.pbzero.h
+// gen_amalgamated begin header: include/perfetto/protozero/field_writer.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
+#define INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
+
+namespace protozero {
+namespace internal {
+
+template <proto_utils::ProtoSchemaType proto_schema_type>
+struct FieldWriter {
+ static_assert(proto_schema_type != proto_utils::ProtoSchemaType::kMessage,
+ "FieldWriter can't be used with nested messages");
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kDouble> {
+ inline static void Append(Message& message, uint32_t field_id, double value) {
+ message.AppendFixed(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kFloat> {
+ inline static void Append(Message& message, uint32_t field_id, float value) {
+ message.AppendFixed(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kBool> {
+ inline static void Append(Message& message, uint32_t field_id, bool value) {
+ message.AppendTinyVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kInt32> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ int32_t value) {
+ message.AppendVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kInt64> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ int64_t value) {
+ message.AppendVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kUint32> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ uint32_t value) {
+ message.AppendVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kUint64> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ uint64_t value) {
+ message.AppendVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kSint32> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ int32_t value) {
+ message.AppendSignedVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kSint64> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ int64_t value) {
+ message.AppendSignedVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kFixed32> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ uint32_t value) {
+ message.AppendFixed(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kFixed64> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ uint64_t value) {
+ message.AppendFixed(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kSfixed32> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ int32_t value) {
+ message.AppendFixed(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kSfixed64> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ int64_t value) {
+ message.AppendFixed(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kEnum> {
+ template <typename EnumType>
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ EnumType value) {
+ message.AppendVarInt(field_id, value);
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kString> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ const char* data,
+ size_t size) {
+ message.AppendBytes(field_id, data, size);
+ }
+
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ const std::string& value) {
+ message.AppendBytes(field_id, value.data(), value.size());
+ }
+};
+
+template <>
+struct FieldWriter<proto_utils::ProtoSchemaType::kBytes> {
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ const uint8_t* data,
+ size_t size) {
+ message.AppendBytes(field_id, data, size);
+ }
+
+ inline static void Append(Message& message,
+ uint32_t field_id,
+ const std::string& value) {
+ message.AppendBytes(field_id, value.data(), value.size());
+ }
+};
+
+} // namespace internal
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
+// gen_amalgamated begin header: include/perfetto/protozero/packed_repeated_fields.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
+#define INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
+
+#include <stdint.h>
+
+#include <array>
+#include <memory>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace protozero {
+
+// This file contains classes used when encoding packed repeated fields.
+// To encode such a field, the caller is first expected to accumulate all of the
+// values in one of the following types (depending on the wire type of the
+// individual elements), defined below:
+// * protozero::PackedVarInt
+// * protozero::PackedFixedSizeInt</*element_type=*/ uint32_t>
+// Then that buffer is passed to the protozero-generated setters as an argument.
+// After calling the setter, the buffer can be destroyed.
+//
+// An example of encoding a packed field:
+// protozero::HeapBuffered<protozero::Message> msg;
+// protozero::PackedVarInt buf;
+// buf.Append(42);
+// buf.Append(-1);
+// msg->set_fieldname(buf);
+// msg.SerializeAsString();
+
+class PackedBufferBase {
+ public:
+ PackedBufferBase() { Reset(); }
+
+ // Copy or move is disabled due to pointers to stack addresses.
+ PackedBufferBase(const PackedBufferBase&) = delete;
+ PackedBufferBase(PackedBufferBase&&) = delete;
+ PackedBufferBase& operator=(const PackedBufferBase&) = delete;
+ PackedBufferBase& operator=(PackedBufferBase&&) = delete;
+
+ void Reset();
+
+ const uint8_t* data() const { return storage_begin_; }
+
+ size_t size() const {
+ return static_cast<size_t>(write_ptr_ - storage_begin_);
+ }
+
+ protected:
+ void GrowIfNeeded() {
+ PERFETTO_DCHECK(write_ptr_ >= storage_begin_ && write_ptr_ <= storage_end_);
+ if (PERFETTO_UNLIKELY(write_ptr_ + kMaxElementSize > storage_end_)) {
+ GrowSlowpath();
+ }
+ }
+
+ void GrowSlowpath();
+
+ // max(uint64_t varint encoding, biggest fixed type (uint64)).
+ static constexpr size_t kMaxElementSize = 10;
+
+ // So sizeof(this) == 8k.
+ static constexpr size_t kOnStackStorageSize = 8192 - 32;
+
+ uint8_t* storage_begin_;
+ uint8_t* storage_end_;
+ uint8_t* write_ptr_;
+ std::unique_ptr<uint8_t[]> heap_buf_;
+ alignas(uint64_t) uint8_t stack_buf_[kOnStackStorageSize];
+};
+
+class PackedVarInt : public PackedBufferBase {
+ public:
+ template <typename T>
+ void Append(T value) {
+ GrowIfNeeded();
+ write_ptr_ = proto_utils::WriteVarInt(value, write_ptr_);
+ }
+};
+
+template <typename T /* e.g. uint32_t for Fixed32 */>
+class PackedFixedSizeInt : public PackedBufferBase {
+ public:
+ void Append(T value) {
+ static_assert(sizeof(T) == 4 || sizeof(T) == 8,
+ "PackedFixedSizeInt should be used only with 32/64-bit ints");
+ static_assert(sizeof(T) <= kMaxElementSize,
+ "kMaxElementSize needs to be updated");
+ GrowIfNeeded();
+ PERFETTO_DCHECK(reinterpret_cast<size_t>(write_ptr_) % alignof(T) == 0);
+ memcpy(reinterpret_cast<T*>(write_ptr_), &value, sizeof(T));
+ write_ptr_ += sizeof(T);
+ }
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
+// gen_amalgamated begin header: include/perfetto/protozero/proto_decoder.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
+#define INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
+
+#include <stdint.h>
+#include <array>
+#include <memory>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/field.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace protozero {
+
+// A generic protobuf decoder. Doesn't require any knowledge about the proto
+// schema. It tokenizes fields, retrieves their ID and type and exposes
+// accessors to retrieve its values.
+// It does NOT recurse in nested submessages, instead it just computes their
+// boundaries, recursion is left to the caller.
+// This class is designed to be used in perf-sensitive contexts. It does not
+// allocate and does not perform any proto semantic checks (e.g. repeated /
+// required / optional). It's supposedly safe wrt out-of-bounds memory accesses
+// (see proto_decoder_fuzzer.cc).
+// This class serves also as a building block for TypedProtoDecoder, used when
+// the schema is known at compile time.
+class PERFETTO_EXPORT_COMPONENT ProtoDecoder {
+ public:
+ // Creates a ProtoDecoder using the given |buffer| with size |length| bytes.
+ ProtoDecoder(const void* buffer, size_t length)
+ : begin_(reinterpret_cast<const uint8_t*>(buffer)),
+ end_(begin_ + length),
+ read_ptr_(begin_) {}
+ ProtoDecoder(const std::string& str) : ProtoDecoder(str.data(), str.size()) {}
+ ProtoDecoder(const ConstBytes& cb) : ProtoDecoder(cb.data, cb.size) {}
+
+ // Reads the next field from the buffer and advances the read cursor. If a
+ // full field cannot be read, the returned Field will be invalid (i.e.
+ // field.valid() == false).
+ Field ReadField();
+
+ // Finds the first field with the given id. Doesn't affect the read cursor.
+ Field FindField(uint32_t field_id);
+
+ // Resets the read cursor to the start of the buffer.
+ void Reset() { read_ptr_ = begin_; }
+
+ // Resets the read cursor to the given position (must be within the buffer).
+ void Reset(const uint8_t* pos) {
+ PERFETTO_DCHECK(pos >= begin_ && pos < end_);
+ read_ptr_ = pos;
+ }
+
+ // Returns the position of read cursor, relative to the start of the buffer.
+ size_t read_offset() const { return static_cast<size_t>(read_ptr_ - begin_); }
+
+ size_t bytes_left() const {
+ PERFETTO_DCHECK(read_ptr_ <= end_);
+ return static_cast<size_t>(end_ - read_ptr_);
+ }
+
+ const uint8_t* begin() const { return begin_; }
+ const uint8_t* end() const { return end_; }
+
+ protected:
+ const uint8_t* const begin_;
+ const uint8_t* const end_;
+ const uint8_t* read_ptr_ = nullptr;
+};
+
+// An iterator-like class used to iterate through repeated fields. Used by
+// TypedProtoDecoder. The iteration sequence is a bit counter-intuitive due to
+// the fact that fields_[field_id] holds the *last* value of the field, not the
+// first, but the remaining storage holds repeated fields in FIFO order.
+// Assume that we push the 10,11,12 into a repeated field with ID=1.
+//
+// Decoder memory layout: [ fields storage ] [ repeated fields storage ]
+// 1st iteration: 10
+// 2nd iteration: 11 10
+// 3rd iteration: 12 10 11
+//
+// We start the iteration @ fields_[num_fields], which is the start of the
+// repeated fields storage, proceed until the end and lastly jump @ fields_[id].
+template <typename T>
+class RepeatedFieldIterator {
+ public:
+ RepeatedFieldIterator(uint32_t field_id,
+ const Field* begin,
+ const Field* end,
+ const Field* last)
+ : field_id_(field_id), iter_(begin), end_(end), last_(last) {
+ FindNextMatchingId();
+ }
+
+ // Constructs an invalid iterator.
+ RepeatedFieldIterator()
+ : field_id_(0u), iter_(nullptr), end_(nullptr), last_(nullptr) {}
+
+ explicit operator bool() const { return iter_ != end_; }
+ const Field& field() const { return *iter_; }
+
+ T operator*() const {
+ T val{};
+ iter_->get(&val);
+ return val;
+ }
+ const Field* operator->() const { return iter_; }
+
+ RepeatedFieldIterator& operator++() {
+ PERFETTO_DCHECK(iter_ != end_);
+ if (iter_ == last_) {
+ iter_ = end_;
+ return *this;
+ }
+ ++iter_;
+ FindNextMatchingId();
+ return *this;
+ }
+
+ RepeatedFieldIterator operator++(int) {
+ PERFETTO_DCHECK(iter_ != end_);
+ RepeatedFieldIterator it(*this);
+ ++(*this);
+ return it;
+ }
+
+ private:
+ void FindNextMatchingId() {
+ PERFETTO_DCHECK(iter_ != last_);
+ for (; iter_ != end_; ++iter_) {
+ if (iter_->id() == field_id_)
+ return;
+ }
+ iter_ = last_->valid() ? last_ : end_;
+ }
+
+ uint32_t field_id_;
+
+ // Initially points to the beginning of the repeated field storage, then is
+ // incremented as we call operator++().
+ const Field* iter_;
+
+ // Always points to fields_[size_], i.e. past the end of the storage.
+ const Field* end_;
+
+ // Always points to fields_[field_id].
+ const Field* last_;
+};
+
+// As RepeatedFieldIterator, but allows iterating over a packed repeated field
+// (which will be initially stored as a single length-delimited field).
+// See |GetPackedRepeatedField| for details.
+//
+// Assumes little endianness, and that the input buffers are well formed -
+// containing an exact multiple of encoded elements.
+template <proto_utils::ProtoWireType wire_type, typename CppType>
+class PackedRepeatedFieldIterator {
+ public:
+ PackedRepeatedFieldIterator(const uint8_t* data_begin,
+ size_t size,
+ bool* parse_error_ptr)
+ : data_end_(data_begin ? data_begin + size : nullptr),
+ read_ptr_(data_begin),
+ parse_error_(parse_error_ptr) {
+ using proto_utils::ProtoWireType;
+ static_assert(wire_type == ProtoWireType::kVarInt ||
+ wire_type == ProtoWireType::kFixed32 ||
+ wire_type == ProtoWireType::kFixed64,
+ "invalid type");
+
+ PERFETTO_DCHECK(parse_error_ptr);
+
+ // Either the field is unset (and there are no data pointer), or the field
+ // is set with a zero length payload. Mark the iterator as invalid in both
+ // cases.
+ if (size == 0) {
+ curr_value_valid_ = false;
+ return;
+ }
+
+ if ((wire_type == ProtoWireType::kFixed32 && (size % 4) != 0) ||
+ (wire_type == ProtoWireType::kFixed64 && (size % 8) != 0)) {
+ *parse_error_ = true;
+ curr_value_valid_ = false;
+ return;
+ }
+
+ ++(*this);
+ }
+
+ const CppType operator*() const { return curr_value_; }
+ explicit operator bool() const { return curr_value_valid_; }
+
+ PackedRepeatedFieldIterator& operator++() {
+ using proto_utils::ProtoWireType;
+
+ if (PERFETTO_UNLIKELY(!curr_value_valid_))
+ return *this;
+
+ if (PERFETTO_UNLIKELY(read_ptr_ == data_end_)) {
+ curr_value_valid_ = false;
+ return *this;
+ }
+
+ if (wire_type == ProtoWireType::kVarInt) {
+ uint64_t new_value = 0;
+ const uint8_t* new_pos =
+ proto_utils::ParseVarInt(read_ptr_, data_end_, &new_value);
+
+ if (PERFETTO_UNLIKELY(new_pos == read_ptr_)) {
+ // Failed to decode the varint (probably incomplete buffer).
+ *parse_error_ = true;
+ curr_value_valid_ = false;
+ } else {
+ read_ptr_ = new_pos;
+ curr_value_ = static_cast<CppType>(new_value);
+ }
+ } else { // kFixed32 or kFixed64
+ constexpr size_t kStep = wire_type == ProtoWireType::kFixed32 ? 4 : 8;
+
+ // NB: the raw buffer is not guaranteed to be aligned, so neither are
+ // these copies.
+ memcpy(&curr_value_, read_ptr_, sizeof(CppType));
+ read_ptr_ += kStep;
+ }
+
+ return *this;
+ }
+
+ PackedRepeatedFieldIterator operator++(int) {
+ PackedRepeatedFieldIterator it(*this);
+ ++(*this);
+ return it;
+ }
+
+ private:
+ // Might be null if the backing proto field isn't set.
+ const uint8_t* const data_end_;
+
+ // The iterator looks ahead by an element, so |curr_value| holds the value
+ // to be returned when the caller dereferences the iterator, and |read_ptr_|
+ // points at the start of the next element to be decoded.
+ // |read_ptr_| might be null if the backing proto field isn't set.
+ const uint8_t* read_ptr_;
+ CppType curr_value_ = {};
+
+ // Set to false once we've exhausted the iterator, or encountered an error.
+ bool curr_value_valid_ = true;
+
+ // Where to set parsing errors, supplied by the caller.
+ bool* const parse_error_;
+};
+
+// This decoder loads all fields upfront, without recursing in nested messages.
+// It is used as a base class for typed decoders generated by the pbzero plugin.
+// The split between TypedProtoDecoderBase and TypedProtoDecoder<> is to have
+// unique definition of functions like ParseAllFields() and ExpandHeapStorage().
+// The storage (either on-stack or on-heap) for this class is organized as
+// follows:
+// |-------------------------- fields_ ----------------------|
+// [ field 0 (invalid) ] [ fields 1 .. N ] [ repeated fields ]
+// ^ ^
+// num_fields_ size_
+// Note that if a message has high field numbers, upon creation |size_| can be
+// < |num_fields_| (until a heap expansion is hit while inserting).
+class PERFETTO_EXPORT_COMPONENT TypedProtoDecoderBase : public ProtoDecoder {
+ public:
+ // If the field |id| is known at compile time, prefer the templated
+ // specialization at<kFieldNumber>().
+ const Field& Get(uint32_t id) const {
+ if (PERFETTO_LIKELY(id < num_fields_ && id < size_))
+ return fields_[id];
+ // If id >= num_fields_, the field id is invalid (was not known in the
+ // .proto) and we return the 0th field, which is always !valid().
+ // If id >= size_ and <= num_fields, the id is valid but the field has not
+ // been seen while decoding (hence the stack storage has not been expanded)
+ // so we return the 0th invalid field.
+ return fields_[0];
+ }
+
+ // Returns an object that allows to iterate over all instances of a repeated
+ // field given its id. Example usage:
+ // for (auto it = decoder.GetRepeated<int32_t>(N); it; ++it) { ... }
+ template <typename T>
+ RepeatedFieldIterator<T> GetRepeated(uint32_t field_id) const {
+ const Field* repeated_begin;
+ // The storage for repeated fields starts after the slot for the highest
+ // field id (refer to the diagram in the class-level comment). However, if
+ // a message has more than INITIAL_STACK_CAPACITY field there will be no
+ // slots available for the repeated fields (if ExpandHeapStorage() was not
+ // called). Imagine a message that has highest field id = 102 and that is
+ // still using the stack:
+ // [ F0 ] [ F1 ] ... [ F100 ] [ F101 ] [ F1012] [ repeated fields ]
+ // ^ num_fields_
+ // ^ size (== capacity)
+ if (PERFETTO_LIKELY(num_fields_ < size_)) {
+ repeated_begin = &fields_[num_fields_];
+ } else {
+ // This is the case of not having any storage space for repeated fields.
+ // This makes it so begin == end, so the iterator will just skip @ last.
+ repeated_begin = &fields_[size_];
+ }
+ const Field* repeated_end = &fields_[size_];
+ const Field* last = &Get(field_id);
+ return RepeatedFieldIterator<T>(field_id, repeated_begin, repeated_end,
+ last);
+ }
+
+ // Returns an objects that allows to iterate over all entries of a packed
+ // repeated field given its id and type. The |wire_type| is necessary for
+ // decoding the packed field, the |cpp_type| is for convenience & stronger
+ // typing.
+ //
+ // The caller must also supply a pointer to a bool that is set to true if the
+ // packed buffer is found to be malformed while iterating (so you need to
+ // exhaust the iterator if you want to check the full extent of the buffer).
+ //
+ // Note that unlike standard protobuf parsers, protozero does not allow
+ // treating of packed repeated fields as non-packed and vice-versa (therefore
+ // not making the packed option forwards and backwards compatible). So
+ // the caller needs to use the right accessor for correct results.
+ template <proto_utils::ProtoWireType wire_type, typename cpp_type>
+ PackedRepeatedFieldIterator<wire_type, cpp_type> GetPackedRepeated(
+ uint32_t field_id,
+ bool* parse_error_location) const {
+ const Field& field = Get(field_id);
+ if (field.valid() &&
+ field.type() == proto_utils::ProtoWireType::kLengthDelimited) {
+ return PackedRepeatedFieldIterator<wire_type, cpp_type>(
+ field.data(), field.size(), parse_error_location);
+ }
+ return PackedRepeatedFieldIterator<wire_type, cpp_type>(
+ nullptr, 0, parse_error_location);
+ }
+
+ protected:
+ TypedProtoDecoderBase(Field* storage,
+ uint32_t num_fields,
+ uint32_t capacity,
+ const uint8_t* buffer,
+ size_t length)
+ : ProtoDecoder(buffer, length),
+ fields_(storage),
+ num_fields_(num_fields),
+ // The reason for "capacity -1" is to avoid hitting the expansion path
+ // in TypedProtoDecoderBase::ParseAllFields() when we are just setting
+ // fields < INITIAL_STACK_CAPACITY (which is the most common case).
+ size_(std::min(num_fields, capacity - 1)),
+ capacity_(capacity) {
+ // The reason why Field needs to be trivially de/constructible is to avoid
+ // implicit initializers on all the ~1000 entries. We need it to initialize
+ // only on the first |max_field_id| fields, the remaining capacity doesn't
+ // require initialization.
+ static_assert(std::is_trivially_constructible<Field>::value &&
+ std::is_trivially_destructible<Field>::value &&
+ std::is_trivial<Field>::value,
+ "Field must be a trivial aggregate type");
+ memset(fields_, 0, sizeof(Field) * capacity_);
+ PERFETTO_DCHECK(capacity > 0);
+ }
+
+ void ParseAllFields();
+
+ // Called when the default on-stack storage is exhausted and new repeated
+ // fields need to be pushed.
+ void ExpandHeapStorage();
+
+ // Used only in presence of a large number of repeated fields, when the
+ // default on-stack storage is exhausted.
+ std::unique_ptr<Field[]> heap_storage_;
+
+ // Points to the storage, either on-stack (default, provided by the template
+ // specialization) or |heap_storage_| after ExpandHeapStorage() is called, in
+ // case of a large number of repeated fields.
+ Field* fields_;
+
+ // Number of known fields, without accounting repeated storage. This is equal
+ // to MAX_FIELD_ID + 1 (to account for the invalid 0th field). It never
+ // changes after construction.
+ // This is unrelated with |size_| and |capacity_|. If the highest field id of
+ // a proto message is 131, |num_fields_| will be = 132 but, on initialization,
+ // |size_| = |capacity_| = 100 (INITIAL_STACK_CAPACITY).
+ // One cannot generally assume that |fields_| has enough storage to
+ // dereference every field. That is only true:
+ // - For field ids < INITIAL_STACK_CAPACITY.
+ // - After the first call to ExpandHeapStorage().
+ uint32_t num_fields_;
+
+ // Number of active |fields_| entries. This is initially equal to
+ // min(num_fields_, INITIAL_STACK_CAPACITY - 1) and after ExpandHeapStorage()
+ // becomes == |num_fields_|. If the message has non-packed repeated fields, it
+ // can grow further, up to |capacity_|.
+ // |size_| is always <= |capacity_|. But |num_fields_| can be > |size_|.
+ uint32_t size_;
+
+ // Initially equal to kFieldsCapacity of the TypedProtoDecoder
+ // specialization. Can grow when falling back on heap-based storage, in which
+ // case it represents the size (#fields with each entry of a repeated field
+ // counted individually) of the |heap_storage_| array.
+ uint32_t capacity_;
+};
+
+// This constant is a tradeoff between having a larger stack frame and being
+// able to decode field IDs up to N (or N - num_fields repeated fields) without
+// falling back on the heap.
+#define PROTOZERO_DECODER_INITIAL_STACK_CAPACITY 100
+
+// Template class instantiated by the auto-generated decoder classes declared in
+// xxx.pbzero.h files.
+template <int MAX_FIELD_ID, bool HAS_NONPACKED_REPEATED_FIELDS>
+class TypedProtoDecoder : public TypedProtoDecoderBase {
+ public:
+ TypedProtoDecoder(const uint8_t* buffer, size_t length)
+ : TypedProtoDecoderBase(on_stack_storage_,
+ /*num_fields=*/MAX_FIELD_ID + 1,
+ PROTOZERO_DECODER_INITIAL_STACK_CAPACITY,
+ buffer,
+ length) {
+ TypedProtoDecoderBase::ParseAllFields();
+ }
+
+ template <uint32_t FIELD_ID>
+ const Field& at() const {
+ static_assert(FIELD_ID <= MAX_FIELD_ID, "FIELD_ID > MAX_FIELD_ID");
+ // If the field id is < the on-stack capacity, it's safe to always
+ // dereference |fields_|, whether it's still using the stack or it fell
+ // back on the heap. Because both terms of the if () are known at compile
+ // time, the compiler elides the branch for ids < INITIAL_STACK_CAPACITY.
+ if (FIELD_ID < PROTOZERO_DECODER_INITIAL_STACK_CAPACITY) {
+ return fields_[FIELD_ID];
+ } else {
+ // Otherwise use the slowpath Get() which will do a runtime check.
+ return Get(FIELD_ID);
+ }
+ }
+
+ TypedProtoDecoder(TypedProtoDecoder&& other) noexcept
+ : TypedProtoDecoderBase(std::move(other)) {
+ // If the moved-from decoder was using on-stack storage, we need to update
+ // our pointer to point to this decoder's on-stack storage.
+ if (fields_ == other.on_stack_storage_) {
+ fields_ = on_stack_storage_;
+ memcpy(on_stack_storage_, other.on_stack_storage_,
+ sizeof(on_stack_storage_));
+ }
+ }
+
+ private:
+ Field on_stack_storage_[PROTOZERO_DECODER_INITIAL_STACK_CAPACITY];
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ChromeActiveProcesses;
+class ChromeApplicationStateInfo;
+class ChromeCompositorSchedulerState;
+class ChromeContentSettingsEventInfo;
+class ChromeFrameReporter;
+class ChromeHistogramSample;
+class ChromeKeyedService;
+class ChromeLatencyInfo;
+class ChromeLegacyIpc;
+class ChromeMessagePump;
+class ChromeMojoEventInfo;
+class ChromeRendererSchedulerState;
+class ChromeUserEvent;
+class ChromeWindowHandleEventInfo;
+class DebugAnnotation;
+class LogMessage;
+class PixelModemEventInsight;
+class Screenshot;
+class SourceLocation;
+class TaskExecution;
+class TrackEvent_LegacyEvent;
+namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
+enum FlowDirection : int32_t;
+} // namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
+using TrackEvent_LegacyEvent_FlowDirection = perfetto_pbzero_enum_TrackEvent_LegacyEvent::FlowDirection;
+namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
+enum InstantEventScope : int32_t;
+} // namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
+using TrackEvent_LegacyEvent_InstantEventScope = perfetto_pbzero_enum_TrackEvent_LegacyEvent::InstantEventScope;
+namespace perfetto_pbzero_enum_TrackEvent {
+enum Type : int32_t;
+} // namespace perfetto_pbzero_enum_TrackEvent
+using TrackEvent_Type = perfetto_pbzero_enum_TrackEvent::Type;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_TrackEvent {
+enum Type : int32_t {
+ TYPE_UNSPECIFIED = 0,
+ TYPE_SLICE_BEGIN = 1,
+ TYPE_SLICE_END = 2,
+ TYPE_INSTANT = 3,
+ TYPE_COUNTER = 4,
+};
+} // namespace perfetto_pbzero_enum_TrackEvent
+using TrackEvent_Type = perfetto_pbzero_enum_TrackEvent::Type;
+
+
+constexpr TrackEvent_Type TrackEvent_Type_MIN = TrackEvent_Type::TYPE_UNSPECIFIED;
+constexpr TrackEvent_Type TrackEvent_Type_MAX = TrackEvent_Type::TYPE_COUNTER;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TrackEvent_Type_Name(::perfetto::protos::pbzero::TrackEvent_Type value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_UNSPECIFIED:
+ return "TYPE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_SLICE_BEGIN:
+ return "TYPE_SLICE_BEGIN";
+
+ case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_SLICE_END:
+ return "TYPE_SLICE_END";
+
+ case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_INSTANT:
+ return "TYPE_INSTANT";
+
+ case ::perfetto::protos::pbzero::TrackEvent_Type::TYPE_COUNTER:
+ return "TYPE_COUNTER";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
+enum FlowDirection : int32_t {
+ FLOW_UNSPECIFIED = 0,
+ FLOW_IN = 1,
+ FLOW_OUT = 2,
+ FLOW_INOUT = 3,
+};
+} // namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
+using TrackEvent_LegacyEvent_FlowDirection = perfetto_pbzero_enum_TrackEvent_LegacyEvent::FlowDirection;
+
+
+constexpr TrackEvent_LegacyEvent_FlowDirection TrackEvent_LegacyEvent_FlowDirection_MIN = TrackEvent_LegacyEvent_FlowDirection::FLOW_UNSPECIFIED;
+constexpr TrackEvent_LegacyEvent_FlowDirection TrackEvent_LegacyEvent_FlowDirection_MAX = TrackEvent_LegacyEvent_FlowDirection::FLOW_INOUT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TrackEvent_LegacyEvent_FlowDirection_Name(::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_UNSPECIFIED:
+ return "FLOW_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_IN:
+ return "FLOW_IN";
+
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_OUT:
+ return "FLOW_OUT";
+
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection::FLOW_INOUT:
+ return "FLOW_INOUT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent {
+enum InstantEventScope : int32_t {
+ SCOPE_UNSPECIFIED = 0,
+ SCOPE_GLOBAL = 1,
+ SCOPE_PROCESS = 2,
+ SCOPE_THREAD = 3,
+};
+} // namespace perfetto_pbzero_enum_TrackEvent_LegacyEvent
+using TrackEvent_LegacyEvent_InstantEventScope = perfetto_pbzero_enum_TrackEvent_LegacyEvent::InstantEventScope;
+
+
+constexpr TrackEvent_LegacyEvent_InstantEventScope TrackEvent_LegacyEvent_InstantEventScope_MIN = TrackEvent_LegacyEvent_InstantEventScope::SCOPE_UNSPECIFIED;
+constexpr TrackEvent_LegacyEvent_InstantEventScope TrackEvent_LegacyEvent_InstantEventScope_MAX = TrackEvent_LegacyEvent_InstantEventScope::SCOPE_THREAD;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TrackEvent_LegacyEvent_InstantEventScope_Name(::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_UNSPECIFIED:
+ return "SCOPE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_GLOBAL:
+ return "SCOPE_GLOBAL";
+
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_PROCESS:
+ return "SCOPE_PROCESS";
+
+ case ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope::SCOPE_THREAD:
+ return "SCOPE_THREAD";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class EventName_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ EventName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EventName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EventName_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+};
+
+class EventName : public ::protozero::Message {
+ public:
+ using Decoder = EventName_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EventName"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ EventName>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ EventName>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class EventCategory_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ EventCategory_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EventCategory_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EventCategory_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+};
+
+class EventCategory : public ::protozero::Message {
+ public:
+ using Decoder = EventCategory_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EventCategory"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ EventCategory>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ EventCategory>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrackEventDefaults_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/45, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TrackEventDefaults_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackEventDefaults_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackEventDefaults_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_track_uuid() const { return at<11>().valid(); }
+ uint64_t track_uuid() const { return at<11>().as_uint64(); }
+ bool has_extra_counter_track_uuids() const { return at<31>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> extra_counter_track_uuids() const { return GetRepeated<uint64_t>(31); }
+ bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> extra_double_counter_track_uuids() const { return GetRepeated<uint64_t>(45); }
+};
+
+class TrackEventDefaults : public ::protozero::Message {
+ public:
+ using Decoder = TrackEventDefaults_Decoder;
+ enum : int32_t {
+ kTrackUuidFieldNumber = 11,
+ kExtraCounterTrackUuidsFieldNumber = 31,
+ kExtraDoubleCounterTrackUuidsFieldNumber = 45,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackEventDefaults"; }
+
+
+ using FieldMetadata_TrackUuid =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEventDefaults>;
+
+ static constexpr FieldMetadata_TrackUuid kTrackUuid{};
+ void set_track_uuid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrackUuid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraCounterTrackUuids =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEventDefaults>;
+
+ static constexpr FieldMetadata_ExtraCounterTrackUuids kExtraCounterTrackUuids{};
+ void add_extra_counter_track_uuids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExtraCounterTrackUuids::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraDoubleCounterTrackUuids =
+ ::protozero::proto_utils::FieldMetadata<
+ 45,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEventDefaults>;
+
+ static constexpr FieldMetadata_ExtraDoubleCounterTrackUuids kExtraDoubleCounterTrackUuids{};
+ void add_extra_double_counter_track_uuids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterTrackUuids::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrackEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/51, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TrackEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_category_iids() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> category_iids() const { return GetRepeated<uint64_t>(3); }
+ bool has_categories() const { return at<22>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> categories() const { return GetRepeated<::protozero::ConstChars>(22); }
+ bool has_name_iid() const { return at<10>().valid(); }
+ uint64_t name_iid() const { return at<10>().as_uint64(); }
+ bool has_name() const { return at<23>().valid(); }
+ ::protozero::ConstChars name() const { return at<23>().as_string(); }
+ bool has_type() const { return at<9>().valid(); }
+ int32_t type() const { return at<9>().as_int32(); }
+ bool has_track_uuid() const { return at<11>().valid(); }
+ uint64_t track_uuid() const { return at<11>().as_uint64(); }
+ bool has_counter_value() const { return at<30>().valid(); }
+ int64_t counter_value() const { return at<30>().as_int64(); }
+ bool has_double_counter_value() const { return at<44>().valid(); }
+ double double_counter_value() const { return at<44>().as_double(); }
+ bool has_extra_counter_track_uuids() const { return at<31>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> extra_counter_track_uuids() const { return GetRepeated<uint64_t>(31); }
+ bool has_extra_counter_values() const { return at<12>().valid(); }
+ ::protozero::RepeatedFieldIterator<int64_t> extra_counter_values() const { return GetRepeated<int64_t>(12); }
+ bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> extra_double_counter_track_uuids() const { return GetRepeated<uint64_t>(45); }
+ bool has_extra_double_counter_values() const { return at<46>().valid(); }
+ ::protozero::RepeatedFieldIterator<double> extra_double_counter_values() const { return GetRepeated<double>(46); }
+ bool has_flow_ids_old() const { return at<36>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> flow_ids_old() const { return GetRepeated<uint64_t>(36); }
+ bool has_flow_ids() const { return at<47>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> flow_ids() const { return GetRepeated<uint64_t>(47); }
+ bool has_terminating_flow_ids_old() const { return at<42>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> terminating_flow_ids_old() const { return GetRepeated<uint64_t>(42); }
+ bool has_terminating_flow_ids() const { return at<48>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> terminating_flow_ids() const { return GetRepeated<uint64_t>(48); }
+ bool has_debug_annotations() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotations() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_task_execution() const { return at<5>().valid(); }
+ ::protozero::ConstBytes task_execution() const { return at<5>().as_bytes(); }
+ bool has_log_message() const { return at<21>().valid(); }
+ ::protozero::ConstBytes log_message() const { return at<21>().as_bytes(); }
+ bool has_cc_scheduler_state() const { return at<24>().valid(); }
+ ::protozero::ConstBytes cc_scheduler_state() const { return at<24>().as_bytes(); }
+ bool has_chrome_user_event() const { return at<25>().valid(); }
+ ::protozero::ConstBytes chrome_user_event() const { return at<25>().as_bytes(); }
+ bool has_chrome_keyed_service() const { return at<26>().valid(); }
+ ::protozero::ConstBytes chrome_keyed_service() const { return at<26>().as_bytes(); }
+ bool has_chrome_legacy_ipc() const { return at<27>().valid(); }
+ ::protozero::ConstBytes chrome_legacy_ipc() const { return at<27>().as_bytes(); }
+ bool has_chrome_histogram_sample() const { return at<28>().valid(); }
+ ::protozero::ConstBytes chrome_histogram_sample() const { return at<28>().as_bytes(); }
+ bool has_chrome_latency_info() const { return at<29>().valid(); }
+ ::protozero::ConstBytes chrome_latency_info() const { return at<29>().as_bytes(); }
+ bool has_chrome_frame_reporter() const { return at<32>().valid(); }
+ ::protozero::ConstBytes chrome_frame_reporter() const { return at<32>().as_bytes(); }
+ bool has_chrome_application_state_info() const { return at<39>().valid(); }
+ ::protozero::ConstBytes chrome_application_state_info() const { return at<39>().as_bytes(); }
+ bool has_chrome_renderer_scheduler_state() const { return at<40>().valid(); }
+ ::protozero::ConstBytes chrome_renderer_scheduler_state() const { return at<40>().as_bytes(); }
+ bool has_chrome_window_handle_event_info() const { return at<41>().valid(); }
+ ::protozero::ConstBytes chrome_window_handle_event_info() const { return at<41>().as_bytes(); }
+ bool has_chrome_content_settings_event_info() const { return at<43>().valid(); }
+ ::protozero::ConstBytes chrome_content_settings_event_info() const { return at<43>().as_bytes(); }
+ bool has_chrome_active_processes() const { return at<49>().valid(); }
+ ::protozero::ConstBytes chrome_active_processes() const { return at<49>().as_bytes(); }
+ bool has_screenshot() const { return at<50>().valid(); }
+ ::protozero::ConstBytes screenshot() const { return at<50>().as_bytes(); }
+ bool has_pixel_modem_event_insight() const { return at<51>().valid(); }
+ ::protozero::ConstBytes pixel_modem_event_insight() const { return at<51>().as_bytes(); }
+ bool has_source_location() const { return at<33>().valid(); }
+ ::protozero::ConstBytes source_location() const { return at<33>().as_bytes(); }
+ bool has_source_location_iid() const { return at<34>().valid(); }
+ uint64_t source_location_iid() const { return at<34>().as_uint64(); }
+ bool has_chrome_message_pump() const { return at<35>().valid(); }
+ ::protozero::ConstBytes chrome_message_pump() const { return at<35>().as_bytes(); }
+ bool has_chrome_mojo_event_info() const { return at<38>().valid(); }
+ ::protozero::ConstBytes chrome_mojo_event_info() const { return at<38>().as_bytes(); }
+ bool has_timestamp_delta_us() const { return at<1>().valid(); }
+ int64_t timestamp_delta_us() const { return at<1>().as_int64(); }
+ bool has_timestamp_absolute_us() const { return at<16>().valid(); }
+ int64_t timestamp_absolute_us() const { return at<16>().as_int64(); }
+ bool has_thread_time_delta_us() const { return at<2>().valid(); }
+ int64_t thread_time_delta_us() const { return at<2>().as_int64(); }
+ bool has_thread_time_absolute_us() const { return at<17>().valid(); }
+ int64_t thread_time_absolute_us() const { return at<17>().as_int64(); }
+ bool has_thread_instruction_count_delta() const { return at<8>().valid(); }
+ int64_t thread_instruction_count_delta() const { return at<8>().as_int64(); }
+ bool has_thread_instruction_count_absolute() const { return at<20>().valid(); }
+ int64_t thread_instruction_count_absolute() const { return at<20>().as_int64(); }
+ bool has_legacy_event() const { return at<6>().valid(); }
+ ::protozero::ConstBytes legacy_event() const { return at<6>().as_bytes(); }
+};
+
+class TrackEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrackEvent_Decoder;
+ enum : int32_t {
+ kCategoryIidsFieldNumber = 3,
+ kCategoriesFieldNumber = 22,
+ kNameIidFieldNumber = 10,
+ kNameFieldNumber = 23,
+ kTypeFieldNumber = 9,
+ kTrackUuidFieldNumber = 11,
+ kCounterValueFieldNumber = 30,
+ kDoubleCounterValueFieldNumber = 44,
+ kExtraCounterTrackUuidsFieldNumber = 31,
+ kExtraCounterValuesFieldNumber = 12,
+ kExtraDoubleCounterTrackUuidsFieldNumber = 45,
+ kExtraDoubleCounterValuesFieldNumber = 46,
+ kFlowIdsOldFieldNumber = 36,
+ kFlowIdsFieldNumber = 47,
+ kTerminatingFlowIdsOldFieldNumber = 42,
+ kTerminatingFlowIdsFieldNumber = 48,
+ kDebugAnnotationsFieldNumber = 4,
+ kTaskExecutionFieldNumber = 5,
+ kLogMessageFieldNumber = 21,
+ kCcSchedulerStateFieldNumber = 24,
+ kChromeUserEventFieldNumber = 25,
+ kChromeKeyedServiceFieldNumber = 26,
+ kChromeLegacyIpcFieldNumber = 27,
+ kChromeHistogramSampleFieldNumber = 28,
+ kChromeLatencyInfoFieldNumber = 29,
+ kChromeFrameReporterFieldNumber = 32,
+ kChromeApplicationStateInfoFieldNumber = 39,
+ kChromeRendererSchedulerStateFieldNumber = 40,
+ kChromeWindowHandleEventInfoFieldNumber = 41,
+ kChromeContentSettingsEventInfoFieldNumber = 43,
+ kChromeActiveProcessesFieldNumber = 49,
+ kScreenshotFieldNumber = 50,
+ kPixelModemEventInsightFieldNumber = 51,
+ kSourceLocationFieldNumber = 33,
+ kSourceLocationIidFieldNumber = 34,
+ kChromeMessagePumpFieldNumber = 35,
+ kChromeMojoEventInfoFieldNumber = 38,
+ kTimestampDeltaUsFieldNumber = 1,
+ kTimestampAbsoluteUsFieldNumber = 16,
+ kThreadTimeDeltaUsFieldNumber = 2,
+ kThreadTimeAbsoluteUsFieldNumber = 17,
+ kThreadInstructionCountDeltaFieldNumber = 8,
+ kThreadInstructionCountAbsoluteFieldNumber = 20,
+ kLegacyEventFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackEvent"; }
+
+ using LegacyEvent = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent;
+
+ using Type = ::perfetto::protos::pbzero::TrackEvent_Type;
+ static inline const char* Type_Name(Type value) {
+ return ::perfetto::protos::pbzero::TrackEvent_Type_Name(value);
+ }
+ static inline const Type TYPE_UNSPECIFIED = Type::TYPE_UNSPECIFIED;
+ static inline const Type TYPE_SLICE_BEGIN = Type::TYPE_SLICE_BEGIN;
+ static inline const Type TYPE_SLICE_END = Type::TYPE_SLICE_END;
+ static inline const Type TYPE_INSTANT = Type::TYPE_INSTANT;
+ static inline const Type TYPE_COUNTER = Type::TYPE_COUNTER;
+
+ using FieldMetadata_CategoryIids =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_CategoryIids kCategoryIids{};
+ void add_category_iids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CategoryIids::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Categories =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_Categories kCategories{};
+ void add_categories(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Categories::kFieldId, data, size);
+ }
+ void add_categories(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Categories::kFieldId, chars.data, chars.size);
+ }
+ void add_categories(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Categories::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_NameIid kNameIid{};
+ void set_name_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TrackEvent_Type,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(TrackEvent_Type value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TrackUuid =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_TrackUuid kTrackUuid{};
+ void set_track_uuid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrackUuid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CounterValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 30,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_CounterValue kCounterValue{};
+ void set_counter_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleCounterValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 44,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_DoubleCounterValue kDoubleCounterValue{};
+ void set_double_counter_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleCounterValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraCounterTrackUuids =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ExtraCounterTrackUuids kExtraCounterTrackUuids{};
+ void add_extra_counter_track_uuids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExtraCounterTrackUuids::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraCounterValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ExtraCounterValues kExtraCounterValues{};
+ void add_extra_counter_values(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExtraCounterValues::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraDoubleCounterTrackUuids =
+ ::protozero::proto_utils::FieldMetadata<
+ 45,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ExtraDoubleCounterTrackUuids kExtraDoubleCounterTrackUuids{};
+ void add_extra_double_counter_track_uuids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterTrackUuids::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraDoubleCounterValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 46,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ExtraDoubleCounterValues kExtraDoubleCounterValues{};
+ void add_extra_double_counter_values(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterValues::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlowIdsOld =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_FlowIdsOld kFlowIdsOld{};
+ void add_flow_ids_old(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlowIdsOld::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlowIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 47,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_FlowIds kFlowIds{};
+ void add_flow_ids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlowIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TerminatingFlowIdsOld =
+ ::protozero::proto_utils::FieldMetadata<
+ 42,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_TerminatingFlowIdsOld kTerminatingFlowIdsOld{};
+ void add_terminating_flow_ids_old(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TerminatingFlowIdsOld::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TerminatingFlowIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 48,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_TerminatingFlowIds kTerminatingFlowIds{};
+ void add_terminating_flow_ids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TerminatingFlowIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DebugAnnotations =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_DebugAnnotations kDebugAnnotations{};
+ template <typename T = DebugAnnotation> T* add_debug_annotations() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_TaskExecution =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TaskExecution,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_TaskExecution kTaskExecution{};
+ template <typename T = TaskExecution> T* set_task_execution() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_LogMessage =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LogMessage,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_LogMessage kLogMessage{};
+ template <typename T = LogMessage> T* set_log_message() {
+ return BeginNestedMessage<T>(21);
+ }
+
+
+ using FieldMetadata_CcSchedulerState =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeCompositorSchedulerState,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_CcSchedulerState kCcSchedulerState{};
+ template <typename T = ChromeCompositorSchedulerState> T* set_cc_scheduler_state() {
+ return BeginNestedMessage<T>(24);
+ }
+
+
+ using FieldMetadata_ChromeUserEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeUserEvent,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeUserEvent kChromeUserEvent{};
+ template <typename T = ChromeUserEvent> T* set_chrome_user_event() {
+ return BeginNestedMessage<T>(25);
+ }
+
+
+ using FieldMetadata_ChromeKeyedService =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeKeyedService,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeKeyedService kChromeKeyedService{};
+ template <typename T = ChromeKeyedService> T* set_chrome_keyed_service() {
+ return BeginNestedMessage<T>(26);
+ }
+
+
+ using FieldMetadata_ChromeLegacyIpc =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeLegacyIpc,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeLegacyIpc kChromeLegacyIpc{};
+ template <typename T = ChromeLegacyIpc> T* set_chrome_legacy_ipc() {
+ return BeginNestedMessage<T>(27);
+ }
+
+
+ using FieldMetadata_ChromeHistogramSample =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeHistogramSample,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeHistogramSample kChromeHistogramSample{};
+ template <typename T = ChromeHistogramSample> T* set_chrome_histogram_sample() {
+ return BeginNestedMessage<T>(28);
+ }
+
+
+ using FieldMetadata_ChromeLatencyInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 29,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeLatencyInfo,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeLatencyInfo kChromeLatencyInfo{};
+ template <typename T = ChromeLatencyInfo> T* set_chrome_latency_info() {
+ return BeginNestedMessage<T>(29);
+ }
+
+
+ using FieldMetadata_ChromeFrameReporter =
+ ::protozero::proto_utils::FieldMetadata<
+ 32,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeFrameReporter,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeFrameReporter kChromeFrameReporter{};
+ template <typename T = ChromeFrameReporter> T* set_chrome_frame_reporter() {
+ return BeginNestedMessage<T>(32);
+ }
+
+
+ using FieldMetadata_ChromeApplicationStateInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 39,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeApplicationStateInfo,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeApplicationStateInfo kChromeApplicationStateInfo{};
+ template <typename T = ChromeApplicationStateInfo> T* set_chrome_application_state_info() {
+ return BeginNestedMessage<T>(39);
+ }
+
+
+ using FieldMetadata_ChromeRendererSchedulerState =
+ ::protozero::proto_utils::FieldMetadata<
+ 40,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeRendererSchedulerState,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeRendererSchedulerState kChromeRendererSchedulerState{};
+ template <typename T = ChromeRendererSchedulerState> T* set_chrome_renderer_scheduler_state() {
+ return BeginNestedMessage<T>(40);
+ }
+
+
+ using FieldMetadata_ChromeWindowHandleEventInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 41,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeWindowHandleEventInfo,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeWindowHandleEventInfo kChromeWindowHandleEventInfo{};
+ template <typename T = ChromeWindowHandleEventInfo> T* set_chrome_window_handle_event_info() {
+ return BeginNestedMessage<T>(41);
+ }
+
+
+ using FieldMetadata_ChromeContentSettingsEventInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 43,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeContentSettingsEventInfo,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeContentSettingsEventInfo kChromeContentSettingsEventInfo{};
+ template <typename T = ChromeContentSettingsEventInfo> T* set_chrome_content_settings_event_info() {
+ return BeginNestedMessage<T>(43);
+ }
+
+
+ using FieldMetadata_ChromeActiveProcesses =
+ ::protozero::proto_utils::FieldMetadata<
+ 49,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeActiveProcesses,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeActiveProcesses kChromeActiveProcesses{};
+ template <typename T = ChromeActiveProcesses> T* set_chrome_active_processes() {
+ return BeginNestedMessage<T>(49);
+ }
+
+
+ using FieldMetadata_Screenshot =
+ ::protozero::proto_utils::FieldMetadata<
+ 50,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Screenshot,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_Screenshot kScreenshot{};
+ template <typename T = Screenshot> T* set_screenshot() {
+ return BeginNestedMessage<T>(50);
+ }
+
+
+ using FieldMetadata_PixelModemEventInsight =
+ ::protozero::proto_utils::FieldMetadata<
+ 51,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PixelModemEventInsight,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_PixelModemEventInsight kPixelModemEventInsight{};
+ template <typename T = PixelModemEventInsight> T* set_pixel_modem_event_insight() {
+ return BeginNestedMessage<T>(51);
+ }
+
+
+ using FieldMetadata_SourceLocation =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SourceLocation,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_SourceLocation kSourceLocation{};
+ template <typename T = SourceLocation> T* set_source_location() {
+ return BeginNestedMessage<T>(33);
+ }
+
+
+ using FieldMetadata_SourceLocationIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_SourceLocationIid kSourceLocationIid{};
+ void set_source_location_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceLocationIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChromeMessagePump =
+ ::protozero::proto_utils::FieldMetadata<
+ 35,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeMessagePump,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeMessagePump kChromeMessagePump{};
+ template <typename T = ChromeMessagePump> T* set_chrome_message_pump() {
+ return BeginNestedMessage<T>(35);
+ }
+
+
+ using FieldMetadata_ChromeMojoEventInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 38,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeMojoEventInfo,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ChromeMojoEventInfo kChromeMojoEventInfo{};
+ template <typename T = ChromeMojoEventInfo> T* set_chrome_mojo_event_info() {
+ return BeginNestedMessage<T>(38);
+ }
+
+
+ using FieldMetadata_TimestampDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_TimestampDeltaUs kTimestampDeltaUs{};
+ void set_timestamp_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimestampAbsoluteUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_TimestampAbsoluteUs kTimestampAbsoluteUs{};
+ void set_timestamp_absolute_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampAbsoluteUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadTimeDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ThreadTimeDeltaUs kThreadTimeDeltaUs{};
+ void set_thread_time_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadTimeDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadTimeAbsoluteUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ThreadTimeAbsoluteUs kThreadTimeAbsoluteUs{};
+ void set_thread_time_absolute_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadTimeAbsoluteUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadInstructionCountDelta =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ThreadInstructionCountDelta kThreadInstructionCountDelta{};
+ void set_thread_instruction_count_delta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionCountDelta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadInstructionCountAbsolute =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_ThreadInstructionCountAbsolute kThreadInstructionCountAbsolute{};
+ void set_thread_instruction_count_absolute(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionCountAbsolute::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LegacyEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackEvent_LegacyEvent,
+ TrackEvent>;
+
+ static constexpr FieldMetadata_LegacyEvent kLegacyEvent{};
+ template <typename T = TrackEvent_LegacyEvent> T* set_legacy_event() {
+ return BeginNestedMessage<T>(6);
+ }
+
+};
+
+class TrackEvent_LegacyEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/19, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrackEvent_LegacyEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackEvent_LegacyEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackEvent_LegacyEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name_iid() const { return at<1>().valid(); }
+ uint64_t name_iid() const { return at<1>().as_uint64(); }
+ bool has_phase() const { return at<2>().valid(); }
+ int32_t phase() const { return at<2>().as_int32(); }
+ bool has_duration_us() const { return at<3>().valid(); }
+ int64_t duration_us() const { return at<3>().as_int64(); }
+ bool has_thread_duration_us() const { return at<4>().valid(); }
+ int64_t thread_duration_us() const { return at<4>().as_int64(); }
+ bool has_thread_instruction_delta() const { return at<15>().valid(); }
+ int64_t thread_instruction_delta() const { return at<15>().as_int64(); }
+ bool has_unscoped_id() const { return at<6>().valid(); }
+ uint64_t unscoped_id() const { return at<6>().as_uint64(); }
+ bool has_local_id() const { return at<10>().valid(); }
+ uint64_t local_id() const { return at<10>().as_uint64(); }
+ bool has_global_id() const { return at<11>().valid(); }
+ uint64_t global_id() const { return at<11>().as_uint64(); }
+ bool has_id_scope() const { return at<7>().valid(); }
+ ::protozero::ConstChars id_scope() const { return at<7>().as_string(); }
+ bool has_use_async_tts() const { return at<9>().valid(); }
+ bool use_async_tts() const { return at<9>().as_bool(); }
+ bool has_bind_id() const { return at<8>().valid(); }
+ uint64_t bind_id() const { return at<8>().as_uint64(); }
+ bool has_bind_to_enclosing() const { return at<12>().valid(); }
+ bool bind_to_enclosing() const { return at<12>().as_bool(); }
+ bool has_flow_direction() const { return at<13>().valid(); }
+ int32_t flow_direction() const { return at<13>().as_int32(); }
+ bool has_instant_event_scope() const { return at<14>().valid(); }
+ int32_t instant_event_scope() const { return at<14>().as_int32(); }
+ bool has_pid_override() const { return at<18>().valid(); }
+ int32_t pid_override() const { return at<18>().as_int32(); }
+ bool has_tid_override() const { return at<19>().valid(); }
+ int32_t tid_override() const { return at<19>().as_int32(); }
+};
+
+class TrackEvent_LegacyEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrackEvent_LegacyEvent_Decoder;
+ enum : int32_t {
+ kNameIidFieldNumber = 1,
+ kPhaseFieldNumber = 2,
+ kDurationUsFieldNumber = 3,
+ kThreadDurationUsFieldNumber = 4,
+ kThreadInstructionDeltaFieldNumber = 15,
+ kUnscopedIdFieldNumber = 6,
+ kLocalIdFieldNumber = 10,
+ kGlobalIdFieldNumber = 11,
+ kIdScopeFieldNumber = 7,
+ kUseAsyncTtsFieldNumber = 9,
+ kBindIdFieldNumber = 8,
+ kBindToEnclosingFieldNumber = 12,
+ kFlowDirectionFieldNumber = 13,
+ kInstantEventScopeFieldNumber = 14,
+ kPidOverrideFieldNumber = 18,
+ kTidOverrideFieldNumber = 19,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackEvent.LegacyEvent"; }
+
+
+ using FlowDirection = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection;
+ static inline const char* FlowDirection_Name(FlowDirection value) {
+ return ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection_Name(value);
+ }
+
+ using InstantEventScope = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope;
+ static inline const char* InstantEventScope_Name(InstantEventScope value) {
+ return ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope_Name(value);
+ }
+ static inline const FlowDirection FLOW_UNSPECIFIED = FlowDirection::FLOW_UNSPECIFIED;
+ static inline const FlowDirection FLOW_IN = FlowDirection::FLOW_IN;
+ static inline const FlowDirection FLOW_OUT = FlowDirection::FLOW_OUT;
+ static inline const FlowDirection FLOW_INOUT = FlowDirection::FLOW_INOUT;
+ static inline const InstantEventScope SCOPE_UNSPECIFIED = InstantEventScope::SCOPE_UNSPECIFIED;
+ static inline const InstantEventScope SCOPE_GLOBAL = InstantEventScope::SCOPE_GLOBAL;
+ static inline const InstantEventScope SCOPE_PROCESS = InstantEventScope::SCOPE_PROCESS;
+ static inline const InstantEventScope SCOPE_THREAD = InstantEventScope::SCOPE_THREAD;
+
+ using FieldMetadata_NameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_NameIid kNameIid{};
+ void set_name_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Phase =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_Phase kPhase{};
+ void set_phase(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Phase::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DurationUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_DurationUs kDurationUs{};
+ void set_duration_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DurationUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadDurationUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_ThreadDurationUs kThreadDurationUs{};
+ void set_thread_duration_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadDurationUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadInstructionDelta =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_ThreadInstructionDelta kThreadInstructionDelta{};
+ void set_thread_instruction_delta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionDelta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnscopedId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_UnscopedId kUnscopedId{};
+ void set_unscoped_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnscopedId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LocalId =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_LocalId kLocalId{};
+ void set_local_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LocalId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GlobalId =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_GlobalId kGlobalId{};
+ void set_global_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GlobalId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IdScope =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_IdScope kIdScope{};
+ void set_id_scope(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_IdScope::kFieldId, data, size);
+ }
+ void set_id_scope(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_IdScope::kFieldId, chars.data, chars.size);
+ }
+ void set_id_scope(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_IdScope::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UseAsyncTts =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_UseAsyncTts kUseAsyncTts{};
+ void set_use_async_tts(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_UseAsyncTts::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BindId =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_BindId kBindId{};
+ void set_bind_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BindId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BindToEnclosing =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_BindToEnclosing kBindToEnclosing{};
+ void set_bind_to_enclosing(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BindToEnclosing::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlowDirection =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TrackEvent_LegacyEvent_FlowDirection,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_FlowDirection kFlowDirection{};
+ void set_flow_direction(TrackEvent_LegacyEvent_FlowDirection value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlowDirection::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstantEventScope =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TrackEvent_LegacyEvent_InstantEventScope,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_InstantEventScope kInstantEventScope{};
+ void set_instant_event_scope(TrackEvent_LegacyEvent_InstantEventScope value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstantEventScope::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PidOverride =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_PidOverride kPidOverride{};
+ void set_pid_override(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PidOverride::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TidOverride =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrackEvent_LegacyEvent>;
+
+ static constexpr FieldMetadata_TidOverride kTidOverride{};
+ void set_tid_override(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TidOverride::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class TracePacket_Decoder;
+class TrackEvent;
+class TrackEvent_Decoder;
+} // namespace pbzero
+} // namespace protos
+
+// A helper for keeping track of incremental state when intercepting track
+// events.
+class PERFETTO_EXPORT_COMPONENT TrackEventStateTracker {
+ public:
+ ~TrackEventStateTracker();
+
+ struct StackFrame {
+ uint64_t timestamp{};
+
+ // Only one of |name| and |name_iid| will be set.
+ std::string name;
+ uint64_t name_iid{};
+ uint64_t name_hash{};
+
+ // Only one of |category| and |category_iid| will be set.
+ std::string category;
+ uint64_t category_iid{};
+ };
+
+ struct Track {
+ uint64_t uuid{};
+ uint32_t index{}; // Ordinal number for the track in the tracing session.
+
+ std::string name;
+ int64_t pid{};
+ int64_t tid{};
+
+ // Opaque user data associated with the track.
+ std::vector<uint8_t> user_data;
+
+ // Stack of opened slices on this track.
+ std::vector<StackFrame> stack;
+ };
+
+ // State for a single trace writer sequence (typically a single thread).
+ struct SequenceState {
+ // Trace packet sequence defaults.
+ Track track;
+
+ // Interned state.
+#if PERFETTO_DCHECK_IS_ON()
+ uint32_t sequence_id{};
+#endif
+ std::map<uint64_t /*iid*/, std::string> event_names;
+ std::map<uint64_t /*iid*/, std::string> event_categories;
+ std::map<uint64_t /*iid*/, std::string> debug_annotation_names;
+ // Current absolute timestamp of the incremental clock.
+ uint64_t most_recent_absolute_time_ns = 0;
+ // default_clock_id == 0 means, no default clock_id is set.
+ uint32_t default_clock_id = 0;
+ };
+
+ // State for the entire tracing session. Shared by all trace writer sequences
+ // participating in the session.
+ struct SessionState {
+ // Non-thread-bound tracks.
+ std::map<uint64_t /*uuid*/, Track> tracks;
+ };
+
+ // Represents a single decoded track event (without arguments).
+ struct ParsedTrackEvent {
+ explicit ParsedTrackEvent(
+ const perfetto::protos::pbzero::TrackEvent::Decoder&);
+
+ // Underlying event.
+ const perfetto::protos::pbzero::TrackEvent::Decoder& track_event;
+
+ // Event metadata.
+ uint64_t timestamp_ns{};
+ uint64_t duration_ns{};
+
+ size_t stack_depth{};
+
+ protozero::ConstChars category{};
+ protozero::ConstChars name{};
+ uint64_t name_hash{};
+ };
+
+ // Interface used by the tracker to access tracing session and sequence state
+ // and to report parsed track events.
+ class PERFETTO_EXPORT_COMPONENT Delegate {
+ public:
+ virtual ~Delegate();
+
+ // Called to retrieve the session-global state shared by all sequences. The
+ // returned pointer must remain valid (locked) throughout the call to
+ // |ProcessTracePacket|.
+ virtual SessionState* GetSessionState() = 0;
+
+ // Called when the metadata (e.g., name) for a track changes. |Track| can be
+ // modified by the callback to attach user data.
+ virtual void OnTrackUpdated(Track&) = 0;
+
+ // If the packet given to |ProcessTracePacket| contains a track event, this
+ // method is called to report the properties of that event. Note that memory
+ // pointers in |TrackEvent| will only be valid during this call.
+ virtual void OnTrackEvent(const Track&, const ParsedTrackEvent&) = 0;
+ };
+
+ // Process a single trace packet, reporting any contained track event back via
+ // the delegate interface. |SequenceState| must correspond to the sequence
+ // that was used to write the packet.
+ static void ProcessTracePacket(Delegate&,
+ SequenceState&,
+ const protos::pbzero::TracePacket_Decoder&);
+
+ private:
+ static void UpdateIncrementalState(
+ Delegate&,
+ SequenceState&,
+ const protos::pbzero::TracePacket_Decoder&);
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
+#define INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_state_tracker.h"
+
+#include <stdarg.h>
+
+#include <functional>
+#include <map>
+#include <vector>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_PRINTF_ATTR \
+ __attribute__((format(printf, /*format_index=*/2, /*first_to_check=*/3)))
+#else
+#define PERFETTO_PRINTF_ATTR
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && !defined(STDOUT_FILENO)
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+#endif
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DebugAnnotation_Decoder;
+class TracePacket_Decoder;
+class TrackEvent_Decoder;
+} // namespace pbzero
+} // namespace protos
+
+struct ConsoleColor;
+
+class PERFETTO_EXPORT_COMPONENT ConsoleInterceptor
+ : public Interceptor<ConsoleInterceptor> {
+ public:
+ ~ConsoleInterceptor() override;
+
+ static void Register();
+ static void OnTracePacket(InterceptorContext context);
+
+ static void SetOutputFdForTesting(int fd);
+
+ void OnSetup(const SetupArgs&) override;
+ void OnStart(const StartArgs&) override;
+ void OnStop(const StopArgs&) override;
+
+ struct ThreadLocalState : public InterceptorBase::ThreadLocalState {
+ ThreadLocalState(ThreadLocalStateArgs&);
+ ~ThreadLocalState() override;
+
+ // Destination file. Assumed to stay valid until the program ends (i.e., is
+ // stderr or stdout).
+ int fd{};
+ bool use_colors{};
+
+ // Messages up to this length are buffered and written atomically. If a
+ // message is longer, it will be printed with multiple writes.
+ std::array<char, 1024> message_buffer{};
+ size_t buffer_pos{};
+
+ // We only support a single trace writer sequence per thread, so the
+ // sequence state is stored in TLS.
+ TrackEventStateTracker::SequenceState sequence_state;
+ uint64_t start_time_ns{};
+ };
+
+ private:
+ class Delegate;
+
+ // Appends a formatted message to |message_buffer_| or directly to the output
+ // file if the buffer is full.
+ static void Printf(InterceptorContext& context,
+ const char* format,
+ ...) PERFETTO_PRINTF_ATTR;
+ static void Flush(InterceptorContext& context);
+ static void SetColor(InterceptorContext& context, const ConsoleColor&);
+ static void SetColor(InterceptorContext& context, const char*);
+
+ static void PrintDebugAnnotations(InterceptorContext&,
+ const protos::pbzero::TrackEvent_Decoder&,
+ const ConsoleColor& slice_color,
+ const ConsoleColor& highlight_color);
+ static void PrintDebugAnnotationName(
+ InterceptorContext&,
+ const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation);
+ static void PrintDebugAnnotationValue(
+ InterceptorContext&,
+ const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation);
+
+ int fd_ = STDOUT_FILENO;
+ bool use_colors_ = true;
+
+ TrackEventStateTracker::SessionState session_state_;
+ uint64_t start_time_ns_{};
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
+// gen_amalgamated begin header: include/perfetto/tracing/core/data_source_descriptor.h
+// gen_amalgamated begin header: gen/protos/perfetto/common/data_source_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class DataSourceDescriptor;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT DataSourceDescriptor : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kIdFieldNumber = 7,
+ kWillNotifyOnStopFieldNumber = 2,
+ kWillNotifyOnStartFieldNumber = 3,
+ kHandlesIncrementalStateClearFieldNumber = 4,
+ kNoFlushFieldNumber = 9,
+ kGpuCounterDescriptorFieldNumber = 5,
+ kTrackEventDescriptorFieldNumber = 6,
+ kFtraceDescriptorFieldNumber = 8,
+ };
+
+ DataSourceDescriptor();
+ ~DataSourceDescriptor() override;
+ DataSourceDescriptor(DataSourceDescriptor&&) noexcept;
+ DataSourceDescriptor& operator=(DataSourceDescriptor&&);
+ DataSourceDescriptor(const DataSourceDescriptor&);
+ DataSourceDescriptor& operator=(const DataSourceDescriptor&);
+ bool operator==(const DataSourceDescriptor&) const;
+ bool operator!=(const DataSourceDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_id() const { return _has_field_[7]; }
+ uint64_t id() const { return id_; }
+ void set_id(uint64_t value) { id_ = value; _has_field_.set(7); }
+
+ bool has_will_notify_on_stop() const { return _has_field_[2]; }
+ bool will_notify_on_stop() const { return will_notify_on_stop_; }
+ void set_will_notify_on_stop(bool value) { will_notify_on_stop_ = value; _has_field_.set(2); }
+
+ bool has_will_notify_on_start() const { return _has_field_[3]; }
+ bool will_notify_on_start() const { return will_notify_on_start_; }
+ void set_will_notify_on_start(bool value) { will_notify_on_start_ = value; _has_field_.set(3); }
+
+ bool has_handles_incremental_state_clear() const { return _has_field_[4]; }
+ bool handles_incremental_state_clear() const { return handles_incremental_state_clear_; }
+ void set_handles_incremental_state_clear(bool value) { handles_incremental_state_clear_ = value; _has_field_.set(4); }
+
+ bool has_no_flush() const { return _has_field_[9]; }
+ bool no_flush() const { return no_flush_; }
+ void set_no_flush(bool value) { no_flush_ = value; _has_field_.set(9); }
+
+ const std::string& gpu_counter_descriptor_raw() const { return gpu_counter_descriptor_; }
+ void set_gpu_counter_descriptor_raw(const std::string& raw) { gpu_counter_descriptor_ = raw; _has_field_.set(5); }
+
+ const std::string& track_event_descriptor_raw() const { return track_event_descriptor_; }
+ void set_track_event_descriptor_raw(const std::string& raw) { track_event_descriptor_ = raw; _has_field_.set(6); }
+
+ const std::string& ftrace_descriptor_raw() const { return ftrace_descriptor_; }
+ void set_ftrace_descriptor_raw(const std::string& raw) { ftrace_descriptor_ = raw; _has_field_.set(8); }
+
+ private:
+ std::string name_{};
+ uint64_t id_{};
+ bool will_notify_on_stop_{};
+ bool will_notify_on_start_{};
+ bool handles_incremental_state_clear_{};
+ bool no_flush_{};
+ std::string gpu_counter_descriptor_; // [lazy=true]
+ std::string track_event_descriptor_; // [lazy=true]
+ std::string ftrace_descriptor_; // [lazy=true]
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<10> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h"
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
+// gen_amalgamated begin header: include/perfetto/tracing/core/trace_config.h
+// gen_amalgamated begin header: gen/protos/perfetto/config/trace_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TraceConfig;
+class TraceConfig_CmdTraceStartDelay;
+class TraceConfig_AndroidReportConfig;
+class TraceConfig_TraceFilter;
+class TraceConfig_TraceFilter_StringFilterChain;
+class TraceConfig_TraceFilter_StringFilterRule;
+class TraceConfig_IncidentReportConfig;
+class TraceConfig_IncrementalStateConfig;
+class TraceConfig_TriggerConfig;
+class TraceConfig_TriggerConfig_Trigger;
+class TraceConfig_GuardrailOverrides;
+class TraceConfig_StatsdMetadata;
+class TraceConfig_ProducerConfig;
+class TraceConfig_BuiltinDataSource;
+class TraceConfig_DataSource;
+class DataSourceConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+class InterceptorConfig;
+class ConsoleConfig;
+class ChromeConfig;
+class SystemInfoConfig;
+class TraceConfig_BufferConfig;
+enum TraceConfig_LockdownModeOperation : int;
+enum TraceConfig_CompressionType : int;
+enum TraceConfig_StatsdLogging : int;
+enum TraceConfig_TraceFilter_StringFilterPolicy : int;
+enum TraceConfig_TriggerConfig_TriggerMode : int;
+enum BuiltinClock : int;
+enum DataSourceConfig_SessionInitiator : int;
+enum ConsoleConfig_Output : int;
+enum ChromeConfig_ClientPriority : int;
+enum TraceConfig_BufferConfig_FillPolicy : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum TraceConfig_LockdownModeOperation : int {
+ TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED = 0,
+ TraceConfig_LockdownModeOperation_LOCKDOWN_CLEAR = 1,
+ TraceConfig_LockdownModeOperation_LOCKDOWN_SET = 2,
+};
+enum TraceConfig_CompressionType : int {
+ TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED = 0,
+ TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE = 1,
+};
+enum TraceConfig_StatsdLogging : int {
+ TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED = 0,
+ TraceConfig_StatsdLogging_STATSD_LOGGING_ENABLED = 1,
+ TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED = 2,
+};
+enum TraceConfig_TraceFilter_StringFilterPolicy : int {
+ TraceConfig_TraceFilter_StringFilterPolicy_SFP_UNSPECIFIED = 0,
+ TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_REDACT_GROUPS = 1,
+ TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_REDACT_GROUPS = 2,
+ TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_BREAK = 3,
+ TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_BREAK = 4,
+ TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS = 5,
+};
+enum TraceConfig_TriggerConfig_TriggerMode : int {
+ TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED = 0,
+ TraceConfig_TriggerConfig_TriggerMode_START_TRACING = 1,
+ TraceConfig_TriggerConfig_TriggerMode_STOP_TRACING = 2,
+ TraceConfig_TriggerConfig_TriggerMode_CLONE_SNAPSHOT = 4,
+};
+enum TraceConfig_BufferConfig_FillPolicy : int {
+ TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED = 0,
+ TraceConfig_BufferConfig_FillPolicy_RING_BUFFER = 1,
+ TraceConfig_BufferConfig_FillPolicy_DISCARD = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig : public ::protozero::CppMessageObj {
+ public:
+ using BufferConfig = TraceConfig_BufferConfig;
+ using DataSource = TraceConfig_DataSource;
+ using BuiltinDataSource = TraceConfig_BuiltinDataSource;
+ using ProducerConfig = TraceConfig_ProducerConfig;
+ using StatsdMetadata = TraceConfig_StatsdMetadata;
+ using GuardrailOverrides = TraceConfig_GuardrailOverrides;
+ using TriggerConfig = TraceConfig_TriggerConfig;
+ using IncrementalStateConfig = TraceConfig_IncrementalStateConfig;
+ using IncidentReportConfig = TraceConfig_IncidentReportConfig;
+ using TraceFilter = TraceConfig_TraceFilter;
+ using AndroidReportConfig = TraceConfig_AndroidReportConfig;
+ using CmdTraceStartDelay = TraceConfig_CmdTraceStartDelay;
+ using LockdownModeOperation = TraceConfig_LockdownModeOperation;
+ static constexpr auto LOCKDOWN_UNCHANGED = TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED;
+ static constexpr auto LOCKDOWN_CLEAR = TraceConfig_LockdownModeOperation_LOCKDOWN_CLEAR;
+ static constexpr auto LOCKDOWN_SET = TraceConfig_LockdownModeOperation_LOCKDOWN_SET;
+ static constexpr auto LockdownModeOperation_MIN = TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED;
+ static constexpr auto LockdownModeOperation_MAX = TraceConfig_LockdownModeOperation_LOCKDOWN_SET;
+ using CompressionType = TraceConfig_CompressionType;
+ static constexpr auto COMPRESSION_TYPE_UNSPECIFIED = TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED;
+ static constexpr auto COMPRESSION_TYPE_DEFLATE = TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE;
+ static constexpr auto CompressionType_MIN = TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED;
+ static constexpr auto CompressionType_MAX = TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE;
+ using StatsdLogging = TraceConfig_StatsdLogging;
+ static constexpr auto STATSD_LOGGING_UNSPECIFIED = TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED;
+ static constexpr auto STATSD_LOGGING_ENABLED = TraceConfig_StatsdLogging_STATSD_LOGGING_ENABLED;
+ static constexpr auto STATSD_LOGGING_DISABLED = TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED;
+ static constexpr auto StatsdLogging_MIN = TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED;
+ static constexpr auto StatsdLogging_MAX = TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED;
+ enum FieldNumbers {
+ kBuffersFieldNumber = 1,
+ kDataSourcesFieldNumber = 2,
+ kBuiltinDataSourcesFieldNumber = 20,
+ kDurationMsFieldNumber = 3,
+ kPreferSuspendClockForDurationFieldNumber = 36,
+ kEnableExtraGuardrailsFieldNumber = 4,
+ kLockdownModeFieldNumber = 5,
+ kProducersFieldNumber = 6,
+ kStatsdMetadataFieldNumber = 7,
+ kWriteIntoFileFieldNumber = 8,
+ kOutputPathFieldNumber = 29,
+ kFileWritePeriodMsFieldNumber = 9,
+ kMaxFileSizeBytesFieldNumber = 10,
+ kGuardrailOverridesFieldNumber = 11,
+ kDeferredStartFieldNumber = 12,
+ kFlushPeriodMsFieldNumber = 13,
+ kFlushTimeoutMsFieldNumber = 14,
+ kDataSourceStopTimeoutMsFieldNumber = 23,
+ kNotifyTraceurFieldNumber = 16,
+ kBugreportScoreFieldNumber = 30,
+ kBugreportFilenameFieldNumber = 38,
+ kTriggerConfigFieldNumber = 17,
+ kActivateTriggersFieldNumber = 18,
+ kIncrementalStateConfigFieldNumber = 21,
+ kAllowUserBuildTracingFieldNumber = 19,
+ kUniqueSessionNameFieldNumber = 22,
+ kCompressionTypeFieldNumber = 24,
+ kIncidentReportConfigFieldNumber = 25,
+ kStatsdLoggingFieldNumber = 31,
+ kTraceUuidMsbFieldNumber = 27,
+ kTraceUuidLsbFieldNumber = 28,
+ kTraceFilterFieldNumber = 33,
+ kAndroidReportConfigFieldNumber = 34,
+ kCmdTraceStartDelayFieldNumber = 35,
+ };
+
+ TraceConfig();
+ ~TraceConfig() override;
+ TraceConfig(TraceConfig&&) noexcept;
+ TraceConfig& operator=(TraceConfig&&);
+ TraceConfig(const TraceConfig&);
+ TraceConfig& operator=(const TraceConfig&);
+ bool operator==(const TraceConfig&) const;
+ bool operator!=(const TraceConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<TraceConfig_BufferConfig>& buffers() const { return buffers_; }
+ std::vector<TraceConfig_BufferConfig>* mutable_buffers() { return &buffers_; }
+ int buffers_size() const;
+ void clear_buffers();
+ TraceConfig_BufferConfig* add_buffers();
+
+ const std::vector<TraceConfig_DataSource>& data_sources() const { return data_sources_; }
+ std::vector<TraceConfig_DataSource>* mutable_data_sources() { return &data_sources_; }
+ int data_sources_size() const;
+ void clear_data_sources();
+ TraceConfig_DataSource* add_data_sources();
+
+ bool has_builtin_data_sources() const { return _has_field_[20]; }
+ const TraceConfig_BuiltinDataSource& builtin_data_sources() const { return *builtin_data_sources_; }
+ TraceConfig_BuiltinDataSource* mutable_builtin_data_sources() { _has_field_.set(20); return builtin_data_sources_.get(); }
+
+ bool has_duration_ms() const { return _has_field_[3]; }
+ uint32_t duration_ms() const { return duration_ms_; }
+ void set_duration_ms(uint32_t value) { duration_ms_ = value; _has_field_.set(3); }
+
+ bool has_prefer_suspend_clock_for_duration() const { return _has_field_[36]; }
+ bool prefer_suspend_clock_for_duration() const { return prefer_suspend_clock_for_duration_; }
+ void set_prefer_suspend_clock_for_duration(bool value) { prefer_suspend_clock_for_duration_ = value; _has_field_.set(36); }
+
+ bool has_enable_extra_guardrails() const { return _has_field_[4]; }
+ bool enable_extra_guardrails() const { return enable_extra_guardrails_; }
+ void set_enable_extra_guardrails(bool value) { enable_extra_guardrails_ = value; _has_field_.set(4); }
+
+ bool has_lockdown_mode() const { return _has_field_[5]; }
+ TraceConfig_LockdownModeOperation lockdown_mode() const { return lockdown_mode_; }
+ void set_lockdown_mode(TraceConfig_LockdownModeOperation value) { lockdown_mode_ = value; _has_field_.set(5); }
+
+ const std::vector<TraceConfig_ProducerConfig>& producers() const { return producers_; }
+ std::vector<TraceConfig_ProducerConfig>* mutable_producers() { return &producers_; }
+ int producers_size() const;
+ void clear_producers();
+ TraceConfig_ProducerConfig* add_producers();
+
+ bool has_statsd_metadata() const { return _has_field_[7]; }
+ const TraceConfig_StatsdMetadata& statsd_metadata() const { return *statsd_metadata_; }
+ TraceConfig_StatsdMetadata* mutable_statsd_metadata() { _has_field_.set(7); return statsd_metadata_.get(); }
+
+ bool has_write_into_file() const { return _has_field_[8]; }
+ bool write_into_file() const { return write_into_file_; }
+ void set_write_into_file(bool value) { write_into_file_ = value; _has_field_.set(8); }
+
+ bool has_output_path() const { return _has_field_[29]; }
+ const std::string& output_path() const { return output_path_; }
+ void set_output_path(const std::string& value) { output_path_ = value; _has_field_.set(29); }
+
+ bool has_file_write_period_ms() const { return _has_field_[9]; }
+ uint32_t file_write_period_ms() const { return file_write_period_ms_; }
+ void set_file_write_period_ms(uint32_t value) { file_write_period_ms_ = value; _has_field_.set(9); }
+
+ bool has_max_file_size_bytes() const { return _has_field_[10]; }
+ uint64_t max_file_size_bytes() const { return max_file_size_bytes_; }
+ void set_max_file_size_bytes(uint64_t value) { max_file_size_bytes_ = value; _has_field_.set(10); }
+
+ bool has_guardrail_overrides() const { return _has_field_[11]; }
+ const TraceConfig_GuardrailOverrides& guardrail_overrides() const { return *guardrail_overrides_; }
+ TraceConfig_GuardrailOverrides* mutable_guardrail_overrides() { _has_field_.set(11); return guardrail_overrides_.get(); }
+
+ bool has_deferred_start() const { return _has_field_[12]; }
+ bool deferred_start() const { return deferred_start_; }
+ void set_deferred_start(bool value) { deferred_start_ = value; _has_field_.set(12); }
+
+ bool has_flush_period_ms() const { return _has_field_[13]; }
+ uint32_t flush_period_ms() const { return flush_period_ms_; }
+ void set_flush_period_ms(uint32_t value) { flush_period_ms_ = value; _has_field_.set(13); }
+
+ bool has_flush_timeout_ms() const { return _has_field_[14]; }
+ uint32_t flush_timeout_ms() const { return flush_timeout_ms_; }
+ void set_flush_timeout_ms(uint32_t value) { flush_timeout_ms_ = value; _has_field_.set(14); }
+
+ bool has_data_source_stop_timeout_ms() const { return _has_field_[23]; }
+ uint32_t data_source_stop_timeout_ms() const { return data_source_stop_timeout_ms_; }
+ void set_data_source_stop_timeout_ms(uint32_t value) { data_source_stop_timeout_ms_ = value; _has_field_.set(23); }
+
+ bool has_notify_traceur() const { return _has_field_[16]; }
+ bool notify_traceur() const { return notify_traceur_; }
+ void set_notify_traceur(bool value) { notify_traceur_ = value; _has_field_.set(16); }
+
+ bool has_bugreport_score() const { return _has_field_[30]; }
+ int32_t bugreport_score() const { return bugreport_score_; }
+ void set_bugreport_score(int32_t value) { bugreport_score_ = value; _has_field_.set(30); }
+
+ bool has_bugreport_filename() const { return _has_field_[38]; }
+ const std::string& bugreport_filename() const { return bugreport_filename_; }
+ void set_bugreport_filename(const std::string& value) { bugreport_filename_ = value; _has_field_.set(38); }
+
+ bool has_trigger_config() const { return _has_field_[17]; }
+ const TraceConfig_TriggerConfig& trigger_config() const { return *trigger_config_; }
+ TraceConfig_TriggerConfig* mutable_trigger_config() { _has_field_.set(17); return trigger_config_.get(); }
+
+ const std::vector<std::string>& activate_triggers() const { return activate_triggers_; }
+ std::vector<std::string>* mutable_activate_triggers() { return &activate_triggers_; }
+ int activate_triggers_size() const { return static_cast<int>(activate_triggers_.size()); }
+ void clear_activate_triggers() { activate_triggers_.clear(); }
+ void add_activate_triggers(std::string value) { activate_triggers_.emplace_back(value); }
+ std::string* add_activate_triggers() { activate_triggers_.emplace_back(); return &activate_triggers_.back(); }
+
+ bool has_incremental_state_config() const { return _has_field_[21]; }
+ const TraceConfig_IncrementalStateConfig& incremental_state_config() const { return *incremental_state_config_; }
+ TraceConfig_IncrementalStateConfig* mutable_incremental_state_config() { _has_field_.set(21); return incremental_state_config_.get(); }
+
+ bool has_allow_user_build_tracing() const { return _has_field_[19]; }
+ bool allow_user_build_tracing() const { return allow_user_build_tracing_; }
+ void set_allow_user_build_tracing(bool value) { allow_user_build_tracing_ = value; _has_field_.set(19); }
+
+ bool has_unique_session_name() const { return _has_field_[22]; }
+ const std::string& unique_session_name() const { return unique_session_name_; }
+ void set_unique_session_name(const std::string& value) { unique_session_name_ = value; _has_field_.set(22); }
+
+ bool has_compression_type() const { return _has_field_[24]; }
+ TraceConfig_CompressionType compression_type() const { return compression_type_; }
+ void set_compression_type(TraceConfig_CompressionType value) { compression_type_ = value; _has_field_.set(24); }
+
+ bool has_incident_report_config() const { return _has_field_[25]; }
+ const TraceConfig_IncidentReportConfig& incident_report_config() const { return *incident_report_config_; }
+ TraceConfig_IncidentReportConfig* mutable_incident_report_config() { _has_field_.set(25); return incident_report_config_.get(); }
+
+ bool has_statsd_logging() const { return _has_field_[31]; }
+ TraceConfig_StatsdLogging statsd_logging() const { return statsd_logging_; }
+ void set_statsd_logging(TraceConfig_StatsdLogging value) { statsd_logging_ = value; _has_field_.set(31); }
+
+ bool has_trace_uuid_msb() const { return _has_field_[27]; }
+ int64_t trace_uuid_msb() const { return trace_uuid_msb_; }
+ void set_trace_uuid_msb(int64_t value) { trace_uuid_msb_ = value; _has_field_.set(27); }
+
+ bool has_trace_uuid_lsb() const { return _has_field_[28]; }
+ int64_t trace_uuid_lsb() const { return trace_uuid_lsb_; }
+ void set_trace_uuid_lsb(int64_t value) { trace_uuid_lsb_ = value; _has_field_.set(28); }
+
+ bool has_trace_filter() const { return _has_field_[33]; }
+ const TraceConfig_TraceFilter& trace_filter() const { return *trace_filter_; }
+ TraceConfig_TraceFilter* mutable_trace_filter() { _has_field_.set(33); return trace_filter_.get(); }
+
+ bool has_android_report_config() const { return _has_field_[34]; }
+ const TraceConfig_AndroidReportConfig& android_report_config() const { return *android_report_config_; }
+ TraceConfig_AndroidReportConfig* mutable_android_report_config() { _has_field_.set(34); return android_report_config_.get(); }
+
+ bool has_cmd_trace_start_delay() const { return _has_field_[35]; }
+ const TraceConfig_CmdTraceStartDelay& cmd_trace_start_delay() const { return *cmd_trace_start_delay_; }
+ TraceConfig_CmdTraceStartDelay* mutable_cmd_trace_start_delay() { _has_field_.set(35); return cmd_trace_start_delay_.get(); }
+
+ private:
+ std::vector<TraceConfig_BufferConfig> buffers_;
+ std::vector<TraceConfig_DataSource> data_sources_;
+ ::protozero::CopyablePtr<TraceConfig_BuiltinDataSource> builtin_data_sources_;
+ uint32_t duration_ms_{};
+ bool prefer_suspend_clock_for_duration_{};
+ bool enable_extra_guardrails_{};
+ TraceConfig_LockdownModeOperation lockdown_mode_{};
+ std::vector<TraceConfig_ProducerConfig> producers_;
+ ::protozero::CopyablePtr<TraceConfig_StatsdMetadata> statsd_metadata_;
+ bool write_into_file_{};
+ std::string output_path_{};
+ uint32_t file_write_period_ms_{};
+ uint64_t max_file_size_bytes_{};
+ ::protozero::CopyablePtr<TraceConfig_GuardrailOverrides> guardrail_overrides_;
+ bool deferred_start_{};
+ uint32_t flush_period_ms_{};
+ uint32_t flush_timeout_ms_{};
+ uint32_t data_source_stop_timeout_ms_{};
+ bool notify_traceur_{};
+ int32_t bugreport_score_{};
+ std::string bugreport_filename_{};
+ ::protozero::CopyablePtr<TraceConfig_TriggerConfig> trigger_config_;
+ std::vector<std::string> activate_triggers_;
+ ::protozero::CopyablePtr<TraceConfig_IncrementalStateConfig> incremental_state_config_;
+ bool allow_user_build_tracing_{};
+ std::string unique_session_name_{};
+ TraceConfig_CompressionType compression_type_{};
+ ::protozero::CopyablePtr<TraceConfig_IncidentReportConfig> incident_report_config_;
+ TraceConfig_StatsdLogging statsd_logging_{};
+ int64_t trace_uuid_msb_{};
+ int64_t trace_uuid_lsb_{};
+ ::protozero::CopyablePtr<TraceConfig_TraceFilter> trace_filter_;
+ ::protozero::CopyablePtr<TraceConfig_AndroidReportConfig> android_report_config_;
+ ::protozero::CopyablePtr<TraceConfig_CmdTraceStartDelay> cmd_trace_start_delay_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<39> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_CmdTraceStartDelay : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kMinDelayMsFieldNumber = 1,
+ kMaxDelayMsFieldNumber = 2,
+ };
+
+ TraceConfig_CmdTraceStartDelay();
+ ~TraceConfig_CmdTraceStartDelay() override;
+ TraceConfig_CmdTraceStartDelay(TraceConfig_CmdTraceStartDelay&&) noexcept;
+ TraceConfig_CmdTraceStartDelay& operator=(TraceConfig_CmdTraceStartDelay&&);
+ TraceConfig_CmdTraceStartDelay(const TraceConfig_CmdTraceStartDelay&);
+ TraceConfig_CmdTraceStartDelay& operator=(const TraceConfig_CmdTraceStartDelay&);
+ bool operator==(const TraceConfig_CmdTraceStartDelay&) const;
+ bool operator!=(const TraceConfig_CmdTraceStartDelay& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_min_delay_ms() const { return _has_field_[1]; }
+ uint32_t min_delay_ms() const { return min_delay_ms_; }
+ void set_min_delay_ms(uint32_t value) { min_delay_ms_ = value; _has_field_.set(1); }
+
+ bool has_max_delay_ms() const { return _has_field_[2]; }
+ uint32_t max_delay_ms() const { return max_delay_ms_; }
+ void set_max_delay_ms(uint32_t value) { max_delay_ms_ = value; _has_field_.set(2); }
+
+ private:
+ uint32_t min_delay_ms_{};
+ uint32_t max_delay_ms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_AndroidReportConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kReporterServicePackageFieldNumber = 1,
+ kReporterServiceClassFieldNumber = 2,
+ kSkipReportFieldNumber = 3,
+ kUsePipeInFrameworkForTestingFieldNumber = 4,
+ };
+
+ TraceConfig_AndroidReportConfig();
+ ~TraceConfig_AndroidReportConfig() override;
+ TraceConfig_AndroidReportConfig(TraceConfig_AndroidReportConfig&&) noexcept;
+ TraceConfig_AndroidReportConfig& operator=(TraceConfig_AndroidReportConfig&&);
+ TraceConfig_AndroidReportConfig(const TraceConfig_AndroidReportConfig&);
+ TraceConfig_AndroidReportConfig& operator=(const TraceConfig_AndroidReportConfig&);
+ bool operator==(const TraceConfig_AndroidReportConfig&) const;
+ bool operator!=(const TraceConfig_AndroidReportConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_reporter_service_package() const { return _has_field_[1]; }
+ const std::string& reporter_service_package() const { return reporter_service_package_; }
+ void set_reporter_service_package(const std::string& value) { reporter_service_package_ = value; _has_field_.set(1); }
+
+ bool has_reporter_service_class() const { return _has_field_[2]; }
+ const std::string& reporter_service_class() const { return reporter_service_class_; }
+ void set_reporter_service_class(const std::string& value) { reporter_service_class_ = value; _has_field_.set(2); }
+
+ bool has_skip_report() const { return _has_field_[3]; }
+ bool skip_report() const { return skip_report_; }
+ void set_skip_report(bool value) { skip_report_ = value; _has_field_.set(3); }
+
+ bool has_use_pipe_in_framework_for_testing() const { return _has_field_[4]; }
+ bool use_pipe_in_framework_for_testing() const { return use_pipe_in_framework_for_testing_; }
+ void set_use_pipe_in_framework_for_testing(bool value) { use_pipe_in_framework_for_testing_ = value; _has_field_.set(4); }
+
+ private:
+ std::string reporter_service_package_{};
+ std::string reporter_service_class_{};
+ bool skip_report_{};
+ bool use_pipe_in_framework_for_testing_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_TraceFilter : public ::protozero::CppMessageObj {
+ public:
+ using StringFilterRule = TraceConfig_TraceFilter_StringFilterRule;
+ using StringFilterChain = TraceConfig_TraceFilter_StringFilterChain;
+ using StringFilterPolicy = TraceConfig_TraceFilter_StringFilterPolicy;
+ static constexpr auto SFP_UNSPECIFIED = TraceConfig_TraceFilter_StringFilterPolicy_SFP_UNSPECIFIED;
+ static constexpr auto SFP_MATCH_REDACT_GROUPS = TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_REDACT_GROUPS;
+ static constexpr auto SFP_ATRACE_MATCH_REDACT_GROUPS = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_REDACT_GROUPS;
+ static constexpr auto SFP_MATCH_BREAK = TraceConfig_TraceFilter_StringFilterPolicy_SFP_MATCH_BREAK;
+ static constexpr auto SFP_ATRACE_MATCH_BREAK = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_MATCH_BREAK;
+ static constexpr auto SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS;
+ static constexpr auto StringFilterPolicy_MIN = TraceConfig_TraceFilter_StringFilterPolicy_SFP_UNSPECIFIED;
+ static constexpr auto StringFilterPolicy_MAX = TraceConfig_TraceFilter_StringFilterPolicy_SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS;
+ enum FieldNumbers {
+ kBytecodeFieldNumber = 1,
+ kBytecodeV2FieldNumber = 2,
+ kStringFilterChainFieldNumber = 3,
+ };
+
+ TraceConfig_TraceFilter();
+ ~TraceConfig_TraceFilter() override;
+ TraceConfig_TraceFilter(TraceConfig_TraceFilter&&) noexcept;
+ TraceConfig_TraceFilter& operator=(TraceConfig_TraceFilter&&);
+ TraceConfig_TraceFilter(const TraceConfig_TraceFilter&);
+ TraceConfig_TraceFilter& operator=(const TraceConfig_TraceFilter&);
+ bool operator==(const TraceConfig_TraceFilter&) const;
+ bool operator!=(const TraceConfig_TraceFilter& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_bytecode() const { return _has_field_[1]; }
+ const std::string& bytecode() const { return bytecode_; }
+ void set_bytecode(const std::string& value) { bytecode_ = value; _has_field_.set(1); }
+ void set_bytecode(const void* p, size_t s) { bytecode_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(1); }
+
+ bool has_bytecode_v2() const { return _has_field_[2]; }
+ const std::string& bytecode_v2() const { return bytecode_v2_; }
+ void set_bytecode_v2(const std::string& value) { bytecode_v2_ = value; _has_field_.set(2); }
+ void set_bytecode_v2(const void* p, size_t s) { bytecode_v2_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(2); }
+
+ bool has_string_filter_chain() const { return _has_field_[3]; }
+ const TraceConfig_TraceFilter_StringFilterChain& string_filter_chain() const { return *string_filter_chain_; }
+ TraceConfig_TraceFilter_StringFilterChain* mutable_string_filter_chain() { _has_field_.set(3); return string_filter_chain_.get(); }
+
+ private:
+ std::string bytecode_{};
+ std::string bytecode_v2_{};
+ ::protozero::CopyablePtr<TraceConfig_TraceFilter_StringFilterChain> string_filter_chain_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_TraceFilter_StringFilterChain : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kRulesFieldNumber = 1,
+ };
+
+ TraceConfig_TraceFilter_StringFilterChain();
+ ~TraceConfig_TraceFilter_StringFilterChain() override;
+ TraceConfig_TraceFilter_StringFilterChain(TraceConfig_TraceFilter_StringFilterChain&&) noexcept;
+ TraceConfig_TraceFilter_StringFilterChain& operator=(TraceConfig_TraceFilter_StringFilterChain&&);
+ TraceConfig_TraceFilter_StringFilterChain(const TraceConfig_TraceFilter_StringFilterChain&);
+ TraceConfig_TraceFilter_StringFilterChain& operator=(const TraceConfig_TraceFilter_StringFilterChain&);
+ bool operator==(const TraceConfig_TraceFilter_StringFilterChain&) const;
+ bool operator!=(const TraceConfig_TraceFilter_StringFilterChain& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<TraceConfig_TraceFilter_StringFilterRule>& rules() const { return rules_; }
+ std::vector<TraceConfig_TraceFilter_StringFilterRule>* mutable_rules() { return &rules_; }
+ int rules_size() const;
+ void clear_rules();
+ TraceConfig_TraceFilter_StringFilterRule* add_rules();
+
+ private:
+ std::vector<TraceConfig_TraceFilter_StringFilterRule> rules_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_TraceFilter_StringFilterRule : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPolicyFieldNumber = 1,
+ kRegexPatternFieldNumber = 2,
+ kAtracePayloadStartsWithFieldNumber = 3,
+ };
+
+ TraceConfig_TraceFilter_StringFilterRule();
+ ~TraceConfig_TraceFilter_StringFilterRule() override;
+ TraceConfig_TraceFilter_StringFilterRule(TraceConfig_TraceFilter_StringFilterRule&&) noexcept;
+ TraceConfig_TraceFilter_StringFilterRule& operator=(TraceConfig_TraceFilter_StringFilterRule&&);
+ TraceConfig_TraceFilter_StringFilterRule(const TraceConfig_TraceFilter_StringFilterRule&);
+ TraceConfig_TraceFilter_StringFilterRule& operator=(const TraceConfig_TraceFilter_StringFilterRule&);
+ bool operator==(const TraceConfig_TraceFilter_StringFilterRule&) const;
+ bool operator!=(const TraceConfig_TraceFilter_StringFilterRule& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_policy() const { return _has_field_[1]; }
+ TraceConfig_TraceFilter_StringFilterPolicy policy() const { return policy_; }
+ void set_policy(TraceConfig_TraceFilter_StringFilterPolicy value) { policy_ = value; _has_field_.set(1); }
+
+ bool has_regex_pattern() const { return _has_field_[2]; }
+ const std::string& regex_pattern() const { return regex_pattern_; }
+ void set_regex_pattern(const std::string& value) { regex_pattern_ = value; _has_field_.set(2); }
+
+ bool has_atrace_payload_starts_with() const { return _has_field_[3]; }
+ const std::string& atrace_payload_starts_with() const { return atrace_payload_starts_with_; }
+ void set_atrace_payload_starts_with(const std::string& value) { atrace_payload_starts_with_ = value; _has_field_.set(3); }
+
+ private:
+ TraceConfig_TraceFilter_StringFilterPolicy policy_{};
+ std::string regex_pattern_{};
+ std::string atrace_payload_starts_with_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_IncidentReportConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDestinationPackageFieldNumber = 1,
+ kDestinationClassFieldNumber = 2,
+ kPrivacyLevelFieldNumber = 3,
+ kSkipIncidentdFieldNumber = 5,
+ kSkipDropboxFieldNumber = 4,
+ };
+
+ TraceConfig_IncidentReportConfig();
+ ~TraceConfig_IncidentReportConfig() override;
+ TraceConfig_IncidentReportConfig(TraceConfig_IncidentReportConfig&&) noexcept;
+ TraceConfig_IncidentReportConfig& operator=(TraceConfig_IncidentReportConfig&&);
+ TraceConfig_IncidentReportConfig(const TraceConfig_IncidentReportConfig&);
+ TraceConfig_IncidentReportConfig& operator=(const TraceConfig_IncidentReportConfig&);
+ bool operator==(const TraceConfig_IncidentReportConfig&) const;
+ bool operator!=(const TraceConfig_IncidentReportConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_destination_package() const { return _has_field_[1]; }
+ const std::string& destination_package() const { return destination_package_; }
+ void set_destination_package(const std::string& value) { destination_package_ = value; _has_field_.set(1); }
+
+ bool has_destination_class() const { return _has_field_[2]; }
+ const std::string& destination_class() const { return destination_class_; }
+ void set_destination_class(const std::string& value) { destination_class_ = value; _has_field_.set(2); }
+
+ bool has_privacy_level() const { return _has_field_[3]; }
+ int32_t privacy_level() const { return privacy_level_; }
+ void set_privacy_level(int32_t value) { privacy_level_ = value; _has_field_.set(3); }
+
+ bool has_skip_incidentd() const { return _has_field_[5]; }
+ bool skip_incidentd() const { return skip_incidentd_; }
+ void set_skip_incidentd(bool value) { skip_incidentd_ = value; _has_field_.set(5); }
+
+ bool has_skip_dropbox() const { return _has_field_[4]; }
+ bool skip_dropbox() const { return skip_dropbox_; }
+ void set_skip_dropbox(bool value) { skip_dropbox_ = value; _has_field_.set(4); }
+
+ private:
+ std::string destination_package_{};
+ std::string destination_class_{};
+ int32_t privacy_level_{};
+ bool skip_incidentd_{};
+ bool skip_dropbox_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_IncrementalStateConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kClearPeriodMsFieldNumber = 1,
+ };
+
+ TraceConfig_IncrementalStateConfig();
+ ~TraceConfig_IncrementalStateConfig() override;
+ TraceConfig_IncrementalStateConfig(TraceConfig_IncrementalStateConfig&&) noexcept;
+ TraceConfig_IncrementalStateConfig& operator=(TraceConfig_IncrementalStateConfig&&);
+ TraceConfig_IncrementalStateConfig(const TraceConfig_IncrementalStateConfig&);
+ TraceConfig_IncrementalStateConfig& operator=(const TraceConfig_IncrementalStateConfig&);
+ bool operator==(const TraceConfig_IncrementalStateConfig&) const;
+ bool operator!=(const TraceConfig_IncrementalStateConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_clear_period_ms() const { return _has_field_[1]; }
+ uint32_t clear_period_ms() const { return clear_period_ms_; }
+ void set_clear_period_ms(uint32_t value) { clear_period_ms_ = value; _has_field_.set(1); }
+
+ private:
+ uint32_t clear_period_ms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_TriggerConfig : public ::protozero::CppMessageObj {
+ public:
+ using Trigger = TraceConfig_TriggerConfig_Trigger;
+ using TriggerMode = TraceConfig_TriggerConfig_TriggerMode;
+ static constexpr auto UNSPECIFIED = TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED;
+ static constexpr auto START_TRACING = TraceConfig_TriggerConfig_TriggerMode_START_TRACING;
+ static constexpr auto STOP_TRACING = TraceConfig_TriggerConfig_TriggerMode_STOP_TRACING;
+ static constexpr auto CLONE_SNAPSHOT = TraceConfig_TriggerConfig_TriggerMode_CLONE_SNAPSHOT;
+ static constexpr auto TriggerMode_MIN = TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED;
+ static constexpr auto TriggerMode_MAX = TraceConfig_TriggerConfig_TriggerMode_CLONE_SNAPSHOT;
+ enum FieldNumbers {
+ kTriggerModeFieldNumber = 1,
+ kUseCloneSnapshotIfAvailableFieldNumber = 5,
+ kTriggersFieldNumber = 2,
+ kTriggerTimeoutMsFieldNumber = 3,
+ };
+
+ TraceConfig_TriggerConfig();
+ ~TraceConfig_TriggerConfig() override;
+ TraceConfig_TriggerConfig(TraceConfig_TriggerConfig&&) noexcept;
+ TraceConfig_TriggerConfig& operator=(TraceConfig_TriggerConfig&&);
+ TraceConfig_TriggerConfig(const TraceConfig_TriggerConfig&);
+ TraceConfig_TriggerConfig& operator=(const TraceConfig_TriggerConfig&);
+ bool operator==(const TraceConfig_TriggerConfig&) const;
+ bool operator!=(const TraceConfig_TriggerConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trigger_mode() const { return _has_field_[1]; }
+ TraceConfig_TriggerConfig_TriggerMode trigger_mode() const { return trigger_mode_; }
+ void set_trigger_mode(TraceConfig_TriggerConfig_TriggerMode value) { trigger_mode_ = value; _has_field_.set(1); }
+
+ bool has_use_clone_snapshot_if_available() const { return _has_field_[5]; }
+ bool use_clone_snapshot_if_available() const { return use_clone_snapshot_if_available_; }
+ void set_use_clone_snapshot_if_available(bool value) { use_clone_snapshot_if_available_ = value; _has_field_.set(5); }
+
+ const std::vector<TraceConfig_TriggerConfig_Trigger>& triggers() const { return triggers_; }
+ std::vector<TraceConfig_TriggerConfig_Trigger>* mutable_triggers() { return &triggers_; }
+ int triggers_size() const;
+ void clear_triggers();
+ TraceConfig_TriggerConfig_Trigger* add_triggers();
+
+ bool has_trigger_timeout_ms() const { return _has_field_[3]; }
+ uint32_t trigger_timeout_ms() const { return trigger_timeout_ms_; }
+ void set_trigger_timeout_ms(uint32_t value) { trigger_timeout_ms_ = value; _has_field_.set(3); }
+
+ private:
+ TraceConfig_TriggerConfig_TriggerMode trigger_mode_{};
+ bool use_clone_snapshot_if_available_{};
+ std::vector<TraceConfig_TriggerConfig_Trigger> triggers_;
+ uint32_t trigger_timeout_ms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_TriggerConfig_Trigger : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kProducerNameRegexFieldNumber = 2,
+ kStopDelayMsFieldNumber = 3,
+ kMaxPer24HFieldNumber = 4,
+ kSkipProbabilityFieldNumber = 5,
+ };
+
+ TraceConfig_TriggerConfig_Trigger();
+ ~TraceConfig_TriggerConfig_Trigger() override;
+ TraceConfig_TriggerConfig_Trigger(TraceConfig_TriggerConfig_Trigger&&) noexcept;
+ TraceConfig_TriggerConfig_Trigger& operator=(TraceConfig_TriggerConfig_Trigger&&);
+ TraceConfig_TriggerConfig_Trigger(const TraceConfig_TriggerConfig_Trigger&);
+ TraceConfig_TriggerConfig_Trigger& operator=(const TraceConfig_TriggerConfig_Trigger&);
+ bool operator==(const TraceConfig_TriggerConfig_Trigger&) const;
+ bool operator!=(const TraceConfig_TriggerConfig_Trigger& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_producer_name_regex() const { return _has_field_[2]; }
+ const std::string& producer_name_regex() const { return producer_name_regex_; }
+ void set_producer_name_regex(const std::string& value) { producer_name_regex_ = value; _has_field_.set(2); }
+
+ bool has_stop_delay_ms() const { return _has_field_[3]; }
+ uint32_t stop_delay_ms() const { return stop_delay_ms_; }
+ void set_stop_delay_ms(uint32_t value) { stop_delay_ms_ = value; _has_field_.set(3); }
+
+ bool has_max_per_24_h() const { return _has_field_[4]; }
+ uint32_t max_per_24_h() const { return max_per_24_h_; }
+ void set_max_per_24_h(uint32_t value) { max_per_24_h_ = value; _has_field_.set(4); }
+
+ bool has_skip_probability() const { return _has_field_[5]; }
+ double skip_probability() const { return skip_probability_; }
+ void set_skip_probability(double value) { skip_probability_ = value; _has_field_.set(5); }
+
+ private:
+ std::string name_{};
+ std::string producer_name_regex_{};
+ uint32_t stop_delay_ms_{};
+ uint32_t max_per_24_h_{};
+ double skip_probability_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_GuardrailOverrides : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kMaxUploadPerDayBytesFieldNumber = 1,
+ kMaxTracingBufferSizeKbFieldNumber = 2,
+ };
+
+ TraceConfig_GuardrailOverrides();
+ ~TraceConfig_GuardrailOverrides() override;
+ TraceConfig_GuardrailOverrides(TraceConfig_GuardrailOverrides&&) noexcept;
+ TraceConfig_GuardrailOverrides& operator=(TraceConfig_GuardrailOverrides&&);
+ TraceConfig_GuardrailOverrides(const TraceConfig_GuardrailOverrides&);
+ TraceConfig_GuardrailOverrides& operator=(const TraceConfig_GuardrailOverrides&);
+ bool operator==(const TraceConfig_GuardrailOverrides&) const;
+ bool operator!=(const TraceConfig_GuardrailOverrides& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_max_upload_per_day_bytes() const { return _has_field_[1]; }
+ uint64_t max_upload_per_day_bytes() const { return max_upload_per_day_bytes_; }
+ void set_max_upload_per_day_bytes(uint64_t value) { max_upload_per_day_bytes_ = value; _has_field_.set(1); }
+
+ bool has_max_tracing_buffer_size_kb() const { return _has_field_[2]; }
+ uint32_t max_tracing_buffer_size_kb() const { return max_tracing_buffer_size_kb_; }
+ void set_max_tracing_buffer_size_kb(uint32_t value) { max_tracing_buffer_size_kb_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t max_upload_per_day_bytes_{};
+ uint32_t max_tracing_buffer_size_kb_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_StatsdMetadata : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTriggeringAlertIdFieldNumber = 1,
+ kTriggeringConfigUidFieldNumber = 2,
+ kTriggeringConfigIdFieldNumber = 3,
+ kTriggeringSubscriptionIdFieldNumber = 4,
+ };
+
+ TraceConfig_StatsdMetadata();
+ ~TraceConfig_StatsdMetadata() override;
+ TraceConfig_StatsdMetadata(TraceConfig_StatsdMetadata&&) noexcept;
+ TraceConfig_StatsdMetadata& operator=(TraceConfig_StatsdMetadata&&);
+ TraceConfig_StatsdMetadata(const TraceConfig_StatsdMetadata&);
+ TraceConfig_StatsdMetadata& operator=(const TraceConfig_StatsdMetadata&);
+ bool operator==(const TraceConfig_StatsdMetadata&) const;
+ bool operator!=(const TraceConfig_StatsdMetadata& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_triggering_alert_id() const { return _has_field_[1]; }
+ int64_t triggering_alert_id() const { return triggering_alert_id_; }
+ void set_triggering_alert_id(int64_t value) { triggering_alert_id_ = value; _has_field_.set(1); }
+
+ bool has_triggering_config_uid() const { return _has_field_[2]; }
+ int32_t triggering_config_uid() const { return triggering_config_uid_; }
+ void set_triggering_config_uid(int32_t value) { triggering_config_uid_ = value; _has_field_.set(2); }
+
+ bool has_triggering_config_id() const { return _has_field_[3]; }
+ int64_t triggering_config_id() const { return triggering_config_id_; }
+ void set_triggering_config_id(int64_t value) { triggering_config_id_ = value; _has_field_.set(3); }
+
+ bool has_triggering_subscription_id() const { return _has_field_[4]; }
+ int64_t triggering_subscription_id() const { return triggering_subscription_id_; }
+ void set_triggering_subscription_id(int64_t value) { triggering_subscription_id_ = value; _has_field_.set(4); }
+
+ private:
+ int64_t triggering_alert_id_{};
+ int32_t triggering_config_uid_{};
+ int64_t triggering_config_id_{};
+ int64_t triggering_subscription_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_ProducerConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kProducerNameFieldNumber = 1,
+ kShmSizeKbFieldNumber = 2,
+ kPageSizeKbFieldNumber = 3,
+ };
+
+ TraceConfig_ProducerConfig();
+ ~TraceConfig_ProducerConfig() override;
+ TraceConfig_ProducerConfig(TraceConfig_ProducerConfig&&) noexcept;
+ TraceConfig_ProducerConfig& operator=(TraceConfig_ProducerConfig&&);
+ TraceConfig_ProducerConfig(const TraceConfig_ProducerConfig&);
+ TraceConfig_ProducerConfig& operator=(const TraceConfig_ProducerConfig&);
+ bool operator==(const TraceConfig_ProducerConfig&) const;
+ bool operator!=(const TraceConfig_ProducerConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_producer_name() const { return _has_field_[1]; }
+ const std::string& producer_name() const { return producer_name_; }
+ void set_producer_name(const std::string& value) { producer_name_ = value; _has_field_.set(1); }
+
+ bool has_shm_size_kb() const { return _has_field_[2]; }
+ uint32_t shm_size_kb() const { return shm_size_kb_; }
+ void set_shm_size_kb(uint32_t value) { shm_size_kb_ = value; _has_field_.set(2); }
+
+ bool has_page_size_kb() const { return _has_field_[3]; }
+ uint32_t page_size_kb() const { return page_size_kb_; }
+ void set_page_size_kb(uint32_t value) { page_size_kb_ = value; _has_field_.set(3); }
+
+ private:
+ std::string producer_name_{};
+ uint32_t shm_size_kb_{};
+ uint32_t page_size_kb_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_BuiltinDataSource : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDisableClockSnapshottingFieldNumber = 1,
+ kDisableTraceConfigFieldNumber = 2,
+ kDisableSystemInfoFieldNumber = 3,
+ kDisableServiceEventsFieldNumber = 4,
+ kPrimaryTraceClockFieldNumber = 5,
+ kSnapshotIntervalMsFieldNumber = 6,
+ kPreferSuspendClockForSnapshotFieldNumber = 7,
+ kDisableChunkUsageHistogramsFieldNumber = 8,
+ };
+
+ TraceConfig_BuiltinDataSource();
+ ~TraceConfig_BuiltinDataSource() override;
+ TraceConfig_BuiltinDataSource(TraceConfig_BuiltinDataSource&&) noexcept;
+ TraceConfig_BuiltinDataSource& operator=(TraceConfig_BuiltinDataSource&&);
+ TraceConfig_BuiltinDataSource(const TraceConfig_BuiltinDataSource&);
+ TraceConfig_BuiltinDataSource& operator=(const TraceConfig_BuiltinDataSource&);
+ bool operator==(const TraceConfig_BuiltinDataSource&) const;
+ bool operator!=(const TraceConfig_BuiltinDataSource& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_disable_clock_snapshotting() const { return _has_field_[1]; }
+ bool disable_clock_snapshotting() const { return disable_clock_snapshotting_; }
+ void set_disable_clock_snapshotting(bool value) { disable_clock_snapshotting_ = value; _has_field_.set(1); }
+
+ bool has_disable_trace_config() const { return _has_field_[2]; }
+ bool disable_trace_config() const { return disable_trace_config_; }
+ void set_disable_trace_config(bool value) { disable_trace_config_ = value; _has_field_.set(2); }
+
+ bool has_disable_system_info() const { return _has_field_[3]; }
+ bool disable_system_info() const { return disable_system_info_; }
+ void set_disable_system_info(bool value) { disable_system_info_ = value; _has_field_.set(3); }
+
+ bool has_disable_service_events() const { return _has_field_[4]; }
+ bool disable_service_events() const { return disable_service_events_; }
+ void set_disable_service_events(bool value) { disable_service_events_ = value; _has_field_.set(4); }
+
+ bool has_primary_trace_clock() const { return _has_field_[5]; }
+ BuiltinClock primary_trace_clock() const { return primary_trace_clock_; }
+ void set_primary_trace_clock(BuiltinClock value) { primary_trace_clock_ = value; _has_field_.set(5); }
+
+ bool has_snapshot_interval_ms() const { return _has_field_[6]; }
+ uint32_t snapshot_interval_ms() const { return snapshot_interval_ms_; }
+ void set_snapshot_interval_ms(uint32_t value) { snapshot_interval_ms_ = value; _has_field_.set(6); }
+
+ bool has_prefer_suspend_clock_for_snapshot() const { return _has_field_[7]; }
+ bool prefer_suspend_clock_for_snapshot() const { return prefer_suspend_clock_for_snapshot_; }
+ void set_prefer_suspend_clock_for_snapshot(bool value) { prefer_suspend_clock_for_snapshot_ = value; _has_field_.set(7); }
+
+ bool has_disable_chunk_usage_histograms() const { return _has_field_[8]; }
+ bool disable_chunk_usage_histograms() const { return disable_chunk_usage_histograms_; }
+ void set_disable_chunk_usage_histograms(bool value) { disable_chunk_usage_histograms_ = value; _has_field_.set(8); }
+
+ private:
+ bool disable_clock_snapshotting_{};
+ bool disable_trace_config_{};
+ bool disable_system_info_{};
+ bool disable_service_events_{};
+ BuiltinClock primary_trace_clock_{};
+ uint32_t snapshot_interval_ms_{};
+ bool prefer_suspend_clock_for_snapshot_{};
+ bool disable_chunk_usage_histograms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_DataSource : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kConfigFieldNumber = 1,
+ kProducerNameFilterFieldNumber = 2,
+ kProducerNameRegexFilterFieldNumber = 3,
+ };
+
+ TraceConfig_DataSource();
+ ~TraceConfig_DataSource() override;
+ TraceConfig_DataSource(TraceConfig_DataSource&&) noexcept;
+ TraceConfig_DataSource& operator=(TraceConfig_DataSource&&);
+ TraceConfig_DataSource(const TraceConfig_DataSource&);
+ TraceConfig_DataSource& operator=(const TraceConfig_DataSource&);
+ bool operator==(const TraceConfig_DataSource&) const;
+ bool operator!=(const TraceConfig_DataSource& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_config() const { return _has_field_[1]; }
+ const DataSourceConfig& config() const { return *config_; }
+ DataSourceConfig* mutable_config() { _has_field_.set(1); return config_.get(); }
+
+ const std::vector<std::string>& producer_name_filter() const { return producer_name_filter_; }
+ std::vector<std::string>* mutable_producer_name_filter() { return &producer_name_filter_; }
+ int producer_name_filter_size() const { return static_cast<int>(producer_name_filter_.size()); }
+ void clear_producer_name_filter() { producer_name_filter_.clear(); }
+ void add_producer_name_filter(std::string value) { producer_name_filter_.emplace_back(value); }
+ std::string* add_producer_name_filter() { producer_name_filter_.emplace_back(); return &producer_name_filter_.back(); }
+
+ const std::vector<std::string>& producer_name_regex_filter() const { return producer_name_regex_filter_; }
+ std::vector<std::string>* mutable_producer_name_regex_filter() { return &producer_name_regex_filter_; }
+ int producer_name_regex_filter_size() const { return static_cast<int>(producer_name_regex_filter_.size()); }
+ void clear_producer_name_regex_filter() { producer_name_regex_filter_.clear(); }
+ void add_producer_name_regex_filter(std::string value) { producer_name_regex_filter_.emplace_back(value); }
+ std::string* add_producer_name_regex_filter() { producer_name_regex_filter_.emplace_back(); return &producer_name_regex_filter_.back(); }
+
+ private:
+ ::protozero::CopyablePtr<DataSourceConfig> config_;
+ std::vector<std::string> producer_name_filter_;
+ std::vector<std::string> producer_name_regex_filter_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceConfig_BufferConfig : public ::protozero::CppMessageObj {
+ public:
+ using FillPolicy = TraceConfig_BufferConfig_FillPolicy;
+ static constexpr auto UNSPECIFIED = TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED;
+ static constexpr auto RING_BUFFER = TraceConfig_BufferConfig_FillPolicy_RING_BUFFER;
+ static constexpr auto DISCARD = TraceConfig_BufferConfig_FillPolicy_DISCARD;
+ static constexpr auto FillPolicy_MIN = TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED;
+ static constexpr auto FillPolicy_MAX = TraceConfig_BufferConfig_FillPolicy_DISCARD;
+ enum FieldNumbers {
+ kSizeKbFieldNumber = 1,
+ kFillPolicyFieldNumber = 4,
+ kTransferOnCloneFieldNumber = 5,
+ kClearBeforeCloneFieldNumber = 6,
+ };
+
+ TraceConfig_BufferConfig();
+ ~TraceConfig_BufferConfig() override;
+ TraceConfig_BufferConfig(TraceConfig_BufferConfig&&) noexcept;
+ TraceConfig_BufferConfig& operator=(TraceConfig_BufferConfig&&);
+ TraceConfig_BufferConfig(const TraceConfig_BufferConfig&);
+ TraceConfig_BufferConfig& operator=(const TraceConfig_BufferConfig&);
+ bool operator==(const TraceConfig_BufferConfig&) const;
+ bool operator!=(const TraceConfig_BufferConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_size_kb() const { return _has_field_[1]; }
+ uint32_t size_kb() const { return size_kb_; }
+ void set_size_kb(uint32_t value) { size_kb_ = value; _has_field_.set(1); }
+
+ bool has_fill_policy() const { return _has_field_[4]; }
+ TraceConfig_BufferConfig_FillPolicy fill_policy() const { return fill_policy_; }
+ void set_fill_policy(TraceConfig_BufferConfig_FillPolicy value) { fill_policy_ = value; _has_field_.set(4); }
+
+ bool has_transfer_on_clone() const { return _has_field_[5]; }
+ bool transfer_on_clone() const { return transfer_on_clone_; }
+ void set_transfer_on_clone(bool value) { transfer_on_clone_ = value; _has_field_.set(5); }
+
+ bool has_clear_before_clone() const { return _has_field_[6]; }
+ bool clear_before_clone() const { return clear_before_clone_; }
+ void set_clear_before_clone(bool value) { clear_before_clone_ = value; _has_field_.set(6); }
+
+ private:
+ uint32_t size_kb_{};
+ TraceConfig_BufferConfig_FillPolicy fill_policy_{};
+ bool transfer_on_clone_{};
+ bool clear_before_clone_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
+
+// Creates the aliases in the ::perfetto namespace, doing things like:
+// using ::perfetto::Foo = ::perfetto::protos::gen::Foo.
+// See comments in forward_decls.h for the historical reasons of this
+// indirection layer.
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h"
+
+namespace perfetto {
+
+inline TraceConfig::TriggerConfig::TriggerMode GetTriggerMode(
+ const TraceConfig& cfg) {
+ auto mode = cfg.trigger_config().trigger_mode();
+ if (cfg.trigger_config().use_clone_snapshot_if_available())
+ mode = TraceConfig::TriggerConfig::CLONE_SNAPSHOT;
+ return mode;
+}
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
+// gen_amalgamated begin header: include/perfetto/tracing/data_source.h
+// gen_amalgamated begin header: include/perfetto/tracing/core/flush_flags.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace perfetto {
+
+// This class is a wrapper around the uint64_t flags that are sent across the
+// tracing protocol whenenver a flush occurs. It helps determining the reason
+// and initiator of the flush.
+// NOTE: the values here are part of the tracing protocol ABI. Do not renumber.
+class FlushFlags {
+ public:
+ enum class Initiator : uint64_t {
+ // DO NOT RENUMBER, ABI.
+ kUnknown = 0,
+ kTraced = 1,
+ kPerfettoCmd = 2,
+ kConsumerSdk = 3,
+ kMax,
+ };
+
+ enum class Reason : uint64_t {
+ // DO NOT RENUMBER, ABI.
+ kUnknown = 0,
+ kPeriodic = 1,
+ kTraceStop = 2,
+ kTraceClone = 3,
+ kExplicit = 4,
+ kMax,
+ };
+
+ enum class CloneTarget : uint64_t {
+ // DO NOT RENUMBER, ABI.
+ kUnknown = 0,
+ kBugreport = 1,
+ kMax,
+ };
+
+ explicit FlushFlags(uint64_t flags = 0) : flags_(flags) {}
+ FlushFlags(Initiator i, Reason r, CloneTarget c = CloneTarget::kUnknown)
+ : flags_((static_cast<uint64_t>(i) << kInitiatorShift) |
+ (static_cast<uint64_t>(r) << kReasonShift) |
+ (static_cast<uint64_t>(c) << kCloneTargetShift)) {}
+
+ bool operator==(const FlushFlags& o) const { return flags_ == o.flags_; }
+ bool operator!=(const FlushFlags& o) const { return !(*this == o); }
+
+ Initiator initiator() const {
+ // Due to version mismatch we might see a value from the future that we
+ // didn't know yet. If that happens, short ciruit to kUnknown.
+ static_assert(
+ uint64_t(Initiator::kMax) - 1 <= (kInitiatorMask >> kInitiatorShift),
+ "enum out of range");
+ const uint64_t value = (flags_ & kInitiatorMask) >> kInitiatorShift;
+ return value < uint64_t(Initiator::kMax) ? Initiator(value)
+ : Initiator::kUnknown;
+ }
+
+ Reason reason() const {
+ static_assert(uint64_t(Reason::kMax) - 1 <= (kReasonMask >> kReasonShift),
+ "enum out of range");
+ const uint64_t value = (flags_ & kReasonMask) >> kReasonShift;
+ return value < uint64_t(Reason::kMax) ? Reason(value) : Reason::kUnknown;
+ }
+
+ CloneTarget clone_target() const {
+ static_assert(uint64_t(CloneTarget::kMax) - 1 <=
+ (kCloneTargetMask >> kCloneTargetShift),
+ "enum out of range");
+ const uint64_t value = (flags_ & kCloneTargetMask) >> kCloneTargetShift;
+ return value < uint64_t(CloneTarget::kMax) ? CloneTarget(value)
+ : CloneTarget::kUnknown;
+ }
+
+ uint64_t flags() const { return flags_; }
+
+ private:
+ // DO NOT CHANGE, ABI.
+ static constexpr uint64_t kReasonMask = 0xF;
+ static constexpr uint64_t kReasonShift = 0;
+ static constexpr uint64_t kInitiatorMask = 0xF0;
+ static constexpr uint64_t kInitiatorShift = 4;
+ static constexpr uint64_t kCloneTargetMask = 0xF00;
+ static constexpr uint64_t kCloneTargetShift = 8;
+
+ uint64_t flags_ = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_CORE_FLUSH_FLAGS_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/data_source_type.h
+// gen_amalgamated begin header: include/perfetto/tracing/internal/tracing_muxer.h
+// gen_amalgamated begin header: include/perfetto/tracing/internal/tracing_tls.h
+// gen_amalgamated begin header: include/perfetto/tracing/platform.h
+// gen_amalgamated begin header: include/perfetto/base/proc_utils.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
+
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+extern "C" {
+// Prototype extracted from the Windows SDK to avoid including windows.h.
+__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+#include <zircon/process.h>
+#include <zircon/types.h>
+#else
+#include <unistd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+using PlatformProcessId = zx_handle_t;
+inline PlatformProcessId GetProcessId() {
+ return zx_process_self();
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using PlatformProcessId = uint64_t;
+inline PlatformProcessId GetProcessId() {
+ return static_cast<uint64_t>(GetCurrentProcessId());
+}
+#else
+using PlatformProcessId = pid_t;
+inline PlatformProcessId GetProcessId() {
+ return getpid();
+}
+#endif
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
+// gen_amalgamated begin header: include/perfetto/base/thread_utils.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+extern "C" {
+// Prototype extracted from the Windows SDK to avoid including windows.h.
+__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+#include <zircon/types.h>
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+#else
+#include <pthread.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+using PlatformThreadId = pid_t;
+inline PlatformThreadId GetThreadId() {
+ return gettid();
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
+using PlatformThreadId = pid_t;
+inline PlatformThreadId GetThreadId() {
+ return static_cast<pid_t>(syscall(__NR_gettid));
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+using PlatformThreadId = zx_koid_t;
+// Not inlined because the result is cached internally.
+PERFETTO_EXPORT_COMPONENT PlatformThreadId GetThreadId();
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+using PlatformThreadId = uint64_t;
+inline PlatformThreadId GetThreadId() {
+ uint64_t tid;
+ pthread_threadid_np(nullptr, &tid);
+ return tid;
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using PlatformThreadId = uint64_t;
+inline PlatformThreadId GetThreadId() {
+ return static_cast<uint64_t>(GetCurrentThreadId());
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+using PlatformThreadId = pid_t;
+inline PlatformThreadId GetThreadId() {
+ return reinterpret_cast<int32_t>(pthread_self());
+}
+#else // Default to pthreads in case no OS is set.
+using PlatformThreadId = pthread_t;
+inline PlatformThreadId GetThreadId() {
+ return pthread_self();
+}
+#endif
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+// gen_amalgamated begin header: include/perfetto/tracing/tracing.h
+// gen_amalgamated begin header: include/perfetto/tracing/backend_type.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_
+#define INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_
+
+#include <stdint.h>
+
+namespace perfetto {
+
+enum BackendType : uint32_t {
+ kUnspecifiedBackend = 0,
+
+ // Connects to a previously-initialized perfetto tracing backend for
+ // in-process. If the in-process backend has not been previously initialized
+ // it will do so and create the tracing service on a dedicated thread.
+ kInProcessBackend = 1 << 0,
+
+ // Connects to the system tracing service (e.g. on Linux/Android/Mac uses a
+ // named UNIX socket).
+ kSystemBackend = 1 << 1,
+
+ // Used to provide a custom IPC transport to connect to the service.
+ // TracingInitArgs::custom_backend must be non-null and point to an
+ // indefinitely lived instance.
+ kCustomBackend = 1 << 2,
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/in_process_tracing_backend.h
+// gen_amalgamated begin header: include/perfetto/tracing/tracing_backend.h
+// gen_amalgamated begin header: include/perfetto/base/platform_handle.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
+#define INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
+
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+
+namespace perfetto {
+namespace base {
+
+// PlatformHandle should be used only for types that are HANDLE(s) in Windows.
+// It should NOT be used to blanket-replace "int fd" in the codebase.
+// Windows has two types of "handles", which, in UNIX-land, both map to int:
+// 1. File handles returned by the posix-compatibility API like _open().
+// These are just int(s) and should stay such, because all the posix-like API
+// in Windows.h take an int, not a HANDLE.
+// 2. Handles returned by old-school WINAPI like CreateFile, CreateEvent etc.
+// These are proper HANDLE(s). PlatformHandle should be used here.
+//
+// On Windows, sockets have their own type (SOCKET) which is neither a HANDLE
+// nor an int. However Windows SOCKET(s) can have an event HANDLE attached
+// to them (which in Perfetto is a PlatformHandle), and that can be used in
+// WaitForMultipleObjects, hence in base::TaskRunner.AddFileDescriptorWatch().
+// On POSIX OSes, a SocketHandle is really just an int (a file descriptor).
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// Windows.h typedefs HANDLE to void*, and SOCKET to uintptr_t. We use their
+// types to avoid leaking Windows.h through our headers.
+using PlatformHandle = void*;
+using SocketHandle = uintptr_t;
+
+// On Windows both nullptr and 0xffff... (INVALID_HANDLE_VALUE) are invalid.
+struct PlatformHandleChecker {
+ static inline bool IsValid(PlatformHandle h) {
+ return h && h != reinterpret_cast<PlatformHandle>(-1);
+ }
+};
+#else
+using PlatformHandle = int;
+using SocketHandle = int;
+struct PlatformHandleChecker {
+ static inline bool IsValid(PlatformHandle h) { return h >= 0; }
+};
+#endif
+
+// The definition of this lives in base/file_utils.cc (to avoid creating an
+// extra build edge for a one liner). This is really an alias for close() (UNIX)
+// CloseHandle() (Windows). THe indirection layer is just to avoid leaking
+// system headers like Windows.h through perfetto headers.
+// Thre return value is always UNIX-style: 0 on success, -1 on failure.
+int ClosePlatformHandle(PlatformHandle);
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
+#define INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
+
+#include <functional>
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h"
+
+// The embedder can (but doesn't have to) extend the TracingBackend class and
+// pass as an argument to Tracing::Initialize(kCustomBackend) to override the
+// way to reach the service. This is for peculiar cases where the embedder has
+// a multi-process architecture and wants to override the IPC transport. The
+// real use-case for this at the time of writing is chromium (+ Mojo IPC).
+// Extending this class requires depending on the full set of perfetto headers
+// (not just /public/). Contact the team before doing so as the non-public
+// headers are not guaranteed to be API stable.
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}
+
+// These classes are declared in headers outside of /public/.
+class Consumer;
+class ConsumerEndpoint;
+class Producer;
+class ProducerEndpoint;
+
+using CreateSocketCallback = std::function<void(base::SocketHandle)>;
+using CreateSocketAsync = void (*)(CreateSocketCallback);
+
+// Responsible for connecting to the producer.
+class PERFETTO_EXPORT_COMPONENT TracingProducerBackend {
+ public:
+ virtual ~TracingProducerBackend();
+
+ // Connects a Producer instance and obtains a ProducerEndpoint, which is
+ // essentially a 1:1 channel between one Producer and the Service.
+ // To disconnect just destroy the returned endpoint object. It is safe to
+ // destroy the Producer once Producer::OnDisconnect() has been invoked.
+ struct ConnectProducerArgs {
+ std::string producer_name;
+
+ // The Producer object that will receive calls like Start/StopDataSource().
+ // The caller has to guarantee that this object is valid as long as the
+ // returned ProducerEndpoint is alive.
+ Producer* producer = nullptr;
+
+ // The task runner where the Producer methods will be called onto.
+ // The caller has to guarantee that the passed TaskRunner is valid as long
+ // as the returned ProducerEndpoint is alive.
+ ::perfetto::base::TaskRunner* task_runner = nullptr;
+
+ // These get propagated from TracingInitArgs and are optionally provided by
+ // the client when calling Tracing::Initialize().
+ uint32_t shmem_size_hint_bytes = 0;
+ uint32_t shmem_page_size_hint_bytes = 0;
+
+ // If true, the backend should allocate a shared memory buffer and provide
+ // it to the service when connecting.
+ // It's used in startup tracing.
+ bool use_producer_provided_smb = false;
+
+ // If set, the producer will call this function to create and connect to a
+ // socket. See the corresponding field in TracingInitArgs for more info.
+ CreateSocketAsync create_socket_async = nullptr;
+ };
+
+ virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
+ const ConnectProducerArgs&) = 0;
+};
+
+// Responsible for connecting to the consumer.
+class PERFETTO_EXPORT_COMPONENT TracingConsumerBackend {
+ public:
+ virtual ~TracingConsumerBackend();
+
+ // As above, for the Consumer-side.
+ struct ConnectConsumerArgs {
+ // The Consumer object that will receive calls like OnTracingDisabled(),
+ // OnTraceData().
+ Consumer* consumer{};
+
+ // The task runner where the Consumer methods will be called onto.
+ ::perfetto::base::TaskRunner* task_runner{};
+ };
+ virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
+ const ConnectConsumerArgs&) = 0;
+};
+
+class PERFETTO_EXPORT_COMPONENT TracingBackend : public TracingProducerBackend,
+ public TracingConsumerBackend {
+ public:
+ ~TracingBackend() override;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}
+
+class Producer;
+class TracingService;
+
+namespace internal {
+
+// A built-in implementation of TracingBackend that creates a tracing service
+// instance in-process. Instantiated when the embedder calls
+// Tracing::Initialize(kInProcessBackend). Solves most in-app-only tracing
+// use-cases.
+class PERFETTO_EXPORT_COMPONENT InProcessTracingBackend
+ : public TracingBackend {
+ public:
+ static TracingBackend* GetInstance();
+
+ ~InProcessTracingBackend() override;
+
+ // TracingBackend implementation.
+ std::unique_ptr<ProducerEndpoint> ConnectProducer(
+ const ConnectProducerArgs&) override;
+ std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
+ const ConnectConsumerArgs&) override;
+
+ private:
+ InProcessTracingBackend();
+ TracingService* GetOrCreateService(base::TaskRunner*);
+
+ std::unique_ptr<TracingService> service_;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/system_tracing_backend.h
+// gen_amalgamated begin header: include/perfetto/tracing/default_socket.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_DEFAULT_SOCKET_H_
+#define INCLUDE_PERFETTO_TRACING_DEFAULT_SOCKET_H_
+
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+
+PERFETTO_EXPORT_COMPONENT const char* GetConsumerSocket();
+// This function is used for tokenize the |producer_socket_names| string into
+// multiple producer socket names.
+PERFETTO_EXPORT_COMPONENT std::vector<std::string> TokenizeProducerSockets(
+ const char* producer_socket_names);
+PERFETTO_EXPORT_COMPONENT const char* GetProducerSocket();
+
+// Optionally returns the relay socket name (nullable). The relay socket is used
+// for forwarding the IPC messages between the local producers and the remote
+// tracing service.
+PERFETTO_EXPORT_COMPONENT const char* GetRelaySocket();
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_DEFAULT_SOCKET_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/default_socket.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}
+
+class Producer;
+
+// Built-in implementations of TracingProducerBackend and TracingConsumerBackend
+// that connect to the system tracing daemon (traced) via a UNIX socket using
+// the perfetto built-in proto-based IPC mechanism. Instantiated when the
+// embedder calls Tracing::Initialize(kSystemBackend). They allow to get
+// app-traces fused together with system traces, useful to correlate on the
+// timeline system events (e.g. scheduling slices from the kernel) with in-app
+// events.
+namespace internal {
+
+// Producer backend
+class PERFETTO_EXPORT_COMPONENT SystemProducerTracingBackend
+ : public TracingProducerBackend {
+ public:
+ static TracingProducerBackend* GetInstance();
+
+ std::unique_ptr<ProducerEndpoint> ConnectProducer(
+ const ConnectProducerArgs&) override;
+
+ private:
+ SystemProducerTracingBackend();
+};
+
+// Consumer backend
+class PERFETTO_EXPORT_COMPONENT SystemConsumerTracingBackend
+ : public TracingConsumerBackend {
+ public:
+ static TracingConsumerBackend* GetInstance();
+
+ std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
+ const ConnectConsumerArgs&) override;
+
+ private:
+ SystemConsumerTracingBackend();
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
+// gen_amalgamated begin header: include/perfetto/tracing/tracing_policy.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_
+#define INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_
+
+#include <functional>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/backend_type.h"
+
+namespace perfetto {
+
+// Applies policy decisions, such as allowing or denying connections, when
+// certain tracing SDK events occur. All methods are called on an internal
+// perfetto thread.
+class PERFETTO_EXPORT_COMPONENT TracingPolicy {
+ public:
+ virtual ~TracingPolicy();
+
+ // Called when the current process attempts to connect a new consumer to the
+ // backend of |backend_type| to check if the connection should be allowed. Its
+ // implementation should execute |result_callback| with the result of the
+ // check (synchronuosly or asynchronously on any thread). If the result is
+ // false, the consumer connection is aborted. Chrome uses this to restrict
+ // creating (system) tracing sessions based on an enterprise policy.
+ struct ShouldAllowConsumerSessionArgs {
+ BackendType backend_type;
+ std::function<void(bool /*allow*/)> result_callback;
+ };
+ virtual void ShouldAllowConsumerSession(
+ const ShouldAllowConsumerSessionArgs&) = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACING_H_
+#define INCLUDE_PERFETTO_TRACING_TRACING_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/backend_type.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/in_process_tracing_backend.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/system_tracing_backend.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_policy.h"
+
+namespace perfetto {
+
+namespace internal {
+class TracingMuxerImpl;
+}
+
+class TracingBackend;
+class Platform;
+class StartupTracingSession; // Declared below.
+class TracingSession; // Declared below.
+
+struct TracingError {
+ enum ErrorCode : uint32_t {
+ // Peer disconnection.
+ kDisconnected = 1,
+
+ // The Start() method failed. This is typically because errors in the passed
+ // TraceConfig. More details are available in |message|.
+ kTracingFailed = 2,
+ };
+
+ ErrorCode code;
+ std::string message;
+
+ TracingError(ErrorCode cd, std::string msg)
+ : code(cd), message(std::move(msg)) {
+ PERFETTO_CHECK(!message.empty());
+ }
+};
+
+using LogLev = ::perfetto::base::LogLev;
+using LogMessageCallbackArgs = ::perfetto::base::LogMessageCallbackArgs;
+using LogMessageCallback = ::perfetto::base::LogMessageCallback;
+
+struct TracingInitArgs {
+ uint32_t backends = 0; // One or more BackendTypes.
+ TracingBackend* custom_backend = nullptr; // [Optional].
+
+ // [Optional] Platform implementation. It allows the embedder to take control
+ // of platform-specific bits like thread creation and TLS slot handling. If
+ // not set it will use Platform::GetDefaultPlatform().
+ Platform* platform = nullptr;
+
+ // [Optional] Tune the size of the shared memory buffer between the current
+ // process and the service backend(s). This is a trade-off between memory
+ // footprint and the ability to sustain bursts of trace writes (see comments
+ // in shared_memory_abi.h).
+ // If set, the value must be a multiple of 4KB. The value can be ignored if
+ // larger than kMaxShmSize (32MB) or not a multiple of 4KB.
+ uint32_t shmem_size_hint_kb = 0;
+
+ // [Optional] Specifies the preferred size of each page in the shmem buffer.
+ // This is a trade-off between IPC overhead and fragmentation/efficiency of
+ // the shmem buffer in presence of multiple writer threads.
+ // Must be one of [4, 8, 16, 32].
+ uint32_t shmem_page_size_hint_kb = 0;
+
+ // [Optional] The length of the period during which shared-memory-buffer
+ // chunks that have been filled with data are accumulated (batched) on the
+ // producer side, before the service is notified of them over an out-of-band
+ // IPC call. If, while this period lasts, the shared memory buffer gets too
+ // full, the IPC call will be sent immediately. The value of this parameter is
+ // a trade-off between IPC traffic overhead and the ability to sustain bursts
+ // of trace writes. The higher the value, the more chunks will be batched and
+ // the less buffer space will be available to hide the latency of the service,
+ // and vice versa. For more details, see the SetBatchCommitsDuration method in
+ // shared_memory_arbiter.h.
+ //
+ // Note: With the default value of 0ms, batching still happens but with a zero
+ // delay, i.e. commits will be sent to the service at the next opportunity.
+ uint32_t shmem_batch_commits_duration_ms = 0;
+
+ // [Optional] Enables direct producer-side patching of chunks that have not
+ // yet been committed to the service. This flag will only have an effect
+ // if the service supports direct patching, otherwise it will be ignored.
+ bool shmem_direct_patching_enabled = false;
+
+ // [Optional] If set, the policy object is notified when certain SDK events
+ // occur and may apply policy decisions, such as denying connections. The
+ // embedder is responsible for ensuring the object remains alive for the
+ // lifetime of the process.
+ TracingPolicy* tracing_policy = nullptr;
+
+ // [Optional] If set, log messages generated by perfetto are passed to this
+ // callback instead of being logged directly.
+ LogMessageCallback log_message_callback = nullptr;
+
+ // When this flag is set to false, it overrides
+ // `DataSource::kSupportsMultipleInstances` for all the data sources.
+ // As a result when a tracing session is already running and if we attempt to
+ // start another session, it will fail to start the data source which were
+ // already active.
+ bool supports_multiple_data_source_instances = true;
+
+ // If this flag is set the default clock for taking timestamps is overridden
+ // with CLOCK_MONOTONIC (for use in Chrome).
+ bool use_monotonic_clock = false;
+
+ // If this flag is set the default clock for taking timestamps is overridden
+ // with CLOCK_MONOTONIC_RAW on platforms that support it.
+ bool use_monotonic_raw_clock = false;
+
+ // This flag can be set to false in order to avoid enabling the system
+ // consumer in Tracing::Initialize(), so that the linker can remove the unused
+ // consumer IPC implementation to reduce binary size. This setting only has an
+ // effect if kSystemBackend is specified in |backends|. When this option is
+ // false, Tracing::NewTrace() will instatiate the system backend only if
+ // explicitly specified as kSystemBackend: kUndefinedBackend will consider
+ // only already instantiated backends.
+ bool enable_system_consumer = true;
+
+ // When true, sets disallow_merging_with_system_tracks in TrackDescriptor,
+ // making sure that Trace Processor doesn't merge track event and system
+ // event tracks for the same thread.
+ bool disallow_merging_with_system_tracks = false;
+
+ // If set, this function will be called by the producer client to create a
+ // socket for connection to the system service. The function takes one
+ // argument: a callback that takes an open file descriptor. The function
+ // should create a socket with the name defined by
+ // perfetto::GetProducerSocket(), connect to it, and return the corresponding
+ // descriptor via the callback.
+ // This is intended for the use-case where a process being traced is run
+ // inside a sandbox and can't create sockets directly.
+ // Not yet supported for consumer connections currently.
+ CreateSocketAsync create_socket_async = nullptr;
+
+ protected:
+ friend class Tracing;
+ friend class internal::TracingMuxerImpl;
+
+ using BackendFactoryFunction = TracingBackend* (*)();
+ using ProducerBackendFactoryFunction = TracingProducerBackend* (*)();
+ using ConsumerBackendFactoryFunction = TracingConsumerBackend* (*)();
+
+ BackendFactoryFunction in_process_backend_factory_ = nullptr;
+ ProducerBackendFactoryFunction system_producer_backend_factory_ = nullptr;
+ ConsumerBackendFactoryFunction system_consumer_backend_factory_ = nullptr;
+ bool dcheck_is_on_ = PERFETTO_DCHECK_IS_ON();
+};
+
+// The entry-point for using perfetto.
+class PERFETTO_EXPORT_COMPONENT Tracing {
+ public:
+ // Initializes Perfetto with the given backends in the calling process and/or
+ // with a user-provided backend. It's possible to call this function more than
+ // once to initialize different backends. If a backend was already initialized
+ // the call will have no effect on it. All the members of `args` will be
+ // ignored in subsequent calls, except those require to initialize new
+ // backends (`backends`, `enable_system_consumer`, `shmem_size_hint_kb`,
+ // `shmem_page_size_hint_kb` and `shmem_batch_commits_duration_ms`).
+ static inline void Initialize(const TracingInitArgs& args)
+ PERFETTO_ALWAYS_INLINE {
+ TracingInitArgs args_copy(args);
+ // This code is inlined to allow dead-code elimination for unused backends.
+ // This saves ~200 KB when not using the in-process backend (b/148198993).
+ // The logic behind it is the following:
+ // Nothing other than the code below references the two GetInstance()
+ // methods. From a linker-graph viewpoint, those GetInstance() pull in many
+ // other pieces of the codebase (e.g. InProcessTracingBackend pulls the
+ // whole TracingServiceImpl, SystemTracingBackend pulls the whole //ipc
+ // layer). Due to the inline, the compiler can see through the code and
+ // realize that some branches are always not taken. When that happens, no
+ // reference to the backends' GetInstance() is emitted and that allows the
+ // linker GC to get rid of the entire set of dependencies.
+ if (args.backends & kInProcessBackend) {
+ args_copy.in_process_backend_factory_ =
+ &internal::InProcessTracingBackend::GetInstance;
+ }
+ if (args.backends & kSystemBackend) {
+ args_copy.system_producer_backend_factory_ =
+ &internal::SystemProducerTracingBackend::GetInstance;
+ if (args.enable_system_consumer) {
+ args_copy.system_consumer_backend_factory_ =
+ &internal::SystemConsumerTracingBackend::GetInstance;
+ }
+ }
+ InitializeInternal(args_copy);
+ }
+
+ // Checks if tracing has been initialized by calling |Initialize|.
+ static bool IsInitialized();
+
+ // Start a new tracing session using the given tracing backend. Use
+ // |kUnspecifiedBackend| to select an available backend automatically.
+ static PERFETTO_ALWAYS_INLINE inline std::unique_ptr<TracingSession> NewTrace(
+ BackendType backend = kUnspecifiedBackend);
+
+ // Shut down Perfetto, releasing any allocated OS resources (threads, files,
+ // sockets, etc.). Note that Perfetto cannot be reinitialized again in the
+ // same process[1]. Instead, this function is meant for shutting down all
+ // Perfetto-related code so that it can be safely unloaded, e.g., with
+ // dlclose().
+ //
+ // It is only safe to call this function when all threads recording trace
+ // events have been terminated or otherwise guaranteed to not make any further
+ // calls into Perfetto.
+ //
+ // [1] Unless static data is also cleared through other means.
+ static void Shutdown();
+
+ // Uninitialize Perfetto. Only exposed for testing scenarios where it can be
+ // guaranteed that no tracing sessions or other operations are happening when
+ // this call is made.
+ static void ResetForTesting();
+
+ // Start a new startup tracing session in the current process. Startup tracing
+ // can be used in anticipation of a session that will be started by the
+ // specified backend in the near future. The data source configs in the
+ // supplied TraceConfig have to (mostly) match those in the config that will
+ // later be provided by the backend.
+ // Learn more about config matching at ComputeStartupConfigHash.
+ //
+ // Note that startup tracing requires that either:
+ // (a) the service backend already has an SMB set up, or
+ // (b) the service backend to support producer-provided SMBs if the backend
+ // is not yet connected or no SMB has been set up yet
+ // (See `use_producer_provided_smb`). If necessary, the
+ // client library will briefly disconnect and reconnect the backend to
+ // supply an SMB to the backend. If the service does not accept the SMB,
+ // startup tracing will be aborted, but the service may still start the
+ // corresponding tracing session later.
+ //
+ // Startup tracing is NOT supported with the in-process backend. For this
+ // backend, you can just start a regular tracing session and block until it is
+ // set up instead.
+ //
+ // The client library will start the data sources instances specified in the
+ // config with a placeholder target buffer. Once the backend starts a matching
+ // tracing session, the session will resume as normal. If no matching session
+ // is started after a timeout (or the backend doesn't accept the
+ // producer-provided SMB), the startup tracing session will be aborted
+ // and the data source instances stopped.
+ struct OnStartupTracingSetupCallbackArgs {
+ int num_data_sources_started;
+ };
+ struct SetupStartupTracingOpts {
+ BackendType backend = kUnspecifiedBackend;
+ uint32_t timeout_ms = 10000;
+
+ // If set, this callback is executed (on an internal Perfetto thread) when
+ // startup tracing was set up.
+ std::function<void(OnStartupTracingSetupCallbackArgs)> on_setup;
+
+ // If set, this callback is executed (on an internal Perfetto thread) if any
+ // data sources were aborted, e.g. due to exceeding the timeout or as a
+ // response to Abort().
+ std::function<void()> on_aborted;
+
+ // If set, this callback is executed (on an internal Perfetto thread) after
+ // all data sources were adopted by a tracing session initiated by the
+ // backend.
+ std::function<void()> on_adopted;
+ };
+
+ static std::unique_ptr<StartupTracingSession> SetupStartupTracing(
+ const TraceConfig& config,
+ SetupStartupTracingOpts);
+
+ // Blocking version of above method, so callers can ensure that tracing is
+ // active before proceeding with app startup. Calls into
+ // DataSource::Trace() or trace macros right after this method are written
+ // into the startup session.
+ static std::unique_ptr<StartupTracingSession> SetupStartupTracingBlocking(
+ const TraceConfig& config,
+ SetupStartupTracingOpts);
+
+ // Informs the tracing services to activate any of these triggers if any
+ // tracing session was waiting for them.
+ //
+ // Sends the trigger signal to all the initialized backends that are currently
+ // connected and that connect in the next `ttl_ms` milliseconds (but
+ // returns immediately anyway).
+ static void ActivateTriggers(const std::vector<std::string>& triggers,
+ uint32_t ttl_ms);
+
+ private:
+ static void InitializeInternal(const TracingInitArgs&);
+ static std::unique_ptr<TracingSession> NewTraceInternal(
+ BackendType,
+ TracingConsumerBackend* (*system_backend_factory)());
+
+ Tracing() = delete;
+};
+
+class PERFETTO_EXPORT_COMPONENT TracingSession {
+ public:
+ virtual ~TracingSession();
+
+ // Configure the session passing the trace config.
+ // If a writable file handle is given through |fd|, the trace will
+ // automatically written to that file. Otherwise you should call ReadTrace()
+ // to retrieve the trace data. This call does not take ownership of |fd|.
+ // TODO(primiano): add an error callback.
+ virtual void Setup(const TraceConfig&, int fd = -1) = 0;
+
+ // Enable tracing asynchronously. Use SetOnStartCallback() to get a
+ // notification when the session has fully started.
+ virtual void Start() = 0;
+
+ // Enable tracing and block until tracing has started. Note that if data
+ // sources are registered after this call was initiated, the call may return
+ // before the additional data sources have started. Also, if other producers
+ // (e.g., with system-wide tracing) have registered data sources without start
+ // notification support, this call may return before those data sources have
+ // started.
+ virtual void StartBlocking() = 0;
+
+ // This callback will be invoked when all data sources have acknowledged that
+ // tracing has started. This callback will be invoked on an internal perfetto
+ // thread.
+ virtual void SetOnStartCallback(std::function<void()>) = 0;
+
+ // This callback can be used to get a notification when some error occurred
+ // (e.g., peer disconnection). Error type will be passed as an argument. This
+ // callback will be invoked on an internal perfetto thread.
+ virtual void SetOnErrorCallback(std::function<void(TracingError)>) = 0;
+
+ // Issues a flush request, asking all data sources to ack the request, within
+ // the specified timeout. A "flush" is a fence to ensure visibility of data in
+ // the async tracing pipeline. It guarantees that all data written before the
+ // Flush() call will be visible in the trace buffer and hence by the
+ // ReadTrace() / ReadTraceBlocking() methods.
+ // Args:
+ // callback: will be invoked on an internal perfetto thread when all data
+ // sources have acked, or the timeout is reached. The bool argument
+ // will be true if all data sources acked within the timeout, false if
+ // the timeout was hit or some other error occurred (e.g. the tracing
+ // session wasn't started or ended).
+ // timeout_ms: how much time the service will wait for data source acks. If
+ // 0, the global timeout specified in the TraceConfig (flush_timeout_ms)
+ // will be used. If flush_timeout_ms is also unspecified, a default value
+ // of 5s will be used.
+ // Known issues:
+ // Because flushing is still based on service-side scraping, the very last
+ // trace packet for each data source thread will not be visible. Fixing
+ // this requires either propagating the Flush() to the data sources or
+ // changing the order of atomic operations in the service (b/162206162).
+ // Until then, a workaround is to make sure to call
+ // DataSource::Trace([](TraceContext ctx) { ctx.Flush(); }) just before
+ // stopping, on each thread where DataSource::Trace has been previously
+ // called.
+ virtual void Flush(std::function<void(bool)>, uint32_t timeout_ms = 0) = 0;
+
+ // Blocking version of Flush(). Waits until all data sources have acked and
+ // returns the success/failure status.
+ bool FlushBlocking(uint32_t timeout_ms = 0);
+
+ // Disable tracing asynchronously.
+ // Use SetOnStopCallback() to get a notification when the tracing session is
+ // fully stopped and all data sources have acked.
+ virtual void Stop() = 0;
+
+ // Disable tracing and block until tracing has stopped.
+ virtual void StopBlocking() = 0;
+
+ // This callback will be invoked when tracing is disabled.
+ // This can happen either when explicitly calling TracingSession.Stop() or
+ // when the trace reaches its |duration_ms| time limit.
+ // This callback will be invoked on an internal perfetto thread.
+ virtual void SetOnStopCallback(std::function<void()>) = 0;
+
+ // Changes the TraceConfig for an active tracing session. The session must
+ // have been configured and started before. Note that the tracing service
+ // only supports changing a subset of TraceConfig fields,
+ // see ConsumerEndpoint::ChangeTraceConfig().
+ virtual void ChangeTraceConfig(const TraceConfig&) = 0;
+
+ // Struct passed as argument to the callback passed to ReadTrace().
+ // [data, size] is guaranteed to contain 1 or more full trace packets, which
+ // can be decoded using trace.proto. No partial or truncated packets are
+ // exposed. If the trace is empty this returns a zero-sized nullptr with
+ // |has_more| == true to signal EOF.
+ // This callback will be invoked on an internal perfetto thread.
+ struct ReadTraceCallbackArgs {
+ const char* data = nullptr;
+ size_t size = 0;
+
+ // When false, this will be the last invocation of the callback for this
+ // read cycle.
+ bool has_more = false;
+ };
+
+ // Reads back the trace data (raw protobuf-encoded bytes) asynchronously.
+ // Can be called at any point during the trace, typically but not necessarily,
+ // after stopping. If this is called before the end of the trace (i.e. before
+ // Stop() / StopBlocking()), in almost all cases you need to call
+ // Flush() / FlushBlocking() before Read(). This is to guarantee that tracing
+ // data in-flight in the data sources is committed into the tracing buffers
+ // before reading them.
+ // Reading the trace data is a destructive operation w.r.t. contents of the
+ // trace buffer and is not idempotent.
+ // A single ReadTrace() call can yield >1 callback invocations, until
+ // |has_more| is false.
+ using ReadTraceCallback = std::function<void(ReadTraceCallbackArgs)>;
+ virtual void ReadTrace(ReadTraceCallback) = 0;
+
+ // Synchronous version of ReadTrace(). It blocks the calling thread until all
+ // the trace contents are read. This is slow and inefficient (involves more
+ // copies) and is mainly intended for testing.
+ std::vector<char> ReadTraceBlocking();
+
+ // Struct passed as an argument to the callback for GetTraceStats(). Contains
+ // statistics about the tracing session.
+ struct GetTraceStatsCallbackArgs {
+ // Whether or not querying statistics succeeded.
+ bool success = false;
+ // Serialized TraceStats protobuf message. To decode:
+ //
+ // perfetto::protos::gen::TraceStats trace_stats;
+ // trace_stats.ParseFromArray(args.trace_stats_data.data(),
+ // args.trace_stats_data.size());
+ //
+ std::vector<uint8_t> trace_stats_data;
+ };
+
+ // Requests a snapshot of statistical data for this tracing session. Only one
+ // query may be active at a time. This callback will be invoked on an internal
+ // perfetto thread.
+ using GetTraceStatsCallback = std::function<void(GetTraceStatsCallbackArgs)>;
+ virtual void GetTraceStats(GetTraceStatsCallback) = 0;
+
+ // Synchronous version of GetTraceStats() for convenience.
+ GetTraceStatsCallbackArgs GetTraceStatsBlocking();
+
+ // Struct passed as an argument to the callback for QueryServiceState().
+ // Contains information about registered data sources.
+ struct QueryServiceStateCallbackArgs {
+ // Whether or not getting the service state succeeded.
+ bool success = false;
+ // Serialized TracingServiceState protobuf message. To decode:
+ //
+ // perfetto::protos::gen::TracingServiceState state;
+ // state.ParseFromArray(args.service_state_data.data(),
+ // args.service_state_data.size());
+ //
+ std::vector<uint8_t> service_state_data;
+ };
+
+ // Requests a snapshot of the tracing service state for this session. Only one
+ // request per session may be active at a time. This callback will be invoked
+ // on an internal perfetto thread.
+ using QueryServiceStateCallback =
+ std::function<void(QueryServiceStateCallbackArgs)>;
+ virtual void QueryServiceState(QueryServiceStateCallback) = 0;
+
+ // Synchronous version of QueryServiceState() for convenience.
+ QueryServiceStateCallbackArgs QueryServiceStateBlocking();
+};
+
+class PERFETTO_EXPORT_COMPONENT StartupTracingSession {
+ public:
+ // Note that destroying the StartupTracingSession object will not abort the
+ // startup session automatically. Call Abort() explicitly to do so.
+ virtual ~StartupTracingSession();
+
+ // Abort any active but still unbound data source instances that belong to
+ // this startup tracing session. Does not affect data source instances that
+ // were already bound to a service-controlled session.
+ virtual void Abort() = 0;
+
+ // Same as above, but blocks the current thread until aborted.
+ // Note some of the internal (non observable from public APIs) cleanup might
+ // be done even after this method returns.
+ virtual void AbortBlocking() = 0;
+};
+
+PERFETTO_ALWAYS_INLINE inline std::unique_ptr<TracingSession>
+Tracing::NewTrace(BackendType backend) {
+ // This code is inlined to allow dead-code elimination for unused consumer
+ // implementation. The logic behind it is the following:
+ // Nothing other than the code below references the GetInstance() method
+ // below. From a linker-graph viewpoint, those GetInstance() pull in many
+ // other pieces of the codebase (ConsumerOnlySystemTracingBackend pulls
+ // ConsumerIPCClient). Due to the inline, the compiler can see through the
+ // code and realize that some branches are always not taken. When that
+ // happens, no reference to the backends' GetInstance() is emitted and that
+ // allows the linker GC to get rid of the entire set of dependencies.
+ TracingConsumerBackend* (*system_backend_factory)();
+ system_backend_factory = nullptr;
+ // In case PERFETTO_IPC is disabled, a fake system backend is used, which
+ // always panics. NewTrace(kSystemBackend) should fail if PERFETTO_IPC is
+ // diabled, not panic.
+#if PERFETTO_BUILDFLAG(PERFETTO_IPC)
+ if (backend & kSystemBackend) {
+ system_backend_factory =
+ &internal::SystemConsumerTracingBackend::GetInstance;
+ }
+#endif
+ return NewTraceInternal(backend, system_backend_factory);
+}
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACING_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_PLATFORM_H_
+#define INCLUDE_PERFETTO_TRACING_PLATFORM_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/base/proc_utils.h"
+// gen_amalgamated expanded: #include "perfetto/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+} // namespace base
+
+// This abstract class is used to abstract dependencies on platform-specific
+// primitives that cannot be implemented by the perfetto codebase and must be
+// provided or overridden by the embedder.
+// This is, for instance, for cases where we want to use some particular
+// base:: class in Chrome and provide instead POSIX fallbacks for other
+// embedders.
+
+// Base class for thread-local objects. This is to get a basic object vtable and
+// delegate destruction to the embedder. See Platform::CreateThreadLocalObject.
+class PERFETTO_EXPORT_COMPONENT PlatformThreadLocalObject {
+ public:
+ // Implemented by perfetto internal code. The embedder must call this when
+ // implementing GetOrCreateThreadLocalObject() to create an instance for the
+ // first time on each thread.
+ static std::unique_ptr<PlatformThreadLocalObject> CreateInstance();
+ virtual ~PlatformThreadLocalObject();
+};
+
+class PERFETTO_EXPORT_COMPONENT Platform {
+ public:
+ // Embedders can use this unless they have custom needs (e.g. Chrome wanting
+ // to use its own base class for TLS).
+ static Platform* GetDefaultPlatform();
+
+ // Embedders can call this to set process ID in those cases where getpid()
+ // returns incorrect values (e.g. for sandboxed processes in Chromium).
+ // Should only be called once, before tracing has been initialized.
+ static void SetCurrentProcessId(base::PlatformProcessId process_id) {
+ PERFETTO_CHECK(!process_id_);
+ PERFETTO_DCHECK(!Tracing::IsInitialized());
+ process_id_ = process_id;
+ }
+
+ // Returns process ID previously set by SetCurrentProcessId, or the process
+ // ID provided by the OS if no custom ID was provided.
+ static base::PlatformProcessId GetCurrentProcessId() {
+ if (process_id_)
+ return process_id_;
+ return base::GetProcessId();
+ }
+
+ virtual ~Platform();
+
+ // Creates a thread-local object. The embedder must:
+ // - Create an instance per-thread calling ThreadLocalObject::CreateInstance.
+ // - Own the lifetime of the returned object as long as the thread is alive.
+ // - Destroy it when the thread exits.
+ // Perfetto requires only one thread-local object overall (obviously, one
+ // instance per-thread) from the embedder.
+ using ThreadLocalObject = ::perfetto::PlatformThreadLocalObject;
+ virtual ThreadLocalObject* GetOrCreateThreadLocalObject() = 0;
+
+ // Creates a sequenced task runner. The easiest implementation is to create
+ // a new thread (e.g. use base::ThreadTaskRunner) but this can also be
+ // implemented in some more clever way (e.g. using chromiums's scheduler).
+ struct CreateTaskRunnerArgs {
+ // Optional. Sets the name to the newly created task runner. In the default
+ // PosixPlatform implementation this causes a pthread_setname_np(). This is
+ // only for ease of debugging, it does not affect the tracing behavior.
+ std::string name_for_debugging;
+ };
+ virtual std::unique_ptr<base::TaskRunner> CreateTaskRunner(
+ const CreateTaskRunnerArgs&) = 0;
+
+ // Used to derive the producer name. Mostly relevant when using the
+ // kSystemBackend mode. It can be an arbitrary string when using the
+ // in-process mode.
+ virtual std::string GetCurrentProcessName() = 0;
+
+ // Tear down any persistent platform state (e.g., TLS variables). The platform
+ // interface must not be used after calling this function.
+ virtual void Shutdown();
+
+ // Returns the thread ID provided by the OS by default. Chromium uses
+ // different thread IDs on some platforms, so it needs the ability to
+ // override this method.
+ virtual base::PlatformThreadId GetCurrentThreadId();
+
+ private:
+ static base::PlatformProcessId process_id_;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_PLATFORM_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
+
+#include <array>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
+
+namespace perfetto {
+
+class TraceWriterBase;
+
+namespace internal {
+
+// Organization of the thread-local storage
+// ----------------------------------------
+// First of all, remember the cardinality of the problem: at any point in time
+// there are M data sources registered (i.e. number of subclasses of DataSource)
+// and up to N concurrent instances for each data source, so up to M * N total
+// data source instances around.
+// Each data source instance can be accessed by T threads (no upper bound).
+// We can safely put hard limits both to M and N (i.e. say that we support at
+// most 32 data source types per process and up to 8 concurrent instances).
+//
+// We want to make it so from the Platform viewpoint, we use only one global
+// TLS object, so T instances in total, one per thread, regardless of M and N.
+// This allows to deal with at-thread-exit destruction only in one place, rather
+// than N, M or M * N.
+//
+// Visually:
+// [ Thread 1 ] [ Thread 2 ] [ Thread T ]
+// +---------------+ +---------------+ +---------------+
+// Data source Foo | | | | | |
+// Instance 1 | TLS | | TLS | | TLS |
+// Instance 2 | Object | | Object | | Object |
+// Instance 3 | | | | | |
+// | | | | | |
+// Data source Bar | | | | | |
+// Instance 1 | | | | | |
+// Instance 2 | | | | | |
+// +---------------+ +---------------+ +---------------+
+//
+// Each TLS Object is organized as an array of M DataSourceThreadLocalState.
+// Each DSTLS itself is an array of up to N per-instance objects.
+// The only per-instance object for now is the TraceWriter.
+// So for each data source, for each instance, for each thread we keep one
+// TraceWriter.
+// The lookup is O(1): Given the TLS object, the TraceWriter is just tls[M][N].
+class TracingTLS : public Platform::ThreadLocalObject {
+ public:
+ ~TracingTLS() override;
+
+ // This is checked against TraceMuxerImpl's global generation counter to
+ // handle destruction of TraceWriter(s) that belong to data sources that
+ // have been stopped. When the two numbers diverge, a scan of all the
+ // thread-local TraceWriter(s) is issued.
+ uint32_t generation = 0;
+
+ // This flag is true while this thread is inside a trace point for any data
+ // source or in other delicate parts of the tracing machinery during which we
+ // should not try to trace. Used to prevent unexpected re-entrancy.
+ // This flag is also load-bearing when handling re-entrancy during thread-exit
+ // handlers. See comment in TracingTLS::~TracingTLS().
+ bool is_in_trace_point = false;
+
+ // Used inside a trace point (only one trace point per thread can be active at
+ // any time) to cache the instances bitmap.
+ uint32_t cached_instances = 0;
+
+ // By default all data source instances have independent thread-local state
+ // (see above).
+ std::array<DataSourceThreadLocalState, kMaxDataSources> data_sources_tls{};
+
+ // Track event data sources, however, share the same thread-local state in
+ // order to be able to share trace writers and interning state across all
+ // track event categories.
+ DataSourceThreadLocalState track_event_tls{};
+};
+
+struct ScopedReentrancyAnnotator {
+ ScopedReentrancyAnnotator(TracingTLS& root_tls) : root_tls_(root_tls) {
+ PERFETTO_DCHECK(!root_tls_.is_in_trace_point);
+ root_tls_.is_in_trace_point = true;
+ }
+ ~ScopedReentrancyAnnotator() { root_tls_.is_in_trace_point = false; }
+
+ private:
+ TracingTLS& root_tls_;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
+
+#include <atomic>
+#include <memory>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_tls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
+namespace perfetto {
+
+class DataSourceBase;
+class TraceWriterBase;
+struct TracingInitArgs;
+class TracingSession;
+
+namespace internal {
+
+struct DataSourceParams {
+ bool supports_multiple_instances;
+ bool requires_callbacks_under_lock;
+};
+
+struct DataSourceStaticState;
+
+// This class acts as a bridge between the public API methods and the
+// TracingBackend(s). It exposes a simplified view of the world to the API
+// methods, so that they don't have to care about the multiplicity of backends.
+// It handles all the bookkeeping to map data source instances and trace writers
+// to the various backends.
+// See tracing_muxer_impl.h for the full picture. This class contains only the
+// fewer fields and methods that need to be exposed to public/ headers. Fields
+// and methods that are required to implement them should go into
+// src/tracing/internal/tracing_muxer_impl.h instead: that one can pull in
+// perfetto headers outside of public, this one cannot.
+class PERFETTO_EXPORT_COMPONENT TracingMuxer {
+ public:
+ static TracingMuxer* Get() { return instance_; }
+
+ virtual ~TracingMuxer();
+
+ TracingTLS* GetOrCreateTracingTLS() {
+ return static_cast<TracingTLS*>(platform_->GetOrCreateThreadLocalObject());
+ }
+
+ // This method can fail and return false if trying to register more than
+ // kMaxDataSources types.
+ using DataSourceFactory = std::function<std::unique_ptr<DataSourceBase>()>;
+ virtual bool RegisterDataSource(const DataSourceDescriptor&,
+ DataSourceFactory,
+ DataSourceParams,
+ bool no_flush,
+ DataSourceStaticState*) = 0;
+
+ // Updates the DataSourceDescriptor for the DataSource.
+ virtual void UpdateDataSourceDescriptor(const DataSourceDescriptor&,
+ const DataSourceStaticState*) = 0;
+
+ // It identifies the right backend and forwards the call to it.
+ // The returned TraceWriter must be used within the same sequence (for most
+ // projects this means "same thread"). Alternatively the client needs to take
+ // care of using synchronization primitives to prevent concurrent accesses.
+ virtual std::unique_ptr<TraceWriterBase> CreateTraceWriter(
+ DataSourceStaticState*,
+ uint32_t data_source_instance_index,
+ DataSourceState*,
+ BufferExhaustedPolicy buffer_exhausted_policy) = 0;
+
+ virtual void DestroyStoppedTraceWritersForCurrentThread() = 0;
+
+ uint32_t generation(std::memory_order ord) { return generation_.load(ord); }
+
+ using InterceptorFactory = std::function<std::unique_ptr<InterceptorBase>()>;
+ virtual void RegisterInterceptor(const InterceptorDescriptor&,
+ InterceptorFactory,
+ InterceptorBase::TLSFactory,
+ InterceptorBase::TracePacketCallback) = 0;
+
+ // Informs the tracing services to activate any of these triggers if any
+ // tracing session was waiting for them.
+ //
+ // Sends the trigger signal to all the initialized backends that are currently
+ // connected and that connect in the next `ttl_ms` milliseconds (but returns
+ // immediately anyway).
+ virtual void ActivateTriggers(const std::vector<std::string>&,
+ uint32_t ttl_ms) = 0;
+
+ base::PlatformThreadId GetCurrentThreadId() {
+ return platform_->GetCurrentThreadId();
+ }
+
+ protected:
+ explicit TracingMuxer(Platform* platform) : platform_(platform) {}
+
+ static TracingMuxer* instance_;
+ Platform* const platform_ = nullptr;
+
+ // Incremented every time a data source is destroyed. See tracing_tls.h.
+ std::atomic<uint32_t> generation_{};
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_TYPE_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_TYPE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"
+
+namespace perfetto {
+namespace internal {
+
+// Represents a data source type (not an instance).
+//
+// All the static state of a DataSource<T> lives here (including
+// DataSourceStaticState).
+//
+// The C shared library API wrapper cannot use DataSource<T>, because it needs
+// to create new data source types at runtime, so it uses this directly.
+//
+// The main reason why this intermediate class exist is to decouple the
+// DataSourceStaticState from the specific DataSource<T>. The C API cannot
+// dynamically create template instances and it needs a way to decouple those at
+// runtime.
+class PERFETTO_EXPORT_COMPONENT DataSourceType {
+ public:
+ // Function pointer type used to create custom per instance thread local
+ // state.
+ using CreateCustomTlsFn =
+ DataSourceInstanceThreadLocalState::ObjectWithDeleter (*)(
+ DataSourceInstanceThreadLocalState* tls_inst,
+ uint32_t instance_index,
+ void* user_arg);
+ // Function pointer type used to create custom per instance thread local
+ // incremental state (which might be cleared periodically by the tracing
+ // service).
+ using CreateIncrementalStateFn =
+ DataSourceInstanceThreadLocalState::ObjectWithDeleter (*)(
+ DataSourceInstanceThreadLocalState* tls_inst,
+ uint32_t instance_index,
+ void* user_arg);
+
+ // Registers the data source type with the central tracing muxer.
+ // * `descriptor` is the data source protobuf descriptor.
+ // * `factory` is a std::function used to create instances of the data source
+ // type.
+ // * `buffer_exhausted_policy` specifies what to do when the shared memory
+ // buffer runs out of chunks.
+ // * `create_custom_tls_fn` and `create_incremental_state_fn` are function
+ // pointers called to create custom state. They will receive `user_arg` as
+ // an extra param.
+ bool Register(const DataSourceDescriptor& descriptor,
+ TracingMuxer::DataSourceFactory factory,
+ internal::DataSourceParams params,
+ BufferExhaustedPolicy buffer_exhausted_policy,
+ bool no_flush,
+ CreateCustomTlsFn create_custom_tls_fn,
+ CreateIncrementalStateFn create_incremental_state_fn,
+ void* user_arg) {
+ buffer_exhausted_policy_ = buffer_exhausted_policy;
+ create_custom_tls_fn_ = create_custom_tls_fn;
+ create_incremental_state_fn_ = create_incremental_state_fn;
+ user_arg_ = user_arg;
+ auto* tracing_impl = TracingMuxer::Get();
+ return tracing_impl->RegisterDataSource(descriptor, factory, params,
+ no_flush, &state_);
+ }
+
+ // Updates the data source type descriptor.
+ void UpdateDescriptor(const DataSourceDescriptor& descriptor) {
+ auto* tracing_impl = TracingMuxer::Get();
+ tracing_impl->UpdateDataSourceDescriptor(descriptor, &state_);
+ }
+
+ // The beginning of a trace point.
+ //
+ // `tls_state` must point to a thread local variable that caches a pointer to
+ // an internal per data source type thread local state.
+ //
+ // `instances` must point to a copy of the current active instances for the
+ // data source type.
+ //
+ // `DataSourceTraits` can be used to customize the thread local storage used
+ // for the data source type.
+ //
+ // `TracePointTraits` and `trace_point_data` are customization point for
+ // getting the active instances bitmap.
+ //
+ // If this returns false, the trace point must be skipped.
+ template <typename DataSourceTraits, typename TracePointTraits>
+ bool TracePrologue(
+ DataSourceThreadLocalState** tls_state,
+ uint32_t* instances,
+ typename TracePointTraits::TracePointData trace_point_data) {
+ // See tracing_muxer.h for the structure of the TLS.
+ if (PERFETTO_UNLIKELY(!*tls_state)) {
+ *tls_state = GetOrCreateDataSourceTLS<DataSourceTraits>();
+ // If the TLS hasn't been obtained yet, it's possible that this thread
+ // hasn't observed the initialization of global state like the muxer yet.
+ // To ensure that the thread "sees" the effects of such initialization,
+ // we have to reload |instances| with an acquire fence, ensuring that any
+ // initialization performed before instances was updated is visible
+ // in this thread.
+ *instances &= TracePointTraits::GetActiveInstances(trace_point_data)
+ ->load(std::memory_order_acquire);
+ if (!*instances)
+ return false;
+ }
+ auto* tracing_impl = TracingMuxer::Get();
+
+ // Avoid re-entering the trace point recursively.
+ if (PERFETTO_UNLIKELY((*tls_state)->root_tls->is_in_trace_point))
+ return false;
+
+ (*tls_state)->root_tls->is_in_trace_point = true;
+
+ // TracingTLS::generation is a global monotonic counter that is incremented
+ // every time a tracing session is stopped. We use that as a signal to force
+ // a slow-path garbage collection of all the trace writers for the current
+ // thread and to destroy the ones that belong to tracing sessions that have
+ // ended. This is to avoid having too many TraceWriter instances alive, each
+ // holding onto one chunk of the shared memory buffer.
+ // Rationale why memory_order_relaxed should be fine:
+ // - The TraceWriter object that we use is always constructed and destructed
+ // on the current thread. There is no risk of accessing a half-initialized
+ // TraceWriter (which would be really bad).
+ // - In the worst case, in the case of a race on the generation check, we
+ // might end up using a TraceWriter for the same data source that belongs
+ // to a stopped session. This is not really wrong, as we don't give any
+ // guarantee on the global atomicity of the stop. In the worst case the
+ // service will reject the data commit if this arrives too late.
+
+ if (PERFETTO_UNLIKELY(
+ (*tls_state)->root_tls->generation !=
+ tracing_impl->generation(std::memory_order_relaxed))) {
+ // Will update root_tls->generation.
+ tracing_impl->DestroyStoppedTraceWritersForCurrentThread();
+ }
+
+ return true;
+ }
+
+ // Must be called at the ending of a trace point that was not skipped.
+ void TraceEpilogue(DataSourceThreadLocalState* tls_state) {
+ tls_state->root_tls->is_in_trace_point = false;
+ }
+
+ struct InstancesIterator {
+ // A bitmap of the currenly active instances.
+ uint32_t cached_instances;
+ // The current instance index.
+ uint32_t i;
+ // The current instance. If this is `nullptr`, the iteration is over.
+ DataSourceInstanceThreadLocalState* instance;
+ };
+
+ // Returns an iterator to the active instances of this data source type.
+ //
+ // `cached_instances` is a copy of the bitmap of the active instances for this
+ // data source type (usually just a copy of ValidInstances(), but can be
+ // customized).
+ //
+ // `tls_state` is the thread local pointer obtained from TracePrologue.
+ //
+ // `TracePointTraits` and `trace_point_data` are customization point for
+ // getting the active instances bitmap.
+ template <typename TracePointTraits>
+ InstancesIterator BeginIteration(
+ uint32_t cached_instances,
+ DataSourceThreadLocalState* tls_state,
+ typename TracePointTraits::TracePointData trace_point_data) {
+ InstancesIterator it{};
+ it.cached_instances = cached_instances;
+ FirstActiveInstance<TracePointTraits>(&it, tls_state, trace_point_data);
+ return it;
+ }
+
+ // Advances `*iterator` to point to the next active instance of this data
+ // source type.
+ //
+ // `tls_state` is the thread local pointer obtained from TracePrologue.
+ //
+ // `TracePointTraits` and `trace_point_data` are customization point for
+ // getting the active instances bitmap.
+ template <typename TracePointTraits>
+ void NextIteration(
+ InstancesIterator* iterator,
+ DataSourceThreadLocalState* tls_state,
+ typename TracePointTraits::TracePointData trace_point_data) {
+ iterator->i++;
+ FirstActiveInstance<TracePointTraits>(iterator, tls_state,
+ trace_point_data);
+ }
+
+ void* GetIncrementalState(
+ internal::DataSourceInstanceThreadLocalState* tls_inst,
+ uint32_t instance_index) {
+ // Recreate incremental state data if it has been reset by the service.
+ if (tls_inst->incremental_state_generation !=
+ static_state()->incremental_state_generation.load(
+ std::memory_order_relaxed)) {
+ tls_inst->incremental_state.reset();
+ CreateIncrementalState(tls_inst, instance_index);
+ }
+ return tls_inst->incremental_state.get();
+ }
+
+ std::atomic<uint32_t>* valid_instances() { return &state_.valid_instances; }
+
+ DataSourceStaticState* static_state() { return &state_; }
+
+ private:
+ void CreateIncrementalState(
+ internal::DataSourceInstanceThreadLocalState* tls_inst,
+ uint32_t instance_index) {
+ PERFETTO_DCHECK(create_incremental_state_fn_ != nullptr);
+ tls_inst->incremental_state =
+ create_incremental_state_fn_(tls_inst, instance_index, user_arg_);
+ tls_inst->incremental_state_generation =
+ static_state()->incremental_state_generation.load(
+ std::memory_order_relaxed);
+ }
+
+ void PopulateTlsInst(DataSourceInstanceThreadLocalState* tls_inst,
+ DataSourceState* instance_state,
+ uint32_t instance_index);
+
+ // Advances `*iterator` to the first active instance whose index is greater or
+ // equal than `iterator->i`.
+ template <typename TracePointTraits>
+ void FirstActiveInstance(
+ InstancesIterator* iterator,
+ DataSourceThreadLocalState* tls_state,
+ typename TracePointTraits::TracePointData trace_point_data) {
+ iterator->instance = nullptr;
+ for (; iterator->i < kMaxDataSourceInstances; iterator->i++) {
+ DataSourceState* instance_state =
+ state_.TryGetCached(iterator->cached_instances, iterator->i);
+ if (!instance_state)
+ continue;
+ // Even if we passed the check above, the DataSourceInstance might be
+ // still destroyed concurrently while this code runs. The code below is
+ // designed to deal with such race, as follows:
+ // - We don't access the user-defined data source instance state. The only
+ // bits of state we use are |backend_id| and |buffer_id|.
+ // - Beyond those two integers, we access only the TraceWriter here. The
+ // TraceWriter is always safe because it lives on the TLS.
+ // - |instance_state| is backed by static storage, so the pointer is
+ // always valid, even after the data source instance is destroyed.
+ // - In the case of a race-on-destruction, we'll still see the latest
+ // backend_id and buffer_id and in the worst case keep trying writing
+ // into the tracing shared memory buffer after stopped. But this isn't
+ // really any worse than the case of the stop IPC being delayed by the
+ // kernel scheduler. The tracing service is robust against data commit
+ // attemps made after tracing is stopped.
+ // There is a theoretical race that would case the wrong behavior w.r.t
+ // writing data in the wrong buffer, but it's so rare that we ignore it:
+ // if the data source is stopped and started kMaxDataSourceInstances
+ // times (so that the same id is recycled) while we are in this function,
+ // we might end up reusing the old data source's backend_id and buffer_id
+ // for the new one, because we don't see the generation change past this
+ // point. But stopping and starting tracing (even once) takes so much
+ // handshaking to make this extremely unrealistic.
+
+ auto& tls_inst = tls_state->per_instance[iterator->i];
+ if (PERFETTO_UNLIKELY(!tls_inst.trace_writer)) {
+ // Here we need an acquire barrier, which matches the release-store made
+ // by TracingMuxerImpl::SetupDataSource(), to ensure that the backend_id
+ // and buffer_id are consistent.
+ iterator->cached_instances &=
+ TracePointTraits::GetActiveInstances(trace_point_data)
+ ->load(std::memory_order_acquire);
+ instance_state =
+ state_.TryGetCached(iterator->cached_instances, iterator->i);
+ if (!instance_state || !instance_state->trace_lambda_enabled.load(
+ std::memory_order_relaxed))
+ continue;
+ PopulateTlsInst(&tls_inst, instance_state, iterator->i);
+ }
+ iterator->instance = &tls_inst;
+ break;
+ }
+ }
+
+ // Note that the returned object is one per-thread per-data-source-type, NOT
+ // per data-source *instance*.
+ template <typename DataSourceTraits>
+ DataSourceThreadLocalState* GetOrCreateDataSourceTLS() {
+ auto* tracing_impl = TracingMuxer::Get();
+ TracingTLS* root_tls = tracing_impl->GetOrCreateTracingTLS();
+ DataSourceThreadLocalState* ds_tls =
+ DataSourceTraits::GetDataSourceTLS(&state_, root_tls);
+ // We keep re-initializing as the initialization is idempotent and not worth
+ // the code for extra checks. Also, ds_tls->static_state might point to
+ // another data source if ResetForTesting() has been used.
+ ds_tls->static_state = &state_;
+ assert(!ds_tls->root_tls || ds_tls->root_tls == root_tls);
+ ds_tls->root_tls = root_tls;
+ return ds_tls;
+ }
+
+ DataSourceStaticState state_;
+ BufferExhaustedPolicy buffer_exhausted_policy_{};
+ CreateCustomTlsFn create_custom_tls_fn_ = nullptr;
+ CreateIncrementalStateFn create_incremental_state_fn_ = nullptr;
+ // User defined pointer that carries extra content for the fn_ callbacks
+ // above. Only used in the C shared library.
+ void* user_arg_ = nullptr;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_TYPE_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/trace_packet.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidCameraFrameEvent;
+class AndroidCameraSessionStats;
+class AndroidEnergyEstimationBreakdown;
+class AndroidGameInterventionList;
+class AndroidInputEvent;
+class AndroidLogPacket;
+class AndroidSystemProperty;
+class BatteryCounters;
+class ChromeBenchmarkMetadata;
+class ChromeEventBundle;
+class ChromeMetadataPacket;
+class ClockSnapshot;
+class CpuInfo;
+class DeobfuscationMapping;
+class EntityStateResidency;
+class EtwTraceEventBundle;
+class ExtensionDescriptor;
+class FrameTimelineEvent;
+class FtraceEventBundle;
+class FtraceStats;
+class GpuCounterEvent;
+class GpuLog;
+class GpuMemTotalEvent;
+class GpuRenderStageEvent;
+class GraphicsFrameEvent;
+class HeapGraph;
+class InitialDisplayState;
+class InodeFileMap;
+class InternedData;
+class LayersSnapshotProto;
+class MemoryTrackerSnapshot;
+class ModuleSymbols;
+class NetworkPacketBundle;
+class NetworkPacketEvent;
+class PackagesList;
+class PerfSample;
+class PerfettoMetatrace;
+class PowerRails;
+class ProcessDescriptor;
+class ProcessStats;
+class ProcessTree;
+class ProfilePacket;
+class ProfiledFrameSymbols;
+class ProtoLogMessage;
+class ProtoLogViewerConfig;
+class RemoteClockSync;
+class ShellHandlerMappings;
+class ShellTransition;
+class SmapsPacket;
+class StatsdAtom;
+class StreamingAllocation;
+class StreamingFree;
+class StreamingProfilePacket;
+class SysStats;
+class SystemInfo;
+class TestEvent;
+class ThreadDescriptor;
+class TraceConfig;
+class TracePacketDefaults;
+class TraceStats;
+class TraceUuid;
+class TracingServiceEvent;
+class TrackDescriptor;
+class TrackEvent;
+class TrackEventRangeOfInterest;
+class TransactionTraceEntry;
+class TranslationTable;
+class Trigger;
+class UiState;
+class V8CodeMove;
+class V8InternalCode;
+class V8JsCode;
+class V8RegExpCode;
+class V8WasmCode;
+class VulkanApiEvent;
+class VulkanMemoryEvent;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_TracePacket {
+enum SequenceFlags : int32_t {
+ SEQ_UNSPECIFIED = 0,
+ SEQ_INCREMENTAL_STATE_CLEARED = 1,
+ SEQ_NEEDS_INCREMENTAL_STATE = 2,
+};
+} // namespace perfetto_pbzero_enum_TracePacket
+using TracePacket_SequenceFlags = perfetto_pbzero_enum_TracePacket::SequenceFlags;
+
+
+constexpr TracePacket_SequenceFlags TracePacket_SequenceFlags_MIN = TracePacket_SequenceFlags::SEQ_UNSPECIFIED;
+constexpr TracePacket_SequenceFlags TracePacket_SequenceFlags_MAX = TracePacket_SequenceFlags::SEQ_NEEDS_INCREMENTAL_STATE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TracePacket_SequenceFlags_Name(::perfetto::protos::pbzero::TracePacket_SequenceFlags value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TracePacket_SequenceFlags::SEQ_UNSPECIFIED:
+ return "SEQ_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TracePacket_SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED:
+ return "SEQ_INCREMENTAL_STATE_CLEARED";
+
+ case ::perfetto::protos::pbzero::TracePacket_SequenceFlags::SEQ_NEEDS_INCREMENTAL_STATE:
+ return "SEQ_NEEDS_INCREMENTAL_STATE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class TracePacket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/900, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TracePacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracePacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracePacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timestamp() const { return at<8>().valid(); }
+ uint64_t timestamp() const { return at<8>().as_uint64(); }
+ bool has_timestamp_clock_id() const { return at<58>().valid(); }
+ uint32_t timestamp_clock_id() const { return at<58>().as_uint32(); }
+ bool has_process_tree() const { return at<2>().valid(); }
+ ::protozero::ConstBytes process_tree() const { return at<2>().as_bytes(); }
+ bool has_process_stats() const { return at<9>().valid(); }
+ ::protozero::ConstBytes process_stats() const { return at<9>().as_bytes(); }
+ bool has_inode_file_map() const { return at<4>().valid(); }
+ ::protozero::ConstBytes inode_file_map() const { return at<4>().as_bytes(); }
+ bool has_chrome_events() const { return at<5>().valid(); }
+ ::protozero::ConstBytes chrome_events() const { return at<5>().as_bytes(); }
+ bool has_clock_snapshot() const { return at<6>().valid(); }
+ ::protozero::ConstBytes clock_snapshot() const { return at<6>().as_bytes(); }
+ bool has_sys_stats() const { return at<7>().valid(); }
+ ::protozero::ConstBytes sys_stats() const { return at<7>().as_bytes(); }
+ bool has_track_event() const { return at<11>().valid(); }
+ ::protozero::ConstBytes track_event() const { return at<11>().as_bytes(); }
+ bool has_trace_uuid() const { return at<89>().valid(); }
+ ::protozero::ConstBytes trace_uuid() const { return at<89>().as_bytes(); }
+ bool has_trace_config() const { return at<33>().valid(); }
+ ::protozero::ConstBytes trace_config() const { return at<33>().as_bytes(); }
+ bool has_ftrace_stats() const { return at<34>().valid(); }
+ ::protozero::ConstBytes ftrace_stats() const { return at<34>().as_bytes(); }
+ bool has_trace_stats() const { return at<35>().valid(); }
+ ::protozero::ConstBytes trace_stats() const { return at<35>().as_bytes(); }
+ bool has_profile_packet() const { return at<37>().valid(); }
+ ::protozero::ConstBytes profile_packet() const { return at<37>().as_bytes(); }
+ bool has_streaming_allocation() const { return at<74>().valid(); }
+ ::protozero::ConstBytes streaming_allocation() const { return at<74>().as_bytes(); }
+ bool has_streaming_free() const { return at<75>().valid(); }
+ ::protozero::ConstBytes streaming_free() const { return at<75>().as_bytes(); }
+ bool has_battery() const { return at<38>().valid(); }
+ ::protozero::ConstBytes battery() const { return at<38>().as_bytes(); }
+ bool has_power_rails() const { return at<40>().valid(); }
+ ::protozero::ConstBytes power_rails() const { return at<40>().as_bytes(); }
+ bool has_android_log() const { return at<39>().valid(); }
+ ::protozero::ConstBytes android_log() const { return at<39>().as_bytes(); }
+ bool has_system_info() const { return at<45>().valid(); }
+ ::protozero::ConstBytes system_info() const { return at<45>().as_bytes(); }
+ bool has_trigger() const { return at<46>().valid(); }
+ ::protozero::ConstBytes trigger() const { return at<46>().as_bytes(); }
+ bool has_packages_list() const { return at<47>().valid(); }
+ ::protozero::ConstBytes packages_list() const { return at<47>().as_bytes(); }
+ bool has_chrome_benchmark_metadata() const { return at<48>().valid(); }
+ ::protozero::ConstBytes chrome_benchmark_metadata() const { return at<48>().as_bytes(); }
+ bool has_perfetto_metatrace() const { return at<49>().valid(); }
+ ::protozero::ConstBytes perfetto_metatrace() const { return at<49>().as_bytes(); }
+ bool has_chrome_metadata() const { return at<51>().valid(); }
+ ::protozero::ConstBytes chrome_metadata() const { return at<51>().as_bytes(); }
+ bool has_gpu_counter_event() const { return at<52>().valid(); }
+ ::protozero::ConstBytes gpu_counter_event() const { return at<52>().as_bytes(); }
+ bool has_gpu_render_stage_event() const { return at<53>().valid(); }
+ ::protozero::ConstBytes gpu_render_stage_event() const { return at<53>().as_bytes(); }
+ bool has_streaming_profile_packet() const { return at<54>().valid(); }
+ ::protozero::ConstBytes streaming_profile_packet() const { return at<54>().as_bytes(); }
+ bool has_heap_graph() const { return at<56>().valid(); }
+ ::protozero::ConstBytes heap_graph() const { return at<56>().as_bytes(); }
+ bool has_graphics_frame_event() const { return at<57>().valid(); }
+ ::protozero::ConstBytes graphics_frame_event() const { return at<57>().as_bytes(); }
+ bool has_vulkan_memory_event() const { return at<62>().valid(); }
+ ::protozero::ConstBytes vulkan_memory_event() const { return at<62>().as_bytes(); }
+ bool has_gpu_log() const { return at<63>().valid(); }
+ ::protozero::ConstBytes gpu_log() const { return at<63>().as_bytes(); }
+ bool has_vulkan_api_event() const { return at<65>().valid(); }
+ ::protozero::ConstBytes vulkan_api_event() const { return at<65>().as_bytes(); }
+ bool has_perf_sample() const { return at<66>().valid(); }
+ ::protozero::ConstBytes perf_sample() const { return at<66>().as_bytes(); }
+ bool has_cpu_info() const { return at<67>().valid(); }
+ ::protozero::ConstBytes cpu_info() const { return at<67>().as_bytes(); }
+ bool has_smaps_packet() const { return at<68>().valid(); }
+ ::protozero::ConstBytes smaps_packet() const { return at<68>().as_bytes(); }
+ bool has_service_event() const { return at<69>().valid(); }
+ ::protozero::ConstBytes service_event() const { return at<69>().as_bytes(); }
+ bool has_initial_display_state() const { return at<70>().valid(); }
+ ::protozero::ConstBytes initial_display_state() const { return at<70>().as_bytes(); }
+ bool has_gpu_mem_total_event() const { return at<71>().valid(); }
+ ::protozero::ConstBytes gpu_mem_total_event() const { return at<71>().as_bytes(); }
+ bool has_memory_tracker_snapshot() const { return at<73>().valid(); }
+ ::protozero::ConstBytes memory_tracker_snapshot() const { return at<73>().as_bytes(); }
+ bool has_frame_timeline_event() const { return at<76>().valid(); }
+ ::protozero::ConstBytes frame_timeline_event() const { return at<76>().as_bytes(); }
+ bool has_android_energy_estimation_breakdown() const { return at<77>().valid(); }
+ ::protozero::ConstBytes android_energy_estimation_breakdown() const { return at<77>().as_bytes(); }
+ bool has_ui_state() const { return at<78>().valid(); }
+ ::protozero::ConstBytes ui_state() const { return at<78>().as_bytes(); }
+ bool has_android_camera_frame_event() const { return at<80>().valid(); }
+ ::protozero::ConstBytes android_camera_frame_event() const { return at<80>().as_bytes(); }
+ bool has_android_camera_session_stats() const { return at<81>().valid(); }
+ ::protozero::ConstBytes android_camera_session_stats() const { return at<81>().as_bytes(); }
+ bool has_translation_table() const { return at<82>().valid(); }
+ ::protozero::ConstBytes translation_table() const { return at<82>().as_bytes(); }
+ bool has_android_game_intervention_list() const { return at<83>().valid(); }
+ ::protozero::ConstBytes android_game_intervention_list() const { return at<83>().as_bytes(); }
+ bool has_statsd_atom() const { return at<84>().valid(); }
+ ::protozero::ConstBytes statsd_atom() const { return at<84>().as_bytes(); }
+ bool has_android_system_property() const { return at<86>().valid(); }
+ ::protozero::ConstBytes android_system_property() const { return at<86>().as_bytes(); }
+ bool has_entity_state_residency() const { return at<91>().valid(); }
+ ::protozero::ConstBytes entity_state_residency() const { return at<91>().as_bytes(); }
+ bool has_profiled_frame_symbols() const { return at<55>().valid(); }
+ ::protozero::ConstBytes profiled_frame_symbols() const { return at<55>().as_bytes(); }
+ bool has_module_symbols() const { return at<61>().valid(); }
+ ::protozero::ConstBytes module_symbols() const { return at<61>().as_bytes(); }
+ bool has_deobfuscation_mapping() const { return at<64>().valid(); }
+ ::protozero::ConstBytes deobfuscation_mapping() const { return at<64>().as_bytes(); }
+ bool has_track_descriptor() const { return at<60>().valid(); }
+ ::protozero::ConstBytes track_descriptor() const { return at<60>().as_bytes(); }
+ bool has_process_descriptor() const { return at<43>().valid(); }
+ ::protozero::ConstBytes process_descriptor() const { return at<43>().as_bytes(); }
+ bool has_thread_descriptor() const { return at<44>().valid(); }
+ ::protozero::ConstBytes thread_descriptor() const { return at<44>().as_bytes(); }
+ bool has_ftrace_events() const { return at<1>().valid(); }
+ ::protozero::ConstBytes ftrace_events() const { return at<1>().as_bytes(); }
+ bool has_synchronization_marker() const { return at<36>().valid(); }
+ ::protozero::ConstBytes synchronization_marker() const { return at<36>().as_bytes(); }
+ bool has_compressed_packets() const { return at<50>().valid(); }
+ ::protozero::ConstBytes compressed_packets() const { return at<50>().as_bytes(); }
+ bool has_extension_descriptor() const { return at<72>().valid(); }
+ ::protozero::ConstBytes extension_descriptor() const { return at<72>().as_bytes(); }
+ bool has_network_packet() const { return at<88>().valid(); }
+ ::protozero::ConstBytes network_packet() const { return at<88>().as_bytes(); }
+ bool has_network_packet_bundle() const { return at<92>().valid(); }
+ ::protozero::ConstBytes network_packet_bundle() const { return at<92>().as_bytes(); }
+ bool has_track_event_range_of_interest() const { return at<90>().valid(); }
+ ::protozero::ConstBytes track_event_range_of_interest() const { return at<90>().as_bytes(); }
+ bool has_surfaceflinger_layers_snapshot() const { return at<93>().valid(); }
+ ::protozero::ConstBytes surfaceflinger_layers_snapshot() const { return at<93>().as_bytes(); }
+ bool has_surfaceflinger_transactions() const { return at<94>().valid(); }
+ ::protozero::ConstBytes surfaceflinger_transactions() const { return at<94>().as_bytes(); }
+ bool has_shell_transition() const { return at<96>().valid(); }
+ ::protozero::ConstBytes shell_transition() const { return at<96>().as_bytes(); }
+ bool has_shell_handler_mappings() const { return at<97>().valid(); }
+ ::protozero::ConstBytes shell_handler_mappings() const { return at<97>().as_bytes(); }
+ bool has_protolog_message() const { return at<104>().valid(); }
+ ::protozero::ConstBytes protolog_message() const { return at<104>().as_bytes(); }
+ bool has_protolog_viewer_config() const { return at<105>().valid(); }
+ ::protozero::ConstBytes protolog_viewer_config() const { return at<105>().as_bytes(); }
+ bool has_etw_events() const { return at<95>().valid(); }
+ ::protozero::ConstBytes etw_events() const { return at<95>().as_bytes(); }
+ bool has_v8_js_code() const { return at<99>().valid(); }
+ ::protozero::ConstBytes v8_js_code() const { return at<99>().as_bytes(); }
+ bool has_v8_internal_code() const { return at<100>().valid(); }
+ ::protozero::ConstBytes v8_internal_code() const { return at<100>().as_bytes(); }
+ bool has_v8_wasm_code() const { return at<101>().valid(); }
+ ::protozero::ConstBytes v8_wasm_code() const { return at<101>().as_bytes(); }
+ bool has_v8_reg_exp_code() const { return at<102>().valid(); }
+ ::protozero::ConstBytes v8_reg_exp_code() const { return at<102>().as_bytes(); }
+ bool has_v8_code_move() const { return at<103>().valid(); }
+ ::protozero::ConstBytes v8_code_move() const { return at<103>().as_bytes(); }
+ bool has_android_input_event() const { return at<106>().valid(); }
+ ::protozero::ConstBytes android_input_event() const { return at<106>().as_bytes(); }
+ bool has_remote_clock_sync() const { return at<107>().valid(); }
+ ::protozero::ConstBytes remote_clock_sync() const { return at<107>().as_bytes(); }
+ bool has_for_testing() const { return at<900>().valid(); }
+ ::protozero::ConstBytes for_testing() const { return at<900>().as_bytes(); }
+ bool has_trusted_uid() const { return at<3>().valid(); }
+ int32_t trusted_uid() const { return at<3>().as_int32(); }
+ bool has_trusted_packet_sequence_id() const { return at<10>().valid(); }
+ uint32_t trusted_packet_sequence_id() const { return at<10>().as_uint32(); }
+ bool has_trusted_pid() const { return at<79>().valid(); }
+ int32_t trusted_pid() const { return at<79>().as_int32(); }
+ bool has_interned_data() const { return at<12>().valid(); }
+ ::protozero::ConstBytes interned_data() const { return at<12>().as_bytes(); }
+ bool has_sequence_flags() const { return at<13>().valid(); }
+ uint32_t sequence_flags() const { return at<13>().as_uint32(); }
+ bool has_incremental_state_cleared() const { return at<41>().valid(); }
+ bool incremental_state_cleared() const { return at<41>().as_bool(); }
+ bool has_trace_packet_defaults() const { return at<59>().valid(); }
+ ::protozero::ConstBytes trace_packet_defaults() const { return at<59>().as_bytes(); }
+ bool has_previous_packet_dropped() const { return at<42>().valid(); }
+ bool previous_packet_dropped() const { return at<42>().as_bool(); }
+ bool has_first_packet_on_sequence() const { return at<87>().valid(); }
+ bool first_packet_on_sequence() const { return at<87>().as_bool(); }
+ bool has_machine_id() const { return at<98>().valid(); }
+ uint32_t machine_id() const { return at<98>().as_uint32(); }
+};
+
+class TracePacket : public ::protozero::Message {
+ public:
+ using Decoder = TracePacket_Decoder;
+ enum : int32_t {
+ kTimestampFieldNumber = 8,
+ kTimestampClockIdFieldNumber = 58,
+ kProcessTreeFieldNumber = 2,
+ kProcessStatsFieldNumber = 9,
+ kInodeFileMapFieldNumber = 4,
+ kChromeEventsFieldNumber = 5,
+ kClockSnapshotFieldNumber = 6,
+ kSysStatsFieldNumber = 7,
+ kTrackEventFieldNumber = 11,
+ kTraceUuidFieldNumber = 89,
+ kTraceConfigFieldNumber = 33,
+ kFtraceStatsFieldNumber = 34,
+ kTraceStatsFieldNumber = 35,
+ kProfilePacketFieldNumber = 37,
+ kStreamingAllocationFieldNumber = 74,
+ kStreamingFreeFieldNumber = 75,
+ kBatteryFieldNumber = 38,
+ kPowerRailsFieldNumber = 40,
+ kAndroidLogFieldNumber = 39,
+ kSystemInfoFieldNumber = 45,
+ kTriggerFieldNumber = 46,
+ kPackagesListFieldNumber = 47,
+ kChromeBenchmarkMetadataFieldNumber = 48,
+ kPerfettoMetatraceFieldNumber = 49,
+ kChromeMetadataFieldNumber = 51,
+ kGpuCounterEventFieldNumber = 52,
+ kGpuRenderStageEventFieldNumber = 53,
+ kStreamingProfilePacketFieldNumber = 54,
+ kHeapGraphFieldNumber = 56,
+ kGraphicsFrameEventFieldNumber = 57,
+ kVulkanMemoryEventFieldNumber = 62,
+ kGpuLogFieldNumber = 63,
+ kVulkanApiEventFieldNumber = 65,
+ kPerfSampleFieldNumber = 66,
+ kCpuInfoFieldNumber = 67,
+ kSmapsPacketFieldNumber = 68,
+ kServiceEventFieldNumber = 69,
+ kInitialDisplayStateFieldNumber = 70,
+ kGpuMemTotalEventFieldNumber = 71,
+ kMemoryTrackerSnapshotFieldNumber = 73,
+ kFrameTimelineEventFieldNumber = 76,
+ kAndroidEnergyEstimationBreakdownFieldNumber = 77,
+ kUiStateFieldNumber = 78,
+ kAndroidCameraFrameEventFieldNumber = 80,
+ kAndroidCameraSessionStatsFieldNumber = 81,
+ kTranslationTableFieldNumber = 82,
+ kAndroidGameInterventionListFieldNumber = 83,
+ kStatsdAtomFieldNumber = 84,
+ kAndroidSystemPropertyFieldNumber = 86,
+ kEntityStateResidencyFieldNumber = 91,
+ kProfiledFrameSymbolsFieldNumber = 55,
+ kModuleSymbolsFieldNumber = 61,
+ kDeobfuscationMappingFieldNumber = 64,
+ kTrackDescriptorFieldNumber = 60,
+ kProcessDescriptorFieldNumber = 43,
+ kThreadDescriptorFieldNumber = 44,
+ kFtraceEventsFieldNumber = 1,
+ kSynchronizationMarkerFieldNumber = 36,
+ kCompressedPacketsFieldNumber = 50,
+ kExtensionDescriptorFieldNumber = 72,
+ kNetworkPacketFieldNumber = 88,
+ kNetworkPacketBundleFieldNumber = 92,
+ kTrackEventRangeOfInterestFieldNumber = 90,
+ kSurfaceflingerLayersSnapshotFieldNumber = 93,
+ kSurfaceflingerTransactionsFieldNumber = 94,
+ kShellTransitionFieldNumber = 96,
+ kShellHandlerMappingsFieldNumber = 97,
+ kProtologMessageFieldNumber = 104,
+ kProtologViewerConfigFieldNumber = 105,
+ kEtwEventsFieldNumber = 95,
+ kV8JsCodeFieldNumber = 99,
+ kV8InternalCodeFieldNumber = 100,
+ kV8WasmCodeFieldNumber = 101,
+ kV8RegExpCodeFieldNumber = 102,
+ kV8CodeMoveFieldNumber = 103,
+ kAndroidInputEventFieldNumber = 106,
+ kRemoteClockSyncFieldNumber = 107,
+ kForTestingFieldNumber = 900,
+ kTrustedUidFieldNumber = 3,
+ kTrustedPacketSequenceIdFieldNumber = 10,
+ kTrustedPidFieldNumber = 79,
+ kInternedDataFieldNumber = 12,
+ kSequenceFlagsFieldNumber = 13,
+ kIncrementalStateClearedFieldNumber = 41,
+ kTracePacketDefaultsFieldNumber = 59,
+ kPreviousPacketDroppedFieldNumber = 42,
+ kFirstPacketOnSequenceFieldNumber = 87,
+ kMachineIdFieldNumber = 98,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracePacket"; }
+
+
+ using SequenceFlags = ::perfetto::protos::pbzero::TracePacket_SequenceFlags;
+ static inline const char* SequenceFlags_Name(SequenceFlags value) {
+ return ::perfetto::protos::pbzero::TracePacket_SequenceFlags_Name(value);
+ }
+ static inline const SequenceFlags SEQ_UNSPECIFIED = SequenceFlags::SEQ_UNSPECIFIED;
+ static inline const SequenceFlags SEQ_INCREMENTAL_STATE_CLEARED = SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED;
+ static inline const SequenceFlags SEQ_NEEDS_INCREMENTAL_STATE = SequenceFlags::SEQ_NEEDS_INCREMENTAL_STATE;
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TracePacket>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimestampClockId =
+ ::protozero::proto_utils::FieldMetadata<
+ 58,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TimestampClockId kTimestampClockId{};
+ void set_timestamp_clock_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampClockId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessTree =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessTree,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ProcessTree kProcessTree{};
+ template <typename T = ProcessTree> T* set_process_tree() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_ProcessStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessStats,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ProcessStats kProcessStats{};
+ template <typename T = ProcessStats> T* set_process_stats() {
+ return BeginNestedMessage<T>(9);
+ }
+
+
+ using FieldMetadata_InodeFileMap =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InodeFileMap,
+ TracePacket>;
+
+ static constexpr FieldMetadata_InodeFileMap kInodeFileMap{};
+ template <typename T = InodeFileMap> T* set_inode_file_map() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_ChromeEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeEventBundle,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ChromeEvents kChromeEvents{};
+ template <typename T = ChromeEventBundle> T* set_chrome_events() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_ClockSnapshot =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClockSnapshot,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ClockSnapshot kClockSnapshot{};
+ template <typename T = ClockSnapshot> T* set_clock_snapshot() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_SysStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats,
+ TracePacket>;
+
+ static constexpr FieldMetadata_SysStats kSysStats{};
+ template <typename T = SysStats> T* set_sys_stats() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_TrackEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TrackEvent kTrackEvent{};
+ template <typename T = TrackEvent> T* set_track_event() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_TraceUuid =
+ ::protozero::proto_utils::FieldMetadata<
+ 89,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceUuid,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TraceUuid kTraceUuid{};
+ template <typename T = TraceUuid> T* set_trace_uuid() {
+ return BeginNestedMessage<T>(89);
+ }
+
+
+ using FieldMetadata_TraceConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TraceConfig kTraceConfig{};
+ template <typename T = TraceConfig> T* set_trace_config() {
+ return BeginNestedMessage<T>(33);
+ }
+
+
+ using FieldMetadata_FtraceStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceStats,
+ TracePacket>;
+
+ static constexpr FieldMetadata_FtraceStats kFtraceStats{};
+ template <typename T = FtraceStats> T* set_ftrace_stats() {
+ return BeginNestedMessage<T>(34);
+ }
+
+
+ using FieldMetadata_TraceStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 35,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceStats,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TraceStats kTraceStats{};
+ template <typename T = TraceStats> T* set_trace_stats() {
+ return BeginNestedMessage<T>(35);
+ }
+
+
+ using FieldMetadata_ProfilePacket =
+ ::protozero::proto_utils::FieldMetadata<
+ 37,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfilePacket,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ProfilePacket kProfilePacket{};
+ template <typename T = ProfilePacket> T* set_profile_packet() {
+ return BeginNestedMessage<T>(37);
+ }
+
+
+ using FieldMetadata_StreamingAllocation =
+ ::protozero::proto_utils::FieldMetadata<
+ 74,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StreamingAllocation,
+ TracePacket>;
+
+ static constexpr FieldMetadata_StreamingAllocation kStreamingAllocation{};
+ template <typename T = StreamingAllocation> T* set_streaming_allocation() {
+ return BeginNestedMessage<T>(74);
+ }
+
+
+ using FieldMetadata_StreamingFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 75,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StreamingFree,
+ TracePacket>;
+
+ static constexpr FieldMetadata_StreamingFree kStreamingFree{};
+ template <typename T = StreamingFree> T* set_streaming_free() {
+ return BeginNestedMessage<T>(75);
+ }
+
+
+ using FieldMetadata_Battery =
+ ::protozero::proto_utils::FieldMetadata<
+ 38,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BatteryCounters,
+ TracePacket>;
+
+ static constexpr FieldMetadata_Battery kBattery{};
+ template <typename T = BatteryCounters> T* set_battery() {
+ return BeginNestedMessage<T>(38);
+ }
+
+
+ using FieldMetadata_PowerRails =
+ ::protozero::proto_utils::FieldMetadata<
+ 40,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PowerRails,
+ TracePacket>;
+
+ static constexpr FieldMetadata_PowerRails kPowerRails{};
+ template <typename T = PowerRails> T* set_power_rails() {
+ return BeginNestedMessage<T>(40);
+ }
+
+
+ using FieldMetadata_AndroidLog =
+ ::protozero::proto_utils::FieldMetadata<
+ 39,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidLogPacket,
+ TracePacket>;
+
+ static constexpr FieldMetadata_AndroidLog kAndroidLog{};
+ template <typename T = AndroidLogPacket> T* set_android_log() {
+ return BeginNestedMessage<T>(39);
+ }
+
+
+ using FieldMetadata_SystemInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 45,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SystemInfo,
+ TracePacket>;
+
+ static constexpr FieldMetadata_SystemInfo kSystemInfo{};
+ template <typename T = SystemInfo> T* set_system_info() {
+ return BeginNestedMessage<T>(45);
+ }
+
+
+ using FieldMetadata_Trigger =
+ ::protozero::proto_utils::FieldMetadata<
+ 46,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Trigger,
+ TracePacket>;
+
+ static constexpr FieldMetadata_Trigger kTrigger{};
+ template <typename T = Trigger> T* set_trigger() {
+ return BeginNestedMessage<T>(46);
+ }
+
+
+ using FieldMetadata_PackagesList =
+ ::protozero::proto_utils::FieldMetadata<
+ 47,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PackagesList,
+ TracePacket>;
+
+ static constexpr FieldMetadata_PackagesList kPackagesList{};
+ template <typename T = PackagesList> T* set_packages_list() {
+ return BeginNestedMessage<T>(47);
+ }
+
+
+ using FieldMetadata_ChromeBenchmarkMetadata =
+ ::protozero::proto_utils::FieldMetadata<
+ 48,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeBenchmarkMetadata,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ChromeBenchmarkMetadata kChromeBenchmarkMetadata{};
+ template <typename T = ChromeBenchmarkMetadata> T* set_chrome_benchmark_metadata() {
+ return BeginNestedMessage<T>(48);
+ }
+
+
+ using FieldMetadata_PerfettoMetatrace =
+ ::protozero::proto_utils::FieldMetadata<
+ 49,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfettoMetatrace,
+ TracePacket>;
+
+ static constexpr FieldMetadata_PerfettoMetatrace kPerfettoMetatrace{};
+ template <typename T = PerfettoMetatrace> T* set_perfetto_metatrace() {
+ return BeginNestedMessage<T>(49);
+ }
+
+
+ using FieldMetadata_ChromeMetadata =
+ ::protozero::proto_utils::FieldMetadata<
+ 51,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeMetadataPacket,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ChromeMetadata kChromeMetadata{};
+ template <typename T = ChromeMetadataPacket> T* set_chrome_metadata() {
+ return BeginNestedMessage<T>(51);
+ }
+
+
+ using FieldMetadata_GpuCounterEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 52,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuCounterEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_GpuCounterEvent kGpuCounterEvent{};
+ template <typename T = GpuCounterEvent> T* set_gpu_counter_event() {
+ return BeginNestedMessage<T>(52);
+ }
+
+
+ using FieldMetadata_GpuRenderStageEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 53,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuRenderStageEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_GpuRenderStageEvent kGpuRenderStageEvent{};
+ template <typename T = GpuRenderStageEvent> T* set_gpu_render_stage_event() {
+ return BeginNestedMessage<T>(53);
+ }
+
+
+ using FieldMetadata_StreamingProfilePacket =
+ ::protozero::proto_utils::FieldMetadata<
+ 54,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StreamingProfilePacket,
+ TracePacket>;
+
+ static constexpr FieldMetadata_StreamingProfilePacket kStreamingProfilePacket{};
+ template <typename T = StreamingProfilePacket> T* set_streaming_profile_packet() {
+ return BeginNestedMessage<T>(54);
+ }
+
+
+ using FieldMetadata_HeapGraph =
+ ::protozero::proto_utils::FieldMetadata<
+ 56,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HeapGraph,
+ TracePacket>;
+
+ static constexpr FieldMetadata_HeapGraph kHeapGraph{};
+ template <typename T = HeapGraph> T* set_heap_graph() {
+ return BeginNestedMessage<T>(56);
+ }
+
+
+ using FieldMetadata_GraphicsFrameEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 57,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GraphicsFrameEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_GraphicsFrameEvent kGraphicsFrameEvent{};
+ template <typename T = GraphicsFrameEvent> T* set_graphics_frame_event() {
+ return BeginNestedMessage<T>(57);
+ }
+
+
+ using FieldMetadata_VulkanMemoryEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 62,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VulkanMemoryEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_VulkanMemoryEvent kVulkanMemoryEvent{};
+ template <typename T = VulkanMemoryEvent> T* set_vulkan_memory_event() {
+ return BeginNestedMessage<T>(62);
+ }
+
+
+ using FieldMetadata_GpuLog =
+ ::protozero::proto_utils::FieldMetadata<
+ 63,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuLog,
+ TracePacket>;
+
+ static constexpr FieldMetadata_GpuLog kGpuLog{};
+ template <typename T = GpuLog> T* set_gpu_log() {
+ return BeginNestedMessage<T>(63);
+ }
+
+
+ using FieldMetadata_VulkanApiEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 65,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VulkanApiEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_VulkanApiEvent kVulkanApiEvent{};
+ template <typename T = VulkanApiEvent> T* set_vulkan_api_event() {
+ return BeginNestedMessage<T>(65);
+ }
+
+
+ using FieldMetadata_PerfSample =
+ ::protozero::proto_utils::FieldMetadata<
+ 66,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfSample,
+ TracePacket>;
+
+ static constexpr FieldMetadata_PerfSample kPerfSample{};
+ template <typename T = PerfSample> T* set_perf_sample() {
+ return BeginNestedMessage<T>(66);
+ }
+
+
+ using FieldMetadata_CpuInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 67,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuInfo,
+ TracePacket>;
+
+ static constexpr FieldMetadata_CpuInfo kCpuInfo{};
+ template <typename T = CpuInfo> T* set_cpu_info() {
+ return BeginNestedMessage<T>(67);
+ }
+
+
+ using FieldMetadata_SmapsPacket =
+ ::protozero::proto_utils::FieldMetadata<
+ 68,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SmapsPacket,
+ TracePacket>;
+
+ static constexpr FieldMetadata_SmapsPacket kSmapsPacket{};
+ template <typename T = SmapsPacket> T* set_smaps_packet() {
+ return BeginNestedMessage<T>(68);
+ }
+
+
+ using FieldMetadata_ServiceEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 69,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TracingServiceEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ServiceEvent kServiceEvent{};
+ template <typename T = TracingServiceEvent> T* set_service_event() {
+ return BeginNestedMessage<T>(69);
+ }
+
+
+ using FieldMetadata_InitialDisplayState =
+ ::protozero::proto_utils::FieldMetadata<
+ 70,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InitialDisplayState,
+ TracePacket>;
+
+ static constexpr FieldMetadata_InitialDisplayState kInitialDisplayState{};
+ template <typename T = InitialDisplayState> T* set_initial_display_state() {
+ return BeginNestedMessage<T>(70);
+ }
+
+
+ using FieldMetadata_GpuMemTotalEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 71,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuMemTotalEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_GpuMemTotalEvent kGpuMemTotalEvent{};
+ template <typename T = GpuMemTotalEvent> T* set_gpu_mem_total_event() {
+ return BeginNestedMessage<T>(71);
+ }
+
+
+ using FieldMetadata_MemoryTrackerSnapshot =
+ ::protozero::proto_utils::FieldMetadata<
+ 73,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MemoryTrackerSnapshot,
+ TracePacket>;
+
+ static constexpr FieldMetadata_MemoryTrackerSnapshot kMemoryTrackerSnapshot{};
+ template <typename T = MemoryTrackerSnapshot> T* set_memory_tracker_snapshot() {
+ return BeginNestedMessage<T>(73);
+ }
+
+
+ using FieldMetadata_FrameTimelineEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 76,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FrameTimelineEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_FrameTimelineEvent kFrameTimelineEvent{};
+ template <typename T = FrameTimelineEvent> T* set_frame_timeline_event() {
+ return BeginNestedMessage<T>(76);
+ }
+
+
+ using FieldMetadata_AndroidEnergyEstimationBreakdown =
+ ::protozero::proto_utils::FieldMetadata<
+ 77,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidEnergyEstimationBreakdown,
+ TracePacket>;
+
+ static constexpr FieldMetadata_AndroidEnergyEstimationBreakdown kAndroidEnergyEstimationBreakdown{};
+ template <typename T = AndroidEnergyEstimationBreakdown> T* set_android_energy_estimation_breakdown() {
+ return BeginNestedMessage<T>(77);
+ }
+
+
+ using FieldMetadata_UiState =
+ ::protozero::proto_utils::FieldMetadata<
+ 78,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ UiState,
+ TracePacket>;
+
+ static constexpr FieldMetadata_UiState kUiState{};
+ template <typename T = UiState> T* set_ui_state() {
+ return BeginNestedMessage<T>(78);
+ }
+
+
+ using FieldMetadata_AndroidCameraFrameEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 80,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidCameraFrameEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_AndroidCameraFrameEvent kAndroidCameraFrameEvent{};
+ template <typename T = AndroidCameraFrameEvent> T* set_android_camera_frame_event() {
+ return BeginNestedMessage<T>(80);
+ }
+
+
+ using FieldMetadata_AndroidCameraSessionStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 81,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidCameraSessionStats,
+ TracePacket>;
+
+ static constexpr FieldMetadata_AndroidCameraSessionStats kAndroidCameraSessionStats{};
+ template <typename T = AndroidCameraSessionStats> T* set_android_camera_session_stats() {
+ return BeginNestedMessage<T>(81);
+ }
+
+
+ using FieldMetadata_TranslationTable =
+ ::protozero::proto_utils::FieldMetadata<
+ 82,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TranslationTable,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TranslationTable kTranslationTable{};
+ template <typename T = TranslationTable> T* set_translation_table() {
+ return BeginNestedMessage<T>(82);
+ }
+
+
+ using FieldMetadata_AndroidGameInterventionList =
+ ::protozero::proto_utils::FieldMetadata<
+ 83,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidGameInterventionList,
+ TracePacket>;
+
+ static constexpr FieldMetadata_AndroidGameInterventionList kAndroidGameInterventionList{};
+ template <typename T = AndroidGameInterventionList> T* set_android_game_intervention_list() {
+ return BeginNestedMessage<T>(83);
+ }
+
+
+ using FieldMetadata_StatsdAtom =
+ ::protozero::proto_utils::FieldMetadata<
+ 84,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StatsdAtom,
+ TracePacket>;
+
+ static constexpr FieldMetadata_StatsdAtom kStatsdAtom{};
+ template <typename T = StatsdAtom> T* set_statsd_atom() {
+ return BeginNestedMessage<T>(84);
+ }
+
+
+ using FieldMetadata_AndroidSystemProperty =
+ ::protozero::proto_utils::FieldMetadata<
+ 86,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidSystemProperty,
+ TracePacket>;
+
+ static constexpr FieldMetadata_AndroidSystemProperty kAndroidSystemProperty{};
+ template <typename T = AndroidSystemProperty> T* set_android_system_property() {
+ return BeginNestedMessage<T>(86);
+ }
+
+
+ using FieldMetadata_EntityStateResidency =
+ ::protozero::proto_utils::FieldMetadata<
+ 91,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EntityStateResidency,
+ TracePacket>;
+
+ static constexpr FieldMetadata_EntityStateResidency kEntityStateResidency{};
+ template <typename T = EntityStateResidency> T* set_entity_state_residency() {
+ return BeginNestedMessage<T>(91);
+ }
+
+
+ using FieldMetadata_ProfiledFrameSymbols =
+ ::protozero::proto_utils::FieldMetadata<
+ 55,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfiledFrameSymbols,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ProfiledFrameSymbols kProfiledFrameSymbols{};
+ template <typename T = ProfiledFrameSymbols> T* set_profiled_frame_symbols() {
+ return BeginNestedMessage<T>(55);
+ }
+
+
+ using FieldMetadata_ModuleSymbols =
+ ::protozero::proto_utils::FieldMetadata<
+ 61,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ModuleSymbols,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ModuleSymbols kModuleSymbols{};
+ template <typename T = ModuleSymbols> T* set_module_symbols() {
+ return BeginNestedMessage<T>(61);
+ }
+
+
+ using FieldMetadata_DeobfuscationMapping =
+ ::protozero::proto_utils::FieldMetadata<
+ 64,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DeobfuscationMapping,
+ TracePacket>;
+
+ static constexpr FieldMetadata_DeobfuscationMapping kDeobfuscationMapping{};
+ template <typename T = DeobfuscationMapping> T* set_deobfuscation_mapping() {
+ return BeginNestedMessage<T>(64);
+ }
+
+
+ using FieldMetadata_TrackDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 60,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackDescriptor,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TrackDescriptor kTrackDescriptor{};
+ template <typename T = TrackDescriptor> T* set_track_descriptor() {
+ return BeginNestedMessage<T>(60);
+ }
+
+
+ using FieldMetadata_ProcessDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 43,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessDescriptor,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ProcessDescriptor kProcessDescriptor{};
+ template <typename T = ProcessDescriptor> T* set_process_descriptor() {
+ return BeginNestedMessage<T>(43);
+ }
+
+
+ using FieldMetadata_ThreadDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 44,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ThreadDescriptor,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ThreadDescriptor kThreadDescriptor{};
+ template <typename T = ThreadDescriptor> T* set_thread_descriptor() {
+ return BeginNestedMessage<T>(44);
+ }
+
+
+ using FieldMetadata_FtraceEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceEventBundle,
+ TracePacket>;
+
+ static constexpr FieldMetadata_FtraceEvents kFtraceEvents{};
+ template <typename T = FtraceEventBundle> T* set_ftrace_events() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_SynchronizationMarker =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ TracePacket>;
+
+ static constexpr FieldMetadata_SynchronizationMarker kSynchronizationMarker{};
+ void set_synchronization_marker(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_SynchronizationMarker::kFieldId, data, size);
+ }
+ void set_synchronization_marker(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_SynchronizationMarker::kFieldId, bytes.data, bytes.size);
+ }
+ void set_synchronization_marker(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SynchronizationMarker::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CompressedPackets =
+ ::protozero::proto_utils::FieldMetadata<
+ 50,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ TracePacket>;
+
+ static constexpr FieldMetadata_CompressedPackets kCompressedPackets{};
+ void set_compressed_packets(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_CompressedPackets::kFieldId, data, size);
+ }
+ void set_compressed_packets(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_CompressedPackets::kFieldId, bytes.data, bytes.size);
+ }
+ void set_compressed_packets(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_CompressedPackets::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtensionDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 72,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ExtensionDescriptor,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ExtensionDescriptor kExtensionDescriptor{};
+ template <typename T = ExtensionDescriptor> T* set_extension_descriptor() {
+ return BeginNestedMessage<T>(72);
+ }
+
+
+ using FieldMetadata_NetworkPacket =
+ ::protozero::proto_utils::FieldMetadata<
+ 88,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetworkPacketEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_NetworkPacket kNetworkPacket{};
+ template <typename T = NetworkPacketEvent> T* set_network_packet() {
+ return BeginNestedMessage<T>(88);
+ }
+
+
+ using FieldMetadata_NetworkPacketBundle =
+ ::protozero::proto_utils::FieldMetadata<
+ 92,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetworkPacketBundle,
+ TracePacket>;
+
+ static constexpr FieldMetadata_NetworkPacketBundle kNetworkPacketBundle{};
+ template <typename T = NetworkPacketBundle> T* set_network_packet_bundle() {
+ return BeginNestedMessage<T>(92);
+ }
+
+
+ using FieldMetadata_TrackEventRangeOfInterest =
+ ::protozero::proto_utils::FieldMetadata<
+ 90,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackEventRangeOfInterest,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TrackEventRangeOfInterest kTrackEventRangeOfInterest{};
+ template <typename T = TrackEventRangeOfInterest> T* set_track_event_range_of_interest() {
+ return BeginNestedMessage<T>(90);
+ }
+
+
+ using FieldMetadata_SurfaceflingerLayersSnapshot =
+ ::protozero::proto_utils::FieldMetadata<
+ 93,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayersSnapshotProto,
+ TracePacket>;
+
+ static constexpr FieldMetadata_SurfaceflingerLayersSnapshot kSurfaceflingerLayersSnapshot{};
+ template <typename T = LayersSnapshotProto> T* set_surfaceflinger_layers_snapshot() {
+ return BeginNestedMessage<T>(93);
+ }
+
+
+ using FieldMetadata_SurfaceflingerTransactions =
+ ::protozero::proto_utils::FieldMetadata<
+ 94,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransactionTraceEntry,
+ TracePacket>;
+
+ static constexpr FieldMetadata_SurfaceflingerTransactions kSurfaceflingerTransactions{};
+ template <typename T = TransactionTraceEntry> T* set_surfaceflinger_transactions() {
+ return BeginNestedMessage<T>(94);
+ }
+
+
+ using FieldMetadata_ShellTransition =
+ ::protozero::proto_utils::FieldMetadata<
+ 96,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ShellTransition,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ShellTransition kShellTransition{};
+ template <typename T = ShellTransition> T* set_shell_transition() {
+ return BeginNestedMessage<T>(96);
+ }
+
+
+ using FieldMetadata_ShellHandlerMappings =
+ ::protozero::proto_utils::FieldMetadata<
+ 97,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ShellHandlerMappings,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ShellHandlerMappings kShellHandlerMappings{};
+ template <typename T = ShellHandlerMappings> T* set_shell_handler_mappings() {
+ return BeginNestedMessage<T>(97);
+ }
+
+
+ using FieldMetadata_ProtologMessage =
+ ::protozero::proto_utils::FieldMetadata<
+ 104,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProtoLogMessage,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ProtologMessage kProtologMessage{};
+ template <typename T = ProtoLogMessage> T* set_protolog_message() {
+ return BeginNestedMessage<T>(104);
+ }
+
+
+ using FieldMetadata_ProtologViewerConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 105,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProtoLogViewerConfig,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ProtologViewerConfig kProtologViewerConfig{};
+ template <typename T = ProtoLogViewerConfig> T* set_protolog_viewer_config() {
+ return BeginNestedMessage<T>(105);
+ }
+
+
+ using FieldMetadata_EtwEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 95,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EtwTraceEventBundle,
+ TracePacket>;
+
+ static constexpr FieldMetadata_EtwEvents kEtwEvents{};
+ template <typename T = EtwTraceEventBundle> T* set_etw_events() {
+ return BeginNestedMessage<T>(95);
+ }
+
+
+ using FieldMetadata_V8JsCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 99,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8JsCode,
+ TracePacket>;
+
+ static constexpr FieldMetadata_V8JsCode kV8JsCode{};
+ template <typename T = V8JsCode> T* set_v8_js_code() {
+ return BeginNestedMessage<T>(99);
+ }
+
+
+ using FieldMetadata_V8InternalCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 100,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8InternalCode,
+ TracePacket>;
+
+ static constexpr FieldMetadata_V8InternalCode kV8InternalCode{};
+ template <typename T = V8InternalCode> T* set_v8_internal_code() {
+ return BeginNestedMessage<T>(100);
+ }
+
+
+ using FieldMetadata_V8WasmCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 101,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8WasmCode,
+ TracePacket>;
+
+ static constexpr FieldMetadata_V8WasmCode kV8WasmCode{};
+ template <typename T = V8WasmCode> T* set_v8_wasm_code() {
+ return BeginNestedMessage<T>(101);
+ }
+
+
+ using FieldMetadata_V8RegExpCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 102,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8RegExpCode,
+ TracePacket>;
+
+ static constexpr FieldMetadata_V8RegExpCode kV8RegExpCode{};
+ template <typename T = V8RegExpCode> T* set_v8_reg_exp_code() {
+ return BeginNestedMessage<T>(102);
+ }
+
+
+ using FieldMetadata_V8CodeMove =
+ ::protozero::proto_utils::FieldMetadata<
+ 103,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8CodeMove,
+ TracePacket>;
+
+ static constexpr FieldMetadata_V8CodeMove kV8CodeMove{};
+ template <typename T = V8CodeMove> T* set_v8_code_move() {
+ return BeginNestedMessage<T>(103);
+ }
+
+
+ using FieldMetadata_AndroidInputEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 106,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidInputEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_AndroidInputEvent kAndroidInputEvent{};
+ template <typename T = AndroidInputEvent> T* set_android_input_event() {
+ return BeginNestedMessage<T>(106);
+ }
+
+
+ using FieldMetadata_RemoteClockSync =
+ ::protozero::proto_utils::FieldMetadata<
+ 107,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RemoteClockSync,
+ TracePacket>;
+
+ static constexpr FieldMetadata_RemoteClockSync kRemoteClockSync{};
+ template <typename T = RemoteClockSync> T* set_remote_clock_sync() {
+ return BeginNestedMessage<T>(107);
+ }
+
+
+ using FieldMetadata_ForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 900,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TestEvent,
+ TracePacket>;
+
+ static constexpr FieldMetadata_ForTesting kForTesting{};
+ template <typename T = TestEvent> T* set_for_testing() {
+ return BeginNestedMessage<T>(900);
+ }
+
+
+ using FieldMetadata_TrustedUid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TrustedUid kTrustedUid{};
+ void set_trusted_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrustedUid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TrustedPacketSequenceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TrustedPacketSequenceId kTrustedPacketSequenceId{};
+ void set_trusted_packet_sequence_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrustedPacketSequenceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TrustedPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 79,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TrustedPid kTrustedPid{};
+ void set_trusted_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrustedPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InternedData =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedData,
+ TracePacket>;
+
+ static constexpr FieldMetadata_InternedData kInternedData{};
+ template <typename T = InternedData> T* set_interned_data() {
+ return BeginNestedMessage<T>(12);
+ }
+
+
+ using FieldMetadata_SequenceFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracePacket>;
+
+ static constexpr FieldMetadata_SequenceFlags kSequenceFlags{};
+ void set_sequence_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SequenceFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IncrementalStateCleared =
+ ::protozero::proto_utils::FieldMetadata<
+ 41,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracePacket>;
+
+ static constexpr FieldMetadata_IncrementalStateCleared kIncrementalStateCleared{};
+ void set_incremental_state_cleared(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IncrementalStateCleared::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TracePacketDefaults =
+ ::protozero::proto_utils::FieldMetadata<
+ 59,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TracePacketDefaults,
+ TracePacket>;
+
+ static constexpr FieldMetadata_TracePacketDefaults kTracePacketDefaults{};
+ template <typename T = TracePacketDefaults> T* set_trace_packet_defaults() {
+ return BeginNestedMessage<T>(59);
+ }
+
+
+ using FieldMetadata_PreviousPacketDropped =
+ ::protozero::proto_utils::FieldMetadata<
+ 42,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracePacket>;
+
+ static constexpr FieldMetadata_PreviousPacketDropped kPreviousPacketDropped{};
+ void set_previous_packet_dropped(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreviousPacketDropped::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FirstPacketOnSequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 87,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracePacket>;
+
+ static constexpr FieldMetadata_FirstPacketOnSequence kFirstPacketOnSequence{};
+ void set_first_packet_on_sequence(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_FirstPacketOnSequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MachineId =
+ ::protozero::proto_utils::FieldMetadata<
+ 98,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracePacket>;
+
+ static constexpr FieldMetadata_MachineId kMachineId{};
+ void set_machine_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MachineId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
+#define INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
+
+// This header contains the key class (DataSource) that a producer app should
+// override in order to create a custom data source that gets tracing Start/Stop
+// notifications and emits tracing data.
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <mutex>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/flush_flags.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_type.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/locked_handle.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+// DEPRECATED: Instead of using this macro, prefer specifying symbol linkage
+// attributes explicitly using the `_WITH_ATTRS` macro variants (e.g.,
+// PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS). This avoids
+// potential macro definition collisions between two libraries using Perfetto.
+//
+// PERFETTO_COMPONENT_EXPORT is used to mark symbols in Perfetto's headers
+// (typically templates) that are defined by the user outside of Perfetto and
+// should be made visible outside the current module. (e.g., in Chrome's
+// component build).
+#if !defined(PERFETTO_COMPONENT_EXPORT)
+#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
+// Workaround for C4003: not enough arguments for function-like macro invocation
+// 'PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE'
+#define PERFETTO_COMPONENT_EXPORT __declspec()
+#else
+#define PERFETTO_COMPONENT_EXPORT
+#endif
+#endif
+
+namespace perfetto {
+namespace internal {
+class TracingMuxerImpl;
+class TrackEventCategoryRegistry;
+template <typename, const internal::TrackEventCategoryRegistry*>
+class TrackEventDataSource;
+} // namespace internal
+
+namespace shlib {
+class TrackEvent;
+} // namespace shlib
+
+namespace test {
+class DataSourceInternalForTest;
+} // namespace test
+
+// Base class with the virtual methods to get start/stop notifications.
+// Embedders are supposed to derive the templated version below, not this one.
+class PERFETTO_EXPORT_COMPONENT DataSourceBase {
+ public:
+ virtual ~DataSourceBase();
+
+ // TODO(primiano): change the const& args below to be pointers instead. It
+ // makes it more awkward to handle output arguments and require mutable(s).
+ // This requires synchronizing a breaking API change for existing embedders.
+
+ // OnSetup() is invoked when tracing is configured. In most cases this happens
+ // just before starting the trace. In the case of deferred start (see
+ // deferred_start in trace_config.proto) start might happen later.
+ //
+ // Can be called from any thread.
+ class SetupArgs {
+ public:
+ // This is valid only within the scope of the OnSetup() call and must not
+ // be retained.
+ const DataSourceConfig* config = nullptr;
+
+ // Backend type.
+ BackendType backend_type = kUnspecifiedBackend;
+
+ // The index of this data source instance (0..kMaxDataSourceInstances - 1).
+ uint32_t internal_instance_index = 0;
+ };
+ virtual void OnSetup(const SetupArgs&);
+
+ class StartArgs {
+ public:
+ // The index of this data source instance (0..kMaxDataSourceInstances - 1).
+ uint32_t internal_instance_index = 0;
+ };
+ // Invoked after tracing is actually started.
+ //
+ // Can be called from any thread.
+ virtual void OnStart(const StartArgs&);
+
+ class PERFETTO_EXPORT_COMPONENT StopArgs {
+ public:
+ virtual ~StopArgs();
+
+ // HandleAsynchronously() can optionally be called to defer the tracing
+ // session stop and write tracing data just before stopping.
+ // This function returns a closure that must be invoked after the last
+ // trace events have been emitted. The returned closure can be called from
+ // any thread. The caller also needs to explicitly call TraceContext.Flush()
+ // from the last Trace() lambda invocation because no other implicit flushes
+ // will happen after the stop signal.
+ // When this function is called, the tracing service will defer the stop of
+ // the tracing session until the returned closure is invoked.
+ // However, the caller cannot hang onto this closure for too long. The
+ // tracing service will forcefully stop the tracing session without waiting
+ // for pending producers after TraceConfig.data_source_stop_timeout_ms
+ // (default: 5s, can be overridden by Consumers when starting a trace).
+ // If the closure is called after this timeout an error will be logged and
+ // the trace data emitted will not be present in the trace. No other
+ // functional side effects (e.g. crashes or corruptions) will happen. In
+ // other words, it is fine to accidentally hold onto this closure for too
+ // long but, if that happens, some tracing data will be lost.
+ virtual std::function<void()> HandleStopAsynchronously() const = 0;
+
+ // The index of this data source instance (0..kMaxDataSourceInstances - 1).
+ uint32_t internal_instance_index = 0;
+ };
+ // Invoked before tracing is stopped.
+ //
+ // Can be called from any thread. Blocking this for too long it's not a good
+ // idea and can cause deadlocks. Use HandleAsynchronously() to postpone
+ // disabling the data source instance.
+ virtual void OnStop(const StopArgs&);
+
+ class ClearIncrementalStateArgs {
+ public:
+ // The index of this data source instance (0..kMaxDataSourceInstances - 1).
+ uint32_t internal_instance_index = 0;
+ };
+ // Invoked before marking the thread local per-instance incremental state
+ // outdated.
+ //
+ // Can be called from any thread.
+ virtual void WillClearIncrementalState(const ClearIncrementalStateArgs&);
+
+ class FlushArgs {
+ public:
+ virtual ~FlushArgs();
+
+ // HandleFlushAsynchronously() can be called to postpone acknowledging the
+ // flush request. This function returns a closure that must be invoked after
+ // the flush request has been processed. The returned closure can be called
+ // from any thread.
+ virtual std::function<void()> HandleFlushAsynchronously() const = 0;
+
+ // The index of this data source instance (0..kMaxDataSourceInstances - 1).
+ uint32_t internal_instance_index = 0;
+
+ // The reason and initiator of the flush. See flush_flags.h .
+ FlushFlags flush_flags;
+ };
+ // Called when the tracing service requests a Flush. Users can override this
+ // to tell other threads to flush their TraceContext for this data source
+ // (the library cannot execute code on all the threads on its own).
+ //
+ // Can be called from any thread. Blocking this for too long it's not a good
+ // idea and can cause deadlocks. Use HandleAsynchronously() to postpone
+ // sending the flush acknowledgement to the service.
+ virtual void OnFlush(const FlushArgs&);
+
+ // Determines whether a startup session can be adopted by a service-initiated
+ // tracing session (i.e. whether their configs are compatible).
+ virtual bool CanAdoptStartupSession(const DataSourceConfig& startup_config,
+ const DataSourceConfig& service_config);
+};
+
+struct DefaultDataSourceTraits {
+ // |IncrementalStateType| can optionally be used store custom per-sequence
+ // incremental data (e.g., interning tables).
+ using IncrementalStateType = void;
+ // |TlsStateType| can optionally be used to store custom per-sequence
+ // session data, which is not reset when incremental state is cleared
+ // (e.g. configuration options).
+ using TlsStateType = void;
+
+ // Allows overriding what type of thread-local state configuration the data
+ // source uses. By default every data source gets independent thread-local
+ // state, which means every instance uses separate trace writers and
+ // incremental state even on the same thread. Some data sources (most notably
+ // the track event data source) want to share trace writers and incremental
+ // state on the same thread.
+ static internal::DataSourceThreadLocalState* GetDataSourceTLS(
+ internal::DataSourceStaticState* static_state,
+ internal::TracingTLS* root_tls) {
+ auto* ds_tls = &root_tls->data_sources_tls[static_state->index];
+ // ds_tls->static_state can be:
+ // * nullptr
+ // * equal to static_state
+ // * equal to the static state of a different data source, in tests (when
+ // ResetForTesting() has been used)
+ // In any case, there's no need to do anything, the caller will reinitialize
+ // static_state.
+ return ds_tls;
+ }
+};
+
+// Holds the type for a DataSource. Accessed by the static Trace() method
+// fastpaths. This allows redefinitions under a component where a component
+// specific export macro is used.
+// Due to C2086 (redefinition) error on MSVC/clang-cl, internal::DataSourceType
+// can't be a static data member. To avoid explicit specialization after
+// instantiation error, type() needs to be in a template helper class that's
+// instantiated independently from DataSource. See b/280777748.
+template <typename DerivedDataSource,
+ typename DataSourceTraits = DefaultDataSourceTraits>
+struct DataSourceHelper {
+ static internal::DataSourceType& type() {
+ static perfetto::internal::DataSourceType type_;
+ return type_;
+ }
+};
+
+// Templated base class meant to be derived by embedders to create a custom data
+// source. DerivedDataSource must be the type of the derived class itself, e.g.:
+// class MyDataSource : public DataSource<MyDataSource> {...}.
+//
+// |DataSourceTraits| allows customizing the behavior of the data source. See
+// |DefaultDataSourceTraits|.
+template <typename DerivedDataSource,
+ typename DataSourceTraits = DefaultDataSourceTraits>
+class DataSource : public DataSourceBase {
+ struct DefaultTracePointTraits;
+ using Helper = DataSourceHelper<DerivedDataSource, DataSourceTraits>;
+
+ public:
+ // The BufferExhaustedPolicy to use for TraceWriters of this DataSource.
+ // Override this in your DataSource class to change the default, which is to
+ // drop data on shared memory overruns.
+ constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy =
+ BufferExhaustedPolicy::kDrop;
+
+ // When this flag is false, we cannot have multiple instances of this data
+ // source. When a data source is already active and if we attempt
+ // to start another instance of that data source (via another tracing
+ // session), it will fail to start the second instance of data source.
+ static constexpr bool kSupportsMultipleInstances = true;
+
+ // When this flag is true, DataSource callbacks (OnSetup, OnStart, etc.) are
+ // called under the lock (the same that is used in GetDataSourceLocked
+ // function). This is not recommended because it can lead to deadlocks, but
+ // it was the default behavior for a long time and some embedders rely on it
+ // to protect concurrent access to the DataSource members. So we keep the
+ // "true" value as the default.
+ static constexpr bool kRequiresCallbacksUnderLock = true;
+
+ // Argument passed to the lambda function passed to Trace() (below).
+ class TraceContext {
+ public:
+ using TracePacketHandle =
+ ::protozero::MessageHandle<::perfetto::protos::pbzero::TracePacket>;
+
+ TraceContext(TraceContext&&) noexcept = default;
+ ~TraceContext() {
+ // If the data source is being intercepted, flush the trace writer after
+ // each trace point to make sure the interceptor sees the data right away.
+ if (PERFETTO_UNLIKELY(tls_inst_->is_intercepted))
+ Flush();
+ }
+
+ // Adds an empty trace packet to the trace to ensure that the service can
+ // safely read the last event from the trace buffer.
+ // See PERFETTO_INTERNAL_ADD_EMPTY_EVENT macros for context.
+ void AddEmptyTracePacket() {
+ // If nothing was written since the last empty packet, there's nothing to
+ // scrape, so adding more empty packets serves no purpose.
+ if (tls_inst_->trace_writer->written() ==
+ tls_inst_->last_empty_packet_position) {
+ return;
+ }
+ tls_inst_->trace_writer->NewTracePacket();
+ tls_inst_->last_empty_packet_position =
+ tls_inst_->trace_writer->written();
+ }
+
+ TracePacketHandle NewTracePacket() {
+ return tls_inst_->trace_writer->NewTracePacket();
+ }
+
+ // Forces a commit of the thread-local tracing data written so far to the
+ // service. This is almost never required (tracing data is periodically
+ // committed as trace pages are filled up) and has a non-negligible
+ // performance hit (requires an IPC + refresh of the current thread-local
+ // chunk). The only case when this should be used is when handling OnStop()
+ // asynchronously, to ensure sure that the data is committed before the
+ // Stop timeout expires.
+ // The TracePacketHandle obtained by the last NewTracePacket() call must be
+ // finalized before calling Flush() (either implicitly by going out of scope
+ // or by explicitly calling Finalize()).
+ // |cb| is an optional callback. When non-null it will request the
+ // service to ACK the flush and will be invoked on an internal thread after
+ // the service has acknowledged it. The callback might be NEVER INVOKED if
+ // the service crashes or the IPC connection is dropped.
+ void Flush(std::function<void()> cb = {}) {
+ tls_inst_->trace_writer->Flush(cb);
+ }
+
+ // Returns the number of bytes written on the current thread by the current
+ // data-source since its creation.
+ // This can be useful for splitting protos that might grow very large.
+ uint64_t written() { return tls_inst_->trace_writer->written(); }
+
+ // Returns a RAII handle to access the data source instance, guaranteeing
+ // that it won't be deleted on another thread (because of trace stopping)
+ // while accessing it from within the Trace() lambda.
+ // The returned handle can be invalid (nullptr) if tracing is stopped
+ // immediately before calling this. The caller is supposed to check for its
+ // validity before using it. After checking, the handle is guaranteed to
+ // remain valid until the handle goes out of scope.
+ LockedHandle<DerivedDataSource> GetDataSourceLocked() const {
+ auto* internal_state =
+ Helper::type().static_state()->TryGet(instance_index_);
+ if (!internal_state)
+ return LockedHandle<DerivedDataSource>();
+ std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
+ return LockedHandle<DerivedDataSource>(
+ std::move(lock),
+ static_cast<DerivedDataSource*>(internal_state->data_source.get()));
+ }
+
+ // Post-condition: returned ptr will be non-null.
+ typename DataSourceTraits::TlsStateType* GetCustomTlsState() {
+ PERFETTO_DCHECK(tls_inst_->data_source_custom_tls);
+ return reinterpret_cast<typename DataSourceTraits::TlsStateType*>(
+ tls_inst_->data_source_custom_tls.get());
+ }
+
+ typename DataSourceTraits::IncrementalStateType* GetIncrementalState() {
+ return static_cast<typename DataSourceTraits::IncrementalStateType*>(
+ Helper::type().GetIncrementalState(tls_inst_, instance_index_));
+ }
+
+ private:
+ friend class DataSource;
+ template <typename, const internal::TrackEventCategoryRegistry*>
+ friend class internal::TrackEventDataSource;
+ TraceContext(internal::DataSourceInstanceThreadLocalState* tls_inst,
+ uint32_t instance_index)
+ : tls_inst_(tls_inst), instance_index_(instance_index) {}
+ TraceContext(const TraceContext&) = delete;
+ TraceContext& operator=(const TraceContext&) = delete;
+
+ internal::DataSourceInstanceThreadLocalState* const tls_inst_;
+ uint32_t const instance_index_;
+ };
+
+ // The main tracing method. Tracing code should call this passing a lambda as
+ // argument, with the following signature: void(TraceContext).
+ // The lambda will be called synchronously (i.e., always before Trace()
+ // returns) only if tracing is enabled and the data source has been enabled in
+ // the tracing config.
+ // The lambda can be called more than once per Trace() call, in the case of
+ // concurrent tracing sessions (or even if the data source is instantiated
+ // twice within the same trace config).
+ template <typename Lambda>
+ static void Trace(Lambda tracing_fn) {
+ CallIfEnabled<DefaultTracePointTraits>([&tracing_fn](uint32_t instances) {
+ TraceWithInstances<DefaultTracePointTraits>(instances,
+ std::move(tracing_fn));
+ });
+ }
+
+ // An efficient trace point guard for checking if this data source is active.
+ // |callback| is a function which will only be called if there are active
+ // instances. It is given an instance state parameter, which should be passed
+ // to TraceWithInstances() to actually record trace data.
+ template <typename Traits = DefaultTracePointTraits, typename Callback>
+ static void CallIfEnabled(Callback callback,
+ typename Traits::TracePointData trace_point_data =
+ {}) PERFETTO_ALWAYS_INLINE {
+ // |instances| is a per-class bitmap that tells:
+ // 1. If the data source is enabled at all.
+ // 2. The index of the slot within
+ // internal::DataSourceStaticState::instances that holds the instance
+ // state. In turn this allows to map the data source to the tracing
+ // session and buffers.
+ // memory_order_relaxed is okay because:
+ // - |instances| is re-read with an acquire barrier below if this succeeds.
+ // - The code between this point and the acquire-load is based on static
+ // storage which has indefinite lifetime.
+ uint32_t instances = Traits::GetActiveInstances(trace_point_data)
+ ->load(std::memory_order_relaxed);
+
+ // This is the tracing fast-path. Bail out immediately if tracing is not
+ // enabled (or tracing is enabled but not for this data source).
+ if (PERFETTO_LIKELY(!instances))
+ return;
+ callback(instances);
+ }
+
+ // The "lower half" of a trace point which actually performs tracing after
+ // this data source has been determined to be active.
+ // |instances| must be the instance state value retrieved through
+ // CallIfEnabled().
+ // |tracing_fn| will be called to record trace data as in Trace().
+ //
+ // |trace_point_data| is an optional parameter given to |Traits::
+ // GetActiveInstances| to make it possible to use custom storage for
+ // the data source enabled state. This is, for example, used by TrackEvent to
+ // implement per-tracing category enabled states.
+ template <typename Traits = DefaultTracePointTraits, typename Lambda>
+ static void TraceWithInstances(
+ uint32_t cached_instances,
+ Lambda tracing_fn,
+ typename Traits::TracePointData trace_point_data = {}) {
+ PERFETTO_DCHECK(cached_instances);
+
+ if (!Helper::type().template TracePrologue<DataSourceTraits, Traits>(
+ &tls_state_, &cached_instances, trace_point_data)) {
+ return;
+ }
+
+ for (internal::DataSourceType::InstancesIterator it =
+ Helper::type().template BeginIteration<Traits>(
+ cached_instances, tls_state_, trace_point_data);
+ it.instance; Helper::type().template NextIteration<Traits>(
+ &it, tls_state_, trace_point_data)) {
+ tracing_fn(TraceContext(it.instance, it.i));
+ }
+
+ Helper::type().TraceEpilogue(tls_state_);
+ }
+
+ // Registers the data source on all tracing backends, including ones that
+ // connect after the registration. Doing so enables the data source to receive
+ // Setup/Start/Stop notifications and makes the Trace() method work when
+ // tracing is enabled and the data source is selected.
+ // This must be called after Tracing::Initialize().
+ // Can return false to signal failure if attemping to register more than
+ // kMaxDataSources (32) data sources types or if tracing hasn't been
+ // initialized.
+ // The optional |constructor_args| will be passed to the data source when it
+ // is constructed.
+ template <class... Args>
+ static bool Register(const DataSourceDescriptor& descriptor,
+ const Args&... constructor_args) {
+ // Silences -Wunused-variable warning in case the trace method is not used
+ // by the translation unit that declares the data source.
+ (void)tls_state_;
+
+ auto factory = [constructor_args...]() {
+ return std::unique_ptr<DataSourceBase>(
+ new DerivedDataSource(constructor_args...));
+ };
+ constexpr bool no_flush =
+ std::is_same_v<decltype(&DerivedDataSource::OnFlush),
+ decltype(&DataSourceBase::OnFlush)>;
+ internal::DataSourceParams params{
+ DerivedDataSource::kSupportsMultipleInstances,
+ DerivedDataSource::kRequiresCallbacksUnderLock};
+ return Helper::type().Register(
+ descriptor, factory, params, DerivedDataSource::kBufferExhaustedPolicy,
+ no_flush,
+ GetCreateTlsFn(
+ static_cast<typename DataSourceTraits::TlsStateType*>(nullptr)),
+ GetCreateIncrementalStateFn(
+ static_cast<typename DataSourceTraits::IncrementalStateType*>(
+ nullptr)),
+ nullptr);
+ }
+
+ // Updates the data source descriptor.
+ static void UpdateDescriptor(const DataSourceDescriptor& descriptor) {
+ Helper::type().UpdateDescriptor(descriptor);
+ }
+
+ private:
+ friend ::perfetto::test::DataSourceInternalForTest;
+ friend ::perfetto::shlib::TrackEvent;
+ // Traits for customizing the behavior of a specific trace point.
+ struct DefaultTracePointTraits {
+ // By default, every call to DataSource::Trace() will record trace events
+ // for every active instance of that data source. A single trace point can,
+ // however, use a custom set of enable flags for more fine grained control
+ // of when that trace point is active.
+ //
+ // DANGER: when doing this, the data source must use the appropriate memory
+ // fences when changing the state of the bitmap.
+ //
+ // |TraceWithInstances| may be optionally given an additional parameter for
+ // looking up the enable flags. That parameter is passed as |TracePointData|
+ // to |GetActiveInstances|. This is, for example, used by TrackEvent to
+ // implement per-category enabled states.
+ struct TracePointData {};
+ static constexpr std::atomic<uint32_t>* GetActiveInstances(TracePointData) {
+ return Helper::type().valid_instances();
+ }
+ };
+
+ template <typename T>
+ static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter
+ CreateIncrementalState(internal::DataSourceInstanceThreadLocalState*,
+ uint32_t,
+ void*) {
+ return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
+ reinterpret_cast<void*>(new T()),
+ [](void* p) { delete reinterpret_cast<T*>(p); });
+ }
+
+ // The second parameter here is used to specialize the case where there is no
+ // incremental state type.
+ template <typename T>
+ static internal::DataSourceType::CreateIncrementalStateFn
+ GetCreateIncrementalStateFn(const T*) {
+ return &CreateIncrementalState<T>;
+ }
+
+ static internal::DataSourceType::CreateIncrementalStateFn
+ GetCreateIncrementalStateFn(const void*) {
+ return nullptr;
+ }
+
+ template <typename T>
+ static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter
+ CreateDataSourceCustomTls(
+ internal::DataSourceInstanceThreadLocalState* tls_inst,
+ uint32_t instance_index,
+ void*) {
+ return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
+ reinterpret_cast<void*>(new T(TraceContext(tls_inst, instance_index))),
+ [](void* p) { delete reinterpret_cast<T*>(p); });
+ }
+
+ // The second parameter here is used to specialize the case where there is no
+ // tls state type.
+ template <typename T>
+ static internal::DataSourceType::CreateCustomTlsFn GetCreateTlsFn(const T*) {
+ return &CreateDataSourceCustomTls<T>;
+ }
+
+ static internal::DataSourceType::CreateCustomTlsFn GetCreateTlsFn(
+ const void*) {
+ return nullptr;
+ }
+
+ // This TLS object is a cached raw pointer and has deliberately no destructor.
+ // The Platform implementation is supposed to create and manage the lifetime
+ // of the Platform::ThreadLocalObject and take care of destroying it.
+ // This is because non-POD thread_local variables have subtleties (global
+ // destructors) that we need to defer to the embedder. In chromium's platform
+ // implementation, for instance, the tls slot is implemented using
+ // chromium's base::ThreadLocalStorage.
+ static thread_local internal::DataSourceThreadLocalState* tls_state_;
+};
+
+// static
+template <typename T, typename D>
+thread_local internal::DataSourceThreadLocalState* DataSource<T, D>::tls_state_;
+
+} // namespace perfetto
+
+// If placed at the end of a macro declaration, eats the semicolon at the end of
+// the macro invocation (e.g., "MACRO(...);") to avoid warnings about extra
+// semicolons.
+#define PERFETTO_INTERNAL_SWALLOW_SEMICOLON() \
+ extern int perfetto_internal_unused
+
+// This macro must be used once for each data source next to the data source's
+// declaration.
+#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...) \
+ PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
+ PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)
+
+// Similar to `PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS` but it also takes
+// custom attributes, which are useful when DataSource is defined in a component
+// where a component specific export macro is used.
+#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
+ template <> \
+ attrs perfetto::internal::DataSourceType& \
+ perfetto::DataSourceHelper<__VA_ARGS__>::type()
+
+// This macro must be used once for each data source in one source file to
+// allocate static storage for the data source's static state.
+#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...) \
+ PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
+ PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)
+
+// Similar to `PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS` but it also takes
+// custom attributes, which are useful when DataSource is defined in a component
+// where a component specific export macro is used.
+#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
+ template <> \
+ perfetto::internal::DataSourceType& \
+ perfetto::DataSourceHelper<__VA_ARGS__>::type() { \
+ static perfetto::internal::DataSourceType type_; \
+ return type_; \
+ } \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
+
+#endif // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
+// gen_amalgamated begin header: include/perfetto/tracing/track_event.h
+// gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_data_source.h
+// gen_amalgamated begin header: include/perfetto/base/template_util.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_
+#define INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_
+
+#include <cstddef>
+#include <type_traits>
+
+namespace perfetto {
+namespace base {
+
+// Helper to express preferences in an overload set. If more than one overload
+// is available for a given set of parameters the overload with the higher
+// priority will be chosen.
+template <size_t I>
+struct priority_tag : priority_tag<I - 1> {};
+
+template <>
+struct priority_tag<0> {};
+
+// enable_if_t is an implementation of std::enable_if_t from C++14.
+//
+// Specification:
+// https://en.cppreference.com/w/cpp/types/enable_if
+template <bool B, class T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+// decay_t is an implementation of std::decay_t from C++14.
+//
+// Specification:
+// https://en.cppreference.com/w/cpp/types/decay
+template <class T>
+using decay_t = typename std::decay<T>::type;
+
+// remove_cvref is an implementation of std::remove_cvref from
+// C++20.
+//
+// Specification:
+// https://en.cppreference.com/w/cpp/types/remove_cvref
+
+template <class T>
+struct remove_cvref {
+ using type = typename std::remove_cv<typename std::remove_cv<
+ typename std::remove_reference<T>::type>::type>::type;
+};
+template <class T>
+using remove_cvref_t = typename remove_cvref<T>::type;
+
+// Check if a given type is a specialization of a given template:
+// is_specialization<T, std::vector>::value.
+
+template <typename Type, template <typename...> class Template>
+struct is_specialization : std::false_type {};
+
+template <template <typename...> class Ref, typename... Args>
+struct is_specialization<Ref<Args...>, Ref> : std::true_type {};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_
+// gen_amalgamated begin header: include/perfetto/tracing/event_context.h
+// gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_internal.h
+// gen_amalgamated begin header: include/perfetto/base/flat_set.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_FLAT_SET_H_
+#define INCLUDE_PERFETTO_BASE_FLAT_SET_H_
+
+#include <algorithm>
+#include <vector>
+
+// A vector-based set::set-like container.
+// It's more cache friendly than std::*set and performs for cases where:
+// 1. A high number of dupes is expected (e.g. pid tracking in ftrace).
+// 2. The working set is small (hundreds of elements).
+
+// Performance characteristics (for uniformly random insertion order):
+// - For smaller insertions (up to ~500), it outperforms both std::set<int> and
+// std::unordered_set<int> by ~3x.
+// - Up until 4k insertions, it is always faster than std::set<int>.
+// - unordered_set<int> is faster with more than 2k insertions.
+// - unordered_set, however, it's less memory efficient and has more caveats
+// (see chromium's base/containers/README.md).
+//
+// See flat_set_benchmark.cc and the charts in go/perfetto-int-set-benchmark.
+
+namespace perfetto {
+namespace base {
+
+template <typename T>
+class FlatSet {
+ public:
+ using value_type = T;
+ using const_pointer = const T*;
+ using iterator = typename std::vector<T>::iterator;
+ using const_iterator = typename std::vector<T>::const_iterator;
+
+ FlatSet() = default;
+
+ // Mainly for tests. Deliberately not marked as "explicit".
+ FlatSet(std::initializer_list<T> initial) : entries_(initial) {
+ std::sort(entries_.begin(), entries_.end());
+ entries_.erase(std::unique(entries_.begin(), entries_.end()),
+ entries_.end());
+ }
+
+ const_iterator find(T value) const {
+ auto entries_end = entries_.end();
+ auto it = std::lower_bound(entries_.begin(), entries_end, value);
+ return (it != entries_end && *it == value) ? it : entries_end;
+ }
+
+ size_t count(T value) const { return find(value) == entries_.end() ? 0 : 1; }
+
+ std::pair<iterator, bool> insert(T value) {
+ auto entries_end = entries_.end();
+ auto it = std::lower_bound(entries_.begin(), entries_end, value);
+ if (it != entries_end && *it == value)
+ return std::make_pair(it, false);
+ // If the value is not found |it| is either end() or the next item strictly
+ // greater than |value|. In both cases we want to insert just before that.
+ it = entries_.insert(it, std::move(value));
+ return std::make_pair(it, true);
+ }
+
+ size_t erase(T value) {
+ auto it = find(value);
+ if (it == entries_.end())
+ return 0;
+ entries_.erase(it);
+ return 1;
+ }
+
+ void clear() { entries_.clear(); }
+
+ bool empty() const { return entries_.empty(); }
+ void reserve(size_t n) { entries_.reserve(n); }
+ size_t size() const { return entries_.size(); }
+ const_iterator begin() const { return entries_.begin(); }
+ const_iterator end() const { return entries_.end(); }
+
+ private:
+ std::vector<T> entries_;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_FLAT_SET_H_
+// gen_amalgamated begin header: include/perfetto/protozero/scattered_heap_buffer.h
+// gen_amalgamated begin header: include/perfetto/protozero/root_message.h
+// gen_amalgamated begin header: include/perfetto/protozero/message_arena.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
+#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
+
+#include <stdint.h>
+
+#include <forward_list>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+
+namespace protozero {
+
+class Message;
+
+// Object allocator for fixed-sized protozero::Message objects.
+// It's a simple bump-pointer allocator which leverages the stack-alike
+// usage pattern of protozero nested messages. It avoids hitting the system
+// allocator in most cases, by reusing the same block, and falls back on
+// allocating new blocks only when using deeply nested messages (which are
+// extremely rare).
+// This is used by RootMessage<T> to handle the storage for root-level messages.
+class PERFETTO_EXPORT_COMPONENT MessageArena {
+ public:
+ MessageArena();
+ ~MessageArena();
+
+ // Strictly no copies or moves as this is used to hand out pointers.
+ MessageArena(const MessageArena&) = delete;
+ MessageArena& operator=(const MessageArena&) = delete;
+ MessageArena(MessageArena&&) = delete;
+ MessageArena& operator=(MessageArena&&) = delete;
+
+ // Allocates a new Message object.
+ Message* NewMessage();
+
+ // Deletes the last message allocated. The |msg| argument is used only for
+ // DCHECKs, it MUST be the pointer obtained by the last NewMessage() call.
+ void DeleteLastMessage(Message* msg) {
+ PERFETTO_DCHECK(!blocks_.empty() && blocks_.front().entries > 0);
+ PERFETTO_DCHECK(&blocks_.front().storage[blocks_.front().entries - 1] ==
+ static_cast<void*>(msg));
+ DeleteLastMessageInternal();
+ }
+
+ // Resets the state of the arena, clearing up all but one block. This is used
+ // to avoid leaking outstanding unfinished sub-messages while recycling the
+ // RootMessage object (this is extremely rare due to the RAII scoped handles
+ // but could happen if some client does some overly clever std::move() trick).
+ void Reset() {
+ PERFETTO_DCHECK(!blocks_.empty());
+ blocks_.resize(1);
+ auto& block = blocks_.front();
+ block.entries = 0;
+ PERFETTO_ASAN_POISON(block.storage, sizeof(block.storage));
+ }
+
+ private:
+ void DeleteLastMessageInternal();
+
+ struct Block {
+ static constexpr size_t kCapacity = 16;
+
+ Block() { PERFETTO_ASAN_POISON(storage, sizeof(storage)); }
+
+ std::aligned_storage<sizeof(Message), alignof(Message)>::type
+ storage[kCapacity];
+ uint32_t entries = 0; // # Message entries used (<= kCapacity).
+ };
+
+ // blocks are used to hand out pointers and must not be moved. Hence why
+ // std::list rather than std::vector.
+ std::forward_list<Block> blocks_;
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
+#define INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_arena.h"
+
+namespace protozero {
+
+// Helper class to hand out messages using the default MessageArena.
+// Usage:
+// RootMessage<perfetto::protos::zero::MyMessage> msg;
+// msg.Reset(stream_writer);
+// msg.set_foo(...);
+// auto* nested = msg.set_nested();
+template <typename T = Message>
+class RootMessage : public T {
+ public:
+ RootMessage() { T::Reset(nullptr, &root_arena_); }
+
+ // Disallow copy and move.
+ RootMessage(const RootMessage&) = delete;
+ RootMessage& operator=(const RootMessage&) = delete;
+ RootMessage(RootMessage&&) = delete;
+ RootMessage& operator=(RootMessage&&) = delete;
+
+ void Reset(ScatteredStreamWriter* writer) {
+ root_arena_.Reset();
+ Message::Reset(writer, &root_arena_);
+ }
+
+ private:
+ MessageArena root_arena_;
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_
+#define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/root_message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"
+
+namespace protozero {
+
+class Message;
+
+class PERFETTO_EXPORT_COMPONENT ScatteredHeapBuffer
+ : public protozero::ScatteredStreamWriter::Delegate {
+ public:
+ class PERFETTO_EXPORT_COMPONENT Slice {
+ public:
+ Slice();
+ explicit Slice(size_t size);
+ Slice(Slice&& slice) noexcept;
+ ~Slice();
+ Slice& operator=(Slice&&);
+
+ inline protozero::ContiguousMemoryRange GetTotalRange() const {
+ return {buffer_.get(), buffer_.get() + size_};
+ }
+
+ inline protozero::ContiguousMemoryRange GetUsedRange() const {
+ return {buffer_.get(), buffer_.get() + size_ - unused_bytes_};
+ }
+
+ uint8_t* start() const { return buffer_.get(); }
+ size_t size() const { return size_; }
+ size_t unused_bytes() const { return unused_bytes_; }
+ void set_unused_bytes(size_t unused_bytes) {
+ PERFETTO_DCHECK(unused_bytes_ <= size_);
+ unused_bytes_ = unused_bytes;
+ }
+
+ void Clear();
+
+ private:
+ std::unique_ptr<uint8_t[]> buffer_;
+ size_t size_;
+ size_t unused_bytes_;
+ };
+
+ ScatteredHeapBuffer(size_t initial_slice_size_bytes = 128,
+ size_t maximum_slice_size_bytes = 128 * 1024);
+ ~ScatteredHeapBuffer() override;
+
+ // protozero::ScatteredStreamWriter::Delegate implementation.
+ protozero::ContiguousMemoryRange GetNewBuffer() override;
+
+ // Return the slices backing this buffer, adjusted for the number of bytes the
+ // writer has written.
+ const std::vector<Slice>& GetSlices();
+
+ // Stitch all the slices into a single contiguous buffer.
+ std::vector<uint8_t> StitchSlices();
+
+ // Note that the returned ranges point back to this buffer and thus cannot
+ // outlive it.
+ std::vector<protozero::ContiguousMemoryRange> GetRanges();
+
+ // Note that size of the last slice isn't updated to reflect the number of
+ // bytes written by the trace writer.
+ const std::vector<Slice>& slices() const { return slices_; }
+
+ void set_writer(protozero::ScatteredStreamWriter* writer) {
+ writer_ = writer;
+ }
+
+ // Update unused_bytes() of the current |Slice| based on the writer's state.
+ void AdjustUsedSizeOfCurrentSlice();
+
+ // Returns the total size the slices occupy in heap memory (including unused).
+ size_t GetTotalSize();
+
+ // Reset the contents of this buffer but retain one slice allocation (if it
+ // exists) to be reused for future writes.
+ void Reset();
+
+ private:
+ size_t next_slice_size_;
+ const size_t maximum_slice_size_;
+ protozero::ScatteredStreamWriter* writer_ = nullptr;
+ std::vector<Slice> slices_;
+
+ // Used to keep an allocated slice around after this buffer is reset.
+ Slice cached_slice_;
+};
+
+// Helper function to create heap-based protozero messages in one line.
+// Useful when manually serializing a protozero message (primarily in
+// tests/utilities). So instead of the following:
+// protozero::MyMessage msg;
+// protozero::ScatteredHeapBuffer shb;
+// protozero::ScatteredStreamWriter writer(&shb);
+// shb.set_writer(&writer);
+// msg.Reset(&writer);
+// ...
+// You can write:
+// protozero::HeapBuffered<protozero::MyMessage> msg;
+// msg->set_stuff(...);
+// msg.SerializeAsString();
+template <typename T = ::protozero::Message>
+class HeapBuffered {
+ public:
+ HeapBuffered() : HeapBuffered(4096, 4096) {}
+ HeapBuffered(size_t initial_slice_size_bytes, size_t maximum_slice_size_bytes)
+ : shb_(initial_slice_size_bytes, maximum_slice_size_bytes),
+ writer_(&shb_) {
+ shb_.set_writer(&writer_);
+ msg_.Reset(&writer_);
+ }
+
+ // This can't be neither copied nor moved because Message hands out pointers
+ // to itself when creating submessages.
+ HeapBuffered(const HeapBuffered&) = delete;
+ HeapBuffered& operator=(const HeapBuffered&) = delete;
+ HeapBuffered(HeapBuffered&&) = delete;
+ HeapBuffered& operator=(HeapBuffered&&) = delete;
+
+ T* get() { return &msg_; }
+ T* operator->() { return &msg_; }
+
+ bool empty() const { return shb_.slices().empty(); }
+
+ std::vector<uint8_t> SerializeAsArray() {
+ msg_.Finalize();
+ return shb_.StitchSlices();
+ }
+
+ std::string SerializeAsString() {
+ auto vec = SerializeAsArray();
+ return std::string(reinterpret_cast<const char*>(vec.data()), vec.size());
+ }
+
+ std::vector<protozero::ContiguousMemoryRange> GetRanges() {
+ msg_.Finalize();
+ return shb_.GetRanges();
+ }
+
+ const std::vector<ScatteredHeapBuffer::Slice>& GetSlices() {
+ msg_.Finalize();
+ return shb_.GetSlices();
+ }
+
+ void Reset() {
+ shb_.Reset();
+ writer_.Reset(protozero::ContiguousMemoryRange{});
+ msg_.Reset(&writer_);
+ PERFETTO_DCHECK(empty());
+ }
+
+ private:
+ ScatteredHeapBuffer shb_;
+ ScatteredStreamWriter writer_;
+ RootMessage<T> msg_;
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_
+// gen_amalgamated begin header: include/perfetto/tracing/debug_annotation.h
+// gen_amalgamated begin header: include/perfetto/tracing/traced_value_forward.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
+#define INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
+
+namespace perfetto {
+
+class TracedValue;
+class TracedArray;
+class TracedDictionary;
+template <typename MessageType>
+class TracedProto;
+
+template <typename T>
+void WriteIntoTracedValue(TracedValue context, T&& value);
+template <typename MessageType, typename T>
+void WriteIntoTracedProto(TracedProto<MessageType> context, T&& value);
+
+template <typename T, class = void>
+struct TraceFormatTraits;
+
+// Helpers to check whether a given type T can be written into a TracedValue /
+// TracedProto<MessageType>.
+//
+// Intended to be used for types like smart pointers, who should support
+// WriteIntoTrace only iff their inner type supports being written into
+// a TracedValue.
+//
+// template <typename T>
+// class SmartPtr {
+// ...
+//
+// // Note: |Check| is needed to ensure that using
+// SmartPtr<ClassWhichDoesNotSupportTracedValue> does not generate a
+// compilation error.
+//
+// template <typename Check=void>
+// typename check_traced_value_support<T, Check>::value
+// WriteIntoTrace(perfetto::TracedValue context) const {
+// WriteIntoTracedValue(std::move(context), *ptr_);
+// }
+//
+// template <typename MessageType>
+// typename check_traced_value_support<T, MessageType>::value
+// WriteIntoTrace(perfetto::TracedProto<MessageType> message) const {
+// WriteIntoTracedProto(std::move(message), *ptr_);
+// }
+// };
+template <typename T, typename ResultType = void, typename = void>
+struct check_traced_value_support;
+
+template <typename MessageType,
+ typename T,
+ typename ResultType = void,
+ typename = void>
+struct check_traced_proto_support;
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/debug_annotation.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DebugAnnotation;
+class DebugAnnotation_NestedValue;
+namespace perfetto_pbzero_enum_DebugAnnotation_NestedValue {
+enum NestedType : int32_t;
+} // namespace perfetto_pbzero_enum_DebugAnnotation_NestedValue
+using DebugAnnotation_NestedValue_NestedType = perfetto_pbzero_enum_DebugAnnotation_NestedValue::NestedType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_DebugAnnotation_NestedValue {
+enum NestedType : int32_t {
+ UNSPECIFIED = 0,
+ DICT = 1,
+ ARRAY = 2,
+};
+} // namespace perfetto_pbzero_enum_DebugAnnotation_NestedValue
+using DebugAnnotation_NestedValue_NestedType = perfetto_pbzero_enum_DebugAnnotation_NestedValue::NestedType;
+
+
+constexpr DebugAnnotation_NestedValue_NestedType DebugAnnotation_NestedValue_NestedType_MIN = DebugAnnotation_NestedValue_NestedType::UNSPECIFIED;
+constexpr DebugAnnotation_NestedValue_NestedType DebugAnnotation_NestedValue_NestedType_MAX = DebugAnnotation_NestedValue_NestedType::ARRAY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* DebugAnnotation_NestedValue_NestedType_Name(::perfetto::protos::pbzero::DebugAnnotation_NestedValue_NestedType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::DebugAnnotation_NestedValue_NestedType::UNSPECIFIED:
+ return "UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::DebugAnnotation_NestedValue_NestedType::DICT:
+ return "DICT";
+
+ case ::perfetto::protos::pbzero::DebugAnnotation_NestedValue_NestedType::ARRAY:
+ return "ARRAY";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class DebugAnnotationValueTypeName_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DebugAnnotationValueTypeName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DebugAnnotationValueTypeName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DebugAnnotationValueTypeName_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+};
+
+class DebugAnnotationValueTypeName : public ::protozero::Message {
+ public:
+ using Decoder = DebugAnnotationValueTypeName_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DebugAnnotationValueTypeName"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DebugAnnotationValueTypeName>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotationValueTypeName>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DebugAnnotationName_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DebugAnnotationName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DebugAnnotationName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DebugAnnotationName_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+};
+
+class DebugAnnotationName : public ::protozero::Message {
+ public:
+ using Decoder = DebugAnnotationName_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DebugAnnotationName"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DebugAnnotationName>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotationName>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DebugAnnotation_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/17, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ DebugAnnotation_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DebugAnnotation_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DebugAnnotation_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name_iid() const { return at<1>().valid(); }
+ uint64_t name_iid() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<10>().valid(); }
+ ::protozero::ConstChars name() const { return at<10>().as_string(); }
+ bool has_bool_value() const { return at<2>().valid(); }
+ bool bool_value() const { return at<2>().as_bool(); }
+ bool has_uint_value() const { return at<3>().valid(); }
+ uint64_t uint_value() const { return at<3>().as_uint64(); }
+ bool has_int_value() const { return at<4>().valid(); }
+ int64_t int_value() const { return at<4>().as_int64(); }
+ bool has_double_value() const { return at<5>().valid(); }
+ double double_value() const { return at<5>().as_double(); }
+ bool has_pointer_value() const { return at<7>().valid(); }
+ uint64_t pointer_value() const { return at<7>().as_uint64(); }
+ bool has_nested_value() const { return at<8>().valid(); }
+ ::protozero::ConstBytes nested_value() const { return at<8>().as_bytes(); }
+ bool has_legacy_json_value() const { return at<9>().valid(); }
+ ::protozero::ConstChars legacy_json_value() const { return at<9>().as_string(); }
+ bool has_string_value() const { return at<6>().valid(); }
+ ::protozero::ConstChars string_value() const { return at<6>().as_string(); }
+ bool has_string_value_iid() const { return at<17>().valid(); }
+ uint64_t string_value_iid() const { return at<17>().as_uint64(); }
+ bool has_proto_type_name() const { return at<16>().valid(); }
+ ::protozero::ConstChars proto_type_name() const { return at<16>().as_string(); }
+ bool has_proto_type_name_iid() const { return at<13>().valid(); }
+ uint64_t proto_type_name_iid() const { return at<13>().as_uint64(); }
+ bool has_proto_value() const { return at<14>().valid(); }
+ ::protozero::ConstBytes proto_value() const { return at<14>().as_bytes(); }
+ bool has_dict_entries() const { return at<11>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> dict_entries() const { return GetRepeated<::protozero::ConstBytes>(11); }
+ bool has_array_values() const { return at<12>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> array_values() const { return GetRepeated<::protozero::ConstBytes>(12); }
+};
+
+class DebugAnnotation : public ::protozero::Message {
+ public:
+ using Decoder = DebugAnnotation_Decoder;
+ enum : int32_t {
+ kNameIidFieldNumber = 1,
+ kNameFieldNumber = 10,
+ kBoolValueFieldNumber = 2,
+ kUintValueFieldNumber = 3,
+ kIntValueFieldNumber = 4,
+ kDoubleValueFieldNumber = 5,
+ kPointerValueFieldNumber = 7,
+ kNestedValueFieldNumber = 8,
+ kLegacyJsonValueFieldNumber = 9,
+ kStringValueFieldNumber = 6,
+ kStringValueIidFieldNumber = 17,
+ kProtoTypeNameFieldNumber = 16,
+ kProtoTypeNameIidFieldNumber = 13,
+ kProtoValueFieldNumber = 14,
+ kDictEntriesFieldNumber = 11,
+ kArrayValuesFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DebugAnnotation"; }
+
+ using NestedValue = ::perfetto::protos::pbzero::DebugAnnotation_NestedValue;
+
+ using FieldMetadata_NameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_NameIid kNameIid{};
+ void set_name_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BoolValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_BoolValue kBoolValue{};
+ void set_bool_value(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BoolValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UintValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_UintValue kUintValue{};
+ void set_uint_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UintValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_DoubleValue kDoubleValue{};
+ void set_double_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PointerValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_PointerValue kPointerValue{};
+ void set_pointer_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PointerValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NestedValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation_NestedValue,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_NestedValue kNestedValue{};
+ template <typename T = DebugAnnotation_NestedValue> T* set_nested_value() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_LegacyJsonValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_LegacyJsonValue kLegacyJsonValue{};
+ void set_legacy_json_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LegacyJsonValue::kFieldId, data, size);
+ }
+ void set_legacy_json_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LegacyJsonValue::kFieldId, chars.data, chars.size);
+ }
+ void set_legacy_json_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LegacyJsonValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_StringValue kStringValue{};
+ void set_string_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, data, size);
+ }
+ void set_string_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, chars.data, chars.size);
+ }
+ void set_string_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValueIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_StringValueIid kStringValueIid{};
+ void set_string_value_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValueIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProtoTypeName =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_ProtoTypeName kProtoTypeName{};
+ void set_proto_type_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProtoTypeName::kFieldId, data, size);
+ }
+ void set_proto_type_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProtoTypeName::kFieldId, chars.data, chars.size);
+ }
+ void set_proto_type_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProtoTypeName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProtoTypeNameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_ProtoTypeNameIid kProtoTypeNameIid{};
+ void set_proto_type_name_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProtoTypeNameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProtoValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_ProtoValue kProtoValue{};
+ void set_proto_value(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_ProtoValue::kFieldId, data, size);
+ }
+ void set_proto_value(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_ProtoValue::kFieldId, bytes.data, bytes.size);
+ }
+ void set_proto_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProtoValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DictEntries =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_DictEntries kDictEntries{};
+ template <typename T = DebugAnnotation> T* add_dict_entries() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_ArrayValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation,
+ DebugAnnotation>;
+
+ static constexpr FieldMetadata_ArrayValues kArrayValues{};
+ template <typename T = DebugAnnotation> T* add_array_values() {
+ return BeginNestedMessage<T>(12);
+ }
+
+};
+
+class DebugAnnotation_NestedValue_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ DebugAnnotation_NestedValue_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DebugAnnotation_NestedValue_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DebugAnnotation_NestedValue_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nested_type() const { return at<1>().valid(); }
+ int32_t nested_type() const { return at<1>().as_int32(); }
+ bool has_dict_keys() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> dict_keys() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_dict_values() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> dict_values() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_array_values() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> array_values() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_int_value() const { return at<5>().valid(); }
+ int64_t int_value() const { return at<5>().as_int64(); }
+ bool has_double_value() const { return at<6>().valid(); }
+ double double_value() const { return at<6>().as_double(); }
+ bool has_bool_value() const { return at<7>().valid(); }
+ bool bool_value() const { return at<7>().as_bool(); }
+ bool has_string_value() const { return at<8>().valid(); }
+ ::protozero::ConstChars string_value() const { return at<8>().as_string(); }
+};
+
+class DebugAnnotation_NestedValue : public ::protozero::Message {
+ public:
+ using Decoder = DebugAnnotation_NestedValue_Decoder;
+ enum : int32_t {
+ kNestedTypeFieldNumber = 1,
+ kDictKeysFieldNumber = 2,
+ kDictValuesFieldNumber = 3,
+ kArrayValuesFieldNumber = 4,
+ kIntValueFieldNumber = 5,
+ kDoubleValueFieldNumber = 6,
+ kBoolValueFieldNumber = 7,
+ kStringValueFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DebugAnnotation.NestedValue"; }
+
+
+ using NestedType = ::perfetto::protos::pbzero::DebugAnnotation_NestedValue_NestedType;
+ static inline const char* NestedType_Name(NestedType value) {
+ return ::perfetto::protos::pbzero::DebugAnnotation_NestedValue_NestedType_Name(value);
+ }
+ static inline const NestedType UNSPECIFIED = NestedType::UNSPECIFIED;
+ static inline const NestedType DICT = NestedType::DICT;
+ static inline const NestedType ARRAY = NestedType::ARRAY;
+
+ using FieldMetadata_NestedType =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ DebugAnnotation_NestedValue_NestedType,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_NestedType kNestedType{};
+ void set_nested_type(DebugAnnotation_NestedValue_NestedType value) {
+ static constexpr uint32_t field_id = FieldMetadata_NestedType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DictKeys =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_DictKeys kDictKeys{};
+ void add_dict_keys(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DictKeys::kFieldId, data, size);
+ }
+ void add_dict_keys(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DictKeys::kFieldId, chars.data, chars.size);
+ }
+ void add_dict_keys(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DictKeys::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DictValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation_NestedValue,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_DictValues kDictValues{};
+ template <typename T = DebugAnnotation_NestedValue> T* add_dict_values() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_ArrayValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation_NestedValue,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_ArrayValues kArrayValues{};
+ template <typename T = DebugAnnotation_NestedValue> T* add_array_values() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_DoubleValue kDoubleValue{};
+ void set_double_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BoolValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_BoolValue kBoolValue{};
+ void set_bool_value(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BoolValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DebugAnnotation_NestedValue>;
+
+ static constexpr FieldMetadata_StringValue kStringValue{};
+ void set_string_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, data, size);
+ }
+ void set_string_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, chars.data, chars.size);
+ }
+ void set_string_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_DEBUG_ANNOTATION_H_
+#define INCLUDE_PERFETTO_TRACING_DEBUG_ANNOTATION_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_value_forward.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+namespace {
+// std::underlying_type can't be used with non-enum types, so we need this
+// indirection.
+template <typename T, bool = std::is_enum<T>::value>
+struct safe_underlying_type {
+ using type = typename std::underlying_type<T>::type;
+};
+
+template <typename T>
+struct safe_underlying_type<T, false> {
+ using type = T;
+};
+} // namespace
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DebugAnnotation;
+} // namespace pbzero
+} // namespace protos
+
+// A base class for custom track event debug annotations.
+class PERFETTO_EXPORT_COMPONENT DebugAnnotation {
+ public:
+ DebugAnnotation() = default;
+ virtual ~DebugAnnotation();
+
+ // Called to write the contents of the debug annotation into the trace.
+ virtual void Add(protos::pbzero::DebugAnnotation*) const = 0;
+
+ void WriteIntoTracedValue(TracedValue context) const;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_DEBUG_ANNOTATION_H_
+// gen_amalgamated begin header: include/perfetto/tracing/traced_value.h
+// gen_amalgamated begin header: include/perfetto/tracing/internal/checked_scope.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_CHECKED_SCOPE_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_CHECKED_SCOPE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace internal {
+
+#if PERFETTO_DCHECK_IS_ON()
+
+// Checker to ensure that despite multiple scopes being present, only the active
+// one is being accessed. Rules:
+// - Only an active scope can create inner scopes. When this happens, it stops
+// being active and the inner scope becomes active instead.
+// - Only an active scope can be destroyed. When this happens, its parent scope
+// becomes active.
+class PERFETTO_EXPORT_COMPONENT CheckedScope {
+ public:
+ explicit CheckedScope(CheckedScope* parent_scope);
+ ~CheckedScope();
+ CheckedScope(CheckedScope&&);
+ CheckedScope& operator=(CheckedScope&&);
+ CheckedScope(const CheckedScope&) = delete;
+ CheckedScope& operator=(const CheckedScope&) = delete;
+
+ void Reset();
+
+ CheckedScope* parent_scope() const { return parent_scope_; }
+ bool is_active() const { return is_active_; }
+
+ private:
+ void set_is_active(bool is_active) { is_active_ = is_active; }
+
+ bool is_active_ = true;
+ CheckedScope* parent_scope_;
+
+ bool deleted_ = false;
+};
+
+#else
+
+// Dummy for cases when DCHECK is not enabled. Methods are marked constexpr to
+// ensure that the compiler can inline and optimise them away.
+class CheckedScope {
+ public:
+ inline explicit CheckedScope(CheckedScope*) {}
+ inline ~CheckedScope() {}
+
+ CheckedScope(const CheckedScope&) = delete;
+ CheckedScope& operator=(const CheckedScope&) = delete;
+
+ CheckedScope(CheckedScope&&) = default;
+ CheckedScope& operator=(CheckedScope&&) = default;
+
+ inline void Reset() {}
+
+ inline CheckedScope* parent_scope() const { return nullptr; }
+ inline bool is_active() const { return true; }
+};
+
+#endif // PERFETTO_DCHECK_IS_ON()
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_CHECKED_SCOPE_H_
+// gen_amalgamated begin header: include/perfetto/tracing/string_helpers.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
+#define INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+
+#include <cstddef>
+#include <string>
+
+namespace perfetto {
+
+// A wrapper for marking strings that can't be determined to be static at build
+// time, but are in fact static.
+class PERFETTO_EXPORT_COMPONENT StaticString {
+ public:
+ // Implicit constructor for string literals.
+ template <size_t N>
+ constexpr StaticString(const char (&str)[N]) : value(str) {}
+
+ // Implicit constructor for null strings.
+ constexpr StaticString(std::nullptr_t) : value(nullptr) {}
+
+ constexpr explicit StaticString(const char* str) : value(str) {}
+
+ const char* value;
+};
+
+// A explicit wrapper for marking strings as dynamic to ensure that perfetto
+// doesn't try to cache the pointer value.
+class PERFETTO_EXPORT_COMPONENT DynamicString {
+ public:
+ explicit DynamicString(const std::string& str)
+ : value(str.data()), length(str.length()) {}
+ explicit DynamicString(const char* str) : value(str) {
+ PERFETTO_DCHECK(str);
+ length = strlen(str);
+ }
+ DynamicString(const char* str, size_t len) : value(str), length(len) {}
+
+ const char* value;
+ size_t length;
+};
+
+namespace internal {
+
+template <size_t N>
+constexpr const char* GetStaticString(const char (&string)[N]) {
+ return string;
+}
+
+constexpr std::nullptr_t GetStaticString(std::nullptr_t) {
+ return nullptr;
+}
+
+constexpr const char* GetStaticString(perfetto::StaticString string) {
+ return string.value;
+}
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
+#define INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/template_util.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/checked_scope.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/string_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_value_forward.h"
+
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+
+namespace perfetto {
+
+namespace protos {
+namespace pbzero {
+class DebugAnnotation;
+}
+} // namespace protos
+
+class DebugAnnotation;
+class EventContext;
+
+// These classes provide a JSON-inspired way to write structed data into traces.
+//
+// Each TracedValue can be consumed exactly once to write a value into a trace
+// using one of the Write* methods.
+//
+// Write* methods fall into two categories:
+// - Primitive types (int, string, bool, double, etc): they just write the
+// provided value, consuming the TracedValue in the process.
+// - Complex types (arrays and dicts): they consume the TracedValue and
+// return a corresponding scoped object (TracedArray or TracedDictionary).
+// This scope then can be used to write multiple items into the container:
+// TracedArray::AppendItem and TracedDictionary::AddItem return a new
+// TracedValue which then can be used to write an element of the
+// dictionary or array.
+//
+// To define how a custom class should be written into the trace, users should
+// define one of the two following functions:
+// - Foo::WriteIntoTrace(TracedValue) const
+// (preferred for code which depends on perfetto directly)
+// - perfetto::TraceFormatTraits<T>::WriteIntoTrace(
+// TracedValue, const T&);
+// (should be used if T is defined in a library which doesn't know anything
+// about tracing).
+//
+//
+// After defining a conversion method, the object can be used directly as a
+// TRACE_EVENT argument:
+//
+// Foo foo;
+// TRACE_EVENT("cat", "Event", "arg", foo);
+//
+// Examples:
+//
+// TRACE_EVENT("cat", "event", "params", [&](perfetto::TracedValue context)
+// {
+// auto dict = std::move(context).WriteDictionary();
+// dict->Add("param1", param1);
+// dict->Add("param2", param2);
+// ...
+// dict->Add("paramN", paramN);
+//
+// {
+// auto inner_array = dict->AddArray("inner");
+// inner_array->Append(value1);
+// inner_array->Append(value2);
+// }
+// });
+//
+// template <typename T>
+// TraceFormatTraits<std::optional<T>>::WriteIntoTrace(
+// TracedValue context, const std::optional<T>& value) {
+// if (!value) {
+// std::move(context).WritePointer(nullptr);
+// return;
+// }
+// perfetto::WriteIntoTrace(std::move(context), *value);
+// }
+//
+// template <typename T>
+// TraceFormatTraits<std::vector<T>>::WriteIntoTrace(
+// TracedValue context, const std::array<T>& value) {
+// auto array = std::move(context).WriteArray();
+// for (const auto& item: value) {
+// array_scope.Append(item);
+// }
+// }
+//
+// class Foo {
+// void WriteIntoTrace(TracedValue context) const {
+// auto dict = std::move(context).WriteDictionary();
+// dict->Set("key", 42);
+// dict->Set("foo", "bar");
+// dict->Set("member", member_);
+// }
+// }
+namespace internal {
+// TODO(altimin): Currently EventContext can be null due the need to support
+// TracedValue-based serialisation with the Chrome's TraceLog. After this is
+// gone, the second parameter should be changed to EventContext&.
+PERFETTO_EXPORT_COMPONENT TracedValue
+CreateTracedValueFromProto(protos::pbzero::DebugAnnotation*,
+ EventContext* = nullptr);
+}
+
+class PERFETTO_EXPORT_COMPONENT TracedValue {
+ public:
+ TracedValue(const TracedValue&) = delete;
+ TracedValue& operator=(const TracedValue&) = delete;
+ TracedValue& operator=(TracedValue&&) = delete;
+ TracedValue(TracedValue&&);
+ ~TracedValue();
+
+ // TracedValue represents a context into which a single value can be written
+ // (either by writing it directly for primitive types, or by creating a
+ // TracedArray or TracedDictionary for the complex types). This is enforced
+ // by allowing Write* methods to be called only on rvalue references.
+
+ void WriteInt64(int64_t value) &&;
+ void WriteUInt64(uint64_t value) &&;
+ void WriteDouble(double value) &&;
+ void WriteBoolean(bool value) &&;
+ void WriteString(const char*) &&;
+ void WriteString(const char*, size_t len) &&;
+ void WriteString(const std::string&) &&;
+ void WriteString(std::string_view) &&;
+ void WritePointer(const void* value) &&;
+ template <typename MessageType>
+ TracedProto<MessageType> WriteProto() &&;
+
+ // Rules for writing nested dictionaries and arrays:
+ // - Only one scope (TracedArray, TracedDictionary or TracedValue) can be
+ // active at the same time. It's only allowed to call methods on the active
+ // scope.
+ // - When a scope creates a nested scope, the new scope becomes active.
+ // - When a scope is destroyed, its parent scope becomes active again.
+ //
+ // Typically users will have to create a scope only at the beginning of a
+ // conversion function and this scope should be destroyed at the end of it.
+ // TracedArray::Append and TracedDictionary::Add create, write and complete
+ // inner scopes automatically.
+
+ // Scope which allows multiple values to be appended.
+ TracedArray WriteArray() && PERFETTO_WARN_UNUSED_RESULT;
+
+ // Scope which allows multiple key-value pairs to be added.
+ TracedDictionary WriteDictionary() && PERFETTO_WARN_UNUSED_RESULT;
+
+ private:
+ friend class TracedArray;
+ friend class TracedDictionary;
+ friend TracedValue internal::CreateTracedValueFromProto(
+ protos::pbzero::DebugAnnotation*,
+ EventContext*);
+
+ static TracedValue CreateFromProto(protos::pbzero::DebugAnnotation* proto,
+ EventContext* event_context = nullptr);
+
+ inline TracedValue(protos::pbzero::DebugAnnotation* annotation,
+ EventContext* event_context,
+ internal::CheckedScope* parent_scope)
+ : annotation_(annotation),
+ event_context_(event_context),
+ checked_scope_(parent_scope) {}
+
+ protozero::Message* WriteProtoInternal(const char* name);
+
+ // Temporary support for perfetto::DebugAnnotation C++ class before it's going
+ // to be replaced by TracedValue.
+ // TODO(altimin): Convert v8 to use TracedValue directly and delete it.
+ friend class DebugAnnotation;
+
+ protos::pbzero::DebugAnnotation* const annotation_ = nullptr;
+ EventContext* const event_context_ = nullptr;
+
+ internal::CheckedScope checked_scope_;
+};
+
+template <typename MessageType>
+TracedProto<MessageType> TracedValue::WriteProto() && {
+ return TracedProto<MessageType>(
+ static_cast<MessageType*>(WriteProtoInternal(MessageType::GetName())),
+ event_context_);
+}
+
+class PERFETTO_EXPORT_COMPONENT TracedArray {
+ public:
+ // implicit
+ TracedArray(TracedValue);
+
+ TracedArray(const TracedArray&) = delete;
+ TracedArray& operator=(const TracedArray&) = delete;
+ TracedArray& operator=(TracedArray&&) = delete;
+ TracedArray(TracedArray&&) = default;
+ ~TracedArray() = default;
+
+ TracedValue AppendItem();
+
+ template <typename T>
+ void Append(T&& value) {
+ WriteIntoTracedValue(AppendItem(), std::forward<T>(value));
+ }
+
+ TracedDictionary AppendDictionary() PERFETTO_WARN_UNUSED_RESULT;
+ TracedArray AppendArray();
+
+ private:
+ friend class TracedValue;
+
+ inline TracedArray(protos::pbzero::DebugAnnotation* annotation,
+ EventContext* event_context,
+ internal::CheckedScope* parent_scope)
+ : annotation_(annotation),
+ event_context_(event_context),
+ checked_scope_(parent_scope) {}
+
+ protos::pbzero::DebugAnnotation* annotation_;
+ EventContext* const event_context_;
+
+ internal::CheckedScope checked_scope_;
+};
+
+class PERFETTO_EXPORT_COMPONENT TracedDictionary {
+ public:
+ // implicit
+ TracedDictionary(TracedValue);
+
+ TracedDictionary(const TracedDictionary&) = delete;
+ TracedDictionary& operator=(const TracedDictionary&) = delete;
+ TracedDictionary& operator=(TracedDictionary&&) = delete;
+ TracedDictionary(TracedDictionary&&) = default;
+ ~TracedDictionary() = default;
+
+ // There are two paths for writing dictionary keys: fast path for writing
+ // compile-time const, whose pointer is remains valid during the entire
+ // runtime of the program and the slow path for dynamic strings, which need to
+ // be copied.
+ // In the most common case, a string literal can be passed to `Add`/`AddItem`.
+ // In other cases, either StaticString or DynamicString declarations are
+ // needed.
+
+ TracedValue AddItem(StaticString key);
+ TracedValue AddItem(DynamicString key);
+
+ template <typename T>
+ void Add(StaticString key, T&& value) {
+ WriteIntoTracedValue(AddItem(key), std::forward<T>(value));
+ }
+
+ template <typename T>
+ void Add(DynamicString key, T&& value) {
+ WriteIntoTracedValue(AddItem(key), std::forward<T>(value));
+ }
+
+ TracedDictionary AddDictionary(StaticString key);
+ TracedDictionary AddDictionary(DynamicString key);
+ TracedArray AddArray(StaticString key);
+ TracedArray AddArray(DynamicString key);
+
+ private:
+ friend class TracedValue;
+ template <typename T>
+ friend class TracedProto;
+
+ // Create a |TracedDictionary| which will populate the given field of the
+ // given |message|.
+ template <typename MessageType, typename FieldMetadata>
+ inline TracedDictionary(MessageType* message,
+ FieldMetadata,
+ EventContext* event_context,
+ internal::CheckedScope* parent_scope)
+ : message_(message),
+ field_id_(FieldMetadata::kFieldId),
+ event_context_(event_context),
+ checked_scope_(parent_scope) {
+ static_assert(std::is_base_of<protozero::Message, MessageType>::value,
+ "Message should be a subclass of protozero::Message");
+ static_assert(std::is_base_of<protozero::proto_utils::FieldMetadataBase,
+ FieldMetadata>::value,
+ "FieldMetadata should be a subclass of FieldMetadataBase");
+ static_assert(
+ std::is_same<typename FieldMetadata::message_type, MessageType>::value,
+ "Field does not belong to this message");
+ static_assert(
+ std::is_same<typename FieldMetadata::cpp_field_type,
+ ::perfetto::protos::pbzero::DebugAnnotation>::value,
+ "Field should be of DebugAnnotation type");
+ static_assert(
+ FieldMetadata::kRepetitionType ==
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ "Field should be non-packed repeated");
+ }
+
+ protozero::Message* const message_;
+ const uint32_t field_id_;
+ EventContext* event_context_;
+
+ internal::CheckedScope checked_scope_;
+};
+
+namespace internal {
+
+// SFINAE helpers for finding a right overload to convert a given class to
+// trace-friendly form, ordered from most to least preferred.
+
+constexpr int kMaxWriteImplPriority = 4;
+
+// If T has WriteIntoTracedValue member function, call it.
+template <typename T>
+decltype(std::declval<T>().WriteIntoTracedValue(std::declval<TracedValue>()),
+ void())
+WriteImpl(base::priority_tag<4>, TracedValue context, T&& value) {
+ value.WriteIntoTracedValue(std::move(context));
+}
+
+// If T has WriteIntoTrace member function, call it.
+template <typename T>
+decltype(std::declval<T>().WriteIntoTrace(std::declval<TracedValue>()), void())
+WriteImpl(base::priority_tag<4>, TracedValue context, T&& value) {
+ value.WriteIntoTrace(std::move(context));
+}
+
+// If perfetto::TraceFormatTraits<T>::WriteIntoTracedValue(TracedValue, const
+// T&) is available, use it.
+template <typename T>
+decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTracedValue(
+ std::declval<TracedValue>(),
+ std::declval<T>()),
+ void())
+WriteImpl(base::priority_tag<3>, TracedValue context, T&& value) {
+ TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTracedValue(
+ std::move(context), std::forward<T>(value));
+}
+
+// If perfetto::TraceFormatTraits<T>::WriteIntoTrace(TracedValue, const T&)
+// is available, use it.
+template <typename T>
+decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
+ std::declval<TracedValue>(),
+ std::declval<T>()),
+ void())
+WriteImpl(base::priority_tag<3>, TracedValue context, T&& value) {
+ TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
+ std::move(context), std::forward<T>(value));
+}
+
+// If T has operator(), which takes TracedValue, use it.
+// Very useful for lambda resolutions.
+template <typename T>
+decltype(std::declval<T>()(std::declval<TracedValue>()), void())
+WriteImpl(base::priority_tag<2>, TracedValue context, T&& value) {
+ std::forward<T>(value)(std::move(context));
+}
+
+// If T is a container and its elements have tracing support, use it.
+//
+// Note: a reference to T should be passed to std::begin, otherwise
+// for non-reference types const T& will be passed to std::begin, losing
+// support for non-const WriteIntoTracedValue methods.
+template <typename T>
+typename check_traced_value_support<
+ decltype(*std::begin(std::declval<T&>()))>::type
+WriteImpl(base::priority_tag<1>, TracedValue context, T&& value) {
+ auto array = std::move(context).WriteArray();
+ for (auto&& item : value) {
+ array.Append(item);
+ }
+}
+
+// std::underlying_type can't be used with non-enum types, so we need this
+// indirection.
+template <typename T, bool = std::is_enum<T>::value>
+struct safe_underlying_type {
+ using type = typename std::underlying_type<T>::type;
+};
+
+template <typename T>
+struct safe_underlying_type<T, false> {
+ using type = T;
+};
+
+template <typename T>
+struct is_incomplete_type {
+ static constexpr bool value = sizeof(T) != 0;
+};
+
+// sizeof is not available for const char[], but it's still not considered to be
+// an incomplete type for our purposes as the size can be determined at runtime
+// due to strings being null-terminated.
+template <>
+struct is_incomplete_type<const char[]> {
+ static constexpr bool value = true;
+};
+
+} // namespace internal
+
+// Helper template to determine if a given type can be passed to
+// perfetto::WriteIntoTracedValue. These templates will fail to resolve if the
+// class does not have it support, so they are useful in SFINAE and in producing
+// helpful compiler results.
+template <typename T, class Result = void>
+using check_traced_value_support_t = decltype(
+ internal::WriteImpl(
+ std::declval<base::priority_tag<internal::kMaxWriteImplPriority>>(),
+ std::declval<TracedValue>(),
+ std::declval<T>()),
+ std::declval<Result>());
+
+// check_traced_value_support<T, V>::type is defined (and equal to V) iff T
+// supports being passed to WriteIntoTracedValue. See the comment in
+// traced_value_forward.h for more details.
+template <typename T, class Result>
+struct check_traced_value_support<T,
+ Result,
+ check_traced_value_support_t<T, Result>> {
+ static_assert(
+ internal::is_incomplete_type<T>::value,
+ "perfetto::TracedValue should not be used with incomplete types");
+
+ static constexpr bool value = true;
+ using type = Result;
+};
+
+namespace internal {
+
+// Helper class to check if a given type can be passed to
+// perfetto::WriteIntoTracedValue. This template will always resolve (with
+// |value| being set to either true or false depending on presence of the
+// support, so this macro is useful in the situation when you want to e.g. OR
+// the result with some other conditions.
+//
+// In this case, compiler will not give you the full deduction chain, so, for
+// example, use check_traced_value_support for writing positive static_asserts
+// and has_traced_value_support for writing negative.
+template <typename T>
+class has_traced_value_support {
+ using Yes = char[1];
+ using No = char[2];
+
+ template <typename V>
+ static Yes& check_support(check_traced_value_support_t<V, int>);
+ template <typename V>
+ static No& check_support(...);
+
+ public:
+ static constexpr bool value = sizeof(Yes) == sizeof(check_support<T>(0));
+};
+
+} // namespace internal
+
+template <typename T>
+void WriteIntoTracedValue(TracedValue context, T&& value) {
+ // TODO(altimin): Add a URL to documentation and a list of common failure
+ // patterns.
+ static_assert(
+ internal::has_traced_value_support<T>::value,
+ "The provided type (passed to TRACE_EVENT argument / TracedArray::Append "
+ "/ TracedDictionary::Add) does not support being written in a trace "
+ "format. Please see the comment in traced_value.h for more details.");
+
+ // Should be kept in sync with check_traced_value_support_t!
+ internal::WriteImpl(base::priority_tag<internal::kMaxWriteImplPriority>(),
+ std::move(context), std::forward<T>(value));
+}
+
+// Helpers to write a given value into TracedValue even if the given type
+// doesn't support conversion (in which case the provided fallback should be
+// used). Useful for automatically generating conversions for autogenerated
+// code, but otherwise shouldn't be used as non-autogenerated code is expected
+// to define WriteIntoTracedValue convertor.
+// See WriteWithFallback test in traced_value_unittest.cc for a concrete
+// example.
+template <typename T>
+typename std::enable_if<internal::has_traced_value_support<T>::value>::type
+WriteIntoTracedValueWithFallback(TracedValue context,
+ T&& value,
+ const std::string&) {
+ WriteIntoTracedValue(std::move(context), std::forward<T>(value));
+}
+
+template <typename T>
+typename std::enable_if<!internal::has_traced_value_support<T>::value>::type
+WriteIntoTracedValueWithFallback(TracedValue context,
+ T&&,
+ const std::string& fallback) {
+ std::move(context).WriteString(fallback);
+}
+
+// TraceFormatTraits implementations for primitive types.
+
+// Specialisation for signed integer types (note: it excludes enums, which have
+// their own explicit specialisation).
+template <typename T>
+struct TraceFormatTraits<
+ T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ !std::is_same<T, bool>::value &&
+ std::is_signed<T>::value>::type> {
+ inline static void WriteIntoTrace(TracedValue context, T value) {
+ std::move(context).WriteInt64(value);
+ }
+};
+
+// Specialisation for unsigned integer types (note: it excludes enums, which
+// have their own explicit specialisation).
+template <typename T>
+struct TraceFormatTraits<
+ T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ !std::is_same<T, bool>::value &&
+ std::is_unsigned<T>::value>::type> {
+ inline static void WriteIntoTrace(TracedValue context, T value) {
+ std::move(context).WriteUInt64(value);
+ }
+};
+
+// Specialisation for bools.
+template <>
+struct TraceFormatTraits<bool> {
+ inline static void WriteIntoTrace(TracedValue context, bool value) {
+ std::move(context).WriteBoolean(value);
+ }
+};
+
+// Specialisation for floating point values.
+template <typename T>
+struct TraceFormatTraits<
+ T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type> {
+ inline static void WriteIntoTrace(TracedValue context, T value) {
+ std::move(context).WriteDouble(static_cast<double>(value));
+ }
+};
+
+// Specialisation for signed enums.
+template <typename T>
+struct TraceFormatTraits<
+ T,
+ typename std::enable_if<
+ std::is_enum<T>::value &&
+ std::is_signed<
+ typename internal::safe_underlying_type<T>::type>::value>::type> {
+ inline static void WriteIntoTrace(TracedValue context, T value) {
+ std::move(context).WriteInt64(static_cast<int64_t>(value));
+ }
+};
+
+// Specialisation for unsigned enums.
+template <typename T>
+struct TraceFormatTraits<
+ T,
+ typename std::enable_if<
+ std::is_enum<T>::value &&
+ std::is_unsigned<
+ typename internal::safe_underlying_type<T>::type>::value>::type> {
+ inline static void WriteIntoTrace(TracedValue context, T value) {
+ std::move(context).WriteUInt64(static_cast<uint64_t>(value));
+ }
+};
+
+// Specialisations for C-style strings.
+template <>
+struct TraceFormatTraits<const char*> {
+ inline static void WriteIntoTrace(TracedValue context, const char* value) {
+ std::move(context).WriteString(value);
+ }
+};
+
+template <>
+struct TraceFormatTraits<char[]> {
+ inline static void WriteIntoTrace(TracedValue context, const char value[]) {
+ std::move(context).WriteString(value);
+ }
+};
+
+template <size_t N>
+struct TraceFormatTraits<char[N]> {
+ inline static void WriteIntoTrace(TracedValue context, const char value[N]) {
+ std::move(context).WriteString(value);
+ }
+};
+
+// Specialization for Perfetto strings.
+template <>
+struct TraceFormatTraits<perfetto::StaticString> {
+ inline static void WriteIntoTrace(TracedValue context,
+ perfetto::StaticString str) {
+ std::move(context).WriteString(str.value);
+ }
+};
+
+template <>
+struct TraceFormatTraits<perfetto::DynamicString> {
+ inline static void WriteIntoTrace(TracedValue context,
+ perfetto::DynamicString str) {
+ std::move(context).WriteString(str.value, str.length);
+ }
+};
+
+// Specialisation for C++ strings.
+template <>
+struct TraceFormatTraits<std::string> {
+ inline static void WriteIntoTrace(TracedValue context,
+ const std::string& value) {
+ std::move(context).WriteString(value);
+ }
+};
+
+// Specialisation for C++ string_views.
+template <>
+struct TraceFormatTraits<std::string_view> {
+ inline static void WriteIntoTrace(TracedValue context,
+ std::string_view value) {
+ std::move(context).WriteString(value);
+ }
+};
+
+// Specialisation for (const) void*, which writes the pointer value.
+template <>
+struct TraceFormatTraits<void*> {
+ inline static void WriteIntoTrace(TracedValue context, void* value) {
+ std::move(context).WritePointer(value);
+ }
+};
+
+template <>
+struct TraceFormatTraits<const void*> {
+ inline static void WriteIntoTrace(TracedValue context, const void* value) {
+ std::move(context).WritePointer(value);
+ }
+};
+
+// Specialisation for std::unique_ptr<>, which writes either nullptr or the
+// object it points to.
+template <typename T>
+struct TraceFormatTraits<std::unique_ptr<T>, check_traced_value_support_t<T>> {
+ inline static void WriteIntoTrace(TracedValue context,
+ const std::unique_ptr<T>& value) {
+ ::perfetto::WriteIntoTracedValue(std::move(context), value.get());
+ }
+
+ template <typename MessageType>
+ inline static void WriteIntoTrace(TracedProto<MessageType> message,
+ const std::unique_ptr<T>& value) {
+ ::perfetto::WriteIntoTracedProto(std::move(message), value.get());
+ }
+};
+
+// Specialisation for raw pointer, which writes either nullptr or the object it
+// points to.
+template <typename T>
+struct TraceFormatTraits<T*, check_traced_value_support_t<T>> {
+ inline static void WriteIntoTrace(TracedValue context, T* value) {
+ if (!value) {
+ std::move(context).WritePointer(nullptr);
+ return;
+ }
+ ::perfetto::WriteIntoTracedValue(std::move(context), *value);
+ }
+
+ template <typename MessageType>
+ inline static void WriteIntoTrace(TracedProto<MessageType> message,
+ T* value) {
+ if (!value) {
+ // Start the message, but do not write anything. TraceProcessor will emit
+ // a NULL value.
+ return;
+ }
+
+ ::perfetto::WriteIntoTracedProto(std::move(message), *value);
+ }
+};
+
+// Specialisation for nullptr.
+template <>
+struct TraceFormatTraits<std::nullptr_t> {
+ inline static void WriteIntoTrace(TracedValue context, std::nullptr_t) {
+ std::move(context).WritePointer(nullptr);
+ }
+
+ template <typename MessageType>
+ inline static void WriteIntoTrace(TracedProto<MessageType>, std::nullptr_t) {
+ // Start the message, but do not write anything. TraceProcessor will emit a
+ // NULL value.
+ }
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
+// gen_amalgamated begin header: include/perfetto/tracing/track.h
+// gen_amalgamated begin header: include/perfetto/tracing/internal/fnv1a.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_FNV1A_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_FNV1A_H_
+
+#include <cstddef>
+#include <cstdint>
+
+namespace perfetto {
+namespace internal {
+
+// Constexpr functions to compute a 64-bit hash of the input data. The algorithm
+// used is FNV-1a as it is fast and easy to implement and has relatively few
+// collisions.
+//
+// WARNING: This hash function should not be used for any cryptographic purpose.
+
+static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325;
+static constexpr uint64_t kFnv1a64Prime = 0x100000001b3;
+
+static constexpr inline uint64_t Fnv1a(const char* s) {
+ uint64_t ret = kFnv1a64OffsetBasis;
+ for (; *s; s++) {
+ ret = ret ^ static_cast<uint8_t>(*s);
+ ret *= kFnv1a64Prime;
+ }
+ return ret;
+}
+
+static constexpr inline uint64_t Fnv1a(const void* data, size_t size) {
+ uint64_t ret = kFnv1a64OffsetBasis;
+ const uint8_t* s = static_cast<const uint8_t*>(data);
+ for (size_t i = 0; i < size; i++) {
+ ret = ret ^ s[i];
+ ret *= kFnv1a64Prime;
+ }
+ return ret;
+}
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_FNV1A_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/counter_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_COUNTER_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_COUNTER_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class CounterDescriptor;
+enum CounterDescriptor_BuiltinCounterType : int;
+enum CounterDescriptor_Unit : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum CounterDescriptor_BuiltinCounterType : int {
+ CounterDescriptor_BuiltinCounterType_COUNTER_UNSPECIFIED = 0,
+ CounterDescriptor_BuiltinCounterType_COUNTER_THREAD_TIME_NS = 1,
+ CounterDescriptor_BuiltinCounterType_COUNTER_THREAD_INSTRUCTION_COUNT = 2,
+};
+enum CounterDescriptor_Unit : int {
+ CounterDescriptor_Unit_UNIT_UNSPECIFIED = 0,
+ CounterDescriptor_Unit_UNIT_TIME_NS = 1,
+ CounterDescriptor_Unit_UNIT_COUNT = 2,
+ CounterDescriptor_Unit_UNIT_SIZE_BYTES = 3,
+};
+
+class PERFETTO_EXPORT_COMPONENT CounterDescriptor : public ::protozero::CppMessageObj {
+ public:
+ using BuiltinCounterType = CounterDescriptor_BuiltinCounterType;
+ static constexpr auto COUNTER_UNSPECIFIED = CounterDescriptor_BuiltinCounterType_COUNTER_UNSPECIFIED;
+ static constexpr auto COUNTER_THREAD_TIME_NS = CounterDescriptor_BuiltinCounterType_COUNTER_THREAD_TIME_NS;
+ static constexpr auto COUNTER_THREAD_INSTRUCTION_COUNT = CounterDescriptor_BuiltinCounterType_COUNTER_THREAD_INSTRUCTION_COUNT;
+ static constexpr auto BuiltinCounterType_MIN = CounterDescriptor_BuiltinCounterType_COUNTER_UNSPECIFIED;
+ static constexpr auto BuiltinCounterType_MAX = CounterDescriptor_BuiltinCounterType_COUNTER_THREAD_INSTRUCTION_COUNT;
+ using Unit = CounterDescriptor_Unit;
+ static constexpr auto UNIT_UNSPECIFIED = CounterDescriptor_Unit_UNIT_UNSPECIFIED;
+ static constexpr auto UNIT_TIME_NS = CounterDescriptor_Unit_UNIT_TIME_NS;
+ static constexpr auto UNIT_COUNT = CounterDescriptor_Unit_UNIT_COUNT;
+ static constexpr auto UNIT_SIZE_BYTES = CounterDescriptor_Unit_UNIT_SIZE_BYTES;
+ static constexpr auto Unit_MIN = CounterDescriptor_Unit_UNIT_UNSPECIFIED;
+ static constexpr auto Unit_MAX = CounterDescriptor_Unit_UNIT_SIZE_BYTES;
+ enum FieldNumbers {
+ kTypeFieldNumber = 1,
+ kCategoriesFieldNumber = 2,
+ kUnitFieldNumber = 3,
+ kUnitNameFieldNumber = 6,
+ kUnitMultiplierFieldNumber = 4,
+ kIsIncrementalFieldNumber = 5,
+ };
+
+ CounterDescriptor();
+ ~CounterDescriptor() override;
+ CounterDescriptor(CounterDescriptor&&) noexcept;
+ CounterDescriptor& operator=(CounterDescriptor&&);
+ CounterDescriptor(const CounterDescriptor&);
+ CounterDescriptor& operator=(const CounterDescriptor&);
+ bool operator==(const CounterDescriptor&) const;
+ bool operator!=(const CounterDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_type() const { return _has_field_[1]; }
+ CounterDescriptor_BuiltinCounterType type() const { return type_; }
+ void set_type(CounterDescriptor_BuiltinCounterType value) { type_ = value; _has_field_.set(1); }
+
+ const std::vector<std::string>& categories() const { return categories_; }
+ std::vector<std::string>* mutable_categories() { return &categories_; }
+ int categories_size() const { return static_cast<int>(categories_.size()); }
+ void clear_categories() { categories_.clear(); }
+ void add_categories(std::string value) { categories_.emplace_back(value); }
+ std::string* add_categories() { categories_.emplace_back(); return &categories_.back(); }
+
+ bool has_unit() const { return _has_field_[3]; }
+ CounterDescriptor_Unit unit() const { return unit_; }
+ void set_unit(CounterDescriptor_Unit value) { unit_ = value; _has_field_.set(3); }
+
+ bool has_unit_name() const { return _has_field_[6]; }
+ const std::string& unit_name() const { return unit_name_; }
+ void set_unit_name(const std::string& value) { unit_name_ = value; _has_field_.set(6); }
+
+ bool has_unit_multiplier() const { return _has_field_[4]; }
+ int64_t unit_multiplier() const { return unit_multiplier_; }
+ void set_unit_multiplier(int64_t value) { unit_multiplier_ = value; _has_field_.set(4); }
+
+ bool has_is_incremental() const { return _has_field_[5]; }
+ bool is_incremental() const { return is_incremental_; }
+ void set_is_incremental(bool value) { is_incremental_ = value; _has_field_.set(5); }
+
+ private:
+ CounterDescriptor_BuiltinCounterType type_{};
+ std::vector<std::string> categories_;
+ CounterDescriptor_Unit unit_{};
+ std::string unit_name_{};
+ int64_t unit_multiplier_{};
+ bool is_incremental_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_COUNTER_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/counter_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_COUNTER_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_COUNTER_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_CounterDescriptor {
+enum BuiltinCounterType : int32_t;
+} // namespace perfetto_pbzero_enum_CounterDescriptor
+using CounterDescriptor_BuiltinCounterType = perfetto_pbzero_enum_CounterDescriptor::BuiltinCounterType;
+namespace perfetto_pbzero_enum_CounterDescriptor {
+enum Unit : int32_t;
+} // namespace perfetto_pbzero_enum_CounterDescriptor
+using CounterDescriptor_Unit = perfetto_pbzero_enum_CounterDescriptor::Unit;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_CounterDescriptor {
+enum BuiltinCounterType : int32_t {
+ COUNTER_UNSPECIFIED = 0,
+ COUNTER_THREAD_TIME_NS = 1,
+ COUNTER_THREAD_INSTRUCTION_COUNT = 2,
+};
+} // namespace perfetto_pbzero_enum_CounterDescriptor
+using CounterDescriptor_BuiltinCounterType = perfetto_pbzero_enum_CounterDescriptor::BuiltinCounterType;
+
+
+constexpr CounterDescriptor_BuiltinCounterType CounterDescriptor_BuiltinCounterType_MIN = CounterDescriptor_BuiltinCounterType::COUNTER_UNSPECIFIED;
+constexpr CounterDescriptor_BuiltinCounterType CounterDescriptor_BuiltinCounterType_MAX = CounterDescriptor_BuiltinCounterType::COUNTER_THREAD_INSTRUCTION_COUNT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* CounterDescriptor_BuiltinCounterType_Name(::perfetto::protos::pbzero::CounterDescriptor_BuiltinCounterType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::CounterDescriptor_BuiltinCounterType::COUNTER_UNSPECIFIED:
+ return "COUNTER_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::CounterDescriptor_BuiltinCounterType::COUNTER_THREAD_TIME_NS:
+ return "COUNTER_THREAD_TIME_NS";
+
+ case ::perfetto::protos::pbzero::CounterDescriptor_BuiltinCounterType::COUNTER_THREAD_INSTRUCTION_COUNT:
+ return "COUNTER_THREAD_INSTRUCTION_COUNT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_CounterDescriptor {
+enum Unit : int32_t {
+ UNIT_UNSPECIFIED = 0,
+ UNIT_TIME_NS = 1,
+ UNIT_COUNT = 2,
+ UNIT_SIZE_BYTES = 3,
+};
+} // namespace perfetto_pbzero_enum_CounterDescriptor
+using CounterDescriptor_Unit = perfetto_pbzero_enum_CounterDescriptor::Unit;
+
+
+constexpr CounterDescriptor_Unit CounterDescriptor_Unit_MIN = CounterDescriptor_Unit::UNIT_UNSPECIFIED;
+constexpr CounterDescriptor_Unit CounterDescriptor_Unit_MAX = CounterDescriptor_Unit::UNIT_SIZE_BYTES;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* CounterDescriptor_Unit_Name(::perfetto::protos::pbzero::CounterDescriptor_Unit value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::CounterDescriptor_Unit::UNIT_UNSPECIFIED:
+ return "UNIT_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::CounterDescriptor_Unit::UNIT_TIME_NS:
+ return "UNIT_TIME_NS";
+
+ case ::perfetto::protos::pbzero::CounterDescriptor_Unit::UNIT_COUNT:
+ return "UNIT_COUNT";
+
+ case ::perfetto::protos::pbzero::CounterDescriptor_Unit::UNIT_SIZE_BYTES:
+ return "UNIT_SIZE_BYTES";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class CounterDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ CounterDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CounterDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CounterDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_type() const { return at<1>().valid(); }
+ int32_t type() const { return at<1>().as_int32(); }
+ bool has_categories() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> categories() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_unit() const { return at<3>().valid(); }
+ int32_t unit() const { return at<3>().as_int32(); }
+ bool has_unit_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars unit_name() const { return at<6>().as_string(); }
+ bool has_unit_multiplier() const { return at<4>().valid(); }
+ int64_t unit_multiplier() const { return at<4>().as_int64(); }
+ bool has_is_incremental() const { return at<5>().valid(); }
+ bool is_incremental() const { return at<5>().as_bool(); }
+};
+
+class CounterDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = CounterDescriptor_Decoder;
+ enum : int32_t {
+ kTypeFieldNumber = 1,
+ kCategoriesFieldNumber = 2,
+ kUnitFieldNumber = 3,
+ kUnitNameFieldNumber = 6,
+ kUnitMultiplierFieldNumber = 4,
+ kIsIncrementalFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CounterDescriptor"; }
+
+
+ using BuiltinCounterType = ::perfetto::protos::pbzero::CounterDescriptor_BuiltinCounterType;
+ static inline const char* BuiltinCounterType_Name(BuiltinCounterType value) {
+ return ::perfetto::protos::pbzero::CounterDescriptor_BuiltinCounterType_Name(value);
+ }
+
+ using Unit = ::perfetto::protos::pbzero::CounterDescriptor_Unit;
+ static inline const char* Unit_Name(Unit value) {
+ return ::perfetto::protos::pbzero::CounterDescriptor_Unit_Name(value);
+ }
+ static inline const BuiltinCounterType COUNTER_UNSPECIFIED = BuiltinCounterType::COUNTER_UNSPECIFIED;
+ static inline const BuiltinCounterType COUNTER_THREAD_TIME_NS = BuiltinCounterType::COUNTER_THREAD_TIME_NS;
+ static inline const BuiltinCounterType COUNTER_THREAD_INSTRUCTION_COUNT = BuiltinCounterType::COUNTER_THREAD_INSTRUCTION_COUNT;
+ static inline const Unit UNIT_UNSPECIFIED = Unit::UNIT_UNSPECIFIED;
+ static inline const Unit UNIT_TIME_NS = Unit::UNIT_TIME_NS;
+ static inline const Unit UNIT_COUNT = Unit::UNIT_COUNT;
+ static inline const Unit UNIT_SIZE_BYTES = Unit::UNIT_SIZE_BYTES;
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ CounterDescriptor_BuiltinCounterType,
+ CounterDescriptor>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(CounterDescriptor_BuiltinCounterType value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Categories =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CounterDescriptor>;
+
+ static constexpr FieldMetadata_Categories kCategories{};
+ void add_categories(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Categories::kFieldId, data, size);
+ }
+ void add_categories(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Categories::kFieldId, chars.data, chars.size);
+ }
+ void add_categories(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Categories::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Unit =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ CounterDescriptor_Unit,
+ CounterDescriptor>;
+
+ static constexpr FieldMetadata_Unit kUnit{};
+ void set_unit(CounterDescriptor_Unit value) {
+ static constexpr uint32_t field_id = FieldMetadata_Unit::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnitName =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CounterDescriptor>;
+
+ static constexpr FieldMetadata_UnitName kUnitName{};
+ void set_unit_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_UnitName::kFieldId, data, size);
+ }
+ void set_unit_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_UnitName::kFieldId, chars.data, chars.size);
+ }
+ void set_unit_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnitName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnitMultiplier =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CounterDescriptor>;
+
+ static constexpr FieldMetadata_UnitMultiplier kUnitMultiplier{};
+ void set_unit_multiplier(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnitMultiplier::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsIncremental =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ CounterDescriptor>;
+
+ static constexpr FieldMetadata_IsIncremental kIsIncremental{};
+ void set_is_incremental(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsIncremental::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/track_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TrackDescriptor;
+class CounterDescriptor;
+class ChromeThreadDescriptor;
+class ThreadDescriptor;
+class ChromeProcessDescriptor;
+class ProcessDescriptor;
+enum CounterDescriptor_BuiltinCounterType : int;
+enum CounterDescriptor_Unit : int;
+enum ChromeThreadDescriptor_ThreadType : int;
+enum ThreadDescriptor_ChromeThreadType : int;
+enum ChromeProcessDescriptor_ProcessType : int;
+enum ProcessDescriptor_ChromeProcessType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TrackDescriptor : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kUuidFieldNumber = 1,
+ kParentUuidFieldNumber = 5,
+ kNameFieldNumber = 2,
+ kProcessFieldNumber = 3,
+ kChromeProcessFieldNumber = 6,
+ kThreadFieldNumber = 4,
+ kChromeThreadFieldNumber = 7,
+ kCounterFieldNumber = 8,
+ kDisallowMergingWithSystemTracksFieldNumber = 9,
+ };
+
+ TrackDescriptor();
+ ~TrackDescriptor() override;
+ TrackDescriptor(TrackDescriptor&&) noexcept;
+ TrackDescriptor& operator=(TrackDescriptor&&);
+ TrackDescriptor(const TrackDescriptor&);
+ TrackDescriptor& operator=(const TrackDescriptor&);
+ bool operator==(const TrackDescriptor&) const;
+ bool operator!=(const TrackDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_uuid() const { return _has_field_[1]; }
+ uint64_t uuid() const { return uuid_; }
+ void set_uuid(uint64_t value) { uuid_ = value; _has_field_.set(1); }
+
+ bool has_parent_uuid() const { return _has_field_[5]; }
+ uint64_t parent_uuid() const { return parent_uuid_; }
+ void set_parent_uuid(uint64_t value) { parent_uuid_ = value; _has_field_.set(5); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ bool has_process() const { return _has_field_[3]; }
+ const ProcessDescriptor& process() const { return *process_; }
+ ProcessDescriptor* mutable_process() { _has_field_.set(3); return process_.get(); }
+
+ bool has_chrome_process() const { return _has_field_[6]; }
+ const ChromeProcessDescriptor& chrome_process() const { return *chrome_process_; }
+ ChromeProcessDescriptor* mutable_chrome_process() { _has_field_.set(6); return chrome_process_.get(); }
+
+ bool has_thread() const { return _has_field_[4]; }
+ const ThreadDescriptor& thread() const { return *thread_; }
+ ThreadDescriptor* mutable_thread() { _has_field_.set(4); return thread_.get(); }
+
+ bool has_chrome_thread() const { return _has_field_[7]; }
+ const ChromeThreadDescriptor& chrome_thread() const { return *chrome_thread_; }
+ ChromeThreadDescriptor* mutable_chrome_thread() { _has_field_.set(7); return chrome_thread_.get(); }
+
+ bool has_counter() const { return _has_field_[8]; }
+ const CounterDescriptor& counter() const { return *counter_; }
+ CounterDescriptor* mutable_counter() { _has_field_.set(8); return counter_.get(); }
+
+ bool has_disallow_merging_with_system_tracks() const { return _has_field_[9]; }
+ bool disallow_merging_with_system_tracks() const { return disallow_merging_with_system_tracks_; }
+ void set_disallow_merging_with_system_tracks(bool value) { disallow_merging_with_system_tracks_ = value; _has_field_.set(9); }
+
+ private:
+ uint64_t uuid_{};
+ uint64_t parent_uuid_{};
+ std::string name_{};
+ ::protozero::CopyablePtr<ProcessDescriptor> process_;
+ ::protozero::CopyablePtr<ChromeProcessDescriptor> chrome_process_;
+ ::protozero::CopyablePtr<ThreadDescriptor> thread_;
+ ::protozero::CopyablePtr<ChromeThreadDescriptor> chrome_thread_;
+ ::protozero::CopyablePtr<CounterDescriptor> counter_;
+ bool disallow_merging_with_system_tracks_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<10> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/track_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ChromeProcessDescriptor;
+class ChromeThreadDescriptor;
+class CounterDescriptor;
+class ProcessDescriptor;
+class ThreadDescriptor;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TrackDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrackDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_uuid() const { return at<1>().valid(); }
+ uint64_t uuid() const { return at<1>().as_uint64(); }
+ bool has_parent_uuid() const { return at<5>().valid(); }
+ uint64_t parent_uuid() const { return at<5>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_process() const { return at<3>().valid(); }
+ ::protozero::ConstBytes process() const { return at<3>().as_bytes(); }
+ bool has_chrome_process() const { return at<6>().valid(); }
+ ::protozero::ConstBytes chrome_process() const { return at<6>().as_bytes(); }
+ bool has_thread() const { return at<4>().valid(); }
+ ::protozero::ConstBytes thread() const { return at<4>().as_bytes(); }
+ bool has_chrome_thread() const { return at<7>().valid(); }
+ ::protozero::ConstBytes chrome_thread() const { return at<7>().as_bytes(); }
+ bool has_counter() const { return at<8>().valid(); }
+ ::protozero::ConstBytes counter() const { return at<8>().as_bytes(); }
+ bool has_disallow_merging_with_system_tracks() const { return at<9>().valid(); }
+ bool disallow_merging_with_system_tracks() const { return at<9>().as_bool(); }
+};
+
+class TrackDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = TrackDescriptor_Decoder;
+ enum : int32_t {
+ kUuidFieldNumber = 1,
+ kParentUuidFieldNumber = 5,
+ kNameFieldNumber = 2,
+ kProcessFieldNumber = 3,
+ kChromeProcessFieldNumber = 6,
+ kThreadFieldNumber = 4,
+ kChromeThreadFieldNumber = 7,
+ kCounterFieldNumber = 8,
+ kDisallowMergingWithSystemTracksFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackDescriptor"; }
+
+
+ using FieldMetadata_Uuid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_Uuid kUuid{};
+ void set_uuid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uuid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ParentUuid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_ParentUuid kParentUuid{};
+ void set_parent_uuid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParentUuid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Process =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessDescriptor,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_Process kProcess{};
+ template <typename T = ProcessDescriptor> T* set_process() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_ChromeProcess =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeProcessDescriptor,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_ChromeProcess kChromeProcess{};
+ template <typename T = ChromeProcessDescriptor> T* set_chrome_process() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_Thread =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ThreadDescriptor,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_Thread kThread{};
+ template <typename T = ThreadDescriptor> T* set_thread() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_ChromeThread =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeThreadDescriptor,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_ChromeThread kChromeThread{};
+ template <typename T = ChromeThreadDescriptor> T* set_chrome_thread() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_Counter =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CounterDescriptor,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_Counter kCounter{};
+ template <typename T = CounterDescriptor> T* set_counter() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_DisallowMergingWithSystemTracks =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TrackDescriptor>;
+
+ static constexpr FieldMetadata_DisallowMergingWithSystemTracks kDisallowMergingWithSystemTracks{};
+ void set_disallow_merging_with_system_tracks(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisallowMergingWithSystemTracks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/proc_utils.h"
+// gen_amalgamated expanded: #include "perfetto/base/thread_utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/fnv1a.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/counter_descriptor.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_descriptor.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
+
+#include <stdint.h>
+#include <map>
+#include <mutex>
+
+namespace perfetto {
+namespace internal {
+class TrackRegistry;
+}
+class Flow;
+class TerminatingFlow;
+
+// Track events are recorded on a timeline track, which maintains the relative
+// time ordering of all events on that track. Each thread has its own default
+// track (ThreadTrack), which is by default where all track events are written.
+// Thread tracks are grouped under their hosting process (ProcessTrack).
+
+// Events which aren't strictly scoped to a thread or a process, or don't
+// correspond to synchronous code execution on a thread can use a custom
+// track (Track, ThreadTrack or ProcessTrack). A Track object can also
+// optionally be parented to a thread or a process.
+//
+// A track is represented by a uuid, which must be unique across the entire
+// recorded trace.
+//
+// For example, to record an event that begins and ends on different threads,
+// use a matching id to tie the begin and end events together:
+//
+// TRACE_EVENT_BEGIN("category", "AsyncEvent", perfetto::Track(8086));
+// ...
+// TRACE_EVENT_END("category", perfetto::Track(8086));
+//
+// Tracks can also be annotated with metadata:
+//
+// auto desc = track.Serialize();
+// desc.set_name("MyTrack");
+// perfetto::TrackEvent::SetTrackDescriptor(track, desc);
+//
+// Threads and processes can also be named in a similar way, e.g.:
+//
+// auto desc = perfetto::ProcessTrack::Current().Serialize();
+// desc.mutable_process()->set_process_name("MyProcess");
+// perfetto::TrackEvent::SetTrackDescriptor(
+// perfetto::ProcessTrack::Current(), desc);
+//
+// The metadata remains valid between tracing sessions. To free up data for a
+// track, call EraseTrackDescriptor:
+//
+// perfetto::TrackEvent::EraseTrackDescriptor(track);
+//
+struct PERFETTO_EXPORT_COMPONENT Track {
+ const uint64_t uuid;
+ const uint64_t parent_uuid;
+ constexpr Track() : uuid(0), parent_uuid(0) {}
+
+ // Construct a track with identifier |id|, optionally parented under |parent|.
+ // If no parent is specified, the track's parent is the current process's
+ // track.
+ //
+ // To minimize the chances for accidental id collisions across processes, the
+ // track's effective uuid is generated by xorring |id| with a random,
+ // per-process cookie.
+ explicit constexpr Track(uint64_t id, Track parent = MakeProcessTrack())
+ : uuid(id ^ parent.uuid), parent_uuid(parent.uuid) {}
+
+ explicit operator bool() const { return uuid; }
+ void Serialize(protos::pbzero::TrackDescriptor*) const;
+ protos::gen::TrackDescriptor Serialize() const;
+
+ // Construct a global track with identifier |id|.
+ //
+ // Beware: the globally unique |id| should be chosen carefully to avoid
+ // accidental clashes with track identifiers emitted by other producers.
+ static Track Global(uint64_t id) { return Track(id, Track()); }
+
+ // Construct a track using |ptr| as identifier.
+ static Track FromPointer(const void* ptr, Track parent = MakeProcessTrack()) {
+ // Using pointers as global TrackIds isn't supported as pointers are
+ // per-proccess and the same pointer value can be used in different
+ // processes. If you hit this check but are providing no |parent| track,
+ // verify that Tracing::Initialize() was called for the current process.
+ PERFETTO_DCHECK(parent.uuid != Track().uuid);
+
+ return Track(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr)),
+ parent);
+ }
+
+ // Construct a track using |ptr| as identifier within thread-scope.
+ // Shorthand for `Track::FromPointer(ptr, ThreadTrack::Current())`
+ // Usage: TRACE_EVENT_BEGIN("...", "...", perfetto::Track::ThreadScoped(this))
+ static Track ThreadScoped(
+ const void* ptr,
+ Track parent = MakeThreadTrack(base::GetThreadId())) {
+ return Track::FromPointer(ptr, parent);
+ }
+
+ protected:
+ constexpr Track(uint64_t uuid_, uint64_t parent_uuid_)
+ : uuid(uuid_), parent_uuid(parent_uuid_) {}
+
+ static Track MakeThreadTrack(base::PlatformThreadId tid) {
+ // If tid were 0 here (which is an invalid tid), we would create a thread
+ // track with a uuid that conflicts with the corresponding ProcessTrack.
+ PERFETTO_DCHECK(tid != 0);
+ return Track(static_cast<uint64_t>(tid), MakeProcessTrack());
+ }
+
+ static Track MakeProcessTrack() { return Track(process_uuid, Track()); }
+
+ static constexpr inline uint64_t CompileTimeHash(const char* string) {
+ return internal::Fnv1a(string);
+ }
+
+ private:
+ friend class internal::TrackRegistry;
+ friend class Flow;
+ friend class TerminatingFlow;
+ static uint64_t process_uuid;
+};
+
+// A process track represents events that describe the state of the entire
+// application (e.g., counter events). Currently a ProcessTrack can only
+// represent the current process.
+struct PERFETTO_EXPORT_COMPONENT ProcessTrack : public Track {
+ const base::PlatformProcessId pid;
+
+ static ProcessTrack Current() { return ProcessTrack(); }
+
+ void Serialize(protos::pbzero::TrackDescriptor*) const;
+ protos::gen::TrackDescriptor Serialize() const;
+
+ private:
+ ProcessTrack()
+ : Track(MakeProcessTrack()), pid(Platform::GetCurrentProcessId()) {}
+};
+
+// A thread track is associated with a specific thread of execution. Currently
+// only threads in the current process can be referenced.
+struct PERFETTO_EXPORT_COMPONENT ThreadTrack : public Track {
+ const base::PlatformProcessId pid;
+ const base::PlatformThreadId tid;
+ bool disallow_merging_with_system_tracks = false;
+
+ static ThreadTrack Current();
+
+ // Represents a thread in the current process.
+ static ThreadTrack ForThread(base::PlatformThreadId tid_);
+
+ void Serialize(protos::pbzero::TrackDescriptor*) const;
+ protos::gen::TrackDescriptor Serialize() const;
+
+ private:
+ explicit ThreadTrack(base::PlatformThreadId tid_,
+ bool disallow_merging_with_system_tracks_)
+ : Track(MakeThreadTrack(tid_)),
+ pid(ProcessTrack::Current().pid),
+ tid(tid_),
+ disallow_merging_with_system_tracks(
+ disallow_merging_with_system_tracks_) {}
+};
+
+// A track for recording counter values with the TRACE_COUNTER macro. Counter
+// tracks can optionally be given units and other metadata. See
+// /protos/perfetto/trace/track_event/counter_descriptor.proto for details.
+class PERFETTO_EXPORT_COMPONENT CounterTrack : public Track {
+ // A random value mixed into counter track uuids to avoid collisions with
+ // other types of tracks.
+ static constexpr uint64_t kCounterMagic = 0xb1a4a67d7970839eul;
+
+ public:
+ using Unit = perfetto::protos::pbzero::CounterDescriptor::Unit;
+ using CounterType =
+ perfetto::protos::gen::CounterDescriptor::BuiltinCounterType;
+
+ // |name| must outlive this object.
+ constexpr explicit CounterTrack(const char* name,
+ Track parent = MakeProcessTrack())
+ : Track(internal::Fnv1a(name) ^ kCounterMagic, parent),
+ name_(name),
+ category_(nullptr) {}
+
+ // |unit_name| is a free-form description of the unit used by this counter. It
+ // must outlive this object.
+ constexpr CounterTrack(const char* name,
+ const char* unit_name,
+ Track parent = MakeProcessTrack())
+ : Track(internal::Fnv1a(name) ^ kCounterMagic, parent),
+ name_(name),
+ category_(nullptr),
+ unit_name_(unit_name) {}
+
+ constexpr CounterTrack(const char* name,
+ Unit unit,
+ Track parent = MakeProcessTrack())
+ : Track(internal::Fnv1a(name) ^ kCounterMagic, parent),
+ name_(name),
+ category_(nullptr),
+ unit_(unit) {}
+
+ static constexpr CounterTrack Global(const char* name,
+ const char* unit_name) {
+ return CounterTrack(name, unit_name, Track());
+ }
+
+ static constexpr CounterTrack Global(const char* name, Unit unit) {
+ return CounterTrack(name, unit, Track());
+ }
+
+ static constexpr CounterTrack Global(const char* name) {
+ return Global(name, nullptr);
+ }
+
+ constexpr CounterTrack set_unit(Unit unit) const {
+ return CounterTrack(uuid, parent_uuid, name_, category_, unit, unit_name_,
+ unit_multiplier_, is_incremental_, type_);
+ }
+
+ constexpr CounterTrack set_type(CounterType type) const {
+ return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
+ unit_multiplier_, is_incremental_, type);
+ }
+
+ constexpr CounterTrack set_unit_name(const char* unit_name) const {
+ return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name,
+ unit_multiplier_, is_incremental_, type_);
+ }
+
+ constexpr CounterTrack set_unit_multiplier(int64_t unit_multiplier) const {
+ return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
+ unit_multiplier, is_incremental_, type_);
+ }
+
+ constexpr CounterTrack set_category(const char* category) const {
+ return CounterTrack(uuid, parent_uuid, name_, category, unit_, unit_name_,
+ unit_multiplier_, is_incremental_, type_);
+ }
+
+ constexpr CounterTrack set_is_incremental(bool is_incremental = true) const {
+ return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
+ unit_multiplier_, is_incremental, type_);
+ }
+
+ constexpr bool is_incremental() const { return is_incremental_; }
+
+ void Serialize(protos::pbzero::TrackDescriptor*) const;
+ protos::gen::TrackDescriptor Serialize() const;
+
+ private:
+ constexpr CounterTrack(uint64_t uuid_,
+ uint64_t parent_uuid_,
+ const char* name,
+ const char* category,
+ Unit unit,
+ const char* unit_name,
+ int64_t unit_multiplier,
+ bool is_incremental,
+ CounterType type)
+ : Track(uuid_, parent_uuid_),
+ name_(name),
+ category_(category),
+ unit_(unit),
+ unit_name_(unit_name),
+ unit_multiplier_(unit_multiplier),
+ is_incremental_(is_incremental),
+ type_(type) {}
+
+ const char* const name_;
+ const char* const category_;
+ Unit unit_ = perfetto::protos::pbzero::CounterDescriptor::UNIT_UNSPECIFIED;
+ const char* const unit_name_ = nullptr;
+ int64_t unit_multiplier_ = 1;
+ const bool is_incremental_ = false;
+ CounterType type_ =
+ perfetto::protos::gen::CounterDescriptor::COUNTER_UNSPECIFIED;
+};
+
+namespace internal {
+
+// Keeps a map of uuids to serialized track descriptors and provides a
+// thread-safe way to read and write them. Each trace writer keeps a TLS set of
+// the tracks it has seen (see TrackEventIncrementalState). In the common case,
+// this registry is not consulted (and no locks are taken). However when a new
+// track is seen, this registry is used to write either 1) the default
+// descriptor for that track (see *Track::Serialize) or 2) a serialized
+// descriptor stored in the registry which may have additional metadata (e.g.,
+// track name).
+// TODO(eseckler): Remove PERFETTO_EXPORT_COMPONENT once Chromium no longer
+// calls TrackRegistry::InitializeInstance() directly.
+class PERFETTO_EXPORT_COMPONENT TrackRegistry {
+ public:
+ using SerializedTrackDescriptor = std::string;
+
+ TrackRegistry();
+ ~TrackRegistry();
+
+ static void InitializeInstance();
+ static void ResetForTesting();
+ static uint64_t ComputeProcessUuid();
+ static TrackRegistry* Get() { return instance_; }
+
+ void EraseTrack(Track);
+
+ // Store metadata for |track| in the registry. |fill_function| is called
+ // synchronously to record additional properties for the track.
+ template <typename TrackType>
+ void UpdateTrack(
+ const TrackType& track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> fill_function) {
+ UpdateTrackImpl(track, [&](protos::pbzero::TrackDescriptor* desc) {
+ track.Serialize(desc);
+ fill_function(desc);
+ });
+ }
+
+ // This variant lets the user supply a serialized track descriptor directly.
+ void UpdateTrack(Track, const std::string& serialized_desc);
+
+ // If |track| exists in the registry, write out the serialized track
+ // descriptor for it into |packet|. Otherwise just the ephemeral track object
+ // is serialized without any additional metadata.
+ template <typename TrackType>
+ void SerializeTrack(
+ const TrackType& track,
+ protozero::MessageHandle<protos::pbzero::TracePacket> packet) {
+ // If the track has extra metadata (recorded with UpdateTrack), it will be
+ // found in the registry. To minimize the time the lock is held, make a copy
+ // of the data held in the registry and write it outside the lock.
+ std::string desc_copy;
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ const auto& it = tracks_.find(track.uuid);
+ if (it != tracks_.end()) {
+ desc_copy = it->second;
+ PERFETTO_DCHECK(!desc_copy.empty());
+ }
+ }
+ if (!desc_copy.empty()) {
+ WriteTrackDescriptor(std::move(desc_copy), std::move(packet));
+ } else {
+ // Otherwise we just write the basic descriptor for this type of track
+ // (e.g., just uuid, no name).
+ track.Serialize(packet->set_track_descriptor());
+ }
+ }
+
+ static void WriteTrackDescriptor(
+ const SerializedTrackDescriptor& desc,
+ protozero::MessageHandle<protos::pbzero::TracePacket> packet);
+
+ private:
+ void UpdateTrackImpl(
+ Track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> fill_function);
+
+ std::mutex mutex_;
+ std::map<uint64_t /* uuid */, SerializedTrackDescriptor> tracks_;
+
+ static TrackRegistry* instance_;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/builtin_clock.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum BuiltinClock : int32_t {
+ BUILTIN_CLOCK_UNKNOWN = 0,
+ BUILTIN_CLOCK_REALTIME = 1,
+ BUILTIN_CLOCK_REALTIME_COARSE = 2,
+ BUILTIN_CLOCK_MONOTONIC = 3,
+ BUILTIN_CLOCK_MONOTONIC_COARSE = 4,
+ BUILTIN_CLOCK_MONOTONIC_RAW = 5,
+ BUILTIN_CLOCK_BOOTTIME = 6,
+ BUILTIN_CLOCK_MAX_ID = 63,
+};
+
+constexpr BuiltinClock BuiltinClock_MIN = BuiltinClock::BUILTIN_CLOCK_UNKNOWN;
+constexpr BuiltinClock BuiltinClock_MAX = BuiltinClock::BUILTIN_CLOCK_MAX_ID;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* BuiltinClock_Name(::perfetto::protos::pbzero::BuiltinClock value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_UNKNOWN:
+ return "BUILTIN_CLOCK_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_REALTIME:
+ return "BUILTIN_CLOCK_REALTIME";
+
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_REALTIME_COARSE:
+ return "BUILTIN_CLOCK_REALTIME_COARSE";
+
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MONOTONIC:
+ return "BUILTIN_CLOCK_MONOTONIC";
+
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MONOTONIC_COARSE:
+ return "BUILTIN_CLOCK_MONOTONIC_COARSE";
+
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MONOTONIC_RAW:
+ return "BUILTIN_CLOCK_MONOTONIC_RAW";
+
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_BOOTTIME:
+ return "BUILTIN_CLOCK_BOOTTIME";
+
+ case ::perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MAX_ID:
+ return "BUILTIN_CLOCK_MAX_ID";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/interned_data/interned_data.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class Callstack;
+class DebugAnnotationName;
+class DebugAnnotationValueTypeName;
+class EventCategory;
+class EventName;
+class Frame;
+class HistogramName;
+class InternedGpuRenderStageSpecification;
+class InternedGraphicsContext;
+class InternedString;
+class InternedV8Isolate;
+class InternedV8JsFunction;
+class InternedV8JsScript;
+class InternedV8String;
+class InternedV8WasmScript;
+class LogMessageBody;
+class Mapping;
+class NetworkPacketContext;
+class ProfiledFrameSymbols;
+class SourceLocation;
+class UnsymbolizedSourceLocation;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class InternedData_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/37, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ InternedData_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedData_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedData_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_categories() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> event_categories() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_event_names() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> event_names() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_debug_annotation_names() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotation_names() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_debug_annotation_value_type_names() const { return at<27>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotation_value_type_names() const { return GetRepeated<::protozero::ConstBytes>(27); }
+ bool has_source_locations() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> source_locations() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_unsymbolized_source_locations() const { return at<28>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> unsymbolized_source_locations() const { return GetRepeated<::protozero::ConstBytes>(28); }
+ bool has_log_message_body() const { return at<20>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> log_message_body() const { return GetRepeated<::protozero::ConstBytes>(20); }
+ bool has_histogram_names() const { return at<25>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> histogram_names() const { return GetRepeated<::protozero::ConstBytes>(25); }
+ bool has_build_ids() const { return at<16>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> build_ids() const { return GetRepeated<::protozero::ConstBytes>(16); }
+ bool has_mapping_paths() const { return at<17>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> mapping_paths() const { return GetRepeated<::protozero::ConstBytes>(17); }
+ bool has_source_paths() const { return at<18>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> source_paths() const { return GetRepeated<::protozero::ConstBytes>(18); }
+ bool has_function_names() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> function_names() const { return GetRepeated<::protozero::ConstBytes>(5); }
+ bool has_profiled_frame_symbols() const { return at<21>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> profiled_frame_symbols() const { return GetRepeated<::protozero::ConstBytes>(21); }
+ bool has_mappings() const { return at<19>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> mappings() const { return GetRepeated<::protozero::ConstBytes>(19); }
+ bool has_frames() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> frames() const { return GetRepeated<::protozero::ConstBytes>(6); }
+ bool has_callstacks() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> callstacks() const { return GetRepeated<::protozero::ConstBytes>(7); }
+ bool has_vulkan_memory_keys() const { return at<22>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> vulkan_memory_keys() const { return GetRepeated<::protozero::ConstBytes>(22); }
+ bool has_graphics_contexts() const { return at<23>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> graphics_contexts() const { return GetRepeated<::protozero::ConstBytes>(23); }
+ bool has_gpu_specifications() const { return at<24>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> gpu_specifications() const { return GetRepeated<::protozero::ConstBytes>(24); }
+ bool has_kernel_symbols() const { return at<26>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> kernel_symbols() const { return GetRepeated<::protozero::ConstBytes>(26); }
+ bool has_debug_annotation_string_values() const { return at<29>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotation_string_values() const { return GetRepeated<::protozero::ConstBytes>(29); }
+ bool has_packet_context() const { return at<30>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> packet_context() const { return GetRepeated<::protozero::ConstBytes>(30); }
+ bool has_v8_js_function_name() const { return at<31>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> v8_js_function_name() const { return GetRepeated<::protozero::ConstBytes>(31); }
+ bool has_v8_js_function() const { return at<32>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> v8_js_function() const { return GetRepeated<::protozero::ConstBytes>(32); }
+ bool has_v8_js_script() const { return at<33>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> v8_js_script() const { return GetRepeated<::protozero::ConstBytes>(33); }
+ bool has_v8_wasm_script() const { return at<34>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> v8_wasm_script() const { return GetRepeated<::protozero::ConstBytes>(34); }
+ bool has_v8_isolate() const { return at<35>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> v8_isolate() const { return GetRepeated<::protozero::ConstBytes>(35); }
+ bool has_protolog_string_args() const { return at<36>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> protolog_string_args() const { return GetRepeated<::protozero::ConstBytes>(36); }
+ bool has_protolog_stacktrace() const { return at<37>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> protolog_stacktrace() const { return GetRepeated<::protozero::ConstBytes>(37); }
+};
+
+class InternedData : public ::protozero::Message {
+ public:
+ using Decoder = InternedData_Decoder;
+ enum : int32_t {
+ kEventCategoriesFieldNumber = 1,
+ kEventNamesFieldNumber = 2,
+ kDebugAnnotationNamesFieldNumber = 3,
+ kDebugAnnotationValueTypeNamesFieldNumber = 27,
+ kSourceLocationsFieldNumber = 4,
+ kUnsymbolizedSourceLocationsFieldNumber = 28,
+ kLogMessageBodyFieldNumber = 20,
+ kHistogramNamesFieldNumber = 25,
+ kBuildIdsFieldNumber = 16,
+ kMappingPathsFieldNumber = 17,
+ kSourcePathsFieldNumber = 18,
+ kFunctionNamesFieldNumber = 5,
+ kProfiledFrameSymbolsFieldNumber = 21,
+ kMappingsFieldNumber = 19,
+ kFramesFieldNumber = 6,
+ kCallstacksFieldNumber = 7,
+ kVulkanMemoryKeysFieldNumber = 22,
+ kGraphicsContextsFieldNumber = 23,
+ kGpuSpecificationsFieldNumber = 24,
+ kKernelSymbolsFieldNumber = 26,
+ kDebugAnnotationStringValuesFieldNumber = 29,
+ kPacketContextFieldNumber = 30,
+ kV8JsFunctionNameFieldNumber = 31,
+ kV8JsFunctionFieldNumber = 32,
+ kV8JsScriptFieldNumber = 33,
+ kV8WasmScriptFieldNumber = 34,
+ kV8IsolateFieldNumber = 35,
+ kProtologStringArgsFieldNumber = 36,
+ kProtologStacktraceFieldNumber = 37,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedData"; }
+
+
+ using FieldMetadata_EventCategories =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EventCategory,
+ InternedData>;
+
+ static constexpr FieldMetadata_EventCategories kEventCategories{};
+ template <typename T = EventCategory> T* add_event_categories() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_EventNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EventName,
+ InternedData>;
+
+ static constexpr FieldMetadata_EventNames kEventNames{};
+ template <typename T = EventName> T* add_event_names() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_DebugAnnotationNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotationName,
+ InternedData>;
+
+ static constexpr FieldMetadata_DebugAnnotationNames kDebugAnnotationNames{};
+ template <typename T = DebugAnnotationName> T* add_debug_annotation_names() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_DebugAnnotationValueTypeNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotationValueTypeName,
+ InternedData>;
+
+ static constexpr FieldMetadata_DebugAnnotationValueTypeNames kDebugAnnotationValueTypeNames{};
+ template <typename T = DebugAnnotationValueTypeName> T* add_debug_annotation_value_type_names() {
+ return BeginNestedMessage<T>(27);
+ }
+
+
+ using FieldMetadata_SourceLocations =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SourceLocation,
+ InternedData>;
+
+ static constexpr FieldMetadata_SourceLocations kSourceLocations{};
+ template <typename T = SourceLocation> T* add_source_locations() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_UnsymbolizedSourceLocations =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ UnsymbolizedSourceLocation,
+ InternedData>;
+
+ static constexpr FieldMetadata_UnsymbolizedSourceLocations kUnsymbolizedSourceLocations{};
+ template <typename T = UnsymbolizedSourceLocation> T* add_unsymbolized_source_locations() {
+ return BeginNestedMessage<T>(28);
+ }
+
+
+ using FieldMetadata_LogMessageBody =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LogMessageBody,
+ InternedData>;
+
+ static constexpr FieldMetadata_LogMessageBody kLogMessageBody{};
+ template <typename T = LogMessageBody> T* add_log_message_body() {
+ return BeginNestedMessage<T>(20);
+ }
+
+
+ using FieldMetadata_HistogramNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HistogramName,
+ InternedData>;
+
+ static constexpr FieldMetadata_HistogramNames kHistogramNames{};
+ template <typename T = HistogramName> T* add_histogram_names() {
+ return BeginNestedMessage<T>(25);
+ }
+
+
+ using FieldMetadata_BuildIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_BuildIds kBuildIds{};
+ template <typename T = InternedString> T* add_build_ids() {
+ return BeginNestedMessage<T>(16);
+ }
+
+
+ using FieldMetadata_MappingPaths =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_MappingPaths kMappingPaths{};
+ template <typename T = InternedString> T* add_mapping_paths() {
+ return BeginNestedMessage<T>(17);
+ }
+
+
+ using FieldMetadata_SourcePaths =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_SourcePaths kSourcePaths{};
+ template <typename T = InternedString> T* add_source_paths() {
+ return BeginNestedMessage<T>(18);
+ }
+
+
+ using FieldMetadata_FunctionNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_FunctionNames kFunctionNames{};
+ template <typename T = InternedString> T* add_function_names() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_ProfiledFrameSymbols =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfiledFrameSymbols,
+ InternedData>;
+
+ static constexpr FieldMetadata_ProfiledFrameSymbols kProfiledFrameSymbols{};
+ template <typename T = ProfiledFrameSymbols> T* add_profiled_frame_symbols() {
+ return BeginNestedMessage<T>(21);
+ }
+
+
+ using FieldMetadata_Mappings =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Mapping,
+ InternedData>;
+
+ static constexpr FieldMetadata_Mappings kMappings{};
+ template <typename T = Mapping> T* add_mappings() {
+ return BeginNestedMessage<T>(19);
+ }
+
+
+ using FieldMetadata_Frames =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Frame,
+ InternedData>;
+
+ static constexpr FieldMetadata_Frames kFrames{};
+ template <typename T = Frame> T* add_frames() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_Callstacks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Callstack,
+ InternedData>;
+
+ static constexpr FieldMetadata_Callstacks kCallstacks{};
+ template <typename T = Callstack> T* add_callstacks() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_VulkanMemoryKeys =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_VulkanMemoryKeys kVulkanMemoryKeys{};
+ template <typename T = InternedString> T* add_vulkan_memory_keys() {
+ return BeginNestedMessage<T>(22);
+ }
+
+
+ using FieldMetadata_GraphicsContexts =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedGraphicsContext,
+ InternedData>;
+
+ static constexpr FieldMetadata_GraphicsContexts kGraphicsContexts{};
+ template <typename T = InternedGraphicsContext> T* add_graphics_contexts() {
+ return BeginNestedMessage<T>(23);
+ }
+
+
+ using FieldMetadata_GpuSpecifications =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedGpuRenderStageSpecification,
+ InternedData>;
+
+ static constexpr FieldMetadata_GpuSpecifications kGpuSpecifications{};
+ template <typename T = InternedGpuRenderStageSpecification> T* add_gpu_specifications() {
+ return BeginNestedMessage<T>(24);
+ }
+
+
+ using FieldMetadata_KernelSymbols =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_KernelSymbols kKernelSymbols{};
+ template <typename T = InternedString> T* add_kernel_symbols() {
+ return BeginNestedMessage<T>(26);
+ }
+
+
+ using FieldMetadata_DebugAnnotationStringValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 29,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_DebugAnnotationStringValues kDebugAnnotationStringValues{};
+ template <typename T = InternedString> T* add_debug_annotation_string_values() {
+ return BeginNestedMessage<T>(29);
+ }
+
+
+ using FieldMetadata_PacketContext =
+ ::protozero::proto_utils::FieldMetadata<
+ 30,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetworkPacketContext,
+ InternedData>;
+
+ static constexpr FieldMetadata_PacketContext kPacketContext{};
+ template <typename T = NetworkPacketContext> T* add_packet_context() {
+ return BeginNestedMessage<T>(30);
+ }
+
+
+ using FieldMetadata_V8JsFunctionName =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedV8String,
+ InternedData>;
+
+ static constexpr FieldMetadata_V8JsFunctionName kV8JsFunctionName{};
+ template <typename T = InternedV8String> T* add_v8_js_function_name() {
+ return BeginNestedMessage<T>(31);
+ }
+
+
+ using FieldMetadata_V8JsFunction =
+ ::protozero::proto_utils::FieldMetadata<
+ 32,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedV8JsFunction,
+ InternedData>;
+
+ static constexpr FieldMetadata_V8JsFunction kV8JsFunction{};
+ template <typename T = InternedV8JsFunction> T* add_v8_js_function() {
+ return BeginNestedMessage<T>(32);
+ }
+
+
+ using FieldMetadata_V8JsScript =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedV8JsScript,
+ InternedData>;
+
+ static constexpr FieldMetadata_V8JsScript kV8JsScript{};
+ template <typename T = InternedV8JsScript> T* add_v8_js_script() {
+ return BeginNestedMessage<T>(33);
+ }
+
+
+ using FieldMetadata_V8WasmScript =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedV8WasmScript,
+ InternedData>;
+
+ static constexpr FieldMetadata_V8WasmScript kV8WasmScript{};
+ template <typename T = InternedV8WasmScript> T* add_v8_wasm_script() {
+ return BeginNestedMessage<T>(34);
+ }
+
+
+ using FieldMetadata_V8Isolate =
+ ::protozero::proto_utils::FieldMetadata<
+ 35,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedV8Isolate,
+ InternedData>;
+
+ static constexpr FieldMetadata_V8Isolate kV8Isolate{};
+ template <typename T = InternedV8Isolate> T* add_v8_isolate() {
+ return BeginNestedMessage<T>(35);
+ }
+
+
+ using FieldMetadata_ProtologStringArgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_ProtologStringArgs kProtologStringArgs{};
+ template <typename T = InternedString> T* add_protolog_string_args() {
+ return BeginNestedMessage<T>(36);
+ }
+
+
+ using FieldMetadata_ProtologStacktrace =
+ ::protozero::proto_utils::FieldMetadata<
+ 37,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ InternedData>;
+
+ static constexpr FieldMetadata_ProtologStacktrace kProtologStacktrace{};
+ template <typename T = InternedString> T* add_protolog_stacktrace() {
+ return BeginNestedMessage<T>(37);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/flat_set.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/data_source.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/debug_annotation.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_value.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+#include <unordered_map>
+
+namespace perfetto {
+
+// Represents a point in time for the clock specified by |clock_id|.
+struct TraceTimestamp {
+ // Clock IDs have the following semantic:
+ // [1, 63]: Builtin types, see BuiltinClock from
+ // ../common/builtin_clock.proto.
+ // [64, 127]: User-defined clocks. These clocks are sequence-scoped. They
+ // are only valid within the same |trusted_packet_sequence_id|
+ // (i.e. only for TracePacket(s) emitted by the same TraceWriter
+ // that emitted the clock snapshot).
+ // [128, MAX]: Reserved for future use. The idea is to allow global clock
+ // IDs and setting this ID to hash(full_clock_name) & ~127.
+ // Learn more: `clock_snapshot.proto`
+ uint32_t clock_id;
+ uint64_t value;
+};
+
+class EventContext;
+class TrackEventSessionObserver;
+struct Category;
+struct TraceTimestamp;
+namespace protos {
+namespace gen {
+class TrackEventConfig;
+} // namespace gen
+namespace pbzero {
+class DebugAnnotation;
+} // namespace pbzero
+} // namespace protos
+
+// A callback interface for observing track event tracing sessions starting and
+// stopping. See TrackEvent::{Add,Remove}SessionObserver. Note that all methods
+// will be called on an internal Perfetto thread.
+class PERFETTO_EXPORT_COMPONENT TrackEventSessionObserver {
+ public:
+ virtual ~TrackEventSessionObserver();
+ // Called when a track event tracing session is configured. Note tracing isn't
+ // active yet, so track events emitted here won't be recorded. See
+ // DataSourceBase::OnSetup.
+ virtual void OnSetup(const DataSourceBase::SetupArgs&);
+ // Called when a track event tracing session is started. It is possible to
+ // emit track events from this callback.
+ virtual void OnStart(const DataSourceBase::StartArgs&);
+ // Called when a track event tracing session is stopped. It is still possible
+ // to emit track events from this callback.
+ virtual void OnStop(const DataSourceBase::StopArgs&);
+ // Called when tracing muxer requests to clear incremental state.
+ virtual void WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs&);
+};
+
+// A class that the embedder can store arbitrary data user data per thread.
+class PERFETTO_EXPORT_COMPONENT TrackEventTlsStateUserData {
+ public:
+ TrackEventTlsStateUserData() = default;
+ // Not clonable.
+ TrackEventTlsStateUserData(const TrackEventTlsStateUserData&) = delete;
+ TrackEventTlsStateUserData& operator=(const TrackEventTlsStateUserData&) =
+ delete;
+
+ virtual ~TrackEventTlsStateUserData();
+};
+
+namespace internal {
+class TrackEventCategoryRegistry;
+
+class PERFETTO_EXPORT_COMPONENT BaseTrackEventInternedDataIndex {
+ public:
+ virtual ~BaseTrackEventInternedDataIndex();
+
+#if PERFETTO_DCHECK_IS_ON()
+ const char* type_id_ = nullptr;
+ const void* add_function_ptr_ = nullptr;
+#endif // PERFETTO_DCHECK_IS_ON()
+};
+
+struct TrackEventTlsState {
+ template <typename TraceContext>
+ explicit TrackEventTlsState(const TraceContext& trace_context);
+ bool enable_thread_time_sampling = false;
+ bool filter_debug_annotations = false;
+ bool filter_dynamic_event_names = false;
+ uint64_t timestamp_unit_multiplier = 1;
+ uint32_t default_clock;
+ std::map<const void*, std::unique_ptr<TrackEventTlsStateUserData>> user_data;
+};
+
+struct TrackEventIncrementalState {
+ static constexpr size_t kMaxInternedDataFields = 32;
+
+ // Packet-sequence-scoped clock that encodes nanosecond timestamps in the
+ // domain of the clock returned by GetClockId() as delta values - see
+ // Clock::is_incremental in perfetto/trace/clock_snapshot.proto.
+ // Default unit: nanoseconds.
+ static constexpr uint32_t kClockIdIncremental = 64;
+
+ // Packet-sequence-scoped clock that encodes timestamps in the domain of the
+ // clock returned by GetClockId() with custom unit_multiplier.
+ // Default unit: nanoseconds.
+ static constexpr uint32_t kClockIdAbsolute = 65;
+
+ bool was_cleared = true;
+
+ // A heap-allocated message for storing newly seen interned data while we are
+ // in the middle of writing a track event. When a track event wants to write
+ // new interned data into the trace, it is first serialized into this message
+ // and then flushed to the real trace in EventContext when the packet ends.
+ // The message is cached here as a part of incremental state so that we can
+ // reuse the underlying buffer allocation for subsequently written interned
+ // data.
+ protozero::HeapBuffered<protos::pbzero::InternedData>
+ serialized_interned_data;
+
+ // In-memory indices for looking up interned data ids.
+ // For each intern-able field (up to a max of 32) we keep a dictionary of
+ // field-value -> interning-key. Depending on the type we either keep the full
+ // value or a hash of it (See track_event_interned_data_index.h)
+ using InternedDataIndex =
+ std::pair</* interned_data.proto field number */ size_t,
+ std::unique_ptr<BaseTrackEventInternedDataIndex>>;
+ std::array<InternedDataIndex, kMaxInternedDataFields> interned_data_indices =
+ {};
+
+ // Track uuids for which we have written descriptors into the trace. If a
+ // trace event uses a track which is not in this set, we'll write out a
+ // descriptor for it.
+ base::FlatSet<uint64_t> seen_tracks;
+
+ // Dynamically registered category names that have been encountered during
+ // this tracing session. The value in the map indicates whether the category
+ // is enabled or disabled.
+ std::unordered_map<std::string, bool> dynamic_categories;
+
+ // The latest reference timestamp that was used in a TracePacket or in a
+ // ClockSnapshot. The increment between this timestamp and the current trace
+ // time (GetTimeNs) is a value in kClockIdIncremental's domain.
+ uint64_t last_timestamp_ns = 0;
+
+ // The latest known counter values that was used in a TracePacket for each
+ // counter track. The key (uint64_t) is the uuid of counter track.
+ // The value is used for delta encoding of counter values.
+ std::unordered_map<uint64_t, int64_t> last_counter_value_per_track;
+ int64_t last_thread_time_ns = 0;
+};
+
+// The backend portion of the track event trace point implemention. Outlined to
+// a separate .cc file so it can be shared by different track event category
+// namespaces.
+class PERFETTO_EXPORT_COMPONENT TrackEventInternal {
+ public:
+ static bool Initialize(
+ const TrackEventCategoryRegistry&,
+ bool (*register_data_source)(const DataSourceDescriptor&));
+
+ static bool AddSessionObserver(const TrackEventCategoryRegistry&,
+ TrackEventSessionObserver*);
+ static void RemoveSessionObserver(const TrackEventCategoryRegistry&,
+ TrackEventSessionObserver*);
+
+ static void EnableTracing(const TrackEventCategoryRegistry& registry,
+ const protos::gen::TrackEventConfig& config,
+ const DataSourceBase::SetupArgs&);
+ static void OnStart(const TrackEventCategoryRegistry&,
+ const DataSourceBase::StartArgs&);
+ static void OnStop(const TrackEventCategoryRegistry&,
+ const DataSourceBase::StopArgs&);
+ static void DisableTracing(const TrackEventCategoryRegistry& registry,
+ uint32_t internal_instance_index);
+ static void WillClearIncrementalState(
+ const TrackEventCategoryRegistry&,
+ const DataSourceBase::ClearIncrementalStateArgs&);
+
+ static bool IsCategoryEnabled(const TrackEventCategoryRegistry& registry,
+ const protos::gen::TrackEventConfig& config,
+ const Category& category);
+
+ static void WriteEventName(perfetto::DynamicString event_name,
+ perfetto::EventContext& event_ctx,
+ const TrackEventTlsState&);
+
+ static void WriteEventName(perfetto::StaticString event_name,
+ perfetto::EventContext& event_ctx,
+ const TrackEventTlsState&);
+
+ static perfetto::EventContext WriteEvent(
+ TraceWriterBase*,
+ TrackEventIncrementalState*,
+ TrackEventTlsState& tls_state,
+ const Category* category,
+ perfetto::protos::pbzero::TrackEvent::Type,
+ const TraceTimestamp& timestamp,
+ bool on_current_thread_track);
+
+ static void ResetIncrementalStateIfRequired(
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ const TrackEventTlsState& tls_state,
+ const TraceTimestamp& timestamp) {
+ if (incr_state->was_cleared) {
+ incr_state->was_cleared = false;
+ ResetIncrementalState(trace_writer, incr_state, tls_state, timestamp);
+ }
+ }
+
+ // TODO(altimin): Remove this method once Chrome uses
+ // EventContext::AddDebugAnnotation directly.
+ template <typename NameType, typename ValueType>
+ static void AddDebugAnnotation(perfetto::EventContext* event_ctx,
+ NameType&& name,
+ ValueType&& value) {
+ auto annotation =
+ AddDebugAnnotation(event_ctx, std::forward<NameType>(name));
+ WriteIntoTracedValue(
+ internal::CreateTracedValueFromProto(annotation, event_ctx),
+ std::forward<ValueType>(value));
+ }
+
+ // If the given track hasn't been seen by the trace writer yet, write a
+ // descriptor for it into the trace. Doesn't take a lock unless the track
+ // descriptor is new.
+ template <typename TrackType>
+ static void WriteTrackDescriptorIfNeeded(
+ const TrackType& track,
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ const TrackEventTlsState& tls_state,
+ const TraceTimestamp& timestamp) {
+ auto it_and_inserted = incr_state->seen_tracks.insert(track.uuid);
+ if (PERFETTO_LIKELY(!it_and_inserted.second))
+ return;
+ WriteTrackDescriptor(track, trace_writer, incr_state, tls_state, timestamp);
+ }
+
+ // Unconditionally write a track descriptor into the trace.
+ template <typename TrackType>
+ static void WriteTrackDescriptor(const TrackType& track,
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ const TrackEventTlsState& tls_state,
+ const TraceTimestamp& timestamp) {
+ ResetIncrementalStateIfRequired(trace_writer, incr_state, tls_state,
+ timestamp);
+ TrackRegistry::Get()->SerializeTrack(
+ track, NewTracePacket(trace_writer, incr_state, tls_state, timestamp));
+ }
+
+ // Get the current time in nanoseconds in the trace clock timebase.
+ static uint64_t GetTimeNs();
+
+ static TraceTimestamp GetTraceTime();
+
+ static inline protos::pbzero::BuiltinClock GetClockId() { return clock_; }
+ static inline void SetClockId(protos::pbzero::BuiltinClock clock) {
+ clock_ = clock;
+ }
+
+ static inline bool GetDisallowMergingWithSystemTracks() {
+ return disallow_merging_with_system_tracks_;
+ }
+ static inline void SetDisallowMergingWithSystemTracks(
+ bool disallow_merging_with_system_tracks) {
+ disallow_merging_with_system_tracks_ = disallow_merging_with_system_tracks;
+ }
+
+ static int GetSessionCount();
+
+ // Represents the default track for the calling thread.
+ static const Track kDefaultTrack;
+
+ private:
+ static void ResetIncrementalState(TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ const TrackEventTlsState& tls_state,
+ const TraceTimestamp& timestamp);
+
+ static protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket(
+ TraceWriterBase*,
+ TrackEventIncrementalState*,
+ const TrackEventTlsState& tls_state,
+ TraceTimestamp,
+ uint32_t seq_flags =
+ protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
+
+ static protos::pbzero::DebugAnnotation* AddDebugAnnotation(
+ perfetto::EventContext*,
+ const char* name);
+
+ static protos::pbzero::DebugAnnotation* AddDebugAnnotation(
+ perfetto::EventContext*,
+ perfetto::DynamicString name);
+
+ static std::atomic<int> session_count_;
+
+ static protos::pbzero::BuiltinClock clock_;
+ static bool disallow_merging_with_system_tracks_;
+};
+
+template <typename TraceContext>
+TrackEventTlsState::TrackEventTlsState(const TraceContext& trace_context) {
+ auto locked_ds = trace_context.GetDataSourceLocked();
+ bool disable_incremental_timestamps = false;
+ if (locked_ds.valid()) {
+ const auto& config = locked_ds->GetConfig();
+ disable_incremental_timestamps = config.disable_incremental_timestamps();
+ filter_debug_annotations = config.filter_debug_annotations();
+ filter_dynamic_event_names = config.filter_dynamic_event_names();
+ enable_thread_time_sampling = config.enable_thread_time_sampling();
+ if (config.has_timestamp_unit_multiplier()) {
+ timestamp_unit_multiplier = config.timestamp_unit_multiplier();
+ }
+ }
+ if (disable_incremental_timestamps) {
+ if (timestamp_unit_multiplier == 1) {
+ default_clock = static_cast<uint32_t>(TrackEventInternal::GetClockId());
+ } else {
+ default_clock = TrackEventIncrementalState::kClockIdAbsolute;
+ }
+ } else {
+ default_clock = TrackEventIncrementalState::kClockIdIncremental;
+ }
+}
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
+// gen_amalgamated begin header: include/perfetto/tracing/traced_proto.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
+#define INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/template_util.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_value.h"
+
+namespace perfetto {
+class EventContext;
+namespace internal {
+template <typename FieldMetadata,
+ bool is_message,
+ protozero::proto_utils::RepetitionType repetition_type>
+struct TypedProtoWriterImpl;
+}
+
+// A Wrapper around a protozero message to allow C++ classes to specify how it
+// should be serialised into the trace:
+//
+// class Foo {
+// public:
+// void WriteIntoTrace(perfetto::TracedProto<pbzero::Foo> message) {
+// message->set_int_field(int_field_);
+// }
+// };
+//
+// This class also exposes EventContext, e.g. to enable data interning.
+//
+// NOTE: the functionality below is not ready yet.
+// TODO(altimin): Make the interop below possible.
+// TracedProto also provides a seamless integration with writing untyped
+// values via TracedValue / TracedDictionary / TracedArray:
+//
+// - TracedValue can be converted to a TracedProto, either by calling
+// TracedValue::WriteProto<T>() or implicitly.
+// - If a proto message has a repeating DebugAnnotation debug_annotations
+// field, it can be filled using the TracedDictionary obtained from
+// TracedProto::AddDebugAnnotations.
+template <typename MessageType>
+class TracedProto {
+ public:
+ // implicit
+ TracedProto(TracedValue&& value)
+ : TracedProto(std::move(value).WriteProto<MessageType>()) {}
+ ~TracedProto() = default;
+
+ TracedProto(const TracedProto&) = delete;
+ TracedProto& operator=(const TracedProto&) = delete;
+ TracedProto& operator=(TracedProto&&) = delete;
+ TracedProto(TracedProto&&) = default;
+
+ MessageType* operator->() const { return message_; }
+
+ MessageType* message() { return message_; }
+
+ // Write additional untyped values into the same context, which is useful
+ // when a given C++ class has a typed representation, but also either has
+ // members which can only be written into an untyped context (e.g. they are
+ // autogenerated) or it's desirable to have a way to quickly extend the
+ // trace representation of this class (e.g. for debugging).
+ //
+ // The usage of the returned TracedDictionary should not be interleaved with
+ // writing into |message| as this results in an inefficient proto layout. To
+ // enforce this, AddDebugAnnotations should be called on TracedProto&&, i.e.
+ // std::move(message).AddDebugAnnotations().
+ //
+ // This requires a 'repeated DebugAnnotations debug_annotations' field in
+ // MessageType.
+ template <typename Check = void>
+ TracedDictionary AddDebugAnnotations() && {
+ static_assert(
+ std::is_base_of<
+ protozero::proto_utils::FieldMetadataBase,
+ typename MessageType::FieldMetadata_DebugAnnotations>::value,
+ "This message does not have a |debug_annotations| field. Please add a"
+ "'repeated perfetto.protos.DebugAnnotation debug_annnotations = N;' "
+ "field to your message.");
+ return TracedDictionary(message_, MessageType::kDebugAnnotations, context_,
+ nullptr);
+ }
+
+ // Start writing a single entry corresponding to the given |field| and return
+ // TracedProto should be used to populate this further.
+ // This method requires |field|'s type to be a nested message, but both
+ // repeated and non-repeated complex fields are supported.
+ template <typename FieldMetadata>
+ TracedProto<typename FieldMetadata::cpp_field_type> WriteNestedMessage(
+ FieldMetadata) {
+ static_assert(std::is_base_of<MessageType,
+ typename FieldMetadata::message_type>::value,
+ "Field should belong to the current message");
+ static_assert(
+ FieldMetadata::kProtoFieldType ==
+ protozero::proto_utils::ProtoSchemaType::kMessage,
+ "AddItem() can be used only for nested message fields. To write a "
+ "primitive field, use traced_proto->set_field() or traced_proto.Set()");
+ return Wrap(
+ message_->template BeginNestedMessage<
+ typename FieldMetadata::cpp_field_type>(FieldMetadata::kFieldId));
+ }
+
+ // Write a given |value| into proto as a new |field| of the current message.
+ // This method supports both nested messages and primitive types (i.e. int or
+ // string), but requires the |field| to be non-repeateable (i.e. optional).
+ // For repeatable fields, AppendValue or AppendFrom should be used.
+ template <typename FieldMetadata, typename ValueType>
+ void Set(FieldMetadata, ValueType&& value) {
+ static_assert(std::is_base_of<MessageType,
+ typename FieldMetadata::message_type>::value,
+ "Field should belong to the current message");
+ static_assert(
+ FieldMetadata::kRepetitionType ==
+ protozero::proto_utils::RepetitionType::kNotRepeated,
+ "Set() can't be used with repeated fields due to ambiguity between "
+ "writing |value| as a single entry or treating |value| as a container "
+ "and writing all contained items as multiple entries. Please use "
+ "dedicated AppendValue() or AppendFrom() methods to differentiate "
+ "between "
+ "these two situations");
+
+ internal::TypedProtoWriterImpl<
+ FieldMetadata,
+ FieldMetadata::kProtoFieldType ==
+ protozero::proto_utils::ProtoSchemaType::kMessage,
+ protozero::proto_utils::RepetitionType::kNotRepeated>::
+ Write(*this, std::forward<ValueType>(value));
+ }
+
+ // Write a given |value| a single entry into the repeated |field| of the
+ // current message. If the field is not repeated, Set() should be used
+ // instead.
+ template <typename FieldMetadata, typename ValueType>
+ void AppendValue(FieldMetadata, ValueType&& value) {
+ static_assert(std::is_base_of<MessageType,
+ typename FieldMetadata::message_type>::value,
+ "Field should belong to the current message");
+ static_assert(
+ FieldMetadata::kRepetitionType ==
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ "Append*() methods can be used only with repeated fields. "
+ "Please use Set() for non-repeated");
+
+ // Write a single value into a given repeated field by explicitly passing
+ // "kNotRepeated" to the TypedProtoWriterImpl.
+ internal::TypedProtoWriterImpl<
+ FieldMetadata,
+ FieldMetadata::kProtoFieldType ==
+ protozero::proto_utils::ProtoSchemaType::kMessage,
+ protozero::proto_utils::RepetitionType::kNotRepeated>::
+ Write(*this, std::forward<ValueType>(value));
+ }
+
+ // Write a given |value| as a set of entries into the repeated |field| of the
+ // current message. If the field is not repeated, Set() should be used
+ // instead.
+ template <typename FieldMetadata, typename ValueType>
+ void AppendFrom(FieldMetadata, ValueType&& value) {
+ static_assert(std::is_base_of<MessageType,
+ typename FieldMetadata::message_type>::value,
+ "Field should belong to the current message");
+ static_assert(
+ FieldMetadata::kRepetitionType ==
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ "Append*() methods can be used only with repeated fields. "
+ "Please use Set() for non-repeated");
+
+ internal::TypedProtoWriterImpl<
+ FieldMetadata,
+ FieldMetadata::kProtoFieldType ==
+ protozero::proto_utils::ProtoSchemaType::kMessage,
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked>::
+ Write(*this, std::forward<ValueType>(value));
+ }
+
+ // Write a nested message into a field according to the provided metadata.
+ // TODO(altimin): Replace the current usages in Chrome with the functions
+ // above and make these methods private.
+ template <typename FieldMetadata>
+ TracedProto<typename FieldMetadata::cpp_field_type> WriteNestedMessage() {
+ return WriteNestedMessage(FieldMetadata());
+ }
+
+ private:
+ friend class EventContext;
+ friend class TracedValue;
+ // Allow TracedProto<Foo> to create TracedProto<Bar>.
+ template <typename T>
+ friend class TracedProto;
+
+ // Wraps a raw protozero message using the same context as the current object.
+ template <typename ChildMessageType>
+ TracedProto<ChildMessageType> Wrap(ChildMessageType* message) {
+ return TracedProto<ChildMessageType>(message, context_);
+ }
+
+ // Context might be null here when writing typed message which is
+ // nested into untyped legacy trace event macro argument.
+ // TODO(altimin): Turn this into EventContext& when this case is eliminated
+ // and expose it in public API.
+ EventContext* context() const { return context_; }
+
+ TracedProto(MessageType* message, EventContext* context)
+ : message_(message), context_(context) {}
+
+ MessageType* const message_;
+ EventContext* context_;
+};
+
+template <typename MessageType, typename ValueType>
+void WriteIntoTracedProto(TracedProto<MessageType> message, ValueType&& value);
+
+namespace internal {
+
+template <typename FieldMetadata,
+ bool is_message,
+ protozero::proto_utils::RepetitionType repetition_type>
+struct TypedProtoWriterImpl;
+
+// Simple non-repeated field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/false,
+ protozero::proto_utils::RepetitionType::kNotRepeated> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto>& context, ValueType&& value) {
+ protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
+ *context.message(), FieldMetadata::kFieldId, value);
+ }
+};
+
+// Simple repeated non-packed field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/false,
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto>& context, ValueType&& value) {
+ for (auto&& item : value) {
+ protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
+ *context.message(), FieldMetadata::kFieldId, item);
+ }
+ }
+};
+
+// Nested repeated non-packed field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/true,
+ protozero::proto_utils::RepetitionType::kNotRepeated> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto>& context, ValueType&& value) {
+ WriteIntoTracedProto(context.template WriteNestedMessage<FieldMetadata>(),
+ std::forward<ValueType>(value));
+ }
+};
+
+// Nested repeated non-packed field.
+template <typename FieldMetadata>
+struct TypedProtoWriterImpl<
+ FieldMetadata,
+ /*is_message=*/true,
+ protozero::proto_utils::RepetitionType::kRepeatedNotPacked> {
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto>& context, ValueType&& value) {
+ for (auto&& item : value) {
+ WriteIntoTracedProto(context.template WriteNestedMessage<FieldMetadata>(),
+ item);
+ }
+ }
+};
+
+constexpr int kMaxWriteTracedProtoImplPriority = 1;
+
+// If perfetto::TraceFormatTraits<T>::WriteIntoTrace(TracedProto<MessageType>,
+// T) is available, use it.
+template <typename MessageType, typename T>
+decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
+ std::declval<TracedProto<MessageType>>(),
+ std::declval<T>()),
+ void())
+WriteIntoTracedProtoImpl(base::priority_tag<1>,
+ TracedProto<MessageType> message,
+ T&& value) {
+ TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
+ std::move(message), std::forward<T>(value));
+}
+
+// If T has WriteIntoTrace(TracedProto<MessageType>) method, use it.
+template <typename MessageType, typename T>
+decltype(
+ std::declval<T>().WriteIntoTrace(std::declval<TracedProto<MessageType>>()),
+ void())
+WriteIntoTracedProtoImpl(base::priority_tag<0>,
+ TracedProto<MessageType> message,
+ T&& value) {
+ value.WriteIntoTrace(std::move(message));
+}
+
+// TypedProtoWriter takes the protozero message (TracedProto<MessageType>),
+// field description (FieldMetadata) and value and writes the given value
+// into the given field of the given protozero message.
+//
+// This is primarily used for inline writing of typed messages:
+// TRACE_EVENT(..., pbzero::Message:kField, value);
+//
+// Ideally we would use a function here and not a struct, but passing template
+// arguments directly to the function (e.g. foo<void>()) isn't supported until
+// C++20, so we have to use a helper struct here.
+template <typename FieldMetadata>
+struct TypedProtoWriter {
+ private:
+ using ProtoSchemaType = protozero::proto_utils::ProtoSchemaType;
+ using RepetitionType = protozero::proto_utils::RepetitionType;
+
+ static_assert(FieldMetadata::kRepetitionType !=
+ RepetitionType::kRepeatedPacked,
+ "writing packed fields isn't supported yet");
+
+ template <bool is_message, RepetitionType repetition_type>
+ struct Writer;
+
+ public:
+ template <typename Proto, typename ValueType>
+ static void Write(TracedProto<Proto>& context, ValueType&& value) {
+ TypedProtoWriterImpl<
+ FieldMetadata,
+ FieldMetadata::kProtoFieldType == ProtoSchemaType::kMessage,
+ FieldMetadata::kRepetitionType>::Write(context,
+ std::forward<ValueType>(value));
+ }
+};
+
+} // namespace internal
+
+// Helper template to determine if a given type can be passed to
+// perfetto::WriteIntoTracedProto. These templates will fail to resolve if the
+// class does not have necesary support, so they are useful for SFINAE and for
+// producing helpful compiler error messages.
+template <typename MessageType, typename ValueType, typename Result = void>
+using check_traced_proto_support_t =
+ decltype(internal::WriteIntoTracedProtoImpl(
+ std::declval<
+ base::priority_tag<internal::kMaxWriteTracedProtoImplPriority>>(),
+ std::declval<TracedProto<MessageType>>(),
+ std::declval<ValueType>()));
+
+// check_traced_proto_support<MessageType, T, V>::type is defined (and equal to
+// V) iff T supports being passed to WriteIntoTracedProto together with
+// TracedProto<MessageType>. See the comment in traced_value_forward.h for more
+// details.
+template <typename MessageType, typename ValueType, class Result>
+struct check_traced_proto_support<
+ MessageType,
+ ValueType,
+ Result,
+ check_traced_proto_support_t<MessageType, ValueType, Result>> {
+ static constexpr bool value = true;
+ using type = Result;
+};
+
+template <typename MessageType, typename ValueType>
+void WriteIntoTracedProto(TracedProto<MessageType> message, ValueType&& value) {
+ // TODO(altimin): Add a URL to the documentation and a list of common failure
+ // patterns.
+ static_assert(
+ std::is_same<check_traced_proto_support_t<MessageType, ValueType>,
+ void>::value,
+ "The provided type does not support being serialised into the "
+ "provided protozero message. Please see the comment in traced_proto.h "
+ "for more details.");
+
+ internal::WriteIntoTracedProtoImpl(
+ base::priority_tag<internal::kMaxWriteTracedProtoImplPriority>(),
+ std::move(message), std::forward<ValueType>(value));
+}
+
+template <typename MessageType, typename FieldMetadataType, typename ValueType>
+void WriteTracedProtoField(TracedProto<MessageType>& message,
+ FieldMetadataType,
+ ValueType&& value) {
+ static_assert(
+ std::is_base_of<protozero::proto_utils::FieldMetadataBase,
+ FieldMetadataType>::value,
+ "Field name should be a protozero::internal::FieldMetadata<...>");
+ static_assert(
+ std::is_base_of<MessageType,
+ typename FieldMetadataType::message_type>::value,
+ "Field's parent type should match the context.");
+
+ internal::TypedProtoWriter<FieldMetadataType>::Write(
+ message, std::forward<ValueType>(value));
+}
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
+#define INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_proto.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DebugAnnotation;
+} // namespace pbzero
+} // namespace protos
+
+namespace internal {
+class TrackEventInternal;
+}
+
+// Allows adding custom arguments into track events. Example:
+//
+// TRACE_EVENT_BEGIN("category", "Title",
+// [](perfetto::EventContext ctx) {
+// auto* log = ctx.event()->set_log_message();
+// log->set_body_iid(1234);
+//
+// ctx.AddDebugAnnotation("name", 1234);
+// });
+//
+class PERFETTO_EXPORT_COMPONENT EventContext {
+ public:
+ EventContext(EventContext&&) = default;
+
+ // For Chromium during the transition phase to the client library.
+ // TODO(eseckler): Remove once Chromium has switched to client lib entirely.
+ explicit EventContext(
+ protos::pbzero::TrackEvent* event,
+ internal::TrackEventIncrementalState* incremental_state = nullptr,
+ bool filter_debug_annotations = false)
+ : event_(event),
+ incremental_state_(incremental_state),
+ filter_debug_annotations_(filter_debug_annotations) {}
+
+ ~EventContext();
+
+ internal::TrackEventIncrementalState* GetIncrementalState() const {
+ return incremental_state_;
+ }
+
+ // Disclaimer: Experimental method, subject to change.
+ // Exposed publicly to emit some TrackEvent fields in Chromium only in local
+ // tracing. Long-term, we really shouldn't be (ab)using the
+ // filter_debug_annotation setting for this.
+ //
+ // TODO(kraskevich): Come up with a more precise name once we have more than
+ // one usecase.
+ bool ShouldFilterDebugAnnotations() const {
+ if (tls_state_) {
+ return tls_state_->filter_debug_annotations;
+ }
+ // In Chromium tls_state_ is nullptr, so we need to get this information
+ // from a separate field.
+ return filter_debug_annotations_;
+ }
+
+ // Get a TrackEvent message to write typed arguments to.
+ //
+ // event() is a template method to allow callers to specify a subclass of
+ // TrackEvent instead. Those subclasses correspond to TrackEvent message with
+ // application-specific extensions. More information in
+ // design-docs/extensions.md.
+ template <typename EventType = protos::pbzero::TrackEvent>
+ EventType* event() const {
+ // As the method does downcasting, we check that a target subclass does
+ // not add new fields.
+ static_assert(
+ sizeof(EventType) == sizeof(protos::pbzero::TrackEvent),
+ "Event type must be binary-compatible with protos::pbzero::TrackEvent");
+ return static_cast<EventType*>(event_);
+ }
+
+ // Convert a raw pointer to protozero message to TracedProto which captures
+ // the reference to this EventContext.
+ template <typename MessageType>
+ TracedProto<MessageType> Wrap(MessageType* message) {
+ static_assert(std::is_base_of<protozero::Message, MessageType>::value,
+ "TracedProto can be used only with protozero messages");
+
+ return TracedProto<MessageType>(message, this);
+ }
+
+ // Add a new `debug_annotation` proto message and populate it from |value|
+ // using perfetto::TracedValue API. Users should generally prefer passing
+ // values directly to TRACE_EVENT (i.e. TRACE_EVENT(..., "arg", value, ...);)
+ // but in rare cases (e.g. when an argument should be written conditionally)
+ // EventContext::AddDebugAnnotation provides an explicit equivalent.
+ template <typename EventNameType, typename T>
+ void AddDebugAnnotation(EventNameType&& name, T&& value) {
+ if (tls_state_ && tls_state_->filter_debug_annotations)
+ return;
+ auto annotation = AddDebugAnnotation(std::forward<EventNameType>(name));
+ WriteIntoTracedValue(internal::CreateTracedValueFromProto(annotation, this),
+ std::forward<T>(value));
+ }
+
+ // Read arbitrary user data that is associated with the thread-local per
+ // instance state of the track event. `key` must be non-null and unique
+ // per TrackEventTlsStateUserData subclass.
+ TrackEventTlsStateUserData* GetTlsUserData(const void* key);
+
+ // Set arbitrary user data that is associated with the thread-local per
+ // instance state of the track event. `key` must be non-null and unique
+ // per TrackEventTlsStateUserData subclass.
+ void SetTlsUserData(const void* key,
+ std::unique_ptr<TrackEventTlsStateUserData> data);
+
+ private:
+ template <typename, size_t, typename, typename>
+ friend class TrackEventInternedDataIndex;
+ friend class internal::TrackEventInternal;
+
+ using TracePacketHandle =
+ ::protozero::MessageHandle<protos::pbzero::TracePacket>;
+
+ EventContext(TraceWriterBase* trace_writer,
+ TracePacketHandle,
+ internal::TrackEventIncrementalState*,
+ internal::TrackEventTlsState*);
+ EventContext(const EventContext&) = delete;
+
+ protos::pbzero::DebugAnnotation* AddDebugAnnotation(const char* name);
+ protos::pbzero::DebugAnnotation* AddDebugAnnotation(
+ ::perfetto::DynamicString name);
+
+ TraceWriterBase* trace_writer_ = nullptr;
+ TracePacketHandle trace_packet_;
+ protos::pbzero::TrackEvent* event_;
+ internal::TrackEventIncrementalState* incremental_state_;
+ // TODO(mohitms): Make it const-reference instead of pointer, once we
+ // are certain that it cannot be nullptr. Once we switch to client library in
+ // chrome, we can make that happen.
+ internal::TrackEventTlsState* tls_state_ = nullptr;
+ // TODO(kraskevich): Come up with a more precise name once we have more than
+ // one usecase.
+ // TODO(kraskevich): Remove once Chromium has fully switched to client lib.
+ const bool filter_debug_annotations_ = false;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_legacy.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_LEGACY_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_LEGACY_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/event_context.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+#ifndef PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 0
+#endif
+
+// ----------------------------------------------------------------------------
+// Constants.
+// ----------------------------------------------------------------------------
+
+namespace perfetto {
+namespace legacy {
+
+enum TraceEventFlag {
+ kTraceEventFlagNone = 0,
+ kTraceEventFlagCopy = 1u << 0,
+ kTraceEventFlagHasId = 1u << 1,
+ kTraceEventFlagScopeOffset = 1u << 2,
+ kTraceEventFlagScopeExtra = 1u << 3,
+ kTraceEventFlagExplicitTimestamp = 1u << 4,
+ kTraceEventFlagAsyncTTS = 1u << 5,
+ kTraceEventFlagBindToEnclosing = 1u << 6,
+ kTraceEventFlagFlowIn = 1u << 7,
+ kTraceEventFlagFlowOut = 1u << 8,
+ kTraceEventFlagHasContextId = 1u << 9,
+ kTraceEventFlagHasProcessId = 1u << 10,
+ kTraceEventFlagHasLocalId = 1u << 11,
+ kTraceEventFlagHasGlobalId = 1u << 12,
+ // TODO(eseckler): Remove once we have native support for typed proto events
+ // in TRACE_EVENT macros.
+ kTraceEventFlagTypedProtoArgs = 1u << 15,
+ kTraceEventFlagJavaStringLiterals = 1u << 16,
+};
+
+enum PerfettoLegacyCurrentThreadId { kCurrentThreadId };
+
+// The following user-provided adaptors are used to serialize user-defined
+// thread id and time types into track events. For full compatibility, the user
+// should also define the following macros appropriately:
+//
+// #define TRACE_TIME_TICKS_NOW() ...
+// #define TRACE_TIME_NOW() ...
+
+// User-provided function to convert an abstract thread id into a thread track.
+template <typename T>
+ThreadTrack ConvertThreadId(const T&);
+
+// Built-in implementation for events referring to the current thread.
+template <>
+ThreadTrack PERFETTO_EXPORT_COMPONENT
+ConvertThreadId(const PerfettoLegacyCurrentThreadId&);
+
+} // namespace legacy
+} // namespace perfetto
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+// The following constants are defined in the global namespace, since they were
+// originally implemented as macros.
+
+// Event phases.
+static constexpr char TRACE_EVENT_PHASE_BEGIN = 'B';
+static constexpr char TRACE_EVENT_PHASE_END = 'E';
+static constexpr char TRACE_EVENT_PHASE_COMPLETE = 'X';
+static constexpr char TRACE_EVENT_PHASE_INSTANT = 'I';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_BEGIN = 'S';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_INTO = 'T';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_PAST = 'p';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_END = 'F';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN = 'b';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_END = 'e';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT = 'n';
+static constexpr char TRACE_EVENT_PHASE_FLOW_BEGIN = 's';
+static constexpr char TRACE_EVENT_PHASE_FLOW_STEP = 't';
+static constexpr char TRACE_EVENT_PHASE_FLOW_END = 'f';
+static constexpr char TRACE_EVENT_PHASE_METADATA = 'M';
+static constexpr char TRACE_EVENT_PHASE_COUNTER = 'C';
+static constexpr char TRACE_EVENT_PHASE_SAMPLE = 'P';
+static constexpr char TRACE_EVENT_PHASE_CREATE_OBJECT = 'N';
+static constexpr char TRACE_EVENT_PHASE_SNAPSHOT_OBJECT = 'O';
+static constexpr char TRACE_EVENT_PHASE_DELETE_OBJECT = 'D';
+static constexpr char TRACE_EVENT_PHASE_MEMORY_DUMP = 'v';
+static constexpr char TRACE_EVENT_PHASE_MARK = 'R';
+static constexpr char TRACE_EVENT_PHASE_CLOCK_SYNC = 'c';
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+static constexpr uint32_t TRACE_EVENT_FLAG_NONE =
+ perfetto::legacy::kTraceEventFlagNone;
+static constexpr uint32_t TRACE_EVENT_FLAG_COPY =
+ perfetto::legacy::kTraceEventFlagCopy;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_ID =
+ perfetto::legacy::kTraceEventFlagHasId;
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_OFFSET =
+ perfetto::legacy::kTraceEventFlagScopeOffset;
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_EXTRA =
+ perfetto::legacy::kTraceEventFlagScopeExtra;
+static constexpr uint32_t TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP =
+ perfetto::legacy::kTraceEventFlagExplicitTimestamp;
+static constexpr uint32_t TRACE_EVENT_FLAG_ASYNC_TTS =
+ perfetto::legacy::kTraceEventFlagAsyncTTS;
+static constexpr uint32_t TRACE_EVENT_FLAG_BIND_TO_ENCLOSING =
+ perfetto::legacy::kTraceEventFlagBindToEnclosing;
+static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_IN =
+ perfetto::legacy::kTraceEventFlagFlowIn;
+static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_OUT =
+ perfetto::legacy::kTraceEventFlagFlowOut;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_CONTEXT_ID =
+ perfetto::legacy::kTraceEventFlagHasContextId;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_PROCESS_ID =
+ perfetto::legacy::kTraceEventFlagHasProcessId;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_LOCAL_ID =
+ perfetto::legacy::kTraceEventFlagHasLocalId;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_GLOBAL_ID =
+ perfetto::legacy::kTraceEventFlagHasGlobalId;
+static constexpr uint32_t TRACE_EVENT_FLAG_TYPED_PROTO_ARGS =
+ perfetto::legacy::kTraceEventFlagTypedProtoArgs;
+static constexpr uint32_t TRACE_EVENT_FLAG_JAVA_STRING_LITERALS =
+ perfetto::legacy::kTraceEventFlagJavaStringLiterals;
+
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_MASK =
+ TRACE_EVENT_FLAG_SCOPE_OFFSET | TRACE_EVENT_FLAG_SCOPE_EXTRA;
+
+// Type values for identifying types in the TraceValue union.
+static constexpr uint8_t TRACE_VALUE_TYPE_BOOL = 1;
+static constexpr uint8_t TRACE_VALUE_TYPE_UINT = 2;
+static constexpr uint8_t TRACE_VALUE_TYPE_INT = 3;
+static constexpr uint8_t TRACE_VALUE_TYPE_DOUBLE = 4;
+static constexpr uint8_t TRACE_VALUE_TYPE_POINTER = 5;
+static constexpr uint8_t TRACE_VALUE_TYPE_STRING = 6;
+static constexpr uint8_t TRACE_VALUE_TYPE_COPY_STRING = 7;
+static constexpr uint8_t TRACE_VALUE_TYPE_CONVERTABLE = 8;
+static constexpr uint8_t TRACE_VALUE_TYPE_PROTO = 9;
+
+// Enum reflecting the scope of an INSTANT event. Must fit within
+// TRACE_EVENT_FLAG_SCOPE_MASK.
+static constexpr uint8_t TRACE_EVENT_SCOPE_GLOBAL = 0u << 2;
+static constexpr uint8_t TRACE_EVENT_SCOPE_PROCESS = 1u << 2;
+static constexpr uint8_t TRACE_EVENT_SCOPE_THREAD = 2u << 2;
+
+static constexpr char TRACE_EVENT_SCOPE_NAME_GLOBAL = 'g';
+static constexpr char TRACE_EVENT_SCOPE_NAME_PROCESS = 'p';
+static constexpr char TRACE_EVENT_SCOPE_NAME_THREAD = 't';
+
+#define TRACE_EVENT_API_CURRENT_THREAD_ID ::perfetto::legacy::kCurrentThreadId
+
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+namespace perfetto {
+namespace internal {
+
+// LegacyTraceId encapsulates an ID that can either be an integer or pointer.
+class PERFETTO_EXPORT_COMPONENT LegacyTraceId {
+ public:
+ // Can be combined with WithScope.
+ class LocalId {
+ public:
+ explicit LocalId(const void* raw_id)
+ : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
+ explicit LocalId(uint64_t raw_id) : raw_id_(raw_id) {}
+ uint64_t raw_id() const { return raw_id_; }
+
+ private:
+ uint64_t raw_id_;
+ };
+
+ // Can be combined with WithScope.
+ class GlobalId {
+ public:
+ explicit GlobalId(uint64_t raw_id) : raw_id_(raw_id) {}
+ uint64_t raw_id() const { return raw_id_; }
+
+ private:
+ uint64_t raw_id_;
+ };
+
+ class WithScope {
+ public:
+ WithScope(const char* scope, uint64_t raw_id)
+ : scope_(scope), raw_id_(raw_id) {}
+ WithScope(const char* scope, LocalId local_id)
+ : scope_(scope), raw_id_(local_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasLocalId;
+ }
+ WithScope(const char* scope, GlobalId global_id)
+ : scope_(scope), raw_id_(global_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasGlobalId;
+ }
+ WithScope(const char* scope, uint64_t prefix, uint64_t raw_id)
+ : scope_(scope), has_prefix_(true), prefix_(prefix), raw_id_(raw_id) {}
+ WithScope(const char* scope, uint64_t prefix, GlobalId global_id)
+ : scope_(scope),
+ has_prefix_(true),
+ prefix_(prefix),
+ raw_id_(global_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasGlobalId;
+ }
+ uint64_t raw_id() const { return raw_id_; }
+ const char* scope() const { return scope_; }
+ bool has_prefix() const { return has_prefix_; }
+ uint64_t prefix() const { return prefix_; }
+ uint32_t id_flags() const { return id_flags_; }
+
+ private:
+ const char* scope_ = nullptr;
+ bool has_prefix_ = false;
+ uint64_t prefix_;
+ uint64_t raw_id_;
+ uint32_t id_flags_ = legacy::kTraceEventFlagHasId;
+ };
+
+ explicit LegacyTraceId(const void* raw_id)
+ : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
+ id_flags_ = legacy::kTraceEventFlagHasLocalId;
+ }
+ explicit LegacyTraceId(uint64_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(uint32_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(uint16_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(uint8_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(int64_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+ explicit LegacyTraceId(int32_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+ explicit LegacyTraceId(int16_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+ explicit LegacyTraceId(int8_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+// Different platforms disagree on which integer types are same and which
+// are different. E.g. on Mac size_t is considered a different type from
+// uint64_t even though it has the same size and signedness.
+// Below we add overloads for those types that are known to cause ambiguity.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ explicit LegacyTraceId(size_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(intptr_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ explicit LegacyTraceId(unsigned long raw_id) : raw_id_(raw_id) {}
+#endif
+ explicit LegacyTraceId(LocalId raw_id) : raw_id_(raw_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasLocalId;
+ }
+ explicit LegacyTraceId(GlobalId raw_id) : raw_id_(raw_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasGlobalId;
+ }
+ explicit LegacyTraceId(WithScope scoped_id)
+ : scope_(scoped_id.scope()),
+ has_prefix_(scoped_id.has_prefix()),
+ prefix_(scoped_id.prefix()),
+ raw_id_(scoped_id.raw_id()),
+ id_flags_(scoped_id.id_flags()) {}
+
+ uint64_t raw_id() const { return raw_id_; }
+ const char* scope() const { return scope_; }
+ bool has_prefix() const { return has_prefix_; }
+ uint64_t prefix() const { return prefix_; }
+ uint32_t id_flags() const { return id_flags_; }
+
+ void Write(protos::pbzero::TrackEvent::LegacyEvent*,
+ uint32_t event_flags) const;
+
+ private:
+ const char* scope_ = nullptr;
+ bool has_prefix_ = false;
+ uint64_t prefix_;
+ uint64_t raw_id_;
+ uint32_t id_flags_ = legacy::kTraceEventFlagHasId;
+};
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+template <typename T>
+bool IsEqual(T x, T y) {
+ return x == y;
+}
+
+template <typename T, typename U>
+bool IsEqual(T, U) {
+ return false;
+}
+
+class PERFETTO_EXPORT_COMPONENT TrackEventLegacy {
+ public:
+ static constexpr protos::pbzero::TrackEvent::Type PhaseToType(char phase) {
+ // clang-format off
+ return (phase == TRACE_EVENT_PHASE_BEGIN) ?
+ protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN :
+ (phase == TRACE_EVENT_PHASE_END) ?
+ protos::pbzero::TrackEvent::TYPE_SLICE_END :
+ (phase == TRACE_EVENT_PHASE_INSTANT) ?
+ protos::pbzero::TrackEvent::TYPE_INSTANT :
+ protos::pbzero::TrackEvent::TYPE_UNSPECIFIED;
+ // clang-format on
+ }
+
+ // Reduce binary size overhead by outlining most of the code for writing a
+ // legacy trace event.
+ template <typename... Args>
+ static void WriteLegacyEvent(EventContext ctx,
+ char phase,
+ uint32_t flags,
+ Args&&... args) PERFETTO_NO_INLINE {
+ PERFETTO_DCHECK(!(flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID));
+ AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
+ if (NeedLegacyFlags(phase, flags)) {
+ auto legacy_event = ctx.event()->set_legacy_event();
+ SetLegacyFlags(legacy_event, phase, flags);
+ }
+ }
+
+ template <typename ThreadIdType, typename... Args>
+ static void WriteLegacyEventWithIdAndTid(EventContext ctx,
+ char phase,
+ uint32_t flags,
+ const LegacyTraceId& id,
+ const ThreadIdType& thread_id,
+ Args&&... args) PERFETTO_NO_INLINE {
+ //
+ // Overrides to consider:
+ //
+ // 1. If we have an id, we need to write {unscoped,local,global}_id and/or
+ // bind_id.
+ // 2. If we have a thread id, we need to write track_uuid() or
+ // {pid,tid}_override if the id represents another process. The
+ // conversion from |thread_id| happens in embedder code since the type is
+ // embedder-specified.
+ // 3. If we have a timestamp, we need to write a different timestamp in the
+ // trace packet itself and make sure TrackEvent won't write one
+ // internally. This is already done at the call site.
+ //
+ PERFETTO_DCHECK(PhaseToType(phase) ==
+ protos::pbzero::TrackEvent::TYPE_UNSPECIFIED ||
+ !(flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID));
+ flags |= id.id_flags();
+ AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
+ if (NeedLegacyFlags(phase, flags)) {
+ auto legacy_event = ctx.event()->set_legacy_event();
+ SetLegacyFlags(legacy_event, phase, flags);
+ if (id.id_flags())
+ id.Write(legacy_event, flags);
+ if (flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID) {
+ // The thread identifier actually represents a process id. Let's set an
+ // override for it.
+ int32_t pid_override =
+ static_cast<int32_t>(legacy::ConvertThreadId(thread_id).tid);
+ legacy_event->set_pid_override(pid_override);
+ legacy_event->set_tid_override(-1);
+ } else {
+ // Only synchronous phases are supported for other threads. These phases
+ // are supported in TrackEvent types and receive a track_uuid
+ // association via TrackEventDataSource::TraceForCategoryImpl().
+ PERFETTO_DCHECK(PhaseToType(phase) !=
+ protos::pbzero::TrackEvent::TYPE_UNSPECIFIED ||
+ IsEqual(thread_id, TRACE_EVENT_API_CURRENT_THREAD_ID) ||
+ legacy::ConvertThreadId(thread_id).tid ==
+ ThreadTrack::Current().tid);
+ }
+ }
+ }
+
+ // No arguments.
+ static void AddDebugAnnotations(EventContext*) {}
+
+ // N number of debug arguments.
+ template <typename ArgNameType, typename ArgType, typename... OtherArgs>
+ static void AddDebugAnnotations(EventContext* ctx,
+ ArgNameType&& arg_name,
+ ArgType&& arg_value,
+ OtherArgs&&... more_args) {
+ TrackEventInternal::AddDebugAnnotation(ctx,
+ std::forward<ArgNameType>(arg_name),
+ std::forward<ArgType>(arg_value));
+ AddDebugAnnotations(ctx, std::forward<OtherArgs>(more_args)...);
+ }
+
+ private:
+ static bool NeedLegacyFlags(char phase, uint32_t flags) {
+ if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
+ return true;
+ // TODO(skyostil): Implement/deprecate:
+ // - TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP
+ // - TRACE_EVENT_FLAG_HAS_CONTEXT_ID
+ // - TRACE_EVENT_FLAG_TYPED_PROTO_ARGS
+ // - TRACE_EVENT_FLAG_JAVA_STRING_LITERALS
+ return flags &
+ (TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_HAS_LOCAL_ID |
+ TRACE_EVENT_FLAG_HAS_GLOBAL_ID | TRACE_EVENT_FLAG_ASYNC_TTS |
+ TRACE_EVENT_FLAG_BIND_TO_ENCLOSING | TRACE_EVENT_FLAG_FLOW_IN |
+ TRACE_EVENT_FLAG_FLOW_OUT | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
+ }
+
+ static void SetLegacyFlags(
+ protos::pbzero::TrackEvent::LegacyEvent* legacy_event,
+ char phase,
+ uint32_t flags) {
+ if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
+ legacy_event->set_phase(phase);
+ if (flags & TRACE_EVENT_FLAG_ASYNC_TTS)
+ legacy_event->set_use_async_tts(true);
+ if (flags & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING)
+ legacy_event->set_bind_to_enclosing(true);
+
+ const auto kFlowIn = TRACE_EVENT_FLAG_FLOW_IN;
+ const auto kFlowOut = TRACE_EVENT_FLAG_FLOW_OUT;
+ const auto kFlowInOut = kFlowIn | kFlowOut;
+ if ((flags & kFlowInOut) == kFlowInOut) {
+ legacy_event->set_flow_direction(
+ protos::pbzero::TrackEvent::LegacyEvent::FLOW_INOUT);
+ } else if (flags & kFlowIn) {
+ legacy_event->set_flow_direction(
+ protos::pbzero::TrackEvent::LegacyEvent::FLOW_IN);
+ } else if (flags & kFlowOut) {
+ legacy_event->set_flow_direction(
+ protos::pbzero::TrackEvent::LegacyEvent::FLOW_OUT);
+ }
+ }
+};
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+// Legacy macros allow argument values to be nullptr and convert them to the
+// "NULL" string. The following function helps mimic this behavior: it forwards
+// all types of arguments apart from a nullptr string as is, and in case of a
+// nullptr returns "NULL".
+template <typename T>
+inline T PossiblyNull(T&& value) {
+ return std::forward<T>(value);
+}
+
+inline const char* PossiblyNull(const char* name) {
+ return name ? name : "NULL";
+}
+
+inline const char* PossiblyNull(char* name) {
+ return name ? name : "NULL";
+}
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_LEGACY_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/write_track_event_args.h
+// gen_amalgamated begin header: include/perfetto/tracing/track_event_args.h
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_ARGS_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_ARGS_H_
+
+// gen_amalgamated expanded: #include "perfetto/tracing/event_context.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track.h"
+
+namespace perfetto {
+
+// A helper to add |flow_id| as a non-terminating flow id to TRACE_EVENT
+// inline: TRACE_EVENT(..., perfetto::Flow::ProcessScoped(42));
+class Flow {
+ public:
+ // |flow_id| which is local within a given process (e.g. atomic counter xor'ed
+ // with feature-specific value). This value is xor'ed with Perfetto's internal
+ // process track id to attempt to ensure that it's globally-unique.
+ static PERFETTO_ALWAYS_INLINE inline Flow ProcessScoped(uint64_t flow_id) {
+ return Global(flow_id ^ Track::process_uuid);
+ }
+
+ // Same as above, but construct an id from a pointer.
+ // NOTE: After the object is destroyed, the value of |ptr| can be reused for a
+ // different object (in particular if the object is allocated on a stack).
+ // Please ensure that you emit a trace event with the flow id of
+ // perfetto::TerminatingFlow::FromPointer(this) from the destructor of the
+ // object to avoid accidental conflicts.
+ static PERFETTO_ALWAYS_INLINE inline Flow FromPointer(void* ptr) {
+ return ProcessScoped(reinterpret_cast<uintptr_t>(ptr));
+ }
+
+ // Add the |flow_id|. The caller is responsible for ensuring that it's
+ // globally-unique (e.g. by generating a random value). This should be used
+ // only for flow events which cross the process boundary (e.g. IPCs).
+ static PERFETTO_ALWAYS_INLINE inline Flow Global(uint64_t flow_id) {
+ return Flow(flow_id);
+ }
+
+ // TODO(altimin): Remove once converting a single usage in Chromium.
+ explicit constexpr Flow(uint64_t flow_id) : flow_id_(flow_id) {}
+
+ void operator()(EventContext& ctx) const {
+ ctx.event()->add_flow_ids(flow_id_);
+ }
+
+ private:
+ uint64_t flow_id_;
+};
+
+// A helper to add a given |flow_id| as a terminating flow to TRACE_EVENT
+// inline.
+class TerminatingFlow {
+ public:
+ // See `Flow::ProcessScoped(uint64_t)`.
+ static PERFETTO_ALWAYS_INLINE inline TerminatingFlow ProcessScoped(
+ uint64_t flow_id) {
+ return Global(flow_id ^ Track::process_uuid);
+ }
+
+ // See `Flow::FromPointer(void*)`.
+ static PERFETTO_ALWAYS_INLINE inline TerminatingFlow FromPointer(void* ptr) {
+ return ProcessScoped(reinterpret_cast<uintptr_t>(ptr));
+ }
+
+ // See `Flow::Global(uint64_t)`.
+ static PERFETTO_ALWAYS_INLINE inline TerminatingFlow Global(
+ uint64_t flow_id) {
+ TerminatingFlow tf;
+ tf.flow_id_ = flow_id;
+ return tf;
+ }
+
+ void operator()(EventContext& ctx) const {
+ ctx.event()->add_terminating_flow_ids(flow_id_);
+ }
+
+ private:
+ uint64_t flow_id_;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_ARGS_H_
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/event_context.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/traced_proto.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_args.h"
+
+namespace perfetto {
+namespace internal {
+
+// No arguments means that we don't have to write anything.
+PERFETTO_ALWAYS_INLINE inline void WriteTrackEventArgs(EventContext) {}
+
+namespace {
+
+// A template helper for determining whether a type can be used as a track event
+// lambda, i.e., it has the signature "void(EventContext)". This is achieved by
+// checking that we can pass an EventContext value (the inner declval) into a T
+// instance (the outer declval). If this is a valid expression, the result
+// evaluates to sizeof(0), i.e., true.
+// TODO(skyostil): Replace this with std::is_convertible<std::function<...>>
+// once we have C++14.
+template <typename T>
+static constexpr bool IsValidTraceLambdaImpl(
+ typename std::enable_if<static_cast<bool>(
+ sizeof(std::declval<T>()(std::declval<EventContext>()), 0))>::type* =
+ nullptr) {
+ return true;
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambdaImpl(...) {
+ return false;
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambda() {
+ return IsValidTraceLambdaImpl<T>(nullptr);
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambdaTakingReferenceImpl(
+ typename std::enable_if<static_cast<bool>(
+ sizeof(std::declval<T>()(std::declval<EventContext&>()), 0))>::type* =
+ nullptr) {
+ return true;
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambdaTakingReferenceImpl(...) {
+ return false;
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambdaTakingReference() {
+ return IsValidTraceLambdaTakingReferenceImpl<T>(nullptr);
+}
+
+template <typename T>
+static constexpr bool IsFieldMetadataTypeImpl(
+ typename std::enable_if<
+ std::is_base_of<protozero::proto_utils::FieldMetadataBase,
+ T>::value>::type* = nullptr) {
+ return true;
+}
+
+template <typename T>
+static constexpr bool IsFieldMetadataTypeImpl(...) {
+ return false;
+}
+
+template <typename T>
+static constexpr bool IsFieldMetadataType() {
+ return IsFieldMetadataTypeImpl<T>(nullptr);
+}
+
+} // namespace
+
+// Write an old-style lambda taking an EventContext (without a reference)
+// as it will consume EventContext via std::move, it can only be the last
+// argument.
+template <typename ArgumentFunction,
+ typename ArgFunctionCheck = typename std::enable_if<
+ IsValidTraceLambda<ArgumentFunction>()>::type>
+PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(
+ EventContext event_ctx,
+ const ArgumentFunction& arg_function) {
+ arg_function(std::move(event_ctx));
+}
+
+// Forward-declare the specification for writing untyped arguments to ensure
+// that typed specification could recursively pick it up.
+template <typename ArgValue, typename... Args>
+PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(EventContext event_ctx,
+ const char* arg_name,
+ ArgValue&& arg_value,
+ Args&&... args);
+
+template <typename FieldMetadataType,
+ typename ArgValue,
+ typename... Args,
+ typename FieldMetadataTypeCheck = typename std::enable_if<
+ IsFieldMetadataType<FieldMetadataType>()>::type>
+PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(EventContext event_ctx,
+ FieldMetadataType field_name,
+ ArgValue&& arg_value,
+ Args&&... args);
+
+template <typename ArgumentFunction,
+ typename... Args,
+ typename ArgFunctionCheck = typename std::enable_if<
+ IsValidTraceLambdaTakingReference<ArgumentFunction>()>::type>
+PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(
+ EventContext event_ctx,
+ const ArgumentFunction& arg_function,
+ Args&&... args) {
+ // |arg_function| will capture EventContext by reference, so std::move isn't
+ // needed.
+ arg_function(event_ctx);
+
+ WriteTrackEventArgs(std::move(event_ctx), std::forward<Args>(args)...);
+}
+
+// Write one typed message and recursively write the rest of the arguments.
+template <typename FieldMetadataType,
+ typename ArgValue,
+ typename... Args,
+ typename FieldMetadataTypeCheck>
+PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(EventContext event_ctx,
+ FieldMetadataType field_name,
+ ArgValue&& arg_value,
+ Args&&... args) {
+ static_assert(std::is_base_of<protozero::proto_utils::FieldMetadataBase,
+ FieldMetadataType>::value,
+ "");
+ static_assert(
+ std::is_base_of<protos::pbzero::TrackEvent,
+ typename FieldMetadataType::message_type>::value,
+ "Only fields of TrackEvent (and TrackEvent's extensions) can "
+ "be passed to TRACE_EVENT");
+ auto track_event_proto = event_ctx.Wrap(
+ event_ctx.event<typename FieldMetadataType::message_type>());
+ WriteTracedProtoField(track_event_proto, field_name,
+ std::forward<ArgValue>(arg_value));
+ WriteTrackEventArgs(std::move(event_ctx), std::forward<Args>(args)...);
+}
+
+// Write one debug annotation and recursively write the rest of the arguments.
+template <typename ArgValue, typename... Args>
+PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(EventContext event_ctx,
+ const char* arg_name,
+ ArgValue&& arg_value,
+ Args&&... args) {
+ event_ctx.AddDebugAnnotation(arg_name, std::forward<ArgValue>(arg_value));
+ WriteTrackEventArgs(std::move(event_ctx), std::forward<Args>(args)...);
+}
+
+// Write one debug annotation and recursively write the rest of the arguments.
+template <typename ArgValue, typename... Args>
+PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(EventContext event_ctx,
+ DynamicString arg_name,
+ ArgValue&& arg_value,
+ Args&&... args) {
+ event_ctx.AddDebugAnnotation(arg_name, std::forward<ArgValue>(arg_value));
+ WriteTrackEventArgs(std::move(event_ctx), std::forward<Args>(args)...);
+}
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
+// gen_amalgamated begin header: include/perfetto/tracing/track_event_category_registry.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CATEGORY_REGISTRY_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CATEGORY_REGISTRY_H_
+
+// gen_amalgamated expanded: #include "perfetto/tracing/data_source.h"
+
+#include <stddef.h>
+
+#include <atomic>
+#include <utility>
+
+namespace perfetto {
+class DynamicCategory;
+
+// A compile-time representation of a track event category. See
+// PERFETTO_DEFINE_CATEGORIES for registering your own categories.
+struct PERFETTO_EXPORT_COMPONENT Category {
+ using Tags = std::array<const char*, 4>;
+
+ const char* const name = nullptr;
+ const char* const description = nullptr;
+ const Tags tags = {};
+
+ constexpr Category(const Category&) = default;
+ constexpr explicit Category(const char* name_)
+ : name(CheckIsValidCategory(name_)),
+ name_sizes_(ComputeNameSizes(name_)) {}
+
+ constexpr Category SetDescription(const char* description_) const {
+ return Category(name, description_, tags, name_sizes_);
+ }
+
+ template <typename... Args>
+ constexpr Category SetTags(Args&&... args) const {
+ return Category(name, description, {std::forward<Args>(args)...},
+ name_sizes_);
+ }
+
+ // A comma separated list of multiple categories to be used in a single trace
+ // point.
+ static constexpr Category Group(const char* names) {
+ return Category(names, AllowGroup{});
+ }
+
+ // Used for parsing dynamic category groups. Note that |name| and
+ // |DynamicCategory| must outlive the returned object because the category
+ // name isn't copied.
+ static Category FromDynamicCategory(const char* name);
+ static Category FromDynamicCategory(const DynamicCategory&);
+
+ constexpr bool IsGroup() const { return GetNameSize(1) > 0; }
+
+ // Returns the number of character in the category name. Not valid for
+ // category groups.
+ size_t name_size() const {
+ PERFETTO_DCHECK(!IsGroup());
+ return GetNameSize(0);
+ }
+
+ // Iterates over all the members of this category group, or just the name of
+ // the category itself if this isn't a category group. Return false from
+ // |callback| to stop iteration.
+ template <typename T>
+ void ForEachGroupMember(T callback) const {
+ const char* name_ptr = name;
+ size_t i = 0;
+ while (size_t name_size = GetNameSize(i++)) {
+ if (!callback(name_ptr, name_size))
+ break;
+ name_ptr += name_size + 1;
+ }
+ }
+
+ private:
+ static constexpr size_t kMaxGroupSize = 4;
+ using NameSizes = std::array<uint8_t, kMaxGroupSize>;
+
+ constexpr Category(const char* name_,
+ const char* description_,
+ Tags tags_,
+ NameSizes name_sizes)
+ : name(name_),
+ description(description_),
+ tags(tags_),
+ name_sizes_(name_sizes) {}
+
+ enum AllowGroup {};
+ constexpr Category(const char* name_, AllowGroup)
+ : name(CheckIsValidCategoryGroup(name_)),
+ name_sizes_(ComputeNameSizes(name_)) {}
+
+ constexpr size_t GetNameSize(size_t i) const {
+ return i < name_sizes_.size() ? name_sizes_[i] : 0;
+ }
+
+ static constexpr NameSizes ComputeNameSizes(const char* s) {
+ static_assert(kMaxGroupSize == 4, "Unexpected maximum category group size");
+ return NameSizes{{static_cast<uint8_t>(GetNthNameSize(0, s, s)),
+ static_cast<uint8_t>(GetNthNameSize(1, s, s)),
+ static_cast<uint8_t>(GetNthNameSize(2, s, s)),
+ static_cast<uint8_t>(GetNthNameSize(3, s, s))}};
+ }
+
+ static constexpr ptrdiff_t GetNthNameSize(int n,
+ const char* start,
+ const char* end,
+ int counter = 0) {
+ return (!*end || *end == ',')
+ ? ((!*end || counter == n)
+ ? (counter == n ? end - start : 0)
+ : GetNthNameSize(n, end + 1, end + 1, counter + 1))
+ : GetNthNameSize(n, start, end + 1, counter);
+ }
+
+ static constexpr const char* CheckIsValidCategory(const char* n) {
+ // We just replace invalid input with a nullptr here; it will trigger a
+ // static assert in TrackEventCategoryRegistry::ValidateCategories().
+ return GetNthNameSize(1, n, n) ? nullptr : n;
+ }
+
+ static constexpr const char* CheckIsValidCategoryGroup(const char* n) {
+ // Same as above: replace invalid input with nullptr.
+ return !GetNthNameSize(1, n, n) || GetNthNameSize(kMaxGroupSize, n, n)
+ ? nullptr
+ : n;
+ }
+
+ // An array of lengths of the different names associated with this category.
+ // If this category doesn't represent a group of multiple categories, only the
+ // first element is non-zero.
+ const NameSizes name_sizes_ = {};
+};
+
+// Dynamically constructed category names should marked as such through this
+// container type to make it less likely for trace points to accidentally start
+// using dynamic categories. Events with dynamic categories will always be
+// slightly more expensive than regular events, so use them sparingly.
+class PERFETTO_EXPORT_COMPONENT DynamicCategory final {
+ public:
+ explicit DynamicCategory(const std::string& name_) : name(name_) {}
+ explicit DynamicCategory(const char* name_) : name(name_) {}
+ DynamicCategory() {}
+ ~DynamicCategory() = default;
+
+ DynamicCategory(const DynamicCategory&) = default;
+ DynamicCategory& operator=(const DynamicCategory&) = delete;
+
+ DynamicCategory(DynamicCategory&&) = default;
+ DynamicCategory& operator=(DynamicCategory&&) = delete;
+
+ const std::string name;
+};
+
+namespace internal {
+
+constexpr const char* NullCategory(const char*) {
+ return nullptr;
+}
+
+perfetto::DynamicCategory NullCategory(const perfetto::DynamicCategory&);
+
+constexpr bool StringMatchesPrefix(const char* str, const char* prefix) {
+ return !*str ? !*prefix
+ : !*prefix ? true
+ : *str != *prefix
+ ? false
+ : StringMatchesPrefix(str + 1, prefix + 1);
+}
+
+constexpr bool IsStringInPrefixList(const char*) {
+ return false;
+}
+
+template <typename... Args>
+constexpr bool IsStringInPrefixList(const char* str,
+ const char* prefix,
+ Args... args) {
+ return StringMatchesPrefix(str, prefix) ||
+ IsStringInPrefixList(str, std::forward<Args>(args)...);
+}
+
+// Holds all the registered categories for one category namespace. See
+// PERFETTO_DEFINE_CATEGORIES for building the registry.
+class PERFETTO_EXPORT_COMPONENT TrackEventCategoryRegistry {
+ public:
+ constexpr TrackEventCategoryRegistry(size_t category_count,
+ const Category* categories,
+ std::atomic<uint8_t>* state_storage)
+ : categories_(categories),
+ category_count_(category_count),
+ state_storage_(state_storage) {
+ static_assert(
+ sizeof(state_storage[0].load()) * 8 >= kMaxDataSourceInstances,
+ "The category state must have enough bits for all possible data source "
+ "instances");
+ }
+
+ size_t category_count() const { return category_count_; }
+
+ // Returns a category based on its index.
+ const Category* GetCategory(size_t index) const {
+ PERFETTO_DCHECK(index < category_count_);
+ return &categories_[index];
+ }
+
+ // Turn tracing on or off for the given category in a track event data source
+ // instance.
+ void EnableCategoryForInstance(size_t category_index,
+ uint32_t instance_index) const;
+ void DisableCategoryForInstance(size_t category_index,
+ uint32_t instance_index) const;
+
+ constexpr std::atomic<uint8_t>* GetCategoryState(
+ size_t category_index) const {
+ return &state_storage_[category_index];
+ }
+
+ // --------------------------------------------------------------------------
+ // Trace point support
+ // --------------------------------------------------------------------------
+ //
+ // (The following methods are used by the track event trace point
+ // implementation and typically don't need to be called by other code.)
+
+ // At compile time, turn a category name into an index into the registry.
+ // Returns kInvalidCategoryIndex if the category was not found, or
+ // kDynamicCategoryIndex if |is_dynamic| is true or a DynamicCategory was
+ // passed in.
+ static constexpr size_t kInvalidCategoryIndex = static_cast<size_t>(-1);
+ static constexpr size_t kDynamicCategoryIndex = static_cast<size_t>(-2);
+ constexpr size_t Find(const char* name, bool is_dynamic) const {
+ return CheckIsValidCategoryIndex(FindImpl(name, is_dynamic));
+ }
+
+ constexpr size_t Find(const DynamicCategory&, bool) const {
+ return kDynamicCategoryIndex;
+ }
+
+ constexpr bool ValidateCategories(size_t index = 0) const {
+ return (index == category_count_)
+ ? true
+ : IsValidCategoryName(categories_[index].name)
+ ? ValidateCategories(index + 1)
+ : false;
+ }
+
+ private:
+ // TODO(skyostil): Make the compile-time routines nicer with C++14.
+ constexpr size_t FindImpl(const char* name,
+ bool is_dynamic,
+ size_t index = 0) const {
+ return is_dynamic ? kDynamicCategoryIndex
+ : (index == category_count_)
+ ? kInvalidCategoryIndex
+ : StringEq(categories_[index].name, name)
+ ? index
+ : FindImpl(name, false, index + 1);
+ }
+
+ // A compile time helper for checking that a category index is valid.
+ static constexpr size_t CheckIsValidCategoryIndex(size_t index) {
+ // Relies on PERFETTO_CHECK() (and the surrounding lambda) being a
+ // non-constexpr function, which will fail the build if the given |index| is
+ // invalid. The funny formatting here is so that clang shows the comment
+ // below as part of the error message.
+ // clang-format off
+ return index != kInvalidCategoryIndex ? index : \
+ /* Invalid category -- add it to PERFETTO_DEFINE_CATEGORIES(). */ [] {
+ PERFETTO_CHECK(
+ false &&
+ "A track event used an unknown category. Please add it to "
+ "PERFETTO_DEFINE_CATEGORIES().");
+ return kInvalidCategoryIndex;
+ }();
+ // clang-format on
+ }
+
+ static constexpr bool IsValidCategoryName(const char* name) {
+ return (!name || *name == '\"' || *name == '*' || *name == ' ')
+ ? false
+ : *name ? IsValidCategoryName(name + 1) : true;
+ }
+
+ static constexpr bool StringEq(const char* a, const char* b) {
+ return *a != *b ? false
+ : (!*a || !*b) ? (*a == *b) : StringEq(a + 1, b + 1);
+ }
+
+ const Category* const categories_;
+ const size_t category_count_;
+ std::atomic<uint8_t>* const state_storage_;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CATEGORY_REGISTRY_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/track_event/track_event_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TrackEventConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TrackEventConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDisabledCategoriesFieldNumber = 1,
+ kEnabledCategoriesFieldNumber = 2,
+ kDisabledTagsFieldNumber = 3,
+ kEnabledTagsFieldNumber = 4,
+ kDisableIncrementalTimestampsFieldNumber = 5,
+ kTimestampUnitMultiplierFieldNumber = 6,
+ kFilterDebugAnnotationsFieldNumber = 7,
+ kEnableThreadTimeSamplingFieldNumber = 8,
+ kFilterDynamicEventNamesFieldNumber = 9,
+ };
+
+ TrackEventConfig();
+ ~TrackEventConfig() override;
+ TrackEventConfig(TrackEventConfig&&) noexcept;
+ TrackEventConfig& operator=(TrackEventConfig&&);
+ TrackEventConfig(const TrackEventConfig&);
+ TrackEventConfig& operator=(const TrackEventConfig&);
+ bool operator==(const TrackEventConfig&) const;
+ bool operator!=(const TrackEventConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<std::string>& disabled_categories() const { return disabled_categories_; }
+ std::vector<std::string>* mutable_disabled_categories() { return &disabled_categories_; }
+ int disabled_categories_size() const { return static_cast<int>(disabled_categories_.size()); }
+ void clear_disabled_categories() { disabled_categories_.clear(); }
+ void add_disabled_categories(std::string value) { disabled_categories_.emplace_back(value); }
+ std::string* add_disabled_categories() { disabled_categories_.emplace_back(); return &disabled_categories_.back(); }
+
+ const std::vector<std::string>& enabled_categories() const { return enabled_categories_; }
+ std::vector<std::string>* mutable_enabled_categories() { return &enabled_categories_; }
+ int enabled_categories_size() const { return static_cast<int>(enabled_categories_.size()); }
+ void clear_enabled_categories() { enabled_categories_.clear(); }
+ void add_enabled_categories(std::string value) { enabled_categories_.emplace_back(value); }
+ std::string* add_enabled_categories() { enabled_categories_.emplace_back(); return &enabled_categories_.back(); }
+
+ const std::vector<std::string>& disabled_tags() const { return disabled_tags_; }
+ std::vector<std::string>* mutable_disabled_tags() { return &disabled_tags_; }
+ int disabled_tags_size() const { return static_cast<int>(disabled_tags_.size()); }
+ void clear_disabled_tags() { disabled_tags_.clear(); }
+ void add_disabled_tags(std::string value) { disabled_tags_.emplace_back(value); }
+ std::string* add_disabled_tags() { disabled_tags_.emplace_back(); return &disabled_tags_.back(); }
+
+ const std::vector<std::string>& enabled_tags() const { return enabled_tags_; }
+ std::vector<std::string>* mutable_enabled_tags() { return &enabled_tags_; }
+ int enabled_tags_size() const { return static_cast<int>(enabled_tags_.size()); }
+ void clear_enabled_tags() { enabled_tags_.clear(); }
+ void add_enabled_tags(std::string value) { enabled_tags_.emplace_back(value); }
+ std::string* add_enabled_tags() { enabled_tags_.emplace_back(); return &enabled_tags_.back(); }
+
+ bool has_disable_incremental_timestamps() const { return _has_field_[5]; }
+ bool disable_incremental_timestamps() const { return disable_incremental_timestamps_; }
+ void set_disable_incremental_timestamps(bool value) { disable_incremental_timestamps_ = value; _has_field_.set(5); }
+
+ bool has_timestamp_unit_multiplier() const { return _has_field_[6]; }
+ uint64_t timestamp_unit_multiplier() const { return timestamp_unit_multiplier_; }
+ void set_timestamp_unit_multiplier(uint64_t value) { timestamp_unit_multiplier_ = value; _has_field_.set(6); }
+
+ bool has_filter_debug_annotations() const { return _has_field_[7]; }
+ bool filter_debug_annotations() const { return filter_debug_annotations_; }
+ void set_filter_debug_annotations(bool value) { filter_debug_annotations_ = value; _has_field_.set(7); }
+
+ bool has_enable_thread_time_sampling() const { return _has_field_[8]; }
+ bool enable_thread_time_sampling() const { return enable_thread_time_sampling_; }
+ void set_enable_thread_time_sampling(bool value) { enable_thread_time_sampling_ = value; _has_field_.set(8); }
+
+ bool has_filter_dynamic_event_names() const { return _has_field_[9]; }
+ bool filter_dynamic_event_names() const { return filter_dynamic_event_names_; }
+ void set_filter_dynamic_event_names(bool value) { filter_dynamic_event_names_ = value; _has_field_.set(9); }
+
+ private:
+ std::vector<std::string> disabled_categories_;
+ std::vector<std::string> enabled_categories_;
+ std::vector<std::string> disabled_tags_;
+ std::vector<std::string> enabled_tags_;
+ bool disable_incremental_timestamps_{};
+ uint64_t timestamp_unit_multiplier_{};
+ bool filter_debug_annotations_{};
+ bool enable_thread_time_sampling_{};
+ bool filter_dynamic_event_names_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<10> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_PROTO_CPP_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_DATA_SOURCE_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_DATA_SOURCE_H_
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/base/template_util.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/data_source.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/event_context.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_legacy.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/write_track_event_args.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_category_registry.h"
+// gen_amalgamated expanded: #include "protos/perfetto/common/builtin_clock.pbzero.h"
+// gen_amalgamated expanded: #include "protos/perfetto/config/track_event/track_event_config.gen.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+#include <type_traits>
+
+namespace perfetto {
+
+namespace {
+
+class StopArgsImpl : public DataSourceBase::StopArgs {
+ public:
+ // HandleAsynchronously() can optionally be called to defer the tracing
+ // session stop and write track events just before stopping. This function
+ // returns a closure that must be invoked after the last track events have
+ // been emitted. The caller also needs to explicitly call
+ // TrackEvent::Flush() because no other implicit flushes will happen after
+ // the stop signal.
+ // See the comment in include/perfetto/tracing/data_source.h for more info.
+ std::function<void()> HandleStopAsynchronously() const override {
+ auto closure = std::move(async_stop_closure);
+ async_stop_closure = std::function<void()>();
+ return closure;
+ }
+
+ mutable std::function<void()> async_stop_closure;
+};
+
+} // namespace
+
+// A function for converting an abstract timestamp into a
+// perfetto::TraceTimestamp struct. By specialising this template and defining
+// static ConvertTimestampToTraceTimeNs function in it the user can register
+// additional timestamp types. The return value should specify the
+// clock domain used by the timestamp as well as its value.
+//
+// The supported clock domains are the ones described in
+// perfetto.protos.ClockSnapshot. However, custom clock IDs (>=64) are
+// reserved for internal use by the SDK for the time being.
+// The timestamp value should be in nanoseconds regardless of the clock domain.
+template <typename T>
+struct TraceTimestampTraits;
+
+// A pass-through implementation for raw uint64_t nanosecond timestamps.
+template <>
+struct TraceTimestampTraits<uint64_t> {
+ static inline TraceTimestamp ConvertTimestampToTraceTimeNs(
+ const uint64_t& timestamp) {
+ return {static_cast<uint32_t>(internal::TrackEventInternal::GetClockId()), timestamp};
+ }
+};
+
+// A pass-through implementation for the trace timestamp structure.
+template <>
+struct TraceTimestampTraits<TraceTimestamp> {
+ static inline TraceTimestamp ConvertTimestampToTraceTimeNs(
+ const TraceTimestamp& timestamp) {
+ return timestamp;
+ }
+};
+
+namespace internal {
+namespace {
+
+// Checks if |T| is a valid track.
+template <typename T>
+static constexpr bool IsValidTrack() {
+ return std::is_convertible<T, Track>::value;
+}
+
+// Checks if |T| is a valid non-counter track.
+template <typename T>
+static constexpr bool IsValidNormalTrack() {
+ return std::is_convertible<T, Track>::value &&
+ !std::is_convertible<T, CounterTrack>::value;
+}
+
+// Because the user can use arbitrary timestamp types, we can't compare against
+// any known base type here. Instead, we check that a track or a trace lambda
+// isn't being interpreted as a timestamp.
+template <typename T,
+ typename CanBeConvertedToNsCheck = decltype(
+ ::perfetto::TraceTimestampTraits<typename base::remove_cvref_t<
+ T>>::ConvertTimestampToTraceTimeNs(std::declval<T>())),
+ typename NotTrackCheck =
+ typename std::enable_if<!IsValidNormalTrack<T>()>::type,
+ typename NotLambdaCheck =
+ typename std::enable_if<!IsValidTraceLambda<T>()>::type>
+static constexpr bool IsValidTimestamp() {
+ return true;
+}
+
+// Taken from C++17
+template <typename...>
+using void_t = void;
+
+// Returns true iff `GetStaticString(T)` is defined OR T == DynamicString.
+template <typename T, typename = void>
+struct IsValidEventNameType
+ : std::is_same<perfetto::DynamicString, typename std::decay<T>::type> {};
+
+template <typename T>
+struct IsValidEventNameType<
+ T,
+ void_t<decltype(GetStaticString(std::declval<T>()))>> : std::true_type {};
+
+template <typename T>
+inline void ValidateEventNameType() {
+ static_assert(
+ IsValidEventNameType<T>::value,
+ "Event names must be static strings. To use dynamic event names, see "
+ "https://perfetto.dev/docs/instrumentation/"
+ "track-events#dynamic-event-names");
+}
+
+inline bool UnorderedEqual(std::vector<std::string> vec1,
+ std::vector<std::string> vec2) {
+ std::sort(vec1.begin(), vec1.end());
+ vec1.erase(std::unique(vec1.begin(), vec1.end()), vec1.end());
+ std::sort(vec2.begin(), vec2.end());
+ vec2.erase(std::unique(vec2.begin(), vec2.end()), vec2.end());
+ return vec1 == vec2;
+}
+
+} // namespace
+
+inline ::perfetto::DynamicString DecayEventNameType(
+ ::perfetto::DynamicString name) {
+ return name;
+}
+
+inline ::perfetto::StaticString DecayEventNameType(
+ ::perfetto::StaticString name) {
+ return name;
+}
+
+// Convert all static strings of different length to StaticString to avoid
+// unnecessary template instantiations.
+inline ::perfetto::StaticString DecayEventNameType(const char* name) {
+ return ::perfetto::StaticString{name};
+}
+
+// Traits for dynamic categories.
+template <typename CategoryType>
+struct CategoryTraits {
+ static constexpr bool kIsDynamic = true;
+ static constexpr const Category* GetStaticCategory(
+ const TrackEventCategoryRegistry*,
+ const CategoryType&) {
+ return nullptr;
+ }
+ static size_t GetStaticIndex(const CategoryType&) {
+ PERFETTO_DCHECK(false); // Not reached.
+ return TrackEventCategoryRegistry::kDynamicCategoryIndex;
+ }
+ static DynamicCategory GetDynamicCategory(const CategoryType& category) {
+ return DynamicCategory{category};
+ }
+};
+
+// Traits for static categories.
+template <>
+struct CategoryTraits<size_t> {
+ static constexpr bool kIsDynamic = false;
+ static const Category* GetStaticCategory(
+ const TrackEventCategoryRegistry* registry,
+ size_t category_index) {
+ return registry->GetCategory(category_index);
+ }
+ static constexpr size_t GetStaticIndex(size_t category_index) {
+ return category_index;
+ }
+ static DynamicCategory GetDynamicCategory(size_t) {
+ PERFETTO_DCHECK(false); // Not reached.
+ return DynamicCategory();
+ }
+};
+
+struct TrackEventDataSourceTraits : public perfetto::DefaultDataSourceTraits {
+ using IncrementalStateType = TrackEventIncrementalState;
+ using TlsStateType = TrackEventTlsState;
+
+ // Use a one shared TLS slot so that all track event data sources write into
+ // the same sequence and share interning dictionaries.
+ static DataSourceThreadLocalState* GetDataSourceTLS(DataSourceStaticState*,
+ TracingTLS* root_tls) {
+ return &root_tls->track_event_tls;
+ }
+};
+
+// A generic track event data source which is instantiated once per track event
+// category namespace.
+template <typename DerivedDataSource,
+ const TrackEventCategoryRegistry* Registry>
+class TrackEventDataSource
+ : public DataSource<DerivedDataSource, TrackEventDataSourceTraits> {
+ using Base = DataSource<DerivedDataSource, TrackEventDataSourceTraits>;
+
+ public:
+ static constexpr bool kRequiresCallbacksUnderLock = false;
+
+ // Add or remove a session observer for this track event data source. The
+ // observer will be notified about started and stopped tracing sessions.
+ // Returns |true| if the observer was successfully added (i.e., the maximum
+ // number of observers wasn't exceeded).
+ static bool AddSessionObserver(TrackEventSessionObserver* observer) {
+ return TrackEventInternal::AddSessionObserver(*Registry, observer);
+ }
+
+ static void RemoveSessionObserver(TrackEventSessionObserver* observer) {
+ TrackEventInternal::RemoveSessionObserver(*Registry, observer);
+ }
+
+ // DataSource implementation.
+ void OnSetup(const DataSourceBase::SetupArgs& args) override {
+ auto config_raw = args.config->track_event_config_raw();
+ bool ok = config_.ParseFromArray(config_raw.data(), config_raw.size());
+ PERFETTO_DCHECK(ok);
+ TrackEventInternal::EnableTracing(*Registry, config_, args);
+ }
+
+ void OnStart(const DataSourceBase::StartArgs& args) override {
+ TrackEventInternal::OnStart(*Registry, args);
+ }
+
+ void OnStop(const DataSourceBase::StopArgs& args) override {
+ auto outer_stop_closure = args.HandleStopAsynchronously();
+ StopArgsImpl inner_stop_args{};
+ uint32_t internal_instance_index = args.internal_instance_index;
+ inner_stop_args.internal_instance_index = internal_instance_index;
+ inner_stop_args.async_stop_closure = [internal_instance_index,
+ outer_stop_closure] {
+ TrackEventInternal::DisableTracing(*Registry, internal_instance_index);
+ outer_stop_closure();
+ };
+
+ TrackEventInternal::OnStop(*Registry, inner_stop_args);
+
+ // If inner_stop_args.HandleStopAsynchronously() hasn't been called,
+ // run the async closure here.
+ if (inner_stop_args.async_stop_closure)
+ std::move(inner_stop_args.async_stop_closure)();
+ }
+
+ void WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs& args) override {
+ TrackEventInternal::WillClearIncrementalState(*Registry, args);
+ }
+
+ // In Chrome, startup sessions are propagated from the browser process to
+ // child processes using command-line flags. Command-line flags can only
+ // convey the category filter and privacy settings, so we use only those
+ // to determine which startup sessions to adopt.
+ // TODO(khokhlov): After Chrome is able to propagate the entire config to the
+ // child process, we can make this comparison more strict by only clearing
+ // selected fields and comparing everything else. One specific thing to keep
+ // in mind is to clear the |convert_to_legacy_json| field, because Telemetry
+ // initiates tracing with proto format, but in some cases adopts the tracing
+ // session later via devtools which expect json format.
+ bool CanAdoptStartupSession(const DataSourceConfig& startup_config,
+ const DataSourceConfig& service_config) override {
+ if (startup_config.track_event_config_raw().empty() ||
+ service_config.track_event_config_raw().empty()) {
+ return false;
+ }
+
+ protos::gen::TrackEventConfig startup_te_cfg;
+ startup_te_cfg.ParseFromString(startup_config.track_event_config_raw());
+ protos::gen::TrackEventConfig service_te_cfg;
+ service_te_cfg.ParseFromString(service_config.track_event_config_raw());
+
+ if (!UnorderedEqual(startup_te_cfg.enabled_categories(),
+ service_te_cfg.enabled_categories())) {
+ return false;
+ }
+ if (!UnorderedEqual(startup_te_cfg.disabled_categories(),
+ service_te_cfg.disabled_categories())) {
+ return false;
+ }
+ if (!UnorderedEqual(startup_te_cfg.enabled_tags(),
+ service_te_cfg.enabled_tags())) {
+ return false;
+ }
+ if (!UnorderedEqual(startup_te_cfg.disabled_tags(),
+ service_te_cfg.disabled_tags())) {
+ return false;
+ }
+ if (startup_te_cfg.filter_debug_annotations() !=
+ service_te_cfg.filter_debug_annotations()) {
+ return false;
+ }
+ if (startup_te_cfg.filter_dynamic_event_names() !=
+ service_te_cfg.filter_dynamic_event_names()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ static void Flush() {
+ Base::template Trace([](typename Base::TraceContext ctx) { ctx.Flush(); });
+ }
+
+ // Determine if *any* tracing category is enabled.
+ static bool IsEnabled() {
+ bool enabled = false;
+ Base::template CallIfEnabled(
+ [&](uint32_t /*instances*/) { enabled = true; });
+ return enabled;
+ }
+
+ // Determine if tracing for the given static category is enabled.
+ static bool IsCategoryEnabled(size_t category_index) {
+ return Registry->GetCategoryState(category_index)
+ ->load(std::memory_order_relaxed);
+ }
+
+ // Determine if tracing for the given dynamic category is enabled.
+ static bool IsDynamicCategoryEnabled(
+ const DynamicCategory& dynamic_category) {
+ bool enabled = false;
+ Base::template Trace([&](typename Base::TraceContext ctx) {
+ enabled = enabled || IsDynamicCategoryEnabled(&ctx, dynamic_category);
+ });
+ return enabled;
+ }
+
+ // This is the inlined entrypoint for all track event trace points. It tries
+ // to be as lightweight as possible in terms of instructions and aims to
+ // compile down to an unlikely conditional jump to the actual trace writing
+ // function.
+ template <typename Callback>
+ static void CallIfCategoryEnabled(size_t category_index,
+ Callback callback) PERFETTO_ALWAYS_INLINE {
+ Base::template CallIfEnabled<CategoryTracePointTraits>(
+ [&callback](uint32_t instances) { callback(instances); },
+ {category_index});
+ }
+
+ // The following methods forward all arguments to TraceForCategoryBody
+ // while casting string constants to const char* and integer arguments to
+ // int64_t, uint64_t or bool.
+ template <typename CategoryType,
+ typename EventNameType,
+ typename... Arguments>
+ static void TraceForCategory(uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ Arguments&&... args) PERFETTO_ALWAYS_INLINE {
+ TraceForCategoryBody(instances, DecayStrType(category), DecayStrType(name),
+ type, DecayArgType(args)...);
+ }
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryLegacy(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ Arguments&&... args) PERFETTO_ALWAYS_INLINE {
+ TraceForCategoryLegacyBody(instances, DecayStrType(category),
+ DecayStrType(event_name), type, track, phase,
+ flags, DecayArgType(args)...);
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryLegacy(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_ALWAYS_INLINE {
+ TraceForCategoryLegacyBody(instances, DecayStrType(category),
+ DecayStrType(event_name), type, track, phase,
+ flags, timestamp, DecayArgType(args)...);
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename ThreadIdType,
+ typename LegacyIdType,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryLegacyWithId(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ ThreadIdType thread_id,
+ LegacyIdType legacy_id,
+ Arguments&&... args) PERFETTO_ALWAYS_INLINE {
+ TraceForCategoryLegacyWithIdBody(
+ instances, DecayStrType(category), DecayStrType(event_name), type,
+ track, phase, flags, thread_id, legacy_id, DecayArgType(args)...);
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename ThreadIdType,
+ typename LegacyIdType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryLegacyWithId(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ ThreadIdType thread_id,
+ LegacyIdType legacy_id,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_ALWAYS_INLINE {
+ TraceForCategoryLegacyWithIdBody(instances, DecayStrType(category),
+ DecayStrType(event_name), type, track,
+ phase, flags, thread_id, legacy_id,
+ timestamp, DecayArgType(args)...);
+ }
+#endif
+
+ // Initialize the track event library. Should be called before tracing is
+ // enabled.
+ static bool Register() {
+ // Registration is performed out-of-line so users don't need to depend on
+ // DataSourceDescriptor C++ bindings.
+ return TrackEventInternal::Initialize(
+ *Registry,
+ [](const DataSourceDescriptor& dsd) { return Base::Register(dsd); });
+ }
+
+ // Record metadata about different types of timeline tracks. See Track.
+ static void SetTrackDescriptor(const Track& track,
+ const protos::gen::TrackDescriptor& desc) {
+ PERFETTO_DCHECK(track.uuid == desc.uuid());
+ TrackRegistry::Get()->UpdateTrack(track, desc.SerializeAsString());
+ Base::template Trace([&](typename Base::TraceContext ctx) {
+ TrackEventInternal::WriteTrackDescriptor(
+ track, ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
+ *ctx.GetCustomTlsState(), TrackEventInternal::GetTraceTime());
+ });
+ }
+
+ // DEPRECATED. Only kept for backwards compatibility.
+ static void SetTrackDescriptor(
+ const Track& track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback) {
+ SetTrackDescriptorImpl(track, std::move(callback));
+ }
+
+ // DEPRECATED. Only kept for backwards compatibility.
+ static void SetProcessDescriptor(
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback,
+ const ProcessTrack& track = ProcessTrack::Current()) {
+ SetTrackDescriptorImpl(std::move(track), std::move(callback));
+ }
+
+ // DEPRECATED. Only kept for backwards compatibility.
+ static void SetThreadDescriptor(
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback,
+ const ThreadTrack& track = ThreadTrack::Current()) {
+ SetTrackDescriptorImpl(std::move(track), std::move(callback));
+ }
+
+ static void EraseTrackDescriptor(const Track& track) {
+ TrackRegistry::Get()->EraseTrack(track);
+ }
+
+ // Returns the current trace timestamp in nanoseconds. Note the returned
+ // timebase may vary depending on the platform, but will always match the
+ // timestamps recorded by track events (see GetTraceClockId).
+ static uint64_t GetTraceTimeNs() { return TrackEventInternal::GetTimeNs(); }
+
+ // Returns the type of clock used by GetTraceTimeNs().
+ static constexpr protos::pbzero::BuiltinClock GetTraceClockId() {
+ return TrackEventInternal::GetClockId();
+ }
+
+ const protos::gen::TrackEventConfig& GetConfig() const { return config_; }
+
+ private:
+ // The DecayStrType method is used to avoid unnecessary instantiations of
+ // templates on string constants of different sizes. Without it, strings
+ // of different lengths have different types: char[10], char[15] etc.
+ // DecayStrType forwards all types of arguments as is, with the exception
+ // of string constants which are all cast to const char*. This allows to
+ // avoid extra instantiations of TraceForCategory templates.
+ template <typename T>
+ static T&& DecayStrType(T&& t) {
+ return std::forward<T>(t);
+ }
+
+ static const char* DecayStrType(const char* t) { return t; }
+
+ // The DecayArgType method is used to avoid unnecessary instantiations of
+ // templates on:
+ // * string constants of different sizes.
+ // * primitive of different constness (or references).
+ // This avoids extra instantiations of TraceForCategory templates.
+ template <typename T>
+ static T&& DecayArgType(T&& t) {
+ return std::forward<T>(t);
+ }
+
+ static const char* DecayArgType(const char* s) { return s; }
+ static uint64_t DecayArgType(uint64_t u) { return u; }
+ static uint32_t DecayArgType(uint32_t u) { return u; }
+ static uint16_t DecayArgType(uint16_t u) { return u; }
+ static uint8_t DecayArgType(uint8_t u) { return u; }
+ static int64_t DecayArgType(int64_t i) { return i; }
+ static int32_t DecayArgType(int32_t i) { return i; }
+ static int16_t DecayArgType(int16_t i) { return i; }
+ static int8_t DecayArgType(int8_t i) { return i; }
+ static bool DecayArgType(bool b) { return b; }
+ static float DecayArgType(float f) { return f; }
+ static double DecayArgType(double f) { return f; }
+
+ // Once we've determined tracing to be enabled for this category, actually
+ // write a trace event onto this thread's default track. Outlined to avoid
+ // bloating code (mostly stack depth) at the actual trace point.
+ //
+ // The following combination of parameters is supported (in the given order):
+ // - Zero or one track,
+ // - Zero or one custom timestamp,
+ // - Arbitrary number of debug annotations.
+ // - Zero or one lambda.
+
+ // Trace point which does not take a track or timestamp.
+ template <typename CategoryType,
+ typename EventNameType,
+ typename... Arguments>
+ static void TraceForCategoryBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImplNoTimestamp(instances, category, event_name, type,
+ TrackEventInternal::kDefaultTrack,
+ std::forward<Arguments>(args)...);
+ }
+
+ // Trace point which takes a track, but not timestamp.
+ // NOTE: Here track should be captured using universal reference (TrackType&&)
+ // instead of const TrackType& to ensure that the proper overload is selected
+ // (otherwise the compiler will fail to disambiguate between adding const& and
+ // parsing track as a part of Arguments...).
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImplNoTimestamp(instances, category, event_name, type,
+ std::forward<TrackType>(track),
+ std::forward<Arguments>(args)...);
+ }
+
+ // Trace point which takes a timestamp, but not track.
+ template <typename CategoryType,
+ typename EventNameType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(instances, category, event_name, type,
+ TrackEventInternal::kDefaultTrack,
+ std::forward<TimestampType>(timestamp),
+ std::forward<Arguments>(args)...);
+ }
+
+ // Trace point which takes a timestamp and a track.
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(instances, category, event_name, type,
+ std::forward<TrackType>(track),
+ std::forward<TimestampType>(timestamp),
+ std::forward<Arguments>(args)...);
+ }
+
+ // Trace point with with a counter sample.
+ template <typename CategoryType, typename EventNameType, typename ValueType>
+ static void TraceForCategoryBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType&,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ CounterTrack track,
+ ValueType value) PERFETTO_ALWAYS_INLINE {
+ PERFETTO_DCHECK(type == perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER);
+ TraceForCategory(instances, category, /*name=*/nullptr, type, track,
+ TrackEventInternal::GetTraceTime(), value);
+ }
+
+ // Trace point with with a timestamp and a counter sample.
+ template <typename CategoryType,
+ typename EventNameType,
+ typename TimestampType = uint64_t,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type,
+ typename ValueType>
+ static void TraceForCategoryBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType&,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ CounterTrack track,
+ TimestampType timestamp,
+ ValueType value) PERFETTO_NO_INLINE {
+ PERFETTO_DCHECK(type == perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER);
+ TraceForCategoryImpl(
+ instances, category, /*name=*/nullptr, type, track, timestamp,
+ [&](EventContext event_ctx) {
+ if (std::is_integral<ValueType>::value) {
+ int64_t value_int64 = static_cast<int64_t>(value);
+ if (track.is_incremental()) {
+ TrackEventIncrementalState* incr_state =
+ event_ctx.GetIncrementalState();
+ PERFETTO_DCHECK(incr_state != nullptr);
+ auto prv_value =
+ incr_state->last_counter_value_per_track[track.uuid];
+ event_ctx.event()->set_counter_value(value_int64 - prv_value);
+ prv_value = value_int64;
+ incr_state->last_counter_value_per_track[track.uuid] = prv_value;
+ } else {
+ event_ctx.event()->set_counter_value(value_int64);
+ }
+ } else {
+ event_ctx.event()->set_double_counter_value(
+ static_cast<double>(value));
+ }
+ });
+ }
+
+// Additional trace points used in legacy macros.
+// It's possible to implement legacy macros using a common TraceForCategory,
+// by supplying a lambda that sets all necessary legacy fields. But this
+// results in a binary size bloat because every trace point generates its own
+// template instantiation with its own lambda. ICF can't eliminate those as
+// each lambda captures different variables and so the code is not completely
+// identical.
+// What we do instead is define additional TraceForCategoryLegacy templates
+// that take legacy arguments directly. Their instantiations can have the same
+// binary code for at least some macro invocations and so can be successfully
+// folded by the linker.
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryLegacyBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImplNoTimestamp(
+ instances, category, event_name, type, track,
+ [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags,
+ args...);
+ });
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryLegacyBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(
+ instances, category, event_name, type, track, timestamp,
+ [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags,
+ args...);
+ });
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename ThreadIdType,
+ typename LegacyIdType,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryLegacyWithIdBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ ThreadIdType thread_id,
+ LegacyIdType legacy_id,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImplNoTimestamp(
+ instances, category, event_name, type, track,
+ [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ ::perfetto::internal::LegacyTraceId trace_id{legacy_id};
+ TrackEventLegacy::WriteLegacyEventWithIdAndTid(
+ std::move(ctx), phase, flags, trace_id, thread_id, args...);
+ });
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename ThreadIdType,
+ typename LegacyIdType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryLegacyWithIdBody(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ ThreadIdType thread_id,
+ LegacyIdType legacy_id,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(
+ instances, category, event_name, type, track, timestamp,
+ [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ ::perfetto::internal::LegacyTraceId trace_id{legacy_id};
+ TrackEventLegacy::WriteLegacyEventWithIdAndTid(
+ std::move(ctx), phase, flags, trace_id, thread_id, args...);
+ });
+ }
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+ // Each category has its own enabled/disabled state, stored in the category
+ // registry.
+ struct CategoryTracePointTraits {
+ // Each trace point with a static category has an associated category index.
+ struct TracePointData {
+ size_t category_index;
+ };
+ // Called to get the enabled state bitmap of a given category.
+ // |data| is the trace point data structure given to
+ // DataSource::TraceWithInstances.
+ static constexpr std::atomic<uint8_t>* GetActiveInstances(
+ TracePointData data) {
+ return Registry->GetCategoryState(data.category_index);
+ }
+ };
+
+ template <typename CategoryType,
+ typename EventNameType,
+ typename TrackType = Track,
+ typename TrackTypeCheck =
+ typename std::enable_if<IsValidTrack<TrackType>()>::type>
+ static perfetto::EventContext WriteTrackEventImpl(
+ typename Base::TraceContext& ctx,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
+ const TraceTimestamp& trace_timestamp) PERFETTO_ALWAYS_INLINE {
+ using CatTraits = CategoryTraits<CategoryType>;
+ const Category* static_category =
+ CatTraits::GetStaticCategory(Registry, category);
+
+ TrackEventTlsState& tls_state = *ctx.GetCustomTlsState();
+ TraceWriterBase* trace_writer = ctx.tls_inst_->trace_writer.get();
+ // Make sure incremental state is valid.
+ TrackEventIncrementalState* incr_state = ctx.GetIncrementalState();
+ TrackEventInternal::ResetIncrementalStateIfRequired(
+ trace_writer, incr_state, tls_state, trace_timestamp);
+
+ // Write the track descriptor before any event on the track.
+ if (track) {
+ TrackEventInternal::WriteTrackDescriptorIfNeeded(
+ track, trace_writer, incr_state, tls_state, trace_timestamp);
+ }
+
+ // Write the event itself.
+ bool on_current_thread_track =
+ (&track == &TrackEventInternal::kDefaultTrack);
+ auto event_ctx = TrackEventInternal::WriteEvent(
+ trace_writer, incr_state, tls_state, static_category, type,
+ trace_timestamp, on_current_thread_track);
+ // event name should be emitted with `TRACE_EVENT_BEGIN` macros
+ // but not with `TRACE_EVENT_END`.
+ if (type != protos::pbzero::TrackEvent::TYPE_SLICE_END) {
+ TrackEventInternal::WriteEventName(event_name, event_ctx, tls_state);
+ }
+ // Write dynamic categories (except for events that don't require
+ // categories). For counter events, the counter name (and optional
+ // category) is stored as part of the track descriptor instead being
+ // recorded with individual events.
+ if (CatTraits::kIsDynamic &&
+ type != protos::pbzero::TrackEvent::TYPE_SLICE_END &&
+ type != protos::pbzero::TrackEvent::TYPE_COUNTER) {
+ DynamicCategory dynamic_category =
+ CatTraits::GetDynamicCategory(category);
+ Category cat = Category::FromDynamicCategory(dynamic_category);
+ cat.ForEachGroupMember([&](const char* member_name, size_t name_size) {
+ event_ctx.event()->add_categories(member_name, name_size);
+ return true;
+ });
+ }
+ if (type == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED) {
+ // Explicitly clear the track, so that the event is not associated
+ // with the default track, but instead uses the legacy mechanism
+ // based on the phase and pid/tid override.
+ event_ctx.event()->set_track_uuid(0);
+ } else if (!on_current_thread_track) {
+ // We emit these events using TrackDescriptors, and we cannot emit
+ // events on behalf of other processes using the TrackDescriptor
+ // format. Chrome is the only user of events with explicit process
+ // ids and currently only Chrome emits PHASE_MEMORY_DUMP events
+ // with an explicit process id, so we should be fine here.
+ // TODO(mohitms): Get rid of events with explicit process ids
+ // entirely.
+ event_ctx.event()->set_track_uuid(track.uuid);
+ }
+
+ return event_ctx;
+ }
+
+ template <typename CategoryType,
+ typename EventNameType,
+ typename TrackType = Track,
+ typename TimestampType = uint64_t,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type,
+ typename TrackTypeCheck =
+ typename std::enable_if<IsValidTrack<TrackType>()>::type>
+ static perfetto::EventContext WriteTrackEvent(
+ typename Base::TraceContext& ctx,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
+ const TimestampType& timestamp) PERFETTO_NO_INLINE {
+ TraceTimestamp trace_timestamp = ::perfetto::TraceTimestampTraits<
+ TimestampType>::ConvertTimestampToTraceTimeNs(timestamp);
+ return WriteTrackEventImpl(ctx, category, event_name, type, track,
+ trace_timestamp);
+ }
+
+ template <typename CategoryType,
+ typename EventNameType,
+ typename TrackType = Track,
+ typename TrackTypeCheck =
+ typename std::enable_if<IsValidTrack<TrackType>()>::type>
+ static perfetto::EventContext WriteTrackEvent(
+ typename Base::TraceContext& ctx,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track) PERFETTO_NO_INLINE {
+ TraceTimestamp trace_timestamp = TrackEventInternal::GetTraceTime();
+ return WriteTrackEventImpl(ctx, category, event_name, type, track,
+ trace_timestamp);
+ }
+
+ template <typename CategoryType,
+ typename EventNameType,
+ typename TrackType = Track,
+ typename TimestampType = uint64_t,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type,
+ typename TrackTypeCheck =
+ typename std::enable_if<IsValidTrack<TrackType>()>::type,
+ typename... Arguments>
+ static void TraceForCategoryImpl(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
+ const TimestampType& timestamp,
+ Arguments&&... args) PERFETTO_ALWAYS_INLINE {
+ using CatTraits = CategoryTraits<CategoryType>;
+ TraceWithInstances(
+ instances, category, [&](typename Base::TraceContext ctx) {
+ // If this category is dynamic, first check whether it's enabled.
+ if (CatTraits::kIsDynamic &&
+ !IsDynamicCategoryEnabled(
+ &ctx, CatTraits::GetDynamicCategory(category))) {
+ return;
+ }
+
+ auto event_ctx = WriteTrackEvent(ctx, category, event_name, type,
+ track, timestamp);
+ WriteTrackEventArgs(std::move(event_ctx),
+ std::forward<Arguments>(args)...);
+ });
+ }
+
+ template <typename CategoryType,
+ typename EventNameType,
+ typename TrackType = Track,
+ typename TrackTypeCheck =
+ typename std::enable_if<IsValidTrack<TrackType>()>::type,
+ typename... Arguments>
+ static void TraceForCategoryImplNoTimestamp(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
+ Arguments&&... args) PERFETTO_ALWAYS_INLINE {
+ using CatTraits = CategoryTraits<CategoryType>;
+ TraceWithInstances(
+ instances, category, [&](typename Base::TraceContext ctx) {
+ // If this category is dynamic, first check whether it's enabled.
+ if (CatTraits::kIsDynamic &&
+ !IsDynamicCategoryEnabled(
+ &ctx, CatTraits::GetDynamicCategory(category))) {
+ return;
+ }
+
+ auto event_ctx =
+ WriteTrackEvent(ctx, category, event_name, type, track);
+ WriteTrackEventArgs(std::move(event_ctx),
+ std::forward<Arguments>(args)...);
+ });
+ }
+
+ template <typename CategoryType, typename Lambda>
+ static void TraceWithInstances(uint32_t instances,
+ const CategoryType& category,
+ Lambda lambda) PERFETTO_ALWAYS_INLINE {
+ using CatTraits = CategoryTraits<CategoryType>;
+ if (CatTraits::kIsDynamic) {
+ Base::template TraceWithInstances(instances, std::move(lambda));
+ } else {
+ Base::template TraceWithInstances<CategoryTracePointTraits>(
+ instances, std::move(lambda), {CatTraits::GetStaticIndex(category)});
+ }
+ }
+
+ // Records a track descriptor into the track descriptor registry and, if we
+ // are tracing, also mirrors the descriptor into the trace.
+ template <typename TrackType>
+ static void SetTrackDescriptorImpl(
+ const TrackType& track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback) {
+ TrackRegistry::Get()->UpdateTrack(track, std::move(callback));
+ Base::template Trace([&](typename Base::TraceContext ctx) {
+ TrackEventInternal::WriteTrackDescriptor(
+ track, ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
+ *ctx.GetCustomTlsState(), TrackEventInternal::GetTraceTime());
+ });
+ }
+
+ // Determines if the given dynamic category is enabled, first by checking the
+ // per-trace writer cache or by falling back to computing it based on the
+ // trace config for the given session.
+ static bool IsDynamicCategoryEnabled(
+ typename Base::TraceContext* ctx,
+ const DynamicCategory& dynamic_category) {
+ auto incr_state = ctx->GetIncrementalState();
+ auto it = incr_state->dynamic_categories.find(dynamic_category.name);
+ if (it == incr_state->dynamic_categories.end()) {
+ // We haven't seen this category before. Let's figure out if it's enabled.
+ // This requires grabbing a lock to read the session's trace config.
+ auto ds = ctx->GetDataSourceLocked();
+ if (!ds) {
+ return false;
+ }
+ Category category{Category::FromDynamicCategory(dynamic_category)};
+ bool enabled = TrackEventInternal::IsCategoryEnabled(
+ *Registry, ds->config_, category);
+ // TODO(skyostil): Cap the size of |dynamic_categories|.
+ incr_state->dynamic_categories[dynamic_category.name] = enabled;
+ return enabled;
+ }
+ return it->second;
+ }
+
+ // Config for the current tracing session.
+ protos::gen::TrackEventConfig config_;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_DATA_SOURCE_H_
+// gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_macros.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
+
+// This file contains underlying macros for the trace point track event
+// implementation. Perfetto API users typically don't need to use anything here
+// directly.
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_data_source.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/string_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_category_registry.h"
+
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC system_header
+#endif
+
+// Defines data structures for backing a category registry.
+//
+// Each category has one enabled/disabled bit per possible data source instance.
+// The bits are packed, i.e., each byte holds the state for instances. To
+// improve cache locality, the bits for each instance are stored separately from
+// the names of the categories:
+//
+// byte 0 byte 1
+// (inst0, inst1, ..., inst7), (inst0, inst1, ..., inst7)
+//
+#define PERFETTO_INTERNAL_DECLARE_CATEGORIES(attrs, ...) \
+ namespace internal { \
+ constexpr ::perfetto::Category kCategories[] = {__VA_ARGS__}; \
+ constexpr size_t kCategoryCount = \
+ sizeof(kCategories) / sizeof(kCategories[0]); \
+ /* The per-instance enable/disable state per category */ \
+ attrs extern std::atomic<uint8_t> g_category_state_storage[kCategoryCount]; \
+ /* The category registry which mediates access to the above structures. */ \
+ /* The registry is used for two purposes: */ \
+ /**/ \
+ /* 1) For looking up categories at build (constexpr) time. */ \
+ /* 2) For declaring the per-namespace TrackEvent data source. */ \
+ /**/ \
+ /* Because usage #1 requires a constexpr type and usage #2 requires an */ \
+ /* extern type (to avoid declaring a type based on a translation-unit */ \
+ /* variable), we need two separate copies of the registry with different */ \
+ /* storage specifiers. */ \
+ /**/ \
+ /* Note that because of a Clang/Windows bug, the constexpr category */ \
+ /* registry isn't given the enabled/disabled state array. All access */ \
+ /* to the category states should therefore be done through the */ \
+ /* non-constexpr registry. See */ \
+ /* https://bugs.llvm.org/show_bug.cgi?id=51558 */ \
+ /**/ \
+ /* TODO(skyostil): Unify these using a C++17 inline constexpr variable. */ \
+ constexpr ::perfetto::internal::TrackEventCategoryRegistry \
+ kConstExprCategoryRegistry(kCategoryCount, &kCategories[0], nullptr); \
+ attrs extern const ::perfetto::internal::TrackEventCategoryRegistry \
+ kCategoryRegistry; \
+ static_assert(kConstExprCategoryRegistry.ValidateCategories(), \
+ "Invalid category names found"); \
+ } // namespace internal
+
+// In a .cc file, declares storage for each category's runtime state.
+#define PERFETTO_INTERNAL_CATEGORY_STORAGE(attrs) \
+ namespace internal { \
+ attrs std::atomic<uint8_t> g_category_state_storage[kCategoryCount]; \
+ attrs const ::perfetto::internal::TrackEventCategoryRegistry \
+ kCategoryRegistry(kCategoryCount, \
+ &kCategories[0], \
+ &g_category_state_storage[0]); \
+ } // namespace internal
+
+// Defines the TrackEvent data source for the current track event namespace.
+// `virtual ~TrackEvent` is added to avoid `-Wweak-vtables` warning.
+// Learn more : aosp/2019906
+#define PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE(attrs) \
+ struct attrs TrackEvent : public ::perfetto::internal::TrackEventDataSource< \
+ TrackEvent, &internal::kCategoryRegistry> { \
+ virtual ~TrackEvent(); \
+ }
+
+#define PERFETTO_INTERNAL_DEFINE_TRACK_EVENT_DATA_SOURCE() \
+ TrackEvent::~TrackEvent() = default;
+
+// At compile time, turns a category name represented by a static string into an
+// index into the current category registry. A build error will be generated if
+// the category hasn't been registered or added to the list of allowed dynamic
+// categories. See PERFETTO_DEFINE_CATEGORIES.
+#define PERFETTO_GET_CATEGORY_INDEX(category) \
+ PERFETTO_TRACK_EVENT_NAMESPACE::internal::kConstExprCategoryRegistry.Find( \
+ category, \
+ ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::IsDynamicCategory(category))
+
+// Generate a unique variable name with a given prefix.
+#define PERFETTO_INTERNAL_CONCAT2(a, b) a##b
+#define PERFETTO_INTERNAL_CONCAT(a, b) PERFETTO_INTERNAL_CONCAT2(a, b)
+#define PERFETTO_UID(prefix) PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
+
+// Efficiently determines whether tracing is enabled for the given category, and
+// if so, emits one trace event with the given arguments.
+#define PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(method, category, name, ...) \
+ do { \
+ ::perfetto::internal::ValidateEventNameType<decltype(name)>(); \
+ namespace tns = PERFETTO_TRACK_EVENT_NAMESPACE; \
+ /* Compute the category index outside the lambda to work around a */ \
+ /* GCC 7 bug */ \
+ constexpr auto PERFETTO_UID( \
+ kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_) = \
+ PERFETTO_GET_CATEGORY_INDEX(category); \
+ if (::PERFETTO_TRACK_EVENT_NAMESPACE::internal::IsDynamicCategory( \
+ category)) { \
+ tns::TrackEvent::CallIfEnabled( \
+ [&](uint32_t instances) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
+ tns::TrackEvent::method(instances, category, name, ##__VA_ARGS__); \
+ }); \
+ } else { \
+ tns::TrackEvent::CallIfCategoryEnabled( \
+ PERFETTO_UID(kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_), \
+ [&](uint32_t instances) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
+ tns::TrackEvent::method( \
+ instances, \
+ PERFETTO_UID( \
+ kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_), \
+ name, ##__VA_ARGS__); \
+ }); \
+ } \
+ } while (false)
+
+// This internal macro is unused from the repo now, but some improper usage
+// remain outside of the repo.
+// TODO(b/294800182): Remove this.
+#define PERFETTO_INTERNAL_TRACK_EVENT(...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(TraceForCategory, ##__VA_ARGS__)
+
+// C++17 doesn't like a move constructor being defined for the EventFinalizer
+// class but C++11 and MSVC doesn't compile without it being defined so support
+// both.
+#if !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
+#define PERFETTO_INTERNAL_EVENT_FINALIZER_KEYWORD delete
+#else
+#define PERFETTO_INTERNAL_EVENT_FINALIZER_KEYWORD default
+#endif
+
+#include <mozilla/Attributes.h>
+#define PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER(category) \
+ struct PERFETTO_UID(ScopedEvent) { \
+ struct EventFinalizer { \
+ /* The parameter is an implementation detail. It allows the */ \
+ /* anonymous struct to use aggregate initialization to invoke the */ \
+ /* lambda (which emits the BEGIN event and returns an integer) */ \
+ /* with the proper reference capture for any */ \
+ /* TrackEventArgumentFunction in |__VA_ARGS__|. This is required so */ \
+ /* that the scoped event is exactly ONE line and can't escape the */ \
+ /* scope if used in a single line if statement. */ \
+ MOZ_IMPLICIT EventFinalizer(...) {} \
+ ~EventFinalizer() { TRACE_EVENT_END(category); } \
+ \
+ EventFinalizer(const EventFinalizer&) = delete; \
+ inline EventFinalizer& operator=(const EventFinalizer&) = delete; \
+ \
+ EventFinalizer(EventFinalizer&&) = \
+ PERFETTO_INTERNAL_EVENT_FINALIZER_KEYWORD; \
+ EventFinalizer& operator=(EventFinalizer&&) = delete; \
+ } finalizer; \
+ }
+
+#define PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ...) \
+ PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER(category) \
+ PERFETTO_UID(scoped_event) { \
+ [&]() { \
+ TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
+ return 0; \
+ }() \
+ }
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+// Required for TRACE_EVENT_WITH_FLOW legacy macros, which pass the bind_id as
+// id.
+#define PERFETTO_INTERNAL_SCOPED_LEGACY_TRACK_EVENT_WITH_ID( \
+ category, name, track, flags, thread_id, id, ...) \
+ PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER(category) \
+ PERFETTO_UID(scoped_event) { \
+ [&]() { \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategoryLegacyWithId, category, name, \
+ ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, track, \
+ 'B', flags, thread_id, id, ##__VA_ARGS__); \
+ return 0; \
+ }() \
+ }
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC) || \
+ PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
+// On GCC versions <9 there's a bug that prevents using captured constant
+// variables in constexpr evaluation inside a lambda:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82643
+// TODO(khokhlov): Remove this fallback after Perfetto moves to a more recent
+// GCC version.
+#define PERFETTO_INTERNAL_CATEGORY_ENABLED(category) \
+ (::PERFETTO_TRACK_EVENT_NAMESPACE::internal::IsDynamicCategory(category) \
+ ? PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::IsDynamicCategoryEnabled( \
+ ::perfetto::DynamicCategory(category)) \
+ : PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::IsCategoryEnabled( \
+ PERFETTO_GET_CATEGORY_INDEX(category)))
+#else // !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
+#define PERFETTO_INTERNAL_CATEGORY_ENABLED(category) \
+ [&]() -> bool { \
+ using PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent; \
+ using ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::IsDynamicCategory; \
+ constexpr auto PERFETTO_UID(index) = \
+ PERFETTO_GET_CATEGORY_INDEX(category); \
+ constexpr auto PERFETTO_UID(dynamic) = IsDynamicCategory(category); \
+ return PERFETTO_UID(dynamic) \
+ ? TrackEvent::IsDynamicCategoryEnabled( \
+ ::perfetto::DynamicCategory(category)) \
+ : TrackEvent::IsCategoryEnabled(PERFETTO_UID(index)); \
+ }()
+#endif // !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
+
+// Emits an empty trace packet into the trace to ensure that the service can
+// safely read the last event from the trace buffer. This can be used to
+// periodically "flush" the last event on threads that don't support explicit
+// flushing of the shared memory buffer chunk when the tracing session stops
+// (e.g. thread pool workers in Chromium).
+//
+// This workaround is only required because the tracing service cannot safely
+// read the last trace packet from an incomplete SMB chunk (crbug.com/1021571
+// and b/162206162) when scraping the SMB. Adding an empty trace packet ensures
+// that all prior events can be scraped by the service.
+#define PERFETTO_INTERNAL_ADD_EMPTY_EVENT() \
+ do { \
+ PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::Trace( \
+ [](PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::TraceContext ctx) { \
+ ctx.AddEmptyTracePacket(); \
+ }); \
+ } while (false)
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_data_source.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_macros.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/string_helpers.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_category_registry.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+#include <type_traits>
+
+// This file contains a set of macros designed for instrumenting applications
+// with track event trace points. While the underlying TrackEvent API can also
+// be used directly, doing so efficiently requires some care (e.g., to avoid
+// evaluating arguments while tracing is disabled). These types of optimizations
+// are abstracted away by the macros below.
+//
+// ================
+// Quickstart guide
+// ================
+//
+// To add track events to your application, first define your categories in,
+// e.g., my_tracing.h:
+//
+// PERFETTO_DEFINE_CATEGORIES(
+// perfetto::Category("base"),
+// perfetto::Category("v8"),
+// perfetto::Category("cc"));
+//
+// Then in a single .cc file, e.g., my_tracing.cc:
+//
+// #include "my_tracing.h"
+// PERFETTO_TRACK_EVENT_STATIC_STORAGE();
+//
+// Finally, register track events at startup, after which you can record
+// events with the TRACE_EVENT macros:
+//
+// #include "my_tracing.h"
+//
+// int main() {
+// perfetto::TrackEvent::Register();
+//
+// // A basic track event with just a name.
+// TRACE_EVENT("category", "MyEvent");
+//
+// // A track event with (up to two) debug annotations.
+// TRACE_EVENT("category", "MyEvent", "parameter", 42);
+//
+// // A track event with a strongly typed parameter.
+// TRACE_EVENT("category", "MyEvent", [](perfetto::EventContext ctx) {
+// ctx.event()->set_foo(42);
+// ctx.event()->set_bar(.5f);
+// });
+// }
+//
+// Note that track events must be nested consistently, i.e., the following is
+// not allowed:
+//
+// TRACE_EVENT_BEGIN("a", "bar", ...);
+// TRACE_EVENT_BEGIN("b", "foo", ...);
+// TRACE_EVENT_END("a"); // "foo" must be closed before "bar".
+// TRACE_EVENT_END("b");
+//
+// ====================
+// Implementation notes
+// ====================
+//
+// The track event library consists of the following layers and components. The
+// classes the internal namespace shouldn't be considered part of the public
+// API.
+// .--------------------------------.
+// .----| TRACE_EVENT |----.
+// write | | - App instrumentation point | | write
+// event | '--------------------------------' | arguments
+// V V
+// .----------------------------------. .-----------------------------.
+// | TrackEvent | | EventContext |
+// | - Registry of event categories | | - One track event instance |
+// '----------------------------------' '-----------------------------'
+// | |
+// | | look up
+// | is | interning ids
+// V V
+// .----------------------------------. .-----------------------------.
+// | internal::TrackEventDataSource | | TrackEventInternedDataIndex |
+// | - Perfetto data source | | - Corresponds to a field in |
+// | - Has TrackEventIncrementalState | | in interned_data.proto |
+// '----------------------------------' '-----------------------------'
+// | | ^
+// | | owns (1:many) |
+// | write event '-------------------------'
+// V
+// .----------------------------------.
+// | internal::TrackEventInternal |
+// | - Outlined code to serialize |
+// | one track event |
+// '----------------------------------'
+//
+
+// DEPRECATED: Please use PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE to implement
+// multiple track event category sets in one program.
+//
+// Each compilation unit can be in exactly one track event namespace,
+// allowing the overall program to use multiple track event data sources and
+// category lists if necessary. Use this macro to select the namespace for the
+// current compilation unit.
+//
+// If the program uses multiple track event namespaces, category & track event
+// registration (see quickstart above) needs to happen for both namespaces
+// separately.
+
+#ifndef PERFETTO_TRACK_EVENT_NAMESPACE
+#define PERFETTO_TRACK_EVENT_NAMESPACE perfetto_track_event
+#endif
+
+// Deprecated; see perfetto::Category().
+#define PERFETTO_CATEGORY(name) \
+ ::perfetto::Category { #name }
+
+// Internal helpers for determining if a given category is defined at build or
+// runtime.
+namespace PERFETTO_TRACK_EVENT_NAMESPACE {
+namespace internal {
+
+// By default no statically defined categories are dynamic, but this can be
+// overridden with PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES.
+template <typename... T>
+constexpr bool IsDynamicCategory(const char*) {
+ return false;
+}
+
+// Explicitly dynamic categories are always dynamic.
+constexpr bool IsDynamicCategory(const ::perfetto::DynamicCategory&) {
+ return true;
+}
+
+} // namespace internal
+} // namespace PERFETTO_TRACK_EVENT_NAMESPACE
+
+// Normally all categories are defined statically at build-time (see
+// PERFETTO_DEFINE_CATEGORIES). However, some categories are only used for
+// testing, and we shouldn't publish them to the tracing service or include them
+// in a production binary. Use this macro to define a list of prefixes for these
+// types of categories. Note that trace points using these categories will be
+// slightly less efficient compared to regular trace points.
+#define PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES(...) \
+ namespace PERFETTO_TRACK_EVENT_NAMESPACE { \
+ namespace internal { \
+ template <> \
+ constexpr bool IsDynamicCategory(const char* name) { \
+ return ::perfetto::internal::IsStringInPrefixList(name, __VA_ARGS__); \
+ } \
+ } /* namespace internal */ \
+ } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */ \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
+
+// Register the set of available categories by passing a list of categories to
+// this macro: perfetto::Category("cat1"), perfetto::Category("cat2"), ...
+// `ns` is the name of the namespace in which the categories should be declared.
+// `attrs` are linkage attributes for the underlying data source. See
+// PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS.
+//
+// Implementation note: the extra namespace (PERFETTO_TRACK_EVENT_NAMESPACE) is
+// kept here only for backward compatibility.
+#define PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS(ns, attrs, ...) \
+ namespace ns { \
+ namespace PERFETTO_TRACK_EVENT_NAMESPACE { \
+ /* The list of category names */ \
+ PERFETTO_INTERNAL_DECLARE_CATEGORIES(attrs, __VA_ARGS__) \
+ /* The track event data source for this set of categories */ \
+ PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE(attrs); \
+ } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */ \
+ using PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent; \
+ } /* namespace ns */ \
+ PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
+ attrs, ns::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent, \
+ ::perfetto::internal::TrackEventDataSourceTraits)
+
+// Register the set of available categories by passing a list of categories to
+// this macro: perfetto::Category("cat1"), perfetto::Category("cat2"), ...
+// `ns` is the name of the namespace in which the categories should be declared.
+#define PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE(ns, ...) \
+ PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS( \
+ ns, PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)
+
+// Make categories in a given namespace the default ones used by track events
+// for the current translation unit. Can only be used *once* in a given global
+// or namespace scope.
+#define PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(ns) \
+ namespace PERFETTO_TRACK_EVENT_NAMESPACE { \
+ using ::ns::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent; \
+ namespace internal { \
+ using ::ns::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry; \
+ using ::ns::PERFETTO_TRACK_EVENT_NAMESPACE::internal:: \
+ kConstExprCategoryRegistry; \
+ } /* namespace internal */ \
+ } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */ \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
+
+// Make categories in a given namespace the default ones used by track events
+// for the current block scope. Can only be used in a function or block scope.
+#define PERFETTO_USE_CATEGORIES_FROM_NAMESPACE_SCOPED(ns) \
+ namespace PERFETTO_TRACK_EVENT_NAMESPACE = ns::PERFETTO_TRACK_EVENT_NAMESPACE
+
+// Register categories in the default (global) namespace. Warning: only one set
+// of global categories can be defined in a single program. Create namespaced
+// categories with PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE to work around this
+// limitation.
+#define PERFETTO_DEFINE_CATEGORIES(...) \
+ PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE(perfetto, __VA_ARGS__); \
+ PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(perfetto)
+
+// Allocate storage for each category by using this macro once per track event
+// namespace. `ns` is the name of the namespace in which the categories should
+// be declared and `attrs` specify linkage attributes for the data source.
+#define PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE_WITH_ATTRS(ns, attrs) \
+ namespace ns { \
+ namespace PERFETTO_TRACK_EVENT_NAMESPACE { \
+ PERFETTO_INTERNAL_CATEGORY_STORAGE(attrs) \
+ PERFETTO_INTERNAL_DEFINE_TRACK_EVENT_DATA_SOURCE() \
+ } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */ \
+ } /* namespace ns */ \
+ PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
+ attrs, ns::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent, \
+ ::perfetto::internal::TrackEventDataSourceTraits)
+
+// Allocate storage for each category by using this macro once per track event
+// namespace.
+#define PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(ns) \
+ PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE_WITH_ATTRS( \
+ ns, PERFETTO_COMPONENT_EXPORT)
+
+// Allocate storage for each category by using this macro once per track event
+// namespace.
+#define PERFETTO_TRACK_EVENT_STATIC_STORAGE() \
+ PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(perfetto)
+
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC system_header
+#endif
+
+// Begin a slice under |category| with the title |name|. Both strings must be
+// static constants. The track event is only recorded if |category| is enabled
+// for a tracing session.
+//
+// The slice is thread-scoped (i.e., written to the default track of the current
+// thread) unless overridden with a custom track object (see Track).
+//
+// |name| must be a string with static lifetime (i.e., the same
+// address must not be used for a different event name in the future). If you
+// want to use a dynamically allocated name, do this:
+//
+// TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
+// ctx.event()->set_name(dynamic_name);
+// });
+//
+// The following optional arguments can be passed to `TRACE_EVENT` to add extra
+// information to events:
+//
+// TRACE_EVENT("cat", "name"[, track][, timestamp]
+// [, "debug_name1", debug_value1]
+// [, "debug_name2", debug_value2]
+// ...
+// [, "debug_nameN", debug_valueN]
+// [, lambda]);
+//
+// Some examples of valid combinations:
+//
+// 1. A lambda for writing custom TrackEvent fields:
+//
+// TRACE_EVENT("category", "Name", [&](perfetto::EventContext ctx) {
+// ctx.event()->set_custom_value(...);
+// });
+//
+// 2. A timestamp and a lambda:
+//
+// TRACE_EVENT("category", "Name", time_in_nanoseconds,
+// [&](perfetto::EventContext ctx) {
+// ctx.event()->set_custom_value(...);
+// });
+//
+// |time_in_nanoseconds| should be an uint64_t by default. To support custom
+// timestamp types,
+// |perfetto::TraceTimestampTraits<T>::ConvertTimestampToTraceTimeNs|
+// should be defined. See |ConvertTimestampToTraceTimeNs| for more details.
+//
+// 3. Arbitrary number of debug annotations:
+//
+// TRACE_EVENT("category", "Name", "arg", value);
+// TRACE_EVENT("category", "Name", "arg", value, "arg2", value2);
+// TRACE_EVENT("category", "Name", "arg", value, "arg2", value2,
+// "arg3", value3);
+//
+// See |TracedValue| for recording custom types as debug annotations.
+//
+// 4. Arbitrary number of debug annotations and a lambda:
+//
+// TRACE_EVENT("category", "Name", "arg", value,
+// [&](perfetto::EventContext ctx) {
+// ctx.event()->set_custom_value(...);
+// });
+//
+// 5. An overridden track:
+//
+// TRACE_EVENT("category", "Name", perfetto::Track(1234));
+//
+// See |Track| for other types of tracks which may be used.
+//
+// 6. A track and a lambda:
+//
+// TRACE_EVENT("category", "Name", perfetto::Track(1234),
+// [&](perfetto::EventContext ctx) {
+// ctx.event()->set_custom_value(...);
+// });
+//
+// 7. A track and a timestamp:
+//
+// TRACE_EVENT("category", "Name", perfetto::Track(1234),
+// time_in_nanoseconds);
+//
+// 8. A track, a timestamp and a lambda:
+//
+// TRACE_EVENT("category", "Name", perfetto::Track(1234),
+// time_in_nanoseconds, [&](perfetto::EventContext ctx) {
+// ctx.event()->set_custom_value(...);
+// });
+//
+// 9. A track and an arbitrary number of debug annotions:
+//
+// TRACE_EVENT("category", "Name", perfetto::Track(1234),
+// "arg", value);
+// TRACE_EVENT("category", "Name", perfetto::Track(1234),
+// "arg", value, "arg2", value2);
+//
+#define TRACE_EVENT_BEGIN(category, name, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategory, category, \
+ ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
+
+// End a slice under |category|.
+#define TRACE_EVENT_END(category, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategory, category, /*name=*/nullptr, \
+ ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END, ##__VA_ARGS__)
+
+// Begin a slice which gets automatically closed when going out of scope.
+#define TRACE_EVENT(category, name, ...) \
+ PERFETTO_INTERNAL_SCOPED_TRACK_EVENT( \
+ category, ::perfetto::internal::DecayEventNameType(name), ##__VA_ARGS__)
+
+// Emit a slice which has zero duration.
+#define TRACE_EVENT_INSTANT(category, name, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategory, category, \
+ ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, ##__VA_ARGS__)
+
+// Efficiently determine if the given static or dynamic trace category or
+// category group is enabled for tracing.
+#define TRACE_EVENT_CATEGORY_ENABLED(category) \
+ PERFETTO_INTERNAL_CATEGORY_ENABLED(category)
+
+// Time-varying numeric data can be recorded with the TRACE_COUNTER macro:
+//
+// TRACE_COUNTER("cat", counter_track[, timestamp], value);
+//
+// For example, to record a single value for a counter called "MyCounter":
+//
+// TRACE_COUNTER("category", "MyCounter", 1234.5);
+//
+// This data is displayed as a counter track in the Perfetto UI.
+//
+// Both integer and floating point counter values are supported. Counters can
+// also be annotated with additional information such as units, for example, for
+// tracking the rendering framerate in terms of frames per second or "fps":
+//
+// TRACE_COUNTER("category", perfetto::CounterTrack("Framerate", "fps"), 120);
+//
+// As another example, a memory counter that records bytes but accepts samples
+// as kilobytes (to reduce trace binary size) can be defined like this:
+//
+// perfetto::CounterTrack memory_track = perfetto::CounterTrack("Memory")
+// .set_unit("bytes")
+// .set_multiplier(1024);
+// TRACE_COUNTER("category", memory_track, 4 /* = 4096 bytes */);
+//
+// See /protos/perfetto/trace/track_event/counter_descriptor.proto
+// for the full set of attributes for a counter track.
+//
+// To record a counter value at a specific point in time (instead of the current
+// time), you can pass in a custom timestamp:
+//
+// // First record the current time and counter value.
+// uint64_t timestamp = perfetto::TrackEvent::GetTraceTimeNs();
+// int64_t value = 1234;
+//
+// // Later, emit a sample at that point in time.
+// TRACE_COUNTER("category", "MyCounter", timestamp, value);
+//
+#define TRACE_COUNTER(category, track, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategory, category, /*name=*/nullptr, \
+ ::perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER, \
+ ::perfetto::CounterTrack(track), ##__VA_ARGS__)
+
+// TODO(skyostil): Add flow events.
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
+// gen_amalgamated begin header: include/perfetto/tracing/track_event_interned_data_index.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
+
+// gen_amalgamated expanded: #include "perfetto/tracing/internal/track_event_internal.h"
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/event_context.h"
+
+#include <map>
+#include <type_traits>
+#include <unordered_map>
+
+// This file has templates for defining your own interned data types to be used
+// with track event. Interned data can be useful for avoiding repeating the same
+// constant data (e.g., strings) throughout the trace.
+//
+// =============
+// Example usage
+// =============
+//
+// First define an interning index for your type. It should map to a specific
+// field of interned_data.proto and define how the interned data is written into
+// that message.
+//
+// struct MyInternedData
+// : public perfetto::TrackEventInternedDataIndex<
+// MyInternedData,
+// perfetto::protos::pbzero::InternedData::kMyInternedDataFieldNumber,
+// const char*> {
+// static void Add(perfetto::protos::pbzero::InternedData* interned_data,
+// size_t iid,
+// const char* value) {
+// auto my_data = interned_data->add_my_interned_data();
+// my_data->set_iid(iid);
+// my_data->set_value(value);
+// }
+// };
+//
+// Next, use your interned data in a trace point as shown below. The interned
+// string will only be emitted the first time the trace point is hit.
+//
+// TRACE_EVENT_BEGIN(
+// "category", "Event", [&](perfetto::EventContext ctx) {
+// auto my_message = ctx.event()->set_my_message();
+// size_t iid = MyInternedData::Get(&ctx, "Some data");
+// my_message->set_iid(iid);
+// });
+//
+
+namespace perfetto {
+
+// By default, the interning index stores a full copy of the interned data. This
+// ensures the same data is always mapped to the same interning id, and there is
+// no danger of collisions. This comes at the cost of memory usage, however, so
+// consider using HashedInternedDataTraits if that may be an issue.
+//
+// This type of index also performs hashing on the stored data for lookups; for
+// types where this isn't necessary (e.g., raw const char*), use
+// SmallInternedDataTraits.
+struct BigInternedDataTraits {
+ template <typename ValueType>
+ class Index {
+ public:
+ bool LookUpOrInsert(size_t* iid, const ValueType& value) {
+ size_t next_id = data_.size() + 1;
+ auto it_and_inserted = data_.insert(std::make_pair(value, next_id));
+ if (!it_and_inserted.second) {
+ *iid = it_and_inserted.first->second;
+ return true;
+ }
+ *iid = next_id;
+ return false;
+ }
+
+ private:
+ std::unordered_map<ValueType, size_t> data_;
+ };
+};
+
+// This type of interning index keeps full copies of interned data without
+// hashing the values. This is a good fit for small types that can be directly
+// used as index keys.
+struct SmallInternedDataTraits {
+ template <typename ValueType>
+ class Index {
+ public:
+ bool LookUpOrInsert(size_t* iid, const ValueType& value) {
+ size_t next_id = data_.size() + 1;
+ auto it_and_inserted = data_.insert(std::make_pair(value, next_id));
+ if (!it_and_inserted.second) {
+ *iid = it_and_inserted.first->second;
+ return true;
+ }
+ *iid = next_id;
+ return false;
+ }
+
+ private:
+ std::map<ValueType, size_t> data_;
+ };
+};
+
+// This type of interning index only stores the hash of the interned values
+// instead of the values themselves. This is more efficient in terms of memory
+// usage, but assumes that there are no hash collisions. If a hash collision
+// occurs, two or more values will be mapped to the same interning id.
+//
+// Note that the given type must have a specialization for std::hash.
+struct HashedInternedDataTraits {
+ template <typename ValueType>
+ class Index {
+ public:
+ bool LookUpOrInsert(size_t* iid, const ValueType& value) {
+ auto key = std::hash<ValueType>()(value);
+ size_t next_id = data_.size() + 1;
+ auto it_and_inserted = data_.insert(std::make_pair(key, next_id));
+ if (!it_and_inserted.second) {
+ *iid = it_and_inserted.first->second;
+ return true;
+ }
+ *iid = next_id;
+ return false;
+ }
+
+ private:
+ std::map<size_t, size_t> data_;
+ };
+};
+
+// A templated base class for an interned data type which corresponds to a field
+// in interned_data.proto.
+//
+// |InternedDataType| must be the type of the subclass.
+// |FieldNumber| is the corresponding protobuf field in InternedData.
+// |ValueType| is the type which is stored in the index. It must be copyable.
+// |Traits| can be used to customize the storage and lookup mechanism.
+//
+// The subclass should define a static method with the following signature for
+// committing interned data together with the interning id |iid| into the trace:
+//
+// static void Add(perfetto::protos::pbzero::InternedData*,
+// size_t iid,
+// const ValueType& value);
+//
+template <typename InternedDataType,
+ size_t FieldNumber,
+ typename ValueType,
+ // Avoid unnecessary hashing for pointers by default.
+ typename Traits =
+ typename std::conditional<(std::is_pointer<ValueType>::value),
+ SmallInternedDataTraits,
+ BigInternedDataTraits>::type>
+class TrackEventInternedDataIndex
+ : public internal::BaseTrackEventInternedDataIndex {
+ public:
+ // Return an interning id for |value|. The returned id can be immediately
+ // written to the trace. The optional |add_args| are passed to the Add()
+ // function.
+ template <typename... Args>
+ static size_t Get(EventContext* ctx,
+ const ValueType& value,
+ Args&&... add_args) {
+ return Get(ctx->incremental_state_, value, std::forward<Args>(add_args)...);
+ }
+
+ template <typename... Args>
+ static size_t Get(internal::TrackEventIncrementalState* incremental_state,
+ const ValueType& value,
+ Args&&... add_args) {
+ // First check if the value exists in the dictionary.
+ auto index_for_field = GetOrCreateIndexForField(incremental_state);
+ size_t iid;
+ if (PERFETTO_LIKELY(index_for_field->index_.LookUpOrInsert(&iid, value))) {
+ PERFETTO_DCHECK(iid);
+ return iid;
+ }
+
+ // If not, we need to serialize the definition of the interned value into
+ // the heap buffered message (which is committed to the trace when the
+ // packet ends).
+ PERFETTO_DCHECK(iid);
+ InternedDataType::Add(incremental_state->serialized_interned_data.get(),
+ iid, std::move(value),
+ std::forward<Args>(add_args)...);
+ return iid;
+ }
+
+ protected:
+ // Some use cases require a custom Get implemention, so they need access to
+ // GetOrCreateIndexForField + the returned index.
+ static InternedDataType* GetOrCreateIndexForField(
+ internal::TrackEventIncrementalState* incremental_state) {
+ // Fast path: look for matching field number.
+ for (const auto& entry : incremental_state->interned_data_indices) {
+ if (entry.first == FieldNumber) {
+#if PERFETTO_DCHECK_IS_ON()
+ if (strcmp(PERFETTO_DEBUG_FUNCTION_IDENTIFIER(),
+ entry.second->type_id_)) {
+ PERFETTO_FATAL(
+ "Interned data accessed under different types! Previous type: "
+ "%s. New type: %s.",
+ entry.second->type_id_, PERFETTO_DEBUG_FUNCTION_IDENTIFIER());
+ }
+ // If an interned data index is defined in an anonymous namespace, we
+ // can end up with multiple copies of it in the same program. Because
+ // they will all share a memory address through TLS, this can lead to
+ // subtle data corruption if all the copies aren't exactly identical.
+ // Try to detect this by checking if the Add() function address remains
+ // constant.
+ if (reinterpret_cast<void*>(&InternedDataType::Add) !=
+ entry.second->add_function_ptr_) {
+ PERFETTO_FATAL(
+ "Inconsistent interned data index. Maybe the index was defined "
+ "in an anonymous namespace in a header or copied to multiple "
+ "files? Duplicate index definitions can lead to memory "
+ "corruption! Type id: %s",
+ entry.second->type_id_);
+ }
+#endif // PERFETTO_DCHECK_IS_ON()
+ return reinterpret_cast<InternedDataType*>(entry.second.get());
+ }
+ }
+ // No match -- add a new entry for this field.
+ for (auto& entry : incremental_state->interned_data_indices) {
+ if (!entry.first) {
+ entry.first = FieldNumber;
+ entry.second.reset(new InternedDataType());
+#if PERFETTO_DCHECK_IS_ON()
+ entry.second->type_id_ = PERFETTO_DEBUG_FUNCTION_IDENTIFIER();
+ entry.second->add_function_ptr_ =
+ reinterpret_cast<void*>(&InternedDataType::Add);
+#endif // PERFETTO_DCHECK_IS_ON()
+ return reinterpret_cast<InternedDataType*>(entry.second.get());
+ }
+ }
+ // Out of space in the interned data index table.
+ PERFETTO_CHECK(false);
+ }
+
+ // The actual interning dictionary for this type of interned data. The actual
+ // container type is defined by |Traits|, hence the extra layer of template
+ // indirection here.
+ typename Traits::template Index<ValueType> index_;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
+// gen_amalgamated begin header: include/perfetto/tracing/track_event_legacy.h
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
+
+// This file defines a compatibility shim between legacy (Chrome, V8) trace
+// event macros and track events. To avoid accidentally introducing legacy
+// events in new code, the PERFETTO_ENABLE_LEGACY_TRACE_EVENTS macro must be set
+// to 1 activate the compatibility layer.
+
+// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event.h"
+
+#include <stdint.h>
+
+#ifndef PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 0
+#endif
+
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC system_header
+#endif
+
+// ----------------------------------------------------------------------------
+// Internal legacy trace point implementation.
+// ----------------------------------------------------------------------------
+
+namespace perfetto {
+namespace legacy {
+
+// The following user-provided adaptors are used to serialize user-defined
+// thread id and time types into track events. For full compatibility, the user
+// should also define the following macros appropriately:
+//
+// #define TRACE_TIME_TICKS_NOW() ...
+// #define TRACE_TIME_NOW() ...
+
+// User-provided function to convert an abstract thread id into a thread track.
+template <typename T>
+ThreadTrack ConvertThreadId(const T&);
+
+// Built-in implementation for events referring to the current thread.
+template <>
+ThreadTrack PERFETTO_EXPORT_COMPONENT
+ConvertThreadId(const PerfettoLegacyCurrentThreadId&);
+
+} // namespace legacy
+} // namespace perfetto
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+// Implementations for the INTERNAL_* adapter macros used by the trace points
+// below.
+#define PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(phase, category, name, track, \
+ ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategory, category, \
+ ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track, \
+ ##__VA_ARGS__);
+
+#define PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, track, flags, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategoryLegacy, category, \
+ ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track, \
+ phase, flags, ##__VA_ARGS__);
+
+#define PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, track, flags, thread_id, id, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD( \
+ TraceForCategoryLegacyWithId, category, \
+ ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track, \
+ phase, flags, thread_id, id, ##__VA_ARGS__);
+
+// The main entrypoint for writing unscoped legacy events. This macro
+// determines the right track to write the event on based on |flags| and
+// |thread_id|.
+#define PERFETTO_INTERNAL_LEGACY_EVENT(phase, category, name, flags, \
+ thread_id, ...) \
+ [&]() { \
+ using ::perfetto::internal::TrackEventInternal; \
+ PERFETTO_DCHECK(!(flags & TRACE_EVENT_FLAG_COPY)); \
+ /* First check the scope for instant events. */ \
+ if ((phase) == TRACE_EVENT_PHASE_INSTANT) { \
+ /* Note: Avoids the need to set LegacyEvent::instant_event_scope. */ \
+ auto scope = (flags)&TRACE_EVENT_FLAG_SCOPE_MASK; \
+ switch (scope) { \
+ case TRACE_EVENT_SCOPE_GLOBAL: \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, ::perfetto::Track::Global(0), flags, \
+ ##__VA_ARGS__); \
+ return; \
+ case TRACE_EVENT_SCOPE_PROCESS: \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, ::perfetto::ProcessTrack::Current(), \
+ flags, ##__VA_ARGS__); \
+ return; \
+ default: \
+ case TRACE_EVENT_SCOPE_THREAD: \
+ /* Fallthrough. */ \
+ break; \
+ } \
+ } \
+ /* If an event targets the current thread or another process, write \
+ * it on the current thread's track. The process override case is \
+ * handled through |pid_override| in WriteLegacyEvent. */ \
+ if (std::is_same< \
+ decltype(thread_id), \
+ ::perfetto::legacy::PerfettoLegacyCurrentThreadId>::value || \
+ ((flags)&TRACE_EVENT_FLAG_HAS_PROCESS_ID)) { \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, TrackEventInternal::kDefaultTrack, flags, \
+ ##__VA_ARGS__); \
+ } else { \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, \
+ ::perfetto::legacy::ConvertThreadId(thread_id), flags, \
+ ##__VA_ARGS__); \
+ } \
+ }()
+
+#define PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID(phase, category, name, flags, \
+ thread_id, id, ...) \
+ [&]() { \
+ using ::perfetto::internal::TrackEventInternal; \
+ PERFETTO_DCHECK(!(flags & TRACE_EVENT_FLAG_COPY)); \
+ /* First check the scope for instant events. */ \
+ if ((phase) == TRACE_EVENT_PHASE_INSTANT) { \
+ /* Note: Avoids the need to set LegacyEvent::instant_event_scope. */ \
+ auto scope = (flags)&TRACE_EVENT_FLAG_SCOPE_MASK; \
+ switch (scope) { \
+ case TRACE_EVENT_SCOPE_GLOBAL: \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, ::perfetto::Track::Global(0), flags, \
+ thread_id, id, ##__VA_ARGS__); \
+ return; \
+ case TRACE_EVENT_SCOPE_PROCESS: \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, ::perfetto::ProcessTrack::Current(), \
+ flags, thread_id, id, ##__VA_ARGS__); \
+ return; \
+ default: \
+ case TRACE_EVENT_SCOPE_THREAD: \
+ /* Fallthrough. */ \
+ break; \
+ } \
+ } \
+ /* If an event targets the current thread or another process, write \
+ * it on the current thread's track. The process override case is \
+ * handled through |pid_override| in WriteLegacyEvent. */ \
+ if (std::is_same< \
+ decltype(thread_id), \
+ ::perfetto::legacy::PerfettoLegacyCurrentThreadId>::value || \
+ ((flags)&TRACE_EVENT_FLAG_HAS_PROCESS_ID)) { \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, TrackEventInternal::kDefaultTrack, flags, \
+ thread_id, id, ##__VA_ARGS__); \
+ } else { \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, \
+ ::perfetto::legacy::ConvertThreadId(thread_id), flags, thread_id, \
+ id, ##__VA_ARGS__); \
+ } \
+ }()
+
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ ::perfetto::legacy::kCurrentThreadId, ##__VA_ARGS__)
+
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
+ PERFETTO_INTERNAL_SCOPED_TRACK_EVENT( \
+ category, ::perfetto::internal::DecayEventNameType(name), ##__VA_ARGS__)
+
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category, name, bind_id, \
+ flags, ...) \
+ PERFETTO_INTERNAL_SCOPED_LEGACY_TRACK_EVENT_WITH_ID( \
+ category, ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::internal::TrackEventInternal::kDefaultTrack, flags, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, bind_id, ##__VA_ARGS__)
+
+#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category, name, \
+ timestamp, flags, ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ ::perfetto::legacy::kCurrentThreadId, timestamp, ##__VA_ARGS__)
+
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ phase, category, name, id, thread_id, timestamp, flags, ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ thread_id, id, timestamp, ##__VA_ARGS__)
+
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
+ ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ ::perfetto::legacy::kCurrentThreadId, id, ##__VA_ARGS__)
+
+#define INTERNAL_TRACE_EVENT_METADATA_ADD(category, name, ...) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_METADATA, category, name, \
+ TRACE_EVENT_FLAG_NONE)
+
+// ----------------------------------------------------------------------------
+// Legacy tracing common API (adapted from trace_event_common.h).
+// ----------------------------------------------------------------------------
+
+#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name
+
+// Scoped events.
+#define TRACE_EVENT0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
+#define TRACE_EVENT_WITH_FLOW0(category_group, name, bind_id, flow_flags) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, bind_id, \
+ flow_flags)
+#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED( \
+ category_group, name, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_WITH_FLOW1(category_group, name, bind_id, flow_flags, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW( \
+ category_group, name, bind_id, flow_flags, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, \
+ arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED( \
+ category_group, name, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_WITH_FLOW2(category_group, name, bind_id, flow_flags, \
+ arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW( \
+ category_group, name, bind_id, flow_flags, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+// Instant events.
+#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_NONE | scope)
+#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_NONE | scope, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_NONE | scope, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_INSTANT0(category_group, name, scope) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, \
+ ::perfetto::DynamicString{name}, scope)
+#define TRACE_EVENT_COPY_INSTANT1(category_group, name, scope, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, \
+ ::perfetto::DynamicString{name}, scope, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_INSTANT2(category_group, name, scope, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, \
+ ::perfetto::DynamicString{name}, scope, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_INSTANT_WITH_FLAGS0(category_group, name, scope_and_flags) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ scope_and_flags)
+#define TRACE_EVENT_INSTANT_WITH_FLAGS1(category_group, name, scope_and_flags, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ scope_and_flags, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+
+// Instant events with explicit timestamps.
+#define TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(category_group, name, scope, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE | scope)
+
+#define TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(category_group, name, scope, \
+ timestamp, arg_name, arg_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_INSTANT, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE | scope, arg_name, \
+ ::perfetto::internal::PossiblyNull(arg_val))
+
+// Begin events.
+#define TRACE_EVENT_BEGIN0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_BEGIN1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_BEGIN2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD( \
+ TRACE_EVENT_PHASE_BEGIN, category_group, name, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_BEGIN_WITH_FLAGS0(category_group, name, flags) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, flags)
+#define TRACE_EVENT_BEGIN_WITH_FLAGS1(category_group, name, flags, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ flags, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_BEGIN2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, \
+ TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+// Begin events with explicit timestamps.
+#define TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category_group, name, id, \
+ thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( \
+ category_group, name, id, thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, thread_id, timestamp, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP1( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, thread_id, timestamp, \
+ TRACE_EVENT_FLAG_NONE, ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP2( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, thread_id, timestamp, \
+ TRACE_EVENT_FLAG_NONE, ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+// End events.
+#define TRACE_EVENT_END0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_END1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_END2(category_group, name, arg1_name, arg1_val, arg2_name, \
+ arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD( \
+ TRACE_EVENT_PHASE_END, category_group, name, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_END_WITH_FLAGS0(category_group, name, flags) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, flags)
+#define TRACE_EVENT_END_WITH_FLAGS1(category_group, name, flags, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, flags, \
+ arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_END2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD( \
+ TRACE_EVENT_PHASE_END, category_group, ::perfetto::DynamicString{name}, \
+ TRACE_EVENT_FLAG_NONE, ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+// Mark events.
+#define TRACE_EVENT_MARK_WITH_TIMESTAMP0(category_group, name, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(TRACE_EVENT_PHASE_MARK, \
+ category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE)
+
+#define TRACE_EVENT_MARK_WITH_TIMESTAMP1(category_group, name, timestamp, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+
+#define TRACE_EVENT_MARK_WITH_TIMESTAMP2( \
+ category_group, name, timestamp, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+#define TRACE_EVENT_COPY_MARK(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_MARK, category_group, \
+ ::perfetto::DynamicString{name}, \
+ TRACE_EVENT_FLAG_NONE)
+
+#define TRACE_EVENT_COPY_MARK1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD( \
+ TRACE_EVENT_PHASE_MARK, category_group, ::perfetto::DynamicString{name}, \
+ TRACE_EVENT_FLAG_NONE, ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+
+#define TRACE_EVENT_COPY_MARK_WITH_TIMESTAMP(category_group, name, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_MARK, category_group, ::perfetto::DynamicString{name}, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+
+// End events with explicit thread and timestamp.
+#define TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(category_group, name, id, \
+ thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( \
+ category_group, name, id, thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, thread_id, timestamp, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP1( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, thread_id, timestamp, \
+ TRACE_EVENT_FLAG_NONE, ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP2( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, thread_id, timestamp, \
+ TRACE_EVENT_FLAG_NONE, ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+// Counters.
+#define TRACE_COUNTER1(category_group, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, "value", \
+ static_cast<int>(value))
+#define TRACE_COUNTER_WITH_FLAG1(category_group, name, flag, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ flag, "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER1(category_group, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ ::perfetto::DynamicString{name}, \
+ TRACE_EVENT_FLAG_NONE, "value", \
+ static_cast<int>(value))
+#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, value1_name, \
+ static_cast<int>(value1_val), value2_name, \
+ static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER2(category_group, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD( \
+ TRACE_EVENT_PHASE_COUNTER, category_group, \
+ ::perfetto::DynamicString{name}, TRACE_EVENT_FLAG_NONE, value1_name, \
+ static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val))
+
+// Counters with explicit timestamps.
+#define TRACE_COUNTER_WITH_TIMESTAMP1(category_group, name, timestamp, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value))
+
+#define TRACE_COUNTER_WITH_TIMESTAMP2(category_group, name, timestamp, \
+ value1_name, value1_val, value2_name, \
+ value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Counters with ids.
+#define TRACE_COUNTER_ID1(category_group, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, "value", \
+ static_cast<int>(value))
+#define TRACE_COPY_COUNTER_ID1(category_group, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ ::perfetto::DynamicString{name}, id, \
+ TRACE_EVENT_FLAG_NONE, "value", \
+ static_cast<int>(value))
+#define TRACE_COUNTER_ID2(category_group, name, id, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER_ID2(category_group, name, id, value1_name, \
+ value1_val, value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_COUNTER, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE, value1_name, \
+ static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val))
+
+// Sampling profiler events.
+#define TRACE_EVENT_SAMPLE_WITH_ID1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_SAMPLE, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \
+ arg1_val)
+
+// Legacy async events.
+#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_FLAGS0(category_group, name, id, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, flags)
+
+// Legacy async events with explicit timestamps.
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \
+ category_group, name, id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0( \
+ category_group, name, id, timestamp, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(category_group, name, \
+ id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP2(category_group, name, id, \
+ timestamp, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_API_CURRENT_THREAD_ID, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0( \
+ category_group, name, id, timestamp, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags)
+
+// Legacy async step into events.
+#define TRACE_EVENT_ASYNC_STEP_INTO0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP_INTO1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+
+// Legacy async step into events with timestamps.
+#define TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category_group, name, id, \
+ step, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ "step", step)
+
+// Legacy async step past events.
+#define TRACE_EVENT_ASYNC_STEP_PAST0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP_PAST1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_STEP_PAST, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+
+// Legacy async end events.
+#define TRACE_EVENT_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_ASYNC_END2(category_group, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_ASYNC_END1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_ASYNC_END2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_ASYNC_END_WITH_FLAGS0(category_group, name, id, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, flags)
+
+// Legacy async end events with explicit timestamps.
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1(category_group, name, id, \
+ timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP2(category_group, name, id, \
+ timestamp, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_ASYNC_END_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_API_CURRENT_THREAD_ID, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0(category_group, name, \
+ id, timestamp, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags)
+
+// Async events.
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_FLAGS0(category_group, name, id, \
+ flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
+ category_group, name, id, flags)
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1( \
+ category_group, name, id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val))
+
+// Async end events.
+#define TRACE_EVENT_NESTABLE_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_END1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_END2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_FLAGS0(category_group, name, id, \
+ flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
+ category_group, name, id, flags)
+
+// Async instant events.
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(category_group, name, id, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TTS2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_ASYNC_TTS, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TTS2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_ASYNC_TTS, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+// Async events with explicit timestamps.
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, \
+ id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(category_group, name, \
+ id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1( \
+ category_group, name, id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP2( \
+ category_group, name, id, timestamp, arg1_name, arg1_val, arg2_name, \
+ arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, ::perfetto::internal::PossiblyNull(arg1_val), arg2_name, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0( \
+ category_group, name, id, timestamp, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags)
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0( \
+ category_group, name, id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN1(category_group, name, id, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( \
+ category_group, name, id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_API_CURRENT_THREAD_ID, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1( \
+ category_group, name, id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_API_CURRENT_THREAD_ID, \
+ timestamp, TRACE_EVENT_FLAG_NONE, ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( \
+ category_group, name, id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, \
+ ::perfetto::DynamicString{name}, id, TRACE_EVENT_API_CURRENT_THREAD_ID, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP2( \
+ category_group, name, id, timestamp, arg1_name, arg1_val, arg2_name, \
+ arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ ::perfetto::DynamicString{arg1_name}, \
+ ::perfetto::internal::PossiblyNull(arg1_val), \
+ ::perfetto::DynamicString{arg2_name}, \
+ ::perfetto::internal::PossiblyNull(arg2_val))
+
+// Metadata events.
+#define TRACE_EVENT_METADATA1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_METADATA_ADD( \
+ category_group, name, arg1_name, \
+ ::perfetto::internal::PossiblyNull(arg1_val))
+
+// Clock sync events.
+#define TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_CLOCK_SYNC, "__metadata", \
+ "clock_sync", TRACE_EVENT_FLAG_NONE, "sync_id", \
+ sync_id)
+#define TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_CLOCK_SYNC, "__metadata", "clock_sync", issue_end_ts, \
+ TRACE_EVENT_FLAG_NONE, "sync_id", sync_id, "issue_ts", issue_ts)
+
+// Object events.
+#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+
+#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \
+ snapshot) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "snapshot", snapshot)
+
+#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP( \
+ category_group, name, id, timestamp, snapshot) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ "snapshot", snapshot)
+
+#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_DELETE_OBJECT, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+
+// TODO(skyostil): Implement binary-efficient trace events.
+#define TRACE_EVENT_BINARY_EFFICIENT0 TRACE_EVENT0
+#define TRACE_EVENT_BINARY_EFFICIENT1 TRACE_EVENT1
+#define TRACE_EVENT_BINARY_EFFICIENT2 TRACE_EVENT2
+
+// Macro to efficiently determine if a given category group is enabled.
+#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category, ret) \
+ do { \
+ *ret = TRACE_EVENT_CATEGORY_ENABLED(category); \
+ } while (0)
+
+// Macro to efficiently determine, through polling, if a new trace has begun.
+#define TRACE_EVENT_IS_NEW_TRACE(ret) \
+ do { \
+ static int PERFETTO_UID(prev) = -1; \
+ int PERFETTO_UID(curr) = \
+ ::perfetto::internal::TrackEventInternal::GetSessionCount(); \
+ if (PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::IsEnabled() && \
+ (PERFETTO_UID(prev) != PERFETTO_UID(curr))) { \
+ *(ret) = true; \
+ PERFETTO_UID(prev) = PERFETTO_UID(curr); \
+ } else { \
+ *(ret) = false; \
+ } \
+ } while (0)
+
+// ----------------------------------------------------------------------------
+// Legacy tracing API (adapted from trace_event.h).
+// ----------------------------------------------------------------------------
+
+// We can implement the following subset of the legacy tracing API without
+// involvement from the embedder. APIs such as TRACE_EVENT_API_ADD_TRACE_EVENT
+// are still up to the embedder to define.
+
+#define TRACE_STR_COPY(str) \
+ ::perfetto::DynamicString { ::perfetto::internal::PossiblyNull(str) }
+
+#define TRACE_ID_WITH_SCOPE(scope, ...) \
+ ::perfetto::internal::LegacyTraceId::WithScope(scope, ##__VA_ARGS__)
+
+// Use this for ids that are unique across processes. This allows different
+// processes to use the same id to refer to the same event.
+#define TRACE_ID_GLOBAL(id) ::perfetto::internal::LegacyTraceId::GlobalId(id)
+
+// Use this for ids that are unique within a single process. This allows
+// different processes to use the same id to refer to different events.
+#define TRACE_ID_LOCAL(id) ::perfetto::internal::LegacyTraceId::LocalId(id)
+
+// Returns a pointer to a uint8_t which indicates whether tracing is enabled for
+// the given category or not. A zero value means tracing is disabled and
+// non-zero indicates at least one tracing session for this category is active.
+// Note that callers should not make any assumptions at what each bit represents
+// in the status byte. Does not support dynamic categories.
+#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category) \
+ reinterpret_cast<const uint8_t*>( \
+ [&] { \
+ static_assert( \
+ !std::is_same<::perfetto::DynamicCategory, \
+ decltype(category)>::value, \
+ "Enabled flag pointers are not supported for dynamic trace " \
+ "categories."); \
+ }, \
+ PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
+ .GetCategoryState( \
+ PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
+ .Find(category, /*is_dynamic=*/false)))
+
+// Given a pointer returned by TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED,
+// yields a pointer to the name of the corresponding category group.
+#define TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(category_enabled_ptr) \
+ PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
+ .GetCategory( \
+ category_enabled_ptr - \
+ reinterpret_cast<const uint8_t*>( \
+ PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
+ .GetCategoryState(0u))) \
+ ->name
+
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_H_
+#define INCLUDE_PERFETTO_TRACING_H_
+
+// This headers wraps all the headers necessary to use the public Perfetto
+// Tracing API. Embedders should preferably use this one header to avoid having
+// to figure out the various set of header required for each class.
+// The only exception to this should be large projects where build time is a
+// concern (e.g. chromium), which migh prefer sticking to strict IWYU.
+
+// gen_amalgamated expanded: #include "perfetto/base/time.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/console_interceptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/data_source_descriptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/core/trace_config.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/data_source.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/platform.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_interned_data_index.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_legacy.h"
+// gen_amalgamated expanded: #include "perfetto/tracing/track_event_state_tracker.h"
+
+#endif // INCLUDE_PERFETTO_TRACING_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/android_energy_consumer_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_ENERGY_CONSUMER_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_ENERGY_CONSUMER_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidEnergyConsumerDescriptor;
+class AndroidEnergyConsumer;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT AndroidEnergyConsumerDescriptor : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kEnergyConsumersFieldNumber = 1,
+ };
+
+ AndroidEnergyConsumerDescriptor();
+ ~AndroidEnergyConsumerDescriptor() override;
+ AndroidEnergyConsumerDescriptor(AndroidEnergyConsumerDescriptor&&) noexcept;
+ AndroidEnergyConsumerDescriptor& operator=(AndroidEnergyConsumerDescriptor&&);
+ AndroidEnergyConsumerDescriptor(const AndroidEnergyConsumerDescriptor&);
+ AndroidEnergyConsumerDescriptor& operator=(const AndroidEnergyConsumerDescriptor&);
+ bool operator==(const AndroidEnergyConsumerDescriptor&) const;
+ bool operator!=(const AndroidEnergyConsumerDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<AndroidEnergyConsumer>& energy_consumers() const { return energy_consumers_; }
+ std::vector<AndroidEnergyConsumer>* mutable_energy_consumers() { return &energy_consumers_; }
+ int energy_consumers_size() const;
+ void clear_energy_consumers();
+ AndroidEnergyConsumer* add_energy_consumers();
+
+ private:
+ std::vector<AndroidEnergyConsumer> energy_consumers_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT AndroidEnergyConsumer : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kEnergyConsumerIdFieldNumber = 1,
+ kOrdinalFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kNameFieldNumber = 4,
+ };
+
+ AndroidEnergyConsumer();
+ ~AndroidEnergyConsumer() override;
+ AndroidEnergyConsumer(AndroidEnergyConsumer&&) noexcept;
+ AndroidEnergyConsumer& operator=(AndroidEnergyConsumer&&);
+ AndroidEnergyConsumer(const AndroidEnergyConsumer&);
+ AndroidEnergyConsumer& operator=(const AndroidEnergyConsumer&);
+ bool operator==(const AndroidEnergyConsumer&) const;
+ bool operator!=(const AndroidEnergyConsumer& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_energy_consumer_id() const { return _has_field_[1]; }
+ int32_t energy_consumer_id() const { return energy_consumer_id_; }
+ void set_energy_consumer_id(int32_t value) { energy_consumer_id_ = value; _has_field_.set(1); }
+
+ bool has_ordinal() const { return _has_field_[2]; }
+ int32_t ordinal() const { return ordinal_; }
+ void set_ordinal(int32_t value) { ordinal_ = value; _has_field_.set(2); }
+
+ bool has_type() const { return _has_field_[3]; }
+ const std::string& type() const { return type_; }
+ void set_type(const std::string& value) { type_ = value; _has_field_.set(3); }
+
+ bool has_name() const { return _has_field_[4]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(4); }
+
+ private:
+ int32_t energy_consumer_id_{};
+ int32_t ordinal_{};
+ std::string type_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_ENERGY_CONSUMER_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/android_log_constants.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_LOG_CONSTANTS_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_LOG_CONSTANTS_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum AndroidLogId : int;
+enum AndroidLogPriority : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum AndroidLogId : int {
+ LID_DEFAULT = 0,
+ LID_RADIO = 1,
+ LID_EVENTS = 2,
+ LID_SYSTEM = 3,
+ LID_CRASH = 4,
+ LID_STATS = 5,
+ LID_SECURITY = 6,
+ LID_KERNEL = 7,
+};
+enum AndroidLogPriority : int {
+ PRIO_UNSPECIFIED = 0,
+ PRIO_UNUSED = 1,
+ PRIO_VERBOSE = 2,
+ PRIO_DEBUG = 3,
+ PRIO_INFO = 4,
+ PRIO_WARN = 5,
+ PRIO_ERROR = 6,
+ PRIO_FATAL = 7,
+};
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_LOG_CONSTANTS_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/builtin_clock.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum BuiltinClock : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum BuiltinClock : int {
+ BUILTIN_CLOCK_UNKNOWN = 0,
+ BUILTIN_CLOCK_REALTIME = 1,
+ BUILTIN_CLOCK_REALTIME_COARSE = 2,
+ BUILTIN_CLOCK_MONOTONIC = 3,
+ BUILTIN_CLOCK_MONOTONIC_COARSE = 4,
+ BUILTIN_CLOCK_MONOTONIC_RAW = 5,
+ BUILTIN_CLOCK_BOOTTIME = 6,
+ BUILTIN_CLOCK_MAX_ID = 63,
+};
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/commit_data_request.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_COMMIT_DATA_REQUEST_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_COMMIT_DATA_REQUEST_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class CommitDataRequest;
+class CommitDataRequest_ChunkToPatch;
+class CommitDataRequest_ChunkToPatch_Patch;
+class CommitDataRequest_ChunksToMove;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT CommitDataRequest : public ::protozero::CppMessageObj {
+ public:
+ using ChunksToMove = CommitDataRequest_ChunksToMove;
+ using ChunkToPatch = CommitDataRequest_ChunkToPatch;
+ enum FieldNumbers {
+ kChunksToMoveFieldNumber = 1,
+ kChunksToPatchFieldNumber = 2,
+ kFlushRequestIdFieldNumber = 3,
+ };
+
+ CommitDataRequest();
+ ~CommitDataRequest() override;
+ CommitDataRequest(CommitDataRequest&&) noexcept;
+ CommitDataRequest& operator=(CommitDataRequest&&);
+ CommitDataRequest(const CommitDataRequest&);
+ CommitDataRequest& operator=(const CommitDataRequest&);
+ bool operator==(const CommitDataRequest&) const;
+ bool operator!=(const CommitDataRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<CommitDataRequest_ChunksToMove>& chunks_to_move() const { return chunks_to_move_; }
+ std::vector<CommitDataRequest_ChunksToMove>* mutable_chunks_to_move() { return &chunks_to_move_; }
+ int chunks_to_move_size() const;
+ void clear_chunks_to_move();
+ CommitDataRequest_ChunksToMove* add_chunks_to_move();
+
+ const std::vector<CommitDataRequest_ChunkToPatch>& chunks_to_patch() const { return chunks_to_patch_; }
+ std::vector<CommitDataRequest_ChunkToPatch>* mutable_chunks_to_patch() { return &chunks_to_patch_; }
+ int chunks_to_patch_size() const;
+ void clear_chunks_to_patch();
+ CommitDataRequest_ChunkToPatch* add_chunks_to_patch();
+
+ bool has_flush_request_id() const { return _has_field_[3]; }
+ uint64_t flush_request_id() const { return flush_request_id_; }
+ void set_flush_request_id(uint64_t value) { flush_request_id_ = value; _has_field_.set(3); }
+
+ private:
+ std::vector<CommitDataRequest_ChunksToMove> chunks_to_move_;
+ std::vector<CommitDataRequest_ChunkToPatch> chunks_to_patch_;
+ uint64_t flush_request_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT CommitDataRequest_ChunkToPatch : public ::protozero::CppMessageObj {
+ public:
+ using Patch = CommitDataRequest_ChunkToPatch_Patch;
+ enum FieldNumbers {
+ kTargetBufferFieldNumber = 1,
+ kWriterIdFieldNumber = 2,
+ kChunkIdFieldNumber = 3,
+ kPatchesFieldNumber = 4,
+ kHasMorePatchesFieldNumber = 5,
+ };
+
+ CommitDataRequest_ChunkToPatch();
+ ~CommitDataRequest_ChunkToPatch() override;
+ CommitDataRequest_ChunkToPatch(CommitDataRequest_ChunkToPatch&&) noexcept;
+ CommitDataRequest_ChunkToPatch& operator=(CommitDataRequest_ChunkToPatch&&);
+ CommitDataRequest_ChunkToPatch(const CommitDataRequest_ChunkToPatch&);
+ CommitDataRequest_ChunkToPatch& operator=(const CommitDataRequest_ChunkToPatch&);
+ bool operator==(const CommitDataRequest_ChunkToPatch&) const;
+ bool operator!=(const CommitDataRequest_ChunkToPatch& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_target_buffer() const { return _has_field_[1]; }
+ uint32_t target_buffer() const { return target_buffer_; }
+ void set_target_buffer(uint32_t value) { target_buffer_ = value; _has_field_.set(1); }
+
+ bool has_writer_id() const { return _has_field_[2]; }
+ uint32_t writer_id() const { return writer_id_; }
+ void set_writer_id(uint32_t value) { writer_id_ = value; _has_field_.set(2); }
+
+ bool has_chunk_id() const { return _has_field_[3]; }
+ uint32_t chunk_id() const { return chunk_id_; }
+ void set_chunk_id(uint32_t value) { chunk_id_ = value; _has_field_.set(3); }
+
+ const std::vector<CommitDataRequest_ChunkToPatch_Patch>& patches() const { return patches_; }
+ std::vector<CommitDataRequest_ChunkToPatch_Patch>* mutable_patches() { return &patches_; }
+ int patches_size() const;
+ void clear_patches();
+ CommitDataRequest_ChunkToPatch_Patch* add_patches();
+
+ bool has_has_more_patches() const { return _has_field_[5]; }
+ bool has_more_patches() const { return has_more_patches_; }
+ void set_has_more_patches(bool value) { has_more_patches_ = value; _has_field_.set(5); }
+
+ private:
+ uint32_t target_buffer_{};
+ uint32_t writer_id_{};
+ uint32_t chunk_id_{};
+ std::vector<CommitDataRequest_ChunkToPatch_Patch> patches_;
+ bool has_more_patches_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT CommitDataRequest_ChunkToPatch_Patch : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kOffsetFieldNumber = 1,
+ kDataFieldNumber = 2,
+ };
+
+ CommitDataRequest_ChunkToPatch_Patch();
+ ~CommitDataRequest_ChunkToPatch_Patch() override;
+ CommitDataRequest_ChunkToPatch_Patch(CommitDataRequest_ChunkToPatch_Patch&&) noexcept;
+ CommitDataRequest_ChunkToPatch_Patch& operator=(CommitDataRequest_ChunkToPatch_Patch&&);
+ CommitDataRequest_ChunkToPatch_Patch(const CommitDataRequest_ChunkToPatch_Patch&);
+ CommitDataRequest_ChunkToPatch_Patch& operator=(const CommitDataRequest_ChunkToPatch_Patch&);
+ bool operator==(const CommitDataRequest_ChunkToPatch_Patch&) const;
+ bool operator!=(const CommitDataRequest_ChunkToPatch_Patch& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_offset() const { return _has_field_[1]; }
+ uint32_t offset() const { return offset_; }
+ void set_offset(uint32_t value) { offset_ = value; _has_field_.set(1); }
+
+ bool has_data() const { return _has_field_[2]; }
+ const std::string& data() const { return data_; }
+ void set_data(const std::string& value) { data_ = value; _has_field_.set(2); }
+ void set_data(const void* p, size_t s) { data_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(2); }
+
+ private:
+ uint32_t offset_{};
+ std::string data_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT CommitDataRequest_ChunksToMove : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPageFieldNumber = 1,
+ kChunkFieldNumber = 2,
+ kTargetBufferFieldNumber = 3,
+ kDataFieldNumber = 4,
+ };
+
+ CommitDataRequest_ChunksToMove();
+ ~CommitDataRequest_ChunksToMove() override;
+ CommitDataRequest_ChunksToMove(CommitDataRequest_ChunksToMove&&) noexcept;
+ CommitDataRequest_ChunksToMove& operator=(CommitDataRequest_ChunksToMove&&);
+ CommitDataRequest_ChunksToMove(const CommitDataRequest_ChunksToMove&);
+ CommitDataRequest_ChunksToMove& operator=(const CommitDataRequest_ChunksToMove&);
+ bool operator==(const CommitDataRequest_ChunksToMove&) const;
+ bool operator!=(const CommitDataRequest_ChunksToMove& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_page() const { return _has_field_[1]; }
+ uint32_t page() const { return page_; }
+ void set_page(uint32_t value) { page_ = value; _has_field_.set(1); }
+
+ bool has_chunk() const { return _has_field_[2]; }
+ uint32_t chunk() const { return chunk_; }
+ void set_chunk(uint32_t value) { chunk_ = value; _has_field_.set(2); }
+
+ bool has_target_buffer() const { return _has_field_[3]; }
+ uint32_t target_buffer() const { return target_buffer_; }
+ void set_target_buffer(uint32_t value) { target_buffer_ = value; _has_field_.set(3); }
+
+ bool has_data() const { return _has_field_[4]; }
+ const std::string& data() const { return data_; }
+ void set_data(const std::string& value) { data_ = value; _has_field_.set(4); }
+ void set_data(const void* p, size_t s) { data_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(4); }
+
+ private:
+ uint32_t page_{};
+ uint32_t chunk_{};
+ uint32_t target_buffer_{};
+ std::string data_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_COMMIT_DATA_REQUEST_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class OneofOptions;
+class EnumValueDescriptorProto;
+class EnumDescriptorProto;
+class OneofDescriptorProto;
+class FieldDescriptorProto;
+class FieldOptions;
+class UninterpretedOption;
+class UninterpretedOption_NamePart;
+class DescriptorProto;
+class DescriptorProto_ReservedRange;
+class FileDescriptorProto;
+class FileDescriptorSet;
+enum FieldDescriptorProto_Type : int;
+enum FieldDescriptorProto_Label : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum FieldDescriptorProto_Type : int {
+ FieldDescriptorProto_Type_TYPE_DOUBLE = 1,
+ FieldDescriptorProto_Type_TYPE_FLOAT = 2,
+ FieldDescriptorProto_Type_TYPE_INT64 = 3,
+ FieldDescriptorProto_Type_TYPE_UINT64 = 4,
+ FieldDescriptorProto_Type_TYPE_INT32 = 5,
+ FieldDescriptorProto_Type_TYPE_FIXED64 = 6,
+ FieldDescriptorProto_Type_TYPE_FIXED32 = 7,
+ FieldDescriptorProto_Type_TYPE_BOOL = 8,
+ FieldDescriptorProto_Type_TYPE_STRING = 9,
+ FieldDescriptorProto_Type_TYPE_GROUP = 10,
+ FieldDescriptorProto_Type_TYPE_MESSAGE = 11,
+ FieldDescriptorProto_Type_TYPE_BYTES = 12,
+ FieldDescriptorProto_Type_TYPE_UINT32 = 13,
+ FieldDescriptorProto_Type_TYPE_ENUM = 14,
+ FieldDescriptorProto_Type_TYPE_SFIXED32 = 15,
+ FieldDescriptorProto_Type_TYPE_SFIXED64 = 16,
+ FieldDescriptorProto_Type_TYPE_SINT32 = 17,
+ FieldDescriptorProto_Type_TYPE_SINT64 = 18,
+};
+enum FieldDescriptorProto_Label : int {
+ FieldDescriptorProto_Label_LABEL_OPTIONAL = 1,
+ FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
+ FieldDescriptorProto_Label_LABEL_REPEATED = 3,
+};
+
+class PERFETTO_EXPORT_COMPONENT OneofOptions : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ OneofOptions();
+ ~OneofOptions() override;
+ OneofOptions(OneofOptions&&) noexcept;
+ OneofOptions& operator=(OneofOptions&&);
+ OneofOptions(const OneofOptions&);
+ OneofOptions& operator=(const OneofOptions&);
+ bool operator==(const OneofOptions&) const;
+ bool operator!=(const OneofOptions& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT EnumValueDescriptorProto : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kNumberFieldNumber = 2,
+ };
+
+ EnumValueDescriptorProto();
+ ~EnumValueDescriptorProto() override;
+ EnumValueDescriptorProto(EnumValueDescriptorProto&&) noexcept;
+ EnumValueDescriptorProto& operator=(EnumValueDescriptorProto&&);
+ EnumValueDescriptorProto(const EnumValueDescriptorProto&);
+ EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto&);
+ bool operator==(const EnumValueDescriptorProto&) const;
+ bool operator!=(const EnumValueDescriptorProto& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_number() const { return _has_field_[2]; }
+ int32_t number() const { return number_; }
+ void set_number(int32_t value) { number_ = value; _has_field_.set(2); }
+
+ private:
+ std::string name_{};
+ int32_t number_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT EnumDescriptorProto : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kValueFieldNumber = 2,
+ kReservedNameFieldNumber = 5,
+ };
+
+ EnumDescriptorProto();
+ ~EnumDescriptorProto() override;
+ EnumDescriptorProto(EnumDescriptorProto&&) noexcept;
+ EnumDescriptorProto& operator=(EnumDescriptorProto&&);
+ EnumDescriptorProto(const EnumDescriptorProto&);
+ EnumDescriptorProto& operator=(const EnumDescriptorProto&);
+ bool operator==(const EnumDescriptorProto&) const;
+ bool operator!=(const EnumDescriptorProto& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ const std::vector<EnumValueDescriptorProto>& value() const { return value_; }
+ std::vector<EnumValueDescriptorProto>* mutable_value() { return &value_; }
+ int value_size() const;
+ void clear_value();
+ EnumValueDescriptorProto* add_value();
+
+ const std::vector<std::string>& reserved_name() const { return reserved_name_; }
+ std::vector<std::string>* mutable_reserved_name() { return &reserved_name_; }
+ int reserved_name_size() const { return static_cast<int>(reserved_name_.size()); }
+ void clear_reserved_name() { reserved_name_.clear(); }
+ void add_reserved_name(std::string value) { reserved_name_.emplace_back(value); }
+ std::string* add_reserved_name() { reserved_name_.emplace_back(); return &reserved_name_.back(); }
+
+ private:
+ std::string name_{};
+ std::vector<EnumValueDescriptorProto> value_;
+ std::vector<std::string> reserved_name_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT OneofDescriptorProto : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kOptionsFieldNumber = 2,
+ };
+
+ OneofDescriptorProto();
+ ~OneofDescriptorProto() override;
+ OneofDescriptorProto(OneofDescriptorProto&&) noexcept;
+ OneofDescriptorProto& operator=(OneofDescriptorProto&&);
+ OneofDescriptorProto(const OneofDescriptorProto&);
+ OneofDescriptorProto& operator=(const OneofDescriptorProto&);
+ bool operator==(const OneofDescriptorProto&) const;
+ bool operator!=(const OneofDescriptorProto& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_options() const { return _has_field_[2]; }
+ const OneofOptions& options() const { return *options_; }
+ OneofOptions* mutable_options() { _has_field_.set(2); return options_.get(); }
+
+ private:
+ std::string name_{};
+ ::protozero::CopyablePtr<OneofOptions> options_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FieldDescriptorProto : public ::protozero::CppMessageObj {
+ public:
+ using Type = FieldDescriptorProto_Type;
+ static constexpr auto TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE;
+ static constexpr auto TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT;
+ static constexpr auto TYPE_INT64 = FieldDescriptorProto_Type_TYPE_INT64;
+ static constexpr auto TYPE_UINT64 = FieldDescriptorProto_Type_TYPE_UINT64;
+ static constexpr auto TYPE_INT32 = FieldDescriptorProto_Type_TYPE_INT32;
+ static constexpr auto TYPE_FIXED64 = FieldDescriptorProto_Type_TYPE_FIXED64;
+ static constexpr auto TYPE_FIXED32 = FieldDescriptorProto_Type_TYPE_FIXED32;
+ static constexpr auto TYPE_BOOL = FieldDescriptorProto_Type_TYPE_BOOL;
+ static constexpr auto TYPE_STRING = FieldDescriptorProto_Type_TYPE_STRING;
+ static constexpr auto TYPE_GROUP = FieldDescriptorProto_Type_TYPE_GROUP;
+ static constexpr auto TYPE_MESSAGE = FieldDescriptorProto_Type_TYPE_MESSAGE;
+ static constexpr auto TYPE_BYTES = FieldDescriptorProto_Type_TYPE_BYTES;
+ static constexpr auto TYPE_UINT32 = FieldDescriptorProto_Type_TYPE_UINT32;
+ static constexpr auto TYPE_ENUM = FieldDescriptorProto_Type_TYPE_ENUM;
+ static constexpr auto TYPE_SFIXED32 = FieldDescriptorProto_Type_TYPE_SFIXED32;
+ static constexpr auto TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64;
+ static constexpr auto TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32;
+ static constexpr auto TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64;
+ static constexpr auto Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE;
+ static constexpr auto Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64;
+ using Label = FieldDescriptorProto_Label;
+ static constexpr auto LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
+ static constexpr auto LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
+ static constexpr auto LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED;
+ static constexpr auto Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL;
+ static constexpr auto Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED;
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kNumberFieldNumber = 3,
+ kLabelFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ kTypeNameFieldNumber = 6,
+ kExtendeeFieldNumber = 2,
+ kDefaultValueFieldNumber = 7,
+ kOptionsFieldNumber = 8,
+ kOneofIndexFieldNumber = 9,
+ };
+
+ FieldDescriptorProto();
+ ~FieldDescriptorProto() override;
+ FieldDescriptorProto(FieldDescriptorProto&&) noexcept;
+ FieldDescriptorProto& operator=(FieldDescriptorProto&&);
+ FieldDescriptorProto(const FieldDescriptorProto&);
+ FieldDescriptorProto& operator=(const FieldDescriptorProto&);
+ bool operator==(const FieldDescriptorProto&) const;
+ bool operator!=(const FieldDescriptorProto& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_number() const { return _has_field_[3]; }
+ int32_t number() const { return number_; }
+ void set_number(int32_t value) { number_ = value; _has_field_.set(3); }
+
+ bool has_label() const { return _has_field_[4]; }
+ FieldDescriptorProto_Label label() const { return label_; }
+ void set_label(FieldDescriptorProto_Label value) { label_ = value; _has_field_.set(4); }
+
+ bool has_type() const { return _has_field_[5]; }
+ FieldDescriptorProto_Type type() const { return type_; }
+ void set_type(FieldDescriptorProto_Type value) { type_ = value; _has_field_.set(5); }
+
+ bool has_type_name() const { return _has_field_[6]; }
+ const std::string& type_name() const { return type_name_; }
+ void set_type_name(const std::string& value) { type_name_ = value; _has_field_.set(6); }
+
+ bool has_extendee() const { return _has_field_[2]; }
+ const std::string& extendee() const { return extendee_; }
+ void set_extendee(const std::string& value) { extendee_ = value; _has_field_.set(2); }
+
+ bool has_default_value() const { return _has_field_[7]; }
+ const std::string& default_value() const { return default_value_; }
+ void set_default_value(const std::string& value) { default_value_ = value; _has_field_.set(7); }
+
+ bool has_options() const { return _has_field_[8]; }
+ const FieldOptions& options() const { return *options_; }
+ FieldOptions* mutable_options() { _has_field_.set(8); return options_.get(); }
+
+ bool has_oneof_index() const { return _has_field_[9]; }
+ int32_t oneof_index() const { return oneof_index_; }
+ void set_oneof_index(int32_t value) { oneof_index_ = value; _has_field_.set(9); }
+
+ private:
+ std::string name_{};
+ int32_t number_{};
+ FieldDescriptorProto_Label label_{};
+ FieldDescriptorProto_Type type_{};
+ std::string type_name_{};
+ std::string extendee_{};
+ std::string default_value_{};
+ ::protozero::CopyablePtr<FieldOptions> options_;
+ int32_t oneof_index_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<10> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FieldOptions : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPackedFieldNumber = 2,
+ kUninterpretedOptionFieldNumber = 999,
+ };
+
+ FieldOptions();
+ ~FieldOptions() override;
+ FieldOptions(FieldOptions&&) noexcept;
+ FieldOptions& operator=(FieldOptions&&);
+ FieldOptions(const FieldOptions&);
+ FieldOptions& operator=(const FieldOptions&);
+ bool operator==(const FieldOptions&) const;
+ bool operator!=(const FieldOptions& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_packed() const { return _has_field_[2]; }
+ bool packed() const { return packed_; }
+ void set_packed(bool value) { packed_ = value; _has_field_.set(2); }
+
+ const std::vector<UninterpretedOption>& uninterpreted_option() const { return uninterpreted_option_; }
+ std::vector<UninterpretedOption>* mutable_uninterpreted_option() { return &uninterpreted_option_; }
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
+ UninterpretedOption* add_uninterpreted_option();
+
+ private:
+ bool packed_{};
+ std::vector<UninterpretedOption> uninterpreted_option_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<1000> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UninterpretedOption : public ::protozero::CppMessageObj {
+ public:
+ using NamePart = UninterpretedOption_NamePart;
+ enum FieldNumbers {
+ kNameFieldNumber = 2,
+ kIdentifierValueFieldNumber = 3,
+ kPositiveIntValueFieldNumber = 4,
+ kNegativeIntValueFieldNumber = 5,
+ kDoubleValueFieldNumber = 6,
+ kStringValueFieldNumber = 7,
+ kAggregateValueFieldNumber = 8,
+ };
+
+ UninterpretedOption();
+ ~UninterpretedOption() override;
+ UninterpretedOption(UninterpretedOption&&) noexcept;
+ UninterpretedOption& operator=(UninterpretedOption&&);
+ UninterpretedOption(const UninterpretedOption&);
+ UninterpretedOption& operator=(const UninterpretedOption&);
+ bool operator==(const UninterpretedOption&) const;
+ bool operator!=(const UninterpretedOption& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<UninterpretedOption_NamePart>& name() const { return name_; }
+ std::vector<UninterpretedOption_NamePart>* mutable_name() { return &name_; }
+ int name_size() const;
+ void clear_name();
+ UninterpretedOption_NamePart* add_name();
+
+ bool has_identifier_value() const { return _has_field_[3]; }
+ const std::string& identifier_value() const { return identifier_value_; }
+ void set_identifier_value(const std::string& value) { identifier_value_ = value; _has_field_.set(3); }
+
+ bool has_positive_int_value() const { return _has_field_[4]; }
+ uint64_t positive_int_value() const { return positive_int_value_; }
+ void set_positive_int_value(uint64_t value) { positive_int_value_ = value; _has_field_.set(4); }
+
+ bool has_negative_int_value() const { return _has_field_[5]; }
+ int64_t negative_int_value() const { return negative_int_value_; }
+ void set_negative_int_value(int64_t value) { negative_int_value_ = value; _has_field_.set(5); }
+
+ bool has_double_value() const { return _has_field_[6]; }
+ double double_value() const { return double_value_; }
+ void set_double_value(double value) { double_value_ = value; _has_field_.set(6); }
+
+ bool has_string_value() const { return _has_field_[7]; }
+ const std::string& string_value() const { return string_value_; }
+ void set_string_value(const std::string& value) { string_value_ = value; _has_field_.set(7); }
+ void set_string_value(const void* p, size_t s) { string_value_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(7); }
+
+ bool has_aggregate_value() const { return _has_field_[8]; }
+ const std::string& aggregate_value() const { return aggregate_value_; }
+ void set_aggregate_value(const std::string& value) { aggregate_value_ = value; _has_field_.set(8); }
+
+ private:
+ std::vector<UninterpretedOption_NamePart> name_;
+ std::string identifier_value_{};
+ uint64_t positive_int_value_{};
+ int64_t negative_int_value_{};
+ double double_value_{};
+ std::string string_value_{};
+ std::string aggregate_value_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UninterpretedOption_NamePart : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNamePartFieldNumber = 1,
+ kIsExtensionFieldNumber = 2,
+ };
+
+ UninterpretedOption_NamePart();
+ ~UninterpretedOption_NamePart() override;
+ UninterpretedOption_NamePart(UninterpretedOption_NamePart&&) noexcept;
+ UninterpretedOption_NamePart& operator=(UninterpretedOption_NamePart&&);
+ UninterpretedOption_NamePart(const UninterpretedOption_NamePart&);
+ UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart&);
+ bool operator==(const UninterpretedOption_NamePart&) const;
+ bool operator!=(const UninterpretedOption_NamePart& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name_part() const { return _has_field_[1]; }
+ const std::string& name_part() const { return name_part_; }
+ void set_name_part(const std::string& value) { name_part_ = value; _has_field_.set(1); }
+
+ bool has_is_extension() const { return _has_field_[2]; }
+ bool is_extension() const { return is_extension_; }
+ void set_is_extension(bool value) { is_extension_ = value; _has_field_.set(2); }
+
+ private:
+ std::string name_part_{};
+ bool is_extension_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DescriptorProto : public ::protozero::CppMessageObj {
+ public:
+ using ReservedRange = DescriptorProto_ReservedRange;
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kFieldFieldNumber = 2,
+ kExtensionFieldNumber = 6,
+ kNestedTypeFieldNumber = 3,
+ kEnumTypeFieldNumber = 4,
+ kOneofDeclFieldNumber = 8,
+ kReservedRangeFieldNumber = 9,
+ kReservedNameFieldNumber = 10,
+ };
+
+ DescriptorProto();
+ ~DescriptorProto() override;
+ DescriptorProto(DescriptorProto&&) noexcept;
+ DescriptorProto& operator=(DescriptorProto&&);
+ DescriptorProto(const DescriptorProto&);
+ DescriptorProto& operator=(const DescriptorProto&);
+ bool operator==(const DescriptorProto&) const;
+ bool operator!=(const DescriptorProto& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ const std::vector<FieldDescriptorProto>& field() const { return field_; }
+ std::vector<FieldDescriptorProto>* mutable_field() { return &field_; }
+ int field_size() const;
+ void clear_field();
+ FieldDescriptorProto* add_field();
+
+ const std::vector<FieldDescriptorProto>& extension() const { return extension_; }
+ std::vector<FieldDescriptorProto>* mutable_extension() { return &extension_; }
+ int extension_size() const;
+ void clear_extension();
+ FieldDescriptorProto* add_extension();
+
+ const std::vector<DescriptorProto>& nested_type() const { return nested_type_; }
+ std::vector<DescriptorProto>* mutable_nested_type() { return &nested_type_; }
+ int nested_type_size() const;
+ void clear_nested_type();
+ DescriptorProto* add_nested_type();
+
+ const std::vector<EnumDescriptorProto>& enum_type() const { return enum_type_; }
+ std::vector<EnumDescriptorProto>* mutable_enum_type() { return &enum_type_; }
+ int enum_type_size() const;
+ void clear_enum_type();
+ EnumDescriptorProto* add_enum_type();
+
+ const std::vector<OneofDescriptorProto>& oneof_decl() const { return oneof_decl_; }
+ std::vector<OneofDescriptorProto>* mutable_oneof_decl() { return &oneof_decl_; }
+ int oneof_decl_size() const;
+ void clear_oneof_decl();
+ OneofDescriptorProto* add_oneof_decl();
+
+ const std::vector<DescriptorProto_ReservedRange>& reserved_range() const { return reserved_range_; }
+ std::vector<DescriptorProto_ReservedRange>* mutable_reserved_range() { return &reserved_range_; }
+ int reserved_range_size() const;
+ void clear_reserved_range();
+ DescriptorProto_ReservedRange* add_reserved_range();
+
+ const std::vector<std::string>& reserved_name() const { return reserved_name_; }
+ std::vector<std::string>* mutable_reserved_name() { return &reserved_name_; }
+ int reserved_name_size() const { return static_cast<int>(reserved_name_.size()); }
+ void clear_reserved_name() { reserved_name_.clear(); }
+ void add_reserved_name(std::string value) { reserved_name_.emplace_back(value); }
+ std::string* add_reserved_name() { reserved_name_.emplace_back(); return &reserved_name_.back(); }
+
+ private:
+ std::string name_{};
+ std::vector<FieldDescriptorProto> field_;
+ std::vector<FieldDescriptorProto> extension_;
+ std::vector<DescriptorProto> nested_type_;
+ std::vector<EnumDescriptorProto> enum_type_;
+ std::vector<OneofDescriptorProto> oneof_decl_;
+ std::vector<DescriptorProto_ReservedRange> reserved_range_;
+ std::vector<std::string> reserved_name_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<11> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DescriptorProto_ReservedRange : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kStartFieldNumber = 1,
+ kEndFieldNumber = 2,
+ };
+
+ DescriptorProto_ReservedRange();
+ ~DescriptorProto_ReservedRange() override;
+ DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&&) noexcept;
+ DescriptorProto_ReservedRange& operator=(DescriptorProto_ReservedRange&&);
+ DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange&);
+ DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange&);
+ bool operator==(const DescriptorProto_ReservedRange&) const;
+ bool operator!=(const DescriptorProto_ReservedRange& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_start() const { return _has_field_[1]; }
+ int32_t start() const { return start_; }
+ void set_start(int32_t value) { start_ = value; _has_field_.set(1); }
+
+ bool has_end() const { return _has_field_[2]; }
+ int32_t end() const { return end_; }
+ void set_end(int32_t value) { end_ = value; _has_field_.set(2); }
+
+ private:
+ int32_t start_{};
+ int32_t end_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FileDescriptorProto : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kPackageFieldNumber = 2,
+ kDependencyFieldNumber = 3,
+ kPublicDependencyFieldNumber = 10,
+ kWeakDependencyFieldNumber = 11,
+ kMessageTypeFieldNumber = 4,
+ kEnumTypeFieldNumber = 5,
+ kExtensionFieldNumber = 7,
+ };
+
+ FileDescriptorProto();
+ ~FileDescriptorProto() override;
+ FileDescriptorProto(FileDescriptorProto&&) noexcept;
+ FileDescriptorProto& operator=(FileDescriptorProto&&);
+ FileDescriptorProto(const FileDescriptorProto&);
+ FileDescriptorProto& operator=(const FileDescriptorProto&);
+ bool operator==(const FileDescriptorProto&) const;
+ bool operator!=(const FileDescriptorProto& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_package() const { return _has_field_[2]; }
+ const std::string& package() const { return package_; }
+ void set_package(const std::string& value) { package_ = value; _has_field_.set(2); }
+
+ const std::vector<std::string>& dependency() const { return dependency_; }
+ std::vector<std::string>* mutable_dependency() { return &dependency_; }
+ int dependency_size() const { return static_cast<int>(dependency_.size()); }
+ void clear_dependency() { dependency_.clear(); }
+ void add_dependency(std::string value) { dependency_.emplace_back(value); }
+ std::string* add_dependency() { dependency_.emplace_back(); return &dependency_.back(); }
+
+ const std::vector<int32_t>& public_dependency() const { return public_dependency_; }
+ std::vector<int32_t>* mutable_public_dependency() { return &public_dependency_; }
+ int public_dependency_size() const { return static_cast<int>(public_dependency_.size()); }
+ void clear_public_dependency() { public_dependency_.clear(); }
+ void add_public_dependency(int32_t value) { public_dependency_.emplace_back(value); }
+ int32_t* add_public_dependency() { public_dependency_.emplace_back(); return &public_dependency_.back(); }
+
+ const std::vector<int32_t>& weak_dependency() const { return weak_dependency_; }
+ std::vector<int32_t>* mutable_weak_dependency() { return &weak_dependency_; }
+ int weak_dependency_size() const { return static_cast<int>(weak_dependency_.size()); }
+ void clear_weak_dependency() { weak_dependency_.clear(); }
+ void add_weak_dependency(int32_t value) { weak_dependency_.emplace_back(value); }
+ int32_t* add_weak_dependency() { weak_dependency_.emplace_back(); return &weak_dependency_.back(); }
+
+ const std::vector<DescriptorProto>& message_type() const { return message_type_; }
+ std::vector<DescriptorProto>* mutable_message_type() { return &message_type_; }
+ int message_type_size() const;
+ void clear_message_type();
+ DescriptorProto* add_message_type();
+
+ const std::vector<EnumDescriptorProto>& enum_type() const { return enum_type_; }
+ std::vector<EnumDescriptorProto>* mutable_enum_type() { return &enum_type_; }
+ int enum_type_size() const;
+ void clear_enum_type();
+ EnumDescriptorProto* add_enum_type();
+
+ const std::vector<FieldDescriptorProto>& extension() const { return extension_; }
+ std::vector<FieldDescriptorProto>* mutable_extension() { return &extension_; }
+ int extension_size() const;
+ void clear_extension();
+ FieldDescriptorProto* add_extension();
+
+ private:
+ std::string name_{};
+ std::string package_{};
+ std::vector<std::string> dependency_;
+ std::vector<int32_t> public_dependency_;
+ std::vector<int32_t> weak_dependency_;
+ std::vector<DescriptorProto> message_type_;
+ std::vector<EnumDescriptorProto> enum_type_;
+ std::vector<FieldDescriptorProto> extension_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<12> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FileDescriptorSet : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kFileFieldNumber = 1,
+ };
+
+ FileDescriptorSet();
+ ~FileDescriptorSet() override;
+ FileDescriptorSet(FileDescriptorSet&&) noexcept;
+ FileDescriptorSet& operator=(FileDescriptorSet&&);
+ FileDescriptorSet(const FileDescriptorSet&);
+ FileDescriptorSet& operator=(const FileDescriptorSet&);
+ bool operator==(const FileDescriptorSet&) const;
+ bool operator!=(const FileDescriptorSet& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<FileDescriptorProto>& file() const { return file_; }
+ std::vector<FileDescriptorProto>* mutable_file() { return &file_; }
+ int file_size() const;
+ void clear_file();
+ FileDescriptorProto* add_file();
+
+ private:
+ std::vector<FileDescriptorProto> file_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/ftrace_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_FTRACE_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_FTRACE_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class FtraceDescriptor;
+class FtraceDescriptor_AtraceCategory;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT FtraceDescriptor : public ::protozero::CppMessageObj {
+ public:
+ using AtraceCategory = FtraceDescriptor_AtraceCategory;
+ enum FieldNumbers {
+ kAtraceCategoriesFieldNumber = 1,
+ };
+
+ FtraceDescriptor();
+ ~FtraceDescriptor() override;
+ FtraceDescriptor(FtraceDescriptor&&) noexcept;
+ FtraceDescriptor& operator=(FtraceDescriptor&&);
+ FtraceDescriptor(const FtraceDescriptor&);
+ FtraceDescriptor& operator=(const FtraceDescriptor&);
+ bool operator==(const FtraceDescriptor&) const;
+ bool operator!=(const FtraceDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<FtraceDescriptor_AtraceCategory>& atrace_categories() const { return atrace_categories_; }
+ std::vector<FtraceDescriptor_AtraceCategory>* mutable_atrace_categories() { return &atrace_categories_; }
+ int atrace_categories_size() const;
+ void clear_atrace_categories();
+ FtraceDescriptor_AtraceCategory* add_atrace_categories();
+
+ private:
+ std::vector<FtraceDescriptor_AtraceCategory> atrace_categories_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FtraceDescriptor_AtraceCategory : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kDescriptionFieldNumber = 2,
+ };
+
+ FtraceDescriptor_AtraceCategory();
+ ~FtraceDescriptor_AtraceCategory() override;
+ FtraceDescriptor_AtraceCategory(FtraceDescriptor_AtraceCategory&&) noexcept;
+ FtraceDescriptor_AtraceCategory& operator=(FtraceDescriptor_AtraceCategory&&);
+ FtraceDescriptor_AtraceCategory(const FtraceDescriptor_AtraceCategory&);
+ FtraceDescriptor_AtraceCategory& operator=(const FtraceDescriptor_AtraceCategory&);
+ bool operator==(const FtraceDescriptor_AtraceCategory&) const;
+ bool operator!=(const FtraceDescriptor_AtraceCategory& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_description() const { return _has_field_[2]; }
+ const std::string& description() const { return description_; }
+ void set_description(const std::string& value) { description_ = value; _has_field_.set(2); }
+
+ private:
+ std::string name_{};
+ std::string description_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_FTRACE_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/gpu_counter_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_GPU_COUNTER_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_GPU_COUNTER_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class GpuCounterDescriptor;
+class GpuCounterDescriptor_GpuCounterBlock;
+class GpuCounterDescriptor_GpuCounterSpec;
+enum GpuCounterDescriptor_GpuCounterGroup : int;
+enum GpuCounterDescriptor_MeasureUnit : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum GpuCounterDescriptor_GpuCounterGroup : int {
+ GpuCounterDescriptor_GpuCounterGroup_UNCLASSIFIED = 0,
+ GpuCounterDescriptor_GpuCounterGroup_SYSTEM = 1,
+ GpuCounterDescriptor_GpuCounterGroup_VERTICES = 2,
+ GpuCounterDescriptor_GpuCounterGroup_FRAGMENTS = 3,
+ GpuCounterDescriptor_GpuCounterGroup_PRIMITIVES = 4,
+ GpuCounterDescriptor_GpuCounterGroup_MEMORY = 5,
+ GpuCounterDescriptor_GpuCounterGroup_COMPUTE = 6,
+};
+enum GpuCounterDescriptor_MeasureUnit : int {
+ GpuCounterDescriptor_MeasureUnit_NONE = 0,
+ GpuCounterDescriptor_MeasureUnit_BIT = 1,
+ GpuCounterDescriptor_MeasureUnit_KILOBIT = 2,
+ GpuCounterDescriptor_MeasureUnit_MEGABIT = 3,
+ GpuCounterDescriptor_MeasureUnit_GIGABIT = 4,
+ GpuCounterDescriptor_MeasureUnit_TERABIT = 5,
+ GpuCounterDescriptor_MeasureUnit_PETABIT = 6,
+ GpuCounterDescriptor_MeasureUnit_BYTE = 7,
+ GpuCounterDescriptor_MeasureUnit_KILOBYTE = 8,
+ GpuCounterDescriptor_MeasureUnit_MEGABYTE = 9,
+ GpuCounterDescriptor_MeasureUnit_GIGABYTE = 10,
+ GpuCounterDescriptor_MeasureUnit_TERABYTE = 11,
+ GpuCounterDescriptor_MeasureUnit_PETABYTE = 12,
+ GpuCounterDescriptor_MeasureUnit_HERTZ = 13,
+ GpuCounterDescriptor_MeasureUnit_KILOHERTZ = 14,
+ GpuCounterDescriptor_MeasureUnit_MEGAHERTZ = 15,
+ GpuCounterDescriptor_MeasureUnit_GIGAHERTZ = 16,
+ GpuCounterDescriptor_MeasureUnit_TERAHERTZ = 17,
+ GpuCounterDescriptor_MeasureUnit_PETAHERTZ = 18,
+ GpuCounterDescriptor_MeasureUnit_NANOSECOND = 19,
+ GpuCounterDescriptor_MeasureUnit_MICROSECOND = 20,
+ GpuCounterDescriptor_MeasureUnit_MILLISECOND = 21,
+ GpuCounterDescriptor_MeasureUnit_SECOND = 22,
+ GpuCounterDescriptor_MeasureUnit_MINUTE = 23,
+ GpuCounterDescriptor_MeasureUnit_HOUR = 24,
+ GpuCounterDescriptor_MeasureUnit_VERTEX = 25,
+ GpuCounterDescriptor_MeasureUnit_PIXEL = 26,
+ GpuCounterDescriptor_MeasureUnit_TRIANGLE = 27,
+ GpuCounterDescriptor_MeasureUnit_PRIMITIVE = 38,
+ GpuCounterDescriptor_MeasureUnit_FRAGMENT = 39,
+ GpuCounterDescriptor_MeasureUnit_MILLIWATT = 28,
+ GpuCounterDescriptor_MeasureUnit_WATT = 29,
+ GpuCounterDescriptor_MeasureUnit_KILOWATT = 30,
+ GpuCounterDescriptor_MeasureUnit_JOULE = 31,
+ GpuCounterDescriptor_MeasureUnit_VOLT = 32,
+ GpuCounterDescriptor_MeasureUnit_AMPERE = 33,
+ GpuCounterDescriptor_MeasureUnit_CELSIUS = 34,
+ GpuCounterDescriptor_MeasureUnit_FAHRENHEIT = 35,
+ GpuCounterDescriptor_MeasureUnit_KELVIN = 36,
+ GpuCounterDescriptor_MeasureUnit_PERCENT = 37,
+ GpuCounterDescriptor_MeasureUnit_INSTRUCTION = 40,
+};
+
+class PERFETTO_EXPORT_COMPONENT GpuCounterDescriptor : public ::protozero::CppMessageObj {
+ public:
+ using GpuCounterSpec = GpuCounterDescriptor_GpuCounterSpec;
+ using GpuCounterBlock = GpuCounterDescriptor_GpuCounterBlock;
+ using GpuCounterGroup = GpuCounterDescriptor_GpuCounterGroup;
+ static constexpr auto UNCLASSIFIED = GpuCounterDescriptor_GpuCounterGroup_UNCLASSIFIED;
+ static constexpr auto SYSTEM = GpuCounterDescriptor_GpuCounterGroup_SYSTEM;
+ static constexpr auto VERTICES = GpuCounterDescriptor_GpuCounterGroup_VERTICES;
+ static constexpr auto FRAGMENTS = GpuCounterDescriptor_GpuCounterGroup_FRAGMENTS;
+ static constexpr auto PRIMITIVES = GpuCounterDescriptor_GpuCounterGroup_PRIMITIVES;
+ static constexpr auto MEMORY = GpuCounterDescriptor_GpuCounterGroup_MEMORY;
+ static constexpr auto COMPUTE = GpuCounterDescriptor_GpuCounterGroup_COMPUTE;
+ static constexpr auto GpuCounterGroup_MIN = GpuCounterDescriptor_GpuCounterGroup_UNCLASSIFIED;
+ static constexpr auto GpuCounterGroup_MAX = GpuCounterDescriptor_GpuCounterGroup_COMPUTE;
+ using MeasureUnit = GpuCounterDescriptor_MeasureUnit;
+ static constexpr auto NONE = GpuCounterDescriptor_MeasureUnit_NONE;
+ static constexpr auto BIT = GpuCounterDescriptor_MeasureUnit_BIT;
+ static constexpr auto KILOBIT = GpuCounterDescriptor_MeasureUnit_KILOBIT;
+ static constexpr auto MEGABIT = GpuCounterDescriptor_MeasureUnit_MEGABIT;
+ static constexpr auto GIGABIT = GpuCounterDescriptor_MeasureUnit_GIGABIT;
+ static constexpr auto TERABIT = GpuCounterDescriptor_MeasureUnit_TERABIT;
+ static constexpr auto PETABIT = GpuCounterDescriptor_MeasureUnit_PETABIT;
+ static constexpr auto BYTE = GpuCounterDescriptor_MeasureUnit_BYTE;
+ static constexpr auto KILOBYTE = GpuCounterDescriptor_MeasureUnit_KILOBYTE;
+ static constexpr auto MEGABYTE = GpuCounterDescriptor_MeasureUnit_MEGABYTE;
+ static constexpr auto GIGABYTE = GpuCounterDescriptor_MeasureUnit_GIGABYTE;
+ static constexpr auto TERABYTE = GpuCounterDescriptor_MeasureUnit_TERABYTE;
+ static constexpr auto PETABYTE = GpuCounterDescriptor_MeasureUnit_PETABYTE;
+ static constexpr auto HERTZ = GpuCounterDescriptor_MeasureUnit_HERTZ;
+ static constexpr auto KILOHERTZ = GpuCounterDescriptor_MeasureUnit_KILOHERTZ;
+ static constexpr auto MEGAHERTZ = GpuCounterDescriptor_MeasureUnit_MEGAHERTZ;
+ static constexpr auto GIGAHERTZ = GpuCounterDescriptor_MeasureUnit_GIGAHERTZ;
+ static constexpr auto TERAHERTZ = GpuCounterDescriptor_MeasureUnit_TERAHERTZ;
+ static constexpr auto PETAHERTZ = GpuCounterDescriptor_MeasureUnit_PETAHERTZ;
+ static constexpr auto NANOSECOND = GpuCounterDescriptor_MeasureUnit_NANOSECOND;
+ static constexpr auto MICROSECOND = GpuCounterDescriptor_MeasureUnit_MICROSECOND;
+ static constexpr auto MILLISECOND = GpuCounterDescriptor_MeasureUnit_MILLISECOND;
+ static constexpr auto SECOND = GpuCounterDescriptor_MeasureUnit_SECOND;
+ static constexpr auto MINUTE = GpuCounterDescriptor_MeasureUnit_MINUTE;
+ static constexpr auto HOUR = GpuCounterDescriptor_MeasureUnit_HOUR;
+ static constexpr auto VERTEX = GpuCounterDescriptor_MeasureUnit_VERTEX;
+ static constexpr auto PIXEL = GpuCounterDescriptor_MeasureUnit_PIXEL;
+ static constexpr auto TRIANGLE = GpuCounterDescriptor_MeasureUnit_TRIANGLE;
+ static constexpr auto PRIMITIVE = GpuCounterDescriptor_MeasureUnit_PRIMITIVE;
+ static constexpr auto FRAGMENT = GpuCounterDescriptor_MeasureUnit_FRAGMENT;
+ static constexpr auto MILLIWATT = GpuCounterDescriptor_MeasureUnit_MILLIWATT;
+ static constexpr auto WATT = GpuCounterDescriptor_MeasureUnit_WATT;
+ static constexpr auto KILOWATT = GpuCounterDescriptor_MeasureUnit_KILOWATT;
+ static constexpr auto JOULE = GpuCounterDescriptor_MeasureUnit_JOULE;
+ static constexpr auto VOLT = GpuCounterDescriptor_MeasureUnit_VOLT;
+ static constexpr auto AMPERE = GpuCounterDescriptor_MeasureUnit_AMPERE;
+ static constexpr auto CELSIUS = GpuCounterDescriptor_MeasureUnit_CELSIUS;
+ static constexpr auto FAHRENHEIT = GpuCounterDescriptor_MeasureUnit_FAHRENHEIT;
+ static constexpr auto KELVIN = GpuCounterDescriptor_MeasureUnit_KELVIN;
+ static constexpr auto PERCENT = GpuCounterDescriptor_MeasureUnit_PERCENT;
+ static constexpr auto INSTRUCTION = GpuCounterDescriptor_MeasureUnit_INSTRUCTION;
+ static constexpr auto MeasureUnit_MIN = GpuCounterDescriptor_MeasureUnit_NONE;
+ static constexpr auto MeasureUnit_MAX = GpuCounterDescriptor_MeasureUnit_INSTRUCTION;
+ enum FieldNumbers {
+ kSpecsFieldNumber = 1,
+ kBlocksFieldNumber = 2,
+ kMinSamplingPeriodNsFieldNumber = 3,
+ kMaxSamplingPeriodNsFieldNumber = 4,
+ kSupportsInstrumentedSamplingFieldNumber = 5,
+ };
+
+ GpuCounterDescriptor();
+ ~GpuCounterDescriptor() override;
+ GpuCounterDescriptor(GpuCounterDescriptor&&) noexcept;
+ GpuCounterDescriptor& operator=(GpuCounterDescriptor&&);
+ GpuCounterDescriptor(const GpuCounterDescriptor&);
+ GpuCounterDescriptor& operator=(const GpuCounterDescriptor&);
+ bool operator==(const GpuCounterDescriptor&) const;
+ bool operator!=(const GpuCounterDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<GpuCounterDescriptor_GpuCounterSpec>& specs() const { return specs_; }
+ std::vector<GpuCounterDescriptor_GpuCounterSpec>* mutable_specs() { return &specs_; }
+ int specs_size() const;
+ void clear_specs();
+ GpuCounterDescriptor_GpuCounterSpec* add_specs();
+
+ const std::vector<GpuCounterDescriptor_GpuCounterBlock>& blocks() const { return blocks_; }
+ std::vector<GpuCounterDescriptor_GpuCounterBlock>* mutable_blocks() { return &blocks_; }
+ int blocks_size() const;
+ void clear_blocks();
+ GpuCounterDescriptor_GpuCounterBlock* add_blocks();
+
+ bool has_min_sampling_period_ns() const { return _has_field_[3]; }
+ uint64_t min_sampling_period_ns() const { return min_sampling_period_ns_; }
+ void set_min_sampling_period_ns(uint64_t value) { min_sampling_period_ns_ = value; _has_field_.set(3); }
+
+ bool has_max_sampling_period_ns() const { return _has_field_[4]; }
+ uint64_t max_sampling_period_ns() const { return max_sampling_period_ns_; }
+ void set_max_sampling_period_ns(uint64_t value) { max_sampling_period_ns_ = value; _has_field_.set(4); }
+
+ bool has_supports_instrumented_sampling() const { return _has_field_[5]; }
+ bool supports_instrumented_sampling() const { return supports_instrumented_sampling_; }
+ void set_supports_instrumented_sampling(bool value) { supports_instrumented_sampling_ = value; _has_field_.set(5); }
+
+ private:
+ std::vector<GpuCounterDescriptor_GpuCounterSpec> specs_;
+ std::vector<GpuCounterDescriptor_GpuCounterBlock> blocks_;
+ uint64_t min_sampling_period_ns_{};
+ uint64_t max_sampling_period_ns_{};
+ bool supports_instrumented_sampling_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GpuCounterDescriptor_GpuCounterBlock : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kBlockIdFieldNumber = 1,
+ kBlockCapacityFieldNumber = 2,
+ kNameFieldNumber = 3,
+ kDescriptionFieldNumber = 4,
+ kCounterIdsFieldNumber = 5,
+ };
+
+ GpuCounterDescriptor_GpuCounterBlock();
+ ~GpuCounterDescriptor_GpuCounterBlock() override;
+ GpuCounterDescriptor_GpuCounterBlock(GpuCounterDescriptor_GpuCounterBlock&&) noexcept;
+ GpuCounterDescriptor_GpuCounterBlock& operator=(GpuCounterDescriptor_GpuCounterBlock&&);
+ GpuCounterDescriptor_GpuCounterBlock(const GpuCounterDescriptor_GpuCounterBlock&);
+ GpuCounterDescriptor_GpuCounterBlock& operator=(const GpuCounterDescriptor_GpuCounterBlock&);
+ bool operator==(const GpuCounterDescriptor_GpuCounterBlock&) const;
+ bool operator!=(const GpuCounterDescriptor_GpuCounterBlock& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_block_id() const { return _has_field_[1]; }
+ uint32_t block_id() const { return block_id_; }
+ void set_block_id(uint32_t value) { block_id_ = value; _has_field_.set(1); }
+
+ bool has_block_capacity() const { return _has_field_[2]; }
+ uint32_t block_capacity() const { return block_capacity_; }
+ void set_block_capacity(uint32_t value) { block_capacity_ = value; _has_field_.set(2); }
+
+ bool has_name() const { return _has_field_[3]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(3); }
+
+ bool has_description() const { return _has_field_[4]; }
+ const std::string& description() const { return description_; }
+ void set_description(const std::string& value) { description_ = value; _has_field_.set(4); }
+
+ const std::vector<uint32_t>& counter_ids() const { return counter_ids_; }
+ std::vector<uint32_t>* mutable_counter_ids() { return &counter_ids_; }
+ int counter_ids_size() const { return static_cast<int>(counter_ids_.size()); }
+ void clear_counter_ids() { counter_ids_.clear(); }
+ void add_counter_ids(uint32_t value) { counter_ids_.emplace_back(value); }
+ uint32_t* add_counter_ids() { counter_ids_.emplace_back(); return &counter_ids_.back(); }
+
+ private:
+ uint32_t block_id_{};
+ uint32_t block_capacity_{};
+ std::string name_{};
+ std::string description_{};
+ std::vector<uint32_t> counter_ids_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GpuCounterDescriptor_GpuCounterSpec : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kCounterIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kDescriptionFieldNumber = 3,
+ kIntPeakValueFieldNumber = 5,
+ kDoublePeakValueFieldNumber = 6,
+ kNumeratorUnitsFieldNumber = 7,
+ kDenominatorUnitsFieldNumber = 8,
+ kSelectByDefaultFieldNumber = 9,
+ kGroupsFieldNumber = 10,
+ };
+
+ GpuCounterDescriptor_GpuCounterSpec();
+ ~GpuCounterDescriptor_GpuCounterSpec() override;
+ GpuCounterDescriptor_GpuCounterSpec(GpuCounterDescriptor_GpuCounterSpec&&) noexcept;
+ GpuCounterDescriptor_GpuCounterSpec& operator=(GpuCounterDescriptor_GpuCounterSpec&&);
+ GpuCounterDescriptor_GpuCounterSpec(const GpuCounterDescriptor_GpuCounterSpec&);
+ GpuCounterDescriptor_GpuCounterSpec& operator=(const GpuCounterDescriptor_GpuCounterSpec&);
+ bool operator==(const GpuCounterDescriptor_GpuCounterSpec&) const;
+ bool operator!=(const GpuCounterDescriptor_GpuCounterSpec& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_counter_id() const { return _has_field_[1]; }
+ uint32_t counter_id() const { return counter_id_; }
+ void set_counter_id(uint32_t value) { counter_id_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ bool has_description() const { return _has_field_[3]; }
+ const std::string& description() const { return description_; }
+ void set_description(const std::string& value) { description_ = value; _has_field_.set(3); }
+
+ bool has_int_peak_value() const { return _has_field_[5]; }
+ int64_t int_peak_value() const { return int_peak_value_; }
+ void set_int_peak_value(int64_t value) { int_peak_value_ = value; _has_field_.set(5); }
+
+ bool has_double_peak_value() const { return _has_field_[6]; }
+ double double_peak_value() const { return double_peak_value_; }
+ void set_double_peak_value(double value) { double_peak_value_ = value; _has_field_.set(6); }
+
+ const std::vector<GpuCounterDescriptor_MeasureUnit>& numerator_units() const { return numerator_units_; }
+ std::vector<GpuCounterDescriptor_MeasureUnit>* mutable_numerator_units() { return &numerator_units_; }
+ int numerator_units_size() const { return static_cast<int>(numerator_units_.size()); }
+ void clear_numerator_units() { numerator_units_.clear(); }
+ void add_numerator_units(GpuCounterDescriptor_MeasureUnit value) { numerator_units_.emplace_back(value); }
+ GpuCounterDescriptor_MeasureUnit* add_numerator_units() { numerator_units_.emplace_back(); return &numerator_units_.back(); }
+
+ const std::vector<GpuCounterDescriptor_MeasureUnit>& denominator_units() const { return denominator_units_; }
+ std::vector<GpuCounterDescriptor_MeasureUnit>* mutable_denominator_units() { return &denominator_units_; }
+ int denominator_units_size() const { return static_cast<int>(denominator_units_.size()); }
+ void clear_denominator_units() { denominator_units_.clear(); }
+ void add_denominator_units(GpuCounterDescriptor_MeasureUnit value) { denominator_units_.emplace_back(value); }
+ GpuCounterDescriptor_MeasureUnit* add_denominator_units() { denominator_units_.emplace_back(); return &denominator_units_.back(); }
+
+ bool has_select_by_default() const { return _has_field_[9]; }
+ bool select_by_default() const { return select_by_default_; }
+ void set_select_by_default(bool value) { select_by_default_ = value; _has_field_.set(9); }
+
+ const std::vector<GpuCounterDescriptor_GpuCounterGroup>& groups() const { return groups_; }
+ std::vector<GpuCounterDescriptor_GpuCounterGroup>* mutable_groups() { return &groups_; }
+ int groups_size() const { return static_cast<int>(groups_.size()); }
+ void clear_groups() { groups_.clear(); }
+ void add_groups(GpuCounterDescriptor_GpuCounterGroup value) { groups_.emplace_back(value); }
+ GpuCounterDescriptor_GpuCounterGroup* add_groups() { groups_.emplace_back(); return &groups_.back(); }
+
+ private:
+ uint32_t counter_id_{};
+ std::string name_{};
+ std::string description_{};
+ int64_t int_peak_value_{};
+ double double_peak_value_{};
+ std::vector<GpuCounterDescriptor_MeasureUnit> numerator_units_;
+ std::vector<GpuCounterDescriptor_MeasureUnit> denominator_units_;
+ bool select_by_default_{};
+ std::vector<GpuCounterDescriptor_GpuCounterGroup> groups_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<11> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_GPU_COUNTER_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/interceptor_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_INTERCEPTOR_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_INTERCEPTOR_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class InterceptorDescriptor;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT InterceptorDescriptor : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ };
+
+ InterceptorDescriptor();
+ ~InterceptorDescriptor() override;
+ InterceptorDescriptor(InterceptorDescriptor&&) noexcept;
+ InterceptorDescriptor& operator=(InterceptorDescriptor&&);
+ InterceptorDescriptor(const InterceptorDescriptor&);
+ InterceptorDescriptor& operator=(const InterceptorDescriptor&);
+ bool operator==(const InterceptorDescriptor&) const;
+ bool operator!=(const InterceptorDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ private:
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_INTERCEPTOR_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/observable_events.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_OBSERVABLE_EVENTS_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_OBSERVABLE_EVENTS_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ObservableEvents;
+class ObservableEvents_CloneTriggerHit;
+class ObservableEvents_DataSourceInstanceStateChange;
+enum ObservableEvents_Type : int;
+enum ObservableEvents_DataSourceInstanceState : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ObservableEvents_Type : int {
+ ObservableEvents_Type_TYPE_UNSPECIFIED = 0,
+ ObservableEvents_Type_TYPE_DATA_SOURCES_INSTANCES = 1,
+ ObservableEvents_Type_TYPE_ALL_DATA_SOURCES_STARTED = 2,
+ ObservableEvents_Type_TYPE_CLONE_TRIGGER_HIT = 4,
+};
+enum ObservableEvents_DataSourceInstanceState : int {
+ ObservableEvents_DataSourceInstanceState_DATA_SOURCE_INSTANCE_STATE_STOPPED = 1,
+ ObservableEvents_DataSourceInstanceState_DATA_SOURCE_INSTANCE_STATE_STARTED = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT ObservableEvents : public ::protozero::CppMessageObj {
+ public:
+ using DataSourceInstanceStateChange = ObservableEvents_DataSourceInstanceStateChange;
+ using CloneTriggerHit = ObservableEvents_CloneTriggerHit;
+ using Type = ObservableEvents_Type;
+ static constexpr auto TYPE_UNSPECIFIED = ObservableEvents_Type_TYPE_UNSPECIFIED;
+ static constexpr auto TYPE_DATA_SOURCES_INSTANCES = ObservableEvents_Type_TYPE_DATA_SOURCES_INSTANCES;
+ static constexpr auto TYPE_ALL_DATA_SOURCES_STARTED = ObservableEvents_Type_TYPE_ALL_DATA_SOURCES_STARTED;
+ static constexpr auto TYPE_CLONE_TRIGGER_HIT = ObservableEvents_Type_TYPE_CLONE_TRIGGER_HIT;
+ static constexpr auto Type_MIN = ObservableEvents_Type_TYPE_UNSPECIFIED;
+ static constexpr auto Type_MAX = ObservableEvents_Type_TYPE_CLONE_TRIGGER_HIT;
+ using DataSourceInstanceState = ObservableEvents_DataSourceInstanceState;
+ static constexpr auto DATA_SOURCE_INSTANCE_STATE_STOPPED = ObservableEvents_DataSourceInstanceState_DATA_SOURCE_INSTANCE_STATE_STOPPED;
+ static constexpr auto DATA_SOURCE_INSTANCE_STATE_STARTED = ObservableEvents_DataSourceInstanceState_DATA_SOURCE_INSTANCE_STATE_STARTED;
+ static constexpr auto DataSourceInstanceState_MIN = ObservableEvents_DataSourceInstanceState_DATA_SOURCE_INSTANCE_STATE_STOPPED;
+ static constexpr auto DataSourceInstanceState_MAX = ObservableEvents_DataSourceInstanceState_DATA_SOURCE_INSTANCE_STATE_STARTED;
+ enum FieldNumbers {
+ kInstanceStateChangesFieldNumber = 1,
+ kAllDataSourcesStartedFieldNumber = 2,
+ kCloneTriggerHitFieldNumber = 3,
+ };
+
+ ObservableEvents();
+ ~ObservableEvents() override;
+ ObservableEvents(ObservableEvents&&) noexcept;
+ ObservableEvents& operator=(ObservableEvents&&);
+ ObservableEvents(const ObservableEvents&);
+ ObservableEvents& operator=(const ObservableEvents&);
+ bool operator==(const ObservableEvents&) const;
+ bool operator!=(const ObservableEvents& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<ObservableEvents_DataSourceInstanceStateChange>& instance_state_changes() const { return instance_state_changes_; }
+ std::vector<ObservableEvents_DataSourceInstanceStateChange>* mutable_instance_state_changes() { return &instance_state_changes_; }
+ int instance_state_changes_size() const;
+ void clear_instance_state_changes();
+ ObservableEvents_DataSourceInstanceStateChange* add_instance_state_changes();
+
+ bool has_all_data_sources_started() const { return _has_field_[2]; }
+ bool all_data_sources_started() const { return all_data_sources_started_; }
+ void set_all_data_sources_started(bool value) { all_data_sources_started_ = value; _has_field_.set(2); }
+
+ bool has_clone_trigger_hit() const { return _has_field_[3]; }
+ const ObservableEvents_CloneTriggerHit& clone_trigger_hit() const { return *clone_trigger_hit_; }
+ ObservableEvents_CloneTriggerHit* mutable_clone_trigger_hit() { _has_field_.set(3); return clone_trigger_hit_.get(); }
+
+ private:
+ std::vector<ObservableEvents_DataSourceInstanceStateChange> instance_state_changes_;
+ bool all_data_sources_started_{};
+ ::protozero::CopyablePtr<ObservableEvents_CloneTriggerHit> clone_trigger_hit_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ObservableEvents_CloneTriggerHit : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTracingSessionIdFieldNumber = 1,
+ };
+
+ ObservableEvents_CloneTriggerHit();
+ ~ObservableEvents_CloneTriggerHit() override;
+ ObservableEvents_CloneTriggerHit(ObservableEvents_CloneTriggerHit&&) noexcept;
+ ObservableEvents_CloneTriggerHit& operator=(ObservableEvents_CloneTriggerHit&&);
+ ObservableEvents_CloneTriggerHit(const ObservableEvents_CloneTriggerHit&);
+ ObservableEvents_CloneTriggerHit& operator=(const ObservableEvents_CloneTriggerHit&);
+ bool operator==(const ObservableEvents_CloneTriggerHit&) const;
+ bool operator!=(const ObservableEvents_CloneTriggerHit& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_tracing_session_id() const { return _has_field_[1]; }
+ int64_t tracing_session_id() const { return tracing_session_id_; }
+ void set_tracing_session_id(int64_t value) { tracing_session_id_ = value; _has_field_.set(1); }
+
+ private:
+ int64_t tracing_session_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ObservableEvents_DataSourceInstanceStateChange : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kProducerNameFieldNumber = 1,
+ kDataSourceNameFieldNumber = 2,
+ kStateFieldNumber = 3,
+ };
+
+ ObservableEvents_DataSourceInstanceStateChange();
+ ~ObservableEvents_DataSourceInstanceStateChange() override;
+ ObservableEvents_DataSourceInstanceStateChange(ObservableEvents_DataSourceInstanceStateChange&&) noexcept;
+ ObservableEvents_DataSourceInstanceStateChange& operator=(ObservableEvents_DataSourceInstanceStateChange&&);
+ ObservableEvents_DataSourceInstanceStateChange(const ObservableEvents_DataSourceInstanceStateChange&);
+ ObservableEvents_DataSourceInstanceStateChange& operator=(const ObservableEvents_DataSourceInstanceStateChange&);
+ bool operator==(const ObservableEvents_DataSourceInstanceStateChange&) const;
+ bool operator!=(const ObservableEvents_DataSourceInstanceStateChange& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_producer_name() const { return _has_field_[1]; }
+ const std::string& producer_name() const { return producer_name_; }
+ void set_producer_name(const std::string& value) { producer_name_ = value; _has_field_.set(1); }
+
+ bool has_data_source_name() const { return _has_field_[2]; }
+ const std::string& data_source_name() const { return data_source_name_; }
+ void set_data_source_name(const std::string& value) { data_source_name_ = value; _has_field_.set(2); }
+
+ bool has_state() const { return _has_field_[3]; }
+ ObservableEvents_DataSourceInstanceState state() const { return state_; }
+ void set_state(ObservableEvents_DataSourceInstanceState value) { state_ = value; _has_field_.set(3); }
+
+ private:
+ std::string producer_name_{};
+ std::string data_source_name_{};
+ ObservableEvents_DataSourceInstanceState state_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_OBSERVABLE_EVENTS_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/perf_events.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PERF_EVENTS_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PERF_EVENTS_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class PerfEvents;
+class PerfEvents_RawEvent;
+class PerfEvents_Tracepoint;
+class PerfEvents_Timebase;
+enum PerfEvents_Counter : int;
+enum PerfEvents_PerfClock : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum PerfEvents_Counter : int {
+ PerfEvents_Counter_UNKNOWN_COUNTER = 0,
+ PerfEvents_Counter_SW_CPU_CLOCK = 1,
+ PerfEvents_Counter_SW_PAGE_FAULTS = 2,
+ PerfEvents_Counter_SW_TASK_CLOCK = 3,
+ PerfEvents_Counter_SW_CONTEXT_SWITCHES = 4,
+ PerfEvents_Counter_SW_CPU_MIGRATIONS = 5,
+ PerfEvents_Counter_SW_PAGE_FAULTS_MIN = 6,
+ PerfEvents_Counter_SW_PAGE_FAULTS_MAJ = 7,
+ PerfEvents_Counter_SW_ALIGNMENT_FAULTS = 8,
+ PerfEvents_Counter_SW_EMULATION_FAULTS = 9,
+ PerfEvents_Counter_SW_DUMMY = 20,
+ PerfEvents_Counter_HW_CPU_CYCLES = 10,
+ PerfEvents_Counter_HW_INSTRUCTIONS = 11,
+ PerfEvents_Counter_HW_CACHE_REFERENCES = 12,
+ PerfEvents_Counter_HW_CACHE_MISSES = 13,
+ PerfEvents_Counter_HW_BRANCH_INSTRUCTIONS = 14,
+ PerfEvents_Counter_HW_BRANCH_MISSES = 15,
+ PerfEvents_Counter_HW_BUS_CYCLES = 16,
+ PerfEvents_Counter_HW_STALLED_CYCLES_FRONTEND = 17,
+ PerfEvents_Counter_HW_STALLED_CYCLES_BACKEND = 18,
+ PerfEvents_Counter_HW_REF_CPU_CYCLES = 19,
+};
+enum PerfEvents_PerfClock : int {
+ PerfEvents_PerfClock_UNKNOWN_PERF_CLOCK = 0,
+ PerfEvents_PerfClock_PERF_CLOCK_REALTIME = 1,
+ PerfEvents_PerfClock_PERF_CLOCK_MONOTONIC = 2,
+ PerfEvents_PerfClock_PERF_CLOCK_MONOTONIC_RAW = 3,
+ PerfEvents_PerfClock_PERF_CLOCK_BOOTTIME = 4,
+};
+
+class PERFETTO_EXPORT_COMPONENT PerfEvents : public ::protozero::CppMessageObj {
+ public:
+ using Timebase = PerfEvents_Timebase;
+ using Tracepoint = PerfEvents_Tracepoint;
+ using RawEvent = PerfEvents_RawEvent;
+ using Counter = PerfEvents_Counter;
+ static constexpr auto UNKNOWN_COUNTER = PerfEvents_Counter_UNKNOWN_COUNTER;
+ static constexpr auto SW_CPU_CLOCK = PerfEvents_Counter_SW_CPU_CLOCK;
+ static constexpr auto SW_PAGE_FAULTS = PerfEvents_Counter_SW_PAGE_FAULTS;
+ static constexpr auto SW_TASK_CLOCK = PerfEvents_Counter_SW_TASK_CLOCK;
+ static constexpr auto SW_CONTEXT_SWITCHES = PerfEvents_Counter_SW_CONTEXT_SWITCHES;
+ static constexpr auto SW_CPU_MIGRATIONS = PerfEvents_Counter_SW_CPU_MIGRATIONS;
+ static constexpr auto SW_PAGE_FAULTS_MIN = PerfEvents_Counter_SW_PAGE_FAULTS_MIN;
+ static constexpr auto SW_PAGE_FAULTS_MAJ = PerfEvents_Counter_SW_PAGE_FAULTS_MAJ;
+ static constexpr auto SW_ALIGNMENT_FAULTS = PerfEvents_Counter_SW_ALIGNMENT_FAULTS;
+ static constexpr auto SW_EMULATION_FAULTS = PerfEvents_Counter_SW_EMULATION_FAULTS;
+ static constexpr auto SW_DUMMY = PerfEvents_Counter_SW_DUMMY;
+ static constexpr auto HW_CPU_CYCLES = PerfEvents_Counter_HW_CPU_CYCLES;
+ static constexpr auto HW_INSTRUCTIONS = PerfEvents_Counter_HW_INSTRUCTIONS;
+ static constexpr auto HW_CACHE_REFERENCES = PerfEvents_Counter_HW_CACHE_REFERENCES;
+ static constexpr auto HW_CACHE_MISSES = PerfEvents_Counter_HW_CACHE_MISSES;
+ static constexpr auto HW_BRANCH_INSTRUCTIONS = PerfEvents_Counter_HW_BRANCH_INSTRUCTIONS;
+ static constexpr auto HW_BRANCH_MISSES = PerfEvents_Counter_HW_BRANCH_MISSES;
+ static constexpr auto HW_BUS_CYCLES = PerfEvents_Counter_HW_BUS_CYCLES;
+ static constexpr auto HW_STALLED_CYCLES_FRONTEND = PerfEvents_Counter_HW_STALLED_CYCLES_FRONTEND;
+ static constexpr auto HW_STALLED_CYCLES_BACKEND = PerfEvents_Counter_HW_STALLED_CYCLES_BACKEND;
+ static constexpr auto HW_REF_CPU_CYCLES = PerfEvents_Counter_HW_REF_CPU_CYCLES;
+ static constexpr auto Counter_MIN = PerfEvents_Counter_UNKNOWN_COUNTER;
+ static constexpr auto Counter_MAX = PerfEvents_Counter_SW_DUMMY;
+ using PerfClock = PerfEvents_PerfClock;
+ static constexpr auto UNKNOWN_PERF_CLOCK = PerfEvents_PerfClock_UNKNOWN_PERF_CLOCK;
+ static constexpr auto PERF_CLOCK_REALTIME = PerfEvents_PerfClock_PERF_CLOCK_REALTIME;
+ static constexpr auto PERF_CLOCK_MONOTONIC = PerfEvents_PerfClock_PERF_CLOCK_MONOTONIC;
+ static constexpr auto PERF_CLOCK_MONOTONIC_RAW = PerfEvents_PerfClock_PERF_CLOCK_MONOTONIC_RAW;
+ static constexpr auto PERF_CLOCK_BOOTTIME = PerfEvents_PerfClock_PERF_CLOCK_BOOTTIME;
+ static constexpr auto PerfClock_MIN = PerfEvents_PerfClock_UNKNOWN_PERF_CLOCK;
+ static constexpr auto PerfClock_MAX = PerfEvents_PerfClock_PERF_CLOCK_BOOTTIME;
+ enum FieldNumbers {
+ };
+
+ PerfEvents();
+ ~PerfEvents() override;
+ PerfEvents(PerfEvents&&) noexcept;
+ PerfEvents& operator=(PerfEvents&&);
+ PerfEvents(const PerfEvents&);
+ PerfEvents& operator=(const PerfEvents&);
+ bool operator==(const PerfEvents&) const;
+ bool operator!=(const PerfEvents& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT PerfEvents_RawEvent : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTypeFieldNumber = 1,
+ kConfigFieldNumber = 2,
+ kConfig1FieldNumber = 3,
+ kConfig2FieldNumber = 4,
+ };
+
+ PerfEvents_RawEvent();
+ ~PerfEvents_RawEvent() override;
+ PerfEvents_RawEvent(PerfEvents_RawEvent&&) noexcept;
+ PerfEvents_RawEvent& operator=(PerfEvents_RawEvent&&);
+ PerfEvents_RawEvent(const PerfEvents_RawEvent&);
+ PerfEvents_RawEvent& operator=(const PerfEvents_RawEvent&);
+ bool operator==(const PerfEvents_RawEvent&) const;
+ bool operator!=(const PerfEvents_RawEvent& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_type() const { return _has_field_[1]; }
+ uint32_t type() const { return type_; }
+ void set_type(uint32_t value) { type_ = value; _has_field_.set(1); }
+
+ bool has_config() const { return _has_field_[2]; }
+ uint64_t config() const { return config_; }
+ void set_config(uint64_t value) { config_ = value; _has_field_.set(2); }
+
+ bool has_config1() const { return _has_field_[3]; }
+ uint64_t config1() const { return config1_; }
+ void set_config1(uint64_t value) { config1_ = value; _has_field_.set(3); }
+
+ bool has_config2() const { return _has_field_[4]; }
+ uint64_t config2() const { return config2_; }
+ void set_config2(uint64_t value) { config2_ = value; _has_field_.set(4); }
+
+ private:
+ uint32_t type_{};
+ uint64_t config_{};
+ uint64_t config1_{};
+ uint64_t config2_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT PerfEvents_Tracepoint : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kFilterFieldNumber = 2,
+ };
+
+ PerfEvents_Tracepoint();
+ ~PerfEvents_Tracepoint() override;
+ PerfEvents_Tracepoint(PerfEvents_Tracepoint&&) noexcept;
+ PerfEvents_Tracepoint& operator=(PerfEvents_Tracepoint&&);
+ PerfEvents_Tracepoint(const PerfEvents_Tracepoint&);
+ PerfEvents_Tracepoint& operator=(const PerfEvents_Tracepoint&);
+ bool operator==(const PerfEvents_Tracepoint&) const;
+ bool operator!=(const PerfEvents_Tracepoint& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_filter() const { return _has_field_[2]; }
+ const std::string& filter() const { return filter_; }
+ void set_filter(const std::string& value) { filter_ = value; _has_field_.set(2); }
+
+ private:
+ std::string name_{};
+ std::string filter_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT PerfEvents_Timebase : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kFrequencyFieldNumber = 2,
+ kPeriodFieldNumber = 1,
+ kCounterFieldNumber = 4,
+ kTracepointFieldNumber = 3,
+ kRawEventFieldNumber = 5,
+ kTimestampClockFieldNumber = 11,
+ kNameFieldNumber = 10,
+ };
+
+ PerfEvents_Timebase();
+ ~PerfEvents_Timebase() override;
+ PerfEvents_Timebase(PerfEvents_Timebase&&) noexcept;
+ PerfEvents_Timebase& operator=(PerfEvents_Timebase&&);
+ PerfEvents_Timebase(const PerfEvents_Timebase&);
+ PerfEvents_Timebase& operator=(const PerfEvents_Timebase&);
+ bool operator==(const PerfEvents_Timebase&) const;
+ bool operator!=(const PerfEvents_Timebase& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_frequency() const { return _has_field_[2]; }
+ uint64_t frequency() const { return frequency_; }
+ void set_frequency(uint64_t value) { frequency_ = value; _has_field_.set(2); }
+
+ bool has_period() const { return _has_field_[1]; }
+ uint64_t period() const { return period_; }
+ void set_period(uint64_t value) { period_ = value; _has_field_.set(1); }
+
+ bool has_counter() const { return _has_field_[4]; }
+ PerfEvents_Counter counter() const { return counter_; }
+ void set_counter(PerfEvents_Counter value) { counter_ = value; _has_field_.set(4); }
+
+ bool has_tracepoint() const { return _has_field_[3]; }
+ const PerfEvents_Tracepoint& tracepoint() const { return *tracepoint_; }
+ PerfEvents_Tracepoint* mutable_tracepoint() { _has_field_.set(3); return tracepoint_.get(); }
+
+ bool has_raw_event() const { return _has_field_[5]; }
+ const PerfEvents_RawEvent& raw_event() const { return *raw_event_; }
+ PerfEvents_RawEvent* mutable_raw_event() { _has_field_.set(5); return raw_event_.get(); }
+
+ bool has_timestamp_clock() const { return _has_field_[11]; }
+ PerfEvents_PerfClock timestamp_clock() const { return timestamp_clock_; }
+ void set_timestamp_clock(PerfEvents_PerfClock value) { timestamp_clock_ = value; _has_field_.set(11); }
+
+ bool has_name() const { return _has_field_[10]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(10); }
+
+ private:
+ uint64_t frequency_{};
+ uint64_t period_{};
+ PerfEvents_Counter counter_{};
+ ::protozero::CopyablePtr<PerfEvents_Tracepoint> tracepoint_;
+ ::protozero::CopyablePtr<PerfEvents_RawEvent> raw_event_;
+ PerfEvents_PerfClock timestamp_clock_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<12> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PERF_EVENTS_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/protolog_common.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PROTOLOG_COMMON_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PROTOLOG_COMMON_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ProtoLogLevel : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ProtoLogLevel : int {
+ PROTOLOG_LEVEL_UNDEFINED = 0,
+ PROTOLOG_LEVEL_DEBUG = 1,
+ PROTOLOG_LEVEL_VERBOSE = 2,
+ PROTOLOG_LEVEL_INFO = 3,
+ PROTOLOG_LEVEL_WARN = 4,
+ PROTOLOG_LEVEL_ERROR = 5,
+ PROTOLOG_LEVEL_WTF = 6,
+};
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PROTOLOG_COMMON_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/sys_stats_counters.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_SYS_STATS_COUNTERS_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_SYS_STATS_COUNTERS_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum MeminfoCounters : int;
+enum VmstatCounters : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum MeminfoCounters : int {
+ MEMINFO_UNSPECIFIED = 0,
+ MEMINFO_MEM_TOTAL = 1,
+ MEMINFO_MEM_FREE = 2,
+ MEMINFO_MEM_AVAILABLE = 3,
+ MEMINFO_BUFFERS = 4,
+ MEMINFO_CACHED = 5,
+ MEMINFO_SWAP_CACHED = 6,
+ MEMINFO_ACTIVE = 7,
+ MEMINFO_INACTIVE = 8,
+ MEMINFO_ACTIVE_ANON = 9,
+ MEMINFO_INACTIVE_ANON = 10,
+ MEMINFO_ACTIVE_FILE = 11,
+ MEMINFO_INACTIVE_FILE = 12,
+ MEMINFO_UNEVICTABLE = 13,
+ MEMINFO_MLOCKED = 14,
+ MEMINFO_SWAP_TOTAL = 15,
+ MEMINFO_SWAP_FREE = 16,
+ MEMINFO_DIRTY = 17,
+ MEMINFO_WRITEBACK = 18,
+ MEMINFO_ANON_PAGES = 19,
+ MEMINFO_MAPPED = 20,
+ MEMINFO_SHMEM = 21,
+ MEMINFO_SLAB = 22,
+ MEMINFO_SLAB_RECLAIMABLE = 23,
+ MEMINFO_SLAB_UNRECLAIMABLE = 24,
+ MEMINFO_KERNEL_STACK = 25,
+ MEMINFO_PAGE_TABLES = 26,
+ MEMINFO_COMMIT_LIMIT = 27,
+ MEMINFO_COMMITED_AS = 28,
+ MEMINFO_VMALLOC_TOTAL = 29,
+ MEMINFO_VMALLOC_USED = 30,
+ MEMINFO_VMALLOC_CHUNK = 31,
+ MEMINFO_CMA_TOTAL = 32,
+ MEMINFO_CMA_FREE = 33,
+};
+enum VmstatCounters : int {
+ VMSTAT_UNSPECIFIED = 0,
+ VMSTAT_NR_FREE_PAGES = 1,
+ VMSTAT_NR_ALLOC_BATCH = 2,
+ VMSTAT_NR_INACTIVE_ANON = 3,
+ VMSTAT_NR_ACTIVE_ANON = 4,
+ VMSTAT_NR_INACTIVE_FILE = 5,
+ VMSTAT_NR_ACTIVE_FILE = 6,
+ VMSTAT_NR_UNEVICTABLE = 7,
+ VMSTAT_NR_MLOCK = 8,
+ VMSTAT_NR_ANON_PAGES = 9,
+ VMSTAT_NR_MAPPED = 10,
+ VMSTAT_NR_FILE_PAGES = 11,
+ VMSTAT_NR_DIRTY = 12,
+ VMSTAT_NR_WRITEBACK = 13,
+ VMSTAT_NR_SLAB_RECLAIMABLE = 14,
+ VMSTAT_NR_SLAB_UNRECLAIMABLE = 15,
+ VMSTAT_NR_PAGE_TABLE_PAGES = 16,
+ VMSTAT_NR_KERNEL_STACK = 17,
+ VMSTAT_NR_OVERHEAD = 18,
+ VMSTAT_NR_UNSTABLE = 19,
+ VMSTAT_NR_BOUNCE = 20,
+ VMSTAT_NR_VMSCAN_WRITE = 21,
+ VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM = 22,
+ VMSTAT_NR_WRITEBACK_TEMP = 23,
+ VMSTAT_NR_ISOLATED_ANON = 24,
+ VMSTAT_NR_ISOLATED_FILE = 25,
+ VMSTAT_NR_SHMEM = 26,
+ VMSTAT_NR_DIRTIED = 27,
+ VMSTAT_NR_WRITTEN = 28,
+ VMSTAT_NR_PAGES_SCANNED = 29,
+ VMSTAT_WORKINGSET_REFAULT = 30,
+ VMSTAT_WORKINGSET_ACTIVATE = 31,
+ VMSTAT_WORKINGSET_NODERECLAIM = 32,
+ VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES = 33,
+ VMSTAT_NR_FREE_CMA = 34,
+ VMSTAT_NR_SWAPCACHE = 35,
+ VMSTAT_NR_DIRTY_THRESHOLD = 36,
+ VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD = 37,
+ VMSTAT_PGPGIN = 38,
+ VMSTAT_PGPGOUT = 39,
+ VMSTAT_PGPGOUTCLEAN = 40,
+ VMSTAT_PSWPIN = 41,
+ VMSTAT_PSWPOUT = 42,
+ VMSTAT_PGALLOC_DMA = 43,
+ VMSTAT_PGALLOC_NORMAL = 44,
+ VMSTAT_PGALLOC_MOVABLE = 45,
+ VMSTAT_PGFREE = 46,
+ VMSTAT_PGACTIVATE = 47,
+ VMSTAT_PGDEACTIVATE = 48,
+ VMSTAT_PGFAULT = 49,
+ VMSTAT_PGMAJFAULT = 50,
+ VMSTAT_PGREFILL_DMA = 51,
+ VMSTAT_PGREFILL_NORMAL = 52,
+ VMSTAT_PGREFILL_MOVABLE = 53,
+ VMSTAT_PGSTEAL_KSWAPD_DMA = 54,
+ VMSTAT_PGSTEAL_KSWAPD_NORMAL = 55,
+ VMSTAT_PGSTEAL_KSWAPD_MOVABLE = 56,
+ VMSTAT_PGSTEAL_DIRECT_DMA = 57,
+ VMSTAT_PGSTEAL_DIRECT_NORMAL = 58,
+ VMSTAT_PGSTEAL_DIRECT_MOVABLE = 59,
+ VMSTAT_PGSCAN_KSWAPD_DMA = 60,
+ VMSTAT_PGSCAN_KSWAPD_NORMAL = 61,
+ VMSTAT_PGSCAN_KSWAPD_MOVABLE = 62,
+ VMSTAT_PGSCAN_DIRECT_DMA = 63,
+ VMSTAT_PGSCAN_DIRECT_NORMAL = 64,
+ VMSTAT_PGSCAN_DIRECT_MOVABLE = 65,
+ VMSTAT_PGSCAN_DIRECT_THROTTLE = 66,
+ VMSTAT_PGINODESTEAL = 67,
+ VMSTAT_SLABS_SCANNED = 68,
+ VMSTAT_KSWAPD_INODESTEAL = 69,
+ VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY = 70,
+ VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY = 71,
+ VMSTAT_PAGEOUTRUN = 72,
+ VMSTAT_ALLOCSTALL = 73,
+ VMSTAT_PGROTATED = 74,
+ VMSTAT_DROP_PAGECACHE = 75,
+ VMSTAT_DROP_SLAB = 76,
+ VMSTAT_PGMIGRATE_SUCCESS = 77,
+ VMSTAT_PGMIGRATE_FAIL = 78,
+ VMSTAT_COMPACT_MIGRATE_SCANNED = 79,
+ VMSTAT_COMPACT_FREE_SCANNED = 80,
+ VMSTAT_COMPACT_ISOLATED = 81,
+ VMSTAT_COMPACT_STALL = 82,
+ VMSTAT_COMPACT_FAIL = 83,
+ VMSTAT_COMPACT_SUCCESS = 84,
+ VMSTAT_COMPACT_DAEMON_WAKE = 85,
+ VMSTAT_UNEVICTABLE_PGS_CULLED = 86,
+ VMSTAT_UNEVICTABLE_PGS_SCANNED = 87,
+ VMSTAT_UNEVICTABLE_PGS_RESCUED = 88,
+ VMSTAT_UNEVICTABLE_PGS_MLOCKED = 89,
+ VMSTAT_UNEVICTABLE_PGS_MUNLOCKED = 90,
+ VMSTAT_UNEVICTABLE_PGS_CLEARED = 91,
+ VMSTAT_UNEVICTABLE_PGS_STRANDED = 92,
+ VMSTAT_NR_ZSPAGES = 93,
+ VMSTAT_NR_ION_HEAP = 94,
+ VMSTAT_NR_GPU_HEAP = 95,
+ VMSTAT_ALLOCSTALL_DMA = 96,
+ VMSTAT_ALLOCSTALL_MOVABLE = 97,
+ VMSTAT_ALLOCSTALL_NORMAL = 98,
+ VMSTAT_COMPACT_DAEMON_FREE_SCANNED = 99,
+ VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED = 100,
+ VMSTAT_NR_FASTRPC = 101,
+ VMSTAT_NR_INDIRECTLY_RECLAIMABLE = 102,
+ VMSTAT_NR_ION_HEAP_POOL = 103,
+ VMSTAT_NR_KERNEL_MISC_RECLAIMABLE = 104,
+ VMSTAT_NR_SHADOW_CALL_STACK_BYTES = 105,
+ VMSTAT_NR_SHMEM_HUGEPAGES = 106,
+ VMSTAT_NR_SHMEM_PMDMAPPED = 107,
+ VMSTAT_NR_UNRECLAIMABLE_PAGES = 108,
+ VMSTAT_NR_ZONE_ACTIVE_ANON = 109,
+ VMSTAT_NR_ZONE_ACTIVE_FILE = 110,
+ VMSTAT_NR_ZONE_INACTIVE_ANON = 111,
+ VMSTAT_NR_ZONE_INACTIVE_FILE = 112,
+ VMSTAT_NR_ZONE_UNEVICTABLE = 113,
+ VMSTAT_NR_ZONE_WRITE_PENDING = 114,
+ VMSTAT_OOM_KILL = 115,
+ VMSTAT_PGLAZYFREE = 116,
+ VMSTAT_PGLAZYFREED = 117,
+ VMSTAT_PGREFILL = 118,
+ VMSTAT_PGSCAN_DIRECT = 119,
+ VMSTAT_PGSCAN_KSWAPD = 120,
+ VMSTAT_PGSKIP_DMA = 121,
+ VMSTAT_PGSKIP_MOVABLE = 122,
+ VMSTAT_PGSKIP_NORMAL = 123,
+ VMSTAT_PGSTEAL_DIRECT = 124,
+ VMSTAT_PGSTEAL_KSWAPD = 125,
+ VMSTAT_SWAP_RA = 126,
+ VMSTAT_SWAP_RA_HIT = 127,
+ VMSTAT_WORKINGSET_RESTORE = 128,
+ VMSTAT_ALLOCSTALL_DEVICE = 129,
+ VMSTAT_ALLOCSTALL_DMA32 = 130,
+ VMSTAT_BALLOON_DEFLATE = 131,
+ VMSTAT_BALLOON_INFLATE = 132,
+ VMSTAT_BALLOON_MIGRATE = 133,
+ VMSTAT_CMA_ALLOC_FAIL = 134,
+ VMSTAT_CMA_ALLOC_SUCCESS = 135,
+ VMSTAT_NR_FILE_HUGEPAGES = 136,
+ VMSTAT_NR_FILE_PMDMAPPED = 137,
+ VMSTAT_NR_FOLL_PIN_ACQUIRED = 138,
+ VMSTAT_NR_FOLL_PIN_RELEASED = 139,
+ VMSTAT_NR_SEC_PAGE_TABLE_PAGES = 140,
+ VMSTAT_NR_SHADOW_CALL_STACK = 141,
+ VMSTAT_NR_SWAPCACHED = 142,
+ VMSTAT_NR_THROTTLED_WRITTEN = 143,
+ VMSTAT_PGALLOC_DEVICE = 144,
+ VMSTAT_PGALLOC_DMA32 = 145,
+ VMSTAT_PGDEMOTE_DIRECT = 146,
+ VMSTAT_PGDEMOTE_KSWAPD = 147,
+ VMSTAT_PGREUSE = 148,
+ VMSTAT_PGSCAN_ANON = 149,
+ VMSTAT_PGSCAN_FILE = 150,
+ VMSTAT_PGSKIP_DEVICE = 151,
+ VMSTAT_PGSKIP_DMA32 = 152,
+ VMSTAT_PGSTEAL_ANON = 153,
+ VMSTAT_PGSTEAL_FILE = 154,
+ VMSTAT_THP_COLLAPSE_ALLOC = 155,
+ VMSTAT_THP_COLLAPSE_ALLOC_FAILED = 156,
+ VMSTAT_THP_DEFERRED_SPLIT_PAGE = 157,
+ VMSTAT_THP_FAULT_ALLOC = 158,
+ VMSTAT_THP_FAULT_FALLBACK = 159,
+ VMSTAT_THP_FAULT_FALLBACK_CHARGE = 160,
+ VMSTAT_THP_FILE_ALLOC = 161,
+ VMSTAT_THP_FILE_FALLBACK = 162,
+ VMSTAT_THP_FILE_FALLBACK_CHARGE = 163,
+ VMSTAT_THP_FILE_MAPPED = 164,
+ VMSTAT_THP_MIGRATION_FAIL = 165,
+ VMSTAT_THP_MIGRATION_SPLIT = 166,
+ VMSTAT_THP_MIGRATION_SUCCESS = 167,
+ VMSTAT_THP_SCAN_EXCEED_NONE_PTE = 168,
+ VMSTAT_THP_SCAN_EXCEED_SHARE_PTE = 169,
+ VMSTAT_THP_SCAN_EXCEED_SWAP_PTE = 170,
+ VMSTAT_THP_SPLIT_PAGE = 171,
+ VMSTAT_THP_SPLIT_PAGE_FAILED = 172,
+ VMSTAT_THP_SPLIT_PMD = 173,
+ VMSTAT_THP_SWPOUT = 174,
+ VMSTAT_THP_SWPOUT_FALLBACK = 175,
+ VMSTAT_THP_ZERO_PAGE_ALLOC = 176,
+ VMSTAT_THP_ZERO_PAGE_ALLOC_FAILED = 177,
+ VMSTAT_VMA_LOCK_ABORT = 178,
+ VMSTAT_VMA_LOCK_MISS = 179,
+ VMSTAT_VMA_LOCK_RETRY = 180,
+ VMSTAT_VMA_LOCK_SUCCESS = 181,
+ VMSTAT_WORKINGSET_ACTIVATE_ANON = 182,
+ VMSTAT_WORKINGSET_ACTIVATE_FILE = 183,
+ VMSTAT_WORKINGSET_NODES = 184,
+ VMSTAT_WORKINGSET_REFAULT_ANON = 185,
+ VMSTAT_WORKINGSET_REFAULT_FILE = 186,
+ VMSTAT_WORKINGSET_RESTORE_ANON = 187,
+ VMSTAT_WORKINGSET_RESTORE_FILE = 188,
+};
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_SYS_STATS_COUNTERS_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/trace_stats.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACE_STATS_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACE_STATS_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TraceStats;
+class TraceStats_FilterStats;
+class TraceStats_WriterStats;
+class TraceStats_BufferStats;
+enum TraceStats_FinalFlushOutcome : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum TraceStats_FinalFlushOutcome : int {
+ TraceStats_FinalFlushOutcome_FINAL_FLUSH_UNSPECIFIED = 0,
+ TraceStats_FinalFlushOutcome_FINAL_FLUSH_SUCCEEDED = 1,
+ TraceStats_FinalFlushOutcome_FINAL_FLUSH_FAILED = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT TraceStats : public ::protozero::CppMessageObj {
+ public:
+ using BufferStats = TraceStats_BufferStats;
+ using WriterStats = TraceStats_WriterStats;
+ using FilterStats = TraceStats_FilterStats;
+ using FinalFlushOutcome = TraceStats_FinalFlushOutcome;
+ static constexpr auto FINAL_FLUSH_UNSPECIFIED = TraceStats_FinalFlushOutcome_FINAL_FLUSH_UNSPECIFIED;
+ static constexpr auto FINAL_FLUSH_SUCCEEDED = TraceStats_FinalFlushOutcome_FINAL_FLUSH_SUCCEEDED;
+ static constexpr auto FINAL_FLUSH_FAILED = TraceStats_FinalFlushOutcome_FINAL_FLUSH_FAILED;
+ static constexpr auto FinalFlushOutcome_MIN = TraceStats_FinalFlushOutcome_FINAL_FLUSH_UNSPECIFIED;
+ static constexpr auto FinalFlushOutcome_MAX = TraceStats_FinalFlushOutcome_FINAL_FLUSH_FAILED;
+ enum FieldNumbers {
+ kBufferStatsFieldNumber = 1,
+ kChunkPayloadHistogramDefFieldNumber = 17,
+ kWriterStatsFieldNumber = 18,
+ kProducersConnectedFieldNumber = 2,
+ kProducersSeenFieldNumber = 3,
+ kDataSourcesRegisteredFieldNumber = 4,
+ kDataSourcesSeenFieldNumber = 5,
+ kTracingSessionsFieldNumber = 6,
+ kTotalBuffersFieldNumber = 7,
+ kChunksDiscardedFieldNumber = 8,
+ kPatchesDiscardedFieldNumber = 9,
+ kInvalidPacketsFieldNumber = 10,
+ kFilterStatsFieldNumber = 11,
+ kFlushesRequestedFieldNumber = 12,
+ kFlushesSucceededFieldNumber = 13,
+ kFlushesFailedFieldNumber = 14,
+ kFinalFlushOutcomeFieldNumber = 15,
+ };
+
+ TraceStats();
+ ~TraceStats() override;
+ TraceStats(TraceStats&&) noexcept;
+ TraceStats& operator=(TraceStats&&);
+ TraceStats(const TraceStats&);
+ TraceStats& operator=(const TraceStats&);
+ bool operator==(const TraceStats&) const;
+ bool operator!=(const TraceStats& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<TraceStats_BufferStats>& buffer_stats() const { return buffer_stats_; }
+ std::vector<TraceStats_BufferStats>* mutable_buffer_stats() { return &buffer_stats_; }
+ int buffer_stats_size() const;
+ void clear_buffer_stats();
+ TraceStats_BufferStats* add_buffer_stats();
+
+ const std::vector<int64_t>& chunk_payload_histogram_def() const { return chunk_payload_histogram_def_; }
+ std::vector<int64_t>* mutable_chunk_payload_histogram_def() { return &chunk_payload_histogram_def_; }
+ int chunk_payload_histogram_def_size() const { return static_cast<int>(chunk_payload_histogram_def_.size()); }
+ void clear_chunk_payload_histogram_def() { chunk_payload_histogram_def_.clear(); }
+ void add_chunk_payload_histogram_def(int64_t value) { chunk_payload_histogram_def_.emplace_back(value); }
+ int64_t* add_chunk_payload_histogram_def() { chunk_payload_histogram_def_.emplace_back(); return &chunk_payload_histogram_def_.back(); }
+
+ const std::vector<TraceStats_WriterStats>& writer_stats() const { return writer_stats_; }
+ std::vector<TraceStats_WriterStats>* mutable_writer_stats() { return &writer_stats_; }
+ int writer_stats_size() const;
+ void clear_writer_stats();
+ TraceStats_WriterStats* add_writer_stats();
+
+ bool has_producers_connected() const { return _has_field_[2]; }
+ uint32_t producers_connected() const { return producers_connected_; }
+ void set_producers_connected(uint32_t value) { producers_connected_ = value; _has_field_.set(2); }
+
+ bool has_producers_seen() const { return _has_field_[3]; }
+ uint64_t producers_seen() const { return producers_seen_; }
+ void set_producers_seen(uint64_t value) { producers_seen_ = value; _has_field_.set(3); }
+
+ bool has_data_sources_registered() const { return _has_field_[4]; }
+ uint32_t data_sources_registered() const { return data_sources_registered_; }
+ void set_data_sources_registered(uint32_t value) { data_sources_registered_ = value; _has_field_.set(4); }
+
+ bool has_data_sources_seen() const { return _has_field_[5]; }
+ uint64_t data_sources_seen() const { return data_sources_seen_; }
+ void set_data_sources_seen(uint64_t value) { data_sources_seen_ = value; _has_field_.set(5); }
+
+ bool has_tracing_sessions() const { return _has_field_[6]; }
+ uint32_t tracing_sessions() const { return tracing_sessions_; }
+ void set_tracing_sessions(uint32_t value) { tracing_sessions_ = value; _has_field_.set(6); }
+
+ bool has_total_buffers() const { return _has_field_[7]; }
+ uint32_t total_buffers() const { return total_buffers_; }
+ void set_total_buffers(uint32_t value) { total_buffers_ = value; _has_field_.set(7); }
+
+ bool has_chunks_discarded() const { return _has_field_[8]; }
+ uint64_t chunks_discarded() const { return chunks_discarded_; }
+ void set_chunks_discarded(uint64_t value) { chunks_discarded_ = value; _has_field_.set(8); }
+
+ bool has_patches_discarded() const { return _has_field_[9]; }
+ uint64_t patches_discarded() const { return patches_discarded_; }
+ void set_patches_discarded(uint64_t value) { patches_discarded_ = value; _has_field_.set(9); }
+
+ bool has_invalid_packets() const { return _has_field_[10]; }
+ uint64_t invalid_packets() const { return invalid_packets_; }
+ void set_invalid_packets(uint64_t value) { invalid_packets_ = value; _has_field_.set(10); }
+
+ bool has_filter_stats() const { return _has_field_[11]; }
+ const TraceStats_FilterStats& filter_stats() const { return *filter_stats_; }
+ TraceStats_FilterStats* mutable_filter_stats() { _has_field_.set(11); return filter_stats_.get(); }
+
+ bool has_flushes_requested() const { return _has_field_[12]; }
+ uint64_t flushes_requested() const { return flushes_requested_; }
+ void set_flushes_requested(uint64_t value) { flushes_requested_ = value; _has_field_.set(12); }
+
+ bool has_flushes_succeeded() const { return _has_field_[13]; }
+ uint64_t flushes_succeeded() const { return flushes_succeeded_; }
+ void set_flushes_succeeded(uint64_t value) { flushes_succeeded_ = value; _has_field_.set(13); }
+
+ bool has_flushes_failed() const { return _has_field_[14]; }
+ uint64_t flushes_failed() const { return flushes_failed_; }
+ void set_flushes_failed(uint64_t value) { flushes_failed_ = value; _has_field_.set(14); }
+
+ bool has_final_flush_outcome() const { return _has_field_[15]; }
+ TraceStats_FinalFlushOutcome final_flush_outcome() const { return final_flush_outcome_; }
+ void set_final_flush_outcome(TraceStats_FinalFlushOutcome value) { final_flush_outcome_ = value; _has_field_.set(15); }
+
+ private:
+ std::vector<TraceStats_BufferStats> buffer_stats_;
+ std::vector<int64_t> chunk_payload_histogram_def_;
+ std::vector<TraceStats_WriterStats> writer_stats_;
+ uint32_t producers_connected_{};
+ uint64_t producers_seen_{};
+ uint32_t data_sources_registered_{};
+ uint64_t data_sources_seen_{};
+ uint32_t tracing_sessions_{};
+ uint32_t total_buffers_{};
+ uint64_t chunks_discarded_{};
+ uint64_t patches_discarded_{};
+ uint64_t invalid_packets_{};
+ ::protozero::CopyablePtr<TraceStats_FilterStats> filter_stats_;
+ uint64_t flushes_requested_{};
+ uint64_t flushes_succeeded_{};
+ uint64_t flushes_failed_{};
+ TraceStats_FinalFlushOutcome final_flush_outcome_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<19> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceStats_FilterStats : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kInputPacketsFieldNumber = 1,
+ kInputBytesFieldNumber = 2,
+ kOutputBytesFieldNumber = 3,
+ kErrorsFieldNumber = 4,
+ kTimeTakenNsFieldNumber = 5,
+ kBytesDiscardedPerBufferFieldNumber = 20,
+ };
+
+ TraceStats_FilterStats();
+ ~TraceStats_FilterStats() override;
+ TraceStats_FilterStats(TraceStats_FilterStats&&) noexcept;
+ TraceStats_FilterStats& operator=(TraceStats_FilterStats&&);
+ TraceStats_FilterStats(const TraceStats_FilterStats&);
+ TraceStats_FilterStats& operator=(const TraceStats_FilterStats&);
+ bool operator==(const TraceStats_FilterStats&) const;
+ bool operator!=(const TraceStats_FilterStats& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_input_packets() const { return _has_field_[1]; }
+ uint64_t input_packets() const { return input_packets_; }
+ void set_input_packets(uint64_t value) { input_packets_ = value; _has_field_.set(1); }
+
+ bool has_input_bytes() const { return _has_field_[2]; }
+ uint64_t input_bytes() const { return input_bytes_; }
+ void set_input_bytes(uint64_t value) { input_bytes_ = value; _has_field_.set(2); }
+
+ bool has_output_bytes() const { return _has_field_[3]; }
+ uint64_t output_bytes() const { return output_bytes_; }
+ void set_output_bytes(uint64_t value) { output_bytes_ = value; _has_field_.set(3); }
+
+ bool has_errors() const { return _has_field_[4]; }
+ uint64_t errors() const { return errors_; }
+ void set_errors(uint64_t value) { errors_ = value; _has_field_.set(4); }
+
+ bool has_time_taken_ns() const { return _has_field_[5]; }
+ uint64_t time_taken_ns() const { return time_taken_ns_; }
+ void set_time_taken_ns(uint64_t value) { time_taken_ns_ = value; _has_field_.set(5); }
+
+ const std::vector<uint64_t>& bytes_discarded_per_buffer() const { return bytes_discarded_per_buffer_; }
+ std::vector<uint64_t>* mutable_bytes_discarded_per_buffer() { return &bytes_discarded_per_buffer_; }
+ int bytes_discarded_per_buffer_size() const { return static_cast<int>(bytes_discarded_per_buffer_.size()); }
+ void clear_bytes_discarded_per_buffer() { bytes_discarded_per_buffer_.clear(); }
+ void add_bytes_discarded_per_buffer(uint64_t value) { bytes_discarded_per_buffer_.emplace_back(value); }
+ uint64_t* add_bytes_discarded_per_buffer() { bytes_discarded_per_buffer_.emplace_back(); return &bytes_discarded_per_buffer_.back(); }
+
+ private:
+ uint64_t input_packets_{};
+ uint64_t input_bytes_{};
+ uint64_t output_bytes_{};
+ uint64_t errors_{};
+ uint64_t time_taken_ns_{};
+ std::vector<uint64_t> bytes_discarded_per_buffer_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<21> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceStats_WriterStats : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSequenceIdFieldNumber = 1,
+ kBufferFieldNumber = 4,
+ kChunkPayloadHistogramCountsFieldNumber = 2,
+ kChunkPayloadHistogramSumFieldNumber = 3,
+ };
+
+ TraceStats_WriterStats();
+ ~TraceStats_WriterStats() override;
+ TraceStats_WriterStats(TraceStats_WriterStats&&) noexcept;
+ TraceStats_WriterStats& operator=(TraceStats_WriterStats&&);
+ TraceStats_WriterStats(const TraceStats_WriterStats&);
+ TraceStats_WriterStats& operator=(const TraceStats_WriterStats&);
+ bool operator==(const TraceStats_WriterStats&) const;
+ bool operator!=(const TraceStats_WriterStats& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_sequence_id() const { return _has_field_[1]; }
+ uint64_t sequence_id() const { return sequence_id_; }
+ void set_sequence_id(uint64_t value) { sequence_id_ = value; _has_field_.set(1); }
+
+ bool has_buffer() const { return _has_field_[4]; }
+ uint32_t buffer() const { return buffer_; }
+ void set_buffer(uint32_t value) { buffer_ = value; _has_field_.set(4); }
+
+ const std::vector<uint64_t>& chunk_payload_histogram_counts() const { return chunk_payload_histogram_counts_; }
+ std::vector<uint64_t>* mutable_chunk_payload_histogram_counts() { return &chunk_payload_histogram_counts_; }
+ int chunk_payload_histogram_counts_size() const { return static_cast<int>(chunk_payload_histogram_counts_.size()); }
+ void clear_chunk_payload_histogram_counts() { chunk_payload_histogram_counts_.clear(); }
+ void add_chunk_payload_histogram_counts(uint64_t value) { chunk_payload_histogram_counts_.emplace_back(value); }
+ uint64_t* add_chunk_payload_histogram_counts() { chunk_payload_histogram_counts_.emplace_back(); return &chunk_payload_histogram_counts_.back(); }
+
+ const std::vector<int64_t>& chunk_payload_histogram_sum() const { return chunk_payload_histogram_sum_; }
+ std::vector<int64_t>* mutable_chunk_payload_histogram_sum() { return &chunk_payload_histogram_sum_; }
+ int chunk_payload_histogram_sum_size() const { return static_cast<int>(chunk_payload_histogram_sum_.size()); }
+ void clear_chunk_payload_histogram_sum() { chunk_payload_histogram_sum_.clear(); }
+ void add_chunk_payload_histogram_sum(int64_t value) { chunk_payload_histogram_sum_.emplace_back(value); }
+ int64_t* add_chunk_payload_histogram_sum() { chunk_payload_histogram_sum_.emplace_back(); return &chunk_payload_histogram_sum_.back(); }
+
+ private:
+ uint64_t sequence_id_{};
+ uint32_t buffer_{};
+ std::vector<uint64_t> chunk_payload_histogram_counts_;
+ std::vector<int64_t> chunk_payload_histogram_sum_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TraceStats_BufferStats : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kBufferSizeFieldNumber = 12,
+ kBytesWrittenFieldNumber = 1,
+ kBytesOverwrittenFieldNumber = 13,
+ kBytesReadFieldNumber = 14,
+ kPaddingBytesWrittenFieldNumber = 15,
+ kPaddingBytesClearedFieldNumber = 16,
+ kChunksWrittenFieldNumber = 2,
+ kChunksRewrittenFieldNumber = 10,
+ kChunksOverwrittenFieldNumber = 3,
+ kChunksDiscardedFieldNumber = 18,
+ kChunksReadFieldNumber = 17,
+ kChunksCommittedOutOfOrderFieldNumber = 11,
+ kWriteWrapCountFieldNumber = 4,
+ kPatchesSucceededFieldNumber = 5,
+ kPatchesFailedFieldNumber = 6,
+ kReadaheadsSucceededFieldNumber = 7,
+ kReadaheadsFailedFieldNumber = 8,
+ kAbiViolationsFieldNumber = 9,
+ kTraceWriterPacketLossFieldNumber = 19,
+ };
+
+ TraceStats_BufferStats();
+ ~TraceStats_BufferStats() override;
+ TraceStats_BufferStats(TraceStats_BufferStats&&) noexcept;
+ TraceStats_BufferStats& operator=(TraceStats_BufferStats&&);
+ TraceStats_BufferStats(const TraceStats_BufferStats&);
+ TraceStats_BufferStats& operator=(const TraceStats_BufferStats&);
+ bool operator==(const TraceStats_BufferStats&) const;
+ bool operator!=(const TraceStats_BufferStats& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_buffer_size() const { return _has_field_[12]; }
+ uint64_t buffer_size() const { return buffer_size_; }
+ void set_buffer_size(uint64_t value) { buffer_size_ = value; _has_field_.set(12); }
+
+ bool has_bytes_written() const { return _has_field_[1]; }
+ uint64_t bytes_written() const { return bytes_written_; }
+ void set_bytes_written(uint64_t value) { bytes_written_ = value; _has_field_.set(1); }
+
+ bool has_bytes_overwritten() const { return _has_field_[13]; }
+ uint64_t bytes_overwritten() const { return bytes_overwritten_; }
+ void set_bytes_overwritten(uint64_t value) { bytes_overwritten_ = value; _has_field_.set(13); }
+
+ bool has_bytes_read() const { return _has_field_[14]; }
+ uint64_t bytes_read() const { return bytes_read_; }
+ void set_bytes_read(uint64_t value) { bytes_read_ = value; _has_field_.set(14); }
+
+ bool has_padding_bytes_written() const { return _has_field_[15]; }
+ uint64_t padding_bytes_written() const { return padding_bytes_written_; }
+ void set_padding_bytes_written(uint64_t value) { padding_bytes_written_ = value; _has_field_.set(15); }
+
+ bool has_padding_bytes_cleared() const { return _has_field_[16]; }
+ uint64_t padding_bytes_cleared() const { return padding_bytes_cleared_; }
+ void set_padding_bytes_cleared(uint64_t value) { padding_bytes_cleared_ = value; _has_field_.set(16); }
+
+ bool has_chunks_written() const { return _has_field_[2]; }
+ uint64_t chunks_written() const { return chunks_written_; }
+ void set_chunks_written(uint64_t value) { chunks_written_ = value; _has_field_.set(2); }
+
+ bool has_chunks_rewritten() const { return _has_field_[10]; }
+ uint64_t chunks_rewritten() const { return chunks_rewritten_; }
+ void set_chunks_rewritten(uint64_t value) { chunks_rewritten_ = value; _has_field_.set(10); }
+
+ bool has_chunks_overwritten() const { return _has_field_[3]; }
+ uint64_t chunks_overwritten() const { return chunks_overwritten_; }
+ void set_chunks_overwritten(uint64_t value) { chunks_overwritten_ = value; _has_field_.set(3); }
+
+ bool has_chunks_discarded() const { return _has_field_[18]; }
+ uint64_t chunks_discarded() const { return chunks_discarded_; }
+ void set_chunks_discarded(uint64_t value) { chunks_discarded_ = value; _has_field_.set(18); }
+
+ bool has_chunks_read() const { return _has_field_[17]; }
+ uint64_t chunks_read() const { return chunks_read_; }
+ void set_chunks_read(uint64_t value) { chunks_read_ = value; _has_field_.set(17); }
+
+ bool has_chunks_committed_out_of_order() const { return _has_field_[11]; }
+ uint64_t chunks_committed_out_of_order() const { return chunks_committed_out_of_order_; }
+ void set_chunks_committed_out_of_order(uint64_t value) { chunks_committed_out_of_order_ = value; _has_field_.set(11); }
+
+ bool has_write_wrap_count() const { return _has_field_[4]; }
+ uint64_t write_wrap_count() const { return write_wrap_count_; }
+ void set_write_wrap_count(uint64_t value) { write_wrap_count_ = value; _has_field_.set(4); }
+
+ bool has_patches_succeeded() const { return _has_field_[5]; }
+ uint64_t patches_succeeded() const { return patches_succeeded_; }
+ void set_patches_succeeded(uint64_t value) { patches_succeeded_ = value; _has_field_.set(5); }
+
+ bool has_patches_failed() const { return _has_field_[6]; }
+ uint64_t patches_failed() const { return patches_failed_; }
+ void set_patches_failed(uint64_t value) { patches_failed_ = value; _has_field_.set(6); }
+
+ bool has_readaheads_succeeded() const { return _has_field_[7]; }
+ uint64_t readaheads_succeeded() const { return readaheads_succeeded_; }
+ void set_readaheads_succeeded(uint64_t value) { readaheads_succeeded_ = value; _has_field_.set(7); }
+
+ bool has_readaheads_failed() const { return _has_field_[8]; }
+ uint64_t readaheads_failed() const { return readaheads_failed_; }
+ void set_readaheads_failed(uint64_t value) { readaheads_failed_ = value; _has_field_.set(8); }
+
+ bool has_abi_violations() const { return _has_field_[9]; }
+ uint64_t abi_violations() const { return abi_violations_; }
+ void set_abi_violations(uint64_t value) { abi_violations_ = value; _has_field_.set(9); }
+
+ bool has_trace_writer_packet_loss() const { return _has_field_[19]; }
+ uint64_t trace_writer_packet_loss() const { return trace_writer_packet_loss_; }
+ void set_trace_writer_packet_loss(uint64_t value) { trace_writer_packet_loss_ = value; _has_field_.set(19); }
+
+ private:
+ uint64_t buffer_size_{};
+ uint64_t bytes_written_{};
+ uint64_t bytes_overwritten_{};
+ uint64_t bytes_read_{};
+ uint64_t padding_bytes_written_{};
+ uint64_t padding_bytes_cleared_{};
+ uint64_t chunks_written_{};
+ uint64_t chunks_rewritten_{};
+ uint64_t chunks_overwritten_{};
+ uint64_t chunks_discarded_{};
+ uint64_t chunks_read_{};
+ uint64_t chunks_committed_out_of_order_{};
+ uint64_t write_wrap_count_{};
+ uint64_t patches_succeeded_{};
+ uint64_t patches_failed_{};
+ uint64_t readaheads_succeeded_{};
+ uint64_t readaheads_failed_{};
+ uint64_t abi_violations_{};
+ uint64_t trace_writer_packet_loss_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<20> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACE_STATS_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/tracing_service_capabilities.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_CAPABILITIES_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_CAPABILITIES_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TracingServiceCapabilities;
+enum ObservableEvents_Type : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TracingServiceCapabilities : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kHasQueryCapabilitiesFieldNumber = 1,
+ kObservableEventsFieldNumber = 2,
+ kHasTraceConfigOutputPathFieldNumber = 3,
+ kHasCloneSessionFieldNumber = 4,
+ };
+
+ TracingServiceCapabilities();
+ ~TracingServiceCapabilities() override;
+ TracingServiceCapabilities(TracingServiceCapabilities&&) noexcept;
+ TracingServiceCapabilities& operator=(TracingServiceCapabilities&&);
+ TracingServiceCapabilities(const TracingServiceCapabilities&);
+ TracingServiceCapabilities& operator=(const TracingServiceCapabilities&);
+ bool operator==(const TracingServiceCapabilities&) const;
+ bool operator!=(const TracingServiceCapabilities& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_has_query_capabilities() const { return _has_field_[1]; }
+ bool has_query_capabilities() const { return has_query_capabilities_; }
+ void set_has_query_capabilities(bool value) { has_query_capabilities_ = value; _has_field_.set(1); }
+
+ const std::vector<ObservableEvents_Type>& observable_events() const { return observable_events_; }
+ std::vector<ObservableEvents_Type>* mutable_observable_events() { return &observable_events_; }
+ int observable_events_size() const { return static_cast<int>(observable_events_.size()); }
+ void clear_observable_events() { observable_events_.clear(); }
+ void add_observable_events(ObservableEvents_Type value) { observable_events_.emplace_back(value); }
+ ObservableEvents_Type* add_observable_events() { observable_events_.emplace_back(); return &observable_events_.back(); }
+
+ bool has_has_trace_config_output_path() const { return _has_field_[3]; }
+ bool has_trace_config_output_path() const { return has_trace_config_output_path_; }
+ void set_has_trace_config_output_path(bool value) { has_trace_config_output_path_ = value; _has_field_.set(3); }
+
+ bool has_has_clone_session() const { return _has_field_[4]; }
+ bool has_clone_session() const { return has_clone_session_; }
+ void set_has_clone_session(bool value) { has_clone_session_ = value; _has_field_.set(4); }
+
+ private:
+ bool has_query_capabilities_{};
+ std::vector<ObservableEvents_Type> observable_events_;
+ bool has_trace_config_output_path_{};
+ bool has_clone_session_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_CAPABILITIES_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/tracing_service_state.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_STATE_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_STATE_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TracingServiceState;
+class TracingServiceState_TracingSession;
+class TracingServiceState_DataSource;
+class DataSourceDescriptor;
+class TracingServiceState_Producer;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TracingServiceState : public ::protozero::CppMessageObj {
+ public:
+ using Producer = TracingServiceState_Producer;
+ using DataSource = TracingServiceState_DataSource;
+ using TracingSession = TracingServiceState_TracingSession;
+ enum FieldNumbers {
+ kProducersFieldNumber = 1,
+ kDataSourcesFieldNumber = 2,
+ kTracingSessionsFieldNumber = 6,
+ kSupportsTracingSessionsFieldNumber = 7,
+ kNumSessionsFieldNumber = 3,
+ kNumSessionsStartedFieldNumber = 4,
+ kTracingServiceVersionFieldNumber = 5,
+ };
+
+ TracingServiceState();
+ ~TracingServiceState() override;
+ TracingServiceState(TracingServiceState&&) noexcept;
+ TracingServiceState& operator=(TracingServiceState&&);
+ TracingServiceState(const TracingServiceState&);
+ TracingServiceState& operator=(const TracingServiceState&);
+ bool operator==(const TracingServiceState&) const;
+ bool operator!=(const TracingServiceState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<TracingServiceState_Producer>& producers() const { return producers_; }
+ std::vector<TracingServiceState_Producer>* mutable_producers() { return &producers_; }
+ int producers_size() const;
+ void clear_producers();
+ TracingServiceState_Producer* add_producers();
+
+ const std::vector<TracingServiceState_DataSource>& data_sources() const { return data_sources_; }
+ std::vector<TracingServiceState_DataSource>* mutable_data_sources() { return &data_sources_; }
+ int data_sources_size() const;
+ void clear_data_sources();
+ TracingServiceState_DataSource* add_data_sources();
+
+ const std::vector<TracingServiceState_TracingSession>& tracing_sessions() const { return tracing_sessions_; }
+ std::vector<TracingServiceState_TracingSession>* mutable_tracing_sessions() { return &tracing_sessions_; }
+ int tracing_sessions_size() const;
+ void clear_tracing_sessions();
+ TracingServiceState_TracingSession* add_tracing_sessions();
+
+ bool has_supports_tracing_sessions() const { return _has_field_[7]; }
+ bool supports_tracing_sessions() const { return supports_tracing_sessions_; }
+ void set_supports_tracing_sessions(bool value) { supports_tracing_sessions_ = value; _has_field_.set(7); }
+
+ bool has_num_sessions() const { return _has_field_[3]; }
+ int32_t num_sessions() const { return num_sessions_; }
+ void set_num_sessions(int32_t value) { num_sessions_ = value; _has_field_.set(3); }
+
+ bool has_num_sessions_started() const { return _has_field_[4]; }
+ int32_t num_sessions_started() const { return num_sessions_started_; }
+ void set_num_sessions_started(int32_t value) { num_sessions_started_ = value; _has_field_.set(4); }
+
+ bool has_tracing_service_version() const { return _has_field_[5]; }
+ const std::string& tracing_service_version() const { return tracing_service_version_; }
+ void set_tracing_service_version(const std::string& value) { tracing_service_version_ = value; _has_field_.set(5); }
+
+ private:
+ std::vector<TracingServiceState_Producer> producers_;
+ std::vector<TracingServiceState_DataSource> data_sources_;
+ std::vector<TracingServiceState_TracingSession> tracing_sessions_;
+ bool supports_tracing_sessions_{};
+ int32_t num_sessions_{};
+ int32_t num_sessions_started_{};
+ std::string tracing_service_version_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TracingServiceState_TracingSession : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIdFieldNumber = 1,
+ kConsumerUidFieldNumber = 2,
+ kStateFieldNumber = 3,
+ kUniqueSessionNameFieldNumber = 4,
+ kBufferSizeKbFieldNumber = 5,
+ kDurationMsFieldNumber = 6,
+ kNumDataSourcesFieldNumber = 7,
+ kStartRealtimeNsFieldNumber = 8,
+ kBugreportScoreFieldNumber = 9,
+ kBugreportFilenameFieldNumber = 10,
+ kIsStartedFieldNumber = 11,
+ };
+
+ TracingServiceState_TracingSession();
+ ~TracingServiceState_TracingSession() override;
+ TracingServiceState_TracingSession(TracingServiceState_TracingSession&&) noexcept;
+ TracingServiceState_TracingSession& operator=(TracingServiceState_TracingSession&&);
+ TracingServiceState_TracingSession(const TracingServiceState_TracingSession&);
+ TracingServiceState_TracingSession& operator=(const TracingServiceState_TracingSession&);
+ bool operator==(const TracingServiceState_TracingSession&) const;
+ bool operator!=(const TracingServiceState_TracingSession& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_id() const { return _has_field_[1]; }
+ uint64_t id() const { return id_; }
+ void set_id(uint64_t value) { id_ = value; _has_field_.set(1); }
+
+ bool has_consumer_uid() const { return _has_field_[2]; }
+ int32_t consumer_uid() const { return consumer_uid_; }
+ void set_consumer_uid(int32_t value) { consumer_uid_ = value; _has_field_.set(2); }
+
+ bool has_state() const { return _has_field_[3]; }
+ const std::string& state() const { return state_; }
+ void set_state(const std::string& value) { state_ = value; _has_field_.set(3); }
+
+ bool has_unique_session_name() const { return _has_field_[4]; }
+ const std::string& unique_session_name() const { return unique_session_name_; }
+ void set_unique_session_name(const std::string& value) { unique_session_name_ = value; _has_field_.set(4); }
+
+ const std::vector<uint32_t>& buffer_size_kb() const { return buffer_size_kb_; }
+ std::vector<uint32_t>* mutable_buffer_size_kb() { return &buffer_size_kb_; }
+ int buffer_size_kb_size() const { return static_cast<int>(buffer_size_kb_.size()); }
+ void clear_buffer_size_kb() { buffer_size_kb_.clear(); }
+ void add_buffer_size_kb(uint32_t value) { buffer_size_kb_.emplace_back(value); }
+ uint32_t* add_buffer_size_kb() { buffer_size_kb_.emplace_back(); return &buffer_size_kb_.back(); }
+
+ bool has_duration_ms() const { return _has_field_[6]; }
+ uint32_t duration_ms() const { return duration_ms_; }
+ void set_duration_ms(uint32_t value) { duration_ms_ = value; _has_field_.set(6); }
+
+ bool has_num_data_sources() const { return _has_field_[7]; }
+ uint32_t num_data_sources() const { return num_data_sources_; }
+ void set_num_data_sources(uint32_t value) { num_data_sources_ = value; _has_field_.set(7); }
+
+ bool has_start_realtime_ns() const { return _has_field_[8]; }
+ int64_t start_realtime_ns() const { return start_realtime_ns_; }
+ void set_start_realtime_ns(int64_t value) { start_realtime_ns_ = value; _has_field_.set(8); }
+
+ bool has_bugreport_score() const { return _has_field_[9]; }
+ int32_t bugreport_score() const { return bugreport_score_; }
+ void set_bugreport_score(int32_t value) { bugreport_score_ = value; _has_field_.set(9); }
+
+ bool has_bugreport_filename() const { return _has_field_[10]; }
+ const std::string& bugreport_filename() const { return bugreport_filename_; }
+ void set_bugreport_filename(const std::string& value) { bugreport_filename_ = value; _has_field_.set(10); }
+
+ bool has_is_started() const { return _has_field_[11]; }
+ bool is_started() const { return is_started_; }
+ void set_is_started(bool value) { is_started_ = value; _has_field_.set(11); }
+
+ private:
+ uint64_t id_{};
+ int32_t consumer_uid_{};
+ std::string state_{};
+ std::string unique_session_name_{};
+ std::vector<uint32_t> buffer_size_kb_;
+ uint32_t duration_ms_{};
+ uint32_t num_data_sources_{};
+ int64_t start_realtime_ns_{};
+ int32_t bugreport_score_{};
+ std::string bugreport_filename_{};
+ bool is_started_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<12> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TracingServiceState_DataSource : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDsDescriptorFieldNumber = 1,
+ kProducerIdFieldNumber = 2,
+ };
+
+ TracingServiceState_DataSource();
+ ~TracingServiceState_DataSource() override;
+ TracingServiceState_DataSource(TracingServiceState_DataSource&&) noexcept;
+ TracingServiceState_DataSource& operator=(TracingServiceState_DataSource&&);
+ TracingServiceState_DataSource(const TracingServiceState_DataSource&);
+ TracingServiceState_DataSource& operator=(const TracingServiceState_DataSource&);
+ bool operator==(const TracingServiceState_DataSource&) const;
+ bool operator!=(const TracingServiceState_DataSource& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_ds_descriptor() const { return _has_field_[1]; }
+ const DataSourceDescriptor& ds_descriptor() const { return *ds_descriptor_; }
+ DataSourceDescriptor* mutable_ds_descriptor() { _has_field_.set(1); return ds_descriptor_.get(); }
+
+ bool has_producer_id() const { return _has_field_[2]; }
+ int32_t producer_id() const { return producer_id_; }
+ void set_producer_id(int32_t value) { producer_id_ = value; _has_field_.set(2); }
+
+ private:
+ ::protozero::CopyablePtr<DataSourceDescriptor> ds_descriptor_;
+ int32_t producer_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TracingServiceState_Producer : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kPidFieldNumber = 5,
+ kUidFieldNumber = 3,
+ kSdkVersionFieldNumber = 4,
+ };
+
+ TracingServiceState_Producer();
+ ~TracingServiceState_Producer() override;
+ TracingServiceState_Producer(TracingServiceState_Producer&&) noexcept;
+ TracingServiceState_Producer& operator=(TracingServiceState_Producer&&);
+ TracingServiceState_Producer(const TracingServiceState_Producer&);
+ TracingServiceState_Producer& operator=(const TracingServiceState_Producer&);
+ bool operator==(const TracingServiceState_Producer&) const;
+ bool operator!=(const TracingServiceState_Producer& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_id() const { return _has_field_[1]; }
+ int32_t id() const { return id_; }
+ void set_id(int32_t value) { id_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ bool has_pid() const { return _has_field_[5]; }
+ int32_t pid() const { return pid_; }
+ void set_pid(int32_t value) { pid_ = value; _has_field_.set(5); }
+
+ bool has_uid() const { return _has_field_[3]; }
+ int32_t uid() const { return uid_; }
+ void set_uid(int32_t value) { uid_ = value; _has_field_.set(3); }
+
+ bool has_sdk_version() const { return _has_field_[4]; }
+ const std::string& sdk_version() const { return sdk_version_; }
+ void set_sdk_version(const std::string& value) { sdk_version_ = value; _has_field_.set(4); }
+
+ private:
+ int32_t id_{};
+ std::string name_{};
+ int32_t pid_{};
+ int32_t uid_{};
+ std::string sdk_version_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_STATE_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/track_event_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACK_EVENT_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACK_EVENT_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TrackEventDescriptor;
+class TrackEventCategory;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TrackEventDescriptor : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kAvailableCategoriesFieldNumber = 1,
+ };
+
+ TrackEventDescriptor();
+ ~TrackEventDescriptor() override;
+ TrackEventDescriptor(TrackEventDescriptor&&) noexcept;
+ TrackEventDescriptor& operator=(TrackEventDescriptor&&);
+ TrackEventDescriptor(const TrackEventDescriptor&);
+ TrackEventDescriptor& operator=(const TrackEventDescriptor&);
+ bool operator==(const TrackEventDescriptor&) const;
+ bool operator!=(const TrackEventDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<TrackEventCategory>& available_categories() const { return available_categories_; }
+ std::vector<TrackEventCategory>* mutable_available_categories() { return &available_categories_; }
+ int available_categories_size() const;
+ void clear_available_categories();
+ TrackEventCategory* add_available_categories();
+
+ private:
+ std::vector<TrackEventCategory> available_categories_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TrackEventCategory : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kDescriptionFieldNumber = 2,
+ kTagsFieldNumber = 3,
+ };
+
+ TrackEventCategory();
+ ~TrackEventCategory() override;
+ TrackEventCategory(TrackEventCategory&&) noexcept;
+ TrackEventCategory& operator=(TrackEventCategory&&);
+ TrackEventCategory(const TrackEventCategory&);
+ TrackEventCategory& operator=(const TrackEventCategory&);
+ bool operator==(const TrackEventCategory&) const;
+ bool operator!=(const TrackEventCategory& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_description() const { return _has_field_[2]; }
+ const std::string& description() const { return description_; }
+ void set_description(const std::string& value) { description_ = value; _has_field_.set(2); }
+
+ const std::vector<std::string>& tags() const { return tags_; }
+ std::vector<std::string>* mutable_tags() { return &tags_; }
+ int tags_size() const { return static_cast<int>(tags_.size()); }
+ void clear_tags() { tags_.clear(); }
+ void add_tags(std::string value) { tags_.emplace_back(value); }
+ std::string* add_tags() { tags_.emplace_back(); return &tags_.back(); }
+
+ private:
+ std::string name_{};
+ std::string description_{};
+ std::vector<std::string> tags_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACK_EVENT_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/common/android_energy_consumer_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_ENERGY_CONSUMER_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_ENERGY_CONSUMER_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidEnergyConsumer;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidEnergyConsumerDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidEnergyConsumerDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidEnergyConsumerDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidEnergyConsumerDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_energy_consumers() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> energy_consumers() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class AndroidEnergyConsumerDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = AndroidEnergyConsumerDescriptor_Decoder;
+ enum : int32_t {
+ kEnergyConsumersFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidEnergyConsumerDescriptor"; }
+
+
+ using FieldMetadata_EnergyConsumers =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidEnergyConsumer,
+ AndroidEnergyConsumerDescriptor>;
+
+ static constexpr FieldMetadata_EnergyConsumers kEnergyConsumers{};
+ template <typename T = AndroidEnergyConsumer> T* add_energy_consumers() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class AndroidEnergyConsumer_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidEnergyConsumer_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidEnergyConsumer_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidEnergyConsumer_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_energy_consumer_id() const { return at<1>().valid(); }
+ int32_t energy_consumer_id() const { return at<1>().as_int32(); }
+ bool has_ordinal() const { return at<2>().valid(); }
+ int32_t ordinal() const { return at<2>().as_int32(); }
+ bool has_type() const { return at<3>().valid(); }
+ ::protozero::ConstChars type() const { return at<3>().as_string(); }
+ bool has_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars name() const { return at<4>().as_string(); }
+};
+
+class AndroidEnergyConsumer : public ::protozero::Message {
+ public:
+ using Decoder = AndroidEnergyConsumer_Decoder;
+ enum : int32_t {
+ kEnergyConsumerIdFieldNumber = 1,
+ kOrdinalFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kNameFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidEnergyConsumer"; }
+
+
+ using FieldMetadata_EnergyConsumerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidEnergyConsumer>;
+
+ static constexpr FieldMetadata_EnergyConsumerId kEnergyConsumerId{};
+ void set_energy_consumer_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnergyConsumerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ordinal =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidEnergyConsumer>;
+
+ static constexpr FieldMetadata_Ordinal kOrdinal{};
+ void set_ordinal(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ordinal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidEnergyConsumer>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Type::kFieldId, data, size);
+ }
+ void set_type(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Type::kFieldId, chars.data, chars.size);
+ }
+ void set_type(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidEnergyConsumer>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/android_log_constants.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_LOG_CONSTANTS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_ANDROID_LOG_CONSTANTS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum AndroidLogId : int32_t {
+ LID_DEFAULT = 0,
+ LID_RADIO = 1,
+ LID_EVENTS = 2,
+ LID_SYSTEM = 3,
+ LID_CRASH = 4,
+ LID_STATS = 5,
+ LID_SECURITY = 6,
+ LID_KERNEL = 7,
+};
+
+constexpr AndroidLogId AndroidLogId_MIN = AndroidLogId::LID_DEFAULT;
+constexpr AndroidLogId AndroidLogId_MAX = AndroidLogId::LID_KERNEL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* AndroidLogId_Name(::perfetto::protos::pbzero::AndroidLogId value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_DEFAULT:
+ return "LID_DEFAULT";
+
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_RADIO:
+ return "LID_RADIO";
+
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_EVENTS:
+ return "LID_EVENTS";
+
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_SYSTEM:
+ return "LID_SYSTEM";
+
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_CRASH:
+ return "LID_CRASH";
+
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_STATS:
+ return "LID_STATS";
+
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_SECURITY:
+ return "LID_SECURITY";
+
+ case ::perfetto::protos::pbzero::AndroidLogId::LID_KERNEL:
+ return "LID_KERNEL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+enum AndroidLogPriority : int32_t {
+ PRIO_UNSPECIFIED = 0,
+ PRIO_UNUSED = 1,
+ PRIO_VERBOSE = 2,
+ PRIO_DEBUG = 3,
+ PRIO_INFO = 4,
+ PRIO_WARN = 5,
+ PRIO_ERROR = 6,
+ PRIO_FATAL = 7,
+};
+
+constexpr AndroidLogPriority AndroidLogPriority_MIN = AndroidLogPriority::PRIO_UNSPECIFIED;
+constexpr AndroidLogPriority AndroidLogPriority_MAX = AndroidLogPriority::PRIO_FATAL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* AndroidLogPriority_Name(::perfetto::protos::pbzero::AndroidLogPriority value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_UNSPECIFIED:
+ return "PRIO_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_UNUSED:
+ return "PRIO_UNUSED";
+
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_VERBOSE:
+ return "PRIO_VERBOSE";
+
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_DEBUG:
+ return "PRIO_DEBUG";
+
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_INFO:
+ return "PRIO_INFO";
+
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_WARN:
+ return "PRIO_WARN";
+
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_ERROR:
+ return "PRIO_ERROR";
+
+ case ::perfetto::protos::pbzero::AndroidLogPriority::PRIO_FATAL:
+ return "PRIO_FATAL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/commit_data_request.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_COMMIT_DATA_REQUEST_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_COMMIT_DATA_REQUEST_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class CommitDataRequest_ChunkToPatch;
+class CommitDataRequest_ChunkToPatch_Patch;
+class CommitDataRequest_ChunksToMove;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class CommitDataRequest_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ CommitDataRequest_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CommitDataRequest_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CommitDataRequest_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chunks_to_move() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> chunks_to_move() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_chunks_to_patch() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> chunks_to_patch() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_flush_request_id() const { return at<3>().valid(); }
+ uint64_t flush_request_id() const { return at<3>().as_uint64(); }
+};
+
+class CommitDataRequest : public ::protozero::Message {
+ public:
+ using Decoder = CommitDataRequest_Decoder;
+ enum : int32_t {
+ kChunksToMoveFieldNumber = 1,
+ kChunksToPatchFieldNumber = 2,
+ kFlushRequestIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CommitDataRequest"; }
+
+ using ChunksToMove = ::perfetto::protos::pbzero::CommitDataRequest_ChunksToMove;
+ using ChunkToPatch = ::perfetto::protos::pbzero::CommitDataRequest_ChunkToPatch;
+
+ using FieldMetadata_ChunksToMove =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CommitDataRequest_ChunksToMove,
+ CommitDataRequest>;
+
+ static constexpr FieldMetadata_ChunksToMove kChunksToMove{};
+ template <typename T = CommitDataRequest_ChunksToMove> T* add_chunks_to_move() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ChunksToPatch =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CommitDataRequest_ChunkToPatch,
+ CommitDataRequest>;
+
+ static constexpr FieldMetadata_ChunksToPatch kChunksToPatch{};
+ template <typename T = CommitDataRequest_ChunkToPatch> T* add_chunks_to_patch() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_FlushRequestId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CommitDataRequest>;
+
+ static constexpr FieldMetadata_FlushRequestId kFlushRequestId{};
+ void set_flush_request_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushRequestId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CommitDataRequest_ChunkToPatch_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ CommitDataRequest_ChunkToPatch_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CommitDataRequest_ChunkToPatch_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CommitDataRequest_ChunkToPatch_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_target_buffer() const { return at<1>().valid(); }
+ uint32_t target_buffer() const { return at<1>().as_uint32(); }
+ bool has_writer_id() const { return at<2>().valid(); }
+ uint32_t writer_id() const { return at<2>().as_uint32(); }
+ bool has_chunk_id() const { return at<3>().valid(); }
+ uint32_t chunk_id() const { return at<3>().as_uint32(); }
+ bool has_patches() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> patches() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_has_more_patches() const { return at<5>().valid(); }
+ bool has_more_patches() const { return at<5>().as_bool(); }
+};
+
+class CommitDataRequest_ChunkToPatch : public ::protozero::Message {
+ public:
+ using Decoder = CommitDataRequest_ChunkToPatch_Decoder;
+ enum : int32_t {
+ kTargetBufferFieldNumber = 1,
+ kWriterIdFieldNumber = 2,
+ kChunkIdFieldNumber = 3,
+ kPatchesFieldNumber = 4,
+ kHasMorePatchesFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CommitDataRequest.ChunkToPatch"; }
+
+ using Patch = ::perfetto::protos::pbzero::CommitDataRequest_ChunkToPatch_Patch;
+
+ using FieldMetadata_TargetBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CommitDataRequest_ChunkToPatch>;
+
+ static constexpr FieldMetadata_TargetBuffer kTargetBuffer{};
+ void set_target_buffer(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetBuffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WriterId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CommitDataRequest_ChunkToPatch>;
+
+ static constexpr FieldMetadata_WriterId kWriterId{};
+ void set_writer_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WriterId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunkId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CommitDataRequest_ChunkToPatch>;
+
+ static constexpr FieldMetadata_ChunkId kChunkId{};
+ void set_chunk_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunkId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Patches =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CommitDataRequest_ChunkToPatch_Patch,
+ CommitDataRequest_ChunkToPatch>;
+
+ static constexpr FieldMetadata_Patches kPatches{};
+ template <typename T = CommitDataRequest_ChunkToPatch_Patch> T* add_patches() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_HasMorePatches =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ CommitDataRequest_ChunkToPatch>;
+
+ static constexpr FieldMetadata_HasMorePatches kHasMorePatches{};
+ void set_has_more_patches(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasMorePatches::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CommitDataRequest_ChunkToPatch_Patch_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CommitDataRequest_ChunkToPatch_Patch_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CommitDataRequest_ChunkToPatch_Patch_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CommitDataRequest_ChunkToPatch_Patch_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_offset() const { return at<1>().valid(); }
+ uint32_t offset() const { return at<1>().as_uint32(); }
+ bool has_data() const { return at<2>().valid(); }
+ ::protozero::ConstBytes data() const { return at<2>().as_bytes(); }
+};
+
+class CommitDataRequest_ChunkToPatch_Patch : public ::protozero::Message {
+ public:
+ using Decoder = CommitDataRequest_ChunkToPatch_Patch_Decoder;
+ enum : int32_t {
+ kOffsetFieldNumber = 1,
+ kDataFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CommitDataRequest.ChunkToPatch.Patch"; }
+
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CommitDataRequest_ChunkToPatch_Patch>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Data =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ CommitDataRequest_ChunkToPatch_Patch>;
+
+ static constexpr FieldMetadata_Data kData{};
+ void set_data(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Data::kFieldId, data, size);
+ }
+ void set_data(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Data::kFieldId, bytes.data, bytes.size);
+ }
+ void set_data(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Data::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CommitDataRequest_ChunksToMove_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CommitDataRequest_ChunksToMove_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CommitDataRequest_ChunksToMove_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CommitDataRequest_ChunksToMove_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_page() const { return at<1>().valid(); }
+ uint32_t page() const { return at<1>().as_uint32(); }
+ bool has_chunk() const { return at<2>().valid(); }
+ uint32_t chunk() const { return at<2>().as_uint32(); }
+ bool has_target_buffer() const { return at<3>().valid(); }
+ uint32_t target_buffer() const { return at<3>().as_uint32(); }
+ bool has_data() const { return at<4>().valid(); }
+ ::protozero::ConstBytes data() const { return at<4>().as_bytes(); }
+};
+
+class CommitDataRequest_ChunksToMove : public ::protozero::Message {
+ public:
+ using Decoder = CommitDataRequest_ChunksToMove_Decoder;
+ enum : int32_t {
+ kPageFieldNumber = 1,
+ kChunkFieldNumber = 2,
+ kTargetBufferFieldNumber = 3,
+ kDataFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CommitDataRequest.ChunksToMove"; }
+
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CommitDataRequest_ChunksToMove>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Chunk =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CommitDataRequest_ChunksToMove>;
+
+ static constexpr FieldMetadata_Chunk kChunk{};
+ void set_chunk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chunk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CommitDataRequest_ChunksToMove>;
+
+ static constexpr FieldMetadata_TargetBuffer kTargetBuffer{};
+ void set_target_buffer(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetBuffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Data =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ CommitDataRequest_ChunksToMove>;
+
+ static constexpr FieldMetadata_Data kData{};
+ void set_data(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Data::kFieldId, data, size);
+ }
+ void set_data(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Data::kFieldId, bytes.data, bytes.size);
+ }
+ void set_data(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Data::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/data_source_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FtraceDescriptor;
+class GpuCounterDescriptor;
+class TrackEventDescriptor;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class DataSourceDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DataSourceDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DataSourceDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DataSourceDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_id() const { return at<7>().valid(); }
+ uint64_t id() const { return at<7>().as_uint64(); }
+ bool has_will_notify_on_stop() const { return at<2>().valid(); }
+ bool will_notify_on_stop() const { return at<2>().as_bool(); }
+ bool has_will_notify_on_start() const { return at<3>().valid(); }
+ bool will_notify_on_start() const { return at<3>().as_bool(); }
+ bool has_handles_incremental_state_clear() const { return at<4>().valid(); }
+ bool handles_incremental_state_clear() const { return at<4>().as_bool(); }
+ bool has_no_flush() const { return at<9>().valid(); }
+ bool no_flush() const { return at<9>().as_bool(); }
+ bool has_gpu_counter_descriptor() const { return at<5>().valid(); }
+ ::protozero::ConstBytes gpu_counter_descriptor() const { return at<5>().as_bytes(); }
+ bool has_track_event_descriptor() const { return at<6>().valid(); }
+ ::protozero::ConstBytes track_event_descriptor() const { return at<6>().as_bytes(); }
+ bool has_ftrace_descriptor() const { return at<8>().valid(); }
+ ::protozero::ConstBytes ftrace_descriptor() const { return at<8>().as_bytes(); }
+};
+
+class DataSourceDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = DataSourceDescriptor_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kIdFieldNumber = 7,
+ kWillNotifyOnStopFieldNumber = 2,
+ kWillNotifyOnStartFieldNumber = 3,
+ kHandlesIncrementalStateClearFieldNumber = 4,
+ kNoFlushFieldNumber = 9,
+ kGpuCounterDescriptorFieldNumber = 5,
+ kTrackEventDescriptorFieldNumber = 6,
+ kFtraceDescriptorFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DataSourceDescriptor"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WillNotifyOnStop =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_WillNotifyOnStop kWillNotifyOnStop{};
+ void set_will_notify_on_stop(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_WillNotifyOnStop::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WillNotifyOnStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_WillNotifyOnStart kWillNotifyOnStart{};
+ void set_will_notify_on_start(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_WillNotifyOnStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HandlesIncrementalStateClear =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_HandlesIncrementalStateClear kHandlesIncrementalStateClear{};
+ void set_handles_incremental_state_clear(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HandlesIncrementalStateClear::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NoFlush =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_NoFlush kNoFlush{};
+ void set_no_flush(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NoFlush::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GpuCounterDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuCounterDescriptor,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_GpuCounterDescriptor kGpuCounterDescriptor{};
+ template <typename T = GpuCounterDescriptor> T* set_gpu_counter_descriptor() {
+ return BeginNestedMessage<T>(5);
+ }
+
+ void set_gpu_counter_descriptor_raw(const std::string& raw) {
+ return AppendBytes(5, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_TrackEventDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackEventDescriptor,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_TrackEventDescriptor kTrackEventDescriptor{};
+ template <typename T = TrackEventDescriptor> T* set_track_event_descriptor() {
+ return BeginNestedMessage<T>(6);
+ }
+
+ void set_track_event_descriptor_raw(const std::string& raw) {
+ return AppendBytes(6, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_FtraceDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceDescriptor,
+ DataSourceDescriptor>;
+
+ static constexpr FieldMetadata_FtraceDescriptor kFtraceDescriptor{};
+ template <typename T = FtraceDescriptor> T* set_ftrace_descriptor() {
+ return BeginNestedMessage<T>(8);
+ }
+
+ void set_ftrace_descriptor_raw(const std::string& raw) {
+ return AppendBytes(8, raw.data(), raw.size());
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DescriptorProto;
+class DescriptorProto_ReservedRange;
+class EnumDescriptorProto;
+class EnumValueDescriptorProto;
+class FieldDescriptorProto;
+class FieldOptions;
+class FileDescriptorProto;
+class OneofDescriptorProto;
+class OneofOptions;
+class UninterpretedOption;
+class UninterpretedOption_NamePart;
+namespace perfetto_pbzero_enum_FieldDescriptorProto {
+enum Label : int32_t;
+} // namespace perfetto_pbzero_enum_FieldDescriptorProto
+using FieldDescriptorProto_Label = perfetto_pbzero_enum_FieldDescriptorProto::Label;
+namespace perfetto_pbzero_enum_FieldDescriptorProto {
+enum Type : int32_t;
+} // namespace perfetto_pbzero_enum_FieldDescriptorProto
+using FieldDescriptorProto_Type = perfetto_pbzero_enum_FieldDescriptorProto::Type;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_FieldDescriptorProto {
+enum Type : int32_t {
+ TYPE_DOUBLE = 1,
+ TYPE_FLOAT = 2,
+ TYPE_INT64 = 3,
+ TYPE_UINT64 = 4,
+ TYPE_INT32 = 5,
+ TYPE_FIXED64 = 6,
+ TYPE_FIXED32 = 7,
+ TYPE_BOOL = 8,
+ TYPE_STRING = 9,
+ TYPE_GROUP = 10,
+ TYPE_MESSAGE = 11,
+ TYPE_BYTES = 12,
+ TYPE_UINT32 = 13,
+ TYPE_ENUM = 14,
+ TYPE_SFIXED32 = 15,
+ TYPE_SFIXED64 = 16,
+ TYPE_SINT32 = 17,
+ TYPE_SINT64 = 18,
+};
+} // namespace perfetto_pbzero_enum_FieldDescriptorProto
+using FieldDescriptorProto_Type = perfetto_pbzero_enum_FieldDescriptorProto::Type;
+
+
+constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_MIN = FieldDescriptorProto_Type::TYPE_DOUBLE;
+constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_MAX = FieldDescriptorProto_Type::TYPE_SINT64;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FieldDescriptorProto_Type_Name(::perfetto::protos::pbzero::FieldDescriptorProto_Type value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_DOUBLE:
+ return "TYPE_DOUBLE";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_FLOAT:
+ return "TYPE_FLOAT";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_INT64:
+ return "TYPE_INT64";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_UINT64:
+ return "TYPE_UINT64";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_INT32:
+ return "TYPE_INT32";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_FIXED64:
+ return "TYPE_FIXED64";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_FIXED32:
+ return "TYPE_FIXED32";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_BOOL:
+ return "TYPE_BOOL";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_STRING:
+ return "TYPE_STRING";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_GROUP:
+ return "TYPE_GROUP";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_MESSAGE:
+ return "TYPE_MESSAGE";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_BYTES:
+ return "TYPE_BYTES";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_UINT32:
+ return "TYPE_UINT32";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_ENUM:
+ return "TYPE_ENUM";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_SFIXED32:
+ return "TYPE_SFIXED32";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_SFIXED64:
+ return "TYPE_SFIXED64";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_SINT32:
+ return "TYPE_SINT32";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Type::TYPE_SINT64:
+ return "TYPE_SINT64";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_FieldDescriptorProto {
+enum Label : int32_t {
+ LABEL_OPTIONAL = 1,
+ LABEL_REQUIRED = 2,
+ LABEL_REPEATED = 3,
+};
+} // namespace perfetto_pbzero_enum_FieldDescriptorProto
+using FieldDescriptorProto_Label = perfetto_pbzero_enum_FieldDescriptorProto::Label;
+
+
+constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_MIN = FieldDescriptorProto_Label::LABEL_OPTIONAL;
+constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_MAX = FieldDescriptorProto_Label::LABEL_REPEATED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FieldDescriptorProto_Label_Name(::perfetto::protos::pbzero::FieldDescriptorProto_Label value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Label::LABEL_OPTIONAL:
+ return "LABEL_OPTIONAL";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Label::LABEL_REQUIRED:
+ return "LABEL_REQUIRED";
+
+ case ::perfetto::protos::pbzero::FieldDescriptorProto_Label::LABEL_REPEATED:
+ return "LABEL_REPEATED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class OneofOptions_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ OneofOptions_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit OneofOptions_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit OneofOptions_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class OneofOptions : public ::protozero::Message {
+ public:
+ using Decoder = OneofOptions_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.OneofOptions"; }
+
+};
+
+class EnumValueDescriptorProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ EnumValueDescriptorProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EnumValueDescriptorProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EnumValueDescriptorProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_number() const { return at<2>().valid(); }
+ int32_t number() const { return at<2>().as_int32(); }
+};
+
+class EnumValueDescriptorProto : public ::protozero::Message {
+ public:
+ using Decoder = EnumValueDescriptorProto_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kNumberFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EnumValueDescriptorProto"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ EnumValueDescriptorProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Number =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ EnumValueDescriptorProto>;
+
+ static constexpr FieldMetadata_Number kNumber{};
+ void set_number(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Number::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class EnumDescriptorProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ EnumDescriptorProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EnumDescriptorProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EnumDescriptorProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> value() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_reserved_name() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> reserved_name() const { return GetRepeated<::protozero::ConstChars>(5); }
+};
+
+class EnumDescriptorProto : public ::protozero::Message {
+ public:
+ using Decoder = EnumDescriptorProto_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kValueFieldNumber = 2,
+ kReservedNameFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EnumDescriptorProto"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ EnumDescriptorProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EnumValueDescriptorProto,
+ EnumDescriptorProto>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ template <typename T = EnumValueDescriptorProto> T* add_value() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_ReservedName =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ EnumDescriptorProto>;
+
+ static constexpr FieldMetadata_ReservedName kReservedName{};
+ void add_reserved_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ReservedName::kFieldId, data, size);
+ }
+ void add_reserved_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ReservedName::kFieldId, chars.data, chars.size);
+ }
+ void add_reserved_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class OneofDescriptorProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ OneofDescriptorProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit OneofDescriptorProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit OneofDescriptorProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_options() const { return at<2>().valid(); }
+ ::protozero::ConstBytes options() const { return at<2>().as_bytes(); }
+};
+
+class OneofDescriptorProto : public ::protozero::Message {
+ public:
+ using Decoder = OneofDescriptorProto_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kOptionsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.OneofDescriptorProto"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ OneofDescriptorProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Options =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ OneofOptions,
+ OneofDescriptorProto>;
+
+ static constexpr FieldMetadata_Options kOptions{};
+ template <typename T = OneofOptions> T* set_options() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class FieldDescriptorProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FieldDescriptorProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FieldDescriptorProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FieldDescriptorProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_number() const { return at<3>().valid(); }
+ int32_t number() const { return at<3>().as_int32(); }
+ bool has_label() const { return at<4>().valid(); }
+ int32_t label() const { return at<4>().as_int32(); }
+ bool has_type() const { return at<5>().valid(); }
+ int32_t type() const { return at<5>().as_int32(); }
+ bool has_type_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars type_name() const { return at<6>().as_string(); }
+ bool has_extendee() const { return at<2>().valid(); }
+ ::protozero::ConstChars extendee() const { return at<2>().as_string(); }
+ bool has_default_value() const { return at<7>().valid(); }
+ ::protozero::ConstChars default_value() const { return at<7>().as_string(); }
+ bool has_options() const { return at<8>().valid(); }
+ ::protozero::ConstBytes options() const { return at<8>().as_bytes(); }
+ bool has_oneof_index() const { return at<9>().valid(); }
+ int32_t oneof_index() const { return at<9>().as_int32(); }
+};
+
+class FieldDescriptorProto : public ::protozero::Message {
+ public:
+ using Decoder = FieldDescriptorProto_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kNumberFieldNumber = 3,
+ kLabelFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ kTypeNameFieldNumber = 6,
+ kExtendeeFieldNumber = 2,
+ kDefaultValueFieldNumber = 7,
+ kOptionsFieldNumber = 8,
+ kOneofIndexFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FieldDescriptorProto"; }
+
+
+ using Type = ::perfetto::protos::pbzero::FieldDescriptorProto_Type;
+ static inline const char* Type_Name(Type value) {
+ return ::perfetto::protos::pbzero::FieldDescriptorProto_Type_Name(value);
+ }
+
+ using Label = ::perfetto::protos::pbzero::FieldDescriptorProto_Label;
+ static inline const char* Label_Name(Label value) {
+ return ::perfetto::protos::pbzero::FieldDescriptorProto_Label_Name(value);
+ }
+ static inline const Type TYPE_DOUBLE = Type::TYPE_DOUBLE;
+ static inline const Type TYPE_FLOAT = Type::TYPE_FLOAT;
+ static inline const Type TYPE_INT64 = Type::TYPE_INT64;
+ static inline const Type TYPE_UINT64 = Type::TYPE_UINT64;
+ static inline const Type TYPE_INT32 = Type::TYPE_INT32;
+ static inline const Type TYPE_FIXED64 = Type::TYPE_FIXED64;
+ static inline const Type TYPE_FIXED32 = Type::TYPE_FIXED32;
+ static inline const Type TYPE_BOOL = Type::TYPE_BOOL;
+ static inline const Type TYPE_STRING = Type::TYPE_STRING;
+ static inline const Type TYPE_GROUP = Type::TYPE_GROUP;
+ static inline const Type TYPE_MESSAGE = Type::TYPE_MESSAGE;
+ static inline const Type TYPE_BYTES = Type::TYPE_BYTES;
+ static inline const Type TYPE_UINT32 = Type::TYPE_UINT32;
+ static inline const Type TYPE_ENUM = Type::TYPE_ENUM;
+ static inline const Type TYPE_SFIXED32 = Type::TYPE_SFIXED32;
+ static inline const Type TYPE_SFIXED64 = Type::TYPE_SFIXED64;
+ static inline const Type TYPE_SINT32 = Type::TYPE_SINT32;
+ static inline const Type TYPE_SINT64 = Type::TYPE_SINT64;
+ static inline const Label LABEL_OPTIONAL = Label::LABEL_OPTIONAL;
+ static inline const Label LABEL_REQUIRED = Label::LABEL_REQUIRED;
+ static inline const Label LABEL_REPEATED = Label::LABEL_REPEATED;
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Number =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_Number kNumber{};
+ void set_number(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Number::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Label =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FieldDescriptorProto_Label,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_Label kLabel{};
+ void set_label(FieldDescriptorProto_Label value) {
+ static constexpr uint32_t field_id = FieldMetadata_Label::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FieldDescriptorProto_Type,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(FieldDescriptorProto_Type value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TypeName =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_TypeName kTypeName{};
+ void set_type_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TypeName::kFieldId, data, size);
+ }
+ void set_type_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TypeName::kFieldId, chars.data, chars.size);
+ }
+ void set_type_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TypeName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Extendee =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_Extendee kExtendee{};
+ void set_extendee(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Extendee::kFieldId, data, size);
+ }
+ void set_extendee(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Extendee::kFieldId, chars.data, chars.size);
+ }
+ void set_extendee(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Extendee::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DefaultValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_DefaultValue kDefaultValue{};
+ void set_default_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DefaultValue::kFieldId, data, size);
+ }
+ void set_default_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DefaultValue::kFieldId, chars.data, chars.size);
+ }
+ void set_default_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DefaultValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Options =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FieldOptions,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_Options kOptions{};
+ template <typename T = FieldOptions> T* set_options() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_OneofIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FieldDescriptorProto>;
+
+ static constexpr FieldMetadata_OneofIndex kOneofIndex{};
+ void set_oneof_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OneofIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FieldOptions_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/999, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FieldOptions_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FieldOptions_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FieldOptions_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_packed() const { return at<2>().valid(); }
+ bool packed() const { return at<2>().as_bool(); }
+ bool has_uninterpreted_option() const { return at<999>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> uninterpreted_option() const { return GetRepeated<::protozero::ConstBytes>(999); }
+};
+
+class FieldOptions : public ::protozero::Message {
+ public:
+ using Decoder = FieldOptions_Decoder;
+ enum : int32_t {
+ kPackedFieldNumber = 2,
+ kUninterpretedOptionFieldNumber = 999,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FieldOptions"; }
+
+
+ using FieldMetadata_Packed =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FieldOptions>;
+
+ static constexpr FieldMetadata_Packed kPacked{};
+ void set_packed(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Packed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UninterpretedOption =
+ ::protozero::proto_utils::FieldMetadata<
+ 999,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ UninterpretedOption,
+ FieldOptions>;
+
+ static constexpr FieldMetadata_UninterpretedOption kUninterpretedOption{};
+ template <typename T = UninterpretedOption> T* add_uninterpreted_option() {
+ return BeginNestedMessage<T>(999);
+ }
+
+};
+
+class UninterpretedOption_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ UninterpretedOption_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit UninterpretedOption_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit UninterpretedOption_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> name() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_identifier_value() const { return at<3>().valid(); }
+ ::protozero::ConstChars identifier_value() const { return at<3>().as_string(); }
+ bool has_positive_int_value() const { return at<4>().valid(); }
+ uint64_t positive_int_value() const { return at<4>().as_uint64(); }
+ bool has_negative_int_value() const { return at<5>().valid(); }
+ int64_t negative_int_value() const { return at<5>().as_int64(); }
+ bool has_double_value() const { return at<6>().valid(); }
+ double double_value() const { return at<6>().as_double(); }
+ bool has_string_value() const { return at<7>().valid(); }
+ ::protozero::ConstBytes string_value() const { return at<7>().as_bytes(); }
+ bool has_aggregate_value() const { return at<8>().valid(); }
+ ::protozero::ConstChars aggregate_value() const { return at<8>().as_string(); }
+};
+
+class UninterpretedOption : public ::protozero::Message {
+ public:
+ using Decoder = UninterpretedOption_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 2,
+ kIdentifierValueFieldNumber = 3,
+ kPositiveIntValueFieldNumber = 4,
+ kNegativeIntValueFieldNumber = 5,
+ kDoubleValueFieldNumber = 6,
+ kStringValueFieldNumber = 7,
+ kAggregateValueFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.UninterpretedOption"; }
+
+ using NamePart = ::perfetto::protos::pbzero::UninterpretedOption_NamePart;
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ UninterpretedOption_NamePart,
+ UninterpretedOption>;
+
+ static constexpr FieldMetadata_Name kName{};
+ template <typename T = UninterpretedOption_NamePart> T* add_name() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_IdentifierValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ UninterpretedOption>;
+
+ static constexpr FieldMetadata_IdentifierValue kIdentifierValue{};
+ void set_identifier_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_IdentifierValue::kFieldId, data, size);
+ }
+ void set_identifier_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_IdentifierValue::kFieldId, chars.data, chars.size);
+ }
+ void set_identifier_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_IdentifierValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PositiveIntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ UninterpretedOption>;
+
+ static constexpr FieldMetadata_PositiveIntValue kPositiveIntValue{};
+ void set_positive_int_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PositiveIntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NegativeIntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ UninterpretedOption>;
+
+ static constexpr FieldMetadata_NegativeIntValue kNegativeIntValue{};
+ void set_negative_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NegativeIntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ UninterpretedOption>;
+
+ static constexpr FieldMetadata_DoubleValue kDoubleValue{};
+ void set_double_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ UninterpretedOption>;
+
+ static constexpr FieldMetadata_StringValue kStringValue{};
+ void set_string_value(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, data, size);
+ }
+ void set_string_value(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, bytes.data, bytes.size);
+ }
+ void set_string_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AggregateValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ UninterpretedOption>;
+
+ static constexpr FieldMetadata_AggregateValue kAggregateValue{};
+ void set_aggregate_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_AggregateValue::kFieldId, data, size);
+ }
+ void set_aggregate_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_AggregateValue::kFieldId, chars.data, chars.size);
+ }
+ void set_aggregate_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_AggregateValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class UninterpretedOption_NamePart_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ UninterpretedOption_NamePart_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit UninterpretedOption_NamePart_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit UninterpretedOption_NamePart_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name_part() const { return at<1>().valid(); }
+ ::protozero::ConstChars name_part() const { return at<1>().as_string(); }
+ bool has_is_extension() const { return at<2>().valid(); }
+ bool is_extension() const { return at<2>().as_bool(); }
+};
+
+class UninterpretedOption_NamePart : public ::protozero::Message {
+ public:
+ using Decoder = UninterpretedOption_NamePart_Decoder;
+ enum : int32_t {
+ kNamePartFieldNumber = 1,
+ kIsExtensionFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.UninterpretedOption.NamePart"; }
+
+
+ using FieldMetadata_NamePart =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ UninterpretedOption_NamePart>;
+
+ static constexpr FieldMetadata_NamePart kNamePart{};
+ void set_name_part(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_NamePart::kFieldId, data, size);
+ }
+ void set_name_part(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_NamePart::kFieldId, chars.data, chars.size);
+ }
+ void set_name_part(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_NamePart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsExtension =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ UninterpretedOption_NamePart>;
+
+ static constexpr FieldMetadata_IsExtension kIsExtension{};
+ void set_is_extension(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsExtension::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DescriptorProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ DescriptorProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DescriptorProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DescriptorProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_field() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> field() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_extension() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> extension() const { return GetRepeated<::protozero::ConstBytes>(6); }
+ bool has_nested_type() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> nested_type() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_enum_type() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> enum_type() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_oneof_decl() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> oneof_decl() const { return GetRepeated<::protozero::ConstBytes>(8); }
+ bool has_reserved_range() const { return at<9>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> reserved_range() const { return GetRepeated<::protozero::ConstBytes>(9); }
+ bool has_reserved_name() const { return at<10>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> reserved_name() const { return GetRepeated<::protozero::ConstChars>(10); }
+};
+
+class DescriptorProto : public ::protozero::Message {
+ public:
+ using Decoder = DescriptorProto_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kFieldFieldNumber = 2,
+ kExtensionFieldNumber = 6,
+ kNestedTypeFieldNumber = 3,
+ kEnumTypeFieldNumber = 4,
+ kOneofDeclFieldNumber = 8,
+ kReservedRangeFieldNumber = 9,
+ kReservedNameFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DescriptorProto"; }
+
+ using ReservedRange = ::perfetto::protos::pbzero::DescriptorProto_ReservedRange;
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FieldDescriptorProto,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_Field kField{};
+ template <typename T = FieldDescriptorProto> T* add_field() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_Extension =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FieldDescriptorProto,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_Extension kExtension{};
+ template <typename T = FieldDescriptorProto> T* add_extension() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_NestedType =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DescriptorProto,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_NestedType kNestedType{};
+ template <typename T = DescriptorProto> T* add_nested_type() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_EnumType =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EnumDescriptorProto,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_EnumType kEnumType{};
+ template <typename T = EnumDescriptorProto> T* add_enum_type() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_OneofDecl =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ OneofDescriptorProto,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_OneofDecl kOneofDecl{};
+ template <typename T = OneofDescriptorProto> T* add_oneof_decl() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_ReservedRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DescriptorProto_ReservedRange,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_ReservedRange kReservedRange{};
+ template <typename T = DescriptorProto_ReservedRange> T* add_reserved_range() {
+ return BeginNestedMessage<T>(9);
+ }
+
+
+ using FieldMetadata_ReservedName =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DescriptorProto>;
+
+ static constexpr FieldMetadata_ReservedName kReservedName{};
+ void add_reserved_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ReservedName::kFieldId, data, size);
+ }
+ void add_reserved_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ReservedName::kFieldId, chars.data, chars.size);
+ }
+ void add_reserved_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DescriptorProto_ReservedRange_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DescriptorProto_ReservedRange_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DescriptorProto_ReservedRange_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DescriptorProto_ReservedRange_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_start() const { return at<1>().valid(); }
+ int32_t start() const { return at<1>().as_int32(); }
+ bool has_end() const { return at<2>().valid(); }
+ int32_t end() const { return at<2>().as_int32(); }
+};
+
+class DescriptorProto_ReservedRange : public ::protozero::Message {
+ public:
+ using Decoder = DescriptorProto_ReservedRange_Decoder;
+ enum : int32_t {
+ kStartFieldNumber = 1,
+ kEndFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DescriptorProto.ReservedRange"; }
+
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DescriptorProto_ReservedRange>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_End =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DescriptorProto_ReservedRange>;
+
+ static constexpr FieldMetadata_End kEnd{};
+ void set_end(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_End::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FileDescriptorProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FileDescriptorProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FileDescriptorProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FileDescriptorProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_package() const { return at<2>().valid(); }
+ ::protozero::ConstChars package() const { return at<2>().as_string(); }
+ bool has_dependency() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> dependency() const { return GetRepeated<::protozero::ConstChars>(3); }
+ bool has_public_dependency() const { return at<10>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> public_dependency() const { return GetRepeated<int32_t>(10); }
+ bool has_weak_dependency() const { return at<11>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> weak_dependency() const { return GetRepeated<int32_t>(11); }
+ bool has_message_type() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> message_type() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_enum_type() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> enum_type() const { return GetRepeated<::protozero::ConstBytes>(5); }
+ bool has_extension() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> extension() const { return GetRepeated<::protozero::ConstBytes>(7); }
+};
+
+class FileDescriptorProto : public ::protozero::Message {
+ public:
+ using Decoder = FileDescriptorProto_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kPackageFieldNumber = 2,
+ kDependencyFieldNumber = 3,
+ kPublicDependencyFieldNumber = 10,
+ kWeakDependencyFieldNumber = 11,
+ kMessageTypeFieldNumber = 4,
+ kEnumTypeFieldNumber = 5,
+ kExtensionFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FileDescriptorProto"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Package =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_Package kPackage{};
+ void set_package(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Package::kFieldId, data, size);
+ }
+ void set_package(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Package::kFieldId, chars.data, chars.size);
+ }
+ void set_package(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Package::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dependency =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_Dependency kDependency{};
+ void add_dependency(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Dependency::kFieldId, data, size);
+ }
+ void add_dependency(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Dependency::kFieldId, chars.data, chars.size);
+ }
+ void add_dependency(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dependency::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PublicDependency =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_PublicDependency kPublicDependency{};
+ void add_public_dependency(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PublicDependency::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WeakDependency =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_WeakDependency kWeakDependency{};
+ void add_weak_dependency(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WeakDependency::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MessageType =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DescriptorProto,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_MessageType kMessageType{};
+ template <typename T = DescriptorProto> T* add_message_type() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_EnumType =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EnumDescriptorProto,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_EnumType kEnumType{};
+ template <typename T = EnumDescriptorProto> T* add_enum_type() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_Extension =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FieldDescriptorProto,
+ FileDescriptorProto>;
+
+ static constexpr FieldMetadata_Extension kExtension{};
+ template <typename T = FieldDescriptorProto> T* add_extension() {
+ return BeginNestedMessage<T>(7);
+ }
+
+};
+
+class FileDescriptorSet_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FileDescriptorSet_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FileDescriptorSet_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FileDescriptorSet_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_file() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> file() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class FileDescriptorSet : public ::protozero::Message {
+ public:
+ using Decoder = FileDescriptorSet_Decoder;
+ enum : int32_t {
+ kFileFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FileDescriptorSet"; }
+
+
+ using FieldMetadata_File =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FileDescriptorProto,
+ FileDescriptorSet>;
+
+ static constexpr FieldMetadata_File kFile{};
+ template <typename T = FileDescriptorProto> T* add_file() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/ftrace_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_FTRACE_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_FTRACE_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FtraceDescriptor_AtraceCategory;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class FtraceDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FtraceDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_atrace_categories() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> atrace_categories() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class FtraceDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = FtraceDescriptor_Decoder;
+ enum : int32_t {
+ kAtraceCategoriesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceDescriptor"; }
+
+ using AtraceCategory = ::perfetto::protos::pbzero::FtraceDescriptor_AtraceCategory;
+
+ using FieldMetadata_AtraceCategories =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceDescriptor_AtraceCategory,
+ FtraceDescriptor>;
+
+ static constexpr FieldMetadata_AtraceCategories kAtraceCategories{};
+ template <typename T = FtraceDescriptor_AtraceCategory> T* add_atrace_categories() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class FtraceDescriptor_AtraceCategory_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FtraceDescriptor_AtraceCategory_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceDescriptor_AtraceCategory_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceDescriptor_AtraceCategory_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_description() const { return at<2>().valid(); }
+ ::protozero::ConstChars description() const { return at<2>().as_string(); }
+};
+
+class FtraceDescriptor_AtraceCategory : public ::protozero::Message {
+ public:
+ using Decoder = FtraceDescriptor_AtraceCategory_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kDescriptionFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceDescriptor.AtraceCategory"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceDescriptor_AtraceCategory>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Description =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceDescriptor_AtraceCategory>;
+
+ static constexpr FieldMetadata_Description kDescription{};
+ void set_description(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Description::kFieldId, data, size);
+ }
+ void set_description(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Description::kFieldId, chars.data, chars.size);
+ }
+ void set_description(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Description::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/gpu_counter_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_GPU_COUNTER_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_GPU_COUNTER_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class GpuCounterDescriptor_GpuCounterBlock;
+class GpuCounterDescriptor_GpuCounterSpec;
+namespace perfetto_pbzero_enum_GpuCounterDescriptor {
+enum GpuCounterGroup : int32_t;
+} // namespace perfetto_pbzero_enum_GpuCounterDescriptor
+using GpuCounterDescriptor_GpuCounterGroup = perfetto_pbzero_enum_GpuCounterDescriptor::GpuCounterGroup;
+namespace perfetto_pbzero_enum_GpuCounterDescriptor {
+enum MeasureUnit : int32_t;
+} // namespace perfetto_pbzero_enum_GpuCounterDescriptor
+using GpuCounterDescriptor_MeasureUnit = perfetto_pbzero_enum_GpuCounterDescriptor::MeasureUnit;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_GpuCounterDescriptor {
+enum GpuCounterGroup : int32_t {
+ UNCLASSIFIED = 0,
+ SYSTEM = 1,
+ VERTICES = 2,
+ FRAGMENTS = 3,
+ PRIMITIVES = 4,
+ MEMORY = 5,
+ COMPUTE = 6,
+};
+} // namespace perfetto_pbzero_enum_GpuCounterDescriptor
+using GpuCounterDescriptor_GpuCounterGroup = perfetto_pbzero_enum_GpuCounterDescriptor::GpuCounterGroup;
+
+
+constexpr GpuCounterDescriptor_GpuCounterGroup GpuCounterDescriptor_GpuCounterGroup_MIN = GpuCounterDescriptor_GpuCounterGroup::UNCLASSIFIED;
+constexpr GpuCounterDescriptor_GpuCounterGroup GpuCounterDescriptor_GpuCounterGroup_MAX = GpuCounterDescriptor_GpuCounterGroup::COMPUTE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* GpuCounterDescriptor_GpuCounterGroup_Name(::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup::UNCLASSIFIED:
+ return "UNCLASSIFIED";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup::SYSTEM:
+ return "SYSTEM";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup::VERTICES:
+ return "VERTICES";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup::FRAGMENTS:
+ return "FRAGMENTS";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup::PRIMITIVES:
+ return "PRIMITIVES";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup::MEMORY:
+ return "MEMORY";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup::COMPUTE:
+ return "COMPUTE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_GpuCounterDescriptor {
+enum MeasureUnit : int32_t {
+ NONE = 0,
+ BIT = 1,
+ KILOBIT = 2,
+ MEGABIT = 3,
+ GIGABIT = 4,
+ TERABIT = 5,
+ PETABIT = 6,
+ BYTE = 7,
+ KILOBYTE = 8,
+ MEGABYTE = 9,
+ GIGABYTE = 10,
+ TERABYTE = 11,
+ PETABYTE = 12,
+ HERTZ = 13,
+ KILOHERTZ = 14,
+ MEGAHERTZ = 15,
+ GIGAHERTZ = 16,
+ TERAHERTZ = 17,
+ PETAHERTZ = 18,
+ NANOSECOND = 19,
+ MICROSECOND = 20,
+ MILLISECOND = 21,
+ SECOND = 22,
+ MINUTE = 23,
+ HOUR = 24,
+ VERTEX = 25,
+ PIXEL = 26,
+ TRIANGLE = 27,
+ PRIMITIVE = 38,
+ FRAGMENT = 39,
+ MILLIWATT = 28,
+ WATT = 29,
+ KILOWATT = 30,
+ JOULE = 31,
+ VOLT = 32,
+ AMPERE = 33,
+ CELSIUS = 34,
+ FAHRENHEIT = 35,
+ KELVIN = 36,
+ PERCENT = 37,
+ INSTRUCTION = 40,
+};
+} // namespace perfetto_pbzero_enum_GpuCounterDescriptor
+using GpuCounterDescriptor_MeasureUnit = perfetto_pbzero_enum_GpuCounterDescriptor::MeasureUnit;
+
+
+constexpr GpuCounterDescriptor_MeasureUnit GpuCounterDescriptor_MeasureUnit_MIN = GpuCounterDescriptor_MeasureUnit::NONE;
+constexpr GpuCounterDescriptor_MeasureUnit GpuCounterDescriptor_MeasureUnit_MAX = GpuCounterDescriptor_MeasureUnit::INSTRUCTION;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* GpuCounterDescriptor_MeasureUnit_Name(::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::NONE:
+ return "NONE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::BIT:
+ return "BIT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::KILOBIT:
+ return "KILOBIT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::MEGABIT:
+ return "MEGABIT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::GIGABIT:
+ return "GIGABIT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::TERABIT:
+ return "TERABIT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::PETABIT:
+ return "PETABIT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::BYTE:
+ return "BYTE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::KILOBYTE:
+ return "KILOBYTE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::MEGABYTE:
+ return "MEGABYTE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::GIGABYTE:
+ return "GIGABYTE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::TERABYTE:
+ return "TERABYTE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::PETABYTE:
+ return "PETABYTE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::HERTZ:
+ return "HERTZ";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::KILOHERTZ:
+ return "KILOHERTZ";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::MEGAHERTZ:
+ return "MEGAHERTZ";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::GIGAHERTZ:
+ return "GIGAHERTZ";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::TERAHERTZ:
+ return "TERAHERTZ";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::PETAHERTZ:
+ return "PETAHERTZ";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::NANOSECOND:
+ return "NANOSECOND";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::MICROSECOND:
+ return "MICROSECOND";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::MILLISECOND:
+ return "MILLISECOND";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::SECOND:
+ return "SECOND";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::MINUTE:
+ return "MINUTE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::HOUR:
+ return "HOUR";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::VERTEX:
+ return "VERTEX";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::PIXEL:
+ return "PIXEL";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::TRIANGLE:
+ return "TRIANGLE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::PRIMITIVE:
+ return "PRIMITIVE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::FRAGMENT:
+ return "FRAGMENT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::MILLIWATT:
+ return "MILLIWATT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::WATT:
+ return "WATT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::KILOWATT:
+ return "KILOWATT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::JOULE:
+ return "JOULE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::VOLT:
+ return "VOLT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::AMPERE:
+ return "AMPERE";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::CELSIUS:
+ return "CELSIUS";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::FAHRENHEIT:
+ return "FAHRENHEIT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::KELVIN:
+ return "KELVIN";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::PERCENT:
+ return "PERCENT";
+
+ case ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit::INSTRUCTION:
+ return "INSTRUCTION";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class GpuCounterDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GpuCounterDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuCounterDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuCounterDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_specs() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> specs() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_blocks() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> blocks() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_min_sampling_period_ns() const { return at<3>().valid(); }
+ uint64_t min_sampling_period_ns() const { return at<3>().as_uint64(); }
+ bool has_max_sampling_period_ns() const { return at<4>().valid(); }
+ uint64_t max_sampling_period_ns() const { return at<4>().as_uint64(); }
+ bool has_supports_instrumented_sampling() const { return at<5>().valid(); }
+ bool supports_instrumented_sampling() const { return at<5>().as_bool(); }
+};
+
+class GpuCounterDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = GpuCounterDescriptor_Decoder;
+ enum : int32_t {
+ kSpecsFieldNumber = 1,
+ kBlocksFieldNumber = 2,
+ kMinSamplingPeriodNsFieldNumber = 3,
+ kMaxSamplingPeriodNsFieldNumber = 4,
+ kSupportsInstrumentedSamplingFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuCounterDescriptor"; }
+
+ using GpuCounterSpec = ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterSpec;
+ using GpuCounterBlock = ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterBlock;
+
+ using GpuCounterGroup = ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup;
+ static inline const char* GpuCounterGroup_Name(GpuCounterGroup value) {
+ return ::perfetto::protos::pbzero::GpuCounterDescriptor_GpuCounterGroup_Name(value);
+ }
+
+ using MeasureUnit = ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit;
+ static inline const char* MeasureUnit_Name(MeasureUnit value) {
+ return ::perfetto::protos::pbzero::GpuCounterDescriptor_MeasureUnit_Name(value);
+ }
+ static inline const GpuCounterGroup UNCLASSIFIED = GpuCounterGroup::UNCLASSIFIED;
+ static inline const GpuCounterGroup SYSTEM = GpuCounterGroup::SYSTEM;
+ static inline const GpuCounterGroup VERTICES = GpuCounterGroup::VERTICES;
+ static inline const GpuCounterGroup FRAGMENTS = GpuCounterGroup::FRAGMENTS;
+ static inline const GpuCounterGroup PRIMITIVES = GpuCounterGroup::PRIMITIVES;
+ static inline const GpuCounterGroup MEMORY = GpuCounterGroup::MEMORY;
+ static inline const GpuCounterGroup COMPUTE = GpuCounterGroup::COMPUTE;
+ static inline const MeasureUnit NONE = MeasureUnit::NONE;
+ static inline const MeasureUnit BIT = MeasureUnit::BIT;
+ static inline const MeasureUnit KILOBIT = MeasureUnit::KILOBIT;
+ static inline const MeasureUnit MEGABIT = MeasureUnit::MEGABIT;
+ static inline const MeasureUnit GIGABIT = MeasureUnit::GIGABIT;
+ static inline const MeasureUnit TERABIT = MeasureUnit::TERABIT;
+ static inline const MeasureUnit PETABIT = MeasureUnit::PETABIT;
+ static inline const MeasureUnit BYTE = MeasureUnit::BYTE;
+ static inline const MeasureUnit KILOBYTE = MeasureUnit::KILOBYTE;
+ static inline const MeasureUnit MEGABYTE = MeasureUnit::MEGABYTE;
+ static inline const MeasureUnit GIGABYTE = MeasureUnit::GIGABYTE;
+ static inline const MeasureUnit TERABYTE = MeasureUnit::TERABYTE;
+ static inline const MeasureUnit PETABYTE = MeasureUnit::PETABYTE;
+ static inline const MeasureUnit HERTZ = MeasureUnit::HERTZ;
+ static inline const MeasureUnit KILOHERTZ = MeasureUnit::KILOHERTZ;
+ static inline const MeasureUnit MEGAHERTZ = MeasureUnit::MEGAHERTZ;
+ static inline const MeasureUnit GIGAHERTZ = MeasureUnit::GIGAHERTZ;
+ static inline const MeasureUnit TERAHERTZ = MeasureUnit::TERAHERTZ;
+ static inline const MeasureUnit PETAHERTZ = MeasureUnit::PETAHERTZ;
+ static inline const MeasureUnit NANOSECOND = MeasureUnit::NANOSECOND;
+ static inline const MeasureUnit MICROSECOND = MeasureUnit::MICROSECOND;
+ static inline const MeasureUnit MILLISECOND = MeasureUnit::MILLISECOND;
+ static inline const MeasureUnit SECOND = MeasureUnit::SECOND;
+ static inline const MeasureUnit MINUTE = MeasureUnit::MINUTE;
+ static inline const MeasureUnit HOUR = MeasureUnit::HOUR;
+ static inline const MeasureUnit VERTEX = MeasureUnit::VERTEX;
+ static inline const MeasureUnit PIXEL = MeasureUnit::PIXEL;
+ static inline const MeasureUnit TRIANGLE = MeasureUnit::TRIANGLE;
+ static inline const MeasureUnit PRIMITIVE = MeasureUnit::PRIMITIVE;
+ static inline const MeasureUnit FRAGMENT = MeasureUnit::FRAGMENT;
+ static inline const MeasureUnit MILLIWATT = MeasureUnit::MILLIWATT;
+ static inline const MeasureUnit WATT = MeasureUnit::WATT;
+ static inline const MeasureUnit KILOWATT = MeasureUnit::KILOWATT;
+ static inline const MeasureUnit JOULE = MeasureUnit::JOULE;
+ static inline const MeasureUnit VOLT = MeasureUnit::VOLT;
+ static inline const MeasureUnit AMPERE = MeasureUnit::AMPERE;
+ static inline const MeasureUnit CELSIUS = MeasureUnit::CELSIUS;
+ static inline const MeasureUnit FAHRENHEIT = MeasureUnit::FAHRENHEIT;
+ static inline const MeasureUnit KELVIN = MeasureUnit::KELVIN;
+ static inline const MeasureUnit PERCENT = MeasureUnit::PERCENT;
+ static inline const MeasureUnit INSTRUCTION = MeasureUnit::INSTRUCTION;
+
+ using FieldMetadata_Specs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuCounterDescriptor_GpuCounterSpec,
+ GpuCounterDescriptor>;
+
+ static constexpr FieldMetadata_Specs kSpecs{};
+ template <typename T = GpuCounterDescriptor_GpuCounterSpec> T* add_specs() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuCounterDescriptor_GpuCounterBlock,
+ GpuCounterDescriptor>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ template <typename T = GpuCounterDescriptor_GpuCounterBlock> T* add_blocks() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_MinSamplingPeriodNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuCounterDescriptor>;
+
+ static constexpr FieldMetadata_MinSamplingPeriodNs kMinSamplingPeriodNs{};
+ void set_min_sampling_period_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MinSamplingPeriodNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxSamplingPeriodNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuCounterDescriptor>;
+
+ static constexpr FieldMetadata_MaxSamplingPeriodNs kMaxSamplingPeriodNs{};
+ void set_max_sampling_period_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxSamplingPeriodNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SupportsInstrumentedSampling =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ GpuCounterDescriptor>;
+
+ static constexpr FieldMetadata_SupportsInstrumentedSampling kSupportsInstrumentedSampling{};
+ void set_supports_instrumented_sampling(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SupportsInstrumentedSampling::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuCounterDescriptor_GpuCounterBlock_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GpuCounterDescriptor_GpuCounterBlock_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuCounterDescriptor_GpuCounterBlock_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuCounterDescriptor_GpuCounterBlock_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_block_id() const { return at<1>().valid(); }
+ uint32_t block_id() const { return at<1>().as_uint32(); }
+ bool has_block_capacity() const { return at<2>().valid(); }
+ uint32_t block_capacity() const { return at<2>().as_uint32(); }
+ bool has_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars name() const { return at<3>().as_string(); }
+ bool has_description() const { return at<4>().valid(); }
+ ::protozero::ConstChars description() const { return at<4>().as_string(); }
+ bool has_counter_ids() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> counter_ids() const { return GetRepeated<uint32_t>(5); }
+};
+
+class GpuCounterDescriptor_GpuCounterBlock : public ::protozero::Message {
+ public:
+ using Decoder = GpuCounterDescriptor_GpuCounterBlock_Decoder;
+ enum : int32_t {
+ kBlockIdFieldNumber = 1,
+ kBlockCapacityFieldNumber = 2,
+ kNameFieldNumber = 3,
+ kDescriptionFieldNumber = 4,
+ kCounterIdsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuCounterDescriptor.GpuCounterBlock"; }
+
+
+ using FieldMetadata_BlockId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuCounterDescriptor_GpuCounterBlock>;
+
+ static constexpr FieldMetadata_BlockId kBlockId{};
+ void set_block_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlockId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BlockCapacity =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuCounterDescriptor_GpuCounterBlock>;
+
+ static constexpr FieldMetadata_BlockCapacity kBlockCapacity{};
+ void set_block_capacity(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlockCapacity::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuCounterDescriptor_GpuCounterBlock>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Description =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuCounterDescriptor_GpuCounterBlock>;
+
+ static constexpr FieldMetadata_Description kDescription{};
+ void set_description(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Description::kFieldId, data, size);
+ }
+ void set_description(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Description::kFieldId, chars.data, chars.size);
+ }
+ void set_description(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Description::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CounterIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuCounterDescriptor_GpuCounterBlock>;
+
+ static constexpr FieldMetadata_CounterIds kCounterIds{};
+ void add_counter_ids(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuCounterDescriptor_GpuCounterSpec_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GpuCounterDescriptor_GpuCounterSpec_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuCounterDescriptor_GpuCounterSpec_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuCounterDescriptor_GpuCounterSpec_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_counter_id() const { return at<1>().valid(); }
+ uint32_t counter_id() const { return at<1>().as_uint32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_description() const { return at<3>().valid(); }
+ ::protozero::ConstChars description() const { return at<3>().as_string(); }
+ bool has_int_peak_value() const { return at<5>().valid(); }
+ int64_t int_peak_value() const { return at<5>().as_int64(); }
+ bool has_double_peak_value() const { return at<6>().valid(); }
+ double double_peak_value() const { return at<6>().as_double(); }
+ bool has_numerator_units() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> numerator_units() const { return GetRepeated<int32_t>(7); }
+ bool has_denominator_units() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> denominator_units() const { return GetRepeated<int32_t>(8); }
+ bool has_select_by_default() const { return at<9>().valid(); }
+ bool select_by_default() const { return at<9>().as_bool(); }
+ bool has_groups() const { return at<10>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> groups() const { return GetRepeated<int32_t>(10); }
+};
+
+class GpuCounterDescriptor_GpuCounterSpec : public ::protozero::Message {
+ public:
+ using Decoder = GpuCounterDescriptor_GpuCounterSpec_Decoder;
+ enum : int32_t {
+ kCounterIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kDescriptionFieldNumber = 3,
+ kIntPeakValueFieldNumber = 5,
+ kDoublePeakValueFieldNumber = 6,
+ kNumeratorUnitsFieldNumber = 7,
+ kDenominatorUnitsFieldNumber = 8,
+ kSelectByDefaultFieldNumber = 9,
+ kGroupsFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuCounterDescriptor.GpuCounterSpec"; }
+
+
+ using FieldMetadata_CounterId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_CounterId kCounterId{};
+ void set_counter_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Description =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_Description kDescription{};
+ void set_description(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Description::kFieldId, data, size);
+ }
+ void set_description(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Description::kFieldId, chars.data, chars.size);
+ }
+ void set_description(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Description::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntPeakValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_IntPeakValue kIntPeakValue{};
+ void set_int_peak_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntPeakValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoublePeakValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_DoublePeakValue kDoublePeakValue{};
+ void set_double_peak_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoublePeakValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumeratorUnits =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ GpuCounterDescriptor_MeasureUnit,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_NumeratorUnits kNumeratorUnits{};
+ void add_numerator_units(GpuCounterDescriptor_MeasureUnit value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumeratorUnits::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DenominatorUnits =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ GpuCounterDescriptor_MeasureUnit,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_DenominatorUnits kDenominatorUnits{};
+ void add_denominator_units(GpuCounterDescriptor_MeasureUnit value) {
+ static constexpr uint32_t field_id = FieldMetadata_DenominatorUnits::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SelectByDefault =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_SelectByDefault kSelectByDefault{};
+ void set_select_by_default(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SelectByDefault::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Groups =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ GpuCounterDescriptor_GpuCounterGroup,
+ GpuCounterDescriptor_GpuCounterSpec>;
+
+ static constexpr FieldMetadata_Groups kGroups{};
+ void add_groups(GpuCounterDescriptor_GpuCounterGroup value) {
+ static constexpr uint32_t field_id = FieldMetadata_Groups::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/interceptor_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_INTERCEPTOR_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_INTERCEPTOR_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class InterceptorDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InterceptorDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InterceptorDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InterceptorDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class InterceptorDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = InterceptorDescriptor_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InterceptorDescriptor"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InterceptorDescriptor>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/observable_events.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_OBSERVABLE_EVENTS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_OBSERVABLE_EVENTS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ObservableEvents_CloneTriggerHit;
+class ObservableEvents_DataSourceInstanceStateChange;
+namespace perfetto_pbzero_enum_ObservableEvents {
+enum DataSourceInstanceState : int32_t;
+} // namespace perfetto_pbzero_enum_ObservableEvents
+using ObservableEvents_DataSourceInstanceState = perfetto_pbzero_enum_ObservableEvents::DataSourceInstanceState;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ObservableEvents {
+enum Type : int32_t {
+ TYPE_UNSPECIFIED = 0,
+ TYPE_DATA_SOURCES_INSTANCES = 1,
+ TYPE_ALL_DATA_SOURCES_STARTED = 2,
+ TYPE_CLONE_TRIGGER_HIT = 4,
+};
+} // namespace perfetto_pbzero_enum_ObservableEvents
+using ObservableEvents_Type = perfetto_pbzero_enum_ObservableEvents::Type;
+
+
+constexpr ObservableEvents_Type ObservableEvents_Type_MIN = ObservableEvents_Type::TYPE_UNSPECIFIED;
+constexpr ObservableEvents_Type ObservableEvents_Type_MAX = ObservableEvents_Type::TYPE_CLONE_TRIGGER_HIT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ObservableEvents_Type_Name(::perfetto::protos::pbzero::ObservableEvents_Type value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ObservableEvents_Type::TYPE_UNSPECIFIED:
+ return "TYPE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ObservableEvents_Type::TYPE_DATA_SOURCES_INSTANCES:
+ return "TYPE_DATA_SOURCES_INSTANCES";
+
+ case ::perfetto::protos::pbzero::ObservableEvents_Type::TYPE_ALL_DATA_SOURCES_STARTED:
+ return "TYPE_ALL_DATA_SOURCES_STARTED";
+
+ case ::perfetto::protos::pbzero::ObservableEvents_Type::TYPE_CLONE_TRIGGER_HIT:
+ return "TYPE_CLONE_TRIGGER_HIT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ObservableEvents {
+enum DataSourceInstanceState : int32_t {
+ DATA_SOURCE_INSTANCE_STATE_STOPPED = 1,
+ DATA_SOURCE_INSTANCE_STATE_STARTED = 2,
+};
+} // namespace perfetto_pbzero_enum_ObservableEvents
+using ObservableEvents_DataSourceInstanceState = perfetto_pbzero_enum_ObservableEvents::DataSourceInstanceState;
+
+
+constexpr ObservableEvents_DataSourceInstanceState ObservableEvents_DataSourceInstanceState_MIN = ObservableEvents_DataSourceInstanceState::DATA_SOURCE_INSTANCE_STATE_STOPPED;
+constexpr ObservableEvents_DataSourceInstanceState ObservableEvents_DataSourceInstanceState_MAX = ObservableEvents_DataSourceInstanceState::DATA_SOURCE_INSTANCE_STATE_STARTED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ObservableEvents_DataSourceInstanceState_Name(::perfetto::protos::pbzero::ObservableEvents_DataSourceInstanceState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ObservableEvents_DataSourceInstanceState::DATA_SOURCE_INSTANCE_STATE_STOPPED:
+ return "DATA_SOURCE_INSTANCE_STATE_STOPPED";
+
+ case ::perfetto::protos::pbzero::ObservableEvents_DataSourceInstanceState::DATA_SOURCE_INSTANCE_STATE_STARTED:
+ return "DATA_SOURCE_INSTANCE_STATE_STARTED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ObservableEvents_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ObservableEvents_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ObservableEvents_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ObservableEvents_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_instance_state_changes() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> instance_state_changes() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_all_data_sources_started() const { return at<2>().valid(); }
+ bool all_data_sources_started() const { return at<2>().as_bool(); }
+ bool has_clone_trigger_hit() const { return at<3>().valid(); }
+ ::protozero::ConstBytes clone_trigger_hit() const { return at<3>().as_bytes(); }
+};
+
+class ObservableEvents : public ::protozero::Message {
+ public:
+ using Decoder = ObservableEvents_Decoder;
+ enum : int32_t {
+ kInstanceStateChangesFieldNumber = 1,
+ kAllDataSourcesStartedFieldNumber = 2,
+ kCloneTriggerHitFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ObservableEvents"; }
+
+ using DataSourceInstanceStateChange = ::perfetto::protos::pbzero::ObservableEvents_DataSourceInstanceStateChange;
+ using CloneTriggerHit = ::perfetto::protos::pbzero::ObservableEvents_CloneTriggerHit;
+
+ using Type = ::perfetto::protos::pbzero::ObservableEvents_Type;
+ static inline const char* Type_Name(Type value) {
+ return ::perfetto::protos::pbzero::ObservableEvents_Type_Name(value);
+ }
+
+ using DataSourceInstanceState = ::perfetto::protos::pbzero::ObservableEvents_DataSourceInstanceState;
+ static inline const char* DataSourceInstanceState_Name(DataSourceInstanceState value) {
+ return ::perfetto::protos::pbzero::ObservableEvents_DataSourceInstanceState_Name(value);
+ }
+ static inline const Type TYPE_UNSPECIFIED = Type::TYPE_UNSPECIFIED;
+ static inline const Type TYPE_DATA_SOURCES_INSTANCES = Type::TYPE_DATA_SOURCES_INSTANCES;
+ static inline const Type TYPE_ALL_DATA_SOURCES_STARTED = Type::TYPE_ALL_DATA_SOURCES_STARTED;
+ static inline const Type TYPE_CLONE_TRIGGER_HIT = Type::TYPE_CLONE_TRIGGER_HIT;
+ static inline const DataSourceInstanceState DATA_SOURCE_INSTANCE_STATE_STOPPED = DataSourceInstanceState::DATA_SOURCE_INSTANCE_STATE_STOPPED;
+ static inline const DataSourceInstanceState DATA_SOURCE_INSTANCE_STATE_STARTED = DataSourceInstanceState::DATA_SOURCE_INSTANCE_STATE_STARTED;
+
+ using FieldMetadata_InstanceStateChanges =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ObservableEvents_DataSourceInstanceStateChange,
+ ObservableEvents>;
+
+ static constexpr FieldMetadata_InstanceStateChanges kInstanceStateChanges{};
+ template <typename T = ObservableEvents_DataSourceInstanceStateChange> T* add_instance_state_changes() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_AllDataSourcesStarted =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ObservableEvents>;
+
+ static constexpr FieldMetadata_AllDataSourcesStarted kAllDataSourcesStarted{};
+ void set_all_data_sources_started(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllDataSourcesStarted::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CloneTriggerHit =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ObservableEvents_CloneTriggerHit,
+ ObservableEvents>;
+
+ static constexpr FieldMetadata_CloneTriggerHit kCloneTriggerHit{};
+ template <typename T = ObservableEvents_CloneTriggerHit> T* set_clone_trigger_hit() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class ObservableEvents_CloneTriggerHit_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ObservableEvents_CloneTriggerHit_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ObservableEvents_CloneTriggerHit_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ObservableEvents_CloneTriggerHit_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tracing_session_id() const { return at<1>().valid(); }
+ int64_t tracing_session_id() const { return at<1>().as_int64(); }
+};
+
+class ObservableEvents_CloneTriggerHit : public ::protozero::Message {
+ public:
+ using Decoder = ObservableEvents_CloneTriggerHit_Decoder;
+ enum : int32_t {
+ kTracingSessionIdFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ObservableEvents.CloneTriggerHit"; }
+
+
+ using FieldMetadata_TracingSessionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ObservableEvents_CloneTriggerHit>;
+
+ static constexpr FieldMetadata_TracingSessionId kTracingSessionId{};
+ void set_tracing_session_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingSessionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ObservableEvents_DataSourceInstanceStateChange_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ObservableEvents_DataSourceInstanceStateChange_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ObservableEvents_DataSourceInstanceStateChange_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ObservableEvents_DataSourceInstanceStateChange_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_producer_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars producer_name() const { return at<1>().as_string(); }
+ bool has_data_source_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars data_source_name() const { return at<2>().as_string(); }
+ bool has_state() const { return at<3>().valid(); }
+ int32_t state() const { return at<3>().as_int32(); }
+};
+
+class ObservableEvents_DataSourceInstanceStateChange : public ::protozero::Message {
+ public:
+ using Decoder = ObservableEvents_DataSourceInstanceStateChange_Decoder;
+ enum : int32_t {
+ kProducerNameFieldNumber = 1,
+ kDataSourceNameFieldNumber = 2,
+ kStateFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ObservableEvents.DataSourceInstanceStateChange"; }
+
+
+ using FieldMetadata_ProducerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ObservableEvents_DataSourceInstanceStateChange>;
+
+ static constexpr FieldMetadata_ProducerName kProducerName{};
+ void set_producer_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProducerName::kFieldId, data, size);
+ }
+ void set_producer_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProducerName::kFieldId, chars.data, chars.size);
+ }
+ void set_producer_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSourceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ObservableEvents_DataSourceInstanceStateChange>;
+
+ static constexpr FieldMetadata_DataSourceName kDataSourceName{};
+ void set_data_source_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DataSourceName::kFieldId, data, size);
+ }
+ void set_data_source_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DataSourceName::kFieldId, chars.data, chars.size);
+ }
+ void set_data_source_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSourceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ObservableEvents_DataSourceInstanceState,
+ ObservableEvents_DataSourceInstanceStateChange>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(ObservableEvents_DataSourceInstanceState value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/perf_events.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PERF_EVENTS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PERF_EVENTS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class PerfEvents_RawEvent;
+class PerfEvents_Timebase;
+class PerfEvents_Tracepoint;
+namespace perfetto_pbzero_enum_PerfEvents {
+enum Counter : int32_t;
+} // namespace perfetto_pbzero_enum_PerfEvents
+using PerfEvents_Counter = perfetto_pbzero_enum_PerfEvents::Counter;
+namespace perfetto_pbzero_enum_PerfEvents {
+enum PerfClock : int32_t;
+} // namespace perfetto_pbzero_enum_PerfEvents
+using PerfEvents_PerfClock = perfetto_pbzero_enum_PerfEvents::PerfClock;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_PerfEvents {
+enum Counter : int32_t {
+ UNKNOWN_COUNTER = 0,
+ SW_CPU_CLOCK = 1,
+ SW_PAGE_FAULTS = 2,
+ SW_TASK_CLOCK = 3,
+ SW_CONTEXT_SWITCHES = 4,
+ SW_CPU_MIGRATIONS = 5,
+ SW_PAGE_FAULTS_MIN = 6,
+ SW_PAGE_FAULTS_MAJ = 7,
+ SW_ALIGNMENT_FAULTS = 8,
+ SW_EMULATION_FAULTS = 9,
+ SW_DUMMY = 20,
+ HW_CPU_CYCLES = 10,
+ HW_INSTRUCTIONS = 11,
+ HW_CACHE_REFERENCES = 12,
+ HW_CACHE_MISSES = 13,
+ HW_BRANCH_INSTRUCTIONS = 14,
+ HW_BRANCH_MISSES = 15,
+ HW_BUS_CYCLES = 16,
+ HW_STALLED_CYCLES_FRONTEND = 17,
+ HW_STALLED_CYCLES_BACKEND = 18,
+ HW_REF_CPU_CYCLES = 19,
+};
+} // namespace perfetto_pbzero_enum_PerfEvents
+using PerfEvents_Counter = perfetto_pbzero_enum_PerfEvents::Counter;
+
+
+constexpr PerfEvents_Counter PerfEvents_Counter_MIN = PerfEvents_Counter::UNKNOWN_COUNTER;
+constexpr PerfEvents_Counter PerfEvents_Counter_MAX = PerfEvents_Counter::SW_DUMMY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* PerfEvents_Counter_Name(::perfetto::protos::pbzero::PerfEvents_Counter value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::UNKNOWN_COUNTER:
+ return "UNKNOWN_COUNTER";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_CPU_CLOCK:
+ return "SW_CPU_CLOCK";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_PAGE_FAULTS:
+ return "SW_PAGE_FAULTS";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_TASK_CLOCK:
+ return "SW_TASK_CLOCK";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_CONTEXT_SWITCHES:
+ return "SW_CONTEXT_SWITCHES";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_CPU_MIGRATIONS:
+ return "SW_CPU_MIGRATIONS";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_PAGE_FAULTS_MIN:
+ return "SW_PAGE_FAULTS_MIN";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_PAGE_FAULTS_MAJ:
+ return "SW_PAGE_FAULTS_MAJ";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_ALIGNMENT_FAULTS:
+ return "SW_ALIGNMENT_FAULTS";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_EMULATION_FAULTS:
+ return "SW_EMULATION_FAULTS";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::SW_DUMMY:
+ return "SW_DUMMY";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_CPU_CYCLES:
+ return "HW_CPU_CYCLES";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_INSTRUCTIONS:
+ return "HW_INSTRUCTIONS";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_CACHE_REFERENCES:
+ return "HW_CACHE_REFERENCES";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_CACHE_MISSES:
+ return "HW_CACHE_MISSES";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_BRANCH_INSTRUCTIONS:
+ return "HW_BRANCH_INSTRUCTIONS";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_BRANCH_MISSES:
+ return "HW_BRANCH_MISSES";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_BUS_CYCLES:
+ return "HW_BUS_CYCLES";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_STALLED_CYCLES_FRONTEND:
+ return "HW_STALLED_CYCLES_FRONTEND";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_STALLED_CYCLES_BACKEND:
+ return "HW_STALLED_CYCLES_BACKEND";
+
+ case ::perfetto::protos::pbzero::PerfEvents_Counter::HW_REF_CPU_CYCLES:
+ return "HW_REF_CPU_CYCLES";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_PerfEvents {
+enum PerfClock : int32_t {
+ UNKNOWN_PERF_CLOCK = 0,
+ PERF_CLOCK_REALTIME = 1,
+ PERF_CLOCK_MONOTONIC = 2,
+ PERF_CLOCK_MONOTONIC_RAW = 3,
+ PERF_CLOCK_BOOTTIME = 4,
+};
+} // namespace perfetto_pbzero_enum_PerfEvents
+using PerfEvents_PerfClock = perfetto_pbzero_enum_PerfEvents::PerfClock;
+
+
+constexpr PerfEvents_PerfClock PerfEvents_PerfClock_MIN = PerfEvents_PerfClock::UNKNOWN_PERF_CLOCK;
+constexpr PerfEvents_PerfClock PerfEvents_PerfClock_MAX = PerfEvents_PerfClock::PERF_CLOCK_BOOTTIME;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* PerfEvents_PerfClock_Name(::perfetto::protos::pbzero::PerfEvents_PerfClock value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::PerfEvents_PerfClock::UNKNOWN_PERF_CLOCK:
+ return "UNKNOWN_PERF_CLOCK";
+
+ case ::perfetto::protos::pbzero::PerfEvents_PerfClock::PERF_CLOCK_REALTIME:
+ return "PERF_CLOCK_REALTIME";
+
+ case ::perfetto::protos::pbzero::PerfEvents_PerfClock::PERF_CLOCK_MONOTONIC:
+ return "PERF_CLOCK_MONOTONIC";
+
+ case ::perfetto::protos::pbzero::PerfEvents_PerfClock::PERF_CLOCK_MONOTONIC_RAW:
+ return "PERF_CLOCK_MONOTONIC_RAW";
+
+ case ::perfetto::protos::pbzero::PerfEvents_PerfClock::PERF_CLOCK_BOOTTIME:
+ return "PERF_CLOCK_BOOTTIME";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class PerfEvents_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfEvents_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfEvents_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfEvents_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class PerfEvents : public ::protozero::Message {
+ public:
+ using Decoder = PerfEvents_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfEvents"; }
+
+ using Timebase = ::perfetto::protos::pbzero::PerfEvents_Timebase;
+ using Tracepoint = ::perfetto::protos::pbzero::PerfEvents_Tracepoint;
+ using RawEvent = ::perfetto::protos::pbzero::PerfEvents_RawEvent;
+
+ using Counter = ::perfetto::protos::pbzero::PerfEvents_Counter;
+ static inline const char* Counter_Name(Counter value) {
+ return ::perfetto::protos::pbzero::PerfEvents_Counter_Name(value);
+ }
+
+ using PerfClock = ::perfetto::protos::pbzero::PerfEvents_PerfClock;
+ static inline const char* PerfClock_Name(PerfClock value) {
+ return ::perfetto::protos::pbzero::PerfEvents_PerfClock_Name(value);
+ }
+ static inline const Counter UNKNOWN_COUNTER = Counter::UNKNOWN_COUNTER;
+ static inline const Counter SW_CPU_CLOCK = Counter::SW_CPU_CLOCK;
+ static inline const Counter SW_PAGE_FAULTS = Counter::SW_PAGE_FAULTS;
+ static inline const Counter SW_TASK_CLOCK = Counter::SW_TASK_CLOCK;
+ static inline const Counter SW_CONTEXT_SWITCHES = Counter::SW_CONTEXT_SWITCHES;
+ static inline const Counter SW_CPU_MIGRATIONS = Counter::SW_CPU_MIGRATIONS;
+ static inline const Counter SW_PAGE_FAULTS_MIN = Counter::SW_PAGE_FAULTS_MIN;
+ static inline const Counter SW_PAGE_FAULTS_MAJ = Counter::SW_PAGE_FAULTS_MAJ;
+ static inline const Counter SW_ALIGNMENT_FAULTS = Counter::SW_ALIGNMENT_FAULTS;
+ static inline const Counter SW_EMULATION_FAULTS = Counter::SW_EMULATION_FAULTS;
+ static inline const Counter SW_DUMMY = Counter::SW_DUMMY;
+ static inline const Counter HW_CPU_CYCLES = Counter::HW_CPU_CYCLES;
+ static inline const Counter HW_INSTRUCTIONS = Counter::HW_INSTRUCTIONS;
+ static inline const Counter HW_CACHE_REFERENCES = Counter::HW_CACHE_REFERENCES;
+ static inline const Counter HW_CACHE_MISSES = Counter::HW_CACHE_MISSES;
+ static inline const Counter HW_BRANCH_INSTRUCTIONS = Counter::HW_BRANCH_INSTRUCTIONS;
+ static inline const Counter HW_BRANCH_MISSES = Counter::HW_BRANCH_MISSES;
+ static inline const Counter HW_BUS_CYCLES = Counter::HW_BUS_CYCLES;
+ static inline const Counter HW_STALLED_CYCLES_FRONTEND = Counter::HW_STALLED_CYCLES_FRONTEND;
+ static inline const Counter HW_STALLED_CYCLES_BACKEND = Counter::HW_STALLED_CYCLES_BACKEND;
+ static inline const Counter HW_REF_CPU_CYCLES = Counter::HW_REF_CPU_CYCLES;
+ static inline const PerfClock UNKNOWN_PERF_CLOCK = PerfClock::UNKNOWN_PERF_CLOCK;
+ static inline const PerfClock PERF_CLOCK_REALTIME = PerfClock::PERF_CLOCK_REALTIME;
+ static inline const PerfClock PERF_CLOCK_MONOTONIC = PerfClock::PERF_CLOCK_MONOTONIC;
+ static inline const PerfClock PERF_CLOCK_MONOTONIC_RAW = PerfClock::PERF_CLOCK_MONOTONIC_RAW;
+ static inline const PerfClock PERF_CLOCK_BOOTTIME = PerfClock::PERF_CLOCK_BOOTTIME;
+};
+
+class PerfEvents_RawEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfEvents_RawEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfEvents_RawEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfEvents_RawEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_type() const { return at<1>().valid(); }
+ uint32_t type() const { return at<1>().as_uint32(); }
+ bool has_config() const { return at<2>().valid(); }
+ uint64_t config() const { return at<2>().as_uint64(); }
+ bool has_config1() const { return at<3>().valid(); }
+ uint64_t config1() const { return at<3>().as_uint64(); }
+ bool has_config2() const { return at<4>().valid(); }
+ uint64_t config2() const { return at<4>().as_uint64(); }
+};
+
+class PerfEvents_RawEvent : public ::protozero::Message {
+ public:
+ using Decoder = PerfEvents_RawEvent_Decoder;
+ enum : int32_t {
+ kTypeFieldNumber = 1,
+ kConfigFieldNumber = 2,
+ kConfig1FieldNumber = 3,
+ kConfig2FieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfEvents.RawEvent"; }
+
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEvents_RawEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Config =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfEvents_RawEvent>;
+
+ static constexpr FieldMetadata_Config kConfig{};
+ void set_config(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Config::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Config1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfEvents_RawEvent>;
+
+ static constexpr FieldMetadata_Config1 kConfig1{};
+ void set_config1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Config1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Config2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfEvents_RawEvent>;
+
+ static constexpr FieldMetadata_Config2 kConfig2{};
+ void set_config2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Config2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PerfEvents_Tracepoint_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfEvents_Tracepoint_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfEvents_Tracepoint_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfEvents_Tracepoint_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_filter() const { return at<2>().valid(); }
+ ::protozero::ConstChars filter() const { return at<2>().as_string(); }
+};
+
+class PerfEvents_Tracepoint : public ::protozero::Message {
+ public:
+ using Decoder = PerfEvents_Tracepoint_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kFilterFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfEvents.Tracepoint"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEvents_Tracepoint>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Filter =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEvents_Tracepoint>;
+
+ static constexpr FieldMetadata_Filter kFilter{};
+ void set_filter(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Filter::kFieldId, data, size);
+ }
+ void set_filter(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Filter::kFieldId, chars.data, chars.size);
+ }
+ void set_filter(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Filter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PerfEvents_Timebase_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfEvents_Timebase_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfEvents_Timebase_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfEvents_Timebase_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_frequency() const { return at<2>().valid(); }
+ uint64_t frequency() const { return at<2>().as_uint64(); }
+ bool has_period() const { return at<1>().valid(); }
+ uint64_t period() const { return at<1>().as_uint64(); }
+ bool has_counter() const { return at<4>().valid(); }
+ int32_t counter() const { return at<4>().as_int32(); }
+ bool has_tracepoint() const { return at<3>().valid(); }
+ ::protozero::ConstBytes tracepoint() const { return at<3>().as_bytes(); }
+ bool has_raw_event() const { return at<5>().valid(); }
+ ::protozero::ConstBytes raw_event() const { return at<5>().as_bytes(); }
+ bool has_timestamp_clock() const { return at<11>().valid(); }
+ int32_t timestamp_clock() const { return at<11>().as_int32(); }
+ bool has_name() const { return at<10>().valid(); }
+ ::protozero::ConstChars name() const { return at<10>().as_string(); }
+};
+
+class PerfEvents_Timebase : public ::protozero::Message {
+ public:
+ using Decoder = PerfEvents_Timebase_Decoder;
+ enum : int32_t {
+ kFrequencyFieldNumber = 2,
+ kPeriodFieldNumber = 1,
+ kCounterFieldNumber = 4,
+ kTracepointFieldNumber = 3,
+ kRawEventFieldNumber = 5,
+ kTimestampClockFieldNumber = 11,
+ kNameFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfEvents.Timebase"; }
+
+
+ using FieldMetadata_Frequency =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfEvents_Timebase>;
+
+ static constexpr FieldMetadata_Frequency kFrequency{};
+ void set_frequency(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Frequency::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Period =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfEvents_Timebase>;
+
+ static constexpr FieldMetadata_Period kPeriod{};
+ void set_period(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Period::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Counter =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ PerfEvents_Counter,
+ PerfEvents_Timebase>;
+
+ static constexpr FieldMetadata_Counter kCounter{};
+ void set_counter(PerfEvents_Counter value) {
+ static constexpr uint32_t field_id = FieldMetadata_Counter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tracepoint =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfEvents_Tracepoint,
+ PerfEvents_Timebase>;
+
+ static constexpr FieldMetadata_Tracepoint kTracepoint{};
+ template <typename T = PerfEvents_Tracepoint> T* set_tracepoint() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_RawEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfEvents_RawEvent,
+ PerfEvents_Timebase>;
+
+ static constexpr FieldMetadata_RawEvent kRawEvent{};
+ template <typename T = PerfEvents_RawEvent> T* set_raw_event() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_TimestampClock =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ PerfEvents_PerfClock,
+ PerfEvents_Timebase>;
+
+ static constexpr FieldMetadata_TimestampClock kTimestampClock{};
+ void set_timestamp_clock(PerfEvents_PerfClock value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampClock::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEvents_Timebase>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/protolog_common.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PROTOLOG_COMMON_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_PROTOLOG_COMMON_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum ProtoLogLevel : int32_t {
+ PROTOLOG_LEVEL_UNDEFINED = 0,
+ PROTOLOG_LEVEL_DEBUG = 1,
+ PROTOLOG_LEVEL_VERBOSE = 2,
+ PROTOLOG_LEVEL_INFO = 3,
+ PROTOLOG_LEVEL_WARN = 4,
+ PROTOLOG_LEVEL_ERROR = 5,
+ PROTOLOG_LEVEL_WTF = 6,
+};
+
+constexpr ProtoLogLevel ProtoLogLevel_MIN = ProtoLogLevel::PROTOLOG_LEVEL_UNDEFINED;
+constexpr ProtoLogLevel ProtoLogLevel_MAX = ProtoLogLevel::PROTOLOG_LEVEL_WTF;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ProtoLogLevel_Name(::perfetto::protos::pbzero::ProtoLogLevel value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ProtoLogLevel::PROTOLOG_LEVEL_UNDEFINED:
+ return "PROTOLOG_LEVEL_UNDEFINED";
+
+ case ::perfetto::protos::pbzero::ProtoLogLevel::PROTOLOG_LEVEL_DEBUG:
+ return "PROTOLOG_LEVEL_DEBUG";
+
+ case ::perfetto::protos::pbzero::ProtoLogLevel::PROTOLOG_LEVEL_VERBOSE:
+ return "PROTOLOG_LEVEL_VERBOSE";
+
+ case ::perfetto::protos::pbzero::ProtoLogLevel::PROTOLOG_LEVEL_INFO:
+ return "PROTOLOG_LEVEL_INFO";
+
+ case ::perfetto::protos::pbzero::ProtoLogLevel::PROTOLOG_LEVEL_WARN:
+ return "PROTOLOG_LEVEL_WARN";
+
+ case ::perfetto::protos::pbzero::ProtoLogLevel::PROTOLOG_LEVEL_ERROR:
+ return "PROTOLOG_LEVEL_ERROR";
+
+ case ::perfetto::protos::pbzero::ProtoLogLevel::PROTOLOG_LEVEL_WTF:
+ return "PROTOLOG_LEVEL_WTF";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/sys_stats_counters.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_SYS_STATS_COUNTERS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_SYS_STATS_COUNTERS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum MeminfoCounters : int32_t {
+ MEMINFO_UNSPECIFIED = 0,
+ MEMINFO_MEM_TOTAL = 1,
+ MEMINFO_MEM_FREE = 2,
+ MEMINFO_MEM_AVAILABLE = 3,
+ MEMINFO_BUFFERS = 4,
+ MEMINFO_CACHED = 5,
+ MEMINFO_SWAP_CACHED = 6,
+ MEMINFO_ACTIVE = 7,
+ MEMINFO_INACTIVE = 8,
+ MEMINFO_ACTIVE_ANON = 9,
+ MEMINFO_INACTIVE_ANON = 10,
+ MEMINFO_ACTIVE_FILE = 11,
+ MEMINFO_INACTIVE_FILE = 12,
+ MEMINFO_UNEVICTABLE = 13,
+ MEMINFO_MLOCKED = 14,
+ MEMINFO_SWAP_TOTAL = 15,
+ MEMINFO_SWAP_FREE = 16,
+ MEMINFO_DIRTY = 17,
+ MEMINFO_WRITEBACK = 18,
+ MEMINFO_ANON_PAGES = 19,
+ MEMINFO_MAPPED = 20,
+ MEMINFO_SHMEM = 21,
+ MEMINFO_SLAB = 22,
+ MEMINFO_SLAB_RECLAIMABLE = 23,
+ MEMINFO_SLAB_UNRECLAIMABLE = 24,
+ MEMINFO_KERNEL_STACK = 25,
+ MEMINFO_PAGE_TABLES = 26,
+ MEMINFO_COMMIT_LIMIT = 27,
+ MEMINFO_COMMITED_AS = 28,
+ MEMINFO_VMALLOC_TOTAL = 29,
+ MEMINFO_VMALLOC_USED = 30,
+ MEMINFO_VMALLOC_CHUNK = 31,
+ MEMINFO_CMA_TOTAL = 32,
+ MEMINFO_CMA_FREE = 33,
+};
+
+constexpr MeminfoCounters MeminfoCounters_MIN = MeminfoCounters::MEMINFO_UNSPECIFIED;
+constexpr MeminfoCounters MeminfoCounters_MAX = MeminfoCounters::MEMINFO_CMA_FREE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* MeminfoCounters_Name(::perfetto::protos::pbzero::MeminfoCounters value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_UNSPECIFIED:
+ return "MEMINFO_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_MEM_TOTAL:
+ return "MEMINFO_MEM_TOTAL";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_MEM_FREE:
+ return "MEMINFO_MEM_FREE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_MEM_AVAILABLE:
+ return "MEMINFO_MEM_AVAILABLE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_BUFFERS:
+ return "MEMINFO_BUFFERS";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_CACHED:
+ return "MEMINFO_CACHED";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_SWAP_CACHED:
+ return "MEMINFO_SWAP_CACHED";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE:
+ return "MEMINFO_ACTIVE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE:
+ return "MEMINFO_INACTIVE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE_ANON:
+ return "MEMINFO_ACTIVE_ANON";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE_ANON:
+ return "MEMINFO_INACTIVE_ANON";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE_FILE:
+ return "MEMINFO_ACTIVE_FILE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE_FILE:
+ return "MEMINFO_INACTIVE_FILE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_UNEVICTABLE:
+ return "MEMINFO_UNEVICTABLE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_MLOCKED:
+ return "MEMINFO_MLOCKED";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_SWAP_TOTAL:
+ return "MEMINFO_SWAP_TOTAL";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_SWAP_FREE:
+ return "MEMINFO_SWAP_FREE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_DIRTY:
+ return "MEMINFO_DIRTY";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_WRITEBACK:
+ return "MEMINFO_WRITEBACK";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_ANON_PAGES:
+ return "MEMINFO_ANON_PAGES";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_MAPPED:
+ return "MEMINFO_MAPPED";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_SHMEM:
+ return "MEMINFO_SHMEM";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_SLAB:
+ return "MEMINFO_SLAB";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_SLAB_RECLAIMABLE:
+ return "MEMINFO_SLAB_RECLAIMABLE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_SLAB_UNRECLAIMABLE:
+ return "MEMINFO_SLAB_UNRECLAIMABLE";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_KERNEL_STACK:
+ return "MEMINFO_KERNEL_STACK";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_PAGE_TABLES:
+ return "MEMINFO_PAGE_TABLES";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_COMMIT_LIMIT:
+ return "MEMINFO_COMMIT_LIMIT";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_COMMITED_AS:
+ return "MEMINFO_COMMITED_AS";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_TOTAL:
+ return "MEMINFO_VMALLOC_TOTAL";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_USED:
+ return "MEMINFO_VMALLOC_USED";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_CHUNK:
+ return "MEMINFO_VMALLOC_CHUNK";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_CMA_TOTAL:
+ return "MEMINFO_CMA_TOTAL";
+
+ case ::perfetto::protos::pbzero::MeminfoCounters::MEMINFO_CMA_FREE:
+ return "MEMINFO_CMA_FREE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+enum VmstatCounters : int32_t {
+ VMSTAT_UNSPECIFIED = 0,
+ VMSTAT_NR_FREE_PAGES = 1,
+ VMSTAT_NR_ALLOC_BATCH = 2,
+ VMSTAT_NR_INACTIVE_ANON = 3,
+ VMSTAT_NR_ACTIVE_ANON = 4,
+ VMSTAT_NR_INACTIVE_FILE = 5,
+ VMSTAT_NR_ACTIVE_FILE = 6,
+ VMSTAT_NR_UNEVICTABLE = 7,
+ VMSTAT_NR_MLOCK = 8,
+ VMSTAT_NR_ANON_PAGES = 9,
+ VMSTAT_NR_MAPPED = 10,
+ VMSTAT_NR_FILE_PAGES = 11,
+ VMSTAT_NR_DIRTY = 12,
+ VMSTAT_NR_WRITEBACK = 13,
+ VMSTAT_NR_SLAB_RECLAIMABLE = 14,
+ VMSTAT_NR_SLAB_UNRECLAIMABLE = 15,
+ VMSTAT_NR_PAGE_TABLE_PAGES = 16,
+ VMSTAT_NR_KERNEL_STACK = 17,
+ VMSTAT_NR_OVERHEAD = 18,
+ VMSTAT_NR_UNSTABLE = 19,
+ VMSTAT_NR_BOUNCE = 20,
+ VMSTAT_NR_VMSCAN_WRITE = 21,
+ VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM = 22,
+ VMSTAT_NR_WRITEBACK_TEMP = 23,
+ VMSTAT_NR_ISOLATED_ANON = 24,
+ VMSTAT_NR_ISOLATED_FILE = 25,
+ VMSTAT_NR_SHMEM = 26,
+ VMSTAT_NR_DIRTIED = 27,
+ VMSTAT_NR_WRITTEN = 28,
+ VMSTAT_NR_PAGES_SCANNED = 29,
+ VMSTAT_WORKINGSET_REFAULT = 30,
+ VMSTAT_WORKINGSET_ACTIVATE = 31,
+ VMSTAT_WORKINGSET_NODERECLAIM = 32,
+ VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES = 33,
+ VMSTAT_NR_FREE_CMA = 34,
+ VMSTAT_NR_SWAPCACHE = 35,
+ VMSTAT_NR_DIRTY_THRESHOLD = 36,
+ VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD = 37,
+ VMSTAT_PGPGIN = 38,
+ VMSTAT_PGPGOUT = 39,
+ VMSTAT_PGPGOUTCLEAN = 40,
+ VMSTAT_PSWPIN = 41,
+ VMSTAT_PSWPOUT = 42,
+ VMSTAT_PGALLOC_DMA = 43,
+ VMSTAT_PGALLOC_NORMAL = 44,
+ VMSTAT_PGALLOC_MOVABLE = 45,
+ VMSTAT_PGFREE = 46,
+ VMSTAT_PGACTIVATE = 47,
+ VMSTAT_PGDEACTIVATE = 48,
+ VMSTAT_PGFAULT = 49,
+ VMSTAT_PGMAJFAULT = 50,
+ VMSTAT_PGREFILL_DMA = 51,
+ VMSTAT_PGREFILL_NORMAL = 52,
+ VMSTAT_PGREFILL_MOVABLE = 53,
+ VMSTAT_PGSTEAL_KSWAPD_DMA = 54,
+ VMSTAT_PGSTEAL_KSWAPD_NORMAL = 55,
+ VMSTAT_PGSTEAL_KSWAPD_MOVABLE = 56,
+ VMSTAT_PGSTEAL_DIRECT_DMA = 57,
+ VMSTAT_PGSTEAL_DIRECT_NORMAL = 58,
+ VMSTAT_PGSTEAL_DIRECT_MOVABLE = 59,
+ VMSTAT_PGSCAN_KSWAPD_DMA = 60,
+ VMSTAT_PGSCAN_KSWAPD_NORMAL = 61,
+ VMSTAT_PGSCAN_KSWAPD_MOVABLE = 62,
+ VMSTAT_PGSCAN_DIRECT_DMA = 63,
+ VMSTAT_PGSCAN_DIRECT_NORMAL = 64,
+ VMSTAT_PGSCAN_DIRECT_MOVABLE = 65,
+ VMSTAT_PGSCAN_DIRECT_THROTTLE = 66,
+ VMSTAT_PGINODESTEAL = 67,
+ VMSTAT_SLABS_SCANNED = 68,
+ VMSTAT_KSWAPD_INODESTEAL = 69,
+ VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY = 70,
+ VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY = 71,
+ VMSTAT_PAGEOUTRUN = 72,
+ VMSTAT_ALLOCSTALL = 73,
+ VMSTAT_PGROTATED = 74,
+ VMSTAT_DROP_PAGECACHE = 75,
+ VMSTAT_DROP_SLAB = 76,
+ VMSTAT_PGMIGRATE_SUCCESS = 77,
+ VMSTAT_PGMIGRATE_FAIL = 78,
+ VMSTAT_COMPACT_MIGRATE_SCANNED = 79,
+ VMSTAT_COMPACT_FREE_SCANNED = 80,
+ VMSTAT_COMPACT_ISOLATED = 81,
+ VMSTAT_COMPACT_STALL = 82,
+ VMSTAT_COMPACT_FAIL = 83,
+ VMSTAT_COMPACT_SUCCESS = 84,
+ VMSTAT_COMPACT_DAEMON_WAKE = 85,
+ VMSTAT_UNEVICTABLE_PGS_CULLED = 86,
+ VMSTAT_UNEVICTABLE_PGS_SCANNED = 87,
+ VMSTAT_UNEVICTABLE_PGS_RESCUED = 88,
+ VMSTAT_UNEVICTABLE_PGS_MLOCKED = 89,
+ VMSTAT_UNEVICTABLE_PGS_MUNLOCKED = 90,
+ VMSTAT_UNEVICTABLE_PGS_CLEARED = 91,
+ VMSTAT_UNEVICTABLE_PGS_STRANDED = 92,
+ VMSTAT_NR_ZSPAGES = 93,
+ VMSTAT_NR_ION_HEAP = 94,
+ VMSTAT_NR_GPU_HEAP = 95,
+ VMSTAT_ALLOCSTALL_DMA = 96,
+ VMSTAT_ALLOCSTALL_MOVABLE = 97,
+ VMSTAT_ALLOCSTALL_NORMAL = 98,
+ VMSTAT_COMPACT_DAEMON_FREE_SCANNED = 99,
+ VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED = 100,
+ VMSTAT_NR_FASTRPC = 101,
+ VMSTAT_NR_INDIRECTLY_RECLAIMABLE = 102,
+ VMSTAT_NR_ION_HEAP_POOL = 103,
+ VMSTAT_NR_KERNEL_MISC_RECLAIMABLE = 104,
+ VMSTAT_NR_SHADOW_CALL_STACK_BYTES = 105,
+ VMSTAT_NR_SHMEM_HUGEPAGES = 106,
+ VMSTAT_NR_SHMEM_PMDMAPPED = 107,
+ VMSTAT_NR_UNRECLAIMABLE_PAGES = 108,
+ VMSTAT_NR_ZONE_ACTIVE_ANON = 109,
+ VMSTAT_NR_ZONE_ACTIVE_FILE = 110,
+ VMSTAT_NR_ZONE_INACTIVE_ANON = 111,
+ VMSTAT_NR_ZONE_INACTIVE_FILE = 112,
+ VMSTAT_NR_ZONE_UNEVICTABLE = 113,
+ VMSTAT_NR_ZONE_WRITE_PENDING = 114,
+ VMSTAT_OOM_KILL = 115,
+ VMSTAT_PGLAZYFREE = 116,
+ VMSTAT_PGLAZYFREED = 117,
+ VMSTAT_PGREFILL = 118,
+ VMSTAT_PGSCAN_DIRECT = 119,
+ VMSTAT_PGSCAN_KSWAPD = 120,
+ VMSTAT_PGSKIP_DMA = 121,
+ VMSTAT_PGSKIP_MOVABLE = 122,
+ VMSTAT_PGSKIP_NORMAL = 123,
+ VMSTAT_PGSTEAL_DIRECT = 124,
+ VMSTAT_PGSTEAL_KSWAPD = 125,
+ VMSTAT_SWAP_RA = 126,
+ VMSTAT_SWAP_RA_HIT = 127,
+ VMSTAT_WORKINGSET_RESTORE = 128,
+ VMSTAT_ALLOCSTALL_DEVICE = 129,
+ VMSTAT_ALLOCSTALL_DMA32 = 130,
+ VMSTAT_BALLOON_DEFLATE = 131,
+ VMSTAT_BALLOON_INFLATE = 132,
+ VMSTAT_BALLOON_MIGRATE = 133,
+ VMSTAT_CMA_ALLOC_FAIL = 134,
+ VMSTAT_CMA_ALLOC_SUCCESS = 135,
+ VMSTAT_NR_FILE_HUGEPAGES = 136,
+ VMSTAT_NR_FILE_PMDMAPPED = 137,
+ VMSTAT_NR_FOLL_PIN_ACQUIRED = 138,
+ VMSTAT_NR_FOLL_PIN_RELEASED = 139,
+ VMSTAT_NR_SEC_PAGE_TABLE_PAGES = 140,
+ VMSTAT_NR_SHADOW_CALL_STACK = 141,
+ VMSTAT_NR_SWAPCACHED = 142,
+ VMSTAT_NR_THROTTLED_WRITTEN = 143,
+ VMSTAT_PGALLOC_DEVICE = 144,
+ VMSTAT_PGALLOC_DMA32 = 145,
+ VMSTAT_PGDEMOTE_DIRECT = 146,
+ VMSTAT_PGDEMOTE_KSWAPD = 147,
+ VMSTAT_PGREUSE = 148,
+ VMSTAT_PGSCAN_ANON = 149,
+ VMSTAT_PGSCAN_FILE = 150,
+ VMSTAT_PGSKIP_DEVICE = 151,
+ VMSTAT_PGSKIP_DMA32 = 152,
+ VMSTAT_PGSTEAL_ANON = 153,
+ VMSTAT_PGSTEAL_FILE = 154,
+ VMSTAT_THP_COLLAPSE_ALLOC = 155,
+ VMSTAT_THP_COLLAPSE_ALLOC_FAILED = 156,
+ VMSTAT_THP_DEFERRED_SPLIT_PAGE = 157,
+ VMSTAT_THP_FAULT_ALLOC = 158,
+ VMSTAT_THP_FAULT_FALLBACK = 159,
+ VMSTAT_THP_FAULT_FALLBACK_CHARGE = 160,
+ VMSTAT_THP_FILE_ALLOC = 161,
+ VMSTAT_THP_FILE_FALLBACK = 162,
+ VMSTAT_THP_FILE_FALLBACK_CHARGE = 163,
+ VMSTAT_THP_FILE_MAPPED = 164,
+ VMSTAT_THP_MIGRATION_FAIL = 165,
+ VMSTAT_THP_MIGRATION_SPLIT = 166,
+ VMSTAT_THP_MIGRATION_SUCCESS = 167,
+ VMSTAT_THP_SCAN_EXCEED_NONE_PTE = 168,
+ VMSTAT_THP_SCAN_EXCEED_SHARE_PTE = 169,
+ VMSTAT_THP_SCAN_EXCEED_SWAP_PTE = 170,
+ VMSTAT_THP_SPLIT_PAGE = 171,
+ VMSTAT_THP_SPLIT_PAGE_FAILED = 172,
+ VMSTAT_THP_SPLIT_PMD = 173,
+ VMSTAT_THP_SWPOUT = 174,
+ VMSTAT_THP_SWPOUT_FALLBACK = 175,
+ VMSTAT_THP_ZERO_PAGE_ALLOC = 176,
+ VMSTAT_THP_ZERO_PAGE_ALLOC_FAILED = 177,
+ VMSTAT_VMA_LOCK_ABORT = 178,
+ VMSTAT_VMA_LOCK_MISS = 179,
+ VMSTAT_VMA_LOCK_RETRY = 180,
+ VMSTAT_VMA_LOCK_SUCCESS = 181,
+ VMSTAT_WORKINGSET_ACTIVATE_ANON = 182,
+ VMSTAT_WORKINGSET_ACTIVATE_FILE = 183,
+ VMSTAT_WORKINGSET_NODES = 184,
+ VMSTAT_WORKINGSET_REFAULT_ANON = 185,
+ VMSTAT_WORKINGSET_REFAULT_FILE = 186,
+ VMSTAT_WORKINGSET_RESTORE_ANON = 187,
+ VMSTAT_WORKINGSET_RESTORE_FILE = 188,
+};
+
+constexpr VmstatCounters VmstatCounters_MIN = VmstatCounters::VMSTAT_UNSPECIFIED;
+constexpr VmstatCounters VmstatCounters_MAX = VmstatCounters::VMSTAT_WORKINGSET_RESTORE_FILE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* VmstatCounters_Name(::perfetto::protos::pbzero::VmstatCounters value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNSPECIFIED:
+ return "VMSTAT_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FREE_PAGES:
+ return "VMSTAT_NR_FREE_PAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ALLOC_BATCH:
+ return "VMSTAT_NR_ALLOC_BATCH";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_INACTIVE_ANON:
+ return "VMSTAT_NR_INACTIVE_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ACTIVE_ANON:
+ return "VMSTAT_NR_ACTIVE_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_INACTIVE_FILE:
+ return "VMSTAT_NR_INACTIVE_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ACTIVE_FILE:
+ return "VMSTAT_NR_ACTIVE_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_UNEVICTABLE:
+ return "VMSTAT_NR_UNEVICTABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_MLOCK:
+ return "VMSTAT_NR_MLOCK";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ANON_PAGES:
+ return "VMSTAT_NR_ANON_PAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_MAPPED:
+ return "VMSTAT_NR_MAPPED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FILE_PAGES:
+ return "VMSTAT_NR_FILE_PAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY:
+ return "VMSTAT_NR_DIRTY";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_WRITEBACK:
+ return "VMSTAT_NR_WRITEBACK";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SLAB_RECLAIMABLE:
+ return "VMSTAT_NR_SLAB_RECLAIMABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SLAB_UNRECLAIMABLE:
+ return "VMSTAT_NR_SLAB_UNRECLAIMABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_PAGE_TABLE_PAGES:
+ return "VMSTAT_NR_PAGE_TABLE_PAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_KERNEL_STACK:
+ return "VMSTAT_NR_KERNEL_STACK";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_OVERHEAD:
+ return "VMSTAT_NR_OVERHEAD";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_UNSTABLE:
+ return "VMSTAT_NR_UNSTABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_BOUNCE:
+ return "VMSTAT_NR_BOUNCE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_VMSCAN_WRITE:
+ return "VMSTAT_NR_VMSCAN_WRITE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM:
+ return "VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_WRITEBACK_TEMP:
+ return "VMSTAT_NR_WRITEBACK_TEMP";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ISOLATED_ANON:
+ return "VMSTAT_NR_ISOLATED_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ISOLATED_FILE:
+ return "VMSTAT_NR_ISOLATED_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SHMEM:
+ return "VMSTAT_NR_SHMEM";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTIED:
+ return "VMSTAT_NR_DIRTIED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_WRITTEN:
+ return "VMSTAT_NR_WRITTEN";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_PAGES_SCANNED:
+ return "VMSTAT_NR_PAGES_SCANNED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_REFAULT:
+ return "VMSTAT_WORKINGSET_REFAULT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_ACTIVATE:
+ return "VMSTAT_WORKINGSET_ACTIVATE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_NODERECLAIM:
+ return "VMSTAT_WORKINGSET_NODERECLAIM";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES:
+ return "VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FREE_CMA:
+ return "VMSTAT_NR_FREE_CMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SWAPCACHE:
+ return "VMSTAT_NR_SWAPCACHE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY_THRESHOLD:
+ return "VMSTAT_NR_DIRTY_THRESHOLD";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD:
+ return "VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGPGIN:
+ return "VMSTAT_PGPGIN";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGPGOUT:
+ return "VMSTAT_PGPGOUT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGPGOUTCLEAN:
+ return "VMSTAT_PGPGOUTCLEAN";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PSWPIN:
+ return "VMSTAT_PSWPIN";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PSWPOUT:
+ return "VMSTAT_PSWPOUT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_DMA:
+ return "VMSTAT_PGALLOC_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_NORMAL:
+ return "VMSTAT_PGALLOC_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_MOVABLE:
+ return "VMSTAT_PGALLOC_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGFREE:
+ return "VMSTAT_PGFREE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGACTIVATE:
+ return "VMSTAT_PGACTIVATE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGDEACTIVATE:
+ return "VMSTAT_PGDEACTIVATE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGFAULT:
+ return "VMSTAT_PGFAULT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGMAJFAULT:
+ return "VMSTAT_PGMAJFAULT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_DMA:
+ return "VMSTAT_PGREFILL_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_NORMAL:
+ return "VMSTAT_PGREFILL_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_MOVABLE:
+ return "VMSTAT_PGREFILL_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_DMA:
+ return "VMSTAT_PGSTEAL_KSWAPD_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_NORMAL:
+ return "VMSTAT_PGSTEAL_KSWAPD_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_MOVABLE:
+ return "VMSTAT_PGSTEAL_KSWAPD_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_DMA:
+ return "VMSTAT_PGSTEAL_DIRECT_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_NORMAL:
+ return "VMSTAT_PGSTEAL_DIRECT_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_MOVABLE:
+ return "VMSTAT_PGSTEAL_DIRECT_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_DMA:
+ return "VMSTAT_PGSCAN_KSWAPD_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_NORMAL:
+ return "VMSTAT_PGSCAN_KSWAPD_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_MOVABLE:
+ return "VMSTAT_PGSCAN_KSWAPD_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_DMA:
+ return "VMSTAT_PGSCAN_DIRECT_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_NORMAL:
+ return "VMSTAT_PGSCAN_DIRECT_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_MOVABLE:
+ return "VMSTAT_PGSCAN_DIRECT_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_THROTTLE:
+ return "VMSTAT_PGSCAN_DIRECT_THROTTLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGINODESTEAL:
+ return "VMSTAT_PGINODESTEAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_SLABS_SCANNED:
+ return "VMSTAT_SLABS_SCANNED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_INODESTEAL:
+ return "VMSTAT_KSWAPD_INODESTEAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY:
+ return "VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY:
+ return "VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PAGEOUTRUN:
+ return "VMSTAT_PAGEOUTRUN";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL:
+ return "VMSTAT_ALLOCSTALL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGROTATED:
+ return "VMSTAT_PGROTATED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_DROP_PAGECACHE:
+ return "VMSTAT_DROP_PAGECACHE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_DROP_SLAB:
+ return "VMSTAT_DROP_SLAB";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGMIGRATE_SUCCESS:
+ return "VMSTAT_PGMIGRATE_SUCCESS";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGMIGRATE_FAIL:
+ return "VMSTAT_PGMIGRATE_FAIL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_MIGRATE_SCANNED:
+ return "VMSTAT_COMPACT_MIGRATE_SCANNED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_FREE_SCANNED:
+ return "VMSTAT_COMPACT_FREE_SCANNED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_ISOLATED:
+ return "VMSTAT_COMPACT_ISOLATED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_STALL:
+ return "VMSTAT_COMPACT_STALL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_FAIL:
+ return "VMSTAT_COMPACT_FAIL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_SUCCESS:
+ return "VMSTAT_COMPACT_SUCCESS";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_DAEMON_WAKE:
+ return "VMSTAT_COMPACT_DAEMON_WAKE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_CULLED:
+ return "VMSTAT_UNEVICTABLE_PGS_CULLED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_SCANNED:
+ return "VMSTAT_UNEVICTABLE_PGS_SCANNED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_RESCUED:
+ return "VMSTAT_UNEVICTABLE_PGS_RESCUED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_MLOCKED:
+ return "VMSTAT_UNEVICTABLE_PGS_MLOCKED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_MUNLOCKED:
+ return "VMSTAT_UNEVICTABLE_PGS_MUNLOCKED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_CLEARED:
+ return "VMSTAT_UNEVICTABLE_PGS_CLEARED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_STRANDED:
+ return "VMSTAT_UNEVICTABLE_PGS_STRANDED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ZSPAGES:
+ return "VMSTAT_NR_ZSPAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ION_HEAP:
+ return "VMSTAT_NR_ION_HEAP";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_GPU_HEAP:
+ return "VMSTAT_NR_GPU_HEAP";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_DMA:
+ return "VMSTAT_ALLOCSTALL_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_MOVABLE:
+ return "VMSTAT_ALLOCSTALL_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_NORMAL:
+ return "VMSTAT_ALLOCSTALL_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_DAEMON_FREE_SCANNED:
+ return "VMSTAT_COMPACT_DAEMON_FREE_SCANNED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED:
+ return "VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FASTRPC:
+ return "VMSTAT_NR_FASTRPC";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_INDIRECTLY_RECLAIMABLE:
+ return "VMSTAT_NR_INDIRECTLY_RECLAIMABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ION_HEAP_POOL:
+ return "VMSTAT_NR_ION_HEAP_POOL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_KERNEL_MISC_RECLAIMABLE:
+ return "VMSTAT_NR_KERNEL_MISC_RECLAIMABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SHADOW_CALL_STACK_BYTES:
+ return "VMSTAT_NR_SHADOW_CALL_STACK_BYTES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SHMEM_HUGEPAGES:
+ return "VMSTAT_NR_SHMEM_HUGEPAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SHMEM_PMDMAPPED:
+ return "VMSTAT_NR_SHMEM_PMDMAPPED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_UNRECLAIMABLE_PAGES:
+ return "VMSTAT_NR_UNRECLAIMABLE_PAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_ACTIVE_ANON:
+ return "VMSTAT_NR_ZONE_ACTIVE_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_ACTIVE_FILE:
+ return "VMSTAT_NR_ZONE_ACTIVE_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_INACTIVE_ANON:
+ return "VMSTAT_NR_ZONE_INACTIVE_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_INACTIVE_FILE:
+ return "VMSTAT_NR_ZONE_INACTIVE_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_UNEVICTABLE:
+ return "VMSTAT_NR_ZONE_UNEVICTABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_WRITE_PENDING:
+ return "VMSTAT_NR_ZONE_WRITE_PENDING";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_OOM_KILL:
+ return "VMSTAT_OOM_KILL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGLAZYFREE:
+ return "VMSTAT_PGLAZYFREE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGLAZYFREED:
+ return "VMSTAT_PGLAZYFREED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGREFILL:
+ return "VMSTAT_PGREFILL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT:
+ return "VMSTAT_PGSCAN_DIRECT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD:
+ return "VMSTAT_PGSCAN_KSWAPD";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_DMA:
+ return "VMSTAT_PGSKIP_DMA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_MOVABLE:
+ return "VMSTAT_PGSKIP_MOVABLE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_NORMAL:
+ return "VMSTAT_PGSKIP_NORMAL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT:
+ return "VMSTAT_PGSTEAL_DIRECT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD:
+ return "VMSTAT_PGSTEAL_KSWAPD";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_SWAP_RA:
+ return "VMSTAT_SWAP_RA";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_SWAP_RA_HIT:
+ return "VMSTAT_SWAP_RA_HIT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_RESTORE:
+ return "VMSTAT_WORKINGSET_RESTORE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_DEVICE:
+ return "VMSTAT_ALLOCSTALL_DEVICE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_DMA32:
+ return "VMSTAT_ALLOCSTALL_DMA32";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_BALLOON_DEFLATE:
+ return "VMSTAT_BALLOON_DEFLATE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_BALLOON_INFLATE:
+ return "VMSTAT_BALLOON_INFLATE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_BALLOON_MIGRATE:
+ return "VMSTAT_BALLOON_MIGRATE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_CMA_ALLOC_FAIL:
+ return "VMSTAT_CMA_ALLOC_FAIL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_CMA_ALLOC_SUCCESS:
+ return "VMSTAT_CMA_ALLOC_SUCCESS";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FILE_HUGEPAGES:
+ return "VMSTAT_NR_FILE_HUGEPAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FILE_PMDMAPPED:
+ return "VMSTAT_NR_FILE_PMDMAPPED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FOLL_PIN_ACQUIRED:
+ return "VMSTAT_NR_FOLL_PIN_ACQUIRED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_FOLL_PIN_RELEASED:
+ return "VMSTAT_NR_FOLL_PIN_RELEASED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SEC_PAGE_TABLE_PAGES:
+ return "VMSTAT_NR_SEC_PAGE_TABLE_PAGES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SHADOW_CALL_STACK:
+ return "VMSTAT_NR_SHADOW_CALL_STACK";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_SWAPCACHED:
+ return "VMSTAT_NR_SWAPCACHED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_NR_THROTTLED_WRITTEN:
+ return "VMSTAT_NR_THROTTLED_WRITTEN";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_DEVICE:
+ return "VMSTAT_PGALLOC_DEVICE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_DMA32:
+ return "VMSTAT_PGALLOC_DMA32";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGDEMOTE_DIRECT:
+ return "VMSTAT_PGDEMOTE_DIRECT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGDEMOTE_KSWAPD:
+ return "VMSTAT_PGDEMOTE_KSWAPD";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGREUSE:
+ return "VMSTAT_PGREUSE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_ANON:
+ return "VMSTAT_PGSCAN_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_FILE:
+ return "VMSTAT_PGSCAN_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_DEVICE:
+ return "VMSTAT_PGSKIP_DEVICE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_DMA32:
+ return "VMSTAT_PGSKIP_DMA32";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_ANON:
+ return "VMSTAT_PGSTEAL_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_FILE:
+ return "VMSTAT_PGSTEAL_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_COLLAPSE_ALLOC:
+ return "VMSTAT_THP_COLLAPSE_ALLOC";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_COLLAPSE_ALLOC_FAILED:
+ return "VMSTAT_THP_COLLAPSE_ALLOC_FAILED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_DEFERRED_SPLIT_PAGE:
+ return "VMSTAT_THP_DEFERRED_SPLIT_PAGE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_FAULT_ALLOC:
+ return "VMSTAT_THP_FAULT_ALLOC";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_FAULT_FALLBACK:
+ return "VMSTAT_THP_FAULT_FALLBACK";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_FAULT_FALLBACK_CHARGE:
+ return "VMSTAT_THP_FAULT_FALLBACK_CHARGE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_FILE_ALLOC:
+ return "VMSTAT_THP_FILE_ALLOC";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_FILE_FALLBACK:
+ return "VMSTAT_THP_FILE_FALLBACK";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_FILE_FALLBACK_CHARGE:
+ return "VMSTAT_THP_FILE_FALLBACK_CHARGE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_FILE_MAPPED:
+ return "VMSTAT_THP_FILE_MAPPED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_MIGRATION_FAIL:
+ return "VMSTAT_THP_MIGRATION_FAIL";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_MIGRATION_SPLIT:
+ return "VMSTAT_THP_MIGRATION_SPLIT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_MIGRATION_SUCCESS:
+ return "VMSTAT_THP_MIGRATION_SUCCESS";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SCAN_EXCEED_NONE_PTE:
+ return "VMSTAT_THP_SCAN_EXCEED_NONE_PTE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SCAN_EXCEED_SHARE_PTE:
+ return "VMSTAT_THP_SCAN_EXCEED_SHARE_PTE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SCAN_EXCEED_SWAP_PTE:
+ return "VMSTAT_THP_SCAN_EXCEED_SWAP_PTE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SPLIT_PAGE:
+ return "VMSTAT_THP_SPLIT_PAGE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SPLIT_PAGE_FAILED:
+ return "VMSTAT_THP_SPLIT_PAGE_FAILED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SPLIT_PMD:
+ return "VMSTAT_THP_SPLIT_PMD";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SWPOUT:
+ return "VMSTAT_THP_SWPOUT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_SWPOUT_FALLBACK:
+ return "VMSTAT_THP_SWPOUT_FALLBACK";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_ZERO_PAGE_ALLOC:
+ return "VMSTAT_THP_ZERO_PAGE_ALLOC";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_THP_ZERO_PAGE_ALLOC_FAILED:
+ return "VMSTAT_THP_ZERO_PAGE_ALLOC_FAILED";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_VMA_LOCK_ABORT:
+ return "VMSTAT_VMA_LOCK_ABORT";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_VMA_LOCK_MISS:
+ return "VMSTAT_VMA_LOCK_MISS";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_VMA_LOCK_RETRY:
+ return "VMSTAT_VMA_LOCK_RETRY";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_VMA_LOCK_SUCCESS:
+ return "VMSTAT_VMA_LOCK_SUCCESS";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_ACTIVATE_ANON:
+ return "VMSTAT_WORKINGSET_ACTIVATE_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_ACTIVATE_FILE:
+ return "VMSTAT_WORKINGSET_ACTIVATE_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_NODES:
+ return "VMSTAT_WORKINGSET_NODES";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_REFAULT_ANON:
+ return "VMSTAT_WORKINGSET_REFAULT_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_REFAULT_FILE:
+ return "VMSTAT_WORKINGSET_REFAULT_FILE";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_RESTORE_ANON:
+ return "VMSTAT_WORKINGSET_RESTORE_ANON";
+
+ case ::perfetto::protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_RESTORE_FILE:
+ return "VMSTAT_WORKINGSET_RESTORE_FILE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/trace_stats.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACE_STATS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACE_STATS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class TraceStats_BufferStats;
+class TraceStats_FilterStats;
+class TraceStats_WriterStats;
+namespace perfetto_pbzero_enum_TraceStats {
+enum FinalFlushOutcome : int32_t;
+} // namespace perfetto_pbzero_enum_TraceStats
+using TraceStats_FinalFlushOutcome = perfetto_pbzero_enum_TraceStats::FinalFlushOutcome;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_TraceStats {
+enum FinalFlushOutcome : int32_t {
+ FINAL_FLUSH_UNSPECIFIED = 0,
+ FINAL_FLUSH_SUCCEEDED = 1,
+ FINAL_FLUSH_FAILED = 2,
+};
+} // namespace perfetto_pbzero_enum_TraceStats
+using TraceStats_FinalFlushOutcome = perfetto_pbzero_enum_TraceStats::FinalFlushOutcome;
+
+
+constexpr TraceStats_FinalFlushOutcome TraceStats_FinalFlushOutcome_MIN = TraceStats_FinalFlushOutcome::FINAL_FLUSH_UNSPECIFIED;
+constexpr TraceStats_FinalFlushOutcome TraceStats_FinalFlushOutcome_MAX = TraceStats_FinalFlushOutcome::FINAL_FLUSH_FAILED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TraceStats_FinalFlushOutcome_Name(::perfetto::protos::pbzero::TraceStats_FinalFlushOutcome value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TraceStats_FinalFlushOutcome::FINAL_FLUSH_UNSPECIFIED:
+ return "FINAL_FLUSH_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TraceStats_FinalFlushOutcome::FINAL_FLUSH_SUCCEEDED:
+ return "FINAL_FLUSH_SUCCEEDED";
+
+ case ::perfetto::protos::pbzero::TraceStats_FinalFlushOutcome::FINAL_FLUSH_FAILED:
+ return "FINAL_FLUSH_FAILED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class TraceStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/18, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TraceStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buffer_stats() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> buffer_stats() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_chunk_payload_histogram_def() const { return at<17>().valid(); }
+ ::protozero::RepeatedFieldIterator<int64_t> chunk_payload_histogram_def() const { return GetRepeated<int64_t>(17); }
+ bool has_writer_stats() const { return at<18>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> writer_stats() const { return GetRepeated<::protozero::ConstBytes>(18); }
+ bool has_producers_connected() const { return at<2>().valid(); }
+ uint32_t producers_connected() const { return at<2>().as_uint32(); }
+ bool has_producers_seen() const { return at<3>().valid(); }
+ uint64_t producers_seen() const { return at<3>().as_uint64(); }
+ bool has_data_sources_registered() const { return at<4>().valid(); }
+ uint32_t data_sources_registered() const { return at<4>().as_uint32(); }
+ bool has_data_sources_seen() const { return at<5>().valid(); }
+ uint64_t data_sources_seen() const { return at<5>().as_uint64(); }
+ bool has_tracing_sessions() const { return at<6>().valid(); }
+ uint32_t tracing_sessions() const { return at<6>().as_uint32(); }
+ bool has_total_buffers() const { return at<7>().valid(); }
+ uint32_t total_buffers() const { return at<7>().as_uint32(); }
+ bool has_chunks_discarded() const { return at<8>().valid(); }
+ uint64_t chunks_discarded() const { return at<8>().as_uint64(); }
+ bool has_patches_discarded() const { return at<9>().valid(); }
+ uint64_t patches_discarded() const { return at<9>().as_uint64(); }
+ bool has_invalid_packets() const { return at<10>().valid(); }
+ uint64_t invalid_packets() const { return at<10>().as_uint64(); }
+ bool has_filter_stats() const { return at<11>().valid(); }
+ ::protozero::ConstBytes filter_stats() const { return at<11>().as_bytes(); }
+ bool has_flushes_requested() const { return at<12>().valid(); }
+ uint64_t flushes_requested() const { return at<12>().as_uint64(); }
+ bool has_flushes_succeeded() const { return at<13>().valid(); }
+ uint64_t flushes_succeeded() const { return at<13>().as_uint64(); }
+ bool has_flushes_failed() const { return at<14>().valid(); }
+ uint64_t flushes_failed() const { return at<14>().as_uint64(); }
+ bool has_final_flush_outcome() const { return at<15>().valid(); }
+ int32_t final_flush_outcome() const { return at<15>().as_int32(); }
+};
+
+class TraceStats : public ::protozero::Message {
+ public:
+ using Decoder = TraceStats_Decoder;
+ enum : int32_t {
+ kBufferStatsFieldNumber = 1,
+ kChunkPayloadHistogramDefFieldNumber = 17,
+ kWriterStatsFieldNumber = 18,
+ kProducersConnectedFieldNumber = 2,
+ kProducersSeenFieldNumber = 3,
+ kDataSourcesRegisteredFieldNumber = 4,
+ kDataSourcesSeenFieldNumber = 5,
+ kTracingSessionsFieldNumber = 6,
+ kTotalBuffersFieldNumber = 7,
+ kChunksDiscardedFieldNumber = 8,
+ kPatchesDiscardedFieldNumber = 9,
+ kInvalidPacketsFieldNumber = 10,
+ kFilterStatsFieldNumber = 11,
+ kFlushesRequestedFieldNumber = 12,
+ kFlushesSucceededFieldNumber = 13,
+ kFlushesFailedFieldNumber = 14,
+ kFinalFlushOutcomeFieldNumber = 15,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceStats"; }
+
+ using BufferStats = ::perfetto::protos::pbzero::TraceStats_BufferStats;
+ using WriterStats = ::perfetto::protos::pbzero::TraceStats_WriterStats;
+ using FilterStats = ::perfetto::protos::pbzero::TraceStats_FilterStats;
+
+ using FinalFlushOutcome = ::perfetto::protos::pbzero::TraceStats_FinalFlushOutcome;
+ static inline const char* FinalFlushOutcome_Name(FinalFlushOutcome value) {
+ return ::perfetto::protos::pbzero::TraceStats_FinalFlushOutcome_Name(value);
+ }
+ static inline const FinalFlushOutcome FINAL_FLUSH_UNSPECIFIED = FinalFlushOutcome::FINAL_FLUSH_UNSPECIFIED;
+ static inline const FinalFlushOutcome FINAL_FLUSH_SUCCEEDED = FinalFlushOutcome::FINAL_FLUSH_SUCCEEDED;
+ static inline const FinalFlushOutcome FINAL_FLUSH_FAILED = FinalFlushOutcome::FINAL_FLUSH_FAILED;
+
+ using FieldMetadata_BufferStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceStats_BufferStats,
+ TraceStats>;
+
+ static constexpr FieldMetadata_BufferStats kBufferStats{};
+ template <typename T = TraceStats_BufferStats> T* add_buffer_stats() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ChunkPayloadHistogramDef =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_ChunkPayloadHistogramDef kChunkPayloadHistogramDef{};
+ void add_chunk_payload_histogram_def(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunkPayloadHistogramDef::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WriterStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceStats_WriterStats,
+ TraceStats>;
+
+ static constexpr FieldMetadata_WriterStats kWriterStats{};
+ template <typename T = TraceStats_WriterStats> T* add_writer_stats() {
+ return BeginNestedMessage<T>(18);
+ }
+
+
+ using FieldMetadata_ProducersConnected =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_ProducersConnected kProducersConnected{};
+ void set_producers_connected(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducersConnected::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProducersSeen =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_ProducersSeen kProducersSeen{};
+ void set_producers_seen(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducersSeen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSourcesRegistered =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_DataSourcesRegistered kDataSourcesRegistered{};
+ void set_data_sources_registered(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSourcesRegistered::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSourcesSeen =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_DataSourcesSeen kDataSourcesSeen{};
+ void set_data_sources_seen(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSourcesSeen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TracingSessions =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_TracingSessions kTracingSessions{};
+ void set_tracing_sessions(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingSessions::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalBuffers =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_TotalBuffers kTotalBuffers{};
+ void set_total_buffers(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalBuffers::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunksDiscarded =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_ChunksDiscarded kChunksDiscarded{};
+ void set_chunks_discarded(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunksDiscarded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PatchesDiscarded =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_PatchesDiscarded kPatchesDiscarded{};
+ void set_patches_discarded(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PatchesDiscarded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InvalidPackets =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_InvalidPackets kInvalidPackets{};
+ void set_invalid_packets(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InvalidPackets::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FilterStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceStats_FilterStats,
+ TraceStats>;
+
+ static constexpr FieldMetadata_FilterStats kFilterStats{};
+ template <typename T = TraceStats_FilterStats> T* set_filter_stats() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_FlushesRequested =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_FlushesRequested kFlushesRequested{};
+ void set_flushes_requested(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushesRequested::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlushesSucceeded =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_FlushesSucceeded kFlushesSucceeded{};
+ void set_flushes_succeeded(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushesSucceeded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlushesFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats>;
+
+ static constexpr FieldMetadata_FlushesFailed kFlushesFailed{};
+ void set_flushes_failed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushesFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FinalFlushOutcome =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TraceStats_FinalFlushOutcome,
+ TraceStats>;
+
+ static constexpr FieldMetadata_FinalFlushOutcome kFinalFlushOutcome{};
+ void set_final_flush_outcome(TraceStats_FinalFlushOutcome value) {
+ static constexpr uint32_t field_id = FieldMetadata_FinalFlushOutcome::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceStats_FilterStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/20, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TraceStats_FilterStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceStats_FilterStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceStats_FilterStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_input_packets() const { return at<1>().valid(); }
+ uint64_t input_packets() const { return at<1>().as_uint64(); }
+ bool has_input_bytes() const { return at<2>().valid(); }
+ uint64_t input_bytes() const { return at<2>().as_uint64(); }
+ bool has_output_bytes() const { return at<3>().valid(); }
+ uint64_t output_bytes() const { return at<3>().as_uint64(); }
+ bool has_errors() const { return at<4>().valid(); }
+ uint64_t errors() const { return at<4>().as_uint64(); }
+ bool has_time_taken_ns() const { return at<5>().valid(); }
+ uint64_t time_taken_ns() const { return at<5>().as_uint64(); }
+ bool has_bytes_discarded_per_buffer() const { return at<20>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> bytes_discarded_per_buffer() const { return GetRepeated<uint64_t>(20); }
+};
+
+class TraceStats_FilterStats : public ::protozero::Message {
+ public:
+ using Decoder = TraceStats_FilterStats_Decoder;
+ enum : int32_t {
+ kInputPacketsFieldNumber = 1,
+ kInputBytesFieldNumber = 2,
+ kOutputBytesFieldNumber = 3,
+ kErrorsFieldNumber = 4,
+ kTimeTakenNsFieldNumber = 5,
+ kBytesDiscardedPerBufferFieldNumber = 20,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceStats.FilterStats"; }
+
+
+ using FieldMetadata_InputPackets =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_FilterStats>;
+
+ static constexpr FieldMetadata_InputPackets kInputPackets{};
+ void set_input_packets(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputPackets::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InputBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_FilterStats>;
+
+ static constexpr FieldMetadata_InputBytes kInputBytes{};
+ void set_input_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OutputBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_FilterStats>;
+
+ static constexpr FieldMetadata_OutputBytes kOutputBytes{};
+ void set_output_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OutputBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Errors =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_FilterStats>;
+
+ static constexpr FieldMetadata_Errors kErrors{};
+ void set_errors(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Errors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimeTakenNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_FilterStats>;
+
+ static constexpr FieldMetadata_TimeTakenNs kTimeTakenNs{};
+ void set_time_taken_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimeTakenNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesDiscardedPerBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_FilterStats>;
+
+ static constexpr FieldMetadata_BytesDiscardedPerBuffer kBytesDiscardedPerBuffer{};
+ void add_bytes_discarded_per_buffer(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesDiscardedPerBuffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceStats_WriterStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceStats_WriterStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceStats_WriterStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceStats_WriterStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_sequence_id() const { return at<1>().valid(); }
+ uint64_t sequence_id() const { return at<1>().as_uint64(); }
+ bool has_buffer() const { return at<4>().valid(); }
+ uint32_t buffer() const { return at<4>().as_uint32(); }
+ bool has_chunk_payload_histogram_counts() const { return at<2>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> chunk_payload_histogram_counts(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(2, parse_error_ptr); }
+ bool has_chunk_payload_histogram_sum() const { return at<3>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int64_t> chunk_payload_histogram_sum(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int64_t>(3, parse_error_ptr); }
+};
+
+class TraceStats_WriterStats : public ::protozero::Message {
+ public:
+ using Decoder = TraceStats_WriterStats_Decoder;
+ enum : int32_t {
+ kSequenceIdFieldNumber = 1,
+ kBufferFieldNumber = 4,
+ kChunkPayloadHistogramCountsFieldNumber = 2,
+ kChunkPayloadHistogramSumFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceStats.WriterStats"; }
+
+
+ using FieldMetadata_SequenceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_WriterStats>;
+
+ static constexpr FieldMetadata_SequenceId kSequenceId{};
+ void set_sequence_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SequenceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Buffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceStats_WriterStats>;
+
+ static constexpr FieldMetadata_Buffer kBuffer{};
+ void set_buffer(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Buffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunkPayloadHistogramCounts =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_WriterStats>;
+
+ static constexpr FieldMetadata_ChunkPayloadHistogramCounts kChunkPayloadHistogramCounts{};
+ void set_chunk_payload_histogram_counts(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_ChunkPayloadHistogramCounts::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_ChunkPayloadHistogramSum =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceStats_WriterStats>;
+
+ static constexpr FieldMetadata_ChunkPayloadHistogramSum kChunkPayloadHistogramSum{};
+ void set_chunk_payload_histogram_sum(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_ChunkPayloadHistogramSum::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+};
+
+class TraceStats_BufferStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/19, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceStats_BufferStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceStats_BufferStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceStats_BufferStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buffer_size() const { return at<12>().valid(); }
+ uint64_t buffer_size() const { return at<12>().as_uint64(); }
+ bool has_bytes_written() const { return at<1>().valid(); }
+ uint64_t bytes_written() const { return at<1>().as_uint64(); }
+ bool has_bytes_overwritten() const { return at<13>().valid(); }
+ uint64_t bytes_overwritten() const { return at<13>().as_uint64(); }
+ bool has_bytes_read() const { return at<14>().valid(); }
+ uint64_t bytes_read() const { return at<14>().as_uint64(); }
+ bool has_padding_bytes_written() const { return at<15>().valid(); }
+ uint64_t padding_bytes_written() const { return at<15>().as_uint64(); }
+ bool has_padding_bytes_cleared() const { return at<16>().valid(); }
+ uint64_t padding_bytes_cleared() const { return at<16>().as_uint64(); }
+ bool has_chunks_written() const { return at<2>().valid(); }
+ uint64_t chunks_written() const { return at<2>().as_uint64(); }
+ bool has_chunks_rewritten() const { return at<10>().valid(); }
+ uint64_t chunks_rewritten() const { return at<10>().as_uint64(); }
+ bool has_chunks_overwritten() const { return at<3>().valid(); }
+ uint64_t chunks_overwritten() const { return at<3>().as_uint64(); }
+ bool has_chunks_discarded() const { return at<18>().valid(); }
+ uint64_t chunks_discarded() const { return at<18>().as_uint64(); }
+ bool has_chunks_read() const { return at<17>().valid(); }
+ uint64_t chunks_read() const { return at<17>().as_uint64(); }
+ bool has_chunks_committed_out_of_order() const { return at<11>().valid(); }
+ uint64_t chunks_committed_out_of_order() const { return at<11>().as_uint64(); }
+ bool has_write_wrap_count() const { return at<4>().valid(); }
+ uint64_t write_wrap_count() const { return at<4>().as_uint64(); }
+ bool has_patches_succeeded() const { return at<5>().valid(); }
+ uint64_t patches_succeeded() const { return at<5>().as_uint64(); }
+ bool has_patches_failed() const { return at<6>().valid(); }
+ uint64_t patches_failed() const { return at<6>().as_uint64(); }
+ bool has_readaheads_succeeded() const { return at<7>().valid(); }
+ uint64_t readaheads_succeeded() const { return at<7>().as_uint64(); }
+ bool has_readaheads_failed() const { return at<8>().valid(); }
+ uint64_t readaheads_failed() const { return at<8>().as_uint64(); }
+ bool has_abi_violations() const { return at<9>().valid(); }
+ uint64_t abi_violations() const { return at<9>().as_uint64(); }
+ bool has_trace_writer_packet_loss() const { return at<19>().valid(); }
+ uint64_t trace_writer_packet_loss() const { return at<19>().as_uint64(); }
+};
+
+class TraceStats_BufferStats : public ::protozero::Message {
+ public:
+ using Decoder = TraceStats_BufferStats_Decoder;
+ enum : int32_t {
+ kBufferSizeFieldNumber = 12,
+ kBytesWrittenFieldNumber = 1,
+ kBytesOverwrittenFieldNumber = 13,
+ kBytesReadFieldNumber = 14,
+ kPaddingBytesWrittenFieldNumber = 15,
+ kPaddingBytesClearedFieldNumber = 16,
+ kChunksWrittenFieldNumber = 2,
+ kChunksRewrittenFieldNumber = 10,
+ kChunksOverwrittenFieldNumber = 3,
+ kChunksDiscardedFieldNumber = 18,
+ kChunksReadFieldNumber = 17,
+ kChunksCommittedOutOfOrderFieldNumber = 11,
+ kWriteWrapCountFieldNumber = 4,
+ kPatchesSucceededFieldNumber = 5,
+ kPatchesFailedFieldNumber = 6,
+ kReadaheadsSucceededFieldNumber = 7,
+ kReadaheadsFailedFieldNumber = 8,
+ kAbiViolationsFieldNumber = 9,
+ kTraceWriterPacketLossFieldNumber = 19,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceStats.BufferStats"; }
+
+
+ using FieldMetadata_BufferSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_BufferSize kBufferSize{};
+ void set_buffer_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesWritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_BytesWritten kBytesWritten{};
+ void set_bytes_written(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesWritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesOverwritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_BytesOverwritten kBytesOverwritten{};
+ void set_bytes_overwritten(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesOverwritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesRead =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_BytesRead kBytesRead{};
+ void set_bytes_read(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesRead::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaddingBytesWritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_PaddingBytesWritten kPaddingBytesWritten{};
+ void set_padding_bytes_written(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaddingBytesWritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaddingBytesCleared =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_PaddingBytesCleared kPaddingBytesCleared{};
+ void set_padding_bytes_cleared(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaddingBytesCleared::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunksWritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ChunksWritten kChunksWritten{};
+ void set_chunks_written(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunksWritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunksRewritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ChunksRewritten kChunksRewritten{};
+ void set_chunks_rewritten(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunksRewritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunksOverwritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ChunksOverwritten kChunksOverwritten{};
+ void set_chunks_overwritten(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunksOverwritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunksDiscarded =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ChunksDiscarded kChunksDiscarded{};
+ void set_chunks_discarded(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunksDiscarded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunksRead =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ChunksRead kChunksRead{};
+ void set_chunks_read(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunksRead::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChunksCommittedOutOfOrder =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ChunksCommittedOutOfOrder kChunksCommittedOutOfOrder{};
+ void set_chunks_committed_out_of_order(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunksCommittedOutOfOrder::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WriteWrapCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_WriteWrapCount kWriteWrapCount{};
+ void set_write_wrap_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WriteWrapCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PatchesSucceeded =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_PatchesSucceeded kPatchesSucceeded{};
+ void set_patches_succeeded(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PatchesSucceeded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PatchesFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_PatchesFailed kPatchesFailed{};
+ void set_patches_failed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PatchesFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadaheadsSucceeded =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ReadaheadsSucceeded kReadaheadsSucceeded{};
+ void set_readaheads_succeeded(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadaheadsSucceeded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadaheadsFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_ReadaheadsFailed kReadaheadsFailed{};
+ void set_readaheads_failed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadaheadsFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AbiViolations =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_AbiViolations kAbiViolations{};
+ void set_abi_violations(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AbiViolations::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceWriterPacketLoss =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceStats_BufferStats>;
+
+ static constexpr FieldMetadata_TraceWriterPacketLoss kTraceWriterPacketLoss{};
+ void set_trace_writer_packet_loss(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceWriterPacketLoss::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/tracing_service_capabilities.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_CAPABILITIES_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_CAPABILITIES_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ObservableEvents {
+enum Type : int32_t;
+} // namespace perfetto_pbzero_enum_ObservableEvents
+using ObservableEvents_Type = perfetto_pbzero_enum_ObservableEvents::Type;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TracingServiceCapabilities_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TracingServiceCapabilities_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingServiceCapabilities_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingServiceCapabilities_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_has_query_capabilities() const { return at<1>().valid(); }
+ bool has_query_capabilities() const { return at<1>().as_bool(); }
+ bool has_observable_events() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> observable_events() const { return GetRepeated<int32_t>(2); }
+ bool has_has_trace_config_output_path() const { return at<3>().valid(); }
+ bool has_trace_config_output_path() const { return at<3>().as_bool(); }
+ bool has_has_clone_session() const { return at<4>().valid(); }
+ bool has_clone_session() const { return at<4>().as_bool(); }
+};
+
+class TracingServiceCapabilities : public ::protozero::Message {
+ public:
+ using Decoder = TracingServiceCapabilities_Decoder;
+ enum : int32_t {
+ kHasQueryCapabilitiesFieldNumber = 1,
+ kObservableEventsFieldNumber = 2,
+ kHasTraceConfigOutputPathFieldNumber = 3,
+ kHasCloneSessionFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingServiceCapabilities"; }
+
+
+ using FieldMetadata_HasQueryCapabilities =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceCapabilities>;
+
+ static constexpr FieldMetadata_HasQueryCapabilities kHasQueryCapabilities{};
+ void set_has_query_capabilities(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasQueryCapabilities::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ObservableEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ObservableEvents_Type,
+ TracingServiceCapabilities>;
+
+ static constexpr FieldMetadata_ObservableEvents kObservableEvents{};
+ void add_observable_events(ObservableEvents_Type value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObservableEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasTraceConfigOutputPath =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceCapabilities>;
+
+ static constexpr FieldMetadata_HasTraceConfigOutputPath kHasTraceConfigOutputPath{};
+ void set_has_trace_config_output_path(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasTraceConfigOutputPath::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasCloneSession =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceCapabilities>;
+
+ static constexpr FieldMetadata_HasCloneSession kHasCloneSession{};
+ void set_has_clone_session(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasCloneSession::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/tracing_service_state.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_STATE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACING_SERVICE_STATE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DataSourceDescriptor;
+class TracingServiceState_DataSource;
+class TracingServiceState_Producer;
+class TracingServiceState_TracingSession;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TracingServiceState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TracingServiceState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingServiceState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingServiceState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_producers() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> producers() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_data_sources() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> data_sources() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_tracing_sessions() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> tracing_sessions() const { return GetRepeated<::protozero::ConstBytes>(6); }
+ bool has_supports_tracing_sessions() const { return at<7>().valid(); }
+ bool supports_tracing_sessions() const { return at<7>().as_bool(); }
+ bool has_num_sessions() const { return at<3>().valid(); }
+ int32_t num_sessions() const { return at<3>().as_int32(); }
+ bool has_num_sessions_started() const { return at<4>().valid(); }
+ int32_t num_sessions_started() const { return at<4>().as_int32(); }
+ bool has_tracing_service_version() const { return at<5>().valid(); }
+ ::protozero::ConstChars tracing_service_version() const { return at<5>().as_string(); }
+};
+
+class TracingServiceState : public ::protozero::Message {
+ public:
+ using Decoder = TracingServiceState_Decoder;
+ enum : int32_t {
+ kProducersFieldNumber = 1,
+ kDataSourcesFieldNumber = 2,
+ kTracingSessionsFieldNumber = 6,
+ kSupportsTracingSessionsFieldNumber = 7,
+ kNumSessionsFieldNumber = 3,
+ kNumSessionsStartedFieldNumber = 4,
+ kTracingServiceVersionFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingServiceState"; }
+
+ using Producer = ::perfetto::protos::pbzero::TracingServiceState_Producer;
+ using DataSource = ::perfetto::protos::pbzero::TracingServiceState_DataSource;
+ using TracingSession = ::perfetto::protos::pbzero::TracingServiceState_TracingSession;
+
+ using FieldMetadata_Producers =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TracingServiceState_Producer,
+ TracingServiceState>;
+
+ static constexpr FieldMetadata_Producers kProducers{};
+ template <typename T = TracingServiceState_Producer> T* add_producers() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_DataSources =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TracingServiceState_DataSource,
+ TracingServiceState>;
+
+ static constexpr FieldMetadata_DataSources kDataSources{};
+ template <typename T = TracingServiceState_DataSource> T* add_data_sources() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_TracingSessions =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TracingServiceState_TracingSession,
+ TracingServiceState>;
+
+ static constexpr FieldMetadata_TracingSessions kTracingSessions{};
+ template <typename T = TracingServiceState_TracingSession> T* add_tracing_sessions() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_SupportsTracingSessions =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceState>;
+
+ static constexpr FieldMetadata_SupportsTracingSessions kSupportsTracingSessions{};
+ void set_supports_tracing_sessions(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SupportsTracingSessions::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumSessions =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState>;
+
+ static constexpr FieldMetadata_NumSessions kNumSessions{};
+ void set_num_sessions(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumSessions::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumSessionsStarted =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState>;
+
+ static constexpr FieldMetadata_NumSessionsStarted kNumSessionsStarted{};
+ void set_num_sessions_started(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumSessionsStarted::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TracingServiceVersion =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TracingServiceState>;
+
+ static constexpr FieldMetadata_TracingServiceVersion kTracingServiceVersion{};
+ void set_tracing_service_version(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TracingServiceVersion::kFieldId, data, size);
+ }
+ void set_tracing_service_version(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TracingServiceVersion::kFieldId, chars.data, chars.size);
+ }
+ void set_tracing_service_version(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingServiceVersion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TracingServiceState_TracingSession_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TracingServiceState_TracingSession_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingServiceState_TracingSession_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingServiceState_TracingSession_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+ bool has_consumer_uid() const { return at<2>().valid(); }
+ int32_t consumer_uid() const { return at<2>().as_int32(); }
+ bool has_state() const { return at<3>().valid(); }
+ ::protozero::ConstChars state() const { return at<3>().as_string(); }
+ bool has_unique_session_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars unique_session_name() const { return at<4>().as_string(); }
+ bool has_buffer_size_kb() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> buffer_size_kb() const { return GetRepeated<uint32_t>(5); }
+ bool has_duration_ms() const { return at<6>().valid(); }
+ uint32_t duration_ms() const { return at<6>().as_uint32(); }
+ bool has_num_data_sources() const { return at<7>().valid(); }
+ uint32_t num_data_sources() const { return at<7>().as_uint32(); }
+ bool has_start_realtime_ns() const { return at<8>().valid(); }
+ int64_t start_realtime_ns() const { return at<8>().as_int64(); }
+ bool has_bugreport_score() const { return at<9>().valid(); }
+ int32_t bugreport_score() const { return at<9>().as_int32(); }
+ bool has_bugreport_filename() const { return at<10>().valid(); }
+ ::protozero::ConstChars bugreport_filename() const { return at<10>().as_string(); }
+ bool has_is_started() const { return at<11>().valid(); }
+ bool is_started() const { return at<11>().as_bool(); }
+};
+
+class TracingServiceState_TracingSession : public ::protozero::Message {
+ public:
+ using Decoder = TracingServiceState_TracingSession_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kConsumerUidFieldNumber = 2,
+ kStateFieldNumber = 3,
+ kUniqueSessionNameFieldNumber = 4,
+ kBufferSizeKbFieldNumber = 5,
+ kDurationMsFieldNumber = 6,
+ kNumDataSourcesFieldNumber = 7,
+ kStartRealtimeNsFieldNumber = 8,
+ kBugreportScoreFieldNumber = 9,
+ kBugreportFilenameFieldNumber = 10,
+ kIsStartedFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingServiceState.TracingSession"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ConsumerUid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_ConsumerUid kConsumerUid{};
+ void set_consumer_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ConsumerUid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_State::kFieldId, data, size);
+ }
+ void set_state(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_State::kFieldId, chars.data, chars.size);
+ }
+ void set_state(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UniqueSessionName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_UniqueSessionName kUniqueSessionName{};
+ void set_unique_session_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_UniqueSessionName::kFieldId, data, size);
+ }
+ void set_unique_session_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_UniqueSessionName::kFieldId, chars.data, chars.size);
+ }
+ void set_unique_session_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_UniqueSessionName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BufferSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_BufferSizeKb kBufferSizeKb{};
+ void add_buffer_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DurationMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_DurationMs kDurationMs{};
+ void set_duration_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DurationMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumDataSources =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_NumDataSources kNumDataSources{};
+ void set_num_data_sources(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumDataSources::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartRealtimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_StartRealtimeNs kStartRealtimeNs{};
+ void set_start_realtime_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartRealtimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BugreportScore =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_BugreportScore kBugreportScore{};
+ void set_bugreport_score(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BugreportScore::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BugreportFilename =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_BugreportFilename kBugreportFilename{};
+ void set_bugreport_filename(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_BugreportFilename::kFieldId, data, size);
+ }
+ void set_bugreport_filename(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_BugreportFilename::kFieldId, chars.data, chars.size);
+ }
+ void set_bugreport_filename(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_BugreportFilename::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsStarted =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceState_TracingSession>;
+
+ static constexpr FieldMetadata_IsStarted kIsStarted{};
+ void set_is_started(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsStarted::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TracingServiceState_DataSource_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TracingServiceState_DataSource_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingServiceState_DataSource_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingServiceState_DataSource_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ds_descriptor() const { return at<1>().valid(); }
+ ::protozero::ConstBytes ds_descriptor() const { return at<1>().as_bytes(); }
+ bool has_producer_id() const { return at<2>().valid(); }
+ int32_t producer_id() const { return at<2>().as_int32(); }
+};
+
+class TracingServiceState_DataSource : public ::protozero::Message {
+ public:
+ using Decoder = TracingServiceState_DataSource_Decoder;
+ enum : int32_t {
+ kDsDescriptorFieldNumber = 1,
+ kProducerIdFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingServiceState.DataSource"; }
+
+
+ using FieldMetadata_DsDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DataSourceDescriptor,
+ TracingServiceState_DataSource>;
+
+ static constexpr FieldMetadata_DsDescriptor kDsDescriptor{};
+ template <typename T = DataSourceDescriptor> T* set_ds_descriptor() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ProducerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState_DataSource>;
+
+ static constexpr FieldMetadata_ProducerId kProducerId{};
+ void set_producer_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TracingServiceState_Producer_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TracingServiceState_Producer_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingServiceState_Producer_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingServiceState_Producer_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int32_t id() const { return at<1>().as_int32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_pid() const { return at<5>().valid(); }
+ int32_t pid() const { return at<5>().as_int32(); }
+ bool has_uid() const { return at<3>().valid(); }
+ int32_t uid() const { return at<3>().as_int32(); }
+ bool has_sdk_version() const { return at<4>().valid(); }
+ ::protozero::ConstChars sdk_version() const { return at<4>().as_string(); }
+};
+
+class TracingServiceState_Producer : public ::protozero::Message {
+ public:
+ using Decoder = TracingServiceState_Producer_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kPidFieldNumber = 5,
+ kUidFieldNumber = 3,
+ kSdkVersionFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingServiceState.Producer"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState_Producer>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TracingServiceState_Producer>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState_Producer>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingServiceState_Producer>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SdkVersion =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TracingServiceState_Producer>;
+
+ static constexpr FieldMetadata_SdkVersion kSdkVersion{};
+ void set_sdk_version(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SdkVersion::kFieldId, data, size);
+ }
+ void set_sdk_version(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SdkVersion::kFieldId, chars.data, chars.size);
+ }
+ void set_sdk_version(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SdkVersion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/common/track_event_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACK_EVENT_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_TRACK_EVENT_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class TrackEventCategory;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TrackEventDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TrackEventDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackEventDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackEventDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_available_categories() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> available_categories() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class TrackEventDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = TrackEventDescriptor_Decoder;
+ enum : int32_t {
+ kAvailableCategoriesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackEventDescriptor"; }
+
+
+ using FieldMetadata_AvailableCategories =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackEventCategory,
+ TrackEventDescriptor>;
+
+ static constexpr FieldMetadata_AvailableCategories kAvailableCategories{};
+ template <typename T = TrackEventCategory> T* add_available_categories() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class TrackEventCategory_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TrackEventCategory_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackEventCategory_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackEventCategory_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_description() const { return at<2>().valid(); }
+ ::protozero::ConstChars description() const { return at<2>().as_string(); }
+ bool has_tags() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> tags() const { return GetRepeated<::protozero::ConstChars>(3); }
+};
+
+class TrackEventCategory : public ::protozero::Message {
+ public:
+ using Decoder = TrackEventCategory_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kDescriptionFieldNumber = 2,
+ kTagsFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackEventCategory"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEventCategory>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Description =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEventCategory>;
+
+ static constexpr FieldMetadata_Description kDescription{};
+ void set_description(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Description::kFieldId, data, size);
+ }
+ void set_description(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Description::kFieldId, chars.data, chars.size);
+ }
+ void set_description(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Description::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEventCategory>;
+
+ static constexpr FieldMetadata_Tags kTags{};
+ void add_tags(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Tags::kFieldId, data, size);
+ }
+ void add_tags(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Tags::kFieldId, chars.data, chars.size);
+ }
+ void add_tags(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_game_intervention_list_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_GAME_INTERVENTION_LIST_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_GAME_INTERVENTION_LIST_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidGameInterventionListConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT AndroidGameInterventionListConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPackageNameFilterFieldNumber = 1,
+ };
+
+ AndroidGameInterventionListConfig();
+ ~AndroidGameInterventionListConfig() override;
+ AndroidGameInterventionListConfig(AndroidGameInterventionListConfig&&) noexcept;
+ AndroidGameInterventionListConfig& operator=(AndroidGameInterventionListConfig&&);
+ AndroidGameInterventionListConfig(const AndroidGameInterventionListConfig&);
+ AndroidGameInterventionListConfig& operator=(const AndroidGameInterventionListConfig&);
+ bool operator==(const AndroidGameInterventionListConfig&) const;
+ bool operator!=(const AndroidGameInterventionListConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<std::string>& package_name_filter() const { return package_name_filter_; }
+ std::vector<std::string>* mutable_package_name_filter() { return &package_name_filter_; }
+ int package_name_filter_size() const { return static_cast<int>(package_name_filter_.size()); }
+ void clear_package_name_filter() { package_name_filter_.clear(); }
+ void add_package_name_filter(std::string value) { package_name_filter_.emplace_back(value); }
+ std::string* add_package_name_filter() { package_name_filter_.emplace_back(); return &package_name_filter_.back(); }
+
+ private:
+ std::vector<std::string> package_name_filter_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_GAME_INTERVENTION_LIST_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_input_event_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_INPUT_EVENT_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_INPUT_EVENT_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidInputEventConfig;
+class AndroidInputEventConfig_TraceRule;
+enum AndroidInputEventConfig_TraceMode : int;
+enum AndroidInputEventConfig_TraceLevel : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum AndroidInputEventConfig_TraceMode : int {
+ AndroidInputEventConfig_TraceMode_TRACE_MODE_TRACE_ALL = 0,
+ AndroidInputEventConfig_TraceMode_TRACE_MODE_USE_RULES = 1,
+};
+enum AndroidInputEventConfig_TraceLevel : int {
+ AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_NONE = 0,
+ AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_REDACTED = 1,
+ AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_COMPLETE = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT AndroidInputEventConfig : public ::protozero::CppMessageObj {
+ public:
+ using TraceRule = AndroidInputEventConfig_TraceRule;
+ using TraceMode = AndroidInputEventConfig_TraceMode;
+ static constexpr auto TRACE_MODE_TRACE_ALL = AndroidInputEventConfig_TraceMode_TRACE_MODE_TRACE_ALL;
+ static constexpr auto TRACE_MODE_USE_RULES = AndroidInputEventConfig_TraceMode_TRACE_MODE_USE_RULES;
+ static constexpr auto TraceMode_MIN = AndroidInputEventConfig_TraceMode_TRACE_MODE_TRACE_ALL;
+ static constexpr auto TraceMode_MAX = AndroidInputEventConfig_TraceMode_TRACE_MODE_USE_RULES;
+ using TraceLevel = AndroidInputEventConfig_TraceLevel;
+ static constexpr auto TRACE_LEVEL_NONE = AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_NONE;
+ static constexpr auto TRACE_LEVEL_REDACTED = AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_REDACTED;
+ static constexpr auto TRACE_LEVEL_COMPLETE = AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_COMPLETE;
+ static constexpr auto TraceLevel_MIN = AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_NONE;
+ static constexpr auto TraceLevel_MAX = AndroidInputEventConfig_TraceLevel_TRACE_LEVEL_COMPLETE;
+ enum FieldNumbers {
+ kModeFieldNumber = 1,
+ kRulesFieldNumber = 2,
+ kTraceDispatcherInputEventsFieldNumber = 3,
+ kTraceDispatcherWindowDispatchFieldNumber = 4,
+ };
+
+ AndroidInputEventConfig();
+ ~AndroidInputEventConfig() override;
+ AndroidInputEventConfig(AndroidInputEventConfig&&) noexcept;
+ AndroidInputEventConfig& operator=(AndroidInputEventConfig&&);
+ AndroidInputEventConfig(const AndroidInputEventConfig&);
+ AndroidInputEventConfig& operator=(const AndroidInputEventConfig&);
+ bool operator==(const AndroidInputEventConfig&) const;
+ bool operator!=(const AndroidInputEventConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_mode() const { return _has_field_[1]; }
+ AndroidInputEventConfig_TraceMode mode() const { return mode_; }
+ void set_mode(AndroidInputEventConfig_TraceMode value) { mode_ = value; _has_field_.set(1); }
+
+ const std::vector<AndroidInputEventConfig_TraceRule>& rules() const { return rules_; }
+ std::vector<AndroidInputEventConfig_TraceRule>* mutable_rules() { return &rules_; }
+ int rules_size() const;
+ void clear_rules();
+ AndroidInputEventConfig_TraceRule* add_rules();
+
+ bool has_trace_dispatcher_input_events() const { return _has_field_[3]; }
+ bool trace_dispatcher_input_events() const { return trace_dispatcher_input_events_; }
+ void set_trace_dispatcher_input_events(bool value) { trace_dispatcher_input_events_ = value; _has_field_.set(3); }
+
+ bool has_trace_dispatcher_window_dispatch() const { return _has_field_[4]; }
+ bool trace_dispatcher_window_dispatch() const { return trace_dispatcher_window_dispatch_; }
+ void set_trace_dispatcher_window_dispatch(bool value) { trace_dispatcher_window_dispatch_ = value; _has_field_.set(4); }
+
+ private:
+ AndroidInputEventConfig_TraceMode mode_{};
+ std::vector<AndroidInputEventConfig_TraceRule> rules_;
+ bool trace_dispatcher_input_events_{};
+ bool trace_dispatcher_window_dispatch_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT AndroidInputEventConfig_TraceRule : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTraceLevelFieldNumber = 1,
+ kMatchAllPackagesFieldNumber = 2,
+ kMatchAnyPackagesFieldNumber = 3,
+ kMatchSecureFieldNumber = 4,
+ kMatchImeConnectionActiveFieldNumber = 5,
+ };
+
+ AndroidInputEventConfig_TraceRule();
+ ~AndroidInputEventConfig_TraceRule() override;
+ AndroidInputEventConfig_TraceRule(AndroidInputEventConfig_TraceRule&&) noexcept;
+ AndroidInputEventConfig_TraceRule& operator=(AndroidInputEventConfig_TraceRule&&);
+ AndroidInputEventConfig_TraceRule(const AndroidInputEventConfig_TraceRule&);
+ AndroidInputEventConfig_TraceRule& operator=(const AndroidInputEventConfig_TraceRule&);
+ bool operator==(const AndroidInputEventConfig_TraceRule&) const;
+ bool operator!=(const AndroidInputEventConfig_TraceRule& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_level() const { return _has_field_[1]; }
+ AndroidInputEventConfig_TraceLevel trace_level() const { return trace_level_; }
+ void set_trace_level(AndroidInputEventConfig_TraceLevel value) { trace_level_ = value; _has_field_.set(1); }
+
+ const std::vector<std::string>& match_all_packages() const { return match_all_packages_; }
+ std::vector<std::string>* mutable_match_all_packages() { return &match_all_packages_; }
+ int match_all_packages_size() const { return static_cast<int>(match_all_packages_.size()); }
+ void clear_match_all_packages() { match_all_packages_.clear(); }
+ void add_match_all_packages(std::string value) { match_all_packages_.emplace_back(value); }
+ std::string* add_match_all_packages() { match_all_packages_.emplace_back(); return &match_all_packages_.back(); }
+
+ const std::vector<std::string>& match_any_packages() const { return match_any_packages_; }
+ std::vector<std::string>* mutable_match_any_packages() { return &match_any_packages_; }
+ int match_any_packages_size() const { return static_cast<int>(match_any_packages_.size()); }
+ void clear_match_any_packages() { match_any_packages_.clear(); }
+ void add_match_any_packages(std::string value) { match_any_packages_.emplace_back(value); }
+ std::string* add_match_any_packages() { match_any_packages_.emplace_back(); return &match_any_packages_.back(); }
+
+ bool has_match_secure() const { return _has_field_[4]; }
+ bool match_secure() const { return match_secure_; }
+ void set_match_secure(bool value) { match_secure_ = value; _has_field_.set(4); }
+
+ bool has_match_ime_connection_active() const { return _has_field_[5]; }
+ bool match_ime_connection_active() const { return match_ime_connection_active_; }
+ void set_match_ime_connection_active(bool value) { match_ime_connection_active_ = value; _has_field_.set(5); }
+
+ private:
+ AndroidInputEventConfig_TraceLevel trace_level_{};
+ std::vector<std::string> match_all_packages_;
+ std::vector<std::string> match_any_packages_;
+ bool match_secure_{};
+ bool match_ime_connection_active_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_INPUT_EVENT_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_log_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_LOG_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_LOG_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidLogConfig;
+enum AndroidLogId : int;
+enum AndroidLogPriority : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT AndroidLogConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kLogIdsFieldNumber = 1,
+ kMinPrioFieldNumber = 3,
+ kFilterTagsFieldNumber = 4,
+ };
+
+ AndroidLogConfig();
+ ~AndroidLogConfig() override;
+ AndroidLogConfig(AndroidLogConfig&&) noexcept;
+ AndroidLogConfig& operator=(AndroidLogConfig&&);
+ AndroidLogConfig(const AndroidLogConfig&);
+ AndroidLogConfig& operator=(const AndroidLogConfig&);
+ bool operator==(const AndroidLogConfig&) const;
+ bool operator!=(const AndroidLogConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<AndroidLogId>& log_ids() const { return log_ids_; }
+ std::vector<AndroidLogId>* mutable_log_ids() { return &log_ids_; }
+ int log_ids_size() const { return static_cast<int>(log_ids_.size()); }
+ void clear_log_ids() { log_ids_.clear(); }
+ void add_log_ids(AndroidLogId value) { log_ids_.emplace_back(value); }
+ AndroidLogId* add_log_ids() { log_ids_.emplace_back(); return &log_ids_.back(); }
+
+ bool has_min_prio() const { return _has_field_[3]; }
+ AndroidLogPriority min_prio() const { return min_prio_; }
+ void set_min_prio(AndroidLogPriority value) { min_prio_ = value; _has_field_.set(3); }
+
+ const std::vector<std::string>& filter_tags() const { return filter_tags_; }
+ std::vector<std::string>* mutable_filter_tags() { return &filter_tags_; }
+ int filter_tags_size() const { return static_cast<int>(filter_tags_.size()); }
+ void clear_filter_tags() { filter_tags_.clear(); }
+ void add_filter_tags(std::string value) { filter_tags_.emplace_back(value); }
+ std::string* add_filter_tags() { filter_tags_.emplace_back(); return &filter_tags_.back(); }
+
+ private:
+ std::vector<AndroidLogId> log_ids_;
+ AndroidLogPriority min_prio_{};
+ std::vector<std::string> filter_tags_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_LOG_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_polled_state_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_POLLED_STATE_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_POLLED_STATE_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidPolledStateConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT AndroidPolledStateConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPollMsFieldNumber = 1,
+ };
+
+ AndroidPolledStateConfig();
+ ~AndroidPolledStateConfig() override;
+ AndroidPolledStateConfig(AndroidPolledStateConfig&&) noexcept;
+ AndroidPolledStateConfig& operator=(AndroidPolledStateConfig&&);
+ AndroidPolledStateConfig(const AndroidPolledStateConfig&);
+ AndroidPolledStateConfig& operator=(const AndroidPolledStateConfig&);
+ bool operator==(const AndroidPolledStateConfig&) const;
+ bool operator!=(const AndroidPolledStateConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_poll_ms() const { return _has_field_[1]; }
+ uint32_t poll_ms() const { return poll_ms_; }
+ void set_poll_ms(uint32_t value) { poll_ms_ = value; _has_field_.set(1); }
+
+ private:
+ uint32_t poll_ms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_POLLED_STATE_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SDK_SYSPROP_GUARD_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SDK_SYSPROP_GUARD_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidSdkSyspropGuardConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT AndroidSdkSyspropGuardConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSurfaceflingerSkiaTrackEventsFieldNumber = 1,
+ kHwuiSkiaTrackEventsFieldNumber = 2,
+ kHwuiPackageNameFilterFieldNumber = 3,
+ };
+
+ AndroidSdkSyspropGuardConfig();
+ ~AndroidSdkSyspropGuardConfig() override;
+ AndroidSdkSyspropGuardConfig(AndroidSdkSyspropGuardConfig&&) noexcept;
+ AndroidSdkSyspropGuardConfig& operator=(AndroidSdkSyspropGuardConfig&&);
+ AndroidSdkSyspropGuardConfig(const AndroidSdkSyspropGuardConfig&);
+ AndroidSdkSyspropGuardConfig& operator=(const AndroidSdkSyspropGuardConfig&);
+ bool operator==(const AndroidSdkSyspropGuardConfig&) const;
+ bool operator!=(const AndroidSdkSyspropGuardConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_surfaceflinger_skia_track_events() const { return _has_field_[1]; }
+ bool surfaceflinger_skia_track_events() const { return surfaceflinger_skia_track_events_; }
+ void set_surfaceflinger_skia_track_events(bool value) { surfaceflinger_skia_track_events_ = value; _has_field_.set(1); }
+
+ bool has_hwui_skia_track_events() const { return _has_field_[2]; }
+ bool hwui_skia_track_events() const { return hwui_skia_track_events_; }
+ void set_hwui_skia_track_events(bool value) { hwui_skia_track_events_ = value; _has_field_.set(2); }
+
+ const std::vector<std::string>& hwui_package_name_filter() const { return hwui_package_name_filter_; }
+ std::vector<std::string>* mutable_hwui_package_name_filter() { return &hwui_package_name_filter_; }
+ int hwui_package_name_filter_size() const { return static_cast<int>(hwui_package_name_filter_.size()); }
+ void clear_hwui_package_name_filter() { hwui_package_name_filter_.clear(); }
+ void add_hwui_package_name_filter(std::string value) { hwui_package_name_filter_.emplace_back(value); }
+ std::string* add_hwui_package_name_filter() { hwui_package_name_filter_.emplace_back(); return &hwui_package_name_filter_.back(); }
+
+ private:
+ bool surfaceflinger_skia_track_events_{};
+ bool hwui_skia_track_events_{};
+ std::vector<std::string> hwui_package_name_filter_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SDK_SYSPROP_GUARD_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_system_property_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SYSTEM_PROPERTY_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SYSTEM_PROPERTY_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidSystemPropertyConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT AndroidSystemPropertyConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPollMsFieldNumber = 1,
+ kPropertyNameFieldNumber = 2,
+ };
+
+ AndroidSystemPropertyConfig();
+ ~AndroidSystemPropertyConfig() override;
+ AndroidSystemPropertyConfig(AndroidSystemPropertyConfig&&) noexcept;
+ AndroidSystemPropertyConfig& operator=(AndroidSystemPropertyConfig&&);
+ AndroidSystemPropertyConfig(const AndroidSystemPropertyConfig&);
+ AndroidSystemPropertyConfig& operator=(const AndroidSystemPropertyConfig&);
+ bool operator==(const AndroidSystemPropertyConfig&) const;
+ bool operator!=(const AndroidSystemPropertyConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_poll_ms() const { return _has_field_[1]; }
+ uint32_t poll_ms() const { return poll_ms_; }
+ void set_poll_ms(uint32_t value) { poll_ms_ = value; _has_field_.set(1); }
+
+ const std::vector<std::string>& property_name() const { return property_name_; }
+ std::vector<std::string>* mutable_property_name() { return &property_name_; }
+ int property_name_size() const { return static_cast<int>(property_name_.size()); }
+ void clear_property_name() { property_name_.clear(); }
+ void add_property_name(std::string value) { property_name_.emplace_back(value); }
+ std::string* add_property_name() { property_name_.emplace_back(); return &property_name_.back(); }
+
+ private:
+ uint32_t poll_ms_{};
+ std::vector<std::string> property_name_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SYSTEM_PROPERTY_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/network_trace_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_NETWORK_TRACE_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_NETWORK_TRACE_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class NetworkPacketTraceConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT NetworkPacketTraceConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPollMsFieldNumber = 1,
+ kAggregationThresholdFieldNumber = 2,
+ kInternLimitFieldNumber = 3,
+ kDropLocalPortFieldNumber = 4,
+ kDropRemotePortFieldNumber = 5,
+ kDropTcpFlagsFieldNumber = 6,
+ };
+
+ NetworkPacketTraceConfig();
+ ~NetworkPacketTraceConfig() override;
+ NetworkPacketTraceConfig(NetworkPacketTraceConfig&&) noexcept;
+ NetworkPacketTraceConfig& operator=(NetworkPacketTraceConfig&&);
+ NetworkPacketTraceConfig(const NetworkPacketTraceConfig&);
+ NetworkPacketTraceConfig& operator=(const NetworkPacketTraceConfig&);
+ bool operator==(const NetworkPacketTraceConfig&) const;
+ bool operator!=(const NetworkPacketTraceConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_poll_ms() const { return _has_field_[1]; }
+ uint32_t poll_ms() const { return poll_ms_; }
+ void set_poll_ms(uint32_t value) { poll_ms_ = value; _has_field_.set(1); }
+
+ bool has_aggregation_threshold() const { return _has_field_[2]; }
+ uint32_t aggregation_threshold() const { return aggregation_threshold_; }
+ void set_aggregation_threshold(uint32_t value) { aggregation_threshold_ = value; _has_field_.set(2); }
+
+ bool has_intern_limit() const { return _has_field_[3]; }
+ uint32_t intern_limit() const { return intern_limit_; }
+ void set_intern_limit(uint32_t value) { intern_limit_ = value; _has_field_.set(3); }
+
+ bool has_drop_local_port() const { return _has_field_[4]; }
+ bool drop_local_port() const { return drop_local_port_; }
+ void set_drop_local_port(bool value) { drop_local_port_ = value; _has_field_.set(4); }
+
+ bool has_drop_remote_port() const { return _has_field_[5]; }
+ bool drop_remote_port() const { return drop_remote_port_; }
+ void set_drop_remote_port(bool value) { drop_remote_port_ = value; _has_field_.set(5); }
+
+ bool has_drop_tcp_flags() const { return _has_field_[6]; }
+ bool drop_tcp_flags() const { return drop_tcp_flags_; }
+ void set_drop_tcp_flags(bool value) { drop_tcp_flags_ = value; _has_field_.set(6); }
+
+ private:
+ uint32_t poll_ms_{};
+ uint32_t aggregation_threshold_{};
+ uint32_t intern_limit_{};
+ bool drop_local_port_{};
+ bool drop_remote_port_{};
+ bool drop_tcp_flags_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_NETWORK_TRACE_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/packages_list_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PACKAGES_LIST_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PACKAGES_LIST_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class PackagesListConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT PackagesListConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPackageNameFilterFieldNumber = 1,
+ };
+
+ PackagesListConfig();
+ ~PackagesListConfig() override;
+ PackagesListConfig(PackagesListConfig&&) noexcept;
+ PackagesListConfig& operator=(PackagesListConfig&&);
+ PackagesListConfig(const PackagesListConfig&);
+ PackagesListConfig& operator=(const PackagesListConfig&);
+ bool operator==(const PackagesListConfig&) const;
+ bool operator!=(const PackagesListConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<std::string>& package_name_filter() const { return package_name_filter_; }
+ std::vector<std::string>* mutable_package_name_filter() { return &package_name_filter_; }
+ int package_name_filter_size() const { return static_cast<int>(package_name_filter_.size()); }
+ void clear_package_name_filter() { package_name_filter_.clear(); }
+ void add_package_name_filter(std::string value) { package_name_filter_.emplace_back(value); }
+ std::string* add_package_name_filter() { package_name_filter_.emplace_back(); return &package_name_filter_.back(); }
+
+ private:
+ std::vector<std::string> package_name_filter_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PACKAGES_LIST_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/protolog_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PROTOLOG_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PROTOLOG_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ProtoLogGroup;
+class ProtoLogConfig;
+enum ProtoLogLevel : int;
+enum ProtoLogConfig_TracingMode : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ProtoLogConfig_TracingMode : int {
+ ProtoLogConfig_TracingMode_DEFAULT = 0,
+ ProtoLogConfig_TracingMode_ENABLE_ALL = 1,
+};
+
+class PERFETTO_EXPORT_COMPONENT ProtoLogGroup : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kGroupNameFieldNumber = 1,
+ kLogFromFieldNumber = 2,
+ kCollectStacktraceFieldNumber = 3,
+ };
+
+ ProtoLogGroup();
+ ~ProtoLogGroup() override;
+ ProtoLogGroup(ProtoLogGroup&&) noexcept;
+ ProtoLogGroup& operator=(ProtoLogGroup&&);
+ ProtoLogGroup(const ProtoLogGroup&);
+ ProtoLogGroup& operator=(const ProtoLogGroup&);
+ bool operator==(const ProtoLogGroup&) const;
+ bool operator!=(const ProtoLogGroup& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_group_name() const { return _has_field_[1]; }
+ const std::string& group_name() const { return group_name_; }
+ void set_group_name(const std::string& value) { group_name_ = value; _has_field_.set(1); }
+
+ bool has_log_from() const { return _has_field_[2]; }
+ ProtoLogLevel log_from() const { return log_from_; }
+ void set_log_from(ProtoLogLevel value) { log_from_ = value; _has_field_.set(2); }
+
+ bool has_collect_stacktrace() const { return _has_field_[3]; }
+ bool collect_stacktrace() const { return collect_stacktrace_; }
+ void set_collect_stacktrace(bool value) { collect_stacktrace_ = value; _has_field_.set(3); }
+
+ private:
+ std::string group_name_{};
+ ProtoLogLevel log_from_{};
+ bool collect_stacktrace_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ProtoLogConfig : public ::protozero::CppMessageObj {
+ public:
+ using TracingMode = ProtoLogConfig_TracingMode;
+ static constexpr auto DEFAULT = ProtoLogConfig_TracingMode_DEFAULT;
+ static constexpr auto ENABLE_ALL = ProtoLogConfig_TracingMode_ENABLE_ALL;
+ static constexpr auto TracingMode_MIN = ProtoLogConfig_TracingMode_DEFAULT;
+ static constexpr auto TracingMode_MAX = ProtoLogConfig_TracingMode_ENABLE_ALL;
+ enum FieldNumbers {
+ kGroupOverridesFieldNumber = 1,
+ kTracingModeFieldNumber = 2,
+ };
+
+ ProtoLogConfig();
+ ~ProtoLogConfig() override;
+ ProtoLogConfig(ProtoLogConfig&&) noexcept;
+ ProtoLogConfig& operator=(ProtoLogConfig&&);
+ ProtoLogConfig(const ProtoLogConfig&);
+ ProtoLogConfig& operator=(const ProtoLogConfig&);
+ bool operator==(const ProtoLogConfig&) const;
+ bool operator!=(const ProtoLogConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<ProtoLogGroup>& group_overrides() const { return group_overrides_; }
+ std::vector<ProtoLogGroup>* mutable_group_overrides() { return &group_overrides_; }
+ int group_overrides_size() const;
+ void clear_group_overrides();
+ ProtoLogGroup* add_group_overrides();
+
+ bool has_tracing_mode() const { return _has_field_[2]; }
+ ProtoLogConfig_TracingMode tracing_mode() const { return tracing_mode_; }
+ void set_tracing_mode(ProtoLogConfig_TracingMode value) { tracing_mode_ = value; _has_field_.set(2); }
+
+ private:
+ std::vector<ProtoLogGroup> group_overrides_;
+ ProtoLogConfig_TracingMode tracing_mode_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PROTOLOG_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/surfaceflinger_layers_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_LAYERS_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_LAYERS_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class SurfaceFlingerLayersConfig;
+enum SurfaceFlingerLayersConfig_Mode : int;
+enum SurfaceFlingerLayersConfig_TraceFlag : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum SurfaceFlingerLayersConfig_Mode : int {
+ SurfaceFlingerLayersConfig_Mode_MODE_UNSPECIFIED = 0,
+ SurfaceFlingerLayersConfig_Mode_MODE_ACTIVE = 1,
+ SurfaceFlingerLayersConfig_Mode_MODE_GENERATED = 2,
+ SurfaceFlingerLayersConfig_Mode_MODE_DUMP = 3,
+ SurfaceFlingerLayersConfig_Mode_MODE_GENERATED_BUGREPORT_ONLY = 4,
+};
+enum SurfaceFlingerLayersConfig_TraceFlag : int {
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_UNSPECIFIED = 0,
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_INPUT = 2,
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_COMPOSITION = 4,
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_EXTRA = 8,
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_HWC = 16,
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_BUFFERS = 32,
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_VIRTUAL_DISPLAYS = 64,
+ SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_ALL = 14,
+};
+
+class PERFETTO_EXPORT_COMPONENT SurfaceFlingerLayersConfig : public ::protozero::CppMessageObj {
+ public:
+ using Mode = SurfaceFlingerLayersConfig_Mode;
+ static constexpr auto MODE_UNSPECIFIED = SurfaceFlingerLayersConfig_Mode_MODE_UNSPECIFIED;
+ static constexpr auto MODE_ACTIVE = SurfaceFlingerLayersConfig_Mode_MODE_ACTIVE;
+ static constexpr auto MODE_GENERATED = SurfaceFlingerLayersConfig_Mode_MODE_GENERATED;
+ static constexpr auto MODE_DUMP = SurfaceFlingerLayersConfig_Mode_MODE_DUMP;
+ static constexpr auto MODE_GENERATED_BUGREPORT_ONLY = SurfaceFlingerLayersConfig_Mode_MODE_GENERATED_BUGREPORT_ONLY;
+ static constexpr auto Mode_MIN = SurfaceFlingerLayersConfig_Mode_MODE_UNSPECIFIED;
+ static constexpr auto Mode_MAX = SurfaceFlingerLayersConfig_Mode_MODE_GENERATED_BUGREPORT_ONLY;
+ using TraceFlag = SurfaceFlingerLayersConfig_TraceFlag;
+ static constexpr auto TRACE_FLAG_UNSPECIFIED = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_UNSPECIFIED;
+ static constexpr auto TRACE_FLAG_INPUT = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_INPUT;
+ static constexpr auto TRACE_FLAG_COMPOSITION = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_COMPOSITION;
+ static constexpr auto TRACE_FLAG_EXTRA = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_EXTRA;
+ static constexpr auto TRACE_FLAG_HWC = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_HWC;
+ static constexpr auto TRACE_FLAG_BUFFERS = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_BUFFERS;
+ static constexpr auto TRACE_FLAG_VIRTUAL_DISPLAYS = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_VIRTUAL_DISPLAYS;
+ static constexpr auto TRACE_FLAG_ALL = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_ALL;
+ static constexpr auto TraceFlag_MIN = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_UNSPECIFIED;
+ static constexpr auto TraceFlag_MAX = SurfaceFlingerLayersConfig_TraceFlag_TRACE_FLAG_VIRTUAL_DISPLAYS;
+ enum FieldNumbers {
+ kModeFieldNumber = 1,
+ kTraceFlagsFieldNumber = 2,
+ };
+
+ SurfaceFlingerLayersConfig();
+ ~SurfaceFlingerLayersConfig() override;
+ SurfaceFlingerLayersConfig(SurfaceFlingerLayersConfig&&) noexcept;
+ SurfaceFlingerLayersConfig& operator=(SurfaceFlingerLayersConfig&&);
+ SurfaceFlingerLayersConfig(const SurfaceFlingerLayersConfig&);
+ SurfaceFlingerLayersConfig& operator=(const SurfaceFlingerLayersConfig&);
+ bool operator==(const SurfaceFlingerLayersConfig&) const;
+ bool operator!=(const SurfaceFlingerLayersConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_mode() const { return _has_field_[1]; }
+ SurfaceFlingerLayersConfig_Mode mode() const { return mode_; }
+ void set_mode(SurfaceFlingerLayersConfig_Mode value) { mode_ = value; _has_field_.set(1); }
+
+ const std::vector<SurfaceFlingerLayersConfig_TraceFlag>& trace_flags() const { return trace_flags_; }
+ std::vector<SurfaceFlingerLayersConfig_TraceFlag>* mutable_trace_flags() { return &trace_flags_; }
+ int trace_flags_size() const { return static_cast<int>(trace_flags_.size()); }
+ void clear_trace_flags() { trace_flags_.clear(); }
+ void add_trace_flags(SurfaceFlingerLayersConfig_TraceFlag value) { trace_flags_.emplace_back(value); }
+ SurfaceFlingerLayersConfig_TraceFlag* add_trace_flags() { trace_flags_.emplace_back(); return &trace_flags_.back(); }
+
+ private:
+ SurfaceFlingerLayersConfig_Mode mode_{};
+ std::vector<SurfaceFlingerLayersConfig_TraceFlag> trace_flags_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_LAYERS_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_TRANSACTIONS_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_TRANSACTIONS_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class SurfaceFlingerTransactionsConfig;
+enum SurfaceFlingerTransactionsConfig_Mode : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum SurfaceFlingerTransactionsConfig_Mode : int {
+ SurfaceFlingerTransactionsConfig_Mode_MODE_UNSPECIFIED = 0,
+ SurfaceFlingerTransactionsConfig_Mode_MODE_CONTINUOUS = 1,
+ SurfaceFlingerTransactionsConfig_Mode_MODE_ACTIVE = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT SurfaceFlingerTransactionsConfig : public ::protozero::CppMessageObj {
+ public:
+ using Mode = SurfaceFlingerTransactionsConfig_Mode;
+ static constexpr auto MODE_UNSPECIFIED = SurfaceFlingerTransactionsConfig_Mode_MODE_UNSPECIFIED;
+ static constexpr auto MODE_CONTINUOUS = SurfaceFlingerTransactionsConfig_Mode_MODE_CONTINUOUS;
+ static constexpr auto MODE_ACTIVE = SurfaceFlingerTransactionsConfig_Mode_MODE_ACTIVE;
+ static constexpr auto Mode_MIN = SurfaceFlingerTransactionsConfig_Mode_MODE_UNSPECIFIED;
+ static constexpr auto Mode_MAX = SurfaceFlingerTransactionsConfig_Mode_MODE_ACTIVE;
+ enum FieldNumbers {
+ kModeFieldNumber = 1,
+ };
+
+ SurfaceFlingerTransactionsConfig();
+ ~SurfaceFlingerTransactionsConfig() override;
+ SurfaceFlingerTransactionsConfig(SurfaceFlingerTransactionsConfig&&) noexcept;
+ SurfaceFlingerTransactionsConfig& operator=(SurfaceFlingerTransactionsConfig&&);
+ SurfaceFlingerTransactionsConfig(const SurfaceFlingerTransactionsConfig&);
+ SurfaceFlingerTransactionsConfig& operator=(const SurfaceFlingerTransactionsConfig&);
+ bool operator==(const SurfaceFlingerTransactionsConfig&) const;
+ bool operator!=(const SurfaceFlingerTransactionsConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_mode() const { return _has_field_[1]; }
+ SurfaceFlingerTransactionsConfig_Mode mode() const { return mode_; }
+ void set_mode(SurfaceFlingerTransactionsConfig_Mode value) { mode_ = value; _has_field_.set(1); }
+
+ private:
+ SurfaceFlingerTransactionsConfig_Mode mode_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_TRANSACTIONS_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/ftrace/ftrace_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_FTRACE_FTRACE_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_FTRACE_FTRACE_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class FtraceConfig;
+class FtraceConfig_PrintFilter;
+class FtraceConfig_PrintFilter_Rule;
+class FtraceConfig_PrintFilter_Rule_AtraceMessage;
+class FtraceConfig_CompactSchedConfig;
+enum FtraceConfig_KsymsMemPolicy : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum FtraceConfig_KsymsMemPolicy : int {
+ FtraceConfig_KsymsMemPolicy_KSYMS_UNSPECIFIED = 0,
+ FtraceConfig_KsymsMemPolicy_KSYMS_CLEANUP_ON_STOP = 1,
+ FtraceConfig_KsymsMemPolicy_KSYMS_RETAIN = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT FtraceConfig : public ::protozero::CppMessageObj {
+ public:
+ using CompactSchedConfig = FtraceConfig_CompactSchedConfig;
+ using PrintFilter = FtraceConfig_PrintFilter;
+ using KsymsMemPolicy = FtraceConfig_KsymsMemPolicy;
+ static constexpr auto KSYMS_UNSPECIFIED = FtraceConfig_KsymsMemPolicy_KSYMS_UNSPECIFIED;
+ static constexpr auto KSYMS_CLEANUP_ON_STOP = FtraceConfig_KsymsMemPolicy_KSYMS_CLEANUP_ON_STOP;
+ static constexpr auto KSYMS_RETAIN = FtraceConfig_KsymsMemPolicy_KSYMS_RETAIN;
+ static constexpr auto KsymsMemPolicy_MIN = FtraceConfig_KsymsMemPolicy_KSYMS_UNSPECIFIED;
+ static constexpr auto KsymsMemPolicy_MAX = FtraceConfig_KsymsMemPolicy_KSYMS_RETAIN;
+ enum FieldNumbers {
+ kFtraceEventsFieldNumber = 1,
+ kAtraceCategoriesFieldNumber = 2,
+ kAtraceAppsFieldNumber = 3,
+ kBufferSizeKbFieldNumber = 10,
+ kDrainPeriodMsFieldNumber = 11,
+ kDrainBufferPercentFieldNumber = 26,
+ kCompactSchedFieldNumber = 12,
+ kPrintFilterFieldNumber = 22,
+ kSymbolizeKsymsFieldNumber = 13,
+ kKsymsMemPolicyFieldNumber = 17,
+ kInitializeKsymsSynchronouslyForTestingFieldNumber = 14,
+ kThrottleRssStatFieldNumber = 15,
+ kDisableGenericEventsFieldNumber = 16,
+ kSyscallEventsFieldNumber = 18,
+ kEnableFunctionGraphFieldNumber = 19,
+ kFunctionFiltersFieldNumber = 20,
+ kFunctionGraphRootsFieldNumber = 21,
+ kPreserveFtraceBufferFieldNumber = 23,
+ kUseMonotonicRawClockFieldNumber = 24,
+ kInstanceNameFieldNumber = 25,
+ kBufferSizeLowerBoundFieldNumber = 27,
+ };
+
+ FtraceConfig();
+ ~FtraceConfig() override;
+ FtraceConfig(FtraceConfig&&) noexcept;
+ FtraceConfig& operator=(FtraceConfig&&);
+ FtraceConfig(const FtraceConfig&);
+ FtraceConfig& operator=(const FtraceConfig&);
+ bool operator==(const FtraceConfig&) const;
+ bool operator!=(const FtraceConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<std::string>& ftrace_events() const { return ftrace_events_; }
+ std::vector<std::string>* mutable_ftrace_events() { return &ftrace_events_; }
+ int ftrace_events_size() const { return static_cast<int>(ftrace_events_.size()); }
+ void clear_ftrace_events() { ftrace_events_.clear(); }
+ void add_ftrace_events(std::string value) { ftrace_events_.emplace_back(value); }
+ std::string* add_ftrace_events() { ftrace_events_.emplace_back(); return &ftrace_events_.back(); }
+
+ const std::vector<std::string>& atrace_categories() const { return atrace_categories_; }
+ std::vector<std::string>* mutable_atrace_categories() { return &atrace_categories_; }
+ int atrace_categories_size() const { return static_cast<int>(atrace_categories_.size()); }
+ void clear_atrace_categories() { atrace_categories_.clear(); }
+ void add_atrace_categories(std::string value) { atrace_categories_.emplace_back(value); }
+ std::string* add_atrace_categories() { atrace_categories_.emplace_back(); return &atrace_categories_.back(); }
+
+ const std::vector<std::string>& atrace_apps() const { return atrace_apps_; }
+ std::vector<std::string>* mutable_atrace_apps() { return &atrace_apps_; }
+ int atrace_apps_size() const { return static_cast<int>(atrace_apps_.size()); }
+ void clear_atrace_apps() { atrace_apps_.clear(); }
+ void add_atrace_apps(std::string value) { atrace_apps_.emplace_back(value); }
+ std::string* add_atrace_apps() { atrace_apps_.emplace_back(); return &atrace_apps_.back(); }
+
+ bool has_buffer_size_kb() const { return _has_field_[10]; }
+ uint32_t buffer_size_kb() const { return buffer_size_kb_; }
+ void set_buffer_size_kb(uint32_t value) { buffer_size_kb_ = value; _has_field_.set(10); }
+
+ bool has_drain_period_ms() const { return _has_field_[11]; }
+ uint32_t drain_period_ms() const { return drain_period_ms_; }
+ void set_drain_period_ms(uint32_t value) { drain_period_ms_ = value; _has_field_.set(11); }
+
+ bool has_drain_buffer_percent() const { return _has_field_[26]; }
+ uint32_t drain_buffer_percent() const { return drain_buffer_percent_; }
+ void set_drain_buffer_percent(uint32_t value) { drain_buffer_percent_ = value; _has_field_.set(26); }
+
+ bool has_compact_sched() const { return _has_field_[12]; }
+ const FtraceConfig_CompactSchedConfig& compact_sched() const { return *compact_sched_; }
+ FtraceConfig_CompactSchedConfig* mutable_compact_sched() { _has_field_.set(12); return compact_sched_.get(); }
+
+ bool has_print_filter() const { return _has_field_[22]; }
+ const FtraceConfig_PrintFilter& print_filter() const { return *print_filter_; }
+ FtraceConfig_PrintFilter* mutable_print_filter() { _has_field_.set(22); return print_filter_.get(); }
+
+ bool has_symbolize_ksyms() const { return _has_field_[13]; }
+ bool symbolize_ksyms() const { return symbolize_ksyms_; }
+ void set_symbolize_ksyms(bool value) { symbolize_ksyms_ = value; _has_field_.set(13); }
+
+ bool has_ksyms_mem_policy() const { return _has_field_[17]; }
+ FtraceConfig_KsymsMemPolicy ksyms_mem_policy() const { return ksyms_mem_policy_; }
+ void set_ksyms_mem_policy(FtraceConfig_KsymsMemPolicy value) { ksyms_mem_policy_ = value; _has_field_.set(17); }
+
+ bool has_initialize_ksyms_synchronously_for_testing() const { return _has_field_[14]; }
+ bool initialize_ksyms_synchronously_for_testing() const { return initialize_ksyms_synchronously_for_testing_; }
+ void set_initialize_ksyms_synchronously_for_testing(bool value) { initialize_ksyms_synchronously_for_testing_ = value; _has_field_.set(14); }
+
+ bool has_throttle_rss_stat() const { return _has_field_[15]; }
+ bool throttle_rss_stat() const { return throttle_rss_stat_; }
+ void set_throttle_rss_stat(bool value) { throttle_rss_stat_ = value; _has_field_.set(15); }
+
+ bool has_disable_generic_events() const { return _has_field_[16]; }
+ bool disable_generic_events() const { return disable_generic_events_; }
+ void set_disable_generic_events(bool value) { disable_generic_events_ = value; _has_field_.set(16); }
+
+ const std::vector<std::string>& syscall_events() const { return syscall_events_; }
+ std::vector<std::string>* mutable_syscall_events() { return &syscall_events_; }
+ int syscall_events_size() const { return static_cast<int>(syscall_events_.size()); }
+ void clear_syscall_events() { syscall_events_.clear(); }
+ void add_syscall_events(std::string value) { syscall_events_.emplace_back(value); }
+ std::string* add_syscall_events() { syscall_events_.emplace_back(); return &syscall_events_.back(); }
+
+ bool has_enable_function_graph() const { return _has_field_[19]; }
+ bool enable_function_graph() const { return enable_function_graph_; }
+ void set_enable_function_graph(bool value) { enable_function_graph_ = value; _has_field_.set(19); }
+
+ const std::vector<std::string>& function_filters() const { return function_filters_; }
+ std::vector<std::string>* mutable_function_filters() { return &function_filters_; }
+ int function_filters_size() const { return static_cast<int>(function_filters_.size()); }
+ void clear_function_filters() { function_filters_.clear(); }
+ void add_function_filters(std::string value) { function_filters_.emplace_back(value); }
+ std::string* add_function_filters() { function_filters_.emplace_back(); return &function_filters_.back(); }
+
+ const std::vector<std::string>& function_graph_roots() const { return function_graph_roots_; }
+ std::vector<std::string>* mutable_function_graph_roots() { return &function_graph_roots_; }
+ int function_graph_roots_size() const { return static_cast<int>(function_graph_roots_.size()); }
+ void clear_function_graph_roots() { function_graph_roots_.clear(); }
+ void add_function_graph_roots(std::string value) { function_graph_roots_.emplace_back(value); }
+ std::string* add_function_graph_roots() { function_graph_roots_.emplace_back(); return &function_graph_roots_.back(); }
+
+ bool has_preserve_ftrace_buffer() const { return _has_field_[23]; }
+ bool preserve_ftrace_buffer() const { return preserve_ftrace_buffer_; }
+ void set_preserve_ftrace_buffer(bool value) { preserve_ftrace_buffer_ = value; _has_field_.set(23); }
+
+ bool has_use_monotonic_raw_clock() const { return _has_field_[24]; }
+ bool use_monotonic_raw_clock() const { return use_monotonic_raw_clock_; }
+ void set_use_monotonic_raw_clock(bool value) { use_monotonic_raw_clock_ = value; _has_field_.set(24); }
+
+ bool has_instance_name() const { return _has_field_[25]; }
+ const std::string& instance_name() const { return instance_name_; }
+ void set_instance_name(const std::string& value) { instance_name_ = value; _has_field_.set(25); }
+
+ bool has_buffer_size_lower_bound() const { return _has_field_[27]; }
+ bool buffer_size_lower_bound() const { return buffer_size_lower_bound_; }
+ void set_buffer_size_lower_bound(bool value) { buffer_size_lower_bound_ = value; _has_field_.set(27); }
+
+ private:
+ std::vector<std::string> ftrace_events_;
+ std::vector<std::string> atrace_categories_;
+ std::vector<std::string> atrace_apps_;
+ uint32_t buffer_size_kb_{};
+ uint32_t drain_period_ms_{};
+ uint32_t drain_buffer_percent_{};
+ ::protozero::CopyablePtr<FtraceConfig_CompactSchedConfig> compact_sched_;
+ ::protozero::CopyablePtr<FtraceConfig_PrintFilter> print_filter_;
+ bool symbolize_ksyms_{};
+ FtraceConfig_KsymsMemPolicy ksyms_mem_policy_{};
+ bool initialize_ksyms_synchronously_for_testing_{};
+ bool throttle_rss_stat_{};
+ bool disable_generic_events_{};
+ std::vector<std::string> syscall_events_;
+ bool enable_function_graph_{};
+ std::vector<std::string> function_filters_;
+ std::vector<std::string> function_graph_roots_;
+ bool preserve_ftrace_buffer_{};
+ bool use_monotonic_raw_clock_{};
+ std::string instance_name_{};
+ bool buffer_size_lower_bound_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<28> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FtraceConfig_PrintFilter : public ::protozero::CppMessageObj {
+ public:
+ using Rule = FtraceConfig_PrintFilter_Rule;
+ enum FieldNumbers {
+ kRulesFieldNumber = 1,
+ };
+
+ FtraceConfig_PrintFilter();
+ ~FtraceConfig_PrintFilter() override;
+ FtraceConfig_PrintFilter(FtraceConfig_PrintFilter&&) noexcept;
+ FtraceConfig_PrintFilter& operator=(FtraceConfig_PrintFilter&&);
+ FtraceConfig_PrintFilter(const FtraceConfig_PrintFilter&);
+ FtraceConfig_PrintFilter& operator=(const FtraceConfig_PrintFilter&);
+ bool operator==(const FtraceConfig_PrintFilter&) const;
+ bool operator!=(const FtraceConfig_PrintFilter& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<FtraceConfig_PrintFilter_Rule>& rules() const { return rules_; }
+ std::vector<FtraceConfig_PrintFilter_Rule>* mutable_rules() { return &rules_; }
+ int rules_size() const;
+ void clear_rules();
+ FtraceConfig_PrintFilter_Rule* add_rules();
+
+ private:
+ std::vector<FtraceConfig_PrintFilter_Rule> rules_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FtraceConfig_PrintFilter_Rule : public ::protozero::CppMessageObj {
+ public:
+ using AtraceMessage = FtraceConfig_PrintFilter_Rule_AtraceMessage;
+ enum FieldNumbers {
+ kPrefixFieldNumber = 1,
+ kAtraceMsgFieldNumber = 3,
+ kAllowFieldNumber = 2,
+ };
+
+ FtraceConfig_PrintFilter_Rule();
+ ~FtraceConfig_PrintFilter_Rule() override;
+ FtraceConfig_PrintFilter_Rule(FtraceConfig_PrintFilter_Rule&&) noexcept;
+ FtraceConfig_PrintFilter_Rule& operator=(FtraceConfig_PrintFilter_Rule&&);
+ FtraceConfig_PrintFilter_Rule(const FtraceConfig_PrintFilter_Rule&);
+ FtraceConfig_PrintFilter_Rule& operator=(const FtraceConfig_PrintFilter_Rule&);
+ bool operator==(const FtraceConfig_PrintFilter_Rule&) const;
+ bool operator!=(const FtraceConfig_PrintFilter_Rule& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_prefix() const { return _has_field_[1]; }
+ const std::string& prefix() const { return prefix_; }
+ void set_prefix(const std::string& value) { prefix_ = value; _has_field_.set(1); }
+
+ bool has_atrace_msg() const { return _has_field_[3]; }
+ const FtraceConfig_PrintFilter_Rule_AtraceMessage& atrace_msg() const { return *atrace_msg_; }
+ FtraceConfig_PrintFilter_Rule_AtraceMessage* mutable_atrace_msg() { _has_field_.set(3); return atrace_msg_.get(); }
+
+ bool has_allow() const { return _has_field_[2]; }
+ bool allow() const { return allow_; }
+ void set_allow(bool value) { allow_ = value; _has_field_.set(2); }
+
+ private:
+ std::string prefix_{};
+ ::protozero::CopyablePtr<FtraceConfig_PrintFilter_Rule_AtraceMessage> atrace_msg_;
+ bool allow_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FtraceConfig_PrintFilter_Rule_AtraceMessage : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTypeFieldNumber = 1,
+ kPrefixFieldNumber = 2,
+ };
+
+ FtraceConfig_PrintFilter_Rule_AtraceMessage();
+ ~FtraceConfig_PrintFilter_Rule_AtraceMessage() override;
+ FtraceConfig_PrintFilter_Rule_AtraceMessage(FtraceConfig_PrintFilter_Rule_AtraceMessage&&) noexcept;
+ FtraceConfig_PrintFilter_Rule_AtraceMessage& operator=(FtraceConfig_PrintFilter_Rule_AtraceMessage&&);
+ FtraceConfig_PrintFilter_Rule_AtraceMessage(const FtraceConfig_PrintFilter_Rule_AtraceMessage&);
+ FtraceConfig_PrintFilter_Rule_AtraceMessage& operator=(const FtraceConfig_PrintFilter_Rule_AtraceMessage&);
+ bool operator==(const FtraceConfig_PrintFilter_Rule_AtraceMessage&) const;
+ bool operator!=(const FtraceConfig_PrintFilter_Rule_AtraceMessage& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_type() const { return _has_field_[1]; }
+ const std::string& type() const { return type_; }
+ void set_type(const std::string& value) { type_ = value; _has_field_.set(1); }
+
+ bool has_prefix() const { return _has_field_[2]; }
+ const std::string& prefix() const { return prefix_; }
+ void set_prefix(const std::string& value) { prefix_ = value; _has_field_.set(2); }
+
+ private:
+ std::string type_{};
+ std::string prefix_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FtraceConfig_CompactSchedConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kEnabledFieldNumber = 1,
+ };
+
+ FtraceConfig_CompactSchedConfig();
+ ~FtraceConfig_CompactSchedConfig() override;
+ FtraceConfig_CompactSchedConfig(FtraceConfig_CompactSchedConfig&&) noexcept;
+ FtraceConfig_CompactSchedConfig& operator=(FtraceConfig_CompactSchedConfig&&);
+ FtraceConfig_CompactSchedConfig(const FtraceConfig_CompactSchedConfig&);
+ FtraceConfig_CompactSchedConfig& operator=(const FtraceConfig_CompactSchedConfig&);
+ bool operator==(const FtraceConfig_CompactSchedConfig&) const;
+ bool operator!=(const FtraceConfig_CompactSchedConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_enabled() const { return _has_field_[1]; }
+ bool enabled() const { return enabled_; }
+ void set_enabled(bool value) { enabled_ = value; _has_field_.set(1); }
+
+ private:
+ bool enabled_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_FTRACE_FTRACE_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/gpu/gpu_counter_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_GPU_COUNTER_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_GPU_COUNTER_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class GpuCounterConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT GpuCounterConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kCounterPeriodNsFieldNumber = 1,
+ kCounterIdsFieldNumber = 2,
+ kInstrumentedSamplingFieldNumber = 3,
+ kFixGpuClockFieldNumber = 4,
+ };
+
+ GpuCounterConfig();
+ ~GpuCounterConfig() override;
+ GpuCounterConfig(GpuCounterConfig&&) noexcept;
+ GpuCounterConfig& operator=(GpuCounterConfig&&);
+ GpuCounterConfig(const GpuCounterConfig&);
+ GpuCounterConfig& operator=(const GpuCounterConfig&);
+ bool operator==(const GpuCounterConfig&) const;
+ bool operator!=(const GpuCounterConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_counter_period_ns() const { return _has_field_[1]; }
+ uint64_t counter_period_ns() const { return counter_period_ns_; }
+ void set_counter_period_ns(uint64_t value) { counter_period_ns_ = value; _has_field_.set(1); }
+
+ const std::vector<uint32_t>& counter_ids() const { return counter_ids_; }
+ std::vector<uint32_t>* mutable_counter_ids() { return &counter_ids_; }
+ int counter_ids_size() const { return static_cast<int>(counter_ids_.size()); }
+ void clear_counter_ids() { counter_ids_.clear(); }
+ void add_counter_ids(uint32_t value) { counter_ids_.emplace_back(value); }
+ uint32_t* add_counter_ids() { counter_ids_.emplace_back(); return &counter_ids_.back(); }
+
+ bool has_instrumented_sampling() const { return _has_field_[3]; }
+ bool instrumented_sampling() const { return instrumented_sampling_; }
+ void set_instrumented_sampling(bool value) { instrumented_sampling_ = value; _has_field_.set(3); }
+
+ bool has_fix_gpu_clock() const { return _has_field_[4]; }
+ bool fix_gpu_clock() const { return fix_gpu_clock_; }
+ void set_fix_gpu_clock(bool value) { fix_gpu_clock_ = value; _has_field_.set(4); }
+
+ private:
+ uint64_t counter_period_ns_{};
+ std::vector<uint32_t> counter_ids_;
+ bool instrumented_sampling_{};
+ bool fix_gpu_clock_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_GPU_COUNTER_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/gpu/vulkan_memory_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_VULKAN_MEMORY_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_VULKAN_MEMORY_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class VulkanMemoryConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT VulkanMemoryConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTrackDriverMemoryUsageFieldNumber = 1,
+ kTrackDeviceMemoryUsageFieldNumber = 2,
+ };
+
+ VulkanMemoryConfig();
+ ~VulkanMemoryConfig() override;
+ VulkanMemoryConfig(VulkanMemoryConfig&&) noexcept;
+ VulkanMemoryConfig& operator=(VulkanMemoryConfig&&);
+ VulkanMemoryConfig(const VulkanMemoryConfig&);
+ VulkanMemoryConfig& operator=(const VulkanMemoryConfig&);
+ bool operator==(const VulkanMemoryConfig&) const;
+ bool operator!=(const VulkanMemoryConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_track_driver_memory_usage() const { return _has_field_[1]; }
+ bool track_driver_memory_usage() const { return track_driver_memory_usage_; }
+ void set_track_driver_memory_usage(bool value) { track_driver_memory_usage_ = value; _has_field_.set(1); }
+
+ bool has_track_device_memory_usage() const { return _has_field_[2]; }
+ bool track_device_memory_usage() const { return track_device_memory_usage_; }
+ void set_track_device_memory_usage(bool value) { track_device_memory_usage_ = value; _has_field_.set(2); }
+
+ private:
+ bool track_driver_memory_usage_{};
+ bool track_device_memory_usage_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_VULKAN_MEMORY_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/inode_file/inode_file_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INODE_FILE_INODE_FILE_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INODE_FILE_INODE_FILE_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class InodeFileConfig;
+class InodeFileConfig_MountPointMappingEntry;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT InodeFileConfig : public ::protozero::CppMessageObj {
+ public:
+ using MountPointMappingEntry = InodeFileConfig_MountPointMappingEntry;
+ enum FieldNumbers {
+ kScanIntervalMsFieldNumber = 1,
+ kScanDelayMsFieldNumber = 2,
+ kScanBatchSizeFieldNumber = 3,
+ kDoNotScanFieldNumber = 4,
+ kScanMountPointsFieldNumber = 5,
+ kMountPointMappingFieldNumber = 6,
+ };
+
+ InodeFileConfig();
+ ~InodeFileConfig() override;
+ InodeFileConfig(InodeFileConfig&&) noexcept;
+ InodeFileConfig& operator=(InodeFileConfig&&);
+ InodeFileConfig(const InodeFileConfig&);
+ InodeFileConfig& operator=(const InodeFileConfig&);
+ bool operator==(const InodeFileConfig&) const;
+ bool operator!=(const InodeFileConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_scan_interval_ms() const { return _has_field_[1]; }
+ uint32_t scan_interval_ms() const { return scan_interval_ms_; }
+ void set_scan_interval_ms(uint32_t value) { scan_interval_ms_ = value; _has_field_.set(1); }
+
+ bool has_scan_delay_ms() const { return _has_field_[2]; }
+ uint32_t scan_delay_ms() const { return scan_delay_ms_; }
+ void set_scan_delay_ms(uint32_t value) { scan_delay_ms_ = value; _has_field_.set(2); }
+
+ bool has_scan_batch_size() const { return _has_field_[3]; }
+ uint32_t scan_batch_size() const { return scan_batch_size_; }
+ void set_scan_batch_size(uint32_t value) { scan_batch_size_ = value; _has_field_.set(3); }
+
+ bool has_do_not_scan() const { return _has_field_[4]; }
+ bool do_not_scan() const { return do_not_scan_; }
+ void set_do_not_scan(bool value) { do_not_scan_ = value; _has_field_.set(4); }
+
+ const std::vector<std::string>& scan_mount_points() const { return scan_mount_points_; }
+ std::vector<std::string>* mutable_scan_mount_points() { return &scan_mount_points_; }
+ int scan_mount_points_size() const { return static_cast<int>(scan_mount_points_.size()); }
+ void clear_scan_mount_points() { scan_mount_points_.clear(); }
+ void add_scan_mount_points(std::string value) { scan_mount_points_.emplace_back(value); }
+ std::string* add_scan_mount_points() { scan_mount_points_.emplace_back(); return &scan_mount_points_.back(); }
+
+ const std::vector<InodeFileConfig_MountPointMappingEntry>& mount_point_mapping() const { return mount_point_mapping_; }
+ std::vector<InodeFileConfig_MountPointMappingEntry>* mutable_mount_point_mapping() { return &mount_point_mapping_; }
+ int mount_point_mapping_size() const;
+ void clear_mount_point_mapping();
+ InodeFileConfig_MountPointMappingEntry* add_mount_point_mapping();
+
+ private:
+ uint32_t scan_interval_ms_{};
+ uint32_t scan_delay_ms_{};
+ uint32_t scan_batch_size_{};
+ bool do_not_scan_{};
+ std::vector<std::string> scan_mount_points_;
+ std::vector<InodeFileConfig_MountPointMappingEntry> mount_point_mapping_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT InodeFileConfig_MountPointMappingEntry : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kMountpointFieldNumber = 1,
+ kScanRootsFieldNumber = 2,
+ };
+
+ InodeFileConfig_MountPointMappingEntry();
+ ~InodeFileConfig_MountPointMappingEntry() override;
+ InodeFileConfig_MountPointMappingEntry(InodeFileConfig_MountPointMappingEntry&&) noexcept;
+ InodeFileConfig_MountPointMappingEntry& operator=(InodeFileConfig_MountPointMappingEntry&&);
+ InodeFileConfig_MountPointMappingEntry(const InodeFileConfig_MountPointMappingEntry&);
+ InodeFileConfig_MountPointMappingEntry& operator=(const InodeFileConfig_MountPointMappingEntry&);
+ bool operator==(const InodeFileConfig_MountPointMappingEntry&) const;
+ bool operator!=(const InodeFileConfig_MountPointMappingEntry& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_mountpoint() const { return _has_field_[1]; }
+ const std::string& mountpoint() const { return mountpoint_; }
+ void set_mountpoint(const std::string& value) { mountpoint_ = value; _has_field_.set(1); }
+
+ const std::vector<std::string>& scan_roots() const { return scan_roots_; }
+ std::vector<std::string>* mutable_scan_roots() { return &scan_roots_; }
+ int scan_roots_size() const { return static_cast<int>(scan_roots_.size()); }
+ void clear_scan_roots() { scan_roots_.clear(); }
+ void add_scan_roots(std::string value) { scan_roots_.emplace_back(value); }
+ std::string* add_scan_roots() { scan_roots_.emplace_back(); return &scan_roots_.back(); }
+
+ private:
+ std::string mountpoint_{};
+ std::vector<std::string> scan_roots_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INODE_FILE_INODE_FILE_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/interceptors/console_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTORS_CONSOLE_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTORS_CONSOLE_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ConsoleConfig;
+enum ConsoleConfig_Output : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ConsoleConfig_Output : int {
+ ConsoleConfig_Output_OUTPUT_UNSPECIFIED = 0,
+ ConsoleConfig_Output_OUTPUT_STDOUT = 1,
+ ConsoleConfig_Output_OUTPUT_STDERR = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT ConsoleConfig : public ::protozero::CppMessageObj {
+ public:
+ using Output = ConsoleConfig_Output;
+ static constexpr auto OUTPUT_UNSPECIFIED = ConsoleConfig_Output_OUTPUT_UNSPECIFIED;
+ static constexpr auto OUTPUT_STDOUT = ConsoleConfig_Output_OUTPUT_STDOUT;
+ static constexpr auto OUTPUT_STDERR = ConsoleConfig_Output_OUTPUT_STDERR;
+ static constexpr auto Output_MIN = ConsoleConfig_Output_OUTPUT_UNSPECIFIED;
+ static constexpr auto Output_MAX = ConsoleConfig_Output_OUTPUT_STDERR;
+ enum FieldNumbers {
+ kOutputFieldNumber = 1,
+ kEnableColorsFieldNumber = 2,
+ };
+
+ ConsoleConfig();
+ ~ConsoleConfig() override;
+ ConsoleConfig(ConsoleConfig&&) noexcept;
+ ConsoleConfig& operator=(ConsoleConfig&&);
+ ConsoleConfig(const ConsoleConfig&);
+ ConsoleConfig& operator=(const ConsoleConfig&);
+ bool operator==(const ConsoleConfig&) const;
+ bool operator!=(const ConsoleConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_output() const { return _has_field_[1]; }
+ ConsoleConfig_Output output() const { return output_; }
+ void set_output(ConsoleConfig_Output value) { output_ = value; _has_field_.set(1); }
+
+ bool has_enable_colors() const { return _has_field_[2]; }
+ bool enable_colors() const { return enable_colors_; }
+ void set_enable_colors(bool value) { enable_colors_ = value; _has_field_.set(2); }
+
+ private:
+ ConsoleConfig_Output output_{};
+ bool enable_colors_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTORS_CONSOLE_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/power/android_power_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_POWER_ANDROID_POWER_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_POWER_ANDROID_POWER_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class AndroidPowerConfig;
+enum AndroidPowerConfig_BatteryCounters : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum AndroidPowerConfig_BatteryCounters : int {
+ AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_UNSPECIFIED = 0,
+ AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CHARGE = 1,
+ AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CAPACITY_PERCENT = 2,
+ AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CURRENT = 3,
+ AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CURRENT_AVG = 4,
+ AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_VOLTAGE = 5,
+};
+
+class PERFETTO_EXPORT_COMPONENT AndroidPowerConfig : public ::protozero::CppMessageObj {
+ public:
+ using BatteryCounters = AndroidPowerConfig_BatteryCounters;
+ static constexpr auto BATTERY_COUNTER_UNSPECIFIED = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_UNSPECIFIED;
+ static constexpr auto BATTERY_COUNTER_CHARGE = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CHARGE;
+ static constexpr auto BATTERY_COUNTER_CAPACITY_PERCENT = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CAPACITY_PERCENT;
+ static constexpr auto BATTERY_COUNTER_CURRENT = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CURRENT;
+ static constexpr auto BATTERY_COUNTER_CURRENT_AVG = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_CURRENT_AVG;
+ static constexpr auto BATTERY_COUNTER_VOLTAGE = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_VOLTAGE;
+ static constexpr auto BatteryCounters_MIN = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_UNSPECIFIED;
+ static constexpr auto BatteryCounters_MAX = AndroidPowerConfig_BatteryCounters_BATTERY_COUNTER_VOLTAGE;
+ enum FieldNumbers {
+ kBatteryPollMsFieldNumber = 1,
+ kBatteryCountersFieldNumber = 2,
+ kCollectPowerRailsFieldNumber = 3,
+ kCollectEnergyEstimationBreakdownFieldNumber = 4,
+ kCollectEntityStateResidencyFieldNumber = 5,
+ };
+
+ AndroidPowerConfig();
+ ~AndroidPowerConfig() override;
+ AndroidPowerConfig(AndroidPowerConfig&&) noexcept;
+ AndroidPowerConfig& operator=(AndroidPowerConfig&&);
+ AndroidPowerConfig(const AndroidPowerConfig&);
+ AndroidPowerConfig& operator=(const AndroidPowerConfig&);
+ bool operator==(const AndroidPowerConfig&) const;
+ bool operator!=(const AndroidPowerConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_battery_poll_ms() const { return _has_field_[1]; }
+ uint32_t battery_poll_ms() const { return battery_poll_ms_; }
+ void set_battery_poll_ms(uint32_t value) { battery_poll_ms_ = value; _has_field_.set(1); }
+
+ const std::vector<AndroidPowerConfig_BatteryCounters>& battery_counters() const { return battery_counters_; }
+ std::vector<AndroidPowerConfig_BatteryCounters>* mutable_battery_counters() { return &battery_counters_; }
+ int battery_counters_size() const { return static_cast<int>(battery_counters_.size()); }
+ void clear_battery_counters() { battery_counters_.clear(); }
+ void add_battery_counters(AndroidPowerConfig_BatteryCounters value) { battery_counters_.emplace_back(value); }
+ AndroidPowerConfig_BatteryCounters* add_battery_counters() { battery_counters_.emplace_back(); return &battery_counters_.back(); }
+
+ bool has_collect_power_rails() const { return _has_field_[3]; }
+ bool collect_power_rails() const { return collect_power_rails_; }
+ void set_collect_power_rails(bool value) { collect_power_rails_ = value; _has_field_.set(3); }
+
+ bool has_collect_energy_estimation_breakdown() const { return _has_field_[4]; }
+ bool collect_energy_estimation_breakdown() const { return collect_energy_estimation_breakdown_; }
+ void set_collect_energy_estimation_breakdown(bool value) { collect_energy_estimation_breakdown_ = value; _has_field_.set(4); }
+
+ bool has_collect_entity_state_residency() const { return _has_field_[5]; }
+ bool collect_entity_state_residency() const { return collect_entity_state_residency_; }
+ void set_collect_entity_state_residency(bool value) { collect_entity_state_residency_ = value; _has_field_.set(5); }
+
+ private:
+ uint32_t battery_poll_ms_{};
+ std::vector<AndroidPowerConfig_BatteryCounters> battery_counters_;
+ bool collect_power_rails_{};
+ bool collect_energy_estimation_breakdown_{};
+ bool collect_entity_state_residency_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_POWER_ANDROID_POWER_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/process_stats/process_stats_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROCESS_STATS_PROCESS_STATS_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROCESS_STATS_PROCESS_STATS_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ProcessStatsConfig;
+enum ProcessStatsConfig_Quirks : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ProcessStatsConfig_Quirks : int {
+ ProcessStatsConfig_Quirks_QUIRKS_UNSPECIFIED = 0,
+ ProcessStatsConfig_Quirks_DISABLE_INITIAL_DUMP = 1,
+ ProcessStatsConfig_Quirks_DISABLE_ON_DEMAND = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT ProcessStatsConfig : public ::protozero::CppMessageObj {
+ public:
+ using Quirks = ProcessStatsConfig_Quirks;
+ static constexpr auto QUIRKS_UNSPECIFIED = ProcessStatsConfig_Quirks_QUIRKS_UNSPECIFIED;
+ static constexpr auto DISABLE_INITIAL_DUMP = ProcessStatsConfig_Quirks_DISABLE_INITIAL_DUMP;
+ static constexpr auto DISABLE_ON_DEMAND = ProcessStatsConfig_Quirks_DISABLE_ON_DEMAND;
+ static constexpr auto Quirks_MIN = ProcessStatsConfig_Quirks_QUIRKS_UNSPECIFIED;
+ static constexpr auto Quirks_MAX = ProcessStatsConfig_Quirks_DISABLE_ON_DEMAND;
+ enum FieldNumbers {
+ kQuirksFieldNumber = 1,
+ kScanAllProcessesOnStartFieldNumber = 2,
+ kRecordThreadNamesFieldNumber = 3,
+ kProcStatsPollMsFieldNumber = 4,
+ kProcStatsCacheTtlMsFieldNumber = 6,
+ kResolveProcessFdsFieldNumber = 9,
+ kScanSmapsRollupFieldNumber = 10,
+ kRecordProcessAgeFieldNumber = 11,
+ kRecordProcessRuntimeFieldNumber = 12,
+ };
+
+ ProcessStatsConfig();
+ ~ProcessStatsConfig() override;
+ ProcessStatsConfig(ProcessStatsConfig&&) noexcept;
+ ProcessStatsConfig& operator=(ProcessStatsConfig&&);
+ ProcessStatsConfig(const ProcessStatsConfig&);
+ ProcessStatsConfig& operator=(const ProcessStatsConfig&);
+ bool operator==(const ProcessStatsConfig&) const;
+ bool operator!=(const ProcessStatsConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<ProcessStatsConfig_Quirks>& quirks() const { return quirks_; }
+ std::vector<ProcessStatsConfig_Quirks>* mutable_quirks() { return &quirks_; }
+ int quirks_size() const { return static_cast<int>(quirks_.size()); }
+ void clear_quirks() { quirks_.clear(); }
+ void add_quirks(ProcessStatsConfig_Quirks value) { quirks_.emplace_back(value); }
+ ProcessStatsConfig_Quirks* add_quirks() { quirks_.emplace_back(); return &quirks_.back(); }
+
+ bool has_scan_all_processes_on_start() const { return _has_field_[2]; }
+ bool scan_all_processes_on_start() const { return scan_all_processes_on_start_; }
+ void set_scan_all_processes_on_start(bool value) { scan_all_processes_on_start_ = value; _has_field_.set(2); }
+
+ bool has_record_thread_names() const { return _has_field_[3]; }
+ bool record_thread_names() const { return record_thread_names_; }
+ void set_record_thread_names(bool value) { record_thread_names_ = value; _has_field_.set(3); }
+
+ bool has_proc_stats_poll_ms() const { return _has_field_[4]; }
+ uint32_t proc_stats_poll_ms() const { return proc_stats_poll_ms_; }
+ void set_proc_stats_poll_ms(uint32_t value) { proc_stats_poll_ms_ = value; _has_field_.set(4); }
+
+ bool has_proc_stats_cache_ttl_ms() const { return _has_field_[6]; }
+ uint32_t proc_stats_cache_ttl_ms() const { return proc_stats_cache_ttl_ms_; }
+ void set_proc_stats_cache_ttl_ms(uint32_t value) { proc_stats_cache_ttl_ms_ = value; _has_field_.set(6); }
+
+ bool has_resolve_process_fds() const { return _has_field_[9]; }
+ bool resolve_process_fds() const { return resolve_process_fds_; }
+ void set_resolve_process_fds(bool value) { resolve_process_fds_ = value; _has_field_.set(9); }
+
+ bool has_scan_smaps_rollup() const { return _has_field_[10]; }
+ bool scan_smaps_rollup() const { return scan_smaps_rollup_; }
+ void set_scan_smaps_rollup(bool value) { scan_smaps_rollup_ = value; _has_field_.set(10); }
+
+ bool has_record_process_age() const { return _has_field_[11]; }
+ bool record_process_age() const { return record_process_age_; }
+ void set_record_process_age(bool value) { record_process_age_ = value; _has_field_.set(11); }
+
+ bool has_record_process_runtime() const { return _has_field_[12]; }
+ bool record_process_runtime() const { return record_process_runtime_; }
+ void set_record_process_runtime(bool value) { record_process_runtime_ = value; _has_field_.set(12); }
+
+ private:
+ std::vector<ProcessStatsConfig_Quirks> quirks_;
+ bool scan_all_processes_on_start_{};
+ bool record_thread_names_{};
+ uint32_t proc_stats_poll_ms_{};
+ uint32_t proc_stats_cache_ttl_ms_{};
+ bool resolve_process_fds_{};
+ bool scan_smaps_rollup_{};
+ bool record_process_age_{};
+ bool record_process_runtime_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<13> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROCESS_STATS_PROCESS_STATS_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/profiling/heapprofd_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_HEAPPROFD_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_HEAPPROFD_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class HeapprofdConfig;
+class HeapprofdConfig_ContinuousDumpConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT HeapprofdConfig : public ::protozero::CppMessageObj {
+ public:
+ using ContinuousDumpConfig = HeapprofdConfig_ContinuousDumpConfig;
+ enum FieldNumbers {
+ kSamplingIntervalBytesFieldNumber = 1,
+ kAdaptiveSamplingShmemThresholdFieldNumber = 24,
+ kAdaptiveSamplingMaxSamplingIntervalBytesFieldNumber = 25,
+ kProcessCmdlineFieldNumber = 2,
+ kPidFieldNumber = 4,
+ kTargetInstalledByFieldNumber = 26,
+ kHeapsFieldNumber = 20,
+ kExcludeHeapsFieldNumber = 27,
+ kStreamAllocationsFieldNumber = 23,
+ kHeapSamplingIntervalsFieldNumber = 22,
+ kAllHeapsFieldNumber = 21,
+ kAllFieldNumber = 5,
+ kMinAnonymousMemoryKbFieldNumber = 15,
+ kMaxHeapprofdMemoryKbFieldNumber = 16,
+ kMaxHeapprofdCpuSecsFieldNumber = 17,
+ kSkipSymbolPrefixFieldNumber = 7,
+ kContinuousDumpConfigFieldNumber = 6,
+ kShmemSizeBytesFieldNumber = 8,
+ kBlockClientFieldNumber = 9,
+ kBlockClientTimeoutUsFieldNumber = 14,
+ kNoStartupFieldNumber = 10,
+ kNoRunningFieldNumber = 11,
+ kDumpAtMaxFieldNumber = 13,
+ kDisableForkTeardownFieldNumber = 18,
+ kDisableVforkDetectionFieldNumber = 19,
+ };
+
+ HeapprofdConfig();
+ ~HeapprofdConfig() override;
+ HeapprofdConfig(HeapprofdConfig&&) noexcept;
+ HeapprofdConfig& operator=(HeapprofdConfig&&);
+ HeapprofdConfig(const HeapprofdConfig&);
+ HeapprofdConfig& operator=(const HeapprofdConfig&);
+ bool operator==(const HeapprofdConfig&) const;
+ bool operator!=(const HeapprofdConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_sampling_interval_bytes() const { return _has_field_[1]; }
+ uint64_t sampling_interval_bytes() const { return sampling_interval_bytes_; }
+ void set_sampling_interval_bytes(uint64_t value) { sampling_interval_bytes_ = value; _has_field_.set(1); }
+
+ bool has_adaptive_sampling_shmem_threshold() const { return _has_field_[24]; }
+ uint64_t adaptive_sampling_shmem_threshold() const { return adaptive_sampling_shmem_threshold_; }
+ void set_adaptive_sampling_shmem_threshold(uint64_t value) { adaptive_sampling_shmem_threshold_ = value; _has_field_.set(24); }
+
+ bool has_adaptive_sampling_max_sampling_interval_bytes() const { return _has_field_[25]; }
+ uint64_t adaptive_sampling_max_sampling_interval_bytes() const { return adaptive_sampling_max_sampling_interval_bytes_; }
+ void set_adaptive_sampling_max_sampling_interval_bytes(uint64_t value) { adaptive_sampling_max_sampling_interval_bytes_ = value; _has_field_.set(25); }
+
+ const std::vector<std::string>& process_cmdline() const { return process_cmdline_; }
+ std::vector<std::string>* mutable_process_cmdline() { return &process_cmdline_; }
+ int process_cmdline_size() const { return static_cast<int>(process_cmdline_.size()); }
+ void clear_process_cmdline() { process_cmdline_.clear(); }
+ void add_process_cmdline(std::string value) { process_cmdline_.emplace_back(value); }
+ std::string* add_process_cmdline() { process_cmdline_.emplace_back(); return &process_cmdline_.back(); }
+
+ const std::vector<uint64_t>& pid() const { return pid_; }
+ std::vector<uint64_t>* mutable_pid() { return &pid_; }
+ int pid_size() const { return static_cast<int>(pid_.size()); }
+ void clear_pid() { pid_.clear(); }
+ void add_pid(uint64_t value) { pid_.emplace_back(value); }
+ uint64_t* add_pid() { pid_.emplace_back(); return &pid_.back(); }
+
+ const std::vector<std::string>& target_installed_by() const { return target_installed_by_; }
+ std::vector<std::string>* mutable_target_installed_by() { return &target_installed_by_; }
+ int target_installed_by_size() const { return static_cast<int>(target_installed_by_.size()); }
+ void clear_target_installed_by() { target_installed_by_.clear(); }
+ void add_target_installed_by(std::string value) { target_installed_by_.emplace_back(value); }
+ std::string* add_target_installed_by() { target_installed_by_.emplace_back(); return &target_installed_by_.back(); }
+
+ const std::vector<std::string>& heaps() const { return heaps_; }
+ std::vector<std::string>* mutable_heaps() { return &heaps_; }
+ int heaps_size() const { return static_cast<int>(heaps_.size()); }
+ void clear_heaps() { heaps_.clear(); }
+ void add_heaps(std::string value) { heaps_.emplace_back(value); }
+ std::string* add_heaps() { heaps_.emplace_back(); return &heaps_.back(); }
+
+ const std::vector<std::string>& exclude_heaps() const { return exclude_heaps_; }
+ std::vector<std::string>* mutable_exclude_heaps() { return &exclude_heaps_; }
+ int exclude_heaps_size() const { return static_cast<int>(exclude_heaps_.size()); }
+ void clear_exclude_heaps() { exclude_heaps_.clear(); }
+ void add_exclude_heaps(std::string value) { exclude_heaps_.emplace_back(value); }
+ std::string* add_exclude_heaps() { exclude_heaps_.emplace_back(); return &exclude_heaps_.back(); }
+
+ bool has_stream_allocations() const { return _has_field_[23]; }
+ bool stream_allocations() const { return stream_allocations_; }
+ void set_stream_allocations(bool value) { stream_allocations_ = value; _has_field_.set(23); }
+
+ const std::vector<uint64_t>& heap_sampling_intervals() const { return heap_sampling_intervals_; }
+ std::vector<uint64_t>* mutable_heap_sampling_intervals() { return &heap_sampling_intervals_; }
+ int heap_sampling_intervals_size() const { return static_cast<int>(heap_sampling_intervals_.size()); }
+ void clear_heap_sampling_intervals() { heap_sampling_intervals_.clear(); }
+ void add_heap_sampling_intervals(uint64_t value) { heap_sampling_intervals_.emplace_back(value); }
+ uint64_t* add_heap_sampling_intervals() { heap_sampling_intervals_.emplace_back(); return &heap_sampling_intervals_.back(); }
+
+ bool has_all_heaps() const { return _has_field_[21]; }
+ bool all_heaps() const { return all_heaps_; }
+ void set_all_heaps(bool value) { all_heaps_ = value; _has_field_.set(21); }
+
+ bool has_all() const { return _has_field_[5]; }
+ bool all() const { return all_; }
+ void set_all(bool value) { all_ = value; _has_field_.set(5); }
+
+ bool has_min_anonymous_memory_kb() const { return _has_field_[15]; }
+ uint32_t min_anonymous_memory_kb() const { return min_anonymous_memory_kb_; }
+ void set_min_anonymous_memory_kb(uint32_t value) { min_anonymous_memory_kb_ = value; _has_field_.set(15); }
+
+ bool has_max_heapprofd_memory_kb() const { return _has_field_[16]; }
+ uint32_t max_heapprofd_memory_kb() const { return max_heapprofd_memory_kb_; }
+ void set_max_heapprofd_memory_kb(uint32_t value) { max_heapprofd_memory_kb_ = value; _has_field_.set(16); }
+
+ bool has_max_heapprofd_cpu_secs() const { return _has_field_[17]; }
+ uint64_t max_heapprofd_cpu_secs() const { return max_heapprofd_cpu_secs_; }
+ void set_max_heapprofd_cpu_secs(uint64_t value) { max_heapprofd_cpu_secs_ = value; _has_field_.set(17); }
+
+ const std::vector<std::string>& skip_symbol_prefix() const { return skip_symbol_prefix_; }
+ std::vector<std::string>* mutable_skip_symbol_prefix() { return &skip_symbol_prefix_; }
+ int skip_symbol_prefix_size() const { return static_cast<int>(skip_symbol_prefix_.size()); }
+ void clear_skip_symbol_prefix() { skip_symbol_prefix_.clear(); }
+ void add_skip_symbol_prefix(std::string value) { skip_symbol_prefix_.emplace_back(value); }
+ std::string* add_skip_symbol_prefix() { skip_symbol_prefix_.emplace_back(); return &skip_symbol_prefix_.back(); }
+
+ bool has_continuous_dump_config() const { return _has_field_[6]; }
+ const HeapprofdConfig_ContinuousDumpConfig& continuous_dump_config() const { return *continuous_dump_config_; }
+ HeapprofdConfig_ContinuousDumpConfig* mutable_continuous_dump_config() { _has_field_.set(6); return continuous_dump_config_.get(); }
+
+ bool has_shmem_size_bytes() const { return _has_field_[8]; }
+ uint64_t shmem_size_bytes() const { return shmem_size_bytes_; }
+ void set_shmem_size_bytes(uint64_t value) { shmem_size_bytes_ = value; _has_field_.set(8); }
+
+ bool has_block_client() const { return _has_field_[9]; }
+ bool block_client() const { return block_client_; }
+ void set_block_client(bool value) { block_client_ = value; _has_field_.set(9); }
+
+ bool has_block_client_timeout_us() const { return _has_field_[14]; }
+ uint32_t block_client_timeout_us() const { return block_client_timeout_us_; }
+ void set_block_client_timeout_us(uint32_t value) { block_client_timeout_us_ = value; _has_field_.set(14); }
+
+ bool has_no_startup() const { return _has_field_[10]; }
+ bool no_startup() const { return no_startup_; }
+ void set_no_startup(bool value) { no_startup_ = value; _has_field_.set(10); }
+
+ bool has_no_running() const { return _has_field_[11]; }
+ bool no_running() const { return no_running_; }
+ void set_no_running(bool value) { no_running_ = value; _has_field_.set(11); }
+
+ bool has_dump_at_max() const { return _has_field_[13]; }
+ bool dump_at_max() const { return dump_at_max_; }
+ void set_dump_at_max(bool value) { dump_at_max_ = value; _has_field_.set(13); }
+
+ bool has_disable_fork_teardown() const { return _has_field_[18]; }
+ bool disable_fork_teardown() const { return disable_fork_teardown_; }
+ void set_disable_fork_teardown(bool value) { disable_fork_teardown_ = value; _has_field_.set(18); }
+
+ bool has_disable_vfork_detection() const { return _has_field_[19]; }
+ bool disable_vfork_detection() const { return disable_vfork_detection_; }
+ void set_disable_vfork_detection(bool value) { disable_vfork_detection_ = value; _has_field_.set(19); }
+
+ private:
+ uint64_t sampling_interval_bytes_{};
+ uint64_t adaptive_sampling_shmem_threshold_{};
+ uint64_t adaptive_sampling_max_sampling_interval_bytes_{};
+ std::vector<std::string> process_cmdline_;
+ std::vector<uint64_t> pid_;
+ std::vector<std::string> target_installed_by_;
+ std::vector<std::string> heaps_;
+ std::vector<std::string> exclude_heaps_;
+ bool stream_allocations_{};
+ std::vector<uint64_t> heap_sampling_intervals_;
+ bool all_heaps_{};
+ bool all_{};
+ uint32_t min_anonymous_memory_kb_{};
+ uint32_t max_heapprofd_memory_kb_{};
+ uint64_t max_heapprofd_cpu_secs_{};
+ std::vector<std::string> skip_symbol_prefix_;
+ ::protozero::CopyablePtr<HeapprofdConfig_ContinuousDumpConfig> continuous_dump_config_;
+ uint64_t shmem_size_bytes_{};
+ bool block_client_{};
+ uint32_t block_client_timeout_us_{};
+ bool no_startup_{};
+ bool no_running_{};
+ bool dump_at_max_{};
+ bool disable_fork_teardown_{};
+ bool disable_vfork_detection_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<28> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT HeapprofdConfig_ContinuousDumpConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDumpPhaseMsFieldNumber = 5,
+ kDumpIntervalMsFieldNumber = 6,
+ };
+
+ HeapprofdConfig_ContinuousDumpConfig();
+ ~HeapprofdConfig_ContinuousDumpConfig() override;
+ HeapprofdConfig_ContinuousDumpConfig(HeapprofdConfig_ContinuousDumpConfig&&) noexcept;
+ HeapprofdConfig_ContinuousDumpConfig& operator=(HeapprofdConfig_ContinuousDumpConfig&&);
+ HeapprofdConfig_ContinuousDumpConfig(const HeapprofdConfig_ContinuousDumpConfig&);
+ HeapprofdConfig_ContinuousDumpConfig& operator=(const HeapprofdConfig_ContinuousDumpConfig&);
+ bool operator==(const HeapprofdConfig_ContinuousDumpConfig&) const;
+ bool operator!=(const HeapprofdConfig_ContinuousDumpConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_dump_phase_ms() const { return _has_field_[5]; }
+ uint32_t dump_phase_ms() const { return dump_phase_ms_; }
+ void set_dump_phase_ms(uint32_t value) { dump_phase_ms_ = value; _has_field_.set(5); }
+
+ bool has_dump_interval_ms() const { return _has_field_[6]; }
+ uint32_t dump_interval_ms() const { return dump_interval_ms_; }
+ void set_dump_interval_ms(uint32_t value) { dump_interval_ms_ = value; _has_field_.set(6); }
+
+ private:
+ uint32_t dump_phase_ms_{};
+ uint32_t dump_interval_ms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_HEAPPROFD_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/profiling/java_hprof_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_JAVA_HPROF_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_JAVA_HPROF_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class JavaHprofConfig;
+class JavaHprofConfig_ContinuousDumpConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT JavaHprofConfig : public ::protozero::CppMessageObj {
+ public:
+ using ContinuousDumpConfig = JavaHprofConfig_ContinuousDumpConfig;
+ enum FieldNumbers {
+ kProcessCmdlineFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTargetInstalledByFieldNumber = 7,
+ kContinuousDumpConfigFieldNumber = 3,
+ kMinAnonymousMemoryKbFieldNumber = 4,
+ kDumpSmapsFieldNumber = 5,
+ kIgnoredTypesFieldNumber = 6,
+ };
+
+ JavaHprofConfig();
+ ~JavaHprofConfig() override;
+ JavaHprofConfig(JavaHprofConfig&&) noexcept;
+ JavaHprofConfig& operator=(JavaHprofConfig&&);
+ JavaHprofConfig(const JavaHprofConfig&);
+ JavaHprofConfig& operator=(const JavaHprofConfig&);
+ bool operator==(const JavaHprofConfig&) const;
+ bool operator!=(const JavaHprofConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<std::string>& process_cmdline() const { return process_cmdline_; }
+ std::vector<std::string>* mutable_process_cmdline() { return &process_cmdline_; }
+ int process_cmdline_size() const { return static_cast<int>(process_cmdline_.size()); }
+ void clear_process_cmdline() { process_cmdline_.clear(); }
+ void add_process_cmdline(std::string value) { process_cmdline_.emplace_back(value); }
+ std::string* add_process_cmdline() { process_cmdline_.emplace_back(); return &process_cmdline_.back(); }
+
+ const std::vector<uint64_t>& pid() const { return pid_; }
+ std::vector<uint64_t>* mutable_pid() { return &pid_; }
+ int pid_size() const { return static_cast<int>(pid_.size()); }
+ void clear_pid() { pid_.clear(); }
+ void add_pid(uint64_t value) { pid_.emplace_back(value); }
+ uint64_t* add_pid() { pid_.emplace_back(); return &pid_.back(); }
+
+ const std::vector<std::string>& target_installed_by() const { return target_installed_by_; }
+ std::vector<std::string>* mutable_target_installed_by() { return &target_installed_by_; }
+ int target_installed_by_size() const { return static_cast<int>(target_installed_by_.size()); }
+ void clear_target_installed_by() { target_installed_by_.clear(); }
+ void add_target_installed_by(std::string value) { target_installed_by_.emplace_back(value); }
+ std::string* add_target_installed_by() { target_installed_by_.emplace_back(); return &target_installed_by_.back(); }
+
+ bool has_continuous_dump_config() const { return _has_field_[3]; }
+ const JavaHprofConfig_ContinuousDumpConfig& continuous_dump_config() const { return *continuous_dump_config_; }
+ JavaHprofConfig_ContinuousDumpConfig* mutable_continuous_dump_config() { _has_field_.set(3); return continuous_dump_config_.get(); }
+
+ bool has_min_anonymous_memory_kb() const { return _has_field_[4]; }
+ uint32_t min_anonymous_memory_kb() const { return min_anonymous_memory_kb_; }
+ void set_min_anonymous_memory_kb(uint32_t value) { min_anonymous_memory_kb_ = value; _has_field_.set(4); }
+
+ bool has_dump_smaps() const { return _has_field_[5]; }
+ bool dump_smaps() const { return dump_smaps_; }
+ void set_dump_smaps(bool value) { dump_smaps_ = value; _has_field_.set(5); }
+
+ const std::vector<std::string>& ignored_types() const { return ignored_types_; }
+ std::vector<std::string>* mutable_ignored_types() { return &ignored_types_; }
+ int ignored_types_size() const { return static_cast<int>(ignored_types_.size()); }
+ void clear_ignored_types() { ignored_types_.clear(); }
+ void add_ignored_types(std::string value) { ignored_types_.emplace_back(value); }
+ std::string* add_ignored_types() { ignored_types_.emplace_back(); return &ignored_types_.back(); }
+
+ private:
+ std::vector<std::string> process_cmdline_;
+ std::vector<uint64_t> pid_;
+ std::vector<std::string> target_installed_by_;
+ ::protozero::CopyablePtr<JavaHprofConfig_ContinuousDumpConfig> continuous_dump_config_;
+ uint32_t min_anonymous_memory_kb_{};
+ bool dump_smaps_{};
+ std::vector<std::string> ignored_types_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT JavaHprofConfig_ContinuousDumpConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDumpPhaseMsFieldNumber = 1,
+ kDumpIntervalMsFieldNumber = 2,
+ kScanPidsOnlyOnStartFieldNumber = 3,
+ };
+
+ JavaHprofConfig_ContinuousDumpConfig();
+ ~JavaHprofConfig_ContinuousDumpConfig() override;
+ JavaHprofConfig_ContinuousDumpConfig(JavaHprofConfig_ContinuousDumpConfig&&) noexcept;
+ JavaHprofConfig_ContinuousDumpConfig& operator=(JavaHprofConfig_ContinuousDumpConfig&&);
+ JavaHprofConfig_ContinuousDumpConfig(const JavaHprofConfig_ContinuousDumpConfig&);
+ JavaHprofConfig_ContinuousDumpConfig& operator=(const JavaHprofConfig_ContinuousDumpConfig&);
+ bool operator==(const JavaHprofConfig_ContinuousDumpConfig&) const;
+ bool operator!=(const JavaHprofConfig_ContinuousDumpConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_dump_phase_ms() const { return _has_field_[1]; }
+ uint32_t dump_phase_ms() const { return dump_phase_ms_; }
+ void set_dump_phase_ms(uint32_t value) { dump_phase_ms_ = value; _has_field_.set(1); }
+
+ bool has_dump_interval_ms() const { return _has_field_[2]; }
+ uint32_t dump_interval_ms() const { return dump_interval_ms_; }
+ void set_dump_interval_ms(uint32_t value) { dump_interval_ms_ = value; _has_field_.set(2); }
+
+ bool has_scan_pids_only_on_start() const { return _has_field_[3]; }
+ bool scan_pids_only_on_start() const { return scan_pids_only_on_start_; }
+ void set_scan_pids_only_on_start(bool value) { scan_pids_only_on_start_ = value; _has_field_.set(3); }
+
+ private:
+ uint32_t dump_phase_ms_{};
+ uint32_t dump_interval_ms_{};
+ bool scan_pids_only_on_start_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_JAVA_HPROF_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/profiling/perf_event_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_PERF_EVENT_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_PERF_EVENT_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class PerfEventConfig;
+class PerfEventConfig_CallstackSampling;
+class PerfEventConfig_Scope;
+class PerfEvents_Timebase;
+class PerfEvents_RawEvent;
+class PerfEvents_Tracepoint;
+enum PerfEventConfig_UnwindMode : int;
+enum PerfEvents_Counter : int;
+enum PerfEvents_PerfClock : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum PerfEventConfig_UnwindMode : int {
+ PerfEventConfig_UnwindMode_UNWIND_UNKNOWN = 0,
+ PerfEventConfig_UnwindMode_UNWIND_SKIP = 1,
+ PerfEventConfig_UnwindMode_UNWIND_DWARF = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT PerfEventConfig : public ::protozero::CppMessageObj {
+ public:
+ using CallstackSampling = PerfEventConfig_CallstackSampling;
+ using Scope = PerfEventConfig_Scope;
+ using UnwindMode = PerfEventConfig_UnwindMode;
+ static constexpr auto UNWIND_UNKNOWN = PerfEventConfig_UnwindMode_UNWIND_UNKNOWN;
+ static constexpr auto UNWIND_SKIP = PerfEventConfig_UnwindMode_UNWIND_SKIP;
+ static constexpr auto UNWIND_DWARF = PerfEventConfig_UnwindMode_UNWIND_DWARF;
+ static constexpr auto UnwindMode_MIN = PerfEventConfig_UnwindMode_UNWIND_UNKNOWN;
+ static constexpr auto UnwindMode_MAX = PerfEventConfig_UnwindMode_UNWIND_DWARF;
+ enum FieldNumbers {
+ kTimebaseFieldNumber = 15,
+ kCallstackSamplingFieldNumber = 16,
+ kRingBufferReadPeriodMsFieldNumber = 8,
+ kRingBufferPagesFieldNumber = 3,
+ kMaxEnqueuedFootprintKbFieldNumber = 17,
+ kMaxDaemonMemoryKbFieldNumber = 13,
+ kRemoteDescriptorTimeoutMsFieldNumber = 9,
+ kUnwindStateClearPeriodMsFieldNumber = 10,
+ kTargetInstalledByFieldNumber = 18,
+ kAllCpusFieldNumber = 1,
+ kSamplingFrequencyFieldNumber = 2,
+ kKernelFramesFieldNumber = 12,
+ kTargetPidFieldNumber = 4,
+ kTargetCmdlineFieldNumber = 5,
+ kExcludePidFieldNumber = 6,
+ kExcludeCmdlineFieldNumber = 7,
+ kAdditionalCmdlineCountFieldNumber = 11,
+ };
+
+ PerfEventConfig();
+ ~PerfEventConfig() override;
+ PerfEventConfig(PerfEventConfig&&) noexcept;
+ PerfEventConfig& operator=(PerfEventConfig&&);
+ PerfEventConfig(const PerfEventConfig&);
+ PerfEventConfig& operator=(const PerfEventConfig&);
+ bool operator==(const PerfEventConfig&) const;
+ bool operator!=(const PerfEventConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_timebase() const { return _has_field_[15]; }
+ const PerfEvents_Timebase& timebase() const { return *timebase_; }
+ PerfEvents_Timebase* mutable_timebase() { _has_field_.set(15); return timebase_.get(); }
+
+ bool has_callstack_sampling() const { return _has_field_[16]; }
+ const PerfEventConfig_CallstackSampling& callstack_sampling() const { return *callstack_sampling_; }
+ PerfEventConfig_CallstackSampling* mutable_callstack_sampling() { _has_field_.set(16); return callstack_sampling_.get(); }
+
+ bool has_ring_buffer_read_period_ms() const { return _has_field_[8]; }
+ uint32_t ring_buffer_read_period_ms() const { return ring_buffer_read_period_ms_; }
+ void set_ring_buffer_read_period_ms(uint32_t value) { ring_buffer_read_period_ms_ = value; _has_field_.set(8); }
+
+ bool has_ring_buffer_pages() const { return _has_field_[3]; }
+ uint32_t ring_buffer_pages() const { return ring_buffer_pages_; }
+ void set_ring_buffer_pages(uint32_t value) { ring_buffer_pages_ = value; _has_field_.set(3); }
+
+ bool has_max_enqueued_footprint_kb() const { return _has_field_[17]; }
+ uint64_t max_enqueued_footprint_kb() const { return max_enqueued_footprint_kb_; }
+ void set_max_enqueued_footprint_kb(uint64_t value) { max_enqueued_footprint_kb_ = value; _has_field_.set(17); }
+
+ bool has_max_daemon_memory_kb() const { return _has_field_[13]; }
+ uint32_t max_daemon_memory_kb() const { return max_daemon_memory_kb_; }
+ void set_max_daemon_memory_kb(uint32_t value) { max_daemon_memory_kb_ = value; _has_field_.set(13); }
+
+ bool has_remote_descriptor_timeout_ms() const { return _has_field_[9]; }
+ uint32_t remote_descriptor_timeout_ms() const { return remote_descriptor_timeout_ms_; }
+ void set_remote_descriptor_timeout_ms(uint32_t value) { remote_descriptor_timeout_ms_ = value; _has_field_.set(9); }
+
+ bool has_unwind_state_clear_period_ms() const { return _has_field_[10]; }
+ uint32_t unwind_state_clear_period_ms() const { return unwind_state_clear_period_ms_; }
+ void set_unwind_state_clear_period_ms(uint32_t value) { unwind_state_clear_period_ms_ = value; _has_field_.set(10); }
+
+ const std::vector<std::string>& target_installed_by() const { return target_installed_by_; }
+ std::vector<std::string>* mutable_target_installed_by() { return &target_installed_by_; }
+ int target_installed_by_size() const { return static_cast<int>(target_installed_by_.size()); }
+ void clear_target_installed_by() { target_installed_by_.clear(); }
+ void add_target_installed_by(std::string value) { target_installed_by_.emplace_back(value); }
+ std::string* add_target_installed_by() { target_installed_by_.emplace_back(); return &target_installed_by_.back(); }
+
+ bool has_all_cpus() const { return _has_field_[1]; }
+ bool all_cpus() const { return all_cpus_; }
+ void set_all_cpus(bool value) { all_cpus_ = value; _has_field_.set(1); }
+
+ bool has_sampling_frequency() const { return _has_field_[2]; }
+ uint32_t sampling_frequency() const { return sampling_frequency_; }
+ void set_sampling_frequency(uint32_t value) { sampling_frequency_ = value; _has_field_.set(2); }
+
+ bool has_kernel_frames() const { return _has_field_[12]; }
+ bool kernel_frames() const { return kernel_frames_; }
+ void set_kernel_frames(bool value) { kernel_frames_ = value; _has_field_.set(12); }
+
+ const std::vector<int32_t>& target_pid() const { return target_pid_; }
+ std::vector<int32_t>* mutable_target_pid() { return &target_pid_; }
+ int target_pid_size() const { return static_cast<int>(target_pid_.size()); }
+ void clear_target_pid() { target_pid_.clear(); }
+ void add_target_pid(int32_t value) { target_pid_.emplace_back(value); }
+ int32_t* add_target_pid() { target_pid_.emplace_back(); return &target_pid_.back(); }
+
+ const std::vector<std::string>& target_cmdline() const { return target_cmdline_; }
+ std::vector<std::string>* mutable_target_cmdline() { return &target_cmdline_; }
+ int target_cmdline_size() const { return static_cast<int>(target_cmdline_.size()); }
+ void clear_target_cmdline() { target_cmdline_.clear(); }
+ void add_target_cmdline(std::string value) { target_cmdline_.emplace_back(value); }
+ std::string* add_target_cmdline() { target_cmdline_.emplace_back(); return &target_cmdline_.back(); }
+
+ const std::vector<int32_t>& exclude_pid() const { return exclude_pid_; }
+ std::vector<int32_t>* mutable_exclude_pid() { return &exclude_pid_; }
+ int exclude_pid_size() const { return static_cast<int>(exclude_pid_.size()); }
+ void clear_exclude_pid() { exclude_pid_.clear(); }
+ void add_exclude_pid(int32_t value) { exclude_pid_.emplace_back(value); }
+ int32_t* add_exclude_pid() { exclude_pid_.emplace_back(); return &exclude_pid_.back(); }
+
+ const std::vector<std::string>& exclude_cmdline() const { return exclude_cmdline_; }
+ std::vector<std::string>* mutable_exclude_cmdline() { return &exclude_cmdline_; }
+ int exclude_cmdline_size() const { return static_cast<int>(exclude_cmdline_.size()); }
+ void clear_exclude_cmdline() { exclude_cmdline_.clear(); }
+ void add_exclude_cmdline(std::string value) { exclude_cmdline_.emplace_back(value); }
+ std::string* add_exclude_cmdline() { exclude_cmdline_.emplace_back(); return &exclude_cmdline_.back(); }
+
+ bool has_additional_cmdline_count() const { return _has_field_[11]; }
+ uint32_t additional_cmdline_count() const { return additional_cmdline_count_; }
+ void set_additional_cmdline_count(uint32_t value) { additional_cmdline_count_ = value; _has_field_.set(11); }
+
+ private:
+ ::protozero::CopyablePtr<PerfEvents_Timebase> timebase_;
+ ::protozero::CopyablePtr<PerfEventConfig_CallstackSampling> callstack_sampling_;
+ uint32_t ring_buffer_read_period_ms_{};
+ uint32_t ring_buffer_pages_{};
+ uint64_t max_enqueued_footprint_kb_{};
+ uint32_t max_daemon_memory_kb_{};
+ uint32_t remote_descriptor_timeout_ms_{};
+ uint32_t unwind_state_clear_period_ms_{};
+ std::vector<std::string> target_installed_by_;
+ bool all_cpus_{};
+ uint32_t sampling_frequency_{};
+ bool kernel_frames_{};
+ std::vector<int32_t> target_pid_;
+ std::vector<std::string> target_cmdline_;
+ std::vector<int32_t> exclude_pid_;
+ std::vector<std::string> exclude_cmdline_;
+ uint32_t additional_cmdline_count_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<19> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT PerfEventConfig_CallstackSampling : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kScopeFieldNumber = 1,
+ kKernelFramesFieldNumber = 2,
+ kUserFramesFieldNumber = 3,
+ };
+
+ PerfEventConfig_CallstackSampling();
+ ~PerfEventConfig_CallstackSampling() override;
+ PerfEventConfig_CallstackSampling(PerfEventConfig_CallstackSampling&&) noexcept;
+ PerfEventConfig_CallstackSampling& operator=(PerfEventConfig_CallstackSampling&&);
+ PerfEventConfig_CallstackSampling(const PerfEventConfig_CallstackSampling&);
+ PerfEventConfig_CallstackSampling& operator=(const PerfEventConfig_CallstackSampling&);
+ bool operator==(const PerfEventConfig_CallstackSampling&) const;
+ bool operator!=(const PerfEventConfig_CallstackSampling& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_scope() const { return _has_field_[1]; }
+ const PerfEventConfig_Scope& scope() const { return *scope_; }
+ PerfEventConfig_Scope* mutable_scope() { _has_field_.set(1); return scope_.get(); }
+
+ bool has_kernel_frames() const { return _has_field_[2]; }
+ bool kernel_frames() const { return kernel_frames_; }
+ void set_kernel_frames(bool value) { kernel_frames_ = value; _has_field_.set(2); }
+
+ bool has_user_frames() const { return _has_field_[3]; }
+ PerfEventConfig_UnwindMode user_frames() const { return user_frames_; }
+ void set_user_frames(PerfEventConfig_UnwindMode value) { user_frames_ = value; _has_field_.set(3); }
+
+ private:
+ ::protozero::CopyablePtr<PerfEventConfig_Scope> scope_;
+ bool kernel_frames_{};
+ PerfEventConfig_UnwindMode user_frames_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT PerfEventConfig_Scope : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTargetPidFieldNumber = 1,
+ kTargetCmdlineFieldNumber = 2,
+ kExcludePidFieldNumber = 3,
+ kExcludeCmdlineFieldNumber = 4,
+ kAdditionalCmdlineCountFieldNumber = 5,
+ kProcessShardCountFieldNumber = 6,
+ };
+
+ PerfEventConfig_Scope();
+ ~PerfEventConfig_Scope() override;
+ PerfEventConfig_Scope(PerfEventConfig_Scope&&) noexcept;
+ PerfEventConfig_Scope& operator=(PerfEventConfig_Scope&&);
+ PerfEventConfig_Scope(const PerfEventConfig_Scope&);
+ PerfEventConfig_Scope& operator=(const PerfEventConfig_Scope&);
+ bool operator==(const PerfEventConfig_Scope&) const;
+ bool operator!=(const PerfEventConfig_Scope& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<int32_t>& target_pid() const { return target_pid_; }
+ std::vector<int32_t>* mutable_target_pid() { return &target_pid_; }
+ int target_pid_size() const { return static_cast<int>(target_pid_.size()); }
+ void clear_target_pid() { target_pid_.clear(); }
+ void add_target_pid(int32_t value) { target_pid_.emplace_back(value); }
+ int32_t* add_target_pid() { target_pid_.emplace_back(); return &target_pid_.back(); }
+
+ const std::vector<std::string>& target_cmdline() const { return target_cmdline_; }
+ std::vector<std::string>* mutable_target_cmdline() { return &target_cmdline_; }
+ int target_cmdline_size() const { return static_cast<int>(target_cmdline_.size()); }
+ void clear_target_cmdline() { target_cmdline_.clear(); }
+ void add_target_cmdline(std::string value) { target_cmdline_.emplace_back(value); }
+ std::string* add_target_cmdline() { target_cmdline_.emplace_back(); return &target_cmdline_.back(); }
+
+ const std::vector<int32_t>& exclude_pid() const { return exclude_pid_; }
+ std::vector<int32_t>* mutable_exclude_pid() { return &exclude_pid_; }
+ int exclude_pid_size() const { return static_cast<int>(exclude_pid_.size()); }
+ void clear_exclude_pid() { exclude_pid_.clear(); }
+ void add_exclude_pid(int32_t value) { exclude_pid_.emplace_back(value); }
+ int32_t* add_exclude_pid() { exclude_pid_.emplace_back(); return &exclude_pid_.back(); }
+
+ const std::vector<std::string>& exclude_cmdline() const { return exclude_cmdline_; }
+ std::vector<std::string>* mutable_exclude_cmdline() { return &exclude_cmdline_; }
+ int exclude_cmdline_size() const { return static_cast<int>(exclude_cmdline_.size()); }
+ void clear_exclude_cmdline() { exclude_cmdline_.clear(); }
+ void add_exclude_cmdline(std::string value) { exclude_cmdline_.emplace_back(value); }
+ std::string* add_exclude_cmdline() { exclude_cmdline_.emplace_back(); return &exclude_cmdline_.back(); }
+
+ bool has_additional_cmdline_count() const { return _has_field_[5]; }
+ uint32_t additional_cmdline_count() const { return additional_cmdline_count_; }
+ void set_additional_cmdline_count(uint32_t value) { additional_cmdline_count_ = value; _has_field_.set(5); }
+
+ bool has_process_shard_count() const { return _has_field_[6]; }
+ uint32_t process_shard_count() const { return process_shard_count_; }
+ void set_process_shard_count(uint32_t value) { process_shard_count_ = value; _has_field_.set(6); }
+
+ private:
+ std::vector<int32_t> target_pid_;
+ std::vector<std::string> target_cmdline_;
+ std::vector<int32_t> exclude_pid_;
+ std::vector<std::string> exclude_cmdline_;
+ uint32_t additional_cmdline_count_{};
+ uint32_t process_shard_count_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_PERF_EVENT_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/statsd/atom_ids.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_ATOM_IDS_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_ATOM_IDS_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum AtomId : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum AtomId : int {
+ ATOM_UNSPECIFIED = 0,
+ ATOM_BLE_SCAN_STATE_CHANGED = 2,
+ ATOM_PROCESS_STATE_CHANGED = 3,
+ ATOM_BLE_SCAN_RESULT_RECEIVED = 4,
+ ATOM_SENSOR_STATE_CHANGED = 5,
+ ATOM_GPS_SCAN_STATE_CHANGED = 6,
+ ATOM_SYNC_STATE_CHANGED = 7,
+ ATOM_SCHEDULED_JOB_STATE_CHANGED = 8,
+ ATOM_SCREEN_BRIGHTNESS_CHANGED = 9,
+ ATOM_WAKELOCK_STATE_CHANGED = 10,
+ ATOM_LONG_PARTIAL_WAKELOCK_STATE_CHANGED = 11,
+ ATOM_MOBILE_RADIO_POWER_STATE_CHANGED = 12,
+ ATOM_WIFI_RADIO_POWER_STATE_CHANGED = 13,
+ ATOM_ACTIVITY_MANAGER_SLEEP_STATE_CHANGED = 14,
+ ATOM_MEMORY_FACTOR_STATE_CHANGED = 15,
+ ATOM_EXCESSIVE_CPU_USAGE_REPORTED = 16,
+ ATOM_CACHED_KILL_REPORTED = 17,
+ ATOM_PROCESS_MEMORY_STAT_REPORTED = 18,
+ ATOM_LAUNCHER_EVENT = 19,
+ ATOM_BATTERY_SAVER_MODE_STATE_CHANGED = 20,
+ ATOM_DEVICE_IDLE_MODE_STATE_CHANGED = 21,
+ ATOM_DEVICE_IDLING_MODE_STATE_CHANGED = 22,
+ ATOM_AUDIO_STATE_CHANGED = 23,
+ ATOM_MEDIA_CODEC_STATE_CHANGED = 24,
+ ATOM_CAMERA_STATE_CHANGED = 25,
+ ATOM_FLASHLIGHT_STATE_CHANGED = 26,
+ ATOM_UID_PROCESS_STATE_CHANGED = 27,
+ ATOM_PROCESS_LIFE_CYCLE_STATE_CHANGED = 28,
+ ATOM_SCREEN_STATE_CHANGED = 29,
+ ATOM_BATTERY_LEVEL_CHANGED = 30,
+ ATOM_CHARGING_STATE_CHANGED = 31,
+ ATOM_PLUGGED_STATE_CHANGED = 32,
+ ATOM_INTERACTIVE_STATE_CHANGED = 33,
+ ATOM_TOUCH_EVENT_REPORTED = 34,
+ ATOM_WAKEUP_ALARM_OCCURRED = 35,
+ ATOM_KERNEL_WAKEUP_REPORTED = 36,
+ ATOM_WIFI_LOCK_STATE_CHANGED = 37,
+ ATOM_WIFI_SIGNAL_STRENGTH_CHANGED = 38,
+ ATOM_WIFI_SCAN_STATE_CHANGED = 39,
+ ATOM_PHONE_SIGNAL_STRENGTH_CHANGED = 40,
+ ATOM_SETTING_CHANGED = 41,
+ ATOM_ACTIVITY_FOREGROUND_STATE_CHANGED = 42,
+ ATOM_ISOLATED_UID_CHANGED = 43,
+ ATOM_PACKET_WAKEUP_OCCURRED = 44,
+ ATOM_WALL_CLOCK_TIME_SHIFTED = 45,
+ ATOM_ANOMALY_DETECTED = 46,
+ ATOM_APP_BREADCRUMB_REPORTED = 47,
+ ATOM_APP_START_OCCURRED = 48,
+ ATOM_APP_START_CANCELED = 49,
+ ATOM_APP_START_FULLY_DRAWN = 50,
+ ATOM_LMK_KILL_OCCURRED = 51,
+ ATOM_PICTURE_IN_PICTURE_STATE_CHANGED = 52,
+ ATOM_WIFI_MULTICAST_LOCK_STATE_CHANGED = 53,
+ ATOM_LMK_STATE_CHANGED = 54,
+ ATOM_APP_START_MEMORY_STATE_CAPTURED = 55,
+ ATOM_SHUTDOWN_SEQUENCE_REPORTED = 56,
+ ATOM_BOOT_SEQUENCE_REPORTED = 57,
+ ATOM_DAVEY_OCCURRED = 58,
+ ATOM_OVERLAY_STATE_CHANGED = 59,
+ ATOM_FOREGROUND_SERVICE_STATE_CHANGED = 60,
+ ATOM_CALL_STATE_CHANGED = 61,
+ ATOM_KEYGUARD_STATE_CHANGED = 62,
+ ATOM_KEYGUARD_BOUNCER_STATE_CHANGED = 63,
+ ATOM_KEYGUARD_BOUNCER_PASSWORD_ENTERED = 64,
+ ATOM_APP_DIED = 65,
+ ATOM_RESOURCE_CONFIGURATION_CHANGED = 66,
+ ATOM_BLUETOOTH_ENABLED_STATE_CHANGED = 67,
+ ATOM_BLUETOOTH_CONNECTION_STATE_CHANGED = 68,
+ ATOM_GPS_SIGNAL_QUALITY_CHANGED = 69,
+ ATOM_USB_CONNECTOR_STATE_CHANGED = 70,
+ ATOM_SPEAKER_IMPEDANCE_REPORTED = 71,
+ ATOM_HARDWARE_FAILED = 72,
+ ATOM_PHYSICAL_DROP_DETECTED = 73,
+ ATOM_CHARGE_CYCLES_REPORTED = 74,
+ ATOM_MOBILE_CONNECTION_STATE_CHANGED = 75,
+ ATOM_MOBILE_RADIO_TECHNOLOGY_CHANGED = 76,
+ ATOM_USB_DEVICE_ATTACHED = 77,
+ ATOM_APP_CRASH_OCCURRED = 78,
+ ATOM_ANR_OCCURRED = 79,
+ ATOM_WTF_OCCURRED = 80,
+ ATOM_LOW_MEM_REPORTED = 81,
+ ATOM_GENERIC_ATOM = 82,
+ ATOM_VIBRATOR_STATE_CHANGED = 84,
+ ATOM_DEFERRED_JOB_STATS_REPORTED = 85,
+ ATOM_THERMAL_THROTTLING = 86,
+ ATOM_BIOMETRIC_ACQUIRED = 87,
+ ATOM_BIOMETRIC_AUTHENTICATED = 88,
+ ATOM_BIOMETRIC_ERROR_OCCURRED = 89,
+ ATOM_UI_EVENT_REPORTED = 90,
+ ATOM_BATTERY_HEALTH_SNAPSHOT = 91,
+ ATOM_SLOW_IO = 92,
+ ATOM_BATTERY_CAUSED_SHUTDOWN = 93,
+ ATOM_PHONE_SERVICE_STATE_CHANGED = 94,
+ ATOM_PHONE_STATE_CHANGED = 95,
+ ATOM_USER_RESTRICTION_CHANGED = 96,
+ ATOM_SETTINGS_UI_CHANGED = 97,
+ ATOM_CONNECTIVITY_STATE_CHANGED = 98,
+ ATOM_SERVICE_STATE_CHANGED = 99,
+ ATOM_SERVICE_LAUNCH_REPORTED = 100,
+ ATOM_FLAG_FLIP_UPDATE_OCCURRED = 101,
+ ATOM_BINARY_PUSH_STATE_CHANGED = 102,
+ ATOM_DEVICE_POLICY_EVENT = 103,
+ ATOM_DOCS_UI_FILE_OP_CANCELED = 104,
+ ATOM_DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED = 105,
+ ATOM_DOCS_UI_FILE_OP_FAILURE = 106,
+ ATOM_DOCS_UI_PROVIDER_FILE_OP = 107,
+ ATOM_DOCS_UI_INVALID_SCOPED_ACCESS_REQUEST = 108,
+ ATOM_DOCS_UI_LAUNCH_REPORTED = 109,
+ ATOM_DOCS_UI_ROOT_VISITED = 110,
+ ATOM_DOCS_UI_STARTUP_MS = 111,
+ ATOM_DOCS_UI_USER_ACTION_REPORTED = 112,
+ ATOM_WIFI_ENABLED_STATE_CHANGED = 113,
+ ATOM_WIFI_RUNNING_STATE_CHANGED = 114,
+ ATOM_APP_COMPACTED = 115,
+ ATOM_NETWORK_DNS_EVENT_REPORTED = 116,
+ ATOM_DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED = 117,
+ ATOM_DOCS_UI_PICK_RESULT_REPORTED = 118,
+ ATOM_DOCS_UI_SEARCH_MODE_REPORTED = 119,
+ ATOM_DOCS_UI_SEARCH_TYPE_REPORTED = 120,
+ ATOM_DATA_STALL_EVENT = 121,
+ ATOM_RESCUE_PARTY_RESET_REPORTED = 122,
+ ATOM_SIGNED_CONFIG_REPORTED = 123,
+ ATOM_GNSS_NI_EVENT_REPORTED = 124,
+ ATOM_BLUETOOTH_LINK_LAYER_CONNECTION_EVENT = 125,
+ ATOM_BLUETOOTH_ACL_CONNECTION_STATE_CHANGED = 126,
+ ATOM_BLUETOOTH_SCO_CONNECTION_STATE_CHANGED = 127,
+ ATOM_APP_DOWNGRADED = 128,
+ ATOM_APP_OPTIMIZED_AFTER_DOWNGRADED = 129,
+ ATOM_LOW_STORAGE_STATE_CHANGED = 130,
+ ATOM_GNSS_NFW_NOTIFICATION_REPORTED = 131,
+ ATOM_GNSS_CONFIGURATION_REPORTED = 132,
+ ATOM_USB_PORT_OVERHEAT_EVENT_REPORTED = 133,
+ ATOM_NFC_ERROR_OCCURRED = 134,
+ ATOM_NFC_STATE_CHANGED = 135,
+ ATOM_NFC_BEAM_OCCURRED = 136,
+ ATOM_NFC_CARDEMULATION_OCCURRED = 137,
+ ATOM_NFC_TAG_OCCURRED = 138,
+ ATOM_NFC_HCE_TRANSACTION_OCCURRED = 139,
+ ATOM_SE_STATE_CHANGED = 140,
+ ATOM_SE_OMAPI_REPORTED = 141,
+ ATOM_BROADCAST_DISPATCH_LATENCY_REPORTED = 142,
+ ATOM_ATTENTION_MANAGER_SERVICE_RESULT_REPORTED = 143,
+ ATOM_ADB_CONNECTION_CHANGED = 144,
+ ATOM_SPEECH_DSP_STAT_REPORTED = 145,
+ ATOM_USB_CONTAMINANT_REPORTED = 146,
+ ATOM_WATCHDOG_ROLLBACK_OCCURRED = 147,
+ ATOM_BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED = 148,
+ ATOM_BUBBLE_UI_CHANGED = 149,
+ ATOM_SCHEDULED_JOB_CONSTRAINT_CHANGED = 150,
+ ATOM_BLUETOOTH_ACTIVE_DEVICE_CHANGED = 151,
+ ATOM_BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED = 152,
+ ATOM_BLUETOOTH_A2DP_CODEC_CONFIG_CHANGED = 153,
+ ATOM_BLUETOOTH_A2DP_CODEC_CAPABILITY_CHANGED = 154,
+ ATOM_BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED = 155,
+ ATOM_BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED = 156,
+ ATOM_BLUETOOTH_DEVICE_RSSI_REPORTED = 157,
+ ATOM_BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED = 158,
+ ATOM_BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED = 159,
+ ATOM_BLUETOOTH_HCI_TIMEOUT_REPORTED = 160,
+ ATOM_BLUETOOTH_QUALITY_REPORT_REPORTED = 161,
+ ATOM_BLUETOOTH_DEVICE_INFO_REPORTED = 162,
+ ATOM_BLUETOOTH_REMOTE_VERSION_INFO_REPORTED = 163,
+ ATOM_BLUETOOTH_SDP_ATTRIBUTE_REPORTED = 164,
+ ATOM_BLUETOOTH_BOND_STATE_CHANGED = 165,
+ ATOM_BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED = 166,
+ ATOM_BLUETOOTH_SMP_PAIRING_EVENT_REPORTED = 167,
+ ATOM_SCREEN_TIMEOUT_EXTENSION_REPORTED = 168,
+ ATOM_PROCESS_START_TIME = 169,
+ ATOM_PERMISSION_GRANT_REQUEST_RESULT_REPORTED = 170,
+ ATOM_BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED = 171,
+ ATOM_DEVICE_IDENTIFIER_ACCESS_DENIED = 172,
+ ATOM_BUBBLE_DEVELOPER_ERROR_REPORTED = 173,
+ ATOM_ASSIST_GESTURE_STAGE_REPORTED = 174,
+ ATOM_ASSIST_GESTURE_FEEDBACK_REPORTED = 175,
+ ATOM_ASSIST_GESTURE_PROGRESS_REPORTED = 176,
+ ATOM_TOUCH_GESTURE_CLASSIFIED = 177,
+ ATOM_HIDDEN_API_USED = 178,
+ ATOM_STYLE_UI_CHANGED = 179,
+ ATOM_PRIVACY_INDICATORS_INTERACTED = 180,
+ ATOM_APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED = 181,
+ ATOM_NETWORK_STACK_REPORTED = 182,
+ ATOM_APP_MOVED_STORAGE_REPORTED = 183,
+ ATOM_BIOMETRIC_ENROLLED = 184,
+ ATOM_SYSTEM_SERVER_WATCHDOG_OCCURRED = 185,
+ ATOM_TOMB_STONE_OCCURRED = 186,
+ ATOM_BLUETOOTH_CLASS_OF_DEVICE_REPORTED = 187,
+ ATOM_INTELLIGENCE_EVENT_REPORTED = 188,
+ ATOM_THERMAL_THROTTLING_SEVERITY_STATE_CHANGED = 189,
+ ATOM_ROLE_REQUEST_RESULT_REPORTED = 190,
+ ATOM_MEDIAMETRICS_AUDIOPOLICY_REPORTED = 191,
+ ATOM_MEDIAMETRICS_AUDIORECORD_REPORTED = 192,
+ ATOM_MEDIAMETRICS_AUDIOTHREAD_REPORTED = 193,
+ ATOM_MEDIAMETRICS_AUDIOTRACK_REPORTED = 194,
+ ATOM_MEDIAMETRICS_CODEC_REPORTED = 195,
+ ATOM_MEDIAMETRICS_DRM_WIDEVINE_REPORTED = 196,
+ ATOM_MEDIAMETRICS_EXTRACTOR_REPORTED = 197,
+ ATOM_MEDIAMETRICS_MEDIADRM_REPORTED = 198,
+ ATOM_MEDIAMETRICS_NUPLAYER_REPORTED = 199,
+ ATOM_MEDIAMETRICS_RECORDER_REPORTED = 200,
+ ATOM_MEDIAMETRICS_DRMMANAGER_REPORTED = 201,
+ ATOM_CAR_POWER_STATE_CHANGED = 203,
+ ATOM_GARAGE_MODE_INFO = 204,
+ ATOM_TEST_ATOM_REPORTED = 205,
+ ATOM_CONTENT_CAPTURE_CALLER_MISMATCH_REPORTED = 206,
+ ATOM_CONTENT_CAPTURE_SERVICE_EVENTS = 207,
+ ATOM_CONTENT_CAPTURE_SESSION_EVENTS = 208,
+ ATOM_CONTENT_CAPTURE_FLUSHED = 209,
+ ATOM_LOCATION_MANAGER_API_USAGE_REPORTED = 210,
+ ATOM_REVIEW_PERMISSIONS_FRAGMENT_RESULT_REPORTED = 211,
+ ATOM_RUNTIME_PERMISSIONS_UPGRADE_RESULT = 212,
+ ATOM_GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS = 213,
+ ATOM_LOCATION_ACCESS_CHECK_NOTIFICATION_ACTION = 214,
+ ATOM_APP_PERMISSION_FRAGMENT_ACTION_REPORTED = 215,
+ ATOM_APP_PERMISSION_FRAGMENT_VIEWED = 216,
+ ATOM_APP_PERMISSIONS_FRAGMENT_VIEWED = 217,
+ ATOM_PERMISSION_APPS_FRAGMENT_VIEWED = 218,
+ ATOM_TEXT_SELECTION_EVENT = 219,
+ ATOM_TEXT_LINKIFY_EVENT = 220,
+ ATOM_CONVERSATION_ACTIONS_EVENT = 221,
+ ATOM_LANGUAGE_DETECTION_EVENT = 222,
+ ATOM_EXCLUSION_RECT_STATE_CHANGED = 223,
+ ATOM_BACK_GESTURE_REPORTED_REPORTED = 224,
+ ATOM_UPDATE_ENGINE_UPDATE_ATTEMPT_REPORTED = 225,
+ ATOM_UPDATE_ENGINE_SUCCESSFUL_UPDATE_REPORTED = 226,
+ ATOM_CAMERA_ACTION_EVENT = 227,
+ ATOM_APP_COMPATIBILITY_CHANGE_REPORTED = 228,
+ ATOM_PERFETTO_UPLOADED = 229,
+ ATOM_VMS_CLIENT_CONNECTION_STATE_CHANGED = 230,
+ ATOM_MEDIA_PROVIDER_SCAN_OCCURRED = 233,
+ ATOM_MEDIA_CONTENT_DELETED = 234,
+ ATOM_MEDIA_PROVIDER_PERMISSION_REQUESTED = 235,
+ ATOM_MEDIA_PROVIDER_SCHEMA_CHANGED = 236,
+ ATOM_MEDIA_PROVIDER_IDLE_MAINTENANCE_FINISHED = 237,
+ ATOM_REBOOT_ESCROW_RECOVERY_REPORTED = 238,
+ ATOM_BOOT_TIME_EVENT_DURATION_REPORTED = 239,
+ ATOM_BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED = 240,
+ ATOM_BOOT_TIME_EVENT_UTC_TIME_REPORTED = 241,
+ ATOM_BOOT_TIME_EVENT_ERROR_CODE_REPORTED = 242,
+ ATOM_USERSPACE_REBOOT_REPORTED = 243,
+ ATOM_NOTIFICATION_REPORTED = 244,
+ ATOM_NOTIFICATION_PANEL_REPORTED = 245,
+ ATOM_NOTIFICATION_CHANNEL_MODIFIED = 246,
+ ATOM_INTEGRITY_CHECK_RESULT_REPORTED = 247,
+ ATOM_INTEGRITY_RULES_PUSHED = 248,
+ ATOM_CB_MESSAGE_REPORTED = 249,
+ ATOM_CB_MESSAGE_ERROR = 250,
+ ATOM_WIFI_HEALTH_STAT_REPORTED = 251,
+ ATOM_WIFI_FAILURE_STAT_REPORTED = 252,
+ ATOM_WIFI_CONNECTION_RESULT_REPORTED = 253,
+ ATOM_APP_FREEZE_CHANGED = 254,
+ ATOM_SNAPSHOT_MERGE_REPORTED = 255,
+ ATOM_FOREGROUND_SERVICE_APP_OP_SESSION_ENDED = 256,
+ ATOM_DISPLAY_JANK_REPORTED = 257,
+ ATOM_APP_STANDBY_BUCKET_CHANGED = 258,
+ ATOM_SHARESHEET_STARTED = 259,
+ ATOM_RANKING_SELECTED = 260,
+ ATOM_TVSETTINGS_UI_INTERACTED = 261,
+ ATOM_LAUNCHER_SNAPSHOT = 262,
+ ATOM_PACKAGE_INSTALLER_V2_REPORTED = 263,
+ ATOM_USER_LIFECYCLE_JOURNEY_REPORTED = 264,
+ ATOM_USER_LIFECYCLE_EVENT_OCCURRED = 265,
+ ATOM_ACCESSIBILITY_SHORTCUT_REPORTED = 266,
+ ATOM_ACCESSIBILITY_SERVICE_REPORTED = 267,
+ ATOM_DOCS_UI_DRAG_AND_DROP_REPORTED = 268,
+ ATOM_APP_USAGE_EVENT_OCCURRED = 269,
+ ATOM_AUTO_REVOKE_NOTIFICATION_CLICKED = 270,
+ ATOM_AUTO_REVOKE_FRAGMENT_APP_VIEWED = 271,
+ ATOM_AUTO_REVOKED_APP_INTERACTION = 272,
+ ATOM_APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION = 273,
+ ATOM_EVS_USAGE_STATS_REPORTED = 274,
+ ATOM_AUDIO_POWER_USAGE_DATA_REPORTED = 275,
+ ATOM_TV_TUNER_STATE_CHANGED = 276,
+ ATOM_MEDIAOUTPUT_OP_SWITCH_REPORTED = 277,
+ ATOM_CB_MESSAGE_FILTERED = 278,
+ ATOM_TV_TUNER_DVR_STATUS = 279,
+ ATOM_TV_CAS_SESSION_OPEN_STATUS = 280,
+ ATOM_ASSISTANT_INVOCATION_REPORTED = 281,
+ ATOM_DISPLAY_WAKE_REPORTED = 282,
+ ATOM_CAR_USER_HAL_MODIFY_USER_REQUEST_REPORTED = 283,
+ ATOM_CAR_USER_HAL_MODIFY_USER_RESPONSE_REPORTED = 284,
+ ATOM_CAR_USER_HAL_POST_SWITCH_RESPONSE_REPORTED = 285,
+ ATOM_CAR_USER_HAL_INITIAL_USER_INFO_REQUEST_REPORTED = 286,
+ ATOM_CAR_USER_HAL_INITIAL_USER_INFO_RESPONSE_REPORTED = 287,
+ ATOM_CAR_USER_HAL_USER_ASSOCIATION_REQUEST_REPORTED = 288,
+ ATOM_CAR_USER_HAL_SET_USER_ASSOCIATION_RESPONSE_REPORTED = 289,
+ ATOM_NETWORK_IP_PROVISIONING_REPORTED = 290,
+ ATOM_NETWORK_DHCP_RENEW_REPORTED = 291,
+ ATOM_NETWORK_VALIDATION_REPORTED = 292,
+ ATOM_NETWORK_STACK_QUIRK_REPORTED = 293,
+ ATOM_MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED = 294,
+ ATOM_MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED = 295,
+ ATOM_MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED = 296,
+ ATOM_MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED = 297,
+ ATOM_BLOB_COMMITTED = 298,
+ ATOM_BLOB_LEASED = 299,
+ ATOM_BLOB_OPENED = 300,
+ ATOM_CONTACTS_PROVIDER_STATUS_REPORTED = 301,
+ ATOM_KEYSTORE_KEY_EVENT_REPORTED = 302,
+ ATOM_NETWORK_TETHERING_REPORTED = 303,
+ ATOM_IME_TOUCH_REPORTED = 304,
+ ATOM_UI_INTERACTION_FRAME_INFO_REPORTED = 305,
+ ATOM_UI_ACTION_LATENCY_REPORTED = 306,
+ ATOM_WIFI_DISCONNECT_REPORTED = 307,
+ ATOM_WIFI_CONNECTION_STATE_CHANGED = 308,
+ ATOM_HDMI_CEC_ACTIVE_SOURCE_CHANGED = 309,
+ ATOM_HDMI_CEC_MESSAGE_REPORTED = 310,
+ ATOM_AIRPLANE_MODE = 311,
+ ATOM_MODEM_RESTART = 312,
+ ATOM_CARRIER_ID_MISMATCH_REPORTED = 313,
+ ATOM_CARRIER_ID_TABLE_UPDATED = 314,
+ ATOM_DATA_STALL_RECOVERY_REPORTED = 315,
+ ATOM_MEDIAMETRICS_MEDIAPARSER_REPORTED = 316,
+ ATOM_TLS_HANDSHAKE_REPORTED = 317,
+ ATOM_TEXT_CLASSIFIER_API_USAGE_REPORTED = 318,
+ ATOM_CAR_WATCHDOG_KILL_STATS_REPORTED = 319,
+ ATOM_MEDIAMETRICS_PLAYBACK_REPORTED = 320,
+ ATOM_MEDIA_NETWORK_INFO_CHANGED = 321,
+ ATOM_MEDIA_PLAYBACK_STATE_CHANGED = 322,
+ ATOM_MEDIA_PLAYBACK_ERROR_REPORTED = 323,
+ ATOM_MEDIA_PLAYBACK_TRACK_CHANGED = 324,
+ ATOM_WIFI_SCAN_REPORTED = 325,
+ ATOM_WIFI_PNO_SCAN_REPORTED = 326,
+ ATOM_TIF_TUNE_CHANGED = 327,
+ ATOM_AUTO_ROTATE_REPORTED = 328,
+ ATOM_PERFETTO_TRIGGER = 329,
+ ATOM_TRANSCODING_DATA = 330,
+ ATOM_IMS_SERVICE_ENTITLEMENT_UPDATED = 331,
+ ATOM_DEVICE_ROTATED = 333,
+ ATOM_SIM_SPECIFIC_SETTINGS_RESTORED = 334,
+ ATOM_TEXT_CLASSIFIER_DOWNLOAD_REPORTED = 335,
+ ATOM_PIN_STORAGE_EVENT = 336,
+ ATOM_FACE_DOWN_REPORTED = 337,
+ ATOM_BLUETOOTH_HAL_CRASH_REASON_REPORTED = 338,
+ ATOM_REBOOT_ESCROW_PREPARATION_REPORTED = 339,
+ ATOM_REBOOT_ESCROW_LSKF_CAPTURE_REPORTED = 340,
+ ATOM_REBOOT_ESCROW_REBOOT_REPORTED = 341,
+ ATOM_BINDER_LATENCY_REPORTED = 342,
+ ATOM_MEDIAMETRICS_AAUDIOSTREAM_REPORTED = 343,
+ ATOM_MEDIA_TRANSCODING_SESSION_ENDED = 344,
+ ATOM_MAGNIFICATION_USAGE_REPORTED = 345,
+ ATOM_MAGNIFICATION_MODE_WITH_IME_ON_REPORTED = 346,
+ ATOM_APP_SEARCH_CALL_STATS_REPORTED = 347,
+ ATOM_APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED = 348,
+ ATOM_DEVICE_CONTROL_CHANGED = 349,
+ ATOM_DEVICE_STATE_CHANGED = 350,
+ ATOM_INPUTDEVICE_REGISTERED = 351,
+ ATOM_SMARTSPACE_CARD_REPORTED = 352,
+ ATOM_AUTH_PROMPT_AUTHENTICATE_INVOKED = 353,
+ ATOM_AUTH_MANAGER_CAN_AUTHENTICATE_INVOKED = 354,
+ ATOM_AUTH_ENROLL_ACTION_INVOKED = 355,
+ ATOM_AUTH_DEPRECATED_API_USED = 356,
+ ATOM_UNATTENDED_REBOOT_OCCURRED = 357,
+ ATOM_LONG_REBOOT_BLOCKING_REPORTED = 358,
+ ATOM_LOCATION_TIME_ZONE_PROVIDER_STATE_CHANGED = 359,
+ ATOM_FDTRACK_EVENT_OCCURRED = 364,
+ ATOM_TIMEOUT_AUTO_EXTENDED_REPORTED = 365,
+ ATOM_ALARM_BATCH_DELIVERED = 367,
+ ATOM_ALARM_SCHEDULED = 368,
+ ATOM_CAR_WATCHDOG_IO_OVERUSE_STATS_REPORTED = 369,
+ ATOM_USER_LEVEL_HIBERNATION_STATE_CHANGED = 370,
+ ATOM_APP_SEARCH_INITIALIZE_STATS_REPORTED = 371,
+ ATOM_APP_SEARCH_QUERY_STATS_REPORTED = 372,
+ ATOM_APP_PROCESS_DIED = 373,
+ ATOM_NETWORK_IP_REACHABILITY_MONITOR_REPORTED = 374,
+ ATOM_SLOW_INPUT_EVENT_REPORTED = 375,
+ ATOM_ANR_OCCURRED_PROCESSING_STARTED = 376,
+ ATOM_APP_SEARCH_REMOVE_STATS_REPORTED = 377,
+ ATOM_MEDIA_CODEC_REPORTED = 378,
+ ATOM_PERMISSION_USAGE_FRAGMENT_INTERACTION = 379,
+ ATOM_PERMISSION_DETAILS_INTERACTION = 380,
+ ATOM_PRIVACY_SENSOR_TOGGLE_INTERACTION = 381,
+ ATOM_PRIVACY_TOGGLE_DIALOG_INTERACTION = 382,
+ ATOM_APP_SEARCH_OPTIMIZE_STATS_REPORTED = 383,
+ ATOM_NON_A11Y_TOOL_SERVICE_WARNING_REPORT = 384,
+ ATOM_APP_SEARCH_SET_SCHEMA_STATS_REPORTED = 385,
+ ATOM_APP_COMPAT_STATE_CHANGED = 386,
+ ATOM_SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED = 387,
+ ATOM_SPLITSCREEN_UI_CHANGED = 388,
+ ATOM_NETWORK_DNS_HANDSHAKE_REPORTED = 389,
+ ATOM_BLUETOOTH_CODE_PATH_COUNTER = 390,
+ ATOM_BLUETOOTH_LE_BATCH_SCAN_REPORT_DELAY = 392,
+ ATOM_ACCESSIBILITY_FLOATING_MENU_UI_CHANGED = 393,
+ ATOM_NEURALNETWORKS_COMPILATION_COMPLETED = 394,
+ ATOM_NEURALNETWORKS_EXECUTION_COMPLETED = 395,
+ ATOM_NEURALNETWORKS_COMPILATION_FAILED = 396,
+ ATOM_NEURALNETWORKS_EXECUTION_FAILED = 397,
+ ATOM_CONTEXT_HUB_BOOTED = 398,
+ ATOM_CONTEXT_HUB_RESTARTED = 399,
+ ATOM_CONTEXT_HUB_LOADED_NANOAPP_SNAPSHOT_REPORTED = 400,
+ ATOM_CHRE_CODE_DOWNLOAD_TRANSACTED = 401,
+ ATOM_UWB_SESSION_INITED = 402,
+ ATOM_UWB_SESSION_CLOSED = 403,
+ ATOM_UWB_FIRST_RANGING_RECEIVED = 404,
+ ATOM_UWB_RANGING_MEASUREMENT_RECEIVED = 405,
+ ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_SCHEDULED = 406,
+ ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_COMPLETED = 407,
+ ATOM_CLIPBOARD_CLEARED = 408,
+ ATOM_VM_CREATION_REQUESTED = 409,
+ ATOM_NEARBY_DEVICE_SCAN_STATE_CHANGED = 410,
+ ATOM_CAMERA_COMPAT_CONTROL_EVENT_REPORTED = 411,
+ ATOM_APPLICATION_LOCALES_CHANGED = 412,
+ ATOM_MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED = 413,
+ ATOM_FOLD_STATE_DURATION_REPORTED = 414,
+ ATOM_LOCATION_TIME_ZONE_PROVIDER_CONTROLLER_STATE_CHANGED = 415,
+ ATOM_DISPLAY_HBM_STATE_CHANGED = 416,
+ ATOM_DISPLAY_HBM_BRIGHTNESS_CHANGED = 417,
+ ATOM_PERSISTENT_URI_PERMISSIONS_FLUSHED = 418,
+ ATOM_EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED = 419,
+ ATOM_VBMETA_DIGEST_REPORTED = 420,
+ ATOM_APEX_INFO_GATHERED = 421,
+ ATOM_PVM_INFO_GATHERED = 422,
+ ATOM_WEAR_SETTINGS_UI_INTERACTED = 423,
+ ATOM_TRACING_SERVICE_REPORT_EVENT = 424,
+ ATOM_MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED = 425,
+ ATOM_LAUNCHER_LATENCY = 426,
+ ATOM_DROPBOX_ENTRY_DROPPED = 427,
+ ATOM_WIFI_P2P_CONNECTION_REPORTED = 428,
+ ATOM_GAME_STATE_CHANGED = 429,
+ ATOM_HOTWORD_DETECTOR_CREATE_REQUESTED = 430,
+ ATOM_HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED = 431,
+ ATOM_HOTWORD_DETECTION_SERVICE_RESTARTED = 432,
+ ATOM_HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED = 433,
+ ATOM_HOTWORD_DETECTOR_EVENTS = 434,
+ ATOM_AD_SERVICES_API_CALLED = 435,
+ ATOM_AD_SERVICES_MESUREMENT_REPORTS_UPLOADED = 436,
+ ATOM_BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED = 437,
+ ATOM_CONTACTS_INDEXER_UPDATE_STATS_REPORTED = 440,
+ ATOM_APP_BACKGROUND_RESTRICTIONS_INFO = 441,
+ ATOM_MMS_SMS_PROVIDER_GET_THREAD_ID_FAILED = 442,
+ ATOM_MMS_SMS_DATABASE_HELPER_ON_UPGRADE_FAILED = 443,
+ ATOM_PERMISSION_REMINDER_NOTIFICATION_INTERACTED = 444,
+ ATOM_RECENT_PERMISSION_DECISIONS_INTERACTED = 445,
+ ATOM_GNSS_PSDS_DOWNLOAD_REPORTED = 446,
+ ATOM_LE_AUDIO_CONNECTION_SESSION_REPORTED = 447,
+ ATOM_LE_AUDIO_BROADCAST_SESSION_REPORTED = 448,
+ ATOM_DREAM_UI_EVENT_REPORTED = 449,
+ ATOM_TASK_MANAGER_EVENT_REPORTED = 450,
+ ATOM_CDM_ASSOCIATION_ACTION = 451,
+ ATOM_MAGNIFICATION_TRIPLE_TAP_AND_HOLD_ACTIVATED_SESSION_REPORTED = 452,
+ ATOM_MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED = 453,
+ ATOM_ACCESSIBILITY_TEXT_READING_OPTIONS_CHANGED = 454,
+ ATOM_WIFI_SETUP_FAILURE_CRASH_REPORTED = 455,
+ ATOM_UWB_DEVICE_ERROR_REPORTED = 456,
+ ATOM_ISOLATED_COMPILATION_SCHEDULED = 457,
+ ATOM_ISOLATED_COMPILATION_ENDED = 458,
+ ATOM_ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE = 459,
+ ATOM_SYSTEM_SERVER_PRE_WATCHDOG_OCCURRED = 460,
+ ATOM_TELEPHONY_ANOMALY_DETECTED = 461,
+ ATOM_LETTERBOX_POSITION_CHANGED = 462,
+ ATOM_REMOTE_KEY_PROVISIONING_ATTEMPT = 463,
+ ATOM_REMOTE_KEY_PROVISIONING_NETWORK_INFO = 464,
+ ATOM_REMOTE_KEY_PROVISIONING_TIMING = 465,
+ ATOM_MEDIAOUTPUT_OP_INTERACTION_REPORT = 466,
+ ATOM_SYNC_EXEMPTION_OCCURRED = 468,
+ ATOM_AUTOFILL_PRESENTATION_EVENT_REPORTED = 469,
+ ATOM_DOCK_STATE_CHANGED = 470,
+ ATOM_SAFETY_SOURCE_STATE_COLLECTED = 471,
+ ATOM_SAFETY_CENTER_SYSTEM_EVENT_REPORTED = 472,
+ ATOM_SAFETY_CENTER_INTERACTION_REPORTED = 473,
+ ATOM_SETTINGS_PROVIDER_SETTING_CHANGED = 474,
+ ATOM_BROADCAST_DELIVERY_EVENT_REPORTED = 475,
+ ATOM_SERVICE_REQUEST_EVENT_REPORTED = 476,
+ ATOM_PROVIDER_ACQUISITION_EVENT_REPORTED = 477,
+ ATOM_BLUETOOTH_DEVICE_NAME_REPORTED = 478,
+ ATOM_CB_CONFIG_UPDATED = 479,
+ ATOM_CB_MODULE_ERROR_REPORTED = 480,
+ ATOM_CB_SERVICE_FEATURE_CHANGED = 481,
+ ATOM_CB_RECEIVER_FEATURE_CHANGED = 482,
+ ATOM_JSSCRIPTENGINE_LATENCY_REPORTED = 483,
+ ATOM_PRIVACY_SIGNAL_NOTIFICATION_INTERACTION = 484,
+ ATOM_PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION = 485,
+ ATOM_PRIVACY_SIGNALS_JOB_FAILURE = 486,
+ ATOM_VIBRATION_REPORTED = 487,
+ ATOM_UWB_RANGING_START = 489,
+ ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STATUS_REPORTED = 490,
+ ATOM_APP_COMPACTED_V2 = 491,
+ ATOM_AD_SERVICES_SETTINGS_USAGE_REPORTED = 493,
+ ATOM_DISPLAY_BRIGHTNESS_CHANGED = 494,
+ ATOM_ACTIVITY_ACTION_BLOCKED = 495,
+ ATOM_BACKGROUND_FETCH_PROCESS_REPORTED = 496,
+ ATOM_UPDATE_CUSTOM_AUDIENCE_PROCESS_REPORTED = 497,
+ ATOM_RUN_AD_BIDDING_PROCESS_REPORTED = 498,
+ ATOM_RUN_AD_SCORING_PROCESS_REPORTED = 499,
+ ATOM_RUN_AD_SELECTION_PROCESS_REPORTED = 500,
+ ATOM_RUN_AD_BIDDING_PER_CA_PROCESS_REPORTED = 501,
+ ATOM_MOBILE_DATA_DOWNLOAD_DOWNLOAD_RESULT_REPORTED = 502,
+ ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STORAGE_STATS_REPORTED = 503,
+ ATOM_NETWORK_DNS_SERVER_SUPPORT_REPORTED = 504,
+ ATOM_VM_BOOTED = 505,
+ ATOM_VM_EXITED = 506,
+ ATOM_AMBIENT_BRIGHTNESS_STATS_REPORTED = 507,
+ ATOM_MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED = 508,
+ ATOM_MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED = 509,
+ ATOM_MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED = 510,
+ ATOM_MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED = 511,
+ ATOM_AD_SERVICES_MEASUREMENT_REGISTRATIONS = 512,
+ ATOM_HEARING_AID_INFO_REPORTED = 513,
+ ATOM_DEVICE_WIDE_JOB_CONSTRAINT_CHANGED = 514,
+ ATOM_AMBIENT_MODE_CHANGED = 515,
+ ATOM_ANR_LATENCY_REPORTED = 516,
+ ATOM_RESOURCE_API_INFO = 517,
+ ATOM_SYSTEM_DEFAULT_NETWORK_CHANGED = 518,
+ ATOM_IWLAN_SETUP_DATA_CALL_RESULT_REPORTED = 519,
+ ATOM_IWLAN_PDN_DISCONNECTED_REASON_REPORTED = 520,
+ ATOM_AIRPLANE_MODE_SESSION_REPORTED = 521,
+ ATOM_VM_CPU_STATUS_REPORTED = 522,
+ ATOM_VM_MEM_STATUS_REPORTED = 523,
+ ATOM_PACKAGE_INSTALLATION_SESSION_REPORTED = 524,
+ ATOM_DEFAULT_NETWORK_REMATCH_INFO = 525,
+ ATOM_NETWORK_SELECTION_PERFORMANCE = 526,
+ ATOM_NETWORK_NSD_REPORTED = 527,
+ ATOM_BLUETOOTH_DISCONNECTION_REASON_REPORTED = 529,
+ ATOM_BLUETOOTH_LOCAL_VERSIONS_REPORTED = 530,
+ ATOM_BLUETOOTH_REMOTE_SUPPORTED_FEATURES_REPORTED = 531,
+ ATOM_BLUETOOTH_LOCAL_SUPPORTED_FEATURES_REPORTED = 532,
+ ATOM_BLUETOOTH_GATT_APP_INFO = 533,
+ ATOM_BRIGHTNESS_CONFIGURATION_UPDATED = 534,
+ ATOM_AD_SERVICES_GET_TOPICS_REPORTED = 535,
+ ATOM_AD_SERVICES_EPOCH_COMPUTATION_GET_TOP_TOPICS_REPORTED = 536,
+ ATOM_AD_SERVICES_EPOCH_COMPUTATION_CLASSIFIER_REPORTED = 537,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_LAUNCHED = 538,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FINISHED = 539,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECTION_REPORTED = 540,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_DEVICE_SCAN_TRIGGERED = 541,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FIRST_DEVICE_SCAN_LATENCY = 542,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECT_DEVICE_LATENCY = 543,
+ ATOM_PACKAGE_MANAGER_SNAPSHOT_REPORTED = 544,
+ ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED = 545,
+ ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED = 546,
+ ATOM_LAUNCHER_IMPRESSION_EVENT = 547,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_ALL_DEVICES_SCAN_LATENCY = 549,
+ ATOM_WS_WATCH_FACE_EDITED = 551,
+ ATOM_WS_WATCH_FACE_FAVORITE_ACTION_REPORTED = 552,
+ ATOM_WS_WATCH_FACE_SET_ACTION_REPORTED = 553,
+ ATOM_PACKAGE_UNINSTALLATION_REPORTED = 554,
+ ATOM_GAME_MODE_CHANGED = 555,
+ ATOM_GAME_MODE_CONFIGURATION_CHANGED = 556,
+ ATOM_BEDTIME_MODE_STATE_CHANGED = 557,
+ ATOM_NETWORK_SLICE_SESSION_ENDED = 558,
+ ATOM_NETWORK_SLICE_DAILY_DATA_USAGE_REPORTED = 559,
+ ATOM_NFC_TAG_TYPE_OCCURRED = 560,
+ ATOM_NFC_AID_CONFLICT_OCCURRED = 561,
+ ATOM_NFC_READER_CONFLICT_OCCURRED = 562,
+ ATOM_WS_TILE_LIST_CHANGED = 563,
+ ATOM_GET_TYPE_ACCESSED_WITHOUT_PERMISSION = 564,
+ ATOM_MOBILE_BUNDLED_APP_INFO_GATHERED = 566,
+ ATOM_WS_WATCH_FACE_COMPLICATION_SET_CHANGED = 567,
+ ATOM_MEDIA_DRM_CREATED = 568,
+ ATOM_MEDIA_DRM_ERRORED = 569,
+ ATOM_MEDIA_DRM_SESSION_OPENED = 570,
+ ATOM_MEDIA_DRM_SESSION_CLOSED = 571,
+ ATOM_USER_SELECTED_RESOLUTION = 572,
+ ATOM_UNSAFE_INTENT_EVENT_REPORTED = 573,
+ ATOM_PERFORMANCE_HINT_SESSION_REPORTED = 574,
+ ATOM_MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED = 576,
+ ATOM_BIOMETRIC_TOUCH_REPORTED = 577,
+ ATOM_HOTWORD_AUDIO_EGRESS_EVENT_REPORTED = 578,
+ ATOM_APP_SEARCH_SCHEMA_MIGRATION_STATS_REPORTED = 579,
+ ATOM_LOCATION_ENABLED_STATE_CHANGED = 580,
+ ATOM_IME_REQUEST_FINISHED = 581,
+ ATOM_USB_COMPLIANCE_WARNINGS_REPORTED = 582,
+ ATOM_APP_SUPPORTED_LOCALES_CHANGED = 583,
+ ATOM_GRAMMATICAL_INFLECTION_CHANGED = 584,
+ ATOM_MEDIA_PROVIDER_VOLUME_RECOVERY_REPORTED = 586,
+ ATOM_BIOMETRIC_PROPERTIES_COLLECTED = 587,
+ ATOM_KERNEL_WAKEUP_ATTRIBUTED = 588,
+ ATOM_SCREEN_STATE_CHANGED_V2 = 589,
+ ATOM_WS_BACKUP_ACTION_REPORTED = 590,
+ ATOM_WS_RESTORE_ACTION_REPORTED = 591,
+ ATOM_DEVICE_LOG_ACCESS_EVENT_REPORTED = 592,
+ ATOM_MEDIA_SESSION_UPDATED = 594,
+ ATOM_WEAR_OOBE_STATE_CHANGED = 595,
+ ATOM_WS_NOTIFICATION_UPDATED = 596,
+ ATOM_NETWORK_VALIDATION_FAILURE_STATS_DAILY_REPORTED = 601,
+ ATOM_WS_COMPLICATION_TAPPED = 602,
+ ATOM_WS_WEAR_TIME_SESSION = 610,
+ ATOM_WIFI_BYTES_TRANSFER = 10000,
+ ATOM_WIFI_BYTES_TRANSFER_BY_FG_BG = 10001,
+ ATOM_MOBILE_BYTES_TRANSFER = 10002,
+ ATOM_MOBILE_BYTES_TRANSFER_BY_FG_BG = 10003,
+ ATOM_BLUETOOTH_BYTES_TRANSFER = 10006,
+ ATOM_KERNEL_WAKELOCK = 10004,
+ ATOM_SUBSYSTEM_SLEEP_STATE = 10005,
+ ATOM_CPU_TIME_PER_UID = 10009,
+ ATOM_CPU_TIME_PER_UID_FREQ = 10010,
+ ATOM_WIFI_ACTIVITY_INFO = 10011,
+ ATOM_MODEM_ACTIVITY_INFO = 10012,
+ ATOM_BLUETOOTH_ACTIVITY_INFO = 10007,
+ ATOM_PROCESS_MEMORY_STATE = 10013,
+ ATOM_SYSTEM_ELAPSED_REALTIME = 10014,
+ ATOM_SYSTEM_UPTIME = 10015,
+ ATOM_CPU_ACTIVE_TIME = 10016,
+ ATOM_CPU_CLUSTER_TIME = 10017,
+ ATOM_DISK_SPACE = 10018,
+ ATOM_REMAINING_BATTERY_CAPACITY = 10019,
+ ATOM_FULL_BATTERY_CAPACITY = 10020,
+ ATOM_TEMPERATURE = 10021,
+ ATOM_BINDER_CALLS = 10022,
+ ATOM_BINDER_CALLS_EXCEPTIONS = 10023,
+ ATOM_LOOPER_STATS = 10024,
+ ATOM_DISK_STATS = 10025,
+ ATOM_DIRECTORY_USAGE = 10026,
+ ATOM_APP_SIZE = 10027,
+ ATOM_CATEGORY_SIZE = 10028,
+ ATOM_PROC_STATS = 10029,
+ ATOM_BATTERY_VOLTAGE = 10030,
+ ATOM_NUM_FINGERPRINTS_ENROLLED = 10031,
+ ATOM_DISK_IO = 10032,
+ ATOM_POWER_PROFILE = 10033,
+ ATOM_PROC_STATS_PKG_PROC = 10034,
+ ATOM_PROCESS_CPU_TIME = 10035,
+ ATOM_CPU_TIME_PER_THREAD_FREQ = 10037,
+ ATOM_ON_DEVICE_POWER_MEASUREMENT = 10038,
+ ATOM_DEVICE_CALCULATED_POWER_USE = 10039,
+ ATOM_PROCESS_MEMORY_HIGH_WATER_MARK = 10042,
+ ATOM_BATTERY_LEVEL = 10043,
+ ATOM_BUILD_INFORMATION = 10044,
+ ATOM_BATTERY_CYCLE_COUNT = 10045,
+ ATOM_DEBUG_ELAPSED_CLOCK = 10046,
+ ATOM_DEBUG_FAILING_ELAPSED_CLOCK = 10047,
+ ATOM_NUM_FACES_ENROLLED = 10048,
+ ATOM_ROLE_HOLDER = 10049,
+ ATOM_DANGEROUS_PERMISSION_STATE = 10050,
+ ATOM_TRAIN_INFO = 10051,
+ ATOM_TIME_ZONE_DATA_INFO = 10052,
+ ATOM_EXTERNAL_STORAGE_INFO = 10053,
+ ATOM_GPU_STATS_GLOBAL_INFO = 10054,
+ ATOM_GPU_STATS_APP_INFO = 10055,
+ ATOM_SYSTEM_ION_HEAP_SIZE = 10056,
+ ATOM_APPS_ON_EXTERNAL_STORAGE_INFO = 10057,
+ ATOM_FACE_SETTINGS = 10058,
+ ATOM_COOLING_DEVICE = 10059,
+ ATOM_APP_OPS = 10060,
+ ATOM_PROCESS_SYSTEM_ION_HEAP_SIZE = 10061,
+ ATOM_SURFACEFLINGER_STATS_GLOBAL_INFO = 10062,
+ ATOM_SURFACEFLINGER_STATS_LAYER_INFO = 10063,
+ ATOM_PROCESS_MEMORY_SNAPSHOT = 10064,
+ ATOM_VMS_CLIENT_STATS = 10065,
+ ATOM_NOTIFICATION_REMOTE_VIEWS = 10066,
+ ATOM_DANGEROUS_PERMISSION_STATE_SAMPLED = 10067,
+ ATOM_GRAPHICS_STATS = 10068,
+ ATOM_RUNTIME_APP_OP_ACCESS = 10069,
+ ATOM_ION_HEAP_SIZE = 10070,
+ ATOM_PACKAGE_NOTIFICATION_PREFERENCES = 10071,
+ ATOM_PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES = 10072,
+ ATOM_PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES = 10073,
+ ATOM_GNSS_STATS = 10074,
+ ATOM_ATTRIBUTED_APP_OPS = 10075,
+ ATOM_VOICE_CALL_SESSION = 10076,
+ ATOM_VOICE_CALL_RAT_USAGE = 10077,
+ ATOM_SIM_SLOT_STATE = 10078,
+ ATOM_SUPPORTED_RADIO_ACCESS_FAMILY = 10079,
+ ATOM_SETTING_SNAPSHOT = 10080,
+ ATOM_BLOB_INFO = 10081,
+ ATOM_DATA_USAGE_BYTES_TRANSFER = 10082,
+ ATOM_BYTES_TRANSFER_BY_TAG_AND_METERED = 10083,
+ ATOM_DND_MODE_RULE = 10084,
+ ATOM_GENERAL_EXTERNAL_STORAGE_ACCESS_STATS = 10085,
+ ATOM_INCOMING_SMS = 10086,
+ ATOM_OUTGOING_SMS = 10087,
+ ATOM_CARRIER_ID_TABLE_VERSION = 10088,
+ ATOM_DATA_CALL_SESSION = 10089,
+ ATOM_CELLULAR_SERVICE_STATE = 10090,
+ ATOM_CELLULAR_DATA_SERVICE_SWITCH = 10091,
+ ATOM_SYSTEM_MEMORY = 10092,
+ ATOM_IMS_REGISTRATION_TERMINATION = 10093,
+ ATOM_IMS_REGISTRATION_STATS = 10094,
+ ATOM_CPU_TIME_PER_CLUSTER_FREQ = 10095,
+ ATOM_CPU_CYCLES_PER_UID_CLUSTER = 10096,
+ ATOM_DEVICE_ROTATED_DATA = 10097,
+ ATOM_CPU_CYCLES_PER_THREAD_GROUP_CLUSTER = 10098,
+ ATOM_MEDIA_DRM_ACTIVITY_INFO = 10099,
+ ATOM_OEM_MANAGED_BYTES_TRANSFER = 10100,
+ ATOM_GNSS_POWER_STATS = 10101,
+ ATOM_TIME_ZONE_DETECTOR_STATE = 10102,
+ ATOM_KEYSTORE2_STORAGE_STATS = 10103,
+ ATOM_RKP_POOL_STATS = 10104,
+ ATOM_PROCESS_DMABUF_MEMORY = 10105,
+ ATOM_PENDING_ALARM_INFO = 10106,
+ ATOM_USER_LEVEL_HIBERNATED_APPS = 10107,
+ ATOM_LAUNCHER_LAYOUT_SNAPSHOT = 10108,
+ ATOM_GLOBAL_HIBERNATED_APPS = 10109,
+ ATOM_INPUT_EVENT_LATENCY_SKETCH = 10110,
+ ATOM_BATTERY_USAGE_STATS_BEFORE_RESET = 10111,
+ ATOM_BATTERY_USAGE_STATS_SINCE_RESET = 10112,
+ ATOM_BATTERY_USAGE_STATS_SINCE_RESET_USING_POWER_PROFILE_MODEL = 10113,
+ ATOM_INSTALLED_INCREMENTAL_PACKAGE = 10114,
+ ATOM_TELEPHONY_NETWORK_REQUESTS = 10115,
+ ATOM_APP_SEARCH_STORAGE_INFO = 10116,
+ ATOM_VMSTAT = 10117,
+ ATOM_KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO = 10118,
+ ATOM_KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO = 10119,
+ ATOM_KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO = 10120,
+ ATOM_KEYSTORE2_ATOM_WITH_OVERFLOW = 10121,
+ ATOM_KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO = 10122,
+ ATOM_KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO = 10123,
+ ATOM_RKP_ERROR_STATS = 10124,
+ ATOM_KEYSTORE2_CRASH_STATS = 10125,
+ ATOM_VENDOR_APEX_INFO = 10126,
+ ATOM_ACCESSIBILITY_SHORTCUT_STATS = 10127,
+ ATOM_ACCESSIBILITY_FLOATING_MENU_STATS = 10128,
+ ATOM_DATA_USAGE_BYTES_TRANSFER_V2 = 10129,
+ ATOM_MEDIA_CAPABILITIES = 10130,
+ ATOM_CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY = 10131,
+ ATOM_CAR_WATCHDOG_UID_IO_USAGE_SUMMARY = 10132,
+ ATOM_IMS_REGISTRATION_FEATURE_TAG_STATS = 10133,
+ ATOM_RCS_CLIENT_PROVISIONING_STATS = 10134,
+ ATOM_RCS_ACS_PROVISIONING_STATS = 10135,
+ ATOM_SIP_DELEGATE_STATS = 10136,
+ ATOM_SIP_TRANSPORT_FEATURE_TAG_STATS = 10137,
+ ATOM_SIP_MESSAGE_RESPONSE = 10138,
+ ATOM_SIP_TRANSPORT_SESSION = 10139,
+ ATOM_IMS_DEDICATED_BEARER_LISTENER_EVENT = 10140,
+ ATOM_IMS_DEDICATED_BEARER_EVENT = 10141,
+ ATOM_IMS_REGISTRATION_SERVICE_DESC_STATS = 10142,
+ ATOM_UCE_EVENT_STATS = 10143,
+ ATOM_PRESENCE_NOTIFY_EVENT = 10144,
+ ATOM_GBA_EVENT = 10145,
+ ATOM_PER_SIM_STATUS = 10146,
+ ATOM_GPU_WORK_PER_UID = 10147,
+ ATOM_PERSISTENT_URI_PERMISSIONS_AMOUNT_PER_PACKAGE = 10148,
+ ATOM_SIGNED_PARTITION_INFO = 10149,
+ ATOM_PINNED_FILE_SIZES_PER_PACKAGE = 10150,
+ ATOM_PENDING_INTENTS_PER_PACKAGE = 10151,
+ ATOM_USER_INFO = 10152,
+ ATOM_TELEPHONY_NETWORK_REQUESTS_V2 = 10153,
+ ATOM_DEVICE_TELEPHONY_PROPERTIES = 10154,
+ ATOM_REMOTE_KEY_PROVISIONING_ERROR_COUNTS = 10155,
+ ATOM_SAFETY_STATE = 10156,
+ ATOM_INCOMING_MMS = 10157,
+ ATOM_OUTGOING_MMS = 10158,
+ ATOM_MULTI_USER_INFO = 10160,
+ ATOM_NETWORK_BPF_MAP_INFO = 10161,
+ ATOM_OUTGOING_SHORT_CODE_SMS = 10162,
+ ATOM_CONNECTIVITY_STATE_SAMPLE = 10163,
+ ATOM_NETWORK_SELECTION_REMATCH_REASONS_INFO = 10164,
+ ATOM_GAME_MODE_INFO = 10165,
+ ATOM_GAME_MODE_CONFIGURATION = 10166,
+ ATOM_GAME_MODE_LISTENER = 10167,
+ ATOM_NETWORK_SLICE_REQUEST_COUNT = 10168,
+ ATOM_WS_TILE_SNAPSHOT = 10169,
+ ATOM_WS_ACTIVE_WATCH_FACE_COMPLICATION_SET_SNAPSHOT = 10170,
+ ATOM_PROCESS_STATE = 10171,
+ ATOM_PROCESS_ASSOCIATION = 10172,
+ ATOM_ADPF_SYSTEM_COMPONENT_INFO = 10173,
+ ATOM_NOTIFICATION_MEMORY_USE = 10174,
+ ATOM_HDR_CAPABILITIES = 10175,
+ ATOM_WS_FAVOURITE_WATCH_FACE_LIST_SNAPSHOT = 10176,
+ ATOM_WIFI_AWARE_NDP_REPORTED = 638,
+ ATOM_WIFI_AWARE_ATTACH_REPORTED = 639,
+ ATOM_WIFI_SELF_RECOVERY_TRIGGERED = 661,
+ ATOM_SOFT_AP_STARTED = 680,
+ ATOM_SOFT_AP_STOPPED = 681,
+ ATOM_WIFI_LOCK_RELEASED = 687,
+ ATOM_WIFI_LOCK_DEACTIVATED = 688,
+ ATOM_WIFI_CONFIG_SAVED = 689,
+ ATOM_WIFI_AWARE_RESOURCE_USING_CHANGED = 690,
+ ATOM_WIFI_AWARE_HAL_API_CALLED = 691,
+ ATOM_WIFI_LOCAL_ONLY_REQUEST_RECEIVED = 692,
+ ATOM_WIFI_LOCAL_ONLY_REQUEST_SCAN_TRIGGERED = 693,
+ ATOM_WIFI_THREAD_TASK_EXECUTED = 694,
+ ATOM_WIFI_STATE_CHANGED = 700,
+ ATOM_WIFI_AWARE_CAPABILITIES = 10190,
+ ATOM_WIFI_MODULE_INFO = 10193,
+ ATOM_SETTINGS_SPA_REPORTED = 622,
+ ATOM_EXPRESS_EVENT_REPORTED = 528,
+ ATOM_EXPRESS_HISTOGRAM_SAMPLE_REPORTED = 593,
+ ATOM_EXPRESS_UID_EVENT_REPORTED = 644,
+ ATOM_EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED = 658,
+ ATOM_PERMISSION_RATIONALE_DIALOG_VIEWED = 645,
+ ATOM_PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED = 646,
+ ATOM_APP_DATA_SHARING_UPDATES_NOTIFICATION_INTERACTION = 647,
+ ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_VIEWED = 648,
+ ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_ACTION_REPORTED = 649,
+ ATOM_WS_INCOMING_CALL_ACTION_REPORTED = 626,
+ ATOM_WS_CALL_DISCONNECTION_REPORTED = 627,
+ ATOM_WS_CALL_DURATION_REPORTED = 628,
+ ATOM_WS_CALL_USER_EXPERIENCE_LATENCY_REPORTED = 629,
+ ATOM_WS_CALL_INTERACTION_REPORTED = 630,
+ ATOM_FULL_SCREEN_INTENT_LAUNCHED = 631,
+ ATOM_BAL_ALLOWED = 632,
+ ATOM_IN_TASK_ACTIVITY_STARTED = 685,
+ ATOM_CACHED_APPS_HIGH_WATERMARK = 10189,
+ ATOM_ODREFRESH_REPORTED = 366,
+ ATOM_ODSIGN_REPORTED = 548,
+ ATOM_ART_DATUM_REPORTED = 332,
+ ATOM_ART_DEVICE_DATUM_REPORTED = 550,
+ ATOM_ART_DATUM_DELTA_REPORTED = 565,
+ ATOM_BACKGROUND_DEXOPT_JOB_ENDED = 467,
+ ATOM_WEAR_ADAPTIVE_SUSPEND_STATS_REPORTED = 619,
+ ATOM_WEAR_POWER_ANOMALY_SERVICE_OPERATIONAL_STATS_REPORTED = 620,
+ ATOM_WEAR_POWER_ANOMALY_SERVICE_EVENT_STATS_REPORTED = 621,
+ ATOM_EMERGENCY_STATE_CHANGED = 633,
+ ATOM_DND_STATE_CHANGED = 657,
+ ATOM_MTE_STATE = 10181,
+ ATOM_AD_SERVICES_BACK_COMPAT_GET_TOPICS_REPORTED = 598,
+ ATOM_AD_SERVICES_BACK_COMPAT_EPOCH_COMPUTATION_CLASSIFIER_REPORTED = 599,
+ ATOM_AD_SERVICES_MEASUREMENT_DEBUG_KEYS = 640,
+ ATOM_AD_SERVICES_ERROR_REPORTED = 662,
+ ATOM_AD_SERVICES_BACKGROUND_JOBS_EXECUTION_REPORTED = 663,
+ ATOM_AD_SERVICES_MEASUREMENT_DELAYED_SOURCE_REGISTRATION = 673,
+ ATOM_AD_SERVICES_MEASUREMENT_ATTRIBUTION = 674,
+ ATOM_AD_SERVICES_MEASUREMENT_JOBS = 675,
+ ATOM_AD_SERVICES_MEASUREMENT_WIPEOUT = 676,
+ ATOM_AD_SERVICES_CONSENT_MIGRATED = 702,
+ ATOM_RKPD_POOL_STATS = 664,
+ ATOM_RKPD_CLIENT_OPERATION = 665,
+ ATOM_AUTOFILL_UI_EVENT_REPORTED = 603,
+ ATOM_AUTOFILL_FILL_REQUEST_REPORTED = 604,
+ ATOM_AUTOFILL_FILL_RESPONSE_REPORTED = 605,
+ ATOM_AUTOFILL_SAVE_EVENT_REPORTED = 606,
+ ATOM_AUTOFILL_SESSION_COMMITTED = 607,
+ ATOM_AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED = 659,
+ ATOM_TEST_EXTENSION_ATOM_REPORTED = 660,
+ ATOM_TEST_RESTRICTED_ATOM_REPORTED = 672,
+ ATOM_STATS_SOCKET_LOSS_REPORTED = 752,
+ ATOM_PLUGIN_INITIALIZED = 655,
+ ATOM_TV_LOW_POWER_STANDBY_POLICY = 679,
+ ATOM_LOCKSCREEN_SHORTCUT_SELECTED = 611,
+ ATOM_LOCKSCREEN_SHORTCUT_TRIGGERED = 612,
+ ATOM_EMERGENCY_NUMBERS_INFO = 10180,
+ ATOM_QUALIFIED_RAT_LIST_CHANGED = 634,
+ ATOM_QNS_IMS_CALL_DROP_STATS = 635,
+ ATOM_QNS_FALLBACK_RESTRICTION_CHANGED = 636,
+ ATOM_QNS_RAT_PREFERENCE_MISMATCH_INFO = 10177,
+ ATOM_QNS_HANDOVER_TIME_MILLIS = 10178,
+ ATOM_QNS_HANDOVER_PINGPONG = 10179,
+ ATOM_SATELLITE_CONTROLLER = 10182,
+ ATOM_SATELLITE_SESSION = 10183,
+ ATOM_SATELLITE_INCOMING_DATAGRAM = 10184,
+ ATOM_SATELLITE_OUTGOING_DATAGRAM = 10185,
+ ATOM_SATELLITE_PROVISION = 10186,
+ ATOM_SATELLITE_SOS_MESSAGE_RECOMMENDER = 10187,
+ ATOM_IKE_SESSION_TERMINATED = 678,
+ ATOM_IKE_LIVENESS_CHECK_SESSION_VALIDATED = 760,
+ ATOM_BLUETOOTH_HASHED_DEVICE_NAME_REPORTED = 613,
+ ATOM_BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION = 614,
+ ATOM_BLUETOOTH_L2CAP_COC_SERVER_CONNECTION = 615,
+ ATOM_BLUETOOTH_LE_SESSION_CONNECTED = 656,
+ ATOM_RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED = 666,
+ ATOM_BLUETOOTH_PROFILE_CONNECTION_ATTEMPTED = 696,
+ ATOM_HEALTH_CONNECT_UI_IMPRESSION = 623,
+ ATOM_HEALTH_CONNECT_UI_INTERACTION = 624,
+ ATOM_HEALTH_CONNECT_APP_OPENED_REPORTED = 625,
+ ATOM_HEALTH_CONNECT_API_CALLED = 616,
+ ATOM_HEALTH_CONNECT_USAGE_STATS = 617,
+ ATOM_HEALTH_CONNECT_STORAGE_STATS = 618,
+ ATOM_HEALTH_CONNECT_API_INVOKED = 643,
+ ATOM_EXERCISE_ROUTE_API_CALLED = 654,
+ ATOM_ATOM_9999 = 9999,
+ ATOM_ATOM_99999 = 99999,
+ ATOM_THREADNETWORK_TELEMETRY_DATA_REPORTED = 738,
+ ATOM_THREADNETWORK_TOPO_ENTRY_REPEATED = 739,
+ ATOM_THREADNETWORK_DEVICE_INFO_REPORTED = 740,
+ ATOM_EMERGENCY_NUMBER_DIALED = 637,
+ ATOM_SANDBOX_API_CALLED = 488,
+ ATOM_SANDBOX_ACTIVITY_EVENT_OCCURRED = 735,
+ ATOM_SANDBOX_SDK_STORAGE = 10159,
+ ATOM_CRONET_ENGINE_CREATED = 703,
+ ATOM_CRONET_TRAFFIC_REPORTED = 704,
+ ATOM_CRONET_ENGINE_BUILDER_INITIALIZED = 762,
+ ATOM_CRONET_HTTP_FLAGS_INITIALIZED = 763,
+ ATOM_CRONET_INITIALIZED = 764,
+ ATOM_DAILY_KEEPALIVE_INFO_REPORTED = 650,
+ ATOM_IP_CLIENT_RA_INFO_REPORTED = 778,
+ ATOM_APF_SESSION_INFO_REPORTED = 777,
+ ATOM_CREDENTIAL_MANAGER_API_CALLED = 585,
+ ATOM_CREDENTIAL_MANAGER_INIT_PHASE_REPORTED = 651,
+ ATOM_CREDENTIAL_MANAGER_CANDIDATE_PHASE_REPORTED = 652,
+ ATOM_CREDENTIAL_MANAGER_FINAL_PHASE_REPORTED = 653,
+ ATOM_CREDENTIAL_MANAGER_TOTAL_REPORTED = 667,
+ ATOM_CREDENTIAL_MANAGER_FINALNOUID_REPORTED = 668,
+ ATOM_CREDENTIAL_MANAGER_GET_REPORTED = 669,
+ ATOM_CREDENTIAL_MANAGER_AUTH_CLICK_REPORTED = 670,
+ ATOM_CREDENTIAL_MANAGER_APIV2_CALLED = 671,
+ ATOM_UWB_ACTIVITY_INFO = 10188,
+ ATOM_MEDIA_ACTION_REPORTED = 608,
+ ATOM_MEDIA_CONTROLS_LAUNCHED = 609,
+ ATOM_MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED = 600,
+ ATOM_MEDIA_CODEC_STARTED = 641,
+ ATOM_MEDIA_CODEC_STOPPED = 642,
+ ATOM_MEDIA_CODEC_RENDERED = 684,
+};
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_ATOM_IDS_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/statsd/statsd_tracing_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_STATSD_TRACING_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_STATSD_TRACING_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class StatsdPullAtomConfig;
+class StatsdTracingConfig;
+enum AtomId : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT StatsdPullAtomConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPullAtomIdFieldNumber = 1,
+ kRawPullAtomIdFieldNumber = 2,
+ kPullFrequencyMsFieldNumber = 3,
+ kPackagesFieldNumber = 4,
+ };
+
+ StatsdPullAtomConfig();
+ ~StatsdPullAtomConfig() override;
+ StatsdPullAtomConfig(StatsdPullAtomConfig&&) noexcept;
+ StatsdPullAtomConfig& operator=(StatsdPullAtomConfig&&);
+ StatsdPullAtomConfig(const StatsdPullAtomConfig&);
+ StatsdPullAtomConfig& operator=(const StatsdPullAtomConfig&);
+ bool operator==(const StatsdPullAtomConfig&) const;
+ bool operator!=(const StatsdPullAtomConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<AtomId>& pull_atom_id() const { return pull_atom_id_; }
+ std::vector<AtomId>* mutable_pull_atom_id() { return &pull_atom_id_; }
+ int pull_atom_id_size() const { return static_cast<int>(pull_atom_id_.size()); }
+ void clear_pull_atom_id() { pull_atom_id_.clear(); }
+ void add_pull_atom_id(AtomId value) { pull_atom_id_.emplace_back(value); }
+ AtomId* add_pull_atom_id() { pull_atom_id_.emplace_back(); return &pull_atom_id_.back(); }
+
+ const std::vector<int32_t>& raw_pull_atom_id() const { return raw_pull_atom_id_; }
+ std::vector<int32_t>* mutable_raw_pull_atom_id() { return &raw_pull_atom_id_; }
+ int raw_pull_atom_id_size() const { return static_cast<int>(raw_pull_atom_id_.size()); }
+ void clear_raw_pull_atom_id() { raw_pull_atom_id_.clear(); }
+ void add_raw_pull_atom_id(int32_t value) { raw_pull_atom_id_.emplace_back(value); }
+ int32_t* add_raw_pull_atom_id() { raw_pull_atom_id_.emplace_back(); return &raw_pull_atom_id_.back(); }
+
+ bool has_pull_frequency_ms() const { return _has_field_[3]; }
+ int32_t pull_frequency_ms() const { return pull_frequency_ms_; }
+ void set_pull_frequency_ms(int32_t value) { pull_frequency_ms_ = value; _has_field_.set(3); }
+
+ const std::vector<std::string>& packages() const { return packages_; }
+ std::vector<std::string>* mutable_packages() { return &packages_; }
+ int packages_size() const { return static_cast<int>(packages_.size()); }
+ void clear_packages() { packages_.clear(); }
+ void add_packages(std::string value) { packages_.emplace_back(value); }
+ std::string* add_packages() { packages_.emplace_back(); return &packages_.back(); }
+
+ private:
+ std::vector<AtomId> pull_atom_id_;
+ std::vector<int32_t> raw_pull_atom_id_;
+ int32_t pull_frequency_ms_{};
+ std::vector<std::string> packages_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT StatsdTracingConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPushAtomIdFieldNumber = 1,
+ kRawPushAtomIdFieldNumber = 2,
+ kPullConfigFieldNumber = 3,
+ };
+
+ StatsdTracingConfig();
+ ~StatsdTracingConfig() override;
+ StatsdTracingConfig(StatsdTracingConfig&&) noexcept;
+ StatsdTracingConfig& operator=(StatsdTracingConfig&&);
+ StatsdTracingConfig(const StatsdTracingConfig&);
+ StatsdTracingConfig& operator=(const StatsdTracingConfig&);
+ bool operator==(const StatsdTracingConfig&) const;
+ bool operator!=(const StatsdTracingConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<AtomId>& push_atom_id() const { return push_atom_id_; }
+ std::vector<AtomId>* mutable_push_atom_id() { return &push_atom_id_; }
+ int push_atom_id_size() const { return static_cast<int>(push_atom_id_.size()); }
+ void clear_push_atom_id() { push_atom_id_.clear(); }
+ void add_push_atom_id(AtomId value) { push_atom_id_.emplace_back(value); }
+ AtomId* add_push_atom_id() { push_atom_id_.emplace_back(); return &push_atom_id_.back(); }
+
+ const std::vector<int32_t>& raw_push_atom_id() const { return raw_push_atom_id_; }
+ std::vector<int32_t>* mutable_raw_push_atom_id() { return &raw_push_atom_id_; }
+ int raw_push_atom_id_size() const { return static_cast<int>(raw_push_atom_id_.size()); }
+ void clear_raw_push_atom_id() { raw_push_atom_id_.clear(); }
+ void add_raw_push_atom_id(int32_t value) { raw_push_atom_id_.emplace_back(value); }
+ int32_t* add_raw_push_atom_id() { raw_push_atom_id_.emplace_back(); return &raw_push_atom_id_.back(); }
+
+ const std::vector<StatsdPullAtomConfig>& pull_config() const { return pull_config_; }
+ std::vector<StatsdPullAtomConfig>* mutable_pull_config() { return &pull_config_; }
+ int pull_config_size() const;
+ void clear_pull_config();
+ StatsdPullAtomConfig* add_pull_config();
+
+ private:
+ std::vector<AtomId> push_atom_id_;
+ std::vector<int32_t> raw_push_atom_id_;
+ std::vector<StatsdPullAtomConfig> pull_config_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_STATSD_TRACING_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/sys_stats/sys_stats_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYS_STATS_SYS_STATS_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYS_STATS_SYS_STATS_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class SysStatsConfig;
+enum SysStatsConfig_StatCounters : int;
+enum MeminfoCounters : int;
+enum VmstatCounters : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum SysStatsConfig_StatCounters : int {
+ SysStatsConfig_StatCounters_STAT_UNSPECIFIED = 0,
+ SysStatsConfig_StatCounters_STAT_CPU_TIMES = 1,
+ SysStatsConfig_StatCounters_STAT_IRQ_COUNTS = 2,
+ SysStatsConfig_StatCounters_STAT_SOFTIRQ_COUNTS = 3,
+ SysStatsConfig_StatCounters_STAT_FORK_COUNT = 4,
+};
+
+class PERFETTO_EXPORT_COMPONENT SysStatsConfig : public ::protozero::CppMessageObj {
+ public:
+ using StatCounters = SysStatsConfig_StatCounters;
+ static constexpr auto STAT_UNSPECIFIED = SysStatsConfig_StatCounters_STAT_UNSPECIFIED;
+ static constexpr auto STAT_CPU_TIMES = SysStatsConfig_StatCounters_STAT_CPU_TIMES;
+ static constexpr auto STAT_IRQ_COUNTS = SysStatsConfig_StatCounters_STAT_IRQ_COUNTS;
+ static constexpr auto STAT_SOFTIRQ_COUNTS = SysStatsConfig_StatCounters_STAT_SOFTIRQ_COUNTS;
+ static constexpr auto STAT_FORK_COUNT = SysStatsConfig_StatCounters_STAT_FORK_COUNT;
+ static constexpr auto StatCounters_MIN = SysStatsConfig_StatCounters_STAT_UNSPECIFIED;
+ static constexpr auto StatCounters_MAX = SysStatsConfig_StatCounters_STAT_FORK_COUNT;
+ enum FieldNumbers {
+ kMeminfoPeriodMsFieldNumber = 1,
+ kMeminfoCountersFieldNumber = 2,
+ kVmstatPeriodMsFieldNumber = 3,
+ kVmstatCountersFieldNumber = 4,
+ kStatPeriodMsFieldNumber = 5,
+ kStatCountersFieldNumber = 6,
+ kDevfreqPeriodMsFieldNumber = 7,
+ kCpufreqPeriodMsFieldNumber = 8,
+ kBuddyinfoPeriodMsFieldNumber = 9,
+ kDiskstatPeriodMsFieldNumber = 10,
+ kPsiPeriodMsFieldNumber = 11,
+ };
+
+ SysStatsConfig();
+ ~SysStatsConfig() override;
+ SysStatsConfig(SysStatsConfig&&) noexcept;
+ SysStatsConfig& operator=(SysStatsConfig&&);
+ SysStatsConfig(const SysStatsConfig&);
+ SysStatsConfig& operator=(const SysStatsConfig&);
+ bool operator==(const SysStatsConfig&) const;
+ bool operator!=(const SysStatsConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_meminfo_period_ms() const { return _has_field_[1]; }
+ uint32_t meminfo_period_ms() const { return meminfo_period_ms_; }
+ void set_meminfo_period_ms(uint32_t value) { meminfo_period_ms_ = value; _has_field_.set(1); }
+
+ const std::vector<MeminfoCounters>& meminfo_counters() const { return meminfo_counters_; }
+ std::vector<MeminfoCounters>* mutable_meminfo_counters() { return &meminfo_counters_; }
+ int meminfo_counters_size() const { return static_cast<int>(meminfo_counters_.size()); }
+ void clear_meminfo_counters() { meminfo_counters_.clear(); }
+ void add_meminfo_counters(MeminfoCounters value) { meminfo_counters_.emplace_back(value); }
+ MeminfoCounters* add_meminfo_counters() { meminfo_counters_.emplace_back(); return &meminfo_counters_.back(); }
+
+ bool has_vmstat_period_ms() const { return _has_field_[3]; }
+ uint32_t vmstat_period_ms() const { return vmstat_period_ms_; }
+ void set_vmstat_period_ms(uint32_t value) { vmstat_period_ms_ = value; _has_field_.set(3); }
+
+ const std::vector<VmstatCounters>& vmstat_counters() const { return vmstat_counters_; }
+ std::vector<VmstatCounters>* mutable_vmstat_counters() { return &vmstat_counters_; }
+ int vmstat_counters_size() const { return static_cast<int>(vmstat_counters_.size()); }
+ void clear_vmstat_counters() { vmstat_counters_.clear(); }
+ void add_vmstat_counters(VmstatCounters value) { vmstat_counters_.emplace_back(value); }
+ VmstatCounters* add_vmstat_counters() { vmstat_counters_.emplace_back(); return &vmstat_counters_.back(); }
+
+ bool has_stat_period_ms() const { return _has_field_[5]; }
+ uint32_t stat_period_ms() const { return stat_period_ms_; }
+ void set_stat_period_ms(uint32_t value) { stat_period_ms_ = value; _has_field_.set(5); }
+
+ const std::vector<SysStatsConfig_StatCounters>& stat_counters() const { return stat_counters_; }
+ std::vector<SysStatsConfig_StatCounters>* mutable_stat_counters() { return &stat_counters_; }
+ int stat_counters_size() const { return static_cast<int>(stat_counters_.size()); }
+ void clear_stat_counters() { stat_counters_.clear(); }
+ void add_stat_counters(SysStatsConfig_StatCounters value) { stat_counters_.emplace_back(value); }
+ SysStatsConfig_StatCounters* add_stat_counters() { stat_counters_.emplace_back(); return &stat_counters_.back(); }
+
+ bool has_devfreq_period_ms() const { return _has_field_[7]; }
+ uint32_t devfreq_period_ms() const { return devfreq_period_ms_; }
+ void set_devfreq_period_ms(uint32_t value) { devfreq_period_ms_ = value; _has_field_.set(7); }
+
+ bool has_cpufreq_period_ms() const { return _has_field_[8]; }
+ uint32_t cpufreq_period_ms() const { return cpufreq_period_ms_; }
+ void set_cpufreq_period_ms(uint32_t value) { cpufreq_period_ms_ = value; _has_field_.set(8); }
+
+ bool has_buddyinfo_period_ms() const { return _has_field_[9]; }
+ uint32_t buddyinfo_period_ms() const { return buddyinfo_period_ms_; }
+ void set_buddyinfo_period_ms(uint32_t value) { buddyinfo_period_ms_ = value; _has_field_.set(9); }
+
+ bool has_diskstat_period_ms() const { return _has_field_[10]; }
+ uint32_t diskstat_period_ms() const { return diskstat_period_ms_; }
+ void set_diskstat_period_ms(uint32_t value) { diskstat_period_ms_ = value; _has_field_.set(10); }
+
+ bool has_psi_period_ms() const { return _has_field_[11]; }
+ uint32_t psi_period_ms() const { return psi_period_ms_; }
+ void set_psi_period_ms(uint32_t value) { psi_period_ms_ = value; _has_field_.set(11); }
+
+ private:
+ uint32_t meminfo_period_ms_{};
+ std::vector<MeminfoCounters> meminfo_counters_;
+ uint32_t vmstat_period_ms_{};
+ std::vector<VmstatCounters> vmstat_counters_;
+ uint32_t stat_period_ms_{};
+ std::vector<SysStatsConfig_StatCounters> stat_counters_;
+ uint32_t devfreq_period_ms_{};
+ uint32_t cpufreq_period_ms_{};
+ uint32_t buddyinfo_period_ms_{};
+ uint32_t diskstat_period_ms_{};
+ uint32_t psi_period_ms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<12> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYS_STATS_SYS_STATS_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/system_info/system_info.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYSTEM_INFO_SYSTEM_INFO_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYSTEM_INFO_SYSTEM_INFO_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class SystemInfoConfig;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT SystemInfoConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ SystemInfoConfig();
+ ~SystemInfoConfig() override;
+ SystemInfoConfig(SystemInfoConfig&&) noexcept;
+ SystemInfoConfig& operator=(SystemInfoConfig&&);
+ SystemInfoConfig(const SystemInfoConfig&);
+ SystemInfoConfig& operator=(const SystemInfoConfig&);
+ bool operator==(const SystemInfoConfig&) const;
+ bool operator!=(const SystemInfoConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYSTEM_INFO_SYSTEM_INFO_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/chrome/chrome_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeConfig;
+enum ChromeConfig_ClientPriority : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeConfig_ClientPriority : int {
+ ChromeConfig_ClientPriority_UNKNOWN = 0,
+ ChromeConfig_ClientPriority_BACKGROUND = 1,
+ ChromeConfig_ClientPriority_USER_INITIATED = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeConfig : public ::protozero::CppMessageObj {
+ public:
+ using ClientPriority = ChromeConfig_ClientPriority;
+ static constexpr auto UNKNOWN = ChromeConfig_ClientPriority_UNKNOWN;
+ static constexpr auto BACKGROUND = ChromeConfig_ClientPriority_BACKGROUND;
+ static constexpr auto USER_INITIATED = ChromeConfig_ClientPriority_USER_INITIATED;
+ static constexpr auto ClientPriority_MIN = ChromeConfig_ClientPriority_UNKNOWN;
+ static constexpr auto ClientPriority_MAX = ChromeConfig_ClientPriority_USER_INITIATED;
+ enum FieldNumbers {
+ kTraceConfigFieldNumber = 1,
+ kPrivacyFilteringEnabledFieldNumber = 2,
+ kConvertToLegacyJsonFieldNumber = 3,
+ kClientPriorityFieldNumber = 4,
+ kJsonAgentLabelFilterFieldNumber = 5,
+ };
+
+ ChromeConfig();
+ ~ChromeConfig() override;
+ ChromeConfig(ChromeConfig&&) noexcept;
+ ChromeConfig& operator=(ChromeConfig&&);
+ ChromeConfig(const ChromeConfig&);
+ ChromeConfig& operator=(const ChromeConfig&);
+ bool operator==(const ChromeConfig&) const;
+ bool operator!=(const ChromeConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_config() const { return _has_field_[1]; }
+ const std::string& trace_config() const { return trace_config_; }
+ void set_trace_config(const std::string& value) { trace_config_ = value; _has_field_.set(1); }
+
+ bool has_privacy_filtering_enabled() const { return _has_field_[2]; }
+ bool privacy_filtering_enabled() const { return privacy_filtering_enabled_; }
+ void set_privacy_filtering_enabled(bool value) { privacy_filtering_enabled_ = value; _has_field_.set(2); }
+
+ bool has_convert_to_legacy_json() const { return _has_field_[3]; }
+ bool convert_to_legacy_json() const { return convert_to_legacy_json_; }
+ void set_convert_to_legacy_json(bool value) { convert_to_legacy_json_ = value; _has_field_.set(3); }
+
+ bool has_client_priority() const { return _has_field_[4]; }
+ ChromeConfig_ClientPriority client_priority() const { return client_priority_; }
+ void set_client_priority(ChromeConfig_ClientPriority value) { client_priority_ = value; _has_field_.set(4); }
+
+ bool has_json_agent_label_filter() const { return _has_field_[5]; }
+ const std::string& json_agent_label_filter() const { return json_agent_label_filter_; }
+ void set_json_agent_label_filter(const std::string& value) { json_agent_label_filter_ = value; _has_field_.set(5); }
+
+ private:
+ std::string trace_config_{};
+ bool privacy_filtering_enabled_{};
+ bool convert_to_legacy_json_{};
+ ChromeConfig_ClientPriority client_priority_{};
+ std::string json_agent_label_filter_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/chrome/scenario_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_SCENARIO_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_SCENARIO_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TracingTriggerRulesConfig;
+class TriggerRule;
+class TriggerRule_RepeatingInterval;
+class TriggerRule_HistogramTrigger;
+class ChromeFieldTracingConfig;
+class ScenarioConfig;
+class NestedScenarioConfig;
+class TraceConfig;
+class TraceConfig_CmdTraceStartDelay;
+class TraceConfig_AndroidReportConfig;
+class TraceConfig_TraceFilter;
+class TraceConfig_TraceFilter_StringFilterChain;
+class TraceConfig_TraceFilter_StringFilterRule;
+class TraceConfig_IncidentReportConfig;
+class TraceConfig_IncrementalStateConfig;
+class TraceConfig_TriggerConfig;
+class TraceConfig_TriggerConfig_Trigger;
+class TraceConfig_GuardrailOverrides;
+class TraceConfig_StatsdMetadata;
+class TraceConfig_ProducerConfig;
+class TraceConfig_BuiltinDataSource;
+class TraceConfig_DataSource;
+class DataSourceConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+class InterceptorConfig;
+class ConsoleConfig;
+class ChromeConfig;
+class SystemInfoConfig;
+class TraceConfig_BufferConfig;
+enum TraceConfig_LockdownModeOperation : int;
+enum TraceConfig_CompressionType : int;
+enum TraceConfig_StatsdLogging : int;
+enum TraceConfig_TraceFilter_StringFilterPolicy : int;
+enum TraceConfig_TriggerConfig_TriggerMode : int;
+enum BuiltinClock : int;
+enum DataSourceConfig_SessionInitiator : int;
+enum ConsoleConfig_Output : int;
+enum ChromeConfig_ClientPriority : int;
+enum TraceConfig_BufferConfig_FillPolicy : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TracingTriggerRulesConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kRulesFieldNumber = 1,
+ };
+
+ TracingTriggerRulesConfig();
+ ~TracingTriggerRulesConfig() override;
+ TracingTriggerRulesConfig(TracingTriggerRulesConfig&&) noexcept;
+ TracingTriggerRulesConfig& operator=(TracingTriggerRulesConfig&&);
+ TracingTriggerRulesConfig(const TracingTriggerRulesConfig&);
+ TracingTriggerRulesConfig& operator=(const TracingTriggerRulesConfig&);
+ bool operator==(const TracingTriggerRulesConfig&) const;
+ bool operator!=(const TracingTriggerRulesConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<TriggerRule>& rules() const { return rules_; }
+ std::vector<TriggerRule>* mutable_rules() { return &rules_; }
+ int rules_size() const;
+ void clear_rules();
+ TriggerRule* add_rules();
+
+ private:
+ std::vector<TriggerRule> rules_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TriggerRule : public ::protozero::CppMessageObj {
+ public:
+ using HistogramTrigger = TriggerRule_HistogramTrigger;
+ using RepeatingInterval = TriggerRule_RepeatingInterval;
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kTriggerChanceFieldNumber = 2,
+ kDelayMsFieldNumber = 3,
+ kActivationDelayMsFieldNumber = 8,
+ kManualTriggerNameFieldNumber = 4,
+ kHistogramFieldNumber = 5,
+ kRepeatingIntervalFieldNumber = 6,
+ };
+
+ TriggerRule();
+ ~TriggerRule() override;
+ TriggerRule(TriggerRule&&) noexcept;
+ TriggerRule& operator=(TriggerRule&&);
+ TriggerRule(const TriggerRule&);
+ TriggerRule& operator=(const TriggerRule&);
+ bool operator==(const TriggerRule&) const;
+ bool operator!=(const TriggerRule& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_trigger_chance() const { return _has_field_[2]; }
+ float trigger_chance() const { return trigger_chance_; }
+ void set_trigger_chance(float value) { trigger_chance_ = value; _has_field_.set(2); }
+
+ bool has_delay_ms() const { return _has_field_[3]; }
+ uint64_t delay_ms() const { return delay_ms_; }
+ void set_delay_ms(uint64_t value) { delay_ms_ = value; _has_field_.set(3); }
+
+ bool has_activation_delay_ms() const { return _has_field_[8]; }
+ uint64_t activation_delay_ms() const { return activation_delay_ms_; }
+ void set_activation_delay_ms(uint64_t value) { activation_delay_ms_ = value; _has_field_.set(8); }
+
+ bool has_manual_trigger_name() const { return _has_field_[4]; }
+ const std::string& manual_trigger_name() const { return manual_trigger_name_; }
+ void set_manual_trigger_name(const std::string& value) { manual_trigger_name_ = value; _has_field_.set(4); }
+
+ bool has_histogram() const { return _has_field_[5]; }
+ const TriggerRule_HistogramTrigger& histogram() const { return *histogram_; }
+ TriggerRule_HistogramTrigger* mutable_histogram() { _has_field_.set(5); return histogram_.get(); }
+
+ bool has_repeating_interval() const { return _has_field_[6]; }
+ const TriggerRule_RepeatingInterval& repeating_interval() const { return *repeating_interval_; }
+ TriggerRule_RepeatingInterval* mutable_repeating_interval() { _has_field_.set(6); return repeating_interval_.get(); }
+
+ private:
+ std::string name_{};
+ float trigger_chance_{};
+ uint64_t delay_ms_{};
+ uint64_t activation_delay_ms_{};
+ std::string manual_trigger_name_{};
+ ::protozero::CopyablePtr<TriggerRule_HistogramTrigger> histogram_;
+ ::protozero::CopyablePtr<TriggerRule_RepeatingInterval> repeating_interval_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TriggerRule_RepeatingInterval : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPeriodMsFieldNumber = 1,
+ kRandomizedFieldNumber = 2,
+ };
+
+ TriggerRule_RepeatingInterval();
+ ~TriggerRule_RepeatingInterval() override;
+ TriggerRule_RepeatingInterval(TriggerRule_RepeatingInterval&&) noexcept;
+ TriggerRule_RepeatingInterval& operator=(TriggerRule_RepeatingInterval&&);
+ TriggerRule_RepeatingInterval(const TriggerRule_RepeatingInterval&);
+ TriggerRule_RepeatingInterval& operator=(const TriggerRule_RepeatingInterval&);
+ bool operator==(const TriggerRule_RepeatingInterval&) const;
+ bool operator!=(const TriggerRule_RepeatingInterval& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_period_ms() const { return _has_field_[1]; }
+ uint64_t period_ms() const { return period_ms_; }
+ void set_period_ms(uint64_t value) { period_ms_ = value; _has_field_.set(1); }
+
+ bool has_randomized() const { return _has_field_[2]; }
+ bool randomized() const { return randomized_; }
+ void set_randomized(bool value) { randomized_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t period_ms_{};
+ bool randomized_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TriggerRule_HistogramTrigger : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kHistogramNameFieldNumber = 1,
+ kMinValueFieldNumber = 2,
+ kMaxValueFieldNumber = 3,
+ };
+
+ TriggerRule_HistogramTrigger();
+ ~TriggerRule_HistogramTrigger() override;
+ TriggerRule_HistogramTrigger(TriggerRule_HistogramTrigger&&) noexcept;
+ TriggerRule_HistogramTrigger& operator=(TriggerRule_HistogramTrigger&&);
+ TriggerRule_HistogramTrigger(const TriggerRule_HistogramTrigger&);
+ TriggerRule_HistogramTrigger& operator=(const TriggerRule_HistogramTrigger&);
+ bool operator==(const TriggerRule_HistogramTrigger&) const;
+ bool operator!=(const TriggerRule_HistogramTrigger& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_histogram_name() const { return _has_field_[1]; }
+ const std::string& histogram_name() const { return histogram_name_; }
+ void set_histogram_name(const std::string& value) { histogram_name_ = value; _has_field_.set(1); }
+
+ bool has_min_value() const { return _has_field_[2]; }
+ int64_t min_value() const { return min_value_; }
+ void set_min_value(int64_t value) { min_value_ = value; _has_field_.set(2); }
+
+ bool has_max_value() const { return _has_field_[3]; }
+ int64_t max_value() const { return max_value_; }
+ void set_max_value(int64_t value) { max_value_ = value; _has_field_.set(3); }
+
+ private:
+ std::string histogram_name_{};
+ int64_t min_value_{};
+ int64_t max_value_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChromeFieldTracingConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kScenariosFieldNumber = 1,
+ };
+
+ ChromeFieldTracingConfig();
+ ~ChromeFieldTracingConfig() override;
+ ChromeFieldTracingConfig(ChromeFieldTracingConfig&&) noexcept;
+ ChromeFieldTracingConfig& operator=(ChromeFieldTracingConfig&&);
+ ChromeFieldTracingConfig(const ChromeFieldTracingConfig&);
+ ChromeFieldTracingConfig& operator=(const ChromeFieldTracingConfig&);
+ bool operator==(const ChromeFieldTracingConfig&) const;
+ bool operator!=(const ChromeFieldTracingConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<ScenarioConfig>& scenarios() const { return scenarios_; }
+ std::vector<ScenarioConfig>* mutable_scenarios() { return &scenarios_; }
+ int scenarios_size() const;
+ void clear_scenarios();
+ ScenarioConfig* add_scenarios();
+
+ private:
+ std::vector<ScenarioConfig> scenarios_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ScenarioConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kScenarioNameFieldNumber = 1,
+ kStartRulesFieldNumber = 2,
+ kStopRulesFieldNumber = 3,
+ kUploadRulesFieldNumber = 4,
+ kSetupRulesFieldNumber = 5,
+ kTraceConfigFieldNumber = 6,
+ kNestedScenariosFieldNumber = 7,
+ };
+
+ ScenarioConfig();
+ ~ScenarioConfig() override;
+ ScenarioConfig(ScenarioConfig&&) noexcept;
+ ScenarioConfig& operator=(ScenarioConfig&&);
+ ScenarioConfig(const ScenarioConfig&);
+ ScenarioConfig& operator=(const ScenarioConfig&);
+ bool operator==(const ScenarioConfig&) const;
+ bool operator!=(const ScenarioConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_scenario_name() const { return _has_field_[1]; }
+ const std::string& scenario_name() const { return scenario_name_; }
+ void set_scenario_name(const std::string& value) { scenario_name_ = value; _has_field_.set(1); }
+
+ const std::vector<TriggerRule>& start_rules() const { return start_rules_; }
+ std::vector<TriggerRule>* mutable_start_rules() { return &start_rules_; }
+ int start_rules_size() const;
+ void clear_start_rules();
+ TriggerRule* add_start_rules();
+
+ const std::vector<TriggerRule>& stop_rules() const { return stop_rules_; }
+ std::vector<TriggerRule>* mutable_stop_rules() { return &stop_rules_; }
+ int stop_rules_size() const;
+ void clear_stop_rules();
+ TriggerRule* add_stop_rules();
+
+ const std::vector<TriggerRule>& upload_rules() const { return upload_rules_; }
+ std::vector<TriggerRule>* mutable_upload_rules() { return &upload_rules_; }
+ int upload_rules_size() const;
+ void clear_upload_rules();
+ TriggerRule* add_upload_rules();
+
+ const std::vector<TriggerRule>& setup_rules() const { return setup_rules_; }
+ std::vector<TriggerRule>* mutable_setup_rules() { return &setup_rules_; }
+ int setup_rules_size() const;
+ void clear_setup_rules();
+ TriggerRule* add_setup_rules();
+
+ bool has_trace_config() const { return _has_field_[6]; }
+ const TraceConfig& trace_config() const { return *trace_config_; }
+ TraceConfig* mutable_trace_config() { _has_field_.set(6); return trace_config_.get(); }
+
+ const std::vector<NestedScenarioConfig>& nested_scenarios() const { return nested_scenarios_; }
+ std::vector<NestedScenarioConfig>* mutable_nested_scenarios() { return &nested_scenarios_; }
+ int nested_scenarios_size() const;
+ void clear_nested_scenarios();
+ NestedScenarioConfig* add_nested_scenarios();
+
+ private:
+ std::string scenario_name_{};
+ std::vector<TriggerRule> start_rules_;
+ std::vector<TriggerRule> stop_rules_;
+ std::vector<TriggerRule> upload_rules_;
+ std::vector<TriggerRule> setup_rules_;
+ ::protozero::CopyablePtr<TraceConfig> trace_config_;
+ std::vector<NestedScenarioConfig> nested_scenarios_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT NestedScenarioConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kScenarioNameFieldNumber = 1,
+ kStartRulesFieldNumber = 2,
+ kStopRulesFieldNumber = 3,
+ kUploadRulesFieldNumber = 4,
+ };
+
+ NestedScenarioConfig();
+ ~NestedScenarioConfig() override;
+ NestedScenarioConfig(NestedScenarioConfig&&) noexcept;
+ NestedScenarioConfig& operator=(NestedScenarioConfig&&);
+ NestedScenarioConfig(const NestedScenarioConfig&);
+ NestedScenarioConfig& operator=(const NestedScenarioConfig&);
+ bool operator==(const NestedScenarioConfig&) const;
+ bool operator!=(const NestedScenarioConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_scenario_name() const { return _has_field_[1]; }
+ const std::string& scenario_name() const { return scenario_name_; }
+ void set_scenario_name(const std::string& value) { scenario_name_ = value; _has_field_.set(1); }
+
+ const std::vector<TriggerRule>& start_rules() const { return start_rules_; }
+ std::vector<TriggerRule>* mutable_start_rules() { return &start_rules_; }
+ int start_rules_size() const;
+ void clear_start_rules();
+ TriggerRule* add_start_rules();
+
+ const std::vector<TriggerRule>& stop_rules() const { return stop_rules_; }
+ std::vector<TriggerRule>* mutable_stop_rules() { return &stop_rules_; }
+ int stop_rules_size() const;
+ void clear_stop_rules();
+ TriggerRule* add_stop_rules();
+
+ const std::vector<TriggerRule>& upload_rules() const { return upload_rules_; }
+ std::vector<TriggerRule>* mutable_upload_rules() { return &upload_rules_; }
+ int upload_rules_size() const;
+ void clear_upload_rules();
+ TriggerRule* add_upload_rules();
+
+ private:
+ std::string scenario_name_{};
+ std::vector<TriggerRule> start_rules_;
+ std::vector<TriggerRule> stop_rules_;
+ std::vector<TriggerRule> upload_rules_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_SCENARIO_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/chrome/v8_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_V8_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_V8_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class V8Config;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT V8Config : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kLogScriptSourcesFieldNumber = 1,
+ kLogInstructionsFieldNumber = 2,
+ };
+
+ V8Config();
+ ~V8Config() override;
+ V8Config(V8Config&&) noexcept;
+ V8Config& operator=(V8Config&&);
+ V8Config(const V8Config&);
+ V8Config& operator=(const V8Config&);
+ bool operator==(const V8Config&) const;
+ bool operator!=(const V8Config& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_log_script_sources() const { return _has_field_[1]; }
+ bool log_script_sources() const { return log_script_sources_; }
+ void set_log_script_sources(bool value) { log_script_sources_ = value; _has_field_.set(1); }
+
+ bool has_log_instructions() const { return _has_field_[2]; }
+ bool log_instructions() const { return log_instructions_; }
+ void set_log_instructions(bool value) { log_instructions_ = value; _has_field_.set(2); }
+
+ private:
+ bool log_script_sources_{};
+ bool log_instructions_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_V8_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/etw/etw_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ETW_ETW_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ETW_ETW_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class EtwConfig;
+enum EtwConfig_KernelFlag : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum EtwConfig_KernelFlag : int {
+ EtwConfig_KernelFlag_CSWITCH = 0,
+ EtwConfig_KernelFlag_DISPATCHER = 1,
+};
+
+class PERFETTO_EXPORT_COMPONENT EtwConfig : public ::protozero::CppMessageObj {
+ public:
+ using KernelFlag = EtwConfig_KernelFlag;
+ static constexpr auto CSWITCH = EtwConfig_KernelFlag_CSWITCH;
+ static constexpr auto DISPATCHER = EtwConfig_KernelFlag_DISPATCHER;
+ static constexpr auto KernelFlag_MIN = EtwConfig_KernelFlag_CSWITCH;
+ static constexpr auto KernelFlag_MAX = EtwConfig_KernelFlag_DISPATCHER;
+ enum FieldNumbers {
+ kKernelFlagsFieldNumber = 1,
+ };
+
+ EtwConfig();
+ ~EtwConfig() override;
+ EtwConfig(EtwConfig&&) noexcept;
+ EtwConfig& operator=(EtwConfig&&);
+ EtwConfig(const EtwConfig&);
+ EtwConfig& operator=(const EtwConfig&);
+ bool operator==(const EtwConfig&) const;
+ bool operator!=(const EtwConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<EtwConfig_KernelFlag>& kernel_flags() const { return kernel_flags_; }
+ std::vector<EtwConfig_KernelFlag>* mutable_kernel_flags() { return &kernel_flags_; }
+ int kernel_flags_size() const { return static_cast<int>(kernel_flags_.size()); }
+ void clear_kernel_flags() { kernel_flags_.clear(); }
+ void add_kernel_flags(EtwConfig_KernelFlag value) { kernel_flags_.emplace_back(value); }
+ EtwConfig_KernelFlag* add_kernel_flags() { kernel_flags_.emplace_back(); return &kernel_flags_.back(); }
+
+ private:
+ std::vector<EtwConfig_KernelFlag> kernel_flags_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ETW_ETW_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/interceptor_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class InterceptorConfig;
+class ConsoleConfig;
+enum ConsoleConfig_Output : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT InterceptorConfig : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ kConsoleConfigFieldNumber = 100,
+ };
+
+ InterceptorConfig();
+ ~InterceptorConfig() override;
+ InterceptorConfig(InterceptorConfig&&) noexcept;
+ InterceptorConfig& operator=(InterceptorConfig&&);
+ InterceptorConfig(const InterceptorConfig&);
+ InterceptorConfig& operator=(const InterceptorConfig&);
+ bool operator==(const InterceptorConfig&) const;
+ bool operator!=(const InterceptorConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ bool has_console_config() const { return _has_field_[100]; }
+ const ConsoleConfig& console_config() const { return *console_config_; }
+ ConsoleConfig* mutable_console_config() { _has_field_.set(100); return console_config_.get(); }
+
+ private:
+ std::string name_{};
+ ::protozero::CopyablePtr<ConsoleConfig> console_config_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<101> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/stress_test_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STRESS_TEST_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STRESS_TEST_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class StressTestConfig;
+class StressTestConfig_WriterTiming;
+class TraceConfig;
+class TraceConfig_CmdTraceStartDelay;
+class TraceConfig_AndroidReportConfig;
+class TraceConfig_TraceFilter;
+class TraceConfig_TraceFilter_StringFilterChain;
+class TraceConfig_TraceFilter_StringFilterRule;
+class TraceConfig_IncidentReportConfig;
+class TraceConfig_IncrementalStateConfig;
+class TraceConfig_TriggerConfig;
+class TraceConfig_TriggerConfig_Trigger;
+class TraceConfig_GuardrailOverrides;
+class TraceConfig_StatsdMetadata;
+class TraceConfig_ProducerConfig;
+class TraceConfig_BuiltinDataSource;
+class TraceConfig_DataSource;
+class DataSourceConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+class InterceptorConfig;
+class ConsoleConfig;
+class ChromeConfig;
+class SystemInfoConfig;
+class TraceConfig_BufferConfig;
+enum TraceConfig_LockdownModeOperation : int;
+enum TraceConfig_CompressionType : int;
+enum TraceConfig_StatsdLogging : int;
+enum TraceConfig_TraceFilter_StringFilterPolicy : int;
+enum TraceConfig_TriggerConfig_TriggerMode : int;
+enum BuiltinClock : int;
+enum DataSourceConfig_SessionInitiator : int;
+enum ConsoleConfig_Output : int;
+enum ChromeConfig_ClientPriority : int;
+enum TraceConfig_BufferConfig_FillPolicy : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT StressTestConfig : public ::protozero::CppMessageObj {
+ public:
+ using WriterTiming = StressTestConfig_WriterTiming;
+ enum FieldNumbers {
+ kTraceConfigFieldNumber = 1,
+ kShmemSizeKbFieldNumber = 2,
+ kShmemPageSizeKbFieldNumber = 3,
+ kNumProcessesFieldNumber = 4,
+ kNumThreadsFieldNumber = 5,
+ kMaxEventsFieldNumber = 6,
+ kNestingFieldNumber = 7,
+ kSteadyStateTimingsFieldNumber = 8,
+ kBurstPeriodMsFieldNumber = 9,
+ kBurstDurationMsFieldNumber = 10,
+ kBurstTimingsFieldNumber = 11,
+ };
+
+ StressTestConfig();
+ ~StressTestConfig() override;
+ StressTestConfig(StressTestConfig&&) noexcept;
+ StressTestConfig& operator=(StressTestConfig&&);
+ StressTestConfig(const StressTestConfig&);
+ StressTestConfig& operator=(const StressTestConfig&);
+ bool operator==(const StressTestConfig&) const;
+ bool operator!=(const StressTestConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_config() const { return _has_field_[1]; }
+ const TraceConfig& trace_config() const { return *trace_config_; }
+ TraceConfig* mutable_trace_config() { _has_field_.set(1); return trace_config_.get(); }
+
+ bool has_shmem_size_kb() const { return _has_field_[2]; }
+ uint32_t shmem_size_kb() const { return shmem_size_kb_; }
+ void set_shmem_size_kb(uint32_t value) { shmem_size_kb_ = value; _has_field_.set(2); }
+
+ bool has_shmem_page_size_kb() const { return _has_field_[3]; }
+ uint32_t shmem_page_size_kb() const { return shmem_page_size_kb_; }
+ void set_shmem_page_size_kb(uint32_t value) { shmem_page_size_kb_ = value; _has_field_.set(3); }
+
+ bool has_num_processes() const { return _has_field_[4]; }
+ uint32_t num_processes() const { return num_processes_; }
+ void set_num_processes(uint32_t value) { num_processes_ = value; _has_field_.set(4); }
+
+ bool has_num_threads() const { return _has_field_[5]; }
+ uint32_t num_threads() const { return num_threads_; }
+ void set_num_threads(uint32_t value) { num_threads_ = value; _has_field_.set(5); }
+
+ bool has_max_events() const { return _has_field_[6]; }
+ uint32_t max_events() const { return max_events_; }
+ void set_max_events(uint32_t value) { max_events_ = value; _has_field_.set(6); }
+
+ bool has_nesting() const { return _has_field_[7]; }
+ uint32_t nesting() const { return nesting_; }
+ void set_nesting(uint32_t value) { nesting_ = value; _has_field_.set(7); }
+
+ bool has_steady_state_timings() const { return _has_field_[8]; }
+ const StressTestConfig_WriterTiming& steady_state_timings() const { return *steady_state_timings_; }
+ StressTestConfig_WriterTiming* mutable_steady_state_timings() { _has_field_.set(8); return steady_state_timings_.get(); }
+
+ bool has_burst_period_ms() const { return _has_field_[9]; }
+ uint32_t burst_period_ms() const { return burst_period_ms_; }
+ void set_burst_period_ms(uint32_t value) { burst_period_ms_ = value; _has_field_.set(9); }
+
+ bool has_burst_duration_ms() const { return _has_field_[10]; }
+ uint32_t burst_duration_ms() const { return burst_duration_ms_; }
+ void set_burst_duration_ms(uint32_t value) { burst_duration_ms_ = value; _has_field_.set(10); }
+
+ bool has_burst_timings() const { return _has_field_[11]; }
+ const StressTestConfig_WriterTiming& burst_timings() const { return *burst_timings_; }
+ StressTestConfig_WriterTiming* mutable_burst_timings() { _has_field_.set(11); return burst_timings_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<TraceConfig> trace_config_;
+ uint32_t shmem_size_kb_{};
+ uint32_t shmem_page_size_kb_{};
+ uint32_t num_processes_{};
+ uint32_t num_threads_{};
+ uint32_t max_events_{};
+ uint32_t nesting_{};
+ ::protozero::CopyablePtr<StressTestConfig_WriterTiming> steady_state_timings_;
+ uint32_t burst_period_ms_{};
+ uint32_t burst_duration_ms_{};
+ ::protozero::CopyablePtr<StressTestConfig_WriterTiming> burst_timings_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<12> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT StressTestConfig_WriterTiming : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPayloadMeanFieldNumber = 1,
+ kPayloadStddevFieldNumber = 2,
+ kRateMeanFieldNumber = 3,
+ kRateStddevFieldNumber = 4,
+ kPayloadWriteTimeMsFieldNumber = 5,
+ };
+
+ StressTestConfig_WriterTiming();
+ ~StressTestConfig_WriterTiming() override;
+ StressTestConfig_WriterTiming(StressTestConfig_WriterTiming&&) noexcept;
+ StressTestConfig_WriterTiming& operator=(StressTestConfig_WriterTiming&&);
+ StressTestConfig_WriterTiming(const StressTestConfig_WriterTiming&);
+ StressTestConfig_WriterTiming& operator=(const StressTestConfig_WriterTiming&);
+ bool operator==(const StressTestConfig_WriterTiming&) const;
+ bool operator!=(const StressTestConfig_WriterTiming& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_payload_mean() const { return _has_field_[1]; }
+ double payload_mean() const { return payload_mean_; }
+ void set_payload_mean(double value) { payload_mean_ = value; _has_field_.set(1); }
+
+ bool has_payload_stddev() const { return _has_field_[2]; }
+ double payload_stddev() const { return payload_stddev_; }
+ void set_payload_stddev(double value) { payload_stddev_ = value; _has_field_.set(2); }
+
+ bool has_rate_mean() const { return _has_field_[3]; }
+ double rate_mean() const { return rate_mean_; }
+ void set_rate_mean(double value) { rate_mean_ = value; _has_field_.set(3); }
+
+ bool has_rate_stddev() const { return _has_field_[4]; }
+ double rate_stddev() const { return rate_stddev_; }
+ void set_rate_stddev(double value) { rate_stddev_ = value; _has_field_.set(4); }
+
+ bool has_payload_write_time_ms() const { return _has_field_[5]; }
+ uint32_t payload_write_time_ms() const { return payload_write_time_ms_; }
+ void set_payload_write_time_ms(uint32_t value) { payload_write_time_ms_ = value; _has_field_.set(5); }
+
+ private:
+ double payload_mean_{};
+ double payload_stddev_{};
+ double rate_mean_{};
+ double rate_stddev_{};
+ uint32_t payload_write_time_ms_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STRESS_TEST_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/test_config.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TEST_CONFIG_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TEST_CONFIG_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TestConfig;
+class TestConfig_DummyFields;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TestConfig : public ::protozero::CppMessageObj {
+ public:
+ using DummyFields = TestConfig_DummyFields;
+ enum FieldNumbers {
+ kMessageCountFieldNumber = 1,
+ kMaxMessagesPerSecondFieldNumber = 2,
+ kSeedFieldNumber = 3,
+ kMessageSizeFieldNumber = 4,
+ kSendBatchOnRegisterFieldNumber = 5,
+ kDummyFieldsFieldNumber = 6,
+ };
+
+ TestConfig();
+ ~TestConfig() override;
+ TestConfig(TestConfig&&) noexcept;
+ TestConfig& operator=(TestConfig&&);
+ TestConfig(const TestConfig&);
+ TestConfig& operator=(const TestConfig&);
+ bool operator==(const TestConfig&) const;
+ bool operator!=(const TestConfig& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_message_count() const { return _has_field_[1]; }
+ uint32_t message_count() const { return message_count_; }
+ void set_message_count(uint32_t value) { message_count_ = value; _has_field_.set(1); }
+
+ bool has_max_messages_per_second() const { return _has_field_[2]; }
+ uint32_t max_messages_per_second() const { return max_messages_per_second_; }
+ void set_max_messages_per_second(uint32_t value) { max_messages_per_second_ = value; _has_field_.set(2); }
+
+ bool has_seed() const { return _has_field_[3]; }
+ uint32_t seed() const { return seed_; }
+ void set_seed(uint32_t value) { seed_ = value; _has_field_.set(3); }
+
+ bool has_message_size() const { return _has_field_[4]; }
+ uint32_t message_size() const { return message_size_; }
+ void set_message_size(uint32_t value) { message_size_ = value; _has_field_.set(4); }
+
+ bool has_send_batch_on_register() const { return _has_field_[5]; }
+ bool send_batch_on_register() const { return send_batch_on_register_; }
+ void set_send_batch_on_register(bool value) { send_batch_on_register_ = value; _has_field_.set(5); }
+
+ bool has_dummy_fields() const { return _has_field_[6]; }
+ const TestConfig_DummyFields& dummy_fields() const { return *dummy_fields_; }
+ TestConfig_DummyFields* mutable_dummy_fields() { _has_field_.set(6); return dummy_fields_.get(); }
+
+ private:
+ uint32_t message_count_{};
+ uint32_t max_messages_per_second_{};
+ uint32_t seed_{};
+ uint32_t message_size_{};
+ bool send_batch_on_register_{};
+ ::protozero::CopyablePtr<TestConfig_DummyFields> dummy_fields_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TestConfig_DummyFields : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kFieldUint32FieldNumber = 1,
+ kFieldInt32FieldNumber = 2,
+ kFieldUint64FieldNumber = 3,
+ kFieldInt64FieldNumber = 4,
+ kFieldFixed64FieldNumber = 5,
+ kFieldSfixed64FieldNumber = 6,
+ kFieldFixed32FieldNumber = 7,
+ kFieldSfixed32FieldNumber = 8,
+ kFieldDoubleFieldNumber = 9,
+ kFieldFloatFieldNumber = 10,
+ kFieldSint64FieldNumber = 11,
+ kFieldSint32FieldNumber = 12,
+ kFieldStringFieldNumber = 13,
+ kFieldBytesFieldNumber = 14,
+ };
+
+ TestConfig_DummyFields();
+ ~TestConfig_DummyFields() override;
+ TestConfig_DummyFields(TestConfig_DummyFields&&) noexcept;
+ TestConfig_DummyFields& operator=(TestConfig_DummyFields&&);
+ TestConfig_DummyFields(const TestConfig_DummyFields&);
+ TestConfig_DummyFields& operator=(const TestConfig_DummyFields&);
+ bool operator==(const TestConfig_DummyFields&) const;
+ bool operator!=(const TestConfig_DummyFields& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_field_uint32() const { return _has_field_[1]; }
+ uint32_t field_uint32() const { return field_uint32_; }
+ void set_field_uint32(uint32_t value) { field_uint32_ = value; _has_field_.set(1); }
+
+ bool has_field_int32() const { return _has_field_[2]; }
+ int32_t field_int32() const { return field_int32_; }
+ void set_field_int32(int32_t value) { field_int32_ = value; _has_field_.set(2); }
+
+ bool has_field_uint64() const { return _has_field_[3]; }
+ uint64_t field_uint64() const { return field_uint64_; }
+ void set_field_uint64(uint64_t value) { field_uint64_ = value; _has_field_.set(3); }
+
+ bool has_field_int64() const { return _has_field_[4]; }
+ int64_t field_int64() const { return field_int64_; }
+ void set_field_int64(int64_t value) { field_int64_ = value; _has_field_.set(4); }
+
+ bool has_field_fixed64() const { return _has_field_[5]; }
+ uint64_t field_fixed64() const { return field_fixed64_; }
+ void set_field_fixed64(uint64_t value) { field_fixed64_ = value; _has_field_.set(5); }
+
+ bool has_field_sfixed64() const { return _has_field_[6]; }
+ int64_t field_sfixed64() const { return field_sfixed64_; }
+ void set_field_sfixed64(int64_t value) { field_sfixed64_ = value; _has_field_.set(6); }
+
+ bool has_field_fixed32() const { return _has_field_[7]; }
+ uint32_t field_fixed32() const { return field_fixed32_; }
+ void set_field_fixed32(uint32_t value) { field_fixed32_ = value; _has_field_.set(7); }
+
+ bool has_field_sfixed32() const { return _has_field_[8]; }
+ int32_t field_sfixed32() const { return field_sfixed32_; }
+ void set_field_sfixed32(int32_t value) { field_sfixed32_ = value; _has_field_.set(8); }
+
+ bool has_field_double() const { return _has_field_[9]; }
+ double field_double() const { return field_double_; }
+ void set_field_double(double value) { field_double_ = value; _has_field_.set(9); }
+
+ bool has_field_float() const { return _has_field_[10]; }
+ float field_float() const { return field_float_; }
+ void set_field_float(float value) { field_float_ = value; _has_field_.set(10); }
+
+ bool has_field_sint64() const { return _has_field_[11]; }
+ int64_t field_sint64() const { return field_sint64_; }
+ void set_field_sint64(int64_t value) { field_sint64_ = value; _has_field_.set(11); }
+
+ bool has_field_sint32() const { return _has_field_[12]; }
+ int32_t field_sint32() const { return field_sint32_; }
+ void set_field_sint32(int32_t value) { field_sint32_ = value; _has_field_.set(12); }
+
+ bool has_field_string() const { return _has_field_[13]; }
+ const std::string& field_string() const { return field_string_; }
+ void set_field_string(const std::string& value) { field_string_ = value; _has_field_.set(13); }
+
+ bool has_field_bytes() const { return _has_field_[14]; }
+ const std::string& field_bytes() const { return field_bytes_; }
+ void set_field_bytes(const std::string& value) { field_bytes_ = value; _has_field_.set(14); }
+ void set_field_bytes(const void* p, size_t s) { field_bytes_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(14); }
+
+ private:
+ uint32_t field_uint32_{};
+ int32_t field_int32_{};
+ uint64_t field_uint64_{};
+ int64_t field_int64_{};
+ uint64_t field_fixed64_{};
+ int64_t field_sfixed64_{};
+ uint32_t field_fixed32_{};
+ int32_t field_sfixed32_{};
+ double field_double_{};
+ float field_float_{};
+ int64_t field_sint64_{};
+ int32_t field_sint32_{};
+ std::string field_string_{};
+ std::string field_bytes_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<15> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TEST_CONFIG_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_game_intervention_list_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_GAME_INTERVENTION_LIST_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_GAME_INTERVENTION_LIST_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidGameInterventionListConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidGameInterventionListConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidGameInterventionListConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidGameInterventionListConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_package_name_filter() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> package_name_filter() const { return GetRepeated<::protozero::ConstChars>(1); }
+};
+
+class AndroidGameInterventionListConfig : public ::protozero::Message {
+ public:
+ using Decoder = AndroidGameInterventionListConfig_Decoder;
+ enum : int32_t {
+ kPackageNameFilterFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidGameInterventionListConfig"; }
+
+
+ using FieldMetadata_PackageNameFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidGameInterventionListConfig>;
+
+ static constexpr FieldMetadata_PackageNameFilter kPackageNameFilter{};
+ void add_package_name_filter(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_PackageNameFilter::kFieldId, data, size);
+ }
+ void add_package_name_filter(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_PackageNameFilter::kFieldId, chars.data, chars.size);
+ }
+ void add_package_name_filter(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_PackageNameFilter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_input_event_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_INPUT_EVENT_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_INPUT_EVENT_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidInputEventConfig_TraceRule;
+namespace perfetto_pbzero_enum_AndroidInputEventConfig {
+enum TraceLevel : int32_t;
+} // namespace perfetto_pbzero_enum_AndroidInputEventConfig
+using AndroidInputEventConfig_TraceLevel = perfetto_pbzero_enum_AndroidInputEventConfig::TraceLevel;
+namespace perfetto_pbzero_enum_AndroidInputEventConfig {
+enum TraceMode : int32_t;
+} // namespace perfetto_pbzero_enum_AndroidInputEventConfig
+using AndroidInputEventConfig_TraceMode = perfetto_pbzero_enum_AndroidInputEventConfig::TraceMode;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_AndroidInputEventConfig {
+enum TraceMode : int32_t {
+ TRACE_MODE_TRACE_ALL = 0,
+ TRACE_MODE_USE_RULES = 1,
+};
+} // namespace perfetto_pbzero_enum_AndroidInputEventConfig
+using AndroidInputEventConfig_TraceMode = perfetto_pbzero_enum_AndroidInputEventConfig::TraceMode;
+
+
+constexpr AndroidInputEventConfig_TraceMode AndroidInputEventConfig_TraceMode_MIN = AndroidInputEventConfig_TraceMode::TRACE_MODE_TRACE_ALL;
+constexpr AndroidInputEventConfig_TraceMode AndroidInputEventConfig_TraceMode_MAX = AndroidInputEventConfig_TraceMode::TRACE_MODE_USE_RULES;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* AndroidInputEventConfig_TraceMode_Name(::perfetto::protos::pbzero::AndroidInputEventConfig_TraceMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceMode::TRACE_MODE_TRACE_ALL:
+ return "TRACE_MODE_TRACE_ALL";
+
+ case ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceMode::TRACE_MODE_USE_RULES:
+ return "TRACE_MODE_USE_RULES";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_AndroidInputEventConfig {
+enum TraceLevel : int32_t {
+ TRACE_LEVEL_NONE = 0,
+ TRACE_LEVEL_REDACTED = 1,
+ TRACE_LEVEL_COMPLETE = 2,
+};
+} // namespace perfetto_pbzero_enum_AndroidInputEventConfig
+using AndroidInputEventConfig_TraceLevel = perfetto_pbzero_enum_AndroidInputEventConfig::TraceLevel;
+
+
+constexpr AndroidInputEventConfig_TraceLevel AndroidInputEventConfig_TraceLevel_MIN = AndroidInputEventConfig_TraceLevel::TRACE_LEVEL_NONE;
+constexpr AndroidInputEventConfig_TraceLevel AndroidInputEventConfig_TraceLevel_MAX = AndroidInputEventConfig_TraceLevel::TRACE_LEVEL_COMPLETE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* AndroidInputEventConfig_TraceLevel_Name(::perfetto::protos::pbzero::AndroidInputEventConfig_TraceLevel value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceLevel::TRACE_LEVEL_NONE:
+ return "TRACE_LEVEL_NONE";
+
+ case ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceLevel::TRACE_LEVEL_REDACTED:
+ return "TRACE_LEVEL_REDACTED";
+
+ case ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceLevel::TRACE_LEVEL_COMPLETE:
+ return "TRACE_LEVEL_COMPLETE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class AndroidInputEventConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidInputEventConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidInputEventConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidInputEventConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mode() const { return at<1>().valid(); }
+ int32_t mode() const { return at<1>().as_int32(); }
+ bool has_rules() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> rules() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_trace_dispatcher_input_events() const { return at<3>().valid(); }
+ bool trace_dispatcher_input_events() const { return at<3>().as_bool(); }
+ bool has_trace_dispatcher_window_dispatch() const { return at<4>().valid(); }
+ bool trace_dispatcher_window_dispatch() const { return at<4>().as_bool(); }
+};
+
+class AndroidInputEventConfig : public ::protozero::Message {
+ public:
+ using Decoder = AndroidInputEventConfig_Decoder;
+ enum : int32_t {
+ kModeFieldNumber = 1,
+ kRulesFieldNumber = 2,
+ kTraceDispatcherInputEventsFieldNumber = 3,
+ kTraceDispatcherWindowDispatchFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidInputEventConfig"; }
+
+ using TraceRule = ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceRule;
+
+ using TraceMode = ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceMode;
+ static inline const char* TraceMode_Name(TraceMode value) {
+ return ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceMode_Name(value);
+ }
+
+ using TraceLevel = ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceLevel;
+ static inline const char* TraceLevel_Name(TraceLevel value) {
+ return ::perfetto::protos::pbzero::AndroidInputEventConfig_TraceLevel_Name(value);
+ }
+ static inline const TraceMode TRACE_MODE_TRACE_ALL = TraceMode::TRACE_MODE_TRACE_ALL;
+ static inline const TraceMode TRACE_MODE_USE_RULES = TraceMode::TRACE_MODE_USE_RULES;
+ static inline const TraceLevel TRACE_LEVEL_NONE = TraceLevel::TRACE_LEVEL_NONE;
+ static inline const TraceLevel TRACE_LEVEL_REDACTED = TraceLevel::TRACE_LEVEL_REDACTED;
+ static inline const TraceLevel TRACE_LEVEL_COMPLETE = TraceLevel::TRACE_LEVEL_COMPLETE;
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidInputEventConfig_TraceMode,
+ AndroidInputEventConfig>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(AndroidInputEventConfig_TraceMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rules =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidInputEventConfig_TraceRule,
+ AndroidInputEventConfig>;
+
+ static constexpr FieldMetadata_Rules kRules{};
+ template <typename T = AndroidInputEventConfig_TraceRule> T* add_rules() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_TraceDispatcherInputEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidInputEventConfig>;
+
+ static constexpr FieldMetadata_TraceDispatcherInputEvents kTraceDispatcherInputEvents{};
+ void set_trace_dispatcher_input_events(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceDispatcherInputEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceDispatcherWindowDispatch =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidInputEventConfig>;
+
+ static constexpr FieldMetadata_TraceDispatcherWindowDispatch kTraceDispatcherWindowDispatch{};
+ void set_trace_dispatcher_window_dispatch(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceDispatcherWindowDispatch::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidInputEventConfig_TraceRule_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidInputEventConfig_TraceRule_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidInputEventConfig_TraceRule_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidInputEventConfig_TraceRule_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trace_level() const { return at<1>().valid(); }
+ int32_t trace_level() const { return at<1>().as_int32(); }
+ bool has_match_all_packages() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> match_all_packages() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_match_any_packages() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> match_any_packages() const { return GetRepeated<::protozero::ConstChars>(3); }
+ bool has_match_secure() const { return at<4>().valid(); }
+ bool match_secure() const { return at<4>().as_bool(); }
+ bool has_match_ime_connection_active() const { return at<5>().valid(); }
+ bool match_ime_connection_active() const { return at<5>().as_bool(); }
+};
+
+class AndroidInputEventConfig_TraceRule : public ::protozero::Message {
+ public:
+ using Decoder = AndroidInputEventConfig_TraceRule_Decoder;
+ enum : int32_t {
+ kTraceLevelFieldNumber = 1,
+ kMatchAllPackagesFieldNumber = 2,
+ kMatchAnyPackagesFieldNumber = 3,
+ kMatchSecureFieldNumber = 4,
+ kMatchImeConnectionActiveFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidInputEventConfig.TraceRule"; }
+
+
+ using FieldMetadata_TraceLevel =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidInputEventConfig_TraceLevel,
+ AndroidInputEventConfig_TraceRule>;
+
+ static constexpr FieldMetadata_TraceLevel kTraceLevel{};
+ void set_trace_level(AndroidInputEventConfig_TraceLevel value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceLevel::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MatchAllPackages =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidInputEventConfig_TraceRule>;
+
+ static constexpr FieldMetadata_MatchAllPackages kMatchAllPackages{};
+ void add_match_all_packages(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_MatchAllPackages::kFieldId, data, size);
+ }
+ void add_match_all_packages(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_MatchAllPackages::kFieldId, chars.data, chars.size);
+ }
+ void add_match_all_packages(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MatchAllPackages::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MatchAnyPackages =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidInputEventConfig_TraceRule>;
+
+ static constexpr FieldMetadata_MatchAnyPackages kMatchAnyPackages{};
+ void add_match_any_packages(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_MatchAnyPackages::kFieldId, data, size);
+ }
+ void add_match_any_packages(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_MatchAnyPackages::kFieldId, chars.data, chars.size);
+ }
+ void add_match_any_packages(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MatchAnyPackages::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MatchSecure =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidInputEventConfig_TraceRule>;
+
+ static constexpr FieldMetadata_MatchSecure kMatchSecure{};
+ void set_match_secure(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_MatchSecure::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MatchImeConnectionActive =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidInputEventConfig_TraceRule>;
+
+ static constexpr FieldMetadata_MatchImeConnectionActive kMatchImeConnectionActive{};
+ void set_match_ime_connection_active(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_MatchImeConnectionActive::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_log_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_LOG_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_LOG_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+enum AndroidLogId : int32_t;
+enum AndroidLogPriority : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidLogConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidLogConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidLogConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidLogConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_log_ids() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> log_ids() const { return GetRepeated<int32_t>(1); }
+ bool has_min_prio() const { return at<3>().valid(); }
+ int32_t min_prio() const { return at<3>().as_int32(); }
+ bool has_filter_tags() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> filter_tags() const { return GetRepeated<::protozero::ConstChars>(4); }
+};
+
+class AndroidLogConfig : public ::protozero::Message {
+ public:
+ using Decoder = AndroidLogConfig_Decoder;
+ enum : int32_t {
+ kLogIdsFieldNumber = 1,
+ kMinPrioFieldNumber = 3,
+ kFilterTagsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidLogConfig"; }
+
+
+ using FieldMetadata_LogIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidLogId,
+ AndroidLogConfig>;
+
+ static constexpr FieldMetadata_LogIds kLogIds{};
+ void add_log_ids(AndroidLogId value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MinPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidLogPriority,
+ AndroidLogConfig>;
+
+ static constexpr FieldMetadata_MinPrio kMinPrio{};
+ void set_min_prio(AndroidLogPriority value) {
+ static constexpr uint32_t field_id = FieldMetadata_MinPrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FilterTags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidLogConfig>;
+
+ static constexpr FieldMetadata_FilterTags kFilterTags{};
+ void add_filter_tags(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FilterTags::kFieldId, data, size);
+ }
+ void add_filter_tags(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FilterTags::kFieldId, chars.data, chars.size);
+ }
+ void add_filter_tags(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FilterTags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_polled_state_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_POLLED_STATE_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_POLLED_STATE_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidPolledStateConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidPolledStateConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidPolledStateConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidPolledStateConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_poll_ms() const { return at<1>().valid(); }
+ uint32_t poll_ms() const { return at<1>().as_uint32(); }
+};
+
+class AndroidPolledStateConfig : public ::protozero::Message {
+ public:
+ using Decoder = AndroidPolledStateConfig_Decoder;
+ enum : int32_t {
+ kPollMsFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidPolledStateConfig"; }
+
+
+ using FieldMetadata_PollMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidPolledStateConfig>;
+
+ static constexpr FieldMetadata_PollMs kPollMs{};
+ void set_poll_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PollMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_sdk_sysprop_guard_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SDK_SYSPROP_GUARD_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SDK_SYSPROP_GUARD_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidSdkSyspropGuardConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidSdkSyspropGuardConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidSdkSyspropGuardConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidSdkSyspropGuardConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_surfaceflinger_skia_track_events() const { return at<1>().valid(); }
+ bool surfaceflinger_skia_track_events() const { return at<1>().as_bool(); }
+ bool has_hwui_skia_track_events() const { return at<2>().valid(); }
+ bool hwui_skia_track_events() const { return at<2>().as_bool(); }
+ bool has_hwui_package_name_filter() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> hwui_package_name_filter() const { return GetRepeated<::protozero::ConstChars>(3); }
+};
+
+class AndroidSdkSyspropGuardConfig : public ::protozero::Message {
+ public:
+ using Decoder = AndroidSdkSyspropGuardConfig_Decoder;
+ enum : int32_t {
+ kSurfaceflingerSkiaTrackEventsFieldNumber = 1,
+ kHwuiSkiaTrackEventsFieldNumber = 2,
+ kHwuiPackageNameFilterFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidSdkSyspropGuardConfig"; }
+
+
+ using FieldMetadata_SurfaceflingerSkiaTrackEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidSdkSyspropGuardConfig>;
+
+ static constexpr FieldMetadata_SurfaceflingerSkiaTrackEvents kSurfaceflingerSkiaTrackEvents{};
+ void set_surfaceflinger_skia_track_events(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SurfaceflingerSkiaTrackEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwuiSkiaTrackEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidSdkSyspropGuardConfig>;
+
+ static constexpr FieldMetadata_HwuiSkiaTrackEvents kHwuiSkiaTrackEvents{};
+ void set_hwui_skia_track_events(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwuiSkiaTrackEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwuiPackageNameFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidSdkSyspropGuardConfig>;
+
+ static constexpr FieldMetadata_HwuiPackageNameFilter kHwuiPackageNameFilter{};
+ void add_hwui_package_name_filter(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HwuiPackageNameFilter::kFieldId, data, size);
+ }
+ void add_hwui_package_name_filter(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HwuiPackageNameFilter::kFieldId, chars.data, chars.size);
+ }
+ void add_hwui_package_name_filter(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwuiPackageNameFilter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/android_system_property_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SYSTEM_PROPERTY_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_ANDROID_SYSTEM_PROPERTY_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidSystemPropertyConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidSystemPropertyConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidSystemPropertyConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidSystemPropertyConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_poll_ms() const { return at<1>().valid(); }
+ uint32_t poll_ms() const { return at<1>().as_uint32(); }
+ bool has_property_name() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> property_name() const { return GetRepeated<::protozero::ConstChars>(2); }
+};
+
+class AndroidSystemPropertyConfig : public ::protozero::Message {
+ public:
+ using Decoder = AndroidSystemPropertyConfig_Decoder;
+ enum : int32_t {
+ kPollMsFieldNumber = 1,
+ kPropertyNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidSystemPropertyConfig"; }
+
+
+ using FieldMetadata_PollMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidSystemPropertyConfig>;
+
+ static constexpr FieldMetadata_PollMs kPollMs{};
+ void set_poll_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PollMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PropertyName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidSystemPropertyConfig>;
+
+ static constexpr FieldMetadata_PropertyName kPropertyName{};
+ void add_property_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_PropertyName::kFieldId, data, size);
+ }
+ void add_property_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_PropertyName::kFieldId, chars.data, chars.size);
+ }
+ void add_property_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_PropertyName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/network_trace_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_NETWORK_TRACE_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_NETWORK_TRACE_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class NetworkPacketTraceConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NetworkPacketTraceConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NetworkPacketTraceConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NetworkPacketTraceConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_poll_ms() const { return at<1>().valid(); }
+ uint32_t poll_ms() const { return at<1>().as_uint32(); }
+ bool has_aggregation_threshold() const { return at<2>().valid(); }
+ uint32_t aggregation_threshold() const { return at<2>().as_uint32(); }
+ bool has_intern_limit() const { return at<3>().valid(); }
+ uint32_t intern_limit() const { return at<3>().as_uint32(); }
+ bool has_drop_local_port() const { return at<4>().valid(); }
+ bool drop_local_port() const { return at<4>().as_bool(); }
+ bool has_drop_remote_port() const { return at<5>().valid(); }
+ bool drop_remote_port() const { return at<5>().as_bool(); }
+ bool has_drop_tcp_flags() const { return at<6>().valid(); }
+ bool drop_tcp_flags() const { return at<6>().as_bool(); }
+};
+
+class NetworkPacketTraceConfig : public ::protozero::Message {
+ public:
+ using Decoder = NetworkPacketTraceConfig_Decoder;
+ enum : int32_t {
+ kPollMsFieldNumber = 1,
+ kAggregationThresholdFieldNumber = 2,
+ kInternLimitFieldNumber = 3,
+ kDropLocalPortFieldNumber = 4,
+ kDropRemotePortFieldNumber = 5,
+ kDropTcpFlagsFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NetworkPacketTraceConfig"; }
+
+
+ using FieldMetadata_PollMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketTraceConfig>;
+
+ static constexpr FieldMetadata_PollMs kPollMs{};
+ void set_poll_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PollMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AggregationThreshold =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketTraceConfig>;
+
+ static constexpr FieldMetadata_AggregationThreshold kAggregationThreshold{};
+ void set_aggregation_threshold(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AggregationThreshold::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InternLimit =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketTraceConfig>;
+
+ static constexpr FieldMetadata_InternLimit kInternLimit{};
+ void set_intern_limit(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InternLimit::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DropLocalPort =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ NetworkPacketTraceConfig>;
+
+ static constexpr FieldMetadata_DropLocalPort kDropLocalPort{};
+ void set_drop_local_port(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DropLocalPort::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DropRemotePort =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ NetworkPacketTraceConfig>;
+
+ static constexpr FieldMetadata_DropRemotePort kDropRemotePort{};
+ void set_drop_remote_port(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DropRemotePort::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DropTcpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ NetworkPacketTraceConfig>;
+
+ static constexpr FieldMetadata_DropTcpFlags kDropTcpFlags{};
+ void set_drop_tcp_flags(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DropTcpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/packages_list_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PACKAGES_LIST_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PACKAGES_LIST_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class PackagesListConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ PackagesListConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PackagesListConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PackagesListConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_package_name_filter() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> package_name_filter() const { return GetRepeated<::protozero::ConstChars>(1); }
+};
+
+class PackagesListConfig : public ::protozero::Message {
+ public:
+ using Decoder = PackagesListConfig_Decoder;
+ enum : int32_t {
+ kPackageNameFilterFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PackagesListConfig"; }
+
+
+ using FieldMetadata_PackageNameFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PackagesListConfig>;
+
+ static constexpr FieldMetadata_PackageNameFilter kPackageNameFilter{};
+ void add_package_name_filter(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_PackageNameFilter::kFieldId, data, size);
+ }
+ void add_package_name_filter(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_PackageNameFilter::kFieldId, chars.data, chars.size);
+ }
+ void add_package_name_filter(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_PackageNameFilter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/protolog_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PROTOLOG_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_PROTOLOG_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ProtoLogGroup;
+namespace perfetto_pbzero_enum_ProtoLogConfig {
+enum TracingMode : int32_t;
+} // namespace perfetto_pbzero_enum_ProtoLogConfig
+using ProtoLogConfig_TracingMode = perfetto_pbzero_enum_ProtoLogConfig::TracingMode;
+enum ProtoLogLevel : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ProtoLogConfig {
+enum TracingMode : int32_t {
+ DEFAULT = 0,
+ ENABLE_ALL = 1,
+};
+} // namespace perfetto_pbzero_enum_ProtoLogConfig
+using ProtoLogConfig_TracingMode = perfetto_pbzero_enum_ProtoLogConfig::TracingMode;
+
+
+constexpr ProtoLogConfig_TracingMode ProtoLogConfig_TracingMode_MIN = ProtoLogConfig_TracingMode::DEFAULT;
+constexpr ProtoLogConfig_TracingMode ProtoLogConfig_TracingMode_MAX = ProtoLogConfig_TracingMode::ENABLE_ALL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ProtoLogConfig_TracingMode_Name(::perfetto::protos::pbzero::ProtoLogConfig_TracingMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ProtoLogConfig_TracingMode::DEFAULT:
+ return "DEFAULT";
+
+ case ::perfetto::protos::pbzero::ProtoLogConfig_TracingMode::ENABLE_ALL:
+ return "ENABLE_ALL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ProtoLogGroup_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProtoLogGroup_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProtoLogGroup_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProtoLogGroup_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_group_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars group_name() const { return at<1>().as_string(); }
+ bool has_log_from() const { return at<2>().valid(); }
+ int32_t log_from() const { return at<2>().as_int32(); }
+ bool has_collect_stacktrace() const { return at<3>().valid(); }
+ bool collect_stacktrace() const { return at<3>().as_bool(); }
+};
+
+class ProtoLogGroup : public ::protozero::Message {
+ public:
+ using Decoder = ProtoLogGroup_Decoder;
+ enum : int32_t {
+ kGroupNameFieldNumber = 1,
+ kLogFromFieldNumber = 2,
+ kCollectStacktraceFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProtoLogGroup"; }
+
+
+ using FieldMetadata_GroupName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProtoLogGroup>;
+
+ static constexpr FieldMetadata_GroupName kGroupName{};
+ void set_group_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_GroupName::kFieldId, data, size);
+ }
+ void set_group_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_GroupName::kFieldId, chars.data, chars.size);
+ }
+ void set_group_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_GroupName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LogFrom =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ProtoLogLevel,
+ ProtoLogGroup>;
+
+ static constexpr FieldMetadata_LogFrom kLogFrom{};
+ void set_log_from(ProtoLogLevel value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogFrom::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CollectStacktrace =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProtoLogGroup>;
+
+ static constexpr FieldMetadata_CollectStacktrace kCollectStacktrace{};
+ void set_collect_stacktrace(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CollectStacktrace::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProtoLogConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProtoLogConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProtoLogConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProtoLogConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_group_overrides() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> group_overrides() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_tracing_mode() const { return at<2>().valid(); }
+ int32_t tracing_mode() const { return at<2>().as_int32(); }
+};
+
+class ProtoLogConfig : public ::protozero::Message {
+ public:
+ using Decoder = ProtoLogConfig_Decoder;
+ enum : int32_t {
+ kGroupOverridesFieldNumber = 1,
+ kTracingModeFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProtoLogConfig"; }
+
+
+ using TracingMode = ::perfetto::protos::pbzero::ProtoLogConfig_TracingMode;
+ static inline const char* TracingMode_Name(TracingMode value) {
+ return ::perfetto::protos::pbzero::ProtoLogConfig_TracingMode_Name(value);
+ }
+ static inline const TracingMode DEFAULT = TracingMode::DEFAULT;
+ static inline const TracingMode ENABLE_ALL = TracingMode::ENABLE_ALL;
+
+ using FieldMetadata_GroupOverrides =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProtoLogGroup,
+ ProtoLogConfig>;
+
+ static constexpr FieldMetadata_GroupOverrides kGroupOverrides{};
+ template <typename T = ProtoLogGroup> T* add_group_overrides() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_TracingMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ProtoLogConfig_TracingMode,
+ ProtoLogConfig>;
+
+ static constexpr FieldMetadata_TracingMode kTracingMode{};
+ void set_tracing_mode(ProtoLogConfig_TracingMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/surfaceflinger_layers_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_LAYERS_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_LAYERS_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig {
+enum Mode : int32_t;
+} // namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig
+using SurfaceFlingerLayersConfig_Mode = perfetto_pbzero_enum_SurfaceFlingerLayersConfig::Mode;
+namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig {
+enum TraceFlag : int32_t;
+} // namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig
+using SurfaceFlingerLayersConfig_TraceFlag = perfetto_pbzero_enum_SurfaceFlingerLayersConfig::TraceFlag;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig {
+enum Mode : int32_t {
+ MODE_UNSPECIFIED = 0,
+ MODE_ACTIVE = 1,
+ MODE_GENERATED = 2,
+ MODE_DUMP = 3,
+ MODE_GENERATED_BUGREPORT_ONLY = 4,
+};
+} // namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig
+using SurfaceFlingerLayersConfig_Mode = perfetto_pbzero_enum_SurfaceFlingerLayersConfig::Mode;
+
+
+constexpr SurfaceFlingerLayersConfig_Mode SurfaceFlingerLayersConfig_Mode_MIN = SurfaceFlingerLayersConfig_Mode::MODE_UNSPECIFIED;
+constexpr SurfaceFlingerLayersConfig_Mode SurfaceFlingerLayersConfig_Mode_MAX = SurfaceFlingerLayersConfig_Mode::MODE_GENERATED_BUGREPORT_ONLY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* SurfaceFlingerLayersConfig_Mode_Name(::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode::MODE_UNSPECIFIED:
+ return "MODE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode::MODE_ACTIVE:
+ return "MODE_ACTIVE";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode::MODE_GENERATED:
+ return "MODE_GENERATED";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode::MODE_DUMP:
+ return "MODE_DUMP";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode::MODE_GENERATED_BUGREPORT_ONLY:
+ return "MODE_GENERATED_BUGREPORT_ONLY";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig {
+enum TraceFlag : int32_t {
+ TRACE_FLAG_UNSPECIFIED = 0,
+ TRACE_FLAG_INPUT = 2,
+ TRACE_FLAG_COMPOSITION = 4,
+ TRACE_FLAG_EXTRA = 8,
+ TRACE_FLAG_HWC = 16,
+ TRACE_FLAG_BUFFERS = 32,
+ TRACE_FLAG_VIRTUAL_DISPLAYS = 64,
+ TRACE_FLAG_ALL = 14,
+};
+} // namespace perfetto_pbzero_enum_SurfaceFlingerLayersConfig
+using SurfaceFlingerLayersConfig_TraceFlag = perfetto_pbzero_enum_SurfaceFlingerLayersConfig::TraceFlag;
+
+
+constexpr SurfaceFlingerLayersConfig_TraceFlag SurfaceFlingerLayersConfig_TraceFlag_MIN = SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_UNSPECIFIED;
+constexpr SurfaceFlingerLayersConfig_TraceFlag SurfaceFlingerLayersConfig_TraceFlag_MAX = SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_VIRTUAL_DISPLAYS;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* SurfaceFlingerLayersConfig_TraceFlag_Name(::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_UNSPECIFIED:
+ return "TRACE_FLAG_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_INPUT:
+ return "TRACE_FLAG_INPUT";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_COMPOSITION:
+ return "TRACE_FLAG_COMPOSITION";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_EXTRA:
+ return "TRACE_FLAG_EXTRA";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_HWC:
+ return "TRACE_FLAG_HWC";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_BUFFERS:
+ return "TRACE_FLAG_BUFFERS";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_VIRTUAL_DISPLAYS:
+ return "TRACE_FLAG_VIRTUAL_DISPLAYS";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag::TRACE_FLAG_ALL:
+ return "TRACE_FLAG_ALL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class SurfaceFlingerLayersConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ SurfaceFlingerLayersConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SurfaceFlingerLayersConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SurfaceFlingerLayersConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mode() const { return at<1>().valid(); }
+ int32_t mode() const { return at<1>().as_int32(); }
+ bool has_trace_flags() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> trace_flags() const { return GetRepeated<int32_t>(2); }
+};
+
+class SurfaceFlingerLayersConfig : public ::protozero::Message {
+ public:
+ using Decoder = SurfaceFlingerLayersConfig_Decoder;
+ enum : int32_t {
+ kModeFieldNumber = 1,
+ kTraceFlagsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SurfaceFlingerLayersConfig"; }
+
+
+ using Mode = ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode;
+ static inline const char* Mode_Name(Mode value) {
+ return ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_Mode_Name(value);
+ }
+
+ using TraceFlag = ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag;
+ static inline const char* TraceFlag_Name(TraceFlag value) {
+ return ::perfetto::protos::pbzero::SurfaceFlingerLayersConfig_TraceFlag_Name(value);
+ }
+ static inline const Mode MODE_UNSPECIFIED = Mode::MODE_UNSPECIFIED;
+ static inline const Mode MODE_ACTIVE = Mode::MODE_ACTIVE;
+ static inline const Mode MODE_GENERATED = Mode::MODE_GENERATED;
+ static inline const Mode MODE_DUMP = Mode::MODE_DUMP;
+ static inline const Mode MODE_GENERATED_BUGREPORT_ONLY = Mode::MODE_GENERATED_BUGREPORT_ONLY;
+ static inline const TraceFlag TRACE_FLAG_UNSPECIFIED = TraceFlag::TRACE_FLAG_UNSPECIFIED;
+ static inline const TraceFlag TRACE_FLAG_INPUT = TraceFlag::TRACE_FLAG_INPUT;
+ static inline const TraceFlag TRACE_FLAG_COMPOSITION = TraceFlag::TRACE_FLAG_COMPOSITION;
+ static inline const TraceFlag TRACE_FLAG_EXTRA = TraceFlag::TRACE_FLAG_EXTRA;
+ static inline const TraceFlag TRACE_FLAG_HWC = TraceFlag::TRACE_FLAG_HWC;
+ static inline const TraceFlag TRACE_FLAG_BUFFERS = TraceFlag::TRACE_FLAG_BUFFERS;
+ static inline const TraceFlag TRACE_FLAG_VIRTUAL_DISPLAYS = TraceFlag::TRACE_FLAG_VIRTUAL_DISPLAYS;
+ static inline const TraceFlag TRACE_FLAG_ALL = TraceFlag::TRACE_FLAG_ALL;
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ SurfaceFlingerLayersConfig_Mode,
+ SurfaceFlingerLayersConfig>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(SurfaceFlingerLayersConfig_Mode value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ SurfaceFlingerLayersConfig_TraceFlag,
+ SurfaceFlingerLayersConfig>;
+
+ static constexpr FieldMetadata_TraceFlags kTraceFlags{};
+ void add_trace_flags(SurfaceFlingerLayersConfig_TraceFlag value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/android/surfaceflinger_transactions_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_TRANSACTIONS_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ANDROID_SURFACEFLINGER_TRANSACTIONS_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_SurfaceFlingerTransactionsConfig {
+enum Mode : int32_t;
+} // namespace perfetto_pbzero_enum_SurfaceFlingerTransactionsConfig
+using SurfaceFlingerTransactionsConfig_Mode = perfetto_pbzero_enum_SurfaceFlingerTransactionsConfig::Mode;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_SurfaceFlingerTransactionsConfig {
+enum Mode : int32_t {
+ MODE_UNSPECIFIED = 0,
+ MODE_CONTINUOUS = 1,
+ MODE_ACTIVE = 2,
+};
+} // namespace perfetto_pbzero_enum_SurfaceFlingerTransactionsConfig
+using SurfaceFlingerTransactionsConfig_Mode = perfetto_pbzero_enum_SurfaceFlingerTransactionsConfig::Mode;
+
+
+constexpr SurfaceFlingerTransactionsConfig_Mode SurfaceFlingerTransactionsConfig_Mode_MIN = SurfaceFlingerTransactionsConfig_Mode::MODE_UNSPECIFIED;
+constexpr SurfaceFlingerTransactionsConfig_Mode SurfaceFlingerTransactionsConfig_Mode_MAX = SurfaceFlingerTransactionsConfig_Mode::MODE_ACTIVE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* SurfaceFlingerTransactionsConfig_Mode_Name(::perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig_Mode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig_Mode::MODE_UNSPECIFIED:
+ return "MODE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig_Mode::MODE_CONTINUOUS:
+ return "MODE_CONTINUOUS";
+
+ case ::perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig_Mode::MODE_ACTIVE:
+ return "MODE_ACTIVE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class SurfaceFlingerTransactionsConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SurfaceFlingerTransactionsConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SurfaceFlingerTransactionsConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SurfaceFlingerTransactionsConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mode() const { return at<1>().valid(); }
+ int32_t mode() const { return at<1>().as_int32(); }
+};
+
+class SurfaceFlingerTransactionsConfig : public ::protozero::Message {
+ public:
+ using Decoder = SurfaceFlingerTransactionsConfig_Decoder;
+ enum : int32_t {
+ kModeFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SurfaceFlingerTransactionsConfig"; }
+
+
+ using Mode = ::perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig_Mode;
+ static inline const char* Mode_Name(Mode value) {
+ return ::perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig_Mode_Name(value);
+ }
+ static inline const Mode MODE_UNSPECIFIED = Mode::MODE_UNSPECIFIED;
+ static inline const Mode MODE_CONTINUOUS = Mode::MODE_CONTINUOUS;
+ static inline const Mode MODE_ACTIVE = Mode::MODE_ACTIVE;
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ SurfaceFlingerTransactionsConfig_Mode,
+ SurfaceFlingerTransactionsConfig>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(SurfaceFlingerTransactionsConfig_Mode value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/ftrace/ftrace_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_FTRACE_FTRACE_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_FTRACE_FTRACE_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FtraceConfig_CompactSchedConfig;
+class FtraceConfig_PrintFilter;
+class FtraceConfig_PrintFilter_Rule;
+class FtraceConfig_PrintFilter_Rule_AtraceMessage;
+namespace perfetto_pbzero_enum_FtraceConfig {
+enum KsymsMemPolicy : int32_t;
+} // namespace perfetto_pbzero_enum_FtraceConfig
+using FtraceConfig_KsymsMemPolicy = perfetto_pbzero_enum_FtraceConfig::KsymsMemPolicy;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_FtraceConfig {
+enum KsymsMemPolicy : int32_t {
+ KSYMS_UNSPECIFIED = 0,
+ KSYMS_CLEANUP_ON_STOP = 1,
+ KSYMS_RETAIN = 2,
+};
+} // namespace perfetto_pbzero_enum_FtraceConfig
+using FtraceConfig_KsymsMemPolicy = perfetto_pbzero_enum_FtraceConfig::KsymsMemPolicy;
+
+
+constexpr FtraceConfig_KsymsMemPolicy FtraceConfig_KsymsMemPolicy_MIN = FtraceConfig_KsymsMemPolicy::KSYMS_UNSPECIFIED;
+constexpr FtraceConfig_KsymsMemPolicy FtraceConfig_KsymsMemPolicy_MAX = FtraceConfig_KsymsMemPolicy::KSYMS_RETAIN;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FtraceConfig_KsymsMemPolicy_Name(::perfetto::protos::pbzero::FtraceConfig_KsymsMemPolicy value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FtraceConfig_KsymsMemPolicy::KSYMS_UNSPECIFIED:
+ return "KSYMS_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::FtraceConfig_KsymsMemPolicy::KSYMS_CLEANUP_ON_STOP:
+ return "KSYMS_CLEANUP_ON_STOP";
+
+ case ::perfetto::protos::pbzero::FtraceConfig_KsymsMemPolicy::KSYMS_RETAIN:
+ return "KSYMS_RETAIN";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class FtraceConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/27, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FtraceConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ftrace_events() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> ftrace_events() const { return GetRepeated<::protozero::ConstChars>(1); }
+ bool has_atrace_categories() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> atrace_categories() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_atrace_apps() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> atrace_apps() const { return GetRepeated<::protozero::ConstChars>(3); }
+ bool has_buffer_size_kb() const { return at<10>().valid(); }
+ uint32_t buffer_size_kb() const { return at<10>().as_uint32(); }
+ bool has_drain_period_ms() const { return at<11>().valid(); }
+ uint32_t drain_period_ms() const { return at<11>().as_uint32(); }
+ bool has_drain_buffer_percent() const { return at<26>().valid(); }
+ uint32_t drain_buffer_percent() const { return at<26>().as_uint32(); }
+ bool has_compact_sched() const { return at<12>().valid(); }
+ ::protozero::ConstBytes compact_sched() const { return at<12>().as_bytes(); }
+ bool has_print_filter() const { return at<22>().valid(); }
+ ::protozero::ConstBytes print_filter() const { return at<22>().as_bytes(); }
+ bool has_symbolize_ksyms() const { return at<13>().valid(); }
+ bool symbolize_ksyms() const { return at<13>().as_bool(); }
+ bool has_ksyms_mem_policy() const { return at<17>().valid(); }
+ int32_t ksyms_mem_policy() const { return at<17>().as_int32(); }
+ bool has_initialize_ksyms_synchronously_for_testing() const { return at<14>().valid(); }
+ bool initialize_ksyms_synchronously_for_testing() const { return at<14>().as_bool(); }
+ bool has_throttle_rss_stat() const { return at<15>().valid(); }
+ bool throttle_rss_stat() const { return at<15>().as_bool(); }
+ bool has_disable_generic_events() const { return at<16>().valid(); }
+ bool disable_generic_events() const { return at<16>().as_bool(); }
+ bool has_syscall_events() const { return at<18>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> syscall_events() const { return GetRepeated<::protozero::ConstChars>(18); }
+ bool has_enable_function_graph() const { return at<19>().valid(); }
+ bool enable_function_graph() const { return at<19>().as_bool(); }
+ bool has_function_filters() const { return at<20>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> function_filters() const { return GetRepeated<::protozero::ConstChars>(20); }
+ bool has_function_graph_roots() const { return at<21>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> function_graph_roots() const { return GetRepeated<::protozero::ConstChars>(21); }
+ bool has_preserve_ftrace_buffer() const { return at<23>().valid(); }
+ bool preserve_ftrace_buffer() const { return at<23>().as_bool(); }
+ bool has_use_monotonic_raw_clock() const { return at<24>().valid(); }
+ bool use_monotonic_raw_clock() const { return at<24>().as_bool(); }
+ bool has_instance_name() const { return at<25>().valid(); }
+ ::protozero::ConstChars instance_name() const { return at<25>().as_string(); }
+ bool has_buffer_size_lower_bound() const { return at<27>().valid(); }
+ bool buffer_size_lower_bound() const { return at<27>().as_bool(); }
+};
+
+class FtraceConfig : public ::protozero::Message {
+ public:
+ using Decoder = FtraceConfig_Decoder;
+ enum : int32_t {
+ kFtraceEventsFieldNumber = 1,
+ kAtraceCategoriesFieldNumber = 2,
+ kAtraceAppsFieldNumber = 3,
+ kBufferSizeKbFieldNumber = 10,
+ kDrainPeriodMsFieldNumber = 11,
+ kDrainBufferPercentFieldNumber = 26,
+ kCompactSchedFieldNumber = 12,
+ kPrintFilterFieldNumber = 22,
+ kSymbolizeKsymsFieldNumber = 13,
+ kKsymsMemPolicyFieldNumber = 17,
+ kInitializeKsymsSynchronouslyForTestingFieldNumber = 14,
+ kThrottleRssStatFieldNumber = 15,
+ kDisableGenericEventsFieldNumber = 16,
+ kSyscallEventsFieldNumber = 18,
+ kEnableFunctionGraphFieldNumber = 19,
+ kFunctionFiltersFieldNumber = 20,
+ kFunctionGraphRootsFieldNumber = 21,
+ kPreserveFtraceBufferFieldNumber = 23,
+ kUseMonotonicRawClockFieldNumber = 24,
+ kInstanceNameFieldNumber = 25,
+ kBufferSizeLowerBoundFieldNumber = 27,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceConfig"; }
+
+ using CompactSchedConfig = ::perfetto::protos::pbzero::FtraceConfig_CompactSchedConfig;
+ using PrintFilter = ::perfetto::protos::pbzero::FtraceConfig_PrintFilter;
+
+ using KsymsMemPolicy = ::perfetto::protos::pbzero::FtraceConfig_KsymsMemPolicy;
+ static inline const char* KsymsMemPolicy_Name(KsymsMemPolicy value) {
+ return ::perfetto::protos::pbzero::FtraceConfig_KsymsMemPolicy_Name(value);
+ }
+ static inline const KsymsMemPolicy KSYMS_UNSPECIFIED = KsymsMemPolicy::KSYMS_UNSPECIFIED;
+ static inline const KsymsMemPolicy KSYMS_CLEANUP_ON_STOP = KsymsMemPolicy::KSYMS_CLEANUP_ON_STOP;
+ static inline const KsymsMemPolicy KSYMS_RETAIN = KsymsMemPolicy::KSYMS_RETAIN;
+
+ using FieldMetadata_FtraceEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_FtraceEvents kFtraceEvents{};
+ void add_ftrace_events(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FtraceEvents::kFieldId, data, size);
+ }
+ void add_ftrace_events(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FtraceEvents::kFieldId, chars.data, chars.size);
+ }
+ void add_ftrace_events(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FtraceEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AtraceCategories =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_AtraceCategories kAtraceCategories{};
+ void add_atrace_categories(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_AtraceCategories::kFieldId, data, size);
+ }
+ void add_atrace_categories(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_AtraceCategories::kFieldId, chars.data, chars.size);
+ }
+ void add_atrace_categories(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_AtraceCategories::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AtraceApps =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_AtraceApps kAtraceApps{};
+ void add_atrace_apps(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_AtraceApps::kFieldId, data, size);
+ }
+ void add_atrace_apps(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_AtraceApps::kFieldId, chars.data, chars.size);
+ }
+ void add_atrace_apps(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_AtraceApps::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BufferSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_BufferSizeKb kBufferSizeKb{};
+ void set_buffer_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DrainPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_DrainPeriodMs kDrainPeriodMs{};
+ void set_drain_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DrainPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DrainBufferPercent =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_DrainBufferPercent kDrainBufferPercent{};
+ void set_drain_buffer_percent(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DrainBufferPercent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CompactSched =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceConfig_CompactSchedConfig,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_CompactSched kCompactSched{};
+ template <typename T = FtraceConfig_CompactSchedConfig> T* set_compact_sched() {
+ return BeginNestedMessage<T>(12);
+ }
+
+
+ using FieldMetadata_PrintFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceConfig_PrintFilter,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_PrintFilter kPrintFilter{};
+ template <typename T = FtraceConfig_PrintFilter> T* set_print_filter() {
+ return BeginNestedMessage<T>(22);
+ }
+
+
+ using FieldMetadata_SymbolizeKsyms =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_SymbolizeKsyms kSymbolizeKsyms{};
+ void set_symbolize_ksyms(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SymbolizeKsyms::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KsymsMemPolicy =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FtraceConfig_KsymsMemPolicy,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_KsymsMemPolicy kKsymsMemPolicy{};
+ void set_ksyms_mem_policy(FtraceConfig_KsymsMemPolicy value) {
+ static constexpr uint32_t field_id = FieldMetadata_KsymsMemPolicy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InitializeKsymsSynchronouslyForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_InitializeKsymsSynchronouslyForTesting kInitializeKsymsSynchronouslyForTesting{};
+ void set_initialize_ksyms_synchronously_for_testing(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_InitializeKsymsSynchronouslyForTesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThrottleRssStat =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_ThrottleRssStat kThrottleRssStat{};
+ void set_throttle_rss_stat(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThrottleRssStat::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableGenericEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_DisableGenericEvents kDisableGenericEvents{};
+ void set_disable_generic_events(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableGenericEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SyscallEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_SyscallEvents kSyscallEvents{};
+ void add_syscall_events(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SyscallEvents::kFieldId, data, size);
+ }
+ void add_syscall_events(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SyscallEvents::kFieldId, chars.data, chars.size);
+ }
+ void add_syscall_events(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SyscallEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnableFunctionGraph =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_EnableFunctionGraph kEnableFunctionGraph{};
+ void set_enable_function_graph(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnableFunctionGraph::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FunctionFilters =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_FunctionFilters kFunctionFilters{};
+ void add_function_filters(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FunctionFilters::kFieldId, data, size);
+ }
+ void add_function_filters(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FunctionFilters::kFieldId, chars.data, chars.size);
+ }
+ void add_function_filters(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FunctionFilters::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FunctionGraphRoots =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_FunctionGraphRoots kFunctionGraphRoots{};
+ void add_function_graph_roots(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FunctionGraphRoots::kFieldId, data, size);
+ }
+ void add_function_graph_roots(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FunctionGraphRoots::kFieldId, chars.data, chars.size);
+ }
+ void add_function_graph_roots(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FunctionGraphRoots::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreserveFtraceBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_PreserveFtraceBuffer kPreserveFtraceBuffer{};
+ void set_preserve_ftrace_buffer(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreserveFtraceBuffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UseMonotonicRawClock =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_UseMonotonicRawClock kUseMonotonicRawClock{};
+ void set_use_monotonic_raw_clock(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_UseMonotonicRawClock::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstanceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_InstanceName kInstanceName{};
+ void set_instance_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_InstanceName::kFieldId, data, size);
+ }
+ void set_instance_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_InstanceName::kFieldId, chars.data, chars.size);
+ }
+ void set_instance_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstanceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BufferSizeLowerBound =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig>;
+
+ static constexpr FieldMetadata_BufferSizeLowerBound kBufferSizeLowerBound{};
+ void set_buffer_size_lower_bound(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferSizeLowerBound::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FtraceConfig_PrintFilter_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FtraceConfig_PrintFilter_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceConfig_PrintFilter_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceConfig_PrintFilter_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_rules() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> rules() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class FtraceConfig_PrintFilter : public ::protozero::Message {
+ public:
+ using Decoder = FtraceConfig_PrintFilter_Decoder;
+ enum : int32_t {
+ kRulesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceConfig.PrintFilter"; }
+
+ using Rule = ::perfetto::protos::pbzero::FtraceConfig_PrintFilter_Rule;
+
+ using FieldMetadata_Rules =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceConfig_PrintFilter_Rule,
+ FtraceConfig_PrintFilter>;
+
+ static constexpr FieldMetadata_Rules kRules{};
+ template <typename T = FtraceConfig_PrintFilter_Rule> T* add_rules() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class FtraceConfig_PrintFilter_Rule_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FtraceConfig_PrintFilter_Rule_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceConfig_PrintFilter_Rule_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceConfig_PrintFilter_Rule_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_prefix() const { return at<1>().valid(); }
+ ::protozero::ConstChars prefix() const { return at<1>().as_string(); }
+ bool has_atrace_msg() const { return at<3>().valid(); }
+ ::protozero::ConstBytes atrace_msg() const { return at<3>().as_bytes(); }
+ bool has_allow() const { return at<2>().valid(); }
+ bool allow() const { return at<2>().as_bool(); }
+};
+
+class FtraceConfig_PrintFilter_Rule : public ::protozero::Message {
+ public:
+ using Decoder = FtraceConfig_PrintFilter_Rule_Decoder;
+ enum : int32_t {
+ kPrefixFieldNumber = 1,
+ kAtraceMsgFieldNumber = 3,
+ kAllowFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceConfig.PrintFilter.Rule"; }
+
+ using AtraceMessage = ::perfetto::protos::pbzero::FtraceConfig_PrintFilter_Rule_AtraceMessage;
+
+ using FieldMetadata_Prefix =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig_PrintFilter_Rule>;
+
+ static constexpr FieldMetadata_Prefix kPrefix{};
+ void set_prefix(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Prefix::kFieldId, data, size);
+ }
+ void set_prefix(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Prefix::kFieldId, chars.data, chars.size);
+ }
+ void set_prefix(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prefix::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AtraceMsg =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceConfig_PrintFilter_Rule_AtraceMessage,
+ FtraceConfig_PrintFilter_Rule>;
+
+ static constexpr FieldMetadata_AtraceMsg kAtraceMsg{};
+ template <typename T = FtraceConfig_PrintFilter_Rule_AtraceMessage> T* set_atrace_msg() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_Allow =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig_PrintFilter_Rule>;
+
+ static constexpr FieldMetadata_Allow kAllow{};
+ void set_allow(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Allow::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FtraceConfig_PrintFilter_Rule_AtraceMessage_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FtraceConfig_PrintFilter_Rule_AtraceMessage_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceConfig_PrintFilter_Rule_AtraceMessage_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceConfig_PrintFilter_Rule_AtraceMessage_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_type() const { return at<1>().valid(); }
+ ::protozero::ConstChars type() const { return at<1>().as_string(); }
+ bool has_prefix() const { return at<2>().valid(); }
+ ::protozero::ConstChars prefix() const { return at<2>().as_string(); }
+};
+
+class FtraceConfig_PrintFilter_Rule_AtraceMessage : public ::protozero::Message {
+ public:
+ using Decoder = FtraceConfig_PrintFilter_Rule_AtraceMessage_Decoder;
+ enum : int32_t {
+ kTypeFieldNumber = 1,
+ kPrefixFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceConfig.PrintFilter.Rule.AtraceMessage"; }
+
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig_PrintFilter_Rule_AtraceMessage>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Type::kFieldId, data, size);
+ }
+ void set_type(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Type::kFieldId, chars.data, chars.size);
+ }
+ void set_type(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prefix =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceConfig_PrintFilter_Rule_AtraceMessage>;
+
+ static constexpr FieldMetadata_Prefix kPrefix{};
+ void set_prefix(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Prefix::kFieldId, data, size);
+ }
+ void set_prefix(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Prefix::kFieldId, chars.data, chars.size);
+ }
+ void set_prefix(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prefix::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FtraceConfig_CompactSchedConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FtraceConfig_CompactSchedConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceConfig_CompactSchedConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceConfig_CompactSchedConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_enabled() const { return at<1>().valid(); }
+ bool enabled() const { return at<1>().as_bool(); }
+};
+
+class FtraceConfig_CompactSchedConfig : public ::protozero::Message {
+ public:
+ using Decoder = FtraceConfig_CompactSchedConfig_Decoder;
+ enum : int32_t {
+ kEnabledFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceConfig.CompactSchedConfig"; }
+
+
+ using FieldMetadata_Enabled =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceConfig_CompactSchedConfig>;
+
+ static constexpr FieldMetadata_Enabled kEnabled{};
+ void set_enabled(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Enabled::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/gpu/gpu_counter_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_GPU_COUNTER_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_GPU_COUNTER_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class GpuCounterConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GpuCounterConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuCounterConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuCounterConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_counter_period_ns() const { return at<1>().valid(); }
+ uint64_t counter_period_ns() const { return at<1>().as_uint64(); }
+ bool has_counter_ids() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> counter_ids() const { return GetRepeated<uint32_t>(2); }
+ bool has_instrumented_sampling() const { return at<3>().valid(); }
+ bool instrumented_sampling() const { return at<3>().as_bool(); }
+ bool has_fix_gpu_clock() const { return at<4>().valid(); }
+ bool fix_gpu_clock() const { return at<4>().as_bool(); }
+};
+
+class GpuCounterConfig : public ::protozero::Message {
+ public:
+ using Decoder = GpuCounterConfig_Decoder;
+ enum : int32_t {
+ kCounterPeriodNsFieldNumber = 1,
+ kCounterIdsFieldNumber = 2,
+ kInstrumentedSamplingFieldNumber = 3,
+ kFixGpuClockFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuCounterConfig"; }
+
+
+ using FieldMetadata_CounterPeriodNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuCounterConfig>;
+
+ static constexpr FieldMetadata_CounterPeriodNs kCounterPeriodNs{};
+ void set_counter_period_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterPeriodNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CounterIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuCounterConfig>;
+
+ static constexpr FieldMetadata_CounterIds kCounterIds{};
+ void add_counter_ids(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstrumentedSampling =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ GpuCounterConfig>;
+
+ static constexpr FieldMetadata_InstrumentedSampling kInstrumentedSampling{};
+ void set_instrumented_sampling(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstrumentedSampling::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FixGpuClock =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ GpuCounterConfig>;
+
+ static constexpr FieldMetadata_FixGpuClock kFixGpuClock{};
+ void set_fix_gpu_clock(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_FixGpuClock::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/gpu/vulkan_memory_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_VULKAN_MEMORY_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_GPU_VULKAN_MEMORY_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class VulkanMemoryConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VulkanMemoryConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VulkanMemoryConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VulkanMemoryConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_track_driver_memory_usage() const { return at<1>().valid(); }
+ bool track_driver_memory_usage() const { return at<1>().as_bool(); }
+ bool has_track_device_memory_usage() const { return at<2>().valid(); }
+ bool track_device_memory_usage() const { return at<2>().as_bool(); }
+};
+
+class VulkanMemoryConfig : public ::protozero::Message {
+ public:
+ using Decoder = VulkanMemoryConfig_Decoder;
+ enum : int32_t {
+ kTrackDriverMemoryUsageFieldNumber = 1,
+ kTrackDeviceMemoryUsageFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VulkanMemoryConfig"; }
+
+
+ using FieldMetadata_TrackDriverMemoryUsage =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ VulkanMemoryConfig>;
+
+ static constexpr FieldMetadata_TrackDriverMemoryUsage kTrackDriverMemoryUsage{};
+ void set_track_driver_memory_usage(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrackDriverMemoryUsage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TrackDeviceMemoryUsage =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ VulkanMemoryConfig>;
+
+ static constexpr FieldMetadata_TrackDeviceMemoryUsage kTrackDeviceMemoryUsage{};
+ void set_track_device_memory_usage(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrackDeviceMemoryUsage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/inode_file/inode_file_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INODE_FILE_INODE_FILE_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INODE_FILE_INODE_FILE_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class InodeFileConfig_MountPointMappingEntry;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class InodeFileConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ InodeFileConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InodeFileConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InodeFileConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_scan_interval_ms() const { return at<1>().valid(); }
+ uint32_t scan_interval_ms() const { return at<1>().as_uint32(); }
+ bool has_scan_delay_ms() const { return at<2>().valid(); }
+ uint32_t scan_delay_ms() const { return at<2>().as_uint32(); }
+ bool has_scan_batch_size() const { return at<3>().valid(); }
+ uint32_t scan_batch_size() const { return at<3>().as_uint32(); }
+ bool has_do_not_scan() const { return at<4>().valid(); }
+ bool do_not_scan() const { return at<4>().as_bool(); }
+ bool has_scan_mount_points() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> scan_mount_points() const { return GetRepeated<::protozero::ConstChars>(5); }
+ bool has_mount_point_mapping() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> mount_point_mapping() const { return GetRepeated<::protozero::ConstBytes>(6); }
+};
+
+class InodeFileConfig : public ::protozero::Message {
+ public:
+ using Decoder = InodeFileConfig_Decoder;
+ enum : int32_t {
+ kScanIntervalMsFieldNumber = 1,
+ kScanDelayMsFieldNumber = 2,
+ kScanBatchSizeFieldNumber = 3,
+ kDoNotScanFieldNumber = 4,
+ kScanMountPointsFieldNumber = 5,
+ kMountPointMappingFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InodeFileConfig"; }
+
+ using MountPointMappingEntry = ::perfetto::protos::pbzero::InodeFileConfig_MountPointMappingEntry;
+
+ using FieldMetadata_ScanIntervalMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InodeFileConfig>;
+
+ static constexpr FieldMetadata_ScanIntervalMs kScanIntervalMs{};
+ void set_scan_interval_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanIntervalMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanDelayMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InodeFileConfig>;
+
+ static constexpr FieldMetadata_ScanDelayMs kScanDelayMs{};
+ void set_scan_delay_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanDelayMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanBatchSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InodeFileConfig>;
+
+ static constexpr FieldMetadata_ScanBatchSize kScanBatchSize{};
+ void set_scan_batch_size(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanBatchSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoNotScan =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InodeFileConfig>;
+
+ static constexpr FieldMetadata_DoNotScan kDoNotScan{};
+ void set_do_not_scan(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoNotScan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanMountPoints =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InodeFileConfig>;
+
+ static constexpr FieldMetadata_ScanMountPoints kScanMountPoints{};
+ void add_scan_mount_points(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ScanMountPoints::kFieldId, data, size);
+ }
+ void add_scan_mount_points(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ScanMountPoints::kFieldId, chars.data, chars.size);
+ }
+ void add_scan_mount_points(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanMountPoints::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MountPointMapping =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InodeFileConfig_MountPointMappingEntry,
+ InodeFileConfig>;
+
+ static constexpr FieldMetadata_MountPointMapping kMountPointMapping{};
+ template <typename T = InodeFileConfig_MountPointMappingEntry> T* add_mount_point_mapping() {
+ return BeginNestedMessage<T>(6);
+ }
+
+};
+
+class InodeFileConfig_MountPointMappingEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ InodeFileConfig_MountPointMappingEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InodeFileConfig_MountPointMappingEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InodeFileConfig_MountPointMappingEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mountpoint() const { return at<1>().valid(); }
+ ::protozero::ConstChars mountpoint() const { return at<1>().as_string(); }
+ bool has_scan_roots() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> scan_roots() const { return GetRepeated<::protozero::ConstChars>(2); }
+};
+
+class InodeFileConfig_MountPointMappingEntry : public ::protozero::Message {
+ public:
+ using Decoder = InodeFileConfig_MountPointMappingEntry_Decoder;
+ enum : int32_t {
+ kMountpointFieldNumber = 1,
+ kScanRootsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InodeFileConfig.MountPointMappingEntry"; }
+
+
+ using FieldMetadata_Mountpoint =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InodeFileConfig_MountPointMappingEntry>;
+
+ static constexpr FieldMetadata_Mountpoint kMountpoint{};
+ void set_mountpoint(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Mountpoint::kFieldId, data, size);
+ }
+ void set_mountpoint(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Mountpoint::kFieldId, chars.data, chars.size);
+ }
+ void set_mountpoint(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mountpoint::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanRoots =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InodeFileConfig_MountPointMappingEntry>;
+
+ static constexpr FieldMetadata_ScanRoots kScanRoots{};
+ void add_scan_roots(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ScanRoots::kFieldId, data, size);
+ }
+ void add_scan_roots(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ScanRoots::kFieldId, chars.data, chars.size);
+ }
+ void add_scan_roots(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanRoots::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/interceptors/console_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTORS_CONSOLE_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTORS_CONSOLE_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ConsoleConfig {
+enum Output : int32_t;
+} // namespace perfetto_pbzero_enum_ConsoleConfig
+using ConsoleConfig_Output = perfetto_pbzero_enum_ConsoleConfig::Output;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ConsoleConfig {
+enum Output : int32_t {
+ OUTPUT_UNSPECIFIED = 0,
+ OUTPUT_STDOUT = 1,
+ OUTPUT_STDERR = 2,
+};
+} // namespace perfetto_pbzero_enum_ConsoleConfig
+using ConsoleConfig_Output = perfetto_pbzero_enum_ConsoleConfig::Output;
+
+
+constexpr ConsoleConfig_Output ConsoleConfig_Output_MIN = ConsoleConfig_Output::OUTPUT_UNSPECIFIED;
+constexpr ConsoleConfig_Output ConsoleConfig_Output_MAX = ConsoleConfig_Output::OUTPUT_STDERR;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ConsoleConfig_Output_Name(::perfetto::protos::pbzero::ConsoleConfig_Output value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ConsoleConfig_Output::OUTPUT_UNSPECIFIED:
+ return "OUTPUT_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ConsoleConfig_Output::OUTPUT_STDOUT:
+ return "OUTPUT_STDOUT";
+
+ case ::perfetto::protos::pbzero::ConsoleConfig_Output::OUTPUT_STDERR:
+ return "OUTPUT_STDERR";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ConsoleConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ConsoleConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ConsoleConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ConsoleConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_output() const { return at<1>().valid(); }
+ int32_t output() const { return at<1>().as_int32(); }
+ bool has_enable_colors() const { return at<2>().valid(); }
+ bool enable_colors() const { return at<2>().as_bool(); }
+};
+
+class ConsoleConfig : public ::protozero::Message {
+ public:
+ using Decoder = ConsoleConfig_Decoder;
+ enum : int32_t {
+ kOutputFieldNumber = 1,
+ kEnableColorsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ConsoleConfig"; }
+
+
+ using Output = ::perfetto::protos::pbzero::ConsoleConfig_Output;
+ static inline const char* Output_Name(Output value) {
+ return ::perfetto::protos::pbzero::ConsoleConfig_Output_Name(value);
+ }
+ static inline const Output OUTPUT_UNSPECIFIED = Output::OUTPUT_UNSPECIFIED;
+ static inline const Output OUTPUT_STDOUT = Output::OUTPUT_STDOUT;
+ static inline const Output OUTPUT_STDERR = Output::OUTPUT_STDERR;
+
+ using FieldMetadata_Output =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ConsoleConfig_Output,
+ ConsoleConfig>;
+
+ static constexpr FieldMetadata_Output kOutput{};
+ void set_output(ConsoleConfig_Output value) {
+ static constexpr uint32_t field_id = FieldMetadata_Output::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnableColors =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ConsoleConfig>;
+
+ static constexpr FieldMetadata_EnableColors kEnableColors{};
+ void set_enable_colors(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnableColors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/power/android_power_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_POWER_ANDROID_POWER_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_POWER_ANDROID_POWER_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_AndroidPowerConfig {
+enum BatteryCounters : int32_t;
+} // namespace perfetto_pbzero_enum_AndroidPowerConfig
+using AndroidPowerConfig_BatteryCounters = perfetto_pbzero_enum_AndroidPowerConfig::BatteryCounters;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_AndroidPowerConfig {
+enum BatteryCounters : int32_t {
+ BATTERY_COUNTER_UNSPECIFIED = 0,
+ BATTERY_COUNTER_CHARGE = 1,
+ BATTERY_COUNTER_CAPACITY_PERCENT = 2,
+ BATTERY_COUNTER_CURRENT = 3,
+ BATTERY_COUNTER_CURRENT_AVG = 4,
+ BATTERY_COUNTER_VOLTAGE = 5,
+};
+} // namespace perfetto_pbzero_enum_AndroidPowerConfig
+using AndroidPowerConfig_BatteryCounters = perfetto_pbzero_enum_AndroidPowerConfig::BatteryCounters;
+
+
+constexpr AndroidPowerConfig_BatteryCounters AndroidPowerConfig_BatteryCounters_MIN = AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_UNSPECIFIED;
+constexpr AndroidPowerConfig_BatteryCounters AndroidPowerConfig_BatteryCounters_MAX = AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_VOLTAGE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* AndroidPowerConfig_BatteryCounters_Name(::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_UNSPECIFIED:
+ return "BATTERY_COUNTER_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_CHARGE:
+ return "BATTERY_COUNTER_CHARGE";
+
+ case ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_CAPACITY_PERCENT:
+ return "BATTERY_COUNTER_CAPACITY_PERCENT";
+
+ case ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_CURRENT:
+ return "BATTERY_COUNTER_CURRENT";
+
+ case ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_CURRENT_AVG:
+ return "BATTERY_COUNTER_CURRENT_AVG";
+
+ case ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters::BATTERY_COUNTER_VOLTAGE:
+ return "BATTERY_COUNTER_VOLTAGE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class AndroidPowerConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidPowerConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidPowerConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidPowerConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_battery_poll_ms() const { return at<1>().valid(); }
+ uint32_t battery_poll_ms() const { return at<1>().as_uint32(); }
+ bool has_battery_counters() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> battery_counters() const { return GetRepeated<int32_t>(2); }
+ bool has_collect_power_rails() const { return at<3>().valid(); }
+ bool collect_power_rails() const { return at<3>().as_bool(); }
+ bool has_collect_energy_estimation_breakdown() const { return at<4>().valid(); }
+ bool collect_energy_estimation_breakdown() const { return at<4>().as_bool(); }
+ bool has_collect_entity_state_residency() const { return at<5>().valid(); }
+ bool collect_entity_state_residency() const { return at<5>().as_bool(); }
+};
+
+class AndroidPowerConfig : public ::protozero::Message {
+ public:
+ using Decoder = AndroidPowerConfig_Decoder;
+ enum : int32_t {
+ kBatteryPollMsFieldNumber = 1,
+ kBatteryCountersFieldNumber = 2,
+ kCollectPowerRailsFieldNumber = 3,
+ kCollectEnergyEstimationBreakdownFieldNumber = 4,
+ kCollectEntityStateResidencyFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidPowerConfig"; }
+
+
+ using BatteryCounters = ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters;
+ static inline const char* BatteryCounters_Name(BatteryCounters value) {
+ return ::perfetto::protos::pbzero::AndroidPowerConfig_BatteryCounters_Name(value);
+ }
+ static inline const BatteryCounters BATTERY_COUNTER_UNSPECIFIED = BatteryCounters::BATTERY_COUNTER_UNSPECIFIED;
+ static inline const BatteryCounters BATTERY_COUNTER_CHARGE = BatteryCounters::BATTERY_COUNTER_CHARGE;
+ static inline const BatteryCounters BATTERY_COUNTER_CAPACITY_PERCENT = BatteryCounters::BATTERY_COUNTER_CAPACITY_PERCENT;
+ static inline const BatteryCounters BATTERY_COUNTER_CURRENT = BatteryCounters::BATTERY_COUNTER_CURRENT;
+ static inline const BatteryCounters BATTERY_COUNTER_CURRENT_AVG = BatteryCounters::BATTERY_COUNTER_CURRENT_AVG;
+ static inline const BatteryCounters BATTERY_COUNTER_VOLTAGE = BatteryCounters::BATTERY_COUNTER_VOLTAGE;
+
+ using FieldMetadata_BatteryPollMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidPowerConfig>;
+
+ static constexpr FieldMetadata_BatteryPollMs kBatteryPollMs{};
+ void set_battery_poll_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BatteryPollMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BatteryCounters =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidPowerConfig_BatteryCounters,
+ AndroidPowerConfig>;
+
+ static constexpr FieldMetadata_BatteryCounters kBatteryCounters{};
+ void add_battery_counters(AndroidPowerConfig_BatteryCounters value) {
+ static constexpr uint32_t field_id = FieldMetadata_BatteryCounters::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CollectPowerRails =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidPowerConfig>;
+
+ static constexpr FieldMetadata_CollectPowerRails kCollectPowerRails{};
+ void set_collect_power_rails(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CollectPowerRails::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CollectEnergyEstimationBreakdown =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidPowerConfig>;
+
+ static constexpr FieldMetadata_CollectEnergyEstimationBreakdown kCollectEnergyEstimationBreakdown{};
+ void set_collect_energy_estimation_breakdown(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CollectEnergyEstimationBreakdown::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CollectEntityStateResidency =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidPowerConfig>;
+
+ static constexpr FieldMetadata_CollectEntityStateResidency kCollectEntityStateResidency{};
+ void set_collect_entity_state_residency(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CollectEntityStateResidency::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/process_stats/process_stats_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROCESS_STATS_PROCESS_STATS_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROCESS_STATS_PROCESS_STATS_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ProcessStatsConfig {
+enum Quirks : int32_t;
+} // namespace perfetto_pbzero_enum_ProcessStatsConfig
+using ProcessStatsConfig_Quirks = perfetto_pbzero_enum_ProcessStatsConfig::Quirks;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ProcessStatsConfig {
+enum Quirks : int32_t {
+ QUIRKS_UNSPECIFIED = 0,
+ DISABLE_INITIAL_DUMP = 1,
+ DISABLE_ON_DEMAND = 2,
+};
+} // namespace perfetto_pbzero_enum_ProcessStatsConfig
+using ProcessStatsConfig_Quirks = perfetto_pbzero_enum_ProcessStatsConfig::Quirks;
+
+
+constexpr ProcessStatsConfig_Quirks ProcessStatsConfig_Quirks_MIN = ProcessStatsConfig_Quirks::QUIRKS_UNSPECIFIED;
+constexpr ProcessStatsConfig_Quirks ProcessStatsConfig_Quirks_MAX = ProcessStatsConfig_Quirks::DISABLE_ON_DEMAND;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ProcessStatsConfig_Quirks_Name(::perfetto::protos::pbzero::ProcessStatsConfig_Quirks value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ProcessStatsConfig_Quirks::QUIRKS_UNSPECIFIED:
+ return "QUIRKS_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ProcessStatsConfig_Quirks::DISABLE_INITIAL_DUMP:
+ return "DISABLE_INITIAL_DUMP";
+
+ case ::perfetto::protos::pbzero::ProcessStatsConfig_Quirks::DISABLE_ON_DEMAND:
+ return "DISABLE_ON_DEMAND";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ProcessStatsConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/12, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProcessStatsConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessStatsConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessStatsConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_quirks() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> quirks() const { return GetRepeated<int32_t>(1); }
+ bool has_scan_all_processes_on_start() const { return at<2>().valid(); }
+ bool scan_all_processes_on_start() const { return at<2>().as_bool(); }
+ bool has_record_thread_names() const { return at<3>().valid(); }
+ bool record_thread_names() const { return at<3>().as_bool(); }
+ bool has_proc_stats_poll_ms() const { return at<4>().valid(); }
+ uint32_t proc_stats_poll_ms() const { return at<4>().as_uint32(); }
+ bool has_proc_stats_cache_ttl_ms() const { return at<6>().valid(); }
+ uint32_t proc_stats_cache_ttl_ms() const { return at<6>().as_uint32(); }
+ bool has_resolve_process_fds() const { return at<9>().valid(); }
+ bool resolve_process_fds() const { return at<9>().as_bool(); }
+ bool has_scan_smaps_rollup() const { return at<10>().valid(); }
+ bool scan_smaps_rollup() const { return at<10>().as_bool(); }
+ bool has_record_process_age() const { return at<11>().valid(); }
+ bool record_process_age() const { return at<11>().as_bool(); }
+ bool has_record_process_runtime() const { return at<12>().valid(); }
+ bool record_process_runtime() const { return at<12>().as_bool(); }
+};
+
+class ProcessStatsConfig : public ::protozero::Message {
+ public:
+ using Decoder = ProcessStatsConfig_Decoder;
+ enum : int32_t {
+ kQuirksFieldNumber = 1,
+ kScanAllProcessesOnStartFieldNumber = 2,
+ kRecordThreadNamesFieldNumber = 3,
+ kProcStatsPollMsFieldNumber = 4,
+ kProcStatsCacheTtlMsFieldNumber = 6,
+ kResolveProcessFdsFieldNumber = 9,
+ kScanSmapsRollupFieldNumber = 10,
+ kRecordProcessAgeFieldNumber = 11,
+ kRecordProcessRuntimeFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessStatsConfig"; }
+
+
+ using Quirks = ::perfetto::protos::pbzero::ProcessStatsConfig_Quirks;
+ static inline const char* Quirks_Name(Quirks value) {
+ return ::perfetto::protos::pbzero::ProcessStatsConfig_Quirks_Name(value);
+ }
+ static inline const Quirks QUIRKS_UNSPECIFIED = Quirks::QUIRKS_UNSPECIFIED;
+ static inline const Quirks DISABLE_INITIAL_DUMP = Quirks::DISABLE_INITIAL_DUMP;
+ static inline const Quirks DISABLE_ON_DEMAND = Quirks::DISABLE_ON_DEMAND;
+
+ using FieldMetadata_Quirks =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ProcessStatsConfig_Quirks,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_Quirks kQuirks{};
+ void add_quirks(ProcessStatsConfig_Quirks value) {
+ static constexpr uint32_t field_id = FieldMetadata_Quirks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanAllProcessesOnStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_ScanAllProcessesOnStart kScanAllProcessesOnStart{};
+ void set_scan_all_processes_on_start(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanAllProcessesOnStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RecordThreadNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_RecordThreadNames kRecordThreadNames{};
+ void set_record_thread_names(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_RecordThreadNames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcStatsPollMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_ProcStatsPollMs kProcStatsPollMs{};
+ void set_proc_stats_poll_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcStatsPollMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcStatsCacheTtlMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_ProcStatsCacheTtlMs kProcStatsCacheTtlMs{};
+ void set_proc_stats_cache_ttl_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcStatsCacheTtlMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResolveProcessFds =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_ResolveProcessFds kResolveProcessFds{};
+ void set_resolve_process_fds(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResolveProcessFds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanSmapsRollup =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_ScanSmapsRollup kScanSmapsRollup{};
+ void set_scan_smaps_rollup(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanSmapsRollup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RecordProcessAge =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_RecordProcessAge kRecordProcessAge{};
+ void set_record_process_age(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_RecordProcessAge::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RecordProcessRuntime =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProcessStatsConfig>;
+
+ static constexpr FieldMetadata_RecordProcessRuntime kRecordProcessRuntime{};
+ void set_record_process_runtime(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_RecordProcessRuntime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/profiling/heapprofd_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_HEAPPROFD_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_HEAPPROFD_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class HeapprofdConfig_ContinuousDumpConfig;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class HeapprofdConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/27, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ HeapprofdConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HeapprofdConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HeapprofdConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_sampling_interval_bytes() const { return at<1>().valid(); }
+ uint64_t sampling_interval_bytes() const { return at<1>().as_uint64(); }
+ bool has_adaptive_sampling_shmem_threshold() const { return at<24>().valid(); }
+ uint64_t adaptive_sampling_shmem_threshold() const { return at<24>().as_uint64(); }
+ bool has_adaptive_sampling_max_sampling_interval_bytes() const { return at<25>().valid(); }
+ uint64_t adaptive_sampling_max_sampling_interval_bytes() const { return at<25>().as_uint64(); }
+ bool has_process_cmdline() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> process_cmdline() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_pid() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> pid() const { return GetRepeated<uint64_t>(4); }
+ bool has_target_installed_by() const { return at<26>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> target_installed_by() const { return GetRepeated<::protozero::ConstChars>(26); }
+ bool has_heaps() const { return at<20>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> heaps() const { return GetRepeated<::protozero::ConstChars>(20); }
+ bool has_exclude_heaps() const { return at<27>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> exclude_heaps() const { return GetRepeated<::protozero::ConstChars>(27); }
+ bool has_stream_allocations() const { return at<23>().valid(); }
+ bool stream_allocations() const { return at<23>().as_bool(); }
+ bool has_heap_sampling_intervals() const { return at<22>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> heap_sampling_intervals() const { return GetRepeated<uint64_t>(22); }
+ bool has_all_heaps() const { return at<21>().valid(); }
+ bool all_heaps() const { return at<21>().as_bool(); }
+ bool has_all() const { return at<5>().valid(); }
+ bool all() const { return at<5>().as_bool(); }
+ bool has_min_anonymous_memory_kb() const { return at<15>().valid(); }
+ uint32_t min_anonymous_memory_kb() const { return at<15>().as_uint32(); }
+ bool has_max_heapprofd_memory_kb() const { return at<16>().valid(); }
+ uint32_t max_heapprofd_memory_kb() const { return at<16>().as_uint32(); }
+ bool has_max_heapprofd_cpu_secs() const { return at<17>().valid(); }
+ uint64_t max_heapprofd_cpu_secs() const { return at<17>().as_uint64(); }
+ bool has_skip_symbol_prefix() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> skip_symbol_prefix() const { return GetRepeated<::protozero::ConstChars>(7); }
+ bool has_continuous_dump_config() const { return at<6>().valid(); }
+ ::protozero::ConstBytes continuous_dump_config() const { return at<6>().as_bytes(); }
+ bool has_shmem_size_bytes() const { return at<8>().valid(); }
+ uint64_t shmem_size_bytes() const { return at<8>().as_uint64(); }
+ bool has_block_client() const { return at<9>().valid(); }
+ bool block_client() const { return at<9>().as_bool(); }
+ bool has_block_client_timeout_us() const { return at<14>().valid(); }
+ uint32_t block_client_timeout_us() const { return at<14>().as_uint32(); }
+ bool has_no_startup() const { return at<10>().valid(); }
+ bool no_startup() const { return at<10>().as_bool(); }
+ bool has_no_running() const { return at<11>().valid(); }
+ bool no_running() const { return at<11>().as_bool(); }
+ bool has_dump_at_max() const { return at<13>().valid(); }
+ bool dump_at_max() const { return at<13>().as_bool(); }
+ bool has_disable_fork_teardown() const { return at<18>().valid(); }
+ bool disable_fork_teardown() const { return at<18>().as_bool(); }
+ bool has_disable_vfork_detection() const { return at<19>().valid(); }
+ bool disable_vfork_detection() const { return at<19>().as_bool(); }
+};
+
+class HeapprofdConfig : public ::protozero::Message {
+ public:
+ using Decoder = HeapprofdConfig_Decoder;
+ enum : int32_t {
+ kSamplingIntervalBytesFieldNumber = 1,
+ kAdaptiveSamplingShmemThresholdFieldNumber = 24,
+ kAdaptiveSamplingMaxSamplingIntervalBytesFieldNumber = 25,
+ kProcessCmdlineFieldNumber = 2,
+ kPidFieldNumber = 4,
+ kTargetInstalledByFieldNumber = 26,
+ kHeapsFieldNumber = 20,
+ kExcludeHeapsFieldNumber = 27,
+ kStreamAllocationsFieldNumber = 23,
+ kHeapSamplingIntervalsFieldNumber = 22,
+ kAllHeapsFieldNumber = 21,
+ kAllFieldNumber = 5,
+ kMinAnonymousMemoryKbFieldNumber = 15,
+ kMaxHeapprofdMemoryKbFieldNumber = 16,
+ kMaxHeapprofdCpuSecsFieldNumber = 17,
+ kSkipSymbolPrefixFieldNumber = 7,
+ kContinuousDumpConfigFieldNumber = 6,
+ kShmemSizeBytesFieldNumber = 8,
+ kBlockClientFieldNumber = 9,
+ kBlockClientTimeoutUsFieldNumber = 14,
+ kNoStartupFieldNumber = 10,
+ kNoRunningFieldNumber = 11,
+ kDumpAtMaxFieldNumber = 13,
+ kDisableForkTeardownFieldNumber = 18,
+ kDisableVforkDetectionFieldNumber = 19,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HeapprofdConfig"; }
+
+ using ContinuousDumpConfig = ::perfetto::protos::pbzero::HeapprofdConfig_ContinuousDumpConfig;
+
+ using FieldMetadata_SamplingIntervalBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_SamplingIntervalBytes kSamplingIntervalBytes{};
+ void set_sampling_interval_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SamplingIntervalBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AdaptiveSamplingShmemThreshold =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_AdaptiveSamplingShmemThreshold kAdaptiveSamplingShmemThreshold{};
+ void set_adaptive_sampling_shmem_threshold(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdaptiveSamplingShmemThreshold::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AdaptiveSamplingMaxSamplingIntervalBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_AdaptiveSamplingMaxSamplingIntervalBytes kAdaptiveSamplingMaxSamplingIntervalBytes{};
+ void set_adaptive_sampling_max_sampling_interval_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdaptiveSamplingMaxSamplingIntervalBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessCmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_ProcessCmdline kProcessCmdline{};
+ void add_process_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProcessCmdline::kFieldId, data, size);
+ }
+ void add_process_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProcessCmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_process_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessCmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void add_pid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetInstalledBy =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_TargetInstalledBy kTargetInstalledBy{};
+ void add_target_installed_by(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TargetInstalledBy::kFieldId, data, size);
+ }
+ void add_target_installed_by(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TargetInstalledBy::kFieldId, chars.data, chars.size);
+ }
+ void add_target_installed_by(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetInstalledBy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Heaps =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_Heaps kHeaps{};
+ void add_heaps(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Heaps::kFieldId, data, size);
+ }
+ void add_heaps(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Heaps::kFieldId, chars.data, chars.size);
+ }
+ void add_heaps(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Heaps::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExcludeHeaps =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_ExcludeHeaps kExcludeHeaps{};
+ void add_exclude_heaps(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ExcludeHeaps::kFieldId, data, size);
+ }
+ void add_exclude_heaps(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ExcludeHeaps::kFieldId, chars.data, chars.size);
+ }
+ void add_exclude_heaps(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExcludeHeaps::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StreamAllocations =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_StreamAllocations kStreamAllocations{};
+ void set_stream_allocations(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_StreamAllocations::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapSamplingIntervals =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_HeapSamplingIntervals kHeapSamplingIntervals{};
+ void add_heap_sampling_intervals(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapSamplingIntervals::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllHeaps =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_AllHeaps kAllHeaps{};
+ void set_all_heaps(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllHeaps::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_All =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_All kAll{};
+ void set_all(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_All::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MinAnonymousMemoryKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_MinAnonymousMemoryKb kMinAnonymousMemoryKb{};
+ void set_min_anonymous_memory_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MinAnonymousMemoryKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxHeapprofdMemoryKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_MaxHeapprofdMemoryKb kMaxHeapprofdMemoryKb{};
+ void set_max_heapprofd_memory_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxHeapprofdMemoryKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxHeapprofdCpuSecs =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_MaxHeapprofdCpuSecs kMaxHeapprofdCpuSecs{};
+ void set_max_heapprofd_cpu_secs(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxHeapprofdCpuSecs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkipSymbolPrefix =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_SkipSymbolPrefix kSkipSymbolPrefix{};
+ void add_skip_symbol_prefix(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SkipSymbolPrefix::kFieldId, data, size);
+ }
+ void add_skip_symbol_prefix(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SkipSymbolPrefix::kFieldId, chars.data, chars.size);
+ }
+ void add_skip_symbol_prefix(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkipSymbolPrefix::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ContinuousDumpConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HeapprofdConfig_ContinuousDumpConfig,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_ContinuousDumpConfig kContinuousDumpConfig{};
+ template <typename T = HeapprofdConfig_ContinuousDumpConfig> T* set_continuous_dump_config() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_ShmemSizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_ShmemSizeBytes kShmemSizeBytes{};
+ void set_shmem_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShmemSizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BlockClient =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_BlockClient kBlockClient{};
+ void set_block_client(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlockClient::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BlockClientTimeoutUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_BlockClientTimeoutUs kBlockClientTimeoutUs{};
+ void set_block_client_timeout_us(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlockClientTimeoutUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NoStartup =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_NoStartup kNoStartup{};
+ void set_no_startup(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NoStartup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NoRunning =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_NoRunning kNoRunning{};
+ void set_no_running(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NoRunning::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DumpAtMax =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_DumpAtMax kDumpAtMax{};
+ void set_dump_at_max(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DumpAtMax::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableForkTeardown =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_DisableForkTeardown kDisableForkTeardown{};
+ void set_disable_fork_teardown(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableForkTeardown::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableVforkDetection =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapprofdConfig>;
+
+ static constexpr FieldMetadata_DisableVforkDetection kDisableVforkDetection{};
+ void set_disable_vfork_detection(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableVforkDetection::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HeapprofdConfig_ContinuousDumpConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HeapprofdConfig_ContinuousDumpConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HeapprofdConfig_ContinuousDumpConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HeapprofdConfig_ContinuousDumpConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dump_phase_ms() const { return at<5>().valid(); }
+ uint32_t dump_phase_ms() const { return at<5>().as_uint32(); }
+ bool has_dump_interval_ms() const { return at<6>().valid(); }
+ uint32_t dump_interval_ms() const { return at<6>().as_uint32(); }
+};
+
+class HeapprofdConfig_ContinuousDumpConfig : public ::protozero::Message {
+ public:
+ using Decoder = HeapprofdConfig_ContinuousDumpConfig_Decoder;
+ enum : int32_t {
+ kDumpPhaseMsFieldNumber = 5,
+ kDumpIntervalMsFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HeapprofdConfig.ContinuousDumpConfig"; }
+
+
+ using FieldMetadata_DumpPhaseMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HeapprofdConfig_ContinuousDumpConfig>;
+
+ static constexpr FieldMetadata_DumpPhaseMs kDumpPhaseMs{};
+ void set_dump_phase_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DumpPhaseMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DumpIntervalMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HeapprofdConfig_ContinuousDumpConfig>;
+
+ static constexpr FieldMetadata_DumpIntervalMs kDumpIntervalMs{};
+ void set_dump_interval_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DumpIntervalMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/profiling/java_hprof_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_JAVA_HPROF_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_JAVA_HPROF_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class JavaHprofConfig_ContinuousDumpConfig;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class JavaHprofConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ JavaHprofConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit JavaHprofConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit JavaHprofConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_process_cmdline() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> process_cmdline() const { return GetRepeated<::protozero::ConstChars>(1); }
+ bool has_pid() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> pid() const { return GetRepeated<uint64_t>(2); }
+ bool has_target_installed_by() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> target_installed_by() const { return GetRepeated<::protozero::ConstChars>(7); }
+ bool has_continuous_dump_config() const { return at<3>().valid(); }
+ ::protozero::ConstBytes continuous_dump_config() const { return at<3>().as_bytes(); }
+ bool has_min_anonymous_memory_kb() const { return at<4>().valid(); }
+ uint32_t min_anonymous_memory_kb() const { return at<4>().as_uint32(); }
+ bool has_dump_smaps() const { return at<5>().valid(); }
+ bool dump_smaps() const { return at<5>().as_bool(); }
+ bool has_ignored_types() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> ignored_types() const { return GetRepeated<::protozero::ConstChars>(6); }
+};
+
+class JavaHprofConfig : public ::protozero::Message {
+ public:
+ using Decoder = JavaHprofConfig_Decoder;
+ enum : int32_t {
+ kProcessCmdlineFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTargetInstalledByFieldNumber = 7,
+ kContinuousDumpConfigFieldNumber = 3,
+ kMinAnonymousMemoryKbFieldNumber = 4,
+ kDumpSmapsFieldNumber = 5,
+ kIgnoredTypesFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.JavaHprofConfig"; }
+
+ using ContinuousDumpConfig = ::perfetto::protos::pbzero::JavaHprofConfig_ContinuousDumpConfig;
+
+ using FieldMetadata_ProcessCmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ JavaHprofConfig>;
+
+ static constexpr FieldMetadata_ProcessCmdline kProcessCmdline{};
+ void add_process_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProcessCmdline::kFieldId, data, size);
+ }
+ void add_process_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProcessCmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_process_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessCmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ JavaHprofConfig>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void add_pid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetInstalledBy =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ JavaHprofConfig>;
+
+ static constexpr FieldMetadata_TargetInstalledBy kTargetInstalledBy{};
+ void add_target_installed_by(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TargetInstalledBy::kFieldId, data, size);
+ }
+ void add_target_installed_by(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TargetInstalledBy::kFieldId, chars.data, chars.size);
+ }
+ void add_target_installed_by(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetInstalledBy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ContinuousDumpConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ JavaHprofConfig_ContinuousDumpConfig,
+ JavaHprofConfig>;
+
+ static constexpr FieldMetadata_ContinuousDumpConfig kContinuousDumpConfig{};
+ template <typename T = JavaHprofConfig_ContinuousDumpConfig> T* set_continuous_dump_config() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_MinAnonymousMemoryKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ JavaHprofConfig>;
+
+ static constexpr FieldMetadata_MinAnonymousMemoryKb kMinAnonymousMemoryKb{};
+ void set_min_anonymous_memory_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MinAnonymousMemoryKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DumpSmaps =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ JavaHprofConfig>;
+
+ static constexpr FieldMetadata_DumpSmaps kDumpSmaps{};
+ void set_dump_smaps(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DumpSmaps::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IgnoredTypes =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ JavaHprofConfig>;
+
+ static constexpr FieldMetadata_IgnoredTypes kIgnoredTypes{};
+ void add_ignored_types(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_IgnoredTypes::kFieldId, data, size);
+ }
+ void add_ignored_types(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_IgnoredTypes::kFieldId, chars.data, chars.size);
+ }
+ void add_ignored_types(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_IgnoredTypes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class JavaHprofConfig_ContinuousDumpConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ JavaHprofConfig_ContinuousDumpConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit JavaHprofConfig_ContinuousDumpConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit JavaHprofConfig_ContinuousDumpConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dump_phase_ms() const { return at<1>().valid(); }
+ uint32_t dump_phase_ms() const { return at<1>().as_uint32(); }
+ bool has_dump_interval_ms() const { return at<2>().valid(); }
+ uint32_t dump_interval_ms() const { return at<2>().as_uint32(); }
+ bool has_scan_pids_only_on_start() const { return at<3>().valid(); }
+ bool scan_pids_only_on_start() const { return at<3>().as_bool(); }
+};
+
+class JavaHprofConfig_ContinuousDumpConfig : public ::protozero::Message {
+ public:
+ using Decoder = JavaHprofConfig_ContinuousDumpConfig_Decoder;
+ enum : int32_t {
+ kDumpPhaseMsFieldNumber = 1,
+ kDumpIntervalMsFieldNumber = 2,
+ kScanPidsOnlyOnStartFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.JavaHprofConfig.ContinuousDumpConfig"; }
+
+
+ using FieldMetadata_DumpPhaseMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ JavaHprofConfig_ContinuousDumpConfig>;
+
+ static constexpr FieldMetadata_DumpPhaseMs kDumpPhaseMs{};
+ void set_dump_phase_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DumpPhaseMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DumpIntervalMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ JavaHprofConfig_ContinuousDumpConfig>;
+
+ static constexpr FieldMetadata_DumpIntervalMs kDumpIntervalMs{};
+ void set_dump_interval_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DumpIntervalMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanPidsOnlyOnStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ JavaHprofConfig_ContinuousDumpConfig>;
+
+ static constexpr FieldMetadata_ScanPidsOnlyOnStart kScanPidsOnlyOnStart{};
+ void set_scan_pids_only_on_start(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanPidsOnlyOnStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/profiling/perf_event_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_PERF_EVENT_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_PROFILING_PERF_EVENT_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class PerfEventConfig_CallstackSampling;
+class PerfEventConfig_Scope;
+class PerfEvents_Timebase;
+namespace perfetto_pbzero_enum_PerfEventConfig {
+enum UnwindMode : int32_t;
+} // namespace perfetto_pbzero_enum_PerfEventConfig
+using PerfEventConfig_UnwindMode = perfetto_pbzero_enum_PerfEventConfig::UnwindMode;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_PerfEventConfig {
+enum UnwindMode : int32_t {
+ UNWIND_UNKNOWN = 0,
+ UNWIND_SKIP = 1,
+ UNWIND_DWARF = 2,
+};
+} // namespace perfetto_pbzero_enum_PerfEventConfig
+using PerfEventConfig_UnwindMode = perfetto_pbzero_enum_PerfEventConfig::UnwindMode;
+
+
+constexpr PerfEventConfig_UnwindMode PerfEventConfig_UnwindMode_MIN = PerfEventConfig_UnwindMode::UNWIND_UNKNOWN;
+constexpr PerfEventConfig_UnwindMode PerfEventConfig_UnwindMode_MAX = PerfEventConfig_UnwindMode::UNWIND_DWARF;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* PerfEventConfig_UnwindMode_Name(::perfetto::protos::pbzero::PerfEventConfig_UnwindMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::PerfEventConfig_UnwindMode::UNWIND_UNKNOWN:
+ return "UNWIND_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::PerfEventConfig_UnwindMode::UNWIND_SKIP:
+ return "UNWIND_SKIP";
+
+ case ::perfetto::protos::pbzero::PerfEventConfig_UnwindMode::UNWIND_DWARF:
+ return "UNWIND_DWARF";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class PerfEventConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/18, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ PerfEventConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfEventConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfEventConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timebase() const { return at<15>().valid(); }
+ ::protozero::ConstBytes timebase() const { return at<15>().as_bytes(); }
+ bool has_callstack_sampling() const { return at<16>().valid(); }
+ ::protozero::ConstBytes callstack_sampling() const { return at<16>().as_bytes(); }
+ bool has_ring_buffer_read_period_ms() const { return at<8>().valid(); }
+ uint32_t ring_buffer_read_period_ms() const { return at<8>().as_uint32(); }
+ bool has_ring_buffer_pages() const { return at<3>().valid(); }
+ uint32_t ring_buffer_pages() const { return at<3>().as_uint32(); }
+ bool has_max_enqueued_footprint_kb() const { return at<17>().valid(); }
+ uint64_t max_enqueued_footprint_kb() const { return at<17>().as_uint64(); }
+ bool has_max_daemon_memory_kb() const { return at<13>().valid(); }
+ uint32_t max_daemon_memory_kb() const { return at<13>().as_uint32(); }
+ bool has_remote_descriptor_timeout_ms() const { return at<9>().valid(); }
+ uint32_t remote_descriptor_timeout_ms() const { return at<9>().as_uint32(); }
+ bool has_unwind_state_clear_period_ms() const { return at<10>().valid(); }
+ uint32_t unwind_state_clear_period_ms() const { return at<10>().as_uint32(); }
+ bool has_target_installed_by() const { return at<18>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> target_installed_by() const { return GetRepeated<::protozero::ConstChars>(18); }
+ bool has_all_cpus() const { return at<1>().valid(); }
+ bool all_cpus() const { return at<1>().as_bool(); }
+ bool has_sampling_frequency() const { return at<2>().valid(); }
+ uint32_t sampling_frequency() const { return at<2>().as_uint32(); }
+ bool has_kernel_frames() const { return at<12>().valid(); }
+ bool kernel_frames() const { return at<12>().as_bool(); }
+ bool has_target_pid() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> target_pid() const { return GetRepeated<int32_t>(4); }
+ bool has_target_cmdline() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> target_cmdline() const { return GetRepeated<::protozero::ConstChars>(5); }
+ bool has_exclude_pid() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> exclude_pid() const { return GetRepeated<int32_t>(6); }
+ bool has_exclude_cmdline() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> exclude_cmdline() const { return GetRepeated<::protozero::ConstChars>(7); }
+ bool has_additional_cmdline_count() const { return at<11>().valid(); }
+ uint32_t additional_cmdline_count() const { return at<11>().as_uint32(); }
+};
+
+class PerfEventConfig : public ::protozero::Message {
+ public:
+ using Decoder = PerfEventConfig_Decoder;
+ enum : int32_t {
+ kTimebaseFieldNumber = 15,
+ kCallstackSamplingFieldNumber = 16,
+ kRingBufferReadPeriodMsFieldNumber = 8,
+ kRingBufferPagesFieldNumber = 3,
+ kMaxEnqueuedFootprintKbFieldNumber = 17,
+ kMaxDaemonMemoryKbFieldNumber = 13,
+ kRemoteDescriptorTimeoutMsFieldNumber = 9,
+ kUnwindStateClearPeriodMsFieldNumber = 10,
+ kTargetInstalledByFieldNumber = 18,
+ kAllCpusFieldNumber = 1,
+ kSamplingFrequencyFieldNumber = 2,
+ kKernelFramesFieldNumber = 12,
+ kTargetPidFieldNumber = 4,
+ kTargetCmdlineFieldNumber = 5,
+ kExcludePidFieldNumber = 6,
+ kExcludeCmdlineFieldNumber = 7,
+ kAdditionalCmdlineCountFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfEventConfig"; }
+
+ using CallstackSampling = ::perfetto::protos::pbzero::PerfEventConfig_CallstackSampling;
+ using Scope = ::perfetto::protos::pbzero::PerfEventConfig_Scope;
+
+ using UnwindMode = ::perfetto::protos::pbzero::PerfEventConfig_UnwindMode;
+ static inline const char* UnwindMode_Name(UnwindMode value) {
+ return ::perfetto::protos::pbzero::PerfEventConfig_UnwindMode_Name(value);
+ }
+ static inline const UnwindMode UNWIND_UNKNOWN = UnwindMode::UNWIND_UNKNOWN;
+ static inline const UnwindMode UNWIND_SKIP = UnwindMode::UNWIND_SKIP;
+ static inline const UnwindMode UNWIND_DWARF = UnwindMode::UNWIND_DWARF;
+
+ using FieldMetadata_Timebase =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfEvents_Timebase,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_Timebase kTimebase{};
+ template <typename T = PerfEvents_Timebase> T* set_timebase() {
+ return BeginNestedMessage<T>(15);
+ }
+
+
+ using FieldMetadata_CallstackSampling =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfEventConfig_CallstackSampling,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_CallstackSampling kCallstackSampling{};
+ template <typename T = PerfEventConfig_CallstackSampling> T* set_callstack_sampling() {
+ return BeginNestedMessage<T>(16);
+ }
+
+
+ using FieldMetadata_RingBufferReadPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_RingBufferReadPeriodMs kRingBufferReadPeriodMs{};
+ void set_ring_buffer_read_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RingBufferReadPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RingBufferPages =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_RingBufferPages kRingBufferPages{};
+ void set_ring_buffer_pages(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RingBufferPages::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxEnqueuedFootprintKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_MaxEnqueuedFootprintKb kMaxEnqueuedFootprintKb{};
+ void set_max_enqueued_footprint_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxEnqueuedFootprintKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxDaemonMemoryKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_MaxDaemonMemoryKb kMaxDaemonMemoryKb{};
+ void set_max_daemon_memory_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxDaemonMemoryKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RemoteDescriptorTimeoutMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_RemoteDescriptorTimeoutMs kRemoteDescriptorTimeoutMs{};
+ void set_remote_descriptor_timeout_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RemoteDescriptorTimeoutMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnwindStateClearPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_UnwindStateClearPeriodMs kUnwindStateClearPeriodMs{};
+ void set_unwind_state_clear_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnwindStateClearPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetInstalledBy =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_TargetInstalledBy kTargetInstalledBy{};
+ void add_target_installed_by(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TargetInstalledBy::kFieldId, data, size);
+ }
+ void add_target_installed_by(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TargetInstalledBy::kFieldId, chars.data, chars.size);
+ }
+ void add_target_installed_by(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetInstalledBy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllCpus =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_AllCpus kAllCpus{};
+ void set_all_cpus(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllCpus::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SamplingFrequency =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_SamplingFrequency kSamplingFrequency{};
+ void set_sampling_frequency(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SamplingFrequency::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KernelFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_KernelFrames kKernelFrames{};
+ void set_kernel_frames(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_KernelFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_TargetPid kTargetPid{};
+ void add_target_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetCmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_TargetCmdline kTargetCmdline{};
+ void add_target_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TargetCmdline::kFieldId, data, size);
+ }
+ void add_target_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TargetCmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_target_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetCmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExcludePid =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_ExcludePid kExcludePid{};
+ void add_exclude_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExcludePid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExcludeCmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_ExcludeCmdline kExcludeCmdline{};
+ void add_exclude_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ExcludeCmdline::kFieldId, data, size);
+ }
+ void add_exclude_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ExcludeCmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_exclude_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExcludeCmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AdditionalCmdlineCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig>;
+
+ static constexpr FieldMetadata_AdditionalCmdlineCount kAdditionalCmdlineCount{};
+ void set_additional_cmdline_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdditionalCmdlineCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PerfEventConfig_Scope_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ PerfEventConfig_Scope_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfEventConfig_Scope_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfEventConfig_Scope_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_target_pid() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> target_pid() const { return GetRepeated<int32_t>(1); }
+ bool has_target_cmdline() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> target_cmdline() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_exclude_pid() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> exclude_pid() const { return GetRepeated<int32_t>(3); }
+ bool has_exclude_cmdline() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> exclude_cmdline() const { return GetRepeated<::protozero::ConstChars>(4); }
+ bool has_additional_cmdline_count() const { return at<5>().valid(); }
+ uint32_t additional_cmdline_count() const { return at<5>().as_uint32(); }
+ bool has_process_shard_count() const { return at<6>().valid(); }
+ uint32_t process_shard_count() const { return at<6>().as_uint32(); }
+};
+
+class PerfEventConfig_Scope : public ::protozero::Message {
+ public:
+ using Decoder = PerfEventConfig_Scope_Decoder;
+ enum : int32_t {
+ kTargetPidFieldNumber = 1,
+ kTargetCmdlineFieldNumber = 2,
+ kExcludePidFieldNumber = 3,
+ kExcludeCmdlineFieldNumber = 4,
+ kAdditionalCmdlineCountFieldNumber = 5,
+ kProcessShardCountFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfEventConfig.Scope"; }
+
+
+ using FieldMetadata_TargetPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ PerfEventConfig_Scope>;
+
+ static constexpr FieldMetadata_TargetPid kTargetPid{};
+ void add_target_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetCmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEventConfig_Scope>;
+
+ static constexpr FieldMetadata_TargetCmdline kTargetCmdline{};
+ void add_target_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TargetCmdline::kFieldId, data, size);
+ }
+ void add_target_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TargetCmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_target_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetCmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExcludePid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ PerfEventConfig_Scope>;
+
+ static constexpr FieldMetadata_ExcludePid kExcludePid{};
+ void add_exclude_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExcludePid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExcludeCmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfEventConfig_Scope>;
+
+ static constexpr FieldMetadata_ExcludeCmdline kExcludeCmdline{};
+ void add_exclude_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ExcludeCmdline::kFieldId, data, size);
+ }
+ void add_exclude_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ExcludeCmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_exclude_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExcludeCmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AdditionalCmdlineCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig_Scope>;
+
+ static constexpr FieldMetadata_AdditionalCmdlineCount kAdditionalCmdlineCount{};
+ void set_additional_cmdline_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdditionalCmdlineCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessShardCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfEventConfig_Scope>;
+
+ static constexpr FieldMetadata_ProcessShardCount kProcessShardCount{};
+ void set_process_shard_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessShardCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PerfEventConfig_CallstackSampling_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfEventConfig_CallstackSampling_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfEventConfig_CallstackSampling_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfEventConfig_CallstackSampling_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_scope() const { return at<1>().valid(); }
+ ::protozero::ConstBytes scope() const { return at<1>().as_bytes(); }
+ bool has_kernel_frames() const { return at<2>().valid(); }
+ bool kernel_frames() const { return at<2>().as_bool(); }
+ bool has_user_frames() const { return at<3>().valid(); }
+ int32_t user_frames() const { return at<3>().as_int32(); }
+};
+
+class PerfEventConfig_CallstackSampling : public ::protozero::Message {
+ public:
+ using Decoder = PerfEventConfig_CallstackSampling_Decoder;
+ enum : int32_t {
+ kScopeFieldNumber = 1,
+ kKernelFramesFieldNumber = 2,
+ kUserFramesFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfEventConfig.CallstackSampling"; }
+
+
+ using FieldMetadata_Scope =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfEventConfig_Scope,
+ PerfEventConfig_CallstackSampling>;
+
+ static constexpr FieldMetadata_Scope kScope{};
+ template <typename T = PerfEventConfig_Scope> T* set_scope() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_KernelFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PerfEventConfig_CallstackSampling>;
+
+ static constexpr FieldMetadata_KernelFrames kKernelFrames{};
+ void set_kernel_frames(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_KernelFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UserFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ PerfEventConfig_UnwindMode,
+ PerfEventConfig_CallstackSampling>;
+
+ static constexpr FieldMetadata_UserFrames kUserFrames{};
+ void set_user_frames(PerfEventConfig_UnwindMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_UserFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/statsd/atom_ids.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_ATOM_IDS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_ATOM_IDS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum AtomId : int32_t {
+ ATOM_UNSPECIFIED = 0,
+ ATOM_BLE_SCAN_STATE_CHANGED = 2,
+ ATOM_PROCESS_STATE_CHANGED = 3,
+ ATOM_BLE_SCAN_RESULT_RECEIVED = 4,
+ ATOM_SENSOR_STATE_CHANGED = 5,
+ ATOM_GPS_SCAN_STATE_CHANGED = 6,
+ ATOM_SYNC_STATE_CHANGED = 7,
+ ATOM_SCHEDULED_JOB_STATE_CHANGED = 8,
+ ATOM_SCREEN_BRIGHTNESS_CHANGED = 9,
+ ATOM_WAKELOCK_STATE_CHANGED = 10,
+ ATOM_LONG_PARTIAL_WAKELOCK_STATE_CHANGED = 11,
+ ATOM_MOBILE_RADIO_POWER_STATE_CHANGED = 12,
+ ATOM_WIFI_RADIO_POWER_STATE_CHANGED = 13,
+ ATOM_ACTIVITY_MANAGER_SLEEP_STATE_CHANGED = 14,
+ ATOM_MEMORY_FACTOR_STATE_CHANGED = 15,
+ ATOM_EXCESSIVE_CPU_USAGE_REPORTED = 16,
+ ATOM_CACHED_KILL_REPORTED = 17,
+ ATOM_PROCESS_MEMORY_STAT_REPORTED = 18,
+ ATOM_LAUNCHER_EVENT = 19,
+ ATOM_BATTERY_SAVER_MODE_STATE_CHANGED = 20,
+ ATOM_DEVICE_IDLE_MODE_STATE_CHANGED = 21,
+ ATOM_DEVICE_IDLING_MODE_STATE_CHANGED = 22,
+ ATOM_AUDIO_STATE_CHANGED = 23,
+ ATOM_MEDIA_CODEC_STATE_CHANGED = 24,
+ ATOM_CAMERA_STATE_CHANGED = 25,
+ ATOM_FLASHLIGHT_STATE_CHANGED = 26,
+ ATOM_UID_PROCESS_STATE_CHANGED = 27,
+ ATOM_PROCESS_LIFE_CYCLE_STATE_CHANGED = 28,
+ ATOM_SCREEN_STATE_CHANGED = 29,
+ ATOM_BATTERY_LEVEL_CHANGED = 30,
+ ATOM_CHARGING_STATE_CHANGED = 31,
+ ATOM_PLUGGED_STATE_CHANGED = 32,
+ ATOM_INTERACTIVE_STATE_CHANGED = 33,
+ ATOM_TOUCH_EVENT_REPORTED = 34,
+ ATOM_WAKEUP_ALARM_OCCURRED = 35,
+ ATOM_KERNEL_WAKEUP_REPORTED = 36,
+ ATOM_WIFI_LOCK_STATE_CHANGED = 37,
+ ATOM_WIFI_SIGNAL_STRENGTH_CHANGED = 38,
+ ATOM_WIFI_SCAN_STATE_CHANGED = 39,
+ ATOM_PHONE_SIGNAL_STRENGTH_CHANGED = 40,
+ ATOM_SETTING_CHANGED = 41,
+ ATOM_ACTIVITY_FOREGROUND_STATE_CHANGED = 42,
+ ATOM_ISOLATED_UID_CHANGED = 43,
+ ATOM_PACKET_WAKEUP_OCCURRED = 44,
+ ATOM_WALL_CLOCK_TIME_SHIFTED = 45,
+ ATOM_ANOMALY_DETECTED = 46,
+ ATOM_APP_BREADCRUMB_REPORTED = 47,
+ ATOM_APP_START_OCCURRED = 48,
+ ATOM_APP_START_CANCELED = 49,
+ ATOM_APP_START_FULLY_DRAWN = 50,
+ ATOM_LMK_KILL_OCCURRED = 51,
+ ATOM_PICTURE_IN_PICTURE_STATE_CHANGED = 52,
+ ATOM_WIFI_MULTICAST_LOCK_STATE_CHANGED = 53,
+ ATOM_LMK_STATE_CHANGED = 54,
+ ATOM_APP_START_MEMORY_STATE_CAPTURED = 55,
+ ATOM_SHUTDOWN_SEQUENCE_REPORTED = 56,
+ ATOM_BOOT_SEQUENCE_REPORTED = 57,
+ ATOM_DAVEY_OCCURRED = 58,
+ ATOM_OVERLAY_STATE_CHANGED = 59,
+ ATOM_FOREGROUND_SERVICE_STATE_CHANGED = 60,
+ ATOM_CALL_STATE_CHANGED = 61,
+ ATOM_KEYGUARD_STATE_CHANGED = 62,
+ ATOM_KEYGUARD_BOUNCER_STATE_CHANGED = 63,
+ ATOM_KEYGUARD_BOUNCER_PASSWORD_ENTERED = 64,
+ ATOM_APP_DIED = 65,
+ ATOM_RESOURCE_CONFIGURATION_CHANGED = 66,
+ ATOM_BLUETOOTH_ENABLED_STATE_CHANGED = 67,
+ ATOM_BLUETOOTH_CONNECTION_STATE_CHANGED = 68,
+ ATOM_GPS_SIGNAL_QUALITY_CHANGED = 69,
+ ATOM_USB_CONNECTOR_STATE_CHANGED = 70,
+ ATOM_SPEAKER_IMPEDANCE_REPORTED = 71,
+ ATOM_HARDWARE_FAILED = 72,
+ ATOM_PHYSICAL_DROP_DETECTED = 73,
+ ATOM_CHARGE_CYCLES_REPORTED = 74,
+ ATOM_MOBILE_CONNECTION_STATE_CHANGED = 75,
+ ATOM_MOBILE_RADIO_TECHNOLOGY_CHANGED = 76,
+ ATOM_USB_DEVICE_ATTACHED = 77,
+ ATOM_APP_CRASH_OCCURRED = 78,
+ ATOM_ANR_OCCURRED = 79,
+ ATOM_WTF_OCCURRED = 80,
+ ATOM_LOW_MEM_REPORTED = 81,
+ ATOM_GENERIC_ATOM = 82,
+ ATOM_VIBRATOR_STATE_CHANGED = 84,
+ ATOM_DEFERRED_JOB_STATS_REPORTED = 85,
+ ATOM_THERMAL_THROTTLING = 86,
+ ATOM_BIOMETRIC_ACQUIRED = 87,
+ ATOM_BIOMETRIC_AUTHENTICATED = 88,
+ ATOM_BIOMETRIC_ERROR_OCCURRED = 89,
+ ATOM_UI_EVENT_REPORTED = 90,
+ ATOM_BATTERY_HEALTH_SNAPSHOT = 91,
+ ATOM_SLOW_IO = 92,
+ ATOM_BATTERY_CAUSED_SHUTDOWN = 93,
+ ATOM_PHONE_SERVICE_STATE_CHANGED = 94,
+ ATOM_PHONE_STATE_CHANGED = 95,
+ ATOM_USER_RESTRICTION_CHANGED = 96,
+ ATOM_SETTINGS_UI_CHANGED = 97,
+ ATOM_CONNECTIVITY_STATE_CHANGED = 98,
+ ATOM_SERVICE_STATE_CHANGED = 99,
+ ATOM_SERVICE_LAUNCH_REPORTED = 100,
+ ATOM_FLAG_FLIP_UPDATE_OCCURRED = 101,
+ ATOM_BINARY_PUSH_STATE_CHANGED = 102,
+ ATOM_DEVICE_POLICY_EVENT = 103,
+ ATOM_DOCS_UI_FILE_OP_CANCELED = 104,
+ ATOM_DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED = 105,
+ ATOM_DOCS_UI_FILE_OP_FAILURE = 106,
+ ATOM_DOCS_UI_PROVIDER_FILE_OP = 107,
+ ATOM_DOCS_UI_INVALID_SCOPED_ACCESS_REQUEST = 108,
+ ATOM_DOCS_UI_LAUNCH_REPORTED = 109,
+ ATOM_DOCS_UI_ROOT_VISITED = 110,
+ ATOM_DOCS_UI_STARTUP_MS = 111,
+ ATOM_DOCS_UI_USER_ACTION_REPORTED = 112,
+ ATOM_WIFI_ENABLED_STATE_CHANGED = 113,
+ ATOM_WIFI_RUNNING_STATE_CHANGED = 114,
+ ATOM_APP_COMPACTED = 115,
+ ATOM_NETWORK_DNS_EVENT_REPORTED = 116,
+ ATOM_DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED = 117,
+ ATOM_DOCS_UI_PICK_RESULT_REPORTED = 118,
+ ATOM_DOCS_UI_SEARCH_MODE_REPORTED = 119,
+ ATOM_DOCS_UI_SEARCH_TYPE_REPORTED = 120,
+ ATOM_DATA_STALL_EVENT = 121,
+ ATOM_RESCUE_PARTY_RESET_REPORTED = 122,
+ ATOM_SIGNED_CONFIG_REPORTED = 123,
+ ATOM_GNSS_NI_EVENT_REPORTED = 124,
+ ATOM_BLUETOOTH_LINK_LAYER_CONNECTION_EVENT = 125,
+ ATOM_BLUETOOTH_ACL_CONNECTION_STATE_CHANGED = 126,
+ ATOM_BLUETOOTH_SCO_CONNECTION_STATE_CHANGED = 127,
+ ATOM_APP_DOWNGRADED = 128,
+ ATOM_APP_OPTIMIZED_AFTER_DOWNGRADED = 129,
+ ATOM_LOW_STORAGE_STATE_CHANGED = 130,
+ ATOM_GNSS_NFW_NOTIFICATION_REPORTED = 131,
+ ATOM_GNSS_CONFIGURATION_REPORTED = 132,
+ ATOM_USB_PORT_OVERHEAT_EVENT_REPORTED = 133,
+ ATOM_NFC_ERROR_OCCURRED = 134,
+ ATOM_NFC_STATE_CHANGED = 135,
+ ATOM_NFC_BEAM_OCCURRED = 136,
+ ATOM_NFC_CARDEMULATION_OCCURRED = 137,
+ ATOM_NFC_TAG_OCCURRED = 138,
+ ATOM_NFC_HCE_TRANSACTION_OCCURRED = 139,
+ ATOM_SE_STATE_CHANGED = 140,
+ ATOM_SE_OMAPI_REPORTED = 141,
+ ATOM_BROADCAST_DISPATCH_LATENCY_REPORTED = 142,
+ ATOM_ATTENTION_MANAGER_SERVICE_RESULT_REPORTED = 143,
+ ATOM_ADB_CONNECTION_CHANGED = 144,
+ ATOM_SPEECH_DSP_STAT_REPORTED = 145,
+ ATOM_USB_CONTAMINANT_REPORTED = 146,
+ ATOM_WATCHDOG_ROLLBACK_OCCURRED = 147,
+ ATOM_BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED = 148,
+ ATOM_BUBBLE_UI_CHANGED = 149,
+ ATOM_SCHEDULED_JOB_CONSTRAINT_CHANGED = 150,
+ ATOM_BLUETOOTH_ACTIVE_DEVICE_CHANGED = 151,
+ ATOM_BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED = 152,
+ ATOM_BLUETOOTH_A2DP_CODEC_CONFIG_CHANGED = 153,
+ ATOM_BLUETOOTH_A2DP_CODEC_CAPABILITY_CHANGED = 154,
+ ATOM_BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED = 155,
+ ATOM_BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED = 156,
+ ATOM_BLUETOOTH_DEVICE_RSSI_REPORTED = 157,
+ ATOM_BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED = 158,
+ ATOM_BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED = 159,
+ ATOM_BLUETOOTH_HCI_TIMEOUT_REPORTED = 160,
+ ATOM_BLUETOOTH_QUALITY_REPORT_REPORTED = 161,
+ ATOM_BLUETOOTH_DEVICE_INFO_REPORTED = 162,
+ ATOM_BLUETOOTH_REMOTE_VERSION_INFO_REPORTED = 163,
+ ATOM_BLUETOOTH_SDP_ATTRIBUTE_REPORTED = 164,
+ ATOM_BLUETOOTH_BOND_STATE_CHANGED = 165,
+ ATOM_BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED = 166,
+ ATOM_BLUETOOTH_SMP_PAIRING_EVENT_REPORTED = 167,
+ ATOM_SCREEN_TIMEOUT_EXTENSION_REPORTED = 168,
+ ATOM_PROCESS_START_TIME = 169,
+ ATOM_PERMISSION_GRANT_REQUEST_RESULT_REPORTED = 170,
+ ATOM_BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED = 171,
+ ATOM_DEVICE_IDENTIFIER_ACCESS_DENIED = 172,
+ ATOM_BUBBLE_DEVELOPER_ERROR_REPORTED = 173,
+ ATOM_ASSIST_GESTURE_STAGE_REPORTED = 174,
+ ATOM_ASSIST_GESTURE_FEEDBACK_REPORTED = 175,
+ ATOM_ASSIST_GESTURE_PROGRESS_REPORTED = 176,
+ ATOM_TOUCH_GESTURE_CLASSIFIED = 177,
+ ATOM_HIDDEN_API_USED = 178,
+ ATOM_STYLE_UI_CHANGED = 179,
+ ATOM_PRIVACY_INDICATORS_INTERACTED = 180,
+ ATOM_APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED = 181,
+ ATOM_NETWORK_STACK_REPORTED = 182,
+ ATOM_APP_MOVED_STORAGE_REPORTED = 183,
+ ATOM_BIOMETRIC_ENROLLED = 184,
+ ATOM_SYSTEM_SERVER_WATCHDOG_OCCURRED = 185,
+ ATOM_TOMB_STONE_OCCURRED = 186,
+ ATOM_BLUETOOTH_CLASS_OF_DEVICE_REPORTED = 187,
+ ATOM_INTELLIGENCE_EVENT_REPORTED = 188,
+ ATOM_THERMAL_THROTTLING_SEVERITY_STATE_CHANGED = 189,
+ ATOM_ROLE_REQUEST_RESULT_REPORTED = 190,
+ ATOM_MEDIAMETRICS_AUDIOPOLICY_REPORTED = 191,
+ ATOM_MEDIAMETRICS_AUDIORECORD_REPORTED = 192,
+ ATOM_MEDIAMETRICS_AUDIOTHREAD_REPORTED = 193,
+ ATOM_MEDIAMETRICS_AUDIOTRACK_REPORTED = 194,
+ ATOM_MEDIAMETRICS_CODEC_REPORTED = 195,
+ ATOM_MEDIAMETRICS_DRM_WIDEVINE_REPORTED = 196,
+ ATOM_MEDIAMETRICS_EXTRACTOR_REPORTED = 197,
+ ATOM_MEDIAMETRICS_MEDIADRM_REPORTED = 198,
+ ATOM_MEDIAMETRICS_NUPLAYER_REPORTED = 199,
+ ATOM_MEDIAMETRICS_RECORDER_REPORTED = 200,
+ ATOM_MEDIAMETRICS_DRMMANAGER_REPORTED = 201,
+ ATOM_CAR_POWER_STATE_CHANGED = 203,
+ ATOM_GARAGE_MODE_INFO = 204,
+ ATOM_TEST_ATOM_REPORTED = 205,
+ ATOM_CONTENT_CAPTURE_CALLER_MISMATCH_REPORTED = 206,
+ ATOM_CONTENT_CAPTURE_SERVICE_EVENTS = 207,
+ ATOM_CONTENT_CAPTURE_SESSION_EVENTS = 208,
+ ATOM_CONTENT_CAPTURE_FLUSHED = 209,
+ ATOM_LOCATION_MANAGER_API_USAGE_REPORTED = 210,
+ ATOM_REVIEW_PERMISSIONS_FRAGMENT_RESULT_REPORTED = 211,
+ ATOM_RUNTIME_PERMISSIONS_UPGRADE_RESULT = 212,
+ ATOM_GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS = 213,
+ ATOM_LOCATION_ACCESS_CHECK_NOTIFICATION_ACTION = 214,
+ ATOM_APP_PERMISSION_FRAGMENT_ACTION_REPORTED = 215,
+ ATOM_APP_PERMISSION_FRAGMENT_VIEWED = 216,
+ ATOM_APP_PERMISSIONS_FRAGMENT_VIEWED = 217,
+ ATOM_PERMISSION_APPS_FRAGMENT_VIEWED = 218,
+ ATOM_TEXT_SELECTION_EVENT = 219,
+ ATOM_TEXT_LINKIFY_EVENT = 220,
+ ATOM_CONVERSATION_ACTIONS_EVENT = 221,
+ ATOM_LANGUAGE_DETECTION_EVENT = 222,
+ ATOM_EXCLUSION_RECT_STATE_CHANGED = 223,
+ ATOM_BACK_GESTURE_REPORTED_REPORTED = 224,
+ ATOM_UPDATE_ENGINE_UPDATE_ATTEMPT_REPORTED = 225,
+ ATOM_UPDATE_ENGINE_SUCCESSFUL_UPDATE_REPORTED = 226,
+ ATOM_CAMERA_ACTION_EVENT = 227,
+ ATOM_APP_COMPATIBILITY_CHANGE_REPORTED = 228,
+ ATOM_PERFETTO_UPLOADED = 229,
+ ATOM_VMS_CLIENT_CONNECTION_STATE_CHANGED = 230,
+ ATOM_MEDIA_PROVIDER_SCAN_OCCURRED = 233,
+ ATOM_MEDIA_CONTENT_DELETED = 234,
+ ATOM_MEDIA_PROVIDER_PERMISSION_REQUESTED = 235,
+ ATOM_MEDIA_PROVIDER_SCHEMA_CHANGED = 236,
+ ATOM_MEDIA_PROVIDER_IDLE_MAINTENANCE_FINISHED = 237,
+ ATOM_REBOOT_ESCROW_RECOVERY_REPORTED = 238,
+ ATOM_BOOT_TIME_EVENT_DURATION_REPORTED = 239,
+ ATOM_BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED = 240,
+ ATOM_BOOT_TIME_EVENT_UTC_TIME_REPORTED = 241,
+ ATOM_BOOT_TIME_EVENT_ERROR_CODE_REPORTED = 242,
+ ATOM_USERSPACE_REBOOT_REPORTED = 243,
+ ATOM_NOTIFICATION_REPORTED = 244,
+ ATOM_NOTIFICATION_PANEL_REPORTED = 245,
+ ATOM_NOTIFICATION_CHANNEL_MODIFIED = 246,
+ ATOM_INTEGRITY_CHECK_RESULT_REPORTED = 247,
+ ATOM_INTEGRITY_RULES_PUSHED = 248,
+ ATOM_CB_MESSAGE_REPORTED = 249,
+ ATOM_CB_MESSAGE_ERROR = 250,
+ ATOM_WIFI_HEALTH_STAT_REPORTED = 251,
+ ATOM_WIFI_FAILURE_STAT_REPORTED = 252,
+ ATOM_WIFI_CONNECTION_RESULT_REPORTED = 253,
+ ATOM_APP_FREEZE_CHANGED = 254,
+ ATOM_SNAPSHOT_MERGE_REPORTED = 255,
+ ATOM_FOREGROUND_SERVICE_APP_OP_SESSION_ENDED = 256,
+ ATOM_DISPLAY_JANK_REPORTED = 257,
+ ATOM_APP_STANDBY_BUCKET_CHANGED = 258,
+ ATOM_SHARESHEET_STARTED = 259,
+ ATOM_RANKING_SELECTED = 260,
+ ATOM_TVSETTINGS_UI_INTERACTED = 261,
+ ATOM_LAUNCHER_SNAPSHOT = 262,
+ ATOM_PACKAGE_INSTALLER_V2_REPORTED = 263,
+ ATOM_USER_LIFECYCLE_JOURNEY_REPORTED = 264,
+ ATOM_USER_LIFECYCLE_EVENT_OCCURRED = 265,
+ ATOM_ACCESSIBILITY_SHORTCUT_REPORTED = 266,
+ ATOM_ACCESSIBILITY_SERVICE_REPORTED = 267,
+ ATOM_DOCS_UI_DRAG_AND_DROP_REPORTED = 268,
+ ATOM_APP_USAGE_EVENT_OCCURRED = 269,
+ ATOM_AUTO_REVOKE_NOTIFICATION_CLICKED = 270,
+ ATOM_AUTO_REVOKE_FRAGMENT_APP_VIEWED = 271,
+ ATOM_AUTO_REVOKED_APP_INTERACTION = 272,
+ ATOM_APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION = 273,
+ ATOM_EVS_USAGE_STATS_REPORTED = 274,
+ ATOM_AUDIO_POWER_USAGE_DATA_REPORTED = 275,
+ ATOM_TV_TUNER_STATE_CHANGED = 276,
+ ATOM_MEDIAOUTPUT_OP_SWITCH_REPORTED = 277,
+ ATOM_CB_MESSAGE_FILTERED = 278,
+ ATOM_TV_TUNER_DVR_STATUS = 279,
+ ATOM_TV_CAS_SESSION_OPEN_STATUS = 280,
+ ATOM_ASSISTANT_INVOCATION_REPORTED = 281,
+ ATOM_DISPLAY_WAKE_REPORTED = 282,
+ ATOM_CAR_USER_HAL_MODIFY_USER_REQUEST_REPORTED = 283,
+ ATOM_CAR_USER_HAL_MODIFY_USER_RESPONSE_REPORTED = 284,
+ ATOM_CAR_USER_HAL_POST_SWITCH_RESPONSE_REPORTED = 285,
+ ATOM_CAR_USER_HAL_INITIAL_USER_INFO_REQUEST_REPORTED = 286,
+ ATOM_CAR_USER_HAL_INITIAL_USER_INFO_RESPONSE_REPORTED = 287,
+ ATOM_CAR_USER_HAL_USER_ASSOCIATION_REQUEST_REPORTED = 288,
+ ATOM_CAR_USER_HAL_SET_USER_ASSOCIATION_RESPONSE_REPORTED = 289,
+ ATOM_NETWORK_IP_PROVISIONING_REPORTED = 290,
+ ATOM_NETWORK_DHCP_RENEW_REPORTED = 291,
+ ATOM_NETWORK_VALIDATION_REPORTED = 292,
+ ATOM_NETWORK_STACK_QUIRK_REPORTED = 293,
+ ATOM_MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED = 294,
+ ATOM_MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED = 295,
+ ATOM_MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED = 296,
+ ATOM_MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED = 297,
+ ATOM_BLOB_COMMITTED = 298,
+ ATOM_BLOB_LEASED = 299,
+ ATOM_BLOB_OPENED = 300,
+ ATOM_CONTACTS_PROVIDER_STATUS_REPORTED = 301,
+ ATOM_KEYSTORE_KEY_EVENT_REPORTED = 302,
+ ATOM_NETWORK_TETHERING_REPORTED = 303,
+ ATOM_IME_TOUCH_REPORTED = 304,
+ ATOM_UI_INTERACTION_FRAME_INFO_REPORTED = 305,
+ ATOM_UI_ACTION_LATENCY_REPORTED = 306,
+ ATOM_WIFI_DISCONNECT_REPORTED = 307,
+ ATOM_WIFI_CONNECTION_STATE_CHANGED = 308,
+ ATOM_HDMI_CEC_ACTIVE_SOURCE_CHANGED = 309,
+ ATOM_HDMI_CEC_MESSAGE_REPORTED = 310,
+ ATOM_AIRPLANE_MODE = 311,
+ ATOM_MODEM_RESTART = 312,
+ ATOM_CARRIER_ID_MISMATCH_REPORTED = 313,
+ ATOM_CARRIER_ID_TABLE_UPDATED = 314,
+ ATOM_DATA_STALL_RECOVERY_REPORTED = 315,
+ ATOM_MEDIAMETRICS_MEDIAPARSER_REPORTED = 316,
+ ATOM_TLS_HANDSHAKE_REPORTED = 317,
+ ATOM_TEXT_CLASSIFIER_API_USAGE_REPORTED = 318,
+ ATOM_CAR_WATCHDOG_KILL_STATS_REPORTED = 319,
+ ATOM_MEDIAMETRICS_PLAYBACK_REPORTED = 320,
+ ATOM_MEDIA_NETWORK_INFO_CHANGED = 321,
+ ATOM_MEDIA_PLAYBACK_STATE_CHANGED = 322,
+ ATOM_MEDIA_PLAYBACK_ERROR_REPORTED = 323,
+ ATOM_MEDIA_PLAYBACK_TRACK_CHANGED = 324,
+ ATOM_WIFI_SCAN_REPORTED = 325,
+ ATOM_WIFI_PNO_SCAN_REPORTED = 326,
+ ATOM_TIF_TUNE_CHANGED = 327,
+ ATOM_AUTO_ROTATE_REPORTED = 328,
+ ATOM_PERFETTO_TRIGGER = 329,
+ ATOM_TRANSCODING_DATA = 330,
+ ATOM_IMS_SERVICE_ENTITLEMENT_UPDATED = 331,
+ ATOM_DEVICE_ROTATED = 333,
+ ATOM_SIM_SPECIFIC_SETTINGS_RESTORED = 334,
+ ATOM_TEXT_CLASSIFIER_DOWNLOAD_REPORTED = 335,
+ ATOM_PIN_STORAGE_EVENT = 336,
+ ATOM_FACE_DOWN_REPORTED = 337,
+ ATOM_BLUETOOTH_HAL_CRASH_REASON_REPORTED = 338,
+ ATOM_REBOOT_ESCROW_PREPARATION_REPORTED = 339,
+ ATOM_REBOOT_ESCROW_LSKF_CAPTURE_REPORTED = 340,
+ ATOM_REBOOT_ESCROW_REBOOT_REPORTED = 341,
+ ATOM_BINDER_LATENCY_REPORTED = 342,
+ ATOM_MEDIAMETRICS_AAUDIOSTREAM_REPORTED = 343,
+ ATOM_MEDIA_TRANSCODING_SESSION_ENDED = 344,
+ ATOM_MAGNIFICATION_USAGE_REPORTED = 345,
+ ATOM_MAGNIFICATION_MODE_WITH_IME_ON_REPORTED = 346,
+ ATOM_APP_SEARCH_CALL_STATS_REPORTED = 347,
+ ATOM_APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED = 348,
+ ATOM_DEVICE_CONTROL_CHANGED = 349,
+ ATOM_DEVICE_STATE_CHANGED = 350,
+ ATOM_INPUTDEVICE_REGISTERED = 351,
+ ATOM_SMARTSPACE_CARD_REPORTED = 352,
+ ATOM_AUTH_PROMPT_AUTHENTICATE_INVOKED = 353,
+ ATOM_AUTH_MANAGER_CAN_AUTHENTICATE_INVOKED = 354,
+ ATOM_AUTH_ENROLL_ACTION_INVOKED = 355,
+ ATOM_AUTH_DEPRECATED_API_USED = 356,
+ ATOM_UNATTENDED_REBOOT_OCCURRED = 357,
+ ATOM_LONG_REBOOT_BLOCKING_REPORTED = 358,
+ ATOM_LOCATION_TIME_ZONE_PROVIDER_STATE_CHANGED = 359,
+ ATOM_FDTRACK_EVENT_OCCURRED = 364,
+ ATOM_TIMEOUT_AUTO_EXTENDED_REPORTED = 365,
+ ATOM_ALARM_BATCH_DELIVERED = 367,
+ ATOM_ALARM_SCHEDULED = 368,
+ ATOM_CAR_WATCHDOG_IO_OVERUSE_STATS_REPORTED = 369,
+ ATOM_USER_LEVEL_HIBERNATION_STATE_CHANGED = 370,
+ ATOM_APP_SEARCH_INITIALIZE_STATS_REPORTED = 371,
+ ATOM_APP_SEARCH_QUERY_STATS_REPORTED = 372,
+ ATOM_APP_PROCESS_DIED = 373,
+ ATOM_NETWORK_IP_REACHABILITY_MONITOR_REPORTED = 374,
+ ATOM_SLOW_INPUT_EVENT_REPORTED = 375,
+ ATOM_ANR_OCCURRED_PROCESSING_STARTED = 376,
+ ATOM_APP_SEARCH_REMOVE_STATS_REPORTED = 377,
+ ATOM_MEDIA_CODEC_REPORTED = 378,
+ ATOM_PERMISSION_USAGE_FRAGMENT_INTERACTION = 379,
+ ATOM_PERMISSION_DETAILS_INTERACTION = 380,
+ ATOM_PRIVACY_SENSOR_TOGGLE_INTERACTION = 381,
+ ATOM_PRIVACY_TOGGLE_DIALOG_INTERACTION = 382,
+ ATOM_APP_SEARCH_OPTIMIZE_STATS_REPORTED = 383,
+ ATOM_NON_A11Y_TOOL_SERVICE_WARNING_REPORT = 384,
+ ATOM_APP_SEARCH_SET_SCHEMA_STATS_REPORTED = 385,
+ ATOM_APP_COMPAT_STATE_CHANGED = 386,
+ ATOM_SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED = 387,
+ ATOM_SPLITSCREEN_UI_CHANGED = 388,
+ ATOM_NETWORK_DNS_HANDSHAKE_REPORTED = 389,
+ ATOM_BLUETOOTH_CODE_PATH_COUNTER = 390,
+ ATOM_BLUETOOTH_LE_BATCH_SCAN_REPORT_DELAY = 392,
+ ATOM_ACCESSIBILITY_FLOATING_MENU_UI_CHANGED = 393,
+ ATOM_NEURALNETWORKS_COMPILATION_COMPLETED = 394,
+ ATOM_NEURALNETWORKS_EXECUTION_COMPLETED = 395,
+ ATOM_NEURALNETWORKS_COMPILATION_FAILED = 396,
+ ATOM_NEURALNETWORKS_EXECUTION_FAILED = 397,
+ ATOM_CONTEXT_HUB_BOOTED = 398,
+ ATOM_CONTEXT_HUB_RESTARTED = 399,
+ ATOM_CONTEXT_HUB_LOADED_NANOAPP_SNAPSHOT_REPORTED = 400,
+ ATOM_CHRE_CODE_DOWNLOAD_TRANSACTED = 401,
+ ATOM_UWB_SESSION_INITED = 402,
+ ATOM_UWB_SESSION_CLOSED = 403,
+ ATOM_UWB_FIRST_RANGING_RECEIVED = 404,
+ ATOM_UWB_RANGING_MEASUREMENT_RECEIVED = 405,
+ ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_SCHEDULED = 406,
+ ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_COMPLETED = 407,
+ ATOM_CLIPBOARD_CLEARED = 408,
+ ATOM_VM_CREATION_REQUESTED = 409,
+ ATOM_NEARBY_DEVICE_SCAN_STATE_CHANGED = 410,
+ ATOM_CAMERA_COMPAT_CONTROL_EVENT_REPORTED = 411,
+ ATOM_APPLICATION_LOCALES_CHANGED = 412,
+ ATOM_MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED = 413,
+ ATOM_FOLD_STATE_DURATION_REPORTED = 414,
+ ATOM_LOCATION_TIME_ZONE_PROVIDER_CONTROLLER_STATE_CHANGED = 415,
+ ATOM_DISPLAY_HBM_STATE_CHANGED = 416,
+ ATOM_DISPLAY_HBM_BRIGHTNESS_CHANGED = 417,
+ ATOM_PERSISTENT_URI_PERMISSIONS_FLUSHED = 418,
+ ATOM_EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED = 419,
+ ATOM_VBMETA_DIGEST_REPORTED = 420,
+ ATOM_APEX_INFO_GATHERED = 421,
+ ATOM_PVM_INFO_GATHERED = 422,
+ ATOM_WEAR_SETTINGS_UI_INTERACTED = 423,
+ ATOM_TRACING_SERVICE_REPORT_EVENT = 424,
+ ATOM_MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED = 425,
+ ATOM_LAUNCHER_LATENCY = 426,
+ ATOM_DROPBOX_ENTRY_DROPPED = 427,
+ ATOM_WIFI_P2P_CONNECTION_REPORTED = 428,
+ ATOM_GAME_STATE_CHANGED = 429,
+ ATOM_HOTWORD_DETECTOR_CREATE_REQUESTED = 430,
+ ATOM_HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED = 431,
+ ATOM_HOTWORD_DETECTION_SERVICE_RESTARTED = 432,
+ ATOM_HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED = 433,
+ ATOM_HOTWORD_DETECTOR_EVENTS = 434,
+ ATOM_AD_SERVICES_API_CALLED = 435,
+ ATOM_AD_SERVICES_MESUREMENT_REPORTS_UPLOADED = 436,
+ ATOM_BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED = 437,
+ ATOM_CONTACTS_INDEXER_UPDATE_STATS_REPORTED = 440,
+ ATOM_APP_BACKGROUND_RESTRICTIONS_INFO = 441,
+ ATOM_MMS_SMS_PROVIDER_GET_THREAD_ID_FAILED = 442,
+ ATOM_MMS_SMS_DATABASE_HELPER_ON_UPGRADE_FAILED = 443,
+ ATOM_PERMISSION_REMINDER_NOTIFICATION_INTERACTED = 444,
+ ATOM_RECENT_PERMISSION_DECISIONS_INTERACTED = 445,
+ ATOM_GNSS_PSDS_DOWNLOAD_REPORTED = 446,
+ ATOM_LE_AUDIO_CONNECTION_SESSION_REPORTED = 447,
+ ATOM_LE_AUDIO_BROADCAST_SESSION_REPORTED = 448,
+ ATOM_DREAM_UI_EVENT_REPORTED = 449,
+ ATOM_TASK_MANAGER_EVENT_REPORTED = 450,
+ ATOM_CDM_ASSOCIATION_ACTION = 451,
+ ATOM_MAGNIFICATION_TRIPLE_TAP_AND_HOLD_ACTIVATED_SESSION_REPORTED = 452,
+ ATOM_MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED = 453,
+ ATOM_ACCESSIBILITY_TEXT_READING_OPTIONS_CHANGED = 454,
+ ATOM_WIFI_SETUP_FAILURE_CRASH_REPORTED = 455,
+ ATOM_UWB_DEVICE_ERROR_REPORTED = 456,
+ ATOM_ISOLATED_COMPILATION_SCHEDULED = 457,
+ ATOM_ISOLATED_COMPILATION_ENDED = 458,
+ ATOM_ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE = 459,
+ ATOM_SYSTEM_SERVER_PRE_WATCHDOG_OCCURRED = 460,
+ ATOM_TELEPHONY_ANOMALY_DETECTED = 461,
+ ATOM_LETTERBOX_POSITION_CHANGED = 462,
+ ATOM_REMOTE_KEY_PROVISIONING_ATTEMPT = 463,
+ ATOM_REMOTE_KEY_PROVISIONING_NETWORK_INFO = 464,
+ ATOM_REMOTE_KEY_PROVISIONING_TIMING = 465,
+ ATOM_MEDIAOUTPUT_OP_INTERACTION_REPORT = 466,
+ ATOM_SYNC_EXEMPTION_OCCURRED = 468,
+ ATOM_AUTOFILL_PRESENTATION_EVENT_REPORTED = 469,
+ ATOM_DOCK_STATE_CHANGED = 470,
+ ATOM_SAFETY_SOURCE_STATE_COLLECTED = 471,
+ ATOM_SAFETY_CENTER_SYSTEM_EVENT_REPORTED = 472,
+ ATOM_SAFETY_CENTER_INTERACTION_REPORTED = 473,
+ ATOM_SETTINGS_PROVIDER_SETTING_CHANGED = 474,
+ ATOM_BROADCAST_DELIVERY_EVENT_REPORTED = 475,
+ ATOM_SERVICE_REQUEST_EVENT_REPORTED = 476,
+ ATOM_PROVIDER_ACQUISITION_EVENT_REPORTED = 477,
+ ATOM_BLUETOOTH_DEVICE_NAME_REPORTED = 478,
+ ATOM_CB_CONFIG_UPDATED = 479,
+ ATOM_CB_MODULE_ERROR_REPORTED = 480,
+ ATOM_CB_SERVICE_FEATURE_CHANGED = 481,
+ ATOM_CB_RECEIVER_FEATURE_CHANGED = 482,
+ ATOM_JSSCRIPTENGINE_LATENCY_REPORTED = 483,
+ ATOM_PRIVACY_SIGNAL_NOTIFICATION_INTERACTION = 484,
+ ATOM_PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION = 485,
+ ATOM_PRIVACY_SIGNALS_JOB_FAILURE = 486,
+ ATOM_VIBRATION_REPORTED = 487,
+ ATOM_UWB_RANGING_START = 489,
+ ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STATUS_REPORTED = 490,
+ ATOM_APP_COMPACTED_V2 = 491,
+ ATOM_AD_SERVICES_SETTINGS_USAGE_REPORTED = 493,
+ ATOM_DISPLAY_BRIGHTNESS_CHANGED = 494,
+ ATOM_ACTIVITY_ACTION_BLOCKED = 495,
+ ATOM_BACKGROUND_FETCH_PROCESS_REPORTED = 496,
+ ATOM_UPDATE_CUSTOM_AUDIENCE_PROCESS_REPORTED = 497,
+ ATOM_RUN_AD_BIDDING_PROCESS_REPORTED = 498,
+ ATOM_RUN_AD_SCORING_PROCESS_REPORTED = 499,
+ ATOM_RUN_AD_SELECTION_PROCESS_REPORTED = 500,
+ ATOM_RUN_AD_BIDDING_PER_CA_PROCESS_REPORTED = 501,
+ ATOM_MOBILE_DATA_DOWNLOAD_DOWNLOAD_RESULT_REPORTED = 502,
+ ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STORAGE_STATS_REPORTED = 503,
+ ATOM_NETWORK_DNS_SERVER_SUPPORT_REPORTED = 504,
+ ATOM_VM_BOOTED = 505,
+ ATOM_VM_EXITED = 506,
+ ATOM_AMBIENT_BRIGHTNESS_STATS_REPORTED = 507,
+ ATOM_MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED = 508,
+ ATOM_MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED = 509,
+ ATOM_MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED = 510,
+ ATOM_MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED = 511,
+ ATOM_AD_SERVICES_MEASUREMENT_REGISTRATIONS = 512,
+ ATOM_HEARING_AID_INFO_REPORTED = 513,
+ ATOM_DEVICE_WIDE_JOB_CONSTRAINT_CHANGED = 514,
+ ATOM_AMBIENT_MODE_CHANGED = 515,
+ ATOM_ANR_LATENCY_REPORTED = 516,
+ ATOM_RESOURCE_API_INFO = 517,
+ ATOM_SYSTEM_DEFAULT_NETWORK_CHANGED = 518,
+ ATOM_IWLAN_SETUP_DATA_CALL_RESULT_REPORTED = 519,
+ ATOM_IWLAN_PDN_DISCONNECTED_REASON_REPORTED = 520,
+ ATOM_AIRPLANE_MODE_SESSION_REPORTED = 521,
+ ATOM_VM_CPU_STATUS_REPORTED = 522,
+ ATOM_VM_MEM_STATUS_REPORTED = 523,
+ ATOM_PACKAGE_INSTALLATION_SESSION_REPORTED = 524,
+ ATOM_DEFAULT_NETWORK_REMATCH_INFO = 525,
+ ATOM_NETWORK_SELECTION_PERFORMANCE = 526,
+ ATOM_NETWORK_NSD_REPORTED = 527,
+ ATOM_BLUETOOTH_DISCONNECTION_REASON_REPORTED = 529,
+ ATOM_BLUETOOTH_LOCAL_VERSIONS_REPORTED = 530,
+ ATOM_BLUETOOTH_REMOTE_SUPPORTED_FEATURES_REPORTED = 531,
+ ATOM_BLUETOOTH_LOCAL_SUPPORTED_FEATURES_REPORTED = 532,
+ ATOM_BLUETOOTH_GATT_APP_INFO = 533,
+ ATOM_BRIGHTNESS_CONFIGURATION_UPDATED = 534,
+ ATOM_AD_SERVICES_GET_TOPICS_REPORTED = 535,
+ ATOM_AD_SERVICES_EPOCH_COMPUTATION_GET_TOP_TOPICS_REPORTED = 536,
+ ATOM_AD_SERVICES_EPOCH_COMPUTATION_CLASSIFIER_REPORTED = 537,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_LAUNCHED = 538,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FINISHED = 539,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECTION_REPORTED = 540,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_DEVICE_SCAN_TRIGGERED = 541,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FIRST_DEVICE_SCAN_LATENCY = 542,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECT_DEVICE_LATENCY = 543,
+ ATOM_PACKAGE_MANAGER_SNAPSHOT_REPORTED = 544,
+ ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED = 545,
+ ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED = 546,
+ ATOM_LAUNCHER_IMPRESSION_EVENT = 547,
+ ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_ALL_DEVICES_SCAN_LATENCY = 549,
+ ATOM_WS_WATCH_FACE_EDITED = 551,
+ ATOM_WS_WATCH_FACE_FAVORITE_ACTION_REPORTED = 552,
+ ATOM_WS_WATCH_FACE_SET_ACTION_REPORTED = 553,
+ ATOM_PACKAGE_UNINSTALLATION_REPORTED = 554,
+ ATOM_GAME_MODE_CHANGED = 555,
+ ATOM_GAME_MODE_CONFIGURATION_CHANGED = 556,
+ ATOM_BEDTIME_MODE_STATE_CHANGED = 557,
+ ATOM_NETWORK_SLICE_SESSION_ENDED = 558,
+ ATOM_NETWORK_SLICE_DAILY_DATA_USAGE_REPORTED = 559,
+ ATOM_NFC_TAG_TYPE_OCCURRED = 560,
+ ATOM_NFC_AID_CONFLICT_OCCURRED = 561,
+ ATOM_NFC_READER_CONFLICT_OCCURRED = 562,
+ ATOM_WS_TILE_LIST_CHANGED = 563,
+ ATOM_GET_TYPE_ACCESSED_WITHOUT_PERMISSION = 564,
+ ATOM_MOBILE_BUNDLED_APP_INFO_GATHERED = 566,
+ ATOM_WS_WATCH_FACE_COMPLICATION_SET_CHANGED = 567,
+ ATOM_MEDIA_DRM_CREATED = 568,
+ ATOM_MEDIA_DRM_ERRORED = 569,
+ ATOM_MEDIA_DRM_SESSION_OPENED = 570,
+ ATOM_MEDIA_DRM_SESSION_CLOSED = 571,
+ ATOM_USER_SELECTED_RESOLUTION = 572,
+ ATOM_UNSAFE_INTENT_EVENT_REPORTED = 573,
+ ATOM_PERFORMANCE_HINT_SESSION_REPORTED = 574,
+ ATOM_MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED = 576,
+ ATOM_BIOMETRIC_TOUCH_REPORTED = 577,
+ ATOM_HOTWORD_AUDIO_EGRESS_EVENT_REPORTED = 578,
+ ATOM_APP_SEARCH_SCHEMA_MIGRATION_STATS_REPORTED = 579,
+ ATOM_LOCATION_ENABLED_STATE_CHANGED = 580,
+ ATOM_IME_REQUEST_FINISHED = 581,
+ ATOM_USB_COMPLIANCE_WARNINGS_REPORTED = 582,
+ ATOM_APP_SUPPORTED_LOCALES_CHANGED = 583,
+ ATOM_GRAMMATICAL_INFLECTION_CHANGED = 584,
+ ATOM_MEDIA_PROVIDER_VOLUME_RECOVERY_REPORTED = 586,
+ ATOM_BIOMETRIC_PROPERTIES_COLLECTED = 587,
+ ATOM_KERNEL_WAKEUP_ATTRIBUTED = 588,
+ ATOM_SCREEN_STATE_CHANGED_V2 = 589,
+ ATOM_WS_BACKUP_ACTION_REPORTED = 590,
+ ATOM_WS_RESTORE_ACTION_REPORTED = 591,
+ ATOM_DEVICE_LOG_ACCESS_EVENT_REPORTED = 592,
+ ATOM_MEDIA_SESSION_UPDATED = 594,
+ ATOM_WEAR_OOBE_STATE_CHANGED = 595,
+ ATOM_WS_NOTIFICATION_UPDATED = 596,
+ ATOM_NETWORK_VALIDATION_FAILURE_STATS_DAILY_REPORTED = 601,
+ ATOM_WS_COMPLICATION_TAPPED = 602,
+ ATOM_WS_WEAR_TIME_SESSION = 610,
+ ATOM_WIFI_BYTES_TRANSFER = 10000,
+ ATOM_WIFI_BYTES_TRANSFER_BY_FG_BG = 10001,
+ ATOM_MOBILE_BYTES_TRANSFER = 10002,
+ ATOM_MOBILE_BYTES_TRANSFER_BY_FG_BG = 10003,
+ ATOM_BLUETOOTH_BYTES_TRANSFER = 10006,
+ ATOM_KERNEL_WAKELOCK = 10004,
+ ATOM_SUBSYSTEM_SLEEP_STATE = 10005,
+ ATOM_CPU_TIME_PER_UID = 10009,
+ ATOM_CPU_TIME_PER_UID_FREQ = 10010,
+ ATOM_WIFI_ACTIVITY_INFO = 10011,
+ ATOM_MODEM_ACTIVITY_INFO = 10012,
+ ATOM_BLUETOOTH_ACTIVITY_INFO = 10007,
+ ATOM_PROCESS_MEMORY_STATE = 10013,
+ ATOM_SYSTEM_ELAPSED_REALTIME = 10014,
+ ATOM_SYSTEM_UPTIME = 10015,
+ ATOM_CPU_ACTIVE_TIME = 10016,
+ ATOM_CPU_CLUSTER_TIME = 10017,
+ ATOM_DISK_SPACE = 10018,
+ ATOM_REMAINING_BATTERY_CAPACITY = 10019,
+ ATOM_FULL_BATTERY_CAPACITY = 10020,
+ ATOM_TEMPERATURE = 10021,
+ ATOM_BINDER_CALLS = 10022,
+ ATOM_BINDER_CALLS_EXCEPTIONS = 10023,
+ ATOM_LOOPER_STATS = 10024,
+ ATOM_DISK_STATS = 10025,
+ ATOM_DIRECTORY_USAGE = 10026,
+ ATOM_APP_SIZE = 10027,
+ ATOM_CATEGORY_SIZE = 10028,
+ ATOM_PROC_STATS = 10029,
+ ATOM_BATTERY_VOLTAGE = 10030,
+ ATOM_NUM_FINGERPRINTS_ENROLLED = 10031,
+ ATOM_DISK_IO = 10032,
+ ATOM_POWER_PROFILE = 10033,
+ ATOM_PROC_STATS_PKG_PROC = 10034,
+ ATOM_PROCESS_CPU_TIME = 10035,
+ ATOM_CPU_TIME_PER_THREAD_FREQ = 10037,
+ ATOM_ON_DEVICE_POWER_MEASUREMENT = 10038,
+ ATOM_DEVICE_CALCULATED_POWER_USE = 10039,
+ ATOM_PROCESS_MEMORY_HIGH_WATER_MARK = 10042,
+ ATOM_BATTERY_LEVEL = 10043,
+ ATOM_BUILD_INFORMATION = 10044,
+ ATOM_BATTERY_CYCLE_COUNT = 10045,
+ ATOM_DEBUG_ELAPSED_CLOCK = 10046,
+ ATOM_DEBUG_FAILING_ELAPSED_CLOCK = 10047,
+ ATOM_NUM_FACES_ENROLLED = 10048,
+ ATOM_ROLE_HOLDER = 10049,
+ ATOM_DANGEROUS_PERMISSION_STATE = 10050,
+ ATOM_TRAIN_INFO = 10051,
+ ATOM_TIME_ZONE_DATA_INFO = 10052,
+ ATOM_EXTERNAL_STORAGE_INFO = 10053,
+ ATOM_GPU_STATS_GLOBAL_INFO = 10054,
+ ATOM_GPU_STATS_APP_INFO = 10055,
+ ATOM_SYSTEM_ION_HEAP_SIZE = 10056,
+ ATOM_APPS_ON_EXTERNAL_STORAGE_INFO = 10057,
+ ATOM_FACE_SETTINGS = 10058,
+ ATOM_COOLING_DEVICE = 10059,
+ ATOM_APP_OPS = 10060,
+ ATOM_PROCESS_SYSTEM_ION_HEAP_SIZE = 10061,
+ ATOM_SURFACEFLINGER_STATS_GLOBAL_INFO = 10062,
+ ATOM_SURFACEFLINGER_STATS_LAYER_INFO = 10063,
+ ATOM_PROCESS_MEMORY_SNAPSHOT = 10064,
+ ATOM_VMS_CLIENT_STATS = 10065,
+ ATOM_NOTIFICATION_REMOTE_VIEWS = 10066,
+ ATOM_DANGEROUS_PERMISSION_STATE_SAMPLED = 10067,
+ ATOM_GRAPHICS_STATS = 10068,
+ ATOM_RUNTIME_APP_OP_ACCESS = 10069,
+ ATOM_ION_HEAP_SIZE = 10070,
+ ATOM_PACKAGE_NOTIFICATION_PREFERENCES = 10071,
+ ATOM_PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES = 10072,
+ ATOM_PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES = 10073,
+ ATOM_GNSS_STATS = 10074,
+ ATOM_ATTRIBUTED_APP_OPS = 10075,
+ ATOM_VOICE_CALL_SESSION = 10076,
+ ATOM_VOICE_CALL_RAT_USAGE = 10077,
+ ATOM_SIM_SLOT_STATE = 10078,
+ ATOM_SUPPORTED_RADIO_ACCESS_FAMILY = 10079,
+ ATOM_SETTING_SNAPSHOT = 10080,
+ ATOM_BLOB_INFO = 10081,
+ ATOM_DATA_USAGE_BYTES_TRANSFER = 10082,
+ ATOM_BYTES_TRANSFER_BY_TAG_AND_METERED = 10083,
+ ATOM_DND_MODE_RULE = 10084,
+ ATOM_GENERAL_EXTERNAL_STORAGE_ACCESS_STATS = 10085,
+ ATOM_INCOMING_SMS = 10086,
+ ATOM_OUTGOING_SMS = 10087,
+ ATOM_CARRIER_ID_TABLE_VERSION = 10088,
+ ATOM_DATA_CALL_SESSION = 10089,
+ ATOM_CELLULAR_SERVICE_STATE = 10090,
+ ATOM_CELLULAR_DATA_SERVICE_SWITCH = 10091,
+ ATOM_SYSTEM_MEMORY = 10092,
+ ATOM_IMS_REGISTRATION_TERMINATION = 10093,
+ ATOM_IMS_REGISTRATION_STATS = 10094,
+ ATOM_CPU_TIME_PER_CLUSTER_FREQ = 10095,
+ ATOM_CPU_CYCLES_PER_UID_CLUSTER = 10096,
+ ATOM_DEVICE_ROTATED_DATA = 10097,
+ ATOM_CPU_CYCLES_PER_THREAD_GROUP_CLUSTER = 10098,
+ ATOM_MEDIA_DRM_ACTIVITY_INFO = 10099,
+ ATOM_OEM_MANAGED_BYTES_TRANSFER = 10100,
+ ATOM_GNSS_POWER_STATS = 10101,
+ ATOM_TIME_ZONE_DETECTOR_STATE = 10102,
+ ATOM_KEYSTORE2_STORAGE_STATS = 10103,
+ ATOM_RKP_POOL_STATS = 10104,
+ ATOM_PROCESS_DMABUF_MEMORY = 10105,
+ ATOM_PENDING_ALARM_INFO = 10106,
+ ATOM_USER_LEVEL_HIBERNATED_APPS = 10107,
+ ATOM_LAUNCHER_LAYOUT_SNAPSHOT = 10108,
+ ATOM_GLOBAL_HIBERNATED_APPS = 10109,
+ ATOM_INPUT_EVENT_LATENCY_SKETCH = 10110,
+ ATOM_BATTERY_USAGE_STATS_BEFORE_RESET = 10111,
+ ATOM_BATTERY_USAGE_STATS_SINCE_RESET = 10112,
+ ATOM_BATTERY_USAGE_STATS_SINCE_RESET_USING_POWER_PROFILE_MODEL = 10113,
+ ATOM_INSTALLED_INCREMENTAL_PACKAGE = 10114,
+ ATOM_TELEPHONY_NETWORK_REQUESTS = 10115,
+ ATOM_APP_SEARCH_STORAGE_INFO = 10116,
+ ATOM_VMSTAT = 10117,
+ ATOM_KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO = 10118,
+ ATOM_KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO = 10119,
+ ATOM_KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO = 10120,
+ ATOM_KEYSTORE2_ATOM_WITH_OVERFLOW = 10121,
+ ATOM_KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO = 10122,
+ ATOM_KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO = 10123,
+ ATOM_RKP_ERROR_STATS = 10124,
+ ATOM_KEYSTORE2_CRASH_STATS = 10125,
+ ATOM_VENDOR_APEX_INFO = 10126,
+ ATOM_ACCESSIBILITY_SHORTCUT_STATS = 10127,
+ ATOM_ACCESSIBILITY_FLOATING_MENU_STATS = 10128,
+ ATOM_DATA_USAGE_BYTES_TRANSFER_V2 = 10129,
+ ATOM_MEDIA_CAPABILITIES = 10130,
+ ATOM_CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY = 10131,
+ ATOM_CAR_WATCHDOG_UID_IO_USAGE_SUMMARY = 10132,
+ ATOM_IMS_REGISTRATION_FEATURE_TAG_STATS = 10133,
+ ATOM_RCS_CLIENT_PROVISIONING_STATS = 10134,
+ ATOM_RCS_ACS_PROVISIONING_STATS = 10135,
+ ATOM_SIP_DELEGATE_STATS = 10136,
+ ATOM_SIP_TRANSPORT_FEATURE_TAG_STATS = 10137,
+ ATOM_SIP_MESSAGE_RESPONSE = 10138,
+ ATOM_SIP_TRANSPORT_SESSION = 10139,
+ ATOM_IMS_DEDICATED_BEARER_LISTENER_EVENT = 10140,
+ ATOM_IMS_DEDICATED_BEARER_EVENT = 10141,
+ ATOM_IMS_REGISTRATION_SERVICE_DESC_STATS = 10142,
+ ATOM_UCE_EVENT_STATS = 10143,
+ ATOM_PRESENCE_NOTIFY_EVENT = 10144,
+ ATOM_GBA_EVENT = 10145,
+ ATOM_PER_SIM_STATUS = 10146,
+ ATOM_GPU_WORK_PER_UID = 10147,
+ ATOM_PERSISTENT_URI_PERMISSIONS_AMOUNT_PER_PACKAGE = 10148,
+ ATOM_SIGNED_PARTITION_INFO = 10149,
+ ATOM_PINNED_FILE_SIZES_PER_PACKAGE = 10150,
+ ATOM_PENDING_INTENTS_PER_PACKAGE = 10151,
+ ATOM_USER_INFO = 10152,
+ ATOM_TELEPHONY_NETWORK_REQUESTS_V2 = 10153,
+ ATOM_DEVICE_TELEPHONY_PROPERTIES = 10154,
+ ATOM_REMOTE_KEY_PROVISIONING_ERROR_COUNTS = 10155,
+ ATOM_SAFETY_STATE = 10156,
+ ATOM_INCOMING_MMS = 10157,
+ ATOM_OUTGOING_MMS = 10158,
+ ATOM_MULTI_USER_INFO = 10160,
+ ATOM_NETWORK_BPF_MAP_INFO = 10161,
+ ATOM_OUTGOING_SHORT_CODE_SMS = 10162,
+ ATOM_CONNECTIVITY_STATE_SAMPLE = 10163,
+ ATOM_NETWORK_SELECTION_REMATCH_REASONS_INFO = 10164,
+ ATOM_GAME_MODE_INFO = 10165,
+ ATOM_GAME_MODE_CONFIGURATION = 10166,
+ ATOM_GAME_MODE_LISTENER = 10167,
+ ATOM_NETWORK_SLICE_REQUEST_COUNT = 10168,
+ ATOM_WS_TILE_SNAPSHOT = 10169,
+ ATOM_WS_ACTIVE_WATCH_FACE_COMPLICATION_SET_SNAPSHOT = 10170,
+ ATOM_PROCESS_STATE = 10171,
+ ATOM_PROCESS_ASSOCIATION = 10172,
+ ATOM_ADPF_SYSTEM_COMPONENT_INFO = 10173,
+ ATOM_NOTIFICATION_MEMORY_USE = 10174,
+ ATOM_HDR_CAPABILITIES = 10175,
+ ATOM_WS_FAVOURITE_WATCH_FACE_LIST_SNAPSHOT = 10176,
+ ATOM_WIFI_AWARE_NDP_REPORTED = 638,
+ ATOM_WIFI_AWARE_ATTACH_REPORTED = 639,
+ ATOM_WIFI_SELF_RECOVERY_TRIGGERED = 661,
+ ATOM_SOFT_AP_STARTED = 680,
+ ATOM_SOFT_AP_STOPPED = 681,
+ ATOM_WIFI_LOCK_RELEASED = 687,
+ ATOM_WIFI_LOCK_DEACTIVATED = 688,
+ ATOM_WIFI_CONFIG_SAVED = 689,
+ ATOM_WIFI_AWARE_RESOURCE_USING_CHANGED = 690,
+ ATOM_WIFI_AWARE_HAL_API_CALLED = 691,
+ ATOM_WIFI_LOCAL_ONLY_REQUEST_RECEIVED = 692,
+ ATOM_WIFI_LOCAL_ONLY_REQUEST_SCAN_TRIGGERED = 693,
+ ATOM_WIFI_THREAD_TASK_EXECUTED = 694,
+ ATOM_WIFI_STATE_CHANGED = 700,
+ ATOM_WIFI_AWARE_CAPABILITIES = 10190,
+ ATOM_WIFI_MODULE_INFO = 10193,
+ ATOM_SETTINGS_SPA_REPORTED = 622,
+ ATOM_EXPRESS_EVENT_REPORTED = 528,
+ ATOM_EXPRESS_HISTOGRAM_SAMPLE_REPORTED = 593,
+ ATOM_EXPRESS_UID_EVENT_REPORTED = 644,
+ ATOM_EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED = 658,
+ ATOM_PERMISSION_RATIONALE_DIALOG_VIEWED = 645,
+ ATOM_PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED = 646,
+ ATOM_APP_DATA_SHARING_UPDATES_NOTIFICATION_INTERACTION = 647,
+ ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_VIEWED = 648,
+ ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_ACTION_REPORTED = 649,
+ ATOM_WS_INCOMING_CALL_ACTION_REPORTED = 626,
+ ATOM_WS_CALL_DISCONNECTION_REPORTED = 627,
+ ATOM_WS_CALL_DURATION_REPORTED = 628,
+ ATOM_WS_CALL_USER_EXPERIENCE_LATENCY_REPORTED = 629,
+ ATOM_WS_CALL_INTERACTION_REPORTED = 630,
+ ATOM_FULL_SCREEN_INTENT_LAUNCHED = 631,
+ ATOM_BAL_ALLOWED = 632,
+ ATOM_IN_TASK_ACTIVITY_STARTED = 685,
+ ATOM_CACHED_APPS_HIGH_WATERMARK = 10189,
+ ATOM_ODREFRESH_REPORTED = 366,
+ ATOM_ODSIGN_REPORTED = 548,
+ ATOM_ART_DATUM_REPORTED = 332,
+ ATOM_ART_DEVICE_DATUM_REPORTED = 550,
+ ATOM_ART_DATUM_DELTA_REPORTED = 565,
+ ATOM_BACKGROUND_DEXOPT_JOB_ENDED = 467,
+ ATOM_WEAR_ADAPTIVE_SUSPEND_STATS_REPORTED = 619,
+ ATOM_WEAR_POWER_ANOMALY_SERVICE_OPERATIONAL_STATS_REPORTED = 620,
+ ATOM_WEAR_POWER_ANOMALY_SERVICE_EVENT_STATS_REPORTED = 621,
+ ATOM_EMERGENCY_STATE_CHANGED = 633,
+ ATOM_DND_STATE_CHANGED = 657,
+ ATOM_MTE_STATE = 10181,
+ ATOM_AD_SERVICES_BACK_COMPAT_GET_TOPICS_REPORTED = 598,
+ ATOM_AD_SERVICES_BACK_COMPAT_EPOCH_COMPUTATION_CLASSIFIER_REPORTED = 599,
+ ATOM_AD_SERVICES_MEASUREMENT_DEBUG_KEYS = 640,
+ ATOM_AD_SERVICES_ERROR_REPORTED = 662,
+ ATOM_AD_SERVICES_BACKGROUND_JOBS_EXECUTION_REPORTED = 663,
+ ATOM_AD_SERVICES_MEASUREMENT_DELAYED_SOURCE_REGISTRATION = 673,
+ ATOM_AD_SERVICES_MEASUREMENT_ATTRIBUTION = 674,
+ ATOM_AD_SERVICES_MEASUREMENT_JOBS = 675,
+ ATOM_AD_SERVICES_MEASUREMENT_WIPEOUT = 676,
+ ATOM_AD_SERVICES_CONSENT_MIGRATED = 702,
+ ATOM_RKPD_POOL_STATS = 664,
+ ATOM_RKPD_CLIENT_OPERATION = 665,
+ ATOM_AUTOFILL_UI_EVENT_REPORTED = 603,
+ ATOM_AUTOFILL_FILL_REQUEST_REPORTED = 604,
+ ATOM_AUTOFILL_FILL_RESPONSE_REPORTED = 605,
+ ATOM_AUTOFILL_SAVE_EVENT_REPORTED = 606,
+ ATOM_AUTOFILL_SESSION_COMMITTED = 607,
+ ATOM_AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED = 659,
+ ATOM_TEST_EXTENSION_ATOM_REPORTED = 660,
+ ATOM_TEST_RESTRICTED_ATOM_REPORTED = 672,
+ ATOM_STATS_SOCKET_LOSS_REPORTED = 752,
+ ATOM_PLUGIN_INITIALIZED = 655,
+ ATOM_TV_LOW_POWER_STANDBY_POLICY = 679,
+ ATOM_LOCKSCREEN_SHORTCUT_SELECTED = 611,
+ ATOM_LOCKSCREEN_SHORTCUT_TRIGGERED = 612,
+ ATOM_EMERGENCY_NUMBERS_INFO = 10180,
+ ATOM_QUALIFIED_RAT_LIST_CHANGED = 634,
+ ATOM_QNS_IMS_CALL_DROP_STATS = 635,
+ ATOM_QNS_FALLBACK_RESTRICTION_CHANGED = 636,
+ ATOM_QNS_RAT_PREFERENCE_MISMATCH_INFO = 10177,
+ ATOM_QNS_HANDOVER_TIME_MILLIS = 10178,
+ ATOM_QNS_HANDOVER_PINGPONG = 10179,
+ ATOM_SATELLITE_CONTROLLER = 10182,
+ ATOM_SATELLITE_SESSION = 10183,
+ ATOM_SATELLITE_INCOMING_DATAGRAM = 10184,
+ ATOM_SATELLITE_OUTGOING_DATAGRAM = 10185,
+ ATOM_SATELLITE_PROVISION = 10186,
+ ATOM_SATELLITE_SOS_MESSAGE_RECOMMENDER = 10187,
+ ATOM_IKE_SESSION_TERMINATED = 678,
+ ATOM_IKE_LIVENESS_CHECK_SESSION_VALIDATED = 760,
+ ATOM_BLUETOOTH_HASHED_DEVICE_NAME_REPORTED = 613,
+ ATOM_BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION = 614,
+ ATOM_BLUETOOTH_L2CAP_COC_SERVER_CONNECTION = 615,
+ ATOM_BLUETOOTH_LE_SESSION_CONNECTED = 656,
+ ATOM_RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED = 666,
+ ATOM_BLUETOOTH_PROFILE_CONNECTION_ATTEMPTED = 696,
+ ATOM_HEALTH_CONNECT_UI_IMPRESSION = 623,
+ ATOM_HEALTH_CONNECT_UI_INTERACTION = 624,
+ ATOM_HEALTH_CONNECT_APP_OPENED_REPORTED = 625,
+ ATOM_HEALTH_CONNECT_API_CALLED = 616,
+ ATOM_HEALTH_CONNECT_USAGE_STATS = 617,
+ ATOM_HEALTH_CONNECT_STORAGE_STATS = 618,
+ ATOM_HEALTH_CONNECT_API_INVOKED = 643,
+ ATOM_EXERCISE_ROUTE_API_CALLED = 654,
+ ATOM_ATOM_9999 = 9999,
+ ATOM_ATOM_99999 = 99999,
+ ATOM_THREADNETWORK_TELEMETRY_DATA_REPORTED = 738,
+ ATOM_THREADNETWORK_TOPO_ENTRY_REPEATED = 739,
+ ATOM_THREADNETWORK_DEVICE_INFO_REPORTED = 740,
+ ATOM_EMERGENCY_NUMBER_DIALED = 637,
+ ATOM_SANDBOX_API_CALLED = 488,
+ ATOM_SANDBOX_ACTIVITY_EVENT_OCCURRED = 735,
+ ATOM_SANDBOX_SDK_STORAGE = 10159,
+ ATOM_CRONET_ENGINE_CREATED = 703,
+ ATOM_CRONET_TRAFFIC_REPORTED = 704,
+ ATOM_CRONET_ENGINE_BUILDER_INITIALIZED = 762,
+ ATOM_CRONET_HTTP_FLAGS_INITIALIZED = 763,
+ ATOM_CRONET_INITIALIZED = 764,
+ ATOM_DAILY_KEEPALIVE_INFO_REPORTED = 650,
+ ATOM_IP_CLIENT_RA_INFO_REPORTED = 778,
+ ATOM_APF_SESSION_INFO_REPORTED = 777,
+ ATOM_CREDENTIAL_MANAGER_API_CALLED = 585,
+ ATOM_CREDENTIAL_MANAGER_INIT_PHASE_REPORTED = 651,
+ ATOM_CREDENTIAL_MANAGER_CANDIDATE_PHASE_REPORTED = 652,
+ ATOM_CREDENTIAL_MANAGER_FINAL_PHASE_REPORTED = 653,
+ ATOM_CREDENTIAL_MANAGER_TOTAL_REPORTED = 667,
+ ATOM_CREDENTIAL_MANAGER_FINALNOUID_REPORTED = 668,
+ ATOM_CREDENTIAL_MANAGER_GET_REPORTED = 669,
+ ATOM_CREDENTIAL_MANAGER_AUTH_CLICK_REPORTED = 670,
+ ATOM_CREDENTIAL_MANAGER_APIV2_CALLED = 671,
+ ATOM_UWB_ACTIVITY_INFO = 10188,
+ ATOM_MEDIA_ACTION_REPORTED = 608,
+ ATOM_MEDIA_CONTROLS_LAUNCHED = 609,
+ ATOM_MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED = 600,
+ ATOM_MEDIA_CODEC_STARTED = 641,
+ ATOM_MEDIA_CODEC_STOPPED = 642,
+ ATOM_MEDIA_CODEC_RENDERED = 684,
+};
+
+constexpr AtomId AtomId_MIN = AtomId::ATOM_UNSPECIFIED;
+constexpr AtomId AtomId_MAX = AtomId::ATOM_ATOM_99999;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* AtomId_Name(::perfetto::protos::pbzero::AtomId value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UNSPECIFIED:
+ return "ATOM_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLE_SCAN_STATE_CHANGED:
+ return "ATOM_BLE_SCAN_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_STATE_CHANGED:
+ return "ATOM_PROCESS_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLE_SCAN_RESULT_RECEIVED:
+ return "ATOM_BLE_SCAN_RESULT_RECEIVED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SENSOR_STATE_CHANGED:
+ return "ATOM_SENSOR_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GPS_SCAN_STATE_CHANGED:
+ return "ATOM_GPS_SCAN_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYNC_STATE_CHANGED:
+ return "ATOM_SYNC_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SCHEDULED_JOB_STATE_CHANGED:
+ return "ATOM_SCHEDULED_JOB_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SCREEN_BRIGHTNESS_CHANGED:
+ return "ATOM_SCREEN_BRIGHTNESS_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WAKELOCK_STATE_CHANGED:
+ return "ATOM_WAKELOCK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LONG_PARTIAL_WAKELOCK_STATE_CHANGED:
+ return "ATOM_LONG_PARTIAL_WAKELOCK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_RADIO_POWER_STATE_CHANGED:
+ return "ATOM_MOBILE_RADIO_POWER_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_RADIO_POWER_STATE_CHANGED:
+ return "ATOM_WIFI_RADIO_POWER_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACTIVITY_MANAGER_SLEEP_STATE_CHANGED:
+ return "ATOM_ACTIVITY_MANAGER_SLEEP_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEMORY_FACTOR_STATE_CHANGED:
+ return "ATOM_MEMORY_FACTOR_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXCESSIVE_CPU_USAGE_REPORTED:
+ return "ATOM_EXCESSIVE_CPU_USAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CACHED_KILL_REPORTED:
+ return "ATOM_CACHED_KILL_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_MEMORY_STAT_REPORTED:
+ return "ATOM_PROCESS_MEMORY_STAT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LAUNCHER_EVENT:
+ return "ATOM_LAUNCHER_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_SAVER_MODE_STATE_CHANGED:
+ return "ATOM_BATTERY_SAVER_MODE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_IDLE_MODE_STATE_CHANGED:
+ return "ATOM_DEVICE_IDLE_MODE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_IDLING_MODE_STATE_CHANGED:
+ return "ATOM_DEVICE_IDLING_MODE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUDIO_STATE_CHANGED:
+ return "ATOM_AUDIO_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CODEC_STATE_CHANGED:
+ return "ATOM_MEDIA_CODEC_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAMERA_STATE_CHANGED:
+ return "ATOM_CAMERA_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FLASHLIGHT_STATE_CHANGED:
+ return "ATOM_FLASHLIGHT_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UID_PROCESS_STATE_CHANGED:
+ return "ATOM_UID_PROCESS_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_LIFE_CYCLE_STATE_CHANGED:
+ return "ATOM_PROCESS_LIFE_CYCLE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SCREEN_STATE_CHANGED:
+ return "ATOM_SCREEN_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_LEVEL_CHANGED:
+ return "ATOM_BATTERY_LEVEL_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CHARGING_STATE_CHANGED:
+ return "ATOM_CHARGING_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PLUGGED_STATE_CHANGED:
+ return "ATOM_PLUGGED_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INTERACTIVE_STATE_CHANGED:
+ return "ATOM_INTERACTIVE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TOUCH_EVENT_REPORTED:
+ return "ATOM_TOUCH_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WAKEUP_ALARM_OCCURRED:
+ return "ATOM_WAKEUP_ALARM_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KERNEL_WAKEUP_REPORTED:
+ return "ATOM_KERNEL_WAKEUP_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_LOCK_STATE_CHANGED:
+ return "ATOM_WIFI_LOCK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_SIGNAL_STRENGTH_CHANGED:
+ return "ATOM_WIFI_SIGNAL_STRENGTH_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_SCAN_STATE_CHANGED:
+ return "ATOM_WIFI_SCAN_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PHONE_SIGNAL_STRENGTH_CHANGED:
+ return "ATOM_PHONE_SIGNAL_STRENGTH_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SETTING_CHANGED:
+ return "ATOM_SETTING_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACTIVITY_FOREGROUND_STATE_CHANGED:
+ return "ATOM_ACTIVITY_FOREGROUND_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ISOLATED_UID_CHANGED:
+ return "ATOM_ISOLATED_UID_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKET_WAKEUP_OCCURRED:
+ return "ATOM_PACKET_WAKEUP_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WALL_CLOCK_TIME_SHIFTED:
+ return "ATOM_WALL_CLOCK_TIME_SHIFTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ANOMALY_DETECTED:
+ return "ATOM_ANOMALY_DETECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_BREADCRUMB_REPORTED:
+ return "ATOM_APP_BREADCRUMB_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_START_OCCURRED:
+ return "ATOM_APP_START_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_START_CANCELED:
+ return "ATOM_APP_START_CANCELED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_START_FULLY_DRAWN:
+ return "ATOM_APP_START_FULLY_DRAWN";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LMK_KILL_OCCURRED:
+ return "ATOM_LMK_KILL_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PICTURE_IN_PICTURE_STATE_CHANGED:
+ return "ATOM_PICTURE_IN_PICTURE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_MULTICAST_LOCK_STATE_CHANGED:
+ return "ATOM_WIFI_MULTICAST_LOCK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LMK_STATE_CHANGED:
+ return "ATOM_LMK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_START_MEMORY_STATE_CAPTURED:
+ return "ATOM_APP_START_MEMORY_STATE_CAPTURED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SHUTDOWN_SEQUENCE_REPORTED:
+ return "ATOM_SHUTDOWN_SEQUENCE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BOOT_SEQUENCE_REPORTED:
+ return "ATOM_BOOT_SEQUENCE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DAVEY_OCCURRED:
+ return "ATOM_DAVEY_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_OVERLAY_STATE_CHANGED:
+ return "ATOM_OVERLAY_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FOREGROUND_SERVICE_STATE_CHANGED:
+ return "ATOM_FOREGROUND_SERVICE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CALL_STATE_CHANGED:
+ return "ATOM_CALL_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYGUARD_STATE_CHANGED:
+ return "ATOM_KEYGUARD_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYGUARD_BOUNCER_STATE_CHANGED:
+ return "ATOM_KEYGUARD_BOUNCER_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYGUARD_BOUNCER_PASSWORD_ENTERED:
+ return "ATOM_KEYGUARD_BOUNCER_PASSWORD_ENTERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_DIED:
+ return "ATOM_APP_DIED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RESOURCE_CONFIGURATION_CHANGED:
+ return "ATOM_RESOURCE_CONFIGURATION_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_ENABLED_STATE_CHANGED:
+ return "ATOM_BLUETOOTH_ENABLED_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_CONNECTION_STATE_CHANGED:
+ return "ATOM_BLUETOOTH_CONNECTION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GPS_SIGNAL_QUALITY_CHANGED:
+ return "ATOM_GPS_SIGNAL_QUALITY_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USB_CONNECTOR_STATE_CHANGED:
+ return "ATOM_USB_CONNECTOR_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SPEAKER_IMPEDANCE_REPORTED:
+ return "ATOM_SPEAKER_IMPEDANCE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HARDWARE_FAILED:
+ return "ATOM_HARDWARE_FAILED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PHYSICAL_DROP_DETECTED:
+ return "ATOM_PHYSICAL_DROP_DETECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CHARGE_CYCLES_REPORTED:
+ return "ATOM_CHARGE_CYCLES_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_CONNECTION_STATE_CHANGED:
+ return "ATOM_MOBILE_CONNECTION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_RADIO_TECHNOLOGY_CHANGED:
+ return "ATOM_MOBILE_RADIO_TECHNOLOGY_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USB_DEVICE_ATTACHED:
+ return "ATOM_USB_DEVICE_ATTACHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_CRASH_OCCURRED:
+ return "ATOM_APP_CRASH_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ANR_OCCURRED:
+ return "ATOM_ANR_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WTF_OCCURRED:
+ return "ATOM_WTF_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOW_MEM_REPORTED:
+ return "ATOM_LOW_MEM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GENERIC_ATOM:
+ return "ATOM_GENERIC_ATOM";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VIBRATOR_STATE_CHANGED:
+ return "ATOM_VIBRATOR_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEFERRED_JOB_STATS_REPORTED:
+ return "ATOM_DEFERRED_JOB_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_THERMAL_THROTTLING:
+ return "ATOM_THERMAL_THROTTLING";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BIOMETRIC_ACQUIRED:
+ return "ATOM_BIOMETRIC_ACQUIRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BIOMETRIC_AUTHENTICATED:
+ return "ATOM_BIOMETRIC_AUTHENTICATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BIOMETRIC_ERROR_OCCURRED:
+ return "ATOM_BIOMETRIC_ERROR_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UI_EVENT_REPORTED:
+ return "ATOM_UI_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_HEALTH_SNAPSHOT:
+ return "ATOM_BATTERY_HEALTH_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SLOW_IO:
+ return "ATOM_SLOW_IO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_CAUSED_SHUTDOWN:
+ return "ATOM_BATTERY_CAUSED_SHUTDOWN";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PHONE_SERVICE_STATE_CHANGED:
+ return "ATOM_PHONE_SERVICE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PHONE_STATE_CHANGED:
+ return "ATOM_PHONE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USER_RESTRICTION_CHANGED:
+ return "ATOM_USER_RESTRICTION_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SETTINGS_UI_CHANGED:
+ return "ATOM_SETTINGS_UI_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONNECTIVITY_STATE_CHANGED:
+ return "ATOM_CONNECTIVITY_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SERVICE_STATE_CHANGED:
+ return "ATOM_SERVICE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SERVICE_LAUNCH_REPORTED:
+ return "ATOM_SERVICE_LAUNCH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FLAG_FLIP_UPDATE_OCCURRED:
+ return "ATOM_FLAG_FLIP_UPDATE_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BINARY_PUSH_STATE_CHANGED:
+ return "ATOM_BINARY_PUSH_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_POLICY_EVENT:
+ return "ATOM_DEVICE_POLICY_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_FILE_OP_CANCELED:
+ return "ATOM_DOCS_UI_FILE_OP_CANCELED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED:
+ return "ATOM_DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_FILE_OP_FAILURE:
+ return "ATOM_DOCS_UI_FILE_OP_FAILURE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_PROVIDER_FILE_OP:
+ return "ATOM_DOCS_UI_PROVIDER_FILE_OP";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_INVALID_SCOPED_ACCESS_REQUEST:
+ return "ATOM_DOCS_UI_INVALID_SCOPED_ACCESS_REQUEST";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_LAUNCH_REPORTED:
+ return "ATOM_DOCS_UI_LAUNCH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_ROOT_VISITED:
+ return "ATOM_DOCS_UI_ROOT_VISITED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_STARTUP_MS:
+ return "ATOM_DOCS_UI_STARTUP_MS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_USER_ACTION_REPORTED:
+ return "ATOM_DOCS_UI_USER_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_ENABLED_STATE_CHANGED:
+ return "ATOM_WIFI_ENABLED_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_RUNNING_STATE_CHANGED:
+ return "ATOM_WIFI_RUNNING_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_COMPACTED:
+ return "ATOM_APP_COMPACTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_DNS_EVENT_REPORTED:
+ return "ATOM_NETWORK_DNS_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED:
+ return "ATOM_DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_PICK_RESULT_REPORTED:
+ return "ATOM_DOCS_UI_PICK_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_SEARCH_MODE_REPORTED:
+ return "ATOM_DOCS_UI_SEARCH_MODE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_SEARCH_TYPE_REPORTED:
+ return "ATOM_DOCS_UI_SEARCH_TYPE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DATA_STALL_EVENT:
+ return "ATOM_DATA_STALL_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RESCUE_PARTY_RESET_REPORTED:
+ return "ATOM_RESCUE_PARTY_RESET_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIGNED_CONFIG_REPORTED:
+ return "ATOM_SIGNED_CONFIG_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GNSS_NI_EVENT_REPORTED:
+ return "ATOM_GNSS_NI_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_LINK_LAYER_CONNECTION_EVENT:
+ return "ATOM_BLUETOOTH_LINK_LAYER_CONNECTION_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_ACL_CONNECTION_STATE_CHANGED:
+ return "ATOM_BLUETOOTH_ACL_CONNECTION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_SCO_CONNECTION_STATE_CHANGED:
+ return "ATOM_BLUETOOTH_SCO_CONNECTION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_DOWNGRADED:
+ return "ATOM_APP_DOWNGRADED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_OPTIMIZED_AFTER_DOWNGRADED:
+ return "ATOM_APP_OPTIMIZED_AFTER_DOWNGRADED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOW_STORAGE_STATE_CHANGED:
+ return "ATOM_LOW_STORAGE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GNSS_NFW_NOTIFICATION_REPORTED:
+ return "ATOM_GNSS_NFW_NOTIFICATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GNSS_CONFIGURATION_REPORTED:
+ return "ATOM_GNSS_CONFIGURATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USB_PORT_OVERHEAT_EVENT_REPORTED:
+ return "ATOM_USB_PORT_OVERHEAT_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_ERROR_OCCURRED:
+ return "ATOM_NFC_ERROR_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_STATE_CHANGED:
+ return "ATOM_NFC_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_BEAM_OCCURRED:
+ return "ATOM_NFC_BEAM_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_CARDEMULATION_OCCURRED:
+ return "ATOM_NFC_CARDEMULATION_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_TAG_OCCURRED:
+ return "ATOM_NFC_TAG_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_HCE_TRANSACTION_OCCURRED:
+ return "ATOM_NFC_HCE_TRANSACTION_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SE_STATE_CHANGED:
+ return "ATOM_SE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SE_OMAPI_REPORTED:
+ return "ATOM_SE_OMAPI_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BROADCAST_DISPATCH_LATENCY_REPORTED:
+ return "ATOM_BROADCAST_DISPATCH_LATENCY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ATTENTION_MANAGER_SERVICE_RESULT_REPORTED:
+ return "ATOM_ATTENTION_MANAGER_SERVICE_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ADB_CONNECTION_CHANGED:
+ return "ATOM_ADB_CONNECTION_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SPEECH_DSP_STAT_REPORTED:
+ return "ATOM_SPEECH_DSP_STAT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USB_CONTAMINANT_REPORTED:
+ return "ATOM_USB_CONTAMINANT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WATCHDOG_ROLLBACK_OCCURRED:
+ return "ATOM_WATCHDOG_ROLLBACK_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED:
+ return "ATOM_BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BUBBLE_UI_CHANGED:
+ return "ATOM_BUBBLE_UI_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SCHEDULED_JOB_CONSTRAINT_CHANGED:
+ return "ATOM_SCHEDULED_JOB_CONSTRAINT_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_ACTIVE_DEVICE_CHANGED:
+ return "ATOM_BLUETOOTH_ACTIVE_DEVICE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED:
+ return "ATOM_BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_A2DP_CODEC_CONFIG_CHANGED:
+ return "ATOM_BLUETOOTH_A2DP_CODEC_CONFIG_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_A2DP_CODEC_CAPABILITY_CHANGED:
+ return "ATOM_BLUETOOTH_A2DP_CODEC_CAPABILITY_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED:
+ return "ATOM_BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED:
+ return "ATOM_BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_DEVICE_RSSI_REPORTED:
+ return "ATOM_BLUETOOTH_DEVICE_RSSI_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED:
+ return "ATOM_BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED:
+ return "ATOM_BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_HCI_TIMEOUT_REPORTED:
+ return "ATOM_BLUETOOTH_HCI_TIMEOUT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_QUALITY_REPORT_REPORTED:
+ return "ATOM_BLUETOOTH_QUALITY_REPORT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_DEVICE_INFO_REPORTED:
+ return "ATOM_BLUETOOTH_DEVICE_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_REMOTE_VERSION_INFO_REPORTED:
+ return "ATOM_BLUETOOTH_REMOTE_VERSION_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_SDP_ATTRIBUTE_REPORTED:
+ return "ATOM_BLUETOOTH_SDP_ATTRIBUTE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_BOND_STATE_CHANGED:
+ return "ATOM_BLUETOOTH_BOND_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED:
+ return "ATOM_BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_SMP_PAIRING_EVENT_REPORTED:
+ return "ATOM_BLUETOOTH_SMP_PAIRING_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SCREEN_TIMEOUT_EXTENSION_REPORTED:
+ return "ATOM_SCREEN_TIMEOUT_EXTENSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_START_TIME:
+ return "ATOM_PROCESS_START_TIME";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERMISSION_GRANT_REQUEST_RESULT_REPORTED:
+ return "ATOM_PERMISSION_GRANT_REQUEST_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED:
+ return "ATOM_BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_IDENTIFIER_ACCESS_DENIED:
+ return "ATOM_DEVICE_IDENTIFIER_ACCESS_DENIED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BUBBLE_DEVELOPER_ERROR_REPORTED:
+ return "ATOM_BUBBLE_DEVELOPER_ERROR_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ASSIST_GESTURE_STAGE_REPORTED:
+ return "ATOM_ASSIST_GESTURE_STAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ASSIST_GESTURE_FEEDBACK_REPORTED:
+ return "ATOM_ASSIST_GESTURE_FEEDBACK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ASSIST_GESTURE_PROGRESS_REPORTED:
+ return "ATOM_ASSIST_GESTURE_PROGRESS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TOUCH_GESTURE_CLASSIFIED:
+ return "ATOM_TOUCH_GESTURE_CLASSIFIED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HIDDEN_API_USED:
+ return "ATOM_HIDDEN_API_USED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_STYLE_UI_CHANGED:
+ return "ATOM_STYLE_UI_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PRIVACY_INDICATORS_INTERACTED:
+ return "ATOM_PRIVACY_INDICATORS_INTERACTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED:
+ return "ATOM_APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_STACK_REPORTED:
+ return "ATOM_NETWORK_STACK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_MOVED_STORAGE_REPORTED:
+ return "ATOM_APP_MOVED_STORAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BIOMETRIC_ENROLLED:
+ return "ATOM_BIOMETRIC_ENROLLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYSTEM_SERVER_WATCHDOG_OCCURRED:
+ return "ATOM_SYSTEM_SERVER_WATCHDOG_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TOMB_STONE_OCCURRED:
+ return "ATOM_TOMB_STONE_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_CLASS_OF_DEVICE_REPORTED:
+ return "ATOM_BLUETOOTH_CLASS_OF_DEVICE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INTELLIGENCE_EVENT_REPORTED:
+ return "ATOM_INTELLIGENCE_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_THERMAL_THROTTLING_SEVERITY_STATE_CHANGED:
+ return "ATOM_THERMAL_THROTTLING_SEVERITY_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ROLE_REQUEST_RESULT_REPORTED:
+ return "ATOM_ROLE_REQUEST_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIOPOLICY_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIOPOLICY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIORECORD_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIORECORD_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIOTHREAD_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIOTHREAD_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIOTRACK_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIOTRACK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_CODEC_REPORTED:
+ return "ATOM_MEDIAMETRICS_CODEC_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_DRM_WIDEVINE_REPORTED:
+ return "ATOM_MEDIAMETRICS_DRM_WIDEVINE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_EXTRACTOR_REPORTED:
+ return "ATOM_MEDIAMETRICS_EXTRACTOR_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_MEDIADRM_REPORTED:
+ return "ATOM_MEDIAMETRICS_MEDIADRM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_NUPLAYER_REPORTED:
+ return "ATOM_MEDIAMETRICS_NUPLAYER_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_RECORDER_REPORTED:
+ return "ATOM_MEDIAMETRICS_RECORDER_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_DRMMANAGER_REPORTED:
+ return "ATOM_MEDIAMETRICS_DRMMANAGER_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_POWER_STATE_CHANGED:
+ return "ATOM_CAR_POWER_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GARAGE_MODE_INFO:
+ return "ATOM_GARAGE_MODE_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEST_ATOM_REPORTED:
+ return "ATOM_TEST_ATOM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTENT_CAPTURE_CALLER_MISMATCH_REPORTED:
+ return "ATOM_CONTENT_CAPTURE_CALLER_MISMATCH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTENT_CAPTURE_SERVICE_EVENTS:
+ return "ATOM_CONTENT_CAPTURE_SERVICE_EVENTS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTENT_CAPTURE_SESSION_EVENTS:
+ return "ATOM_CONTENT_CAPTURE_SESSION_EVENTS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTENT_CAPTURE_FLUSHED:
+ return "ATOM_CONTENT_CAPTURE_FLUSHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOCATION_MANAGER_API_USAGE_REPORTED:
+ return "ATOM_LOCATION_MANAGER_API_USAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REVIEW_PERMISSIONS_FRAGMENT_RESULT_REPORTED:
+ return "ATOM_REVIEW_PERMISSIONS_FRAGMENT_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RUNTIME_PERMISSIONS_UPGRADE_RESULT:
+ return "ATOM_RUNTIME_PERMISSIONS_UPGRADE_RESULT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS:
+ return "ATOM_GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOCATION_ACCESS_CHECK_NOTIFICATION_ACTION:
+ return "ATOM_LOCATION_ACCESS_CHECK_NOTIFICATION_ACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_PERMISSION_FRAGMENT_ACTION_REPORTED:
+ return "ATOM_APP_PERMISSION_FRAGMENT_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_PERMISSION_FRAGMENT_VIEWED:
+ return "ATOM_APP_PERMISSION_FRAGMENT_VIEWED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_PERMISSIONS_FRAGMENT_VIEWED:
+ return "ATOM_APP_PERMISSIONS_FRAGMENT_VIEWED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERMISSION_APPS_FRAGMENT_VIEWED:
+ return "ATOM_PERMISSION_APPS_FRAGMENT_VIEWED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEXT_SELECTION_EVENT:
+ return "ATOM_TEXT_SELECTION_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEXT_LINKIFY_EVENT:
+ return "ATOM_TEXT_LINKIFY_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONVERSATION_ACTIONS_EVENT:
+ return "ATOM_CONVERSATION_ACTIONS_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LANGUAGE_DETECTION_EVENT:
+ return "ATOM_LANGUAGE_DETECTION_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXCLUSION_RECT_STATE_CHANGED:
+ return "ATOM_EXCLUSION_RECT_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BACK_GESTURE_REPORTED_REPORTED:
+ return "ATOM_BACK_GESTURE_REPORTED_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UPDATE_ENGINE_UPDATE_ATTEMPT_REPORTED:
+ return "ATOM_UPDATE_ENGINE_UPDATE_ATTEMPT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UPDATE_ENGINE_SUCCESSFUL_UPDATE_REPORTED:
+ return "ATOM_UPDATE_ENGINE_SUCCESSFUL_UPDATE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAMERA_ACTION_EVENT:
+ return "ATOM_CAMERA_ACTION_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_COMPATIBILITY_CHANGE_REPORTED:
+ return "ATOM_APP_COMPATIBILITY_CHANGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERFETTO_UPLOADED:
+ return "ATOM_PERFETTO_UPLOADED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VMS_CLIENT_CONNECTION_STATE_CHANGED:
+ return "ATOM_VMS_CLIENT_CONNECTION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PROVIDER_SCAN_OCCURRED:
+ return "ATOM_MEDIA_PROVIDER_SCAN_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CONTENT_DELETED:
+ return "ATOM_MEDIA_CONTENT_DELETED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PROVIDER_PERMISSION_REQUESTED:
+ return "ATOM_MEDIA_PROVIDER_PERMISSION_REQUESTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PROVIDER_SCHEMA_CHANGED:
+ return "ATOM_MEDIA_PROVIDER_SCHEMA_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PROVIDER_IDLE_MAINTENANCE_FINISHED:
+ return "ATOM_MEDIA_PROVIDER_IDLE_MAINTENANCE_FINISHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REBOOT_ESCROW_RECOVERY_REPORTED:
+ return "ATOM_REBOOT_ESCROW_RECOVERY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BOOT_TIME_EVENT_DURATION_REPORTED:
+ return "ATOM_BOOT_TIME_EVENT_DURATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED:
+ return "ATOM_BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BOOT_TIME_EVENT_UTC_TIME_REPORTED:
+ return "ATOM_BOOT_TIME_EVENT_UTC_TIME_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BOOT_TIME_EVENT_ERROR_CODE_REPORTED:
+ return "ATOM_BOOT_TIME_EVENT_ERROR_CODE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USERSPACE_REBOOT_REPORTED:
+ return "ATOM_USERSPACE_REBOOT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NOTIFICATION_REPORTED:
+ return "ATOM_NOTIFICATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NOTIFICATION_PANEL_REPORTED:
+ return "ATOM_NOTIFICATION_PANEL_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NOTIFICATION_CHANNEL_MODIFIED:
+ return "ATOM_NOTIFICATION_CHANNEL_MODIFIED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INTEGRITY_CHECK_RESULT_REPORTED:
+ return "ATOM_INTEGRITY_CHECK_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INTEGRITY_RULES_PUSHED:
+ return "ATOM_INTEGRITY_RULES_PUSHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CB_MESSAGE_REPORTED:
+ return "ATOM_CB_MESSAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CB_MESSAGE_ERROR:
+ return "ATOM_CB_MESSAGE_ERROR";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_HEALTH_STAT_REPORTED:
+ return "ATOM_WIFI_HEALTH_STAT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_FAILURE_STAT_REPORTED:
+ return "ATOM_WIFI_FAILURE_STAT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_CONNECTION_RESULT_REPORTED:
+ return "ATOM_WIFI_CONNECTION_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_FREEZE_CHANGED:
+ return "ATOM_APP_FREEZE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SNAPSHOT_MERGE_REPORTED:
+ return "ATOM_SNAPSHOT_MERGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FOREGROUND_SERVICE_APP_OP_SESSION_ENDED:
+ return "ATOM_FOREGROUND_SERVICE_APP_OP_SESSION_ENDED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISPLAY_JANK_REPORTED:
+ return "ATOM_DISPLAY_JANK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_STANDBY_BUCKET_CHANGED:
+ return "ATOM_APP_STANDBY_BUCKET_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SHARESHEET_STARTED:
+ return "ATOM_SHARESHEET_STARTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RANKING_SELECTED:
+ return "ATOM_RANKING_SELECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TVSETTINGS_UI_INTERACTED:
+ return "ATOM_TVSETTINGS_UI_INTERACTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LAUNCHER_SNAPSHOT:
+ return "ATOM_LAUNCHER_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_INSTALLER_V2_REPORTED:
+ return "ATOM_PACKAGE_INSTALLER_V2_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USER_LIFECYCLE_JOURNEY_REPORTED:
+ return "ATOM_USER_LIFECYCLE_JOURNEY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USER_LIFECYCLE_EVENT_OCCURRED:
+ return "ATOM_USER_LIFECYCLE_EVENT_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACCESSIBILITY_SHORTCUT_REPORTED:
+ return "ATOM_ACCESSIBILITY_SHORTCUT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACCESSIBILITY_SERVICE_REPORTED:
+ return "ATOM_ACCESSIBILITY_SERVICE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCS_UI_DRAG_AND_DROP_REPORTED:
+ return "ATOM_DOCS_UI_DRAG_AND_DROP_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_USAGE_EVENT_OCCURRED:
+ return "ATOM_APP_USAGE_EVENT_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTO_REVOKE_NOTIFICATION_CLICKED:
+ return "ATOM_AUTO_REVOKE_NOTIFICATION_CLICKED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTO_REVOKE_FRAGMENT_APP_VIEWED:
+ return "ATOM_AUTO_REVOKE_FRAGMENT_APP_VIEWED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTO_REVOKED_APP_INTERACTION:
+ return "ATOM_AUTO_REVOKED_APP_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION:
+ return "ATOM_APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EVS_USAGE_STATS_REPORTED:
+ return "ATOM_EVS_USAGE_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUDIO_POWER_USAGE_DATA_REPORTED:
+ return "ATOM_AUDIO_POWER_USAGE_DATA_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TV_TUNER_STATE_CHANGED:
+ return "ATOM_TV_TUNER_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAOUTPUT_OP_SWITCH_REPORTED:
+ return "ATOM_MEDIAOUTPUT_OP_SWITCH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CB_MESSAGE_FILTERED:
+ return "ATOM_CB_MESSAGE_FILTERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TV_TUNER_DVR_STATUS:
+ return "ATOM_TV_TUNER_DVR_STATUS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TV_CAS_SESSION_OPEN_STATUS:
+ return "ATOM_TV_CAS_SESSION_OPEN_STATUS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ASSISTANT_INVOCATION_REPORTED:
+ return "ATOM_ASSISTANT_INVOCATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISPLAY_WAKE_REPORTED:
+ return "ATOM_DISPLAY_WAKE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_USER_HAL_MODIFY_USER_REQUEST_REPORTED:
+ return "ATOM_CAR_USER_HAL_MODIFY_USER_REQUEST_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_USER_HAL_MODIFY_USER_RESPONSE_REPORTED:
+ return "ATOM_CAR_USER_HAL_MODIFY_USER_RESPONSE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_USER_HAL_POST_SWITCH_RESPONSE_REPORTED:
+ return "ATOM_CAR_USER_HAL_POST_SWITCH_RESPONSE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_USER_HAL_INITIAL_USER_INFO_REQUEST_REPORTED:
+ return "ATOM_CAR_USER_HAL_INITIAL_USER_INFO_REQUEST_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_USER_HAL_INITIAL_USER_INFO_RESPONSE_REPORTED:
+ return "ATOM_CAR_USER_HAL_INITIAL_USER_INFO_RESPONSE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_USER_HAL_USER_ASSOCIATION_REQUEST_REPORTED:
+ return "ATOM_CAR_USER_HAL_USER_ASSOCIATION_REQUEST_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_USER_HAL_SET_USER_ASSOCIATION_RESPONSE_REPORTED:
+ return "ATOM_CAR_USER_HAL_SET_USER_ASSOCIATION_RESPONSE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_IP_PROVISIONING_REPORTED:
+ return "ATOM_NETWORK_IP_PROVISIONING_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_DHCP_RENEW_REPORTED:
+ return "ATOM_NETWORK_DHCP_RENEW_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_VALIDATION_REPORTED:
+ return "ATOM_NETWORK_VALIDATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_STACK_QUIRK_REPORTED:
+ return "ATOM_NETWORK_STACK_QUIRK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLOB_COMMITTED:
+ return "ATOM_BLOB_COMMITTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLOB_LEASED:
+ return "ATOM_BLOB_LEASED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLOB_OPENED:
+ return "ATOM_BLOB_OPENED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTACTS_PROVIDER_STATUS_REPORTED:
+ return "ATOM_CONTACTS_PROVIDER_STATUS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE_KEY_EVENT_REPORTED:
+ return "ATOM_KEYSTORE_KEY_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_TETHERING_REPORTED:
+ return "ATOM_NETWORK_TETHERING_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IME_TOUCH_REPORTED:
+ return "ATOM_IME_TOUCH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UI_INTERACTION_FRAME_INFO_REPORTED:
+ return "ATOM_UI_INTERACTION_FRAME_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UI_ACTION_LATENCY_REPORTED:
+ return "ATOM_UI_ACTION_LATENCY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_DISCONNECT_REPORTED:
+ return "ATOM_WIFI_DISCONNECT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_CONNECTION_STATE_CHANGED:
+ return "ATOM_WIFI_CONNECTION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HDMI_CEC_ACTIVE_SOURCE_CHANGED:
+ return "ATOM_HDMI_CEC_ACTIVE_SOURCE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HDMI_CEC_MESSAGE_REPORTED:
+ return "ATOM_HDMI_CEC_MESSAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AIRPLANE_MODE:
+ return "ATOM_AIRPLANE_MODE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MODEM_RESTART:
+ return "ATOM_MODEM_RESTART";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CARRIER_ID_MISMATCH_REPORTED:
+ return "ATOM_CARRIER_ID_MISMATCH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CARRIER_ID_TABLE_UPDATED:
+ return "ATOM_CARRIER_ID_TABLE_UPDATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DATA_STALL_RECOVERY_REPORTED:
+ return "ATOM_DATA_STALL_RECOVERY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_MEDIAPARSER_REPORTED:
+ return "ATOM_MEDIAMETRICS_MEDIAPARSER_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TLS_HANDSHAKE_REPORTED:
+ return "ATOM_TLS_HANDSHAKE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEXT_CLASSIFIER_API_USAGE_REPORTED:
+ return "ATOM_TEXT_CLASSIFIER_API_USAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_WATCHDOG_KILL_STATS_REPORTED:
+ return "ATOM_CAR_WATCHDOG_KILL_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_PLAYBACK_REPORTED:
+ return "ATOM_MEDIAMETRICS_PLAYBACK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_NETWORK_INFO_CHANGED:
+ return "ATOM_MEDIA_NETWORK_INFO_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PLAYBACK_STATE_CHANGED:
+ return "ATOM_MEDIA_PLAYBACK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PLAYBACK_ERROR_REPORTED:
+ return "ATOM_MEDIA_PLAYBACK_ERROR_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PLAYBACK_TRACK_CHANGED:
+ return "ATOM_MEDIA_PLAYBACK_TRACK_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_SCAN_REPORTED:
+ return "ATOM_WIFI_SCAN_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_PNO_SCAN_REPORTED:
+ return "ATOM_WIFI_PNO_SCAN_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TIF_TUNE_CHANGED:
+ return "ATOM_TIF_TUNE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTO_ROTATE_REPORTED:
+ return "ATOM_AUTO_ROTATE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERFETTO_TRIGGER:
+ return "ATOM_PERFETTO_TRIGGER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TRANSCODING_DATA:
+ return "ATOM_TRANSCODING_DATA";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IMS_SERVICE_ENTITLEMENT_UPDATED:
+ return "ATOM_IMS_SERVICE_ENTITLEMENT_UPDATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_ROTATED:
+ return "ATOM_DEVICE_ROTATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIM_SPECIFIC_SETTINGS_RESTORED:
+ return "ATOM_SIM_SPECIFIC_SETTINGS_RESTORED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEXT_CLASSIFIER_DOWNLOAD_REPORTED:
+ return "ATOM_TEXT_CLASSIFIER_DOWNLOAD_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PIN_STORAGE_EVENT:
+ return "ATOM_PIN_STORAGE_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FACE_DOWN_REPORTED:
+ return "ATOM_FACE_DOWN_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_HAL_CRASH_REASON_REPORTED:
+ return "ATOM_BLUETOOTH_HAL_CRASH_REASON_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REBOOT_ESCROW_PREPARATION_REPORTED:
+ return "ATOM_REBOOT_ESCROW_PREPARATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REBOOT_ESCROW_LSKF_CAPTURE_REPORTED:
+ return "ATOM_REBOOT_ESCROW_LSKF_CAPTURE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REBOOT_ESCROW_REBOOT_REPORTED:
+ return "ATOM_REBOOT_ESCROW_REBOOT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BINDER_LATENCY_REPORTED:
+ return "ATOM_BINDER_LATENCY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AAUDIOSTREAM_REPORTED:
+ return "ATOM_MEDIAMETRICS_AAUDIOSTREAM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_TRANSCODING_SESSION_ENDED:
+ return "ATOM_MEDIA_TRANSCODING_SESSION_ENDED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MAGNIFICATION_USAGE_REPORTED:
+ return "ATOM_MAGNIFICATION_USAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MAGNIFICATION_MODE_WITH_IME_ON_REPORTED:
+ return "ATOM_MAGNIFICATION_MODE_WITH_IME_ON_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_CALL_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_CALL_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_CONTROL_CHANGED:
+ return "ATOM_DEVICE_CONTROL_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_STATE_CHANGED:
+ return "ATOM_DEVICE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INPUTDEVICE_REGISTERED:
+ return "ATOM_INPUTDEVICE_REGISTERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SMARTSPACE_CARD_REPORTED:
+ return "ATOM_SMARTSPACE_CARD_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTH_PROMPT_AUTHENTICATE_INVOKED:
+ return "ATOM_AUTH_PROMPT_AUTHENTICATE_INVOKED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTH_MANAGER_CAN_AUTHENTICATE_INVOKED:
+ return "ATOM_AUTH_MANAGER_CAN_AUTHENTICATE_INVOKED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTH_ENROLL_ACTION_INVOKED:
+ return "ATOM_AUTH_ENROLL_ACTION_INVOKED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTH_DEPRECATED_API_USED:
+ return "ATOM_AUTH_DEPRECATED_API_USED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UNATTENDED_REBOOT_OCCURRED:
+ return "ATOM_UNATTENDED_REBOOT_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LONG_REBOOT_BLOCKING_REPORTED:
+ return "ATOM_LONG_REBOOT_BLOCKING_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOCATION_TIME_ZONE_PROVIDER_STATE_CHANGED:
+ return "ATOM_LOCATION_TIME_ZONE_PROVIDER_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FDTRACK_EVENT_OCCURRED:
+ return "ATOM_FDTRACK_EVENT_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TIMEOUT_AUTO_EXTENDED_REPORTED:
+ return "ATOM_TIMEOUT_AUTO_EXTENDED_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ALARM_BATCH_DELIVERED:
+ return "ATOM_ALARM_BATCH_DELIVERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ALARM_SCHEDULED:
+ return "ATOM_ALARM_SCHEDULED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_WATCHDOG_IO_OVERUSE_STATS_REPORTED:
+ return "ATOM_CAR_WATCHDOG_IO_OVERUSE_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USER_LEVEL_HIBERNATION_STATE_CHANGED:
+ return "ATOM_USER_LEVEL_HIBERNATION_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_INITIALIZE_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_INITIALIZE_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_QUERY_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_QUERY_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_PROCESS_DIED:
+ return "ATOM_APP_PROCESS_DIED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_IP_REACHABILITY_MONITOR_REPORTED:
+ return "ATOM_NETWORK_IP_REACHABILITY_MONITOR_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SLOW_INPUT_EVENT_REPORTED:
+ return "ATOM_SLOW_INPUT_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ANR_OCCURRED_PROCESSING_STARTED:
+ return "ATOM_ANR_OCCURRED_PROCESSING_STARTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_REMOVE_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_REMOVE_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CODEC_REPORTED:
+ return "ATOM_MEDIA_CODEC_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERMISSION_USAGE_FRAGMENT_INTERACTION:
+ return "ATOM_PERMISSION_USAGE_FRAGMENT_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERMISSION_DETAILS_INTERACTION:
+ return "ATOM_PERMISSION_DETAILS_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PRIVACY_SENSOR_TOGGLE_INTERACTION:
+ return "ATOM_PRIVACY_SENSOR_TOGGLE_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PRIVACY_TOGGLE_DIALOG_INTERACTION:
+ return "ATOM_PRIVACY_TOGGLE_DIALOG_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_OPTIMIZE_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_OPTIMIZE_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NON_A11Y_TOOL_SERVICE_WARNING_REPORT:
+ return "ATOM_NON_A11Y_TOOL_SERVICE_WARNING_REPORT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_SET_SCHEMA_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_SET_SCHEMA_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_COMPAT_STATE_CHANGED:
+ return "ATOM_APP_COMPAT_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED:
+ return "ATOM_SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SPLITSCREEN_UI_CHANGED:
+ return "ATOM_SPLITSCREEN_UI_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_DNS_HANDSHAKE_REPORTED:
+ return "ATOM_NETWORK_DNS_HANDSHAKE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_CODE_PATH_COUNTER:
+ return "ATOM_BLUETOOTH_CODE_PATH_COUNTER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_LE_BATCH_SCAN_REPORT_DELAY:
+ return "ATOM_BLUETOOTH_LE_BATCH_SCAN_REPORT_DELAY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACCESSIBILITY_FLOATING_MENU_UI_CHANGED:
+ return "ATOM_ACCESSIBILITY_FLOATING_MENU_UI_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NEURALNETWORKS_COMPILATION_COMPLETED:
+ return "ATOM_NEURALNETWORKS_COMPILATION_COMPLETED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NEURALNETWORKS_EXECUTION_COMPLETED:
+ return "ATOM_NEURALNETWORKS_EXECUTION_COMPLETED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NEURALNETWORKS_COMPILATION_FAILED:
+ return "ATOM_NEURALNETWORKS_COMPILATION_FAILED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NEURALNETWORKS_EXECUTION_FAILED:
+ return "ATOM_NEURALNETWORKS_EXECUTION_FAILED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTEXT_HUB_BOOTED:
+ return "ATOM_CONTEXT_HUB_BOOTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTEXT_HUB_RESTARTED:
+ return "ATOM_CONTEXT_HUB_RESTARTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTEXT_HUB_LOADED_NANOAPP_SNAPSHOT_REPORTED:
+ return "ATOM_CONTEXT_HUB_LOADED_NANOAPP_SNAPSHOT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CHRE_CODE_DOWNLOAD_TRANSACTED:
+ return "ATOM_CHRE_CODE_DOWNLOAD_TRANSACTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UWB_SESSION_INITED:
+ return "ATOM_UWB_SESSION_INITED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UWB_SESSION_CLOSED:
+ return "ATOM_UWB_SESSION_CLOSED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UWB_FIRST_RANGING_RECEIVED:
+ return "ATOM_UWB_FIRST_RANGING_RECEIVED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UWB_RANGING_MEASUREMENT_RECEIVED:
+ return "ATOM_UWB_RANGING_MEASUREMENT_RECEIVED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_SCHEDULED:
+ return "ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_SCHEDULED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_COMPLETED:
+ return "ATOM_TEXT_CLASSIFIER_DOWNLOAD_WORK_COMPLETED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CLIPBOARD_CLEARED:
+ return "ATOM_CLIPBOARD_CLEARED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VM_CREATION_REQUESTED:
+ return "ATOM_VM_CREATION_REQUESTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NEARBY_DEVICE_SCAN_STATE_CHANGED:
+ return "ATOM_NEARBY_DEVICE_SCAN_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAMERA_COMPAT_CONTROL_EVENT_REPORTED:
+ return "ATOM_CAMERA_COMPAT_CONTROL_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APPLICATION_LOCALES_CHANGED:
+ return "ATOM_APPLICATION_LOCALES_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FOLD_STATE_DURATION_REPORTED:
+ return "ATOM_FOLD_STATE_DURATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOCATION_TIME_ZONE_PROVIDER_CONTROLLER_STATE_CHANGED:
+ return "ATOM_LOCATION_TIME_ZONE_PROVIDER_CONTROLLER_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISPLAY_HBM_STATE_CHANGED:
+ return "ATOM_DISPLAY_HBM_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISPLAY_HBM_BRIGHTNESS_CHANGED:
+ return "ATOM_DISPLAY_HBM_BRIGHTNESS_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERSISTENT_URI_PERMISSIONS_FLUSHED:
+ return "ATOM_PERSISTENT_URI_PERMISSIONS_FLUSHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED:
+ return "ATOM_EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VBMETA_DIGEST_REPORTED:
+ return "ATOM_VBMETA_DIGEST_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APEX_INFO_GATHERED:
+ return "ATOM_APEX_INFO_GATHERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PVM_INFO_GATHERED:
+ return "ATOM_PVM_INFO_GATHERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_SETTINGS_UI_INTERACTED:
+ return "ATOM_WEAR_SETTINGS_UI_INTERACTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TRACING_SERVICE_REPORT_EVENT:
+ return "ATOM_TRACING_SERVICE_REPORT_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED:
+ return "ATOM_MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LAUNCHER_LATENCY:
+ return "ATOM_LAUNCHER_LATENCY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DROPBOX_ENTRY_DROPPED:
+ return "ATOM_DROPBOX_ENTRY_DROPPED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_P2P_CONNECTION_REPORTED:
+ return "ATOM_WIFI_P2P_CONNECTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GAME_STATE_CHANGED:
+ return "ATOM_GAME_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HOTWORD_DETECTOR_CREATE_REQUESTED:
+ return "ATOM_HOTWORD_DETECTOR_CREATE_REQUESTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED:
+ return "ATOM_HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HOTWORD_DETECTION_SERVICE_RESTARTED:
+ return "ATOM_HOTWORD_DETECTION_SERVICE_RESTARTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED:
+ return "ATOM_HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HOTWORD_DETECTOR_EVENTS:
+ return "ATOM_HOTWORD_DETECTOR_EVENTS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_API_CALLED:
+ return "ATOM_AD_SERVICES_API_CALLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_MESUREMENT_REPORTS_UPLOADED:
+ return "ATOM_AD_SERVICES_MESUREMENT_REPORTS_UPLOADED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED:
+ return "ATOM_BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONTACTS_INDEXER_UPDATE_STATS_REPORTED:
+ return "ATOM_CONTACTS_INDEXER_UPDATE_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_BACKGROUND_RESTRICTIONS_INFO:
+ return "ATOM_APP_BACKGROUND_RESTRICTIONS_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MMS_SMS_PROVIDER_GET_THREAD_ID_FAILED:
+ return "ATOM_MMS_SMS_PROVIDER_GET_THREAD_ID_FAILED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MMS_SMS_DATABASE_HELPER_ON_UPGRADE_FAILED:
+ return "ATOM_MMS_SMS_DATABASE_HELPER_ON_UPGRADE_FAILED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERMISSION_REMINDER_NOTIFICATION_INTERACTED:
+ return "ATOM_PERMISSION_REMINDER_NOTIFICATION_INTERACTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RECENT_PERMISSION_DECISIONS_INTERACTED:
+ return "ATOM_RECENT_PERMISSION_DECISIONS_INTERACTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GNSS_PSDS_DOWNLOAD_REPORTED:
+ return "ATOM_GNSS_PSDS_DOWNLOAD_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LE_AUDIO_CONNECTION_SESSION_REPORTED:
+ return "ATOM_LE_AUDIO_CONNECTION_SESSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LE_AUDIO_BROADCAST_SESSION_REPORTED:
+ return "ATOM_LE_AUDIO_BROADCAST_SESSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DREAM_UI_EVENT_REPORTED:
+ return "ATOM_DREAM_UI_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TASK_MANAGER_EVENT_REPORTED:
+ return "ATOM_TASK_MANAGER_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CDM_ASSOCIATION_ACTION:
+ return "ATOM_CDM_ASSOCIATION_ACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MAGNIFICATION_TRIPLE_TAP_AND_HOLD_ACTIVATED_SESSION_REPORTED:
+ return "ATOM_MAGNIFICATION_TRIPLE_TAP_AND_HOLD_ACTIVATED_SESSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED:
+ return "ATOM_MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACCESSIBILITY_TEXT_READING_OPTIONS_CHANGED:
+ return "ATOM_ACCESSIBILITY_TEXT_READING_OPTIONS_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_SETUP_FAILURE_CRASH_REPORTED:
+ return "ATOM_WIFI_SETUP_FAILURE_CRASH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UWB_DEVICE_ERROR_REPORTED:
+ return "ATOM_UWB_DEVICE_ERROR_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ISOLATED_COMPILATION_SCHEDULED:
+ return "ATOM_ISOLATED_COMPILATION_SCHEDULED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ISOLATED_COMPILATION_ENDED:
+ return "ATOM_ISOLATED_COMPILATION_ENDED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE:
+ return "ATOM_ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYSTEM_SERVER_PRE_WATCHDOG_OCCURRED:
+ return "ATOM_SYSTEM_SERVER_PRE_WATCHDOG_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TELEPHONY_ANOMALY_DETECTED:
+ return "ATOM_TELEPHONY_ANOMALY_DETECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LETTERBOX_POSITION_CHANGED:
+ return "ATOM_LETTERBOX_POSITION_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REMOTE_KEY_PROVISIONING_ATTEMPT:
+ return "ATOM_REMOTE_KEY_PROVISIONING_ATTEMPT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REMOTE_KEY_PROVISIONING_NETWORK_INFO:
+ return "ATOM_REMOTE_KEY_PROVISIONING_NETWORK_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REMOTE_KEY_PROVISIONING_TIMING:
+ return "ATOM_REMOTE_KEY_PROVISIONING_TIMING";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAOUTPUT_OP_INTERACTION_REPORT:
+ return "ATOM_MEDIAOUTPUT_OP_INTERACTION_REPORT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYNC_EXEMPTION_OCCURRED:
+ return "ATOM_SYNC_EXEMPTION_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTOFILL_PRESENTATION_EVENT_REPORTED:
+ return "ATOM_AUTOFILL_PRESENTATION_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DOCK_STATE_CHANGED:
+ return "ATOM_DOCK_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SAFETY_SOURCE_STATE_COLLECTED:
+ return "ATOM_SAFETY_SOURCE_STATE_COLLECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SAFETY_CENTER_SYSTEM_EVENT_REPORTED:
+ return "ATOM_SAFETY_CENTER_SYSTEM_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SAFETY_CENTER_INTERACTION_REPORTED:
+ return "ATOM_SAFETY_CENTER_INTERACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SETTINGS_PROVIDER_SETTING_CHANGED:
+ return "ATOM_SETTINGS_PROVIDER_SETTING_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BROADCAST_DELIVERY_EVENT_REPORTED:
+ return "ATOM_BROADCAST_DELIVERY_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SERVICE_REQUEST_EVENT_REPORTED:
+ return "ATOM_SERVICE_REQUEST_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROVIDER_ACQUISITION_EVENT_REPORTED:
+ return "ATOM_PROVIDER_ACQUISITION_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_DEVICE_NAME_REPORTED:
+ return "ATOM_BLUETOOTH_DEVICE_NAME_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CB_CONFIG_UPDATED:
+ return "ATOM_CB_CONFIG_UPDATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CB_MODULE_ERROR_REPORTED:
+ return "ATOM_CB_MODULE_ERROR_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CB_SERVICE_FEATURE_CHANGED:
+ return "ATOM_CB_SERVICE_FEATURE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CB_RECEIVER_FEATURE_CHANGED:
+ return "ATOM_CB_RECEIVER_FEATURE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_JSSCRIPTENGINE_LATENCY_REPORTED:
+ return "ATOM_JSSCRIPTENGINE_LATENCY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PRIVACY_SIGNAL_NOTIFICATION_INTERACTION:
+ return "ATOM_PRIVACY_SIGNAL_NOTIFICATION_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION:
+ return "ATOM_PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PRIVACY_SIGNALS_JOB_FAILURE:
+ return "ATOM_PRIVACY_SIGNALS_JOB_FAILURE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VIBRATION_REPORTED:
+ return "ATOM_VIBRATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UWB_RANGING_START:
+ return "ATOM_UWB_RANGING_START";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STATUS_REPORTED:
+ return "ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STATUS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_COMPACTED_V2:
+ return "ATOM_APP_COMPACTED_V2";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_SETTINGS_USAGE_REPORTED:
+ return "ATOM_AD_SERVICES_SETTINGS_USAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISPLAY_BRIGHTNESS_CHANGED:
+ return "ATOM_DISPLAY_BRIGHTNESS_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACTIVITY_ACTION_BLOCKED:
+ return "ATOM_ACTIVITY_ACTION_BLOCKED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BACKGROUND_FETCH_PROCESS_REPORTED:
+ return "ATOM_BACKGROUND_FETCH_PROCESS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UPDATE_CUSTOM_AUDIENCE_PROCESS_REPORTED:
+ return "ATOM_UPDATE_CUSTOM_AUDIENCE_PROCESS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RUN_AD_BIDDING_PROCESS_REPORTED:
+ return "ATOM_RUN_AD_BIDDING_PROCESS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RUN_AD_SCORING_PROCESS_REPORTED:
+ return "ATOM_RUN_AD_SCORING_PROCESS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RUN_AD_SELECTION_PROCESS_REPORTED:
+ return "ATOM_RUN_AD_SELECTION_PROCESS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RUN_AD_BIDDING_PER_CA_PROCESS_REPORTED:
+ return "ATOM_RUN_AD_BIDDING_PER_CA_PROCESS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_DATA_DOWNLOAD_DOWNLOAD_RESULT_REPORTED:
+ return "ATOM_MOBILE_DATA_DOWNLOAD_DOWNLOAD_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STORAGE_STATS_REPORTED:
+ return "ATOM_MOBILE_DATA_DOWNLOAD_FILE_GROUP_STORAGE_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_DNS_SERVER_SUPPORT_REPORTED:
+ return "ATOM_NETWORK_DNS_SERVER_SUPPORT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VM_BOOTED:
+ return "ATOM_VM_BOOTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VM_EXITED:
+ return "ATOM_VM_EXITED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AMBIENT_BRIGHTNESS_STATS_REPORTED:
+ return "ATOM_AMBIENT_BRIGHTNESS_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED:
+ return "ATOM_MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED:
+ return "ATOM_MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED:
+ return "ATOM_MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED:
+ return "ATOM_MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_MEASUREMENT_REGISTRATIONS:
+ return "ATOM_AD_SERVICES_MEASUREMENT_REGISTRATIONS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEARING_AID_INFO_REPORTED:
+ return "ATOM_HEARING_AID_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_WIDE_JOB_CONSTRAINT_CHANGED:
+ return "ATOM_DEVICE_WIDE_JOB_CONSTRAINT_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AMBIENT_MODE_CHANGED:
+ return "ATOM_AMBIENT_MODE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ANR_LATENCY_REPORTED:
+ return "ATOM_ANR_LATENCY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RESOURCE_API_INFO:
+ return "ATOM_RESOURCE_API_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYSTEM_DEFAULT_NETWORK_CHANGED:
+ return "ATOM_SYSTEM_DEFAULT_NETWORK_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IWLAN_SETUP_DATA_CALL_RESULT_REPORTED:
+ return "ATOM_IWLAN_SETUP_DATA_CALL_RESULT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IWLAN_PDN_DISCONNECTED_REASON_REPORTED:
+ return "ATOM_IWLAN_PDN_DISCONNECTED_REASON_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AIRPLANE_MODE_SESSION_REPORTED:
+ return "ATOM_AIRPLANE_MODE_SESSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VM_CPU_STATUS_REPORTED:
+ return "ATOM_VM_CPU_STATUS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VM_MEM_STATUS_REPORTED:
+ return "ATOM_VM_MEM_STATUS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_INSTALLATION_SESSION_REPORTED:
+ return "ATOM_PACKAGE_INSTALLATION_SESSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEFAULT_NETWORK_REMATCH_INFO:
+ return "ATOM_DEFAULT_NETWORK_REMATCH_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_SELECTION_PERFORMANCE:
+ return "ATOM_NETWORK_SELECTION_PERFORMANCE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_NSD_REPORTED:
+ return "ATOM_NETWORK_NSD_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_DISCONNECTION_REASON_REPORTED:
+ return "ATOM_BLUETOOTH_DISCONNECTION_REASON_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_LOCAL_VERSIONS_REPORTED:
+ return "ATOM_BLUETOOTH_LOCAL_VERSIONS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_REMOTE_SUPPORTED_FEATURES_REPORTED:
+ return "ATOM_BLUETOOTH_REMOTE_SUPPORTED_FEATURES_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_LOCAL_SUPPORTED_FEATURES_REPORTED:
+ return "ATOM_BLUETOOTH_LOCAL_SUPPORTED_FEATURES_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_GATT_APP_INFO:
+ return "ATOM_BLUETOOTH_GATT_APP_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BRIGHTNESS_CONFIGURATION_UPDATED:
+ return "ATOM_BRIGHTNESS_CONFIGURATION_UPDATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_GET_TOPICS_REPORTED:
+ return "ATOM_AD_SERVICES_GET_TOPICS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_EPOCH_COMPUTATION_GET_TOP_TOPICS_REPORTED:
+ return "ATOM_AD_SERVICES_EPOCH_COMPUTATION_GET_TOP_TOPICS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_EPOCH_COMPUTATION_CLASSIFIER_REPORTED:
+ return "ATOM_AD_SERVICES_EPOCH_COMPUTATION_CLASSIFIER_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_LAUNCHED:
+ return "ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_LAUNCHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FINISHED:
+ return "ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FINISHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECTION_REPORTED:
+ return "ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_DEVICE_SCAN_TRIGGERED:
+ return "ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_DEVICE_SCAN_TRIGGERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FIRST_DEVICE_SCAN_LATENCY:
+ return "ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_FIRST_DEVICE_SCAN_LATENCY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECT_DEVICE_LATENCY:
+ return "ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_CONNECT_DEVICE_LATENCY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_MANAGER_SNAPSHOT_REPORTED:
+ return "ATOM_PACKAGE_MANAGER_SNAPSHOT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED:
+ return "ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED:
+ return "ATOM_PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LAUNCHER_IMPRESSION_EVENT:
+ return "ATOM_LAUNCHER_IMPRESSION_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_ALL_DEVICES_SCAN_LATENCY:
+ return "ATOM_WEAR_MEDIA_OUTPUT_SWITCHER_ALL_DEVICES_SCAN_LATENCY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_WATCH_FACE_EDITED:
+ return "ATOM_WS_WATCH_FACE_EDITED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_WATCH_FACE_FAVORITE_ACTION_REPORTED:
+ return "ATOM_WS_WATCH_FACE_FAVORITE_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_WATCH_FACE_SET_ACTION_REPORTED:
+ return "ATOM_WS_WATCH_FACE_SET_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_UNINSTALLATION_REPORTED:
+ return "ATOM_PACKAGE_UNINSTALLATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GAME_MODE_CHANGED:
+ return "ATOM_GAME_MODE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GAME_MODE_CONFIGURATION_CHANGED:
+ return "ATOM_GAME_MODE_CONFIGURATION_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BEDTIME_MODE_STATE_CHANGED:
+ return "ATOM_BEDTIME_MODE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_SLICE_SESSION_ENDED:
+ return "ATOM_NETWORK_SLICE_SESSION_ENDED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_SLICE_DAILY_DATA_USAGE_REPORTED:
+ return "ATOM_NETWORK_SLICE_DAILY_DATA_USAGE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_TAG_TYPE_OCCURRED:
+ return "ATOM_NFC_TAG_TYPE_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_AID_CONFLICT_OCCURRED:
+ return "ATOM_NFC_AID_CONFLICT_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NFC_READER_CONFLICT_OCCURRED:
+ return "ATOM_NFC_READER_CONFLICT_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_TILE_LIST_CHANGED:
+ return "ATOM_WS_TILE_LIST_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GET_TYPE_ACCESSED_WITHOUT_PERMISSION:
+ return "ATOM_GET_TYPE_ACCESSED_WITHOUT_PERMISSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_BUNDLED_APP_INFO_GATHERED:
+ return "ATOM_MOBILE_BUNDLED_APP_INFO_GATHERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_WATCH_FACE_COMPLICATION_SET_CHANGED:
+ return "ATOM_WS_WATCH_FACE_COMPLICATION_SET_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_DRM_CREATED:
+ return "ATOM_MEDIA_DRM_CREATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_DRM_ERRORED:
+ return "ATOM_MEDIA_DRM_ERRORED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_DRM_SESSION_OPENED:
+ return "ATOM_MEDIA_DRM_SESSION_OPENED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_DRM_SESSION_CLOSED:
+ return "ATOM_MEDIA_DRM_SESSION_CLOSED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USER_SELECTED_RESOLUTION:
+ return "ATOM_USER_SELECTED_RESOLUTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UNSAFE_INTENT_EVENT_REPORTED:
+ return "ATOM_UNSAFE_INTENT_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERFORMANCE_HINT_SESSION_REPORTED:
+ return "ATOM_PERFORMANCE_HINT_SESSION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED:
+ return "ATOM_MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BIOMETRIC_TOUCH_REPORTED:
+ return "ATOM_BIOMETRIC_TOUCH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HOTWORD_AUDIO_EGRESS_EVENT_REPORTED:
+ return "ATOM_HOTWORD_AUDIO_EGRESS_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_SCHEMA_MIGRATION_STATS_REPORTED:
+ return "ATOM_APP_SEARCH_SCHEMA_MIGRATION_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOCATION_ENABLED_STATE_CHANGED:
+ return "ATOM_LOCATION_ENABLED_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IME_REQUEST_FINISHED:
+ return "ATOM_IME_REQUEST_FINISHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USB_COMPLIANCE_WARNINGS_REPORTED:
+ return "ATOM_USB_COMPLIANCE_WARNINGS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SUPPORTED_LOCALES_CHANGED:
+ return "ATOM_APP_SUPPORTED_LOCALES_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GRAMMATICAL_INFLECTION_CHANGED:
+ return "ATOM_GRAMMATICAL_INFLECTION_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_PROVIDER_VOLUME_RECOVERY_REPORTED:
+ return "ATOM_MEDIA_PROVIDER_VOLUME_RECOVERY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BIOMETRIC_PROPERTIES_COLLECTED:
+ return "ATOM_BIOMETRIC_PROPERTIES_COLLECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KERNEL_WAKEUP_ATTRIBUTED:
+ return "ATOM_KERNEL_WAKEUP_ATTRIBUTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SCREEN_STATE_CHANGED_V2:
+ return "ATOM_SCREEN_STATE_CHANGED_V2";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_BACKUP_ACTION_REPORTED:
+ return "ATOM_WS_BACKUP_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_RESTORE_ACTION_REPORTED:
+ return "ATOM_WS_RESTORE_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_LOG_ACCESS_EVENT_REPORTED:
+ return "ATOM_DEVICE_LOG_ACCESS_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_SESSION_UPDATED:
+ return "ATOM_MEDIA_SESSION_UPDATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_OOBE_STATE_CHANGED:
+ return "ATOM_WEAR_OOBE_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_NOTIFICATION_UPDATED:
+ return "ATOM_WS_NOTIFICATION_UPDATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_VALIDATION_FAILURE_STATS_DAILY_REPORTED:
+ return "ATOM_NETWORK_VALIDATION_FAILURE_STATS_DAILY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_COMPLICATION_TAPPED:
+ return "ATOM_WS_COMPLICATION_TAPPED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_WEAR_TIME_SESSION:
+ return "ATOM_WS_WEAR_TIME_SESSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_BYTES_TRANSFER:
+ return "ATOM_WIFI_BYTES_TRANSFER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_BYTES_TRANSFER_BY_FG_BG:
+ return "ATOM_WIFI_BYTES_TRANSFER_BY_FG_BG";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_BYTES_TRANSFER:
+ return "ATOM_MOBILE_BYTES_TRANSFER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MOBILE_BYTES_TRANSFER_BY_FG_BG:
+ return "ATOM_MOBILE_BYTES_TRANSFER_BY_FG_BG";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_BYTES_TRANSFER:
+ return "ATOM_BLUETOOTH_BYTES_TRANSFER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KERNEL_WAKELOCK:
+ return "ATOM_KERNEL_WAKELOCK";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SUBSYSTEM_SLEEP_STATE:
+ return "ATOM_SUBSYSTEM_SLEEP_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_TIME_PER_UID:
+ return "ATOM_CPU_TIME_PER_UID";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_TIME_PER_UID_FREQ:
+ return "ATOM_CPU_TIME_PER_UID_FREQ";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_ACTIVITY_INFO:
+ return "ATOM_WIFI_ACTIVITY_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MODEM_ACTIVITY_INFO:
+ return "ATOM_MODEM_ACTIVITY_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_ACTIVITY_INFO:
+ return "ATOM_BLUETOOTH_ACTIVITY_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_MEMORY_STATE:
+ return "ATOM_PROCESS_MEMORY_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYSTEM_ELAPSED_REALTIME:
+ return "ATOM_SYSTEM_ELAPSED_REALTIME";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYSTEM_UPTIME:
+ return "ATOM_SYSTEM_UPTIME";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_ACTIVE_TIME:
+ return "ATOM_CPU_ACTIVE_TIME";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_CLUSTER_TIME:
+ return "ATOM_CPU_CLUSTER_TIME";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISK_SPACE:
+ return "ATOM_DISK_SPACE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REMAINING_BATTERY_CAPACITY:
+ return "ATOM_REMAINING_BATTERY_CAPACITY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FULL_BATTERY_CAPACITY:
+ return "ATOM_FULL_BATTERY_CAPACITY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEMPERATURE:
+ return "ATOM_TEMPERATURE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BINDER_CALLS:
+ return "ATOM_BINDER_CALLS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BINDER_CALLS_EXCEPTIONS:
+ return "ATOM_BINDER_CALLS_EXCEPTIONS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOOPER_STATS:
+ return "ATOM_LOOPER_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISK_STATS:
+ return "ATOM_DISK_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DIRECTORY_USAGE:
+ return "ATOM_DIRECTORY_USAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SIZE:
+ return "ATOM_APP_SIZE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CATEGORY_SIZE:
+ return "ATOM_CATEGORY_SIZE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROC_STATS:
+ return "ATOM_PROC_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_VOLTAGE:
+ return "ATOM_BATTERY_VOLTAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NUM_FINGERPRINTS_ENROLLED:
+ return "ATOM_NUM_FINGERPRINTS_ENROLLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DISK_IO:
+ return "ATOM_DISK_IO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_POWER_PROFILE:
+ return "ATOM_POWER_PROFILE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROC_STATS_PKG_PROC:
+ return "ATOM_PROC_STATS_PKG_PROC";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_CPU_TIME:
+ return "ATOM_PROCESS_CPU_TIME";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_TIME_PER_THREAD_FREQ:
+ return "ATOM_CPU_TIME_PER_THREAD_FREQ";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ON_DEVICE_POWER_MEASUREMENT:
+ return "ATOM_ON_DEVICE_POWER_MEASUREMENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_CALCULATED_POWER_USE:
+ return "ATOM_DEVICE_CALCULATED_POWER_USE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_MEMORY_HIGH_WATER_MARK:
+ return "ATOM_PROCESS_MEMORY_HIGH_WATER_MARK";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_LEVEL:
+ return "ATOM_BATTERY_LEVEL";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BUILD_INFORMATION:
+ return "ATOM_BUILD_INFORMATION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_CYCLE_COUNT:
+ return "ATOM_BATTERY_CYCLE_COUNT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEBUG_ELAPSED_CLOCK:
+ return "ATOM_DEBUG_ELAPSED_CLOCK";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEBUG_FAILING_ELAPSED_CLOCK:
+ return "ATOM_DEBUG_FAILING_ELAPSED_CLOCK";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NUM_FACES_ENROLLED:
+ return "ATOM_NUM_FACES_ENROLLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ROLE_HOLDER:
+ return "ATOM_ROLE_HOLDER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DANGEROUS_PERMISSION_STATE:
+ return "ATOM_DANGEROUS_PERMISSION_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TRAIN_INFO:
+ return "ATOM_TRAIN_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TIME_ZONE_DATA_INFO:
+ return "ATOM_TIME_ZONE_DATA_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXTERNAL_STORAGE_INFO:
+ return "ATOM_EXTERNAL_STORAGE_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GPU_STATS_GLOBAL_INFO:
+ return "ATOM_GPU_STATS_GLOBAL_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GPU_STATS_APP_INFO:
+ return "ATOM_GPU_STATS_APP_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYSTEM_ION_HEAP_SIZE:
+ return "ATOM_SYSTEM_ION_HEAP_SIZE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APPS_ON_EXTERNAL_STORAGE_INFO:
+ return "ATOM_APPS_ON_EXTERNAL_STORAGE_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FACE_SETTINGS:
+ return "ATOM_FACE_SETTINGS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_COOLING_DEVICE:
+ return "ATOM_COOLING_DEVICE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_OPS:
+ return "ATOM_APP_OPS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_SYSTEM_ION_HEAP_SIZE:
+ return "ATOM_PROCESS_SYSTEM_ION_HEAP_SIZE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SURFACEFLINGER_STATS_GLOBAL_INFO:
+ return "ATOM_SURFACEFLINGER_STATS_GLOBAL_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SURFACEFLINGER_STATS_LAYER_INFO:
+ return "ATOM_SURFACEFLINGER_STATS_LAYER_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_MEMORY_SNAPSHOT:
+ return "ATOM_PROCESS_MEMORY_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VMS_CLIENT_STATS:
+ return "ATOM_VMS_CLIENT_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NOTIFICATION_REMOTE_VIEWS:
+ return "ATOM_NOTIFICATION_REMOTE_VIEWS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DANGEROUS_PERMISSION_STATE_SAMPLED:
+ return "ATOM_DANGEROUS_PERMISSION_STATE_SAMPLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GRAPHICS_STATS:
+ return "ATOM_GRAPHICS_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RUNTIME_APP_OP_ACCESS:
+ return "ATOM_RUNTIME_APP_OP_ACCESS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ION_HEAP_SIZE:
+ return "ATOM_ION_HEAP_SIZE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_NOTIFICATION_PREFERENCES:
+ return "ATOM_PACKAGE_NOTIFICATION_PREFERENCES";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES:
+ return "ATOM_PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES:
+ return "ATOM_PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GNSS_STATS:
+ return "ATOM_GNSS_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ATTRIBUTED_APP_OPS:
+ return "ATOM_ATTRIBUTED_APP_OPS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VOICE_CALL_SESSION:
+ return "ATOM_VOICE_CALL_SESSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VOICE_CALL_RAT_USAGE:
+ return "ATOM_VOICE_CALL_RAT_USAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIM_SLOT_STATE:
+ return "ATOM_SIM_SLOT_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SUPPORTED_RADIO_ACCESS_FAMILY:
+ return "ATOM_SUPPORTED_RADIO_ACCESS_FAMILY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SETTING_SNAPSHOT:
+ return "ATOM_SETTING_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLOB_INFO:
+ return "ATOM_BLOB_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DATA_USAGE_BYTES_TRANSFER:
+ return "ATOM_DATA_USAGE_BYTES_TRANSFER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BYTES_TRANSFER_BY_TAG_AND_METERED:
+ return "ATOM_BYTES_TRANSFER_BY_TAG_AND_METERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DND_MODE_RULE:
+ return "ATOM_DND_MODE_RULE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GENERAL_EXTERNAL_STORAGE_ACCESS_STATS:
+ return "ATOM_GENERAL_EXTERNAL_STORAGE_ACCESS_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INCOMING_SMS:
+ return "ATOM_INCOMING_SMS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_OUTGOING_SMS:
+ return "ATOM_OUTGOING_SMS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CARRIER_ID_TABLE_VERSION:
+ return "ATOM_CARRIER_ID_TABLE_VERSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DATA_CALL_SESSION:
+ return "ATOM_DATA_CALL_SESSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CELLULAR_SERVICE_STATE:
+ return "ATOM_CELLULAR_SERVICE_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CELLULAR_DATA_SERVICE_SWITCH:
+ return "ATOM_CELLULAR_DATA_SERVICE_SWITCH";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SYSTEM_MEMORY:
+ return "ATOM_SYSTEM_MEMORY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IMS_REGISTRATION_TERMINATION:
+ return "ATOM_IMS_REGISTRATION_TERMINATION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IMS_REGISTRATION_STATS:
+ return "ATOM_IMS_REGISTRATION_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_TIME_PER_CLUSTER_FREQ:
+ return "ATOM_CPU_TIME_PER_CLUSTER_FREQ";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_CYCLES_PER_UID_CLUSTER:
+ return "ATOM_CPU_CYCLES_PER_UID_CLUSTER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_ROTATED_DATA:
+ return "ATOM_DEVICE_ROTATED_DATA";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CPU_CYCLES_PER_THREAD_GROUP_CLUSTER:
+ return "ATOM_CPU_CYCLES_PER_THREAD_GROUP_CLUSTER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_DRM_ACTIVITY_INFO:
+ return "ATOM_MEDIA_DRM_ACTIVITY_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_OEM_MANAGED_BYTES_TRANSFER:
+ return "ATOM_OEM_MANAGED_BYTES_TRANSFER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GNSS_POWER_STATS:
+ return "ATOM_GNSS_POWER_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TIME_ZONE_DETECTOR_STATE:
+ return "ATOM_TIME_ZONE_DETECTOR_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_STORAGE_STATS:
+ return "ATOM_KEYSTORE2_STORAGE_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RKP_POOL_STATS:
+ return "ATOM_RKP_POOL_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_DMABUF_MEMORY:
+ return "ATOM_PROCESS_DMABUF_MEMORY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PENDING_ALARM_INFO:
+ return "ATOM_PENDING_ALARM_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USER_LEVEL_HIBERNATED_APPS:
+ return "ATOM_USER_LEVEL_HIBERNATED_APPS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LAUNCHER_LAYOUT_SNAPSHOT:
+ return "ATOM_LAUNCHER_LAYOUT_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GLOBAL_HIBERNATED_APPS:
+ return "ATOM_GLOBAL_HIBERNATED_APPS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INPUT_EVENT_LATENCY_SKETCH:
+ return "ATOM_INPUT_EVENT_LATENCY_SKETCH";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_USAGE_STATS_BEFORE_RESET:
+ return "ATOM_BATTERY_USAGE_STATS_BEFORE_RESET";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_USAGE_STATS_SINCE_RESET:
+ return "ATOM_BATTERY_USAGE_STATS_SINCE_RESET";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BATTERY_USAGE_STATS_SINCE_RESET_USING_POWER_PROFILE_MODEL:
+ return "ATOM_BATTERY_USAGE_STATS_SINCE_RESET_USING_POWER_PROFILE_MODEL";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INSTALLED_INCREMENTAL_PACKAGE:
+ return "ATOM_INSTALLED_INCREMENTAL_PACKAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TELEPHONY_NETWORK_REQUESTS:
+ return "ATOM_TELEPHONY_NETWORK_REQUESTS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_SEARCH_STORAGE_INFO:
+ return "ATOM_APP_SEARCH_STORAGE_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VMSTAT:
+ return "ATOM_VMSTAT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO:
+ return "ATOM_KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO:
+ return "ATOM_KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO:
+ return "ATOM_KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_ATOM_WITH_OVERFLOW:
+ return "ATOM_KEYSTORE2_ATOM_WITH_OVERFLOW";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO:
+ return "ATOM_KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO:
+ return "ATOM_KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RKP_ERROR_STATS:
+ return "ATOM_RKP_ERROR_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_KEYSTORE2_CRASH_STATS:
+ return "ATOM_KEYSTORE2_CRASH_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_VENDOR_APEX_INFO:
+ return "ATOM_VENDOR_APEX_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACCESSIBILITY_SHORTCUT_STATS:
+ return "ATOM_ACCESSIBILITY_SHORTCUT_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ACCESSIBILITY_FLOATING_MENU_STATS:
+ return "ATOM_ACCESSIBILITY_FLOATING_MENU_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DATA_USAGE_BYTES_TRANSFER_V2:
+ return "ATOM_DATA_USAGE_BYTES_TRANSFER_V2";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CAPABILITIES:
+ return "ATOM_MEDIA_CAPABILITIES";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY:
+ return "ATOM_CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CAR_WATCHDOG_UID_IO_USAGE_SUMMARY:
+ return "ATOM_CAR_WATCHDOG_UID_IO_USAGE_SUMMARY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IMS_REGISTRATION_FEATURE_TAG_STATS:
+ return "ATOM_IMS_REGISTRATION_FEATURE_TAG_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RCS_CLIENT_PROVISIONING_STATS:
+ return "ATOM_RCS_CLIENT_PROVISIONING_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RCS_ACS_PROVISIONING_STATS:
+ return "ATOM_RCS_ACS_PROVISIONING_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIP_DELEGATE_STATS:
+ return "ATOM_SIP_DELEGATE_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIP_TRANSPORT_FEATURE_TAG_STATS:
+ return "ATOM_SIP_TRANSPORT_FEATURE_TAG_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIP_MESSAGE_RESPONSE:
+ return "ATOM_SIP_MESSAGE_RESPONSE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIP_TRANSPORT_SESSION:
+ return "ATOM_SIP_TRANSPORT_SESSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IMS_DEDICATED_BEARER_LISTENER_EVENT:
+ return "ATOM_IMS_DEDICATED_BEARER_LISTENER_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IMS_DEDICATED_BEARER_EVENT:
+ return "ATOM_IMS_DEDICATED_BEARER_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IMS_REGISTRATION_SERVICE_DESC_STATS:
+ return "ATOM_IMS_REGISTRATION_SERVICE_DESC_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UCE_EVENT_STATS:
+ return "ATOM_UCE_EVENT_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PRESENCE_NOTIFY_EVENT:
+ return "ATOM_PRESENCE_NOTIFY_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GBA_EVENT:
+ return "ATOM_GBA_EVENT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PER_SIM_STATUS:
+ return "ATOM_PER_SIM_STATUS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GPU_WORK_PER_UID:
+ return "ATOM_GPU_WORK_PER_UID";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERSISTENT_URI_PERMISSIONS_AMOUNT_PER_PACKAGE:
+ return "ATOM_PERSISTENT_URI_PERMISSIONS_AMOUNT_PER_PACKAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SIGNED_PARTITION_INFO:
+ return "ATOM_SIGNED_PARTITION_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PINNED_FILE_SIZES_PER_PACKAGE:
+ return "ATOM_PINNED_FILE_SIZES_PER_PACKAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PENDING_INTENTS_PER_PACKAGE:
+ return "ATOM_PENDING_INTENTS_PER_PACKAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_USER_INFO:
+ return "ATOM_USER_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TELEPHONY_NETWORK_REQUESTS_V2:
+ return "ATOM_TELEPHONY_NETWORK_REQUESTS_V2";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DEVICE_TELEPHONY_PROPERTIES:
+ return "ATOM_DEVICE_TELEPHONY_PROPERTIES";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_REMOTE_KEY_PROVISIONING_ERROR_COUNTS:
+ return "ATOM_REMOTE_KEY_PROVISIONING_ERROR_COUNTS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SAFETY_STATE:
+ return "ATOM_SAFETY_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_INCOMING_MMS:
+ return "ATOM_INCOMING_MMS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_OUTGOING_MMS:
+ return "ATOM_OUTGOING_MMS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MULTI_USER_INFO:
+ return "ATOM_MULTI_USER_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_BPF_MAP_INFO:
+ return "ATOM_NETWORK_BPF_MAP_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_OUTGOING_SHORT_CODE_SMS:
+ return "ATOM_OUTGOING_SHORT_CODE_SMS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CONNECTIVITY_STATE_SAMPLE:
+ return "ATOM_CONNECTIVITY_STATE_SAMPLE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_SELECTION_REMATCH_REASONS_INFO:
+ return "ATOM_NETWORK_SELECTION_REMATCH_REASONS_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GAME_MODE_INFO:
+ return "ATOM_GAME_MODE_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GAME_MODE_CONFIGURATION:
+ return "ATOM_GAME_MODE_CONFIGURATION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_GAME_MODE_LISTENER:
+ return "ATOM_GAME_MODE_LISTENER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NETWORK_SLICE_REQUEST_COUNT:
+ return "ATOM_NETWORK_SLICE_REQUEST_COUNT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_TILE_SNAPSHOT:
+ return "ATOM_WS_TILE_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_ACTIVE_WATCH_FACE_COMPLICATION_SET_SNAPSHOT:
+ return "ATOM_WS_ACTIVE_WATCH_FACE_COMPLICATION_SET_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_STATE:
+ return "ATOM_PROCESS_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PROCESS_ASSOCIATION:
+ return "ATOM_PROCESS_ASSOCIATION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ADPF_SYSTEM_COMPONENT_INFO:
+ return "ATOM_ADPF_SYSTEM_COMPONENT_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_NOTIFICATION_MEMORY_USE:
+ return "ATOM_NOTIFICATION_MEMORY_USE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HDR_CAPABILITIES:
+ return "ATOM_HDR_CAPABILITIES";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_FAVOURITE_WATCH_FACE_LIST_SNAPSHOT:
+ return "ATOM_WS_FAVOURITE_WATCH_FACE_LIST_SNAPSHOT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_AWARE_NDP_REPORTED:
+ return "ATOM_WIFI_AWARE_NDP_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_AWARE_ATTACH_REPORTED:
+ return "ATOM_WIFI_AWARE_ATTACH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_SELF_RECOVERY_TRIGGERED:
+ return "ATOM_WIFI_SELF_RECOVERY_TRIGGERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SOFT_AP_STARTED:
+ return "ATOM_SOFT_AP_STARTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SOFT_AP_STOPPED:
+ return "ATOM_SOFT_AP_STOPPED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_LOCK_RELEASED:
+ return "ATOM_WIFI_LOCK_RELEASED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_LOCK_DEACTIVATED:
+ return "ATOM_WIFI_LOCK_DEACTIVATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_CONFIG_SAVED:
+ return "ATOM_WIFI_CONFIG_SAVED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_AWARE_RESOURCE_USING_CHANGED:
+ return "ATOM_WIFI_AWARE_RESOURCE_USING_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_AWARE_HAL_API_CALLED:
+ return "ATOM_WIFI_AWARE_HAL_API_CALLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_LOCAL_ONLY_REQUEST_RECEIVED:
+ return "ATOM_WIFI_LOCAL_ONLY_REQUEST_RECEIVED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_LOCAL_ONLY_REQUEST_SCAN_TRIGGERED:
+ return "ATOM_WIFI_LOCAL_ONLY_REQUEST_SCAN_TRIGGERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_THREAD_TASK_EXECUTED:
+ return "ATOM_WIFI_THREAD_TASK_EXECUTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_STATE_CHANGED:
+ return "ATOM_WIFI_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_AWARE_CAPABILITIES:
+ return "ATOM_WIFI_AWARE_CAPABILITIES";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WIFI_MODULE_INFO:
+ return "ATOM_WIFI_MODULE_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SETTINGS_SPA_REPORTED:
+ return "ATOM_SETTINGS_SPA_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXPRESS_EVENT_REPORTED:
+ return "ATOM_EXPRESS_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXPRESS_HISTOGRAM_SAMPLE_REPORTED:
+ return "ATOM_EXPRESS_HISTOGRAM_SAMPLE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXPRESS_UID_EVENT_REPORTED:
+ return "ATOM_EXPRESS_UID_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED:
+ return "ATOM_EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERMISSION_RATIONALE_DIALOG_VIEWED:
+ return "ATOM_PERMISSION_RATIONALE_DIALOG_VIEWED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED:
+ return "ATOM_PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_DATA_SHARING_UPDATES_NOTIFICATION_INTERACTION:
+ return "ATOM_APP_DATA_SHARING_UPDATES_NOTIFICATION_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_VIEWED:
+ return "ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_VIEWED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_ACTION_REPORTED:
+ return "ATOM_APP_DATA_SHARING_UPDATES_FRAGMENT_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_INCOMING_CALL_ACTION_REPORTED:
+ return "ATOM_WS_INCOMING_CALL_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_CALL_DISCONNECTION_REPORTED:
+ return "ATOM_WS_CALL_DISCONNECTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_CALL_DURATION_REPORTED:
+ return "ATOM_WS_CALL_DURATION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_CALL_USER_EXPERIENCE_LATENCY_REPORTED:
+ return "ATOM_WS_CALL_USER_EXPERIENCE_LATENCY_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WS_CALL_INTERACTION_REPORTED:
+ return "ATOM_WS_CALL_INTERACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_FULL_SCREEN_INTENT_LAUNCHED:
+ return "ATOM_FULL_SCREEN_INTENT_LAUNCHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BAL_ALLOWED:
+ return "ATOM_BAL_ALLOWED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IN_TASK_ACTIVITY_STARTED:
+ return "ATOM_IN_TASK_ACTIVITY_STARTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CACHED_APPS_HIGH_WATERMARK:
+ return "ATOM_CACHED_APPS_HIGH_WATERMARK";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ODREFRESH_REPORTED:
+ return "ATOM_ODREFRESH_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ODSIGN_REPORTED:
+ return "ATOM_ODSIGN_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ART_DATUM_REPORTED:
+ return "ATOM_ART_DATUM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ART_DEVICE_DATUM_REPORTED:
+ return "ATOM_ART_DEVICE_DATUM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ART_DATUM_DELTA_REPORTED:
+ return "ATOM_ART_DATUM_DELTA_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BACKGROUND_DEXOPT_JOB_ENDED:
+ return "ATOM_BACKGROUND_DEXOPT_JOB_ENDED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_ADAPTIVE_SUSPEND_STATS_REPORTED:
+ return "ATOM_WEAR_ADAPTIVE_SUSPEND_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_POWER_ANOMALY_SERVICE_OPERATIONAL_STATS_REPORTED:
+ return "ATOM_WEAR_POWER_ANOMALY_SERVICE_OPERATIONAL_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_WEAR_POWER_ANOMALY_SERVICE_EVENT_STATS_REPORTED:
+ return "ATOM_WEAR_POWER_ANOMALY_SERVICE_EVENT_STATS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EMERGENCY_STATE_CHANGED:
+ return "ATOM_EMERGENCY_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DND_STATE_CHANGED:
+ return "ATOM_DND_STATE_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MTE_STATE:
+ return "ATOM_MTE_STATE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_BACK_COMPAT_GET_TOPICS_REPORTED:
+ return "ATOM_AD_SERVICES_BACK_COMPAT_GET_TOPICS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_BACK_COMPAT_EPOCH_COMPUTATION_CLASSIFIER_REPORTED:
+ return "ATOM_AD_SERVICES_BACK_COMPAT_EPOCH_COMPUTATION_CLASSIFIER_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_MEASUREMENT_DEBUG_KEYS:
+ return "ATOM_AD_SERVICES_MEASUREMENT_DEBUG_KEYS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_ERROR_REPORTED:
+ return "ATOM_AD_SERVICES_ERROR_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_BACKGROUND_JOBS_EXECUTION_REPORTED:
+ return "ATOM_AD_SERVICES_BACKGROUND_JOBS_EXECUTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_MEASUREMENT_DELAYED_SOURCE_REGISTRATION:
+ return "ATOM_AD_SERVICES_MEASUREMENT_DELAYED_SOURCE_REGISTRATION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_MEASUREMENT_ATTRIBUTION:
+ return "ATOM_AD_SERVICES_MEASUREMENT_ATTRIBUTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_MEASUREMENT_JOBS:
+ return "ATOM_AD_SERVICES_MEASUREMENT_JOBS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_MEASUREMENT_WIPEOUT:
+ return "ATOM_AD_SERVICES_MEASUREMENT_WIPEOUT";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AD_SERVICES_CONSENT_MIGRATED:
+ return "ATOM_AD_SERVICES_CONSENT_MIGRATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RKPD_POOL_STATS:
+ return "ATOM_RKPD_POOL_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RKPD_CLIENT_OPERATION:
+ return "ATOM_RKPD_CLIENT_OPERATION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTOFILL_UI_EVENT_REPORTED:
+ return "ATOM_AUTOFILL_UI_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTOFILL_FILL_REQUEST_REPORTED:
+ return "ATOM_AUTOFILL_FILL_REQUEST_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTOFILL_FILL_RESPONSE_REPORTED:
+ return "ATOM_AUTOFILL_FILL_RESPONSE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTOFILL_SAVE_EVENT_REPORTED:
+ return "ATOM_AUTOFILL_SAVE_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTOFILL_SESSION_COMMITTED:
+ return "ATOM_AUTOFILL_SESSION_COMMITTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED:
+ return "ATOM_AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEST_EXTENSION_ATOM_REPORTED:
+ return "ATOM_TEST_EXTENSION_ATOM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TEST_RESTRICTED_ATOM_REPORTED:
+ return "ATOM_TEST_RESTRICTED_ATOM_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_STATS_SOCKET_LOSS_REPORTED:
+ return "ATOM_STATS_SOCKET_LOSS_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_PLUGIN_INITIALIZED:
+ return "ATOM_PLUGIN_INITIALIZED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_TV_LOW_POWER_STANDBY_POLICY:
+ return "ATOM_TV_LOW_POWER_STANDBY_POLICY";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOCKSCREEN_SHORTCUT_SELECTED:
+ return "ATOM_LOCKSCREEN_SHORTCUT_SELECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_LOCKSCREEN_SHORTCUT_TRIGGERED:
+ return "ATOM_LOCKSCREEN_SHORTCUT_TRIGGERED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EMERGENCY_NUMBERS_INFO:
+ return "ATOM_EMERGENCY_NUMBERS_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_QUALIFIED_RAT_LIST_CHANGED:
+ return "ATOM_QUALIFIED_RAT_LIST_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_QNS_IMS_CALL_DROP_STATS:
+ return "ATOM_QNS_IMS_CALL_DROP_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_QNS_FALLBACK_RESTRICTION_CHANGED:
+ return "ATOM_QNS_FALLBACK_RESTRICTION_CHANGED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_QNS_RAT_PREFERENCE_MISMATCH_INFO:
+ return "ATOM_QNS_RAT_PREFERENCE_MISMATCH_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_QNS_HANDOVER_TIME_MILLIS:
+ return "ATOM_QNS_HANDOVER_TIME_MILLIS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_QNS_HANDOVER_PINGPONG:
+ return "ATOM_QNS_HANDOVER_PINGPONG";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SATELLITE_CONTROLLER:
+ return "ATOM_SATELLITE_CONTROLLER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SATELLITE_SESSION:
+ return "ATOM_SATELLITE_SESSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SATELLITE_INCOMING_DATAGRAM:
+ return "ATOM_SATELLITE_INCOMING_DATAGRAM";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SATELLITE_OUTGOING_DATAGRAM:
+ return "ATOM_SATELLITE_OUTGOING_DATAGRAM";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SATELLITE_PROVISION:
+ return "ATOM_SATELLITE_PROVISION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SATELLITE_SOS_MESSAGE_RECOMMENDER:
+ return "ATOM_SATELLITE_SOS_MESSAGE_RECOMMENDER";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IKE_SESSION_TERMINATED:
+ return "ATOM_IKE_SESSION_TERMINATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IKE_LIVENESS_CHECK_SESSION_VALIDATED:
+ return "ATOM_IKE_LIVENESS_CHECK_SESSION_VALIDATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_HASHED_DEVICE_NAME_REPORTED:
+ return "ATOM_BLUETOOTH_HASHED_DEVICE_NAME_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION:
+ return "ATOM_BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_L2CAP_COC_SERVER_CONNECTION:
+ return "ATOM_BLUETOOTH_L2CAP_COC_SERVER_CONNECTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_LE_SESSION_CONNECTED:
+ return "ATOM_BLUETOOTH_LE_SESSION_CONNECTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED:
+ return "ATOM_RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_BLUETOOTH_PROFILE_CONNECTION_ATTEMPTED:
+ return "ATOM_BLUETOOTH_PROFILE_CONNECTION_ATTEMPTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEALTH_CONNECT_UI_IMPRESSION:
+ return "ATOM_HEALTH_CONNECT_UI_IMPRESSION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEALTH_CONNECT_UI_INTERACTION:
+ return "ATOM_HEALTH_CONNECT_UI_INTERACTION";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEALTH_CONNECT_APP_OPENED_REPORTED:
+ return "ATOM_HEALTH_CONNECT_APP_OPENED_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEALTH_CONNECT_API_CALLED:
+ return "ATOM_HEALTH_CONNECT_API_CALLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEALTH_CONNECT_USAGE_STATS:
+ return "ATOM_HEALTH_CONNECT_USAGE_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEALTH_CONNECT_STORAGE_STATS:
+ return "ATOM_HEALTH_CONNECT_STORAGE_STATS";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_HEALTH_CONNECT_API_INVOKED:
+ return "ATOM_HEALTH_CONNECT_API_INVOKED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EXERCISE_ROUTE_API_CALLED:
+ return "ATOM_EXERCISE_ROUTE_API_CALLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ATOM_9999:
+ return "ATOM_ATOM_9999";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_ATOM_99999:
+ return "ATOM_ATOM_99999";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_THREADNETWORK_TELEMETRY_DATA_REPORTED:
+ return "ATOM_THREADNETWORK_TELEMETRY_DATA_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_THREADNETWORK_TOPO_ENTRY_REPEATED:
+ return "ATOM_THREADNETWORK_TOPO_ENTRY_REPEATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_THREADNETWORK_DEVICE_INFO_REPORTED:
+ return "ATOM_THREADNETWORK_DEVICE_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_EMERGENCY_NUMBER_DIALED:
+ return "ATOM_EMERGENCY_NUMBER_DIALED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SANDBOX_API_CALLED:
+ return "ATOM_SANDBOX_API_CALLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SANDBOX_ACTIVITY_EVENT_OCCURRED:
+ return "ATOM_SANDBOX_ACTIVITY_EVENT_OCCURRED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_SANDBOX_SDK_STORAGE:
+ return "ATOM_SANDBOX_SDK_STORAGE";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CRONET_ENGINE_CREATED:
+ return "ATOM_CRONET_ENGINE_CREATED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CRONET_TRAFFIC_REPORTED:
+ return "ATOM_CRONET_TRAFFIC_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CRONET_ENGINE_BUILDER_INITIALIZED:
+ return "ATOM_CRONET_ENGINE_BUILDER_INITIALIZED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CRONET_HTTP_FLAGS_INITIALIZED:
+ return "ATOM_CRONET_HTTP_FLAGS_INITIALIZED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CRONET_INITIALIZED:
+ return "ATOM_CRONET_INITIALIZED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_DAILY_KEEPALIVE_INFO_REPORTED:
+ return "ATOM_DAILY_KEEPALIVE_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_IP_CLIENT_RA_INFO_REPORTED:
+ return "ATOM_IP_CLIENT_RA_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_APF_SESSION_INFO_REPORTED:
+ return "ATOM_APF_SESSION_INFO_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_API_CALLED:
+ return "ATOM_CREDENTIAL_MANAGER_API_CALLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_INIT_PHASE_REPORTED:
+ return "ATOM_CREDENTIAL_MANAGER_INIT_PHASE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_CANDIDATE_PHASE_REPORTED:
+ return "ATOM_CREDENTIAL_MANAGER_CANDIDATE_PHASE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_FINAL_PHASE_REPORTED:
+ return "ATOM_CREDENTIAL_MANAGER_FINAL_PHASE_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_TOTAL_REPORTED:
+ return "ATOM_CREDENTIAL_MANAGER_TOTAL_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_FINALNOUID_REPORTED:
+ return "ATOM_CREDENTIAL_MANAGER_FINALNOUID_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_GET_REPORTED:
+ return "ATOM_CREDENTIAL_MANAGER_GET_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_AUTH_CLICK_REPORTED:
+ return "ATOM_CREDENTIAL_MANAGER_AUTH_CLICK_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_CREDENTIAL_MANAGER_APIV2_CALLED:
+ return "ATOM_CREDENTIAL_MANAGER_APIV2_CALLED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_UWB_ACTIVITY_INFO:
+ return "ATOM_UWB_ACTIVITY_INFO";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_ACTION_REPORTED:
+ return "ATOM_MEDIA_ACTION_REPORTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CONTROLS_LAUNCHED:
+ return "ATOM_MEDIA_CONTROLS_LAUNCHED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED:
+ return "ATOM_MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CODEC_STARTED:
+ return "ATOM_MEDIA_CODEC_STARTED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CODEC_STOPPED:
+ return "ATOM_MEDIA_CODEC_STOPPED";
+
+ case ::perfetto::protos::pbzero::AtomId::ATOM_MEDIA_CODEC_RENDERED:
+ return "ATOM_MEDIA_CODEC_RENDERED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/statsd/statsd_tracing_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_STATSD_TRACING_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STATSD_STATSD_TRACING_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class StatsdPullAtomConfig;
+enum AtomId : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class StatsdPullAtomConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ StatsdPullAtomConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StatsdPullAtomConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StatsdPullAtomConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pull_atom_id() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> pull_atom_id() const { return GetRepeated<int32_t>(1); }
+ bool has_raw_pull_atom_id() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> raw_pull_atom_id() const { return GetRepeated<int32_t>(2); }
+ bool has_pull_frequency_ms() const { return at<3>().valid(); }
+ int32_t pull_frequency_ms() const { return at<3>().as_int32(); }
+ bool has_packages() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> packages() const { return GetRepeated<::protozero::ConstChars>(4); }
+};
+
+class StatsdPullAtomConfig : public ::protozero::Message {
+ public:
+ using Decoder = StatsdPullAtomConfig_Decoder;
+ enum : int32_t {
+ kPullAtomIdFieldNumber = 1,
+ kRawPullAtomIdFieldNumber = 2,
+ kPullFrequencyMsFieldNumber = 3,
+ kPackagesFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StatsdPullAtomConfig"; }
+
+
+ using FieldMetadata_PullAtomId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AtomId,
+ StatsdPullAtomConfig>;
+
+ static constexpr FieldMetadata_PullAtomId kPullAtomId{};
+ void add_pull_atom_id(AtomId value) {
+ static constexpr uint32_t field_id = FieldMetadata_PullAtomId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RawPullAtomId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ StatsdPullAtomConfig>;
+
+ static constexpr FieldMetadata_RawPullAtomId kRawPullAtomId{};
+ void add_raw_pull_atom_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RawPullAtomId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PullFrequencyMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ StatsdPullAtomConfig>;
+
+ static constexpr FieldMetadata_PullFrequencyMs kPullFrequencyMs{};
+ void set_pull_frequency_ms(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PullFrequencyMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Packages =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ StatsdPullAtomConfig>;
+
+ static constexpr FieldMetadata_Packages kPackages{};
+ void add_packages(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Packages::kFieldId, data, size);
+ }
+ void add_packages(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Packages::kFieldId, chars.data, chars.size);
+ }
+ void add_packages(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Packages::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class StatsdTracingConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ StatsdTracingConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StatsdTracingConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StatsdTracingConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_push_atom_id() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> push_atom_id() const { return GetRepeated<int32_t>(1); }
+ bool has_raw_push_atom_id() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> raw_push_atom_id() const { return GetRepeated<int32_t>(2); }
+ bool has_pull_config() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> pull_config() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class StatsdTracingConfig : public ::protozero::Message {
+ public:
+ using Decoder = StatsdTracingConfig_Decoder;
+ enum : int32_t {
+ kPushAtomIdFieldNumber = 1,
+ kRawPushAtomIdFieldNumber = 2,
+ kPullConfigFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StatsdTracingConfig"; }
+
+
+ using FieldMetadata_PushAtomId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AtomId,
+ StatsdTracingConfig>;
+
+ static constexpr FieldMetadata_PushAtomId kPushAtomId{};
+ void add_push_atom_id(AtomId value) {
+ static constexpr uint32_t field_id = FieldMetadata_PushAtomId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RawPushAtomId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ StatsdTracingConfig>;
+
+ static constexpr FieldMetadata_RawPushAtomId kRawPushAtomId{};
+ void add_raw_push_atom_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RawPushAtomId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PullConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StatsdPullAtomConfig,
+ StatsdTracingConfig>;
+
+ static constexpr FieldMetadata_PullConfig kPullConfig{};
+ template <typename T = StatsdPullAtomConfig> T* add_pull_config() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYS_STATS_SYS_STATS_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYS_STATS_SYS_STATS_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+enum MeminfoCounters : int32_t;
+namespace perfetto_pbzero_enum_SysStatsConfig {
+enum StatCounters : int32_t;
+} // namespace perfetto_pbzero_enum_SysStatsConfig
+using SysStatsConfig_StatCounters = perfetto_pbzero_enum_SysStatsConfig::StatCounters;
+enum VmstatCounters : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_SysStatsConfig {
+enum StatCounters : int32_t {
+ STAT_UNSPECIFIED = 0,
+ STAT_CPU_TIMES = 1,
+ STAT_IRQ_COUNTS = 2,
+ STAT_SOFTIRQ_COUNTS = 3,
+ STAT_FORK_COUNT = 4,
+};
+} // namespace perfetto_pbzero_enum_SysStatsConfig
+using SysStatsConfig_StatCounters = perfetto_pbzero_enum_SysStatsConfig::StatCounters;
+
+
+constexpr SysStatsConfig_StatCounters SysStatsConfig_StatCounters_MIN = SysStatsConfig_StatCounters::STAT_UNSPECIFIED;
+constexpr SysStatsConfig_StatCounters SysStatsConfig_StatCounters_MAX = SysStatsConfig_StatCounters::STAT_FORK_COUNT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* SysStatsConfig_StatCounters_Name(::perfetto::protos::pbzero::SysStatsConfig_StatCounters value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::SysStatsConfig_StatCounters::STAT_UNSPECIFIED:
+ return "STAT_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::SysStatsConfig_StatCounters::STAT_CPU_TIMES:
+ return "STAT_CPU_TIMES";
+
+ case ::perfetto::protos::pbzero::SysStatsConfig_StatCounters::STAT_IRQ_COUNTS:
+ return "STAT_IRQ_COUNTS";
+
+ case ::perfetto::protos::pbzero::SysStatsConfig_StatCounters::STAT_SOFTIRQ_COUNTS:
+ return "STAT_SOFTIRQ_COUNTS";
+
+ case ::perfetto::protos::pbzero::SysStatsConfig_StatCounters::STAT_FORK_COUNT:
+ return "STAT_FORK_COUNT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class SysStatsConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ SysStatsConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStatsConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStatsConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_meminfo_period_ms() const { return at<1>().valid(); }
+ uint32_t meminfo_period_ms() const { return at<1>().as_uint32(); }
+ bool has_meminfo_counters() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> meminfo_counters() const { return GetRepeated<int32_t>(2); }
+ bool has_vmstat_period_ms() const { return at<3>().valid(); }
+ uint32_t vmstat_period_ms() const { return at<3>().as_uint32(); }
+ bool has_vmstat_counters() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> vmstat_counters() const { return GetRepeated<int32_t>(4); }
+ bool has_stat_period_ms() const { return at<5>().valid(); }
+ uint32_t stat_period_ms() const { return at<5>().as_uint32(); }
+ bool has_stat_counters() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> stat_counters() const { return GetRepeated<int32_t>(6); }
+ bool has_devfreq_period_ms() const { return at<7>().valid(); }
+ uint32_t devfreq_period_ms() const { return at<7>().as_uint32(); }
+ bool has_cpufreq_period_ms() const { return at<8>().valid(); }
+ uint32_t cpufreq_period_ms() const { return at<8>().as_uint32(); }
+ bool has_buddyinfo_period_ms() const { return at<9>().valid(); }
+ uint32_t buddyinfo_period_ms() const { return at<9>().as_uint32(); }
+ bool has_diskstat_period_ms() const { return at<10>().valid(); }
+ uint32_t diskstat_period_ms() const { return at<10>().as_uint32(); }
+ bool has_psi_period_ms() const { return at<11>().valid(); }
+ uint32_t psi_period_ms() const { return at<11>().as_uint32(); }
+};
+
+class SysStatsConfig : public ::protozero::Message {
+ public:
+ using Decoder = SysStatsConfig_Decoder;
+ enum : int32_t {
+ kMeminfoPeriodMsFieldNumber = 1,
+ kMeminfoCountersFieldNumber = 2,
+ kVmstatPeriodMsFieldNumber = 3,
+ kVmstatCountersFieldNumber = 4,
+ kStatPeriodMsFieldNumber = 5,
+ kStatCountersFieldNumber = 6,
+ kDevfreqPeriodMsFieldNumber = 7,
+ kCpufreqPeriodMsFieldNumber = 8,
+ kBuddyinfoPeriodMsFieldNumber = 9,
+ kDiskstatPeriodMsFieldNumber = 10,
+ kPsiPeriodMsFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStatsConfig"; }
+
+
+ using StatCounters = ::perfetto::protos::pbzero::SysStatsConfig_StatCounters;
+ static inline const char* StatCounters_Name(StatCounters value) {
+ return ::perfetto::protos::pbzero::SysStatsConfig_StatCounters_Name(value);
+ }
+ static inline const StatCounters STAT_UNSPECIFIED = StatCounters::STAT_UNSPECIFIED;
+ static inline const StatCounters STAT_CPU_TIMES = StatCounters::STAT_CPU_TIMES;
+ static inline const StatCounters STAT_IRQ_COUNTS = StatCounters::STAT_IRQ_COUNTS;
+ static inline const StatCounters STAT_SOFTIRQ_COUNTS = StatCounters::STAT_SOFTIRQ_COUNTS;
+ static inline const StatCounters STAT_FORK_COUNT = StatCounters::STAT_FORK_COUNT;
+
+ using FieldMetadata_MeminfoPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_MeminfoPeriodMs kMeminfoPeriodMs{};
+ void set_meminfo_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MeminfoPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MeminfoCounters =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ MeminfoCounters,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_MeminfoCounters kMeminfoCounters{};
+ void add_meminfo_counters(MeminfoCounters value) {
+ static constexpr uint32_t field_id = FieldMetadata_MeminfoCounters::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VmstatPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_VmstatPeriodMs kVmstatPeriodMs{};
+ void set_vmstat_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VmstatPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VmstatCounters =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ VmstatCounters,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_VmstatCounters kVmstatCounters{};
+ void add_vmstat_counters(VmstatCounters value) {
+ static constexpr uint32_t field_id = FieldMetadata_VmstatCounters::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StatPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_StatPeriodMs kStatPeriodMs{};
+ void set_stat_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StatPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StatCounters =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ SysStatsConfig_StatCounters,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_StatCounters kStatCounters{};
+ void add_stat_counters(SysStatsConfig_StatCounters value) {
+ static constexpr uint32_t field_id = FieldMetadata_StatCounters::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DevfreqPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_DevfreqPeriodMs kDevfreqPeriodMs{};
+ void set_devfreq_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DevfreqPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpufreqPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_CpufreqPeriodMs kCpufreqPeriodMs{};
+ void set_cpufreq_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpufreqPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BuddyinfoPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_BuddyinfoPeriodMs kBuddyinfoPeriodMs{};
+ void set_buddyinfo_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BuddyinfoPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DiskstatPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_DiskstatPeriodMs kDiskstatPeriodMs{};
+ void set_diskstat_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DiskstatPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PsiPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStatsConfig>;
+
+ static constexpr FieldMetadata_PsiPeriodMs kPsiPeriodMs{};
+ void set_psi_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PsiPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/system_info/system_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYSTEM_INFO_SYSTEM_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_SYSTEM_INFO_SYSTEM_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SystemInfoConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SystemInfoConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SystemInfoConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SystemInfoConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class SystemInfoConfig : public ::protozero::Message {
+ public:
+ using Decoder = SystemInfoConfig_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.SystemInfoConfig"; }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/track_event/track_event_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TrackEventConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TrackEventConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackEventConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackEventConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_disabled_categories() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> disabled_categories() const { return GetRepeated<::protozero::ConstChars>(1); }
+ bool has_enabled_categories() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> enabled_categories() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_disabled_tags() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> disabled_tags() const { return GetRepeated<::protozero::ConstChars>(3); }
+ bool has_enabled_tags() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> enabled_tags() const { return GetRepeated<::protozero::ConstChars>(4); }
+ bool has_disable_incremental_timestamps() const { return at<5>().valid(); }
+ bool disable_incremental_timestamps() const { return at<5>().as_bool(); }
+ bool has_timestamp_unit_multiplier() const { return at<6>().valid(); }
+ uint64_t timestamp_unit_multiplier() const { return at<6>().as_uint64(); }
+ bool has_filter_debug_annotations() const { return at<7>().valid(); }
+ bool filter_debug_annotations() const { return at<7>().as_bool(); }
+ bool has_enable_thread_time_sampling() const { return at<8>().valid(); }
+ bool enable_thread_time_sampling() const { return at<8>().as_bool(); }
+ bool has_filter_dynamic_event_names() const { return at<9>().valid(); }
+ bool filter_dynamic_event_names() const { return at<9>().as_bool(); }
+};
+
+class TrackEventConfig : public ::protozero::Message {
+ public:
+ using Decoder = TrackEventConfig_Decoder;
+ enum : int32_t {
+ kDisabledCategoriesFieldNumber = 1,
+ kEnabledCategoriesFieldNumber = 2,
+ kDisabledTagsFieldNumber = 3,
+ kEnabledTagsFieldNumber = 4,
+ kDisableIncrementalTimestampsFieldNumber = 5,
+ kTimestampUnitMultiplierFieldNumber = 6,
+ kFilterDebugAnnotationsFieldNumber = 7,
+ kEnableThreadTimeSamplingFieldNumber = 8,
+ kFilterDynamicEventNamesFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackEventConfig"; }
+
+
+ using FieldMetadata_DisabledCategories =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_DisabledCategories kDisabledCategories{};
+ void add_disabled_categories(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DisabledCategories::kFieldId, data, size);
+ }
+ void add_disabled_categories(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DisabledCategories::kFieldId, chars.data, chars.size);
+ }
+ void add_disabled_categories(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisabledCategories::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnabledCategories =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_EnabledCategories kEnabledCategories{};
+ void add_enabled_categories(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_EnabledCategories::kFieldId, data, size);
+ }
+ void add_enabled_categories(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_EnabledCategories::kFieldId, chars.data, chars.size);
+ }
+ void add_enabled_categories(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnabledCategories::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisabledTags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_DisabledTags kDisabledTags{};
+ void add_disabled_tags(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DisabledTags::kFieldId, data, size);
+ }
+ void add_disabled_tags(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DisabledTags::kFieldId, chars.data, chars.size);
+ }
+ void add_disabled_tags(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisabledTags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnabledTags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_EnabledTags kEnabledTags{};
+ void add_enabled_tags(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_EnabledTags::kFieldId, data, size);
+ }
+ void add_enabled_tags(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_EnabledTags::kFieldId, chars.data, chars.size);
+ }
+ void add_enabled_tags(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnabledTags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableIncrementalTimestamps =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_DisableIncrementalTimestamps kDisableIncrementalTimestamps{};
+ void set_disable_incremental_timestamps(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableIncrementalTimestamps::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimestampUnitMultiplier =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_TimestampUnitMultiplier kTimestampUnitMultiplier{};
+ void set_timestamp_unit_multiplier(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampUnitMultiplier::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FilterDebugAnnotations =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_FilterDebugAnnotations kFilterDebugAnnotations{};
+ void set_filter_debug_annotations(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_FilterDebugAnnotations::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnableThreadTimeSampling =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_EnableThreadTimeSampling kEnableThreadTimeSampling{};
+ void set_enable_thread_time_sampling(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnableThreadTimeSampling::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FilterDynamicEventNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TrackEventConfig>;
+
+ static constexpr FieldMetadata_FilterDynamicEventNames kFilterDynamicEventNames{};
+ void set_filter_dynamic_event_names(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_FilterDynamicEventNames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/chrome/chrome_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ChromeConfig {
+enum ClientPriority : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeConfig
+using ChromeConfig_ClientPriority = perfetto_pbzero_enum_ChromeConfig::ClientPriority;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeConfig {
+enum ClientPriority : int32_t {
+ UNKNOWN = 0,
+ BACKGROUND = 1,
+ USER_INITIATED = 2,
+};
+} // namespace perfetto_pbzero_enum_ChromeConfig
+using ChromeConfig_ClientPriority = perfetto_pbzero_enum_ChromeConfig::ClientPriority;
+
+
+constexpr ChromeConfig_ClientPriority ChromeConfig_ClientPriority_MIN = ChromeConfig_ClientPriority::UNKNOWN;
+constexpr ChromeConfig_ClientPriority ChromeConfig_ClientPriority_MAX = ChromeConfig_ClientPriority::USER_INITIATED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeConfig_ClientPriority_Name(::perfetto::protos::pbzero::ChromeConfig_ClientPriority value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeConfig_ClientPriority::UNKNOWN:
+ return "UNKNOWN";
+
+ case ::perfetto::protos::pbzero::ChromeConfig_ClientPriority::BACKGROUND:
+ return "BACKGROUND";
+
+ case ::perfetto::protos::pbzero::ChromeConfig_ClientPriority::USER_INITIATED:
+ return "USER_INITIATED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trace_config() const { return at<1>().valid(); }
+ ::protozero::ConstChars trace_config() const { return at<1>().as_string(); }
+ bool has_privacy_filtering_enabled() const { return at<2>().valid(); }
+ bool privacy_filtering_enabled() const { return at<2>().as_bool(); }
+ bool has_convert_to_legacy_json() const { return at<3>().valid(); }
+ bool convert_to_legacy_json() const { return at<3>().as_bool(); }
+ bool has_client_priority() const { return at<4>().valid(); }
+ int32_t client_priority() const { return at<4>().as_int32(); }
+ bool has_json_agent_label_filter() const { return at<5>().valid(); }
+ ::protozero::ConstChars json_agent_label_filter() const { return at<5>().as_string(); }
+};
+
+class ChromeConfig : public ::protozero::Message {
+ public:
+ using Decoder = ChromeConfig_Decoder;
+ enum : int32_t {
+ kTraceConfigFieldNumber = 1,
+ kPrivacyFilteringEnabledFieldNumber = 2,
+ kConvertToLegacyJsonFieldNumber = 3,
+ kClientPriorityFieldNumber = 4,
+ kJsonAgentLabelFilterFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeConfig"; }
+
+
+ using ClientPriority = ::perfetto::protos::pbzero::ChromeConfig_ClientPriority;
+ static inline const char* ClientPriority_Name(ClientPriority value) {
+ return ::perfetto::protos::pbzero::ChromeConfig_ClientPriority_Name(value);
+ }
+ static inline const ClientPriority UNKNOWN = ClientPriority::UNKNOWN;
+ static inline const ClientPriority BACKGROUND = ClientPriority::BACKGROUND;
+ static inline const ClientPriority USER_INITIATED = ClientPriority::USER_INITIATED;
+
+ using FieldMetadata_TraceConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeConfig>;
+
+ static constexpr FieldMetadata_TraceConfig kTraceConfig{};
+ void set_trace_config(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TraceConfig::kFieldId, data, size);
+ }
+ void set_trace_config(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TraceConfig::kFieldId, chars.data, chars.size);
+ }
+ void set_trace_config(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceConfig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrivacyFilteringEnabled =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeConfig>;
+
+ static constexpr FieldMetadata_PrivacyFilteringEnabled kPrivacyFilteringEnabled{};
+ void set_privacy_filtering_enabled(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrivacyFilteringEnabled::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ConvertToLegacyJson =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeConfig>;
+
+ static constexpr FieldMetadata_ConvertToLegacyJson kConvertToLegacyJson{};
+ void set_convert_to_legacy_json(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ConvertToLegacyJson::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClientPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeConfig_ClientPriority,
+ ChromeConfig>;
+
+ static constexpr FieldMetadata_ClientPriority kClientPriority{};
+ void set_client_priority(ChromeConfig_ClientPriority value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClientPriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JsonAgentLabelFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeConfig>;
+
+ static constexpr FieldMetadata_JsonAgentLabelFilter kJsonAgentLabelFilter{};
+ void set_json_agent_label_filter(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_JsonAgentLabelFilter::kFieldId, data, size);
+ }
+ void set_json_agent_label_filter(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_JsonAgentLabelFilter::kFieldId, chars.data, chars.size);
+ }
+ void set_json_agent_label_filter(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_JsonAgentLabelFilter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/chrome/scenario_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_SCENARIO_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_SCENARIO_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class NestedScenarioConfig;
+class ScenarioConfig;
+class TraceConfig;
+class TriggerRule;
+class TriggerRule_HistogramTrigger;
+class TriggerRule_RepeatingInterval;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TracingTriggerRulesConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TracingTriggerRulesConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingTriggerRulesConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingTriggerRulesConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_rules() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> rules() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class TracingTriggerRulesConfig : public ::protozero::Message {
+ public:
+ using Decoder = TracingTriggerRulesConfig_Decoder;
+ enum : int32_t {
+ kRulesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingTriggerRulesConfig"; }
+
+
+ using FieldMetadata_Rules =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ TracingTriggerRulesConfig>;
+
+ static constexpr FieldMetadata_Rules kRules{};
+ template <typename T = TriggerRule> T* add_rules() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class ChromeFieldTracingConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeFieldTracingConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeFieldTracingConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeFieldTracingConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_scenarios() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> scenarios() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class ChromeFieldTracingConfig : public ::protozero::Message {
+ public:
+ using Decoder = ChromeFieldTracingConfig_Decoder;
+ enum : int32_t {
+ kScenariosFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeFieldTracingConfig"; }
+
+
+ using FieldMetadata_Scenarios =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ScenarioConfig,
+ ChromeFieldTracingConfig>;
+
+ static constexpr FieldMetadata_Scenarios kScenarios{};
+ template <typename T = ScenarioConfig> T* add_scenarios() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class ScenarioConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ScenarioConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ScenarioConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ScenarioConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_scenario_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars scenario_name() const { return at<1>().as_string(); }
+ bool has_start_rules() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> start_rules() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_stop_rules() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> stop_rules() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_upload_rules() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> upload_rules() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_setup_rules() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> setup_rules() const { return GetRepeated<::protozero::ConstBytes>(5); }
+ bool has_trace_config() const { return at<6>().valid(); }
+ ::protozero::ConstBytes trace_config() const { return at<6>().as_bytes(); }
+ bool has_nested_scenarios() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> nested_scenarios() const { return GetRepeated<::protozero::ConstBytes>(7); }
+};
+
+class ScenarioConfig : public ::protozero::Message {
+ public:
+ using Decoder = ScenarioConfig_Decoder;
+ enum : int32_t {
+ kScenarioNameFieldNumber = 1,
+ kStartRulesFieldNumber = 2,
+ kStopRulesFieldNumber = 3,
+ kUploadRulesFieldNumber = 4,
+ kSetupRulesFieldNumber = 5,
+ kTraceConfigFieldNumber = 6,
+ kNestedScenariosFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ScenarioConfig"; }
+
+
+ using FieldMetadata_ScenarioName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ScenarioConfig>;
+
+ static constexpr FieldMetadata_ScenarioName kScenarioName{};
+ void set_scenario_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ScenarioName::kFieldId, data, size);
+ }
+ void set_scenario_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ScenarioName::kFieldId, chars.data, chars.size);
+ }
+ void set_scenario_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScenarioName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ ScenarioConfig>;
+
+ static constexpr FieldMetadata_StartRules kStartRules{};
+ template <typename T = TriggerRule> T* add_start_rules() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_StopRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ ScenarioConfig>;
+
+ static constexpr FieldMetadata_StopRules kStopRules{};
+ template <typename T = TriggerRule> T* add_stop_rules() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_UploadRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ ScenarioConfig>;
+
+ static constexpr FieldMetadata_UploadRules kUploadRules{};
+ template <typename T = TriggerRule> T* add_upload_rules() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_SetupRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ ScenarioConfig>;
+
+ static constexpr FieldMetadata_SetupRules kSetupRules{};
+ template <typename T = TriggerRule> T* add_setup_rules() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_TraceConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig,
+ ScenarioConfig>;
+
+ static constexpr FieldMetadata_TraceConfig kTraceConfig{};
+ template <typename T = TraceConfig> T* set_trace_config() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_NestedScenarios =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NestedScenarioConfig,
+ ScenarioConfig>;
+
+ static constexpr FieldMetadata_NestedScenarios kNestedScenarios{};
+ template <typename T = NestedScenarioConfig> T* add_nested_scenarios() {
+ return BeginNestedMessage<T>(7);
+ }
+
+};
+
+class NestedScenarioConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ NestedScenarioConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NestedScenarioConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NestedScenarioConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_scenario_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars scenario_name() const { return at<1>().as_string(); }
+ bool has_start_rules() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> start_rules() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_stop_rules() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> stop_rules() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_upload_rules() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> upload_rules() const { return GetRepeated<::protozero::ConstBytes>(4); }
+};
+
+class NestedScenarioConfig : public ::protozero::Message {
+ public:
+ using Decoder = NestedScenarioConfig_Decoder;
+ enum : int32_t {
+ kScenarioNameFieldNumber = 1,
+ kStartRulesFieldNumber = 2,
+ kStopRulesFieldNumber = 3,
+ kUploadRulesFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NestedScenarioConfig"; }
+
+
+ using FieldMetadata_ScenarioName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ NestedScenarioConfig>;
+
+ static constexpr FieldMetadata_ScenarioName kScenarioName{};
+ void set_scenario_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ScenarioName::kFieldId, data, size);
+ }
+ void set_scenario_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ScenarioName::kFieldId, chars.data, chars.size);
+ }
+ void set_scenario_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScenarioName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ NestedScenarioConfig>;
+
+ static constexpr FieldMetadata_StartRules kStartRules{};
+ template <typename T = TriggerRule> T* add_start_rules() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_StopRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ NestedScenarioConfig>;
+
+ static constexpr FieldMetadata_StopRules kStopRules{};
+ template <typename T = TriggerRule> T* add_stop_rules() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_UploadRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule,
+ NestedScenarioConfig>;
+
+ static constexpr FieldMetadata_UploadRules kUploadRules{};
+ template <typename T = TriggerRule> T* add_upload_rules() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+class TriggerRule_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TriggerRule_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TriggerRule_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TriggerRule_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_trigger_chance() const { return at<2>().valid(); }
+ float trigger_chance() const { return at<2>().as_float(); }
+ bool has_delay_ms() const { return at<3>().valid(); }
+ uint64_t delay_ms() const { return at<3>().as_uint64(); }
+ bool has_activation_delay_ms() const { return at<8>().valid(); }
+ uint64_t activation_delay_ms() const { return at<8>().as_uint64(); }
+ bool has_manual_trigger_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars manual_trigger_name() const { return at<4>().as_string(); }
+ bool has_histogram() const { return at<5>().valid(); }
+ ::protozero::ConstBytes histogram() const { return at<5>().as_bytes(); }
+ bool has_repeating_interval() const { return at<6>().valid(); }
+ ::protozero::ConstBytes repeating_interval() const { return at<6>().as_bytes(); }
+};
+
+class TriggerRule : public ::protozero::Message {
+ public:
+ using Decoder = TriggerRule_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kTriggerChanceFieldNumber = 2,
+ kDelayMsFieldNumber = 3,
+ kActivationDelayMsFieldNumber = 8,
+ kManualTriggerNameFieldNumber = 4,
+ kHistogramFieldNumber = 5,
+ kRepeatingIntervalFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TriggerRule"; }
+
+ using HistogramTrigger = ::perfetto::protos::pbzero::TriggerRule_HistogramTrigger;
+ using RepeatingInterval = ::perfetto::protos::pbzero::TriggerRule_RepeatingInterval;
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TriggerRule>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TriggerChance =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ TriggerRule>;
+
+ static constexpr FieldMetadata_TriggerChance kTriggerChance{};
+ void set_trigger_chance(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggerChance::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DelayMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TriggerRule>;
+
+ static constexpr FieldMetadata_DelayMs kDelayMs{};
+ void set_delay_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DelayMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ActivationDelayMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TriggerRule>;
+
+ static constexpr FieldMetadata_ActivationDelayMs kActivationDelayMs{};
+ void set_activation_delay_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActivationDelayMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ManualTriggerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TriggerRule>;
+
+ static constexpr FieldMetadata_ManualTriggerName kManualTriggerName{};
+ void set_manual_trigger_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ManualTriggerName::kFieldId, data, size);
+ }
+ void set_manual_trigger_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ManualTriggerName::kFieldId, chars.data, chars.size);
+ }
+ void set_manual_trigger_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ManualTriggerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Histogram =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule_HistogramTrigger,
+ TriggerRule>;
+
+ static constexpr FieldMetadata_Histogram kHistogram{};
+ template <typename T = TriggerRule_HistogramTrigger> T* set_histogram() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_RepeatingInterval =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TriggerRule_RepeatingInterval,
+ TriggerRule>;
+
+ static constexpr FieldMetadata_RepeatingInterval kRepeatingInterval{};
+ template <typename T = TriggerRule_RepeatingInterval> T* set_repeating_interval() {
+ return BeginNestedMessage<T>(6);
+ }
+
+};
+
+class TriggerRule_RepeatingInterval_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TriggerRule_RepeatingInterval_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TriggerRule_RepeatingInterval_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TriggerRule_RepeatingInterval_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_period_ms() const { return at<1>().valid(); }
+ uint64_t period_ms() const { return at<1>().as_uint64(); }
+ bool has_randomized() const { return at<2>().valid(); }
+ bool randomized() const { return at<2>().as_bool(); }
+};
+
+class TriggerRule_RepeatingInterval : public ::protozero::Message {
+ public:
+ using Decoder = TriggerRule_RepeatingInterval_Decoder;
+ enum : int32_t {
+ kPeriodMsFieldNumber = 1,
+ kRandomizedFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TriggerRule.RepeatingInterval"; }
+
+
+ using FieldMetadata_PeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TriggerRule_RepeatingInterval>;
+
+ static constexpr FieldMetadata_PeriodMs kPeriodMs{};
+ void set_period_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Randomized =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TriggerRule_RepeatingInterval>;
+
+ static constexpr FieldMetadata_Randomized kRandomized{};
+ void set_randomized(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Randomized::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TriggerRule_HistogramTrigger_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TriggerRule_HistogramTrigger_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TriggerRule_HistogramTrigger_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TriggerRule_HistogramTrigger_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_histogram_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars histogram_name() const { return at<1>().as_string(); }
+ bool has_min_value() const { return at<2>().valid(); }
+ int64_t min_value() const { return at<2>().as_int64(); }
+ bool has_max_value() const { return at<3>().valid(); }
+ int64_t max_value() const { return at<3>().as_int64(); }
+};
+
+class TriggerRule_HistogramTrigger : public ::protozero::Message {
+ public:
+ using Decoder = TriggerRule_HistogramTrigger_Decoder;
+ enum : int32_t {
+ kHistogramNameFieldNumber = 1,
+ kMinValueFieldNumber = 2,
+ kMaxValueFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TriggerRule.HistogramTrigger"; }
+
+
+ using FieldMetadata_HistogramName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TriggerRule_HistogramTrigger>;
+
+ static constexpr FieldMetadata_HistogramName kHistogramName{};
+ void set_histogram_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HistogramName::kFieldId, data, size);
+ }
+ void set_histogram_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HistogramName::kFieldId, chars.data, chars.size);
+ }
+ void set_histogram_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HistogramName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MinValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TriggerRule_HistogramTrigger>;
+
+ static constexpr FieldMetadata_MinValue kMinValue{};
+ void set_min_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MinValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TriggerRule_HistogramTrigger>;
+
+ static constexpr FieldMetadata_MaxValue kMaxValue{};
+ void set_max_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/chrome/v8_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_V8_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_CHROME_V8_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class V8Config_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8Config_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8Config_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8Config_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_log_script_sources() const { return at<1>().valid(); }
+ bool log_script_sources() const { return at<1>().as_bool(); }
+ bool has_log_instructions() const { return at<2>().valid(); }
+ bool log_instructions() const { return at<2>().as_bool(); }
+};
+
+class V8Config : public ::protozero::Message {
+ public:
+ using Decoder = V8Config_Decoder;
+ enum : int32_t {
+ kLogScriptSourcesFieldNumber = 1,
+ kLogInstructionsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8Config"; }
+
+
+ using FieldMetadata_LogScriptSources =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ V8Config>;
+
+ static constexpr FieldMetadata_LogScriptSources kLogScriptSources{};
+ void set_log_script_sources(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogScriptSources::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LogInstructions =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ V8Config>;
+
+ static constexpr FieldMetadata_LogInstructions kLogInstructions{};
+ void set_log_instructions(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogInstructions::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/data_source_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidGameInterventionListConfig;
+class AndroidInputEventConfig;
+class AndroidLogConfig;
+class AndroidPolledStateConfig;
+class AndroidPowerConfig;
+class AndroidSdkSyspropGuardConfig;
+class AndroidSystemPropertyConfig;
+class ChromeConfig;
+class EtwConfig;
+class FtraceConfig;
+class GpuCounterConfig;
+class HeapprofdConfig;
+class InodeFileConfig;
+class InterceptorConfig;
+class JavaHprofConfig;
+class NetworkPacketTraceConfig;
+class PackagesListConfig;
+class PerfEventConfig;
+class ProcessStatsConfig;
+class ProtoLogConfig;
+class StatsdTracingConfig;
+class SurfaceFlingerLayersConfig;
+class SurfaceFlingerTransactionsConfig;
+class SysStatsConfig;
+class SystemInfoConfig;
+class TestConfig;
+class TrackEventConfig;
+class V8Config;
+class VulkanMemoryConfig;
+namespace perfetto_pbzero_enum_DataSourceConfig {
+enum SessionInitiator : int32_t;
+} // namespace perfetto_pbzero_enum_DataSourceConfig
+using DataSourceConfig_SessionInitiator = perfetto_pbzero_enum_DataSourceConfig::SessionInitiator;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_DataSourceConfig {
+enum SessionInitiator : int32_t {
+ SESSION_INITIATOR_UNSPECIFIED = 0,
+ SESSION_INITIATOR_TRUSTED_SYSTEM = 1,
+};
+} // namespace perfetto_pbzero_enum_DataSourceConfig
+using DataSourceConfig_SessionInitiator = perfetto_pbzero_enum_DataSourceConfig::SessionInitiator;
+
+
+constexpr DataSourceConfig_SessionInitiator DataSourceConfig_SessionInitiator_MIN = DataSourceConfig_SessionInitiator::SESSION_INITIATOR_UNSPECIFIED;
+constexpr DataSourceConfig_SessionInitiator DataSourceConfig_SessionInitiator_MAX = DataSourceConfig_SessionInitiator::SESSION_INITIATOR_TRUSTED_SYSTEM;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* DataSourceConfig_SessionInitiator_Name(::perfetto::protos::pbzero::DataSourceConfig_SessionInitiator value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::DataSourceConfig_SessionInitiator::SESSION_INITIATOR_UNSPECIFIED:
+ return "SESSION_INITIATOR_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::DataSourceConfig_SessionInitiator::SESSION_INITIATOR_TRUSTED_SYSTEM:
+ return "SESSION_INITIATOR_TRUSTED_SYSTEM";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class DataSourceConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/128, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DataSourceConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DataSourceConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DataSourceConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_target_buffer() const { return at<2>().valid(); }
+ uint32_t target_buffer() const { return at<2>().as_uint32(); }
+ bool has_trace_duration_ms() const { return at<3>().valid(); }
+ uint32_t trace_duration_ms() const { return at<3>().as_uint32(); }
+ bool has_prefer_suspend_clock_for_duration() const { return at<122>().valid(); }
+ bool prefer_suspend_clock_for_duration() const { return at<122>().as_bool(); }
+ bool has_stop_timeout_ms() const { return at<7>().valid(); }
+ uint32_t stop_timeout_ms() const { return at<7>().as_uint32(); }
+ bool has_enable_extra_guardrails() const { return at<6>().valid(); }
+ bool enable_extra_guardrails() const { return at<6>().as_bool(); }
+ bool has_session_initiator() const { return at<8>().valid(); }
+ int32_t session_initiator() const { return at<8>().as_int32(); }
+ bool has_tracing_session_id() const { return at<4>().valid(); }
+ uint64_t tracing_session_id() const { return at<4>().as_uint64(); }
+ bool has_ftrace_config() const { return at<100>().valid(); }
+ ::protozero::ConstBytes ftrace_config() const { return at<100>().as_bytes(); }
+ bool has_inode_file_config() const { return at<102>().valid(); }
+ ::protozero::ConstBytes inode_file_config() const { return at<102>().as_bytes(); }
+ bool has_process_stats_config() const { return at<103>().valid(); }
+ ::protozero::ConstBytes process_stats_config() const { return at<103>().as_bytes(); }
+ bool has_sys_stats_config() const { return at<104>().valid(); }
+ ::protozero::ConstBytes sys_stats_config() const { return at<104>().as_bytes(); }
+ bool has_heapprofd_config() const { return at<105>().valid(); }
+ ::protozero::ConstBytes heapprofd_config() const { return at<105>().as_bytes(); }
+ bool has_java_hprof_config() const { return at<110>().valid(); }
+ ::protozero::ConstBytes java_hprof_config() const { return at<110>().as_bytes(); }
+ bool has_android_power_config() const { return at<106>().valid(); }
+ ::protozero::ConstBytes android_power_config() const { return at<106>().as_bytes(); }
+ bool has_android_log_config() const { return at<107>().valid(); }
+ ::protozero::ConstBytes android_log_config() const { return at<107>().as_bytes(); }
+ bool has_gpu_counter_config() const { return at<108>().valid(); }
+ ::protozero::ConstBytes gpu_counter_config() const { return at<108>().as_bytes(); }
+ bool has_android_game_intervention_list_config() const { return at<116>().valid(); }
+ ::protozero::ConstBytes android_game_intervention_list_config() const { return at<116>().as_bytes(); }
+ bool has_packages_list_config() const { return at<109>().valid(); }
+ ::protozero::ConstBytes packages_list_config() const { return at<109>().as_bytes(); }
+ bool has_perf_event_config() const { return at<111>().valid(); }
+ ::protozero::ConstBytes perf_event_config() const { return at<111>().as_bytes(); }
+ bool has_vulkan_memory_config() const { return at<112>().valid(); }
+ ::protozero::ConstBytes vulkan_memory_config() const { return at<112>().as_bytes(); }
+ bool has_track_event_config() const { return at<113>().valid(); }
+ ::protozero::ConstBytes track_event_config() const { return at<113>().as_bytes(); }
+ bool has_android_polled_state_config() const { return at<114>().valid(); }
+ ::protozero::ConstBytes android_polled_state_config() const { return at<114>().as_bytes(); }
+ bool has_android_system_property_config() const { return at<118>().valid(); }
+ ::protozero::ConstBytes android_system_property_config() const { return at<118>().as_bytes(); }
+ bool has_statsd_tracing_config() const { return at<117>().valid(); }
+ ::protozero::ConstBytes statsd_tracing_config() const { return at<117>().as_bytes(); }
+ bool has_system_info_config() const { return at<119>().valid(); }
+ ::protozero::ConstBytes system_info_config() const { return at<119>().as_bytes(); }
+ bool has_chrome_config() const { return at<101>().valid(); }
+ ::protozero::ConstBytes chrome_config() const { return at<101>().as_bytes(); }
+ bool has_v8_config() const { return at<127>().valid(); }
+ ::protozero::ConstBytes v8_config() const { return at<127>().as_bytes(); }
+ bool has_interceptor_config() const { return at<115>().valid(); }
+ ::protozero::ConstBytes interceptor_config() const { return at<115>().as_bytes(); }
+ bool has_network_packet_trace_config() const { return at<120>().valid(); }
+ ::protozero::ConstBytes network_packet_trace_config() const { return at<120>().as_bytes(); }
+ bool has_surfaceflinger_layers_config() const { return at<121>().valid(); }
+ ::protozero::ConstBytes surfaceflinger_layers_config() const { return at<121>().as_bytes(); }
+ bool has_surfaceflinger_transactions_config() const { return at<123>().valid(); }
+ ::protozero::ConstBytes surfaceflinger_transactions_config() const { return at<123>().as_bytes(); }
+ bool has_android_sdk_sysprop_guard_config() const { return at<124>().valid(); }
+ ::protozero::ConstBytes android_sdk_sysprop_guard_config() const { return at<124>().as_bytes(); }
+ bool has_etw_config() const { return at<125>().valid(); }
+ ::protozero::ConstBytes etw_config() const { return at<125>().as_bytes(); }
+ bool has_protolog_config() const { return at<126>().valid(); }
+ ::protozero::ConstBytes protolog_config() const { return at<126>().as_bytes(); }
+ bool has_android_input_event_config() const { return at<128>().valid(); }
+ ::protozero::ConstBytes android_input_event_config() const { return at<128>().as_bytes(); }
+ // field legacy_config omitted because its id is too high
+ // field for_testing omitted because its id is too high
+};
+
+class DataSourceConfig : public ::protozero::Message {
+ public:
+ using Decoder = DataSourceConfig_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kTargetBufferFieldNumber = 2,
+ kTraceDurationMsFieldNumber = 3,
+ kPreferSuspendClockForDurationFieldNumber = 122,
+ kStopTimeoutMsFieldNumber = 7,
+ kEnableExtraGuardrailsFieldNumber = 6,
+ kSessionInitiatorFieldNumber = 8,
+ kTracingSessionIdFieldNumber = 4,
+ kFtraceConfigFieldNumber = 100,
+ kInodeFileConfigFieldNumber = 102,
+ kProcessStatsConfigFieldNumber = 103,
+ kSysStatsConfigFieldNumber = 104,
+ kHeapprofdConfigFieldNumber = 105,
+ kJavaHprofConfigFieldNumber = 110,
+ kAndroidPowerConfigFieldNumber = 106,
+ kAndroidLogConfigFieldNumber = 107,
+ kGpuCounterConfigFieldNumber = 108,
+ kAndroidGameInterventionListConfigFieldNumber = 116,
+ kPackagesListConfigFieldNumber = 109,
+ kPerfEventConfigFieldNumber = 111,
+ kVulkanMemoryConfigFieldNumber = 112,
+ kTrackEventConfigFieldNumber = 113,
+ kAndroidPolledStateConfigFieldNumber = 114,
+ kAndroidSystemPropertyConfigFieldNumber = 118,
+ kStatsdTracingConfigFieldNumber = 117,
+ kSystemInfoConfigFieldNumber = 119,
+ kChromeConfigFieldNumber = 101,
+ kV8ConfigFieldNumber = 127,
+ kInterceptorConfigFieldNumber = 115,
+ kNetworkPacketTraceConfigFieldNumber = 120,
+ kSurfaceflingerLayersConfigFieldNumber = 121,
+ kSurfaceflingerTransactionsConfigFieldNumber = 123,
+ kAndroidSdkSyspropGuardConfigFieldNumber = 124,
+ kEtwConfigFieldNumber = 125,
+ kProtologConfigFieldNumber = 126,
+ kAndroidInputEventConfigFieldNumber = 128,
+ kLegacyConfigFieldNumber = 1000,
+ kForTestingFieldNumber = 1001,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DataSourceConfig"; }
+
+
+ using SessionInitiator = ::perfetto::protos::pbzero::DataSourceConfig_SessionInitiator;
+ static inline const char* SessionInitiator_Name(SessionInitiator value) {
+ return ::perfetto::protos::pbzero::DataSourceConfig_SessionInitiator_Name(value);
+ }
+ static inline const SessionInitiator SESSION_INITIATOR_UNSPECIFIED = SessionInitiator::SESSION_INITIATOR_UNSPECIFIED;
+ static inline const SessionInitiator SESSION_INITIATOR_TRUSTED_SYSTEM = SessionInitiator::SESSION_INITIATOR_TRUSTED_SYSTEM;
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_TargetBuffer kTargetBuffer{};
+ void set_target_buffer(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetBuffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceDurationMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_TraceDurationMs kTraceDurationMs{};
+ void set_trace_duration_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceDurationMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreferSuspendClockForDuration =
+ ::protozero::proto_utils::FieldMetadata<
+ 122,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_PreferSuspendClockForDuration kPreferSuspendClockForDuration{};
+ void set_prefer_suspend_clock_for_duration(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreferSuspendClockForDuration::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StopTimeoutMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_StopTimeoutMs kStopTimeoutMs{};
+ void set_stop_timeout_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StopTimeoutMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnableExtraGuardrails =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_EnableExtraGuardrails kEnableExtraGuardrails{};
+ void set_enable_extra_guardrails(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnableExtraGuardrails::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SessionInitiator =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ DataSourceConfig_SessionInitiator,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_SessionInitiator kSessionInitiator{};
+ void set_session_initiator(DataSourceConfig_SessionInitiator value) {
+ static constexpr uint32_t field_id = FieldMetadata_SessionInitiator::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TracingSessionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_TracingSessionId kTracingSessionId{};
+ void set_tracing_session_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingSessionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FtraceConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 100,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_FtraceConfig kFtraceConfig{};
+ template <typename T = FtraceConfig> T* set_ftrace_config() {
+ return BeginNestedMessage<T>(100);
+ }
+
+ void set_ftrace_config_raw(const std::string& raw) {
+ return AppendBytes(100, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_InodeFileConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 102,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InodeFileConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_InodeFileConfig kInodeFileConfig{};
+ template <typename T = InodeFileConfig> T* set_inode_file_config() {
+ return BeginNestedMessage<T>(102);
+ }
+
+ void set_inode_file_config_raw(const std::string& raw) {
+ return AppendBytes(102, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_ProcessStatsConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 103,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessStatsConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_ProcessStatsConfig kProcessStatsConfig{};
+ template <typename T = ProcessStatsConfig> T* set_process_stats_config() {
+ return BeginNestedMessage<T>(103);
+ }
+
+ void set_process_stats_config_raw(const std::string& raw) {
+ return AppendBytes(103, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_SysStatsConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 104,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStatsConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_SysStatsConfig kSysStatsConfig{};
+ template <typename T = SysStatsConfig> T* set_sys_stats_config() {
+ return BeginNestedMessage<T>(104);
+ }
+
+ void set_sys_stats_config_raw(const std::string& raw) {
+ return AppendBytes(104, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_HeapprofdConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 105,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HeapprofdConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_HeapprofdConfig kHeapprofdConfig{};
+ template <typename T = HeapprofdConfig> T* set_heapprofd_config() {
+ return BeginNestedMessage<T>(105);
+ }
+
+ void set_heapprofd_config_raw(const std::string& raw) {
+ return AppendBytes(105, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_JavaHprofConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 110,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ JavaHprofConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_JavaHprofConfig kJavaHprofConfig{};
+ template <typename T = JavaHprofConfig> T* set_java_hprof_config() {
+ return BeginNestedMessage<T>(110);
+ }
+
+ void set_java_hprof_config_raw(const std::string& raw) {
+ return AppendBytes(110, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_AndroidPowerConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 106,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidPowerConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_AndroidPowerConfig kAndroidPowerConfig{};
+ template <typename T = AndroidPowerConfig> T* set_android_power_config() {
+ return BeginNestedMessage<T>(106);
+ }
+
+ void set_android_power_config_raw(const std::string& raw) {
+ return AppendBytes(106, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_AndroidLogConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 107,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidLogConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_AndroidLogConfig kAndroidLogConfig{};
+ template <typename T = AndroidLogConfig> T* set_android_log_config() {
+ return BeginNestedMessage<T>(107);
+ }
+
+ void set_android_log_config_raw(const std::string& raw) {
+ return AppendBytes(107, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_GpuCounterConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 108,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuCounterConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_GpuCounterConfig kGpuCounterConfig{};
+ template <typename T = GpuCounterConfig> T* set_gpu_counter_config() {
+ return BeginNestedMessage<T>(108);
+ }
+
+ void set_gpu_counter_config_raw(const std::string& raw) {
+ return AppendBytes(108, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_AndroidGameInterventionListConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 116,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidGameInterventionListConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_AndroidGameInterventionListConfig kAndroidGameInterventionListConfig{};
+ template <typename T = AndroidGameInterventionListConfig> T* set_android_game_intervention_list_config() {
+ return BeginNestedMessage<T>(116);
+ }
+
+ void set_android_game_intervention_list_config_raw(const std::string& raw) {
+ return AppendBytes(116, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_PackagesListConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 109,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PackagesListConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_PackagesListConfig kPackagesListConfig{};
+ template <typename T = PackagesListConfig> T* set_packages_list_config() {
+ return BeginNestedMessage<T>(109);
+ }
+
+ void set_packages_list_config_raw(const std::string& raw) {
+ return AppendBytes(109, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_PerfEventConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 111,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfEventConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_PerfEventConfig kPerfEventConfig{};
+ template <typename T = PerfEventConfig> T* set_perf_event_config() {
+ return BeginNestedMessage<T>(111);
+ }
+
+ void set_perf_event_config_raw(const std::string& raw) {
+ return AppendBytes(111, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_VulkanMemoryConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 112,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VulkanMemoryConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_VulkanMemoryConfig kVulkanMemoryConfig{};
+ template <typename T = VulkanMemoryConfig> T* set_vulkan_memory_config() {
+ return BeginNestedMessage<T>(112);
+ }
+
+ void set_vulkan_memory_config_raw(const std::string& raw) {
+ return AppendBytes(112, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_TrackEventConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 113,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackEventConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_TrackEventConfig kTrackEventConfig{};
+ template <typename T = TrackEventConfig> T* set_track_event_config() {
+ return BeginNestedMessage<T>(113);
+ }
+
+ void set_track_event_config_raw(const std::string& raw) {
+ return AppendBytes(113, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_AndroidPolledStateConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 114,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidPolledStateConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_AndroidPolledStateConfig kAndroidPolledStateConfig{};
+ template <typename T = AndroidPolledStateConfig> T* set_android_polled_state_config() {
+ return BeginNestedMessage<T>(114);
+ }
+
+ void set_android_polled_state_config_raw(const std::string& raw) {
+ return AppendBytes(114, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_AndroidSystemPropertyConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 118,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidSystemPropertyConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_AndroidSystemPropertyConfig kAndroidSystemPropertyConfig{};
+ template <typename T = AndroidSystemPropertyConfig> T* set_android_system_property_config() {
+ return BeginNestedMessage<T>(118);
+ }
+
+ void set_android_system_property_config_raw(const std::string& raw) {
+ return AppendBytes(118, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_StatsdTracingConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 117,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StatsdTracingConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_StatsdTracingConfig kStatsdTracingConfig{};
+ template <typename T = StatsdTracingConfig> T* set_statsd_tracing_config() {
+ return BeginNestedMessage<T>(117);
+ }
+
+ void set_statsd_tracing_config_raw(const std::string& raw) {
+ return AppendBytes(117, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_SystemInfoConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 119,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SystemInfoConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_SystemInfoConfig kSystemInfoConfig{};
+ template <typename T = SystemInfoConfig> T* set_system_info_config() {
+ return BeginNestedMessage<T>(119);
+ }
+
+
+ using FieldMetadata_ChromeConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 101,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_ChromeConfig kChromeConfig{};
+ template <typename T = ChromeConfig> T* set_chrome_config() {
+ return BeginNestedMessage<T>(101);
+ }
+
+
+ using FieldMetadata_V8Config =
+ ::protozero::proto_utils::FieldMetadata<
+ 127,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8Config,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_V8Config kV8Config{};
+ template <typename T = V8Config> T* set_v8_config() {
+ return BeginNestedMessage<T>(127);
+ }
+
+ void set_v8_config_raw(const std::string& raw) {
+ return AppendBytes(127, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_InterceptorConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 115,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InterceptorConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_InterceptorConfig kInterceptorConfig{};
+ template <typename T = InterceptorConfig> T* set_interceptor_config() {
+ return BeginNestedMessage<T>(115);
+ }
+
+
+ using FieldMetadata_NetworkPacketTraceConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 120,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetworkPacketTraceConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_NetworkPacketTraceConfig kNetworkPacketTraceConfig{};
+ template <typename T = NetworkPacketTraceConfig> T* set_network_packet_trace_config() {
+ return BeginNestedMessage<T>(120);
+ }
+
+ void set_network_packet_trace_config_raw(const std::string& raw) {
+ return AppendBytes(120, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_SurfaceflingerLayersConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 121,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SurfaceFlingerLayersConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_SurfaceflingerLayersConfig kSurfaceflingerLayersConfig{};
+ template <typename T = SurfaceFlingerLayersConfig> T* set_surfaceflinger_layers_config() {
+ return BeginNestedMessage<T>(121);
+ }
+
+ void set_surfaceflinger_layers_config_raw(const std::string& raw) {
+ return AppendBytes(121, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_SurfaceflingerTransactionsConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 123,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SurfaceFlingerTransactionsConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_SurfaceflingerTransactionsConfig kSurfaceflingerTransactionsConfig{};
+ template <typename T = SurfaceFlingerTransactionsConfig> T* set_surfaceflinger_transactions_config() {
+ return BeginNestedMessage<T>(123);
+ }
+
+ void set_surfaceflinger_transactions_config_raw(const std::string& raw) {
+ return AppendBytes(123, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_AndroidSdkSyspropGuardConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 124,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidSdkSyspropGuardConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_AndroidSdkSyspropGuardConfig kAndroidSdkSyspropGuardConfig{};
+ template <typename T = AndroidSdkSyspropGuardConfig> T* set_android_sdk_sysprop_guard_config() {
+ return BeginNestedMessage<T>(124);
+ }
+
+ void set_android_sdk_sysprop_guard_config_raw(const std::string& raw) {
+ return AppendBytes(124, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_EtwConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 125,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EtwConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_EtwConfig kEtwConfig{};
+ template <typename T = EtwConfig> T* set_etw_config() {
+ return BeginNestedMessage<T>(125);
+ }
+
+ void set_etw_config_raw(const std::string& raw) {
+ return AppendBytes(125, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_ProtologConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 126,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProtoLogConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_ProtologConfig kProtologConfig{};
+ template <typename T = ProtoLogConfig> T* set_protolog_config() {
+ return BeginNestedMessage<T>(126);
+ }
+
+ void set_protolog_config_raw(const std::string& raw) {
+ return AppendBytes(126, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_AndroidInputEventConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 128,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidInputEventConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_AndroidInputEventConfig kAndroidInputEventConfig{};
+ template <typename T = AndroidInputEventConfig> T* set_android_input_event_config() {
+ return BeginNestedMessage<T>(128);
+ }
+
+ void set_android_input_event_config_raw(const std::string& raw) {
+ return AppendBytes(128, raw.data(), raw.size());
+ }
+
+
+ using FieldMetadata_LegacyConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 1000,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_LegacyConfig kLegacyConfig{};
+ void set_legacy_config(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LegacyConfig::kFieldId, data, size);
+ }
+ void set_legacy_config(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LegacyConfig::kFieldId, chars.data, chars.size);
+ }
+ void set_legacy_config(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LegacyConfig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 1001,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TestConfig,
+ DataSourceConfig>;
+
+ static constexpr FieldMetadata_ForTesting kForTesting{};
+ template <typename T = TestConfig> T* set_for_testing() {
+ return BeginNestedMessage<T>(1001);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/etw/etw_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ETW_ETW_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_ETW_ETW_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_EtwConfig {
+enum KernelFlag : int32_t;
+} // namespace perfetto_pbzero_enum_EtwConfig
+using EtwConfig_KernelFlag = perfetto_pbzero_enum_EtwConfig::KernelFlag;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_EtwConfig {
+enum KernelFlag : int32_t {
+ CSWITCH = 0,
+ DISPATCHER = 1,
+};
+} // namespace perfetto_pbzero_enum_EtwConfig
+using EtwConfig_KernelFlag = perfetto_pbzero_enum_EtwConfig::KernelFlag;
+
+
+constexpr EtwConfig_KernelFlag EtwConfig_KernelFlag_MIN = EtwConfig_KernelFlag::CSWITCH;
+constexpr EtwConfig_KernelFlag EtwConfig_KernelFlag_MAX = EtwConfig_KernelFlag::DISPATCHER;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* EtwConfig_KernelFlag_Name(::perfetto::protos::pbzero::EtwConfig_KernelFlag value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::EtwConfig_KernelFlag::CSWITCH:
+ return "CSWITCH";
+
+ case ::perfetto::protos::pbzero::EtwConfig_KernelFlag::DISPATCHER:
+ return "DISPATCHER";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class EtwConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ EtwConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EtwConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EtwConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_kernel_flags() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> kernel_flags() const { return GetRepeated<int32_t>(1); }
+};
+
+class EtwConfig : public ::protozero::Message {
+ public:
+ using Decoder = EtwConfig_Decoder;
+ enum : int32_t {
+ kKernelFlagsFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EtwConfig"; }
+
+
+ using KernelFlag = ::perfetto::protos::pbzero::EtwConfig_KernelFlag;
+ static inline const char* KernelFlag_Name(KernelFlag value) {
+ return ::perfetto::protos::pbzero::EtwConfig_KernelFlag_Name(value);
+ }
+ static inline const KernelFlag CSWITCH = KernelFlag::CSWITCH;
+ static inline const KernelFlag DISPATCHER = KernelFlag::DISPATCHER;
+
+ using FieldMetadata_KernelFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ EtwConfig_KernelFlag,
+ EtwConfig>;
+
+ static constexpr FieldMetadata_KernelFlags kKernelFlags{};
+ void add_kernel_flags(EtwConfig_KernelFlag value) {
+ static constexpr uint32_t field_id = FieldMetadata_KernelFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/interceptor_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ConsoleConfig;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class InterceptorConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/100, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InterceptorConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InterceptorConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InterceptorConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_console_config() const { return at<100>().valid(); }
+ ::protozero::ConstBytes console_config() const { return at<100>().as_bytes(); }
+};
+
+class InterceptorConfig : public ::protozero::Message {
+ public:
+ using Decoder = InterceptorConfig_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kConsoleConfigFieldNumber = 100,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InterceptorConfig"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InterceptorConfig>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ConsoleConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 100,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ConsoleConfig,
+ InterceptorConfig>;
+
+ static constexpr FieldMetadata_ConsoleConfig kConsoleConfig{};
+ template <typename T = ConsoleConfig> T* set_console_config() {
+ return BeginNestedMessage<T>(100);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/stress_test_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STRESS_TEST_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_STRESS_TEST_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class StressTestConfig_WriterTiming;
+class TraceConfig;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class StressTestConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ StressTestConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StressTestConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StressTestConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trace_config() const { return at<1>().valid(); }
+ ::protozero::ConstBytes trace_config() const { return at<1>().as_bytes(); }
+ bool has_shmem_size_kb() const { return at<2>().valid(); }
+ uint32_t shmem_size_kb() const { return at<2>().as_uint32(); }
+ bool has_shmem_page_size_kb() const { return at<3>().valid(); }
+ uint32_t shmem_page_size_kb() const { return at<3>().as_uint32(); }
+ bool has_num_processes() const { return at<4>().valid(); }
+ uint32_t num_processes() const { return at<4>().as_uint32(); }
+ bool has_num_threads() const { return at<5>().valid(); }
+ uint32_t num_threads() const { return at<5>().as_uint32(); }
+ bool has_max_events() const { return at<6>().valid(); }
+ uint32_t max_events() const { return at<6>().as_uint32(); }
+ bool has_nesting() const { return at<7>().valid(); }
+ uint32_t nesting() const { return at<7>().as_uint32(); }
+ bool has_steady_state_timings() const { return at<8>().valid(); }
+ ::protozero::ConstBytes steady_state_timings() const { return at<8>().as_bytes(); }
+ bool has_burst_period_ms() const { return at<9>().valid(); }
+ uint32_t burst_period_ms() const { return at<9>().as_uint32(); }
+ bool has_burst_duration_ms() const { return at<10>().valid(); }
+ uint32_t burst_duration_ms() const { return at<10>().as_uint32(); }
+ bool has_burst_timings() const { return at<11>().valid(); }
+ ::protozero::ConstBytes burst_timings() const { return at<11>().as_bytes(); }
+};
+
+class StressTestConfig : public ::protozero::Message {
+ public:
+ using Decoder = StressTestConfig_Decoder;
+ enum : int32_t {
+ kTraceConfigFieldNumber = 1,
+ kShmemSizeKbFieldNumber = 2,
+ kShmemPageSizeKbFieldNumber = 3,
+ kNumProcessesFieldNumber = 4,
+ kNumThreadsFieldNumber = 5,
+ kMaxEventsFieldNumber = 6,
+ kNestingFieldNumber = 7,
+ kSteadyStateTimingsFieldNumber = 8,
+ kBurstPeriodMsFieldNumber = 9,
+ kBurstDurationMsFieldNumber = 10,
+ kBurstTimingsFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StressTestConfig"; }
+
+ using WriterTiming = ::perfetto::protos::pbzero::StressTestConfig_WriterTiming;
+
+ using FieldMetadata_TraceConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_TraceConfig kTraceConfig{};
+ template <typename T = TraceConfig> T* set_trace_config() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ShmemSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_ShmemSizeKb kShmemSizeKb{};
+ void set_shmem_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShmemSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ShmemPageSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_ShmemPageSizeKb kShmemPageSizeKb{};
+ void set_shmem_page_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShmemPageSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumProcesses =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_NumProcesses kNumProcesses{};
+ void set_num_processes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumProcesses::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumThreads =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_NumThreads kNumThreads{};
+ void set_num_threads(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumThreads::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_MaxEvents kMaxEvents{};
+ void set_max_events(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_Nesting kNesting{};
+ void set_nesting(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SteadyStateTimings =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StressTestConfig_WriterTiming,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_SteadyStateTimings kSteadyStateTimings{};
+ template <typename T = StressTestConfig_WriterTiming> T* set_steady_state_timings() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_BurstPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_BurstPeriodMs kBurstPeriodMs{};
+ void set_burst_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BurstPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BurstDurationMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_BurstDurationMs kBurstDurationMs{};
+ void set_burst_duration_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BurstDurationMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BurstTimings =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ StressTestConfig_WriterTiming,
+ StressTestConfig>;
+
+ static constexpr FieldMetadata_BurstTimings kBurstTimings{};
+ template <typename T = StressTestConfig_WriterTiming> T* set_burst_timings() {
+ return BeginNestedMessage<T>(11);
+ }
+
+};
+
+class StressTestConfig_WriterTiming_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ StressTestConfig_WriterTiming_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StressTestConfig_WriterTiming_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StressTestConfig_WriterTiming_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_payload_mean() const { return at<1>().valid(); }
+ double payload_mean() const { return at<1>().as_double(); }
+ bool has_payload_stddev() const { return at<2>().valid(); }
+ double payload_stddev() const { return at<2>().as_double(); }
+ bool has_rate_mean() const { return at<3>().valid(); }
+ double rate_mean() const { return at<3>().as_double(); }
+ bool has_rate_stddev() const { return at<4>().valid(); }
+ double rate_stddev() const { return at<4>().as_double(); }
+ bool has_payload_write_time_ms() const { return at<5>().valid(); }
+ uint32_t payload_write_time_ms() const { return at<5>().as_uint32(); }
+};
+
+class StressTestConfig_WriterTiming : public ::protozero::Message {
+ public:
+ using Decoder = StressTestConfig_WriterTiming_Decoder;
+ enum : int32_t {
+ kPayloadMeanFieldNumber = 1,
+ kPayloadStddevFieldNumber = 2,
+ kRateMeanFieldNumber = 3,
+ kRateStddevFieldNumber = 4,
+ kPayloadWriteTimeMsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StressTestConfig.WriterTiming"; }
+
+
+ using FieldMetadata_PayloadMean =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ StressTestConfig_WriterTiming>;
+
+ static constexpr FieldMetadata_PayloadMean kPayloadMean{};
+ void set_payload_mean(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_PayloadMean::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PayloadStddev =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ StressTestConfig_WriterTiming>;
+
+ static constexpr FieldMetadata_PayloadStddev kPayloadStddev{};
+ void set_payload_stddev(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_PayloadStddev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RateMean =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ StressTestConfig_WriterTiming>;
+
+ static constexpr FieldMetadata_RateMean kRateMean{};
+ void set_rate_mean(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_RateMean::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RateStddev =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ StressTestConfig_WriterTiming>;
+
+ static constexpr FieldMetadata_RateStddev kRateStddev{};
+ void set_rate_stddev(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_RateStddev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PayloadWriteTimeMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StressTestConfig_WriterTiming>;
+
+ static constexpr FieldMetadata_PayloadWriteTimeMs kPayloadWriteTimeMs{};
+ void set_payload_write_time_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PayloadWriteTimeMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/test_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TEST_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TEST_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class TestConfig_DummyFields;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TestConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TestConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TestConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TestConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_message_count() const { return at<1>().valid(); }
+ uint32_t message_count() const { return at<1>().as_uint32(); }
+ bool has_max_messages_per_second() const { return at<2>().valid(); }
+ uint32_t max_messages_per_second() const { return at<2>().as_uint32(); }
+ bool has_seed() const { return at<3>().valid(); }
+ uint32_t seed() const { return at<3>().as_uint32(); }
+ bool has_message_size() const { return at<4>().valid(); }
+ uint32_t message_size() const { return at<4>().as_uint32(); }
+ bool has_send_batch_on_register() const { return at<5>().valid(); }
+ bool send_batch_on_register() const { return at<5>().as_bool(); }
+ bool has_dummy_fields() const { return at<6>().valid(); }
+ ::protozero::ConstBytes dummy_fields() const { return at<6>().as_bytes(); }
+};
+
+class TestConfig : public ::protozero::Message {
+ public:
+ using Decoder = TestConfig_Decoder;
+ enum : int32_t {
+ kMessageCountFieldNumber = 1,
+ kMaxMessagesPerSecondFieldNumber = 2,
+ kSeedFieldNumber = 3,
+ kMessageSizeFieldNumber = 4,
+ kSendBatchOnRegisterFieldNumber = 5,
+ kDummyFieldsFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TestConfig"; }
+
+ using DummyFields = ::perfetto::protos::pbzero::TestConfig_DummyFields;
+
+ using FieldMetadata_MessageCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestConfig>;
+
+ static constexpr FieldMetadata_MessageCount kMessageCount{};
+ void set_message_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MessageCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxMessagesPerSecond =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestConfig>;
+
+ static constexpr FieldMetadata_MaxMessagesPerSecond kMaxMessagesPerSecond{};
+ void set_max_messages_per_second(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxMessagesPerSecond::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seed =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestConfig>;
+
+ static constexpr FieldMetadata_Seed kSeed{};
+ void set_seed(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MessageSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestConfig>;
+
+ static constexpr FieldMetadata_MessageSize kMessageSize{};
+ void set_message_size(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MessageSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SendBatchOnRegister =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TestConfig>;
+
+ static constexpr FieldMetadata_SendBatchOnRegister kSendBatchOnRegister{};
+ void set_send_batch_on_register(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SendBatchOnRegister::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DummyFields =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TestConfig_DummyFields,
+ TestConfig>;
+
+ static constexpr FieldMetadata_DummyFields kDummyFields{};
+ template <typename T = TestConfig_DummyFields> T* set_dummy_fields() {
+ return BeginNestedMessage<T>(6);
+ }
+
+};
+
+class TestConfig_DummyFields_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/14, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TestConfig_DummyFields_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TestConfig_DummyFields_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TestConfig_DummyFields_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_field_uint32() const { return at<1>().valid(); }
+ uint32_t field_uint32() const { return at<1>().as_uint32(); }
+ bool has_field_int32() const { return at<2>().valid(); }
+ int32_t field_int32() const { return at<2>().as_int32(); }
+ bool has_field_uint64() const { return at<3>().valid(); }
+ uint64_t field_uint64() const { return at<3>().as_uint64(); }
+ bool has_field_int64() const { return at<4>().valid(); }
+ int64_t field_int64() const { return at<4>().as_int64(); }
+ bool has_field_fixed64() const { return at<5>().valid(); }
+ uint64_t field_fixed64() const { return at<5>().as_uint64(); }
+ bool has_field_sfixed64() const { return at<6>().valid(); }
+ int64_t field_sfixed64() const { return at<6>().as_int64(); }
+ bool has_field_fixed32() const { return at<7>().valid(); }
+ uint32_t field_fixed32() const { return at<7>().as_uint32(); }
+ bool has_field_sfixed32() const { return at<8>().valid(); }
+ int32_t field_sfixed32() const { return at<8>().as_int32(); }
+ bool has_field_double() const { return at<9>().valid(); }
+ double field_double() const { return at<9>().as_double(); }
+ bool has_field_float() const { return at<10>().valid(); }
+ float field_float() const { return at<10>().as_float(); }
+ bool has_field_sint64() const { return at<11>().valid(); }
+ int64_t field_sint64() const { return at<11>().as_sint64(); }
+ bool has_field_sint32() const { return at<12>().valid(); }
+ int32_t field_sint32() const { return at<12>().as_sint32(); }
+ bool has_field_string() const { return at<13>().valid(); }
+ ::protozero::ConstChars field_string() const { return at<13>().as_string(); }
+ bool has_field_bytes() const { return at<14>().valid(); }
+ ::protozero::ConstBytes field_bytes() const { return at<14>().as_bytes(); }
+};
+
+class TestConfig_DummyFields : public ::protozero::Message {
+ public:
+ using Decoder = TestConfig_DummyFields_Decoder;
+ enum : int32_t {
+ kFieldUint32FieldNumber = 1,
+ kFieldInt32FieldNumber = 2,
+ kFieldUint64FieldNumber = 3,
+ kFieldInt64FieldNumber = 4,
+ kFieldFixed64FieldNumber = 5,
+ kFieldSfixed64FieldNumber = 6,
+ kFieldFixed32FieldNumber = 7,
+ kFieldSfixed32FieldNumber = 8,
+ kFieldDoubleFieldNumber = 9,
+ kFieldFloatFieldNumber = 10,
+ kFieldSint64FieldNumber = 11,
+ kFieldSint32FieldNumber = 12,
+ kFieldStringFieldNumber = 13,
+ kFieldBytesFieldNumber = 14,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TestConfig.DummyFields"; }
+
+
+ using FieldMetadata_FieldUint32 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldUint32 kFieldUint32{};
+ void set_field_uint32(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldUint32::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldInt32 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldInt32 kFieldInt32{};
+ void set_field_int32(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldInt32::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldUint64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldUint64 kFieldUint64{};
+ void set_field_uint64(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldUint64::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldInt64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldInt64 kFieldInt64{};
+ void set_field_int64(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldInt64::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldFixed64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldFixed64 kFieldFixed64{};
+ void set_field_fixed64(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldFixed64::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldSfixed64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSfixed64,
+ int64_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldSfixed64 kFieldSfixed64{};
+ void set_field_sfixed64(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldSfixed64::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSfixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldFixed32 =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32,
+ uint32_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldFixed32 kFieldFixed32{};
+ void set_field_fixed32(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldFixed32::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldSfixed32 =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSfixed32,
+ int32_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldSfixed32 kFieldSfixed32{};
+ void set_field_sfixed32(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldSfixed32::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSfixed32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldDouble =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldDouble kFieldDouble{};
+ void set_field_double(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldDouble::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldFloat =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldFloat kFieldFloat{};
+ void set_field_float(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldFloat::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldSint64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint64,
+ int64_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldSint64 kFieldSint64{};
+ void set_field_sint64(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldSint64::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldSint32 =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint32,
+ int32_t,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldSint32 kFieldSint32{};
+ void set_field_sint32(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldSint32::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldString =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldString kFieldString{};
+ void set_field_string(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FieldString::kFieldId, data, size);
+ }
+ void set_field_string(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FieldString::kFieldId, chars.data, chars.size);
+ }
+ void set_field_string(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldString::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ TestConfig_DummyFields>;
+
+ static constexpr FieldMetadata_FieldBytes kFieldBytes{};
+ void set_field_bytes(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_FieldBytes::kFieldId, data, size);
+ }
+ void set_field_bytes(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_FieldBytes::kFieldId, bytes.data, bytes.size);
+ }
+ void set_field_bytes(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FieldBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/config/trace_config.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DataSourceConfig;
+class TraceConfig_AndroidReportConfig;
+class TraceConfig_BufferConfig;
+class TraceConfig_BuiltinDataSource;
+class TraceConfig_CmdTraceStartDelay;
+class TraceConfig_DataSource;
+class TraceConfig_GuardrailOverrides;
+class TraceConfig_IncidentReportConfig;
+class TraceConfig_IncrementalStateConfig;
+class TraceConfig_ProducerConfig;
+class TraceConfig_StatsdMetadata;
+class TraceConfig_TraceFilter;
+class TraceConfig_TraceFilter_StringFilterChain;
+class TraceConfig_TraceFilter_StringFilterRule;
+class TraceConfig_TriggerConfig;
+class TraceConfig_TriggerConfig_Trigger;
+enum BuiltinClock : int32_t;
+namespace perfetto_pbzero_enum_TraceConfig_BufferConfig {
+enum FillPolicy : int32_t;
+} // namespace perfetto_pbzero_enum_TraceConfig_BufferConfig
+using TraceConfig_BufferConfig_FillPolicy = perfetto_pbzero_enum_TraceConfig_BufferConfig::FillPolicy;
+namespace perfetto_pbzero_enum_TraceConfig {
+enum CompressionType : int32_t;
+} // namespace perfetto_pbzero_enum_TraceConfig
+using TraceConfig_CompressionType = perfetto_pbzero_enum_TraceConfig::CompressionType;
+namespace perfetto_pbzero_enum_TraceConfig {
+enum LockdownModeOperation : int32_t;
+} // namespace perfetto_pbzero_enum_TraceConfig
+using TraceConfig_LockdownModeOperation = perfetto_pbzero_enum_TraceConfig::LockdownModeOperation;
+namespace perfetto_pbzero_enum_TraceConfig {
+enum StatsdLogging : int32_t;
+} // namespace perfetto_pbzero_enum_TraceConfig
+using TraceConfig_StatsdLogging = perfetto_pbzero_enum_TraceConfig::StatsdLogging;
+namespace perfetto_pbzero_enum_TraceConfig_TraceFilter {
+enum StringFilterPolicy : int32_t;
+} // namespace perfetto_pbzero_enum_TraceConfig_TraceFilter
+using TraceConfig_TraceFilter_StringFilterPolicy = perfetto_pbzero_enum_TraceConfig_TraceFilter::StringFilterPolicy;
+namespace perfetto_pbzero_enum_TraceConfig_TriggerConfig {
+enum TriggerMode : int32_t;
+} // namespace perfetto_pbzero_enum_TraceConfig_TriggerConfig
+using TraceConfig_TriggerConfig_TriggerMode = perfetto_pbzero_enum_TraceConfig_TriggerConfig::TriggerMode;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_TraceConfig {
+enum LockdownModeOperation : int32_t {
+ LOCKDOWN_UNCHANGED = 0,
+ LOCKDOWN_CLEAR = 1,
+ LOCKDOWN_SET = 2,
+};
+} // namespace perfetto_pbzero_enum_TraceConfig
+using TraceConfig_LockdownModeOperation = perfetto_pbzero_enum_TraceConfig::LockdownModeOperation;
+
+
+constexpr TraceConfig_LockdownModeOperation TraceConfig_LockdownModeOperation_MIN = TraceConfig_LockdownModeOperation::LOCKDOWN_UNCHANGED;
+constexpr TraceConfig_LockdownModeOperation TraceConfig_LockdownModeOperation_MAX = TraceConfig_LockdownModeOperation::LOCKDOWN_SET;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TraceConfig_LockdownModeOperation_Name(::perfetto::protos::pbzero::TraceConfig_LockdownModeOperation value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TraceConfig_LockdownModeOperation::LOCKDOWN_UNCHANGED:
+ return "LOCKDOWN_UNCHANGED";
+
+ case ::perfetto::protos::pbzero::TraceConfig_LockdownModeOperation::LOCKDOWN_CLEAR:
+ return "LOCKDOWN_CLEAR";
+
+ case ::perfetto::protos::pbzero::TraceConfig_LockdownModeOperation::LOCKDOWN_SET:
+ return "LOCKDOWN_SET";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TraceConfig {
+enum CompressionType : int32_t {
+ COMPRESSION_TYPE_UNSPECIFIED = 0,
+ COMPRESSION_TYPE_DEFLATE = 1,
+};
+} // namespace perfetto_pbzero_enum_TraceConfig
+using TraceConfig_CompressionType = perfetto_pbzero_enum_TraceConfig::CompressionType;
+
+
+constexpr TraceConfig_CompressionType TraceConfig_CompressionType_MIN = TraceConfig_CompressionType::COMPRESSION_TYPE_UNSPECIFIED;
+constexpr TraceConfig_CompressionType TraceConfig_CompressionType_MAX = TraceConfig_CompressionType::COMPRESSION_TYPE_DEFLATE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TraceConfig_CompressionType_Name(::perfetto::protos::pbzero::TraceConfig_CompressionType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TraceConfig_CompressionType::COMPRESSION_TYPE_UNSPECIFIED:
+ return "COMPRESSION_TYPE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TraceConfig_CompressionType::COMPRESSION_TYPE_DEFLATE:
+ return "COMPRESSION_TYPE_DEFLATE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TraceConfig {
+enum StatsdLogging : int32_t {
+ STATSD_LOGGING_UNSPECIFIED = 0,
+ STATSD_LOGGING_ENABLED = 1,
+ STATSD_LOGGING_DISABLED = 2,
+};
+} // namespace perfetto_pbzero_enum_TraceConfig
+using TraceConfig_StatsdLogging = perfetto_pbzero_enum_TraceConfig::StatsdLogging;
+
+
+constexpr TraceConfig_StatsdLogging TraceConfig_StatsdLogging_MIN = TraceConfig_StatsdLogging::STATSD_LOGGING_UNSPECIFIED;
+constexpr TraceConfig_StatsdLogging TraceConfig_StatsdLogging_MAX = TraceConfig_StatsdLogging::STATSD_LOGGING_DISABLED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TraceConfig_StatsdLogging_Name(::perfetto::protos::pbzero::TraceConfig_StatsdLogging value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TraceConfig_StatsdLogging::STATSD_LOGGING_UNSPECIFIED:
+ return "STATSD_LOGGING_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TraceConfig_StatsdLogging::STATSD_LOGGING_ENABLED:
+ return "STATSD_LOGGING_ENABLED";
+
+ case ::perfetto::protos::pbzero::TraceConfig_StatsdLogging::STATSD_LOGGING_DISABLED:
+ return "STATSD_LOGGING_DISABLED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TraceConfig_TraceFilter {
+enum StringFilterPolicy : int32_t {
+ SFP_UNSPECIFIED = 0,
+ SFP_MATCH_REDACT_GROUPS = 1,
+ SFP_ATRACE_MATCH_REDACT_GROUPS = 2,
+ SFP_MATCH_BREAK = 3,
+ SFP_ATRACE_MATCH_BREAK = 4,
+ SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS = 5,
+};
+} // namespace perfetto_pbzero_enum_TraceConfig_TraceFilter
+using TraceConfig_TraceFilter_StringFilterPolicy = perfetto_pbzero_enum_TraceConfig_TraceFilter::StringFilterPolicy;
+
+
+constexpr TraceConfig_TraceFilter_StringFilterPolicy TraceConfig_TraceFilter_StringFilterPolicy_MIN = TraceConfig_TraceFilter_StringFilterPolicy::SFP_UNSPECIFIED;
+constexpr TraceConfig_TraceFilter_StringFilterPolicy TraceConfig_TraceFilter_StringFilterPolicy_MAX = TraceConfig_TraceFilter_StringFilterPolicy::SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TraceConfig_TraceFilter_StringFilterPolicy_Name(::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy::SFP_UNSPECIFIED:
+ return "SFP_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy::SFP_MATCH_REDACT_GROUPS:
+ return "SFP_MATCH_REDACT_GROUPS";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy::SFP_ATRACE_MATCH_REDACT_GROUPS:
+ return "SFP_ATRACE_MATCH_REDACT_GROUPS";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy::SFP_MATCH_BREAK:
+ return "SFP_MATCH_BREAK";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy::SFP_ATRACE_MATCH_BREAK:
+ return "SFP_ATRACE_MATCH_BREAK";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy::SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS:
+ return "SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TraceConfig_TriggerConfig {
+enum TriggerMode : int32_t {
+ UNSPECIFIED = 0,
+ START_TRACING = 1,
+ STOP_TRACING = 2,
+ CLONE_SNAPSHOT = 4,
+};
+} // namespace perfetto_pbzero_enum_TraceConfig_TriggerConfig
+using TraceConfig_TriggerConfig_TriggerMode = perfetto_pbzero_enum_TraceConfig_TriggerConfig::TriggerMode;
+
+
+constexpr TraceConfig_TriggerConfig_TriggerMode TraceConfig_TriggerConfig_TriggerMode_MIN = TraceConfig_TriggerConfig_TriggerMode::UNSPECIFIED;
+constexpr TraceConfig_TriggerConfig_TriggerMode TraceConfig_TriggerConfig_TriggerMode_MAX = TraceConfig_TriggerConfig_TriggerMode::CLONE_SNAPSHOT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TraceConfig_TriggerConfig_TriggerMode_Name(::perfetto::protos::pbzero::TraceConfig_TriggerConfig_TriggerMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TraceConfig_TriggerConfig_TriggerMode::UNSPECIFIED:
+ return "UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TriggerConfig_TriggerMode::START_TRACING:
+ return "START_TRACING";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TriggerConfig_TriggerMode::STOP_TRACING:
+ return "STOP_TRACING";
+
+ case ::perfetto::protos::pbzero::TraceConfig_TriggerConfig_TriggerMode::CLONE_SNAPSHOT:
+ return "CLONE_SNAPSHOT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TraceConfig_BufferConfig {
+enum FillPolicy : int32_t {
+ UNSPECIFIED = 0,
+ RING_BUFFER = 1,
+ DISCARD = 2,
+};
+} // namespace perfetto_pbzero_enum_TraceConfig_BufferConfig
+using TraceConfig_BufferConfig_FillPolicy = perfetto_pbzero_enum_TraceConfig_BufferConfig::FillPolicy;
+
+
+constexpr TraceConfig_BufferConfig_FillPolicy TraceConfig_BufferConfig_FillPolicy_MIN = TraceConfig_BufferConfig_FillPolicy::UNSPECIFIED;
+constexpr TraceConfig_BufferConfig_FillPolicy TraceConfig_BufferConfig_FillPolicy_MAX = TraceConfig_BufferConfig_FillPolicy::DISCARD;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TraceConfig_BufferConfig_FillPolicy_Name(::perfetto::protos::pbzero::TraceConfig_BufferConfig_FillPolicy value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TraceConfig_BufferConfig_FillPolicy::UNSPECIFIED:
+ return "UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TraceConfig_BufferConfig_FillPolicy::RING_BUFFER:
+ return "RING_BUFFER";
+
+ case ::perfetto::protos::pbzero::TraceConfig_BufferConfig_FillPolicy::DISCARD:
+ return "DISCARD";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class TraceConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/38, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TraceConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buffers() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> buffers() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_data_sources() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> data_sources() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_builtin_data_sources() const { return at<20>().valid(); }
+ ::protozero::ConstBytes builtin_data_sources() const { return at<20>().as_bytes(); }
+ bool has_duration_ms() const { return at<3>().valid(); }
+ uint32_t duration_ms() const { return at<3>().as_uint32(); }
+ bool has_prefer_suspend_clock_for_duration() const { return at<36>().valid(); }
+ bool prefer_suspend_clock_for_duration() const { return at<36>().as_bool(); }
+ bool has_enable_extra_guardrails() const { return at<4>().valid(); }
+ bool enable_extra_guardrails() const { return at<4>().as_bool(); }
+ bool has_lockdown_mode() const { return at<5>().valid(); }
+ int32_t lockdown_mode() const { return at<5>().as_int32(); }
+ bool has_producers() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> producers() const { return GetRepeated<::protozero::ConstBytes>(6); }
+ bool has_statsd_metadata() const { return at<7>().valid(); }
+ ::protozero::ConstBytes statsd_metadata() const { return at<7>().as_bytes(); }
+ bool has_write_into_file() const { return at<8>().valid(); }
+ bool write_into_file() const { return at<8>().as_bool(); }
+ bool has_output_path() const { return at<29>().valid(); }
+ ::protozero::ConstChars output_path() const { return at<29>().as_string(); }
+ bool has_file_write_period_ms() const { return at<9>().valid(); }
+ uint32_t file_write_period_ms() const { return at<9>().as_uint32(); }
+ bool has_max_file_size_bytes() const { return at<10>().valid(); }
+ uint64_t max_file_size_bytes() const { return at<10>().as_uint64(); }
+ bool has_guardrail_overrides() const { return at<11>().valid(); }
+ ::protozero::ConstBytes guardrail_overrides() const { return at<11>().as_bytes(); }
+ bool has_deferred_start() const { return at<12>().valid(); }
+ bool deferred_start() const { return at<12>().as_bool(); }
+ bool has_flush_period_ms() const { return at<13>().valid(); }
+ uint32_t flush_period_ms() const { return at<13>().as_uint32(); }
+ bool has_flush_timeout_ms() const { return at<14>().valid(); }
+ uint32_t flush_timeout_ms() const { return at<14>().as_uint32(); }
+ bool has_data_source_stop_timeout_ms() const { return at<23>().valid(); }
+ uint32_t data_source_stop_timeout_ms() const { return at<23>().as_uint32(); }
+ bool has_notify_traceur() const { return at<16>().valid(); }
+ bool notify_traceur() const { return at<16>().as_bool(); }
+ bool has_bugreport_score() const { return at<30>().valid(); }
+ int32_t bugreport_score() const { return at<30>().as_int32(); }
+ bool has_bugreport_filename() const { return at<38>().valid(); }
+ ::protozero::ConstChars bugreport_filename() const { return at<38>().as_string(); }
+ bool has_trigger_config() const { return at<17>().valid(); }
+ ::protozero::ConstBytes trigger_config() const { return at<17>().as_bytes(); }
+ bool has_activate_triggers() const { return at<18>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> activate_triggers() const { return GetRepeated<::protozero::ConstChars>(18); }
+ bool has_incremental_state_config() const { return at<21>().valid(); }
+ ::protozero::ConstBytes incremental_state_config() const { return at<21>().as_bytes(); }
+ bool has_allow_user_build_tracing() const { return at<19>().valid(); }
+ bool allow_user_build_tracing() const { return at<19>().as_bool(); }
+ bool has_unique_session_name() const { return at<22>().valid(); }
+ ::protozero::ConstChars unique_session_name() const { return at<22>().as_string(); }
+ bool has_compression_type() const { return at<24>().valid(); }
+ int32_t compression_type() const { return at<24>().as_int32(); }
+ bool has_incident_report_config() const { return at<25>().valid(); }
+ ::protozero::ConstBytes incident_report_config() const { return at<25>().as_bytes(); }
+ bool has_statsd_logging() const { return at<31>().valid(); }
+ int32_t statsd_logging() const { return at<31>().as_int32(); }
+ bool has_trace_uuid_msb() const { return at<27>().valid(); }
+ int64_t trace_uuid_msb() const { return at<27>().as_int64(); }
+ bool has_trace_uuid_lsb() const { return at<28>().valid(); }
+ int64_t trace_uuid_lsb() const { return at<28>().as_int64(); }
+ bool has_trace_filter() const { return at<33>().valid(); }
+ ::protozero::ConstBytes trace_filter() const { return at<33>().as_bytes(); }
+ bool has_android_report_config() const { return at<34>().valid(); }
+ ::protozero::ConstBytes android_report_config() const { return at<34>().as_bytes(); }
+ bool has_cmd_trace_start_delay() const { return at<35>().valid(); }
+ ::protozero::ConstBytes cmd_trace_start_delay() const { return at<35>().as_bytes(); }
+};
+
+class TraceConfig : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_Decoder;
+ enum : int32_t {
+ kBuffersFieldNumber = 1,
+ kDataSourcesFieldNumber = 2,
+ kBuiltinDataSourcesFieldNumber = 20,
+ kDurationMsFieldNumber = 3,
+ kPreferSuspendClockForDurationFieldNumber = 36,
+ kEnableExtraGuardrailsFieldNumber = 4,
+ kLockdownModeFieldNumber = 5,
+ kProducersFieldNumber = 6,
+ kStatsdMetadataFieldNumber = 7,
+ kWriteIntoFileFieldNumber = 8,
+ kOutputPathFieldNumber = 29,
+ kFileWritePeriodMsFieldNumber = 9,
+ kMaxFileSizeBytesFieldNumber = 10,
+ kGuardrailOverridesFieldNumber = 11,
+ kDeferredStartFieldNumber = 12,
+ kFlushPeriodMsFieldNumber = 13,
+ kFlushTimeoutMsFieldNumber = 14,
+ kDataSourceStopTimeoutMsFieldNumber = 23,
+ kNotifyTraceurFieldNumber = 16,
+ kBugreportScoreFieldNumber = 30,
+ kBugreportFilenameFieldNumber = 38,
+ kTriggerConfigFieldNumber = 17,
+ kActivateTriggersFieldNumber = 18,
+ kIncrementalStateConfigFieldNumber = 21,
+ kAllowUserBuildTracingFieldNumber = 19,
+ kUniqueSessionNameFieldNumber = 22,
+ kCompressionTypeFieldNumber = 24,
+ kIncidentReportConfigFieldNumber = 25,
+ kStatsdLoggingFieldNumber = 31,
+ kTraceUuidMsbFieldNumber = 27,
+ kTraceUuidLsbFieldNumber = 28,
+ kTraceFilterFieldNumber = 33,
+ kAndroidReportConfigFieldNumber = 34,
+ kCmdTraceStartDelayFieldNumber = 35,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig"; }
+
+ using BufferConfig = ::perfetto::protos::pbzero::TraceConfig_BufferConfig;
+ using DataSource = ::perfetto::protos::pbzero::TraceConfig_DataSource;
+ using BuiltinDataSource = ::perfetto::protos::pbzero::TraceConfig_BuiltinDataSource;
+ using ProducerConfig = ::perfetto::protos::pbzero::TraceConfig_ProducerConfig;
+ using StatsdMetadata = ::perfetto::protos::pbzero::TraceConfig_StatsdMetadata;
+ using GuardrailOverrides = ::perfetto::protos::pbzero::TraceConfig_GuardrailOverrides;
+ using TriggerConfig = ::perfetto::protos::pbzero::TraceConfig_TriggerConfig;
+ using IncrementalStateConfig = ::perfetto::protos::pbzero::TraceConfig_IncrementalStateConfig;
+ using IncidentReportConfig = ::perfetto::protos::pbzero::TraceConfig_IncidentReportConfig;
+ using TraceFilter = ::perfetto::protos::pbzero::TraceConfig_TraceFilter;
+ using AndroidReportConfig = ::perfetto::protos::pbzero::TraceConfig_AndroidReportConfig;
+ using CmdTraceStartDelay = ::perfetto::protos::pbzero::TraceConfig_CmdTraceStartDelay;
+
+ using LockdownModeOperation = ::perfetto::protos::pbzero::TraceConfig_LockdownModeOperation;
+ static inline const char* LockdownModeOperation_Name(LockdownModeOperation value) {
+ return ::perfetto::protos::pbzero::TraceConfig_LockdownModeOperation_Name(value);
+ }
+
+ using CompressionType = ::perfetto::protos::pbzero::TraceConfig_CompressionType;
+ static inline const char* CompressionType_Name(CompressionType value) {
+ return ::perfetto::protos::pbzero::TraceConfig_CompressionType_Name(value);
+ }
+
+ using StatsdLogging = ::perfetto::protos::pbzero::TraceConfig_StatsdLogging;
+ static inline const char* StatsdLogging_Name(StatsdLogging value) {
+ return ::perfetto::protos::pbzero::TraceConfig_StatsdLogging_Name(value);
+ }
+ static inline const LockdownModeOperation LOCKDOWN_UNCHANGED = LockdownModeOperation::LOCKDOWN_UNCHANGED;
+ static inline const LockdownModeOperation LOCKDOWN_CLEAR = LockdownModeOperation::LOCKDOWN_CLEAR;
+ static inline const LockdownModeOperation LOCKDOWN_SET = LockdownModeOperation::LOCKDOWN_SET;
+ static inline const CompressionType COMPRESSION_TYPE_UNSPECIFIED = CompressionType::COMPRESSION_TYPE_UNSPECIFIED;
+ static inline const CompressionType COMPRESSION_TYPE_DEFLATE = CompressionType::COMPRESSION_TYPE_DEFLATE;
+ static inline const StatsdLogging STATSD_LOGGING_UNSPECIFIED = StatsdLogging::STATSD_LOGGING_UNSPECIFIED;
+ static inline const StatsdLogging STATSD_LOGGING_ENABLED = StatsdLogging::STATSD_LOGGING_ENABLED;
+ static inline const StatsdLogging STATSD_LOGGING_DISABLED = StatsdLogging::STATSD_LOGGING_DISABLED;
+
+ using FieldMetadata_Buffers =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_BufferConfig,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_Buffers kBuffers{};
+ template <typename T = TraceConfig_BufferConfig> T* add_buffers() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_DataSources =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_DataSource,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_DataSources kDataSources{};
+ template <typename T = TraceConfig_DataSource> T* add_data_sources() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_BuiltinDataSources =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_BuiltinDataSource,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_BuiltinDataSources kBuiltinDataSources{};
+ template <typename T = TraceConfig_BuiltinDataSource> T* set_builtin_data_sources() {
+ return BeginNestedMessage<T>(20);
+ }
+
+
+ using FieldMetadata_DurationMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_DurationMs kDurationMs{};
+ void set_duration_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DurationMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreferSuspendClockForDuration =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_PreferSuspendClockForDuration kPreferSuspendClockForDuration{};
+ void set_prefer_suspend_clock_for_duration(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreferSuspendClockForDuration::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnableExtraGuardrails =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_EnableExtraGuardrails kEnableExtraGuardrails{};
+ void set_enable_extra_guardrails(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnableExtraGuardrails::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LockdownMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TraceConfig_LockdownModeOperation,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_LockdownMode kLockdownMode{};
+ void set_lockdown_mode(TraceConfig_LockdownModeOperation value) {
+ static constexpr uint32_t field_id = FieldMetadata_LockdownMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Producers =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_ProducerConfig,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_Producers kProducers{};
+ template <typename T = TraceConfig_ProducerConfig> T* add_producers() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_StatsdMetadata =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_StatsdMetadata,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_StatsdMetadata kStatsdMetadata{};
+ template <typename T = TraceConfig_StatsdMetadata> T* set_statsd_metadata() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_WriteIntoFile =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_WriteIntoFile kWriteIntoFile{};
+ void set_write_into_file(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_WriteIntoFile::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OutputPath =
+ ::protozero::proto_utils::FieldMetadata<
+ 29,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_OutputPath kOutputPath{};
+ void set_output_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_OutputPath::kFieldId, data, size);
+ }
+ void set_output_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_OutputPath::kFieldId, chars.data, chars.size);
+ }
+ void set_output_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_OutputPath::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FileWritePeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_FileWritePeriodMs kFileWritePeriodMs{};
+ void set_file_write_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FileWritePeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxFileSizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_MaxFileSizeBytes kMaxFileSizeBytes{};
+ void set_max_file_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxFileSizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GuardrailOverrides =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_GuardrailOverrides,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_GuardrailOverrides kGuardrailOverrides{};
+ template <typename T = TraceConfig_GuardrailOverrides> T* set_guardrail_overrides() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_DeferredStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_DeferredStart kDeferredStart{};
+ void set_deferred_start(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeferredStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlushPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_FlushPeriodMs kFlushPeriodMs{};
+ void set_flush_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlushTimeoutMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_FlushTimeoutMs kFlushTimeoutMs{};
+ void set_flush_timeout_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushTimeoutMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSourceStopTimeoutMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_DataSourceStopTimeoutMs kDataSourceStopTimeoutMs{};
+ void set_data_source_stop_timeout_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSourceStopTimeoutMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NotifyTraceur =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_NotifyTraceur kNotifyTraceur{};
+ void set_notify_traceur(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NotifyTraceur::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BugreportScore =
+ ::protozero::proto_utils::FieldMetadata<
+ 30,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_BugreportScore kBugreportScore{};
+ void set_bugreport_score(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BugreportScore::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BugreportFilename =
+ ::protozero::proto_utils::FieldMetadata<
+ 38,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_BugreportFilename kBugreportFilename{};
+ void set_bugreport_filename(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_BugreportFilename::kFieldId, data, size);
+ }
+ void set_bugreport_filename(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_BugreportFilename::kFieldId, chars.data, chars.size);
+ }
+ void set_bugreport_filename(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_BugreportFilename::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TriggerConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_TriggerConfig,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_TriggerConfig kTriggerConfig{};
+ template <typename T = TraceConfig_TriggerConfig> T* set_trigger_config() {
+ return BeginNestedMessage<T>(17);
+ }
+
+
+ using FieldMetadata_ActivateTriggers =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_ActivateTriggers kActivateTriggers{};
+ void add_activate_triggers(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ActivateTriggers::kFieldId, data, size);
+ }
+ void add_activate_triggers(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ActivateTriggers::kFieldId, chars.data, chars.size);
+ }
+ void add_activate_triggers(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActivateTriggers::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IncrementalStateConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_IncrementalStateConfig,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_IncrementalStateConfig kIncrementalStateConfig{};
+ template <typename T = TraceConfig_IncrementalStateConfig> T* set_incremental_state_config() {
+ return BeginNestedMessage<T>(21);
+ }
+
+
+ using FieldMetadata_AllowUserBuildTracing =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_AllowUserBuildTracing kAllowUserBuildTracing{};
+ void set_allow_user_build_tracing(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllowUserBuildTracing::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UniqueSessionName =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_UniqueSessionName kUniqueSessionName{};
+ void set_unique_session_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_UniqueSessionName::kFieldId, data, size);
+ }
+ void set_unique_session_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_UniqueSessionName::kFieldId, chars.data, chars.size);
+ }
+ void set_unique_session_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_UniqueSessionName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CompressionType =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TraceConfig_CompressionType,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_CompressionType kCompressionType{};
+ void set_compression_type(TraceConfig_CompressionType value) {
+ static constexpr uint32_t field_id = FieldMetadata_CompressionType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IncidentReportConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_IncidentReportConfig,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_IncidentReportConfig kIncidentReportConfig{};
+ template <typename T = TraceConfig_IncidentReportConfig> T* set_incident_report_config() {
+ return BeginNestedMessage<T>(25);
+ }
+
+
+ using FieldMetadata_StatsdLogging =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TraceConfig_StatsdLogging,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_StatsdLogging kStatsdLogging{};
+ void set_statsd_logging(TraceConfig_StatsdLogging value) {
+ static constexpr uint32_t field_id = FieldMetadata_StatsdLogging::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceUuidMsb =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_TraceUuidMsb kTraceUuidMsb{};
+ void set_trace_uuid_msb(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceUuidMsb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceUuidLsb =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_TraceUuidLsb kTraceUuidLsb{};
+ void set_trace_uuid_lsb(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceUuidLsb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_TraceFilter,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_TraceFilter kTraceFilter{};
+ template <typename T = TraceConfig_TraceFilter> T* set_trace_filter() {
+ return BeginNestedMessage<T>(33);
+ }
+
+
+ using FieldMetadata_AndroidReportConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_AndroidReportConfig,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_AndroidReportConfig kAndroidReportConfig{};
+ template <typename T = TraceConfig_AndroidReportConfig> T* set_android_report_config() {
+ return BeginNestedMessage<T>(34);
+ }
+
+
+ using FieldMetadata_CmdTraceStartDelay =
+ ::protozero::proto_utils::FieldMetadata<
+ 35,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_CmdTraceStartDelay,
+ TraceConfig>;
+
+ static constexpr FieldMetadata_CmdTraceStartDelay kCmdTraceStartDelay{};
+ template <typename T = TraceConfig_CmdTraceStartDelay> T* set_cmd_trace_start_delay() {
+ return BeginNestedMessage<T>(35);
+ }
+
+};
+
+class TraceConfig_CmdTraceStartDelay_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_CmdTraceStartDelay_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_CmdTraceStartDelay_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_CmdTraceStartDelay_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_min_delay_ms() const { return at<1>().valid(); }
+ uint32_t min_delay_ms() const { return at<1>().as_uint32(); }
+ bool has_max_delay_ms() const { return at<2>().valid(); }
+ uint32_t max_delay_ms() const { return at<2>().as_uint32(); }
+};
+
+class TraceConfig_CmdTraceStartDelay : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_CmdTraceStartDelay_Decoder;
+ enum : int32_t {
+ kMinDelayMsFieldNumber = 1,
+ kMaxDelayMsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.CmdTraceStartDelay"; }
+
+
+ using FieldMetadata_MinDelayMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_CmdTraceStartDelay>;
+
+ static constexpr FieldMetadata_MinDelayMs kMinDelayMs{};
+ void set_min_delay_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MinDelayMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxDelayMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_CmdTraceStartDelay>;
+
+ static constexpr FieldMetadata_MaxDelayMs kMaxDelayMs{};
+ void set_max_delay_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxDelayMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_AndroidReportConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_AndroidReportConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_AndroidReportConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_AndroidReportConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_reporter_service_package() const { return at<1>().valid(); }
+ ::protozero::ConstChars reporter_service_package() const { return at<1>().as_string(); }
+ bool has_reporter_service_class() const { return at<2>().valid(); }
+ ::protozero::ConstChars reporter_service_class() const { return at<2>().as_string(); }
+ bool has_skip_report() const { return at<3>().valid(); }
+ bool skip_report() const { return at<3>().as_bool(); }
+ bool has_use_pipe_in_framework_for_testing() const { return at<4>().valid(); }
+ bool use_pipe_in_framework_for_testing() const { return at<4>().as_bool(); }
+};
+
+class TraceConfig_AndroidReportConfig : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_AndroidReportConfig_Decoder;
+ enum : int32_t {
+ kReporterServicePackageFieldNumber = 1,
+ kReporterServiceClassFieldNumber = 2,
+ kSkipReportFieldNumber = 3,
+ kUsePipeInFrameworkForTestingFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.AndroidReportConfig"; }
+
+
+ using FieldMetadata_ReporterServicePackage =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_AndroidReportConfig>;
+
+ static constexpr FieldMetadata_ReporterServicePackage kReporterServicePackage{};
+ void set_reporter_service_package(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ReporterServicePackage::kFieldId, data, size);
+ }
+ void set_reporter_service_package(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ReporterServicePackage::kFieldId, chars.data, chars.size);
+ }
+ void set_reporter_service_package(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReporterServicePackage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReporterServiceClass =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_AndroidReportConfig>;
+
+ static constexpr FieldMetadata_ReporterServiceClass kReporterServiceClass{};
+ void set_reporter_service_class(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ReporterServiceClass::kFieldId, data, size);
+ }
+ void set_reporter_service_class(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ReporterServiceClass::kFieldId, chars.data, chars.size);
+ }
+ void set_reporter_service_class(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReporterServiceClass::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkipReport =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_AndroidReportConfig>;
+
+ static constexpr FieldMetadata_SkipReport kSkipReport{};
+ void set_skip_report(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkipReport::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UsePipeInFrameworkForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_AndroidReportConfig>;
+
+ static constexpr FieldMetadata_UsePipeInFrameworkForTesting kUsePipeInFrameworkForTesting{};
+ void set_use_pipe_in_framework_for_testing(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_UsePipeInFrameworkForTesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_TraceFilter_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_TraceFilter_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_TraceFilter_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_TraceFilter_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytecode() const { return at<1>().valid(); }
+ ::protozero::ConstBytes bytecode() const { return at<1>().as_bytes(); }
+ bool has_bytecode_v2() const { return at<2>().valid(); }
+ ::protozero::ConstBytes bytecode_v2() const { return at<2>().as_bytes(); }
+ bool has_string_filter_chain() const { return at<3>().valid(); }
+ ::protozero::ConstBytes string_filter_chain() const { return at<3>().as_bytes(); }
+};
+
+class TraceConfig_TraceFilter : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_TraceFilter_Decoder;
+ enum : int32_t {
+ kBytecodeFieldNumber = 1,
+ kBytecodeV2FieldNumber = 2,
+ kStringFilterChainFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.TraceFilter"; }
+
+ using StringFilterRule = ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterRule;
+ using StringFilterChain = ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterChain;
+
+ using StringFilterPolicy = ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy;
+ static inline const char* StringFilterPolicy_Name(StringFilterPolicy value) {
+ return ::perfetto::protos::pbzero::TraceConfig_TraceFilter_StringFilterPolicy_Name(value);
+ }
+ static inline const StringFilterPolicy SFP_UNSPECIFIED = StringFilterPolicy::SFP_UNSPECIFIED;
+ static inline const StringFilterPolicy SFP_MATCH_REDACT_GROUPS = StringFilterPolicy::SFP_MATCH_REDACT_GROUPS;
+ static inline const StringFilterPolicy SFP_ATRACE_MATCH_REDACT_GROUPS = StringFilterPolicy::SFP_ATRACE_MATCH_REDACT_GROUPS;
+ static inline const StringFilterPolicy SFP_MATCH_BREAK = StringFilterPolicy::SFP_MATCH_BREAK;
+ static inline const StringFilterPolicy SFP_ATRACE_MATCH_BREAK = StringFilterPolicy::SFP_ATRACE_MATCH_BREAK;
+ static inline const StringFilterPolicy SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS = StringFilterPolicy::SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS;
+
+ using FieldMetadata_Bytecode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ TraceConfig_TraceFilter>;
+
+ static constexpr FieldMetadata_Bytecode kBytecode{};
+ void set_bytecode(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Bytecode::kFieldId, data, size);
+ }
+ void set_bytecode(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Bytecode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_bytecode(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytecode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytecodeV2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ TraceConfig_TraceFilter>;
+
+ static constexpr FieldMetadata_BytecodeV2 kBytecodeV2{};
+ void set_bytecode_v2(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_BytecodeV2::kFieldId, data, size);
+ }
+ void set_bytecode_v2(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_BytecodeV2::kFieldId, bytes.data, bytes.size);
+ }
+ void set_bytecode_v2(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytecodeV2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringFilterChain =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_TraceFilter_StringFilterChain,
+ TraceConfig_TraceFilter>;
+
+ static constexpr FieldMetadata_StringFilterChain kStringFilterChain{};
+ template <typename T = TraceConfig_TraceFilter_StringFilterChain> T* set_string_filter_chain() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class TraceConfig_TraceFilter_StringFilterChain_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TraceConfig_TraceFilter_StringFilterChain_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_TraceFilter_StringFilterChain_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_TraceFilter_StringFilterChain_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_rules() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> rules() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class TraceConfig_TraceFilter_StringFilterChain : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_TraceFilter_StringFilterChain_Decoder;
+ enum : int32_t {
+ kRulesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.TraceFilter.StringFilterChain"; }
+
+
+ using FieldMetadata_Rules =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_TraceFilter_StringFilterRule,
+ TraceConfig_TraceFilter_StringFilterChain>;
+
+ static constexpr FieldMetadata_Rules kRules{};
+ template <typename T = TraceConfig_TraceFilter_StringFilterRule> T* add_rules() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class TraceConfig_TraceFilter_StringFilterRule_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_TraceFilter_StringFilterRule_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_TraceFilter_StringFilterRule_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_TraceFilter_StringFilterRule_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_policy() const { return at<1>().valid(); }
+ int32_t policy() const { return at<1>().as_int32(); }
+ bool has_regex_pattern() const { return at<2>().valid(); }
+ ::protozero::ConstChars regex_pattern() const { return at<2>().as_string(); }
+ bool has_atrace_payload_starts_with() const { return at<3>().valid(); }
+ ::protozero::ConstChars atrace_payload_starts_with() const { return at<3>().as_string(); }
+};
+
+class TraceConfig_TraceFilter_StringFilterRule : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_TraceFilter_StringFilterRule_Decoder;
+ enum : int32_t {
+ kPolicyFieldNumber = 1,
+ kRegexPatternFieldNumber = 2,
+ kAtracePayloadStartsWithFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.TraceFilter.StringFilterRule"; }
+
+
+ using FieldMetadata_Policy =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TraceConfig_TraceFilter_StringFilterPolicy,
+ TraceConfig_TraceFilter_StringFilterRule>;
+
+ static constexpr FieldMetadata_Policy kPolicy{};
+ void set_policy(TraceConfig_TraceFilter_StringFilterPolicy value) {
+ static constexpr uint32_t field_id = FieldMetadata_Policy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RegexPattern =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_TraceFilter_StringFilterRule>;
+
+ static constexpr FieldMetadata_RegexPattern kRegexPattern{};
+ void set_regex_pattern(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_RegexPattern::kFieldId, data, size);
+ }
+ void set_regex_pattern(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_RegexPattern::kFieldId, chars.data, chars.size);
+ }
+ void set_regex_pattern(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_RegexPattern::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AtracePayloadStartsWith =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_TraceFilter_StringFilterRule>;
+
+ static constexpr FieldMetadata_AtracePayloadStartsWith kAtracePayloadStartsWith{};
+ void set_atrace_payload_starts_with(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_AtracePayloadStartsWith::kFieldId, data, size);
+ }
+ void set_atrace_payload_starts_with(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_AtracePayloadStartsWith::kFieldId, chars.data, chars.size);
+ }
+ void set_atrace_payload_starts_with(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_AtracePayloadStartsWith::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_IncidentReportConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_IncidentReportConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_IncidentReportConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_IncidentReportConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_destination_package() const { return at<1>().valid(); }
+ ::protozero::ConstChars destination_package() const { return at<1>().as_string(); }
+ bool has_destination_class() const { return at<2>().valid(); }
+ ::protozero::ConstChars destination_class() const { return at<2>().as_string(); }
+ bool has_privacy_level() const { return at<3>().valid(); }
+ int32_t privacy_level() const { return at<3>().as_int32(); }
+ bool has_skip_incidentd() const { return at<5>().valid(); }
+ bool skip_incidentd() const { return at<5>().as_bool(); }
+ bool has_skip_dropbox() const { return at<4>().valid(); }
+ bool skip_dropbox() const { return at<4>().as_bool(); }
+};
+
+class TraceConfig_IncidentReportConfig : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_IncidentReportConfig_Decoder;
+ enum : int32_t {
+ kDestinationPackageFieldNumber = 1,
+ kDestinationClassFieldNumber = 2,
+ kPrivacyLevelFieldNumber = 3,
+ kSkipIncidentdFieldNumber = 5,
+ kSkipDropboxFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.IncidentReportConfig"; }
+
+
+ using FieldMetadata_DestinationPackage =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_IncidentReportConfig>;
+
+ static constexpr FieldMetadata_DestinationPackage kDestinationPackage{};
+ void set_destination_package(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DestinationPackage::kFieldId, data, size);
+ }
+ void set_destination_package(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DestinationPackage::kFieldId, chars.data, chars.size);
+ }
+ void set_destination_package(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DestinationPackage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DestinationClass =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_IncidentReportConfig>;
+
+ static constexpr FieldMetadata_DestinationClass kDestinationClass{};
+ void set_destination_class(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DestinationClass::kFieldId, data, size);
+ }
+ void set_destination_class(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DestinationClass::kFieldId, chars.data, chars.size);
+ }
+ void set_destination_class(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DestinationClass::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrivacyLevel =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TraceConfig_IncidentReportConfig>;
+
+ static constexpr FieldMetadata_PrivacyLevel kPrivacyLevel{};
+ void set_privacy_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrivacyLevel::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkipIncidentd =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_IncidentReportConfig>;
+
+ static constexpr FieldMetadata_SkipIncidentd kSkipIncidentd{};
+ void set_skip_incidentd(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkipIncidentd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkipDropbox =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_IncidentReportConfig>;
+
+ static constexpr FieldMetadata_SkipDropbox kSkipDropbox{};
+ void set_skip_dropbox(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkipDropbox::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_IncrementalStateConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_IncrementalStateConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_IncrementalStateConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_IncrementalStateConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_clear_period_ms() const { return at<1>().valid(); }
+ uint32_t clear_period_ms() const { return at<1>().as_uint32(); }
+};
+
+class TraceConfig_IncrementalStateConfig : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_IncrementalStateConfig_Decoder;
+ enum : int32_t {
+ kClearPeriodMsFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.IncrementalStateConfig"; }
+
+
+ using FieldMetadata_ClearPeriodMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_IncrementalStateConfig>;
+
+ static constexpr FieldMetadata_ClearPeriodMs kClearPeriodMs{};
+ void set_clear_period_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClearPeriodMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_TriggerConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TraceConfig_TriggerConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_TriggerConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_TriggerConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trigger_mode() const { return at<1>().valid(); }
+ int32_t trigger_mode() const { return at<1>().as_int32(); }
+ bool has_use_clone_snapshot_if_available() const { return at<5>().valid(); }
+ bool use_clone_snapshot_if_available() const { return at<5>().as_bool(); }
+ bool has_triggers() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> triggers() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_trigger_timeout_ms() const { return at<3>().valid(); }
+ uint32_t trigger_timeout_ms() const { return at<3>().as_uint32(); }
+};
+
+class TraceConfig_TriggerConfig : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_TriggerConfig_Decoder;
+ enum : int32_t {
+ kTriggerModeFieldNumber = 1,
+ kUseCloneSnapshotIfAvailableFieldNumber = 5,
+ kTriggersFieldNumber = 2,
+ kTriggerTimeoutMsFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.TriggerConfig"; }
+
+ using Trigger = ::perfetto::protos::pbzero::TraceConfig_TriggerConfig_Trigger;
+
+ using TriggerMode = ::perfetto::protos::pbzero::TraceConfig_TriggerConfig_TriggerMode;
+ static inline const char* TriggerMode_Name(TriggerMode value) {
+ return ::perfetto::protos::pbzero::TraceConfig_TriggerConfig_TriggerMode_Name(value);
+ }
+ static inline const TriggerMode UNSPECIFIED = TriggerMode::UNSPECIFIED;
+ static inline const TriggerMode START_TRACING = TriggerMode::START_TRACING;
+ static inline const TriggerMode STOP_TRACING = TriggerMode::STOP_TRACING;
+ static inline const TriggerMode CLONE_SNAPSHOT = TriggerMode::CLONE_SNAPSHOT;
+
+ using FieldMetadata_TriggerMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TraceConfig_TriggerConfig_TriggerMode,
+ TraceConfig_TriggerConfig>;
+
+ static constexpr FieldMetadata_TriggerMode kTriggerMode{};
+ void set_trigger_mode(TraceConfig_TriggerConfig_TriggerMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggerMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UseCloneSnapshotIfAvailable =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_TriggerConfig>;
+
+ static constexpr FieldMetadata_UseCloneSnapshotIfAvailable kUseCloneSnapshotIfAvailable{};
+ void set_use_clone_snapshot_if_available(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_UseCloneSnapshotIfAvailable::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Triggers =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TraceConfig_TriggerConfig_Trigger,
+ TraceConfig_TriggerConfig>;
+
+ static constexpr FieldMetadata_Triggers kTriggers{};
+ template <typename T = TraceConfig_TriggerConfig_Trigger> T* add_triggers() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_TriggerTimeoutMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_TriggerConfig>;
+
+ static constexpr FieldMetadata_TriggerTimeoutMs kTriggerTimeoutMs{};
+ void set_trigger_timeout_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggerTimeoutMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_TriggerConfig_Trigger_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_TriggerConfig_Trigger_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_TriggerConfig_Trigger_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_TriggerConfig_Trigger_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_producer_name_regex() const { return at<2>().valid(); }
+ ::protozero::ConstChars producer_name_regex() const { return at<2>().as_string(); }
+ bool has_stop_delay_ms() const { return at<3>().valid(); }
+ uint32_t stop_delay_ms() const { return at<3>().as_uint32(); }
+ bool has_max_per_24_h() const { return at<4>().valid(); }
+ uint32_t max_per_24_h() const { return at<4>().as_uint32(); }
+ bool has_skip_probability() const { return at<5>().valid(); }
+ double skip_probability() const { return at<5>().as_double(); }
+};
+
+class TraceConfig_TriggerConfig_Trigger : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_TriggerConfig_Trigger_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kProducerNameRegexFieldNumber = 2,
+ kStopDelayMsFieldNumber = 3,
+ kMaxPer24HFieldNumber = 4,
+ kSkipProbabilityFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.TriggerConfig.Trigger"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_TriggerConfig_Trigger>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProducerNameRegex =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_TriggerConfig_Trigger>;
+
+ static constexpr FieldMetadata_ProducerNameRegex kProducerNameRegex{};
+ void set_producer_name_regex(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProducerNameRegex::kFieldId, data, size);
+ }
+ void set_producer_name_regex(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProducerNameRegex::kFieldId, chars.data, chars.size);
+ }
+ void set_producer_name_regex(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducerNameRegex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StopDelayMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_TriggerConfig_Trigger>;
+
+ static constexpr FieldMetadata_StopDelayMs kStopDelayMs{};
+ void set_stop_delay_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StopDelayMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxPer24H =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_TriggerConfig_Trigger>;
+
+ static constexpr FieldMetadata_MaxPer24H kMaxPer24H{};
+ void set_max_per_24_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxPer24H::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkipProbability =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ TraceConfig_TriggerConfig_Trigger>;
+
+ static constexpr FieldMetadata_SkipProbability kSkipProbability{};
+ void set_skip_probability(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkipProbability::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_GuardrailOverrides_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_GuardrailOverrides_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_GuardrailOverrides_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_GuardrailOverrides_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_max_upload_per_day_bytes() const { return at<1>().valid(); }
+ uint64_t max_upload_per_day_bytes() const { return at<1>().as_uint64(); }
+ bool has_max_tracing_buffer_size_kb() const { return at<2>().valid(); }
+ uint32_t max_tracing_buffer_size_kb() const { return at<2>().as_uint32(); }
+};
+
+class TraceConfig_GuardrailOverrides : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_GuardrailOverrides_Decoder;
+ enum : int32_t {
+ kMaxUploadPerDayBytesFieldNumber = 1,
+ kMaxTracingBufferSizeKbFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.GuardrailOverrides"; }
+
+
+ using FieldMetadata_MaxUploadPerDayBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TraceConfig_GuardrailOverrides>;
+
+ static constexpr FieldMetadata_MaxUploadPerDayBytes kMaxUploadPerDayBytes{};
+ void set_max_upload_per_day_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxUploadPerDayBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxTracingBufferSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_GuardrailOverrides>;
+
+ static constexpr FieldMetadata_MaxTracingBufferSizeKb kMaxTracingBufferSizeKb{};
+ void set_max_tracing_buffer_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxTracingBufferSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_StatsdMetadata_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_StatsdMetadata_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_StatsdMetadata_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_StatsdMetadata_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_triggering_alert_id() const { return at<1>().valid(); }
+ int64_t triggering_alert_id() const { return at<1>().as_int64(); }
+ bool has_triggering_config_uid() const { return at<2>().valid(); }
+ int32_t triggering_config_uid() const { return at<2>().as_int32(); }
+ bool has_triggering_config_id() const { return at<3>().valid(); }
+ int64_t triggering_config_id() const { return at<3>().as_int64(); }
+ bool has_triggering_subscription_id() const { return at<4>().valid(); }
+ int64_t triggering_subscription_id() const { return at<4>().as_int64(); }
+};
+
+class TraceConfig_StatsdMetadata : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_StatsdMetadata_Decoder;
+ enum : int32_t {
+ kTriggeringAlertIdFieldNumber = 1,
+ kTriggeringConfigUidFieldNumber = 2,
+ kTriggeringConfigIdFieldNumber = 3,
+ kTriggeringSubscriptionIdFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.StatsdMetadata"; }
+
+
+ using FieldMetadata_TriggeringAlertId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceConfig_StatsdMetadata>;
+
+ static constexpr FieldMetadata_TriggeringAlertId kTriggeringAlertId{};
+ void set_triggering_alert_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggeringAlertId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TriggeringConfigUid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TraceConfig_StatsdMetadata>;
+
+ static constexpr FieldMetadata_TriggeringConfigUid kTriggeringConfigUid{};
+ void set_triggering_config_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggeringConfigUid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TriggeringConfigId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceConfig_StatsdMetadata>;
+
+ static constexpr FieldMetadata_TriggeringConfigId kTriggeringConfigId{};
+ void set_triggering_config_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggeringConfigId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TriggeringSubscriptionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceConfig_StatsdMetadata>;
+
+ static constexpr FieldMetadata_TriggeringSubscriptionId kTriggeringSubscriptionId{};
+ void set_triggering_subscription_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggeringSubscriptionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_ProducerConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_ProducerConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_ProducerConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_ProducerConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_producer_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars producer_name() const { return at<1>().as_string(); }
+ bool has_shm_size_kb() const { return at<2>().valid(); }
+ uint32_t shm_size_kb() const { return at<2>().as_uint32(); }
+ bool has_page_size_kb() const { return at<3>().valid(); }
+ uint32_t page_size_kb() const { return at<3>().as_uint32(); }
+};
+
+class TraceConfig_ProducerConfig : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_ProducerConfig_Decoder;
+ enum : int32_t {
+ kProducerNameFieldNumber = 1,
+ kShmSizeKbFieldNumber = 2,
+ kPageSizeKbFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.ProducerConfig"; }
+
+
+ using FieldMetadata_ProducerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_ProducerConfig>;
+
+ static constexpr FieldMetadata_ProducerName kProducerName{};
+ void set_producer_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProducerName::kFieldId, data, size);
+ }
+ void set_producer_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProducerName::kFieldId, chars.data, chars.size);
+ }
+ void set_producer_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ShmSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_ProducerConfig>;
+
+ static constexpr FieldMetadata_ShmSizeKb kShmSizeKb{};
+ void set_shm_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShmSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PageSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_ProducerConfig>;
+
+ static constexpr FieldMetadata_PageSizeKb kPageSizeKb{};
+ void set_page_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PageSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_BuiltinDataSource_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_BuiltinDataSource_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_BuiltinDataSource_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_BuiltinDataSource_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_disable_clock_snapshotting() const { return at<1>().valid(); }
+ bool disable_clock_snapshotting() const { return at<1>().as_bool(); }
+ bool has_disable_trace_config() const { return at<2>().valid(); }
+ bool disable_trace_config() const { return at<2>().as_bool(); }
+ bool has_disable_system_info() const { return at<3>().valid(); }
+ bool disable_system_info() const { return at<3>().as_bool(); }
+ bool has_disable_service_events() const { return at<4>().valid(); }
+ bool disable_service_events() const { return at<4>().as_bool(); }
+ bool has_primary_trace_clock() const { return at<5>().valid(); }
+ int32_t primary_trace_clock() const { return at<5>().as_int32(); }
+ bool has_snapshot_interval_ms() const { return at<6>().valid(); }
+ uint32_t snapshot_interval_ms() const { return at<6>().as_uint32(); }
+ bool has_prefer_suspend_clock_for_snapshot() const { return at<7>().valid(); }
+ bool prefer_suspend_clock_for_snapshot() const { return at<7>().as_bool(); }
+ bool has_disable_chunk_usage_histograms() const { return at<8>().valid(); }
+ bool disable_chunk_usage_histograms() const { return at<8>().as_bool(); }
+};
+
+class TraceConfig_BuiltinDataSource : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_BuiltinDataSource_Decoder;
+ enum : int32_t {
+ kDisableClockSnapshottingFieldNumber = 1,
+ kDisableTraceConfigFieldNumber = 2,
+ kDisableSystemInfoFieldNumber = 3,
+ kDisableServiceEventsFieldNumber = 4,
+ kPrimaryTraceClockFieldNumber = 5,
+ kSnapshotIntervalMsFieldNumber = 6,
+ kPreferSuspendClockForSnapshotFieldNumber = 7,
+ kDisableChunkUsageHistogramsFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.BuiltinDataSource"; }
+
+
+ using FieldMetadata_DisableClockSnapshotting =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_DisableClockSnapshotting kDisableClockSnapshotting{};
+ void set_disable_clock_snapshotting(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableClockSnapshotting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableTraceConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_DisableTraceConfig kDisableTraceConfig{};
+ void set_disable_trace_config(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableTraceConfig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableSystemInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_DisableSystemInfo kDisableSystemInfo{};
+ void set_disable_system_info(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableSystemInfo::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableServiceEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_DisableServiceEvents kDisableServiceEvents{};
+ void set_disable_service_events(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableServiceEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrimaryTraceClock =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ BuiltinClock,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_PrimaryTraceClock kPrimaryTraceClock{};
+ void set_primary_trace_clock(BuiltinClock value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrimaryTraceClock::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SnapshotIntervalMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_SnapshotIntervalMs kSnapshotIntervalMs{};
+ void set_snapshot_interval_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SnapshotIntervalMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreferSuspendClockForSnapshot =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_PreferSuspendClockForSnapshot kPreferSuspendClockForSnapshot{};
+ void set_prefer_suspend_clock_for_snapshot(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreferSuspendClockForSnapshot::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisableChunkUsageHistograms =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BuiltinDataSource>;
+
+ static constexpr FieldMetadata_DisableChunkUsageHistograms kDisableChunkUsageHistograms{};
+ void set_disable_chunk_usage_histograms(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisableChunkUsageHistograms::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_DataSource_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TraceConfig_DataSource_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_DataSource_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_DataSource_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_config() const { return at<1>().valid(); }
+ ::protozero::ConstBytes config() const { return at<1>().as_bytes(); }
+ bool has_producer_name_filter() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> producer_name_filter() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_producer_name_regex_filter() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> producer_name_regex_filter() const { return GetRepeated<::protozero::ConstChars>(3); }
+};
+
+class TraceConfig_DataSource : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_DataSource_Decoder;
+ enum : int32_t {
+ kConfigFieldNumber = 1,
+ kProducerNameFilterFieldNumber = 2,
+ kProducerNameRegexFilterFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.DataSource"; }
+
+
+ using FieldMetadata_Config =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DataSourceConfig,
+ TraceConfig_DataSource>;
+
+ static constexpr FieldMetadata_Config kConfig{};
+ template <typename T = DataSourceConfig> T* set_config() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ProducerNameFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_DataSource>;
+
+ static constexpr FieldMetadata_ProducerNameFilter kProducerNameFilter{};
+ void add_producer_name_filter(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProducerNameFilter::kFieldId, data, size);
+ }
+ void add_producer_name_filter(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProducerNameFilter::kFieldId, chars.data, chars.size);
+ }
+ void add_producer_name_filter(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducerNameFilter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProducerNameRegexFilter =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TraceConfig_DataSource>;
+
+ static constexpr FieldMetadata_ProducerNameRegexFilter kProducerNameRegexFilter{};
+ void add_producer_name_regex_filter(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProducerNameRegexFilter::kFieldId, data, size);
+ }
+ void add_producer_name_regex_filter(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProducerNameRegexFilter::kFieldId, chars.data, chars.size);
+ }
+ void add_producer_name_regex_filter(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducerNameRegexFilter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TraceConfig_BufferConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceConfig_BufferConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceConfig_BufferConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceConfig_BufferConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_size_kb() const { return at<1>().valid(); }
+ uint32_t size_kb() const { return at<1>().as_uint32(); }
+ bool has_fill_policy() const { return at<4>().valid(); }
+ int32_t fill_policy() const { return at<4>().as_int32(); }
+ bool has_transfer_on_clone() const { return at<5>().valid(); }
+ bool transfer_on_clone() const { return at<5>().as_bool(); }
+ bool has_clear_before_clone() const { return at<6>().valid(); }
+ bool clear_before_clone() const { return at<6>().as_bool(); }
+};
+
+class TraceConfig_BufferConfig : public ::protozero::Message {
+ public:
+ using Decoder = TraceConfig_BufferConfig_Decoder;
+ enum : int32_t {
+ kSizeKbFieldNumber = 1,
+ kFillPolicyFieldNumber = 4,
+ kTransferOnCloneFieldNumber = 5,
+ kClearBeforeCloneFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceConfig.BufferConfig"; }
+
+
+ using FillPolicy = ::perfetto::protos::pbzero::TraceConfig_BufferConfig_FillPolicy;
+ static inline const char* FillPolicy_Name(FillPolicy value) {
+ return ::perfetto::protos::pbzero::TraceConfig_BufferConfig_FillPolicy_Name(value);
+ }
+ static inline const FillPolicy UNSPECIFIED = FillPolicy::UNSPECIFIED;
+ static inline const FillPolicy RING_BUFFER = FillPolicy::RING_BUFFER;
+ static inline const FillPolicy DISCARD = FillPolicy::DISCARD;
+
+ using FieldMetadata_SizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TraceConfig_BufferConfig>;
+
+ static constexpr FieldMetadata_SizeKb kSizeKb{};
+ void set_size_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FillPolicy =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TraceConfig_BufferConfig_FillPolicy,
+ TraceConfig_BufferConfig>;
+
+ static constexpr FieldMetadata_FillPolicy kFillPolicy{};
+ void set_fill_policy(TraceConfig_BufferConfig_FillPolicy value) {
+ static constexpr uint32_t field_id = FieldMetadata_FillPolicy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TransferOnClone =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BufferConfig>;
+
+ static constexpr FieldMetadata_TransferOnClone kTransferOnClone{};
+ void set_transfer_on_clone(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TransferOnClone::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClearBeforeClone =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TraceConfig_BufferConfig>;
+
+ static constexpr FieldMetadata_ClearBeforeClone kClearBeforeClone{};
+ void set_clear_before_clone(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClearBeforeClone::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/clock_snapshot.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CLOCK_SNAPSHOT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CLOCK_SNAPSHOT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ClockSnapshot_Clock;
+enum BuiltinClock : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ClockSnapshot_Clock {
+enum BuiltinClocks : int32_t {
+ UNKNOWN = 0,
+ REALTIME = 1,
+ REALTIME_COARSE = 2,
+ MONOTONIC = 3,
+ MONOTONIC_COARSE = 4,
+ MONOTONIC_RAW = 5,
+ BOOTTIME = 6,
+ BUILTIN_CLOCK_MAX_ID = 63,
+};
+} // namespace perfetto_pbzero_enum_ClockSnapshot_Clock
+using ClockSnapshot_Clock_BuiltinClocks = perfetto_pbzero_enum_ClockSnapshot_Clock::BuiltinClocks;
+
+
+constexpr ClockSnapshot_Clock_BuiltinClocks ClockSnapshot_Clock_BuiltinClocks_MIN = ClockSnapshot_Clock_BuiltinClocks::UNKNOWN;
+constexpr ClockSnapshot_Clock_BuiltinClocks ClockSnapshot_Clock_BuiltinClocks_MAX = ClockSnapshot_Clock_BuiltinClocks::BUILTIN_CLOCK_MAX_ID;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ClockSnapshot_Clock_BuiltinClocks_Name(::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::UNKNOWN:
+ return "UNKNOWN";
+
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::REALTIME:
+ return "REALTIME";
+
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::REALTIME_COARSE:
+ return "REALTIME_COARSE";
+
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::MONOTONIC:
+ return "MONOTONIC";
+
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::MONOTONIC_COARSE:
+ return "MONOTONIC_COARSE";
+
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::MONOTONIC_RAW:
+ return "MONOTONIC_RAW";
+
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::BOOTTIME:
+ return "BOOTTIME";
+
+ case ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks::BUILTIN_CLOCK_MAX_ID:
+ return "BUILTIN_CLOCK_MAX_ID";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ClockSnapshot_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ClockSnapshot_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClockSnapshot_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClockSnapshot_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_clocks() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> clocks() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_primary_trace_clock() const { return at<2>().valid(); }
+ int32_t primary_trace_clock() const { return at<2>().as_int32(); }
+};
+
+class ClockSnapshot : public ::protozero::Message {
+ public:
+ using Decoder = ClockSnapshot_Decoder;
+ enum : int32_t {
+ kClocksFieldNumber = 1,
+ kPrimaryTraceClockFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClockSnapshot"; }
+
+ using Clock = ::perfetto::protos::pbzero::ClockSnapshot_Clock;
+
+ using FieldMetadata_Clocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClockSnapshot_Clock,
+ ClockSnapshot>;
+
+ static constexpr FieldMetadata_Clocks kClocks{};
+ template <typename T = ClockSnapshot_Clock> T* add_clocks() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_PrimaryTraceClock =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ BuiltinClock,
+ ClockSnapshot>;
+
+ static constexpr FieldMetadata_PrimaryTraceClock kPrimaryTraceClock{};
+ void set_primary_trace_clock(BuiltinClock value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrimaryTraceClock::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ClockSnapshot_Clock_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ClockSnapshot_Clock_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClockSnapshot_Clock_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClockSnapshot_Clock_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_clock_id() const { return at<1>().valid(); }
+ uint32_t clock_id() const { return at<1>().as_uint32(); }
+ bool has_timestamp() const { return at<2>().valid(); }
+ uint64_t timestamp() const { return at<2>().as_uint64(); }
+ bool has_is_incremental() const { return at<3>().valid(); }
+ bool is_incremental() const { return at<3>().as_bool(); }
+ bool has_unit_multiplier_ns() const { return at<4>().valid(); }
+ uint64_t unit_multiplier_ns() const { return at<4>().as_uint64(); }
+};
+
+class ClockSnapshot_Clock : public ::protozero::Message {
+ public:
+ using Decoder = ClockSnapshot_Clock_Decoder;
+ enum : int32_t {
+ kClockIdFieldNumber = 1,
+ kTimestampFieldNumber = 2,
+ kIsIncrementalFieldNumber = 3,
+ kUnitMultiplierNsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClockSnapshot.Clock"; }
+
+
+ using BuiltinClocks = ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks;
+ static inline const char* BuiltinClocks_Name(BuiltinClocks value) {
+ return ::perfetto::protos::pbzero::ClockSnapshot_Clock_BuiltinClocks_Name(value);
+ }
+ static inline const BuiltinClocks UNKNOWN = BuiltinClocks::UNKNOWN;
+ static inline const BuiltinClocks REALTIME = BuiltinClocks::REALTIME;
+ static inline const BuiltinClocks REALTIME_COARSE = BuiltinClocks::REALTIME_COARSE;
+ static inline const BuiltinClocks MONOTONIC = BuiltinClocks::MONOTONIC;
+ static inline const BuiltinClocks MONOTONIC_COARSE = BuiltinClocks::MONOTONIC_COARSE;
+ static inline const BuiltinClocks MONOTONIC_RAW = BuiltinClocks::MONOTONIC_RAW;
+ static inline const BuiltinClocks BOOTTIME = BuiltinClocks::BOOTTIME;
+ static inline const BuiltinClocks BUILTIN_CLOCK_MAX_ID = BuiltinClocks::BUILTIN_CLOCK_MAX_ID;
+
+ using FieldMetadata_ClockId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ClockSnapshot_Clock>;
+
+ static constexpr FieldMetadata_ClockId kClockId{};
+ void set_clock_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClockId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockSnapshot_Clock>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsIncremental =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ClockSnapshot_Clock>;
+
+ static constexpr FieldMetadata_IsIncremental kIsIncremental{};
+ void set_is_incremental(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsIncremental::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnitMultiplierNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockSnapshot_Clock>;
+
+ static constexpr FieldMetadata_UnitMultiplierNs kUnitMultiplierNs{};
+ void set_unit_multiplier_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnitMultiplierNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/trace_uuid.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_UUID_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_UUID_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TraceUuid_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TraceUuid_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TraceUuid_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TraceUuid_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_msb() const { return at<1>().valid(); }
+ int64_t msb() const { return at<1>().as_int64(); }
+ bool has_lsb() const { return at<2>().valid(); }
+ int64_t lsb() const { return at<2>().as_int64(); }
+};
+
+class TraceUuid : public ::protozero::Message {
+ public:
+ using Decoder = TraceUuid_Decoder;
+ enum : int32_t {
+ kMsbFieldNumber = 1,
+ kLsbFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TraceUuid"; }
+
+
+ using FieldMetadata_Msb =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceUuid>;
+
+ static constexpr FieldMetadata_Msb kMsb{};
+ void set_msb(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Msb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lsb =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TraceUuid>;
+
+ static constexpr FieldMetadata_Lsb kLsb{};
+ void set_lsb(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lsb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/trigger.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRIGGER_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRIGGER_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class Trigger_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Trigger_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Trigger_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Trigger_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trigger_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars trigger_name() const { return at<1>().as_string(); }
+ bool has_producer_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars producer_name() const { return at<2>().as_string(); }
+ bool has_trusted_producer_uid() const { return at<3>().valid(); }
+ int32_t trusted_producer_uid() const { return at<3>().as_int32(); }
+};
+
+class Trigger : public ::protozero::Message {
+ public:
+ using Decoder = Trigger_Decoder;
+ enum : int32_t {
+ kTriggerNameFieldNumber = 1,
+ kProducerNameFieldNumber = 2,
+ kTrustedProducerUidFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Trigger"; }
+
+
+ using FieldMetadata_TriggerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Trigger>;
+
+ static constexpr FieldMetadata_TriggerName kTriggerName{};
+ void set_trigger_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TriggerName::kFieldId, data, size);
+ }
+ void set_trigger_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TriggerName::kFieldId, chars.data, chars.size);
+ }
+ void set_trigger_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProducerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Trigger>;
+
+ static constexpr FieldMetadata_ProducerName kProducerName{};
+ void set_producer_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProducerName::kFieldId, data, size);
+ }
+ void set_producer_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProducerName::kFieldId, chars.data, chars.size);
+ }
+ void set_producer_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProducerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TrustedProducerUid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Trigger>;
+
+ static constexpr FieldMetadata_TrustedProducerUid kTrustedProducerUid{};
+ void set_trusted_producer_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TrustedProducerUid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/system_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_SYSTEM_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_SYSTEM_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class Utsname;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SystemInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SystemInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SystemInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SystemInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_utsname() const { return at<1>().valid(); }
+ ::protozero::ConstBytes utsname() const { return at<1>().as_bytes(); }
+ bool has_android_build_fingerprint() const { return at<2>().valid(); }
+ ::protozero::ConstChars android_build_fingerprint() const { return at<2>().as_string(); }
+ bool has_tracing_service_version() const { return at<4>().valid(); }
+ ::protozero::ConstChars tracing_service_version() const { return at<4>().as_string(); }
+ bool has_android_sdk_version() const { return at<5>().valid(); }
+ uint64_t android_sdk_version() const { return at<5>().as_uint64(); }
+ bool has_page_size() const { return at<6>().valid(); }
+ uint32_t page_size() const { return at<6>().as_uint32(); }
+ bool has_num_cpus() const { return at<8>().valid(); }
+ uint32_t num_cpus() const { return at<8>().as_uint32(); }
+ bool has_timezone_off_mins() const { return at<7>().valid(); }
+ int32_t timezone_off_mins() const { return at<7>().as_int32(); }
+ bool has_hz() const { return at<3>().valid(); }
+ int64_t hz() const { return at<3>().as_int64(); }
+};
+
+class SystemInfo : public ::protozero::Message {
+ public:
+ using Decoder = SystemInfo_Decoder;
+ enum : int32_t {
+ kUtsnameFieldNumber = 1,
+ kAndroidBuildFingerprintFieldNumber = 2,
+ kTracingServiceVersionFieldNumber = 4,
+ kAndroidSdkVersionFieldNumber = 5,
+ kPageSizeFieldNumber = 6,
+ kNumCpusFieldNumber = 8,
+ kTimezoneOffMinsFieldNumber = 7,
+ kHzFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SystemInfo"; }
+
+
+ using FieldMetadata_Utsname =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Utsname,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_Utsname kUtsname{};
+ template <typename T = Utsname> T* set_utsname() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_AndroidBuildFingerprint =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_AndroidBuildFingerprint kAndroidBuildFingerprint{};
+ void set_android_build_fingerprint(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_AndroidBuildFingerprint::kFieldId, data, size);
+ }
+ void set_android_build_fingerprint(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_AndroidBuildFingerprint::kFieldId, chars.data, chars.size);
+ }
+ void set_android_build_fingerprint(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_AndroidBuildFingerprint::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TracingServiceVersion =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_TracingServiceVersion kTracingServiceVersion{};
+ void set_tracing_service_version(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TracingServiceVersion::kFieldId, data, size);
+ }
+ void set_tracing_service_version(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TracingServiceVersion::kFieldId, chars.data, chars.size);
+ }
+ void set_tracing_service_version(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingServiceVersion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AndroidSdkVersion =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_AndroidSdkVersion kAndroidSdkVersion{};
+ void set_android_sdk_version(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AndroidSdkVersion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PageSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_PageSize kPageSize{};
+ void set_page_size(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PageSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumCpus =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_NumCpus kNumCpus{};
+ void set_num_cpus(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumCpus::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimezoneOffMins =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_TimezoneOffMins kTimezoneOffMins{};
+ void set_timezone_off_mins(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimezoneOffMins::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Hz =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ SystemInfo>;
+
+ static constexpr FieldMetadata_Hz kHz{};
+ void set_hz(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hz::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Utsname_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Utsname_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Utsname_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Utsname_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_sysname() const { return at<1>().valid(); }
+ ::protozero::ConstChars sysname() const { return at<1>().as_string(); }
+ bool has_version() const { return at<2>().valid(); }
+ ::protozero::ConstChars version() const { return at<2>().as_string(); }
+ bool has_release() const { return at<3>().valid(); }
+ ::protozero::ConstChars release() const { return at<3>().as_string(); }
+ bool has_machine() const { return at<4>().valid(); }
+ ::protozero::ConstChars machine() const { return at<4>().as_string(); }
+};
+
+class Utsname : public ::protozero::Message {
+ public:
+ using Decoder = Utsname_Decoder;
+ enum : int32_t {
+ kSysnameFieldNumber = 1,
+ kVersionFieldNumber = 2,
+ kReleaseFieldNumber = 3,
+ kMachineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Utsname"; }
+
+
+ using FieldMetadata_Sysname =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Utsname>;
+
+ static constexpr FieldMetadata_Sysname kSysname{};
+ void set_sysname(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Sysname::kFieldId, data, size);
+ }
+ void set_sysname(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Sysname::kFieldId, chars.data, chars.size);
+ }
+ void set_sysname(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sysname::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Version =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Utsname>;
+
+ static constexpr FieldMetadata_Version kVersion{};
+ void set_version(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Version::kFieldId, data, size);
+ }
+ void set_version(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Version::kFieldId, chars.data, chars.size);
+ }
+ void set_version(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Version::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Release =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Utsname>;
+
+ static constexpr FieldMetadata_Release kRelease{};
+ void set_release(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Release::kFieldId, data, size);
+ }
+ void set_release(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Release::kFieldId, chars.data, chars.size);
+ }
+ void set_release(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Release::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Machine =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Utsname>;
+
+ static constexpr FieldMetadata_Machine kMachine{};
+ void set_machine(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Machine::kFieldId, data, size);
+ }
+ void set_machine(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Machine::kFieldId, chars.data, chars.size);
+ }
+ void set_machine(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Machine::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/android_game_intervention_list.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_GAME_INTERVENTION_LIST_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_GAME_INTERVENTION_LIST_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidGameInterventionList_GameModeInfo;
+class AndroidGameInterventionList_GamePackageInfo;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidGameInterventionList_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidGameInterventionList_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidGameInterventionList_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidGameInterventionList_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_game_packages() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> game_packages() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_parse_error() const { return at<2>().valid(); }
+ bool parse_error() const { return at<2>().as_bool(); }
+ bool has_read_error() const { return at<3>().valid(); }
+ bool read_error() const { return at<3>().as_bool(); }
+};
+
+class AndroidGameInterventionList : public ::protozero::Message {
+ public:
+ using Decoder = AndroidGameInterventionList_Decoder;
+ enum : int32_t {
+ kGamePackagesFieldNumber = 1,
+ kParseErrorFieldNumber = 2,
+ kReadErrorFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidGameInterventionList"; }
+
+ using GameModeInfo = ::perfetto::protos::pbzero::AndroidGameInterventionList_GameModeInfo;
+ using GamePackageInfo = ::perfetto::protos::pbzero::AndroidGameInterventionList_GamePackageInfo;
+
+ using FieldMetadata_GamePackages =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidGameInterventionList_GamePackageInfo,
+ AndroidGameInterventionList>;
+
+ static constexpr FieldMetadata_GamePackages kGamePackages{};
+ template <typename T = AndroidGameInterventionList_GamePackageInfo> T* add_game_packages() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ParseError =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidGameInterventionList>;
+
+ static constexpr FieldMetadata_ParseError kParseError{};
+ void set_parse_error(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParseError::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadError =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidGameInterventionList>;
+
+ static constexpr FieldMetadata_ReadError kReadError{};
+ void set_read_error(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadError::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidGameInterventionList_GamePackageInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidGameInterventionList_GamePackageInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidGameInterventionList_GamePackageInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidGameInterventionList_GamePackageInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_uid() const { return at<2>().valid(); }
+ uint64_t uid() const { return at<2>().as_uint64(); }
+ bool has_current_mode() const { return at<3>().valid(); }
+ uint32_t current_mode() const { return at<3>().as_uint32(); }
+ bool has_game_mode_info() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> game_mode_info() const { return GetRepeated<::protozero::ConstBytes>(4); }
+};
+
+class AndroidGameInterventionList_GamePackageInfo : public ::protozero::Message {
+ public:
+ using Decoder = AndroidGameInterventionList_GamePackageInfo_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kUidFieldNumber = 2,
+ kCurrentModeFieldNumber = 3,
+ kGameModeInfoFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidGameInterventionList.GamePackageInfo"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidGameInterventionList_GamePackageInfo>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidGameInterventionList_GamePackageInfo>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrentMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidGameInterventionList_GamePackageInfo>;
+
+ static constexpr FieldMetadata_CurrentMode kCurrentMode{};
+ void set_current_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrentMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GameModeInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidGameInterventionList_GameModeInfo,
+ AndroidGameInterventionList_GamePackageInfo>;
+
+ static constexpr FieldMetadata_GameModeInfo kGameModeInfo{};
+ template <typename T = AndroidGameInterventionList_GameModeInfo> T* add_game_mode_info() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+class AndroidGameInterventionList_GameModeInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidGameInterventionList_GameModeInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidGameInterventionList_GameModeInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidGameInterventionList_GameModeInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mode() const { return at<1>().valid(); }
+ uint32_t mode() const { return at<1>().as_uint32(); }
+ bool has_use_angle() const { return at<2>().valid(); }
+ bool use_angle() const { return at<2>().as_bool(); }
+ bool has_resolution_downscale() const { return at<3>().valid(); }
+ float resolution_downscale() const { return at<3>().as_float(); }
+ bool has_fps() const { return at<4>().valid(); }
+ float fps() const { return at<4>().as_float(); }
+};
+
+class AndroidGameInterventionList_GameModeInfo : public ::protozero::Message {
+ public:
+ using Decoder = AndroidGameInterventionList_GameModeInfo_Decoder;
+ enum : int32_t {
+ kModeFieldNumber = 1,
+ kUseAngleFieldNumber = 2,
+ kResolutionDownscaleFieldNumber = 3,
+ kFpsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidGameInterventionList.GameModeInfo"; }
+
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidGameInterventionList_GameModeInfo>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UseAngle =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ AndroidGameInterventionList_GameModeInfo>;
+
+ static constexpr FieldMetadata_UseAngle kUseAngle{};
+ void set_use_angle(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_UseAngle::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResolutionDownscale =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidGameInterventionList_GameModeInfo>;
+
+ static constexpr FieldMetadata_ResolutionDownscale kResolutionDownscale{};
+ void set_resolution_downscale(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResolutionDownscale::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fps =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidGameInterventionList_GameModeInfo>;
+
+ static constexpr FieldMetadata_Fps kFps{};
+ void set_fps(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fps::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/android_input_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_INPUT_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_INPUT_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidKeyEvent;
+class AndroidMotionEvent;
+class AndroidMotionEvent_Pointer;
+class AndroidMotionEvent_Pointer_AxisValue;
+class AndroidWindowInputDispatchEvent;
+class AndroidWindowInputDispatchEvent_DispatchedPointer;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidInputEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidInputEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidInputEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidInputEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dispatcher_motion_event() const { return at<1>().valid(); }
+ ::protozero::ConstBytes dispatcher_motion_event() const { return at<1>().as_bytes(); }
+ bool has_dispatcher_motion_event_redacted() const { return at<2>().valid(); }
+ ::protozero::ConstBytes dispatcher_motion_event_redacted() const { return at<2>().as_bytes(); }
+ bool has_dispatcher_key_event() const { return at<3>().valid(); }
+ ::protozero::ConstBytes dispatcher_key_event() const { return at<3>().as_bytes(); }
+ bool has_dispatcher_key_event_redacted() const { return at<4>().valid(); }
+ ::protozero::ConstBytes dispatcher_key_event_redacted() const { return at<4>().as_bytes(); }
+ bool has_dispatcher_window_dispatch_event() const { return at<5>().valid(); }
+ ::protozero::ConstBytes dispatcher_window_dispatch_event() const { return at<5>().as_bytes(); }
+ bool has_dispatcher_window_dispatch_event_redacted() const { return at<6>().valid(); }
+ ::protozero::ConstBytes dispatcher_window_dispatch_event_redacted() const { return at<6>().as_bytes(); }
+};
+
+class AndroidInputEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidInputEvent_Decoder;
+ enum : int32_t {
+ kDispatcherMotionEventFieldNumber = 1,
+ kDispatcherMotionEventRedactedFieldNumber = 2,
+ kDispatcherKeyEventFieldNumber = 3,
+ kDispatcherKeyEventRedactedFieldNumber = 4,
+ kDispatcherWindowDispatchEventFieldNumber = 5,
+ kDispatcherWindowDispatchEventRedactedFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidInputEvent"; }
+
+
+ using FieldMetadata_DispatcherMotionEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidMotionEvent,
+ AndroidInputEvent>;
+
+ static constexpr FieldMetadata_DispatcherMotionEvent kDispatcherMotionEvent{};
+ template <typename T = AndroidMotionEvent> T* set_dispatcher_motion_event() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_DispatcherMotionEventRedacted =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidMotionEvent,
+ AndroidInputEvent>;
+
+ static constexpr FieldMetadata_DispatcherMotionEventRedacted kDispatcherMotionEventRedacted{};
+ template <typename T = AndroidMotionEvent> T* set_dispatcher_motion_event_redacted() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_DispatcherKeyEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidKeyEvent,
+ AndroidInputEvent>;
+
+ static constexpr FieldMetadata_DispatcherKeyEvent kDispatcherKeyEvent{};
+ template <typename T = AndroidKeyEvent> T* set_dispatcher_key_event() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_DispatcherKeyEventRedacted =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidKeyEvent,
+ AndroidInputEvent>;
+
+ static constexpr FieldMetadata_DispatcherKeyEventRedacted kDispatcherKeyEventRedacted{};
+ template <typename T = AndroidKeyEvent> T* set_dispatcher_key_event_redacted() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_DispatcherWindowDispatchEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidWindowInputDispatchEvent,
+ AndroidInputEvent>;
+
+ static constexpr FieldMetadata_DispatcherWindowDispatchEvent kDispatcherWindowDispatchEvent{};
+ template <typename T = AndroidWindowInputDispatchEvent> T* set_dispatcher_window_dispatch_event() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_DispatcherWindowDispatchEventRedacted =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidWindowInputDispatchEvent,
+ AndroidInputEvent>;
+
+ static constexpr FieldMetadata_DispatcherWindowDispatchEventRedacted kDispatcherWindowDispatchEventRedacted{};
+ template <typename T = AndroidWindowInputDispatchEvent> T* set_dispatcher_window_dispatch_event_redacted() {
+ return BeginNestedMessage<T>(6);
+ }
+
+};
+
+class AndroidWindowInputDispatchEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidWindowInputDispatchEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidWindowInputDispatchEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidWindowInputDispatchEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_id() const { return at<1>().valid(); }
+ uint32_t event_id() const { return at<1>().as_uint32(); }
+ bool has_vsync_id() const { return at<2>().valid(); }
+ int64_t vsync_id() const { return at<2>().as_int64(); }
+ bool has_window_id() const { return at<3>().valid(); }
+ int32_t window_id() const { return at<3>().as_int32(); }
+ bool has_dispatched_pointer() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> dispatched_pointer() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_resolved_flags() const { return at<5>().valid(); }
+ uint32_t resolved_flags() const { return at<5>().as_uint32(); }
+};
+
+class AndroidWindowInputDispatchEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidWindowInputDispatchEvent_Decoder;
+ enum : int32_t {
+ kEventIdFieldNumber = 1,
+ kVsyncIdFieldNumber = 2,
+ kWindowIdFieldNumber = 3,
+ kDispatchedPointerFieldNumber = 4,
+ kResolvedFlagsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidWindowInputDispatchEvent"; }
+
+ using DispatchedPointer = ::perfetto::protos::pbzero::AndroidWindowInputDispatchEvent_DispatchedPointer;
+
+ using FieldMetadata_EventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32,
+ uint32_t,
+ AndroidWindowInputDispatchEvent>;
+
+ static constexpr FieldMetadata_EventId kEventId{};
+ void set_event_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VsyncId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidWindowInputDispatchEvent>;
+
+ static constexpr FieldMetadata_VsyncId kVsyncId{};
+ void set_vsync_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VsyncId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WindowId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidWindowInputDispatchEvent>;
+
+ static constexpr FieldMetadata_WindowId kWindowId{};
+ void set_window_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WindowId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DispatchedPointer =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidWindowInputDispatchEvent_DispatchedPointer,
+ AndroidWindowInputDispatchEvent>;
+
+ static constexpr FieldMetadata_DispatchedPointer kDispatchedPointer{};
+ template <typename T = AndroidWindowInputDispatchEvent_DispatchedPointer> T* add_dispatched_pointer() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_ResolvedFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidWindowInputDispatchEvent>;
+
+ static constexpr FieldMetadata_ResolvedFlags kResolvedFlags{};
+ void set_resolved_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResolvedFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidWindowInputDispatchEvent_DispatchedPointer_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidWindowInputDispatchEvent_DispatchedPointer_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidWindowInputDispatchEvent_DispatchedPointer_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidWindowInputDispatchEvent_DispatchedPointer_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pointer_id() const { return at<1>().valid(); }
+ int32_t pointer_id() const { return at<1>().as_int32(); }
+ bool has_x_in_display() const { return at<2>().valid(); }
+ float x_in_display() const { return at<2>().as_float(); }
+ bool has_y_in_display() const { return at<3>().valid(); }
+ float y_in_display() const { return at<3>().as_float(); }
+ bool has_axis_value_in_window() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> axis_value_in_window() const { return GetRepeated<::protozero::ConstBytes>(4); }
+};
+
+class AndroidWindowInputDispatchEvent_DispatchedPointer : public ::protozero::Message {
+ public:
+ using Decoder = AndroidWindowInputDispatchEvent_DispatchedPointer_Decoder;
+ enum : int32_t {
+ kPointerIdFieldNumber = 1,
+ kXInDisplayFieldNumber = 2,
+ kYInDisplayFieldNumber = 3,
+ kAxisValueInWindowFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidWindowInputDispatchEvent.DispatchedPointer"; }
+
+
+ using FieldMetadata_PointerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidWindowInputDispatchEvent_DispatchedPointer>;
+
+ static constexpr FieldMetadata_PointerId kPointerId{};
+ void set_pointer_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PointerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_XInDisplay =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidWindowInputDispatchEvent_DispatchedPointer>;
+
+ static constexpr FieldMetadata_XInDisplay kXInDisplay{};
+ void set_x_in_display(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_XInDisplay::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_YInDisplay =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidWindowInputDispatchEvent_DispatchedPointer>;
+
+ static constexpr FieldMetadata_YInDisplay kYInDisplay{};
+ void set_y_in_display(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_YInDisplay::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AxisValueInWindow =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidMotionEvent_Pointer_AxisValue,
+ AndroidWindowInputDispatchEvent_DispatchedPointer>;
+
+ static constexpr FieldMetadata_AxisValueInWindow kAxisValueInWindow{};
+ template <typename T = AndroidMotionEvent_Pointer_AxisValue> T* add_axis_value_in_window() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+class AndroidKeyEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/13, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidKeyEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidKeyEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidKeyEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_id() const { return at<1>().valid(); }
+ uint32_t event_id() const { return at<1>().as_uint32(); }
+ bool has_event_time_nanos() const { return at<2>().valid(); }
+ int64_t event_time_nanos() const { return at<2>().as_int64(); }
+ bool has_down_time_nanos() const { return at<3>().valid(); }
+ int64_t down_time_nanos() const { return at<3>().as_int64(); }
+ bool has_source() const { return at<4>().valid(); }
+ uint32_t source() const { return at<4>().as_uint32(); }
+ bool has_action() const { return at<5>().valid(); }
+ int32_t action() const { return at<5>().as_int32(); }
+ bool has_device_id() const { return at<6>().valid(); }
+ int32_t device_id() const { return at<6>().as_int32(); }
+ bool has_display_id() const { return at<7>().valid(); }
+ int32_t display_id() const { return at<7>().as_sint32(); }
+ bool has_key_code() const { return at<8>().valid(); }
+ int32_t key_code() const { return at<8>().as_int32(); }
+ bool has_scan_code() const { return at<9>().valid(); }
+ uint32_t scan_code() const { return at<9>().as_uint32(); }
+ bool has_meta_state() const { return at<10>().valid(); }
+ uint32_t meta_state() const { return at<10>().as_uint32(); }
+ bool has_repeat_count() const { return at<11>().valid(); }
+ int32_t repeat_count() const { return at<11>().as_int32(); }
+ bool has_flags() const { return at<12>().valid(); }
+ uint32_t flags() const { return at<12>().as_uint32(); }
+ bool has_policy_flags() const { return at<13>().valid(); }
+ uint32_t policy_flags() const { return at<13>().as_uint32(); }
+};
+
+class AndroidKeyEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidKeyEvent_Decoder;
+ enum : int32_t {
+ kEventIdFieldNumber = 1,
+ kEventTimeNanosFieldNumber = 2,
+ kDownTimeNanosFieldNumber = 3,
+ kSourceFieldNumber = 4,
+ kActionFieldNumber = 5,
+ kDeviceIdFieldNumber = 6,
+ kDisplayIdFieldNumber = 7,
+ kKeyCodeFieldNumber = 8,
+ kScanCodeFieldNumber = 9,
+ kMetaStateFieldNumber = 10,
+ kRepeatCountFieldNumber = 11,
+ kFlagsFieldNumber = 12,
+ kPolicyFlagsFieldNumber = 13,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidKeyEvent"; }
+
+
+ using FieldMetadata_EventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32,
+ uint32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_EventId kEventId{};
+ void set_event_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EventTimeNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_EventTimeNanos kEventTimeNanos{};
+ void set_event_time_nanos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventTimeNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DownTimeNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_DownTimeNanos kDownTimeNanos{};
+ void set_down_time_nanos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DownTimeNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Source =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_Source kSource{};
+ void set_source(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Source::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Action =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_Action kAction{};
+ void set_action(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Action::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeviceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_DeviceId kDeviceId{};
+ void set_device_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeviceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisplayId =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint32,
+ int32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_DisplayId kDisplayId{};
+ void set_display_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisplayId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KeyCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_KeyCode kKeyCode{};
+ void set_key_code(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KeyCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_ScanCode kScanCode{};
+ void set_scan_code(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MetaState =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_MetaState kMetaState{};
+ void set_meta_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MetaState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RepeatCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_RepeatCount kRepeatCount{};
+ void set_repeat_count(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RepeatCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PolicyFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidKeyEvent>;
+
+ static constexpr FieldMetadata_PolicyFlags kPolicyFlags{};
+ void set_policy_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PolicyFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidMotionEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/25, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidMotionEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidMotionEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidMotionEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_id() const { return at<1>().valid(); }
+ uint32_t event_id() const { return at<1>().as_uint32(); }
+ bool has_event_time_nanos() const { return at<2>().valid(); }
+ int64_t event_time_nanos() const { return at<2>().as_int64(); }
+ bool has_source() const { return at<3>().valid(); }
+ uint32_t source() const { return at<3>().as_uint32(); }
+ bool has_action() const { return at<4>().valid(); }
+ int32_t action() const { return at<4>().as_int32(); }
+ bool has_device_id() const { return at<5>().valid(); }
+ int32_t device_id() const { return at<5>().as_int32(); }
+ bool has_display_id() const { return at<6>().valid(); }
+ int32_t display_id() const { return at<6>().as_sint32(); }
+ bool has_classification() const { return at<7>().valid(); }
+ int32_t classification() const { return at<7>().as_int32(); }
+ bool has_flags() const { return at<8>().valid(); }
+ uint32_t flags() const { return at<8>().as_uint32(); }
+ bool has_pointer() const { return at<9>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> pointer() const { return GetRepeated<::protozero::ConstBytes>(9); }
+ bool has_original_event_id() const { return at<16>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kFixed32, uint32_t> original_event_id(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kFixed32, uint32_t>(16, parse_error_ptr); }
+ bool has_down_time_nanos() const { return at<17>().valid(); }
+ int64_t down_time_nanos() const { return at<17>().as_int64(); }
+ bool has_cursor_position_x() const { return at<18>().valid(); }
+ float cursor_position_x() const { return at<18>().as_float(); }
+ bool has_cursor_position_y() const { return at<19>().valid(); }
+ float cursor_position_y() const { return at<19>().as_float(); }
+ bool has_action_button() const { return at<20>().valid(); }
+ int32_t action_button() const { return at<20>().as_int32(); }
+ bool has_button_state() const { return at<21>().valid(); }
+ uint32_t button_state() const { return at<21>().as_uint32(); }
+ bool has_meta_state() const { return at<22>().valid(); }
+ uint32_t meta_state() const { return at<22>().as_uint32(); }
+ bool has_policy_flags() const { return at<23>().valid(); }
+ uint32_t policy_flags() const { return at<23>().as_uint32(); }
+ bool has_precision_x() const { return at<24>().valid(); }
+ float precision_x() const { return at<24>().as_float(); }
+ bool has_precision_y() const { return at<25>().valid(); }
+ float precision_y() const { return at<25>().as_float(); }
+};
+
+class AndroidMotionEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidMotionEvent_Decoder;
+ enum : int32_t {
+ kEventIdFieldNumber = 1,
+ kEventTimeNanosFieldNumber = 2,
+ kSourceFieldNumber = 3,
+ kActionFieldNumber = 4,
+ kDeviceIdFieldNumber = 5,
+ kDisplayIdFieldNumber = 6,
+ kClassificationFieldNumber = 7,
+ kFlagsFieldNumber = 8,
+ kPointerFieldNumber = 9,
+ kOriginalEventIdFieldNumber = 16,
+ kDownTimeNanosFieldNumber = 17,
+ kCursorPositionXFieldNumber = 18,
+ kCursorPositionYFieldNumber = 19,
+ kActionButtonFieldNumber = 20,
+ kButtonStateFieldNumber = 21,
+ kMetaStateFieldNumber = 22,
+ kPolicyFlagsFieldNumber = 23,
+ kPrecisionXFieldNumber = 24,
+ kPrecisionYFieldNumber = 25,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidMotionEvent"; }
+
+ using Pointer = ::perfetto::protos::pbzero::AndroidMotionEvent_Pointer;
+
+ using FieldMetadata_EventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32,
+ uint32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_EventId kEventId{};
+ void set_event_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EventTimeNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_EventTimeNanos kEventTimeNanos{};
+ void set_event_time_nanos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventTimeNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Source =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_Source kSource{};
+ void set_source(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Source::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Action =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_Action kAction{};
+ void set_action(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Action::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeviceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_DeviceId kDeviceId{};
+ void set_device_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeviceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisplayId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint32,
+ int32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_DisplayId kDisplayId{};
+ void set_display_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisplayId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Classification =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_Classification kClassification{};
+ void set_classification(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Classification::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pointer =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidMotionEvent_Pointer,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_Pointer kPointer{};
+ template <typename T = AndroidMotionEvent_Pointer> T* add_pointer() {
+ return BeginNestedMessage<T>(9);
+ }
+
+
+ using FieldMetadata_OriginalEventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32,
+ uint32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_OriginalEventId kOriginalEventId{};
+ void set_original_event_id(const ::protozero::PackedFixedSizeInt<uint32_t>& packed_buffer) {
+ AppendBytes(FieldMetadata_OriginalEventId::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_DownTimeNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_DownTimeNanos kDownTimeNanos{};
+ void set_down_time_nanos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DownTimeNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CursorPositionX =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_CursorPositionX kCursorPositionX{};
+ void set_cursor_position_x(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_CursorPositionX::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CursorPositionY =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_CursorPositionY kCursorPositionY{};
+ void set_cursor_position_y(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_CursorPositionY::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ActionButton =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_ActionButton kActionButton{};
+ void set_action_button(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActionButton::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ButtonState =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_ButtonState kButtonState{};
+ void set_button_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ButtonState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MetaState =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_MetaState kMetaState{};
+ void set_meta_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MetaState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PolicyFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_PolicyFlags kPolicyFlags{};
+ void set_policy_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PolicyFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrecisionX =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_PrecisionX kPrecisionX{};
+ void set_precision_x(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrecisionX::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrecisionY =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidMotionEvent>;
+
+ static constexpr FieldMetadata_PrecisionY kPrecisionY{};
+ void set_precision_y(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrecisionY::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidMotionEvent_Pointer_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidMotionEvent_Pointer_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidMotionEvent_Pointer_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidMotionEvent_Pointer_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_axis_value() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> axis_value() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_pointer_id() const { return at<2>().valid(); }
+ int32_t pointer_id() const { return at<2>().as_int32(); }
+ bool has_tool_type() const { return at<3>().valid(); }
+ int32_t tool_type() const { return at<3>().as_int32(); }
+};
+
+class AndroidMotionEvent_Pointer : public ::protozero::Message {
+ public:
+ using Decoder = AndroidMotionEvent_Pointer_Decoder;
+ enum : int32_t {
+ kAxisValueFieldNumber = 1,
+ kPointerIdFieldNumber = 2,
+ kToolTypeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidMotionEvent.Pointer"; }
+
+ using AxisValue = ::perfetto::protos::pbzero::AndroidMotionEvent_Pointer_AxisValue;
+
+ using FieldMetadata_AxisValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidMotionEvent_Pointer_AxisValue,
+ AndroidMotionEvent_Pointer>;
+
+ static constexpr FieldMetadata_AxisValue kAxisValue{};
+ template <typename T = AndroidMotionEvent_Pointer_AxisValue> T* add_axis_value() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_PointerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidMotionEvent_Pointer>;
+
+ static constexpr FieldMetadata_PointerId kPointerId{};
+ void set_pointer_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PointerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ToolType =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidMotionEvent_Pointer>;
+
+ static constexpr FieldMetadata_ToolType kToolType{};
+ void set_tool_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ToolType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidMotionEvent_Pointer_AxisValue_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidMotionEvent_Pointer_AxisValue_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidMotionEvent_Pointer_AxisValue_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidMotionEvent_Pointer_AxisValue_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_axis() const { return at<1>().valid(); }
+ int32_t axis() const { return at<1>().as_int32(); }
+ bool has_value() const { return at<2>().valid(); }
+ float value() const { return at<2>().as_float(); }
+};
+
+class AndroidMotionEvent_Pointer_AxisValue : public ::protozero::Message {
+ public:
+ using Decoder = AndroidMotionEvent_Pointer_AxisValue_Decoder;
+ enum : int32_t {
+ kAxisFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidMotionEvent.Pointer.AxisValue"; }
+
+
+ using FieldMetadata_Axis =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidMotionEvent_Pointer_AxisValue>;
+
+ static constexpr FieldMetadata_Axis kAxis{};
+ void set_axis(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Axis::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidMotionEvent_Pointer_AxisValue>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/android_log.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_LOG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_LOG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidLogPacket_LogEvent;
+class AndroidLogPacket_LogEvent_Arg;
+class AndroidLogPacket_Stats;
+enum AndroidLogId : int32_t;
+enum AndroidLogPriority : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidLogPacket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidLogPacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidLogPacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidLogPacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_events() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> events() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_stats() const { return at<2>().valid(); }
+ ::protozero::ConstBytes stats() const { return at<2>().as_bytes(); }
+};
+
+class AndroidLogPacket : public ::protozero::Message {
+ public:
+ using Decoder = AndroidLogPacket_Decoder;
+ enum : int32_t {
+ kEventsFieldNumber = 1,
+ kStatsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidLogPacket"; }
+
+ using LogEvent = ::perfetto::protos::pbzero::AndroidLogPacket_LogEvent;
+ using Stats = ::perfetto::protos::pbzero::AndroidLogPacket_Stats;
+
+ using FieldMetadata_Events =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidLogPacket_LogEvent,
+ AndroidLogPacket>;
+
+ static constexpr FieldMetadata_Events kEvents{};
+ template <typename T = AndroidLogPacket_LogEvent> T* add_events() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Stats =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidLogPacket_Stats,
+ AndroidLogPacket>;
+
+ static constexpr FieldMetadata_Stats kStats{};
+ template <typename T = AndroidLogPacket_Stats> T* set_stats() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class AndroidLogPacket_Stats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidLogPacket_Stats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidLogPacket_Stats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidLogPacket_Stats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_num_total() const { return at<1>().valid(); }
+ uint64_t num_total() const { return at<1>().as_uint64(); }
+ bool has_num_failed() const { return at<2>().valid(); }
+ uint64_t num_failed() const { return at<2>().as_uint64(); }
+ bool has_num_skipped() const { return at<3>().valid(); }
+ uint64_t num_skipped() const { return at<3>().as_uint64(); }
+};
+
+class AndroidLogPacket_Stats : public ::protozero::Message {
+ public:
+ using Decoder = AndroidLogPacket_Stats_Decoder;
+ enum : int32_t {
+ kNumTotalFieldNumber = 1,
+ kNumFailedFieldNumber = 2,
+ kNumSkippedFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidLogPacket.Stats"; }
+
+
+ using FieldMetadata_NumTotal =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidLogPacket_Stats>;
+
+ static constexpr FieldMetadata_NumTotal kNumTotal{};
+ void set_num_total(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumTotal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidLogPacket_Stats>;
+
+ static constexpr FieldMetadata_NumFailed kNumFailed{};
+ void set_num_failed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumSkipped =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidLogPacket_Stats>;
+
+ static constexpr FieldMetadata_NumSkipped kNumSkipped{};
+ void set_num_skipped(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumSkipped::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidLogPacket_LogEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidLogPacket_LogEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidLogPacket_LogEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidLogPacket_LogEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_log_id() const { return at<1>().valid(); }
+ int32_t log_id() const { return at<1>().as_int32(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_tid() const { return at<3>().valid(); }
+ int32_t tid() const { return at<3>().as_int32(); }
+ bool has_uid() const { return at<4>().valid(); }
+ int32_t uid() const { return at<4>().as_int32(); }
+ bool has_timestamp() const { return at<5>().valid(); }
+ uint64_t timestamp() const { return at<5>().as_uint64(); }
+ bool has_tag() const { return at<6>().valid(); }
+ ::protozero::ConstChars tag() const { return at<6>().as_string(); }
+ bool has_prio() const { return at<7>().valid(); }
+ int32_t prio() const { return at<7>().as_int32(); }
+ bool has_message() const { return at<8>().valid(); }
+ ::protozero::ConstChars message() const { return at<8>().as_string(); }
+ bool has_args() const { return at<9>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> args() const { return GetRepeated<::protozero::ConstBytes>(9); }
+};
+
+class AndroidLogPacket_LogEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidLogPacket_LogEvent_Decoder;
+ enum : int32_t {
+ kLogIdFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTidFieldNumber = 3,
+ kUidFieldNumber = 4,
+ kTimestampFieldNumber = 5,
+ kTagFieldNumber = 6,
+ kPrioFieldNumber = 7,
+ kMessageFieldNumber = 8,
+ kArgsFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidLogPacket.LogEvent"; }
+
+ using Arg = ::perfetto::protos::pbzero::AndroidLogPacket_LogEvent_Arg;
+
+ using FieldMetadata_LogId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidLogId,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_LogId kLogId{};
+ void set_log_id(AndroidLogId value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, data, size);
+ }
+ void set_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, chars.data, chars.size);
+ }
+ void set_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidLogPriority,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(AndroidLogPriority value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Message =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Message kMessage{};
+ void set_message(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Message::kFieldId, data, size);
+ }
+ void set_message(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Message::kFieldId, chars.data, chars.size);
+ }
+ void set_message(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Message::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Args =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidLogPacket_LogEvent_Arg,
+ AndroidLogPacket_LogEvent>;
+
+ static constexpr FieldMetadata_Args kArgs{};
+ template <typename T = AndroidLogPacket_LogEvent_Arg> T* add_args() {
+ return BeginNestedMessage<T>(9);
+ }
+
+};
+
+class AndroidLogPacket_LogEvent_Arg_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidLogPacket_LogEvent_Arg_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidLogPacket_LogEvent_Arg_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidLogPacket_LogEvent_Arg_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_int_value() const { return at<2>().valid(); }
+ int64_t int_value() const { return at<2>().as_int64(); }
+ bool has_float_value() const { return at<3>().valid(); }
+ float float_value() const { return at<3>().as_float(); }
+ bool has_string_value() const { return at<4>().valid(); }
+ ::protozero::ConstChars string_value() const { return at<4>().as_string(); }
+};
+
+class AndroidLogPacket_LogEvent_Arg : public ::protozero::Message {
+ public:
+ using Decoder = AndroidLogPacket_LogEvent_Arg_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kIntValueFieldNumber = 2,
+ kFloatValueFieldNumber = 3,
+ kStringValueFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidLogPacket.LogEvent.Arg"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidLogPacket_LogEvent_Arg>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidLogPacket_LogEvent_Arg>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FloatValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ AndroidLogPacket_LogEvent_Arg>;
+
+ static constexpr FieldMetadata_FloatValue kFloatValue{};
+ void set_float_value(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_FloatValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidLogPacket_LogEvent_Arg>;
+
+ static constexpr FieldMetadata_StringValue kStringValue{};
+ void set_string_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, data, size);
+ }
+ void set_string_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, chars.data, chars.size);
+ }
+ void set_string_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/android_system_property.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_SYSTEM_PROPERTY_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_ANDROID_SYSTEM_PROPERTY_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidSystemProperty_PropertyValue;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidSystemProperty_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidSystemProperty_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidSystemProperty_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidSystemProperty_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_values() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> values() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class AndroidSystemProperty : public ::protozero::Message {
+ public:
+ using Decoder = AndroidSystemProperty_Decoder;
+ enum : int32_t {
+ kValuesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidSystemProperty"; }
+
+ using PropertyValue = ::perfetto::protos::pbzero::AndroidSystemProperty_PropertyValue;
+
+ using FieldMetadata_Values =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidSystemProperty_PropertyValue,
+ AndroidSystemProperty>;
+
+ static constexpr FieldMetadata_Values kValues{};
+ template <typename T = AndroidSystemProperty_PropertyValue> T* add_values() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class AndroidSystemProperty_PropertyValue_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidSystemProperty_PropertyValue_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidSystemProperty_PropertyValue_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidSystemProperty_PropertyValue_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class AndroidSystemProperty_PropertyValue : public ::protozero::Message {
+ public:
+ using Decoder = AndroidSystemProperty_PropertyValue_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidSystemProperty.PropertyValue"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidSystemProperty_PropertyValue>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidSystemProperty_PropertyValue>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/camera_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_CAMERA_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_CAMERA_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidCameraFrameEvent_CameraNodeProcessingDetails;
+class AndroidCameraSessionStats_CameraGraph;
+class AndroidCameraSessionStats_CameraGraph_CameraEdge;
+class AndroidCameraSessionStats_CameraGraph_CameraNode;
+namespace perfetto_pbzero_enum_AndroidCameraFrameEvent {
+enum CaptureResultStatus : int32_t;
+} // namespace perfetto_pbzero_enum_AndroidCameraFrameEvent
+using AndroidCameraFrameEvent_CaptureResultStatus = perfetto_pbzero_enum_AndroidCameraFrameEvent::CaptureResultStatus;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_AndroidCameraFrameEvent {
+enum CaptureResultStatus : int32_t {
+ STATUS_UNSPECIFIED = 0,
+ STATUS_OK = 1,
+ STATUS_EARLY_METADATA_ERROR = 2,
+ STATUS_FINAL_METADATA_ERROR = 3,
+ STATUS_BUFFER_ERROR = 4,
+ STATUS_FLUSH_ERROR = 5,
+};
+} // namespace perfetto_pbzero_enum_AndroidCameraFrameEvent
+using AndroidCameraFrameEvent_CaptureResultStatus = perfetto_pbzero_enum_AndroidCameraFrameEvent::CaptureResultStatus;
+
+
+constexpr AndroidCameraFrameEvent_CaptureResultStatus AndroidCameraFrameEvent_CaptureResultStatus_MIN = AndroidCameraFrameEvent_CaptureResultStatus::STATUS_UNSPECIFIED;
+constexpr AndroidCameraFrameEvent_CaptureResultStatus AndroidCameraFrameEvent_CaptureResultStatus_MAX = AndroidCameraFrameEvent_CaptureResultStatus::STATUS_FLUSH_ERROR;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* AndroidCameraFrameEvent_CaptureResultStatus_Name(::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus::STATUS_UNSPECIFIED:
+ return "STATUS_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus::STATUS_OK:
+ return "STATUS_OK";
+
+ case ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus::STATUS_EARLY_METADATA_ERROR:
+ return "STATUS_EARLY_METADATA_ERROR";
+
+ case ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus::STATUS_FINAL_METADATA_ERROR:
+ return "STATUS_FINAL_METADATA_ERROR";
+
+ case ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus::STATUS_BUFFER_ERROR:
+ return "STATUS_BUFFER_ERROR";
+
+ case ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus::STATUS_FLUSH_ERROR:
+ return "STATUS_FLUSH_ERROR";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class AndroidCameraSessionStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidCameraSessionStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidCameraSessionStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidCameraSessionStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_session_id() const { return at<1>().valid(); }
+ uint64_t session_id() const { return at<1>().as_uint64(); }
+ bool has_graph() const { return at<2>().valid(); }
+ ::protozero::ConstBytes graph() const { return at<2>().as_bytes(); }
+};
+
+class AndroidCameraSessionStats : public ::protozero::Message {
+ public:
+ using Decoder = AndroidCameraSessionStats_Decoder;
+ enum : int32_t {
+ kSessionIdFieldNumber = 1,
+ kGraphFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidCameraSessionStats"; }
+
+ using CameraGraph = ::perfetto::protos::pbzero::AndroidCameraSessionStats_CameraGraph;
+
+ using FieldMetadata_SessionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidCameraSessionStats>;
+
+ static constexpr FieldMetadata_SessionId kSessionId{};
+ void set_session_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SessionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Graph =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidCameraSessionStats_CameraGraph,
+ AndroidCameraSessionStats>;
+
+ static constexpr FieldMetadata_Graph kGraph{};
+ template <typename T = AndroidCameraSessionStats_CameraGraph> T* set_graph() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class AndroidCameraSessionStats_CameraGraph_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidCameraSessionStats_CameraGraph_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidCameraSessionStats_CameraGraph_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidCameraSessionStats_CameraGraph_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nodes() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> nodes() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_edges() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> edges() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class AndroidCameraSessionStats_CameraGraph : public ::protozero::Message {
+ public:
+ using Decoder = AndroidCameraSessionStats_CameraGraph_Decoder;
+ enum : int32_t {
+ kNodesFieldNumber = 1,
+ kEdgesFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidCameraSessionStats.CameraGraph"; }
+
+ using CameraNode = ::perfetto::protos::pbzero::AndroidCameraSessionStats_CameraGraph_CameraNode;
+ using CameraEdge = ::perfetto::protos::pbzero::AndroidCameraSessionStats_CameraGraph_CameraEdge;
+
+ using FieldMetadata_Nodes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidCameraSessionStats_CameraGraph_CameraNode,
+ AndroidCameraSessionStats_CameraGraph>;
+
+ static constexpr FieldMetadata_Nodes kNodes{};
+ template <typename T = AndroidCameraSessionStats_CameraGraph_CameraNode> T* add_nodes() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Edges =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidCameraSessionStats_CameraGraph_CameraEdge,
+ AndroidCameraSessionStats_CameraGraph>;
+
+ static constexpr FieldMetadata_Edges kEdges{};
+ template <typename T = AndroidCameraSessionStats_CameraGraph_CameraEdge> T* add_edges() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class AndroidCameraSessionStats_CameraGraph_CameraEdge_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidCameraSessionStats_CameraGraph_CameraEdge_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidCameraSessionStats_CameraGraph_CameraEdge_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidCameraSessionStats_CameraGraph_CameraEdge_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_output_node_id() const { return at<1>().valid(); }
+ int64_t output_node_id() const { return at<1>().as_int64(); }
+ bool has_output_id() const { return at<2>().valid(); }
+ int64_t output_id() const { return at<2>().as_int64(); }
+ bool has_input_node_id() const { return at<3>().valid(); }
+ int64_t input_node_id() const { return at<3>().as_int64(); }
+ bool has_input_id() const { return at<4>().valid(); }
+ int64_t input_id() const { return at<4>().as_int64(); }
+ bool has_vendor_data_version() const { return at<5>().valid(); }
+ int32_t vendor_data_version() const { return at<5>().as_int32(); }
+ bool has_vendor_data() const { return at<6>().valid(); }
+ ::protozero::ConstBytes vendor_data() const { return at<6>().as_bytes(); }
+};
+
+class AndroidCameraSessionStats_CameraGraph_CameraEdge : public ::protozero::Message {
+ public:
+ using Decoder = AndroidCameraSessionStats_CameraGraph_CameraEdge_Decoder;
+ enum : int32_t {
+ kOutputNodeIdFieldNumber = 1,
+ kOutputIdFieldNumber = 2,
+ kInputNodeIdFieldNumber = 3,
+ kInputIdFieldNumber = 4,
+ kVendorDataVersionFieldNumber = 5,
+ kVendorDataFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidCameraSessionStats.CameraGraph.CameraEdge"; }
+
+
+ using FieldMetadata_OutputNodeId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraSessionStats_CameraGraph_CameraEdge>;
+
+ static constexpr FieldMetadata_OutputNodeId kOutputNodeId{};
+ void set_output_node_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OutputNodeId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OutputId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraSessionStats_CameraGraph_CameraEdge>;
+
+ static constexpr FieldMetadata_OutputId kOutputId{};
+ void set_output_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OutputId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InputNodeId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraSessionStats_CameraGraph_CameraEdge>;
+
+ static constexpr FieldMetadata_InputNodeId kInputNodeId{};
+ void set_input_node_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputNodeId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InputId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraSessionStats_CameraGraph_CameraEdge>;
+
+ static constexpr FieldMetadata_InputId kInputId{};
+ void set_input_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VendorDataVersion =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidCameraSessionStats_CameraGraph_CameraEdge>;
+
+ static constexpr FieldMetadata_VendorDataVersion kVendorDataVersion{};
+ void set_vendor_data_version(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VendorDataVersion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VendorData =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ AndroidCameraSessionStats_CameraGraph_CameraEdge>;
+
+ static constexpr FieldMetadata_VendorData kVendorData{};
+ void set_vendor_data(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_VendorData::kFieldId, data, size);
+ }
+ void set_vendor_data(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_VendorData::kFieldId, bytes.data, bytes.size);
+ }
+ void set_vendor_data(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_VendorData::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidCameraSessionStats_CameraGraph_CameraNode_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidCameraSessionStats_CameraGraph_CameraNode_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidCameraSessionStats_CameraGraph_CameraNode_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidCameraSessionStats_CameraGraph_CameraNode_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_node_id() const { return at<1>().valid(); }
+ int64_t node_id() const { return at<1>().as_int64(); }
+ bool has_input_ids() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int64_t> input_ids() const { return GetRepeated<int64_t>(2); }
+ bool has_output_ids() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<int64_t> output_ids() const { return GetRepeated<int64_t>(3); }
+ bool has_vendor_data_version() const { return at<4>().valid(); }
+ int32_t vendor_data_version() const { return at<4>().as_int32(); }
+ bool has_vendor_data() const { return at<5>().valid(); }
+ ::protozero::ConstBytes vendor_data() const { return at<5>().as_bytes(); }
+};
+
+class AndroidCameraSessionStats_CameraGraph_CameraNode : public ::protozero::Message {
+ public:
+ using Decoder = AndroidCameraSessionStats_CameraGraph_CameraNode_Decoder;
+ enum : int32_t {
+ kNodeIdFieldNumber = 1,
+ kInputIdsFieldNumber = 2,
+ kOutputIdsFieldNumber = 3,
+ kVendorDataVersionFieldNumber = 4,
+ kVendorDataFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidCameraSessionStats.CameraGraph.CameraNode"; }
+
+
+ using FieldMetadata_NodeId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraSessionStats_CameraGraph_CameraNode>;
+
+ static constexpr FieldMetadata_NodeId kNodeId{};
+ void set_node_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NodeId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InputIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraSessionStats_CameraGraph_CameraNode>;
+
+ static constexpr FieldMetadata_InputIds kInputIds{};
+ void add_input_ids(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OutputIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraSessionStats_CameraGraph_CameraNode>;
+
+ static constexpr FieldMetadata_OutputIds kOutputIds{};
+ void add_output_ids(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OutputIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VendorDataVersion =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidCameraSessionStats_CameraGraph_CameraNode>;
+
+ static constexpr FieldMetadata_VendorDataVersion kVendorDataVersion{};
+ void set_vendor_data_version(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VendorDataVersion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VendorData =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ AndroidCameraSessionStats_CameraGraph_CameraNode>;
+
+ static constexpr FieldMetadata_VendorData kVendorData{};
+ void set_vendor_data(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_VendorData::kFieldId, data, size);
+ }
+ void set_vendor_data(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_VendorData::kFieldId, bytes.data, bytes.size);
+ }
+ void set_vendor_data(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_VendorData::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidCameraFrameEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/16, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidCameraFrameEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidCameraFrameEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidCameraFrameEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_session_id() const { return at<1>().valid(); }
+ uint64_t session_id() const { return at<1>().as_uint64(); }
+ bool has_camera_id() const { return at<2>().valid(); }
+ uint32_t camera_id() const { return at<2>().as_uint32(); }
+ bool has_frame_number() const { return at<3>().valid(); }
+ int64_t frame_number() const { return at<3>().as_int64(); }
+ bool has_request_id() const { return at<4>().valid(); }
+ int64_t request_id() const { return at<4>().as_int64(); }
+ bool has_request_received_ns() const { return at<5>().valid(); }
+ int64_t request_received_ns() const { return at<5>().as_int64(); }
+ bool has_request_processing_started_ns() const { return at<6>().valid(); }
+ int64_t request_processing_started_ns() const { return at<6>().as_int64(); }
+ bool has_start_of_exposure_ns() const { return at<7>().valid(); }
+ int64_t start_of_exposure_ns() const { return at<7>().as_int64(); }
+ bool has_start_of_frame_ns() const { return at<8>().valid(); }
+ int64_t start_of_frame_ns() const { return at<8>().as_int64(); }
+ bool has_responses_all_sent_ns() const { return at<9>().valid(); }
+ int64_t responses_all_sent_ns() const { return at<9>().as_int64(); }
+ bool has_capture_result_status() const { return at<10>().valid(); }
+ int32_t capture_result_status() const { return at<10>().as_int32(); }
+ bool has_skipped_sensor_frames() const { return at<11>().valid(); }
+ int32_t skipped_sensor_frames() const { return at<11>().as_int32(); }
+ bool has_capture_intent() const { return at<12>().valid(); }
+ int32_t capture_intent() const { return at<12>().as_int32(); }
+ bool has_num_streams() const { return at<13>().valid(); }
+ int32_t num_streams() const { return at<13>().as_int32(); }
+ bool has_node_processing_details() const { return at<14>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> node_processing_details() const { return GetRepeated<::protozero::ConstBytes>(14); }
+ bool has_vendor_data_version() const { return at<15>().valid(); }
+ int32_t vendor_data_version() const { return at<15>().as_int32(); }
+ bool has_vendor_data() const { return at<16>().valid(); }
+ ::protozero::ConstBytes vendor_data() const { return at<16>().as_bytes(); }
+};
+
+class AndroidCameraFrameEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidCameraFrameEvent_Decoder;
+ enum : int32_t {
+ kSessionIdFieldNumber = 1,
+ kCameraIdFieldNumber = 2,
+ kFrameNumberFieldNumber = 3,
+ kRequestIdFieldNumber = 4,
+ kRequestReceivedNsFieldNumber = 5,
+ kRequestProcessingStartedNsFieldNumber = 6,
+ kStartOfExposureNsFieldNumber = 7,
+ kStartOfFrameNsFieldNumber = 8,
+ kResponsesAllSentNsFieldNumber = 9,
+ kCaptureResultStatusFieldNumber = 10,
+ kSkippedSensorFramesFieldNumber = 11,
+ kCaptureIntentFieldNumber = 12,
+ kNumStreamsFieldNumber = 13,
+ kNodeProcessingDetailsFieldNumber = 14,
+ kVendorDataVersionFieldNumber = 15,
+ kVendorDataFieldNumber = 16,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidCameraFrameEvent"; }
+
+ using CameraNodeProcessingDetails = ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CameraNodeProcessingDetails;
+
+ using CaptureResultStatus = ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus;
+ static inline const char* CaptureResultStatus_Name(CaptureResultStatus value) {
+ return ::perfetto::protos::pbzero::AndroidCameraFrameEvent_CaptureResultStatus_Name(value);
+ }
+ static inline const CaptureResultStatus STATUS_UNSPECIFIED = CaptureResultStatus::STATUS_UNSPECIFIED;
+ static inline const CaptureResultStatus STATUS_OK = CaptureResultStatus::STATUS_OK;
+ static inline const CaptureResultStatus STATUS_EARLY_METADATA_ERROR = CaptureResultStatus::STATUS_EARLY_METADATA_ERROR;
+ static inline const CaptureResultStatus STATUS_FINAL_METADATA_ERROR = CaptureResultStatus::STATUS_FINAL_METADATA_ERROR;
+ static inline const CaptureResultStatus STATUS_BUFFER_ERROR = CaptureResultStatus::STATUS_BUFFER_ERROR;
+ static inline const CaptureResultStatus STATUS_FLUSH_ERROR = CaptureResultStatus::STATUS_FLUSH_ERROR;
+
+ using FieldMetadata_SessionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_SessionId kSessionId{};
+ void set_session_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SessionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CameraId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_CameraId kCameraId{};
+ void set_camera_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CameraId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_FrameNumber kFrameNumber{};
+ void set_frame_number(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RequestId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_RequestId kRequestId{};
+ void set_request_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RequestId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RequestReceivedNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_RequestReceivedNs kRequestReceivedNs{};
+ void set_request_received_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RequestReceivedNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RequestProcessingStartedNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_RequestProcessingStartedNs kRequestProcessingStartedNs{};
+ void set_request_processing_started_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RequestProcessingStartedNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartOfExposureNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_StartOfExposureNs kStartOfExposureNs{};
+ void set_start_of_exposure_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartOfExposureNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartOfFrameNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_StartOfFrameNs kStartOfFrameNs{};
+ void set_start_of_frame_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartOfFrameNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResponsesAllSentNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_ResponsesAllSentNs kResponsesAllSentNs{};
+ void set_responses_all_sent_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResponsesAllSentNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CaptureResultStatus =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ AndroidCameraFrameEvent_CaptureResultStatus,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_CaptureResultStatus kCaptureResultStatus{};
+ void set_capture_result_status(AndroidCameraFrameEvent_CaptureResultStatus value) {
+ static constexpr uint32_t field_id = FieldMetadata_CaptureResultStatus::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkippedSensorFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_SkippedSensorFrames kSkippedSensorFrames{};
+ void set_skipped_sensor_frames(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkippedSensorFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CaptureIntent =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_CaptureIntent kCaptureIntent{};
+ void set_capture_intent(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CaptureIntent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumStreams =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_NumStreams kNumStreams{};
+ void set_num_streams(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumStreams::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NodeProcessingDetails =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidCameraFrameEvent_CameraNodeProcessingDetails,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_NodeProcessingDetails kNodeProcessingDetails{};
+ template <typename T = AndroidCameraFrameEvent_CameraNodeProcessingDetails> T* add_node_processing_details() {
+ return BeginNestedMessage<T>(14);
+ }
+
+
+ using FieldMetadata_VendorDataVersion =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_VendorDataVersion kVendorDataVersion{};
+ void set_vendor_data_version(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VendorDataVersion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VendorData =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ AndroidCameraFrameEvent>;
+
+ static constexpr FieldMetadata_VendorData kVendorData{};
+ void set_vendor_data(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_VendorData::kFieldId, data, size);
+ }
+ void set_vendor_data(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_VendorData::kFieldId, bytes.data, bytes.size);
+ }
+ void set_vendor_data(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_VendorData::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidCameraFrameEvent_CameraNodeProcessingDetails_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidCameraFrameEvent_CameraNodeProcessingDetails_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidCameraFrameEvent_CameraNodeProcessingDetails_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidCameraFrameEvent_CameraNodeProcessingDetails_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_node_id() const { return at<1>().valid(); }
+ int64_t node_id() const { return at<1>().as_int64(); }
+ bool has_start_processing_ns() const { return at<2>().valid(); }
+ int64_t start_processing_ns() const { return at<2>().as_int64(); }
+ bool has_end_processing_ns() const { return at<3>().valid(); }
+ int64_t end_processing_ns() const { return at<3>().as_int64(); }
+ bool has_scheduling_latency_ns() const { return at<4>().valid(); }
+ int64_t scheduling_latency_ns() const { return at<4>().as_int64(); }
+};
+
+class AndroidCameraFrameEvent_CameraNodeProcessingDetails : public ::protozero::Message {
+ public:
+ using Decoder = AndroidCameraFrameEvent_CameraNodeProcessingDetails_Decoder;
+ enum : int32_t {
+ kNodeIdFieldNumber = 1,
+ kStartProcessingNsFieldNumber = 2,
+ kEndProcessingNsFieldNumber = 3,
+ kSchedulingLatencyNsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidCameraFrameEvent.CameraNodeProcessingDetails"; }
+
+
+ using FieldMetadata_NodeId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent_CameraNodeProcessingDetails>;
+
+ static constexpr FieldMetadata_NodeId kNodeId{};
+ void set_node_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NodeId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartProcessingNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent_CameraNodeProcessingDetails>;
+
+ static constexpr FieldMetadata_StartProcessingNs kStartProcessingNs{};
+ void set_start_processing_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartProcessingNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EndProcessingNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent_CameraNodeProcessingDetails>;
+
+ static constexpr FieldMetadata_EndProcessingNs kEndProcessingNs{};
+ void set_end_processing_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EndProcessingNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SchedulingLatencyNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidCameraFrameEvent_CameraNodeProcessingDetails>;
+
+ static constexpr FieldMetadata_SchedulingLatencyNs kSchedulingLatencyNs{};
+ void set_scheduling_latency_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SchedulingLatencyNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/frame_timeline_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_FRAME_TIMELINE_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_FRAME_TIMELINE_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FrameTimelineEvent_ActualDisplayFrameStart;
+class FrameTimelineEvent_ActualSurfaceFrameStart;
+class FrameTimelineEvent_ExpectedDisplayFrameStart;
+class FrameTimelineEvent_ExpectedSurfaceFrameStart;
+class FrameTimelineEvent_FrameEnd;
+namespace perfetto_pbzero_enum_FrameTimelineEvent {
+enum JankSeverityType : int32_t;
+} // namespace perfetto_pbzero_enum_FrameTimelineEvent
+using FrameTimelineEvent_JankSeverityType = perfetto_pbzero_enum_FrameTimelineEvent::JankSeverityType;
+namespace perfetto_pbzero_enum_FrameTimelineEvent {
+enum PredictionType : int32_t;
+} // namespace perfetto_pbzero_enum_FrameTimelineEvent
+using FrameTimelineEvent_PredictionType = perfetto_pbzero_enum_FrameTimelineEvent::PredictionType;
+namespace perfetto_pbzero_enum_FrameTimelineEvent {
+enum PresentType : int32_t;
+} // namespace perfetto_pbzero_enum_FrameTimelineEvent
+using FrameTimelineEvent_PresentType = perfetto_pbzero_enum_FrameTimelineEvent::PresentType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_FrameTimelineEvent {
+enum JankType : int32_t {
+ JANK_UNSPECIFIED = 0,
+ JANK_NONE = 1,
+ JANK_SF_SCHEDULING = 2,
+ JANK_PREDICTION_ERROR = 4,
+ JANK_DISPLAY_HAL = 8,
+ JANK_SF_CPU_DEADLINE_MISSED = 16,
+ JANK_SF_GPU_DEADLINE_MISSED = 32,
+ JANK_APP_DEADLINE_MISSED = 64,
+ JANK_BUFFER_STUFFING = 128,
+ JANK_UNKNOWN = 256,
+ JANK_SF_STUFFING = 512,
+ JANK_DROPPED = 1024,
+};
+} // namespace perfetto_pbzero_enum_FrameTimelineEvent
+using FrameTimelineEvent_JankType = perfetto_pbzero_enum_FrameTimelineEvent::JankType;
+
+
+constexpr FrameTimelineEvent_JankType FrameTimelineEvent_JankType_MIN = FrameTimelineEvent_JankType::JANK_UNSPECIFIED;
+constexpr FrameTimelineEvent_JankType FrameTimelineEvent_JankType_MAX = FrameTimelineEvent_JankType::JANK_DROPPED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FrameTimelineEvent_JankType_Name(::perfetto::protos::pbzero::FrameTimelineEvent_JankType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_UNSPECIFIED:
+ return "JANK_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_NONE:
+ return "JANK_NONE";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_SF_SCHEDULING:
+ return "JANK_SF_SCHEDULING";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_PREDICTION_ERROR:
+ return "JANK_PREDICTION_ERROR";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_DISPLAY_HAL:
+ return "JANK_DISPLAY_HAL";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_SF_CPU_DEADLINE_MISSED:
+ return "JANK_SF_CPU_DEADLINE_MISSED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_SF_GPU_DEADLINE_MISSED:
+ return "JANK_SF_GPU_DEADLINE_MISSED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_APP_DEADLINE_MISSED:
+ return "JANK_APP_DEADLINE_MISSED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_BUFFER_STUFFING:
+ return "JANK_BUFFER_STUFFING";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_UNKNOWN:
+ return "JANK_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_SF_STUFFING:
+ return "JANK_SF_STUFFING";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankType::JANK_DROPPED:
+ return "JANK_DROPPED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_FrameTimelineEvent {
+enum JankSeverityType : int32_t {
+ SEVERITY_UNKNOWN = 0,
+ SEVERITY_NONE = 1,
+ SEVERITY_PARTIAL = 2,
+ SEVERITY_FULL = 3,
+};
+} // namespace perfetto_pbzero_enum_FrameTimelineEvent
+using FrameTimelineEvent_JankSeverityType = perfetto_pbzero_enum_FrameTimelineEvent::JankSeverityType;
+
+
+constexpr FrameTimelineEvent_JankSeverityType FrameTimelineEvent_JankSeverityType_MIN = FrameTimelineEvent_JankSeverityType::SEVERITY_UNKNOWN;
+constexpr FrameTimelineEvent_JankSeverityType FrameTimelineEvent_JankSeverityType_MAX = FrameTimelineEvent_JankSeverityType::SEVERITY_FULL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FrameTimelineEvent_JankSeverityType_Name(::perfetto::protos::pbzero::FrameTimelineEvent_JankSeverityType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankSeverityType::SEVERITY_UNKNOWN:
+ return "SEVERITY_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankSeverityType::SEVERITY_NONE:
+ return "SEVERITY_NONE";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankSeverityType::SEVERITY_PARTIAL:
+ return "SEVERITY_PARTIAL";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_JankSeverityType::SEVERITY_FULL:
+ return "SEVERITY_FULL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_FrameTimelineEvent {
+enum PresentType : int32_t {
+ PRESENT_UNSPECIFIED = 0,
+ PRESENT_ON_TIME = 1,
+ PRESENT_LATE = 2,
+ PRESENT_EARLY = 3,
+ PRESENT_DROPPED = 4,
+ PRESENT_UNKNOWN = 5,
+};
+} // namespace perfetto_pbzero_enum_FrameTimelineEvent
+using FrameTimelineEvent_PresentType = perfetto_pbzero_enum_FrameTimelineEvent::PresentType;
+
+
+constexpr FrameTimelineEvent_PresentType FrameTimelineEvent_PresentType_MIN = FrameTimelineEvent_PresentType::PRESENT_UNSPECIFIED;
+constexpr FrameTimelineEvent_PresentType FrameTimelineEvent_PresentType_MAX = FrameTimelineEvent_PresentType::PRESENT_UNKNOWN;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FrameTimelineEvent_PresentType_Name(::perfetto::protos::pbzero::FrameTimelineEvent_PresentType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType::PRESENT_UNSPECIFIED:
+ return "PRESENT_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType::PRESENT_ON_TIME:
+ return "PRESENT_ON_TIME";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType::PRESENT_LATE:
+ return "PRESENT_LATE";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType::PRESENT_EARLY:
+ return "PRESENT_EARLY";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType::PRESENT_DROPPED:
+ return "PRESENT_DROPPED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType::PRESENT_UNKNOWN:
+ return "PRESENT_UNKNOWN";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_FrameTimelineEvent {
+enum PredictionType : int32_t {
+ PREDICTION_UNSPECIFIED = 0,
+ PREDICTION_VALID = 1,
+ PREDICTION_EXPIRED = 2,
+ PREDICTION_UNKNOWN = 3,
+};
+} // namespace perfetto_pbzero_enum_FrameTimelineEvent
+using FrameTimelineEvent_PredictionType = perfetto_pbzero_enum_FrameTimelineEvent::PredictionType;
+
+
+constexpr FrameTimelineEvent_PredictionType FrameTimelineEvent_PredictionType_MIN = FrameTimelineEvent_PredictionType::PREDICTION_UNSPECIFIED;
+constexpr FrameTimelineEvent_PredictionType FrameTimelineEvent_PredictionType_MAX = FrameTimelineEvent_PredictionType::PREDICTION_UNKNOWN;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FrameTimelineEvent_PredictionType_Name(::perfetto::protos::pbzero::FrameTimelineEvent_PredictionType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PredictionType::PREDICTION_UNSPECIFIED:
+ return "PREDICTION_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PredictionType::PREDICTION_VALID:
+ return "PREDICTION_VALID";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PredictionType::PREDICTION_EXPIRED:
+ return "PREDICTION_EXPIRED";
+
+ case ::perfetto::protos::pbzero::FrameTimelineEvent_PredictionType::PREDICTION_UNKNOWN:
+ return "PREDICTION_UNKNOWN";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class FrameTimelineEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FrameTimelineEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FrameTimelineEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FrameTimelineEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_expected_display_frame_start() const { return at<1>().valid(); }
+ ::protozero::ConstBytes expected_display_frame_start() const { return at<1>().as_bytes(); }
+ bool has_actual_display_frame_start() const { return at<2>().valid(); }
+ ::protozero::ConstBytes actual_display_frame_start() const { return at<2>().as_bytes(); }
+ bool has_expected_surface_frame_start() const { return at<3>().valid(); }
+ ::protozero::ConstBytes expected_surface_frame_start() const { return at<3>().as_bytes(); }
+ bool has_actual_surface_frame_start() const { return at<4>().valid(); }
+ ::protozero::ConstBytes actual_surface_frame_start() const { return at<4>().as_bytes(); }
+ bool has_frame_end() const { return at<5>().valid(); }
+ ::protozero::ConstBytes frame_end() const { return at<5>().as_bytes(); }
+};
+
+class FrameTimelineEvent : public ::protozero::Message {
+ public:
+ using Decoder = FrameTimelineEvent_Decoder;
+ enum : int32_t {
+ kExpectedDisplayFrameStartFieldNumber = 1,
+ kActualDisplayFrameStartFieldNumber = 2,
+ kExpectedSurfaceFrameStartFieldNumber = 3,
+ kActualSurfaceFrameStartFieldNumber = 4,
+ kFrameEndFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FrameTimelineEvent"; }
+
+ using ExpectedSurfaceFrameStart = ::perfetto::protos::pbzero::FrameTimelineEvent_ExpectedSurfaceFrameStart;
+ using ActualSurfaceFrameStart = ::perfetto::protos::pbzero::FrameTimelineEvent_ActualSurfaceFrameStart;
+ using ExpectedDisplayFrameStart = ::perfetto::protos::pbzero::FrameTimelineEvent_ExpectedDisplayFrameStart;
+ using ActualDisplayFrameStart = ::perfetto::protos::pbzero::FrameTimelineEvent_ActualDisplayFrameStart;
+ using FrameEnd = ::perfetto::protos::pbzero::FrameTimelineEvent_FrameEnd;
+
+ using JankType = ::perfetto::protos::pbzero::FrameTimelineEvent_JankType;
+ static inline const char* JankType_Name(JankType value) {
+ return ::perfetto::protos::pbzero::FrameTimelineEvent_JankType_Name(value);
+ }
+
+ using JankSeverityType = ::perfetto::protos::pbzero::FrameTimelineEvent_JankSeverityType;
+ static inline const char* JankSeverityType_Name(JankSeverityType value) {
+ return ::perfetto::protos::pbzero::FrameTimelineEvent_JankSeverityType_Name(value);
+ }
+
+ using PresentType = ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType;
+ static inline const char* PresentType_Name(PresentType value) {
+ return ::perfetto::protos::pbzero::FrameTimelineEvent_PresentType_Name(value);
+ }
+
+ using PredictionType = ::perfetto::protos::pbzero::FrameTimelineEvent_PredictionType;
+ static inline const char* PredictionType_Name(PredictionType value) {
+ return ::perfetto::protos::pbzero::FrameTimelineEvent_PredictionType_Name(value);
+ }
+ static inline const JankType JANK_UNSPECIFIED = JankType::JANK_UNSPECIFIED;
+ static inline const JankType JANK_NONE = JankType::JANK_NONE;
+ static inline const JankType JANK_SF_SCHEDULING = JankType::JANK_SF_SCHEDULING;
+ static inline const JankType JANK_PREDICTION_ERROR = JankType::JANK_PREDICTION_ERROR;
+ static inline const JankType JANK_DISPLAY_HAL = JankType::JANK_DISPLAY_HAL;
+ static inline const JankType JANK_SF_CPU_DEADLINE_MISSED = JankType::JANK_SF_CPU_DEADLINE_MISSED;
+ static inline const JankType JANK_SF_GPU_DEADLINE_MISSED = JankType::JANK_SF_GPU_DEADLINE_MISSED;
+ static inline const JankType JANK_APP_DEADLINE_MISSED = JankType::JANK_APP_DEADLINE_MISSED;
+ static inline const JankType JANK_BUFFER_STUFFING = JankType::JANK_BUFFER_STUFFING;
+ static inline const JankType JANK_UNKNOWN = JankType::JANK_UNKNOWN;
+ static inline const JankType JANK_SF_STUFFING = JankType::JANK_SF_STUFFING;
+ static inline const JankType JANK_DROPPED = JankType::JANK_DROPPED;
+ static inline const JankSeverityType SEVERITY_UNKNOWN = JankSeverityType::SEVERITY_UNKNOWN;
+ static inline const JankSeverityType SEVERITY_NONE = JankSeverityType::SEVERITY_NONE;
+ static inline const JankSeverityType SEVERITY_PARTIAL = JankSeverityType::SEVERITY_PARTIAL;
+ static inline const JankSeverityType SEVERITY_FULL = JankSeverityType::SEVERITY_FULL;
+ static inline const PresentType PRESENT_UNSPECIFIED = PresentType::PRESENT_UNSPECIFIED;
+ static inline const PresentType PRESENT_ON_TIME = PresentType::PRESENT_ON_TIME;
+ static inline const PresentType PRESENT_LATE = PresentType::PRESENT_LATE;
+ static inline const PresentType PRESENT_EARLY = PresentType::PRESENT_EARLY;
+ static inline const PresentType PRESENT_DROPPED = PresentType::PRESENT_DROPPED;
+ static inline const PresentType PRESENT_UNKNOWN = PresentType::PRESENT_UNKNOWN;
+ static inline const PredictionType PREDICTION_UNSPECIFIED = PredictionType::PREDICTION_UNSPECIFIED;
+ static inline const PredictionType PREDICTION_VALID = PredictionType::PREDICTION_VALID;
+ static inline const PredictionType PREDICTION_EXPIRED = PredictionType::PREDICTION_EXPIRED;
+ static inline const PredictionType PREDICTION_UNKNOWN = PredictionType::PREDICTION_UNKNOWN;
+
+ using FieldMetadata_ExpectedDisplayFrameStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FrameTimelineEvent_ExpectedDisplayFrameStart,
+ FrameTimelineEvent>;
+
+ static constexpr FieldMetadata_ExpectedDisplayFrameStart kExpectedDisplayFrameStart{};
+ template <typename T = FrameTimelineEvent_ExpectedDisplayFrameStart> T* set_expected_display_frame_start() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ActualDisplayFrameStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FrameTimelineEvent_ActualDisplayFrameStart,
+ FrameTimelineEvent>;
+
+ static constexpr FieldMetadata_ActualDisplayFrameStart kActualDisplayFrameStart{};
+ template <typename T = FrameTimelineEvent_ActualDisplayFrameStart> T* set_actual_display_frame_start() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_ExpectedSurfaceFrameStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FrameTimelineEvent_ExpectedSurfaceFrameStart,
+ FrameTimelineEvent>;
+
+ static constexpr FieldMetadata_ExpectedSurfaceFrameStart kExpectedSurfaceFrameStart{};
+ template <typename T = FrameTimelineEvent_ExpectedSurfaceFrameStart> T* set_expected_surface_frame_start() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_ActualSurfaceFrameStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FrameTimelineEvent_ActualSurfaceFrameStart,
+ FrameTimelineEvent>;
+
+ static constexpr FieldMetadata_ActualSurfaceFrameStart kActualSurfaceFrameStart{};
+ template <typename T = FrameTimelineEvent_ActualSurfaceFrameStart> T* set_actual_surface_frame_start() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_FrameEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FrameTimelineEvent_FrameEnd,
+ FrameTimelineEvent>;
+
+ static constexpr FieldMetadata_FrameEnd kFrameEnd{};
+ template <typename T = FrameTimelineEvent_FrameEnd> T* set_frame_end() {
+ return BeginNestedMessage<T>(5);
+ }
+
+};
+
+class FrameTimelineEvent_FrameEnd_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FrameTimelineEvent_FrameEnd_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FrameTimelineEvent_FrameEnd_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FrameTimelineEvent_FrameEnd_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cookie() const { return at<1>().valid(); }
+ int64_t cookie() const { return at<1>().as_int64(); }
+};
+
+class FrameTimelineEvent_FrameEnd : public ::protozero::Message {
+ public:
+ using Decoder = FrameTimelineEvent_FrameEnd_Decoder;
+ enum : int32_t {
+ kCookieFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FrameTimelineEvent.FrameEnd"; }
+
+
+ using FieldMetadata_Cookie =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_FrameEnd>;
+
+ static constexpr FieldMetadata_Cookie kCookie{};
+ void set_cookie(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cookie::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FrameTimelineEvent_ActualDisplayFrameStart_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FrameTimelineEvent_ActualDisplayFrameStart_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FrameTimelineEvent_ActualDisplayFrameStart_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FrameTimelineEvent_ActualDisplayFrameStart_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cookie() const { return at<1>().valid(); }
+ int64_t cookie() const { return at<1>().as_int64(); }
+ bool has_token() const { return at<2>().valid(); }
+ int64_t token() const { return at<2>().as_int64(); }
+ bool has_pid() const { return at<3>().valid(); }
+ int32_t pid() const { return at<3>().as_int32(); }
+ bool has_present_type() const { return at<4>().valid(); }
+ int32_t present_type() const { return at<4>().as_int32(); }
+ bool has_on_time_finish() const { return at<5>().valid(); }
+ bool on_time_finish() const { return at<5>().as_bool(); }
+ bool has_gpu_composition() const { return at<6>().valid(); }
+ bool gpu_composition() const { return at<6>().as_bool(); }
+ bool has_jank_type() const { return at<7>().valid(); }
+ int32_t jank_type() const { return at<7>().as_int32(); }
+ bool has_prediction_type() const { return at<8>().valid(); }
+ int32_t prediction_type() const { return at<8>().as_int32(); }
+ bool has_jank_severity_type() const { return at<9>().valid(); }
+ int32_t jank_severity_type() const { return at<9>().as_int32(); }
+};
+
+class FrameTimelineEvent_ActualDisplayFrameStart : public ::protozero::Message {
+ public:
+ using Decoder = FrameTimelineEvent_ActualDisplayFrameStart_Decoder;
+ enum : int32_t {
+ kCookieFieldNumber = 1,
+ kTokenFieldNumber = 2,
+ kPidFieldNumber = 3,
+ kPresentTypeFieldNumber = 4,
+ kOnTimeFinishFieldNumber = 5,
+ kGpuCompositionFieldNumber = 6,
+ kJankTypeFieldNumber = 7,
+ kPredictionTypeFieldNumber = 8,
+ kJankSeverityTypeFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FrameTimelineEvent.ActualDisplayFrameStart"; }
+
+
+ using FieldMetadata_Cookie =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_Cookie kCookie{};
+ void set_cookie(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cookie::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Token =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_Token kToken{};
+ void set_token(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Token::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PresentType =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FrameTimelineEvent_PresentType,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_PresentType kPresentType{};
+ void set_present_type(FrameTimelineEvent_PresentType value) {
+ static constexpr uint32_t field_id = FieldMetadata_PresentType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OnTimeFinish =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_OnTimeFinish kOnTimeFinish{};
+ void set_on_time_finish(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_OnTimeFinish::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GpuComposition =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_GpuComposition kGpuComposition{};
+ void set_gpu_composition(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuComposition::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JankType =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_JankType kJankType{};
+ void set_jank_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_JankType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PredictionType =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FrameTimelineEvent_PredictionType,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_PredictionType kPredictionType{};
+ void set_prediction_type(FrameTimelineEvent_PredictionType value) {
+ static constexpr uint32_t field_id = FieldMetadata_PredictionType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JankSeverityType =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FrameTimelineEvent_JankSeverityType,
+ FrameTimelineEvent_ActualDisplayFrameStart>;
+
+ static constexpr FieldMetadata_JankSeverityType kJankSeverityType{};
+ void set_jank_severity_type(FrameTimelineEvent_JankSeverityType value) {
+ static constexpr uint32_t field_id = FieldMetadata_JankSeverityType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FrameTimelineEvent_ExpectedDisplayFrameStart_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FrameTimelineEvent_ExpectedDisplayFrameStart_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FrameTimelineEvent_ExpectedDisplayFrameStart_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FrameTimelineEvent_ExpectedDisplayFrameStart_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cookie() const { return at<1>().valid(); }
+ int64_t cookie() const { return at<1>().as_int64(); }
+ bool has_token() const { return at<2>().valid(); }
+ int64_t token() const { return at<2>().as_int64(); }
+ bool has_pid() const { return at<3>().valid(); }
+ int32_t pid() const { return at<3>().as_int32(); }
+};
+
+class FrameTimelineEvent_ExpectedDisplayFrameStart : public ::protozero::Message {
+ public:
+ using Decoder = FrameTimelineEvent_ExpectedDisplayFrameStart_Decoder;
+ enum : int32_t {
+ kCookieFieldNumber = 1,
+ kTokenFieldNumber = 2,
+ kPidFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FrameTimelineEvent.ExpectedDisplayFrameStart"; }
+
+
+ using FieldMetadata_Cookie =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ExpectedDisplayFrameStart>;
+
+ static constexpr FieldMetadata_Cookie kCookie{};
+ void set_cookie(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cookie::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Token =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ExpectedDisplayFrameStart>;
+
+ static constexpr FieldMetadata_Token kToken{};
+ void set_token(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Token::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FrameTimelineEvent_ExpectedDisplayFrameStart>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FrameTimelineEvent_ActualSurfaceFrameStart_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/12, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FrameTimelineEvent_ActualSurfaceFrameStart_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FrameTimelineEvent_ActualSurfaceFrameStart_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FrameTimelineEvent_ActualSurfaceFrameStart_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cookie() const { return at<1>().valid(); }
+ int64_t cookie() const { return at<1>().as_int64(); }
+ bool has_token() const { return at<2>().valid(); }
+ int64_t token() const { return at<2>().as_int64(); }
+ bool has_display_frame_token() const { return at<3>().valid(); }
+ int64_t display_frame_token() const { return at<3>().as_int64(); }
+ bool has_pid() const { return at<4>().valid(); }
+ int32_t pid() const { return at<4>().as_int32(); }
+ bool has_layer_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars layer_name() const { return at<5>().as_string(); }
+ bool has_present_type() const { return at<6>().valid(); }
+ int32_t present_type() const { return at<6>().as_int32(); }
+ bool has_on_time_finish() const { return at<7>().valid(); }
+ bool on_time_finish() const { return at<7>().as_bool(); }
+ bool has_gpu_composition() const { return at<8>().valid(); }
+ bool gpu_composition() const { return at<8>().as_bool(); }
+ bool has_jank_type() const { return at<9>().valid(); }
+ int32_t jank_type() const { return at<9>().as_int32(); }
+ bool has_prediction_type() const { return at<10>().valid(); }
+ int32_t prediction_type() const { return at<10>().as_int32(); }
+ bool has_is_buffer() const { return at<11>().valid(); }
+ bool is_buffer() const { return at<11>().as_bool(); }
+ bool has_jank_severity_type() const { return at<12>().valid(); }
+ int32_t jank_severity_type() const { return at<12>().as_int32(); }
+};
+
+class FrameTimelineEvent_ActualSurfaceFrameStart : public ::protozero::Message {
+ public:
+ using Decoder = FrameTimelineEvent_ActualSurfaceFrameStart_Decoder;
+ enum : int32_t {
+ kCookieFieldNumber = 1,
+ kTokenFieldNumber = 2,
+ kDisplayFrameTokenFieldNumber = 3,
+ kPidFieldNumber = 4,
+ kLayerNameFieldNumber = 5,
+ kPresentTypeFieldNumber = 6,
+ kOnTimeFinishFieldNumber = 7,
+ kGpuCompositionFieldNumber = 8,
+ kJankTypeFieldNumber = 9,
+ kPredictionTypeFieldNumber = 10,
+ kIsBufferFieldNumber = 11,
+ kJankSeverityTypeFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FrameTimelineEvent.ActualSurfaceFrameStart"; }
+
+
+ using FieldMetadata_Cookie =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_Cookie kCookie{};
+ void set_cookie(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cookie::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Token =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_Token kToken{};
+ void set_token(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Token::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisplayFrameToken =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_DisplayFrameToken kDisplayFrameToken{};
+ void set_display_frame_token(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisplayFrameToken::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_LayerName kLayerName{};
+ void set_layer_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LayerName::kFieldId, data, size);
+ }
+ void set_layer_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LayerName::kFieldId, chars.data, chars.size);
+ }
+ void set_layer_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PresentType =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FrameTimelineEvent_PresentType,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_PresentType kPresentType{};
+ void set_present_type(FrameTimelineEvent_PresentType value) {
+ static constexpr uint32_t field_id = FieldMetadata_PresentType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OnTimeFinish =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_OnTimeFinish kOnTimeFinish{};
+ void set_on_time_finish(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_OnTimeFinish::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GpuComposition =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_GpuComposition kGpuComposition{};
+ void set_gpu_composition(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuComposition::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JankType =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_JankType kJankType{};
+ void set_jank_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_JankType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PredictionType =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FrameTimelineEvent_PredictionType,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_PredictionType kPredictionType{};
+ void set_prediction_type(FrameTimelineEvent_PredictionType value) {
+ static constexpr uint32_t field_id = FieldMetadata_PredictionType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_IsBuffer kIsBuffer{};
+ void set_is_buffer(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsBuffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JankSeverityType =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FrameTimelineEvent_JankSeverityType,
+ FrameTimelineEvent_ActualSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_JankSeverityType kJankSeverityType{};
+ void set_jank_severity_type(FrameTimelineEvent_JankSeverityType value) {
+ static constexpr uint32_t field_id = FieldMetadata_JankSeverityType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FrameTimelineEvent_ExpectedSurfaceFrameStart_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FrameTimelineEvent_ExpectedSurfaceFrameStart_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FrameTimelineEvent_ExpectedSurfaceFrameStart_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FrameTimelineEvent_ExpectedSurfaceFrameStart_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cookie() const { return at<1>().valid(); }
+ int64_t cookie() const { return at<1>().as_int64(); }
+ bool has_token() const { return at<2>().valid(); }
+ int64_t token() const { return at<2>().as_int64(); }
+ bool has_display_frame_token() const { return at<3>().valid(); }
+ int64_t display_frame_token() const { return at<3>().as_int64(); }
+ bool has_pid() const { return at<4>().valid(); }
+ int32_t pid() const { return at<4>().as_int32(); }
+ bool has_layer_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars layer_name() const { return at<5>().as_string(); }
+};
+
+class FrameTimelineEvent_ExpectedSurfaceFrameStart : public ::protozero::Message {
+ public:
+ using Decoder = FrameTimelineEvent_ExpectedSurfaceFrameStart_Decoder;
+ enum : int32_t {
+ kCookieFieldNumber = 1,
+ kTokenFieldNumber = 2,
+ kDisplayFrameTokenFieldNumber = 3,
+ kPidFieldNumber = 4,
+ kLayerNameFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FrameTimelineEvent.ExpectedSurfaceFrameStart"; }
+
+
+ using FieldMetadata_Cookie =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ExpectedSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_Cookie kCookie{};
+ void set_cookie(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cookie::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Token =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ExpectedSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_Token kToken{};
+ void set_token(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Token::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisplayFrameToken =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FrameTimelineEvent_ExpectedSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_DisplayFrameToken kDisplayFrameToken{};
+ void set_display_frame_token(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisplayFrameToken::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FrameTimelineEvent_ExpectedSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FrameTimelineEvent_ExpectedSurfaceFrameStart>;
+
+ static constexpr FieldMetadata_LayerName kLayerName{};
+ void set_layer_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LayerName::kFieldId, data, size);
+ }
+ void set_layer_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LayerName::kFieldId, chars.data, chars.size);
+ }
+ void set_layer_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/gpu_mem_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_GPU_MEM_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_GPU_MEM_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class GpuMemTotalEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuMemTotalEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuMemTotalEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuMemTotalEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gpu_id() const { return at<1>().valid(); }
+ uint32_t gpu_id() const { return at<1>().as_uint32(); }
+ bool has_pid() const { return at<2>().valid(); }
+ uint32_t pid() const { return at<2>().as_uint32(); }
+ bool has_size() const { return at<3>().valid(); }
+ uint64_t size() const { return at<3>().as_uint64(); }
+};
+
+class GpuMemTotalEvent : public ::protozero::Message {
+ public:
+ using Decoder = GpuMemTotalEvent_Decoder;
+ enum : int32_t {
+ kGpuIdFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kSizeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuMemTotalEvent"; }
+
+
+ using FieldMetadata_GpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuMemTotalEvent>;
+
+ static constexpr FieldMetadata_GpuId kGpuId{};
+ void set_gpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuMemTotalEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuMemTotalEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/graphics_frame_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_GRAPHICS_FRAME_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_GRAPHICS_FRAME_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class GraphicsFrameEvent_BufferEvent;
+namespace perfetto_pbzero_enum_GraphicsFrameEvent {
+enum BufferEventType : int32_t;
+} // namespace perfetto_pbzero_enum_GraphicsFrameEvent
+using GraphicsFrameEvent_BufferEventType = perfetto_pbzero_enum_GraphicsFrameEvent::BufferEventType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_GraphicsFrameEvent {
+enum BufferEventType : int32_t {
+ UNSPECIFIED = 0,
+ DEQUEUE = 1,
+ QUEUE = 2,
+ POST = 3,
+ ACQUIRE_FENCE = 4,
+ LATCH = 5,
+ HWC_COMPOSITION_QUEUED = 6,
+ FALLBACK_COMPOSITION = 7,
+ PRESENT_FENCE = 8,
+ RELEASE_FENCE = 9,
+ MODIFY = 10,
+ DETACH = 11,
+ ATTACH = 12,
+ CANCEL = 13,
+};
+} // namespace perfetto_pbzero_enum_GraphicsFrameEvent
+using GraphicsFrameEvent_BufferEventType = perfetto_pbzero_enum_GraphicsFrameEvent::BufferEventType;
+
+
+constexpr GraphicsFrameEvent_BufferEventType GraphicsFrameEvent_BufferEventType_MIN = GraphicsFrameEvent_BufferEventType::UNSPECIFIED;
+constexpr GraphicsFrameEvent_BufferEventType GraphicsFrameEvent_BufferEventType_MAX = GraphicsFrameEvent_BufferEventType::CANCEL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* GraphicsFrameEvent_BufferEventType_Name(::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::UNSPECIFIED:
+ return "UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::DEQUEUE:
+ return "DEQUEUE";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::QUEUE:
+ return "QUEUE";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::POST:
+ return "POST";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::ACQUIRE_FENCE:
+ return "ACQUIRE_FENCE";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::LATCH:
+ return "LATCH";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::HWC_COMPOSITION_QUEUED:
+ return "HWC_COMPOSITION_QUEUED";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::FALLBACK_COMPOSITION:
+ return "FALLBACK_COMPOSITION";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::PRESENT_FENCE:
+ return "PRESENT_FENCE";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::RELEASE_FENCE:
+ return "RELEASE_FENCE";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::MODIFY:
+ return "MODIFY";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::DETACH:
+ return "DETACH";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::ATTACH:
+ return "ATTACH";
+
+ case ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType::CANCEL:
+ return "CANCEL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class GraphicsFrameEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GraphicsFrameEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GraphicsFrameEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GraphicsFrameEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buffer_event() const { return at<1>().valid(); }
+ ::protozero::ConstBytes buffer_event() const { return at<1>().as_bytes(); }
+};
+
+class GraphicsFrameEvent : public ::protozero::Message {
+ public:
+ using Decoder = GraphicsFrameEvent_Decoder;
+ enum : int32_t {
+ kBufferEventFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GraphicsFrameEvent"; }
+
+ using BufferEvent = ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEvent;
+
+ using BufferEventType = ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType;
+ static inline const char* BufferEventType_Name(BufferEventType value) {
+ return ::perfetto::protos::pbzero::GraphicsFrameEvent_BufferEventType_Name(value);
+ }
+ static inline const BufferEventType UNSPECIFIED = BufferEventType::UNSPECIFIED;
+ static inline const BufferEventType DEQUEUE = BufferEventType::DEQUEUE;
+ static inline const BufferEventType QUEUE = BufferEventType::QUEUE;
+ static inline const BufferEventType POST = BufferEventType::POST;
+ static inline const BufferEventType ACQUIRE_FENCE = BufferEventType::ACQUIRE_FENCE;
+ static inline const BufferEventType LATCH = BufferEventType::LATCH;
+ static inline const BufferEventType HWC_COMPOSITION_QUEUED = BufferEventType::HWC_COMPOSITION_QUEUED;
+ static inline const BufferEventType FALLBACK_COMPOSITION = BufferEventType::FALLBACK_COMPOSITION;
+ static inline const BufferEventType PRESENT_FENCE = BufferEventType::PRESENT_FENCE;
+ static inline const BufferEventType RELEASE_FENCE = BufferEventType::RELEASE_FENCE;
+ static inline const BufferEventType MODIFY = BufferEventType::MODIFY;
+ static inline const BufferEventType DETACH = BufferEventType::DETACH;
+ static inline const BufferEventType ATTACH = BufferEventType::ATTACH;
+ static inline const BufferEventType CANCEL = BufferEventType::CANCEL;
+
+ using FieldMetadata_BufferEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GraphicsFrameEvent_BufferEvent,
+ GraphicsFrameEvent>;
+
+ static constexpr FieldMetadata_BufferEvent kBufferEvent{};
+ template <typename T = GraphicsFrameEvent_BufferEvent> T* set_buffer_event() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class GraphicsFrameEvent_BufferEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GraphicsFrameEvent_BufferEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GraphicsFrameEvent_BufferEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GraphicsFrameEvent_BufferEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_frame_number() const { return at<1>().valid(); }
+ uint32_t frame_number() const { return at<1>().as_uint32(); }
+ bool has_type() const { return at<2>().valid(); }
+ int32_t type() const { return at<2>().as_int32(); }
+ bool has_layer_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars layer_name() const { return at<3>().as_string(); }
+ bool has_duration_ns() const { return at<4>().valid(); }
+ uint64_t duration_ns() const { return at<4>().as_uint64(); }
+ bool has_buffer_id() const { return at<5>().valid(); }
+ uint32_t buffer_id() const { return at<5>().as_uint32(); }
+};
+
+class GraphicsFrameEvent_BufferEvent : public ::protozero::Message {
+ public:
+ using Decoder = GraphicsFrameEvent_BufferEvent_Decoder;
+ enum : int32_t {
+ kFrameNumberFieldNumber = 1,
+ kTypeFieldNumber = 2,
+ kLayerNameFieldNumber = 3,
+ kDurationNsFieldNumber = 4,
+ kBufferIdFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GraphicsFrameEvent.BufferEvent"; }
+
+
+ using FieldMetadata_FrameNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GraphicsFrameEvent_BufferEvent>;
+
+ static constexpr FieldMetadata_FrameNumber kFrameNumber{};
+ void set_frame_number(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ GraphicsFrameEvent_BufferEventType,
+ GraphicsFrameEvent_BufferEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(GraphicsFrameEvent_BufferEventType value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GraphicsFrameEvent_BufferEvent>;
+
+ static constexpr FieldMetadata_LayerName kLayerName{};
+ void set_layer_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LayerName::kFieldId, data, size);
+ }
+ void set_layer_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LayerName::kFieldId, chars.data, chars.size);
+ }
+ void set_layer_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DurationNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GraphicsFrameEvent_BufferEvent>;
+
+ static constexpr FieldMetadata_DurationNs kDurationNs{};
+ void set_duration_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DurationNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BufferId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GraphicsFrameEvent_BufferEvent>;
+
+ static constexpr FieldMetadata_BufferId kBufferId{};
+ void set_buffer_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/initial_display_state.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_INITIAL_DISPLAY_STATE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_INITIAL_DISPLAY_STATE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class InitialDisplayState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InitialDisplayState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InitialDisplayState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InitialDisplayState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_display_state() const { return at<1>().valid(); }
+ int32_t display_state() const { return at<1>().as_int32(); }
+ bool has_brightness() const { return at<2>().valid(); }
+ double brightness() const { return at<2>().as_double(); }
+};
+
+class InitialDisplayState : public ::protozero::Message {
+ public:
+ using Decoder = InitialDisplayState_Decoder;
+ enum : int32_t {
+ kDisplayStateFieldNumber = 1,
+ kBrightnessFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InitialDisplayState"; }
+
+
+ using FieldMetadata_DisplayState =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InitialDisplayState>;
+
+ static constexpr FieldMetadata_DisplayState kDisplayState{};
+ void set_display_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisplayState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Brightness =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ InitialDisplayState>;
+
+ static constexpr FieldMetadata_Brightness kBrightness{};
+ void set_brightness(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_Brightness::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/network_trace.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_NETWORK_TRACE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_NETWORK_TRACE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class NetworkPacketEvent;
+enum TrafficDirection : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum TrafficDirection : int32_t {
+ DIR_UNSPECIFIED = 0,
+ DIR_INGRESS = 1,
+ DIR_EGRESS = 2,
+};
+
+constexpr TrafficDirection TrafficDirection_MIN = TrafficDirection::DIR_UNSPECIFIED;
+constexpr TrafficDirection TrafficDirection_MAX = TrafficDirection::DIR_EGRESS;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TrafficDirection_Name(::perfetto::protos::pbzero::TrafficDirection value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TrafficDirection::DIR_UNSPECIFIED:
+ return "DIR_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::TrafficDirection::DIR_INGRESS:
+ return "DIR_INGRESS";
+
+ case ::perfetto::protos::pbzero::TrafficDirection::DIR_EGRESS:
+ return "DIR_EGRESS";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class NetworkPacketContext_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NetworkPacketContext_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NetworkPacketContext_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NetworkPacketContext_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_ctx() const { return at<2>().valid(); }
+ ::protozero::ConstBytes ctx() const { return at<2>().as_bytes(); }
+};
+
+class NetworkPacketContext : public ::protozero::Message {
+ public:
+ using Decoder = NetworkPacketContext_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kCtxFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NetworkPacketContext"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NetworkPacketContext>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetworkPacketEvent,
+ NetworkPacketContext>;
+
+ static constexpr FieldMetadata_Ctx kCtx{};
+ template <typename T = NetworkPacketEvent> T* set_ctx() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class NetworkPacketBundle_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NetworkPacketBundle_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NetworkPacketBundle_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NetworkPacketBundle_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_ctx() const { return at<2>().valid(); }
+ ::protozero::ConstBytes ctx() const { return at<2>().as_bytes(); }
+ bool has_packet_timestamps() const { return at<3>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> packet_timestamps(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(3, parse_error_ptr); }
+ bool has_packet_lengths() const { return at<4>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t> packet_lengths(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t>(4, parse_error_ptr); }
+ bool has_total_packets() const { return at<5>().valid(); }
+ uint32_t total_packets() const { return at<5>().as_uint32(); }
+ bool has_total_duration() const { return at<6>().valid(); }
+ uint64_t total_duration() const { return at<6>().as_uint64(); }
+ bool has_total_length() const { return at<7>().valid(); }
+ uint64_t total_length() const { return at<7>().as_uint64(); }
+};
+
+class NetworkPacketBundle : public ::protozero::Message {
+ public:
+ using Decoder = NetworkPacketBundle_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kCtxFieldNumber = 2,
+ kPacketTimestampsFieldNumber = 3,
+ kPacketLengthsFieldNumber = 4,
+ kTotalPacketsFieldNumber = 5,
+ kTotalDurationFieldNumber = 6,
+ kTotalLengthFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NetworkPacketBundle"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NetworkPacketBundle>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetworkPacketEvent,
+ NetworkPacketBundle>;
+
+ static constexpr FieldMetadata_Ctx kCtx{};
+ template <typename T = NetworkPacketEvent> T* set_ctx() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_PacketTimestamps =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NetworkPacketBundle>;
+
+ static constexpr FieldMetadata_PacketTimestamps kPacketTimestamps{};
+ void set_packet_timestamps(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_PacketTimestamps::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_PacketLengths =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketBundle>;
+
+ static constexpr FieldMetadata_PacketLengths kPacketLengths{};
+ void set_packet_lengths(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_PacketLengths::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_TotalPackets =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketBundle>;
+
+ static constexpr FieldMetadata_TotalPackets kTotalPackets{};
+ void set_total_packets(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalPackets::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalDuration =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NetworkPacketBundle>;
+
+ static constexpr FieldMetadata_TotalDuration kTotalDuration{};
+ void set_total_duration(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalDuration::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalLength =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NetworkPacketBundle>;
+
+ static constexpr FieldMetadata_TotalLength kTotalLength{};
+ void set_total_length(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalLength::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class NetworkPacketEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NetworkPacketEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NetworkPacketEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NetworkPacketEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_direction() const { return at<1>().valid(); }
+ int32_t direction() const { return at<1>().as_int32(); }
+ bool has_interface() const { return at<2>().valid(); }
+ ::protozero::ConstChars interface() const { return at<2>().as_string(); }
+ bool has_length() const { return at<3>().valid(); }
+ uint32_t length() const { return at<3>().as_uint32(); }
+ bool has_uid() const { return at<4>().valid(); }
+ uint32_t uid() const { return at<4>().as_uint32(); }
+ bool has_tag() const { return at<5>().valid(); }
+ uint32_t tag() const { return at<5>().as_uint32(); }
+ bool has_ip_proto() const { return at<6>().valid(); }
+ uint32_t ip_proto() const { return at<6>().as_uint32(); }
+ bool has_tcp_flags() const { return at<7>().valid(); }
+ uint32_t tcp_flags() const { return at<7>().as_uint32(); }
+ bool has_local_port() const { return at<8>().valid(); }
+ uint32_t local_port() const { return at<8>().as_uint32(); }
+ bool has_remote_port() const { return at<9>().valid(); }
+ uint32_t remote_port() const { return at<9>().as_uint32(); }
+ bool has_icmp_type() const { return at<10>().valid(); }
+ uint32_t icmp_type() const { return at<10>().as_uint32(); }
+ bool has_icmp_code() const { return at<11>().valid(); }
+ uint32_t icmp_code() const { return at<11>().as_uint32(); }
+};
+
+class NetworkPacketEvent : public ::protozero::Message {
+ public:
+ using Decoder = NetworkPacketEvent_Decoder;
+ enum : int32_t {
+ kDirectionFieldNumber = 1,
+ kInterfaceFieldNumber = 2,
+ kLengthFieldNumber = 3,
+ kUidFieldNumber = 4,
+ kTagFieldNumber = 5,
+ kIpProtoFieldNumber = 6,
+ kTcpFlagsFieldNumber = 7,
+ kLocalPortFieldNumber = 8,
+ kRemotePortFieldNumber = 9,
+ kIcmpTypeFieldNumber = 10,
+ kIcmpCodeFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NetworkPacketEvent"; }
+
+
+ using FieldMetadata_Direction =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ TrafficDirection,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_Direction kDirection{};
+ void set_direction(TrafficDirection value) {
+ static constexpr uint32_t field_id = FieldMetadata_Direction::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Interface =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_Interface kInterface{};
+ void set_interface(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Interface::kFieldId, data, size);
+ }
+ void set_interface(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Interface::kFieldId, chars.data, chars.size);
+ }
+ void set_interface(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Interface::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Length =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_Length kLength{};
+ void set_length(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Length::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IpProto =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_IpProto kIpProto{};
+ void set_ip_proto(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IpProto::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TcpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_TcpFlags kTcpFlags{};
+ void set_tcp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TcpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LocalPort =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_LocalPort kLocalPort{};
+ void set_local_port(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LocalPort::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RemotePort =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_RemotePort kRemotePort{};
+ void set_remote_port(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RemotePort::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IcmpType =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_IcmpType kIcmpType{};
+ void set_icmp_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IcmpType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IcmpCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetworkPacketEvent>;
+
+ static constexpr FieldMetadata_IcmpCode kIcmpCode{};
+ void set_icmp_code(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IcmpCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/packages_list.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_PACKAGES_LIST_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_PACKAGES_LIST_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class PackagesList_PackageInfo;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class PackagesList_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ PackagesList_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PackagesList_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PackagesList_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_packages() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> packages() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_parse_error() const { return at<2>().valid(); }
+ bool parse_error() const { return at<2>().as_bool(); }
+ bool has_read_error() const { return at<3>().valid(); }
+ bool read_error() const { return at<3>().as_bool(); }
+};
+
+class PackagesList : public ::protozero::Message {
+ public:
+ using Decoder = PackagesList_Decoder;
+ enum : int32_t {
+ kPackagesFieldNumber = 1,
+ kParseErrorFieldNumber = 2,
+ kReadErrorFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PackagesList"; }
+
+ using PackageInfo = ::perfetto::protos::pbzero::PackagesList_PackageInfo;
+
+ using FieldMetadata_Packages =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PackagesList_PackageInfo,
+ PackagesList>;
+
+ static constexpr FieldMetadata_Packages kPackages{};
+ template <typename T = PackagesList_PackageInfo> T* add_packages() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ParseError =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PackagesList>;
+
+ static constexpr FieldMetadata_ParseError kParseError{};
+ void set_parse_error(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParseError::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadError =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PackagesList>;
+
+ static constexpr FieldMetadata_ReadError kReadError{};
+ void set_read_error(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadError::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PackagesList_PackageInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PackagesList_PackageInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PackagesList_PackageInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PackagesList_PackageInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_uid() const { return at<2>().valid(); }
+ uint64_t uid() const { return at<2>().as_uint64(); }
+ bool has_debuggable() const { return at<3>().valid(); }
+ bool debuggable() const { return at<3>().as_bool(); }
+ bool has_profileable_from_shell() const { return at<4>().valid(); }
+ bool profileable_from_shell() const { return at<4>().as_bool(); }
+ bool has_version_code() const { return at<5>().valid(); }
+ int64_t version_code() const { return at<5>().as_int64(); }
+};
+
+class PackagesList_PackageInfo : public ::protozero::Message {
+ public:
+ using Decoder = PackagesList_PackageInfo_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kUidFieldNumber = 2,
+ kDebuggableFieldNumber = 3,
+ kProfileableFromShellFieldNumber = 4,
+ kVersionCodeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PackagesList.PackageInfo"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PackagesList_PackageInfo>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PackagesList_PackageInfo>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Debuggable =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PackagesList_PackageInfo>;
+
+ static constexpr FieldMetadata_Debuggable kDebuggable{};
+ void set_debuggable(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Debuggable::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProfileableFromShell =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PackagesList_PackageInfo>;
+
+ static constexpr FieldMetadata_ProfileableFromShell kProfileableFromShell{};
+ void set_profileable_from_shell(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProfileableFromShell::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VersionCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ PackagesList_PackageInfo>;
+
+ static constexpr FieldMetadata_VersionCode kVersionCode{};
+ void set_version_code(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VersionCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/protolog.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_PROTOLOG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_PROTOLOG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ProtoLogViewerConfig_Group;
+class ProtoLogViewerConfig_MessageData;
+enum ProtoLogLevel : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ProtoLogViewerConfig_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProtoLogViewerConfig_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProtoLogViewerConfig_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProtoLogViewerConfig_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_messages() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> messages() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_groups() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> groups() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class ProtoLogViewerConfig : public ::protozero::Message {
+ public:
+ using Decoder = ProtoLogViewerConfig_Decoder;
+ enum : int32_t {
+ kMessagesFieldNumber = 1,
+ kGroupsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProtoLogViewerConfig"; }
+
+ using MessageData = ::perfetto::protos::pbzero::ProtoLogViewerConfig_MessageData;
+ using Group = ::perfetto::protos::pbzero::ProtoLogViewerConfig_Group;
+
+ using FieldMetadata_Messages =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProtoLogViewerConfig_MessageData,
+ ProtoLogViewerConfig>;
+
+ static constexpr FieldMetadata_Messages kMessages{};
+ template <typename T = ProtoLogViewerConfig_MessageData> T* add_messages() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Groups =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProtoLogViewerConfig_Group,
+ ProtoLogViewerConfig>;
+
+ static constexpr FieldMetadata_Groups kGroups{};
+ template <typename T = ProtoLogViewerConfig_Group> T* add_groups() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class ProtoLogViewerConfig_Group_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProtoLogViewerConfig_Group_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProtoLogViewerConfig_Group_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProtoLogViewerConfig_Group_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint32_t id() const { return at<1>().as_uint32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_tag() const { return at<3>().valid(); }
+ ::protozero::ConstChars tag() const { return at<3>().as_string(); }
+};
+
+class ProtoLogViewerConfig_Group : public ::protozero::Message {
+ public:
+ using Decoder = ProtoLogViewerConfig_Group_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kTagFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProtoLogViewerConfig.Group"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProtoLogViewerConfig_Group>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProtoLogViewerConfig_Group>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProtoLogViewerConfig_Group>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, data, size);
+ }
+ void set_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, chars.data, chars.size);
+ }
+ void set_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProtoLogViewerConfig_MessageData_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProtoLogViewerConfig_MessageData_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProtoLogViewerConfig_MessageData_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProtoLogViewerConfig_MessageData_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_message_id() const { return at<1>().valid(); }
+ uint64_t message_id() const { return at<1>().as_uint64(); }
+ bool has_message() const { return at<2>().valid(); }
+ ::protozero::ConstChars message() const { return at<2>().as_string(); }
+ bool has_level() const { return at<3>().valid(); }
+ int32_t level() const { return at<3>().as_int32(); }
+ bool has_group_id() const { return at<4>().valid(); }
+ uint32_t group_id() const { return at<4>().as_uint32(); }
+};
+
+class ProtoLogViewerConfig_MessageData : public ::protozero::Message {
+ public:
+ using Decoder = ProtoLogViewerConfig_MessageData_Decoder;
+ enum : int32_t {
+ kMessageIdFieldNumber = 1,
+ kMessageFieldNumber = 2,
+ kLevelFieldNumber = 3,
+ kGroupIdFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProtoLogViewerConfig.MessageData"; }
+
+
+ using FieldMetadata_MessageId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ ProtoLogViewerConfig_MessageData>;
+
+ static constexpr FieldMetadata_MessageId kMessageId{};
+ void set_message_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MessageId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Message =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProtoLogViewerConfig_MessageData>;
+
+ static constexpr FieldMetadata_Message kMessage{};
+ void set_message(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Message::kFieldId, data, size);
+ }
+ void set_message(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Message::kFieldId, chars.data, chars.size);
+ }
+ void set_message(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Message::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ProtoLogLevel,
+ ProtoLogViewerConfig_MessageData>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(ProtoLogLevel value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GroupId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProtoLogViewerConfig_MessageData>;
+
+ static constexpr FieldMetadata_GroupId kGroupId{};
+ void set_group_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GroupId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProtoLogMessage_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProtoLogMessage_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProtoLogMessage_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProtoLogMessage_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_message_id() const { return at<1>().valid(); }
+ uint64_t message_id() const { return at<1>().as_uint64(); }
+ bool has_str_param_iids() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> str_param_iids() const { return GetRepeated<uint32_t>(2); }
+ bool has_sint64_params() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<int64_t> sint64_params() const { return GetRepeated<int64_t>(3); }
+ bool has_double_params() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<double> double_params() const { return GetRepeated<double>(4); }
+ bool has_boolean_params() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> boolean_params() const { return GetRepeated<int32_t>(5); }
+ bool has_stacktrace_iid() const { return at<6>().valid(); }
+ uint32_t stacktrace_iid() const { return at<6>().as_uint32(); }
+};
+
+class ProtoLogMessage : public ::protozero::Message {
+ public:
+ using Decoder = ProtoLogMessage_Decoder;
+ enum : int32_t {
+ kMessageIdFieldNumber = 1,
+ kStrParamIidsFieldNumber = 2,
+ kSint64ParamsFieldNumber = 3,
+ kDoubleParamsFieldNumber = 4,
+ kBooleanParamsFieldNumber = 5,
+ kStacktraceIidFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProtoLogMessage"; }
+
+
+ using FieldMetadata_MessageId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ ProtoLogMessage>;
+
+ static constexpr FieldMetadata_MessageId kMessageId{};
+ void set_message_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MessageId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StrParamIids =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProtoLogMessage>;
+
+ static constexpr FieldMetadata_StrParamIids kStrParamIids{};
+ void add_str_param_iids(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StrParamIids::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sint64Params =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kSint64,
+ int64_t,
+ ProtoLogMessage>;
+
+ static constexpr FieldMetadata_Sint64Params kSint64Params{};
+ void add_sint64_params(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sint64Params::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleParams =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ ProtoLogMessage>;
+
+ static constexpr FieldMetadata_DoubleParams kDoubleParams{};
+ void add_double_params(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleParams::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BooleanParams =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProtoLogMessage>;
+
+ static constexpr FieldMetadata_BooleanParams kBooleanParams{};
+ void add_boolean_params(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BooleanParams::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StacktraceIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProtoLogMessage>;
+
+ static constexpr FieldMetadata_StacktraceIid kStacktraceIid{};
+ void set_stacktrace_iid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StacktraceIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/shell_transition.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SHELL_TRANSITION_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SHELL_TRANSITION_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ShellHandlerMapping;
+class ShellTransition_Target;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ShellHandlerMapping_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ShellHandlerMapping_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ShellHandlerMapping_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ShellHandlerMapping_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int32_t id() const { return at<1>().as_int32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+};
+
+class ShellHandlerMapping : public ::protozero::Message {
+ public:
+ using Decoder = ShellHandlerMapping_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ShellHandlerMapping"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellHandlerMapping>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ShellHandlerMapping>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ShellHandlerMappings_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ShellHandlerMappings_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ShellHandlerMappings_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ShellHandlerMappings_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mapping() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> mapping() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class ShellHandlerMappings : public ::protozero::Message {
+ public:
+ using Decoder = ShellHandlerMappings_Decoder;
+ enum : int32_t {
+ kMappingFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ShellHandlerMappings"; }
+
+
+ using FieldMetadata_Mapping =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ShellHandlerMapping,
+ ShellHandlerMappings>;
+
+ static constexpr FieldMetadata_Mapping kMapping{};
+ template <typename T = ShellHandlerMapping> T* add_mapping() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class ShellTransition_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/17, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ShellTransition_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ShellTransition_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ShellTransition_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int32_t id() const { return at<1>().as_int32(); }
+ bool has_create_time_ns() const { return at<2>().valid(); }
+ int64_t create_time_ns() const { return at<2>().as_int64(); }
+ bool has_send_time_ns() const { return at<3>().valid(); }
+ int64_t send_time_ns() const { return at<3>().as_int64(); }
+ bool has_dispatch_time_ns() const { return at<4>().valid(); }
+ int64_t dispatch_time_ns() const { return at<4>().as_int64(); }
+ bool has_merge_time_ns() const { return at<5>().valid(); }
+ int64_t merge_time_ns() const { return at<5>().as_int64(); }
+ bool has_merge_request_time_ns() const { return at<6>().valid(); }
+ int64_t merge_request_time_ns() const { return at<6>().as_int64(); }
+ bool has_shell_abort_time_ns() const { return at<7>().valid(); }
+ int64_t shell_abort_time_ns() const { return at<7>().as_int64(); }
+ bool has_wm_abort_time_ns() const { return at<8>().valid(); }
+ int64_t wm_abort_time_ns() const { return at<8>().as_int64(); }
+ bool has_finish_time_ns() const { return at<9>().valid(); }
+ int64_t finish_time_ns() const { return at<9>().as_int64(); }
+ bool has_start_transaction_id() const { return at<10>().valid(); }
+ uint64_t start_transaction_id() const { return at<10>().as_uint64(); }
+ bool has_finish_transaction_id() const { return at<11>().valid(); }
+ uint64_t finish_transaction_id() const { return at<11>().as_uint64(); }
+ bool has_handler() const { return at<12>().valid(); }
+ int32_t handler() const { return at<12>().as_int32(); }
+ bool has_type() const { return at<13>().valid(); }
+ int32_t type() const { return at<13>().as_int32(); }
+ bool has_targets() const { return at<14>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> targets() const { return GetRepeated<::protozero::ConstBytes>(14); }
+ bool has_merge_target() const { return at<15>().valid(); }
+ int32_t merge_target() const { return at<15>().as_int32(); }
+ bool has_flags() const { return at<16>().valid(); }
+ int32_t flags() const { return at<16>().as_int32(); }
+ bool has_starting_window_remove_time_ns() const { return at<17>().valid(); }
+ int64_t starting_window_remove_time_ns() const { return at<17>().as_int64(); }
+};
+
+class ShellTransition : public ::protozero::Message {
+ public:
+ using Decoder = ShellTransition_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kCreateTimeNsFieldNumber = 2,
+ kSendTimeNsFieldNumber = 3,
+ kDispatchTimeNsFieldNumber = 4,
+ kMergeTimeNsFieldNumber = 5,
+ kMergeRequestTimeNsFieldNumber = 6,
+ kShellAbortTimeNsFieldNumber = 7,
+ kWmAbortTimeNsFieldNumber = 8,
+ kFinishTimeNsFieldNumber = 9,
+ kStartTransactionIdFieldNumber = 10,
+ kFinishTransactionIdFieldNumber = 11,
+ kHandlerFieldNumber = 12,
+ kTypeFieldNumber = 13,
+ kTargetsFieldNumber = 14,
+ kMergeTargetFieldNumber = 15,
+ kFlagsFieldNumber = 16,
+ kStartingWindowRemoveTimeNsFieldNumber = 17,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ShellTransition"; }
+
+ using Target = ::perfetto::protos::pbzero::ShellTransition_Target;
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CreateTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_CreateTimeNs kCreateTimeNs{};
+ void set_create_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CreateTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SendTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_SendTimeNs kSendTimeNs{};
+ void set_send_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SendTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DispatchTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_DispatchTimeNs kDispatchTimeNs{};
+ void set_dispatch_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DispatchTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MergeTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_MergeTimeNs kMergeTimeNs{};
+ void set_merge_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MergeTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MergeRequestTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_MergeRequestTimeNs kMergeRequestTimeNs{};
+ void set_merge_request_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MergeRequestTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ShellAbortTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_ShellAbortTimeNs kShellAbortTimeNs{};
+ void set_shell_abort_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShellAbortTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WmAbortTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_WmAbortTimeNs kWmAbortTimeNs{};
+ void set_wm_abort_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WmAbortTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FinishTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_FinishTimeNs kFinishTimeNs{};
+ void set_finish_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FinishTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartTransactionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_StartTransactionId kStartTransactionId{};
+ void set_start_transaction_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartTransactionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FinishTransactionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_FinishTransactionId kFinishTransactionId{};
+ void set_finish_transaction_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FinishTransactionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Handler =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_Handler kHandler{};
+ void set_handler(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Handler::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Targets =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ShellTransition_Target,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_Targets kTargets{};
+ template <typename T = ShellTransition_Target> T* add_targets() {
+ return BeginNestedMessage<T>(14);
+ }
+
+
+ using FieldMetadata_MergeTarget =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_MergeTarget kMergeTarget{};
+ void set_merge_target(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MergeTarget::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartingWindowRemoveTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ShellTransition>;
+
+ static constexpr FieldMetadata_StartingWindowRemoveTimeNs kStartingWindowRemoveTimeNs{};
+ void set_starting_window_remove_time_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartingWindowRemoveTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ShellTransition_Target_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ShellTransition_Target_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ShellTransition_Target_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ShellTransition_Target_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mode() const { return at<1>().valid(); }
+ int32_t mode() const { return at<1>().as_int32(); }
+ bool has_layer_id() const { return at<2>().valid(); }
+ int32_t layer_id() const { return at<2>().as_int32(); }
+ bool has_window_id() const { return at<3>().valid(); }
+ int32_t window_id() const { return at<3>().as_int32(); }
+ bool has_flags() const { return at<4>().valid(); }
+ int32_t flags() const { return at<4>().as_int32(); }
+};
+
+class ShellTransition_Target : public ::protozero::Message {
+ public:
+ using Decoder = ShellTransition_Target_Decoder;
+ enum : int32_t {
+ kModeFieldNumber = 1,
+ kLayerIdFieldNumber = 2,
+ kWindowIdFieldNumber = 3,
+ kFlagsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ShellTransition.Target"; }
+
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition_Target>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition_Target>;
+
+ static constexpr FieldMetadata_LayerId kLayerId{};
+ void set_layer_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WindowId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition_Target>;
+
+ static constexpr FieldMetadata_WindowId kWindowId{};
+ void set_window_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WindowId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ShellTransition_Target>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/surfaceflinger_common.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SURFACEFLINGER_COMMON_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SURFACEFLINGER_COMMON_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class RectProto;
+class RegionProto;
+class TransformProto;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ColorTransformProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ColorTransformProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ColorTransformProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ColorTransformProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_val() const { return at<1>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kFixed32, float> val(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kFixed32, float>(1, parse_error_ptr); }
+};
+
+class ColorTransformProto : public ::protozero::Message {
+ public:
+ using Decoder = ColorTransformProto_Decoder;
+ enum : int32_t {
+ kValFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ColorTransformProto"; }
+
+
+ using FieldMetadata_Val =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ ColorTransformProto>;
+
+ static constexpr FieldMetadata_Val kVal{};
+ void set_val(const ::protozero::PackedFixedSizeInt<float>& packed_buffer) {
+ AppendBytes(FieldMetadata_Val::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+};
+
+class BlurRegion_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlurRegion_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlurRegion_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlurRegion_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_blur_radius() const { return at<1>().valid(); }
+ uint32_t blur_radius() const { return at<1>().as_uint32(); }
+ bool has_corner_radius_tl() const { return at<2>().valid(); }
+ uint32_t corner_radius_tl() const { return at<2>().as_uint32(); }
+ bool has_corner_radius_tr() const { return at<3>().valid(); }
+ uint32_t corner_radius_tr() const { return at<3>().as_uint32(); }
+ bool has_corner_radius_bl() const { return at<4>().valid(); }
+ uint32_t corner_radius_bl() const { return at<4>().as_uint32(); }
+ bool has_corner_radius_br() const { return at<5>().valid(); }
+ float corner_radius_br() const { return at<5>().as_float(); }
+ bool has_alpha() const { return at<6>().valid(); }
+ float alpha() const { return at<6>().as_float(); }
+ bool has_left() const { return at<7>().valid(); }
+ int32_t left() const { return at<7>().as_int32(); }
+ bool has_top() const { return at<8>().valid(); }
+ int32_t top() const { return at<8>().as_int32(); }
+ bool has_right() const { return at<9>().valid(); }
+ int32_t right() const { return at<9>().as_int32(); }
+ bool has_bottom() const { return at<10>().valid(); }
+ int32_t bottom() const { return at<10>().as_int32(); }
+};
+
+class BlurRegion : public ::protozero::Message {
+ public:
+ using Decoder = BlurRegion_Decoder;
+ enum : int32_t {
+ kBlurRadiusFieldNumber = 1,
+ kCornerRadiusTlFieldNumber = 2,
+ kCornerRadiusTrFieldNumber = 3,
+ kCornerRadiusBlFieldNumber = 4,
+ kCornerRadiusBrFieldNumber = 5,
+ kAlphaFieldNumber = 6,
+ kLeftFieldNumber = 7,
+ kTopFieldNumber = 8,
+ kRightFieldNumber = 9,
+ kBottomFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlurRegion"; }
+
+
+ using FieldMetadata_BlurRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_BlurRadius kBlurRadius{};
+ void set_blur_radius(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlurRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CornerRadiusTl =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_CornerRadiusTl kCornerRadiusTl{};
+ void set_corner_radius_tl(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CornerRadiusTl::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CornerRadiusTr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_CornerRadiusTr kCornerRadiusTr{};
+ void set_corner_radius_tr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CornerRadiusTr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CornerRadiusBl =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_CornerRadiusBl kCornerRadiusBl{};
+ void set_corner_radius_bl(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CornerRadiusBl::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CornerRadiusBr =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_CornerRadiusBr kCornerRadiusBr{};
+ void set_corner_radius_br(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_CornerRadiusBr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Alpha =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_Alpha kAlpha{};
+ void set_alpha(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Alpha::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Left =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_Left kLeft{};
+ void set_left(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Left::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Top =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_Top kTop{};
+ void set_top(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Top::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Right =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_Right kRight{};
+ void set_right(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Right::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bottom =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlurRegion>;
+
+ static constexpr FieldMetadata_Bottom kBottom{};
+ void set_bottom(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bottom::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InputWindowInfoProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/17, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InputWindowInfoProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InputWindowInfoProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InputWindowInfoProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_layout_params_flags() const { return at<1>().valid(); }
+ uint32_t layout_params_flags() const { return at<1>().as_uint32(); }
+ bool has_layout_params_type() const { return at<2>().valid(); }
+ int32_t layout_params_type() const { return at<2>().as_int32(); }
+ bool has_frame() const { return at<3>().valid(); }
+ ::protozero::ConstBytes frame() const { return at<3>().as_bytes(); }
+ bool has_touchable_region() const { return at<4>().valid(); }
+ ::protozero::ConstBytes touchable_region() const { return at<4>().as_bytes(); }
+ bool has_surface_inset() const { return at<5>().valid(); }
+ int32_t surface_inset() const { return at<5>().as_int32(); }
+ bool has_visible() const { return at<6>().valid(); }
+ bool visible() const { return at<6>().as_bool(); }
+ bool has_can_receive_keys() const { return at<7>().valid(); }
+ bool can_receive_keys() const { return at<7>().as_bool(); }
+ bool has_focusable() const { return at<8>().valid(); }
+ bool focusable() const { return at<8>().as_bool(); }
+ bool has_has_wallpaper() const { return at<9>().valid(); }
+ bool has_wallpaper() const { return at<9>().as_bool(); }
+ bool has_global_scale_factor() const { return at<10>().valid(); }
+ float global_scale_factor() const { return at<10>().as_float(); }
+ bool has_window_x_scale() const { return at<11>().valid(); }
+ float window_x_scale() const { return at<11>().as_float(); }
+ bool has_window_y_scale() const { return at<12>().valid(); }
+ float window_y_scale() const { return at<12>().as_float(); }
+ bool has_crop_layer_id() const { return at<13>().valid(); }
+ int32_t crop_layer_id() const { return at<13>().as_int32(); }
+ bool has_replace_touchable_region_with_crop() const { return at<14>().valid(); }
+ bool replace_touchable_region_with_crop() const { return at<14>().as_bool(); }
+ bool has_touchable_region_crop() const { return at<15>().valid(); }
+ ::protozero::ConstBytes touchable_region_crop() const { return at<15>().as_bytes(); }
+ bool has_transform() const { return at<16>().valid(); }
+ ::protozero::ConstBytes transform() const { return at<16>().as_bytes(); }
+ bool has_input_config() const { return at<17>().valid(); }
+ uint32_t input_config() const { return at<17>().as_uint32(); }
+};
+
+class InputWindowInfoProto : public ::protozero::Message {
+ public:
+ using Decoder = InputWindowInfoProto_Decoder;
+ enum : int32_t {
+ kLayoutParamsFlagsFieldNumber = 1,
+ kLayoutParamsTypeFieldNumber = 2,
+ kFrameFieldNumber = 3,
+ kTouchableRegionFieldNumber = 4,
+ kSurfaceInsetFieldNumber = 5,
+ kVisibleFieldNumber = 6,
+ kCanReceiveKeysFieldNumber = 7,
+ kFocusableFieldNumber = 8,
+ kHasWallpaperFieldNumber = 9,
+ kGlobalScaleFactorFieldNumber = 10,
+ kWindowXScaleFieldNumber = 11,
+ kWindowYScaleFieldNumber = 12,
+ kCropLayerIdFieldNumber = 13,
+ kReplaceTouchableRegionWithCropFieldNumber = 14,
+ kTouchableRegionCropFieldNumber = 15,
+ kTransformFieldNumber = 16,
+ kInputConfigFieldNumber = 17,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InputWindowInfoProto"; }
+
+
+ using FieldMetadata_LayoutParamsFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_LayoutParamsFlags kLayoutParamsFlags{};
+ void set_layout_params_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayoutParamsFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayoutParamsType =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_LayoutParamsType kLayoutParamsType{};
+ void set_layout_params_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayoutParamsType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Frame =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_Frame kFrame{};
+ template <typename T = RectProto> T* set_frame() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_TouchableRegion =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegionProto,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_TouchableRegion kTouchableRegion{};
+ template <typename T = RegionProto> T* set_touchable_region() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_SurfaceInset =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_SurfaceInset kSurfaceInset{};
+ void set_surface_inset(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SurfaceInset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Visible =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_Visible kVisible{};
+ void set_visible(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Visible::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CanReceiveKeys =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_CanReceiveKeys kCanReceiveKeys{};
+ void set_can_receive_keys(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CanReceiveKeys::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Focusable =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_Focusable kFocusable{};
+ void set_focusable(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Focusable::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasWallpaper =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_HasWallpaper kHasWallpaper{};
+ void set_has_wallpaper(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasWallpaper::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GlobalScaleFactor =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_GlobalScaleFactor kGlobalScaleFactor{};
+ void set_global_scale_factor(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_GlobalScaleFactor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WindowXScale =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_WindowXScale kWindowXScale{};
+ void set_window_x_scale(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_WindowXScale::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WindowYScale =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_WindowYScale kWindowYScale{};
+ void set_window_y_scale(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_WindowYScale::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CropLayerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_CropLayerId kCropLayerId{};
+ void set_crop_layer_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CropLayerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReplaceTouchableRegionWithCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_ReplaceTouchableRegionWithCrop kReplaceTouchableRegionWithCrop{};
+ void set_replace_touchable_region_with_crop(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReplaceTouchableRegionWithCrop::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TouchableRegionCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_TouchableRegionCrop kTouchableRegionCrop{};
+ template <typename T = RectProto> T* set_touchable_region_crop() {
+ return BeginNestedMessage<T>(15);
+ }
+
+
+ using FieldMetadata_Transform =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransformProto,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_Transform kTransform{};
+ template <typename T = TransformProto> T* set_transform() {
+ return BeginNestedMessage<T>(16);
+ }
+
+
+ using FieldMetadata_InputConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InputWindowInfoProto>;
+
+ static constexpr FieldMetadata_InputConfig kInputConfig{};
+ void set_input_config(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputConfig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ColorProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ColorProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ColorProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ColorProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_r() const { return at<1>().valid(); }
+ float r() const { return at<1>().as_float(); }
+ bool has_g() const { return at<2>().valid(); }
+ float g() const { return at<2>().as_float(); }
+ bool has_b() const { return at<3>().valid(); }
+ float b() const { return at<3>().as_float(); }
+ bool has_a() const { return at<4>().valid(); }
+ float a() const { return at<4>().as_float(); }
+};
+
+class ColorProto : public ::protozero::Message {
+ public:
+ using Decoder = ColorProto_Decoder;
+ enum : int32_t {
+ kRFieldNumber = 1,
+ kGFieldNumber = 2,
+ kBFieldNumber = 3,
+ kAFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ColorProto"; }
+
+
+ using FieldMetadata_R =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ ColorProto>;
+
+ static constexpr FieldMetadata_R kR{};
+ void set_r(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_R::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_G =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ ColorProto>;
+
+ static constexpr FieldMetadata_G kG{};
+ void set_g(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_G::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_B =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ ColorProto>;
+
+ static constexpr FieldMetadata_B kB{};
+ void set_b(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_B::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_A =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ ColorProto>;
+
+ static constexpr FieldMetadata_A kA{};
+ void set_a(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_A::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TransformProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TransformProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TransformProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TransformProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dsdx() const { return at<1>().valid(); }
+ float dsdx() const { return at<1>().as_float(); }
+ bool has_dtdx() const { return at<2>().valid(); }
+ float dtdx() const { return at<2>().as_float(); }
+ bool has_dsdy() const { return at<3>().valid(); }
+ float dsdy() const { return at<3>().as_float(); }
+ bool has_dtdy() const { return at<4>().valid(); }
+ float dtdy() const { return at<4>().as_float(); }
+ bool has_type() const { return at<5>().valid(); }
+ int32_t type() const { return at<5>().as_int32(); }
+};
+
+class TransformProto : public ::protozero::Message {
+ public:
+ using Decoder = TransformProto_Decoder;
+ enum : int32_t {
+ kDsdxFieldNumber = 1,
+ kDtdxFieldNumber = 2,
+ kDsdyFieldNumber = 3,
+ kDtdyFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TransformProto"; }
+
+
+ using FieldMetadata_Dsdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ TransformProto>;
+
+ static constexpr FieldMetadata_Dsdx kDsdx{};
+ void set_dsdx(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dsdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dtdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ TransformProto>;
+
+ static constexpr FieldMetadata_Dtdx kDtdx{};
+ void set_dtdx(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dtdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dsdy =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ TransformProto>;
+
+ static constexpr FieldMetadata_Dsdy kDsdy{};
+ void set_dsdy(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dsdy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dtdy =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ TransformProto>;
+
+ static constexpr FieldMetadata_Dtdy kDtdy{};
+ void set_dtdy(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dtdy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TransformProto>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SizeProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SizeProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SizeProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SizeProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_w() const { return at<1>().valid(); }
+ int32_t w() const { return at<1>().as_int32(); }
+ bool has_h() const { return at<2>().valid(); }
+ int32_t h() const { return at<2>().as_int32(); }
+};
+
+class SizeProto : public ::protozero::Message {
+ public:
+ using Decoder = SizeProto_Decoder;
+ enum : int32_t {
+ kWFieldNumber = 1,
+ kHFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SizeProto"; }
+
+
+ using FieldMetadata_W =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SizeProto>;
+
+ static constexpr FieldMetadata_W kW{};
+ void set_w(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_W::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_H =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SizeProto>;
+
+ static constexpr FieldMetadata_H kH{};
+ void set_h(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_H::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RectProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RectProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RectProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RectProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_left() const { return at<1>().valid(); }
+ int32_t left() const { return at<1>().as_int32(); }
+ bool has_top() const { return at<2>().valid(); }
+ int32_t top() const { return at<2>().as_int32(); }
+ bool has_right() const { return at<3>().valid(); }
+ int32_t right() const { return at<3>().as_int32(); }
+ bool has_bottom() const { return at<4>().valid(); }
+ int32_t bottom() const { return at<4>().as_int32(); }
+};
+
+class RectProto : public ::protozero::Message {
+ public:
+ using Decoder = RectProto_Decoder;
+ enum : int32_t {
+ kLeftFieldNumber = 1,
+ kTopFieldNumber = 2,
+ kRightFieldNumber = 3,
+ kBottomFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RectProto"; }
+
+
+ using FieldMetadata_Left =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RectProto>;
+
+ static constexpr FieldMetadata_Left kLeft{};
+ void set_left(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Left::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Top =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RectProto>;
+
+ static constexpr FieldMetadata_Top kTop{};
+ void set_top(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Top::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Right =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RectProto>;
+
+ static constexpr FieldMetadata_Right kRight{};
+ void set_right(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Right::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bottom =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RectProto>;
+
+ static constexpr FieldMetadata_Bottom kBottom{};
+ void set_bottom(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bottom::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RegionProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ RegionProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegionProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegionProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_rect() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> rect() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class RegionProto : public ::protozero::Message {
+ public:
+ using Decoder = RegionProto_Decoder;
+ enum : int32_t {
+ kRectFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegionProto"; }
+
+
+ using FieldMetadata_Rect =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ RegionProto>;
+
+ static constexpr FieldMetadata_Rect kRect{};
+ template <typename T = RectProto> T* add_rect() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/surfaceflinger_layers.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SURFACEFLINGER_LAYERS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SURFACEFLINGER_LAYERS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ActiveBufferProto;
+class BarrierLayerProto;
+class BlurRegion;
+class ColorProto;
+class ColorTransformProto;
+class DisplayProto;
+class FloatRectProto;
+class InputWindowInfoProto;
+class LayerProto;
+class LayerProto_MetadataEntry;
+class LayersProto;
+class LayersSnapshotProto;
+class PositionProto;
+class RectProto;
+class RegionProto;
+class SizeProto;
+class TransformProto;
+enum HwcCompositionType : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum HwcCompositionType : int32_t {
+ HWC_TYPE_UNSPECIFIED = 0,
+ HWC_TYPE_CLIENT = 1,
+ HWC_TYPE_DEVICE = 2,
+ HWC_TYPE_SOLID_COLOR = 3,
+ HWC_TYPE_CURSOR = 4,
+ HWC_TYPE_SIDEBAND = 5,
+ HWC_TYPE_DISPLAY_DECORATION = 6,
+};
+
+constexpr HwcCompositionType HwcCompositionType_MIN = HwcCompositionType::HWC_TYPE_UNSPECIFIED;
+constexpr HwcCompositionType HwcCompositionType_MAX = HwcCompositionType::HWC_TYPE_DISPLAY_DECORATION;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* HwcCompositionType_Name(::perfetto::protos::pbzero::HwcCompositionType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::HwcCompositionType::HWC_TYPE_UNSPECIFIED:
+ return "HWC_TYPE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::HwcCompositionType::HWC_TYPE_CLIENT:
+ return "HWC_TYPE_CLIENT";
+
+ case ::perfetto::protos::pbzero::HwcCompositionType::HWC_TYPE_DEVICE:
+ return "HWC_TYPE_DEVICE";
+
+ case ::perfetto::protos::pbzero::HwcCompositionType::HWC_TYPE_SOLID_COLOR:
+ return "HWC_TYPE_SOLID_COLOR";
+
+ case ::perfetto::protos::pbzero::HwcCompositionType::HWC_TYPE_CURSOR:
+ return "HWC_TYPE_CURSOR";
+
+ case ::perfetto::protos::pbzero::HwcCompositionType::HWC_TYPE_SIDEBAND:
+ return "HWC_TYPE_SIDEBAND";
+
+ case ::perfetto::protos::pbzero::HwcCompositionType::HWC_TYPE_DISPLAY_DECORATION:
+ return "HWC_TYPE_DISPLAY_DECORATION";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_LayersTraceFileProto {
+enum MagicNumber : int32_t {
+ INVALID = 0,
+ MAGIC_NUMBER_L = 1414682956,
+ MAGIC_NUMBER_H = 1162035538,
+};
+} // namespace perfetto_pbzero_enum_LayersTraceFileProto
+using LayersTraceFileProto_MagicNumber = perfetto_pbzero_enum_LayersTraceFileProto::MagicNumber;
+
+
+constexpr LayersTraceFileProto_MagicNumber LayersTraceFileProto_MagicNumber_MIN = LayersTraceFileProto_MagicNumber::INVALID;
+constexpr LayersTraceFileProto_MagicNumber LayersTraceFileProto_MagicNumber_MAX = LayersTraceFileProto_MagicNumber::MAGIC_NUMBER_L;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LayersTraceFileProto_MagicNumber_Name(::perfetto::protos::pbzero::LayersTraceFileProto_MagicNumber value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LayersTraceFileProto_MagicNumber::INVALID:
+ return "INVALID";
+
+ case ::perfetto::protos::pbzero::LayersTraceFileProto_MagicNumber::MAGIC_NUMBER_L:
+ return "MAGIC_NUMBER_L";
+
+ case ::perfetto::protos::pbzero::LayersTraceFileProto_MagicNumber::MAGIC_NUMBER_H:
+ return "MAGIC_NUMBER_H";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class BarrierLayerProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BarrierLayerProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BarrierLayerProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BarrierLayerProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int32_t id() const { return at<1>().as_int32(); }
+ bool has_frame_number() const { return at<2>().valid(); }
+ uint64_t frame_number() const { return at<2>().as_uint64(); }
+};
+
+class BarrierLayerProto : public ::protozero::Message {
+ public:
+ using Decoder = BarrierLayerProto_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kFrameNumberFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BarrierLayerProto"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BarrierLayerProto>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BarrierLayerProto>;
+
+ static constexpr FieldMetadata_FrameNumber kFrameNumber{};
+ void set_frame_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ActiveBufferProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ActiveBufferProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ActiveBufferProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ActiveBufferProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_width() const { return at<1>().valid(); }
+ uint32_t width() const { return at<1>().as_uint32(); }
+ bool has_height() const { return at<2>().valid(); }
+ uint32_t height() const { return at<2>().as_uint32(); }
+ bool has_stride() const { return at<3>().valid(); }
+ uint32_t stride() const { return at<3>().as_uint32(); }
+ bool has_format() const { return at<4>().valid(); }
+ int32_t format() const { return at<4>().as_int32(); }
+ bool has_usage() const { return at<5>().valid(); }
+ uint64_t usage() const { return at<5>().as_uint64(); }
+};
+
+class ActiveBufferProto : public ::protozero::Message {
+ public:
+ using Decoder = ActiveBufferProto_Decoder;
+ enum : int32_t {
+ kWidthFieldNumber = 1,
+ kHeightFieldNumber = 2,
+ kStrideFieldNumber = 3,
+ kFormatFieldNumber = 4,
+ kUsageFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ActiveBufferProto"; }
+
+
+ using FieldMetadata_Width =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ActiveBufferProto>;
+
+ static constexpr FieldMetadata_Width kWidth{};
+ void set_width(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Width::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Height =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ActiveBufferProto>;
+
+ static constexpr FieldMetadata_Height kHeight{};
+ void set_height(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Height::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Stride =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ActiveBufferProto>;
+
+ static constexpr FieldMetadata_Stride kStride{};
+ void set_stride(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Stride::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Format =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ActiveBufferProto>;
+
+ static constexpr FieldMetadata_Format kFormat{};
+ void set_format(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Format::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Usage =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ActiveBufferProto>;
+
+ static constexpr FieldMetadata_Usage kUsage{};
+ void set_usage(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Usage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FloatRectProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FloatRectProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FloatRectProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FloatRectProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_left() const { return at<1>().valid(); }
+ float left() const { return at<1>().as_float(); }
+ bool has_top() const { return at<2>().valid(); }
+ float top() const { return at<2>().as_float(); }
+ bool has_right() const { return at<3>().valid(); }
+ float right() const { return at<3>().as_float(); }
+ bool has_bottom() const { return at<4>().valid(); }
+ float bottom() const { return at<4>().as_float(); }
+};
+
+class FloatRectProto : public ::protozero::Message {
+ public:
+ using Decoder = FloatRectProto_Decoder;
+ enum : int32_t {
+ kLeftFieldNumber = 1,
+ kTopFieldNumber = 2,
+ kRightFieldNumber = 3,
+ kBottomFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FloatRectProto"; }
+
+
+ using FieldMetadata_Left =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ FloatRectProto>;
+
+ static constexpr FieldMetadata_Left kLeft{};
+ void set_left(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Left::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Top =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ FloatRectProto>;
+
+ static constexpr FieldMetadata_Top kTop{};
+ void set_top(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Top::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Right =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ FloatRectProto>;
+
+ static constexpr FieldMetadata_Right kRight{};
+ void set_right(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Right::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bottom =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ FloatRectProto>;
+
+ static constexpr FieldMetadata_Bottom kBottom{};
+ void set_bottom(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bottom::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PositionProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PositionProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PositionProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PositionProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_x() const { return at<1>().valid(); }
+ float x() const { return at<1>().as_float(); }
+ bool has_y() const { return at<2>().valid(); }
+ float y() const { return at<2>().as_float(); }
+};
+
+class PositionProto : public ::protozero::Message {
+ public:
+ using Decoder = PositionProto_Decoder;
+ enum : int32_t {
+ kXFieldNumber = 1,
+ kYFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PositionProto"; }
+
+
+ using FieldMetadata_X =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ PositionProto>;
+
+ static constexpr FieldMetadata_X kX{};
+ void set_x(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_X::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Y =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ PositionProto>;
+
+ static constexpr FieldMetadata_Y kY{};
+ void set_y(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Y::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/58, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ LayerProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int32_t id() const { return at<1>().as_int32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_children() const { return at<3>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t> children(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(3, parse_error_ptr); }
+ bool has_relatives() const { return at<4>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t> relatives(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(4, parse_error_ptr); }
+ bool has_type() const { return at<5>().valid(); }
+ ::protozero::ConstChars type() const { return at<5>().as_string(); }
+ bool has_transparent_region() const { return at<6>().valid(); }
+ ::protozero::ConstBytes transparent_region() const { return at<6>().as_bytes(); }
+ bool has_visible_region() const { return at<7>().valid(); }
+ ::protozero::ConstBytes visible_region() const { return at<7>().as_bytes(); }
+ bool has_damage_region() const { return at<8>().valid(); }
+ ::protozero::ConstBytes damage_region() const { return at<8>().as_bytes(); }
+ bool has_layer_stack() const { return at<9>().valid(); }
+ uint32_t layer_stack() const { return at<9>().as_uint32(); }
+ bool has_z() const { return at<10>().valid(); }
+ int32_t z() const { return at<10>().as_int32(); }
+ bool has_position() const { return at<11>().valid(); }
+ ::protozero::ConstBytes position() const { return at<11>().as_bytes(); }
+ bool has_requested_position() const { return at<12>().valid(); }
+ ::protozero::ConstBytes requested_position() const { return at<12>().as_bytes(); }
+ bool has_size() const { return at<13>().valid(); }
+ ::protozero::ConstBytes size() const { return at<13>().as_bytes(); }
+ bool has_crop() const { return at<14>().valid(); }
+ ::protozero::ConstBytes crop() const { return at<14>().as_bytes(); }
+ bool has_final_crop() const { return at<15>().valid(); }
+ ::protozero::ConstBytes final_crop() const { return at<15>().as_bytes(); }
+ bool has_is_opaque() const { return at<16>().valid(); }
+ bool is_opaque() const { return at<16>().as_bool(); }
+ bool has_invalidate() const { return at<17>().valid(); }
+ bool invalidate() const { return at<17>().as_bool(); }
+ bool has_dataspace() const { return at<18>().valid(); }
+ ::protozero::ConstChars dataspace() const { return at<18>().as_string(); }
+ bool has_pixel_format() const { return at<19>().valid(); }
+ ::protozero::ConstChars pixel_format() const { return at<19>().as_string(); }
+ bool has_color() const { return at<20>().valid(); }
+ ::protozero::ConstBytes color() const { return at<20>().as_bytes(); }
+ bool has_requested_color() const { return at<21>().valid(); }
+ ::protozero::ConstBytes requested_color() const { return at<21>().as_bytes(); }
+ bool has_flags() const { return at<22>().valid(); }
+ uint32_t flags() const { return at<22>().as_uint32(); }
+ bool has_transform() const { return at<23>().valid(); }
+ ::protozero::ConstBytes transform() const { return at<23>().as_bytes(); }
+ bool has_requested_transform() const { return at<24>().valid(); }
+ ::protozero::ConstBytes requested_transform() const { return at<24>().as_bytes(); }
+ bool has_parent() const { return at<25>().valid(); }
+ int32_t parent() const { return at<25>().as_int32(); }
+ bool has_z_order_relative_of() const { return at<26>().valid(); }
+ int32_t z_order_relative_of() const { return at<26>().as_int32(); }
+ bool has_active_buffer() const { return at<27>().valid(); }
+ ::protozero::ConstBytes active_buffer() const { return at<27>().as_bytes(); }
+ bool has_queued_frames() const { return at<28>().valid(); }
+ int32_t queued_frames() const { return at<28>().as_int32(); }
+ bool has_refresh_pending() const { return at<29>().valid(); }
+ bool refresh_pending() const { return at<29>().as_bool(); }
+ bool has_hwc_frame() const { return at<30>().valid(); }
+ ::protozero::ConstBytes hwc_frame() const { return at<30>().as_bytes(); }
+ bool has_hwc_crop() const { return at<31>().valid(); }
+ ::protozero::ConstBytes hwc_crop() const { return at<31>().as_bytes(); }
+ bool has_hwc_transform() const { return at<32>().valid(); }
+ int32_t hwc_transform() const { return at<32>().as_int32(); }
+ bool has_window_type() const { return at<33>().valid(); }
+ int32_t window_type() const { return at<33>().as_int32(); }
+ bool has_app_id() const { return at<34>().valid(); }
+ int32_t app_id() const { return at<34>().as_int32(); }
+ bool has_hwc_composition_type() const { return at<35>().valid(); }
+ int32_t hwc_composition_type() const { return at<35>().as_int32(); }
+ bool has_is_protected() const { return at<36>().valid(); }
+ bool is_protected() const { return at<36>().as_bool(); }
+ bool has_curr_frame() const { return at<37>().valid(); }
+ uint64_t curr_frame() const { return at<37>().as_uint64(); }
+ bool has_barrier_layer() const { return at<38>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> barrier_layer() const { return GetRepeated<::protozero::ConstBytes>(38); }
+ bool has_buffer_transform() const { return at<39>().valid(); }
+ ::protozero::ConstBytes buffer_transform() const { return at<39>().as_bytes(); }
+ bool has_effective_scaling_mode() const { return at<40>().valid(); }
+ int32_t effective_scaling_mode() const { return at<40>().as_int32(); }
+ bool has_corner_radius() const { return at<41>().valid(); }
+ float corner_radius() const { return at<41>().as_float(); }
+ bool has_metadata() const { return at<42>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> metadata() const { return GetRepeated<::protozero::ConstBytes>(42); }
+ bool has_effective_transform() const { return at<43>().valid(); }
+ ::protozero::ConstBytes effective_transform() const { return at<43>().as_bytes(); }
+ bool has_source_bounds() const { return at<44>().valid(); }
+ ::protozero::ConstBytes source_bounds() const { return at<44>().as_bytes(); }
+ bool has_bounds() const { return at<45>().valid(); }
+ ::protozero::ConstBytes bounds() const { return at<45>().as_bytes(); }
+ bool has_screen_bounds() const { return at<46>().valid(); }
+ ::protozero::ConstBytes screen_bounds() const { return at<46>().as_bytes(); }
+ bool has_input_window_info() const { return at<47>().valid(); }
+ ::protozero::ConstBytes input_window_info() const { return at<47>().as_bytes(); }
+ bool has_corner_radius_crop() const { return at<48>().valid(); }
+ ::protozero::ConstBytes corner_radius_crop() const { return at<48>().as_bytes(); }
+ bool has_shadow_radius() const { return at<49>().valid(); }
+ float shadow_radius() const { return at<49>().as_float(); }
+ bool has_color_transform() const { return at<50>().valid(); }
+ ::protozero::ConstBytes color_transform() const { return at<50>().as_bytes(); }
+ bool has_is_relative_of() const { return at<51>().valid(); }
+ bool is_relative_of() const { return at<51>().as_bool(); }
+ bool has_background_blur_radius() const { return at<52>().valid(); }
+ int32_t background_blur_radius() const { return at<52>().as_int32(); }
+ bool has_owner_uid() const { return at<53>().valid(); }
+ uint32_t owner_uid() const { return at<53>().as_uint32(); }
+ bool has_blur_regions() const { return at<54>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> blur_regions() const { return GetRepeated<::protozero::ConstBytes>(54); }
+ bool has_is_trusted_overlay() const { return at<55>().valid(); }
+ bool is_trusted_overlay() const { return at<55>().as_bool(); }
+ bool has_requested_corner_radius() const { return at<56>().valid(); }
+ float requested_corner_radius() const { return at<56>().as_float(); }
+ bool has_destination_frame() const { return at<57>().valid(); }
+ ::protozero::ConstBytes destination_frame() const { return at<57>().as_bytes(); }
+ bool has_original_id() const { return at<58>().valid(); }
+ uint32_t original_id() const { return at<58>().as_uint32(); }
+};
+
+class LayerProto : public ::protozero::Message {
+ public:
+ using Decoder = LayerProto_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kChildrenFieldNumber = 3,
+ kRelativesFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ kTransparentRegionFieldNumber = 6,
+ kVisibleRegionFieldNumber = 7,
+ kDamageRegionFieldNumber = 8,
+ kLayerStackFieldNumber = 9,
+ kZFieldNumber = 10,
+ kPositionFieldNumber = 11,
+ kRequestedPositionFieldNumber = 12,
+ kSizeFieldNumber = 13,
+ kCropFieldNumber = 14,
+ kFinalCropFieldNumber = 15,
+ kIsOpaqueFieldNumber = 16,
+ kInvalidateFieldNumber = 17,
+ kDataspaceFieldNumber = 18,
+ kPixelFormatFieldNumber = 19,
+ kColorFieldNumber = 20,
+ kRequestedColorFieldNumber = 21,
+ kFlagsFieldNumber = 22,
+ kTransformFieldNumber = 23,
+ kRequestedTransformFieldNumber = 24,
+ kParentFieldNumber = 25,
+ kZOrderRelativeOfFieldNumber = 26,
+ kActiveBufferFieldNumber = 27,
+ kQueuedFramesFieldNumber = 28,
+ kRefreshPendingFieldNumber = 29,
+ kHwcFrameFieldNumber = 30,
+ kHwcCropFieldNumber = 31,
+ kHwcTransformFieldNumber = 32,
+ kWindowTypeFieldNumber = 33,
+ kAppIdFieldNumber = 34,
+ kHwcCompositionTypeFieldNumber = 35,
+ kIsProtectedFieldNumber = 36,
+ kCurrFrameFieldNumber = 37,
+ kBarrierLayerFieldNumber = 38,
+ kBufferTransformFieldNumber = 39,
+ kEffectiveScalingModeFieldNumber = 40,
+ kCornerRadiusFieldNumber = 41,
+ kMetadataFieldNumber = 42,
+ kEffectiveTransformFieldNumber = 43,
+ kSourceBoundsFieldNumber = 44,
+ kBoundsFieldNumber = 45,
+ kScreenBoundsFieldNumber = 46,
+ kInputWindowInfoFieldNumber = 47,
+ kCornerRadiusCropFieldNumber = 48,
+ kShadowRadiusFieldNumber = 49,
+ kColorTransformFieldNumber = 50,
+ kIsRelativeOfFieldNumber = 51,
+ kBackgroundBlurRadiusFieldNumber = 52,
+ kOwnerUidFieldNumber = 53,
+ kBlurRegionsFieldNumber = 54,
+ kIsTrustedOverlayFieldNumber = 55,
+ kRequestedCornerRadiusFieldNumber = 56,
+ kDestinationFrameFieldNumber = 57,
+ kOriginalIdFieldNumber = 58,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerProto"; }
+
+ using MetadataEntry = ::perfetto::protos::pbzero::LayerProto_MetadataEntry;
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Children =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Children kChildren{};
+ void set_children(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_Children::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_Relatives =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Relatives kRelatives{};
+ void set_relatives(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_Relatives::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Type::kFieldId, data, size);
+ }
+ void set_type(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Type::kFieldId, chars.data, chars.size);
+ }
+ void set_type(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TransparentRegion =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegionProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_TransparentRegion kTransparentRegion{};
+ template <typename T = RegionProto> T* set_transparent_region() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_VisibleRegion =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegionProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_VisibleRegion kVisibleRegion{};
+ template <typename T = RegionProto> T* set_visible_region() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_DamageRegion =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegionProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_DamageRegion kDamageRegion{};
+ template <typename T = RegionProto> T* set_damage_region() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_LayerStack =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_LayerStack kLayerStack{};
+ void set_layer_stack(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerStack::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Z =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Z kZ{};
+ void set_z(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Z::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Position =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PositionProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Position kPosition{};
+ template <typename T = PositionProto> T* set_position() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_RequestedPosition =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PositionProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_RequestedPosition kRequestedPosition{};
+ template <typename T = PositionProto> T* set_requested_position() {
+ return BeginNestedMessage<T>(12);
+ }
+
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SizeProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ template <typename T = SizeProto> T* set_size() {
+ return BeginNestedMessage<T>(13);
+ }
+
+
+ using FieldMetadata_Crop =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Crop kCrop{};
+ template <typename T = RectProto> T* set_crop() {
+ return BeginNestedMessage<T>(14);
+ }
+
+
+ using FieldMetadata_FinalCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_FinalCrop kFinalCrop{};
+ template <typename T = RectProto> T* set_final_crop() {
+ return BeginNestedMessage<T>(15);
+ }
+
+
+ using FieldMetadata_IsOpaque =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerProto>;
+
+ static constexpr FieldMetadata_IsOpaque kIsOpaque{};
+ void set_is_opaque(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsOpaque::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Invalidate =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Invalidate kInvalidate{};
+ void set_invalidate(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Invalidate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dataspace =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Dataspace kDataspace{};
+ void set_dataspace(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Dataspace::kFieldId, data, size);
+ }
+ void set_dataspace(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Dataspace::kFieldId, chars.data, chars.size);
+ }
+ void set_dataspace(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dataspace::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PixelFormat =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayerProto>;
+
+ static constexpr FieldMetadata_PixelFormat kPixelFormat{};
+ void set_pixel_format(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_PixelFormat::kFieldId, data, size);
+ }
+ void set_pixel_format(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_PixelFormat::kFieldId, chars.data, chars.size);
+ }
+ void set_pixel_format(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_PixelFormat::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Color =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ColorProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Color kColor{};
+ template <typename T = ColorProto> T* set_color() {
+ return BeginNestedMessage<T>(20);
+ }
+
+
+ using FieldMetadata_RequestedColor =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ColorProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_RequestedColor kRequestedColor{};
+ template <typename T = ColorProto> T* set_requested_color() {
+ return BeginNestedMessage<T>(21);
+ }
+
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Transform =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransformProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Transform kTransform{};
+ template <typename T = TransformProto> T* set_transform() {
+ return BeginNestedMessage<T>(23);
+ }
+
+
+ using FieldMetadata_RequestedTransform =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransformProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_RequestedTransform kRequestedTransform{};
+ template <typename T = TransformProto> T* set_requested_transform() {
+ return BeginNestedMessage<T>(24);
+ }
+
+
+ using FieldMetadata_Parent =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Parent kParent{};
+ void set_parent(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Parent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ZOrderRelativeOf =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_ZOrderRelativeOf kZOrderRelativeOf{};
+ void set_z_order_relative_of(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ZOrderRelativeOf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ActiveBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ActiveBufferProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_ActiveBuffer kActiveBuffer{};
+ template <typename T = ActiveBufferProto> T* set_active_buffer() {
+ return BeginNestedMessage<T>(27);
+ }
+
+
+ using FieldMetadata_QueuedFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_QueuedFrames kQueuedFrames{};
+ void set_queued_frames(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_QueuedFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RefreshPending =
+ ::protozero::proto_utils::FieldMetadata<
+ 29,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerProto>;
+
+ static constexpr FieldMetadata_RefreshPending kRefreshPending{};
+ void set_refresh_pending(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_RefreshPending::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwcFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 30,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_HwcFrame kHwcFrame{};
+ template <typename T = RectProto> T* set_hwc_frame() {
+ return BeginNestedMessage<T>(30);
+ }
+
+
+ using FieldMetadata_HwcCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FloatRectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_HwcCrop kHwcCrop{};
+ template <typename T = FloatRectProto> T* set_hwc_crop() {
+ return BeginNestedMessage<T>(31);
+ }
+
+
+ using FieldMetadata_HwcTransform =
+ ::protozero::proto_utils::FieldMetadata<
+ 32,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_HwcTransform kHwcTransform{};
+ void set_hwc_transform(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwcTransform::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WindowType =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_WindowType kWindowType{};
+ void set_window_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WindowType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppId =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_AppId kAppId{};
+ void set_app_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwcCompositionType =
+ ::protozero::proto_utils::FieldMetadata<
+ 35,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ HwcCompositionType,
+ LayerProto>;
+
+ static constexpr FieldMetadata_HwcCompositionType kHwcCompositionType{};
+ void set_hwc_composition_type(HwcCompositionType value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwcCompositionType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsProtected =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerProto>;
+
+ static constexpr FieldMetadata_IsProtected kIsProtected{};
+ void set_is_protected(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsProtected::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 37,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_CurrFrame kCurrFrame{};
+ void set_curr_frame(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BarrierLayer =
+ ::protozero::proto_utils::FieldMetadata<
+ 38,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BarrierLayerProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_BarrierLayer kBarrierLayer{};
+ template <typename T = BarrierLayerProto> T* add_barrier_layer() {
+ return BeginNestedMessage<T>(38);
+ }
+
+
+ using FieldMetadata_BufferTransform =
+ ::protozero::proto_utils::FieldMetadata<
+ 39,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransformProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_BufferTransform kBufferTransform{};
+ template <typename T = TransformProto> T* set_buffer_transform() {
+ return BeginNestedMessage<T>(39);
+ }
+
+
+ using FieldMetadata_EffectiveScalingMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 40,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_EffectiveScalingMode kEffectiveScalingMode{};
+ void set_effective_scaling_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EffectiveScalingMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CornerRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 41,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerProto>;
+
+ static constexpr FieldMetadata_CornerRadius kCornerRadius{};
+ void set_corner_radius(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_CornerRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Metadata =
+ ::protozero::proto_utils::FieldMetadata<
+ 42,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerProto_MetadataEntry,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Metadata kMetadata{};
+ template <typename T = LayerProto_MetadataEntry> T* add_metadata() {
+ return BeginNestedMessage<T>(42);
+ }
+
+
+ using FieldMetadata_EffectiveTransform =
+ ::protozero::proto_utils::FieldMetadata<
+ 43,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransformProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_EffectiveTransform kEffectiveTransform{};
+ template <typename T = TransformProto> T* set_effective_transform() {
+ return BeginNestedMessage<T>(43);
+ }
+
+
+ using FieldMetadata_SourceBounds =
+ ::protozero::proto_utils::FieldMetadata<
+ 44,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FloatRectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_SourceBounds kSourceBounds{};
+ template <typename T = FloatRectProto> T* set_source_bounds() {
+ return BeginNestedMessage<T>(44);
+ }
+
+
+ using FieldMetadata_Bounds =
+ ::protozero::proto_utils::FieldMetadata<
+ 45,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FloatRectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_Bounds kBounds{};
+ template <typename T = FloatRectProto> T* set_bounds() {
+ return BeginNestedMessage<T>(45);
+ }
+
+
+ using FieldMetadata_ScreenBounds =
+ ::protozero::proto_utils::FieldMetadata<
+ 46,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FloatRectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_ScreenBounds kScreenBounds{};
+ template <typename T = FloatRectProto> T* set_screen_bounds() {
+ return BeginNestedMessage<T>(46);
+ }
+
+
+ using FieldMetadata_InputWindowInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 47,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InputWindowInfoProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_InputWindowInfo kInputWindowInfo{};
+ template <typename T = InputWindowInfoProto> T* set_input_window_info() {
+ return BeginNestedMessage<T>(47);
+ }
+
+
+ using FieldMetadata_CornerRadiusCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 48,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FloatRectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_CornerRadiusCrop kCornerRadiusCrop{};
+ template <typename T = FloatRectProto> T* set_corner_radius_crop() {
+ return BeginNestedMessage<T>(48);
+ }
+
+
+ using FieldMetadata_ShadowRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 49,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerProto>;
+
+ static constexpr FieldMetadata_ShadowRadius kShadowRadius{};
+ void set_shadow_radius(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShadowRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ColorTransform =
+ ::protozero::proto_utils::FieldMetadata<
+ 50,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ColorTransformProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_ColorTransform kColorTransform{};
+ template <typename T = ColorTransformProto> T* set_color_transform() {
+ return BeginNestedMessage<T>(50);
+ }
+
+
+ using FieldMetadata_IsRelativeOf =
+ ::protozero::proto_utils::FieldMetadata<
+ 51,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerProto>;
+
+ static constexpr FieldMetadata_IsRelativeOf kIsRelativeOf{};
+ void set_is_relative_of(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsRelativeOf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BackgroundBlurRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 52,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_BackgroundBlurRadius kBackgroundBlurRadius{};
+ void set_background_blur_radius(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BackgroundBlurRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OwnerUid =
+ ::protozero::proto_utils::FieldMetadata<
+ 53,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_OwnerUid kOwnerUid{};
+ void set_owner_uid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OwnerUid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BlurRegions =
+ ::protozero::proto_utils::FieldMetadata<
+ 54,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlurRegion,
+ LayerProto>;
+
+ static constexpr FieldMetadata_BlurRegions kBlurRegions{};
+ template <typename T = BlurRegion> T* add_blur_regions() {
+ return BeginNestedMessage<T>(54);
+ }
+
+
+ using FieldMetadata_IsTrustedOverlay =
+ ::protozero::proto_utils::FieldMetadata<
+ 55,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerProto>;
+
+ static constexpr FieldMetadata_IsTrustedOverlay kIsTrustedOverlay{};
+ void set_is_trusted_overlay(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsTrustedOverlay::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RequestedCornerRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 56,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerProto>;
+
+ static constexpr FieldMetadata_RequestedCornerRadius kRequestedCornerRadius{};
+ void set_requested_corner_radius(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_RequestedCornerRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DestinationFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 57,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerProto>;
+
+ static constexpr FieldMetadata_DestinationFrame kDestinationFrame{};
+ template <typename T = RectProto> T* set_destination_frame() {
+ return BeginNestedMessage<T>(57);
+ }
+
+
+ using FieldMetadata_OriginalId =
+ ::protozero::proto_utils::FieldMetadata<
+ 58,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerProto>;
+
+ static constexpr FieldMetadata_OriginalId kOriginalId{};
+ void set_original_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OriginalId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerProto_MetadataEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LayerProto_MetadataEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerProto_MetadataEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerProto_MetadataEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ int32_t key() const { return at<1>().as_int32(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class LayerProto_MetadataEntry : public ::protozero::Message {
+ public:
+ using Decoder = LayerProto_MetadataEntry_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerProto.MetadataEntry"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerProto_MetadataEntry>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayerProto_MetadataEntry>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DisplayProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DisplayProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DisplayProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DisplayProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_layer_stack() const { return at<3>().valid(); }
+ uint32_t layer_stack() const { return at<3>().as_uint32(); }
+ bool has_size() const { return at<4>().valid(); }
+ ::protozero::ConstBytes size() const { return at<4>().as_bytes(); }
+ bool has_layer_stack_space_rect() const { return at<5>().valid(); }
+ ::protozero::ConstBytes layer_stack_space_rect() const { return at<5>().as_bytes(); }
+ bool has_transform() const { return at<6>().valid(); }
+ ::protozero::ConstBytes transform() const { return at<6>().as_bytes(); }
+ bool has_is_virtual() const { return at<7>().valid(); }
+ bool is_virtual() const { return at<7>().as_bool(); }
+ bool has_dpi_x() const { return at<8>().valid(); }
+ double dpi_x() const { return at<8>().as_double(); }
+ bool has_dpi_y() const { return at<9>().valid(); }
+ double dpi_y() const { return at<9>().as_double(); }
+};
+
+class DisplayProto : public ::protozero::Message {
+ public:
+ using Decoder = DisplayProto_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kLayerStackFieldNumber = 3,
+ kSizeFieldNumber = 4,
+ kLayerStackSpaceRectFieldNumber = 5,
+ kTransformFieldNumber = 6,
+ kIsVirtualFieldNumber = 7,
+ kDpiXFieldNumber = 8,
+ kDpiYFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DisplayProto"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerStack =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_LayerStack kLayerStack{};
+ void set_layer_stack(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerStack::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SizeProto,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ template <typename T = SizeProto> T* set_size() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_LayerStackSpaceRect =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_LayerStackSpaceRect kLayerStackSpaceRect{};
+ template <typename T = RectProto> T* set_layer_stack_space_rect() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_Transform =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransformProto,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_Transform kTransform{};
+ template <typename T = TransformProto> T* set_transform() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_IsVirtual =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_IsVirtual kIsVirtual{};
+ void set_is_virtual(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsVirtual::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DpiX =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_DpiX kDpiX{};
+ void set_dpi_x(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DpiX::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DpiY =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ DisplayProto>;
+
+ static constexpr FieldMetadata_DpiY kDpiY{};
+ void set_dpi_y(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DpiY::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayersProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ LayersProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayersProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayersProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_layers() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> layers() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class LayersProto : public ::protozero::Message {
+ public:
+ using Decoder = LayersProto_Decoder;
+ enum : int32_t {
+ kLayersFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayersProto"; }
+
+
+ using FieldMetadata_Layers =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerProto,
+ LayersProto>;
+
+ static constexpr FieldMetadata_Layers kLayers{};
+ template <typename T = LayerProto> T* add_layers() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class LayersSnapshotProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ LayersSnapshotProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayersSnapshotProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayersSnapshotProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_elapsed_realtime_nanos() const { return at<1>().valid(); }
+ int64_t elapsed_realtime_nanos() const { return at<1>().as_int64(); }
+ bool has_where() const { return at<2>().valid(); }
+ ::protozero::ConstChars where() const { return at<2>().as_string(); }
+ bool has_layers() const { return at<3>().valid(); }
+ ::protozero::ConstBytes layers() const { return at<3>().as_bytes(); }
+ bool has_hwc_blob() const { return at<4>().valid(); }
+ ::protozero::ConstChars hwc_blob() const { return at<4>().as_string(); }
+ bool has_excludes_composition_state() const { return at<5>().valid(); }
+ bool excludes_composition_state() const { return at<5>().as_bool(); }
+ bool has_missed_entries() const { return at<6>().valid(); }
+ uint32_t missed_entries() const { return at<6>().as_uint32(); }
+ bool has_displays() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> displays() const { return GetRepeated<::protozero::ConstBytes>(7); }
+ bool has_vsync_id() const { return at<8>().valid(); }
+ int64_t vsync_id() const { return at<8>().as_int64(); }
+};
+
+class LayersSnapshotProto : public ::protozero::Message {
+ public:
+ using Decoder = LayersSnapshotProto_Decoder;
+ enum : int32_t {
+ kElapsedRealtimeNanosFieldNumber = 1,
+ kWhereFieldNumber = 2,
+ kLayersFieldNumber = 3,
+ kHwcBlobFieldNumber = 4,
+ kExcludesCompositionStateFieldNumber = 5,
+ kMissedEntriesFieldNumber = 6,
+ kDisplaysFieldNumber = 7,
+ kVsyncIdFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayersSnapshotProto"; }
+
+
+ using FieldMetadata_ElapsedRealtimeNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSfixed64,
+ int64_t,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_ElapsedRealtimeNanos kElapsedRealtimeNanos{};
+ void set_elapsed_realtime_nanos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ElapsedRealtimeNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSfixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Where =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_Where kWhere{};
+ void set_where(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Where::kFieldId, data, size);
+ }
+ void set_where(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Where::kFieldId, chars.data, chars.size);
+ }
+ void set_where(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Where::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Layers =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayersProto,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_Layers kLayers{};
+ template <typename T = LayersProto> T* set_layers() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_HwcBlob =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_HwcBlob kHwcBlob{};
+ void set_hwc_blob(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HwcBlob::kFieldId, data, size);
+ }
+ void set_hwc_blob(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HwcBlob::kFieldId, chars.data, chars.size);
+ }
+ void set_hwc_blob(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwcBlob::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExcludesCompositionState =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_ExcludesCompositionState kExcludesCompositionState{};
+ void set_excludes_composition_state(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExcludesCompositionState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MissedEntries =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_MissedEntries kMissedEntries{};
+ void set_missed_entries(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MissedEntries::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Displays =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DisplayProto,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_Displays kDisplays{};
+ template <typename T = DisplayProto> T* add_displays() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_VsyncId =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ LayersSnapshotProto>;
+
+ static constexpr FieldMetadata_VsyncId kVsyncId{};
+ void set_vsync_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VsyncId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayersTraceFileProto_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ LayersTraceFileProto_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayersTraceFileProto_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayersTraceFileProto_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_magic_number() const { return at<1>().valid(); }
+ uint64_t magic_number() const { return at<1>().as_uint64(); }
+ bool has_entry() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> entry() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_real_to_elapsed_time_offset_nanos() const { return at<3>().valid(); }
+ uint64_t real_to_elapsed_time_offset_nanos() const { return at<3>().as_uint64(); }
+};
+
+class LayersTraceFileProto : public ::protozero::Message {
+ public:
+ using Decoder = LayersTraceFileProto_Decoder;
+ enum : int32_t {
+ kMagicNumberFieldNumber = 1,
+ kEntryFieldNumber = 2,
+ kRealToElapsedTimeOffsetNanosFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayersTraceFileProto"; }
+
+
+ using MagicNumber = ::perfetto::protos::pbzero::LayersTraceFileProto_MagicNumber;
+ static inline const char* MagicNumber_Name(MagicNumber value) {
+ return ::perfetto::protos::pbzero::LayersTraceFileProto_MagicNumber_Name(value);
+ }
+ static inline const MagicNumber INVALID = MagicNumber::INVALID;
+ static inline const MagicNumber MAGIC_NUMBER_L = MagicNumber::MAGIC_NUMBER_L;
+ static inline const MagicNumber MAGIC_NUMBER_H = MagicNumber::MAGIC_NUMBER_H;
+
+ using FieldMetadata_MagicNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ LayersTraceFileProto>;
+
+ static constexpr FieldMetadata_MagicNumber kMagicNumber{};
+ void set_magic_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MagicNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Entry =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayersSnapshotProto,
+ LayersTraceFileProto>;
+
+ static constexpr FieldMetadata_Entry kEntry{};
+ template <typename T = LayersSnapshotProto> T* add_entry() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_RealToElapsedTimeOffsetNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ LayersTraceFileProto>;
+
+ static constexpr FieldMetadata_RealToElapsedTimeOffsetNanos kRealToElapsedTimeOffsetNanos{};
+ void set_real_to_elapsed_time_offset_nanos(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RealToElapsedTimeOffsetNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/android/surfaceflinger_transactions.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SURFACEFLINGER_TRANSACTIONS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ANDROID_SURFACEFLINGER_TRANSACTIONS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class BlurRegion;
+class ColorTransformProto;
+class DisplayInfo;
+class DisplayState;
+class LayerCreationArgs;
+class LayerState;
+class LayerState_BufferData;
+class LayerState_Color3;
+class LayerState_Matrix22;
+class LayerState_WindowInfo;
+class RectProto;
+class RegionProto;
+class TransactionState;
+class TransactionTraceEntry;
+class Transform;
+namespace perfetto_pbzero_enum_LayerState_BufferData {
+enum PixelFormat : int32_t;
+} // namespace perfetto_pbzero_enum_LayerState_BufferData
+using LayerState_BufferData_PixelFormat = perfetto_pbzero_enum_LayerState_BufferData::PixelFormat;
+namespace perfetto_pbzero_enum_LayerState {
+enum DropInputMode : int32_t;
+} // namespace perfetto_pbzero_enum_LayerState
+using LayerState_DropInputMode = perfetto_pbzero_enum_LayerState::DropInputMode;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_DisplayState {
+enum Changes : int32_t {
+ eChangesNone = 0,
+ eSurfaceChanged = 1,
+ eLayerStackChanged = 2,
+ eDisplayProjectionChanged = 4,
+ eDisplaySizeChanged = 8,
+ eFlagsChanged = 16,
+};
+} // namespace perfetto_pbzero_enum_DisplayState
+using DisplayState_Changes = perfetto_pbzero_enum_DisplayState::Changes;
+
+
+constexpr DisplayState_Changes DisplayState_Changes_MIN = DisplayState_Changes::eChangesNone;
+constexpr DisplayState_Changes DisplayState_Changes_MAX = DisplayState_Changes::eFlagsChanged;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* DisplayState_Changes_Name(::perfetto::protos::pbzero::DisplayState_Changes value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::DisplayState_Changes::eChangesNone:
+ return "eChangesNone";
+
+ case ::perfetto::protos::pbzero::DisplayState_Changes::eSurfaceChanged:
+ return "eSurfaceChanged";
+
+ case ::perfetto::protos::pbzero::DisplayState_Changes::eLayerStackChanged:
+ return "eLayerStackChanged";
+
+ case ::perfetto::protos::pbzero::DisplayState_Changes::eDisplayProjectionChanged:
+ return "eDisplayProjectionChanged";
+
+ case ::perfetto::protos::pbzero::DisplayState_Changes::eDisplaySizeChanged:
+ return "eDisplaySizeChanged";
+
+ case ::perfetto::protos::pbzero::DisplayState_Changes::eFlagsChanged:
+ return "eFlagsChanged";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_LayerState {
+enum ChangesLsb : int32_t {
+ eChangesLsbNone = 0,
+ ePositionChanged = 1,
+ eLayerChanged = 2,
+ eAlphaChanged = 8,
+ eMatrixChanged = 16,
+ eTransparentRegionChanged = 32,
+ eFlagsChanged = 64,
+ eLayerStackChanged = 128,
+ eReleaseBufferListenerChanged = 1024,
+ eShadowRadiusChanged = 2048,
+ eBufferCropChanged = 8192,
+ eRelativeLayerChanged = 16384,
+ eReparent = 32768,
+ eColorChanged = 65536,
+ eBufferTransformChanged = 262144,
+ eTransformToDisplayInverseChanged = 524288,
+ eCropChanged = 1048576,
+ eBufferChanged = 2097152,
+ eAcquireFenceChanged = 4194304,
+ eDataspaceChanged = 8388608,
+ eHdrMetadataChanged = 16777216,
+ eSurfaceDamageRegionChanged = 33554432,
+ eApiChanged = 67108864,
+ eSidebandStreamChanged = 134217728,
+ eColorTransformChanged = 268435456,
+ eHasListenerCallbacksChanged = 536870912,
+ eInputInfoChanged = 1073741824,
+ eCornerRadiusChanged = -2147483648,
+};
+} // namespace perfetto_pbzero_enum_LayerState
+using LayerState_ChangesLsb = perfetto_pbzero_enum_LayerState::ChangesLsb;
+
+
+constexpr LayerState_ChangesLsb LayerState_ChangesLsb_MIN = LayerState_ChangesLsb::eCornerRadiusChanged;
+constexpr LayerState_ChangesLsb LayerState_ChangesLsb_MAX = LayerState_ChangesLsb::eInputInfoChanged;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LayerState_ChangesLsb_Name(::perfetto::protos::pbzero::LayerState_ChangesLsb value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eChangesLsbNone:
+ return "eChangesLsbNone";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::ePositionChanged:
+ return "ePositionChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eLayerChanged:
+ return "eLayerChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eAlphaChanged:
+ return "eAlphaChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eMatrixChanged:
+ return "eMatrixChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eTransparentRegionChanged:
+ return "eTransparentRegionChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eFlagsChanged:
+ return "eFlagsChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eLayerStackChanged:
+ return "eLayerStackChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eReleaseBufferListenerChanged:
+ return "eReleaseBufferListenerChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eShadowRadiusChanged:
+ return "eShadowRadiusChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eBufferCropChanged:
+ return "eBufferCropChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eRelativeLayerChanged:
+ return "eRelativeLayerChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eReparent:
+ return "eReparent";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eColorChanged:
+ return "eColorChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eBufferTransformChanged:
+ return "eBufferTransformChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eTransformToDisplayInverseChanged:
+ return "eTransformToDisplayInverseChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eCropChanged:
+ return "eCropChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eBufferChanged:
+ return "eBufferChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eAcquireFenceChanged:
+ return "eAcquireFenceChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eDataspaceChanged:
+ return "eDataspaceChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eHdrMetadataChanged:
+ return "eHdrMetadataChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eSurfaceDamageRegionChanged:
+ return "eSurfaceDamageRegionChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eApiChanged:
+ return "eApiChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eSidebandStreamChanged:
+ return "eSidebandStreamChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eColorTransformChanged:
+ return "eColorTransformChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eHasListenerCallbacksChanged:
+ return "eHasListenerCallbacksChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eInputInfoChanged:
+ return "eInputInfoChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesLsb::eCornerRadiusChanged:
+ return "eCornerRadiusChanged";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_LayerState {
+enum ChangesMsb : int32_t {
+ eChangesMsbNone = 0,
+ eDestinationFrameChanged = 1,
+ eCachedBufferChanged = 2,
+ eBackgroundColorChanged = 4,
+ eMetadataChanged = 8,
+ eColorSpaceAgnosticChanged = 16,
+ eFrameRateSelectionPriority = 32,
+ eFrameRateChanged = 64,
+ eBackgroundBlurRadiusChanged = 128,
+ eProducerDisconnect = 256,
+ eFixedTransformHintChanged = 512,
+ eFrameNumberChanged = 1024,
+ eBlurRegionsChanged = 2048,
+ eAutoRefreshChanged = 4096,
+ eStretchChanged = 8192,
+ eTrustedOverlayChanged = 16384,
+ eDropInputModeChanged = 32768,
+};
+} // namespace perfetto_pbzero_enum_LayerState
+using LayerState_ChangesMsb = perfetto_pbzero_enum_LayerState::ChangesMsb;
+
+
+constexpr LayerState_ChangesMsb LayerState_ChangesMsb_MIN = LayerState_ChangesMsb::eChangesMsbNone;
+constexpr LayerState_ChangesMsb LayerState_ChangesMsb_MAX = LayerState_ChangesMsb::eDropInputModeChanged;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LayerState_ChangesMsb_Name(::perfetto::protos::pbzero::LayerState_ChangesMsb value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eChangesMsbNone:
+ return "eChangesMsbNone";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eDestinationFrameChanged:
+ return "eDestinationFrameChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eCachedBufferChanged:
+ return "eCachedBufferChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eBackgroundColorChanged:
+ return "eBackgroundColorChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eMetadataChanged:
+ return "eMetadataChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eColorSpaceAgnosticChanged:
+ return "eColorSpaceAgnosticChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eFrameRateSelectionPriority:
+ return "eFrameRateSelectionPriority";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eFrameRateChanged:
+ return "eFrameRateChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eBackgroundBlurRadiusChanged:
+ return "eBackgroundBlurRadiusChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eProducerDisconnect:
+ return "eProducerDisconnect";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eFixedTransformHintChanged:
+ return "eFixedTransformHintChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eFrameNumberChanged:
+ return "eFrameNumberChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eBlurRegionsChanged:
+ return "eBlurRegionsChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eAutoRefreshChanged:
+ return "eAutoRefreshChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eStretchChanged:
+ return "eStretchChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eTrustedOverlayChanged:
+ return "eTrustedOverlayChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_ChangesMsb::eDropInputModeChanged:
+ return "eDropInputModeChanged";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_LayerState {
+enum Flags : int32_t {
+ eFlagsNone = 0,
+ eLayerHidden = 1,
+ eLayerOpaque = 2,
+ eLayerSkipScreenshot = 64,
+ eLayerSecure = 128,
+ eEnableBackpressure = 256,
+ eLayerIsDisplayDecoration = 512,
+};
+} // namespace perfetto_pbzero_enum_LayerState
+using LayerState_Flags = perfetto_pbzero_enum_LayerState::Flags;
+
+
+constexpr LayerState_Flags LayerState_Flags_MIN = LayerState_Flags::eFlagsNone;
+constexpr LayerState_Flags LayerState_Flags_MAX = LayerState_Flags::eLayerIsDisplayDecoration;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LayerState_Flags_Name(::perfetto::protos::pbzero::LayerState_Flags value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LayerState_Flags::eFlagsNone:
+ return "eFlagsNone";
+
+ case ::perfetto::protos::pbzero::LayerState_Flags::eLayerHidden:
+ return "eLayerHidden";
+
+ case ::perfetto::protos::pbzero::LayerState_Flags::eLayerOpaque:
+ return "eLayerOpaque";
+
+ case ::perfetto::protos::pbzero::LayerState_Flags::eLayerSkipScreenshot:
+ return "eLayerSkipScreenshot";
+
+ case ::perfetto::protos::pbzero::LayerState_Flags::eLayerSecure:
+ return "eLayerSecure";
+
+ case ::perfetto::protos::pbzero::LayerState_Flags::eEnableBackpressure:
+ return "eEnableBackpressure";
+
+ case ::perfetto::protos::pbzero::LayerState_Flags::eLayerIsDisplayDecoration:
+ return "eLayerIsDisplayDecoration";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_LayerState {
+enum DropInputMode : int32_t {
+ NONE = 0,
+ ALL = 1,
+ OBSCURED = 2,
+};
+} // namespace perfetto_pbzero_enum_LayerState
+using LayerState_DropInputMode = perfetto_pbzero_enum_LayerState::DropInputMode;
+
+
+constexpr LayerState_DropInputMode LayerState_DropInputMode_MIN = LayerState_DropInputMode::NONE;
+constexpr LayerState_DropInputMode LayerState_DropInputMode_MAX = LayerState_DropInputMode::OBSCURED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LayerState_DropInputMode_Name(::perfetto::protos::pbzero::LayerState_DropInputMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LayerState_DropInputMode::NONE:
+ return "NONE";
+
+ case ::perfetto::protos::pbzero::LayerState_DropInputMode::ALL:
+ return "ALL";
+
+ case ::perfetto::protos::pbzero::LayerState_DropInputMode::OBSCURED:
+ return "OBSCURED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_LayerState_BufferData {
+enum BufferDataChange : int32_t {
+ BufferDataChangeNone = 0,
+ fenceChanged = 1,
+ frameNumberChanged = 2,
+ cachedBufferChanged = 4,
+};
+} // namespace perfetto_pbzero_enum_LayerState_BufferData
+using LayerState_BufferData_BufferDataChange = perfetto_pbzero_enum_LayerState_BufferData::BufferDataChange;
+
+
+constexpr LayerState_BufferData_BufferDataChange LayerState_BufferData_BufferDataChange_MIN = LayerState_BufferData_BufferDataChange::BufferDataChangeNone;
+constexpr LayerState_BufferData_BufferDataChange LayerState_BufferData_BufferDataChange_MAX = LayerState_BufferData_BufferDataChange::cachedBufferChanged;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LayerState_BufferData_BufferDataChange_Name(::perfetto::protos::pbzero::LayerState_BufferData_BufferDataChange value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LayerState_BufferData_BufferDataChange::BufferDataChangeNone:
+ return "BufferDataChangeNone";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_BufferDataChange::fenceChanged:
+ return "fenceChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_BufferDataChange::frameNumberChanged:
+ return "frameNumberChanged";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_BufferDataChange::cachedBufferChanged:
+ return "cachedBufferChanged";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_LayerState_BufferData {
+enum PixelFormat : int32_t {
+ PIXEL_FORMAT_UNKNOWN = 0,
+ PIXEL_FORMAT_CUSTOM = -4,
+ PIXEL_FORMAT_TRANSLUCENT = -3,
+ PIXEL_FORMAT_TRANSPARENT = -2,
+ PIXEL_FORMAT_OPAQUE = -1,
+ PIXEL_FORMAT_RGBA_8888 = 1,
+ PIXEL_FORMAT_RGBX_8888 = 2,
+ PIXEL_FORMAT_RGB_888 = 3,
+ PIXEL_FORMAT_RGB_565 = 4,
+ PIXEL_FORMAT_BGRA_8888 = 5,
+ PIXEL_FORMAT_RGBA_5551 = 6,
+ PIXEL_FORMAT_RGBA_4444 = 7,
+ PIXEL_FORMAT_RGBA_FP16 = 22,
+ PIXEL_FORMAT_RGBA_1010102 = 43,
+ PIXEL_FORMAT_R_8 = 56,
+};
+} // namespace perfetto_pbzero_enum_LayerState_BufferData
+using LayerState_BufferData_PixelFormat = perfetto_pbzero_enum_LayerState_BufferData::PixelFormat;
+
+
+constexpr LayerState_BufferData_PixelFormat LayerState_BufferData_PixelFormat_MIN = LayerState_BufferData_PixelFormat::PIXEL_FORMAT_CUSTOM;
+constexpr LayerState_BufferData_PixelFormat LayerState_BufferData_PixelFormat_MAX = LayerState_BufferData_PixelFormat::PIXEL_FORMAT_R_8;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LayerState_BufferData_PixelFormat_Name(::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_UNKNOWN:
+ return "PIXEL_FORMAT_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_CUSTOM:
+ return "PIXEL_FORMAT_CUSTOM";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_TRANSLUCENT:
+ return "PIXEL_FORMAT_TRANSLUCENT";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_TRANSPARENT:
+ return "PIXEL_FORMAT_TRANSPARENT";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_OPAQUE:
+ return "PIXEL_FORMAT_OPAQUE";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGBA_8888:
+ return "PIXEL_FORMAT_RGBA_8888";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGBX_8888:
+ return "PIXEL_FORMAT_RGBX_8888";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGB_888:
+ return "PIXEL_FORMAT_RGB_888";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGB_565:
+ return "PIXEL_FORMAT_RGB_565";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_BGRA_8888:
+ return "PIXEL_FORMAT_BGRA_8888";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGBA_5551:
+ return "PIXEL_FORMAT_RGBA_5551";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGBA_4444:
+ return "PIXEL_FORMAT_RGBA_4444";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGBA_FP16:
+ return "PIXEL_FORMAT_RGBA_FP16";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_RGBA_1010102:
+ return "PIXEL_FORMAT_RGBA_1010102";
+
+ case ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat::PIXEL_FORMAT_R_8:
+ return "PIXEL_FORMAT_R_8";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_TransactionTraceFile {
+enum MagicNumber : int32_t {
+ INVALID = 0,
+ MAGIC_NUMBER_L = 1415073364,
+ MAGIC_NUMBER_H = 1162035538,
+};
+} // namespace perfetto_pbzero_enum_TransactionTraceFile
+using TransactionTraceFile_MagicNumber = perfetto_pbzero_enum_TransactionTraceFile::MagicNumber;
+
+
+constexpr TransactionTraceFile_MagicNumber TransactionTraceFile_MagicNumber_MIN = TransactionTraceFile_MagicNumber::INVALID;
+constexpr TransactionTraceFile_MagicNumber TransactionTraceFile_MagicNumber_MAX = TransactionTraceFile_MagicNumber::MAGIC_NUMBER_L;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* TransactionTraceFile_MagicNumber_Name(::perfetto::protos::pbzero::TransactionTraceFile_MagicNumber value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::TransactionTraceFile_MagicNumber::INVALID:
+ return "INVALID";
+
+ case ::perfetto::protos::pbzero::TransactionTraceFile_MagicNumber::MAGIC_NUMBER_L:
+ return "MAGIC_NUMBER_L";
+
+ case ::perfetto::protos::pbzero::TransactionTraceFile_MagicNumber::MAGIC_NUMBER_H:
+ return "MAGIC_NUMBER_H";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class DisplayState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DisplayState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DisplayState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DisplayState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int32_t id() const { return at<1>().as_int32(); }
+ bool has_what() const { return at<2>().valid(); }
+ uint32_t what() const { return at<2>().as_uint32(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_layer_stack() const { return at<4>().valid(); }
+ uint32_t layer_stack() const { return at<4>().as_uint32(); }
+ bool has_orientation() const { return at<5>().valid(); }
+ uint32_t orientation() const { return at<5>().as_uint32(); }
+ bool has_layer_stack_space_rect() const { return at<6>().valid(); }
+ ::protozero::ConstBytes layer_stack_space_rect() const { return at<6>().as_bytes(); }
+ bool has_oriented_display_space_rect() const { return at<7>().valid(); }
+ ::protozero::ConstBytes oriented_display_space_rect() const { return at<7>().as_bytes(); }
+ bool has_width() const { return at<8>().valid(); }
+ uint32_t width() const { return at<8>().as_uint32(); }
+ bool has_height() const { return at<9>().valid(); }
+ uint32_t height() const { return at<9>().as_uint32(); }
+};
+
+class DisplayState : public ::protozero::Message {
+ public:
+ using Decoder = DisplayState_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kWhatFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kLayerStackFieldNumber = 4,
+ kOrientationFieldNumber = 5,
+ kLayerStackSpaceRectFieldNumber = 6,
+ kOrientedDisplaySpaceRectFieldNumber = 7,
+ kWidthFieldNumber = 8,
+ kHeightFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DisplayState"; }
+
+
+ using Changes = ::perfetto::protos::pbzero::DisplayState_Changes;
+ static inline const char* Changes_Name(Changes value) {
+ return ::perfetto::protos::pbzero::DisplayState_Changes_Name(value);
+ }
+ static inline const Changes eChangesNone = Changes::eChangesNone;
+ static inline const Changes eSurfaceChanged = Changes::eSurfaceChanged;
+ static inline const Changes eLayerStackChanged = Changes::eLayerStackChanged;
+ static inline const Changes eDisplayProjectionChanged = Changes::eDisplayProjectionChanged;
+ static inline const Changes eDisplaySizeChanged = Changes::eDisplaySizeChanged;
+ static inline const Changes eFlagsChanged = Changes::eFlagsChanged;
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DisplayState>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_What =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayState>;
+
+ static constexpr FieldMetadata_What kWhat{};
+ void set_what(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_What::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayState>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerStack =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayState>;
+
+ static constexpr FieldMetadata_LayerStack kLayerStack{};
+ void set_layer_stack(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerStack::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Orientation =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayState>;
+
+ static constexpr FieldMetadata_Orientation kOrientation{};
+ void set_orientation(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Orientation::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerStackSpaceRect =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ DisplayState>;
+
+ static constexpr FieldMetadata_LayerStackSpaceRect kLayerStackSpaceRect{};
+ template <typename T = RectProto> T* set_layer_stack_space_rect() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_OrientedDisplaySpaceRect =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ DisplayState>;
+
+ static constexpr FieldMetadata_OrientedDisplaySpaceRect kOrientedDisplaySpaceRect{};
+ template <typename T = RectProto> T* set_oriented_display_space_rect() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_Width =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayState>;
+
+ static constexpr FieldMetadata_Width kWidth{};
+ void set_width(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Width::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Height =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayState>;
+
+ static constexpr FieldMetadata_Height kHeight{};
+ void set_height(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Height::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/42, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ LayerState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_layer_id() const { return at<1>().valid(); }
+ uint32_t layer_id() const { return at<1>().as_uint32(); }
+ bool has_what() const { return at<2>().valid(); }
+ uint64_t what() const { return at<2>().as_uint64(); }
+ bool has_x() const { return at<3>().valid(); }
+ float x() const { return at<3>().as_float(); }
+ bool has_y() const { return at<4>().valid(); }
+ float y() const { return at<4>().as_float(); }
+ bool has_z() const { return at<5>().valid(); }
+ int32_t z() const { return at<5>().as_int32(); }
+ bool has_w() const { return at<6>().valid(); }
+ uint32_t w() const { return at<6>().as_uint32(); }
+ bool has_h() const { return at<7>().valid(); }
+ uint32_t h() const { return at<7>().as_uint32(); }
+ bool has_layer_stack() const { return at<8>().valid(); }
+ uint32_t layer_stack() const { return at<8>().as_uint32(); }
+ bool has_flags() const { return at<9>().valid(); }
+ uint32_t flags() const { return at<9>().as_uint32(); }
+ bool has_mask() const { return at<10>().valid(); }
+ uint32_t mask() const { return at<10>().as_uint32(); }
+ bool has_matrix() const { return at<11>().valid(); }
+ ::protozero::ConstBytes matrix() const { return at<11>().as_bytes(); }
+ bool has_corner_radius() const { return at<12>().valid(); }
+ float corner_radius() const { return at<12>().as_float(); }
+ bool has_background_blur_radius() const { return at<13>().valid(); }
+ uint32_t background_blur_radius() const { return at<13>().as_uint32(); }
+ bool has_parent_id() const { return at<14>().valid(); }
+ uint32_t parent_id() const { return at<14>().as_uint32(); }
+ bool has_relative_parent_id() const { return at<15>().valid(); }
+ uint32_t relative_parent_id() const { return at<15>().as_uint32(); }
+ bool has_alpha() const { return at<16>().valid(); }
+ float alpha() const { return at<16>().as_float(); }
+ bool has_color() const { return at<17>().valid(); }
+ ::protozero::ConstBytes color() const { return at<17>().as_bytes(); }
+ bool has_transparent_region() const { return at<18>().valid(); }
+ ::protozero::ConstBytes transparent_region() const { return at<18>().as_bytes(); }
+ bool has_transform() const { return at<19>().valid(); }
+ uint32_t transform() const { return at<19>().as_uint32(); }
+ bool has_transform_to_display_inverse() const { return at<20>().valid(); }
+ bool transform_to_display_inverse() const { return at<20>().as_bool(); }
+ bool has_crop() const { return at<21>().valid(); }
+ ::protozero::ConstBytes crop() const { return at<21>().as_bytes(); }
+ bool has_buffer_data() const { return at<22>().valid(); }
+ ::protozero::ConstBytes buffer_data() const { return at<22>().as_bytes(); }
+ bool has_api() const { return at<23>().valid(); }
+ int32_t api() const { return at<23>().as_int32(); }
+ bool has_has_sideband_stream() const { return at<24>().valid(); }
+ bool has_sideband_stream() const { return at<24>().as_bool(); }
+ bool has_color_transform() const { return at<25>().valid(); }
+ ::protozero::ConstBytes color_transform() const { return at<25>().as_bytes(); }
+ bool has_blur_regions() const { return at<26>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> blur_regions() const { return GetRepeated<::protozero::ConstBytes>(26); }
+ bool has_window_info_handle() const { return at<27>().valid(); }
+ ::protozero::ConstBytes window_info_handle() const { return at<27>().as_bytes(); }
+ bool has_bg_color_alpha() const { return at<28>().valid(); }
+ float bg_color_alpha() const { return at<28>().as_float(); }
+ bool has_bg_color_dataspace() const { return at<29>().valid(); }
+ int32_t bg_color_dataspace() const { return at<29>().as_int32(); }
+ bool has_color_space_agnostic() const { return at<30>().valid(); }
+ bool color_space_agnostic() const { return at<30>().as_bool(); }
+ bool has_shadow_radius() const { return at<31>().valid(); }
+ float shadow_radius() const { return at<31>().as_float(); }
+ bool has_frame_rate_selection_priority() const { return at<32>().valid(); }
+ int32_t frame_rate_selection_priority() const { return at<32>().as_int32(); }
+ bool has_frame_rate() const { return at<33>().valid(); }
+ float frame_rate() const { return at<33>().as_float(); }
+ bool has_frame_rate_compatibility() const { return at<34>().valid(); }
+ int32_t frame_rate_compatibility() const { return at<34>().as_int32(); }
+ bool has_change_frame_rate_strategy() const { return at<35>().valid(); }
+ int32_t change_frame_rate_strategy() const { return at<35>().as_int32(); }
+ bool has_fixed_transform_hint() const { return at<36>().valid(); }
+ uint32_t fixed_transform_hint() const { return at<36>().as_uint32(); }
+ bool has_frame_number() const { return at<37>().valid(); }
+ uint64_t frame_number() const { return at<37>().as_uint64(); }
+ bool has_auto_refresh() const { return at<38>().valid(); }
+ bool auto_refresh() const { return at<38>().as_bool(); }
+ bool has_is_trusted_overlay() const { return at<39>().valid(); }
+ bool is_trusted_overlay() const { return at<39>().as_bool(); }
+ bool has_buffer_crop() const { return at<40>().valid(); }
+ ::protozero::ConstBytes buffer_crop() const { return at<40>().as_bytes(); }
+ bool has_destination_frame() const { return at<41>().valid(); }
+ ::protozero::ConstBytes destination_frame() const { return at<41>().as_bytes(); }
+ bool has_drop_input_mode() const { return at<42>().valid(); }
+ int32_t drop_input_mode() const { return at<42>().as_int32(); }
+};
+
+class LayerState : public ::protozero::Message {
+ public:
+ using Decoder = LayerState_Decoder;
+ enum : int32_t {
+ kLayerIdFieldNumber = 1,
+ kWhatFieldNumber = 2,
+ kXFieldNumber = 3,
+ kYFieldNumber = 4,
+ kZFieldNumber = 5,
+ kWFieldNumber = 6,
+ kHFieldNumber = 7,
+ kLayerStackFieldNumber = 8,
+ kFlagsFieldNumber = 9,
+ kMaskFieldNumber = 10,
+ kMatrixFieldNumber = 11,
+ kCornerRadiusFieldNumber = 12,
+ kBackgroundBlurRadiusFieldNumber = 13,
+ kParentIdFieldNumber = 14,
+ kRelativeParentIdFieldNumber = 15,
+ kAlphaFieldNumber = 16,
+ kColorFieldNumber = 17,
+ kTransparentRegionFieldNumber = 18,
+ kTransformFieldNumber = 19,
+ kTransformToDisplayInverseFieldNumber = 20,
+ kCropFieldNumber = 21,
+ kBufferDataFieldNumber = 22,
+ kApiFieldNumber = 23,
+ kHasSidebandStreamFieldNumber = 24,
+ kColorTransformFieldNumber = 25,
+ kBlurRegionsFieldNumber = 26,
+ kWindowInfoHandleFieldNumber = 27,
+ kBgColorAlphaFieldNumber = 28,
+ kBgColorDataspaceFieldNumber = 29,
+ kColorSpaceAgnosticFieldNumber = 30,
+ kShadowRadiusFieldNumber = 31,
+ kFrameRateSelectionPriorityFieldNumber = 32,
+ kFrameRateFieldNumber = 33,
+ kFrameRateCompatibilityFieldNumber = 34,
+ kChangeFrameRateStrategyFieldNumber = 35,
+ kFixedTransformHintFieldNumber = 36,
+ kFrameNumberFieldNumber = 37,
+ kAutoRefreshFieldNumber = 38,
+ kIsTrustedOverlayFieldNumber = 39,
+ kBufferCropFieldNumber = 40,
+ kDestinationFrameFieldNumber = 41,
+ kDropInputModeFieldNumber = 42,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerState"; }
+
+ using Matrix22 = ::perfetto::protos::pbzero::LayerState_Matrix22;
+ using Color3 = ::perfetto::protos::pbzero::LayerState_Color3;
+ using BufferData = ::perfetto::protos::pbzero::LayerState_BufferData;
+ using WindowInfo = ::perfetto::protos::pbzero::LayerState_WindowInfo;
+
+ using ChangesLsb = ::perfetto::protos::pbzero::LayerState_ChangesLsb;
+ static inline const char* ChangesLsb_Name(ChangesLsb value) {
+ return ::perfetto::protos::pbzero::LayerState_ChangesLsb_Name(value);
+ }
+
+ using ChangesMsb = ::perfetto::protos::pbzero::LayerState_ChangesMsb;
+ static inline const char* ChangesMsb_Name(ChangesMsb value) {
+ return ::perfetto::protos::pbzero::LayerState_ChangesMsb_Name(value);
+ }
+
+ using Flags = ::perfetto::protos::pbzero::LayerState_Flags;
+ static inline const char* Flags_Name(Flags value) {
+ return ::perfetto::protos::pbzero::LayerState_Flags_Name(value);
+ }
+
+ using DropInputMode = ::perfetto::protos::pbzero::LayerState_DropInputMode;
+ static inline const char* DropInputMode_Name(DropInputMode value) {
+ return ::perfetto::protos::pbzero::LayerState_DropInputMode_Name(value);
+ }
+ static inline const ChangesLsb eChangesLsbNone = ChangesLsb::eChangesLsbNone;
+ static inline const ChangesLsb ePositionChanged = ChangesLsb::ePositionChanged;
+ static inline const ChangesLsb eLayerChanged = ChangesLsb::eLayerChanged;
+ static inline const ChangesLsb eAlphaChanged = ChangesLsb::eAlphaChanged;
+ static inline const ChangesLsb eMatrixChanged = ChangesLsb::eMatrixChanged;
+ static inline const ChangesLsb eTransparentRegionChanged = ChangesLsb::eTransparentRegionChanged;
+ static inline const ChangesLsb eFlagsChanged = ChangesLsb::eFlagsChanged;
+ static inline const ChangesLsb eLayerStackChanged = ChangesLsb::eLayerStackChanged;
+ static inline const ChangesLsb eReleaseBufferListenerChanged = ChangesLsb::eReleaseBufferListenerChanged;
+ static inline const ChangesLsb eShadowRadiusChanged = ChangesLsb::eShadowRadiusChanged;
+ static inline const ChangesLsb eBufferCropChanged = ChangesLsb::eBufferCropChanged;
+ static inline const ChangesLsb eRelativeLayerChanged = ChangesLsb::eRelativeLayerChanged;
+ static inline const ChangesLsb eReparent = ChangesLsb::eReparent;
+ static inline const ChangesLsb eColorChanged = ChangesLsb::eColorChanged;
+ static inline const ChangesLsb eBufferTransformChanged = ChangesLsb::eBufferTransformChanged;
+ static inline const ChangesLsb eTransformToDisplayInverseChanged = ChangesLsb::eTransformToDisplayInverseChanged;
+ static inline const ChangesLsb eCropChanged = ChangesLsb::eCropChanged;
+ static inline const ChangesLsb eBufferChanged = ChangesLsb::eBufferChanged;
+ static inline const ChangesLsb eAcquireFenceChanged = ChangesLsb::eAcquireFenceChanged;
+ static inline const ChangesLsb eDataspaceChanged = ChangesLsb::eDataspaceChanged;
+ static inline const ChangesLsb eHdrMetadataChanged = ChangesLsb::eHdrMetadataChanged;
+ static inline const ChangesLsb eSurfaceDamageRegionChanged = ChangesLsb::eSurfaceDamageRegionChanged;
+ static inline const ChangesLsb eApiChanged = ChangesLsb::eApiChanged;
+ static inline const ChangesLsb eSidebandStreamChanged = ChangesLsb::eSidebandStreamChanged;
+ static inline const ChangesLsb eColorTransformChanged = ChangesLsb::eColorTransformChanged;
+ static inline const ChangesLsb eHasListenerCallbacksChanged = ChangesLsb::eHasListenerCallbacksChanged;
+ static inline const ChangesLsb eInputInfoChanged = ChangesLsb::eInputInfoChanged;
+ static inline const ChangesLsb eCornerRadiusChanged = ChangesLsb::eCornerRadiusChanged;
+ static inline const ChangesMsb eChangesMsbNone = ChangesMsb::eChangesMsbNone;
+ static inline const ChangesMsb eDestinationFrameChanged = ChangesMsb::eDestinationFrameChanged;
+ static inline const ChangesMsb eCachedBufferChanged = ChangesMsb::eCachedBufferChanged;
+ static inline const ChangesMsb eBackgroundColorChanged = ChangesMsb::eBackgroundColorChanged;
+ static inline const ChangesMsb eMetadataChanged = ChangesMsb::eMetadataChanged;
+ static inline const ChangesMsb eColorSpaceAgnosticChanged = ChangesMsb::eColorSpaceAgnosticChanged;
+ static inline const ChangesMsb eFrameRateSelectionPriority = ChangesMsb::eFrameRateSelectionPriority;
+ static inline const ChangesMsb eFrameRateChanged = ChangesMsb::eFrameRateChanged;
+ static inline const ChangesMsb eBackgroundBlurRadiusChanged = ChangesMsb::eBackgroundBlurRadiusChanged;
+ static inline const ChangesMsb eProducerDisconnect = ChangesMsb::eProducerDisconnect;
+ static inline const ChangesMsb eFixedTransformHintChanged = ChangesMsb::eFixedTransformHintChanged;
+ static inline const ChangesMsb eFrameNumberChanged = ChangesMsb::eFrameNumberChanged;
+ static inline const ChangesMsb eBlurRegionsChanged = ChangesMsb::eBlurRegionsChanged;
+ static inline const ChangesMsb eAutoRefreshChanged = ChangesMsb::eAutoRefreshChanged;
+ static inline const ChangesMsb eStretchChanged = ChangesMsb::eStretchChanged;
+ static inline const ChangesMsb eTrustedOverlayChanged = ChangesMsb::eTrustedOverlayChanged;
+ static inline const ChangesMsb eDropInputModeChanged = ChangesMsb::eDropInputModeChanged;
+ static inline const Flags eFlagsNone = Flags::eFlagsNone;
+ static inline const Flags eLayerHidden = Flags::eLayerHidden;
+ static inline const Flags eLayerOpaque = Flags::eLayerOpaque;
+ static inline const Flags eLayerSkipScreenshot = Flags::eLayerSkipScreenshot;
+ static inline const Flags eLayerSecure = Flags::eLayerSecure;
+ static inline const Flags eEnableBackpressure = Flags::eEnableBackpressure;
+ static inline const Flags eLayerIsDisplayDecoration = Flags::eLayerIsDisplayDecoration;
+ static inline const DropInputMode NONE = DropInputMode::NONE;
+ static inline const DropInputMode ALL = DropInputMode::ALL;
+ static inline const DropInputMode OBSCURED = DropInputMode::OBSCURED;
+
+ using FieldMetadata_LayerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_LayerId kLayerId{};
+ void set_layer_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_What =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_What kWhat{};
+ void set_what(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_What::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_X =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState>;
+
+ static constexpr FieldMetadata_X kX{};
+ void set_x(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_X::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Y =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState>;
+
+ static constexpr FieldMetadata_Y kY{};
+ void set_y(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Y::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Z =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_Z kZ{};
+ void set_z(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Z::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_W =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_W kW{};
+ void set_w(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_W::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_H =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_H kH{};
+ void set_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_H::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerStack =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_LayerStack kLayerStack{};
+ void set_layer_stack(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerStack::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mask =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_Mask kMask{};
+ void set_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Matrix =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerState_Matrix22,
+ LayerState>;
+
+ static constexpr FieldMetadata_Matrix kMatrix{};
+ template <typename T = LayerState_Matrix22> T* set_matrix() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_CornerRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState>;
+
+ static constexpr FieldMetadata_CornerRadius kCornerRadius{};
+ void set_corner_radius(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_CornerRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BackgroundBlurRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_BackgroundBlurRadius kBackgroundBlurRadius{};
+ void set_background_blur_radius(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BackgroundBlurRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ParentId =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_ParentId kParentId{};
+ void set_parent_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParentId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RelativeParentId =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_RelativeParentId kRelativeParentId{};
+ void set_relative_parent_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RelativeParentId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Alpha =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState>;
+
+ static constexpr FieldMetadata_Alpha kAlpha{};
+ void set_alpha(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Alpha::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Color =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerState_Color3,
+ LayerState>;
+
+ static constexpr FieldMetadata_Color kColor{};
+ template <typename T = LayerState_Color3> T* set_color() {
+ return BeginNestedMessage<T>(17);
+ }
+
+
+ using FieldMetadata_TransparentRegion =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegionProto,
+ LayerState>;
+
+ static constexpr FieldMetadata_TransparentRegion kTransparentRegion{};
+ template <typename T = RegionProto> T* set_transparent_region() {
+ return BeginNestedMessage<T>(18);
+ }
+
+
+ using FieldMetadata_Transform =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_Transform kTransform{};
+ void set_transform(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Transform::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TransformToDisplayInverse =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState>;
+
+ static constexpr FieldMetadata_TransformToDisplayInverse kTransformToDisplayInverse{};
+ void set_transform_to_display_inverse(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TransformToDisplayInverse::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Crop =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerState>;
+
+ static constexpr FieldMetadata_Crop kCrop{};
+ template <typename T = RectProto> T* set_crop() {
+ return BeginNestedMessage<T>(21);
+ }
+
+
+ using FieldMetadata_BufferData =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerState_BufferData,
+ LayerState>;
+
+ static constexpr FieldMetadata_BufferData kBufferData{};
+ template <typename T = LayerState_BufferData> T* set_buffer_data() {
+ return BeginNestedMessage<T>(22);
+ }
+
+
+ using FieldMetadata_Api =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_Api kApi{};
+ void set_api(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Api::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasSidebandStream =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState>;
+
+ static constexpr FieldMetadata_HasSidebandStream kHasSidebandStream{};
+ void set_has_sideband_stream(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasSidebandStream::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ColorTransform =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ColorTransformProto,
+ LayerState>;
+
+ static constexpr FieldMetadata_ColorTransform kColorTransform{};
+ template <typename T = ColorTransformProto> T* set_color_transform() {
+ return BeginNestedMessage<T>(25);
+ }
+
+
+ using FieldMetadata_BlurRegions =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlurRegion,
+ LayerState>;
+
+ static constexpr FieldMetadata_BlurRegions kBlurRegions{};
+ template <typename T = BlurRegion> T* add_blur_regions() {
+ return BeginNestedMessage<T>(26);
+ }
+
+
+ using FieldMetadata_WindowInfoHandle =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerState_WindowInfo,
+ LayerState>;
+
+ static constexpr FieldMetadata_WindowInfoHandle kWindowInfoHandle{};
+ template <typename T = LayerState_WindowInfo> T* set_window_info_handle() {
+ return BeginNestedMessage<T>(27);
+ }
+
+
+ using FieldMetadata_BgColorAlpha =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState>;
+
+ static constexpr FieldMetadata_BgColorAlpha kBgColorAlpha{};
+ void set_bg_color_alpha(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_BgColorAlpha::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BgColorDataspace =
+ ::protozero::proto_utils::FieldMetadata<
+ 29,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_BgColorDataspace kBgColorDataspace{};
+ void set_bg_color_dataspace(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BgColorDataspace::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ColorSpaceAgnostic =
+ ::protozero::proto_utils::FieldMetadata<
+ 30,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState>;
+
+ static constexpr FieldMetadata_ColorSpaceAgnostic kColorSpaceAgnostic{};
+ void set_color_space_agnostic(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ColorSpaceAgnostic::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ShadowRadius =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState>;
+
+ static constexpr FieldMetadata_ShadowRadius kShadowRadius{};
+ void set_shadow_radius(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShadowRadius::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameRateSelectionPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 32,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_FrameRateSelectionPriority kFrameRateSelectionPriority{};
+ void set_frame_rate_selection_priority(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameRateSelectionPriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameRate =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState>;
+
+ static constexpr FieldMetadata_FrameRate kFrameRate{};
+ void set_frame_rate(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameRate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameRateCompatibility =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_FrameRateCompatibility kFrameRateCompatibility{};
+ void set_frame_rate_compatibility(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameRateCompatibility::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChangeFrameRateStrategy =
+ ::protozero::proto_utils::FieldMetadata<
+ 35,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_ChangeFrameRateStrategy kChangeFrameRateStrategy{};
+ void set_change_frame_rate_strategy(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChangeFrameRateStrategy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FixedTransformHint =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_FixedTransformHint kFixedTransformHint{};
+ void set_fixed_transform_hint(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FixedTransformHint::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 37,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LayerState>;
+
+ static constexpr FieldMetadata_FrameNumber kFrameNumber{};
+ void set_frame_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AutoRefresh =
+ ::protozero::proto_utils::FieldMetadata<
+ 38,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState>;
+
+ static constexpr FieldMetadata_AutoRefresh kAutoRefresh{};
+ void set_auto_refresh(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AutoRefresh::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsTrustedOverlay =
+ ::protozero::proto_utils::FieldMetadata<
+ 39,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState>;
+
+ static constexpr FieldMetadata_IsTrustedOverlay kIsTrustedOverlay{};
+ void set_is_trusted_overlay(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsTrustedOverlay::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BufferCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 40,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerState>;
+
+ static constexpr FieldMetadata_BufferCrop kBufferCrop{};
+ template <typename T = RectProto> T* set_buffer_crop() {
+ return BeginNestedMessage<T>(40);
+ }
+
+
+ using FieldMetadata_DestinationFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 41,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerState>;
+
+ static constexpr FieldMetadata_DestinationFrame kDestinationFrame{};
+ template <typename T = RectProto> T* set_destination_frame() {
+ return BeginNestedMessage<T>(41);
+ }
+
+
+ using FieldMetadata_DropInputMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 42,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ LayerState_DropInputMode,
+ LayerState>;
+
+ static constexpr FieldMetadata_DropInputMode kDropInputMode{};
+ void set_drop_input_mode(LayerState_DropInputMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_DropInputMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerState_WindowInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/12, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LayerState_WindowInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerState_WindowInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerState_WindowInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_layout_params_flags() const { return at<1>().valid(); }
+ uint32_t layout_params_flags() const { return at<1>().as_uint32(); }
+ bool has_layout_params_type() const { return at<2>().valid(); }
+ int32_t layout_params_type() const { return at<2>().as_int32(); }
+ bool has_touchable_region() const { return at<3>().valid(); }
+ ::protozero::ConstBytes touchable_region() const { return at<3>().as_bytes(); }
+ bool has_surface_inset() const { return at<4>().valid(); }
+ int32_t surface_inset() const { return at<4>().as_int32(); }
+ bool has_focusable() const { return at<5>().valid(); }
+ bool focusable() const { return at<5>().as_bool(); }
+ bool has_has_wallpaper() const { return at<6>().valid(); }
+ bool has_wallpaper() const { return at<6>().as_bool(); }
+ bool has_global_scale_factor() const { return at<7>().valid(); }
+ float global_scale_factor() const { return at<7>().as_float(); }
+ bool has_crop_layer_id() const { return at<8>().valid(); }
+ uint32_t crop_layer_id() const { return at<8>().as_uint32(); }
+ bool has_replace_touchable_region_with_crop() const { return at<9>().valid(); }
+ bool replace_touchable_region_with_crop() const { return at<9>().as_bool(); }
+ bool has_touchable_region_crop() const { return at<10>().valid(); }
+ ::protozero::ConstBytes touchable_region_crop() const { return at<10>().as_bytes(); }
+ bool has_transform() const { return at<11>().valid(); }
+ ::protozero::ConstBytes transform() const { return at<11>().as_bytes(); }
+ bool has_input_config() const { return at<12>().valid(); }
+ uint32_t input_config() const { return at<12>().as_uint32(); }
+};
+
+class LayerState_WindowInfo : public ::protozero::Message {
+ public:
+ using Decoder = LayerState_WindowInfo_Decoder;
+ enum : int32_t {
+ kLayoutParamsFlagsFieldNumber = 1,
+ kLayoutParamsTypeFieldNumber = 2,
+ kTouchableRegionFieldNumber = 3,
+ kSurfaceInsetFieldNumber = 4,
+ kFocusableFieldNumber = 5,
+ kHasWallpaperFieldNumber = 6,
+ kGlobalScaleFactorFieldNumber = 7,
+ kCropLayerIdFieldNumber = 8,
+ kReplaceTouchableRegionWithCropFieldNumber = 9,
+ kTouchableRegionCropFieldNumber = 10,
+ kTransformFieldNumber = 11,
+ kInputConfigFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerState.WindowInfo"; }
+
+
+ using FieldMetadata_LayoutParamsFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_LayoutParamsFlags kLayoutParamsFlags{};
+ void set_layout_params_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayoutParamsFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayoutParamsType =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_LayoutParamsType kLayoutParamsType{};
+ void set_layout_params_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayoutParamsType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TouchableRegion =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegionProto,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_TouchableRegion kTouchableRegion{};
+ template <typename T = RegionProto> T* set_touchable_region() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_SurfaceInset =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_SurfaceInset kSurfaceInset{};
+ void set_surface_inset(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SurfaceInset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Focusable =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_Focusable kFocusable{};
+ void set_focusable(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Focusable::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasWallpaper =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_HasWallpaper kHasWallpaper{};
+ void set_has_wallpaper(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasWallpaper::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GlobalScaleFactor =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_GlobalScaleFactor kGlobalScaleFactor{};
+ void set_global_scale_factor(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_GlobalScaleFactor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CropLayerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_CropLayerId kCropLayerId{};
+ void set_crop_layer_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CropLayerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReplaceTouchableRegionWithCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_ReplaceTouchableRegionWithCrop kReplaceTouchableRegionWithCrop{};
+ void set_replace_touchable_region_with_crop(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReplaceTouchableRegionWithCrop::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TouchableRegionCrop =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RectProto,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_TouchableRegionCrop kTouchableRegionCrop{};
+ template <typename T = RectProto> T* set_touchable_region_crop() {
+ return BeginNestedMessage<T>(10);
+ }
+
+
+ using FieldMetadata_Transform =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Transform,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_Transform kTransform{};
+ template <typename T = Transform> T* set_transform() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_InputConfig =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState_WindowInfo>;
+
+ static constexpr FieldMetadata_InputConfig kInputConfig{};
+ void set_input_config(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputConfig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerState_BufferData_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LayerState_BufferData_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerState_BufferData_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerState_BufferData_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buffer_id() const { return at<1>().valid(); }
+ uint64_t buffer_id() const { return at<1>().as_uint64(); }
+ bool has_width() const { return at<2>().valid(); }
+ uint32_t width() const { return at<2>().as_uint32(); }
+ bool has_height() const { return at<3>().valid(); }
+ uint32_t height() const { return at<3>().as_uint32(); }
+ bool has_frame_number() const { return at<4>().valid(); }
+ uint64_t frame_number() const { return at<4>().as_uint64(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+ bool has_cached_buffer_id() const { return at<6>().valid(); }
+ uint64_t cached_buffer_id() const { return at<6>().as_uint64(); }
+ bool has_pixel_format() const { return at<7>().valid(); }
+ int32_t pixel_format() const { return at<7>().as_int32(); }
+ bool has_usage() const { return at<8>().valid(); }
+ uint64_t usage() const { return at<8>().as_uint64(); }
+};
+
+class LayerState_BufferData : public ::protozero::Message {
+ public:
+ using Decoder = LayerState_BufferData_Decoder;
+ enum : int32_t {
+ kBufferIdFieldNumber = 1,
+ kWidthFieldNumber = 2,
+ kHeightFieldNumber = 3,
+ kFrameNumberFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ kCachedBufferIdFieldNumber = 6,
+ kPixelFormatFieldNumber = 7,
+ kUsageFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerState.BufferData"; }
+
+
+ using BufferDataChange = ::perfetto::protos::pbzero::LayerState_BufferData_BufferDataChange;
+ static inline const char* BufferDataChange_Name(BufferDataChange value) {
+ return ::perfetto::protos::pbzero::LayerState_BufferData_BufferDataChange_Name(value);
+ }
+
+ using PixelFormat = ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat;
+ static inline const char* PixelFormat_Name(PixelFormat value) {
+ return ::perfetto::protos::pbzero::LayerState_BufferData_PixelFormat_Name(value);
+ }
+ static inline const BufferDataChange BufferDataChangeNone = BufferDataChange::BufferDataChangeNone;
+ static inline const BufferDataChange fenceChanged = BufferDataChange::fenceChanged;
+ static inline const BufferDataChange frameNumberChanged = BufferDataChange::frameNumberChanged;
+ static inline const BufferDataChange cachedBufferChanged = BufferDataChange::cachedBufferChanged;
+ static inline const PixelFormat PIXEL_FORMAT_UNKNOWN = PixelFormat::PIXEL_FORMAT_UNKNOWN;
+ static inline const PixelFormat PIXEL_FORMAT_CUSTOM = PixelFormat::PIXEL_FORMAT_CUSTOM;
+ static inline const PixelFormat PIXEL_FORMAT_TRANSLUCENT = PixelFormat::PIXEL_FORMAT_TRANSLUCENT;
+ static inline const PixelFormat PIXEL_FORMAT_TRANSPARENT = PixelFormat::PIXEL_FORMAT_TRANSPARENT;
+ static inline const PixelFormat PIXEL_FORMAT_OPAQUE = PixelFormat::PIXEL_FORMAT_OPAQUE;
+ static inline const PixelFormat PIXEL_FORMAT_RGBA_8888 = PixelFormat::PIXEL_FORMAT_RGBA_8888;
+ static inline const PixelFormat PIXEL_FORMAT_RGBX_8888 = PixelFormat::PIXEL_FORMAT_RGBX_8888;
+ static inline const PixelFormat PIXEL_FORMAT_RGB_888 = PixelFormat::PIXEL_FORMAT_RGB_888;
+ static inline const PixelFormat PIXEL_FORMAT_RGB_565 = PixelFormat::PIXEL_FORMAT_RGB_565;
+ static inline const PixelFormat PIXEL_FORMAT_BGRA_8888 = PixelFormat::PIXEL_FORMAT_BGRA_8888;
+ static inline const PixelFormat PIXEL_FORMAT_RGBA_5551 = PixelFormat::PIXEL_FORMAT_RGBA_5551;
+ static inline const PixelFormat PIXEL_FORMAT_RGBA_4444 = PixelFormat::PIXEL_FORMAT_RGBA_4444;
+ static inline const PixelFormat PIXEL_FORMAT_RGBA_FP16 = PixelFormat::PIXEL_FORMAT_RGBA_FP16;
+ static inline const PixelFormat PIXEL_FORMAT_RGBA_1010102 = PixelFormat::PIXEL_FORMAT_RGBA_1010102;
+ static inline const PixelFormat PIXEL_FORMAT_R_8 = PixelFormat::PIXEL_FORMAT_R_8;
+
+ using FieldMetadata_BufferId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_BufferId kBufferId{};
+ void set_buffer_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Width =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_Width kWidth{};
+ void set_width(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Width::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Height =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_Height kHeight{};
+ void set_height(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Height::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_FrameNumber kFrameNumber{};
+ void set_frame_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CachedBufferId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_CachedBufferId kCachedBufferId{};
+ void set_cached_buffer_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CachedBufferId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PixelFormat =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ LayerState_BufferData_PixelFormat,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_PixelFormat kPixelFormat{};
+ void set_pixel_format(LayerState_BufferData_PixelFormat value) {
+ static constexpr uint32_t field_id = FieldMetadata_PixelFormat::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Usage =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LayerState_BufferData>;
+
+ static constexpr FieldMetadata_Usage kUsage{};
+ void set_usage(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Usage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerState_Color3_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LayerState_Color3_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerState_Color3_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerState_Color3_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_r() const { return at<1>().valid(); }
+ float r() const { return at<1>().as_float(); }
+ bool has_g() const { return at<2>().valid(); }
+ float g() const { return at<2>().as_float(); }
+ bool has_b() const { return at<3>().valid(); }
+ float b() const { return at<3>().as_float(); }
+};
+
+class LayerState_Color3 : public ::protozero::Message {
+ public:
+ using Decoder = LayerState_Color3_Decoder;
+ enum : int32_t {
+ kRFieldNumber = 1,
+ kGFieldNumber = 2,
+ kBFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerState.Color3"; }
+
+
+ using FieldMetadata_R =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_Color3>;
+
+ static constexpr FieldMetadata_R kR{};
+ void set_r(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_R::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_G =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_Color3>;
+
+ static constexpr FieldMetadata_G kG{};
+ void set_g(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_G::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_B =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_Color3>;
+
+ static constexpr FieldMetadata_B kB{};
+ void set_b(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_B::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerState_Matrix22_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LayerState_Matrix22_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerState_Matrix22_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerState_Matrix22_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dsdx() const { return at<1>().valid(); }
+ float dsdx() const { return at<1>().as_float(); }
+ bool has_dtdx() const { return at<2>().valid(); }
+ float dtdx() const { return at<2>().as_float(); }
+ bool has_dtdy() const { return at<3>().valid(); }
+ float dtdy() const { return at<3>().as_float(); }
+ bool has_dsdy() const { return at<4>().valid(); }
+ float dsdy() const { return at<4>().as_float(); }
+};
+
+class LayerState_Matrix22 : public ::protozero::Message {
+ public:
+ using Decoder = LayerState_Matrix22_Decoder;
+ enum : int32_t {
+ kDsdxFieldNumber = 1,
+ kDtdxFieldNumber = 2,
+ kDtdyFieldNumber = 3,
+ kDsdyFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerState.Matrix22"; }
+
+
+ using FieldMetadata_Dsdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_Matrix22>;
+
+ static constexpr FieldMetadata_Dsdx kDsdx{};
+ void set_dsdx(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dsdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dtdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_Matrix22>;
+
+ static constexpr FieldMetadata_Dtdx kDtdx{};
+ void set_dtdx(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dtdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dtdy =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_Matrix22>;
+
+ static constexpr FieldMetadata_Dtdy kDtdy{};
+ void set_dtdy(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dtdy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dsdy =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ LayerState_Matrix22>;
+
+ static constexpr FieldMetadata_Dsdy kDsdy{};
+ void set_dsdy(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dsdy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TransactionState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TransactionState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TransactionState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TransactionState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_uid() const { return at<2>().valid(); }
+ int32_t uid() const { return at<2>().as_int32(); }
+ bool has_vsync_id() const { return at<3>().valid(); }
+ int64_t vsync_id() const { return at<3>().as_int64(); }
+ bool has_input_event_id() const { return at<4>().valid(); }
+ int32_t input_event_id() const { return at<4>().as_int32(); }
+ bool has_post_time() const { return at<5>().valid(); }
+ int64_t post_time() const { return at<5>().as_int64(); }
+ bool has_transaction_id() const { return at<6>().valid(); }
+ uint64_t transaction_id() const { return at<6>().as_uint64(); }
+ bool has_layer_changes() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> layer_changes() const { return GetRepeated<::protozero::ConstBytes>(7); }
+ bool has_display_changes() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> display_changes() const { return GetRepeated<::protozero::ConstBytes>(8); }
+ bool has_merged_transaction_ids() const { return at<9>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> merged_transaction_ids() const { return GetRepeated<uint64_t>(9); }
+};
+
+class TransactionState : public ::protozero::Message {
+ public:
+ using Decoder = TransactionState_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kUidFieldNumber = 2,
+ kVsyncIdFieldNumber = 3,
+ kInputEventIdFieldNumber = 4,
+ kPostTimeFieldNumber = 5,
+ kTransactionIdFieldNumber = 6,
+ kLayerChangesFieldNumber = 7,
+ kDisplayChangesFieldNumber = 8,
+ kMergedTransactionIdsFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TransactionState"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TransactionState>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TransactionState>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VsyncId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TransactionState>;
+
+ static constexpr FieldMetadata_VsyncId kVsyncId{};
+ void set_vsync_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VsyncId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InputEventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TransactionState>;
+
+ static constexpr FieldMetadata_InputEventId kInputEventId{};
+ void set_input_event_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InputEventId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PostTime =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TransactionState>;
+
+ static constexpr FieldMetadata_PostTime kPostTime{};
+ void set_post_time(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PostTime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TransactionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TransactionState>;
+
+ static constexpr FieldMetadata_TransactionId kTransactionId{};
+ void set_transaction_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TransactionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerChanges =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerState,
+ TransactionState>;
+
+ static constexpr FieldMetadata_LayerChanges kLayerChanges{};
+ template <typename T = LayerState> T* add_layer_changes() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_DisplayChanges =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DisplayState,
+ TransactionState>;
+
+ static constexpr FieldMetadata_DisplayChanges kDisplayChanges{};
+ template <typename T = DisplayState> T* add_display_changes() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_MergedTransactionIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TransactionState>;
+
+ static constexpr FieldMetadata_MergedTransactionIds kMergedTransactionIds{};
+ void add_merged_transaction_ids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MergedTransactionIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Transform_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Transform_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Transform_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Transform_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dsdx() const { return at<1>().valid(); }
+ float dsdx() const { return at<1>().as_float(); }
+ bool has_dtdx() const { return at<2>().valid(); }
+ float dtdx() const { return at<2>().as_float(); }
+ bool has_dtdy() const { return at<3>().valid(); }
+ float dtdy() const { return at<3>().as_float(); }
+ bool has_dsdy() const { return at<4>().valid(); }
+ float dsdy() const { return at<4>().as_float(); }
+ bool has_tx() const { return at<5>().valid(); }
+ float tx() const { return at<5>().as_float(); }
+ bool has_ty() const { return at<6>().valid(); }
+ float ty() const { return at<6>().as_float(); }
+};
+
+class Transform : public ::protozero::Message {
+ public:
+ using Decoder = Transform_Decoder;
+ enum : int32_t {
+ kDsdxFieldNumber = 1,
+ kDtdxFieldNumber = 2,
+ kDtdyFieldNumber = 3,
+ kDsdyFieldNumber = 4,
+ kTxFieldNumber = 5,
+ kTyFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Transform"; }
+
+
+ using FieldMetadata_Dsdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ Transform>;
+
+ static constexpr FieldMetadata_Dsdx kDsdx{};
+ void set_dsdx(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dsdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dtdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ Transform>;
+
+ static constexpr FieldMetadata_Dtdx kDtdx{};
+ void set_dtdx(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dtdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dtdy =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ Transform>;
+
+ static constexpr FieldMetadata_Dtdy kDtdy{};
+ void set_dtdy(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dtdy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dsdy =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ Transform>;
+
+ static constexpr FieldMetadata_Dsdy kDsdy{};
+ void set_dsdy(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dsdy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tx =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ Transform>;
+
+ static constexpr FieldMetadata_Tx kTx{};
+ void set_tx(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ty =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ Transform>;
+
+ static constexpr FieldMetadata_Ty kTy{};
+ void set_ty(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ty::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LayerCreationArgs_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LayerCreationArgs_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LayerCreationArgs_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LayerCreationArgs_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_layer_id() const { return at<1>().valid(); }
+ uint32_t layer_id() const { return at<1>().as_uint32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_parent_id() const { return at<4>().valid(); }
+ uint32_t parent_id() const { return at<4>().as_uint32(); }
+ bool has_mirror_from_id() const { return at<5>().valid(); }
+ uint32_t mirror_from_id() const { return at<5>().as_uint32(); }
+ bool has_add_to_root() const { return at<6>().valid(); }
+ bool add_to_root() const { return at<6>().as_bool(); }
+ bool has_layer_stack_to_mirror() const { return at<7>().valid(); }
+ uint32_t layer_stack_to_mirror() const { return at<7>().as_uint32(); }
+};
+
+class LayerCreationArgs : public ::protozero::Message {
+ public:
+ using Decoder = LayerCreationArgs_Decoder;
+ enum : int32_t {
+ kLayerIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kParentIdFieldNumber = 4,
+ kMirrorFromIdFieldNumber = 5,
+ kAddToRootFieldNumber = 6,
+ kLayerStackToMirrorFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LayerCreationArgs"; }
+
+
+ using FieldMetadata_LayerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerCreationArgs>;
+
+ static constexpr FieldMetadata_LayerId kLayerId{};
+ void set_layer_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LayerCreationArgs>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerCreationArgs>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ParentId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerCreationArgs>;
+
+ static constexpr FieldMetadata_ParentId kParentId{};
+ void set_parent_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParentId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MirrorFromId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerCreationArgs>;
+
+ static constexpr FieldMetadata_MirrorFromId kMirrorFromId{};
+ void set_mirror_from_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MirrorFromId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AddToRoot =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ LayerCreationArgs>;
+
+ static constexpr FieldMetadata_AddToRoot kAddToRoot{};
+ void set_add_to_root(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AddToRoot::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerStackToMirror =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LayerCreationArgs>;
+
+ static constexpr FieldMetadata_LayerStackToMirror kLayerStackToMirror{};
+ void set_layer_stack_to_mirror(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerStackToMirror::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DisplayInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/12, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DisplayInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DisplayInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DisplayInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_layer_stack() const { return at<1>().valid(); }
+ uint32_t layer_stack() const { return at<1>().as_uint32(); }
+ bool has_display_id() const { return at<2>().valid(); }
+ int32_t display_id() const { return at<2>().as_int32(); }
+ bool has_logical_width() const { return at<3>().valid(); }
+ int32_t logical_width() const { return at<3>().as_int32(); }
+ bool has_logical_height() const { return at<4>().valid(); }
+ int32_t logical_height() const { return at<4>().as_int32(); }
+ bool has_transform_inverse() const { return at<5>().valid(); }
+ ::protozero::ConstBytes transform_inverse() const { return at<5>().as_bytes(); }
+ bool has_transform() const { return at<6>().valid(); }
+ ::protozero::ConstBytes transform() const { return at<6>().as_bytes(); }
+ bool has_receives_input() const { return at<7>().valid(); }
+ bool receives_input() const { return at<7>().as_bool(); }
+ bool has_is_secure() const { return at<8>().valid(); }
+ bool is_secure() const { return at<8>().as_bool(); }
+ bool has_is_primary() const { return at<9>().valid(); }
+ bool is_primary() const { return at<9>().as_bool(); }
+ bool has_is_virtual() const { return at<10>().valid(); }
+ bool is_virtual() const { return at<10>().as_bool(); }
+ bool has_rotation_flags() const { return at<11>().valid(); }
+ int32_t rotation_flags() const { return at<11>().as_int32(); }
+ bool has_transform_hint() const { return at<12>().valid(); }
+ int32_t transform_hint() const { return at<12>().as_int32(); }
+};
+
+class DisplayInfo : public ::protozero::Message {
+ public:
+ using Decoder = DisplayInfo_Decoder;
+ enum : int32_t {
+ kLayerStackFieldNumber = 1,
+ kDisplayIdFieldNumber = 2,
+ kLogicalWidthFieldNumber = 3,
+ kLogicalHeightFieldNumber = 4,
+ kTransformInverseFieldNumber = 5,
+ kTransformFieldNumber = 6,
+ kReceivesInputFieldNumber = 7,
+ kIsSecureFieldNumber = 8,
+ kIsPrimaryFieldNumber = 9,
+ kIsVirtualFieldNumber = 10,
+ kRotationFlagsFieldNumber = 11,
+ kTransformHintFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DisplayInfo"; }
+
+
+ using FieldMetadata_LayerStack =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_LayerStack kLayerStack{};
+ void set_layer_stack(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerStack::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisplayId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_DisplayId kDisplayId{};
+ void set_display_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisplayId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LogicalWidth =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_LogicalWidth kLogicalWidth{};
+ void set_logical_width(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogicalWidth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LogicalHeight =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_LogicalHeight kLogicalHeight{};
+ void set_logical_height(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogicalHeight::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TransformInverse =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Transform,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_TransformInverse kTransformInverse{};
+ template <typename T = Transform> T* set_transform_inverse() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_Transform =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Transform,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_Transform kTransform{};
+ template <typename T = Transform> T* set_transform() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_ReceivesInput =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_ReceivesInput kReceivesInput{};
+ void set_receives_input(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReceivesInput::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsSecure =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_IsSecure kIsSecure{};
+ void set_is_secure(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsSecure::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsPrimary =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_IsPrimary kIsPrimary{};
+ void set_is_primary(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsPrimary::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsVirtual =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_IsVirtual kIsVirtual{};
+ void set_is_virtual(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsVirtual::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RotationFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_RotationFlags kRotationFlags{};
+ void set_rotation_flags(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RotationFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TransformHint =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DisplayInfo>;
+
+ static constexpr FieldMetadata_TransformHint kTransformHint{};
+ void set_transform_hint(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TransformHint::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TransactionTraceEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TransactionTraceEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TransactionTraceEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TransactionTraceEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_elapsed_realtime_nanos() const { return at<1>().valid(); }
+ int64_t elapsed_realtime_nanos() const { return at<1>().as_int64(); }
+ bool has_vsync_id() const { return at<2>().valid(); }
+ int64_t vsync_id() const { return at<2>().as_int64(); }
+ bool has_transactions() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> transactions() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_added_layers() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> added_layers() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_destroyed_layers() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> destroyed_layers() const { return GetRepeated<uint32_t>(5); }
+ bool has_added_displays() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> added_displays() const { return GetRepeated<::protozero::ConstBytes>(6); }
+ bool has_removed_displays() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> removed_displays() const { return GetRepeated<int32_t>(7); }
+ bool has_destroyed_layer_handles() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> destroyed_layer_handles() const { return GetRepeated<uint32_t>(8); }
+ bool has_displays_changed() const { return at<9>().valid(); }
+ bool displays_changed() const { return at<9>().as_bool(); }
+ bool has_displays() const { return at<10>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> displays() const { return GetRepeated<::protozero::ConstBytes>(10); }
+};
+
+class TransactionTraceEntry : public ::protozero::Message {
+ public:
+ using Decoder = TransactionTraceEntry_Decoder;
+ enum : int32_t {
+ kElapsedRealtimeNanosFieldNumber = 1,
+ kVsyncIdFieldNumber = 2,
+ kTransactionsFieldNumber = 3,
+ kAddedLayersFieldNumber = 4,
+ kDestroyedLayersFieldNumber = 5,
+ kAddedDisplaysFieldNumber = 6,
+ kRemovedDisplaysFieldNumber = 7,
+ kDestroyedLayerHandlesFieldNumber = 8,
+ kDisplaysChangedFieldNumber = 9,
+ kDisplaysFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TransactionTraceEntry"; }
+
+
+ using FieldMetadata_ElapsedRealtimeNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_ElapsedRealtimeNanos kElapsedRealtimeNanos{};
+ void set_elapsed_realtime_nanos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ElapsedRealtimeNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VsyncId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_VsyncId kVsyncId{};
+ void set_vsync_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VsyncId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Transactions =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransactionState,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_Transactions kTransactions{};
+ template <typename T = TransactionState> T* add_transactions() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_AddedLayers =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LayerCreationArgs,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_AddedLayers kAddedLayers{};
+ template <typename T = LayerCreationArgs> T* add_added_layers() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_DestroyedLayers =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_DestroyedLayers kDestroyedLayers{};
+ void add_destroyed_layers(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DestroyedLayers::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AddedDisplays =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DisplayState,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_AddedDisplays kAddedDisplays{};
+ template <typename T = DisplayState> T* add_added_displays() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_RemovedDisplays =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_RemovedDisplays kRemovedDisplays{};
+ void add_removed_displays(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RemovedDisplays::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DestroyedLayerHandles =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_DestroyedLayerHandles kDestroyedLayerHandles{};
+ void add_destroyed_layer_handles(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DestroyedLayerHandles::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DisplaysChanged =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_DisplaysChanged kDisplaysChanged{};
+ void set_displays_changed(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DisplaysChanged::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Displays =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DisplayInfo,
+ TransactionTraceEntry>;
+
+ static constexpr FieldMetadata_Displays kDisplays{};
+ template <typename T = DisplayInfo> T* add_displays() {
+ return BeginNestedMessage<T>(10);
+ }
+
+};
+
+class TransactionTraceFile_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TransactionTraceFile_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TransactionTraceFile_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TransactionTraceFile_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_magic_number() const { return at<1>().valid(); }
+ uint64_t magic_number() const { return at<1>().as_uint64(); }
+ bool has_entry() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> entry() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_real_to_elapsed_time_offset_nanos() const { return at<3>().valid(); }
+ uint64_t real_to_elapsed_time_offset_nanos() const { return at<3>().as_uint64(); }
+ bool has_version() const { return at<4>().valid(); }
+ uint32_t version() const { return at<4>().as_uint32(); }
+};
+
+class TransactionTraceFile : public ::protozero::Message {
+ public:
+ using Decoder = TransactionTraceFile_Decoder;
+ enum : int32_t {
+ kMagicNumberFieldNumber = 1,
+ kEntryFieldNumber = 2,
+ kRealToElapsedTimeOffsetNanosFieldNumber = 3,
+ kVersionFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TransactionTraceFile"; }
+
+
+ using MagicNumber = ::perfetto::protos::pbzero::TransactionTraceFile_MagicNumber;
+ static inline const char* MagicNumber_Name(MagicNumber value) {
+ return ::perfetto::protos::pbzero::TransactionTraceFile_MagicNumber_Name(value);
+ }
+ static inline const MagicNumber INVALID = MagicNumber::INVALID;
+ static inline const MagicNumber MAGIC_NUMBER_L = MagicNumber::MAGIC_NUMBER_L;
+ static inline const MagicNumber MAGIC_NUMBER_H = MagicNumber::MAGIC_NUMBER_H;
+
+ using FieldMetadata_MagicNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ TransactionTraceFile>;
+
+ static constexpr FieldMetadata_MagicNumber kMagicNumber{};
+ void set_magic_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MagicNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Entry =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TransactionTraceEntry,
+ TransactionTraceFile>;
+
+ static constexpr FieldMetadata_Entry kEntry{};
+ template <typename T = TransactionTraceEntry> T* add_entry() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_RealToElapsedTimeOffsetNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ TransactionTraceFile>;
+
+ static constexpr FieldMetadata_RealToElapsedTimeOffsetNanos kRealToElapsedTimeOffsetNanos{};
+ void set_real_to_elapsed_time_offset_nanos(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RealToElapsedTimeOffsetNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Version =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TransactionTraceFile>;
+
+ static constexpr FieldMetadata_Version kVersion{};
+ void set_version(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Version::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_CHROME_BENCHMARK_METADATA_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_CHROME_BENCHMARK_METADATA_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeBenchmarkMetadata_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeBenchmarkMetadata_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeBenchmarkMetadata_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeBenchmarkMetadata_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_benchmark_start_time_us() const { return at<1>().valid(); }
+ int64_t benchmark_start_time_us() const { return at<1>().as_int64(); }
+ bool has_story_run_time_us() const { return at<2>().valid(); }
+ int64_t story_run_time_us() const { return at<2>().as_int64(); }
+ bool has_benchmark_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars benchmark_name() const { return at<3>().as_string(); }
+ bool has_benchmark_description() const { return at<4>().valid(); }
+ ::protozero::ConstChars benchmark_description() const { return at<4>().as_string(); }
+ bool has_label() const { return at<5>().valid(); }
+ ::protozero::ConstChars label() const { return at<5>().as_string(); }
+ bool has_story_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars story_name() const { return at<6>().as_string(); }
+ bool has_story_tags() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> story_tags() const { return GetRepeated<::protozero::ConstChars>(7); }
+ bool has_story_run_index() const { return at<8>().valid(); }
+ int32_t story_run_index() const { return at<8>().as_int32(); }
+ bool has_had_failures() const { return at<9>().valid(); }
+ bool had_failures() const { return at<9>().as_bool(); }
+};
+
+class ChromeBenchmarkMetadata : public ::protozero::Message {
+ public:
+ using Decoder = ChromeBenchmarkMetadata_Decoder;
+ enum : int32_t {
+ kBenchmarkStartTimeUsFieldNumber = 1,
+ kStoryRunTimeUsFieldNumber = 2,
+ kBenchmarkNameFieldNumber = 3,
+ kBenchmarkDescriptionFieldNumber = 4,
+ kLabelFieldNumber = 5,
+ kStoryNameFieldNumber = 6,
+ kStoryTagsFieldNumber = 7,
+ kStoryRunIndexFieldNumber = 8,
+ kHadFailuresFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeBenchmarkMetadata"; }
+
+
+ using FieldMetadata_BenchmarkStartTimeUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_BenchmarkStartTimeUs kBenchmarkStartTimeUs{};
+ void set_benchmark_start_time_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BenchmarkStartTimeUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StoryRunTimeUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_StoryRunTimeUs kStoryRunTimeUs{};
+ void set_story_run_time_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StoryRunTimeUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BenchmarkName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_BenchmarkName kBenchmarkName{};
+ void set_benchmark_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_BenchmarkName::kFieldId, data, size);
+ }
+ void set_benchmark_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_BenchmarkName::kFieldId, chars.data, chars.size);
+ }
+ void set_benchmark_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_BenchmarkName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BenchmarkDescription =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_BenchmarkDescription kBenchmarkDescription{};
+ void set_benchmark_description(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_BenchmarkDescription::kFieldId, data, size);
+ }
+ void set_benchmark_description(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_BenchmarkDescription::kFieldId, chars.data, chars.size);
+ }
+ void set_benchmark_description(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_BenchmarkDescription::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Label =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_Label kLabel{};
+ void set_label(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Label::kFieldId, data, size);
+ }
+ void set_label(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Label::kFieldId, chars.data, chars.size);
+ }
+ void set_label(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Label::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StoryName =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_StoryName kStoryName{};
+ void set_story_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StoryName::kFieldId, data, size);
+ }
+ void set_story_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StoryName::kFieldId, chars.data, chars.size);
+ }
+ void set_story_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StoryName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StoryTags =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_StoryTags kStoryTags{};
+ void add_story_tags(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StoryTags::kFieldId, data, size);
+ }
+ void add_story_tags(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StoryTags::kFieldId, chars.data, chars.size);
+ }
+ void add_story_tags(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StoryTags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StoryRunIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_StoryRunIndex kStoryRunIndex{};
+ void set_story_run_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StoryRunIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HadFailures =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeBenchmarkMetadata>;
+
+ static constexpr FieldMetadata_HadFailures kHadFailures{};
+ void set_had_failures(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HadFailures::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_CHROME_METADATA_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_CHROME_METADATA_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class BackgroundTracingMetadata;
+class BackgroundTracingMetadata_TriggerRule;
+class BackgroundTracingMetadata_TriggerRule_HistogramRule;
+class BackgroundTracingMetadata_TriggerRule_NamedRule;
+class ChromeMetadataPacket_FinchHash;
+namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule_NamedRule {
+enum EventType : int32_t;
+} // namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule_NamedRule
+using BackgroundTracingMetadata_TriggerRule_NamedRule_EventType = perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule_NamedRule::EventType;
+namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule {
+enum TriggerType : int32_t;
+} // namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule
+using BackgroundTracingMetadata_TriggerRule_TriggerType = perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule::TriggerType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule {
+enum TriggerType : int32_t {
+ TRIGGER_UNSPECIFIED = 0,
+ MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE = 1,
+ MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED = 2,
+};
+} // namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule
+using BackgroundTracingMetadata_TriggerRule_TriggerType = perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule::TriggerType;
+
+
+constexpr BackgroundTracingMetadata_TriggerRule_TriggerType BackgroundTracingMetadata_TriggerRule_TriggerType_MIN = BackgroundTracingMetadata_TriggerRule_TriggerType::TRIGGER_UNSPECIFIED;
+constexpr BackgroundTracingMetadata_TriggerRule_TriggerType BackgroundTracingMetadata_TriggerRule_TriggerType_MAX = BackgroundTracingMetadata_TriggerRule_TriggerType::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* BackgroundTracingMetadata_TriggerRule_TriggerType_Name(::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_TriggerType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_TriggerType::TRIGGER_UNSPECIFIED:
+ return "TRIGGER_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_TriggerType::MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE:
+ return "MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_TriggerType::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED:
+ return "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule_NamedRule {
+enum EventType : int32_t {
+ UNSPECIFIED = 0,
+ SESSION_RESTORE = 1,
+ NAVIGATION = 2,
+ STARTUP = 3,
+ REACHED_CODE = 4,
+ CONTENT_TRIGGER = 5,
+ TEST_RULE = 1000,
+};
+} // namespace perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule_NamedRule
+using BackgroundTracingMetadata_TriggerRule_NamedRule_EventType = perfetto_pbzero_enum_BackgroundTracingMetadata_TriggerRule_NamedRule::EventType;
+
+
+constexpr BackgroundTracingMetadata_TriggerRule_NamedRule_EventType BackgroundTracingMetadata_TriggerRule_NamedRule_EventType_MIN = BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::UNSPECIFIED;
+constexpr BackgroundTracingMetadata_TriggerRule_NamedRule_EventType BackgroundTracingMetadata_TriggerRule_NamedRule_EventType_MAX = BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::TEST_RULE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* BackgroundTracingMetadata_TriggerRule_NamedRule_EventType_Name(::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::UNSPECIFIED:
+ return "UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::SESSION_RESTORE:
+ return "SESSION_RESTORE";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::NAVIGATION:
+ return "NAVIGATION";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::STARTUP:
+ return "STARTUP";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::REACHED_CODE:
+ return "REACHED_CODE";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::CONTENT_TRIGGER:
+ return "CONTENT_TRIGGER";
+
+ case ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType::TEST_RULE:
+ return "TEST_RULE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class BackgroundTracingMetadata_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ BackgroundTracingMetadata_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BackgroundTracingMetadata_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BackgroundTracingMetadata_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_triggered_rule() const { return at<1>().valid(); }
+ ::protozero::ConstBytes triggered_rule() const { return at<1>().as_bytes(); }
+ bool has_active_rules() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> active_rules() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_scenario_name_hash() const { return at<3>().valid(); }
+ uint32_t scenario_name_hash() const { return at<3>().as_uint32(); }
+};
+
+class BackgroundTracingMetadata : public ::protozero::Message {
+ public:
+ using Decoder = BackgroundTracingMetadata_Decoder;
+ enum : int32_t {
+ kTriggeredRuleFieldNumber = 1,
+ kActiveRulesFieldNumber = 2,
+ kScenarioNameHashFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BackgroundTracingMetadata"; }
+
+ using TriggerRule = ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule;
+
+ using FieldMetadata_TriggeredRule =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BackgroundTracingMetadata_TriggerRule,
+ BackgroundTracingMetadata>;
+
+ static constexpr FieldMetadata_TriggeredRule kTriggeredRule{};
+ template <typename T = BackgroundTracingMetadata_TriggerRule> T* set_triggered_rule() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ActiveRules =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BackgroundTracingMetadata_TriggerRule,
+ BackgroundTracingMetadata>;
+
+ static constexpr FieldMetadata_ActiveRules kActiveRules{};
+ template <typename T = BackgroundTracingMetadata_TriggerRule> T* add_active_rules() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_ScenarioNameHash =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32,
+ uint32_t,
+ BackgroundTracingMetadata>;
+
+ static constexpr FieldMetadata_ScenarioNameHash kScenarioNameHash{};
+ void set_scenario_name_hash(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScenarioNameHash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BackgroundTracingMetadata_TriggerRule_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BackgroundTracingMetadata_TriggerRule_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BackgroundTracingMetadata_TriggerRule_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BackgroundTracingMetadata_TriggerRule_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trigger_type() const { return at<1>().valid(); }
+ int32_t trigger_type() const { return at<1>().as_int32(); }
+ bool has_histogram_rule() const { return at<2>().valid(); }
+ ::protozero::ConstBytes histogram_rule() const { return at<2>().as_bytes(); }
+ bool has_named_rule() const { return at<3>().valid(); }
+ ::protozero::ConstBytes named_rule() const { return at<3>().as_bytes(); }
+ bool has_name_hash() const { return at<4>().valid(); }
+ uint32_t name_hash() const { return at<4>().as_uint32(); }
+};
+
+class BackgroundTracingMetadata_TriggerRule : public ::protozero::Message {
+ public:
+ using Decoder = BackgroundTracingMetadata_TriggerRule_Decoder;
+ enum : int32_t {
+ kTriggerTypeFieldNumber = 1,
+ kHistogramRuleFieldNumber = 2,
+ kNamedRuleFieldNumber = 3,
+ kNameHashFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BackgroundTracingMetadata.TriggerRule"; }
+
+ using HistogramRule = ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_HistogramRule;
+ using NamedRule = ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule;
+
+ using TriggerType = ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_TriggerType;
+ static inline const char* TriggerType_Name(TriggerType value) {
+ return ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_TriggerType_Name(value);
+ }
+ static inline const TriggerType TRIGGER_UNSPECIFIED = TriggerType::TRIGGER_UNSPECIFIED;
+ static inline const TriggerType MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE = TriggerType::MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE;
+ static inline const TriggerType MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED = TriggerType::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED;
+
+ using FieldMetadata_TriggerType =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ BackgroundTracingMetadata_TriggerRule_TriggerType,
+ BackgroundTracingMetadata_TriggerRule>;
+
+ static constexpr FieldMetadata_TriggerType kTriggerType{};
+ void set_trigger_type(BackgroundTracingMetadata_TriggerRule_TriggerType value) {
+ static constexpr uint32_t field_id = FieldMetadata_TriggerType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HistogramRule =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BackgroundTracingMetadata_TriggerRule_HistogramRule,
+ BackgroundTracingMetadata_TriggerRule>;
+
+ static constexpr FieldMetadata_HistogramRule kHistogramRule{};
+ template <typename T = BackgroundTracingMetadata_TriggerRule_HistogramRule> T* set_histogram_rule() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_NamedRule =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BackgroundTracingMetadata_TriggerRule_NamedRule,
+ BackgroundTracingMetadata_TriggerRule>;
+
+ static constexpr FieldMetadata_NamedRule kNamedRule{};
+ template <typename T = BackgroundTracingMetadata_TriggerRule_NamedRule> T* set_named_rule() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_NameHash =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32,
+ uint32_t,
+ BackgroundTracingMetadata_TriggerRule>;
+
+ static constexpr FieldMetadata_NameHash kNameHash{};
+ void set_name_hash(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameHash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BackgroundTracingMetadata_TriggerRule_NamedRule_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BackgroundTracingMetadata_TriggerRule_NamedRule_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BackgroundTracingMetadata_TriggerRule_NamedRule_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BackgroundTracingMetadata_TriggerRule_NamedRule_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_type() const { return at<1>().valid(); }
+ int32_t event_type() const { return at<1>().as_int32(); }
+ bool has_content_trigger_name_hash() const { return at<2>().valid(); }
+ uint64_t content_trigger_name_hash() const { return at<2>().as_uint64(); }
+};
+
+class BackgroundTracingMetadata_TriggerRule_NamedRule : public ::protozero::Message {
+ public:
+ using Decoder = BackgroundTracingMetadata_TriggerRule_NamedRule_Decoder;
+ enum : int32_t {
+ kEventTypeFieldNumber = 1,
+ kContentTriggerNameHashFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BackgroundTracingMetadata.TriggerRule.NamedRule"; }
+
+
+ using EventType = ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType;
+ static inline const char* EventType_Name(EventType value) {
+ return ::perfetto::protos::pbzero::BackgroundTracingMetadata_TriggerRule_NamedRule_EventType_Name(value);
+ }
+ static inline const EventType UNSPECIFIED = EventType::UNSPECIFIED;
+ static inline const EventType SESSION_RESTORE = EventType::SESSION_RESTORE;
+ static inline const EventType NAVIGATION = EventType::NAVIGATION;
+ static inline const EventType STARTUP = EventType::STARTUP;
+ static inline const EventType REACHED_CODE = EventType::REACHED_CODE;
+ static inline const EventType CONTENT_TRIGGER = EventType::CONTENT_TRIGGER;
+ static inline const EventType TEST_RULE = EventType::TEST_RULE;
+
+ using FieldMetadata_EventType =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ BackgroundTracingMetadata_TriggerRule_NamedRule_EventType,
+ BackgroundTracingMetadata_TriggerRule_NamedRule>;
+
+ static constexpr FieldMetadata_EventType kEventType{};
+ void set_event_type(BackgroundTracingMetadata_TriggerRule_NamedRule_EventType value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ContentTriggerNameHash =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ BackgroundTracingMetadata_TriggerRule_NamedRule>;
+
+ static constexpr FieldMetadata_ContentTriggerNameHash kContentTriggerNameHash{};
+ void set_content_trigger_name_hash(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ContentTriggerNameHash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BackgroundTracingMetadata_TriggerRule_HistogramRule_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BackgroundTracingMetadata_TriggerRule_HistogramRule_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BackgroundTracingMetadata_TriggerRule_HistogramRule_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BackgroundTracingMetadata_TriggerRule_HistogramRule_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_histogram_name_hash() const { return at<1>().valid(); }
+ uint64_t histogram_name_hash() const { return at<1>().as_uint64(); }
+ bool has_histogram_min_trigger() const { return at<2>().valid(); }
+ int64_t histogram_min_trigger() const { return at<2>().as_int64(); }
+ bool has_histogram_max_trigger() const { return at<3>().valid(); }
+ int64_t histogram_max_trigger() const { return at<3>().as_int64(); }
+};
+
+class BackgroundTracingMetadata_TriggerRule_HistogramRule : public ::protozero::Message {
+ public:
+ using Decoder = BackgroundTracingMetadata_TriggerRule_HistogramRule_Decoder;
+ enum : int32_t {
+ kHistogramNameHashFieldNumber = 1,
+ kHistogramMinTriggerFieldNumber = 2,
+ kHistogramMaxTriggerFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BackgroundTracingMetadata.TriggerRule.HistogramRule"; }
+
+
+ using FieldMetadata_HistogramNameHash =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ BackgroundTracingMetadata_TriggerRule_HistogramRule>;
+
+ static constexpr FieldMetadata_HistogramNameHash kHistogramNameHash{};
+ void set_histogram_name_hash(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HistogramNameHash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HistogramMinTrigger =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BackgroundTracingMetadata_TriggerRule_HistogramRule>;
+
+ static constexpr FieldMetadata_HistogramMinTrigger kHistogramMinTrigger{};
+ void set_histogram_min_trigger(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HistogramMinTrigger::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HistogramMaxTrigger =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BackgroundTracingMetadata_TriggerRule_HistogramRule>;
+
+ static constexpr FieldMetadata_HistogramMaxTrigger kHistogramMaxTrigger{};
+ void set_histogram_max_trigger(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HistogramMaxTrigger::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeMetadataPacket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeMetadataPacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeMetadataPacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeMetadataPacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_background_tracing_metadata() const { return at<1>().valid(); }
+ ::protozero::ConstBytes background_tracing_metadata() const { return at<1>().as_bytes(); }
+ bool has_chrome_version_code() const { return at<2>().valid(); }
+ int32_t chrome_version_code() const { return at<2>().as_int32(); }
+ bool has_enabled_categories() const { return at<3>().valid(); }
+ ::protozero::ConstChars enabled_categories() const { return at<3>().as_string(); }
+ bool has_field_trial_hashes() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> field_trial_hashes() const { return GetRepeated<::protozero::ConstBytes>(4); }
+};
+
+class ChromeMetadataPacket : public ::protozero::Message {
+ public:
+ using Decoder = ChromeMetadataPacket_Decoder;
+ enum : int32_t {
+ kBackgroundTracingMetadataFieldNumber = 1,
+ kChromeVersionCodeFieldNumber = 2,
+ kEnabledCategoriesFieldNumber = 3,
+ kFieldTrialHashesFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeMetadataPacket"; }
+
+ using FinchHash = ::perfetto::protos::pbzero::ChromeMetadataPacket_FinchHash;
+
+ using FieldMetadata_BackgroundTracingMetadata =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BackgroundTracingMetadata,
+ ChromeMetadataPacket>;
+
+ static constexpr FieldMetadata_BackgroundTracingMetadata kBackgroundTracingMetadata{};
+ template <typename T = BackgroundTracingMetadata> T* set_background_tracing_metadata() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ChromeVersionCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeMetadataPacket>;
+
+ static constexpr FieldMetadata_ChromeVersionCode kChromeVersionCode{};
+ void set_chrome_version_code(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChromeVersionCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnabledCategories =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeMetadataPacket>;
+
+ static constexpr FieldMetadata_EnabledCategories kEnabledCategories{};
+ void set_enabled_categories(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_EnabledCategories::kFieldId, data, size);
+ }
+ void set_enabled_categories(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_EnabledCategories::kFieldId, chars.data, chars.size);
+ }
+ void set_enabled_categories(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnabledCategories::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FieldTrialHashes =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeMetadataPacket_FinchHash,
+ ChromeMetadataPacket>;
+
+ static constexpr FieldMetadata_FieldTrialHashes kFieldTrialHashes{};
+ template <typename T = ChromeMetadataPacket_FinchHash> T* add_field_trial_hashes() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+class ChromeMetadataPacket_FinchHash_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeMetadataPacket_FinchHash_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeMetadataPacket_FinchHash_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeMetadataPacket_FinchHash_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ uint32_t name() const { return at<1>().as_uint32(); }
+ bool has_group() const { return at<2>().valid(); }
+ uint32_t group() const { return at<2>().as_uint32(); }
+};
+
+class ChromeMetadataPacket_FinchHash : public ::protozero::Message {
+ public:
+ using Decoder = ChromeMetadataPacket_FinchHash_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kGroupFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeMetadataPacket.FinchHash"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeMetadataPacket_FinchHash>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeMetadataPacket_FinchHash>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_CHROME_TRACE_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_CHROME_TRACE_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ChromeLegacyJsonTrace;
+class ChromeMetadata;
+class ChromeStringTableEntry;
+class ChromeTraceEvent;
+class ChromeTraceEvent_Arg;
+class ChromeTracedValue;
+namespace perfetto_pbzero_enum_ChromeLegacyJsonTrace {
+enum TraceType : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeLegacyJsonTrace
+using ChromeLegacyJsonTrace_TraceType = perfetto_pbzero_enum_ChromeLegacyJsonTrace::TraceType;
+namespace perfetto_pbzero_enum_ChromeTracedValue {
+enum NestedType : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeTracedValue
+using ChromeTracedValue_NestedType = perfetto_pbzero_enum_ChromeTracedValue::NestedType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeLegacyJsonTrace {
+enum TraceType : int32_t {
+ USER_TRACE = 0,
+ SYSTEM_TRACE = 1,
+};
+} // namespace perfetto_pbzero_enum_ChromeLegacyJsonTrace
+using ChromeLegacyJsonTrace_TraceType = perfetto_pbzero_enum_ChromeLegacyJsonTrace::TraceType;
+
+
+constexpr ChromeLegacyJsonTrace_TraceType ChromeLegacyJsonTrace_TraceType_MIN = ChromeLegacyJsonTrace_TraceType::USER_TRACE;
+constexpr ChromeLegacyJsonTrace_TraceType ChromeLegacyJsonTrace_TraceType_MAX = ChromeLegacyJsonTrace_TraceType::SYSTEM_TRACE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeLegacyJsonTrace_TraceType_Name(::perfetto::protos::pbzero::ChromeLegacyJsonTrace_TraceType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeLegacyJsonTrace_TraceType::USER_TRACE:
+ return "USER_TRACE";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyJsonTrace_TraceType::SYSTEM_TRACE:
+ return "SYSTEM_TRACE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeTracedValue {
+enum NestedType : int32_t {
+ DICT = 0,
+ ARRAY = 1,
+};
+} // namespace perfetto_pbzero_enum_ChromeTracedValue
+using ChromeTracedValue_NestedType = perfetto_pbzero_enum_ChromeTracedValue::NestedType;
+
+
+constexpr ChromeTracedValue_NestedType ChromeTracedValue_NestedType_MIN = ChromeTracedValue_NestedType::DICT;
+constexpr ChromeTracedValue_NestedType ChromeTracedValue_NestedType_MAX = ChromeTracedValue_NestedType::ARRAY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeTracedValue_NestedType_Name(::perfetto::protos::pbzero::ChromeTracedValue_NestedType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeTracedValue_NestedType::DICT:
+ return "DICT";
+
+ case ::perfetto::protos::pbzero::ChromeTracedValue_NestedType::ARRAY:
+ return "ARRAY";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeEventBundle_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeEventBundle_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeEventBundle_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeEventBundle_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trace_events() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> trace_events() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_metadata() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> metadata() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_legacy_ftrace_output() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> legacy_ftrace_output() const { return GetRepeated<::protozero::ConstChars>(4); }
+ bool has_legacy_json_trace() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> legacy_json_trace() const { return GetRepeated<::protozero::ConstBytes>(5); }
+ bool has_string_table() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> string_table() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class ChromeEventBundle : public ::protozero::Message {
+ public:
+ using Decoder = ChromeEventBundle_Decoder;
+ enum : int32_t {
+ kTraceEventsFieldNumber = 1,
+ kMetadataFieldNumber = 2,
+ kLegacyFtraceOutputFieldNumber = 4,
+ kLegacyJsonTraceFieldNumber = 5,
+ kStringTableFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeEventBundle"; }
+
+
+ using FieldMetadata_TraceEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeTraceEvent,
+ ChromeEventBundle>;
+
+ static constexpr FieldMetadata_TraceEvents kTraceEvents{};
+ template <typename T = ChromeTraceEvent> T* add_trace_events() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Metadata =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeMetadata,
+ ChromeEventBundle>;
+
+ static constexpr FieldMetadata_Metadata kMetadata{};
+ template <typename T = ChromeMetadata> T* add_metadata() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_LegacyFtraceOutput =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeEventBundle>;
+
+ static constexpr FieldMetadata_LegacyFtraceOutput kLegacyFtraceOutput{};
+ void add_legacy_ftrace_output(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LegacyFtraceOutput::kFieldId, data, size);
+ }
+ void add_legacy_ftrace_output(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LegacyFtraceOutput::kFieldId, chars.data, chars.size);
+ }
+ void add_legacy_ftrace_output(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LegacyFtraceOutput::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LegacyJsonTrace =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeLegacyJsonTrace,
+ ChromeEventBundle>;
+
+ static constexpr FieldMetadata_LegacyJsonTrace kLegacyJsonTrace{};
+ template <typename T = ChromeLegacyJsonTrace> T* add_legacy_json_trace() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_StringTable =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeStringTableEntry,
+ ChromeEventBundle>;
+
+ static constexpr FieldMetadata_StringTable kStringTable{};
+ template <typename T = ChromeStringTableEntry> T* add_string_table() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class ChromeLegacyJsonTrace_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeLegacyJsonTrace_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeLegacyJsonTrace_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeLegacyJsonTrace_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_type() const { return at<1>().valid(); }
+ int32_t type() const { return at<1>().as_int32(); }
+ bool has_data() const { return at<2>().valid(); }
+ ::protozero::ConstChars data() const { return at<2>().as_string(); }
+};
+
+class ChromeLegacyJsonTrace : public ::protozero::Message {
+ public:
+ using Decoder = ChromeLegacyJsonTrace_Decoder;
+ enum : int32_t {
+ kTypeFieldNumber = 1,
+ kDataFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeLegacyJsonTrace"; }
+
+
+ using TraceType = ::perfetto::protos::pbzero::ChromeLegacyJsonTrace_TraceType;
+ static inline const char* TraceType_Name(TraceType value) {
+ return ::perfetto::protos::pbzero::ChromeLegacyJsonTrace_TraceType_Name(value);
+ }
+ static inline const TraceType USER_TRACE = TraceType::USER_TRACE;
+ static inline const TraceType SYSTEM_TRACE = TraceType::SYSTEM_TRACE;
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeLegacyJsonTrace_TraceType,
+ ChromeLegacyJsonTrace>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(ChromeLegacyJsonTrace_TraceType value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Data =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeLegacyJsonTrace>;
+
+ static constexpr FieldMetadata_Data kData{};
+ void set_data(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Data::kFieldId, data, size);
+ }
+ void set_data(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Data::kFieldId, chars.data, chars.size);
+ }
+ void set_data(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Data::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeMetadata_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeMetadata_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeMetadata_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeMetadata_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_string_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars string_value() const { return at<2>().as_string(); }
+ bool has_bool_value() const { return at<3>().valid(); }
+ bool bool_value() const { return at<3>().as_bool(); }
+ bool has_int_value() const { return at<4>().valid(); }
+ int64_t int_value() const { return at<4>().as_int64(); }
+ bool has_json_value() const { return at<5>().valid(); }
+ ::protozero::ConstChars json_value() const { return at<5>().as_string(); }
+};
+
+class ChromeMetadata : public ::protozero::Message {
+ public:
+ using Decoder = ChromeMetadata_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStringValueFieldNumber = 2,
+ kBoolValueFieldNumber = 3,
+ kIntValueFieldNumber = 4,
+ kJsonValueFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeMetadata"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeMetadata>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeMetadata>;
+
+ static constexpr FieldMetadata_StringValue kStringValue{};
+ void set_string_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, data, size);
+ }
+ void set_string_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, chars.data, chars.size);
+ }
+ void set_string_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BoolValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeMetadata>;
+
+ static constexpr FieldMetadata_BoolValue kBoolValue{};
+ void set_bool_value(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BoolValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeMetadata>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JsonValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeMetadata>;
+
+ static constexpr FieldMetadata_JsonValue kJsonValue{};
+ void set_json_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_JsonValue::kFieldId, data, size);
+ }
+ void set_json_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_JsonValue::kFieldId, chars.data, chars.size);
+ }
+ void set_json_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_JsonValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeTraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/16, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeTraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeTraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeTraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_timestamp() const { return at<2>().valid(); }
+ int64_t timestamp() const { return at<2>().as_int64(); }
+ bool has_phase() const { return at<3>().valid(); }
+ int32_t phase() const { return at<3>().as_int32(); }
+ bool has_thread_id() const { return at<4>().valid(); }
+ int32_t thread_id() const { return at<4>().as_int32(); }
+ bool has_duration() const { return at<5>().valid(); }
+ int64_t duration() const { return at<5>().as_int64(); }
+ bool has_thread_duration() const { return at<6>().valid(); }
+ int64_t thread_duration() const { return at<6>().as_int64(); }
+ bool has_scope() const { return at<7>().valid(); }
+ ::protozero::ConstChars scope() const { return at<7>().as_string(); }
+ bool has_id() const { return at<8>().valid(); }
+ uint64_t id() const { return at<8>().as_uint64(); }
+ bool has_flags() const { return at<9>().valid(); }
+ uint32_t flags() const { return at<9>().as_uint32(); }
+ bool has_category_group_name() const { return at<10>().valid(); }
+ ::protozero::ConstChars category_group_name() const { return at<10>().as_string(); }
+ bool has_process_id() const { return at<11>().valid(); }
+ int32_t process_id() const { return at<11>().as_int32(); }
+ bool has_thread_timestamp() const { return at<12>().valid(); }
+ int64_t thread_timestamp() const { return at<12>().as_int64(); }
+ bool has_bind_id() const { return at<13>().valid(); }
+ uint64_t bind_id() const { return at<13>().as_uint64(); }
+ bool has_args() const { return at<14>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> args() const { return GetRepeated<::protozero::ConstBytes>(14); }
+ bool has_name_index() const { return at<15>().valid(); }
+ uint32_t name_index() const { return at<15>().as_uint32(); }
+ bool has_category_group_name_index() const { return at<16>().valid(); }
+ uint32_t category_group_name_index() const { return at<16>().as_uint32(); }
+};
+
+class ChromeTraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ChromeTraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kTimestampFieldNumber = 2,
+ kPhaseFieldNumber = 3,
+ kThreadIdFieldNumber = 4,
+ kDurationFieldNumber = 5,
+ kThreadDurationFieldNumber = 6,
+ kScopeFieldNumber = 7,
+ kIdFieldNumber = 8,
+ kFlagsFieldNumber = 9,
+ kCategoryGroupNameFieldNumber = 10,
+ kProcessIdFieldNumber = 11,
+ kThreadTimestampFieldNumber = 12,
+ kBindIdFieldNumber = 13,
+ kArgsFieldNumber = 14,
+ kNameIndexFieldNumber = 15,
+ kCategoryGroupNameIndexFieldNumber = 16,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeTraceEvent"; }
+
+ using Arg = ::perfetto::protos::pbzero::ChromeTraceEvent_Arg;
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Phase =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Phase kPhase{};
+ void set_phase(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Phase::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_ThreadId kThreadId{};
+ void set_thread_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Duration =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Duration kDuration{};
+ void set_duration(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Duration::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadDuration =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_ThreadDuration kThreadDuration{};
+ void set_thread_duration(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadDuration::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Scope =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Scope kScope{};
+ void set_scope(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Scope::kFieldId, data, size);
+ }
+ void set_scope(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Scope::kFieldId, chars.data, chars.size);
+ }
+ void set_scope(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Scope::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CategoryGroupName =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_CategoryGroupName kCategoryGroupName{};
+ void set_category_group_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_CategoryGroupName::kFieldId, data, size);
+ }
+ void set_category_group_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_CategoryGroupName::kFieldId, chars.data, chars.size);
+ }
+ void set_category_group_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_CategoryGroupName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessId =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_ProcessId kProcessId{};
+ void set_process_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_ThreadTimestamp kThreadTimestamp{};
+ void set_thread_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BindId =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_BindId kBindId{};
+ void set_bind_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BindId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Args =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeTraceEvent_Arg,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_Args kArgs{};
+ template <typename T = ChromeTraceEvent_Arg> T* add_args() {
+ return BeginNestedMessage<T>(14);
+ }
+
+
+ using FieldMetadata_NameIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_NameIndex kNameIndex{};
+ void set_name_index(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CategoryGroupNameIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeTraceEvent>;
+
+ static constexpr FieldMetadata_CategoryGroupNameIndex kCategoryGroupNameIndex{};
+ void set_category_group_name_index(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CategoryGroupNameIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeTraceEvent_Arg_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeTraceEvent_Arg_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeTraceEvent_Arg_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeTraceEvent_Arg_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_bool_value() const { return at<2>().valid(); }
+ bool bool_value() const { return at<2>().as_bool(); }
+ bool has_uint_value() const { return at<3>().valid(); }
+ uint64_t uint_value() const { return at<3>().as_uint64(); }
+ bool has_int_value() const { return at<4>().valid(); }
+ int64_t int_value() const { return at<4>().as_int64(); }
+ bool has_double_value() const { return at<5>().valid(); }
+ double double_value() const { return at<5>().as_double(); }
+ bool has_string_value() const { return at<6>().valid(); }
+ ::protozero::ConstChars string_value() const { return at<6>().as_string(); }
+ bool has_pointer_value() const { return at<7>().valid(); }
+ uint64_t pointer_value() const { return at<7>().as_uint64(); }
+ bool has_json_value() const { return at<8>().valid(); }
+ ::protozero::ConstChars json_value() const { return at<8>().as_string(); }
+ bool has_traced_value() const { return at<10>().valid(); }
+ ::protozero::ConstBytes traced_value() const { return at<10>().as_bytes(); }
+ bool has_name_index() const { return at<9>().valid(); }
+ uint32_t name_index() const { return at<9>().as_uint32(); }
+};
+
+class ChromeTraceEvent_Arg : public ::protozero::Message {
+ public:
+ using Decoder = ChromeTraceEvent_Arg_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kBoolValueFieldNumber = 2,
+ kUintValueFieldNumber = 3,
+ kIntValueFieldNumber = 4,
+ kDoubleValueFieldNumber = 5,
+ kStringValueFieldNumber = 6,
+ kPointerValueFieldNumber = 7,
+ kJsonValueFieldNumber = 8,
+ kTracedValueFieldNumber = 10,
+ kNameIndexFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeTraceEvent.Arg"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BoolValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_BoolValue kBoolValue{};
+ void set_bool_value(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BoolValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UintValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_UintValue kUintValue{};
+ void set_uint_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UintValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_DoubleValue kDoubleValue{};
+ void set_double_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_StringValue kStringValue{};
+ void set_string_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, data, size);
+ }
+ void set_string_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, chars.data, chars.size);
+ }
+ void set_string_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PointerValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_PointerValue kPointerValue{};
+ void set_pointer_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PointerValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JsonValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_JsonValue kJsonValue{};
+ void set_json_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_JsonValue::kFieldId, data, size);
+ }
+ void set_json_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_JsonValue::kFieldId, chars.data, chars.size);
+ }
+ void set_json_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_JsonValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TracedValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeTracedValue,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_TracedValue kTracedValue{};
+ template <typename T = ChromeTracedValue> T* set_traced_value() {
+ return BeginNestedMessage<T>(10);
+ }
+
+
+ using FieldMetadata_NameIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeTraceEvent_Arg>;
+
+ static constexpr FieldMetadata_NameIndex kNameIndex{};
+ void set_name_index(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeStringTableEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeStringTableEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeStringTableEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeStringTableEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_value() const { return at<1>().valid(); }
+ ::protozero::ConstChars value() const { return at<1>().as_string(); }
+ bool has_index() const { return at<2>().valid(); }
+ int32_t index() const { return at<2>().as_int32(); }
+};
+
+class ChromeStringTableEntry : public ::protozero::Message {
+ public:
+ using Decoder = ChromeStringTableEntry_Decoder;
+ enum : int32_t {
+ kValueFieldNumber = 1,
+ kIndexFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeStringTableEntry"; }
+
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeStringTableEntry>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeStringTableEntry>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeTracedValue_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeTracedValue_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeTracedValue_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeTracedValue_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nested_type() const { return at<1>().valid(); }
+ int32_t nested_type() const { return at<1>().as_int32(); }
+ bool has_dict_keys() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> dict_keys() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_dict_values() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> dict_values() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_array_values() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> array_values() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_int_value() const { return at<5>().valid(); }
+ int32_t int_value() const { return at<5>().as_int32(); }
+ bool has_double_value() const { return at<6>().valid(); }
+ double double_value() const { return at<6>().as_double(); }
+ bool has_bool_value() const { return at<7>().valid(); }
+ bool bool_value() const { return at<7>().as_bool(); }
+ bool has_string_value() const { return at<8>().valid(); }
+ ::protozero::ConstChars string_value() const { return at<8>().as_string(); }
+};
+
+class ChromeTracedValue : public ::protozero::Message {
+ public:
+ using Decoder = ChromeTracedValue_Decoder;
+ enum : int32_t {
+ kNestedTypeFieldNumber = 1,
+ kDictKeysFieldNumber = 2,
+ kDictValuesFieldNumber = 3,
+ kArrayValuesFieldNumber = 4,
+ kIntValueFieldNumber = 5,
+ kDoubleValueFieldNumber = 6,
+ kBoolValueFieldNumber = 7,
+ kStringValueFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeTracedValue"; }
+
+
+ using NestedType = ::perfetto::protos::pbzero::ChromeTracedValue_NestedType;
+ static inline const char* NestedType_Name(NestedType value) {
+ return ::perfetto::protos::pbzero::ChromeTracedValue_NestedType_Name(value);
+ }
+ static inline const NestedType DICT = NestedType::DICT;
+ static inline const NestedType ARRAY = NestedType::ARRAY;
+
+ using FieldMetadata_NestedType =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeTracedValue_NestedType,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_NestedType kNestedType{};
+ void set_nested_type(ChromeTracedValue_NestedType value) {
+ static constexpr uint32_t field_id = FieldMetadata_NestedType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DictKeys =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_DictKeys kDictKeys{};
+ void add_dict_keys(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DictKeys::kFieldId, data, size);
+ }
+ void add_dict_keys(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DictKeys::kFieldId, chars.data, chars.size);
+ }
+ void add_dict_keys(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DictKeys::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DictValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeTracedValue,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_DictValues kDictValues{};
+ template <typename T = ChromeTracedValue> T* add_dict_values() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_ArrayValues =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeTracedValue,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_ArrayValues kArrayValues{};
+ template <typename T = ChromeTracedValue> T* add_array_values() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_DoubleValue kDoubleValue{};
+ void set_double_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BoolValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_BoolValue kBoolValue{};
+ void set_bool_value(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BoolValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeTracedValue>;
+
+ static constexpr FieldMetadata_StringValue kStringValue{};
+ void set_string_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, data, size);
+ }
+ void set_string_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringValue::kFieldId, chars.data, chars.size);
+ }
+ void set_string_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/chrome/v8.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_V8_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_CHROME_V8_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class InternedV8Isolate_CodeRange;
+class V8String;
+namespace perfetto_pbzero_enum_InternedV8JsFunction {
+enum Kind : int32_t;
+} // namespace perfetto_pbzero_enum_InternedV8JsFunction
+using InternedV8JsFunction_Kind = perfetto_pbzero_enum_InternedV8JsFunction::Kind;
+namespace perfetto_pbzero_enum_InternedV8JsScript {
+enum Type : int32_t;
+} // namespace perfetto_pbzero_enum_InternedV8JsScript
+using InternedV8JsScript_Type = perfetto_pbzero_enum_InternedV8JsScript::Type;
+namespace perfetto_pbzero_enum_V8InternalCode {
+enum Type : int32_t;
+} // namespace perfetto_pbzero_enum_V8InternalCode
+using V8InternalCode_Type = perfetto_pbzero_enum_V8InternalCode::Type;
+namespace perfetto_pbzero_enum_V8JsCode {
+enum Tier : int32_t;
+} // namespace perfetto_pbzero_enum_V8JsCode
+using V8JsCode_Tier = perfetto_pbzero_enum_V8JsCode::Tier;
+namespace perfetto_pbzero_enum_V8WasmCode {
+enum Tier : int32_t;
+} // namespace perfetto_pbzero_enum_V8WasmCode
+using V8WasmCode_Tier = perfetto_pbzero_enum_V8WasmCode::Tier;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_V8WasmCode {
+enum Tier : int32_t {
+ TIER_UNKNOWN = 0,
+ TIER_LIFTOFF = 1,
+ TIER_TURBOFAN = 2,
+};
+} // namespace perfetto_pbzero_enum_V8WasmCode
+using V8WasmCode_Tier = perfetto_pbzero_enum_V8WasmCode::Tier;
+
+
+constexpr V8WasmCode_Tier V8WasmCode_Tier_MIN = V8WasmCode_Tier::TIER_UNKNOWN;
+constexpr V8WasmCode_Tier V8WasmCode_Tier_MAX = V8WasmCode_Tier::TIER_TURBOFAN;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* V8WasmCode_Tier_Name(::perfetto::protos::pbzero::V8WasmCode_Tier value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::V8WasmCode_Tier::TIER_UNKNOWN:
+ return "TIER_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::V8WasmCode_Tier::TIER_LIFTOFF:
+ return "TIER_LIFTOFF";
+
+ case ::perfetto::protos::pbzero::V8WasmCode_Tier::TIER_TURBOFAN:
+ return "TIER_TURBOFAN";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_V8InternalCode {
+enum Type : int32_t {
+ TYPE_UNKNOWN = 0,
+ TYPE_BYTECODE_HANDLER = 1,
+ TYPE_FOR_TESTING = 2,
+ TYPE_BUILTIN = 3,
+ TYPE_WASM_FUNCTION = 4,
+ TYPE_WASM_TO_CAPI_FUNCTION = 5,
+ TYPE_WASM_TO_JS_FUNCTION = 6,
+ TYPE_JS_TO_WASM_FUNCTION = 7,
+ TYPE_JS_TO_JS_FUNCTION = 8,
+ TYPE_C_WASM_ENTRY = 9,
+};
+} // namespace perfetto_pbzero_enum_V8InternalCode
+using V8InternalCode_Type = perfetto_pbzero_enum_V8InternalCode::Type;
+
+
+constexpr V8InternalCode_Type V8InternalCode_Type_MIN = V8InternalCode_Type::TYPE_UNKNOWN;
+constexpr V8InternalCode_Type V8InternalCode_Type_MAX = V8InternalCode_Type::TYPE_C_WASM_ENTRY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* V8InternalCode_Type_Name(::perfetto::protos::pbzero::V8InternalCode_Type value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_UNKNOWN:
+ return "TYPE_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_BYTECODE_HANDLER:
+ return "TYPE_BYTECODE_HANDLER";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_FOR_TESTING:
+ return "TYPE_FOR_TESTING";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_BUILTIN:
+ return "TYPE_BUILTIN";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_WASM_FUNCTION:
+ return "TYPE_WASM_FUNCTION";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_WASM_TO_CAPI_FUNCTION:
+ return "TYPE_WASM_TO_CAPI_FUNCTION";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_WASM_TO_JS_FUNCTION:
+ return "TYPE_WASM_TO_JS_FUNCTION";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_JS_TO_WASM_FUNCTION:
+ return "TYPE_JS_TO_WASM_FUNCTION";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_JS_TO_JS_FUNCTION:
+ return "TYPE_JS_TO_JS_FUNCTION";
+
+ case ::perfetto::protos::pbzero::V8InternalCode_Type::TYPE_C_WASM_ENTRY:
+ return "TYPE_C_WASM_ENTRY";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_V8JsCode {
+enum Tier : int32_t {
+ TIER_UNKNOWN = 0,
+ TIER_IGNITION = 1,
+ TIER_SPARKPLUG = 2,
+ TIER_MAGLEV = 3,
+ TIER_TURBOSHAFT = 4,
+ TIER_TURBOFAN = 5,
+};
+} // namespace perfetto_pbzero_enum_V8JsCode
+using V8JsCode_Tier = perfetto_pbzero_enum_V8JsCode::Tier;
+
+
+constexpr V8JsCode_Tier V8JsCode_Tier_MIN = V8JsCode_Tier::TIER_UNKNOWN;
+constexpr V8JsCode_Tier V8JsCode_Tier_MAX = V8JsCode_Tier::TIER_TURBOFAN;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* V8JsCode_Tier_Name(::perfetto::protos::pbzero::V8JsCode_Tier value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::V8JsCode_Tier::TIER_UNKNOWN:
+ return "TIER_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::V8JsCode_Tier::TIER_IGNITION:
+ return "TIER_IGNITION";
+
+ case ::perfetto::protos::pbzero::V8JsCode_Tier::TIER_SPARKPLUG:
+ return "TIER_SPARKPLUG";
+
+ case ::perfetto::protos::pbzero::V8JsCode_Tier::TIER_MAGLEV:
+ return "TIER_MAGLEV";
+
+ case ::perfetto::protos::pbzero::V8JsCode_Tier::TIER_TURBOSHAFT:
+ return "TIER_TURBOSHAFT";
+
+ case ::perfetto::protos::pbzero::V8JsCode_Tier::TIER_TURBOFAN:
+ return "TIER_TURBOFAN";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_InternedV8JsFunction {
+enum Kind : int32_t {
+ KIND_UNKNOWN = 0,
+ KIND_NORMAL_FUNCTION = 1,
+ KIND_MODULE = 2,
+ KIND_ASYNC_MODULE = 3,
+ KIND_BASE_CONSTRUCTOR = 4,
+ KIND_DEFAULT_BASE_CONSTRUCTOR = 5,
+ KIND_DEFAULT_DERIVED_CONSTRUCTOR = 6,
+ KIND_DERIVED_CONSTRUCTOR = 7,
+ KIND_GETTER_FUNCTION = 8,
+ KIND_STATIC_GETTER_FUNCTION = 9,
+ KIND_SETTER_FUNCTION = 10,
+ KIND_STATIC_SETTER_FUNCTION = 11,
+ KIND_ARROW_FUNCTION = 12,
+ KIND_ASYNC_ARROW_FUNCTION = 13,
+ KIND_ASYNC_FUNCTION = 14,
+ KIND_ASYNC_CONCISE_METHOD = 15,
+ KIND_STATIC_ASYNC_CONCISE_METHOD = 16,
+ KIND_ASYNC_CONCISE_GENERATOR_METHOD = 17,
+ KIND_STATIC_ASYNC_CONCISE_GENERATOR_METHOD = 18,
+ KIND_ASYNC_GENERATOR_FUNCTION = 19,
+ KIND_GENERATOR_FUNCTION = 20,
+ KIND_CONCISE_GENERATOR_METHOD = 21,
+ KIND_STATIC_CONCISE_GENERATOR_METHOD = 22,
+ KIND_CONCISE_METHOD = 23,
+ KIND_STATIC_CONCISE_METHOD = 24,
+ KIND_CLASS_MEMBERS_INITIALIZER_FUNCTION = 25,
+ KIND_CLASS_STATIC_INITIALIZER_FUNCTION = 26,
+ KIND_INVALID = 27,
+};
+} // namespace perfetto_pbzero_enum_InternedV8JsFunction
+using InternedV8JsFunction_Kind = perfetto_pbzero_enum_InternedV8JsFunction::Kind;
+
+
+constexpr InternedV8JsFunction_Kind InternedV8JsFunction_Kind_MIN = InternedV8JsFunction_Kind::KIND_UNKNOWN;
+constexpr InternedV8JsFunction_Kind InternedV8JsFunction_Kind_MAX = InternedV8JsFunction_Kind::KIND_INVALID;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* InternedV8JsFunction_Kind_Name(::perfetto::protos::pbzero::InternedV8JsFunction_Kind value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_UNKNOWN:
+ return "KIND_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_NORMAL_FUNCTION:
+ return "KIND_NORMAL_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_MODULE:
+ return "KIND_MODULE";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_ASYNC_MODULE:
+ return "KIND_ASYNC_MODULE";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_BASE_CONSTRUCTOR:
+ return "KIND_BASE_CONSTRUCTOR";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_DEFAULT_BASE_CONSTRUCTOR:
+ return "KIND_DEFAULT_BASE_CONSTRUCTOR";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_DEFAULT_DERIVED_CONSTRUCTOR:
+ return "KIND_DEFAULT_DERIVED_CONSTRUCTOR";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_DERIVED_CONSTRUCTOR:
+ return "KIND_DERIVED_CONSTRUCTOR";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_GETTER_FUNCTION:
+ return "KIND_GETTER_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_STATIC_GETTER_FUNCTION:
+ return "KIND_STATIC_GETTER_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_SETTER_FUNCTION:
+ return "KIND_SETTER_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_STATIC_SETTER_FUNCTION:
+ return "KIND_STATIC_SETTER_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_ARROW_FUNCTION:
+ return "KIND_ARROW_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_ASYNC_ARROW_FUNCTION:
+ return "KIND_ASYNC_ARROW_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_ASYNC_FUNCTION:
+ return "KIND_ASYNC_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_ASYNC_CONCISE_METHOD:
+ return "KIND_ASYNC_CONCISE_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_STATIC_ASYNC_CONCISE_METHOD:
+ return "KIND_STATIC_ASYNC_CONCISE_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_ASYNC_CONCISE_GENERATOR_METHOD:
+ return "KIND_ASYNC_CONCISE_GENERATOR_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_STATIC_ASYNC_CONCISE_GENERATOR_METHOD:
+ return "KIND_STATIC_ASYNC_CONCISE_GENERATOR_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_ASYNC_GENERATOR_FUNCTION:
+ return "KIND_ASYNC_GENERATOR_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_GENERATOR_FUNCTION:
+ return "KIND_GENERATOR_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_CONCISE_GENERATOR_METHOD:
+ return "KIND_CONCISE_GENERATOR_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_STATIC_CONCISE_GENERATOR_METHOD:
+ return "KIND_STATIC_CONCISE_GENERATOR_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_CONCISE_METHOD:
+ return "KIND_CONCISE_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_STATIC_CONCISE_METHOD:
+ return "KIND_STATIC_CONCISE_METHOD";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_CLASS_MEMBERS_INITIALIZER_FUNCTION:
+ return "KIND_CLASS_MEMBERS_INITIALIZER_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_CLASS_STATIC_INITIALIZER_FUNCTION:
+ return "KIND_CLASS_STATIC_INITIALIZER_FUNCTION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsFunction_Kind::KIND_INVALID:
+ return "KIND_INVALID";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_InternedV8JsScript {
+enum Type : int32_t {
+ TYPE_UNKNOWN = 0,
+ TYPE_NORMAL = 1,
+ TYPE_EVAL = 2,
+ TYPE_MODULE = 3,
+ TYPE_NATIVE = 4,
+ TYPE_EXTENSION = 5,
+ TYPE_INSPECTOR = 6,
+};
+} // namespace perfetto_pbzero_enum_InternedV8JsScript
+using InternedV8JsScript_Type = perfetto_pbzero_enum_InternedV8JsScript::Type;
+
+
+constexpr InternedV8JsScript_Type InternedV8JsScript_Type_MIN = InternedV8JsScript_Type::TYPE_UNKNOWN;
+constexpr InternedV8JsScript_Type InternedV8JsScript_Type_MAX = InternedV8JsScript_Type::TYPE_INSPECTOR;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* InternedV8JsScript_Type_Name(::perfetto::protos::pbzero::InternedV8JsScript_Type value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::InternedV8JsScript_Type::TYPE_UNKNOWN:
+ return "TYPE_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::InternedV8JsScript_Type::TYPE_NORMAL:
+ return "TYPE_NORMAL";
+
+ case ::perfetto::protos::pbzero::InternedV8JsScript_Type::TYPE_EVAL:
+ return "TYPE_EVAL";
+
+ case ::perfetto::protos::pbzero::InternedV8JsScript_Type::TYPE_MODULE:
+ return "TYPE_MODULE";
+
+ case ::perfetto::protos::pbzero::InternedV8JsScript_Type::TYPE_NATIVE:
+ return "TYPE_NATIVE";
+
+ case ::perfetto::protos::pbzero::InternedV8JsScript_Type::TYPE_EXTENSION:
+ return "TYPE_EXTENSION";
+
+ case ::perfetto::protos::pbzero::InternedV8JsScript_Type::TYPE_INSPECTOR:
+ return "TYPE_INSPECTOR";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class V8CodeDefaults_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8CodeDefaults_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8CodeDefaults_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8CodeDefaults_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tid() const { return at<1>().valid(); }
+ uint32_t tid() const { return at<1>().as_uint32(); }
+};
+
+class V8CodeDefaults : public ::protozero::Message {
+ public:
+ using Decoder = V8CodeDefaults_Decoder;
+ enum : int32_t {
+ kTidFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8CodeDefaults"; }
+
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V8CodeDefaults>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V8CodeMove_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8CodeMove_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8CodeMove_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8CodeMove_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_isolate_iid() const { return at<1>().valid(); }
+ uint64_t isolate_iid() const { return at<1>().as_uint64(); }
+ bool has_tid() const { return at<2>().valid(); }
+ uint32_t tid() const { return at<2>().as_uint32(); }
+ bool has_from_instruction_start_address() const { return at<3>().valid(); }
+ uint64_t from_instruction_start_address() const { return at<3>().as_uint64(); }
+ bool has_to_instruction_start_address() const { return at<4>().valid(); }
+ uint64_t to_instruction_start_address() const { return at<4>().as_uint64(); }
+ bool has_instruction_size_bytes() const { return at<5>().valid(); }
+ uint64_t instruction_size_bytes() const { return at<5>().as_uint64(); }
+ bool has_to_machine_code() const { return at<6>().valid(); }
+ ::protozero::ConstBytes to_machine_code() const { return at<6>().as_bytes(); }
+ bool has_to_bytecode() const { return at<7>().valid(); }
+ ::protozero::ConstBytes to_bytecode() const { return at<7>().as_bytes(); }
+};
+
+class V8CodeMove : public ::protozero::Message {
+ public:
+ using Decoder = V8CodeMove_Decoder;
+ enum : int32_t {
+ kIsolateIidFieldNumber = 1,
+ kTidFieldNumber = 2,
+ kFromInstructionStartAddressFieldNumber = 3,
+ kToInstructionStartAddressFieldNumber = 4,
+ kInstructionSizeBytesFieldNumber = 5,
+ kToMachineCodeFieldNumber = 6,
+ kToBytecodeFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8CodeMove"; }
+
+
+ using FieldMetadata_IsolateIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8CodeMove>;
+
+ static constexpr FieldMetadata_IsolateIid kIsolateIid{};
+ void set_isolate_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsolateIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V8CodeMove>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FromInstructionStartAddress =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8CodeMove>;
+
+ static constexpr FieldMetadata_FromInstructionStartAddress kFromInstructionStartAddress{};
+ void set_from_instruction_start_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FromInstructionStartAddress::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ToInstructionStartAddress =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8CodeMove>;
+
+ static constexpr FieldMetadata_ToInstructionStartAddress kToInstructionStartAddress{};
+ void set_to_instruction_start_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ToInstructionStartAddress::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionSizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8CodeMove>;
+
+ static constexpr FieldMetadata_InstructionSizeBytes kInstructionSizeBytes{};
+ void set_instruction_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionSizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ToMachineCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8CodeMove>;
+
+ static constexpr FieldMetadata_ToMachineCode kToMachineCode{};
+ void set_to_machine_code(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_ToMachineCode::kFieldId, data, size);
+ }
+ void set_to_machine_code(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_ToMachineCode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_to_machine_code(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ToMachineCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ToBytecode =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8CodeMove>;
+
+ static constexpr FieldMetadata_ToBytecode kToBytecode{};
+ void set_to_bytecode(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_ToBytecode::kFieldId, data, size);
+ }
+ void set_to_bytecode(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_ToBytecode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_to_bytecode(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ToBytecode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V8RegExpCode_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8RegExpCode_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8RegExpCode_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8RegExpCode_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_v8_isolate_iid() const { return at<1>().valid(); }
+ uint64_t v8_isolate_iid() const { return at<1>().as_uint64(); }
+ bool has_tid() const { return at<2>().valid(); }
+ uint32_t tid() const { return at<2>().as_uint32(); }
+ bool has_pattern() const { return at<3>().valid(); }
+ ::protozero::ConstBytes pattern() const { return at<3>().as_bytes(); }
+ bool has_instruction_start() const { return at<4>().valid(); }
+ uint64_t instruction_start() const { return at<4>().as_uint64(); }
+ bool has_instruction_size_bytes() const { return at<5>().valid(); }
+ uint64_t instruction_size_bytes() const { return at<5>().as_uint64(); }
+ bool has_machine_code() const { return at<6>().valid(); }
+ ::protozero::ConstBytes machine_code() const { return at<6>().as_bytes(); }
+};
+
+class V8RegExpCode : public ::protozero::Message {
+ public:
+ using Decoder = V8RegExpCode_Decoder;
+ enum : int32_t {
+ kV8IsolateIidFieldNumber = 1,
+ kTidFieldNumber = 2,
+ kPatternFieldNumber = 3,
+ kInstructionStartFieldNumber = 4,
+ kInstructionSizeBytesFieldNumber = 5,
+ kMachineCodeFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8RegExpCode"; }
+
+
+ using FieldMetadata_V8IsolateIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8RegExpCode>;
+
+ static constexpr FieldMetadata_V8IsolateIid kV8IsolateIid{};
+ void set_v8_isolate_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8IsolateIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V8RegExpCode>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pattern =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8String,
+ V8RegExpCode>;
+
+ static constexpr FieldMetadata_Pattern kPattern{};
+ template <typename T = V8String> T* set_pattern() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_InstructionStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8RegExpCode>;
+
+ static constexpr FieldMetadata_InstructionStart kInstructionStart{};
+ void set_instruction_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionSizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8RegExpCode>;
+
+ static constexpr FieldMetadata_InstructionSizeBytes kInstructionSizeBytes{};
+ void set_instruction_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionSizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MachineCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8RegExpCode>;
+
+ static constexpr FieldMetadata_MachineCode kMachineCode{};
+ void set_machine_code(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, data, size);
+ }
+ void set_machine_code(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_machine_code(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MachineCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V8WasmCode_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8WasmCode_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8WasmCode_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8WasmCode_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_v8_isolate_iid() const { return at<1>().valid(); }
+ uint64_t v8_isolate_iid() const { return at<1>().as_uint64(); }
+ bool has_tid() const { return at<2>().valid(); }
+ uint32_t tid() const { return at<2>().as_uint32(); }
+ bool has_v8_wasm_script_iid() const { return at<3>().valid(); }
+ uint64_t v8_wasm_script_iid() const { return at<3>().as_uint64(); }
+ bool has_function_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars function_name() const { return at<4>().as_string(); }
+ bool has_tier() const { return at<5>().valid(); }
+ int32_t tier() const { return at<5>().as_int32(); }
+ bool has_code_offset_in_module() const { return at<6>().valid(); }
+ int32_t code_offset_in_module() const { return at<6>().as_int32(); }
+ bool has_instruction_start() const { return at<7>().valid(); }
+ uint64_t instruction_start() const { return at<7>().as_uint64(); }
+ bool has_instruction_size_bytes() const { return at<8>().valid(); }
+ uint64_t instruction_size_bytes() const { return at<8>().as_uint64(); }
+ bool has_machine_code() const { return at<9>().valid(); }
+ ::protozero::ConstBytes machine_code() const { return at<9>().as_bytes(); }
+};
+
+class V8WasmCode : public ::protozero::Message {
+ public:
+ using Decoder = V8WasmCode_Decoder;
+ enum : int32_t {
+ kV8IsolateIidFieldNumber = 1,
+ kTidFieldNumber = 2,
+ kV8WasmScriptIidFieldNumber = 3,
+ kFunctionNameFieldNumber = 4,
+ kTierFieldNumber = 5,
+ kCodeOffsetInModuleFieldNumber = 6,
+ kInstructionStartFieldNumber = 7,
+ kInstructionSizeBytesFieldNumber = 8,
+ kMachineCodeFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8WasmCode"; }
+
+
+ using Tier = ::perfetto::protos::pbzero::V8WasmCode_Tier;
+ static inline const char* Tier_Name(Tier value) {
+ return ::perfetto::protos::pbzero::V8WasmCode_Tier_Name(value);
+ }
+ static inline const Tier TIER_UNKNOWN = Tier::TIER_UNKNOWN;
+ static inline const Tier TIER_LIFTOFF = Tier::TIER_LIFTOFF;
+ static inline const Tier TIER_TURBOFAN = Tier::TIER_TURBOFAN;
+
+ using FieldMetadata_V8IsolateIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_V8IsolateIid kV8IsolateIid{};
+ void set_v8_isolate_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8IsolateIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_V8WasmScriptIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_V8WasmScriptIid kV8WasmScriptIid{};
+ void set_v8_wasm_script_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8WasmScriptIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FunctionName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_FunctionName kFunctionName{};
+ void set_function_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FunctionName::kFieldId, data, size);
+ }
+ void set_function_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FunctionName::kFieldId, chars.data, chars.size);
+ }
+ void set_function_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FunctionName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tier =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ V8WasmCode_Tier,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_Tier kTier{};
+ void set_tier(V8WasmCode_Tier value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tier::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CodeOffsetInModule =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_CodeOffsetInModule kCodeOffsetInModule{};
+ void set_code_offset_in_module(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CodeOffsetInModule::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_InstructionStart kInstructionStart{};
+ void set_instruction_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionSizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_InstructionSizeBytes kInstructionSizeBytes{};
+ void set_instruction_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionSizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MachineCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8WasmCode>;
+
+ static constexpr FieldMetadata_MachineCode kMachineCode{};
+ void set_machine_code(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, data, size);
+ }
+ void set_machine_code(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_machine_code(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MachineCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V8InternalCode_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8InternalCode_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8InternalCode_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8InternalCode_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_v8_isolate_iid() const { return at<1>().valid(); }
+ uint64_t v8_isolate_iid() const { return at<1>().as_uint64(); }
+ bool has_tid() const { return at<2>().valid(); }
+ uint32_t tid() const { return at<2>().as_uint32(); }
+ bool has_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars name() const { return at<3>().as_string(); }
+ bool has_type() const { return at<4>().valid(); }
+ int32_t type() const { return at<4>().as_int32(); }
+ bool has_builtin_id() const { return at<5>().valid(); }
+ int32_t builtin_id() const { return at<5>().as_int32(); }
+ bool has_instruction_start() const { return at<6>().valid(); }
+ uint64_t instruction_start() const { return at<6>().as_uint64(); }
+ bool has_instruction_size_bytes() const { return at<7>().valid(); }
+ uint64_t instruction_size_bytes() const { return at<7>().as_uint64(); }
+ bool has_machine_code() const { return at<8>().valid(); }
+ ::protozero::ConstBytes machine_code() const { return at<8>().as_bytes(); }
+};
+
+class V8InternalCode : public ::protozero::Message {
+ public:
+ using Decoder = V8InternalCode_Decoder;
+ enum : int32_t {
+ kV8IsolateIidFieldNumber = 1,
+ kTidFieldNumber = 2,
+ kNameFieldNumber = 3,
+ kTypeFieldNumber = 4,
+ kBuiltinIdFieldNumber = 5,
+ kInstructionStartFieldNumber = 6,
+ kInstructionSizeBytesFieldNumber = 7,
+ kMachineCodeFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8InternalCode"; }
+
+
+ using Type = ::perfetto::protos::pbzero::V8InternalCode_Type;
+ static inline const char* Type_Name(Type value) {
+ return ::perfetto::protos::pbzero::V8InternalCode_Type_Name(value);
+ }
+ static inline const Type TYPE_UNKNOWN = Type::TYPE_UNKNOWN;
+ static inline const Type TYPE_BYTECODE_HANDLER = Type::TYPE_BYTECODE_HANDLER;
+ static inline const Type TYPE_FOR_TESTING = Type::TYPE_FOR_TESTING;
+ static inline const Type TYPE_BUILTIN = Type::TYPE_BUILTIN;
+ static inline const Type TYPE_WASM_FUNCTION = Type::TYPE_WASM_FUNCTION;
+ static inline const Type TYPE_WASM_TO_CAPI_FUNCTION = Type::TYPE_WASM_TO_CAPI_FUNCTION;
+ static inline const Type TYPE_WASM_TO_JS_FUNCTION = Type::TYPE_WASM_TO_JS_FUNCTION;
+ static inline const Type TYPE_JS_TO_WASM_FUNCTION = Type::TYPE_JS_TO_WASM_FUNCTION;
+ static inline const Type TYPE_JS_TO_JS_FUNCTION = Type::TYPE_JS_TO_JS_FUNCTION;
+ static inline const Type TYPE_C_WASM_ENTRY = Type::TYPE_C_WASM_ENTRY;
+
+ using FieldMetadata_V8IsolateIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_V8IsolateIid kV8IsolateIid{};
+ void set_v8_isolate_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8IsolateIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ V8InternalCode_Type,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(V8InternalCode_Type value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BuiltinId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_BuiltinId kBuiltinId{};
+ void set_builtin_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BuiltinId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_InstructionStart kInstructionStart{};
+ void set_instruction_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionSizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_InstructionSizeBytes kInstructionSizeBytes{};
+ void set_instruction_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionSizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MachineCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8InternalCode>;
+
+ static constexpr FieldMetadata_MachineCode kMachineCode{};
+ void set_machine_code(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, data, size);
+ }
+ void set_machine_code(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_machine_code(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MachineCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V8JsCode_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8JsCode_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8JsCode_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8JsCode_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_v8_isolate_iid() const { return at<1>().valid(); }
+ uint64_t v8_isolate_iid() const { return at<1>().as_uint64(); }
+ bool has_tid() const { return at<2>().valid(); }
+ uint32_t tid() const { return at<2>().as_uint32(); }
+ bool has_v8_js_function_iid() const { return at<3>().valid(); }
+ uint64_t v8_js_function_iid() const { return at<3>().as_uint64(); }
+ bool has_tier() const { return at<4>().valid(); }
+ int32_t tier() const { return at<4>().as_int32(); }
+ bool has_instruction_start() const { return at<5>().valid(); }
+ uint64_t instruction_start() const { return at<5>().as_uint64(); }
+ bool has_instruction_size_bytes() const { return at<6>().valid(); }
+ uint64_t instruction_size_bytes() const { return at<6>().as_uint64(); }
+ bool has_machine_code() const { return at<7>().valid(); }
+ ::protozero::ConstBytes machine_code() const { return at<7>().as_bytes(); }
+ bool has_bytecode() const { return at<8>().valid(); }
+ ::protozero::ConstBytes bytecode() const { return at<8>().as_bytes(); }
+};
+
+class V8JsCode : public ::protozero::Message {
+ public:
+ using Decoder = V8JsCode_Decoder;
+ enum : int32_t {
+ kV8IsolateIidFieldNumber = 1,
+ kTidFieldNumber = 2,
+ kV8JsFunctionIidFieldNumber = 3,
+ kTierFieldNumber = 4,
+ kInstructionStartFieldNumber = 5,
+ kInstructionSizeBytesFieldNumber = 6,
+ kMachineCodeFieldNumber = 7,
+ kBytecodeFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8JsCode"; }
+
+
+ using Tier = ::perfetto::protos::pbzero::V8JsCode_Tier;
+ static inline const char* Tier_Name(Tier value) {
+ return ::perfetto::protos::pbzero::V8JsCode_Tier_Name(value);
+ }
+ static inline const Tier TIER_UNKNOWN = Tier::TIER_UNKNOWN;
+ static inline const Tier TIER_IGNITION = Tier::TIER_IGNITION;
+ static inline const Tier TIER_SPARKPLUG = Tier::TIER_SPARKPLUG;
+ static inline const Tier TIER_MAGLEV = Tier::TIER_MAGLEV;
+ static inline const Tier TIER_TURBOSHAFT = Tier::TIER_TURBOSHAFT;
+ static inline const Tier TIER_TURBOFAN = Tier::TIER_TURBOFAN;
+
+ using FieldMetadata_V8IsolateIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_V8IsolateIid kV8IsolateIid{};
+ void set_v8_isolate_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8IsolateIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_V8JsFunctionIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_V8JsFunctionIid kV8JsFunctionIid{};
+ void set_v8_js_function_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8JsFunctionIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tier =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ V8JsCode_Tier,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_Tier kTier{};
+ void set_tier(V8JsCode_Tier value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tier::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_InstructionStart kInstructionStart{};
+ void set_instruction_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InstructionSizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_InstructionSizeBytes kInstructionSizeBytes{};
+ void set_instruction_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InstructionSizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MachineCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_MachineCode kMachineCode{};
+ void set_machine_code(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, data, size);
+ }
+ void set_machine_code(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_MachineCode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_machine_code(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MachineCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bytecode =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8JsCode>;
+
+ static constexpr FieldMetadata_Bytecode kBytecode{};
+ void set_bytecode(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Bytecode::kFieldId, data, size);
+ }
+ void set_bytecode(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Bytecode::kFieldId, bytes.data, bytes.size);
+ }
+ void set_bytecode(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytecode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InternedV8Isolate_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedV8Isolate_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedV8Isolate_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedV8Isolate_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_pid() const { return at<2>().valid(); }
+ uint32_t pid() const { return at<2>().as_uint32(); }
+ bool has_isolate_id() const { return at<3>().valid(); }
+ int32_t isolate_id() const { return at<3>().as_int32(); }
+ bool has_code_range() const { return at<4>().valid(); }
+ ::protozero::ConstBytes code_range() const { return at<4>().as_bytes(); }
+ bool has_embedded_blob_code_start_address() const { return at<5>().valid(); }
+ uint64_t embedded_blob_code_start_address() const { return at<5>().as_uint64(); }
+ bool has_embedded_blob_code_size() const { return at<6>().valid(); }
+ uint64_t embedded_blob_code_size() const { return at<6>().as_uint64(); }
+};
+
+class InternedV8Isolate : public ::protozero::Message {
+ public:
+ using Decoder = InternedV8Isolate_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kIsolateIdFieldNumber = 3,
+ kCodeRangeFieldNumber = 4,
+ kEmbeddedBlobCodeStartAddressFieldNumber = 5,
+ kEmbeddedBlobCodeSizeFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedV8Isolate"; }
+
+ using CodeRange = ::perfetto::protos::pbzero::InternedV8Isolate_CodeRange;
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8Isolate>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InternedV8Isolate>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsolateId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InternedV8Isolate>;
+
+ static constexpr FieldMetadata_IsolateId kIsolateId{};
+ void set_isolate_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsolateId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CodeRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedV8Isolate_CodeRange,
+ InternedV8Isolate>;
+
+ static constexpr FieldMetadata_CodeRange kCodeRange{};
+ template <typename T = InternedV8Isolate_CodeRange> T* set_code_range() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_EmbeddedBlobCodeStartAddress =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8Isolate>;
+
+ static constexpr FieldMetadata_EmbeddedBlobCodeStartAddress kEmbeddedBlobCodeStartAddress{};
+ void set_embedded_blob_code_start_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EmbeddedBlobCodeStartAddress::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EmbeddedBlobCodeSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8Isolate>;
+
+ static constexpr FieldMetadata_EmbeddedBlobCodeSize kEmbeddedBlobCodeSize{};
+ void set_embedded_blob_code_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EmbeddedBlobCodeSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InternedV8Isolate_CodeRange_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedV8Isolate_CodeRange_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedV8Isolate_CodeRange_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedV8Isolate_CodeRange_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_base_address() const { return at<1>().valid(); }
+ uint64_t base_address() const { return at<1>().as_uint64(); }
+ bool has_size() const { return at<2>().valid(); }
+ uint64_t size() const { return at<2>().as_uint64(); }
+ bool has_embedded_blob_code_copy_start_address() const { return at<3>().valid(); }
+ uint64_t embedded_blob_code_copy_start_address() const { return at<3>().as_uint64(); }
+ bool has_is_process_wide() const { return at<4>().valid(); }
+ bool is_process_wide() const { return at<4>().as_bool(); }
+};
+
+class InternedV8Isolate_CodeRange : public ::protozero::Message {
+ public:
+ using Decoder = InternedV8Isolate_CodeRange_Decoder;
+ enum : int32_t {
+ kBaseAddressFieldNumber = 1,
+ kSizeFieldNumber = 2,
+ kEmbeddedBlobCodeCopyStartAddressFieldNumber = 3,
+ kIsProcessWideFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedV8Isolate.CodeRange"; }
+
+
+ using FieldMetadata_BaseAddress =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8Isolate_CodeRange>;
+
+ static constexpr FieldMetadata_BaseAddress kBaseAddress{};
+ void set_base_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BaseAddress::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8Isolate_CodeRange>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EmbeddedBlobCodeCopyStartAddress =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8Isolate_CodeRange>;
+
+ static constexpr FieldMetadata_EmbeddedBlobCodeCopyStartAddress kEmbeddedBlobCodeCopyStartAddress{};
+ void set_embedded_blob_code_copy_start_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EmbeddedBlobCodeCopyStartAddress::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsProcessWide =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InternedV8Isolate_CodeRange>;
+
+ static constexpr FieldMetadata_IsProcessWide kIsProcessWide{};
+ void set_is_process_wide(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsProcessWide::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InternedV8JsFunction_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedV8JsFunction_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedV8JsFunction_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedV8JsFunction_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_v8_js_function_name_iid() const { return at<2>().valid(); }
+ uint64_t v8_js_function_name_iid() const { return at<2>().as_uint64(); }
+ bool has_v8_js_script_iid() const { return at<3>().valid(); }
+ uint64_t v8_js_script_iid() const { return at<3>().as_uint64(); }
+ bool has_is_toplevel() const { return at<4>().valid(); }
+ bool is_toplevel() const { return at<4>().as_bool(); }
+ bool has_kind() const { return at<5>().valid(); }
+ int32_t kind() const { return at<5>().as_int32(); }
+ bool has_byte_offset() const { return at<6>().valid(); }
+ uint32_t byte_offset() const { return at<6>().as_uint32(); }
+};
+
+class InternedV8JsFunction : public ::protozero::Message {
+ public:
+ using Decoder = InternedV8JsFunction_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kV8JsFunctionNameIidFieldNumber = 2,
+ kV8JsScriptIidFieldNumber = 3,
+ kIsToplevelFieldNumber = 4,
+ kKindFieldNumber = 5,
+ kByteOffsetFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedV8JsFunction"; }
+
+
+ using Kind = ::perfetto::protos::pbzero::InternedV8JsFunction_Kind;
+ static inline const char* Kind_Name(Kind value) {
+ return ::perfetto::protos::pbzero::InternedV8JsFunction_Kind_Name(value);
+ }
+ static inline const Kind KIND_UNKNOWN = Kind::KIND_UNKNOWN;
+ static inline const Kind KIND_NORMAL_FUNCTION = Kind::KIND_NORMAL_FUNCTION;
+ static inline const Kind KIND_MODULE = Kind::KIND_MODULE;
+ static inline const Kind KIND_ASYNC_MODULE = Kind::KIND_ASYNC_MODULE;
+ static inline const Kind KIND_BASE_CONSTRUCTOR = Kind::KIND_BASE_CONSTRUCTOR;
+ static inline const Kind KIND_DEFAULT_BASE_CONSTRUCTOR = Kind::KIND_DEFAULT_BASE_CONSTRUCTOR;
+ static inline const Kind KIND_DEFAULT_DERIVED_CONSTRUCTOR = Kind::KIND_DEFAULT_DERIVED_CONSTRUCTOR;
+ static inline const Kind KIND_DERIVED_CONSTRUCTOR = Kind::KIND_DERIVED_CONSTRUCTOR;
+ static inline const Kind KIND_GETTER_FUNCTION = Kind::KIND_GETTER_FUNCTION;
+ static inline const Kind KIND_STATIC_GETTER_FUNCTION = Kind::KIND_STATIC_GETTER_FUNCTION;
+ static inline const Kind KIND_SETTER_FUNCTION = Kind::KIND_SETTER_FUNCTION;
+ static inline const Kind KIND_STATIC_SETTER_FUNCTION = Kind::KIND_STATIC_SETTER_FUNCTION;
+ static inline const Kind KIND_ARROW_FUNCTION = Kind::KIND_ARROW_FUNCTION;
+ static inline const Kind KIND_ASYNC_ARROW_FUNCTION = Kind::KIND_ASYNC_ARROW_FUNCTION;
+ static inline const Kind KIND_ASYNC_FUNCTION = Kind::KIND_ASYNC_FUNCTION;
+ static inline const Kind KIND_ASYNC_CONCISE_METHOD = Kind::KIND_ASYNC_CONCISE_METHOD;
+ static inline const Kind KIND_STATIC_ASYNC_CONCISE_METHOD = Kind::KIND_STATIC_ASYNC_CONCISE_METHOD;
+ static inline const Kind KIND_ASYNC_CONCISE_GENERATOR_METHOD = Kind::KIND_ASYNC_CONCISE_GENERATOR_METHOD;
+ static inline const Kind KIND_STATIC_ASYNC_CONCISE_GENERATOR_METHOD = Kind::KIND_STATIC_ASYNC_CONCISE_GENERATOR_METHOD;
+ static inline const Kind KIND_ASYNC_GENERATOR_FUNCTION = Kind::KIND_ASYNC_GENERATOR_FUNCTION;
+ static inline const Kind KIND_GENERATOR_FUNCTION = Kind::KIND_GENERATOR_FUNCTION;
+ static inline const Kind KIND_CONCISE_GENERATOR_METHOD = Kind::KIND_CONCISE_GENERATOR_METHOD;
+ static inline const Kind KIND_STATIC_CONCISE_GENERATOR_METHOD = Kind::KIND_STATIC_CONCISE_GENERATOR_METHOD;
+ static inline const Kind KIND_CONCISE_METHOD = Kind::KIND_CONCISE_METHOD;
+ static inline const Kind KIND_STATIC_CONCISE_METHOD = Kind::KIND_STATIC_CONCISE_METHOD;
+ static inline const Kind KIND_CLASS_MEMBERS_INITIALIZER_FUNCTION = Kind::KIND_CLASS_MEMBERS_INITIALIZER_FUNCTION;
+ static inline const Kind KIND_CLASS_STATIC_INITIALIZER_FUNCTION = Kind::KIND_CLASS_STATIC_INITIALIZER_FUNCTION;
+ static inline const Kind KIND_INVALID = Kind::KIND_INVALID;
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8JsFunction>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_V8JsFunctionNameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8JsFunction>;
+
+ static constexpr FieldMetadata_V8JsFunctionNameIid kV8JsFunctionNameIid{};
+ void set_v8_js_function_name_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8JsFunctionNameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_V8JsScriptIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8JsFunction>;
+
+ static constexpr FieldMetadata_V8JsScriptIid kV8JsScriptIid{};
+ void set_v8_js_script_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_V8JsScriptIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsToplevel =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ InternedV8JsFunction>;
+
+ static constexpr FieldMetadata_IsToplevel kIsToplevel{};
+ void set_is_toplevel(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsToplevel::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Kind =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ InternedV8JsFunction_Kind,
+ InternedV8JsFunction>;
+
+ static constexpr FieldMetadata_Kind kKind{};
+ void set_kind(InternedV8JsFunction_Kind value) {
+ static constexpr uint32_t field_id = FieldMetadata_Kind::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ByteOffset =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InternedV8JsFunction>;
+
+ static constexpr FieldMetadata_ByteOffset kByteOffset{};
+ void set_byte_offset(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ByteOffset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InternedV8WasmScript_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedV8WasmScript_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedV8WasmScript_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedV8WasmScript_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_script_id() const { return at<2>().valid(); }
+ int32_t script_id() const { return at<2>().as_int32(); }
+ bool has_url() const { return at<3>().valid(); }
+ ::protozero::ConstChars url() const { return at<3>().as_string(); }
+};
+
+class InternedV8WasmScript : public ::protozero::Message {
+ public:
+ using Decoder = InternedV8WasmScript_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kScriptIdFieldNumber = 2,
+ kUrlFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedV8WasmScript"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8WasmScript>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScriptId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InternedV8WasmScript>;
+
+ static constexpr FieldMetadata_ScriptId kScriptId{};
+ void set_script_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScriptId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Url =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InternedV8WasmScript>;
+
+ static constexpr FieldMetadata_Url kUrl{};
+ void set_url(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Url::kFieldId, data, size);
+ }
+ void set_url(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Url::kFieldId, chars.data, chars.size);
+ }
+ void set_url(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Url::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InternedV8JsScript_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedV8JsScript_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedV8JsScript_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedV8JsScript_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_script_id() const { return at<2>().valid(); }
+ int32_t script_id() const { return at<2>().as_int32(); }
+ bool has_type() const { return at<3>().valid(); }
+ int32_t type() const { return at<3>().as_int32(); }
+ bool has_name() const { return at<4>().valid(); }
+ ::protozero::ConstBytes name() const { return at<4>().as_bytes(); }
+ bool has_source() const { return at<5>().valid(); }
+ ::protozero::ConstBytes source() const { return at<5>().as_bytes(); }
+};
+
+class InternedV8JsScript : public ::protozero::Message {
+ public:
+ using Decoder = InternedV8JsScript_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kScriptIdFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kNameFieldNumber = 4,
+ kSourceFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedV8JsScript"; }
+
+
+ using Type = ::perfetto::protos::pbzero::InternedV8JsScript_Type;
+ static inline const char* Type_Name(Type value) {
+ return ::perfetto::protos::pbzero::InternedV8JsScript_Type_Name(value);
+ }
+ static inline const Type TYPE_UNKNOWN = Type::TYPE_UNKNOWN;
+ static inline const Type TYPE_NORMAL = Type::TYPE_NORMAL;
+ static inline const Type TYPE_EVAL = Type::TYPE_EVAL;
+ static inline const Type TYPE_MODULE = Type::TYPE_MODULE;
+ static inline const Type TYPE_NATIVE = Type::TYPE_NATIVE;
+ static inline const Type TYPE_EXTENSION = Type::TYPE_EXTENSION;
+ static inline const Type TYPE_INSPECTOR = Type::TYPE_INSPECTOR;
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8JsScript>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScriptId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InternedV8JsScript>;
+
+ static constexpr FieldMetadata_ScriptId kScriptId{};
+ void set_script_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScriptId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ InternedV8JsScript_Type,
+ InternedV8JsScript>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(InternedV8JsScript_Type value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8String,
+ InternedV8JsScript>;
+
+ static constexpr FieldMetadata_Name kName{};
+ template <typename T = V8String> T* set_name() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_Source =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8String,
+ InternedV8JsScript>;
+
+ static constexpr FieldMetadata_Source kSource{};
+ template <typename T = V8String> T* set_source() {
+ return BeginNestedMessage<T>(5);
+ }
+
+};
+
+class InternedV8String_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedV8String_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedV8String_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedV8String_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_latin1() const { return at<2>().valid(); }
+ ::protozero::ConstBytes latin1() const { return at<2>().as_bytes(); }
+ bool has_utf16_le() const { return at<3>().valid(); }
+ ::protozero::ConstBytes utf16_le() const { return at<3>().as_bytes(); }
+ bool has_utf16_be() const { return at<4>().valid(); }
+ ::protozero::ConstBytes utf16_be() const { return at<4>().as_bytes(); }
+};
+
+class InternedV8String : public ::protozero::Message {
+ public:
+ using Decoder = InternedV8String_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kLatin1FieldNumber = 2,
+ kUtf16LeFieldNumber = 3,
+ kUtf16BeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedV8String"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedV8String>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Latin1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ InternedV8String>;
+
+ static constexpr FieldMetadata_Latin1 kLatin1{};
+ void set_latin1(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Latin1::kFieldId, data, size);
+ }
+ void set_latin1(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Latin1::kFieldId, bytes.data, bytes.size);
+ }
+ void set_latin1(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Latin1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Utf16Le =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ InternedV8String>;
+
+ static constexpr FieldMetadata_Utf16Le kUtf16Le{};
+ void set_utf16_le(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Utf16Le::kFieldId, data, size);
+ }
+ void set_utf16_le(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Utf16Le::kFieldId, bytes.data, bytes.size);
+ }
+ void set_utf16_le(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Utf16Le::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Utf16Be =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ InternedV8String>;
+
+ static constexpr FieldMetadata_Utf16Be kUtf16Be{};
+ void set_utf16_be(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Utf16Be::kFieldId, data, size);
+ }
+ void set_utf16_be(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Utf16Be::kFieldId, bytes.data, bytes.size);
+ }
+ void set_utf16_be(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Utf16Be::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V8String_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V8String_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V8String_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V8String_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_latin1() const { return at<1>().valid(); }
+ ::protozero::ConstBytes latin1() const { return at<1>().as_bytes(); }
+ bool has_utf16_le() const { return at<2>().valid(); }
+ ::protozero::ConstBytes utf16_le() const { return at<2>().as_bytes(); }
+ bool has_utf16_be() const { return at<3>().valid(); }
+ ::protozero::ConstBytes utf16_be() const { return at<3>().as_bytes(); }
+};
+
+class V8String : public ::protozero::Message {
+ public:
+ using Decoder = V8String_Decoder;
+ enum : int32_t {
+ kLatin1FieldNumber = 1,
+ kUtf16LeFieldNumber = 2,
+ kUtf16BeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V8String"; }
+
+
+ using FieldMetadata_Latin1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8String>;
+
+ static constexpr FieldMetadata_Latin1 kLatin1{};
+ void set_latin1(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Latin1::kFieldId, data, size);
+ }
+ void set_latin1(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Latin1::kFieldId, bytes.data, bytes.size);
+ }
+ void set_latin1(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Latin1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Utf16Le =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8String>;
+
+ static constexpr FieldMetadata_Utf16Le kUtf16Le{};
+ void set_utf16_le(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Utf16Le::kFieldId, data, size);
+ }
+ void set_utf16_le(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Utf16Le::kFieldId, bytes.data, bytes.size);
+ }
+ void set_utf16_le(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Utf16Le::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Utf16Be =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ V8String>;
+
+ static constexpr FieldMetadata_Utf16Be kUtf16Be{};
+ void set_utf16_be(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Utf16Be::kFieldId, data, size);
+ }
+ void set_utf16_be(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Utf16Be::kFieldId, bytes.data, bytes.size);
+ }
+ void set_utf16_be(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Utf16Be::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/etw/etw.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ETW_ETW_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ETW_ETW_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_CSwitchEtwEvent {
+enum OldThreadState : int32_t;
+} // namespace perfetto_pbzero_enum_CSwitchEtwEvent
+using CSwitchEtwEvent_OldThreadState = perfetto_pbzero_enum_CSwitchEtwEvent::OldThreadState;
+namespace perfetto_pbzero_enum_CSwitchEtwEvent {
+enum OldThreadWaitMode : int32_t;
+} // namespace perfetto_pbzero_enum_CSwitchEtwEvent
+using CSwitchEtwEvent_OldThreadWaitMode = perfetto_pbzero_enum_CSwitchEtwEvent::OldThreadWaitMode;
+namespace perfetto_pbzero_enum_CSwitchEtwEvent {
+enum OldThreadWaitReason : int32_t;
+} // namespace perfetto_pbzero_enum_CSwitchEtwEvent
+using CSwitchEtwEvent_OldThreadWaitReason = perfetto_pbzero_enum_CSwitchEtwEvent::OldThreadWaitReason;
+namespace perfetto_pbzero_enum_ReadyThreadEtwEvent {
+enum AdjustReason : int32_t;
+} // namespace perfetto_pbzero_enum_ReadyThreadEtwEvent
+using ReadyThreadEtwEvent_AdjustReason = perfetto_pbzero_enum_ReadyThreadEtwEvent::AdjustReason;
+namespace perfetto_pbzero_enum_ReadyThreadEtwEvent {
+enum TraceFlag : int32_t;
+} // namespace perfetto_pbzero_enum_ReadyThreadEtwEvent
+using ReadyThreadEtwEvent_TraceFlag = perfetto_pbzero_enum_ReadyThreadEtwEvent::TraceFlag;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ReadyThreadEtwEvent {
+enum AdjustReason : int32_t {
+ IGNORE_THE_INCREMENT = 0,
+ APPLY_INCREMENT = 1,
+ APPLY_INCREMENT_BOOST = 2,
+};
+} // namespace perfetto_pbzero_enum_ReadyThreadEtwEvent
+using ReadyThreadEtwEvent_AdjustReason = perfetto_pbzero_enum_ReadyThreadEtwEvent::AdjustReason;
+
+
+constexpr ReadyThreadEtwEvent_AdjustReason ReadyThreadEtwEvent_AdjustReason_MIN = ReadyThreadEtwEvent_AdjustReason::IGNORE_THE_INCREMENT;
+constexpr ReadyThreadEtwEvent_AdjustReason ReadyThreadEtwEvent_AdjustReason_MAX = ReadyThreadEtwEvent_AdjustReason::APPLY_INCREMENT_BOOST;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ReadyThreadEtwEvent_AdjustReason_Name(::perfetto::protos::pbzero::ReadyThreadEtwEvent_AdjustReason value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ReadyThreadEtwEvent_AdjustReason::IGNORE_THE_INCREMENT:
+ return "IGNORE_THE_INCREMENT";
+
+ case ::perfetto::protos::pbzero::ReadyThreadEtwEvent_AdjustReason::APPLY_INCREMENT:
+ return "APPLY_INCREMENT";
+
+ case ::perfetto::protos::pbzero::ReadyThreadEtwEvent_AdjustReason::APPLY_INCREMENT_BOOST:
+ return "APPLY_INCREMENT_BOOST";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ReadyThreadEtwEvent {
+enum TraceFlag : int32_t {
+ TRACE_FLAG_UNSPECIFIED = 0,
+ THREAD_READIED = 1,
+ KERNEL_STACK_SWAPPED_OUT = 2,
+ PROCESS_ADDRESS_SWAPPED_OUT = 4,
+};
+} // namespace perfetto_pbzero_enum_ReadyThreadEtwEvent
+using ReadyThreadEtwEvent_TraceFlag = perfetto_pbzero_enum_ReadyThreadEtwEvent::TraceFlag;
+
+
+constexpr ReadyThreadEtwEvent_TraceFlag ReadyThreadEtwEvent_TraceFlag_MIN = ReadyThreadEtwEvent_TraceFlag::TRACE_FLAG_UNSPECIFIED;
+constexpr ReadyThreadEtwEvent_TraceFlag ReadyThreadEtwEvent_TraceFlag_MAX = ReadyThreadEtwEvent_TraceFlag::PROCESS_ADDRESS_SWAPPED_OUT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ReadyThreadEtwEvent_TraceFlag_Name(::perfetto::protos::pbzero::ReadyThreadEtwEvent_TraceFlag value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ReadyThreadEtwEvent_TraceFlag::TRACE_FLAG_UNSPECIFIED:
+ return "TRACE_FLAG_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ReadyThreadEtwEvent_TraceFlag::THREAD_READIED:
+ return "THREAD_READIED";
+
+ case ::perfetto::protos::pbzero::ReadyThreadEtwEvent_TraceFlag::KERNEL_STACK_SWAPPED_OUT:
+ return "KERNEL_STACK_SWAPPED_OUT";
+
+ case ::perfetto::protos::pbzero::ReadyThreadEtwEvent_TraceFlag::PROCESS_ADDRESS_SWAPPED_OUT:
+ return "PROCESS_ADDRESS_SWAPPED_OUT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_CSwitchEtwEvent {
+enum OldThreadWaitReason : int32_t {
+ EXECUTIVE = 0,
+ FREE_PAGE = 1,
+ PAGE_IN = 2,
+ POOL_ALLOCATION = 3,
+ DELAY_EXECUTION = 4,
+ SUSPEND = 5,
+ USER_REQUEST = 6,
+ WR_EXECUTIVE = 7,
+ WR_FREE_PAGE = 8,
+ WR_PAGE_IN = 9,
+ WR_POOL_ALLOCATION = 10,
+ WR_DELAY_EXECUTION = 11,
+ WR_SUSPENDED = 12,
+ WR_USER_REQUEST = 13,
+ WR_EVENT_PAIR = 14,
+ WR_QUEUE = 15,
+ WR_LPC_RECEIVER = 16,
+ WR_LPC_REPLY = 17,
+ WR_VIRTUAL_MEMORY = 18,
+ WR_PAGE_OUT = 19,
+ WR_RENDEZ_VOUS = 20,
+ WR_KEYED_EVENT = 21,
+ WR_TERMINATED = 22,
+ WR_PROCESS_IN_SWAP = 23,
+ WR_CPU_RATE_CONTROL = 24,
+ WR_CALLOUT_STACK = 25,
+ WR_KERNEL = 26,
+ WR_RESOURCE = 27,
+ WR_PUSH_LOCK = 28,
+ WR_MUTEX = 29,
+ WR_QUANTUM_END = 30,
+ WR_DISPATCH_INT = 31,
+ WR_PREEMPTED = 32,
+ WR_YIELD_EXECUTION = 33,
+ WR_FAST_MUTEX = 34,
+ WR_GUARD_MUTEX = 35,
+ WR_RUNDOWN = 36,
+ MAXIMUM_WAIT_REASON = 37,
+};
+} // namespace perfetto_pbzero_enum_CSwitchEtwEvent
+using CSwitchEtwEvent_OldThreadWaitReason = perfetto_pbzero_enum_CSwitchEtwEvent::OldThreadWaitReason;
+
+
+constexpr CSwitchEtwEvent_OldThreadWaitReason CSwitchEtwEvent_OldThreadWaitReason_MIN = CSwitchEtwEvent_OldThreadWaitReason::EXECUTIVE;
+constexpr CSwitchEtwEvent_OldThreadWaitReason CSwitchEtwEvent_OldThreadWaitReason_MAX = CSwitchEtwEvent_OldThreadWaitReason::MAXIMUM_WAIT_REASON;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* CSwitchEtwEvent_OldThreadWaitReason_Name(::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::EXECUTIVE:
+ return "EXECUTIVE";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::FREE_PAGE:
+ return "FREE_PAGE";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::PAGE_IN:
+ return "PAGE_IN";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::POOL_ALLOCATION:
+ return "POOL_ALLOCATION";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::DELAY_EXECUTION:
+ return "DELAY_EXECUTION";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::SUSPEND:
+ return "SUSPEND";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::USER_REQUEST:
+ return "USER_REQUEST";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_EXECUTIVE:
+ return "WR_EXECUTIVE";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_FREE_PAGE:
+ return "WR_FREE_PAGE";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_PAGE_IN:
+ return "WR_PAGE_IN";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_POOL_ALLOCATION:
+ return "WR_POOL_ALLOCATION";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_DELAY_EXECUTION:
+ return "WR_DELAY_EXECUTION";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_SUSPENDED:
+ return "WR_SUSPENDED";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_USER_REQUEST:
+ return "WR_USER_REQUEST";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_EVENT_PAIR:
+ return "WR_EVENT_PAIR";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_QUEUE:
+ return "WR_QUEUE";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_LPC_RECEIVER:
+ return "WR_LPC_RECEIVER";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_LPC_REPLY:
+ return "WR_LPC_REPLY";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_VIRTUAL_MEMORY:
+ return "WR_VIRTUAL_MEMORY";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_PAGE_OUT:
+ return "WR_PAGE_OUT";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_RENDEZ_VOUS:
+ return "WR_RENDEZ_VOUS";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_KEYED_EVENT:
+ return "WR_KEYED_EVENT";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_TERMINATED:
+ return "WR_TERMINATED";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_PROCESS_IN_SWAP:
+ return "WR_PROCESS_IN_SWAP";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_CPU_RATE_CONTROL:
+ return "WR_CPU_RATE_CONTROL";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_CALLOUT_STACK:
+ return "WR_CALLOUT_STACK";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_KERNEL:
+ return "WR_KERNEL";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_RESOURCE:
+ return "WR_RESOURCE";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_PUSH_LOCK:
+ return "WR_PUSH_LOCK";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_MUTEX:
+ return "WR_MUTEX";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_QUANTUM_END:
+ return "WR_QUANTUM_END";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_DISPATCH_INT:
+ return "WR_DISPATCH_INT";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_PREEMPTED:
+ return "WR_PREEMPTED";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_YIELD_EXECUTION:
+ return "WR_YIELD_EXECUTION";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_FAST_MUTEX:
+ return "WR_FAST_MUTEX";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_GUARD_MUTEX:
+ return "WR_GUARD_MUTEX";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::WR_RUNDOWN:
+ return "WR_RUNDOWN";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason::MAXIMUM_WAIT_REASON:
+ return "MAXIMUM_WAIT_REASON";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_CSwitchEtwEvent {
+enum OldThreadWaitMode : int32_t {
+ KERNEL_MODE = 0,
+ USER_MODE = 1,
+};
+} // namespace perfetto_pbzero_enum_CSwitchEtwEvent
+using CSwitchEtwEvent_OldThreadWaitMode = perfetto_pbzero_enum_CSwitchEtwEvent::OldThreadWaitMode;
+
+
+constexpr CSwitchEtwEvent_OldThreadWaitMode CSwitchEtwEvent_OldThreadWaitMode_MIN = CSwitchEtwEvent_OldThreadWaitMode::KERNEL_MODE;
+constexpr CSwitchEtwEvent_OldThreadWaitMode CSwitchEtwEvent_OldThreadWaitMode_MAX = CSwitchEtwEvent_OldThreadWaitMode::USER_MODE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* CSwitchEtwEvent_OldThreadWaitMode_Name(::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitMode::KERNEL_MODE:
+ return "KERNEL_MODE";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitMode::USER_MODE:
+ return "USER_MODE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_CSwitchEtwEvent {
+enum OldThreadState : int32_t {
+ INITIALIZED = 0,
+ READY = 1,
+ RUNNING = 2,
+ STANDBY = 3,
+ TERMINATED = 4,
+ WAITING = 5,
+ TRANSITION = 6,
+ DEFERRED_READY = 7,
+};
+} // namespace perfetto_pbzero_enum_CSwitchEtwEvent
+using CSwitchEtwEvent_OldThreadState = perfetto_pbzero_enum_CSwitchEtwEvent::OldThreadState;
+
+
+constexpr CSwitchEtwEvent_OldThreadState CSwitchEtwEvent_OldThreadState_MIN = CSwitchEtwEvent_OldThreadState::INITIALIZED;
+constexpr CSwitchEtwEvent_OldThreadState CSwitchEtwEvent_OldThreadState_MAX = CSwitchEtwEvent_OldThreadState::DEFERRED_READY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* CSwitchEtwEvent_OldThreadState_Name(::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::INITIALIZED:
+ return "INITIALIZED";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::READY:
+ return "READY";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::RUNNING:
+ return "RUNNING";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::STANDBY:
+ return "STANDBY";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::TERMINATED:
+ return "TERMINATED";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::WAITING:
+ return "WAITING";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::TRANSITION:
+ return "TRANSITION";
+
+ case ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState::DEFERRED_READY:
+ return "DEFERRED_READY";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ReadyThreadEtwEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ReadyThreadEtwEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ReadyThreadEtwEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ReadyThreadEtwEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_t_thread_id() const { return at<1>().valid(); }
+ uint32_t t_thread_id() const { return at<1>().as_uint32(); }
+ bool has_adjust_reason() const { return at<2>().valid(); }
+ int32_t adjust_reason() const { return at<2>().as_int32(); }
+ bool has_adjust_increment() const { return at<3>().valid(); }
+ int32_t adjust_increment() const { return at<3>().as_sint32(); }
+ bool has_flag() const { return at<4>().valid(); }
+ int32_t flag() const { return at<4>().as_int32(); }
+};
+
+class ReadyThreadEtwEvent : public ::protozero::Message {
+ public:
+ using Decoder = ReadyThreadEtwEvent_Decoder;
+ enum : int32_t {
+ kTThreadIdFieldNumber = 1,
+ kAdjustReasonFieldNumber = 2,
+ kAdjustIncrementFieldNumber = 3,
+ kFlagFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ReadyThreadEtwEvent"; }
+
+
+ using AdjustReason = ::perfetto::protos::pbzero::ReadyThreadEtwEvent_AdjustReason;
+ static inline const char* AdjustReason_Name(AdjustReason value) {
+ return ::perfetto::protos::pbzero::ReadyThreadEtwEvent_AdjustReason_Name(value);
+ }
+
+ using TraceFlag = ::perfetto::protos::pbzero::ReadyThreadEtwEvent_TraceFlag;
+ static inline const char* TraceFlag_Name(TraceFlag value) {
+ return ::perfetto::protos::pbzero::ReadyThreadEtwEvent_TraceFlag_Name(value);
+ }
+ static inline const AdjustReason IGNORE_THE_INCREMENT = AdjustReason::IGNORE_THE_INCREMENT;
+ static inline const AdjustReason APPLY_INCREMENT = AdjustReason::APPLY_INCREMENT;
+ static inline const AdjustReason APPLY_INCREMENT_BOOST = AdjustReason::APPLY_INCREMENT_BOOST;
+ static inline const TraceFlag TRACE_FLAG_UNSPECIFIED = TraceFlag::TRACE_FLAG_UNSPECIFIED;
+ static inline const TraceFlag THREAD_READIED = TraceFlag::THREAD_READIED;
+ static inline const TraceFlag KERNEL_STACK_SWAPPED_OUT = TraceFlag::KERNEL_STACK_SWAPPED_OUT;
+ static inline const TraceFlag PROCESS_ADDRESS_SWAPPED_OUT = TraceFlag::PROCESS_ADDRESS_SWAPPED_OUT;
+
+ using FieldMetadata_TThreadId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ReadyThreadEtwEvent>;
+
+ static constexpr FieldMetadata_TThreadId kTThreadId{};
+ void set_t_thread_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TThreadId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AdjustReason =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ReadyThreadEtwEvent_AdjustReason,
+ ReadyThreadEtwEvent>;
+
+ static constexpr FieldMetadata_AdjustReason kAdjustReason{};
+ void set_adjust_reason(ReadyThreadEtwEvent_AdjustReason value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdjustReason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AdjustIncrement =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint32,
+ int32_t,
+ ReadyThreadEtwEvent>;
+
+ static constexpr FieldMetadata_AdjustIncrement kAdjustIncrement{};
+ void set_adjust_increment(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdjustIncrement::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flag =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ReadyThreadEtwEvent_TraceFlag,
+ ReadyThreadEtwEvent>;
+
+ static constexpr FieldMetadata_Flag kFlag{};
+ void set_flag(ReadyThreadEtwEvent_TraceFlag value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CSwitchEtwEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CSwitchEtwEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CSwitchEtwEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CSwitchEtwEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_new_thread_id() const { return at<1>().valid(); }
+ uint32_t new_thread_id() const { return at<1>().as_uint32(); }
+ bool has_old_thread_id() const { return at<2>().valid(); }
+ uint32_t old_thread_id() const { return at<2>().as_uint32(); }
+ bool has_new_thread_priority() const { return at<3>().valid(); }
+ int32_t new_thread_priority() const { return at<3>().as_sint32(); }
+ bool has_old_thread_priority() const { return at<4>().valid(); }
+ int32_t old_thread_priority() const { return at<4>().as_sint32(); }
+ bool has_previous_c_state() const { return at<5>().valid(); }
+ uint32_t previous_c_state() const { return at<5>().as_uint32(); }
+ bool has_old_thread_wait_reason() const { return at<6>().valid(); }
+ int32_t old_thread_wait_reason() const { return at<6>().as_int32(); }
+ bool has_old_thread_wait_mode() const { return at<7>().valid(); }
+ int32_t old_thread_wait_mode() const { return at<7>().as_int32(); }
+ bool has_old_thread_state() const { return at<8>().valid(); }
+ int32_t old_thread_state() const { return at<8>().as_int32(); }
+ bool has_old_thread_wait_ideal_processor() const { return at<9>().valid(); }
+ int32_t old_thread_wait_ideal_processor() const { return at<9>().as_sint32(); }
+ bool has_new_thread_wait_time() const { return at<10>().valid(); }
+ uint32_t new_thread_wait_time() const { return at<10>().as_uint32(); }
+};
+
+class CSwitchEtwEvent : public ::protozero::Message {
+ public:
+ using Decoder = CSwitchEtwEvent_Decoder;
+ enum : int32_t {
+ kNewThreadIdFieldNumber = 1,
+ kOldThreadIdFieldNumber = 2,
+ kNewThreadPriorityFieldNumber = 3,
+ kOldThreadPriorityFieldNumber = 4,
+ kPreviousCStateFieldNumber = 5,
+ kOldThreadWaitReasonFieldNumber = 6,
+ kOldThreadWaitModeFieldNumber = 7,
+ kOldThreadStateFieldNumber = 8,
+ kOldThreadWaitIdealProcessorFieldNumber = 9,
+ kNewThreadWaitTimeFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CSwitchEtwEvent"; }
+
+
+ using OldThreadWaitReason = ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason;
+ static inline const char* OldThreadWaitReason_Name(OldThreadWaitReason value) {
+ return ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitReason_Name(value);
+ }
+
+ using OldThreadWaitMode = ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitMode;
+ static inline const char* OldThreadWaitMode_Name(OldThreadWaitMode value) {
+ return ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadWaitMode_Name(value);
+ }
+
+ using OldThreadState = ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState;
+ static inline const char* OldThreadState_Name(OldThreadState value) {
+ return ::perfetto::protos::pbzero::CSwitchEtwEvent_OldThreadState_Name(value);
+ }
+ static inline const OldThreadWaitReason EXECUTIVE = OldThreadWaitReason::EXECUTIVE;
+ static inline const OldThreadWaitReason FREE_PAGE = OldThreadWaitReason::FREE_PAGE;
+ static inline const OldThreadWaitReason PAGE_IN = OldThreadWaitReason::PAGE_IN;
+ static inline const OldThreadWaitReason POOL_ALLOCATION = OldThreadWaitReason::POOL_ALLOCATION;
+ static inline const OldThreadWaitReason DELAY_EXECUTION = OldThreadWaitReason::DELAY_EXECUTION;
+ static inline const OldThreadWaitReason SUSPEND = OldThreadWaitReason::SUSPEND;
+ static inline const OldThreadWaitReason USER_REQUEST = OldThreadWaitReason::USER_REQUEST;
+ static inline const OldThreadWaitReason WR_EXECUTIVE = OldThreadWaitReason::WR_EXECUTIVE;
+ static inline const OldThreadWaitReason WR_FREE_PAGE = OldThreadWaitReason::WR_FREE_PAGE;
+ static inline const OldThreadWaitReason WR_PAGE_IN = OldThreadWaitReason::WR_PAGE_IN;
+ static inline const OldThreadWaitReason WR_POOL_ALLOCATION = OldThreadWaitReason::WR_POOL_ALLOCATION;
+ static inline const OldThreadWaitReason WR_DELAY_EXECUTION = OldThreadWaitReason::WR_DELAY_EXECUTION;
+ static inline const OldThreadWaitReason WR_SUSPENDED = OldThreadWaitReason::WR_SUSPENDED;
+ static inline const OldThreadWaitReason WR_USER_REQUEST = OldThreadWaitReason::WR_USER_REQUEST;
+ static inline const OldThreadWaitReason WR_EVENT_PAIR = OldThreadWaitReason::WR_EVENT_PAIR;
+ static inline const OldThreadWaitReason WR_QUEUE = OldThreadWaitReason::WR_QUEUE;
+ static inline const OldThreadWaitReason WR_LPC_RECEIVER = OldThreadWaitReason::WR_LPC_RECEIVER;
+ static inline const OldThreadWaitReason WR_LPC_REPLY = OldThreadWaitReason::WR_LPC_REPLY;
+ static inline const OldThreadWaitReason WR_VIRTUAL_MEMORY = OldThreadWaitReason::WR_VIRTUAL_MEMORY;
+ static inline const OldThreadWaitReason WR_PAGE_OUT = OldThreadWaitReason::WR_PAGE_OUT;
+ static inline const OldThreadWaitReason WR_RENDEZ_VOUS = OldThreadWaitReason::WR_RENDEZ_VOUS;
+ static inline const OldThreadWaitReason WR_KEYED_EVENT = OldThreadWaitReason::WR_KEYED_EVENT;
+ static inline const OldThreadWaitReason WR_TERMINATED = OldThreadWaitReason::WR_TERMINATED;
+ static inline const OldThreadWaitReason WR_PROCESS_IN_SWAP = OldThreadWaitReason::WR_PROCESS_IN_SWAP;
+ static inline const OldThreadWaitReason WR_CPU_RATE_CONTROL = OldThreadWaitReason::WR_CPU_RATE_CONTROL;
+ static inline const OldThreadWaitReason WR_CALLOUT_STACK = OldThreadWaitReason::WR_CALLOUT_STACK;
+ static inline const OldThreadWaitReason WR_KERNEL = OldThreadWaitReason::WR_KERNEL;
+ static inline const OldThreadWaitReason WR_RESOURCE = OldThreadWaitReason::WR_RESOURCE;
+ static inline const OldThreadWaitReason WR_PUSH_LOCK = OldThreadWaitReason::WR_PUSH_LOCK;
+ static inline const OldThreadWaitReason WR_MUTEX = OldThreadWaitReason::WR_MUTEX;
+ static inline const OldThreadWaitReason WR_QUANTUM_END = OldThreadWaitReason::WR_QUANTUM_END;
+ static inline const OldThreadWaitReason WR_DISPATCH_INT = OldThreadWaitReason::WR_DISPATCH_INT;
+ static inline const OldThreadWaitReason WR_PREEMPTED = OldThreadWaitReason::WR_PREEMPTED;
+ static inline const OldThreadWaitReason WR_YIELD_EXECUTION = OldThreadWaitReason::WR_YIELD_EXECUTION;
+ static inline const OldThreadWaitReason WR_FAST_MUTEX = OldThreadWaitReason::WR_FAST_MUTEX;
+ static inline const OldThreadWaitReason WR_GUARD_MUTEX = OldThreadWaitReason::WR_GUARD_MUTEX;
+ static inline const OldThreadWaitReason WR_RUNDOWN = OldThreadWaitReason::WR_RUNDOWN;
+ static inline const OldThreadWaitReason MAXIMUM_WAIT_REASON = OldThreadWaitReason::MAXIMUM_WAIT_REASON;
+ static inline const OldThreadWaitMode KERNEL_MODE = OldThreadWaitMode::KERNEL_MODE;
+ static inline const OldThreadWaitMode USER_MODE = OldThreadWaitMode::USER_MODE;
+ static inline const OldThreadState INITIALIZED = OldThreadState::INITIALIZED;
+ static inline const OldThreadState READY = OldThreadState::READY;
+ static inline const OldThreadState RUNNING = OldThreadState::RUNNING;
+ static inline const OldThreadState STANDBY = OldThreadState::STANDBY;
+ static inline const OldThreadState TERMINATED = OldThreadState::TERMINATED;
+ static inline const OldThreadState WAITING = OldThreadState::WAITING;
+ static inline const OldThreadState TRANSITION = OldThreadState::TRANSITION;
+ static inline const OldThreadState DEFERRED_READY = OldThreadState::DEFERRED_READY;
+
+ using FieldMetadata_NewThreadId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_NewThreadId kNewThreadId{};
+ void set_new_thread_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewThreadId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldThreadId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_OldThreadId kOldThreadId{};
+ void set_old_thread_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldThreadId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewThreadPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint32,
+ int32_t,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_NewThreadPriority kNewThreadPriority{};
+ void set_new_thread_priority(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewThreadPriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldThreadPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint32,
+ int32_t,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_OldThreadPriority kOldThreadPriority{};
+ void set_old_thread_priority(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldThreadPriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreviousCState =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_PreviousCState kPreviousCState{};
+ void set_previous_c_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreviousCState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldThreadWaitReason =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ CSwitchEtwEvent_OldThreadWaitReason,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_OldThreadWaitReason kOldThreadWaitReason{};
+ void set_old_thread_wait_reason(CSwitchEtwEvent_OldThreadWaitReason value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldThreadWaitReason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldThreadWaitMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ CSwitchEtwEvent_OldThreadWaitMode,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_OldThreadWaitMode kOldThreadWaitMode{};
+ void set_old_thread_wait_mode(CSwitchEtwEvent_OldThreadWaitMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldThreadWaitMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldThreadState =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ CSwitchEtwEvent_OldThreadState,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_OldThreadState kOldThreadState{};
+ void set_old_thread_state(CSwitchEtwEvent_OldThreadState value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldThreadState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldThreadWaitIdealProcessor =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kSint32,
+ int32_t,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_OldThreadWaitIdealProcessor kOldThreadWaitIdealProcessor{};
+ void set_old_thread_wait_ideal_processor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldThreadWaitIdealProcessor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kSint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewThreadWaitTime =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CSwitchEtwEvent>;
+
+ static constexpr FieldMetadata_NewThreadWaitTime kNewThreadWaitTime{};
+ void set_new_thread_wait_time(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewThreadWaitTime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/etw/etw_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ETW_ETW_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ETW_ETW_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class CSwitchEtwEvent;
+class ReadyThreadEtwEvent;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class EtwTraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ EtwTraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EtwTraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EtwTraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timestamp() const { return at<1>().valid(); }
+ uint64_t timestamp() const { return at<1>().as_uint64(); }
+ bool has_cpu() const { return at<4>().valid(); }
+ uint32_t cpu() const { return at<4>().as_uint32(); }
+ bool has_c_switch() const { return at<2>().valid(); }
+ ::protozero::ConstBytes c_switch() const { return at<2>().as_bytes(); }
+ bool has_ready_thread() const { return at<3>().valid(); }
+ ::protozero::ConstBytes ready_thread() const { return at<3>().as_bytes(); }
+};
+
+class EtwTraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = EtwTraceEvent_Decoder;
+ enum : int32_t {
+ kTimestampFieldNumber = 1,
+ kCpuFieldNumber = 4,
+ kCSwitchFieldNumber = 2,
+ kReadyThreadFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EtwTraceEvent"; }
+
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ EtwTraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ EtwTraceEvent>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CSwitch =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CSwitchEtwEvent,
+ EtwTraceEvent>;
+
+ static constexpr FieldMetadata_CSwitch kCSwitch{};
+ template <typename T = CSwitchEtwEvent> T* set_c_switch() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_ReadyThread =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ReadyThreadEtwEvent,
+ EtwTraceEvent>;
+
+ static constexpr FieldMetadata_ReadyThread kReadyThread{};
+ template <typename T = ReadyThreadEtwEvent> T* set_ready_thread() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/etw/etw_event_bundle.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ETW_ETW_EVENT_BUNDLE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_ETW_ETW_EVENT_BUNDLE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class EtwTraceEvent;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class EtwTraceEventBundle_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ EtwTraceEventBundle_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EtwTraceEventBundle_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EtwTraceEventBundle_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint32_t cpu() const { return at<1>().as_uint32(); }
+ bool has_event() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> event() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class EtwTraceEventBundle : public ::protozero::Message {
+ public:
+ using Decoder = EtwTraceEventBundle_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kEventFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EtwTraceEventBundle"; }
+
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ EtwTraceEventBundle>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Event =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EtwTraceEvent,
+ EtwTraceEventBundle>;
+
+ static constexpr FieldMetadata_Event kEvent{};
+ template <typename T = EtwTraceEvent> T* add_event() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/filesystem/inode_file_map.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FILESYSTEM_INODE_FILE_MAP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FILESYSTEM_INODE_FILE_MAP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class InodeFileMap_Entry;
+namespace perfetto_pbzero_enum_InodeFileMap_Entry {
+enum Type : int32_t;
+} // namespace perfetto_pbzero_enum_InodeFileMap_Entry
+using InodeFileMap_Entry_Type = perfetto_pbzero_enum_InodeFileMap_Entry::Type;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_InodeFileMap_Entry {
+enum Type : int32_t {
+ UNKNOWN = 0,
+ FILE = 1,
+ DIRECTORY = 2,
+};
+} // namespace perfetto_pbzero_enum_InodeFileMap_Entry
+using InodeFileMap_Entry_Type = perfetto_pbzero_enum_InodeFileMap_Entry::Type;
+
+
+constexpr InodeFileMap_Entry_Type InodeFileMap_Entry_Type_MIN = InodeFileMap_Entry_Type::UNKNOWN;
+constexpr InodeFileMap_Entry_Type InodeFileMap_Entry_Type_MAX = InodeFileMap_Entry_Type::DIRECTORY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* InodeFileMap_Entry_Type_Name(::perfetto::protos::pbzero::InodeFileMap_Entry_Type value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::InodeFileMap_Entry_Type::UNKNOWN:
+ return "UNKNOWN";
+
+ case ::perfetto::protos::pbzero::InodeFileMap_Entry_Type::FILE:
+ return "FILE";
+
+ case ::perfetto::protos::pbzero::InodeFileMap_Entry_Type::DIRECTORY:
+ return "DIRECTORY";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class InodeFileMap_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ InodeFileMap_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InodeFileMap_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InodeFileMap_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_block_device_id() const { return at<1>().valid(); }
+ uint64_t block_device_id() const { return at<1>().as_uint64(); }
+ bool has_mount_points() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> mount_points() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_entries() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> entries() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class InodeFileMap : public ::protozero::Message {
+ public:
+ using Decoder = InodeFileMap_Decoder;
+ enum : int32_t {
+ kBlockDeviceIdFieldNumber = 1,
+ kMountPointsFieldNumber = 2,
+ kEntriesFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InodeFileMap"; }
+
+ using Entry = ::perfetto::protos::pbzero::InodeFileMap_Entry;
+
+ using FieldMetadata_BlockDeviceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InodeFileMap>;
+
+ static constexpr FieldMetadata_BlockDeviceId kBlockDeviceId{};
+ void set_block_device_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlockDeviceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MountPoints =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InodeFileMap>;
+
+ static constexpr FieldMetadata_MountPoints kMountPoints{};
+ void add_mount_points(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_MountPoints::kFieldId, data, size);
+ }
+ void add_mount_points(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_MountPoints::kFieldId, chars.data, chars.size);
+ }
+ void add_mount_points(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MountPoints::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Entries =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InodeFileMap_Entry,
+ InodeFileMap>;
+
+ static constexpr FieldMetadata_Entries kEntries{};
+ template <typename T = InodeFileMap_Entry> T* add_entries() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class InodeFileMap_Entry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ InodeFileMap_Entry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InodeFileMap_Entry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InodeFileMap_Entry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_inode_number() const { return at<1>().valid(); }
+ uint64_t inode_number() const { return at<1>().as_uint64(); }
+ bool has_paths() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> paths() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_type() const { return at<3>().valid(); }
+ int32_t type() const { return at<3>().as_int32(); }
+};
+
+class InodeFileMap_Entry : public ::protozero::Message {
+ public:
+ using Decoder = InodeFileMap_Entry_Decoder;
+ enum : int32_t {
+ kInodeNumberFieldNumber = 1,
+ kPathsFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InodeFileMap.Entry"; }
+
+
+ using Type = ::perfetto::protos::pbzero::InodeFileMap_Entry_Type;
+ static inline const char* Type_Name(Type value) {
+ return ::perfetto::protos::pbzero::InodeFileMap_Entry_Type_Name(value);
+ }
+ static inline const Type UNKNOWN = Type::UNKNOWN;
+ static inline const Type FILE = Type::FILE;
+ static inline const Type DIRECTORY = Type::DIRECTORY;
+
+ using FieldMetadata_InodeNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InodeFileMap_Entry>;
+
+ static constexpr FieldMetadata_InodeNumber kInodeNumber{};
+ void set_inode_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InodeNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Paths =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InodeFileMap_Entry>;
+
+ static constexpr FieldMetadata_Paths kPaths{};
+ void add_paths(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Paths::kFieldId, data, size);
+ }
+ void add_paths(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Paths::kFieldId, chars.data, chars.size);
+ }
+ void add_paths(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Paths::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ InodeFileMap_Entry_Type,
+ InodeFileMap_Entry>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(InodeFileMap_Entry_Type value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ftrace_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AllocPagesIommuEndFtraceEvent;
+class AllocPagesIommuFailFtraceEvent;
+class AllocPagesIommuStartFtraceEvent;
+class AllocPagesSysEndFtraceEvent;
+class AllocPagesSysFailFtraceEvent;
+class AllocPagesSysStartFtraceEvent;
+class AndroidFsDatareadEndFtraceEvent;
+class AndroidFsDatareadStartFtraceEvent;
+class AndroidFsDatawriteEndFtraceEvent;
+class AndroidFsDatawriteStartFtraceEvent;
+class AndroidFsFsyncEndFtraceEvent;
+class AndroidFsFsyncStartFtraceEvent;
+class BinderCommandFtraceEvent;
+class BinderLockFtraceEvent;
+class BinderLockedFtraceEvent;
+class BinderReturnFtraceEvent;
+class BinderSetPriorityFtraceEvent;
+class BinderTransactionAllocBufFtraceEvent;
+class BinderTransactionFtraceEvent;
+class BinderTransactionReceivedFtraceEvent;
+class BinderUnlockFtraceEvent;
+class BlockBioBackmergeFtraceEvent;
+class BlockBioBounceFtraceEvent;
+class BlockBioCompleteFtraceEvent;
+class BlockBioFrontmergeFtraceEvent;
+class BlockBioQueueFtraceEvent;
+class BlockBioRemapFtraceEvent;
+class BlockDirtyBufferFtraceEvent;
+class BlockGetrqFtraceEvent;
+class BlockPlugFtraceEvent;
+class BlockRqAbortFtraceEvent;
+class BlockRqCompleteFtraceEvent;
+class BlockRqInsertFtraceEvent;
+class BlockRqIssueFtraceEvent;
+class BlockRqRemapFtraceEvent;
+class BlockRqRequeueFtraceEvent;
+class BlockSleeprqFtraceEvent;
+class BlockSplitFtraceEvent;
+class BlockTouchBufferFtraceEvent;
+class BlockUnplugFtraceEvent;
+class CdevUpdateFtraceEvent;
+class CgroupAttachTaskFtraceEvent;
+class CgroupDestroyRootFtraceEvent;
+class CgroupMkdirFtraceEvent;
+class CgroupReleaseFtraceEvent;
+class CgroupRemountFtraceEvent;
+class CgroupRenameFtraceEvent;
+class CgroupRmdirFtraceEvent;
+class CgroupSetupRootFtraceEvent;
+class CgroupTransferTasksFtraceEvent;
+class ClkDisableFtraceEvent;
+class ClkEnableFtraceEvent;
+class ClkSetRateFtraceEvent;
+class ClockDisableFtraceEvent;
+class ClockEnableFtraceEvent;
+class ClockSetRateFtraceEvent;
+class CmaAllocInfoFtraceEvent;
+class CmaAllocStartFtraceEvent;
+class ConsoleFtraceEvent;
+class CpuFrequencyFtraceEvent;
+class CpuFrequencyLimitsFtraceEvent;
+class CpuIdleFtraceEvent;
+class CpuhpEnterFtraceEvent;
+class CpuhpExitFtraceEvent;
+class CpuhpLatencyFtraceEvent;
+class CpuhpMultiEnterFtraceEvent;
+class CpuhpPauseFtraceEvent;
+class CrosEcSensorhubDataFtraceEvent;
+class DmaAllocContiguousRetryFtraceEvent;
+class DmaFenceEmitFtraceEvent;
+class DmaFenceInitFtraceEvent;
+class DmaFenceSignaledFtraceEvent;
+class DmaFenceWaitEndFtraceEvent;
+class DmaFenceWaitStartFtraceEvent;
+class DmaHeapStatFtraceEvent;
+class DpuDsiCmdFifoStatusFtraceEvent;
+class DpuDsiRxFtraceEvent;
+class DpuDsiTxFtraceEvent;
+class DpuTracingMarkWriteFtraceEvent;
+class DrmRunJobFtraceEvent;
+class DrmSchedJobFtraceEvent;
+class DrmSchedProcessJobFtraceEvent;
+class DrmVblankEventDeliveredFtraceEvent;
+class DrmVblankEventFtraceEvent;
+class DsiCmdFifoStatusFtraceEvent;
+class DsiRxFtraceEvent;
+class DsiTxFtraceEvent;
+class Ext4AllocDaBlocksFtraceEvent;
+class Ext4AllocateBlocksFtraceEvent;
+class Ext4AllocateInodeFtraceEvent;
+class Ext4BeginOrderedTruncateFtraceEvent;
+class Ext4CollapseRangeFtraceEvent;
+class Ext4DaReleaseSpaceFtraceEvent;
+class Ext4DaReserveSpaceFtraceEvent;
+class Ext4DaUpdateReserveSpaceFtraceEvent;
+class Ext4DaWriteBeginFtraceEvent;
+class Ext4DaWriteEndFtraceEvent;
+class Ext4DaWritePagesExtentFtraceEvent;
+class Ext4DaWritePagesFtraceEvent;
+class Ext4DirectIOEnterFtraceEvent;
+class Ext4DirectIOExitFtraceEvent;
+class Ext4DiscardBlocksFtraceEvent;
+class Ext4DiscardPreallocationsFtraceEvent;
+class Ext4DropInodeFtraceEvent;
+class Ext4EsCacheExtentFtraceEvent;
+class Ext4EsFindDelayedExtentRangeEnterFtraceEvent;
+class Ext4EsFindDelayedExtentRangeExitFtraceEvent;
+class Ext4EsInsertExtentFtraceEvent;
+class Ext4EsLookupExtentEnterFtraceEvent;
+class Ext4EsLookupExtentExitFtraceEvent;
+class Ext4EsRemoveExtentFtraceEvent;
+class Ext4EsShrinkCountFtraceEvent;
+class Ext4EsShrinkFtraceEvent;
+class Ext4EsShrinkScanEnterFtraceEvent;
+class Ext4EsShrinkScanExitFtraceEvent;
+class Ext4EvictInodeFtraceEvent;
+class Ext4ExtConvertToInitializedEnterFtraceEvent;
+class Ext4ExtConvertToInitializedFastpathFtraceEvent;
+class Ext4ExtHandleUnwrittenExtentsFtraceEvent;
+class Ext4ExtInCacheFtraceEvent;
+class Ext4ExtLoadExtentFtraceEvent;
+class Ext4ExtMapBlocksEnterFtraceEvent;
+class Ext4ExtMapBlocksExitFtraceEvent;
+class Ext4ExtPutInCacheFtraceEvent;
+class Ext4ExtRemoveSpaceDoneFtraceEvent;
+class Ext4ExtRemoveSpaceFtraceEvent;
+class Ext4ExtRmIdxFtraceEvent;
+class Ext4ExtRmLeafFtraceEvent;
+class Ext4ExtShowExtentFtraceEvent;
+class Ext4FallocateEnterFtraceEvent;
+class Ext4FallocateExitFtraceEvent;
+class Ext4FindDelallocRangeFtraceEvent;
+class Ext4ForgetFtraceEvent;
+class Ext4FreeBlocksFtraceEvent;
+class Ext4FreeInodeFtraceEvent;
+class Ext4GetImpliedClusterAllocExitFtraceEvent;
+class Ext4GetReservedClusterAllocFtraceEvent;
+class Ext4IndMapBlocksEnterFtraceEvent;
+class Ext4IndMapBlocksExitFtraceEvent;
+class Ext4InsertRangeFtraceEvent;
+class Ext4InvalidatepageFtraceEvent;
+class Ext4JournalStartFtraceEvent;
+class Ext4JournalStartReservedFtraceEvent;
+class Ext4JournalledInvalidatepageFtraceEvent;
+class Ext4JournalledWriteEndFtraceEvent;
+class Ext4LoadInodeBitmapFtraceEvent;
+class Ext4LoadInodeFtraceEvent;
+class Ext4MarkInodeDirtyFtraceEvent;
+class Ext4MbBitmapLoadFtraceEvent;
+class Ext4MbBuddyBitmapLoadFtraceEvent;
+class Ext4MbDiscardPreallocationsFtraceEvent;
+class Ext4MbNewGroupPaFtraceEvent;
+class Ext4MbNewInodePaFtraceEvent;
+class Ext4MbReleaseGroupPaFtraceEvent;
+class Ext4MbReleaseInodePaFtraceEvent;
+class Ext4MballocAllocFtraceEvent;
+class Ext4MballocDiscardFtraceEvent;
+class Ext4MballocFreeFtraceEvent;
+class Ext4MballocPreallocFtraceEvent;
+class Ext4OtherInodeUpdateTimeFtraceEvent;
+class Ext4PunchHoleFtraceEvent;
+class Ext4ReadBlockBitmapLoadFtraceEvent;
+class Ext4ReadpageFtraceEvent;
+class Ext4ReleasepageFtraceEvent;
+class Ext4RemoveBlocksFtraceEvent;
+class Ext4RequestBlocksFtraceEvent;
+class Ext4RequestInodeFtraceEvent;
+class Ext4SyncFileEnterFtraceEvent;
+class Ext4SyncFileExitFtraceEvent;
+class Ext4SyncFsFtraceEvent;
+class Ext4TrimAllFreeFtraceEvent;
+class Ext4TrimExtentFtraceEvent;
+class Ext4TruncateEnterFtraceEvent;
+class Ext4TruncateExitFtraceEvent;
+class Ext4UnlinkEnterFtraceEvent;
+class Ext4UnlinkExitFtraceEvent;
+class Ext4WriteBeginFtraceEvent;
+class Ext4WriteEndFtraceEvent;
+class Ext4WritepageFtraceEvent;
+class Ext4WritepagesFtraceEvent;
+class Ext4WritepagesResultFtraceEvent;
+class Ext4ZeroRangeFtraceEvent;
+class F2fsBackgroundGcFtraceEvent;
+class F2fsDoSubmitBioFtraceEvent;
+class F2fsEvictInodeFtraceEvent;
+class F2fsFallocateFtraceEvent;
+class F2fsGcBeginFtraceEvent;
+class F2fsGcEndFtraceEvent;
+class F2fsGetDataBlockFtraceEvent;
+class F2fsGetVictimFtraceEvent;
+class F2fsIgetExitFtraceEvent;
+class F2fsIgetFtraceEvent;
+class F2fsIostatFtraceEvent;
+class F2fsIostatLatencyFtraceEvent;
+class F2fsNewInodeFtraceEvent;
+class F2fsReadpageFtraceEvent;
+class F2fsReserveNewBlockFtraceEvent;
+class F2fsSetPageDirtyFtraceEvent;
+class F2fsSubmitWritePageFtraceEvent;
+class F2fsSyncFileEnterFtraceEvent;
+class F2fsSyncFileExitFtraceEvent;
+class F2fsSyncFsFtraceEvent;
+class F2fsTruncateBlocksEnterFtraceEvent;
+class F2fsTruncateBlocksExitFtraceEvent;
+class F2fsTruncateDataBlocksRangeFtraceEvent;
+class F2fsTruncateFtraceEvent;
+class F2fsTruncateInodeBlocksEnterFtraceEvent;
+class F2fsTruncateInodeBlocksExitFtraceEvent;
+class F2fsTruncateNodeFtraceEvent;
+class F2fsTruncateNodesEnterFtraceEvent;
+class F2fsTruncateNodesExitFtraceEvent;
+class F2fsTruncatePartialNodesFtraceEvent;
+class F2fsUnlinkEnterFtraceEvent;
+class F2fsUnlinkExitFtraceEvent;
+class F2fsVmPageMkwriteFtraceEvent;
+class F2fsWriteBeginFtraceEvent;
+class F2fsWriteCheckpointFtraceEvent;
+class F2fsWriteEndFtraceEvent;
+class FastrpcDmaStatFtraceEvent;
+class FenceDestroyFtraceEvent;
+class FenceEnableSignalFtraceEvent;
+class FenceInitFtraceEvent;
+class FenceSignaledFtraceEvent;
+class FuncgraphEntryFtraceEvent;
+class FuncgraphExitFtraceEvent;
+class G2dTracingMarkWriteFtraceEvent;
+class GenericFtraceEvent;
+class GpuFrequencyFtraceEvent;
+class GpuMemTotalFtraceEvent;
+class GpuWorkPeriodFtraceEvent;
+class HostHcallFtraceEvent;
+class HostMemAbortFtraceEvent;
+class HostSmcFtraceEvent;
+class HypEnterFtraceEvent;
+class HypExitFtraceEvent;
+class I2cReadFtraceEvent;
+class I2cReplyFtraceEvent;
+class I2cResultFtraceEvent;
+class I2cWriteFtraceEvent;
+class InetSockSetStateFtraceEvent;
+class IommuMapRangeFtraceEvent;
+class IommuSecPtblMapRangeEndFtraceEvent;
+class IommuSecPtblMapRangeStartFtraceEvent;
+class IonAllocBufferEndFtraceEvent;
+class IonAllocBufferFailFtraceEvent;
+class IonAllocBufferFallbackFtraceEvent;
+class IonAllocBufferStartFtraceEvent;
+class IonBufferCreateFtraceEvent;
+class IonBufferDestroyFtraceEvent;
+class IonCpAllocRetryFtraceEvent;
+class IonCpSecureBufferEndFtraceEvent;
+class IonCpSecureBufferStartFtraceEvent;
+class IonHeapGrowFtraceEvent;
+class IonHeapShrinkFtraceEvent;
+class IonPrefetchingFtraceEvent;
+class IonSecureCmaAddToPoolEndFtraceEvent;
+class IonSecureCmaAddToPoolStartFtraceEvent;
+class IonSecureCmaAllocateEndFtraceEvent;
+class IonSecureCmaAllocateStartFtraceEvent;
+class IonSecureCmaShrinkPoolEndFtraceEvent;
+class IonSecureCmaShrinkPoolStartFtraceEvent;
+class IonStatFtraceEvent;
+class IpiEntryFtraceEvent;
+class IpiExitFtraceEvent;
+class IpiRaiseFtraceEvent;
+class IrqHandlerEntryFtraceEvent;
+class IrqHandlerExitFtraceEvent;
+class KfreeFtraceEvent;
+class KfreeSkbFtraceEvent;
+class KmallocFtraceEvent;
+class KmallocNodeFtraceEvent;
+class KmemCacheAllocFtraceEvent;
+class KmemCacheAllocNodeFtraceEvent;
+class KmemCacheFreeFtraceEvent;
+class KvmAccessFaultFtraceEvent;
+class KvmAckIrqFtraceEvent;
+class KvmAgeHvaFtraceEvent;
+class KvmAgePageFtraceEvent;
+class KvmArmClearDebugFtraceEvent;
+class KvmArmSetDreg32FtraceEvent;
+class KvmArmSetRegsetFtraceEvent;
+class KvmArmSetupDebugFtraceEvent;
+class KvmEntryFtraceEvent;
+class KvmExitFtraceEvent;
+class KvmFpuFtraceEvent;
+class KvmGetTimerMapFtraceEvent;
+class KvmGuestFaultFtraceEvent;
+class KvmHandleSysRegFtraceEvent;
+class KvmHvcArm64FtraceEvent;
+class KvmIrqLineFtraceEvent;
+class KvmMmioEmulateFtraceEvent;
+class KvmMmioFtraceEvent;
+class KvmSetGuestDebugFtraceEvent;
+class KvmSetIrqFtraceEvent;
+class KvmSetSpteHvaFtraceEvent;
+class KvmSetWayFlushFtraceEvent;
+class KvmSysAccessFtraceEvent;
+class KvmTestAgeHvaFtraceEvent;
+class KvmTimerEmulateFtraceEvent;
+class KvmTimerHrtimerExpireFtraceEvent;
+class KvmTimerRestoreStateFtraceEvent;
+class KvmTimerSaveStateFtraceEvent;
+class KvmTimerUpdateIrqFtraceEvent;
+class KvmToggleCacheFtraceEvent;
+class KvmUnmapHvaRangeFtraceEvent;
+class KvmUserspaceExitFtraceEvent;
+class KvmVcpuWakeupFtraceEvent;
+class KvmWfxArm64FtraceEvent;
+class LowmemoryKillFtraceEvent;
+class LwisTracingMarkWriteFtraceEvent;
+class MaliMaliCSFINTERRUPTENDFtraceEvent;
+class MaliMaliCSFINTERRUPTSTARTFtraceEvent;
+class MaliMaliKCPUCQSSETFtraceEvent;
+class MaliMaliKCPUCQSWAITENDFtraceEvent;
+class MaliMaliKCPUCQSWAITSTARTFtraceEvent;
+class MaliMaliKCPUFENCESIGNALFtraceEvent;
+class MaliMaliKCPUFENCEWAITENDFtraceEvent;
+class MaliMaliKCPUFENCEWAITSTARTFtraceEvent;
+class MaliTracingMarkWriteFtraceEvent;
+class MarkVictimFtraceEvent;
+class MdpCmdKickoffFtraceEvent;
+class MdpCmdPingpongDoneFtraceEvent;
+class MdpCmdReadptrDoneFtraceEvent;
+class MdpCmdReleaseBwFtraceEvent;
+class MdpCmdWaitPingpongFtraceEvent;
+class MdpCommitFtraceEvent;
+class MdpCompareBwFtraceEvent;
+class MdpMisrCrcFtraceEvent;
+class MdpMixerUpdateFtraceEvent;
+class MdpPerfPrefillCalcFtraceEvent;
+class MdpPerfSetOtFtraceEvent;
+class MdpPerfSetPanicLutsFtraceEvent;
+class MdpPerfSetQosLutsFtraceEvent;
+class MdpPerfSetWmLevelsFtraceEvent;
+class MdpPerfUpdateBusFtraceEvent;
+class MdpSsppChangeFtraceEvent;
+class MdpSsppSetFtraceEvent;
+class MdpTraceCounterFtraceEvent;
+class MdpVideoUnderrunDoneFtraceEvent;
+class MigratePagesEndFtraceEvent;
+class MigratePagesStartFtraceEvent;
+class MigrateRetryFtraceEvent;
+class MmCompactionBeginFtraceEvent;
+class MmCompactionDeferCompactionFtraceEvent;
+class MmCompactionDeferResetFtraceEvent;
+class MmCompactionDeferredFtraceEvent;
+class MmCompactionEndFtraceEvent;
+class MmCompactionFinishedFtraceEvent;
+class MmCompactionIsolateFreepagesFtraceEvent;
+class MmCompactionIsolateMigratepagesFtraceEvent;
+class MmCompactionKcompactdSleepFtraceEvent;
+class MmCompactionKcompactdWakeFtraceEvent;
+class MmCompactionMigratepagesFtraceEvent;
+class MmCompactionSuitableFtraceEvent;
+class MmCompactionTryToCompactPagesFtraceEvent;
+class MmCompactionWakeupKcompactdFtraceEvent;
+class MmEventRecordFtraceEvent;
+class MmFilemapAddToPageCacheFtraceEvent;
+class MmFilemapDeleteFromPageCacheFtraceEvent;
+class MmPageAllocExtfragFtraceEvent;
+class MmPageAllocFtraceEvent;
+class MmPageAllocZoneLockedFtraceEvent;
+class MmPageFreeBatchedFtraceEvent;
+class MmPageFreeFtraceEvent;
+class MmPagePcpuDrainFtraceEvent;
+class MmShrinkSlabEndFtraceEvent;
+class MmShrinkSlabStartFtraceEvent;
+class MmVmscanDirectReclaimBeginFtraceEvent;
+class MmVmscanDirectReclaimEndFtraceEvent;
+class MmVmscanKswapdSleepFtraceEvent;
+class MmVmscanKswapdWakeFtraceEvent;
+class NapiGroReceiveEntryFtraceEvent;
+class NapiGroReceiveExitFtraceEvent;
+class NetDevXmitFtraceEvent;
+class NetifReceiveSkbFtraceEvent;
+class OomScoreAdjUpdateFtraceEvent;
+class PanelWriteGenericFtraceEvent;
+class PrintFtraceEvent;
+class RegulatorDisableCompleteFtraceEvent;
+class RegulatorDisableFtraceEvent;
+class RegulatorEnableCompleteFtraceEvent;
+class RegulatorEnableDelayFtraceEvent;
+class RegulatorEnableFtraceEvent;
+class RegulatorSetVoltageCompleteFtraceEvent;
+class RegulatorSetVoltageFtraceEvent;
+class RotatorBwAoAsContextFtraceEvent;
+class RpmStatusFtraceEvent;
+class RssStatFtraceEvent;
+class RssStatThrottledFtraceEvent;
+class SamsungTracingMarkWriteFtraceEvent;
+class SchedBlockedReasonFtraceEvent;
+class SchedCpuHotplugFtraceEvent;
+class SchedCpuUtilCfsFtraceEvent;
+class SchedMigrateTaskFtraceEvent;
+class SchedPiSetprioFtraceEvent;
+class SchedProcessExecFtraceEvent;
+class SchedProcessExitFtraceEvent;
+class SchedProcessForkFtraceEvent;
+class SchedProcessFreeFtraceEvent;
+class SchedProcessHangFtraceEvent;
+class SchedProcessWaitFtraceEvent;
+class SchedSwitchFtraceEvent;
+class SchedSwitchWithCtrsFtraceEvent;
+class SchedWakeupFtraceEvent;
+class SchedWakeupNewFtraceEvent;
+class SchedWakingFtraceEvent;
+class ScmCallEndFtraceEvent;
+class ScmCallStartFtraceEvent;
+class SdeSdeEvtlogFtraceEvent;
+class SdeSdePerfCalcCrtcFtraceEvent;
+class SdeSdePerfCrtcUpdateFtraceEvent;
+class SdeSdePerfSetQosLutsFtraceEvent;
+class SdeSdePerfUpdateBusFtraceEvent;
+class SdeTracingMarkWriteFtraceEvent;
+class SignalDeliverFtraceEvent;
+class SignalGenerateFtraceEvent;
+class SmbusReadFtraceEvent;
+class SmbusReplyFtraceEvent;
+class SmbusResultFtraceEvent;
+class SmbusWriteFtraceEvent;
+class SoftirqEntryFtraceEvent;
+class SoftirqExitFtraceEvent;
+class SoftirqRaiseFtraceEvent;
+class SuspendResumeFtraceEvent;
+class SuspendResumeMinimalFtraceEvent;
+class SyncPtFtraceEvent;
+class SyncTimelineFtraceEvent;
+class SyncWaitFtraceEvent;
+class SysEnterFtraceEvent;
+class SysExitFtraceEvent;
+class TaskNewtaskFtraceEvent;
+class TaskRenameFtraceEvent;
+class TcpRetransmitSkbFtraceEvent;
+class ThermalTemperatureFtraceEvent;
+class TracingMarkWriteFtraceEvent;
+class TrapRegFtraceEvent;
+class TrustyEnqueueNopFtraceEvent;
+class TrustyIpcConnectEndFtraceEvent;
+class TrustyIpcConnectFtraceEvent;
+class TrustyIpcHandleEventFtraceEvent;
+class TrustyIpcPollFtraceEvent;
+class TrustyIpcReadEndFtraceEvent;
+class TrustyIpcReadFtraceEvent;
+class TrustyIpcRxFtraceEvent;
+class TrustyIpcWriteFtraceEvent;
+class TrustyIrqFtraceEvent;
+class TrustyReclaimMemoryDoneFtraceEvent;
+class TrustyReclaimMemoryFtraceEvent;
+class TrustyShareMemoryDoneFtraceEvent;
+class TrustyShareMemoryFtraceEvent;
+class TrustySmcDoneFtraceEvent;
+class TrustySmcFtraceEvent;
+class TrustyStdCall32DoneFtraceEvent;
+class TrustyStdCall32FtraceEvent;
+class UfshcdClkGatingFtraceEvent;
+class UfshcdCommandFtraceEvent;
+class V4l2DqbufFtraceEvent;
+class V4l2QbufFtraceEvent;
+class Vb2V4l2BufDoneFtraceEvent;
+class Vb2V4l2BufQueueFtraceEvent;
+class Vb2V4l2DqbufFtraceEvent;
+class Vb2V4l2QbufFtraceEvent;
+class VgicUpdateIrqPendingFtraceEvent;
+class VirtioGpuCmdQueueFtraceEvent;
+class VirtioGpuCmdResponseFtraceEvent;
+class VirtioVideoCmdDoneFtraceEvent;
+class VirtioVideoCmdFtraceEvent;
+class VirtioVideoResourceQueueDoneFtraceEvent;
+class VirtioVideoResourceQueueFtraceEvent;
+class WakeupSourceActivateFtraceEvent;
+class WakeupSourceDeactivateFtraceEvent;
+class WorkqueueActivateWorkFtraceEvent;
+class WorkqueueExecuteEndFtraceEvent;
+class WorkqueueExecuteStartFtraceEvent;
+class WorkqueueQueueWorkFtraceEvent;
+class ZeroFtraceEvent;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class FtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/497, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timestamp() const { return at<1>().valid(); }
+ uint64_t timestamp() const { return at<1>().as_uint64(); }
+ bool has_pid() const { return at<2>().valid(); }
+ uint32_t pid() const { return at<2>().as_uint32(); }
+ bool has_common_flags() const { return at<5>().valid(); }
+ uint32_t common_flags() const { return at<5>().as_uint32(); }
+ bool has_print() const { return at<3>().valid(); }
+ ::protozero::ConstBytes print() const { return at<3>().as_bytes(); }
+ bool has_sched_switch() const { return at<4>().valid(); }
+ ::protozero::ConstBytes sched_switch() const { return at<4>().as_bytes(); }
+ bool has_cpu_frequency() const { return at<11>().valid(); }
+ ::protozero::ConstBytes cpu_frequency() const { return at<11>().as_bytes(); }
+ bool has_cpu_frequency_limits() const { return at<12>().valid(); }
+ ::protozero::ConstBytes cpu_frequency_limits() const { return at<12>().as_bytes(); }
+ bool has_cpu_idle() const { return at<13>().valid(); }
+ ::protozero::ConstBytes cpu_idle() const { return at<13>().as_bytes(); }
+ bool has_clock_enable() const { return at<14>().valid(); }
+ ::protozero::ConstBytes clock_enable() const { return at<14>().as_bytes(); }
+ bool has_clock_disable() const { return at<15>().valid(); }
+ ::protozero::ConstBytes clock_disable() const { return at<15>().as_bytes(); }
+ bool has_clock_set_rate() const { return at<16>().valid(); }
+ ::protozero::ConstBytes clock_set_rate() const { return at<16>().as_bytes(); }
+ bool has_sched_wakeup() const { return at<17>().valid(); }
+ ::protozero::ConstBytes sched_wakeup() const { return at<17>().as_bytes(); }
+ bool has_sched_blocked_reason() const { return at<18>().valid(); }
+ ::protozero::ConstBytes sched_blocked_reason() const { return at<18>().as_bytes(); }
+ bool has_sched_cpu_hotplug() const { return at<19>().valid(); }
+ ::protozero::ConstBytes sched_cpu_hotplug() const { return at<19>().as_bytes(); }
+ bool has_sched_waking() const { return at<20>().valid(); }
+ ::protozero::ConstBytes sched_waking() const { return at<20>().as_bytes(); }
+ bool has_ipi_entry() const { return at<21>().valid(); }
+ ::protozero::ConstBytes ipi_entry() const { return at<21>().as_bytes(); }
+ bool has_ipi_exit() const { return at<22>().valid(); }
+ ::protozero::ConstBytes ipi_exit() const { return at<22>().as_bytes(); }
+ bool has_ipi_raise() const { return at<23>().valid(); }
+ ::protozero::ConstBytes ipi_raise() const { return at<23>().as_bytes(); }
+ bool has_softirq_entry() const { return at<24>().valid(); }
+ ::protozero::ConstBytes softirq_entry() const { return at<24>().as_bytes(); }
+ bool has_softirq_exit() const { return at<25>().valid(); }
+ ::protozero::ConstBytes softirq_exit() const { return at<25>().as_bytes(); }
+ bool has_softirq_raise() const { return at<26>().valid(); }
+ ::protozero::ConstBytes softirq_raise() const { return at<26>().as_bytes(); }
+ bool has_i2c_read() const { return at<27>().valid(); }
+ ::protozero::ConstBytes i2c_read() const { return at<27>().as_bytes(); }
+ bool has_i2c_write() const { return at<28>().valid(); }
+ ::protozero::ConstBytes i2c_write() const { return at<28>().as_bytes(); }
+ bool has_i2c_result() const { return at<29>().valid(); }
+ ::protozero::ConstBytes i2c_result() const { return at<29>().as_bytes(); }
+ bool has_i2c_reply() const { return at<30>().valid(); }
+ ::protozero::ConstBytes i2c_reply() const { return at<30>().as_bytes(); }
+ bool has_smbus_read() const { return at<31>().valid(); }
+ ::protozero::ConstBytes smbus_read() const { return at<31>().as_bytes(); }
+ bool has_smbus_write() const { return at<32>().valid(); }
+ ::protozero::ConstBytes smbus_write() const { return at<32>().as_bytes(); }
+ bool has_smbus_result() const { return at<33>().valid(); }
+ ::protozero::ConstBytes smbus_result() const { return at<33>().as_bytes(); }
+ bool has_smbus_reply() const { return at<34>().valid(); }
+ ::protozero::ConstBytes smbus_reply() const { return at<34>().as_bytes(); }
+ bool has_lowmemory_kill() const { return at<35>().valid(); }
+ ::protozero::ConstBytes lowmemory_kill() const { return at<35>().as_bytes(); }
+ bool has_irq_handler_entry() const { return at<36>().valid(); }
+ ::protozero::ConstBytes irq_handler_entry() const { return at<36>().as_bytes(); }
+ bool has_irq_handler_exit() const { return at<37>().valid(); }
+ ::protozero::ConstBytes irq_handler_exit() const { return at<37>().as_bytes(); }
+ bool has_sync_pt() const { return at<38>().valid(); }
+ ::protozero::ConstBytes sync_pt() const { return at<38>().as_bytes(); }
+ bool has_sync_timeline() const { return at<39>().valid(); }
+ ::protozero::ConstBytes sync_timeline() const { return at<39>().as_bytes(); }
+ bool has_sync_wait() const { return at<40>().valid(); }
+ ::protozero::ConstBytes sync_wait() const { return at<40>().as_bytes(); }
+ bool has_ext4_da_write_begin() const { return at<41>().valid(); }
+ ::protozero::ConstBytes ext4_da_write_begin() const { return at<41>().as_bytes(); }
+ bool has_ext4_da_write_end() const { return at<42>().valid(); }
+ ::protozero::ConstBytes ext4_da_write_end() const { return at<42>().as_bytes(); }
+ bool has_ext4_sync_file_enter() const { return at<43>().valid(); }
+ ::protozero::ConstBytes ext4_sync_file_enter() const { return at<43>().as_bytes(); }
+ bool has_ext4_sync_file_exit() const { return at<44>().valid(); }
+ ::protozero::ConstBytes ext4_sync_file_exit() const { return at<44>().as_bytes(); }
+ bool has_block_rq_issue() const { return at<45>().valid(); }
+ ::protozero::ConstBytes block_rq_issue() const { return at<45>().as_bytes(); }
+ bool has_mm_vmscan_direct_reclaim_begin() const { return at<46>().valid(); }
+ ::protozero::ConstBytes mm_vmscan_direct_reclaim_begin() const { return at<46>().as_bytes(); }
+ bool has_mm_vmscan_direct_reclaim_end() const { return at<47>().valid(); }
+ ::protozero::ConstBytes mm_vmscan_direct_reclaim_end() const { return at<47>().as_bytes(); }
+ bool has_mm_vmscan_kswapd_wake() const { return at<48>().valid(); }
+ ::protozero::ConstBytes mm_vmscan_kswapd_wake() const { return at<48>().as_bytes(); }
+ bool has_mm_vmscan_kswapd_sleep() const { return at<49>().valid(); }
+ ::protozero::ConstBytes mm_vmscan_kswapd_sleep() const { return at<49>().as_bytes(); }
+ bool has_binder_transaction() const { return at<50>().valid(); }
+ ::protozero::ConstBytes binder_transaction() const { return at<50>().as_bytes(); }
+ bool has_binder_transaction_received() const { return at<51>().valid(); }
+ ::protozero::ConstBytes binder_transaction_received() const { return at<51>().as_bytes(); }
+ bool has_binder_set_priority() const { return at<52>().valid(); }
+ ::protozero::ConstBytes binder_set_priority() const { return at<52>().as_bytes(); }
+ bool has_binder_lock() const { return at<53>().valid(); }
+ ::protozero::ConstBytes binder_lock() const { return at<53>().as_bytes(); }
+ bool has_binder_locked() const { return at<54>().valid(); }
+ ::protozero::ConstBytes binder_locked() const { return at<54>().as_bytes(); }
+ bool has_binder_unlock() const { return at<55>().valid(); }
+ ::protozero::ConstBytes binder_unlock() const { return at<55>().as_bytes(); }
+ bool has_workqueue_activate_work() const { return at<56>().valid(); }
+ ::protozero::ConstBytes workqueue_activate_work() const { return at<56>().as_bytes(); }
+ bool has_workqueue_execute_end() const { return at<57>().valid(); }
+ ::protozero::ConstBytes workqueue_execute_end() const { return at<57>().as_bytes(); }
+ bool has_workqueue_execute_start() const { return at<58>().valid(); }
+ ::protozero::ConstBytes workqueue_execute_start() const { return at<58>().as_bytes(); }
+ bool has_workqueue_queue_work() const { return at<59>().valid(); }
+ ::protozero::ConstBytes workqueue_queue_work() const { return at<59>().as_bytes(); }
+ bool has_regulator_disable() const { return at<60>().valid(); }
+ ::protozero::ConstBytes regulator_disable() const { return at<60>().as_bytes(); }
+ bool has_regulator_disable_complete() const { return at<61>().valid(); }
+ ::protozero::ConstBytes regulator_disable_complete() const { return at<61>().as_bytes(); }
+ bool has_regulator_enable() const { return at<62>().valid(); }
+ ::protozero::ConstBytes regulator_enable() const { return at<62>().as_bytes(); }
+ bool has_regulator_enable_complete() const { return at<63>().valid(); }
+ ::protozero::ConstBytes regulator_enable_complete() const { return at<63>().as_bytes(); }
+ bool has_regulator_enable_delay() const { return at<64>().valid(); }
+ ::protozero::ConstBytes regulator_enable_delay() const { return at<64>().as_bytes(); }
+ bool has_regulator_set_voltage() const { return at<65>().valid(); }
+ ::protozero::ConstBytes regulator_set_voltage() const { return at<65>().as_bytes(); }
+ bool has_regulator_set_voltage_complete() const { return at<66>().valid(); }
+ ::protozero::ConstBytes regulator_set_voltage_complete() const { return at<66>().as_bytes(); }
+ bool has_cgroup_attach_task() const { return at<67>().valid(); }
+ ::protozero::ConstBytes cgroup_attach_task() const { return at<67>().as_bytes(); }
+ bool has_cgroup_mkdir() const { return at<68>().valid(); }
+ ::protozero::ConstBytes cgroup_mkdir() const { return at<68>().as_bytes(); }
+ bool has_cgroup_remount() const { return at<69>().valid(); }
+ ::protozero::ConstBytes cgroup_remount() const { return at<69>().as_bytes(); }
+ bool has_cgroup_rmdir() const { return at<70>().valid(); }
+ ::protozero::ConstBytes cgroup_rmdir() const { return at<70>().as_bytes(); }
+ bool has_cgroup_transfer_tasks() const { return at<71>().valid(); }
+ ::protozero::ConstBytes cgroup_transfer_tasks() const { return at<71>().as_bytes(); }
+ bool has_cgroup_destroy_root() const { return at<72>().valid(); }
+ ::protozero::ConstBytes cgroup_destroy_root() const { return at<72>().as_bytes(); }
+ bool has_cgroup_release() const { return at<73>().valid(); }
+ ::protozero::ConstBytes cgroup_release() const { return at<73>().as_bytes(); }
+ bool has_cgroup_rename() const { return at<74>().valid(); }
+ ::protozero::ConstBytes cgroup_rename() const { return at<74>().as_bytes(); }
+ bool has_cgroup_setup_root() const { return at<75>().valid(); }
+ ::protozero::ConstBytes cgroup_setup_root() const { return at<75>().as_bytes(); }
+ bool has_mdp_cmd_kickoff() const { return at<76>().valid(); }
+ ::protozero::ConstBytes mdp_cmd_kickoff() const { return at<76>().as_bytes(); }
+ bool has_mdp_commit() const { return at<77>().valid(); }
+ ::protozero::ConstBytes mdp_commit() const { return at<77>().as_bytes(); }
+ bool has_mdp_perf_set_ot() const { return at<78>().valid(); }
+ ::protozero::ConstBytes mdp_perf_set_ot() const { return at<78>().as_bytes(); }
+ bool has_mdp_sspp_change() const { return at<79>().valid(); }
+ ::protozero::ConstBytes mdp_sspp_change() const { return at<79>().as_bytes(); }
+ bool has_tracing_mark_write() const { return at<80>().valid(); }
+ ::protozero::ConstBytes tracing_mark_write() const { return at<80>().as_bytes(); }
+ bool has_mdp_cmd_pingpong_done() const { return at<81>().valid(); }
+ ::protozero::ConstBytes mdp_cmd_pingpong_done() const { return at<81>().as_bytes(); }
+ bool has_mdp_compare_bw() const { return at<82>().valid(); }
+ ::protozero::ConstBytes mdp_compare_bw() const { return at<82>().as_bytes(); }
+ bool has_mdp_perf_set_panic_luts() const { return at<83>().valid(); }
+ ::protozero::ConstBytes mdp_perf_set_panic_luts() const { return at<83>().as_bytes(); }
+ bool has_mdp_sspp_set() const { return at<84>().valid(); }
+ ::protozero::ConstBytes mdp_sspp_set() const { return at<84>().as_bytes(); }
+ bool has_mdp_cmd_readptr_done() const { return at<85>().valid(); }
+ ::protozero::ConstBytes mdp_cmd_readptr_done() const { return at<85>().as_bytes(); }
+ bool has_mdp_misr_crc() const { return at<86>().valid(); }
+ ::protozero::ConstBytes mdp_misr_crc() const { return at<86>().as_bytes(); }
+ bool has_mdp_perf_set_qos_luts() const { return at<87>().valid(); }
+ ::protozero::ConstBytes mdp_perf_set_qos_luts() const { return at<87>().as_bytes(); }
+ bool has_mdp_trace_counter() const { return at<88>().valid(); }
+ ::protozero::ConstBytes mdp_trace_counter() const { return at<88>().as_bytes(); }
+ bool has_mdp_cmd_release_bw() const { return at<89>().valid(); }
+ ::protozero::ConstBytes mdp_cmd_release_bw() const { return at<89>().as_bytes(); }
+ bool has_mdp_mixer_update() const { return at<90>().valid(); }
+ ::protozero::ConstBytes mdp_mixer_update() const { return at<90>().as_bytes(); }
+ bool has_mdp_perf_set_wm_levels() const { return at<91>().valid(); }
+ ::protozero::ConstBytes mdp_perf_set_wm_levels() const { return at<91>().as_bytes(); }
+ bool has_mdp_video_underrun_done() const { return at<92>().valid(); }
+ ::protozero::ConstBytes mdp_video_underrun_done() const { return at<92>().as_bytes(); }
+ bool has_mdp_cmd_wait_pingpong() const { return at<93>().valid(); }
+ ::protozero::ConstBytes mdp_cmd_wait_pingpong() const { return at<93>().as_bytes(); }
+ bool has_mdp_perf_prefill_calc() const { return at<94>().valid(); }
+ ::protozero::ConstBytes mdp_perf_prefill_calc() const { return at<94>().as_bytes(); }
+ bool has_mdp_perf_update_bus() const { return at<95>().valid(); }
+ ::protozero::ConstBytes mdp_perf_update_bus() const { return at<95>().as_bytes(); }
+ bool has_rotator_bw_ao_as_context() const { return at<96>().valid(); }
+ ::protozero::ConstBytes rotator_bw_ao_as_context() const { return at<96>().as_bytes(); }
+ bool has_mm_filemap_add_to_page_cache() const { return at<97>().valid(); }
+ ::protozero::ConstBytes mm_filemap_add_to_page_cache() const { return at<97>().as_bytes(); }
+ bool has_mm_filemap_delete_from_page_cache() const { return at<98>().valid(); }
+ ::protozero::ConstBytes mm_filemap_delete_from_page_cache() const { return at<98>().as_bytes(); }
+ bool has_mm_compaction_begin() const { return at<99>().valid(); }
+ ::protozero::ConstBytes mm_compaction_begin() const { return at<99>().as_bytes(); }
+ bool has_mm_compaction_defer_compaction() const { return at<100>().valid(); }
+ ::protozero::ConstBytes mm_compaction_defer_compaction() const { return at<100>().as_bytes(); }
+ bool has_mm_compaction_deferred() const { return at<101>().valid(); }
+ ::protozero::ConstBytes mm_compaction_deferred() const { return at<101>().as_bytes(); }
+ bool has_mm_compaction_defer_reset() const { return at<102>().valid(); }
+ ::protozero::ConstBytes mm_compaction_defer_reset() const { return at<102>().as_bytes(); }
+ bool has_mm_compaction_end() const { return at<103>().valid(); }
+ ::protozero::ConstBytes mm_compaction_end() const { return at<103>().as_bytes(); }
+ bool has_mm_compaction_finished() const { return at<104>().valid(); }
+ ::protozero::ConstBytes mm_compaction_finished() const { return at<104>().as_bytes(); }
+ bool has_mm_compaction_isolate_freepages() const { return at<105>().valid(); }
+ ::protozero::ConstBytes mm_compaction_isolate_freepages() const { return at<105>().as_bytes(); }
+ bool has_mm_compaction_isolate_migratepages() const { return at<106>().valid(); }
+ ::protozero::ConstBytes mm_compaction_isolate_migratepages() const { return at<106>().as_bytes(); }
+ bool has_mm_compaction_kcompactd_sleep() const { return at<107>().valid(); }
+ ::protozero::ConstBytes mm_compaction_kcompactd_sleep() const { return at<107>().as_bytes(); }
+ bool has_mm_compaction_kcompactd_wake() const { return at<108>().valid(); }
+ ::protozero::ConstBytes mm_compaction_kcompactd_wake() const { return at<108>().as_bytes(); }
+ bool has_mm_compaction_migratepages() const { return at<109>().valid(); }
+ ::protozero::ConstBytes mm_compaction_migratepages() const { return at<109>().as_bytes(); }
+ bool has_mm_compaction_suitable() const { return at<110>().valid(); }
+ ::protozero::ConstBytes mm_compaction_suitable() const { return at<110>().as_bytes(); }
+ bool has_mm_compaction_try_to_compact_pages() const { return at<111>().valid(); }
+ ::protozero::ConstBytes mm_compaction_try_to_compact_pages() const { return at<111>().as_bytes(); }
+ bool has_mm_compaction_wakeup_kcompactd() const { return at<112>().valid(); }
+ ::protozero::ConstBytes mm_compaction_wakeup_kcompactd() const { return at<112>().as_bytes(); }
+ bool has_suspend_resume() const { return at<113>().valid(); }
+ ::protozero::ConstBytes suspend_resume() const { return at<113>().as_bytes(); }
+ bool has_sched_wakeup_new() const { return at<114>().valid(); }
+ ::protozero::ConstBytes sched_wakeup_new() const { return at<114>().as_bytes(); }
+ bool has_block_bio_backmerge() const { return at<115>().valid(); }
+ ::protozero::ConstBytes block_bio_backmerge() const { return at<115>().as_bytes(); }
+ bool has_block_bio_bounce() const { return at<116>().valid(); }
+ ::protozero::ConstBytes block_bio_bounce() const { return at<116>().as_bytes(); }
+ bool has_block_bio_complete() const { return at<117>().valid(); }
+ ::protozero::ConstBytes block_bio_complete() const { return at<117>().as_bytes(); }
+ bool has_block_bio_frontmerge() const { return at<118>().valid(); }
+ ::protozero::ConstBytes block_bio_frontmerge() const { return at<118>().as_bytes(); }
+ bool has_block_bio_queue() const { return at<119>().valid(); }
+ ::protozero::ConstBytes block_bio_queue() const { return at<119>().as_bytes(); }
+ bool has_block_bio_remap() const { return at<120>().valid(); }
+ ::protozero::ConstBytes block_bio_remap() const { return at<120>().as_bytes(); }
+ bool has_block_dirty_buffer() const { return at<121>().valid(); }
+ ::protozero::ConstBytes block_dirty_buffer() const { return at<121>().as_bytes(); }
+ bool has_block_getrq() const { return at<122>().valid(); }
+ ::protozero::ConstBytes block_getrq() const { return at<122>().as_bytes(); }
+ bool has_block_plug() const { return at<123>().valid(); }
+ ::protozero::ConstBytes block_plug() const { return at<123>().as_bytes(); }
+ bool has_block_rq_abort() const { return at<124>().valid(); }
+ ::protozero::ConstBytes block_rq_abort() const { return at<124>().as_bytes(); }
+ bool has_block_rq_complete() const { return at<125>().valid(); }
+ ::protozero::ConstBytes block_rq_complete() const { return at<125>().as_bytes(); }
+ bool has_block_rq_insert() const { return at<126>().valid(); }
+ ::protozero::ConstBytes block_rq_insert() const { return at<126>().as_bytes(); }
+ bool has_block_rq_remap() const { return at<128>().valid(); }
+ ::protozero::ConstBytes block_rq_remap() const { return at<128>().as_bytes(); }
+ bool has_block_rq_requeue() const { return at<129>().valid(); }
+ ::protozero::ConstBytes block_rq_requeue() const { return at<129>().as_bytes(); }
+ bool has_block_sleeprq() const { return at<130>().valid(); }
+ ::protozero::ConstBytes block_sleeprq() const { return at<130>().as_bytes(); }
+ bool has_block_split() const { return at<131>().valid(); }
+ ::protozero::ConstBytes block_split() const { return at<131>().as_bytes(); }
+ bool has_block_touch_buffer() const { return at<132>().valid(); }
+ ::protozero::ConstBytes block_touch_buffer() const { return at<132>().as_bytes(); }
+ bool has_block_unplug() const { return at<133>().valid(); }
+ ::protozero::ConstBytes block_unplug() const { return at<133>().as_bytes(); }
+ bool has_ext4_alloc_da_blocks() const { return at<134>().valid(); }
+ ::protozero::ConstBytes ext4_alloc_da_blocks() const { return at<134>().as_bytes(); }
+ bool has_ext4_allocate_blocks() const { return at<135>().valid(); }
+ ::protozero::ConstBytes ext4_allocate_blocks() const { return at<135>().as_bytes(); }
+ bool has_ext4_allocate_inode() const { return at<136>().valid(); }
+ ::protozero::ConstBytes ext4_allocate_inode() const { return at<136>().as_bytes(); }
+ bool has_ext4_begin_ordered_truncate() const { return at<137>().valid(); }
+ ::protozero::ConstBytes ext4_begin_ordered_truncate() const { return at<137>().as_bytes(); }
+ bool has_ext4_collapse_range() const { return at<138>().valid(); }
+ ::protozero::ConstBytes ext4_collapse_range() const { return at<138>().as_bytes(); }
+ bool has_ext4_da_release_space() const { return at<139>().valid(); }
+ ::protozero::ConstBytes ext4_da_release_space() const { return at<139>().as_bytes(); }
+ bool has_ext4_da_reserve_space() const { return at<140>().valid(); }
+ ::protozero::ConstBytes ext4_da_reserve_space() const { return at<140>().as_bytes(); }
+ bool has_ext4_da_update_reserve_space() const { return at<141>().valid(); }
+ ::protozero::ConstBytes ext4_da_update_reserve_space() const { return at<141>().as_bytes(); }
+ bool has_ext4_da_write_pages() const { return at<142>().valid(); }
+ ::protozero::ConstBytes ext4_da_write_pages() const { return at<142>().as_bytes(); }
+ bool has_ext4_da_write_pages_extent() const { return at<143>().valid(); }
+ ::protozero::ConstBytes ext4_da_write_pages_extent() const { return at<143>().as_bytes(); }
+ bool has_ext4_direct_io_enter() const { return at<144>().valid(); }
+ ::protozero::ConstBytes ext4_direct_io_enter() const { return at<144>().as_bytes(); }
+ bool has_ext4_direct_io_exit() const { return at<145>().valid(); }
+ ::protozero::ConstBytes ext4_direct_io_exit() const { return at<145>().as_bytes(); }
+ bool has_ext4_discard_blocks() const { return at<146>().valid(); }
+ ::protozero::ConstBytes ext4_discard_blocks() const { return at<146>().as_bytes(); }
+ bool has_ext4_discard_preallocations() const { return at<147>().valid(); }
+ ::protozero::ConstBytes ext4_discard_preallocations() const { return at<147>().as_bytes(); }
+ bool has_ext4_drop_inode() const { return at<148>().valid(); }
+ ::protozero::ConstBytes ext4_drop_inode() const { return at<148>().as_bytes(); }
+ bool has_ext4_es_cache_extent() const { return at<149>().valid(); }
+ ::protozero::ConstBytes ext4_es_cache_extent() const { return at<149>().as_bytes(); }
+ bool has_ext4_es_find_delayed_extent_range_enter() const { return at<150>().valid(); }
+ ::protozero::ConstBytes ext4_es_find_delayed_extent_range_enter() const { return at<150>().as_bytes(); }
+ bool has_ext4_es_find_delayed_extent_range_exit() const { return at<151>().valid(); }
+ ::protozero::ConstBytes ext4_es_find_delayed_extent_range_exit() const { return at<151>().as_bytes(); }
+ bool has_ext4_es_insert_extent() const { return at<152>().valid(); }
+ ::protozero::ConstBytes ext4_es_insert_extent() const { return at<152>().as_bytes(); }
+ bool has_ext4_es_lookup_extent_enter() const { return at<153>().valid(); }
+ ::protozero::ConstBytes ext4_es_lookup_extent_enter() const { return at<153>().as_bytes(); }
+ bool has_ext4_es_lookup_extent_exit() const { return at<154>().valid(); }
+ ::protozero::ConstBytes ext4_es_lookup_extent_exit() const { return at<154>().as_bytes(); }
+ bool has_ext4_es_remove_extent() const { return at<155>().valid(); }
+ ::protozero::ConstBytes ext4_es_remove_extent() const { return at<155>().as_bytes(); }
+ bool has_ext4_es_shrink() const { return at<156>().valid(); }
+ ::protozero::ConstBytes ext4_es_shrink() const { return at<156>().as_bytes(); }
+ bool has_ext4_es_shrink_count() const { return at<157>().valid(); }
+ ::protozero::ConstBytes ext4_es_shrink_count() const { return at<157>().as_bytes(); }
+ bool has_ext4_es_shrink_scan_enter() const { return at<158>().valid(); }
+ ::protozero::ConstBytes ext4_es_shrink_scan_enter() const { return at<158>().as_bytes(); }
+ bool has_ext4_es_shrink_scan_exit() const { return at<159>().valid(); }
+ ::protozero::ConstBytes ext4_es_shrink_scan_exit() const { return at<159>().as_bytes(); }
+ bool has_ext4_evict_inode() const { return at<160>().valid(); }
+ ::protozero::ConstBytes ext4_evict_inode() const { return at<160>().as_bytes(); }
+ bool has_ext4_ext_convert_to_initialized_enter() const { return at<161>().valid(); }
+ ::protozero::ConstBytes ext4_ext_convert_to_initialized_enter() const { return at<161>().as_bytes(); }
+ bool has_ext4_ext_convert_to_initialized_fastpath() const { return at<162>().valid(); }
+ ::protozero::ConstBytes ext4_ext_convert_to_initialized_fastpath() const { return at<162>().as_bytes(); }
+ bool has_ext4_ext_handle_unwritten_extents() const { return at<163>().valid(); }
+ ::protozero::ConstBytes ext4_ext_handle_unwritten_extents() const { return at<163>().as_bytes(); }
+ bool has_ext4_ext_in_cache() const { return at<164>().valid(); }
+ ::protozero::ConstBytes ext4_ext_in_cache() const { return at<164>().as_bytes(); }
+ bool has_ext4_ext_load_extent() const { return at<165>().valid(); }
+ ::protozero::ConstBytes ext4_ext_load_extent() const { return at<165>().as_bytes(); }
+ bool has_ext4_ext_map_blocks_enter() const { return at<166>().valid(); }
+ ::protozero::ConstBytes ext4_ext_map_blocks_enter() const { return at<166>().as_bytes(); }
+ bool has_ext4_ext_map_blocks_exit() const { return at<167>().valid(); }
+ ::protozero::ConstBytes ext4_ext_map_blocks_exit() const { return at<167>().as_bytes(); }
+ bool has_ext4_ext_put_in_cache() const { return at<168>().valid(); }
+ ::protozero::ConstBytes ext4_ext_put_in_cache() const { return at<168>().as_bytes(); }
+ bool has_ext4_ext_remove_space() const { return at<169>().valid(); }
+ ::protozero::ConstBytes ext4_ext_remove_space() const { return at<169>().as_bytes(); }
+ bool has_ext4_ext_remove_space_done() const { return at<170>().valid(); }
+ ::protozero::ConstBytes ext4_ext_remove_space_done() const { return at<170>().as_bytes(); }
+ bool has_ext4_ext_rm_idx() const { return at<171>().valid(); }
+ ::protozero::ConstBytes ext4_ext_rm_idx() const { return at<171>().as_bytes(); }
+ bool has_ext4_ext_rm_leaf() const { return at<172>().valid(); }
+ ::protozero::ConstBytes ext4_ext_rm_leaf() const { return at<172>().as_bytes(); }
+ bool has_ext4_ext_show_extent() const { return at<173>().valid(); }
+ ::protozero::ConstBytes ext4_ext_show_extent() const { return at<173>().as_bytes(); }
+ bool has_ext4_fallocate_enter() const { return at<174>().valid(); }
+ ::protozero::ConstBytes ext4_fallocate_enter() const { return at<174>().as_bytes(); }
+ bool has_ext4_fallocate_exit() const { return at<175>().valid(); }
+ ::protozero::ConstBytes ext4_fallocate_exit() const { return at<175>().as_bytes(); }
+ bool has_ext4_find_delalloc_range() const { return at<176>().valid(); }
+ ::protozero::ConstBytes ext4_find_delalloc_range() const { return at<176>().as_bytes(); }
+ bool has_ext4_forget() const { return at<177>().valid(); }
+ ::protozero::ConstBytes ext4_forget() const { return at<177>().as_bytes(); }
+ bool has_ext4_free_blocks() const { return at<178>().valid(); }
+ ::protozero::ConstBytes ext4_free_blocks() const { return at<178>().as_bytes(); }
+ bool has_ext4_free_inode() const { return at<179>().valid(); }
+ ::protozero::ConstBytes ext4_free_inode() const { return at<179>().as_bytes(); }
+ bool has_ext4_get_implied_cluster_alloc_exit() const { return at<180>().valid(); }
+ ::protozero::ConstBytes ext4_get_implied_cluster_alloc_exit() const { return at<180>().as_bytes(); }
+ bool has_ext4_get_reserved_cluster_alloc() const { return at<181>().valid(); }
+ ::protozero::ConstBytes ext4_get_reserved_cluster_alloc() const { return at<181>().as_bytes(); }
+ bool has_ext4_ind_map_blocks_enter() const { return at<182>().valid(); }
+ ::protozero::ConstBytes ext4_ind_map_blocks_enter() const { return at<182>().as_bytes(); }
+ bool has_ext4_ind_map_blocks_exit() const { return at<183>().valid(); }
+ ::protozero::ConstBytes ext4_ind_map_blocks_exit() const { return at<183>().as_bytes(); }
+ bool has_ext4_insert_range() const { return at<184>().valid(); }
+ ::protozero::ConstBytes ext4_insert_range() const { return at<184>().as_bytes(); }
+ bool has_ext4_invalidatepage() const { return at<185>().valid(); }
+ ::protozero::ConstBytes ext4_invalidatepage() const { return at<185>().as_bytes(); }
+ bool has_ext4_journal_start() const { return at<186>().valid(); }
+ ::protozero::ConstBytes ext4_journal_start() const { return at<186>().as_bytes(); }
+ bool has_ext4_journal_start_reserved() const { return at<187>().valid(); }
+ ::protozero::ConstBytes ext4_journal_start_reserved() const { return at<187>().as_bytes(); }
+ bool has_ext4_journalled_invalidatepage() const { return at<188>().valid(); }
+ ::protozero::ConstBytes ext4_journalled_invalidatepage() const { return at<188>().as_bytes(); }
+ bool has_ext4_journalled_write_end() const { return at<189>().valid(); }
+ ::protozero::ConstBytes ext4_journalled_write_end() const { return at<189>().as_bytes(); }
+ bool has_ext4_load_inode() const { return at<190>().valid(); }
+ ::protozero::ConstBytes ext4_load_inode() const { return at<190>().as_bytes(); }
+ bool has_ext4_load_inode_bitmap() const { return at<191>().valid(); }
+ ::protozero::ConstBytes ext4_load_inode_bitmap() const { return at<191>().as_bytes(); }
+ bool has_ext4_mark_inode_dirty() const { return at<192>().valid(); }
+ ::protozero::ConstBytes ext4_mark_inode_dirty() const { return at<192>().as_bytes(); }
+ bool has_ext4_mb_bitmap_load() const { return at<193>().valid(); }
+ ::protozero::ConstBytes ext4_mb_bitmap_load() const { return at<193>().as_bytes(); }
+ bool has_ext4_mb_buddy_bitmap_load() const { return at<194>().valid(); }
+ ::protozero::ConstBytes ext4_mb_buddy_bitmap_load() const { return at<194>().as_bytes(); }
+ bool has_ext4_mb_discard_preallocations() const { return at<195>().valid(); }
+ ::protozero::ConstBytes ext4_mb_discard_preallocations() const { return at<195>().as_bytes(); }
+ bool has_ext4_mb_new_group_pa() const { return at<196>().valid(); }
+ ::protozero::ConstBytes ext4_mb_new_group_pa() const { return at<196>().as_bytes(); }
+ bool has_ext4_mb_new_inode_pa() const { return at<197>().valid(); }
+ ::protozero::ConstBytes ext4_mb_new_inode_pa() const { return at<197>().as_bytes(); }
+ bool has_ext4_mb_release_group_pa() const { return at<198>().valid(); }
+ ::protozero::ConstBytes ext4_mb_release_group_pa() const { return at<198>().as_bytes(); }
+ bool has_ext4_mb_release_inode_pa() const { return at<199>().valid(); }
+ ::protozero::ConstBytes ext4_mb_release_inode_pa() const { return at<199>().as_bytes(); }
+ bool has_ext4_mballoc_alloc() const { return at<200>().valid(); }
+ ::protozero::ConstBytes ext4_mballoc_alloc() const { return at<200>().as_bytes(); }
+ bool has_ext4_mballoc_discard() const { return at<201>().valid(); }
+ ::protozero::ConstBytes ext4_mballoc_discard() const { return at<201>().as_bytes(); }
+ bool has_ext4_mballoc_free() const { return at<202>().valid(); }
+ ::protozero::ConstBytes ext4_mballoc_free() const { return at<202>().as_bytes(); }
+ bool has_ext4_mballoc_prealloc() const { return at<203>().valid(); }
+ ::protozero::ConstBytes ext4_mballoc_prealloc() const { return at<203>().as_bytes(); }
+ bool has_ext4_other_inode_update_time() const { return at<204>().valid(); }
+ ::protozero::ConstBytes ext4_other_inode_update_time() const { return at<204>().as_bytes(); }
+ bool has_ext4_punch_hole() const { return at<205>().valid(); }
+ ::protozero::ConstBytes ext4_punch_hole() const { return at<205>().as_bytes(); }
+ bool has_ext4_read_block_bitmap_load() const { return at<206>().valid(); }
+ ::protozero::ConstBytes ext4_read_block_bitmap_load() const { return at<206>().as_bytes(); }
+ bool has_ext4_readpage() const { return at<207>().valid(); }
+ ::protozero::ConstBytes ext4_readpage() const { return at<207>().as_bytes(); }
+ bool has_ext4_releasepage() const { return at<208>().valid(); }
+ ::protozero::ConstBytes ext4_releasepage() const { return at<208>().as_bytes(); }
+ bool has_ext4_remove_blocks() const { return at<209>().valid(); }
+ ::protozero::ConstBytes ext4_remove_blocks() const { return at<209>().as_bytes(); }
+ bool has_ext4_request_blocks() const { return at<210>().valid(); }
+ ::protozero::ConstBytes ext4_request_blocks() const { return at<210>().as_bytes(); }
+ bool has_ext4_request_inode() const { return at<211>().valid(); }
+ ::protozero::ConstBytes ext4_request_inode() const { return at<211>().as_bytes(); }
+ bool has_ext4_sync_fs() const { return at<212>().valid(); }
+ ::protozero::ConstBytes ext4_sync_fs() const { return at<212>().as_bytes(); }
+ bool has_ext4_trim_all_free() const { return at<213>().valid(); }
+ ::protozero::ConstBytes ext4_trim_all_free() const { return at<213>().as_bytes(); }
+ bool has_ext4_trim_extent() const { return at<214>().valid(); }
+ ::protozero::ConstBytes ext4_trim_extent() const { return at<214>().as_bytes(); }
+ bool has_ext4_truncate_enter() const { return at<215>().valid(); }
+ ::protozero::ConstBytes ext4_truncate_enter() const { return at<215>().as_bytes(); }
+ bool has_ext4_truncate_exit() const { return at<216>().valid(); }
+ ::protozero::ConstBytes ext4_truncate_exit() const { return at<216>().as_bytes(); }
+ bool has_ext4_unlink_enter() const { return at<217>().valid(); }
+ ::protozero::ConstBytes ext4_unlink_enter() const { return at<217>().as_bytes(); }
+ bool has_ext4_unlink_exit() const { return at<218>().valid(); }
+ ::protozero::ConstBytes ext4_unlink_exit() const { return at<218>().as_bytes(); }
+ bool has_ext4_write_begin() const { return at<219>().valid(); }
+ ::protozero::ConstBytes ext4_write_begin() const { return at<219>().as_bytes(); }
+ bool has_ext4_write_end() const { return at<230>().valid(); }
+ ::protozero::ConstBytes ext4_write_end() const { return at<230>().as_bytes(); }
+ bool has_ext4_writepage() const { return at<231>().valid(); }
+ ::protozero::ConstBytes ext4_writepage() const { return at<231>().as_bytes(); }
+ bool has_ext4_writepages() const { return at<232>().valid(); }
+ ::protozero::ConstBytes ext4_writepages() const { return at<232>().as_bytes(); }
+ bool has_ext4_writepages_result() const { return at<233>().valid(); }
+ ::protozero::ConstBytes ext4_writepages_result() const { return at<233>().as_bytes(); }
+ bool has_ext4_zero_range() const { return at<234>().valid(); }
+ ::protozero::ConstBytes ext4_zero_range() const { return at<234>().as_bytes(); }
+ bool has_task_newtask() const { return at<235>().valid(); }
+ ::protozero::ConstBytes task_newtask() const { return at<235>().as_bytes(); }
+ bool has_task_rename() const { return at<236>().valid(); }
+ ::protozero::ConstBytes task_rename() const { return at<236>().as_bytes(); }
+ bool has_sched_process_exec() const { return at<237>().valid(); }
+ ::protozero::ConstBytes sched_process_exec() const { return at<237>().as_bytes(); }
+ bool has_sched_process_exit() const { return at<238>().valid(); }
+ ::protozero::ConstBytes sched_process_exit() const { return at<238>().as_bytes(); }
+ bool has_sched_process_fork() const { return at<239>().valid(); }
+ ::protozero::ConstBytes sched_process_fork() const { return at<239>().as_bytes(); }
+ bool has_sched_process_free() const { return at<240>().valid(); }
+ ::protozero::ConstBytes sched_process_free() const { return at<240>().as_bytes(); }
+ bool has_sched_process_hang() const { return at<241>().valid(); }
+ ::protozero::ConstBytes sched_process_hang() const { return at<241>().as_bytes(); }
+ bool has_sched_process_wait() const { return at<242>().valid(); }
+ ::protozero::ConstBytes sched_process_wait() const { return at<242>().as_bytes(); }
+ bool has_f2fs_do_submit_bio() const { return at<243>().valid(); }
+ ::protozero::ConstBytes f2fs_do_submit_bio() const { return at<243>().as_bytes(); }
+ bool has_f2fs_evict_inode() const { return at<244>().valid(); }
+ ::protozero::ConstBytes f2fs_evict_inode() const { return at<244>().as_bytes(); }
+ bool has_f2fs_fallocate() const { return at<245>().valid(); }
+ ::protozero::ConstBytes f2fs_fallocate() const { return at<245>().as_bytes(); }
+ bool has_f2fs_get_data_block() const { return at<246>().valid(); }
+ ::protozero::ConstBytes f2fs_get_data_block() const { return at<246>().as_bytes(); }
+ bool has_f2fs_get_victim() const { return at<247>().valid(); }
+ ::protozero::ConstBytes f2fs_get_victim() const { return at<247>().as_bytes(); }
+ bool has_f2fs_iget() const { return at<248>().valid(); }
+ ::protozero::ConstBytes f2fs_iget() const { return at<248>().as_bytes(); }
+ bool has_f2fs_iget_exit() const { return at<249>().valid(); }
+ ::protozero::ConstBytes f2fs_iget_exit() const { return at<249>().as_bytes(); }
+ bool has_f2fs_new_inode() const { return at<250>().valid(); }
+ ::protozero::ConstBytes f2fs_new_inode() const { return at<250>().as_bytes(); }
+ bool has_f2fs_readpage() const { return at<251>().valid(); }
+ ::protozero::ConstBytes f2fs_readpage() const { return at<251>().as_bytes(); }
+ bool has_f2fs_reserve_new_block() const { return at<252>().valid(); }
+ ::protozero::ConstBytes f2fs_reserve_new_block() const { return at<252>().as_bytes(); }
+ bool has_f2fs_set_page_dirty() const { return at<253>().valid(); }
+ ::protozero::ConstBytes f2fs_set_page_dirty() const { return at<253>().as_bytes(); }
+ bool has_f2fs_submit_write_page() const { return at<254>().valid(); }
+ ::protozero::ConstBytes f2fs_submit_write_page() const { return at<254>().as_bytes(); }
+ bool has_f2fs_sync_file_enter() const { return at<255>().valid(); }
+ ::protozero::ConstBytes f2fs_sync_file_enter() const { return at<255>().as_bytes(); }
+ bool has_f2fs_sync_file_exit() const { return at<256>().valid(); }
+ ::protozero::ConstBytes f2fs_sync_file_exit() const { return at<256>().as_bytes(); }
+ bool has_f2fs_sync_fs() const { return at<257>().valid(); }
+ ::protozero::ConstBytes f2fs_sync_fs() const { return at<257>().as_bytes(); }
+ bool has_f2fs_truncate() const { return at<258>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate() const { return at<258>().as_bytes(); }
+ bool has_f2fs_truncate_blocks_enter() const { return at<259>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_blocks_enter() const { return at<259>().as_bytes(); }
+ bool has_f2fs_truncate_blocks_exit() const { return at<260>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_blocks_exit() const { return at<260>().as_bytes(); }
+ bool has_f2fs_truncate_data_blocks_range() const { return at<261>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_data_blocks_range() const { return at<261>().as_bytes(); }
+ bool has_f2fs_truncate_inode_blocks_enter() const { return at<262>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_inode_blocks_enter() const { return at<262>().as_bytes(); }
+ bool has_f2fs_truncate_inode_blocks_exit() const { return at<263>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_inode_blocks_exit() const { return at<263>().as_bytes(); }
+ bool has_f2fs_truncate_node() const { return at<264>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_node() const { return at<264>().as_bytes(); }
+ bool has_f2fs_truncate_nodes_enter() const { return at<265>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_nodes_enter() const { return at<265>().as_bytes(); }
+ bool has_f2fs_truncate_nodes_exit() const { return at<266>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_nodes_exit() const { return at<266>().as_bytes(); }
+ bool has_f2fs_truncate_partial_nodes() const { return at<267>().valid(); }
+ ::protozero::ConstBytes f2fs_truncate_partial_nodes() const { return at<267>().as_bytes(); }
+ bool has_f2fs_unlink_enter() const { return at<268>().valid(); }
+ ::protozero::ConstBytes f2fs_unlink_enter() const { return at<268>().as_bytes(); }
+ bool has_f2fs_unlink_exit() const { return at<269>().valid(); }
+ ::protozero::ConstBytes f2fs_unlink_exit() const { return at<269>().as_bytes(); }
+ bool has_f2fs_vm_page_mkwrite() const { return at<270>().valid(); }
+ ::protozero::ConstBytes f2fs_vm_page_mkwrite() const { return at<270>().as_bytes(); }
+ bool has_f2fs_write_begin() const { return at<271>().valid(); }
+ ::protozero::ConstBytes f2fs_write_begin() const { return at<271>().as_bytes(); }
+ bool has_f2fs_write_checkpoint() const { return at<272>().valid(); }
+ ::protozero::ConstBytes f2fs_write_checkpoint() const { return at<272>().as_bytes(); }
+ bool has_f2fs_write_end() const { return at<273>().valid(); }
+ ::protozero::ConstBytes f2fs_write_end() const { return at<273>().as_bytes(); }
+ bool has_alloc_pages_iommu_end() const { return at<274>().valid(); }
+ ::protozero::ConstBytes alloc_pages_iommu_end() const { return at<274>().as_bytes(); }
+ bool has_alloc_pages_iommu_fail() const { return at<275>().valid(); }
+ ::protozero::ConstBytes alloc_pages_iommu_fail() const { return at<275>().as_bytes(); }
+ bool has_alloc_pages_iommu_start() const { return at<276>().valid(); }
+ ::protozero::ConstBytes alloc_pages_iommu_start() const { return at<276>().as_bytes(); }
+ bool has_alloc_pages_sys_end() const { return at<277>().valid(); }
+ ::protozero::ConstBytes alloc_pages_sys_end() const { return at<277>().as_bytes(); }
+ bool has_alloc_pages_sys_fail() const { return at<278>().valid(); }
+ ::protozero::ConstBytes alloc_pages_sys_fail() const { return at<278>().as_bytes(); }
+ bool has_alloc_pages_sys_start() const { return at<279>().valid(); }
+ ::protozero::ConstBytes alloc_pages_sys_start() const { return at<279>().as_bytes(); }
+ bool has_dma_alloc_contiguous_retry() const { return at<280>().valid(); }
+ ::protozero::ConstBytes dma_alloc_contiguous_retry() const { return at<280>().as_bytes(); }
+ bool has_iommu_map_range() const { return at<281>().valid(); }
+ ::protozero::ConstBytes iommu_map_range() const { return at<281>().as_bytes(); }
+ bool has_iommu_sec_ptbl_map_range_end() const { return at<282>().valid(); }
+ ::protozero::ConstBytes iommu_sec_ptbl_map_range_end() const { return at<282>().as_bytes(); }
+ bool has_iommu_sec_ptbl_map_range_start() const { return at<283>().valid(); }
+ ::protozero::ConstBytes iommu_sec_ptbl_map_range_start() const { return at<283>().as_bytes(); }
+ bool has_ion_alloc_buffer_end() const { return at<284>().valid(); }
+ ::protozero::ConstBytes ion_alloc_buffer_end() const { return at<284>().as_bytes(); }
+ bool has_ion_alloc_buffer_fail() const { return at<285>().valid(); }
+ ::protozero::ConstBytes ion_alloc_buffer_fail() const { return at<285>().as_bytes(); }
+ bool has_ion_alloc_buffer_fallback() const { return at<286>().valid(); }
+ ::protozero::ConstBytes ion_alloc_buffer_fallback() const { return at<286>().as_bytes(); }
+ bool has_ion_alloc_buffer_start() const { return at<287>().valid(); }
+ ::protozero::ConstBytes ion_alloc_buffer_start() const { return at<287>().as_bytes(); }
+ bool has_ion_cp_alloc_retry() const { return at<288>().valid(); }
+ ::protozero::ConstBytes ion_cp_alloc_retry() const { return at<288>().as_bytes(); }
+ bool has_ion_cp_secure_buffer_end() const { return at<289>().valid(); }
+ ::protozero::ConstBytes ion_cp_secure_buffer_end() const { return at<289>().as_bytes(); }
+ bool has_ion_cp_secure_buffer_start() const { return at<290>().valid(); }
+ ::protozero::ConstBytes ion_cp_secure_buffer_start() const { return at<290>().as_bytes(); }
+ bool has_ion_prefetching() const { return at<291>().valid(); }
+ ::protozero::ConstBytes ion_prefetching() const { return at<291>().as_bytes(); }
+ bool has_ion_secure_cma_add_to_pool_end() const { return at<292>().valid(); }
+ ::protozero::ConstBytes ion_secure_cma_add_to_pool_end() const { return at<292>().as_bytes(); }
+ bool has_ion_secure_cma_add_to_pool_start() const { return at<293>().valid(); }
+ ::protozero::ConstBytes ion_secure_cma_add_to_pool_start() const { return at<293>().as_bytes(); }
+ bool has_ion_secure_cma_allocate_end() const { return at<294>().valid(); }
+ ::protozero::ConstBytes ion_secure_cma_allocate_end() const { return at<294>().as_bytes(); }
+ bool has_ion_secure_cma_allocate_start() const { return at<295>().valid(); }
+ ::protozero::ConstBytes ion_secure_cma_allocate_start() const { return at<295>().as_bytes(); }
+ bool has_ion_secure_cma_shrink_pool_end() const { return at<296>().valid(); }
+ ::protozero::ConstBytes ion_secure_cma_shrink_pool_end() const { return at<296>().as_bytes(); }
+ bool has_ion_secure_cma_shrink_pool_start() const { return at<297>().valid(); }
+ ::protozero::ConstBytes ion_secure_cma_shrink_pool_start() const { return at<297>().as_bytes(); }
+ bool has_kfree() const { return at<298>().valid(); }
+ ::protozero::ConstBytes kfree() const { return at<298>().as_bytes(); }
+ bool has_kmalloc() const { return at<299>().valid(); }
+ ::protozero::ConstBytes kmalloc() const { return at<299>().as_bytes(); }
+ bool has_kmalloc_node() const { return at<300>().valid(); }
+ ::protozero::ConstBytes kmalloc_node() const { return at<300>().as_bytes(); }
+ bool has_kmem_cache_alloc() const { return at<301>().valid(); }
+ ::protozero::ConstBytes kmem_cache_alloc() const { return at<301>().as_bytes(); }
+ bool has_kmem_cache_alloc_node() const { return at<302>().valid(); }
+ ::protozero::ConstBytes kmem_cache_alloc_node() const { return at<302>().as_bytes(); }
+ bool has_kmem_cache_free() const { return at<303>().valid(); }
+ ::protozero::ConstBytes kmem_cache_free() const { return at<303>().as_bytes(); }
+ bool has_migrate_pages_end() const { return at<304>().valid(); }
+ ::protozero::ConstBytes migrate_pages_end() const { return at<304>().as_bytes(); }
+ bool has_migrate_pages_start() const { return at<305>().valid(); }
+ ::protozero::ConstBytes migrate_pages_start() const { return at<305>().as_bytes(); }
+ bool has_migrate_retry() const { return at<306>().valid(); }
+ ::protozero::ConstBytes migrate_retry() const { return at<306>().as_bytes(); }
+ bool has_mm_page_alloc() const { return at<307>().valid(); }
+ ::protozero::ConstBytes mm_page_alloc() const { return at<307>().as_bytes(); }
+ bool has_mm_page_alloc_extfrag() const { return at<308>().valid(); }
+ ::protozero::ConstBytes mm_page_alloc_extfrag() const { return at<308>().as_bytes(); }
+ bool has_mm_page_alloc_zone_locked() const { return at<309>().valid(); }
+ ::protozero::ConstBytes mm_page_alloc_zone_locked() const { return at<309>().as_bytes(); }
+ bool has_mm_page_free() const { return at<310>().valid(); }
+ ::protozero::ConstBytes mm_page_free() const { return at<310>().as_bytes(); }
+ bool has_mm_page_free_batched() const { return at<311>().valid(); }
+ ::protozero::ConstBytes mm_page_free_batched() const { return at<311>().as_bytes(); }
+ bool has_mm_page_pcpu_drain() const { return at<312>().valid(); }
+ ::protozero::ConstBytes mm_page_pcpu_drain() const { return at<312>().as_bytes(); }
+ bool has_rss_stat() const { return at<313>().valid(); }
+ ::protozero::ConstBytes rss_stat() const { return at<313>().as_bytes(); }
+ bool has_ion_heap_shrink() const { return at<314>().valid(); }
+ ::protozero::ConstBytes ion_heap_shrink() const { return at<314>().as_bytes(); }
+ bool has_ion_heap_grow() const { return at<315>().valid(); }
+ ::protozero::ConstBytes ion_heap_grow() const { return at<315>().as_bytes(); }
+ bool has_fence_init() const { return at<316>().valid(); }
+ ::protozero::ConstBytes fence_init() const { return at<316>().as_bytes(); }
+ bool has_fence_destroy() const { return at<317>().valid(); }
+ ::protozero::ConstBytes fence_destroy() const { return at<317>().as_bytes(); }
+ bool has_fence_enable_signal() const { return at<318>().valid(); }
+ ::protozero::ConstBytes fence_enable_signal() const { return at<318>().as_bytes(); }
+ bool has_fence_signaled() const { return at<319>().valid(); }
+ ::protozero::ConstBytes fence_signaled() const { return at<319>().as_bytes(); }
+ bool has_clk_enable() const { return at<320>().valid(); }
+ ::protozero::ConstBytes clk_enable() const { return at<320>().as_bytes(); }
+ bool has_clk_disable() const { return at<321>().valid(); }
+ ::protozero::ConstBytes clk_disable() const { return at<321>().as_bytes(); }
+ bool has_clk_set_rate() const { return at<322>().valid(); }
+ ::protozero::ConstBytes clk_set_rate() const { return at<322>().as_bytes(); }
+ bool has_binder_transaction_alloc_buf() const { return at<323>().valid(); }
+ ::protozero::ConstBytes binder_transaction_alloc_buf() const { return at<323>().as_bytes(); }
+ bool has_signal_deliver() const { return at<324>().valid(); }
+ ::protozero::ConstBytes signal_deliver() const { return at<324>().as_bytes(); }
+ bool has_signal_generate() const { return at<325>().valid(); }
+ ::protozero::ConstBytes signal_generate() const { return at<325>().as_bytes(); }
+ bool has_oom_score_adj_update() const { return at<326>().valid(); }
+ ::protozero::ConstBytes oom_score_adj_update() const { return at<326>().as_bytes(); }
+ bool has_generic() const { return at<327>().valid(); }
+ ::protozero::ConstBytes generic() const { return at<327>().as_bytes(); }
+ bool has_mm_event_record() const { return at<328>().valid(); }
+ ::protozero::ConstBytes mm_event_record() const { return at<328>().as_bytes(); }
+ bool has_sys_enter() const { return at<329>().valid(); }
+ ::protozero::ConstBytes sys_enter() const { return at<329>().as_bytes(); }
+ bool has_sys_exit() const { return at<330>().valid(); }
+ ::protozero::ConstBytes sys_exit() const { return at<330>().as_bytes(); }
+ bool has_zero() const { return at<331>().valid(); }
+ ::protozero::ConstBytes zero() const { return at<331>().as_bytes(); }
+ bool has_gpu_frequency() const { return at<332>().valid(); }
+ ::protozero::ConstBytes gpu_frequency() const { return at<332>().as_bytes(); }
+ bool has_sde_tracing_mark_write() const { return at<333>().valid(); }
+ ::protozero::ConstBytes sde_tracing_mark_write() const { return at<333>().as_bytes(); }
+ bool has_mark_victim() const { return at<334>().valid(); }
+ ::protozero::ConstBytes mark_victim() const { return at<334>().as_bytes(); }
+ bool has_ion_stat() const { return at<335>().valid(); }
+ ::protozero::ConstBytes ion_stat() const { return at<335>().as_bytes(); }
+ bool has_ion_buffer_create() const { return at<336>().valid(); }
+ ::protozero::ConstBytes ion_buffer_create() const { return at<336>().as_bytes(); }
+ bool has_ion_buffer_destroy() const { return at<337>().valid(); }
+ ::protozero::ConstBytes ion_buffer_destroy() const { return at<337>().as_bytes(); }
+ bool has_scm_call_start() const { return at<338>().valid(); }
+ ::protozero::ConstBytes scm_call_start() const { return at<338>().as_bytes(); }
+ bool has_scm_call_end() const { return at<339>().valid(); }
+ ::protozero::ConstBytes scm_call_end() const { return at<339>().as_bytes(); }
+ bool has_gpu_mem_total() const { return at<340>().valid(); }
+ ::protozero::ConstBytes gpu_mem_total() const { return at<340>().as_bytes(); }
+ bool has_thermal_temperature() const { return at<341>().valid(); }
+ ::protozero::ConstBytes thermal_temperature() const { return at<341>().as_bytes(); }
+ bool has_cdev_update() const { return at<342>().valid(); }
+ ::protozero::ConstBytes cdev_update() const { return at<342>().as_bytes(); }
+ bool has_cpuhp_exit() const { return at<343>().valid(); }
+ ::protozero::ConstBytes cpuhp_exit() const { return at<343>().as_bytes(); }
+ bool has_cpuhp_multi_enter() const { return at<344>().valid(); }
+ ::protozero::ConstBytes cpuhp_multi_enter() const { return at<344>().as_bytes(); }
+ bool has_cpuhp_enter() const { return at<345>().valid(); }
+ ::protozero::ConstBytes cpuhp_enter() const { return at<345>().as_bytes(); }
+ bool has_cpuhp_latency() const { return at<346>().valid(); }
+ ::protozero::ConstBytes cpuhp_latency() const { return at<346>().as_bytes(); }
+ bool has_fastrpc_dma_stat() const { return at<347>().valid(); }
+ ::protozero::ConstBytes fastrpc_dma_stat() const { return at<347>().as_bytes(); }
+ bool has_dpu_tracing_mark_write() const { return at<348>().valid(); }
+ ::protozero::ConstBytes dpu_tracing_mark_write() const { return at<348>().as_bytes(); }
+ bool has_g2d_tracing_mark_write() const { return at<349>().valid(); }
+ ::protozero::ConstBytes g2d_tracing_mark_write() const { return at<349>().as_bytes(); }
+ bool has_mali_tracing_mark_write() const { return at<350>().valid(); }
+ ::protozero::ConstBytes mali_tracing_mark_write() const { return at<350>().as_bytes(); }
+ bool has_dma_heap_stat() const { return at<351>().valid(); }
+ ::protozero::ConstBytes dma_heap_stat() const { return at<351>().as_bytes(); }
+ bool has_cpuhp_pause() const { return at<352>().valid(); }
+ ::protozero::ConstBytes cpuhp_pause() const { return at<352>().as_bytes(); }
+ bool has_sched_pi_setprio() const { return at<353>().valid(); }
+ ::protozero::ConstBytes sched_pi_setprio() const { return at<353>().as_bytes(); }
+ bool has_sde_sde_evtlog() const { return at<354>().valid(); }
+ ::protozero::ConstBytes sde_sde_evtlog() const { return at<354>().as_bytes(); }
+ bool has_sde_sde_perf_calc_crtc() const { return at<355>().valid(); }
+ ::protozero::ConstBytes sde_sde_perf_calc_crtc() const { return at<355>().as_bytes(); }
+ bool has_sde_sde_perf_crtc_update() const { return at<356>().valid(); }
+ ::protozero::ConstBytes sde_sde_perf_crtc_update() const { return at<356>().as_bytes(); }
+ bool has_sde_sde_perf_set_qos_luts() const { return at<357>().valid(); }
+ ::protozero::ConstBytes sde_sde_perf_set_qos_luts() const { return at<357>().as_bytes(); }
+ bool has_sde_sde_perf_update_bus() const { return at<358>().valid(); }
+ ::protozero::ConstBytes sde_sde_perf_update_bus() const { return at<358>().as_bytes(); }
+ bool has_rss_stat_throttled() const { return at<359>().valid(); }
+ ::protozero::ConstBytes rss_stat_throttled() const { return at<359>().as_bytes(); }
+ bool has_netif_receive_skb() const { return at<360>().valid(); }
+ ::protozero::ConstBytes netif_receive_skb() const { return at<360>().as_bytes(); }
+ bool has_net_dev_xmit() const { return at<361>().valid(); }
+ ::protozero::ConstBytes net_dev_xmit() const { return at<361>().as_bytes(); }
+ bool has_inet_sock_set_state() const { return at<362>().valid(); }
+ ::protozero::ConstBytes inet_sock_set_state() const { return at<362>().as_bytes(); }
+ bool has_tcp_retransmit_skb() const { return at<363>().valid(); }
+ ::protozero::ConstBytes tcp_retransmit_skb() const { return at<363>().as_bytes(); }
+ bool has_cros_ec_sensorhub_data() const { return at<364>().valid(); }
+ ::protozero::ConstBytes cros_ec_sensorhub_data() const { return at<364>().as_bytes(); }
+ bool has_napi_gro_receive_entry() const { return at<365>().valid(); }
+ ::protozero::ConstBytes napi_gro_receive_entry() const { return at<365>().as_bytes(); }
+ bool has_napi_gro_receive_exit() const { return at<366>().valid(); }
+ ::protozero::ConstBytes napi_gro_receive_exit() const { return at<366>().as_bytes(); }
+ bool has_kfree_skb() const { return at<367>().valid(); }
+ ::protozero::ConstBytes kfree_skb() const { return at<367>().as_bytes(); }
+ bool has_kvm_access_fault() const { return at<368>().valid(); }
+ ::protozero::ConstBytes kvm_access_fault() const { return at<368>().as_bytes(); }
+ bool has_kvm_ack_irq() const { return at<369>().valid(); }
+ ::protozero::ConstBytes kvm_ack_irq() const { return at<369>().as_bytes(); }
+ bool has_kvm_age_hva() const { return at<370>().valid(); }
+ ::protozero::ConstBytes kvm_age_hva() const { return at<370>().as_bytes(); }
+ bool has_kvm_age_page() const { return at<371>().valid(); }
+ ::protozero::ConstBytes kvm_age_page() const { return at<371>().as_bytes(); }
+ bool has_kvm_arm_clear_debug() const { return at<372>().valid(); }
+ ::protozero::ConstBytes kvm_arm_clear_debug() const { return at<372>().as_bytes(); }
+ bool has_kvm_arm_set_dreg32() const { return at<373>().valid(); }
+ ::protozero::ConstBytes kvm_arm_set_dreg32() const { return at<373>().as_bytes(); }
+ bool has_kvm_arm_set_regset() const { return at<374>().valid(); }
+ ::protozero::ConstBytes kvm_arm_set_regset() const { return at<374>().as_bytes(); }
+ bool has_kvm_arm_setup_debug() const { return at<375>().valid(); }
+ ::protozero::ConstBytes kvm_arm_setup_debug() const { return at<375>().as_bytes(); }
+ bool has_kvm_entry() const { return at<376>().valid(); }
+ ::protozero::ConstBytes kvm_entry() const { return at<376>().as_bytes(); }
+ bool has_kvm_exit() const { return at<377>().valid(); }
+ ::protozero::ConstBytes kvm_exit() const { return at<377>().as_bytes(); }
+ bool has_kvm_fpu() const { return at<378>().valid(); }
+ ::protozero::ConstBytes kvm_fpu() const { return at<378>().as_bytes(); }
+ bool has_kvm_get_timer_map() const { return at<379>().valid(); }
+ ::protozero::ConstBytes kvm_get_timer_map() const { return at<379>().as_bytes(); }
+ bool has_kvm_guest_fault() const { return at<380>().valid(); }
+ ::protozero::ConstBytes kvm_guest_fault() const { return at<380>().as_bytes(); }
+ bool has_kvm_handle_sys_reg() const { return at<381>().valid(); }
+ ::protozero::ConstBytes kvm_handle_sys_reg() const { return at<381>().as_bytes(); }
+ bool has_kvm_hvc_arm64() const { return at<382>().valid(); }
+ ::protozero::ConstBytes kvm_hvc_arm64() const { return at<382>().as_bytes(); }
+ bool has_kvm_irq_line() const { return at<383>().valid(); }
+ ::protozero::ConstBytes kvm_irq_line() const { return at<383>().as_bytes(); }
+ bool has_kvm_mmio() const { return at<384>().valid(); }
+ ::protozero::ConstBytes kvm_mmio() const { return at<384>().as_bytes(); }
+ bool has_kvm_mmio_emulate() const { return at<385>().valid(); }
+ ::protozero::ConstBytes kvm_mmio_emulate() const { return at<385>().as_bytes(); }
+ bool has_kvm_set_guest_debug() const { return at<386>().valid(); }
+ ::protozero::ConstBytes kvm_set_guest_debug() const { return at<386>().as_bytes(); }
+ bool has_kvm_set_irq() const { return at<387>().valid(); }
+ ::protozero::ConstBytes kvm_set_irq() const { return at<387>().as_bytes(); }
+ bool has_kvm_set_spte_hva() const { return at<388>().valid(); }
+ ::protozero::ConstBytes kvm_set_spte_hva() const { return at<388>().as_bytes(); }
+ bool has_kvm_set_way_flush() const { return at<389>().valid(); }
+ ::protozero::ConstBytes kvm_set_way_flush() const { return at<389>().as_bytes(); }
+ bool has_kvm_sys_access() const { return at<390>().valid(); }
+ ::protozero::ConstBytes kvm_sys_access() const { return at<390>().as_bytes(); }
+ bool has_kvm_test_age_hva() const { return at<391>().valid(); }
+ ::protozero::ConstBytes kvm_test_age_hva() const { return at<391>().as_bytes(); }
+ bool has_kvm_timer_emulate() const { return at<392>().valid(); }
+ ::protozero::ConstBytes kvm_timer_emulate() const { return at<392>().as_bytes(); }
+ bool has_kvm_timer_hrtimer_expire() const { return at<393>().valid(); }
+ ::protozero::ConstBytes kvm_timer_hrtimer_expire() const { return at<393>().as_bytes(); }
+ bool has_kvm_timer_restore_state() const { return at<394>().valid(); }
+ ::protozero::ConstBytes kvm_timer_restore_state() const { return at<394>().as_bytes(); }
+ bool has_kvm_timer_save_state() const { return at<395>().valid(); }
+ ::protozero::ConstBytes kvm_timer_save_state() const { return at<395>().as_bytes(); }
+ bool has_kvm_timer_update_irq() const { return at<396>().valid(); }
+ ::protozero::ConstBytes kvm_timer_update_irq() const { return at<396>().as_bytes(); }
+ bool has_kvm_toggle_cache() const { return at<397>().valid(); }
+ ::protozero::ConstBytes kvm_toggle_cache() const { return at<397>().as_bytes(); }
+ bool has_kvm_unmap_hva_range() const { return at<398>().valid(); }
+ ::protozero::ConstBytes kvm_unmap_hva_range() const { return at<398>().as_bytes(); }
+ bool has_kvm_userspace_exit() const { return at<399>().valid(); }
+ ::protozero::ConstBytes kvm_userspace_exit() const { return at<399>().as_bytes(); }
+ bool has_kvm_vcpu_wakeup() const { return at<400>().valid(); }
+ ::protozero::ConstBytes kvm_vcpu_wakeup() const { return at<400>().as_bytes(); }
+ bool has_kvm_wfx_arm64() const { return at<401>().valid(); }
+ ::protozero::ConstBytes kvm_wfx_arm64() const { return at<401>().as_bytes(); }
+ bool has_trap_reg() const { return at<402>().valid(); }
+ ::protozero::ConstBytes trap_reg() const { return at<402>().as_bytes(); }
+ bool has_vgic_update_irq_pending() const { return at<403>().valid(); }
+ ::protozero::ConstBytes vgic_update_irq_pending() const { return at<403>().as_bytes(); }
+ bool has_wakeup_source_activate() const { return at<404>().valid(); }
+ ::protozero::ConstBytes wakeup_source_activate() const { return at<404>().as_bytes(); }
+ bool has_wakeup_source_deactivate() const { return at<405>().valid(); }
+ ::protozero::ConstBytes wakeup_source_deactivate() const { return at<405>().as_bytes(); }
+ bool has_ufshcd_command() const { return at<406>().valid(); }
+ ::protozero::ConstBytes ufshcd_command() const { return at<406>().as_bytes(); }
+ bool has_ufshcd_clk_gating() const { return at<407>().valid(); }
+ ::protozero::ConstBytes ufshcd_clk_gating() const { return at<407>().as_bytes(); }
+ bool has_console() const { return at<408>().valid(); }
+ ::protozero::ConstBytes console() const { return at<408>().as_bytes(); }
+ bool has_drm_vblank_event() const { return at<409>().valid(); }
+ ::protozero::ConstBytes drm_vblank_event() const { return at<409>().as_bytes(); }
+ bool has_drm_vblank_event_delivered() const { return at<410>().valid(); }
+ ::protozero::ConstBytes drm_vblank_event_delivered() const { return at<410>().as_bytes(); }
+ bool has_drm_sched_job() const { return at<411>().valid(); }
+ ::protozero::ConstBytes drm_sched_job() const { return at<411>().as_bytes(); }
+ bool has_drm_run_job() const { return at<412>().valid(); }
+ ::protozero::ConstBytes drm_run_job() const { return at<412>().as_bytes(); }
+ bool has_drm_sched_process_job() const { return at<413>().valid(); }
+ ::protozero::ConstBytes drm_sched_process_job() const { return at<413>().as_bytes(); }
+ bool has_dma_fence_init() const { return at<414>().valid(); }
+ ::protozero::ConstBytes dma_fence_init() const { return at<414>().as_bytes(); }
+ bool has_dma_fence_emit() const { return at<415>().valid(); }
+ ::protozero::ConstBytes dma_fence_emit() const { return at<415>().as_bytes(); }
+ bool has_dma_fence_signaled() const { return at<416>().valid(); }
+ ::protozero::ConstBytes dma_fence_signaled() const { return at<416>().as_bytes(); }
+ bool has_dma_fence_wait_start() const { return at<417>().valid(); }
+ ::protozero::ConstBytes dma_fence_wait_start() const { return at<417>().as_bytes(); }
+ bool has_dma_fence_wait_end() const { return at<418>().valid(); }
+ ::protozero::ConstBytes dma_fence_wait_end() const { return at<418>().as_bytes(); }
+ bool has_f2fs_iostat() const { return at<419>().valid(); }
+ ::protozero::ConstBytes f2fs_iostat() const { return at<419>().as_bytes(); }
+ bool has_f2fs_iostat_latency() const { return at<420>().valid(); }
+ ::protozero::ConstBytes f2fs_iostat_latency() const { return at<420>().as_bytes(); }
+ bool has_sched_cpu_util_cfs() const { return at<421>().valid(); }
+ ::protozero::ConstBytes sched_cpu_util_cfs() const { return at<421>().as_bytes(); }
+ bool has_v4l2_qbuf() const { return at<422>().valid(); }
+ ::protozero::ConstBytes v4l2_qbuf() const { return at<422>().as_bytes(); }
+ bool has_v4l2_dqbuf() const { return at<423>().valid(); }
+ ::protozero::ConstBytes v4l2_dqbuf() const { return at<423>().as_bytes(); }
+ bool has_vb2_v4l2_buf_queue() const { return at<424>().valid(); }
+ ::protozero::ConstBytes vb2_v4l2_buf_queue() const { return at<424>().as_bytes(); }
+ bool has_vb2_v4l2_buf_done() const { return at<425>().valid(); }
+ ::protozero::ConstBytes vb2_v4l2_buf_done() const { return at<425>().as_bytes(); }
+ bool has_vb2_v4l2_qbuf() const { return at<426>().valid(); }
+ ::protozero::ConstBytes vb2_v4l2_qbuf() const { return at<426>().as_bytes(); }
+ bool has_vb2_v4l2_dqbuf() const { return at<427>().valid(); }
+ ::protozero::ConstBytes vb2_v4l2_dqbuf() const { return at<427>().as_bytes(); }
+ bool has_dsi_cmd_fifo_status() const { return at<428>().valid(); }
+ ::protozero::ConstBytes dsi_cmd_fifo_status() const { return at<428>().as_bytes(); }
+ bool has_dsi_rx() const { return at<429>().valid(); }
+ ::protozero::ConstBytes dsi_rx() const { return at<429>().as_bytes(); }
+ bool has_dsi_tx() const { return at<430>().valid(); }
+ ::protozero::ConstBytes dsi_tx() const { return at<430>().as_bytes(); }
+ bool has_android_fs_dataread_end() const { return at<431>().valid(); }
+ ::protozero::ConstBytes android_fs_dataread_end() const { return at<431>().as_bytes(); }
+ bool has_android_fs_dataread_start() const { return at<432>().valid(); }
+ ::protozero::ConstBytes android_fs_dataread_start() const { return at<432>().as_bytes(); }
+ bool has_android_fs_datawrite_end() const { return at<433>().valid(); }
+ ::protozero::ConstBytes android_fs_datawrite_end() const { return at<433>().as_bytes(); }
+ bool has_android_fs_datawrite_start() const { return at<434>().valid(); }
+ ::protozero::ConstBytes android_fs_datawrite_start() const { return at<434>().as_bytes(); }
+ bool has_android_fs_fsync_end() const { return at<435>().valid(); }
+ ::protozero::ConstBytes android_fs_fsync_end() const { return at<435>().as_bytes(); }
+ bool has_android_fs_fsync_start() const { return at<436>().valid(); }
+ ::protozero::ConstBytes android_fs_fsync_start() const { return at<436>().as_bytes(); }
+ bool has_funcgraph_entry() const { return at<437>().valid(); }
+ ::protozero::ConstBytes funcgraph_entry() const { return at<437>().as_bytes(); }
+ bool has_funcgraph_exit() const { return at<438>().valid(); }
+ ::protozero::ConstBytes funcgraph_exit() const { return at<438>().as_bytes(); }
+ bool has_virtio_video_cmd() const { return at<439>().valid(); }
+ ::protozero::ConstBytes virtio_video_cmd() const { return at<439>().as_bytes(); }
+ bool has_virtio_video_cmd_done() const { return at<440>().valid(); }
+ ::protozero::ConstBytes virtio_video_cmd_done() const { return at<440>().as_bytes(); }
+ bool has_virtio_video_resource_queue() const { return at<441>().valid(); }
+ ::protozero::ConstBytes virtio_video_resource_queue() const { return at<441>().as_bytes(); }
+ bool has_virtio_video_resource_queue_done() const { return at<442>().valid(); }
+ ::protozero::ConstBytes virtio_video_resource_queue_done() const { return at<442>().as_bytes(); }
+ bool has_mm_shrink_slab_start() const { return at<443>().valid(); }
+ ::protozero::ConstBytes mm_shrink_slab_start() const { return at<443>().as_bytes(); }
+ bool has_mm_shrink_slab_end() const { return at<444>().valid(); }
+ ::protozero::ConstBytes mm_shrink_slab_end() const { return at<444>().as_bytes(); }
+ bool has_trusty_smc() const { return at<445>().valid(); }
+ ::protozero::ConstBytes trusty_smc() const { return at<445>().as_bytes(); }
+ bool has_trusty_smc_done() const { return at<446>().valid(); }
+ ::protozero::ConstBytes trusty_smc_done() const { return at<446>().as_bytes(); }
+ bool has_trusty_std_call32() const { return at<447>().valid(); }
+ ::protozero::ConstBytes trusty_std_call32() const { return at<447>().as_bytes(); }
+ bool has_trusty_std_call32_done() const { return at<448>().valid(); }
+ ::protozero::ConstBytes trusty_std_call32_done() const { return at<448>().as_bytes(); }
+ bool has_trusty_share_memory() const { return at<449>().valid(); }
+ ::protozero::ConstBytes trusty_share_memory() const { return at<449>().as_bytes(); }
+ bool has_trusty_share_memory_done() const { return at<450>().valid(); }
+ ::protozero::ConstBytes trusty_share_memory_done() const { return at<450>().as_bytes(); }
+ bool has_trusty_reclaim_memory() const { return at<451>().valid(); }
+ ::protozero::ConstBytes trusty_reclaim_memory() const { return at<451>().as_bytes(); }
+ bool has_trusty_reclaim_memory_done() const { return at<452>().valid(); }
+ ::protozero::ConstBytes trusty_reclaim_memory_done() const { return at<452>().as_bytes(); }
+ bool has_trusty_irq() const { return at<453>().valid(); }
+ ::protozero::ConstBytes trusty_irq() const { return at<453>().as_bytes(); }
+ bool has_trusty_ipc_handle_event() const { return at<454>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_handle_event() const { return at<454>().as_bytes(); }
+ bool has_trusty_ipc_connect() const { return at<455>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_connect() const { return at<455>().as_bytes(); }
+ bool has_trusty_ipc_connect_end() const { return at<456>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_connect_end() const { return at<456>().as_bytes(); }
+ bool has_trusty_ipc_write() const { return at<457>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_write() const { return at<457>().as_bytes(); }
+ bool has_trusty_ipc_poll() const { return at<458>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_poll() const { return at<458>().as_bytes(); }
+ bool has_trusty_ipc_read() const { return at<460>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_read() const { return at<460>().as_bytes(); }
+ bool has_trusty_ipc_read_end() const { return at<461>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_read_end() const { return at<461>().as_bytes(); }
+ bool has_trusty_ipc_rx() const { return at<462>().valid(); }
+ ::protozero::ConstBytes trusty_ipc_rx() const { return at<462>().as_bytes(); }
+ bool has_trusty_enqueue_nop() const { return at<464>().valid(); }
+ ::protozero::ConstBytes trusty_enqueue_nop() const { return at<464>().as_bytes(); }
+ bool has_cma_alloc_start() const { return at<465>().valid(); }
+ ::protozero::ConstBytes cma_alloc_start() const { return at<465>().as_bytes(); }
+ bool has_cma_alloc_info() const { return at<466>().valid(); }
+ ::protozero::ConstBytes cma_alloc_info() const { return at<466>().as_bytes(); }
+ bool has_lwis_tracing_mark_write() const { return at<467>().valid(); }
+ ::protozero::ConstBytes lwis_tracing_mark_write() const { return at<467>().as_bytes(); }
+ bool has_virtio_gpu_cmd_queue() const { return at<468>().valid(); }
+ ::protozero::ConstBytes virtio_gpu_cmd_queue() const { return at<468>().as_bytes(); }
+ bool has_virtio_gpu_cmd_response() const { return at<469>().valid(); }
+ ::protozero::ConstBytes virtio_gpu_cmd_response() const { return at<469>().as_bytes(); }
+ bool has_mali_mali_kcpu_cqs_set() const { return at<470>().valid(); }
+ ::protozero::ConstBytes mali_mali_kcpu_cqs_set() const { return at<470>().as_bytes(); }
+ bool has_mali_mali_kcpu_cqs_wait_start() const { return at<471>().valid(); }
+ ::protozero::ConstBytes mali_mali_kcpu_cqs_wait_start() const { return at<471>().as_bytes(); }
+ bool has_mali_mali_kcpu_cqs_wait_end() const { return at<472>().valid(); }
+ ::protozero::ConstBytes mali_mali_kcpu_cqs_wait_end() const { return at<472>().as_bytes(); }
+ bool has_mali_mali_kcpu_fence_signal() const { return at<473>().valid(); }
+ ::protozero::ConstBytes mali_mali_kcpu_fence_signal() const { return at<473>().as_bytes(); }
+ bool has_mali_mali_kcpu_fence_wait_start() const { return at<474>().valid(); }
+ ::protozero::ConstBytes mali_mali_kcpu_fence_wait_start() const { return at<474>().as_bytes(); }
+ bool has_mali_mali_kcpu_fence_wait_end() const { return at<475>().valid(); }
+ ::protozero::ConstBytes mali_mali_kcpu_fence_wait_end() const { return at<475>().as_bytes(); }
+ bool has_hyp_enter() const { return at<476>().valid(); }
+ ::protozero::ConstBytes hyp_enter() const { return at<476>().as_bytes(); }
+ bool has_hyp_exit() const { return at<477>().valid(); }
+ ::protozero::ConstBytes hyp_exit() const { return at<477>().as_bytes(); }
+ bool has_host_hcall() const { return at<478>().valid(); }
+ ::protozero::ConstBytes host_hcall() const { return at<478>().as_bytes(); }
+ bool has_host_smc() const { return at<479>().valid(); }
+ ::protozero::ConstBytes host_smc() const { return at<479>().as_bytes(); }
+ bool has_host_mem_abort() const { return at<480>().valid(); }
+ ::protozero::ConstBytes host_mem_abort() const { return at<480>().as_bytes(); }
+ bool has_suspend_resume_minimal() const { return at<481>().valid(); }
+ ::protozero::ConstBytes suspend_resume_minimal() const { return at<481>().as_bytes(); }
+ bool has_mali_mali_csf_interrupt_start() const { return at<482>().valid(); }
+ ::protozero::ConstBytes mali_mali_csf_interrupt_start() const { return at<482>().as_bytes(); }
+ bool has_mali_mali_csf_interrupt_end() const { return at<483>().valid(); }
+ ::protozero::ConstBytes mali_mali_csf_interrupt_end() const { return at<483>().as_bytes(); }
+ bool has_samsung_tracing_mark_write() const { return at<484>().valid(); }
+ ::protozero::ConstBytes samsung_tracing_mark_write() const { return at<484>().as_bytes(); }
+ bool has_binder_command() const { return at<485>().valid(); }
+ ::protozero::ConstBytes binder_command() const { return at<485>().as_bytes(); }
+ bool has_binder_return() const { return at<486>().valid(); }
+ ::protozero::ConstBytes binder_return() const { return at<486>().as_bytes(); }
+ bool has_sched_switch_with_ctrs() const { return at<487>().valid(); }
+ ::protozero::ConstBytes sched_switch_with_ctrs() const { return at<487>().as_bytes(); }
+ bool has_gpu_work_period() const { return at<488>().valid(); }
+ ::protozero::ConstBytes gpu_work_period() const { return at<488>().as_bytes(); }
+ bool has_rpm_status() const { return at<489>().valid(); }
+ ::protozero::ConstBytes rpm_status() const { return at<489>().as_bytes(); }
+ bool has_panel_write_generic() const { return at<490>().valid(); }
+ ::protozero::ConstBytes panel_write_generic() const { return at<490>().as_bytes(); }
+ bool has_sched_migrate_task() const { return at<491>().valid(); }
+ ::protozero::ConstBytes sched_migrate_task() const { return at<491>().as_bytes(); }
+ bool has_dpu_dsi_cmd_fifo_status() const { return at<492>().valid(); }
+ ::protozero::ConstBytes dpu_dsi_cmd_fifo_status() const { return at<492>().as_bytes(); }
+ bool has_dpu_dsi_rx() const { return at<493>().valid(); }
+ ::protozero::ConstBytes dpu_dsi_rx() const { return at<493>().as_bytes(); }
+ bool has_dpu_dsi_tx() const { return at<494>().valid(); }
+ ::protozero::ConstBytes dpu_dsi_tx() const { return at<494>().as_bytes(); }
+ bool has_f2fs_background_gc() const { return at<495>().valid(); }
+ ::protozero::ConstBytes f2fs_background_gc() const { return at<495>().as_bytes(); }
+ bool has_f2fs_gc_begin() const { return at<496>().valid(); }
+ ::protozero::ConstBytes f2fs_gc_begin() const { return at<496>().as_bytes(); }
+ bool has_f2fs_gc_end() const { return at<497>().valid(); }
+ ::protozero::ConstBytes f2fs_gc_end() const { return at<497>().as_bytes(); }
+};
+
+class FtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FtraceEvent_Decoder;
+ enum : int32_t {
+ kTimestampFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kCommonFlagsFieldNumber = 5,
+ kPrintFieldNumber = 3,
+ kSchedSwitchFieldNumber = 4,
+ kCpuFrequencyFieldNumber = 11,
+ kCpuFrequencyLimitsFieldNumber = 12,
+ kCpuIdleFieldNumber = 13,
+ kClockEnableFieldNumber = 14,
+ kClockDisableFieldNumber = 15,
+ kClockSetRateFieldNumber = 16,
+ kSchedWakeupFieldNumber = 17,
+ kSchedBlockedReasonFieldNumber = 18,
+ kSchedCpuHotplugFieldNumber = 19,
+ kSchedWakingFieldNumber = 20,
+ kIpiEntryFieldNumber = 21,
+ kIpiExitFieldNumber = 22,
+ kIpiRaiseFieldNumber = 23,
+ kSoftirqEntryFieldNumber = 24,
+ kSoftirqExitFieldNumber = 25,
+ kSoftirqRaiseFieldNumber = 26,
+ kI2cReadFieldNumber = 27,
+ kI2cWriteFieldNumber = 28,
+ kI2cResultFieldNumber = 29,
+ kI2cReplyFieldNumber = 30,
+ kSmbusReadFieldNumber = 31,
+ kSmbusWriteFieldNumber = 32,
+ kSmbusResultFieldNumber = 33,
+ kSmbusReplyFieldNumber = 34,
+ kLowmemoryKillFieldNumber = 35,
+ kIrqHandlerEntryFieldNumber = 36,
+ kIrqHandlerExitFieldNumber = 37,
+ kSyncPtFieldNumber = 38,
+ kSyncTimelineFieldNumber = 39,
+ kSyncWaitFieldNumber = 40,
+ kExt4DaWriteBeginFieldNumber = 41,
+ kExt4DaWriteEndFieldNumber = 42,
+ kExt4SyncFileEnterFieldNumber = 43,
+ kExt4SyncFileExitFieldNumber = 44,
+ kBlockRqIssueFieldNumber = 45,
+ kMmVmscanDirectReclaimBeginFieldNumber = 46,
+ kMmVmscanDirectReclaimEndFieldNumber = 47,
+ kMmVmscanKswapdWakeFieldNumber = 48,
+ kMmVmscanKswapdSleepFieldNumber = 49,
+ kBinderTransactionFieldNumber = 50,
+ kBinderTransactionReceivedFieldNumber = 51,
+ kBinderSetPriorityFieldNumber = 52,
+ kBinderLockFieldNumber = 53,
+ kBinderLockedFieldNumber = 54,
+ kBinderUnlockFieldNumber = 55,
+ kWorkqueueActivateWorkFieldNumber = 56,
+ kWorkqueueExecuteEndFieldNumber = 57,
+ kWorkqueueExecuteStartFieldNumber = 58,
+ kWorkqueueQueueWorkFieldNumber = 59,
+ kRegulatorDisableFieldNumber = 60,
+ kRegulatorDisableCompleteFieldNumber = 61,
+ kRegulatorEnableFieldNumber = 62,
+ kRegulatorEnableCompleteFieldNumber = 63,
+ kRegulatorEnableDelayFieldNumber = 64,
+ kRegulatorSetVoltageFieldNumber = 65,
+ kRegulatorSetVoltageCompleteFieldNumber = 66,
+ kCgroupAttachTaskFieldNumber = 67,
+ kCgroupMkdirFieldNumber = 68,
+ kCgroupRemountFieldNumber = 69,
+ kCgroupRmdirFieldNumber = 70,
+ kCgroupTransferTasksFieldNumber = 71,
+ kCgroupDestroyRootFieldNumber = 72,
+ kCgroupReleaseFieldNumber = 73,
+ kCgroupRenameFieldNumber = 74,
+ kCgroupSetupRootFieldNumber = 75,
+ kMdpCmdKickoffFieldNumber = 76,
+ kMdpCommitFieldNumber = 77,
+ kMdpPerfSetOtFieldNumber = 78,
+ kMdpSsppChangeFieldNumber = 79,
+ kTracingMarkWriteFieldNumber = 80,
+ kMdpCmdPingpongDoneFieldNumber = 81,
+ kMdpCompareBwFieldNumber = 82,
+ kMdpPerfSetPanicLutsFieldNumber = 83,
+ kMdpSsppSetFieldNumber = 84,
+ kMdpCmdReadptrDoneFieldNumber = 85,
+ kMdpMisrCrcFieldNumber = 86,
+ kMdpPerfSetQosLutsFieldNumber = 87,
+ kMdpTraceCounterFieldNumber = 88,
+ kMdpCmdReleaseBwFieldNumber = 89,
+ kMdpMixerUpdateFieldNumber = 90,
+ kMdpPerfSetWmLevelsFieldNumber = 91,
+ kMdpVideoUnderrunDoneFieldNumber = 92,
+ kMdpCmdWaitPingpongFieldNumber = 93,
+ kMdpPerfPrefillCalcFieldNumber = 94,
+ kMdpPerfUpdateBusFieldNumber = 95,
+ kRotatorBwAoAsContextFieldNumber = 96,
+ kMmFilemapAddToPageCacheFieldNumber = 97,
+ kMmFilemapDeleteFromPageCacheFieldNumber = 98,
+ kMmCompactionBeginFieldNumber = 99,
+ kMmCompactionDeferCompactionFieldNumber = 100,
+ kMmCompactionDeferredFieldNumber = 101,
+ kMmCompactionDeferResetFieldNumber = 102,
+ kMmCompactionEndFieldNumber = 103,
+ kMmCompactionFinishedFieldNumber = 104,
+ kMmCompactionIsolateFreepagesFieldNumber = 105,
+ kMmCompactionIsolateMigratepagesFieldNumber = 106,
+ kMmCompactionKcompactdSleepFieldNumber = 107,
+ kMmCompactionKcompactdWakeFieldNumber = 108,
+ kMmCompactionMigratepagesFieldNumber = 109,
+ kMmCompactionSuitableFieldNumber = 110,
+ kMmCompactionTryToCompactPagesFieldNumber = 111,
+ kMmCompactionWakeupKcompactdFieldNumber = 112,
+ kSuspendResumeFieldNumber = 113,
+ kSchedWakeupNewFieldNumber = 114,
+ kBlockBioBackmergeFieldNumber = 115,
+ kBlockBioBounceFieldNumber = 116,
+ kBlockBioCompleteFieldNumber = 117,
+ kBlockBioFrontmergeFieldNumber = 118,
+ kBlockBioQueueFieldNumber = 119,
+ kBlockBioRemapFieldNumber = 120,
+ kBlockDirtyBufferFieldNumber = 121,
+ kBlockGetrqFieldNumber = 122,
+ kBlockPlugFieldNumber = 123,
+ kBlockRqAbortFieldNumber = 124,
+ kBlockRqCompleteFieldNumber = 125,
+ kBlockRqInsertFieldNumber = 126,
+ kBlockRqRemapFieldNumber = 128,
+ kBlockRqRequeueFieldNumber = 129,
+ kBlockSleeprqFieldNumber = 130,
+ kBlockSplitFieldNumber = 131,
+ kBlockTouchBufferFieldNumber = 132,
+ kBlockUnplugFieldNumber = 133,
+ kExt4AllocDaBlocksFieldNumber = 134,
+ kExt4AllocateBlocksFieldNumber = 135,
+ kExt4AllocateInodeFieldNumber = 136,
+ kExt4BeginOrderedTruncateFieldNumber = 137,
+ kExt4CollapseRangeFieldNumber = 138,
+ kExt4DaReleaseSpaceFieldNumber = 139,
+ kExt4DaReserveSpaceFieldNumber = 140,
+ kExt4DaUpdateReserveSpaceFieldNumber = 141,
+ kExt4DaWritePagesFieldNumber = 142,
+ kExt4DaWritePagesExtentFieldNumber = 143,
+ kExt4DirectIOEnterFieldNumber = 144,
+ kExt4DirectIOExitFieldNumber = 145,
+ kExt4DiscardBlocksFieldNumber = 146,
+ kExt4DiscardPreallocationsFieldNumber = 147,
+ kExt4DropInodeFieldNumber = 148,
+ kExt4EsCacheExtentFieldNumber = 149,
+ kExt4EsFindDelayedExtentRangeEnterFieldNumber = 150,
+ kExt4EsFindDelayedExtentRangeExitFieldNumber = 151,
+ kExt4EsInsertExtentFieldNumber = 152,
+ kExt4EsLookupExtentEnterFieldNumber = 153,
+ kExt4EsLookupExtentExitFieldNumber = 154,
+ kExt4EsRemoveExtentFieldNumber = 155,
+ kExt4EsShrinkFieldNumber = 156,
+ kExt4EsShrinkCountFieldNumber = 157,
+ kExt4EsShrinkScanEnterFieldNumber = 158,
+ kExt4EsShrinkScanExitFieldNumber = 159,
+ kExt4EvictInodeFieldNumber = 160,
+ kExt4ExtConvertToInitializedEnterFieldNumber = 161,
+ kExt4ExtConvertToInitializedFastpathFieldNumber = 162,
+ kExt4ExtHandleUnwrittenExtentsFieldNumber = 163,
+ kExt4ExtInCacheFieldNumber = 164,
+ kExt4ExtLoadExtentFieldNumber = 165,
+ kExt4ExtMapBlocksEnterFieldNumber = 166,
+ kExt4ExtMapBlocksExitFieldNumber = 167,
+ kExt4ExtPutInCacheFieldNumber = 168,
+ kExt4ExtRemoveSpaceFieldNumber = 169,
+ kExt4ExtRemoveSpaceDoneFieldNumber = 170,
+ kExt4ExtRmIdxFieldNumber = 171,
+ kExt4ExtRmLeafFieldNumber = 172,
+ kExt4ExtShowExtentFieldNumber = 173,
+ kExt4FallocateEnterFieldNumber = 174,
+ kExt4FallocateExitFieldNumber = 175,
+ kExt4FindDelallocRangeFieldNumber = 176,
+ kExt4ForgetFieldNumber = 177,
+ kExt4FreeBlocksFieldNumber = 178,
+ kExt4FreeInodeFieldNumber = 179,
+ kExt4GetImpliedClusterAllocExitFieldNumber = 180,
+ kExt4GetReservedClusterAllocFieldNumber = 181,
+ kExt4IndMapBlocksEnterFieldNumber = 182,
+ kExt4IndMapBlocksExitFieldNumber = 183,
+ kExt4InsertRangeFieldNumber = 184,
+ kExt4InvalidatepageFieldNumber = 185,
+ kExt4JournalStartFieldNumber = 186,
+ kExt4JournalStartReservedFieldNumber = 187,
+ kExt4JournalledInvalidatepageFieldNumber = 188,
+ kExt4JournalledWriteEndFieldNumber = 189,
+ kExt4LoadInodeFieldNumber = 190,
+ kExt4LoadInodeBitmapFieldNumber = 191,
+ kExt4MarkInodeDirtyFieldNumber = 192,
+ kExt4MbBitmapLoadFieldNumber = 193,
+ kExt4MbBuddyBitmapLoadFieldNumber = 194,
+ kExt4MbDiscardPreallocationsFieldNumber = 195,
+ kExt4MbNewGroupPaFieldNumber = 196,
+ kExt4MbNewInodePaFieldNumber = 197,
+ kExt4MbReleaseGroupPaFieldNumber = 198,
+ kExt4MbReleaseInodePaFieldNumber = 199,
+ kExt4MballocAllocFieldNumber = 200,
+ kExt4MballocDiscardFieldNumber = 201,
+ kExt4MballocFreeFieldNumber = 202,
+ kExt4MballocPreallocFieldNumber = 203,
+ kExt4OtherInodeUpdateTimeFieldNumber = 204,
+ kExt4PunchHoleFieldNumber = 205,
+ kExt4ReadBlockBitmapLoadFieldNumber = 206,
+ kExt4ReadpageFieldNumber = 207,
+ kExt4ReleasepageFieldNumber = 208,
+ kExt4RemoveBlocksFieldNumber = 209,
+ kExt4RequestBlocksFieldNumber = 210,
+ kExt4RequestInodeFieldNumber = 211,
+ kExt4SyncFsFieldNumber = 212,
+ kExt4TrimAllFreeFieldNumber = 213,
+ kExt4TrimExtentFieldNumber = 214,
+ kExt4TruncateEnterFieldNumber = 215,
+ kExt4TruncateExitFieldNumber = 216,
+ kExt4UnlinkEnterFieldNumber = 217,
+ kExt4UnlinkExitFieldNumber = 218,
+ kExt4WriteBeginFieldNumber = 219,
+ kExt4WriteEndFieldNumber = 230,
+ kExt4WritepageFieldNumber = 231,
+ kExt4WritepagesFieldNumber = 232,
+ kExt4WritepagesResultFieldNumber = 233,
+ kExt4ZeroRangeFieldNumber = 234,
+ kTaskNewtaskFieldNumber = 235,
+ kTaskRenameFieldNumber = 236,
+ kSchedProcessExecFieldNumber = 237,
+ kSchedProcessExitFieldNumber = 238,
+ kSchedProcessForkFieldNumber = 239,
+ kSchedProcessFreeFieldNumber = 240,
+ kSchedProcessHangFieldNumber = 241,
+ kSchedProcessWaitFieldNumber = 242,
+ kF2fsDoSubmitBioFieldNumber = 243,
+ kF2fsEvictInodeFieldNumber = 244,
+ kF2fsFallocateFieldNumber = 245,
+ kF2fsGetDataBlockFieldNumber = 246,
+ kF2fsGetVictimFieldNumber = 247,
+ kF2fsIgetFieldNumber = 248,
+ kF2fsIgetExitFieldNumber = 249,
+ kF2fsNewInodeFieldNumber = 250,
+ kF2fsReadpageFieldNumber = 251,
+ kF2fsReserveNewBlockFieldNumber = 252,
+ kF2fsSetPageDirtyFieldNumber = 253,
+ kF2fsSubmitWritePageFieldNumber = 254,
+ kF2fsSyncFileEnterFieldNumber = 255,
+ kF2fsSyncFileExitFieldNumber = 256,
+ kF2fsSyncFsFieldNumber = 257,
+ kF2fsTruncateFieldNumber = 258,
+ kF2fsTruncateBlocksEnterFieldNumber = 259,
+ kF2fsTruncateBlocksExitFieldNumber = 260,
+ kF2fsTruncateDataBlocksRangeFieldNumber = 261,
+ kF2fsTruncateInodeBlocksEnterFieldNumber = 262,
+ kF2fsTruncateInodeBlocksExitFieldNumber = 263,
+ kF2fsTruncateNodeFieldNumber = 264,
+ kF2fsTruncateNodesEnterFieldNumber = 265,
+ kF2fsTruncateNodesExitFieldNumber = 266,
+ kF2fsTruncatePartialNodesFieldNumber = 267,
+ kF2fsUnlinkEnterFieldNumber = 268,
+ kF2fsUnlinkExitFieldNumber = 269,
+ kF2fsVmPageMkwriteFieldNumber = 270,
+ kF2fsWriteBeginFieldNumber = 271,
+ kF2fsWriteCheckpointFieldNumber = 272,
+ kF2fsWriteEndFieldNumber = 273,
+ kAllocPagesIommuEndFieldNumber = 274,
+ kAllocPagesIommuFailFieldNumber = 275,
+ kAllocPagesIommuStartFieldNumber = 276,
+ kAllocPagesSysEndFieldNumber = 277,
+ kAllocPagesSysFailFieldNumber = 278,
+ kAllocPagesSysStartFieldNumber = 279,
+ kDmaAllocContiguousRetryFieldNumber = 280,
+ kIommuMapRangeFieldNumber = 281,
+ kIommuSecPtblMapRangeEndFieldNumber = 282,
+ kIommuSecPtblMapRangeStartFieldNumber = 283,
+ kIonAllocBufferEndFieldNumber = 284,
+ kIonAllocBufferFailFieldNumber = 285,
+ kIonAllocBufferFallbackFieldNumber = 286,
+ kIonAllocBufferStartFieldNumber = 287,
+ kIonCpAllocRetryFieldNumber = 288,
+ kIonCpSecureBufferEndFieldNumber = 289,
+ kIonCpSecureBufferStartFieldNumber = 290,
+ kIonPrefetchingFieldNumber = 291,
+ kIonSecureCmaAddToPoolEndFieldNumber = 292,
+ kIonSecureCmaAddToPoolStartFieldNumber = 293,
+ kIonSecureCmaAllocateEndFieldNumber = 294,
+ kIonSecureCmaAllocateStartFieldNumber = 295,
+ kIonSecureCmaShrinkPoolEndFieldNumber = 296,
+ kIonSecureCmaShrinkPoolStartFieldNumber = 297,
+ kKfreeFieldNumber = 298,
+ kKmallocFieldNumber = 299,
+ kKmallocNodeFieldNumber = 300,
+ kKmemCacheAllocFieldNumber = 301,
+ kKmemCacheAllocNodeFieldNumber = 302,
+ kKmemCacheFreeFieldNumber = 303,
+ kMigratePagesEndFieldNumber = 304,
+ kMigratePagesStartFieldNumber = 305,
+ kMigrateRetryFieldNumber = 306,
+ kMmPageAllocFieldNumber = 307,
+ kMmPageAllocExtfragFieldNumber = 308,
+ kMmPageAllocZoneLockedFieldNumber = 309,
+ kMmPageFreeFieldNumber = 310,
+ kMmPageFreeBatchedFieldNumber = 311,
+ kMmPagePcpuDrainFieldNumber = 312,
+ kRssStatFieldNumber = 313,
+ kIonHeapShrinkFieldNumber = 314,
+ kIonHeapGrowFieldNumber = 315,
+ kFenceInitFieldNumber = 316,
+ kFenceDestroyFieldNumber = 317,
+ kFenceEnableSignalFieldNumber = 318,
+ kFenceSignaledFieldNumber = 319,
+ kClkEnableFieldNumber = 320,
+ kClkDisableFieldNumber = 321,
+ kClkSetRateFieldNumber = 322,
+ kBinderTransactionAllocBufFieldNumber = 323,
+ kSignalDeliverFieldNumber = 324,
+ kSignalGenerateFieldNumber = 325,
+ kOomScoreAdjUpdateFieldNumber = 326,
+ kGenericFieldNumber = 327,
+ kMmEventRecordFieldNumber = 328,
+ kSysEnterFieldNumber = 329,
+ kSysExitFieldNumber = 330,
+ kZeroFieldNumber = 331,
+ kGpuFrequencyFieldNumber = 332,
+ kSdeTracingMarkWriteFieldNumber = 333,
+ kMarkVictimFieldNumber = 334,
+ kIonStatFieldNumber = 335,
+ kIonBufferCreateFieldNumber = 336,
+ kIonBufferDestroyFieldNumber = 337,
+ kScmCallStartFieldNumber = 338,
+ kScmCallEndFieldNumber = 339,
+ kGpuMemTotalFieldNumber = 340,
+ kThermalTemperatureFieldNumber = 341,
+ kCdevUpdateFieldNumber = 342,
+ kCpuhpExitFieldNumber = 343,
+ kCpuhpMultiEnterFieldNumber = 344,
+ kCpuhpEnterFieldNumber = 345,
+ kCpuhpLatencyFieldNumber = 346,
+ kFastrpcDmaStatFieldNumber = 347,
+ kDpuTracingMarkWriteFieldNumber = 348,
+ kG2dTracingMarkWriteFieldNumber = 349,
+ kMaliTracingMarkWriteFieldNumber = 350,
+ kDmaHeapStatFieldNumber = 351,
+ kCpuhpPauseFieldNumber = 352,
+ kSchedPiSetprioFieldNumber = 353,
+ kSdeSdeEvtlogFieldNumber = 354,
+ kSdeSdePerfCalcCrtcFieldNumber = 355,
+ kSdeSdePerfCrtcUpdateFieldNumber = 356,
+ kSdeSdePerfSetQosLutsFieldNumber = 357,
+ kSdeSdePerfUpdateBusFieldNumber = 358,
+ kRssStatThrottledFieldNumber = 359,
+ kNetifReceiveSkbFieldNumber = 360,
+ kNetDevXmitFieldNumber = 361,
+ kInetSockSetStateFieldNumber = 362,
+ kTcpRetransmitSkbFieldNumber = 363,
+ kCrosEcSensorhubDataFieldNumber = 364,
+ kNapiGroReceiveEntryFieldNumber = 365,
+ kNapiGroReceiveExitFieldNumber = 366,
+ kKfreeSkbFieldNumber = 367,
+ kKvmAccessFaultFieldNumber = 368,
+ kKvmAckIrqFieldNumber = 369,
+ kKvmAgeHvaFieldNumber = 370,
+ kKvmAgePageFieldNumber = 371,
+ kKvmArmClearDebugFieldNumber = 372,
+ kKvmArmSetDreg32FieldNumber = 373,
+ kKvmArmSetRegsetFieldNumber = 374,
+ kKvmArmSetupDebugFieldNumber = 375,
+ kKvmEntryFieldNumber = 376,
+ kKvmExitFieldNumber = 377,
+ kKvmFpuFieldNumber = 378,
+ kKvmGetTimerMapFieldNumber = 379,
+ kKvmGuestFaultFieldNumber = 380,
+ kKvmHandleSysRegFieldNumber = 381,
+ kKvmHvcArm64FieldNumber = 382,
+ kKvmIrqLineFieldNumber = 383,
+ kKvmMmioFieldNumber = 384,
+ kKvmMmioEmulateFieldNumber = 385,
+ kKvmSetGuestDebugFieldNumber = 386,
+ kKvmSetIrqFieldNumber = 387,
+ kKvmSetSpteHvaFieldNumber = 388,
+ kKvmSetWayFlushFieldNumber = 389,
+ kKvmSysAccessFieldNumber = 390,
+ kKvmTestAgeHvaFieldNumber = 391,
+ kKvmTimerEmulateFieldNumber = 392,
+ kKvmTimerHrtimerExpireFieldNumber = 393,
+ kKvmTimerRestoreStateFieldNumber = 394,
+ kKvmTimerSaveStateFieldNumber = 395,
+ kKvmTimerUpdateIrqFieldNumber = 396,
+ kKvmToggleCacheFieldNumber = 397,
+ kKvmUnmapHvaRangeFieldNumber = 398,
+ kKvmUserspaceExitFieldNumber = 399,
+ kKvmVcpuWakeupFieldNumber = 400,
+ kKvmWfxArm64FieldNumber = 401,
+ kTrapRegFieldNumber = 402,
+ kVgicUpdateIrqPendingFieldNumber = 403,
+ kWakeupSourceActivateFieldNumber = 404,
+ kWakeupSourceDeactivateFieldNumber = 405,
+ kUfshcdCommandFieldNumber = 406,
+ kUfshcdClkGatingFieldNumber = 407,
+ kConsoleFieldNumber = 408,
+ kDrmVblankEventFieldNumber = 409,
+ kDrmVblankEventDeliveredFieldNumber = 410,
+ kDrmSchedJobFieldNumber = 411,
+ kDrmRunJobFieldNumber = 412,
+ kDrmSchedProcessJobFieldNumber = 413,
+ kDmaFenceInitFieldNumber = 414,
+ kDmaFenceEmitFieldNumber = 415,
+ kDmaFenceSignaledFieldNumber = 416,
+ kDmaFenceWaitStartFieldNumber = 417,
+ kDmaFenceWaitEndFieldNumber = 418,
+ kF2fsIostatFieldNumber = 419,
+ kF2fsIostatLatencyFieldNumber = 420,
+ kSchedCpuUtilCfsFieldNumber = 421,
+ kV4l2QbufFieldNumber = 422,
+ kV4l2DqbufFieldNumber = 423,
+ kVb2V4l2BufQueueFieldNumber = 424,
+ kVb2V4l2BufDoneFieldNumber = 425,
+ kVb2V4l2QbufFieldNumber = 426,
+ kVb2V4l2DqbufFieldNumber = 427,
+ kDsiCmdFifoStatusFieldNumber = 428,
+ kDsiRxFieldNumber = 429,
+ kDsiTxFieldNumber = 430,
+ kAndroidFsDatareadEndFieldNumber = 431,
+ kAndroidFsDatareadStartFieldNumber = 432,
+ kAndroidFsDatawriteEndFieldNumber = 433,
+ kAndroidFsDatawriteStartFieldNumber = 434,
+ kAndroidFsFsyncEndFieldNumber = 435,
+ kAndroidFsFsyncStartFieldNumber = 436,
+ kFuncgraphEntryFieldNumber = 437,
+ kFuncgraphExitFieldNumber = 438,
+ kVirtioVideoCmdFieldNumber = 439,
+ kVirtioVideoCmdDoneFieldNumber = 440,
+ kVirtioVideoResourceQueueFieldNumber = 441,
+ kVirtioVideoResourceQueueDoneFieldNumber = 442,
+ kMmShrinkSlabStartFieldNumber = 443,
+ kMmShrinkSlabEndFieldNumber = 444,
+ kTrustySmcFieldNumber = 445,
+ kTrustySmcDoneFieldNumber = 446,
+ kTrustyStdCall32FieldNumber = 447,
+ kTrustyStdCall32DoneFieldNumber = 448,
+ kTrustyShareMemoryFieldNumber = 449,
+ kTrustyShareMemoryDoneFieldNumber = 450,
+ kTrustyReclaimMemoryFieldNumber = 451,
+ kTrustyReclaimMemoryDoneFieldNumber = 452,
+ kTrustyIrqFieldNumber = 453,
+ kTrustyIpcHandleEventFieldNumber = 454,
+ kTrustyIpcConnectFieldNumber = 455,
+ kTrustyIpcConnectEndFieldNumber = 456,
+ kTrustyIpcWriteFieldNumber = 457,
+ kTrustyIpcPollFieldNumber = 458,
+ kTrustyIpcReadFieldNumber = 460,
+ kTrustyIpcReadEndFieldNumber = 461,
+ kTrustyIpcRxFieldNumber = 462,
+ kTrustyEnqueueNopFieldNumber = 464,
+ kCmaAllocStartFieldNumber = 465,
+ kCmaAllocInfoFieldNumber = 466,
+ kLwisTracingMarkWriteFieldNumber = 467,
+ kVirtioGpuCmdQueueFieldNumber = 468,
+ kVirtioGpuCmdResponseFieldNumber = 469,
+ kMaliMaliKCPUCQSSETFieldNumber = 470,
+ kMaliMaliKCPUCQSWAITSTARTFieldNumber = 471,
+ kMaliMaliKCPUCQSWAITENDFieldNumber = 472,
+ kMaliMaliKCPUFENCESIGNALFieldNumber = 473,
+ kMaliMaliKCPUFENCEWAITSTARTFieldNumber = 474,
+ kMaliMaliKCPUFENCEWAITENDFieldNumber = 475,
+ kHypEnterFieldNumber = 476,
+ kHypExitFieldNumber = 477,
+ kHostHcallFieldNumber = 478,
+ kHostSmcFieldNumber = 479,
+ kHostMemAbortFieldNumber = 480,
+ kSuspendResumeMinimalFieldNumber = 481,
+ kMaliMaliCSFINTERRUPTSTARTFieldNumber = 482,
+ kMaliMaliCSFINTERRUPTENDFieldNumber = 483,
+ kSamsungTracingMarkWriteFieldNumber = 484,
+ kBinderCommandFieldNumber = 485,
+ kBinderReturnFieldNumber = 486,
+ kSchedSwitchWithCtrsFieldNumber = 487,
+ kGpuWorkPeriodFieldNumber = 488,
+ kRpmStatusFieldNumber = 489,
+ kPanelWriteGenericFieldNumber = 490,
+ kSchedMigrateTaskFieldNumber = 491,
+ kDpuDsiCmdFifoStatusFieldNumber = 492,
+ kDpuDsiRxFieldNumber = 493,
+ kDpuDsiTxFieldNumber = 494,
+ kF2fsBackgroundGcFieldNumber = 495,
+ kF2fsGcBeginFieldNumber = 496,
+ kF2fsGcEndFieldNumber = 497,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceEvent"; }
+
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CommonFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CommonFlags kCommonFlags{};
+ void set_common_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CommonFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Print =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PrintFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Print kPrint{};
+ template <typename T = PrintFtraceEvent> T* set_print() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_SchedSwitch =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedSwitchFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedSwitch kSchedSwitch{};
+ template <typename T = SchedSwitchFtraceEvent> T* set_sched_switch() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_CpuFrequency =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuFrequencyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuFrequency kCpuFrequency{};
+ template <typename T = CpuFrequencyFtraceEvent> T* set_cpu_frequency() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_CpuFrequencyLimits =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuFrequencyLimitsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuFrequencyLimits kCpuFrequencyLimits{};
+ template <typename T = CpuFrequencyLimitsFtraceEvent> T* set_cpu_frequency_limits() {
+ return BeginNestedMessage<T>(12);
+ }
+
+
+ using FieldMetadata_CpuIdle =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuIdleFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuIdle kCpuIdle{};
+ template <typename T = CpuIdleFtraceEvent> T* set_cpu_idle() {
+ return BeginNestedMessage<T>(13);
+ }
+
+
+ using FieldMetadata_ClockEnable =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClockEnableFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ClockEnable kClockEnable{};
+ template <typename T = ClockEnableFtraceEvent> T* set_clock_enable() {
+ return BeginNestedMessage<T>(14);
+ }
+
+
+ using FieldMetadata_ClockDisable =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClockDisableFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ClockDisable kClockDisable{};
+ template <typename T = ClockDisableFtraceEvent> T* set_clock_disable() {
+ return BeginNestedMessage<T>(15);
+ }
+
+
+ using FieldMetadata_ClockSetRate =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClockSetRateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ClockSetRate kClockSetRate{};
+ template <typename T = ClockSetRateFtraceEvent> T* set_clock_set_rate() {
+ return BeginNestedMessage<T>(16);
+ }
+
+
+ using FieldMetadata_SchedWakeup =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedWakeupFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedWakeup kSchedWakeup{};
+ template <typename T = SchedWakeupFtraceEvent> T* set_sched_wakeup() {
+ return BeginNestedMessage<T>(17);
+ }
+
+
+ using FieldMetadata_SchedBlockedReason =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedBlockedReasonFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedBlockedReason kSchedBlockedReason{};
+ template <typename T = SchedBlockedReasonFtraceEvent> T* set_sched_blocked_reason() {
+ return BeginNestedMessage<T>(18);
+ }
+
+
+ using FieldMetadata_SchedCpuHotplug =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedCpuHotplugFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedCpuHotplug kSchedCpuHotplug{};
+ template <typename T = SchedCpuHotplugFtraceEvent> T* set_sched_cpu_hotplug() {
+ return BeginNestedMessage<T>(19);
+ }
+
+
+ using FieldMetadata_SchedWaking =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedWakingFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedWaking kSchedWaking{};
+ template <typename T = SchedWakingFtraceEvent> T* set_sched_waking() {
+ return BeginNestedMessage<T>(20);
+ }
+
+
+ using FieldMetadata_IpiEntry =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IpiEntryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IpiEntry kIpiEntry{};
+ template <typename T = IpiEntryFtraceEvent> T* set_ipi_entry() {
+ return BeginNestedMessage<T>(21);
+ }
+
+
+ using FieldMetadata_IpiExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IpiExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IpiExit kIpiExit{};
+ template <typename T = IpiExitFtraceEvent> T* set_ipi_exit() {
+ return BeginNestedMessage<T>(22);
+ }
+
+
+ using FieldMetadata_IpiRaise =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IpiRaiseFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IpiRaise kIpiRaise{};
+ template <typename T = IpiRaiseFtraceEvent> T* set_ipi_raise() {
+ return BeginNestedMessage<T>(23);
+ }
+
+
+ using FieldMetadata_SoftirqEntry =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SoftirqEntryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SoftirqEntry kSoftirqEntry{};
+ template <typename T = SoftirqEntryFtraceEvent> T* set_softirq_entry() {
+ return BeginNestedMessage<T>(24);
+ }
+
+
+ using FieldMetadata_SoftirqExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SoftirqExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SoftirqExit kSoftirqExit{};
+ template <typename T = SoftirqExitFtraceEvent> T* set_softirq_exit() {
+ return BeginNestedMessage<T>(25);
+ }
+
+
+ using FieldMetadata_SoftirqRaise =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SoftirqRaiseFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SoftirqRaise kSoftirqRaise{};
+ template <typename T = SoftirqRaiseFtraceEvent> T* set_softirq_raise() {
+ return BeginNestedMessage<T>(26);
+ }
+
+
+ using FieldMetadata_I2cRead =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ I2cReadFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_I2cRead kI2cRead{};
+ template <typename T = I2cReadFtraceEvent> T* set_i2c_read() {
+ return BeginNestedMessage<T>(27);
+ }
+
+
+ using FieldMetadata_I2cWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ I2cWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_I2cWrite kI2cWrite{};
+ template <typename T = I2cWriteFtraceEvent> T* set_i2c_write() {
+ return BeginNestedMessage<T>(28);
+ }
+
+
+ using FieldMetadata_I2cResult =
+ ::protozero::proto_utils::FieldMetadata<
+ 29,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ I2cResultFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_I2cResult kI2cResult{};
+ template <typename T = I2cResultFtraceEvent> T* set_i2c_result() {
+ return BeginNestedMessage<T>(29);
+ }
+
+
+ using FieldMetadata_I2cReply =
+ ::protozero::proto_utils::FieldMetadata<
+ 30,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ I2cReplyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_I2cReply kI2cReply{};
+ template <typename T = I2cReplyFtraceEvent> T* set_i2c_reply() {
+ return BeginNestedMessage<T>(30);
+ }
+
+
+ using FieldMetadata_SmbusRead =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SmbusReadFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SmbusRead kSmbusRead{};
+ template <typename T = SmbusReadFtraceEvent> T* set_smbus_read() {
+ return BeginNestedMessage<T>(31);
+ }
+
+
+ using FieldMetadata_SmbusWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 32,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SmbusWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SmbusWrite kSmbusWrite{};
+ template <typename T = SmbusWriteFtraceEvent> T* set_smbus_write() {
+ return BeginNestedMessage<T>(32);
+ }
+
+
+ using FieldMetadata_SmbusResult =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SmbusResultFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SmbusResult kSmbusResult{};
+ template <typename T = SmbusResultFtraceEvent> T* set_smbus_result() {
+ return BeginNestedMessage<T>(33);
+ }
+
+
+ using FieldMetadata_SmbusReply =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SmbusReplyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SmbusReply kSmbusReply{};
+ template <typename T = SmbusReplyFtraceEvent> T* set_smbus_reply() {
+ return BeginNestedMessage<T>(34);
+ }
+
+
+ using FieldMetadata_LowmemoryKill =
+ ::protozero::proto_utils::FieldMetadata<
+ 35,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LowmemoryKillFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_LowmemoryKill kLowmemoryKill{};
+ template <typename T = LowmemoryKillFtraceEvent> T* set_lowmemory_kill() {
+ return BeginNestedMessage<T>(35);
+ }
+
+
+ using FieldMetadata_IrqHandlerEntry =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IrqHandlerEntryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IrqHandlerEntry kIrqHandlerEntry{};
+ template <typename T = IrqHandlerEntryFtraceEvent> T* set_irq_handler_entry() {
+ return BeginNestedMessage<T>(36);
+ }
+
+
+ using FieldMetadata_IrqHandlerExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 37,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IrqHandlerExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IrqHandlerExit kIrqHandlerExit{};
+ template <typename T = IrqHandlerExitFtraceEvent> T* set_irq_handler_exit() {
+ return BeginNestedMessage<T>(37);
+ }
+
+
+ using FieldMetadata_SyncPt =
+ ::protozero::proto_utils::FieldMetadata<
+ 38,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SyncPtFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SyncPt kSyncPt{};
+ template <typename T = SyncPtFtraceEvent> T* set_sync_pt() {
+ return BeginNestedMessage<T>(38);
+ }
+
+
+ using FieldMetadata_SyncTimeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 39,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SyncTimelineFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SyncTimeline kSyncTimeline{};
+ template <typename T = SyncTimelineFtraceEvent> T* set_sync_timeline() {
+ return BeginNestedMessage<T>(39);
+ }
+
+
+ using FieldMetadata_SyncWait =
+ ::protozero::proto_utils::FieldMetadata<
+ 40,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SyncWaitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SyncWait kSyncWait{};
+ template <typename T = SyncWaitFtraceEvent> T* set_sync_wait() {
+ return BeginNestedMessage<T>(40);
+ }
+
+
+ using FieldMetadata_Ext4DaWriteBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 41,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DaWriteBeginFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DaWriteBegin kExt4DaWriteBegin{};
+ template <typename T = Ext4DaWriteBeginFtraceEvent> T* set_ext4_da_write_begin() {
+ return BeginNestedMessage<T>(41);
+ }
+
+
+ using FieldMetadata_Ext4DaWriteEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 42,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DaWriteEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DaWriteEnd kExt4DaWriteEnd{};
+ template <typename T = Ext4DaWriteEndFtraceEvent> T* set_ext4_da_write_end() {
+ return BeginNestedMessage<T>(42);
+ }
+
+
+ using FieldMetadata_Ext4SyncFileEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 43,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4SyncFileEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4SyncFileEnter kExt4SyncFileEnter{};
+ template <typename T = Ext4SyncFileEnterFtraceEvent> T* set_ext4_sync_file_enter() {
+ return BeginNestedMessage<T>(43);
+ }
+
+
+ using FieldMetadata_Ext4SyncFileExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 44,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4SyncFileExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4SyncFileExit kExt4SyncFileExit{};
+ template <typename T = Ext4SyncFileExitFtraceEvent> T* set_ext4_sync_file_exit() {
+ return BeginNestedMessage<T>(44);
+ }
+
+
+ using FieldMetadata_BlockRqIssue =
+ ::protozero::proto_utils::FieldMetadata<
+ 45,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockRqIssueFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockRqIssue kBlockRqIssue{};
+ template <typename T = BlockRqIssueFtraceEvent> T* set_block_rq_issue() {
+ return BeginNestedMessage<T>(45);
+ }
+
+
+ using FieldMetadata_MmVmscanDirectReclaimBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 46,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmVmscanDirectReclaimBeginFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmVmscanDirectReclaimBegin kMmVmscanDirectReclaimBegin{};
+ template <typename T = MmVmscanDirectReclaimBeginFtraceEvent> T* set_mm_vmscan_direct_reclaim_begin() {
+ return BeginNestedMessage<T>(46);
+ }
+
+
+ using FieldMetadata_MmVmscanDirectReclaimEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 47,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmVmscanDirectReclaimEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmVmscanDirectReclaimEnd kMmVmscanDirectReclaimEnd{};
+ template <typename T = MmVmscanDirectReclaimEndFtraceEvent> T* set_mm_vmscan_direct_reclaim_end() {
+ return BeginNestedMessage<T>(47);
+ }
+
+
+ using FieldMetadata_MmVmscanKswapdWake =
+ ::protozero::proto_utils::FieldMetadata<
+ 48,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmVmscanKswapdWakeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmVmscanKswapdWake kMmVmscanKswapdWake{};
+ template <typename T = MmVmscanKswapdWakeFtraceEvent> T* set_mm_vmscan_kswapd_wake() {
+ return BeginNestedMessage<T>(48);
+ }
+
+
+ using FieldMetadata_MmVmscanKswapdSleep =
+ ::protozero::proto_utils::FieldMetadata<
+ 49,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmVmscanKswapdSleepFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmVmscanKswapdSleep kMmVmscanKswapdSleep{};
+ template <typename T = MmVmscanKswapdSleepFtraceEvent> T* set_mm_vmscan_kswapd_sleep() {
+ return BeginNestedMessage<T>(49);
+ }
+
+
+ using FieldMetadata_BinderTransaction =
+ ::protozero::proto_utils::FieldMetadata<
+ 50,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderTransactionFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderTransaction kBinderTransaction{};
+ template <typename T = BinderTransactionFtraceEvent> T* set_binder_transaction() {
+ return BeginNestedMessage<T>(50);
+ }
+
+
+ using FieldMetadata_BinderTransactionReceived =
+ ::protozero::proto_utils::FieldMetadata<
+ 51,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderTransactionReceivedFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderTransactionReceived kBinderTransactionReceived{};
+ template <typename T = BinderTransactionReceivedFtraceEvent> T* set_binder_transaction_received() {
+ return BeginNestedMessage<T>(51);
+ }
+
+
+ using FieldMetadata_BinderSetPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 52,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderSetPriorityFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderSetPriority kBinderSetPriority{};
+ template <typename T = BinderSetPriorityFtraceEvent> T* set_binder_set_priority() {
+ return BeginNestedMessage<T>(52);
+ }
+
+
+ using FieldMetadata_BinderLock =
+ ::protozero::proto_utils::FieldMetadata<
+ 53,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderLockFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderLock kBinderLock{};
+ template <typename T = BinderLockFtraceEvent> T* set_binder_lock() {
+ return BeginNestedMessage<T>(53);
+ }
+
+
+ using FieldMetadata_BinderLocked =
+ ::protozero::proto_utils::FieldMetadata<
+ 54,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderLockedFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderLocked kBinderLocked{};
+ template <typename T = BinderLockedFtraceEvent> T* set_binder_locked() {
+ return BeginNestedMessage<T>(54);
+ }
+
+
+ using FieldMetadata_BinderUnlock =
+ ::protozero::proto_utils::FieldMetadata<
+ 55,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderUnlockFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderUnlock kBinderUnlock{};
+ template <typename T = BinderUnlockFtraceEvent> T* set_binder_unlock() {
+ return BeginNestedMessage<T>(55);
+ }
+
+
+ using FieldMetadata_WorkqueueActivateWork =
+ ::protozero::proto_utils::FieldMetadata<
+ 56,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ WorkqueueActivateWorkFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_WorkqueueActivateWork kWorkqueueActivateWork{};
+ template <typename T = WorkqueueActivateWorkFtraceEvent> T* set_workqueue_activate_work() {
+ return BeginNestedMessage<T>(56);
+ }
+
+
+ using FieldMetadata_WorkqueueExecuteEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 57,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ WorkqueueExecuteEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_WorkqueueExecuteEnd kWorkqueueExecuteEnd{};
+ template <typename T = WorkqueueExecuteEndFtraceEvent> T* set_workqueue_execute_end() {
+ return BeginNestedMessage<T>(57);
+ }
+
+
+ using FieldMetadata_WorkqueueExecuteStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 58,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ WorkqueueExecuteStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_WorkqueueExecuteStart kWorkqueueExecuteStart{};
+ template <typename T = WorkqueueExecuteStartFtraceEvent> T* set_workqueue_execute_start() {
+ return BeginNestedMessage<T>(58);
+ }
+
+
+ using FieldMetadata_WorkqueueQueueWork =
+ ::protozero::proto_utils::FieldMetadata<
+ 59,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ WorkqueueQueueWorkFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_WorkqueueQueueWork kWorkqueueQueueWork{};
+ template <typename T = WorkqueueQueueWorkFtraceEvent> T* set_workqueue_queue_work() {
+ return BeginNestedMessage<T>(59);
+ }
+
+
+ using FieldMetadata_RegulatorDisable =
+ ::protozero::proto_utils::FieldMetadata<
+ 60,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegulatorDisableFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RegulatorDisable kRegulatorDisable{};
+ template <typename T = RegulatorDisableFtraceEvent> T* set_regulator_disable() {
+ return BeginNestedMessage<T>(60);
+ }
+
+
+ using FieldMetadata_RegulatorDisableComplete =
+ ::protozero::proto_utils::FieldMetadata<
+ 61,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegulatorDisableCompleteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RegulatorDisableComplete kRegulatorDisableComplete{};
+ template <typename T = RegulatorDisableCompleteFtraceEvent> T* set_regulator_disable_complete() {
+ return BeginNestedMessage<T>(61);
+ }
+
+
+ using FieldMetadata_RegulatorEnable =
+ ::protozero::proto_utils::FieldMetadata<
+ 62,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegulatorEnableFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RegulatorEnable kRegulatorEnable{};
+ template <typename T = RegulatorEnableFtraceEvent> T* set_regulator_enable() {
+ return BeginNestedMessage<T>(62);
+ }
+
+
+ using FieldMetadata_RegulatorEnableComplete =
+ ::protozero::proto_utils::FieldMetadata<
+ 63,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegulatorEnableCompleteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RegulatorEnableComplete kRegulatorEnableComplete{};
+ template <typename T = RegulatorEnableCompleteFtraceEvent> T* set_regulator_enable_complete() {
+ return BeginNestedMessage<T>(63);
+ }
+
+
+ using FieldMetadata_RegulatorEnableDelay =
+ ::protozero::proto_utils::FieldMetadata<
+ 64,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegulatorEnableDelayFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RegulatorEnableDelay kRegulatorEnableDelay{};
+ template <typename T = RegulatorEnableDelayFtraceEvent> T* set_regulator_enable_delay() {
+ return BeginNestedMessage<T>(64);
+ }
+
+
+ using FieldMetadata_RegulatorSetVoltage =
+ ::protozero::proto_utils::FieldMetadata<
+ 65,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegulatorSetVoltageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RegulatorSetVoltage kRegulatorSetVoltage{};
+ template <typename T = RegulatorSetVoltageFtraceEvent> T* set_regulator_set_voltage() {
+ return BeginNestedMessage<T>(65);
+ }
+
+
+ using FieldMetadata_RegulatorSetVoltageComplete =
+ ::protozero::proto_utils::FieldMetadata<
+ 66,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RegulatorSetVoltageCompleteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RegulatorSetVoltageComplete kRegulatorSetVoltageComplete{};
+ template <typename T = RegulatorSetVoltageCompleteFtraceEvent> T* set_regulator_set_voltage_complete() {
+ return BeginNestedMessage<T>(66);
+ }
+
+
+ using FieldMetadata_CgroupAttachTask =
+ ::protozero::proto_utils::FieldMetadata<
+ 67,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupAttachTaskFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupAttachTask kCgroupAttachTask{};
+ template <typename T = CgroupAttachTaskFtraceEvent> T* set_cgroup_attach_task() {
+ return BeginNestedMessage<T>(67);
+ }
+
+
+ using FieldMetadata_CgroupMkdir =
+ ::protozero::proto_utils::FieldMetadata<
+ 68,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupMkdirFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupMkdir kCgroupMkdir{};
+ template <typename T = CgroupMkdirFtraceEvent> T* set_cgroup_mkdir() {
+ return BeginNestedMessage<T>(68);
+ }
+
+
+ using FieldMetadata_CgroupRemount =
+ ::protozero::proto_utils::FieldMetadata<
+ 69,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupRemountFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupRemount kCgroupRemount{};
+ template <typename T = CgroupRemountFtraceEvent> T* set_cgroup_remount() {
+ return BeginNestedMessage<T>(69);
+ }
+
+
+ using FieldMetadata_CgroupRmdir =
+ ::protozero::proto_utils::FieldMetadata<
+ 70,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupRmdirFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupRmdir kCgroupRmdir{};
+ template <typename T = CgroupRmdirFtraceEvent> T* set_cgroup_rmdir() {
+ return BeginNestedMessage<T>(70);
+ }
+
+
+ using FieldMetadata_CgroupTransferTasks =
+ ::protozero::proto_utils::FieldMetadata<
+ 71,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupTransferTasksFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupTransferTasks kCgroupTransferTasks{};
+ template <typename T = CgroupTransferTasksFtraceEvent> T* set_cgroup_transfer_tasks() {
+ return BeginNestedMessage<T>(71);
+ }
+
+
+ using FieldMetadata_CgroupDestroyRoot =
+ ::protozero::proto_utils::FieldMetadata<
+ 72,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupDestroyRootFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupDestroyRoot kCgroupDestroyRoot{};
+ template <typename T = CgroupDestroyRootFtraceEvent> T* set_cgroup_destroy_root() {
+ return BeginNestedMessage<T>(72);
+ }
+
+
+ using FieldMetadata_CgroupRelease =
+ ::protozero::proto_utils::FieldMetadata<
+ 73,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupReleaseFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupRelease kCgroupRelease{};
+ template <typename T = CgroupReleaseFtraceEvent> T* set_cgroup_release() {
+ return BeginNestedMessage<T>(73);
+ }
+
+
+ using FieldMetadata_CgroupRename =
+ ::protozero::proto_utils::FieldMetadata<
+ 74,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupRenameFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupRename kCgroupRename{};
+ template <typename T = CgroupRenameFtraceEvent> T* set_cgroup_rename() {
+ return BeginNestedMessage<T>(74);
+ }
+
+
+ using FieldMetadata_CgroupSetupRoot =
+ ::protozero::proto_utils::FieldMetadata<
+ 75,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CgroupSetupRootFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CgroupSetupRoot kCgroupSetupRoot{};
+ template <typename T = CgroupSetupRootFtraceEvent> T* set_cgroup_setup_root() {
+ return BeginNestedMessage<T>(75);
+ }
+
+
+ using FieldMetadata_MdpCmdKickoff =
+ ::protozero::proto_utils::FieldMetadata<
+ 76,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpCmdKickoffFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpCmdKickoff kMdpCmdKickoff{};
+ template <typename T = MdpCmdKickoffFtraceEvent> T* set_mdp_cmd_kickoff() {
+ return BeginNestedMessage<T>(76);
+ }
+
+
+ using FieldMetadata_MdpCommit =
+ ::protozero::proto_utils::FieldMetadata<
+ 77,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpCommitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpCommit kMdpCommit{};
+ template <typename T = MdpCommitFtraceEvent> T* set_mdp_commit() {
+ return BeginNestedMessage<T>(77);
+ }
+
+
+ using FieldMetadata_MdpPerfSetOt =
+ ::protozero::proto_utils::FieldMetadata<
+ 78,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpPerfSetOtFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpPerfSetOt kMdpPerfSetOt{};
+ template <typename T = MdpPerfSetOtFtraceEvent> T* set_mdp_perf_set_ot() {
+ return BeginNestedMessage<T>(78);
+ }
+
+
+ using FieldMetadata_MdpSsppChange =
+ ::protozero::proto_utils::FieldMetadata<
+ 79,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpSsppChangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpSsppChange kMdpSsppChange{};
+ template <typename T = MdpSsppChangeFtraceEvent> T* set_mdp_sspp_change() {
+ return BeginNestedMessage<T>(79);
+ }
+
+
+ using FieldMetadata_TracingMarkWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 80,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TracingMarkWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TracingMarkWrite kTracingMarkWrite{};
+ template <typename T = TracingMarkWriteFtraceEvent> T* set_tracing_mark_write() {
+ return BeginNestedMessage<T>(80);
+ }
+
+
+ using FieldMetadata_MdpCmdPingpongDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 81,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpCmdPingpongDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpCmdPingpongDone kMdpCmdPingpongDone{};
+ template <typename T = MdpCmdPingpongDoneFtraceEvent> T* set_mdp_cmd_pingpong_done() {
+ return BeginNestedMessage<T>(81);
+ }
+
+
+ using FieldMetadata_MdpCompareBw =
+ ::protozero::proto_utils::FieldMetadata<
+ 82,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpCompareBwFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpCompareBw kMdpCompareBw{};
+ template <typename T = MdpCompareBwFtraceEvent> T* set_mdp_compare_bw() {
+ return BeginNestedMessage<T>(82);
+ }
+
+
+ using FieldMetadata_MdpPerfSetPanicLuts =
+ ::protozero::proto_utils::FieldMetadata<
+ 83,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpPerfSetPanicLutsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpPerfSetPanicLuts kMdpPerfSetPanicLuts{};
+ template <typename T = MdpPerfSetPanicLutsFtraceEvent> T* set_mdp_perf_set_panic_luts() {
+ return BeginNestedMessage<T>(83);
+ }
+
+
+ using FieldMetadata_MdpSsppSet =
+ ::protozero::proto_utils::FieldMetadata<
+ 84,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpSsppSetFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpSsppSet kMdpSsppSet{};
+ template <typename T = MdpSsppSetFtraceEvent> T* set_mdp_sspp_set() {
+ return BeginNestedMessage<T>(84);
+ }
+
+
+ using FieldMetadata_MdpCmdReadptrDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 85,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpCmdReadptrDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpCmdReadptrDone kMdpCmdReadptrDone{};
+ template <typename T = MdpCmdReadptrDoneFtraceEvent> T* set_mdp_cmd_readptr_done() {
+ return BeginNestedMessage<T>(85);
+ }
+
+
+ using FieldMetadata_MdpMisrCrc =
+ ::protozero::proto_utils::FieldMetadata<
+ 86,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpMisrCrcFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpMisrCrc kMdpMisrCrc{};
+ template <typename T = MdpMisrCrcFtraceEvent> T* set_mdp_misr_crc() {
+ return BeginNestedMessage<T>(86);
+ }
+
+
+ using FieldMetadata_MdpPerfSetQosLuts =
+ ::protozero::proto_utils::FieldMetadata<
+ 87,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpPerfSetQosLutsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpPerfSetQosLuts kMdpPerfSetQosLuts{};
+ template <typename T = MdpPerfSetQosLutsFtraceEvent> T* set_mdp_perf_set_qos_luts() {
+ return BeginNestedMessage<T>(87);
+ }
+
+
+ using FieldMetadata_MdpTraceCounter =
+ ::protozero::proto_utils::FieldMetadata<
+ 88,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpTraceCounterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpTraceCounter kMdpTraceCounter{};
+ template <typename T = MdpTraceCounterFtraceEvent> T* set_mdp_trace_counter() {
+ return BeginNestedMessage<T>(88);
+ }
+
+
+ using FieldMetadata_MdpCmdReleaseBw =
+ ::protozero::proto_utils::FieldMetadata<
+ 89,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpCmdReleaseBwFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpCmdReleaseBw kMdpCmdReleaseBw{};
+ template <typename T = MdpCmdReleaseBwFtraceEvent> T* set_mdp_cmd_release_bw() {
+ return BeginNestedMessage<T>(89);
+ }
+
+
+ using FieldMetadata_MdpMixerUpdate =
+ ::protozero::proto_utils::FieldMetadata<
+ 90,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpMixerUpdateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpMixerUpdate kMdpMixerUpdate{};
+ template <typename T = MdpMixerUpdateFtraceEvent> T* set_mdp_mixer_update() {
+ return BeginNestedMessage<T>(90);
+ }
+
+
+ using FieldMetadata_MdpPerfSetWmLevels =
+ ::protozero::proto_utils::FieldMetadata<
+ 91,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpPerfSetWmLevelsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpPerfSetWmLevels kMdpPerfSetWmLevels{};
+ template <typename T = MdpPerfSetWmLevelsFtraceEvent> T* set_mdp_perf_set_wm_levels() {
+ return BeginNestedMessage<T>(91);
+ }
+
+
+ using FieldMetadata_MdpVideoUnderrunDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 92,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpVideoUnderrunDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpVideoUnderrunDone kMdpVideoUnderrunDone{};
+ template <typename T = MdpVideoUnderrunDoneFtraceEvent> T* set_mdp_video_underrun_done() {
+ return BeginNestedMessage<T>(92);
+ }
+
+
+ using FieldMetadata_MdpCmdWaitPingpong =
+ ::protozero::proto_utils::FieldMetadata<
+ 93,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpCmdWaitPingpongFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpCmdWaitPingpong kMdpCmdWaitPingpong{};
+ template <typename T = MdpCmdWaitPingpongFtraceEvent> T* set_mdp_cmd_wait_pingpong() {
+ return BeginNestedMessage<T>(93);
+ }
+
+
+ using FieldMetadata_MdpPerfPrefillCalc =
+ ::protozero::proto_utils::FieldMetadata<
+ 94,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpPerfPrefillCalcFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpPerfPrefillCalc kMdpPerfPrefillCalc{};
+ template <typename T = MdpPerfPrefillCalcFtraceEvent> T* set_mdp_perf_prefill_calc() {
+ return BeginNestedMessage<T>(94);
+ }
+
+
+ using FieldMetadata_MdpPerfUpdateBus =
+ ::protozero::proto_utils::FieldMetadata<
+ 95,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MdpPerfUpdateBusFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MdpPerfUpdateBus kMdpPerfUpdateBus{};
+ template <typename T = MdpPerfUpdateBusFtraceEvent> T* set_mdp_perf_update_bus() {
+ return BeginNestedMessage<T>(95);
+ }
+
+
+ using FieldMetadata_RotatorBwAoAsContext =
+ ::protozero::proto_utils::FieldMetadata<
+ 96,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RotatorBwAoAsContextFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RotatorBwAoAsContext kRotatorBwAoAsContext{};
+ template <typename T = RotatorBwAoAsContextFtraceEvent> T* set_rotator_bw_ao_as_context() {
+ return BeginNestedMessage<T>(96);
+ }
+
+
+ using FieldMetadata_MmFilemapAddToPageCache =
+ ::protozero::proto_utils::FieldMetadata<
+ 97,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmFilemapAddToPageCacheFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmFilemapAddToPageCache kMmFilemapAddToPageCache{};
+ template <typename T = MmFilemapAddToPageCacheFtraceEvent> T* set_mm_filemap_add_to_page_cache() {
+ return BeginNestedMessage<T>(97);
+ }
+
+
+ using FieldMetadata_MmFilemapDeleteFromPageCache =
+ ::protozero::proto_utils::FieldMetadata<
+ 98,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmFilemapDeleteFromPageCacheFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmFilemapDeleteFromPageCache kMmFilemapDeleteFromPageCache{};
+ template <typename T = MmFilemapDeleteFromPageCacheFtraceEvent> T* set_mm_filemap_delete_from_page_cache() {
+ return BeginNestedMessage<T>(98);
+ }
+
+
+ using FieldMetadata_MmCompactionBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 99,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionBeginFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionBegin kMmCompactionBegin{};
+ template <typename T = MmCompactionBeginFtraceEvent> T* set_mm_compaction_begin() {
+ return BeginNestedMessage<T>(99);
+ }
+
+
+ using FieldMetadata_MmCompactionDeferCompaction =
+ ::protozero::proto_utils::FieldMetadata<
+ 100,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionDeferCompactionFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionDeferCompaction kMmCompactionDeferCompaction{};
+ template <typename T = MmCompactionDeferCompactionFtraceEvent> T* set_mm_compaction_defer_compaction() {
+ return BeginNestedMessage<T>(100);
+ }
+
+
+ using FieldMetadata_MmCompactionDeferred =
+ ::protozero::proto_utils::FieldMetadata<
+ 101,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionDeferredFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionDeferred kMmCompactionDeferred{};
+ template <typename T = MmCompactionDeferredFtraceEvent> T* set_mm_compaction_deferred() {
+ return BeginNestedMessage<T>(101);
+ }
+
+
+ using FieldMetadata_MmCompactionDeferReset =
+ ::protozero::proto_utils::FieldMetadata<
+ 102,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionDeferResetFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionDeferReset kMmCompactionDeferReset{};
+ template <typename T = MmCompactionDeferResetFtraceEvent> T* set_mm_compaction_defer_reset() {
+ return BeginNestedMessage<T>(102);
+ }
+
+
+ using FieldMetadata_MmCompactionEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 103,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionEnd kMmCompactionEnd{};
+ template <typename T = MmCompactionEndFtraceEvent> T* set_mm_compaction_end() {
+ return BeginNestedMessage<T>(103);
+ }
+
+
+ using FieldMetadata_MmCompactionFinished =
+ ::protozero::proto_utils::FieldMetadata<
+ 104,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionFinishedFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionFinished kMmCompactionFinished{};
+ template <typename T = MmCompactionFinishedFtraceEvent> T* set_mm_compaction_finished() {
+ return BeginNestedMessage<T>(104);
+ }
+
+
+ using FieldMetadata_MmCompactionIsolateFreepages =
+ ::protozero::proto_utils::FieldMetadata<
+ 105,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionIsolateFreepagesFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionIsolateFreepages kMmCompactionIsolateFreepages{};
+ template <typename T = MmCompactionIsolateFreepagesFtraceEvent> T* set_mm_compaction_isolate_freepages() {
+ return BeginNestedMessage<T>(105);
+ }
+
+
+ using FieldMetadata_MmCompactionIsolateMigratepages =
+ ::protozero::proto_utils::FieldMetadata<
+ 106,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionIsolateMigratepagesFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionIsolateMigratepages kMmCompactionIsolateMigratepages{};
+ template <typename T = MmCompactionIsolateMigratepagesFtraceEvent> T* set_mm_compaction_isolate_migratepages() {
+ return BeginNestedMessage<T>(106);
+ }
+
+
+ using FieldMetadata_MmCompactionKcompactdSleep =
+ ::protozero::proto_utils::FieldMetadata<
+ 107,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionKcompactdSleepFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionKcompactdSleep kMmCompactionKcompactdSleep{};
+ template <typename T = MmCompactionKcompactdSleepFtraceEvent> T* set_mm_compaction_kcompactd_sleep() {
+ return BeginNestedMessage<T>(107);
+ }
+
+
+ using FieldMetadata_MmCompactionKcompactdWake =
+ ::protozero::proto_utils::FieldMetadata<
+ 108,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionKcompactdWakeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionKcompactdWake kMmCompactionKcompactdWake{};
+ template <typename T = MmCompactionKcompactdWakeFtraceEvent> T* set_mm_compaction_kcompactd_wake() {
+ return BeginNestedMessage<T>(108);
+ }
+
+
+ using FieldMetadata_MmCompactionMigratepages =
+ ::protozero::proto_utils::FieldMetadata<
+ 109,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionMigratepagesFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionMigratepages kMmCompactionMigratepages{};
+ template <typename T = MmCompactionMigratepagesFtraceEvent> T* set_mm_compaction_migratepages() {
+ return BeginNestedMessage<T>(109);
+ }
+
+
+ using FieldMetadata_MmCompactionSuitable =
+ ::protozero::proto_utils::FieldMetadata<
+ 110,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionSuitableFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionSuitable kMmCompactionSuitable{};
+ template <typename T = MmCompactionSuitableFtraceEvent> T* set_mm_compaction_suitable() {
+ return BeginNestedMessage<T>(110);
+ }
+
+
+ using FieldMetadata_MmCompactionTryToCompactPages =
+ ::protozero::proto_utils::FieldMetadata<
+ 111,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionTryToCompactPagesFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionTryToCompactPages kMmCompactionTryToCompactPages{};
+ template <typename T = MmCompactionTryToCompactPagesFtraceEvent> T* set_mm_compaction_try_to_compact_pages() {
+ return BeginNestedMessage<T>(111);
+ }
+
+
+ using FieldMetadata_MmCompactionWakeupKcompactd =
+ ::protozero::proto_utils::FieldMetadata<
+ 112,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmCompactionWakeupKcompactdFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmCompactionWakeupKcompactd kMmCompactionWakeupKcompactd{};
+ template <typename T = MmCompactionWakeupKcompactdFtraceEvent> T* set_mm_compaction_wakeup_kcompactd() {
+ return BeginNestedMessage<T>(112);
+ }
+
+
+ using FieldMetadata_SuspendResume =
+ ::protozero::proto_utils::FieldMetadata<
+ 113,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SuspendResumeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SuspendResume kSuspendResume{};
+ template <typename T = SuspendResumeFtraceEvent> T* set_suspend_resume() {
+ return BeginNestedMessage<T>(113);
+ }
+
+
+ using FieldMetadata_SchedWakeupNew =
+ ::protozero::proto_utils::FieldMetadata<
+ 114,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedWakeupNewFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedWakeupNew kSchedWakeupNew{};
+ template <typename T = SchedWakeupNewFtraceEvent> T* set_sched_wakeup_new() {
+ return BeginNestedMessage<T>(114);
+ }
+
+
+ using FieldMetadata_BlockBioBackmerge =
+ ::protozero::proto_utils::FieldMetadata<
+ 115,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockBioBackmergeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockBioBackmerge kBlockBioBackmerge{};
+ template <typename T = BlockBioBackmergeFtraceEvent> T* set_block_bio_backmerge() {
+ return BeginNestedMessage<T>(115);
+ }
+
+
+ using FieldMetadata_BlockBioBounce =
+ ::protozero::proto_utils::FieldMetadata<
+ 116,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockBioBounceFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockBioBounce kBlockBioBounce{};
+ template <typename T = BlockBioBounceFtraceEvent> T* set_block_bio_bounce() {
+ return BeginNestedMessage<T>(116);
+ }
+
+
+ using FieldMetadata_BlockBioComplete =
+ ::protozero::proto_utils::FieldMetadata<
+ 117,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockBioCompleteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockBioComplete kBlockBioComplete{};
+ template <typename T = BlockBioCompleteFtraceEvent> T* set_block_bio_complete() {
+ return BeginNestedMessage<T>(117);
+ }
+
+
+ using FieldMetadata_BlockBioFrontmerge =
+ ::protozero::proto_utils::FieldMetadata<
+ 118,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockBioFrontmergeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockBioFrontmerge kBlockBioFrontmerge{};
+ template <typename T = BlockBioFrontmergeFtraceEvent> T* set_block_bio_frontmerge() {
+ return BeginNestedMessage<T>(118);
+ }
+
+
+ using FieldMetadata_BlockBioQueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 119,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockBioQueueFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockBioQueue kBlockBioQueue{};
+ template <typename T = BlockBioQueueFtraceEvent> T* set_block_bio_queue() {
+ return BeginNestedMessage<T>(119);
+ }
+
+
+ using FieldMetadata_BlockBioRemap =
+ ::protozero::proto_utils::FieldMetadata<
+ 120,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockBioRemapFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockBioRemap kBlockBioRemap{};
+ template <typename T = BlockBioRemapFtraceEvent> T* set_block_bio_remap() {
+ return BeginNestedMessage<T>(120);
+ }
+
+
+ using FieldMetadata_BlockDirtyBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 121,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockDirtyBufferFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockDirtyBuffer kBlockDirtyBuffer{};
+ template <typename T = BlockDirtyBufferFtraceEvent> T* set_block_dirty_buffer() {
+ return BeginNestedMessage<T>(121);
+ }
+
+
+ using FieldMetadata_BlockGetrq =
+ ::protozero::proto_utils::FieldMetadata<
+ 122,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockGetrqFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockGetrq kBlockGetrq{};
+ template <typename T = BlockGetrqFtraceEvent> T* set_block_getrq() {
+ return BeginNestedMessage<T>(122);
+ }
+
+
+ using FieldMetadata_BlockPlug =
+ ::protozero::proto_utils::FieldMetadata<
+ 123,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockPlugFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockPlug kBlockPlug{};
+ template <typename T = BlockPlugFtraceEvent> T* set_block_plug() {
+ return BeginNestedMessage<T>(123);
+ }
+
+
+ using FieldMetadata_BlockRqAbort =
+ ::protozero::proto_utils::FieldMetadata<
+ 124,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockRqAbortFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockRqAbort kBlockRqAbort{};
+ template <typename T = BlockRqAbortFtraceEvent> T* set_block_rq_abort() {
+ return BeginNestedMessage<T>(124);
+ }
+
+
+ using FieldMetadata_BlockRqComplete =
+ ::protozero::proto_utils::FieldMetadata<
+ 125,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockRqCompleteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockRqComplete kBlockRqComplete{};
+ template <typename T = BlockRqCompleteFtraceEvent> T* set_block_rq_complete() {
+ return BeginNestedMessage<T>(125);
+ }
+
+
+ using FieldMetadata_BlockRqInsert =
+ ::protozero::proto_utils::FieldMetadata<
+ 126,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockRqInsertFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockRqInsert kBlockRqInsert{};
+ template <typename T = BlockRqInsertFtraceEvent> T* set_block_rq_insert() {
+ return BeginNestedMessage<T>(126);
+ }
+
+
+ using FieldMetadata_BlockRqRemap =
+ ::protozero::proto_utils::FieldMetadata<
+ 128,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockRqRemapFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockRqRemap kBlockRqRemap{};
+ template <typename T = BlockRqRemapFtraceEvent> T* set_block_rq_remap() {
+ return BeginNestedMessage<T>(128);
+ }
+
+
+ using FieldMetadata_BlockRqRequeue =
+ ::protozero::proto_utils::FieldMetadata<
+ 129,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockRqRequeueFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockRqRequeue kBlockRqRequeue{};
+ template <typename T = BlockRqRequeueFtraceEvent> T* set_block_rq_requeue() {
+ return BeginNestedMessage<T>(129);
+ }
+
+
+ using FieldMetadata_BlockSleeprq =
+ ::protozero::proto_utils::FieldMetadata<
+ 130,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockSleeprqFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockSleeprq kBlockSleeprq{};
+ template <typename T = BlockSleeprqFtraceEvent> T* set_block_sleeprq() {
+ return BeginNestedMessage<T>(130);
+ }
+
+
+ using FieldMetadata_BlockSplit =
+ ::protozero::proto_utils::FieldMetadata<
+ 131,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockSplitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockSplit kBlockSplit{};
+ template <typename T = BlockSplitFtraceEvent> T* set_block_split() {
+ return BeginNestedMessage<T>(131);
+ }
+
+
+ using FieldMetadata_BlockTouchBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 132,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockTouchBufferFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockTouchBuffer kBlockTouchBuffer{};
+ template <typename T = BlockTouchBufferFtraceEvent> T* set_block_touch_buffer() {
+ return BeginNestedMessage<T>(132);
+ }
+
+
+ using FieldMetadata_BlockUnplug =
+ ::protozero::proto_utils::FieldMetadata<
+ 133,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BlockUnplugFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BlockUnplug kBlockUnplug{};
+ template <typename T = BlockUnplugFtraceEvent> T* set_block_unplug() {
+ return BeginNestedMessage<T>(133);
+ }
+
+
+ using FieldMetadata_Ext4AllocDaBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 134,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4AllocDaBlocksFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4AllocDaBlocks kExt4AllocDaBlocks{};
+ template <typename T = Ext4AllocDaBlocksFtraceEvent> T* set_ext4_alloc_da_blocks() {
+ return BeginNestedMessage<T>(134);
+ }
+
+
+ using FieldMetadata_Ext4AllocateBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 135,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4AllocateBlocksFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4AllocateBlocks kExt4AllocateBlocks{};
+ template <typename T = Ext4AllocateBlocksFtraceEvent> T* set_ext4_allocate_blocks() {
+ return BeginNestedMessage<T>(135);
+ }
+
+
+ using FieldMetadata_Ext4AllocateInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 136,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4AllocateInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4AllocateInode kExt4AllocateInode{};
+ template <typename T = Ext4AllocateInodeFtraceEvent> T* set_ext4_allocate_inode() {
+ return BeginNestedMessage<T>(136);
+ }
+
+
+ using FieldMetadata_Ext4BeginOrderedTruncate =
+ ::protozero::proto_utils::FieldMetadata<
+ 137,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4BeginOrderedTruncateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4BeginOrderedTruncate kExt4BeginOrderedTruncate{};
+ template <typename T = Ext4BeginOrderedTruncateFtraceEvent> T* set_ext4_begin_ordered_truncate() {
+ return BeginNestedMessage<T>(137);
+ }
+
+
+ using FieldMetadata_Ext4CollapseRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 138,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4CollapseRangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4CollapseRange kExt4CollapseRange{};
+ template <typename T = Ext4CollapseRangeFtraceEvent> T* set_ext4_collapse_range() {
+ return BeginNestedMessage<T>(138);
+ }
+
+
+ using FieldMetadata_Ext4DaReleaseSpace =
+ ::protozero::proto_utils::FieldMetadata<
+ 139,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DaReleaseSpaceFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DaReleaseSpace kExt4DaReleaseSpace{};
+ template <typename T = Ext4DaReleaseSpaceFtraceEvent> T* set_ext4_da_release_space() {
+ return BeginNestedMessage<T>(139);
+ }
+
+
+ using FieldMetadata_Ext4DaReserveSpace =
+ ::protozero::proto_utils::FieldMetadata<
+ 140,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DaReserveSpaceFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DaReserveSpace kExt4DaReserveSpace{};
+ template <typename T = Ext4DaReserveSpaceFtraceEvent> T* set_ext4_da_reserve_space() {
+ return BeginNestedMessage<T>(140);
+ }
+
+
+ using FieldMetadata_Ext4DaUpdateReserveSpace =
+ ::protozero::proto_utils::FieldMetadata<
+ 141,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DaUpdateReserveSpaceFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DaUpdateReserveSpace kExt4DaUpdateReserveSpace{};
+ template <typename T = Ext4DaUpdateReserveSpaceFtraceEvent> T* set_ext4_da_update_reserve_space() {
+ return BeginNestedMessage<T>(141);
+ }
+
+
+ using FieldMetadata_Ext4DaWritePages =
+ ::protozero::proto_utils::FieldMetadata<
+ 142,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DaWritePagesFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DaWritePages kExt4DaWritePages{};
+ template <typename T = Ext4DaWritePagesFtraceEvent> T* set_ext4_da_write_pages() {
+ return BeginNestedMessage<T>(142);
+ }
+
+
+ using FieldMetadata_Ext4DaWritePagesExtent =
+ ::protozero::proto_utils::FieldMetadata<
+ 143,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DaWritePagesExtentFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DaWritePagesExtent kExt4DaWritePagesExtent{};
+ template <typename T = Ext4DaWritePagesExtentFtraceEvent> T* set_ext4_da_write_pages_extent() {
+ return BeginNestedMessage<T>(143);
+ }
+
+
+ using FieldMetadata_Ext4DirectIOEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 144,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DirectIOEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DirectIOEnter kExt4DirectIOEnter{};
+ template <typename T = Ext4DirectIOEnterFtraceEvent> T* set_ext4_direct_io_enter() {
+ return BeginNestedMessage<T>(144);
+ }
+
+
+ using FieldMetadata_Ext4DirectIOExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 145,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DirectIOExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DirectIOExit kExt4DirectIOExit{};
+ template <typename T = Ext4DirectIOExitFtraceEvent> T* set_ext4_direct_io_exit() {
+ return BeginNestedMessage<T>(145);
+ }
+
+
+ using FieldMetadata_Ext4DiscardBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 146,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DiscardBlocksFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DiscardBlocks kExt4DiscardBlocks{};
+ template <typename T = Ext4DiscardBlocksFtraceEvent> T* set_ext4_discard_blocks() {
+ return BeginNestedMessage<T>(146);
+ }
+
+
+ using FieldMetadata_Ext4DiscardPreallocations =
+ ::protozero::proto_utils::FieldMetadata<
+ 147,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DiscardPreallocationsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DiscardPreallocations kExt4DiscardPreallocations{};
+ template <typename T = Ext4DiscardPreallocationsFtraceEvent> T* set_ext4_discard_preallocations() {
+ return BeginNestedMessage<T>(147);
+ }
+
+
+ using FieldMetadata_Ext4DropInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 148,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4DropInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4DropInode kExt4DropInode{};
+ template <typename T = Ext4DropInodeFtraceEvent> T* set_ext4_drop_inode() {
+ return BeginNestedMessage<T>(148);
+ }
+
+
+ using FieldMetadata_Ext4EsCacheExtent =
+ ::protozero::proto_utils::FieldMetadata<
+ 149,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsCacheExtentFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsCacheExtent kExt4EsCacheExtent{};
+ template <typename T = Ext4EsCacheExtentFtraceEvent> T* set_ext4_es_cache_extent() {
+ return BeginNestedMessage<T>(149);
+ }
+
+
+ using FieldMetadata_Ext4EsFindDelayedExtentRangeEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 150,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsFindDelayedExtentRangeEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsFindDelayedExtentRangeEnter kExt4EsFindDelayedExtentRangeEnter{};
+ template <typename T = Ext4EsFindDelayedExtentRangeEnterFtraceEvent> T* set_ext4_es_find_delayed_extent_range_enter() {
+ return BeginNestedMessage<T>(150);
+ }
+
+
+ using FieldMetadata_Ext4EsFindDelayedExtentRangeExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 151,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsFindDelayedExtentRangeExit kExt4EsFindDelayedExtentRangeExit{};
+ template <typename T = Ext4EsFindDelayedExtentRangeExitFtraceEvent> T* set_ext4_es_find_delayed_extent_range_exit() {
+ return BeginNestedMessage<T>(151);
+ }
+
+
+ using FieldMetadata_Ext4EsInsertExtent =
+ ::protozero::proto_utils::FieldMetadata<
+ 152,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsInsertExtentFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsInsertExtent kExt4EsInsertExtent{};
+ template <typename T = Ext4EsInsertExtentFtraceEvent> T* set_ext4_es_insert_extent() {
+ return BeginNestedMessage<T>(152);
+ }
+
+
+ using FieldMetadata_Ext4EsLookupExtentEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 153,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsLookupExtentEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsLookupExtentEnter kExt4EsLookupExtentEnter{};
+ template <typename T = Ext4EsLookupExtentEnterFtraceEvent> T* set_ext4_es_lookup_extent_enter() {
+ return BeginNestedMessage<T>(153);
+ }
+
+
+ using FieldMetadata_Ext4EsLookupExtentExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 154,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsLookupExtentExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsLookupExtentExit kExt4EsLookupExtentExit{};
+ template <typename T = Ext4EsLookupExtentExitFtraceEvent> T* set_ext4_es_lookup_extent_exit() {
+ return BeginNestedMessage<T>(154);
+ }
+
+
+ using FieldMetadata_Ext4EsRemoveExtent =
+ ::protozero::proto_utils::FieldMetadata<
+ 155,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsRemoveExtentFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsRemoveExtent kExt4EsRemoveExtent{};
+ template <typename T = Ext4EsRemoveExtentFtraceEvent> T* set_ext4_es_remove_extent() {
+ return BeginNestedMessage<T>(155);
+ }
+
+
+ using FieldMetadata_Ext4EsShrink =
+ ::protozero::proto_utils::FieldMetadata<
+ 156,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsShrinkFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsShrink kExt4EsShrink{};
+ template <typename T = Ext4EsShrinkFtraceEvent> T* set_ext4_es_shrink() {
+ return BeginNestedMessage<T>(156);
+ }
+
+
+ using FieldMetadata_Ext4EsShrinkCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 157,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsShrinkCountFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsShrinkCount kExt4EsShrinkCount{};
+ template <typename T = Ext4EsShrinkCountFtraceEvent> T* set_ext4_es_shrink_count() {
+ return BeginNestedMessage<T>(157);
+ }
+
+
+ using FieldMetadata_Ext4EsShrinkScanEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 158,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsShrinkScanEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsShrinkScanEnter kExt4EsShrinkScanEnter{};
+ template <typename T = Ext4EsShrinkScanEnterFtraceEvent> T* set_ext4_es_shrink_scan_enter() {
+ return BeginNestedMessage<T>(158);
+ }
+
+
+ using FieldMetadata_Ext4EsShrinkScanExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 159,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EsShrinkScanExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EsShrinkScanExit kExt4EsShrinkScanExit{};
+ template <typename T = Ext4EsShrinkScanExitFtraceEvent> T* set_ext4_es_shrink_scan_exit() {
+ return BeginNestedMessage<T>(159);
+ }
+
+
+ using FieldMetadata_Ext4EvictInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 160,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4EvictInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4EvictInode kExt4EvictInode{};
+ template <typename T = Ext4EvictInodeFtraceEvent> T* set_ext4_evict_inode() {
+ return BeginNestedMessage<T>(160);
+ }
+
+
+ using FieldMetadata_Ext4ExtConvertToInitializedEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 161,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtConvertToInitializedEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtConvertToInitializedEnter kExt4ExtConvertToInitializedEnter{};
+ template <typename T = Ext4ExtConvertToInitializedEnterFtraceEvent> T* set_ext4_ext_convert_to_initialized_enter() {
+ return BeginNestedMessage<T>(161);
+ }
+
+
+ using FieldMetadata_Ext4ExtConvertToInitializedFastpath =
+ ::protozero::proto_utils::FieldMetadata<
+ 162,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtConvertToInitializedFastpath kExt4ExtConvertToInitializedFastpath{};
+ template <typename T = Ext4ExtConvertToInitializedFastpathFtraceEvent> T* set_ext4_ext_convert_to_initialized_fastpath() {
+ return BeginNestedMessage<T>(162);
+ }
+
+
+ using FieldMetadata_Ext4ExtHandleUnwrittenExtents =
+ ::protozero::proto_utils::FieldMetadata<
+ 163,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtHandleUnwrittenExtents kExt4ExtHandleUnwrittenExtents{};
+ template <typename T = Ext4ExtHandleUnwrittenExtentsFtraceEvent> T* set_ext4_ext_handle_unwritten_extents() {
+ return BeginNestedMessage<T>(163);
+ }
+
+
+ using FieldMetadata_Ext4ExtInCache =
+ ::protozero::proto_utils::FieldMetadata<
+ 164,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtInCacheFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtInCache kExt4ExtInCache{};
+ template <typename T = Ext4ExtInCacheFtraceEvent> T* set_ext4_ext_in_cache() {
+ return BeginNestedMessage<T>(164);
+ }
+
+
+ using FieldMetadata_Ext4ExtLoadExtent =
+ ::protozero::proto_utils::FieldMetadata<
+ 165,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtLoadExtentFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtLoadExtent kExt4ExtLoadExtent{};
+ template <typename T = Ext4ExtLoadExtentFtraceEvent> T* set_ext4_ext_load_extent() {
+ return BeginNestedMessage<T>(165);
+ }
+
+
+ using FieldMetadata_Ext4ExtMapBlocksEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 166,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtMapBlocksEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtMapBlocksEnter kExt4ExtMapBlocksEnter{};
+ template <typename T = Ext4ExtMapBlocksEnterFtraceEvent> T* set_ext4_ext_map_blocks_enter() {
+ return BeginNestedMessage<T>(166);
+ }
+
+
+ using FieldMetadata_Ext4ExtMapBlocksExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 167,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtMapBlocksExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtMapBlocksExit kExt4ExtMapBlocksExit{};
+ template <typename T = Ext4ExtMapBlocksExitFtraceEvent> T* set_ext4_ext_map_blocks_exit() {
+ return BeginNestedMessage<T>(167);
+ }
+
+
+ using FieldMetadata_Ext4ExtPutInCache =
+ ::protozero::proto_utils::FieldMetadata<
+ 168,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtPutInCacheFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtPutInCache kExt4ExtPutInCache{};
+ template <typename T = Ext4ExtPutInCacheFtraceEvent> T* set_ext4_ext_put_in_cache() {
+ return BeginNestedMessage<T>(168);
+ }
+
+
+ using FieldMetadata_Ext4ExtRemoveSpace =
+ ::protozero::proto_utils::FieldMetadata<
+ 169,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtRemoveSpaceFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtRemoveSpace kExt4ExtRemoveSpace{};
+ template <typename T = Ext4ExtRemoveSpaceFtraceEvent> T* set_ext4_ext_remove_space() {
+ return BeginNestedMessage<T>(169);
+ }
+
+
+ using FieldMetadata_Ext4ExtRemoveSpaceDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 170,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtRemoveSpaceDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtRemoveSpaceDone kExt4ExtRemoveSpaceDone{};
+ template <typename T = Ext4ExtRemoveSpaceDoneFtraceEvent> T* set_ext4_ext_remove_space_done() {
+ return BeginNestedMessage<T>(170);
+ }
+
+
+ using FieldMetadata_Ext4ExtRmIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 171,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtRmIdxFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtRmIdx kExt4ExtRmIdx{};
+ template <typename T = Ext4ExtRmIdxFtraceEvent> T* set_ext4_ext_rm_idx() {
+ return BeginNestedMessage<T>(171);
+ }
+
+
+ using FieldMetadata_Ext4ExtRmLeaf =
+ ::protozero::proto_utils::FieldMetadata<
+ 172,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtRmLeafFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtRmLeaf kExt4ExtRmLeaf{};
+ template <typename T = Ext4ExtRmLeafFtraceEvent> T* set_ext4_ext_rm_leaf() {
+ return BeginNestedMessage<T>(172);
+ }
+
+
+ using FieldMetadata_Ext4ExtShowExtent =
+ ::protozero::proto_utils::FieldMetadata<
+ 173,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ExtShowExtentFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ExtShowExtent kExt4ExtShowExtent{};
+ template <typename T = Ext4ExtShowExtentFtraceEvent> T* set_ext4_ext_show_extent() {
+ return BeginNestedMessage<T>(173);
+ }
+
+
+ using FieldMetadata_Ext4FallocateEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 174,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4FallocateEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4FallocateEnter kExt4FallocateEnter{};
+ template <typename T = Ext4FallocateEnterFtraceEvent> T* set_ext4_fallocate_enter() {
+ return BeginNestedMessage<T>(174);
+ }
+
+
+ using FieldMetadata_Ext4FallocateExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 175,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4FallocateExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4FallocateExit kExt4FallocateExit{};
+ template <typename T = Ext4FallocateExitFtraceEvent> T* set_ext4_fallocate_exit() {
+ return BeginNestedMessage<T>(175);
+ }
+
+
+ using FieldMetadata_Ext4FindDelallocRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 176,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4FindDelallocRangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4FindDelallocRange kExt4FindDelallocRange{};
+ template <typename T = Ext4FindDelallocRangeFtraceEvent> T* set_ext4_find_delalloc_range() {
+ return BeginNestedMessage<T>(176);
+ }
+
+
+ using FieldMetadata_Ext4Forget =
+ ::protozero::proto_utils::FieldMetadata<
+ 177,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ForgetFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4Forget kExt4Forget{};
+ template <typename T = Ext4ForgetFtraceEvent> T* set_ext4_forget() {
+ return BeginNestedMessage<T>(177);
+ }
+
+
+ using FieldMetadata_Ext4FreeBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 178,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4FreeBlocksFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4FreeBlocks kExt4FreeBlocks{};
+ template <typename T = Ext4FreeBlocksFtraceEvent> T* set_ext4_free_blocks() {
+ return BeginNestedMessage<T>(178);
+ }
+
+
+ using FieldMetadata_Ext4FreeInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 179,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4FreeInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4FreeInode kExt4FreeInode{};
+ template <typename T = Ext4FreeInodeFtraceEvent> T* set_ext4_free_inode() {
+ return BeginNestedMessage<T>(179);
+ }
+
+
+ using FieldMetadata_Ext4GetImpliedClusterAllocExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 180,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4GetImpliedClusterAllocExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4GetImpliedClusterAllocExit kExt4GetImpliedClusterAllocExit{};
+ template <typename T = Ext4GetImpliedClusterAllocExitFtraceEvent> T* set_ext4_get_implied_cluster_alloc_exit() {
+ return BeginNestedMessage<T>(180);
+ }
+
+
+ using FieldMetadata_Ext4GetReservedClusterAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 181,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4GetReservedClusterAllocFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4GetReservedClusterAlloc kExt4GetReservedClusterAlloc{};
+ template <typename T = Ext4GetReservedClusterAllocFtraceEvent> T* set_ext4_get_reserved_cluster_alloc() {
+ return BeginNestedMessage<T>(181);
+ }
+
+
+ using FieldMetadata_Ext4IndMapBlocksEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 182,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4IndMapBlocksEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4IndMapBlocksEnter kExt4IndMapBlocksEnter{};
+ template <typename T = Ext4IndMapBlocksEnterFtraceEvent> T* set_ext4_ind_map_blocks_enter() {
+ return BeginNestedMessage<T>(182);
+ }
+
+
+ using FieldMetadata_Ext4IndMapBlocksExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 183,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4IndMapBlocksExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4IndMapBlocksExit kExt4IndMapBlocksExit{};
+ template <typename T = Ext4IndMapBlocksExitFtraceEvent> T* set_ext4_ind_map_blocks_exit() {
+ return BeginNestedMessage<T>(183);
+ }
+
+
+ using FieldMetadata_Ext4InsertRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 184,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4InsertRangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4InsertRange kExt4InsertRange{};
+ template <typename T = Ext4InsertRangeFtraceEvent> T* set_ext4_insert_range() {
+ return BeginNestedMessage<T>(184);
+ }
+
+
+ using FieldMetadata_Ext4Invalidatepage =
+ ::protozero::proto_utils::FieldMetadata<
+ 185,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4InvalidatepageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4Invalidatepage kExt4Invalidatepage{};
+ template <typename T = Ext4InvalidatepageFtraceEvent> T* set_ext4_invalidatepage() {
+ return BeginNestedMessage<T>(185);
+ }
+
+
+ using FieldMetadata_Ext4JournalStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 186,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4JournalStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4JournalStart kExt4JournalStart{};
+ template <typename T = Ext4JournalStartFtraceEvent> T* set_ext4_journal_start() {
+ return BeginNestedMessage<T>(186);
+ }
+
+
+ using FieldMetadata_Ext4JournalStartReserved =
+ ::protozero::proto_utils::FieldMetadata<
+ 187,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4JournalStartReservedFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4JournalStartReserved kExt4JournalStartReserved{};
+ template <typename T = Ext4JournalStartReservedFtraceEvent> T* set_ext4_journal_start_reserved() {
+ return BeginNestedMessage<T>(187);
+ }
+
+
+ using FieldMetadata_Ext4JournalledInvalidatepage =
+ ::protozero::proto_utils::FieldMetadata<
+ 188,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4JournalledInvalidatepageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4JournalledInvalidatepage kExt4JournalledInvalidatepage{};
+ template <typename T = Ext4JournalledInvalidatepageFtraceEvent> T* set_ext4_journalled_invalidatepage() {
+ return BeginNestedMessage<T>(188);
+ }
+
+
+ using FieldMetadata_Ext4JournalledWriteEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 189,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4JournalledWriteEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4JournalledWriteEnd kExt4JournalledWriteEnd{};
+ template <typename T = Ext4JournalledWriteEndFtraceEvent> T* set_ext4_journalled_write_end() {
+ return BeginNestedMessage<T>(189);
+ }
+
+
+ using FieldMetadata_Ext4LoadInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 190,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4LoadInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4LoadInode kExt4LoadInode{};
+ template <typename T = Ext4LoadInodeFtraceEvent> T* set_ext4_load_inode() {
+ return BeginNestedMessage<T>(190);
+ }
+
+
+ using FieldMetadata_Ext4LoadInodeBitmap =
+ ::protozero::proto_utils::FieldMetadata<
+ 191,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4LoadInodeBitmapFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4LoadInodeBitmap kExt4LoadInodeBitmap{};
+ template <typename T = Ext4LoadInodeBitmapFtraceEvent> T* set_ext4_load_inode_bitmap() {
+ return BeginNestedMessage<T>(191);
+ }
+
+
+ using FieldMetadata_Ext4MarkInodeDirty =
+ ::protozero::proto_utils::FieldMetadata<
+ 192,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MarkInodeDirtyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MarkInodeDirty kExt4MarkInodeDirty{};
+ template <typename T = Ext4MarkInodeDirtyFtraceEvent> T* set_ext4_mark_inode_dirty() {
+ return BeginNestedMessage<T>(192);
+ }
+
+
+ using FieldMetadata_Ext4MbBitmapLoad =
+ ::protozero::proto_utils::FieldMetadata<
+ 193,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MbBitmapLoadFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MbBitmapLoad kExt4MbBitmapLoad{};
+ template <typename T = Ext4MbBitmapLoadFtraceEvent> T* set_ext4_mb_bitmap_load() {
+ return BeginNestedMessage<T>(193);
+ }
+
+
+ using FieldMetadata_Ext4MbBuddyBitmapLoad =
+ ::protozero::proto_utils::FieldMetadata<
+ 194,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MbBuddyBitmapLoadFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MbBuddyBitmapLoad kExt4MbBuddyBitmapLoad{};
+ template <typename T = Ext4MbBuddyBitmapLoadFtraceEvent> T* set_ext4_mb_buddy_bitmap_load() {
+ return BeginNestedMessage<T>(194);
+ }
+
+
+ using FieldMetadata_Ext4MbDiscardPreallocations =
+ ::protozero::proto_utils::FieldMetadata<
+ 195,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MbDiscardPreallocationsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MbDiscardPreallocations kExt4MbDiscardPreallocations{};
+ template <typename T = Ext4MbDiscardPreallocationsFtraceEvent> T* set_ext4_mb_discard_preallocations() {
+ return BeginNestedMessage<T>(195);
+ }
+
+
+ using FieldMetadata_Ext4MbNewGroupPa =
+ ::protozero::proto_utils::FieldMetadata<
+ 196,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MbNewGroupPaFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MbNewGroupPa kExt4MbNewGroupPa{};
+ template <typename T = Ext4MbNewGroupPaFtraceEvent> T* set_ext4_mb_new_group_pa() {
+ return BeginNestedMessage<T>(196);
+ }
+
+
+ using FieldMetadata_Ext4MbNewInodePa =
+ ::protozero::proto_utils::FieldMetadata<
+ 197,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MbNewInodePaFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MbNewInodePa kExt4MbNewInodePa{};
+ template <typename T = Ext4MbNewInodePaFtraceEvent> T* set_ext4_mb_new_inode_pa() {
+ return BeginNestedMessage<T>(197);
+ }
+
+
+ using FieldMetadata_Ext4MbReleaseGroupPa =
+ ::protozero::proto_utils::FieldMetadata<
+ 198,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MbReleaseGroupPaFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MbReleaseGroupPa kExt4MbReleaseGroupPa{};
+ template <typename T = Ext4MbReleaseGroupPaFtraceEvent> T* set_ext4_mb_release_group_pa() {
+ return BeginNestedMessage<T>(198);
+ }
+
+
+ using FieldMetadata_Ext4MbReleaseInodePa =
+ ::protozero::proto_utils::FieldMetadata<
+ 199,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MbReleaseInodePaFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MbReleaseInodePa kExt4MbReleaseInodePa{};
+ template <typename T = Ext4MbReleaseInodePaFtraceEvent> T* set_ext4_mb_release_inode_pa() {
+ return BeginNestedMessage<T>(199);
+ }
+
+
+ using FieldMetadata_Ext4MballocAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 200,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MballocAllocFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MballocAlloc kExt4MballocAlloc{};
+ template <typename T = Ext4MballocAllocFtraceEvent> T* set_ext4_mballoc_alloc() {
+ return BeginNestedMessage<T>(200);
+ }
+
+
+ using FieldMetadata_Ext4MballocDiscard =
+ ::protozero::proto_utils::FieldMetadata<
+ 201,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MballocDiscardFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MballocDiscard kExt4MballocDiscard{};
+ template <typename T = Ext4MballocDiscardFtraceEvent> T* set_ext4_mballoc_discard() {
+ return BeginNestedMessage<T>(201);
+ }
+
+
+ using FieldMetadata_Ext4MballocFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 202,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MballocFreeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MballocFree kExt4MballocFree{};
+ template <typename T = Ext4MballocFreeFtraceEvent> T* set_ext4_mballoc_free() {
+ return BeginNestedMessage<T>(202);
+ }
+
+
+ using FieldMetadata_Ext4MballocPrealloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 203,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4MballocPreallocFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4MballocPrealloc kExt4MballocPrealloc{};
+ template <typename T = Ext4MballocPreallocFtraceEvent> T* set_ext4_mballoc_prealloc() {
+ return BeginNestedMessage<T>(203);
+ }
+
+
+ using FieldMetadata_Ext4OtherInodeUpdateTime =
+ ::protozero::proto_utils::FieldMetadata<
+ 204,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4OtherInodeUpdateTimeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4OtherInodeUpdateTime kExt4OtherInodeUpdateTime{};
+ template <typename T = Ext4OtherInodeUpdateTimeFtraceEvent> T* set_ext4_other_inode_update_time() {
+ return BeginNestedMessage<T>(204);
+ }
+
+
+ using FieldMetadata_Ext4PunchHole =
+ ::protozero::proto_utils::FieldMetadata<
+ 205,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4PunchHoleFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4PunchHole kExt4PunchHole{};
+ template <typename T = Ext4PunchHoleFtraceEvent> T* set_ext4_punch_hole() {
+ return BeginNestedMessage<T>(205);
+ }
+
+
+ using FieldMetadata_Ext4ReadBlockBitmapLoad =
+ ::protozero::proto_utils::FieldMetadata<
+ 206,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ReadBlockBitmapLoadFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ReadBlockBitmapLoad kExt4ReadBlockBitmapLoad{};
+ template <typename T = Ext4ReadBlockBitmapLoadFtraceEvent> T* set_ext4_read_block_bitmap_load() {
+ return BeginNestedMessage<T>(206);
+ }
+
+
+ using FieldMetadata_Ext4Readpage =
+ ::protozero::proto_utils::FieldMetadata<
+ 207,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ReadpageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4Readpage kExt4Readpage{};
+ template <typename T = Ext4ReadpageFtraceEvent> T* set_ext4_readpage() {
+ return BeginNestedMessage<T>(207);
+ }
+
+
+ using FieldMetadata_Ext4Releasepage =
+ ::protozero::proto_utils::FieldMetadata<
+ 208,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ReleasepageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4Releasepage kExt4Releasepage{};
+ template <typename T = Ext4ReleasepageFtraceEvent> T* set_ext4_releasepage() {
+ return BeginNestedMessage<T>(208);
+ }
+
+
+ using FieldMetadata_Ext4RemoveBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 209,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4RemoveBlocksFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4RemoveBlocks kExt4RemoveBlocks{};
+ template <typename T = Ext4RemoveBlocksFtraceEvent> T* set_ext4_remove_blocks() {
+ return BeginNestedMessage<T>(209);
+ }
+
+
+ using FieldMetadata_Ext4RequestBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 210,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4RequestBlocksFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4RequestBlocks kExt4RequestBlocks{};
+ template <typename T = Ext4RequestBlocksFtraceEvent> T* set_ext4_request_blocks() {
+ return BeginNestedMessage<T>(210);
+ }
+
+
+ using FieldMetadata_Ext4RequestInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 211,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4RequestInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4RequestInode kExt4RequestInode{};
+ template <typename T = Ext4RequestInodeFtraceEvent> T* set_ext4_request_inode() {
+ return BeginNestedMessage<T>(211);
+ }
+
+
+ using FieldMetadata_Ext4SyncFs =
+ ::protozero::proto_utils::FieldMetadata<
+ 212,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4SyncFsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4SyncFs kExt4SyncFs{};
+ template <typename T = Ext4SyncFsFtraceEvent> T* set_ext4_sync_fs() {
+ return BeginNestedMessage<T>(212);
+ }
+
+
+ using FieldMetadata_Ext4TrimAllFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 213,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4TrimAllFreeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4TrimAllFree kExt4TrimAllFree{};
+ template <typename T = Ext4TrimAllFreeFtraceEvent> T* set_ext4_trim_all_free() {
+ return BeginNestedMessage<T>(213);
+ }
+
+
+ using FieldMetadata_Ext4TrimExtent =
+ ::protozero::proto_utils::FieldMetadata<
+ 214,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4TrimExtentFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4TrimExtent kExt4TrimExtent{};
+ template <typename T = Ext4TrimExtentFtraceEvent> T* set_ext4_trim_extent() {
+ return BeginNestedMessage<T>(214);
+ }
+
+
+ using FieldMetadata_Ext4TruncateEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 215,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4TruncateEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4TruncateEnter kExt4TruncateEnter{};
+ template <typename T = Ext4TruncateEnterFtraceEvent> T* set_ext4_truncate_enter() {
+ return BeginNestedMessage<T>(215);
+ }
+
+
+ using FieldMetadata_Ext4TruncateExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 216,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4TruncateExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4TruncateExit kExt4TruncateExit{};
+ template <typename T = Ext4TruncateExitFtraceEvent> T* set_ext4_truncate_exit() {
+ return BeginNestedMessage<T>(216);
+ }
+
+
+ using FieldMetadata_Ext4UnlinkEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 217,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4UnlinkEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4UnlinkEnter kExt4UnlinkEnter{};
+ template <typename T = Ext4UnlinkEnterFtraceEvent> T* set_ext4_unlink_enter() {
+ return BeginNestedMessage<T>(217);
+ }
+
+
+ using FieldMetadata_Ext4UnlinkExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 218,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4UnlinkExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4UnlinkExit kExt4UnlinkExit{};
+ template <typename T = Ext4UnlinkExitFtraceEvent> T* set_ext4_unlink_exit() {
+ return BeginNestedMessage<T>(218);
+ }
+
+
+ using FieldMetadata_Ext4WriteBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 219,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4WriteBeginFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4WriteBegin kExt4WriteBegin{};
+ template <typename T = Ext4WriteBeginFtraceEvent> T* set_ext4_write_begin() {
+ return BeginNestedMessage<T>(219);
+ }
+
+
+ using FieldMetadata_Ext4WriteEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 230,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4WriteEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4WriteEnd kExt4WriteEnd{};
+ template <typename T = Ext4WriteEndFtraceEvent> T* set_ext4_write_end() {
+ return BeginNestedMessage<T>(230);
+ }
+
+
+ using FieldMetadata_Ext4Writepage =
+ ::protozero::proto_utils::FieldMetadata<
+ 231,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4WritepageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4Writepage kExt4Writepage{};
+ template <typename T = Ext4WritepageFtraceEvent> T* set_ext4_writepage() {
+ return BeginNestedMessage<T>(231);
+ }
+
+
+ using FieldMetadata_Ext4Writepages =
+ ::protozero::proto_utils::FieldMetadata<
+ 232,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4WritepagesFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4Writepages kExt4Writepages{};
+ template <typename T = Ext4WritepagesFtraceEvent> T* set_ext4_writepages() {
+ return BeginNestedMessage<T>(232);
+ }
+
+
+ using FieldMetadata_Ext4WritepagesResult =
+ ::protozero::proto_utils::FieldMetadata<
+ 233,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4WritepagesResultFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4WritepagesResult kExt4WritepagesResult{};
+ template <typename T = Ext4WritepagesResultFtraceEvent> T* set_ext4_writepages_result() {
+ return BeginNestedMessage<T>(233);
+ }
+
+
+ using FieldMetadata_Ext4ZeroRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 234,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Ext4ZeroRangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Ext4ZeroRange kExt4ZeroRange{};
+ template <typename T = Ext4ZeroRangeFtraceEvent> T* set_ext4_zero_range() {
+ return BeginNestedMessage<T>(234);
+ }
+
+
+ using FieldMetadata_TaskNewtask =
+ ::protozero::proto_utils::FieldMetadata<
+ 235,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TaskNewtaskFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TaskNewtask kTaskNewtask{};
+ template <typename T = TaskNewtaskFtraceEvent> T* set_task_newtask() {
+ return BeginNestedMessage<T>(235);
+ }
+
+
+ using FieldMetadata_TaskRename =
+ ::protozero::proto_utils::FieldMetadata<
+ 236,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TaskRenameFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TaskRename kTaskRename{};
+ template <typename T = TaskRenameFtraceEvent> T* set_task_rename() {
+ return BeginNestedMessage<T>(236);
+ }
+
+
+ using FieldMetadata_SchedProcessExec =
+ ::protozero::proto_utils::FieldMetadata<
+ 237,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedProcessExecFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedProcessExec kSchedProcessExec{};
+ template <typename T = SchedProcessExecFtraceEvent> T* set_sched_process_exec() {
+ return BeginNestedMessage<T>(237);
+ }
+
+
+ using FieldMetadata_SchedProcessExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 238,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedProcessExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedProcessExit kSchedProcessExit{};
+ template <typename T = SchedProcessExitFtraceEvent> T* set_sched_process_exit() {
+ return BeginNestedMessage<T>(238);
+ }
+
+
+ using FieldMetadata_SchedProcessFork =
+ ::protozero::proto_utils::FieldMetadata<
+ 239,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedProcessForkFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedProcessFork kSchedProcessFork{};
+ template <typename T = SchedProcessForkFtraceEvent> T* set_sched_process_fork() {
+ return BeginNestedMessage<T>(239);
+ }
+
+
+ using FieldMetadata_SchedProcessFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 240,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedProcessFreeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedProcessFree kSchedProcessFree{};
+ template <typename T = SchedProcessFreeFtraceEvent> T* set_sched_process_free() {
+ return BeginNestedMessage<T>(240);
+ }
+
+
+ using FieldMetadata_SchedProcessHang =
+ ::protozero::proto_utils::FieldMetadata<
+ 241,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedProcessHangFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedProcessHang kSchedProcessHang{};
+ template <typename T = SchedProcessHangFtraceEvent> T* set_sched_process_hang() {
+ return BeginNestedMessage<T>(241);
+ }
+
+
+ using FieldMetadata_SchedProcessWait =
+ ::protozero::proto_utils::FieldMetadata<
+ 242,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedProcessWaitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedProcessWait kSchedProcessWait{};
+ template <typename T = SchedProcessWaitFtraceEvent> T* set_sched_process_wait() {
+ return BeginNestedMessage<T>(242);
+ }
+
+
+ using FieldMetadata_F2fsDoSubmitBio =
+ ::protozero::proto_utils::FieldMetadata<
+ 243,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsDoSubmitBioFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsDoSubmitBio kF2fsDoSubmitBio{};
+ template <typename T = F2fsDoSubmitBioFtraceEvent> T* set_f2fs_do_submit_bio() {
+ return BeginNestedMessage<T>(243);
+ }
+
+
+ using FieldMetadata_F2fsEvictInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 244,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsEvictInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsEvictInode kF2fsEvictInode{};
+ template <typename T = F2fsEvictInodeFtraceEvent> T* set_f2fs_evict_inode() {
+ return BeginNestedMessage<T>(244);
+ }
+
+
+ using FieldMetadata_F2fsFallocate =
+ ::protozero::proto_utils::FieldMetadata<
+ 245,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsFallocateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsFallocate kF2fsFallocate{};
+ template <typename T = F2fsFallocateFtraceEvent> T* set_f2fs_fallocate() {
+ return BeginNestedMessage<T>(245);
+ }
+
+
+ using FieldMetadata_F2fsGetDataBlock =
+ ::protozero::proto_utils::FieldMetadata<
+ 246,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsGetDataBlockFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsGetDataBlock kF2fsGetDataBlock{};
+ template <typename T = F2fsGetDataBlockFtraceEvent> T* set_f2fs_get_data_block() {
+ return BeginNestedMessage<T>(246);
+ }
+
+
+ using FieldMetadata_F2fsGetVictim =
+ ::protozero::proto_utils::FieldMetadata<
+ 247,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsGetVictimFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsGetVictim kF2fsGetVictim{};
+ template <typename T = F2fsGetVictimFtraceEvent> T* set_f2fs_get_victim() {
+ return BeginNestedMessage<T>(247);
+ }
+
+
+ using FieldMetadata_F2fsIget =
+ ::protozero::proto_utils::FieldMetadata<
+ 248,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsIgetFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsIget kF2fsIget{};
+ template <typename T = F2fsIgetFtraceEvent> T* set_f2fs_iget() {
+ return BeginNestedMessage<T>(248);
+ }
+
+
+ using FieldMetadata_F2fsIgetExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 249,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsIgetExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsIgetExit kF2fsIgetExit{};
+ template <typename T = F2fsIgetExitFtraceEvent> T* set_f2fs_iget_exit() {
+ return BeginNestedMessage<T>(249);
+ }
+
+
+ using FieldMetadata_F2fsNewInode =
+ ::protozero::proto_utils::FieldMetadata<
+ 250,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsNewInodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsNewInode kF2fsNewInode{};
+ template <typename T = F2fsNewInodeFtraceEvent> T* set_f2fs_new_inode() {
+ return BeginNestedMessage<T>(250);
+ }
+
+
+ using FieldMetadata_F2fsReadpage =
+ ::protozero::proto_utils::FieldMetadata<
+ 251,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsReadpageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsReadpage kF2fsReadpage{};
+ template <typename T = F2fsReadpageFtraceEvent> T* set_f2fs_readpage() {
+ return BeginNestedMessage<T>(251);
+ }
+
+
+ using FieldMetadata_F2fsReserveNewBlock =
+ ::protozero::proto_utils::FieldMetadata<
+ 252,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsReserveNewBlockFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsReserveNewBlock kF2fsReserveNewBlock{};
+ template <typename T = F2fsReserveNewBlockFtraceEvent> T* set_f2fs_reserve_new_block() {
+ return BeginNestedMessage<T>(252);
+ }
+
+
+ using FieldMetadata_F2fsSetPageDirty =
+ ::protozero::proto_utils::FieldMetadata<
+ 253,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsSetPageDirtyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsSetPageDirty kF2fsSetPageDirty{};
+ template <typename T = F2fsSetPageDirtyFtraceEvent> T* set_f2fs_set_page_dirty() {
+ return BeginNestedMessage<T>(253);
+ }
+
+
+ using FieldMetadata_F2fsSubmitWritePage =
+ ::protozero::proto_utils::FieldMetadata<
+ 254,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsSubmitWritePageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsSubmitWritePage kF2fsSubmitWritePage{};
+ template <typename T = F2fsSubmitWritePageFtraceEvent> T* set_f2fs_submit_write_page() {
+ return BeginNestedMessage<T>(254);
+ }
+
+
+ using FieldMetadata_F2fsSyncFileEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 255,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsSyncFileEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsSyncFileEnter kF2fsSyncFileEnter{};
+ template <typename T = F2fsSyncFileEnterFtraceEvent> T* set_f2fs_sync_file_enter() {
+ return BeginNestedMessage<T>(255);
+ }
+
+
+ using FieldMetadata_F2fsSyncFileExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 256,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsSyncFileExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsSyncFileExit kF2fsSyncFileExit{};
+ template <typename T = F2fsSyncFileExitFtraceEvent> T* set_f2fs_sync_file_exit() {
+ return BeginNestedMessage<T>(256);
+ }
+
+
+ using FieldMetadata_F2fsSyncFs =
+ ::protozero::proto_utils::FieldMetadata<
+ 257,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsSyncFsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsSyncFs kF2fsSyncFs{};
+ template <typename T = F2fsSyncFsFtraceEvent> T* set_f2fs_sync_fs() {
+ return BeginNestedMessage<T>(257);
+ }
+
+
+ using FieldMetadata_F2fsTruncate =
+ ::protozero::proto_utils::FieldMetadata<
+ 258,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncate kF2fsTruncate{};
+ template <typename T = F2fsTruncateFtraceEvent> T* set_f2fs_truncate() {
+ return BeginNestedMessage<T>(258);
+ }
+
+
+ using FieldMetadata_F2fsTruncateBlocksEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 259,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateBlocksEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateBlocksEnter kF2fsTruncateBlocksEnter{};
+ template <typename T = F2fsTruncateBlocksEnterFtraceEvent> T* set_f2fs_truncate_blocks_enter() {
+ return BeginNestedMessage<T>(259);
+ }
+
+
+ using FieldMetadata_F2fsTruncateBlocksExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 260,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateBlocksExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateBlocksExit kF2fsTruncateBlocksExit{};
+ template <typename T = F2fsTruncateBlocksExitFtraceEvent> T* set_f2fs_truncate_blocks_exit() {
+ return BeginNestedMessage<T>(260);
+ }
+
+
+ using FieldMetadata_F2fsTruncateDataBlocksRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 261,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateDataBlocksRangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateDataBlocksRange kF2fsTruncateDataBlocksRange{};
+ template <typename T = F2fsTruncateDataBlocksRangeFtraceEvent> T* set_f2fs_truncate_data_blocks_range() {
+ return BeginNestedMessage<T>(261);
+ }
+
+
+ using FieldMetadata_F2fsTruncateInodeBlocksEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 262,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateInodeBlocksEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateInodeBlocksEnter kF2fsTruncateInodeBlocksEnter{};
+ template <typename T = F2fsTruncateInodeBlocksEnterFtraceEvent> T* set_f2fs_truncate_inode_blocks_enter() {
+ return BeginNestedMessage<T>(262);
+ }
+
+
+ using FieldMetadata_F2fsTruncateInodeBlocksExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 263,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateInodeBlocksExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateInodeBlocksExit kF2fsTruncateInodeBlocksExit{};
+ template <typename T = F2fsTruncateInodeBlocksExitFtraceEvent> T* set_f2fs_truncate_inode_blocks_exit() {
+ return BeginNestedMessage<T>(263);
+ }
+
+
+ using FieldMetadata_F2fsTruncateNode =
+ ::protozero::proto_utils::FieldMetadata<
+ 264,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateNodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateNode kF2fsTruncateNode{};
+ template <typename T = F2fsTruncateNodeFtraceEvent> T* set_f2fs_truncate_node() {
+ return BeginNestedMessage<T>(264);
+ }
+
+
+ using FieldMetadata_F2fsTruncateNodesEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 265,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateNodesEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateNodesEnter kF2fsTruncateNodesEnter{};
+ template <typename T = F2fsTruncateNodesEnterFtraceEvent> T* set_f2fs_truncate_nodes_enter() {
+ return BeginNestedMessage<T>(265);
+ }
+
+
+ using FieldMetadata_F2fsTruncateNodesExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 266,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncateNodesExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncateNodesExit kF2fsTruncateNodesExit{};
+ template <typename T = F2fsTruncateNodesExitFtraceEvent> T* set_f2fs_truncate_nodes_exit() {
+ return BeginNestedMessage<T>(266);
+ }
+
+
+ using FieldMetadata_F2fsTruncatePartialNodes =
+ ::protozero::proto_utils::FieldMetadata<
+ 267,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsTruncatePartialNodesFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsTruncatePartialNodes kF2fsTruncatePartialNodes{};
+ template <typename T = F2fsTruncatePartialNodesFtraceEvent> T* set_f2fs_truncate_partial_nodes() {
+ return BeginNestedMessage<T>(267);
+ }
+
+
+ using FieldMetadata_F2fsUnlinkEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 268,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsUnlinkEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsUnlinkEnter kF2fsUnlinkEnter{};
+ template <typename T = F2fsUnlinkEnterFtraceEvent> T* set_f2fs_unlink_enter() {
+ return BeginNestedMessage<T>(268);
+ }
+
+
+ using FieldMetadata_F2fsUnlinkExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 269,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsUnlinkExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsUnlinkExit kF2fsUnlinkExit{};
+ template <typename T = F2fsUnlinkExitFtraceEvent> T* set_f2fs_unlink_exit() {
+ return BeginNestedMessage<T>(269);
+ }
+
+
+ using FieldMetadata_F2fsVmPageMkwrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 270,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsVmPageMkwriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsVmPageMkwrite kF2fsVmPageMkwrite{};
+ template <typename T = F2fsVmPageMkwriteFtraceEvent> T* set_f2fs_vm_page_mkwrite() {
+ return BeginNestedMessage<T>(270);
+ }
+
+
+ using FieldMetadata_F2fsWriteBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 271,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsWriteBeginFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsWriteBegin kF2fsWriteBegin{};
+ template <typename T = F2fsWriteBeginFtraceEvent> T* set_f2fs_write_begin() {
+ return BeginNestedMessage<T>(271);
+ }
+
+
+ using FieldMetadata_F2fsWriteCheckpoint =
+ ::protozero::proto_utils::FieldMetadata<
+ 272,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsWriteCheckpointFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsWriteCheckpoint kF2fsWriteCheckpoint{};
+ template <typename T = F2fsWriteCheckpointFtraceEvent> T* set_f2fs_write_checkpoint() {
+ return BeginNestedMessage<T>(272);
+ }
+
+
+ using FieldMetadata_F2fsWriteEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 273,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsWriteEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsWriteEnd kF2fsWriteEnd{};
+ template <typename T = F2fsWriteEndFtraceEvent> T* set_f2fs_write_end() {
+ return BeginNestedMessage<T>(273);
+ }
+
+
+ using FieldMetadata_AllocPagesIommuEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 274,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AllocPagesIommuEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AllocPagesIommuEnd kAllocPagesIommuEnd{};
+ template <typename T = AllocPagesIommuEndFtraceEvent> T* set_alloc_pages_iommu_end() {
+ return BeginNestedMessage<T>(274);
+ }
+
+
+ using FieldMetadata_AllocPagesIommuFail =
+ ::protozero::proto_utils::FieldMetadata<
+ 275,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AllocPagesIommuFailFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AllocPagesIommuFail kAllocPagesIommuFail{};
+ template <typename T = AllocPagesIommuFailFtraceEvent> T* set_alloc_pages_iommu_fail() {
+ return BeginNestedMessage<T>(275);
+ }
+
+
+ using FieldMetadata_AllocPagesIommuStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 276,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AllocPagesIommuStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AllocPagesIommuStart kAllocPagesIommuStart{};
+ template <typename T = AllocPagesIommuStartFtraceEvent> T* set_alloc_pages_iommu_start() {
+ return BeginNestedMessage<T>(276);
+ }
+
+
+ using FieldMetadata_AllocPagesSysEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 277,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AllocPagesSysEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AllocPagesSysEnd kAllocPagesSysEnd{};
+ template <typename T = AllocPagesSysEndFtraceEvent> T* set_alloc_pages_sys_end() {
+ return BeginNestedMessage<T>(277);
+ }
+
+
+ using FieldMetadata_AllocPagesSysFail =
+ ::protozero::proto_utils::FieldMetadata<
+ 278,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AllocPagesSysFailFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AllocPagesSysFail kAllocPagesSysFail{};
+ template <typename T = AllocPagesSysFailFtraceEvent> T* set_alloc_pages_sys_fail() {
+ return BeginNestedMessage<T>(278);
+ }
+
+
+ using FieldMetadata_AllocPagesSysStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 279,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AllocPagesSysStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AllocPagesSysStart kAllocPagesSysStart{};
+ template <typename T = AllocPagesSysStartFtraceEvent> T* set_alloc_pages_sys_start() {
+ return BeginNestedMessage<T>(279);
+ }
+
+
+ using FieldMetadata_DmaAllocContiguousRetry =
+ ::protozero::proto_utils::FieldMetadata<
+ 280,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DmaAllocContiguousRetryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DmaAllocContiguousRetry kDmaAllocContiguousRetry{};
+ template <typename T = DmaAllocContiguousRetryFtraceEvent> T* set_dma_alloc_contiguous_retry() {
+ return BeginNestedMessage<T>(280);
+ }
+
+
+ using FieldMetadata_IommuMapRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 281,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IommuMapRangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IommuMapRange kIommuMapRange{};
+ template <typename T = IommuMapRangeFtraceEvent> T* set_iommu_map_range() {
+ return BeginNestedMessage<T>(281);
+ }
+
+
+ using FieldMetadata_IommuSecPtblMapRangeEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 282,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IommuSecPtblMapRangeEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IommuSecPtblMapRangeEnd kIommuSecPtblMapRangeEnd{};
+ template <typename T = IommuSecPtblMapRangeEndFtraceEvent> T* set_iommu_sec_ptbl_map_range_end() {
+ return BeginNestedMessage<T>(282);
+ }
+
+
+ using FieldMetadata_IommuSecPtblMapRangeStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 283,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IommuSecPtblMapRangeStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IommuSecPtblMapRangeStart kIommuSecPtblMapRangeStart{};
+ template <typename T = IommuSecPtblMapRangeStartFtraceEvent> T* set_iommu_sec_ptbl_map_range_start() {
+ return BeginNestedMessage<T>(283);
+ }
+
+
+ using FieldMetadata_IonAllocBufferEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 284,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonAllocBufferEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonAllocBufferEnd kIonAllocBufferEnd{};
+ template <typename T = IonAllocBufferEndFtraceEvent> T* set_ion_alloc_buffer_end() {
+ return BeginNestedMessage<T>(284);
+ }
+
+
+ using FieldMetadata_IonAllocBufferFail =
+ ::protozero::proto_utils::FieldMetadata<
+ 285,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonAllocBufferFailFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonAllocBufferFail kIonAllocBufferFail{};
+ template <typename T = IonAllocBufferFailFtraceEvent> T* set_ion_alloc_buffer_fail() {
+ return BeginNestedMessage<T>(285);
+ }
+
+
+ using FieldMetadata_IonAllocBufferFallback =
+ ::protozero::proto_utils::FieldMetadata<
+ 286,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonAllocBufferFallbackFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonAllocBufferFallback kIonAllocBufferFallback{};
+ template <typename T = IonAllocBufferFallbackFtraceEvent> T* set_ion_alloc_buffer_fallback() {
+ return BeginNestedMessage<T>(286);
+ }
+
+
+ using FieldMetadata_IonAllocBufferStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 287,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonAllocBufferStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonAllocBufferStart kIonAllocBufferStart{};
+ template <typename T = IonAllocBufferStartFtraceEvent> T* set_ion_alloc_buffer_start() {
+ return BeginNestedMessage<T>(287);
+ }
+
+
+ using FieldMetadata_IonCpAllocRetry =
+ ::protozero::proto_utils::FieldMetadata<
+ 288,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonCpAllocRetryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonCpAllocRetry kIonCpAllocRetry{};
+ template <typename T = IonCpAllocRetryFtraceEvent> T* set_ion_cp_alloc_retry() {
+ return BeginNestedMessage<T>(288);
+ }
+
+
+ using FieldMetadata_IonCpSecureBufferEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 289,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonCpSecureBufferEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonCpSecureBufferEnd kIonCpSecureBufferEnd{};
+ template <typename T = IonCpSecureBufferEndFtraceEvent> T* set_ion_cp_secure_buffer_end() {
+ return BeginNestedMessage<T>(289);
+ }
+
+
+ using FieldMetadata_IonCpSecureBufferStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 290,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonCpSecureBufferStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonCpSecureBufferStart kIonCpSecureBufferStart{};
+ template <typename T = IonCpSecureBufferStartFtraceEvent> T* set_ion_cp_secure_buffer_start() {
+ return BeginNestedMessage<T>(290);
+ }
+
+
+ using FieldMetadata_IonPrefetching =
+ ::protozero::proto_utils::FieldMetadata<
+ 291,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonPrefetchingFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonPrefetching kIonPrefetching{};
+ template <typename T = IonPrefetchingFtraceEvent> T* set_ion_prefetching() {
+ return BeginNestedMessage<T>(291);
+ }
+
+
+ using FieldMetadata_IonSecureCmaAddToPoolEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 292,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonSecureCmaAddToPoolEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonSecureCmaAddToPoolEnd kIonSecureCmaAddToPoolEnd{};
+ template <typename T = IonSecureCmaAddToPoolEndFtraceEvent> T* set_ion_secure_cma_add_to_pool_end() {
+ return BeginNestedMessage<T>(292);
+ }
+
+
+ using FieldMetadata_IonSecureCmaAddToPoolStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 293,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonSecureCmaAddToPoolStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonSecureCmaAddToPoolStart kIonSecureCmaAddToPoolStart{};
+ template <typename T = IonSecureCmaAddToPoolStartFtraceEvent> T* set_ion_secure_cma_add_to_pool_start() {
+ return BeginNestedMessage<T>(293);
+ }
+
+
+ using FieldMetadata_IonSecureCmaAllocateEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 294,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonSecureCmaAllocateEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonSecureCmaAllocateEnd kIonSecureCmaAllocateEnd{};
+ template <typename T = IonSecureCmaAllocateEndFtraceEvent> T* set_ion_secure_cma_allocate_end() {
+ return BeginNestedMessage<T>(294);
+ }
+
+
+ using FieldMetadata_IonSecureCmaAllocateStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 295,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonSecureCmaAllocateStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonSecureCmaAllocateStart kIonSecureCmaAllocateStart{};
+ template <typename T = IonSecureCmaAllocateStartFtraceEvent> T* set_ion_secure_cma_allocate_start() {
+ return BeginNestedMessage<T>(295);
+ }
+
+
+ using FieldMetadata_IonSecureCmaShrinkPoolEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 296,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonSecureCmaShrinkPoolEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonSecureCmaShrinkPoolEnd kIonSecureCmaShrinkPoolEnd{};
+ template <typename T = IonSecureCmaShrinkPoolEndFtraceEvent> T* set_ion_secure_cma_shrink_pool_end() {
+ return BeginNestedMessage<T>(296);
+ }
+
+
+ using FieldMetadata_IonSecureCmaShrinkPoolStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 297,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonSecureCmaShrinkPoolStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonSecureCmaShrinkPoolStart kIonSecureCmaShrinkPoolStart{};
+ template <typename T = IonSecureCmaShrinkPoolStartFtraceEvent> T* set_ion_secure_cma_shrink_pool_start() {
+ return BeginNestedMessage<T>(297);
+ }
+
+
+ using FieldMetadata_Kfree =
+ ::protozero::proto_utils::FieldMetadata<
+ 298,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KfreeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Kfree kKfree{};
+ template <typename T = KfreeFtraceEvent> T* set_kfree() {
+ return BeginNestedMessage<T>(298);
+ }
+
+
+ using FieldMetadata_Kmalloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 299,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KmallocFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Kmalloc kKmalloc{};
+ template <typename T = KmallocFtraceEvent> T* set_kmalloc() {
+ return BeginNestedMessage<T>(299);
+ }
+
+
+ using FieldMetadata_KmallocNode =
+ ::protozero::proto_utils::FieldMetadata<
+ 300,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KmallocNodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KmallocNode kKmallocNode{};
+ template <typename T = KmallocNodeFtraceEvent> T* set_kmalloc_node() {
+ return BeginNestedMessage<T>(300);
+ }
+
+
+ using FieldMetadata_KmemCacheAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 301,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KmemCacheAllocFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KmemCacheAlloc kKmemCacheAlloc{};
+ template <typename T = KmemCacheAllocFtraceEvent> T* set_kmem_cache_alloc() {
+ return BeginNestedMessage<T>(301);
+ }
+
+
+ using FieldMetadata_KmemCacheAllocNode =
+ ::protozero::proto_utils::FieldMetadata<
+ 302,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KmemCacheAllocNodeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KmemCacheAllocNode kKmemCacheAllocNode{};
+ template <typename T = KmemCacheAllocNodeFtraceEvent> T* set_kmem_cache_alloc_node() {
+ return BeginNestedMessage<T>(302);
+ }
+
+
+ using FieldMetadata_KmemCacheFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 303,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KmemCacheFreeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KmemCacheFree kKmemCacheFree{};
+ template <typename T = KmemCacheFreeFtraceEvent> T* set_kmem_cache_free() {
+ return BeginNestedMessage<T>(303);
+ }
+
+
+ using FieldMetadata_MigratePagesEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 304,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MigratePagesEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MigratePagesEnd kMigratePagesEnd{};
+ template <typename T = MigratePagesEndFtraceEvent> T* set_migrate_pages_end() {
+ return BeginNestedMessage<T>(304);
+ }
+
+
+ using FieldMetadata_MigratePagesStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 305,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MigratePagesStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MigratePagesStart kMigratePagesStart{};
+ template <typename T = MigratePagesStartFtraceEvent> T* set_migrate_pages_start() {
+ return BeginNestedMessage<T>(305);
+ }
+
+
+ using FieldMetadata_MigrateRetry =
+ ::protozero::proto_utils::FieldMetadata<
+ 306,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MigrateRetryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MigrateRetry kMigrateRetry{};
+ template <typename T = MigrateRetryFtraceEvent> T* set_migrate_retry() {
+ return BeginNestedMessage<T>(306);
+ }
+
+
+ using FieldMetadata_MmPageAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 307,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmPageAllocFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmPageAlloc kMmPageAlloc{};
+ template <typename T = MmPageAllocFtraceEvent> T* set_mm_page_alloc() {
+ return BeginNestedMessage<T>(307);
+ }
+
+
+ using FieldMetadata_MmPageAllocExtfrag =
+ ::protozero::proto_utils::FieldMetadata<
+ 308,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmPageAllocExtfragFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmPageAllocExtfrag kMmPageAllocExtfrag{};
+ template <typename T = MmPageAllocExtfragFtraceEvent> T* set_mm_page_alloc_extfrag() {
+ return BeginNestedMessage<T>(308);
+ }
+
+
+ using FieldMetadata_MmPageAllocZoneLocked =
+ ::protozero::proto_utils::FieldMetadata<
+ 309,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmPageAllocZoneLockedFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmPageAllocZoneLocked kMmPageAllocZoneLocked{};
+ template <typename T = MmPageAllocZoneLockedFtraceEvent> T* set_mm_page_alloc_zone_locked() {
+ return BeginNestedMessage<T>(309);
+ }
+
+
+ using FieldMetadata_MmPageFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 310,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmPageFreeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmPageFree kMmPageFree{};
+ template <typename T = MmPageFreeFtraceEvent> T* set_mm_page_free() {
+ return BeginNestedMessage<T>(310);
+ }
+
+
+ using FieldMetadata_MmPageFreeBatched =
+ ::protozero::proto_utils::FieldMetadata<
+ 311,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmPageFreeBatchedFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmPageFreeBatched kMmPageFreeBatched{};
+ template <typename T = MmPageFreeBatchedFtraceEvent> T* set_mm_page_free_batched() {
+ return BeginNestedMessage<T>(311);
+ }
+
+
+ using FieldMetadata_MmPagePcpuDrain =
+ ::protozero::proto_utils::FieldMetadata<
+ 312,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmPagePcpuDrainFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmPagePcpuDrain kMmPagePcpuDrain{};
+ template <typename T = MmPagePcpuDrainFtraceEvent> T* set_mm_page_pcpu_drain() {
+ return BeginNestedMessage<T>(312);
+ }
+
+
+ using FieldMetadata_RssStat =
+ ::protozero::proto_utils::FieldMetadata<
+ 313,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RssStatFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RssStat kRssStat{};
+ template <typename T = RssStatFtraceEvent> T* set_rss_stat() {
+ return BeginNestedMessage<T>(313);
+ }
+
+
+ using FieldMetadata_IonHeapShrink =
+ ::protozero::proto_utils::FieldMetadata<
+ 314,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonHeapShrinkFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonHeapShrink kIonHeapShrink{};
+ template <typename T = IonHeapShrinkFtraceEvent> T* set_ion_heap_shrink() {
+ return BeginNestedMessage<T>(314);
+ }
+
+
+ using FieldMetadata_IonHeapGrow =
+ ::protozero::proto_utils::FieldMetadata<
+ 315,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonHeapGrowFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonHeapGrow kIonHeapGrow{};
+ template <typename T = IonHeapGrowFtraceEvent> T* set_ion_heap_grow() {
+ return BeginNestedMessage<T>(315);
+ }
+
+
+ using FieldMetadata_FenceInit =
+ ::protozero::proto_utils::FieldMetadata<
+ 316,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FenceInitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_FenceInit kFenceInit{};
+ template <typename T = FenceInitFtraceEvent> T* set_fence_init() {
+ return BeginNestedMessage<T>(316);
+ }
+
+
+ using FieldMetadata_FenceDestroy =
+ ::protozero::proto_utils::FieldMetadata<
+ 317,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FenceDestroyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_FenceDestroy kFenceDestroy{};
+ template <typename T = FenceDestroyFtraceEvent> T* set_fence_destroy() {
+ return BeginNestedMessage<T>(317);
+ }
+
+
+ using FieldMetadata_FenceEnableSignal =
+ ::protozero::proto_utils::FieldMetadata<
+ 318,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FenceEnableSignalFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_FenceEnableSignal kFenceEnableSignal{};
+ template <typename T = FenceEnableSignalFtraceEvent> T* set_fence_enable_signal() {
+ return BeginNestedMessage<T>(318);
+ }
+
+
+ using FieldMetadata_FenceSignaled =
+ ::protozero::proto_utils::FieldMetadata<
+ 319,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FenceSignaledFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_FenceSignaled kFenceSignaled{};
+ template <typename T = FenceSignaledFtraceEvent> T* set_fence_signaled() {
+ return BeginNestedMessage<T>(319);
+ }
+
+
+ using FieldMetadata_ClkEnable =
+ ::protozero::proto_utils::FieldMetadata<
+ 320,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClkEnableFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ClkEnable kClkEnable{};
+ template <typename T = ClkEnableFtraceEvent> T* set_clk_enable() {
+ return BeginNestedMessage<T>(320);
+ }
+
+
+ using FieldMetadata_ClkDisable =
+ ::protozero::proto_utils::FieldMetadata<
+ 321,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClkDisableFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ClkDisable kClkDisable{};
+ template <typename T = ClkDisableFtraceEvent> T* set_clk_disable() {
+ return BeginNestedMessage<T>(321);
+ }
+
+
+ using FieldMetadata_ClkSetRate =
+ ::protozero::proto_utils::FieldMetadata<
+ 322,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClkSetRateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ClkSetRate kClkSetRate{};
+ template <typename T = ClkSetRateFtraceEvent> T* set_clk_set_rate() {
+ return BeginNestedMessage<T>(322);
+ }
+
+
+ using FieldMetadata_BinderTransactionAllocBuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 323,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderTransactionAllocBufFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderTransactionAllocBuf kBinderTransactionAllocBuf{};
+ template <typename T = BinderTransactionAllocBufFtraceEvent> T* set_binder_transaction_alloc_buf() {
+ return BeginNestedMessage<T>(323);
+ }
+
+
+ using FieldMetadata_SignalDeliver =
+ ::protozero::proto_utils::FieldMetadata<
+ 324,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SignalDeliverFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SignalDeliver kSignalDeliver{};
+ template <typename T = SignalDeliverFtraceEvent> T* set_signal_deliver() {
+ return BeginNestedMessage<T>(324);
+ }
+
+
+ using FieldMetadata_SignalGenerate =
+ ::protozero::proto_utils::FieldMetadata<
+ 325,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SignalGenerateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SignalGenerate kSignalGenerate{};
+ template <typename T = SignalGenerateFtraceEvent> T* set_signal_generate() {
+ return BeginNestedMessage<T>(325);
+ }
+
+
+ using FieldMetadata_OomScoreAdjUpdate =
+ ::protozero::proto_utils::FieldMetadata<
+ 326,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ OomScoreAdjUpdateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_OomScoreAdjUpdate kOomScoreAdjUpdate{};
+ template <typename T = OomScoreAdjUpdateFtraceEvent> T* set_oom_score_adj_update() {
+ return BeginNestedMessage<T>(326);
+ }
+
+
+ using FieldMetadata_Generic =
+ ::protozero::proto_utils::FieldMetadata<
+ 327,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GenericFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Generic kGeneric{};
+ template <typename T = GenericFtraceEvent> T* set_generic() {
+ return BeginNestedMessage<T>(327);
+ }
+
+
+ using FieldMetadata_MmEventRecord =
+ ::protozero::proto_utils::FieldMetadata<
+ 328,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmEventRecordFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmEventRecord kMmEventRecord{};
+ template <typename T = MmEventRecordFtraceEvent> T* set_mm_event_record() {
+ return BeginNestedMessage<T>(328);
+ }
+
+
+ using FieldMetadata_SysEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 329,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SysEnter kSysEnter{};
+ template <typename T = SysEnterFtraceEvent> T* set_sys_enter() {
+ return BeginNestedMessage<T>(329);
+ }
+
+
+ using FieldMetadata_SysExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 330,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SysExit kSysExit{};
+ template <typename T = SysExitFtraceEvent> T* set_sys_exit() {
+ return BeginNestedMessage<T>(330);
+ }
+
+
+ using FieldMetadata_Zero =
+ ::protozero::proto_utils::FieldMetadata<
+ 331,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ZeroFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Zero kZero{};
+ template <typename T = ZeroFtraceEvent> T* set_zero() {
+ return BeginNestedMessage<T>(331);
+ }
+
+
+ using FieldMetadata_GpuFrequency =
+ ::protozero::proto_utils::FieldMetadata<
+ 332,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuFrequencyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_GpuFrequency kGpuFrequency{};
+ template <typename T = GpuFrequencyFtraceEvent> T* set_gpu_frequency() {
+ return BeginNestedMessage<T>(332);
+ }
+
+
+ using FieldMetadata_SdeTracingMarkWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 333,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SdeTracingMarkWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SdeTracingMarkWrite kSdeTracingMarkWrite{};
+ template <typename T = SdeTracingMarkWriteFtraceEvent> T* set_sde_tracing_mark_write() {
+ return BeginNestedMessage<T>(333);
+ }
+
+
+ using FieldMetadata_MarkVictim =
+ ::protozero::proto_utils::FieldMetadata<
+ 334,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MarkVictimFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MarkVictim kMarkVictim{};
+ template <typename T = MarkVictimFtraceEvent> T* set_mark_victim() {
+ return BeginNestedMessage<T>(334);
+ }
+
+
+ using FieldMetadata_IonStat =
+ ::protozero::proto_utils::FieldMetadata<
+ 335,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonStatFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonStat kIonStat{};
+ template <typename T = IonStatFtraceEvent> T* set_ion_stat() {
+ return BeginNestedMessage<T>(335);
+ }
+
+
+ using FieldMetadata_IonBufferCreate =
+ ::protozero::proto_utils::FieldMetadata<
+ 336,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonBufferCreateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonBufferCreate kIonBufferCreate{};
+ template <typename T = IonBufferCreateFtraceEvent> T* set_ion_buffer_create() {
+ return BeginNestedMessage<T>(336);
+ }
+
+
+ using FieldMetadata_IonBufferDestroy =
+ ::protozero::proto_utils::FieldMetadata<
+ 337,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ IonBufferDestroyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_IonBufferDestroy kIonBufferDestroy{};
+ template <typename T = IonBufferDestroyFtraceEvent> T* set_ion_buffer_destroy() {
+ return BeginNestedMessage<T>(337);
+ }
+
+
+ using FieldMetadata_ScmCallStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 338,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ScmCallStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ScmCallStart kScmCallStart{};
+ template <typename T = ScmCallStartFtraceEvent> T* set_scm_call_start() {
+ return BeginNestedMessage<T>(338);
+ }
+
+
+ using FieldMetadata_ScmCallEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 339,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ScmCallEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ScmCallEnd kScmCallEnd{};
+ template <typename T = ScmCallEndFtraceEvent> T* set_scm_call_end() {
+ return BeginNestedMessage<T>(339);
+ }
+
+
+ using FieldMetadata_GpuMemTotal =
+ ::protozero::proto_utils::FieldMetadata<
+ 340,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuMemTotalFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_GpuMemTotal kGpuMemTotal{};
+ template <typename T = GpuMemTotalFtraceEvent> T* set_gpu_mem_total() {
+ return BeginNestedMessage<T>(340);
+ }
+
+
+ using FieldMetadata_ThermalTemperature =
+ ::protozero::proto_utils::FieldMetadata<
+ 341,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ThermalTemperatureFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_ThermalTemperature kThermalTemperature{};
+ template <typename T = ThermalTemperatureFtraceEvent> T* set_thermal_temperature() {
+ return BeginNestedMessage<T>(341);
+ }
+
+
+ using FieldMetadata_CdevUpdate =
+ ::protozero::proto_utils::FieldMetadata<
+ 342,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CdevUpdateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CdevUpdate kCdevUpdate{};
+ template <typename T = CdevUpdateFtraceEvent> T* set_cdev_update() {
+ return BeginNestedMessage<T>(342);
+ }
+
+
+ using FieldMetadata_CpuhpExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 343,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuhpExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuhpExit kCpuhpExit{};
+ template <typename T = CpuhpExitFtraceEvent> T* set_cpuhp_exit() {
+ return BeginNestedMessage<T>(343);
+ }
+
+
+ using FieldMetadata_CpuhpMultiEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 344,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuhpMultiEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuhpMultiEnter kCpuhpMultiEnter{};
+ template <typename T = CpuhpMultiEnterFtraceEvent> T* set_cpuhp_multi_enter() {
+ return BeginNestedMessage<T>(344);
+ }
+
+
+ using FieldMetadata_CpuhpEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 345,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuhpEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuhpEnter kCpuhpEnter{};
+ template <typename T = CpuhpEnterFtraceEvent> T* set_cpuhp_enter() {
+ return BeginNestedMessage<T>(345);
+ }
+
+
+ using FieldMetadata_CpuhpLatency =
+ ::protozero::proto_utils::FieldMetadata<
+ 346,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuhpLatencyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuhpLatency kCpuhpLatency{};
+ template <typename T = CpuhpLatencyFtraceEvent> T* set_cpuhp_latency() {
+ return BeginNestedMessage<T>(346);
+ }
+
+
+ using FieldMetadata_FastrpcDmaStat =
+ ::protozero::proto_utils::FieldMetadata<
+ 347,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FastrpcDmaStatFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_FastrpcDmaStat kFastrpcDmaStat{};
+ template <typename T = FastrpcDmaStatFtraceEvent> T* set_fastrpc_dma_stat() {
+ return BeginNestedMessage<T>(347);
+ }
+
+
+ using FieldMetadata_DpuTracingMarkWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 348,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DpuTracingMarkWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DpuTracingMarkWrite kDpuTracingMarkWrite{};
+ template <typename T = DpuTracingMarkWriteFtraceEvent> T* set_dpu_tracing_mark_write() {
+ return BeginNestedMessage<T>(348);
+ }
+
+
+ using FieldMetadata_G2dTracingMarkWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 349,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ G2dTracingMarkWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_G2dTracingMarkWrite kG2dTracingMarkWrite{};
+ template <typename T = G2dTracingMarkWriteFtraceEvent> T* set_g2d_tracing_mark_write() {
+ return BeginNestedMessage<T>(349);
+ }
+
+
+ using FieldMetadata_MaliTracingMarkWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 350,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliTracingMarkWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliTracingMarkWrite kMaliTracingMarkWrite{};
+ template <typename T = MaliTracingMarkWriteFtraceEvent> T* set_mali_tracing_mark_write() {
+ return BeginNestedMessage<T>(350);
+ }
+
+
+ using FieldMetadata_DmaHeapStat =
+ ::protozero::proto_utils::FieldMetadata<
+ 351,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DmaHeapStatFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DmaHeapStat kDmaHeapStat{};
+ template <typename T = DmaHeapStatFtraceEvent> T* set_dma_heap_stat() {
+ return BeginNestedMessage<T>(351);
+ }
+
+
+ using FieldMetadata_CpuhpPause =
+ ::protozero::proto_utils::FieldMetadata<
+ 352,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuhpPauseFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CpuhpPause kCpuhpPause{};
+ template <typename T = CpuhpPauseFtraceEvent> T* set_cpuhp_pause() {
+ return BeginNestedMessage<T>(352);
+ }
+
+
+ using FieldMetadata_SchedPiSetprio =
+ ::protozero::proto_utils::FieldMetadata<
+ 353,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedPiSetprioFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedPiSetprio kSchedPiSetprio{};
+ template <typename T = SchedPiSetprioFtraceEvent> T* set_sched_pi_setprio() {
+ return BeginNestedMessage<T>(353);
+ }
+
+
+ using FieldMetadata_SdeSdeEvtlog =
+ ::protozero::proto_utils::FieldMetadata<
+ 354,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SdeSdeEvtlogFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SdeSdeEvtlog kSdeSdeEvtlog{};
+ template <typename T = SdeSdeEvtlogFtraceEvent> T* set_sde_sde_evtlog() {
+ return BeginNestedMessage<T>(354);
+ }
+
+
+ using FieldMetadata_SdeSdePerfCalcCrtc =
+ ::protozero::proto_utils::FieldMetadata<
+ 355,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SdeSdePerfCalcCrtcFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SdeSdePerfCalcCrtc kSdeSdePerfCalcCrtc{};
+ template <typename T = SdeSdePerfCalcCrtcFtraceEvent> T* set_sde_sde_perf_calc_crtc() {
+ return BeginNestedMessage<T>(355);
+ }
+
+
+ using FieldMetadata_SdeSdePerfCrtcUpdate =
+ ::protozero::proto_utils::FieldMetadata<
+ 356,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SdeSdePerfCrtcUpdateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SdeSdePerfCrtcUpdate kSdeSdePerfCrtcUpdate{};
+ template <typename T = SdeSdePerfCrtcUpdateFtraceEvent> T* set_sde_sde_perf_crtc_update() {
+ return BeginNestedMessage<T>(356);
+ }
+
+
+ using FieldMetadata_SdeSdePerfSetQosLuts =
+ ::protozero::proto_utils::FieldMetadata<
+ 357,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SdeSdePerfSetQosLutsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SdeSdePerfSetQosLuts kSdeSdePerfSetQosLuts{};
+ template <typename T = SdeSdePerfSetQosLutsFtraceEvent> T* set_sde_sde_perf_set_qos_luts() {
+ return BeginNestedMessage<T>(357);
+ }
+
+
+ using FieldMetadata_SdeSdePerfUpdateBus =
+ ::protozero::proto_utils::FieldMetadata<
+ 358,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SdeSdePerfUpdateBusFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SdeSdePerfUpdateBus kSdeSdePerfUpdateBus{};
+ template <typename T = SdeSdePerfUpdateBusFtraceEvent> T* set_sde_sde_perf_update_bus() {
+ return BeginNestedMessage<T>(358);
+ }
+
+
+ using FieldMetadata_RssStatThrottled =
+ ::protozero::proto_utils::FieldMetadata<
+ 359,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RssStatThrottledFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RssStatThrottled kRssStatThrottled{};
+ template <typename T = RssStatThrottledFtraceEvent> T* set_rss_stat_throttled() {
+ return BeginNestedMessage<T>(359);
+ }
+
+
+ using FieldMetadata_NetifReceiveSkb =
+ ::protozero::proto_utils::FieldMetadata<
+ 360,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetifReceiveSkbFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_NetifReceiveSkb kNetifReceiveSkb{};
+ template <typename T = NetifReceiveSkbFtraceEvent> T* set_netif_receive_skb() {
+ return BeginNestedMessage<T>(360);
+ }
+
+
+ using FieldMetadata_NetDevXmit =
+ ::protozero::proto_utils::FieldMetadata<
+ 361,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NetDevXmitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_NetDevXmit kNetDevXmit{};
+ template <typename T = NetDevXmitFtraceEvent> T* set_net_dev_xmit() {
+ return BeginNestedMessage<T>(361);
+ }
+
+
+ using FieldMetadata_InetSockSetState =
+ ::protozero::proto_utils::FieldMetadata<
+ 362,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InetSockSetStateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_InetSockSetState kInetSockSetState{};
+ template <typename T = InetSockSetStateFtraceEvent> T* set_inet_sock_set_state() {
+ return BeginNestedMessage<T>(362);
+ }
+
+
+ using FieldMetadata_TcpRetransmitSkb =
+ ::protozero::proto_utils::FieldMetadata<
+ 363,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TcpRetransmitSkbFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TcpRetransmitSkb kTcpRetransmitSkb{};
+ template <typename T = TcpRetransmitSkbFtraceEvent> T* set_tcp_retransmit_skb() {
+ return BeginNestedMessage<T>(363);
+ }
+
+
+ using FieldMetadata_CrosEcSensorhubData =
+ ::protozero::proto_utils::FieldMetadata<
+ 364,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CrosEcSensorhubDataFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CrosEcSensorhubData kCrosEcSensorhubData{};
+ template <typename T = CrosEcSensorhubDataFtraceEvent> T* set_cros_ec_sensorhub_data() {
+ return BeginNestedMessage<T>(364);
+ }
+
+
+ using FieldMetadata_NapiGroReceiveEntry =
+ ::protozero::proto_utils::FieldMetadata<
+ 365,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NapiGroReceiveEntryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_NapiGroReceiveEntry kNapiGroReceiveEntry{};
+ template <typename T = NapiGroReceiveEntryFtraceEvent> T* set_napi_gro_receive_entry() {
+ return BeginNestedMessage<T>(365);
+ }
+
+
+ using FieldMetadata_NapiGroReceiveExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 366,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ NapiGroReceiveExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_NapiGroReceiveExit kNapiGroReceiveExit{};
+ template <typename T = NapiGroReceiveExitFtraceEvent> T* set_napi_gro_receive_exit() {
+ return BeginNestedMessage<T>(366);
+ }
+
+
+ using FieldMetadata_KfreeSkb =
+ ::protozero::proto_utils::FieldMetadata<
+ 367,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KfreeSkbFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KfreeSkb kKfreeSkb{};
+ template <typename T = KfreeSkbFtraceEvent> T* set_kfree_skb() {
+ return BeginNestedMessage<T>(367);
+ }
+
+
+ using FieldMetadata_KvmAccessFault =
+ ::protozero::proto_utils::FieldMetadata<
+ 368,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmAccessFaultFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmAccessFault kKvmAccessFault{};
+ template <typename T = KvmAccessFaultFtraceEvent> T* set_kvm_access_fault() {
+ return BeginNestedMessage<T>(368);
+ }
+
+
+ using FieldMetadata_KvmAckIrq =
+ ::protozero::proto_utils::FieldMetadata<
+ 369,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmAckIrqFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmAckIrq kKvmAckIrq{};
+ template <typename T = KvmAckIrqFtraceEvent> T* set_kvm_ack_irq() {
+ return BeginNestedMessage<T>(369);
+ }
+
+
+ using FieldMetadata_KvmAgeHva =
+ ::protozero::proto_utils::FieldMetadata<
+ 370,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmAgeHvaFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmAgeHva kKvmAgeHva{};
+ template <typename T = KvmAgeHvaFtraceEvent> T* set_kvm_age_hva() {
+ return BeginNestedMessage<T>(370);
+ }
+
+
+ using FieldMetadata_KvmAgePage =
+ ::protozero::proto_utils::FieldMetadata<
+ 371,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmAgePageFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmAgePage kKvmAgePage{};
+ template <typename T = KvmAgePageFtraceEvent> T* set_kvm_age_page() {
+ return BeginNestedMessage<T>(371);
+ }
+
+
+ using FieldMetadata_KvmArmClearDebug =
+ ::protozero::proto_utils::FieldMetadata<
+ 372,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmArmClearDebugFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmArmClearDebug kKvmArmClearDebug{};
+ template <typename T = KvmArmClearDebugFtraceEvent> T* set_kvm_arm_clear_debug() {
+ return BeginNestedMessage<T>(372);
+ }
+
+
+ using FieldMetadata_KvmArmSetDreg32 =
+ ::protozero::proto_utils::FieldMetadata<
+ 373,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmArmSetDreg32FtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmArmSetDreg32 kKvmArmSetDreg32{};
+ template <typename T = KvmArmSetDreg32FtraceEvent> T* set_kvm_arm_set_dreg32() {
+ return BeginNestedMessage<T>(373);
+ }
+
+
+ using FieldMetadata_KvmArmSetRegset =
+ ::protozero::proto_utils::FieldMetadata<
+ 374,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmArmSetRegsetFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmArmSetRegset kKvmArmSetRegset{};
+ template <typename T = KvmArmSetRegsetFtraceEvent> T* set_kvm_arm_set_regset() {
+ return BeginNestedMessage<T>(374);
+ }
+
+
+ using FieldMetadata_KvmArmSetupDebug =
+ ::protozero::proto_utils::FieldMetadata<
+ 375,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmArmSetupDebugFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmArmSetupDebug kKvmArmSetupDebug{};
+ template <typename T = KvmArmSetupDebugFtraceEvent> T* set_kvm_arm_setup_debug() {
+ return BeginNestedMessage<T>(375);
+ }
+
+
+ using FieldMetadata_KvmEntry =
+ ::protozero::proto_utils::FieldMetadata<
+ 376,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmEntryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmEntry kKvmEntry{};
+ template <typename T = KvmEntryFtraceEvent> T* set_kvm_entry() {
+ return BeginNestedMessage<T>(376);
+ }
+
+
+ using FieldMetadata_KvmExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 377,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmExit kKvmExit{};
+ template <typename T = KvmExitFtraceEvent> T* set_kvm_exit() {
+ return BeginNestedMessage<T>(377);
+ }
+
+
+ using FieldMetadata_KvmFpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 378,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmFpuFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmFpu kKvmFpu{};
+ template <typename T = KvmFpuFtraceEvent> T* set_kvm_fpu() {
+ return BeginNestedMessage<T>(378);
+ }
+
+
+ using FieldMetadata_KvmGetTimerMap =
+ ::protozero::proto_utils::FieldMetadata<
+ 379,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmGetTimerMapFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmGetTimerMap kKvmGetTimerMap{};
+ template <typename T = KvmGetTimerMapFtraceEvent> T* set_kvm_get_timer_map() {
+ return BeginNestedMessage<T>(379);
+ }
+
+
+ using FieldMetadata_KvmGuestFault =
+ ::protozero::proto_utils::FieldMetadata<
+ 380,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmGuestFaultFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmGuestFault kKvmGuestFault{};
+ template <typename T = KvmGuestFaultFtraceEvent> T* set_kvm_guest_fault() {
+ return BeginNestedMessage<T>(380);
+ }
+
+
+ using FieldMetadata_KvmHandleSysReg =
+ ::protozero::proto_utils::FieldMetadata<
+ 381,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmHandleSysRegFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmHandleSysReg kKvmHandleSysReg{};
+ template <typename T = KvmHandleSysRegFtraceEvent> T* set_kvm_handle_sys_reg() {
+ return BeginNestedMessage<T>(381);
+ }
+
+
+ using FieldMetadata_KvmHvcArm64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 382,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmHvcArm64FtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmHvcArm64 kKvmHvcArm64{};
+ template <typename T = KvmHvcArm64FtraceEvent> T* set_kvm_hvc_arm64() {
+ return BeginNestedMessage<T>(382);
+ }
+
+
+ using FieldMetadata_KvmIrqLine =
+ ::protozero::proto_utils::FieldMetadata<
+ 383,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmIrqLineFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmIrqLine kKvmIrqLine{};
+ template <typename T = KvmIrqLineFtraceEvent> T* set_kvm_irq_line() {
+ return BeginNestedMessage<T>(383);
+ }
+
+
+ using FieldMetadata_KvmMmio =
+ ::protozero::proto_utils::FieldMetadata<
+ 384,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmMmioFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmMmio kKvmMmio{};
+ template <typename T = KvmMmioFtraceEvent> T* set_kvm_mmio() {
+ return BeginNestedMessage<T>(384);
+ }
+
+
+ using FieldMetadata_KvmMmioEmulate =
+ ::protozero::proto_utils::FieldMetadata<
+ 385,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmMmioEmulateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmMmioEmulate kKvmMmioEmulate{};
+ template <typename T = KvmMmioEmulateFtraceEvent> T* set_kvm_mmio_emulate() {
+ return BeginNestedMessage<T>(385);
+ }
+
+
+ using FieldMetadata_KvmSetGuestDebug =
+ ::protozero::proto_utils::FieldMetadata<
+ 386,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmSetGuestDebugFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmSetGuestDebug kKvmSetGuestDebug{};
+ template <typename T = KvmSetGuestDebugFtraceEvent> T* set_kvm_set_guest_debug() {
+ return BeginNestedMessage<T>(386);
+ }
+
+
+ using FieldMetadata_KvmSetIrq =
+ ::protozero::proto_utils::FieldMetadata<
+ 387,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmSetIrqFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmSetIrq kKvmSetIrq{};
+ template <typename T = KvmSetIrqFtraceEvent> T* set_kvm_set_irq() {
+ return BeginNestedMessage<T>(387);
+ }
+
+
+ using FieldMetadata_KvmSetSpteHva =
+ ::protozero::proto_utils::FieldMetadata<
+ 388,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmSetSpteHvaFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmSetSpteHva kKvmSetSpteHva{};
+ template <typename T = KvmSetSpteHvaFtraceEvent> T* set_kvm_set_spte_hva() {
+ return BeginNestedMessage<T>(388);
+ }
+
+
+ using FieldMetadata_KvmSetWayFlush =
+ ::protozero::proto_utils::FieldMetadata<
+ 389,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmSetWayFlushFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmSetWayFlush kKvmSetWayFlush{};
+ template <typename T = KvmSetWayFlushFtraceEvent> T* set_kvm_set_way_flush() {
+ return BeginNestedMessage<T>(389);
+ }
+
+
+ using FieldMetadata_KvmSysAccess =
+ ::protozero::proto_utils::FieldMetadata<
+ 390,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmSysAccessFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmSysAccess kKvmSysAccess{};
+ template <typename T = KvmSysAccessFtraceEvent> T* set_kvm_sys_access() {
+ return BeginNestedMessage<T>(390);
+ }
+
+
+ using FieldMetadata_KvmTestAgeHva =
+ ::protozero::proto_utils::FieldMetadata<
+ 391,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmTestAgeHvaFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmTestAgeHva kKvmTestAgeHva{};
+ template <typename T = KvmTestAgeHvaFtraceEvent> T* set_kvm_test_age_hva() {
+ return BeginNestedMessage<T>(391);
+ }
+
+
+ using FieldMetadata_KvmTimerEmulate =
+ ::protozero::proto_utils::FieldMetadata<
+ 392,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmTimerEmulateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmTimerEmulate kKvmTimerEmulate{};
+ template <typename T = KvmTimerEmulateFtraceEvent> T* set_kvm_timer_emulate() {
+ return BeginNestedMessage<T>(392);
+ }
+
+
+ using FieldMetadata_KvmTimerHrtimerExpire =
+ ::protozero::proto_utils::FieldMetadata<
+ 393,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmTimerHrtimerExpireFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmTimerHrtimerExpire kKvmTimerHrtimerExpire{};
+ template <typename T = KvmTimerHrtimerExpireFtraceEvent> T* set_kvm_timer_hrtimer_expire() {
+ return BeginNestedMessage<T>(393);
+ }
+
+
+ using FieldMetadata_KvmTimerRestoreState =
+ ::protozero::proto_utils::FieldMetadata<
+ 394,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmTimerRestoreStateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmTimerRestoreState kKvmTimerRestoreState{};
+ template <typename T = KvmTimerRestoreStateFtraceEvent> T* set_kvm_timer_restore_state() {
+ return BeginNestedMessage<T>(394);
+ }
+
+
+ using FieldMetadata_KvmTimerSaveState =
+ ::protozero::proto_utils::FieldMetadata<
+ 395,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmTimerSaveStateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmTimerSaveState kKvmTimerSaveState{};
+ template <typename T = KvmTimerSaveStateFtraceEvent> T* set_kvm_timer_save_state() {
+ return BeginNestedMessage<T>(395);
+ }
+
+
+ using FieldMetadata_KvmTimerUpdateIrq =
+ ::protozero::proto_utils::FieldMetadata<
+ 396,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmTimerUpdateIrqFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmTimerUpdateIrq kKvmTimerUpdateIrq{};
+ template <typename T = KvmTimerUpdateIrqFtraceEvent> T* set_kvm_timer_update_irq() {
+ return BeginNestedMessage<T>(396);
+ }
+
+
+ using FieldMetadata_KvmToggleCache =
+ ::protozero::proto_utils::FieldMetadata<
+ 397,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmToggleCacheFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmToggleCache kKvmToggleCache{};
+ template <typename T = KvmToggleCacheFtraceEvent> T* set_kvm_toggle_cache() {
+ return BeginNestedMessage<T>(397);
+ }
+
+
+ using FieldMetadata_KvmUnmapHvaRange =
+ ::protozero::proto_utils::FieldMetadata<
+ 398,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmUnmapHvaRangeFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmUnmapHvaRange kKvmUnmapHvaRange{};
+ template <typename T = KvmUnmapHvaRangeFtraceEvent> T* set_kvm_unmap_hva_range() {
+ return BeginNestedMessage<T>(398);
+ }
+
+
+ using FieldMetadata_KvmUserspaceExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 399,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmUserspaceExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmUserspaceExit kKvmUserspaceExit{};
+ template <typename T = KvmUserspaceExitFtraceEvent> T* set_kvm_userspace_exit() {
+ return BeginNestedMessage<T>(399);
+ }
+
+
+ using FieldMetadata_KvmVcpuWakeup =
+ ::protozero::proto_utils::FieldMetadata<
+ 400,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmVcpuWakeupFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmVcpuWakeup kKvmVcpuWakeup{};
+ template <typename T = KvmVcpuWakeupFtraceEvent> T* set_kvm_vcpu_wakeup() {
+ return BeginNestedMessage<T>(400);
+ }
+
+
+ using FieldMetadata_KvmWfxArm64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 401,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ KvmWfxArm64FtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_KvmWfxArm64 kKvmWfxArm64{};
+ template <typename T = KvmWfxArm64FtraceEvent> T* set_kvm_wfx_arm64() {
+ return BeginNestedMessage<T>(401);
+ }
+
+
+ using FieldMetadata_TrapReg =
+ ::protozero::proto_utils::FieldMetadata<
+ 402,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrapRegFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrapReg kTrapReg{};
+ template <typename T = TrapRegFtraceEvent> T* set_trap_reg() {
+ return BeginNestedMessage<T>(402);
+ }
+
+
+ using FieldMetadata_VgicUpdateIrqPending =
+ ::protozero::proto_utils::FieldMetadata<
+ 403,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VgicUpdateIrqPendingFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_VgicUpdateIrqPending kVgicUpdateIrqPending{};
+ template <typename T = VgicUpdateIrqPendingFtraceEvent> T* set_vgic_update_irq_pending() {
+ return BeginNestedMessage<T>(403);
+ }
+
+
+ using FieldMetadata_WakeupSourceActivate =
+ ::protozero::proto_utils::FieldMetadata<
+ 404,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ WakeupSourceActivateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_WakeupSourceActivate kWakeupSourceActivate{};
+ template <typename T = WakeupSourceActivateFtraceEvent> T* set_wakeup_source_activate() {
+ return BeginNestedMessage<T>(404);
+ }
+
+
+ using FieldMetadata_WakeupSourceDeactivate =
+ ::protozero::proto_utils::FieldMetadata<
+ 405,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ WakeupSourceDeactivateFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_WakeupSourceDeactivate kWakeupSourceDeactivate{};
+ template <typename T = WakeupSourceDeactivateFtraceEvent> T* set_wakeup_source_deactivate() {
+ return BeginNestedMessage<T>(405);
+ }
+
+
+ using FieldMetadata_UfshcdCommand =
+ ::protozero::proto_utils::FieldMetadata<
+ 406,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ UfshcdCommandFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_UfshcdCommand kUfshcdCommand{};
+ template <typename T = UfshcdCommandFtraceEvent> T* set_ufshcd_command() {
+ return BeginNestedMessage<T>(406);
+ }
+
+
+ using FieldMetadata_UfshcdClkGating =
+ ::protozero::proto_utils::FieldMetadata<
+ 407,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ UfshcdClkGatingFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_UfshcdClkGating kUfshcdClkGating{};
+ template <typename T = UfshcdClkGatingFtraceEvent> T* set_ufshcd_clk_gating() {
+ return BeginNestedMessage<T>(407);
+ }
+
+
+ using FieldMetadata_Console =
+ ::protozero::proto_utils::FieldMetadata<
+ 408,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ConsoleFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Console kConsole{};
+ template <typename T = ConsoleFtraceEvent> T* set_console() {
+ return BeginNestedMessage<T>(408);
+ }
+
+
+ using FieldMetadata_DrmVblankEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 409,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DrmVblankEventFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DrmVblankEvent kDrmVblankEvent{};
+ template <typename T = DrmVblankEventFtraceEvent> T* set_drm_vblank_event() {
+ return BeginNestedMessage<T>(409);
+ }
+
+
+ using FieldMetadata_DrmVblankEventDelivered =
+ ::protozero::proto_utils::FieldMetadata<
+ 410,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DrmVblankEventDeliveredFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DrmVblankEventDelivered kDrmVblankEventDelivered{};
+ template <typename T = DrmVblankEventDeliveredFtraceEvent> T* set_drm_vblank_event_delivered() {
+ return BeginNestedMessage<T>(410);
+ }
+
+
+ using FieldMetadata_DrmSchedJob =
+ ::protozero::proto_utils::FieldMetadata<
+ 411,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DrmSchedJobFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DrmSchedJob kDrmSchedJob{};
+ template <typename T = DrmSchedJobFtraceEvent> T* set_drm_sched_job() {
+ return BeginNestedMessage<T>(411);
+ }
+
+
+ using FieldMetadata_DrmRunJob =
+ ::protozero::proto_utils::FieldMetadata<
+ 412,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DrmRunJobFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DrmRunJob kDrmRunJob{};
+ template <typename T = DrmRunJobFtraceEvent> T* set_drm_run_job() {
+ return BeginNestedMessage<T>(412);
+ }
+
+
+ using FieldMetadata_DrmSchedProcessJob =
+ ::protozero::proto_utils::FieldMetadata<
+ 413,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DrmSchedProcessJobFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DrmSchedProcessJob kDrmSchedProcessJob{};
+ template <typename T = DrmSchedProcessJobFtraceEvent> T* set_drm_sched_process_job() {
+ return BeginNestedMessage<T>(413);
+ }
+
+
+ using FieldMetadata_DmaFenceInit =
+ ::protozero::proto_utils::FieldMetadata<
+ 414,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DmaFenceInitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DmaFenceInit kDmaFenceInit{};
+ template <typename T = DmaFenceInitFtraceEvent> T* set_dma_fence_init() {
+ return BeginNestedMessage<T>(414);
+ }
+
+
+ using FieldMetadata_DmaFenceEmit =
+ ::protozero::proto_utils::FieldMetadata<
+ 415,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DmaFenceEmitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DmaFenceEmit kDmaFenceEmit{};
+ template <typename T = DmaFenceEmitFtraceEvent> T* set_dma_fence_emit() {
+ return BeginNestedMessage<T>(415);
+ }
+
+
+ using FieldMetadata_DmaFenceSignaled =
+ ::protozero::proto_utils::FieldMetadata<
+ 416,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DmaFenceSignaledFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DmaFenceSignaled kDmaFenceSignaled{};
+ template <typename T = DmaFenceSignaledFtraceEvent> T* set_dma_fence_signaled() {
+ return BeginNestedMessage<T>(416);
+ }
+
+
+ using FieldMetadata_DmaFenceWaitStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 417,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DmaFenceWaitStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DmaFenceWaitStart kDmaFenceWaitStart{};
+ template <typename T = DmaFenceWaitStartFtraceEvent> T* set_dma_fence_wait_start() {
+ return BeginNestedMessage<T>(417);
+ }
+
+
+ using FieldMetadata_DmaFenceWaitEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 418,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DmaFenceWaitEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DmaFenceWaitEnd kDmaFenceWaitEnd{};
+ template <typename T = DmaFenceWaitEndFtraceEvent> T* set_dma_fence_wait_end() {
+ return BeginNestedMessage<T>(418);
+ }
+
+
+ using FieldMetadata_F2fsIostat =
+ ::protozero::proto_utils::FieldMetadata<
+ 419,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsIostatFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsIostat kF2fsIostat{};
+ template <typename T = F2fsIostatFtraceEvent> T* set_f2fs_iostat() {
+ return BeginNestedMessage<T>(419);
+ }
+
+
+ using FieldMetadata_F2fsIostatLatency =
+ ::protozero::proto_utils::FieldMetadata<
+ 420,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsIostatLatencyFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsIostatLatency kF2fsIostatLatency{};
+ template <typename T = F2fsIostatLatencyFtraceEvent> T* set_f2fs_iostat_latency() {
+ return BeginNestedMessage<T>(420);
+ }
+
+
+ using FieldMetadata_SchedCpuUtilCfs =
+ ::protozero::proto_utils::FieldMetadata<
+ 421,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedCpuUtilCfsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedCpuUtilCfs kSchedCpuUtilCfs{};
+ template <typename T = SchedCpuUtilCfsFtraceEvent> T* set_sched_cpu_util_cfs() {
+ return BeginNestedMessage<T>(421);
+ }
+
+
+ using FieldMetadata_V4l2Qbuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 422,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V4l2QbufFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_V4l2Qbuf kV4l2Qbuf{};
+ template <typename T = V4l2QbufFtraceEvent> T* set_v4l2_qbuf() {
+ return BeginNestedMessage<T>(422);
+ }
+
+
+ using FieldMetadata_V4l2Dqbuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 423,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V4l2DqbufFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_V4l2Dqbuf kV4l2Dqbuf{};
+ template <typename T = V4l2DqbufFtraceEvent> T* set_v4l2_dqbuf() {
+ return BeginNestedMessage<T>(423);
+ }
+
+
+ using FieldMetadata_Vb2V4l2BufQueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 424,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Vb2V4l2BufQueueFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Vb2V4l2BufQueue kVb2V4l2BufQueue{};
+ template <typename T = Vb2V4l2BufQueueFtraceEvent> T* set_vb2_v4l2_buf_queue() {
+ return BeginNestedMessage<T>(424);
+ }
+
+
+ using FieldMetadata_Vb2V4l2BufDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 425,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Vb2V4l2BufDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Vb2V4l2BufDone kVb2V4l2BufDone{};
+ template <typename T = Vb2V4l2BufDoneFtraceEvent> T* set_vb2_v4l2_buf_done() {
+ return BeginNestedMessage<T>(425);
+ }
+
+
+ using FieldMetadata_Vb2V4l2Qbuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 426,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Vb2V4l2QbufFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Vb2V4l2Qbuf kVb2V4l2Qbuf{};
+ template <typename T = Vb2V4l2QbufFtraceEvent> T* set_vb2_v4l2_qbuf() {
+ return BeginNestedMessage<T>(426);
+ }
+
+
+ using FieldMetadata_Vb2V4l2Dqbuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 427,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Vb2V4l2DqbufFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_Vb2V4l2Dqbuf kVb2V4l2Dqbuf{};
+ template <typename T = Vb2V4l2DqbufFtraceEvent> T* set_vb2_v4l2_dqbuf() {
+ return BeginNestedMessage<T>(427);
+ }
+
+
+ using FieldMetadata_DsiCmdFifoStatus =
+ ::protozero::proto_utils::FieldMetadata<
+ 428,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DsiCmdFifoStatusFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DsiCmdFifoStatus kDsiCmdFifoStatus{};
+ template <typename T = DsiCmdFifoStatusFtraceEvent> T* set_dsi_cmd_fifo_status() {
+ return BeginNestedMessage<T>(428);
+ }
+
+
+ using FieldMetadata_DsiRx =
+ ::protozero::proto_utils::FieldMetadata<
+ 429,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DsiRxFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DsiRx kDsiRx{};
+ template <typename T = DsiRxFtraceEvent> T* set_dsi_rx() {
+ return BeginNestedMessage<T>(429);
+ }
+
+
+ using FieldMetadata_DsiTx =
+ ::protozero::proto_utils::FieldMetadata<
+ 430,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DsiTxFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DsiTx kDsiTx{};
+ template <typename T = DsiTxFtraceEvent> T* set_dsi_tx() {
+ return BeginNestedMessage<T>(430);
+ }
+
+
+ using FieldMetadata_AndroidFsDatareadEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 431,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidFsDatareadEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AndroidFsDatareadEnd kAndroidFsDatareadEnd{};
+ template <typename T = AndroidFsDatareadEndFtraceEvent> T* set_android_fs_dataread_end() {
+ return BeginNestedMessage<T>(431);
+ }
+
+
+ using FieldMetadata_AndroidFsDatareadStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 432,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidFsDatareadStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AndroidFsDatareadStart kAndroidFsDatareadStart{};
+ template <typename T = AndroidFsDatareadStartFtraceEvent> T* set_android_fs_dataread_start() {
+ return BeginNestedMessage<T>(432);
+ }
+
+
+ using FieldMetadata_AndroidFsDatawriteEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 433,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidFsDatawriteEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AndroidFsDatawriteEnd kAndroidFsDatawriteEnd{};
+ template <typename T = AndroidFsDatawriteEndFtraceEvent> T* set_android_fs_datawrite_end() {
+ return BeginNestedMessage<T>(433);
+ }
+
+
+ using FieldMetadata_AndroidFsDatawriteStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 434,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidFsDatawriteStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AndroidFsDatawriteStart kAndroidFsDatawriteStart{};
+ template <typename T = AndroidFsDatawriteStartFtraceEvent> T* set_android_fs_datawrite_start() {
+ return BeginNestedMessage<T>(434);
+ }
+
+
+ using FieldMetadata_AndroidFsFsyncEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 435,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidFsFsyncEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AndroidFsFsyncEnd kAndroidFsFsyncEnd{};
+ template <typename T = AndroidFsFsyncEndFtraceEvent> T* set_android_fs_fsync_end() {
+ return BeginNestedMessage<T>(435);
+ }
+
+
+ using FieldMetadata_AndroidFsFsyncStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 436,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidFsFsyncStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_AndroidFsFsyncStart kAndroidFsFsyncStart{};
+ template <typename T = AndroidFsFsyncStartFtraceEvent> T* set_android_fs_fsync_start() {
+ return BeginNestedMessage<T>(436);
+ }
+
+
+ using FieldMetadata_FuncgraphEntry =
+ ::protozero::proto_utils::FieldMetadata<
+ 437,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FuncgraphEntryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_FuncgraphEntry kFuncgraphEntry{};
+ template <typename T = FuncgraphEntryFtraceEvent> T* set_funcgraph_entry() {
+ return BeginNestedMessage<T>(437);
+ }
+
+
+ using FieldMetadata_FuncgraphExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 438,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FuncgraphExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_FuncgraphExit kFuncgraphExit{};
+ template <typename T = FuncgraphExitFtraceEvent> T* set_funcgraph_exit() {
+ return BeginNestedMessage<T>(438);
+ }
+
+
+ using FieldMetadata_VirtioVideoCmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 439,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VirtioVideoCmdFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_VirtioVideoCmd kVirtioVideoCmd{};
+ template <typename T = VirtioVideoCmdFtraceEvent> T* set_virtio_video_cmd() {
+ return BeginNestedMessage<T>(439);
+ }
+
+
+ using FieldMetadata_VirtioVideoCmdDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 440,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VirtioVideoCmdDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_VirtioVideoCmdDone kVirtioVideoCmdDone{};
+ template <typename T = VirtioVideoCmdDoneFtraceEvent> T* set_virtio_video_cmd_done() {
+ return BeginNestedMessage<T>(440);
+ }
+
+
+ using FieldMetadata_VirtioVideoResourceQueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 441,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VirtioVideoResourceQueueFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_VirtioVideoResourceQueue kVirtioVideoResourceQueue{};
+ template <typename T = VirtioVideoResourceQueueFtraceEvent> T* set_virtio_video_resource_queue() {
+ return BeginNestedMessage<T>(441);
+ }
+
+
+ using FieldMetadata_VirtioVideoResourceQueueDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 442,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VirtioVideoResourceQueueDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_VirtioVideoResourceQueueDone kVirtioVideoResourceQueueDone{};
+ template <typename T = VirtioVideoResourceQueueDoneFtraceEvent> T* set_virtio_video_resource_queue_done() {
+ return BeginNestedMessage<T>(442);
+ }
+
+
+ using FieldMetadata_MmShrinkSlabStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 443,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmShrinkSlabStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmShrinkSlabStart kMmShrinkSlabStart{};
+ template <typename T = MmShrinkSlabStartFtraceEvent> T* set_mm_shrink_slab_start() {
+ return BeginNestedMessage<T>(443);
+ }
+
+
+ using FieldMetadata_MmShrinkSlabEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 444,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MmShrinkSlabEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MmShrinkSlabEnd kMmShrinkSlabEnd{};
+ template <typename T = MmShrinkSlabEndFtraceEvent> T* set_mm_shrink_slab_end() {
+ return BeginNestedMessage<T>(444);
+ }
+
+
+ using FieldMetadata_TrustySmc =
+ ::protozero::proto_utils::FieldMetadata<
+ 445,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustySmcFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustySmc kTrustySmc{};
+ template <typename T = TrustySmcFtraceEvent> T* set_trusty_smc() {
+ return BeginNestedMessage<T>(445);
+ }
+
+
+ using FieldMetadata_TrustySmcDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 446,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustySmcDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustySmcDone kTrustySmcDone{};
+ template <typename T = TrustySmcDoneFtraceEvent> T* set_trusty_smc_done() {
+ return BeginNestedMessage<T>(446);
+ }
+
+
+ using FieldMetadata_TrustyStdCall32 =
+ ::protozero::proto_utils::FieldMetadata<
+ 447,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyStdCall32FtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyStdCall32 kTrustyStdCall32{};
+ template <typename T = TrustyStdCall32FtraceEvent> T* set_trusty_std_call32() {
+ return BeginNestedMessage<T>(447);
+ }
+
+
+ using FieldMetadata_TrustyStdCall32Done =
+ ::protozero::proto_utils::FieldMetadata<
+ 448,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyStdCall32DoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyStdCall32Done kTrustyStdCall32Done{};
+ template <typename T = TrustyStdCall32DoneFtraceEvent> T* set_trusty_std_call32_done() {
+ return BeginNestedMessage<T>(448);
+ }
+
+
+ using FieldMetadata_TrustyShareMemory =
+ ::protozero::proto_utils::FieldMetadata<
+ 449,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyShareMemoryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyShareMemory kTrustyShareMemory{};
+ template <typename T = TrustyShareMemoryFtraceEvent> T* set_trusty_share_memory() {
+ return BeginNestedMessage<T>(449);
+ }
+
+
+ using FieldMetadata_TrustyShareMemoryDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 450,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyShareMemoryDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyShareMemoryDone kTrustyShareMemoryDone{};
+ template <typename T = TrustyShareMemoryDoneFtraceEvent> T* set_trusty_share_memory_done() {
+ return BeginNestedMessage<T>(450);
+ }
+
+
+ using FieldMetadata_TrustyReclaimMemory =
+ ::protozero::proto_utils::FieldMetadata<
+ 451,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyReclaimMemoryFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyReclaimMemory kTrustyReclaimMemory{};
+ template <typename T = TrustyReclaimMemoryFtraceEvent> T* set_trusty_reclaim_memory() {
+ return BeginNestedMessage<T>(451);
+ }
+
+
+ using FieldMetadata_TrustyReclaimMemoryDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 452,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyReclaimMemoryDoneFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyReclaimMemoryDone kTrustyReclaimMemoryDone{};
+ template <typename T = TrustyReclaimMemoryDoneFtraceEvent> T* set_trusty_reclaim_memory_done() {
+ return BeginNestedMessage<T>(452);
+ }
+
+
+ using FieldMetadata_TrustyIrq =
+ ::protozero::proto_utils::FieldMetadata<
+ 453,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIrqFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIrq kTrustyIrq{};
+ template <typename T = TrustyIrqFtraceEvent> T* set_trusty_irq() {
+ return BeginNestedMessage<T>(453);
+ }
+
+
+ using FieldMetadata_TrustyIpcHandleEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 454,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcHandleEventFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcHandleEvent kTrustyIpcHandleEvent{};
+ template <typename T = TrustyIpcHandleEventFtraceEvent> T* set_trusty_ipc_handle_event() {
+ return BeginNestedMessage<T>(454);
+ }
+
+
+ using FieldMetadata_TrustyIpcConnect =
+ ::protozero::proto_utils::FieldMetadata<
+ 455,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcConnectFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcConnect kTrustyIpcConnect{};
+ template <typename T = TrustyIpcConnectFtraceEvent> T* set_trusty_ipc_connect() {
+ return BeginNestedMessage<T>(455);
+ }
+
+
+ using FieldMetadata_TrustyIpcConnectEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 456,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcConnectEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcConnectEnd kTrustyIpcConnectEnd{};
+ template <typename T = TrustyIpcConnectEndFtraceEvent> T* set_trusty_ipc_connect_end() {
+ return BeginNestedMessage<T>(456);
+ }
+
+
+ using FieldMetadata_TrustyIpcWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 457,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcWrite kTrustyIpcWrite{};
+ template <typename T = TrustyIpcWriteFtraceEvent> T* set_trusty_ipc_write() {
+ return BeginNestedMessage<T>(457);
+ }
+
+
+ using FieldMetadata_TrustyIpcPoll =
+ ::protozero::proto_utils::FieldMetadata<
+ 458,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcPollFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcPoll kTrustyIpcPoll{};
+ template <typename T = TrustyIpcPollFtraceEvent> T* set_trusty_ipc_poll() {
+ return BeginNestedMessage<T>(458);
+ }
+
+
+ using FieldMetadata_TrustyIpcRead =
+ ::protozero::proto_utils::FieldMetadata<
+ 460,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcReadFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcRead kTrustyIpcRead{};
+ template <typename T = TrustyIpcReadFtraceEvent> T* set_trusty_ipc_read() {
+ return BeginNestedMessage<T>(460);
+ }
+
+
+ using FieldMetadata_TrustyIpcReadEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 461,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcReadEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcReadEnd kTrustyIpcReadEnd{};
+ template <typename T = TrustyIpcReadEndFtraceEvent> T* set_trusty_ipc_read_end() {
+ return BeginNestedMessage<T>(461);
+ }
+
+
+ using FieldMetadata_TrustyIpcRx =
+ ::protozero::proto_utils::FieldMetadata<
+ 462,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyIpcRxFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyIpcRx kTrustyIpcRx{};
+ template <typename T = TrustyIpcRxFtraceEvent> T* set_trusty_ipc_rx() {
+ return BeginNestedMessage<T>(462);
+ }
+
+
+ using FieldMetadata_TrustyEnqueueNop =
+ ::protozero::proto_utils::FieldMetadata<
+ 464,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrustyEnqueueNopFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_TrustyEnqueueNop kTrustyEnqueueNop{};
+ template <typename T = TrustyEnqueueNopFtraceEvent> T* set_trusty_enqueue_nop() {
+ return BeginNestedMessage<T>(464);
+ }
+
+
+ using FieldMetadata_CmaAllocStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 465,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CmaAllocStartFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CmaAllocStart kCmaAllocStart{};
+ template <typename T = CmaAllocStartFtraceEvent> T* set_cma_alloc_start() {
+ return BeginNestedMessage<T>(465);
+ }
+
+
+ using FieldMetadata_CmaAllocInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 466,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CmaAllocInfoFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_CmaAllocInfo kCmaAllocInfo{};
+ template <typename T = CmaAllocInfoFtraceEvent> T* set_cma_alloc_info() {
+ return BeginNestedMessage<T>(466);
+ }
+
+
+ using FieldMetadata_LwisTracingMarkWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 467,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ LwisTracingMarkWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_LwisTracingMarkWrite kLwisTracingMarkWrite{};
+ template <typename T = LwisTracingMarkWriteFtraceEvent> T* set_lwis_tracing_mark_write() {
+ return BeginNestedMessage<T>(467);
+ }
+
+
+ using FieldMetadata_VirtioGpuCmdQueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 468,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VirtioGpuCmdQueueFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_VirtioGpuCmdQueue kVirtioGpuCmdQueue{};
+ template <typename T = VirtioGpuCmdQueueFtraceEvent> T* set_virtio_gpu_cmd_queue() {
+ return BeginNestedMessage<T>(468);
+ }
+
+
+ using FieldMetadata_VirtioGpuCmdResponse =
+ ::protozero::proto_utils::FieldMetadata<
+ 469,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VirtioGpuCmdResponseFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_VirtioGpuCmdResponse kVirtioGpuCmdResponse{};
+ template <typename T = VirtioGpuCmdResponseFtraceEvent> T* set_virtio_gpu_cmd_response() {
+ return BeginNestedMessage<T>(469);
+ }
+
+
+ using FieldMetadata_MaliMaliKCPUCQSSET =
+ ::protozero::proto_utils::FieldMetadata<
+ 470,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliKCPUCQSSETFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliKCPUCQSSET kMaliMaliKCPUCQSSET{};
+ template <typename T = MaliMaliKCPUCQSSETFtraceEvent> T* set_mali_mali_kcpu_cqs_set() {
+ return BeginNestedMessage<T>(470);
+ }
+
+
+ using FieldMetadata_MaliMaliKCPUCQSWAITSTART =
+ ::protozero::proto_utils::FieldMetadata<
+ 471,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliKCPUCQSWAITSTARTFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliKCPUCQSWAITSTART kMaliMaliKCPUCQSWAITSTART{};
+ template <typename T = MaliMaliKCPUCQSWAITSTARTFtraceEvent> T* set_mali_mali_kcpu_cqs_wait_start() {
+ return BeginNestedMessage<T>(471);
+ }
+
+
+ using FieldMetadata_MaliMaliKCPUCQSWAITEND =
+ ::protozero::proto_utils::FieldMetadata<
+ 472,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliKCPUCQSWAITENDFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliKCPUCQSWAITEND kMaliMaliKCPUCQSWAITEND{};
+ template <typename T = MaliMaliKCPUCQSWAITENDFtraceEvent> T* set_mali_mali_kcpu_cqs_wait_end() {
+ return BeginNestedMessage<T>(472);
+ }
+
+
+ using FieldMetadata_MaliMaliKCPUFENCESIGNAL =
+ ::protozero::proto_utils::FieldMetadata<
+ 473,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliKCPUFENCESIGNALFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliKCPUFENCESIGNAL kMaliMaliKCPUFENCESIGNAL{};
+ template <typename T = MaliMaliKCPUFENCESIGNALFtraceEvent> T* set_mali_mali_kcpu_fence_signal() {
+ return BeginNestedMessage<T>(473);
+ }
+
+
+ using FieldMetadata_MaliMaliKCPUFENCEWAITSTART =
+ ::protozero::proto_utils::FieldMetadata<
+ 474,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliKCPUFENCEWAITSTARTFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliKCPUFENCEWAITSTART kMaliMaliKCPUFENCEWAITSTART{};
+ template <typename T = MaliMaliKCPUFENCEWAITSTARTFtraceEvent> T* set_mali_mali_kcpu_fence_wait_start() {
+ return BeginNestedMessage<T>(474);
+ }
+
+
+ using FieldMetadata_MaliMaliKCPUFENCEWAITEND =
+ ::protozero::proto_utils::FieldMetadata<
+ 475,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliKCPUFENCEWAITENDFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliKCPUFENCEWAITEND kMaliMaliKCPUFENCEWAITEND{};
+ template <typename T = MaliMaliKCPUFENCEWAITENDFtraceEvent> T* set_mali_mali_kcpu_fence_wait_end() {
+ return BeginNestedMessage<T>(475);
+ }
+
+
+ using FieldMetadata_HypEnter =
+ ::protozero::proto_utils::FieldMetadata<
+ 476,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HypEnterFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_HypEnter kHypEnter{};
+ template <typename T = HypEnterFtraceEvent> T* set_hyp_enter() {
+ return BeginNestedMessage<T>(476);
+ }
+
+
+ using FieldMetadata_HypExit =
+ ::protozero::proto_utils::FieldMetadata<
+ 477,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HypExitFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_HypExit kHypExit{};
+ template <typename T = HypExitFtraceEvent> T* set_hyp_exit() {
+ return BeginNestedMessage<T>(477);
+ }
+
+
+ using FieldMetadata_HostHcall =
+ ::protozero::proto_utils::FieldMetadata<
+ 478,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HostHcallFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_HostHcall kHostHcall{};
+ template <typename T = HostHcallFtraceEvent> T* set_host_hcall() {
+ return BeginNestedMessage<T>(478);
+ }
+
+
+ using FieldMetadata_HostSmc =
+ ::protozero::proto_utils::FieldMetadata<
+ 479,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HostSmcFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_HostSmc kHostSmc{};
+ template <typename T = HostSmcFtraceEvent> T* set_host_smc() {
+ return BeginNestedMessage<T>(479);
+ }
+
+
+ using FieldMetadata_HostMemAbort =
+ ::protozero::proto_utils::FieldMetadata<
+ 480,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HostMemAbortFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_HostMemAbort kHostMemAbort{};
+ template <typename T = HostMemAbortFtraceEvent> T* set_host_mem_abort() {
+ return BeginNestedMessage<T>(480);
+ }
+
+
+ using FieldMetadata_SuspendResumeMinimal =
+ ::protozero::proto_utils::FieldMetadata<
+ 481,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SuspendResumeMinimalFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SuspendResumeMinimal kSuspendResumeMinimal{};
+ template <typename T = SuspendResumeMinimalFtraceEvent> T* set_suspend_resume_minimal() {
+ return BeginNestedMessage<T>(481);
+ }
+
+
+ using FieldMetadata_MaliMaliCSFINTERRUPTSTART =
+ ::protozero::proto_utils::FieldMetadata<
+ 482,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliCSFINTERRUPTSTARTFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliCSFINTERRUPTSTART kMaliMaliCSFINTERRUPTSTART{};
+ template <typename T = MaliMaliCSFINTERRUPTSTARTFtraceEvent> T* set_mali_mali_csf_interrupt_start() {
+ return BeginNestedMessage<T>(482);
+ }
+
+
+ using FieldMetadata_MaliMaliCSFINTERRUPTEND =
+ ::protozero::proto_utils::FieldMetadata<
+ 483,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MaliMaliCSFINTERRUPTENDFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_MaliMaliCSFINTERRUPTEND kMaliMaliCSFINTERRUPTEND{};
+ template <typename T = MaliMaliCSFINTERRUPTENDFtraceEvent> T* set_mali_mali_csf_interrupt_end() {
+ return BeginNestedMessage<T>(483);
+ }
+
+
+ using FieldMetadata_SamsungTracingMarkWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 484,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SamsungTracingMarkWriteFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SamsungTracingMarkWrite kSamsungTracingMarkWrite{};
+ template <typename T = SamsungTracingMarkWriteFtraceEvent> T* set_samsung_tracing_mark_write() {
+ return BeginNestedMessage<T>(484);
+ }
+
+
+ using FieldMetadata_BinderCommand =
+ ::protozero::proto_utils::FieldMetadata<
+ 485,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderCommandFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderCommand kBinderCommand{};
+ template <typename T = BinderCommandFtraceEvent> T* set_binder_command() {
+ return BeginNestedMessage<T>(485);
+ }
+
+
+ using FieldMetadata_BinderReturn =
+ ::protozero::proto_utils::FieldMetadata<
+ 486,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BinderReturnFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_BinderReturn kBinderReturn{};
+ template <typename T = BinderReturnFtraceEvent> T* set_binder_return() {
+ return BeginNestedMessage<T>(486);
+ }
+
+
+ using FieldMetadata_SchedSwitchWithCtrs =
+ ::protozero::proto_utils::FieldMetadata<
+ 487,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedSwitchWithCtrsFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedSwitchWithCtrs kSchedSwitchWithCtrs{};
+ template <typename T = SchedSwitchWithCtrsFtraceEvent> T* set_sched_switch_with_ctrs() {
+ return BeginNestedMessage<T>(487);
+ }
+
+
+ using FieldMetadata_GpuWorkPeriod =
+ ::protozero::proto_utils::FieldMetadata<
+ 488,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuWorkPeriodFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_GpuWorkPeriod kGpuWorkPeriod{};
+ template <typename T = GpuWorkPeriodFtraceEvent> T* set_gpu_work_period() {
+ return BeginNestedMessage<T>(488);
+ }
+
+
+ using FieldMetadata_RpmStatus =
+ ::protozero::proto_utils::FieldMetadata<
+ 489,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RpmStatusFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_RpmStatus kRpmStatus{};
+ template <typename T = RpmStatusFtraceEvent> T* set_rpm_status() {
+ return BeginNestedMessage<T>(489);
+ }
+
+
+ using FieldMetadata_PanelWriteGeneric =
+ ::protozero::proto_utils::FieldMetadata<
+ 490,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PanelWriteGenericFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_PanelWriteGeneric kPanelWriteGeneric{};
+ template <typename T = PanelWriteGenericFtraceEvent> T* set_panel_write_generic() {
+ return BeginNestedMessage<T>(490);
+ }
+
+
+ using FieldMetadata_SchedMigrateTask =
+ ::protozero::proto_utils::FieldMetadata<
+ 491,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SchedMigrateTaskFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_SchedMigrateTask kSchedMigrateTask{};
+ template <typename T = SchedMigrateTaskFtraceEvent> T* set_sched_migrate_task() {
+ return BeginNestedMessage<T>(491);
+ }
+
+
+ using FieldMetadata_DpuDsiCmdFifoStatus =
+ ::protozero::proto_utils::FieldMetadata<
+ 492,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DpuDsiCmdFifoStatusFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DpuDsiCmdFifoStatus kDpuDsiCmdFifoStatus{};
+ template <typename T = DpuDsiCmdFifoStatusFtraceEvent> T* set_dpu_dsi_cmd_fifo_status() {
+ return BeginNestedMessage<T>(492);
+ }
+
+
+ using FieldMetadata_DpuDsiRx =
+ ::protozero::proto_utils::FieldMetadata<
+ 493,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DpuDsiRxFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DpuDsiRx kDpuDsiRx{};
+ template <typename T = DpuDsiRxFtraceEvent> T* set_dpu_dsi_rx() {
+ return BeginNestedMessage<T>(493);
+ }
+
+
+ using FieldMetadata_DpuDsiTx =
+ ::protozero::proto_utils::FieldMetadata<
+ 494,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DpuDsiTxFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_DpuDsiTx kDpuDsiTx{};
+ template <typename T = DpuDsiTxFtraceEvent> T* set_dpu_dsi_tx() {
+ return BeginNestedMessage<T>(494);
+ }
+
+
+ using FieldMetadata_F2fsBackgroundGc =
+ ::protozero::proto_utils::FieldMetadata<
+ 495,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsBackgroundGcFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsBackgroundGc kF2fsBackgroundGc{};
+ template <typename T = F2fsBackgroundGcFtraceEvent> T* set_f2fs_background_gc() {
+ return BeginNestedMessage<T>(495);
+ }
+
+
+ using FieldMetadata_F2fsGcBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 496,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsGcBeginFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsGcBegin kF2fsGcBegin{};
+ template <typename T = F2fsGcBeginFtraceEvent> T* set_f2fs_gc_begin() {
+ return BeginNestedMessage<T>(496);
+ }
+
+
+ using FieldMetadata_F2fsGcEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 497,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ F2fsGcEndFtraceEvent,
+ FtraceEvent>;
+
+ static constexpr FieldMetadata_F2fsGcEnd kF2fsGcEnd{};
+ template <typename T = F2fsGcEndFtraceEvent> T* set_f2fs_gc_end() {
+ return BeginNestedMessage<T>(497);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_EVENT_BUNDLE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_EVENT_BUNDLE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FtraceEvent;
+class FtraceEventBundle_CompactSched;
+class FtraceEventBundle_FtraceError;
+enum FtraceClock : int32_t;
+enum FtraceParseStatus : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum FtraceClock : int32_t {
+ FTRACE_CLOCK_UNSPECIFIED = 0,
+ FTRACE_CLOCK_UNKNOWN = 1,
+ FTRACE_CLOCK_GLOBAL = 2,
+ FTRACE_CLOCK_LOCAL = 3,
+ FTRACE_CLOCK_MONO_RAW = 4,
+};
+
+constexpr FtraceClock FtraceClock_MIN = FtraceClock::FTRACE_CLOCK_UNSPECIFIED;
+constexpr FtraceClock FtraceClock_MAX = FtraceClock::FTRACE_CLOCK_MONO_RAW;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FtraceClock_Name(::perfetto::protos::pbzero::FtraceClock value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FtraceClock::FTRACE_CLOCK_UNSPECIFIED:
+ return "FTRACE_CLOCK_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::FtraceClock::FTRACE_CLOCK_UNKNOWN:
+ return "FTRACE_CLOCK_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::FtraceClock::FTRACE_CLOCK_GLOBAL:
+ return "FTRACE_CLOCK_GLOBAL";
+
+ case ::perfetto::protos::pbzero::FtraceClock::FTRACE_CLOCK_LOCAL:
+ return "FTRACE_CLOCK_LOCAL";
+
+ case ::perfetto::protos::pbzero::FtraceClock::FTRACE_CLOCK_MONO_RAW:
+ return "FTRACE_CLOCK_MONO_RAW";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class FtraceEventBundle_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FtraceEventBundle_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceEventBundle_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceEventBundle_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint32_t cpu() const { return at<1>().as_uint32(); }
+ bool has_event() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> event() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_lost_events() const { return at<3>().valid(); }
+ bool lost_events() const { return at<3>().as_bool(); }
+ bool has_compact_sched() const { return at<4>().valid(); }
+ ::protozero::ConstBytes compact_sched() const { return at<4>().as_bytes(); }
+ bool has_ftrace_clock() const { return at<5>().valid(); }
+ int32_t ftrace_clock() const { return at<5>().as_int32(); }
+ bool has_ftrace_timestamp() const { return at<6>().valid(); }
+ int64_t ftrace_timestamp() const { return at<6>().as_int64(); }
+ bool has_boot_timestamp() const { return at<7>().valid(); }
+ int64_t boot_timestamp() const { return at<7>().as_int64(); }
+ bool has_error() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> error() const { return GetRepeated<::protozero::ConstBytes>(8); }
+ bool has_last_read_event_timestamp() const { return at<9>().valid(); }
+ uint64_t last_read_event_timestamp() const { return at<9>().as_uint64(); }
+};
+
+class FtraceEventBundle : public ::protozero::Message {
+ public:
+ using Decoder = FtraceEventBundle_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kEventFieldNumber = 2,
+ kLostEventsFieldNumber = 3,
+ kCompactSchedFieldNumber = 4,
+ kFtraceClockFieldNumber = 5,
+ kFtraceTimestampFieldNumber = 6,
+ kBootTimestampFieldNumber = 7,
+ kErrorFieldNumber = 8,
+ kLastReadEventTimestampFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceEventBundle"; }
+
+ using CompactSched = ::perfetto::protos::pbzero::FtraceEventBundle_CompactSched;
+ using FtraceError = ::perfetto::protos::pbzero::FtraceEventBundle_FtraceError;
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Event =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceEvent,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_Event kEvent{};
+ template <typename T = FtraceEvent> T* add_event() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_LostEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_LostEvents kLostEvents{};
+ void set_lost_events(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_LostEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CompactSched =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceEventBundle_CompactSched,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_CompactSched kCompactSched{};
+ template <typename T = FtraceEventBundle_CompactSched> T* set_compact_sched() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_FtraceClock =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FtraceClock,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_FtraceClock kFtraceClock{};
+ void set_ftrace_clock(FtraceClock value) {
+ static constexpr uint32_t field_id = FieldMetadata_FtraceClock::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FtraceTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_FtraceTimestamp kFtraceTimestamp{};
+ void set_ftrace_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FtraceTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BootTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_BootTimestamp kBootTimestamp{};
+ void set_boot_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BootTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Error =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceEventBundle_FtraceError,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_Error kError{};
+ template <typename T = FtraceEventBundle_FtraceError> T* add_error() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_LastReadEventTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceEventBundle>;
+
+ static constexpr FieldMetadata_LastReadEventTimestamp kLastReadEventTimestamp{};
+ void set_last_read_event_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LastReadEventTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FtraceEventBundle_FtraceError_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FtraceEventBundle_FtraceError_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceEventBundle_FtraceError_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceEventBundle_FtraceError_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timestamp() const { return at<1>().valid(); }
+ uint64_t timestamp() const { return at<1>().as_uint64(); }
+ bool has_status() const { return at<2>().valid(); }
+ int32_t status() const { return at<2>().as_int32(); }
+};
+
+class FtraceEventBundle_FtraceError : public ::protozero::Message {
+ public:
+ using Decoder = FtraceEventBundle_FtraceError_Decoder;
+ enum : int32_t {
+ kTimestampFieldNumber = 1,
+ kStatusFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceEventBundle.FtraceError"; }
+
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceEventBundle_FtraceError>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FtraceParseStatus,
+ FtraceEventBundle_FtraceError>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(FtraceParseStatus value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FtraceEventBundle_CompactSched_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/12, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FtraceEventBundle_CompactSched_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceEventBundle_CompactSched_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceEventBundle_CompactSched_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_intern_table() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> intern_table() const { return GetRepeated<::protozero::ConstChars>(5); }
+ bool has_switch_timestamp() const { return at<1>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> switch_timestamp(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(1, parse_error_ptr); }
+ bool has_switch_prev_state() const { return at<2>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int64_t> switch_prev_state(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int64_t>(2, parse_error_ptr); }
+ bool has_switch_next_pid() const { return at<3>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t> switch_next_pid(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(3, parse_error_ptr); }
+ bool has_switch_next_prio() const { return at<4>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t> switch_next_prio(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(4, parse_error_ptr); }
+ bool has_switch_next_comm_index() const { return at<6>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t> switch_next_comm_index(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t>(6, parse_error_ptr); }
+ bool has_waking_timestamp() const { return at<7>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> waking_timestamp(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(7, parse_error_ptr); }
+ bool has_waking_pid() const { return at<8>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t> waking_pid(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(8, parse_error_ptr); }
+ bool has_waking_target_cpu() const { return at<9>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t> waking_target_cpu(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(9, parse_error_ptr); }
+ bool has_waking_prio() const { return at<10>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t> waking_prio(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(10, parse_error_ptr); }
+ bool has_waking_comm_index() const { return at<11>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t> waking_comm_index(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t>(11, parse_error_ptr); }
+ bool has_waking_common_flags() const { return at<12>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t> waking_common_flags(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint32_t>(12, parse_error_ptr); }
+};
+
+class FtraceEventBundle_CompactSched : public ::protozero::Message {
+ public:
+ using Decoder = FtraceEventBundle_CompactSched_Decoder;
+ enum : int32_t {
+ kInternTableFieldNumber = 5,
+ kSwitchTimestampFieldNumber = 1,
+ kSwitchPrevStateFieldNumber = 2,
+ kSwitchNextPidFieldNumber = 3,
+ kSwitchNextPrioFieldNumber = 4,
+ kSwitchNextCommIndexFieldNumber = 6,
+ kWakingTimestampFieldNumber = 7,
+ kWakingPidFieldNumber = 8,
+ kWakingTargetCpuFieldNumber = 9,
+ kWakingPrioFieldNumber = 10,
+ kWakingCommIndexFieldNumber = 11,
+ kWakingCommonFlagsFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceEventBundle.CompactSched"; }
+
+
+ using FieldMetadata_InternTable =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_InternTable kInternTable{};
+ void add_intern_table(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_InternTable::kFieldId, data, size);
+ }
+ void add_intern_table(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_InternTable::kFieldId, chars.data, chars.size);
+ }
+ void add_intern_table(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_InternTable::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SwitchTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_SwitchTimestamp kSwitchTimestamp{};
+ void set_switch_timestamp(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_SwitchTimestamp::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_SwitchPrevState =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_SwitchPrevState kSwitchPrevState{};
+ void set_switch_prev_state(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_SwitchPrevState::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_SwitchNextPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_SwitchNextPid kSwitchNextPid{};
+ void set_switch_next_pid(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_SwitchNextPid::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_SwitchNextPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_SwitchNextPrio kSwitchNextPrio{};
+ void set_switch_next_prio(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_SwitchNextPrio::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_SwitchNextCommIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_SwitchNextCommIndex kSwitchNextCommIndex{};
+ void set_switch_next_comm_index(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_SwitchNextCommIndex::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_WakingTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_WakingTimestamp kWakingTimestamp{};
+ void set_waking_timestamp(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_WakingTimestamp::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_WakingPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_WakingPid kWakingPid{};
+ void set_waking_pid(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_WakingPid::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_WakingTargetCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_WakingTargetCpu kWakingTargetCpu{};
+ void set_waking_target_cpu(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_WakingTargetCpu::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_WakingPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_WakingPrio kWakingPrio{};
+ void set_waking_prio(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_WakingPrio::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_WakingCommIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_WakingCommIndex kWakingCommIndex{};
+ void set_waking_comm_index(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_WakingCommIndex::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_WakingCommonFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceEventBundle_CompactSched>;
+
+ static constexpr FieldMetadata_WakingCommonFlags kWakingCommonFlags{};
+ void set_waking_common_flags(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_WakingCommonFlags::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_STATS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_STATS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FtraceCpuStats;
+enum FtraceParseStatus : int32_t;
+namespace perfetto_pbzero_enum_FtraceStats {
+enum Phase : int32_t;
+} // namespace perfetto_pbzero_enum_FtraceStats
+using FtraceStats_Phase = perfetto_pbzero_enum_FtraceStats::Phase;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum FtraceParseStatus : int32_t {
+ FTRACE_STATUS_UNSPECIFIED = 0,
+ FTRACE_STATUS_OK = 1,
+ FTRACE_STATUS_UNEXPECTED_READ_ERROR = 2,
+ FTRACE_STATUS_PARTIAL_PAGE_READ = 3,
+ FTRACE_STATUS_ABI_INVALID_PAGE_HEADER = 4,
+ FTRACE_STATUS_ABI_SHORT_EVENT_HEADER = 5,
+ FTRACE_STATUS_ABI_NULL_PADDING = 6,
+ FTRACE_STATUS_ABI_SHORT_PADDING_LENGTH = 7,
+ FTRACE_STATUS_ABI_INVALID_PADDING_LENGTH = 8,
+ FTRACE_STATUS_ABI_SHORT_TIME_EXTEND = 9,
+ FTRACE_STATUS_ABI_SHORT_TIME_STAMP = 10,
+ FTRACE_STATUS_ABI_SHORT_DATA_LENGTH = 11,
+ FTRACE_STATUS_ABI_ZERO_DATA_LENGTH = 12,
+ FTRACE_STATUS_ABI_INVALID_DATA_LENGTH = 13,
+ FTRACE_STATUS_ABI_SHORT_EVENT_ID = 14,
+ FTRACE_STATUS_ABI_END_OVERFLOW = 15,
+ FTRACE_STATUS_SHORT_COMPACT_EVENT = 16,
+ FTRACE_STATUS_INVALID_EVENT = 17,
+};
+
+constexpr FtraceParseStatus FtraceParseStatus_MIN = FtraceParseStatus::FTRACE_STATUS_UNSPECIFIED;
+constexpr FtraceParseStatus FtraceParseStatus_MAX = FtraceParseStatus::FTRACE_STATUS_INVALID_EVENT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FtraceParseStatus_Name(::perfetto::protos::pbzero::FtraceParseStatus value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_UNSPECIFIED:
+ return "FTRACE_STATUS_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_OK:
+ return "FTRACE_STATUS_OK";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_UNEXPECTED_READ_ERROR:
+ return "FTRACE_STATUS_UNEXPECTED_READ_ERROR";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_PARTIAL_PAGE_READ:
+ return "FTRACE_STATUS_PARTIAL_PAGE_READ";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_INVALID_PAGE_HEADER:
+ return "FTRACE_STATUS_ABI_INVALID_PAGE_HEADER";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_SHORT_EVENT_HEADER:
+ return "FTRACE_STATUS_ABI_SHORT_EVENT_HEADER";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_NULL_PADDING:
+ return "FTRACE_STATUS_ABI_NULL_PADDING";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_SHORT_PADDING_LENGTH:
+ return "FTRACE_STATUS_ABI_SHORT_PADDING_LENGTH";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_INVALID_PADDING_LENGTH:
+ return "FTRACE_STATUS_ABI_INVALID_PADDING_LENGTH";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_SHORT_TIME_EXTEND:
+ return "FTRACE_STATUS_ABI_SHORT_TIME_EXTEND";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_SHORT_TIME_STAMP:
+ return "FTRACE_STATUS_ABI_SHORT_TIME_STAMP";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_SHORT_DATA_LENGTH:
+ return "FTRACE_STATUS_ABI_SHORT_DATA_LENGTH";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_ZERO_DATA_LENGTH:
+ return "FTRACE_STATUS_ABI_ZERO_DATA_LENGTH";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_INVALID_DATA_LENGTH:
+ return "FTRACE_STATUS_ABI_INVALID_DATA_LENGTH";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_SHORT_EVENT_ID:
+ return "FTRACE_STATUS_ABI_SHORT_EVENT_ID";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_ABI_END_OVERFLOW:
+ return "FTRACE_STATUS_ABI_END_OVERFLOW";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_SHORT_COMPACT_EVENT:
+ return "FTRACE_STATUS_SHORT_COMPACT_EVENT";
+
+ case ::perfetto::protos::pbzero::FtraceParseStatus::FTRACE_STATUS_INVALID_EVENT:
+ return "FTRACE_STATUS_INVALID_EVENT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_FtraceStats {
+enum Phase : int32_t {
+ UNSPECIFIED = 0,
+ START_OF_TRACE = 1,
+ END_OF_TRACE = 2,
+};
+} // namespace perfetto_pbzero_enum_FtraceStats
+using FtraceStats_Phase = perfetto_pbzero_enum_FtraceStats::Phase;
+
+
+constexpr FtraceStats_Phase FtraceStats_Phase_MIN = FtraceStats_Phase::UNSPECIFIED;
+constexpr FtraceStats_Phase FtraceStats_Phase_MAX = FtraceStats_Phase::END_OF_TRACE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* FtraceStats_Phase_Name(::perfetto::protos::pbzero::FtraceStats_Phase value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::FtraceStats_Phase::UNSPECIFIED:
+ return "UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::FtraceStats_Phase::START_OF_TRACE:
+ return "START_OF_TRACE";
+
+ case ::perfetto::protos::pbzero::FtraceStats_Phase::END_OF_TRACE:
+ return "END_OF_TRACE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class FtraceStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ FtraceStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_phase() const { return at<1>().valid(); }
+ int32_t phase() const { return at<1>().as_int32(); }
+ bool has_cpu_stats() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> cpu_stats() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_kernel_symbols_parsed() const { return at<3>().valid(); }
+ uint32_t kernel_symbols_parsed() const { return at<3>().as_uint32(); }
+ bool has_kernel_symbols_mem_kb() const { return at<4>().valid(); }
+ uint32_t kernel_symbols_mem_kb() const { return at<4>().as_uint32(); }
+ bool has_atrace_errors() const { return at<5>().valid(); }
+ ::protozero::ConstChars atrace_errors() const { return at<5>().as_string(); }
+ bool has_unknown_ftrace_events() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> unknown_ftrace_events() const { return GetRepeated<::protozero::ConstChars>(6); }
+ bool has_failed_ftrace_events() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> failed_ftrace_events() const { return GetRepeated<::protozero::ConstChars>(7); }
+ bool has_preserve_ftrace_buffer() const { return at<8>().valid(); }
+ bool preserve_ftrace_buffer() const { return at<8>().as_bool(); }
+ bool has_ftrace_parse_errors() const { return at<9>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> ftrace_parse_errors() const { return GetRepeated<int32_t>(9); }
+};
+
+class FtraceStats : public ::protozero::Message {
+ public:
+ using Decoder = FtraceStats_Decoder;
+ enum : int32_t {
+ kPhaseFieldNumber = 1,
+ kCpuStatsFieldNumber = 2,
+ kKernelSymbolsParsedFieldNumber = 3,
+ kKernelSymbolsMemKbFieldNumber = 4,
+ kAtraceErrorsFieldNumber = 5,
+ kUnknownFtraceEventsFieldNumber = 6,
+ kFailedFtraceEventsFieldNumber = 7,
+ kPreserveFtraceBufferFieldNumber = 8,
+ kFtraceParseErrorsFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceStats"; }
+
+
+ using Phase = ::perfetto::protos::pbzero::FtraceStats_Phase;
+ static inline const char* Phase_Name(Phase value) {
+ return ::perfetto::protos::pbzero::FtraceStats_Phase_Name(value);
+ }
+ static inline const Phase UNSPECIFIED = Phase::UNSPECIFIED;
+ static inline const Phase START_OF_TRACE = Phase::START_OF_TRACE;
+ static inline const Phase END_OF_TRACE = Phase::END_OF_TRACE;
+
+ using FieldMetadata_Phase =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FtraceStats_Phase,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_Phase kPhase{};
+ void set_phase(FtraceStats_Phase value) {
+ static constexpr uint32_t field_id = FieldMetadata_Phase::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuStats =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceCpuStats,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_CpuStats kCpuStats{};
+ template <typename T = FtraceCpuStats> T* add_cpu_stats() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_KernelSymbolsParsed =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_KernelSymbolsParsed kKernelSymbolsParsed{};
+ void set_kernel_symbols_parsed(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KernelSymbolsParsed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KernelSymbolsMemKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_KernelSymbolsMemKb kKernelSymbolsMemKb{};
+ void set_kernel_symbols_mem_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KernelSymbolsMemKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AtraceErrors =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_AtraceErrors kAtraceErrors{};
+ void set_atrace_errors(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_AtraceErrors::kFieldId, data, size);
+ }
+ void set_atrace_errors(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_AtraceErrors::kFieldId, chars.data, chars.size);
+ }
+ void set_atrace_errors(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_AtraceErrors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnknownFtraceEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_UnknownFtraceEvents kUnknownFtraceEvents{};
+ void add_unknown_ftrace_events(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_UnknownFtraceEvents::kFieldId, data, size);
+ }
+ void add_unknown_ftrace_events(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_UnknownFtraceEvents::kFieldId, chars.data, chars.size);
+ }
+ void add_unknown_ftrace_events(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnknownFtraceEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FailedFtraceEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_FailedFtraceEvents kFailedFtraceEvents{};
+ void add_failed_ftrace_events(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FailedFtraceEvents::kFieldId, data, size);
+ }
+ void add_failed_ftrace_events(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FailedFtraceEvents::kFieldId, chars.data, chars.size);
+ }
+ void add_failed_ftrace_events(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FailedFtraceEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreserveFtraceBuffer =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_PreserveFtraceBuffer kPreserveFtraceBuffer{};
+ void set_preserve_ftrace_buffer(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreserveFtraceBuffer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FtraceParseErrors =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ FtraceParseStatus,
+ FtraceStats>;
+
+ static constexpr FieldMetadata_FtraceParseErrors kFtraceParseErrors{};
+ void add_ftrace_parse_errors(FtraceParseStatus value) {
+ static constexpr uint32_t field_id = FieldMetadata_FtraceParseErrors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FtraceCpuStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FtraceCpuStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FtraceCpuStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FtraceCpuStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint64_t cpu() const { return at<1>().as_uint64(); }
+ bool has_entries() const { return at<2>().valid(); }
+ uint64_t entries() const { return at<2>().as_uint64(); }
+ bool has_overrun() const { return at<3>().valid(); }
+ uint64_t overrun() const { return at<3>().as_uint64(); }
+ bool has_commit_overrun() const { return at<4>().valid(); }
+ uint64_t commit_overrun() const { return at<4>().as_uint64(); }
+ bool has_bytes_read() const { return at<5>().valid(); }
+ uint64_t bytes_read() const { return at<5>().as_uint64(); }
+ bool has_oldest_event_ts() const { return at<6>().valid(); }
+ double oldest_event_ts() const { return at<6>().as_double(); }
+ bool has_now_ts() const { return at<7>().valid(); }
+ double now_ts() const { return at<7>().as_double(); }
+ bool has_dropped_events() const { return at<8>().valid(); }
+ uint64_t dropped_events() const { return at<8>().as_uint64(); }
+ bool has_read_events() const { return at<9>().valid(); }
+ uint64_t read_events() const { return at<9>().as_uint64(); }
+};
+
+class FtraceCpuStats : public ::protozero::Message {
+ public:
+ using Decoder = FtraceCpuStats_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kEntriesFieldNumber = 2,
+ kOverrunFieldNumber = 3,
+ kCommitOverrunFieldNumber = 4,
+ kBytesReadFieldNumber = 5,
+ kOldestEventTsFieldNumber = 6,
+ kNowTsFieldNumber = 7,
+ kDroppedEventsFieldNumber = 8,
+ kReadEventsFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FtraceCpuStats"; }
+
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Entries =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_Entries kEntries{};
+ void set_entries(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Entries::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Overrun =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_Overrun kOverrun{};
+ void set_overrun(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Overrun::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CommitOverrun =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_CommitOverrun kCommitOverrun{};
+ void set_commit_overrun(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CommitOverrun::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesRead =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_BytesRead kBytesRead{};
+ void set_bytes_read(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesRead::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldestEventTs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_OldestEventTs kOldestEventTs{};
+ void set_oldest_event_ts(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldestEventTs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NowTs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_NowTs kNowTs{};
+ void set_now_ts(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_NowTs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DroppedEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_DroppedEvents kDroppedEvents{};
+ void set_dropped_events(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DroppedEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadEvents =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FtraceCpuStats>;
+
+ static constexpr FieldMetadata_ReadEvents kReadEvents{};
+ void set_read_events(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadEvents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/test_bundle_wrapper.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TEST_BUNDLE_WRAPPER_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TEST_BUNDLE_WRAPPER_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FtraceEventBundle;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TestBundleWrapper_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TestBundleWrapper_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TestBundleWrapper_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TestBundleWrapper_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_before() const { return at<1>().valid(); }
+ ::protozero::ConstChars before() const { return at<1>().as_string(); }
+ bool has_bundle() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> bundle() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_after() const { return at<3>().valid(); }
+ ::protozero::ConstChars after() const { return at<3>().as_string(); }
+};
+
+class TestBundleWrapper : public ::protozero::Message {
+ public:
+ using Decoder = TestBundleWrapper_Decoder;
+ enum : int32_t {
+ kBeforeFieldNumber = 1,
+ kBundleFieldNumber = 2,
+ kAfterFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TestBundleWrapper"; }
+
+
+ using FieldMetadata_Before =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestBundleWrapper>;
+
+ static constexpr FieldMetadata_Before kBefore{};
+ void set_before(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Before::kFieldId, data, size);
+ }
+ void set_before(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Before::kFieldId, chars.data, chars.size);
+ }
+ void set_before(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Before::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bundle =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FtraceEventBundle,
+ TestBundleWrapper>;
+
+ static constexpr FieldMetadata_Bundle kBundle{};
+ template <typename T = FtraceEventBundle> T* add_bundle() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_After =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestBundleWrapper>;
+
+ static constexpr FieldMetadata_After kAfter{};
+ void set_after(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_After::kFieldId, data, size);
+ }
+ void set_after(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_After::kFieldId, chars.data, chars.size);
+ }
+ void set_after(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_After::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/generic.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_GENERIC_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_GENERIC_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class GenericFtraceEvent_Field;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class GenericFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GenericFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GenericFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GenericFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars event_name() const { return at<1>().as_string(); }
+ bool has_field() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> field() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class GenericFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = GenericFtraceEvent_Decoder;
+ enum : int32_t {
+ kEventNameFieldNumber = 1,
+ kFieldFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GenericFtraceEvent"; }
+
+ using Field = ::perfetto::protos::pbzero::GenericFtraceEvent_Field;
+
+ using FieldMetadata_EventName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GenericFtraceEvent>;
+
+ static constexpr FieldMetadata_EventName kEventName{};
+ void set_event_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_EventName::kFieldId, data, size);
+ }
+ void set_event_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_EventName::kFieldId, chars.data, chars.size);
+ }
+ void set_event_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GenericFtraceEvent_Field,
+ GenericFtraceEvent>;
+
+ static constexpr FieldMetadata_Field kField{};
+ template <typename T = GenericFtraceEvent_Field> T* add_field() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class GenericFtraceEvent_Field_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GenericFtraceEvent_Field_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GenericFtraceEvent_Field_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GenericFtraceEvent_Field_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_str_value() const { return at<3>().valid(); }
+ ::protozero::ConstChars str_value() const { return at<3>().as_string(); }
+ bool has_int_value() const { return at<4>().valid(); }
+ int64_t int_value() const { return at<4>().as_int64(); }
+ bool has_uint_value() const { return at<5>().valid(); }
+ uint64_t uint_value() const { return at<5>().as_uint64(); }
+};
+
+class GenericFtraceEvent_Field : public ::protozero::Message {
+ public:
+ using Decoder = GenericFtraceEvent_Field_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStrValueFieldNumber = 3,
+ kIntValueFieldNumber = 4,
+ kUintValueFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GenericFtraceEvent.Field"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GenericFtraceEvent_Field>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StrValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GenericFtraceEvent_Field>;
+
+ static constexpr FieldMetadata_StrValue kStrValue{};
+ void set_str_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StrValue::kFieldId, data, size);
+ }
+ void set_str_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StrValue::kFieldId, chars.data, chars.size);
+ }
+ void set_str_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StrValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ GenericFtraceEvent_Field>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UintValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GenericFtraceEvent_Field>;
+
+ static constexpr FieldMetadata_UintValue kUintValue{};
+ void set_uint_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UintValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/android_fs.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_ANDROID_FS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_ANDROID_FS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidFsFsyncStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidFsFsyncStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidFsFsyncStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidFsFsyncStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cmdline() const { return at<1>().valid(); }
+ ::protozero::ConstChars cmdline() const { return at<1>().as_string(); }
+ bool has_i_size() const { return at<2>().valid(); }
+ int64_t i_size() const { return at<2>().as_int64(); }
+ bool has_ino() const { return at<3>().valid(); }
+ uint64_t ino() const { return at<3>().as_uint64(); }
+ bool has_pathbuf() const { return at<4>().valid(); }
+ ::protozero::ConstChars pathbuf() const { return at<4>().as_string(); }
+ bool has_pid() const { return at<5>().valid(); }
+ int32_t pid() const { return at<5>().as_int32(); }
+};
+
+class AndroidFsFsyncStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidFsFsyncStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kCmdlineFieldNumber = 1,
+ kISizeFieldNumber = 2,
+ kInoFieldNumber = 3,
+ kPathbufFieldNumber = 4,
+ kPidFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidFsFsyncStartFtraceEvent"; }
+
+
+ using FieldMetadata_Cmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidFsFsyncStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmdline kCmdline{};
+ void set_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, data, size);
+ }
+ void set_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, chars.data, chars.size);
+ }
+ void set_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ISize =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsFsyncStartFtraceEvent>;
+
+ static constexpr FieldMetadata_ISize kISize{};
+ void set_i_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ISize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidFsFsyncStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pathbuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidFsFsyncStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Pathbuf kPathbuf{};
+ void set_pathbuf(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Pathbuf::kFieldId, data, size);
+ }
+ void set_pathbuf(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Pathbuf::kFieldId, chars.data, chars.size);
+ }
+ void set_pathbuf(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pathbuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsFsyncStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidFsFsyncEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidFsFsyncEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidFsFsyncEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidFsFsyncEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes() const { return at<1>().valid(); }
+ int32_t bytes() const { return at<1>().as_int32(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+};
+
+class AndroidFsFsyncEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidFsFsyncEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidFsFsyncEndFtraceEvent"; }
+
+
+ using FieldMetadata_Bytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsFsyncEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytes kBytes{};
+ void set_bytes(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidFsFsyncEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsFsyncEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidFsDatawriteStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidFsDatawriteStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidFsDatawriteStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidFsDatawriteStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes() const { return at<1>().valid(); }
+ int32_t bytes() const { return at<1>().as_int32(); }
+ bool has_cmdline() const { return at<2>().valid(); }
+ ::protozero::ConstChars cmdline() const { return at<2>().as_string(); }
+ bool has_i_size() const { return at<3>().valid(); }
+ int64_t i_size() const { return at<3>().as_int64(); }
+ bool has_ino() const { return at<4>().valid(); }
+ uint64_t ino() const { return at<4>().as_uint64(); }
+ bool has_offset() const { return at<5>().valid(); }
+ int64_t offset() const { return at<5>().as_int64(); }
+ bool has_pathbuf() const { return at<6>().valid(); }
+ ::protozero::ConstChars pathbuf() const { return at<6>().as_string(); }
+ bool has_pid() const { return at<7>().valid(); }
+ int32_t pid() const { return at<7>().as_int32(); }
+};
+
+class AndroidFsDatawriteStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidFsDatawriteStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesFieldNumber = 1,
+ kCmdlineFieldNumber = 2,
+ kISizeFieldNumber = 3,
+ kInoFieldNumber = 4,
+ kOffsetFieldNumber = 5,
+ kPathbufFieldNumber = 6,
+ kPidFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidFsDatawriteStartFtraceEvent"; }
+
+
+ using FieldMetadata_Bytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsDatawriteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytes kBytes{};
+ void set_bytes(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidFsDatawriteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmdline kCmdline{};
+ void set_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, data, size);
+ }
+ void set_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, chars.data, chars.size);
+ }
+ void set_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ISize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsDatawriteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_ISize kISize{};
+ void set_i_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ISize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidFsDatawriteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsDatawriteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pathbuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidFsDatawriteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Pathbuf kPathbuf{};
+ void set_pathbuf(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Pathbuf::kFieldId, data, size);
+ }
+ void set_pathbuf(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Pathbuf::kFieldId, chars.data, chars.size);
+ }
+ void set_pathbuf(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pathbuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsDatawriteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidFsDatawriteEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidFsDatawriteEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidFsDatawriteEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidFsDatawriteEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes() const { return at<1>().valid(); }
+ int32_t bytes() const { return at<1>().as_int32(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+};
+
+class AndroidFsDatawriteEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidFsDatawriteEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidFsDatawriteEndFtraceEvent"; }
+
+
+ using FieldMetadata_Bytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsDatawriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytes kBytes{};
+ void set_bytes(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidFsDatawriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsDatawriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidFsDatareadStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidFsDatareadStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidFsDatareadStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidFsDatareadStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes() const { return at<1>().valid(); }
+ int32_t bytes() const { return at<1>().as_int32(); }
+ bool has_cmdline() const { return at<2>().valid(); }
+ ::protozero::ConstChars cmdline() const { return at<2>().as_string(); }
+ bool has_i_size() const { return at<3>().valid(); }
+ int64_t i_size() const { return at<3>().as_int64(); }
+ bool has_ino() const { return at<4>().valid(); }
+ uint64_t ino() const { return at<4>().as_uint64(); }
+ bool has_offset() const { return at<5>().valid(); }
+ int64_t offset() const { return at<5>().as_int64(); }
+ bool has_pathbuf() const { return at<6>().valid(); }
+ ::protozero::ConstChars pathbuf() const { return at<6>().as_string(); }
+ bool has_pid() const { return at<7>().valid(); }
+ int32_t pid() const { return at<7>().as_int32(); }
+};
+
+class AndroidFsDatareadStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidFsDatareadStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesFieldNumber = 1,
+ kCmdlineFieldNumber = 2,
+ kISizeFieldNumber = 3,
+ kInoFieldNumber = 4,
+ kOffsetFieldNumber = 5,
+ kPathbufFieldNumber = 6,
+ kPidFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidFsDatareadStartFtraceEvent"; }
+
+
+ using FieldMetadata_Bytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsDatareadStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytes kBytes{};
+ void set_bytes(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidFsDatareadStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmdline kCmdline{};
+ void set_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, data, size);
+ }
+ void set_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, chars.data, chars.size);
+ }
+ void set_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ISize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsDatareadStartFtraceEvent>;
+
+ static constexpr FieldMetadata_ISize kISize{};
+ void set_i_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ISize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidFsDatareadStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsDatareadStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pathbuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ AndroidFsDatareadStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Pathbuf kPathbuf{};
+ void set_pathbuf(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Pathbuf::kFieldId, data, size);
+ }
+ void set_pathbuf(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Pathbuf::kFieldId, chars.data, chars.size);
+ }
+ void set_pathbuf(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pathbuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsDatareadStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AndroidFsDatareadEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidFsDatareadEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidFsDatareadEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidFsDatareadEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes() const { return at<1>().valid(); }
+ int32_t bytes() const { return at<1>().as_int32(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+};
+
+class AndroidFsDatareadEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AndroidFsDatareadEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidFsDatareadEndFtraceEvent"; }
+
+
+ using FieldMetadata_Bytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidFsDatareadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytes kBytes{};
+ void set_bytes(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AndroidFsDatareadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidFsDatareadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/binder.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_BINDER_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_BINDER_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class BinderReturnFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderReturnFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderReturnFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderReturnFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cmd() const { return at<1>().valid(); }
+ uint32_t cmd() const { return at<1>().as_uint32(); }
+};
+
+class BinderReturnFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderReturnFtraceEvent_Decoder;
+ enum : int32_t {
+ kCmdFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderReturnFtraceEvent"; }
+
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BinderReturnFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderCommandFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderCommandFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderCommandFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderCommandFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cmd() const { return at<1>().valid(); }
+ uint32_t cmd() const { return at<1>().as_uint32(); }
+};
+
+class BinderCommandFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderCommandFtraceEvent_Decoder;
+ enum : int32_t {
+ kCmdFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderCommandFtraceEvent"; }
+
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BinderCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderTransactionAllocBufFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderTransactionAllocBufFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderTransactionAllocBufFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderTransactionAllocBufFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_data_size() const { return at<1>().valid(); }
+ uint64_t data_size() const { return at<1>().as_uint64(); }
+ bool has_debug_id() const { return at<2>().valid(); }
+ int32_t debug_id() const { return at<2>().as_int32(); }
+ bool has_offsets_size() const { return at<3>().valid(); }
+ uint64_t offsets_size() const { return at<3>().as_uint64(); }
+ bool has_extra_buffers_size() const { return at<4>().valid(); }
+ uint64_t extra_buffers_size() const { return at<4>().as_uint64(); }
+};
+
+class BinderTransactionAllocBufFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderTransactionAllocBufFtraceEvent_Decoder;
+ enum : int32_t {
+ kDataSizeFieldNumber = 1,
+ kDebugIdFieldNumber = 2,
+ kOffsetsSizeFieldNumber = 3,
+ kExtraBuffersSizeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderTransactionAllocBufFtraceEvent"; }
+
+
+ using FieldMetadata_DataSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BinderTransactionAllocBufFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize kDataSize{};
+ void set_data_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DebugId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderTransactionAllocBufFtraceEvent>;
+
+ static constexpr FieldMetadata_DebugId kDebugId{};
+ void set_debug_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DebugId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OffsetsSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BinderTransactionAllocBufFtraceEvent>;
+
+ static constexpr FieldMetadata_OffsetsSize kOffsetsSize{};
+ void set_offsets_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OffsetsSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraBuffersSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BinderTransactionAllocBufFtraceEvent>;
+
+ static constexpr FieldMetadata_ExtraBuffersSize kExtraBuffersSize{};
+ void set_extra_buffers_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExtraBuffersSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderUnlockFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderUnlockFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderUnlockFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderUnlockFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tag() const { return at<1>().valid(); }
+ ::protozero::ConstChars tag() const { return at<1>().as_string(); }
+};
+
+class BinderUnlockFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderUnlockFtraceEvent_Decoder;
+ enum : int32_t {
+ kTagFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderUnlockFtraceEvent"; }
+
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BinderUnlockFtraceEvent>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, data, size);
+ }
+ void set_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, chars.data, chars.size);
+ }
+ void set_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderLockedFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderLockedFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderLockedFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderLockedFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tag() const { return at<1>().valid(); }
+ ::protozero::ConstChars tag() const { return at<1>().as_string(); }
+};
+
+class BinderLockedFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderLockedFtraceEvent_Decoder;
+ enum : int32_t {
+ kTagFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderLockedFtraceEvent"; }
+
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BinderLockedFtraceEvent>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, data, size);
+ }
+ void set_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, chars.data, chars.size);
+ }
+ void set_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderLockFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderLockFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderLockFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderLockFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tag() const { return at<1>().valid(); }
+ ::protozero::ConstChars tag() const { return at<1>().as_string(); }
+};
+
+class BinderLockFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderLockFtraceEvent_Decoder;
+ enum : int32_t {
+ kTagFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderLockFtraceEvent"; }
+
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BinderLockFtraceEvent>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, data, size);
+ }
+ void set_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, chars.data, chars.size);
+ }
+ void set_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderSetPriorityFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderSetPriorityFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderSetPriorityFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderSetPriorityFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_proc() const { return at<1>().valid(); }
+ int32_t proc() const { return at<1>().as_int32(); }
+ bool has_thread() const { return at<2>().valid(); }
+ int32_t thread() const { return at<2>().as_int32(); }
+ bool has_old_prio() const { return at<3>().valid(); }
+ uint32_t old_prio() const { return at<3>().as_uint32(); }
+ bool has_new_prio() const { return at<4>().valid(); }
+ uint32_t new_prio() const { return at<4>().as_uint32(); }
+ bool has_desired_prio() const { return at<5>().valid(); }
+ uint32_t desired_prio() const { return at<5>().as_uint32(); }
+};
+
+class BinderSetPriorityFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderSetPriorityFtraceEvent_Decoder;
+ enum : int32_t {
+ kProcFieldNumber = 1,
+ kThreadFieldNumber = 2,
+ kOldPrioFieldNumber = 3,
+ kNewPrioFieldNumber = 4,
+ kDesiredPrioFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderSetPriorityFtraceEvent"; }
+
+
+ using FieldMetadata_Proc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderSetPriorityFtraceEvent>;
+
+ static constexpr FieldMetadata_Proc kProc{};
+ void set_proc(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Proc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Thread =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderSetPriorityFtraceEvent>;
+
+ static constexpr FieldMetadata_Thread kThread{};
+ void set_thread(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Thread::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BinderSetPriorityFtraceEvent>;
+
+ static constexpr FieldMetadata_OldPrio kOldPrio{};
+ void set_old_prio(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldPrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BinderSetPriorityFtraceEvent>;
+
+ static constexpr FieldMetadata_NewPrio kNewPrio{};
+ void set_new_prio(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewPrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DesiredPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BinderSetPriorityFtraceEvent>;
+
+ static constexpr FieldMetadata_DesiredPrio kDesiredPrio{};
+ void set_desired_prio(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DesiredPrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderTransactionReceivedFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderTransactionReceivedFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderTransactionReceivedFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderTransactionReceivedFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_debug_id() const { return at<1>().valid(); }
+ int32_t debug_id() const { return at<1>().as_int32(); }
+};
+
+class BinderTransactionReceivedFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderTransactionReceivedFtraceEvent_Decoder;
+ enum : int32_t {
+ kDebugIdFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderTransactionReceivedFtraceEvent"; }
+
+
+ using FieldMetadata_DebugId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderTransactionReceivedFtraceEvent>;
+
+ static constexpr FieldMetadata_DebugId kDebugId{};
+ void set_debug_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DebugId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BinderTransactionFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BinderTransactionFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BinderTransactionFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BinderTransactionFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_debug_id() const { return at<1>().valid(); }
+ int32_t debug_id() const { return at<1>().as_int32(); }
+ bool has_target_node() const { return at<2>().valid(); }
+ int32_t target_node() const { return at<2>().as_int32(); }
+ bool has_to_proc() const { return at<3>().valid(); }
+ int32_t to_proc() const { return at<3>().as_int32(); }
+ bool has_to_thread() const { return at<4>().valid(); }
+ int32_t to_thread() const { return at<4>().as_int32(); }
+ bool has_reply() const { return at<5>().valid(); }
+ int32_t reply() const { return at<5>().as_int32(); }
+ bool has_code() const { return at<6>().valid(); }
+ uint32_t code() const { return at<6>().as_uint32(); }
+ bool has_flags() const { return at<7>().valid(); }
+ uint32_t flags() const { return at<7>().as_uint32(); }
+};
+
+class BinderTransactionFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BinderTransactionFtraceEvent_Decoder;
+ enum : int32_t {
+ kDebugIdFieldNumber = 1,
+ kTargetNodeFieldNumber = 2,
+ kToProcFieldNumber = 3,
+ kToThreadFieldNumber = 4,
+ kReplyFieldNumber = 5,
+ kCodeFieldNumber = 6,
+ kFlagsFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BinderTransactionFtraceEvent"; }
+
+
+ using FieldMetadata_DebugId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderTransactionFtraceEvent>;
+
+ static constexpr FieldMetadata_DebugId kDebugId{};
+ void set_debug_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DebugId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetNode =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderTransactionFtraceEvent>;
+
+ static constexpr FieldMetadata_TargetNode kTargetNode{};
+ void set_target_node(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetNode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ToProc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderTransactionFtraceEvent>;
+
+ static constexpr FieldMetadata_ToProc kToProc{};
+ void set_to_proc(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ToProc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ToThread =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderTransactionFtraceEvent>;
+
+ static constexpr FieldMetadata_ToThread kToThread{};
+ void set_to_thread(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ToThread::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Reply =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BinderTransactionFtraceEvent>;
+
+ static constexpr FieldMetadata_Reply kReply{};
+ void set_reply(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reply::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Code =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BinderTransactionFtraceEvent>;
+
+ static constexpr FieldMetadata_Code kCode{};
+ void set_code(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Code::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BinderTransactionFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/block.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_BLOCK_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_BLOCK_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class BlockUnplugFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockUnplugFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockUnplugFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockUnplugFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nr_rq() const { return at<1>().valid(); }
+ int32_t nr_rq() const { return at<1>().as_int32(); }
+ bool has_comm() const { return at<2>().valid(); }
+ ::protozero::ConstChars comm() const { return at<2>().as_string(); }
+};
+
+class BlockUnplugFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockUnplugFtraceEvent_Decoder;
+ enum : int32_t {
+ kNrRqFieldNumber = 1,
+ kCommFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockUnplugFtraceEvent"; }
+
+
+ using FieldMetadata_NrRq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlockUnplugFtraceEvent>;
+
+ static constexpr FieldMetadata_NrRq kNrRq{};
+ void set_nr_rq(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrRq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockUnplugFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockTouchBufferFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockTouchBufferFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockTouchBufferFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockTouchBufferFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_size() const { return at<3>().valid(); }
+ uint64_t size() const { return at<3>().as_uint64(); }
+};
+
+class BlockTouchBufferFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockTouchBufferFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kSizeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockTouchBufferFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockTouchBufferFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockTouchBufferFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockTouchBufferFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockSplitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockSplitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockSplitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockSplitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_new_sector() const { return at<3>().valid(); }
+ uint64_t new_sector() const { return at<3>().as_uint64(); }
+ bool has_rwbs() const { return at<4>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<4>().as_string(); }
+ bool has_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars comm() const { return at<5>().as_string(); }
+};
+
+class BlockSplitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockSplitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNewSectorFieldNumber = 3,
+ kRwbsFieldNumber = 4,
+ kCommFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockSplitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockSplitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockSplitFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockSplitFtraceEvent>;
+
+ static constexpr FieldMetadata_NewSector kNewSector{};
+ void set_new_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockSplitFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockSplitFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockSleeprqFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockSleeprqFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockSleeprqFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockSleeprqFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_rwbs() const { return at<4>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<4>().as_string(); }
+ bool has_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars comm() const { return at<5>().as_string(); }
+};
+
+class BlockSleeprqFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockSleeprqFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kRwbsFieldNumber = 4,
+ kCommFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockSleeprqFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockSleeprqFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockSleeprqFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockSleeprqFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockSleeprqFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockSleeprqFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockRqRequeueFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockRqRequeueFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockRqRequeueFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockRqRequeueFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_errors() const { return at<4>().valid(); }
+ int32_t errors() const { return at<4>().as_int32(); }
+ bool has_rwbs() const { return at<5>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<5>().as_string(); }
+ bool has_cmd() const { return at<6>().valid(); }
+ ::protozero::ConstChars cmd() const { return at<6>().as_string(); }
+};
+
+class BlockRqRequeueFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockRqRequeueFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kErrorsFieldNumber = 4,
+ kRwbsFieldNumber = 5,
+ kCmdFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockRqRequeueFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqRequeueFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqRequeueFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqRequeueFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Errors =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlockRqRequeueFtraceEvent>;
+
+ static constexpr FieldMetadata_Errors kErrors{};
+ void set_errors(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Errors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqRequeueFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqRequeueFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, data, size);
+ }
+ void set_cmd(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, chars.data, chars.size);
+ }
+ void set_cmd(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockRqRemapFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockRqRemapFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockRqRemapFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockRqRemapFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_old_dev() const { return at<4>().valid(); }
+ uint64_t old_dev() const { return at<4>().as_uint64(); }
+ bool has_old_sector() const { return at<5>().valid(); }
+ uint64_t old_sector() const { return at<5>().as_uint64(); }
+ bool has_nr_bios() const { return at<6>().valid(); }
+ uint32_t nr_bios() const { return at<6>().as_uint32(); }
+ bool has_rwbs() const { return at<7>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<7>().as_string(); }
+};
+
+class BlockRqRemapFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockRqRemapFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kOldDevFieldNumber = 4,
+ kOldSectorFieldNumber = 5,
+ kNrBiosFieldNumber = 6,
+ kRwbsFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockRqRemapFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldDev =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_OldDev kOldDev{};
+ void set_old_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldDev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_OldSector kOldSector{};
+ void set_old_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrBios =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_NrBios kNrBios{};
+ void set_nr_bios(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrBios::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockRqInsertFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockRqInsertFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockRqInsertFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockRqInsertFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_bytes() const { return at<4>().valid(); }
+ uint32_t bytes() const { return at<4>().as_uint32(); }
+ bool has_rwbs() const { return at<5>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<5>().as_string(); }
+ bool has_comm() const { return at<6>().valid(); }
+ ::protozero::ConstChars comm() const { return at<6>().as_string(); }
+ bool has_cmd() const { return at<7>().valid(); }
+ ::protozero::ConstChars cmd() const { return at<7>().as_string(); }
+};
+
+class BlockRqInsertFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockRqInsertFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kBytesFieldNumber = 4,
+ kRwbsFieldNumber = 5,
+ kCommFieldNumber = 6,
+ kCmdFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockRqInsertFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqInsertFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqInsertFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqInsertFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqInsertFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytes kBytes{};
+ void set_bytes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqInsertFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqInsertFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqInsertFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, data, size);
+ }
+ void set_cmd(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, chars.data, chars.size);
+ }
+ void set_cmd(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockRqCompleteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockRqCompleteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockRqCompleteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockRqCompleteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_errors() const { return at<4>().valid(); }
+ int32_t errors() const { return at<4>().as_int32(); }
+ bool has_rwbs() const { return at<5>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<5>().as_string(); }
+ bool has_cmd() const { return at<6>().valid(); }
+ ::protozero::ConstChars cmd() const { return at<6>().as_string(); }
+ bool has_error() const { return at<7>().valid(); }
+ int32_t error() const { return at<7>().as_int32(); }
+};
+
+class BlockRqCompleteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockRqCompleteFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kErrorsFieldNumber = 4,
+ kRwbsFieldNumber = 5,
+ kCmdFieldNumber = 6,
+ kErrorFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockRqCompleteFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Errors =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlockRqCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Errors kErrors{};
+ void set_errors(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Errors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, data, size);
+ }
+ void set_cmd(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, chars.data, chars.size);
+ }
+ void set_cmd(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Error =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlockRqCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Error kError{};
+ void set_error(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Error::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockRqAbortFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockRqAbortFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockRqAbortFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockRqAbortFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_errors() const { return at<4>().valid(); }
+ int32_t errors() const { return at<4>().as_int32(); }
+ bool has_rwbs() const { return at<5>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<5>().as_string(); }
+ bool has_cmd() const { return at<6>().valid(); }
+ ::protozero::ConstChars cmd() const { return at<6>().as_string(); }
+};
+
+class BlockRqAbortFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockRqAbortFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kErrorsFieldNumber = 4,
+ kRwbsFieldNumber = 5,
+ kCmdFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockRqAbortFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Errors =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlockRqAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_Errors kErrors{};
+ void set_errors(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Errors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, data, size);
+ }
+ void set_cmd(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, chars.data, chars.size);
+ }
+ void set_cmd(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockPlugFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockPlugFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockPlugFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockPlugFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+};
+
+class BlockPlugFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockPlugFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockPlugFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockPlugFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockGetrqFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockGetrqFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockGetrqFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockGetrqFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_rwbs() const { return at<4>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<4>().as_string(); }
+ bool has_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars comm() const { return at<5>().as_string(); }
+};
+
+class BlockGetrqFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockGetrqFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kRwbsFieldNumber = 4,
+ kCommFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockGetrqFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockGetrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockGetrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockGetrqFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockGetrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockGetrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockDirtyBufferFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockDirtyBufferFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockDirtyBufferFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockDirtyBufferFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_size() const { return at<3>().valid(); }
+ uint64_t size() const { return at<3>().as_uint64(); }
+};
+
+class BlockDirtyBufferFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockDirtyBufferFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kSizeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockDirtyBufferFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockDirtyBufferFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockDirtyBufferFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockDirtyBufferFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockBioRemapFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockBioRemapFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockBioRemapFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockBioRemapFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_old_dev() const { return at<4>().valid(); }
+ uint64_t old_dev() const { return at<4>().as_uint64(); }
+ bool has_old_sector() const { return at<5>().valid(); }
+ uint64_t old_sector() const { return at<5>().as_uint64(); }
+ bool has_rwbs() const { return at<6>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<6>().as_string(); }
+};
+
+class BlockBioRemapFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockBioRemapFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kOldDevFieldNumber = 4,
+ kOldSectorFieldNumber = 5,
+ kRwbsFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockBioRemapFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockBioRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldDev =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_OldDev kOldDev{};
+ void set_old_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldDev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_OldSector kOldSector{};
+ void set_old_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioRemapFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockBioQueueFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockBioQueueFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockBioQueueFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockBioQueueFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_rwbs() const { return at<4>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<4>().as_string(); }
+ bool has_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars comm() const { return at<5>().as_string(); }
+};
+
+class BlockBioQueueFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockBioQueueFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kRwbsFieldNumber = 4,
+ kCommFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockBioQueueFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockBioQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockBioFrontmergeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockBioFrontmergeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockBioFrontmergeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockBioFrontmergeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_rwbs() const { return at<4>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<4>().as_string(); }
+ bool has_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars comm() const { return at<5>().as_string(); }
+};
+
+class BlockBioFrontmergeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockBioFrontmergeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kRwbsFieldNumber = 4,
+ kCommFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockBioFrontmergeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioFrontmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioFrontmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockBioFrontmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioFrontmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioFrontmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockBioCompleteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockBioCompleteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockBioCompleteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockBioCompleteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_error() const { return at<4>().valid(); }
+ int32_t error() const { return at<4>().as_int32(); }
+ bool has_rwbs() const { return at<5>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<5>().as_string(); }
+};
+
+class BlockBioCompleteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockBioCompleteFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kErrorFieldNumber = 4,
+ kRwbsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockBioCompleteFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockBioCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Error =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ BlockBioCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Error kError{};
+ void set_error(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Error::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockBioBounceFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockBioBounceFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockBioBounceFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockBioBounceFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_rwbs() const { return at<4>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<4>().as_string(); }
+ bool has_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars comm() const { return at<5>().as_string(); }
+};
+
+class BlockBioBounceFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockBioBounceFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kRwbsFieldNumber = 4,
+ kCommFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockBioBounceFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioBounceFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioBounceFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockBioBounceFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioBounceFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioBounceFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockBioBackmergeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockBioBackmergeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockBioBackmergeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockBioBackmergeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_rwbs() const { return at<4>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<4>().as_string(); }
+ bool has_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars comm() const { return at<5>().as_string(); }
+};
+
+class BlockBioBackmergeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockBioBackmergeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kRwbsFieldNumber = 4,
+ kCommFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockBioBackmergeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioBackmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockBioBackmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockBioBackmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioBackmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockBioBackmergeFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BlockRqIssueFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BlockRqIssueFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BlockRqIssueFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BlockRqIssueFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sector() const { return at<2>().valid(); }
+ uint64_t sector() const { return at<2>().as_uint64(); }
+ bool has_nr_sector() const { return at<3>().valid(); }
+ uint32_t nr_sector() const { return at<3>().as_uint32(); }
+ bool has_bytes() const { return at<4>().valid(); }
+ uint32_t bytes() const { return at<4>().as_uint32(); }
+ bool has_rwbs() const { return at<5>().valid(); }
+ ::protozero::ConstChars rwbs() const { return at<5>().as_string(); }
+ bool has_comm() const { return at<6>().valid(); }
+ ::protozero::ConstChars comm() const { return at<6>().as_string(); }
+ bool has_cmd() const { return at<7>().valid(); }
+ ::protozero::ConstChars cmd() const { return at<7>().as_string(); }
+};
+
+class BlockRqIssueFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = BlockRqIssueFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSectorFieldNumber = 2,
+ kNrSectorFieldNumber = 3,
+ kBytesFieldNumber = 4,
+ kRwbsFieldNumber = 5,
+ kCommFieldNumber = 6,
+ kCmdFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BlockRqIssueFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqIssueFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BlockRqIssueFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSector =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqIssueFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSector kNrSector{};
+ void set_nr_sector(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BlockRqIssueFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytes kBytes{};
+ void set_bytes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rwbs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqIssueFtraceEvent>;
+
+ static constexpr FieldMetadata_Rwbs kRwbs{};
+ void set_rwbs(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, data, size);
+ }
+ void set_rwbs(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Rwbs::kFieldId, chars.data, chars.size);
+ }
+ void set_rwbs(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rwbs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqIssueFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BlockRqIssueFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, data, size);
+ }
+ void set_cmd(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmd::kFieldId, chars.data, chars.size);
+ }
+ void set_cmd(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/cgroup.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CGROUP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CGROUP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class CgroupSetupRootFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupSetupRootFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupSetupRootFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupSetupRootFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_root() const { return at<1>().valid(); }
+ int32_t root() const { return at<1>().as_int32(); }
+ bool has_ss_mask() const { return at<2>().valid(); }
+ uint32_t ss_mask() const { return at<2>().as_uint32(); }
+ bool has_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars name() const { return at<3>().as_string(); }
+};
+
+class CgroupSetupRootFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupSetupRootFtraceEvent_Decoder;
+ enum : int32_t {
+ kRootFieldNumber = 1,
+ kSsMaskFieldNumber = 2,
+ kNameFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupSetupRootFtraceEvent"; }
+
+
+ using FieldMetadata_Root =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupSetupRootFtraceEvent>;
+
+ static constexpr FieldMetadata_Root kRoot{};
+ void set_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Root::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SsMask =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CgroupSetupRootFtraceEvent>;
+
+ static constexpr FieldMetadata_SsMask kSsMask{};
+ void set_ss_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SsMask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupSetupRootFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupRenameFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupRenameFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupRenameFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupRenameFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_root() const { return at<1>().valid(); }
+ int32_t root() const { return at<1>().as_int32(); }
+ bool has_id() const { return at<2>().valid(); }
+ int32_t id() const { return at<2>().as_int32(); }
+ bool has_cname() const { return at<3>().valid(); }
+ ::protozero::ConstChars cname() const { return at<3>().as_string(); }
+ bool has_level() const { return at<4>().valid(); }
+ int32_t level() const { return at<4>().as_int32(); }
+ bool has_path() const { return at<5>().valid(); }
+ ::protozero::ConstChars path() const { return at<5>().as_string(); }
+};
+
+class CgroupRenameFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupRenameFtraceEvent_Decoder;
+ enum : int32_t {
+ kRootFieldNumber = 1,
+ kIdFieldNumber = 2,
+ kCnameFieldNumber = 3,
+ kLevelFieldNumber = 4,
+ kPathFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupRenameFtraceEvent"; }
+
+
+ using FieldMetadata_Root =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Root kRoot{};
+ void set_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Root::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cname =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Cname kCname{};
+ void set_cname(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, data, size);
+ }
+ void set_cname(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, chars.data, chars.size);
+ }
+ void set_cname(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cname::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Path =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Path kPath{};
+ void set_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Path::kFieldId, data, size);
+ }
+ void set_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Path::kFieldId, chars.data, chars.size);
+ }
+ void set_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Path::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupReleaseFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupReleaseFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupReleaseFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupReleaseFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_root() const { return at<1>().valid(); }
+ int32_t root() const { return at<1>().as_int32(); }
+ bool has_id() const { return at<2>().valid(); }
+ int32_t id() const { return at<2>().as_int32(); }
+ bool has_cname() const { return at<3>().valid(); }
+ ::protozero::ConstChars cname() const { return at<3>().as_string(); }
+ bool has_level() const { return at<4>().valid(); }
+ int32_t level() const { return at<4>().as_int32(); }
+ bool has_path() const { return at<5>().valid(); }
+ ::protozero::ConstChars path() const { return at<5>().as_string(); }
+};
+
+class CgroupReleaseFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupReleaseFtraceEvent_Decoder;
+ enum : int32_t {
+ kRootFieldNumber = 1,
+ kIdFieldNumber = 2,
+ kCnameFieldNumber = 3,
+ kLevelFieldNumber = 4,
+ kPathFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupReleaseFtraceEvent"; }
+
+
+ using FieldMetadata_Root =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupReleaseFtraceEvent>;
+
+ static constexpr FieldMetadata_Root kRoot{};
+ void set_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Root::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupReleaseFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cname =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupReleaseFtraceEvent>;
+
+ static constexpr FieldMetadata_Cname kCname{};
+ void set_cname(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, data, size);
+ }
+ void set_cname(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, chars.data, chars.size);
+ }
+ void set_cname(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cname::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupReleaseFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Path =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupReleaseFtraceEvent>;
+
+ static constexpr FieldMetadata_Path kPath{};
+ void set_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Path::kFieldId, data, size);
+ }
+ void set_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Path::kFieldId, chars.data, chars.size);
+ }
+ void set_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Path::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupDestroyRootFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupDestroyRootFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupDestroyRootFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupDestroyRootFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_root() const { return at<1>().valid(); }
+ int32_t root() const { return at<1>().as_int32(); }
+ bool has_ss_mask() const { return at<2>().valid(); }
+ uint32_t ss_mask() const { return at<2>().as_uint32(); }
+ bool has_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars name() const { return at<3>().as_string(); }
+};
+
+class CgroupDestroyRootFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupDestroyRootFtraceEvent_Decoder;
+ enum : int32_t {
+ kRootFieldNumber = 1,
+ kSsMaskFieldNumber = 2,
+ kNameFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupDestroyRootFtraceEvent"; }
+
+
+ using FieldMetadata_Root =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupDestroyRootFtraceEvent>;
+
+ static constexpr FieldMetadata_Root kRoot{};
+ void set_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Root::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SsMask =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CgroupDestroyRootFtraceEvent>;
+
+ static constexpr FieldMetadata_SsMask kSsMask{};
+ void set_ss_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SsMask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupDestroyRootFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupTransferTasksFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupTransferTasksFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupTransferTasksFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupTransferTasksFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dst_root() const { return at<1>().valid(); }
+ int32_t dst_root() const { return at<1>().as_int32(); }
+ bool has_dst_id() const { return at<2>().valid(); }
+ int32_t dst_id() const { return at<2>().as_int32(); }
+ bool has_pid() const { return at<3>().valid(); }
+ int32_t pid() const { return at<3>().as_int32(); }
+ bool has_comm() const { return at<4>().valid(); }
+ ::protozero::ConstChars comm() const { return at<4>().as_string(); }
+ bool has_cname() const { return at<5>().valid(); }
+ ::protozero::ConstChars cname() const { return at<5>().as_string(); }
+ bool has_dst_level() const { return at<6>().valid(); }
+ int32_t dst_level() const { return at<6>().as_int32(); }
+ bool has_dst_path() const { return at<7>().valid(); }
+ ::protozero::ConstChars dst_path() const { return at<7>().as_string(); }
+};
+
+class CgroupTransferTasksFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupTransferTasksFtraceEvent_Decoder;
+ enum : int32_t {
+ kDstRootFieldNumber = 1,
+ kDstIdFieldNumber = 2,
+ kPidFieldNumber = 3,
+ kCommFieldNumber = 4,
+ kCnameFieldNumber = 5,
+ kDstLevelFieldNumber = 6,
+ kDstPathFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupTransferTasksFtraceEvent"; }
+
+
+ using FieldMetadata_DstRoot =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupTransferTasksFtraceEvent>;
+
+ static constexpr FieldMetadata_DstRoot kDstRoot{};
+ void set_dst_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstRoot::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupTransferTasksFtraceEvent>;
+
+ static constexpr FieldMetadata_DstId kDstId{};
+ void set_dst_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupTransferTasksFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupTransferTasksFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cname =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupTransferTasksFtraceEvent>;
+
+ static constexpr FieldMetadata_Cname kCname{};
+ void set_cname(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, data, size);
+ }
+ void set_cname(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, chars.data, chars.size);
+ }
+ void set_cname(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cname::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstLevel =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupTransferTasksFtraceEvent>;
+
+ static constexpr FieldMetadata_DstLevel kDstLevel{};
+ void set_dst_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstLevel::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstPath =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupTransferTasksFtraceEvent>;
+
+ static constexpr FieldMetadata_DstPath kDstPath{};
+ void set_dst_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DstPath::kFieldId, data, size);
+ }
+ void set_dst_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DstPath::kFieldId, chars.data, chars.size);
+ }
+ void set_dst_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstPath::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupRmdirFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupRmdirFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupRmdirFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupRmdirFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_root() const { return at<1>().valid(); }
+ int32_t root() const { return at<1>().as_int32(); }
+ bool has_id() const { return at<2>().valid(); }
+ int32_t id() const { return at<2>().as_int32(); }
+ bool has_cname() const { return at<3>().valid(); }
+ ::protozero::ConstChars cname() const { return at<3>().as_string(); }
+ bool has_level() const { return at<4>().valid(); }
+ int32_t level() const { return at<4>().as_int32(); }
+ bool has_path() const { return at<5>().valid(); }
+ ::protozero::ConstChars path() const { return at<5>().as_string(); }
+};
+
+class CgroupRmdirFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupRmdirFtraceEvent_Decoder;
+ enum : int32_t {
+ kRootFieldNumber = 1,
+ kIdFieldNumber = 2,
+ kCnameFieldNumber = 3,
+ kLevelFieldNumber = 4,
+ kPathFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupRmdirFtraceEvent"; }
+
+
+ using FieldMetadata_Root =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupRmdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Root kRoot{};
+ void set_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Root::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupRmdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cname =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupRmdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Cname kCname{};
+ void set_cname(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, data, size);
+ }
+ void set_cname(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, chars.data, chars.size);
+ }
+ void set_cname(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cname::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupRmdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Path =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupRmdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Path kPath{};
+ void set_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Path::kFieldId, data, size);
+ }
+ void set_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Path::kFieldId, chars.data, chars.size);
+ }
+ void set_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Path::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupRemountFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupRemountFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupRemountFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupRemountFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_root() const { return at<1>().valid(); }
+ int32_t root() const { return at<1>().as_int32(); }
+ bool has_ss_mask() const { return at<2>().valid(); }
+ uint32_t ss_mask() const { return at<2>().as_uint32(); }
+ bool has_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars name() const { return at<3>().as_string(); }
+};
+
+class CgroupRemountFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupRemountFtraceEvent_Decoder;
+ enum : int32_t {
+ kRootFieldNumber = 1,
+ kSsMaskFieldNumber = 2,
+ kNameFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupRemountFtraceEvent"; }
+
+
+ using FieldMetadata_Root =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupRemountFtraceEvent>;
+
+ static constexpr FieldMetadata_Root kRoot{};
+ void set_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Root::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SsMask =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CgroupRemountFtraceEvent>;
+
+ static constexpr FieldMetadata_SsMask kSsMask{};
+ void set_ss_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SsMask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupRemountFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupMkdirFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupMkdirFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupMkdirFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupMkdirFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_root() const { return at<1>().valid(); }
+ int32_t root() const { return at<1>().as_int32(); }
+ bool has_id() const { return at<2>().valid(); }
+ int32_t id() const { return at<2>().as_int32(); }
+ bool has_cname() const { return at<3>().valid(); }
+ ::protozero::ConstChars cname() const { return at<3>().as_string(); }
+ bool has_level() const { return at<4>().valid(); }
+ int32_t level() const { return at<4>().as_int32(); }
+ bool has_path() const { return at<5>().valid(); }
+ ::protozero::ConstChars path() const { return at<5>().as_string(); }
+};
+
+class CgroupMkdirFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupMkdirFtraceEvent_Decoder;
+ enum : int32_t {
+ kRootFieldNumber = 1,
+ kIdFieldNumber = 2,
+ kCnameFieldNumber = 3,
+ kLevelFieldNumber = 4,
+ kPathFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupMkdirFtraceEvent"; }
+
+
+ using FieldMetadata_Root =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupMkdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Root kRoot{};
+ void set_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Root::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupMkdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cname =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupMkdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Cname kCname{};
+ void set_cname(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, data, size);
+ }
+ void set_cname(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, chars.data, chars.size);
+ }
+ void set_cname(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cname::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupMkdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Path =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupMkdirFtraceEvent>;
+
+ static constexpr FieldMetadata_Path kPath{};
+ void set_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Path::kFieldId, data, size);
+ }
+ void set_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Path::kFieldId, chars.data, chars.size);
+ }
+ void set_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Path::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CgroupAttachTaskFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CgroupAttachTaskFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CgroupAttachTaskFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CgroupAttachTaskFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dst_root() const { return at<1>().valid(); }
+ int32_t dst_root() const { return at<1>().as_int32(); }
+ bool has_dst_id() const { return at<2>().valid(); }
+ int32_t dst_id() const { return at<2>().as_int32(); }
+ bool has_pid() const { return at<3>().valid(); }
+ int32_t pid() const { return at<3>().as_int32(); }
+ bool has_comm() const { return at<4>().valid(); }
+ ::protozero::ConstChars comm() const { return at<4>().as_string(); }
+ bool has_cname() const { return at<5>().valid(); }
+ ::protozero::ConstChars cname() const { return at<5>().as_string(); }
+ bool has_dst_level() const { return at<6>().valid(); }
+ int32_t dst_level() const { return at<6>().as_int32(); }
+ bool has_dst_path() const { return at<7>().valid(); }
+ ::protozero::ConstChars dst_path() const { return at<7>().as_string(); }
+};
+
+class CgroupAttachTaskFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CgroupAttachTaskFtraceEvent_Decoder;
+ enum : int32_t {
+ kDstRootFieldNumber = 1,
+ kDstIdFieldNumber = 2,
+ kPidFieldNumber = 3,
+ kCommFieldNumber = 4,
+ kCnameFieldNumber = 5,
+ kDstLevelFieldNumber = 6,
+ kDstPathFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CgroupAttachTaskFtraceEvent"; }
+
+
+ using FieldMetadata_DstRoot =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupAttachTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_DstRoot kDstRoot{};
+ void set_dst_root(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstRoot::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupAttachTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_DstId kDstId{};
+ void set_dst_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupAttachTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupAttachTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cname =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupAttachTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Cname kCname{};
+ void set_cname(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, data, size);
+ }
+ void set_cname(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cname::kFieldId, chars.data, chars.size);
+ }
+ void set_cname(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cname::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstLevel =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CgroupAttachTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_DstLevel kDstLevel{};
+ void set_dst_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstLevel::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstPath =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CgroupAttachTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_DstPath kDstPath{};
+ void set_dst_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DstPath::kFieldId, data, size);
+ }
+ void set_dst_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DstPath::kFieldId, chars.data, chars.size);
+ }
+ void set_dst_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstPath::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/clk.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CLK_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CLK_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ClkSetRateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ClkSetRateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClkSetRateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClkSetRateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_rate() const { return at<2>().valid(); }
+ uint64_t rate() const { return at<2>().as_uint64(); }
+};
+
+class ClkSetRateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ClkSetRateFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kRateFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClkSetRateFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ClkSetRateFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rate =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClkSetRateFtraceEvent>;
+
+ static constexpr FieldMetadata_Rate kRate{};
+ void set_rate(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ClkDisableFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ClkDisableFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClkDisableFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClkDisableFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class ClkDisableFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ClkDisableFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClkDisableFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ClkDisableFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ClkEnableFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ClkEnableFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClkEnableFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClkEnableFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class ClkEnableFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ClkEnableFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClkEnableFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ClkEnableFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/cma.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CMA_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CMA_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class CmaAllocInfoFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CmaAllocInfoFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CmaAllocInfoFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CmaAllocInfoFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_align() const { return at<1>().valid(); }
+ uint32_t align() const { return at<1>().as_uint32(); }
+ bool has_count() const { return at<2>().valid(); }
+ uint32_t count() const { return at<2>().as_uint32(); }
+ bool has_err_iso() const { return at<3>().valid(); }
+ uint32_t err_iso() const { return at<3>().as_uint32(); }
+ bool has_err_mig() const { return at<4>().valid(); }
+ uint32_t err_mig() const { return at<4>().as_uint32(); }
+ bool has_err_test() const { return at<5>().valid(); }
+ uint32_t err_test() const { return at<5>().as_uint32(); }
+ bool has_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars name() const { return at<6>().as_string(); }
+ bool has_nr_mapped() const { return at<7>().valid(); }
+ uint64_t nr_mapped() const { return at<7>().as_uint64(); }
+ bool has_nr_migrated() const { return at<8>().valid(); }
+ uint64_t nr_migrated() const { return at<8>().as_uint64(); }
+ bool has_nr_reclaimed() const { return at<9>().valid(); }
+ uint64_t nr_reclaimed() const { return at<9>().as_uint64(); }
+ bool has_pfn() const { return at<10>().valid(); }
+ uint64_t pfn() const { return at<10>().as_uint64(); }
+};
+
+class CmaAllocInfoFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CmaAllocInfoFtraceEvent_Decoder;
+ enum : int32_t {
+ kAlignFieldNumber = 1,
+ kCountFieldNumber = 2,
+ kErrIsoFieldNumber = 3,
+ kErrMigFieldNumber = 4,
+ kErrTestFieldNumber = 5,
+ kNameFieldNumber = 6,
+ kNrMappedFieldNumber = 7,
+ kNrMigratedFieldNumber = 8,
+ kNrReclaimedFieldNumber = 9,
+ kPfnFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CmaAllocInfoFtraceEvent"; }
+
+
+ using FieldMetadata_Align =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_Align kAlign{};
+ void set_align(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Align::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ErrIso =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_ErrIso kErrIso{};
+ void set_err_iso(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ErrIso::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ErrMig =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_ErrMig kErrMig{};
+ void set_err_mig(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ErrMig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ErrTest =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_ErrTest kErrTest{};
+ void set_err_test(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ErrTest::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrMapped =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_NrMapped kNrMapped{};
+ void set_nr_mapped(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrMapped::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrMigrated =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_NrMigrated kNrMigrated{};
+ void set_nr_migrated(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrMigrated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrReclaimed =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_NrReclaimed kNrReclaimed{};
+ void set_nr_reclaimed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrReclaimed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CmaAllocInfoFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CmaAllocStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CmaAllocStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CmaAllocStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CmaAllocStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_align() const { return at<1>().valid(); }
+ uint32_t align() const { return at<1>().as_uint32(); }
+ bool has_count() const { return at<2>().valid(); }
+ uint32_t count() const { return at<2>().as_uint32(); }
+ bool has_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars name() const { return at<3>().as_string(); }
+};
+
+class CmaAllocStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CmaAllocStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kAlignFieldNumber = 1,
+ kCountFieldNumber = 2,
+ kNameFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CmaAllocStartFtraceEvent"; }
+
+
+ using FieldMetadata_Align =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CmaAllocStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Align kAlign{};
+ void set_align(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Align::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CmaAllocStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CmaAllocStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/compaction.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_COMPACTION_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_COMPACTION_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class MmCompactionWakeupKcompactdFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionWakeupKcompactdFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionWakeupKcompactdFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionWakeupKcompactdFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_order() const { return at<2>().valid(); }
+ int32_t order() const { return at<2>().as_int32(); }
+ bool has_classzone_idx() const { return at<3>().valid(); }
+ uint32_t classzone_idx() const { return at<3>().as_uint32(); }
+ bool has_highest_zoneidx() const { return at<4>().valid(); }
+ uint32_t highest_zoneidx() const { return at<4>().as_uint32(); }
+};
+
+class MmCompactionWakeupKcompactdFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionWakeupKcompactdFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ kClasszoneIdxFieldNumber = 3,
+ kHighestZoneidxFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionWakeupKcompactdFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionWakeupKcompactdFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionWakeupKcompactdFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClasszoneIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionWakeupKcompactdFtraceEvent>;
+
+ static constexpr FieldMetadata_ClasszoneIdx kClasszoneIdx{};
+ void set_classzone_idx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClasszoneIdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HighestZoneidx =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionWakeupKcompactdFtraceEvent>;
+
+ static constexpr FieldMetadata_HighestZoneidx kHighestZoneidx{};
+ void set_highest_zoneidx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HighestZoneidx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionTryToCompactPagesFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionTryToCompactPagesFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionTryToCompactPagesFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionTryToCompactPagesFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_order() const { return at<1>().valid(); }
+ int32_t order() const { return at<1>().as_int32(); }
+ bool has_gfp_mask() const { return at<2>().valid(); }
+ uint32_t gfp_mask() const { return at<2>().as_uint32(); }
+ bool has_mode() const { return at<3>().valid(); }
+ uint32_t mode() const { return at<3>().as_uint32(); }
+ bool has_prio() const { return at<4>().valid(); }
+ int32_t prio() const { return at<4>().as_int32(); }
+};
+
+class MmCompactionTryToCompactPagesFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionTryToCompactPagesFtraceEvent_Decoder;
+ enum : int32_t {
+ kOrderFieldNumber = 1,
+ kGfpMaskFieldNumber = 2,
+ kModeFieldNumber = 3,
+ kPrioFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionTryToCompactPagesFtraceEvent"; }
+
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionTryToCompactPagesFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GfpMask =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionTryToCompactPagesFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpMask kGfpMask{};
+ void set_gfp_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpMask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionTryToCompactPagesFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionTryToCompactPagesFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionSuitableFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionSuitableFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionSuitableFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionSuitableFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_idx() const { return at<2>().valid(); }
+ uint32_t idx() const { return at<2>().as_uint32(); }
+ bool has_order() const { return at<3>().valid(); }
+ int32_t order() const { return at<3>().as_int32(); }
+ bool has_ret() const { return at<4>().valid(); }
+ int32_t ret() const { return at<4>().as_int32(); }
+};
+
+class MmCompactionSuitableFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionSuitableFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kIdxFieldNumber = 2,
+ kOrderFieldNumber = 3,
+ kRetFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionSuitableFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionSuitableFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionSuitableFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionSuitableFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionSuitableFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionMigratepagesFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionMigratepagesFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionMigratepagesFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionMigratepagesFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nr_migrated() const { return at<1>().valid(); }
+ uint64_t nr_migrated() const { return at<1>().as_uint64(); }
+ bool has_nr_failed() const { return at<2>().valid(); }
+ uint64_t nr_failed() const { return at<2>().as_uint64(); }
+};
+
+class MmCompactionMigratepagesFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionMigratepagesFtraceEvent_Decoder;
+ enum : int32_t {
+ kNrMigratedFieldNumber = 1,
+ kNrFailedFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionMigratepagesFtraceEvent"; }
+
+
+ using FieldMetadata_NrMigrated =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionMigratepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrMigrated kNrMigrated{};
+ void set_nr_migrated(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrMigrated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionMigratepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrFailed kNrFailed{};
+ void set_nr_failed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionKcompactdWakeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionKcompactdWakeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionKcompactdWakeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionKcompactdWakeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_order() const { return at<2>().valid(); }
+ int32_t order() const { return at<2>().as_int32(); }
+ bool has_classzone_idx() const { return at<3>().valid(); }
+ uint32_t classzone_idx() const { return at<3>().as_uint32(); }
+ bool has_highest_zoneidx() const { return at<4>().valid(); }
+ uint32_t highest_zoneidx() const { return at<4>().as_uint32(); }
+};
+
+class MmCompactionKcompactdWakeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionKcompactdWakeFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ kClasszoneIdxFieldNumber = 3,
+ kHighestZoneidxFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionKcompactdWakeFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionKcompactdWakeFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionKcompactdWakeFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClasszoneIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionKcompactdWakeFtraceEvent>;
+
+ static constexpr FieldMetadata_ClasszoneIdx kClasszoneIdx{};
+ void set_classzone_idx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClasszoneIdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HighestZoneidx =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionKcompactdWakeFtraceEvent>;
+
+ static constexpr FieldMetadata_HighestZoneidx kHighestZoneidx{};
+ void set_highest_zoneidx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HighestZoneidx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionKcompactdSleepFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionKcompactdSleepFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionKcompactdSleepFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionKcompactdSleepFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+};
+
+class MmCompactionKcompactdSleepFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionKcompactdSleepFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionKcompactdSleepFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionKcompactdSleepFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionIsolateMigratepagesFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionIsolateMigratepagesFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionIsolateMigratepagesFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionIsolateMigratepagesFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_start_pfn() const { return at<1>().valid(); }
+ uint64_t start_pfn() const { return at<1>().as_uint64(); }
+ bool has_end_pfn() const { return at<2>().valid(); }
+ uint64_t end_pfn() const { return at<2>().as_uint64(); }
+ bool has_nr_scanned() const { return at<3>().valid(); }
+ uint64_t nr_scanned() const { return at<3>().as_uint64(); }
+ bool has_nr_taken() const { return at<4>().valid(); }
+ uint64_t nr_taken() const { return at<4>().as_uint64(); }
+};
+
+class MmCompactionIsolateMigratepagesFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionIsolateMigratepagesFtraceEvent_Decoder;
+ enum : int32_t {
+ kStartPfnFieldNumber = 1,
+ kEndPfnFieldNumber = 2,
+ kNrScannedFieldNumber = 3,
+ kNrTakenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionIsolateMigratepagesFtraceEvent"; }
+
+
+ using FieldMetadata_StartPfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateMigratepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_StartPfn kStartPfn{};
+ void set_start_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartPfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EndPfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateMigratepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_EndPfn kEndPfn{};
+ void set_end_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EndPfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrScanned =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateMigratepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrScanned kNrScanned{};
+ void set_nr_scanned(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrScanned::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrTaken =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateMigratepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrTaken kNrTaken{};
+ void set_nr_taken(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrTaken::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionIsolateFreepagesFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionIsolateFreepagesFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionIsolateFreepagesFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionIsolateFreepagesFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_start_pfn() const { return at<1>().valid(); }
+ uint64_t start_pfn() const { return at<1>().as_uint64(); }
+ bool has_end_pfn() const { return at<2>().valid(); }
+ uint64_t end_pfn() const { return at<2>().as_uint64(); }
+ bool has_nr_scanned() const { return at<3>().valid(); }
+ uint64_t nr_scanned() const { return at<3>().as_uint64(); }
+ bool has_nr_taken() const { return at<4>().valid(); }
+ uint64_t nr_taken() const { return at<4>().as_uint64(); }
+};
+
+class MmCompactionIsolateFreepagesFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionIsolateFreepagesFtraceEvent_Decoder;
+ enum : int32_t {
+ kStartPfnFieldNumber = 1,
+ kEndPfnFieldNumber = 2,
+ kNrScannedFieldNumber = 3,
+ kNrTakenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionIsolateFreepagesFtraceEvent"; }
+
+
+ using FieldMetadata_StartPfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateFreepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_StartPfn kStartPfn{};
+ void set_start_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartPfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EndPfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateFreepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_EndPfn kEndPfn{};
+ void set_end_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EndPfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrScanned =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateFreepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrScanned kNrScanned{};
+ void set_nr_scanned(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrScanned::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrTaken =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionIsolateFreepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrTaken kNrTaken{};
+ void set_nr_taken(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrTaken::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionFinishedFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionFinishedFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionFinishedFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionFinishedFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_idx() const { return at<2>().valid(); }
+ uint32_t idx() const { return at<2>().as_uint32(); }
+ bool has_order() const { return at<3>().valid(); }
+ int32_t order() const { return at<3>().as_int32(); }
+ bool has_ret() const { return at<4>().valid(); }
+ int32_t ret() const { return at<4>().as_int32(); }
+};
+
+class MmCompactionFinishedFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionFinishedFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kIdxFieldNumber = 2,
+ kOrderFieldNumber = 3,
+ kRetFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionFinishedFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionFinishedFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionFinishedFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionFinishedFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionFinishedFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_zone_start() const { return at<1>().valid(); }
+ uint64_t zone_start() const { return at<1>().as_uint64(); }
+ bool has_migrate_pfn() const { return at<2>().valid(); }
+ uint64_t migrate_pfn() const { return at<2>().as_uint64(); }
+ bool has_free_pfn() const { return at<3>().valid(); }
+ uint64_t free_pfn() const { return at<3>().as_uint64(); }
+ bool has_zone_end() const { return at<4>().valid(); }
+ uint64_t zone_end() const { return at<4>().as_uint64(); }
+ bool has_sync() const { return at<5>().valid(); }
+ uint32_t sync() const { return at<5>().as_uint32(); }
+ bool has_status() const { return at<6>().valid(); }
+ int32_t status() const { return at<6>().as_int32(); }
+};
+
+class MmCompactionEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kZoneStartFieldNumber = 1,
+ kMigratePfnFieldNumber = 2,
+ kFreePfnFieldNumber = 3,
+ kZoneEndFieldNumber = 4,
+ kSyncFieldNumber = 5,
+ kStatusFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionEndFtraceEvent"; }
+
+
+ using FieldMetadata_ZoneStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionEndFtraceEvent>;
+
+ static constexpr FieldMetadata_ZoneStart kZoneStart{};
+ void set_zone_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ZoneStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MigratePfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionEndFtraceEvent>;
+
+ static constexpr FieldMetadata_MigratePfn kMigratePfn{};
+ void set_migrate_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MigratePfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreePfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionEndFtraceEvent>;
+
+ static constexpr FieldMetadata_FreePfn kFreePfn{};
+ void set_free_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreePfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ZoneEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionEndFtraceEvent>;
+
+ static constexpr FieldMetadata_ZoneEnd kZoneEnd{};
+ void set_zone_end(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ZoneEnd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sync =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Sync kSync{};
+ void set_sync(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sync::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionDeferResetFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionDeferResetFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionDeferResetFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionDeferResetFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_idx() const { return at<2>().valid(); }
+ uint32_t idx() const { return at<2>().as_uint32(); }
+ bool has_order() const { return at<3>().valid(); }
+ int32_t order() const { return at<3>().as_int32(); }
+ bool has_considered() const { return at<4>().valid(); }
+ uint32_t considered() const { return at<4>().as_uint32(); }
+ bool has_defer_shift() const { return at<5>().valid(); }
+ uint32_t defer_shift() const { return at<5>().as_uint32(); }
+ bool has_order_failed() const { return at<6>().valid(); }
+ int32_t order_failed() const { return at<6>().as_int32(); }
+};
+
+class MmCompactionDeferResetFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionDeferResetFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kIdxFieldNumber = 2,
+ kOrderFieldNumber = 3,
+ kConsideredFieldNumber = 4,
+ kDeferShiftFieldNumber = 5,
+ kOrderFailedFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionDeferResetFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferResetFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferResetFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferResetFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Considered =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferResetFtraceEvent>;
+
+ static constexpr FieldMetadata_Considered kConsidered{};
+ void set_considered(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Considered::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeferShift =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferResetFtraceEvent>;
+
+ static constexpr FieldMetadata_DeferShift kDeferShift{};
+ void set_defer_shift(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeferShift::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrderFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferResetFtraceEvent>;
+
+ static constexpr FieldMetadata_OrderFailed kOrderFailed{};
+ void set_order_failed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrderFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionDeferredFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionDeferredFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionDeferredFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionDeferredFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_idx() const { return at<2>().valid(); }
+ uint32_t idx() const { return at<2>().as_uint32(); }
+ bool has_order() const { return at<3>().valid(); }
+ int32_t order() const { return at<3>().as_int32(); }
+ bool has_considered() const { return at<4>().valid(); }
+ uint32_t considered() const { return at<4>().as_uint32(); }
+ bool has_defer_shift() const { return at<5>().valid(); }
+ uint32_t defer_shift() const { return at<5>().as_uint32(); }
+ bool has_order_failed() const { return at<6>().valid(); }
+ int32_t order_failed() const { return at<6>().as_int32(); }
+};
+
+class MmCompactionDeferredFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionDeferredFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kIdxFieldNumber = 2,
+ kOrderFieldNumber = 3,
+ kConsideredFieldNumber = 4,
+ kDeferShiftFieldNumber = 5,
+ kOrderFailedFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionDeferredFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferredFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferredFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferredFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Considered =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferredFtraceEvent>;
+
+ static constexpr FieldMetadata_Considered kConsidered{};
+ void set_considered(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Considered::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeferShift =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferredFtraceEvent>;
+
+ static constexpr FieldMetadata_DeferShift kDeferShift{};
+ void set_defer_shift(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeferShift::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrderFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferredFtraceEvent>;
+
+ static constexpr FieldMetadata_OrderFailed kOrderFailed{};
+ void set_order_failed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrderFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionDeferCompactionFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionDeferCompactionFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionDeferCompactionFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionDeferCompactionFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_idx() const { return at<2>().valid(); }
+ uint32_t idx() const { return at<2>().as_uint32(); }
+ bool has_order() const { return at<3>().valid(); }
+ int32_t order() const { return at<3>().as_int32(); }
+ bool has_considered() const { return at<4>().valid(); }
+ uint32_t considered() const { return at<4>().as_uint32(); }
+ bool has_defer_shift() const { return at<5>().valid(); }
+ uint32_t defer_shift() const { return at<5>().as_uint32(); }
+ bool has_order_failed() const { return at<6>().valid(); }
+ int32_t order_failed() const { return at<6>().as_int32(); }
+};
+
+class MmCompactionDeferCompactionFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionDeferCompactionFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kIdxFieldNumber = 2,
+ kOrderFieldNumber = 3,
+ kConsideredFieldNumber = 4,
+ kDeferShiftFieldNumber = 5,
+ kOrderFailedFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionDeferCompactionFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferCompactionFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferCompactionFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferCompactionFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Considered =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferCompactionFtraceEvent>;
+
+ static constexpr FieldMetadata_Considered kConsidered{};
+ void set_considered(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Considered::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeferShift =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionDeferCompactionFtraceEvent>;
+
+ static constexpr FieldMetadata_DeferShift kDeferShift{};
+ void set_defer_shift(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeferShift::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrderFailed =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmCompactionDeferCompactionFtraceEvent>;
+
+ static constexpr FieldMetadata_OrderFailed kOrderFailed{};
+ void set_order_failed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrderFailed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmCompactionBeginFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmCompactionBeginFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmCompactionBeginFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmCompactionBeginFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_zone_start() const { return at<1>().valid(); }
+ uint64_t zone_start() const { return at<1>().as_uint64(); }
+ bool has_migrate_pfn() const { return at<2>().valid(); }
+ uint64_t migrate_pfn() const { return at<2>().as_uint64(); }
+ bool has_free_pfn() const { return at<3>().valid(); }
+ uint64_t free_pfn() const { return at<3>().as_uint64(); }
+ bool has_zone_end() const { return at<4>().valid(); }
+ uint64_t zone_end() const { return at<4>().as_uint64(); }
+ bool has_sync() const { return at<5>().valid(); }
+ uint32_t sync() const { return at<5>().as_uint32(); }
+};
+
+class MmCompactionBeginFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmCompactionBeginFtraceEvent_Decoder;
+ enum : int32_t {
+ kZoneStartFieldNumber = 1,
+ kMigratePfnFieldNumber = 2,
+ kFreePfnFieldNumber = 3,
+ kZoneEndFieldNumber = 4,
+ kSyncFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmCompactionBeginFtraceEvent"; }
+
+
+ using FieldMetadata_ZoneStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_ZoneStart kZoneStart{};
+ void set_zone_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ZoneStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MigratePfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_MigratePfn kMigratePfn{};
+ void set_migrate_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MigratePfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreePfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_FreePfn kFreePfn{};
+ void set_free_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreePfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ZoneEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmCompactionBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_ZoneEnd kZoneEnd{};
+ void set_zone_end(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ZoneEnd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sync =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmCompactionBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Sync kSync{};
+ void set_sync(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sync::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/cpuhp.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CPUHP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CPUHP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class CpuhpPauseFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuhpPauseFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuhpPauseFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuhpPauseFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_active_cpus() const { return at<1>().valid(); }
+ uint32_t active_cpus() const { return at<1>().as_uint32(); }
+ bool has_cpus() const { return at<2>().valid(); }
+ uint32_t cpus() const { return at<2>().as_uint32(); }
+ bool has_pause() const { return at<3>().valid(); }
+ uint32_t pause() const { return at<3>().as_uint32(); }
+ bool has_time() const { return at<4>().valid(); }
+ uint32_t time() const { return at<4>().as_uint32(); }
+};
+
+class CpuhpPauseFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuhpPauseFtraceEvent_Decoder;
+ enum : int32_t {
+ kActiveCpusFieldNumber = 1,
+ kCpusFieldNumber = 2,
+ kPauseFieldNumber = 3,
+ kTimeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuhpPauseFtraceEvent"; }
+
+
+ using FieldMetadata_ActiveCpus =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpPauseFtraceEvent>;
+
+ static constexpr FieldMetadata_ActiveCpus kActiveCpus{};
+ void set_active_cpus(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActiveCpus::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cpus =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpPauseFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpus kCpus{};
+ void set_cpus(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpus::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pause =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpPauseFtraceEvent>;
+
+ static constexpr FieldMetadata_Pause kPause{};
+ void set_pause(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pause::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Time =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpPauseFtraceEvent>;
+
+ static constexpr FieldMetadata_Time kTime{};
+ void set_time(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Time::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CpuhpLatencyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuhpLatencyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuhpLatencyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuhpLatencyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint32_t cpu() const { return at<1>().as_uint32(); }
+ bool has_ret() const { return at<2>().valid(); }
+ int32_t ret() const { return at<2>().as_int32(); }
+ bool has_state() const { return at<3>().valid(); }
+ uint32_t state() const { return at<3>().as_uint32(); }
+ bool has_time() const { return at<4>().valid(); }
+ uint64_t time() const { return at<4>().as_uint64(); }
+};
+
+class CpuhpLatencyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuhpLatencyFtraceEvent_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kRetFieldNumber = 2,
+ kStateFieldNumber = 3,
+ kTimeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuhpLatencyFtraceEvent"; }
+
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Time =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CpuhpLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_Time kTime{};
+ void set_time(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Time::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CpuhpEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuhpEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuhpEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuhpEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint32_t cpu() const { return at<1>().as_uint32(); }
+ bool has_fun() const { return at<2>().valid(); }
+ uint64_t fun() const { return at<2>().as_uint64(); }
+ bool has_idx() const { return at<3>().valid(); }
+ int32_t idx() const { return at<3>().as_int32(); }
+ bool has_target() const { return at<4>().valid(); }
+ int32_t target() const { return at<4>().as_int32(); }
+};
+
+class CpuhpEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuhpEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kFunFieldNumber = 2,
+ kIdxFieldNumber = 3,
+ kTargetFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuhpEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fun =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CpuhpEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Fun kFun{};
+ void set_fun(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fun::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Target =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Target kTarget{};
+ void set_target(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Target::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CpuhpMultiEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuhpMultiEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuhpMultiEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuhpMultiEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint32_t cpu() const { return at<1>().as_uint32(); }
+ bool has_fun() const { return at<2>().valid(); }
+ uint64_t fun() const { return at<2>().as_uint64(); }
+ bool has_idx() const { return at<3>().valid(); }
+ int32_t idx() const { return at<3>().as_int32(); }
+ bool has_target() const { return at<4>().valid(); }
+ int32_t target() const { return at<4>().as_int32(); }
+};
+
+class CpuhpMultiEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuhpMultiEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kFunFieldNumber = 2,
+ kIdxFieldNumber = 3,
+ kTargetFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuhpMultiEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpMultiEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fun =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CpuhpMultiEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Fun kFun{};
+ void set_fun(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fun::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpMultiEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Target =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpMultiEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Target kTarget{};
+ void set_target(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Target::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CpuhpExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuhpExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuhpExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuhpExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint32_t cpu() const { return at<1>().as_uint32(); }
+ bool has_idx() const { return at<2>().valid(); }
+ int32_t idx() const { return at<2>().as_int32(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+ bool has_state() const { return at<4>().valid(); }
+ int32_t state() const { return at<4>().as_int32(); }
+};
+
+class CpuhpExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuhpExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kIdxFieldNumber = 2,
+ kRetFieldNumber = 3,
+ kStateFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuhpExitFtraceEvent"; }
+
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuhpExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Idx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Idx kIdx{};
+ void set_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Idx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ CpuhpExitFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/cros_ec.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CROS_EC_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_CROS_EC_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class CrosEcSensorhubDataFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CrosEcSensorhubDataFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CrosEcSensorhubDataFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CrosEcSensorhubDataFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_current_time() const { return at<1>().valid(); }
+ int64_t current_time() const { return at<1>().as_int64(); }
+ bool has_current_timestamp() const { return at<2>().valid(); }
+ int64_t current_timestamp() const { return at<2>().as_int64(); }
+ bool has_delta() const { return at<3>().valid(); }
+ int64_t delta() const { return at<3>().as_int64(); }
+ bool has_ec_fifo_timestamp() const { return at<4>().valid(); }
+ uint32_t ec_fifo_timestamp() const { return at<4>().as_uint32(); }
+ bool has_ec_sensor_num() const { return at<5>().valid(); }
+ uint32_t ec_sensor_num() const { return at<5>().as_uint32(); }
+ bool has_fifo_timestamp() const { return at<6>().valid(); }
+ int64_t fifo_timestamp() const { return at<6>().as_int64(); }
+};
+
+class CrosEcSensorhubDataFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CrosEcSensorhubDataFtraceEvent_Decoder;
+ enum : int32_t {
+ kCurrentTimeFieldNumber = 1,
+ kCurrentTimestampFieldNumber = 2,
+ kDeltaFieldNumber = 3,
+ kEcFifoTimestampFieldNumber = 4,
+ kEcSensorNumFieldNumber = 5,
+ kFifoTimestampFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CrosEcSensorhubDataFtraceEvent"; }
+
+
+ using FieldMetadata_CurrentTime =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CrosEcSensorhubDataFtraceEvent>;
+
+ static constexpr FieldMetadata_CurrentTime kCurrentTime{};
+ void set_current_time(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrentTime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrentTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CrosEcSensorhubDataFtraceEvent>;
+
+ static constexpr FieldMetadata_CurrentTimestamp kCurrentTimestamp{};
+ void set_current_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrentTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Delta =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CrosEcSensorhubDataFtraceEvent>;
+
+ static constexpr FieldMetadata_Delta kDelta{};
+ void set_delta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Delta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EcFifoTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CrosEcSensorhubDataFtraceEvent>;
+
+ static constexpr FieldMetadata_EcFifoTimestamp kEcFifoTimestamp{};
+ void set_ec_fifo_timestamp(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EcFifoTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EcSensorNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CrosEcSensorhubDataFtraceEvent>;
+
+ static constexpr FieldMetadata_EcSensorNum kEcSensorNum{};
+ void set_ec_sensor_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EcSensorNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FifoTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CrosEcSensorhubDataFtraceEvent>;
+
+ static constexpr FieldMetadata_FifoTimestamp kFifoTimestamp{};
+ void set_fifo_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FifoTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/dma_fence.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DMA_FENCE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DMA_FENCE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class DmaFenceWaitEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DmaFenceWaitEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DmaFenceWaitEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DmaFenceWaitEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class DmaFenceWaitEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DmaFenceWaitEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DmaFenceWaitEndFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceWaitEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceWaitEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceWaitEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceWaitEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DmaFenceWaitStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DmaFenceWaitStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DmaFenceWaitStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DmaFenceWaitStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class DmaFenceWaitStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DmaFenceWaitStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DmaFenceWaitStartFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceWaitStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceWaitStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceWaitStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceWaitStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DmaFenceSignaledFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DmaFenceSignaledFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DmaFenceSignaledFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DmaFenceSignaledFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class DmaFenceSignaledFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DmaFenceSignaledFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DmaFenceSignaledFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DmaFenceEmitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DmaFenceEmitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DmaFenceEmitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DmaFenceEmitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class DmaFenceEmitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DmaFenceEmitFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DmaFenceEmitFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceEmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceEmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceEmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceEmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DmaFenceInitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DmaFenceInitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DmaFenceInitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DmaFenceInitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class DmaFenceInitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DmaFenceInitFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DmaFenceInitFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DmaFenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DmaFenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DMABUF_HEAP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DMABUF_HEAP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class DmaHeapStatFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DmaHeapStatFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DmaHeapStatFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DmaHeapStatFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_inode() const { return at<1>().valid(); }
+ uint64_t inode() const { return at<1>().as_uint64(); }
+ bool has_len() const { return at<2>().valid(); }
+ int64_t len() const { return at<2>().as_int64(); }
+ bool has_total_allocated() const { return at<3>().valid(); }
+ uint64_t total_allocated() const { return at<3>().as_uint64(); }
+};
+
+class DmaHeapStatFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DmaHeapStatFtraceEvent_Decoder;
+ enum : int32_t {
+ kInodeFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kTotalAllocatedFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DmaHeapStatFtraceEvent"; }
+
+
+ using FieldMetadata_Inode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DmaHeapStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Inode kInode{};
+ void set_inode(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Inode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ DmaHeapStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalAllocated =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DmaHeapStatFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalAllocated kTotalAllocated{};
+ void set_total_allocated(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalAllocated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/dpu.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DPU_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DPU_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class DpuDsiTxFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DpuDsiTxFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DpuDsiTxFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DpuDsiTxFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_type() const { return at<1>().valid(); }
+ uint32_t type() const { return at<1>().as_uint32(); }
+ bool has_tx_buf() const { return at<2>().valid(); }
+ uint32_t tx_buf() const { return at<2>().as_uint32(); }
+ bool has_last() const { return at<3>().valid(); }
+ uint32_t last() const { return at<3>().as_uint32(); }
+ bool has_delay_ms() const { return at<4>().valid(); }
+ uint32_t delay_ms() const { return at<4>().as_uint32(); }
+};
+
+class DpuDsiTxFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DpuDsiTxFtraceEvent_Decoder;
+ enum : int32_t {
+ kTypeFieldNumber = 1,
+ kTxBufFieldNumber = 2,
+ kLastFieldNumber = 3,
+ kDelayMsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DpuDsiTxFtraceEvent"; }
+
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiTxFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TxBuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiTxFtraceEvent>;
+
+ static constexpr FieldMetadata_TxBuf kTxBuf{};
+ void set_tx_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TxBuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Last =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiTxFtraceEvent>;
+
+ static constexpr FieldMetadata_Last kLast{};
+ void set_last(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Last::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DelayMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiTxFtraceEvent>;
+
+ static constexpr FieldMetadata_DelayMs kDelayMs{};
+ void set_delay_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DelayMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DpuDsiRxFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DpuDsiRxFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DpuDsiRxFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DpuDsiRxFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cmd() const { return at<1>().valid(); }
+ uint32_t cmd() const { return at<1>().as_uint32(); }
+ bool has_rx_buf() const { return at<2>().valid(); }
+ uint32_t rx_buf() const { return at<2>().as_uint32(); }
+};
+
+class DpuDsiRxFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DpuDsiRxFtraceEvent_Decoder;
+ enum : int32_t {
+ kCmdFieldNumber = 1,
+ kRxBufFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DpuDsiRxFtraceEvent"; }
+
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiRxFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RxBuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiRxFtraceEvent>;
+
+ static constexpr FieldMetadata_RxBuf kRxBuf{};
+ void set_rx_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RxBuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DpuDsiCmdFifoStatusFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DpuDsiCmdFifoStatusFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DpuDsiCmdFifoStatusFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DpuDsiCmdFifoStatusFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_header() const { return at<1>().valid(); }
+ uint32_t header() const { return at<1>().as_uint32(); }
+ bool has_payload() const { return at<2>().valid(); }
+ uint32_t payload() const { return at<2>().as_uint32(); }
+};
+
+class DpuDsiCmdFifoStatusFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DpuDsiCmdFifoStatusFtraceEvent_Decoder;
+ enum : int32_t {
+ kHeaderFieldNumber = 1,
+ kPayloadFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DpuDsiCmdFifoStatusFtraceEvent"; }
+
+
+ using FieldMetadata_Header =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiCmdFifoStatusFtraceEvent>;
+
+ static constexpr FieldMetadata_Header kHeader{};
+ void set_header(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Header::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Payload =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuDsiCmdFifoStatusFtraceEvent>;
+
+ static constexpr FieldMetadata_Payload kPayload{};
+ void set_payload(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Payload::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DpuTracingMarkWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DpuTracingMarkWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DpuTracingMarkWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DpuTracingMarkWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_trace_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars trace_name() const { return at<2>().as_string(); }
+ bool has_trace_begin() const { return at<3>().valid(); }
+ uint32_t trace_begin() const { return at<3>().as_uint32(); }
+ bool has_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars name() const { return at<4>().as_string(); }
+ bool has_type() const { return at<5>().valid(); }
+ uint32_t type() const { return at<5>().as_uint32(); }
+ bool has_value() const { return at<6>().valid(); }
+ int32_t value() const { return at<6>().as_int32(); }
+};
+
+class DpuTracingMarkWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DpuTracingMarkWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kTraceNameFieldNumber = 2,
+ kTraceBeginFieldNumber = 3,
+ kNameFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ kValueFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DpuTracingMarkWriteFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DpuTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DpuTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceName kTraceName{};
+ void set_trace_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, data, size);
+ }
+ void set_trace_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, chars.data, chars.size);
+ }
+ void set_trace_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceBegin kTraceBegin{};
+ void set_trace_begin(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceBegin::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DpuTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DpuTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DpuTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/drm.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DRM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_DRM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class DrmVblankEventDeliveredFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DrmVblankEventDeliveredFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DrmVblankEventDeliveredFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DrmVblankEventDeliveredFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_crtc() const { return at<1>().valid(); }
+ int32_t crtc() const { return at<1>().as_int32(); }
+ bool has_file() const { return at<2>().valid(); }
+ uint64_t file() const { return at<2>().as_uint64(); }
+ bool has_seq() const { return at<3>().valid(); }
+ uint32_t seq() const { return at<3>().as_uint32(); }
+};
+
+class DrmVblankEventDeliveredFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DrmVblankEventDeliveredFtraceEvent_Decoder;
+ enum : int32_t {
+ kCrtcFieldNumber = 1,
+ kFileFieldNumber = 2,
+ kSeqFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DrmVblankEventDeliveredFtraceEvent"; }
+
+
+ using FieldMetadata_Crtc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DrmVblankEventDeliveredFtraceEvent>;
+
+ static constexpr FieldMetadata_Crtc kCrtc{};
+ void set_crtc(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Crtc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_File =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmVblankEventDeliveredFtraceEvent>;
+
+ static constexpr FieldMetadata_File kFile{};
+ void set_file(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_File::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seq =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DrmVblankEventDeliveredFtraceEvent>;
+
+ static constexpr FieldMetadata_Seq kSeq{};
+ void set_seq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DrmVblankEventFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DrmVblankEventFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DrmVblankEventFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DrmVblankEventFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_crtc() const { return at<1>().valid(); }
+ int32_t crtc() const { return at<1>().as_int32(); }
+ bool has_high_prec() const { return at<2>().valid(); }
+ uint32_t high_prec() const { return at<2>().as_uint32(); }
+ bool has_seq() const { return at<3>().valid(); }
+ uint32_t seq() const { return at<3>().as_uint32(); }
+ bool has_time() const { return at<4>().valid(); }
+ int64_t time() const { return at<4>().as_int64(); }
+};
+
+class DrmVblankEventFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DrmVblankEventFtraceEvent_Decoder;
+ enum : int32_t {
+ kCrtcFieldNumber = 1,
+ kHighPrecFieldNumber = 2,
+ kSeqFieldNumber = 3,
+ kTimeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DrmVblankEventFtraceEvent"; }
+
+
+ using FieldMetadata_Crtc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DrmVblankEventFtraceEvent>;
+
+ static constexpr FieldMetadata_Crtc kCrtc{};
+ void set_crtc(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Crtc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HighPrec =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DrmVblankEventFtraceEvent>;
+
+ static constexpr FieldMetadata_HighPrec kHighPrec{};
+ void set_high_prec(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HighPrec::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seq =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DrmVblankEventFtraceEvent>;
+
+ static constexpr FieldMetadata_Seq kSeq{};
+ void set_seq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Time =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ DrmVblankEventFtraceEvent>;
+
+ static constexpr FieldMetadata_Time kTime{};
+ void set_time(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Time::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ext4.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_EXT4_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_EXT4_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class Ext4ZeroRangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ZeroRangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ZeroRangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ZeroRangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ int64_t len() const { return at<4>().as_int64(); }
+ bool has_mode() const { return at<5>().valid(); }
+ int32_t mode() const { return at<5>().as_int32(); }
+};
+
+class Ext4ZeroRangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ZeroRangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kModeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ZeroRangeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ZeroRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ZeroRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4ZeroRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4ZeroRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ZeroRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4WritepagesResultFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4WritepagesResultFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4WritepagesResultFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4WritepagesResultFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+ bool has_pages_written() const { return at<4>().valid(); }
+ int32_t pages_written() const { return at<4>().as_int32(); }
+ bool has_pages_skipped() const { return at<5>().valid(); }
+ int64_t pages_skipped() const { return at<5>().as_int64(); }
+ bool has_writeback_index() const { return at<6>().valid(); }
+ uint64_t writeback_index() const { return at<6>().as_uint64(); }
+ bool has_sync_mode() const { return at<7>().valid(); }
+ int32_t sync_mode() const { return at<7>().as_int32(); }
+};
+
+class Ext4WritepagesResultFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4WritepagesResultFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ kPagesWrittenFieldNumber = 4,
+ kPagesSkippedFieldNumber = 5,
+ kWritebackIndexFieldNumber = 6,
+ kSyncModeFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4WritepagesResultFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepagesResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepagesResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4WritepagesResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PagesWritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4WritepagesResultFtraceEvent>;
+
+ static constexpr FieldMetadata_PagesWritten kPagesWritten{};
+ void set_pages_written(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PagesWritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PagesSkipped =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4WritepagesResultFtraceEvent>;
+
+ static constexpr FieldMetadata_PagesSkipped kPagesSkipped{};
+ void set_pages_skipped(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PagesSkipped::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WritebackIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepagesResultFtraceEvent>;
+
+ static constexpr FieldMetadata_WritebackIndex kWritebackIndex{};
+ void set_writeback_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WritebackIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SyncMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4WritepagesResultFtraceEvent>;
+
+ static constexpr FieldMetadata_SyncMode kSyncMode{};
+ void set_sync_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SyncMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4WritepagesFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4WritepagesFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4WritepagesFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4WritepagesFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_nr_to_write() const { return at<3>().valid(); }
+ int64_t nr_to_write() const { return at<3>().as_int64(); }
+ bool has_pages_skipped() const { return at<4>().valid(); }
+ int64_t pages_skipped() const { return at<4>().as_int64(); }
+ bool has_range_start() const { return at<5>().valid(); }
+ int64_t range_start() const { return at<5>().as_int64(); }
+ bool has_range_end() const { return at<6>().valid(); }
+ int64_t range_end() const { return at<6>().as_int64(); }
+ bool has_writeback_index() const { return at<7>().valid(); }
+ uint64_t writeback_index() const { return at<7>().as_uint64(); }
+ bool has_sync_mode() const { return at<8>().valid(); }
+ int32_t sync_mode() const { return at<8>().as_int32(); }
+ bool has_for_kupdate() const { return at<9>().valid(); }
+ uint32_t for_kupdate() const { return at<9>().as_uint32(); }
+ bool has_range_cyclic() const { return at<10>().valid(); }
+ uint32_t range_cyclic() const { return at<10>().as_uint32(); }
+};
+
+class Ext4WritepagesFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4WritepagesFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNrToWriteFieldNumber = 3,
+ kPagesSkippedFieldNumber = 4,
+ kRangeStartFieldNumber = 5,
+ kRangeEndFieldNumber = 6,
+ kWritebackIndexFieldNumber = 7,
+ kSyncModeFieldNumber = 8,
+ kForKupdateFieldNumber = 9,
+ kRangeCyclicFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4WritepagesFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrToWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrToWrite kNrToWrite{};
+ void set_nr_to_write(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrToWrite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PagesSkipped =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_PagesSkipped kPagesSkipped{};
+ void set_pages_skipped(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PagesSkipped::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RangeStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_RangeStart kRangeStart{};
+ void set_range_start(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RangeStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RangeEnd =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_RangeEnd kRangeEnd{};
+ void set_range_end(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RangeEnd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WritebackIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_WritebackIndex kWritebackIndex{};
+ void set_writeback_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WritebackIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SyncMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_SyncMode kSyncMode{};
+ void set_sync_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SyncMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ForKupdate =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_ForKupdate kForKupdate{};
+ void set_for_kupdate(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ForKupdate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RangeCyclic =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4WritepagesFtraceEvent>;
+
+ static constexpr FieldMetadata_RangeCyclic kRangeCyclic{};
+ void set_range_cyclic(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RangeCyclic::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4WritepageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4WritepageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4WritepageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4WritepageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+};
+
+class Ext4WritepageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4WritepageFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4WritepageFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WritepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4WriteEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4WriteEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4WriteEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4WriteEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_copied() const { return at<5>().valid(); }
+ uint32_t copied() const { return at<5>().as_uint32(); }
+};
+
+class Ext4WriteEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4WriteEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kCopiedFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4WriteEndFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4WriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4WriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Copied =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4WriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Copied kCopied{};
+ void set_copied(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Copied::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4WriteBeginFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4WriteBeginFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4WriteBeginFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4WriteBeginFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+};
+
+class Ext4WriteBeginFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4WriteBeginFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4WriteBeginFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4WriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4WriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4WriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4WriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4UnlinkExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4UnlinkExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4UnlinkExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4UnlinkExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class Ext4UnlinkExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4UnlinkExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4UnlinkExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4UnlinkExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4UnlinkExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4UnlinkExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4UnlinkEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4UnlinkEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4UnlinkEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4UnlinkEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_parent() const { return at<3>().valid(); }
+ uint64_t parent() const { return at<3>().as_uint64(); }
+ bool has_size() const { return at<4>().valid(); }
+ int64_t size() const { return at<4>().as_int64(); }
+};
+
+class Ext4UnlinkEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4UnlinkEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kParentFieldNumber = 3,
+ kSizeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4UnlinkEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4UnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4UnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Parent =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4UnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Parent kParent{};
+ void set_parent(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Parent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4UnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4TruncateExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4TruncateExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4TruncateExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4TruncateExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_blocks() const { return at<3>().valid(); }
+ uint64_t blocks() const { return at<3>().as_uint64(); }
+};
+
+class Ext4TruncateExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4TruncateExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kBlocksFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4TruncateExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4TruncateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4TruncateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4TruncateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4TruncateEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4TruncateEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4TruncateEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4TruncateEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_blocks() const { return at<3>().valid(); }
+ uint64_t blocks() const { return at<3>().as_uint64(); }
+};
+
+class Ext4TruncateEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4TruncateEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kBlocksFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4TruncateEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4TruncateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4TruncateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4TruncateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4TrimExtentFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4TrimExtentFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4TrimExtentFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4TrimExtentFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev_major() const { return at<1>().valid(); }
+ int32_t dev_major() const { return at<1>().as_int32(); }
+ bool has_dev_minor() const { return at<2>().valid(); }
+ int32_t dev_minor() const { return at<2>().as_int32(); }
+ bool has_group() const { return at<3>().valid(); }
+ uint32_t group() const { return at<3>().as_uint32(); }
+ bool has_start() const { return at<4>().valid(); }
+ int32_t start() const { return at<4>().as_int32(); }
+ bool has_len() const { return at<5>().valid(); }
+ int32_t len() const { return at<5>().as_int32(); }
+};
+
+class Ext4TrimExtentFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4TrimExtentFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevMajorFieldNumber = 1,
+ kDevMinorFieldNumber = 2,
+ kGroupFieldNumber = 3,
+ kStartFieldNumber = 4,
+ kLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4TrimExtentFtraceEvent"; }
+
+
+ using FieldMetadata_DevMajor =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_DevMajor kDevMajor{};
+ void set_dev_major(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DevMajor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DevMinor =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_DevMinor kDevMinor{};
+ void set_dev_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DevMinor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4TrimExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4TrimAllFreeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4TrimAllFreeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4TrimAllFreeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4TrimAllFreeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev_major() const { return at<1>().valid(); }
+ int32_t dev_major() const { return at<1>().as_int32(); }
+ bool has_dev_minor() const { return at<2>().valid(); }
+ int32_t dev_minor() const { return at<2>().as_int32(); }
+ bool has_group() const { return at<3>().valid(); }
+ uint32_t group() const { return at<3>().as_uint32(); }
+ bool has_start() const { return at<4>().valid(); }
+ int32_t start() const { return at<4>().as_int32(); }
+ bool has_len() const { return at<5>().valid(); }
+ int32_t len() const { return at<5>().as_int32(); }
+};
+
+class Ext4TrimAllFreeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4TrimAllFreeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevMajorFieldNumber = 1,
+ kDevMinorFieldNumber = 2,
+ kGroupFieldNumber = 3,
+ kStartFieldNumber = 4,
+ kLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4TrimAllFreeFtraceEvent"; }
+
+
+ using FieldMetadata_DevMajor =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimAllFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_DevMajor kDevMajor{};
+ void set_dev_major(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DevMajor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DevMinor =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimAllFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_DevMinor kDevMinor{};
+ void set_dev_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DevMinor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4TrimAllFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimAllFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4TrimAllFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4SyncFsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4SyncFsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4SyncFsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4SyncFsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_wait() const { return at<2>().valid(); }
+ int32_t wait() const { return at<2>().as_int32(); }
+};
+
+class Ext4SyncFsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4SyncFsFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kWaitFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4SyncFsFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4SyncFsFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Wait =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4SyncFsFtraceEvent>;
+
+ static constexpr FieldMetadata_Wait kWait{};
+ void set_wait(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Wait::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4RequestInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4RequestInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4RequestInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4RequestInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_dir() const { return at<2>().valid(); }
+ uint64_t dir() const { return at<2>().as_uint64(); }
+ bool has_mode() const { return at<3>().valid(); }
+ uint32_t mode() const { return at<3>().as_uint32(); }
+};
+
+class Ext4RequestInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4RequestInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kDirFieldNumber = 2,
+ kModeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4RequestInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RequestInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dir =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RequestInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dir kDir{};
+ void set_dir(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dir::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RequestInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4RequestBlocksFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4RequestBlocksFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4RequestBlocksFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4RequestBlocksFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_len() const { return at<3>().valid(); }
+ uint32_t len() const { return at<3>().as_uint32(); }
+ bool has_logical() const { return at<4>().valid(); }
+ uint32_t logical() const { return at<4>().as_uint32(); }
+ bool has_lleft() const { return at<5>().valid(); }
+ uint32_t lleft() const { return at<5>().as_uint32(); }
+ bool has_lright() const { return at<6>().valid(); }
+ uint32_t lright() const { return at<6>().as_uint32(); }
+ bool has_goal() const { return at<7>().valid(); }
+ uint64_t goal() const { return at<7>().as_uint64(); }
+ bool has_pleft() const { return at<8>().valid(); }
+ uint64_t pleft() const { return at<8>().as_uint64(); }
+ bool has_pright() const { return at<9>().valid(); }
+ uint64_t pright() const { return at<9>().as_uint64(); }
+ bool has_flags() const { return at<10>().valid(); }
+ uint32_t flags() const { return at<10>().as_uint32(); }
+};
+
+class Ext4RequestBlocksFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4RequestBlocksFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLenFieldNumber = 3,
+ kLogicalFieldNumber = 4,
+ kLleftFieldNumber = 5,
+ kLrightFieldNumber = 6,
+ kGoalFieldNumber = 7,
+ kPleftFieldNumber = 8,
+ kPrightFieldNumber = 9,
+ kFlagsFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4RequestBlocksFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Logical =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Logical kLogical{};
+ void set_logical(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Logical::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lleft =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Lleft kLleft{};
+ void set_lleft(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lleft::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lright =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Lright kLright{};
+ void set_lright(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lright::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Goal =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Goal kGoal{};
+ void set_goal(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Goal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pleft =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Pleft kPleft{};
+ void set_pleft(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pleft::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pright =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Pright kPright{};
+ void set_pright(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pright::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RequestBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4RemoveBlocksFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4RemoveBlocksFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4RemoveBlocksFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4RemoveBlocksFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_from() const { return at<3>().valid(); }
+ uint32_t from() const { return at<3>().as_uint32(); }
+ bool has_to() const { return at<4>().valid(); }
+ uint32_t to() const { return at<4>().as_uint32(); }
+ bool has_partial() const { return at<5>().valid(); }
+ int64_t partial() const { return at<5>().as_int64(); }
+ bool has_ee_pblk() const { return at<6>().valid(); }
+ uint64_t ee_pblk() const { return at<6>().as_uint64(); }
+ bool has_ee_lblk() const { return at<7>().valid(); }
+ uint32_t ee_lblk() const { return at<7>().as_uint32(); }
+ bool has_ee_len() const { return at<8>().valid(); }
+ uint32_t ee_len() const { return at<8>().as_uint32(); }
+ bool has_pc_lblk() const { return at<9>().valid(); }
+ uint32_t pc_lblk() const { return at<9>().as_uint32(); }
+ bool has_pc_pclu() const { return at<10>().valid(); }
+ uint64_t pc_pclu() const { return at<10>().as_uint64(); }
+ bool has_pc_state() const { return at<11>().valid(); }
+ int32_t pc_state() const { return at<11>().as_int32(); }
+};
+
+class Ext4RemoveBlocksFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4RemoveBlocksFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kFromFieldNumber = 3,
+ kToFieldNumber = 4,
+ kPartialFieldNumber = 5,
+ kEePblkFieldNumber = 6,
+ kEeLblkFieldNumber = 7,
+ kEeLenFieldNumber = 8,
+ kPcLblkFieldNumber = 9,
+ kPcPcluFieldNumber = 10,
+ kPcStateFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4RemoveBlocksFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_From =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_From kFrom{};
+ void set_from(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_From::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_To =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_To kTo{};
+ void set_to(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_To::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Partial =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Partial kPartial{};
+ void set_partial(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Partial::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EePblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_EePblk kEePblk{};
+ void set_ee_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EePblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EeLblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_EeLblk kEeLblk{};
+ void set_ee_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EeLblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EeLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_EeLen kEeLen{};
+ void set_ee_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EeLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcLblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_PcLblk kPcLblk{};
+ void set_pc_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcLblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcPclu =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_PcPclu kPcPclu{};
+ void set_pc_pclu(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcPclu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcState =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4RemoveBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_PcState kPcState{};
+ void set_pc_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ReleasepageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ReleasepageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ReleasepageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ReleasepageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+};
+
+class Ext4ReleasepageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ReleasepageFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ReleasepageFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ReleasepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ReleasepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ReleasepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ReadpageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ReadpageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ReadpageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ReadpageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+};
+
+class Ext4ReadpageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ReadpageFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ReadpageFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ReadBlockBitmapLoadFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ReadBlockBitmapLoadFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ReadBlockBitmapLoadFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ReadBlockBitmapLoadFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_group() const { return at<2>().valid(); }
+ uint32_t group() const { return at<2>().as_uint32(); }
+ bool has_prefetch() const { return at<3>().valid(); }
+ uint32_t prefetch() const { return at<3>().as_uint32(); }
+};
+
+class Ext4ReadBlockBitmapLoadFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ReadBlockBitmapLoadFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kGroupFieldNumber = 2,
+ kPrefetchFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ReadBlockBitmapLoadFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ReadBlockBitmapLoadFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ReadBlockBitmapLoadFtraceEvent>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prefetch =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ReadBlockBitmapLoadFtraceEvent>;
+
+ static constexpr FieldMetadata_Prefetch kPrefetch{};
+ void set_prefetch(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prefetch::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4PunchHoleFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4PunchHoleFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4PunchHoleFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4PunchHoleFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ int64_t len() const { return at<4>().as_int64(); }
+ bool has_mode() const { return at<5>().valid(); }
+ int32_t mode() const { return at<5>().as_int32(); }
+};
+
+class Ext4PunchHoleFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4PunchHoleFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kModeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4PunchHoleFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4PunchHoleFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4PunchHoleFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4PunchHoleFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4PunchHoleFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4PunchHoleFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4OtherInodeUpdateTimeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4OtherInodeUpdateTimeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4OtherInodeUpdateTimeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4OtherInodeUpdateTimeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_orig_ino() const { return at<3>().valid(); }
+ uint64_t orig_ino() const { return at<3>().as_uint64(); }
+ bool has_uid() const { return at<4>().valid(); }
+ uint32_t uid() const { return at<4>().as_uint32(); }
+ bool has_gid() const { return at<5>().valid(); }
+ uint32_t gid() const { return at<5>().as_uint32(); }
+ bool has_mode() const { return at<6>().valid(); }
+ uint32_t mode() const { return at<6>().as_uint32(); }
+};
+
+class Ext4OtherInodeUpdateTimeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4OtherInodeUpdateTimeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOrigInoFieldNumber = 3,
+ kUidFieldNumber = 4,
+ kGidFieldNumber = 5,
+ kModeFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4OtherInodeUpdateTimeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4OtherInodeUpdateTimeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4OtherInodeUpdateTimeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigIno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4OtherInodeUpdateTimeFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigIno kOrigIno{};
+ void set_orig_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigIno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4OtherInodeUpdateTimeFtraceEvent>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Gid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4OtherInodeUpdateTimeFtraceEvent>;
+
+ static constexpr FieldMetadata_Gid kGid{};
+ void set_gid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Gid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4OtherInodeUpdateTimeFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MballocPreallocFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MballocPreallocFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MballocPreallocFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MballocPreallocFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_orig_logical() const { return at<3>().valid(); }
+ uint32_t orig_logical() const { return at<3>().as_uint32(); }
+ bool has_orig_start() const { return at<4>().valid(); }
+ int32_t orig_start() const { return at<4>().as_int32(); }
+ bool has_orig_group() const { return at<5>().valid(); }
+ uint32_t orig_group() const { return at<5>().as_uint32(); }
+ bool has_orig_len() const { return at<6>().valid(); }
+ int32_t orig_len() const { return at<6>().as_int32(); }
+ bool has_result_logical() const { return at<7>().valid(); }
+ uint32_t result_logical() const { return at<7>().as_uint32(); }
+ bool has_result_start() const { return at<8>().valid(); }
+ int32_t result_start() const { return at<8>().as_int32(); }
+ bool has_result_group() const { return at<9>().valid(); }
+ uint32_t result_group() const { return at<9>().as_uint32(); }
+ bool has_result_len() const { return at<10>().valid(); }
+ int32_t result_len() const { return at<10>().as_int32(); }
+};
+
+class Ext4MballocPreallocFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MballocPreallocFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOrigLogicalFieldNumber = 3,
+ kOrigStartFieldNumber = 4,
+ kOrigGroupFieldNumber = 5,
+ kOrigLenFieldNumber = 6,
+ kResultLogicalFieldNumber = 7,
+ kResultStartFieldNumber = 8,
+ kResultGroupFieldNumber = 9,
+ kResultLenFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MballocPreallocFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigLogical =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigLogical kOrigLogical{};
+ void set_orig_logical(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigLogical::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigStart kOrigStart{};
+ void set_orig_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigGroup =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigGroup kOrigGroup{};
+ void set_orig_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigGroup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigLen kOrigLen{};
+ void set_orig_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultLogical =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultLogical kResultLogical{};
+ void set_result_logical(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultLogical::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultStart kResultStart{};
+ void set_result_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultGroup =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultGroup kResultGroup{};
+ void set_result_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultGroup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocPreallocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultLen kResultLen{};
+ void set_result_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MballocFreeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MballocFreeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MballocFreeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MballocFreeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_result_start() const { return at<3>().valid(); }
+ int32_t result_start() const { return at<3>().as_int32(); }
+ bool has_result_group() const { return at<4>().valid(); }
+ uint32_t result_group() const { return at<4>().as_uint32(); }
+ bool has_result_len() const { return at<5>().valid(); }
+ int32_t result_len() const { return at<5>().as_int32(); }
+};
+
+class Ext4MballocFreeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MballocFreeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kResultStartFieldNumber = 3,
+ kResultGroupFieldNumber = 4,
+ kResultLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MballocFreeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultStart kResultStart{};
+ void set_result_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultGroup =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultGroup kResultGroup{};
+ void set_result_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultGroup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultLen kResultLen{};
+ void set_result_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MballocDiscardFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MballocDiscardFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MballocDiscardFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MballocDiscardFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_result_start() const { return at<3>().valid(); }
+ int32_t result_start() const { return at<3>().as_int32(); }
+ bool has_result_group() const { return at<4>().valid(); }
+ uint32_t result_group() const { return at<4>().as_uint32(); }
+ bool has_result_len() const { return at<5>().valid(); }
+ int32_t result_len() const { return at<5>().as_int32(); }
+};
+
+class Ext4MballocDiscardFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MballocDiscardFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kResultStartFieldNumber = 3,
+ kResultGroupFieldNumber = 4,
+ kResultLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MballocDiscardFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocDiscardFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocDiscardFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocDiscardFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultStart kResultStart{};
+ void set_result_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultGroup =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocDiscardFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultGroup kResultGroup{};
+ void set_result_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultGroup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocDiscardFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultLen kResultLen{};
+ void set_result_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MballocAllocFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/20, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MballocAllocFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MballocAllocFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MballocAllocFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_orig_logical() const { return at<3>().valid(); }
+ uint32_t orig_logical() const { return at<3>().as_uint32(); }
+ bool has_orig_start() const { return at<4>().valid(); }
+ int32_t orig_start() const { return at<4>().as_int32(); }
+ bool has_orig_group() const { return at<5>().valid(); }
+ uint32_t orig_group() const { return at<5>().as_uint32(); }
+ bool has_orig_len() const { return at<6>().valid(); }
+ int32_t orig_len() const { return at<6>().as_int32(); }
+ bool has_goal_logical() const { return at<7>().valid(); }
+ uint32_t goal_logical() const { return at<7>().as_uint32(); }
+ bool has_goal_start() const { return at<8>().valid(); }
+ int32_t goal_start() const { return at<8>().as_int32(); }
+ bool has_goal_group() const { return at<9>().valid(); }
+ uint32_t goal_group() const { return at<9>().as_uint32(); }
+ bool has_goal_len() const { return at<10>().valid(); }
+ int32_t goal_len() const { return at<10>().as_int32(); }
+ bool has_result_logical() const { return at<11>().valid(); }
+ uint32_t result_logical() const { return at<11>().as_uint32(); }
+ bool has_result_start() const { return at<12>().valid(); }
+ int32_t result_start() const { return at<12>().as_int32(); }
+ bool has_result_group() const { return at<13>().valid(); }
+ uint32_t result_group() const { return at<13>().as_uint32(); }
+ bool has_result_len() const { return at<14>().valid(); }
+ int32_t result_len() const { return at<14>().as_int32(); }
+ bool has_found() const { return at<15>().valid(); }
+ uint32_t found() const { return at<15>().as_uint32(); }
+ bool has_groups() const { return at<16>().valid(); }
+ uint32_t groups() const { return at<16>().as_uint32(); }
+ bool has_buddy() const { return at<17>().valid(); }
+ uint32_t buddy() const { return at<17>().as_uint32(); }
+ bool has_flags() const { return at<18>().valid(); }
+ uint32_t flags() const { return at<18>().as_uint32(); }
+ bool has_tail() const { return at<19>().valid(); }
+ uint32_t tail() const { return at<19>().as_uint32(); }
+ bool has_cr() const { return at<20>().valid(); }
+ uint32_t cr() const { return at<20>().as_uint32(); }
+};
+
+class Ext4MballocAllocFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MballocAllocFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOrigLogicalFieldNumber = 3,
+ kOrigStartFieldNumber = 4,
+ kOrigGroupFieldNumber = 5,
+ kOrigLenFieldNumber = 6,
+ kGoalLogicalFieldNumber = 7,
+ kGoalStartFieldNumber = 8,
+ kGoalGroupFieldNumber = 9,
+ kGoalLenFieldNumber = 10,
+ kResultLogicalFieldNumber = 11,
+ kResultStartFieldNumber = 12,
+ kResultGroupFieldNumber = 13,
+ kResultLenFieldNumber = 14,
+ kFoundFieldNumber = 15,
+ kGroupsFieldNumber = 16,
+ kBuddyFieldNumber = 17,
+ kFlagsFieldNumber = 18,
+ kTailFieldNumber = 19,
+ kCrFieldNumber = 20,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MballocAllocFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigLogical =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigLogical kOrigLogical{};
+ void set_orig_logical(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigLogical::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigStart kOrigStart{};
+ void set_orig_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigGroup =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigGroup kOrigGroup{};
+ void set_orig_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigGroup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigLen kOrigLen{};
+ void set_orig_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GoalLogical =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_GoalLogical kGoalLogical{};
+ void set_goal_logical(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GoalLogical::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GoalStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_GoalStart kGoalStart{};
+ void set_goal_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GoalStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GoalGroup =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_GoalGroup kGoalGroup{};
+ void set_goal_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GoalGroup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GoalLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_GoalLen kGoalLen{};
+ void set_goal_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GoalLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultLogical =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultLogical kResultLogical{};
+ void set_result_logical(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultLogical::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultStart kResultStart{};
+ void set_result_start(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultGroup =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultGroup kResultGroup{};
+ void set_result_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultGroup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResultLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_ResultLen kResultLen{};
+ void set_result_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResultLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Found =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Found kFound{};
+ void set_found(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Found::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Groups =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Groups kGroups{};
+ void set_groups(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Groups::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Buddy =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Buddy kBuddy{};
+ void set_buddy(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Buddy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tail =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Tail kTail{};
+ void set_tail(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tail::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cr =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MballocAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Cr kCr{};
+ void set_cr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MbReleaseInodePaFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MbReleaseInodePaFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MbReleaseInodePaFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MbReleaseInodePaFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_block() const { return at<3>().valid(); }
+ uint64_t block() const { return at<3>().as_uint64(); }
+ bool has_count() const { return at<4>().valid(); }
+ uint32_t count() const { return at<4>().as_uint32(); }
+};
+
+class Ext4MbReleaseInodePaFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MbReleaseInodePaFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kBlockFieldNumber = 3,
+ kCountFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MbReleaseInodePaFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbReleaseInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbReleaseInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Block =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbReleaseInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_Block kBlock{};
+ void set_block(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Block::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MbReleaseInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MbReleaseGroupPaFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MbReleaseGroupPaFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MbReleaseGroupPaFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MbReleaseGroupPaFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_pa_pstart() const { return at<2>().valid(); }
+ uint64_t pa_pstart() const { return at<2>().as_uint64(); }
+ bool has_pa_len() const { return at<3>().valid(); }
+ uint32_t pa_len() const { return at<3>().as_uint32(); }
+};
+
+class Ext4MbReleaseGroupPaFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MbReleaseGroupPaFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kPaPstartFieldNumber = 2,
+ kPaLenFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MbReleaseGroupPaFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbReleaseGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaPstart =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbReleaseGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaPstart kPaPstart{};
+ void set_pa_pstart(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaPstart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MbReleaseGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaLen kPaLen{};
+ void set_pa_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MbNewInodePaFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MbNewInodePaFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MbNewInodePaFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MbNewInodePaFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pa_pstart() const { return at<3>().valid(); }
+ uint64_t pa_pstart() const { return at<3>().as_uint64(); }
+ bool has_pa_lstart() const { return at<4>().valid(); }
+ uint64_t pa_lstart() const { return at<4>().as_uint64(); }
+ bool has_pa_len() const { return at<5>().valid(); }
+ uint32_t pa_len() const { return at<5>().as_uint32(); }
+};
+
+class Ext4MbNewInodePaFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MbNewInodePaFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPaPstartFieldNumber = 3,
+ kPaLstartFieldNumber = 4,
+ kPaLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MbNewInodePaFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaPstart =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaPstart kPaPstart{};
+ void set_pa_pstart(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaPstart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaLstart =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaLstart kPaLstart{};
+ void set_pa_lstart(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaLstart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MbNewInodePaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaLen kPaLen{};
+ void set_pa_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MbNewGroupPaFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MbNewGroupPaFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MbNewGroupPaFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MbNewGroupPaFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pa_pstart() const { return at<3>().valid(); }
+ uint64_t pa_pstart() const { return at<3>().as_uint64(); }
+ bool has_pa_lstart() const { return at<4>().valid(); }
+ uint64_t pa_lstart() const { return at<4>().as_uint64(); }
+ bool has_pa_len() const { return at<5>().valid(); }
+ uint32_t pa_len() const { return at<5>().as_uint32(); }
+};
+
+class Ext4MbNewGroupPaFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MbNewGroupPaFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPaPstartFieldNumber = 3,
+ kPaLstartFieldNumber = 4,
+ kPaLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MbNewGroupPaFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaPstart =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaPstart kPaPstart{};
+ void set_pa_pstart(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaPstart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaLstart =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbNewGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaLstart kPaLstart{};
+ void set_pa_lstart(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaLstart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PaLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MbNewGroupPaFtraceEvent>;
+
+ static constexpr FieldMetadata_PaLen kPaLen{};
+ void set_pa_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PaLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MbDiscardPreallocationsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MbDiscardPreallocationsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MbDiscardPreallocationsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MbDiscardPreallocationsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_needed() const { return at<2>().valid(); }
+ int32_t needed() const { return at<2>().as_int32(); }
+};
+
+class Ext4MbDiscardPreallocationsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MbDiscardPreallocationsFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kNeededFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MbDiscardPreallocationsFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbDiscardPreallocationsFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Needed =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4MbDiscardPreallocationsFtraceEvent>;
+
+ static constexpr FieldMetadata_Needed kNeeded{};
+ void set_needed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Needed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MbBuddyBitmapLoadFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MbBuddyBitmapLoadFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MbBuddyBitmapLoadFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MbBuddyBitmapLoadFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_group() const { return at<2>().valid(); }
+ uint32_t group() const { return at<2>().as_uint32(); }
+};
+
+class Ext4MbBuddyBitmapLoadFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MbBuddyBitmapLoadFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kGroupFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MbBuddyBitmapLoadFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbBuddyBitmapLoadFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MbBuddyBitmapLoadFtraceEvent>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MbBitmapLoadFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MbBitmapLoadFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MbBitmapLoadFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MbBitmapLoadFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_group() const { return at<2>().valid(); }
+ uint32_t group() const { return at<2>().as_uint32(); }
+};
+
+class Ext4MbBitmapLoadFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MbBitmapLoadFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kGroupFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MbBitmapLoadFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MbBitmapLoadFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4MbBitmapLoadFtraceEvent>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4MarkInodeDirtyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4MarkInodeDirtyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4MarkInodeDirtyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4MarkInodeDirtyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ip() const { return at<3>().valid(); }
+ uint64_t ip() const { return at<3>().as_uint64(); }
+};
+
+class Ext4MarkInodeDirtyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4MarkInodeDirtyFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIpFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4MarkInodeDirtyFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MarkInodeDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MarkInodeDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ip =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4MarkInodeDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Ip kIp{};
+ void set_ip(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ip::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4LoadInodeBitmapFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4LoadInodeBitmapFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4LoadInodeBitmapFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4LoadInodeBitmapFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_group() const { return at<2>().valid(); }
+ uint32_t group() const { return at<2>().as_uint32(); }
+};
+
+class Ext4LoadInodeBitmapFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4LoadInodeBitmapFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kGroupFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4LoadInodeBitmapFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4LoadInodeBitmapFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4LoadInodeBitmapFtraceEvent>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4LoadInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4LoadInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4LoadInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4LoadInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+};
+
+class Ext4LoadInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4LoadInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4LoadInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4LoadInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4LoadInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4JournalledWriteEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4JournalledWriteEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4JournalledWriteEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4JournalledWriteEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_copied() const { return at<5>().valid(); }
+ uint32_t copied() const { return at<5>().as_uint32(); }
+};
+
+class Ext4JournalledWriteEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4JournalledWriteEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kCopiedFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4JournalledWriteEndFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalledWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalledWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4JournalledWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4JournalledWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Copied =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4JournalledWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Copied kCopied{};
+ void set_copied(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Copied::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4JournalledInvalidatepageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4JournalledInvalidatepageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4JournalledInvalidatepageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4JournalledInvalidatepageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+ bool has_offset() const { return at<4>().valid(); }
+ uint64_t offset() const { return at<4>().as_uint64(); }
+ bool has_length() const { return at<5>().valid(); }
+ uint32_t length() const { return at<5>().as_uint32(); }
+};
+
+class Ext4JournalledInvalidatepageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4JournalledInvalidatepageFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ kOffsetFieldNumber = 4,
+ kLengthFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4JournalledInvalidatepageFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalledInvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalledInvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalledInvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalledInvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Length =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4JournalledInvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Length kLength{};
+ void set_length(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Length::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4JournalStartReservedFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4JournalStartReservedFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4JournalStartReservedFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4JournalStartReservedFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ip() const { return at<2>().valid(); }
+ uint64_t ip() const { return at<2>().as_uint64(); }
+ bool has_blocks() const { return at<3>().valid(); }
+ int32_t blocks() const { return at<3>().as_int32(); }
+};
+
+class Ext4JournalStartReservedFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4JournalStartReservedFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kIpFieldNumber = 2,
+ kBlocksFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4JournalStartReservedFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalStartReservedFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ip =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalStartReservedFtraceEvent>;
+
+ static constexpr FieldMetadata_Ip kIp{};
+ void set_ip(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ip::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4JournalStartReservedFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4JournalStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4JournalStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4JournalStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4JournalStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ip() const { return at<2>().valid(); }
+ uint64_t ip() const { return at<2>().as_uint64(); }
+ bool has_blocks() const { return at<3>().valid(); }
+ int32_t blocks() const { return at<3>().as_int32(); }
+ bool has_rsv_blocks() const { return at<4>().valid(); }
+ int32_t rsv_blocks() const { return at<4>().as_int32(); }
+ bool has_nblocks() const { return at<5>().valid(); }
+ int32_t nblocks() const { return at<5>().as_int32(); }
+ bool has_revoke_creds() const { return at<6>().valid(); }
+ int32_t revoke_creds() const { return at<6>().as_int32(); }
+};
+
+class Ext4JournalStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4JournalStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kIpFieldNumber = 2,
+ kBlocksFieldNumber = 3,
+ kRsvBlocksFieldNumber = 4,
+ kNblocksFieldNumber = 5,
+ kRevokeCredsFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4JournalStartFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ip =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4JournalStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Ip kIp{};
+ void set_ip(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ip::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4JournalStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RsvBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4JournalStartFtraceEvent>;
+
+ static constexpr FieldMetadata_RsvBlocks kRsvBlocks{};
+ void set_rsv_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RsvBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nblocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4JournalStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Nblocks kNblocks{};
+ void set_nblocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nblocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RevokeCreds =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4JournalStartFtraceEvent>;
+
+ static constexpr FieldMetadata_RevokeCreds kRevokeCreds{};
+ void set_revoke_creds(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RevokeCreds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4InvalidatepageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4InvalidatepageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4InvalidatepageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4InvalidatepageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+ bool has_offset() const { return at<4>().valid(); }
+ uint64_t offset() const { return at<4>().as_uint64(); }
+ bool has_length() const { return at<5>().valid(); }
+ uint32_t length() const { return at<5>().as_uint32(); }
+};
+
+class Ext4InvalidatepageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4InvalidatepageFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ kOffsetFieldNumber = 4,
+ kLengthFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4InvalidatepageFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4InvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4InvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4InvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4InvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Length =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4InvalidatepageFtraceEvent>;
+
+ static constexpr FieldMetadata_Length kLength{};
+ void set_length(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Length::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4InsertRangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4InsertRangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4InsertRangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4InsertRangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ int64_t len() const { return at<4>().as_int64(); }
+};
+
+class Ext4InsertRangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4InsertRangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4InsertRangeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4InsertRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4InsertRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4InsertRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4InsertRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4IndMapBlocksExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4IndMapBlocksExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4IndMapBlocksExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4IndMapBlocksExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_pblk() const { return at<4>().valid(); }
+ uint64_t pblk() const { return at<4>().as_uint64(); }
+ bool has_lblk() const { return at<5>().valid(); }
+ uint32_t lblk() const { return at<5>().as_uint32(); }
+ bool has_len() const { return at<6>().valid(); }
+ uint32_t len() const { return at<6>().as_uint32(); }
+ bool has_mflags() const { return at<7>().valid(); }
+ uint32_t mflags() const { return at<7>().as_uint32(); }
+ bool has_ret() const { return at<8>().valid(); }
+ int32_t ret() const { return at<8>().as_int32(); }
+};
+
+class Ext4IndMapBlocksExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4IndMapBlocksExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kPblkFieldNumber = 4,
+ kLblkFieldNumber = 5,
+ kLenFieldNumber = 6,
+ kMflagsFieldNumber = 7,
+ kRetFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4IndMapBlocksExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mflags =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Mflags kMflags{};
+ void set_mflags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mflags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4IndMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4IndMapBlocksEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4IndMapBlocksEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4IndMapBlocksEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4IndMapBlocksEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+};
+
+class Ext4IndMapBlocksEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4IndMapBlocksEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4IndMapBlocksEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4IndMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4IndMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4IndMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4IndMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4IndMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4GetReservedClusterAllocFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4GetReservedClusterAllocFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4GetReservedClusterAllocFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4GetReservedClusterAllocFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+};
+
+class Ext4GetReservedClusterAllocFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4GetReservedClusterAllocFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4GetReservedClusterAllocFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4GetReservedClusterAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4GetReservedClusterAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4GetReservedClusterAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4GetReservedClusterAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4GetImpliedClusterAllocExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4GetImpliedClusterAllocExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4GetImpliedClusterAllocExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4GetImpliedClusterAllocExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_pblk() const { return at<4>().valid(); }
+ uint64_t pblk() const { return at<4>().as_uint64(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint32_t len() const { return at<5>().as_uint32(); }
+ bool has_ret() const { return at<6>().valid(); }
+ int32_t ret() const { return at<6>().as_int32(); }
+};
+
+class Ext4GetImpliedClusterAllocExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4GetImpliedClusterAllocExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kPblkFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kRetFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4GetImpliedClusterAllocExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4GetImpliedClusterAllocExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4GetImpliedClusterAllocExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4GetImpliedClusterAllocExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4GetImpliedClusterAllocExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4GetImpliedClusterAllocExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4GetImpliedClusterAllocExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4FreeInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4FreeInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4FreeInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4FreeInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_uid() const { return at<3>().valid(); }
+ uint32_t uid() const { return at<3>().as_uint32(); }
+ bool has_gid() const { return at<4>().valid(); }
+ uint32_t gid() const { return at<4>().as_uint32(); }
+ bool has_blocks() const { return at<5>().valid(); }
+ uint64_t blocks() const { return at<5>().as_uint64(); }
+ bool has_mode() const { return at<6>().valid(); }
+ uint32_t mode() const { return at<6>().as_uint32(); }
+};
+
+class Ext4FreeInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4FreeInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kUidFieldNumber = 3,
+ kGidFieldNumber = 4,
+ kBlocksFieldNumber = 5,
+ kModeFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4FreeInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FreeInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FreeInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FreeInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Gid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FreeInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Gid kGid{};
+ void set_gid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Gid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FreeInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FreeInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4FreeBlocksFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4FreeBlocksFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4FreeBlocksFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4FreeBlocksFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_block() const { return at<3>().valid(); }
+ uint64_t block() const { return at<3>().as_uint64(); }
+ bool has_count() const { return at<4>().valid(); }
+ uint64_t count() const { return at<4>().as_uint64(); }
+ bool has_flags() const { return at<5>().valid(); }
+ int32_t flags() const { return at<5>().as_int32(); }
+ bool has_mode() const { return at<6>().valid(); }
+ uint32_t mode() const { return at<6>().as_uint32(); }
+};
+
+class Ext4FreeBlocksFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4FreeBlocksFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kBlockFieldNumber = 3,
+ kCountFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ kModeFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4FreeBlocksFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FreeBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FreeBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Block =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FreeBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Block kBlock{};
+ void set_block(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Block::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FreeBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4FreeBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FreeBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ForgetFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ForgetFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ForgetFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ForgetFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_block() const { return at<3>().valid(); }
+ uint64_t block() const { return at<3>().as_uint64(); }
+ bool has_is_metadata() const { return at<4>().valid(); }
+ int32_t is_metadata() const { return at<4>().as_int32(); }
+ bool has_mode() const { return at<5>().valid(); }
+ uint32_t mode() const { return at<5>().as_uint32(); }
+};
+
+class Ext4ForgetFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ForgetFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kBlockFieldNumber = 3,
+ kIsMetadataFieldNumber = 4,
+ kModeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ForgetFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ForgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ForgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Block =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ForgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Block kBlock{};
+ void set_block(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Block::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsMetadata =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ForgetFtraceEvent>;
+
+ static constexpr FieldMetadata_IsMetadata kIsMetadata{};
+ void set_is_metadata(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsMetadata::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ForgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4FindDelallocRangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4FindDelallocRangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4FindDelallocRangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4FindDelallocRangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_from() const { return at<3>().valid(); }
+ uint32_t from() const { return at<3>().as_uint32(); }
+ bool has_to() const { return at<4>().valid(); }
+ uint32_t to() const { return at<4>().as_uint32(); }
+ bool has_reverse() const { return at<5>().valid(); }
+ int32_t reverse() const { return at<5>().as_int32(); }
+ bool has_found() const { return at<6>().valid(); }
+ int32_t found() const { return at<6>().as_int32(); }
+ bool has_found_blk() const { return at<7>().valid(); }
+ uint32_t found_blk() const { return at<7>().as_uint32(); }
+};
+
+class Ext4FindDelallocRangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4FindDelallocRangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kFromFieldNumber = 3,
+ kToFieldNumber = 4,
+ kReverseFieldNumber = 5,
+ kFoundFieldNumber = 6,
+ kFoundBlkFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4FindDelallocRangeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FindDelallocRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FindDelallocRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_From =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FindDelallocRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_From kFrom{};
+ void set_from(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_From::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_To =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FindDelallocRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_To kTo{};
+ void set_to(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_To::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Reverse =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4FindDelallocRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Reverse kReverse{};
+ void set_reverse(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reverse::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Found =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4FindDelallocRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Found kFound{};
+ void set_found(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Found::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FoundBlk =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FindDelallocRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_FoundBlk kFoundBlk{};
+ void set_found_blk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FoundBlk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4FallocateExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4FallocateExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4FallocateExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4FallocateExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_blocks() const { return at<4>().valid(); }
+ uint32_t blocks() const { return at<4>().as_uint32(); }
+ bool has_ret() const { return at<5>().valid(); }
+ int32_t ret() const { return at<5>().as_int32(); }
+};
+
+class Ext4FallocateExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4FallocateExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kBlocksFieldNumber = 4,
+ kRetFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4FallocateExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FallocateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FallocateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4FallocateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4FallocateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4FallocateExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4FallocateEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4FallocateEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4FallocateEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4FallocateEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ int64_t len() const { return at<4>().as_int64(); }
+ bool has_mode() const { return at<5>().valid(); }
+ int32_t mode() const { return at<5>().as_int32(); }
+ bool has_pos() const { return at<6>().valid(); }
+ int64_t pos() const { return at<6>().as_int64(); }
+};
+
+class Ext4FallocateEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4FallocateEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kModeFieldNumber = 5,
+ kPosFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4FallocateEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FallocateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4FallocateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4FallocateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4FallocateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4FallocateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4FallocateEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtShowExtentFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtShowExtentFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtShowExtentFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtShowExtentFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pblk() const { return at<3>().valid(); }
+ uint64_t pblk() const { return at<3>().as_uint64(); }
+ bool has_lblk() const { return at<4>().valid(); }
+ uint32_t lblk() const { return at<4>().as_uint32(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint32_t len() const { return at<5>().as_uint32(); }
+};
+
+class Ext4ExtShowExtentFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtShowExtentFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPblkFieldNumber = 3,
+ kLblkFieldNumber = 4,
+ kLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtShowExtentFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtShowExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtShowExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtShowExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtShowExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtShowExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtRmLeafFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtRmLeafFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtRmLeafFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtRmLeafFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_partial() const { return at<3>().valid(); }
+ int64_t partial() const { return at<3>().as_int64(); }
+ bool has_start() const { return at<4>().valid(); }
+ uint32_t start() const { return at<4>().as_uint32(); }
+ bool has_ee_lblk() const { return at<5>().valid(); }
+ uint32_t ee_lblk() const { return at<5>().as_uint32(); }
+ bool has_ee_pblk() const { return at<6>().valid(); }
+ uint64_t ee_pblk() const { return at<6>().as_uint64(); }
+ bool has_ee_len() const { return at<7>().valid(); }
+ int32_t ee_len() const { return at<7>().as_int32(); }
+ bool has_pc_lblk() const { return at<8>().valid(); }
+ uint32_t pc_lblk() const { return at<8>().as_uint32(); }
+ bool has_pc_pclu() const { return at<9>().valid(); }
+ uint64_t pc_pclu() const { return at<9>().as_uint64(); }
+ bool has_pc_state() const { return at<10>().valid(); }
+ int32_t pc_state() const { return at<10>().as_int32(); }
+};
+
+class Ext4ExtRmLeafFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtRmLeafFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPartialFieldNumber = 3,
+ kStartFieldNumber = 4,
+ kEeLblkFieldNumber = 5,
+ kEePblkFieldNumber = 6,
+ kEeLenFieldNumber = 7,
+ kPcLblkFieldNumber = 8,
+ kPcPcluFieldNumber = 9,
+ kPcStateFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtRmLeafFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Partial =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_Partial kPartial{};
+ void set_partial(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Partial::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EeLblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_EeLblk kEeLblk{};
+ void set_ee_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EeLblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EePblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_EePblk kEePblk{};
+ void set_ee_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EePblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EeLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_EeLen kEeLen{};
+ void set_ee_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EeLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcLblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_PcLblk kPcLblk{};
+ void set_pc_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcLblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcPclu =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_PcPclu kPcPclu{};
+ void set_pc_pclu(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcPclu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcState =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtRmLeafFtraceEvent>;
+
+ static constexpr FieldMetadata_PcState kPcState{};
+ void set_pc_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtRmIdxFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtRmIdxFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtRmIdxFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtRmIdxFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pblk() const { return at<3>().valid(); }
+ uint64_t pblk() const { return at<3>().as_uint64(); }
+};
+
+class Ext4ExtRmIdxFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtRmIdxFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPblkFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtRmIdxFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRmIdxFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRmIdxFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRmIdxFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtRemoveSpaceDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtRemoveSpaceDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtRemoveSpaceDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtRemoveSpaceDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_start() const { return at<3>().valid(); }
+ uint32_t start() const { return at<3>().as_uint32(); }
+ bool has_end() const { return at<4>().valid(); }
+ uint32_t end() const { return at<4>().as_uint32(); }
+ bool has_depth() const { return at<5>().valid(); }
+ int32_t depth() const { return at<5>().as_int32(); }
+ bool has_partial() const { return at<6>().valid(); }
+ int64_t partial() const { return at<6>().as_int64(); }
+ bool has_eh_entries() const { return at<7>().valid(); }
+ uint32_t eh_entries() const { return at<7>().as_uint32(); }
+ bool has_pc_lblk() const { return at<8>().valid(); }
+ uint32_t pc_lblk() const { return at<8>().as_uint32(); }
+ bool has_pc_pclu() const { return at<9>().valid(); }
+ uint64_t pc_pclu() const { return at<9>().as_uint64(); }
+ bool has_pc_state() const { return at<10>().valid(); }
+ int32_t pc_state() const { return at<10>().as_int32(); }
+};
+
+class Ext4ExtRemoveSpaceDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtRemoveSpaceDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kStartFieldNumber = 3,
+ kEndFieldNumber = 4,
+ kDepthFieldNumber = 5,
+ kPartialFieldNumber = 6,
+ kEhEntriesFieldNumber = 7,
+ kPcLblkFieldNumber = 8,
+ kPcPcluFieldNumber = 9,
+ kPcStateFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtRemoveSpaceDoneFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_End =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_End kEnd{};
+ void set_end(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_End::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Depth =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Depth kDepth{};
+ void set_depth(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Depth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Partial =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Partial kPartial{};
+ void set_partial(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Partial::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EhEntries =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_EhEntries kEhEntries{};
+ void set_eh_entries(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EhEntries::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcLblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_PcLblk kPcLblk{};
+ void set_pc_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcLblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcPclu =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_PcPclu kPcPclu{};
+ void set_pc_pclu(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcPclu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PcState =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtRemoveSpaceDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_PcState kPcState{};
+ void set_pc_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PcState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtRemoveSpaceFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtRemoveSpaceFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtRemoveSpaceFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtRemoveSpaceFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_start() const { return at<3>().valid(); }
+ uint32_t start() const { return at<3>().as_uint32(); }
+ bool has_end() const { return at<4>().valid(); }
+ uint32_t end() const { return at<4>().as_uint32(); }
+ bool has_depth() const { return at<5>().valid(); }
+ int32_t depth() const { return at<5>().as_int32(); }
+};
+
+class Ext4ExtRemoveSpaceFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtRemoveSpaceFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kStartFieldNumber = 3,
+ kEndFieldNumber = 4,
+ kDepthFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtRemoveSpaceFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRemoveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtRemoveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRemoveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_End =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtRemoveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_End kEnd{};
+ void set_end(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_End::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Depth =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtRemoveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Depth kDepth{};
+ void set_depth(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Depth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtPutInCacheFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtPutInCacheFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtPutInCacheFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtPutInCacheFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_start() const { return at<5>().valid(); }
+ uint64_t start() const { return at<5>().as_uint64(); }
+};
+
+class Ext4ExtPutInCacheFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtPutInCacheFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kStartFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtPutInCacheFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtPutInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtPutInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtPutInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtPutInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtPutInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtMapBlocksExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtMapBlocksExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtMapBlocksExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtMapBlocksExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_pblk() const { return at<4>().valid(); }
+ uint64_t pblk() const { return at<4>().as_uint64(); }
+ bool has_lblk() const { return at<5>().valid(); }
+ uint32_t lblk() const { return at<5>().as_uint32(); }
+ bool has_len() const { return at<6>().valid(); }
+ uint32_t len() const { return at<6>().as_uint32(); }
+ bool has_mflags() const { return at<7>().valid(); }
+ uint32_t mflags() const { return at<7>().as_uint32(); }
+ bool has_ret() const { return at<8>().valid(); }
+ int32_t ret() const { return at<8>().as_int32(); }
+};
+
+class Ext4ExtMapBlocksExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtMapBlocksExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kPblkFieldNumber = 4,
+ kLblkFieldNumber = 5,
+ kLenFieldNumber = 6,
+ kMflagsFieldNumber = 7,
+ kRetFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtMapBlocksExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mflags =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Mflags kMflags{};
+ void set_mflags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mflags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtMapBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtMapBlocksEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtMapBlocksEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtMapBlocksEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtMapBlocksEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+};
+
+class Ext4ExtMapBlocksEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtMapBlocksEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtMapBlocksEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtMapBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtLoadExtentFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtLoadExtentFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtLoadExtentFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtLoadExtentFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pblk() const { return at<3>().valid(); }
+ uint64_t pblk() const { return at<3>().as_uint64(); }
+ bool has_lblk() const { return at<4>().valid(); }
+ uint32_t lblk() const { return at<4>().as_uint32(); }
+};
+
+class Ext4ExtLoadExtentFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtLoadExtentFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPblkFieldNumber = 3,
+ kLblkFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtLoadExtentFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtLoadExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtLoadExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtLoadExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtLoadExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtInCacheFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtInCacheFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtInCacheFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtInCacheFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_ret() const { return at<4>().valid(); }
+ int32_t ret() const { return at<4>().as_int32(); }
+};
+
+class Ext4ExtInCacheFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtInCacheFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kRetFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtInCacheFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtInCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtHandleUnwrittenExtentsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtHandleUnwrittenExtentsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtHandleUnwrittenExtentsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_flags() const { return at<3>().valid(); }
+ int32_t flags() const { return at<3>().as_int32(); }
+ bool has_lblk() const { return at<4>().valid(); }
+ uint32_t lblk() const { return at<4>().as_uint32(); }
+ bool has_pblk() const { return at<5>().valid(); }
+ uint64_t pblk() const { return at<5>().as_uint64(); }
+ bool has_len() const { return at<6>().valid(); }
+ uint32_t len() const { return at<6>().as_uint32(); }
+ bool has_allocated() const { return at<7>().valid(); }
+ uint32_t allocated() const { return at<7>().as_uint32(); }
+ bool has_newblk() const { return at<8>().valid(); }
+ uint64_t newblk() const { return at<8>().as_uint64(); }
+};
+
+class Ext4ExtHandleUnwrittenExtentsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtHandleUnwrittenExtentsFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kLblkFieldNumber = 4,
+ kPblkFieldNumber = 5,
+ kLenFieldNumber = 6,
+ kAllocatedFieldNumber = 7,
+ kNewblkFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtHandleUnwrittenExtentsFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Allocated =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Allocated kAllocated{};
+ void set_allocated(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Allocated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Newblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtHandleUnwrittenExtentsFtraceEvent>;
+
+ static constexpr FieldMetadata_Newblk kNewblk{};
+ void set_newblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Newblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtConvertToInitializedFastpathFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtConvertToInitializedFastpathFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtConvertToInitializedFastpathFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtConvertToInitializedFastpathFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_m_lblk() const { return at<3>().valid(); }
+ uint32_t m_lblk() const { return at<3>().as_uint32(); }
+ bool has_m_len() const { return at<4>().valid(); }
+ uint32_t m_len() const { return at<4>().as_uint32(); }
+ bool has_u_lblk() const { return at<5>().valid(); }
+ uint32_t u_lblk() const { return at<5>().as_uint32(); }
+ bool has_u_len() const { return at<6>().valid(); }
+ uint32_t u_len() const { return at<6>().as_uint32(); }
+ bool has_u_pblk() const { return at<7>().valid(); }
+ uint64_t u_pblk() const { return at<7>().as_uint64(); }
+ bool has_i_lblk() const { return at<8>().valid(); }
+ uint32_t i_lblk() const { return at<8>().as_uint32(); }
+ bool has_i_len() const { return at<9>().valid(); }
+ uint32_t i_len() const { return at<9>().as_uint32(); }
+ bool has_i_pblk() const { return at<10>().valid(); }
+ uint64_t i_pblk() const { return at<10>().as_uint64(); }
+};
+
+class Ext4ExtConvertToInitializedFastpathFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtConvertToInitializedFastpathFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kMLblkFieldNumber = 3,
+ kMLenFieldNumber = 4,
+ kULblkFieldNumber = 5,
+ kULenFieldNumber = 6,
+ kUPblkFieldNumber = 7,
+ kILblkFieldNumber = 8,
+ kILenFieldNumber = 9,
+ kIPblkFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtConvertToInitializedFastpathFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MLblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_MLblk kMLblk{};
+ void set_m_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MLblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_MLen kMLen{};
+ void set_m_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ULblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_ULblk kULblk{};
+ void set_u_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ULblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ULen =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_ULen kULen{};
+ void set_u_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ULen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UPblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_UPblk kUPblk{};
+ void set_u_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UPblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ILblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_ILblk kILblk{};
+ void set_i_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ILblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ILen =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_ILen kILen{};
+ void set_i_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ILen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IPblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtConvertToInitializedFastpathFtraceEvent>;
+
+ static constexpr FieldMetadata_IPblk kIPblk{};
+ void set_i_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IPblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4ExtConvertToInitializedEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4ExtConvertToInitializedEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4ExtConvertToInitializedEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4ExtConvertToInitializedEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_m_lblk() const { return at<3>().valid(); }
+ uint32_t m_lblk() const { return at<3>().as_uint32(); }
+ bool has_m_len() const { return at<4>().valid(); }
+ uint32_t m_len() const { return at<4>().as_uint32(); }
+ bool has_u_lblk() const { return at<5>().valid(); }
+ uint32_t u_lblk() const { return at<5>().as_uint32(); }
+ bool has_u_len() const { return at<6>().valid(); }
+ uint32_t u_len() const { return at<6>().as_uint32(); }
+ bool has_u_pblk() const { return at<7>().valid(); }
+ uint64_t u_pblk() const { return at<7>().as_uint64(); }
+};
+
+class Ext4ExtConvertToInitializedEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4ExtConvertToInitializedEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kMLblkFieldNumber = 3,
+ kMLenFieldNumber = 4,
+ kULblkFieldNumber = 5,
+ kULenFieldNumber = 6,
+ kUPblkFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4ExtConvertToInitializedEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtConvertToInitializedEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtConvertToInitializedEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MLblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_MLblk kMLblk{};
+ void set_m_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MLblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_MLen kMLen{};
+ void set_m_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ULblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_ULblk kULblk{};
+ void set_u_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ULblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ULen =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4ExtConvertToInitializedEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_ULen kULen{};
+ void set_u_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ULen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UPblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4ExtConvertToInitializedEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_UPblk kUPblk{};
+ void set_u_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UPblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EvictInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EvictInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EvictInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EvictInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_nlink() const { return at<3>().valid(); }
+ int32_t nlink() const { return at<3>().as_int32(); }
+};
+
+class Ext4EvictInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EvictInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNlinkFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EvictInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nlink =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Nlink kNlink{};
+ void set_nlink(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nlink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsShrinkScanExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsShrinkScanExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsShrinkScanExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsShrinkScanExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_nr_shrunk() const { return at<2>().valid(); }
+ int32_t nr_shrunk() const { return at<2>().as_int32(); }
+ bool has_cache_cnt() const { return at<3>().valid(); }
+ int32_t cache_cnt() const { return at<3>().as_int32(); }
+};
+
+class Ext4EsShrinkScanExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsShrinkScanExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kNrShrunkFieldNumber = 2,
+ kCacheCntFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsShrinkScanExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsShrinkScanExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrShrunk =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkScanExitFtraceEvent>;
+
+ static constexpr FieldMetadata_NrShrunk kNrShrunk{};
+ void set_nr_shrunk(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrShrunk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CacheCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkScanExitFtraceEvent>;
+
+ static constexpr FieldMetadata_CacheCnt kCacheCnt{};
+ void set_cache_cnt(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CacheCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsShrinkScanEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsShrinkScanEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsShrinkScanEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsShrinkScanEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_nr_to_scan() const { return at<2>().valid(); }
+ int32_t nr_to_scan() const { return at<2>().as_int32(); }
+ bool has_cache_cnt() const { return at<3>().valid(); }
+ int32_t cache_cnt() const { return at<3>().as_int32(); }
+};
+
+class Ext4EsShrinkScanEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsShrinkScanEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kNrToScanFieldNumber = 2,
+ kCacheCntFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsShrinkScanEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsShrinkScanEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrToScan =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkScanEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_NrToScan kNrToScan{};
+ void set_nr_to_scan(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrToScan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CacheCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkScanEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_CacheCnt kCacheCnt{};
+ void set_cache_cnt(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CacheCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsShrinkCountFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsShrinkCountFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsShrinkCountFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsShrinkCountFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_nr_to_scan() const { return at<2>().valid(); }
+ int32_t nr_to_scan() const { return at<2>().as_int32(); }
+ bool has_cache_cnt() const { return at<3>().valid(); }
+ int32_t cache_cnt() const { return at<3>().as_int32(); }
+};
+
+class Ext4EsShrinkCountFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsShrinkCountFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kNrToScanFieldNumber = 2,
+ kCacheCntFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsShrinkCountFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsShrinkCountFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrToScan =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkCountFtraceEvent>;
+
+ static constexpr FieldMetadata_NrToScan kNrToScan{};
+ void set_nr_to_scan(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrToScan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CacheCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkCountFtraceEvent>;
+
+ static constexpr FieldMetadata_CacheCnt kCacheCnt{};
+ void set_cache_cnt(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CacheCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsShrinkFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsShrinkFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsShrinkFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsShrinkFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_nr_shrunk() const { return at<2>().valid(); }
+ int32_t nr_shrunk() const { return at<2>().as_int32(); }
+ bool has_scan_time() const { return at<3>().valid(); }
+ uint64_t scan_time() const { return at<3>().as_uint64(); }
+ bool has_nr_skipped() const { return at<4>().valid(); }
+ int32_t nr_skipped() const { return at<4>().as_int32(); }
+ bool has_retried() const { return at<5>().valid(); }
+ int32_t retried() const { return at<5>().as_int32(); }
+};
+
+class Ext4EsShrinkFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsShrinkFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kNrShrunkFieldNumber = 2,
+ kScanTimeFieldNumber = 3,
+ kNrSkippedFieldNumber = 4,
+ kRetriedFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsShrinkFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrShrunk =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_NrShrunk kNrShrunk{};
+ void set_nr_shrunk(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrShrunk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScanTime =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_ScanTime kScanTime{};
+ void set_scan_time(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScanTime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrSkipped =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_NrSkipped kNrSkipped{};
+ void set_nr_skipped(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrSkipped::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Retried =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_Retried kRetried{};
+ void set_retried(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Retried::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsRemoveExtentFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsRemoveExtentFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsRemoveExtentFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsRemoveExtentFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ int64_t lblk() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ int64_t len() const { return at<4>().as_int64(); }
+};
+
+class Ext4EsRemoveExtentFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsRemoveExtentFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsRemoveExtentFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsRemoveExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsRemoveExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4EsRemoveExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4EsRemoveExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsLookupExtentExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsLookupExtentExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsLookupExtentExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsLookupExtentExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_pblk() const { return at<5>().valid(); }
+ uint64_t pblk() const { return at<5>().as_uint64(); }
+ bool has_status() const { return at<6>().valid(); }
+ uint64_t status() const { return at<6>().as_uint64(); }
+ bool has_found() const { return at<7>().valid(); }
+ int32_t found() const { return at<7>().as_int32(); }
+};
+
+class Ext4EsLookupExtentExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsLookupExtentExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kPblkFieldNumber = 5,
+ kStatusFieldNumber = 6,
+ kFoundFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsLookupExtentExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsLookupExtentExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsLookupExtentExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsLookupExtentExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsLookupExtentExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsLookupExtentExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsLookupExtentExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Found =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4EsLookupExtentExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Found kFound{};
+ void set_found(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Found::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsLookupExtentEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsLookupExtentEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsLookupExtentEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsLookupExtentEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+};
+
+class Ext4EsLookupExtentEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsLookupExtentEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsLookupExtentEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsLookupExtentEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsLookupExtentEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsLookupExtentEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsInsertExtentFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsInsertExtentFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsInsertExtentFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsInsertExtentFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_pblk() const { return at<5>().valid(); }
+ uint64_t pblk() const { return at<5>().as_uint64(); }
+ bool has_status() const { return at<6>().valid(); }
+ uint64_t status() const { return at<6>().as_uint64(); }
+};
+
+class Ext4EsInsertExtentFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsInsertExtentFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kPblkFieldNumber = 5,
+ kStatusFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsInsertExtentFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsInsertExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsInsertExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsInsertExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsInsertExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsInsertExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsInsertExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsFindDelayedExtentRangeExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsFindDelayedExtentRangeExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsFindDelayedExtentRangeExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_pblk() const { return at<5>().valid(); }
+ uint64_t pblk() const { return at<5>().as_uint64(); }
+ bool has_status() const { return at<6>().valid(); }
+ uint64_t status() const { return at<6>().as_uint64(); }
+};
+
+class Ext4EsFindDelayedExtentRangeExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsFindDelayedExtentRangeExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kPblkFieldNumber = 5,
+ kStatusFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsFindDelayedExtentRangeExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsFindDelayedExtentRangeExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsFindDelayedExtentRangeEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsFindDelayedExtentRangeEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsFindDelayedExtentRangeEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsFindDelayedExtentRangeEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+};
+
+class Ext4EsFindDelayedExtentRangeEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsFindDelayedExtentRangeEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsFindDelayedExtentRangeEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsFindDelayedExtentRangeEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsFindDelayedExtentRangeEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsFindDelayedExtentRangeEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4EsCacheExtentFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4EsCacheExtentFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4EsCacheExtentFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4EsCacheExtentFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint32_t lblk() const { return at<3>().as_uint32(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_pblk() const { return at<5>().valid(); }
+ uint64_t pblk() const { return at<5>().as_uint64(); }
+ bool has_status() const { return at<6>().valid(); }
+ uint32_t status() const { return at<6>().as_uint32(); }
+};
+
+class Ext4EsCacheExtentFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4EsCacheExtentFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kPblkFieldNumber = 5,
+ kStatusFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4EsCacheExtentFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsCacheExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsCacheExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsCacheExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsCacheExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4EsCacheExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Pblk kPblk{};
+ void set_pblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4EsCacheExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DropInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DropInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DropInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DropInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_drop() const { return at<3>().valid(); }
+ int32_t drop() const { return at<3>().as_int32(); }
+};
+
+class Ext4DropInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DropInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kDropFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DropInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DropInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DropInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Drop =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DropInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Drop kDrop{};
+ void set_drop(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Drop::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DiscardPreallocationsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DiscardPreallocationsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DiscardPreallocationsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DiscardPreallocationsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_len() const { return at<3>().valid(); }
+ uint32_t len() const { return at<3>().as_uint32(); }
+ bool has_needed() const { return at<4>().valid(); }
+ uint32_t needed() const { return at<4>().as_uint32(); }
+};
+
+class Ext4DiscardPreallocationsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DiscardPreallocationsFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLenFieldNumber = 3,
+ kNeededFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DiscardPreallocationsFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DiscardPreallocationsFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DiscardPreallocationsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DiscardPreallocationsFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Needed =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DiscardPreallocationsFtraceEvent>;
+
+ static constexpr FieldMetadata_Needed kNeeded{};
+ void set_needed(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Needed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DiscardBlocksFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DiscardBlocksFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DiscardBlocksFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DiscardBlocksFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_blk() const { return at<2>().valid(); }
+ uint64_t blk() const { return at<2>().as_uint64(); }
+ bool has_count() const { return at<3>().valid(); }
+ uint64_t count() const { return at<3>().as_uint64(); }
+};
+
+class Ext4DiscardBlocksFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DiscardBlocksFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kBlkFieldNumber = 2,
+ kCountFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DiscardBlocksFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DiscardBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blk =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DiscardBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Blk kBlk{};
+ void set_blk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DiscardBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DirectIOExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DirectIOExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DirectIOExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DirectIOExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+ bool has_rw() const { return at<5>().valid(); }
+ int32_t rw() const { return at<5>().as_int32(); }
+ bool has_ret() const { return at<6>().valid(); }
+ int32_t ret() const { return at<6>().as_int32(); }
+};
+
+class Ext4DirectIOExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DirectIOExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kRwFieldNumber = 5,
+ kRetFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DirectIOExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DirectIOExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DirectIOExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4DirectIOExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DirectIOExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rw =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DirectIOExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Rw kRw{};
+ void set_rw(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DirectIOExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DirectIOEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DirectIOEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DirectIOEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DirectIOEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+ bool has_rw() const { return at<5>().valid(); }
+ int32_t rw() const { return at<5>().as_int32(); }
+};
+
+class Ext4DirectIOEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DirectIOEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kRwFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DirectIOEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DirectIOEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DirectIOEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4DirectIOEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DirectIOEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rw =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DirectIOEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Rw kRw{};
+ void set_rw(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DaWritePagesExtentFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DaWritePagesExtentFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DaWritePagesExtentFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DaWritePagesExtentFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_lblk() const { return at<3>().valid(); }
+ uint64_t lblk() const { return at<3>().as_uint64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+};
+
+class Ext4DaWritePagesExtentFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DaWritePagesExtentFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kLblkFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DaWritePagesExtentFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWritePagesExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWritePagesExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lblk =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWritePagesExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Lblk kLblk{};
+ void set_lblk(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lblk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWritePagesExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWritePagesExtentFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DaWritePagesFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DaWritePagesFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DaWritePagesFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DaWritePagesFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_first_page() const { return at<3>().valid(); }
+ uint64_t first_page() const { return at<3>().as_uint64(); }
+ bool has_nr_to_write() const { return at<4>().valid(); }
+ int64_t nr_to_write() const { return at<4>().as_int64(); }
+ bool has_sync_mode() const { return at<5>().valid(); }
+ int32_t sync_mode() const { return at<5>().as_int32(); }
+ bool has_b_blocknr() const { return at<6>().valid(); }
+ uint64_t b_blocknr() const { return at<6>().as_uint64(); }
+ bool has_b_size() const { return at<7>().valid(); }
+ uint32_t b_size() const { return at<7>().as_uint32(); }
+ bool has_b_state() const { return at<8>().valid(); }
+ uint32_t b_state() const { return at<8>().as_uint32(); }
+ bool has_io_done() const { return at<9>().valid(); }
+ int32_t io_done() const { return at<9>().as_int32(); }
+ bool has_pages_written() const { return at<10>().valid(); }
+ int32_t pages_written() const { return at<10>().as_int32(); }
+};
+
+class Ext4DaWritePagesFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DaWritePagesFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kFirstPageFieldNumber = 3,
+ kNrToWriteFieldNumber = 4,
+ kSyncModeFieldNumber = 5,
+ kBBlocknrFieldNumber = 6,
+ kBSizeFieldNumber = 7,
+ kBStateFieldNumber = 8,
+ kIoDoneFieldNumber = 9,
+ kPagesWrittenFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DaWritePagesFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FirstPage =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_FirstPage kFirstPage{};
+ void set_first_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FirstPage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrToWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_NrToWrite kNrToWrite{};
+ void set_nr_to_write(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrToWrite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SyncMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_SyncMode kSyncMode{};
+ void set_sync_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SyncMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BBlocknr =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_BBlocknr kBBlocknr{};
+ void set_b_blocknr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BBlocknr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_BSize kBSize{};
+ void set_b_size(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BState =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_BState kBState{};
+ void set_b_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IoDone =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_IoDone kIoDone{};
+ void set_io_done(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IoDone::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PagesWritten =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaWritePagesFtraceEvent>;
+
+ static constexpr FieldMetadata_PagesWritten kPagesWritten{};
+ void set_pages_written(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PagesWritten::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DaUpdateReserveSpaceFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DaUpdateReserveSpaceFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DaUpdateReserveSpaceFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DaUpdateReserveSpaceFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_i_blocks() const { return at<3>().valid(); }
+ uint64_t i_blocks() const { return at<3>().as_uint64(); }
+ bool has_used_blocks() const { return at<4>().valid(); }
+ int32_t used_blocks() const { return at<4>().as_int32(); }
+ bool has_reserved_data_blocks() const { return at<5>().valid(); }
+ int32_t reserved_data_blocks() const { return at<5>().as_int32(); }
+ bool has_reserved_meta_blocks() const { return at<6>().valid(); }
+ int32_t reserved_meta_blocks() const { return at<6>().as_int32(); }
+ bool has_allocated_meta_blocks() const { return at<7>().valid(); }
+ int32_t allocated_meta_blocks() const { return at<7>().as_int32(); }
+ bool has_quota_claim() const { return at<8>().valid(); }
+ int32_t quota_claim() const { return at<8>().as_int32(); }
+ bool has_mode() const { return at<9>().valid(); }
+ uint32_t mode() const { return at<9>().as_uint32(); }
+};
+
+class Ext4DaUpdateReserveSpaceFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DaUpdateReserveSpaceFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIBlocksFieldNumber = 3,
+ kUsedBlocksFieldNumber = 4,
+ kReservedDataBlocksFieldNumber = 5,
+ kReservedMetaBlocksFieldNumber = 6,
+ kAllocatedMetaBlocksFieldNumber = 7,
+ kQuotaClaimFieldNumber = 8,
+ kModeFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DaUpdateReserveSpaceFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_IBlocks kIBlocks{};
+ void set_i_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UsedBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_UsedBlocks kUsedBlocks{};
+ void set_used_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UsedBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedDataBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedDataBlocks kReservedDataBlocks{};
+ void set_reserved_data_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedDataBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedMetaBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedMetaBlocks kReservedMetaBlocks{};
+ void set_reserved_meta_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedMetaBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllocatedMetaBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_AllocatedMetaBlocks kAllocatedMetaBlocks{};
+ void set_allocated_meta_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllocatedMetaBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_QuotaClaim =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_QuotaClaim kQuotaClaim{};
+ void set_quota_claim(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_QuotaClaim::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaUpdateReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DaReserveSpaceFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DaReserveSpaceFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DaReserveSpaceFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DaReserveSpaceFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_i_blocks() const { return at<3>().valid(); }
+ uint64_t i_blocks() const { return at<3>().as_uint64(); }
+ bool has_reserved_data_blocks() const { return at<4>().valid(); }
+ int32_t reserved_data_blocks() const { return at<4>().as_int32(); }
+ bool has_reserved_meta_blocks() const { return at<5>().valid(); }
+ int32_t reserved_meta_blocks() const { return at<5>().as_int32(); }
+ bool has_mode() const { return at<6>().valid(); }
+ uint32_t mode() const { return at<6>().as_uint32(); }
+ bool has_md_needed() const { return at<7>().valid(); }
+ int32_t md_needed() const { return at<7>().as_int32(); }
+};
+
+class Ext4DaReserveSpaceFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DaReserveSpaceFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIBlocksFieldNumber = 3,
+ kReservedDataBlocksFieldNumber = 4,
+ kReservedMetaBlocksFieldNumber = 5,
+ kModeFieldNumber = 6,
+ kMdNeededFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DaReserveSpaceFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_IBlocks kIBlocks{};
+ void set_i_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedDataBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedDataBlocks kReservedDataBlocks{};
+ void set_reserved_data_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedDataBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedMetaBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedMetaBlocks kReservedMetaBlocks{};
+ void set_reserved_meta_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedMetaBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MdNeeded =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaReserveSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_MdNeeded kMdNeeded{};
+ void set_md_needed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MdNeeded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DaReleaseSpaceFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DaReleaseSpaceFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DaReleaseSpaceFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DaReleaseSpaceFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_i_blocks() const { return at<3>().valid(); }
+ uint64_t i_blocks() const { return at<3>().as_uint64(); }
+ bool has_freed_blocks() const { return at<4>().valid(); }
+ int32_t freed_blocks() const { return at<4>().as_int32(); }
+ bool has_reserved_data_blocks() const { return at<5>().valid(); }
+ int32_t reserved_data_blocks() const { return at<5>().as_int32(); }
+ bool has_reserved_meta_blocks() const { return at<6>().valid(); }
+ int32_t reserved_meta_blocks() const { return at<6>().as_int32(); }
+ bool has_allocated_meta_blocks() const { return at<7>().valid(); }
+ int32_t allocated_meta_blocks() const { return at<7>().as_int32(); }
+ bool has_mode() const { return at<8>().valid(); }
+ uint32_t mode() const { return at<8>().as_uint32(); }
+};
+
+class Ext4DaReleaseSpaceFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DaReleaseSpaceFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIBlocksFieldNumber = 3,
+ kFreedBlocksFieldNumber = 4,
+ kReservedDataBlocksFieldNumber = 5,
+ kReservedMetaBlocksFieldNumber = 6,
+ kAllocatedMetaBlocksFieldNumber = 7,
+ kModeFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DaReleaseSpaceFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_IBlocks kIBlocks{};
+ void set_i_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreedBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_FreedBlocks kFreedBlocks{};
+ void set_freed_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreedBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedDataBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedDataBlocks kReservedDataBlocks{};
+ void set_reserved_data_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedDataBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedMetaBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedMetaBlocks kReservedMetaBlocks{};
+ void set_reserved_meta_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedMetaBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllocatedMetaBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_AllocatedMetaBlocks kAllocatedMetaBlocks{};
+ void set_allocated_meta_blocks(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllocatedMetaBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaReleaseSpaceFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4CollapseRangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4CollapseRangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4CollapseRangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4CollapseRangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_offset() const { return at<3>().valid(); }
+ int64_t offset() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ int64_t len() const { return at<4>().as_int64(); }
+};
+
+class Ext4CollapseRangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4CollapseRangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kOffsetFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4CollapseRangeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4CollapseRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4CollapseRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4CollapseRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4CollapseRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4BeginOrderedTruncateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4BeginOrderedTruncateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4BeginOrderedTruncateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4BeginOrderedTruncateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_new_size() const { return at<3>().valid(); }
+ int64_t new_size() const { return at<3>().as_int64(); }
+};
+
+class Ext4BeginOrderedTruncateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4BeginOrderedTruncateFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNewSizeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4BeginOrderedTruncateFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4BeginOrderedTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4BeginOrderedTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4BeginOrderedTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_NewSize kNewSize{};
+ void set_new_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4AllocateInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4AllocateInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4AllocateInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4AllocateInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_dir() const { return at<3>().valid(); }
+ uint64_t dir() const { return at<3>().as_uint64(); }
+ bool has_mode() const { return at<4>().valid(); }
+ uint32_t mode() const { return at<4>().as_uint32(); }
+};
+
+class Ext4AllocateInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4AllocateInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kDirFieldNumber = 3,
+ kModeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4AllocateInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dir =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dir kDir{};
+ void set_dir(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dir::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocateInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4AllocateBlocksFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4AllocateBlocksFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4AllocateBlocksFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4AllocateBlocksFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_block() const { return at<3>().valid(); }
+ uint64_t block() const { return at<3>().as_uint64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_logical() const { return at<5>().valid(); }
+ uint32_t logical() const { return at<5>().as_uint32(); }
+ bool has_lleft() const { return at<6>().valid(); }
+ uint32_t lleft() const { return at<6>().as_uint32(); }
+ bool has_lright() const { return at<7>().valid(); }
+ uint32_t lright() const { return at<7>().as_uint32(); }
+ bool has_goal() const { return at<8>().valid(); }
+ uint64_t goal() const { return at<8>().as_uint64(); }
+ bool has_pleft() const { return at<9>().valid(); }
+ uint64_t pleft() const { return at<9>().as_uint64(); }
+ bool has_pright() const { return at<10>().valid(); }
+ uint64_t pright() const { return at<10>().as_uint64(); }
+ bool has_flags() const { return at<11>().valid(); }
+ uint32_t flags() const { return at<11>().as_uint32(); }
+};
+
+class Ext4AllocateBlocksFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4AllocateBlocksFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kBlockFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kLogicalFieldNumber = 5,
+ kLleftFieldNumber = 6,
+ kLrightFieldNumber = 7,
+ kGoalFieldNumber = 8,
+ kPleftFieldNumber = 9,
+ kPrightFieldNumber = 10,
+ kFlagsFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4AllocateBlocksFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Block =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Block kBlock{};
+ void set_block(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Block::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Logical =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Logical kLogical{};
+ void set_logical(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Logical::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lleft =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Lleft kLleft{};
+ void set_lleft(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lleft::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lright =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Lright kLright{};
+ void set_lright(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lright::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Goal =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Goal kGoal{};
+ void set_goal(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Goal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pleft =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Pleft kPleft{};
+ void set_pleft(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pleft::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pright =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Pright kPright{};
+ void set_pright(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pright::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocateBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4AllocDaBlocksFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4AllocDaBlocksFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4AllocDaBlocksFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4AllocDaBlocksFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_data_blocks() const { return at<3>().valid(); }
+ uint32_t data_blocks() const { return at<3>().as_uint32(); }
+ bool has_meta_blocks() const { return at<4>().valid(); }
+ uint32_t meta_blocks() const { return at<4>().as_uint32(); }
+};
+
+class Ext4AllocDaBlocksFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4AllocDaBlocksFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kDataBlocksFieldNumber = 3,
+ kMetaBlocksFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4AllocDaBlocksFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocDaBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4AllocDaBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocDaBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_DataBlocks kDataBlocks{};
+ void set_data_blocks(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MetaBlocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4AllocDaBlocksFtraceEvent>;
+
+ static constexpr FieldMetadata_MetaBlocks kMetaBlocks{};
+ void set_meta_blocks(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MetaBlocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4SyncFileExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4SyncFileExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4SyncFileExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4SyncFileExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class Ext4SyncFileExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4SyncFileExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4SyncFileExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4SyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4SyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4SyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4SyncFileEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4SyncFileEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4SyncFileEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4SyncFileEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_parent() const { return at<3>().valid(); }
+ uint64_t parent() const { return at<3>().as_uint64(); }
+ bool has_datasync() const { return at<4>().valid(); }
+ int32_t datasync() const { return at<4>().as_int32(); }
+};
+
+class Ext4SyncFileEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4SyncFileEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kParentFieldNumber = 3,
+ kDatasyncFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4SyncFileEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4SyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4SyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Parent =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4SyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Parent kParent{};
+ void set_parent(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Parent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Datasync =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Ext4SyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Datasync kDatasync{};
+ void set_datasync(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Datasync::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DaWriteEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DaWriteEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DaWriteEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DaWriteEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_copied() const { return at<5>().valid(); }
+ uint32_t copied() const { return at<5>().as_uint32(); }
+};
+
+class Ext4DaWriteEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DaWriteEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kCopiedFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DaWriteEndFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4DaWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Copied =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Copied kCopied{};
+ void set_copied(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Copied::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Ext4DaWriteBeginFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Ext4DaWriteBeginFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Ext4DaWriteBeginFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Ext4DaWriteBeginFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+};
+
+class Ext4DaWriteBeginFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Ext4DaWriteBeginFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Ext4DaWriteBeginFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Ext4DaWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Ext4DaWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Ext4DaWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/f2fs.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_F2FS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_F2FS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class F2fsGcEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsGcEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsGcEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsGcEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ret() const { return at<2>().valid(); }
+ int32_t ret() const { return at<2>().as_int32(); }
+ bool has_seg_freed() const { return at<3>().valid(); }
+ int32_t seg_freed() const { return at<3>().as_int32(); }
+ bool has_sec_freed() const { return at<4>().valid(); }
+ int32_t sec_freed() const { return at<4>().as_int32(); }
+ bool has_dirty_nodes() const { return at<5>().valid(); }
+ int64_t dirty_nodes() const { return at<5>().as_int64(); }
+ bool has_dirty_dents() const { return at<6>().valid(); }
+ int64_t dirty_dents() const { return at<6>().as_int64(); }
+ bool has_dirty_imeta() const { return at<7>().valid(); }
+ int64_t dirty_imeta() const { return at<7>().as_int64(); }
+ bool has_free_sec() const { return at<8>().valid(); }
+ uint32_t free_sec() const { return at<8>().as_uint32(); }
+ bool has_free_seg() const { return at<9>().valid(); }
+ uint32_t free_seg() const { return at<9>().as_uint32(); }
+ bool has_reserved_seg() const { return at<10>().valid(); }
+ int32_t reserved_seg() const { return at<10>().as_int32(); }
+ bool has_prefree_seg() const { return at<11>().valid(); }
+ uint32_t prefree_seg() const { return at<11>().as_uint32(); }
+};
+
+class F2fsGcEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsGcEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kRetFieldNumber = 2,
+ kSegFreedFieldNumber = 3,
+ kSecFreedFieldNumber = 4,
+ kDirtyNodesFieldNumber = 5,
+ kDirtyDentsFieldNumber = 6,
+ kDirtyImetaFieldNumber = 7,
+ kFreeSecFieldNumber = 8,
+ kFreeSegFieldNumber = 9,
+ kReservedSegFieldNumber = 10,
+ kPrefreeSegFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsGcEndFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SegFreed =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_SegFreed kSegFreed{};
+ void set_seg_freed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SegFreed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SecFreed =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_SecFreed kSecFreed{};
+ void set_sec_freed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SecFreed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DirtyNodes =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_DirtyNodes kDirtyNodes{};
+ void set_dirty_nodes(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirtyNodes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DirtyDents =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_DirtyDents kDirtyDents{};
+ void set_dirty_dents(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirtyDents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DirtyImeta =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_DirtyImeta kDirtyImeta{};
+ void set_dirty_imeta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirtyImeta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreeSec =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_FreeSec kFreeSec{};
+ void set_free_sec(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreeSec::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreeSeg =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_FreeSeg kFreeSeg{};
+ void set_free_seg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreeSeg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedSeg =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedSeg kReservedSeg{};
+ void set_reserved_seg(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedSeg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrefreeSeg =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcEndFtraceEvent>;
+
+ static constexpr FieldMetadata_PrefreeSeg kPrefreeSeg{};
+ void set_prefree_seg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrefreeSeg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsGcBeginFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/13, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsGcBeginFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsGcBeginFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsGcBeginFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_sync() const { return at<2>().valid(); }
+ uint32_t sync() const { return at<2>().as_uint32(); }
+ bool has_background() const { return at<3>().valid(); }
+ uint32_t background() const { return at<3>().as_uint32(); }
+ bool has_dirty_nodes() const { return at<4>().valid(); }
+ int64_t dirty_nodes() const { return at<4>().as_int64(); }
+ bool has_dirty_dents() const { return at<5>().valid(); }
+ int64_t dirty_dents() const { return at<5>().as_int64(); }
+ bool has_dirty_imeta() const { return at<6>().valid(); }
+ int64_t dirty_imeta() const { return at<6>().as_int64(); }
+ bool has_free_sec() const { return at<7>().valid(); }
+ uint32_t free_sec() const { return at<7>().as_uint32(); }
+ bool has_free_seg() const { return at<8>().valid(); }
+ uint32_t free_seg() const { return at<8>().as_uint32(); }
+ bool has_reserved_seg() const { return at<9>().valid(); }
+ int32_t reserved_seg() const { return at<9>().as_int32(); }
+ bool has_prefree_seg() const { return at<10>().valid(); }
+ uint32_t prefree_seg() const { return at<10>().as_uint32(); }
+ bool has_gc_type() const { return at<11>().valid(); }
+ int32_t gc_type() const { return at<11>().as_int32(); }
+ bool has_no_bg_gc() const { return at<12>().valid(); }
+ uint32_t no_bg_gc() const { return at<12>().as_uint32(); }
+ bool has_nr_free_secs() const { return at<13>().valid(); }
+ uint32_t nr_free_secs() const { return at<13>().as_uint32(); }
+};
+
+class F2fsGcBeginFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsGcBeginFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kSyncFieldNumber = 2,
+ kBackgroundFieldNumber = 3,
+ kDirtyNodesFieldNumber = 4,
+ kDirtyDentsFieldNumber = 5,
+ kDirtyImetaFieldNumber = 6,
+ kFreeSecFieldNumber = 7,
+ kFreeSegFieldNumber = 8,
+ kReservedSegFieldNumber = 9,
+ kPrefreeSegFieldNumber = 10,
+ kGcTypeFieldNumber = 11,
+ kNoBgGcFieldNumber = 12,
+ kNrFreeSecsFieldNumber = 13,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsGcBeginFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sync =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Sync kSync{};
+ void set_sync(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sync::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Background =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Background kBackground{};
+ void set_background(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Background::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DirtyNodes =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_DirtyNodes kDirtyNodes{};
+ void set_dirty_nodes(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirtyNodes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DirtyDents =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_DirtyDents kDirtyDents{};
+ void set_dirty_dents(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirtyDents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DirtyImeta =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_DirtyImeta kDirtyImeta{};
+ void set_dirty_imeta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirtyImeta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreeSec =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_FreeSec kFreeSec{};
+ void set_free_sec(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreeSec::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreeSeg =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_FreeSeg kFreeSeg{};
+ void set_free_seg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreeSeg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReservedSeg =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_ReservedSeg kReservedSeg{};
+ void set_reserved_seg(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReservedSeg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrefreeSeg =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_PrefreeSeg kPrefreeSeg{};
+ void set_prefree_seg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrefreeSeg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GcType =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_GcType kGcType{};
+ void set_gc_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GcType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NoBgGc =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_NoBgGc kNoBgGc{};
+ void set_no_bg_gc(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NoBgGc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrFreeSecs =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGcBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_NrFreeSecs kNrFreeSecs{};
+ void set_nr_free_secs(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrFreeSecs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsBackgroundGcFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsBackgroundGcFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsBackgroundGcFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsBackgroundGcFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_wait_ms() const { return at<2>().valid(); }
+ uint32_t wait_ms() const { return at<2>().as_uint32(); }
+ bool has_prefree() const { return at<3>().valid(); }
+ uint32_t prefree() const { return at<3>().as_uint32(); }
+ bool has_free() const { return at<4>().valid(); }
+ uint32_t free() const { return at<4>().as_uint32(); }
+};
+
+class F2fsBackgroundGcFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsBackgroundGcFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kWaitMsFieldNumber = 2,
+ kPrefreeFieldNumber = 3,
+ kFreeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsBackgroundGcFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsBackgroundGcFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WaitMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsBackgroundGcFtraceEvent>;
+
+ static constexpr FieldMetadata_WaitMs kWaitMs{};
+ void set_wait_ms(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WaitMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prefree =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsBackgroundGcFtraceEvent>;
+
+ static constexpr FieldMetadata_Prefree kPrefree{};
+ void set_prefree(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prefree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Free =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsBackgroundGcFtraceEvent>;
+
+ static constexpr FieldMetadata_Free kFree{};
+ void set_free(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Free::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsIostatLatencyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/28, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsIostatLatencyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsIostatLatencyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsIostatLatencyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_d_rd_avg() const { return at<1>().valid(); }
+ uint32_t d_rd_avg() const { return at<1>().as_uint32(); }
+ bool has_d_rd_cnt() const { return at<2>().valid(); }
+ uint32_t d_rd_cnt() const { return at<2>().as_uint32(); }
+ bool has_d_rd_peak() const { return at<3>().valid(); }
+ uint32_t d_rd_peak() const { return at<3>().as_uint32(); }
+ bool has_d_wr_as_avg() const { return at<4>().valid(); }
+ uint32_t d_wr_as_avg() const { return at<4>().as_uint32(); }
+ bool has_d_wr_as_cnt() const { return at<5>().valid(); }
+ uint32_t d_wr_as_cnt() const { return at<5>().as_uint32(); }
+ bool has_d_wr_as_peak() const { return at<6>().valid(); }
+ uint32_t d_wr_as_peak() const { return at<6>().as_uint32(); }
+ bool has_d_wr_s_avg() const { return at<7>().valid(); }
+ uint32_t d_wr_s_avg() const { return at<7>().as_uint32(); }
+ bool has_d_wr_s_cnt() const { return at<8>().valid(); }
+ uint32_t d_wr_s_cnt() const { return at<8>().as_uint32(); }
+ bool has_d_wr_s_peak() const { return at<9>().valid(); }
+ uint32_t d_wr_s_peak() const { return at<9>().as_uint32(); }
+ bool has_dev() const { return at<10>().valid(); }
+ uint64_t dev() const { return at<10>().as_uint64(); }
+ bool has_m_rd_avg() const { return at<11>().valid(); }
+ uint32_t m_rd_avg() const { return at<11>().as_uint32(); }
+ bool has_m_rd_cnt() const { return at<12>().valid(); }
+ uint32_t m_rd_cnt() const { return at<12>().as_uint32(); }
+ bool has_m_rd_peak() const { return at<13>().valid(); }
+ uint32_t m_rd_peak() const { return at<13>().as_uint32(); }
+ bool has_m_wr_as_avg() const { return at<14>().valid(); }
+ uint32_t m_wr_as_avg() const { return at<14>().as_uint32(); }
+ bool has_m_wr_as_cnt() const { return at<15>().valid(); }
+ uint32_t m_wr_as_cnt() const { return at<15>().as_uint32(); }
+ bool has_m_wr_as_peak() const { return at<16>().valid(); }
+ uint32_t m_wr_as_peak() const { return at<16>().as_uint32(); }
+ bool has_m_wr_s_avg() const { return at<17>().valid(); }
+ uint32_t m_wr_s_avg() const { return at<17>().as_uint32(); }
+ bool has_m_wr_s_cnt() const { return at<18>().valid(); }
+ uint32_t m_wr_s_cnt() const { return at<18>().as_uint32(); }
+ bool has_m_wr_s_peak() const { return at<19>().valid(); }
+ uint32_t m_wr_s_peak() const { return at<19>().as_uint32(); }
+ bool has_n_rd_avg() const { return at<20>().valid(); }
+ uint32_t n_rd_avg() const { return at<20>().as_uint32(); }
+ bool has_n_rd_cnt() const { return at<21>().valid(); }
+ uint32_t n_rd_cnt() const { return at<21>().as_uint32(); }
+ bool has_n_rd_peak() const { return at<22>().valid(); }
+ uint32_t n_rd_peak() const { return at<22>().as_uint32(); }
+ bool has_n_wr_as_avg() const { return at<23>().valid(); }
+ uint32_t n_wr_as_avg() const { return at<23>().as_uint32(); }
+ bool has_n_wr_as_cnt() const { return at<24>().valid(); }
+ uint32_t n_wr_as_cnt() const { return at<24>().as_uint32(); }
+ bool has_n_wr_as_peak() const { return at<25>().valid(); }
+ uint32_t n_wr_as_peak() const { return at<25>().as_uint32(); }
+ bool has_n_wr_s_avg() const { return at<26>().valid(); }
+ uint32_t n_wr_s_avg() const { return at<26>().as_uint32(); }
+ bool has_n_wr_s_cnt() const { return at<27>().valid(); }
+ uint32_t n_wr_s_cnt() const { return at<27>().as_uint32(); }
+ bool has_n_wr_s_peak() const { return at<28>().valid(); }
+ uint32_t n_wr_s_peak() const { return at<28>().as_uint32(); }
+};
+
+class F2fsIostatLatencyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsIostatLatencyFtraceEvent_Decoder;
+ enum : int32_t {
+ kDRdAvgFieldNumber = 1,
+ kDRdCntFieldNumber = 2,
+ kDRdPeakFieldNumber = 3,
+ kDWrAsAvgFieldNumber = 4,
+ kDWrAsCntFieldNumber = 5,
+ kDWrAsPeakFieldNumber = 6,
+ kDWrSAvgFieldNumber = 7,
+ kDWrSCntFieldNumber = 8,
+ kDWrSPeakFieldNumber = 9,
+ kDevFieldNumber = 10,
+ kMRdAvgFieldNumber = 11,
+ kMRdCntFieldNumber = 12,
+ kMRdPeakFieldNumber = 13,
+ kMWrAsAvgFieldNumber = 14,
+ kMWrAsCntFieldNumber = 15,
+ kMWrAsPeakFieldNumber = 16,
+ kMWrSAvgFieldNumber = 17,
+ kMWrSCntFieldNumber = 18,
+ kMWrSPeakFieldNumber = 19,
+ kNRdAvgFieldNumber = 20,
+ kNRdCntFieldNumber = 21,
+ kNRdPeakFieldNumber = 22,
+ kNWrAsAvgFieldNumber = 23,
+ kNWrAsCntFieldNumber = 24,
+ kNWrAsPeakFieldNumber = 25,
+ kNWrSAvgFieldNumber = 26,
+ kNWrSCntFieldNumber = 27,
+ kNWrSPeakFieldNumber = 28,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsIostatLatencyFtraceEvent"; }
+
+
+ using FieldMetadata_DRdAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DRdAvg kDRdAvg{};
+ void set_d_rd_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DRdAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DRdCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DRdCnt kDRdCnt{};
+ void set_d_rd_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DRdCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DRdPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DRdPeak kDRdPeak{};
+ void set_d_rd_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DRdPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DWrAsAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DWrAsAvg kDWrAsAvg{};
+ void set_d_wr_as_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DWrAsAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DWrAsCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DWrAsCnt kDWrAsCnt{};
+ void set_d_wr_as_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DWrAsCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DWrAsPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DWrAsPeak kDWrAsPeak{};
+ void set_d_wr_as_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DWrAsPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DWrSAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DWrSAvg kDWrSAvg{};
+ void set_d_wr_s_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DWrSAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DWrSCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DWrSCnt kDWrSCnt{};
+ void set_d_wr_s_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DWrSCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DWrSPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_DWrSPeak kDWrSPeak{};
+ void set_d_wr_s_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DWrSPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MRdAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MRdAvg kMRdAvg{};
+ void set_m_rd_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MRdAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MRdCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MRdCnt kMRdCnt{};
+ void set_m_rd_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MRdCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MRdPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MRdPeak kMRdPeak{};
+ void set_m_rd_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MRdPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MWrAsAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MWrAsAvg kMWrAsAvg{};
+ void set_m_wr_as_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MWrAsAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MWrAsCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MWrAsCnt kMWrAsCnt{};
+ void set_m_wr_as_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MWrAsCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MWrAsPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MWrAsPeak kMWrAsPeak{};
+ void set_m_wr_as_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MWrAsPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MWrSAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MWrSAvg kMWrSAvg{};
+ void set_m_wr_s_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MWrSAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MWrSCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MWrSCnt kMWrSCnt{};
+ void set_m_wr_s_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MWrSCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MWrSPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_MWrSPeak kMWrSPeak{};
+ void set_m_wr_s_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MWrSPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NRdAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NRdAvg kNRdAvg{};
+ void set_n_rd_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NRdAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NRdCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NRdCnt kNRdCnt{};
+ void set_n_rd_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NRdCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NRdPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NRdPeak kNRdPeak{};
+ void set_n_rd_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NRdPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NWrAsAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NWrAsAvg kNWrAsAvg{};
+ void set_n_wr_as_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NWrAsAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NWrAsCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NWrAsCnt kNWrAsCnt{};
+ void set_n_wr_as_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NWrAsCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NWrAsPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NWrAsPeak kNWrAsPeak{};
+ void set_n_wr_as_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NWrAsPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NWrSAvg =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NWrSAvg kNWrSAvg{};
+ void set_n_wr_s_avg(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NWrSAvg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NWrSCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NWrSCnt kNWrSCnt{};
+ void set_n_wr_s_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NWrSCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NWrSPeak =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIostatLatencyFtraceEvent>;
+
+ static constexpr FieldMetadata_NWrSPeak kNWrSPeak{};
+ void set_n_wr_s_peak(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NWrSPeak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsIostatFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/23, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsIostatFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsIostatFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsIostatFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_app_bio() const { return at<1>().valid(); }
+ uint64_t app_bio() const { return at<1>().as_uint64(); }
+ bool has_app_brio() const { return at<2>().valid(); }
+ uint64_t app_brio() const { return at<2>().as_uint64(); }
+ bool has_app_dio() const { return at<3>().valid(); }
+ uint64_t app_dio() const { return at<3>().as_uint64(); }
+ bool has_app_drio() const { return at<4>().valid(); }
+ uint64_t app_drio() const { return at<4>().as_uint64(); }
+ bool has_app_mio() const { return at<5>().valid(); }
+ uint64_t app_mio() const { return at<5>().as_uint64(); }
+ bool has_app_mrio() const { return at<6>().valid(); }
+ uint64_t app_mrio() const { return at<6>().as_uint64(); }
+ bool has_app_rio() const { return at<7>().valid(); }
+ uint64_t app_rio() const { return at<7>().as_uint64(); }
+ bool has_app_wio() const { return at<8>().valid(); }
+ uint64_t app_wio() const { return at<8>().as_uint64(); }
+ bool has_dev() const { return at<9>().valid(); }
+ uint64_t dev() const { return at<9>().as_uint64(); }
+ bool has_fs_cdrio() const { return at<10>().valid(); }
+ uint64_t fs_cdrio() const { return at<10>().as_uint64(); }
+ bool has_fs_cp_dio() const { return at<11>().valid(); }
+ uint64_t fs_cp_dio() const { return at<11>().as_uint64(); }
+ bool has_fs_cp_mio() const { return at<12>().valid(); }
+ uint64_t fs_cp_mio() const { return at<12>().as_uint64(); }
+ bool has_fs_cp_nio() const { return at<13>().valid(); }
+ uint64_t fs_cp_nio() const { return at<13>().as_uint64(); }
+ bool has_fs_dio() const { return at<14>().valid(); }
+ uint64_t fs_dio() const { return at<14>().as_uint64(); }
+ bool has_fs_discard() const { return at<15>().valid(); }
+ uint64_t fs_discard() const { return at<15>().as_uint64(); }
+ bool has_fs_drio() const { return at<16>().valid(); }
+ uint64_t fs_drio() const { return at<16>().as_uint64(); }
+ bool has_fs_gc_dio() const { return at<17>().valid(); }
+ uint64_t fs_gc_dio() const { return at<17>().as_uint64(); }
+ bool has_fs_gc_nio() const { return at<18>().valid(); }
+ uint64_t fs_gc_nio() const { return at<18>().as_uint64(); }
+ bool has_fs_gdrio() const { return at<19>().valid(); }
+ uint64_t fs_gdrio() const { return at<19>().as_uint64(); }
+ bool has_fs_mio() const { return at<20>().valid(); }
+ uint64_t fs_mio() const { return at<20>().as_uint64(); }
+ bool has_fs_mrio() const { return at<21>().valid(); }
+ uint64_t fs_mrio() const { return at<21>().as_uint64(); }
+ bool has_fs_nio() const { return at<22>().valid(); }
+ uint64_t fs_nio() const { return at<22>().as_uint64(); }
+ bool has_fs_nrio() const { return at<23>().valid(); }
+ uint64_t fs_nrio() const { return at<23>().as_uint64(); }
+};
+
+class F2fsIostatFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsIostatFtraceEvent_Decoder;
+ enum : int32_t {
+ kAppBioFieldNumber = 1,
+ kAppBrioFieldNumber = 2,
+ kAppDioFieldNumber = 3,
+ kAppDrioFieldNumber = 4,
+ kAppMioFieldNumber = 5,
+ kAppMrioFieldNumber = 6,
+ kAppRioFieldNumber = 7,
+ kAppWioFieldNumber = 8,
+ kDevFieldNumber = 9,
+ kFsCdrioFieldNumber = 10,
+ kFsCpDioFieldNumber = 11,
+ kFsCpMioFieldNumber = 12,
+ kFsCpNioFieldNumber = 13,
+ kFsDioFieldNumber = 14,
+ kFsDiscardFieldNumber = 15,
+ kFsDrioFieldNumber = 16,
+ kFsGcDioFieldNumber = 17,
+ kFsGcNioFieldNumber = 18,
+ kFsGdrioFieldNumber = 19,
+ kFsMioFieldNumber = 20,
+ kFsMrioFieldNumber = 21,
+ kFsNioFieldNumber = 22,
+ kFsNrioFieldNumber = 23,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsIostatFtraceEvent"; }
+
+
+ using FieldMetadata_AppBio =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppBio kAppBio{};
+ void set_app_bio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppBio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppBrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppBrio kAppBrio{};
+ void set_app_brio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppBrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppDio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppDio kAppDio{};
+ void set_app_dio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppDio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppDrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppDrio kAppDrio{};
+ void set_app_drio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppDrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppMio =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppMio kAppMio{};
+ void set_app_mio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppMio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppMrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppMrio kAppMrio{};
+ void set_app_mrio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppMrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppRio =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppRio kAppRio{};
+ void set_app_rio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppRio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AppWio =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_AppWio kAppWio{};
+ void set_app_wio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AppWio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsCdrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsCdrio kFsCdrio{};
+ void set_fs_cdrio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsCdrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsCpDio =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsCpDio kFsCpDio{};
+ void set_fs_cp_dio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsCpDio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsCpMio =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsCpMio kFsCpMio{};
+ void set_fs_cp_mio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsCpMio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsCpNio =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsCpNio kFsCpNio{};
+ void set_fs_cp_nio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsCpNio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsDio =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsDio kFsDio{};
+ void set_fs_dio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsDio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsDiscard =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsDiscard kFsDiscard{};
+ void set_fs_discard(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsDiscard::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsDrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsDrio kFsDrio{};
+ void set_fs_drio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsDrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsGcDio =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsGcDio kFsGcDio{};
+ void set_fs_gc_dio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsGcDio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsGcNio =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsGcNio kFsGcNio{};
+ void set_fs_gc_nio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsGcNio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsGdrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsGdrio kFsGdrio{};
+ void set_fs_gdrio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsGdrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsMio =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsMio kFsMio{};
+ void set_fs_mio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsMio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsMrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsMrio kFsMrio{};
+ void set_fs_mrio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsMrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsNio =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsNio kFsNio{};
+ void set_fs_nio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsNio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FsNrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIostatFtraceEvent>;
+
+ static constexpr FieldMetadata_FsNrio kFsNrio{};
+ void set_fs_nrio(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FsNrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsWriteEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsWriteEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsWriteEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsWriteEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_copied() const { return at<5>().valid(); }
+ uint32_t copied() const { return at<5>().as_uint32(); }
+};
+
+class F2fsWriteEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsWriteEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kCopiedFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsWriteEndFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Copied =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsWriteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Copied kCopied{};
+ void set_copied(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Copied::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsWriteCheckpointFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsWriteCheckpointFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsWriteCheckpointFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsWriteCheckpointFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_is_umount() const { return at<2>().valid(); }
+ uint32_t is_umount() const { return at<2>().as_uint32(); }
+ bool has_msg() const { return at<3>().valid(); }
+ ::protozero::ConstChars msg() const { return at<3>().as_string(); }
+ bool has_reason() const { return at<4>().valid(); }
+ int32_t reason() const { return at<4>().as_int32(); }
+};
+
+class F2fsWriteCheckpointFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsWriteCheckpointFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kIsUmountFieldNumber = 2,
+ kMsgFieldNumber = 3,
+ kReasonFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsWriteCheckpointFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsWriteCheckpointFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsUmount =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsWriteCheckpointFtraceEvent>;
+
+ static constexpr FieldMetadata_IsUmount kIsUmount{};
+ void set_is_umount(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsUmount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Msg =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ F2fsWriteCheckpointFtraceEvent>;
+
+ static constexpr FieldMetadata_Msg kMsg{};
+ void set_msg(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Msg::kFieldId, data, size);
+ }
+ void set_msg(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Msg::kFieldId, chars.data, chars.size);
+ }
+ void set_msg(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Msg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Reason =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsWriteCheckpointFtraceEvent>;
+
+ static constexpr FieldMetadata_Reason kReason{};
+ void set_reason(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsWriteBeginFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsWriteBeginFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsWriteBeginFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsWriteBeginFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pos() const { return at<3>().valid(); }
+ int64_t pos() const { return at<3>().as_int64(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint32_t len() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+};
+
+class F2fsWriteBeginFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsWriteBeginFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPosFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsWriteBeginFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pos =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Pos kPos{};
+ void set_pos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsWriteBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsVmPageMkwriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsVmPageMkwriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsVmPageMkwriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsVmPageMkwriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_type() const { return at<3>().valid(); }
+ int32_t type() const { return at<3>().as_int32(); }
+ bool has_dir() const { return at<4>().valid(); }
+ int32_t dir() const { return at<4>().as_int32(); }
+ bool has_index() const { return at<5>().valid(); }
+ uint64_t index() const { return at<5>().as_uint64(); }
+ bool has_dirty() const { return at<6>().valid(); }
+ int32_t dirty() const { return at<6>().as_int32(); }
+ bool has_uptodate() const { return at<7>().valid(); }
+ int32_t uptodate() const { return at<7>().as_int32(); }
+};
+
+class F2fsVmPageMkwriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsVmPageMkwriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kDirFieldNumber = 4,
+ kIndexFieldNumber = 5,
+ kDirtyFieldNumber = 6,
+ kUptodateFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsVmPageMkwriteFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsVmPageMkwriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsVmPageMkwriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsVmPageMkwriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dir =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsVmPageMkwriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Dir kDir{};
+ void set_dir(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dir::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsVmPageMkwriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dirty =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsVmPageMkwriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Dirty kDirty{};
+ void set_dirty(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dirty::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uptodate =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsVmPageMkwriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Uptodate kUptodate{};
+ void set_uptodate(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uptodate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsUnlinkExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsUnlinkExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsUnlinkExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsUnlinkExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class F2fsUnlinkExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsUnlinkExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsUnlinkExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsUnlinkExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsUnlinkExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsUnlinkExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsUnlinkEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsUnlinkEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsUnlinkEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsUnlinkEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_size() const { return at<3>().valid(); }
+ int64_t size() const { return at<3>().as_int64(); }
+ bool has_blocks() const { return at<4>().valid(); }
+ uint64_t blocks() const { return at<4>().as_uint64(); }
+ bool has_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars name() const { return at<5>().as_string(); }
+};
+
+class F2fsUnlinkEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsUnlinkEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kSizeFieldNumber = 3,
+ kBlocksFieldNumber = 4,
+ kNameFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsUnlinkEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsUnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsUnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsUnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsUnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ F2fsUnlinkEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncatePartialNodesFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncatePartialNodesFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncatePartialNodesFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncatePartialNodesFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_nid() const { return at<3>().valid(); }
+ uint32_t nid() const { return at<3>().as_uint32(); }
+ bool has_depth() const { return at<4>().valid(); }
+ int32_t depth() const { return at<4>().as_int32(); }
+ bool has_err() const { return at<5>().valid(); }
+ int32_t err() const { return at<5>().as_int32(); }
+};
+
+class F2fsTruncatePartialNodesFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncatePartialNodesFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNidFieldNumber = 3,
+ kDepthFieldNumber = 4,
+ kErrFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncatePartialNodesFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncatePartialNodesFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncatePartialNodesFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncatePartialNodesFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Depth =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsTruncatePartialNodesFtraceEvent>;
+
+ static constexpr FieldMetadata_Depth kDepth{};
+ void set_depth(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Depth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Err =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsTruncatePartialNodesFtraceEvent>;
+
+ static constexpr FieldMetadata_Err kErr{};
+ void set_err(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Err::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateNodesExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateNodesExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateNodesExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateNodesExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class F2fsTruncateNodesExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateNodesExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateNodesExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateNodesExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateNodesExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsTruncateNodesExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateNodesEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateNodesEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateNodesEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateNodesEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_nid() const { return at<3>().valid(); }
+ uint32_t nid() const { return at<3>().as_uint32(); }
+ bool has_blk_addr() const { return at<4>().valid(); }
+ uint32_t blk_addr() const { return at<4>().as_uint32(); }
+};
+
+class F2fsTruncateNodesEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateNodesEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNidFieldNumber = 3,
+ kBlkAddrFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateNodesEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateNodesEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateNodesEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateNodesEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BlkAddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateNodesEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_BlkAddr kBlkAddr{};
+ void set_blk_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlkAddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateNodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateNodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateNodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateNodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_nid() const { return at<3>().valid(); }
+ uint32_t nid() const { return at<3>().as_uint32(); }
+ bool has_blk_addr() const { return at<4>().valid(); }
+ uint32_t blk_addr() const { return at<4>().as_uint32(); }
+};
+
+class F2fsTruncateNodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateNodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNidFieldNumber = 3,
+ kBlkAddrFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateNodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BlkAddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_BlkAddr kBlkAddr{};
+ void set_blk_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlkAddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateInodeBlocksExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateInodeBlocksExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateInodeBlocksExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateInodeBlocksExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class F2fsTruncateInodeBlocksExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateInodeBlocksExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateInodeBlocksExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateInodeBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateInodeBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsTruncateInodeBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateInodeBlocksEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateInodeBlocksEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateInodeBlocksEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateInodeBlocksEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_size() const { return at<3>().valid(); }
+ int64_t size() const { return at<3>().as_int64(); }
+ bool has_blocks() const { return at<4>().valid(); }
+ uint64_t blocks() const { return at<4>().as_uint64(); }
+ bool has_from() const { return at<5>().valid(); }
+ uint64_t from() const { return at<5>().as_uint64(); }
+};
+
+class F2fsTruncateInodeBlocksEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateInodeBlocksEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kSizeFieldNumber = 3,
+ kBlocksFieldNumber = 4,
+ kFromFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateInodeBlocksEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateInodeBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateInodeBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsTruncateInodeBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateInodeBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_From =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateInodeBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_From kFrom{};
+ void set_from(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_From::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateDataBlocksRangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateDataBlocksRangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateDataBlocksRangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateDataBlocksRangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_nid() const { return at<3>().valid(); }
+ uint32_t nid() const { return at<3>().as_uint32(); }
+ bool has_ofs() const { return at<4>().valid(); }
+ uint32_t ofs() const { return at<4>().as_uint32(); }
+ bool has_free() const { return at<5>().valid(); }
+ int32_t free() const { return at<5>().as_int32(); }
+};
+
+class F2fsTruncateDataBlocksRangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateDataBlocksRangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNidFieldNumber = 3,
+ kOfsFieldNumber = 4,
+ kFreeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateDataBlocksRangeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateDataBlocksRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateDataBlocksRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateDataBlocksRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ofs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateDataBlocksRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ofs kOfs{};
+ void set_ofs(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ofs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Free =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsTruncateDataBlocksRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Free kFree{};
+ void set_free(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Free::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateBlocksExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateBlocksExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateBlocksExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateBlocksExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class F2fsTruncateBlocksExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateBlocksExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateBlocksExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsTruncateBlocksExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateBlocksEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateBlocksEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateBlocksEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateBlocksEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_size() const { return at<3>().valid(); }
+ int64_t size() const { return at<3>().as_int64(); }
+ bool has_blocks() const { return at<4>().valid(); }
+ uint64_t blocks() const { return at<4>().as_uint64(); }
+ bool has_from() const { return at<5>().valid(); }
+ uint64_t from() const { return at<5>().as_uint64(); }
+};
+
+class F2fsTruncateBlocksEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateBlocksEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kSizeFieldNumber = 3,
+ kBlocksFieldNumber = 4,
+ kFromFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateBlocksEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsTruncateBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_From =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateBlocksEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_From kFrom{};
+ void set_from(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_From::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsTruncateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsTruncateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsTruncateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsTruncateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pino() const { return at<3>().valid(); }
+ uint64_t pino() const { return at<3>().as_uint64(); }
+ bool has_mode() const { return at<4>().valid(); }
+ uint32_t mode() const { return at<4>().as_uint32(); }
+ bool has_size() const { return at<5>().valid(); }
+ int64_t size() const { return at<5>().as_int64(); }
+ bool has_nlink() const { return at<6>().valid(); }
+ uint32_t nlink() const { return at<6>().as_uint32(); }
+ bool has_blocks() const { return at<7>().valid(); }
+ uint64_t blocks() const { return at<7>().as_uint64(); }
+ bool has_advise() const { return at<8>().valid(); }
+ uint32_t advise() const { return at<8>().as_uint32(); }
+};
+
+class F2fsTruncateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsTruncateFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPinoFieldNumber = 3,
+ kModeFieldNumber = 4,
+ kSizeFieldNumber = 5,
+ kNlinkFieldNumber = 6,
+ kBlocksFieldNumber = 7,
+ kAdviseFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsTruncateFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pino =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Pino kPino{};
+ void set_pino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nlink =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Nlink kNlink{};
+ void set_nlink(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nlink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Advise =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsTruncateFtraceEvent>;
+
+ static constexpr FieldMetadata_Advise kAdvise{};
+ void set_advise(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Advise::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsSyncFsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsSyncFsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsSyncFsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsSyncFsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_dirty() const { return at<2>().valid(); }
+ int32_t dirty() const { return at<2>().as_int32(); }
+ bool has_wait() const { return at<3>().valid(); }
+ int32_t wait() const { return at<3>().as_int32(); }
+};
+
+class F2fsSyncFsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsSyncFsFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kDirtyFieldNumber = 2,
+ kWaitFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsSyncFsFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSyncFsFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dirty =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSyncFsFtraceEvent>;
+
+ static constexpr FieldMetadata_Dirty kDirty{};
+ void set_dirty(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dirty::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Wait =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSyncFsFtraceEvent>;
+
+ static constexpr FieldMetadata_Wait kWait{};
+ void set_wait(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Wait::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsSyncFileExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsSyncFileExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsSyncFileExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsSyncFileExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_need_cp() const { return at<3>().valid(); }
+ uint32_t need_cp() const { return at<3>().as_uint32(); }
+ bool has_datasync() const { return at<4>().valid(); }
+ int32_t datasync() const { return at<4>().as_int32(); }
+ bool has_ret() const { return at<5>().valid(); }
+ int32_t ret() const { return at<5>().as_int32(); }
+ bool has_cp_reason() const { return at<6>().valid(); }
+ int32_t cp_reason() const { return at<6>().as_int32(); }
+};
+
+class F2fsSyncFileExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsSyncFileExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kNeedCpFieldNumber = 3,
+ kDatasyncFieldNumber = 4,
+ kRetFieldNumber = 5,
+ kCpReasonFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsSyncFileExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NeedCp =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsSyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_NeedCp kNeedCp{};
+ void set_need_cp(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NeedCp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Datasync =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Datasync kDatasync{};
+ void set_datasync(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Datasync::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpReason =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSyncFileExitFtraceEvent>;
+
+ static constexpr FieldMetadata_CpReason kCpReason{};
+ void set_cp_reason(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpReason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsSyncFileEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsSyncFileEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsSyncFileEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsSyncFileEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pino() const { return at<3>().valid(); }
+ uint64_t pino() const { return at<3>().as_uint64(); }
+ bool has_mode() const { return at<4>().valid(); }
+ uint32_t mode() const { return at<4>().as_uint32(); }
+ bool has_size() const { return at<5>().valid(); }
+ int64_t size() const { return at<5>().as_int64(); }
+ bool has_nlink() const { return at<6>().valid(); }
+ uint32_t nlink() const { return at<6>().as_uint32(); }
+ bool has_blocks() const { return at<7>().valid(); }
+ uint64_t blocks() const { return at<7>().as_uint64(); }
+ bool has_advise() const { return at<8>().valid(); }
+ uint32_t advise() const { return at<8>().as_uint32(); }
+};
+
+class F2fsSyncFileEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsSyncFileEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPinoFieldNumber = 3,
+ kModeFieldNumber = 4,
+ kSizeFieldNumber = 5,
+ kNlinkFieldNumber = 6,
+ kBlocksFieldNumber = 7,
+ kAdviseFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsSyncFileEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pino =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Pino kPino{};
+ void set_pino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nlink =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Nlink kNlink{};
+ void set_nlink(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nlink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Advise =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsSyncFileEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Advise kAdvise{};
+ void set_advise(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Advise::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsSubmitWritePageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsSubmitWritePageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsSubmitWritePageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsSubmitWritePageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_type() const { return at<3>().valid(); }
+ int32_t type() const { return at<3>().as_int32(); }
+ bool has_index() const { return at<4>().valid(); }
+ uint64_t index() const { return at<4>().as_uint64(); }
+ bool has_block() const { return at<5>().valid(); }
+ uint32_t block() const { return at<5>().as_uint32(); }
+};
+
+class F2fsSubmitWritePageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsSubmitWritePageFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kIndexFieldNumber = 4,
+ kBlockFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsSubmitWritePageFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSubmitWritePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSubmitWritePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSubmitWritePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSubmitWritePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Block =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsSubmitWritePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Block kBlock{};
+ void set_block(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Block::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsSetPageDirtyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsSetPageDirtyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsSetPageDirtyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsSetPageDirtyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_type() const { return at<3>().valid(); }
+ int32_t type() const { return at<3>().as_int32(); }
+ bool has_dir() const { return at<4>().valid(); }
+ int32_t dir() const { return at<4>().as_int32(); }
+ bool has_index() const { return at<5>().valid(); }
+ uint64_t index() const { return at<5>().as_uint64(); }
+ bool has_dirty() const { return at<6>().valid(); }
+ int32_t dirty() const { return at<6>().as_int32(); }
+ bool has_uptodate() const { return at<7>().valid(); }
+ int32_t uptodate() const { return at<7>().as_int32(); }
+};
+
+class F2fsSetPageDirtyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsSetPageDirtyFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kDirFieldNumber = 4,
+ kIndexFieldNumber = 5,
+ kDirtyFieldNumber = 6,
+ kUptodateFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsSetPageDirtyFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSetPageDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSetPageDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSetPageDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dir =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSetPageDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Dir kDir{};
+ void set_dir(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dir::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsSetPageDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dirty =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSetPageDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Dirty kDirty{};
+ void set_dirty(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dirty::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uptodate =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsSetPageDirtyFtraceEvent>;
+
+ static constexpr FieldMetadata_Uptodate kUptodate{};
+ void set_uptodate(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uptodate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsReserveNewBlockFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsReserveNewBlockFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsReserveNewBlockFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsReserveNewBlockFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_nid() const { return at<2>().valid(); }
+ uint32_t nid() const { return at<2>().as_uint32(); }
+ bool has_ofs_in_node() const { return at<3>().valid(); }
+ uint32_t ofs_in_node() const { return at<3>().as_uint32(); }
+};
+
+class F2fsReserveNewBlockFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsReserveNewBlockFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kNidFieldNumber = 2,
+ kOfsInNodeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsReserveNewBlockFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsReserveNewBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsReserveNewBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OfsInNode =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsReserveNewBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_OfsInNode kOfsInNode{};
+ void set_ofs_in_node(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OfsInNode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsReadpageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsReadpageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsReadpageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsReadpageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+ bool has_blkaddr() const { return at<4>().valid(); }
+ uint64_t blkaddr() const { return at<4>().as_uint64(); }
+ bool has_type() const { return at<5>().valid(); }
+ int32_t type() const { return at<5>().as_int32(); }
+ bool has_dir() const { return at<6>().valid(); }
+ int32_t dir() const { return at<6>().as_int32(); }
+ bool has_dirty() const { return at<7>().valid(); }
+ int32_t dirty() const { return at<7>().as_int32(); }
+ bool has_uptodate() const { return at<8>().valid(); }
+ int32_t uptodate() const { return at<8>().as_int32(); }
+};
+
+class F2fsReadpageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsReadpageFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ kBlkaddrFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ kDirFieldNumber = 6,
+ kDirtyFieldNumber = 7,
+ kUptodateFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsReadpageFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blkaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Blkaddr kBlkaddr{};
+ void set_blkaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blkaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dir =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dir kDir{};
+ void set_dir(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dir::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dirty =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Dirty kDirty{};
+ void set_dirty(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dirty::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uptodate =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsReadpageFtraceEvent>;
+
+ static constexpr FieldMetadata_Uptodate kUptodate{};
+ void set_uptodate(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uptodate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsNewInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsNewInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsNewInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsNewInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class F2fsNewInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsNewInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsNewInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsNewInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsNewInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsNewInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsIgetExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsIgetExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsIgetExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsIgetExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class F2fsIgetExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsIgetExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsIgetExitFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIgetExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIgetExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsIgetExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsIgetFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsIgetFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsIgetFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsIgetFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pino() const { return at<3>().valid(); }
+ uint64_t pino() const { return at<3>().as_uint64(); }
+ bool has_mode() const { return at<4>().valid(); }
+ uint32_t mode() const { return at<4>().as_uint32(); }
+ bool has_size() const { return at<5>().valid(); }
+ int64_t size() const { return at<5>().as_int64(); }
+ bool has_nlink() const { return at<6>().valid(); }
+ uint32_t nlink() const { return at<6>().as_uint32(); }
+ bool has_blocks() const { return at<7>().valid(); }
+ uint64_t blocks() const { return at<7>().as_uint64(); }
+ bool has_advise() const { return at<8>().valid(); }
+ uint32_t advise() const { return at<8>().as_uint32(); }
+};
+
+class F2fsIgetFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsIgetFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPinoFieldNumber = 3,
+ kModeFieldNumber = 4,
+ kSizeFieldNumber = 5,
+ kNlinkFieldNumber = 6,
+ kBlocksFieldNumber = 7,
+ kAdviseFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsIgetFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pino =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Pino kPino{};
+ void set_pino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nlink =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Nlink kNlink{};
+ void set_nlink(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nlink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Advise =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsIgetFtraceEvent>;
+
+ static constexpr FieldMetadata_Advise kAdvise{};
+ void set_advise(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Advise::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsGetVictimFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsGetVictimFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsGetVictimFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsGetVictimFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_type() const { return at<2>().valid(); }
+ int32_t type() const { return at<2>().as_int32(); }
+ bool has_gc_type() const { return at<3>().valid(); }
+ int32_t gc_type() const { return at<3>().as_int32(); }
+ bool has_alloc_mode() const { return at<4>().valid(); }
+ int32_t alloc_mode() const { return at<4>().as_int32(); }
+ bool has_gc_mode() const { return at<5>().valid(); }
+ int32_t gc_mode() const { return at<5>().as_int32(); }
+ bool has_victim() const { return at<6>().valid(); }
+ uint32_t victim() const { return at<6>().as_uint32(); }
+ bool has_ofs_unit() const { return at<7>().valid(); }
+ uint32_t ofs_unit() const { return at<7>().as_uint32(); }
+ bool has_pre_victim() const { return at<8>().valid(); }
+ uint32_t pre_victim() const { return at<8>().as_uint32(); }
+ bool has_prefree() const { return at<9>().valid(); }
+ uint32_t prefree() const { return at<9>().as_uint32(); }
+ bool has_free() const { return at<10>().valid(); }
+ uint32_t free() const { return at<10>().as_uint32(); }
+ bool has_cost() const { return at<11>().valid(); }
+ uint32_t cost() const { return at<11>().as_uint32(); }
+};
+
+class F2fsGetVictimFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsGetVictimFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kTypeFieldNumber = 2,
+ kGcTypeFieldNumber = 3,
+ kAllocModeFieldNumber = 4,
+ kGcModeFieldNumber = 5,
+ kVictimFieldNumber = 6,
+ kOfsUnitFieldNumber = 7,
+ kPreVictimFieldNumber = 8,
+ kPrefreeFieldNumber = 9,
+ kFreeFieldNumber = 10,
+ kCostFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsGetVictimFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GcType =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_GcType kGcType{};
+ void set_gc_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GcType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllocMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_AllocMode kAllocMode{};
+ void set_alloc_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllocMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GcMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_GcMode kGcMode{};
+ void set_gc_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GcMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Victim =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_Victim kVictim{};
+ void set_victim(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Victim::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OfsUnit =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_OfsUnit kOfsUnit{};
+ void set_ofs_unit(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OfsUnit::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreVictim =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_PreVictim kPreVictim{};
+ void set_pre_victim(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreVictim::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prefree =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_Prefree kPrefree{};
+ void set_prefree(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prefree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Free =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_Free kFree{};
+ void set_free(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Free::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cost =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsGetVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_Cost kCost{};
+ void set_cost(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cost::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsGetDataBlockFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsGetDataBlockFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsGetDataBlockFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsGetDataBlockFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_iblock() const { return at<3>().valid(); }
+ uint64_t iblock() const { return at<3>().as_uint64(); }
+ bool has_bh_start() const { return at<4>().valid(); }
+ uint64_t bh_start() const { return at<4>().as_uint64(); }
+ bool has_bh_size() const { return at<5>().valid(); }
+ uint64_t bh_size() const { return at<5>().as_uint64(); }
+ bool has_ret() const { return at<6>().valid(); }
+ int32_t ret() const { return at<6>().as_int32(); }
+};
+
+class F2fsGetDataBlockFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsGetDataBlockFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kIblockFieldNumber = 3,
+ kBhStartFieldNumber = 4,
+ kBhSizeFieldNumber = 5,
+ kRetFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsGetDataBlockFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGetDataBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGetDataBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Iblock =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGetDataBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_Iblock kIblock{};
+ void set_iblock(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iblock::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BhStart =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGetDataBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_BhStart kBhStart{};
+ void set_bh_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BhStart::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BhSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsGetDataBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_BhSize kBhSize{};
+ void set_bh_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BhSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsGetDataBlockFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsFallocateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsFallocateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsFallocateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsFallocateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_mode() const { return at<3>().valid(); }
+ int32_t mode() const { return at<3>().as_int32(); }
+ bool has_offset() const { return at<4>().valid(); }
+ int64_t offset() const { return at<4>().as_int64(); }
+ bool has_len() const { return at<5>().valid(); }
+ int64_t len() const { return at<5>().as_int64(); }
+ bool has_size() const { return at<6>().valid(); }
+ int64_t size() const { return at<6>().as_int64(); }
+ bool has_blocks() const { return at<7>().valid(); }
+ uint64_t blocks() const { return at<7>().as_uint64(); }
+ bool has_ret() const { return at<8>().valid(); }
+ int32_t ret() const { return at<8>().as_int32(); }
+};
+
+class F2fsFallocateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsFallocateFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kModeFieldNumber = 3,
+ kOffsetFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kSizeFieldNumber = 6,
+ kBlocksFieldNumber = 7,
+ kRetFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsFallocateFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Offset =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Offset kOffset{};
+ void set_offset(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Offset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsFallocateFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsEvictInodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsEvictInodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsEvictInodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsEvictInodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_ino() const { return at<2>().valid(); }
+ uint64_t ino() const { return at<2>().as_uint64(); }
+ bool has_pino() const { return at<3>().valid(); }
+ uint64_t pino() const { return at<3>().as_uint64(); }
+ bool has_mode() const { return at<4>().valid(); }
+ uint32_t mode() const { return at<4>().as_uint32(); }
+ bool has_size() const { return at<5>().valid(); }
+ int64_t size() const { return at<5>().as_int64(); }
+ bool has_nlink() const { return at<6>().valid(); }
+ uint32_t nlink() const { return at<6>().as_uint32(); }
+ bool has_blocks() const { return at<7>().valid(); }
+ uint64_t blocks() const { return at<7>().as_uint64(); }
+ bool has_advise() const { return at<8>().valid(); }
+ uint32_t advise() const { return at<8>().as_uint32(); }
+};
+
+class F2fsEvictInodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsEvictInodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kInoFieldNumber = 2,
+ kPinoFieldNumber = 3,
+ kModeFieldNumber = 4,
+ kSizeFieldNumber = 5,
+ kNlinkFieldNumber = 6,
+ kBlocksFieldNumber = 7,
+ kAdviseFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsEvictInodeFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ino =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ino kIno{};
+ void set_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pino =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Pino kPino{};
+ void set_pino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pino::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nlink =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Nlink kNlink{};
+ void set_nlink(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nlink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Blocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Blocks kBlocks{};
+ void set_blocks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Blocks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Advise =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsEvictInodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Advise kAdvise{};
+ void set_advise(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Advise::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class F2fsDoSubmitBioFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ F2fsDoSubmitBioFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit F2fsDoSubmitBioFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit F2fsDoSubmitBioFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev() const { return at<1>().valid(); }
+ uint64_t dev() const { return at<1>().as_uint64(); }
+ bool has_btype() const { return at<2>().valid(); }
+ int32_t btype() const { return at<2>().as_int32(); }
+ bool has_sync() const { return at<3>().valid(); }
+ uint32_t sync() const { return at<3>().as_uint32(); }
+ bool has_sector() const { return at<4>().valid(); }
+ uint64_t sector() const { return at<4>().as_uint64(); }
+ bool has_size() const { return at<5>().valid(); }
+ uint32_t size() const { return at<5>().as_uint32(); }
+};
+
+class F2fsDoSubmitBioFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = F2fsDoSubmitBioFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevFieldNumber = 1,
+ kBtypeFieldNumber = 2,
+ kSyncFieldNumber = 3,
+ kSectorFieldNumber = 4,
+ kSizeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.F2fsDoSubmitBioFtraceEvent"; }
+
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsDoSubmitBioFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Btype =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ F2fsDoSubmitBioFtraceEvent>;
+
+ static constexpr FieldMetadata_Btype kBtype{};
+ void set_btype(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Btype::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sync =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsDoSubmitBioFtraceEvent>;
+
+ static constexpr FieldMetadata_Sync kSync{};
+ void set_sync(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sync::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sector =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ F2fsDoSubmitBioFtraceEvent>;
+
+ static constexpr FieldMetadata_Sector kSector{};
+ void set_sector(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sector::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ F2fsDoSubmitBioFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/fastrpc.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FASTRPC_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FASTRPC_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class FastrpcDmaStatFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FastrpcDmaStatFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FastrpcDmaStatFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FastrpcDmaStatFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cid() const { return at<1>().valid(); }
+ int32_t cid() const { return at<1>().as_int32(); }
+ bool has_len() const { return at<2>().valid(); }
+ int64_t len() const { return at<2>().as_int64(); }
+ bool has_total_allocated() const { return at<3>().valid(); }
+ uint64_t total_allocated() const { return at<3>().as_uint64(); }
+};
+
+class FastrpcDmaStatFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FastrpcDmaStatFtraceEvent_Decoder;
+ enum : int32_t {
+ kCidFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kTotalAllocatedFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FastrpcDmaStatFtraceEvent"; }
+
+
+ using FieldMetadata_Cid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FastrpcDmaStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Cid kCid{};
+ void set_cid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ FastrpcDmaStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalAllocated =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FastrpcDmaStatFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalAllocated kTotalAllocated{};
+ void set_total_allocated(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalAllocated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/fence.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FENCE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FENCE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class FenceSignaledFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FenceSignaledFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FenceSignaledFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FenceSignaledFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class FenceSignaledFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FenceSignaledFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FenceSignaledFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceSignaledFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FenceEnableSignalFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FenceEnableSignalFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FenceEnableSignalFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FenceEnableSignalFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class FenceEnableSignalFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FenceEnableSignalFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FenceEnableSignalFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceEnableSignalFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceEnableSignalFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceEnableSignalFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceEnableSignalFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FenceDestroyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FenceDestroyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FenceDestroyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FenceDestroyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class FenceDestroyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FenceDestroyFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FenceDestroyFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceDestroyFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceDestroyFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceDestroyFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceDestroyFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FenceInitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FenceInitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FenceInitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FenceInitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint32_t context() const { return at<1>().as_uint32(); }
+ bool has_driver() const { return at<2>().valid(); }
+ ::protozero::ConstChars driver() const { return at<2>().as_string(); }
+ bool has_seqno() const { return at<3>().valid(); }
+ uint32_t seqno() const { return at<3>().as_uint32(); }
+ bool has_timeline() const { return at<4>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<4>().as_string(); }
+};
+
+class FenceInitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FenceInitFtraceEvent_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kDriverFieldNumber = 2,
+ kSeqnoFieldNumber = 3,
+ kTimelineFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FenceInitFtraceEvent"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Driver =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Driver kDriver{};
+ void set_driver(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, data, size);
+ }
+ void set_driver(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Driver::kFieldId, chars.data, chars.size);
+ }
+ void set_driver(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Driver::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ FenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ FenceInitFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/filemap.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FILEMAP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FILEMAP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class MmFilemapDeleteFromPageCacheFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmFilemapDeleteFromPageCacheFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmFilemapDeleteFromPageCacheFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmFilemapDeleteFromPageCacheFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pfn() const { return at<1>().valid(); }
+ uint64_t pfn() const { return at<1>().as_uint64(); }
+ bool has_i_ino() const { return at<2>().valid(); }
+ uint64_t i_ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+ bool has_s_dev() const { return at<4>().valid(); }
+ uint64_t s_dev() const { return at<4>().as_uint64(); }
+ bool has_page() const { return at<5>().valid(); }
+ uint64_t page() const { return at<5>().as_uint64(); }
+};
+
+class MmFilemapDeleteFromPageCacheFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmFilemapDeleteFromPageCacheFtraceEvent_Decoder;
+ enum : int32_t {
+ kPfnFieldNumber = 1,
+ kIInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ kSDevFieldNumber = 4,
+ kPageFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmFilemapDeleteFromPageCacheFtraceEvent"; }
+
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapDeleteFromPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IIno =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapDeleteFromPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_IIno kIIno{};
+ void set_i_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IIno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapDeleteFromPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SDev =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapDeleteFromPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_SDev kSDev{};
+ void set_s_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SDev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapDeleteFromPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmFilemapAddToPageCacheFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmFilemapAddToPageCacheFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmFilemapAddToPageCacheFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmFilemapAddToPageCacheFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pfn() const { return at<1>().valid(); }
+ uint64_t pfn() const { return at<1>().as_uint64(); }
+ bool has_i_ino() const { return at<2>().valid(); }
+ uint64_t i_ino() const { return at<2>().as_uint64(); }
+ bool has_index() const { return at<3>().valid(); }
+ uint64_t index() const { return at<3>().as_uint64(); }
+ bool has_s_dev() const { return at<4>().valid(); }
+ uint64_t s_dev() const { return at<4>().as_uint64(); }
+ bool has_page() const { return at<5>().valid(); }
+ uint64_t page() const { return at<5>().as_uint64(); }
+};
+
+class MmFilemapAddToPageCacheFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmFilemapAddToPageCacheFtraceEvent_Decoder;
+ enum : int32_t {
+ kPfnFieldNumber = 1,
+ kIInoFieldNumber = 2,
+ kIndexFieldNumber = 3,
+ kSDevFieldNumber = 4,
+ kPageFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmFilemapAddToPageCacheFtraceEvent"; }
+
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapAddToPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IIno =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapAddToPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_IIno kIIno{};
+ void set_i_ino(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IIno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapAddToPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SDev =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapAddToPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_SDev kSDev{};
+ void set_s_dev(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SDev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmFilemapAddToPageCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ftrace.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_FTRACE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class FuncgraphExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FuncgraphExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FuncgraphExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FuncgraphExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_calltime() const { return at<1>().valid(); }
+ uint64_t calltime() const { return at<1>().as_uint64(); }
+ bool has_depth() const { return at<2>().valid(); }
+ int32_t depth() const { return at<2>().as_int32(); }
+ bool has_func() const { return at<3>().valid(); }
+ uint64_t func() const { return at<3>().as_uint64(); }
+ bool has_overrun() const { return at<4>().valid(); }
+ uint64_t overrun() const { return at<4>().as_uint64(); }
+ bool has_rettime() const { return at<5>().valid(); }
+ uint64_t rettime() const { return at<5>().as_uint64(); }
+};
+
+class FuncgraphExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FuncgraphExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kCalltimeFieldNumber = 1,
+ kDepthFieldNumber = 2,
+ kFuncFieldNumber = 3,
+ kOverrunFieldNumber = 4,
+ kRettimeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FuncgraphExitFtraceEvent"; }
+
+
+ using FieldMetadata_Calltime =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FuncgraphExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Calltime kCalltime{};
+ void set_calltime(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Calltime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Depth =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FuncgraphExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Depth kDepth{};
+ void set_depth(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Depth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Func =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FuncgraphExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Func kFunc{};
+ void set_func(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Func::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Overrun =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FuncgraphExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Overrun kOverrun{};
+ void set_overrun(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Overrun::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rettime =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FuncgraphExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Rettime kRettime{};
+ void set_rettime(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rettime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class FuncgraphEntryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ FuncgraphEntryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit FuncgraphEntryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit FuncgraphEntryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_depth() const { return at<1>().valid(); }
+ int32_t depth() const { return at<1>().as_int32(); }
+ bool has_func() const { return at<2>().valid(); }
+ uint64_t func() const { return at<2>().as_uint64(); }
+};
+
+class FuncgraphEntryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = FuncgraphEntryFtraceEvent_Decoder;
+ enum : int32_t {
+ kDepthFieldNumber = 1,
+ kFuncFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.FuncgraphEntryFtraceEvent"; }
+
+
+ using FieldMetadata_Depth =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ FuncgraphEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Depth kDepth{};
+ void set_depth(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Depth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Func =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ FuncgraphEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Func kFunc{};
+ void set_func(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Func::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PrintFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PrintFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PrintFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PrintFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ip() const { return at<1>().valid(); }
+ uint64_t ip() const { return at<1>().as_uint64(); }
+ bool has_buf() const { return at<2>().valid(); }
+ ::protozero::ConstChars buf() const { return at<2>().as_string(); }
+};
+
+class PrintFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = PrintFtraceEvent_Decoder;
+ enum : int32_t {
+ kIpFieldNumber = 1,
+ kBufFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PrintFtraceEvent"; }
+
+
+ using FieldMetadata_Ip =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PrintFtraceEvent>;
+
+ static constexpr FieldMetadata_Ip kIp{};
+ void set_ip(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ip::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Buf =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PrintFtraceEvent>;
+
+ static constexpr FieldMetadata_Buf kBuf{};
+ void set_buf(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Buf::kFieldId, data, size);
+ }
+ void set_buf(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Buf::kFieldId, chars.data, chars.size);
+ }
+ void set_buf(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Buf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/g2d.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_G2D_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_G2D_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class G2dTracingMarkWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ G2dTracingMarkWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit G2dTracingMarkWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit G2dTracingMarkWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars name() const { return at<4>().as_string(); }
+ bool has_type() const { return at<5>().valid(); }
+ uint32_t type() const { return at<5>().as_uint32(); }
+ bool has_value() const { return at<6>().valid(); }
+ int32_t value() const { return at<6>().as_int32(); }
+};
+
+class G2dTracingMarkWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = G2dTracingMarkWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kNameFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ kValueFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.G2dTracingMarkWriteFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ G2dTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ G2dTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ G2dTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ G2dTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/gpu_mem.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_GPU_MEM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_GPU_MEM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class GpuMemTotalFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuMemTotalFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuMemTotalFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuMemTotalFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gpu_id() const { return at<1>().valid(); }
+ uint32_t gpu_id() const { return at<1>().as_uint32(); }
+ bool has_pid() const { return at<2>().valid(); }
+ uint32_t pid() const { return at<2>().as_uint32(); }
+ bool has_size() const { return at<3>().valid(); }
+ uint64_t size() const { return at<3>().as_uint64(); }
+};
+
+class GpuMemTotalFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = GpuMemTotalFtraceEvent_Decoder;
+ enum : int32_t {
+ kGpuIdFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kSizeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuMemTotalFtraceEvent"; }
+
+
+ using FieldMetadata_GpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuMemTotalFtraceEvent>;
+
+ static constexpr FieldMetadata_GpuId kGpuId{};
+ void set_gpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuMemTotalFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuMemTotalFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/gpu_scheduler.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_GPU_SCHEDULER_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_GPU_SCHEDULER_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class DrmSchedProcessJobFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DrmSchedProcessJobFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DrmSchedProcessJobFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DrmSchedProcessJobFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_fence() const { return at<1>().valid(); }
+ uint64_t fence() const { return at<1>().as_uint64(); }
+};
+
+class DrmSchedProcessJobFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DrmSchedProcessJobFtraceEvent_Decoder;
+ enum : int32_t {
+ kFenceFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DrmSchedProcessJobFtraceEvent"; }
+
+
+ using FieldMetadata_Fence =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmSchedProcessJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Fence kFence{};
+ void set_fence(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DrmRunJobFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DrmRunJobFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DrmRunJobFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DrmRunJobFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_entity() const { return at<1>().valid(); }
+ uint64_t entity() const { return at<1>().as_uint64(); }
+ bool has_fence() const { return at<2>().valid(); }
+ uint64_t fence() const { return at<2>().as_uint64(); }
+ bool has_hw_job_count() const { return at<3>().valid(); }
+ int32_t hw_job_count() const { return at<3>().as_int32(); }
+ bool has_id() const { return at<4>().valid(); }
+ uint64_t id() const { return at<4>().as_uint64(); }
+ bool has_job_count() const { return at<5>().valid(); }
+ uint32_t job_count() const { return at<5>().as_uint32(); }
+ bool has_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars name() const { return at<6>().as_string(); }
+};
+
+class DrmRunJobFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DrmRunJobFtraceEvent_Decoder;
+ enum : int32_t {
+ kEntityFieldNumber = 1,
+ kFenceFieldNumber = 2,
+ kHwJobCountFieldNumber = 3,
+ kIdFieldNumber = 4,
+ kJobCountFieldNumber = 5,
+ kNameFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DrmRunJobFtraceEvent"; }
+
+
+ using FieldMetadata_Entity =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmRunJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Entity kEntity{};
+ void set_entity(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Entity::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fence =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmRunJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Fence kFence{};
+ void set_fence(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwJobCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DrmRunJobFtraceEvent>;
+
+ static constexpr FieldMetadata_HwJobCount kHwJobCount{};
+ void set_hw_job_count(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwJobCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmRunJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JobCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DrmRunJobFtraceEvent>;
+
+ static constexpr FieldMetadata_JobCount kJobCount{};
+ void set_job_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_JobCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DrmRunJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DrmSchedJobFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DrmSchedJobFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DrmSchedJobFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DrmSchedJobFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_entity() const { return at<1>().valid(); }
+ uint64_t entity() const { return at<1>().as_uint64(); }
+ bool has_fence() const { return at<2>().valid(); }
+ uint64_t fence() const { return at<2>().as_uint64(); }
+ bool has_hw_job_count() const { return at<3>().valid(); }
+ int32_t hw_job_count() const { return at<3>().as_int32(); }
+ bool has_id() const { return at<4>().valid(); }
+ uint64_t id() const { return at<4>().as_uint64(); }
+ bool has_job_count() const { return at<5>().valid(); }
+ uint32_t job_count() const { return at<5>().as_uint32(); }
+ bool has_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars name() const { return at<6>().as_string(); }
+};
+
+class DrmSchedJobFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DrmSchedJobFtraceEvent_Decoder;
+ enum : int32_t {
+ kEntityFieldNumber = 1,
+ kFenceFieldNumber = 2,
+ kHwJobCountFieldNumber = 3,
+ kIdFieldNumber = 4,
+ kJobCountFieldNumber = 5,
+ kNameFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DrmSchedJobFtraceEvent"; }
+
+
+ using FieldMetadata_Entity =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmSchedJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Entity kEntity{};
+ void set_entity(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Entity::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fence =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmSchedJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Fence kFence{};
+ void set_fence(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwJobCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DrmSchedJobFtraceEvent>;
+
+ static constexpr FieldMetadata_HwJobCount kHwJobCount{};
+ void set_hw_job_count(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwJobCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ DrmSchedJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_JobCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DrmSchedJobFtraceEvent>;
+
+ static constexpr FieldMetadata_JobCount kJobCount{};
+ void set_job_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_JobCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DrmSchedJobFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/hyp.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_HYP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_HYP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class HostMemAbortFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HostMemAbortFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HostMemAbortFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HostMemAbortFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_esr() const { return at<1>().valid(); }
+ uint64_t esr() const { return at<1>().as_uint64(); }
+ bool has_addr() const { return at<2>().valid(); }
+ uint64_t addr() const { return at<2>().as_uint64(); }
+};
+
+class HostMemAbortFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = HostMemAbortFtraceEvent_Decoder;
+ enum : int32_t {
+ kEsrFieldNumber = 1,
+ kAddrFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HostMemAbortFtraceEvent"; }
+
+
+ using FieldMetadata_Esr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HostMemAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_Esr kEsr{};
+ void set_esr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Esr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HostMemAbortFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HostSmcFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HostSmcFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HostSmcFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HostSmcFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+ bool has_forwarded() const { return at<2>().valid(); }
+ uint32_t forwarded() const { return at<2>().as_uint32(); }
+};
+
+class HostSmcFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = HostSmcFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kForwardedFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HostSmcFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HostSmcFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Forwarded =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HostSmcFtraceEvent>;
+
+ static constexpr FieldMetadata_Forwarded kForwarded{};
+ void set_forwarded(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Forwarded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HostHcallFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HostHcallFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HostHcallFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HostHcallFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint32_t id() const { return at<1>().as_uint32(); }
+ bool has_invalid() const { return at<2>().valid(); }
+ uint32_t invalid() const { return at<2>().as_uint32(); }
+};
+
+class HostHcallFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = HostHcallFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kInvalidFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HostHcallFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HostHcallFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Invalid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ HostHcallFtraceEvent>;
+
+ static constexpr FieldMetadata_Invalid kInvalid{};
+ void set_invalid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Invalid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HypExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HypExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HypExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HypExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class HypExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = HypExitFtraceEvent_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.HypExitFtraceEvent"; }
+
+};
+
+class HypEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HypEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HypEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HypEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class HypEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = HypEnterFtraceEvent_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.HypEnterFtraceEvent"; }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/i2c.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_I2C_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_I2C_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SmbusReplyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SmbusReplyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SmbusReplyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SmbusReplyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_addr() const { return at<2>().valid(); }
+ uint32_t addr() const { return at<2>().as_uint32(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_command() const { return at<4>().valid(); }
+ uint32_t command() const { return at<4>().as_uint32(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint32_t len() const { return at<5>().as_uint32(); }
+ bool has_protocol() const { return at<6>().valid(); }
+ uint32_t protocol() const { return at<6>().as_uint32(); }
+};
+
+class SmbusReplyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SmbusReplyFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kAddrFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kCommandFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kProtocolFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SmbusReplyFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SmbusReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Command =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Command kCommand{};
+ void set_command(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Command::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Protocol =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Protocol kProtocol{};
+ void set_protocol(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Protocol::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SmbusResultFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SmbusResultFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SmbusResultFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SmbusResultFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_addr() const { return at<2>().valid(); }
+ uint32_t addr() const { return at<2>().as_uint32(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_read_write() const { return at<4>().valid(); }
+ uint32_t read_write() const { return at<4>().as_uint32(); }
+ bool has_command() const { return at<5>().valid(); }
+ uint32_t command() const { return at<5>().as_uint32(); }
+ bool has_res() const { return at<6>().valid(); }
+ int32_t res() const { return at<6>().as_int32(); }
+ bool has_protocol() const { return at<7>().valid(); }
+ uint32_t protocol() const { return at<7>().as_uint32(); }
+};
+
+class SmbusResultFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SmbusResultFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kAddrFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kReadWriteFieldNumber = 4,
+ kCommandFieldNumber = 5,
+ kResFieldNumber = 6,
+ kProtocolFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SmbusResultFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SmbusResultFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusResultFtraceEvent>;
+
+ static constexpr FieldMetadata_ReadWrite kReadWrite{};
+ void set_read_write(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadWrite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Command =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Command kCommand{};
+ void set_command(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Command::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Res =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SmbusResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Res kRes{};
+ void set_res(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Res::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Protocol =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Protocol kProtocol{};
+ void set_protocol(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Protocol::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SmbusWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SmbusWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SmbusWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SmbusWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_addr() const { return at<2>().valid(); }
+ uint32_t addr() const { return at<2>().as_uint32(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_command() const { return at<4>().valid(); }
+ uint32_t command() const { return at<4>().as_uint32(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint32_t len() const { return at<5>().as_uint32(); }
+ bool has_protocol() const { return at<6>().valid(); }
+ uint32_t protocol() const { return at<6>().as_uint32(); }
+};
+
+class SmbusWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SmbusWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kAddrFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kCommandFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kProtocolFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SmbusWriteFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SmbusWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Command =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Command kCommand{};
+ void set_command(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Command::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Protocol =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Protocol kProtocol{};
+ void set_protocol(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Protocol::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SmbusReadFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SmbusReadFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SmbusReadFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SmbusReadFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_addr() const { return at<3>().valid(); }
+ uint32_t addr() const { return at<3>().as_uint32(); }
+ bool has_command() const { return at<4>().valid(); }
+ uint32_t command() const { return at<4>().as_uint32(); }
+ bool has_protocol() const { return at<5>().valid(); }
+ uint32_t protocol() const { return at<5>().as_uint32(); }
+};
+
+class SmbusReadFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SmbusReadFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kAddrFieldNumber = 3,
+ kCommandFieldNumber = 4,
+ kProtocolFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SmbusReadFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SmbusReadFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Command =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Command kCommand{};
+ void set_command(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Command::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Protocol =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmbusReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Protocol kProtocol{};
+ void set_protocol(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Protocol::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class I2cReplyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ I2cReplyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit I2cReplyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit I2cReplyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_msg_nr() const { return at<2>().valid(); }
+ uint32_t msg_nr() const { return at<2>().as_uint32(); }
+ bool has_addr() const { return at<3>().valid(); }
+ uint32_t addr() const { return at<3>().as_uint32(); }
+ bool has_flags() const { return at<4>().valid(); }
+ uint32_t flags() const { return at<4>().as_uint32(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint32_t len() const { return at<5>().as_uint32(); }
+ bool has_buf() const { return at<6>().valid(); }
+ uint32_t buf() const { return at<6>().as_uint32(); }
+};
+
+class I2cReplyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = I2cReplyFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kMsgNrFieldNumber = 2,
+ kAddrFieldNumber = 3,
+ kFlagsFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kBufFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.I2cReplyFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ I2cReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MsgNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_MsgNr kMsgNr{};
+ void set_msg_nr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MsgNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Buf =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReplyFtraceEvent>;
+
+ static constexpr FieldMetadata_Buf kBuf{};
+ void set_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Buf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class I2cResultFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ I2cResultFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit I2cResultFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit I2cResultFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_nr_msgs() const { return at<2>().valid(); }
+ uint32_t nr_msgs() const { return at<2>().as_uint32(); }
+ bool has_ret() const { return at<3>().valid(); }
+ int32_t ret() const { return at<3>().as_int32(); }
+};
+
+class I2cResultFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = I2cResultFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kNrMsgsFieldNumber = 2,
+ kRetFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.I2cResultFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ I2cResultFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrMsgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cResultFtraceEvent>;
+
+ static constexpr FieldMetadata_NrMsgs kNrMsgs{};
+ void set_nr_msgs(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrMsgs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ I2cResultFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class I2cWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ I2cWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit I2cWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit I2cWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_msg_nr() const { return at<2>().valid(); }
+ uint32_t msg_nr() const { return at<2>().as_uint32(); }
+ bool has_addr() const { return at<3>().valid(); }
+ uint32_t addr() const { return at<3>().as_uint32(); }
+ bool has_flags() const { return at<4>().valid(); }
+ uint32_t flags() const { return at<4>().as_uint32(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint32_t len() const { return at<5>().as_uint32(); }
+ bool has_buf() const { return at<6>().valid(); }
+ uint32_t buf() const { return at<6>().as_uint32(); }
+};
+
+class I2cWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = I2cWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kMsgNrFieldNumber = 2,
+ kAddrFieldNumber = 3,
+ kFlagsFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kBufFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.I2cWriteFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ I2cWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MsgNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_MsgNr kMsgNr{};
+ void set_msg_nr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MsgNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Buf =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Buf kBuf{};
+ void set_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Buf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class I2cReadFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ I2cReadFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit I2cReadFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit I2cReadFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_adapter_nr() const { return at<1>().valid(); }
+ int32_t adapter_nr() const { return at<1>().as_int32(); }
+ bool has_msg_nr() const { return at<2>().valid(); }
+ uint32_t msg_nr() const { return at<2>().as_uint32(); }
+ bool has_addr() const { return at<3>().valid(); }
+ uint32_t addr() const { return at<3>().as_uint32(); }
+ bool has_flags() const { return at<4>().valid(); }
+ uint32_t flags() const { return at<4>().as_uint32(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint32_t len() const { return at<5>().as_uint32(); }
+};
+
+class I2cReadFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = I2cReadFtraceEvent_Decoder;
+ enum : int32_t {
+ kAdapterNrFieldNumber = 1,
+ kMsgNrFieldNumber = 2,
+ kAddrFieldNumber = 3,
+ kFlagsFieldNumber = 4,
+ kLenFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.I2cReadFtraceEvent"; }
+
+
+ using FieldMetadata_AdapterNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ I2cReadFtraceEvent>;
+
+ static constexpr FieldMetadata_AdapterNr kAdapterNr{};
+ void set_adapter_nr(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AdapterNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MsgNr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReadFtraceEvent>;
+
+ static constexpr FieldMetadata_MsgNr kMsgNr{};
+ void set_msg_nr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MsgNr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ I2cReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ion.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_ION_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_ION_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class IonStatFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonStatFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonStatFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonStatFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buffer_id() const { return at<1>().valid(); }
+ uint32_t buffer_id() const { return at<1>().as_uint32(); }
+ bool has_len() const { return at<2>().valid(); }
+ int64_t len() const { return at<2>().as_int64(); }
+ bool has_total_allocated() const { return at<3>().valid(); }
+ uint64_t total_allocated() const { return at<3>().as_uint64(); }
+};
+
+class IonStatFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonStatFtraceEvent_Decoder;
+ enum : int32_t {
+ kBufferIdFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kTotalAllocatedFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonStatFtraceEvent"; }
+
+
+ using FieldMetadata_BufferId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonStatFtraceEvent>;
+
+ static constexpr FieldMetadata_BufferId kBufferId{};
+ void set_buffer_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ IonStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalAllocated =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonStatFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalAllocated kTotalAllocated{};
+ void set_total_allocated(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalAllocated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ipi.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_IPI_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_IPI_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class IpiRaiseFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IpiRaiseFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IpiRaiseFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IpiRaiseFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_target_cpus() const { return at<1>().valid(); }
+ uint32_t target_cpus() const { return at<1>().as_uint32(); }
+ bool has_reason() const { return at<2>().valid(); }
+ ::protozero::ConstChars reason() const { return at<2>().as_string(); }
+};
+
+class IpiRaiseFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IpiRaiseFtraceEvent_Decoder;
+ enum : int32_t {
+ kTargetCpusFieldNumber = 1,
+ kReasonFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IpiRaiseFtraceEvent"; }
+
+
+ using FieldMetadata_TargetCpus =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IpiRaiseFtraceEvent>;
+
+ static constexpr FieldMetadata_TargetCpus kTargetCpus{};
+ void set_target_cpus(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetCpus::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Reason =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IpiRaiseFtraceEvent>;
+
+ static constexpr FieldMetadata_Reason kReason{};
+ void set_reason(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Reason::kFieldId, data, size);
+ }
+ void set_reason(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Reason::kFieldId, chars.data, chars.size);
+ }
+ void set_reason(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IpiExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IpiExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IpiExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IpiExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_reason() const { return at<1>().valid(); }
+ ::protozero::ConstChars reason() const { return at<1>().as_string(); }
+};
+
+class IpiExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IpiExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kReasonFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IpiExitFtraceEvent"; }
+
+
+ using FieldMetadata_Reason =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IpiExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Reason kReason{};
+ void set_reason(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Reason::kFieldId, data, size);
+ }
+ void set_reason(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Reason::kFieldId, chars.data, chars.size);
+ }
+ void set_reason(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IpiEntryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IpiEntryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IpiEntryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IpiEntryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_reason() const { return at<1>().valid(); }
+ ::protozero::ConstChars reason() const { return at<1>().as_string(); }
+};
+
+class IpiEntryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IpiEntryFtraceEvent_Decoder;
+ enum : int32_t {
+ kReasonFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IpiEntryFtraceEvent"; }
+
+
+ using FieldMetadata_Reason =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IpiEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Reason kReason{};
+ void set_reason(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Reason::kFieldId, data, size);
+ }
+ void set_reason(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Reason::kFieldId, chars.data, chars.size);
+ }
+ void set_reason(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/irq.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_IRQ_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_IRQ_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class IrqHandlerExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IrqHandlerExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IrqHandlerExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IrqHandlerExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irq() const { return at<1>().valid(); }
+ int32_t irq() const { return at<1>().as_int32(); }
+ bool has_ret() const { return at<2>().valid(); }
+ int32_t ret() const { return at<2>().as_int32(); }
+};
+
+class IrqHandlerExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IrqHandlerExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kIrqFieldNumber = 1,
+ kRetFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IrqHandlerExitFtraceEvent"; }
+
+
+ using FieldMetadata_Irq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IrqHandlerExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Irq kIrq{};
+ void set_irq(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Irq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IrqHandlerExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IrqHandlerEntryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IrqHandlerEntryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IrqHandlerEntryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IrqHandlerEntryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irq() const { return at<1>().valid(); }
+ int32_t irq() const { return at<1>().as_int32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_handler() const { return at<3>().valid(); }
+ uint32_t handler() const { return at<3>().as_uint32(); }
+};
+
+class IrqHandlerEntryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IrqHandlerEntryFtraceEvent_Decoder;
+ enum : int32_t {
+ kIrqFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kHandlerFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IrqHandlerEntryFtraceEvent"; }
+
+
+ using FieldMetadata_Irq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IrqHandlerEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Irq kIrq{};
+ void set_irq(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Irq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IrqHandlerEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Handler =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IrqHandlerEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Handler kHandler{};
+ void set_handler(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Handler::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SoftirqRaiseFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SoftirqRaiseFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SoftirqRaiseFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SoftirqRaiseFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_vec() const { return at<1>().valid(); }
+ uint32_t vec() const { return at<1>().as_uint32(); }
+};
+
+class SoftirqRaiseFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SoftirqRaiseFtraceEvent_Decoder;
+ enum : int32_t {
+ kVecFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SoftirqRaiseFtraceEvent"; }
+
+
+ using FieldMetadata_Vec =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SoftirqRaiseFtraceEvent>;
+
+ static constexpr FieldMetadata_Vec kVec{};
+ void set_vec(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Vec::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SoftirqExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SoftirqExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SoftirqExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SoftirqExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_vec() const { return at<1>().valid(); }
+ uint32_t vec() const { return at<1>().as_uint32(); }
+};
+
+class SoftirqExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SoftirqExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kVecFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SoftirqExitFtraceEvent"; }
+
+
+ using FieldMetadata_Vec =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SoftirqExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Vec kVec{};
+ void set_vec(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Vec::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SoftirqEntryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SoftirqEntryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SoftirqEntryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SoftirqEntryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_vec() const { return at<1>().valid(); }
+ uint32_t vec() const { return at<1>().as_uint32(); }
+};
+
+class SoftirqEntryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SoftirqEntryFtraceEvent_Decoder;
+ enum : int32_t {
+ kVecFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SoftirqEntryFtraceEvent"; }
+
+
+ using FieldMetadata_Vec =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SoftirqEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Vec kVec{};
+ void set_vec(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Vec::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/kmem.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_KMEM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_KMEM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class IonBufferDestroyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonBufferDestroyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonBufferDestroyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonBufferDestroyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_addr() const { return at<1>().valid(); }
+ uint64_t addr() const { return at<1>().as_uint64(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+};
+
+class IonBufferDestroyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonBufferDestroyFtraceEvent_Decoder;
+ enum : int32_t {
+ kAddrFieldNumber = 1,
+ kLenFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonBufferDestroyFtraceEvent"; }
+
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonBufferDestroyFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonBufferDestroyFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonBufferCreateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonBufferCreateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonBufferCreateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonBufferCreateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_addr() const { return at<1>().valid(); }
+ uint64_t addr() const { return at<1>().as_uint64(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+};
+
+class IonBufferCreateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonBufferCreateFtraceEvent_Decoder;
+ enum : int32_t {
+ kAddrFieldNumber = 1,
+ kLenFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonBufferCreateFtraceEvent"; }
+
+
+ using FieldMetadata_Addr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonBufferCreateFtraceEvent>;
+
+ static constexpr FieldMetadata_Addr kAddr{};
+ void set_addr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Addr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonBufferCreateFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonHeapGrowFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonHeapGrowFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonHeapGrowFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonHeapGrowFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_heap_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<1>().as_string(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+ bool has_total_allocated() const { return at<3>().valid(); }
+ int64_t total_allocated() const { return at<3>().as_int64(); }
+};
+
+class IonHeapGrowFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonHeapGrowFtraceEvent_Decoder;
+ enum : int32_t {
+ kHeapNameFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kTotalAllocatedFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonHeapGrowFtraceEvent"; }
+
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonHeapGrowFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonHeapGrowFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalAllocated =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ IonHeapGrowFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalAllocated kTotalAllocated{};
+ void set_total_allocated(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalAllocated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonHeapShrinkFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonHeapShrinkFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonHeapShrinkFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonHeapShrinkFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_heap_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<1>().as_string(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+ bool has_total_allocated() const { return at<3>().valid(); }
+ int64_t total_allocated() const { return at<3>().as_int64(); }
+};
+
+class IonHeapShrinkFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonHeapShrinkFtraceEvent_Decoder;
+ enum : int32_t {
+ kHeapNameFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kTotalAllocatedFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonHeapShrinkFtraceEvent"; }
+
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonHeapShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonHeapShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalAllocated =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ IonHeapShrinkFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalAllocated kTotalAllocated{};
+ void set_total_allocated(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalAllocated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RssStatFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RssStatFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RssStatFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RssStatFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_member() const { return at<1>().valid(); }
+ int32_t member() const { return at<1>().as_int32(); }
+ bool has_size() const { return at<2>().valid(); }
+ int64_t size() const { return at<2>().as_int64(); }
+ bool has_curr() const { return at<3>().valid(); }
+ uint32_t curr() const { return at<3>().as_uint32(); }
+ bool has_mm_id() const { return at<4>().valid(); }
+ uint32_t mm_id() const { return at<4>().as_uint32(); }
+};
+
+class RssStatFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RssStatFtraceEvent_Decoder;
+ enum : int32_t {
+ kMemberFieldNumber = 1,
+ kSizeFieldNumber = 2,
+ kCurrFieldNumber = 3,
+ kMmIdFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RssStatFtraceEvent"; }
+
+
+ using FieldMetadata_Member =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RssStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Member kMember{};
+ void set_member(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Member::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ RssStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Curr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ RssStatFtraceEvent>;
+
+ static constexpr FieldMetadata_Curr kCurr{};
+ void set_curr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Curr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MmId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ RssStatFtraceEvent>;
+
+ static constexpr FieldMetadata_MmId kMmId{};
+ void set_mm_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MmId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmPagePcpuDrainFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmPagePcpuDrainFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmPagePcpuDrainFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmPagePcpuDrainFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_migratetype() const { return at<1>().valid(); }
+ int32_t migratetype() const { return at<1>().as_int32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+ bool has_page() const { return at<3>().valid(); }
+ uint64_t page() const { return at<3>().as_uint64(); }
+ bool has_pfn() const { return at<4>().valid(); }
+ uint64_t pfn() const { return at<4>().as_uint64(); }
+};
+
+class MmPagePcpuDrainFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmPagePcpuDrainFtraceEvent_Decoder;
+ enum : int32_t {
+ kMigratetypeFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ kPageFieldNumber = 3,
+ kPfnFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmPagePcpuDrainFtraceEvent"; }
+
+
+ using FieldMetadata_Migratetype =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPagePcpuDrainFtraceEvent>;
+
+ static constexpr FieldMetadata_Migratetype kMigratetype{};
+ void set_migratetype(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Migratetype::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmPagePcpuDrainFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPagePcpuDrainFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPagePcpuDrainFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmPageFreeBatchedFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmPageFreeBatchedFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmPageFreeBatchedFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmPageFreeBatchedFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cold() const { return at<1>().valid(); }
+ int32_t cold() const { return at<1>().as_int32(); }
+ bool has_page() const { return at<2>().valid(); }
+ uint64_t page() const { return at<2>().as_uint64(); }
+ bool has_pfn() const { return at<3>().valid(); }
+ uint64_t pfn() const { return at<3>().as_uint64(); }
+};
+
+class MmPageFreeBatchedFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmPageFreeBatchedFtraceEvent_Decoder;
+ enum : int32_t {
+ kColdFieldNumber = 1,
+ kPageFieldNumber = 2,
+ kPfnFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmPageFreeBatchedFtraceEvent"; }
+
+
+ using FieldMetadata_Cold =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageFreeBatchedFtraceEvent>;
+
+ static constexpr FieldMetadata_Cold kCold{};
+ void set_cold(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cold::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageFreeBatchedFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageFreeBatchedFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmPageFreeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmPageFreeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmPageFreeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmPageFreeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_order() const { return at<1>().valid(); }
+ uint32_t order() const { return at<1>().as_uint32(); }
+ bool has_page() const { return at<2>().valid(); }
+ uint64_t page() const { return at<2>().as_uint64(); }
+ bool has_pfn() const { return at<3>().valid(); }
+ uint64_t pfn() const { return at<3>().as_uint64(); }
+};
+
+class MmPageFreeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmPageFreeFtraceEvent_Decoder;
+ enum : int32_t {
+ kOrderFieldNumber = 1,
+ kPageFieldNumber = 2,
+ kPfnFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmPageFreeFtraceEvent"; }
+
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmPageFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmPageAllocZoneLockedFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmPageAllocZoneLockedFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmPageAllocZoneLockedFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmPageAllocZoneLockedFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_migratetype() const { return at<1>().valid(); }
+ int32_t migratetype() const { return at<1>().as_int32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+ bool has_page() const { return at<3>().valid(); }
+ uint64_t page() const { return at<3>().as_uint64(); }
+ bool has_pfn() const { return at<4>().valid(); }
+ uint64_t pfn() const { return at<4>().as_uint64(); }
+};
+
+class MmPageAllocZoneLockedFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmPageAllocZoneLockedFtraceEvent_Decoder;
+ enum : int32_t {
+ kMigratetypeFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ kPageFieldNumber = 3,
+ kPfnFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmPageAllocZoneLockedFtraceEvent"; }
+
+
+ using FieldMetadata_Migratetype =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageAllocZoneLockedFtraceEvent>;
+
+ static constexpr FieldMetadata_Migratetype kMigratetype{};
+ void set_migratetype(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Migratetype::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmPageAllocZoneLockedFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageAllocZoneLockedFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageAllocZoneLockedFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmPageAllocExtfragFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmPageAllocExtfragFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmPageAllocExtfragFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmPageAllocExtfragFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_alloc_migratetype() const { return at<1>().valid(); }
+ int32_t alloc_migratetype() const { return at<1>().as_int32(); }
+ bool has_alloc_order() const { return at<2>().valid(); }
+ int32_t alloc_order() const { return at<2>().as_int32(); }
+ bool has_fallback_migratetype() const { return at<3>().valid(); }
+ int32_t fallback_migratetype() const { return at<3>().as_int32(); }
+ bool has_fallback_order() const { return at<4>().valid(); }
+ int32_t fallback_order() const { return at<4>().as_int32(); }
+ bool has_page() const { return at<5>().valid(); }
+ uint64_t page() const { return at<5>().as_uint64(); }
+ bool has_change_ownership() const { return at<6>().valid(); }
+ int32_t change_ownership() const { return at<6>().as_int32(); }
+ bool has_pfn() const { return at<7>().valid(); }
+ uint64_t pfn() const { return at<7>().as_uint64(); }
+};
+
+class MmPageAllocExtfragFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmPageAllocExtfragFtraceEvent_Decoder;
+ enum : int32_t {
+ kAllocMigratetypeFieldNumber = 1,
+ kAllocOrderFieldNumber = 2,
+ kFallbackMigratetypeFieldNumber = 3,
+ kFallbackOrderFieldNumber = 4,
+ kPageFieldNumber = 5,
+ kChangeOwnershipFieldNumber = 6,
+ kPfnFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmPageAllocExtfragFtraceEvent"; }
+
+
+ using FieldMetadata_AllocMigratetype =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageAllocExtfragFtraceEvent>;
+
+ static constexpr FieldMetadata_AllocMigratetype kAllocMigratetype{};
+ void set_alloc_migratetype(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllocMigratetype::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllocOrder =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageAllocExtfragFtraceEvent>;
+
+ static constexpr FieldMetadata_AllocOrder kAllocOrder{};
+ void set_alloc_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllocOrder::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FallbackMigratetype =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageAllocExtfragFtraceEvent>;
+
+ static constexpr FieldMetadata_FallbackMigratetype kFallbackMigratetype{};
+ void set_fallback_migratetype(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FallbackMigratetype::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FallbackOrder =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageAllocExtfragFtraceEvent>;
+
+ static constexpr FieldMetadata_FallbackOrder kFallbackOrder{};
+ void set_fallback_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FallbackOrder::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageAllocExtfragFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChangeOwnership =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageAllocExtfragFtraceEvent>;
+
+ static constexpr FieldMetadata_ChangeOwnership kChangeOwnership{};
+ void set_change_ownership(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChangeOwnership::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageAllocExtfragFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmPageAllocFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmPageAllocFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmPageAllocFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmPageAllocFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfp_flags() const { return at<1>().valid(); }
+ uint32_t gfp_flags() const { return at<1>().as_uint32(); }
+ bool has_migratetype() const { return at<2>().valid(); }
+ int32_t migratetype() const { return at<2>().as_int32(); }
+ bool has_order() const { return at<3>().valid(); }
+ uint32_t order() const { return at<3>().as_uint32(); }
+ bool has_page() const { return at<4>().valid(); }
+ uint64_t page() const { return at<4>().as_uint64(); }
+ bool has_pfn() const { return at<5>().valid(); }
+ uint64_t pfn() const { return at<5>().as_uint64(); }
+};
+
+class MmPageAllocFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmPageAllocFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfpFlagsFieldNumber = 1,
+ kMigratetypeFieldNumber = 2,
+ kOrderFieldNumber = 3,
+ kPageFieldNumber = 4,
+ kPfnFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmPageAllocFtraceEvent"; }
+
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmPageAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Migratetype =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmPageAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Migratetype kMigratetype{};
+ void set_migratetype(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Migratetype::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmPageAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Page =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Page kPage{};
+ void set_page(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Page::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmPageAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Pfn kPfn{};
+ void set_pfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MigrateRetryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MigrateRetryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MigrateRetryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MigrateRetryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tries() const { return at<1>().valid(); }
+ int32_t tries() const { return at<1>().as_int32(); }
+};
+
+class MigrateRetryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MigrateRetryFtraceEvent_Decoder;
+ enum : int32_t {
+ kTriesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MigrateRetryFtraceEvent"; }
+
+
+ using FieldMetadata_Tries =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MigrateRetryFtraceEvent>;
+
+ static constexpr FieldMetadata_Tries kTries{};
+ void set_tries(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tries::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MigratePagesStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MigratePagesStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MigratePagesStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MigratePagesStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mode() const { return at<1>().valid(); }
+ int32_t mode() const { return at<1>().as_int32(); }
+};
+
+class MigratePagesStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MigratePagesStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kModeFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MigratePagesStartFtraceEvent"; }
+
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MigratePagesStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MigratePagesEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MigratePagesEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MigratePagesEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MigratePagesEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mode() const { return at<1>().valid(); }
+ int32_t mode() const { return at<1>().as_int32(); }
+};
+
+class MigratePagesEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MigratePagesEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kModeFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MigratePagesEndFtraceEvent"; }
+
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MigratePagesEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KmemCacheFreeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KmemCacheFreeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KmemCacheFreeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KmemCacheFreeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_call_site() const { return at<1>().valid(); }
+ uint64_t call_site() const { return at<1>().as_uint64(); }
+ bool has_ptr() const { return at<2>().valid(); }
+ uint64_t ptr() const { return at<2>().as_uint64(); }
+};
+
+class KmemCacheFreeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KmemCacheFreeFtraceEvent_Decoder;
+ enum : int32_t {
+ kCallSiteFieldNumber = 1,
+ kPtrFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KmemCacheFreeFtraceEvent"; }
+
+
+ using FieldMetadata_CallSite =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_CallSite kCallSite{};
+ void set_call_site(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallSite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ptr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ptr kPtr{};
+ void set_ptr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ptr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KmemCacheAllocNodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KmemCacheAllocNodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KmemCacheAllocNodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KmemCacheAllocNodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes_alloc() const { return at<1>().valid(); }
+ uint64_t bytes_alloc() const { return at<1>().as_uint64(); }
+ bool has_bytes_req() const { return at<2>().valid(); }
+ uint64_t bytes_req() const { return at<2>().as_uint64(); }
+ bool has_call_site() const { return at<3>().valid(); }
+ uint64_t call_site() const { return at<3>().as_uint64(); }
+ bool has_gfp_flags() const { return at<4>().valid(); }
+ uint32_t gfp_flags() const { return at<4>().as_uint32(); }
+ bool has_node() const { return at<5>().valid(); }
+ int32_t node() const { return at<5>().as_int32(); }
+ bool has_ptr() const { return at<6>().valid(); }
+ uint64_t ptr() const { return at<6>().as_uint64(); }
+};
+
+class KmemCacheAllocNodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KmemCacheAllocNodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesAllocFieldNumber = 1,
+ kBytesReqFieldNumber = 2,
+ kCallSiteFieldNumber = 3,
+ kGfpFlagsFieldNumber = 4,
+ kNodeFieldNumber = 5,
+ kPtrFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KmemCacheAllocNodeFtraceEvent"; }
+
+
+ using FieldMetadata_BytesAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesAlloc kBytesAlloc{};
+ void set_bytes_alloc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesAlloc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesReq =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesReq kBytesReq{};
+ void set_bytes_req(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesReq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CallSite =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_CallSite kCallSite{};
+ void set_call_site(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallSite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KmemCacheAllocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Node =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KmemCacheAllocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Node kNode{};
+ void set_node(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Node::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ptr =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ptr kPtr{};
+ void set_ptr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ptr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KmemCacheAllocFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KmemCacheAllocFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KmemCacheAllocFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KmemCacheAllocFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes_alloc() const { return at<1>().valid(); }
+ uint64_t bytes_alloc() const { return at<1>().as_uint64(); }
+ bool has_bytes_req() const { return at<2>().valid(); }
+ uint64_t bytes_req() const { return at<2>().as_uint64(); }
+ bool has_call_site() const { return at<3>().valid(); }
+ uint64_t call_site() const { return at<3>().as_uint64(); }
+ bool has_gfp_flags() const { return at<4>().valid(); }
+ uint32_t gfp_flags() const { return at<4>().as_uint32(); }
+ bool has_ptr() const { return at<5>().valid(); }
+ uint64_t ptr() const { return at<5>().as_uint64(); }
+};
+
+class KmemCacheAllocFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KmemCacheAllocFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesAllocFieldNumber = 1,
+ kBytesReqFieldNumber = 2,
+ kCallSiteFieldNumber = 3,
+ kGfpFlagsFieldNumber = 4,
+ kPtrFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KmemCacheAllocFtraceEvent"; }
+
+
+ using FieldMetadata_BytesAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesAlloc kBytesAlloc{};
+ void set_bytes_alloc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesAlloc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesReq =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesReq kBytesReq{};
+ void set_bytes_req(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesReq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CallSite =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_CallSite kCallSite{};
+ void set_call_site(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallSite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KmemCacheAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ptr =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmemCacheAllocFtraceEvent>;
+
+ static constexpr FieldMetadata_Ptr kPtr{};
+ void set_ptr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ptr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KmallocNodeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KmallocNodeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KmallocNodeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KmallocNodeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes_alloc() const { return at<1>().valid(); }
+ uint64_t bytes_alloc() const { return at<1>().as_uint64(); }
+ bool has_bytes_req() const { return at<2>().valid(); }
+ uint64_t bytes_req() const { return at<2>().as_uint64(); }
+ bool has_call_site() const { return at<3>().valid(); }
+ uint64_t call_site() const { return at<3>().as_uint64(); }
+ bool has_gfp_flags() const { return at<4>().valid(); }
+ uint32_t gfp_flags() const { return at<4>().as_uint32(); }
+ bool has_node() const { return at<5>().valid(); }
+ int32_t node() const { return at<5>().as_int32(); }
+ bool has_ptr() const { return at<6>().valid(); }
+ uint64_t ptr() const { return at<6>().as_uint64(); }
+};
+
+class KmallocNodeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KmallocNodeFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesAllocFieldNumber = 1,
+ kBytesReqFieldNumber = 2,
+ kCallSiteFieldNumber = 3,
+ kGfpFlagsFieldNumber = 4,
+ kNodeFieldNumber = 5,
+ kPtrFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KmallocNodeFtraceEvent"; }
+
+
+ using FieldMetadata_BytesAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesAlloc kBytesAlloc{};
+ void set_bytes_alloc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesAlloc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesReq =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesReq kBytesReq{};
+ void set_bytes_req(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesReq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CallSite =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_CallSite kCallSite{};
+ void set_call_site(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallSite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KmallocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Node =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KmallocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Node kNode{};
+ void set_node(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Node::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ptr =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocNodeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ptr kPtr{};
+ void set_ptr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ptr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KmallocFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KmallocFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KmallocFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KmallocFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytes_alloc() const { return at<1>().valid(); }
+ uint64_t bytes_alloc() const { return at<1>().as_uint64(); }
+ bool has_bytes_req() const { return at<2>().valid(); }
+ uint64_t bytes_req() const { return at<2>().as_uint64(); }
+ bool has_call_site() const { return at<3>().valid(); }
+ uint64_t call_site() const { return at<3>().as_uint64(); }
+ bool has_gfp_flags() const { return at<4>().valid(); }
+ uint32_t gfp_flags() const { return at<4>().as_uint32(); }
+ bool has_ptr() const { return at<5>().valid(); }
+ uint64_t ptr() const { return at<5>().as_uint64(); }
+};
+
+class KmallocFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KmallocFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesAllocFieldNumber = 1,
+ kBytesReqFieldNumber = 2,
+ kCallSiteFieldNumber = 3,
+ kGfpFlagsFieldNumber = 4,
+ kPtrFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KmallocFtraceEvent"; }
+
+
+ using FieldMetadata_BytesAlloc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesAlloc kBytesAlloc{};
+ void set_bytes_alloc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesAlloc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BytesReq =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocFtraceEvent>;
+
+ static constexpr FieldMetadata_BytesReq kBytesReq{};
+ void set_bytes_req(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BytesReq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CallSite =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocFtraceEvent>;
+
+ static constexpr FieldMetadata_CallSite kCallSite{};
+ void set_call_site(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallSite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KmallocFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ptr =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KmallocFtraceEvent>;
+
+ static constexpr FieldMetadata_Ptr kPtr{};
+ void set_ptr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ptr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KfreeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KfreeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KfreeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KfreeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_call_site() const { return at<1>().valid(); }
+ uint64_t call_site() const { return at<1>().as_uint64(); }
+ bool has_ptr() const { return at<2>().valid(); }
+ uint64_t ptr() const { return at<2>().as_uint64(); }
+};
+
+class KfreeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KfreeFtraceEvent_Decoder;
+ enum : int32_t {
+ kCallSiteFieldNumber = 1,
+ kPtrFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KfreeFtraceEvent"; }
+
+
+ using FieldMetadata_CallSite =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KfreeFtraceEvent>;
+
+ static constexpr FieldMetadata_CallSite kCallSite{};
+ void set_call_site(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallSite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ptr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KfreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Ptr kPtr{};
+ void set_ptr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ptr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonSecureCmaShrinkPoolStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonSecureCmaShrinkPoolStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonSecureCmaShrinkPoolStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonSecureCmaShrinkPoolStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_drained_size() const { return at<1>().valid(); }
+ uint64_t drained_size() const { return at<1>().as_uint64(); }
+ bool has_skipped_size() const { return at<2>().valid(); }
+ uint64_t skipped_size() const { return at<2>().as_uint64(); }
+};
+
+class IonSecureCmaShrinkPoolStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonSecureCmaShrinkPoolStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kDrainedSizeFieldNumber = 1,
+ kSkippedSizeFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonSecureCmaShrinkPoolStartFtraceEvent"; }
+
+
+ using FieldMetadata_DrainedSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaShrinkPoolStartFtraceEvent>;
+
+ static constexpr FieldMetadata_DrainedSize kDrainedSize{};
+ void set_drained_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DrainedSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkippedSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaShrinkPoolStartFtraceEvent>;
+
+ static constexpr FieldMetadata_SkippedSize kSkippedSize{};
+ void set_skipped_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkippedSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonSecureCmaShrinkPoolEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonSecureCmaShrinkPoolEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonSecureCmaShrinkPoolEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonSecureCmaShrinkPoolEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_drained_size() const { return at<1>().valid(); }
+ uint64_t drained_size() const { return at<1>().as_uint64(); }
+ bool has_skipped_size() const { return at<2>().valid(); }
+ uint64_t skipped_size() const { return at<2>().as_uint64(); }
+};
+
+class IonSecureCmaShrinkPoolEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonSecureCmaShrinkPoolEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kDrainedSizeFieldNumber = 1,
+ kSkippedSizeFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonSecureCmaShrinkPoolEndFtraceEvent"; }
+
+
+ using FieldMetadata_DrainedSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaShrinkPoolEndFtraceEvent>;
+
+ static constexpr FieldMetadata_DrainedSize kDrainedSize{};
+ void set_drained_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DrainedSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkippedSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaShrinkPoolEndFtraceEvent>;
+
+ static constexpr FieldMetadata_SkippedSize kSkippedSize{};
+ void set_skipped_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkippedSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonSecureCmaAllocateStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonSecureCmaAllocateStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonSecureCmaAllocateStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonSecureCmaAllocateStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_align() const { return at<1>().valid(); }
+ uint64_t align() const { return at<1>().as_uint64(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint64_t flags() const { return at<2>().as_uint64(); }
+ bool has_heap_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<3>().as_string(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+};
+
+class IonSecureCmaAllocateStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonSecureCmaAllocateStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kAlignFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kHeapNameFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonSecureCmaAllocateStartFtraceEvent"; }
+
+
+ using FieldMetadata_Align =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAllocateStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Align kAlign{};
+ void set_align(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Align::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAllocateStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonSecureCmaAllocateStartFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAllocateStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonSecureCmaAllocateEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonSecureCmaAllocateEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonSecureCmaAllocateEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonSecureCmaAllocateEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_align() const { return at<1>().valid(); }
+ uint64_t align() const { return at<1>().as_uint64(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint64_t flags() const { return at<2>().as_uint64(); }
+ bool has_heap_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<3>().as_string(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+};
+
+class IonSecureCmaAllocateEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonSecureCmaAllocateEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kAlignFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kHeapNameFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonSecureCmaAllocateEndFtraceEvent"; }
+
+
+ using FieldMetadata_Align =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAllocateEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Align kAlign{};
+ void set_align(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Align::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAllocateEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonSecureCmaAllocateEndFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAllocateEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonSecureCmaAddToPoolStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonSecureCmaAddToPoolStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonSecureCmaAddToPoolStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonSecureCmaAddToPoolStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_is_prefetch() const { return at<1>().valid(); }
+ uint32_t is_prefetch() const { return at<1>().as_uint32(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+ bool has_pool_total() const { return at<3>().valid(); }
+ int32_t pool_total() const { return at<3>().as_int32(); }
+};
+
+class IonSecureCmaAddToPoolStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonSecureCmaAddToPoolStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kIsPrefetchFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kPoolTotalFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonSecureCmaAddToPoolStartFtraceEvent"; }
+
+
+ using FieldMetadata_IsPrefetch =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonSecureCmaAddToPoolStartFtraceEvent>;
+
+ static constexpr FieldMetadata_IsPrefetch kIsPrefetch{};
+ void set_is_prefetch(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsPrefetch::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAddToPoolStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PoolTotal =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IonSecureCmaAddToPoolStartFtraceEvent>;
+
+ static constexpr FieldMetadata_PoolTotal kPoolTotal{};
+ void set_pool_total(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PoolTotal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonSecureCmaAddToPoolEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonSecureCmaAddToPoolEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonSecureCmaAddToPoolEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonSecureCmaAddToPoolEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_is_prefetch() const { return at<1>().valid(); }
+ uint32_t is_prefetch() const { return at<1>().as_uint32(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+ bool has_pool_total() const { return at<3>().valid(); }
+ int32_t pool_total() const { return at<3>().as_int32(); }
+};
+
+class IonSecureCmaAddToPoolEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonSecureCmaAddToPoolEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kIsPrefetchFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kPoolTotalFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonSecureCmaAddToPoolEndFtraceEvent"; }
+
+
+ using FieldMetadata_IsPrefetch =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonSecureCmaAddToPoolEndFtraceEvent>;
+
+ static constexpr FieldMetadata_IsPrefetch kIsPrefetch{};
+ void set_is_prefetch(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsPrefetch::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonSecureCmaAddToPoolEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PoolTotal =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IonSecureCmaAddToPoolEndFtraceEvent>;
+
+ static constexpr FieldMetadata_PoolTotal kPoolTotal{};
+ void set_pool_total(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PoolTotal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonPrefetchingFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonPrefetchingFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonPrefetchingFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonPrefetchingFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_len() const { return at<1>().valid(); }
+ uint64_t len() const { return at<1>().as_uint64(); }
+};
+
+class IonPrefetchingFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonPrefetchingFtraceEvent_Decoder;
+ enum : int32_t {
+ kLenFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonPrefetchingFtraceEvent"; }
+
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonPrefetchingFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonCpSecureBufferStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonCpSecureBufferStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonCpSecureBufferStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonCpSecureBufferStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_align() const { return at<1>().valid(); }
+ uint64_t align() const { return at<1>().as_uint64(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint64_t flags() const { return at<2>().as_uint64(); }
+ bool has_heap_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<3>().as_string(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+};
+
+class IonCpSecureBufferStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonCpSecureBufferStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kAlignFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kHeapNameFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonCpSecureBufferStartFtraceEvent"; }
+
+
+ using FieldMetadata_Align =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonCpSecureBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Align kAlign{};
+ void set_align(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Align::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonCpSecureBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonCpSecureBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonCpSecureBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonCpSecureBufferEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonCpSecureBufferEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonCpSecureBufferEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonCpSecureBufferEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_align() const { return at<1>().valid(); }
+ uint64_t align() const { return at<1>().as_uint64(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint64_t flags() const { return at<2>().as_uint64(); }
+ bool has_heap_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<3>().as_string(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+};
+
+class IonCpSecureBufferEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonCpSecureBufferEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kAlignFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kHeapNameFieldNumber = 3,
+ kLenFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonCpSecureBufferEndFtraceEvent"; }
+
+
+ using FieldMetadata_Align =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonCpSecureBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Align kAlign{};
+ void set_align(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Align::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonCpSecureBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonCpSecureBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonCpSecureBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonCpAllocRetryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonCpAllocRetryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonCpAllocRetryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonCpAllocRetryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tries() const { return at<1>().valid(); }
+ int32_t tries() const { return at<1>().as_int32(); }
+};
+
+class IonCpAllocRetryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonCpAllocRetryFtraceEvent_Decoder;
+ enum : int32_t {
+ kTriesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonCpAllocRetryFtraceEvent"; }
+
+
+ using FieldMetadata_Tries =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IonCpAllocRetryFtraceEvent>;
+
+ static constexpr FieldMetadata_Tries kTries{};
+ void set_tries(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tries::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonAllocBufferStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonAllocBufferStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonAllocBufferStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonAllocBufferStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_client_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars client_name() const { return at<1>().as_string(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_heap_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<3>().as_string(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+ bool has_mask() const { return at<5>().valid(); }
+ uint32_t mask() const { return at<5>().as_uint32(); }
+};
+
+class IonAllocBufferStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonAllocBufferStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kClientNameFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kHeapNameFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kMaskFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonAllocBufferStartFtraceEvent"; }
+
+
+ using FieldMetadata_ClientName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_ClientName kClientName{};
+ void set_client_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, data, size);
+ }
+ void set_client_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, chars.data, chars.size);
+ }
+ void set_client_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClientName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonAllocBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mask =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Mask kMask{};
+ void set_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonAllocBufferFallbackFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonAllocBufferFallbackFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonAllocBufferFallbackFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonAllocBufferFallbackFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_client_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars client_name() const { return at<1>().as_string(); }
+ bool has_error() const { return at<2>().valid(); }
+ int64_t error() const { return at<2>().as_int64(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_heap_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<4>().as_string(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint64_t len() const { return at<5>().as_uint64(); }
+ bool has_mask() const { return at<6>().valid(); }
+ uint32_t mask() const { return at<6>().as_uint32(); }
+};
+
+class IonAllocBufferFallbackFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonAllocBufferFallbackFtraceEvent_Decoder;
+ enum : int32_t {
+ kClientNameFieldNumber = 1,
+ kErrorFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kHeapNameFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kMaskFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonAllocBufferFallbackFtraceEvent"; }
+
+
+ using FieldMetadata_ClientName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferFallbackFtraceEvent>;
+
+ static constexpr FieldMetadata_ClientName kClientName{};
+ void set_client_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, data, size);
+ }
+ void set_client_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, chars.data, chars.size);
+ }
+ void set_client_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClientName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Error =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ IonAllocBufferFallbackFtraceEvent>;
+
+ static constexpr FieldMetadata_Error kError{};
+ void set_error(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Error::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferFallbackFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferFallbackFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonAllocBufferFallbackFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mask =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferFallbackFtraceEvent>;
+
+ static constexpr FieldMetadata_Mask kMask{};
+ void set_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonAllocBufferFailFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonAllocBufferFailFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonAllocBufferFailFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonAllocBufferFailFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_client_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars client_name() const { return at<1>().as_string(); }
+ bool has_error() const { return at<2>().valid(); }
+ int64_t error() const { return at<2>().as_int64(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_heap_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<4>().as_string(); }
+ bool has_len() const { return at<5>().valid(); }
+ uint64_t len() const { return at<5>().as_uint64(); }
+ bool has_mask() const { return at<6>().valid(); }
+ uint32_t mask() const { return at<6>().as_uint32(); }
+};
+
+class IonAllocBufferFailFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonAllocBufferFailFtraceEvent_Decoder;
+ enum : int32_t {
+ kClientNameFieldNumber = 1,
+ kErrorFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kHeapNameFieldNumber = 4,
+ kLenFieldNumber = 5,
+ kMaskFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonAllocBufferFailFtraceEvent"; }
+
+
+ using FieldMetadata_ClientName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferFailFtraceEvent>;
+
+ static constexpr FieldMetadata_ClientName kClientName{};
+ void set_client_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, data, size);
+ }
+ void set_client_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, chars.data, chars.size);
+ }
+ void set_client_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClientName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Error =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ IonAllocBufferFailFtraceEvent>;
+
+ static constexpr FieldMetadata_Error kError{};
+ void set_error(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Error::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferFailFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferFailFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonAllocBufferFailFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mask =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferFailFtraceEvent>;
+
+ static constexpr FieldMetadata_Mask kMask{};
+ void set_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IonAllocBufferEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IonAllocBufferEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IonAllocBufferEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IonAllocBufferEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_client_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars client_name() const { return at<1>().as_string(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_heap_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<3>().as_string(); }
+ bool has_len() const { return at<4>().valid(); }
+ uint64_t len() const { return at<4>().as_uint64(); }
+ bool has_mask() const { return at<5>().valid(); }
+ uint32_t mask() const { return at<5>().as_uint32(); }
+};
+
+class IonAllocBufferEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IonAllocBufferEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kClientNameFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kHeapNameFieldNumber = 3,
+ kLenFieldNumber = 4,
+ kMaskFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IonAllocBufferEndFtraceEvent"; }
+
+
+ using FieldMetadata_ClientName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_ClientName kClientName{};
+ void set_client_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, data, size);
+ }
+ void set_client_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ClientName::kFieldId, chars.data, chars.size);
+ }
+ void set_client_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClientName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ IonAllocBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IonAllocBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mask =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IonAllocBufferEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Mask kMask{};
+ void set_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IommuSecPtblMapRangeStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IommuSecPtblMapRangeStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IommuSecPtblMapRangeStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IommuSecPtblMapRangeStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_len() const { return at<1>().valid(); }
+ uint64_t len() const { return at<1>().as_uint64(); }
+ bool has_num() const { return at<2>().valid(); }
+ int32_t num() const { return at<2>().as_int32(); }
+ bool has_pa() const { return at<3>().valid(); }
+ uint32_t pa() const { return at<3>().as_uint32(); }
+ bool has_sec_id() const { return at<4>().valid(); }
+ int32_t sec_id() const { return at<4>().as_int32(); }
+ bool has_va() const { return at<5>().valid(); }
+ uint64_t va() const { return at<5>().as_uint64(); }
+};
+
+class IommuSecPtblMapRangeStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IommuSecPtblMapRangeStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kLenFieldNumber = 1,
+ kNumFieldNumber = 2,
+ kPaFieldNumber = 3,
+ kSecIdFieldNumber = 4,
+ kVaFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IommuSecPtblMapRangeStartFtraceEvent"; }
+
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuSecPtblMapRangeStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Num =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IommuSecPtblMapRangeStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Num kNum{};
+ void set_num(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Num::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pa =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IommuSecPtblMapRangeStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Pa kPa{};
+ void set_pa(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SecId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IommuSecPtblMapRangeStartFtraceEvent>;
+
+ static constexpr FieldMetadata_SecId kSecId{};
+ void set_sec_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SecId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Va =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuSecPtblMapRangeStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Va kVa{};
+ void set_va(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Va::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IommuSecPtblMapRangeEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IommuSecPtblMapRangeEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IommuSecPtblMapRangeEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IommuSecPtblMapRangeEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_len() const { return at<1>().valid(); }
+ uint64_t len() const { return at<1>().as_uint64(); }
+ bool has_num() const { return at<2>().valid(); }
+ int32_t num() const { return at<2>().as_int32(); }
+ bool has_pa() const { return at<3>().valid(); }
+ uint32_t pa() const { return at<3>().as_uint32(); }
+ bool has_sec_id() const { return at<4>().valid(); }
+ int32_t sec_id() const { return at<4>().as_int32(); }
+ bool has_va() const { return at<5>().valid(); }
+ uint64_t va() const { return at<5>().as_uint64(); }
+};
+
+class IommuSecPtblMapRangeEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IommuSecPtblMapRangeEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kLenFieldNumber = 1,
+ kNumFieldNumber = 2,
+ kPaFieldNumber = 3,
+ kSecIdFieldNumber = 4,
+ kVaFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IommuSecPtblMapRangeEndFtraceEvent"; }
+
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuSecPtblMapRangeEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Num =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IommuSecPtblMapRangeEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Num kNum{};
+ void set_num(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Num::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pa =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ IommuSecPtblMapRangeEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Pa kPa{};
+ void set_pa(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SecId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ IommuSecPtblMapRangeEndFtraceEvent>;
+
+ static constexpr FieldMetadata_SecId kSecId{};
+ void set_sec_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SecId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Va =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuSecPtblMapRangeEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Va kVa{};
+ void set_va(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Va::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class IommuMapRangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ IommuMapRangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit IommuMapRangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit IommuMapRangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chunk_size() const { return at<1>().valid(); }
+ uint64_t chunk_size() const { return at<1>().as_uint64(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+ bool has_pa() const { return at<3>().valid(); }
+ uint64_t pa() const { return at<3>().as_uint64(); }
+ bool has_va() const { return at<4>().valid(); }
+ uint64_t va() const { return at<4>().as_uint64(); }
+};
+
+class IommuMapRangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = IommuMapRangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kChunkSizeFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kPaFieldNumber = 3,
+ kVaFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.IommuMapRangeFtraceEvent"; }
+
+
+ using FieldMetadata_ChunkSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuMapRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_ChunkSize kChunkSize{};
+ void set_chunk_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChunkSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuMapRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pa =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuMapRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Pa kPa{};
+ void set_pa(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Va =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ IommuMapRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Va kVa{};
+ void set_va(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Va::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DmaAllocContiguousRetryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DmaAllocContiguousRetryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DmaAllocContiguousRetryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DmaAllocContiguousRetryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tries() const { return at<1>().valid(); }
+ int32_t tries() const { return at<1>().as_int32(); }
+};
+
+class DmaAllocContiguousRetryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DmaAllocContiguousRetryFtraceEvent_Decoder;
+ enum : int32_t {
+ kTriesFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DmaAllocContiguousRetryFtraceEvent"; }
+
+
+ using FieldMetadata_Tries =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ DmaAllocContiguousRetryFtraceEvent>;
+
+ static constexpr FieldMetadata_Tries kTries{};
+ void set_tries(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tries::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AllocPagesSysStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AllocPagesSysStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AllocPagesSysStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AllocPagesSysStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfp_flags() const { return at<1>().valid(); }
+ uint32_t gfp_flags() const { return at<1>().as_uint32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+};
+
+class AllocPagesSysStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AllocPagesSysStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfpFlagsFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AllocPagesSysStartFtraceEvent"; }
+
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesSysStartFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesSysStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AllocPagesSysFailFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AllocPagesSysFailFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AllocPagesSysFailFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AllocPagesSysFailFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfp_flags() const { return at<1>().valid(); }
+ uint32_t gfp_flags() const { return at<1>().as_uint32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+};
+
+class AllocPagesSysFailFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AllocPagesSysFailFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfpFlagsFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AllocPagesSysFailFtraceEvent"; }
+
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesSysFailFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesSysFailFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AllocPagesSysEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AllocPagesSysEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AllocPagesSysEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AllocPagesSysEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfp_flags() const { return at<1>().valid(); }
+ uint32_t gfp_flags() const { return at<1>().as_uint32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+};
+
+class AllocPagesSysEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AllocPagesSysEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfpFlagsFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AllocPagesSysEndFtraceEvent"; }
+
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesSysEndFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesSysEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AllocPagesIommuStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AllocPagesIommuStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AllocPagesIommuStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AllocPagesIommuStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfp_flags() const { return at<1>().valid(); }
+ uint32_t gfp_flags() const { return at<1>().as_uint32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+};
+
+class AllocPagesIommuStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AllocPagesIommuStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfpFlagsFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AllocPagesIommuStartFtraceEvent"; }
+
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesIommuStartFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesIommuStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AllocPagesIommuFailFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AllocPagesIommuFailFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AllocPagesIommuFailFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AllocPagesIommuFailFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfp_flags() const { return at<1>().valid(); }
+ uint32_t gfp_flags() const { return at<1>().as_uint32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+};
+
+class AllocPagesIommuFailFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AllocPagesIommuFailFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfpFlagsFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AllocPagesIommuFailFtraceEvent"; }
+
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesIommuFailFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesIommuFailFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class AllocPagesIommuEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AllocPagesIommuEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AllocPagesIommuEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AllocPagesIommuEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfp_flags() const { return at<1>().valid(); }
+ uint32_t gfp_flags() const { return at<1>().as_uint32(); }
+ bool has_order() const { return at<2>().valid(); }
+ uint32_t order() const { return at<2>().as_uint32(); }
+};
+
+class AllocPagesIommuEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = AllocPagesIommuEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfpFlagsFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AllocPagesIommuEndFtraceEvent"; }
+
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesIommuEndFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ AllocPagesIommuEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/kvm.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_KVM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_KVM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class VgicUpdateIrqPendingFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VgicUpdateIrqPendingFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VgicUpdateIrqPendingFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VgicUpdateIrqPendingFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irq() const { return at<1>().valid(); }
+ uint32_t irq() const { return at<1>().as_uint32(); }
+ bool has_level() const { return at<2>().valid(); }
+ uint32_t level() const { return at<2>().as_uint32(); }
+ bool has_vcpu_id() const { return at<3>().valid(); }
+ uint64_t vcpu_id() const { return at<3>().as_uint64(); }
+};
+
+class VgicUpdateIrqPendingFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = VgicUpdateIrqPendingFtraceEvent_Decoder;
+ enum : int32_t {
+ kIrqFieldNumber = 1,
+ kLevelFieldNumber = 2,
+ kVcpuIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VgicUpdateIrqPendingFtraceEvent"; }
+
+
+ using FieldMetadata_Irq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VgicUpdateIrqPendingFtraceEvent>;
+
+ static constexpr FieldMetadata_Irq kIrq{};
+ void set_irq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Irq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VgicUpdateIrqPendingFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VgicUpdateIrqPendingFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuId kVcpuId{};
+ void set_vcpu_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrapRegFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrapRegFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrapRegFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrapRegFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_fn() const { return at<1>().valid(); }
+ ::protozero::ConstChars fn() const { return at<1>().as_string(); }
+ bool has_is_write() const { return at<2>().valid(); }
+ uint32_t is_write() const { return at<2>().as_uint32(); }
+ bool has_reg() const { return at<3>().valid(); }
+ int32_t reg() const { return at<3>().as_int32(); }
+ bool has_write_value() const { return at<4>().valid(); }
+ uint64_t write_value() const { return at<4>().as_uint64(); }
+};
+
+class TrapRegFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrapRegFtraceEvent_Decoder;
+ enum : int32_t {
+ kFnFieldNumber = 1,
+ kIsWriteFieldNumber = 2,
+ kRegFieldNumber = 3,
+ kWriteValueFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrapRegFtraceEvent"; }
+
+
+ using FieldMetadata_Fn =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrapRegFtraceEvent>;
+
+ static constexpr FieldMetadata_Fn kFn{};
+ void set_fn(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Fn::kFieldId, data, size);
+ }
+ void set_fn(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Fn::kFieldId, chars.data, chars.size);
+ }
+ void set_fn(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrapRegFtraceEvent>;
+
+ static constexpr FieldMetadata_IsWrite kIsWrite{};
+ void set_is_write(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsWrite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Reg =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrapRegFtraceEvent>;
+
+ static constexpr FieldMetadata_Reg kReg{};
+ void set_reg(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WriteValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrapRegFtraceEvent>;
+
+ static constexpr FieldMetadata_WriteValue kWriteValue{};
+ void set_write_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WriteValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmWfxArm64FtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmWfxArm64FtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmWfxArm64FtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmWfxArm64FtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_is_wfe() const { return at<1>().valid(); }
+ uint32_t is_wfe() const { return at<1>().as_uint32(); }
+ bool has_vcpu_pc() const { return at<2>().valid(); }
+ uint64_t vcpu_pc() const { return at<2>().as_uint64(); }
+};
+
+class KvmWfxArm64FtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmWfxArm64FtraceEvent_Decoder;
+ enum : int32_t {
+ kIsWfeFieldNumber = 1,
+ kVcpuPcFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmWfxArm64FtraceEvent"; }
+
+
+ using FieldMetadata_IsWfe =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmWfxArm64FtraceEvent>;
+
+ static constexpr FieldMetadata_IsWfe kIsWfe{};
+ void set_is_wfe(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsWfe::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmWfxArm64FtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmVcpuWakeupFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmVcpuWakeupFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmVcpuWakeupFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmVcpuWakeupFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ns() const { return at<1>().valid(); }
+ uint64_t ns() const { return at<1>().as_uint64(); }
+ bool has_valid() const { return at<2>().valid(); }
+ uint32_t valid() const { return at<2>().as_uint32(); }
+ bool has_waited() const { return at<3>().valid(); }
+ uint32_t waited() const { return at<3>().as_uint32(); }
+};
+
+class KvmVcpuWakeupFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmVcpuWakeupFtraceEvent_Decoder;
+ enum : int32_t {
+ kNsFieldNumber = 1,
+ kValidFieldNumber = 2,
+ kWaitedFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmVcpuWakeupFtraceEvent"; }
+
+
+ using FieldMetadata_Ns =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmVcpuWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_Ns kNs{};
+ void set_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ns::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Valid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmVcpuWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_Valid kValid{};
+ void set_valid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Valid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Waited =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmVcpuWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_Waited kWaited{};
+ void set_waited(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Waited::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmUserspaceExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmUserspaceExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmUserspaceExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmUserspaceExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_reason() const { return at<1>().valid(); }
+ uint32_t reason() const { return at<1>().as_uint32(); }
+};
+
+class KvmUserspaceExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmUserspaceExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kReasonFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmUserspaceExitFtraceEvent"; }
+
+
+ using FieldMetadata_Reason =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmUserspaceExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Reason kReason{};
+ void set_reason(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmUnmapHvaRangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmUnmapHvaRangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmUnmapHvaRangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmUnmapHvaRangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_end() const { return at<1>().valid(); }
+ uint64_t end() const { return at<1>().as_uint64(); }
+ bool has_start() const { return at<2>().valid(); }
+ uint64_t start() const { return at<2>().as_uint64(); }
+};
+
+class KvmUnmapHvaRangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmUnmapHvaRangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kEndFieldNumber = 1,
+ kStartFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmUnmapHvaRangeFtraceEvent"; }
+
+
+ using FieldMetadata_End =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmUnmapHvaRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_End kEnd{};
+ void set_end(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_End::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmUnmapHvaRangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmToggleCacheFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmToggleCacheFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmToggleCacheFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmToggleCacheFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_now() const { return at<1>().valid(); }
+ uint32_t now() const { return at<1>().as_uint32(); }
+ bool has_vcpu_pc() const { return at<2>().valid(); }
+ uint64_t vcpu_pc() const { return at<2>().as_uint64(); }
+ bool has_was() const { return at<3>().valid(); }
+ uint32_t was() const { return at<3>().as_uint32(); }
+};
+
+class KvmToggleCacheFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmToggleCacheFtraceEvent_Decoder;
+ enum : int32_t {
+ kNowFieldNumber = 1,
+ kVcpuPcFieldNumber = 2,
+ kWasFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmToggleCacheFtraceEvent"; }
+
+
+ using FieldMetadata_Now =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmToggleCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Now kNow{};
+ void set_now(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Now::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmToggleCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Was =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmToggleCacheFtraceEvent>;
+
+ static constexpr FieldMetadata_Was kWas{};
+ void set_was(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Was::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmTimerUpdateIrqFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmTimerUpdateIrqFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmTimerUpdateIrqFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmTimerUpdateIrqFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irq() const { return at<1>().valid(); }
+ uint32_t irq() const { return at<1>().as_uint32(); }
+ bool has_level() const { return at<2>().valid(); }
+ int32_t level() const { return at<2>().as_int32(); }
+ bool has_vcpu_id() const { return at<3>().valid(); }
+ uint64_t vcpu_id() const { return at<3>().as_uint64(); }
+};
+
+class KvmTimerUpdateIrqFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmTimerUpdateIrqFtraceEvent_Decoder;
+ enum : int32_t {
+ kIrqFieldNumber = 1,
+ kLevelFieldNumber = 2,
+ kVcpuIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmTimerUpdateIrqFtraceEvent"; }
+
+
+ using FieldMetadata_Irq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmTimerUpdateIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Irq kIrq{};
+ void set_irq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Irq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmTimerUpdateIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmTimerUpdateIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuId kVcpuId{};
+ void set_vcpu_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmTimerSaveStateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmTimerSaveStateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmTimerSaveStateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmTimerSaveStateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl() const { return at<1>().valid(); }
+ uint64_t ctl() const { return at<1>().as_uint64(); }
+ bool has_cval() const { return at<2>().valid(); }
+ uint64_t cval() const { return at<2>().as_uint64(); }
+ bool has_timer_idx() const { return at<3>().valid(); }
+ int32_t timer_idx() const { return at<3>().as_int32(); }
+};
+
+class KvmTimerSaveStateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmTimerSaveStateFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlFieldNumber = 1,
+ kCvalFieldNumber = 2,
+ kTimerIdxFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmTimerSaveStateFtraceEvent"; }
+
+
+ using FieldMetadata_Ctl =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmTimerSaveStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctl kCtl{};
+ void set_ctl(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctl::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cval =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmTimerSaveStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Cval kCval{};
+ void set_cval(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cval::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimerIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmTimerSaveStateFtraceEvent>;
+
+ static constexpr FieldMetadata_TimerIdx kTimerIdx{};
+ void set_timer_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimerIdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmTimerRestoreStateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmTimerRestoreStateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmTimerRestoreStateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmTimerRestoreStateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl() const { return at<1>().valid(); }
+ uint64_t ctl() const { return at<1>().as_uint64(); }
+ bool has_cval() const { return at<2>().valid(); }
+ uint64_t cval() const { return at<2>().as_uint64(); }
+ bool has_timer_idx() const { return at<3>().valid(); }
+ int32_t timer_idx() const { return at<3>().as_int32(); }
+};
+
+class KvmTimerRestoreStateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmTimerRestoreStateFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlFieldNumber = 1,
+ kCvalFieldNumber = 2,
+ kTimerIdxFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmTimerRestoreStateFtraceEvent"; }
+
+
+ using FieldMetadata_Ctl =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmTimerRestoreStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctl kCtl{};
+ void set_ctl(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctl::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cval =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmTimerRestoreStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Cval kCval{};
+ void set_cval(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cval::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimerIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmTimerRestoreStateFtraceEvent>;
+
+ static constexpr FieldMetadata_TimerIdx kTimerIdx{};
+ void set_timer_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimerIdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmTimerHrtimerExpireFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmTimerHrtimerExpireFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmTimerHrtimerExpireFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmTimerHrtimerExpireFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timer_idx() const { return at<1>().valid(); }
+ int32_t timer_idx() const { return at<1>().as_int32(); }
+};
+
+class KvmTimerHrtimerExpireFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmTimerHrtimerExpireFtraceEvent_Decoder;
+ enum : int32_t {
+ kTimerIdxFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmTimerHrtimerExpireFtraceEvent"; }
+
+
+ using FieldMetadata_TimerIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmTimerHrtimerExpireFtraceEvent>;
+
+ static constexpr FieldMetadata_TimerIdx kTimerIdx{};
+ void set_timer_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimerIdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmTimerEmulateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmTimerEmulateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmTimerEmulateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmTimerEmulateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_should_fire() const { return at<1>().valid(); }
+ uint32_t should_fire() const { return at<1>().as_uint32(); }
+ bool has_timer_idx() const { return at<2>().valid(); }
+ int32_t timer_idx() const { return at<2>().as_int32(); }
+};
+
+class KvmTimerEmulateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmTimerEmulateFtraceEvent_Decoder;
+ enum : int32_t {
+ kShouldFireFieldNumber = 1,
+ kTimerIdxFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmTimerEmulateFtraceEvent"; }
+
+
+ using FieldMetadata_ShouldFire =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmTimerEmulateFtraceEvent>;
+
+ static constexpr FieldMetadata_ShouldFire kShouldFire{};
+ void set_should_fire(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShouldFire::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimerIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmTimerEmulateFtraceEvent>;
+
+ static constexpr FieldMetadata_TimerIdx kTimerIdx{};
+ void set_timer_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimerIdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmTestAgeHvaFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmTestAgeHvaFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmTestAgeHvaFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmTestAgeHvaFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_hva() const { return at<1>().valid(); }
+ uint64_t hva() const { return at<1>().as_uint64(); }
+};
+
+class KvmTestAgeHvaFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmTestAgeHvaFtraceEvent_Decoder;
+ enum : int32_t {
+ kHvaFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmTestAgeHvaFtraceEvent"; }
+
+
+ using FieldMetadata_Hva =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmTestAgeHvaFtraceEvent>;
+
+ static constexpr FieldMetadata_Hva kHva{};
+ void set_hva(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hva::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmSysAccessFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmSysAccessFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmSysAccessFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmSysAccessFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_crm() const { return at<1>().valid(); }
+ uint32_t crm() const { return at<1>().as_uint32(); }
+ bool has_crn() const { return at<2>().valid(); }
+ uint32_t crn() const { return at<2>().as_uint32(); }
+ bool has_op0() const { return at<3>().valid(); }
+ uint32_t op0() const { return at<3>().as_uint32(); }
+ bool has_op1() const { return at<4>().valid(); }
+ uint32_t op1() const { return at<4>().as_uint32(); }
+ bool has_op2() const { return at<5>().valid(); }
+ uint32_t op2() const { return at<5>().as_uint32(); }
+ bool has_is_write() const { return at<6>().valid(); }
+ uint32_t is_write() const { return at<6>().as_uint32(); }
+ bool has_name() const { return at<7>().valid(); }
+ ::protozero::ConstChars name() const { return at<7>().as_string(); }
+ bool has_vcpu_pc() const { return at<8>().valid(); }
+ uint64_t vcpu_pc() const { return at<8>().as_uint64(); }
+};
+
+class KvmSysAccessFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmSysAccessFtraceEvent_Decoder;
+ enum : int32_t {
+ kCRmFieldNumber = 1,
+ kCRnFieldNumber = 2,
+ kOp0FieldNumber = 3,
+ kOp1FieldNumber = 4,
+ kOp2FieldNumber = 5,
+ kIsWriteFieldNumber = 6,
+ kNameFieldNumber = 7,
+ kVcpuPcFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmSysAccessFtraceEvent"; }
+
+
+ using FieldMetadata_CRm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_CRm kCRm{};
+ void set_crm(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CRm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CRn =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_CRn kCRn{};
+ void set_crn(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CRn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Op0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_Op0 kOp0{};
+ void set_op0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Op0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Op1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_Op1 kOp1{};
+ void set_op1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Op1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Op2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_Op2 kOp2{};
+ void set_op2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Op2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsWrite =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_IsWrite kIsWrite{};
+ void set_is_write(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsWrite::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmSysAccessFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmSetWayFlushFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmSetWayFlushFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmSetWayFlushFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmSetWayFlushFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cache() const { return at<1>().valid(); }
+ uint32_t cache() const { return at<1>().as_uint32(); }
+ bool has_vcpu_pc() const { return at<2>().valid(); }
+ uint64_t vcpu_pc() const { return at<2>().as_uint64(); }
+};
+
+class KvmSetWayFlushFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmSetWayFlushFtraceEvent_Decoder;
+ enum : int32_t {
+ kCacheFieldNumber = 1,
+ kVcpuPcFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmSetWayFlushFtraceEvent"; }
+
+
+ using FieldMetadata_Cache =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSetWayFlushFtraceEvent>;
+
+ static constexpr FieldMetadata_Cache kCache{};
+ void set_cache(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cache::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmSetWayFlushFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmSetSpteHvaFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmSetSpteHvaFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmSetSpteHvaFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmSetSpteHvaFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_hva() const { return at<1>().valid(); }
+ uint64_t hva() const { return at<1>().as_uint64(); }
+};
+
+class KvmSetSpteHvaFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmSetSpteHvaFtraceEvent_Decoder;
+ enum : int32_t {
+ kHvaFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmSetSpteHvaFtraceEvent"; }
+
+
+ using FieldMetadata_Hva =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmSetSpteHvaFtraceEvent>;
+
+ static constexpr FieldMetadata_Hva kHva{};
+ void set_hva(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hva::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmSetIrqFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmSetIrqFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmSetIrqFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmSetIrqFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gsi() const { return at<1>().valid(); }
+ uint32_t gsi() const { return at<1>().as_uint32(); }
+ bool has_irq_source_id() const { return at<2>().valid(); }
+ int32_t irq_source_id() const { return at<2>().as_int32(); }
+ bool has_level() const { return at<3>().valid(); }
+ int32_t level() const { return at<3>().as_int32(); }
+};
+
+class KvmSetIrqFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmSetIrqFtraceEvent_Decoder;
+ enum : int32_t {
+ kGsiFieldNumber = 1,
+ kIrqSourceIdFieldNumber = 2,
+ kLevelFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmSetIrqFtraceEvent"; }
+
+
+ using FieldMetadata_Gsi =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSetIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Gsi kGsi{};
+ void set_gsi(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Gsi::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IrqSourceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmSetIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_IrqSourceId kIrqSourceId{};
+ void set_irq_source_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IrqSourceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmSetIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmSetGuestDebugFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmSetGuestDebugFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmSetGuestDebugFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmSetGuestDebugFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_guest_debug() const { return at<1>().valid(); }
+ uint32_t guest_debug() const { return at<1>().as_uint32(); }
+ bool has_vcpu() const { return at<2>().valid(); }
+ uint64_t vcpu() const { return at<2>().as_uint64(); }
+};
+
+class KvmSetGuestDebugFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmSetGuestDebugFtraceEvent_Decoder;
+ enum : int32_t {
+ kGuestDebugFieldNumber = 1,
+ kVcpuFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmSetGuestDebugFtraceEvent"; }
+
+
+ using FieldMetadata_GuestDebug =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmSetGuestDebugFtraceEvent>;
+
+ static constexpr FieldMetadata_GuestDebug kGuestDebug{};
+ void set_guest_debug(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GuestDebug::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Vcpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmSetGuestDebugFtraceEvent>;
+
+ static constexpr FieldMetadata_Vcpu kVcpu{};
+ void set_vcpu(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Vcpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmMmioEmulateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmMmioEmulateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmMmioEmulateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmMmioEmulateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpsr() const { return at<1>().valid(); }
+ uint64_t cpsr() const { return at<1>().as_uint64(); }
+ bool has_instr() const { return at<2>().valid(); }
+ uint64_t instr() const { return at<2>().as_uint64(); }
+ bool has_vcpu_pc() const { return at<3>().valid(); }
+ uint64_t vcpu_pc() const { return at<3>().as_uint64(); }
+};
+
+class KvmMmioEmulateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmMmioEmulateFtraceEvent_Decoder;
+ enum : int32_t {
+ kCpsrFieldNumber = 1,
+ kInstrFieldNumber = 2,
+ kVcpuPcFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmMmioEmulateFtraceEvent"; }
+
+
+ using FieldMetadata_Cpsr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmMmioEmulateFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpsr kCpsr{};
+ void set_cpsr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpsr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Instr =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmMmioEmulateFtraceEvent>;
+
+ static constexpr FieldMetadata_Instr kInstr{};
+ void set_instr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Instr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmMmioEmulateFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmMmioFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmMmioFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmMmioFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmMmioFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gpa() const { return at<1>().valid(); }
+ uint64_t gpa() const { return at<1>().as_uint64(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint32_t len() const { return at<2>().as_uint32(); }
+ bool has_type() const { return at<3>().valid(); }
+ uint32_t type() const { return at<3>().as_uint32(); }
+ bool has_val() const { return at<4>().valid(); }
+ uint64_t val() const { return at<4>().as_uint64(); }
+};
+
+class KvmMmioFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmMmioFtraceEvent_Decoder;
+ enum : int32_t {
+ kGpaFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kValFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmMmioFtraceEvent"; }
+
+
+ using FieldMetadata_Gpa =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmMmioFtraceEvent>;
+
+ static constexpr FieldMetadata_Gpa kGpa{};
+ void set_gpa(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Gpa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmMmioFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmMmioFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Val =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmMmioFtraceEvent>;
+
+ static constexpr FieldMetadata_Val kVal{};
+ void set_val(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Val::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmIrqLineFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmIrqLineFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmIrqLineFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmIrqLineFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irq_num() const { return at<1>().valid(); }
+ int32_t irq_num() const { return at<1>().as_int32(); }
+ bool has_level() const { return at<2>().valid(); }
+ int32_t level() const { return at<2>().as_int32(); }
+ bool has_type() const { return at<3>().valid(); }
+ uint32_t type() const { return at<3>().as_uint32(); }
+ bool has_vcpu_idx() const { return at<4>().valid(); }
+ int32_t vcpu_idx() const { return at<4>().as_int32(); }
+};
+
+class KvmIrqLineFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmIrqLineFtraceEvent_Decoder;
+ enum : int32_t {
+ kIrqNumFieldNumber = 1,
+ kLevelFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kVcpuIdxFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmIrqLineFtraceEvent"; }
+
+
+ using FieldMetadata_IrqNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmIrqLineFtraceEvent>;
+
+ static constexpr FieldMetadata_IrqNum kIrqNum{};
+ void set_irq_num(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IrqNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmIrqLineFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmIrqLineFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuIdx =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmIrqLineFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuIdx kVcpuIdx{};
+ void set_vcpu_idx(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuIdx::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmHvcArm64FtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmHvcArm64FtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmHvcArm64FtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmHvcArm64FtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_imm() const { return at<1>().valid(); }
+ uint64_t imm() const { return at<1>().as_uint64(); }
+ bool has_r0() const { return at<2>().valid(); }
+ uint64_t r0() const { return at<2>().as_uint64(); }
+ bool has_vcpu_pc() const { return at<3>().valid(); }
+ uint64_t vcpu_pc() const { return at<3>().as_uint64(); }
+};
+
+class KvmHvcArm64FtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmHvcArm64FtraceEvent_Decoder;
+ enum : int32_t {
+ kImmFieldNumber = 1,
+ kR0FieldNumber = 2,
+ kVcpuPcFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmHvcArm64FtraceEvent"; }
+
+
+ using FieldMetadata_Imm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmHvcArm64FtraceEvent>;
+
+ static constexpr FieldMetadata_Imm kImm{};
+ void set_imm(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Imm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_R0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmHvcArm64FtraceEvent>;
+
+ static constexpr FieldMetadata_R0 kR0{};
+ void set_r0(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmHvcArm64FtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmHandleSysRegFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmHandleSysRegFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmHandleSysRegFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmHandleSysRegFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_hsr() const { return at<1>().valid(); }
+ uint64_t hsr() const { return at<1>().as_uint64(); }
+};
+
+class KvmHandleSysRegFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmHandleSysRegFtraceEvent_Decoder;
+ enum : int32_t {
+ kHsrFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmHandleSysRegFtraceEvent"; }
+
+
+ using FieldMetadata_Hsr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmHandleSysRegFtraceEvent>;
+
+ static constexpr FieldMetadata_Hsr kHsr{};
+ void set_hsr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hsr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmGuestFaultFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmGuestFaultFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmGuestFaultFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmGuestFaultFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_hsr() const { return at<1>().valid(); }
+ uint64_t hsr() const { return at<1>().as_uint64(); }
+ bool has_hxfar() const { return at<2>().valid(); }
+ uint64_t hxfar() const { return at<2>().as_uint64(); }
+ bool has_ipa() const { return at<3>().valid(); }
+ uint64_t ipa() const { return at<3>().as_uint64(); }
+ bool has_vcpu_pc() const { return at<4>().valid(); }
+ uint64_t vcpu_pc() const { return at<4>().as_uint64(); }
+};
+
+class KvmGuestFaultFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmGuestFaultFtraceEvent_Decoder;
+ enum : int32_t {
+ kHsrFieldNumber = 1,
+ kHxfarFieldNumber = 2,
+ kIpaFieldNumber = 3,
+ kVcpuPcFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmGuestFaultFtraceEvent"; }
+
+
+ using FieldMetadata_Hsr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmGuestFaultFtraceEvent>;
+
+ static constexpr FieldMetadata_Hsr kHsr{};
+ void set_hsr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hsr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Hxfar =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmGuestFaultFtraceEvent>;
+
+ static constexpr FieldMetadata_Hxfar kHxfar{};
+ void set_hxfar(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hxfar::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ipa =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmGuestFaultFtraceEvent>;
+
+ static constexpr FieldMetadata_Ipa kIpa{};
+ void set_ipa(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ipa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmGuestFaultFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmGetTimerMapFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmGetTimerMapFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmGetTimerMapFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmGetTimerMapFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_direct_ptimer() const { return at<1>().valid(); }
+ int32_t direct_ptimer() const { return at<1>().as_int32(); }
+ bool has_direct_vtimer() const { return at<2>().valid(); }
+ int32_t direct_vtimer() const { return at<2>().as_int32(); }
+ bool has_emul_ptimer() const { return at<3>().valid(); }
+ int32_t emul_ptimer() const { return at<3>().as_int32(); }
+ bool has_vcpu_id() const { return at<4>().valid(); }
+ uint64_t vcpu_id() const { return at<4>().as_uint64(); }
+};
+
+class KvmGetTimerMapFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmGetTimerMapFtraceEvent_Decoder;
+ enum : int32_t {
+ kDirectPtimerFieldNumber = 1,
+ kDirectVtimerFieldNumber = 2,
+ kEmulPtimerFieldNumber = 3,
+ kVcpuIdFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmGetTimerMapFtraceEvent"; }
+
+
+ using FieldMetadata_DirectPtimer =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmGetTimerMapFtraceEvent>;
+
+ static constexpr FieldMetadata_DirectPtimer kDirectPtimer{};
+ void set_direct_ptimer(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirectPtimer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DirectVtimer =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmGetTimerMapFtraceEvent>;
+
+ static constexpr FieldMetadata_DirectVtimer kDirectVtimer{};
+ void set_direct_vtimer(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DirectVtimer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EmulPtimer =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmGetTimerMapFtraceEvent>;
+
+ static constexpr FieldMetadata_EmulPtimer kEmulPtimer{};
+ void set_emul_ptimer(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EmulPtimer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmGetTimerMapFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuId kVcpuId{};
+ void set_vcpu_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmFpuFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmFpuFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmFpuFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmFpuFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_load() const { return at<1>().valid(); }
+ uint32_t load() const { return at<1>().as_uint32(); }
+};
+
+class KvmFpuFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmFpuFtraceEvent_Decoder;
+ enum : int32_t {
+ kLoadFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmFpuFtraceEvent"; }
+
+
+ using FieldMetadata_Load =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmFpuFtraceEvent>;
+
+ static constexpr FieldMetadata_Load kLoad{};
+ void set_load(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Load::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_esr_ec() const { return at<1>().valid(); }
+ uint32_t esr_ec() const { return at<1>().as_uint32(); }
+ bool has_ret() const { return at<2>().valid(); }
+ int32_t ret() const { return at<2>().as_int32(); }
+ bool has_vcpu_pc() const { return at<3>().valid(); }
+ uint64_t vcpu_pc() const { return at<3>().as_uint64(); }
+};
+
+class KvmExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kEsrEcFieldNumber = 1,
+ kRetFieldNumber = 2,
+ kVcpuPcFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmExitFtraceEvent"; }
+
+
+ using FieldMetadata_EsrEc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmExitFtraceEvent>;
+
+ static constexpr FieldMetadata_EsrEc kEsrEc{};
+ void set_esr_ec(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EsrEc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmExitFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmEntryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmEntryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmEntryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmEntryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_vcpu_pc() const { return at<1>().valid(); }
+ uint64_t vcpu_pc() const { return at<1>().as_uint64(); }
+};
+
+class KvmEntryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmEntryFtraceEvent_Decoder;
+ enum : int32_t {
+ kVcpuPcFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmEntryFtraceEvent"; }
+
+
+ using FieldMetadata_VcpuPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_VcpuPc kVcpuPc{};
+ void set_vcpu_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VcpuPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmArmSetupDebugFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmArmSetupDebugFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmArmSetupDebugFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmArmSetupDebugFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_guest_debug() const { return at<1>().valid(); }
+ uint32_t guest_debug() const { return at<1>().as_uint32(); }
+ bool has_vcpu() const { return at<2>().valid(); }
+ uint64_t vcpu() const { return at<2>().as_uint64(); }
+};
+
+class KvmArmSetupDebugFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmArmSetupDebugFtraceEvent_Decoder;
+ enum : int32_t {
+ kGuestDebugFieldNumber = 1,
+ kVcpuFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmArmSetupDebugFtraceEvent"; }
+
+
+ using FieldMetadata_GuestDebug =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmArmSetupDebugFtraceEvent>;
+
+ static constexpr FieldMetadata_GuestDebug kGuestDebug{};
+ void set_guest_debug(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GuestDebug::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Vcpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmArmSetupDebugFtraceEvent>;
+
+ static constexpr FieldMetadata_Vcpu kVcpu{};
+ void set_vcpu(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Vcpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmArmSetRegsetFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmArmSetRegsetFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmArmSetRegsetFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmArmSetRegsetFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_len() const { return at<1>().valid(); }
+ int32_t len() const { return at<1>().as_int32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+};
+
+class KvmArmSetRegsetFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmArmSetRegsetFtraceEvent_Decoder;
+ enum : int32_t {
+ kLenFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmArmSetRegsetFtraceEvent"; }
+
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ KvmArmSetRegsetFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ KvmArmSetRegsetFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmArmSetDreg32FtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmArmSetDreg32FtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmArmSetDreg32FtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmArmSetDreg32FtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ uint32_t value() const { return at<2>().as_uint32(); }
+};
+
+class KvmArmSetDreg32FtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmArmSetDreg32FtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmArmSetDreg32FtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ KvmArmSetDreg32FtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmArmSetDreg32FtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmArmClearDebugFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmArmClearDebugFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmArmClearDebugFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmArmClearDebugFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_guest_debug() const { return at<1>().valid(); }
+ uint32_t guest_debug() const { return at<1>().as_uint32(); }
+};
+
+class KvmArmClearDebugFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmArmClearDebugFtraceEvent_Decoder;
+ enum : int32_t {
+ kGuestDebugFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmArmClearDebugFtraceEvent"; }
+
+
+ using FieldMetadata_GuestDebug =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmArmClearDebugFtraceEvent>;
+
+ static constexpr FieldMetadata_GuestDebug kGuestDebug{};
+ void set_guest_debug(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GuestDebug::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmAgePageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmAgePageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmAgePageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmAgePageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gfn() const { return at<1>().valid(); }
+ uint64_t gfn() const { return at<1>().as_uint64(); }
+ bool has_hva() const { return at<2>().valid(); }
+ uint64_t hva() const { return at<2>().as_uint64(); }
+ bool has_level() const { return at<3>().valid(); }
+ uint32_t level() const { return at<3>().as_uint32(); }
+ bool has_referenced() const { return at<4>().valid(); }
+ uint32_t referenced() const { return at<4>().as_uint32(); }
+};
+
+class KvmAgePageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmAgePageFtraceEvent_Decoder;
+ enum : int32_t {
+ kGfnFieldNumber = 1,
+ kHvaFieldNumber = 2,
+ kLevelFieldNumber = 3,
+ kReferencedFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmAgePageFtraceEvent"; }
+
+
+ using FieldMetadata_Gfn =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmAgePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Gfn kGfn{};
+ void set_gfn(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Gfn::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Hva =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmAgePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Hva kHva{};
+ void set_hva(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hva::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Level =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmAgePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Level kLevel{};
+ void set_level(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Level::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Referenced =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmAgePageFtraceEvent>;
+
+ static constexpr FieldMetadata_Referenced kReferenced{};
+ void set_referenced(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Referenced::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmAgeHvaFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmAgeHvaFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmAgeHvaFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmAgeHvaFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_end() const { return at<1>().valid(); }
+ uint64_t end() const { return at<1>().as_uint64(); }
+ bool has_start() const { return at<2>().valid(); }
+ uint64_t start() const { return at<2>().as_uint64(); }
+};
+
+class KvmAgeHvaFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmAgeHvaFtraceEvent_Decoder;
+ enum : int32_t {
+ kEndFieldNumber = 1,
+ kStartFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmAgeHvaFtraceEvent"; }
+
+
+ using FieldMetadata_End =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmAgeHvaFtraceEvent>;
+
+ static constexpr FieldMetadata_End kEnd{};
+ void set_end(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_End::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmAgeHvaFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmAckIrqFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmAckIrqFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmAckIrqFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmAckIrqFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irqchip() const { return at<1>().valid(); }
+ uint32_t irqchip() const { return at<1>().as_uint32(); }
+ bool has_pin() const { return at<2>().valid(); }
+ uint32_t pin() const { return at<2>().as_uint32(); }
+};
+
+class KvmAckIrqFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmAckIrqFtraceEvent_Decoder;
+ enum : int32_t {
+ kIrqchipFieldNumber = 1,
+ kPinFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmAckIrqFtraceEvent"; }
+
+
+ using FieldMetadata_Irqchip =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmAckIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Irqchip kIrqchip{};
+ void set_irqchip(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Irqchip::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pin =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KvmAckIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Pin kPin{};
+ void set_pin(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pin::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class KvmAccessFaultFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KvmAccessFaultFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KvmAccessFaultFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KvmAccessFaultFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ipa() const { return at<1>().valid(); }
+ uint64_t ipa() const { return at<1>().as_uint64(); }
+};
+
+class KvmAccessFaultFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KvmAccessFaultFtraceEvent_Decoder;
+ enum : int32_t {
+ kIpaFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KvmAccessFaultFtraceEvent"; }
+
+
+ using FieldMetadata_Ipa =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KvmAccessFaultFtraceEvent>;
+
+ static constexpr FieldMetadata_Ipa kIpa{};
+ void set_ipa(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ipa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_LOWMEMORYKILLER_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_LOWMEMORYKILLER_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class LowmemoryKillFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LowmemoryKillFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LowmemoryKillFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LowmemoryKillFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_pagecache_size() const { return at<3>().valid(); }
+ int64_t pagecache_size() const { return at<3>().as_int64(); }
+ bool has_pagecache_limit() const { return at<4>().valid(); }
+ int64_t pagecache_limit() const { return at<4>().as_int64(); }
+ bool has_free() const { return at<5>().valid(); }
+ int64_t free() const { return at<5>().as_int64(); }
+};
+
+class LowmemoryKillFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = LowmemoryKillFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kPagecacheSizeFieldNumber = 3,
+ kPagecacheLimitFieldNumber = 4,
+ kFreeFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LowmemoryKillFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LowmemoryKillFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LowmemoryKillFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PagecacheSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ LowmemoryKillFtraceEvent>;
+
+ static constexpr FieldMetadata_PagecacheSize kPagecacheSize{};
+ void set_pagecache_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PagecacheSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PagecacheLimit =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ LowmemoryKillFtraceEvent>;
+
+ static constexpr FieldMetadata_PagecacheLimit kPagecacheLimit{};
+ void set_pagecache_limit(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PagecacheLimit::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Free =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ LowmemoryKillFtraceEvent>;
+
+ static constexpr FieldMetadata_Free kFree{};
+ void set_free(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Free::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/lwis.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_LWIS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_LWIS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class LwisTracingMarkWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LwisTracingMarkWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LwisTracingMarkWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LwisTracingMarkWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_lwis_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars lwis_name() const { return at<1>().as_string(); }
+ bool has_type() const { return at<2>().valid(); }
+ uint32_t type() const { return at<2>().as_uint32(); }
+ bool has_pid() const { return at<3>().valid(); }
+ int32_t pid() const { return at<3>().as_int32(); }
+ bool has_func_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars func_name() const { return at<4>().as_string(); }
+ bool has_value() const { return at<5>().valid(); }
+ int64_t value() const { return at<5>().as_int64(); }
+};
+
+class LwisTracingMarkWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = LwisTracingMarkWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kLwisNameFieldNumber = 1,
+ kTypeFieldNumber = 2,
+ kPidFieldNumber = 3,
+ kFuncNameFieldNumber = 4,
+ kValueFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LwisTracingMarkWriteFtraceEvent"; }
+
+
+ using FieldMetadata_LwisName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LwisTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_LwisName kLwisName{};
+ void set_lwis_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LwisName::kFieldId, data, size);
+ }
+ void set_lwis_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LwisName::kFieldId, chars.data, chars.size);
+ }
+ void set_lwis_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LwisName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ LwisTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ LwisTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FuncName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LwisTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_FuncName kFuncName{};
+ void set_func_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FuncName::kFieldId, data, size);
+ }
+ void set_func_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FuncName::kFieldId, chars.data, chars.size);
+ }
+ void set_func_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FuncName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ LwisTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/mali.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_MALI_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_MALI_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class MaliMaliCSFINTERRUPTENDFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliCSFINTERRUPTENDFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliCSFINTERRUPTENDFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliCSFINTERRUPTENDFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_kctx_tgid() const { return at<1>().valid(); }
+ int32_t kctx_tgid() const { return at<1>().as_int32(); }
+ bool has_kctx_id() const { return at<2>().valid(); }
+ uint32_t kctx_id() const { return at<2>().as_uint32(); }
+ bool has_info_val() const { return at<3>().valid(); }
+ uint64_t info_val() const { return at<3>().as_uint64(); }
+};
+
+class MaliMaliCSFINTERRUPTENDFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliCSFINTERRUPTENDFtraceEvent_Decoder;
+ enum : int32_t {
+ kKctxTgidFieldNumber = 1,
+ kKctxIdFieldNumber = 2,
+ kInfoValFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliCSFINTERRUPTENDFtraceEvent"; }
+
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliCSFINTERRUPTENDFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliCSFINTERRUPTENDFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliCSFINTERRUPTENDFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal kInfoVal{};
+ void set_info_val(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliMaliCSFINTERRUPTSTARTFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliCSFINTERRUPTSTARTFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliCSFINTERRUPTSTARTFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliCSFINTERRUPTSTARTFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_kctx_tgid() const { return at<1>().valid(); }
+ int32_t kctx_tgid() const { return at<1>().as_int32(); }
+ bool has_kctx_id() const { return at<2>().valid(); }
+ uint32_t kctx_id() const { return at<2>().as_uint32(); }
+ bool has_info_val() const { return at<3>().valid(); }
+ uint64_t info_val() const { return at<3>().as_uint64(); }
+};
+
+class MaliMaliCSFINTERRUPTSTARTFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliCSFINTERRUPTSTARTFtraceEvent_Decoder;
+ enum : int32_t {
+ kKctxTgidFieldNumber = 1,
+ kKctxIdFieldNumber = 2,
+ kInfoValFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliCSFINTERRUPTSTARTFtraceEvent"; }
+
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliCSFINTERRUPTSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliCSFINTERRUPTSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliCSFINTERRUPTSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal kInfoVal{};
+ void set_info_val(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliMaliKCPUFENCEWAITENDFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliKCPUFENCEWAITENDFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliKCPUFENCEWAITENDFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliKCPUFENCEWAITENDFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_info_val1() const { return at<1>().valid(); }
+ uint64_t info_val1() const { return at<1>().as_uint64(); }
+ bool has_info_val2() const { return at<2>().valid(); }
+ uint64_t info_val2() const { return at<2>().as_uint64(); }
+ bool has_kctx_tgid() const { return at<3>().valid(); }
+ int32_t kctx_tgid() const { return at<3>().as_int32(); }
+ bool has_kctx_id() const { return at<4>().valid(); }
+ uint32_t kctx_id() const { return at<4>().as_uint32(); }
+ bool has_id() const { return at<5>().valid(); }
+ uint32_t id() const { return at<5>().as_uint32(); }
+};
+
+class MaliMaliKCPUFENCEWAITENDFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliKCPUFENCEWAITENDFtraceEvent_Decoder;
+ enum : int32_t {
+ kInfoVal1FieldNumber = 1,
+ kInfoVal2FieldNumber = 2,
+ kKctxTgidFieldNumber = 3,
+ kKctxIdFieldNumber = 4,
+ kIdFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliKCPUFENCEWAITENDFtraceEvent"; }
+
+
+ using FieldMetadata_InfoVal1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUFENCEWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal1 kInfoVal1{};
+ void set_info_val1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUFENCEWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal2 kInfoVal2{};
+ void set_info_val2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliKCPUFENCEWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUFENCEWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUFENCEWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliMaliKCPUFENCEWAITSTARTFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliKCPUFENCEWAITSTARTFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliKCPUFENCEWAITSTARTFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliKCPUFENCEWAITSTARTFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_info_val1() const { return at<1>().valid(); }
+ uint64_t info_val1() const { return at<1>().as_uint64(); }
+ bool has_info_val2() const { return at<2>().valid(); }
+ uint64_t info_val2() const { return at<2>().as_uint64(); }
+ bool has_kctx_tgid() const { return at<3>().valid(); }
+ int32_t kctx_tgid() const { return at<3>().as_int32(); }
+ bool has_kctx_id() const { return at<4>().valid(); }
+ uint32_t kctx_id() const { return at<4>().as_uint32(); }
+ bool has_id() const { return at<5>().valid(); }
+ uint32_t id() const { return at<5>().as_uint32(); }
+};
+
+class MaliMaliKCPUFENCEWAITSTARTFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliKCPUFENCEWAITSTARTFtraceEvent_Decoder;
+ enum : int32_t {
+ kInfoVal1FieldNumber = 1,
+ kInfoVal2FieldNumber = 2,
+ kKctxTgidFieldNumber = 3,
+ kKctxIdFieldNumber = 4,
+ kIdFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliKCPUFENCEWAITSTARTFtraceEvent"; }
+
+
+ using FieldMetadata_InfoVal1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUFENCEWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal1 kInfoVal1{};
+ void set_info_val1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUFENCEWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal2 kInfoVal2{};
+ void set_info_val2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliKCPUFENCEWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUFENCEWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUFENCEWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliMaliKCPUFENCESIGNALFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliKCPUFENCESIGNALFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliKCPUFENCESIGNALFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliKCPUFENCESIGNALFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_info_val1() const { return at<1>().valid(); }
+ uint64_t info_val1() const { return at<1>().as_uint64(); }
+ bool has_info_val2() const { return at<2>().valid(); }
+ uint64_t info_val2() const { return at<2>().as_uint64(); }
+ bool has_kctx_tgid() const { return at<3>().valid(); }
+ int32_t kctx_tgid() const { return at<3>().as_int32(); }
+ bool has_kctx_id() const { return at<4>().valid(); }
+ uint32_t kctx_id() const { return at<4>().as_uint32(); }
+ bool has_id() const { return at<5>().valid(); }
+ uint32_t id() const { return at<5>().as_uint32(); }
+};
+
+class MaliMaliKCPUFENCESIGNALFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliKCPUFENCESIGNALFtraceEvent_Decoder;
+ enum : int32_t {
+ kInfoVal1FieldNumber = 1,
+ kInfoVal2FieldNumber = 2,
+ kKctxTgidFieldNumber = 3,
+ kKctxIdFieldNumber = 4,
+ kIdFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliKCPUFENCESIGNALFtraceEvent"; }
+
+
+ using FieldMetadata_InfoVal1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUFENCESIGNALFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal1 kInfoVal1{};
+ void set_info_val1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUFENCESIGNALFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal2 kInfoVal2{};
+ void set_info_val2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliKCPUFENCESIGNALFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUFENCESIGNALFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUFENCESIGNALFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliMaliKCPUCQSWAITENDFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliKCPUCQSWAITENDFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliKCPUCQSWAITENDFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliKCPUCQSWAITENDFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint32_t id() const { return at<1>().as_uint32(); }
+ bool has_info_val1() const { return at<2>().valid(); }
+ uint64_t info_val1() const { return at<2>().as_uint64(); }
+ bool has_info_val2() const { return at<3>().valid(); }
+ uint64_t info_val2() const { return at<3>().as_uint64(); }
+ bool has_kctx_id() const { return at<4>().valid(); }
+ uint32_t kctx_id() const { return at<4>().as_uint32(); }
+ bool has_kctx_tgid() const { return at<5>().valid(); }
+ int32_t kctx_tgid() const { return at<5>().as_int32(); }
+};
+
+class MaliMaliKCPUCQSWAITENDFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliKCPUCQSWAITENDFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kInfoVal1FieldNumber = 2,
+ kInfoVal2FieldNumber = 3,
+ kKctxIdFieldNumber = 4,
+ kKctxTgidFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliKCPUCQSWAITENDFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUCQSWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUCQSWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal1 kInfoVal1{};
+ void set_info_val1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUCQSWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal2 kInfoVal2{};
+ void set_info_val2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUCQSWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliKCPUCQSWAITENDFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliMaliKCPUCQSWAITSTARTFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliKCPUCQSWAITSTARTFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliKCPUCQSWAITSTARTFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliKCPUCQSWAITSTARTFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint32_t id() const { return at<1>().as_uint32(); }
+ bool has_info_val1() const { return at<2>().valid(); }
+ uint64_t info_val1() const { return at<2>().as_uint64(); }
+ bool has_info_val2() const { return at<3>().valid(); }
+ uint64_t info_val2() const { return at<3>().as_uint64(); }
+ bool has_kctx_id() const { return at<4>().valid(); }
+ uint32_t kctx_id() const { return at<4>().as_uint32(); }
+ bool has_kctx_tgid() const { return at<5>().valid(); }
+ int32_t kctx_tgid() const { return at<5>().as_int32(); }
+};
+
+class MaliMaliKCPUCQSWAITSTARTFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliKCPUCQSWAITSTARTFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kInfoVal1FieldNumber = 2,
+ kInfoVal2FieldNumber = 3,
+ kKctxIdFieldNumber = 4,
+ kKctxTgidFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliKCPUCQSWAITSTARTFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUCQSWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUCQSWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal1 kInfoVal1{};
+ void set_info_val1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUCQSWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal2 kInfoVal2{};
+ void set_info_val2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUCQSWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliKCPUCQSWAITSTARTFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliMaliKCPUCQSSETFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliMaliKCPUCQSSETFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliMaliKCPUCQSSETFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliMaliKCPUCQSSETFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint32_t id() const { return at<1>().as_uint32(); }
+ bool has_info_val1() const { return at<2>().valid(); }
+ uint64_t info_val1() const { return at<2>().as_uint64(); }
+ bool has_info_val2() const { return at<3>().valid(); }
+ uint64_t info_val2() const { return at<3>().as_uint64(); }
+ bool has_kctx_id() const { return at<4>().valid(); }
+ uint32_t kctx_id() const { return at<4>().as_uint32(); }
+ bool has_kctx_tgid() const { return at<5>().valid(); }
+ int32_t kctx_tgid() const { return at<5>().as_int32(); }
+};
+
+class MaliMaliKCPUCQSSETFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliMaliKCPUCQSSETFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kInfoVal1FieldNumber = 2,
+ kInfoVal2FieldNumber = 3,
+ kKctxIdFieldNumber = 4,
+ kKctxTgidFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliMaliKCPUCQSSETFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUCQSSETFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUCQSSETFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal1 kInfoVal1{};
+ void set_info_val1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InfoVal2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MaliMaliKCPUCQSSETFtraceEvent>;
+
+ static constexpr FieldMetadata_InfoVal2 kInfoVal2{};
+ void set_info_val2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_InfoVal2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliMaliKCPUCQSSETFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxId kKctxId{};
+ void set_kctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KctxTgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliMaliKCPUCQSSETFtraceEvent>;
+
+ static constexpr FieldMetadata_KctxTgid kKctxTgid{};
+ void set_kctx_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KctxTgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MaliTracingMarkWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MaliTracingMarkWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MaliTracingMarkWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MaliTracingMarkWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_type() const { return at<3>().valid(); }
+ uint32_t type() const { return at<3>().as_uint32(); }
+ bool has_value() const { return at<4>().valid(); }
+ int32_t value() const { return at<4>().as_int32(); }
+};
+
+class MaliTracingMarkWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MaliTracingMarkWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ kValueFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MaliTracingMarkWriteFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ MaliTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MaliTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MaliTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/mdss.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_MDSS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_MDSS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class RotatorBwAoAsContextFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RotatorBwAoAsContextFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RotatorBwAoAsContextFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RotatorBwAoAsContextFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_state() const { return at<1>().valid(); }
+ uint32_t state() const { return at<1>().as_uint32(); }
+};
+
+class RotatorBwAoAsContextFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RotatorBwAoAsContextFtraceEvent_Decoder;
+ enum : int32_t {
+ kStateFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RotatorBwAoAsContextFtraceEvent"; }
+
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ RotatorBwAoAsContextFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpPerfUpdateBusFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpPerfUpdateBusFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpPerfUpdateBusFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpPerfUpdateBusFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_client() const { return at<1>().valid(); }
+ int32_t client() const { return at<1>().as_int32(); }
+ bool has_ab_quota() const { return at<2>().valid(); }
+ uint64_t ab_quota() const { return at<2>().as_uint64(); }
+ bool has_ib_quota() const { return at<3>().valid(); }
+ uint64_t ib_quota() const { return at<3>().as_uint64(); }
+};
+
+class MdpPerfUpdateBusFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpPerfUpdateBusFtraceEvent_Decoder;
+ enum : int32_t {
+ kClientFieldNumber = 1,
+ kAbQuotaFieldNumber = 2,
+ kIbQuotaFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpPerfUpdateBusFtraceEvent"; }
+
+
+ using FieldMetadata_Client =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MdpPerfUpdateBusFtraceEvent>;
+
+ static constexpr FieldMetadata_Client kClient{};
+ void set_client(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Client::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AbQuota =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpPerfUpdateBusFtraceEvent>;
+
+ static constexpr FieldMetadata_AbQuota kAbQuota{};
+ void set_ab_quota(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AbQuota::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IbQuota =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpPerfUpdateBusFtraceEvent>;
+
+ static constexpr FieldMetadata_IbQuota kIbQuota{};
+ void set_ib_quota(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IbQuota::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpPerfPrefillCalcFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpPerfPrefillCalcFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpPerfPrefillCalcFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpPerfPrefillCalcFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pnum() const { return at<1>().valid(); }
+ uint32_t pnum() const { return at<1>().as_uint32(); }
+ bool has_latency_buf() const { return at<2>().valid(); }
+ uint32_t latency_buf() const { return at<2>().as_uint32(); }
+ bool has_ot() const { return at<3>().valid(); }
+ uint32_t ot() const { return at<3>().as_uint32(); }
+ bool has_y_buf() const { return at<4>().valid(); }
+ uint32_t y_buf() const { return at<4>().as_uint32(); }
+ bool has_y_scaler() const { return at<5>().valid(); }
+ uint32_t y_scaler() const { return at<5>().as_uint32(); }
+ bool has_pp_lines() const { return at<6>().valid(); }
+ uint32_t pp_lines() const { return at<6>().as_uint32(); }
+ bool has_pp_bytes() const { return at<7>().valid(); }
+ uint32_t pp_bytes() const { return at<7>().as_uint32(); }
+ bool has_post_sc() const { return at<8>().valid(); }
+ uint32_t post_sc() const { return at<8>().as_uint32(); }
+ bool has_fbc_bytes() const { return at<9>().valid(); }
+ uint32_t fbc_bytes() const { return at<9>().as_uint32(); }
+ bool has_prefill_bytes() const { return at<10>().valid(); }
+ uint32_t prefill_bytes() const { return at<10>().as_uint32(); }
+};
+
+class MdpPerfPrefillCalcFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpPerfPrefillCalcFtraceEvent_Decoder;
+ enum : int32_t {
+ kPnumFieldNumber = 1,
+ kLatencyBufFieldNumber = 2,
+ kOtFieldNumber = 3,
+ kYBufFieldNumber = 4,
+ kYScalerFieldNumber = 5,
+ kPpLinesFieldNumber = 6,
+ kPpBytesFieldNumber = 7,
+ kPostScFieldNumber = 8,
+ kFbcBytesFieldNumber = 9,
+ kPrefillBytesFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpPerfPrefillCalcFtraceEvent"; }
+
+
+ using FieldMetadata_Pnum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_Pnum kPnum{};
+ void set_pnum(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pnum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LatencyBuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_LatencyBuf kLatencyBuf{};
+ void set_latency_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LatencyBuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ot =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_Ot kOt{};
+ void set_ot(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ot::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_YBuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_YBuf kYBuf{};
+ void set_y_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_YBuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_YScaler =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_YScaler kYScaler{};
+ void set_y_scaler(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_YScaler::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PpLines =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_PpLines kPpLines{};
+ void set_pp_lines(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PpLines::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PpBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_PpBytes kPpBytes{};
+ void set_pp_bytes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PpBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PostSc =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_PostSc kPostSc{};
+ void set_post_sc(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PostSc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FbcBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_FbcBytes kFbcBytes{};
+ void set_fbc_bytes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FbcBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrefillBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfPrefillCalcFtraceEvent>;
+
+ static constexpr FieldMetadata_PrefillBytes kPrefillBytes{};
+ void set_prefill_bytes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrefillBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpCmdWaitPingpongFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpCmdWaitPingpongFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpCmdWaitPingpongFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpCmdWaitPingpongFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl_num() const { return at<1>().valid(); }
+ uint32_t ctl_num() const { return at<1>().as_uint32(); }
+ bool has_kickoff_cnt() const { return at<2>().valid(); }
+ int32_t kickoff_cnt() const { return at<2>().as_int32(); }
+};
+
+class MdpCmdWaitPingpongFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpCmdWaitPingpongFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlNumFieldNumber = 1,
+ kKickoffCntFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpCmdWaitPingpongFtraceEvent"; }
+
+
+ using FieldMetadata_CtlNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCmdWaitPingpongFtraceEvent>;
+
+ static constexpr FieldMetadata_CtlNum kCtlNum{};
+ void set_ctl_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtlNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KickoffCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MdpCmdWaitPingpongFtraceEvent>;
+
+ static constexpr FieldMetadata_KickoffCnt kKickoffCnt{};
+ void set_kickoff_cnt(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KickoffCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpVideoUnderrunDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpVideoUnderrunDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpVideoUnderrunDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpVideoUnderrunDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl_num() const { return at<1>().valid(); }
+ uint32_t ctl_num() const { return at<1>().as_uint32(); }
+ bool has_underrun_cnt() const { return at<2>().valid(); }
+ uint32_t underrun_cnt() const { return at<2>().as_uint32(); }
+};
+
+class MdpVideoUnderrunDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpVideoUnderrunDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlNumFieldNumber = 1,
+ kUnderrunCntFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpVideoUnderrunDoneFtraceEvent"; }
+
+
+ using FieldMetadata_CtlNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpVideoUnderrunDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_CtlNum kCtlNum{};
+ void set_ctl_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtlNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnderrunCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpVideoUnderrunDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_UnderrunCnt kUnderrunCnt{};
+ void set_underrun_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnderrunCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpPerfSetWmLevelsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpPerfSetWmLevelsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpPerfSetWmLevelsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpPerfSetWmLevelsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pnum() const { return at<1>().valid(); }
+ uint32_t pnum() const { return at<1>().as_uint32(); }
+ bool has_use_space() const { return at<2>().valid(); }
+ uint32_t use_space() const { return at<2>().as_uint32(); }
+ bool has_priority_bytes() const { return at<3>().valid(); }
+ uint32_t priority_bytes() const { return at<3>().as_uint32(); }
+ bool has_wm0() const { return at<4>().valid(); }
+ uint32_t wm0() const { return at<4>().as_uint32(); }
+ bool has_wm1() const { return at<5>().valid(); }
+ uint32_t wm1() const { return at<5>().as_uint32(); }
+ bool has_wm2() const { return at<6>().valid(); }
+ uint32_t wm2() const { return at<6>().as_uint32(); }
+ bool has_mb_cnt() const { return at<7>().valid(); }
+ uint32_t mb_cnt() const { return at<7>().as_uint32(); }
+ bool has_mb_size() const { return at<8>().valid(); }
+ uint32_t mb_size() const { return at<8>().as_uint32(); }
+};
+
+class MdpPerfSetWmLevelsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpPerfSetWmLevelsFtraceEvent_Decoder;
+ enum : int32_t {
+ kPnumFieldNumber = 1,
+ kUseSpaceFieldNumber = 2,
+ kPriorityBytesFieldNumber = 3,
+ kWm0FieldNumber = 4,
+ kWm1FieldNumber = 5,
+ kWm2FieldNumber = 6,
+ kMbCntFieldNumber = 7,
+ kMbSizeFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpPerfSetWmLevelsFtraceEvent"; }
+
+
+ using FieldMetadata_Pnum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_Pnum kPnum{};
+ void set_pnum(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pnum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UseSpace =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_UseSpace kUseSpace{};
+ void set_use_space(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UseSpace::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PriorityBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_PriorityBytes kPriorityBytes{};
+ void set_priority_bytes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PriorityBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Wm0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_Wm0 kWm0{};
+ void set_wm0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Wm0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Wm1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_Wm1 kWm1{};
+ void set_wm1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Wm1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Wm2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_Wm2 kWm2{};
+ void set_wm2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Wm2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MbCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_MbCnt kMbCnt{};
+ void set_mb_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MbCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MbSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetWmLevelsFtraceEvent>;
+
+ static constexpr FieldMetadata_MbSize kMbSize{};
+ void set_mb_size(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MbSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpMixerUpdateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpMixerUpdateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpMixerUpdateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpMixerUpdateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_mixer_num() const { return at<1>().valid(); }
+ uint32_t mixer_num() const { return at<1>().as_uint32(); }
+};
+
+class MdpMixerUpdateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpMixerUpdateFtraceEvent_Decoder;
+ enum : int32_t {
+ kMixerNumFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpMixerUpdateFtraceEvent"; }
+
+
+ using FieldMetadata_MixerNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpMixerUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_MixerNum kMixerNum{};
+ void set_mixer_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MixerNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpCmdReleaseBwFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpCmdReleaseBwFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpCmdReleaseBwFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpCmdReleaseBwFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl_num() const { return at<1>().valid(); }
+ uint32_t ctl_num() const { return at<1>().as_uint32(); }
+};
+
+class MdpCmdReleaseBwFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpCmdReleaseBwFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlNumFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpCmdReleaseBwFtraceEvent"; }
+
+
+ using FieldMetadata_CtlNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCmdReleaseBwFtraceEvent>;
+
+ static constexpr FieldMetadata_CtlNum kCtlNum{};
+ void set_ctl_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtlNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpTraceCounterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpTraceCounterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpTraceCounterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpTraceCounterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_counter_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars counter_name() const { return at<2>().as_string(); }
+ bool has_value() const { return at<3>().valid(); }
+ int32_t value() const { return at<3>().as_int32(); }
+};
+
+class MdpTraceCounterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpTraceCounterFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kCounterNameFieldNumber = 2,
+ kValueFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpTraceCounterFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MdpTraceCounterFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CounterName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ MdpTraceCounterFtraceEvent>;
+
+ static constexpr FieldMetadata_CounterName kCounterName{};
+ void set_counter_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_CounterName::kFieldId, data, size);
+ }
+ void set_counter_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_CounterName::kFieldId, chars.data, chars.size);
+ }
+ void set_counter_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MdpTraceCounterFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpPerfSetQosLutsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpPerfSetQosLutsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpPerfSetQosLutsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpPerfSetQosLutsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pnum() const { return at<1>().valid(); }
+ uint32_t pnum() const { return at<1>().as_uint32(); }
+ bool has_fmt() const { return at<2>().valid(); }
+ uint32_t fmt() const { return at<2>().as_uint32(); }
+ bool has_intf() const { return at<3>().valid(); }
+ uint32_t intf() const { return at<3>().as_uint32(); }
+ bool has_rot() const { return at<4>().valid(); }
+ uint32_t rot() const { return at<4>().as_uint32(); }
+ bool has_fl() const { return at<5>().valid(); }
+ uint32_t fl() const { return at<5>().as_uint32(); }
+ bool has_lut() const { return at<6>().valid(); }
+ uint32_t lut() const { return at<6>().as_uint32(); }
+ bool has_linear() const { return at<7>().valid(); }
+ uint32_t linear() const { return at<7>().as_uint32(); }
+};
+
+class MdpPerfSetQosLutsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpPerfSetQosLutsFtraceEvent_Decoder;
+ enum : int32_t {
+ kPnumFieldNumber = 1,
+ kFmtFieldNumber = 2,
+ kIntfFieldNumber = 3,
+ kRotFieldNumber = 4,
+ kFlFieldNumber = 5,
+ kLutFieldNumber = 6,
+ kLinearFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpPerfSetQosLutsFtraceEvent"; }
+
+
+ using FieldMetadata_Pnum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Pnum kPnum{};
+ void set_pnum(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pnum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fmt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Fmt kFmt{};
+ void set_fmt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fmt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Intf =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Intf kIntf{};
+ void set_intf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Intf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rot =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Rot kRot{};
+ void set_rot(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rot::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fl =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Fl kFl{};
+ void set_fl(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fl::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lut =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Lut kLut{};
+ void set_lut(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lut::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Linear =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Linear kLinear{};
+ void set_linear(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Linear::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpMisrCrcFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpMisrCrcFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpMisrCrcFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpMisrCrcFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_block_id() const { return at<1>().valid(); }
+ uint32_t block_id() const { return at<1>().as_uint32(); }
+ bool has_vsync_cnt() const { return at<2>().valid(); }
+ uint32_t vsync_cnt() const { return at<2>().as_uint32(); }
+ bool has_crc() const { return at<3>().valid(); }
+ uint32_t crc() const { return at<3>().as_uint32(); }
+};
+
+class MdpMisrCrcFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpMisrCrcFtraceEvent_Decoder;
+ enum : int32_t {
+ kBlockIdFieldNumber = 1,
+ kVsyncCntFieldNumber = 2,
+ kCrcFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpMisrCrcFtraceEvent"; }
+
+
+ using FieldMetadata_BlockId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpMisrCrcFtraceEvent>;
+
+ static constexpr FieldMetadata_BlockId kBlockId{};
+ void set_block_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BlockId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VsyncCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpMisrCrcFtraceEvent>;
+
+ static constexpr FieldMetadata_VsyncCnt kVsyncCnt{};
+ void set_vsync_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VsyncCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Crc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpMisrCrcFtraceEvent>;
+
+ static constexpr FieldMetadata_Crc kCrc{};
+ void set_crc(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Crc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpCmdReadptrDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpCmdReadptrDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpCmdReadptrDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpCmdReadptrDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl_num() const { return at<1>().valid(); }
+ uint32_t ctl_num() const { return at<1>().as_uint32(); }
+ bool has_koff_cnt() const { return at<2>().valid(); }
+ int32_t koff_cnt() const { return at<2>().as_int32(); }
+};
+
+class MdpCmdReadptrDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpCmdReadptrDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlNumFieldNumber = 1,
+ kKoffCntFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpCmdReadptrDoneFtraceEvent"; }
+
+
+ using FieldMetadata_CtlNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCmdReadptrDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_CtlNum kCtlNum{};
+ void set_ctl_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtlNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KoffCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MdpCmdReadptrDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_KoffCnt kKoffCnt{};
+ void set_koff_cnt(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KoffCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpSsppSetFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/16, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpSsppSetFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpSsppSetFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpSsppSetFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_num() const { return at<1>().valid(); }
+ uint32_t num() const { return at<1>().as_uint32(); }
+ bool has_play_cnt() const { return at<2>().valid(); }
+ uint32_t play_cnt() const { return at<2>().as_uint32(); }
+ bool has_mixer() const { return at<3>().valid(); }
+ uint32_t mixer() const { return at<3>().as_uint32(); }
+ bool has_stage() const { return at<4>().valid(); }
+ uint32_t stage() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+ bool has_format() const { return at<6>().valid(); }
+ uint32_t format() const { return at<6>().as_uint32(); }
+ bool has_img_w() const { return at<7>().valid(); }
+ uint32_t img_w() const { return at<7>().as_uint32(); }
+ bool has_img_h() const { return at<8>().valid(); }
+ uint32_t img_h() const { return at<8>().as_uint32(); }
+ bool has_src_x() const { return at<9>().valid(); }
+ uint32_t src_x() const { return at<9>().as_uint32(); }
+ bool has_src_y() const { return at<10>().valid(); }
+ uint32_t src_y() const { return at<10>().as_uint32(); }
+ bool has_src_w() const { return at<11>().valid(); }
+ uint32_t src_w() const { return at<11>().as_uint32(); }
+ bool has_src_h() const { return at<12>().valid(); }
+ uint32_t src_h() const { return at<12>().as_uint32(); }
+ bool has_dst_x() const { return at<13>().valid(); }
+ uint32_t dst_x() const { return at<13>().as_uint32(); }
+ bool has_dst_y() const { return at<14>().valid(); }
+ uint32_t dst_y() const { return at<14>().as_uint32(); }
+ bool has_dst_w() const { return at<15>().valid(); }
+ uint32_t dst_w() const { return at<15>().as_uint32(); }
+ bool has_dst_h() const { return at<16>().valid(); }
+ uint32_t dst_h() const { return at<16>().as_uint32(); }
+};
+
+class MdpSsppSetFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpSsppSetFtraceEvent_Decoder;
+ enum : int32_t {
+ kNumFieldNumber = 1,
+ kPlayCntFieldNumber = 2,
+ kMixerFieldNumber = 3,
+ kStageFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ kFormatFieldNumber = 6,
+ kImgWFieldNumber = 7,
+ kImgHFieldNumber = 8,
+ kSrcXFieldNumber = 9,
+ kSrcYFieldNumber = 10,
+ kSrcWFieldNumber = 11,
+ kSrcHFieldNumber = 12,
+ kDstXFieldNumber = 13,
+ kDstYFieldNumber = 14,
+ kDstWFieldNumber = 15,
+ kDstHFieldNumber = 16,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpSsppSetFtraceEvent"; }
+
+
+ using FieldMetadata_Num =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_Num kNum{};
+ void set_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Num::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PlayCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_PlayCnt kPlayCnt{};
+ void set_play_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PlayCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mixer =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_Mixer kMixer{};
+ void set_mixer(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mixer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Stage =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_Stage kStage{};
+ void set_stage(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Stage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Format =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_Format kFormat{};
+ void set_format(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Format::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ImgW =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_ImgW kImgW{};
+ void set_img_w(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ImgW::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ImgH =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_ImgH kImgH{};
+ void set_img_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ImgH::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcX =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcX kSrcX{};
+ void set_src_x(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcX::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcY =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcY kSrcY{};
+ void set_src_y(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcY::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcW =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcW kSrcW{};
+ void set_src_w(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcW::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcH =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcH kSrcH{};
+ void set_src_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcH::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstX =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_DstX kDstX{};
+ void set_dst_x(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstX::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstY =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_DstY kDstY{};
+ void set_dst_y(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstY::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstW =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_DstW kDstW{};
+ void set_dst_w(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstW::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstH =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppSetFtraceEvent>;
+
+ static constexpr FieldMetadata_DstH kDstH{};
+ void set_dst_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstH::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpPerfSetPanicLutsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpPerfSetPanicLutsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpPerfSetPanicLutsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpPerfSetPanicLutsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pnum() const { return at<1>().valid(); }
+ uint32_t pnum() const { return at<1>().as_uint32(); }
+ bool has_fmt() const { return at<2>().valid(); }
+ uint32_t fmt() const { return at<2>().as_uint32(); }
+ bool has_mode() const { return at<3>().valid(); }
+ uint32_t mode() const { return at<3>().as_uint32(); }
+ bool has_panic_lut() const { return at<4>().valid(); }
+ uint32_t panic_lut() const { return at<4>().as_uint32(); }
+ bool has_robust_lut() const { return at<5>().valid(); }
+ uint32_t robust_lut() const { return at<5>().as_uint32(); }
+};
+
+class MdpPerfSetPanicLutsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpPerfSetPanicLutsFtraceEvent_Decoder;
+ enum : int32_t {
+ kPnumFieldNumber = 1,
+ kFmtFieldNumber = 2,
+ kModeFieldNumber = 3,
+ kPanicLutFieldNumber = 4,
+ kRobustLutFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpPerfSetPanicLutsFtraceEvent"; }
+
+
+ using FieldMetadata_Pnum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetPanicLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Pnum kPnum{};
+ void set_pnum(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pnum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fmt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetPanicLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Fmt kFmt{};
+ void set_fmt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fmt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mode =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetPanicLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Mode kMode{};
+ void set_mode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PanicLut =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetPanicLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_PanicLut kPanicLut{};
+ void set_panic_lut(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PanicLut::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RobustLut =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetPanicLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_RobustLut kRobustLut{};
+ void set_robust_lut(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RobustLut::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpCompareBwFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpCompareBwFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpCompareBwFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpCompareBwFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_new_ab() const { return at<1>().valid(); }
+ uint64_t new_ab() const { return at<1>().as_uint64(); }
+ bool has_new_ib() const { return at<2>().valid(); }
+ uint64_t new_ib() const { return at<2>().as_uint64(); }
+ bool has_new_wb() const { return at<3>().valid(); }
+ uint64_t new_wb() const { return at<3>().as_uint64(); }
+ bool has_old_ab() const { return at<4>().valid(); }
+ uint64_t old_ab() const { return at<4>().as_uint64(); }
+ bool has_old_ib() const { return at<5>().valid(); }
+ uint64_t old_ib() const { return at<5>().as_uint64(); }
+ bool has_old_wb() const { return at<6>().valid(); }
+ uint64_t old_wb() const { return at<6>().as_uint64(); }
+ bool has_params_changed() const { return at<7>().valid(); }
+ uint32_t params_changed() const { return at<7>().as_uint32(); }
+ bool has_update_bw() const { return at<8>().valid(); }
+ uint32_t update_bw() const { return at<8>().as_uint32(); }
+};
+
+class MdpCompareBwFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpCompareBwFtraceEvent_Decoder;
+ enum : int32_t {
+ kNewAbFieldNumber = 1,
+ kNewIbFieldNumber = 2,
+ kNewWbFieldNumber = 3,
+ kOldAbFieldNumber = 4,
+ kOldIbFieldNumber = 5,
+ kOldWbFieldNumber = 6,
+ kParamsChangedFieldNumber = 7,
+ kUpdateBwFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpCompareBwFtraceEvent"; }
+
+
+ using FieldMetadata_NewAb =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_NewAb kNewAb{};
+ void set_new_ab(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewAb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewIb =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_NewIb kNewIb{};
+ void set_new_ib(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewIb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewWb =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_NewWb kNewWb{};
+ void set_new_wb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewWb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldAb =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_OldAb kOldAb{};
+ void set_old_ab(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldAb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldIb =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_OldIb kOldIb{};
+ void set_old_ib(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldIb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldWb =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_OldWb kOldWb{};
+ void set_old_wb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldWb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ParamsChanged =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_ParamsChanged kParamsChanged{};
+ void set_params_changed(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParamsChanged::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UpdateBw =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCompareBwFtraceEvent>;
+
+ static constexpr FieldMetadata_UpdateBw kUpdateBw{};
+ void set_update_bw(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UpdateBw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpCmdPingpongDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpCmdPingpongDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpCmdPingpongDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpCmdPingpongDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl_num() const { return at<1>().valid(); }
+ uint32_t ctl_num() const { return at<1>().as_uint32(); }
+ bool has_intf_num() const { return at<2>().valid(); }
+ uint32_t intf_num() const { return at<2>().as_uint32(); }
+ bool has_pp_num() const { return at<3>().valid(); }
+ uint32_t pp_num() const { return at<3>().as_uint32(); }
+ bool has_koff_cnt() const { return at<4>().valid(); }
+ int32_t koff_cnt() const { return at<4>().as_int32(); }
+};
+
+class MdpCmdPingpongDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpCmdPingpongDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlNumFieldNumber = 1,
+ kIntfNumFieldNumber = 2,
+ kPpNumFieldNumber = 3,
+ kKoffCntFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpCmdPingpongDoneFtraceEvent"; }
+
+
+ using FieldMetadata_CtlNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCmdPingpongDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_CtlNum kCtlNum{};
+ void set_ctl_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtlNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntfNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCmdPingpongDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_IntfNum kIntfNum{};
+ void set_intf_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntfNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PpNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCmdPingpongDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_PpNum kPpNum{};
+ void set_pp_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PpNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KoffCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MdpCmdPingpongDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_KoffCnt kKoffCnt{};
+ void set_koff_cnt(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KoffCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TracingMarkWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TracingMarkWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingMarkWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingMarkWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_trace_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars trace_name() const { return at<2>().as_string(); }
+ bool has_trace_begin() const { return at<3>().valid(); }
+ uint32_t trace_begin() const { return at<3>().as_uint32(); }
+};
+
+class TracingMarkWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TracingMarkWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kTraceNameFieldNumber = 2,
+ kTraceBeginFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingMarkWriteFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceName kTraceName{};
+ void set_trace_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, data, size);
+ }
+ void set_trace_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, chars.data, chars.size);
+ }
+ void set_trace_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceBegin kTraceBegin{};
+ void set_trace_begin(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceBegin::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpSsppChangeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/16, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpSsppChangeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpSsppChangeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpSsppChangeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_num() const { return at<1>().valid(); }
+ uint32_t num() const { return at<1>().as_uint32(); }
+ bool has_play_cnt() const { return at<2>().valid(); }
+ uint32_t play_cnt() const { return at<2>().as_uint32(); }
+ bool has_mixer() const { return at<3>().valid(); }
+ uint32_t mixer() const { return at<3>().as_uint32(); }
+ bool has_stage() const { return at<4>().valid(); }
+ uint32_t stage() const { return at<4>().as_uint32(); }
+ bool has_flags() const { return at<5>().valid(); }
+ uint32_t flags() const { return at<5>().as_uint32(); }
+ bool has_format() const { return at<6>().valid(); }
+ uint32_t format() const { return at<6>().as_uint32(); }
+ bool has_img_w() const { return at<7>().valid(); }
+ uint32_t img_w() const { return at<7>().as_uint32(); }
+ bool has_img_h() const { return at<8>().valid(); }
+ uint32_t img_h() const { return at<8>().as_uint32(); }
+ bool has_src_x() const { return at<9>().valid(); }
+ uint32_t src_x() const { return at<9>().as_uint32(); }
+ bool has_src_y() const { return at<10>().valid(); }
+ uint32_t src_y() const { return at<10>().as_uint32(); }
+ bool has_src_w() const { return at<11>().valid(); }
+ uint32_t src_w() const { return at<11>().as_uint32(); }
+ bool has_src_h() const { return at<12>().valid(); }
+ uint32_t src_h() const { return at<12>().as_uint32(); }
+ bool has_dst_x() const { return at<13>().valid(); }
+ uint32_t dst_x() const { return at<13>().as_uint32(); }
+ bool has_dst_y() const { return at<14>().valid(); }
+ uint32_t dst_y() const { return at<14>().as_uint32(); }
+ bool has_dst_w() const { return at<15>().valid(); }
+ uint32_t dst_w() const { return at<15>().as_uint32(); }
+ bool has_dst_h() const { return at<16>().valid(); }
+ uint32_t dst_h() const { return at<16>().as_uint32(); }
+};
+
+class MdpSsppChangeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpSsppChangeFtraceEvent_Decoder;
+ enum : int32_t {
+ kNumFieldNumber = 1,
+ kPlayCntFieldNumber = 2,
+ kMixerFieldNumber = 3,
+ kStageFieldNumber = 4,
+ kFlagsFieldNumber = 5,
+ kFormatFieldNumber = 6,
+ kImgWFieldNumber = 7,
+ kImgHFieldNumber = 8,
+ kSrcXFieldNumber = 9,
+ kSrcYFieldNumber = 10,
+ kSrcWFieldNumber = 11,
+ kSrcHFieldNumber = 12,
+ kDstXFieldNumber = 13,
+ kDstYFieldNumber = 14,
+ kDstWFieldNumber = 15,
+ kDstHFieldNumber = 16,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpSsppChangeFtraceEvent"; }
+
+
+ using FieldMetadata_Num =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Num kNum{};
+ void set_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Num::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PlayCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_PlayCnt kPlayCnt{};
+ void set_play_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PlayCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Mixer =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Mixer kMixer{};
+ void set_mixer(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Mixer::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Stage =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Stage kStage{};
+ void set_stage(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Stage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Format =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_Format kFormat{};
+ void set_format(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Format::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ImgW =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_ImgW kImgW{};
+ void set_img_w(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ImgW::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ImgH =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_ImgH kImgH{};
+ void set_img_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ImgH::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcX =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcX kSrcX{};
+ void set_src_x(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcX::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcY =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcY kSrcY{};
+ void set_src_y(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcY::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcW =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcW kSrcW{};
+ void set_src_w(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcW::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrcH =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_SrcH kSrcH{};
+ void set_src_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrcH::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstX =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_DstX kDstX{};
+ void set_dst_x(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstX::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstY =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_DstY kDstY{};
+ void set_dst_y(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstY::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstW =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_DstW kDstW{};
+ void set_dst_w(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstW::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DstH =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpSsppChangeFtraceEvent>;
+
+ static constexpr FieldMetadata_DstH kDstH{};
+ void set_dst_h(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DstH::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpPerfSetOtFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpPerfSetOtFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpPerfSetOtFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpPerfSetOtFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pnum() const { return at<1>().valid(); }
+ uint32_t pnum() const { return at<1>().as_uint32(); }
+ bool has_xin_id() const { return at<2>().valid(); }
+ uint32_t xin_id() const { return at<2>().as_uint32(); }
+ bool has_rd_lim() const { return at<3>().valid(); }
+ uint32_t rd_lim() const { return at<3>().as_uint32(); }
+ bool has_is_vbif_rt() const { return at<4>().valid(); }
+ uint32_t is_vbif_rt() const { return at<4>().as_uint32(); }
+};
+
+class MdpPerfSetOtFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpPerfSetOtFtraceEvent_Decoder;
+ enum : int32_t {
+ kPnumFieldNumber = 1,
+ kXinIdFieldNumber = 2,
+ kRdLimFieldNumber = 3,
+ kIsVbifRtFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpPerfSetOtFtraceEvent"; }
+
+
+ using FieldMetadata_Pnum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetOtFtraceEvent>;
+
+ static constexpr FieldMetadata_Pnum kPnum{};
+ void set_pnum(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pnum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_XinId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetOtFtraceEvent>;
+
+ static constexpr FieldMetadata_XinId kXinId{};
+ void set_xin_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_XinId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RdLim =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetOtFtraceEvent>;
+
+ static constexpr FieldMetadata_RdLim kRdLim{};
+ void set_rd_lim(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RdLim::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsVbifRt =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpPerfSetOtFtraceEvent>;
+
+ static constexpr FieldMetadata_IsVbifRt kIsVbifRt{};
+ void set_is_vbif_rt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsVbifRt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpCommitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpCommitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpCommitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpCommitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_num() const { return at<1>().valid(); }
+ uint32_t num() const { return at<1>().as_uint32(); }
+ bool has_play_cnt() const { return at<2>().valid(); }
+ uint32_t play_cnt() const { return at<2>().as_uint32(); }
+ bool has_clk_rate() const { return at<3>().valid(); }
+ uint32_t clk_rate() const { return at<3>().as_uint32(); }
+ bool has_bandwidth() const { return at<4>().valid(); }
+ uint64_t bandwidth() const { return at<4>().as_uint64(); }
+};
+
+class MdpCommitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpCommitFtraceEvent_Decoder;
+ enum : int32_t {
+ kNumFieldNumber = 1,
+ kPlayCntFieldNumber = 2,
+ kClkRateFieldNumber = 3,
+ kBandwidthFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpCommitFtraceEvent"; }
+
+
+ using FieldMetadata_Num =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCommitFtraceEvent>;
+
+ static constexpr FieldMetadata_Num kNum{};
+ void set_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Num::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PlayCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCommitFtraceEvent>;
+
+ static constexpr FieldMetadata_PlayCnt kPlayCnt{};
+ void set_play_cnt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PlayCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClkRate =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCommitFtraceEvent>;
+
+ static constexpr FieldMetadata_ClkRate kClkRate{};
+ void set_clk_rate(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClkRate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Bandwidth =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MdpCommitFtraceEvent>;
+
+ static constexpr FieldMetadata_Bandwidth kBandwidth{};
+ void set_bandwidth(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bandwidth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MdpCmdKickoffFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MdpCmdKickoffFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MdpCmdKickoffFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MdpCmdKickoffFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctl_num() const { return at<1>().valid(); }
+ uint32_t ctl_num() const { return at<1>().as_uint32(); }
+ bool has_kickoff_cnt() const { return at<2>().valid(); }
+ int32_t kickoff_cnt() const { return at<2>().as_int32(); }
+};
+
+class MdpCmdKickoffFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MdpCmdKickoffFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtlNumFieldNumber = 1,
+ kKickoffCntFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MdpCmdKickoffFtraceEvent"; }
+
+
+ using FieldMetadata_CtlNum =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MdpCmdKickoffFtraceEvent>;
+
+ static constexpr FieldMetadata_CtlNum kCtlNum{};
+ void set_ctl_num(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtlNum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KickoffCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MdpCmdKickoffFtraceEvent>;
+
+ static constexpr FieldMetadata_KickoffCnt kKickoffCnt{};
+ void set_kickoff_cnt(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KickoffCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/mm_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_MM_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_MM_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class MmEventRecordFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmEventRecordFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmEventRecordFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmEventRecordFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_avg_lat() const { return at<1>().valid(); }
+ uint32_t avg_lat() const { return at<1>().as_uint32(); }
+ bool has_count() const { return at<2>().valid(); }
+ uint32_t count() const { return at<2>().as_uint32(); }
+ bool has_max_lat() const { return at<3>().valid(); }
+ uint32_t max_lat() const { return at<3>().as_uint32(); }
+ bool has_type() const { return at<4>().valid(); }
+ uint32_t type() const { return at<4>().as_uint32(); }
+};
+
+class MmEventRecordFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmEventRecordFtraceEvent_Decoder;
+ enum : int32_t {
+ kAvgLatFieldNumber = 1,
+ kCountFieldNumber = 2,
+ kMaxLatFieldNumber = 3,
+ kTypeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmEventRecordFtraceEvent"; }
+
+
+ using FieldMetadata_AvgLat =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmEventRecordFtraceEvent>;
+
+ static constexpr FieldMetadata_AvgLat kAvgLat{};
+ void set_avg_lat(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AvgLat::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmEventRecordFtraceEvent>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxLat =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmEventRecordFtraceEvent>;
+
+ static constexpr FieldMetadata_MaxLat kMaxLat{};
+ void set_max_lat(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxLat::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmEventRecordFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/net.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_NET_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_NET_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class NapiGroReceiveExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NapiGroReceiveExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NapiGroReceiveExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NapiGroReceiveExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ret() const { return at<1>().valid(); }
+ int32_t ret() const { return at<1>().as_int32(); }
+};
+
+class NapiGroReceiveExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = NapiGroReceiveExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kRetFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NapiGroReceiveExitFtraceEvent"; }
+
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ NapiGroReceiveExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class NapiGroReceiveEntryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/19, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NapiGroReceiveEntryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NapiGroReceiveEntryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NapiGroReceiveEntryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_data_len() const { return at<1>().valid(); }
+ uint32_t data_len() const { return at<1>().as_uint32(); }
+ bool has_gso_size() const { return at<2>().valid(); }
+ uint32_t gso_size() const { return at<2>().as_uint32(); }
+ bool has_gso_type() const { return at<3>().valid(); }
+ uint32_t gso_type() const { return at<3>().as_uint32(); }
+ bool has_hash() const { return at<4>().valid(); }
+ uint32_t hash() const { return at<4>().as_uint32(); }
+ bool has_ip_summed() const { return at<5>().valid(); }
+ uint32_t ip_summed() const { return at<5>().as_uint32(); }
+ bool has_l4_hash() const { return at<6>().valid(); }
+ uint32_t l4_hash() const { return at<6>().as_uint32(); }
+ bool has_len() const { return at<7>().valid(); }
+ uint32_t len() const { return at<7>().as_uint32(); }
+ bool has_mac_header() const { return at<8>().valid(); }
+ int32_t mac_header() const { return at<8>().as_int32(); }
+ bool has_mac_header_valid() const { return at<9>().valid(); }
+ uint32_t mac_header_valid() const { return at<9>().as_uint32(); }
+ bool has_name() const { return at<10>().valid(); }
+ ::protozero::ConstChars name() const { return at<10>().as_string(); }
+ bool has_napi_id() const { return at<11>().valid(); }
+ uint32_t napi_id() const { return at<11>().as_uint32(); }
+ bool has_nr_frags() const { return at<12>().valid(); }
+ uint32_t nr_frags() const { return at<12>().as_uint32(); }
+ bool has_protocol() const { return at<13>().valid(); }
+ uint32_t protocol() const { return at<13>().as_uint32(); }
+ bool has_queue_mapping() const { return at<14>().valid(); }
+ uint32_t queue_mapping() const { return at<14>().as_uint32(); }
+ bool has_skbaddr() const { return at<15>().valid(); }
+ uint64_t skbaddr() const { return at<15>().as_uint64(); }
+ bool has_truesize() const { return at<16>().valid(); }
+ uint32_t truesize() const { return at<16>().as_uint32(); }
+ bool has_vlan_proto() const { return at<17>().valid(); }
+ uint32_t vlan_proto() const { return at<17>().as_uint32(); }
+ bool has_vlan_tagged() const { return at<18>().valid(); }
+ uint32_t vlan_tagged() const { return at<18>().as_uint32(); }
+ bool has_vlan_tci() const { return at<19>().valid(); }
+ uint32_t vlan_tci() const { return at<19>().as_uint32(); }
+};
+
+class NapiGroReceiveEntryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = NapiGroReceiveEntryFtraceEvent_Decoder;
+ enum : int32_t {
+ kDataLenFieldNumber = 1,
+ kGsoSizeFieldNumber = 2,
+ kGsoTypeFieldNumber = 3,
+ kHashFieldNumber = 4,
+ kIpSummedFieldNumber = 5,
+ kL4HashFieldNumber = 6,
+ kLenFieldNumber = 7,
+ kMacHeaderFieldNumber = 8,
+ kMacHeaderValidFieldNumber = 9,
+ kNameFieldNumber = 10,
+ kNapiIdFieldNumber = 11,
+ kNrFragsFieldNumber = 12,
+ kProtocolFieldNumber = 13,
+ kQueueMappingFieldNumber = 14,
+ kSkbaddrFieldNumber = 15,
+ kTruesizeFieldNumber = 16,
+ kVlanProtoFieldNumber = 17,
+ kVlanTaggedFieldNumber = 18,
+ kVlanTciFieldNumber = 19,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NapiGroReceiveEntryFtraceEvent"; }
+
+
+ using FieldMetadata_DataLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_DataLen kDataLen{};
+ void set_data_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GsoSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_GsoSize kGsoSize{};
+ void set_gso_size(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GsoSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GsoType =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_GsoType kGsoType{};
+ void set_gso_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GsoType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Hash =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Hash kHash{};
+ void set_hash(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Hash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IpSummed =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_IpSummed kIpSummed{};
+ void set_ip_summed(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IpSummed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_L4Hash =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_L4Hash kL4Hash{};
+ void set_l4_hash(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_L4Hash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MacHeader =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_MacHeader kMacHeader{};
+ void set_mac_header(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MacHeader::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MacHeaderValid =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_MacHeaderValid kMacHeaderValid{};
+ void set_mac_header_valid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MacHeaderValid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NapiId =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_NapiId kNapiId{};
+ void set_napi_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NapiId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrFrags =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_NrFrags kNrFrags{};
+ void set_nr_frags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrFrags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Protocol =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Protocol kProtocol{};
+ void set_protocol(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Protocol::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_QueueMapping =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_QueueMapping kQueueMapping{};
+ void set_queue_mapping(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_QueueMapping::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Skbaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Skbaddr kSkbaddr{};
+ void set_skbaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Skbaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Truesize =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_Truesize kTruesize{};
+ void set_truesize(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Truesize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VlanProto =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_VlanProto kVlanProto{};
+ void set_vlan_proto(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VlanProto::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VlanTagged =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_VlanTagged kVlanTagged{};
+ void set_vlan_tagged(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VlanTagged::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VlanTci =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NapiGroReceiveEntryFtraceEvent>;
+
+ static constexpr FieldMetadata_VlanTci kVlanTci{};
+ void set_vlan_tci(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VlanTci::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class NetDevXmitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NetDevXmitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NetDevXmitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NetDevXmitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_len() const { return at<1>().valid(); }
+ uint32_t len() const { return at<1>().as_uint32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_rc() const { return at<3>().valid(); }
+ int32_t rc() const { return at<3>().as_int32(); }
+ bool has_skbaddr() const { return at<4>().valid(); }
+ uint64_t skbaddr() const { return at<4>().as_uint64(); }
+};
+
+class NetDevXmitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = NetDevXmitFtraceEvent_Decoder;
+ enum : int32_t {
+ kLenFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kRcFieldNumber = 3,
+ kSkbaddrFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NetDevXmitFtraceEvent"; }
+
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetDevXmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ NetDevXmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ NetDevXmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Rc kRc{};
+ void set_rc(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Skbaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NetDevXmitFtraceEvent>;
+
+ static constexpr FieldMetadata_Skbaddr kSkbaddr{};
+ void set_skbaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Skbaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class NetifReceiveSkbFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ NetifReceiveSkbFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit NetifReceiveSkbFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit NetifReceiveSkbFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_len() const { return at<1>().valid(); }
+ uint32_t len() const { return at<1>().as_uint32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_skbaddr() const { return at<3>().valid(); }
+ uint64_t skbaddr() const { return at<3>().as_uint64(); }
+};
+
+class NetifReceiveSkbFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = NetifReceiveSkbFtraceEvent_Decoder;
+ enum : int32_t {
+ kLenFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kSkbaddrFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.NetifReceiveSkbFtraceEvent"; }
+
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ NetifReceiveSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ NetifReceiveSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Skbaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ NetifReceiveSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Skbaddr kSkbaddr{};
+ void set_skbaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Skbaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/oom.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_OOM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_OOM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class MarkVictimFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MarkVictimFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MarkVictimFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MarkVictimFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+};
+
+class MarkVictimFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MarkVictimFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MarkVictimFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MarkVictimFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class OomScoreAdjUpdateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ OomScoreAdjUpdateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit OomScoreAdjUpdateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit OomScoreAdjUpdateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_oom_score_adj() const { return at<2>().valid(); }
+ int32_t oom_score_adj() const { return at<2>().as_int32(); }
+ bool has_pid() const { return at<3>().valid(); }
+ int32_t pid() const { return at<3>().as_int32(); }
+};
+
+class OomScoreAdjUpdateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = OomScoreAdjUpdateFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kOomScoreAdjFieldNumber = 2,
+ kPidFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.OomScoreAdjUpdateFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ OomScoreAdjUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OomScoreAdj =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ OomScoreAdjUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_OomScoreAdj kOomScoreAdj{};
+ void set_oom_score_adj(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OomScoreAdj::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ OomScoreAdjUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/panel.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_PANEL_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_PANEL_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class PanelWriteGenericFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PanelWriteGenericFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PanelWriteGenericFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PanelWriteGenericFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_trace_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars trace_name() const { return at<2>().as_string(); }
+ bool has_trace_begin() const { return at<3>().valid(); }
+ uint32_t trace_begin() const { return at<3>().as_uint32(); }
+ bool has_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars name() const { return at<4>().as_string(); }
+ bool has_type() const { return at<5>().valid(); }
+ uint32_t type() const { return at<5>().as_uint32(); }
+ bool has_value() const { return at<6>().valid(); }
+ int32_t value() const { return at<6>().as_int32(); }
+};
+
+class PanelWriteGenericFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = PanelWriteGenericFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kTraceNameFieldNumber = 2,
+ kTraceBeginFieldNumber = 3,
+ kNameFieldNumber = 4,
+ kTypeFieldNumber = 5,
+ kValueFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PanelWriteGenericFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ PanelWriteGenericFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PanelWriteGenericFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceName kTraceName{};
+ void set_trace_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, data, size);
+ }
+ void set_trace_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, chars.data, chars.size);
+ }
+ void set_trace_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PanelWriteGenericFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceBegin kTraceBegin{};
+ void set_trace_begin(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceBegin::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PanelWriteGenericFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PanelWriteGenericFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ PanelWriteGenericFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DsiTxFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DsiTxFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DsiTxFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DsiTxFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_last() const { return at<1>().valid(); }
+ uint32_t last() const { return at<1>().as_uint32(); }
+ bool has_tx_buf() const { return at<2>().valid(); }
+ uint32_t tx_buf() const { return at<2>().as_uint32(); }
+ bool has_type() const { return at<3>().valid(); }
+ uint32_t type() const { return at<3>().as_uint32(); }
+};
+
+class DsiTxFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DsiTxFtraceEvent_Decoder;
+ enum : int32_t {
+ kLastFieldNumber = 1,
+ kTxBufFieldNumber = 2,
+ kTypeFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DsiTxFtraceEvent"; }
+
+
+ using FieldMetadata_Last =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DsiTxFtraceEvent>;
+
+ static constexpr FieldMetadata_Last kLast{};
+ void set_last(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Last::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TxBuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DsiTxFtraceEvent>;
+
+ static constexpr FieldMetadata_TxBuf kTxBuf{};
+ void set_tx_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TxBuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DsiTxFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DsiRxFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DsiRxFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DsiRxFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DsiRxFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cmd() const { return at<1>().valid(); }
+ uint32_t cmd() const { return at<1>().as_uint32(); }
+ bool has_rx_buf() const { return at<2>().valid(); }
+ uint32_t rx_buf() const { return at<2>().as_uint32(); }
+};
+
+class DsiRxFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DsiRxFtraceEvent_Decoder;
+ enum : int32_t {
+ kCmdFieldNumber = 1,
+ kRxBufFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DsiRxFtraceEvent"; }
+
+
+ using FieldMetadata_Cmd =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DsiRxFtraceEvent>;
+
+ static constexpr FieldMetadata_Cmd kCmd{};
+ void set_cmd(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RxBuf =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DsiRxFtraceEvent>;
+
+ static constexpr FieldMetadata_RxBuf kRxBuf{};
+ void set_rx_buf(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RxBuf::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class DsiCmdFifoStatusFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ DsiCmdFifoStatusFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DsiCmdFifoStatusFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DsiCmdFifoStatusFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_header() const { return at<1>().valid(); }
+ uint32_t header() const { return at<1>().as_uint32(); }
+ bool has_payload() const { return at<2>().valid(); }
+ uint32_t payload() const { return at<2>().as_uint32(); }
+};
+
+class DsiCmdFifoStatusFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = DsiCmdFifoStatusFtraceEvent_Decoder;
+ enum : int32_t {
+ kHeaderFieldNumber = 1,
+ kPayloadFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DsiCmdFifoStatusFtraceEvent"; }
+
+
+ using FieldMetadata_Header =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DsiCmdFifoStatusFtraceEvent>;
+
+ static constexpr FieldMetadata_Header kHeader{};
+ void set_header(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Header::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Payload =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ DsiCmdFifoStatusFtraceEvent>;
+
+ static constexpr FieldMetadata_Payload kPayload{};
+ void set_payload(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Payload::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/perf_trace_counters.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_PERF_TRACE_COUNTERS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_PERF_TRACE_COUNTERS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SchedSwitchWithCtrsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/17, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedSwitchWithCtrsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedSwitchWithCtrsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedSwitchWithCtrsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_old_pid() const { return at<1>().valid(); }
+ int32_t old_pid() const { return at<1>().as_int32(); }
+ bool has_new_pid() const { return at<2>().valid(); }
+ int32_t new_pid() const { return at<2>().as_int32(); }
+ bool has_cctr() const { return at<3>().valid(); }
+ uint32_t cctr() const { return at<3>().as_uint32(); }
+ bool has_ctr0() const { return at<4>().valid(); }
+ uint32_t ctr0() const { return at<4>().as_uint32(); }
+ bool has_ctr1() const { return at<5>().valid(); }
+ uint32_t ctr1() const { return at<5>().as_uint32(); }
+ bool has_ctr2() const { return at<6>().valid(); }
+ uint32_t ctr2() const { return at<6>().as_uint32(); }
+ bool has_ctr3() const { return at<7>().valid(); }
+ uint32_t ctr3() const { return at<7>().as_uint32(); }
+ bool has_lctr0() const { return at<8>().valid(); }
+ uint32_t lctr0() const { return at<8>().as_uint32(); }
+ bool has_lctr1() const { return at<9>().valid(); }
+ uint32_t lctr1() const { return at<9>().as_uint32(); }
+ bool has_ctr4() const { return at<10>().valid(); }
+ uint32_t ctr4() const { return at<10>().as_uint32(); }
+ bool has_ctr5() const { return at<11>().valid(); }
+ uint32_t ctr5() const { return at<11>().as_uint32(); }
+ bool has_prev_comm() const { return at<12>().valid(); }
+ ::protozero::ConstChars prev_comm() const { return at<12>().as_string(); }
+ bool has_prev_pid() const { return at<13>().valid(); }
+ int32_t prev_pid() const { return at<13>().as_int32(); }
+ bool has_cyc() const { return at<14>().valid(); }
+ uint32_t cyc() const { return at<14>().as_uint32(); }
+ bool has_inst() const { return at<15>().valid(); }
+ uint32_t inst() const { return at<15>().as_uint32(); }
+ bool has_stallbm() const { return at<16>().valid(); }
+ uint32_t stallbm() const { return at<16>().as_uint32(); }
+ bool has_l3dm() const { return at<17>().valid(); }
+ uint32_t l3dm() const { return at<17>().as_uint32(); }
+};
+
+class SchedSwitchWithCtrsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedSwitchWithCtrsFtraceEvent_Decoder;
+ enum : int32_t {
+ kOldPidFieldNumber = 1,
+ kNewPidFieldNumber = 2,
+ kCctrFieldNumber = 3,
+ kCtr0FieldNumber = 4,
+ kCtr1FieldNumber = 5,
+ kCtr2FieldNumber = 6,
+ kCtr3FieldNumber = 7,
+ kLctr0FieldNumber = 8,
+ kLctr1FieldNumber = 9,
+ kCtr4FieldNumber = 10,
+ kCtr5FieldNumber = 11,
+ kPrevCommFieldNumber = 12,
+ kPrevPidFieldNumber = 13,
+ kCycFieldNumber = 14,
+ kInstFieldNumber = 15,
+ kStallbmFieldNumber = 16,
+ kL3dmFieldNumber = 17,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedSwitchWithCtrsFtraceEvent"; }
+
+
+ using FieldMetadata_OldPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_OldPid kOldPid{};
+ void set_old_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NewPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_NewPid kNewPid{};
+ void set_new_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cctr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Cctr kCctr{};
+ void set_cctr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cctr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctr0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctr0 kCtr0{};
+ void set_ctr0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctr0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctr1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctr1 kCtr1{};
+ void set_ctr1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctr1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctr2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctr2 kCtr2{};
+ void set_ctr2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctr2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctr3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctr3 kCtr3{};
+ void set_ctr3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctr3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lctr0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Lctr0 kLctr0{};
+ void set_lctr0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lctr0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lctr1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Lctr1 kLctr1{};
+ void set_lctr1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lctr1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctr4 =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctr4 kCtr4{};
+ void set_ctr4(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctr4::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ctr5 =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Ctr5 kCtr5{};
+ void set_ctr5(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ctr5::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrevComm =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_PrevComm kPrevComm{};
+ void set_prev_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_PrevComm::kFieldId, data, size);
+ }
+ void set_prev_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_PrevComm::kFieldId, chars.data, chars.size);
+ }
+ void set_prev_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrevComm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrevPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_PrevPid kPrevPid{};
+ void set_prev_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrevPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cyc =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Cyc kCyc{};
+ void set_cyc(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cyc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Inst =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Inst kInst{};
+ void set_inst(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Inst::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Stallbm =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_Stallbm kStallbm{};
+ void set_stallbm(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Stallbm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_L3dm =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedSwitchWithCtrsFtraceEvent>;
+
+ static constexpr FieldMetadata_L3dm kL3dm{};
+ void set_l3dm(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_L3dm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/power.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_POWER_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_POWER_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class GpuWorkPeriodFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuWorkPeriodFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuWorkPeriodFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuWorkPeriodFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gpu_id() const { return at<1>().valid(); }
+ uint32_t gpu_id() const { return at<1>().as_uint32(); }
+ bool has_uid() const { return at<2>().valid(); }
+ uint32_t uid() const { return at<2>().as_uint32(); }
+ bool has_start_time_ns() const { return at<3>().valid(); }
+ uint64_t start_time_ns() const { return at<3>().as_uint64(); }
+ bool has_end_time_ns() const { return at<4>().valid(); }
+ uint64_t end_time_ns() const { return at<4>().as_uint64(); }
+ bool has_total_active_duration_ns() const { return at<5>().valid(); }
+ uint64_t total_active_duration_ns() const { return at<5>().as_uint64(); }
+};
+
+class GpuWorkPeriodFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = GpuWorkPeriodFtraceEvent_Decoder;
+ enum : int32_t {
+ kGpuIdFieldNumber = 1,
+ kUidFieldNumber = 2,
+ kStartTimeNsFieldNumber = 3,
+ kEndTimeNsFieldNumber = 4,
+ kTotalActiveDurationNsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuWorkPeriodFtraceEvent"; }
+
+
+ using FieldMetadata_GpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuWorkPeriodFtraceEvent>;
+
+ static constexpr FieldMetadata_GpuId kGpuId{};
+ void set_gpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuWorkPeriodFtraceEvent>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuWorkPeriodFtraceEvent>;
+
+ static constexpr FieldMetadata_StartTimeNs kStartTimeNs{};
+ void set_start_time_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EndTimeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuWorkPeriodFtraceEvent>;
+
+ static constexpr FieldMetadata_EndTimeNs kEndTimeNs{};
+ void set_end_time_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EndTimeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalActiveDurationNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuWorkPeriodFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalActiveDurationNs kTotalActiveDurationNs{};
+ void set_total_active_duration_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalActiveDurationNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class WakeupSourceDeactivateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ WakeupSourceDeactivateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit WakeupSourceDeactivateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit WakeupSourceDeactivateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_state() const { return at<2>().valid(); }
+ uint64_t state() const { return at<2>().as_uint64(); }
+};
+
+class WakeupSourceDeactivateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = WakeupSourceDeactivateFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStateFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.WakeupSourceDeactivateFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ WakeupSourceDeactivateFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WakeupSourceDeactivateFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class WakeupSourceActivateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ WakeupSourceActivateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit WakeupSourceActivateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit WakeupSourceActivateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_state() const { return at<2>().valid(); }
+ uint64_t state() const { return at<2>().as_uint64(); }
+};
+
+class WakeupSourceActivateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = WakeupSourceActivateFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStateFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.WakeupSourceActivateFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ WakeupSourceActivateFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WakeupSourceActivateFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuFrequencyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuFrequencyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuFrequencyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuFrequencyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_gpu_id() const { return at<1>().valid(); }
+ uint32_t gpu_id() const { return at<1>().as_uint32(); }
+ bool has_state() const { return at<2>().valid(); }
+ uint32_t state() const { return at<2>().as_uint32(); }
+};
+
+class GpuFrequencyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = GpuFrequencyFtraceEvent_Decoder;
+ enum : int32_t {
+ kGpuIdFieldNumber = 1,
+ kStateFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuFrequencyFtraceEvent"; }
+
+
+ using FieldMetadata_GpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuFrequencyFtraceEvent>;
+
+ static constexpr FieldMetadata_GpuId kGpuId{};
+ void set_gpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuFrequencyFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SuspendResumeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SuspendResumeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SuspendResumeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SuspendResumeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_action() const { return at<1>().valid(); }
+ ::protozero::ConstChars action() const { return at<1>().as_string(); }
+ bool has_val() const { return at<2>().valid(); }
+ int32_t val() const { return at<2>().as_int32(); }
+ bool has_start() const { return at<3>().valid(); }
+ uint32_t start() const { return at<3>().as_uint32(); }
+};
+
+class SuspendResumeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SuspendResumeFtraceEvent_Decoder;
+ enum : int32_t {
+ kActionFieldNumber = 1,
+ kValFieldNumber = 2,
+ kStartFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SuspendResumeFtraceEvent"; }
+
+
+ using FieldMetadata_Action =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SuspendResumeFtraceEvent>;
+
+ static constexpr FieldMetadata_Action kAction{};
+ void set_action(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Action::kFieldId, data, size);
+ }
+ void set_action(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Action::kFieldId, chars.data, chars.size);
+ }
+ void set_action(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Action::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Val =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SuspendResumeFtraceEvent>;
+
+ static constexpr FieldMetadata_Val kVal{};
+ void set_val(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Val::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SuspendResumeFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ClockSetRateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ClockSetRateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClockSetRateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClockSetRateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_state() const { return at<2>().valid(); }
+ uint64_t state() const { return at<2>().as_uint64(); }
+ bool has_cpu_id() const { return at<3>().valid(); }
+ uint64_t cpu_id() const { return at<3>().as_uint64(); }
+};
+
+class ClockSetRateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ClockSetRateFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStateFieldNumber = 2,
+ kCpuIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClockSetRateFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ClockSetRateFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockSetRateFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockSetRateFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuId kCpuId{};
+ void set_cpu_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ClockDisableFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ClockDisableFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClockDisableFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClockDisableFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_state() const { return at<2>().valid(); }
+ uint64_t state() const { return at<2>().as_uint64(); }
+ bool has_cpu_id() const { return at<3>().valid(); }
+ uint64_t cpu_id() const { return at<3>().as_uint64(); }
+};
+
+class ClockDisableFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ClockDisableFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStateFieldNumber = 2,
+ kCpuIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClockDisableFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ClockDisableFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockDisableFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockDisableFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuId kCpuId{};
+ void set_cpu_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ClockEnableFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ClockEnableFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ClockEnableFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ClockEnableFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_state() const { return at<2>().valid(); }
+ uint64_t state() const { return at<2>().as_uint64(); }
+ bool has_cpu_id() const { return at<3>().valid(); }
+ uint64_t cpu_id() const { return at<3>().as_uint64(); }
+};
+
+class ClockEnableFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ClockEnableFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStateFieldNumber = 2,
+ kCpuIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ClockEnableFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ClockEnableFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockEnableFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ClockEnableFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuId kCpuId{};
+ void set_cpu_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CpuIdleFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuIdleFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuIdleFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuIdleFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_state() const { return at<1>().valid(); }
+ uint32_t state() const { return at<1>().as_uint32(); }
+ bool has_cpu_id() const { return at<2>().valid(); }
+ uint32_t cpu_id() const { return at<2>().as_uint32(); }
+};
+
+class CpuIdleFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuIdleFtraceEvent_Decoder;
+ enum : int32_t {
+ kStateFieldNumber = 1,
+ kCpuIdFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuIdleFtraceEvent"; }
+
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuIdleFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuIdleFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuId kCpuId{};
+ void set_cpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CpuFrequencyLimitsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuFrequencyLimitsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuFrequencyLimitsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuFrequencyLimitsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_min_freq() const { return at<1>().valid(); }
+ uint32_t min_freq() const { return at<1>().as_uint32(); }
+ bool has_max_freq() const { return at<2>().valid(); }
+ uint32_t max_freq() const { return at<2>().as_uint32(); }
+ bool has_cpu_id() const { return at<3>().valid(); }
+ uint32_t cpu_id() const { return at<3>().as_uint32(); }
+};
+
+class CpuFrequencyLimitsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuFrequencyLimitsFtraceEvent_Decoder;
+ enum : int32_t {
+ kMinFreqFieldNumber = 1,
+ kMaxFreqFieldNumber = 2,
+ kCpuIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuFrequencyLimitsFtraceEvent"; }
+
+
+ using FieldMetadata_MinFreq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuFrequencyLimitsFtraceEvent>;
+
+ static constexpr FieldMetadata_MinFreq kMinFreq{};
+ void set_min_freq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MinFreq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxFreq =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuFrequencyLimitsFtraceEvent>;
+
+ static constexpr FieldMetadata_MaxFreq kMaxFreq{};
+ void set_max_freq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxFreq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuFrequencyLimitsFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuId kCpuId{};
+ void set_cpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class CpuFrequencyFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CpuFrequencyFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuFrequencyFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuFrequencyFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_state() const { return at<1>().valid(); }
+ uint32_t state() const { return at<1>().as_uint32(); }
+ bool has_cpu_id() const { return at<2>().valid(); }
+ uint32_t cpu_id() const { return at<2>().as_uint32(); }
+};
+
+class CpuFrequencyFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CpuFrequencyFtraceEvent_Decoder;
+ enum : int32_t {
+ kStateFieldNumber = 1,
+ kCpuIdFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuFrequencyFtraceEvent"; }
+
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuFrequencyFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuFrequencyFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuId kCpuId{};
+ void set_cpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/printk.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_PRINTK_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_PRINTK_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ConsoleFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ConsoleFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ConsoleFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ConsoleFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_msg() const { return at<1>().valid(); }
+ ::protozero::ConstChars msg() const { return at<1>().as_string(); }
+};
+
+class ConsoleFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ConsoleFtraceEvent_Decoder;
+ enum : int32_t {
+ kMsgFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ConsoleFtraceEvent"; }
+
+
+ using FieldMetadata_Msg =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ConsoleFtraceEvent>;
+
+ static constexpr FieldMetadata_Msg kMsg{};
+ void set_msg(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Msg::kFieldId, data, size);
+ }
+ void set_msg(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Msg::kFieldId, chars.data, chars.size);
+ }
+ void set_msg(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Msg::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_RAW_SYSCALLS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_RAW_SYSCALLS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SysExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int64_t id() const { return at<1>().as_int64(); }
+ bool has_ret() const { return at<2>().valid(); }
+ int64_t ret() const { return at<2>().as_int64(); }
+};
+
+class SysExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SysExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kRetFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysExitFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ SysExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ SysExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysEnterFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ SysEnterFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysEnterFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysEnterFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int64_t id() const { return at<1>().as_int64(); }
+ bool has_args() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> args() const { return GetRepeated<uint64_t>(2); }
+};
+
+class SysEnterFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SysEnterFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kArgsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysEnterFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ SysEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Args =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysEnterFtraceEvent>;
+
+ static constexpr FieldMetadata_Args kArgs{};
+ void add_args(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Args::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/regulator.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_REGULATOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_REGULATOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class RegulatorSetVoltageCompleteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RegulatorSetVoltageCompleteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegulatorSetVoltageCompleteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegulatorSetVoltageCompleteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_val() const { return at<2>().valid(); }
+ uint32_t val() const { return at<2>().as_uint32(); }
+};
+
+class RegulatorSetVoltageCompleteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RegulatorSetVoltageCompleteFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kValFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegulatorSetVoltageCompleteFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RegulatorSetVoltageCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Val =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ RegulatorSetVoltageCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Val kVal{};
+ void set_val(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Val::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RegulatorSetVoltageFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RegulatorSetVoltageFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegulatorSetVoltageFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegulatorSetVoltageFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_min() const { return at<2>().valid(); }
+ int32_t min() const { return at<2>().as_int32(); }
+ bool has_max() const { return at<3>().valid(); }
+ int32_t max() const { return at<3>().as_int32(); }
+};
+
+class RegulatorSetVoltageFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RegulatorSetVoltageFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kMinFieldNumber = 2,
+ kMaxFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegulatorSetVoltageFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RegulatorSetVoltageFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Min =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RegulatorSetVoltageFtraceEvent>;
+
+ static constexpr FieldMetadata_Min kMin{};
+ void set_min(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Min::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Max =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RegulatorSetVoltageFtraceEvent>;
+
+ static constexpr FieldMetadata_Max kMax{};
+ void set_max(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Max::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RegulatorEnableDelayFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RegulatorEnableDelayFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegulatorEnableDelayFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegulatorEnableDelayFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class RegulatorEnableDelayFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RegulatorEnableDelayFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegulatorEnableDelayFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RegulatorEnableDelayFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RegulatorEnableCompleteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RegulatorEnableCompleteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegulatorEnableCompleteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegulatorEnableCompleteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class RegulatorEnableCompleteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RegulatorEnableCompleteFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegulatorEnableCompleteFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RegulatorEnableCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RegulatorEnableFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RegulatorEnableFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegulatorEnableFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegulatorEnableFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class RegulatorEnableFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RegulatorEnableFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegulatorEnableFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RegulatorEnableFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RegulatorDisableCompleteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RegulatorDisableCompleteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegulatorDisableCompleteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegulatorDisableCompleteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class RegulatorDisableCompleteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RegulatorDisableCompleteFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegulatorDisableCompleteFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RegulatorDisableCompleteFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RegulatorDisableFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RegulatorDisableFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RegulatorDisableFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RegulatorDisableFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class RegulatorDisableFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RegulatorDisableFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RegulatorDisableFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RegulatorDisableFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/rpm.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_RPM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_RPM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class RpmStatusFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RpmStatusFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RpmStatusFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RpmStatusFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_status() const { return at<2>().valid(); }
+ int32_t status() const { return at<2>().as_int32(); }
+};
+
+class RpmStatusFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RpmStatusFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStatusFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RpmStatusFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ RpmStatusFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RpmStatusFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/samsung.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SAMSUNG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SAMSUNG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SamsungTracingMarkWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SamsungTracingMarkWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SamsungTracingMarkWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SamsungTracingMarkWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_trace_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars trace_name() const { return at<2>().as_string(); }
+ bool has_trace_begin() const { return at<3>().valid(); }
+ uint32_t trace_begin() const { return at<3>().as_uint32(); }
+ bool has_trace_type() const { return at<4>().valid(); }
+ uint32_t trace_type() const { return at<4>().as_uint32(); }
+ bool has_value() const { return at<5>().valid(); }
+ int32_t value() const { return at<5>().as_int32(); }
+};
+
+class SamsungTracingMarkWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SamsungTracingMarkWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kTraceNameFieldNumber = 2,
+ kTraceBeginFieldNumber = 3,
+ kTraceTypeFieldNumber = 4,
+ kValueFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SamsungTracingMarkWriteFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SamsungTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SamsungTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceName kTraceName{};
+ void set_trace_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, data, size);
+ }
+ void set_trace_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, chars.data, chars.size);
+ }
+ void set_trace_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SamsungTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceBegin kTraceBegin{};
+ void set_trace_begin(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceBegin::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceType =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SamsungTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceType kTraceType{};
+ void set_trace_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SamsungTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/sched.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SCHED_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SCHED_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SchedMigrateTaskFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedMigrateTaskFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedMigrateTaskFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedMigrateTaskFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_prio() const { return at<3>().valid(); }
+ int32_t prio() const { return at<3>().as_int32(); }
+ bool has_orig_cpu() const { return at<4>().valid(); }
+ int32_t orig_cpu() const { return at<4>().as_int32(); }
+ bool has_dest_cpu() const { return at<5>().valid(); }
+ int32_t dest_cpu() const { return at<5>().as_int32(); }
+ bool has_running() const { return at<6>().valid(); }
+ int32_t running() const { return at<6>().as_int32(); }
+ bool has_load() const { return at<7>().valid(); }
+ uint32_t load() const { return at<7>().as_uint32(); }
+};
+
+class SchedMigrateTaskFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedMigrateTaskFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ kOrigCpuFieldNumber = 4,
+ kDestCpuFieldNumber = 5,
+ kRunningFieldNumber = 6,
+ kLoadFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedMigrateTaskFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedMigrateTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedMigrateTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedMigrateTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedMigrateTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_OrigCpu kOrigCpu{};
+ void set_orig_cpu(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DestCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedMigrateTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_DestCpu kDestCpu{};
+ void set_dest_cpu(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DestCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Running =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedMigrateTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Running kRunning{};
+ void set_running(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Running::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Load =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedMigrateTaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Load kLoad{};
+ void set_load(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Load::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedCpuUtilCfsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/15, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedCpuUtilCfsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedCpuUtilCfsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedCpuUtilCfsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_active() const { return at<1>().valid(); }
+ int32_t active() const { return at<1>().as_int32(); }
+ bool has_capacity() const { return at<2>().valid(); }
+ uint64_t capacity() const { return at<2>().as_uint64(); }
+ bool has_capacity_orig() const { return at<3>().valid(); }
+ uint64_t capacity_orig() const { return at<3>().as_uint64(); }
+ bool has_cpu() const { return at<4>().valid(); }
+ uint32_t cpu() const { return at<4>().as_uint32(); }
+ bool has_cpu_importance() const { return at<5>().valid(); }
+ uint64_t cpu_importance() const { return at<5>().as_uint64(); }
+ bool has_cpu_util() const { return at<6>().valid(); }
+ uint64_t cpu_util() const { return at<6>().as_uint64(); }
+ bool has_exit_lat() const { return at<7>().valid(); }
+ uint32_t exit_lat() const { return at<7>().as_uint32(); }
+ bool has_group_capacity() const { return at<8>().valid(); }
+ uint64_t group_capacity() const { return at<8>().as_uint64(); }
+ bool has_grp_overutilized() const { return at<9>().valid(); }
+ uint32_t grp_overutilized() const { return at<9>().as_uint32(); }
+ bool has_idle_cpu() const { return at<10>().valid(); }
+ uint32_t idle_cpu() const { return at<10>().as_uint32(); }
+ bool has_nr_running() const { return at<11>().valid(); }
+ uint32_t nr_running() const { return at<11>().as_uint32(); }
+ bool has_spare_cap() const { return at<12>().valid(); }
+ int64_t spare_cap() const { return at<12>().as_int64(); }
+ bool has_task_fits() const { return at<13>().valid(); }
+ uint32_t task_fits() const { return at<13>().as_uint32(); }
+ bool has_wake_group_util() const { return at<14>().valid(); }
+ uint64_t wake_group_util() const { return at<14>().as_uint64(); }
+ bool has_wake_util() const { return at<15>().valid(); }
+ uint64_t wake_util() const { return at<15>().as_uint64(); }
+};
+
+class SchedCpuUtilCfsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedCpuUtilCfsFtraceEvent_Decoder;
+ enum : int32_t {
+ kActiveFieldNumber = 1,
+ kCapacityFieldNumber = 2,
+ kCapacityOrigFieldNumber = 3,
+ kCpuFieldNumber = 4,
+ kCpuImportanceFieldNumber = 5,
+ kCpuUtilFieldNumber = 6,
+ kExitLatFieldNumber = 7,
+ kGroupCapacityFieldNumber = 8,
+ kGrpOverutilizedFieldNumber = 9,
+ kIdleCpuFieldNumber = 10,
+ kNrRunningFieldNumber = 11,
+ kSpareCapFieldNumber = 12,
+ kTaskFitsFieldNumber = 13,
+ kWakeGroupUtilFieldNumber = 14,
+ kWakeUtilFieldNumber = 15,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedCpuUtilCfsFtraceEvent"; }
+
+
+ using FieldMetadata_Active =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_Active kActive{};
+ void set_active(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Active::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Capacity =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_Capacity kCapacity{};
+ void set_capacity(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Capacity::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CapacityOrig =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_CapacityOrig kCapacityOrig{};
+ void set_capacity_orig(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CapacityOrig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuImportance =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuImportance kCpuImportance{};
+ void set_cpu_importance(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuImportance::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuUtil =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_CpuUtil kCpuUtil{};
+ void set_cpu_util(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuUtil::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExitLat =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_ExitLat kExitLat{};
+ void set_exit_lat(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExitLat::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GroupCapacity =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_GroupCapacity kGroupCapacity{};
+ void set_group_capacity(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GroupCapacity::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GrpOverutilized =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_GrpOverutilized kGrpOverutilized{};
+ void set_grp_overutilized(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GrpOverutilized::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IdleCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_IdleCpu kIdleCpu{};
+ void set_idle_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IdleCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrRunning =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_NrRunning kNrRunning{};
+ void set_nr_running(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrRunning::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SpareCap =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_SpareCap kSpareCap{};
+ void set_spare_cap(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SpareCap::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TaskFits =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_TaskFits kTaskFits{};
+ void set_task_fits(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TaskFits::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WakeGroupUtil =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_WakeGroupUtil kWakeGroupUtil{};
+ void set_wake_group_util(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WakeGroupUtil::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WakeUtil =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedCpuUtilCfsFtraceEvent>;
+
+ static constexpr FieldMetadata_WakeUtil kWakeUtil{};
+ void set_wake_util(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WakeUtil::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedPiSetprioFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedPiSetprioFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedPiSetprioFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedPiSetprioFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_newprio() const { return at<2>().valid(); }
+ int32_t newprio() const { return at<2>().as_int32(); }
+ bool has_oldprio() const { return at<3>().valid(); }
+ int32_t oldprio() const { return at<3>().as_int32(); }
+ bool has_pid() const { return at<4>().valid(); }
+ int32_t pid() const { return at<4>().as_int32(); }
+};
+
+class SchedPiSetprioFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedPiSetprioFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kNewprioFieldNumber = 2,
+ kOldprioFieldNumber = 3,
+ kPidFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedPiSetprioFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedPiSetprioFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Newprio =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedPiSetprioFtraceEvent>;
+
+ static constexpr FieldMetadata_Newprio kNewprio{};
+ void set_newprio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Newprio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Oldprio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedPiSetprioFtraceEvent>;
+
+ static constexpr FieldMetadata_Oldprio kOldprio{};
+ void set_oldprio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Oldprio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedPiSetprioFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedProcessWaitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedProcessWaitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedProcessWaitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedProcessWaitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_prio() const { return at<3>().valid(); }
+ int32_t prio() const { return at<3>().as_int32(); }
+};
+
+class SchedProcessWaitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedProcessWaitFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedProcessWaitFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedProcessWaitFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessWaitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessWaitFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedProcessHangFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedProcessHangFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedProcessHangFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedProcessHangFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+};
+
+class SchedProcessHangFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedProcessHangFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedProcessHangFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedProcessHangFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessHangFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedProcessFreeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedProcessFreeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedProcessFreeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedProcessFreeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_prio() const { return at<3>().valid(); }
+ int32_t prio() const { return at<3>().as_int32(); }
+};
+
+class SchedProcessFreeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedProcessFreeFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedProcessFreeFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedProcessFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessFreeFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedProcessForkFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedProcessForkFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedProcessForkFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedProcessForkFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_parent_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars parent_comm() const { return at<1>().as_string(); }
+ bool has_parent_pid() const { return at<2>().valid(); }
+ int32_t parent_pid() const { return at<2>().as_int32(); }
+ bool has_child_comm() const { return at<3>().valid(); }
+ ::protozero::ConstChars child_comm() const { return at<3>().as_string(); }
+ bool has_child_pid() const { return at<4>().valid(); }
+ int32_t child_pid() const { return at<4>().as_int32(); }
+};
+
+class SchedProcessForkFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedProcessForkFtraceEvent_Decoder;
+ enum : int32_t {
+ kParentCommFieldNumber = 1,
+ kParentPidFieldNumber = 2,
+ kChildCommFieldNumber = 3,
+ kChildPidFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedProcessForkFtraceEvent"; }
+
+
+ using FieldMetadata_ParentComm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedProcessForkFtraceEvent>;
+
+ static constexpr FieldMetadata_ParentComm kParentComm{};
+ void set_parent_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ParentComm::kFieldId, data, size);
+ }
+ void set_parent_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ParentComm::kFieldId, chars.data, chars.size);
+ }
+ void set_parent_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParentComm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ParentPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessForkFtraceEvent>;
+
+ static constexpr FieldMetadata_ParentPid kParentPid{};
+ void set_parent_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ParentPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChildComm =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedProcessForkFtraceEvent>;
+
+ static constexpr FieldMetadata_ChildComm kChildComm{};
+ void set_child_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ChildComm::kFieldId, data, size);
+ }
+ void set_child_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ChildComm::kFieldId, chars.data, chars.size);
+ }
+ void set_child_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChildComm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChildPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessForkFtraceEvent>;
+
+ static constexpr FieldMetadata_ChildPid kChildPid{};
+ void set_child_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChildPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedProcessExitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedProcessExitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedProcessExitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedProcessExitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_tgid() const { return at<3>().valid(); }
+ int32_t tgid() const { return at<3>().as_int32(); }
+ bool has_prio() const { return at<4>().valid(); }
+ int32_t prio() const { return at<4>().as_int32(); }
+};
+
+class SchedProcessExitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedProcessExitFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTgidFieldNumber = 3,
+ kPrioFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedProcessExitFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedProcessExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Tgid kTgid{};
+ void set_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessExitFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedProcessExecFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedProcessExecFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedProcessExecFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedProcessExecFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_filename() const { return at<1>().valid(); }
+ ::protozero::ConstChars filename() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_old_pid() const { return at<3>().valid(); }
+ int32_t old_pid() const { return at<3>().as_int32(); }
+};
+
+class SchedProcessExecFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedProcessExecFtraceEvent_Decoder;
+ enum : int32_t {
+ kFilenameFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kOldPidFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedProcessExecFtraceEvent"; }
+
+
+ using FieldMetadata_Filename =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedProcessExecFtraceEvent>;
+
+ static constexpr FieldMetadata_Filename kFilename{};
+ void set_filename(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Filename::kFieldId, data, size);
+ }
+ void set_filename(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Filename::kFieldId, chars.data, chars.size);
+ }
+ void set_filename(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Filename::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessExecFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OldPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedProcessExecFtraceEvent>;
+
+ static constexpr FieldMetadata_OldPid kOldPid{};
+ void set_old_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OldPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedWakeupNewFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedWakeupNewFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedWakeupNewFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedWakeupNewFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_prio() const { return at<3>().valid(); }
+ int32_t prio() const { return at<3>().as_int32(); }
+ bool has_success() const { return at<4>().valid(); }
+ int32_t success() const { return at<4>().as_int32(); }
+ bool has_target_cpu() const { return at<5>().valid(); }
+ int32_t target_cpu() const { return at<5>().as_int32(); }
+};
+
+class SchedWakeupNewFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedWakeupNewFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ kSuccessFieldNumber = 4,
+ kTargetCpuFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedWakeupNewFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedWakeupNewFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupNewFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupNewFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Success =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupNewFtraceEvent>;
+
+ static constexpr FieldMetadata_Success kSuccess{};
+ void set_success(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Success::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupNewFtraceEvent>;
+
+ static constexpr FieldMetadata_TargetCpu kTargetCpu{};
+ void set_target_cpu(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedWakingFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedWakingFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedWakingFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedWakingFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_prio() const { return at<3>().valid(); }
+ int32_t prio() const { return at<3>().as_int32(); }
+ bool has_success() const { return at<4>().valid(); }
+ int32_t success() const { return at<4>().as_int32(); }
+ bool has_target_cpu() const { return at<5>().valid(); }
+ int32_t target_cpu() const { return at<5>().as_int32(); }
+};
+
+class SchedWakingFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedWakingFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ kSuccessFieldNumber = 4,
+ kTargetCpuFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedWakingFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedWakingFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakingFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakingFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Success =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakingFtraceEvent>;
+
+ static constexpr FieldMetadata_Success kSuccess{};
+ void set_success(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Success::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakingFtraceEvent>;
+
+ static constexpr FieldMetadata_TargetCpu kTargetCpu{};
+ void set_target_cpu(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedCpuHotplugFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedCpuHotplugFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedCpuHotplugFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedCpuHotplugFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_affected_cpu() const { return at<1>().valid(); }
+ int32_t affected_cpu() const { return at<1>().as_int32(); }
+ bool has_error() const { return at<2>().valid(); }
+ int32_t error() const { return at<2>().as_int32(); }
+ bool has_status() const { return at<3>().valid(); }
+ int32_t status() const { return at<3>().as_int32(); }
+};
+
+class SchedCpuHotplugFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedCpuHotplugFtraceEvent_Decoder;
+ enum : int32_t {
+ kAffectedCpuFieldNumber = 1,
+ kErrorFieldNumber = 2,
+ kStatusFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedCpuHotplugFtraceEvent"; }
+
+
+ using FieldMetadata_AffectedCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedCpuHotplugFtraceEvent>;
+
+ static constexpr FieldMetadata_AffectedCpu kAffectedCpu{};
+ void set_affected_cpu(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AffectedCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Error =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedCpuHotplugFtraceEvent>;
+
+ static constexpr FieldMetadata_Error kError{};
+ void set_error(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Error::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedCpuHotplugFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedBlockedReasonFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedBlockedReasonFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedBlockedReasonFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedBlockedReasonFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_caller() const { return at<2>().valid(); }
+ uint64_t caller() const { return at<2>().as_uint64(); }
+ bool has_io_wait() const { return at<3>().valid(); }
+ uint32_t io_wait() const { return at<3>().as_uint32(); }
+};
+
+class SchedBlockedReasonFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedBlockedReasonFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kCallerFieldNumber = 2,
+ kIoWaitFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedBlockedReasonFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedBlockedReasonFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Caller =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SchedBlockedReasonFtraceEvent>;
+
+ static constexpr FieldMetadata_Caller kCaller{};
+ void set_caller(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Caller::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IoWait =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SchedBlockedReasonFtraceEvent>;
+
+ static constexpr FieldMetadata_IoWait kIoWait{};
+ void set_io_wait(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IoWait::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedWakeupFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedWakeupFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedWakeupFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedWakeupFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars comm() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_prio() const { return at<3>().valid(); }
+ int32_t prio() const { return at<3>().as_int32(); }
+ bool has_success() const { return at<4>().valid(); }
+ int32_t success() const { return at<4>().as_int32(); }
+ bool has_target_cpu() const { return at<5>().valid(); }
+ int32_t target_cpu() const { return at<5>().as_int32(); }
+};
+
+class SchedWakeupFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedWakeupFtraceEvent_Decoder;
+ enum : int32_t {
+ kCommFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ kSuccessFieldNumber = 4,
+ kTargetCpuFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedWakeupFtraceEvent"; }
+
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Success =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_Success kSuccess{};
+ void set_success(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Success::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedWakeupFtraceEvent>;
+
+ static constexpr FieldMetadata_TargetCpu kTargetCpu{};
+ void set_target_cpu(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SchedSwitchFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SchedSwitchFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SchedSwitchFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SchedSwitchFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_prev_comm() const { return at<1>().valid(); }
+ ::protozero::ConstChars prev_comm() const { return at<1>().as_string(); }
+ bool has_prev_pid() const { return at<2>().valid(); }
+ int32_t prev_pid() const { return at<2>().as_int32(); }
+ bool has_prev_prio() const { return at<3>().valid(); }
+ int32_t prev_prio() const { return at<3>().as_int32(); }
+ bool has_prev_state() const { return at<4>().valid(); }
+ int64_t prev_state() const { return at<4>().as_int64(); }
+ bool has_next_comm() const { return at<5>().valid(); }
+ ::protozero::ConstChars next_comm() const { return at<5>().as_string(); }
+ bool has_next_pid() const { return at<6>().valid(); }
+ int32_t next_pid() const { return at<6>().as_int32(); }
+ bool has_next_prio() const { return at<7>().valid(); }
+ int32_t next_prio() const { return at<7>().as_int32(); }
+};
+
+class SchedSwitchFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SchedSwitchFtraceEvent_Decoder;
+ enum : int32_t {
+ kPrevCommFieldNumber = 1,
+ kPrevPidFieldNumber = 2,
+ kPrevPrioFieldNumber = 3,
+ kPrevStateFieldNumber = 4,
+ kNextCommFieldNumber = 5,
+ kNextPidFieldNumber = 6,
+ kNextPrioFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SchedSwitchFtraceEvent"; }
+
+
+ using FieldMetadata_PrevComm =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedSwitchFtraceEvent>;
+
+ static constexpr FieldMetadata_PrevComm kPrevComm{};
+ void set_prev_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_PrevComm::kFieldId, data, size);
+ }
+ void set_prev_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_PrevComm::kFieldId, chars.data, chars.size);
+ }
+ void set_prev_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrevComm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrevPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedSwitchFtraceEvent>;
+
+ static constexpr FieldMetadata_PrevPid kPrevPid{};
+ void set_prev_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrevPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrevPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedSwitchFtraceEvent>;
+
+ static constexpr FieldMetadata_PrevPrio kPrevPrio{};
+ void set_prev_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrevPrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrevState =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ SchedSwitchFtraceEvent>;
+
+ static constexpr FieldMetadata_PrevState kPrevState{};
+ void set_prev_state(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrevState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NextComm =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SchedSwitchFtraceEvent>;
+
+ static constexpr FieldMetadata_NextComm kNextComm{};
+ void set_next_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_NextComm::kFieldId, data, size);
+ }
+ void set_next_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_NextComm::kFieldId, chars.data, chars.size);
+ }
+ void set_next_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_NextComm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NextPid =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedSwitchFtraceEvent>;
+
+ static constexpr FieldMetadata_NextPid kNextPid{};
+ void set_next_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NextPid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NextPrio =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SchedSwitchFtraceEvent>;
+
+ static constexpr FieldMetadata_NextPrio kNextPrio{};
+ void set_next_prio(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NextPrio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/scm.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SCM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SCM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ScmCallEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ScmCallEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ScmCallEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ScmCallEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class ScmCallEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ScmCallEndFtraceEvent_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.ScmCallEndFtraceEvent"; }
+
+};
+
+class ScmCallStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ScmCallStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ScmCallStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ScmCallStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_arginfo() const { return at<1>().valid(); }
+ uint32_t arginfo() const { return at<1>().as_uint32(); }
+ bool has_x0() const { return at<2>().valid(); }
+ uint64_t x0() const { return at<2>().as_uint64(); }
+ bool has_x5() const { return at<3>().valid(); }
+ uint64_t x5() const { return at<3>().as_uint64(); }
+};
+
+class ScmCallStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ScmCallStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kArginfoFieldNumber = 1,
+ kX0FieldNumber = 2,
+ kX5FieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ScmCallStartFtraceEvent"; }
+
+
+ using FieldMetadata_Arginfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ScmCallStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Arginfo kArginfo{};
+ void set_arginfo(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Arginfo::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_X0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ScmCallStartFtraceEvent>;
+
+ static constexpr FieldMetadata_X0 kX0{};
+ void set_x0(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_X0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_X5 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ScmCallStartFtraceEvent>;
+
+ static constexpr FieldMetadata_X5 kX5{};
+ void set_x5(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_X5::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/sde.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SDE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SDE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SdeSdePerfUpdateBusFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SdeSdePerfUpdateBusFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SdeSdePerfUpdateBusFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SdeSdePerfUpdateBusFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ab_quota() const { return at<1>().valid(); }
+ uint64_t ab_quota() const { return at<1>().as_uint64(); }
+ bool has_bus_id() const { return at<2>().valid(); }
+ uint32_t bus_id() const { return at<2>().as_uint32(); }
+ bool has_client() const { return at<3>().valid(); }
+ int32_t client() const { return at<3>().as_int32(); }
+ bool has_ib_quota() const { return at<4>().valid(); }
+ uint64_t ib_quota() const { return at<4>().as_uint64(); }
+};
+
+class SdeSdePerfUpdateBusFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SdeSdePerfUpdateBusFtraceEvent_Decoder;
+ enum : int32_t {
+ kAbQuotaFieldNumber = 1,
+ kBusIdFieldNumber = 2,
+ kClientFieldNumber = 3,
+ kIbQuotaFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SdeSdePerfUpdateBusFtraceEvent"; }
+
+
+ using FieldMetadata_AbQuota =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfUpdateBusFtraceEvent>;
+
+ static constexpr FieldMetadata_AbQuota kAbQuota{};
+ void set_ab_quota(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AbQuota::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BusId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfUpdateBusFtraceEvent>;
+
+ static constexpr FieldMetadata_BusId kBusId{};
+ void set_bus_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BusId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Client =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SdeSdePerfUpdateBusFtraceEvent>;
+
+ static constexpr FieldMetadata_Client kClient{};
+ void set_client(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Client::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IbQuota =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfUpdateBusFtraceEvent>;
+
+ static constexpr FieldMetadata_IbQuota kIbQuota{};
+ void set_ib_quota(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IbQuota::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SdeSdePerfSetQosLutsFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SdeSdePerfSetQosLutsFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SdeSdePerfSetQosLutsFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SdeSdePerfSetQosLutsFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_fl() const { return at<1>().valid(); }
+ uint32_t fl() const { return at<1>().as_uint32(); }
+ bool has_fmt() const { return at<2>().valid(); }
+ uint32_t fmt() const { return at<2>().as_uint32(); }
+ bool has_lut() const { return at<3>().valid(); }
+ uint64_t lut() const { return at<3>().as_uint64(); }
+ bool has_lut_usage() const { return at<4>().valid(); }
+ uint32_t lut_usage() const { return at<4>().as_uint32(); }
+ bool has_pnum() const { return at<5>().valid(); }
+ uint32_t pnum() const { return at<5>().as_uint32(); }
+ bool has_rt() const { return at<6>().valid(); }
+ uint32_t rt() const { return at<6>().as_uint32(); }
+};
+
+class SdeSdePerfSetQosLutsFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SdeSdePerfSetQosLutsFtraceEvent_Decoder;
+ enum : int32_t {
+ kFlFieldNumber = 1,
+ kFmtFieldNumber = 2,
+ kLutFieldNumber = 3,
+ kLutUsageFieldNumber = 4,
+ kPnumFieldNumber = 5,
+ kRtFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SdeSdePerfSetQosLutsFtraceEvent"; }
+
+
+ using FieldMetadata_Fl =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Fl kFl{};
+ void set_fl(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fl::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fmt =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Fmt kFmt{};
+ void set_fmt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fmt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lut =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Lut kLut{};
+ void set_lut(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lut::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LutUsage =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_LutUsage kLutUsage{};
+ void set_lut_usage(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LutUsage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pnum =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Pnum kPnum{};
+ void set_pnum(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pnum::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Rt =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfSetQosLutsFtraceEvent>;
+
+ static constexpr FieldMetadata_Rt kRt{};
+ void set_rt(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Rt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SdeSdePerfCrtcUpdateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/12, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SdeSdePerfCrtcUpdateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SdeSdePerfCrtcUpdateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SdeSdePerfCrtcUpdateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bw_ctl_ebi() const { return at<1>().valid(); }
+ uint64_t bw_ctl_ebi() const { return at<1>().as_uint64(); }
+ bool has_bw_ctl_llcc() const { return at<2>().valid(); }
+ uint64_t bw_ctl_llcc() const { return at<2>().as_uint64(); }
+ bool has_bw_ctl_mnoc() const { return at<3>().valid(); }
+ uint64_t bw_ctl_mnoc() const { return at<3>().as_uint64(); }
+ bool has_core_clk_rate() const { return at<4>().valid(); }
+ uint32_t core_clk_rate() const { return at<4>().as_uint32(); }
+ bool has_crtc() const { return at<5>().valid(); }
+ uint32_t crtc() const { return at<5>().as_uint32(); }
+ bool has_params() const { return at<6>().valid(); }
+ int32_t params() const { return at<6>().as_int32(); }
+ bool has_per_pipe_ib_ebi() const { return at<7>().valid(); }
+ uint64_t per_pipe_ib_ebi() const { return at<7>().as_uint64(); }
+ bool has_per_pipe_ib_llcc() const { return at<8>().valid(); }
+ uint64_t per_pipe_ib_llcc() const { return at<8>().as_uint64(); }
+ bool has_per_pipe_ib_mnoc() const { return at<9>().valid(); }
+ uint64_t per_pipe_ib_mnoc() const { return at<9>().as_uint64(); }
+ bool has_stop_req() const { return at<10>().valid(); }
+ uint32_t stop_req() const { return at<10>().as_uint32(); }
+ bool has_update_bus() const { return at<11>().valid(); }
+ uint32_t update_bus() const { return at<11>().as_uint32(); }
+ bool has_update_clk() const { return at<12>().valid(); }
+ uint32_t update_clk() const { return at<12>().as_uint32(); }
+};
+
+class SdeSdePerfCrtcUpdateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SdeSdePerfCrtcUpdateFtraceEvent_Decoder;
+ enum : int32_t {
+ kBwCtlEbiFieldNumber = 1,
+ kBwCtlLlccFieldNumber = 2,
+ kBwCtlMnocFieldNumber = 3,
+ kCoreClkRateFieldNumber = 4,
+ kCrtcFieldNumber = 5,
+ kParamsFieldNumber = 6,
+ kPerPipeIbEbiFieldNumber = 7,
+ kPerPipeIbLlccFieldNumber = 8,
+ kPerPipeIbMnocFieldNumber = 9,
+ kStopReqFieldNumber = 10,
+ kUpdateBusFieldNumber = 11,
+ kUpdateClkFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SdeSdePerfCrtcUpdateFtraceEvent"; }
+
+
+ using FieldMetadata_BwCtlEbi =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_BwCtlEbi kBwCtlEbi{};
+ void set_bw_ctl_ebi(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BwCtlEbi::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BwCtlLlcc =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_BwCtlLlcc kBwCtlLlcc{};
+ void set_bw_ctl_llcc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BwCtlLlcc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BwCtlMnoc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_BwCtlMnoc kBwCtlMnoc{};
+ void set_bw_ctl_mnoc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BwCtlMnoc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CoreClkRate =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_CoreClkRate kCoreClkRate{};
+ void set_core_clk_rate(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CoreClkRate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Crtc =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_Crtc kCrtc{};
+ void set_crtc(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Crtc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Params =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_Params kParams{};
+ void set_params(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Params::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PerPipeIbEbi =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_PerPipeIbEbi kPerPipeIbEbi{};
+ void set_per_pipe_ib_ebi(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PerPipeIbEbi::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PerPipeIbLlcc =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_PerPipeIbLlcc kPerPipeIbLlcc{};
+ void set_per_pipe_ib_llcc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PerPipeIbLlcc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PerPipeIbMnoc =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_PerPipeIbMnoc kPerPipeIbMnoc{};
+ void set_per_pipe_ib_mnoc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PerPipeIbMnoc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StopReq =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_StopReq kStopReq{};
+ void set_stop_req(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StopReq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UpdateBus =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_UpdateBus kUpdateBus{};
+ void set_update_bus(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UpdateBus::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UpdateClk =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfCrtcUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_UpdateClk kUpdateClk{};
+ void set_update_clk(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UpdateClk::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SdeSdePerfCalcCrtcFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SdeSdePerfCalcCrtcFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SdeSdePerfCalcCrtcFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SdeSdePerfCalcCrtcFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bw_ctl_ebi() const { return at<1>().valid(); }
+ uint64_t bw_ctl_ebi() const { return at<1>().as_uint64(); }
+ bool has_bw_ctl_llcc() const { return at<2>().valid(); }
+ uint64_t bw_ctl_llcc() const { return at<2>().as_uint64(); }
+ bool has_bw_ctl_mnoc() const { return at<3>().valid(); }
+ uint64_t bw_ctl_mnoc() const { return at<3>().as_uint64(); }
+ bool has_core_clk_rate() const { return at<4>().valid(); }
+ uint32_t core_clk_rate() const { return at<4>().as_uint32(); }
+ bool has_crtc() const { return at<5>().valid(); }
+ uint32_t crtc() const { return at<5>().as_uint32(); }
+ bool has_ib_ebi() const { return at<6>().valid(); }
+ uint64_t ib_ebi() const { return at<6>().as_uint64(); }
+ bool has_ib_llcc() const { return at<7>().valid(); }
+ uint64_t ib_llcc() const { return at<7>().as_uint64(); }
+ bool has_ib_mnoc() const { return at<8>().valid(); }
+ uint64_t ib_mnoc() const { return at<8>().as_uint64(); }
+};
+
+class SdeSdePerfCalcCrtcFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SdeSdePerfCalcCrtcFtraceEvent_Decoder;
+ enum : int32_t {
+ kBwCtlEbiFieldNumber = 1,
+ kBwCtlLlccFieldNumber = 2,
+ kBwCtlMnocFieldNumber = 3,
+ kCoreClkRateFieldNumber = 4,
+ kCrtcFieldNumber = 5,
+ kIbEbiFieldNumber = 6,
+ kIbLlccFieldNumber = 7,
+ kIbMnocFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SdeSdePerfCalcCrtcFtraceEvent"; }
+
+
+ using FieldMetadata_BwCtlEbi =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_BwCtlEbi kBwCtlEbi{};
+ void set_bw_ctl_ebi(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BwCtlEbi::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BwCtlLlcc =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_BwCtlLlcc kBwCtlLlcc{};
+ void set_bw_ctl_llcc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BwCtlLlcc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BwCtlMnoc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_BwCtlMnoc kBwCtlMnoc{};
+ void set_bw_ctl_mnoc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BwCtlMnoc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CoreClkRate =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_CoreClkRate kCoreClkRate{};
+ void set_core_clk_rate(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CoreClkRate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Crtc =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_Crtc kCrtc{};
+ void set_crtc(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Crtc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IbEbi =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_IbEbi kIbEbi{};
+ void set_ib_ebi(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IbEbi::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IbLlcc =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_IbLlcc kIbLlcc{};
+ void set_ib_llcc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IbLlcc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IbMnoc =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SdeSdePerfCalcCrtcFtraceEvent>;
+
+ static constexpr FieldMetadata_IbMnoc kIbMnoc{};
+ void set_ib_mnoc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IbMnoc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SdeSdeEvtlogFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SdeSdeEvtlogFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SdeSdeEvtlogFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SdeSdeEvtlogFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_evtlog_tag() const { return at<1>().valid(); }
+ ::protozero::ConstChars evtlog_tag() const { return at<1>().as_string(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_tag_id() const { return at<3>().valid(); }
+ uint32_t tag_id() const { return at<3>().as_uint32(); }
+};
+
+class SdeSdeEvtlogFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SdeSdeEvtlogFtraceEvent_Decoder;
+ enum : int32_t {
+ kEvtlogTagFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTagIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SdeSdeEvtlogFtraceEvent"; }
+
+
+ using FieldMetadata_EvtlogTag =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SdeSdeEvtlogFtraceEvent>;
+
+ static constexpr FieldMetadata_EvtlogTag kEvtlogTag{};
+ void set_evtlog_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_EvtlogTag::kFieldId, data, size);
+ }
+ void set_evtlog_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_EvtlogTag::kFieldId, chars.data, chars.size);
+ }
+ void set_evtlog_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_EvtlogTag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SdeSdeEvtlogFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TagId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeSdeEvtlogFtraceEvent>;
+
+ static constexpr FieldMetadata_TagId kTagId{};
+ void set_tag_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TagId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SdeTracingMarkWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SdeTracingMarkWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SdeTracingMarkWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SdeTracingMarkWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_trace_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars trace_name() const { return at<2>().as_string(); }
+ bool has_trace_type() const { return at<3>().valid(); }
+ uint32_t trace_type() const { return at<3>().as_uint32(); }
+ bool has_value() const { return at<4>().valid(); }
+ int32_t value() const { return at<4>().as_int32(); }
+ bool has_trace_begin() const { return at<5>().valid(); }
+ uint32_t trace_begin() const { return at<5>().as_uint32(); }
+};
+
+class SdeTracingMarkWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SdeTracingMarkWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kTraceNameFieldNumber = 2,
+ kTraceTypeFieldNumber = 3,
+ kValueFieldNumber = 4,
+ kTraceBeginFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SdeTracingMarkWriteFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SdeTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SdeTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceName kTraceName{};
+ void set_trace_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, data, size);
+ }
+ void set_trace_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_TraceName::kFieldId, chars.data, chars.size);
+ }
+ void set_trace_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceType =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceType kTraceType{};
+ void set_trace_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SdeTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TraceBegin =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SdeTracingMarkWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_TraceBegin kTraceBegin{};
+ void set_trace_begin(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceBegin::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/signal.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SIGNAL_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SIGNAL_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SignalGenerateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SignalGenerateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SignalGenerateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SignalGenerateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_code() const { return at<1>().valid(); }
+ int32_t code() const { return at<1>().as_int32(); }
+ bool has_comm() const { return at<2>().valid(); }
+ ::protozero::ConstChars comm() const { return at<2>().as_string(); }
+ bool has_group() const { return at<3>().valid(); }
+ int32_t group() const { return at<3>().as_int32(); }
+ bool has_pid() const { return at<4>().valid(); }
+ int32_t pid() const { return at<4>().as_int32(); }
+ bool has_result() const { return at<5>().valid(); }
+ int32_t result() const { return at<5>().as_int32(); }
+ bool has_sig() const { return at<6>().valid(); }
+ int32_t sig() const { return at<6>().as_int32(); }
+};
+
+class SignalGenerateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SignalGenerateFtraceEvent_Decoder;
+ enum : int32_t {
+ kCodeFieldNumber = 1,
+ kCommFieldNumber = 2,
+ kGroupFieldNumber = 3,
+ kPidFieldNumber = 4,
+ kResultFieldNumber = 5,
+ kSigFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SignalGenerateFtraceEvent"; }
+
+
+ using FieldMetadata_Code =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SignalGenerateFtraceEvent>;
+
+ static constexpr FieldMetadata_Code kCode{};
+ void set_code(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Code::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SignalGenerateFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Group =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SignalGenerateFtraceEvent>;
+
+ static constexpr FieldMetadata_Group kGroup{};
+ void set_group(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Group::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SignalGenerateFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Result =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SignalGenerateFtraceEvent>;
+
+ static constexpr FieldMetadata_Result kResult{};
+ void set_result(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Result::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sig =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SignalGenerateFtraceEvent>;
+
+ static constexpr FieldMetadata_Sig kSig{};
+ void set_sig(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SignalDeliverFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SignalDeliverFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SignalDeliverFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SignalDeliverFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_code() const { return at<1>().valid(); }
+ int32_t code() const { return at<1>().as_int32(); }
+ bool has_sa_flags() const { return at<2>().valid(); }
+ uint64_t sa_flags() const { return at<2>().as_uint64(); }
+ bool has_sig() const { return at<3>().valid(); }
+ int32_t sig() const { return at<3>().as_int32(); }
+};
+
+class SignalDeliverFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SignalDeliverFtraceEvent_Decoder;
+ enum : int32_t {
+ kCodeFieldNumber = 1,
+ kSaFlagsFieldNumber = 2,
+ kSigFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SignalDeliverFtraceEvent"; }
+
+
+ using FieldMetadata_Code =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SignalDeliverFtraceEvent>;
+
+ static constexpr FieldMetadata_Code kCode{};
+ void set_code(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Code::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SaFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SignalDeliverFtraceEvent>;
+
+ static constexpr FieldMetadata_SaFlags kSaFlags{};
+ void set_sa_flags(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SaFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sig =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SignalDeliverFtraceEvent>;
+
+ static constexpr FieldMetadata_Sig kSig{};
+ void set_sig(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sig::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/skb.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SKB_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SKB_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class KfreeSkbFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ KfreeSkbFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit KfreeSkbFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit KfreeSkbFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_location() const { return at<1>().valid(); }
+ uint64_t location() const { return at<1>().as_uint64(); }
+ bool has_protocol() const { return at<2>().valid(); }
+ uint32_t protocol() const { return at<2>().as_uint32(); }
+ bool has_skbaddr() const { return at<3>().valid(); }
+ uint64_t skbaddr() const { return at<3>().as_uint64(); }
+};
+
+class KfreeSkbFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = KfreeSkbFtraceEvent_Decoder;
+ enum : int32_t {
+ kLocationFieldNumber = 1,
+ kProtocolFieldNumber = 2,
+ kSkbaddrFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.KfreeSkbFtraceEvent"; }
+
+
+ using FieldMetadata_Location =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KfreeSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Location kLocation{};
+ void set_location(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Location::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Protocol =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ KfreeSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Protocol kProtocol{};
+ void set_protocol(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Protocol::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Skbaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ KfreeSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Skbaddr kSkbaddr{};
+ void set_skbaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Skbaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/sock.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SOCK_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SOCK_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class InetSockSetStateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InetSockSetStateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InetSockSetStateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InetSockSetStateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_daddr() const { return at<1>().valid(); }
+ uint32_t daddr() const { return at<1>().as_uint32(); }
+ bool has_dport() const { return at<2>().valid(); }
+ uint32_t dport() const { return at<2>().as_uint32(); }
+ bool has_family() const { return at<3>().valid(); }
+ uint32_t family() const { return at<3>().as_uint32(); }
+ bool has_newstate() const { return at<4>().valid(); }
+ int32_t newstate() const { return at<4>().as_int32(); }
+ bool has_oldstate() const { return at<5>().valid(); }
+ int32_t oldstate() const { return at<5>().as_int32(); }
+ bool has_protocol() const { return at<6>().valid(); }
+ uint32_t protocol() const { return at<6>().as_uint32(); }
+ bool has_saddr() const { return at<7>().valid(); }
+ uint32_t saddr() const { return at<7>().as_uint32(); }
+ bool has_skaddr() const { return at<8>().valid(); }
+ uint64_t skaddr() const { return at<8>().as_uint64(); }
+ bool has_sport() const { return at<9>().valid(); }
+ uint32_t sport() const { return at<9>().as_uint32(); }
+};
+
+class InetSockSetStateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = InetSockSetStateFtraceEvent_Decoder;
+ enum : int32_t {
+ kDaddrFieldNumber = 1,
+ kDportFieldNumber = 2,
+ kFamilyFieldNumber = 3,
+ kNewstateFieldNumber = 4,
+ kOldstateFieldNumber = 5,
+ kProtocolFieldNumber = 6,
+ kSaddrFieldNumber = 7,
+ kSkaddrFieldNumber = 8,
+ kSportFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InetSockSetStateFtraceEvent"; }
+
+
+ using FieldMetadata_Daddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Daddr kDaddr{};
+ void set_daddr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Daddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dport =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Dport kDport{};
+ void set_dport(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dport::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Family =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Family kFamily{};
+ void set_family(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Family::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Newstate =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Newstate kNewstate{};
+ void set_newstate(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Newstate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Oldstate =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Oldstate kOldstate{};
+ void set_oldstate(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Oldstate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Protocol =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Protocol kProtocol{};
+ void set_protocol(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Protocol::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Saddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Saddr kSaddr{};
+ void set_saddr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Saddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Skaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Skaddr kSkaddr{};
+ void set_skaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Skaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sport =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ InetSockSetStateFtraceEvent>;
+
+ static constexpr FieldMetadata_Sport kSport{};
+ void set_sport(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sport::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/sync.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SYNC_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SYNC_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SyncWaitFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SyncWaitFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SyncWaitFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SyncWaitFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_status() const { return at<2>().valid(); }
+ int32_t status() const { return at<2>().as_int32(); }
+ bool has_begin() const { return at<3>().valid(); }
+ uint32_t begin() const { return at<3>().as_uint32(); }
+};
+
+class SyncWaitFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SyncWaitFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kStatusFieldNumber = 2,
+ kBeginFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SyncWaitFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SyncWaitFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Status =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SyncWaitFtraceEvent>;
+
+ static constexpr FieldMetadata_Status kStatus{};
+ void set_status(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Status::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Begin =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SyncWaitFtraceEvent>;
+
+ static constexpr FieldMetadata_Begin kBegin{};
+ void set_begin(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Begin::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SyncTimelineFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SyncTimelineFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SyncTimelineFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SyncTimelineFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class SyncTimelineFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SyncTimelineFtraceEvent_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SyncTimelineFtraceEvent"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SyncTimelineFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SyncTimelineFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SyncPtFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SyncPtFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SyncPtFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SyncPtFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timeline() const { return at<1>().valid(); }
+ ::protozero::ConstChars timeline() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class SyncPtFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SyncPtFtraceEvent_Decoder;
+ enum : int32_t {
+ kTimelineFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SyncPtFtraceEvent"; }
+
+
+ using FieldMetadata_Timeline =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SyncPtFtraceEvent>;
+
+ static constexpr FieldMetadata_Timeline kTimeline{};
+ void set_timeline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, data, size);
+ }
+ void set_timeline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Timeline::kFieldId, chars.data, chars.size);
+ }
+ void set_timeline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timeline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SyncPtFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/synthetic.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SYNTHETIC_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SYNTHETIC_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SuspendResumeMinimalFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SuspendResumeMinimalFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SuspendResumeMinimalFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SuspendResumeMinimalFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_start() const { return at<1>().valid(); }
+ uint32_t start() const { return at<1>().as_uint32(); }
+};
+
+class SuspendResumeMinimalFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = SuspendResumeMinimalFtraceEvent_Decoder;
+ enum : int32_t {
+ kStartFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SuspendResumeMinimalFtraceEvent"; }
+
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SuspendResumeMinimalFtraceEvent>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class RssStatThrottledFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RssStatThrottledFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RssStatThrottledFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RssStatThrottledFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_curr() const { return at<1>().valid(); }
+ uint32_t curr() const { return at<1>().as_uint32(); }
+ bool has_member() const { return at<2>().valid(); }
+ int32_t member() const { return at<2>().as_int32(); }
+ bool has_mm_id() const { return at<3>().valid(); }
+ uint32_t mm_id() const { return at<3>().as_uint32(); }
+ bool has_size() const { return at<4>().valid(); }
+ int64_t size() const { return at<4>().as_int64(); }
+};
+
+class RssStatThrottledFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = RssStatThrottledFtraceEvent_Decoder;
+ enum : int32_t {
+ kCurrFieldNumber = 1,
+ kMemberFieldNumber = 2,
+ kMmIdFieldNumber = 3,
+ kSizeFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RssStatThrottledFtraceEvent"; }
+
+
+ using FieldMetadata_Curr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ RssStatThrottledFtraceEvent>;
+
+ static constexpr FieldMetadata_Curr kCurr{};
+ void set_curr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Curr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Member =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ RssStatThrottledFtraceEvent>;
+
+ static constexpr FieldMetadata_Member kMember{};
+ void set_member(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Member::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MmId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ RssStatThrottledFtraceEvent>;
+
+ static constexpr FieldMetadata_MmId kMmId{};
+ void set_mm_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MmId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ RssStatThrottledFtraceEvent>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void set_size(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/systrace.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SYSTRACE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_SYSTRACE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ZeroFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ZeroFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ZeroFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ZeroFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_flag() const { return at<1>().valid(); }
+ int32_t flag() const { return at<1>().as_int32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_pid() const { return at<3>().valid(); }
+ int32_t pid() const { return at<3>().as_int32(); }
+ bool has_value() const { return at<4>().valid(); }
+ int64_t value() const { return at<4>().as_int64(); }
+};
+
+class ZeroFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ZeroFtraceEvent_Decoder;
+ enum : int32_t {
+ kFlagFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kPidFieldNumber = 3,
+ kValueFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ZeroFtraceEvent"; }
+
+
+ using FieldMetadata_Flag =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ZeroFtraceEvent>;
+
+ static constexpr FieldMetadata_Flag kFlag{};
+ void set_flag(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ZeroFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ZeroFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ZeroFtraceEvent>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/task.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TASK_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TASK_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TaskRenameFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TaskRenameFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TaskRenameFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TaskRenameFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_oldcomm() const { return at<2>().valid(); }
+ ::protozero::ConstChars oldcomm() const { return at<2>().as_string(); }
+ bool has_newcomm() const { return at<3>().valid(); }
+ ::protozero::ConstChars newcomm() const { return at<3>().as_string(); }
+ bool has_oom_score_adj() const { return at<4>().valid(); }
+ int32_t oom_score_adj() const { return at<4>().as_int32(); }
+};
+
+class TaskRenameFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TaskRenameFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kOldcommFieldNumber = 2,
+ kNewcommFieldNumber = 3,
+ kOomScoreAdjFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TaskRenameFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TaskRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Oldcomm =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TaskRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Oldcomm kOldcomm{};
+ void set_oldcomm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Oldcomm::kFieldId, data, size);
+ }
+ void set_oldcomm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Oldcomm::kFieldId, chars.data, chars.size);
+ }
+ void set_oldcomm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Oldcomm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Newcomm =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TaskRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_Newcomm kNewcomm{};
+ void set_newcomm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Newcomm::kFieldId, data, size);
+ }
+ void set_newcomm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Newcomm::kFieldId, chars.data, chars.size);
+ }
+ void set_newcomm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Newcomm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OomScoreAdj =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TaskRenameFtraceEvent>;
+
+ static constexpr FieldMetadata_OomScoreAdj kOomScoreAdj{};
+ void set_oom_score_adj(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OomScoreAdj::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TaskNewtaskFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TaskNewtaskFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TaskNewtaskFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TaskNewtaskFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_comm() const { return at<2>().valid(); }
+ ::protozero::ConstChars comm() const { return at<2>().as_string(); }
+ bool has_clone_flags() const { return at<3>().valid(); }
+ uint64_t clone_flags() const { return at<3>().as_uint64(); }
+ bool has_oom_score_adj() const { return at<4>().valid(); }
+ int32_t oom_score_adj() const { return at<4>().as_int32(); }
+};
+
+class TaskNewtaskFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TaskNewtaskFtraceEvent_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kCommFieldNumber = 2,
+ kCloneFlagsFieldNumber = 3,
+ kOomScoreAdjFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TaskNewtaskFtraceEvent"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TaskNewtaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Comm =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TaskNewtaskFtraceEvent>;
+
+ static constexpr FieldMetadata_Comm kComm{};
+ void set_comm(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, data, size);
+ }
+ void set_comm(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Comm::kFieldId, chars.data, chars.size);
+ }
+ void set_comm(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Comm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CloneFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TaskNewtaskFtraceEvent>;
+
+ static constexpr FieldMetadata_CloneFlags kCloneFlags{};
+ void set_clone_flags(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CloneFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OomScoreAdj =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TaskNewtaskFtraceEvent>;
+
+ static constexpr FieldMetadata_OomScoreAdj kOomScoreAdj{};
+ void set_oom_score_adj(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OomScoreAdj::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/tcp.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TCP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TCP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TcpRetransmitSkbFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TcpRetransmitSkbFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TcpRetransmitSkbFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TcpRetransmitSkbFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_daddr() const { return at<1>().valid(); }
+ uint32_t daddr() const { return at<1>().as_uint32(); }
+ bool has_dport() const { return at<2>().valid(); }
+ uint32_t dport() const { return at<2>().as_uint32(); }
+ bool has_saddr() const { return at<3>().valid(); }
+ uint32_t saddr() const { return at<3>().as_uint32(); }
+ bool has_skaddr() const { return at<4>().valid(); }
+ uint64_t skaddr() const { return at<4>().as_uint64(); }
+ bool has_skbaddr() const { return at<5>().valid(); }
+ uint64_t skbaddr() const { return at<5>().as_uint64(); }
+ bool has_sport() const { return at<6>().valid(); }
+ uint32_t sport() const { return at<6>().as_uint32(); }
+ bool has_state() const { return at<7>().valid(); }
+ int32_t state() const { return at<7>().as_int32(); }
+};
+
+class TcpRetransmitSkbFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TcpRetransmitSkbFtraceEvent_Decoder;
+ enum : int32_t {
+ kDaddrFieldNumber = 1,
+ kDportFieldNumber = 2,
+ kSaddrFieldNumber = 3,
+ kSkaddrFieldNumber = 4,
+ kSkbaddrFieldNumber = 5,
+ kSportFieldNumber = 6,
+ kStateFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TcpRetransmitSkbFtraceEvent"; }
+
+
+ using FieldMetadata_Daddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TcpRetransmitSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Daddr kDaddr{};
+ void set_daddr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Daddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dport =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TcpRetransmitSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Dport kDport{};
+ void set_dport(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dport::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Saddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TcpRetransmitSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Saddr kSaddr{};
+ void set_saddr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Saddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Skaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TcpRetransmitSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Skaddr kSkaddr{};
+ void set_skaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Skaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Skbaddr =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TcpRetransmitSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Skbaddr kSkbaddr{};
+ void set_skbaddr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Skbaddr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sport =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TcpRetransmitSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_Sport kSport{};
+ void set_sport(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sport::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TcpRetransmitSkbFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/thermal.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_THERMAL_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_THERMAL_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class CdevUpdateFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CdevUpdateFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CdevUpdateFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CdevUpdateFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_target() const { return at<1>().valid(); }
+ uint64_t target() const { return at<1>().as_uint64(); }
+ bool has_type() const { return at<2>().valid(); }
+ ::protozero::ConstChars type() const { return at<2>().as_string(); }
+};
+
+class CdevUpdateFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = CdevUpdateFtraceEvent_Decoder;
+ enum : int32_t {
+ kTargetFieldNumber = 1,
+ kTypeFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CdevUpdateFtraceEvent"; }
+
+
+ using FieldMetadata_Target =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ CdevUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_Target kTarget{};
+ void set_target(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Target::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CdevUpdateFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Type::kFieldId, data, size);
+ }
+ void set_type(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Type::kFieldId, chars.data, chars.size);
+ }
+ void set_type(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ThermalTemperatureFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ThermalTemperatureFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ThermalTemperatureFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ThermalTemperatureFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ int32_t id() const { return at<1>().as_int32(); }
+ bool has_temp() const { return at<2>().valid(); }
+ int32_t temp() const { return at<2>().as_int32(); }
+ bool has_temp_prev() const { return at<3>().valid(); }
+ int32_t temp_prev() const { return at<3>().as_int32(); }
+ bool has_thermal_zone() const { return at<4>().valid(); }
+ ::protozero::ConstChars thermal_zone() const { return at<4>().as_string(); }
+};
+
+class ThermalTemperatureFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = ThermalTemperatureFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kTempFieldNumber = 2,
+ kTempPrevFieldNumber = 3,
+ kThermalZoneFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ThermalTemperatureFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ThermalTemperatureFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Temp =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ThermalTemperatureFtraceEvent>;
+
+ static constexpr FieldMetadata_Temp kTemp{};
+ void set_temp(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Temp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TempPrev =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ThermalTemperatureFtraceEvent>;
+
+ static constexpr FieldMetadata_TempPrev kTempPrev{};
+ void set_temp_prev(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TempPrev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThermalZone =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ThermalTemperatureFtraceEvent>;
+
+ static constexpr FieldMetadata_ThermalZone kThermalZone{};
+ void set_thermal_zone(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ThermalZone::kFieldId, data, size);
+ }
+ void set_thermal_zone(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ThermalZone::kFieldId, chars.data, chars.size);
+ }
+ void set_thermal_zone(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThermalZone::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/trusty.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TRUSTY_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_TRUSTY_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TrustyEnqueueNopFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyEnqueueNopFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyEnqueueNopFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyEnqueueNopFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_arg1() const { return at<1>().valid(); }
+ uint32_t arg1() const { return at<1>().as_uint32(); }
+ bool has_arg2() const { return at<2>().valid(); }
+ uint32_t arg2() const { return at<2>().as_uint32(); }
+ bool has_arg3() const { return at<3>().valid(); }
+ uint32_t arg3() const { return at<3>().as_uint32(); }
+};
+
+class TrustyEnqueueNopFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyEnqueueNopFtraceEvent_Decoder;
+ enum : int32_t {
+ kArg1FieldNumber = 1,
+ kArg2FieldNumber = 2,
+ kArg3FieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyEnqueueNopFtraceEvent"; }
+
+
+ using FieldMetadata_Arg1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyEnqueueNopFtraceEvent>;
+
+ static constexpr FieldMetadata_Arg1 kArg1{};
+ void set_arg1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Arg1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Arg2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyEnqueueNopFtraceEvent>;
+
+ static constexpr FieldMetadata_Arg2 kArg2{};
+ void set_arg2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Arg2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Arg3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyEnqueueNopFtraceEvent>;
+
+ static constexpr FieldMetadata_Arg3 kArg3{};
+ void set_arg3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Arg3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcRxFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcRxFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcRxFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcRxFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buf_id() const { return at<1>().valid(); }
+ uint64_t buf_id() const { return at<1>().as_uint64(); }
+ bool has_chan() const { return at<2>().valid(); }
+ uint32_t chan() const { return at<2>().as_uint32(); }
+ bool has_srv_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars srv_name() const { return at<3>().as_string(); }
+};
+
+class TrustyIpcRxFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcRxFtraceEvent_Decoder;
+ enum : int32_t {
+ kBufIdFieldNumber = 1,
+ kChanFieldNumber = 2,
+ kSrvNameFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcRxFtraceEvent"; }
+
+
+ using FieldMetadata_BufId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyIpcRxFtraceEvent>;
+
+ static constexpr FieldMetadata_BufId kBufId{};
+ void set_buf_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcRxFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrvName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrustyIpcRxFtraceEvent>;
+
+ static constexpr FieldMetadata_SrvName kSrvName{};
+ void set_srv_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, data, size);
+ }
+ void set_srv_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, chars.data, chars.size);
+ }
+ void set_srv_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrvName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcReadEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcReadEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcReadEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcReadEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buf_id() const { return at<1>().valid(); }
+ uint64_t buf_id() const { return at<1>().as_uint64(); }
+ bool has_chan() const { return at<2>().valid(); }
+ uint32_t chan() const { return at<2>().as_uint32(); }
+ bool has_len_or_err() const { return at<3>().valid(); }
+ int32_t len_or_err() const { return at<3>().as_int32(); }
+ bool has_shm_cnt() const { return at<4>().valid(); }
+ uint64_t shm_cnt() const { return at<4>().as_uint64(); }
+ bool has_srv_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars srv_name() const { return at<5>().as_string(); }
+};
+
+class TrustyIpcReadEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcReadEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kBufIdFieldNumber = 1,
+ kChanFieldNumber = 2,
+ kLenOrErrFieldNumber = 3,
+ kShmCntFieldNumber = 4,
+ kSrvNameFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcReadEndFtraceEvent"; }
+
+
+ using FieldMetadata_BufId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyIpcReadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_BufId kBufId{};
+ void set_buf_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcReadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LenOrErr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyIpcReadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_LenOrErr kLenOrErr{};
+ void set_len_or_err(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LenOrErr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ShmCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyIpcReadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_ShmCnt kShmCnt{};
+ void set_shm_cnt(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShmCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrvName =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrustyIpcReadEndFtraceEvent>;
+
+ static constexpr FieldMetadata_SrvName kSrvName{};
+ void set_srv_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, data, size);
+ }
+ void set_srv_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, chars.data, chars.size);
+ }
+ void set_srv_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrvName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcReadFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcReadFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcReadFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcReadFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chan() const { return at<1>().valid(); }
+ uint32_t chan() const { return at<1>().as_uint32(); }
+ bool has_srv_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars srv_name() const { return at<2>().as_string(); }
+};
+
+class TrustyIpcReadFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcReadFtraceEvent_Decoder;
+ enum : int32_t {
+ kChanFieldNumber = 1,
+ kSrvNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcReadFtraceEvent"; }
+
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcReadFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrvName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrustyIpcReadFtraceEvent>;
+
+ static constexpr FieldMetadata_SrvName kSrvName{};
+ void set_srv_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, data, size);
+ }
+ void set_srv_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, chars.data, chars.size);
+ }
+ void set_srv_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrvName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcPollFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcPollFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcPollFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcPollFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chan() const { return at<1>().valid(); }
+ uint32_t chan() const { return at<1>().as_uint32(); }
+ bool has_poll_mask() const { return at<2>().valid(); }
+ uint32_t poll_mask() const { return at<2>().as_uint32(); }
+ bool has_srv_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars srv_name() const { return at<3>().as_string(); }
+};
+
+class TrustyIpcPollFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcPollFtraceEvent_Decoder;
+ enum : int32_t {
+ kChanFieldNumber = 1,
+ kPollMaskFieldNumber = 2,
+ kSrvNameFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcPollFtraceEvent"; }
+
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcPollFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PollMask =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcPollFtraceEvent>;
+
+ static constexpr FieldMetadata_PollMask kPollMask{};
+ void set_poll_mask(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PollMask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrvName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrustyIpcPollFtraceEvent>;
+
+ static constexpr FieldMetadata_SrvName kSrvName{};
+ void set_srv_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, data, size);
+ }
+ void set_srv_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, chars.data, chars.size);
+ }
+ void set_srv_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrvName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcWriteFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcWriteFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcWriteFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcWriteFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buf_id() const { return at<1>().valid(); }
+ uint64_t buf_id() const { return at<1>().as_uint64(); }
+ bool has_chan() const { return at<2>().valid(); }
+ uint32_t chan() const { return at<2>().as_uint32(); }
+ bool has_kind_shm() const { return at<3>().valid(); }
+ int32_t kind_shm() const { return at<3>().as_int32(); }
+ bool has_len_or_err() const { return at<4>().valid(); }
+ int32_t len_or_err() const { return at<4>().as_int32(); }
+ bool has_shm_cnt() const { return at<5>().valid(); }
+ uint64_t shm_cnt() const { return at<5>().as_uint64(); }
+ bool has_srv_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars srv_name() const { return at<6>().as_string(); }
+};
+
+class TrustyIpcWriteFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcWriteFtraceEvent_Decoder;
+ enum : int32_t {
+ kBufIdFieldNumber = 1,
+ kChanFieldNumber = 2,
+ kKindShmFieldNumber = 3,
+ kLenOrErrFieldNumber = 4,
+ kShmCntFieldNumber = 5,
+ kSrvNameFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcWriteFtraceEvent"; }
+
+
+ using FieldMetadata_BufId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyIpcWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_BufId kBufId{};
+ void set_buf_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KindShm =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyIpcWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_KindShm kKindShm{};
+ void set_kind_shm(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KindShm::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LenOrErr =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyIpcWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_LenOrErr kLenOrErr{};
+ void set_len_or_err(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LenOrErr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ShmCnt =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyIpcWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_ShmCnt kShmCnt{};
+ void set_shm_cnt(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ShmCnt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrvName =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrustyIpcWriteFtraceEvent>;
+
+ static constexpr FieldMetadata_SrvName kSrvName{};
+ void set_srv_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, data, size);
+ }
+ void set_srv_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, chars.data, chars.size);
+ }
+ void set_srv_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrvName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcConnectEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcConnectEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcConnectEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcConnectEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chan() const { return at<1>().valid(); }
+ uint32_t chan() const { return at<1>().as_uint32(); }
+ bool has_err() const { return at<2>().valid(); }
+ int32_t err() const { return at<2>().as_int32(); }
+ bool has_state() const { return at<3>().valid(); }
+ int32_t state() const { return at<3>().as_int32(); }
+};
+
+class TrustyIpcConnectEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcConnectEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kChanFieldNumber = 1,
+ kErrFieldNumber = 2,
+ kStateFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcConnectEndFtraceEvent"; }
+
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcConnectEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Err =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyIpcConnectEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Err kErr{};
+ void set_err(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Err::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyIpcConnectEndFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcConnectFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcConnectFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcConnectFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcConnectFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chan() const { return at<1>().valid(); }
+ uint32_t chan() const { return at<1>().as_uint32(); }
+ bool has_port() const { return at<2>().valid(); }
+ ::protozero::ConstChars port() const { return at<2>().as_string(); }
+ bool has_state() const { return at<3>().valid(); }
+ int32_t state() const { return at<3>().as_int32(); }
+};
+
+class TrustyIpcConnectFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcConnectFtraceEvent_Decoder;
+ enum : int32_t {
+ kChanFieldNumber = 1,
+ kPortFieldNumber = 2,
+ kStateFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcConnectFtraceEvent"; }
+
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcConnectFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Port =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrustyIpcConnectFtraceEvent>;
+
+ static constexpr FieldMetadata_Port kPort{};
+ void set_port(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Port::kFieldId, data, size);
+ }
+ void set_port(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Port::kFieldId, chars.data, chars.size);
+ }
+ void set_port(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Port::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyIpcConnectFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIpcHandleEventFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIpcHandleEventFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIpcHandleEventFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIpcHandleEventFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chan() const { return at<1>().valid(); }
+ uint32_t chan() const { return at<1>().as_uint32(); }
+ bool has_event_id() const { return at<2>().valid(); }
+ uint32_t event_id() const { return at<2>().as_uint32(); }
+ bool has_srv_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars srv_name() const { return at<3>().as_string(); }
+};
+
+class TrustyIpcHandleEventFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIpcHandleEventFtraceEvent_Decoder;
+ enum : int32_t {
+ kChanFieldNumber = 1,
+ kEventIdFieldNumber = 2,
+ kSrvNameFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIpcHandleEventFtraceEvent"; }
+
+
+ using FieldMetadata_Chan =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcHandleEventFtraceEvent>;
+
+ static constexpr FieldMetadata_Chan kChan{};
+ void set_chan(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Chan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyIpcHandleEventFtraceEvent>;
+
+ static constexpr FieldMetadata_EventId kEventId{};
+ void set_event_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SrvName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TrustyIpcHandleEventFtraceEvent>;
+
+ static constexpr FieldMetadata_SrvName kSrvName{};
+ void set_srv_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, data, size);
+ }
+ void set_srv_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SrvName::kFieldId, chars.data, chars.size);
+ }
+ void set_srv_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SrvName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyIrqFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyIrqFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyIrqFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyIrqFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irq() const { return at<1>().valid(); }
+ int32_t irq() const { return at<1>().as_int32(); }
+};
+
+class TrustyIrqFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyIrqFtraceEvent_Decoder;
+ enum : int32_t {
+ kIrqFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyIrqFtraceEvent"; }
+
+
+ using FieldMetadata_Irq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyIrqFtraceEvent>;
+
+ static constexpr FieldMetadata_Irq kIrq{};
+ void set_irq(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Irq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyReclaimMemoryDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyReclaimMemoryDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyReclaimMemoryDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyReclaimMemoryDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+ bool has_ret() const { return at<2>().valid(); }
+ int32_t ret() const { return at<2>().as_int32(); }
+};
+
+class TrustyReclaimMemoryDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyReclaimMemoryDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kRetFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyReclaimMemoryDoneFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyReclaimMemoryDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyReclaimMemoryDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyReclaimMemoryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyReclaimMemoryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyReclaimMemoryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyReclaimMemoryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+};
+
+class TrustyReclaimMemoryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyReclaimMemoryFtraceEvent_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyReclaimMemoryFtraceEvent"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyReclaimMemoryFtraceEvent>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyShareMemoryDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyShareMemoryDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyShareMemoryDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyShareMemoryDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_handle() const { return at<1>().valid(); }
+ uint64_t handle() const { return at<1>().as_uint64(); }
+ bool has_len() const { return at<2>().valid(); }
+ uint64_t len() const { return at<2>().as_uint64(); }
+ bool has_lend() const { return at<3>().valid(); }
+ uint32_t lend() const { return at<3>().as_uint32(); }
+ bool has_nents() const { return at<4>().valid(); }
+ uint32_t nents() const { return at<4>().as_uint32(); }
+ bool has_ret() const { return at<5>().valid(); }
+ int32_t ret() const { return at<5>().as_int32(); }
+};
+
+class TrustyShareMemoryDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyShareMemoryDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kHandleFieldNumber = 1,
+ kLenFieldNumber = 2,
+ kLendFieldNumber = 3,
+ kNentsFieldNumber = 4,
+ kRetFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyShareMemoryDoneFtraceEvent"; }
+
+
+ using FieldMetadata_Handle =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyShareMemoryDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Handle kHandle{};
+ void set_handle(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Handle::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyShareMemoryDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lend =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyShareMemoryDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Lend kLend{};
+ void set_lend(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lend::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nents =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyShareMemoryDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Nents kNents{};
+ void set_nents(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TrustyShareMemoryDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyShareMemoryFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyShareMemoryFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyShareMemoryFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyShareMemoryFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_len() const { return at<1>().valid(); }
+ uint64_t len() const { return at<1>().as_uint64(); }
+ bool has_lend() const { return at<2>().valid(); }
+ uint32_t lend() const { return at<2>().as_uint32(); }
+ bool has_nents() const { return at<3>().valid(); }
+ uint32_t nents() const { return at<3>().as_uint32(); }
+};
+
+class TrustyShareMemoryFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyShareMemoryFtraceEvent_Decoder;
+ enum : int32_t {
+ kLenFieldNumber = 1,
+ kLendFieldNumber = 2,
+ kNentsFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyShareMemoryFtraceEvent"; }
+
+
+ using FieldMetadata_Len =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyShareMemoryFtraceEvent>;
+
+ static constexpr FieldMetadata_Len kLen{};
+ void set_len(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Len::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lend =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyShareMemoryFtraceEvent>;
+
+ static constexpr FieldMetadata_Lend kLend{};
+ void set_lend(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lend::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nents =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TrustyShareMemoryFtraceEvent>;
+
+ static constexpr FieldMetadata_Nents kNents{};
+ void set_nents(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nents::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyStdCall32DoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyStdCall32DoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyStdCall32DoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyStdCall32DoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ret() const { return at<1>().valid(); }
+ int64_t ret() const { return at<1>().as_int64(); }
+};
+
+class TrustyStdCall32DoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyStdCall32DoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kRetFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyStdCall32DoneFtraceEvent"; }
+
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrustyStdCall32DoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustyStdCall32FtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustyStdCall32FtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustyStdCall32FtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustyStdCall32FtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_r0() const { return at<1>().valid(); }
+ uint64_t r0() const { return at<1>().as_uint64(); }
+ bool has_r1() const { return at<2>().valid(); }
+ uint64_t r1() const { return at<2>().as_uint64(); }
+ bool has_r2() const { return at<3>().valid(); }
+ uint64_t r2() const { return at<3>().as_uint64(); }
+ bool has_r3() const { return at<4>().valid(); }
+ uint64_t r3() const { return at<4>().as_uint64(); }
+};
+
+class TrustyStdCall32FtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustyStdCall32FtraceEvent_Decoder;
+ enum : int32_t {
+ kR0FieldNumber = 1,
+ kR1FieldNumber = 2,
+ kR2FieldNumber = 3,
+ kR3FieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustyStdCall32FtraceEvent"; }
+
+
+ using FieldMetadata_R0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyStdCall32FtraceEvent>;
+
+ static constexpr FieldMetadata_R0 kR0{};
+ void set_r0(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_R1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyStdCall32FtraceEvent>;
+
+ static constexpr FieldMetadata_R1 kR1{};
+ void set_r1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_R2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyStdCall32FtraceEvent>;
+
+ static constexpr FieldMetadata_R2 kR2{};
+ void set_r2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_R3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustyStdCall32FtraceEvent>;
+
+ static constexpr FieldMetadata_R3 kR3{};
+ void set_r3(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustySmcDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustySmcDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustySmcDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustySmcDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ret() const { return at<1>().valid(); }
+ uint64_t ret() const { return at<1>().as_uint64(); }
+};
+
+class TrustySmcDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustySmcDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kRetFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustySmcDoneFtraceEvent"; }
+
+
+ using FieldMetadata_Ret =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustySmcDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Ret kRet{};
+ void set_ret(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ret::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TrustySmcFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrustySmcFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrustySmcFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrustySmcFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_r0() const { return at<1>().valid(); }
+ uint64_t r0() const { return at<1>().as_uint64(); }
+ bool has_r1() const { return at<2>().valid(); }
+ uint64_t r1() const { return at<2>().as_uint64(); }
+ bool has_r2() const { return at<3>().valid(); }
+ uint64_t r2() const { return at<3>().as_uint64(); }
+ bool has_r3() const { return at<4>().valid(); }
+ uint64_t r3() const { return at<4>().as_uint64(); }
+};
+
+class TrustySmcFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TrustySmcFtraceEvent_Decoder;
+ enum : int32_t {
+ kR0FieldNumber = 1,
+ kR1FieldNumber = 2,
+ kR2FieldNumber = 3,
+ kR3FieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrustySmcFtraceEvent"; }
+
+
+ using FieldMetadata_R0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustySmcFtraceEvent>;
+
+ static constexpr FieldMetadata_R0 kR0{};
+ void set_r0(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_R1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustySmcFtraceEvent>;
+
+ static constexpr FieldMetadata_R1 kR1{};
+ void set_r1(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_R2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustySmcFtraceEvent>;
+
+ static constexpr FieldMetadata_R2 kR2{};
+ void set_r2(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_R3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TrustySmcFtraceEvent>;
+
+ static constexpr FieldMetadata_R3 kR3{};
+ void set_r3(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_R3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/ufs.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_UFS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_UFS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class UfshcdClkGatingFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ UfshcdClkGatingFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit UfshcdClkGatingFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit UfshcdClkGatingFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars dev_name() const { return at<1>().as_string(); }
+ bool has_state() const { return at<2>().valid(); }
+ int32_t state() const { return at<2>().as_int32(); }
+};
+
+class UfshcdClkGatingFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = UfshcdClkGatingFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevNameFieldNumber = 1,
+ kStateFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.UfshcdClkGatingFtraceEvent"; }
+
+
+ using FieldMetadata_DevName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ UfshcdClkGatingFtraceEvent>;
+
+ static constexpr FieldMetadata_DevName kDevName{};
+ void set_dev_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DevName::kFieldId, data, size);
+ }
+ void set_dev_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DevName::kFieldId, chars.data, chars.size);
+ }
+ void set_dev_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DevName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ UfshcdClkGatingFtraceEvent>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class UfshcdCommandFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/10, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ UfshcdCommandFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit UfshcdCommandFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit UfshcdCommandFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dev_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars dev_name() const { return at<1>().as_string(); }
+ bool has_doorbell() const { return at<2>().valid(); }
+ uint32_t doorbell() const { return at<2>().as_uint32(); }
+ bool has_intr() const { return at<3>().valid(); }
+ uint32_t intr() const { return at<3>().as_uint32(); }
+ bool has_lba() const { return at<4>().valid(); }
+ uint64_t lba() const { return at<4>().as_uint64(); }
+ bool has_opcode() const { return at<5>().valid(); }
+ uint32_t opcode() const { return at<5>().as_uint32(); }
+ bool has_str() const { return at<6>().valid(); }
+ ::protozero::ConstChars str() const { return at<6>().as_string(); }
+ bool has_tag() const { return at<7>().valid(); }
+ uint32_t tag() const { return at<7>().as_uint32(); }
+ bool has_transfer_len() const { return at<8>().valid(); }
+ int32_t transfer_len() const { return at<8>().as_int32(); }
+ bool has_group_id() const { return at<9>().valid(); }
+ uint32_t group_id() const { return at<9>().as_uint32(); }
+ bool has_str_t() const { return at<10>().valid(); }
+ uint32_t str_t() const { return at<10>().as_uint32(); }
+};
+
+class UfshcdCommandFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = UfshcdCommandFtraceEvent_Decoder;
+ enum : int32_t {
+ kDevNameFieldNumber = 1,
+ kDoorbellFieldNumber = 2,
+ kIntrFieldNumber = 3,
+ kLbaFieldNumber = 4,
+ kOpcodeFieldNumber = 5,
+ kStrFieldNumber = 6,
+ kTagFieldNumber = 7,
+ kTransferLenFieldNumber = 8,
+ kGroupIdFieldNumber = 9,
+ kStrTFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.UfshcdCommandFtraceEvent"; }
+
+
+ using FieldMetadata_DevName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_DevName kDevName{};
+ void set_dev_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DevName::kFieldId, data, size);
+ }
+ void set_dev_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DevName::kFieldId, chars.data, chars.size);
+ }
+ void set_dev_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DevName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Doorbell =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_Doorbell kDoorbell{};
+ void set_doorbell(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Doorbell::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Intr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_Intr kIntr{};
+ void set_intr(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Intr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lba =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_Lba kLba{};
+ void set_lba(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Lba::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Opcode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_Opcode kOpcode{};
+ void set_opcode(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Opcode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Str =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_Str kStr{};
+ void set_str(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Str::kFieldId, data, size);
+ }
+ void set_str(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Str::kFieldId, chars.data, chars.size);
+ }
+ void set_str(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Str::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TransferLen =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_TransferLen kTransferLen{};
+ void set_transfer_len(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TransferLen::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GroupId =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_GroupId kGroupId{};
+ void set_group_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GroupId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StrT =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ UfshcdCommandFtraceEvent>;
+
+ static constexpr FieldMetadata_StrT kStrT{};
+ void set_str_t(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StrT::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/v4l2.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_V4L2_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_V4L2_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class Vb2V4l2DqbufFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/15, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Vb2V4l2DqbufFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Vb2V4l2DqbufFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Vb2V4l2DqbufFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_field() const { return at<1>().valid(); }
+ uint32_t field() const { return at<1>().as_uint32(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_minor() const { return at<3>().valid(); }
+ int32_t minor() const { return at<3>().as_int32(); }
+ bool has_sequence() const { return at<4>().valid(); }
+ uint32_t sequence() const { return at<4>().as_uint32(); }
+ bool has_timecode_flags() const { return at<5>().valid(); }
+ uint32_t timecode_flags() const { return at<5>().as_uint32(); }
+ bool has_timecode_frames() const { return at<6>().valid(); }
+ uint32_t timecode_frames() const { return at<6>().as_uint32(); }
+ bool has_timecode_hours() const { return at<7>().valid(); }
+ uint32_t timecode_hours() const { return at<7>().as_uint32(); }
+ bool has_timecode_minutes() const { return at<8>().valid(); }
+ uint32_t timecode_minutes() const { return at<8>().as_uint32(); }
+ bool has_timecode_seconds() const { return at<9>().valid(); }
+ uint32_t timecode_seconds() const { return at<9>().as_uint32(); }
+ bool has_timecode_type() const { return at<10>().valid(); }
+ uint32_t timecode_type() const { return at<10>().as_uint32(); }
+ bool has_timecode_userbits0() const { return at<11>().valid(); }
+ uint32_t timecode_userbits0() const { return at<11>().as_uint32(); }
+ bool has_timecode_userbits1() const { return at<12>().valid(); }
+ uint32_t timecode_userbits1() const { return at<12>().as_uint32(); }
+ bool has_timecode_userbits2() const { return at<13>().valid(); }
+ uint32_t timecode_userbits2() const { return at<13>().as_uint32(); }
+ bool has_timecode_userbits3() const { return at<14>().valid(); }
+ uint32_t timecode_userbits3() const { return at<14>().as_uint32(); }
+ bool has_timestamp() const { return at<15>().valid(); }
+ int64_t timestamp() const { return at<15>().as_int64(); }
+};
+
+class Vb2V4l2DqbufFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Vb2V4l2DqbufFtraceEvent_Decoder;
+ enum : int32_t {
+ kFieldFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kMinorFieldNumber = 3,
+ kSequenceFieldNumber = 4,
+ kTimecodeFlagsFieldNumber = 5,
+ kTimecodeFramesFieldNumber = 6,
+ kTimecodeHoursFieldNumber = 7,
+ kTimecodeMinutesFieldNumber = 8,
+ kTimecodeSecondsFieldNumber = 9,
+ kTimecodeTypeFieldNumber = 10,
+ kTimecodeUserbits0FieldNumber = 11,
+ kTimecodeUserbits1FieldNumber = 12,
+ kTimecodeUserbits2FieldNumber = 13,
+ kTimecodeUserbits3FieldNumber = 14,
+ kTimestampFieldNumber = 15,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Vb2V4l2DqbufFtraceEvent"; }
+
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Field kField{};
+ void set_field(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Field::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Minor =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Minor kMinor{};
+ void set_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Minor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Sequence kSequence{};
+ void set_sequence(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFlags kTimecodeFlags{};
+ void set_timecode_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFrames kTimecodeFrames{};
+ void set_timecode_frames(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeHours =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeHours kTimecodeHours{};
+ void set_timecode_hours(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeHours::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeMinutes =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeMinutes kTimecodeMinutes{};
+ void set_timecode_minutes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeMinutes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeSeconds =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeSeconds kTimecodeSeconds{};
+ void set_timecode_seconds(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeSeconds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeType =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeType kTimecodeType{};
+ void set_timecode_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits0 kTimecodeUserbits0{};
+ void set_timecode_userbits0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits1 kTimecodeUserbits1{};
+ void set_timecode_userbits1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits2 kTimecodeUserbits2{};
+ void set_timecode_userbits2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits3 kTimecodeUserbits3{};
+ void set_timecode_userbits3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Vb2V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Vb2V4l2QbufFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/15, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Vb2V4l2QbufFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Vb2V4l2QbufFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Vb2V4l2QbufFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_field() const { return at<1>().valid(); }
+ uint32_t field() const { return at<1>().as_uint32(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_minor() const { return at<3>().valid(); }
+ int32_t minor() const { return at<3>().as_int32(); }
+ bool has_sequence() const { return at<4>().valid(); }
+ uint32_t sequence() const { return at<4>().as_uint32(); }
+ bool has_timecode_flags() const { return at<5>().valid(); }
+ uint32_t timecode_flags() const { return at<5>().as_uint32(); }
+ bool has_timecode_frames() const { return at<6>().valid(); }
+ uint32_t timecode_frames() const { return at<6>().as_uint32(); }
+ bool has_timecode_hours() const { return at<7>().valid(); }
+ uint32_t timecode_hours() const { return at<7>().as_uint32(); }
+ bool has_timecode_minutes() const { return at<8>().valid(); }
+ uint32_t timecode_minutes() const { return at<8>().as_uint32(); }
+ bool has_timecode_seconds() const { return at<9>().valid(); }
+ uint32_t timecode_seconds() const { return at<9>().as_uint32(); }
+ bool has_timecode_type() const { return at<10>().valid(); }
+ uint32_t timecode_type() const { return at<10>().as_uint32(); }
+ bool has_timecode_userbits0() const { return at<11>().valid(); }
+ uint32_t timecode_userbits0() const { return at<11>().as_uint32(); }
+ bool has_timecode_userbits1() const { return at<12>().valid(); }
+ uint32_t timecode_userbits1() const { return at<12>().as_uint32(); }
+ bool has_timecode_userbits2() const { return at<13>().valid(); }
+ uint32_t timecode_userbits2() const { return at<13>().as_uint32(); }
+ bool has_timecode_userbits3() const { return at<14>().valid(); }
+ uint32_t timecode_userbits3() const { return at<14>().as_uint32(); }
+ bool has_timestamp() const { return at<15>().valid(); }
+ int64_t timestamp() const { return at<15>().as_int64(); }
+};
+
+class Vb2V4l2QbufFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Vb2V4l2QbufFtraceEvent_Decoder;
+ enum : int32_t {
+ kFieldFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kMinorFieldNumber = 3,
+ kSequenceFieldNumber = 4,
+ kTimecodeFlagsFieldNumber = 5,
+ kTimecodeFramesFieldNumber = 6,
+ kTimecodeHoursFieldNumber = 7,
+ kTimecodeMinutesFieldNumber = 8,
+ kTimecodeSecondsFieldNumber = 9,
+ kTimecodeTypeFieldNumber = 10,
+ kTimecodeUserbits0FieldNumber = 11,
+ kTimecodeUserbits1FieldNumber = 12,
+ kTimecodeUserbits2FieldNumber = 13,
+ kTimecodeUserbits3FieldNumber = 14,
+ kTimestampFieldNumber = 15,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Vb2V4l2QbufFtraceEvent"; }
+
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Field kField{};
+ void set_field(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Field::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Minor =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Minor kMinor{};
+ void set_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Minor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Sequence kSequence{};
+ void set_sequence(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFlags kTimecodeFlags{};
+ void set_timecode_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFrames kTimecodeFrames{};
+ void set_timecode_frames(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeHours =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeHours kTimecodeHours{};
+ void set_timecode_hours(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeHours::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeMinutes =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeMinutes kTimecodeMinutes{};
+ void set_timecode_minutes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeMinutes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeSeconds =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeSeconds kTimecodeSeconds{};
+ void set_timecode_seconds(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeSeconds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeType =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeType kTimecodeType{};
+ void set_timecode_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits0 kTimecodeUserbits0{};
+ void set_timecode_userbits0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits1 kTimecodeUserbits1{};
+ void set_timecode_userbits1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits2 kTimecodeUserbits2{};
+ void set_timecode_userbits2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits3 kTimecodeUserbits3{};
+ void set_timecode_userbits3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Vb2V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Vb2V4l2BufDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/15, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Vb2V4l2BufDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Vb2V4l2BufDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Vb2V4l2BufDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_field() const { return at<1>().valid(); }
+ uint32_t field() const { return at<1>().as_uint32(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_minor() const { return at<3>().valid(); }
+ int32_t minor() const { return at<3>().as_int32(); }
+ bool has_sequence() const { return at<4>().valid(); }
+ uint32_t sequence() const { return at<4>().as_uint32(); }
+ bool has_timecode_flags() const { return at<5>().valid(); }
+ uint32_t timecode_flags() const { return at<5>().as_uint32(); }
+ bool has_timecode_frames() const { return at<6>().valid(); }
+ uint32_t timecode_frames() const { return at<6>().as_uint32(); }
+ bool has_timecode_hours() const { return at<7>().valid(); }
+ uint32_t timecode_hours() const { return at<7>().as_uint32(); }
+ bool has_timecode_minutes() const { return at<8>().valid(); }
+ uint32_t timecode_minutes() const { return at<8>().as_uint32(); }
+ bool has_timecode_seconds() const { return at<9>().valid(); }
+ uint32_t timecode_seconds() const { return at<9>().as_uint32(); }
+ bool has_timecode_type() const { return at<10>().valid(); }
+ uint32_t timecode_type() const { return at<10>().as_uint32(); }
+ bool has_timecode_userbits0() const { return at<11>().valid(); }
+ uint32_t timecode_userbits0() const { return at<11>().as_uint32(); }
+ bool has_timecode_userbits1() const { return at<12>().valid(); }
+ uint32_t timecode_userbits1() const { return at<12>().as_uint32(); }
+ bool has_timecode_userbits2() const { return at<13>().valid(); }
+ uint32_t timecode_userbits2() const { return at<13>().as_uint32(); }
+ bool has_timecode_userbits3() const { return at<14>().valid(); }
+ uint32_t timecode_userbits3() const { return at<14>().as_uint32(); }
+ bool has_timestamp() const { return at<15>().valid(); }
+ int64_t timestamp() const { return at<15>().as_int64(); }
+};
+
+class Vb2V4l2BufDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Vb2V4l2BufDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kFieldFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kMinorFieldNumber = 3,
+ kSequenceFieldNumber = 4,
+ kTimecodeFlagsFieldNumber = 5,
+ kTimecodeFramesFieldNumber = 6,
+ kTimecodeHoursFieldNumber = 7,
+ kTimecodeMinutesFieldNumber = 8,
+ kTimecodeSecondsFieldNumber = 9,
+ kTimecodeTypeFieldNumber = 10,
+ kTimecodeUserbits0FieldNumber = 11,
+ kTimecodeUserbits1FieldNumber = 12,
+ kTimecodeUserbits2FieldNumber = 13,
+ kTimecodeUserbits3FieldNumber = 14,
+ kTimestampFieldNumber = 15,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Vb2V4l2BufDoneFtraceEvent"; }
+
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Field kField{};
+ void set_field(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Field::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Minor =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Minor kMinor{};
+ void set_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Minor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Sequence kSequence{};
+ void set_sequence(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFlags kTimecodeFlags{};
+ void set_timecode_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFrames kTimecodeFrames{};
+ void set_timecode_frames(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeHours =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeHours kTimecodeHours{};
+ void set_timecode_hours(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeHours::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeMinutes =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeMinutes kTimecodeMinutes{};
+ void set_timecode_minutes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeMinutes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeSeconds =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeSeconds kTimecodeSeconds{};
+ void set_timecode_seconds(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeSeconds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeType =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeType kTimecodeType{};
+ void set_timecode_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits0 kTimecodeUserbits0{};
+ void set_timecode_userbits0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits1 kTimecodeUserbits1{};
+ void set_timecode_userbits1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits2 kTimecodeUserbits2{};
+ void set_timecode_userbits2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits3 kTimecodeUserbits3{};
+ void set_timecode_userbits3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Vb2V4l2BufDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Vb2V4l2BufQueueFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/15, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Vb2V4l2BufQueueFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Vb2V4l2BufQueueFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Vb2V4l2BufQueueFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_field() const { return at<1>().valid(); }
+ uint32_t field() const { return at<1>().as_uint32(); }
+ bool has_flags() const { return at<2>().valid(); }
+ uint32_t flags() const { return at<2>().as_uint32(); }
+ bool has_minor() const { return at<3>().valid(); }
+ int32_t minor() const { return at<3>().as_int32(); }
+ bool has_sequence() const { return at<4>().valid(); }
+ uint32_t sequence() const { return at<4>().as_uint32(); }
+ bool has_timecode_flags() const { return at<5>().valid(); }
+ uint32_t timecode_flags() const { return at<5>().as_uint32(); }
+ bool has_timecode_frames() const { return at<6>().valid(); }
+ uint32_t timecode_frames() const { return at<6>().as_uint32(); }
+ bool has_timecode_hours() const { return at<7>().valid(); }
+ uint32_t timecode_hours() const { return at<7>().as_uint32(); }
+ bool has_timecode_minutes() const { return at<8>().valid(); }
+ uint32_t timecode_minutes() const { return at<8>().as_uint32(); }
+ bool has_timecode_seconds() const { return at<9>().valid(); }
+ uint32_t timecode_seconds() const { return at<9>().as_uint32(); }
+ bool has_timecode_type() const { return at<10>().valid(); }
+ uint32_t timecode_type() const { return at<10>().as_uint32(); }
+ bool has_timecode_userbits0() const { return at<11>().valid(); }
+ uint32_t timecode_userbits0() const { return at<11>().as_uint32(); }
+ bool has_timecode_userbits1() const { return at<12>().valid(); }
+ uint32_t timecode_userbits1() const { return at<12>().as_uint32(); }
+ bool has_timecode_userbits2() const { return at<13>().valid(); }
+ uint32_t timecode_userbits2() const { return at<13>().as_uint32(); }
+ bool has_timecode_userbits3() const { return at<14>().valid(); }
+ uint32_t timecode_userbits3() const { return at<14>().as_uint32(); }
+ bool has_timestamp() const { return at<15>().valid(); }
+ int64_t timestamp() const { return at<15>().as_int64(); }
+};
+
+class Vb2V4l2BufQueueFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = Vb2V4l2BufQueueFtraceEvent_Decoder;
+ enum : int32_t {
+ kFieldFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ kMinorFieldNumber = 3,
+ kSequenceFieldNumber = 4,
+ kTimecodeFlagsFieldNumber = 5,
+ kTimecodeFramesFieldNumber = 6,
+ kTimecodeHoursFieldNumber = 7,
+ kTimecodeMinutesFieldNumber = 8,
+ kTimecodeSecondsFieldNumber = 9,
+ kTimecodeTypeFieldNumber = 10,
+ kTimecodeUserbits0FieldNumber = 11,
+ kTimecodeUserbits1FieldNumber = 12,
+ kTimecodeUserbits2FieldNumber = 13,
+ kTimecodeUserbits3FieldNumber = 14,
+ kTimestampFieldNumber = 15,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Vb2V4l2BufQueueFtraceEvent"; }
+
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Field kField{};
+ void set_field(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Field::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Minor =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Minor kMinor{};
+ void set_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Minor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Sequence kSequence{};
+ void set_sequence(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFlags kTimecodeFlags{};
+ void set_timecode_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFrames kTimecodeFrames{};
+ void set_timecode_frames(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeHours =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeHours kTimecodeHours{};
+ void set_timecode_hours(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeHours::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeMinutes =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeMinutes kTimecodeMinutes{};
+ void set_timecode_minutes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeMinutes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeSeconds =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeSeconds kTimecodeSeconds{};
+ void set_timecode_seconds(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeSeconds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeType =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeType kTimecodeType{};
+ void set_timecode_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits0 kTimecodeUserbits0{};
+ void set_timecode_userbits0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits1 kTimecodeUserbits1{};
+ void set_timecode_userbits1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits2 kTimecodeUserbits2{};
+ void set_timecode_userbits2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits3 kTimecodeUserbits3{};
+ void set_timecode_userbits3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ Vb2V4l2BufQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V4l2DqbufFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/18, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V4l2DqbufFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V4l2DqbufFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V4l2DqbufFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytesused() const { return at<1>().valid(); }
+ uint32_t bytesused() const { return at<1>().as_uint32(); }
+ bool has_field() const { return at<2>().valid(); }
+ uint32_t field() const { return at<2>().as_uint32(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_index() const { return at<4>().valid(); }
+ uint32_t index() const { return at<4>().as_uint32(); }
+ bool has_minor() const { return at<5>().valid(); }
+ int32_t minor() const { return at<5>().as_int32(); }
+ bool has_sequence() const { return at<6>().valid(); }
+ uint32_t sequence() const { return at<6>().as_uint32(); }
+ bool has_timecode_flags() const { return at<7>().valid(); }
+ uint32_t timecode_flags() const { return at<7>().as_uint32(); }
+ bool has_timecode_frames() const { return at<8>().valid(); }
+ uint32_t timecode_frames() const { return at<8>().as_uint32(); }
+ bool has_timecode_hours() const { return at<9>().valid(); }
+ uint32_t timecode_hours() const { return at<9>().as_uint32(); }
+ bool has_timecode_minutes() const { return at<10>().valid(); }
+ uint32_t timecode_minutes() const { return at<10>().as_uint32(); }
+ bool has_timecode_seconds() const { return at<11>().valid(); }
+ uint32_t timecode_seconds() const { return at<11>().as_uint32(); }
+ bool has_timecode_type() const { return at<12>().valid(); }
+ uint32_t timecode_type() const { return at<12>().as_uint32(); }
+ bool has_timecode_userbits0() const { return at<13>().valid(); }
+ uint32_t timecode_userbits0() const { return at<13>().as_uint32(); }
+ bool has_timecode_userbits1() const { return at<14>().valid(); }
+ uint32_t timecode_userbits1() const { return at<14>().as_uint32(); }
+ bool has_timecode_userbits2() const { return at<15>().valid(); }
+ uint32_t timecode_userbits2() const { return at<15>().as_uint32(); }
+ bool has_timecode_userbits3() const { return at<16>().valid(); }
+ uint32_t timecode_userbits3() const { return at<16>().as_uint32(); }
+ bool has_timestamp() const { return at<17>().valid(); }
+ int64_t timestamp() const { return at<17>().as_int64(); }
+ bool has_type() const { return at<18>().valid(); }
+ uint32_t type() const { return at<18>().as_uint32(); }
+};
+
+class V4l2DqbufFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = V4l2DqbufFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesusedFieldNumber = 1,
+ kFieldFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kIndexFieldNumber = 4,
+ kMinorFieldNumber = 5,
+ kSequenceFieldNumber = 6,
+ kTimecodeFlagsFieldNumber = 7,
+ kTimecodeFramesFieldNumber = 8,
+ kTimecodeHoursFieldNumber = 9,
+ kTimecodeMinutesFieldNumber = 10,
+ kTimecodeSecondsFieldNumber = 11,
+ kTimecodeTypeFieldNumber = 12,
+ kTimecodeUserbits0FieldNumber = 13,
+ kTimecodeUserbits1FieldNumber = 14,
+ kTimecodeUserbits2FieldNumber = 15,
+ kTimecodeUserbits3FieldNumber = 16,
+ kTimestampFieldNumber = 17,
+ kTypeFieldNumber = 18,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V4l2DqbufFtraceEvent"; }
+
+
+ using FieldMetadata_Bytesused =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytesused kBytesused{};
+ void set_bytesused(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytesused::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Field kField{};
+ void set_field(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Field::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Minor =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Minor kMinor{};
+ void set_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Minor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Sequence kSequence{};
+ void set_sequence(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFlags kTimecodeFlags{};
+ void set_timecode_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFrames kTimecodeFrames{};
+ void set_timecode_frames(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeHours =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeHours kTimecodeHours{};
+ void set_timecode_hours(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeHours::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeMinutes =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeMinutes kTimecodeMinutes{};
+ void set_timecode_minutes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeMinutes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeSeconds =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeSeconds kTimecodeSeconds{};
+ void set_timecode_seconds(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeSeconds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeType =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeType kTimecodeType{};
+ void set_timecode_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits0 kTimecodeUserbits0{};
+ void set_timecode_userbits0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits1 kTimecodeUserbits1{};
+ void set_timecode_userbits1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits2 kTimecodeUserbits2{};
+ void set_timecode_userbits2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits3 kTimecodeUserbits3{};
+ void set_timecode_userbits3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2DqbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class V4l2QbufFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/18, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ V4l2QbufFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit V4l2QbufFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit V4l2QbufFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_bytesused() const { return at<1>().valid(); }
+ uint32_t bytesused() const { return at<1>().as_uint32(); }
+ bool has_field() const { return at<2>().valid(); }
+ uint32_t field() const { return at<2>().as_uint32(); }
+ bool has_flags() const { return at<3>().valid(); }
+ uint32_t flags() const { return at<3>().as_uint32(); }
+ bool has_index() const { return at<4>().valid(); }
+ uint32_t index() const { return at<4>().as_uint32(); }
+ bool has_minor() const { return at<5>().valid(); }
+ int32_t minor() const { return at<5>().as_int32(); }
+ bool has_sequence() const { return at<6>().valid(); }
+ uint32_t sequence() const { return at<6>().as_uint32(); }
+ bool has_timecode_flags() const { return at<7>().valid(); }
+ uint32_t timecode_flags() const { return at<7>().as_uint32(); }
+ bool has_timecode_frames() const { return at<8>().valid(); }
+ uint32_t timecode_frames() const { return at<8>().as_uint32(); }
+ bool has_timecode_hours() const { return at<9>().valid(); }
+ uint32_t timecode_hours() const { return at<9>().as_uint32(); }
+ bool has_timecode_minutes() const { return at<10>().valid(); }
+ uint32_t timecode_minutes() const { return at<10>().as_uint32(); }
+ bool has_timecode_seconds() const { return at<11>().valid(); }
+ uint32_t timecode_seconds() const { return at<11>().as_uint32(); }
+ bool has_timecode_type() const { return at<12>().valid(); }
+ uint32_t timecode_type() const { return at<12>().as_uint32(); }
+ bool has_timecode_userbits0() const { return at<13>().valid(); }
+ uint32_t timecode_userbits0() const { return at<13>().as_uint32(); }
+ bool has_timecode_userbits1() const { return at<14>().valid(); }
+ uint32_t timecode_userbits1() const { return at<14>().as_uint32(); }
+ bool has_timecode_userbits2() const { return at<15>().valid(); }
+ uint32_t timecode_userbits2() const { return at<15>().as_uint32(); }
+ bool has_timecode_userbits3() const { return at<16>().valid(); }
+ uint32_t timecode_userbits3() const { return at<16>().as_uint32(); }
+ bool has_timestamp() const { return at<17>().valid(); }
+ int64_t timestamp() const { return at<17>().as_int64(); }
+ bool has_type() const { return at<18>().valid(); }
+ uint32_t type() const { return at<18>().as_uint32(); }
+};
+
+class V4l2QbufFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = V4l2QbufFtraceEvent_Decoder;
+ enum : int32_t {
+ kBytesusedFieldNumber = 1,
+ kFieldFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ kIndexFieldNumber = 4,
+ kMinorFieldNumber = 5,
+ kSequenceFieldNumber = 6,
+ kTimecodeFlagsFieldNumber = 7,
+ kTimecodeFramesFieldNumber = 8,
+ kTimecodeHoursFieldNumber = 9,
+ kTimecodeMinutesFieldNumber = 10,
+ kTimecodeSecondsFieldNumber = 11,
+ kTimecodeTypeFieldNumber = 12,
+ kTimecodeUserbits0FieldNumber = 13,
+ kTimecodeUserbits1FieldNumber = 14,
+ kTimecodeUserbits2FieldNumber = 15,
+ kTimecodeUserbits3FieldNumber = 16,
+ kTimestampFieldNumber = 17,
+ kTypeFieldNumber = 18,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.V4l2QbufFtraceEvent"; }
+
+
+ using FieldMetadata_Bytesused =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Bytesused kBytesused{};
+ void set_bytesused(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Bytesused::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Field =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Field kField{};
+ void set_field(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Field::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Minor =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Minor kMinor{};
+ void set_minor(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Minor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Sequence kSequence{};
+ void set_sequence(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFlags kTimecodeFlags{};
+ void set_timecode_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeFrames kTimecodeFrames{};
+ void set_timecode_frames(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeHours =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeHours kTimecodeHours{};
+ void set_timecode_hours(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeHours::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeMinutes =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeMinutes kTimecodeMinutes{};
+ void set_timecode_minutes(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeMinutes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeSeconds =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeSeconds kTimecodeSeconds{};
+ void set_timecode_seconds(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeSeconds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeType =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeType kTimecodeType{};
+ void set_timecode_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits0 kTimecodeUserbits0{};
+ void set_timecode_userbits0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits1 kTimecodeUserbits1{};
+ void set_timecode_userbits1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits2 kTimecodeUserbits2{};
+ void set_timecode_userbits2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimecodeUserbits3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_TimecodeUserbits3 kTimecodeUserbits3{};
+ void set_timecode_userbits3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimecodeUserbits3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ V4l2QbufFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/virtio_gpu.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_VIRTIO_GPU_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_VIRTIO_GPU_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class VirtioGpuCmdResponseFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VirtioGpuCmdResponseFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VirtioGpuCmdResponseFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VirtioGpuCmdResponseFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctx_id() const { return at<1>().valid(); }
+ uint32_t ctx_id() const { return at<1>().as_uint32(); }
+ bool has_dev() const { return at<2>().valid(); }
+ int32_t dev() const { return at<2>().as_int32(); }
+ bool has_fence_id() const { return at<3>().valid(); }
+ uint64_t fence_id() const { return at<3>().as_uint64(); }
+ bool has_flags() const { return at<4>().valid(); }
+ uint32_t flags() const { return at<4>().as_uint32(); }
+ bool has_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars name() const { return at<5>().as_string(); }
+ bool has_num_free() const { return at<6>().valid(); }
+ uint32_t num_free() const { return at<6>().as_uint32(); }
+ bool has_seqno() const { return at<7>().valid(); }
+ uint32_t seqno() const { return at<7>().as_uint32(); }
+ bool has_type() const { return at<8>().valid(); }
+ uint32_t type() const { return at<8>().as_uint32(); }
+ bool has_vq() const { return at<9>().valid(); }
+ uint32_t vq() const { return at<9>().as_uint32(); }
+};
+
+class VirtioGpuCmdResponseFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = VirtioGpuCmdResponseFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtxIdFieldNumber = 1,
+ kDevFieldNumber = 2,
+ kFenceIdFieldNumber = 3,
+ kFlagsFieldNumber = 4,
+ kNameFieldNumber = 5,
+ kNumFreeFieldNumber = 6,
+ kSeqnoFieldNumber = 7,
+ kTypeFieldNumber = 8,
+ kVqFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VirtioGpuCmdResponseFtraceEvent"; }
+
+
+ using FieldMetadata_CtxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_CtxId kCtxId{};
+ void set_ctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FenceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_FenceId kFenceId{};
+ void set_fence_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FenceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_NumFree kNumFree{};
+ void set_num_free(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumFree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Vq =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdResponseFtraceEvent>;
+
+ static constexpr FieldMetadata_Vq kVq{};
+ void set_vq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Vq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class VirtioGpuCmdQueueFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VirtioGpuCmdQueueFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VirtioGpuCmdQueueFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VirtioGpuCmdQueueFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_ctx_id() const { return at<1>().valid(); }
+ uint32_t ctx_id() const { return at<1>().as_uint32(); }
+ bool has_dev() const { return at<2>().valid(); }
+ int32_t dev() const { return at<2>().as_int32(); }
+ bool has_fence_id() const { return at<3>().valid(); }
+ uint64_t fence_id() const { return at<3>().as_uint64(); }
+ bool has_flags() const { return at<4>().valid(); }
+ uint32_t flags() const { return at<4>().as_uint32(); }
+ bool has_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars name() const { return at<5>().as_string(); }
+ bool has_num_free() const { return at<6>().valid(); }
+ uint32_t num_free() const { return at<6>().as_uint32(); }
+ bool has_seqno() const { return at<7>().valid(); }
+ uint32_t seqno() const { return at<7>().as_uint32(); }
+ bool has_type() const { return at<8>().valid(); }
+ uint32_t type() const { return at<8>().as_uint32(); }
+ bool has_vq() const { return at<9>().valid(); }
+ uint32_t vq() const { return at<9>().as_uint32(); }
+};
+
+class VirtioGpuCmdQueueFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = VirtioGpuCmdQueueFtraceEvent_Decoder;
+ enum : int32_t {
+ kCtxIdFieldNumber = 1,
+ kDevFieldNumber = 2,
+ kFenceIdFieldNumber = 3,
+ kFlagsFieldNumber = 4,
+ kNameFieldNumber = 5,
+ kNumFreeFieldNumber = 6,
+ kSeqnoFieldNumber = 7,
+ kTypeFieldNumber = 8,
+ kVqFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VirtioGpuCmdQueueFtraceEvent"; }
+
+
+ using FieldMetadata_CtxId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_CtxId kCtxId{};
+ void set_ctx_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CtxId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Dev =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Dev kDev{};
+ void set_dev(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dev::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FenceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_FenceId kFenceId{};
+ void set_fence_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FenceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Flags =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Flags kFlags{};
+ void set_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Flags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumFree =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_NumFree kNumFree{};
+ void set_num_free(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumFree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Seqno =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Seqno kSeqno{};
+ void set_seqno(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Seqno::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Vq =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioGpuCmdQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Vq kVq{};
+ void set_vq(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Vq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/virtio_video.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_VIRTIO_VIDEO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_VIRTIO_VIDEO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class VirtioVideoResourceQueueDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VirtioVideoResourceQueueDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VirtioVideoResourceQueueDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VirtioVideoResourceQueueDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_data_size0() const { return at<1>().valid(); }
+ uint32_t data_size0() const { return at<1>().as_uint32(); }
+ bool has_data_size1() const { return at<2>().valid(); }
+ uint32_t data_size1() const { return at<2>().as_uint32(); }
+ bool has_data_size2() const { return at<3>().valid(); }
+ uint32_t data_size2() const { return at<3>().as_uint32(); }
+ bool has_data_size3() const { return at<4>().valid(); }
+ uint32_t data_size3() const { return at<4>().as_uint32(); }
+ bool has_queue_type() const { return at<5>().valid(); }
+ uint32_t queue_type() const { return at<5>().as_uint32(); }
+ bool has_resource_id() const { return at<6>().valid(); }
+ int32_t resource_id() const { return at<6>().as_int32(); }
+ bool has_stream_id() const { return at<7>().valid(); }
+ int32_t stream_id() const { return at<7>().as_int32(); }
+ bool has_timestamp() const { return at<8>().valid(); }
+ uint64_t timestamp() const { return at<8>().as_uint64(); }
+};
+
+class VirtioVideoResourceQueueDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = VirtioVideoResourceQueueDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kDataSize0FieldNumber = 1,
+ kDataSize1FieldNumber = 2,
+ kDataSize2FieldNumber = 3,
+ kDataSize3FieldNumber = 4,
+ kQueueTypeFieldNumber = 5,
+ kResourceIdFieldNumber = 6,
+ kStreamIdFieldNumber = 7,
+ kTimestampFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VirtioVideoResourceQueueDoneFtraceEvent"; }
+
+
+ using FieldMetadata_DataSize0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize0 kDataSize0{};
+ void set_data_size0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSize1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize1 kDataSize1{};
+ void set_data_size1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSize2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize2 kDataSize2{};
+ void set_data_size2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSize3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize3 kDataSize3{};
+ void set_data_size3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_QueueType =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_QueueType kQueueType{};
+ void set_queue_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_QueueType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResourceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_ResourceId kResourceId{};
+ void set_resource_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResourceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StreamId =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_StreamId kStreamId{};
+ void set_stream_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StreamId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VirtioVideoResourceQueueDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class VirtioVideoResourceQueueFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VirtioVideoResourceQueueFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VirtioVideoResourceQueueFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VirtioVideoResourceQueueFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_data_size0() const { return at<1>().valid(); }
+ uint32_t data_size0() const { return at<1>().as_uint32(); }
+ bool has_data_size1() const { return at<2>().valid(); }
+ uint32_t data_size1() const { return at<2>().as_uint32(); }
+ bool has_data_size2() const { return at<3>().valid(); }
+ uint32_t data_size2() const { return at<3>().as_uint32(); }
+ bool has_data_size3() const { return at<4>().valid(); }
+ uint32_t data_size3() const { return at<4>().as_uint32(); }
+ bool has_queue_type() const { return at<5>().valid(); }
+ uint32_t queue_type() const { return at<5>().as_uint32(); }
+ bool has_resource_id() const { return at<6>().valid(); }
+ int32_t resource_id() const { return at<6>().as_int32(); }
+ bool has_stream_id() const { return at<7>().valid(); }
+ int32_t stream_id() const { return at<7>().as_int32(); }
+ bool has_timestamp() const { return at<8>().valid(); }
+ uint64_t timestamp() const { return at<8>().as_uint64(); }
+};
+
+class VirtioVideoResourceQueueFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = VirtioVideoResourceQueueFtraceEvent_Decoder;
+ enum : int32_t {
+ kDataSize0FieldNumber = 1,
+ kDataSize1FieldNumber = 2,
+ kDataSize2FieldNumber = 3,
+ kDataSize3FieldNumber = 4,
+ kQueueTypeFieldNumber = 5,
+ kResourceIdFieldNumber = 6,
+ kStreamIdFieldNumber = 7,
+ kTimestampFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VirtioVideoResourceQueueFtraceEvent"; }
+
+
+ using FieldMetadata_DataSize0 =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize0 kDataSize0{};
+ void set_data_size0(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize0::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSize1 =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize1 kDataSize1{};
+ void set_data_size1(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize1::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSize2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize2 kDataSize2{};
+ void set_data_size2(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataSize3 =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_DataSize3 kDataSize3{};
+ void set_data_size3(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataSize3::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_QueueType =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_QueueType kQueueType{};
+ void set_queue_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_QueueType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResourceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_ResourceId kResourceId{};
+ void set_resource_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResourceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StreamId =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_StreamId kStreamId{};
+ void set_stream_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StreamId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VirtioVideoResourceQueueFtraceEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class VirtioVideoCmdDoneFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VirtioVideoCmdDoneFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VirtioVideoCmdDoneFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VirtioVideoCmdDoneFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_stream_id() const { return at<1>().valid(); }
+ uint32_t stream_id() const { return at<1>().as_uint32(); }
+ bool has_type() const { return at<2>().valid(); }
+ uint32_t type() const { return at<2>().as_uint32(); }
+};
+
+class VirtioVideoCmdDoneFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = VirtioVideoCmdDoneFtraceEvent_Decoder;
+ enum : int32_t {
+ kStreamIdFieldNumber = 1,
+ kTypeFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VirtioVideoCmdDoneFtraceEvent"; }
+
+
+ using FieldMetadata_StreamId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoCmdDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_StreamId kStreamId{};
+ void set_stream_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StreamId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoCmdDoneFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class VirtioVideoCmdFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VirtioVideoCmdFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VirtioVideoCmdFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VirtioVideoCmdFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_stream_id() const { return at<1>().valid(); }
+ uint32_t stream_id() const { return at<1>().as_uint32(); }
+ bool has_type() const { return at<2>().valid(); }
+ uint32_t type() const { return at<2>().as_uint32(); }
+};
+
+class VirtioVideoCmdFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = VirtioVideoCmdFtraceEvent_Decoder;
+ enum : int32_t {
+ kStreamIdFieldNumber = 1,
+ kTypeFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VirtioVideoCmdFtraceEvent"; }
+
+
+ using FieldMetadata_StreamId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoCmdFtraceEvent>;
+
+ static constexpr FieldMetadata_StreamId kStreamId{};
+ void set_stream_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StreamId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VirtioVideoCmdFtraceEvent>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/vmscan.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_VMSCAN_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_VMSCAN_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class MmShrinkSlabEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmShrinkSlabEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmShrinkSlabEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmShrinkSlabEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_new_scan() const { return at<1>().valid(); }
+ int64_t new_scan() const { return at<1>().as_int64(); }
+ bool has_retval() const { return at<2>().valid(); }
+ int32_t retval() const { return at<2>().as_int32(); }
+ bool has_shr() const { return at<3>().valid(); }
+ uint64_t shr() const { return at<3>().as_uint64(); }
+ bool has_shrink() const { return at<4>().valid(); }
+ uint64_t shrink() const { return at<4>().as_uint64(); }
+ bool has_total_scan() const { return at<5>().valid(); }
+ int64_t total_scan() const { return at<5>().as_int64(); }
+ bool has_unused_scan() const { return at<6>().valid(); }
+ int64_t unused_scan() const { return at<6>().as_int64(); }
+ bool has_nid() const { return at<7>().valid(); }
+ int32_t nid() const { return at<7>().as_int32(); }
+};
+
+class MmShrinkSlabEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmShrinkSlabEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kNewScanFieldNumber = 1,
+ kRetvalFieldNumber = 2,
+ kShrFieldNumber = 3,
+ kShrinkFieldNumber = 4,
+ kTotalScanFieldNumber = 5,
+ kUnusedScanFieldNumber = 6,
+ kNidFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmShrinkSlabEndFtraceEvent"; }
+
+
+ using FieldMetadata_NewScan =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ MmShrinkSlabEndFtraceEvent>;
+
+ static constexpr FieldMetadata_NewScan kNewScan{};
+ void set_new_scan(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NewScan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Retval =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmShrinkSlabEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Retval kRetval{};
+ void set_retval(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Retval::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Shr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Shr kShr{};
+ void set_shr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Shr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Shrink =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Shrink kShrink{};
+ void set_shrink(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Shrink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalScan =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ MmShrinkSlabEndFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalScan kTotalScan{};
+ void set_total_scan(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalScan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnusedScan =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ MmShrinkSlabEndFtraceEvent>;
+
+ static constexpr FieldMetadata_UnusedScan kUnusedScan{};
+ void set_unused_scan(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnusedScan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmShrinkSlabEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmShrinkSlabStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmShrinkSlabStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmShrinkSlabStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmShrinkSlabStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cache_items() const { return at<1>().valid(); }
+ uint64_t cache_items() const { return at<1>().as_uint64(); }
+ bool has_delta() const { return at<2>().valid(); }
+ uint64_t delta() const { return at<2>().as_uint64(); }
+ bool has_gfp_flags() const { return at<3>().valid(); }
+ uint32_t gfp_flags() const { return at<3>().as_uint32(); }
+ bool has_lru_pgs() const { return at<4>().valid(); }
+ uint64_t lru_pgs() const { return at<4>().as_uint64(); }
+ bool has_nr_objects_to_shrink() const { return at<5>().valid(); }
+ int64_t nr_objects_to_shrink() const { return at<5>().as_int64(); }
+ bool has_pgs_scanned() const { return at<6>().valid(); }
+ uint64_t pgs_scanned() const { return at<6>().as_uint64(); }
+ bool has_shr() const { return at<7>().valid(); }
+ uint64_t shr() const { return at<7>().as_uint64(); }
+ bool has_shrink() const { return at<8>().valid(); }
+ uint64_t shrink() const { return at<8>().as_uint64(); }
+ bool has_total_scan() const { return at<9>().valid(); }
+ uint64_t total_scan() const { return at<9>().as_uint64(); }
+ bool has_nid() const { return at<10>().valid(); }
+ int32_t nid() const { return at<10>().as_int32(); }
+ bool has_priority() const { return at<11>().valid(); }
+ int32_t priority() const { return at<11>().as_int32(); }
+};
+
+class MmShrinkSlabStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmShrinkSlabStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kCacheItemsFieldNumber = 1,
+ kDeltaFieldNumber = 2,
+ kGfpFlagsFieldNumber = 3,
+ kLruPgsFieldNumber = 4,
+ kNrObjectsToShrinkFieldNumber = 5,
+ kPgsScannedFieldNumber = 6,
+ kShrFieldNumber = 7,
+ kShrinkFieldNumber = 8,
+ kTotalScanFieldNumber = 9,
+ kNidFieldNumber = 10,
+ kPriorityFieldNumber = 11,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmShrinkSlabStartFtraceEvent"; }
+
+
+ using FieldMetadata_CacheItems =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_CacheItems kCacheItems{};
+ void set_cache_items(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CacheItems::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Delta =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Delta kDelta{};
+ void set_delta(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Delta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LruPgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_LruPgs kLruPgs{};
+ void set_lru_pgs(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LruPgs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NrObjectsToShrink =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_NrObjectsToShrink kNrObjectsToShrink{};
+ void set_nr_objects_to_shrink(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrObjectsToShrink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PgsScanned =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_PgsScanned kPgsScanned{};
+ void set_pgs_scanned(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PgsScanned::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Shr =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Shr kShr{};
+ void set_shr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Shr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Shrink =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Shrink kShrink{};
+ void set_shrink(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Shrink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalScan =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_TotalScan kTotalScan{};
+ void set_total_scan(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalScan::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Priority =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmShrinkSlabStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Priority kPriority{};
+ void set_priority(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Priority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmVmscanKswapdSleepFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmVmscanKswapdSleepFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmVmscanKswapdSleepFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmVmscanKswapdSleepFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+};
+
+class MmVmscanKswapdSleepFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmVmscanKswapdSleepFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmVmscanKswapdSleepFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmVmscanKswapdSleepFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmVmscanKswapdWakeFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmVmscanKswapdWakeFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmVmscanKswapdWakeFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmVmscanKswapdWakeFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nid() const { return at<1>().valid(); }
+ int32_t nid() const { return at<1>().as_int32(); }
+ bool has_order() const { return at<2>().valid(); }
+ int32_t order() const { return at<2>().as_int32(); }
+ bool has_zid() const { return at<3>().valid(); }
+ int32_t zid() const { return at<3>().as_int32(); }
+};
+
+class MmVmscanKswapdWakeFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmVmscanKswapdWakeFtraceEvent_Decoder;
+ enum : int32_t {
+ kNidFieldNumber = 1,
+ kOrderFieldNumber = 2,
+ kZidFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmVmscanKswapdWakeFtraceEvent"; }
+
+
+ using FieldMetadata_Nid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmVmscanKswapdWakeFtraceEvent>;
+
+ static constexpr FieldMetadata_Nid kNid{};
+ void set_nid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmVmscanKswapdWakeFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Zid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmVmscanKswapdWakeFtraceEvent>;
+
+ static constexpr FieldMetadata_Zid kZid{};
+ void set_zid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Zid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmVmscanDirectReclaimEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmVmscanDirectReclaimEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmVmscanDirectReclaimEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmVmscanDirectReclaimEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_nr_reclaimed() const { return at<1>().valid(); }
+ uint64_t nr_reclaimed() const { return at<1>().as_uint64(); }
+};
+
+class MmVmscanDirectReclaimEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmVmscanDirectReclaimEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kNrReclaimedFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmVmscanDirectReclaimEndFtraceEvent"; }
+
+
+ using FieldMetadata_NrReclaimed =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MmVmscanDirectReclaimEndFtraceEvent>;
+
+ static constexpr FieldMetadata_NrReclaimed kNrReclaimed{};
+ void set_nr_reclaimed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NrReclaimed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MmVmscanDirectReclaimBeginFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MmVmscanDirectReclaimBeginFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MmVmscanDirectReclaimBeginFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MmVmscanDirectReclaimBeginFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_order() const { return at<1>().valid(); }
+ int32_t order() const { return at<1>().as_int32(); }
+ bool has_may_writepage() const { return at<2>().valid(); }
+ int32_t may_writepage() const { return at<2>().as_int32(); }
+ bool has_gfp_flags() const { return at<3>().valid(); }
+ uint32_t gfp_flags() const { return at<3>().as_uint32(); }
+};
+
+class MmVmscanDirectReclaimBeginFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = MmVmscanDirectReclaimBeginFtraceEvent_Decoder;
+ enum : int32_t {
+ kOrderFieldNumber = 1,
+ kMayWritepageFieldNumber = 2,
+ kGfpFlagsFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MmVmscanDirectReclaimBeginFtraceEvent"; }
+
+
+ using FieldMetadata_Order =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmVmscanDirectReclaimBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_Order kOrder{};
+ void set_order(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Order::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MayWritepage =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MmVmscanDirectReclaimBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_MayWritepage kMayWritepage{};
+ void set_may_writepage(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MayWritepage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GfpFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MmVmscanDirectReclaimBeginFtraceEvent>;
+
+ static constexpr FieldMetadata_GfpFlags kGfpFlags{};
+ void set_gfp_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GfpFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ftrace/workqueue.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_WORKQUEUE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_FTRACE_WORKQUEUE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class WorkqueueQueueWorkFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ WorkqueueQueueWorkFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit WorkqueueQueueWorkFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit WorkqueueQueueWorkFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_work() const { return at<1>().valid(); }
+ uint64_t work() const { return at<1>().as_uint64(); }
+ bool has_function() const { return at<2>().valid(); }
+ uint64_t function() const { return at<2>().as_uint64(); }
+ bool has_workqueue() const { return at<3>().valid(); }
+ uint64_t workqueue() const { return at<3>().as_uint64(); }
+ bool has_req_cpu() const { return at<4>().valid(); }
+ uint32_t req_cpu() const { return at<4>().as_uint32(); }
+ bool has_cpu() const { return at<5>().valid(); }
+ uint32_t cpu() const { return at<5>().as_uint32(); }
+};
+
+class WorkqueueQueueWorkFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = WorkqueueQueueWorkFtraceEvent_Decoder;
+ enum : int32_t {
+ kWorkFieldNumber = 1,
+ kFunctionFieldNumber = 2,
+ kWorkqueueFieldNumber = 3,
+ kReqCpuFieldNumber = 4,
+ kCpuFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.WorkqueueQueueWorkFtraceEvent"; }
+
+
+ using FieldMetadata_Work =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueQueueWorkFtraceEvent>;
+
+ static constexpr FieldMetadata_Work kWork{};
+ void set_work(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Work::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Function =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueQueueWorkFtraceEvent>;
+
+ static constexpr FieldMetadata_Function kFunction{};
+ void set_function(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Function::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Workqueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueQueueWorkFtraceEvent>;
+
+ static constexpr FieldMetadata_Workqueue kWorkqueue{};
+ void set_workqueue(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Workqueue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReqCpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ WorkqueueQueueWorkFtraceEvent>;
+
+ static constexpr FieldMetadata_ReqCpu kReqCpu{};
+ void set_req_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReqCpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ WorkqueueQueueWorkFtraceEvent>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class WorkqueueExecuteStartFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ WorkqueueExecuteStartFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit WorkqueueExecuteStartFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit WorkqueueExecuteStartFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_work() const { return at<1>().valid(); }
+ uint64_t work() const { return at<1>().as_uint64(); }
+ bool has_function() const { return at<2>().valid(); }
+ uint64_t function() const { return at<2>().as_uint64(); }
+};
+
+class WorkqueueExecuteStartFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = WorkqueueExecuteStartFtraceEvent_Decoder;
+ enum : int32_t {
+ kWorkFieldNumber = 1,
+ kFunctionFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.WorkqueueExecuteStartFtraceEvent"; }
+
+
+ using FieldMetadata_Work =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueExecuteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Work kWork{};
+ void set_work(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Work::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Function =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueExecuteStartFtraceEvent>;
+
+ static constexpr FieldMetadata_Function kFunction{};
+ void set_function(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Function::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class WorkqueueExecuteEndFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ WorkqueueExecuteEndFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit WorkqueueExecuteEndFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit WorkqueueExecuteEndFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_work() const { return at<1>().valid(); }
+ uint64_t work() const { return at<1>().as_uint64(); }
+ bool has_function() const { return at<2>().valid(); }
+ uint64_t function() const { return at<2>().as_uint64(); }
+};
+
+class WorkqueueExecuteEndFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = WorkqueueExecuteEndFtraceEvent_Decoder;
+ enum : int32_t {
+ kWorkFieldNumber = 1,
+ kFunctionFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.WorkqueueExecuteEndFtraceEvent"; }
+
+
+ using FieldMetadata_Work =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueExecuteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Work kWork{};
+ void set_work(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Work::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Function =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueExecuteEndFtraceEvent>;
+
+ static constexpr FieldMetadata_Function kFunction{};
+ void set_function(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Function::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class WorkqueueActivateWorkFtraceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ WorkqueueActivateWorkFtraceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit WorkqueueActivateWorkFtraceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit WorkqueueActivateWorkFtraceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_work() const { return at<1>().valid(); }
+ uint64_t work() const { return at<1>().as_uint64(); }
+};
+
+class WorkqueueActivateWorkFtraceEvent : public ::protozero::Message {
+ public:
+ using Decoder = WorkqueueActivateWorkFtraceEvent_Decoder;
+ enum : int32_t {
+ kWorkFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.WorkqueueActivateWorkFtraceEvent"; }
+
+
+ using FieldMetadata_Work =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ WorkqueueActivateWorkFtraceEvent>;
+
+ static constexpr FieldMetadata_Work kWork{};
+ void set_work(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Work::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_GPU_COUNTER_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_GPU_COUNTER_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class GpuCounterDescriptor;
+class GpuCounterEvent_GpuCounter;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class GpuCounterEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GpuCounterEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuCounterEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuCounterEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_counter_descriptor() const { return at<1>().valid(); }
+ ::protozero::ConstBytes counter_descriptor() const { return at<1>().as_bytes(); }
+ bool has_counters() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> counters() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_gpu_id() const { return at<3>().valid(); }
+ int32_t gpu_id() const { return at<3>().as_int32(); }
+};
+
+class GpuCounterEvent : public ::protozero::Message {
+ public:
+ using Decoder = GpuCounterEvent_Decoder;
+ enum : int32_t {
+ kCounterDescriptorFieldNumber = 1,
+ kCountersFieldNumber = 2,
+ kGpuIdFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuCounterEvent"; }
+
+ using GpuCounter = ::perfetto::protos::pbzero::GpuCounterEvent_GpuCounter;
+
+ using FieldMetadata_CounterDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuCounterDescriptor,
+ GpuCounterEvent>;
+
+ static constexpr FieldMetadata_CounterDescriptor kCounterDescriptor{};
+ template <typename T = GpuCounterDescriptor> T* set_counter_descriptor() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Counters =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuCounterEvent_GpuCounter,
+ GpuCounterEvent>;
+
+ static constexpr FieldMetadata_Counters kCounters{};
+ template <typename T = GpuCounterEvent_GpuCounter> T* add_counters() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_GpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ GpuCounterEvent>;
+
+ static constexpr FieldMetadata_GpuId kGpuId{};
+ void set_gpu_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuCounterEvent_GpuCounter_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuCounterEvent_GpuCounter_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuCounterEvent_GpuCounter_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuCounterEvent_GpuCounter_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_counter_id() const { return at<1>().valid(); }
+ uint32_t counter_id() const { return at<1>().as_uint32(); }
+ bool has_int_value() const { return at<2>().valid(); }
+ int64_t int_value() const { return at<2>().as_int64(); }
+ bool has_double_value() const { return at<3>().valid(); }
+ double double_value() const { return at<3>().as_double(); }
+};
+
+class GpuCounterEvent_GpuCounter : public ::protozero::Message {
+ public:
+ using Decoder = GpuCounterEvent_GpuCounter_Decoder;
+ enum : int32_t {
+ kCounterIdFieldNumber = 1,
+ kIntValueFieldNumber = 2,
+ kDoubleValueFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuCounterEvent.GpuCounter"; }
+
+
+ using FieldMetadata_CounterId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuCounterEvent_GpuCounter>;
+
+ static constexpr FieldMetadata_CounterId kCounterId{};
+ void set_counter_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ GpuCounterEvent_GpuCounter>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ GpuCounterEvent_GpuCounter>;
+
+ static constexpr FieldMetadata_DoubleValue kDoubleValue{};
+ void set_double_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/gpu/gpu_log.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_GPU_LOG_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_GPU_LOG_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_GpuLog {
+enum Severity : int32_t;
+} // namespace perfetto_pbzero_enum_GpuLog
+using GpuLog_Severity = perfetto_pbzero_enum_GpuLog::Severity;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_GpuLog {
+enum Severity : int32_t {
+ LOG_SEVERITY_UNSPECIFIED = 0,
+ LOG_SEVERITY_VERBOSE = 1,
+ LOG_SEVERITY_DEBUG = 2,
+ LOG_SEVERITY_INFO = 3,
+ LOG_SEVERITY_WARNING = 4,
+ LOG_SEVERITY_ERROR = 5,
+};
+} // namespace perfetto_pbzero_enum_GpuLog
+using GpuLog_Severity = perfetto_pbzero_enum_GpuLog::Severity;
+
+
+constexpr GpuLog_Severity GpuLog_Severity_MIN = GpuLog_Severity::LOG_SEVERITY_UNSPECIFIED;
+constexpr GpuLog_Severity GpuLog_Severity_MAX = GpuLog_Severity::LOG_SEVERITY_ERROR;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* GpuLog_Severity_Name(::perfetto::protos::pbzero::GpuLog_Severity value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::GpuLog_Severity::LOG_SEVERITY_UNSPECIFIED:
+ return "LOG_SEVERITY_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::GpuLog_Severity::LOG_SEVERITY_VERBOSE:
+ return "LOG_SEVERITY_VERBOSE";
+
+ case ::perfetto::protos::pbzero::GpuLog_Severity::LOG_SEVERITY_DEBUG:
+ return "LOG_SEVERITY_DEBUG";
+
+ case ::perfetto::protos::pbzero::GpuLog_Severity::LOG_SEVERITY_INFO:
+ return "LOG_SEVERITY_INFO";
+
+ case ::perfetto::protos::pbzero::GpuLog_Severity::LOG_SEVERITY_WARNING:
+ return "LOG_SEVERITY_WARNING";
+
+ case ::perfetto::protos::pbzero::GpuLog_Severity::LOG_SEVERITY_ERROR:
+ return "LOG_SEVERITY_ERROR";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class GpuLog_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuLog_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuLog_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuLog_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_severity() const { return at<1>().valid(); }
+ int32_t severity() const { return at<1>().as_int32(); }
+ bool has_tag() const { return at<2>().valid(); }
+ ::protozero::ConstChars tag() const { return at<2>().as_string(); }
+ bool has_log_message() const { return at<3>().valid(); }
+ ::protozero::ConstChars log_message() const { return at<3>().as_string(); }
+};
+
+class GpuLog : public ::protozero::Message {
+ public:
+ using Decoder = GpuLog_Decoder;
+ enum : int32_t {
+ kSeverityFieldNumber = 1,
+ kTagFieldNumber = 2,
+ kLogMessageFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuLog"; }
+
+
+ using Severity = ::perfetto::protos::pbzero::GpuLog_Severity;
+ static inline const char* Severity_Name(Severity value) {
+ return ::perfetto::protos::pbzero::GpuLog_Severity_Name(value);
+ }
+ static inline const Severity LOG_SEVERITY_UNSPECIFIED = Severity::LOG_SEVERITY_UNSPECIFIED;
+ static inline const Severity LOG_SEVERITY_VERBOSE = Severity::LOG_SEVERITY_VERBOSE;
+ static inline const Severity LOG_SEVERITY_DEBUG = Severity::LOG_SEVERITY_DEBUG;
+ static inline const Severity LOG_SEVERITY_INFO = Severity::LOG_SEVERITY_INFO;
+ static inline const Severity LOG_SEVERITY_WARNING = Severity::LOG_SEVERITY_WARNING;
+ static inline const Severity LOG_SEVERITY_ERROR = Severity::LOG_SEVERITY_ERROR;
+
+ using FieldMetadata_Severity =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ GpuLog_Severity,
+ GpuLog>;
+
+ static constexpr FieldMetadata_Severity kSeverity{};
+ void set_severity(GpuLog_Severity value) {
+ static constexpr uint32_t field_id = FieldMetadata_Severity::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tag =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuLog>;
+
+ static constexpr FieldMetadata_Tag kTag{};
+ void set_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, data, size);
+ }
+ void set_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Tag::kFieldId, chars.data, chars.size);
+ }
+ void set_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LogMessage =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuLog>;
+
+ static constexpr FieldMetadata_LogMessage kLogMessage{};
+ void set_log_message(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_LogMessage::kFieldId, data, size);
+ }
+ void set_log_message(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_LogMessage::kFieldId, chars.data, chars.size);
+ }
+ void set_log_message(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_LogMessage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_GPU_RENDER_STAGE_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_GPU_RENDER_STAGE_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class GpuRenderStageEvent_ExtraData;
+class GpuRenderStageEvent_Specifications;
+class GpuRenderStageEvent_Specifications_ContextSpec;
+class GpuRenderStageEvent_Specifications_Description;
+namespace perfetto_pbzero_enum_InternedGpuRenderStageSpecification {
+enum RenderStageCategory : int32_t;
+} // namespace perfetto_pbzero_enum_InternedGpuRenderStageSpecification
+using InternedGpuRenderStageSpecification_RenderStageCategory = perfetto_pbzero_enum_InternedGpuRenderStageSpecification::RenderStageCategory;
+namespace perfetto_pbzero_enum_InternedGraphicsContext {
+enum Api : int32_t;
+} // namespace perfetto_pbzero_enum_InternedGraphicsContext
+using InternedGraphicsContext_Api = perfetto_pbzero_enum_InternedGraphicsContext::Api;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_InternedGpuRenderStageSpecification {
+enum RenderStageCategory : int32_t {
+ OTHER = 0,
+ GRAPHICS = 1,
+ COMPUTE = 2,
+};
+} // namespace perfetto_pbzero_enum_InternedGpuRenderStageSpecification
+using InternedGpuRenderStageSpecification_RenderStageCategory = perfetto_pbzero_enum_InternedGpuRenderStageSpecification::RenderStageCategory;
+
+
+constexpr InternedGpuRenderStageSpecification_RenderStageCategory InternedGpuRenderStageSpecification_RenderStageCategory_MIN = InternedGpuRenderStageSpecification_RenderStageCategory::OTHER;
+constexpr InternedGpuRenderStageSpecification_RenderStageCategory InternedGpuRenderStageSpecification_RenderStageCategory_MAX = InternedGpuRenderStageSpecification_RenderStageCategory::COMPUTE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* InternedGpuRenderStageSpecification_RenderStageCategory_Name(::perfetto::protos::pbzero::InternedGpuRenderStageSpecification_RenderStageCategory value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::InternedGpuRenderStageSpecification_RenderStageCategory::OTHER:
+ return "OTHER";
+
+ case ::perfetto::protos::pbzero::InternedGpuRenderStageSpecification_RenderStageCategory::GRAPHICS:
+ return "GRAPHICS";
+
+ case ::perfetto::protos::pbzero::InternedGpuRenderStageSpecification_RenderStageCategory::COMPUTE:
+ return "COMPUTE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_InternedGraphicsContext {
+enum Api : int32_t {
+ UNDEFINED = 0,
+ OPEN_GL = 1,
+ VULKAN = 2,
+ OPEN_CL = 3,
+};
+} // namespace perfetto_pbzero_enum_InternedGraphicsContext
+using InternedGraphicsContext_Api = perfetto_pbzero_enum_InternedGraphicsContext::Api;
+
+
+constexpr InternedGraphicsContext_Api InternedGraphicsContext_Api_MIN = InternedGraphicsContext_Api::UNDEFINED;
+constexpr InternedGraphicsContext_Api InternedGraphicsContext_Api_MAX = InternedGraphicsContext_Api::OPEN_CL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* InternedGraphicsContext_Api_Name(::perfetto::protos::pbzero::InternedGraphicsContext_Api value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::InternedGraphicsContext_Api::UNDEFINED:
+ return "UNDEFINED";
+
+ case ::perfetto::protos::pbzero::InternedGraphicsContext_Api::OPEN_GL:
+ return "OPEN_GL";
+
+ case ::perfetto::protos::pbzero::InternedGraphicsContext_Api::VULKAN:
+ return "VULKAN";
+
+ case ::perfetto::protos::pbzero::InternedGraphicsContext_Api::OPEN_CL:
+ return "OPEN_CL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class InternedGpuRenderStageSpecification_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedGpuRenderStageSpecification_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedGpuRenderStageSpecification_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedGpuRenderStageSpecification_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_description() const { return at<3>().valid(); }
+ ::protozero::ConstChars description() const { return at<3>().as_string(); }
+ bool has_category() const { return at<4>().valid(); }
+ int32_t category() const { return at<4>().as_int32(); }
+};
+
+class InternedGpuRenderStageSpecification : public ::protozero::Message {
+ public:
+ using Decoder = InternedGpuRenderStageSpecification_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kDescriptionFieldNumber = 3,
+ kCategoryFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedGpuRenderStageSpecification"; }
+
+
+ using RenderStageCategory = ::perfetto::protos::pbzero::InternedGpuRenderStageSpecification_RenderStageCategory;
+ static inline const char* RenderStageCategory_Name(RenderStageCategory value) {
+ return ::perfetto::protos::pbzero::InternedGpuRenderStageSpecification_RenderStageCategory_Name(value);
+ }
+ static inline const RenderStageCategory OTHER = RenderStageCategory::OTHER;
+ static inline const RenderStageCategory GRAPHICS = RenderStageCategory::GRAPHICS;
+ static inline const RenderStageCategory COMPUTE = RenderStageCategory::COMPUTE;
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedGpuRenderStageSpecification>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InternedGpuRenderStageSpecification>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Description =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ InternedGpuRenderStageSpecification>;
+
+ static constexpr FieldMetadata_Description kDescription{};
+ void set_description(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Description::kFieldId, data, size);
+ }
+ void set_description(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Description::kFieldId, chars.data, chars.size);
+ }
+ void set_description(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Description::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Category =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ InternedGpuRenderStageSpecification_RenderStageCategory,
+ InternedGpuRenderStageSpecification>;
+
+ static constexpr FieldMetadata_Category kCategory{};
+ void set_category(InternedGpuRenderStageSpecification_RenderStageCategory value) {
+ static constexpr uint32_t field_id = FieldMetadata_Category::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InternedGraphicsContext_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedGraphicsContext_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedGraphicsContext_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedGraphicsContext_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+ bool has_api() const { return at<3>().valid(); }
+ int32_t api() const { return at<3>().as_int32(); }
+};
+
+class InternedGraphicsContext : public ::protozero::Message {
+ public:
+ using Decoder = InternedGraphicsContext_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kApiFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedGraphicsContext"; }
+
+
+ using Api = ::perfetto::protos::pbzero::InternedGraphicsContext_Api;
+ static inline const char* Api_Name(Api value) {
+ return ::perfetto::protos::pbzero::InternedGraphicsContext_Api_Name(value);
+ }
+ static inline const Api UNDEFINED = Api::UNDEFINED;
+ static inline const Api OPEN_GL = Api::OPEN_GL;
+ static inline const Api VULKAN = Api::VULKAN;
+ static inline const Api OPEN_CL = Api::OPEN_CL;
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedGraphicsContext>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ InternedGraphicsContext>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Api =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ InternedGraphicsContext_Api,
+ InternedGraphicsContext>;
+
+ static constexpr FieldMetadata_Api kApi{};
+ void set_api(InternedGraphicsContext_Api value) {
+ static constexpr uint32_t field_id = FieldMetadata_Api::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuRenderStageEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/15, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GpuRenderStageEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuRenderStageEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuRenderStageEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_id() const { return at<1>().valid(); }
+ uint64_t event_id() const { return at<1>().as_uint64(); }
+ bool has_duration() const { return at<2>().valid(); }
+ uint64_t duration() const { return at<2>().as_uint64(); }
+ bool has_hw_queue_iid() const { return at<13>().valid(); }
+ uint64_t hw_queue_iid() const { return at<13>().as_uint64(); }
+ bool has_stage_iid() const { return at<14>().valid(); }
+ uint64_t stage_iid() const { return at<14>().as_uint64(); }
+ bool has_gpu_id() const { return at<11>().valid(); }
+ int32_t gpu_id() const { return at<11>().as_int32(); }
+ bool has_context() const { return at<5>().valid(); }
+ uint64_t context() const { return at<5>().as_uint64(); }
+ bool has_render_target_handle() const { return at<8>().valid(); }
+ uint64_t render_target_handle() const { return at<8>().as_uint64(); }
+ bool has_submission_id() const { return at<10>().valid(); }
+ uint32_t submission_id() const { return at<10>().as_uint32(); }
+ bool has_extra_data() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> extra_data() const { return GetRepeated<::protozero::ConstBytes>(6); }
+ bool has_render_pass_handle() const { return at<9>().valid(); }
+ uint64_t render_pass_handle() const { return at<9>().as_uint64(); }
+ bool has_render_subpass_index_mask() const { return at<15>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> render_subpass_index_mask() const { return GetRepeated<uint64_t>(15); }
+ bool has_command_buffer_handle() const { return at<12>().valid(); }
+ uint64_t command_buffer_handle() const { return at<12>().as_uint64(); }
+ bool has_specifications() const { return at<7>().valid(); }
+ ::protozero::ConstBytes specifications() const { return at<7>().as_bytes(); }
+ bool has_hw_queue_id() const { return at<3>().valid(); }
+ int32_t hw_queue_id() const { return at<3>().as_int32(); }
+ bool has_stage_id() const { return at<4>().valid(); }
+ int32_t stage_id() const { return at<4>().as_int32(); }
+};
+
+class GpuRenderStageEvent : public ::protozero::Message {
+ public:
+ using Decoder = GpuRenderStageEvent_Decoder;
+ enum : int32_t {
+ kEventIdFieldNumber = 1,
+ kDurationFieldNumber = 2,
+ kHwQueueIidFieldNumber = 13,
+ kStageIidFieldNumber = 14,
+ kGpuIdFieldNumber = 11,
+ kContextFieldNumber = 5,
+ kRenderTargetHandleFieldNumber = 8,
+ kSubmissionIdFieldNumber = 10,
+ kExtraDataFieldNumber = 6,
+ kRenderPassHandleFieldNumber = 9,
+ kRenderSubpassIndexMaskFieldNumber = 15,
+ kCommandBufferHandleFieldNumber = 12,
+ kSpecificationsFieldNumber = 7,
+ kHwQueueIdFieldNumber = 3,
+ kStageIdFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuRenderStageEvent"; }
+
+ using ExtraData = ::perfetto::protos::pbzero::GpuRenderStageEvent_ExtraData;
+ using Specifications = ::perfetto::protos::pbzero::GpuRenderStageEvent_Specifications;
+
+ using FieldMetadata_EventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_EventId kEventId{};
+ void set_event_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Duration =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_Duration kDuration{};
+ void set_duration(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Duration::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwQueueIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_HwQueueIid kHwQueueIid{};
+ void set_hw_queue_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwQueueIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StageIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_StageIid kStageIid{};
+ void set_stage_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StageIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_GpuId kGpuId{};
+ void set_gpu_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RenderTargetHandle =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_RenderTargetHandle kRenderTargetHandle{};
+ void set_render_target_handle(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RenderTargetHandle::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SubmissionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_SubmissionId kSubmissionId{};
+ void set_submission_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SubmissionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExtraData =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuRenderStageEvent_ExtraData,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_ExtraData kExtraData{};
+ template <typename T = GpuRenderStageEvent_ExtraData> T* add_extra_data() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_RenderPassHandle =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_RenderPassHandle kRenderPassHandle{};
+ void set_render_pass_handle(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RenderPassHandle::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RenderSubpassIndexMask =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_RenderSubpassIndexMask kRenderSubpassIndexMask{};
+ void add_render_subpass_index_mask(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RenderSubpassIndexMask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CommandBufferHandle =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_CommandBufferHandle kCommandBufferHandle{};
+ void set_command_buffer_handle(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CommandBufferHandle::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Specifications =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuRenderStageEvent_Specifications,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_Specifications kSpecifications{};
+ template <typename T = GpuRenderStageEvent_Specifications> T* set_specifications() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_HwQueueId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_HwQueueId kHwQueueId{};
+ void set_hw_queue_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwQueueId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StageId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ GpuRenderStageEvent>;
+
+ static constexpr FieldMetadata_StageId kStageId{};
+ void set_stage_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StageId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuRenderStageEvent_Specifications_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ GpuRenderStageEvent_Specifications_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuRenderStageEvent_Specifications_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuRenderStageEvent_Specifications_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context_spec() const { return at<1>().valid(); }
+ ::protozero::ConstBytes context_spec() const { return at<1>().as_bytes(); }
+ bool has_hw_queue() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> hw_queue() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_stage() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> stage() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class GpuRenderStageEvent_Specifications : public ::protozero::Message {
+ public:
+ using Decoder = GpuRenderStageEvent_Specifications_Decoder;
+ enum : int32_t {
+ kContextSpecFieldNumber = 1,
+ kHwQueueFieldNumber = 2,
+ kStageFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuRenderStageEvent.Specifications"; }
+
+ using ContextSpec = ::perfetto::protos::pbzero::GpuRenderStageEvent_Specifications_ContextSpec;
+ using Description = ::perfetto::protos::pbzero::GpuRenderStageEvent_Specifications_Description;
+
+ using FieldMetadata_ContextSpec =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuRenderStageEvent_Specifications_ContextSpec,
+ GpuRenderStageEvent_Specifications>;
+
+ static constexpr FieldMetadata_ContextSpec kContextSpec{};
+ template <typename T = GpuRenderStageEvent_Specifications_ContextSpec> T* set_context_spec() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_HwQueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuRenderStageEvent_Specifications_Description,
+ GpuRenderStageEvent_Specifications>;
+
+ static constexpr FieldMetadata_HwQueue kHwQueue{};
+ template <typename T = GpuRenderStageEvent_Specifications_Description> T* add_hw_queue() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_Stage =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ GpuRenderStageEvent_Specifications_Description,
+ GpuRenderStageEvent_Specifications>;
+
+ static constexpr FieldMetadata_Stage kStage{};
+ template <typename T = GpuRenderStageEvent_Specifications_Description> T* add_stage() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class GpuRenderStageEvent_Specifications_Description_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuRenderStageEvent_Specifications_Description_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuRenderStageEvent_Specifications_Description_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuRenderStageEvent_Specifications_Description_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_description() const { return at<2>().valid(); }
+ ::protozero::ConstChars description() const { return at<2>().as_string(); }
+};
+
+class GpuRenderStageEvent_Specifications_Description : public ::protozero::Message {
+ public:
+ using Decoder = GpuRenderStageEvent_Specifications_Description_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kDescriptionFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuRenderStageEvent.Specifications.Description"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuRenderStageEvent_Specifications_Description>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Description =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuRenderStageEvent_Specifications_Description>;
+
+ static constexpr FieldMetadata_Description kDescription{};
+ void set_description(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Description::kFieldId, data, size);
+ }
+ void set_description(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Description::kFieldId, chars.data, chars.size);
+ }
+ void set_description(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Description::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuRenderStageEvent_Specifications_ContextSpec_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuRenderStageEvent_Specifications_ContextSpec_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuRenderStageEvent_Specifications_ContextSpec_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuRenderStageEvent_Specifications_ContextSpec_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_context() const { return at<1>().valid(); }
+ uint64_t context() const { return at<1>().as_uint64(); }
+ bool has_pid() const { return at<2>().valid(); }
+ int32_t pid() const { return at<2>().as_int32(); }
+};
+
+class GpuRenderStageEvent_Specifications_ContextSpec : public ::protozero::Message {
+ public:
+ using Decoder = GpuRenderStageEvent_Specifications_ContextSpec_Decoder;
+ enum : int32_t {
+ kContextFieldNumber = 1,
+ kPidFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuRenderStageEvent.Specifications.ContextSpec"; }
+
+
+ using FieldMetadata_Context =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ GpuRenderStageEvent_Specifications_ContextSpec>;
+
+ static constexpr FieldMetadata_Context kContext{};
+ void set_context(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Context::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ GpuRenderStageEvent_Specifications_ContextSpec>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class GpuRenderStageEvent_ExtraData_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ GpuRenderStageEvent_ExtraData_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit GpuRenderStageEvent_ExtraData_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit GpuRenderStageEvent_ExtraData_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class GpuRenderStageEvent_ExtraData : public ::protozero::Message {
+ public:
+ using Decoder = GpuRenderStageEvent_ExtraData_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.GpuRenderStageEvent.ExtraData"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuRenderStageEvent_ExtraData>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ GpuRenderStageEvent_ExtraData>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_VULKAN_API_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_VULKAN_API_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class VulkanApiEvent_VkDebugUtilsObjectName;
+class VulkanApiEvent_VkQueueSubmit;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class VulkanApiEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VulkanApiEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VulkanApiEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VulkanApiEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_vk_debug_utils_object_name() const { return at<1>().valid(); }
+ ::protozero::ConstBytes vk_debug_utils_object_name() const { return at<1>().as_bytes(); }
+ bool has_vk_queue_submit() const { return at<2>().valid(); }
+ ::protozero::ConstBytes vk_queue_submit() const { return at<2>().as_bytes(); }
+};
+
+class VulkanApiEvent : public ::protozero::Message {
+ public:
+ using Decoder = VulkanApiEvent_Decoder;
+ enum : int32_t {
+ kVkDebugUtilsObjectNameFieldNumber = 1,
+ kVkQueueSubmitFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VulkanApiEvent"; }
+
+ using VkDebugUtilsObjectName = ::perfetto::protos::pbzero::VulkanApiEvent_VkDebugUtilsObjectName;
+ using VkQueueSubmit = ::perfetto::protos::pbzero::VulkanApiEvent_VkQueueSubmit;
+
+ using FieldMetadata_VkDebugUtilsObjectName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VulkanApiEvent_VkDebugUtilsObjectName,
+ VulkanApiEvent>;
+
+ static constexpr FieldMetadata_VkDebugUtilsObjectName kVkDebugUtilsObjectName{};
+ template <typename T = VulkanApiEvent_VkDebugUtilsObjectName> T* set_vk_debug_utils_object_name() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_VkQueueSubmit =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VulkanApiEvent_VkQueueSubmit,
+ VulkanApiEvent>;
+
+ static constexpr FieldMetadata_VkQueueSubmit kVkQueueSubmit{};
+ template <typename T = VulkanApiEvent_VkQueueSubmit> T* set_vk_queue_submit() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class VulkanApiEvent_VkQueueSubmit_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ VulkanApiEvent_VkQueueSubmit_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VulkanApiEvent_VkQueueSubmit_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VulkanApiEvent_VkQueueSubmit_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_duration_ns() const { return at<1>().valid(); }
+ uint64_t duration_ns() const { return at<1>().as_uint64(); }
+ bool has_pid() const { return at<2>().valid(); }
+ uint32_t pid() const { return at<2>().as_uint32(); }
+ bool has_tid() const { return at<3>().valid(); }
+ uint32_t tid() const { return at<3>().as_uint32(); }
+ bool has_vk_queue() const { return at<4>().valid(); }
+ uint64_t vk_queue() const { return at<4>().as_uint64(); }
+ bool has_vk_command_buffers() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> vk_command_buffers() const { return GetRepeated<uint64_t>(5); }
+ bool has_submission_id() const { return at<6>().valid(); }
+ uint32_t submission_id() const { return at<6>().as_uint32(); }
+};
+
+class VulkanApiEvent_VkQueueSubmit : public ::protozero::Message {
+ public:
+ using Decoder = VulkanApiEvent_VkQueueSubmit_Decoder;
+ enum : int32_t {
+ kDurationNsFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTidFieldNumber = 3,
+ kVkQueueFieldNumber = 4,
+ kVkCommandBuffersFieldNumber = 5,
+ kSubmissionIdFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VulkanApiEvent.VkQueueSubmit"; }
+
+
+ using FieldMetadata_DurationNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanApiEvent_VkQueueSubmit>;
+
+ static constexpr FieldMetadata_DurationNs kDurationNs{};
+ void set_duration_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DurationNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VulkanApiEvent_VkQueueSubmit>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VulkanApiEvent_VkQueueSubmit>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VkQueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanApiEvent_VkQueueSubmit>;
+
+ static constexpr FieldMetadata_VkQueue kVkQueue{};
+ void set_vk_queue(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VkQueue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VkCommandBuffers =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanApiEvent_VkQueueSubmit>;
+
+ static constexpr FieldMetadata_VkCommandBuffers kVkCommandBuffers{};
+ void add_vk_command_buffers(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VkCommandBuffers::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SubmissionId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VulkanApiEvent_VkQueueSubmit>;
+
+ static constexpr FieldMetadata_SubmissionId kSubmissionId{};
+ void set_submission_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SubmissionId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class VulkanApiEvent_VkDebugUtilsObjectName_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VulkanApiEvent_VkDebugUtilsObjectName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VulkanApiEvent_VkDebugUtilsObjectName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VulkanApiEvent_VkDebugUtilsObjectName_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ uint32_t pid() const { return at<1>().as_uint32(); }
+ bool has_vk_device() const { return at<2>().valid(); }
+ uint64_t vk_device() const { return at<2>().as_uint64(); }
+ bool has_object_type() const { return at<3>().valid(); }
+ int32_t object_type() const { return at<3>().as_int32(); }
+ bool has_object() const { return at<4>().valid(); }
+ uint64_t object() const { return at<4>().as_uint64(); }
+ bool has_object_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars object_name() const { return at<5>().as_string(); }
+};
+
+class VulkanApiEvent_VkDebugUtilsObjectName : public ::protozero::Message {
+ public:
+ using Decoder = VulkanApiEvent_VkDebugUtilsObjectName_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kVkDeviceFieldNumber = 2,
+ kObjectTypeFieldNumber = 3,
+ kObjectFieldNumber = 4,
+ kObjectNameFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VulkanApiEvent.VkDebugUtilsObjectName"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VulkanApiEvent_VkDebugUtilsObjectName>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VkDevice =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanApiEvent_VkDebugUtilsObjectName>;
+
+ static constexpr FieldMetadata_VkDevice kVkDevice{};
+ void set_vk_device(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VkDevice::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ObjectType =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ VulkanApiEvent_VkDebugUtilsObjectName>;
+
+ static constexpr FieldMetadata_ObjectType kObjectType{};
+ void set_object_type(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObjectType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Object =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanApiEvent_VkDebugUtilsObjectName>;
+
+ static constexpr FieldMetadata_Object kObject{};
+ void set_object(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Object::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ObjectName =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ VulkanApiEvent_VkDebugUtilsObjectName>;
+
+ static constexpr FieldMetadata_ObjectName kObjectName{};
+ void set_object_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ObjectName::kFieldId, data, size);
+ }
+ void set_object_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ObjectName::kFieldId, chars.data, chars.size);
+ }
+ void set_object_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObjectName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_VULKAN_MEMORY_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_GPU_VULKAN_MEMORY_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class VulkanMemoryEventAnnotation;
+namespace perfetto_pbzero_enum_VulkanMemoryEvent {
+enum AllocationScope : int32_t;
+} // namespace perfetto_pbzero_enum_VulkanMemoryEvent
+using VulkanMemoryEvent_AllocationScope = perfetto_pbzero_enum_VulkanMemoryEvent::AllocationScope;
+namespace perfetto_pbzero_enum_VulkanMemoryEvent {
+enum Operation : int32_t;
+} // namespace perfetto_pbzero_enum_VulkanMemoryEvent
+using VulkanMemoryEvent_Operation = perfetto_pbzero_enum_VulkanMemoryEvent::Operation;
+namespace perfetto_pbzero_enum_VulkanMemoryEvent {
+enum Source : int32_t;
+} // namespace perfetto_pbzero_enum_VulkanMemoryEvent
+using VulkanMemoryEvent_Source = perfetto_pbzero_enum_VulkanMemoryEvent::Source;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_VulkanMemoryEvent {
+enum Source : int32_t {
+ SOURCE_UNSPECIFIED = 0,
+ SOURCE_DRIVER = 1,
+ SOURCE_DEVICE = 2,
+ SOURCE_DEVICE_MEMORY = 3,
+ SOURCE_BUFFER = 4,
+ SOURCE_IMAGE = 5,
+};
+} // namespace perfetto_pbzero_enum_VulkanMemoryEvent
+using VulkanMemoryEvent_Source = perfetto_pbzero_enum_VulkanMemoryEvent::Source;
+
+
+constexpr VulkanMemoryEvent_Source VulkanMemoryEvent_Source_MIN = VulkanMemoryEvent_Source::SOURCE_UNSPECIFIED;
+constexpr VulkanMemoryEvent_Source VulkanMemoryEvent_Source_MAX = VulkanMemoryEvent_Source::SOURCE_IMAGE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* VulkanMemoryEvent_Source_Name(::perfetto::protos::pbzero::VulkanMemoryEvent_Source value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Source::SOURCE_UNSPECIFIED:
+ return "SOURCE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Source::SOURCE_DRIVER:
+ return "SOURCE_DRIVER";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Source::SOURCE_DEVICE:
+ return "SOURCE_DEVICE";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Source::SOURCE_DEVICE_MEMORY:
+ return "SOURCE_DEVICE_MEMORY";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Source::SOURCE_BUFFER:
+ return "SOURCE_BUFFER";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Source::SOURCE_IMAGE:
+ return "SOURCE_IMAGE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_VulkanMemoryEvent {
+enum Operation : int32_t {
+ OP_UNSPECIFIED = 0,
+ OP_CREATE = 1,
+ OP_DESTROY = 2,
+ OP_BIND = 3,
+ OP_DESTROY_BOUND = 4,
+ OP_ANNOTATIONS = 5,
+};
+} // namespace perfetto_pbzero_enum_VulkanMemoryEvent
+using VulkanMemoryEvent_Operation = perfetto_pbzero_enum_VulkanMemoryEvent::Operation;
+
+
+constexpr VulkanMemoryEvent_Operation VulkanMemoryEvent_Operation_MIN = VulkanMemoryEvent_Operation::OP_UNSPECIFIED;
+constexpr VulkanMemoryEvent_Operation VulkanMemoryEvent_Operation_MAX = VulkanMemoryEvent_Operation::OP_ANNOTATIONS;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* VulkanMemoryEvent_Operation_Name(::perfetto::protos::pbzero::VulkanMemoryEvent_Operation value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation::OP_UNSPECIFIED:
+ return "OP_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation::OP_CREATE:
+ return "OP_CREATE";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation::OP_DESTROY:
+ return "OP_DESTROY";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation::OP_BIND:
+ return "OP_BIND";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation::OP_DESTROY_BOUND:
+ return "OP_DESTROY_BOUND";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation::OP_ANNOTATIONS:
+ return "OP_ANNOTATIONS";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_VulkanMemoryEvent {
+enum AllocationScope : int32_t {
+ SCOPE_UNSPECIFIED = 0,
+ SCOPE_COMMAND = 1,
+ SCOPE_OBJECT = 2,
+ SCOPE_CACHE = 3,
+ SCOPE_DEVICE = 4,
+ SCOPE_INSTANCE = 5,
+};
+} // namespace perfetto_pbzero_enum_VulkanMemoryEvent
+using VulkanMemoryEvent_AllocationScope = perfetto_pbzero_enum_VulkanMemoryEvent::AllocationScope;
+
+
+constexpr VulkanMemoryEvent_AllocationScope VulkanMemoryEvent_AllocationScope_MIN = VulkanMemoryEvent_AllocationScope::SCOPE_UNSPECIFIED;
+constexpr VulkanMemoryEvent_AllocationScope VulkanMemoryEvent_AllocationScope_MAX = VulkanMemoryEvent_AllocationScope::SCOPE_INSTANCE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* VulkanMemoryEvent_AllocationScope_Name(::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope::SCOPE_UNSPECIFIED:
+ return "SCOPE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope::SCOPE_COMMAND:
+ return "SCOPE_COMMAND";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope::SCOPE_OBJECT:
+ return "SCOPE_OBJECT";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope::SCOPE_CACHE:
+ return "SCOPE_CACHE";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope::SCOPE_DEVICE:
+ return "SCOPE_DEVICE";
+
+ case ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope::SCOPE_INSTANCE:
+ return "SCOPE_INSTANCE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class VulkanMemoryEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/20, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ VulkanMemoryEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VulkanMemoryEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VulkanMemoryEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_source() const { return at<1>().valid(); }
+ int32_t source() const { return at<1>().as_int32(); }
+ bool has_operation() const { return at<2>().valid(); }
+ int32_t operation() const { return at<2>().as_int32(); }
+ bool has_timestamp() const { return at<3>().valid(); }
+ int64_t timestamp() const { return at<3>().as_int64(); }
+ bool has_pid() const { return at<4>().valid(); }
+ uint32_t pid() const { return at<4>().as_uint32(); }
+ bool has_memory_address() const { return at<5>().valid(); }
+ uint64_t memory_address() const { return at<5>().as_uint64(); }
+ bool has_memory_size() const { return at<6>().valid(); }
+ uint64_t memory_size() const { return at<6>().as_uint64(); }
+ bool has_caller_iid() const { return at<7>().valid(); }
+ uint64_t caller_iid() const { return at<7>().as_uint64(); }
+ bool has_allocation_scope() const { return at<8>().valid(); }
+ int32_t allocation_scope() const { return at<8>().as_int32(); }
+ bool has_annotations() const { return at<9>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> annotations() const { return GetRepeated<::protozero::ConstBytes>(9); }
+ bool has_device() const { return at<16>().valid(); }
+ uint64_t device() const { return at<16>().as_uint64(); }
+ bool has_device_memory() const { return at<17>().valid(); }
+ uint64_t device_memory() const { return at<17>().as_uint64(); }
+ bool has_memory_type() const { return at<18>().valid(); }
+ uint32_t memory_type() const { return at<18>().as_uint32(); }
+ bool has_heap() const { return at<19>().valid(); }
+ uint32_t heap() const { return at<19>().as_uint32(); }
+ bool has_object_handle() const { return at<20>().valid(); }
+ uint64_t object_handle() const { return at<20>().as_uint64(); }
+};
+
+class VulkanMemoryEvent : public ::protozero::Message {
+ public:
+ using Decoder = VulkanMemoryEvent_Decoder;
+ enum : int32_t {
+ kSourceFieldNumber = 1,
+ kOperationFieldNumber = 2,
+ kTimestampFieldNumber = 3,
+ kPidFieldNumber = 4,
+ kMemoryAddressFieldNumber = 5,
+ kMemorySizeFieldNumber = 6,
+ kCallerIidFieldNumber = 7,
+ kAllocationScopeFieldNumber = 8,
+ kAnnotationsFieldNumber = 9,
+ kDeviceFieldNumber = 16,
+ kDeviceMemoryFieldNumber = 17,
+ kMemoryTypeFieldNumber = 18,
+ kHeapFieldNumber = 19,
+ kObjectHandleFieldNumber = 20,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VulkanMemoryEvent"; }
+
+
+ using Source = ::perfetto::protos::pbzero::VulkanMemoryEvent_Source;
+ static inline const char* Source_Name(Source value) {
+ return ::perfetto::protos::pbzero::VulkanMemoryEvent_Source_Name(value);
+ }
+
+ using Operation = ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation;
+ static inline const char* Operation_Name(Operation value) {
+ return ::perfetto::protos::pbzero::VulkanMemoryEvent_Operation_Name(value);
+ }
+
+ using AllocationScope = ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope;
+ static inline const char* AllocationScope_Name(AllocationScope value) {
+ return ::perfetto::protos::pbzero::VulkanMemoryEvent_AllocationScope_Name(value);
+ }
+ static inline const Source SOURCE_UNSPECIFIED = Source::SOURCE_UNSPECIFIED;
+ static inline const Source SOURCE_DRIVER = Source::SOURCE_DRIVER;
+ static inline const Source SOURCE_DEVICE = Source::SOURCE_DEVICE;
+ static inline const Source SOURCE_DEVICE_MEMORY = Source::SOURCE_DEVICE_MEMORY;
+ static inline const Source SOURCE_BUFFER = Source::SOURCE_BUFFER;
+ static inline const Source SOURCE_IMAGE = Source::SOURCE_IMAGE;
+ static inline const Operation OP_UNSPECIFIED = Operation::OP_UNSPECIFIED;
+ static inline const Operation OP_CREATE = Operation::OP_CREATE;
+ static inline const Operation OP_DESTROY = Operation::OP_DESTROY;
+ static inline const Operation OP_BIND = Operation::OP_BIND;
+ static inline const Operation OP_DESTROY_BOUND = Operation::OP_DESTROY_BOUND;
+ static inline const Operation OP_ANNOTATIONS = Operation::OP_ANNOTATIONS;
+ static inline const AllocationScope SCOPE_UNSPECIFIED = AllocationScope::SCOPE_UNSPECIFIED;
+ static inline const AllocationScope SCOPE_COMMAND = AllocationScope::SCOPE_COMMAND;
+ static inline const AllocationScope SCOPE_OBJECT = AllocationScope::SCOPE_OBJECT;
+ static inline const AllocationScope SCOPE_CACHE = AllocationScope::SCOPE_CACHE;
+ static inline const AllocationScope SCOPE_DEVICE = AllocationScope::SCOPE_DEVICE;
+ static inline const AllocationScope SCOPE_INSTANCE = AllocationScope::SCOPE_INSTANCE;
+
+ using FieldMetadata_Source =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ VulkanMemoryEvent_Source,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_Source kSource{};
+ void set_source(VulkanMemoryEvent_Source value) {
+ static constexpr uint32_t field_id = FieldMetadata_Source::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Operation =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ VulkanMemoryEvent_Operation,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_Operation kOperation{};
+ void set_operation(VulkanMemoryEvent_Operation value) {
+ static constexpr uint32_t field_id = FieldMetadata_Operation::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MemoryAddress =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_MemoryAddress kMemoryAddress{};
+ void set_memory_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MemoryAddress::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MemorySize =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_MemorySize kMemorySize{};
+ void set_memory_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MemorySize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CallerIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_CallerIid kCallerIid{};
+ void set_caller_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallerIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllocationScope =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ VulkanMemoryEvent_AllocationScope,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_AllocationScope kAllocationScope{};
+ void set_allocation_scope(VulkanMemoryEvent_AllocationScope value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllocationScope::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Annotations =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ VulkanMemoryEventAnnotation,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_Annotations kAnnotations{};
+ template <typename T = VulkanMemoryEventAnnotation> T* add_annotations() {
+ return BeginNestedMessage<T>(9);
+ }
+
+
+ using FieldMetadata_Device =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_Device kDevice{};
+ void set_device(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Device::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeviceMemory =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_DeviceMemory kDeviceMemory{};
+ void set_device_memory(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeviceMemory::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MemoryType =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_MemoryType kMemoryType{};
+ void set_memory_type(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MemoryType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Heap =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_Heap kHeap{};
+ void set_heap(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Heap::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ObjectHandle =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ VulkanMemoryEvent>;
+
+ static constexpr FieldMetadata_ObjectHandle kObjectHandle{};
+ void set_object_handle(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObjectHandle::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class VulkanMemoryEventAnnotation_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ VulkanMemoryEventAnnotation_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit VulkanMemoryEventAnnotation_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit VulkanMemoryEventAnnotation_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key_iid() const { return at<1>().valid(); }
+ uint64_t key_iid() const { return at<1>().as_uint64(); }
+ bool has_int_value() const { return at<2>().valid(); }
+ int64_t int_value() const { return at<2>().as_int64(); }
+ bool has_double_value() const { return at<3>().valid(); }
+ double double_value() const { return at<3>().as_double(); }
+ bool has_string_iid() const { return at<4>().valid(); }
+ uint64_t string_iid() const { return at<4>().as_uint64(); }
+};
+
+class VulkanMemoryEventAnnotation : public ::protozero::Message {
+ public:
+ using Decoder = VulkanMemoryEventAnnotation_Decoder;
+ enum : int32_t {
+ kKeyIidFieldNumber = 1,
+ kIntValueFieldNumber = 2,
+ kDoubleValueFieldNumber = 3,
+ kStringIidFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.VulkanMemoryEventAnnotation"; }
+
+
+ using FieldMetadata_KeyIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanMemoryEventAnnotation>;
+
+ static constexpr FieldMetadata_KeyIid kKeyIid{};
+ void set_key_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KeyIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ VulkanMemoryEventAnnotation>;
+
+ static constexpr FieldMetadata_IntValue kIntValue{};
+ void set_int_value(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DoubleValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kDouble,
+ double,
+ VulkanMemoryEventAnnotation>;
+
+ static constexpr FieldMetadata_DoubleValue kDoubleValue{};
+ void set_double_value(double value) {
+ static constexpr uint32_t field_id = FieldMetadata_DoubleValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kDouble>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ VulkanMemoryEventAnnotation>;
+
+ static constexpr FieldMetadata_StringIid kStringIid{};
+ void set_string_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/profiling/deobfuscation.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_DEOBFUSCATION_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_DEOBFUSCATION_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ObfuscatedClass;
+class ObfuscatedMember;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class DeobfuscationMapping_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ DeobfuscationMapping_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit DeobfuscationMapping_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit DeobfuscationMapping_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_package_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars package_name() const { return at<1>().as_string(); }
+ bool has_version_code() const { return at<2>().valid(); }
+ int64_t version_code() const { return at<2>().as_int64(); }
+ bool has_obfuscated_classes() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> obfuscated_classes() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class DeobfuscationMapping : public ::protozero::Message {
+ public:
+ using Decoder = DeobfuscationMapping_Decoder;
+ enum : int32_t {
+ kPackageNameFieldNumber = 1,
+ kVersionCodeFieldNumber = 2,
+ kObfuscatedClassesFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.DeobfuscationMapping"; }
+
+
+ using FieldMetadata_PackageName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ DeobfuscationMapping>;
+
+ static constexpr FieldMetadata_PackageName kPackageName{};
+ void set_package_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_PackageName::kFieldId, data, size);
+ }
+ void set_package_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_PackageName::kFieldId, chars.data, chars.size);
+ }
+ void set_package_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_PackageName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VersionCode =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ DeobfuscationMapping>;
+
+ static constexpr FieldMetadata_VersionCode kVersionCode{};
+ void set_version_code(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VersionCode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ObfuscatedClasses =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ObfuscatedClass,
+ DeobfuscationMapping>;
+
+ static constexpr FieldMetadata_ObfuscatedClasses kObfuscatedClasses{};
+ template <typename T = ObfuscatedClass> T* add_obfuscated_classes() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class ObfuscatedClass_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ObfuscatedClass_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ObfuscatedClass_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ObfuscatedClass_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_obfuscated_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars obfuscated_name() const { return at<1>().as_string(); }
+ bool has_deobfuscated_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars deobfuscated_name() const { return at<2>().as_string(); }
+ bool has_obfuscated_members() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> obfuscated_members() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_obfuscated_methods() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> obfuscated_methods() const { return GetRepeated<::protozero::ConstBytes>(4); }
+};
+
+class ObfuscatedClass : public ::protozero::Message {
+ public:
+ using Decoder = ObfuscatedClass_Decoder;
+ enum : int32_t {
+ kObfuscatedNameFieldNumber = 1,
+ kDeobfuscatedNameFieldNumber = 2,
+ kObfuscatedMembersFieldNumber = 3,
+ kObfuscatedMethodsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ObfuscatedClass"; }
+
+
+ using FieldMetadata_ObfuscatedName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ObfuscatedClass>;
+
+ static constexpr FieldMetadata_ObfuscatedName kObfuscatedName{};
+ void set_obfuscated_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ObfuscatedName::kFieldId, data, size);
+ }
+ void set_obfuscated_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ObfuscatedName::kFieldId, chars.data, chars.size);
+ }
+ void set_obfuscated_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObfuscatedName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeobfuscatedName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ObfuscatedClass>;
+
+ static constexpr FieldMetadata_DeobfuscatedName kDeobfuscatedName{};
+ void set_deobfuscated_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DeobfuscatedName::kFieldId, data, size);
+ }
+ void set_deobfuscated_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DeobfuscatedName::kFieldId, chars.data, chars.size);
+ }
+ void set_deobfuscated_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeobfuscatedName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ObfuscatedMembers =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ObfuscatedMember,
+ ObfuscatedClass>;
+
+ static constexpr FieldMetadata_ObfuscatedMembers kObfuscatedMembers{};
+ template <typename T = ObfuscatedMember> T* add_obfuscated_members() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_ObfuscatedMethods =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ObfuscatedMember,
+ ObfuscatedClass>;
+
+ static constexpr FieldMetadata_ObfuscatedMethods kObfuscatedMethods{};
+ template <typename T = ObfuscatedMember> T* add_obfuscated_methods() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+class ObfuscatedMember_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ObfuscatedMember_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ObfuscatedMember_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ObfuscatedMember_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_obfuscated_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars obfuscated_name() const { return at<1>().as_string(); }
+ bool has_deobfuscated_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars deobfuscated_name() const { return at<2>().as_string(); }
+};
+
+class ObfuscatedMember : public ::protozero::Message {
+ public:
+ using Decoder = ObfuscatedMember_Decoder;
+ enum : int32_t {
+ kObfuscatedNameFieldNumber = 1,
+ kDeobfuscatedNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ObfuscatedMember"; }
+
+
+ using FieldMetadata_ObfuscatedName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ObfuscatedMember>;
+
+ static constexpr FieldMetadata_ObfuscatedName kObfuscatedName{};
+ void set_obfuscated_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ObfuscatedName::kFieldId, data, size);
+ }
+ void set_obfuscated_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ObfuscatedName::kFieldId, chars.data, chars.size);
+ }
+ void set_obfuscated_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObfuscatedName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeobfuscatedName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ObfuscatedMember>;
+
+ static constexpr FieldMetadata_DeobfuscatedName kDeobfuscatedName{};
+ void set_deobfuscated_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DeobfuscatedName::kFieldId, data, size);
+ }
+ void set_deobfuscated_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DeobfuscatedName::kFieldId, chars.data, chars.size);
+ }
+ void set_deobfuscated_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeobfuscatedName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/profiling/heap_graph.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_HEAP_GRAPH_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_HEAP_GRAPH_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class HeapGraphObject;
+class HeapGraphRoot;
+class HeapGraphType;
+class InternedString;
+namespace perfetto_pbzero_enum_HeapGraphRoot {
+enum Type : int32_t;
+} // namespace perfetto_pbzero_enum_HeapGraphRoot
+using HeapGraphRoot_Type = perfetto_pbzero_enum_HeapGraphRoot::Type;
+namespace perfetto_pbzero_enum_HeapGraphType {
+enum Kind : int32_t;
+} // namespace perfetto_pbzero_enum_HeapGraphType
+using HeapGraphType_Kind = perfetto_pbzero_enum_HeapGraphType::Kind;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_HeapGraphType {
+enum Kind : int32_t {
+ KIND_UNKNOWN = 0,
+ KIND_NORMAL = 1,
+ KIND_NOREFERENCES = 2,
+ KIND_STRING = 3,
+ KIND_ARRAY = 4,
+ KIND_CLASS = 5,
+ KIND_CLASSLOADER = 6,
+ KIND_DEXCACHE = 7,
+ KIND_SOFT_REFERENCE = 8,
+ KIND_WEAK_REFERENCE = 9,
+ KIND_FINALIZER_REFERENCE = 10,
+ KIND_PHANTOM_REFERENCE = 11,
+};
+} // namespace perfetto_pbzero_enum_HeapGraphType
+using HeapGraphType_Kind = perfetto_pbzero_enum_HeapGraphType::Kind;
+
+
+constexpr HeapGraphType_Kind HeapGraphType_Kind_MIN = HeapGraphType_Kind::KIND_UNKNOWN;
+constexpr HeapGraphType_Kind HeapGraphType_Kind_MAX = HeapGraphType_Kind::KIND_PHANTOM_REFERENCE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* HeapGraphType_Kind_Name(::perfetto::protos::pbzero::HeapGraphType_Kind value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_UNKNOWN:
+ return "KIND_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_NORMAL:
+ return "KIND_NORMAL";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_NOREFERENCES:
+ return "KIND_NOREFERENCES";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_STRING:
+ return "KIND_STRING";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_ARRAY:
+ return "KIND_ARRAY";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_CLASS:
+ return "KIND_CLASS";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_CLASSLOADER:
+ return "KIND_CLASSLOADER";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_DEXCACHE:
+ return "KIND_DEXCACHE";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_SOFT_REFERENCE:
+ return "KIND_SOFT_REFERENCE";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_WEAK_REFERENCE:
+ return "KIND_WEAK_REFERENCE";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_FINALIZER_REFERENCE:
+ return "KIND_FINALIZER_REFERENCE";
+
+ case ::perfetto::protos::pbzero::HeapGraphType_Kind::KIND_PHANTOM_REFERENCE:
+ return "KIND_PHANTOM_REFERENCE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_HeapGraphRoot {
+enum Type : int32_t {
+ ROOT_UNKNOWN = 0,
+ ROOT_JNI_GLOBAL = 1,
+ ROOT_JNI_LOCAL = 2,
+ ROOT_JAVA_FRAME = 3,
+ ROOT_NATIVE_STACK = 4,
+ ROOT_STICKY_CLASS = 5,
+ ROOT_THREAD_BLOCK = 6,
+ ROOT_MONITOR_USED = 7,
+ ROOT_THREAD_OBJECT = 8,
+ ROOT_INTERNED_STRING = 9,
+ ROOT_FINALIZING = 10,
+ ROOT_DEBUGGER = 11,
+ ROOT_REFERENCE_CLEANUP = 12,
+ ROOT_VM_INTERNAL = 13,
+ ROOT_JNI_MONITOR = 14,
+};
+} // namespace perfetto_pbzero_enum_HeapGraphRoot
+using HeapGraphRoot_Type = perfetto_pbzero_enum_HeapGraphRoot::Type;
+
+
+constexpr HeapGraphRoot_Type HeapGraphRoot_Type_MIN = HeapGraphRoot_Type::ROOT_UNKNOWN;
+constexpr HeapGraphRoot_Type HeapGraphRoot_Type_MAX = HeapGraphRoot_Type::ROOT_JNI_MONITOR;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* HeapGraphRoot_Type_Name(::perfetto::protos::pbzero::HeapGraphRoot_Type value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_UNKNOWN:
+ return "ROOT_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_JNI_GLOBAL:
+ return "ROOT_JNI_GLOBAL";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_JNI_LOCAL:
+ return "ROOT_JNI_LOCAL";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_JAVA_FRAME:
+ return "ROOT_JAVA_FRAME";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_NATIVE_STACK:
+ return "ROOT_NATIVE_STACK";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_STICKY_CLASS:
+ return "ROOT_STICKY_CLASS";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_THREAD_BLOCK:
+ return "ROOT_THREAD_BLOCK";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_MONITOR_USED:
+ return "ROOT_MONITOR_USED";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_THREAD_OBJECT:
+ return "ROOT_THREAD_OBJECT";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_INTERNED_STRING:
+ return "ROOT_INTERNED_STRING";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_FINALIZING:
+ return "ROOT_FINALIZING";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_DEBUGGER:
+ return "ROOT_DEBUGGER";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_REFERENCE_CLEANUP:
+ return "ROOT_REFERENCE_CLEANUP";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_VM_INTERNAL:
+ return "ROOT_VM_INTERNAL";
+
+ case ::perfetto::protos::pbzero::HeapGraphRoot_Type::ROOT_JNI_MONITOR:
+ return "ROOT_JNI_MONITOR";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class HeapGraph_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ HeapGraph_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HeapGraph_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HeapGraph_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_objects() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> objects() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_roots() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> roots() const { return GetRepeated<::protozero::ConstBytes>(7); }
+ bool has_types() const { return at<9>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> types() const { return GetRepeated<::protozero::ConstBytes>(9); }
+ bool has_field_names() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> field_names() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_location_names() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> location_names() const { return GetRepeated<::protozero::ConstBytes>(8); }
+ bool has_continued() const { return at<5>().valid(); }
+ bool continued() const { return at<5>().as_bool(); }
+ bool has_index() const { return at<6>().valid(); }
+ uint64_t index() const { return at<6>().as_uint64(); }
+};
+
+class HeapGraph : public ::protozero::Message {
+ public:
+ using Decoder = HeapGraph_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kObjectsFieldNumber = 2,
+ kRootsFieldNumber = 7,
+ kTypesFieldNumber = 9,
+ kFieldNamesFieldNumber = 4,
+ kLocationNamesFieldNumber = 8,
+ kContinuedFieldNumber = 5,
+ kIndexFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HeapGraph"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Objects =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HeapGraphObject,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_Objects kObjects{};
+ template <typename T = HeapGraphObject> T* add_objects() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_Roots =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HeapGraphRoot,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_Roots kRoots{};
+ template <typename T = HeapGraphRoot> T* add_roots() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_Types =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ HeapGraphType,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_Types kTypes{};
+ template <typename T = HeapGraphType> T* add_types() {
+ return BeginNestedMessage<T>(9);
+ }
+
+
+ using FieldMetadata_FieldNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_FieldNames kFieldNames{};
+ template <typename T = InternedString> T* add_field_names() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_LocationNames =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_LocationNames kLocationNames{};
+ template <typename T = InternedString> T* add_location_names() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_Continued =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_Continued kContinued{};
+ void set_continued(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Continued::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraph>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HeapGraphObject_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HeapGraphObject_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HeapGraphObject_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HeapGraphObject_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+ bool has_id_delta() const { return at<7>().valid(); }
+ uint64_t id_delta() const { return at<7>().as_uint64(); }
+ bool has_type_id() const { return at<2>().valid(); }
+ uint64_t type_id() const { return at<2>().as_uint64(); }
+ bool has_self_size() const { return at<3>().valid(); }
+ uint64_t self_size() const { return at<3>().as_uint64(); }
+ bool has_reference_field_id_base() const { return at<6>().valid(); }
+ uint64_t reference_field_id_base() const { return at<6>().as_uint64(); }
+ bool has_reference_field_id() const { return at<4>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> reference_field_id(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(4, parse_error_ptr); }
+ bool has_reference_object_id() const { return at<5>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> reference_object_id(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(5, parse_error_ptr); }
+ bool has_native_allocation_registry_size_field() const { return at<8>().valid(); }
+ int64_t native_allocation_registry_size_field() const { return at<8>().as_int64(); }
+};
+
+class HeapGraphObject : public ::protozero::Message {
+ public:
+ using Decoder = HeapGraphObject_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kIdDeltaFieldNumber = 7,
+ kTypeIdFieldNumber = 2,
+ kSelfSizeFieldNumber = 3,
+ kReferenceFieldIdBaseFieldNumber = 6,
+ kReferenceFieldIdFieldNumber = 4,
+ kReferenceObjectIdFieldNumber = 5,
+ kNativeAllocationRegistrySizeFieldFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HeapGraphObject"; }
+
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IdDelta =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_IdDelta kIdDelta{};
+ void set_id_delta(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IdDelta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TypeId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_TypeId kTypeId{};
+ void set_type_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TypeId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SelfSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_SelfSize kSelfSize{};
+ void set_self_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SelfSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReferenceFieldIdBase =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_ReferenceFieldIdBase kReferenceFieldIdBase{};
+ void set_reference_field_id_base(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReferenceFieldIdBase::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReferenceFieldId =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_ReferenceFieldId kReferenceFieldId{};
+ void set_reference_field_id(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_ReferenceFieldId::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_ReferenceObjectId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_ReferenceObjectId kReferenceObjectId{};
+ void set_reference_object_id(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_ReferenceObjectId::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_NativeAllocationRegistrySizeField =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ HeapGraphObject>;
+
+ static constexpr FieldMetadata_NativeAllocationRegistrySizeField kNativeAllocationRegistrySizeField{};
+ void set_native_allocation_registry_size_field(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NativeAllocationRegistrySizeField::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HeapGraphType_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HeapGraphType_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HeapGraphType_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HeapGraphType_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+ bool has_location_id() const { return at<2>().valid(); }
+ uint64_t location_id() const { return at<2>().as_uint64(); }
+ bool has_class_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars class_name() const { return at<3>().as_string(); }
+ bool has_object_size() const { return at<4>().valid(); }
+ uint64_t object_size() const { return at<4>().as_uint64(); }
+ bool has_superclass_id() const { return at<5>().valid(); }
+ uint64_t superclass_id() const { return at<5>().as_uint64(); }
+ bool has_reference_field_id() const { return at<6>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> reference_field_id(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(6, parse_error_ptr); }
+ bool has_kind() const { return at<7>().valid(); }
+ int32_t kind() const { return at<7>().as_int32(); }
+ bool has_classloader_id() const { return at<8>().valid(); }
+ uint64_t classloader_id() const { return at<8>().as_uint64(); }
+};
+
+class HeapGraphType : public ::protozero::Message {
+ public:
+ using Decoder = HeapGraphType_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kLocationIdFieldNumber = 2,
+ kClassNameFieldNumber = 3,
+ kObjectSizeFieldNumber = 4,
+ kSuperclassIdFieldNumber = 5,
+ kReferenceFieldIdFieldNumber = 6,
+ kKindFieldNumber = 7,
+ kClassloaderIdFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HeapGraphType"; }
+
+
+ using Kind = ::perfetto::protos::pbzero::HeapGraphType_Kind;
+ static inline const char* Kind_Name(Kind value) {
+ return ::perfetto::protos::pbzero::HeapGraphType_Kind_Name(value);
+ }
+ static inline const Kind KIND_UNKNOWN = Kind::KIND_UNKNOWN;
+ static inline const Kind KIND_NORMAL = Kind::KIND_NORMAL;
+ static inline const Kind KIND_NOREFERENCES = Kind::KIND_NOREFERENCES;
+ static inline const Kind KIND_STRING = Kind::KIND_STRING;
+ static inline const Kind KIND_ARRAY = Kind::KIND_ARRAY;
+ static inline const Kind KIND_CLASS = Kind::KIND_CLASS;
+ static inline const Kind KIND_CLASSLOADER = Kind::KIND_CLASSLOADER;
+ static inline const Kind KIND_DEXCACHE = Kind::KIND_DEXCACHE;
+ static inline const Kind KIND_SOFT_REFERENCE = Kind::KIND_SOFT_REFERENCE;
+ static inline const Kind KIND_WEAK_REFERENCE = Kind::KIND_WEAK_REFERENCE;
+ static inline const Kind KIND_FINALIZER_REFERENCE = Kind::KIND_FINALIZER_REFERENCE;
+ static inline const Kind KIND_PHANTOM_REFERENCE = Kind::KIND_PHANTOM_REFERENCE;
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LocationId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_LocationId kLocationId{};
+ void set_location_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LocationId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClassName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_ClassName kClassName{};
+ void set_class_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ClassName::kFieldId, data, size);
+ }
+ void set_class_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ClassName::kFieldId, chars.data, chars.size);
+ }
+ void set_class_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClassName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ObjectSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_ObjectSize kObjectSize{};
+ void set_object_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObjectSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SuperclassId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_SuperclassId kSuperclassId{};
+ void set_superclass_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SuperclassId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReferenceFieldId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_ReferenceFieldId kReferenceFieldId{};
+ void set_reference_field_id(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_ReferenceFieldId::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_Kind =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ HeapGraphType_Kind,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_Kind kKind{};
+ void set_kind(HeapGraphType_Kind value) {
+ static constexpr uint32_t field_id = FieldMetadata_Kind::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClassloaderId =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphType>;
+
+ static constexpr FieldMetadata_ClassloaderId kClassloaderId{};
+ void set_classloader_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClassloaderId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HeapGraphRoot_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HeapGraphRoot_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HeapGraphRoot_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HeapGraphRoot_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_object_ids() const { return at<1>().valid(); }
+ ::protozero::PackedRepeatedFieldIterator<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t> object_ids(bool* parse_error_ptr) const { return GetPackedRepeated<::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(1, parse_error_ptr); }
+ bool has_root_type() const { return at<2>().valid(); }
+ int32_t root_type() const { return at<2>().as_int32(); }
+};
+
+class HeapGraphRoot : public ::protozero::Message {
+ public:
+ using Decoder = HeapGraphRoot_Decoder;
+ enum : int32_t {
+ kObjectIdsFieldNumber = 1,
+ kRootTypeFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HeapGraphRoot"; }
+
+
+ using Type = ::perfetto::protos::pbzero::HeapGraphRoot_Type;
+ static inline const char* Type_Name(Type value) {
+ return ::perfetto::protos::pbzero::HeapGraphRoot_Type_Name(value);
+ }
+ static inline const Type ROOT_UNKNOWN = Type::ROOT_UNKNOWN;
+ static inline const Type ROOT_JNI_GLOBAL = Type::ROOT_JNI_GLOBAL;
+ static inline const Type ROOT_JNI_LOCAL = Type::ROOT_JNI_LOCAL;
+ static inline const Type ROOT_JAVA_FRAME = Type::ROOT_JAVA_FRAME;
+ static inline const Type ROOT_NATIVE_STACK = Type::ROOT_NATIVE_STACK;
+ static inline const Type ROOT_STICKY_CLASS = Type::ROOT_STICKY_CLASS;
+ static inline const Type ROOT_THREAD_BLOCK = Type::ROOT_THREAD_BLOCK;
+ static inline const Type ROOT_MONITOR_USED = Type::ROOT_MONITOR_USED;
+ static inline const Type ROOT_THREAD_OBJECT = Type::ROOT_THREAD_OBJECT;
+ static inline const Type ROOT_INTERNED_STRING = Type::ROOT_INTERNED_STRING;
+ static inline const Type ROOT_FINALIZING = Type::ROOT_FINALIZING;
+ static inline const Type ROOT_DEBUGGER = Type::ROOT_DEBUGGER;
+ static inline const Type ROOT_REFERENCE_CLEANUP = Type::ROOT_REFERENCE_CLEANUP;
+ static inline const Type ROOT_VM_INTERNAL = Type::ROOT_VM_INTERNAL;
+ static inline const Type ROOT_JNI_MONITOR = Type::ROOT_JNI_MONITOR;
+
+ using FieldMetadata_ObjectIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HeapGraphRoot>;
+
+ static constexpr FieldMetadata_ObjectIds kObjectIds{};
+ void set_object_ids(const ::protozero::PackedVarInt& packed_buffer) {
+ AppendBytes(FieldMetadata_ObjectIds::kFieldId, packed_buffer.data(),
+ packed_buffer.size());
+ }
+
+ using FieldMetadata_RootType =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ HeapGraphRoot_Type,
+ HeapGraphRoot>;
+
+ static constexpr FieldMetadata_RootType kRootType{};
+ void set_root_type(HeapGraphRoot_Type value) {
+ static constexpr uint32_t field_id = FieldMetadata_RootType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/profiling/profile_common.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_PROFILE_COMMON_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_PROFILE_COMMON_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AddressSymbols;
+class Line;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class Callstack_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ Callstack_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Callstack_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Callstack_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_frame_ids() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> frame_ids() const { return GetRepeated<uint64_t>(2); }
+};
+
+class Callstack : public ::protozero::Message {
+ public:
+ using Decoder = Callstack_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kFrameIdsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Callstack"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Callstack>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Callstack>;
+
+ static constexpr FieldMetadata_FrameIds kFrameIds{};
+ void add_frame_ids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Frame_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Frame_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Frame_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Frame_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_function_name_id() const { return at<2>().valid(); }
+ uint64_t function_name_id() const { return at<2>().as_uint64(); }
+ bool has_mapping_id() const { return at<3>().valid(); }
+ uint64_t mapping_id() const { return at<3>().as_uint64(); }
+ bool has_rel_pc() const { return at<4>().valid(); }
+ uint64_t rel_pc() const { return at<4>().as_uint64(); }
+};
+
+class Frame : public ::protozero::Message {
+ public:
+ using Decoder = Frame_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kFunctionNameIdFieldNumber = 2,
+ kMappingIdFieldNumber = 3,
+ kRelPcFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Frame"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Frame>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FunctionNameId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Frame>;
+
+ static constexpr FieldMetadata_FunctionNameId kFunctionNameId{};
+ void set_function_name_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FunctionNameId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MappingId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Frame>;
+
+ static constexpr FieldMetadata_MappingId kMappingId{};
+ void set_mapping_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MappingId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RelPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Frame>;
+
+ static constexpr FieldMetadata_RelPc kRelPc{};
+ void set_rel_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RelPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Mapping_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ Mapping_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Mapping_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Mapping_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_build_id() const { return at<2>().valid(); }
+ uint64_t build_id() const { return at<2>().as_uint64(); }
+ bool has_exact_offset() const { return at<8>().valid(); }
+ uint64_t exact_offset() const { return at<8>().as_uint64(); }
+ bool has_start_offset() const { return at<3>().valid(); }
+ uint64_t start_offset() const { return at<3>().as_uint64(); }
+ bool has_start() const { return at<4>().valid(); }
+ uint64_t start() const { return at<4>().as_uint64(); }
+ bool has_end() const { return at<5>().valid(); }
+ uint64_t end() const { return at<5>().as_uint64(); }
+ bool has_load_bias() const { return at<6>().valid(); }
+ uint64_t load_bias() const { return at<6>().as_uint64(); }
+ bool has_path_string_ids() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> path_string_ids() const { return GetRepeated<uint64_t>(7); }
+};
+
+class Mapping : public ::protozero::Message {
+ public:
+ using Decoder = Mapping_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kBuildIdFieldNumber = 2,
+ kExactOffsetFieldNumber = 8,
+ kStartOffsetFieldNumber = 3,
+ kStartFieldNumber = 4,
+ kEndFieldNumber = 5,
+ kLoadBiasFieldNumber = 6,
+ kPathStringIdsFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Mapping"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BuildId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_BuildId kBuildId{};
+ void set_build_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BuildId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ExactOffset =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_ExactOffset kExactOffset{};
+ void set_exact_offset(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ExactOffset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartOffset =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_StartOffset kStartOffset{};
+ void set_start_offset(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartOffset::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Start =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_Start kStart{};
+ void set_start(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Start::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_End =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_End kEnd{};
+ void set_end(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_End::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LoadBias =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_LoadBias kLoadBias{};
+ void set_load_bias(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LoadBias::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PathStringIds =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ Mapping>;
+
+ static constexpr FieldMetadata_PathStringIds kPathStringIds{};
+ void add_path_string_ids(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PathStringIds::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ModuleSymbols_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ModuleSymbols_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ModuleSymbols_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ModuleSymbols_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_path() const { return at<1>().valid(); }
+ ::protozero::ConstChars path() const { return at<1>().as_string(); }
+ bool has_build_id() const { return at<2>().valid(); }
+ ::protozero::ConstChars build_id() const { return at<2>().as_string(); }
+ bool has_address_symbols() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> address_symbols() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class ModuleSymbols : public ::protozero::Message {
+ public:
+ using Decoder = ModuleSymbols_Decoder;
+ enum : int32_t {
+ kPathFieldNumber = 1,
+ kBuildIdFieldNumber = 2,
+ kAddressSymbolsFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ModuleSymbols"; }
+
+
+ using FieldMetadata_Path =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ModuleSymbols>;
+
+ static constexpr FieldMetadata_Path kPath{};
+ void set_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Path::kFieldId, data, size);
+ }
+ void set_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Path::kFieldId, chars.data, chars.size);
+ }
+ void set_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Path::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BuildId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ModuleSymbols>;
+
+ static constexpr FieldMetadata_BuildId kBuildId{};
+ void set_build_id(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_BuildId::kFieldId, data, size);
+ }
+ void set_build_id(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_BuildId::kFieldId, chars.data, chars.size);
+ }
+ void set_build_id(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_BuildId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AddressSymbols =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AddressSymbols,
+ ModuleSymbols>;
+
+ static constexpr FieldMetadata_AddressSymbols kAddressSymbols{};
+ template <typename T = AddressSymbols> T* add_address_symbols() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class AddressSymbols_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AddressSymbols_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AddressSymbols_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AddressSymbols_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_address() const { return at<1>().valid(); }
+ uint64_t address() const { return at<1>().as_uint64(); }
+ bool has_lines() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> lines() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class AddressSymbols : public ::protozero::Message {
+ public:
+ using Decoder = AddressSymbols_Decoder;
+ enum : int32_t {
+ kAddressFieldNumber = 1,
+ kLinesFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AddressSymbols"; }
+
+
+ using FieldMetadata_Address =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ AddressSymbols>;
+
+ static constexpr FieldMetadata_Address kAddress{};
+ void set_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Address::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Lines =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Line,
+ AddressSymbols>;
+
+ static constexpr FieldMetadata_Lines kLines{};
+ template <typename T = Line> T* add_lines() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class Line_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Line_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Line_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Line_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_function_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars function_name() const { return at<1>().as_string(); }
+ bool has_source_file_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars source_file_name() const { return at<2>().as_string(); }
+ bool has_line_number() const { return at<3>().valid(); }
+ uint32_t line_number() const { return at<3>().as_uint32(); }
+};
+
+class Line : public ::protozero::Message {
+ public:
+ using Decoder = Line_Decoder;
+ enum : int32_t {
+ kFunctionNameFieldNumber = 1,
+ kSourceFileNameFieldNumber = 2,
+ kLineNumberFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Line"; }
+
+
+ using FieldMetadata_FunctionName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Line>;
+
+ static constexpr FieldMetadata_FunctionName kFunctionName{};
+ void set_function_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FunctionName::kFieldId, data, size);
+ }
+ void set_function_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FunctionName::kFieldId, chars.data, chars.size);
+ }
+ void set_function_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FunctionName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SourceFileName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ Line>;
+
+ static constexpr FieldMetadata_SourceFileName kSourceFileName{};
+ void set_source_file_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SourceFileName::kFieldId, data, size);
+ }
+ void set_source_file_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SourceFileName::kFieldId, chars.data, chars.size);
+ }
+ void set_source_file_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceFileName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LineNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ Line>;
+
+ static constexpr FieldMetadata_LineNumber kLineNumber{};
+ void set_line_number(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LineNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProfiledFrameSymbols_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProfiledFrameSymbols_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProfiledFrameSymbols_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProfiledFrameSymbols_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_frame_iid() const { return at<1>().valid(); }
+ uint64_t frame_iid() const { return at<1>().as_uint64(); }
+ bool has_function_name_id() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> function_name_id() const { return GetRepeated<uint64_t>(2); }
+ bool has_file_name_id() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> file_name_id() const { return GetRepeated<uint64_t>(3); }
+ bool has_line_number() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> line_number() const { return GetRepeated<uint32_t>(4); }
+};
+
+class ProfiledFrameSymbols : public ::protozero::Message {
+ public:
+ using Decoder = ProfiledFrameSymbols_Decoder;
+ enum : int32_t {
+ kFrameIidFieldNumber = 1,
+ kFunctionNameIdFieldNumber = 2,
+ kFileNameIdFieldNumber = 3,
+ kLineNumberFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProfiledFrameSymbols"; }
+
+
+ using FieldMetadata_FrameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfiledFrameSymbols>;
+
+ static constexpr FieldMetadata_FrameIid kFrameIid{};
+ void set_frame_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FunctionNameId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfiledFrameSymbols>;
+
+ static constexpr FieldMetadata_FunctionNameId kFunctionNameId{};
+ void add_function_name_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FunctionNameId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FileNameId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfiledFrameSymbols>;
+
+ static constexpr FieldMetadata_FileNameId kFileNameId{};
+ void add_file_name_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FileNameId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LineNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProfiledFrameSymbols>;
+
+ static constexpr FieldMetadata_LineNumber kLineNumber{};
+ void add_line_number(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LineNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class InternedString_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ InternedString_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit InternedString_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit InternedString_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_str() const { return at<2>().valid(); }
+ ::protozero::ConstBytes str() const { return at<2>().as_bytes(); }
+};
+
+class InternedString : public ::protozero::Message {
+ public:
+ using Decoder = InternedString_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kStrFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.InternedString"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ InternedString>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Str =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ InternedString>;
+
+ static constexpr FieldMetadata_Str kStr{};
+ void set_str(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_Str::kFieldId, data, size);
+ }
+ void set_str(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_Str::kFieldId, bytes.data, bytes.size);
+ }
+ void set_str(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Str::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/profiling/profile_packet.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_PROFILE_PACKET_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_PROFILE_PACKET_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class Callstack;
+class Frame;
+class InternedString;
+class Mapping;
+class PerfEvents_Timebase;
+class PerfSample_ProducerEvent;
+class ProfilePacket_HeapSample;
+class ProfilePacket_Histogram;
+class ProfilePacket_Histogram_Bucket;
+class ProfilePacket_ProcessHeapSamples;
+class ProfilePacket_ProcessStats;
+namespace perfetto_pbzero_enum_PerfSample_ProducerEvent {
+enum DataSourceStopReason : int32_t;
+} // namespace perfetto_pbzero_enum_PerfSample_ProducerEvent
+using PerfSample_ProducerEvent_DataSourceStopReason = perfetto_pbzero_enum_PerfSample_ProducerEvent::DataSourceStopReason;
+namespace perfetto_pbzero_enum_PerfSample {
+enum SampleSkipReason : int32_t;
+} // namespace perfetto_pbzero_enum_PerfSample
+using PerfSample_SampleSkipReason = perfetto_pbzero_enum_PerfSample::SampleSkipReason;
+namespace perfetto_pbzero_enum_ProfilePacket_ProcessHeapSamples {
+enum ClientError : int32_t;
+} // namespace perfetto_pbzero_enum_ProfilePacket_ProcessHeapSamples
+using ProfilePacket_ProcessHeapSamples_ClientError = perfetto_pbzero_enum_ProfilePacket_ProcessHeapSamples::ClientError;
+namespace perfetto_pbzero_enum_Profiling {
+enum CpuMode : int32_t;
+} // namespace perfetto_pbzero_enum_Profiling
+using Profiling_CpuMode = perfetto_pbzero_enum_Profiling::CpuMode;
+namespace perfetto_pbzero_enum_Profiling {
+enum StackUnwindError : int32_t;
+} // namespace perfetto_pbzero_enum_Profiling
+using Profiling_StackUnwindError = perfetto_pbzero_enum_Profiling::StackUnwindError;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_PerfSample {
+enum SampleSkipReason : int32_t {
+ PROFILER_SKIP_UNKNOWN = 0,
+ PROFILER_SKIP_READ_STAGE = 1,
+ PROFILER_SKIP_UNWIND_STAGE = 2,
+ PROFILER_SKIP_UNWIND_ENQUEUE = 3,
+};
+} // namespace perfetto_pbzero_enum_PerfSample
+using PerfSample_SampleSkipReason = perfetto_pbzero_enum_PerfSample::SampleSkipReason;
+
+
+constexpr PerfSample_SampleSkipReason PerfSample_SampleSkipReason_MIN = PerfSample_SampleSkipReason::PROFILER_SKIP_UNKNOWN;
+constexpr PerfSample_SampleSkipReason PerfSample_SampleSkipReason_MAX = PerfSample_SampleSkipReason::PROFILER_SKIP_UNWIND_ENQUEUE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* PerfSample_SampleSkipReason_Name(::perfetto::protos::pbzero::PerfSample_SampleSkipReason value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::PerfSample_SampleSkipReason::PROFILER_SKIP_UNKNOWN:
+ return "PROFILER_SKIP_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::PerfSample_SampleSkipReason::PROFILER_SKIP_READ_STAGE:
+ return "PROFILER_SKIP_READ_STAGE";
+
+ case ::perfetto::protos::pbzero::PerfSample_SampleSkipReason::PROFILER_SKIP_UNWIND_STAGE:
+ return "PROFILER_SKIP_UNWIND_STAGE";
+
+ case ::perfetto::protos::pbzero::PerfSample_SampleSkipReason::PROFILER_SKIP_UNWIND_ENQUEUE:
+ return "PROFILER_SKIP_UNWIND_ENQUEUE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_PerfSample_ProducerEvent {
+enum DataSourceStopReason : int32_t {
+ PROFILER_STOP_UNKNOWN = 0,
+ PROFILER_STOP_GUARDRAIL = 1,
+};
+} // namespace perfetto_pbzero_enum_PerfSample_ProducerEvent
+using PerfSample_ProducerEvent_DataSourceStopReason = perfetto_pbzero_enum_PerfSample_ProducerEvent::DataSourceStopReason;
+
+
+constexpr PerfSample_ProducerEvent_DataSourceStopReason PerfSample_ProducerEvent_DataSourceStopReason_MIN = PerfSample_ProducerEvent_DataSourceStopReason::PROFILER_STOP_UNKNOWN;
+constexpr PerfSample_ProducerEvent_DataSourceStopReason PerfSample_ProducerEvent_DataSourceStopReason_MAX = PerfSample_ProducerEvent_DataSourceStopReason::PROFILER_STOP_GUARDRAIL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* PerfSample_ProducerEvent_DataSourceStopReason_Name(::perfetto::protos::pbzero::PerfSample_ProducerEvent_DataSourceStopReason value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::PerfSample_ProducerEvent_DataSourceStopReason::PROFILER_STOP_UNKNOWN:
+ return "PROFILER_STOP_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::PerfSample_ProducerEvent_DataSourceStopReason::PROFILER_STOP_GUARDRAIL:
+ return "PROFILER_STOP_GUARDRAIL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_Profiling {
+enum CpuMode : int32_t {
+ MODE_UNKNOWN = 0,
+ MODE_KERNEL = 1,
+ MODE_USER = 2,
+ MODE_HYPERVISOR = 3,
+ MODE_GUEST_KERNEL = 4,
+ MODE_GUEST_USER = 5,
+};
+} // namespace perfetto_pbzero_enum_Profiling
+using Profiling_CpuMode = perfetto_pbzero_enum_Profiling::CpuMode;
+
+
+constexpr Profiling_CpuMode Profiling_CpuMode_MIN = Profiling_CpuMode::MODE_UNKNOWN;
+constexpr Profiling_CpuMode Profiling_CpuMode_MAX = Profiling_CpuMode::MODE_GUEST_USER;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* Profiling_CpuMode_Name(::perfetto::protos::pbzero::Profiling_CpuMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::Profiling_CpuMode::MODE_UNKNOWN:
+ return "MODE_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::Profiling_CpuMode::MODE_KERNEL:
+ return "MODE_KERNEL";
+
+ case ::perfetto::protos::pbzero::Profiling_CpuMode::MODE_USER:
+ return "MODE_USER";
+
+ case ::perfetto::protos::pbzero::Profiling_CpuMode::MODE_HYPERVISOR:
+ return "MODE_HYPERVISOR";
+
+ case ::perfetto::protos::pbzero::Profiling_CpuMode::MODE_GUEST_KERNEL:
+ return "MODE_GUEST_KERNEL";
+
+ case ::perfetto::protos::pbzero::Profiling_CpuMode::MODE_GUEST_USER:
+ return "MODE_GUEST_USER";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_Profiling {
+enum StackUnwindError : int32_t {
+ UNWIND_ERROR_UNKNOWN = 0,
+ UNWIND_ERROR_NONE = 1,
+ UNWIND_ERROR_MEMORY_INVALID = 2,
+ UNWIND_ERROR_UNWIND_INFO = 3,
+ UNWIND_ERROR_UNSUPPORTED = 4,
+ UNWIND_ERROR_INVALID_MAP = 5,
+ UNWIND_ERROR_MAX_FRAMES_EXCEEDED = 6,
+ UNWIND_ERROR_REPEATED_FRAME = 7,
+ UNWIND_ERROR_INVALID_ELF = 8,
+ UNWIND_ERROR_SYSTEM_CALL = 9,
+ UNWIND_ERROR_THREAD_TIMEOUT = 10,
+ UNWIND_ERROR_THREAD_DOES_NOT_EXIST = 11,
+ UNWIND_ERROR_BAD_ARCH = 12,
+ UNWIND_ERROR_MAPS_PARSE = 13,
+ UNWIND_ERROR_INVALID_PARAMETER = 14,
+ UNWIND_ERROR_PTRACE_CALL = 15,
+};
+} // namespace perfetto_pbzero_enum_Profiling
+using Profiling_StackUnwindError = perfetto_pbzero_enum_Profiling::StackUnwindError;
+
+
+constexpr Profiling_StackUnwindError Profiling_StackUnwindError_MIN = Profiling_StackUnwindError::UNWIND_ERROR_UNKNOWN;
+constexpr Profiling_StackUnwindError Profiling_StackUnwindError_MAX = Profiling_StackUnwindError::UNWIND_ERROR_PTRACE_CALL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* Profiling_StackUnwindError_Name(::perfetto::protos::pbzero::Profiling_StackUnwindError value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_UNKNOWN:
+ return "UNWIND_ERROR_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_NONE:
+ return "UNWIND_ERROR_NONE";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_MEMORY_INVALID:
+ return "UNWIND_ERROR_MEMORY_INVALID";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_UNWIND_INFO:
+ return "UNWIND_ERROR_UNWIND_INFO";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_UNSUPPORTED:
+ return "UNWIND_ERROR_UNSUPPORTED";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_INVALID_MAP:
+ return "UNWIND_ERROR_INVALID_MAP";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_MAX_FRAMES_EXCEEDED:
+ return "UNWIND_ERROR_MAX_FRAMES_EXCEEDED";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_REPEATED_FRAME:
+ return "UNWIND_ERROR_REPEATED_FRAME";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_INVALID_ELF:
+ return "UNWIND_ERROR_INVALID_ELF";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_SYSTEM_CALL:
+ return "UNWIND_ERROR_SYSTEM_CALL";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_THREAD_TIMEOUT:
+ return "UNWIND_ERROR_THREAD_TIMEOUT";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_THREAD_DOES_NOT_EXIST:
+ return "UNWIND_ERROR_THREAD_DOES_NOT_EXIST";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_BAD_ARCH:
+ return "UNWIND_ERROR_BAD_ARCH";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_MAPS_PARSE:
+ return "UNWIND_ERROR_MAPS_PARSE";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_INVALID_PARAMETER:
+ return "UNWIND_ERROR_INVALID_PARAMETER";
+
+ case ::perfetto::protos::pbzero::Profiling_StackUnwindError::UNWIND_ERROR_PTRACE_CALL:
+ return "UNWIND_ERROR_PTRACE_CALL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ProfilePacket_ProcessHeapSamples {
+enum ClientError : int32_t {
+ CLIENT_ERROR_NONE = 0,
+ CLIENT_ERROR_HIT_TIMEOUT = 1,
+ CLIENT_ERROR_INVALID_STACK_BOUNDS = 2,
+};
+} // namespace perfetto_pbzero_enum_ProfilePacket_ProcessHeapSamples
+using ProfilePacket_ProcessHeapSamples_ClientError = perfetto_pbzero_enum_ProfilePacket_ProcessHeapSamples::ClientError;
+
+
+constexpr ProfilePacket_ProcessHeapSamples_ClientError ProfilePacket_ProcessHeapSamples_ClientError_MIN = ProfilePacket_ProcessHeapSamples_ClientError::CLIENT_ERROR_NONE;
+constexpr ProfilePacket_ProcessHeapSamples_ClientError ProfilePacket_ProcessHeapSamples_ClientError_MAX = ProfilePacket_ProcessHeapSamples_ClientError::CLIENT_ERROR_INVALID_STACK_BOUNDS;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ProfilePacket_ProcessHeapSamples_ClientError_Name(::perfetto::protos::pbzero::ProfilePacket_ProcessHeapSamples_ClientError value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ProfilePacket_ProcessHeapSamples_ClientError::CLIENT_ERROR_NONE:
+ return "CLIENT_ERROR_NONE";
+
+ case ::perfetto::protos::pbzero::ProfilePacket_ProcessHeapSamples_ClientError::CLIENT_ERROR_HIT_TIMEOUT:
+ return "CLIENT_ERROR_HIT_TIMEOUT";
+
+ case ::perfetto::protos::pbzero::ProfilePacket_ProcessHeapSamples_ClientError::CLIENT_ERROR_INVALID_STACK_BOUNDS:
+ return "CLIENT_ERROR_INVALID_STACK_BOUNDS";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class PerfSampleDefaults_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfSampleDefaults_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfSampleDefaults_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfSampleDefaults_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timebase() const { return at<1>().valid(); }
+ ::protozero::ConstBytes timebase() const { return at<1>().as_bytes(); }
+ bool has_process_shard_count() const { return at<2>().valid(); }
+ uint32_t process_shard_count() const { return at<2>().as_uint32(); }
+ bool has_chosen_process_shard() const { return at<3>().valid(); }
+ uint32_t chosen_process_shard() const { return at<3>().as_uint32(); }
+};
+
+class PerfSampleDefaults : public ::protozero::Message {
+ public:
+ using Decoder = PerfSampleDefaults_Decoder;
+ enum : int32_t {
+ kTimebaseFieldNumber = 1,
+ kProcessShardCountFieldNumber = 2,
+ kChosenProcessShardFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfSampleDefaults"; }
+
+
+ using FieldMetadata_Timebase =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfEvents_Timebase,
+ PerfSampleDefaults>;
+
+ static constexpr FieldMetadata_Timebase kTimebase{};
+ template <typename T = PerfEvents_Timebase> T* set_timebase() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ProcessShardCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfSampleDefaults>;
+
+ static constexpr FieldMetadata_ProcessShardCount kProcessShardCount{};
+ void set_process_shard_count(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessShardCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChosenProcessShard =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfSampleDefaults>;
+
+ static constexpr FieldMetadata_ChosenProcessShard kChosenProcessShard{};
+ void set_chosen_process_shard(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChosenProcessShard::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PerfSample_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/19, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfSample_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfSample_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfSample_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu() const { return at<1>().valid(); }
+ uint32_t cpu() const { return at<1>().as_uint32(); }
+ bool has_pid() const { return at<2>().valid(); }
+ uint32_t pid() const { return at<2>().as_uint32(); }
+ bool has_tid() const { return at<3>().valid(); }
+ uint32_t tid() const { return at<3>().as_uint32(); }
+ bool has_cpu_mode() const { return at<5>().valid(); }
+ int32_t cpu_mode() const { return at<5>().as_int32(); }
+ bool has_timebase_count() const { return at<6>().valid(); }
+ uint64_t timebase_count() const { return at<6>().as_uint64(); }
+ bool has_callstack_iid() const { return at<4>().valid(); }
+ uint64_t callstack_iid() const { return at<4>().as_uint64(); }
+ bool has_unwind_error() const { return at<16>().valid(); }
+ int32_t unwind_error() const { return at<16>().as_int32(); }
+ bool has_kernel_records_lost() const { return at<17>().valid(); }
+ uint64_t kernel_records_lost() const { return at<17>().as_uint64(); }
+ bool has_sample_skipped_reason() const { return at<18>().valid(); }
+ int32_t sample_skipped_reason() const { return at<18>().as_int32(); }
+ bool has_producer_event() const { return at<19>().valid(); }
+ ::protozero::ConstBytes producer_event() const { return at<19>().as_bytes(); }
+};
+
+class PerfSample : public ::protozero::Message {
+ public:
+ using Decoder = PerfSample_Decoder;
+ enum : int32_t {
+ kCpuFieldNumber = 1,
+ kPidFieldNumber = 2,
+ kTidFieldNumber = 3,
+ kCpuModeFieldNumber = 5,
+ kTimebaseCountFieldNumber = 6,
+ kCallstackIidFieldNumber = 4,
+ kUnwindErrorFieldNumber = 16,
+ kKernelRecordsLostFieldNumber = 17,
+ kSampleSkippedReasonFieldNumber = 18,
+ kProducerEventFieldNumber = 19,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfSample"; }
+
+ using ProducerEvent = ::perfetto::protos::pbzero::PerfSample_ProducerEvent;
+
+ using SampleSkipReason = ::perfetto::protos::pbzero::PerfSample_SampleSkipReason;
+ static inline const char* SampleSkipReason_Name(SampleSkipReason value) {
+ return ::perfetto::protos::pbzero::PerfSample_SampleSkipReason_Name(value);
+ }
+ static inline const SampleSkipReason PROFILER_SKIP_UNKNOWN = SampleSkipReason::PROFILER_SKIP_UNKNOWN;
+ static inline const SampleSkipReason PROFILER_SKIP_READ_STAGE = SampleSkipReason::PROFILER_SKIP_READ_STAGE;
+ static inline const SampleSkipReason PROFILER_SKIP_UNWIND_STAGE = SampleSkipReason::PROFILER_SKIP_UNWIND_STAGE;
+ static inline const SampleSkipReason PROFILER_SKIP_UNWIND_ENQUEUE = SampleSkipReason::PROFILER_SKIP_UNWIND_ENQUEUE;
+
+ using FieldMetadata_Cpu =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfSample>;
+
+ static constexpr FieldMetadata_Cpu kCpu{};
+ void set_cpu(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cpu::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfSample>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfSample>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CpuMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ Profiling_CpuMode,
+ PerfSample>;
+
+ static constexpr FieldMetadata_CpuMode kCpuMode{};
+ void set_cpu_mode(Profiling_CpuMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimebaseCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfSample>;
+
+ static constexpr FieldMetadata_TimebaseCount kTimebaseCount{};
+ void set_timebase_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimebaseCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CallstackIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfSample>;
+
+ static constexpr FieldMetadata_CallstackIid kCallstackIid{};
+ void set_callstack_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallstackIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnwindError =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ Profiling_StackUnwindError,
+ PerfSample>;
+
+ static constexpr FieldMetadata_UnwindError kUnwindError{};
+ void set_unwind_error(Profiling_StackUnwindError value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnwindError::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KernelRecordsLost =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfSample>;
+
+ static constexpr FieldMetadata_KernelRecordsLost kKernelRecordsLost{};
+ void set_kernel_records_lost(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KernelRecordsLost::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SampleSkippedReason =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ PerfSample_SampleSkipReason,
+ PerfSample>;
+
+ static constexpr FieldMetadata_SampleSkippedReason kSampleSkippedReason{};
+ void set_sample_skipped_reason(PerfSample_SampleSkipReason value) {
+ static constexpr uint32_t field_id = FieldMetadata_SampleSkippedReason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProducerEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfSample_ProducerEvent,
+ PerfSample>;
+
+ static constexpr FieldMetadata_ProducerEvent kProducerEvent{};
+ template <typename T = PerfSample_ProducerEvent> T* set_producer_event() {
+ return BeginNestedMessage<T>(19);
+ }
+
+};
+
+class PerfSample_ProducerEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfSample_ProducerEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfSample_ProducerEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfSample_ProducerEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_source_stop_reason() const { return at<1>().valid(); }
+ int32_t source_stop_reason() const { return at<1>().as_int32(); }
+};
+
+class PerfSample_ProducerEvent : public ::protozero::Message {
+ public:
+ using Decoder = PerfSample_ProducerEvent_Decoder;
+ enum : int32_t {
+ kSourceStopReasonFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfSample.ProducerEvent"; }
+
+
+ using DataSourceStopReason = ::perfetto::protos::pbzero::PerfSample_ProducerEvent_DataSourceStopReason;
+ static inline const char* DataSourceStopReason_Name(DataSourceStopReason value) {
+ return ::perfetto::protos::pbzero::PerfSample_ProducerEvent_DataSourceStopReason_Name(value);
+ }
+ static inline const DataSourceStopReason PROFILER_STOP_UNKNOWN = DataSourceStopReason::PROFILER_STOP_UNKNOWN;
+ static inline const DataSourceStopReason PROFILER_STOP_GUARDRAIL = DataSourceStopReason::PROFILER_STOP_GUARDRAIL;
+
+ using FieldMetadata_SourceStopReason =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ PerfSample_ProducerEvent_DataSourceStopReason,
+ PerfSample_ProducerEvent>;
+
+ static constexpr FieldMetadata_SourceStopReason kSourceStopReason{};
+ void set_source_stop_reason(PerfSample_ProducerEvent_DataSourceStopReason value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceStopReason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Profiling_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Profiling_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Profiling_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Profiling_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class Profiling : public ::protozero::Message {
+ public:
+ using Decoder = Profiling_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.Profiling"; }
+
+
+ using CpuMode = ::perfetto::protos::pbzero::Profiling_CpuMode;
+ static inline const char* CpuMode_Name(CpuMode value) {
+ return ::perfetto::protos::pbzero::Profiling_CpuMode_Name(value);
+ }
+
+ using StackUnwindError = ::perfetto::protos::pbzero::Profiling_StackUnwindError;
+ static inline const char* StackUnwindError_Name(StackUnwindError value) {
+ return ::perfetto::protos::pbzero::Profiling_StackUnwindError_Name(value);
+ }
+ static inline const CpuMode MODE_UNKNOWN = CpuMode::MODE_UNKNOWN;
+ static inline const CpuMode MODE_KERNEL = CpuMode::MODE_KERNEL;
+ static inline const CpuMode MODE_USER = CpuMode::MODE_USER;
+ static inline const CpuMode MODE_HYPERVISOR = CpuMode::MODE_HYPERVISOR;
+ static inline const CpuMode MODE_GUEST_KERNEL = CpuMode::MODE_GUEST_KERNEL;
+ static inline const CpuMode MODE_GUEST_USER = CpuMode::MODE_GUEST_USER;
+ static inline const StackUnwindError UNWIND_ERROR_UNKNOWN = StackUnwindError::UNWIND_ERROR_UNKNOWN;
+ static inline const StackUnwindError UNWIND_ERROR_NONE = StackUnwindError::UNWIND_ERROR_NONE;
+ static inline const StackUnwindError UNWIND_ERROR_MEMORY_INVALID = StackUnwindError::UNWIND_ERROR_MEMORY_INVALID;
+ static inline const StackUnwindError UNWIND_ERROR_UNWIND_INFO = StackUnwindError::UNWIND_ERROR_UNWIND_INFO;
+ static inline const StackUnwindError UNWIND_ERROR_UNSUPPORTED = StackUnwindError::UNWIND_ERROR_UNSUPPORTED;
+ static inline const StackUnwindError UNWIND_ERROR_INVALID_MAP = StackUnwindError::UNWIND_ERROR_INVALID_MAP;
+ static inline const StackUnwindError UNWIND_ERROR_MAX_FRAMES_EXCEEDED = StackUnwindError::UNWIND_ERROR_MAX_FRAMES_EXCEEDED;
+ static inline const StackUnwindError UNWIND_ERROR_REPEATED_FRAME = StackUnwindError::UNWIND_ERROR_REPEATED_FRAME;
+ static inline const StackUnwindError UNWIND_ERROR_INVALID_ELF = StackUnwindError::UNWIND_ERROR_INVALID_ELF;
+ static inline const StackUnwindError UNWIND_ERROR_SYSTEM_CALL = StackUnwindError::UNWIND_ERROR_SYSTEM_CALL;
+ static inline const StackUnwindError UNWIND_ERROR_THREAD_TIMEOUT = StackUnwindError::UNWIND_ERROR_THREAD_TIMEOUT;
+ static inline const StackUnwindError UNWIND_ERROR_THREAD_DOES_NOT_EXIST = StackUnwindError::UNWIND_ERROR_THREAD_DOES_NOT_EXIST;
+ static inline const StackUnwindError UNWIND_ERROR_BAD_ARCH = StackUnwindError::UNWIND_ERROR_BAD_ARCH;
+ static inline const StackUnwindError UNWIND_ERROR_MAPS_PARSE = StackUnwindError::UNWIND_ERROR_MAPS_PARSE;
+ static inline const StackUnwindError UNWIND_ERROR_INVALID_PARAMETER = StackUnwindError::UNWIND_ERROR_INVALID_PARAMETER;
+ static inline const StackUnwindError UNWIND_ERROR_PTRACE_CALL = StackUnwindError::UNWIND_ERROR_PTRACE_CALL;
+};
+
+class StreamingProfilePacket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ StreamingProfilePacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StreamingProfilePacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StreamingProfilePacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_callstack_iid() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> callstack_iid() const { return GetRepeated<uint64_t>(1); }
+ bool has_timestamp_delta_us() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int64_t> timestamp_delta_us() const { return GetRepeated<int64_t>(2); }
+ bool has_process_priority() const { return at<3>().valid(); }
+ int32_t process_priority() const { return at<3>().as_int32(); }
+};
+
+class StreamingProfilePacket : public ::protozero::Message {
+ public:
+ using Decoder = StreamingProfilePacket_Decoder;
+ enum : int32_t {
+ kCallstackIidFieldNumber = 1,
+ kTimestampDeltaUsFieldNumber = 2,
+ kProcessPriorityFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StreamingProfilePacket"; }
+
+
+ using FieldMetadata_CallstackIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingProfilePacket>;
+
+ static constexpr FieldMetadata_CallstackIid kCallstackIid{};
+ void add_callstack_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallstackIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimestampDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ StreamingProfilePacket>;
+
+ static constexpr FieldMetadata_TimestampDeltaUs kTimestampDeltaUs{};
+ void add_timestamp_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ StreamingProfilePacket>;
+
+ static constexpr FieldMetadata_ProcessPriority kProcessPriority{};
+ void set_process_priority(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessPriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class StreamingFree_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ StreamingFree_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StreamingFree_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StreamingFree_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_address() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> address() const { return GetRepeated<uint64_t>(1); }
+ bool has_heap_id() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> heap_id() const { return GetRepeated<uint32_t>(2); }
+ bool has_sequence_number() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> sequence_number() const { return GetRepeated<uint64_t>(3); }
+};
+
+class StreamingFree : public ::protozero::Message {
+ public:
+ using Decoder = StreamingFree_Decoder;
+ enum : int32_t {
+ kAddressFieldNumber = 1,
+ kHeapIdFieldNumber = 2,
+ kSequenceNumberFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StreamingFree"; }
+
+
+ using FieldMetadata_Address =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingFree>;
+
+ static constexpr FieldMetadata_Address kAddress{};
+ void add_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Address::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StreamingFree>;
+
+ static constexpr FieldMetadata_HeapId kHeapId{};
+ void add_heap_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SequenceNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingFree>;
+
+ static constexpr FieldMetadata_SequenceNumber kSequenceNumber{};
+ void add_sequence_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SequenceNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class StreamingAllocation_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ StreamingAllocation_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StreamingAllocation_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StreamingAllocation_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_address() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> address() const { return GetRepeated<uint64_t>(1); }
+ bool has_size() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> size() const { return GetRepeated<uint64_t>(2); }
+ bool has_sample_size() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> sample_size() const { return GetRepeated<uint64_t>(3); }
+ bool has_clock_monotonic_coarse_timestamp() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> clock_monotonic_coarse_timestamp() const { return GetRepeated<uint64_t>(4); }
+ bool has_heap_id() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> heap_id() const { return GetRepeated<uint32_t>(5); }
+ bool has_sequence_number() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint64_t> sequence_number() const { return GetRepeated<uint64_t>(6); }
+};
+
+class StreamingAllocation : public ::protozero::Message {
+ public:
+ using Decoder = StreamingAllocation_Decoder;
+ enum : int32_t {
+ kAddressFieldNumber = 1,
+ kSizeFieldNumber = 2,
+ kSampleSizeFieldNumber = 3,
+ kClockMonotonicCoarseTimestampFieldNumber = 4,
+ kHeapIdFieldNumber = 5,
+ kSequenceNumberFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StreamingAllocation"; }
+
+
+ using FieldMetadata_Address =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingAllocation>;
+
+ static constexpr FieldMetadata_Address kAddress{};
+ void add_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Address::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Size =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingAllocation>;
+
+ static constexpr FieldMetadata_Size kSize{};
+ void add_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Size::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SampleSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingAllocation>;
+
+ static constexpr FieldMetadata_SampleSize kSampleSize{};
+ void add_sample_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SampleSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClockMonotonicCoarseTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingAllocation>;
+
+ static constexpr FieldMetadata_ClockMonotonicCoarseTimestamp kClockMonotonicCoarseTimestamp{};
+ void add_clock_monotonic_coarse_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClockMonotonicCoarseTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ StreamingAllocation>;
+
+ static constexpr FieldMetadata_HeapId kHeapId{};
+ void add_heap_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SequenceNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ StreamingAllocation>;
+
+ static constexpr FieldMetadata_SequenceNumber kSequenceNumber{};
+ void add_sequence_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SequenceNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProfilePacket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProfilePacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProfilePacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProfilePacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_strings() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> strings() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_mappings() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> mappings() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_frames() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> frames() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_callstacks() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> callstacks() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_process_dumps() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> process_dumps() const { return GetRepeated<::protozero::ConstBytes>(5); }
+ bool has_continued() const { return at<6>().valid(); }
+ bool continued() const { return at<6>().as_bool(); }
+ bool has_index() const { return at<7>().valid(); }
+ uint64_t index() const { return at<7>().as_uint64(); }
+};
+
+class ProfilePacket : public ::protozero::Message {
+ public:
+ using Decoder = ProfilePacket_Decoder;
+ enum : int32_t {
+ kStringsFieldNumber = 1,
+ kMappingsFieldNumber = 4,
+ kFramesFieldNumber = 2,
+ kCallstacksFieldNumber = 3,
+ kProcessDumpsFieldNumber = 5,
+ kContinuedFieldNumber = 6,
+ kIndexFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProfilePacket"; }
+
+ using HeapSample = ::perfetto::protos::pbzero::ProfilePacket_HeapSample;
+ using Histogram = ::perfetto::protos::pbzero::ProfilePacket_Histogram;
+ using ProcessStats = ::perfetto::protos::pbzero::ProfilePacket_ProcessStats;
+ using ProcessHeapSamples = ::perfetto::protos::pbzero::ProfilePacket_ProcessHeapSamples;
+
+ using FieldMetadata_Strings =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ InternedString,
+ ProfilePacket>;
+
+ static constexpr FieldMetadata_Strings kStrings{};
+ template <typename T = InternedString> T* add_strings() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Mappings =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Mapping,
+ ProfilePacket>;
+
+ static constexpr FieldMetadata_Mappings kMappings{};
+ template <typename T = Mapping> T* add_mappings() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_Frames =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Frame,
+ ProfilePacket>;
+
+ static constexpr FieldMetadata_Frames kFrames{};
+ template <typename T = Frame> T* add_frames() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_Callstacks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Callstack,
+ ProfilePacket>;
+
+ static constexpr FieldMetadata_Callstacks kCallstacks{};
+ template <typename T = Callstack> T* add_callstacks() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_ProcessDumps =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfilePacket_ProcessHeapSamples,
+ ProfilePacket>;
+
+ static constexpr FieldMetadata_ProcessDumps kProcessDumps{};
+ template <typename T = ProfilePacket_ProcessHeapSamples> T* add_process_dumps() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_Continued =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket>;
+
+ static constexpr FieldMetadata_Continued kContinued{};
+ void set_continued(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Continued::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProfilePacket_ProcessHeapSamples_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/14, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProfilePacket_ProcessHeapSamples_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProfilePacket_ProcessHeapSamples_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProfilePacket_ProcessHeapSamples_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ uint64_t pid() const { return at<1>().as_uint64(); }
+ bool has_from_startup() const { return at<3>().valid(); }
+ bool from_startup() const { return at<3>().as_bool(); }
+ bool has_rejected_concurrent() const { return at<4>().valid(); }
+ bool rejected_concurrent() const { return at<4>().as_bool(); }
+ bool has_disconnected() const { return at<6>().valid(); }
+ bool disconnected() const { return at<6>().as_bool(); }
+ bool has_buffer_overran() const { return at<7>().valid(); }
+ bool buffer_overran() const { return at<7>().as_bool(); }
+ bool has_client_error() const { return at<14>().valid(); }
+ int32_t client_error() const { return at<14>().as_int32(); }
+ bool has_buffer_corrupted() const { return at<8>().valid(); }
+ bool buffer_corrupted() const { return at<8>().as_bool(); }
+ bool has_hit_guardrail() const { return at<10>().valid(); }
+ bool hit_guardrail() const { return at<10>().as_bool(); }
+ bool has_heap_name() const { return at<11>().valid(); }
+ ::protozero::ConstChars heap_name() const { return at<11>().as_string(); }
+ bool has_sampling_interval_bytes() const { return at<12>().valid(); }
+ uint64_t sampling_interval_bytes() const { return at<12>().as_uint64(); }
+ bool has_orig_sampling_interval_bytes() const { return at<13>().valid(); }
+ uint64_t orig_sampling_interval_bytes() const { return at<13>().as_uint64(); }
+ bool has_timestamp() const { return at<9>().valid(); }
+ uint64_t timestamp() const { return at<9>().as_uint64(); }
+ bool has_stats() const { return at<5>().valid(); }
+ ::protozero::ConstBytes stats() const { return at<5>().as_bytes(); }
+ bool has_samples() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> samples() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class ProfilePacket_ProcessHeapSamples : public ::protozero::Message {
+ public:
+ using Decoder = ProfilePacket_ProcessHeapSamples_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kFromStartupFieldNumber = 3,
+ kRejectedConcurrentFieldNumber = 4,
+ kDisconnectedFieldNumber = 6,
+ kBufferOverranFieldNumber = 7,
+ kClientErrorFieldNumber = 14,
+ kBufferCorruptedFieldNumber = 8,
+ kHitGuardrailFieldNumber = 10,
+ kHeapNameFieldNumber = 11,
+ kSamplingIntervalBytesFieldNumber = 12,
+ kOrigSamplingIntervalBytesFieldNumber = 13,
+ kTimestampFieldNumber = 9,
+ kStatsFieldNumber = 5,
+ kSamplesFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProfilePacket.ProcessHeapSamples"; }
+
+
+ using ClientError = ::perfetto::protos::pbzero::ProfilePacket_ProcessHeapSamples_ClientError;
+ static inline const char* ClientError_Name(ClientError value) {
+ return ::perfetto::protos::pbzero::ProfilePacket_ProcessHeapSamples_ClientError_Name(value);
+ }
+ static inline const ClientError CLIENT_ERROR_NONE = ClientError::CLIENT_ERROR_NONE;
+ static inline const ClientError CLIENT_ERROR_HIT_TIMEOUT = ClientError::CLIENT_ERROR_HIT_TIMEOUT;
+ static inline const ClientError CLIENT_ERROR_INVALID_STACK_BOUNDS = ClientError::CLIENT_ERROR_INVALID_STACK_BOUNDS;
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FromStartup =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_FromStartup kFromStartup{};
+ void set_from_startup(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_FromStartup::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RejectedConcurrent =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_RejectedConcurrent kRejectedConcurrent{};
+ void set_rejected_concurrent(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_RejectedConcurrent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Disconnected =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_Disconnected kDisconnected{};
+ void set_disconnected(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Disconnected::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BufferOverran =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_BufferOverran kBufferOverran{};
+ void set_buffer_overran(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferOverran::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClientError =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ProfilePacket_ProcessHeapSamples_ClientError,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_ClientError kClientError{};
+ void set_client_error(ProfilePacket_ProcessHeapSamples_ClientError value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClientError::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BufferCorrupted =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_BufferCorrupted kBufferCorrupted{};
+ void set_buffer_corrupted(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BufferCorrupted::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HitGuardrail =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_HitGuardrail kHitGuardrail{};
+ void set_hit_guardrail(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HitGuardrail::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapName =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_HeapName kHeapName{};
+ void set_heap_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, data, size);
+ }
+ void set_heap_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HeapName::kFieldId, chars.data, chars.size);
+ }
+ void set_heap_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SamplingIntervalBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_SamplingIntervalBytes kSamplingIntervalBytes{};
+ void set_sampling_interval_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SamplingIntervalBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrigSamplingIntervalBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_OrigSamplingIntervalBytes kOrigSamplingIntervalBytes{};
+ void set_orig_sampling_interval_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrigSamplingIntervalBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Stats =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfilePacket_ProcessStats,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_Stats kStats{};
+ template <typename T = ProfilePacket_ProcessStats> T* set_stats() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_Samples =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfilePacket_HeapSample,
+ ProfilePacket_ProcessHeapSamples>;
+
+ static constexpr FieldMetadata_Samples kSamples{};
+ template <typename T = ProfilePacket_HeapSample> T* add_samples() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class ProfilePacket_ProcessStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProfilePacket_ProcessStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProfilePacket_ProcessStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProfilePacket_ProcessStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_unwinding_errors() const { return at<1>().valid(); }
+ uint64_t unwinding_errors() const { return at<1>().as_uint64(); }
+ bool has_heap_samples() const { return at<2>().valid(); }
+ uint64_t heap_samples() const { return at<2>().as_uint64(); }
+ bool has_map_reparses() const { return at<3>().valid(); }
+ uint64_t map_reparses() const { return at<3>().as_uint64(); }
+ bool has_unwinding_time_us() const { return at<4>().valid(); }
+ ::protozero::ConstBytes unwinding_time_us() const { return at<4>().as_bytes(); }
+ bool has_total_unwinding_time_us() const { return at<5>().valid(); }
+ uint64_t total_unwinding_time_us() const { return at<5>().as_uint64(); }
+ bool has_client_spinlock_blocked_us() const { return at<6>().valid(); }
+ uint64_t client_spinlock_blocked_us() const { return at<6>().as_uint64(); }
+};
+
+class ProfilePacket_ProcessStats : public ::protozero::Message {
+ public:
+ using Decoder = ProfilePacket_ProcessStats_Decoder;
+ enum : int32_t {
+ kUnwindingErrorsFieldNumber = 1,
+ kHeapSamplesFieldNumber = 2,
+ kMapReparsesFieldNumber = 3,
+ kUnwindingTimeUsFieldNumber = 4,
+ kTotalUnwindingTimeUsFieldNumber = 5,
+ kClientSpinlockBlockedUsFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProfilePacket.ProcessStats"; }
+
+
+ using FieldMetadata_UnwindingErrors =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessStats>;
+
+ static constexpr FieldMetadata_UnwindingErrors kUnwindingErrors{};
+ void set_unwinding_errors(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UnwindingErrors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HeapSamples =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessStats>;
+
+ static constexpr FieldMetadata_HeapSamples kHeapSamples{};
+ void set_heap_samples(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HeapSamples::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MapReparses =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessStats>;
+
+ static constexpr FieldMetadata_MapReparses kMapReparses{};
+ void set_map_reparses(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MapReparses::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UnwindingTimeUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfilePacket_Histogram,
+ ProfilePacket_ProcessStats>;
+
+ static constexpr FieldMetadata_UnwindingTimeUs kUnwindingTimeUs{};
+ template <typename T = ProfilePacket_Histogram> T* set_unwinding_time_us() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_TotalUnwindingTimeUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessStats>;
+
+ static constexpr FieldMetadata_TotalUnwindingTimeUs kTotalUnwindingTimeUs{};
+ void set_total_unwinding_time_us(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalUnwindingTimeUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ClientSpinlockBlockedUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_ProcessStats>;
+
+ static constexpr FieldMetadata_ClientSpinlockBlockedUs kClientSpinlockBlockedUs{};
+ void set_client_spinlock_blocked_us(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ClientSpinlockBlockedUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProfilePacket_Histogram_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProfilePacket_Histogram_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProfilePacket_Histogram_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProfilePacket_Histogram_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_buckets() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> buckets() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class ProfilePacket_Histogram : public ::protozero::Message {
+ public:
+ using Decoder = ProfilePacket_Histogram_Decoder;
+ enum : int32_t {
+ kBucketsFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProfilePacket.Histogram"; }
+
+ using Bucket = ::perfetto::protos::pbzero::ProfilePacket_Histogram_Bucket;
+
+ using FieldMetadata_Buckets =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProfilePacket_Histogram_Bucket,
+ ProfilePacket_Histogram>;
+
+ static constexpr FieldMetadata_Buckets kBuckets{};
+ template <typename T = ProfilePacket_Histogram_Bucket> T* add_buckets() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class ProfilePacket_Histogram_Bucket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProfilePacket_Histogram_Bucket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProfilePacket_Histogram_Bucket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProfilePacket_Histogram_Bucket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_upper_limit() const { return at<1>().valid(); }
+ uint64_t upper_limit() const { return at<1>().as_uint64(); }
+ bool has_max_bucket() const { return at<2>().valid(); }
+ bool max_bucket() const { return at<2>().as_bool(); }
+ bool has_count() const { return at<3>().valid(); }
+ uint64_t count() const { return at<3>().as_uint64(); }
+};
+
+class ProfilePacket_Histogram_Bucket : public ::protozero::Message {
+ public:
+ using Decoder = ProfilePacket_Histogram_Bucket_Decoder;
+ enum : int32_t {
+ kUpperLimitFieldNumber = 1,
+ kMaxBucketFieldNumber = 2,
+ kCountFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProfilePacket.Histogram.Bucket"; }
+
+
+ using FieldMetadata_UpperLimit =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_Histogram_Bucket>;
+
+ static constexpr FieldMetadata_UpperLimit kUpperLimit{};
+ void set_upper_limit(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UpperLimit::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MaxBucket =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProfilePacket_Histogram_Bucket>;
+
+ static constexpr FieldMetadata_MaxBucket kMaxBucket{};
+ void set_max_bucket(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_MaxBucket::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_Histogram_Bucket>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProfilePacket_HeapSample_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProfilePacket_HeapSample_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProfilePacket_HeapSample_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProfilePacket_HeapSample_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_callstack_id() const { return at<1>().valid(); }
+ uint64_t callstack_id() const { return at<1>().as_uint64(); }
+ bool has_self_allocated() const { return at<2>().valid(); }
+ uint64_t self_allocated() const { return at<2>().as_uint64(); }
+ bool has_self_freed() const { return at<3>().valid(); }
+ uint64_t self_freed() const { return at<3>().as_uint64(); }
+ bool has_self_max() const { return at<8>().valid(); }
+ uint64_t self_max() const { return at<8>().as_uint64(); }
+ bool has_self_max_count() const { return at<9>().valid(); }
+ uint64_t self_max_count() const { return at<9>().as_uint64(); }
+ bool has_timestamp() const { return at<4>().valid(); }
+ uint64_t timestamp() const { return at<4>().as_uint64(); }
+ bool has_alloc_count() const { return at<5>().valid(); }
+ uint64_t alloc_count() const { return at<5>().as_uint64(); }
+ bool has_free_count() const { return at<6>().valid(); }
+ uint64_t free_count() const { return at<6>().as_uint64(); }
+};
+
+class ProfilePacket_HeapSample : public ::protozero::Message {
+ public:
+ using Decoder = ProfilePacket_HeapSample_Decoder;
+ enum : int32_t {
+ kCallstackIdFieldNumber = 1,
+ kSelfAllocatedFieldNumber = 2,
+ kSelfFreedFieldNumber = 3,
+ kSelfMaxFieldNumber = 8,
+ kSelfMaxCountFieldNumber = 9,
+ kTimestampFieldNumber = 4,
+ kAllocCountFieldNumber = 5,
+ kFreeCountFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProfilePacket.HeapSample"; }
+
+
+ using FieldMetadata_CallstackId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_CallstackId kCallstackId{};
+ void set_callstack_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CallstackId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SelfAllocated =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_SelfAllocated kSelfAllocated{};
+ void set_self_allocated(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SelfAllocated::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SelfFreed =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_SelfFreed kSelfFreed{};
+ void set_self_freed(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SelfFreed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SelfMax =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_SelfMax kSelfMax{};
+ void set_self_max(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SelfMax::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SelfMaxCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_SelfMaxCount kSelfMaxCount{};
+ void set_self_max_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SelfMaxCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Timestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_Timestamp kTimestamp{};
+ void set_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllocCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_AllocCount kAllocCount{};
+ void set_alloc_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllocCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FreeCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProfilePacket_HeapSample>;
+
+ static constexpr FieldMetadata_FreeCount kFreeCount{};
+ void set_free_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FreeCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/profiling/smaps.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_SMAPS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PROFILING_SMAPS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class SmapsEntry;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SmapsPacket_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ SmapsPacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SmapsPacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SmapsPacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ uint32_t pid() const { return at<1>().as_uint32(); }
+ bool has_entries() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> entries() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class SmapsPacket : public ::protozero::Message {
+ public:
+ using Decoder = SmapsPacket_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kEntriesFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SmapsPacket"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmapsPacket>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Entries =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SmapsEntry,
+ SmapsPacket>;
+
+ static constexpr FieldMetadata_Entries kEntries{};
+ template <typename T = SmapsEntry> T* add_entries() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class SmapsEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/15, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SmapsEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SmapsEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SmapsEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_path() const { return at<1>().valid(); }
+ ::protozero::ConstChars path() const { return at<1>().as_string(); }
+ bool has_size_kb() const { return at<2>().valid(); }
+ uint64_t size_kb() const { return at<2>().as_uint64(); }
+ bool has_private_dirty_kb() const { return at<3>().valid(); }
+ uint64_t private_dirty_kb() const { return at<3>().as_uint64(); }
+ bool has_swap_kb() const { return at<4>().valid(); }
+ uint64_t swap_kb() const { return at<4>().as_uint64(); }
+ bool has_file_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars file_name() const { return at<5>().as_string(); }
+ bool has_start_address() const { return at<6>().valid(); }
+ uint64_t start_address() const { return at<6>().as_uint64(); }
+ bool has_module_timestamp() const { return at<7>().valid(); }
+ uint64_t module_timestamp() const { return at<7>().as_uint64(); }
+ bool has_module_debugid() const { return at<8>().valid(); }
+ ::protozero::ConstChars module_debugid() const { return at<8>().as_string(); }
+ bool has_module_debug_path() const { return at<9>().valid(); }
+ ::protozero::ConstChars module_debug_path() const { return at<9>().as_string(); }
+ bool has_protection_flags() const { return at<10>().valid(); }
+ uint32_t protection_flags() const { return at<10>().as_uint32(); }
+ bool has_private_clean_resident_kb() const { return at<11>().valid(); }
+ uint64_t private_clean_resident_kb() const { return at<11>().as_uint64(); }
+ bool has_shared_dirty_resident_kb() const { return at<12>().valid(); }
+ uint64_t shared_dirty_resident_kb() const { return at<12>().as_uint64(); }
+ bool has_shared_clean_resident_kb() const { return at<13>().valid(); }
+ uint64_t shared_clean_resident_kb() const { return at<13>().as_uint64(); }
+ bool has_locked_kb() const { return at<14>().valid(); }
+ uint64_t locked_kb() const { return at<14>().as_uint64(); }
+ bool has_proportional_resident_kb() const { return at<15>().valid(); }
+ uint64_t proportional_resident_kb() const { return at<15>().as_uint64(); }
+};
+
+class SmapsEntry : public ::protozero::Message {
+ public:
+ using Decoder = SmapsEntry_Decoder;
+ enum : int32_t {
+ kPathFieldNumber = 1,
+ kSizeKbFieldNumber = 2,
+ kPrivateDirtyKbFieldNumber = 3,
+ kSwapKbFieldNumber = 4,
+ kFileNameFieldNumber = 5,
+ kStartAddressFieldNumber = 6,
+ kModuleTimestampFieldNumber = 7,
+ kModuleDebugidFieldNumber = 8,
+ kModuleDebugPathFieldNumber = 9,
+ kProtectionFlagsFieldNumber = 10,
+ kPrivateCleanResidentKbFieldNumber = 11,
+ kSharedDirtyResidentKbFieldNumber = 12,
+ kSharedCleanResidentKbFieldNumber = 13,
+ kLockedKbFieldNumber = 14,
+ kProportionalResidentKbFieldNumber = 15,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SmapsEntry"; }
+
+
+ using FieldMetadata_Path =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_Path kPath{};
+ void set_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Path::kFieldId, data, size);
+ }
+ void set_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Path::kFieldId, chars.data, chars.size);
+ }
+ void set_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Path::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_SizeKb kSizeKb{};
+ void set_size_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrivateDirtyKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_PrivateDirtyKb kPrivateDirtyKb{};
+ void set_private_dirty_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrivateDirtyKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SwapKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_SwapKb kSwapKb{};
+ void set_swap_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SwapKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FileName =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_FileName kFileName{};
+ void set_file_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FileName::kFieldId, data, size);
+ }
+ void set_file_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FileName::kFieldId, chars.data, chars.size);
+ }
+ void set_file_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FileName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartAddress =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_StartAddress kStartAddress{};
+ void set_start_address(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartAddress::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ModuleTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_ModuleTimestamp kModuleTimestamp{};
+ void set_module_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ModuleTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ModuleDebugid =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_ModuleDebugid kModuleDebugid{};
+ void set_module_debugid(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ModuleDebugid::kFieldId, data, size);
+ }
+ void set_module_debugid(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ModuleDebugid::kFieldId, chars.data, chars.size);
+ }
+ void set_module_debugid(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ModuleDebugid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ModuleDebugPath =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_ModuleDebugPath kModuleDebugPath{};
+ void set_module_debug_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ModuleDebugPath::kFieldId, data, size);
+ }
+ void set_module_debug_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ModuleDebugPath::kFieldId, chars.data, chars.size);
+ }
+ void set_module_debug_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ModuleDebugPath::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProtectionFlags =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_ProtectionFlags kProtectionFlags{};
+ void set_protection_flags(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProtectionFlags::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrivateCleanResidentKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_PrivateCleanResidentKb kPrivateCleanResidentKb{};
+ void set_private_clean_resident_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrivateCleanResidentKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SharedDirtyResidentKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_SharedDirtyResidentKb kSharedDirtyResidentKb{};
+ void set_shared_dirty_resident_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SharedDirtyResidentKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SharedCleanResidentKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_SharedCleanResidentKb kSharedCleanResidentKb{};
+ void set_shared_clean_resident_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SharedCleanResidentKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LockedKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_LockedKb kLockedKb{};
+ void set_locked_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LockedKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProportionalResidentKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SmapsEntry>;
+
+ static constexpr FieldMetadata_ProportionalResidentKb kProportionalResidentKb{};
+ void set_proportional_resident_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProportionalResidentKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_active_processes.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_ACTIVE_PROCESSES_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_ACTIVE_PROCESSES_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeActiveProcesses_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeActiveProcesses_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeActiveProcesses_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeActiveProcesses_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> pid() const { return GetRepeated<int32_t>(1); }
+};
+
+class ChromeActiveProcesses : public ::protozero::Message {
+ public:
+ using Decoder = ChromeActiveProcesses_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeActiveProcesses"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeActiveProcesses>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void add_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_application_state_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ChromeApplicationStateInfo {
+enum ChromeApplicationState : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeApplicationStateInfo
+using ChromeApplicationStateInfo_ChromeApplicationState = perfetto_pbzero_enum_ChromeApplicationStateInfo::ChromeApplicationState;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeApplicationStateInfo {
+enum ChromeApplicationState : int32_t {
+ APPLICATION_STATE_UNKNOWN = 0,
+ APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = 1,
+ APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = 2,
+ APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = 3,
+ APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES = 4,
+};
+} // namespace perfetto_pbzero_enum_ChromeApplicationStateInfo
+using ChromeApplicationStateInfo_ChromeApplicationState = perfetto_pbzero_enum_ChromeApplicationStateInfo::ChromeApplicationState;
+
+
+constexpr ChromeApplicationStateInfo_ChromeApplicationState ChromeApplicationStateInfo_ChromeApplicationState_MIN = ChromeApplicationStateInfo_ChromeApplicationState::APPLICATION_STATE_UNKNOWN;
+constexpr ChromeApplicationStateInfo_ChromeApplicationState ChromeApplicationStateInfo_ChromeApplicationState_MAX = ChromeApplicationStateInfo_ChromeApplicationState::APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeApplicationStateInfo_ChromeApplicationState_Name(::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState::APPLICATION_STATE_UNKNOWN:
+ return "APPLICATION_STATE_UNKNOWN";
+
+ case ::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES:
+ return "APPLICATION_STATE_HAS_RUNNING_ACTIVITIES";
+
+ case ::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES:
+ return "APPLICATION_STATE_HAS_PAUSED_ACTIVITIES";
+
+ case ::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES:
+ return "APPLICATION_STATE_HAS_STOPPED_ACTIVITIES";
+
+ case ::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState::APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES:
+ return "APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeApplicationStateInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeApplicationStateInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeApplicationStateInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeApplicationStateInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_application_state() const { return at<1>().valid(); }
+ int32_t application_state() const { return at<1>().as_int32(); }
+};
+
+class ChromeApplicationStateInfo : public ::protozero::Message {
+ public:
+ using Decoder = ChromeApplicationStateInfo_Decoder;
+ enum : int32_t {
+ kApplicationStateFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeApplicationStateInfo"; }
+
+
+ using ChromeApplicationState = ::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState;
+ static inline const char* ChromeApplicationState_Name(ChromeApplicationState value) {
+ return ::perfetto::protos::pbzero::ChromeApplicationStateInfo_ChromeApplicationState_Name(value);
+ }
+ static inline const ChromeApplicationState APPLICATION_STATE_UNKNOWN = ChromeApplicationState::APPLICATION_STATE_UNKNOWN;
+ static inline const ChromeApplicationState APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = ChromeApplicationState::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES;
+ static inline const ChromeApplicationState APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = ChromeApplicationState::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES;
+ static inline const ChromeApplicationState APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = ChromeApplicationState::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES;
+ static inline const ChromeApplicationState APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES = ChromeApplicationState::APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES;
+
+ using FieldMetadata_ApplicationState =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeApplicationStateInfo_ChromeApplicationState,
+ ChromeApplicationStateInfo>;
+
+ static constexpr FieldMetadata_ApplicationState kApplicationState{};
+ void set_application_state(ChromeApplicationStateInfo_ChromeApplicationState value) {
+ static constexpr uint32_t field_id = FieldMetadata_ApplicationState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_COMPOSITOR_SCHEDULER_STATE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_COMPOSITOR_SCHEDULER_STATE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class BeginFrameArgs;
+class BeginFrameObserverState;
+class BeginFrameSourceState;
+class BeginImplFrameArgs;
+class BeginImplFrameArgs_TimestampsInUs;
+class ChromeCompositorStateMachine;
+class ChromeCompositorStateMachine_MajorState;
+class ChromeCompositorStateMachine_MinorState;
+class CompositorTimingHistory;
+class SourceLocation;
+namespace perfetto_pbzero_enum_BeginFrameArgs {
+enum BeginFrameArgsType : int32_t;
+} // namespace perfetto_pbzero_enum_BeginFrameArgs
+using BeginFrameArgs_BeginFrameArgsType = perfetto_pbzero_enum_BeginFrameArgs::BeginFrameArgsType;
+namespace perfetto_pbzero_enum_BeginImplFrameArgs {
+enum State : int32_t;
+} // namespace perfetto_pbzero_enum_BeginImplFrameArgs
+using BeginImplFrameArgs_State = perfetto_pbzero_enum_BeginImplFrameArgs::State;
+enum ChromeCompositorSchedulerAction : int32_t;
+namespace perfetto_pbzero_enum_ChromeCompositorSchedulerState {
+enum BeginImplFrameDeadlineMode : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeCompositorSchedulerState
+using ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode = perfetto_pbzero_enum_ChromeCompositorSchedulerState::BeginImplFrameDeadlineMode;
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum BeginImplFrameState : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_BeginImplFrameState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::BeginImplFrameState;
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum BeginMainFrameState : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_BeginMainFrameState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::BeginMainFrameState;
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum ForcedRedrawOnTimeoutState : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::ForcedRedrawOnTimeoutState;
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum LayerTreeFrameSinkState : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::LayerTreeFrameSinkState;
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState {
+enum ScrollHandlerState : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState
+using ChromeCompositorStateMachine_MinorState_ScrollHandlerState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState::ScrollHandlerState;
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState {
+enum TreePriority : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState
+using ChromeCompositorStateMachine_MinorState_TreePriority = perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState::TreePriority;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum ChromeCompositorSchedulerAction : int32_t {
+ CC_SCHEDULER_ACTION_UNSPECIFIED = 0,
+ CC_SCHEDULER_ACTION_NONE = 1,
+ CC_SCHEDULER_ACTION_SEND_BEGIN_MAIN_FRAME = 2,
+ CC_SCHEDULER_ACTION_COMMIT = 3,
+ CC_SCHEDULER_ACTION_ACTIVATE_SYNC_TREE = 4,
+ CC_SCHEDULER_ACTION_DRAW_IF_POSSIBLE = 5,
+ CC_SCHEDULER_ACTION_DRAW_FORCED = 6,
+ CC_SCHEDULER_ACTION_DRAW_ABORT = 7,
+ CC_SCHEDULER_ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION = 8,
+ CC_SCHEDULER_ACTION_PREPARE_TILES = 9,
+ CC_SCHEDULER_ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK = 10,
+ CC_SCHEDULER_ACTION_PERFORM_IMPL_SIDE_INVALIDATION = 11,
+ CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL = 12,
+ CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON = 13,
+};
+
+constexpr ChromeCompositorSchedulerAction ChromeCompositorSchedulerAction_MIN = ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_UNSPECIFIED;
+constexpr ChromeCompositorSchedulerAction ChromeCompositorSchedulerAction_MAX = ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorSchedulerAction_Name(::perfetto::protos::pbzero::ChromeCompositorSchedulerAction value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_UNSPECIFIED:
+ return "CC_SCHEDULER_ACTION_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_NONE:
+ return "CC_SCHEDULER_ACTION_NONE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_SEND_BEGIN_MAIN_FRAME:
+ return "CC_SCHEDULER_ACTION_SEND_BEGIN_MAIN_FRAME";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_COMMIT:
+ return "CC_SCHEDULER_ACTION_COMMIT";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_ACTIVATE_SYNC_TREE:
+ return "CC_SCHEDULER_ACTION_ACTIVATE_SYNC_TREE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_DRAW_IF_POSSIBLE:
+ return "CC_SCHEDULER_ACTION_DRAW_IF_POSSIBLE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_DRAW_FORCED:
+ return "CC_SCHEDULER_ACTION_DRAW_FORCED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_DRAW_ABORT:
+ return "CC_SCHEDULER_ACTION_DRAW_ABORT";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION:
+ return "CC_SCHEDULER_ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_PREPARE_TILES:
+ return "CC_SCHEDULER_ACTION_PREPARE_TILES";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK:
+ return "CC_SCHEDULER_ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_PERFORM_IMPL_SIDE_INVALIDATION:
+ return "CC_SCHEDULER_ACTION_PERFORM_IMPL_SIDE_INVALIDATION";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL:
+ return "CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerAction::CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON:
+ return "CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_BeginImplFrameArgs {
+enum State : int32_t {
+ BEGIN_FRAME_FINISHED = 0,
+ BEGIN_FRAME_USING = 1,
+};
+} // namespace perfetto_pbzero_enum_BeginImplFrameArgs
+using BeginImplFrameArgs_State = perfetto_pbzero_enum_BeginImplFrameArgs::State;
+
+
+constexpr BeginImplFrameArgs_State BeginImplFrameArgs_State_MIN = BeginImplFrameArgs_State::BEGIN_FRAME_FINISHED;
+constexpr BeginImplFrameArgs_State BeginImplFrameArgs_State_MAX = BeginImplFrameArgs_State::BEGIN_FRAME_USING;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* BeginImplFrameArgs_State_Name(::perfetto::protos::pbzero::BeginImplFrameArgs_State value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::BeginImplFrameArgs_State::BEGIN_FRAME_FINISHED:
+ return "BEGIN_FRAME_FINISHED";
+
+ case ::perfetto::protos::pbzero::BeginImplFrameArgs_State::BEGIN_FRAME_USING:
+ return "BEGIN_FRAME_USING";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_BeginFrameArgs {
+enum BeginFrameArgsType : int32_t {
+ BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED = 0,
+ BEGIN_FRAME_ARGS_TYPE_INVALID = 1,
+ BEGIN_FRAME_ARGS_TYPE_NORMAL = 2,
+ BEGIN_FRAME_ARGS_TYPE_MISSED = 3,
+};
+} // namespace perfetto_pbzero_enum_BeginFrameArgs
+using BeginFrameArgs_BeginFrameArgsType = perfetto_pbzero_enum_BeginFrameArgs::BeginFrameArgsType;
+
+
+constexpr BeginFrameArgs_BeginFrameArgsType BeginFrameArgs_BeginFrameArgsType_MIN = BeginFrameArgs_BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED;
+constexpr BeginFrameArgs_BeginFrameArgsType BeginFrameArgs_BeginFrameArgsType_MAX = BeginFrameArgs_BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_MISSED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* BeginFrameArgs_BeginFrameArgsType_Name(::perfetto::protos::pbzero::BeginFrameArgs_BeginFrameArgsType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::BeginFrameArgs_BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED:
+ return "BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::BeginFrameArgs_BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_INVALID:
+ return "BEGIN_FRAME_ARGS_TYPE_INVALID";
+
+ case ::perfetto::protos::pbzero::BeginFrameArgs_BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_NORMAL:
+ return "BEGIN_FRAME_ARGS_TYPE_NORMAL";
+
+ case ::perfetto::protos::pbzero::BeginFrameArgs_BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_MISSED:
+ return "BEGIN_FRAME_ARGS_TYPE_MISSED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState {
+enum TreePriority : int32_t {
+ TREE_PRIORITY_UNSPECIFIED = 0,
+ TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES = 1,
+ TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY = 2,
+ TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY = 3,
+};
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState
+using ChromeCompositorStateMachine_MinorState_TreePriority = perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState::TreePriority;
+
+
+constexpr ChromeCompositorStateMachine_MinorState_TreePriority ChromeCompositorStateMachine_MinorState_TreePriority_MIN = ChromeCompositorStateMachine_MinorState_TreePriority::TREE_PRIORITY_UNSPECIFIED;
+constexpr ChromeCompositorStateMachine_MinorState_TreePriority ChromeCompositorStateMachine_MinorState_TreePriority_MAX = ChromeCompositorStateMachine_MinorState_TreePriority::TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorStateMachine_MinorState_TreePriority_Name(::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_TreePriority value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_TreePriority::TREE_PRIORITY_UNSPECIFIED:
+ return "TREE_PRIORITY_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_TreePriority::TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES:
+ return "TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_TreePriority::TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY:
+ return "TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_TreePriority::TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY:
+ return "TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState {
+enum ScrollHandlerState : int32_t {
+ SCROLL_HANDLER_UNSPECIFIED = 0,
+ SCROLL_AFFECTS_SCROLL_HANDLER = 1,
+ SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER = 2,
+};
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState
+using ChromeCompositorStateMachine_MinorState_ScrollHandlerState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MinorState::ScrollHandlerState;
+
+
+constexpr ChromeCompositorStateMachine_MinorState_ScrollHandlerState ChromeCompositorStateMachine_MinorState_ScrollHandlerState_MIN = ChromeCompositorStateMachine_MinorState_ScrollHandlerState::SCROLL_HANDLER_UNSPECIFIED;
+constexpr ChromeCompositorStateMachine_MinorState_ScrollHandlerState ChromeCompositorStateMachine_MinorState_ScrollHandlerState_MAX = ChromeCompositorStateMachine_MinorState_ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorStateMachine_MinorState_ScrollHandlerState_Name(::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_ScrollHandlerState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_ScrollHandlerState::SCROLL_HANDLER_UNSPECIFIED:
+ return "SCROLL_HANDLER_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER:
+ return "SCROLL_AFFECTS_SCROLL_HANDLER";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER:
+ return "SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum BeginImplFrameState : int32_t {
+ BEGIN_IMPL_FRAME_UNSPECIFIED = 0,
+ BEGIN_IMPL_FRAME_IDLE = 1,
+ BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME = 2,
+ BEGIN_IMPL_FRAME_INSIDE_DEADLINE = 3,
+};
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_BeginImplFrameState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::BeginImplFrameState;
+
+
+constexpr ChromeCompositorStateMachine_MajorState_BeginImplFrameState ChromeCompositorStateMachine_MajorState_BeginImplFrameState_MIN = ChromeCompositorStateMachine_MajorState_BeginImplFrameState::BEGIN_IMPL_FRAME_UNSPECIFIED;
+constexpr ChromeCompositorStateMachine_MajorState_BeginImplFrameState ChromeCompositorStateMachine_MajorState_BeginImplFrameState_MAX = ChromeCompositorStateMachine_MajorState_BeginImplFrameState::BEGIN_IMPL_FRAME_INSIDE_DEADLINE;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorStateMachine_MajorState_BeginImplFrameState_Name(::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginImplFrameState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginImplFrameState::BEGIN_IMPL_FRAME_UNSPECIFIED:
+ return "BEGIN_IMPL_FRAME_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginImplFrameState::BEGIN_IMPL_FRAME_IDLE:
+ return "BEGIN_IMPL_FRAME_IDLE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginImplFrameState::BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME:
+ return "BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginImplFrameState::BEGIN_IMPL_FRAME_INSIDE_DEADLINE:
+ return "BEGIN_IMPL_FRAME_INSIDE_DEADLINE";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum BeginMainFrameState : int32_t {
+ BEGIN_MAIN_FRAME_UNSPECIFIED = 0,
+ BEGIN_MAIN_FRAME_IDLE = 1,
+ BEGIN_MAIN_FRAME_SENT = 2,
+ BEGIN_MAIN_FRAME_READY_TO_COMMIT = 3,
+};
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_BeginMainFrameState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::BeginMainFrameState;
+
+
+constexpr ChromeCompositorStateMachine_MajorState_BeginMainFrameState ChromeCompositorStateMachine_MajorState_BeginMainFrameState_MIN = ChromeCompositorStateMachine_MajorState_BeginMainFrameState::BEGIN_MAIN_FRAME_UNSPECIFIED;
+constexpr ChromeCompositorStateMachine_MajorState_BeginMainFrameState ChromeCompositorStateMachine_MajorState_BeginMainFrameState_MAX = ChromeCompositorStateMachine_MajorState_BeginMainFrameState::BEGIN_MAIN_FRAME_READY_TO_COMMIT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorStateMachine_MajorState_BeginMainFrameState_Name(::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginMainFrameState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginMainFrameState::BEGIN_MAIN_FRAME_UNSPECIFIED:
+ return "BEGIN_MAIN_FRAME_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginMainFrameState::BEGIN_MAIN_FRAME_IDLE:
+ return "BEGIN_MAIN_FRAME_IDLE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginMainFrameState::BEGIN_MAIN_FRAME_SENT:
+ return "BEGIN_MAIN_FRAME_SENT";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginMainFrameState::BEGIN_MAIN_FRAME_READY_TO_COMMIT:
+ return "BEGIN_MAIN_FRAME_READY_TO_COMMIT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum LayerTreeFrameSinkState : int32_t {
+ LAYER_TREE_FRAME_UNSPECIFIED = 0,
+ LAYER_TREE_FRAME_NONE = 1,
+ LAYER_TREE_FRAME_ACTIVE = 2,
+ LAYER_TREE_FRAME_CREATING = 3,
+ LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT = 4,
+ LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION = 5,
+};
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::LayerTreeFrameSinkState;
+
+
+constexpr ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_MIN = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_UNSPECIFIED;
+constexpr ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_MAX = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_Name(::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_UNSPECIFIED:
+ return "LAYER_TREE_FRAME_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_NONE:
+ return "LAYER_TREE_FRAME_NONE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_ACTIVE:
+ return "LAYER_TREE_FRAME_ACTIVE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_CREATING:
+ return "LAYER_TREE_FRAME_CREATING";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT:
+ return "LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState::LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION:
+ return "LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState {
+enum ForcedRedrawOnTimeoutState : int32_t {
+ FORCED_REDRAW_UNSPECIFIED = 0,
+ FORCED_REDRAW_IDLE = 1,
+ FORCED_REDRAW_WAITING_FOR_COMMIT = 2,
+ FORCED_REDRAW_WAITING_FOR_ACTIVATION = 3,
+ FORCED_REDRAW_WAITING_FOR_DRAW = 4,
+};
+} // namespace perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState
+using ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState = perfetto_pbzero_enum_ChromeCompositorStateMachine_MajorState::ForcedRedrawOnTimeoutState;
+
+
+constexpr ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_MIN = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState::FORCED_REDRAW_UNSPECIFIED;
+constexpr ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_MAX = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState::FORCED_REDRAW_WAITING_FOR_DRAW;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_Name(::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState::FORCED_REDRAW_UNSPECIFIED:
+ return "FORCED_REDRAW_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState::FORCED_REDRAW_IDLE:
+ return "FORCED_REDRAW_IDLE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState::FORCED_REDRAW_WAITING_FOR_COMMIT:
+ return "FORCED_REDRAW_WAITING_FOR_COMMIT";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState::FORCED_REDRAW_WAITING_FOR_ACTIVATION:
+ return "FORCED_REDRAW_WAITING_FOR_ACTIVATION";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState::FORCED_REDRAW_WAITING_FOR_DRAW:
+ return "FORCED_REDRAW_WAITING_FOR_DRAW";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeCompositorSchedulerState {
+enum BeginImplFrameDeadlineMode : int32_t {
+ DEADLINE_MODE_UNSPECIFIED = 0,
+ DEADLINE_MODE_NONE = 1,
+ DEADLINE_MODE_IMMEDIATE = 2,
+ DEADLINE_MODE_REGULAR = 3,
+ DEADLINE_MODE_LATE = 4,
+ DEADLINE_MODE_BLOCKED = 5,
+};
+} // namespace perfetto_pbzero_enum_ChromeCompositorSchedulerState
+using ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode = perfetto_pbzero_enum_ChromeCompositorSchedulerState::BeginImplFrameDeadlineMode;
+
+
+constexpr ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_MIN = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_UNSPECIFIED;
+constexpr ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_MAX = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_BLOCKED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_Name(::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_UNSPECIFIED:
+ return "DEADLINE_MODE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_NONE:
+ return "DEADLINE_MODE_NONE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_IMMEDIATE:
+ return "DEADLINE_MODE_IMMEDIATE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_REGULAR:
+ return "DEADLINE_MODE_REGULAR";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_LATE:
+ return "DEADLINE_MODE_LATE";
+
+ case ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode::DEADLINE_MODE_BLOCKED:
+ return "DEADLINE_MODE_BLOCKED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class CompositorTimingHistory_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ CompositorTimingHistory_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CompositorTimingHistory_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CompositorTimingHistory_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_begin_main_frame_queue_critical_estimate_delta_us() const { return at<1>().valid(); }
+ int64_t begin_main_frame_queue_critical_estimate_delta_us() const { return at<1>().as_int64(); }
+ bool has_begin_main_frame_queue_not_critical_estimate_delta_us() const { return at<2>().valid(); }
+ int64_t begin_main_frame_queue_not_critical_estimate_delta_us() const { return at<2>().as_int64(); }
+ bool has_begin_main_frame_start_to_ready_to_commit_estimate_delta_us() const { return at<3>().valid(); }
+ int64_t begin_main_frame_start_to_ready_to_commit_estimate_delta_us() const { return at<3>().as_int64(); }
+ bool has_commit_to_ready_to_activate_estimate_delta_us() const { return at<4>().valid(); }
+ int64_t commit_to_ready_to_activate_estimate_delta_us() const { return at<4>().as_int64(); }
+ bool has_prepare_tiles_estimate_delta_us() const { return at<5>().valid(); }
+ int64_t prepare_tiles_estimate_delta_us() const { return at<5>().as_int64(); }
+ bool has_activate_estimate_delta_us() const { return at<6>().valid(); }
+ int64_t activate_estimate_delta_us() const { return at<6>().as_int64(); }
+ bool has_draw_estimate_delta_us() const { return at<7>().valid(); }
+ int64_t draw_estimate_delta_us() const { return at<7>().as_int64(); }
+};
+
+class CompositorTimingHistory : public ::protozero::Message {
+ public:
+ using Decoder = CompositorTimingHistory_Decoder;
+ enum : int32_t {
+ kBeginMainFrameQueueCriticalEstimateDeltaUsFieldNumber = 1,
+ kBeginMainFrameQueueNotCriticalEstimateDeltaUsFieldNumber = 2,
+ kBeginMainFrameStartToReadyToCommitEstimateDeltaUsFieldNumber = 3,
+ kCommitToReadyToActivateEstimateDeltaUsFieldNumber = 4,
+ kPrepareTilesEstimateDeltaUsFieldNumber = 5,
+ kActivateEstimateDeltaUsFieldNumber = 6,
+ kDrawEstimateDeltaUsFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CompositorTimingHistory"; }
+
+
+ using FieldMetadata_BeginMainFrameQueueCriticalEstimateDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CompositorTimingHistory>;
+
+ static constexpr FieldMetadata_BeginMainFrameQueueCriticalEstimateDeltaUs kBeginMainFrameQueueCriticalEstimateDeltaUs{};
+ void set_begin_main_frame_queue_critical_estimate_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BeginMainFrameQueueCriticalEstimateDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BeginMainFrameQueueNotCriticalEstimateDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CompositorTimingHistory>;
+
+ static constexpr FieldMetadata_BeginMainFrameQueueNotCriticalEstimateDeltaUs kBeginMainFrameQueueNotCriticalEstimateDeltaUs{};
+ void set_begin_main_frame_queue_not_critical_estimate_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BeginMainFrameQueueNotCriticalEstimateDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BeginMainFrameStartToReadyToCommitEstimateDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CompositorTimingHistory>;
+
+ static constexpr FieldMetadata_BeginMainFrameStartToReadyToCommitEstimateDeltaUs kBeginMainFrameStartToReadyToCommitEstimateDeltaUs{};
+ void set_begin_main_frame_start_to_ready_to_commit_estimate_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BeginMainFrameStartToReadyToCommitEstimateDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CommitToReadyToActivateEstimateDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CompositorTimingHistory>;
+
+ static constexpr FieldMetadata_CommitToReadyToActivateEstimateDeltaUs kCommitToReadyToActivateEstimateDeltaUs{};
+ void set_commit_to_ready_to_activate_estimate_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CommitToReadyToActivateEstimateDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PrepareTilesEstimateDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CompositorTimingHistory>;
+
+ static constexpr FieldMetadata_PrepareTilesEstimateDeltaUs kPrepareTilesEstimateDeltaUs{};
+ void set_prepare_tiles_estimate_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PrepareTilesEstimateDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ActivateEstimateDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CompositorTimingHistory>;
+
+ static constexpr FieldMetadata_ActivateEstimateDeltaUs kActivateEstimateDeltaUs{};
+ void set_activate_estimate_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActivateEstimateDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DrawEstimateDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ CompositorTimingHistory>;
+
+ static constexpr FieldMetadata_DrawEstimateDeltaUs kDrawEstimateDeltaUs{};
+ void set_draw_estimate_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DrawEstimateDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BeginFrameSourceState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BeginFrameSourceState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BeginFrameSourceState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BeginFrameSourceState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_source_id() const { return at<1>().valid(); }
+ uint32_t source_id() const { return at<1>().as_uint32(); }
+ bool has_paused() const { return at<2>().valid(); }
+ bool paused() const { return at<2>().as_bool(); }
+ bool has_num_observers() const { return at<3>().valid(); }
+ uint32_t num_observers() const { return at<3>().as_uint32(); }
+ bool has_last_begin_frame_args() const { return at<4>().valid(); }
+ ::protozero::ConstBytes last_begin_frame_args() const { return at<4>().as_bytes(); }
+};
+
+class BeginFrameSourceState : public ::protozero::Message {
+ public:
+ using Decoder = BeginFrameSourceState_Decoder;
+ enum : int32_t {
+ kSourceIdFieldNumber = 1,
+ kPausedFieldNumber = 2,
+ kNumObserversFieldNumber = 3,
+ kLastBeginFrameArgsFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BeginFrameSourceState"; }
+
+
+ using FieldMetadata_SourceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BeginFrameSourceState>;
+
+ static constexpr FieldMetadata_SourceId kSourceId{};
+ void set_source_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Paused =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ BeginFrameSourceState>;
+
+ static constexpr FieldMetadata_Paused kPaused{};
+ void set_paused(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Paused::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumObservers =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ BeginFrameSourceState>;
+
+ static constexpr FieldMetadata_NumObservers kNumObservers{};
+ void set_num_observers(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumObservers::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LastBeginFrameArgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginFrameArgs,
+ BeginFrameSourceState>;
+
+ static constexpr FieldMetadata_LastBeginFrameArgs kLastBeginFrameArgs{};
+ template <typename T = BeginFrameArgs> T* set_last_begin_frame_args() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+class BeginFrameObserverState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BeginFrameObserverState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BeginFrameObserverState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BeginFrameObserverState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dropped_begin_frame_args() const { return at<1>().valid(); }
+ int64_t dropped_begin_frame_args() const { return at<1>().as_int64(); }
+ bool has_last_begin_frame_args() const { return at<2>().valid(); }
+ ::protozero::ConstBytes last_begin_frame_args() const { return at<2>().as_bytes(); }
+};
+
+class BeginFrameObserverState : public ::protozero::Message {
+ public:
+ using Decoder = BeginFrameObserverState_Decoder;
+ enum : int32_t {
+ kDroppedBeginFrameArgsFieldNumber = 1,
+ kLastBeginFrameArgsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BeginFrameObserverState"; }
+
+
+ using FieldMetadata_DroppedBeginFrameArgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginFrameObserverState>;
+
+ static constexpr FieldMetadata_DroppedBeginFrameArgs kDroppedBeginFrameArgs{};
+ void set_dropped_begin_frame_args(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DroppedBeginFrameArgs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LastBeginFrameArgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginFrameArgs,
+ BeginFrameObserverState>;
+
+ static constexpr FieldMetadata_LastBeginFrameArgs kLastBeginFrameArgs{};
+ template <typename T = BeginFrameArgs> T* set_last_begin_frame_args() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class BeginImplFrameArgs_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BeginImplFrameArgs_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BeginImplFrameArgs_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BeginImplFrameArgs_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_updated_at_us() const { return at<1>().valid(); }
+ int64_t updated_at_us() const { return at<1>().as_int64(); }
+ bool has_finished_at_us() const { return at<2>().valid(); }
+ int64_t finished_at_us() const { return at<2>().as_int64(); }
+ bool has_state() const { return at<3>().valid(); }
+ int32_t state() const { return at<3>().as_int32(); }
+ bool has_current_args() const { return at<4>().valid(); }
+ ::protozero::ConstBytes current_args() const { return at<4>().as_bytes(); }
+ bool has_last_args() const { return at<5>().valid(); }
+ ::protozero::ConstBytes last_args() const { return at<5>().as_bytes(); }
+ bool has_timestamps_in_us() const { return at<6>().valid(); }
+ ::protozero::ConstBytes timestamps_in_us() const { return at<6>().as_bytes(); }
+};
+
+class BeginImplFrameArgs : public ::protozero::Message {
+ public:
+ using Decoder = BeginImplFrameArgs_Decoder;
+ enum : int32_t {
+ kUpdatedAtUsFieldNumber = 1,
+ kFinishedAtUsFieldNumber = 2,
+ kStateFieldNumber = 3,
+ kCurrentArgsFieldNumber = 4,
+ kLastArgsFieldNumber = 5,
+ kTimestampsInUsFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BeginImplFrameArgs"; }
+
+ using TimestampsInUs = ::perfetto::protos::pbzero::BeginImplFrameArgs_TimestampsInUs;
+
+ using State = ::perfetto::protos::pbzero::BeginImplFrameArgs_State;
+ static inline const char* State_Name(State value) {
+ return ::perfetto::protos::pbzero::BeginImplFrameArgs_State_Name(value);
+ }
+ static inline const State BEGIN_FRAME_FINISHED = State::BEGIN_FRAME_FINISHED;
+ static inline const State BEGIN_FRAME_USING = State::BEGIN_FRAME_USING;
+
+ using FieldMetadata_UpdatedAtUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs>;
+
+ static constexpr FieldMetadata_UpdatedAtUs kUpdatedAtUs{};
+ void set_updated_at_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UpdatedAtUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FinishedAtUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs>;
+
+ static constexpr FieldMetadata_FinishedAtUs kFinishedAtUs{};
+ void set_finished_at_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FinishedAtUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ BeginImplFrameArgs_State,
+ BeginImplFrameArgs>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(BeginImplFrameArgs_State value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrentArgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginFrameArgs,
+ BeginImplFrameArgs>;
+
+ static constexpr FieldMetadata_CurrentArgs kCurrentArgs{};
+ template <typename T = BeginFrameArgs> T* set_current_args() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_LastArgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginFrameArgs,
+ BeginImplFrameArgs>;
+
+ static constexpr FieldMetadata_LastArgs kLastArgs{};
+ template <typename T = BeginFrameArgs> T* set_last_args() {
+ return BeginNestedMessage<T>(5);
+ }
+
+
+ using FieldMetadata_TimestampsInUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginImplFrameArgs_TimestampsInUs,
+ BeginImplFrameArgs>;
+
+ static constexpr FieldMetadata_TimestampsInUs kTimestampsInUs{};
+ template <typename T = BeginImplFrameArgs_TimestampsInUs> T* set_timestamps_in_us() {
+ return BeginNestedMessage<T>(6);
+ }
+
+};
+
+class BeginImplFrameArgs_TimestampsInUs_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BeginImplFrameArgs_TimestampsInUs_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BeginImplFrameArgs_TimestampsInUs_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BeginImplFrameArgs_TimestampsInUs_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_interval_delta() const { return at<1>().valid(); }
+ int64_t interval_delta() const { return at<1>().as_int64(); }
+ bool has_now_to_deadline_delta() const { return at<2>().valid(); }
+ int64_t now_to_deadline_delta() const { return at<2>().as_int64(); }
+ bool has_frame_time_to_now_delta() const { return at<3>().valid(); }
+ int64_t frame_time_to_now_delta() const { return at<3>().as_int64(); }
+ bool has_frame_time_to_deadline_delta() const { return at<4>().valid(); }
+ int64_t frame_time_to_deadline_delta() const { return at<4>().as_int64(); }
+ bool has_now() const { return at<5>().valid(); }
+ int64_t now() const { return at<5>().as_int64(); }
+ bool has_frame_time() const { return at<6>().valid(); }
+ int64_t frame_time() const { return at<6>().as_int64(); }
+ bool has_deadline() const { return at<7>().valid(); }
+ int64_t deadline() const { return at<7>().as_int64(); }
+};
+
+class BeginImplFrameArgs_TimestampsInUs : public ::protozero::Message {
+ public:
+ using Decoder = BeginImplFrameArgs_TimestampsInUs_Decoder;
+ enum : int32_t {
+ kIntervalDeltaFieldNumber = 1,
+ kNowToDeadlineDeltaFieldNumber = 2,
+ kFrameTimeToNowDeltaFieldNumber = 3,
+ kFrameTimeToDeadlineDeltaFieldNumber = 4,
+ kNowFieldNumber = 5,
+ kFrameTimeFieldNumber = 6,
+ kDeadlineFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BeginImplFrameArgs.TimestampsInUs"; }
+
+
+ using FieldMetadata_IntervalDelta =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs_TimestampsInUs>;
+
+ static constexpr FieldMetadata_IntervalDelta kIntervalDelta{};
+ void set_interval_delta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntervalDelta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NowToDeadlineDelta =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs_TimestampsInUs>;
+
+ static constexpr FieldMetadata_NowToDeadlineDelta kNowToDeadlineDelta{};
+ void set_now_to_deadline_delta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NowToDeadlineDelta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameTimeToNowDelta =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs_TimestampsInUs>;
+
+ static constexpr FieldMetadata_FrameTimeToNowDelta kFrameTimeToNowDelta{};
+ void set_frame_time_to_now_delta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameTimeToNowDelta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameTimeToDeadlineDelta =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs_TimestampsInUs>;
+
+ static constexpr FieldMetadata_FrameTimeToDeadlineDelta kFrameTimeToDeadlineDelta{};
+ void set_frame_time_to_deadline_delta(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameTimeToDeadlineDelta::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Now =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs_TimestampsInUs>;
+
+ static constexpr FieldMetadata_Now kNow{};
+ void set_now(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Now::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameTime =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs_TimestampsInUs>;
+
+ static constexpr FieldMetadata_FrameTime kFrameTime{};
+ void set_frame_time(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameTime::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Deadline =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginImplFrameArgs_TimestampsInUs>;
+
+ static constexpr FieldMetadata_Deadline kDeadline{};
+ void set_deadline(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Deadline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class BeginFrameArgs_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/12, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BeginFrameArgs_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BeginFrameArgs_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BeginFrameArgs_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_type() const { return at<1>().valid(); }
+ int32_t type() const { return at<1>().as_int32(); }
+ bool has_source_id() const { return at<2>().valid(); }
+ uint64_t source_id() const { return at<2>().as_uint64(); }
+ bool has_sequence_number() const { return at<3>().valid(); }
+ uint64_t sequence_number() const { return at<3>().as_uint64(); }
+ bool has_frame_time_us() const { return at<4>().valid(); }
+ int64_t frame_time_us() const { return at<4>().as_int64(); }
+ bool has_deadline_us() const { return at<5>().valid(); }
+ int64_t deadline_us() const { return at<5>().as_int64(); }
+ bool has_interval_delta_us() const { return at<6>().valid(); }
+ int64_t interval_delta_us() const { return at<6>().as_int64(); }
+ bool has_on_critical_path() const { return at<7>().valid(); }
+ bool on_critical_path() const { return at<7>().as_bool(); }
+ bool has_animate_only() const { return at<8>().valid(); }
+ bool animate_only() const { return at<8>().as_bool(); }
+ bool has_source_location_iid() const { return at<9>().valid(); }
+ uint64_t source_location_iid() const { return at<9>().as_uint64(); }
+ bool has_source_location() const { return at<10>().valid(); }
+ ::protozero::ConstBytes source_location() const { return at<10>().as_bytes(); }
+ bool has_frames_throttled_since_last() const { return at<12>().valid(); }
+ int64_t frames_throttled_since_last() const { return at<12>().as_int64(); }
+};
+
+class BeginFrameArgs : public ::protozero::Message {
+ public:
+ using Decoder = BeginFrameArgs_Decoder;
+ enum : int32_t {
+ kTypeFieldNumber = 1,
+ kSourceIdFieldNumber = 2,
+ kSequenceNumberFieldNumber = 3,
+ kFrameTimeUsFieldNumber = 4,
+ kDeadlineUsFieldNumber = 5,
+ kIntervalDeltaUsFieldNumber = 6,
+ kOnCriticalPathFieldNumber = 7,
+ kAnimateOnlyFieldNumber = 8,
+ kSourceLocationIidFieldNumber = 9,
+ kSourceLocationFieldNumber = 10,
+ kFramesThrottledSinceLastFieldNumber = 12,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BeginFrameArgs"; }
+
+
+ using BeginFrameArgsType = ::perfetto::protos::pbzero::BeginFrameArgs_BeginFrameArgsType;
+ static inline const char* BeginFrameArgsType_Name(BeginFrameArgsType value) {
+ return ::perfetto::protos::pbzero::BeginFrameArgs_BeginFrameArgsType_Name(value);
+ }
+ static inline const BeginFrameArgsType BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED = BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED;
+ static inline const BeginFrameArgsType BEGIN_FRAME_ARGS_TYPE_INVALID = BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_INVALID;
+ static inline const BeginFrameArgsType BEGIN_FRAME_ARGS_TYPE_NORMAL = BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_NORMAL;
+ static inline const BeginFrameArgsType BEGIN_FRAME_ARGS_TYPE_MISSED = BeginFrameArgsType::BEGIN_FRAME_ARGS_TYPE_MISSED;
+
+ using FieldMetadata_Type =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ BeginFrameArgs_BeginFrameArgsType,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_Type kType{};
+ void set_type(BeginFrameArgs_BeginFrameArgsType value) {
+ static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SourceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_SourceId kSourceId{};
+ void set_source_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SequenceNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_SequenceNumber kSequenceNumber{};
+ void set_sequence_number(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SequenceNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameTimeUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_FrameTimeUs kFrameTimeUs{};
+ void set_frame_time_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameTimeUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeadlineUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_DeadlineUs kDeadlineUs{};
+ void set_deadline_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeadlineUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntervalDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_IntervalDeltaUs kIntervalDeltaUs{};
+ void set_interval_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntervalDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OnCriticalPath =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_OnCriticalPath kOnCriticalPath{};
+ void set_on_critical_path(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_OnCriticalPath::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AnimateOnly =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_AnimateOnly kAnimateOnly{};
+ void set_animate_only(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AnimateOnly::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SourceLocationIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_SourceLocationIid kSourceLocationIid{};
+ void set_source_location_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceLocationIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SourceLocation =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SourceLocation,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_SourceLocation kSourceLocation{};
+ template <typename T = SourceLocation> T* set_source_location() {
+ return BeginNestedMessage<T>(10);
+ }
+
+
+ using FieldMetadata_FramesThrottledSinceLast =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BeginFrameArgs>;
+
+ static constexpr FieldMetadata_FramesThrottledSinceLast kFramesThrottledSinceLast{};
+ void set_frames_throttled_since_last(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FramesThrottledSinceLast::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeCompositorStateMachine_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeCompositorStateMachine_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeCompositorStateMachine_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeCompositorStateMachine_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_major_state() const { return at<1>().valid(); }
+ ::protozero::ConstBytes major_state() const { return at<1>().as_bytes(); }
+ bool has_minor_state() const { return at<2>().valid(); }
+ ::protozero::ConstBytes minor_state() const { return at<2>().as_bytes(); }
+};
+
+class ChromeCompositorStateMachine : public ::protozero::Message {
+ public:
+ using Decoder = ChromeCompositorStateMachine_Decoder;
+ enum : int32_t {
+ kMajorStateFieldNumber = 1,
+ kMinorStateFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeCompositorStateMachine"; }
+
+ using MajorState = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState;
+ using MinorState = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState;
+
+ using FieldMetadata_MajorState =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeCompositorStateMachine_MajorState,
+ ChromeCompositorStateMachine>;
+
+ static constexpr FieldMetadata_MajorState kMajorState{};
+ template <typename T = ChromeCompositorStateMachine_MajorState> T* set_major_state() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_MinorState =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeCompositorStateMachine_MinorState,
+ ChromeCompositorStateMachine>;
+
+ static constexpr FieldMetadata_MinorState kMinorState{};
+ template <typename T = ChromeCompositorStateMachine_MinorState> T* set_minor_state() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class ChromeCompositorStateMachine_MinorState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/46, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeCompositorStateMachine_MinorState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeCompositorStateMachine_MinorState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeCompositorStateMachine_MinorState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_commit_count() const { return at<1>().valid(); }
+ int32_t commit_count() const { return at<1>().as_int32(); }
+ bool has_current_frame_number() const { return at<2>().valid(); }
+ int32_t current_frame_number() const { return at<2>().as_int32(); }
+ bool has_last_frame_number_submit_performed() const { return at<3>().valid(); }
+ int32_t last_frame_number_submit_performed() const { return at<3>().as_int32(); }
+ bool has_last_frame_number_draw_performed() const { return at<4>().valid(); }
+ int32_t last_frame_number_draw_performed() const { return at<4>().as_int32(); }
+ bool has_last_frame_number_begin_main_frame_sent() const { return at<5>().valid(); }
+ int32_t last_frame_number_begin_main_frame_sent() const { return at<5>().as_int32(); }
+ bool has_did_draw() const { return at<6>().valid(); }
+ bool did_draw() const { return at<6>().as_bool(); }
+ bool has_did_send_begin_main_frame_for_current_frame() const { return at<7>().valid(); }
+ bool did_send_begin_main_frame_for_current_frame() const { return at<7>().as_bool(); }
+ bool has_did_notify_begin_main_frame_not_expected_until() const { return at<8>().valid(); }
+ bool did_notify_begin_main_frame_not_expected_until() const { return at<8>().as_bool(); }
+ bool has_did_notify_begin_main_frame_not_expected_soon() const { return at<9>().valid(); }
+ bool did_notify_begin_main_frame_not_expected_soon() const { return at<9>().as_bool(); }
+ bool has_wants_begin_main_frame_not_expected() const { return at<10>().valid(); }
+ bool wants_begin_main_frame_not_expected() const { return at<10>().as_bool(); }
+ bool has_did_commit_during_frame() const { return at<11>().valid(); }
+ bool did_commit_during_frame() const { return at<11>().as_bool(); }
+ bool has_did_invalidate_layer_tree_frame_sink() const { return at<12>().valid(); }
+ bool did_invalidate_layer_tree_frame_sink() const { return at<12>().as_bool(); }
+ bool has_did_perform_impl_side_invalidaion() const { return at<13>().valid(); }
+ bool did_perform_impl_side_invalidaion() const { return at<13>().as_bool(); }
+ bool has_did_prepare_tiles() const { return at<14>().valid(); }
+ bool did_prepare_tiles() const { return at<14>().as_bool(); }
+ bool has_consecutive_checkerboard_animations() const { return at<15>().valid(); }
+ int32_t consecutive_checkerboard_animations() const { return at<15>().as_int32(); }
+ bool has_pending_submit_frames() const { return at<16>().valid(); }
+ int32_t pending_submit_frames() const { return at<16>().as_int32(); }
+ bool has_submit_frames_with_current_layer_tree_frame_sink() const { return at<17>().valid(); }
+ int32_t submit_frames_with_current_layer_tree_frame_sink() const { return at<17>().as_int32(); }
+ bool has_needs_redraw() const { return at<18>().valid(); }
+ bool needs_redraw() const { return at<18>().as_bool(); }
+ bool has_needs_prepare_tiles() const { return at<19>().valid(); }
+ bool needs_prepare_tiles() const { return at<19>().as_bool(); }
+ bool has_needs_begin_main_frame() const { return at<20>().valid(); }
+ bool needs_begin_main_frame() const { return at<20>().as_bool(); }
+ bool has_needs_one_begin_impl_frame() const { return at<21>().valid(); }
+ bool needs_one_begin_impl_frame() const { return at<21>().as_bool(); }
+ bool has_visible() const { return at<22>().valid(); }
+ bool visible() const { return at<22>().as_bool(); }
+ bool has_begin_frame_source_paused() const { return at<23>().valid(); }
+ bool begin_frame_source_paused() const { return at<23>().as_bool(); }
+ bool has_can_draw() const { return at<24>().valid(); }
+ bool can_draw() const { return at<24>().as_bool(); }
+ bool has_resourceless_draw() const { return at<25>().valid(); }
+ bool resourceless_draw() const { return at<25>().as_bool(); }
+ bool has_has_pending_tree() const { return at<26>().valid(); }
+ bool has_pending_tree() const { return at<26>().as_bool(); }
+ bool has_pending_tree_is_ready_for_activation() const { return at<27>().valid(); }
+ bool pending_tree_is_ready_for_activation() const { return at<27>().as_bool(); }
+ bool has_active_tree_needs_first_draw() const { return at<28>().valid(); }
+ bool active_tree_needs_first_draw() const { return at<28>().as_bool(); }
+ bool has_active_tree_is_ready_to_draw() const { return at<29>().valid(); }
+ bool active_tree_is_ready_to_draw() const { return at<29>().as_bool(); }
+ bool has_did_create_and_initialize_first_layer_tree_frame_sink() const { return at<30>().valid(); }
+ bool did_create_and_initialize_first_layer_tree_frame_sink() const { return at<30>().as_bool(); }
+ bool has_tree_priority() const { return at<31>().valid(); }
+ int32_t tree_priority() const { return at<31>().as_int32(); }
+ bool has_scroll_handler_state() const { return at<32>().valid(); }
+ int32_t scroll_handler_state() const { return at<32>().as_int32(); }
+ bool has_critical_begin_main_frame_to_activate_is_fast() const { return at<33>().valid(); }
+ bool critical_begin_main_frame_to_activate_is_fast() const { return at<33>().as_bool(); }
+ bool has_main_thread_missed_last_deadline() const { return at<34>().valid(); }
+ bool main_thread_missed_last_deadline() const { return at<34>().as_bool(); }
+ bool has_video_needs_begin_frames() const { return at<36>().valid(); }
+ bool video_needs_begin_frames() const { return at<36>().as_bool(); }
+ bool has_defer_begin_main_frame() const { return at<37>().valid(); }
+ bool defer_begin_main_frame() const { return at<37>().as_bool(); }
+ bool has_last_commit_had_no_updates() const { return at<38>().valid(); }
+ bool last_commit_had_no_updates() const { return at<38>().as_bool(); }
+ bool has_did_draw_in_last_frame() const { return at<39>().valid(); }
+ bool did_draw_in_last_frame() const { return at<39>().as_bool(); }
+ bool has_did_submit_in_last_frame() const { return at<40>().valid(); }
+ bool did_submit_in_last_frame() const { return at<40>().as_bool(); }
+ bool has_needs_impl_side_invalidation() const { return at<41>().valid(); }
+ bool needs_impl_side_invalidation() const { return at<41>().as_bool(); }
+ bool has_current_pending_tree_is_impl_side() const { return at<42>().valid(); }
+ bool current_pending_tree_is_impl_side() const { return at<42>().as_bool(); }
+ bool has_previous_pending_tree_was_impl_side() const { return at<43>().valid(); }
+ bool previous_pending_tree_was_impl_side() const { return at<43>().as_bool(); }
+ bool has_processing_animation_worklets_for_active_tree() const { return at<44>().valid(); }
+ bool processing_animation_worklets_for_active_tree() const { return at<44>().as_bool(); }
+ bool has_processing_animation_worklets_for_pending_tree() const { return at<45>().valid(); }
+ bool processing_animation_worklets_for_pending_tree() const { return at<45>().as_bool(); }
+ bool has_processing_paint_worklets_for_pending_tree() const { return at<46>().valid(); }
+ bool processing_paint_worklets_for_pending_tree() const { return at<46>().as_bool(); }
+};
+
+class ChromeCompositorStateMachine_MinorState : public ::protozero::Message {
+ public:
+ using Decoder = ChromeCompositorStateMachine_MinorState_Decoder;
+ enum : int32_t {
+ kCommitCountFieldNumber = 1,
+ kCurrentFrameNumberFieldNumber = 2,
+ kLastFrameNumberSubmitPerformedFieldNumber = 3,
+ kLastFrameNumberDrawPerformedFieldNumber = 4,
+ kLastFrameNumberBeginMainFrameSentFieldNumber = 5,
+ kDidDrawFieldNumber = 6,
+ kDidSendBeginMainFrameForCurrentFrameFieldNumber = 7,
+ kDidNotifyBeginMainFrameNotExpectedUntilFieldNumber = 8,
+ kDidNotifyBeginMainFrameNotExpectedSoonFieldNumber = 9,
+ kWantsBeginMainFrameNotExpectedFieldNumber = 10,
+ kDidCommitDuringFrameFieldNumber = 11,
+ kDidInvalidateLayerTreeFrameSinkFieldNumber = 12,
+ kDidPerformImplSideInvalidaionFieldNumber = 13,
+ kDidPrepareTilesFieldNumber = 14,
+ kConsecutiveCheckerboardAnimationsFieldNumber = 15,
+ kPendingSubmitFramesFieldNumber = 16,
+ kSubmitFramesWithCurrentLayerTreeFrameSinkFieldNumber = 17,
+ kNeedsRedrawFieldNumber = 18,
+ kNeedsPrepareTilesFieldNumber = 19,
+ kNeedsBeginMainFrameFieldNumber = 20,
+ kNeedsOneBeginImplFrameFieldNumber = 21,
+ kVisibleFieldNumber = 22,
+ kBeginFrameSourcePausedFieldNumber = 23,
+ kCanDrawFieldNumber = 24,
+ kResourcelessDrawFieldNumber = 25,
+ kHasPendingTreeFieldNumber = 26,
+ kPendingTreeIsReadyForActivationFieldNumber = 27,
+ kActiveTreeNeedsFirstDrawFieldNumber = 28,
+ kActiveTreeIsReadyToDrawFieldNumber = 29,
+ kDidCreateAndInitializeFirstLayerTreeFrameSinkFieldNumber = 30,
+ kTreePriorityFieldNumber = 31,
+ kScrollHandlerStateFieldNumber = 32,
+ kCriticalBeginMainFrameToActivateIsFastFieldNumber = 33,
+ kMainThreadMissedLastDeadlineFieldNumber = 34,
+ kVideoNeedsBeginFramesFieldNumber = 36,
+ kDeferBeginMainFrameFieldNumber = 37,
+ kLastCommitHadNoUpdatesFieldNumber = 38,
+ kDidDrawInLastFrameFieldNumber = 39,
+ kDidSubmitInLastFrameFieldNumber = 40,
+ kNeedsImplSideInvalidationFieldNumber = 41,
+ kCurrentPendingTreeIsImplSideFieldNumber = 42,
+ kPreviousPendingTreeWasImplSideFieldNumber = 43,
+ kProcessingAnimationWorkletsForActiveTreeFieldNumber = 44,
+ kProcessingAnimationWorkletsForPendingTreeFieldNumber = 45,
+ kProcessingPaintWorkletsForPendingTreeFieldNumber = 46,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeCompositorStateMachine.MinorState"; }
+
+
+ using TreePriority = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_TreePriority;
+ static inline const char* TreePriority_Name(TreePriority value) {
+ return ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_TreePriority_Name(value);
+ }
+
+ using ScrollHandlerState = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_ScrollHandlerState;
+ static inline const char* ScrollHandlerState_Name(ScrollHandlerState value) {
+ return ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MinorState_ScrollHandlerState_Name(value);
+ }
+ static inline const TreePriority TREE_PRIORITY_UNSPECIFIED = TreePriority::TREE_PRIORITY_UNSPECIFIED;
+ static inline const TreePriority TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES = TreePriority::TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES;
+ static inline const TreePriority TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY = TreePriority::TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY;
+ static inline const TreePriority TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY = TreePriority::TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY;
+ static inline const ScrollHandlerState SCROLL_HANDLER_UNSPECIFIED = ScrollHandlerState::SCROLL_HANDLER_UNSPECIFIED;
+ static inline const ScrollHandlerState SCROLL_AFFECTS_SCROLL_HANDLER = ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER;
+ static inline const ScrollHandlerState SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER = ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
+
+ using FieldMetadata_CommitCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_CommitCount kCommitCount{};
+ void set_commit_count(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CommitCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrentFrameNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_CurrentFrameNumber kCurrentFrameNumber{};
+ void set_current_frame_number(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrentFrameNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LastFrameNumberSubmitPerformed =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_LastFrameNumberSubmitPerformed kLastFrameNumberSubmitPerformed{};
+ void set_last_frame_number_submit_performed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LastFrameNumberSubmitPerformed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LastFrameNumberDrawPerformed =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_LastFrameNumberDrawPerformed kLastFrameNumberDrawPerformed{};
+ void set_last_frame_number_draw_performed(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LastFrameNumberDrawPerformed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LastFrameNumberBeginMainFrameSent =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_LastFrameNumberBeginMainFrameSent kLastFrameNumberBeginMainFrameSent{};
+ void set_last_frame_number_begin_main_frame_sent(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LastFrameNumberBeginMainFrameSent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidDraw =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidDraw kDidDraw{};
+ void set_did_draw(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidDraw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidSendBeginMainFrameForCurrentFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidSendBeginMainFrameForCurrentFrame kDidSendBeginMainFrameForCurrentFrame{};
+ void set_did_send_begin_main_frame_for_current_frame(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidSendBeginMainFrameForCurrentFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidNotifyBeginMainFrameNotExpectedUntil =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidNotifyBeginMainFrameNotExpectedUntil kDidNotifyBeginMainFrameNotExpectedUntil{};
+ void set_did_notify_begin_main_frame_not_expected_until(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidNotifyBeginMainFrameNotExpectedUntil::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidNotifyBeginMainFrameNotExpectedSoon =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidNotifyBeginMainFrameNotExpectedSoon kDidNotifyBeginMainFrameNotExpectedSoon{};
+ void set_did_notify_begin_main_frame_not_expected_soon(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidNotifyBeginMainFrameNotExpectedSoon::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WantsBeginMainFrameNotExpected =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_WantsBeginMainFrameNotExpected kWantsBeginMainFrameNotExpected{};
+ void set_wants_begin_main_frame_not_expected(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_WantsBeginMainFrameNotExpected::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidCommitDuringFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidCommitDuringFrame kDidCommitDuringFrame{};
+ void set_did_commit_during_frame(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidCommitDuringFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidInvalidateLayerTreeFrameSink =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidInvalidateLayerTreeFrameSink kDidInvalidateLayerTreeFrameSink{};
+ void set_did_invalidate_layer_tree_frame_sink(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidInvalidateLayerTreeFrameSink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidPerformImplSideInvalidaion =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidPerformImplSideInvalidaion kDidPerformImplSideInvalidaion{};
+ void set_did_perform_impl_side_invalidaion(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidPerformImplSideInvalidaion::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidPrepareTiles =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidPrepareTiles kDidPrepareTiles{};
+ void set_did_prepare_tiles(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidPrepareTiles::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ConsecutiveCheckerboardAnimations =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ConsecutiveCheckerboardAnimations kConsecutiveCheckerboardAnimations{};
+ void set_consecutive_checkerboard_animations(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ConsecutiveCheckerboardAnimations::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PendingSubmitFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_PendingSubmitFrames kPendingSubmitFrames{};
+ void set_pending_submit_frames(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PendingSubmitFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SubmitFramesWithCurrentLayerTreeFrameSink =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_SubmitFramesWithCurrentLayerTreeFrameSink kSubmitFramesWithCurrentLayerTreeFrameSink{};
+ void set_submit_frames_with_current_layer_tree_frame_sink(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SubmitFramesWithCurrentLayerTreeFrameSink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NeedsRedraw =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_NeedsRedraw kNeedsRedraw{};
+ void set_needs_redraw(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NeedsRedraw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NeedsPrepareTiles =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_NeedsPrepareTiles kNeedsPrepareTiles{};
+ void set_needs_prepare_tiles(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NeedsPrepareTiles::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NeedsBeginMainFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_NeedsBeginMainFrame kNeedsBeginMainFrame{};
+ void set_needs_begin_main_frame(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NeedsBeginMainFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NeedsOneBeginImplFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_NeedsOneBeginImplFrame kNeedsOneBeginImplFrame{};
+ void set_needs_one_begin_impl_frame(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NeedsOneBeginImplFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Visible =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_Visible kVisible{};
+ void set_visible(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Visible::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BeginFrameSourcePaused =
+ ::protozero::proto_utils::FieldMetadata<
+ 23,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_BeginFrameSourcePaused kBeginFrameSourcePaused{};
+ void set_begin_frame_source_paused(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BeginFrameSourcePaused::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CanDraw =
+ ::protozero::proto_utils::FieldMetadata<
+ 24,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_CanDraw kCanDraw{};
+ void set_can_draw(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CanDraw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ResourcelessDraw =
+ ::protozero::proto_utils::FieldMetadata<
+ 25,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ResourcelessDraw kResourcelessDraw{};
+ void set_resourceless_draw(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ResourcelessDraw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasPendingTree =
+ ::protozero::proto_utils::FieldMetadata<
+ 26,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_HasPendingTree kHasPendingTree{};
+ void set_has_pending_tree(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasPendingTree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PendingTreeIsReadyForActivation =
+ ::protozero::proto_utils::FieldMetadata<
+ 27,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_PendingTreeIsReadyForActivation kPendingTreeIsReadyForActivation{};
+ void set_pending_tree_is_ready_for_activation(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PendingTreeIsReadyForActivation::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ActiveTreeNeedsFirstDraw =
+ ::protozero::proto_utils::FieldMetadata<
+ 28,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ActiveTreeNeedsFirstDraw kActiveTreeNeedsFirstDraw{};
+ void set_active_tree_needs_first_draw(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActiveTreeNeedsFirstDraw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ActiveTreeIsReadyToDraw =
+ ::protozero::proto_utils::FieldMetadata<
+ 29,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ActiveTreeIsReadyToDraw kActiveTreeIsReadyToDraw{};
+ void set_active_tree_is_ready_to_draw(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActiveTreeIsReadyToDraw::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidCreateAndInitializeFirstLayerTreeFrameSink =
+ ::protozero::proto_utils::FieldMetadata<
+ 30,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidCreateAndInitializeFirstLayerTreeFrameSink kDidCreateAndInitializeFirstLayerTreeFrameSink{};
+ void set_did_create_and_initialize_first_layer_tree_frame_sink(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidCreateAndInitializeFirstLayerTreeFrameSink::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TreePriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 31,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorStateMachine_MinorState_TreePriority,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_TreePriority kTreePriority{};
+ void set_tree_priority(ChromeCompositorStateMachine_MinorState_TreePriority value) {
+ static constexpr uint32_t field_id = FieldMetadata_TreePriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScrollHandlerState =
+ ::protozero::proto_utils::FieldMetadata<
+ 32,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorStateMachine_MinorState_ScrollHandlerState,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ScrollHandlerState kScrollHandlerState{};
+ void set_scroll_handler_state(ChromeCompositorStateMachine_MinorState_ScrollHandlerState value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScrollHandlerState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CriticalBeginMainFrameToActivateIsFast =
+ ::protozero::proto_utils::FieldMetadata<
+ 33,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_CriticalBeginMainFrameToActivateIsFast kCriticalBeginMainFrameToActivateIsFast{};
+ void set_critical_begin_main_frame_to_activate_is_fast(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CriticalBeginMainFrameToActivateIsFast::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MainThreadMissedLastDeadline =
+ ::protozero::proto_utils::FieldMetadata<
+ 34,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_MainThreadMissedLastDeadline kMainThreadMissedLastDeadline{};
+ void set_main_thread_missed_last_deadline(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_MainThreadMissedLastDeadline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VideoNeedsBeginFrames =
+ ::protozero::proto_utils::FieldMetadata<
+ 36,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_VideoNeedsBeginFrames kVideoNeedsBeginFrames{};
+ void set_video_needs_begin_frames(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_VideoNeedsBeginFrames::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeferBeginMainFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 37,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DeferBeginMainFrame kDeferBeginMainFrame{};
+ void set_defer_begin_main_frame(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeferBeginMainFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LastCommitHadNoUpdates =
+ ::protozero::proto_utils::FieldMetadata<
+ 38,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_LastCommitHadNoUpdates kLastCommitHadNoUpdates{};
+ void set_last_commit_had_no_updates(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_LastCommitHadNoUpdates::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidDrawInLastFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 39,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidDrawInLastFrame kDidDrawInLastFrame{};
+ void set_did_draw_in_last_frame(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidDrawInLastFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DidSubmitInLastFrame =
+ ::protozero::proto_utils::FieldMetadata<
+ 40,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_DidSubmitInLastFrame kDidSubmitInLastFrame{};
+ void set_did_submit_in_last_frame(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_DidSubmitInLastFrame::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NeedsImplSideInvalidation =
+ ::protozero::proto_utils::FieldMetadata<
+ 41,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_NeedsImplSideInvalidation kNeedsImplSideInvalidation{};
+ void set_needs_impl_side_invalidation(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_NeedsImplSideInvalidation::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrentPendingTreeIsImplSide =
+ ::protozero::proto_utils::FieldMetadata<
+ 42,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_CurrentPendingTreeIsImplSide kCurrentPendingTreeIsImplSide{};
+ void set_current_pending_tree_is_impl_side(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrentPendingTreeIsImplSide::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PreviousPendingTreeWasImplSide =
+ ::protozero::proto_utils::FieldMetadata<
+ 43,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_PreviousPendingTreeWasImplSide kPreviousPendingTreeWasImplSide{};
+ void set_previous_pending_tree_was_impl_side(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PreviousPendingTreeWasImplSide::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessingAnimationWorkletsForActiveTree =
+ ::protozero::proto_utils::FieldMetadata<
+ 44,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ProcessingAnimationWorkletsForActiveTree kProcessingAnimationWorkletsForActiveTree{};
+ void set_processing_animation_worklets_for_active_tree(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessingAnimationWorkletsForActiveTree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessingAnimationWorkletsForPendingTree =
+ ::protozero::proto_utils::FieldMetadata<
+ 45,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ProcessingAnimationWorkletsForPendingTree kProcessingAnimationWorkletsForPendingTree{};
+ void set_processing_animation_worklets_for_pending_tree(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessingAnimationWorkletsForPendingTree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessingPaintWorkletsForPendingTree =
+ ::protozero::proto_utils::FieldMetadata<
+ 46,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorStateMachine_MinorState>;
+
+ static constexpr FieldMetadata_ProcessingPaintWorkletsForPendingTree kProcessingPaintWorkletsForPendingTree{};
+ void set_processing_paint_worklets_for_pending_tree(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessingPaintWorkletsForPendingTree::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeCompositorStateMachine_MajorState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeCompositorStateMachine_MajorState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeCompositorStateMachine_MajorState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeCompositorStateMachine_MajorState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_next_action() const { return at<1>().valid(); }
+ int32_t next_action() const { return at<1>().as_int32(); }
+ bool has_begin_impl_frame_state() const { return at<2>().valid(); }
+ int32_t begin_impl_frame_state() const { return at<2>().as_int32(); }
+ bool has_begin_main_frame_state() const { return at<3>().valid(); }
+ int32_t begin_main_frame_state() const { return at<3>().as_int32(); }
+ bool has_layer_tree_frame_sink_state() const { return at<4>().valid(); }
+ int32_t layer_tree_frame_sink_state() const { return at<4>().as_int32(); }
+ bool has_forced_redraw_state() const { return at<5>().valid(); }
+ int32_t forced_redraw_state() const { return at<5>().as_int32(); }
+};
+
+class ChromeCompositorStateMachine_MajorState : public ::protozero::Message {
+ public:
+ using Decoder = ChromeCompositorStateMachine_MajorState_Decoder;
+ enum : int32_t {
+ kNextActionFieldNumber = 1,
+ kBeginImplFrameStateFieldNumber = 2,
+ kBeginMainFrameStateFieldNumber = 3,
+ kLayerTreeFrameSinkStateFieldNumber = 4,
+ kForcedRedrawStateFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeCompositorStateMachine.MajorState"; }
+
+
+ using BeginImplFrameState = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginImplFrameState;
+ static inline const char* BeginImplFrameState_Name(BeginImplFrameState value) {
+ return ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginImplFrameState_Name(value);
+ }
+
+ using BeginMainFrameState = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginMainFrameState;
+ static inline const char* BeginMainFrameState_Name(BeginMainFrameState value) {
+ return ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_BeginMainFrameState_Name(value);
+ }
+
+ using LayerTreeFrameSinkState = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState;
+ static inline const char* LayerTreeFrameSinkState_Name(LayerTreeFrameSinkState value) {
+ return ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_Name(value);
+ }
+
+ using ForcedRedrawOnTimeoutState = ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState;
+ static inline const char* ForcedRedrawOnTimeoutState_Name(ForcedRedrawOnTimeoutState value) {
+ return ::perfetto::protos::pbzero::ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_Name(value);
+ }
+ static inline const BeginImplFrameState BEGIN_IMPL_FRAME_UNSPECIFIED = BeginImplFrameState::BEGIN_IMPL_FRAME_UNSPECIFIED;
+ static inline const BeginImplFrameState BEGIN_IMPL_FRAME_IDLE = BeginImplFrameState::BEGIN_IMPL_FRAME_IDLE;
+ static inline const BeginImplFrameState BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME = BeginImplFrameState::BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME;
+ static inline const BeginImplFrameState BEGIN_IMPL_FRAME_INSIDE_DEADLINE = BeginImplFrameState::BEGIN_IMPL_FRAME_INSIDE_DEADLINE;
+ static inline const BeginMainFrameState BEGIN_MAIN_FRAME_UNSPECIFIED = BeginMainFrameState::BEGIN_MAIN_FRAME_UNSPECIFIED;
+ static inline const BeginMainFrameState BEGIN_MAIN_FRAME_IDLE = BeginMainFrameState::BEGIN_MAIN_FRAME_IDLE;
+ static inline const BeginMainFrameState BEGIN_MAIN_FRAME_SENT = BeginMainFrameState::BEGIN_MAIN_FRAME_SENT;
+ static inline const BeginMainFrameState BEGIN_MAIN_FRAME_READY_TO_COMMIT = BeginMainFrameState::BEGIN_MAIN_FRAME_READY_TO_COMMIT;
+ static inline const LayerTreeFrameSinkState LAYER_TREE_FRAME_UNSPECIFIED = LayerTreeFrameSinkState::LAYER_TREE_FRAME_UNSPECIFIED;
+ static inline const LayerTreeFrameSinkState LAYER_TREE_FRAME_NONE = LayerTreeFrameSinkState::LAYER_TREE_FRAME_NONE;
+ static inline const LayerTreeFrameSinkState LAYER_TREE_FRAME_ACTIVE = LayerTreeFrameSinkState::LAYER_TREE_FRAME_ACTIVE;
+ static inline const LayerTreeFrameSinkState LAYER_TREE_FRAME_CREATING = LayerTreeFrameSinkState::LAYER_TREE_FRAME_CREATING;
+ static inline const LayerTreeFrameSinkState LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT = LayerTreeFrameSinkState::LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT;
+ static inline const LayerTreeFrameSinkState LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION = LayerTreeFrameSinkState::LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION;
+ static inline const ForcedRedrawOnTimeoutState FORCED_REDRAW_UNSPECIFIED = ForcedRedrawOnTimeoutState::FORCED_REDRAW_UNSPECIFIED;
+ static inline const ForcedRedrawOnTimeoutState FORCED_REDRAW_IDLE = ForcedRedrawOnTimeoutState::FORCED_REDRAW_IDLE;
+ static inline const ForcedRedrawOnTimeoutState FORCED_REDRAW_WAITING_FOR_COMMIT = ForcedRedrawOnTimeoutState::FORCED_REDRAW_WAITING_FOR_COMMIT;
+ static inline const ForcedRedrawOnTimeoutState FORCED_REDRAW_WAITING_FOR_ACTIVATION = ForcedRedrawOnTimeoutState::FORCED_REDRAW_WAITING_FOR_ACTIVATION;
+ static inline const ForcedRedrawOnTimeoutState FORCED_REDRAW_WAITING_FOR_DRAW = ForcedRedrawOnTimeoutState::FORCED_REDRAW_WAITING_FOR_DRAW;
+
+ using FieldMetadata_NextAction =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorSchedulerAction,
+ ChromeCompositorStateMachine_MajorState>;
+
+ static constexpr FieldMetadata_NextAction kNextAction{};
+ void set_next_action(ChromeCompositorSchedulerAction value) {
+ static constexpr uint32_t field_id = FieldMetadata_NextAction::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BeginImplFrameState =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorStateMachine_MajorState_BeginImplFrameState,
+ ChromeCompositorStateMachine_MajorState>;
+
+ static constexpr FieldMetadata_BeginImplFrameState kBeginImplFrameState{};
+ void set_begin_impl_frame_state(ChromeCompositorStateMachine_MajorState_BeginImplFrameState value) {
+ static constexpr uint32_t field_id = FieldMetadata_BeginImplFrameState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BeginMainFrameState =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorStateMachine_MajorState_BeginMainFrameState,
+ ChromeCompositorStateMachine_MajorState>;
+
+ static constexpr FieldMetadata_BeginMainFrameState kBeginMainFrameState{};
+ void set_begin_main_frame_state(ChromeCompositorStateMachine_MajorState_BeginMainFrameState value) {
+ static constexpr uint32_t field_id = FieldMetadata_BeginMainFrameState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerTreeFrameSinkState =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState,
+ ChromeCompositorStateMachine_MajorState>;
+
+ static constexpr FieldMetadata_LayerTreeFrameSinkState kLayerTreeFrameSinkState{};
+ void set_layer_tree_frame_sink_state(ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerTreeFrameSinkState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ForcedRedrawState =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState,
+ ChromeCompositorStateMachine_MajorState>;
+
+ static constexpr FieldMetadata_ForcedRedrawState kForcedRedrawState{};
+ void set_forced_redraw_state(ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState value) {
+ static constexpr uint32_t field_id = FieldMetadata_ForcedRedrawState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeCompositorSchedulerState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/17, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeCompositorSchedulerState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeCompositorSchedulerState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeCompositorSchedulerState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_state_machine() const { return at<1>().valid(); }
+ ::protozero::ConstBytes state_machine() const { return at<1>().as_bytes(); }
+ bool has_observing_begin_frame_source() const { return at<2>().valid(); }
+ bool observing_begin_frame_source() const { return at<2>().as_bool(); }
+ bool has_begin_impl_frame_deadline_task() const { return at<3>().valid(); }
+ bool begin_impl_frame_deadline_task() const { return at<3>().as_bool(); }
+ bool has_pending_begin_frame_task() const { return at<4>().valid(); }
+ bool pending_begin_frame_task() const { return at<4>().as_bool(); }
+ bool has_skipped_last_frame_missed_exceeded_deadline() const { return at<5>().valid(); }
+ bool skipped_last_frame_missed_exceeded_deadline() const { return at<5>().as_bool(); }
+ bool has_inside_action() const { return at<7>().valid(); }
+ int32_t inside_action() const { return at<7>().as_int32(); }
+ bool has_deadline_mode() const { return at<8>().valid(); }
+ int32_t deadline_mode() const { return at<8>().as_int32(); }
+ bool has_deadline_us() const { return at<9>().valid(); }
+ int64_t deadline_us() const { return at<9>().as_int64(); }
+ bool has_deadline_scheduled_at_us() const { return at<10>().valid(); }
+ int64_t deadline_scheduled_at_us() const { return at<10>().as_int64(); }
+ bool has_now_us() const { return at<11>().valid(); }
+ int64_t now_us() const { return at<11>().as_int64(); }
+ bool has_now_to_deadline_delta_us() const { return at<12>().valid(); }
+ int64_t now_to_deadline_delta_us() const { return at<12>().as_int64(); }
+ bool has_now_to_deadline_scheduled_at_delta_us() const { return at<13>().valid(); }
+ int64_t now_to_deadline_scheduled_at_delta_us() const { return at<13>().as_int64(); }
+ bool has_begin_impl_frame_args() const { return at<14>().valid(); }
+ ::protozero::ConstBytes begin_impl_frame_args() const { return at<14>().as_bytes(); }
+ bool has_begin_frame_observer_state() const { return at<15>().valid(); }
+ ::protozero::ConstBytes begin_frame_observer_state() const { return at<15>().as_bytes(); }
+ bool has_begin_frame_source_state() const { return at<16>().valid(); }
+ ::protozero::ConstBytes begin_frame_source_state() const { return at<16>().as_bytes(); }
+ bool has_compositor_timing_history() const { return at<17>().valid(); }
+ ::protozero::ConstBytes compositor_timing_history() const { return at<17>().as_bytes(); }
+};
+
+class ChromeCompositorSchedulerState : public ::protozero::Message {
+ public:
+ using Decoder = ChromeCompositorSchedulerState_Decoder;
+ enum : int32_t {
+ kStateMachineFieldNumber = 1,
+ kObservingBeginFrameSourceFieldNumber = 2,
+ kBeginImplFrameDeadlineTaskFieldNumber = 3,
+ kPendingBeginFrameTaskFieldNumber = 4,
+ kSkippedLastFrameMissedExceededDeadlineFieldNumber = 5,
+ kInsideActionFieldNumber = 7,
+ kDeadlineModeFieldNumber = 8,
+ kDeadlineUsFieldNumber = 9,
+ kDeadlineScheduledAtUsFieldNumber = 10,
+ kNowUsFieldNumber = 11,
+ kNowToDeadlineDeltaUsFieldNumber = 12,
+ kNowToDeadlineScheduledAtDeltaUsFieldNumber = 13,
+ kBeginImplFrameArgsFieldNumber = 14,
+ kBeginFrameObserverStateFieldNumber = 15,
+ kBeginFrameSourceStateFieldNumber = 16,
+ kCompositorTimingHistoryFieldNumber = 17,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeCompositorSchedulerState"; }
+
+
+ using BeginImplFrameDeadlineMode = ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode;
+ static inline const char* BeginImplFrameDeadlineMode_Name(BeginImplFrameDeadlineMode value) {
+ return ::perfetto::protos::pbzero::ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_Name(value);
+ }
+ static inline const BeginImplFrameDeadlineMode DEADLINE_MODE_UNSPECIFIED = BeginImplFrameDeadlineMode::DEADLINE_MODE_UNSPECIFIED;
+ static inline const BeginImplFrameDeadlineMode DEADLINE_MODE_NONE = BeginImplFrameDeadlineMode::DEADLINE_MODE_NONE;
+ static inline const BeginImplFrameDeadlineMode DEADLINE_MODE_IMMEDIATE = BeginImplFrameDeadlineMode::DEADLINE_MODE_IMMEDIATE;
+ static inline const BeginImplFrameDeadlineMode DEADLINE_MODE_REGULAR = BeginImplFrameDeadlineMode::DEADLINE_MODE_REGULAR;
+ static inline const BeginImplFrameDeadlineMode DEADLINE_MODE_LATE = BeginImplFrameDeadlineMode::DEADLINE_MODE_LATE;
+ static inline const BeginImplFrameDeadlineMode DEADLINE_MODE_BLOCKED = BeginImplFrameDeadlineMode::DEADLINE_MODE_BLOCKED;
+
+ using FieldMetadata_StateMachine =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeCompositorStateMachine,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_StateMachine kStateMachine{};
+ template <typename T = ChromeCompositorStateMachine> T* set_state_machine() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ObservingBeginFrameSource =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_ObservingBeginFrameSource kObservingBeginFrameSource{};
+ void set_observing_begin_frame_source(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ObservingBeginFrameSource::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BeginImplFrameDeadlineTask =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_BeginImplFrameDeadlineTask kBeginImplFrameDeadlineTask{};
+ void set_begin_impl_frame_deadline_task(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_BeginImplFrameDeadlineTask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PendingBeginFrameTask =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_PendingBeginFrameTask kPendingBeginFrameTask{};
+ void set_pending_begin_frame_task(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_PendingBeginFrameTask::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SkippedLastFrameMissedExceededDeadline =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_SkippedLastFrameMissedExceededDeadline kSkippedLastFrameMissedExceededDeadline{};
+ void set_skipped_last_frame_missed_exceeded_deadline(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SkippedLastFrameMissedExceededDeadline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_InsideAction =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorSchedulerAction,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_InsideAction kInsideAction{};
+ void set_inside_action(ChromeCompositorSchedulerAction value) {
+ static constexpr uint32_t field_id = FieldMetadata_InsideAction::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeadlineMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_DeadlineMode kDeadlineMode{};
+ void set_deadline_mode(ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeadlineMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeadlineUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_DeadlineUs kDeadlineUs{};
+ void set_deadline_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeadlineUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DeadlineScheduledAtUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_DeadlineScheduledAtUs kDeadlineScheduledAtUs{};
+ void set_deadline_scheduled_at_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeadlineScheduledAtUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NowUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_NowUs kNowUs{};
+ void set_now_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NowUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NowToDeadlineDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_NowToDeadlineDeltaUs kNowToDeadlineDeltaUs{};
+ void set_now_to_deadline_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NowToDeadlineDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NowToDeadlineScheduledAtDeltaUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_NowToDeadlineScheduledAtDeltaUs kNowToDeadlineScheduledAtDeltaUs{};
+ void set_now_to_deadline_scheduled_at_delta_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NowToDeadlineScheduledAtDeltaUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BeginImplFrameArgs =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginImplFrameArgs,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_BeginImplFrameArgs kBeginImplFrameArgs{};
+ template <typename T = BeginImplFrameArgs> T* set_begin_impl_frame_args() {
+ return BeginNestedMessage<T>(14);
+ }
+
+
+ using FieldMetadata_BeginFrameObserverState =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginFrameObserverState,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_BeginFrameObserverState kBeginFrameObserverState{};
+ template <typename T = BeginFrameObserverState> T* set_begin_frame_observer_state() {
+ return BeginNestedMessage<T>(15);
+ }
+
+
+ using FieldMetadata_BeginFrameSourceState =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ BeginFrameSourceState,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_BeginFrameSourceState kBeginFrameSourceState{};
+ template <typename T = BeginFrameSourceState> T* set_begin_frame_source_state() {
+ return BeginNestedMessage<T>(16);
+ }
+
+
+ using FieldMetadata_CompositorTimingHistory =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CompositorTimingHistory,
+ ChromeCompositorSchedulerState>;
+
+ static constexpr FieldMetadata_CompositorTimingHistory kCompositorTimingHistory{};
+ template <typename T = CompositorTimingHistory> T* set_compositor_timing_history() {
+ return BeginNestedMessage<T>(17);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_content_settings_event_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_CONTENT_SETTINGS_EVENT_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_CONTENT_SETTINGS_EVENT_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeContentSettingsEventInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeContentSettingsEventInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeContentSettingsEventInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeContentSettingsEventInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_number_of_exceptions() const { return at<1>().valid(); }
+ uint32_t number_of_exceptions() const { return at<1>().as_uint32(); }
+};
+
+class ChromeContentSettingsEventInfo : public ::protozero::Message {
+ public:
+ using Decoder = ChromeContentSettingsEventInfo_Decoder;
+ enum : int32_t {
+ kNumberOfExceptionsFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeContentSettingsEventInfo"; }
+
+
+ using FieldMetadata_NumberOfExceptions =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeContentSettingsEventInfo>;
+
+ static constexpr FieldMetadata_NumberOfExceptions kNumberOfExceptions{};
+ void set_number_of_exceptions(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumberOfExceptions::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_frame_reporter.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_FRAME_REPORTER_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_FRAME_REPORTER_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum FrameDropReason : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_FrameDropReason = perfetto_pbzero_enum_ChromeFrameReporter::FrameDropReason;
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum FrameType : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_FrameType = perfetto_pbzero_enum_ChromeFrameReporter::FrameType;
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum ScrollState : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_ScrollState = perfetto_pbzero_enum_ChromeFrameReporter::ScrollState;
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum State : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_State = perfetto_pbzero_enum_ChromeFrameReporter::State;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum State : int32_t {
+ STATE_NO_UPDATE_DESIRED = 0,
+ STATE_PRESENTED_ALL = 1,
+ STATE_PRESENTED_PARTIAL = 2,
+ STATE_DROPPED = 3,
+};
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_State = perfetto_pbzero_enum_ChromeFrameReporter::State;
+
+
+constexpr ChromeFrameReporter_State ChromeFrameReporter_State_MIN = ChromeFrameReporter_State::STATE_NO_UPDATE_DESIRED;
+constexpr ChromeFrameReporter_State ChromeFrameReporter_State_MAX = ChromeFrameReporter_State::STATE_DROPPED;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeFrameReporter_State_Name(::perfetto::protos::pbzero::ChromeFrameReporter_State value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_State::STATE_NO_UPDATE_DESIRED:
+ return "STATE_NO_UPDATE_DESIRED";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_State::STATE_PRESENTED_ALL:
+ return "STATE_PRESENTED_ALL";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_State::STATE_PRESENTED_PARTIAL:
+ return "STATE_PRESENTED_PARTIAL";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_State::STATE_DROPPED:
+ return "STATE_DROPPED";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum FrameDropReason : int32_t {
+ REASON_UNSPECIFIED = 0,
+ REASON_DISPLAY_COMPOSITOR = 1,
+ REASON_MAIN_THREAD = 2,
+ REASON_CLIENT_COMPOSITOR = 3,
+};
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_FrameDropReason = perfetto_pbzero_enum_ChromeFrameReporter::FrameDropReason;
+
+
+constexpr ChromeFrameReporter_FrameDropReason ChromeFrameReporter_FrameDropReason_MIN = ChromeFrameReporter_FrameDropReason::REASON_UNSPECIFIED;
+constexpr ChromeFrameReporter_FrameDropReason ChromeFrameReporter_FrameDropReason_MAX = ChromeFrameReporter_FrameDropReason::REASON_CLIENT_COMPOSITOR;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeFrameReporter_FrameDropReason_Name(::perfetto::protos::pbzero::ChromeFrameReporter_FrameDropReason value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_FrameDropReason::REASON_UNSPECIFIED:
+ return "REASON_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_FrameDropReason::REASON_DISPLAY_COMPOSITOR:
+ return "REASON_DISPLAY_COMPOSITOR";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_FrameDropReason::REASON_MAIN_THREAD:
+ return "REASON_MAIN_THREAD";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_FrameDropReason::REASON_CLIENT_COMPOSITOR:
+ return "REASON_CLIENT_COMPOSITOR";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum ScrollState : int32_t {
+ SCROLL_NONE = 0,
+ SCROLL_MAIN_THREAD = 1,
+ SCROLL_COMPOSITOR_THREAD = 2,
+ SCROLL_UNKNOWN = 3,
+};
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_ScrollState = perfetto_pbzero_enum_ChromeFrameReporter::ScrollState;
+
+
+constexpr ChromeFrameReporter_ScrollState ChromeFrameReporter_ScrollState_MIN = ChromeFrameReporter_ScrollState::SCROLL_NONE;
+constexpr ChromeFrameReporter_ScrollState ChromeFrameReporter_ScrollState_MAX = ChromeFrameReporter_ScrollState::SCROLL_UNKNOWN;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeFrameReporter_ScrollState_Name(::perfetto::protos::pbzero::ChromeFrameReporter_ScrollState value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_ScrollState::SCROLL_NONE:
+ return "SCROLL_NONE";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_ScrollState::SCROLL_MAIN_THREAD:
+ return "SCROLL_MAIN_THREAD";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_ScrollState::SCROLL_COMPOSITOR_THREAD:
+ return "SCROLL_COMPOSITOR_THREAD";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_ScrollState::SCROLL_UNKNOWN:
+ return "SCROLL_UNKNOWN";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeFrameReporter {
+enum FrameType : int32_t {
+ FORKED = 0,
+ BACKFILL = 1,
+};
+} // namespace perfetto_pbzero_enum_ChromeFrameReporter
+using ChromeFrameReporter_FrameType = perfetto_pbzero_enum_ChromeFrameReporter::FrameType;
+
+
+constexpr ChromeFrameReporter_FrameType ChromeFrameReporter_FrameType_MIN = ChromeFrameReporter_FrameType::FORKED;
+constexpr ChromeFrameReporter_FrameType ChromeFrameReporter_FrameType_MAX = ChromeFrameReporter_FrameType::BACKFILL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeFrameReporter_FrameType_Name(::perfetto::protos::pbzero::ChromeFrameReporter_FrameType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_FrameType::FORKED:
+ return "FORKED";
+
+ case ::perfetto::protos::pbzero::ChromeFrameReporter_FrameType::BACKFILL:
+ return "BACKFILL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeFrameReporter_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/14, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeFrameReporter_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeFrameReporter_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeFrameReporter_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_state() const { return at<1>().valid(); }
+ int32_t state() const { return at<1>().as_int32(); }
+ bool has_reason() const { return at<2>().valid(); }
+ int32_t reason() const { return at<2>().as_int32(); }
+ bool has_frame_source() const { return at<3>().valid(); }
+ uint64_t frame_source() const { return at<3>().as_uint64(); }
+ bool has_frame_sequence() const { return at<4>().valid(); }
+ uint64_t frame_sequence() const { return at<4>().as_uint64(); }
+ bool has_affects_smoothness() const { return at<5>().valid(); }
+ bool affects_smoothness() const { return at<5>().as_bool(); }
+ bool has_scroll_state() const { return at<6>().valid(); }
+ int32_t scroll_state() const { return at<6>().as_int32(); }
+ bool has_has_main_animation() const { return at<7>().valid(); }
+ bool has_main_animation() const { return at<7>().as_bool(); }
+ bool has_has_compositor_animation() const { return at<8>().valid(); }
+ bool has_compositor_animation() const { return at<8>().as_bool(); }
+ bool has_has_smooth_input_main() const { return at<9>().valid(); }
+ bool has_smooth_input_main() const { return at<9>().as_bool(); }
+ bool has_has_missing_content() const { return at<10>().valid(); }
+ bool has_missing_content() const { return at<10>().as_bool(); }
+ bool has_layer_tree_host_id() const { return at<11>().valid(); }
+ uint64_t layer_tree_host_id() const { return at<11>().as_uint64(); }
+ bool has_has_high_latency() const { return at<12>().valid(); }
+ bool has_high_latency() const { return at<12>().as_bool(); }
+ bool has_frame_type() const { return at<13>().valid(); }
+ int32_t frame_type() const { return at<13>().as_int32(); }
+ bool has_high_latency_contribution_stage() const { return at<14>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> high_latency_contribution_stage() const { return GetRepeated<::protozero::ConstChars>(14); }
+};
+
+class ChromeFrameReporter : public ::protozero::Message {
+ public:
+ using Decoder = ChromeFrameReporter_Decoder;
+ enum : int32_t {
+ kStateFieldNumber = 1,
+ kReasonFieldNumber = 2,
+ kFrameSourceFieldNumber = 3,
+ kFrameSequenceFieldNumber = 4,
+ kAffectsSmoothnessFieldNumber = 5,
+ kScrollStateFieldNumber = 6,
+ kHasMainAnimationFieldNumber = 7,
+ kHasCompositorAnimationFieldNumber = 8,
+ kHasSmoothInputMainFieldNumber = 9,
+ kHasMissingContentFieldNumber = 10,
+ kLayerTreeHostIdFieldNumber = 11,
+ kHasHighLatencyFieldNumber = 12,
+ kFrameTypeFieldNumber = 13,
+ kHighLatencyContributionStageFieldNumber = 14,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeFrameReporter"; }
+
+
+ using State = ::perfetto::protos::pbzero::ChromeFrameReporter_State;
+ static inline const char* State_Name(State value) {
+ return ::perfetto::protos::pbzero::ChromeFrameReporter_State_Name(value);
+ }
+
+ using FrameDropReason = ::perfetto::protos::pbzero::ChromeFrameReporter_FrameDropReason;
+ static inline const char* FrameDropReason_Name(FrameDropReason value) {
+ return ::perfetto::protos::pbzero::ChromeFrameReporter_FrameDropReason_Name(value);
+ }
+
+ using ScrollState = ::perfetto::protos::pbzero::ChromeFrameReporter_ScrollState;
+ static inline const char* ScrollState_Name(ScrollState value) {
+ return ::perfetto::protos::pbzero::ChromeFrameReporter_ScrollState_Name(value);
+ }
+
+ using FrameType = ::perfetto::protos::pbzero::ChromeFrameReporter_FrameType;
+ static inline const char* FrameType_Name(FrameType value) {
+ return ::perfetto::protos::pbzero::ChromeFrameReporter_FrameType_Name(value);
+ }
+ static inline const State STATE_NO_UPDATE_DESIRED = State::STATE_NO_UPDATE_DESIRED;
+ static inline const State STATE_PRESENTED_ALL = State::STATE_PRESENTED_ALL;
+ static inline const State STATE_PRESENTED_PARTIAL = State::STATE_PRESENTED_PARTIAL;
+ static inline const State STATE_DROPPED = State::STATE_DROPPED;
+ static inline const FrameDropReason REASON_UNSPECIFIED = FrameDropReason::REASON_UNSPECIFIED;
+ static inline const FrameDropReason REASON_DISPLAY_COMPOSITOR = FrameDropReason::REASON_DISPLAY_COMPOSITOR;
+ static inline const FrameDropReason REASON_MAIN_THREAD = FrameDropReason::REASON_MAIN_THREAD;
+ static inline const FrameDropReason REASON_CLIENT_COMPOSITOR = FrameDropReason::REASON_CLIENT_COMPOSITOR;
+ static inline const ScrollState SCROLL_NONE = ScrollState::SCROLL_NONE;
+ static inline const ScrollState SCROLL_MAIN_THREAD = ScrollState::SCROLL_MAIN_THREAD;
+ static inline const ScrollState SCROLL_COMPOSITOR_THREAD = ScrollState::SCROLL_COMPOSITOR_THREAD;
+ static inline const ScrollState SCROLL_UNKNOWN = ScrollState::SCROLL_UNKNOWN;
+ static inline const FrameType FORKED = FrameType::FORKED;
+ static inline const FrameType BACKFILL = FrameType::BACKFILL;
+
+ using FieldMetadata_State =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeFrameReporter_State,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_State kState{};
+ void set_state(ChromeFrameReporter_State value) {
+ static constexpr uint32_t field_id = FieldMetadata_State::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Reason =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeFrameReporter_FrameDropReason,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_Reason kReason{};
+ void set_reason(ChromeFrameReporter_FrameDropReason value) {
+ static constexpr uint32_t field_id = FieldMetadata_Reason::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameSource =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_FrameSource kFrameSource{};
+ void set_frame_source(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameSource::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameSequence =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_FrameSequence kFrameSequence{};
+ void set_frame_sequence(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameSequence::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AffectsSmoothness =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_AffectsSmoothness kAffectsSmoothness{};
+ void set_affects_smoothness(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AffectsSmoothness::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ScrollState =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeFrameReporter_ScrollState,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_ScrollState kScrollState{};
+ void set_scroll_state(ChromeFrameReporter_ScrollState value) {
+ static constexpr uint32_t field_id = FieldMetadata_ScrollState::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasMainAnimation =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_HasMainAnimation kHasMainAnimation{};
+ void set_has_main_animation(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasMainAnimation::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasCompositorAnimation =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_HasCompositorAnimation kHasCompositorAnimation{};
+ void set_has_compositor_animation(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasCompositorAnimation::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasSmoothInputMain =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_HasSmoothInputMain kHasSmoothInputMain{};
+ void set_has_smooth_input_main(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasSmoothInputMain::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasMissingContent =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_HasMissingContent kHasMissingContent{};
+ void set_has_missing_content(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasMissingContent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LayerTreeHostId =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_LayerTreeHostId kLayerTreeHostId{};
+ void set_layer_tree_host_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LayerTreeHostId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasHighLatency =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_HasHighLatency kHasHighLatency{};
+ void set_has_high_latency(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasHighLatency::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameType =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeFrameReporter_FrameType,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_FrameType kFrameType{};
+ void set_frame_type(ChromeFrameReporter_FrameType value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HighLatencyContributionStage =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeFrameReporter>;
+
+ static constexpr FieldMetadata_HighLatencyContributionStage kHighLatencyContributionStage{};
+ void add_high_latency_contribution_stage(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HighLatencyContributionStage::kFieldId, data, size);
+ }
+ void add_high_latency_contribution_stage(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HighLatencyContributionStage::kFieldId, chars.data, chars.size);
+ }
+ void add_high_latency_contribution_stage(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HighLatencyContributionStage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_HISTOGRAM_SAMPLE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_HISTOGRAM_SAMPLE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeHistogramSample_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeHistogramSample_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeHistogramSample_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeHistogramSample_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name_hash() const { return at<1>().valid(); }
+ uint64_t name_hash() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_sample() const { return at<3>().valid(); }
+ int64_t sample() const { return at<3>().as_int64(); }
+ bool has_name_iid() const { return at<4>().valid(); }
+ uint64_t name_iid() const { return at<4>().as_uint64(); }
+};
+
+class ChromeHistogramSample : public ::protozero::Message {
+ public:
+ using Decoder = ChromeHistogramSample_Decoder;
+ enum : int32_t {
+ kNameHashFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kSampleFieldNumber = 3,
+ kNameIidFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeHistogramSample"; }
+
+
+ using FieldMetadata_NameHash =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeHistogramSample>;
+
+ static constexpr FieldMetadata_NameHash kNameHash{};
+ void set_name_hash(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameHash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeHistogramSample>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Sample =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeHistogramSample>;
+
+ static constexpr FieldMetadata_Sample kSample{};
+ void set_sample(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Sample::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeHistogramSample>;
+
+ static constexpr FieldMetadata_NameIid kNameIid{};
+ void set_name_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class HistogramName_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ HistogramName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit HistogramName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit HistogramName_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+};
+
+class HistogramName : public ::protozero::Message {
+ public:
+ using Decoder = HistogramName_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.HistogramName"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ HistogramName>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ HistogramName>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_KEYED_SERVICE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_KEYED_SERVICE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeKeyedService_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeKeyedService_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeKeyedService_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeKeyedService_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+};
+
+class ChromeKeyedService : public ::protozero::Message {
+ public:
+ using Decoder = ChromeKeyedService_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeKeyedService"; }
+
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeKeyedService>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_latency_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LATENCY_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LATENCY_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ChromeLatencyInfo_ComponentInfo;
+namespace perfetto_pbzero_enum_ChromeLatencyInfo {
+enum LatencyComponentType : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeLatencyInfo
+using ChromeLatencyInfo_LatencyComponentType = perfetto_pbzero_enum_ChromeLatencyInfo::LatencyComponentType;
+namespace perfetto_pbzero_enum_ChromeLatencyInfo {
+enum Step : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeLatencyInfo
+using ChromeLatencyInfo_Step = perfetto_pbzero_enum_ChromeLatencyInfo::Step;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeLatencyInfo {
+enum Step : int32_t {
+ STEP_UNSPECIFIED = 0,
+ STEP_SEND_INPUT_EVENT_UI = 3,
+ STEP_HANDLE_INPUT_EVENT_IMPL = 5,
+ STEP_DID_HANDLE_INPUT_AND_OVERSCROLL = 8,
+ STEP_HANDLE_INPUT_EVENT_MAIN = 4,
+ STEP_MAIN_THREAD_SCROLL_UPDATE = 2,
+ STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT = 1,
+ STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL = 9,
+ STEP_HANDLED_INPUT_EVENT_IMPL = 10,
+ STEP_SWAP_BUFFERS = 6,
+ STEP_DRAW_AND_SWAP = 7,
+ STEP_FINISHED_SWAP_BUFFERS = 11,
+};
+} // namespace perfetto_pbzero_enum_ChromeLatencyInfo
+using ChromeLatencyInfo_Step = perfetto_pbzero_enum_ChromeLatencyInfo::Step;
+
+
+constexpr ChromeLatencyInfo_Step ChromeLatencyInfo_Step_MIN = ChromeLatencyInfo_Step::STEP_UNSPECIFIED;
+constexpr ChromeLatencyInfo_Step ChromeLatencyInfo_Step_MAX = ChromeLatencyInfo_Step::STEP_FINISHED_SWAP_BUFFERS;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeLatencyInfo_Step_Name(::perfetto::protos::pbzero::ChromeLatencyInfo_Step value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_UNSPECIFIED:
+ return "STEP_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_SEND_INPUT_EVENT_UI:
+ return "STEP_SEND_INPUT_EVENT_UI";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_HANDLE_INPUT_EVENT_IMPL:
+ return "STEP_HANDLE_INPUT_EVENT_IMPL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_DID_HANDLE_INPUT_AND_OVERSCROLL:
+ return "STEP_DID_HANDLE_INPUT_AND_OVERSCROLL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_HANDLE_INPUT_EVENT_MAIN:
+ return "STEP_HANDLE_INPUT_EVENT_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_MAIN_THREAD_SCROLL_UPDATE:
+ return "STEP_MAIN_THREAD_SCROLL_UPDATE";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT:
+ return "STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL:
+ return "STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_HANDLED_INPUT_EVENT_IMPL:
+ return "STEP_HANDLED_INPUT_EVENT_IMPL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_SWAP_BUFFERS:
+ return "STEP_SWAP_BUFFERS";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_DRAW_AND_SWAP:
+ return "STEP_DRAW_AND_SWAP";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_Step::STEP_FINISHED_SWAP_BUFFERS:
+ return "STEP_FINISHED_SWAP_BUFFERS";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_ChromeLatencyInfo {
+enum LatencyComponentType : int32_t {
+ COMPONENT_UNSPECIFIED = 0,
+ COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH = 1,
+ COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL = 2,
+ COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL = 3,
+ COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL = 4,
+ COMPONENT_INPUT_EVENT_LATENCY_UI = 5,
+ COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN = 6,
+ COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN = 7,
+ COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL = 8,
+ COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT = 9,
+ COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH = 10,
+ COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP = 11,
+ COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME = 12,
+ COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER = 13,
+ COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP = 14,
+};
+} // namespace perfetto_pbzero_enum_ChromeLatencyInfo
+using ChromeLatencyInfo_LatencyComponentType = perfetto_pbzero_enum_ChromeLatencyInfo::LatencyComponentType;
+
+
+constexpr ChromeLatencyInfo_LatencyComponentType ChromeLatencyInfo_LatencyComponentType_MIN = ChromeLatencyInfo_LatencyComponentType::COMPONENT_UNSPECIFIED;
+constexpr ChromeLatencyInfo_LatencyComponentType ChromeLatencyInfo_LatencyComponentType_MAX = ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeLatencyInfo_LatencyComponentType_Name(::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_UNSPECIFIED:
+ return "COMPONENT_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH:
+ return "COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL:
+ return "COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL:
+ return "COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL:
+ return "COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_UI:
+ return "COMPONENT_INPUT_EVENT_LATENCY_UI";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN:
+ return "COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN:
+ return "COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL:
+ return "COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT:
+ return "COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH:
+ return "COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP:
+ return "COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME:
+ return "COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER:
+ return "COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER";
+
+ case ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP:
+ return "COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeLatencyInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeLatencyInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeLatencyInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeLatencyInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_trace_id() const { return at<1>().valid(); }
+ int64_t trace_id() const { return at<1>().as_int64(); }
+ bool has_step() const { return at<2>().valid(); }
+ int32_t step() const { return at<2>().as_int32(); }
+ bool has_frame_tree_node_id() const { return at<3>().valid(); }
+ int32_t frame_tree_node_id() const { return at<3>().as_int32(); }
+ bool has_component_info() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> component_info() const { return GetRepeated<::protozero::ConstBytes>(4); }
+ bool has_is_coalesced() const { return at<5>().valid(); }
+ bool is_coalesced() const { return at<5>().as_bool(); }
+ bool has_gesture_scroll_id() const { return at<6>().valid(); }
+ int64_t gesture_scroll_id() const { return at<6>().as_int64(); }
+ bool has_touch_id() const { return at<7>().valid(); }
+ int64_t touch_id() const { return at<7>().as_int64(); }
+};
+
+class ChromeLatencyInfo : public ::protozero::Message {
+ public:
+ using Decoder = ChromeLatencyInfo_Decoder;
+ enum : int32_t {
+ kTraceIdFieldNumber = 1,
+ kStepFieldNumber = 2,
+ kFrameTreeNodeIdFieldNumber = 3,
+ kComponentInfoFieldNumber = 4,
+ kIsCoalescedFieldNumber = 5,
+ kGestureScrollIdFieldNumber = 6,
+ kTouchIdFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeLatencyInfo"; }
+
+ using ComponentInfo = ::perfetto::protos::pbzero::ChromeLatencyInfo_ComponentInfo;
+
+ using Step = ::perfetto::protos::pbzero::ChromeLatencyInfo_Step;
+ static inline const char* Step_Name(Step value) {
+ return ::perfetto::protos::pbzero::ChromeLatencyInfo_Step_Name(value);
+ }
+
+ using LatencyComponentType = ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType;
+ static inline const char* LatencyComponentType_Name(LatencyComponentType value) {
+ return ::perfetto::protos::pbzero::ChromeLatencyInfo_LatencyComponentType_Name(value);
+ }
+ static inline const Step STEP_UNSPECIFIED = Step::STEP_UNSPECIFIED;
+ static inline const Step STEP_SEND_INPUT_EVENT_UI = Step::STEP_SEND_INPUT_EVENT_UI;
+ static inline const Step STEP_HANDLE_INPUT_EVENT_IMPL = Step::STEP_HANDLE_INPUT_EVENT_IMPL;
+ static inline const Step STEP_DID_HANDLE_INPUT_AND_OVERSCROLL = Step::STEP_DID_HANDLE_INPUT_AND_OVERSCROLL;
+ static inline const Step STEP_HANDLE_INPUT_EVENT_MAIN = Step::STEP_HANDLE_INPUT_EVENT_MAIN;
+ static inline const Step STEP_MAIN_THREAD_SCROLL_UPDATE = Step::STEP_MAIN_THREAD_SCROLL_UPDATE;
+ static inline const Step STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT = Step::STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT;
+ static inline const Step STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL = Step::STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL;
+ static inline const Step STEP_HANDLED_INPUT_EVENT_IMPL = Step::STEP_HANDLED_INPUT_EVENT_IMPL;
+ static inline const Step STEP_SWAP_BUFFERS = Step::STEP_SWAP_BUFFERS;
+ static inline const Step STEP_DRAW_AND_SWAP = Step::STEP_DRAW_AND_SWAP;
+ static inline const Step STEP_FINISHED_SWAP_BUFFERS = Step::STEP_FINISHED_SWAP_BUFFERS;
+ static inline const LatencyComponentType COMPONENT_UNSPECIFIED = LatencyComponentType::COMPONENT_UNSPECIFIED;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_UI = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_UI;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP;
+ static inline const LatencyComponentType COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME = LatencyComponentType::COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER = LatencyComponentType::COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER;
+ static inline const LatencyComponentType COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP = LatencyComponentType::COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP;
+
+ using FieldMetadata_TraceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeLatencyInfo>;
+
+ static constexpr FieldMetadata_TraceId kTraceId{};
+ void set_trace_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TraceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Step =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeLatencyInfo_Step,
+ ChromeLatencyInfo>;
+
+ static constexpr FieldMetadata_Step kStep{};
+ void set_step(ChromeLatencyInfo_Step value) {
+ static constexpr uint32_t field_id = FieldMetadata_Step::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FrameTreeNodeId =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeLatencyInfo>;
+
+ static constexpr FieldMetadata_FrameTreeNodeId kFrameTreeNodeId{};
+ void set_frame_tree_node_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FrameTreeNodeId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ComponentInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeLatencyInfo_ComponentInfo,
+ ChromeLatencyInfo>;
+
+ static constexpr FieldMetadata_ComponentInfo kComponentInfo{};
+ template <typename T = ChromeLatencyInfo_ComponentInfo> T* add_component_info() {
+ return BeginNestedMessage<T>(4);
+ }
+
+
+ using FieldMetadata_IsCoalesced =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeLatencyInfo>;
+
+ static constexpr FieldMetadata_IsCoalesced kIsCoalesced{};
+ void set_is_coalesced(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsCoalesced::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_GestureScrollId =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeLatencyInfo>;
+
+ static constexpr FieldMetadata_GestureScrollId kGestureScrollId{};
+ void set_gesture_scroll_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GestureScrollId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TouchId =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ChromeLatencyInfo>;
+
+ static constexpr FieldMetadata_TouchId kTouchId{};
+ void set_touch_id(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TouchId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeLatencyInfo_ComponentInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeLatencyInfo_ComponentInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeLatencyInfo_ComponentInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeLatencyInfo_ComponentInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_component_type() const { return at<1>().valid(); }
+ int32_t component_type() const { return at<1>().as_int32(); }
+ bool has_time_us() const { return at<2>().valid(); }
+ uint64_t time_us() const { return at<2>().as_uint64(); }
+};
+
+class ChromeLatencyInfo_ComponentInfo : public ::protozero::Message {
+ public:
+ using Decoder = ChromeLatencyInfo_ComponentInfo_Decoder;
+ enum : int32_t {
+ kComponentTypeFieldNumber = 1,
+ kTimeUsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeLatencyInfo.ComponentInfo"; }
+
+
+ using FieldMetadata_ComponentType =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeLatencyInfo_LatencyComponentType,
+ ChromeLatencyInfo_ComponentInfo>;
+
+ static constexpr FieldMetadata_ComponentType kComponentType{};
+ void set_component_type(ChromeLatencyInfo_LatencyComponentType value) {
+ static constexpr uint32_t field_id = FieldMetadata_ComponentType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimeUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeLatencyInfo_ComponentInfo>;
+
+ static constexpr FieldMetadata_TimeUs kTimeUs{};
+ void set_time_us(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimeUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ChromeLegacyIpc {
+enum MessageClass : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeLegacyIpc
+using ChromeLegacyIpc_MessageClass = perfetto_pbzero_enum_ChromeLegacyIpc::MessageClass;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeLegacyIpc {
+enum MessageClass : int32_t {
+ CLASS_UNSPECIFIED = 0,
+ CLASS_AUTOMATION = 1,
+ CLASS_FRAME = 2,
+ CLASS_PAGE = 3,
+ CLASS_VIEW = 4,
+ CLASS_WIDGET = 5,
+ CLASS_INPUT = 6,
+ CLASS_TEST = 7,
+ CLASS_WORKER = 8,
+ CLASS_NACL = 9,
+ CLASS_GPU_CHANNEL = 10,
+ CLASS_MEDIA = 11,
+ CLASS_PPAPI = 12,
+ CLASS_CHROME = 13,
+ CLASS_DRAG = 14,
+ CLASS_PRINT = 15,
+ CLASS_EXTENSION = 16,
+ CLASS_TEXT_INPUT_CLIENT = 17,
+ CLASS_BLINK_TEST = 18,
+ CLASS_ACCESSIBILITY = 19,
+ CLASS_PRERENDER = 20,
+ CLASS_CHROMOTING = 21,
+ CLASS_BROWSER_PLUGIN = 22,
+ CLASS_ANDROID_WEB_VIEW = 23,
+ CLASS_NACL_HOST = 24,
+ CLASS_ENCRYPTED_MEDIA = 25,
+ CLASS_CAST = 26,
+ CLASS_GIN_JAVA_BRIDGE = 27,
+ CLASS_CHROME_UTILITY_PRINTING = 28,
+ CLASS_OZONE_GPU = 29,
+ CLASS_WEB_TEST = 30,
+ CLASS_NETWORK_HINTS = 31,
+ CLASS_EXTENSIONS_GUEST_VIEW = 32,
+ CLASS_GUEST_VIEW = 33,
+ CLASS_MEDIA_PLAYER_DELEGATE = 34,
+ CLASS_EXTENSION_WORKER = 35,
+ CLASS_SUBRESOURCE_FILTER = 36,
+ CLASS_UNFREEZABLE_FRAME = 37,
+};
+} // namespace perfetto_pbzero_enum_ChromeLegacyIpc
+using ChromeLegacyIpc_MessageClass = perfetto_pbzero_enum_ChromeLegacyIpc::MessageClass;
+
+
+constexpr ChromeLegacyIpc_MessageClass ChromeLegacyIpc_MessageClass_MIN = ChromeLegacyIpc_MessageClass::CLASS_UNSPECIFIED;
+constexpr ChromeLegacyIpc_MessageClass ChromeLegacyIpc_MessageClass_MAX = ChromeLegacyIpc_MessageClass::CLASS_UNFREEZABLE_FRAME;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeLegacyIpc_MessageClass_Name(::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_UNSPECIFIED:
+ return "CLASS_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_AUTOMATION:
+ return "CLASS_AUTOMATION";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_FRAME:
+ return "CLASS_FRAME";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_PAGE:
+ return "CLASS_PAGE";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_VIEW:
+ return "CLASS_VIEW";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_WIDGET:
+ return "CLASS_WIDGET";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_INPUT:
+ return "CLASS_INPUT";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_TEST:
+ return "CLASS_TEST";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_WORKER:
+ return "CLASS_WORKER";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_NACL:
+ return "CLASS_NACL";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_GPU_CHANNEL:
+ return "CLASS_GPU_CHANNEL";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_MEDIA:
+ return "CLASS_MEDIA";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_PPAPI:
+ return "CLASS_PPAPI";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_CHROME:
+ return "CLASS_CHROME";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_DRAG:
+ return "CLASS_DRAG";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_PRINT:
+ return "CLASS_PRINT";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_EXTENSION:
+ return "CLASS_EXTENSION";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_TEXT_INPUT_CLIENT:
+ return "CLASS_TEXT_INPUT_CLIENT";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_BLINK_TEST:
+ return "CLASS_BLINK_TEST";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_ACCESSIBILITY:
+ return "CLASS_ACCESSIBILITY";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_PRERENDER:
+ return "CLASS_PRERENDER";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_CHROMOTING:
+ return "CLASS_CHROMOTING";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_BROWSER_PLUGIN:
+ return "CLASS_BROWSER_PLUGIN";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_ANDROID_WEB_VIEW:
+ return "CLASS_ANDROID_WEB_VIEW";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_NACL_HOST:
+ return "CLASS_NACL_HOST";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_ENCRYPTED_MEDIA:
+ return "CLASS_ENCRYPTED_MEDIA";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_CAST:
+ return "CLASS_CAST";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_GIN_JAVA_BRIDGE:
+ return "CLASS_GIN_JAVA_BRIDGE";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_CHROME_UTILITY_PRINTING:
+ return "CLASS_CHROME_UTILITY_PRINTING";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_OZONE_GPU:
+ return "CLASS_OZONE_GPU";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_WEB_TEST:
+ return "CLASS_WEB_TEST";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_NETWORK_HINTS:
+ return "CLASS_NETWORK_HINTS";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_EXTENSIONS_GUEST_VIEW:
+ return "CLASS_EXTENSIONS_GUEST_VIEW";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_GUEST_VIEW:
+ return "CLASS_GUEST_VIEW";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_MEDIA_PLAYER_DELEGATE:
+ return "CLASS_MEDIA_PLAYER_DELEGATE";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_EXTENSION_WORKER:
+ return "CLASS_EXTENSION_WORKER";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_SUBRESOURCE_FILTER:
+ return "CLASS_SUBRESOURCE_FILTER";
+
+ case ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass::CLASS_UNFREEZABLE_FRAME:
+ return "CLASS_UNFREEZABLE_FRAME";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeLegacyIpc_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeLegacyIpc_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeLegacyIpc_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeLegacyIpc_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_message_class() const { return at<1>().valid(); }
+ int32_t message_class() const { return at<1>().as_int32(); }
+ bool has_message_line() const { return at<2>().valid(); }
+ uint32_t message_line() const { return at<2>().as_uint32(); }
+};
+
+class ChromeLegacyIpc : public ::protozero::Message {
+ public:
+ using Decoder = ChromeLegacyIpc_Decoder;
+ enum : int32_t {
+ kMessageClassFieldNumber = 1,
+ kMessageLineFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeLegacyIpc"; }
+
+
+ using MessageClass = ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass;
+ static inline const char* MessageClass_Name(MessageClass value) {
+ return ::perfetto::protos::pbzero::ChromeLegacyIpc_MessageClass_Name(value);
+ }
+ static inline const MessageClass CLASS_UNSPECIFIED = MessageClass::CLASS_UNSPECIFIED;
+ static inline const MessageClass CLASS_AUTOMATION = MessageClass::CLASS_AUTOMATION;
+ static inline const MessageClass CLASS_FRAME = MessageClass::CLASS_FRAME;
+ static inline const MessageClass CLASS_PAGE = MessageClass::CLASS_PAGE;
+ static inline const MessageClass CLASS_VIEW = MessageClass::CLASS_VIEW;
+ static inline const MessageClass CLASS_WIDGET = MessageClass::CLASS_WIDGET;
+ static inline const MessageClass CLASS_INPUT = MessageClass::CLASS_INPUT;
+ static inline const MessageClass CLASS_TEST = MessageClass::CLASS_TEST;
+ static inline const MessageClass CLASS_WORKER = MessageClass::CLASS_WORKER;
+ static inline const MessageClass CLASS_NACL = MessageClass::CLASS_NACL;
+ static inline const MessageClass CLASS_GPU_CHANNEL = MessageClass::CLASS_GPU_CHANNEL;
+ static inline const MessageClass CLASS_MEDIA = MessageClass::CLASS_MEDIA;
+ static inline const MessageClass CLASS_PPAPI = MessageClass::CLASS_PPAPI;
+ static inline const MessageClass CLASS_CHROME = MessageClass::CLASS_CHROME;
+ static inline const MessageClass CLASS_DRAG = MessageClass::CLASS_DRAG;
+ static inline const MessageClass CLASS_PRINT = MessageClass::CLASS_PRINT;
+ static inline const MessageClass CLASS_EXTENSION = MessageClass::CLASS_EXTENSION;
+ static inline const MessageClass CLASS_TEXT_INPUT_CLIENT = MessageClass::CLASS_TEXT_INPUT_CLIENT;
+ static inline const MessageClass CLASS_BLINK_TEST = MessageClass::CLASS_BLINK_TEST;
+ static inline const MessageClass CLASS_ACCESSIBILITY = MessageClass::CLASS_ACCESSIBILITY;
+ static inline const MessageClass CLASS_PRERENDER = MessageClass::CLASS_PRERENDER;
+ static inline const MessageClass CLASS_CHROMOTING = MessageClass::CLASS_CHROMOTING;
+ static inline const MessageClass CLASS_BROWSER_PLUGIN = MessageClass::CLASS_BROWSER_PLUGIN;
+ static inline const MessageClass CLASS_ANDROID_WEB_VIEW = MessageClass::CLASS_ANDROID_WEB_VIEW;
+ static inline const MessageClass CLASS_NACL_HOST = MessageClass::CLASS_NACL_HOST;
+ static inline const MessageClass CLASS_ENCRYPTED_MEDIA = MessageClass::CLASS_ENCRYPTED_MEDIA;
+ static inline const MessageClass CLASS_CAST = MessageClass::CLASS_CAST;
+ static inline const MessageClass CLASS_GIN_JAVA_BRIDGE = MessageClass::CLASS_GIN_JAVA_BRIDGE;
+ static inline const MessageClass CLASS_CHROME_UTILITY_PRINTING = MessageClass::CLASS_CHROME_UTILITY_PRINTING;
+ static inline const MessageClass CLASS_OZONE_GPU = MessageClass::CLASS_OZONE_GPU;
+ static inline const MessageClass CLASS_WEB_TEST = MessageClass::CLASS_WEB_TEST;
+ static inline const MessageClass CLASS_NETWORK_HINTS = MessageClass::CLASS_NETWORK_HINTS;
+ static inline const MessageClass CLASS_EXTENSIONS_GUEST_VIEW = MessageClass::CLASS_EXTENSIONS_GUEST_VIEW;
+ static inline const MessageClass CLASS_GUEST_VIEW = MessageClass::CLASS_GUEST_VIEW;
+ static inline const MessageClass CLASS_MEDIA_PLAYER_DELEGATE = MessageClass::CLASS_MEDIA_PLAYER_DELEGATE;
+ static inline const MessageClass CLASS_EXTENSION_WORKER = MessageClass::CLASS_EXTENSION_WORKER;
+ static inline const MessageClass CLASS_SUBRESOURCE_FILTER = MessageClass::CLASS_SUBRESOURCE_FILTER;
+ static inline const MessageClass CLASS_UNFREEZABLE_FRAME = MessageClass::CLASS_UNFREEZABLE_FRAME;
+
+ using FieldMetadata_MessageClass =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeLegacyIpc_MessageClass,
+ ChromeLegacyIpc>;
+
+ static constexpr FieldMetadata_MessageClass kMessageClass{};
+ void set_message_class(ChromeLegacyIpc_MessageClass value) {
+ static constexpr uint32_t field_id = FieldMetadata_MessageClass::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MessageLine =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeLegacyIpc>;
+
+ static constexpr FieldMetadata_MessageLine kMessageLine{};
+ void set_message_line(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MessageLine::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_message_pump.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MESSAGE_PUMP_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MESSAGE_PUMP_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeMessagePump_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeMessagePump_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeMessagePump_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeMessagePump_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_sent_messages_in_queue() const { return at<1>().valid(); }
+ bool sent_messages_in_queue() const { return at<1>().as_bool(); }
+ bool has_io_handler_location_iid() const { return at<2>().valid(); }
+ uint64_t io_handler_location_iid() const { return at<2>().as_uint64(); }
+};
+
+class ChromeMessagePump : public ::protozero::Message {
+ public:
+ using Decoder = ChromeMessagePump_Decoder;
+ enum : int32_t {
+ kSentMessagesInQueueFieldNumber = 1,
+ kIoHandlerLocationIidFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeMessagePump"; }
+
+
+ using FieldMetadata_SentMessagesInQueue =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeMessagePump>;
+
+ static constexpr FieldMetadata_SentMessagesInQueue kSentMessagesInQueue{};
+ void set_sent_messages_in_queue(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SentMessagesInQueue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IoHandlerLocationIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeMessagePump>;
+
+ static constexpr FieldMetadata_IoHandlerLocationIid kIoHandlerLocationIid{};
+ void set_io_handler_location_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IoHandlerLocationIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeMojoEventInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeMojoEventInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeMojoEventInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeMojoEventInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_watcher_notify_interface_tag() const { return at<1>().valid(); }
+ ::protozero::ConstChars watcher_notify_interface_tag() const { return at<1>().as_string(); }
+ bool has_ipc_hash() const { return at<2>().valid(); }
+ uint32_t ipc_hash() const { return at<2>().as_uint32(); }
+ bool has_mojo_interface_tag() const { return at<3>().valid(); }
+ ::protozero::ConstChars mojo_interface_tag() const { return at<3>().as_string(); }
+ bool has_mojo_interface_method_iid() const { return at<4>().valid(); }
+ uint64_t mojo_interface_method_iid() const { return at<4>().as_uint64(); }
+ bool has_is_reply() const { return at<5>().valid(); }
+ bool is_reply() const { return at<5>().as_bool(); }
+ bool has_payload_size() const { return at<6>().valid(); }
+ uint64_t payload_size() const { return at<6>().as_uint64(); }
+ bool has_data_num_bytes() const { return at<7>().valid(); }
+ uint64_t data_num_bytes() const { return at<7>().as_uint64(); }
+};
+
+class ChromeMojoEventInfo : public ::protozero::Message {
+ public:
+ using Decoder = ChromeMojoEventInfo_Decoder;
+ enum : int32_t {
+ kWatcherNotifyInterfaceTagFieldNumber = 1,
+ kIpcHashFieldNumber = 2,
+ kMojoInterfaceTagFieldNumber = 3,
+ kMojoInterfaceMethodIidFieldNumber = 4,
+ kIsReplyFieldNumber = 5,
+ kPayloadSizeFieldNumber = 6,
+ kDataNumBytesFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeMojoEventInfo"; }
+
+
+ using FieldMetadata_WatcherNotifyInterfaceTag =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeMojoEventInfo>;
+
+ static constexpr FieldMetadata_WatcherNotifyInterfaceTag kWatcherNotifyInterfaceTag{};
+ void set_watcher_notify_interface_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_WatcherNotifyInterfaceTag::kFieldId, data, size);
+ }
+ void set_watcher_notify_interface_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_WatcherNotifyInterfaceTag::kFieldId, chars.data, chars.size);
+ }
+ void set_watcher_notify_interface_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_WatcherNotifyInterfaceTag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IpcHash =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeMojoEventInfo>;
+
+ static constexpr FieldMetadata_IpcHash kIpcHash{};
+ void set_ipc_hash(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IpcHash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MojoInterfaceTag =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeMojoEventInfo>;
+
+ static constexpr FieldMetadata_MojoInterfaceTag kMojoInterfaceTag{};
+ void set_mojo_interface_tag(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_MojoInterfaceTag::kFieldId, data, size);
+ }
+ void set_mojo_interface_tag(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_MojoInterfaceTag::kFieldId, chars.data, chars.size);
+ }
+ void set_mojo_interface_tag(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_MojoInterfaceTag::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MojoInterfaceMethodIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeMojoEventInfo>;
+
+ static constexpr FieldMetadata_MojoInterfaceMethodIid kMojoInterfaceMethodIid{};
+ void set_mojo_interface_method_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MojoInterfaceMethodIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsReply =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeMojoEventInfo>;
+
+ static constexpr FieldMetadata_IsReply kIsReply{};
+ void set_is_reply(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsReply::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PayloadSize =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeMojoEventInfo>;
+
+ static constexpr FieldMetadata_PayloadSize kPayloadSize{};
+ void set_payload_size(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PayloadSize::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DataNumBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeMojoEventInfo>;
+
+ static constexpr FieldMetadata_DataNumBytes kDataNumBytes{};
+ void set_data_num_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DataNumBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ChromeProcessDescriptor {
+enum ProcessType : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeProcessDescriptor
+using ChromeProcessDescriptor_ProcessType = perfetto_pbzero_enum_ChromeProcessDescriptor::ProcessType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeProcessDescriptor {
+enum ProcessType : int32_t {
+ PROCESS_UNSPECIFIED = 0,
+ PROCESS_BROWSER = 1,
+ PROCESS_RENDERER = 2,
+ PROCESS_UTILITY = 3,
+ PROCESS_ZYGOTE = 4,
+ PROCESS_SANDBOX_HELPER = 5,
+ PROCESS_GPU = 6,
+ PROCESS_PPAPI_PLUGIN = 7,
+ PROCESS_PPAPI_BROKER = 8,
+ PROCESS_SERVICE_NETWORK = 9,
+ PROCESS_SERVICE_TRACING = 10,
+ PROCESS_SERVICE_STORAGE = 11,
+ PROCESS_SERVICE_AUDIO = 12,
+ PROCESS_SERVICE_DATA_DECODER = 13,
+ PROCESS_SERVICE_UTIL_WIN = 14,
+ PROCESS_SERVICE_PROXY_RESOLVER = 15,
+ PROCESS_SERVICE_CDM = 16,
+ PROCESS_SERVICE_VIDEO_CAPTURE = 17,
+ PROCESS_SERVICE_UNZIPPER = 18,
+ PROCESS_SERVICE_MIRRORING = 19,
+ PROCESS_SERVICE_FILEPATCHER = 20,
+ PROCESS_SERVICE_TTS = 21,
+ PROCESS_SERVICE_PRINTING = 22,
+ PROCESS_SERVICE_QUARANTINE = 23,
+ PROCESS_SERVICE_CROS_LOCALSEARCH = 24,
+ PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER = 25,
+ PROCESS_SERVICE_FILEUTIL = 26,
+ PROCESS_SERVICE_PRINTCOMPOSITOR = 27,
+ PROCESS_SERVICE_PAINTPREVIEW = 28,
+ PROCESS_SERVICE_SPEECHRECOGNITION = 29,
+ PROCESS_SERVICE_XRDEVICE = 30,
+ PROCESS_SERVICE_READICON = 31,
+ PROCESS_SERVICE_LANGUAGEDETECTION = 32,
+ PROCESS_SERVICE_SHARING = 33,
+ PROCESS_SERVICE_MEDIAPARSER = 34,
+ PROCESS_SERVICE_QRCODEGENERATOR = 35,
+ PROCESS_SERVICE_PROFILEIMPORT = 36,
+ PROCESS_SERVICE_IME = 37,
+ PROCESS_SERVICE_RECORDING = 38,
+ PROCESS_SERVICE_SHAPEDETECTION = 39,
+ PROCESS_RENDERER_EXTENSION = 40,
+ PROCESS_SERVICE_MEDIA_FOUNDATION = 41,
+};
+} // namespace perfetto_pbzero_enum_ChromeProcessDescriptor
+using ChromeProcessDescriptor_ProcessType = perfetto_pbzero_enum_ChromeProcessDescriptor::ProcessType;
+
+
+constexpr ChromeProcessDescriptor_ProcessType ChromeProcessDescriptor_ProcessType_MIN = ChromeProcessDescriptor_ProcessType::PROCESS_UNSPECIFIED;
+constexpr ChromeProcessDescriptor_ProcessType ChromeProcessDescriptor_ProcessType_MAX = ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_MEDIA_FOUNDATION;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeProcessDescriptor_ProcessType_Name(::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_UNSPECIFIED:
+ return "PROCESS_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_BROWSER:
+ return "PROCESS_BROWSER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_RENDERER:
+ return "PROCESS_RENDERER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_UTILITY:
+ return "PROCESS_UTILITY";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_ZYGOTE:
+ return "PROCESS_ZYGOTE";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SANDBOX_HELPER:
+ return "PROCESS_SANDBOX_HELPER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_GPU:
+ return "PROCESS_GPU";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_PPAPI_PLUGIN:
+ return "PROCESS_PPAPI_PLUGIN";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_PPAPI_BROKER:
+ return "PROCESS_PPAPI_BROKER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_NETWORK:
+ return "PROCESS_SERVICE_NETWORK";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_TRACING:
+ return "PROCESS_SERVICE_TRACING";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_STORAGE:
+ return "PROCESS_SERVICE_STORAGE";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_AUDIO:
+ return "PROCESS_SERVICE_AUDIO";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_DATA_DECODER:
+ return "PROCESS_SERVICE_DATA_DECODER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_UTIL_WIN:
+ return "PROCESS_SERVICE_UTIL_WIN";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_PROXY_RESOLVER:
+ return "PROCESS_SERVICE_PROXY_RESOLVER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_CDM:
+ return "PROCESS_SERVICE_CDM";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_VIDEO_CAPTURE:
+ return "PROCESS_SERVICE_VIDEO_CAPTURE";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_UNZIPPER:
+ return "PROCESS_SERVICE_UNZIPPER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_MIRRORING:
+ return "PROCESS_SERVICE_MIRRORING";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_FILEPATCHER:
+ return "PROCESS_SERVICE_FILEPATCHER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_TTS:
+ return "PROCESS_SERVICE_TTS";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_PRINTING:
+ return "PROCESS_SERVICE_PRINTING";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_QUARANTINE:
+ return "PROCESS_SERVICE_QUARANTINE";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_CROS_LOCALSEARCH:
+ return "PROCESS_SERVICE_CROS_LOCALSEARCH";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER:
+ return "PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_FILEUTIL:
+ return "PROCESS_SERVICE_FILEUTIL";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_PRINTCOMPOSITOR:
+ return "PROCESS_SERVICE_PRINTCOMPOSITOR";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_PAINTPREVIEW:
+ return "PROCESS_SERVICE_PAINTPREVIEW";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_SPEECHRECOGNITION:
+ return "PROCESS_SERVICE_SPEECHRECOGNITION";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_XRDEVICE:
+ return "PROCESS_SERVICE_XRDEVICE";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_READICON:
+ return "PROCESS_SERVICE_READICON";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_LANGUAGEDETECTION:
+ return "PROCESS_SERVICE_LANGUAGEDETECTION";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_SHARING:
+ return "PROCESS_SERVICE_SHARING";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_MEDIAPARSER:
+ return "PROCESS_SERVICE_MEDIAPARSER";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_QRCODEGENERATOR:
+ return "PROCESS_SERVICE_QRCODEGENERATOR";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_PROFILEIMPORT:
+ return "PROCESS_SERVICE_PROFILEIMPORT";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_IME:
+ return "PROCESS_SERVICE_IME";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_RECORDING:
+ return "PROCESS_SERVICE_RECORDING";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_SHAPEDETECTION:
+ return "PROCESS_SERVICE_SHAPEDETECTION";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_RENDERER_EXTENSION:
+ return "PROCESS_RENDERER_EXTENSION";
+
+ case ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType::PROCESS_SERVICE_MEDIA_FOUNDATION:
+ return "PROCESS_SERVICE_MEDIA_FOUNDATION";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeProcessDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeProcessDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeProcessDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeProcessDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_process_type() const { return at<1>().valid(); }
+ int32_t process_type() const { return at<1>().as_int32(); }
+ bool has_process_priority() const { return at<2>().valid(); }
+ int32_t process_priority() const { return at<2>().as_int32(); }
+ bool has_legacy_sort_index() const { return at<3>().valid(); }
+ int32_t legacy_sort_index() const { return at<3>().as_int32(); }
+ bool has_host_app_package_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars host_app_package_name() const { return at<4>().as_string(); }
+ bool has_crash_trace_id() const { return at<5>().valid(); }
+ uint64_t crash_trace_id() const { return at<5>().as_uint64(); }
+};
+
+class ChromeProcessDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = ChromeProcessDescriptor_Decoder;
+ enum : int32_t {
+ kProcessTypeFieldNumber = 1,
+ kProcessPriorityFieldNumber = 2,
+ kLegacySortIndexFieldNumber = 3,
+ kHostAppPackageNameFieldNumber = 4,
+ kCrashTraceIdFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeProcessDescriptor"; }
+
+
+ using ProcessType = ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType;
+ static inline const char* ProcessType_Name(ProcessType value) {
+ return ::perfetto::protos::pbzero::ChromeProcessDescriptor_ProcessType_Name(value);
+ }
+ static inline const ProcessType PROCESS_UNSPECIFIED = ProcessType::PROCESS_UNSPECIFIED;
+ static inline const ProcessType PROCESS_BROWSER = ProcessType::PROCESS_BROWSER;
+ static inline const ProcessType PROCESS_RENDERER = ProcessType::PROCESS_RENDERER;
+ static inline const ProcessType PROCESS_UTILITY = ProcessType::PROCESS_UTILITY;
+ static inline const ProcessType PROCESS_ZYGOTE = ProcessType::PROCESS_ZYGOTE;
+ static inline const ProcessType PROCESS_SANDBOX_HELPER = ProcessType::PROCESS_SANDBOX_HELPER;
+ static inline const ProcessType PROCESS_GPU = ProcessType::PROCESS_GPU;
+ static inline const ProcessType PROCESS_PPAPI_PLUGIN = ProcessType::PROCESS_PPAPI_PLUGIN;
+ static inline const ProcessType PROCESS_PPAPI_BROKER = ProcessType::PROCESS_PPAPI_BROKER;
+ static inline const ProcessType PROCESS_SERVICE_NETWORK = ProcessType::PROCESS_SERVICE_NETWORK;
+ static inline const ProcessType PROCESS_SERVICE_TRACING = ProcessType::PROCESS_SERVICE_TRACING;
+ static inline const ProcessType PROCESS_SERVICE_STORAGE = ProcessType::PROCESS_SERVICE_STORAGE;
+ static inline const ProcessType PROCESS_SERVICE_AUDIO = ProcessType::PROCESS_SERVICE_AUDIO;
+ static inline const ProcessType PROCESS_SERVICE_DATA_DECODER = ProcessType::PROCESS_SERVICE_DATA_DECODER;
+ static inline const ProcessType PROCESS_SERVICE_UTIL_WIN = ProcessType::PROCESS_SERVICE_UTIL_WIN;
+ static inline const ProcessType PROCESS_SERVICE_PROXY_RESOLVER = ProcessType::PROCESS_SERVICE_PROXY_RESOLVER;
+ static inline const ProcessType PROCESS_SERVICE_CDM = ProcessType::PROCESS_SERVICE_CDM;
+ static inline const ProcessType PROCESS_SERVICE_VIDEO_CAPTURE = ProcessType::PROCESS_SERVICE_VIDEO_CAPTURE;
+ static inline const ProcessType PROCESS_SERVICE_UNZIPPER = ProcessType::PROCESS_SERVICE_UNZIPPER;
+ static inline const ProcessType PROCESS_SERVICE_MIRRORING = ProcessType::PROCESS_SERVICE_MIRRORING;
+ static inline const ProcessType PROCESS_SERVICE_FILEPATCHER = ProcessType::PROCESS_SERVICE_FILEPATCHER;
+ static inline const ProcessType PROCESS_SERVICE_TTS = ProcessType::PROCESS_SERVICE_TTS;
+ static inline const ProcessType PROCESS_SERVICE_PRINTING = ProcessType::PROCESS_SERVICE_PRINTING;
+ static inline const ProcessType PROCESS_SERVICE_QUARANTINE = ProcessType::PROCESS_SERVICE_QUARANTINE;
+ static inline const ProcessType PROCESS_SERVICE_CROS_LOCALSEARCH = ProcessType::PROCESS_SERVICE_CROS_LOCALSEARCH;
+ static inline const ProcessType PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER = ProcessType::PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER;
+ static inline const ProcessType PROCESS_SERVICE_FILEUTIL = ProcessType::PROCESS_SERVICE_FILEUTIL;
+ static inline const ProcessType PROCESS_SERVICE_PRINTCOMPOSITOR = ProcessType::PROCESS_SERVICE_PRINTCOMPOSITOR;
+ static inline const ProcessType PROCESS_SERVICE_PAINTPREVIEW = ProcessType::PROCESS_SERVICE_PAINTPREVIEW;
+ static inline const ProcessType PROCESS_SERVICE_SPEECHRECOGNITION = ProcessType::PROCESS_SERVICE_SPEECHRECOGNITION;
+ static inline const ProcessType PROCESS_SERVICE_XRDEVICE = ProcessType::PROCESS_SERVICE_XRDEVICE;
+ static inline const ProcessType PROCESS_SERVICE_READICON = ProcessType::PROCESS_SERVICE_READICON;
+ static inline const ProcessType PROCESS_SERVICE_LANGUAGEDETECTION = ProcessType::PROCESS_SERVICE_LANGUAGEDETECTION;
+ static inline const ProcessType PROCESS_SERVICE_SHARING = ProcessType::PROCESS_SERVICE_SHARING;
+ static inline const ProcessType PROCESS_SERVICE_MEDIAPARSER = ProcessType::PROCESS_SERVICE_MEDIAPARSER;
+ static inline const ProcessType PROCESS_SERVICE_QRCODEGENERATOR = ProcessType::PROCESS_SERVICE_QRCODEGENERATOR;
+ static inline const ProcessType PROCESS_SERVICE_PROFILEIMPORT = ProcessType::PROCESS_SERVICE_PROFILEIMPORT;
+ static inline const ProcessType PROCESS_SERVICE_IME = ProcessType::PROCESS_SERVICE_IME;
+ static inline const ProcessType PROCESS_SERVICE_RECORDING = ProcessType::PROCESS_SERVICE_RECORDING;
+ static inline const ProcessType PROCESS_SERVICE_SHAPEDETECTION = ProcessType::PROCESS_SERVICE_SHAPEDETECTION;
+ static inline const ProcessType PROCESS_RENDERER_EXTENSION = ProcessType::PROCESS_RENDERER_EXTENSION;
+ static inline const ProcessType PROCESS_SERVICE_MEDIA_FOUNDATION = ProcessType::PROCESS_SERVICE_MEDIA_FOUNDATION;
+
+ using FieldMetadata_ProcessType =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeProcessDescriptor_ProcessType,
+ ChromeProcessDescriptor>;
+
+ static constexpr FieldMetadata_ProcessType kProcessType{};
+ void set_process_type(ChromeProcessDescriptor_ProcessType value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeProcessDescriptor>;
+
+ static constexpr FieldMetadata_ProcessPriority kProcessPriority{};
+ void set_process_priority(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessPriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LegacySortIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeProcessDescriptor>;
+
+ static constexpr FieldMetadata_LegacySortIndex kLegacySortIndex{};
+ void set_legacy_sort_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LegacySortIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HostAppPackageName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeProcessDescriptor>;
+
+ static constexpr FieldMetadata_HostAppPackageName kHostAppPackageName{};
+ void set_host_app_package_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_HostAppPackageName::kFieldId, data, size);
+ }
+ void set_host_app_package_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_HostAppPackageName::kFieldId, chars.data, chars.size);
+ }
+ void set_host_app_package_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_HostAppPackageName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CrashTraceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeProcessDescriptor>;
+
+ static constexpr FieldMetadata_CrashTraceId kCrashTraceId{};
+ void set_crash_trace_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CrashTraceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_RENDERER_SCHEDULER_STATE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_RENDERER_SCHEDULER_STATE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+enum ChromeRAILMode : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+enum ChromeRAILMode : int32_t {
+ RAIL_MODE_NONE = 0,
+ RAIL_MODE_RESPONSE = 1,
+ RAIL_MODE_ANIMATION = 2,
+ RAIL_MODE_IDLE = 3,
+ RAIL_MODE_LOAD = 4,
+};
+
+constexpr ChromeRAILMode ChromeRAILMode_MIN = ChromeRAILMode::RAIL_MODE_NONE;
+constexpr ChromeRAILMode ChromeRAILMode_MAX = ChromeRAILMode::RAIL_MODE_LOAD;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeRAILMode_Name(::perfetto::protos::pbzero::ChromeRAILMode value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeRAILMode::RAIL_MODE_NONE:
+ return "RAIL_MODE_NONE";
+
+ case ::perfetto::protos::pbzero::ChromeRAILMode::RAIL_MODE_RESPONSE:
+ return "RAIL_MODE_RESPONSE";
+
+ case ::perfetto::protos::pbzero::ChromeRAILMode::RAIL_MODE_ANIMATION:
+ return "RAIL_MODE_ANIMATION";
+
+ case ::perfetto::protos::pbzero::ChromeRAILMode::RAIL_MODE_IDLE:
+ return "RAIL_MODE_IDLE";
+
+ case ::perfetto::protos::pbzero::ChromeRAILMode::RAIL_MODE_LOAD:
+ return "RAIL_MODE_LOAD";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeRendererSchedulerState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeRendererSchedulerState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeRendererSchedulerState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeRendererSchedulerState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_rail_mode() const { return at<1>().valid(); }
+ int32_t rail_mode() const { return at<1>().as_int32(); }
+ bool has_is_backgrounded() const { return at<2>().valid(); }
+ bool is_backgrounded() const { return at<2>().as_bool(); }
+ bool has_is_hidden() const { return at<3>().valid(); }
+ bool is_hidden() const { return at<3>().as_bool(); }
+};
+
+class ChromeRendererSchedulerState : public ::protozero::Message {
+ public:
+ using Decoder = ChromeRendererSchedulerState_Decoder;
+ enum : int32_t {
+ kRailModeFieldNumber = 1,
+ kIsBackgroundedFieldNumber = 2,
+ kIsHiddenFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeRendererSchedulerState"; }
+
+
+ using FieldMetadata_RailMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeRAILMode,
+ ChromeRendererSchedulerState>;
+
+ static constexpr FieldMetadata_RailMode kRailMode{};
+ void set_rail_mode(ChromeRAILMode value) {
+ static constexpr uint32_t field_id = FieldMetadata_RailMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsBackgrounded =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeRendererSchedulerState>;
+
+ static constexpr FieldMetadata_IsBackgrounded kIsBackgrounded{};
+ void set_is_backgrounded(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsBackgrounded::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsHidden =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ChromeRendererSchedulerState>;
+
+ static constexpr FieldMetadata_IsHidden kIsHidden{};
+ void set_is_hidden(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsHidden::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_THREAD_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_THREAD_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ChromeThreadDescriptor {
+enum ThreadType : int32_t;
+} // namespace perfetto_pbzero_enum_ChromeThreadDescriptor
+using ChromeThreadDescriptor_ThreadType = perfetto_pbzero_enum_ChromeThreadDescriptor::ThreadType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ChromeThreadDescriptor {
+enum ThreadType : int32_t {
+ THREAD_UNSPECIFIED = 0,
+ THREAD_MAIN = 1,
+ THREAD_IO = 2,
+ THREAD_POOL_BG_WORKER = 3,
+ THREAD_POOL_FG_WORKER = 4,
+ THREAD_POOL_FG_BLOCKING = 5,
+ THREAD_POOL_BG_BLOCKING = 6,
+ THREAD_POOL_SERVICE = 7,
+ THREAD_COMPOSITOR = 8,
+ THREAD_VIZ_COMPOSITOR = 9,
+ THREAD_COMPOSITOR_WORKER = 10,
+ THREAD_SERVICE_WORKER = 11,
+ THREAD_NETWORK_SERVICE = 12,
+ THREAD_CHILD_IO = 13,
+ THREAD_BROWSER_IO = 14,
+ THREAD_BROWSER_MAIN = 15,
+ THREAD_RENDERER_MAIN = 16,
+ THREAD_UTILITY_MAIN = 17,
+ THREAD_GPU_MAIN = 18,
+ THREAD_CACHE_BLOCKFILE = 19,
+ THREAD_MEDIA = 20,
+ THREAD_AUDIO_OUTPUTDEVICE = 21,
+ THREAD_AUDIO_INPUTDEVICE = 22,
+ THREAD_GPU_MEMORY = 23,
+ THREAD_GPU_VSYNC = 24,
+ THREAD_DXA_VIDEODECODER = 25,
+ THREAD_BROWSER_WATCHDOG = 26,
+ THREAD_WEBRTC_NETWORK = 27,
+ THREAD_WINDOW_OWNER = 28,
+ THREAD_WEBRTC_SIGNALING = 29,
+ THREAD_WEBRTC_WORKER = 30,
+ THREAD_PPAPI_MAIN = 31,
+ THREAD_GPU_WATCHDOG = 32,
+ THREAD_SWAPPER = 33,
+ THREAD_GAMEPAD_POLLING = 34,
+ THREAD_WEBCRYPTO = 35,
+ THREAD_DATABASE = 36,
+ THREAD_PROXYRESOLVER = 37,
+ THREAD_DEVTOOLSADB = 38,
+ THREAD_NETWORKCONFIGWATCHER = 39,
+ THREAD_WASAPI_RENDER = 40,
+ THREAD_LOADER_LOCK_SAMPLER = 41,
+ THREAD_MEMORY_INFRA = 50,
+ THREAD_SAMPLING_PROFILER = 51,
+};
+} // namespace perfetto_pbzero_enum_ChromeThreadDescriptor
+using ChromeThreadDescriptor_ThreadType = perfetto_pbzero_enum_ChromeThreadDescriptor::ThreadType;
+
+
+constexpr ChromeThreadDescriptor_ThreadType ChromeThreadDescriptor_ThreadType_MIN = ChromeThreadDescriptor_ThreadType::THREAD_UNSPECIFIED;
+constexpr ChromeThreadDescriptor_ThreadType ChromeThreadDescriptor_ThreadType_MAX = ChromeThreadDescriptor_ThreadType::THREAD_SAMPLING_PROFILER;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ChromeThreadDescriptor_ThreadType_Name(::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_UNSPECIFIED:
+ return "THREAD_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_MAIN:
+ return "THREAD_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_IO:
+ return "THREAD_IO";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_POOL_BG_WORKER:
+ return "THREAD_POOL_BG_WORKER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_POOL_FG_WORKER:
+ return "THREAD_POOL_FG_WORKER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_POOL_FG_BLOCKING:
+ return "THREAD_POOL_FG_BLOCKING";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_POOL_BG_BLOCKING:
+ return "THREAD_POOL_BG_BLOCKING";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_POOL_SERVICE:
+ return "THREAD_POOL_SERVICE";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_COMPOSITOR:
+ return "THREAD_COMPOSITOR";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_VIZ_COMPOSITOR:
+ return "THREAD_VIZ_COMPOSITOR";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_COMPOSITOR_WORKER:
+ return "THREAD_COMPOSITOR_WORKER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_SERVICE_WORKER:
+ return "THREAD_SERVICE_WORKER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_NETWORK_SERVICE:
+ return "THREAD_NETWORK_SERVICE";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_CHILD_IO:
+ return "THREAD_CHILD_IO";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_BROWSER_IO:
+ return "THREAD_BROWSER_IO";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_BROWSER_MAIN:
+ return "THREAD_BROWSER_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_RENDERER_MAIN:
+ return "THREAD_RENDERER_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_UTILITY_MAIN:
+ return "THREAD_UTILITY_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_GPU_MAIN:
+ return "THREAD_GPU_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_CACHE_BLOCKFILE:
+ return "THREAD_CACHE_BLOCKFILE";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_MEDIA:
+ return "THREAD_MEDIA";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_AUDIO_OUTPUTDEVICE:
+ return "THREAD_AUDIO_OUTPUTDEVICE";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_AUDIO_INPUTDEVICE:
+ return "THREAD_AUDIO_INPUTDEVICE";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_GPU_MEMORY:
+ return "THREAD_GPU_MEMORY";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_GPU_VSYNC:
+ return "THREAD_GPU_VSYNC";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_DXA_VIDEODECODER:
+ return "THREAD_DXA_VIDEODECODER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_BROWSER_WATCHDOG:
+ return "THREAD_BROWSER_WATCHDOG";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_WEBRTC_NETWORK:
+ return "THREAD_WEBRTC_NETWORK";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_WINDOW_OWNER:
+ return "THREAD_WINDOW_OWNER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_WEBRTC_SIGNALING:
+ return "THREAD_WEBRTC_SIGNALING";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_WEBRTC_WORKER:
+ return "THREAD_WEBRTC_WORKER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_PPAPI_MAIN:
+ return "THREAD_PPAPI_MAIN";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_GPU_WATCHDOG:
+ return "THREAD_GPU_WATCHDOG";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_SWAPPER:
+ return "THREAD_SWAPPER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_GAMEPAD_POLLING:
+ return "THREAD_GAMEPAD_POLLING";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_WEBCRYPTO:
+ return "THREAD_WEBCRYPTO";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_DATABASE:
+ return "THREAD_DATABASE";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_PROXYRESOLVER:
+ return "THREAD_PROXYRESOLVER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_DEVTOOLSADB:
+ return "THREAD_DEVTOOLSADB";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_NETWORKCONFIGWATCHER:
+ return "THREAD_NETWORKCONFIGWATCHER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_WASAPI_RENDER:
+ return "THREAD_WASAPI_RENDER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_LOADER_LOCK_SAMPLER:
+ return "THREAD_LOADER_LOCK_SAMPLER";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_MEMORY_INFRA:
+ return "THREAD_MEMORY_INFRA";
+
+ case ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType::THREAD_SAMPLING_PROFILER:
+ return "THREAD_SAMPLING_PROFILER";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ChromeThreadDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeThreadDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeThreadDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeThreadDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_thread_type() const { return at<1>().valid(); }
+ int32_t thread_type() const { return at<1>().as_int32(); }
+ bool has_legacy_sort_index() const { return at<2>().valid(); }
+ int32_t legacy_sort_index() const { return at<2>().as_int32(); }
+};
+
+class ChromeThreadDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = ChromeThreadDescriptor_Decoder;
+ enum : int32_t {
+ kThreadTypeFieldNumber = 1,
+ kLegacySortIndexFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeThreadDescriptor"; }
+
+
+ using ThreadType = ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType;
+ static inline const char* ThreadType_Name(ThreadType value) {
+ return ::perfetto::protos::pbzero::ChromeThreadDescriptor_ThreadType_Name(value);
+ }
+ static inline const ThreadType THREAD_UNSPECIFIED = ThreadType::THREAD_UNSPECIFIED;
+ static inline const ThreadType THREAD_MAIN = ThreadType::THREAD_MAIN;
+ static inline const ThreadType THREAD_IO = ThreadType::THREAD_IO;
+ static inline const ThreadType THREAD_POOL_BG_WORKER = ThreadType::THREAD_POOL_BG_WORKER;
+ static inline const ThreadType THREAD_POOL_FG_WORKER = ThreadType::THREAD_POOL_FG_WORKER;
+ static inline const ThreadType THREAD_POOL_FG_BLOCKING = ThreadType::THREAD_POOL_FG_BLOCKING;
+ static inline const ThreadType THREAD_POOL_BG_BLOCKING = ThreadType::THREAD_POOL_BG_BLOCKING;
+ static inline const ThreadType THREAD_POOL_SERVICE = ThreadType::THREAD_POOL_SERVICE;
+ static inline const ThreadType THREAD_COMPOSITOR = ThreadType::THREAD_COMPOSITOR;
+ static inline const ThreadType THREAD_VIZ_COMPOSITOR = ThreadType::THREAD_VIZ_COMPOSITOR;
+ static inline const ThreadType THREAD_COMPOSITOR_WORKER = ThreadType::THREAD_COMPOSITOR_WORKER;
+ static inline const ThreadType THREAD_SERVICE_WORKER = ThreadType::THREAD_SERVICE_WORKER;
+ static inline const ThreadType THREAD_NETWORK_SERVICE = ThreadType::THREAD_NETWORK_SERVICE;
+ static inline const ThreadType THREAD_CHILD_IO = ThreadType::THREAD_CHILD_IO;
+ static inline const ThreadType THREAD_BROWSER_IO = ThreadType::THREAD_BROWSER_IO;
+ static inline const ThreadType THREAD_BROWSER_MAIN = ThreadType::THREAD_BROWSER_MAIN;
+ static inline const ThreadType THREAD_RENDERER_MAIN = ThreadType::THREAD_RENDERER_MAIN;
+ static inline const ThreadType THREAD_UTILITY_MAIN = ThreadType::THREAD_UTILITY_MAIN;
+ static inline const ThreadType THREAD_GPU_MAIN = ThreadType::THREAD_GPU_MAIN;
+ static inline const ThreadType THREAD_CACHE_BLOCKFILE = ThreadType::THREAD_CACHE_BLOCKFILE;
+ static inline const ThreadType THREAD_MEDIA = ThreadType::THREAD_MEDIA;
+ static inline const ThreadType THREAD_AUDIO_OUTPUTDEVICE = ThreadType::THREAD_AUDIO_OUTPUTDEVICE;
+ static inline const ThreadType THREAD_AUDIO_INPUTDEVICE = ThreadType::THREAD_AUDIO_INPUTDEVICE;
+ static inline const ThreadType THREAD_GPU_MEMORY = ThreadType::THREAD_GPU_MEMORY;
+ static inline const ThreadType THREAD_GPU_VSYNC = ThreadType::THREAD_GPU_VSYNC;
+ static inline const ThreadType THREAD_DXA_VIDEODECODER = ThreadType::THREAD_DXA_VIDEODECODER;
+ static inline const ThreadType THREAD_BROWSER_WATCHDOG = ThreadType::THREAD_BROWSER_WATCHDOG;
+ static inline const ThreadType THREAD_WEBRTC_NETWORK = ThreadType::THREAD_WEBRTC_NETWORK;
+ static inline const ThreadType THREAD_WINDOW_OWNER = ThreadType::THREAD_WINDOW_OWNER;
+ static inline const ThreadType THREAD_WEBRTC_SIGNALING = ThreadType::THREAD_WEBRTC_SIGNALING;
+ static inline const ThreadType THREAD_WEBRTC_WORKER = ThreadType::THREAD_WEBRTC_WORKER;
+ static inline const ThreadType THREAD_PPAPI_MAIN = ThreadType::THREAD_PPAPI_MAIN;
+ static inline const ThreadType THREAD_GPU_WATCHDOG = ThreadType::THREAD_GPU_WATCHDOG;
+ static inline const ThreadType THREAD_SWAPPER = ThreadType::THREAD_SWAPPER;
+ static inline const ThreadType THREAD_GAMEPAD_POLLING = ThreadType::THREAD_GAMEPAD_POLLING;
+ static inline const ThreadType THREAD_WEBCRYPTO = ThreadType::THREAD_WEBCRYPTO;
+ static inline const ThreadType THREAD_DATABASE = ThreadType::THREAD_DATABASE;
+ static inline const ThreadType THREAD_PROXYRESOLVER = ThreadType::THREAD_PROXYRESOLVER;
+ static inline const ThreadType THREAD_DEVTOOLSADB = ThreadType::THREAD_DEVTOOLSADB;
+ static inline const ThreadType THREAD_NETWORKCONFIGWATCHER = ThreadType::THREAD_NETWORKCONFIGWATCHER;
+ static inline const ThreadType THREAD_WASAPI_RENDER = ThreadType::THREAD_WASAPI_RENDER;
+ static inline const ThreadType THREAD_LOADER_LOCK_SAMPLER = ThreadType::THREAD_LOADER_LOCK_SAMPLER;
+ static inline const ThreadType THREAD_MEMORY_INFRA = ThreadType::THREAD_MEMORY_INFRA;
+ static inline const ThreadType THREAD_SAMPLING_PROFILER = ThreadType::THREAD_SAMPLING_PROFILER;
+
+ using FieldMetadata_ThreadType =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ChromeThreadDescriptor_ThreadType,
+ ChromeThreadDescriptor>;
+
+ static constexpr FieldMetadata_ThreadType kThreadType{};
+ void set_thread_type(ChromeThreadDescriptor_ThreadType value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LegacySortIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ChromeThreadDescriptor>;
+
+ static constexpr FieldMetadata_LegacySortIndex kLegacySortIndex{};
+ void set_legacy_sort_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LegacySortIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_user_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_USER_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_USER_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeUserEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeUserEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeUserEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeUserEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_action() const { return at<1>().valid(); }
+ ::protozero::ConstChars action() const { return at<1>().as_string(); }
+ bool has_action_hash() const { return at<2>().valid(); }
+ uint64_t action_hash() const { return at<2>().as_uint64(); }
+};
+
+class ChromeUserEvent : public ::protozero::Message {
+ public:
+ using Decoder = ChromeUserEvent_Decoder;
+ enum : int32_t {
+ kActionFieldNumber = 1,
+ kActionHashFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeUserEvent"; }
+
+
+ using FieldMetadata_Action =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeUserEvent>;
+
+ static constexpr FieldMetadata_Action kAction{};
+ void set_action(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Action::kFieldId, data, size);
+ }
+ void set_action(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Action::kFieldId, chars.data, chars.size);
+ }
+ void set_action(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Action::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ActionHash =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeUserEvent>;
+
+ static constexpr FieldMetadata_ActionHash kActionHash{};
+ void set_action_hash(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ActionHash::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_window_handle_event_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_WINDOW_HANDLE_EVENT_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_WINDOW_HANDLE_EVENT_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ChromeWindowHandleEventInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeWindowHandleEventInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeWindowHandleEventInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeWindowHandleEventInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_dpi() const { return at<1>().valid(); }
+ uint32_t dpi() const { return at<1>().as_uint32(); }
+ bool has_message_id() const { return at<2>().valid(); }
+ uint32_t message_id() const { return at<2>().as_uint32(); }
+ bool has_hwnd_ptr() const { return at<3>().valid(); }
+ uint64_t hwnd_ptr() const { return at<3>().as_uint64(); }
+};
+
+class ChromeWindowHandleEventInfo : public ::protozero::Message {
+ public:
+ using Decoder = ChromeWindowHandleEventInfo_Decoder;
+ enum : int32_t {
+ kDpiFieldNumber = 1,
+ kMessageIdFieldNumber = 2,
+ kHwndPtrFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeWindowHandleEventInfo"; }
+
+
+ using FieldMetadata_Dpi =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeWindowHandleEventInfo>;
+
+ static constexpr FieldMetadata_Dpi kDpi{};
+ void set_dpi(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Dpi::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MessageId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromeWindowHandleEventInfo>;
+
+ static constexpr FieldMetadata_MessageId kMessageId{};
+ void set_message_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MessageId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HwndPtr =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64,
+ uint64_t,
+ ChromeWindowHandleEventInfo>;
+
+ static constexpr FieldMetadata_HwndPtr kHwndPtr{};
+ void set_hwnd_ptr(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_HwndPtr::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFixed64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/log_message.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_LogMessage {
+enum Priority : int32_t;
+} // namespace perfetto_pbzero_enum_LogMessage
+using LogMessage_Priority = perfetto_pbzero_enum_LogMessage::Priority;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_LogMessage {
+enum Priority : int32_t {
+ PRIO_UNSPECIFIED = 0,
+ PRIO_UNUSED = 1,
+ PRIO_VERBOSE = 2,
+ PRIO_DEBUG = 3,
+ PRIO_INFO = 4,
+ PRIO_WARN = 5,
+ PRIO_ERROR = 6,
+ PRIO_FATAL = 7,
+};
+} // namespace perfetto_pbzero_enum_LogMessage
+using LogMessage_Priority = perfetto_pbzero_enum_LogMessage::Priority;
+
+
+constexpr LogMessage_Priority LogMessage_Priority_MIN = LogMessage_Priority::PRIO_UNSPECIFIED;
+constexpr LogMessage_Priority LogMessage_Priority_MAX = LogMessage_Priority::PRIO_FATAL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* LogMessage_Priority_Name(::perfetto::protos::pbzero::LogMessage_Priority value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_UNSPECIFIED:
+ return "PRIO_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_UNUSED:
+ return "PRIO_UNUSED";
+
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_VERBOSE:
+ return "PRIO_VERBOSE";
+
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_DEBUG:
+ return "PRIO_DEBUG";
+
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_INFO:
+ return "PRIO_INFO";
+
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_WARN:
+ return "PRIO_WARN";
+
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_ERROR:
+ return "PRIO_ERROR";
+
+ case ::perfetto::protos::pbzero::LogMessage_Priority::PRIO_FATAL:
+ return "PRIO_FATAL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class LogMessageBody_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LogMessageBody_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LogMessageBody_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LogMessageBody_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_body() const { return at<2>().valid(); }
+ ::protozero::ConstChars body() const { return at<2>().as_string(); }
+};
+
+class LogMessageBody : public ::protozero::Message {
+ public:
+ using Decoder = LogMessageBody_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kBodyFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LogMessageBody"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LogMessageBody>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Body =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ LogMessageBody>;
+
+ static constexpr FieldMetadata_Body kBody{};
+ void set_body(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Body::kFieldId, data, size);
+ }
+ void set_body(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Body::kFieldId, chars.data, chars.size);
+ }
+ void set_body(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Body::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class LogMessage_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ LogMessage_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit LogMessage_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit LogMessage_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_source_location_iid() const { return at<1>().valid(); }
+ uint64_t source_location_iid() const { return at<1>().as_uint64(); }
+ bool has_body_iid() const { return at<2>().valid(); }
+ uint64_t body_iid() const { return at<2>().as_uint64(); }
+ bool has_prio() const { return at<3>().valid(); }
+ int32_t prio() const { return at<3>().as_int32(); }
+};
+
+class LogMessage : public ::protozero::Message {
+ public:
+ using Decoder = LogMessage_Decoder;
+ enum : int32_t {
+ kSourceLocationIidFieldNumber = 1,
+ kBodyIidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.LogMessage"; }
+
+
+ using Priority = ::perfetto::protos::pbzero::LogMessage_Priority;
+ static inline const char* Priority_Name(Priority value) {
+ return ::perfetto::protos::pbzero::LogMessage_Priority_Name(value);
+ }
+ static inline const Priority PRIO_UNSPECIFIED = Priority::PRIO_UNSPECIFIED;
+ static inline const Priority PRIO_UNUSED = Priority::PRIO_UNUSED;
+ static inline const Priority PRIO_VERBOSE = Priority::PRIO_VERBOSE;
+ static inline const Priority PRIO_DEBUG = Priority::PRIO_DEBUG;
+ static inline const Priority PRIO_INFO = Priority::PRIO_INFO;
+ static inline const Priority PRIO_WARN = Priority::PRIO_WARN;
+ static inline const Priority PRIO_ERROR = Priority::PRIO_ERROR;
+ static inline const Priority PRIO_FATAL = Priority::PRIO_FATAL;
+
+ using FieldMetadata_SourceLocationIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LogMessage>;
+
+ static constexpr FieldMetadata_SourceLocationIid kSourceLocationIid{};
+ void set_source_location_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceLocationIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BodyIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ LogMessage>;
+
+ static constexpr FieldMetadata_BodyIid kBodyIid{};
+ void set_body_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_BodyIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Prio =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ LogMessage_Priority,
+ LogMessage>;
+
+ static constexpr FieldMetadata_Prio kPrio{};
+ void set_prio(LogMessage_Priority value) {
+ static constexpr uint32_t field_id = FieldMetadata_Prio::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/pixel_modem.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PIXEL_MODEM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PIXEL_MODEM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class PixelModemEventInsight_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PixelModemEventInsight_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PixelModemEventInsight_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PixelModemEventInsight_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_detokenized_message() const { return at<1>().valid(); }
+ ::protozero::ConstChars detokenized_message() const { return at<1>().as_string(); }
+};
+
+class PixelModemEventInsight : public ::protozero::Message {
+ public:
+ using Decoder = PixelModemEventInsight_Decoder;
+ enum : int32_t {
+ kDetokenizedMessageFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PixelModemEventInsight"; }
+
+
+ using FieldMetadata_DetokenizedMessage =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PixelModemEventInsight>;
+
+ static constexpr FieldMetadata_DetokenizedMessage kDetokenizedMessage{};
+ void set_detokenized_message(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DetokenizedMessage::kFieldId, data, size);
+ }
+ void set_detokenized_message(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DetokenizedMessage::kFieldId, chars.data, chars.size);
+ }
+ void set_detokenized_message(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DetokenizedMessage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/process_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ProcessDescriptor {
+enum ChromeProcessType : int32_t;
+} // namespace perfetto_pbzero_enum_ProcessDescriptor
+using ProcessDescriptor_ChromeProcessType = perfetto_pbzero_enum_ProcessDescriptor::ChromeProcessType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ProcessDescriptor {
+enum ChromeProcessType : int32_t {
+ PROCESS_UNSPECIFIED = 0,
+ PROCESS_BROWSER = 1,
+ PROCESS_RENDERER = 2,
+ PROCESS_UTILITY = 3,
+ PROCESS_ZYGOTE = 4,
+ PROCESS_SANDBOX_HELPER = 5,
+ PROCESS_GPU = 6,
+ PROCESS_PPAPI_PLUGIN = 7,
+ PROCESS_PPAPI_BROKER = 8,
+};
+} // namespace perfetto_pbzero_enum_ProcessDescriptor
+using ProcessDescriptor_ChromeProcessType = perfetto_pbzero_enum_ProcessDescriptor::ChromeProcessType;
+
+
+constexpr ProcessDescriptor_ChromeProcessType ProcessDescriptor_ChromeProcessType_MIN = ProcessDescriptor_ChromeProcessType::PROCESS_UNSPECIFIED;
+constexpr ProcessDescriptor_ChromeProcessType ProcessDescriptor_ChromeProcessType_MAX = ProcessDescriptor_ChromeProcessType::PROCESS_PPAPI_BROKER;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ProcessDescriptor_ChromeProcessType_Name(::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_UNSPECIFIED:
+ return "PROCESS_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_BROWSER:
+ return "PROCESS_BROWSER";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_RENDERER:
+ return "PROCESS_RENDERER";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_UTILITY:
+ return "PROCESS_UTILITY";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_ZYGOTE:
+ return "PROCESS_ZYGOTE";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_SANDBOX_HELPER:
+ return "PROCESS_SANDBOX_HELPER";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_GPU:
+ return "PROCESS_GPU";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_PPAPI_PLUGIN:
+ return "PROCESS_PPAPI_PLUGIN";
+
+ case ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType::PROCESS_PPAPI_BROKER:
+ return "PROCESS_PPAPI_BROKER";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ProcessDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProcessDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_cmdline() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> cmdline() const { return GetRepeated<::protozero::ConstChars>(2); }
+ bool has_process_name() const { return at<6>().valid(); }
+ ::protozero::ConstChars process_name() const { return at<6>().as_string(); }
+ bool has_process_priority() const { return at<5>().valid(); }
+ int32_t process_priority() const { return at<5>().as_int32(); }
+ bool has_start_timestamp_ns() const { return at<7>().valid(); }
+ int64_t start_timestamp_ns() const { return at<7>().as_int64(); }
+ bool has_chrome_process_type() const { return at<4>().valid(); }
+ int32_t chrome_process_type() const { return at<4>().as_int32(); }
+ bool has_legacy_sort_index() const { return at<3>().valid(); }
+ int32_t legacy_sort_index() const { return at<3>().as_int32(); }
+ bool has_process_labels() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> process_labels() const { return GetRepeated<::protozero::ConstChars>(8); }
+};
+
+class ProcessDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = ProcessDescriptor_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kCmdlineFieldNumber = 2,
+ kProcessNameFieldNumber = 6,
+ kProcessPriorityFieldNumber = 5,
+ kStartTimestampNsFieldNumber = 7,
+ kChromeProcessTypeFieldNumber = 4,
+ kLegacySortIndexFieldNumber = 3,
+ kProcessLabelsFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessDescriptor"; }
+
+
+ using ChromeProcessType = ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType;
+ static inline const char* ChromeProcessType_Name(ChromeProcessType value) {
+ return ::perfetto::protos::pbzero::ProcessDescriptor_ChromeProcessType_Name(value);
+ }
+ static inline const ChromeProcessType PROCESS_UNSPECIFIED = ChromeProcessType::PROCESS_UNSPECIFIED;
+ static inline const ChromeProcessType PROCESS_BROWSER = ChromeProcessType::PROCESS_BROWSER;
+ static inline const ChromeProcessType PROCESS_RENDERER = ChromeProcessType::PROCESS_RENDERER;
+ static inline const ChromeProcessType PROCESS_UTILITY = ChromeProcessType::PROCESS_UTILITY;
+ static inline const ChromeProcessType PROCESS_ZYGOTE = ChromeProcessType::PROCESS_ZYGOTE;
+ static inline const ChromeProcessType PROCESS_SANDBOX_HELPER = ChromeProcessType::PROCESS_SANDBOX_HELPER;
+ static inline const ChromeProcessType PROCESS_GPU = ChromeProcessType::PROCESS_GPU;
+ static inline const ChromeProcessType PROCESS_PPAPI_PLUGIN = ChromeProcessType::PROCESS_PPAPI_PLUGIN;
+ static inline const ChromeProcessType PROCESS_PPAPI_BROKER = ChromeProcessType::PROCESS_PPAPI_BROKER;
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_Cmdline kCmdline{};
+ void add_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, data, size);
+ }
+ void add_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessName =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_ProcessName kProcessName{};
+ void set_process_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProcessName::kFieldId, data, size);
+ }
+ void set_process_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProcessName::kFieldId, chars.data, chars.size);
+ }
+ void set_process_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessPriority =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_ProcessPriority kProcessPriority{};
+ void set_process_priority(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessPriority::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StartTimestampNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_StartTimestampNs kStartTimestampNs{};
+ void set_start_timestamp_ns(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartTimestampNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChromeProcessType =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ProcessDescriptor_ChromeProcessType,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_ChromeProcessType kChromeProcessType{};
+ void set_chrome_process_type(ProcessDescriptor_ChromeProcessType value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChromeProcessType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LegacySortIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_LegacySortIndex kLegacySortIndex{};
+ void set_legacy_sort_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LegacySortIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessLabels =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProcessDescriptor>;
+
+ static constexpr FieldMetadata_ProcessLabels kProcessLabels{};
+ void add_process_labels(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ProcessLabels::kFieldId, data, size);
+ }
+ void add_process_labels(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ProcessLabels::kFieldId, chars.data, chars.size);
+ }
+ void add_process_labels(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessLabels::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/range_of_interest.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_RANGE_OF_INTEREST_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_RANGE_OF_INTEREST_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TrackEventRangeOfInterest_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TrackEventRangeOfInterest_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TrackEventRangeOfInterest_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TrackEventRangeOfInterest_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_start_us() const { return at<1>().valid(); }
+ int64_t start_us() const { return at<1>().as_int64(); }
+};
+
+class TrackEventRangeOfInterest : public ::protozero::Message {
+ public:
+ using Decoder = TrackEventRangeOfInterest_Decoder;
+ enum : int32_t {
+ kStartUsFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TrackEventRangeOfInterest"; }
+
+
+ using FieldMetadata_StartUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ TrackEventRangeOfInterest>;
+
+ static constexpr FieldMetadata_StartUs kStartUs{};
+ void set_start_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StartUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/screenshot.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SCREENSHOT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SCREENSHOT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class Screenshot_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Screenshot_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Screenshot_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Screenshot_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_jpg_image() const { return at<1>().valid(); }
+ ::protozero::ConstBytes jpg_image() const { return at<1>().as_bytes(); }
+};
+
+class Screenshot : public ::protozero::Message {
+ public:
+ using Decoder = Screenshot_Decoder;
+ enum : int32_t {
+ kJpgImageFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Screenshot"; }
+
+
+ using FieldMetadata_JpgImage =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBytes,
+ std::string,
+ Screenshot>;
+
+ static constexpr FieldMetadata_JpgImage kJpgImage{};
+ void set_jpg_image(const uint8_t* data, size_t size) {
+ AppendBytes(FieldMetadata_JpgImage::kFieldId, data, size);
+ }
+ void set_jpg_image(::protozero::ConstBytes bytes) {
+ AppendBytes(FieldMetadata_JpgImage::kFieldId, bytes.data, bytes.size);
+ }
+ void set_jpg_image(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_JpgImage::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBytes>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/source_location.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SourceLocation_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SourceLocation_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SourceLocation_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SourceLocation_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_file_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars file_name() const { return at<2>().as_string(); }
+ bool has_function_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars function_name() const { return at<3>().as_string(); }
+ bool has_line_number() const { return at<4>().valid(); }
+ uint32_t line_number() const { return at<4>().as_uint32(); }
+};
+
+class SourceLocation : public ::protozero::Message {
+ public:
+ using Decoder = SourceLocation_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kFileNameFieldNumber = 2,
+ kFunctionNameFieldNumber = 3,
+ kLineNumberFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SourceLocation"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SourceLocation>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FileName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SourceLocation>;
+
+ static constexpr FieldMetadata_FileName kFileName{};
+ void set_file_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FileName::kFieldId, data, size);
+ }
+ void set_file_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FileName::kFieldId, chars.data, chars.size);
+ }
+ void set_file_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FileName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FunctionName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SourceLocation>;
+
+ static constexpr FieldMetadata_FunctionName kFunctionName{};
+ void set_function_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_FunctionName::kFieldId, data, size);
+ }
+ void set_function_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_FunctionName::kFieldId, chars.data, chars.size);
+ }
+ void set_function_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_FunctionName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LineNumber =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SourceLocation>;
+
+ static constexpr FieldMetadata_LineNumber kLineNumber{};
+ void set_line_number(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LineNumber::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class UnsymbolizedSourceLocation_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ UnsymbolizedSourceLocation_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit UnsymbolizedSourceLocation_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit UnsymbolizedSourceLocation_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_mapping_id() const { return at<2>().valid(); }
+ uint64_t mapping_id() const { return at<2>().as_uint64(); }
+ bool has_rel_pc() const { return at<3>().valid(); }
+ uint64_t rel_pc() const { return at<3>().as_uint64(); }
+};
+
+class UnsymbolizedSourceLocation : public ::protozero::Message {
+ public:
+ using Decoder = UnsymbolizedSourceLocation_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kMappingIdFieldNumber = 2,
+ kRelPcFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.UnsymbolizedSourceLocation"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ UnsymbolizedSourceLocation>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_MappingId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ UnsymbolizedSourceLocation>;
+
+ static constexpr FieldMetadata_MappingId kMappingId{};
+ void set_mapping_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_MappingId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RelPc =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ UnsymbolizedSourceLocation>;
+
+ static constexpr FieldMetadata_RelPc kRelPc{};
+ void set_rel_pc(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RelPc::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/task_execution.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TaskExecution_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TaskExecution_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TaskExecution_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TaskExecution_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_posted_from_iid() const { return at<1>().valid(); }
+ uint64_t posted_from_iid() const { return at<1>().as_uint64(); }
+};
+
+class TaskExecution : public ::protozero::Message {
+ public:
+ using Decoder = TaskExecution_Decoder;
+ enum : int32_t {
+ kPostedFromIidFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TaskExecution"; }
+
+
+ using FieldMetadata_PostedFromIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TaskExecution>;
+
+ static constexpr FieldMetadata_PostedFromIid kPostedFromIid{};
+ void set_posted_from_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_PostedFromIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/thread_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+namespace perfetto_pbzero_enum_ThreadDescriptor {
+enum ChromeThreadType : int32_t;
+} // namespace perfetto_pbzero_enum_ThreadDescriptor
+using ThreadDescriptor_ChromeThreadType = perfetto_pbzero_enum_ThreadDescriptor::ChromeThreadType;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_ThreadDescriptor {
+enum ChromeThreadType : int32_t {
+ CHROME_THREAD_UNSPECIFIED = 0,
+ CHROME_THREAD_MAIN = 1,
+ CHROME_THREAD_IO = 2,
+ CHROME_THREAD_POOL_BG_WORKER = 3,
+ CHROME_THREAD_POOL_FG_WORKER = 4,
+ CHROME_THREAD_POOL_FB_BLOCKING = 5,
+ CHROME_THREAD_POOL_BG_BLOCKING = 6,
+ CHROME_THREAD_POOL_SERVICE = 7,
+ CHROME_THREAD_COMPOSITOR = 8,
+ CHROME_THREAD_VIZ_COMPOSITOR = 9,
+ CHROME_THREAD_COMPOSITOR_WORKER = 10,
+ CHROME_THREAD_SERVICE_WORKER = 11,
+ CHROME_THREAD_MEMORY_INFRA = 50,
+ CHROME_THREAD_SAMPLING_PROFILER = 51,
+};
+} // namespace perfetto_pbzero_enum_ThreadDescriptor
+using ThreadDescriptor_ChromeThreadType = perfetto_pbzero_enum_ThreadDescriptor::ChromeThreadType;
+
+
+constexpr ThreadDescriptor_ChromeThreadType ThreadDescriptor_ChromeThreadType_MIN = ThreadDescriptor_ChromeThreadType::CHROME_THREAD_UNSPECIFIED;
+constexpr ThreadDescriptor_ChromeThreadType ThreadDescriptor_ChromeThreadType_MAX = ThreadDescriptor_ChromeThreadType::CHROME_THREAD_SAMPLING_PROFILER;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* ThreadDescriptor_ChromeThreadType_Name(::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_UNSPECIFIED:
+ return "CHROME_THREAD_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_MAIN:
+ return "CHROME_THREAD_MAIN";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_IO:
+ return "CHROME_THREAD_IO";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_POOL_BG_WORKER:
+ return "CHROME_THREAD_POOL_BG_WORKER";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_POOL_FG_WORKER:
+ return "CHROME_THREAD_POOL_FG_WORKER";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_POOL_FB_BLOCKING:
+ return "CHROME_THREAD_POOL_FB_BLOCKING";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_POOL_BG_BLOCKING:
+ return "CHROME_THREAD_POOL_BG_BLOCKING";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_POOL_SERVICE:
+ return "CHROME_THREAD_POOL_SERVICE";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_COMPOSITOR:
+ return "CHROME_THREAD_COMPOSITOR";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_VIZ_COMPOSITOR:
+ return "CHROME_THREAD_VIZ_COMPOSITOR";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_COMPOSITOR_WORKER:
+ return "CHROME_THREAD_COMPOSITOR_WORKER";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_SERVICE_WORKER:
+ return "CHROME_THREAD_SERVICE_WORKER";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_MEMORY_INFRA:
+ return "CHROME_THREAD_MEMORY_INFRA";
+
+ case ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType::CHROME_THREAD_SAMPLING_PROFILER:
+ return "CHROME_THREAD_SAMPLING_PROFILER";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class ThreadDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ThreadDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ThreadDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ThreadDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_tid() const { return at<2>().valid(); }
+ int32_t tid() const { return at<2>().as_int32(); }
+ bool has_thread_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars thread_name() const { return at<5>().as_string(); }
+ bool has_chrome_thread_type() const { return at<4>().valid(); }
+ int32_t chrome_thread_type() const { return at<4>().as_int32(); }
+ bool has_reference_timestamp_us() const { return at<6>().valid(); }
+ int64_t reference_timestamp_us() const { return at<6>().as_int64(); }
+ bool has_reference_thread_time_us() const { return at<7>().valid(); }
+ int64_t reference_thread_time_us() const { return at<7>().as_int64(); }
+ bool has_reference_thread_instruction_count() const { return at<8>().valid(); }
+ int64_t reference_thread_instruction_count() const { return at<8>().as_int64(); }
+ bool has_legacy_sort_index() const { return at<3>().valid(); }
+ int32_t legacy_sort_index() const { return at<3>().as_int32(); }
+};
+
+class ThreadDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = ThreadDescriptor_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kTidFieldNumber = 2,
+ kThreadNameFieldNumber = 5,
+ kChromeThreadTypeFieldNumber = 4,
+ kReferenceTimestampUsFieldNumber = 6,
+ kReferenceThreadTimeUsFieldNumber = 7,
+ kReferenceThreadInstructionCountFieldNumber = 8,
+ kLegacySortIndexFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ThreadDescriptor"; }
+
+
+ using ChromeThreadType = ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType;
+ static inline const char* ChromeThreadType_Name(ChromeThreadType value) {
+ return ::perfetto::protos::pbzero::ThreadDescriptor_ChromeThreadType_Name(value);
+ }
+ static inline const ChromeThreadType CHROME_THREAD_UNSPECIFIED = ChromeThreadType::CHROME_THREAD_UNSPECIFIED;
+ static inline const ChromeThreadType CHROME_THREAD_MAIN = ChromeThreadType::CHROME_THREAD_MAIN;
+ static inline const ChromeThreadType CHROME_THREAD_IO = ChromeThreadType::CHROME_THREAD_IO;
+ static inline const ChromeThreadType CHROME_THREAD_POOL_BG_WORKER = ChromeThreadType::CHROME_THREAD_POOL_BG_WORKER;
+ static inline const ChromeThreadType CHROME_THREAD_POOL_FG_WORKER = ChromeThreadType::CHROME_THREAD_POOL_FG_WORKER;
+ static inline const ChromeThreadType CHROME_THREAD_POOL_FB_BLOCKING = ChromeThreadType::CHROME_THREAD_POOL_FB_BLOCKING;
+ static inline const ChromeThreadType CHROME_THREAD_POOL_BG_BLOCKING = ChromeThreadType::CHROME_THREAD_POOL_BG_BLOCKING;
+ static inline const ChromeThreadType CHROME_THREAD_POOL_SERVICE = ChromeThreadType::CHROME_THREAD_POOL_SERVICE;
+ static inline const ChromeThreadType CHROME_THREAD_COMPOSITOR = ChromeThreadType::CHROME_THREAD_COMPOSITOR;
+ static inline const ChromeThreadType CHROME_THREAD_VIZ_COMPOSITOR = ChromeThreadType::CHROME_THREAD_VIZ_COMPOSITOR;
+ static inline const ChromeThreadType CHROME_THREAD_COMPOSITOR_WORKER = ChromeThreadType::CHROME_THREAD_COMPOSITOR_WORKER;
+ static inline const ChromeThreadType CHROME_THREAD_SERVICE_WORKER = ChromeThreadType::CHROME_THREAD_SERVICE_WORKER;
+ static inline const ChromeThreadType CHROME_THREAD_MEMORY_INFRA = ChromeThreadType::CHROME_THREAD_MEMORY_INFRA;
+ static inline const ChromeThreadType CHROME_THREAD_SAMPLING_PROFILER = ChromeThreadType::CHROME_THREAD_SAMPLING_PROFILER;
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadName =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_ThreadName kThreadName{};
+ void set_thread_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ThreadName::kFieldId, data, size);
+ }
+ void set_thread_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ThreadName::kFieldId, chars.data, chars.size);
+ }
+ void set_thread_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChromeThreadType =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ ThreadDescriptor_ChromeThreadType,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_ChromeThreadType kChromeThreadType{};
+ void set_chrome_thread_type(ThreadDescriptor_ChromeThreadType value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChromeThreadType::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReferenceTimestampUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_ReferenceTimestampUs kReferenceTimestampUs{};
+ void set_reference_timestamp_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReferenceTimestampUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReferenceThreadTimeUs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_ReferenceThreadTimeUs kReferenceThreadTimeUs{};
+ void set_reference_thread_time_us(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReferenceThreadTimeUs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReferenceThreadInstructionCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_ReferenceThreadInstructionCount kReferenceThreadInstructionCount{};
+ void set_reference_thread_instruction_count(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReferenceThreadInstructionCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LegacySortIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ThreadDescriptor>;
+
+ static constexpr FieldMetadata_LegacySortIndex kLegacySortIndex{};
+ void set_legacy_sort_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LegacySortIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PERFETTO_PERFETTO_METATRACE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PERFETTO_PERFETTO_METATRACE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class PerfettoMetatrace_Arg;
+class PerfettoMetatrace_InternedString;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class PerfettoMetatrace_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/11, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ PerfettoMetatrace_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfettoMetatrace_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfettoMetatrace_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_event_id() const { return at<1>().valid(); }
+ uint32_t event_id() const { return at<1>().as_uint32(); }
+ bool has_counter_id() const { return at<2>().valid(); }
+ uint32_t counter_id() const { return at<2>().as_uint32(); }
+ bool has_event_name() const { return at<8>().valid(); }
+ ::protozero::ConstChars event_name() const { return at<8>().as_string(); }
+ bool has_event_name_iid() const { return at<11>().valid(); }
+ uint64_t event_name_iid() const { return at<11>().as_uint64(); }
+ bool has_counter_name() const { return at<9>().valid(); }
+ ::protozero::ConstChars counter_name() const { return at<9>().as_string(); }
+ bool has_event_duration_ns() const { return at<3>().valid(); }
+ uint64_t event_duration_ns() const { return at<3>().as_uint64(); }
+ bool has_counter_value() const { return at<4>().valid(); }
+ int32_t counter_value() const { return at<4>().as_int32(); }
+ bool has_thread_id() const { return at<5>().valid(); }
+ uint32_t thread_id() const { return at<5>().as_uint32(); }
+ bool has_has_overruns() const { return at<6>().valid(); }
+ bool has_overruns() const { return at<6>().as_bool(); }
+ bool has_args() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> args() const { return GetRepeated<::protozero::ConstBytes>(7); }
+ bool has_interned_strings() const { return at<10>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> interned_strings() const { return GetRepeated<::protozero::ConstBytes>(10); }
+};
+
+class PerfettoMetatrace : public ::protozero::Message {
+ public:
+ using Decoder = PerfettoMetatrace_Decoder;
+ enum : int32_t {
+ kEventIdFieldNumber = 1,
+ kCounterIdFieldNumber = 2,
+ kEventNameFieldNumber = 8,
+ kEventNameIidFieldNumber = 11,
+ kCounterNameFieldNumber = 9,
+ kEventDurationNsFieldNumber = 3,
+ kCounterValueFieldNumber = 4,
+ kThreadIdFieldNumber = 5,
+ kHasOverrunsFieldNumber = 6,
+ kArgsFieldNumber = 7,
+ kInternedStringsFieldNumber = 10,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfettoMetatrace"; }
+
+ using Arg = ::perfetto::protos::pbzero::PerfettoMetatrace_Arg;
+ using InternedString = ::perfetto::protos::pbzero::PerfettoMetatrace_InternedString;
+
+ using FieldMetadata_EventId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_EventId kEventId{};
+ void set_event_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CounterId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_CounterId kCounterId{};
+ void set_counter_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EventName =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_EventName kEventName{};
+ void set_event_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_EventName::kFieldId, data, size);
+ }
+ void set_event_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_EventName::kFieldId, chars.data, chars.size);
+ }
+ void set_event_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EventNameIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_EventNameIid kEventNameIid{};
+ void set_event_name_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventNameIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CounterName =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_CounterName kCounterName{};
+ void set_counter_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_CounterName::kFieldId, data, size);
+ }
+ void set_counter_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_CounterName::kFieldId, chars.data, chars.size);
+ }
+ void set_counter_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EventDurationNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_EventDurationNs kEventDurationNs{};
+ void set_event_duration_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EventDurationNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CounterValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_CounterValue kCounterValue{};
+ void set_counter_value(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CounterValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ThreadId =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_ThreadId kThreadId{};
+ void set_thread_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ThreadId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HasOverruns =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_HasOverruns kHasOverruns{};
+ void set_has_overruns(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_HasOverruns::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Args =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfettoMetatrace_Arg,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_Args kArgs{};
+ template <typename T = PerfettoMetatrace_Arg> T* add_args() {
+ return BeginNestedMessage<T>(7);
+ }
+
+
+ using FieldMetadata_InternedStrings =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfettoMetatrace_InternedString,
+ PerfettoMetatrace>;
+
+ static constexpr FieldMetadata_InternedStrings kInternedStrings{};
+ template <typename T = PerfettoMetatrace_InternedString> T* add_interned_strings() {
+ return BeginNestedMessage<T>(10);
+ }
+
+};
+
+class PerfettoMetatrace_InternedString_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfettoMetatrace_InternedString_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfettoMetatrace_InternedString_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfettoMetatrace_InternedString_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_iid() const { return at<1>().valid(); }
+ uint64_t iid() const { return at<1>().as_uint64(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class PerfettoMetatrace_InternedString : public ::protozero::Message {
+ public:
+ using Decoder = PerfettoMetatrace_InternedString_Decoder;
+ enum : int32_t {
+ kIidFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfettoMetatrace.InternedString"; }
+
+
+ using FieldMetadata_Iid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfettoMetatrace_InternedString>;
+
+ static constexpr FieldMetadata_Iid kIid{};
+ void set_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfettoMetatrace_InternedString>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PerfettoMetatrace_Arg_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PerfettoMetatrace_Arg_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PerfettoMetatrace_Arg_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PerfettoMetatrace_Arg_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ ::protozero::ConstChars key() const { return at<1>().as_string(); }
+ bool has_key_iid() const { return at<3>().valid(); }
+ uint64_t key_iid() const { return at<3>().as_uint64(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+ bool has_value_iid() const { return at<4>().valid(); }
+ uint64_t value_iid() const { return at<4>().as_uint64(); }
+};
+
+class PerfettoMetatrace_Arg : public ::protozero::Message {
+ public:
+ using Decoder = PerfettoMetatrace_Arg_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kKeyIidFieldNumber = 3,
+ kValueFieldNumber = 2,
+ kValueIidFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PerfettoMetatrace.Arg"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfettoMetatrace_Arg>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Key::kFieldId, data, size);
+ }
+ void set_key(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Key::kFieldId, chars.data, chars.size);
+ }
+ void set_key(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_KeyIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfettoMetatrace_Arg>;
+
+ static constexpr FieldMetadata_KeyIid kKeyIid{};
+ void set_key_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_KeyIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PerfettoMetatrace_Arg>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ValueIid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PerfettoMetatrace_Arg>;
+
+ static constexpr FieldMetadata_ValueIid kValueIid{};
+ void set_value_iid(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ValueIid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PERFETTO_TRACING_SERVICE_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PERFETTO_TRACING_SERVICE_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TracingServiceEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/6, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TracingServiceEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracingServiceEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracingServiceEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tracing_started() const { return at<2>().valid(); }
+ bool tracing_started() const { return at<2>().as_bool(); }
+ bool has_all_data_sources_started() const { return at<1>().valid(); }
+ bool all_data_sources_started() const { return at<1>().as_bool(); }
+ bool has_all_data_sources_flushed() const { return at<3>().valid(); }
+ bool all_data_sources_flushed() const { return at<3>().as_bool(); }
+ bool has_read_tracing_buffers_completed() const { return at<4>().valid(); }
+ bool read_tracing_buffers_completed() const { return at<4>().as_bool(); }
+ bool has_tracing_disabled() const { return at<5>().valid(); }
+ bool tracing_disabled() const { return at<5>().as_bool(); }
+ bool has_seized_for_bugreport() const { return at<6>().valid(); }
+ bool seized_for_bugreport() const { return at<6>().as_bool(); }
+};
+
+class TracingServiceEvent : public ::protozero::Message {
+ public:
+ using Decoder = TracingServiceEvent_Decoder;
+ enum : int32_t {
+ kTracingStartedFieldNumber = 2,
+ kAllDataSourcesStartedFieldNumber = 1,
+ kAllDataSourcesFlushedFieldNumber = 3,
+ kReadTracingBuffersCompletedFieldNumber = 4,
+ kTracingDisabledFieldNumber = 5,
+ kSeizedForBugreportFieldNumber = 6,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracingServiceEvent"; }
+
+
+ using FieldMetadata_TracingStarted =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceEvent>;
+
+ static constexpr FieldMetadata_TracingStarted kTracingStarted{};
+ void set_tracing_started(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingStarted::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllDataSourcesStarted =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceEvent>;
+
+ static constexpr FieldMetadata_AllDataSourcesStarted kAllDataSourcesStarted{};
+ void set_all_data_sources_started(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllDataSourcesStarted::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllDataSourcesFlushed =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceEvent>;
+
+ static constexpr FieldMetadata_AllDataSourcesFlushed kAllDataSourcesFlushed{};
+ void set_all_data_sources_flushed(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_AllDataSourcesFlushed::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadTracingBuffersCompleted =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceEvent>;
+
+ static constexpr FieldMetadata_ReadTracingBuffersCompleted kReadTracingBuffersCompleted{};
+ void set_read_tracing_buffers_completed(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadTracingBuffersCompleted::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TracingDisabled =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceEvent>;
+
+ static constexpr FieldMetadata_TracingDisabled kTracingDisabled{};
+ void set_tracing_disabled(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_TracingDisabled::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SeizedForBugreport =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TracingServiceEvent>;
+
+ static constexpr FieldMetadata_SeizedForBugreport kSeizedForBugreport{};
+ void set_seized_for_bugreport(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_SeizedForBugreport::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/power/android_energy_estimation_breakdown.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_ANDROID_ENERGY_ESTIMATION_BREAKDOWN_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_ANDROID_ENERGY_ESTIMATION_BREAKDOWN_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class AndroidEnergyConsumerDescriptor;
+class AndroidEnergyEstimationBreakdown_EnergyUidBreakdown;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class AndroidEnergyEstimationBreakdown_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ AndroidEnergyEstimationBreakdown_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidEnergyEstimationBreakdown_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidEnergyEstimationBreakdown_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_energy_consumer_descriptor() const { return at<1>().valid(); }
+ ::protozero::ConstBytes energy_consumer_descriptor() const { return at<1>().as_bytes(); }
+ bool has_energy_consumer_id() const { return at<2>().valid(); }
+ int32_t energy_consumer_id() const { return at<2>().as_int32(); }
+ bool has_energy_uws() const { return at<3>().valid(); }
+ int64_t energy_uws() const { return at<3>().as_int64(); }
+ bool has_per_uid_breakdown() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> per_uid_breakdown() const { return GetRepeated<::protozero::ConstBytes>(4); }
+};
+
+class AndroidEnergyEstimationBreakdown : public ::protozero::Message {
+ public:
+ using Decoder = AndroidEnergyEstimationBreakdown_Decoder;
+ enum : int32_t {
+ kEnergyConsumerDescriptorFieldNumber = 1,
+ kEnergyConsumerIdFieldNumber = 2,
+ kEnergyUwsFieldNumber = 3,
+ kPerUidBreakdownFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidEnergyEstimationBreakdown"; }
+
+ using EnergyUidBreakdown = ::perfetto::protos::pbzero::AndroidEnergyEstimationBreakdown_EnergyUidBreakdown;
+
+ using FieldMetadata_EnergyConsumerDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidEnergyConsumerDescriptor,
+ AndroidEnergyEstimationBreakdown>;
+
+ static constexpr FieldMetadata_EnergyConsumerDescriptor kEnergyConsumerDescriptor{};
+ template <typename T = AndroidEnergyConsumerDescriptor> T* set_energy_consumer_descriptor() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_EnergyConsumerId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidEnergyEstimationBreakdown>;
+
+ static constexpr FieldMetadata_EnergyConsumerId kEnergyConsumerId{};
+ void set_energy_consumer_id(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnergyConsumerId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnergyUws =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidEnergyEstimationBreakdown>;
+
+ static constexpr FieldMetadata_EnergyUws kEnergyUws{};
+ void set_energy_uws(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnergyUws::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_PerUidBreakdown =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ AndroidEnergyEstimationBreakdown_EnergyUidBreakdown,
+ AndroidEnergyEstimationBreakdown>;
+
+ static constexpr FieldMetadata_PerUidBreakdown kPerUidBreakdown{};
+ template <typename T = AndroidEnergyEstimationBreakdown_EnergyUidBreakdown> T* add_per_uid_breakdown() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+class AndroidEnergyEstimationBreakdown_EnergyUidBreakdown_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ AndroidEnergyEstimationBreakdown_EnergyUidBreakdown_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit AndroidEnergyEstimationBreakdown_EnergyUidBreakdown_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit AndroidEnergyEstimationBreakdown_EnergyUidBreakdown_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_uid() const { return at<1>().valid(); }
+ int32_t uid() const { return at<1>().as_int32(); }
+ bool has_energy_uws() const { return at<2>().valid(); }
+ int64_t energy_uws() const { return at<2>().as_int64(); }
+};
+
+class AndroidEnergyEstimationBreakdown_EnergyUidBreakdown : public ::protozero::Message {
+ public:
+ using Decoder = AndroidEnergyEstimationBreakdown_EnergyUidBreakdown_Decoder;
+ enum : int32_t {
+ kUidFieldNumber = 1,
+ kEnergyUwsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.AndroidEnergyEstimationBreakdown.EnergyUidBreakdown"; }
+
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ AndroidEnergyEstimationBreakdown_EnergyUidBreakdown>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnergyUws =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ AndroidEnergyEstimationBreakdown_EnergyUidBreakdown>;
+
+ static constexpr FieldMetadata_EnergyUws kEnergyUws{};
+ void set_energy_uws(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnergyUws::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/power/android_entity_state_residency.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_ANDROID_ENTITY_STATE_RESIDENCY_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_ANDROID_ENTITY_STATE_RESIDENCY_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class EntityStateResidency_PowerEntityState;
+class EntityStateResidency_StateResidency;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class EntityStateResidency_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ EntityStateResidency_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EntityStateResidency_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EntityStateResidency_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_power_entity_state() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> power_entity_state() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_residency() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> residency() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class EntityStateResidency : public ::protozero::Message {
+ public:
+ using Decoder = EntityStateResidency_Decoder;
+ enum : int32_t {
+ kPowerEntityStateFieldNumber = 1,
+ kResidencyFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EntityStateResidency"; }
+
+ using PowerEntityState = ::perfetto::protos::pbzero::EntityStateResidency_PowerEntityState;
+ using StateResidency = ::perfetto::protos::pbzero::EntityStateResidency_StateResidency;
+
+ using FieldMetadata_PowerEntityState =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EntityStateResidency_PowerEntityState,
+ EntityStateResidency>;
+
+ static constexpr FieldMetadata_PowerEntityState kPowerEntityState{};
+ template <typename T = EntityStateResidency_PowerEntityState> T* add_power_entity_state() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Residency =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ EntityStateResidency_StateResidency,
+ EntityStateResidency>;
+
+ static constexpr FieldMetadata_Residency kResidency{};
+ template <typename T = EntityStateResidency_StateResidency> T* add_residency() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class EntityStateResidency_StateResidency_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ EntityStateResidency_StateResidency_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EntityStateResidency_StateResidency_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EntityStateResidency_StateResidency_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_entity_index() const { return at<1>().valid(); }
+ int32_t entity_index() const { return at<1>().as_int32(); }
+ bool has_state_index() const { return at<2>().valid(); }
+ int32_t state_index() const { return at<2>().as_int32(); }
+ bool has_total_time_in_state_ms() const { return at<3>().valid(); }
+ uint64_t total_time_in_state_ms() const { return at<3>().as_uint64(); }
+ bool has_total_state_entry_count() const { return at<4>().valid(); }
+ uint64_t total_state_entry_count() const { return at<4>().as_uint64(); }
+ bool has_last_entry_timestamp_ms() const { return at<5>().valid(); }
+ uint64_t last_entry_timestamp_ms() const { return at<5>().as_uint64(); }
+};
+
+class EntityStateResidency_StateResidency : public ::protozero::Message {
+ public:
+ using Decoder = EntityStateResidency_StateResidency_Decoder;
+ enum : int32_t {
+ kEntityIndexFieldNumber = 1,
+ kStateIndexFieldNumber = 2,
+ kTotalTimeInStateMsFieldNumber = 3,
+ kTotalStateEntryCountFieldNumber = 4,
+ kLastEntryTimestampMsFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EntityStateResidency.StateResidency"; }
+
+
+ using FieldMetadata_EntityIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ EntityStateResidency_StateResidency>;
+
+ static constexpr FieldMetadata_EntityIndex kEntityIndex{};
+ void set_entity_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EntityIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StateIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ EntityStateResidency_StateResidency>;
+
+ static constexpr FieldMetadata_StateIndex kStateIndex{};
+ void set_state_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StateIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalTimeInStateMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ EntityStateResidency_StateResidency>;
+
+ static constexpr FieldMetadata_TotalTimeInStateMs kTotalTimeInStateMs{};
+ void set_total_time_in_state_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalTimeInStateMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalStateEntryCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ EntityStateResidency_StateResidency>;
+
+ static constexpr FieldMetadata_TotalStateEntryCount kTotalStateEntryCount{};
+ void set_total_state_entry_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalStateEntryCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LastEntryTimestampMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ EntityStateResidency_StateResidency>;
+
+ static constexpr FieldMetadata_LastEntryTimestampMs kLastEntryTimestampMs{};
+ void set_last_entry_timestamp_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_LastEntryTimestampMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class EntityStateResidency_PowerEntityState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ EntityStateResidency_PowerEntityState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit EntityStateResidency_PowerEntityState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit EntityStateResidency_PowerEntityState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_entity_index() const { return at<1>().valid(); }
+ int32_t entity_index() const { return at<1>().as_int32(); }
+ bool has_state_index() const { return at<2>().valid(); }
+ int32_t state_index() const { return at<2>().as_int32(); }
+ bool has_entity_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars entity_name() const { return at<3>().as_string(); }
+ bool has_state_name() const { return at<4>().valid(); }
+ ::protozero::ConstChars state_name() const { return at<4>().as_string(); }
+};
+
+class EntityStateResidency_PowerEntityState : public ::protozero::Message {
+ public:
+ using Decoder = EntityStateResidency_PowerEntityState_Decoder;
+ enum : int32_t {
+ kEntityIndexFieldNumber = 1,
+ kStateIndexFieldNumber = 2,
+ kEntityNameFieldNumber = 3,
+ kStateNameFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.EntityStateResidency.PowerEntityState"; }
+
+
+ using FieldMetadata_EntityIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ EntityStateResidency_PowerEntityState>;
+
+ static constexpr FieldMetadata_EntityIndex kEntityIndex{};
+ void set_entity_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EntityIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StateIndex =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ EntityStateResidency_PowerEntityState>;
+
+ static constexpr FieldMetadata_StateIndex kStateIndex{};
+ void set_state_index(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_StateIndex::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EntityName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ EntityStateResidency_PowerEntityState>;
+
+ static constexpr FieldMetadata_EntityName kEntityName{};
+ void set_entity_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_EntityName::kFieldId, data, size);
+ }
+ void set_entity_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_EntityName::kFieldId, chars.data, chars.size);
+ }
+ void set_entity_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_EntityName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StateName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ EntityStateResidency_PowerEntityState>;
+
+ static constexpr FieldMetadata_StateName kStateName{};
+ void set_state_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StateName::kFieldId, data, size);
+ }
+ void set_state_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StateName::kFieldId, chars.data, chars.size);
+ }
+ void set_state_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StateName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/power/battery_counters.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_BATTERY_COUNTERS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_BATTERY_COUNTERS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class BatteryCounters_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ BatteryCounters_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit BatteryCounters_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit BatteryCounters_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_charge_counter_uah() const { return at<1>().valid(); }
+ int64_t charge_counter_uah() const { return at<1>().as_int64(); }
+ bool has_capacity_percent() const { return at<2>().valid(); }
+ float capacity_percent() const { return at<2>().as_float(); }
+ bool has_current_ua() const { return at<3>().valid(); }
+ int64_t current_ua() const { return at<3>().as_int64(); }
+ bool has_current_avg_ua() const { return at<4>().valid(); }
+ int64_t current_avg_ua() const { return at<4>().as_int64(); }
+ bool has_name() const { return at<5>().valid(); }
+ ::protozero::ConstChars name() const { return at<5>().as_string(); }
+ bool has_energy_counter_uwh() const { return at<6>().valid(); }
+ int64_t energy_counter_uwh() const { return at<6>().as_int64(); }
+ bool has_voltage_uv() const { return at<7>().valid(); }
+ int64_t voltage_uv() const { return at<7>().as_int64(); }
+};
+
+class BatteryCounters : public ::protozero::Message {
+ public:
+ using Decoder = BatteryCounters_Decoder;
+ enum : int32_t {
+ kChargeCounterUahFieldNumber = 1,
+ kCapacityPercentFieldNumber = 2,
+ kCurrentUaFieldNumber = 3,
+ kCurrentAvgUaFieldNumber = 4,
+ kNameFieldNumber = 5,
+ kEnergyCounterUwhFieldNumber = 6,
+ kVoltageUvFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.BatteryCounters"; }
+
+
+ using FieldMetadata_ChargeCounterUah =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BatteryCounters>;
+
+ static constexpr FieldMetadata_ChargeCounterUah kChargeCounterUah{};
+ void set_charge_counter_uah(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChargeCounterUah::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CapacityPercent =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kFloat,
+ float,
+ BatteryCounters>;
+
+ static constexpr FieldMetadata_CapacityPercent kCapacityPercent{};
+ void set_capacity_percent(float value) {
+ static constexpr uint32_t field_id = FieldMetadata_CapacityPercent::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kFloat>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrentUa =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BatteryCounters>;
+
+ static constexpr FieldMetadata_CurrentUa kCurrentUa{};
+ void set_current_ua(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrentUa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_CurrentAvgUa =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BatteryCounters>;
+
+ static constexpr FieldMetadata_CurrentAvgUa kCurrentAvgUa{};
+ void set_current_avg_ua(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CurrentAvgUa::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ BatteryCounters>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_EnergyCounterUwh =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BatteryCounters>;
+
+ static constexpr FieldMetadata_EnergyCounterUwh kEnergyCounterUwh{};
+ void set_energy_counter_uwh(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_EnergyCounterUwh::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VoltageUv =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ BatteryCounters>;
+
+ static constexpr FieldMetadata_VoltageUv kVoltageUv{};
+ void set_voltage_uv(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VoltageUv::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/power/power_rails.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_POWER_RAILS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_POWER_POWER_RAILS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class PowerRails_EnergyData;
+class PowerRails_RailDescriptor;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class PowerRails_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ PowerRails_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PowerRails_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PowerRails_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_rail_descriptor() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> rail_descriptor() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_energy_data() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> energy_data() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class PowerRails : public ::protozero::Message {
+ public:
+ using Decoder = PowerRails_Decoder;
+ enum : int32_t {
+ kRailDescriptorFieldNumber = 1,
+ kEnergyDataFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PowerRails"; }
+
+ using RailDescriptor = ::perfetto::protos::pbzero::PowerRails_RailDescriptor;
+ using EnergyData = ::perfetto::protos::pbzero::PowerRails_EnergyData;
+
+ using FieldMetadata_RailDescriptor =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PowerRails_RailDescriptor,
+ PowerRails>;
+
+ static constexpr FieldMetadata_RailDescriptor kRailDescriptor{};
+ template <typename T = PowerRails_RailDescriptor> T* add_rail_descriptor() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_EnergyData =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PowerRails_EnergyData,
+ PowerRails>;
+
+ static constexpr FieldMetadata_EnergyData kEnergyData{};
+ template <typename T = PowerRails_EnergyData> T* add_energy_data() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class PowerRails_EnergyData_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PowerRails_EnergyData_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PowerRails_EnergyData_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PowerRails_EnergyData_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_index() const { return at<1>().valid(); }
+ uint32_t index() const { return at<1>().as_uint32(); }
+ bool has_timestamp_ms() const { return at<2>().valid(); }
+ uint64_t timestamp_ms() const { return at<2>().as_uint64(); }
+ bool has_energy() const { return at<3>().valid(); }
+ uint64_t energy() const { return at<3>().as_uint64(); }
+};
+
+class PowerRails_EnergyData : public ::protozero::Message {
+ public:
+ using Decoder = PowerRails_EnergyData_Decoder;
+ enum : int32_t {
+ kIndexFieldNumber = 1,
+ kTimestampMsFieldNumber = 2,
+ kEnergyFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PowerRails.EnergyData"; }
+
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PowerRails_EnergyData>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimestampMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PowerRails_EnergyData>;
+
+ static constexpr FieldMetadata_TimestampMs kTimestampMs{};
+ void set_timestamp_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Energy =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ PowerRails_EnergyData>;
+
+ static constexpr FieldMetadata_Energy kEnergy{};
+ void set_energy(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Energy::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class PowerRails_RailDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ PowerRails_RailDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit PowerRails_RailDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit PowerRails_RailDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_index() const { return at<1>().valid(); }
+ uint32_t index() const { return at<1>().as_uint32(); }
+ bool has_rail_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars rail_name() const { return at<2>().as_string(); }
+ bool has_subsys_name() const { return at<3>().valid(); }
+ ::protozero::ConstChars subsys_name() const { return at<3>().as_string(); }
+ bool has_sampling_rate() const { return at<4>().valid(); }
+ uint32_t sampling_rate() const { return at<4>().as_uint32(); }
+};
+
+class PowerRails_RailDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = PowerRails_RailDescriptor_Decoder;
+ enum : int32_t {
+ kIndexFieldNumber = 1,
+ kRailNameFieldNumber = 2,
+ kSubsysNameFieldNumber = 3,
+ kSamplingRateFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.PowerRails.RailDescriptor"; }
+
+
+ using FieldMetadata_Index =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PowerRails_RailDescriptor>;
+
+ static constexpr FieldMetadata_Index kIndex{};
+ void set_index(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Index::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RailName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PowerRails_RailDescriptor>;
+
+ static constexpr FieldMetadata_RailName kRailName{};
+ void set_rail_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_RailName::kFieldId, data, size);
+ }
+ void set_rail_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_RailName::kFieldId, chars.data, chars.size);
+ }
+ void set_rail_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_RailName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SubsysName =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ PowerRails_RailDescriptor>;
+
+ static constexpr FieldMetadata_SubsysName kSubsysName{};
+ void set_subsys_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SubsysName::kFieldId, data, size);
+ }
+ void set_subsys_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SubsysName::kFieldId, chars.data, chars.size);
+ }
+ void set_subsys_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SubsysName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SamplingRate =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ PowerRails_RailDescriptor>;
+
+ static constexpr FieldMetadata_SamplingRate kSamplingRate{};
+ void set_sampling_rate(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SamplingRate::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ps/process_stats.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PS_PROCESS_STATS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PS_PROCESS_STATS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ProcessStats_FDInfo;
+class ProcessStats_Process;
+class ProcessStats_Thread;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ProcessStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProcessStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_processes() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> processes() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_collection_end_timestamp() const { return at<2>().valid(); }
+ uint64_t collection_end_timestamp() const { return at<2>().as_uint64(); }
+};
+
+class ProcessStats : public ::protozero::Message {
+ public:
+ using Decoder = ProcessStats_Decoder;
+ enum : int32_t {
+ kProcessesFieldNumber = 1,
+ kCollectionEndTimestampFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessStats"; }
+
+ using Thread = ::perfetto::protos::pbzero::ProcessStats_Thread;
+ using FDInfo = ::perfetto::protos::pbzero::ProcessStats_FDInfo;
+ using Process = ::perfetto::protos::pbzero::ProcessStats_Process;
+
+ using FieldMetadata_Processes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessStats_Process,
+ ProcessStats>;
+
+ static constexpr FieldMetadata_Processes kProcesses{};
+ template <typename T = ProcessStats_Process> T* add_processes() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_CollectionEndTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats>;
+
+ static constexpr FieldMetadata_CollectionEndTimestamp kCollectionEndTimestamp{};
+ void set_collection_end_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CollectionEndTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProcessStats_Process_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/22, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProcessStats_Process_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessStats_Process_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessStats_Process_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_threads() const { return at<11>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> threads() const { return GetRepeated<::protozero::ConstBytes>(11); }
+ bool has_vm_size_kb() const { return at<2>().valid(); }
+ uint64_t vm_size_kb() const { return at<2>().as_uint64(); }
+ bool has_vm_rss_kb() const { return at<3>().valid(); }
+ uint64_t vm_rss_kb() const { return at<3>().as_uint64(); }
+ bool has_rss_anon_kb() const { return at<4>().valid(); }
+ uint64_t rss_anon_kb() const { return at<4>().as_uint64(); }
+ bool has_rss_file_kb() const { return at<5>().valid(); }
+ uint64_t rss_file_kb() const { return at<5>().as_uint64(); }
+ bool has_rss_shmem_kb() const { return at<6>().valid(); }
+ uint64_t rss_shmem_kb() const { return at<6>().as_uint64(); }
+ bool has_vm_swap_kb() const { return at<7>().valid(); }
+ uint64_t vm_swap_kb() const { return at<7>().as_uint64(); }
+ bool has_vm_locked_kb() const { return at<8>().valid(); }
+ uint64_t vm_locked_kb() const { return at<8>().as_uint64(); }
+ bool has_vm_hwm_kb() const { return at<9>().valid(); }
+ uint64_t vm_hwm_kb() const { return at<9>().as_uint64(); }
+ bool has_oom_score_adj() const { return at<10>().valid(); }
+ int64_t oom_score_adj() const { return at<10>().as_int64(); }
+ bool has_is_peak_rss_resettable() const { return at<12>().valid(); }
+ bool is_peak_rss_resettable() const { return at<12>().as_bool(); }
+ bool has_chrome_private_footprint_kb() const { return at<13>().valid(); }
+ uint32_t chrome_private_footprint_kb() const { return at<13>().as_uint32(); }
+ bool has_chrome_peak_resident_set_kb() const { return at<14>().valid(); }
+ uint32_t chrome_peak_resident_set_kb() const { return at<14>().as_uint32(); }
+ bool has_fds() const { return at<15>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> fds() const { return GetRepeated<::protozero::ConstBytes>(15); }
+ bool has_smr_rss_kb() const { return at<16>().valid(); }
+ uint64_t smr_rss_kb() const { return at<16>().as_uint64(); }
+ bool has_smr_pss_kb() const { return at<17>().valid(); }
+ uint64_t smr_pss_kb() const { return at<17>().as_uint64(); }
+ bool has_smr_pss_anon_kb() const { return at<18>().valid(); }
+ uint64_t smr_pss_anon_kb() const { return at<18>().as_uint64(); }
+ bool has_smr_pss_file_kb() const { return at<19>().valid(); }
+ uint64_t smr_pss_file_kb() const { return at<19>().as_uint64(); }
+ bool has_smr_pss_shmem_kb() const { return at<20>().valid(); }
+ uint64_t smr_pss_shmem_kb() const { return at<20>().as_uint64(); }
+ bool has_runtime_user_mode() const { return at<21>().valid(); }
+ uint64_t runtime_user_mode() const { return at<21>().as_uint64(); }
+ bool has_runtime_kernel_mode() const { return at<22>().valid(); }
+ uint64_t runtime_kernel_mode() const { return at<22>().as_uint64(); }
+};
+
+class ProcessStats_Process : public ::protozero::Message {
+ public:
+ using Decoder = ProcessStats_Process_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kThreadsFieldNumber = 11,
+ kVmSizeKbFieldNumber = 2,
+ kVmRssKbFieldNumber = 3,
+ kRssAnonKbFieldNumber = 4,
+ kRssFileKbFieldNumber = 5,
+ kRssShmemKbFieldNumber = 6,
+ kVmSwapKbFieldNumber = 7,
+ kVmLockedKbFieldNumber = 8,
+ kVmHwmKbFieldNumber = 9,
+ kOomScoreAdjFieldNumber = 10,
+ kIsPeakRssResettableFieldNumber = 12,
+ kChromePrivateFootprintKbFieldNumber = 13,
+ kChromePeakResidentSetKbFieldNumber = 14,
+ kFdsFieldNumber = 15,
+ kSmrRssKbFieldNumber = 16,
+ kSmrPssKbFieldNumber = 17,
+ kSmrPssAnonKbFieldNumber = 18,
+ kSmrPssFileKbFieldNumber = 19,
+ kSmrPssShmemKbFieldNumber = 20,
+ kRuntimeUserModeFieldNumber = 21,
+ kRuntimeKernelModeFieldNumber = 22,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessStats.Process"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Threads =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessStats_Thread,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_Threads kThreads{};
+ template <typename T = ProcessStats_Thread> T* add_threads() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_VmSizeKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_VmSizeKb kVmSizeKb{};
+ void set_vm_size_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VmSizeKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VmRssKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_VmRssKb kVmRssKb{};
+ void set_vm_rss_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VmRssKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RssAnonKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_RssAnonKb kRssAnonKb{};
+ void set_rss_anon_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RssAnonKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RssFileKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_RssFileKb kRssFileKb{};
+ void set_rss_file_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RssFileKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RssShmemKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_RssShmemKb kRssShmemKb{};
+ void set_rss_shmem_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RssShmemKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VmSwapKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_VmSwapKb kVmSwapKb{};
+ void set_vm_swap_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VmSwapKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VmLockedKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_VmLockedKb kVmLockedKb{};
+ void set_vm_locked_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VmLockedKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_VmHwmKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_VmHwmKb kVmHwmKb{};
+ void set_vm_hwm_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_VmHwmKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OomScoreAdj =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_OomScoreAdj kOomScoreAdj{};
+ void set_oom_score_adj(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OomScoreAdj::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsPeakRssResettable =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_IsPeakRssResettable kIsPeakRssResettable{};
+ void set_is_peak_rss_resettable(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsPeakRssResettable::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChromePrivateFootprintKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_ChromePrivateFootprintKb kChromePrivateFootprintKb{};
+ void set_chrome_private_footprint_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChromePrivateFootprintKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ChromePeakResidentSetKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_ChromePeakResidentSetKb kChromePeakResidentSetKb{};
+ void set_chrome_peak_resident_set_kb(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChromePeakResidentSetKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Fds =
+ ::protozero::proto_utils::FieldMetadata<
+ 15,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessStats_FDInfo,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_Fds kFds{};
+ template <typename T = ProcessStats_FDInfo> T* add_fds() {
+ return BeginNestedMessage<T>(15);
+ }
+
+
+ using FieldMetadata_SmrRssKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 16,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_SmrRssKb kSmrRssKb{};
+ void set_smr_rss_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SmrRssKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SmrPssKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 17,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_SmrPssKb kSmrPssKb{};
+ void set_smr_pss_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SmrPssKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SmrPssAnonKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 18,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_SmrPssAnonKb kSmrPssAnonKb{};
+ void set_smr_pss_anon_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SmrPssAnonKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SmrPssFileKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 19,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_SmrPssFileKb kSmrPssFileKb{};
+ void set_smr_pss_file_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SmrPssFileKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SmrPssShmemKb =
+ ::protozero::proto_utils::FieldMetadata<
+ 20,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_SmrPssShmemKb kSmrPssShmemKb{};
+ void set_smr_pss_shmem_kb(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SmrPssShmemKb::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RuntimeUserMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 21,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_RuntimeUserMode kRuntimeUserMode{};
+ void set_runtime_user_mode(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RuntimeUserMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RuntimeKernelMode =
+ ::protozero::proto_utils::FieldMetadata<
+ 22,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_Process>;
+
+ static constexpr FieldMetadata_RuntimeKernelMode kRuntimeKernelMode{};
+ void set_runtime_kernel_mode(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RuntimeKernelMode::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProcessStats_FDInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProcessStats_FDInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessStats_FDInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessStats_FDInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_fd() const { return at<1>().valid(); }
+ uint64_t fd() const { return at<1>().as_uint64(); }
+ bool has_path() const { return at<2>().valid(); }
+ ::protozero::ConstChars path() const { return at<2>().as_string(); }
+};
+
+class ProcessStats_FDInfo : public ::protozero::Message {
+ public:
+ using Decoder = ProcessStats_FDInfo_Decoder;
+ enum : int32_t {
+ kFdFieldNumber = 1,
+ kPathFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessStats.FDInfo"; }
+
+
+ using FieldMetadata_Fd =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessStats_FDInfo>;
+
+ static constexpr FieldMetadata_Fd kFd{};
+ void set_fd(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Fd::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Path =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProcessStats_FDInfo>;
+
+ static constexpr FieldMetadata_Path kPath{};
+ void set_path(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Path::kFieldId, data, size);
+ }
+ void set_path(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Path::kFieldId, chars.data, chars.size);
+ }
+ void set_path(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Path::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProcessStats_Thread_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ProcessStats_Thread_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessStats_Thread_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessStats_Thread_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tid() const { return at<1>().valid(); }
+ int32_t tid() const { return at<1>().as_int32(); }
+};
+
+class ProcessStats_Thread : public ::protozero::Message {
+ public:
+ using Decoder = ProcessStats_Thread_Decoder;
+ enum : int32_t {
+ kTidFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessStats.Thread"; }
+
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessStats_Thread>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ps/process_tree.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PS_PROCESS_TREE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_PS_PROCESS_TREE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ProcessTree_Process;
+class ProcessTree_Thread;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ProcessTree_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProcessTree_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessTree_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessTree_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_processes() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> processes() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_threads() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> threads() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_collection_end_timestamp() const { return at<3>().valid(); }
+ uint64_t collection_end_timestamp() const { return at<3>().as_uint64(); }
+};
+
+class ProcessTree : public ::protozero::Message {
+ public:
+ using Decoder = ProcessTree_Decoder;
+ enum : int32_t {
+ kProcessesFieldNumber = 1,
+ kThreadsFieldNumber = 2,
+ kCollectionEndTimestampFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessTree"; }
+
+ using Thread = ::perfetto::protos::pbzero::ProcessTree_Thread;
+ using Process = ::perfetto::protos::pbzero::ProcessTree_Process;
+
+ using FieldMetadata_Processes =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessTree_Process,
+ ProcessTree>;
+
+ static constexpr FieldMetadata_Processes kProcesses{};
+ template <typename T = ProcessTree_Process> T* add_processes() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Threads =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ProcessTree_Thread,
+ ProcessTree>;
+
+ static constexpr FieldMetadata_Threads kThreads{};
+ template <typename T = ProcessTree_Thread> T* add_threads() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_CollectionEndTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessTree>;
+
+ static constexpr FieldMetadata_CollectionEndTimestamp kCollectionEndTimestamp{};
+ void set_collection_end_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CollectionEndTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProcessTree_Process_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProcessTree_Process_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessTree_Process_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessTree_Process_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_ppid() const { return at<2>().valid(); }
+ int32_t ppid() const { return at<2>().as_int32(); }
+ bool has_cmdline() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> cmdline() const { return GetRepeated<::protozero::ConstChars>(3); }
+ bool has_uid() const { return at<5>().valid(); }
+ int32_t uid() const { return at<5>().as_int32(); }
+ bool has_nspid() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> nspid() const { return GetRepeated<int32_t>(6); }
+ bool has_process_start_from_boot() const { return at<7>().valid(); }
+ uint64_t process_start_from_boot() const { return at<7>().as_uint64(); }
+};
+
+class ProcessTree_Process : public ::protozero::Message {
+ public:
+ using Decoder = ProcessTree_Process_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kPpidFieldNumber = 2,
+ kCmdlineFieldNumber = 3,
+ kUidFieldNumber = 5,
+ kNspidFieldNumber = 6,
+ kProcessStartFromBootFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessTree.Process"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessTree_Process>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Ppid =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessTree_Process>;
+
+ static constexpr FieldMetadata_Ppid kPpid{};
+ void set_ppid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Ppid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProcessTree_Process>;
+
+ static constexpr FieldMetadata_Cmdline kCmdline{};
+ void add_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, data, size);
+ }
+ void add_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, chars.data, chars.size);
+ }
+ void add_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Uid =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessTree_Process>;
+
+ static constexpr FieldMetadata_Uid kUid{};
+ void set_uid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Uid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nspid =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessTree_Process>;
+
+ static constexpr FieldMetadata_Nspid kNspid{};
+ void add_nspid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nspid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessStartFromBoot =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ProcessTree_Process>;
+
+ static constexpr FieldMetadata_ProcessStartFromBoot kProcessStartFromBoot{};
+ void set_process_start_from_boot(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ProcessStartFromBoot::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ProcessTree_Thread_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ProcessTree_Thread_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ProcessTree_Thread_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ProcessTree_Thread_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_tid() const { return at<1>().valid(); }
+ int32_t tid() const { return at<1>().as_int32(); }
+ bool has_tgid() const { return at<3>().valid(); }
+ int32_t tgid() const { return at<3>().as_int32(); }
+ bool has_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars name() const { return at<2>().as_string(); }
+ bool has_nstid() const { return at<4>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> nstid() const { return GetRepeated<int32_t>(4); }
+};
+
+class ProcessTree_Thread : public ::protozero::Message {
+ public:
+ using Decoder = ProcessTree_Thread_Decoder;
+ enum : int32_t {
+ kTidFieldNumber = 1,
+ kTgidFieldNumber = 3,
+ kNameFieldNumber = 2,
+ kNstidFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ProcessTree.Thread"; }
+
+
+ using FieldMetadata_Tid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessTree_Thread>;
+
+ static constexpr FieldMetadata_Tid kTid{};
+ void set_tid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Tgid =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessTree_Thread>;
+
+ static constexpr FieldMetadata_Tgid kTgid{};
+ void set_tgid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Tgid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ProcessTree_Thread>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nstid =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ ProcessTree_Thread>;
+
+ static constexpr FieldMetadata_Nstid kNstid{};
+ void add_nstid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Nstid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/statsd/statsd_atom.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_STATSD_STATSD_ATOM_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_STATSD_STATSD_ATOM_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class Atom;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class StatsdAtom_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ StatsdAtom_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit StatsdAtom_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit StatsdAtom_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_atom() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> atom() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_timestamp_nanos() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<int64_t> timestamp_nanos() const { return GetRepeated<int64_t>(2); }
+};
+
+class StatsdAtom : public ::protozero::Message {
+ public:
+ using Decoder = StatsdAtom_Decoder;
+ enum : int32_t {
+ kAtomFieldNumber = 1,
+ kTimestampNanosFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.StatsdAtom"; }
+
+
+ using FieldMetadata_Atom =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ Atom,
+ StatsdAtom>;
+
+ static constexpr FieldMetadata_Atom kAtom{};
+ template <typename T = Atom> T* add_atom() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_TimestampNanos =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ StatsdAtom>;
+
+ static constexpr FieldMetadata_TimestampNanos kTimestampNanos{};
+ void add_timestamp_nanos(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampNanos::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class Atom_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/0, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ Atom_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Atom_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Atom_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+};
+
+class Atom : public ::protozero::Message {
+ public:
+ using Decoder = Atom_Decoder;
+ static constexpr const char* GetName() { return ".perfetto.protos.Atom"; }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/sys_stats/sys_stats.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_SYS_STATS_SYS_STATS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_SYS_STATS_SYS_STATS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class SysStats_BuddyInfo;
+class SysStats_CpuTimes;
+class SysStats_DevfreqValue;
+class SysStats_DiskStat;
+class SysStats_InterruptCount;
+class SysStats_MeminfoValue;
+class SysStats_PsiSample;
+class SysStats_VmstatValue;
+enum MeminfoCounters : int32_t;
+namespace perfetto_pbzero_enum_SysStats_PsiSample {
+enum PsiResource : int32_t;
+} // namespace perfetto_pbzero_enum_SysStats_PsiSample
+using SysStats_PsiSample_PsiResource = perfetto_pbzero_enum_SysStats_PsiSample::PsiResource;
+enum VmstatCounters : int32_t;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_SysStats_PsiSample {
+enum PsiResource : int32_t {
+ PSI_RESOURCE_UNSPECIFIED = 0,
+ PSI_RESOURCE_CPU_SOME = 1,
+ PSI_RESOURCE_CPU_FULL = 2,
+ PSI_RESOURCE_IO_SOME = 3,
+ PSI_RESOURCE_IO_FULL = 4,
+ PSI_RESOURCE_MEMORY_SOME = 5,
+ PSI_RESOURCE_MEMORY_FULL = 6,
+};
+} // namespace perfetto_pbzero_enum_SysStats_PsiSample
+using SysStats_PsiSample_PsiResource = perfetto_pbzero_enum_SysStats_PsiSample::PsiResource;
+
+
+constexpr SysStats_PsiSample_PsiResource SysStats_PsiSample_PsiResource_MIN = SysStats_PsiSample_PsiResource::PSI_RESOURCE_UNSPECIFIED;
+constexpr SysStats_PsiSample_PsiResource SysStats_PsiSample_PsiResource_MAX = SysStats_PsiSample_PsiResource::PSI_RESOURCE_MEMORY_FULL;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* SysStats_PsiSample_PsiResource_Name(::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource::PSI_RESOURCE_UNSPECIFIED:
+ return "PSI_RESOURCE_UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource::PSI_RESOURCE_CPU_SOME:
+ return "PSI_RESOURCE_CPU_SOME";
+
+ case ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource::PSI_RESOURCE_CPU_FULL:
+ return "PSI_RESOURCE_CPU_FULL";
+
+ case ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource::PSI_RESOURCE_IO_SOME:
+ return "PSI_RESOURCE_IO_SOME";
+
+ case ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource::PSI_RESOURCE_IO_FULL:
+ return "PSI_RESOURCE_IO_FULL";
+
+ case ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource::PSI_RESOURCE_MEMORY_SOME:
+ return "PSI_RESOURCE_MEMORY_SOME";
+
+ case ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource::PSI_RESOURCE_MEMORY_FULL:
+ return "PSI_RESOURCE_MEMORY_FULL";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class SysStats_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/14, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ SysStats_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_meminfo() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> meminfo() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_vmstat() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> vmstat() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_cpu_stat() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> cpu_stat() const { return GetRepeated<::protozero::ConstBytes>(3); }
+ bool has_num_forks() const { return at<4>().valid(); }
+ uint64_t num_forks() const { return at<4>().as_uint64(); }
+ bool has_num_irq_total() const { return at<5>().valid(); }
+ uint64_t num_irq_total() const { return at<5>().as_uint64(); }
+ bool has_num_irq() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> num_irq() const { return GetRepeated<::protozero::ConstBytes>(6); }
+ bool has_num_softirq_total() const { return at<7>().valid(); }
+ uint64_t num_softirq_total() const { return at<7>().as_uint64(); }
+ bool has_num_softirq() const { return at<8>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> num_softirq() const { return GetRepeated<::protozero::ConstBytes>(8); }
+ bool has_collection_end_timestamp() const { return at<9>().valid(); }
+ uint64_t collection_end_timestamp() const { return at<9>().as_uint64(); }
+ bool has_devfreq() const { return at<10>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> devfreq() const { return GetRepeated<::protozero::ConstBytes>(10); }
+ bool has_cpufreq_khz() const { return at<11>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> cpufreq_khz() const { return GetRepeated<uint32_t>(11); }
+ bool has_buddy_info() const { return at<12>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> buddy_info() const { return GetRepeated<::protozero::ConstBytes>(12); }
+ bool has_disk_stat() const { return at<13>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> disk_stat() const { return GetRepeated<::protozero::ConstBytes>(13); }
+ bool has_psi() const { return at<14>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> psi() const { return GetRepeated<::protozero::ConstBytes>(14); }
+};
+
+class SysStats : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_Decoder;
+ enum : int32_t {
+ kMeminfoFieldNumber = 1,
+ kVmstatFieldNumber = 2,
+ kCpuStatFieldNumber = 3,
+ kNumForksFieldNumber = 4,
+ kNumIrqTotalFieldNumber = 5,
+ kNumIrqFieldNumber = 6,
+ kNumSoftirqTotalFieldNumber = 7,
+ kNumSoftirqFieldNumber = 8,
+ kCollectionEndTimestampFieldNumber = 9,
+ kDevfreqFieldNumber = 10,
+ kCpufreqKhzFieldNumber = 11,
+ kBuddyInfoFieldNumber = 12,
+ kDiskStatFieldNumber = 13,
+ kPsiFieldNumber = 14,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats"; }
+
+ using MeminfoValue = ::perfetto::protos::pbzero::SysStats_MeminfoValue;
+ using VmstatValue = ::perfetto::protos::pbzero::SysStats_VmstatValue;
+ using CpuTimes = ::perfetto::protos::pbzero::SysStats_CpuTimes;
+ using InterruptCount = ::perfetto::protos::pbzero::SysStats_InterruptCount;
+ using DevfreqValue = ::perfetto::protos::pbzero::SysStats_DevfreqValue;
+ using BuddyInfo = ::perfetto::protos::pbzero::SysStats_BuddyInfo;
+ using DiskStat = ::perfetto::protos::pbzero::SysStats_DiskStat;
+ using PsiSample = ::perfetto::protos::pbzero::SysStats_PsiSample;
+
+ using FieldMetadata_Meminfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_MeminfoValue,
+ SysStats>;
+
+ static constexpr FieldMetadata_Meminfo kMeminfo{};
+ template <typename T = SysStats_MeminfoValue> T* add_meminfo() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_Vmstat =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_VmstatValue,
+ SysStats>;
+
+ static constexpr FieldMetadata_Vmstat kVmstat{};
+ template <typename T = SysStats_VmstatValue> T* add_vmstat() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_CpuStat =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_CpuTimes,
+ SysStats>;
+
+ static constexpr FieldMetadata_CpuStat kCpuStat{};
+ template <typename T = SysStats_CpuTimes> T* add_cpu_stat() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_NumForks =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats>;
+
+ static constexpr FieldMetadata_NumForks kNumForks{};
+ void set_num_forks(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumForks::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumIrqTotal =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats>;
+
+ static constexpr FieldMetadata_NumIrqTotal kNumIrqTotal{};
+ void set_num_irq_total(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumIrqTotal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumIrq =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_InterruptCount,
+ SysStats>;
+
+ static constexpr FieldMetadata_NumIrq kNumIrq{};
+ template <typename T = SysStats_InterruptCount> T* add_num_irq() {
+ return BeginNestedMessage<T>(6);
+ }
+
+
+ using FieldMetadata_NumSoftirqTotal =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats>;
+
+ static constexpr FieldMetadata_NumSoftirqTotal kNumSoftirqTotal{};
+ void set_num_softirq_total(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_NumSoftirqTotal::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NumSoftirq =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_InterruptCount,
+ SysStats>;
+
+ static constexpr FieldMetadata_NumSoftirq kNumSoftirq{};
+ template <typename T = SysStats_InterruptCount> T* add_num_softirq() {
+ return BeginNestedMessage<T>(8);
+ }
+
+
+ using FieldMetadata_CollectionEndTimestamp =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats>;
+
+ static constexpr FieldMetadata_CollectionEndTimestamp kCollectionEndTimestamp{};
+ void set_collection_end_timestamp(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CollectionEndTimestamp::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Devfreq =
+ ::protozero::proto_utils::FieldMetadata<
+ 10,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_DevfreqValue,
+ SysStats>;
+
+ static constexpr FieldMetadata_Devfreq kDevfreq{};
+ template <typename T = SysStats_DevfreqValue> T* add_devfreq() {
+ return BeginNestedMessage<T>(10);
+ }
+
+
+ using FieldMetadata_CpufreqKhz =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStats>;
+
+ static constexpr FieldMetadata_CpufreqKhz kCpufreqKhz{};
+ void add_cpufreq_khz(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpufreqKhz::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_BuddyInfo =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_BuddyInfo,
+ SysStats>;
+
+ static constexpr FieldMetadata_BuddyInfo kBuddyInfo{};
+ template <typename T = SysStats_BuddyInfo> T* add_buddy_info() {
+ return BeginNestedMessage<T>(12);
+ }
+
+
+ using FieldMetadata_DiskStat =
+ ::protozero::proto_utils::FieldMetadata<
+ 13,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_DiskStat,
+ SysStats>;
+
+ static constexpr FieldMetadata_DiskStat kDiskStat{};
+ template <typename T = SysStats_DiskStat> T* add_disk_stat() {
+ return BeginNestedMessage<T>(13);
+ }
+
+
+ using FieldMetadata_Psi =
+ ::protozero::proto_utils::FieldMetadata<
+ 14,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SysStats_PsiSample,
+ SysStats>;
+
+ static constexpr FieldMetadata_Psi kPsi{};
+ template <typename T = SysStats_PsiSample> T* add_psi() {
+ return BeginNestedMessage<T>(14);
+ }
+
+};
+
+class SysStats_PsiSample_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysStats_PsiSample_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_PsiSample_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_PsiSample_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_resource() const { return at<1>().valid(); }
+ int32_t resource() const { return at<1>().as_int32(); }
+ bool has_total_ns() const { return at<2>().valid(); }
+ uint64_t total_ns() const { return at<2>().as_uint64(); }
+};
+
+class SysStats_PsiSample : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_PsiSample_Decoder;
+ enum : int32_t {
+ kResourceFieldNumber = 1,
+ kTotalNsFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.PsiSample"; }
+
+
+ using PsiResource = ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource;
+ static inline const char* PsiResource_Name(PsiResource value) {
+ return ::perfetto::protos::pbzero::SysStats_PsiSample_PsiResource_Name(value);
+ }
+ static inline const PsiResource PSI_RESOURCE_UNSPECIFIED = PsiResource::PSI_RESOURCE_UNSPECIFIED;
+ static inline const PsiResource PSI_RESOURCE_CPU_SOME = PsiResource::PSI_RESOURCE_CPU_SOME;
+ static inline const PsiResource PSI_RESOURCE_CPU_FULL = PsiResource::PSI_RESOURCE_CPU_FULL;
+ static inline const PsiResource PSI_RESOURCE_IO_SOME = PsiResource::PSI_RESOURCE_IO_SOME;
+ static inline const PsiResource PSI_RESOURCE_IO_FULL = PsiResource::PSI_RESOURCE_IO_FULL;
+ static inline const PsiResource PSI_RESOURCE_MEMORY_SOME = PsiResource::PSI_RESOURCE_MEMORY_SOME;
+ static inline const PsiResource PSI_RESOURCE_MEMORY_FULL = PsiResource::PSI_RESOURCE_MEMORY_FULL;
+
+ using FieldMetadata_Resource =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ SysStats_PsiSample_PsiResource,
+ SysStats_PsiSample>;
+
+ static constexpr FieldMetadata_Resource kResource{};
+ void set_resource(SysStats_PsiSample_PsiResource value) {
+ static constexpr uint32_t field_id = FieldMetadata_Resource::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TotalNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_PsiSample>;
+
+ static constexpr FieldMetadata_TotalNs kTotalNs{};
+ void set_total_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TotalNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysStats_DiskStat_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/9, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysStats_DiskStat_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_DiskStat_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_DiskStat_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_device_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars device_name() const { return at<1>().as_string(); }
+ bool has_read_sectors() const { return at<2>().valid(); }
+ uint64_t read_sectors() const { return at<2>().as_uint64(); }
+ bool has_read_time_ms() const { return at<3>().valid(); }
+ uint64_t read_time_ms() const { return at<3>().as_uint64(); }
+ bool has_write_sectors() const { return at<4>().valid(); }
+ uint64_t write_sectors() const { return at<4>().as_uint64(); }
+ bool has_write_time_ms() const { return at<5>().valid(); }
+ uint64_t write_time_ms() const { return at<5>().as_uint64(); }
+ bool has_discard_sectors() const { return at<6>().valid(); }
+ uint64_t discard_sectors() const { return at<6>().as_uint64(); }
+ bool has_discard_time_ms() const { return at<7>().valid(); }
+ uint64_t discard_time_ms() const { return at<7>().as_uint64(); }
+ bool has_flush_count() const { return at<8>().valid(); }
+ uint64_t flush_count() const { return at<8>().as_uint64(); }
+ bool has_flush_time_ms() const { return at<9>().valid(); }
+ uint64_t flush_time_ms() const { return at<9>().as_uint64(); }
+};
+
+class SysStats_DiskStat : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_DiskStat_Decoder;
+ enum : int32_t {
+ kDeviceNameFieldNumber = 1,
+ kReadSectorsFieldNumber = 2,
+ kReadTimeMsFieldNumber = 3,
+ kWriteSectorsFieldNumber = 4,
+ kWriteTimeMsFieldNumber = 5,
+ kDiscardSectorsFieldNumber = 6,
+ kDiscardTimeMsFieldNumber = 7,
+ kFlushCountFieldNumber = 8,
+ kFlushTimeMsFieldNumber = 9,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.DiskStat"; }
+
+
+ using FieldMetadata_DeviceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_DeviceName kDeviceName{};
+ void set_device_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_DeviceName::kFieldId, data, size);
+ }
+ void set_device_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_DeviceName::kFieldId, chars.data, chars.size);
+ }
+ void set_device_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_DeviceName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadSectors =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_ReadSectors kReadSectors{};
+ void set_read_sectors(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadSectors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ReadTimeMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_ReadTimeMs kReadTimeMs{};
+ void set_read_time_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ReadTimeMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WriteSectors =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_WriteSectors kWriteSectors{};
+ void set_write_sectors(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WriteSectors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_WriteTimeMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_WriteTimeMs kWriteTimeMs{};
+ void set_write_time_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_WriteTimeMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DiscardSectors =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_DiscardSectors kDiscardSectors{};
+ void set_discard_sectors(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DiscardSectors::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DiscardTimeMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_DiscardTimeMs kDiscardTimeMs{};
+ void set_discard_time_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_DiscardTimeMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlushCount =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_FlushCount kFlushCount{};
+ void set_flush_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushCount::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_FlushTimeMs =
+ ::protozero::proto_utils::FieldMetadata<
+ 9,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DiskStat>;
+
+ static constexpr FieldMetadata_FlushTimeMs kFlushTimeMs{};
+ void set_flush_time_ms(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_FlushTimeMs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysStats_BuddyInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ SysStats_BuddyInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_BuddyInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_BuddyInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_node() const { return at<1>().valid(); }
+ ::protozero::ConstChars node() const { return at<1>().as_string(); }
+ bool has_zone() const { return at<2>().valid(); }
+ ::protozero::ConstChars zone() const { return at<2>().as_string(); }
+ bool has_order_pages() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> order_pages() const { return GetRepeated<uint32_t>(3); }
+};
+
+class SysStats_BuddyInfo : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_BuddyInfo_Decoder;
+ enum : int32_t {
+ kNodeFieldNumber = 1,
+ kZoneFieldNumber = 2,
+ kOrderPagesFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.BuddyInfo"; }
+
+
+ using FieldMetadata_Node =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SysStats_BuddyInfo>;
+
+ static constexpr FieldMetadata_Node kNode{};
+ void set_node(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Node::kFieldId, data, size);
+ }
+ void set_node(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Node::kFieldId, chars.data, chars.size);
+ }
+ void set_node(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Node::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Zone =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SysStats_BuddyInfo>;
+
+ static constexpr FieldMetadata_Zone kZone{};
+ void set_zone(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Zone::kFieldId, data, size);
+ }
+ void set_zone(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Zone::kFieldId, chars.data, chars.size);
+ }
+ void set_zone(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Zone::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OrderPages =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStats_BuddyInfo>;
+
+ static constexpr FieldMetadata_OrderPages kOrderPages{};
+ void add_order_pages(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_OrderPages::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysStats_DevfreqValue_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysStats_DevfreqValue_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_DevfreqValue_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_DevfreqValue_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ ::protozero::ConstChars key() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ uint64_t value() const { return at<2>().as_uint64(); }
+};
+
+class SysStats_DevfreqValue : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_DevfreqValue_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.DevfreqValue"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SysStats_DevfreqValue>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Key::kFieldId, data, size);
+ }
+ void set_key(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Key::kFieldId, chars.data, chars.size);
+ }
+ void set_key(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_DevfreqValue>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysStats_InterruptCount_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysStats_InterruptCount_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_InterruptCount_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_InterruptCount_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_irq() const { return at<1>().valid(); }
+ int32_t irq() const { return at<1>().as_int32(); }
+ bool has_count() const { return at<2>().valid(); }
+ uint64_t count() const { return at<2>().as_uint64(); }
+};
+
+class SysStats_InterruptCount : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_InterruptCount_Decoder;
+ enum : int32_t {
+ kIrqFieldNumber = 1,
+ kCountFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.InterruptCount"; }
+
+
+ using FieldMetadata_Irq =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ SysStats_InterruptCount>;
+
+ static constexpr FieldMetadata_Irq kIrq{};
+ void set_irq(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Irq::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Count =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_InterruptCount>;
+
+ static constexpr FieldMetadata_Count kCount{};
+ void set_count(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Count::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysStats_CpuTimes_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/8, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysStats_CpuTimes_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_CpuTimes_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_CpuTimes_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpu_id() const { return at<1>().valid(); }
+ uint32_t cpu_id() const { return at<1>().as_uint32(); }
+ bool has_user_ns() const { return at<2>().valid(); }
+ uint64_t user_ns() const { return at<2>().as_uint64(); }
+ bool has_user_nice_ns() const { return at<3>().valid(); }
+ uint64_t user_nice_ns() const { return at<3>().as_uint64(); }
+ bool has_system_mode_ns() const { return at<4>().valid(); }
+ uint64_t system_mode_ns() const { return at<4>().as_uint64(); }
+ bool has_idle_ns() const { return at<5>().valid(); }
+ uint64_t idle_ns() const { return at<5>().as_uint64(); }
+ bool has_io_wait_ns() const { return at<6>().valid(); }
+ uint64_t io_wait_ns() const { return at<6>().as_uint64(); }
+ bool has_irq_ns() const { return at<7>().valid(); }
+ uint64_t irq_ns() const { return at<7>().as_uint64(); }
+ bool has_softirq_ns() const { return at<8>().valid(); }
+ uint64_t softirq_ns() const { return at<8>().as_uint64(); }
+};
+
+class SysStats_CpuTimes : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_CpuTimes_Decoder;
+ enum : int32_t {
+ kCpuIdFieldNumber = 1,
+ kUserNsFieldNumber = 2,
+ kUserNiceNsFieldNumber = 3,
+ kSystemModeNsFieldNumber = 4,
+ kIdleNsFieldNumber = 5,
+ kIoWaitNsFieldNumber = 6,
+ kIrqNsFieldNumber = 7,
+ kSoftirqNsFieldNumber = 8,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.CpuTimes"; }
+
+
+ using FieldMetadata_CpuId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_CpuId kCpuId{};
+ void set_cpu_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_CpuId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UserNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_UserNs kUserNs{};
+ void set_user_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UserNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_UserNiceNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_UserNiceNs kUserNiceNs{};
+ void set_user_nice_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UserNiceNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SystemModeNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_SystemModeNs kSystemModeNs{};
+ void set_system_mode_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SystemModeNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IdleNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_IdleNs kIdleNs{};
+ void set_idle_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IdleNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IoWaitNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_IoWaitNs kIoWaitNs{};
+ void set_io_wait_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IoWaitNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IrqNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_IrqNs kIrqNs{};
+ void set_irq_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IrqNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SoftirqNs =
+ ::protozero::proto_utils::FieldMetadata<
+ 8,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_CpuTimes>;
+
+ static constexpr FieldMetadata_SoftirqNs kSoftirqNs{};
+ void set_softirq_ns(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SoftirqNs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysStats_VmstatValue_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysStats_VmstatValue_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_VmstatValue_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_VmstatValue_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ int32_t key() const { return at<1>().as_int32(); }
+ bool has_value() const { return at<2>().valid(); }
+ uint64_t value() const { return at<2>().as_uint64(); }
+};
+
+class SysStats_VmstatValue : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_VmstatValue_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.VmstatValue"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ VmstatCounters,
+ SysStats_VmstatValue>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(VmstatCounters value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_VmstatValue>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class SysStats_MeminfoValue_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SysStats_MeminfoValue_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SysStats_MeminfoValue_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SysStats_MeminfoValue_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ int32_t key() const { return at<1>().as_int32(); }
+ bool has_value() const { return at<2>().valid(); }
+ uint64_t value() const { return at<2>().as_uint64(); }
+};
+
+class SysStats_MeminfoValue : public ::protozero::Message {
+ public:
+ using Decoder = SysStats_MeminfoValue_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SysStats.MeminfoValue"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ MeminfoCounters,
+ SysStats_MeminfoValue>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(MeminfoCounters value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ SysStats_MeminfoValue>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/system_info/cpu_info.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_SYSTEM_INFO_CPU_INFO_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_SYSTEM_INFO_CPU_INFO_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class CpuInfo_Cpu;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class CpuInfo_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ CpuInfo_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuInfo_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuInfo_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_cpus() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> cpus() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class CpuInfo : public ::protozero::Message {
+ public:
+ using Decoder = CpuInfo_Decoder;
+ enum : int32_t {
+ kCpusFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuInfo"; }
+
+ using Cpu = ::perfetto::protos::pbzero::CpuInfo_Cpu;
+
+ using FieldMetadata_Cpus =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ CpuInfo_Cpu,
+ CpuInfo>;
+
+ static constexpr FieldMetadata_Cpus kCpus{};
+ template <typename T = CpuInfo_Cpu> T* add_cpus() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class CpuInfo_Cpu_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ CpuInfo_Cpu_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit CpuInfo_Cpu_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit CpuInfo_Cpu_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_processor() const { return at<1>().valid(); }
+ ::protozero::ConstChars processor() const { return at<1>().as_string(); }
+ bool has_frequencies() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<uint32_t> frequencies() const { return GetRepeated<uint32_t>(2); }
+};
+
+class CpuInfo_Cpu : public ::protozero::Message {
+ public:
+ using Decoder = CpuInfo_Cpu_Decoder;
+ enum : int32_t {
+ kProcessorFieldNumber = 1,
+ kFrequenciesFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.CpuInfo.Cpu"; }
+
+
+ using FieldMetadata_Processor =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ CpuInfo_Cpu>;
+
+ static constexpr FieldMetadata_Processor kProcessor{};
+ void set_processor(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Processor::kFieldId, data, size);
+ }
+ void set_processor(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Processor::kFieldId, chars.data, chars.size);
+ }
+ void set_processor(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Processor::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Frequencies =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ CpuInfo_Cpu>;
+
+ static constexpr FieldMetadata_Frequencies kFrequencies{};
+ void add_frequencies(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Frequencies::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/translation/translation_table.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRANSLATION_TRANSLATION_TABLE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRANSLATION_TRANSLATION_TABLE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ChromeHistorgramTranslationTable;
+class ChromeHistorgramTranslationTable_HashToNameEntry;
+class ChromePerformanceMarkTranslationTable;
+class ChromePerformanceMarkTranslationTable_MarkHashToNameEntry;
+class ChromePerformanceMarkTranslationTable_SiteHashToNameEntry;
+class ChromeUserEventTranslationTable;
+class ChromeUserEventTranslationTable_ActionHashToNameEntry;
+class SliceNameTranslationTable;
+class SliceNameTranslationTable_RawToDeobfuscatedNameEntry;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class SliceNameTranslationTable_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ SliceNameTranslationTable_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SliceNameTranslationTable_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SliceNameTranslationTable_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_raw_to_deobfuscated_name() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> raw_to_deobfuscated_name() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class SliceNameTranslationTable : public ::protozero::Message {
+ public:
+ using Decoder = SliceNameTranslationTable_Decoder;
+ enum : int32_t {
+ kRawToDeobfuscatedNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SliceNameTranslationTable"; }
+
+ using RawToDeobfuscatedNameEntry = ::perfetto::protos::pbzero::SliceNameTranslationTable_RawToDeobfuscatedNameEntry;
+
+ using FieldMetadata_RawToDeobfuscatedName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SliceNameTranslationTable_RawToDeobfuscatedNameEntry,
+ SliceNameTranslationTable>;
+
+ static constexpr FieldMetadata_RawToDeobfuscatedName kRawToDeobfuscatedName{};
+ template <typename T = SliceNameTranslationTable_RawToDeobfuscatedNameEntry> T* add_raw_to_deobfuscated_name() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class SliceNameTranslationTable_RawToDeobfuscatedNameEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ SliceNameTranslationTable_RawToDeobfuscatedNameEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit SliceNameTranslationTable_RawToDeobfuscatedNameEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit SliceNameTranslationTable_RawToDeobfuscatedNameEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ ::protozero::ConstChars key() const { return at<1>().as_string(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class SliceNameTranslationTable_RawToDeobfuscatedNameEntry : public ::protozero::Message {
+ public:
+ using Decoder = SliceNameTranslationTable_RawToDeobfuscatedNameEntry_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.SliceNameTranslationTable.RawToDeobfuscatedNameEntry"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SliceNameTranslationTable_RawToDeobfuscatedNameEntry>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Key::kFieldId, data, size);
+ }
+ void set_key(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Key::kFieldId, chars.data, chars.size);
+ }
+ void set_key(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ SliceNameTranslationTable_RawToDeobfuscatedNameEntry>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromePerformanceMarkTranslationTable_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromePerformanceMarkTranslationTable_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromePerformanceMarkTranslationTable_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromePerformanceMarkTranslationTable_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_site_hash_to_name() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> site_hash_to_name() const { return GetRepeated<::protozero::ConstBytes>(1); }
+ bool has_mark_hash_to_name() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> mark_hash_to_name() const { return GetRepeated<::protozero::ConstBytes>(2); }
+};
+
+class ChromePerformanceMarkTranslationTable : public ::protozero::Message {
+ public:
+ using Decoder = ChromePerformanceMarkTranslationTable_Decoder;
+ enum : int32_t {
+ kSiteHashToNameFieldNumber = 1,
+ kMarkHashToNameFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromePerformanceMarkTranslationTable"; }
+
+ using SiteHashToNameEntry = ::perfetto::protos::pbzero::ChromePerformanceMarkTranslationTable_SiteHashToNameEntry;
+ using MarkHashToNameEntry = ::perfetto::protos::pbzero::ChromePerformanceMarkTranslationTable_MarkHashToNameEntry;
+
+ using FieldMetadata_SiteHashToName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromePerformanceMarkTranslationTable_SiteHashToNameEntry,
+ ChromePerformanceMarkTranslationTable>;
+
+ static constexpr FieldMetadata_SiteHashToName kSiteHashToName{};
+ template <typename T = ChromePerformanceMarkTranslationTable_SiteHashToNameEntry> T* add_site_hash_to_name() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_MarkHashToName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromePerformanceMarkTranslationTable_MarkHashToNameEntry,
+ ChromePerformanceMarkTranslationTable>;
+
+ static constexpr FieldMetadata_MarkHashToName kMarkHashToName{};
+ template <typename T = ChromePerformanceMarkTranslationTable_MarkHashToNameEntry> T* add_mark_hash_to_name() {
+ return BeginNestedMessage<T>(2);
+ }
+
+};
+
+class ChromePerformanceMarkTranslationTable_MarkHashToNameEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromePerformanceMarkTranslationTable_MarkHashToNameEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromePerformanceMarkTranslationTable_MarkHashToNameEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromePerformanceMarkTranslationTable_MarkHashToNameEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ uint32_t key() const { return at<1>().as_uint32(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class ChromePerformanceMarkTranslationTable_MarkHashToNameEntry : public ::protozero::Message {
+ public:
+ using Decoder = ChromePerformanceMarkTranslationTable_MarkHashToNameEntry_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromePerformanceMarkTranslationTable.MarkHashToNameEntry"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromePerformanceMarkTranslationTable_MarkHashToNameEntry>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromePerformanceMarkTranslationTable_MarkHashToNameEntry>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromePerformanceMarkTranslationTable_SiteHashToNameEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromePerformanceMarkTranslationTable_SiteHashToNameEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromePerformanceMarkTranslationTable_SiteHashToNameEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromePerformanceMarkTranslationTable_SiteHashToNameEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ uint32_t key() const { return at<1>().as_uint32(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class ChromePerformanceMarkTranslationTable_SiteHashToNameEntry : public ::protozero::Message {
+ public:
+ using Decoder = ChromePerformanceMarkTranslationTable_SiteHashToNameEntry_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromePerformanceMarkTranslationTable.SiteHashToNameEntry"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ ChromePerformanceMarkTranslationTable_SiteHashToNameEntry>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromePerformanceMarkTranslationTable_SiteHashToNameEntry>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeUserEventTranslationTable_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeUserEventTranslationTable_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeUserEventTranslationTable_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeUserEventTranslationTable_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_action_hash_to_name() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> action_hash_to_name() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class ChromeUserEventTranslationTable : public ::protozero::Message {
+ public:
+ using Decoder = ChromeUserEventTranslationTable_Decoder;
+ enum : int32_t {
+ kActionHashToNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeUserEventTranslationTable"; }
+
+ using ActionHashToNameEntry = ::perfetto::protos::pbzero::ChromeUserEventTranslationTable_ActionHashToNameEntry;
+
+ using FieldMetadata_ActionHashToName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeUserEventTranslationTable_ActionHashToNameEntry,
+ ChromeUserEventTranslationTable>;
+
+ static constexpr FieldMetadata_ActionHashToName kActionHashToName{};
+ template <typename T = ChromeUserEventTranslationTable_ActionHashToNameEntry> T* add_action_hash_to_name() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class ChromeUserEventTranslationTable_ActionHashToNameEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeUserEventTranslationTable_ActionHashToNameEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeUserEventTranslationTable_ActionHashToNameEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeUserEventTranslationTable_ActionHashToNameEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ uint64_t key() const { return at<1>().as_uint64(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class ChromeUserEventTranslationTable_ActionHashToNameEntry : public ::protozero::Message {
+ public:
+ using Decoder = ChromeUserEventTranslationTable_ActionHashToNameEntry_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeUserEventTranslationTable.ActionHashToNameEntry"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeUserEventTranslationTable_ActionHashToNameEntry>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeUserEventTranslationTable_ActionHashToNameEntry>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class ChromeHistorgramTranslationTable_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ ChromeHistorgramTranslationTable_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeHistorgramTranslationTable_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeHistorgramTranslationTable_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_hash_to_name() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> hash_to_name() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class ChromeHistorgramTranslationTable : public ::protozero::Message {
+ public:
+ using Decoder = ChromeHistorgramTranslationTable_Decoder;
+ enum : int32_t {
+ kHashToNameFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeHistorgramTranslationTable"; }
+
+ using HashToNameEntry = ::perfetto::protos::pbzero::ChromeHistorgramTranslationTable_HashToNameEntry;
+
+ using FieldMetadata_HashToName =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeHistorgramTranslationTable_HashToNameEntry,
+ ChromeHistorgramTranslationTable>;
+
+ static constexpr FieldMetadata_HashToName kHashToName{};
+ template <typename T = ChromeHistorgramTranslationTable_HashToNameEntry> T* add_hash_to_name() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class ChromeHistorgramTranslationTable_HashToNameEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ChromeHistorgramTranslationTable_HashToNameEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ChromeHistorgramTranslationTable_HashToNameEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ChromeHistorgramTranslationTable_HashToNameEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_key() const { return at<1>().valid(); }
+ uint64_t key() const { return at<1>().as_uint64(); }
+ bool has_value() const { return at<2>().valid(); }
+ ::protozero::ConstChars value() const { return at<2>().as_string(); }
+};
+
+class ChromeHistorgramTranslationTable_HashToNameEntry : public ::protozero::Message {
+ public:
+ using Decoder = ChromeHistorgramTranslationTable_HashToNameEntry_Decoder;
+ enum : int32_t {
+ kKeyFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ChromeHistorgramTranslationTable.HashToNameEntry"; }
+
+
+ using FieldMetadata_Key =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ ChromeHistorgramTranslationTable_HashToNameEntry>;
+
+ static constexpr FieldMetadata_Key kKey{};
+ void set_key(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Key::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Value =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ ChromeHistorgramTranslationTable_HashToNameEntry>;
+
+ static constexpr FieldMetadata_Value kValue{};
+ void set_value(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Value::kFieldId, data, size);
+ }
+ void set_value(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Value::kFieldId, chars.data, chars.size);
+ }
+ void set_value(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Value::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class TranslationTable_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TranslationTable_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TranslationTable_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TranslationTable_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_chrome_histogram() const { return at<1>().valid(); }
+ ::protozero::ConstBytes chrome_histogram() const { return at<1>().as_bytes(); }
+ bool has_chrome_user_event() const { return at<2>().valid(); }
+ ::protozero::ConstBytes chrome_user_event() const { return at<2>().as_bytes(); }
+ bool has_chrome_performance_mark() const { return at<3>().valid(); }
+ ::protozero::ConstBytes chrome_performance_mark() const { return at<3>().as_bytes(); }
+ bool has_slice_name() const { return at<4>().valid(); }
+ ::protozero::ConstBytes slice_name() const { return at<4>().as_bytes(); }
+};
+
+class TranslationTable : public ::protozero::Message {
+ public:
+ using Decoder = TranslationTable_Decoder;
+ enum : int32_t {
+ kChromeHistogramFieldNumber = 1,
+ kChromeUserEventFieldNumber = 2,
+ kChromePerformanceMarkFieldNumber = 3,
+ kSliceNameFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TranslationTable"; }
+
+
+ using FieldMetadata_ChromeHistogram =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeHistorgramTranslationTable,
+ TranslationTable>;
+
+ static constexpr FieldMetadata_ChromeHistogram kChromeHistogram{};
+ template <typename T = ChromeHistorgramTranslationTable> T* set_chrome_histogram() {
+ return BeginNestedMessage<T>(1);
+ }
+
+
+ using FieldMetadata_ChromeUserEvent =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromeUserEventTranslationTable,
+ TranslationTable>;
+
+ static constexpr FieldMetadata_ChromeUserEvent kChromeUserEvent{};
+ template <typename T = ChromeUserEventTranslationTable> T* set_chrome_user_event() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_ChromePerformanceMark =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ChromePerformanceMarkTranslationTable,
+ TranslationTable>;
+
+ static constexpr FieldMetadata_ChromePerformanceMark kChromePerformanceMark{};
+ template <typename T = ChromePerformanceMarkTranslationTable> T* set_chrome_performance_mark() {
+ return BeginNestedMessage<T>(3);
+ }
+
+
+ using FieldMetadata_SliceName =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ SliceNameTranslationTable,
+ TranslationTable>;
+
+ static constexpr FieldMetadata_SliceName kSliceName{};
+ template <typename T = SliceNameTranslationTable> T* set_slice_name() {
+ return BeginNestedMessage<T>(4);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/remote_clock_sync.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_REMOTE_CLOCK_SYNC_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_REMOTE_CLOCK_SYNC_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ClockSnapshot;
+class RemoteClockSync_SyncedClocks;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class RemoteClockSync_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ RemoteClockSync_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RemoteClockSync_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RemoteClockSync_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_synced_clocks() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> synced_clocks() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class RemoteClockSync : public ::protozero::Message {
+ public:
+ using Decoder = RemoteClockSync_Decoder;
+ enum : int32_t {
+ kSyncedClocksFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RemoteClockSync"; }
+
+ using SyncedClocks = ::perfetto::protos::pbzero::RemoteClockSync_SyncedClocks;
+
+ using FieldMetadata_SyncedClocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ RemoteClockSync_SyncedClocks,
+ RemoteClockSync>;
+
+ static constexpr FieldMetadata_SyncedClocks kSyncedClocks{};
+ template <typename T = RemoteClockSync_SyncedClocks> T* add_synced_clocks() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+class RemoteClockSync_SyncedClocks_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ RemoteClockSync_SyncedClocks_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit RemoteClockSync_SyncedClocks_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit RemoteClockSync_SyncedClocks_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_client_clocks() const { return at<2>().valid(); }
+ ::protozero::ConstBytes client_clocks() const { return at<2>().as_bytes(); }
+ bool has_host_clocks() const { return at<3>().valid(); }
+ ::protozero::ConstBytes host_clocks() const { return at<3>().as_bytes(); }
+};
+
+class RemoteClockSync_SyncedClocks : public ::protozero::Message {
+ public:
+ using Decoder = RemoteClockSync_SyncedClocks_Decoder;
+ enum : int32_t {
+ kClientClocksFieldNumber = 2,
+ kHostClocksFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.RemoteClockSync.SyncedClocks"; }
+
+
+ using FieldMetadata_ClientClocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClockSnapshot,
+ RemoteClockSync_SyncedClocks>;
+
+ static constexpr FieldMetadata_ClientClocks kClientClocks{};
+ template <typename T = ClockSnapshot> T* set_client_clocks() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_HostClocks =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ ClockSnapshot,
+ RemoteClockSync_SyncedClocks>;
+
+ static constexpr FieldMetadata_HostClocks kHostClocks{};
+ template <typename T = ClockSnapshot> T* set_host_clocks() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/trace_packet_defaults.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_DEFAULTS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_DEFAULTS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class PerfSampleDefaults;
+class TrackEventDefaults;
+class V8CodeDefaults;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TracePacketDefaults_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/99, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TracePacketDefaults_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TracePacketDefaults_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TracePacketDefaults_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timestamp_clock_id() const { return at<58>().valid(); }
+ uint32_t timestamp_clock_id() const { return at<58>().as_uint32(); }
+ bool has_track_event_defaults() const { return at<11>().valid(); }
+ ::protozero::ConstBytes track_event_defaults() const { return at<11>().as_bytes(); }
+ bool has_perf_sample_defaults() const { return at<12>().valid(); }
+ ::protozero::ConstBytes perf_sample_defaults() const { return at<12>().as_bytes(); }
+ bool has_v8_code_defaults() const { return at<99>().valid(); }
+ ::protozero::ConstBytes v8_code_defaults() const { return at<99>().as_bytes(); }
+};
+
+class TracePacketDefaults : public ::protozero::Message {
+ public:
+ using Decoder = TracePacketDefaults_Decoder;
+ enum : int32_t {
+ kTimestampClockIdFieldNumber = 58,
+ kTrackEventDefaultsFieldNumber = 11,
+ kPerfSampleDefaultsFieldNumber = 12,
+ kV8CodeDefaultsFieldNumber = 99,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TracePacketDefaults"; }
+
+
+ using FieldMetadata_TimestampClockId =
+ ::protozero::proto_utils::FieldMetadata<
+ 58,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TracePacketDefaults>;
+
+ static constexpr FieldMetadata_TimestampClockId kTimestampClockId{};
+ void set_timestamp_clock_id(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimestampClockId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TrackEventDefaults =
+ ::protozero::proto_utils::FieldMetadata<
+ 11,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TrackEventDefaults,
+ TracePacketDefaults>;
+
+ static constexpr FieldMetadata_TrackEventDefaults kTrackEventDefaults{};
+ template <typename T = TrackEventDefaults> T* set_track_event_defaults() {
+ return BeginNestedMessage<T>(11);
+ }
+
+
+ using FieldMetadata_PerfSampleDefaults =
+ ::protozero::proto_utils::FieldMetadata<
+ 12,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ PerfSampleDefaults,
+ TracePacketDefaults>;
+
+ static constexpr FieldMetadata_PerfSampleDefaults kPerfSampleDefaults{};
+ template <typename T = PerfSampleDefaults> T* set_perf_sample_defaults() {
+ return BeginNestedMessage<T>(12);
+ }
+
+
+ using FieldMetadata_V8CodeDefaults =
+ ::protozero::proto_utils::FieldMetadata<
+ 99,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ V8CodeDefaults,
+ TracePacketDefaults>;
+
+ static constexpr FieldMetadata_V8CodeDefaults kV8CodeDefaults{};
+ template <typename T = V8CodeDefaults> T* set_v8_code_defaults() {
+ return BeginNestedMessage<T>(99);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/test_event.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TEST_EVENT_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TEST_EVENT_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DebugAnnotation;
+class TestEvent_TestPayload;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TestEvent_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ TestEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TestEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TestEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_str() const { return at<1>().valid(); }
+ ::protozero::ConstChars str() const { return at<1>().as_string(); }
+ bool has_seq_value() const { return at<2>().valid(); }
+ uint32_t seq_value() const { return at<2>().as_uint32(); }
+ bool has_counter() const { return at<3>().valid(); }
+ uint64_t counter() const { return at<3>().as_uint64(); }
+ bool has_is_last() const { return at<4>().valid(); }
+ bool is_last() const { return at<4>().as_bool(); }
+ bool has_payload() const { return at<5>().valid(); }
+ ::protozero::ConstBytes payload() const { return at<5>().as_bytes(); }
+};
+
+class TestEvent : public ::protozero::Message {
+ public:
+ using Decoder = TestEvent_Decoder;
+ enum : int32_t {
+ kStrFieldNumber = 1,
+ kSeqValueFieldNumber = 2,
+ kCounterFieldNumber = 3,
+ kIsLastFieldNumber = 4,
+ kPayloadFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TestEvent"; }
+
+ using TestPayload = ::perfetto::protos::pbzero::TestEvent_TestPayload;
+
+ using FieldMetadata_Str =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestEvent>;
+
+ static constexpr FieldMetadata_Str kStr{};
+ void set_str(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Str::kFieldId, data, size);
+ }
+ void set_str(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Str::kFieldId, chars.data, chars.size);
+ }
+ void set_str(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Str::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SeqValue =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestEvent>;
+
+ static constexpr FieldMetadata_SeqValue kSeqValue{};
+ void set_seq_value(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SeqValue::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Counter =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ TestEvent>;
+
+ static constexpr FieldMetadata_Counter kCounter{};
+ void set_counter(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Counter::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IsLast =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ TestEvent>;
+
+ static constexpr FieldMetadata_IsLast kIsLast{};
+ void set_is_last(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_IsLast::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Payload =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TestEvent_TestPayload,
+ TestEvent>;
+
+ static constexpr FieldMetadata_Payload kPayload{};
+ template <typename T = TestEvent_TestPayload> T* set_payload() {
+ return BeginNestedMessage<T>(5);
+ }
+
+};
+
+class TestEvent_TestPayload_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/7, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TestEvent_TestPayload_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TestEvent_TestPayload_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TestEvent_TestPayload_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_str() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstChars> str() const { return GetRepeated<::protozero::ConstChars>(1); }
+ bool has_nested() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> nested() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_single_string() const { return at<4>().valid(); }
+ ::protozero::ConstChars single_string() const { return at<4>().as_string(); }
+ bool has_single_int() const { return at<5>().valid(); }
+ int32_t single_int() const { return at<5>().as_int32(); }
+ bool has_repeated_ints() const { return at<6>().valid(); }
+ ::protozero::RepeatedFieldIterator<int32_t> repeated_ints() const { return GetRepeated<int32_t>(6); }
+ bool has_remaining_nesting_depth() const { return at<3>().valid(); }
+ uint32_t remaining_nesting_depth() const { return at<3>().as_uint32(); }
+ bool has_debug_annotations() const { return at<7>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotations() const { return GetRepeated<::protozero::ConstBytes>(7); }
+};
+
+class TestEvent_TestPayload : public ::protozero::Message {
+ public:
+ using Decoder = TestEvent_TestPayload_Decoder;
+ enum : int32_t {
+ kStrFieldNumber = 1,
+ kNestedFieldNumber = 2,
+ kSingleStringFieldNumber = 4,
+ kSingleIntFieldNumber = 5,
+ kRepeatedIntsFieldNumber = 6,
+ kRemainingNestingDepthFieldNumber = 3,
+ kDebugAnnotationsFieldNumber = 7,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TestEvent.TestPayload"; }
+
+
+ using FieldMetadata_Str =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestEvent_TestPayload>;
+
+ static constexpr FieldMetadata_Str kStr{};
+ void add_str(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Str::kFieldId, data, size);
+ }
+ void add_str(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Str::kFieldId, chars.data, chars.size);
+ }
+ void add_str(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Str::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Nested =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TestEvent_TestPayload,
+ TestEvent_TestPayload>;
+
+ static constexpr FieldMetadata_Nested kNested{};
+ template <typename T = TestEvent_TestPayload> T* add_nested() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_SingleString =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestEvent_TestPayload>;
+
+ static constexpr FieldMetadata_SingleString kSingleString{};
+ void set_single_string(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_SingleString::kFieldId, data, size);
+ }
+ void set_single_string(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_SingleString::kFieldId, chars.data, chars.size);
+ }
+ void set_single_string(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_SingleString::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SingleInt =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TestEvent_TestPayload>;
+
+ static constexpr FieldMetadata_SingleInt kSingleInt{};
+ void set_single_int(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SingleInt::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RepeatedInts =
+ ::protozero::proto_utils::FieldMetadata<
+ 6,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TestEvent_TestPayload>;
+
+ static constexpr FieldMetadata_RepeatedInts kRepeatedInts{};
+ void add_repeated_ints(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RepeatedInts::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_RemainingNestingDepth =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestEvent_TestPayload>;
+
+ static constexpr FieldMetadata_RemainingNestingDepth kRemainingNestingDepth{};
+ void set_remaining_nesting_depth(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_RemainingNestingDepth::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DebugAnnotations =
+ ::protozero::proto_utils::FieldMetadata<
+ 7,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation,
+ TestEvent_TestPayload>;
+
+ static constexpr FieldMetadata_DebugAnnotations kDebugAnnotations{};
+ template <typename T = DebugAnnotation> T* add_debug_annotations() {
+ return BeginNestedMessage<T>(7);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/test_extensions.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TEST_EXTENSIONS_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TEST_EXTENSIONS_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class DebugAnnotation;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class TestExtensionChild_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/99, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ TestExtensionChild_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit TestExtensionChild_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit TestExtensionChild_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_child_field_for_testing() const { return at<1>().valid(); }
+ ::protozero::ConstChars child_field_for_testing() const { return at<1>().as_string(); }
+ bool has_debug_annotations() const { return at<99>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotations() const { return GetRepeated<::protozero::ConstBytes>(99); }
+};
+
+class TestExtensionChild : public ::protozero::Message {
+ public:
+ using Decoder = TestExtensionChild_Decoder;
+ enum : int32_t {
+ kChildFieldForTestingFieldNumber = 1,
+ kDebugAnnotationsFieldNumber = 99,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.TestExtensionChild"; }
+
+
+ using FieldMetadata_ChildFieldForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestExtensionChild>;
+
+ static constexpr FieldMetadata_ChildFieldForTesting kChildFieldForTesting{};
+ void set_child_field_for_testing(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ChildFieldForTesting::kFieldId, data, size);
+ }
+ void set_child_field_for_testing(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ChildFieldForTesting::kFieldId, chars.data, chars.size);
+ }
+ void set_child_field_for_testing(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ChildFieldForTesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_DebugAnnotations =
+ ::protozero::proto_utils::FieldMetadata<
+ 99,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ DebugAnnotation,
+ TestExtensionChild>;
+
+ static constexpr FieldMetadata_DebugAnnotations kDebugAnnotations{};
+ template <typename T = DebugAnnotation> T* add_debug_annotations() {
+ return BeginNestedMessage<T>(99);
+ }
+
+};
+
+class TestExtension : public ::perfetto::protos::pbzero::TrackEvent {
+ public:
+
+ using FieldMetadata_StringExtensionForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 9900,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestExtension>;
+
+ static constexpr FieldMetadata_StringExtensionForTesting kStringExtensionForTesting{};
+ void set_string_extension_for_testing(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringExtensionForTesting::kFieldId, data, size);
+ }
+ void set_string_extension_for_testing(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringExtensionForTesting::kFieldId, chars.data, chars.size);
+ }
+ void set_string_extension_for_testing(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringExtensionForTesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_StringExtensionForTesting2 =
+ ::protozero::proto_utils::FieldMetadata<
+ 9905,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestExtension>;
+
+ static constexpr FieldMetadata_StringExtensionForTesting2 kStringExtensionForTesting2{};
+ void set_string_extension_for_testing2(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_StringExtensionForTesting2::kFieldId, data, size);
+ }
+ void set_string_extension_for_testing2(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_StringExtensionForTesting2::kFieldId, chars.data, chars.size);
+ }
+ void set_string_extension_for_testing2(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_StringExtensionForTesting2::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_IntExtensionForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 9901,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ TestExtension>;
+
+ static constexpr FieldMetadata_IntExtensionForTesting kIntExtensionForTesting{};
+ void add_int_extension_for_testing(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_IntExtensionForTesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_OmittedExtensionForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 9902,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ TestExtension>;
+
+ static constexpr FieldMetadata_OmittedExtensionForTesting kOmittedExtensionForTesting{};
+ void set_omitted_extension_for_testing(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_OmittedExtensionForTesting::kFieldId, data, size);
+ }
+ void set_omitted_extension_for_testing(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_OmittedExtensionForTesting::kFieldId, chars.data, chars.size);
+ }
+ void set_omitted_extension_for_testing(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_OmittedExtensionForTesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_NestedMessageExtensionForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 9903,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TestExtensionChild,
+ TestExtension>;
+
+ static constexpr FieldMetadata_NestedMessageExtensionForTesting kNestedMessageExtensionForTesting{};
+ template <typename T = TestExtensionChild> T* set_nested_message_extension_for_testing() {
+ return BeginNestedMessage<T>(9903);
+ }
+
+
+ using FieldMetadata_UintExtensionForTesting =
+ ::protozero::proto_utils::FieldMetadata<
+ 9904,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ TestExtension>;
+
+ static constexpr FieldMetadata_UintExtensionForTesting kUintExtensionForTesting{};
+ void set_uint_extension_for_testing(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_UintExtensionForTesting::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+};
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/trace.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class TracePacket;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class Trace_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ Trace_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit Trace_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit Trace_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_packet() const { return at<1>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> packet() const { return GetRepeated<::protozero::ConstBytes>(1); }
+};
+
+class Trace : public ::protozero::Message {
+ public:
+ using Decoder = Trace_Decoder;
+ enum : int32_t {
+ kPacketFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.Trace"; }
+
+
+ using FieldMetadata_Packet =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ TracePacket,
+ Trace>;
+
+ static constexpr FieldMetadata_Packet kPacket{};
+ template <typename T = TracePacket> T* add_packet() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/extension_descriptor.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_EXTENSION_DESCRIPTOR_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_EXTENSION_DESCRIPTOR_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class FileDescriptorSet;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class ExtensionDescriptor_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/1, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ ExtensionDescriptor_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit ExtensionDescriptor_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit ExtensionDescriptor_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_extension_set() const { return at<1>().valid(); }
+ ::protozero::ConstBytes extension_set() const { return at<1>().as_bytes(); }
+};
+
+class ExtensionDescriptor : public ::protozero::Message {
+ public:
+ using Decoder = ExtensionDescriptor_Decoder;
+ enum : int32_t {
+ kExtensionSetFieldNumber = 1,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.ExtensionDescriptor"; }
+
+
+ using FieldMetadata_ExtensionSet =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ FileDescriptorSet,
+ ExtensionDescriptor>;
+
+ static constexpr FieldMetadata_ExtensionSet kExtensionSet{};
+ template <typename T = FileDescriptorSet> T* set_extension_set() {
+ return BeginNestedMessage<T>(1);
+ }
+
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/memory_graph.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_MEMORY_GRAPH_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_MEMORY_GRAPH_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class MemoryTrackerSnapshot_ProcessSnapshot;
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge;
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode;
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry;
+namespace perfetto_pbzero_enum_MemoryTrackerSnapshot {
+enum LevelOfDetail : int32_t;
+} // namespace perfetto_pbzero_enum_MemoryTrackerSnapshot
+using MemoryTrackerSnapshot_LevelOfDetail = perfetto_pbzero_enum_MemoryTrackerSnapshot::LevelOfDetail;
+namespace perfetto_pbzero_enum_MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry {
+enum Units : int32_t;
+} // namespace perfetto_pbzero_enum_MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry
+using MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units = perfetto_pbzero_enum_MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry::Units;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+namespace perfetto_pbzero_enum_MemoryTrackerSnapshot {
+enum LevelOfDetail : int32_t {
+ DETAIL_FULL = 0,
+ DETAIL_LIGHT = 1,
+ DETAIL_BACKGROUND = 2,
+};
+} // namespace perfetto_pbzero_enum_MemoryTrackerSnapshot
+using MemoryTrackerSnapshot_LevelOfDetail = perfetto_pbzero_enum_MemoryTrackerSnapshot::LevelOfDetail;
+
+
+constexpr MemoryTrackerSnapshot_LevelOfDetail MemoryTrackerSnapshot_LevelOfDetail_MIN = MemoryTrackerSnapshot_LevelOfDetail::DETAIL_FULL;
+constexpr MemoryTrackerSnapshot_LevelOfDetail MemoryTrackerSnapshot_LevelOfDetail_MAX = MemoryTrackerSnapshot_LevelOfDetail::DETAIL_BACKGROUND;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* MemoryTrackerSnapshot_LevelOfDetail_Name(::perfetto::protos::pbzero::MemoryTrackerSnapshot_LevelOfDetail value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::MemoryTrackerSnapshot_LevelOfDetail::DETAIL_FULL:
+ return "DETAIL_FULL";
+
+ case ::perfetto::protos::pbzero::MemoryTrackerSnapshot_LevelOfDetail::DETAIL_LIGHT:
+ return "DETAIL_LIGHT";
+
+ case ::perfetto::protos::pbzero::MemoryTrackerSnapshot_LevelOfDetail::DETAIL_BACKGROUND:
+ return "DETAIL_BACKGROUND";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+namespace perfetto_pbzero_enum_MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry {
+enum Units : int32_t {
+ UNSPECIFIED = 0,
+ BYTES = 1,
+ COUNT = 2,
+};
+} // namespace perfetto_pbzero_enum_MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry
+using MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units = perfetto_pbzero_enum_MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry::Units;
+
+
+constexpr MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units_MIN = MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units::UNSPECIFIED;
+constexpr MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units_MAX = MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units::COUNT;
+
+
+PERFETTO_PROTOZERO_CONSTEXPR14_OR_INLINE
+const char* MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units_Name(::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units value) {
+ switch (value) {
+ case ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units::UNSPECIFIED:
+ return "UNSPECIFIED";
+
+ case ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units::BYTES:
+ return "BYTES";
+
+ case ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units::COUNT:
+ return "COUNT";
+ }
+ return "PBZERO_UNKNOWN_ENUM_VALUE";
+}
+
+class MemoryTrackerSnapshot_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ MemoryTrackerSnapshot_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MemoryTrackerSnapshot_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MemoryTrackerSnapshot_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_global_dump_id() const { return at<1>().valid(); }
+ uint64_t global_dump_id() const { return at<1>().as_uint64(); }
+ bool has_level_of_detail() const { return at<2>().valid(); }
+ int32_t level_of_detail() const { return at<2>().as_int32(); }
+ bool has_process_memory_dumps() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> process_memory_dumps() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class MemoryTrackerSnapshot : public ::protozero::Message {
+ public:
+ using Decoder = MemoryTrackerSnapshot_Decoder;
+ enum : int32_t {
+ kGlobalDumpIdFieldNumber = 1,
+ kLevelOfDetailFieldNumber = 2,
+ kProcessMemoryDumpsFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MemoryTrackerSnapshot"; }
+
+ using ProcessSnapshot = ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot;
+
+ using LevelOfDetail = ::perfetto::protos::pbzero::MemoryTrackerSnapshot_LevelOfDetail;
+ static inline const char* LevelOfDetail_Name(LevelOfDetail value) {
+ return ::perfetto::protos::pbzero::MemoryTrackerSnapshot_LevelOfDetail_Name(value);
+ }
+ static inline const LevelOfDetail DETAIL_FULL = LevelOfDetail::DETAIL_FULL;
+ static inline const LevelOfDetail DETAIL_LIGHT = LevelOfDetail::DETAIL_LIGHT;
+ static inline const LevelOfDetail DETAIL_BACKGROUND = LevelOfDetail::DETAIL_BACKGROUND;
+
+ using FieldMetadata_GlobalDumpId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MemoryTrackerSnapshot>;
+
+ static constexpr FieldMetadata_GlobalDumpId kGlobalDumpId{};
+ void set_global_dump_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_GlobalDumpId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_LevelOfDetail =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ MemoryTrackerSnapshot_LevelOfDetail,
+ MemoryTrackerSnapshot>;
+
+ static constexpr FieldMetadata_LevelOfDetail kLevelOfDetail{};
+ void set_level_of_detail(MemoryTrackerSnapshot_LevelOfDetail value) {
+ static constexpr uint32_t field_id = FieldMetadata_LevelOfDetail::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ProcessMemoryDumps =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MemoryTrackerSnapshot_ProcessSnapshot,
+ MemoryTrackerSnapshot>;
+
+ static constexpr FieldMetadata_ProcessMemoryDumps kProcessMemoryDumps{};
+ template <typename T = MemoryTrackerSnapshot_ProcessSnapshot> T* add_process_memory_dumps() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ MemoryTrackerSnapshot_ProcessSnapshot_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ int32_t pid() const { return at<1>().as_int32(); }
+ bool has_allocator_dumps() const { return at<2>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> allocator_dumps() const { return GetRepeated<::protozero::ConstBytes>(2); }
+ bool has_memory_edges() const { return at<3>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> memory_edges() const { return GetRepeated<::protozero::ConstBytes>(3); }
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot : public ::protozero::Message {
+ public:
+ using Decoder = MemoryTrackerSnapshot_ProcessSnapshot_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kAllocatorDumpsFieldNumber = 2,
+ kMemoryEdgesFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot"; }
+
+ using MemoryNode = ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode;
+ using MemoryEdge = ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge;
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt32,
+ int32_t,
+ MemoryTrackerSnapshot_ProcessSnapshot>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(int32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AllocatorDumps =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode,
+ MemoryTrackerSnapshot_ProcessSnapshot>;
+
+ static constexpr FieldMetadata_AllocatorDumps kAllocatorDumps{};
+ template <typename T = MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode> T* add_allocator_dumps() {
+ return BeginNestedMessage<T>(2);
+ }
+
+
+ using FieldMetadata_MemoryEdges =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge,
+ MemoryTrackerSnapshot_ProcessSnapshot>;
+
+ static constexpr FieldMetadata_MemoryEdges kMemoryEdges{};
+ template <typename T = MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge> T* add_memory_edges() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_source_id() const { return at<1>().valid(); }
+ uint64_t source_id() const { return at<1>().as_uint64(); }
+ bool has_target_id() const { return at<2>().valid(); }
+ uint64_t target_id() const { return at<2>().as_uint64(); }
+ bool has_importance() const { return at<3>().valid(); }
+ uint32_t importance() const { return at<3>().as_uint32(); }
+ bool has_overridable() const { return at<4>().valid(); }
+ bool overridable() const { return at<4>().as_bool(); }
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge : public ::protozero::Message {
+ public:
+ using Decoder = MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge_Decoder;
+ enum : int32_t {
+ kSourceIdFieldNumber = 1,
+ kTargetIdFieldNumber = 2,
+ kImportanceFieldNumber = 3,
+ kOverridableFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot.MemoryEdge"; }
+
+
+ using FieldMetadata_SourceId =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge>;
+
+ static constexpr FieldMetadata_SourceId kSourceId{};
+ void set_source_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SourceId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TargetId =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge>;
+
+ static constexpr FieldMetadata_TargetId kTargetId{};
+ void set_target_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TargetId::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Importance =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge>;
+
+ static constexpr FieldMetadata_Importance kImportance{};
+ void set_importance(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Importance::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Overridable =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryEdge>;
+
+ static constexpr FieldMetadata_Overridable kOverridable{};
+ void set_overridable(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Overridable::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/5, /*HAS_NONPACKED_REPEATED_FIELDS=*/true> {
+ public:
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_id() const { return at<1>().valid(); }
+ uint64_t id() const { return at<1>().as_uint64(); }
+ bool has_absolute_name() const { return at<2>().valid(); }
+ ::protozero::ConstChars absolute_name() const { return at<2>().as_string(); }
+ bool has_weak() const { return at<3>().valid(); }
+ bool weak() const { return at<3>().as_bool(); }
+ bool has_size_bytes() const { return at<4>().valid(); }
+ uint64_t size_bytes() const { return at<4>().as_uint64(); }
+ bool has_entries() const { return at<5>().valid(); }
+ ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> entries() const { return GetRepeated<::protozero::ConstBytes>(5); }
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode : public ::protozero::Message {
+ public:
+ using Decoder = MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_Decoder;
+ enum : int32_t {
+ kIdFieldNumber = 1,
+ kAbsoluteNameFieldNumber = 2,
+ kWeakFieldNumber = 3,
+ kSizeBytesFieldNumber = 4,
+ kEntriesFieldNumber = 5,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot.MemoryNode"; }
+
+ using MemoryNodeEntry = ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry;
+
+ using FieldMetadata_Id =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode>;
+
+ static constexpr FieldMetadata_Id kId{};
+ void set_id(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Id::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_AbsoluteName =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode>;
+
+ static constexpr FieldMetadata_AbsoluteName kAbsoluteName{};
+ void set_absolute_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_AbsoluteName::kFieldId, data, size);
+ }
+ void set_absolute_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_AbsoluteName::kFieldId, chars.data, chars.size);
+ }
+ void set_absolute_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_AbsoluteName::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Weak =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kBool,
+ bool,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode>;
+
+ static constexpr FieldMetadata_Weak kWeak{};
+ void set_weak(bool value) {
+ static constexpr uint32_t field_id = FieldMetadata_Weak::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kBool>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_SizeBytes =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode>;
+
+ static constexpr FieldMetadata_SizeBytes kSizeBytes{};
+ void set_size_bytes(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_SizeBytes::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Entries =
+ ::protozero::proto_utils::FieldMetadata<
+ 5,
+ ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode>;
+
+ static constexpr FieldMetadata_Entries kEntries{};
+ template <typename T = MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry> T* add_entries() {
+ return BeginNestedMessage<T>(5);
+ }
+
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/4, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_name() const { return at<1>().valid(); }
+ ::protozero::ConstChars name() const { return at<1>().as_string(); }
+ bool has_units() const { return at<2>().valid(); }
+ int32_t units() const { return at<2>().as_int32(); }
+ bool has_value_uint64() const { return at<3>().valid(); }
+ uint64_t value_uint64() const { return at<3>().as_uint64(); }
+ bool has_value_string() const { return at<4>().valid(); }
+ ::protozero::ConstChars value_string() const { return at<4>().as_string(); }
+};
+
+class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry : public ::protozero::Message {
+ public:
+ using Decoder = MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Decoder;
+ enum : int32_t {
+ kNameFieldNumber = 1,
+ kUnitsFieldNumber = 2,
+ kValueUint64FieldNumber = 3,
+ kValueStringFieldNumber = 4,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.MemoryTrackerSnapshot.ProcessSnapshot.MemoryNode.MemoryNodeEntry"; }
+
+
+ using Units = ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units;
+ static inline const char* Units_Name(Units value) {
+ return ::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units_Name(value);
+ }
+ static inline const Units UNSPECIFIED = Units::UNSPECIFIED;
+ static inline const Units BYTES = Units::BYTES;
+ static inline const Units COUNT = Units::COUNT;
+
+ using FieldMetadata_Name =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry>;
+
+ static constexpr FieldMetadata_Name kName{};
+ void set_name(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Name::kFieldId, data, size);
+ }
+ void set_name(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Name::kFieldId, chars.data, chars.size);
+ }
+ void set_name(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Units =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kEnum,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry>;
+
+ static constexpr FieldMetadata_Units kUnits{};
+ void set_units(MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry_Units value) {
+ static constexpr uint32_t field_id = FieldMetadata_Units::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kEnum>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ValueUint64 =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint64,
+ uint64_t,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry>;
+
+ static constexpr FieldMetadata_ValueUint64 kValueUint64{};
+ void set_value_uint64(uint64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_ValueUint64::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_ValueString =
+ ::protozero::proto_utils::FieldMetadata<
+ 4,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode_MemoryNodeEntry>;
+
+ static constexpr FieldMetadata_ValueString kValueString{};
+ void set_value_string(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_ValueString::kFieldId, data, size);
+ }
+ void set_value_string(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_ValueString::kFieldId, chars.data, chars.size);
+ }
+ void set_value_string(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_ValueString::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/ui_state.pbzero.h
+// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.
+
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_UI_STATE_PROTO_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_UI_STATE_PROTO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class UiState_HighlightProcess;
+} // Namespace pbzero.
+} // Namespace protos.
+} // Namespace perfetto.
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+
+class UiState_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/3, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ UiState_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit UiState_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit UiState_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_timeline_start_ts() const { return at<1>().valid(); }
+ int64_t timeline_start_ts() const { return at<1>().as_int64(); }
+ bool has_timeline_end_ts() const { return at<2>().valid(); }
+ int64_t timeline_end_ts() const { return at<2>().as_int64(); }
+ bool has_highlight_process() const { return at<3>().valid(); }
+ ::protozero::ConstBytes highlight_process() const { return at<3>().as_bytes(); }
+};
+
+class UiState : public ::protozero::Message {
+ public:
+ using Decoder = UiState_Decoder;
+ enum : int32_t {
+ kTimelineStartTsFieldNumber = 1,
+ kTimelineEndTsFieldNumber = 2,
+ kHighlightProcessFieldNumber = 3,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.UiState"; }
+
+ using HighlightProcess = ::perfetto::protos::pbzero::UiState_HighlightProcess;
+
+ using FieldMetadata_TimelineStartTs =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ UiState>;
+
+ static constexpr FieldMetadata_TimelineStartTs kTimelineStartTs{};
+ void set_timeline_start_ts(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimelineStartTs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_TimelineEndTs =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kInt64,
+ int64_t,
+ UiState>;
+
+ static constexpr FieldMetadata_TimelineEndTs kTimelineEndTs{};
+ void set_timeline_end_ts(int64_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_TimelineEndTs::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kInt64>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_HighlightProcess =
+ ::protozero::proto_utils::FieldMetadata<
+ 3,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kMessage,
+ UiState_HighlightProcess,
+ UiState>;
+
+ static constexpr FieldMetadata_HighlightProcess kHighlightProcess{};
+ template <typename T = UiState_HighlightProcess> T* set_highlight_process() {
+ return BeginNestedMessage<T>(3);
+ }
+
+};
+
+class UiState_HighlightProcess_Decoder : public ::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/2, /*HAS_NONPACKED_REPEATED_FIELDS=*/false> {
+ public:
+ UiState_HighlightProcess_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {}
+ explicit UiState_HighlightProcess_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), raw.size()) {}
+ explicit UiState_HighlightProcess_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {}
+ bool has_pid() const { return at<1>().valid(); }
+ uint32_t pid() const { return at<1>().as_uint32(); }
+ bool has_cmdline() const { return at<2>().valid(); }
+ ::protozero::ConstChars cmdline() const { return at<2>().as_string(); }
+};
+
+class UiState_HighlightProcess : public ::protozero::Message {
+ public:
+ using Decoder = UiState_HighlightProcess_Decoder;
+ enum : int32_t {
+ kPidFieldNumber = 1,
+ kCmdlineFieldNumber = 2,
+ };
+ static constexpr const char* GetName() { return ".perfetto.protos.UiState.HighlightProcess"; }
+
+
+ using FieldMetadata_Pid =
+ ::protozero::proto_utils::FieldMetadata<
+ 1,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kUint32,
+ uint32_t,
+ UiState_HighlightProcess>;
+
+ static constexpr FieldMetadata_Pid kPid{};
+ void set_pid(uint32_t value) {
+ static constexpr uint32_t field_id = FieldMetadata_Pid::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kUint32>
+ ::Append(*this, field_id, value);
+ }
+
+ using FieldMetadata_Cmdline =
+ ::protozero::proto_utils::FieldMetadata<
+ 2,
+ ::protozero::proto_utils::RepetitionType::kNotRepeated,
+ ::protozero::proto_utils::ProtoSchemaType::kString,
+ std::string,
+ UiState_HighlightProcess>;
+
+ static constexpr FieldMetadata_Cmdline kCmdline{};
+ void set_cmdline(const char* data, size_t size) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, data, size);
+ }
+ void set_cmdline(::protozero::ConstChars chars) {
+ AppendBytes(FieldMetadata_Cmdline::kFieldId, chars.data, chars.size);
+ }
+ void set_cmdline(std::string value) {
+ static constexpr uint32_t field_id = FieldMetadata_Cmdline::kFieldId;
+ // Call the appropriate protozero::Message::Append(field_id, ...)
+ // method based on the type of the field.
+ ::protozero::internal::FieldWriter<
+ ::protozero::proto_utils::ProtoSchemaType::kString>
+ ::Append(*this, field_id, value);
+ }
+};
+
+} // Namespace.
+} // Namespace.
+} // Namespace.
+#endif // Include guard.
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_active_processes.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_ACTIVE_PROCESSES_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_ACTIVE_PROCESSES_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeActiveProcesses;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeActiveProcesses : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPidFieldNumber = 1,
+ };
+
+ ChromeActiveProcesses();
+ ~ChromeActiveProcesses() override;
+ ChromeActiveProcesses(ChromeActiveProcesses&&) noexcept;
+ ChromeActiveProcesses& operator=(ChromeActiveProcesses&&);
+ ChromeActiveProcesses(const ChromeActiveProcesses&);
+ ChromeActiveProcesses& operator=(const ChromeActiveProcesses&);
+ bool operator==(const ChromeActiveProcesses&) const;
+ bool operator!=(const ChromeActiveProcesses& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<int32_t>& pid() const { return pid_; }
+ std::vector<int32_t>* mutable_pid() { return &pid_; }
+ int pid_size() const { return static_cast<int>(pid_.size()); }
+ void clear_pid() { pid_.clear(); }
+ void add_pid(int32_t value) { pid_.emplace_back(value); }
+ int32_t* add_pid() { pid_.emplace_back(); return &pid_.back(); }
+
+ private:
+ std::vector<int32_t> pid_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_ACTIVE_PROCESSES_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_application_state_info.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeApplicationStateInfo;
+enum ChromeApplicationStateInfo_ChromeApplicationState : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeApplicationStateInfo_ChromeApplicationState : int {
+ ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_UNKNOWN = 0,
+ ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = 1,
+ ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = 2,
+ ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = 3,
+ ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES = 4,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeApplicationStateInfo : public ::protozero::CppMessageObj {
+ public:
+ using ChromeApplicationState = ChromeApplicationStateInfo_ChromeApplicationState;
+ static constexpr auto APPLICATION_STATE_UNKNOWN = ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_UNKNOWN;
+ static constexpr auto APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_RUNNING_ACTIVITIES;
+ static constexpr auto APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_PAUSED_ACTIVITIES;
+ static constexpr auto APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_STOPPED_ACTIVITIES;
+ static constexpr auto APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES = ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES;
+ static constexpr auto ChromeApplicationState_MIN = ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_UNKNOWN;
+ static constexpr auto ChromeApplicationState_MAX = ChromeApplicationStateInfo_ChromeApplicationState_APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES;
+ enum FieldNumbers {
+ kApplicationStateFieldNumber = 1,
+ };
+
+ ChromeApplicationStateInfo();
+ ~ChromeApplicationStateInfo() override;
+ ChromeApplicationStateInfo(ChromeApplicationStateInfo&&) noexcept;
+ ChromeApplicationStateInfo& operator=(ChromeApplicationStateInfo&&);
+ ChromeApplicationStateInfo(const ChromeApplicationStateInfo&);
+ ChromeApplicationStateInfo& operator=(const ChromeApplicationStateInfo&);
+ bool operator==(const ChromeApplicationStateInfo&) const;
+ bool operator!=(const ChromeApplicationStateInfo& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_application_state() const { return _has_field_[1]; }
+ ChromeApplicationStateInfo_ChromeApplicationState application_state() const { return application_state_; }
+ void set_application_state(ChromeApplicationStateInfo_ChromeApplicationState value) { application_state_ = value; _has_field_.set(1); }
+
+ private:
+ ChromeApplicationStateInfo_ChromeApplicationState application_state_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_COMPOSITOR_SCHEDULER_STATE_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_COMPOSITOR_SCHEDULER_STATE_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class CompositorTimingHistory;
+class BeginFrameSourceState;
+class BeginFrameArgs;
+class SourceLocation;
+class BeginFrameObserverState;
+class BeginImplFrameArgs;
+class BeginImplFrameArgs_TimestampsInUs;
+class ChromeCompositorStateMachine;
+class ChromeCompositorStateMachine_MinorState;
+class ChromeCompositorStateMachine_MajorState;
+class ChromeCompositorSchedulerState;
+enum ChromeCompositorSchedulerAction : int;
+enum BeginFrameArgs_BeginFrameArgsType : int;
+enum BeginImplFrameArgs_State : int;
+enum ChromeCompositorStateMachine_MinorState_TreePriority : int;
+enum ChromeCompositorStateMachine_MinorState_ScrollHandlerState : int;
+enum ChromeCompositorStateMachine_MajorState_BeginImplFrameState : int;
+enum ChromeCompositorStateMachine_MajorState_BeginMainFrameState : int;
+enum ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState : int;
+enum ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState : int;
+enum ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeCompositorSchedulerAction : int {
+ CC_SCHEDULER_ACTION_UNSPECIFIED = 0,
+ CC_SCHEDULER_ACTION_NONE = 1,
+ CC_SCHEDULER_ACTION_SEND_BEGIN_MAIN_FRAME = 2,
+ CC_SCHEDULER_ACTION_COMMIT = 3,
+ CC_SCHEDULER_ACTION_ACTIVATE_SYNC_TREE = 4,
+ CC_SCHEDULER_ACTION_DRAW_IF_POSSIBLE = 5,
+ CC_SCHEDULER_ACTION_DRAW_FORCED = 6,
+ CC_SCHEDULER_ACTION_DRAW_ABORT = 7,
+ CC_SCHEDULER_ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION = 8,
+ CC_SCHEDULER_ACTION_PREPARE_TILES = 9,
+ CC_SCHEDULER_ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK = 10,
+ CC_SCHEDULER_ACTION_PERFORM_IMPL_SIDE_INVALIDATION = 11,
+ CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL = 12,
+ CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON = 13,
+};
+enum BeginFrameArgs_BeginFrameArgsType : int {
+ BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED = 0,
+ BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_INVALID = 1,
+ BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_NORMAL = 2,
+ BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_MISSED = 3,
+};
+enum BeginImplFrameArgs_State : int {
+ BeginImplFrameArgs_State_BEGIN_FRAME_FINISHED = 0,
+ BeginImplFrameArgs_State_BEGIN_FRAME_USING = 1,
+};
+enum ChromeCompositorStateMachine_MinorState_TreePriority : int {
+ ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_UNSPECIFIED = 0,
+ ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES = 1,
+ ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY = 2,
+ ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY = 3,
+};
+enum ChromeCompositorStateMachine_MinorState_ScrollHandlerState : int {
+ ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_HANDLER_UNSPECIFIED = 0,
+ ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_AFFECTS_SCROLL_HANDLER = 1,
+ ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER = 2,
+};
+enum ChromeCompositorStateMachine_MajorState_BeginImplFrameState : int {
+ ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_UNSPECIFIED = 0,
+ ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_IDLE = 1,
+ ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME = 2,
+ ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_INSIDE_DEADLINE = 3,
+};
+enum ChromeCompositorStateMachine_MajorState_BeginMainFrameState : int {
+ ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_UNSPECIFIED = 0,
+ ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_IDLE = 1,
+ ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_SENT = 2,
+ ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_READY_TO_COMMIT = 3,
+};
+enum ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState : int {
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_UNSPECIFIED = 0,
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_NONE = 1,
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_ACTIVE = 2,
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_CREATING = 3,
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT = 4,
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION = 5,
+};
+enum ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState : int {
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_UNSPECIFIED = 0,
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_IDLE = 1,
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_WAITING_FOR_COMMIT = 2,
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_WAITING_FOR_ACTIVATION = 3,
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_WAITING_FOR_DRAW = 4,
+};
+enum ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode : int {
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_UNSPECIFIED = 0,
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_NONE = 1,
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_IMMEDIATE = 2,
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_REGULAR = 3,
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_LATE = 4,
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_BLOCKED = 5,
+};
+
+class PERFETTO_EXPORT_COMPONENT CompositorTimingHistory : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kBeginMainFrameQueueCriticalEstimateDeltaUsFieldNumber = 1,
+ kBeginMainFrameQueueNotCriticalEstimateDeltaUsFieldNumber = 2,
+ kBeginMainFrameStartToReadyToCommitEstimateDeltaUsFieldNumber = 3,
+ kCommitToReadyToActivateEstimateDeltaUsFieldNumber = 4,
+ kPrepareTilesEstimateDeltaUsFieldNumber = 5,
+ kActivateEstimateDeltaUsFieldNumber = 6,
+ kDrawEstimateDeltaUsFieldNumber = 7,
+ };
+
+ CompositorTimingHistory();
+ ~CompositorTimingHistory() override;
+ CompositorTimingHistory(CompositorTimingHistory&&) noexcept;
+ CompositorTimingHistory& operator=(CompositorTimingHistory&&);
+ CompositorTimingHistory(const CompositorTimingHistory&);
+ CompositorTimingHistory& operator=(const CompositorTimingHistory&);
+ bool operator==(const CompositorTimingHistory&) const;
+ bool operator!=(const CompositorTimingHistory& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_begin_main_frame_queue_critical_estimate_delta_us() const { return _has_field_[1]; }
+ int64_t begin_main_frame_queue_critical_estimate_delta_us() const { return begin_main_frame_queue_critical_estimate_delta_us_; }
+ void set_begin_main_frame_queue_critical_estimate_delta_us(int64_t value) { begin_main_frame_queue_critical_estimate_delta_us_ = value; _has_field_.set(1); }
+
+ bool has_begin_main_frame_queue_not_critical_estimate_delta_us() const { return _has_field_[2]; }
+ int64_t begin_main_frame_queue_not_critical_estimate_delta_us() const { return begin_main_frame_queue_not_critical_estimate_delta_us_; }
+ void set_begin_main_frame_queue_not_critical_estimate_delta_us(int64_t value) { begin_main_frame_queue_not_critical_estimate_delta_us_ = value; _has_field_.set(2); }
+
+ bool has_begin_main_frame_start_to_ready_to_commit_estimate_delta_us() const { return _has_field_[3]; }
+ int64_t begin_main_frame_start_to_ready_to_commit_estimate_delta_us() const { return begin_main_frame_start_to_ready_to_commit_estimate_delta_us_; }
+ void set_begin_main_frame_start_to_ready_to_commit_estimate_delta_us(int64_t value) { begin_main_frame_start_to_ready_to_commit_estimate_delta_us_ = value; _has_field_.set(3); }
+
+ bool has_commit_to_ready_to_activate_estimate_delta_us() const { return _has_field_[4]; }
+ int64_t commit_to_ready_to_activate_estimate_delta_us() const { return commit_to_ready_to_activate_estimate_delta_us_; }
+ void set_commit_to_ready_to_activate_estimate_delta_us(int64_t value) { commit_to_ready_to_activate_estimate_delta_us_ = value; _has_field_.set(4); }
+
+ bool has_prepare_tiles_estimate_delta_us() const { return _has_field_[5]; }
+ int64_t prepare_tiles_estimate_delta_us() const { return prepare_tiles_estimate_delta_us_; }
+ void set_prepare_tiles_estimate_delta_us(int64_t value) { prepare_tiles_estimate_delta_us_ = value; _has_field_.set(5); }
+
+ bool has_activate_estimate_delta_us() const { return _has_field_[6]; }
+ int64_t activate_estimate_delta_us() const { return activate_estimate_delta_us_; }
+ void set_activate_estimate_delta_us(int64_t value) { activate_estimate_delta_us_ = value; _has_field_.set(6); }
+
+ bool has_draw_estimate_delta_us() const { return _has_field_[7]; }
+ int64_t draw_estimate_delta_us() const { return draw_estimate_delta_us_; }
+ void set_draw_estimate_delta_us(int64_t value) { draw_estimate_delta_us_ = value; _has_field_.set(7); }
+
+ private:
+ int64_t begin_main_frame_queue_critical_estimate_delta_us_{};
+ int64_t begin_main_frame_queue_not_critical_estimate_delta_us_{};
+ int64_t begin_main_frame_start_to_ready_to_commit_estimate_delta_us_{};
+ int64_t commit_to_ready_to_activate_estimate_delta_us_{};
+ int64_t prepare_tiles_estimate_delta_us_{};
+ int64_t activate_estimate_delta_us_{};
+ int64_t draw_estimate_delta_us_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT BeginFrameSourceState : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSourceIdFieldNumber = 1,
+ kPausedFieldNumber = 2,
+ kNumObserversFieldNumber = 3,
+ kLastBeginFrameArgsFieldNumber = 4,
+ };
+
+ BeginFrameSourceState();
+ ~BeginFrameSourceState() override;
+ BeginFrameSourceState(BeginFrameSourceState&&) noexcept;
+ BeginFrameSourceState& operator=(BeginFrameSourceState&&);
+ BeginFrameSourceState(const BeginFrameSourceState&);
+ BeginFrameSourceState& operator=(const BeginFrameSourceState&);
+ bool operator==(const BeginFrameSourceState&) const;
+ bool operator!=(const BeginFrameSourceState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_source_id() const { return _has_field_[1]; }
+ uint32_t source_id() const { return source_id_; }
+ void set_source_id(uint32_t value) { source_id_ = value; _has_field_.set(1); }
+
+ bool has_paused() const { return _has_field_[2]; }
+ bool paused() const { return paused_; }
+ void set_paused(bool value) { paused_ = value; _has_field_.set(2); }
+
+ bool has_num_observers() const { return _has_field_[3]; }
+ uint32_t num_observers() const { return num_observers_; }
+ void set_num_observers(uint32_t value) { num_observers_ = value; _has_field_.set(3); }
+
+ bool has_last_begin_frame_args() const { return _has_field_[4]; }
+ const BeginFrameArgs& last_begin_frame_args() const { return *last_begin_frame_args_; }
+ BeginFrameArgs* mutable_last_begin_frame_args() { _has_field_.set(4); return last_begin_frame_args_.get(); }
+
+ private:
+ uint32_t source_id_{};
+ bool paused_{};
+ uint32_t num_observers_{};
+ ::protozero::CopyablePtr<BeginFrameArgs> last_begin_frame_args_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT BeginFrameArgs : public ::protozero::CppMessageObj {
+ public:
+ using BeginFrameArgsType = BeginFrameArgs_BeginFrameArgsType;
+ static constexpr auto BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED = BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED;
+ static constexpr auto BEGIN_FRAME_ARGS_TYPE_INVALID = BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_INVALID;
+ static constexpr auto BEGIN_FRAME_ARGS_TYPE_NORMAL = BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_NORMAL;
+ static constexpr auto BEGIN_FRAME_ARGS_TYPE_MISSED = BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_MISSED;
+ static constexpr auto BeginFrameArgsType_MIN = BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_UNSPECIFIED;
+ static constexpr auto BeginFrameArgsType_MAX = BeginFrameArgs_BeginFrameArgsType_BEGIN_FRAME_ARGS_TYPE_MISSED;
+ enum FieldNumbers {
+ kTypeFieldNumber = 1,
+ kSourceIdFieldNumber = 2,
+ kSequenceNumberFieldNumber = 3,
+ kFrameTimeUsFieldNumber = 4,
+ kDeadlineUsFieldNumber = 5,
+ kIntervalDeltaUsFieldNumber = 6,
+ kOnCriticalPathFieldNumber = 7,
+ kAnimateOnlyFieldNumber = 8,
+ kSourceLocationIidFieldNumber = 9,
+ kSourceLocationFieldNumber = 10,
+ kFramesThrottledSinceLastFieldNumber = 12,
+ };
+
+ BeginFrameArgs();
+ ~BeginFrameArgs() override;
+ BeginFrameArgs(BeginFrameArgs&&) noexcept;
+ BeginFrameArgs& operator=(BeginFrameArgs&&);
+ BeginFrameArgs(const BeginFrameArgs&);
+ BeginFrameArgs& operator=(const BeginFrameArgs&);
+ bool operator==(const BeginFrameArgs&) const;
+ bool operator!=(const BeginFrameArgs& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_type() const { return _has_field_[1]; }
+ BeginFrameArgs_BeginFrameArgsType type() const { return type_; }
+ void set_type(BeginFrameArgs_BeginFrameArgsType value) { type_ = value; _has_field_.set(1); }
+
+ bool has_source_id() const { return _has_field_[2]; }
+ uint64_t source_id() const { return source_id_; }
+ void set_source_id(uint64_t value) { source_id_ = value; _has_field_.set(2); }
+
+ bool has_sequence_number() const { return _has_field_[3]; }
+ uint64_t sequence_number() const { return sequence_number_; }
+ void set_sequence_number(uint64_t value) { sequence_number_ = value; _has_field_.set(3); }
+
+ bool has_frame_time_us() const { return _has_field_[4]; }
+ int64_t frame_time_us() const { return frame_time_us_; }
+ void set_frame_time_us(int64_t value) { frame_time_us_ = value; _has_field_.set(4); }
+
+ bool has_deadline_us() const { return _has_field_[5]; }
+ int64_t deadline_us() const { return deadline_us_; }
+ void set_deadline_us(int64_t value) { deadline_us_ = value; _has_field_.set(5); }
+
+ bool has_interval_delta_us() const { return _has_field_[6]; }
+ int64_t interval_delta_us() const { return interval_delta_us_; }
+ void set_interval_delta_us(int64_t value) { interval_delta_us_ = value; _has_field_.set(6); }
+
+ bool has_on_critical_path() const { return _has_field_[7]; }
+ bool on_critical_path() const { return on_critical_path_; }
+ void set_on_critical_path(bool value) { on_critical_path_ = value; _has_field_.set(7); }
+
+ bool has_animate_only() const { return _has_field_[8]; }
+ bool animate_only() const { return animate_only_; }
+ void set_animate_only(bool value) { animate_only_ = value; _has_field_.set(8); }
+
+ bool has_source_location_iid() const { return _has_field_[9]; }
+ uint64_t source_location_iid() const { return source_location_iid_; }
+ void set_source_location_iid(uint64_t value) { source_location_iid_ = value; _has_field_.set(9); }
+
+ bool has_source_location() const { return _has_field_[10]; }
+ const SourceLocation& source_location() const { return *source_location_; }
+ SourceLocation* mutable_source_location() { _has_field_.set(10); return source_location_.get(); }
+
+ bool has_frames_throttled_since_last() const { return _has_field_[12]; }
+ int64_t frames_throttled_since_last() const { return frames_throttled_since_last_; }
+ void set_frames_throttled_since_last(int64_t value) { frames_throttled_since_last_ = value; _has_field_.set(12); }
+
+ private:
+ BeginFrameArgs_BeginFrameArgsType type_{};
+ uint64_t source_id_{};
+ uint64_t sequence_number_{};
+ int64_t frame_time_us_{};
+ int64_t deadline_us_{};
+ int64_t interval_delta_us_{};
+ bool on_critical_path_{};
+ bool animate_only_{};
+ uint64_t source_location_iid_{};
+ ::protozero::CopyablePtr<SourceLocation> source_location_;
+ int64_t frames_throttled_since_last_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<13> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT BeginFrameObserverState : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDroppedBeginFrameArgsFieldNumber = 1,
+ kLastBeginFrameArgsFieldNumber = 2,
+ };
+
+ BeginFrameObserverState();
+ ~BeginFrameObserverState() override;
+ BeginFrameObserverState(BeginFrameObserverState&&) noexcept;
+ BeginFrameObserverState& operator=(BeginFrameObserverState&&);
+ BeginFrameObserverState(const BeginFrameObserverState&);
+ BeginFrameObserverState& operator=(const BeginFrameObserverState&);
+ bool operator==(const BeginFrameObserverState&) const;
+ bool operator!=(const BeginFrameObserverState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_dropped_begin_frame_args() const { return _has_field_[1]; }
+ int64_t dropped_begin_frame_args() const { return dropped_begin_frame_args_; }
+ void set_dropped_begin_frame_args(int64_t value) { dropped_begin_frame_args_ = value; _has_field_.set(1); }
+
+ bool has_last_begin_frame_args() const { return _has_field_[2]; }
+ const BeginFrameArgs& last_begin_frame_args() const { return *last_begin_frame_args_; }
+ BeginFrameArgs* mutable_last_begin_frame_args() { _has_field_.set(2); return last_begin_frame_args_.get(); }
+
+ private:
+ int64_t dropped_begin_frame_args_{};
+ ::protozero::CopyablePtr<BeginFrameArgs> last_begin_frame_args_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT BeginImplFrameArgs : public ::protozero::CppMessageObj {
+ public:
+ using TimestampsInUs = BeginImplFrameArgs_TimestampsInUs;
+ using State = BeginImplFrameArgs_State;
+ static constexpr auto BEGIN_FRAME_FINISHED = BeginImplFrameArgs_State_BEGIN_FRAME_FINISHED;
+ static constexpr auto BEGIN_FRAME_USING = BeginImplFrameArgs_State_BEGIN_FRAME_USING;
+ static constexpr auto State_MIN = BeginImplFrameArgs_State_BEGIN_FRAME_FINISHED;
+ static constexpr auto State_MAX = BeginImplFrameArgs_State_BEGIN_FRAME_USING;
+ enum FieldNumbers {
+ kUpdatedAtUsFieldNumber = 1,
+ kFinishedAtUsFieldNumber = 2,
+ kStateFieldNumber = 3,
+ kCurrentArgsFieldNumber = 4,
+ kLastArgsFieldNumber = 5,
+ kTimestampsInUsFieldNumber = 6,
+ };
+
+ BeginImplFrameArgs();
+ ~BeginImplFrameArgs() override;
+ BeginImplFrameArgs(BeginImplFrameArgs&&) noexcept;
+ BeginImplFrameArgs& operator=(BeginImplFrameArgs&&);
+ BeginImplFrameArgs(const BeginImplFrameArgs&);
+ BeginImplFrameArgs& operator=(const BeginImplFrameArgs&);
+ bool operator==(const BeginImplFrameArgs&) const;
+ bool operator!=(const BeginImplFrameArgs& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_updated_at_us() const { return _has_field_[1]; }
+ int64_t updated_at_us() const { return updated_at_us_; }
+ void set_updated_at_us(int64_t value) { updated_at_us_ = value; _has_field_.set(1); }
+
+ bool has_finished_at_us() const { return _has_field_[2]; }
+ int64_t finished_at_us() const { return finished_at_us_; }
+ void set_finished_at_us(int64_t value) { finished_at_us_ = value; _has_field_.set(2); }
+
+ bool has_state() const { return _has_field_[3]; }
+ BeginImplFrameArgs_State state() const { return state_; }
+ void set_state(BeginImplFrameArgs_State value) { state_ = value; _has_field_.set(3); }
+
+ bool has_current_args() const { return _has_field_[4]; }
+ const BeginFrameArgs& current_args() const { return *current_args_; }
+ BeginFrameArgs* mutable_current_args() { _has_field_.set(4); return current_args_.get(); }
+
+ bool has_last_args() const { return _has_field_[5]; }
+ const BeginFrameArgs& last_args() const { return *last_args_; }
+ BeginFrameArgs* mutable_last_args() { _has_field_.set(5); return last_args_.get(); }
+
+ bool has_timestamps_in_us() const { return _has_field_[6]; }
+ const BeginImplFrameArgs_TimestampsInUs& timestamps_in_us() const { return *timestamps_in_us_; }
+ BeginImplFrameArgs_TimestampsInUs* mutable_timestamps_in_us() { _has_field_.set(6); return timestamps_in_us_.get(); }
+
+ private:
+ int64_t updated_at_us_{};
+ int64_t finished_at_us_{};
+ BeginImplFrameArgs_State state_{};
+ ::protozero::CopyablePtr<BeginFrameArgs> current_args_;
+ ::protozero::CopyablePtr<BeginFrameArgs> last_args_;
+ ::protozero::CopyablePtr<BeginImplFrameArgs_TimestampsInUs> timestamps_in_us_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<7> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT BeginImplFrameArgs_TimestampsInUs : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIntervalDeltaFieldNumber = 1,
+ kNowToDeadlineDeltaFieldNumber = 2,
+ kFrameTimeToNowDeltaFieldNumber = 3,
+ kFrameTimeToDeadlineDeltaFieldNumber = 4,
+ kNowFieldNumber = 5,
+ kFrameTimeFieldNumber = 6,
+ kDeadlineFieldNumber = 7,
+ };
+
+ BeginImplFrameArgs_TimestampsInUs();
+ ~BeginImplFrameArgs_TimestampsInUs() override;
+ BeginImplFrameArgs_TimestampsInUs(BeginImplFrameArgs_TimestampsInUs&&) noexcept;
+ BeginImplFrameArgs_TimestampsInUs& operator=(BeginImplFrameArgs_TimestampsInUs&&);
+ BeginImplFrameArgs_TimestampsInUs(const BeginImplFrameArgs_TimestampsInUs&);
+ BeginImplFrameArgs_TimestampsInUs& operator=(const BeginImplFrameArgs_TimestampsInUs&);
+ bool operator==(const BeginImplFrameArgs_TimestampsInUs&) const;
+ bool operator!=(const BeginImplFrameArgs_TimestampsInUs& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_interval_delta() const { return _has_field_[1]; }
+ int64_t interval_delta() const { return interval_delta_; }
+ void set_interval_delta(int64_t value) { interval_delta_ = value; _has_field_.set(1); }
+
+ bool has_now_to_deadline_delta() const { return _has_field_[2]; }
+ int64_t now_to_deadline_delta() const { return now_to_deadline_delta_; }
+ void set_now_to_deadline_delta(int64_t value) { now_to_deadline_delta_ = value; _has_field_.set(2); }
+
+ bool has_frame_time_to_now_delta() const { return _has_field_[3]; }
+ int64_t frame_time_to_now_delta() const { return frame_time_to_now_delta_; }
+ void set_frame_time_to_now_delta(int64_t value) { frame_time_to_now_delta_ = value; _has_field_.set(3); }
+
+ bool has_frame_time_to_deadline_delta() const { return _has_field_[4]; }
+ int64_t frame_time_to_deadline_delta() const { return frame_time_to_deadline_delta_; }
+ void set_frame_time_to_deadline_delta(int64_t value) { frame_time_to_deadline_delta_ = value; _has_field_.set(4); }
+
+ bool has_now() const { return _has_field_[5]; }
+ int64_t now() const { return now_; }
+ void set_now(int64_t value) { now_ = value; _has_field_.set(5); }
+
+ bool has_frame_time() const { return _has_field_[6]; }
+ int64_t frame_time() const { return frame_time_; }
+ void set_frame_time(int64_t value) { frame_time_ = value; _has_field_.set(6); }
+
+ bool has_deadline() const { return _has_field_[7]; }
+ int64_t deadline() const { return deadline_; }
+ void set_deadline(int64_t value) { deadline_ = value; _has_field_.set(7); }
+
+ private:
+ int64_t interval_delta_{};
+ int64_t now_to_deadline_delta_{};
+ int64_t frame_time_to_now_delta_{};
+ int64_t frame_time_to_deadline_delta_{};
+ int64_t now_{};
+ int64_t frame_time_{};
+ int64_t deadline_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChromeCompositorStateMachine : public ::protozero::CppMessageObj {
+ public:
+ using MajorState = ChromeCompositorStateMachine_MajorState;
+ using MinorState = ChromeCompositorStateMachine_MinorState;
+ enum FieldNumbers {
+ kMajorStateFieldNumber = 1,
+ kMinorStateFieldNumber = 2,
+ };
+
+ ChromeCompositorStateMachine();
+ ~ChromeCompositorStateMachine() override;
+ ChromeCompositorStateMachine(ChromeCompositorStateMachine&&) noexcept;
+ ChromeCompositorStateMachine& operator=(ChromeCompositorStateMachine&&);
+ ChromeCompositorStateMachine(const ChromeCompositorStateMachine&);
+ ChromeCompositorStateMachine& operator=(const ChromeCompositorStateMachine&);
+ bool operator==(const ChromeCompositorStateMachine&) const;
+ bool operator!=(const ChromeCompositorStateMachine& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_major_state() const { return _has_field_[1]; }
+ const ChromeCompositorStateMachine_MajorState& major_state() const { return *major_state_; }
+ ChromeCompositorStateMachine_MajorState* mutable_major_state() { _has_field_.set(1); return major_state_.get(); }
+
+ bool has_minor_state() const { return _has_field_[2]; }
+ const ChromeCompositorStateMachine_MinorState& minor_state() const { return *minor_state_; }
+ ChromeCompositorStateMachine_MinorState* mutable_minor_state() { _has_field_.set(2); return minor_state_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<ChromeCompositorStateMachine_MajorState> major_state_;
+ ::protozero::CopyablePtr<ChromeCompositorStateMachine_MinorState> minor_state_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChromeCompositorStateMachine_MinorState : public ::protozero::CppMessageObj {
+ public:
+ using TreePriority = ChromeCompositorStateMachine_MinorState_TreePriority;
+ static constexpr auto TREE_PRIORITY_UNSPECIFIED = ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_UNSPECIFIED;
+ static constexpr auto TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES = ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES;
+ static constexpr auto TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY = ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY;
+ static constexpr auto TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY = ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY;
+ static constexpr auto TreePriority_MIN = ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_UNSPECIFIED;
+ static constexpr auto TreePriority_MAX = ChromeCompositorStateMachine_MinorState_TreePriority_TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY;
+ using ScrollHandlerState = ChromeCompositorStateMachine_MinorState_ScrollHandlerState;
+ static constexpr auto SCROLL_HANDLER_UNSPECIFIED = ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_HANDLER_UNSPECIFIED;
+ static constexpr auto SCROLL_AFFECTS_SCROLL_HANDLER = ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_AFFECTS_SCROLL_HANDLER;
+ static constexpr auto SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER = ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
+ static constexpr auto ScrollHandlerState_MIN = ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_HANDLER_UNSPECIFIED;
+ static constexpr auto ScrollHandlerState_MAX = ChromeCompositorStateMachine_MinorState_ScrollHandlerState_SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
+ enum FieldNumbers {
+ kCommitCountFieldNumber = 1,
+ kCurrentFrameNumberFieldNumber = 2,
+ kLastFrameNumberSubmitPerformedFieldNumber = 3,
+ kLastFrameNumberDrawPerformedFieldNumber = 4,
+ kLastFrameNumberBeginMainFrameSentFieldNumber = 5,
+ kDidDrawFieldNumber = 6,
+ kDidSendBeginMainFrameForCurrentFrameFieldNumber = 7,
+ kDidNotifyBeginMainFrameNotExpectedUntilFieldNumber = 8,
+ kDidNotifyBeginMainFrameNotExpectedSoonFieldNumber = 9,
+ kWantsBeginMainFrameNotExpectedFieldNumber = 10,
+ kDidCommitDuringFrameFieldNumber = 11,
+ kDidInvalidateLayerTreeFrameSinkFieldNumber = 12,
+ kDidPerformImplSideInvalidaionFieldNumber = 13,
+ kDidPrepareTilesFieldNumber = 14,
+ kConsecutiveCheckerboardAnimationsFieldNumber = 15,
+ kPendingSubmitFramesFieldNumber = 16,
+ kSubmitFramesWithCurrentLayerTreeFrameSinkFieldNumber = 17,
+ kNeedsRedrawFieldNumber = 18,
+ kNeedsPrepareTilesFieldNumber = 19,
+ kNeedsBeginMainFrameFieldNumber = 20,
+ kNeedsOneBeginImplFrameFieldNumber = 21,
+ kVisibleFieldNumber = 22,
+ kBeginFrameSourcePausedFieldNumber = 23,
+ kCanDrawFieldNumber = 24,
+ kResourcelessDrawFieldNumber = 25,
+ kHasPendingTreeFieldNumber = 26,
+ kPendingTreeIsReadyForActivationFieldNumber = 27,
+ kActiveTreeNeedsFirstDrawFieldNumber = 28,
+ kActiveTreeIsReadyToDrawFieldNumber = 29,
+ kDidCreateAndInitializeFirstLayerTreeFrameSinkFieldNumber = 30,
+ kTreePriorityFieldNumber = 31,
+ kScrollHandlerStateFieldNumber = 32,
+ kCriticalBeginMainFrameToActivateIsFastFieldNumber = 33,
+ kMainThreadMissedLastDeadlineFieldNumber = 34,
+ kVideoNeedsBeginFramesFieldNumber = 36,
+ kDeferBeginMainFrameFieldNumber = 37,
+ kLastCommitHadNoUpdatesFieldNumber = 38,
+ kDidDrawInLastFrameFieldNumber = 39,
+ kDidSubmitInLastFrameFieldNumber = 40,
+ kNeedsImplSideInvalidationFieldNumber = 41,
+ kCurrentPendingTreeIsImplSideFieldNumber = 42,
+ kPreviousPendingTreeWasImplSideFieldNumber = 43,
+ kProcessingAnimationWorkletsForActiveTreeFieldNumber = 44,
+ kProcessingAnimationWorkletsForPendingTreeFieldNumber = 45,
+ kProcessingPaintWorkletsForPendingTreeFieldNumber = 46,
+ };
+
+ ChromeCompositorStateMachine_MinorState();
+ ~ChromeCompositorStateMachine_MinorState() override;
+ ChromeCompositorStateMachine_MinorState(ChromeCompositorStateMachine_MinorState&&) noexcept;
+ ChromeCompositorStateMachine_MinorState& operator=(ChromeCompositorStateMachine_MinorState&&);
+ ChromeCompositorStateMachine_MinorState(const ChromeCompositorStateMachine_MinorState&);
+ ChromeCompositorStateMachine_MinorState& operator=(const ChromeCompositorStateMachine_MinorState&);
+ bool operator==(const ChromeCompositorStateMachine_MinorState&) const;
+ bool operator!=(const ChromeCompositorStateMachine_MinorState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_commit_count() const { return _has_field_[1]; }
+ int32_t commit_count() const { return commit_count_; }
+ void set_commit_count(int32_t value) { commit_count_ = value; _has_field_.set(1); }
+
+ bool has_current_frame_number() const { return _has_field_[2]; }
+ int32_t current_frame_number() const { return current_frame_number_; }
+ void set_current_frame_number(int32_t value) { current_frame_number_ = value; _has_field_.set(2); }
+
+ bool has_last_frame_number_submit_performed() const { return _has_field_[3]; }
+ int32_t last_frame_number_submit_performed() const { return last_frame_number_submit_performed_; }
+ void set_last_frame_number_submit_performed(int32_t value) { last_frame_number_submit_performed_ = value; _has_field_.set(3); }
+
+ bool has_last_frame_number_draw_performed() const { return _has_field_[4]; }
+ int32_t last_frame_number_draw_performed() const { return last_frame_number_draw_performed_; }
+ void set_last_frame_number_draw_performed(int32_t value) { last_frame_number_draw_performed_ = value; _has_field_.set(4); }
+
+ bool has_last_frame_number_begin_main_frame_sent() const { return _has_field_[5]; }
+ int32_t last_frame_number_begin_main_frame_sent() const { return last_frame_number_begin_main_frame_sent_; }
+ void set_last_frame_number_begin_main_frame_sent(int32_t value) { last_frame_number_begin_main_frame_sent_ = value; _has_field_.set(5); }
+
+ bool has_did_draw() const { return _has_field_[6]; }
+ bool did_draw() const { return did_draw_; }
+ void set_did_draw(bool value) { did_draw_ = value; _has_field_.set(6); }
+
+ bool has_did_send_begin_main_frame_for_current_frame() const { return _has_field_[7]; }
+ bool did_send_begin_main_frame_for_current_frame() const { return did_send_begin_main_frame_for_current_frame_; }
+ void set_did_send_begin_main_frame_for_current_frame(bool value) { did_send_begin_main_frame_for_current_frame_ = value; _has_field_.set(7); }
+
+ bool has_did_notify_begin_main_frame_not_expected_until() const { return _has_field_[8]; }
+ bool did_notify_begin_main_frame_not_expected_until() const { return did_notify_begin_main_frame_not_expected_until_; }
+ void set_did_notify_begin_main_frame_not_expected_until(bool value) { did_notify_begin_main_frame_not_expected_until_ = value; _has_field_.set(8); }
+
+ bool has_did_notify_begin_main_frame_not_expected_soon() const { return _has_field_[9]; }
+ bool did_notify_begin_main_frame_not_expected_soon() const { return did_notify_begin_main_frame_not_expected_soon_; }
+ void set_did_notify_begin_main_frame_not_expected_soon(bool value) { did_notify_begin_main_frame_not_expected_soon_ = value; _has_field_.set(9); }
+
+ bool has_wants_begin_main_frame_not_expected() const { return _has_field_[10]; }
+ bool wants_begin_main_frame_not_expected() const { return wants_begin_main_frame_not_expected_; }
+ void set_wants_begin_main_frame_not_expected(bool value) { wants_begin_main_frame_not_expected_ = value; _has_field_.set(10); }
+
+ bool has_did_commit_during_frame() const { return _has_field_[11]; }
+ bool did_commit_during_frame() const { return did_commit_during_frame_; }
+ void set_did_commit_during_frame(bool value) { did_commit_during_frame_ = value; _has_field_.set(11); }
+
+ bool has_did_invalidate_layer_tree_frame_sink() const { return _has_field_[12]; }
+ bool did_invalidate_layer_tree_frame_sink() const { return did_invalidate_layer_tree_frame_sink_; }
+ void set_did_invalidate_layer_tree_frame_sink(bool value) { did_invalidate_layer_tree_frame_sink_ = value; _has_field_.set(12); }
+
+ bool has_did_perform_impl_side_invalidaion() const { return _has_field_[13]; }
+ bool did_perform_impl_side_invalidaion() const { return did_perform_impl_side_invalidaion_; }
+ void set_did_perform_impl_side_invalidaion(bool value) { did_perform_impl_side_invalidaion_ = value; _has_field_.set(13); }
+
+ bool has_did_prepare_tiles() const { return _has_field_[14]; }
+ bool did_prepare_tiles() const { return did_prepare_tiles_; }
+ void set_did_prepare_tiles(bool value) { did_prepare_tiles_ = value; _has_field_.set(14); }
+
+ bool has_consecutive_checkerboard_animations() const { return _has_field_[15]; }
+ int32_t consecutive_checkerboard_animations() const { return consecutive_checkerboard_animations_; }
+ void set_consecutive_checkerboard_animations(int32_t value) { consecutive_checkerboard_animations_ = value; _has_field_.set(15); }
+
+ bool has_pending_submit_frames() const { return _has_field_[16]; }
+ int32_t pending_submit_frames() const { return pending_submit_frames_; }
+ void set_pending_submit_frames(int32_t value) { pending_submit_frames_ = value; _has_field_.set(16); }
+
+ bool has_submit_frames_with_current_layer_tree_frame_sink() const { return _has_field_[17]; }
+ int32_t submit_frames_with_current_layer_tree_frame_sink() const { return submit_frames_with_current_layer_tree_frame_sink_; }
+ void set_submit_frames_with_current_layer_tree_frame_sink(int32_t value) { submit_frames_with_current_layer_tree_frame_sink_ = value; _has_field_.set(17); }
+
+ bool has_needs_redraw() const { return _has_field_[18]; }
+ bool needs_redraw() const { return needs_redraw_; }
+ void set_needs_redraw(bool value) { needs_redraw_ = value; _has_field_.set(18); }
+
+ bool has_needs_prepare_tiles() const { return _has_field_[19]; }
+ bool needs_prepare_tiles() const { return needs_prepare_tiles_; }
+ void set_needs_prepare_tiles(bool value) { needs_prepare_tiles_ = value; _has_field_.set(19); }
+
+ bool has_needs_begin_main_frame() const { return _has_field_[20]; }
+ bool needs_begin_main_frame() const { return needs_begin_main_frame_; }
+ void set_needs_begin_main_frame(bool value) { needs_begin_main_frame_ = value; _has_field_.set(20); }
+
+ bool has_needs_one_begin_impl_frame() const { return _has_field_[21]; }
+ bool needs_one_begin_impl_frame() const { return needs_one_begin_impl_frame_; }
+ void set_needs_one_begin_impl_frame(bool value) { needs_one_begin_impl_frame_ = value; _has_field_.set(21); }
+
+ bool has_visible() const { return _has_field_[22]; }
+ bool visible() const { return visible_; }
+ void set_visible(bool value) { visible_ = value; _has_field_.set(22); }
+
+ bool has_begin_frame_source_paused() const { return _has_field_[23]; }
+ bool begin_frame_source_paused() const { return begin_frame_source_paused_; }
+ void set_begin_frame_source_paused(bool value) { begin_frame_source_paused_ = value; _has_field_.set(23); }
+
+ bool has_can_draw() const { return _has_field_[24]; }
+ bool can_draw() const { return can_draw_; }
+ void set_can_draw(bool value) { can_draw_ = value; _has_field_.set(24); }
+
+ bool has_resourceless_draw() const { return _has_field_[25]; }
+ bool resourceless_draw() const { return resourceless_draw_; }
+ void set_resourceless_draw(bool value) { resourceless_draw_ = value; _has_field_.set(25); }
+
+ bool has_has_pending_tree() const { return _has_field_[26]; }
+ bool has_pending_tree() const { return has_pending_tree_; }
+ void set_has_pending_tree(bool value) { has_pending_tree_ = value; _has_field_.set(26); }
+
+ bool has_pending_tree_is_ready_for_activation() const { return _has_field_[27]; }
+ bool pending_tree_is_ready_for_activation() const { return pending_tree_is_ready_for_activation_; }
+ void set_pending_tree_is_ready_for_activation(bool value) { pending_tree_is_ready_for_activation_ = value; _has_field_.set(27); }
+
+ bool has_active_tree_needs_first_draw() const { return _has_field_[28]; }
+ bool active_tree_needs_first_draw() const { return active_tree_needs_first_draw_; }
+ void set_active_tree_needs_first_draw(bool value) { active_tree_needs_first_draw_ = value; _has_field_.set(28); }
+
+ bool has_active_tree_is_ready_to_draw() const { return _has_field_[29]; }
+ bool active_tree_is_ready_to_draw() const { return active_tree_is_ready_to_draw_; }
+ void set_active_tree_is_ready_to_draw(bool value) { active_tree_is_ready_to_draw_ = value; _has_field_.set(29); }
+
+ bool has_did_create_and_initialize_first_layer_tree_frame_sink() const { return _has_field_[30]; }
+ bool did_create_and_initialize_first_layer_tree_frame_sink() const { return did_create_and_initialize_first_layer_tree_frame_sink_; }
+ void set_did_create_and_initialize_first_layer_tree_frame_sink(bool value) { did_create_and_initialize_first_layer_tree_frame_sink_ = value; _has_field_.set(30); }
+
+ bool has_tree_priority() const { return _has_field_[31]; }
+ ChromeCompositorStateMachine_MinorState_TreePriority tree_priority() const { return tree_priority_; }
+ void set_tree_priority(ChromeCompositorStateMachine_MinorState_TreePriority value) { tree_priority_ = value; _has_field_.set(31); }
+
+ bool has_scroll_handler_state() const { return _has_field_[32]; }
+ ChromeCompositorStateMachine_MinorState_ScrollHandlerState scroll_handler_state() const { return scroll_handler_state_; }
+ void set_scroll_handler_state(ChromeCompositorStateMachine_MinorState_ScrollHandlerState value) { scroll_handler_state_ = value; _has_field_.set(32); }
+
+ bool has_critical_begin_main_frame_to_activate_is_fast() const { return _has_field_[33]; }
+ bool critical_begin_main_frame_to_activate_is_fast() const { return critical_begin_main_frame_to_activate_is_fast_; }
+ void set_critical_begin_main_frame_to_activate_is_fast(bool value) { critical_begin_main_frame_to_activate_is_fast_ = value; _has_field_.set(33); }
+
+ bool has_main_thread_missed_last_deadline() const { return _has_field_[34]; }
+ bool main_thread_missed_last_deadline() const { return main_thread_missed_last_deadline_; }
+ void set_main_thread_missed_last_deadline(bool value) { main_thread_missed_last_deadline_ = value; _has_field_.set(34); }
+
+ bool has_video_needs_begin_frames() const { return _has_field_[36]; }
+ bool video_needs_begin_frames() const { return video_needs_begin_frames_; }
+ void set_video_needs_begin_frames(bool value) { video_needs_begin_frames_ = value; _has_field_.set(36); }
+
+ bool has_defer_begin_main_frame() const { return _has_field_[37]; }
+ bool defer_begin_main_frame() const { return defer_begin_main_frame_; }
+ void set_defer_begin_main_frame(bool value) { defer_begin_main_frame_ = value; _has_field_.set(37); }
+
+ bool has_last_commit_had_no_updates() const { return _has_field_[38]; }
+ bool last_commit_had_no_updates() const { return last_commit_had_no_updates_; }
+ void set_last_commit_had_no_updates(bool value) { last_commit_had_no_updates_ = value; _has_field_.set(38); }
+
+ bool has_did_draw_in_last_frame() const { return _has_field_[39]; }
+ bool did_draw_in_last_frame() const { return did_draw_in_last_frame_; }
+ void set_did_draw_in_last_frame(bool value) { did_draw_in_last_frame_ = value; _has_field_.set(39); }
+
+ bool has_did_submit_in_last_frame() const { return _has_field_[40]; }
+ bool did_submit_in_last_frame() const { return did_submit_in_last_frame_; }
+ void set_did_submit_in_last_frame(bool value) { did_submit_in_last_frame_ = value; _has_field_.set(40); }
+
+ bool has_needs_impl_side_invalidation() const { return _has_field_[41]; }
+ bool needs_impl_side_invalidation() const { return needs_impl_side_invalidation_; }
+ void set_needs_impl_side_invalidation(bool value) { needs_impl_side_invalidation_ = value; _has_field_.set(41); }
+
+ bool has_current_pending_tree_is_impl_side() const { return _has_field_[42]; }
+ bool current_pending_tree_is_impl_side() const { return current_pending_tree_is_impl_side_; }
+ void set_current_pending_tree_is_impl_side(bool value) { current_pending_tree_is_impl_side_ = value; _has_field_.set(42); }
+
+ bool has_previous_pending_tree_was_impl_side() const { return _has_field_[43]; }
+ bool previous_pending_tree_was_impl_side() const { return previous_pending_tree_was_impl_side_; }
+ void set_previous_pending_tree_was_impl_side(bool value) { previous_pending_tree_was_impl_side_ = value; _has_field_.set(43); }
+
+ bool has_processing_animation_worklets_for_active_tree() const { return _has_field_[44]; }
+ bool processing_animation_worklets_for_active_tree() const { return processing_animation_worklets_for_active_tree_; }
+ void set_processing_animation_worklets_for_active_tree(bool value) { processing_animation_worklets_for_active_tree_ = value; _has_field_.set(44); }
+
+ bool has_processing_animation_worklets_for_pending_tree() const { return _has_field_[45]; }
+ bool processing_animation_worklets_for_pending_tree() const { return processing_animation_worklets_for_pending_tree_; }
+ void set_processing_animation_worklets_for_pending_tree(bool value) { processing_animation_worklets_for_pending_tree_ = value; _has_field_.set(45); }
+
+ bool has_processing_paint_worklets_for_pending_tree() const { return _has_field_[46]; }
+ bool processing_paint_worklets_for_pending_tree() const { return processing_paint_worklets_for_pending_tree_; }
+ void set_processing_paint_worklets_for_pending_tree(bool value) { processing_paint_worklets_for_pending_tree_ = value; _has_field_.set(46); }
+
+ private:
+ int32_t commit_count_{};
+ int32_t current_frame_number_{};
+ int32_t last_frame_number_submit_performed_{};
+ int32_t last_frame_number_draw_performed_{};
+ int32_t last_frame_number_begin_main_frame_sent_{};
+ bool did_draw_{};
+ bool did_send_begin_main_frame_for_current_frame_{};
+ bool did_notify_begin_main_frame_not_expected_until_{};
+ bool did_notify_begin_main_frame_not_expected_soon_{};
+ bool wants_begin_main_frame_not_expected_{};
+ bool did_commit_during_frame_{};
+ bool did_invalidate_layer_tree_frame_sink_{};
+ bool did_perform_impl_side_invalidaion_{};
+ bool did_prepare_tiles_{};
+ int32_t consecutive_checkerboard_animations_{};
+ int32_t pending_submit_frames_{};
+ int32_t submit_frames_with_current_layer_tree_frame_sink_{};
+ bool needs_redraw_{};
+ bool needs_prepare_tiles_{};
+ bool needs_begin_main_frame_{};
+ bool needs_one_begin_impl_frame_{};
+ bool visible_{};
+ bool begin_frame_source_paused_{};
+ bool can_draw_{};
+ bool resourceless_draw_{};
+ bool has_pending_tree_{};
+ bool pending_tree_is_ready_for_activation_{};
+ bool active_tree_needs_first_draw_{};
+ bool active_tree_is_ready_to_draw_{};
+ bool did_create_and_initialize_first_layer_tree_frame_sink_{};
+ ChromeCompositorStateMachine_MinorState_TreePriority tree_priority_{};
+ ChromeCompositorStateMachine_MinorState_ScrollHandlerState scroll_handler_state_{};
+ bool critical_begin_main_frame_to_activate_is_fast_{};
+ bool main_thread_missed_last_deadline_{};
+ bool video_needs_begin_frames_{};
+ bool defer_begin_main_frame_{};
+ bool last_commit_had_no_updates_{};
+ bool did_draw_in_last_frame_{};
+ bool did_submit_in_last_frame_{};
+ bool needs_impl_side_invalidation_{};
+ bool current_pending_tree_is_impl_side_{};
+ bool previous_pending_tree_was_impl_side_{};
+ bool processing_animation_worklets_for_active_tree_{};
+ bool processing_animation_worklets_for_pending_tree_{};
+ bool processing_paint_worklets_for_pending_tree_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<47> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChromeCompositorStateMachine_MajorState : public ::protozero::CppMessageObj {
+ public:
+ using BeginImplFrameState = ChromeCompositorStateMachine_MajorState_BeginImplFrameState;
+ static constexpr auto BEGIN_IMPL_FRAME_UNSPECIFIED = ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_UNSPECIFIED;
+ static constexpr auto BEGIN_IMPL_FRAME_IDLE = ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_IDLE;
+ static constexpr auto BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME = ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_INSIDE_BEGIN_FRAME;
+ static constexpr auto BEGIN_IMPL_FRAME_INSIDE_DEADLINE = ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_INSIDE_DEADLINE;
+ static constexpr auto BeginImplFrameState_MIN = ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_UNSPECIFIED;
+ static constexpr auto BeginImplFrameState_MAX = ChromeCompositorStateMachine_MajorState_BeginImplFrameState_BEGIN_IMPL_FRAME_INSIDE_DEADLINE;
+ using BeginMainFrameState = ChromeCompositorStateMachine_MajorState_BeginMainFrameState;
+ static constexpr auto BEGIN_MAIN_FRAME_UNSPECIFIED = ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_UNSPECIFIED;
+ static constexpr auto BEGIN_MAIN_FRAME_IDLE = ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_IDLE;
+ static constexpr auto BEGIN_MAIN_FRAME_SENT = ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_SENT;
+ static constexpr auto BEGIN_MAIN_FRAME_READY_TO_COMMIT = ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_READY_TO_COMMIT;
+ static constexpr auto BeginMainFrameState_MIN = ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_UNSPECIFIED;
+ static constexpr auto BeginMainFrameState_MAX = ChromeCompositorStateMachine_MajorState_BeginMainFrameState_BEGIN_MAIN_FRAME_READY_TO_COMMIT;
+ using LayerTreeFrameSinkState = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState;
+ static constexpr auto LAYER_TREE_FRAME_UNSPECIFIED = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_UNSPECIFIED;
+ static constexpr auto LAYER_TREE_FRAME_NONE = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_NONE;
+ static constexpr auto LAYER_TREE_FRAME_ACTIVE = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_ACTIVE;
+ static constexpr auto LAYER_TREE_FRAME_CREATING = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_CREATING;
+ static constexpr auto LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT;
+ static constexpr auto LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION;
+ static constexpr auto LayerTreeFrameSinkState_MIN = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_UNSPECIFIED;
+ static constexpr auto LayerTreeFrameSinkState_MAX = ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState_LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION;
+ using ForcedRedrawOnTimeoutState = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState;
+ static constexpr auto FORCED_REDRAW_UNSPECIFIED = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_UNSPECIFIED;
+ static constexpr auto FORCED_REDRAW_IDLE = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_IDLE;
+ static constexpr auto FORCED_REDRAW_WAITING_FOR_COMMIT = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_WAITING_FOR_COMMIT;
+ static constexpr auto FORCED_REDRAW_WAITING_FOR_ACTIVATION = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_WAITING_FOR_ACTIVATION;
+ static constexpr auto FORCED_REDRAW_WAITING_FOR_DRAW = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_WAITING_FOR_DRAW;
+ static constexpr auto ForcedRedrawOnTimeoutState_MIN = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_UNSPECIFIED;
+ static constexpr auto ForcedRedrawOnTimeoutState_MAX = ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState_FORCED_REDRAW_WAITING_FOR_DRAW;
+ enum FieldNumbers {
+ kNextActionFieldNumber = 1,
+ kBeginImplFrameStateFieldNumber = 2,
+ kBeginMainFrameStateFieldNumber = 3,
+ kLayerTreeFrameSinkStateFieldNumber = 4,
+ kForcedRedrawStateFieldNumber = 5,
+ };
+
+ ChromeCompositorStateMachine_MajorState();
+ ~ChromeCompositorStateMachine_MajorState() override;
+ ChromeCompositorStateMachine_MajorState(ChromeCompositorStateMachine_MajorState&&) noexcept;
+ ChromeCompositorStateMachine_MajorState& operator=(ChromeCompositorStateMachine_MajorState&&);
+ ChromeCompositorStateMachine_MajorState(const ChromeCompositorStateMachine_MajorState&);
+ ChromeCompositorStateMachine_MajorState& operator=(const ChromeCompositorStateMachine_MajorState&);
+ bool operator==(const ChromeCompositorStateMachine_MajorState&) const;
+ bool operator!=(const ChromeCompositorStateMachine_MajorState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_next_action() const { return _has_field_[1]; }
+ ChromeCompositorSchedulerAction next_action() const { return next_action_; }
+ void set_next_action(ChromeCompositorSchedulerAction value) { next_action_ = value; _has_field_.set(1); }
+
+ bool has_begin_impl_frame_state() const { return _has_field_[2]; }
+ ChromeCompositorStateMachine_MajorState_BeginImplFrameState begin_impl_frame_state() const { return begin_impl_frame_state_; }
+ void set_begin_impl_frame_state(ChromeCompositorStateMachine_MajorState_BeginImplFrameState value) { begin_impl_frame_state_ = value; _has_field_.set(2); }
+
+ bool has_begin_main_frame_state() const { return _has_field_[3]; }
+ ChromeCompositorStateMachine_MajorState_BeginMainFrameState begin_main_frame_state() const { return begin_main_frame_state_; }
+ void set_begin_main_frame_state(ChromeCompositorStateMachine_MajorState_BeginMainFrameState value) { begin_main_frame_state_ = value; _has_field_.set(3); }
+
+ bool has_layer_tree_frame_sink_state() const { return _has_field_[4]; }
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState layer_tree_frame_sink_state() const { return layer_tree_frame_sink_state_; }
+ void set_layer_tree_frame_sink_state(ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState value) { layer_tree_frame_sink_state_ = value; _has_field_.set(4); }
+
+ bool has_forced_redraw_state() const { return _has_field_[5]; }
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState forced_redraw_state() const { return forced_redraw_state_; }
+ void set_forced_redraw_state(ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState value) { forced_redraw_state_ = value; _has_field_.set(5); }
+
+ private:
+ ChromeCompositorSchedulerAction next_action_{};
+ ChromeCompositorStateMachine_MajorState_BeginImplFrameState begin_impl_frame_state_{};
+ ChromeCompositorStateMachine_MajorState_BeginMainFrameState begin_main_frame_state_{};
+ ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState layer_tree_frame_sink_state_{};
+ ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState forced_redraw_state_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChromeCompositorSchedulerState : public ::protozero::CppMessageObj {
+ public:
+ using BeginImplFrameDeadlineMode = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode;
+ static constexpr auto DEADLINE_MODE_UNSPECIFIED = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_UNSPECIFIED;
+ static constexpr auto DEADLINE_MODE_NONE = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_NONE;
+ static constexpr auto DEADLINE_MODE_IMMEDIATE = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_IMMEDIATE;
+ static constexpr auto DEADLINE_MODE_REGULAR = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_REGULAR;
+ static constexpr auto DEADLINE_MODE_LATE = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_LATE;
+ static constexpr auto DEADLINE_MODE_BLOCKED = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_BLOCKED;
+ static constexpr auto BeginImplFrameDeadlineMode_MIN = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_UNSPECIFIED;
+ static constexpr auto BeginImplFrameDeadlineMode_MAX = ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode_DEADLINE_MODE_BLOCKED;
+ enum FieldNumbers {
+ kStateMachineFieldNumber = 1,
+ kObservingBeginFrameSourceFieldNumber = 2,
+ kBeginImplFrameDeadlineTaskFieldNumber = 3,
+ kPendingBeginFrameTaskFieldNumber = 4,
+ kSkippedLastFrameMissedExceededDeadlineFieldNumber = 5,
+ kInsideActionFieldNumber = 7,
+ kDeadlineModeFieldNumber = 8,
+ kDeadlineUsFieldNumber = 9,
+ kDeadlineScheduledAtUsFieldNumber = 10,
+ kNowUsFieldNumber = 11,
+ kNowToDeadlineDeltaUsFieldNumber = 12,
+ kNowToDeadlineScheduledAtDeltaUsFieldNumber = 13,
+ kBeginImplFrameArgsFieldNumber = 14,
+ kBeginFrameObserverStateFieldNumber = 15,
+ kBeginFrameSourceStateFieldNumber = 16,
+ kCompositorTimingHistoryFieldNumber = 17,
+ };
+
+ ChromeCompositorSchedulerState();
+ ~ChromeCompositorSchedulerState() override;
+ ChromeCompositorSchedulerState(ChromeCompositorSchedulerState&&) noexcept;
+ ChromeCompositorSchedulerState& operator=(ChromeCompositorSchedulerState&&);
+ ChromeCompositorSchedulerState(const ChromeCompositorSchedulerState&);
+ ChromeCompositorSchedulerState& operator=(const ChromeCompositorSchedulerState&);
+ bool operator==(const ChromeCompositorSchedulerState&) const;
+ bool operator!=(const ChromeCompositorSchedulerState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_state_machine() const { return _has_field_[1]; }
+ const ChromeCompositorStateMachine& state_machine() const { return *state_machine_; }
+ ChromeCompositorStateMachine* mutable_state_machine() { _has_field_.set(1); return state_machine_.get(); }
+
+ bool has_observing_begin_frame_source() const { return _has_field_[2]; }
+ bool observing_begin_frame_source() const { return observing_begin_frame_source_; }
+ void set_observing_begin_frame_source(bool value) { observing_begin_frame_source_ = value; _has_field_.set(2); }
+
+ bool has_begin_impl_frame_deadline_task() const { return _has_field_[3]; }
+ bool begin_impl_frame_deadline_task() const { return begin_impl_frame_deadline_task_; }
+ void set_begin_impl_frame_deadline_task(bool value) { begin_impl_frame_deadline_task_ = value; _has_field_.set(3); }
+
+ bool has_pending_begin_frame_task() const { return _has_field_[4]; }
+ bool pending_begin_frame_task() const { return pending_begin_frame_task_; }
+ void set_pending_begin_frame_task(bool value) { pending_begin_frame_task_ = value; _has_field_.set(4); }
+
+ bool has_skipped_last_frame_missed_exceeded_deadline() const { return _has_field_[5]; }
+ bool skipped_last_frame_missed_exceeded_deadline() const { return skipped_last_frame_missed_exceeded_deadline_; }
+ void set_skipped_last_frame_missed_exceeded_deadline(bool value) { skipped_last_frame_missed_exceeded_deadline_ = value; _has_field_.set(5); }
+
+ bool has_inside_action() const { return _has_field_[7]; }
+ ChromeCompositorSchedulerAction inside_action() const { return inside_action_; }
+ void set_inside_action(ChromeCompositorSchedulerAction value) { inside_action_ = value; _has_field_.set(7); }
+
+ bool has_deadline_mode() const { return _has_field_[8]; }
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode deadline_mode() const { return deadline_mode_; }
+ void set_deadline_mode(ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode value) { deadline_mode_ = value; _has_field_.set(8); }
+
+ bool has_deadline_us() const { return _has_field_[9]; }
+ int64_t deadline_us() const { return deadline_us_; }
+ void set_deadline_us(int64_t value) { deadline_us_ = value; _has_field_.set(9); }
+
+ bool has_deadline_scheduled_at_us() const { return _has_field_[10]; }
+ int64_t deadline_scheduled_at_us() const { return deadline_scheduled_at_us_; }
+ void set_deadline_scheduled_at_us(int64_t value) { deadline_scheduled_at_us_ = value; _has_field_.set(10); }
+
+ bool has_now_us() const { return _has_field_[11]; }
+ int64_t now_us() const { return now_us_; }
+ void set_now_us(int64_t value) { now_us_ = value; _has_field_.set(11); }
+
+ bool has_now_to_deadline_delta_us() const { return _has_field_[12]; }
+ int64_t now_to_deadline_delta_us() const { return now_to_deadline_delta_us_; }
+ void set_now_to_deadline_delta_us(int64_t value) { now_to_deadline_delta_us_ = value; _has_field_.set(12); }
+
+ bool has_now_to_deadline_scheduled_at_delta_us() const { return _has_field_[13]; }
+ int64_t now_to_deadline_scheduled_at_delta_us() const { return now_to_deadline_scheduled_at_delta_us_; }
+ void set_now_to_deadline_scheduled_at_delta_us(int64_t value) { now_to_deadline_scheduled_at_delta_us_ = value; _has_field_.set(13); }
+
+ bool has_begin_impl_frame_args() const { return _has_field_[14]; }
+ const BeginImplFrameArgs& begin_impl_frame_args() const { return *begin_impl_frame_args_; }
+ BeginImplFrameArgs* mutable_begin_impl_frame_args() { _has_field_.set(14); return begin_impl_frame_args_.get(); }
+
+ bool has_begin_frame_observer_state() const { return _has_field_[15]; }
+ const BeginFrameObserverState& begin_frame_observer_state() const { return *begin_frame_observer_state_; }
+ BeginFrameObserverState* mutable_begin_frame_observer_state() { _has_field_.set(15); return begin_frame_observer_state_.get(); }
+
+ bool has_begin_frame_source_state() const { return _has_field_[16]; }
+ const BeginFrameSourceState& begin_frame_source_state() const { return *begin_frame_source_state_; }
+ BeginFrameSourceState* mutable_begin_frame_source_state() { _has_field_.set(16); return begin_frame_source_state_.get(); }
+
+ bool has_compositor_timing_history() const { return _has_field_[17]; }
+ const CompositorTimingHistory& compositor_timing_history() const { return *compositor_timing_history_; }
+ CompositorTimingHistory* mutable_compositor_timing_history() { _has_field_.set(17); return compositor_timing_history_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<ChromeCompositorStateMachine> state_machine_;
+ bool observing_begin_frame_source_{};
+ bool begin_impl_frame_deadline_task_{};
+ bool pending_begin_frame_task_{};
+ bool skipped_last_frame_missed_exceeded_deadline_{};
+ ChromeCompositorSchedulerAction inside_action_{};
+ ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode deadline_mode_{};
+ int64_t deadline_us_{};
+ int64_t deadline_scheduled_at_us_{};
+ int64_t now_us_{};
+ int64_t now_to_deadline_delta_us_{};
+ int64_t now_to_deadline_scheduled_at_delta_us_{};
+ ::protozero::CopyablePtr<BeginImplFrameArgs> begin_impl_frame_args_;
+ ::protozero::CopyablePtr<BeginFrameObserverState> begin_frame_observer_state_;
+ ::protozero::CopyablePtr<BeginFrameSourceState> begin_frame_source_state_;
+ ::protozero::CopyablePtr<CompositorTimingHistory> compositor_timing_history_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<18> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_COMPOSITOR_SCHEDULER_STATE_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_content_settings_event_info.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_CONTENT_SETTINGS_EVENT_INFO_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_CONTENT_SETTINGS_EVENT_INFO_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeContentSettingsEventInfo;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeContentSettingsEventInfo : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNumberOfExceptionsFieldNumber = 1,
+ };
+
+ ChromeContentSettingsEventInfo();
+ ~ChromeContentSettingsEventInfo() override;
+ ChromeContentSettingsEventInfo(ChromeContentSettingsEventInfo&&) noexcept;
+ ChromeContentSettingsEventInfo& operator=(ChromeContentSettingsEventInfo&&);
+ ChromeContentSettingsEventInfo(const ChromeContentSettingsEventInfo&);
+ ChromeContentSettingsEventInfo& operator=(const ChromeContentSettingsEventInfo&);
+ bool operator==(const ChromeContentSettingsEventInfo&) const;
+ bool operator!=(const ChromeContentSettingsEventInfo& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_number_of_exceptions() const { return _has_field_[1]; }
+ uint32_t number_of_exceptions() const { return number_of_exceptions_; }
+ void set_number_of_exceptions(uint32_t value) { number_of_exceptions_ = value; _has_field_.set(1); }
+
+ private:
+ uint32_t number_of_exceptions_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_CONTENT_SETTINGS_EVENT_INFO_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_frame_reporter.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_FRAME_REPORTER_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_FRAME_REPORTER_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeFrameReporter;
+enum ChromeFrameReporter_State : int;
+enum ChromeFrameReporter_FrameDropReason : int;
+enum ChromeFrameReporter_ScrollState : int;
+enum ChromeFrameReporter_FrameType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeFrameReporter_State : int {
+ ChromeFrameReporter_State_STATE_NO_UPDATE_DESIRED = 0,
+ ChromeFrameReporter_State_STATE_PRESENTED_ALL = 1,
+ ChromeFrameReporter_State_STATE_PRESENTED_PARTIAL = 2,
+ ChromeFrameReporter_State_STATE_DROPPED = 3,
+};
+enum ChromeFrameReporter_FrameDropReason : int {
+ ChromeFrameReporter_FrameDropReason_REASON_UNSPECIFIED = 0,
+ ChromeFrameReporter_FrameDropReason_REASON_DISPLAY_COMPOSITOR = 1,
+ ChromeFrameReporter_FrameDropReason_REASON_MAIN_THREAD = 2,
+ ChromeFrameReporter_FrameDropReason_REASON_CLIENT_COMPOSITOR = 3,
+};
+enum ChromeFrameReporter_ScrollState : int {
+ ChromeFrameReporter_ScrollState_SCROLL_NONE = 0,
+ ChromeFrameReporter_ScrollState_SCROLL_MAIN_THREAD = 1,
+ ChromeFrameReporter_ScrollState_SCROLL_COMPOSITOR_THREAD = 2,
+ ChromeFrameReporter_ScrollState_SCROLL_UNKNOWN = 3,
+};
+enum ChromeFrameReporter_FrameType : int {
+ ChromeFrameReporter_FrameType_FORKED = 0,
+ ChromeFrameReporter_FrameType_BACKFILL = 1,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeFrameReporter : public ::protozero::CppMessageObj {
+ public:
+ using State = ChromeFrameReporter_State;
+ static constexpr auto STATE_NO_UPDATE_DESIRED = ChromeFrameReporter_State_STATE_NO_UPDATE_DESIRED;
+ static constexpr auto STATE_PRESENTED_ALL = ChromeFrameReporter_State_STATE_PRESENTED_ALL;
+ static constexpr auto STATE_PRESENTED_PARTIAL = ChromeFrameReporter_State_STATE_PRESENTED_PARTIAL;
+ static constexpr auto STATE_DROPPED = ChromeFrameReporter_State_STATE_DROPPED;
+ static constexpr auto State_MIN = ChromeFrameReporter_State_STATE_NO_UPDATE_DESIRED;
+ static constexpr auto State_MAX = ChromeFrameReporter_State_STATE_DROPPED;
+ using FrameDropReason = ChromeFrameReporter_FrameDropReason;
+ static constexpr auto REASON_UNSPECIFIED = ChromeFrameReporter_FrameDropReason_REASON_UNSPECIFIED;
+ static constexpr auto REASON_DISPLAY_COMPOSITOR = ChromeFrameReporter_FrameDropReason_REASON_DISPLAY_COMPOSITOR;
+ static constexpr auto REASON_MAIN_THREAD = ChromeFrameReporter_FrameDropReason_REASON_MAIN_THREAD;
+ static constexpr auto REASON_CLIENT_COMPOSITOR = ChromeFrameReporter_FrameDropReason_REASON_CLIENT_COMPOSITOR;
+ static constexpr auto FrameDropReason_MIN = ChromeFrameReporter_FrameDropReason_REASON_UNSPECIFIED;
+ static constexpr auto FrameDropReason_MAX = ChromeFrameReporter_FrameDropReason_REASON_CLIENT_COMPOSITOR;
+ using ScrollState = ChromeFrameReporter_ScrollState;
+ static constexpr auto SCROLL_NONE = ChromeFrameReporter_ScrollState_SCROLL_NONE;
+ static constexpr auto SCROLL_MAIN_THREAD = ChromeFrameReporter_ScrollState_SCROLL_MAIN_THREAD;
+ static constexpr auto SCROLL_COMPOSITOR_THREAD = ChromeFrameReporter_ScrollState_SCROLL_COMPOSITOR_THREAD;
+ static constexpr auto SCROLL_UNKNOWN = ChromeFrameReporter_ScrollState_SCROLL_UNKNOWN;
+ static constexpr auto ScrollState_MIN = ChromeFrameReporter_ScrollState_SCROLL_NONE;
+ static constexpr auto ScrollState_MAX = ChromeFrameReporter_ScrollState_SCROLL_UNKNOWN;
+ using FrameType = ChromeFrameReporter_FrameType;
+ static constexpr auto FORKED = ChromeFrameReporter_FrameType_FORKED;
+ static constexpr auto BACKFILL = ChromeFrameReporter_FrameType_BACKFILL;
+ static constexpr auto FrameType_MIN = ChromeFrameReporter_FrameType_FORKED;
+ static constexpr auto FrameType_MAX = ChromeFrameReporter_FrameType_BACKFILL;
+ enum FieldNumbers {
+ kStateFieldNumber = 1,
+ kReasonFieldNumber = 2,
+ kFrameSourceFieldNumber = 3,
+ kFrameSequenceFieldNumber = 4,
+ kAffectsSmoothnessFieldNumber = 5,
+ kScrollStateFieldNumber = 6,
+ kHasMainAnimationFieldNumber = 7,
+ kHasCompositorAnimationFieldNumber = 8,
+ kHasSmoothInputMainFieldNumber = 9,
+ kHasMissingContentFieldNumber = 10,
+ kLayerTreeHostIdFieldNumber = 11,
+ kHasHighLatencyFieldNumber = 12,
+ kFrameTypeFieldNumber = 13,
+ kHighLatencyContributionStageFieldNumber = 14,
+ };
+
+ ChromeFrameReporter();
+ ~ChromeFrameReporter() override;
+ ChromeFrameReporter(ChromeFrameReporter&&) noexcept;
+ ChromeFrameReporter& operator=(ChromeFrameReporter&&);
+ ChromeFrameReporter(const ChromeFrameReporter&);
+ ChromeFrameReporter& operator=(const ChromeFrameReporter&);
+ bool operator==(const ChromeFrameReporter&) const;
+ bool operator!=(const ChromeFrameReporter& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_state() const { return _has_field_[1]; }
+ ChromeFrameReporter_State state() const { return state_; }
+ void set_state(ChromeFrameReporter_State value) { state_ = value; _has_field_.set(1); }
+
+ bool has_reason() const { return _has_field_[2]; }
+ ChromeFrameReporter_FrameDropReason reason() const { return reason_; }
+ void set_reason(ChromeFrameReporter_FrameDropReason value) { reason_ = value; _has_field_.set(2); }
+
+ bool has_frame_source() const { return _has_field_[3]; }
+ uint64_t frame_source() const { return frame_source_; }
+ void set_frame_source(uint64_t value) { frame_source_ = value; _has_field_.set(3); }
+
+ bool has_frame_sequence() const { return _has_field_[4]; }
+ uint64_t frame_sequence() const { return frame_sequence_; }
+ void set_frame_sequence(uint64_t value) { frame_sequence_ = value; _has_field_.set(4); }
+
+ bool has_affects_smoothness() const { return _has_field_[5]; }
+ bool affects_smoothness() const { return affects_smoothness_; }
+ void set_affects_smoothness(bool value) { affects_smoothness_ = value; _has_field_.set(5); }
+
+ bool has_scroll_state() const { return _has_field_[6]; }
+ ChromeFrameReporter_ScrollState scroll_state() const { return scroll_state_; }
+ void set_scroll_state(ChromeFrameReporter_ScrollState value) { scroll_state_ = value; _has_field_.set(6); }
+
+ bool has_has_main_animation() const { return _has_field_[7]; }
+ bool has_main_animation() const { return has_main_animation_; }
+ void set_has_main_animation(bool value) { has_main_animation_ = value; _has_field_.set(7); }
+
+ bool has_has_compositor_animation() const { return _has_field_[8]; }
+ bool has_compositor_animation() const { return has_compositor_animation_; }
+ void set_has_compositor_animation(bool value) { has_compositor_animation_ = value; _has_field_.set(8); }
+
+ bool has_has_smooth_input_main() const { return _has_field_[9]; }
+ bool has_smooth_input_main() const { return has_smooth_input_main_; }
+ void set_has_smooth_input_main(bool value) { has_smooth_input_main_ = value; _has_field_.set(9); }
+
+ bool has_has_missing_content() const { return _has_field_[10]; }
+ bool has_missing_content() const { return has_missing_content_; }
+ void set_has_missing_content(bool value) { has_missing_content_ = value; _has_field_.set(10); }
+
+ bool has_layer_tree_host_id() const { return _has_field_[11]; }
+ uint64_t layer_tree_host_id() const { return layer_tree_host_id_; }
+ void set_layer_tree_host_id(uint64_t value) { layer_tree_host_id_ = value; _has_field_.set(11); }
+
+ bool has_has_high_latency() const { return _has_field_[12]; }
+ bool has_high_latency() const { return has_high_latency_; }
+ void set_has_high_latency(bool value) { has_high_latency_ = value; _has_field_.set(12); }
+
+ bool has_frame_type() const { return _has_field_[13]; }
+ ChromeFrameReporter_FrameType frame_type() const { return frame_type_; }
+ void set_frame_type(ChromeFrameReporter_FrameType value) { frame_type_ = value; _has_field_.set(13); }
+
+ const std::vector<std::string>& high_latency_contribution_stage() const { return high_latency_contribution_stage_; }
+ std::vector<std::string>* mutable_high_latency_contribution_stage() { return &high_latency_contribution_stage_; }
+ int high_latency_contribution_stage_size() const { return static_cast<int>(high_latency_contribution_stage_.size()); }
+ void clear_high_latency_contribution_stage() { high_latency_contribution_stage_.clear(); }
+ void add_high_latency_contribution_stage(std::string value) { high_latency_contribution_stage_.emplace_back(value); }
+ std::string* add_high_latency_contribution_stage() { high_latency_contribution_stage_.emplace_back(); return &high_latency_contribution_stage_.back(); }
+
+ private:
+ ChromeFrameReporter_State state_{};
+ ChromeFrameReporter_FrameDropReason reason_{};
+ uint64_t frame_source_{};
+ uint64_t frame_sequence_{};
+ bool affects_smoothness_{};
+ ChromeFrameReporter_ScrollState scroll_state_{};
+ bool has_main_animation_{};
+ bool has_compositor_animation_{};
+ bool has_smooth_input_main_{};
+ bool has_missing_content_{};
+ uint64_t layer_tree_host_id_{};
+ bool has_high_latency_{};
+ ChromeFrameReporter_FrameType frame_type_{};
+ std::vector<std::string> high_latency_contribution_stage_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<15> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_FRAME_REPORTER_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_histogram_sample.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_HISTOGRAM_SAMPLE_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_HISTOGRAM_SAMPLE_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeHistogramSample;
+class HistogramName;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeHistogramSample : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameHashFieldNumber = 1,
+ kNameFieldNumber = 2,
+ kSampleFieldNumber = 3,
+ kNameIidFieldNumber = 4,
+ };
+
+ ChromeHistogramSample();
+ ~ChromeHistogramSample() override;
+ ChromeHistogramSample(ChromeHistogramSample&&) noexcept;
+ ChromeHistogramSample& operator=(ChromeHistogramSample&&);
+ ChromeHistogramSample(const ChromeHistogramSample&);
+ ChromeHistogramSample& operator=(const ChromeHistogramSample&);
+ bool operator==(const ChromeHistogramSample&) const;
+ bool operator!=(const ChromeHistogramSample& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name_hash() const { return _has_field_[1]; }
+ uint64_t name_hash() const { return name_hash_; }
+ void set_name_hash(uint64_t value) { name_hash_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ bool has_sample() const { return _has_field_[3]; }
+ int64_t sample() const { return sample_; }
+ void set_sample(int64_t value) { sample_ = value; _has_field_.set(3); }
+
+ bool has_name_iid() const { return _has_field_[4]; }
+ uint64_t name_iid() const { return name_iid_; }
+ void set_name_iid(uint64_t value) { name_iid_ = value; _has_field_.set(4); }
+
+ private:
+ uint64_t name_hash_{};
+ std::string name_{};
+ int64_t sample_{};
+ uint64_t name_iid_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT HistogramName : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+
+ HistogramName();
+ ~HistogramName() override;
+ HistogramName(HistogramName&&) noexcept;
+ HistogramName& operator=(HistogramName&&);
+ HistogramName(const HistogramName&);
+ HistogramName& operator=(const HistogramName&);
+ bool operator==(const HistogramName&) const;
+ bool operator!=(const HistogramName& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t iid_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_HISTOGRAM_SAMPLE_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_keyed_service.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_KEYED_SERVICE_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_KEYED_SERVICE_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeKeyedService;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeKeyedService : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNameFieldNumber = 1,
+ };
+
+ ChromeKeyedService();
+ ~ChromeKeyedService() override;
+ ChromeKeyedService(ChromeKeyedService&&) noexcept;
+ ChromeKeyedService& operator=(ChromeKeyedService&&);
+ ChromeKeyedService(const ChromeKeyedService&);
+ ChromeKeyedService& operator=(const ChromeKeyedService&);
+ bool operator==(const ChromeKeyedService&) const;
+ bool operator!=(const ChromeKeyedService& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name() const { return _has_field_[1]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(1); }
+
+ private:
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_KEYED_SERVICE_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_latency_info.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LATENCY_INFO_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LATENCY_INFO_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeLatencyInfo;
+class ChromeLatencyInfo_ComponentInfo;
+enum ChromeLatencyInfo_Step : int;
+enum ChromeLatencyInfo_LatencyComponentType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeLatencyInfo_Step : int {
+ ChromeLatencyInfo_Step_STEP_UNSPECIFIED = 0,
+ ChromeLatencyInfo_Step_STEP_SEND_INPUT_EVENT_UI = 3,
+ ChromeLatencyInfo_Step_STEP_HANDLE_INPUT_EVENT_IMPL = 5,
+ ChromeLatencyInfo_Step_STEP_DID_HANDLE_INPUT_AND_OVERSCROLL = 8,
+ ChromeLatencyInfo_Step_STEP_HANDLE_INPUT_EVENT_MAIN = 4,
+ ChromeLatencyInfo_Step_STEP_MAIN_THREAD_SCROLL_UPDATE = 2,
+ ChromeLatencyInfo_Step_STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT = 1,
+ ChromeLatencyInfo_Step_STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL = 9,
+ ChromeLatencyInfo_Step_STEP_HANDLED_INPUT_EVENT_IMPL = 10,
+ ChromeLatencyInfo_Step_STEP_SWAP_BUFFERS = 6,
+ ChromeLatencyInfo_Step_STEP_DRAW_AND_SWAP = 7,
+ ChromeLatencyInfo_Step_STEP_FINISHED_SWAP_BUFFERS = 11,
+};
+enum ChromeLatencyInfo_LatencyComponentType : int {
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_UNSPECIFIED = 0,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH = 1,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL = 2,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL = 3,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL = 4,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_UI = 5,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN = 6,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN = 7,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL = 8,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT = 9,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH = 10,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP = 11,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME = 12,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER = 13,
+ ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP = 14,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeLatencyInfo : public ::protozero::CppMessageObj {
+ public:
+ using ComponentInfo = ChromeLatencyInfo_ComponentInfo;
+ using Step = ChromeLatencyInfo_Step;
+ static constexpr auto STEP_UNSPECIFIED = ChromeLatencyInfo_Step_STEP_UNSPECIFIED;
+ static constexpr auto STEP_SEND_INPUT_EVENT_UI = ChromeLatencyInfo_Step_STEP_SEND_INPUT_EVENT_UI;
+ static constexpr auto STEP_HANDLE_INPUT_EVENT_IMPL = ChromeLatencyInfo_Step_STEP_HANDLE_INPUT_EVENT_IMPL;
+ static constexpr auto STEP_DID_HANDLE_INPUT_AND_OVERSCROLL = ChromeLatencyInfo_Step_STEP_DID_HANDLE_INPUT_AND_OVERSCROLL;
+ static constexpr auto STEP_HANDLE_INPUT_EVENT_MAIN = ChromeLatencyInfo_Step_STEP_HANDLE_INPUT_EVENT_MAIN;
+ static constexpr auto STEP_MAIN_THREAD_SCROLL_UPDATE = ChromeLatencyInfo_Step_STEP_MAIN_THREAD_SCROLL_UPDATE;
+ static constexpr auto STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT = ChromeLatencyInfo_Step_STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT;
+ static constexpr auto STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL = ChromeLatencyInfo_Step_STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL;
+ static constexpr auto STEP_HANDLED_INPUT_EVENT_IMPL = ChromeLatencyInfo_Step_STEP_HANDLED_INPUT_EVENT_IMPL;
+ static constexpr auto STEP_SWAP_BUFFERS = ChromeLatencyInfo_Step_STEP_SWAP_BUFFERS;
+ static constexpr auto STEP_DRAW_AND_SWAP = ChromeLatencyInfo_Step_STEP_DRAW_AND_SWAP;
+ static constexpr auto STEP_FINISHED_SWAP_BUFFERS = ChromeLatencyInfo_Step_STEP_FINISHED_SWAP_BUFFERS;
+ static constexpr auto Step_MIN = ChromeLatencyInfo_Step_STEP_UNSPECIFIED;
+ static constexpr auto Step_MAX = ChromeLatencyInfo_Step_STEP_FINISHED_SWAP_BUFFERS;
+ using LatencyComponentType = ChromeLatencyInfo_LatencyComponentType;
+ static constexpr auto COMPONENT_UNSPECIFIED = ChromeLatencyInfo_LatencyComponentType_COMPONENT_UNSPECIFIED;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_ORIGINAL;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_UI = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_UI;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_ACK_RWH;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP;
+ static constexpr auto COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME = ChromeLatencyInfo_LatencyComponentType_COMPONENT_DISPLAY_COMPOSITOR_RECEIVED_FRAME;
+ static constexpr auto COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER;
+ static constexpr auto COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP;
+ static constexpr auto LatencyComponentType_MIN = ChromeLatencyInfo_LatencyComponentType_COMPONENT_UNSPECIFIED;
+ static constexpr auto LatencyComponentType_MAX = ChromeLatencyInfo_LatencyComponentType_COMPONENT_INPUT_EVENT_LATENCY_FRAME_SWAP;
+ enum FieldNumbers {
+ kTraceIdFieldNumber = 1,
+ kStepFieldNumber = 2,
+ kFrameTreeNodeIdFieldNumber = 3,
+ kComponentInfoFieldNumber = 4,
+ kIsCoalescedFieldNumber = 5,
+ kGestureScrollIdFieldNumber = 6,
+ kTouchIdFieldNumber = 7,
+ };
+
+ ChromeLatencyInfo();
+ ~ChromeLatencyInfo() override;
+ ChromeLatencyInfo(ChromeLatencyInfo&&) noexcept;
+ ChromeLatencyInfo& operator=(ChromeLatencyInfo&&);
+ ChromeLatencyInfo(const ChromeLatencyInfo&);
+ ChromeLatencyInfo& operator=(const ChromeLatencyInfo&);
+ bool operator==(const ChromeLatencyInfo&) const;
+ bool operator!=(const ChromeLatencyInfo& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_id() const { return _has_field_[1]; }
+ int64_t trace_id() const { return trace_id_; }
+ void set_trace_id(int64_t value) { trace_id_ = value; _has_field_.set(1); }
+
+ bool has_step() const { return _has_field_[2]; }
+ ChromeLatencyInfo_Step step() const { return step_; }
+ void set_step(ChromeLatencyInfo_Step value) { step_ = value; _has_field_.set(2); }
+
+ bool has_frame_tree_node_id() const { return _has_field_[3]; }
+ int32_t frame_tree_node_id() const { return frame_tree_node_id_; }
+ void set_frame_tree_node_id(int32_t value) { frame_tree_node_id_ = value; _has_field_.set(3); }
+
+ const std::vector<ChromeLatencyInfo_ComponentInfo>& component_info() const { return component_info_; }
+ std::vector<ChromeLatencyInfo_ComponentInfo>* mutable_component_info() { return &component_info_; }
+ int component_info_size() const;
+ void clear_component_info();
+ ChromeLatencyInfo_ComponentInfo* add_component_info();
+
+ bool has_is_coalesced() const { return _has_field_[5]; }
+ bool is_coalesced() const { return is_coalesced_; }
+ void set_is_coalesced(bool value) { is_coalesced_ = value; _has_field_.set(5); }
+
+ bool has_gesture_scroll_id() const { return _has_field_[6]; }
+ int64_t gesture_scroll_id() const { return gesture_scroll_id_; }
+ void set_gesture_scroll_id(int64_t value) { gesture_scroll_id_ = value; _has_field_.set(6); }
+
+ bool has_touch_id() const { return _has_field_[7]; }
+ int64_t touch_id() const { return touch_id_; }
+ void set_touch_id(int64_t value) { touch_id_ = value; _has_field_.set(7); }
+
+ private:
+ int64_t trace_id_{};
+ ChromeLatencyInfo_Step step_{};
+ int32_t frame_tree_node_id_{};
+ std::vector<ChromeLatencyInfo_ComponentInfo> component_info_;
+ bool is_coalesced_{};
+ int64_t gesture_scroll_id_{};
+ int64_t touch_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChromeLatencyInfo_ComponentInfo : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kComponentTypeFieldNumber = 1,
+ kTimeUsFieldNumber = 2,
+ };
+
+ ChromeLatencyInfo_ComponentInfo();
+ ~ChromeLatencyInfo_ComponentInfo() override;
+ ChromeLatencyInfo_ComponentInfo(ChromeLatencyInfo_ComponentInfo&&) noexcept;
+ ChromeLatencyInfo_ComponentInfo& operator=(ChromeLatencyInfo_ComponentInfo&&);
+ ChromeLatencyInfo_ComponentInfo(const ChromeLatencyInfo_ComponentInfo&);
+ ChromeLatencyInfo_ComponentInfo& operator=(const ChromeLatencyInfo_ComponentInfo&);
+ bool operator==(const ChromeLatencyInfo_ComponentInfo&) const;
+ bool operator!=(const ChromeLatencyInfo_ComponentInfo& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_component_type() const { return _has_field_[1]; }
+ ChromeLatencyInfo_LatencyComponentType component_type() const { return component_type_; }
+ void set_component_type(ChromeLatencyInfo_LatencyComponentType value) { component_type_ = value; _has_field_.set(1); }
+
+ bool has_time_us() const { return _has_field_[2]; }
+ uint64_t time_us() const { return time_us_; }
+ void set_time_us(uint64_t value) { time_us_ = value; _has_field_.set(2); }
+
+ private:
+ ChromeLatencyInfo_LatencyComponentType component_type_{};
+ uint64_t time_us_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LATENCY_INFO_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeLegacyIpc;
+enum ChromeLegacyIpc_MessageClass : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeLegacyIpc_MessageClass : int {
+ ChromeLegacyIpc_MessageClass_CLASS_UNSPECIFIED = 0,
+ ChromeLegacyIpc_MessageClass_CLASS_AUTOMATION = 1,
+ ChromeLegacyIpc_MessageClass_CLASS_FRAME = 2,
+ ChromeLegacyIpc_MessageClass_CLASS_PAGE = 3,
+ ChromeLegacyIpc_MessageClass_CLASS_VIEW = 4,
+ ChromeLegacyIpc_MessageClass_CLASS_WIDGET = 5,
+ ChromeLegacyIpc_MessageClass_CLASS_INPUT = 6,
+ ChromeLegacyIpc_MessageClass_CLASS_TEST = 7,
+ ChromeLegacyIpc_MessageClass_CLASS_WORKER = 8,
+ ChromeLegacyIpc_MessageClass_CLASS_NACL = 9,
+ ChromeLegacyIpc_MessageClass_CLASS_GPU_CHANNEL = 10,
+ ChromeLegacyIpc_MessageClass_CLASS_MEDIA = 11,
+ ChromeLegacyIpc_MessageClass_CLASS_PPAPI = 12,
+ ChromeLegacyIpc_MessageClass_CLASS_CHROME = 13,
+ ChromeLegacyIpc_MessageClass_CLASS_DRAG = 14,
+ ChromeLegacyIpc_MessageClass_CLASS_PRINT = 15,
+ ChromeLegacyIpc_MessageClass_CLASS_EXTENSION = 16,
+ ChromeLegacyIpc_MessageClass_CLASS_TEXT_INPUT_CLIENT = 17,
+ ChromeLegacyIpc_MessageClass_CLASS_BLINK_TEST = 18,
+ ChromeLegacyIpc_MessageClass_CLASS_ACCESSIBILITY = 19,
+ ChromeLegacyIpc_MessageClass_CLASS_PRERENDER = 20,
+ ChromeLegacyIpc_MessageClass_CLASS_CHROMOTING = 21,
+ ChromeLegacyIpc_MessageClass_CLASS_BROWSER_PLUGIN = 22,
+ ChromeLegacyIpc_MessageClass_CLASS_ANDROID_WEB_VIEW = 23,
+ ChromeLegacyIpc_MessageClass_CLASS_NACL_HOST = 24,
+ ChromeLegacyIpc_MessageClass_CLASS_ENCRYPTED_MEDIA = 25,
+ ChromeLegacyIpc_MessageClass_CLASS_CAST = 26,
+ ChromeLegacyIpc_MessageClass_CLASS_GIN_JAVA_BRIDGE = 27,
+ ChromeLegacyIpc_MessageClass_CLASS_CHROME_UTILITY_PRINTING = 28,
+ ChromeLegacyIpc_MessageClass_CLASS_OZONE_GPU = 29,
+ ChromeLegacyIpc_MessageClass_CLASS_WEB_TEST = 30,
+ ChromeLegacyIpc_MessageClass_CLASS_NETWORK_HINTS = 31,
+ ChromeLegacyIpc_MessageClass_CLASS_EXTENSIONS_GUEST_VIEW = 32,
+ ChromeLegacyIpc_MessageClass_CLASS_GUEST_VIEW = 33,
+ ChromeLegacyIpc_MessageClass_CLASS_MEDIA_PLAYER_DELEGATE = 34,
+ ChromeLegacyIpc_MessageClass_CLASS_EXTENSION_WORKER = 35,
+ ChromeLegacyIpc_MessageClass_CLASS_SUBRESOURCE_FILTER = 36,
+ ChromeLegacyIpc_MessageClass_CLASS_UNFREEZABLE_FRAME = 37,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeLegacyIpc : public ::protozero::CppMessageObj {
+ public:
+ using MessageClass = ChromeLegacyIpc_MessageClass;
+ static constexpr auto CLASS_UNSPECIFIED = ChromeLegacyIpc_MessageClass_CLASS_UNSPECIFIED;
+ static constexpr auto CLASS_AUTOMATION = ChromeLegacyIpc_MessageClass_CLASS_AUTOMATION;
+ static constexpr auto CLASS_FRAME = ChromeLegacyIpc_MessageClass_CLASS_FRAME;
+ static constexpr auto CLASS_PAGE = ChromeLegacyIpc_MessageClass_CLASS_PAGE;
+ static constexpr auto CLASS_VIEW = ChromeLegacyIpc_MessageClass_CLASS_VIEW;
+ static constexpr auto CLASS_WIDGET = ChromeLegacyIpc_MessageClass_CLASS_WIDGET;
+ static constexpr auto CLASS_INPUT = ChromeLegacyIpc_MessageClass_CLASS_INPUT;
+ static constexpr auto CLASS_TEST = ChromeLegacyIpc_MessageClass_CLASS_TEST;
+ static constexpr auto CLASS_WORKER = ChromeLegacyIpc_MessageClass_CLASS_WORKER;
+ static constexpr auto CLASS_NACL = ChromeLegacyIpc_MessageClass_CLASS_NACL;
+ static constexpr auto CLASS_GPU_CHANNEL = ChromeLegacyIpc_MessageClass_CLASS_GPU_CHANNEL;
+ static constexpr auto CLASS_MEDIA = ChromeLegacyIpc_MessageClass_CLASS_MEDIA;
+ static constexpr auto CLASS_PPAPI = ChromeLegacyIpc_MessageClass_CLASS_PPAPI;
+ static constexpr auto CLASS_CHROME = ChromeLegacyIpc_MessageClass_CLASS_CHROME;
+ static constexpr auto CLASS_DRAG = ChromeLegacyIpc_MessageClass_CLASS_DRAG;
+ static constexpr auto CLASS_PRINT = ChromeLegacyIpc_MessageClass_CLASS_PRINT;
+ static constexpr auto CLASS_EXTENSION = ChromeLegacyIpc_MessageClass_CLASS_EXTENSION;
+ static constexpr auto CLASS_TEXT_INPUT_CLIENT = ChromeLegacyIpc_MessageClass_CLASS_TEXT_INPUT_CLIENT;
+ static constexpr auto CLASS_BLINK_TEST = ChromeLegacyIpc_MessageClass_CLASS_BLINK_TEST;
+ static constexpr auto CLASS_ACCESSIBILITY = ChromeLegacyIpc_MessageClass_CLASS_ACCESSIBILITY;
+ static constexpr auto CLASS_PRERENDER = ChromeLegacyIpc_MessageClass_CLASS_PRERENDER;
+ static constexpr auto CLASS_CHROMOTING = ChromeLegacyIpc_MessageClass_CLASS_CHROMOTING;
+ static constexpr auto CLASS_BROWSER_PLUGIN = ChromeLegacyIpc_MessageClass_CLASS_BROWSER_PLUGIN;
+ static constexpr auto CLASS_ANDROID_WEB_VIEW = ChromeLegacyIpc_MessageClass_CLASS_ANDROID_WEB_VIEW;
+ static constexpr auto CLASS_NACL_HOST = ChromeLegacyIpc_MessageClass_CLASS_NACL_HOST;
+ static constexpr auto CLASS_ENCRYPTED_MEDIA = ChromeLegacyIpc_MessageClass_CLASS_ENCRYPTED_MEDIA;
+ static constexpr auto CLASS_CAST = ChromeLegacyIpc_MessageClass_CLASS_CAST;
+ static constexpr auto CLASS_GIN_JAVA_BRIDGE = ChromeLegacyIpc_MessageClass_CLASS_GIN_JAVA_BRIDGE;
+ static constexpr auto CLASS_CHROME_UTILITY_PRINTING = ChromeLegacyIpc_MessageClass_CLASS_CHROME_UTILITY_PRINTING;
+ static constexpr auto CLASS_OZONE_GPU = ChromeLegacyIpc_MessageClass_CLASS_OZONE_GPU;
+ static constexpr auto CLASS_WEB_TEST = ChromeLegacyIpc_MessageClass_CLASS_WEB_TEST;
+ static constexpr auto CLASS_NETWORK_HINTS = ChromeLegacyIpc_MessageClass_CLASS_NETWORK_HINTS;
+ static constexpr auto CLASS_EXTENSIONS_GUEST_VIEW = ChromeLegacyIpc_MessageClass_CLASS_EXTENSIONS_GUEST_VIEW;
+ static constexpr auto CLASS_GUEST_VIEW = ChromeLegacyIpc_MessageClass_CLASS_GUEST_VIEW;
+ static constexpr auto CLASS_MEDIA_PLAYER_DELEGATE = ChromeLegacyIpc_MessageClass_CLASS_MEDIA_PLAYER_DELEGATE;
+ static constexpr auto CLASS_EXTENSION_WORKER = ChromeLegacyIpc_MessageClass_CLASS_EXTENSION_WORKER;
+ static constexpr auto CLASS_SUBRESOURCE_FILTER = ChromeLegacyIpc_MessageClass_CLASS_SUBRESOURCE_FILTER;
+ static constexpr auto CLASS_UNFREEZABLE_FRAME = ChromeLegacyIpc_MessageClass_CLASS_UNFREEZABLE_FRAME;
+ static constexpr auto MessageClass_MIN = ChromeLegacyIpc_MessageClass_CLASS_UNSPECIFIED;
+ static constexpr auto MessageClass_MAX = ChromeLegacyIpc_MessageClass_CLASS_UNFREEZABLE_FRAME;
+ enum FieldNumbers {
+ kMessageClassFieldNumber = 1,
+ kMessageLineFieldNumber = 2,
+ };
+
+ ChromeLegacyIpc();
+ ~ChromeLegacyIpc() override;
+ ChromeLegacyIpc(ChromeLegacyIpc&&) noexcept;
+ ChromeLegacyIpc& operator=(ChromeLegacyIpc&&);
+ ChromeLegacyIpc(const ChromeLegacyIpc&);
+ ChromeLegacyIpc& operator=(const ChromeLegacyIpc&);
+ bool operator==(const ChromeLegacyIpc&) const;
+ bool operator!=(const ChromeLegacyIpc& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_message_class() const { return _has_field_[1]; }
+ ChromeLegacyIpc_MessageClass message_class() const { return message_class_; }
+ void set_message_class(ChromeLegacyIpc_MessageClass value) { message_class_ = value; _has_field_.set(1); }
+
+ bool has_message_line() const { return _has_field_[2]; }
+ uint32_t message_line() const { return message_line_; }
+ void set_message_line(uint32_t value) { message_line_ = value; _has_field_.set(2); }
+
+ private:
+ ChromeLegacyIpc_MessageClass message_class_{};
+ uint32_t message_line_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_message_pump.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MESSAGE_PUMP_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MESSAGE_PUMP_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeMessagePump;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeMessagePump : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSentMessagesInQueueFieldNumber = 1,
+ kIoHandlerLocationIidFieldNumber = 2,
+ };
+
+ ChromeMessagePump();
+ ~ChromeMessagePump() override;
+ ChromeMessagePump(ChromeMessagePump&&) noexcept;
+ ChromeMessagePump& operator=(ChromeMessagePump&&);
+ ChromeMessagePump(const ChromeMessagePump&);
+ ChromeMessagePump& operator=(const ChromeMessagePump&);
+ bool operator==(const ChromeMessagePump&) const;
+ bool operator!=(const ChromeMessagePump& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_sent_messages_in_queue() const { return _has_field_[1]; }
+ bool sent_messages_in_queue() const { return sent_messages_in_queue_; }
+ void set_sent_messages_in_queue(bool value) { sent_messages_in_queue_ = value; _has_field_.set(1); }
+
+ bool has_io_handler_location_iid() const { return _has_field_[2]; }
+ uint64_t io_handler_location_iid() const { return io_handler_location_iid_; }
+ void set_io_handler_location_iid(uint64_t value) { io_handler_location_iid_ = value; _has_field_.set(2); }
+
+ private:
+ bool sent_messages_in_queue_{};
+ uint64_t io_handler_location_iid_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MESSAGE_PUMP_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_mojo_event_info.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeMojoEventInfo;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeMojoEventInfo : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kWatcherNotifyInterfaceTagFieldNumber = 1,
+ kIpcHashFieldNumber = 2,
+ kMojoInterfaceTagFieldNumber = 3,
+ kMojoInterfaceMethodIidFieldNumber = 4,
+ kIsReplyFieldNumber = 5,
+ kPayloadSizeFieldNumber = 6,
+ kDataNumBytesFieldNumber = 7,
+ };
+
+ ChromeMojoEventInfo();
+ ~ChromeMojoEventInfo() override;
+ ChromeMojoEventInfo(ChromeMojoEventInfo&&) noexcept;
+ ChromeMojoEventInfo& operator=(ChromeMojoEventInfo&&);
+ ChromeMojoEventInfo(const ChromeMojoEventInfo&);
+ ChromeMojoEventInfo& operator=(const ChromeMojoEventInfo&);
+ bool operator==(const ChromeMojoEventInfo&) const;
+ bool operator!=(const ChromeMojoEventInfo& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_watcher_notify_interface_tag() const { return _has_field_[1]; }
+ const std::string& watcher_notify_interface_tag() const { return watcher_notify_interface_tag_; }
+ void set_watcher_notify_interface_tag(const std::string& value) { watcher_notify_interface_tag_ = value; _has_field_.set(1); }
+
+ bool has_ipc_hash() const { return _has_field_[2]; }
+ uint32_t ipc_hash() const { return ipc_hash_; }
+ void set_ipc_hash(uint32_t value) { ipc_hash_ = value; _has_field_.set(2); }
+
+ bool has_mojo_interface_tag() const { return _has_field_[3]; }
+ const std::string& mojo_interface_tag() const { return mojo_interface_tag_; }
+ void set_mojo_interface_tag(const std::string& value) { mojo_interface_tag_ = value; _has_field_.set(3); }
+
+ bool has_mojo_interface_method_iid() const { return _has_field_[4]; }
+ uint64_t mojo_interface_method_iid() const { return mojo_interface_method_iid_; }
+ void set_mojo_interface_method_iid(uint64_t value) { mojo_interface_method_iid_ = value; _has_field_.set(4); }
+
+ bool has_is_reply() const { return _has_field_[5]; }
+ bool is_reply() const { return is_reply_; }
+ void set_is_reply(bool value) { is_reply_ = value; _has_field_.set(5); }
+
+ bool has_payload_size() const { return _has_field_[6]; }
+ uint64_t payload_size() const { return payload_size_; }
+ void set_payload_size(uint64_t value) { payload_size_ = value; _has_field_.set(6); }
+
+ bool has_data_num_bytes() const { return _has_field_[7]; }
+ uint64_t data_num_bytes() const { return data_num_bytes_; }
+ void set_data_num_bytes(uint64_t value) { data_num_bytes_ = value; _has_field_.set(7); }
+
+ private:
+ std::string watcher_notify_interface_tag_{};
+ uint32_t ipc_hash_{};
+ std::string mojo_interface_tag_{};
+ uint64_t mojo_interface_method_iid_{};
+ bool is_reply_{};
+ uint64_t payload_size_{};
+ uint64_t data_num_bytes_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeProcessDescriptor;
+enum ChromeProcessDescriptor_ProcessType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeProcessDescriptor_ProcessType : int {
+ ChromeProcessDescriptor_ProcessType_PROCESS_UNSPECIFIED = 0,
+ ChromeProcessDescriptor_ProcessType_PROCESS_BROWSER = 1,
+ ChromeProcessDescriptor_ProcessType_PROCESS_RENDERER = 2,
+ ChromeProcessDescriptor_ProcessType_PROCESS_UTILITY = 3,
+ ChromeProcessDescriptor_ProcessType_PROCESS_ZYGOTE = 4,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SANDBOX_HELPER = 5,
+ ChromeProcessDescriptor_ProcessType_PROCESS_GPU = 6,
+ ChromeProcessDescriptor_ProcessType_PROCESS_PPAPI_PLUGIN = 7,
+ ChromeProcessDescriptor_ProcessType_PROCESS_PPAPI_BROKER = 8,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_NETWORK = 9,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_TRACING = 10,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_STORAGE = 11,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_AUDIO = 12,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_DATA_DECODER = 13,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_UTIL_WIN = 14,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PROXY_RESOLVER = 15,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_CDM = 16,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_VIDEO_CAPTURE = 17,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_UNZIPPER = 18,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_MIRRORING = 19,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_FILEPATCHER = 20,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_TTS = 21,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PRINTING = 22,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_QUARANTINE = 23,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_CROS_LOCALSEARCH = 24,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER = 25,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_FILEUTIL = 26,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PRINTCOMPOSITOR = 27,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PAINTPREVIEW = 28,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_SPEECHRECOGNITION = 29,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_XRDEVICE = 30,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_READICON = 31,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_LANGUAGEDETECTION = 32,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_SHARING = 33,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_MEDIAPARSER = 34,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_QRCODEGENERATOR = 35,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PROFILEIMPORT = 36,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_IME = 37,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_RECORDING = 38,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_SHAPEDETECTION = 39,
+ ChromeProcessDescriptor_ProcessType_PROCESS_RENDERER_EXTENSION = 40,
+ ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_MEDIA_FOUNDATION = 41,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeProcessDescriptor : public ::protozero::CppMessageObj {
+ public:
+ using ProcessType = ChromeProcessDescriptor_ProcessType;
+ static constexpr auto PROCESS_UNSPECIFIED = ChromeProcessDescriptor_ProcessType_PROCESS_UNSPECIFIED;
+ static constexpr auto PROCESS_BROWSER = ChromeProcessDescriptor_ProcessType_PROCESS_BROWSER;
+ static constexpr auto PROCESS_RENDERER = ChromeProcessDescriptor_ProcessType_PROCESS_RENDERER;
+ static constexpr auto PROCESS_UTILITY = ChromeProcessDescriptor_ProcessType_PROCESS_UTILITY;
+ static constexpr auto PROCESS_ZYGOTE = ChromeProcessDescriptor_ProcessType_PROCESS_ZYGOTE;
+ static constexpr auto PROCESS_SANDBOX_HELPER = ChromeProcessDescriptor_ProcessType_PROCESS_SANDBOX_HELPER;
+ static constexpr auto PROCESS_GPU = ChromeProcessDescriptor_ProcessType_PROCESS_GPU;
+ static constexpr auto PROCESS_PPAPI_PLUGIN = ChromeProcessDescriptor_ProcessType_PROCESS_PPAPI_PLUGIN;
+ static constexpr auto PROCESS_PPAPI_BROKER = ChromeProcessDescriptor_ProcessType_PROCESS_PPAPI_BROKER;
+ static constexpr auto PROCESS_SERVICE_NETWORK = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_NETWORK;
+ static constexpr auto PROCESS_SERVICE_TRACING = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_TRACING;
+ static constexpr auto PROCESS_SERVICE_STORAGE = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_STORAGE;
+ static constexpr auto PROCESS_SERVICE_AUDIO = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_AUDIO;
+ static constexpr auto PROCESS_SERVICE_DATA_DECODER = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_DATA_DECODER;
+ static constexpr auto PROCESS_SERVICE_UTIL_WIN = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_UTIL_WIN;
+ static constexpr auto PROCESS_SERVICE_PROXY_RESOLVER = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PROXY_RESOLVER;
+ static constexpr auto PROCESS_SERVICE_CDM = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_CDM;
+ static constexpr auto PROCESS_SERVICE_VIDEO_CAPTURE = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_VIDEO_CAPTURE;
+ static constexpr auto PROCESS_SERVICE_UNZIPPER = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_UNZIPPER;
+ static constexpr auto PROCESS_SERVICE_MIRRORING = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_MIRRORING;
+ static constexpr auto PROCESS_SERVICE_FILEPATCHER = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_FILEPATCHER;
+ static constexpr auto PROCESS_SERVICE_TTS = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_TTS;
+ static constexpr auto PROCESS_SERVICE_PRINTING = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PRINTING;
+ static constexpr auto PROCESS_SERVICE_QUARANTINE = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_QUARANTINE;
+ static constexpr auto PROCESS_SERVICE_CROS_LOCALSEARCH = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_CROS_LOCALSEARCH;
+ static constexpr auto PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER;
+ static constexpr auto PROCESS_SERVICE_FILEUTIL = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_FILEUTIL;
+ static constexpr auto PROCESS_SERVICE_PRINTCOMPOSITOR = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PRINTCOMPOSITOR;
+ static constexpr auto PROCESS_SERVICE_PAINTPREVIEW = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PAINTPREVIEW;
+ static constexpr auto PROCESS_SERVICE_SPEECHRECOGNITION = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_SPEECHRECOGNITION;
+ static constexpr auto PROCESS_SERVICE_XRDEVICE = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_XRDEVICE;
+ static constexpr auto PROCESS_SERVICE_READICON = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_READICON;
+ static constexpr auto PROCESS_SERVICE_LANGUAGEDETECTION = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_LANGUAGEDETECTION;
+ static constexpr auto PROCESS_SERVICE_SHARING = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_SHARING;
+ static constexpr auto PROCESS_SERVICE_MEDIAPARSER = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_MEDIAPARSER;
+ static constexpr auto PROCESS_SERVICE_QRCODEGENERATOR = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_QRCODEGENERATOR;
+ static constexpr auto PROCESS_SERVICE_PROFILEIMPORT = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_PROFILEIMPORT;
+ static constexpr auto PROCESS_SERVICE_IME = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_IME;
+ static constexpr auto PROCESS_SERVICE_RECORDING = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_RECORDING;
+ static constexpr auto PROCESS_SERVICE_SHAPEDETECTION = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_SHAPEDETECTION;
+ static constexpr auto PROCESS_RENDERER_EXTENSION = ChromeProcessDescriptor_ProcessType_PROCESS_RENDERER_EXTENSION;
+ static constexpr auto PROCESS_SERVICE_MEDIA_FOUNDATION = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_MEDIA_FOUNDATION;
+ static constexpr auto ProcessType_MIN = ChromeProcessDescriptor_ProcessType_PROCESS_UNSPECIFIED;
+ static constexpr auto ProcessType_MAX = ChromeProcessDescriptor_ProcessType_PROCESS_SERVICE_MEDIA_FOUNDATION;
+ enum FieldNumbers {
+ kProcessTypeFieldNumber = 1,
+ kProcessPriorityFieldNumber = 2,
+ kLegacySortIndexFieldNumber = 3,
+ kHostAppPackageNameFieldNumber = 4,
+ kCrashTraceIdFieldNumber = 5,
+ };
+
+ ChromeProcessDescriptor();
+ ~ChromeProcessDescriptor() override;
+ ChromeProcessDescriptor(ChromeProcessDescriptor&&) noexcept;
+ ChromeProcessDescriptor& operator=(ChromeProcessDescriptor&&);
+ ChromeProcessDescriptor(const ChromeProcessDescriptor&);
+ ChromeProcessDescriptor& operator=(const ChromeProcessDescriptor&);
+ bool operator==(const ChromeProcessDescriptor&) const;
+ bool operator!=(const ChromeProcessDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_process_type() const { return _has_field_[1]; }
+ ChromeProcessDescriptor_ProcessType process_type() const { return process_type_; }
+ void set_process_type(ChromeProcessDescriptor_ProcessType value) { process_type_ = value; _has_field_.set(1); }
+
+ bool has_process_priority() const { return _has_field_[2]; }
+ int32_t process_priority() const { return process_priority_; }
+ void set_process_priority(int32_t value) { process_priority_ = value; _has_field_.set(2); }
+
+ bool has_legacy_sort_index() const { return _has_field_[3]; }
+ int32_t legacy_sort_index() const { return legacy_sort_index_; }
+ void set_legacy_sort_index(int32_t value) { legacy_sort_index_ = value; _has_field_.set(3); }
+
+ bool has_host_app_package_name() const { return _has_field_[4]; }
+ const std::string& host_app_package_name() const { return host_app_package_name_; }
+ void set_host_app_package_name(const std::string& value) { host_app_package_name_ = value; _has_field_.set(4); }
+
+ bool has_crash_trace_id() const { return _has_field_[5]; }
+ uint64_t crash_trace_id() const { return crash_trace_id_; }
+ void set_crash_trace_id(uint64_t value) { crash_trace_id_ = value; _has_field_.set(5); }
+
+ private:
+ ChromeProcessDescriptor_ProcessType process_type_{};
+ int32_t process_priority_{};
+ int32_t legacy_sort_index_{};
+ std::string host_app_package_name_{};
+ uint64_t crash_trace_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<6> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_RENDERER_SCHEDULER_STATE_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_RENDERER_SCHEDULER_STATE_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeRendererSchedulerState;
+enum ChromeRAILMode : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeRAILMode : int {
+ RAIL_MODE_NONE = 0,
+ RAIL_MODE_RESPONSE = 1,
+ RAIL_MODE_ANIMATION = 2,
+ RAIL_MODE_IDLE = 3,
+ RAIL_MODE_LOAD = 4,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeRendererSchedulerState : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kRailModeFieldNumber = 1,
+ kIsBackgroundedFieldNumber = 2,
+ kIsHiddenFieldNumber = 3,
+ };
+
+ ChromeRendererSchedulerState();
+ ~ChromeRendererSchedulerState() override;
+ ChromeRendererSchedulerState(ChromeRendererSchedulerState&&) noexcept;
+ ChromeRendererSchedulerState& operator=(ChromeRendererSchedulerState&&);
+ ChromeRendererSchedulerState(const ChromeRendererSchedulerState&);
+ ChromeRendererSchedulerState& operator=(const ChromeRendererSchedulerState&);
+ bool operator==(const ChromeRendererSchedulerState&) const;
+ bool operator!=(const ChromeRendererSchedulerState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_rail_mode() const { return _has_field_[1]; }
+ ChromeRAILMode rail_mode() const { return rail_mode_; }
+ void set_rail_mode(ChromeRAILMode value) { rail_mode_ = value; _has_field_.set(1); }
+
+ bool has_is_backgrounded() const { return _has_field_[2]; }
+ bool is_backgrounded() const { return is_backgrounded_; }
+ void set_is_backgrounded(bool value) { is_backgrounded_ = value; _has_field_.set(2); }
+
+ bool has_is_hidden() const { return _has_field_[3]; }
+ bool is_hidden() const { return is_hidden_; }
+ void set_is_hidden(bool value) { is_hidden_ = value; _has_field_.set(3); }
+
+ private:
+ ChromeRAILMode rail_mode_{};
+ bool is_backgrounded_{};
+ bool is_hidden_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_RENDERER_SCHEDULER_STATE_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_THREAD_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_THREAD_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeThreadDescriptor;
+enum ChromeThreadDescriptor_ThreadType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ChromeThreadDescriptor_ThreadType : int {
+ ChromeThreadDescriptor_ThreadType_THREAD_UNSPECIFIED = 0,
+ ChromeThreadDescriptor_ThreadType_THREAD_MAIN = 1,
+ ChromeThreadDescriptor_ThreadType_THREAD_IO = 2,
+ ChromeThreadDescriptor_ThreadType_THREAD_POOL_BG_WORKER = 3,
+ ChromeThreadDescriptor_ThreadType_THREAD_POOL_FG_WORKER = 4,
+ ChromeThreadDescriptor_ThreadType_THREAD_POOL_FG_BLOCKING = 5,
+ ChromeThreadDescriptor_ThreadType_THREAD_POOL_BG_BLOCKING = 6,
+ ChromeThreadDescriptor_ThreadType_THREAD_POOL_SERVICE = 7,
+ ChromeThreadDescriptor_ThreadType_THREAD_COMPOSITOR = 8,
+ ChromeThreadDescriptor_ThreadType_THREAD_VIZ_COMPOSITOR = 9,
+ ChromeThreadDescriptor_ThreadType_THREAD_COMPOSITOR_WORKER = 10,
+ ChromeThreadDescriptor_ThreadType_THREAD_SERVICE_WORKER = 11,
+ ChromeThreadDescriptor_ThreadType_THREAD_NETWORK_SERVICE = 12,
+ ChromeThreadDescriptor_ThreadType_THREAD_CHILD_IO = 13,
+ ChromeThreadDescriptor_ThreadType_THREAD_BROWSER_IO = 14,
+ ChromeThreadDescriptor_ThreadType_THREAD_BROWSER_MAIN = 15,
+ ChromeThreadDescriptor_ThreadType_THREAD_RENDERER_MAIN = 16,
+ ChromeThreadDescriptor_ThreadType_THREAD_UTILITY_MAIN = 17,
+ ChromeThreadDescriptor_ThreadType_THREAD_GPU_MAIN = 18,
+ ChromeThreadDescriptor_ThreadType_THREAD_CACHE_BLOCKFILE = 19,
+ ChromeThreadDescriptor_ThreadType_THREAD_MEDIA = 20,
+ ChromeThreadDescriptor_ThreadType_THREAD_AUDIO_OUTPUTDEVICE = 21,
+ ChromeThreadDescriptor_ThreadType_THREAD_AUDIO_INPUTDEVICE = 22,
+ ChromeThreadDescriptor_ThreadType_THREAD_GPU_MEMORY = 23,
+ ChromeThreadDescriptor_ThreadType_THREAD_GPU_VSYNC = 24,
+ ChromeThreadDescriptor_ThreadType_THREAD_DXA_VIDEODECODER = 25,
+ ChromeThreadDescriptor_ThreadType_THREAD_BROWSER_WATCHDOG = 26,
+ ChromeThreadDescriptor_ThreadType_THREAD_WEBRTC_NETWORK = 27,
+ ChromeThreadDescriptor_ThreadType_THREAD_WINDOW_OWNER = 28,
+ ChromeThreadDescriptor_ThreadType_THREAD_WEBRTC_SIGNALING = 29,
+ ChromeThreadDescriptor_ThreadType_THREAD_WEBRTC_WORKER = 30,
+ ChromeThreadDescriptor_ThreadType_THREAD_PPAPI_MAIN = 31,
+ ChromeThreadDescriptor_ThreadType_THREAD_GPU_WATCHDOG = 32,
+ ChromeThreadDescriptor_ThreadType_THREAD_SWAPPER = 33,
+ ChromeThreadDescriptor_ThreadType_THREAD_GAMEPAD_POLLING = 34,
+ ChromeThreadDescriptor_ThreadType_THREAD_WEBCRYPTO = 35,
+ ChromeThreadDescriptor_ThreadType_THREAD_DATABASE = 36,
+ ChromeThreadDescriptor_ThreadType_THREAD_PROXYRESOLVER = 37,
+ ChromeThreadDescriptor_ThreadType_THREAD_DEVTOOLSADB = 38,
+ ChromeThreadDescriptor_ThreadType_THREAD_NETWORKCONFIGWATCHER = 39,
+ ChromeThreadDescriptor_ThreadType_THREAD_WASAPI_RENDER = 40,
+ ChromeThreadDescriptor_ThreadType_THREAD_LOADER_LOCK_SAMPLER = 41,
+ ChromeThreadDescriptor_ThreadType_THREAD_MEMORY_INFRA = 50,
+ ChromeThreadDescriptor_ThreadType_THREAD_SAMPLING_PROFILER = 51,
+};
+
+class PERFETTO_EXPORT_COMPONENT ChromeThreadDescriptor : public ::protozero::CppMessageObj {
+ public:
+ using ThreadType = ChromeThreadDescriptor_ThreadType;
+ static constexpr auto THREAD_UNSPECIFIED = ChromeThreadDescriptor_ThreadType_THREAD_UNSPECIFIED;
+ static constexpr auto THREAD_MAIN = ChromeThreadDescriptor_ThreadType_THREAD_MAIN;
+ static constexpr auto THREAD_IO = ChromeThreadDescriptor_ThreadType_THREAD_IO;
+ static constexpr auto THREAD_POOL_BG_WORKER = ChromeThreadDescriptor_ThreadType_THREAD_POOL_BG_WORKER;
+ static constexpr auto THREAD_POOL_FG_WORKER = ChromeThreadDescriptor_ThreadType_THREAD_POOL_FG_WORKER;
+ static constexpr auto THREAD_POOL_FG_BLOCKING = ChromeThreadDescriptor_ThreadType_THREAD_POOL_FG_BLOCKING;
+ static constexpr auto THREAD_POOL_BG_BLOCKING = ChromeThreadDescriptor_ThreadType_THREAD_POOL_BG_BLOCKING;
+ static constexpr auto THREAD_POOL_SERVICE = ChromeThreadDescriptor_ThreadType_THREAD_POOL_SERVICE;
+ static constexpr auto THREAD_COMPOSITOR = ChromeThreadDescriptor_ThreadType_THREAD_COMPOSITOR;
+ static constexpr auto THREAD_VIZ_COMPOSITOR = ChromeThreadDescriptor_ThreadType_THREAD_VIZ_COMPOSITOR;
+ static constexpr auto THREAD_COMPOSITOR_WORKER = ChromeThreadDescriptor_ThreadType_THREAD_COMPOSITOR_WORKER;
+ static constexpr auto THREAD_SERVICE_WORKER = ChromeThreadDescriptor_ThreadType_THREAD_SERVICE_WORKER;
+ static constexpr auto THREAD_NETWORK_SERVICE = ChromeThreadDescriptor_ThreadType_THREAD_NETWORK_SERVICE;
+ static constexpr auto THREAD_CHILD_IO = ChromeThreadDescriptor_ThreadType_THREAD_CHILD_IO;
+ static constexpr auto THREAD_BROWSER_IO = ChromeThreadDescriptor_ThreadType_THREAD_BROWSER_IO;
+ static constexpr auto THREAD_BROWSER_MAIN = ChromeThreadDescriptor_ThreadType_THREAD_BROWSER_MAIN;
+ static constexpr auto THREAD_RENDERER_MAIN = ChromeThreadDescriptor_ThreadType_THREAD_RENDERER_MAIN;
+ static constexpr auto THREAD_UTILITY_MAIN = ChromeThreadDescriptor_ThreadType_THREAD_UTILITY_MAIN;
+ static constexpr auto THREAD_GPU_MAIN = ChromeThreadDescriptor_ThreadType_THREAD_GPU_MAIN;
+ static constexpr auto THREAD_CACHE_BLOCKFILE = ChromeThreadDescriptor_ThreadType_THREAD_CACHE_BLOCKFILE;
+ static constexpr auto THREAD_MEDIA = ChromeThreadDescriptor_ThreadType_THREAD_MEDIA;
+ static constexpr auto THREAD_AUDIO_OUTPUTDEVICE = ChromeThreadDescriptor_ThreadType_THREAD_AUDIO_OUTPUTDEVICE;
+ static constexpr auto THREAD_AUDIO_INPUTDEVICE = ChromeThreadDescriptor_ThreadType_THREAD_AUDIO_INPUTDEVICE;
+ static constexpr auto THREAD_GPU_MEMORY = ChromeThreadDescriptor_ThreadType_THREAD_GPU_MEMORY;
+ static constexpr auto THREAD_GPU_VSYNC = ChromeThreadDescriptor_ThreadType_THREAD_GPU_VSYNC;
+ static constexpr auto THREAD_DXA_VIDEODECODER = ChromeThreadDescriptor_ThreadType_THREAD_DXA_VIDEODECODER;
+ static constexpr auto THREAD_BROWSER_WATCHDOG = ChromeThreadDescriptor_ThreadType_THREAD_BROWSER_WATCHDOG;
+ static constexpr auto THREAD_WEBRTC_NETWORK = ChromeThreadDescriptor_ThreadType_THREAD_WEBRTC_NETWORK;
+ static constexpr auto THREAD_WINDOW_OWNER = ChromeThreadDescriptor_ThreadType_THREAD_WINDOW_OWNER;
+ static constexpr auto THREAD_WEBRTC_SIGNALING = ChromeThreadDescriptor_ThreadType_THREAD_WEBRTC_SIGNALING;
+ static constexpr auto THREAD_WEBRTC_WORKER = ChromeThreadDescriptor_ThreadType_THREAD_WEBRTC_WORKER;
+ static constexpr auto THREAD_PPAPI_MAIN = ChromeThreadDescriptor_ThreadType_THREAD_PPAPI_MAIN;
+ static constexpr auto THREAD_GPU_WATCHDOG = ChromeThreadDescriptor_ThreadType_THREAD_GPU_WATCHDOG;
+ static constexpr auto THREAD_SWAPPER = ChromeThreadDescriptor_ThreadType_THREAD_SWAPPER;
+ static constexpr auto THREAD_GAMEPAD_POLLING = ChromeThreadDescriptor_ThreadType_THREAD_GAMEPAD_POLLING;
+ static constexpr auto THREAD_WEBCRYPTO = ChromeThreadDescriptor_ThreadType_THREAD_WEBCRYPTO;
+ static constexpr auto THREAD_DATABASE = ChromeThreadDescriptor_ThreadType_THREAD_DATABASE;
+ static constexpr auto THREAD_PROXYRESOLVER = ChromeThreadDescriptor_ThreadType_THREAD_PROXYRESOLVER;
+ static constexpr auto THREAD_DEVTOOLSADB = ChromeThreadDescriptor_ThreadType_THREAD_DEVTOOLSADB;
+ static constexpr auto THREAD_NETWORKCONFIGWATCHER = ChromeThreadDescriptor_ThreadType_THREAD_NETWORKCONFIGWATCHER;
+ static constexpr auto THREAD_WASAPI_RENDER = ChromeThreadDescriptor_ThreadType_THREAD_WASAPI_RENDER;
+ static constexpr auto THREAD_LOADER_LOCK_SAMPLER = ChromeThreadDescriptor_ThreadType_THREAD_LOADER_LOCK_SAMPLER;
+ static constexpr auto THREAD_MEMORY_INFRA = ChromeThreadDescriptor_ThreadType_THREAD_MEMORY_INFRA;
+ static constexpr auto THREAD_SAMPLING_PROFILER = ChromeThreadDescriptor_ThreadType_THREAD_SAMPLING_PROFILER;
+ static constexpr auto ThreadType_MIN = ChromeThreadDescriptor_ThreadType_THREAD_UNSPECIFIED;
+ static constexpr auto ThreadType_MAX = ChromeThreadDescriptor_ThreadType_THREAD_SAMPLING_PROFILER;
+ enum FieldNumbers {
+ kThreadTypeFieldNumber = 1,
+ kLegacySortIndexFieldNumber = 2,
+ };
+
+ ChromeThreadDescriptor();
+ ~ChromeThreadDescriptor() override;
+ ChromeThreadDescriptor(ChromeThreadDescriptor&&) noexcept;
+ ChromeThreadDescriptor& operator=(ChromeThreadDescriptor&&);
+ ChromeThreadDescriptor(const ChromeThreadDescriptor&);
+ ChromeThreadDescriptor& operator=(const ChromeThreadDescriptor&);
+ bool operator==(const ChromeThreadDescriptor&) const;
+ bool operator!=(const ChromeThreadDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_thread_type() const { return _has_field_[1]; }
+ ChromeThreadDescriptor_ThreadType thread_type() const { return thread_type_; }
+ void set_thread_type(ChromeThreadDescriptor_ThreadType value) { thread_type_ = value; _has_field_.set(1); }
+
+ bool has_legacy_sort_index() const { return _has_field_[2]; }
+ int32_t legacy_sort_index() const { return legacy_sort_index_; }
+ void set_legacy_sort_index(int32_t value) { legacy_sort_index_ = value; _has_field_.set(2); }
+
+ private:
+ ChromeThreadDescriptor_ThreadType thread_type_{};
+ int32_t legacy_sort_index_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_THREAD_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_user_event.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_USER_EVENT_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_USER_EVENT_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeUserEvent;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeUserEvent : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kActionFieldNumber = 1,
+ kActionHashFieldNumber = 2,
+ };
+
+ ChromeUserEvent();
+ ~ChromeUserEvent() override;
+ ChromeUserEvent(ChromeUserEvent&&) noexcept;
+ ChromeUserEvent& operator=(ChromeUserEvent&&);
+ ChromeUserEvent(const ChromeUserEvent&);
+ ChromeUserEvent& operator=(const ChromeUserEvent&);
+ bool operator==(const ChromeUserEvent&) const;
+ bool operator!=(const ChromeUserEvent& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_action() const { return _has_field_[1]; }
+ const std::string& action() const { return action_; }
+ void set_action(const std::string& value) { action_ = value; _has_field_.set(1); }
+
+ bool has_action_hash() const { return _has_field_[2]; }
+ uint64_t action_hash() const { return action_hash_; }
+ void set_action_hash(uint64_t value) { action_hash_ = value; _has_field_.set(2); }
+
+ private:
+ std::string action_{};
+ uint64_t action_hash_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_USER_EVENT_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/chrome_window_handle_event_info.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_WINDOW_HANDLE_EVENT_INFO_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_WINDOW_HANDLE_EVENT_INFO_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ChromeWindowHandleEventInfo;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT ChromeWindowHandleEventInfo : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDpiFieldNumber = 1,
+ kMessageIdFieldNumber = 2,
+ kHwndPtrFieldNumber = 3,
+ };
+
+ ChromeWindowHandleEventInfo();
+ ~ChromeWindowHandleEventInfo() override;
+ ChromeWindowHandleEventInfo(ChromeWindowHandleEventInfo&&) noexcept;
+ ChromeWindowHandleEventInfo& operator=(ChromeWindowHandleEventInfo&&);
+ ChromeWindowHandleEventInfo(const ChromeWindowHandleEventInfo&);
+ ChromeWindowHandleEventInfo& operator=(const ChromeWindowHandleEventInfo&);
+ bool operator==(const ChromeWindowHandleEventInfo&) const;
+ bool operator!=(const ChromeWindowHandleEventInfo& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_dpi() const { return _has_field_[1]; }
+ uint32_t dpi() const { return dpi_; }
+ void set_dpi(uint32_t value) { dpi_ = value; _has_field_.set(1); }
+
+ bool has_message_id() const { return _has_field_[2]; }
+ uint32_t message_id() const { return message_id_; }
+ void set_message_id(uint32_t value) { message_id_ = value; _has_field_.set(2); }
+
+ bool has_hwnd_ptr() const { return _has_field_[3]; }
+ uint64_t hwnd_ptr() const { return hwnd_ptr_; }
+ void set_hwnd_ptr(uint64_t value) { hwnd_ptr_ = value; _has_field_.set(3); }
+
+ private:
+ uint32_t dpi_{};
+ uint32_t message_id_{};
+ uint64_t hwnd_ptr_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_WINDOW_HANDLE_EVENT_INFO_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/debug_annotation.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class DebugAnnotationValueTypeName;
+class DebugAnnotationName;
+class DebugAnnotation;
+class DebugAnnotation_NestedValue;
+enum DebugAnnotation_NestedValue_NestedType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum DebugAnnotation_NestedValue_NestedType : int {
+ DebugAnnotation_NestedValue_NestedType_UNSPECIFIED = 0,
+ DebugAnnotation_NestedValue_NestedType_DICT = 1,
+ DebugAnnotation_NestedValue_NestedType_ARRAY = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT DebugAnnotationValueTypeName : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+
+ DebugAnnotationValueTypeName();
+ ~DebugAnnotationValueTypeName() override;
+ DebugAnnotationValueTypeName(DebugAnnotationValueTypeName&&) noexcept;
+ DebugAnnotationValueTypeName& operator=(DebugAnnotationValueTypeName&&);
+ DebugAnnotationValueTypeName(const DebugAnnotationValueTypeName&);
+ DebugAnnotationValueTypeName& operator=(const DebugAnnotationValueTypeName&);
+ bool operator==(const DebugAnnotationValueTypeName&) const;
+ bool operator!=(const DebugAnnotationValueTypeName& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t iid_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DebugAnnotationName : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+
+ DebugAnnotationName();
+ ~DebugAnnotationName() override;
+ DebugAnnotationName(DebugAnnotationName&&) noexcept;
+ DebugAnnotationName& operator=(DebugAnnotationName&&);
+ DebugAnnotationName(const DebugAnnotationName&);
+ DebugAnnotationName& operator=(const DebugAnnotationName&);
+ bool operator==(const DebugAnnotationName&) const;
+ bool operator!=(const DebugAnnotationName& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t iid_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DebugAnnotation : public ::protozero::CppMessageObj {
+ public:
+ using NestedValue = DebugAnnotation_NestedValue;
+ enum FieldNumbers {
+ kNameIidFieldNumber = 1,
+ kNameFieldNumber = 10,
+ kBoolValueFieldNumber = 2,
+ kUintValueFieldNumber = 3,
+ kIntValueFieldNumber = 4,
+ kDoubleValueFieldNumber = 5,
+ kPointerValueFieldNumber = 7,
+ kNestedValueFieldNumber = 8,
+ kLegacyJsonValueFieldNumber = 9,
+ kStringValueFieldNumber = 6,
+ kStringValueIidFieldNumber = 17,
+ kProtoTypeNameFieldNumber = 16,
+ kProtoTypeNameIidFieldNumber = 13,
+ kProtoValueFieldNumber = 14,
+ kDictEntriesFieldNumber = 11,
+ kArrayValuesFieldNumber = 12,
+ };
+
+ DebugAnnotation();
+ ~DebugAnnotation() override;
+ DebugAnnotation(DebugAnnotation&&) noexcept;
+ DebugAnnotation& operator=(DebugAnnotation&&);
+ DebugAnnotation(const DebugAnnotation&);
+ DebugAnnotation& operator=(const DebugAnnotation&);
+ bool operator==(const DebugAnnotation&) const;
+ bool operator!=(const DebugAnnotation& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name_iid() const { return _has_field_[1]; }
+ uint64_t name_iid() const { return name_iid_; }
+ void set_name_iid(uint64_t value) { name_iid_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[10]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(10); }
+
+ bool has_bool_value() const { return _has_field_[2]; }
+ bool bool_value() const { return bool_value_; }
+ void set_bool_value(bool value) { bool_value_ = value; _has_field_.set(2); }
+
+ bool has_uint_value() const { return _has_field_[3]; }
+ uint64_t uint_value() const { return uint_value_; }
+ void set_uint_value(uint64_t value) { uint_value_ = value; _has_field_.set(3); }
+
+ bool has_int_value() const { return _has_field_[4]; }
+ int64_t int_value() const { return int_value_; }
+ void set_int_value(int64_t value) { int_value_ = value; _has_field_.set(4); }
+
+ bool has_double_value() const { return _has_field_[5]; }
+ double double_value() const { return double_value_; }
+ void set_double_value(double value) { double_value_ = value; _has_field_.set(5); }
+
+ bool has_pointer_value() const { return _has_field_[7]; }
+ uint64_t pointer_value() const { return pointer_value_; }
+ void set_pointer_value(uint64_t value) { pointer_value_ = value; _has_field_.set(7); }
+
+ bool has_nested_value() const { return _has_field_[8]; }
+ const DebugAnnotation_NestedValue& nested_value() const { return *nested_value_; }
+ DebugAnnotation_NestedValue* mutable_nested_value() { _has_field_.set(8); return nested_value_.get(); }
+
+ bool has_legacy_json_value() const { return _has_field_[9]; }
+ const std::string& legacy_json_value() const { return legacy_json_value_; }
+ void set_legacy_json_value(const std::string& value) { legacy_json_value_ = value; _has_field_.set(9); }
+
+ bool has_string_value() const { return _has_field_[6]; }
+ const std::string& string_value() const { return string_value_; }
+ void set_string_value(const std::string& value) { string_value_ = value; _has_field_.set(6); }
+
+ bool has_string_value_iid() const { return _has_field_[17]; }
+ uint64_t string_value_iid() const { return string_value_iid_; }
+ void set_string_value_iid(uint64_t value) { string_value_iid_ = value; _has_field_.set(17); }
+
+ bool has_proto_type_name() const { return _has_field_[16]; }
+ const std::string& proto_type_name() const { return proto_type_name_; }
+ void set_proto_type_name(const std::string& value) { proto_type_name_ = value; _has_field_.set(16); }
+
+ bool has_proto_type_name_iid() const { return _has_field_[13]; }
+ uint64_t proto_type_name_iid() const { return proto_type_name_iid_; }
+ void set_proto_type_name_iid(uint64_t value) { proto_type_name_iid_ = value; _has_field_.set(13); }
+
+ bool has_proto_value() const { return _has_field_[14]; }
+ const std::string& proto_value() const { return proto_value_; }
+ void set_proto_value(const std::string& value) { proto_value_ = value; _has_field_.set(14); }
+ void set_proto_value(const void* p, size_t s) { proto_value_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(14); }
+
+ const std::vector<DebugAnnotation>& dict_entries() const { return dict_entries_; }
+ std::vector<DebugAnnotation>* mutable_dict_entries() { return &dict_entries_; }
+ int dict_entries_size() const;
+ void clear_dict_entries();
+ DebugAnnotation* add_dict_entries();
+
+ const std::vector<DebugAnnotation>& array_values() const { return array_values_; }
+ std::vector<DebugAnnotation>* mutable_array_values() { return &array_values_; }
+ int array_values_size() const;
+ void clear_array_values();
+ DebugAnnotation* add_array_values();
+
+ private:
+ uint64_t name_iid_{};
+ std::string name_{};
+ bool bool_value_{};
+ uint64_t uint_value_{};
+ int64_t int_value_{};
+ double double_value_{};
+ uint64_t pointer_value_{};
+ ::protozero::CopyablePtr<DebugAnnotation_NestedValue> nested_value_;
+ std::string legacy_json_value_{};
+ std::string string_value_{};
+ uint64_t string_value_iid_{};
+ std::string proto_type_name_{};
+ uint64_t proto_type_name_iid_{};
+ std::string proto_value_{};
+ std::vector<DebugAnnotation> dict_entries_;
+ std::vector<DebugAnnotation> array_values_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<18> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DebugAnnotation_NestedValue : public ::protozero::CppMessageObj {
+ public:
+ using NestedType = DebugAnnotation_NestedValue_NestedType;
+ static constexpr auto UNSPECIFIED = DebugAnnotation_NestedValue_NestedType_UNSPECIFIED;
+ static constexpr auto DICT = DebugAnnotation_NestedValue_NestedType_DICT;
+ static constexpr auto ARRAY = DebugAnnotation_NestedValue_NestedType_ARRAY;
+ static constexpr auto NestedType_MIN = DebugAnnotation_NestedValue_NestedType_UNSPECIFIED;
+ static constexpr auto NestedType_MAX = DebugAnnotation_NestedValue_NestedType_ARRAY;
+ enum FieldNumbers {
+ kNestedTypeFieldNumber = 1,
+ kDictKeysFieldNumber = 2,
+ kDictValuesFieldNumber = 3,
+ kArrayValuesFieldNumber = 4,
+ kIntValueFieldNumber = 5,
+ kDoubleValueFieldNumber = 6,
+ kBoolValueFieldNumber = 7,
+ kStringValueFieldNumber = 8,
+ };
+
+ DebugAnnotation_NestedValue();
+ ~DebugAnnotation_NestedValue() override;
+ DebugAnnotation_NestedValue(DebugAnnotation_NestedValue&&) noexcept;
+ DebugAnnotation_NestedValue& operator=(DebugAnnotation_NestedValue&&);
+ DebugAnnotation_NestedValue(const DebugAnnotation_NestedValue&);
+ DebugAnnotation_NestedValue& operator=(const DebugAnnotation_NestedValue&);
+ bool operator==(const DebugAnnotation_NestedValue&) const;
+ bool operator!=(const DebugAnnotation_NestedValue& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_nested_type() const { return _has_field_[1]; }
+ DebugAnnotation_NestedValue_NestedType nested_type() const { return nested_type_; }
+ void set_nested_type(DebugAnnotation_NestedValue_NestedType value) { nested_type_ = value; _has_field_.set(1); }
+
+ const std::vector<std::string>& dict_keys() const { return dict_keys_; }
+ std::vector<std::string>* mutable_dict_keys() { return &dict_keys_; }
+ int dict_keys_size() const { return static_cast<int>(dict_keys_.size()); }
+ void clear_dict_keys() { dict_keys_.clear(); }
+ void add_dict_keys(std::string value) { dict_keys_.emplace_back(value); }
+ std::string* add_dict_keys() { dict_keys_.emplace_back(); return &dict_keys_.back(); }
+
+ const std::vector<DebugAnnotation_NestedValue>& dict_values() const { return dict_values_; }
+ std::vector<DebugAnnotation_NestedValue>* mutable_dict_values() { return &dict_values_; }
+ int dict_values_size() const;
+ void clear_dict_values();
+ DebugAnnotation_NestedValue* add_dict_values();
+
+ const std::vector<DebugAnnotation_NestedValue>& array_values() const { return array_values_; }
+ std::vector<DebugAnnotation_NestedValue>* mutable_array_values() { return &array_values_; }
+ int array_values_size() const;
+ void clear_array_values();
+ DebugAnnotation_NestedValue* add_array_values();
+
+ bool has_int_value() const { return _has_field_[5]; }
+ int64_t int_value() const { return int_value_; }
+ void set_int_value(int64_t value) { int_value_ = value; _has_field_.set(5); }
+
+ bool has_double_value() const { return _has_field_[6]; }
+ double double_value() const { return double_value_; }
+ void set_double_value(double value) { double_value_ = value; _has_field_.set(6); }
+
+ bool has_bool_value() const { return _has_field_[7]; }
+ bool bool_value() const { return bool_value_; }
+ void set_bool_value(bool value) { bool_value_ = value; _has_field_.set(7); }
+
+ bool has_string_value() const { return _has_field_[8]; }
+ const std::string& string_value() const { return string_value_; }
+ void set_string_value(const std::string& value) { string_value_ = value; _has_field_.set(8); }
+
+ private:
+ DebugAnnotation_NestedValue_NestedType nested_type_{};
+ std::vector<std::string> dict_keys_;
+ std::vector<DebugAnnotation_NestedValue> dict_values_;
+ std::vector<DebugAnnotation_NestedValue> array_values_;
+ int64_t int_value_{};
+ double double_value_{};
+ bool bool_value_{};
+ std::string string_value_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/log_message.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class LogMessageBody;
+class LogMessage;
+enum LogMessage_Priority : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum LogMessage_Priority : int {
+ LogMessage_Priority_PRIO_UNSPECIFIED = 0,
+ LogMessage_Priority_PRIO_UNUSED = 1,
+ LogMessage_Priority_PRIO_VERBOSE = 2,
+ LogMessage_Priority_PRIO_DEBUG = 3,
+ LogMessage_Priority_PRIO_INFO = 4,
+ LogMessage_Priority_PRIO_WARN = 5,
+ LogMessage_Priority_PRIO_ERROR = 6,
+ LogMessage_Priority_PRIO_FATAL = 7,
+};
+
+class PERFETTO_EXPORT_COMPONENT LogMessageBody : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kBodyFieldNumber = 2,
+ };
+
+ LogMessageBody();
+ ~LogMessageBody() override;
+ LogMessageBody(LogMessageBody&&) noexcept;
+ LogMessageBody& operator=(LogMessageBody&&);
+ LogMessageBody(const LogMessageBody&);
+ LogMessageBody& operator=(const LogMessageBody&);
+ bool operator==(const LogMessageBody&) const;
+ bool operator!=(const LogMessageBody& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_body() const { return _has_field_[2]; }
+ const std::string& body() const { return body_; }
+ void set_body(const std::string& value) { body_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t iid_{};
+ std::string body_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT LogMessage : public ::protozero::CppMessageObj {
+ public:
+ using Priority = LogMessage_Priority;
+ static constexpr auto PRIO_UNSPECIFIED = LogMessage_Priority_PRIO_UNSPECIFIED;
+ static constexpr auto PRIO_UNUSED = LogMessage_Priority_PRIO_UNUSED;
+ static constexpr auto PRIO_VERBOSE = LogMessage_Priority_PRIO_VERBOSE;
+ static constexpr auto PRIO_DEBUG = LogMessage_Priority_PRIO_DEBUG;
+ static constexpr auto PRIO_INFO = LogMessage_Priority_PRIO_INFO;
+ static constexpr auto PRIO_WARN = LogMessage_Priority_PRIO_WARN;
+ static constexpr auto PRIO_ERROR = LogMessage_Priority_PRIO_ERROR;
+ static constexpr auto PRIO_FATAL = LogMessage_Priority_PRIO_FATAL;
+ static constexpr auto Priority_MIN = LogMessage_Priority_PRIO_UNSPECIFIED;
+ static constexpr auto Priority_MAX = LogMessage_Priority_PRIO_FATAL;
+ enum FieldNumbers {
+ kSourceLocationIidFieldNumber = 1,
+ kBodyIidFieldNumber = 2,
+ kPrioFieldNumber = 3,
+ };
+
+ LogMessage();
+ ~LogMessage() override;
+ LogMessage(LogMessage&&) noexcept;
+ LogMessage& operator=(LogMessage&&);
+ LogMessage(const LogMessage&);
+ LogMessage& operator=(const LogMessage&);
+ bool operator==(const LogMessage&) const;
+ bool operator!=(const LogMessage& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_source_location_iid() const { return _has_field_[1]; }
+ uint64_t source_location_iid() const { return source_location_iid_; }
+ void set_source_location_iid(uint64_t value) { source_location_iid_ = value; _has_field_.set(1); }
+
+ bool has_body_iid() const { return _has_field_[2]; }
+ uint64_t body_iid() const { return body_iid_; }
+ void set_body_iid(uint64_t value) { body_iid_ = value; _has_field_.set(2); }
+
+ bool has_prio() const { return _has_field_[3]; }
+ LogMessage_Priority prio() const { return prio_; }
+ void set_prio(LogMessage_Priority value) { prio_ = value; _has_field_.set(3); }
+
+ private:
+ uint64_t source_location_iid_{};
+ uint64_t body_iid_{};
+ LogMessage_Priority prio_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/pixel_modem.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PIXEL_MODEM_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PIXEL_MODEM_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class PixelModemEventInsight;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT PixelModemEventInsight : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDetokenizedMessageFieldNumber = 1,
+ };
+
+ PixelModemEventInsight();
+ ~PixelModemEventInsight() override;
+ PixelModemEventInsight(PixelModemEventInsight&&) noexcept;
+ PixelModemEventInsight& operator=(PixelModemEventInsight&&);
+ PixelModemEventInsight(const PixelModemEventInsight&);
+ PixelModemEventInsight& operator=(const PixelModemEventInsight&);
+ bool operator==(const PixelModemEventInsight&) const;
+ bool operator!=(const PixelModemEventInsight& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_detokenized_message() const { return _has_field_[1]; }
+ const std::string& detokenized_message() const { return detokenized_message_; }
+ void set_detokenized_message(const std::string& value) { detokenized_message_ = value; _has_field_.set(1); }
+
+ private:
+ std::string detokenized_message_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PIXEL_MODEM_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/process_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ProcessDescriptor;
+enum ProcessDescriptor_ChromeProcessType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ProcessDescriptor_ChromeProcessType : int {
+ ProcessDescriptor_ChromeProcessType_PROCESS_UNSPECIFIED = 0,
+ ProcessDescriptor_ChromeProcessType_PROCESS_BROWSER = 1,
+ ProcessDescriptor_ChromeProcessType_PROCESS_RENDERER = 2,
+ ProcessDescriptor_ChromeProcessType_PROCESS_UTILITY = 3,
+ ProcessDescriptor_ChromeProcessType_PROCESS_ZYGOTE = 4,
+ ProcessDescriptor_ChromeProcessType_PROCESS_SANDBOX_HELPER = 5,
+ ProcessDescriptor_ChromeProcessType_PROCESS_GPU = 6,
+ ProcessDescriptor_ChromeProcessType_PROCESS_PPAPI_PLUGIN = 7,
+ ProcessDescriptor_ChromeProcessType_PROCESS_PPAPI_BROKER = 8,
+};
+
+class PERFETTO_EXPORT_COMPONENT ProcessDescriptor : public ::protozero::CppMessageObj {
+ public:
+ using ChromeProcessType = ProcessDescriptor_ChromeProcessType;
+ static constexpr auto PROCESS_UNSPECIFIED = ProcessDescriptor_ChromeProcessType_PROCESS_UNSPECIFIED;
+ static constexpr auto PROCESS_BROWSER = ProcessDescriptor_ChromeProcessType_PROCESS_BROWSER;
+ static constexpr auto PROCESS_RENDERER = ProcessDescriptor_ChromeProcessType_PROCESS_RENDERER;
+ static constexpr auto PROCESS_UTILITY = ProcessDescriptor_ChromeProcessType_PROCESS_UTILITY;
+ static constexpr auto PROCESS_ZYGOTE = ProcessDescriptor_ChromeProcessType_PROCESS_ZYGOTE;
+ static constexpr auto PROCESS_SANDBOX_HELPER = ProcessDescriptor_ChromeProcessType_PROCESS_SANDBOX_HELPER;
+ static constexpr auto PROCESS_GPU = ProcessDescriptor_ChromeProcessType_PROCESS_GPU;
+ static constexpr auto PROCESS_PPAPI_PLUGIN = ProcessDescriptor_ChromeProcessType_PROCESS_PPAPI_PLUGIN;
+ static constexpr auto PROCESS_PPAPI_BROKER = ProcessDescriptor_ChromeProcessType_PROCESS_PPAPI_BROKER;
+ static constexpr auto ChromeProcessType_MIN = ProcessDescriptor_ChromeProcessType_PROCESS_UNSPECIFIED;
+ static constexpr auto ChromeProcessType_MAX = ProcessDescriptor_ChromeProcessType_PROCESS_PPAPI_BROKER;
+ enum FieldNumbers {
+ kPidFieldNumber = 1,
+ kCmdlineFieldNumber = 2,
+ kProcessNameFieldNumber = 6,
+ kProcessPriorityFieldNumber = 5,
+ kStartTimestampNsFieldNumber = 7,
+ kChromeProcessTypeFieldNumber = 4,
+ kLegacySortIndexFieldNumber = 3,
+ kProcessLabelsFieldNumber = 8,
+ };
+
+ ProcessDescriptor();
+ ~ProcessDescriptor() override;
+ ProcessDescriptor(ProcessDescriptor&&) noexcept;
+ ProcessDescriptor& operator=(ProcessDescriptor&&);
+ ProcessDescriptor(const ProcessDescriptor&);
+ ProcessDescriptor& operator=(const ProcessDescriptor&);
+ bool operator==(const ProcessDescriptor&) const;
+ bool operator!=(const ProcessDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_pid() const { return _has_field_[1]; }
+ int32_t pid() const { return pid_; }
+ void set_pid(int32_t value) { pid_ = value; _has_field_.set(1); }
+
+ const std::vector<std::string>& cmdline() const { return cmdline_; }
+ std::vector<std::string>* mutable_cmdline() { return &cmdline_; }
+ int cmdline_size() const { return static_cast<int>(cmdline_.size()); }
+ void clear_cmdline() { cmdline_.clear(); }
+ void add_cmdline(std::string value) { cmdline_.emplace_back(value); }
+ std::string* add_cmdline() { cmdline_.emplace_back(); return &cmdline_.back(); }
+
+ bool has_process_name() const { return _has_field_[6]; }
+ const std::string& process_name() const { return process_name_; }
+ void set_process_name(const std::string& value) { process_name_ = value; _has_field_.set(6); }
+
+ bool has_process_priority() const { return _has_field_[5]; }
+ int32_t process_priority() const { return process_priority_; }
+ void set_process_priority(int32_t value) { process_priority_ = value; _has_field_.set(5); }
+
+ bool has_start_timestamp_ns() const { return _has_field_[7]; }
+ int64_t start_timestamp_ns() const { return start_timestamp_ns_; }
+ void set_start_timestamp_ns(int64_t value) { start_timestamp_ns_ = value; _has_field_.set(7); }
+
+ bool has_chrome_process_type() const { return _has_field_[4]; }
+ ProcessDescriptor_ChromeProcessType chrome_process_type() const { return chrome_process_type_; }
+ void set_chrome_process_type(ProcessDescriptor_ChromeProcessType value) { chrome_process_type_ = value; _has_field_.set(4); }
+
+ bool has_legacy_sort_index() const { return _has_field_[3]; }
+ int32_t legacy_sort_index() const { return legacy_sort_index_; }
+ void set_legacy_sort_index(int32_t value) { legacy_sort_index_ = value; _has_field_.set(3); }
+
+ const std::vector<std::string>& process_labels() const { return process_labels_; }
+ std::vector<std::string>* mutable_process_labels() { return &process_labels_; }
+ int process_labels_size() const { return static_cast<int>(process_labels_.size()); }
+ void clear_process_labels() { process_labels_.clear(); }
+ void add_process_labels(std::string value) { process_labels_.emplace_back(value); }
+ std::string* add_process_labels() { process_labels_.emplace_back(); return &process_labels_.back(); }
+
+ private:
+ int32_t pid_{};
+ std::vector<std::string> cmdline_;
+ std::string process_name_{};
+ int32_t process_priority_{};
+ int64_t start_timestamp_ns_{};
+ ProcessDescriptor_ChromeProcessType chrome_process_type_{};
+ int32_t legacy_sort_index_{};
+ std::vector<std::string> process_labels_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/range_of_interest.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_RANGE_OF_INTEREST_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_RANGE_OF_INTEREST_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TrackEventRangeOfInterest;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TrackEventRangeOfInterest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kStartUsFieldNumber = 1,
+ };
+
+ TrackEventRangeOfInterest();
+ ~TrackEventRangeOfInterest() override;
+ TrackEventRangeOfInterest(TrackEventRangeOfInterest&&) noexcept;
+ TrackEventRangeOfInterest& operator=(TrackEventRangeOfInterest&&);
+ TrackEventRangeOfInterest(const TrackEventRangeOfInterest&);
+ TrackEventRangeOfInterest& operator=(const TrackEventRangeOfInterest&);
+ bool operator==(const TrackEventRangeOfInterest&) const;
+ bool operator!=(const TrackEventRangeOfInterest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_start_us() const { return _has_field_[1]; }
+ int64_t start_us() const { return start_us_; }
+ void set_start_us(int64_t value) { start_us_ = value; _has_field_.set(1); }
+
+ private:
+ int64_t start_us_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_RANGE_OF_INTEREST_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/screenshot.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SCREENSHOT_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SCREENSHOT_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class Screenshot;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT Screenshot : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kJpgImageFieldNumber = 1,
+ };
+
+ Screenshot();
+ ~Screenshot() override;
+ Screenshot(Screenshot&&) noexcept;
+ Screenshot& operator=(Screenshot&&);
+ Screenshot(const Screenshot&);
+ Screenshot& operator=(const Screenshot&);
+ bool operator==(const Screenshot&) const;
+ bool operator!=(const Screenshot& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_jpg_image() const { return _has_field_[1]; }
+ const std::string& jpg_image() const { return jpg_image_; }
+ void set_jpg_image(const std::string& value) { jpg_image_ = value; _has_field_.set(1); }
+ void set_jpg_image(const void* p, size_t s) { jpg_image_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(1); }
+
+ private:
+ std::string jpg_image_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SCREENSHOT_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/source_location.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class SourceLocation;
+class UnsymbolizedSourceLocation;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT SourceLocation : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kFileNameFieldNumber = 2,
+ kFunctionNameFieldNumber = 3,
+ kLineNumberFieldNumber = 4,
+ };
+
+ SourceLocation();
+ ~SourceLocation() override;
+ SourceLocation(SourceLocation&&) noexcept;
+ SourceLocation& operator=(SourceLocation&&);
+ SourceLocation(const SourceLocation&);
+ SourceLocation& operator=(const SourceLocation&);
+ bool operator==(const SourceLocation&) const;
+ bool operator!=(const SourceLocation& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_file_name() const { return _has_field_[2]; }
+ const std::string& file_name() const { return file_name_; }
+ void set_file_name(const std::string& value) { file_name_ = value; _has_field_.set(2); }
+
+ bool has_function_name() const { return _has_field_[3]; }
+ const std::string& function_name() const { return function_name_; }
+ void set_function_name(const std::string& value) { function_name_ = value; _has_field_.set(3); }
+
+ bool has_line_number() const { return _has_field_[4]; }
+ uint32_t line_number() const { return line_number_; }
+ void set_line_number(uint32_t value) { line_number_ = value; _has_field_.set(4); }
+
+ private:
+ uint64_t iid_{};
+ std::string file_name_{};
+ std::string function_name_{};
+ uint32_t line_number_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UnsymbolizedSourceLocation : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kMappingIdFieldNumber = 2,
+ kRelPcFieldNumber = 3,
+ };
+
+ UnsymbolizedSourceLocation();
+ ~UnsymbolizedSourceLocation() override;
+ UnsymbolizedSourceLocation(UnsymbolizedSourceLocation&&) noexcept;
+ UnsymbolizedSourceLocation& operator=(UnsymbolizedSourceLocation&&);
+ UnsymbolizedSourceLocation(const UnsymbolizedSourceLocation&);
+ UnsymbolizedSourceLocation& operator=(const UnsymbolizedSourceLocation&);
+ bool operator==(const UnsymbolizedSourceLocation&) const;
+ bool operator!=(const UnsymbolizedSourceLocation& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_mapping_id() const { return _has_field_[2]; }
+ uint64_t mapping_id() const { return mapping_id_; }
+ void set_mapping_id(uint64_t value) { mapping_id_ = value; _has_field_.set(2); }
+
+ bool has_rel_pc() const { return _has_field_[3]; }
+ uint64_t rel_pc() const { return rel_pc_; }
+ void set_rel_pc(uint64_t value) { rel_pc_ = value; _has_field_.set(3); }
+
+ private:
+ uint64_t iid_{};
+ uint64_t mapping_id_{};
+ uint64_t rel_pc_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/task_execution.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TaskExecution;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT TaskExecution : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPostedFromIidFieldNumber = 1,
+ };
+
+ TaskExecution();
+ ~TaskExecution() override;
+ TaskExecution(TaskExecution&&) noexcept;
+ TaskExecution& operator=(TaskExecution&&);
+ TaskExecution(const TaskExecution&);
+ TaskExecution& operator=(const TaskExecution&);
+ bool operator==(const TaskExecution&) const;
+ bool operator!=(const TaskExecution& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_posted_from_iid() const { return _has_field_[1]; }
+ uint64_t posted_from_iid() const { return posted_from_iid_; }
+ void set_posted_from_iid(uint64_t value) { posted_from_iid_ = value; _has_field_.set(1); }
+
+ private:
+ uint64_t posted_from_iid_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/thread_descriptor.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class ThreadDescriptor;
+enum ThreadDescriptor_ChromeThreadType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum ThreadDescriptor_ChromeThreadType : int {
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_UNSPECIFIED = 0,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_MAIN = 1,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_IO = 2,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_BG_WORKER = 3,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_FG_WORKER = 4,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_FB_BLOCKING = 5,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_BG_BLOCKING = 6,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_SERVICE = 7,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_COMPOSITOR = 8,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_VIZ_COMPOSITOR = 9,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_COMPOSITOR_WORKER = 10,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_SERVICE_WORKER = 11,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_MEMORY_INFRA = 50,
+ ThreadDescriptor_ChromeThreadType_CHROME_THREAD_SAMPLING_PROFILER = 51,
+};
+
+class PERFETTO_EXPORT_COMPONENT ThreadDescriptor : public ::protozero::CppMessageObj {
+ public:
+ using ChromeThreadType = ThreadDescriptor_ChromeThreadType;
+ static constexpr auto CHROME_THREAD_UNSPECIFIED = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_UNSPECIFIED;
+ static constexpr auto CHROME_THREAD_MAIN = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_MAIN;
+ static constexpr auto CHROME_THREAD_IO = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_IO;
+ static constexpr auto CHROME_THREAD_POOL_BG_WORKER = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_BG_WORKER;
+ static constexpr auto CHROME_THREAD_POOL_FG_WORKER = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_FG_WORKER;
+ static constexpr auto CHROME_THREAD_POOL_FB_BLOCKING = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_FB_BLOCKING;
+ static constexpr auto CHROME_THREAD_POOL_BG_BLOCKING = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_BG_BLOCKING;
+ static constexpr auto CHROME_THREAD_POOL_SERVICE = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_POOL_SERVICE;
+ static constexpr auto CHROME_THREAD_COMPOSITOR = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_COMPOSITOR;
+ static constexpr auto CHROME_THREAD_VIZ_COMPOSITOR = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_VIZ_COMPOSITOR;
+ static constexpr auto CHROME_THREAD_COMPOSITOR_WORKER = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_COMPOSITOR_WORKER;
+ static constexpr auto CHROME_THREAD_SERVICE_WORKER = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_SERVICE_WORKER;
+ static constexpr auto CHROME_THREAD_MEMORY_INFRA = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_MEMORY_INFRA;
+ static constexpr auto CHROME_THREAD_SAMPLING_PROFILER = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_SAMPLING_PROFILER;
+ static constexpr auto ChromeThreadType_MIN = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_UNSPECIFIED;
+ static constexpr auto ChromeThreadType_MAX = ThreadDescriptor_ChromeThreadType_CHROME_THREAD_SAMPLING_PROFILER;
+ enum FieldNumbers {
+ kPidFieldNumber = 1,
+ kTidFieldNumber = 2,
+ kThreadNameFieldNumber = 5,
+ kChromeThreadTypeFieldNumber = 4,
+ kReferenceTimestampUsFieldNumber = 6,
+ kReferenceThreadTimeUsFieldNumber = 7,
+ kReferenceThreadInstructionCountFieldNumber = 8,
+ kLegacySortIndexFieldNumber = 3,
+ };
+
+ ThreadDescriptor();
+ ~ThreadDescriptor() override;
+ ThreadDescriptor(ThreadDescriptor&&) noexcept;
+ ThreadDescriptor& operator=(ThreadDescriptor&&);
+ ThreadDescriptor(const ThreadDescriptor&);
+ ThreadDescriptor& operator=(const ThreadDescriptor&);
+ bool operator==(const ThreadDescriptor&) const;
+ bool operator!=(const ThreadDescriptor& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_pid() const { return _has_field_[1]; }
+ int32_t pid() const { return pid_; }
+ void set_pid(int32_t value) { pid_ = value; _has_field_.set(1); }
+
+ bool has_tid() const { return _has_field_[2]; }
+ int32_t tid() const { return tid_; }
+ void set_tid(int32_t value) { tid_ = value; _has_field_.set(2); }
+
+ bool has_thread_name() const { return _has_field_[5]; }
+ const std::string& thread_name() const { return thread_name_; }
+ void set_thread_name(const std::string& value) { thread_name_ = value; _has_field_.set(5); }
+
+ bool has_chrome_thread_type() const { return _has_field_[4]; }
+ ThreadDescriptor_ChromeThreadType chrome_thread_type() const { return chrome_thread_type_; }
+ void set_chrome_thread_type(ThreadDescriptor_ChromeThreadType value) { chrome_thread_type_ = value; _has_field_.set(4); }
+
+ bool has_reference_timestamp_us() const { return _has_field_[6]; }
+ int64_t reference_timestamp_us() const { return reference_timestamp_us_; }
+ void set_reference_timestamp_us(int64_t value) { reference_timestamp_us_ = value; _has_field_.set(6); }
+
+ bool has_reference_thread_time_us() const { return _has_field_[7]; }
+ int64_t reference_thread_time_us() const { return reference_thread_time_us_; }
+ void set_reference_thread_time_us(int64_t value) { reference_thread_time_us_ = value; _has_field_.set(7); }
+
+ bool has_reference_thread_instruction_count() const { return _has_field_[8]; }
+ int64_t reference_thread_instruction_count() const { return reference_thread_instruction_count_; }
+ void set_reference_thread_instruction_count(int64_t value) { reference_thread_instruction_count_ = value; _has_field_.set(8); }
+
+ bool has_legacy_sort_index() const { return _has_field_[3]; }
+ int32_t legacy_sort_index() const { return legacy_sort_index_; }
+ void set_legacy_sort_index(int32_t value) { legacy_sort_index_ = value; _has_field_.set(3); }
+
+ private:
+ int32_t pid_{};
+ int32_t tid_{};
+ std::string thread_name_{};
+ ThreadDescriptor_ChromeThreadType chrome_thread_type_{};
+ int64_t reference_timestamp_us_{};
+ int64_t reference_thread_time_us_{};
+ int64_t reference_thread_instruction_count_{};
+ int32_t legacy_sort_index_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/track_event.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class EventName;
+class EventCategory;
+class TrackEventDefaults;
+class TrackEvent;
+class TrackEvent_LegacyEvent;
+class ChromeMojoEventInfo;
+class ChromeMessagePump;
+class SourceLocation;
+class PixelModemEventInsight;
+class Screenshot;
+class ChromeActiveProcesses;
+class ChromeContentSettingsEventInfo;
+class ChromeWindowHandleEventInfo;
+class ChromeRendererSchedulerState;
+class ChromeApplicationStateInfo;
+class ChromeFrameReporter;
+class ChromeLatencyInfo;
+class ChromeLatencyInfo_ComponentInfo;
+class ChromeHistogramSample;
+class ChromeLegacyIpc;
+class ChromeKeyedService;
+class ChromeUserEvent;
+class ChromeCompositorSchedulerState;
+class CompositorTimingHistory;
+class BeginFrameSourceState;
+class BeginFrameArgs;
+class BeginFrameObserverState;
+class BeginImplFrameArgs;
+class BeginImplFrameArgs_TimestampsInUs;
+class ChromeCompositorStateMachine;
+class ChromeCompositorStateMachine_MinorState;
+class ChromeCompositorStateMachine_MajorState;
+class LogMessage;
+class TaskExecution;
+class DebugAnnotation;
+class DebugAnnotation_NestedValue;
+enum TrackEvent_Type : int;
+enum TrackEvent_LegacyEvent_FlowDirection : int;
+enum TrackEvent_LegacyEvent_InstantEventScope : int;
+enum ChromeRAILMode : int;
+enum ChromeApplicationStateInfo_ChromeApplicationState : int;
+enum ChromeFrameReporter_State : int;
+enum ChromeFrameReporter_FrameDropReason : int;
+enum ChromeFrameReporter_ScrollState : int;
+enum ChromeFrameReporter_FrameType : int;
+enum ChromeLatencyInfo_Step : int;
+enum ChromeLatencyInfo_LatencyComponentType : int;
+enum ChromeLegacyIpc_MessageClass : int;
+enum ChromeCompositorSchedulerState_BeginImplFrameDeadlineMode : int;
+enum ChromeCompositorSchedulerAction : int;
+enum BeginFrameArgs_BeginFrameArgsType : int;
+enum BeginImplFrameArgs_State : int;
+enum ChromeCompositorStateMachine_MinorState_TreePriority : int;
+enum ChromeCompositorStateMachine_MinorState_ScrollHandlerState : int;
+enum ChromeCompositorStateMachine_MajorState_BeginImplFrameState : int;
+enum ChromeCompositorStateMachine_MajorState_BeginMainFrameState : int;
+enum ChromeCompositorStateMachine_MajorState_LayerTreeFrameSinkState : int;
+enum ChromeCompositorStateMachine_MajorState_ForcedRedrawOnTimeoutState : int;
+enum LogMessage_Priority : int;
+enum DebugAnnotation_NestedValue_NestedType : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum TrackEvent_Type : int {
+ TrackEvent_Type_TYPE_UNSPECIFIED = 0,
+ TrackEvent_Type_TYPE_SLICE_BEGIN = 1,
+ TrackEvent_Type_TYPE_SLICE_END = 2,
+ TrackEvent_Type_TYPE_INSTANT = 3,
+ TrackEvent_Type_TYPE_COUNTER = 4,
+};
+enum TrackEvent_LegacyEvent_FlowDirection : int {
+ TrackEvent_LegacyEvent_FlowDirection_FLOW_UNSPECIFIED = 0,
+ TrackEvent_LegacyEvent_FlowDirection_FLOW_IN = 1,
+ TrackEvent_LegacyEvent_FlowDirection_FLOW_OUT = 2,
+ TrackEvent_LegacyEvent_FlowDirection_FLOW_INOUT = 3,
+};
+enum TrackEvent_LegacyEvent_InstantEventScope : int {
+ TrackEvent_LegacyEvent_InstantEventScope_SCOPE_UNSPECIFIED = 0,
+ TrackEvent_LegacyEvent_InstantEventScope_SCOPE_GLOBAL = 1,
+ TrackEvent_LegacyEvent_InstantEventScope_SCOPE_PROCESS = 2,
+ TrackEvent_LegacyEvent_InstantEventScope_SCOPE_THREAD = 3,
+};
+
+class PERFETTO_EXPORT_COMPONENT EventName : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+
+ EventName();
+ ~EventName() override;
+ EventName(EventName&&) noexcept;
+ EventName& operator=(EventName&&);
+ EventName(const EventName&);
+ EventName& operator=(const EventName&);
+ bool operator==(const EventName&) const;
+ bool operator!=(const EventName& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t iid_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT EventCategory : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIidFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+
+ EventCategory();
+ ~EventCategory() override;
+ EventCategory(EventCategory&&) noexcept;
+ EventCategory& operator=(EventCategory&&);
+ EventCategory(const EventCategory&);
+ EventCategory& operator=(const EventCategory&);
+ bool operator==(const EventCategory&) const;
+ bool operator!=(const EventCategory& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_iid() const { return _has_field_[1]; }
+ uint64_t iid() const { return iid_; }
+ void set_iid(uint64_t value) { iid_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ private:
+ uint64_t iid_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TrackEventDefaults : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTrackUuidFieldNumber = 11,
+ kExtraCounterTrackUuidsFieldNumber = 31,
+ kExtraDoubleCounterTrackUuidsFieldNumber = 45,
+ };
+
+ TrackEventDefaults();
+ ~TrackEventDefaults() override;
+ TrackEventDefaults(TrackEventDefaults&&) noexcept;
+ TrackEventDefaults& operator=(TrackEventDefaults&&);
+ TrackEventDefaults(const TrackEventDefaults&);
+ TrackEventDefaults& operator=(const TrackEventDefaults&);
+ bool operator==(const TrackEventDefaults&) const;
+ bool operator!=(const TrackEventDefaults& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_track_uuid() const { return _has_field_[11]; }
+ uint64_t track_uuid() const { return track_uuid_; }
+ void set_track_uuid(uint64_t value) { track_uuid_ = value; _has_field_.set(11); }
+
+ const std::vector<uint64_t>& extra_counter_track_uuids() const { return extra_counter_track_uuids_; }
+ std::vector<uint64_t>* mutable_extra_counter_track_uuids() { return &extra_counter_track_uuids_; }
+ int extra_counter_track_uuids_size() const { return static_cast<int>(extra_counter_track_uuids_.size()); }
+ void clear_extra_counter_track_uuids() { extra_counter_track_uuids_.clear(); }
+ void add_extra_counter_track_uuids(uint64_t value) { extra_counter_track_uuids_.emplace_back(value); }
+ uint64_t* add_extra_counter_track_uuids() { extra_counter_track_uuids_.emplace_back(); return &extra_counter_track_uuids_.back(); }
+
+ const std::vector<uint64_t>& extra_double_counter_track_uuids() const { return extra_double_counter_track_uuids_; }
+ std::vector<uint64_t>* mutable_extra_double_counter_track_uuids() { return &extra_double_counter_track_uuids_; }
+ int extra_double_counter_track_uuids_size() const { return static_cast<int>(extra_double_counter_track_uuids_.size()); }
+ void clear_extra_double_counter_track_uuids() { extra_double_counter_track_uuids_.clear(); }
+ void add_extra_double_counter_track_uuids(uint64_t value) { extra_double_counter_track_uuids_.emplace_back(value); }
+ uint64_t* add_extra_double_counter_track_uuids() { extra_double_counter_track_uuids_.emplace_back(); return &extra_double_counter_track_uuids_.back(); }
+
+ private:
+ uint64_t track_uuid_{};
+ std::vector<uint64_t> extra_counter_track_uuids_;
+ std::vector<uint64_t> extra_double_counter_track_uuids_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<46> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TrackEvent : public ::protozero::CppMessageObj {
+ public:
+ using LegacyEvent = TrackEvent_LegacyEvent;
+ using Type = TrackEvent_Type;
+ static constexpr auto TYPE_UNSPECIFIED = TrackEvent_Type_TYPE_UNSPECIFIED;
+ static constexpr auto TYPE_SLICE_BEGIN = TrackEvent_Type_TYPE_SLICE_BEGIN;
+ static constexpr auto TYPE_SLICE_END = TrackEvent_Type_TYPE_SLICE_END;
+ static constexpr auto TYPE_INSTANT = TrackEvent_Type_TYPE_INSTANT;
+ static constexpr auto TYPE_COUNTER = TrackEvent_Type_TYPE_COUNTER;
+ static constexpr auto Type_MIN = TrackEvent_Type_TYPE_UNSPECIFIED;
+ static constexpr auto Type_MAX = TrackEvent_Type_TYPE_COUNTER;
+ enum FieldNumbers {
+ kCategoryIidsFieldNumber = 3,
+ kCategoriesFieldNumber = 22,
+ kNameIidFieldNumber = 10,
+ kNameFieldNumber = 23,
+ kTypeFieldNumber = 9,
+ kTrackUuidFieldNumber = 11,
+ kCounterValueFieldNumber = 30,
+ kDoubleCounterValueFieldNumber = 44,
+ kExtraCounterTrackUuidsFieldNumber = 31,
+ kExtraCounterValuesFieldNumber = 12,
+ kExtraDoubleCounterTrackUuidsFieldNumber = 45,
+ kExtraDoubleCounterValuesFieldNumber = 46,
+ kFlowIdsOldFieldNumber = 36,
+ kFlowIdsFieldNumber = 47,
+ kTerminatingFlowIdsOldFieldNumber = 42,
+ kTerminatingFlowIdsFieldNumber = 48,
+ kDebugAnnotationsFieldNumber = 4,
+ kTaskExecutionFieldNumber = 5,
+ kLogMessageFieldNumber = 21,
+ kCcSchedulerStateFieldNumber = 24,
+ kChromeUserEventFieldNumber = 25,
+ kChromeKeyedServiceFieldNumber = 26,
+ kChromeLegacyIpcFieldNumber = 27,
+ kChromeHistogramSampleFieldNumber = 28,
+ kChromeLatencyInfoFieldNumber = 29,
+ kChromeFrameReporterFieldNumber = 32,
+ kChromeApplicationStateInfoFieldNumber = 39,
+ kChromeRendererSchedulerStateFieldNumber = 40,
+ kChromeWindowHandleEventInfoFieldNumber = 41,
+ kChromeContentSettingsEventInfoFieldNumber = 43,
+ kChromeActiveProcessesFieldNumber = 49,
+ kScreenshotFieldNumber = 50,
+ kPixelModemEventInsightFieldNumber = 51,
+ kSourceLocationFieldNumber = 33,
+ kSourceLocationIidFieldNumber = 34,
+ kChromeMessagePumpFieldNumber = 35,
+ kChromeMojoEventInfoFieldNumber = 38,
+ kTimestampDeltaUsFieldNumber = 1,
+ kTimestampAbsoluteUsFieldNumber = 16,
+ kThreadTimeDeltaUsFieldNumber = 2,
+ kThreadTimeAbsoluteUsFieldNumber = 17,
+ kThreadInstructionCountDeltaFieldNumber = 8,
+ kThreadInstructionCountAbsoluteFieldNumber = 20,
+ kLegacyEventFieldNumber = 6,
+ };
+
+ TrackEvent();
+ ~TrackEvent() override;
+ TrackEvent(TrackEvent&&) noexcept;
+ TrackEvent& operator=(TrackEvent&&);
+ TrackEvent(const TrackEvent&);
+ TrackEvent& operator=(const TrackEvent&);
+ bool operator==(const TrackEvent&) const;
+ bool operator!=(const TrackEvent& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<uint64_t>& category_iids() const { return category_iids_; }
+ std::vector<uint64_t>* mutable_category_iids() { return &category_iids_; }
+ int category_iids_size() const { return static_cast<int>(category_iids_.size()); }
+ void clear_category_iids() { category_iids_.clear(); }
+ void add_category_iids(uint64_t value) { category_iids_.emplace_back(value); }
+ uint64_t* add_category_iids() { category_iids_.emplace_back(); return &category_iids_.back(); }
+
+ const std::vector<std::string>& categories() const { return categories_; }
+ std::vector<std::string>* mutable_categories() { return &categories_; }
+ int categories_size() const { return static_cast<int>(categories_.size()); }
+ void clear_categories() { categories_.clear(); }
+ void add_categories(std::string value) { categories_.emplace_back(value); }
+ std::string* add_categories() { categories_.emplace_back(); return &categories_.back(); }
+
+ bool has_name_iid() const { return _has_field_[10]; }
+ uint64_t name_iid() const { return name_iid_; }
+ void set_name_iid(uint64_t value) { name_iid_ = value; _has_field_.set(10); }
+
+ bool has_name() const { return _has_field_[23]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(23); }
+
+ bool has_type() const { return _has_field_[9]; }
+ TrackEvent_Type type() const { return type_; }
+ void set_type(TrackEvent_Type value) { type_ = value; _has_field_.set(9); }
+
+ bool has_track_uuid() const { return _has_field_[11]; }
+ uint64_t track_uuid() const { return track_uuid_; }
+ void set_track_uuid(uint64_t value) { track_uuid_ = value; _has_field_.set(11); }
+
+ bool has_counter_value() const { return _has_field_[30]; }
+ int64_t counter_value() const { return counter_value_; }
+ void set_counter_value(int64_t value) { counter_value_ = value; _has_field_.set(30); }
+
+ bool has_double_counter_value() const { return _has_field_[44]; }
+ double double_counter_value() const { return double_counter_value_; }
+ void set_double_counter_value(double value) { double_counter_value_ = value; _has_field_.set(44); }
+
+ const std::vector<uint64_t>& extra_counter_track_uuids() const { return extra_counter_track_uuids_; }
+ std::vector<uint64_t>* mutable_extra_counter_track_uuids() { return &extra_counter_track_uuids_; }
+ int extra_counter_track_uuids_size() const { return static_cast<int>(extra_counter_track_uuids_.size()); }
+ void clear_extra_counter_track_uuids() { extra_counter_track_uuids_.clear(); }
+ void add_extra_counter_track_uuids(uint64_t value) { extra_counter_track_uuids_.emplace_back(value); }
+ uint64_t* add_extra_counter_track_uuids() { extra_counter_track_uuids_.emplace_back(); return &extra_counter_track_uuids_.back(); }
+
+ const std::vector<int64_t>& extra_counter_values() const { return extra_counter_values_; }
+ std::vector<int64_t>* mutable_extra_counter_values() { return &extra_counter_values_; }
+ int extra_counter_values_size() const { return static_cast<int>(extra_counter_values_.size()); }
+ void clear_extra_counter_values() { extra_counter_values_.clear(); }
+ void add_extra_counter_values(int64_t value) { extra_counter_values_.emplace_back(value); }
+ int64_t* add_extra_counter_values() { extra_counter_values_.emplace_back(); return &extra_counter_values_.back(); }
+
+ const std::vector<uint64_t>& extra_double_counter_track_uuids() const { return extra_double_counter_track_uuids_; }
+ std::vector<uint64_t>* mutable_extra_double_counter_track_uuids() { return &extra_double_counter_track_uuids_; }
+ int extra_double_counter_track_uuids_size() const { return static_cast<int>(extra_double_counter_track_uuids_.size()); }
+ void clear_extra_double_counter_track_uuids() { extra_double_counter_track_uuids_.clear(); }
+ void add_extra_double_counter_track_uuids(uint64_t value) { extra_double_counter_track_uuids_.emplace_back(value); }
+ uint64_t* add_extra_double_counter_track_uuids() { extra_double_counter_track_uuids_.emplace_back(); return &extra_double_counter_track_uuids_.back(); }
+
+ const std::vector<double>& extra_double_counter_values() const { return extra_double_counter_values_; }
+ std::vector<double>* mutable_extra_double_counter_values() { return &extra_double_counter_values_; }
+ int extra_double_counter_values_size() const { return static_cast<int>(extra_double_counter_values_.size()); }
+ void clear_extra_double_counter_values() { extra_double_counter_values_.clear(); }
+ void add_extra_double_counter_values(double value) { extra_double_counter_values_.emplace_back(value); }
+ double* add_extra_double_counter_values() { extra_double_counter_values_.emplace_back(); return &extra_double_counter_values_.back(); }
+
+ const std::vector<uint64_t>& flow_ids_old() const { return flow_ids_old_; }
+ std::vector<uint64_t>* mutable_flow_ids_old() { return &flow_ids_old_; }
+ int flow_ids_old_size() const { return static_cast<int>(flow_ids_old_.size()); }
+ void clear_flow_ids_old() { flow_ids_old_.clear(); }
+ void add_flow_ids_old(uint64_t value) { flow_ids_old_.emplace_back(value); }
+ uint64_t* add_flow_ids_old() { flow_ids_old_.emplace_back(); return &flow_ids_old_.back(); }
+
+ const std::vector<uint64_t>& flow_ids() const { return flow_ids_; }
+ std::vector<uint64_t>* mutable_flow_ids() { return &flow_ids_; }
+ int flow_ids_size() const { return static_cast<int>(flow_ids_.size()); }
+ void clear_flow_ids() { flow_ids_.clear(); }
+ void add_flow_ids(uint64_t value) { flow_ids_.emplace_back(value); }
+ uint64_t* add_flow_ids() { flow_ids_.emplace_back(); return &flow_ids_.back(); }
+
+ const std::vector<uint64_t>& terminating_flow_ids_old() const { return terminating_flow_ids_old_; }
+ std::vector<uint64_t>* mutable_terminating_flow_ids_old() { return &terminating_flow_ids_old_; }
+ int terminating_flow_ids_old_size() const { return static_cast<int>(terminating_flow_ids_old_.size()); }
+ void clear_terminating_flow_ids_old() { terminating_flow_ids_old_.clear(); }
+ void add_terminating_flow_ids_old(uint64_t value) { terminating_flow_ids_old_.emplace_back(value); }
+ uint64_t* add_terminating_flow_ids_old() { terminating_flow_ids_old_.emplace_back(); return &terminating_flow_ids_old_.back(); }
+
+ const std::vector<uint64_t>& terminating_flow_ids() const { return terminating_flow_ids_; }
+ std::vector<uint64_t>* mutable_terminating_flow_ids() { return &terminating_flow_ids_; }
+ int terminating_flow_ids_size() const { return static_cast<int>(terminating_flow_ids_.size()); }
+ void clear_terminating_flow_ids() { terminating_flow_ids_.clear(); }
+ void add_terminating_flow_ids(uint64_t value) { terminating_flow_ids_.emplace_back(value); }
+ uint64_t* add_terminating_flow_ids() { terminating_flow_ids_.emplace_back(); return &terminating_flow_ids_.back(); }
+
+ const std::vector<DebugAnnotation>& debug_annotations() const { return debug_annotations_; }
+ std::vector<DebugAnnotation>* mutable_debug_annotations() { return &debug_annotations_; }
+ int debug_annotations_size() const;
+ void clear_debug_annotations();
+ DebugAnnotation* add_debug_annotations();
+
+ bool has_task_execution() const { return _has_field_[5]; }
+ const TaskExecution& task_execution() const { return *task_execution_; }
+ TaskExecution* mutable_task_execution() { _has_field_.set(5); return task_execution_.get(); }
+
+ bool has_log_message() const { return _has_field_[21]; }
+ const LogMessage& log_message() const { return *log_message_; }
+ LogMessage* mutable_log_message() { _has_field_.set(21); return log_message_.get(); }
+
+ bool has_cc_scheduler_state() const { return _has_field_[24]; }
+ const ChromeCompositorSchedulerState& cc_scheduler_state() const { return *cc_scheduler_state_; }
+ ChromeCompositorSchedulerState* mutable_cc_scheduler_state() { _has_field_.set(24); return cc_scheduler_state_.get(); }
+
+ bool has_chrome_user_event() const { return _has_field_[25]; }
+ const ChromeUserEvent& chrome_user_event() const { return *chrome_user_event_; }
+ ChromeUserEvent* mutable_chrome_user_event() { _has_field_.set(25); return chrome_user_event_.get(); }
+
+ bool has_chrome_keyed_service() const { return _has_field_[26]; }
+ const ChromeKeyedService& chrome_keyed_service() const { return *chrome_keyed_service_; }
+ ChromeKeyedService* mutable_chrome_keyed_service() { _has_field_.set(26); return chrome_keyed_service_.get(); }
+
+ bool has_chrome_legacy_ipc() const { return _has_field_[27]; }
+ const ChromeLegacyIpc& chrome_legacy_ipc() const { return *chrome_legacy_ipc_; }
+ ChromeLegacyIpc* mutable_chrome_legacy_ipc() { _has_field_.set(27); return chrome_legacy_ipc_.get(); }
+
+ bool has_chrome_histogram_sample() const { return _has_field_[28]; }
+ const ChromeHistogramSample& chrome_histogram_sample() const { return *chrome_histogram_sample_; }
+ ChromeHistogramSample* mutable_chrome_histogram_sample() { _has_field_.set(28); return chrome_histogram_sample_.get(); }
+
+ bool has_chrome_latency_info() const { return _has_field_[29]; }
+ const ChromeLatencyInfo& chrome_latency_info() const { return *chrome_latency_info_; }
+ ChromeLatencyInfo* mutable_chrome_latency_info() { _has_field_.set(29); return chrome_latency_info_.get(); }
+
+ bool has_chrome_frame_reporter() const { return _has_field_[32]; }
+ const ChromeFrameReporter& chrome_frame_reporter() const { return *chrome_frame_reporter_; }
+ ChromeFrameReporter* mutable_chrome_frame_reporter() { _has_field_.set(32); return chrome_frame_reporter_.get(); }
+
+ bool has_chrome_application_state_info() const { return _has_field_[39]; }
+ const ChromeApplicationStateInfo& chrome_application_state_info() const { return *chrome_application_state_info_; }
+ ChromeApplicationStateInfo* mutable_chrome_application_state_info() { _has_field_.set(39); return chrome_application_state_info_.get(); }
+
+ bool has_chrome_renderer_scheduler_state() const { return _has_field_[40]; }
+ const ChromeRendererSchedulerState& chrome_renderer_scheduler_state() const { return *chrome_renderer_scheduler_state_; }
+ ChromeRendererSchedulerState* mutable_chrome_renderer_scheduler_state() { _has_field_.set(40); return chrome_renderer_scheduler_state_.get(); }
+
+ bool has_chrome_window_handle_event_info() const { return _has_field_[41]; }
+ const ChromeWindowHandleEventInfo& chrome_window_handle_event_info() const { return *chrome_window_handle_event_info_; }
+ ChromeWindowHandleEventInfo* mutable_chrome_window_handle_event_info() { _has_field_.set(41); return chrome_window_handle_event_info_.get(); }
+
+ bool has_chrome_content_settings_event_info() const { return _has_field_[43]; }
+ const ChromeContentSettingsEventInfo& chrome_content_settings_event_info() const { return *chrome_content_settings_event_info_; }
+ ChromeContentSettingsEventInfo* mutable_chrome_content_settings_event_info() { _has_field_.set(43); return chrome_content_settings_event_info_.get(); }
+
+ bool has_chrome_active_processes() const { return _has_field_[49]; }
+ const ChromeActiveProcesses& chrome_active_processes() const { return *chrome_active_processes_; }
+ ChromeActiveProcesses* mutable_chrome_active_processes() { _has_field_.set(49); return chrome_active_processes_.get(); }
+
+ bool has_screenshot() const { return _has_field_[50]; }
+ const Screenshot& screenshot() const { return *screenshot_; }
+ Screenshot* mutable_screenshot() { _has_field_.set(50); return screenshot_.get(); }
+
+ bool has_pixel_modem_event_insight() const { return _has_field_[51]; }
+ const PixelModemEventInsight& pixel_modem_event_insight() const { return *pixel_modem_event_insight_; }
+ PixelModemEventInsight* mutable_pixel_modem_event_insight() { _has_field_.set(51); return pixel_modem_event_insight_.get(); }
+
+ bool has_source_location() const { return _has_field_[33]; }
+ const SourceLocation& source_location() const { return *source_location_; }
+ SourceLocation* mutable_source_location() { _has_field_.set(33); return source_location_.get(); }
+
+ bool has_source_location_iid() const { return _has_field_[34]; }
+ uint64_t source_location_iid() const { return source_location_iid_; }
+ void set_source_location_iid(uint64_t value) { source_location_iid_ = value; _has_field_.set(34); }
+
+ bool has_chrome_message_pump() const { return _has_field_[35]; }
+ const ChromeMessagePump& chrome_message_pump() const { return *chrome_message_pump_; }
+ ChromeMessagePump* mutable_chrome_message_pump() { _has_field_.set(35); return chrome_message_pump_.get(); }
+
+ bool has_chrome_mojo_event_info() const { return _has_field_[38]; }
+ const ChromeMojoEventInfo& chrome_mojo_event_info() const { return *chrome_mojo_event_info_; }
+ ChromeMojoEventInfo* mutable_chrome_mojo_event_info() { _has_field_.set(38); return chrome_mojo_event_info_.get(); }
+
+ bool has_timestamp_delta_us() const { return _has_field_[1]; }
+ int64_t timestamp_delta_us() const { return timestamp_delta_us_; }
+ void set_timestamp_delta_us(int64_t value) { timestamp_delta_us_ = value; _has_field_.set(1); }
+
+ bool has_timestamp_absolute_us() const { return _has_field_[16]; }
+ int64_t timestamp_absolute_us() const { return timestamp_absolute_us_; }
+ void set_timestamp_absolute_us(int64_t value) { timestamp_absolute_us_ = value; _has_field_.set(16); }
+
+ bool has_thread_time_delta_us() const { return _has_field_[2]; }
+ int64_t thread_time_delta_us() const { return thread_time_delta_us_; }
+ void set_thread_time_delta_us(int64_t value) { thread_time_delta_us_ = value; _has_field_.set(2); }
+
+ bool has_thread_time_absolute_us() const { return _has_field_[17]; }
+ int64_t thread_time_absolute_us() const { return thread_time_absolute_us_; }
+ void set_thread_time_absolute_us(int64_t value) { thread_time_absolute_us_ = value; _has_field_.set(17); }
+
+ bool has_thread_instruction_count_delta() const { return _has_field_[8]; }
+ int64_t thread_instruction_count_delta() const { return thread_instruction_count_delta_; }
+ void set_thread_instruction_count_delta(int64_t value) { thread_instruction_count_delta_ = value; _has_field_.set(8); }
+
+ bool has_thread_instruction_count_absolute() const { return _has_field_[20]; }
+ int64_t thread_instruction_count_absolute() const { return thread_instruction_count_absolute_; }
+ void set_thread_instruction_count_absolute(int64_t value) { thread_instruction_count_absolute_ = value; _has_field_.set(20); }
+
+ bool has_legacy_event() const { return _has_field_[6]; }
+ const TrackEvent_LegacyEvent& legacy_event() const { return *legacy_event_; }
+ TrackEvent_LegacyEvent* mutable_legacy_event() { _has_field_.set(6); return legacy_event_.get(); }
+
+ private:
+ std::vector<uint64_t> category_iids_;
+ std::vector<std::string> categories_;
+ uint64_t name_iid_{};
+ std::string name_{};
+ TrackEvent_Type type_{};
+ uint64_t track_uuid_{};
+ int64_t counter_value_{};
+ double double_counter_value_{};
+ std::vector<uint64_t> extra_counter_track_uuids_;
+ std::vector<int64_t> extra_counter_values_;
+ std::vector<uint64_t> extra_double_counter_track_uuids_;
+ std::vector<double> extra_double_counter_values_;
+ std::vector<uint64_t> flow_ids_old_;
+ std::vector<uint64_t> flow_ids_;
+ std::vector<uint64_t> terminating_flow_ids_old_;
+ std::vector<uint64_t> terminating_flow_ids_;
+ std::vector<DebugAnnotation> debug_annotations_;
+ ::protozero::CopyablePtr<TaskExecution> task_execution_;
+ ::protozero::CopyablePtr<LogMessage> log_message_;
+ ::protozero::CopyablePtr<ChromeCompositorSchedulerState> cc_scheduler_state_;
+ ::protozero::CopyablePtr<ChromeUserEvent> chrome_user_event_;
+ ::protozero::CopyablePtr<ChromeKeyedService> chrome_keyed_service_;
+ ::protozero::CopyablePtr<ChromeLegacyIpc> chrome_legacy_ipc_;
+ ::protozero::CopyablePtr<ChromeHistogramSample> chrome_histogram_sample_;
+ ::protozero::CopyablePtr<ChromeLatencyInfo> chrome_latency_info_;
+ ::protozero::CopyablePtr<ChromeFrameReporter> chrome_frame_reporter_;
+ ::protozero::CopyablePtr<ChromeApplicationStateInfo> chrome_application_state_info_;
+ ::protozero::CopyablePtr<ChromeRendererSchedulerState> chrome_renderer_scheduler_state_;
+ ::protozero::CopyablePtr<ChromeWindowHandleEventInfo> chrome_window_handle_event_info_;
+ ::protozero::CopyablePtr<ChromeContentSettingsEventInfo> chrome_content_settings_event_info_;
+ ::protozero::CopyablePtr<ChromeActiveProcesses> chrome_active_processes_;
+ ::protozero::CopyablePtr<Screenshot> screenshot_;
+ ::protozero::CopyablePtr<PixelModemEventInsight> pixel_modem_event_insight_;
+ ::protozero::CopyablePtr<SourceLocation> source_location_;
+ uint64_t source_location_iid_{};
+ ::protozero::CopyablePtr<ChromeMessagePump> chrome_message_pump_;
+ ::protozero::CopyablePtr<ChromeMojoEventInfo> chrome_mojo_event_info_;
+ int64_t timestamp_delta_us_{};
+ int64_t timestamp_absolute_us_{};
+ int64_t thread_time_delta_us_{};
+ int64_t thread_time_absolute_us_{};
+ int64_t thread_instruction_count_delta_{};
+ int64_t thread_instruction_count_absolute_{};
+ ::protozero::CopyablePtr<TrackEvent_LegacyEvent> legacy_event_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<52> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT TrackEvent_LegacyEvent : public ::protozero::CppMessageObj {
+ public:
+ using FlowDirection = TrackEvent_LegacyEvent_FlowDirection;
+ static constexpr auto FLOW_UNSPECIFIED = TrackEvent_LegacyEvent_FlowDirection_FLOW_UNSPECIFIED;
+ static constexpr auto FLOW_IN = TrackEvent_LegacyEvent_FlowDirection_FLOW_IN;
+ static constexpr auto FLOW_OUT = TrackEvent_LegacyEvent_FlowDirection_FLOW_OUT;
+ static constexpr auto FLOW_INOUT = TrackEvent_LegacyEvent_FlowDirection_FLOW_INOUT;
+ static constexpr auto FlowDirection_MIN = TrackEvent_LegacyEvent_FlowDirection_FLOW_UNSPECIFIED;
+ static constexpr auto FlowDirection_MAX = TrackEvent_LegacyEvent_FlowDirection_FLOW_INOUT;
+ using InstantEventScope = TrackEvent_LegacyEvent_InstantEventScope;
+ static constexpr auto SCOPE_UNSPECIFIED = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_UNSPECIFIED;
+ static constexpr auto SCOPE_GLOBAL = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_GLOBAL;
+ static constexpr auto SCOPE_PROCESS = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_PROCESS;
+ static constexpr auto SCOPE_THREAD = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_THREAD;
+ static constexpr auto InstantEventScope_MIN = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_UNSPECIFIED;
+ static constexpr auto InstantEventScope_MAX = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_THREAD;
+ enum FieldNumbers {
+ kNameIidFieldNumber = 1,
+ kPhaseFieldNumber = 2,
+ kDurationUsFieldNumber = 3,
+ kThreadDurationUsFieldNumber = 4,
+ kThreadInstructionDeltaFieldNumber = 15,
+ kUnscopedIdFieldNumber = 6,
+ kLocalIdFieldNumber = 10,
+ kGlobalIdFieldNumber = 11,
+ kIdScopeFieldNumber = 7,
+ kUseAsyncTtsFieldNumber = 9,
+ kBindIdFieldNumber = 8,
+ kBindToEnclosingFieldNumber = 12,
+ kFlowDirectionFieldNumber = 13,
+ kInstantEventScopeFieldNumber = 14,
+ kPidOverrideFieldNumber = 18,
+ kTidOverrideFieldNumber = 19,
+ };
+
+ TrackEvent_LegacyEvent();
+ ~TrackEvent_LegacyEvent() override;
+ TrackEvent_LegacyEvent(TrackEvent_LegacyEvent&&) noexcept;
+ TrackEvent_LegacyEvent& operator=(TrackEvent_LegacyEvent&&);
+ TrackEvent_LegacyEvent(const TrackEvent_LegacyEvent&);
+ TrackEvent_LegacyEvent& operator=(const TrackEvent_LegacyEvent&);
+ bool operator==(const TrackEvent_LegacyEvent&) const;
+ bool operator!=(const TrackEvent_LegacyEvent& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_name_iid() const { return _has_field_[1]; }
+ uint64_t name_iid() const { return name_iid_; }
+ void set_name_iid(uint64_t value) { name_iid_ = value; _has_field_.set(1); }
+
+ bool has_phase() const { return _has_field_[2]; }
+ int32_t phase() const { return phase_; }
+ void set_phase(int32_t value) { phase_ = value; _has_field_.set(2); }
+
+ bool has_duration_us() const { return _has_field_[3]; }
+ int64_t duration_us() const { return duration_us_; }
+ void set_duration_us(int64_t value) { duration_us_ = value; _has_field_.set(3); }
+
+ bool has_thread_duration_us() const { return _has_field_[4]; }
+ int64_t thread_duration_us() const { return thread_duration_us_; }
+ void set_thread_duration_us(int64_t value) { thread_duration_us_ = value; _has_field_.set(4); }
+
+ bool has_thread_instruction_delta() const { return _has_field_[15]; }
+ int64_t thread_instruction_delta() const { return thread_instruction_delta_; }
+ void set_thread_instruction_delta(int64_t value) { thread_instruction_delta_ = value; _has_field_.set(15); }
+
+ bool has_unscoped_id() const { return _has_field_[6]; }
+ uint64_t unscoped_id() const { return unscoped_id_; }
+ void set_unscoped_id(uint64_t value) { unscoped_id_ = value; _has_field_.set(6); }
+
+ bool has_local_id() const { return _has_field_[10]; }
+ uint64_t local_id() const { return local_id_; }
+ void set_local_id(uint64_t value) { local_id_ = value; _has_field_.set(10); }
+
+ bool has_global_id() const { return _has_field_[11]; }
+ uint64_t global_id() const { return global_id_; }
+ void set_global_id(uint64_t value) { global_id_ = value; _has_field_.set(11); }
+
+ bool has_id_scope() const { return _has_field_[7]; }
+ const std::string& id_scope() const { return id_scope_; }
+ void set_id_scope(const std::string& value) { id_scope_ = value; _has_field_.set(7); }
+
+ bool has_use_async_tts() const { return _has_field_[9]; }
+ bool use_async_tts() const { return use_async_tts_; }
+ void set_use_async_tts(bool value) { use_async_tts_ = value; _has_field_.set(9); }
+
+ bool has_bind_id() const { return _has_field_[8]; }
+ uint64_t bind_id() const { return bind_id_; }
+ void set_bind_id(uint64_t value) { bind_id_ = value; _has_field_.set(8); }
+
+ bool has_bind_to_enclosing() const { return _has_field_[12]; }
+ bool bind_to_enclosing() const { return bind_to_enclosing_; }
+ void set_bind_to_enclosing(bool value) { bind_to_enclosing_ = value; _has_field_.set(12); }
+
+ bool has_flow_direction() const { return _has_field_[13]; }
+ TrackEvent_LegacyEvent_FlowDirection flow_direction() const { return flow_direction_; }
+ void set_flow_direction(TrackEvent_LegacyEvent_FlowDirection value) { flow_direction_ = value; _has_field_.set(13); }
+
+ bool has_instant_event_scope() const { return _has_field_[14]; }
+ TrackEvent_LegacyEvent_InstantEventScope instant_event_scope() const { return instant_event_scope_; }
+ void set_instant_event_scope(TrackEvent_LegacyEvent_InstantEventScope value) { instant_event_scope_ = value; _has_field_.set(14); }
+
+ bool has_pid_override() const { return _has_field_[18]; }
+ int32_t pid_override() const { return pid_override_; }
+ void set_pid_override(int32_t value) { pid_override_ = value; _has_field_.set(18); }
+
+ bool has_tid_override() const { return _has_field_[19]; }
+ int32_t tid_override() const { return tid_override_; }
+ void set_tid_override(int32_t value) { tid_override_ = value; _has_field_.set(19); }
+
+ private:
+ uint64_t name_iid_{};
+ int32_t phase_{};
+ int64_t duration_us_{};
+ int64_t thread_duration_us_{};
+ int64_t thread_instruction_delta_{};
+ uint64_t unscoped_id_{};
+ uint64_t local_id_{};
+ uint64_t global_id_{};
+ std::string id_scope_{};
+ bool use_async_tts_{};
+ uint64_t bind_id_{};
+ bool bind_to_enclosing_{};
+ TrackEvent_LegacyEvent_FlowDirection flow_direction_{};
+ TrackEvent_LegacyEvent_InstantEventScope instant_event_scope_{};
+ int32_t pid_override_{};
+ int32_t tid_override_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<20> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/ipc/consumer_port.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_CONSUMER_PORT_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_CONSUMER_PORT_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class CloneSessionResponse;
+class CloneSessionRequest;
+class SaveTraceForBugreportResponse;
+class SaveTraceForBugreportRequest;
+class QueryCapabilitiesResponse;
+class TracingServiceCapabilities;
+class QueryCapabilitiesRequest;
+class QueryServiceStateResponse;
+class TracingServiceState;
+class TracingServiceState_TracingSession;
+class TracingServiceState_DataSource;
+class DataSourceDescriptor;
+class TracingServiceState_Producer;
+class QueryServiceStateRequest;
+class ObserveEventsResponse;
+class ObservableEvents;
+class ObservableEvents_CloneTriggerHit;
+class ObservableEvents_DataSourceInstanceStateChange;
+class ObserveEventsRequest;
+class GetTraceStatsResponse;
+class TraceStats;
+class TraceStats_FilterStats;
+class TraceStats_WriterStats;
+class TraceStats_BufferStats;
+class GetTraceStatsRequest;
+class AttachResponse;
+class TraceConfig;
+class TraceConfig_CmdTraceStartDelay;
+class TraceConfig_AndroidReportConfig;
+class TraceConfig_TraceFilter;
+class TraceConfig_TraceFilter_StringFilterChain;
+class TraceConfig_TraceFilter_StringFilterRule;
+class TraceConfig_IncidentReportConfig;
+class TraceConfig_IncrementalStateConfig;
+class TraceConfig_TriggerConfig;
+class TraceConfig_TriggerConfig_Trigger;
+class TraceConfig_GuardrailOverrides;
+class TraceConfig_StatsdMetadata;
+class TraceConfig_ProducerConfig;
+class TraceConfig_BuiltinDataSource;
+class TraceConfig_DataSource;
+class DataSourceConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+class InterceptorConfig;
+class ConsoleConfig;
+class ChromeConfig;
+class SystemInfoConfig;
+class TraceConfig_BufferConfig;
+class AttachRequest;
+class DetachResponse;
+class DetachRequest;
+class FlushResponse;
+class FlushRequest;
+class FreeBuffersResponse;
+class FreeBuffersRequest;
+class ReadBuffersResponse;
+class ReadBuffersResponse_Slice;
+class ReadBuffersRequest;
+class DisableTracingResponse;
+class DisableTracingRequest;
+class ChangeTraceConfigResponse;
+class ChangeTraceConfigRequest;
+class StartTracingResponse;
+class StartTracingRequest;
+class EnableTracingResponse;
+class EnableTracingRequest;
+enum ObservableEvents_Type : int;
+enum ObservableEvents_DataSourceInstanceState : int;
+enum TraceStats_FinalFlushOutcome : int;
+enum TraceConfig_LockdownModeOperation : int;
+enum TraceConfig_CompressionType : int;
+enum TraceConfig_StatsdLogging : int;
+enum TraceConfig_TraceFilter_StringFilterPolicy : int;
+enum TraceConfig_TriggerConfig_TriggerMode : int;
+enum BuiltinClock : int;
+enum DataSourceConfig_SessionInitiator : int;
+enum ConsoleConfig_Output : int;
+enum ChromeConfig_ClientPriority : int;
+enum TraceConfig_BufferConfig_FillPolicy : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT CloneSessionResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSuccessFieldNumber = 1,
+ kErrorFieldNumber = 2,
+ kUuidMsbFieldNumber = 3,
+ kUuidLsbFieldNumber = 4,
+ };
+
+ CloneSessionResponse();
+ ~CloneSessionResponse() override;
+ CloneSessionResponse(CloneSessionResponse&&) noexcept;
+ CloneSessionResponse& operator=(CloneSessionResponse&&);
+ CloneSessionResponse(const CloneSessionResponse&);
+ CloneSessionResponse& operator=(const CloneSessionResponse&);
+ bool operator==(const CloneSessionResponse&) const;
+ bool operator!=(const CloneSessionResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_success() const { return _has_field_[1]; }
+ bool success() const { return success_; }
+ void set_success(bool value) { success_ = value; _has_field_.set(1); }
+
+ bool has_error() const { return _has_field_[2]; }
+ const std::string& error() const { return error_; }
+ void set_error(const std::string& value) { error_ = value; _has_field_.set(2); }
+
+ bool has_uuid_msb() const { return _has_field_[3]; }
+ int64_t uuid_msb() const { return uuid_msb_; }
+ void set_uuid_msb(int64_t value) { uuid_msb_ = value; _has_field_.set(3); }
+
+ bool has_uuid_lsb() const { return _has_field_[4]; }
+ int64_t uuid_lsb() const { return uuid_lsb_; }
+ void set_uuid_lsb(int64_t value) { uuid_lsb_ = value; _has_field_.set(4); }
+
+ private:
+ bool success_{};
+ std::string error_{};
+ int64_t uuid_msb_{};
+ int64_t uuid_lsb_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT CloneSessionRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSessionIdFieldNumber = 1,
+ kSkipTraceFilterFieldNumber = 2,
+ kForBugreportFieldNumber = 3,
+ };
+
+ CloneSessionRequest();
+ ~CloneSessionRequest() override;
+ CloneSessionRequest(CloneSessionRequest&&) noexcept;
+ CloneSessionRequest& operator=(CloneSessionRequest&&);
+ CloneSessionRequest(const CloneSessionRequest&);
+ CloneSessionRequest& operator=(const CloneSessionRequest&);
+ bool operator==(const CloneSessionRequest&) const;
+ bool operator!=(const CloneSessionRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_session_id() const { return _has_field_[1]; }
+ uint64_t session_id() const { return session_id_; }
+ void set_session_id(uint64_t value) { session_id_ = value; _has_field_.set(1); }
+
+ bool has_skip_trace_filter() const { return _has_field_[2]; }
+ bool skip_trace_filter() const { return skip_trace_filter_; }
+ void set_skip_trace_filter(bool value) { skip_trace_filter_ = value; _has_field_.set(2); }
+
+ bool has_for_bugreport() const { return _has_field_[3]; }
+ bool for_bugreport() const { return for_bugreport_; }
+ void set_for_bugreport(bool value) { for_bugreport_ = value; _has_field_.set(3); }
+
+ private:
+ uint64_t session_id_{};
+ bool skip_trace_filter_{};
+ bool for_bugreport_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT SaveTraceForBugreportResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSuccessFieldNumber = 1,
+ kMsgFieldNumber = 2,
+ };
+
+ SaveTraceForBugreportResponse();
+ ~SaveTraceForBugreportResponse() override;
+ SaveTraceForBugreportResponse(SaveTraceForBugreportResponse&&) noexcept;
+ SaveTraceForBugreportResponse& operator=(SaveTraceForBugreportResponse&&);
+ SaveTraceForBugreportResponse(const SaveTraceForBugreportResponse&);
+ SaveTraceForBugreportResponse& operator=(const SaveTraceForBugreportResponse&);
+ bool operator==(const SaveTraceForBugreportResponse&) const;
+ bool operator!=(const SaveTraceForBugreportResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_success() const { return _has_field_[1]; }
+ bool success() const { return success_; }
+ void set_success(bool value) { success_ = value; _has_field_.set(1); }
+
+ bool has_msg() const { return _has_field_[2]; }
+ const std::string& msg() const { return msg_; }
+ void set_msg(const std::string& value) { msg_ = value; _has_field_.set(2); }
+
+ private:
+ bool success_{};
+ std::string msg_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT SaveTraceForBugreportRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ SaveTraceForBugreportRequest();
+ ~SaveTraceForBugreportRequest() override;
+ SaveTraceForBugreportRequest(SaveTraceForBugreportRequest&&) noexcept;
+ SaveTraceForBugreportRequest& operator=(SaveTraceForBugreportRequest&&);
+ SaveTraceForBugreportRequest(const SaveTraceForBugreportRequest&);
+ SaveTraceForBugreportRequest& operator=(const SaveTraceForBugreportRequest&);
+ bool operator==(const SaveTraceForBugreportRequest&) const;
+ bool operator!=(const SaveTraceForBugreportRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT QueryCapabilitiesResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kCapabilitiesFieldNumber = 1,
+ };
+
+ QueryCapabilitiesResponse();
+ ~QueryCapabilitiesResponse() override;
+ QueryCapabilitiesResponse(QueryCapabilitiesResponse&&) noexcept;
+ QueryCapabilitiesResponse& operator=(QueryCapabilitiesResponse&&);
+ QueryCapabilitiesResponse(const QueryCapabilitiesResponse&);
+ QueryCapabilitiesResponse& operator=(const QueryCapabilitiesResponse&);
+ bool operator==(const QueryCapabilitiesResponse&) const;
+ bool operator!=(const QueryCapabilitiesResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_capabilities() const { return _has_field_[1]; }
+ const TracingServiceCapabilities& capabilities() const { return *capabilities_; }
+ TracingServiceCapabilities* mutable_capabilities() { _has_field_.set(1); return capabilities_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<TracingServiceCapabilities> capabilities_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT QueryCapabilitiesRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ QueryCapabilitiesRequest();
+ ~QueryCapabilitiesRequest() override;
+ QueryCapabilitiesRequest(QueryCapabilitiesRequest&&) noexcept;
+ QueryCapabilitiesRequest& operator=(QueryCapabilitiesRequest&&);
+ QueryCapabilitiesRequest(const QueryCapabilitiesRequest&);
+ QueryCapabilitiesRequest& operator=(const QueryCapabilitiesRequest&);
+ bool operator==(const QueryCapabilitiesRequest&) const;
+ bool operator!=(const QueryCapabilitiesRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT QueryServiceStateResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kServiceStateFieldNumber = 1,
+ };
+
+ QueryServiceStateResponse();
+ ~QueryServiceStateResponse() override;
+ QueryServiceStateResponse(QueryServiceStateResponse&&) noexcept;
+ QueryServiceStateResponse& operator=(QueryServiceStateResponse&&);
+ QueryServiceStateResponse(const QueryServiceStateResponse&);
+ QueryServiceStateResponse& operator=(const QueryServiceStateResponse&);
+ bool operator==(const QueryServiceStateResponse&) const;
+ bool operator!=(const QueryServiceStateResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_service_state() const { return _has_field_[1]; }
+ const TracingServiceState& service_state() const { return *service_state_; }
+ TracingServiceState* mutable_service_state() { _has_field_.set(1); return service_state_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<TracingServiceState> service_state_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT QueryServiceStateRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSessionsOnlyFieldNumber = 1,
+ };
+
+ QueryServiceStateRequest();
+ ~QueryServiceStateRequest() override;
+ QueryServiceStateRequest(QueryServiceStateRequest&&) noexcept;
+ QueryServiceStateRequest& operator=(QueryServiceStateRequest&&);
+ QueryServiceStateRequest(const QueryServiceStateRequest&);
+ QueryServiceStateRequest& operator=(const QueryServiceStateRequest&);
+ bool operator==(const QueryServiceStateRequest&) const;
+ bool operator!=(const QueryServiceStateRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_sessions_only() const { return _has_field_[1]; }
+ bool sessions_only() const { return sessions_only_; }
+ void set_sessions_only(bool value) { sessions_only_ = value; _has_field_.set(1); }
+
+ private:
+ bool sessions_only_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ObserveEventsResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kEventsFieldNumber = 1,
+ };
+
+ ObserveEventsResponse();
+ ~ObserveEventsResponse() override;
+ ObserveEventsResponse(ObserveEventsResponse&&) noexcept;
+ ObserveEventsResponse& operator=(ObserveEventsResponse&&);
+ ObserveEventsResponse(const ObserveEventsResponse&);
+ ObserveEventsResponse& operator=(const ObserveEventsResponse&);
+ bool operator==(const ObserveEventsResponse&) const;
+ bool operator!=(const ObserveEventsResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_events() const { return _has_field_[1]; }
+ const ObservableEvents& events() const { return *events_; }
+ ObservableEvents* mutable_events() { _has_field_.set(1); return events_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<ObservableEvents> events_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ObserveEventsRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kEventsToObserveFieldNumber = 1,
+ };
+
+ ObserveEventsRequest();
+ ~ObserveEventsRequest() override;
+ ObserveEventsRequest(ObserveEventsRequest&&) noexcept;
+ ObserveEventsRequest& operator=(ObserveEventsRequest&&);
+ ObserveEventsRequest(const ObserveEventsRequest&);
+ ObserveEventsRequest& operator=(const ObserveEventsRequest&);
+ bool operator==(const ObserveEventsRequest&) const;
+ bool operator!=(const ObserveEventsRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<ObservableEvents_Type>& events_to_observe() const { return events_to_observe_; }
+ std::vector<ObservableEvents_Type>* mutable_events_to_observe() { return &events_to_observe_; }
+ int events_to_observe_size() const { return static_cast<int>(events_to_observe_.size()); }
+ void clear_events_to_observe() { events_to_observe_.clear(); }
+ void add_events_to_observe(ObservableEvents_Type value) { events_to_observe_.emplace_back(value); }
+ ObservableEvents_Type* add_events_to_observe() { events_to_observe_.emplace_back(); return &events_to_observe_.back(); }
+
+ private:
+ std::vector<ObservableEvents_Type> events_to_observe_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetTraceStatsResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTraceStatsFieldNumber = 1,
+ };
+
+ GetTraceStatsResponse();
+ ~GetTraceStatsResponse() override;
+ GetTraceStatsResponse(GetTraceStatsResponse&&) noexcept;
+ GetTraceStatsResponse& operator=(GetTraceStatsResponse&&);
+ GetTraceStatsResponse(const GetTraceStatsResponse&);
+ GetTraceStatsResponse& operator=(const GetTraceStatsResponse&);
+ bool operator==(const GetTraceStatsResponse&) const;
+ bool operator!=(const GetTraceStatsResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_stats() const { return _has_field_[1]; }
+ const TraceStats& trace_stats() const { return *trace_stats_; }
+ TraceStats* mutable_trace_stats() { _has_field_.set(1); return trace_stats_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<TraceStats> trace_stats_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetTraceStatsRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ GetTraceStatsRequest();
+ ~GetTraceStatsRequest() override;
+ GetTraceStatsRequest(GetTraceStatsRequest&&) noexcept;
+ GetTraceStatsRequest& operator=(GetTraceStatsRequest&&);
+ GetTraceStatsRequest(const GetTraceStatsRequest&);
+ GetTraceStatsRequest& operator=(const GetTraceStatsRequest&);
+ bool operator==(const GetTraceStatsRequest&) const;
+ bool operator!=(const GetTraceStatsRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT AttachResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTraceConfigFieldNumber = 1,
+ };
+
+ AttachResponse();
+ ~AttachResponse() override;
+ AttachResponse(AttachResponse&&) noexcept;
+ AttachResponse& operator=(AttachResponse&&);
+ AttachResponse(const AttachResponse&);
+ AttachResponse& operator=(const AttachResponse&);
+ bool operator==(const AttachResponse&) const;
+ bool operator!=(const AttachResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_config() const { return _has_field_[1]; }
+ const TraceConfig& trace_config() const { return *trace_config_; }
+ TraceConfig* mutable_trace_config() { _has_field_.set(1); return trace_config_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<TraceConfig> trace_config_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT AttachRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kKeyFieldNumber = 1,
+ };
+
+ AttachRequest();
+ ~AttachRequest() override;
+ AttachRequest(AttachRequest&&) noexcept;
+ AttachRequest& operator=(AttachRequest&&);
+ AttachRequest(const AttachRequest&);
+ AttachRequest& operator=(const AttachRequest&);
+ bool operator==(const AttachRequest&) const;
+ bool operator!=(const AttachRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_key() const { return _has_field_[1]; }
+ const std::string& key() const { return key_; }
+ void set_key(const std::string& value) { key_ = value; _has_field_.set(1); }
+
+ private:
+ std::string key_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DetachResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ DetachResponse();
+ ~DetachResponse() override;
+ DetachResponse(DetachResponse&&) noexcept;
+ DetachResponse& operator=(DetachResponse&&);
+ DetachResponse(const DetachResponse&);
+ DetachResponse& operator=(const DetachResponse&);
+ bool operator==(const DetachResponse&) const;
+ bool operator!=(const DetachResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DetachRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kKeyFieldNumber = 1,
+ };
+
+ DetachRequest();
+ ~DetachRequest() override;
+ DetachRequest(DetachRequest&&) noexcept;
+ DetachRequest& operator=(DetachRequest&&);
+ DetachRequest(const DetachRequest&);
+ DetachRequest& operator=(const DetachRequest&);
+ bool operator==(const DetachRequest&) const;
+ bool operator!=(const DetachRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_key() const { return _has_field_[1]; }
+ const std::string& key() const { return key_; }
+ void set_key(const std::string& value) { key_ = value; _has_field_.set(1); }
+
+ private:
+ std::string key_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FlushResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ FlushResponse();
+ ~FlushResponse() override;
+ FlushResponse(FlushResponse&&) noexcept;
+ FlushResponse& operator=(FlushResponse&&);
+ FlushResponse(const FlushResponse&);
+ FlushResponse& operator=(const FlushResponse&);
+ bool operator==(const FlushResponse&) const;
+ bool operator!=(const FlushResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FlushRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTimeoutMsFieldNumber = 1,
+ kFlagsFieldNumber = 2,
+ };
+
+ FlushRequest();
+ ~FlushRequest() override;
+ FlushRequest(FlushRequest&&) noexcept;
+ FlushRequest& operator=(FlushRequest&&);
+ FlushRequest(const FlushRequest&);
+ FlushRequest& operator=(const FlushRequest&);
+ bool operator==(const FlushRequest&) const;
+ bool operator!=(const FlushRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_timeout_ms() const { return _has_field_[1]; }
+ uint32_t timeout_ms() const { return timeout_ms_; }
+ void set_timeout_ms(uint32_t value) { timeout_ms_ = value; _has_field_.set(1); }
+
+ bool has_flags() const { return _has_field_[2]; }
+ uint64_t flags() const { return flags_; }
+ void set_flags(uint64_t value) { flags_ = value; _has_field_.set(2); }
+
+ private:
+ uint32_t timeout_ms_{};
+ uint64_t flags_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FreeBuffersResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ FreeBuffersResponse();
+ ~FreeBuffersResponse() override;
+ FreeBuffersResponse(FreeBuffersResponse&&) noexcept;
+ FreeBuffersResponse& operator=(FreeBuffersResponse&&);
+ FreeBuffersResponse(const FreeBuffersResponse&);
+ FreeBuffersResponse& operator=(const FreeBuffersResponse&);
+ bool operator==(const FreeBuffersResponse&) const;
+ bool operator!=(const FreeBuffersResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT FreeBuffersRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kBufferIdsFieldNumber = 1,
+ };
+
+ FreeBuffersRequest();
+ ~FreeBuffersRequest() override;
+ FreeBuffersRequest(FreeBuffersRequest&&) noexcept;
+ FreeBuffersRequest& operator=(FreeBuffersRequest&&);
+ FreeBuffersRequest(const FreeBuffersRequest&);
+ FreeBuffersRequest& operator=(const FreeBuffersRequest&);
+ bool operator==(const FreeBuffersRequest&) const;
+ bool operator!=(const FreeBuffersRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<uint32_t>& buffer_ids() const { return buffer_ids_; }
+ std::vector<uint32_t>* mutable_buffer_ids() { return &buffer_ids_; }
+ int buffer_ids_size() const { return static_cast<int>(buffer_ids_.size()); }
+ void clear_buffer_ids() { buffer_ids_.clear(); }
+ void add_buffer_ids(uint32_t value) { buffer_ids_.emplace_back(value); }
+ uint32_t* add_buffer_ids() { buffer_ids_.emplace_back(); return &buffer_ids_.back(); }
+
+ private:
+ std::vector<uint32_t> buffer_ids_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ReadBuffersResponse : public ::protozero::CppMessageObj {
+ public:
+ using Slice = ReadBuffersResponse_Slice;
+ enum FieldNumbers {
+ kSlicesFieldNumber = 2,
+ };
+
+ ReadBuffersResponse();
+ ~ReadBuffersResponse() override;
+ ReadBuffersResponse(ReadBuffersResponse&&) noexcept;
+ ReadBuffersResponse& operator=(ReadBuffersResponse&&);
+ ReadBuffersResponse(const ReadBuffersResponse&);
+ ReadBuffersResponse& operator=(const ReadBuffersResponse&);
+ bool operator==(const ReadBuffersResponse&) const;
+ bool operator!=(const ReadBuffersResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<ReadBuffersResponse_Slice>& slices() const { return slices_; }
+ std::vector<ReadBuffersResponse_Slice>* mutable_slices() { return &slices_; }
+ int slices_size() const;
+ void clear_slices();
+ ReadBuffersResponse_Slice* add_slices();
+
+ private:
+ std::vector<ReadBuffersResponse_Slice> slices_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ReadBuffersResponse_Slice : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataFieldNumber = 1,
+ kLastSliceForPacketFieldNumber = 2,
+ };
+
+ ReadBuffersResponse_Slice();
+ ~ReadBuffersResponse_Slice() override;
+ ReadBuffersResponse_Slice(ReadBuffersResponse_Slice&&) noexcept;
+ ReadBuffersResponse_Slice& operator=(ReadBuffersResponse_Slice&&);
+ ReadBuffersResponse_Slice(const ReadBuffersResponse_Slice&);
+ ReadBuffersResponse_Slice& operator=(const ReadBuffersResponse_Slice&);
+ bool operator==(const ReadBuffersResponse_Slice&) const;
+ bool operator!=(const ReadBuffersResponse_Slice& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_data() const { return _has_field_[1]; }
+ const std::string& data() const { return data_; }
+ void set_data(const std::string& value) { data_ = value; _has_field_.set(1); }
+ void set_data(const void* p, size_t s) { data_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(1); }
+
+ bool has_last_slice_for_packet() const { return _has_field_[2]; }
+ bool last_slice_for_packet() const { return last_slice_for_packet_; }
+ void set_last_slice_for_packet(bool value) { last_slice_for_packet_ = value; _has_field_.set(2); }
+
+ private:
+ std::string data_{};
+ bool last_slice_for_packet_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ReadBuffersRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ ReadBuffersRequest();
+ ~ReadBuffersRequest() override;
+ ReadBuffersRequest(ReadBuffersRequest&&) noexcept;
+ ReadBuffersRequest& operator=(ReadBuffersRequest&&);
+ ReadBuffersRequest(const ReadBuffersRequest&);
+ ReadBuffersRequest& operator=(const ReadBuffersRequest&);
+ bool operator==(const ReadBuffersRequest&) const;
+ bool operator!=(const ReadBuffersRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DisableTracingResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ DisableTracingResponse();
+ ~DisableTracingResponse() override;
+ DisableTracingResponse(DisableTracingResponse&&) noexcept;
+ DisableTracingResponse& operator=(DisableTracingResponse&&);
+ DisableTracingResponse(const DisableTracingResponse&);
+ DisableTracingResponse& operator=(const DisableTracingResponse&);
+ bool operator==(const DisableTracingResponse&) const;
+ bool operator!=(const DisableTracingResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT DisableTracingRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ DisableTracingRequest();
+ ~DisableTracingRequest() override;
+ DisableTracingRequest(DisableTracingRequest&&) noexcept;
+ DisableTracingRequest& operator=(DisableTracingRequest&&);
+ DisableTracingRequest(const DisableTracingRequest&);
+ DisableTracingRequest& operator=(const DisableTracingRequest&);
+ bool operator==(const DisableTracingRequest&) const;
+ bool operator!=(const DisableTracingRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChangeTraceConfigResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ ChangeTraceConfigResponse();
+ ~ChangeTraceConfigResponse() override;
+ ChangeTraceConfigResponse(ChangeTraceConfigResponse&&) noexcept;
+ ChangeTraceConfigResponse& operator=(ChangeTraceConfigResponse&&);
+ ChangeTraceConfigResponse(const ChangeTraceConfigResponse&);
+ ChangeTraceConfigResponse& operator=(const ChangeTraceConfigResponse&);
+ bool operator==(const ChangeTraceConfigResponse&) const;
+ bool operator!=(const ChangeTraceConfigResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ChangeTraceConfigRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTraceConfigFieldNumber = 1,
+ };
+
+ ChangeTraceConfigRequest();
+ ~ChangeTraceConfigRequest() override;
+ ChangeTraceConfigRequest(ChangeTraceConfigRequest&&) noexcept;
+ ChangeTraceConfigRequest& operator=(ChangeTraceConfigRequest&&);
+ ChangeTraceConfigRequest(const ChangeTraceConfigRequest&);
+ ChangeTraceConfigRequest& operator=(const ChangeTraceConfigRequest&);
+ bool operator==(const ChangeTraceConfigRequest&) const;
+ bool operator!=(const ChangeTraceConfigRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_config() const { return _has_field_[1]; }
+ const TraceConfig& trace_config() const { return *trace_config_; }
+ TraceConfig* mutable_trace_config() { _has_field_.set(1); return trace_config_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<TraceConfig> trace_config_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT StartTracingResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ StartTracingResponse();
+ ~StartTracingResponse() override;
+ StartTracingResponse(StartTracingResponse&&) noexcept;
+ StartTracingResponse& operator=(StartTracingResponse&&);
+ StartTracingResponse(const StartTracingResponse&);
+ StartTracingResponse& operator=(const StartTracingResponse&);
+ bool operator==(const StartTracingResponse&) const;
+ bool operator!=(const StartTracingResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT StartTracingRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ StartTracingRequest();
+ ~StartTracingRequest() override;
+ StartTracingRequest(StartTracingRequest&&) noexcept;
+ StartTracingRequest& operator=(StartTracingRequest&&);
+ StartTracingRequest(const StartTracingRequest&);
+ StartTracingRequest& operator=(const StartTracingRequest&);
+ bool operator==(const StartTracingRequest&) const;
+ bool operator!=(const StartTracingRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT EnableTracingResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDisabledFieldNumber = 1,
+ kErrorFieldNumber = 3,
+ };
+
+ EnableTracingResponse();
+ ~EnableTracingResponse() override;
+ EnableTracingResponse(EnableTracingResponse&&) noexcept;
+ EnableTracingResponse& operator=(EnableTracingResponse&&);
+ EnableTracingResponse(const EnableTracingResponse&);
+ EnableTracingResponse& operator=(const EnableTracingResponse&);
+ bool operator==(const EnableTracingResponse&) const;
+ bool operator!=(const EnableTracingResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_disabled() const { return _has_field_[1]; }
+ bool disabled() const { return disabled_; }
+ void set_disabled(bool value) { disabled_ = value; _has_field_.set(1); }
+
+ bool has_error() const { return _has_field_[3]; }
+ const std::string& error() const { return error_; }
+ void set_error(const std::string& value) { error_ = value; _has_field_.set(3); }
+
+ private:
+ bool disabled_{};
+ std::string error_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT EnableTracingRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTraceConfigFieldNumber = 1,
+ kAttachNotificationOnlyFieldNumber = 2,
+ };
+
+ EnableTracingRequest();
+ ~EnableTracingRequest() override;
+ EnableTracingRequest(EnableTracingRequest&&) noexcept;
+ EnableTracingRequest& operator=(EnableTracingRequest&&);
+ EnableTracingRequest(const EnableTracingRequest&);
+ EnableTracingRequest& operator=(const EnableTracingRequest&);
+ bool operator==(const EnableTracingRequest&) const;
+ bool operator!=(const EnableTracingRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_config() const { return _has_field_[1]; }
+ const TraceConfig& trace_config() const { return *trace_config_; }
+ TraceConfig* mutable_trace_config() { _has_field_.set(1); return trace_config_.get(); }
+
+ bool has_attach_notification_only() const { return _has_field_[2]; }
+ bool attach_notification_only() const { return attach_notification_only_; }
+ void set_attach_notification_only(bool value) { attach_notification_only_ = value; _has_field_.set(2); }
+
+ private:
+ ::protozero::CopyablePtr<TraceConfig> trace_config_;
+ bool attach_notification_only_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_CONSUMER_PORT_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/ipc/producer_port.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_PRODUCER_PORT_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_PRODUCER_PORT_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class SyncResponse;
+class SyncRequest;
+class GetAsyncCommandResponse;
+class GetAsyncCommandResponse_ClearIncrementalState;
+class GetAsyncCommandResponse_Flush;
+class GetAsyncCommandResponse_StopDataSource;
+class GetAsyncCommandResponse_StartDataSource;
+class DataSourceConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+class InterceptorConfig;
+class ConsoleConfig;
+class ChromeConfig;
+class SystemInfoConfig;
+class GetAsyncCommandResponse_SetupDataSource;
+class GetAsyncCommandResponse_SetupTracing;
+class GetAsyncCommandRequest;
+class ActivateTriggersResponse;
+class ActivateTriggersRequest;
+class NotifyDataSourceStoppedResponse;
+class NotifyDataSourceStoppedRequest;
+class NotifyDataSourceStartedResponse;
+class NotifyDataSourceStartedRequest;
+class CommitDataResponse;
+class UnregisterTraceWriterResponse;
+class UnregisterTraceWriterRequest;
+class RegisterTraceWriterResponse;
+class RegisterTraceWriterRequest;
+class UnregisterDataSourceResponse;
+class UnregisterDataSourceRequest;
+class UpdateDataSourceResponse;
+class UpdateDataSourceRequest;
+class DataSourceDescriptor;
+class RegisterDataSourceResponse;
+class RegisterDataSourceRequest;
+class InitializeConnectionResponse;
+class InitializeConnectionRequest;
+enum DataSourceConfig_SessionInitiator : int;
+enum ConsoleConfig_Output : int;
+enum ChromeConfig_ClientPriority : int;
+enum InitializeConnectionRequest_ProducerSMBScrapingMode : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum InitializeConnectionRequest_ProducerSMBScrapingMode : int {
+ InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_UNSPECIFIED = 0,
+ InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_ENABLED = 1,
+ InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_DISABLED = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT SyncResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ SyncResponse();
+ ~SyncResponse() override;
+ SyncResponse(SyncResponse&&) noexcept;
+ SyncResponse& operator=(SyncResponse&&);
+ SyncResponse(const SyncResponse&);
+ SyncResponse& operator=(const SyncResponse&);
+ bool operator==(const SyncResponse&) const;
+ bool operator!=(const SyncResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT SyncRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ SyncRequest();
+ ~SyncRequest() override;
+ SyncRequest(SyncRequest&&) noexcept;
+ SyncRequest& operator=(SyncRequest&&);
+ SyncRequest(const SyncRequest&);
+ SyncRequest& operator=(const SyncRequest&);
+ bool operator==(const SyncRequest&) const;
+ bool operator!=(const SyncRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandResponse : public ::protozero::CppMessageObj {
+ public:
+ using SetupDataSource = GetAsyncCommandResponse_SetupDataSource;
+ using StartDataSource = GetAsyncCommandResponse_StartDataSource;
+ using StopDataSource = GetAsyncCommandResponse_StopDataSource;
+ using SetupTracing = GetAsyncCommandResponse_SetupTracing;
+ using Flush = GetAsyncCommandResponse_Flush;
+ using ClearIncrementalState = GetAsyncCommandResponse_ClearIncrementalState;
+ enum FieldNumbers {
+ kSetupTracingFieldNumber = 3,
+ kSetupDataSourceFieldNumber = 6,
+ kStartDataSourceFieldNumber = 1,
+ kStopDataSourceFieldNumber = 2,
+ kFlushFieldNumber = 5,
+ kClearIncrementalStateFieldNumber = 7,
+ };
+
+ GetAsyncCommandResponse();
+ ~GetAsyncCommandResponse() override;
+ GetAsyncCommandResponse(GetAsyncCommandResponse&&) noexcept;
+ GetAsyncCommandResponse& operator=(GetAsyncCommandResponse&&);
+ GetAsyncCommandResponse(const GetAsyncCommandResponse&);
+ GetAsyncCommandResponse& operator=(const GetAsyncCommandResponse&);
+ bool operator==(const GetAsyncCommandResponse&) const;
+ bool operator!=(const GetAsyncCommandResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_setup_tracing() const { return _has_field_[3]; }
+ const GetAsyncCommandResponse_SetupTracing& setup_tracing() const { return *setup_tracing_; }
+ GetAsyncCommandResponse_SetupTracing* mutable_setup_tracing() { _has_field_.set(3); return setup_tracing_.get(); }
+
+ bool has_setup_data_source() const { return _has_field_[6]; }
+ const GetAsyncCommandResponse_SetupDataSource& setup_data_source() const { return *setup_data_source_; }
+ GetAsyncCommandResponse_SetupDataSource* mutable_setup_data_source() { _has_field_.set(6); return setup_data_source_.get(); }
+
+ bool has_start_data_source() const { return _has_field_[1]; }
+ const GetAsyncCommandResponse_StartDataSource& start_data_source() const { return *start_data_source_; }
+ GetAsyncCommandResponse_StartDataSource* mutable_start_data_source() { _has_field_.set(1); return start_data_source_.get(); }
+
+ bool has_stop_data_source() const { return _has_field_[2]; }
+ const GetAsyncCommandResponse_StopDataSource& stop_data_source() const { return *stop_data_source_; }
+ GetAsyncCommandResponse_StopDataSource* mutable_stop_data_source() { _has_field_.set(2); return stop_data_source_.get(); }
+
+ bool has_flush() const { return _has_field_[5]; }
+ const GetAsyncCommandResponse_Flush& flush() const { return *flush_; }
+ GetAsyncCommandResponse_Flush* mutable_flush() { _has_field_.set(5); return flush_.get(); }
+
+ bool has_clear_incremental_state() const { return _has_field_[7]; }
+ const GetAsyncCommandResponse_ClearIncrementalState& clear_incremental_state() const { return *clear_incremental_state_; }
+ GetAsyncCommandResponse_ClearIncrementalState* mutable_clear_incremental_state() { _has_field_.set(7); return clear_incremental_state_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<GetAsyncCommandResponse_SetupTracing> setup_tracing_;
+ ::protozero::CopyablePtr<GetAsyncCommandResponse_SetupDataSource> setup_data_source_;
+ ::protozero::CopyablePtr<GetAsyncCommandResponse_StartDataSource> start_data_source_;
+ ::protozero::CopyablePtr<GetAsyncCommandResponse_StopDataSource> stop_data_source_;
+ ::protozero::CopyablePtr<GetAsyncCommandResponse_Flush> flush_;
+ ::protozero::CopyablePtr<GetAsyncCommandResponse_ClearIncrementalState> clear_incremental_state_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<8> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandResponse_ClearIncrementalState : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataSourceIdsFieldNumber = 1,
+ };
+
+ GetAsyncCommandResponse_ClearIncrementalState();
+ ~GetAsyncCommandResponse_ClearIncrementalState() override;
+ GetAsyncCommandResponse_ClearIncrementalState(GetAsyncCommandResponse_ClearIncrementalState&&) noexcept;
+ GetAsyncCommandResponse_ClearIncrementalState& operator=(GetAsyncCommandResponse_ClearIncrementalState&&);
+ GetAsyncCommandResponse_ClearIncrementalState(const GetAsyncCommandResponse_ClearIncrementalState&);
+ GetAsyncCommandResponse_ClearIncrementalState& operator=(const GetAsyncCommandResponse_ClearIncrementalState&);
+ bool operator==(const GetAsyncCommandResponse_ClearIncrementalState&) const;
+ bool operator!=(const GetAsyncCommandResponse_ClearIncrementalState& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<uint64_t>& data_source_ids() const { return data_source_ids_; }
+ std::vector<uint64_t>* mutable_data_source_ids() { return &data_source_ids_; }
+ int data_source_ids_size() const { return static_cast<int>(data_source_ids_.size()); }
+ void clear_data_source_ids() { data_source_ids_.clear(); }
+ void add_data_source_ids(uint64_t value) { data_source_ids_.emplace_back(value); }
+ uint64_t* add_data_source_ids() { data_source_ids_.emplace_back(); return &data_source_ids_.back(); }
+
+ private:
+ std::vector<uint64_t> data_source_ids_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandResponse_Flush : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataSourceIdsFieldNumber = 1,
+ kRequestIdFieldNumber = 2,
+ kFlagsFieldNumber = 3,
+ };
+
+ GetAsyncCommandResponse_Flush();
+ ~GetAsyncCommandResponse_Flush() override;
+ GetAsyncCommandResponse_Flush(GetAsyncCommandResponse_Flush&&) noexcept;
+ GetAsyncCommandResponse_Flush& operator=(GetAsyncCommandResponse_Flush&&);
+ GetAsyncCommandResponse_Flush(const GetAsyncCommandResponse_Flush&);
+ GetAsyncCommandResponse_Flush& operator=(const GetAsyncCommandResponse_Flush&);
+ bool operator==(const GetAsyncCommandResponse_Flush&) const;
+ bool operator!=(const GetAsyncCommandResponse_Flush& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<uint64_t>& data_source_ids() const { return data_source_ids_; }
+ std::vector<uint64_t>* mutable_data_source_ids() { return &data_source_ids_; }
+ int data_source_ids_size() const { return static_cast<int>(data_source_ids_.size()); }
+ void clear_data_source_ids() { data_source_ids_.clear(); }
+ void add_data_source_ids(uint64_t value) { data_source_ids_.emplace_back(value); }
+ uint64_t* add_data_source_ids() { data_source_ids_.emplace_back(); return &data_source_ids_.back(); }
+
+ bool has_request_id() const { return _has_field_[2]; }
+ uint64_t request_id() const { return request_id_; }
+ void set_request_id(uint64_t value) { request_id_ = value; _has_field_.set(2); }
+
+ bool has_flags() const { return _has_field_[3]; }
+ uint64_t flags() const { return flags_; }
+ void set_flags(uint64_t value) { flags_ = value; _has_field_.set(3); }
+
+ private:
+ std::vector<uint64_t> data_source_ids_;
+ uint64_t request_id_{};
+ uint64_t flags_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandResponse_StopDataSource : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kInstanceIdFieldNumber = 1,
+ };
+
+ GetAsyncCommandResponse_StopDataSource();
+ ~GetAsyncCommandResponse_StopDataSource() override;
+ GetAsyncCommandResponse_StopDataSource(GetAsyncCommandResponse_StopDataSource&&) noexcept;
+ GetAsyncCommandResponse_StopDataSource& operator=(GetAsyncCommandResponse_StopDataSource&&);
+ GetAsyncCommandResponse_StopDataSource(const GetAsyncCommandResponse_StopDataSource&);
+ GetAsyncCommandResponse_StopDataSource& operator=(const GetAsyncCommandResponse_StopDataSource&);
+ bool operator==(const GetAsyncCommandResponse_StopDataSource&) const;
+ bool operator!=(const GetAsyncCommandResponse_StopDataSource& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_instance_id() const { return _has_field_[1]; }
+ uint64_t instance_id() const { return instance_id_; }
+ void set_instance_id(uint64_t value) { instance_id_ = value; _has_field_.set(1); }
+
+ private:
+ uint64_t instance_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandResponse_StartDataSource : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNewInstanceIdFieldNumber = 1,
+ kConfigFieldNumber = 2,
+ };
+
+ GetAsyncCommandResponse_StartDataSource();
+ ~GetAsyncCommandResponse_StartDataSource() override;
+ GetAsyncCommandResponse_StartDataSource(GetAsyncCommandResponse_StartDataSource&&) noexcept;
+ GetAsyncCommandResponse_StartDataSource& operator=(GetAsyncCommandResponse_StartDataSource&&);
+ GetAsyncCommandResponse_StartDataSource(const GetAsyncCommandResponse_StartDataSource&);
+ GetAsyncCommandResponse_StartDataSource& operator=(const GetAsyncCommandResponse_StartDataSource&);
+ bool operator==(const GetAsyncCommandResponse_StartDataSource&) const;
+ bool operator!=(const GetAsyncCommandResponse_StartDataSource& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_new_instance_id() const { return _has_field_[1]; }
+ uint64_t new_instance_id() const { return new_instance_id_; }
+ void set_new_instance_id(uint64_t value) { new_instance_id_ = value; _has_field_.set(1); }
+
+ bool has_config() const { return _has_field_[2]; }
+ const DataSourceConfig& config() const { return *config_; }
+ DataSourceConfig* mutable_config() { _has_field_.set(2); return config_.get(); }
+
+ private:
+ uint64_t new_instance_id_{};
+ ::protozero::CopyablePtr<DataSourceConfig> config_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandResponse_SetupDataSource : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kNewInstanceIdFieldNumber = 1,
+ kConfigFieldNumber = 2,
+ };
+
+ GetAsyncCommandResponse_SetupDataSource();
+ ~GetAsyncCommandResponse_SetupDataSource() override;
+ GetAsyncCommandResponse_SetupDataSource(GetAsyncCommandResponse_SetupDataSource&&) noexcept;
+ GetAsyncCommandResponse_SetupDataSource& operator=(GetAsyncCommandResponse_SetupDataSource&&);
+ GetAsyncCommandResponse_SetupDataSource(const GetAsyncCommandResponse_SetupDataSource&);
+ GetAsyncCommandResponse_SetupDataSource& operator=(const GetAsyncCommandResponse_SetupDataSource&);
+ bool operator==(const GetAsyncCommandResponse_SetupDataSource&) const;
+ bool operator!=(const GetAsyncCommandResponse_SetupDataSource& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_new_instance_id() const { return _has_field_[1]; }
+ uint64_t new_instance_id() const { return new_instance_id_; }
+ void set_new_instance_id(uint64_t value) { new_instance_id_ = value; _has_field_.set(1); }
+
+ bool has_config() const { return _has_field_[2]; }
+ const DataSourceConfig& config() const { return *config_; }
+ DataSourceConfig* mutable_config() { _has_field_.set(2); return config_.get(); }
+
+ private:
+ uint64_t new_instance_id_{};
+ ::protozero::CopyablePtr<DataSourceConfig> config_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandResponse_SetupTracing : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSharedBufferPageSizeKbFieldNumber = 1,
+ kShmKeyWindowsFieldNumber = 2,
+ };
+
+ GetAsyncCommandResponse_SetupTracing();
+ ~GetAsyncCommandResponse_SetupTracing() override;
+ GetAsyncCommandResponse_SetupTracing(GetAsyncCommandResponse_SetupTracing&&) noexcept;
+ GetAsyncCommandResponse_SetupTracing& operator=(GetAsyncCommandResponse_SetupTracing&&);
+ GetAsyncCommandResponse_SetupTracing(const GetAsyncCommandResponse_SetupTracing&);
+ GetAsyncCommandResponse_SetupTracing& operator=(const GetAsyncCommandResponse_SetupTracing&);
+ bool operator==(const GetAsyncCommandResponse_SetupTracing&) const;
+ bool operator!=(const GetAsyncCommandResponse_SetupTracing& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_shared_buffer_page_size_kb() const { return _has_field_[1]; }
+ uint32_t shared_buffer_page_size_kb() const { return shared_buffer_page_size_kb_; }
+ void set_shared_buffer_page_size_kb(uint32_t value) { shared_buffer_page_size_kb_ = value; _has_field_.set(1); }
+
+ bool has_shm_key_windows() const { return _has_field_[2]; }
+ const std::string& shm_key_windows() const { return shm_key_windows_; }
+ void set_shm_key_windows(const std::string& value) { shm_key_windows_ = value; _has_field_.set(2); }
+
+ private:
+ uint32_t shared_buffer_page_size_kb_{};
+ std::string shm_key_windows_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT GetAsyncCommandRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ GetAsyncCommandRequest();
+ ~GetAsyncCommandRequest() override;
+ GetAsyncCommandRequest(GetAsyncCommandRequest&&) noexcept;
+ GetAsyncCommandRequest& operator=(GetAsyncCommandRequest&&);
+ GetAsyncCommandRequest(const GetAsyncCommandRequest&);
+ GetAsyncCommandRequest& operator=(const GetAsyncCommandRequest&);
+ bool operator==(const GetAsyncCommandRequest&) const;
+ bool operator!=(const GetAsyncCommandRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ActivateTriggersResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ ActivateTriggersResponse();
+ ~ActivateTriggersResponse() override;
+ ActivateTriggersResponse(ActivateTriggersResponse&&) noexcept;
+ ActivateTriggersResponse& operator=(ActivateTriggersResponse&&);
+ ActivateTriggersResponse(const ActivateTriggersResponse&);
+ ActivateTriggersResponse& operator=(const ActivateTriggersResponse&);
+ bool operator==(const ActivateTriggersResponse&) const;
+ bool operator!=(const ActivateTriggersResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT ActivateTriggersRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTriggerNamesFieldNumber = 1,
+ };
+
+ ActivateTriggersRequest();
+ ~ActivateTriggersRequest() override;
+ ActivateTriggersRequest(ActivateTriggersRequest&&) noexcept;
+ ActivateTriggersRequest& operator=(ActivateTriggersRequest&&);
+ ActivateTriggersRequest(const ActivateTriggersRequest&);
+ ActivateTriggersRequest& operator=(const ActivateTriggersRequest&);
+ bool operator==(const ActivateTriggersRequest&) const;
+ bool operator!=(const ActivateTriggersRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ const std::vector<std::string>& trigger_names() const { return trigger_names_; }
+ std::vector<std::string>* mutable_trigger_names() { return &trigger_names_; }
+ int trigger_names_size() const { return static_cast<int>(trigger_names_.size()); }
+ void clear_trigger_names() { trigger_names_.clear(); }
+ void add_trigger_names(std::string value) { trigger_names_.emplace_back(value); }
+ std::string* add_trigger_names() { trigger_names_.emplace_back(); return &trigger_names_.back(); }
+
+ private:
+ std::vector<std::string> trigger_names_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT NotifyDataSourceStoppedResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ NotifyDataSourceStoppedResponse();
+ ~NotifyDataSourceStoppedResponse() override;
+ NotifyDataSourceStoppedResponse(NotifyDataSourceStoppedResponse&&) noexcept;
+ NotifyDataSourceStoppedResponse& operator=(NotifyDataSourceStoppedResponse&&);
+ NotifyDataSourceStoppedResponse(const NotifyDataSourceStoppedResponse&);
+ NotifyDataSourceStoppedResponse& operator=(const NotifyDataSourceStoppedResponse&);
+ bool operator==(const NotifyDataSourceStoppedResponse&) const;
+ bool operator!=(const NotifyDataSourceStoppedResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT NotifyDataSourceStoppedRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataSourceIdFieldNumber = 1,
+ };
+
+ NotifyDataSourceStoppedRequest();
+ ~NotifyDataSourceStoppedRequest() override;
+ NotifyDataSourceStoppedRequest(NotifyDataSourceStoppedRequest&&) noexcept;
+ NotifyDataSourceStoppedRequest& operator=(NotifyDataSourceStoppedRequest&&);
+ NotifyDataSourceStoppedRequest(const NotifyDataSourceStoppedRequest&);
+ NotifyDataSourceStoppedRequest& operator=(const NotifyDataSourceStoppedRequest&);
+ bool operator==(const NotifyDataSourceStoppedRequest&) const;
+ bool operator!=(const NotifyDataSourceStoppedRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_data_source_id() const { return _has_field_[1]; }
+ uint64_t data_source_id() const { return data_source_id_; }
+ void set_data_source_id(uint64_t value) { data_source_id_ = value; _has_field_.set(1); }
+
+ private:
+ uint64_t data_source_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT NotifyDataSourceStartedResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ NotifyDataSourceStartedResponse();
+ ~NotifyDataSourceStartedResponse() override;
+ NotifyDataSourceStartedResponse(NotifyDataSourceStartedResponse&&) noexcept;
+ NotifyDataSourceStartedResponse& operator=(NotifyDataSourceStartedResponse&&);
+ NotifyDataSourceStartedResponse(const NotifyDataSourceStartedResponse&);
+ NotifyDataSourceStartedResponse& operator=(const NotifyDataSourceStartedResponse&);
+ bool operator==(const NotifyDataSourceStartedResponse&) const;
+ bool operator!=(const NotifyDataSourceStartedResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT NotifyDataSourceStartedRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataSourceIdFieldNumber = 1,
+ };
+
+ NotifyDataSourceStartedRequest();
+ ~NotifyDataSourceStartedRequest() override;
+ NotifyDataSourceStartedRequest(NotifyDataSourceStartedRequest&&) noexcept;
+ NotifyDataSourceStartedRequest& operator=(NotifyDataSourceStartedRequest&&);
+ NotifyDataSourceStartedRequest(const NotifyDataSourceStartedRequest&);
+ NotifyDataSourceStartedRequest& operator=(const NotifyDataSourceStartedRequest&);
+ bool operator==(const NotifyDataSourceStartedRequest&) const;
+ bool operator!=(const NotifyDataSourceStartedRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_data_source_id() const { return _has_field_[1]; }
+ uint64_t data_source_id() const { return data_source_id_; }
+ void set_data_source_id(uint64_t value) { data_source_id_ = value; _has_field_.set(1); }
+
+ private:
+ uint64_t data_source_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT CommitDataResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ CommitDataResponse();
+ ~CommitDataResponse() override;
+ CommitDataResponse(CommitDataResponse&&) noexcept;
+ CommitDataResponse& operator=(CommitDataResponse&&);
+ CommitDataResponse(const CommitDataResponse&);
+ CommitDataResponse& operator=(const CommitDataResponse&);
+ bool operator==(const CommitDataResponse&) const;
+ bool operator!=(const CommitDataResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UnregisterTraceWriterResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ UnregisterTraceWriterResponse();
+ ~UnregisterTraceWriterResponse() override;
+ UnregisterTraceWriterResponse(UnregisterTraceWriterResponse&&) noexcept;
+ UnregisterTraceWriterResponse& operator=(UnregisterTraceWriterResponse&&);
+ UnregisterTraceWriterResponse(const UnregisterTraceWriterResponse&);
+ UnregisterTraceWriterResponse& operator=(const UnregisterTraceWriterResponse&);
+ bool operator==(const UnregisterTraceWriterResponse&) const;
+ bool operator!=(const UnregisterTraceWriterResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UnregisterTraceWriterRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTraceWriterIdFieldNumber = 1,
+ };
+
+ UnregisterTraceWriterRequest();
+ ~UnregisterTraceWriterRequest() override;
+ UnregisterTraceWriterRequest(UnregisterTraceWriterRequest&&) noexcept;
+ UnregisterTraceWriterRequest& operator=(UnregisterTraceWriterRequest&&);
+ UnregisterTraceWriterRequest(const UnregisterTraceWriterRequest&);
+ UnregisterTraceWriterRequest& operator=(const UnregisterTraceWriterRequest&);
+ bool operator==(const UnregisterTraceWriterRequest&) const;
+ bool operator!=(const UnregisterTraceWriterRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_writer_id() const { return _has_field_[1]; }
+ uint32_t trace_writer_id() const { return trace_writer_id_; }
+ void set_trace_writer_id(uint32_t value) { trace_writer_id_ = value; _has_field_.set(1); }
+
+ private:
+ uint32_t trace_writer_id_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT RegisterTraceWriterResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ RegisterTraceWriterResponse();
+ ~RegisterTraceWriterResponse() override;
+ RegisterTraceWriterResponse(RegisterTraceWriterResponse&&) noexcept;
+ RegisterTraceWriterResponse& operator=(RegisterTraceWriterResponse&&);
+ RegisterTraceWriterResponse(const RegisterTraceWriterResponse&);
+ RegisterTraceWriterResponse& operator=(const RegisterTraceWriterResponse&);
+ bool operator==(const RegisterTraceWriterResponse&) const;
+ bool operator!=(const RegisterTraceWriterResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT RegisterTraceWriterRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kTraceWriterIdFieldNumber = 1,
+ kTargetBufferFieldNumber = 2,
+ };
+
+ RegisterTraceWriterRequest();
+ ~RegisterTraceWriterRequest() override;
+ RegisterTraceWriterRequest(RegisterTraceWriterRequest&&) noexcept;
+ RegisterTraceWriterRequest& operator=(RegisterTraceWriterRequest&&);
+ RegisterTraceWriterRequest(const RegisterTraceWriterRequest&);
+ RegisterTraceWriterRequest& operator=(const RegisterTraceWriterRequest&);
+ bool operator==(const RegisterTraceWriterRequest&) const;
+ bool operator!=(const RegisterTraceWriterRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_trace_writer_id() const { return _has_field_[1]; }
+ uint32_t trace_writer_id() const { return trace_writer_id_; }
+ void set_trace_writer_id(uint32_t value) { trace_writer_id_ = value; _has_field_.set(1); }
+
+ bool has_target_buffer() const { return _has_field_[2]; }
+ uint32_t target_buffer() const { return target_buffer_; }
+ void set_target_buffer(uint32_t value) { target_buffer_ = value; _has_field_.set(2); }
+
+ private:
+ uint32_t trace_writer_id_{};
+ uint32_t target_buffer_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UnregisterDataSourceResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ UnregisterDataSourceResponse();
+ ~UnregisterDataSourceResponse() override;
+ UnregisterDataSourceResponse(UnregisterDataSourceResponse&&) noexcept;
+ UnregisterDataSourceResponse& operator=(UnregisterDataSourceResponse&&);
+ UnregisterDataSourceResponse(const UnregisterDataSourceResponse&);
+ UnregisterDataSourceResponse& operator=(const UnregisterDataSourceResponse&);
+ bool operator==(const UnregisterDataSourceResponse&) const;
+ bool operator!=(const UnregisterDataSourceResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UnregisterDataSourceRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataSourceNameFieldNumber = 1,
+ };
+
+ UnregisterDataSourceRequest();
+ ~UnregisterDataSourceRequest() override;
+ UnregisterDataSourceRequest(UnregisterDataSourceRequest&&) noexcept;
+ UnregisterDataSourceRequest& operator=(UnregisterDataSourceRequest&&);
+ UnregisterDataSourceRequest(const UnregisterDataSourceRequest&);
+ UnregisterDataSourceRequest& operator=(const UnregisterDataSourceRequest&);
+ bool operator==(const UnregisterDataSourceRequest&) const;
+ bool operator!=(const UnregisterDataSourceRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_data_source_name() const { return _has_field_[1]; }
+ const std::string& data_source_name() const { return data_source_name_; }
+ void set_data_source_name(const std::string& value) { data_source_name_ = value; _has_field_.set(1); }
+
+ private:
+ std::string data_source_name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UpdateDataSourceResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ UpdateDataSourceResponse();
+ ~UpdateDataSourceResponse() override;
+ UpdateDataSourceResponse(UpdateDataSourceResponse&&) noexcept;
+ UpdateDataSourceResponse& operator=(UpdateDataSourceResponse&&);
+ UpdateDataSourceResponse(const UpdateDataSourceResponse&);
+ UpdateDataSourceResponse& operator=(const UpdateDataSourceResponse&);
+ bool operator==(const UpdateDataSourceResponse&) const;
+ bool operator!=(const UpdateDataSourceResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT UpdateDataSourceRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataSourceDescriptorFieldNumber = 1,
+ };
+
+ UpdateDataSourceRequest();
+ ~UpdateDataSourceRequest() override;
+ UpdateDataSourceRequest(UpdateDataSourceRequest&&) noexcept;
+ UpdateDataSourceRequest& operator=(UpdateDataSourceRequest&&);
+ UpdateDataSourceRequest(const UpdateDataSourceRequest&);
+ UpdateDataSourceRequest& operator=(const UpdateDataSourceRequest&);
+ bool operator==(const UpdateDataSourceRequest&) const;
+ bool operator!=(const UpdateDataSourceRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_data_source_descriptor() const { return _has_field_[1]; }
+ const DataSourceDescriptor& data_source_descriptor() const { return *data_source_descriptor_; }
+ DataSourceDescriptor* mutable_data_source_descriptor() { _has_field_.set(1); return data_source_descriptor_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<DataSourceDescriptor> data_source_descriptor_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT RegisterDataSourceResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kErrorFieldNumber = 1,
+ };
+
+ RegisterDataSourceResponse();
+ ~RegisterDataSourceResponse() override;
+ RegisterDataSourceResponse(RegisterDataSourceResponse&&) noexcept;
+ RegisterDataSourceResponse& operator=(RegisterDataSourceResponse&&);
+ RegisterDataSourceResponse(const RegisterDataSourceResponse&);
+ RegisterDataSourceResponse& operator=(const RegisterDataSourceResponse&);
+ bool operator==(const RegisterDataSourceResponse&) const;
+ bool operator!=(const RegisterDataSourceResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_error() const { return _has_field_[1]; }
+ const std::string& error() const { return error_; }
+ void set_error(const std::string& value) { error_ = value; _has_field_.set(1); }
+
+ private:
+ std::string error_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT RegisterDataSourceRequest : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kDataSourceDescriptorFieldNumber = 1,
+ };
+
+ RegisterDataSourceRequest();
+ ~RegisterDataSourceRequest() override;
+ RegisterDataSourceRequest(RegisterDataSourceRequest&&) noexcept;
+ RegisterDataSourceRequest& operator=(RegisterDataSourceRequest&&);
+ RegisterDataSourceRequest(const RegisterDataSourceRequest&);
+ RegisterDataSourceRequest& operator=(const RegisterDataSourceRequest&);
+ bool operator==(const RegisterDataSourceRequest&) const;
+ bool operator!=(const RegisterDataSourceRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_data_source_descriptor() const { return _has_field_[1]; }
+ const DataSourceDescriptor& data_source_descriptor() const { return *data_source_descriptor_; }
+ DataSourceDescriptor* mutable_data_source_descriptor() { _has_field_.set(1); return data_source_descriptor_.get(); }
+
+ private:
+ ::protozero::CopyablePtr<DataSourceDescriptor> data_source_descriptor_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT InitializeConnectionResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kUsingShmemProvidedByProducerFieldNumber = 1,
+ kDirectSmbPatchingSupportedFieldNumber = 2,
+ kUseShmemEmulationFieldNumber = 3,
+ };
+
+ InitializeConnectionResponse();
+ ~InitializeConnectionResponse() override;
+ InitializeConnectionResponse(InitializeConnectionResponse&&) noexcept;
+ InitializeConnectionResponse& operator=(InitializeConnectionResponse&&);
+ InitializeConnectionResponse(const InitializeConnectionResponse&);
+ InitializeConnectionResponse& operator=(const InitializeConnectionResponse&);
+ bool operator==(const InitializeConnectionResponse&) const;
+ bool operator!=(const InitializeConnectionResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_using_shmem_provided_by_producer() const { return _has_field_[1]; }
+ bool using_shmem_provided_by_producer() const { return using_shmem_provided_by_producer_; }
+ void set_using_shmem_provided_by_producer(bool value) { using_shmem_provided_by_producer_ = value; _has_field_.set(1); }
+
+ bool has_direct_smb_patching_supported() const { return _has_field_[2]; }
+ bool direct_smb_patching_supported() const { return direct_smb_patching_supported_; }
+ void set_direct_smb_patching_supported(bool value) { direct_smb_patching_supported_ = value; _has_field_.set(2); }
+
+ bool has_use_shmem_emulation() const { return _has_field_[3]; }
+ bool use_shmem_emulation() const { return use_shmem_emulation_; }
+ void set_use_shmem_emulation(bool value) { use_shmem_emulation_ = value; _has_field_.set(3); }
+
+ private:
+ bool using_shmem_provided_by_producer_{};
+ bool direct_smb_patching_supported_{};
+ bool use_shmem_emulation_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT InitializeConnectionRequest : public ::protozero::CppMessageObj {
+ public:
+ using ProducerSMBScrapingMode = InitializeConnectionRequest_ProducerSMBScrapingMode;
+ static constexpr auto SMB_SCRAPING_UNSPECIFIED = InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_UNSPECIFIED;
+ static constexpr auto SMB_SCRAPING_ENABLED = InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_ENABLED;
+ static constexpr auto SMB_SCRAPING_DISABLED = InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_DISABLED;
+ static constexpr auto ProducerSMBScrapingMode_MIN = InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_UNSPECIFIED;
+ static constexpr auto ProducerSMBScrapingMode_MAX = InitializeConnectionRequest_ProducerSMBScrapingMode_SMB_SCRAPING_DISABLED;
+ enum FieldNumbers {
+ kSharedMemoryPageSizeHintBytesFieldNumber = 1,
+ kSharedMemorySizeHintBytesFieldNumber = 2,
+ kProducerNameFieldNumber = 3,
+ kSmbScrapingModeFieldNumber = 4,
+ kProducerProvidedShmemFieldNumber = 6,
+ kSdkVersionFieldNumber = 8,
+ kShmKeyWindowsFieldNumber = 7,
+ };
+
+ InitializeConnectionRequest();
+ ~InitializeConnectionRequest() override;
+ InitializeConnectionRequest(InitializeConnectionRequest&&) noexcept;
+ InitializeConnectionRequest& operator=(InitializeConnectionRequest&&);
+ InitializeConnectionRequest(const InitializeConnectionRequest&);
+ InitializeConnectionRequest& operator=(const InitializeConnectionRequest&);
+ bool operator==(const InitializeConnectionRequest&) const;
+ bool operator!=(const InitializeConnectionRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_shared_memory_page_size_hint_bytes() const { return _has_field_[1]; }
+ uint32_t shared_memory_page_size_hint_bytes() const { return shared_memory_page_size_hint_bytes_; }
+ void set_shared_memory_page_size_hint_bytes(uint32_t value) { shared_memory_page_size_hint_bytes_ = value; _has_field_.set(1); }
+
+ bool has_shared_memory_size_hint_bytes() const { return _has_field_[2]; }
+ uint32_t shared_memory_size_hint_bytes() const { return shared_memory_size_hint_bytes_; }
+ void set_shared_memory_size_hint_bytes(uint32_t value) { shared_memory_size_hint_bytes_ = value; _has_field_.set(2); }
+
+ bool has_producer_name() const { return _has_field_[3]; }
+ const std::string& producer_name() const { return producer_name_; }
+ void set_producer_name(const std::string& value) { producer_name_ = value; _has_field_.set(3); }
+
+ bool has_smb_scraping_mode() const { return _has_field_[4]; }
+ InitializeConnectionRequest_ProducerSMBScrapingMode smb_scraping_mode() const { return smb_scraping_mode_; }
+ void set_smb_scraping_mode(InitializeConnectionRequest_ProducerSMBScrapingMode value) { smb_scraping_mode_ = value; _has_field_.set(4); }
+
+ bool has_producer_provided_shmem() const { return _has_field_[6]; }
+ bool producer_provided_shmem() const { return producer_provided_shmem_; }
+ void set_producer_provided_shmem(bool value) { producer_provided_shmem_ = value; _has_field_.set(6); }
+
+ bool has_sdk_version() const { return _has_field_[8]; }
+ const std::string& sdk_version() const { return sdk_version_; }
+ void set_sdk_version(const std::string& value) { sdk_version_ = value; _has_field_.set(8); }
+
+ bool has_shm_key_windows() const { return _has_field_[7]; }
+ const std::string& shm_key_windows() const { return shm_key_windows_; }
+ void set_shm_key_windows(const std::string& value) { shm_key_windows_ = value; _has_field_.set(7); }
+
+ private:
+ uint32_t shared_memory_page_size_hint_bytes_{};
+ uint32_t shared_memory_size_hint_bytes_{};
+ std::string producer_name_{};
+ InitializeConnectionRequest_ProducerSMBScrapingMode smb_scraping_mode_{};
+ bool producer_provided_shmem_{};
+ std::string sdk_version_{};
+ std::string shm_key_windows_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_PRODUCER_PORT_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/ipc/relay_port.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_RELAY_PORT_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_RELAY_PORT_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class SyncClockResponse;
+class SyncClockRequest;
+class SyncClockRequest_Clock;
+enum SyncClockRequest_Phase : int;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+enum SyncClockRequest_Phase : int {
+ SyncClockRequest_Phase_PING = 1,
+ SyncClockRequest_Phase_UPDATE = 2,
+};
+
+class PERFETTO_EXPORT_COMPONENT SyncClockResponse : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ };
+
+ SyncClockResponse();
+ ~SyncClockResponse() override;
+ SyncClockResponse(SyncClockResponse&&) noexcept;
+ SyncClockResponse& operator=(SyncClockResponse&&);
+ SyncClockResponse(const SyncClockResponse&);
+ SyncClockResponse& operator=(const SyncClockResponse&);
+ bool operator==(const SyncClockResponse&) const;
+ bool operator!=(const SyncClockResponse& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ private:
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT SyncClockRequest : public ::protozero::CppMessageObj {
+ public:
+ using Clock = SyncClockRequest_Clock;
+ using Phase = SyncClockRequest_Phase;
+ static constexpr auto PING = SyncClockRequest_Phase_PING;
+ static constexpr auto UPDATE = SyncClockRequest_Phase_UPDATE;
+ static constexpr auto Phase_MIN = SyncClockRequest_Phase_PING;
+ static constexpr auto Phase_MAX = SyncClockRequest_Phase_UPDATE;
+ enum FieldNumbers {
+ kPhaseFieldNumber = 1,
+ kClocksFieldNumber = 2,
+ };
+
+ SyncClockRequest();
+ ~SyncClockRequest() override;
+ SyncClockRequest(SyncClockRequest&&) noexcept;
+ SyncClockRequest& operator=(SyncClockRequest&&);
+ SyncClockRequest(const SyncClockRequest&);
+ SyncClockRequest& operator=(const SyncClockRequest&);
+ bool operator==(const SyncClockRequest&) const;
+ bool operator!=(const SyncClockRequest& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_phase() const { return _has_field_[1]; }
+ SyncClockRequest_Phase phase() const { return phase_; }
+ void set_phase(SyncClockRequest_Phase value) { phase_ = value; _has_field_.set(1); }
+
+ const std::vector<SyncClockRequest_Clock>& clocks() const { return clocks_; }
+ std::vector<SyncClockRequest_Clock>* mutable_clocks() { return &clocks_; }
+ int clocks_size() const;
+ void clear_clocks();
+ SyncClockRequest_Clock* add_clocks();
+
+ private:
+ SyncClockRequest_Phase phase_{};
+ std::vector<SyncClockRequest_Clock> clocks_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT SyncClockRequest_Clock : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kClockIdFieldNumber = 1,
+ kTimestampFieldNumber = 2,
+ };
+
+ SyncClockRequest_Clock();
+ ~SyncClockRequest_Clock() override;
+ SyncClockRequest_Clock(SyncClockRequest_Clock&&) noexcept;
+ SyncClockRequest_Clock& operator=(SyncClockRequest_Clock&&);
+ SyncClockRequest_Clock(const SyncClockRequest_Clock&);
+ SyncClockRequest_Clock& operator=(const SyncClockRequest_Clock&);
+ bool operator==(const SyncClockRequest_Clock&) const;
+ bool operator!=(const SyncClockRequest_Clock& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_clock_id() const { return _has_field_[1]; }
+ uint32_t clock_id() const { return clock_id_; }
+ void set_clock_id(uint32_t value) { clock_id_ = value; _has_field_.set(1); }
+
+ bool has_timestamp() const { return _has_field_[2]; }
+ uint64_t timestamp() const { return timestamp_; }
+ void set_timestamp(uint64_t value) { timestamp_ = value; _has_field_.set(2); }
+
+ private:
+ uint32_t clock_id_{};
+ uint64_t timestamp_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_RELAY_PORT_PROTO_CPP_H_
+// gen_amalgamated begin header: gen/protos/perfetto/ipc/wire_protocol.gen.h
+// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin
+#ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_WIRE_PROTOCOL_PROTO_CPP_H_
+#define PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_WIRE_PROTOCOL_PROTO_CPP_H_
+
+#include <stdint.h>
+#include <bitset>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+// gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h"
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class IPCFrame;
+class IPCFrame_SetPeerIdentity;
+class IPCFrame_RequestError;
+class IPCFrame_InvokeMethodReply;
+class IPCFrame_InvokeMethod;
+class IPCFrame_BindServiceReply;
+class IPCFrame_BindServiceReply_MethodInfo;
+class IPCFrame_BindService;
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+namespace protozero {
+class Message;
+} // namespace protozero
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame : public ::protozero::CppMessageObj {
+ public:
+ using BindService = IPCFrame_BindService;
+ using BindServiceReply = IPCFrame_BindServiceReply;
+ using InvokeMethod = IPCFrame_InvokeMethod;
+ using InvokeMethodReply = IPCFrame_InvokeMethodReply;
+ using RequestError = IPCFrame_RequestError;
+ using SetPeerIdentity = IPCFrame_SetPeerIdentity;
+ enum FieldNumbers {
+ kRequestIdFieldNumber = 2,
+ kMsgBindServiceFieldNumber = 3,
+ kMsgBindServiceReplyFieldNumber = 4,
+ kMsgInvokeMethodFieldNumber = 5,
+ kMsgInvokeMethodReplyFieldNumber = 6,
+ kMsgRequestErrorFieldNumber = 7,
+ kSetPeerIdentityFieldNumber = 8,
+ kDataForTestingFieldNumber = 1,
+ };
+
+ IPCFrame();
+ ~IPCFrame() override;
+ IPCFrame(IPCFrame&&) noexcept;
+ IPCFrame& operator=(IPCFrame&&);
+ IPCFrame(const IPCFrame&);
+ IPCFrame& operator=(const IPCFrame&);
+ bool operator==(const IPCFrame&) const;
+ bool operator!=(const IPCFrame& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_request_id() const { return _has_field_[2]; }
+ uint64_t request_id() const { return request_id_; }
+ void set_request_id(uint64_t value) { request_id_ = value; _has_field_.set(2); }
+
+ bool has_msg_bind_service() const { return _has_field_[3]; }
+ const IPCFrame_BindService& msg_bind_service() const { return *msg_bind_service_; }
+ IPCFrame_BindService* mutable_msg_bind_service() { _has_field_.set(3); return msg_bind_service_.get(); }
+
+ bool has_msg_bind_service_reply() const { return _has_field_[4]; }
+ const IPCFrame_BindServiceReply& msg_bind_service_reply() const { return *msg_bind_service_reply_; }
+ IPCFrame_BindServiceReply* mutable_msg_bind_service_reply() { _has_field_.set(4); return msg_bind_service_reply_.get(); }
+
+ bool has_msg_invoke_method() const { return _has_field_[5]; }
+ const IPCFrame_InvokeMethod& msg_invoke_method() const { return *msg_invoke_method_; }
+ IPCFrame_InvokeMethod* mutable_msg_invoke_method() { _has_field_.set(5); return msg_invoke_method_.get(); }
+
+ bool has_msg_invoke_method_reply() const { return _has_field_[6]; }
+ const IPCFrame_InvokeMethodReply& msg_invoke_method_reply() const { return *msg_invoke_method_reply_; }
+ IPCFrame_InvokeMethodReply* mutable_msg_invoke_method_reply() { _has_field_.set(6); return msg_invoke_method_reply_.get(); }
+
+ bool has_msg_request_error() const { return _has_field_[7]; }
+ const IPCFrame_RequestError& msg_request_error() const { return *msg_request_error_; }
+ IPCFrame_RequestError* mutable_msg_request_error() { _has_field_.set(7); return msg_request_error_.get(); }
+
+ bool has_set_peer_identity() const { return _has_field_[8]; }
+ const IPCFrame_SetPeerIdentity& set_peer_identity() const { return *set_peer_identity_; }
+ IPCFrame_SetPeerIdentity* mutable_set_peer_identity() { _has_field_.set(8); return set_peer_identity_.get(); }
+
+ const std::vector<std::string>& data_for_testing() const { return data_for_testing_; }
+ std::vector<std::string>* mutable_data_for_testing() { return &data_for_testing_; }
+ int data_for_testing_size() const { return static_cast<int>(data_for_testing_.size()); }
+ void clear_data_for_testing() { data_for_testing_.clear(); }
+ void add_data_for_testing(std::string value) { data_for_testing_.emplace_back(value); }
+ std::string* add_data_for_testing() { data_for_testing_.emplace_back(); return &data_for_testing_.back(); }
+
+ private:
+ uint64_t request_id_{};
+ ::protozero::CopyablePtr<IPCFrame_BindService> msg_bind_service_;
+ ::protozero::CopyablePtr<IPCFrame_BindServiceReply> msg_bind_service_reply_;
+ ::protozero::CopyablePtr<IPCFrame_InvokeMethod> msg_invoke_method_;
+ ::protozero::CopyablePtr<IPCFrame_InvokeMethodReply> msg_invoke_method_reply_;
+ ::protozero::CopyablePtr<IPCFrame_RequestError> msg_request_error_;
+ ::protozero::CopyablePtr<IPCFrame_SetPeerIdentity> set_peer_identity_;
+ std::vector<std::string> data_for_testing_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<9> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame_SetPeerIdentity : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kPidFieldNumber = 1,
+ kUidFieldNumber = 2,
+ kMachineIdHintFieldNumber = 3,
+ };
+
+ IPCFrame_SetPeerIdentity();
+ ~IPCFrame_SetPeerIdentity() override;
+ IPCFrame_SetPeerIdentity(IPCFrame_SetPeerIdentity&&) noexcept;
+ IPCFrame_SetPeerIdentity& operator=(IPCFrame_SetPeerIdentity&&);
+ IPCFrame_SetPeerIdentity(const IPCFrame_SetPeerIdentity&);
+ IPCFrame_SetPeerIdentity& operator=(const IPCFrame_SetPeerIdentity&);
+ bool operator==(const IPCFrame_SetPeerIdentity&) const;
+ bool operator!=(const IPCFrame_SetPeerIdentity& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_pid() const { return _has_field_[1]; }
+ int32_t pid() const { return pid_; }
+ void set_pid(int32_t value) { pid_ = value; _has_field_.set(1); }
+
+ bool has_uid() const { return _has_field_[2]; }
+ int32_t uid() const { return uid_; }
+ void set_uid(int32_t value) { uid_ = value; _has_field_.set(2); }
+
+ bool has_machine_id_hint() const { return _has_field_[3]; }
+ const std::string& machine_id_hint() const { return machine_id_hint_; }
+ void set_machine_id_hint(const std::string& value) { machine_id_hint_ = value; _has_field_.set(3); }
+
+ private:
+ int32_t pid_{};
+ int32_t uid_{};
+ std::string machine_id_hint_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame_RequestError : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kErrorFieldNumber = 1,
+ };
+
+ IPCFrame_RequestError();
+ ~IPCFrame_RequestError() override;
+ IPCFrame_RequestError(IPCFrame_RequestError&&) noexcept;
+ IPCFrame_RequestError& operator=(IPCFrame_RequestError&&);
+ IPCFrame_RequestError(const IPCFrame_RequestError&);
+ IPCFrame_RequestError& operator=(const IPCFrame_RequestError&);
+ bool operator==(const IPCFrame_RequestError&) const;
+ bool operator!=(const IPCFrame_RequestError& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_error() const { return _has_field_[1]; }
+ const std::string& error() const { return error_; }
+ void set_error(const std::string& value) { error_ = value; _has_field_.set(1); }
+
+ private:
+ std::string error_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame_InvokeMethodReply : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kSuccessFieldNumber = 1,
+ kHasMoreFieldNumber = 2,
+ kReplyProtoFieldNumber = 3,
+ };
+
+ IPCFrame_InvokeMethodReply();
+ ~IPCFrame_InvokeMethodReply() override;
+ IPCFrame_InvokeMethodReply(IPCFrame_InvokeMethodReply&&) noexcept;
+ IPCFrame_InvokeMethodReply& operator=(IPCFrame_InvokeMethodReply&&);
+ IPCFrame_InvokeMethodReply(const IPCFrame_InvokeMethodReply&);
+ IPCFrame_InvokeMethodReply& operator=(const IPCFrame_InvokeMethodReply&);
+ bool operator==(const IPCFrame_InvokeMethodReply&) const;
+ bool operator!=(const IPCFrame_InvokeMethodReply& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_success() const { return _has_field_[1]; }
+ bool success() const { return success_; }
+ void set_success(bool value) { success_ = value; _has_field_.set(1); }
+
+ bool has_has_more() const { return _has_field_[2]; }
+ bool has_more() const { return has_more_; }
+ void set_has_more(bool value) { has_more_ = value; _has_field_.set(2); }
+
+ bool has_reply_proto() const { return _has_field_[3]; }
+ const std::string& reply_proto() const { return reply_proto_; }
+ void set_reply_proto(const std::string& value) { reply_proto_ = value; _has_field_.set(3); }
+ void set_reply_proto(const void* p, size_t s) { reply_proto_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(3); }
+
+ private:
+ bool success_{};
+ bool has_more_{};
+ std::string reply_proto_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame_InvokeMethod : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kServiceIdFieldNumber = 1,
+ kMethodIdFieldNumber = 2,
+ kArgsProtoFieldNumber = 3,
+ kDropReplyFieldNumber = 4,
+ };
+
+ IPCFrame_InvokeMethod();
+ ~IPCFrame_InvokeMethod() override;
+ IPCFrame_InvokeMethod(IPCFrame_InvokeMethod&&) noexcept;
+ IPCFrame_InvokeMethod& operator=(IPCFrame_InvokeMethod&&);
+ IPCFrame_InvokeMethod(const IPCFrame_InvokeMethod&);
+ IPCFrame_InvokeMethod& operator=(const IPCFrame_InvokeMethod&);
+ bool operator==(const IPCFrame_InvokeMethod&) const;
+ bool operator!=(const IPCFrame_InvokeMethod& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_service_id() const { return _has_field_[1]; }
+ uint32_t service_id() const { return service_id_; }
+ void set_service_id(uint32_t value) { service_id_ = value; _has_field_.set(1); }
+
+ bool has_method_id() const { return _has_field_[2]; }
+ uint32_t method_id() const { return method_id_; }
+ void set_method_id(uint32_t value) { method_id_ = value; _has_field_.set(2); }
+
+ bool has_args_proto() const { return _has_field_[3]; }
+ const std::string& args_proto() const { return args_proto_; }
+ void set_args_proto(const std::string& value) { args_proto_ = value; _has_field_.set(3); }
+ void set_args_proto(const void* p, size_t s) { args_proto_.assign(reinterpret_cast<const char*>(p), s); _has_field_.set(3); }
+
+ bool has_drop_reply() const { return _has_field_[4]; }
+ bool drop_reply() const { return drop_reply_; }
+ void set_drop_reply(bool value) { drop_reply_ = value; _has_field_.set(4); }
+
+ private:
+ uint32_t service_id_{};
+ uint32_t method_id_{};
+ std::string args_proto_{};
+ bool drop_reply_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<5> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame_BindServiceReply : public ::protozero::CppMessageObj {
+ public:
+ using MethodInfo = IPCFrame_BindServiceReply_MethodInfo;
+ enum FieldNumbers {
+ kSuccessFieldNumber = 1,
+ kServiceIdFieldNumber = 2,
+ kMethodsFieldNumber = 3,
+ };
+
+ IPCFrame_BindServiceReply();
+ ~IPCFrame_BindServiceReply() override;
+ IPCFrame_BindServiceReply(IPCFrame_BindServiceReply&&) noexcept;
+ IPCFrame_BindServiceReply& operator=(IPCFrame_BindServiceReply&&);
+ IPCFrame_BindServiceReply(const IPCFrame_BindServiceReply&);
+ IPCFrame_BindServiceReply& operator=(const IPCFrame_BindServiceReply&);
+ bool operator==(const IPCFrame_BindServiceReply&) const;
+ bool operator!=(const IPCFrame_BindServiceReply& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_success() const { return _has_field_[1]; }
+ bool success() const { return success_; }
+ void set_success(bool value) { success_ = value; _has_field_.set(1); }
+
+ bool has_service_id() const { return _has_field_[2]; }
+ uint32_t service_id() const { return service_id_; }
+ void set_service_id(uint32_t value) { service_id_ = value; _has_field_.set(2); }
+
+ const std::vector<IPCFrame_BindServiceReply_MethodInfo>& methods() const { return methods_; }
+ std::vector<IPCFrame_BindServiceReply_MethodInfo>* mutable_methods() { return &methods_; }
+ int methods_size() const;
+ void clear_methods();
+ IPCFrame_BindServiceReply_MethodInfo* add_methods();
+
+ private:
+ bool success_{};
+ uint32_t service_id_{};
+ std::vector<IPCFrame_BindServiceReply_MethodInfo> methods_;
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<4> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame_BindServiceReply_MethodInfo : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kIdFieldNumber = 1,
+ kNameFieldNumber = 2,
+ };
+
+ IPCFrame_BindServiceReply_MethodInfo();
+ ~IPCFrame_BindServiceReply_MethodInfo() override;
+ IPCFrame_BindServiceReply_MethodInfo(IPCFrame_BindServiceReply_MethodInfo&&) noexcept;
+ IPCFrame_BindServiceReply_MethodInfo& operator=(IPCFrame_BindServiceReply_MethodInfo&&);
+ IPCFrame_BindServiceReply_MethodInfo(const IPCFrame_BindServiceReply_MethodInfo&);
+ IPCFrame_BindServiceReply_MethodInfo& operator=(const IPCFrame_BindServiceReply_MethodInfo&);
+ bool operator==(const IPCFrame_BindServiceReply_MethodInfo&) const;
+ bool operator!=(const IPCFrame_BindServiceReply_MethodInfo& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_id() const { return _has_field_[1]; }
+ uint32_t id() const { return id_; }
+ void set_id(uint32_t value) { id_ = value; _has_field_.set(1); }
+
+ bool has_name() const { return _has_field_[2]; }
+ const std::string& name() const { return name_; }
+ void set_name(const std::string& value) { name_ = value; _has_field_.set(2); }
+
+ private:
+ uint32_t id_{};
+ std::string name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<3> _has_field_{};
+};
+
+
+class PERFETTO_EXPORT_COMPONENT IPCFrame_BindService : public ::protozero::CppMessageObj {
+ public:
+ enum FieldNumbers {
+ kServiceNameFieldNumber = 1,
+ };
+
+ IPCFrame_BindService();
+ ~IPCFrame_BindService() override;
+ IPCFrame_BindService(IPCFrame_BindService&&) noexcept;
+ IPCFrame_BindService& operator=(IPCFrame_BindService&&);
+ IPCFrame_BindService(const IPCFrame_BindService&);
+ IPCFrame_BindService& operator=(const IPCFrame_BindService&);
+ bool operator==(const IPCFrame_BindService&) const;
+ bool operator!=(const IPCFrame_BindService& other) const { return !(*this == other); }
+
+ bool ParseFromArray(const void*, size_t) override;
+ std::string SerializeAsString() const override;
+ std::vector<uint8_t> SerializeAsArray() const override;
+ void Serialize(::protozero::Message*) const;
+
+ bool has_service_name() const { return _has_field_[1]; }
+ const std::string& service_name() const { return service_name_; }
+ void set_service_name(const std::string& value) { service_name_ = value; _has_field_.set(1); }
+
+ private:
+ std::string service_name_{};
+
+ // Allows to preserve unknown protobuf fields for compatibility
+ // with future versions of .proto files.
+ std::string unknown_fields_;
+
+ std::bitset<2> _has_field_{};
+};
+
+} // namespace perfetto
+} // namespace protos
+} // namespace gen
+
+#endif // PERFETTO_PROTOS_PROTOS_PERFETTO_IPC_WIRE_PROTOCOL_PROTO_CPP_H_
+// gen_amalgamated begin header: include/perfetto/protozero/gen_field_helpers.h
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
+#define INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
+
+// gen_amalgamated expanded: #include "perfetto/protozero/message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_heap_buffer.h"
+
+namespace protozero {
+namespace internal {
+namespace gen_helpers {
+
+// This file implements some helpers used by the protobuf generated code in the
+// .gen.cc files.
+//
+// The .gen.cc generated protobuf implementation (as opposed to the .pbzero.h
+// implementation) is not zero-copy and is not supposed to be used in fast
+// paths, so most of these helpers are designed to reduce binary size.
+
+void DeserializeString(const protozero::Field& field, std::string* dst);
+
+// Read packed repeated elements (serialized as `wire_type`) from `field` into
+// the `*dst` vector. Returns false if some bytes of `field` could not be
+// interpreted correctly as `wire_type`.
+template <proto_utils::ProtoWireType wire_type, typename CppType>
+bool DeserializePackedRepeated(const protozero::Field& field,
+ std::vector<CppType>* dst) {
+ bool parse_error = false;
+ for (::protozero::PackedRepeatedFieldIterator<wire_type, CppType> rep(
+ field.data(), field.size(), &parse_error);
+ rep; ++rep) {
+ dst->emplace_back(*rep);
+ }
+ return !parse_error;
+}
+
+extern template bool
+DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, uint64_t>(
+ const protozero::Field& field,
+ std::vector<uint64_t>* dst);
+
+extern template bool
+DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, int64_t>(
+ const protozero::Field& field,
+ std::vector<int64_t>* dst);
+
+extern template bool
+DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, uint32_t>(
+ const protozero::Field& field,
+ std::vector<uint32_t>* dst);
+
+extern template bool
+DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, int32_t>(
+ const protozero::Field& field,
+ std::vector<int32_t>* dst);
+
+// Serializers for different type of fields
+
+void SerializeTinyVarInt(uint32_t field_id, bool value, Message* msg);
+
+template <typename T>
+void SerializeExtendedVarInt(uint32_t field_id, T value, Message* msg) {
+ msg->AppendVarInt(field_id, value);
+}
+
+extern template void SerializeExtendedVarInt<uint64_t>(uint32_t field_id,
+ uint64_t value,
+ Message* msg);
+
+extern template void SerializeExtendedVarInt<uint32_t>(uint32_t field_id,
+ uint32_t value,
+ Message* msg);
+
+template <typename T>
+void SerializeVarInt(uint32_t field_id, T value, Message* msg) {
+ SerializeExtendedVarInt(
+ field_id, proto_utils::ExtendValueForVarIntSerialization(value), msg);
+}
+
+template <typename T>
+void SerializeSignedVarInt(uint32_t field_id, T value, Message* msg) {
+ SerializeVarInt(field_id, proto_utils::ZigZagEncode(value), msg);
+}
+
+template <typename T>
+void SerializeFixed(uint32_t field_id, T value, Message* msg) {
+ msg->AppendFixed(field_id, value);
+}
+
+extern template void SerializeFixed<double>(uint32_t field_id,
+ double value,
+ Message* msg);
+
+extern template void SerializeFixed<float>(uint32_t field_id,
+ float value,
+ Message* msg);
+
+extern template void SerializeFixed<uint64_t>(uint32_t field_id,
+ uint64_t value,
+ Message* msg);
+
+extern template void SerializeFixed<int64_t>(uint32_t field_id,
+ int64_t value,
+ Message* msg);
+
+extern template void SerializeFixed<uint32_t>(uint32_t field_id,
+ uint32_t value,
+ Message* msg);
+
+extern template void SerializeFixed<int32_t>(uint32_t field_id,
+ int32_t value,
+ Message* msg);
+
+void SerializeString(uint32_t field_id, const std::string& value, Message* msg);
+
+void SerializeUnknownFields(const std::string& unknown_fields, Message* msg);
+
+// Wrapper around HeapBuffered that avoids inlining.
+class MessageSerializer {
+ public:
+ MessageSerializer();
+ ~MessageSerializer();
+
+ Message* get() { return msg_.get(); }
+ std::vector<uint8_t> SerializeAsArray();
+ std::string SerializeAsString();
+
+ private:
+ HeapBuffered<Message> msg_;
+};
+
+// Wrapper about operator==() which reduces the binary size of generated protos.
+// This is needed because std::string's operator== is inlined aggressively (even
+// when optimizing for size). Having this layer of indirection with removes the
+// overhead.
+template <typename T>
+bool EqualsField(const T& a, const T& b) {
+ return a == b;
+}
+extern template bool EqualsField<std::string>(const std::string&,
+ const std::string&);
+
+} // namespace gen_helpers
+} // namespace internal
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
+// gen_amalgamated begin header: include/perfetto/protozero/scattered_stream_null_delegate.h
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_NULL_DELEGATE_H_
+#define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_NULL_DELEGATE_H_
+
+#include <memory>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/base/logging.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"
+
+namespace protozero {
+
+class PERFETTO_EXPORT_COMPONENT ScatteredStreamWriterNullDelegate
+ : public ScatteredStreamWriter::Delegate {
+ public:
+ explicit ScatteredStreamWriterNullDelegate(size_t chunk_size);
+ ~ScatteredStreamWriterNullDelegate() override;
+
+ // protozero::ScatteredStreamWriter::Delegate implementation.
+ ContiguousMemoryRange GetNewBuffer() override;
+
+ private:
+ const size_t chunk_size_;
+ std::unique_ptr<uint8_t[]> chunk_;
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_NULL_DELEGATE_H_
+// gen_amalgamated begin header: include/perfetto/protozero/static_buffer.h
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#ifndef INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
+#define INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+// gen_amalgamated expanded: #include "perfetto/base/export.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/root_message.h"
+// gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h"
+
+namespace protozero {
+
+class Message;
+
+// A simple implementation of ScatteredStreamWriter::Delegate backed by a
+// fixed-size buffer. It doesn't support expansion. The caller needs to ensure
+// to never write more than the size of the buffer. Will CHECK() otherwise.
+class PERFETTO_EXPORT_COMPONENT StaticBufferDelegate
+ : public ScatteredStreamWriter::Delegate {
+ public:
+ StaticBufferDelegate(uint8_t* buf, size_t len) : range_{buf, buf + len} {}
+ ~StaticBufferDelegate() override;
+
+ // ScatteredStreamWriter::Delegate implementation.
+ ContiguousMemoryRange GetNewBuffer() override;
+
+ ContiguousMemoryRange const range_;
+ bool get_new_buffer_called_once_ = false;
+};
+
+// Helper function to create protozero messages backed by a fixed-size buffer
+// in one line. You can write:
+// protozero::Static<protozero::MyMessage> msg(buf.data(), buf.size());
+// msg->set_stuff(...);
+// size_t bytes_encoded = msg.Finalize();
+template <typename T /* protozero::Message */>
+class StaticBuffered {
+ public:
+ StaticBuffered(void* buf, size_t len)
+ : delegate_(reinterpret_cast<uint8_t*>(buf), len), writer_(&delegate_) {
+ msg_.Reset(&writer_);
+ }
+
+ // This can't be neither copied nor moved because Message hands out pointers
+ // to itself when creating submessages.
+ StaticBuffered(const StaticBuffered&) = delete;
+ StaticBuffered& operator=(const StaticBuffered&) = delete;
+ StaticBuffered(StaticBuffered&&) = delete;
+ StaticBuffered& operator=(StaticBuffered&&) = delete;
+
+ T* get() { return &msg_; }
+ T* operator->() { return &msg_; }
+
+ // The lack of a size() method is deliberate. It's to prevent that one
+ // accidentally calls size() before Finalize().
+
+ // Returns the number of encoded bytes (<= the size passed in the ctor).
+ size_t Finalize() {
+ msg_.Finalize();
+ return static_cast<size_t>(writer_.write_ptr() - delegate_.range_.begin);
+ }
+
+ private:
+ StaticBufferDelegate delegate_;
+ ScatteredStreamWriter writer_;
+ RootMessage<T> msg_;
+};
+
+// Helper function to create stack-based protozero messages in one line.
+// You can write:
+// protozero::StackBuffered<protozero::MyMessage, 16> msg;
+// msg->set_stuff(...);
+// size_t bytes_encoded = msg.Finalize();
+template <typename T /* protozero::Message */, size_t N>
+class StackBuffered : public StaticBuffered<T> {
+ public:
+ StackBuffered() : StaticBuffered<T>(&buf_[0], N) {}
+
+ private:
+ uint8_t buf_[N]; // Deliberately not initialized.
+};
+
+} // namespace protozero
+
+#endif // INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
+
diff --git a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/METADATA b/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/METADATA
deleted file mode 100644
index 0bab2150ba..0000000000
--- a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/METADATA
+++ /dev/null
@@ -1,790 +0,0 @@
-Metadata-Version: 2.1
-Name: glean-parser
-Version: 13.0.1
-Summary: Parser tools for Mozilla's Glean telemetry
-Home-page: https://github.com/mozilla/glean_parser
-Author: The Glean Team
-Author-email: glean-team@mozilla.com
-Keywords: glean_parser
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Natural Language :: English
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: 3.11
-Classifier: Programming Language :: Python :: 3.12
-Description-Content-Type: text/markdown
-License-File: LICENSE
-License-File: AUTHORS.md
-Requires-Dist: appdirs >=1.4
-Requires-Dist: Click >=7
-Requires-Dist: diskcache >=4
-Requires-Dist: Jinja2 >=2.10.1
-Requires-Dist: jsonschema >=3.0.2
-Requires-Dist: PyYAML >=5.3.1
-
-# Glean Parser
-
-Parser tools for Mozilla's Glean telemetry.
-
-## Features
-
-Contains various utilities for handling `metrics.yaml` and `pings.yaml` for [the
-Glean SDKs](https://mozilla.github.io/glean). This includes producing generated
-code for various integrations, linting and coverage testing.
-
-## Documentation
-
-- [How to Contribute](https://github.com/mozilla/glean_parser/blob/main/CONTRIBUTING.md). Please file bugs in [bugzilla](https://bugzilla.mozilla.org/enter_bug.cgi?assigned_to=nobody%40mozilla.org&bug_ignored=0&bug_severity=normal&bug_status=NEW&cf_fission_milestone=---&cf_fx_iteration=---&cf_fx_points=---&cf_status_firefox65=---&cf_status_firefox66=---&cf_status_firefox67=---&cf_status_firefox_esr60=---&cf_status_thunderbird_esr60=---&cf_tracking_firefox65=---&cf_tracking_firefox66=---&cf_tracking_firefox67=---&cf_tracking_firefox_esr60=---&cf_tracking_firefox_relnote=---&cf_tracking_thunderbird_esr60=---&product=Data%20Platform%20and%20Tools&component=Glean%3A%20SDK&contenttypemethod=list&contenttypeselection=text%2Fplain&defined_groups=1&flag_type-203=X&flag_type-37=X&flag_type-41=X&flag_type-607=X&flag_type-721=X&flag_type-737=X&flag_type-787=X&flag_type-799=X&flag_type-800=X&flag_type-803=X&flag_type-835=X&flag_type-846=X&flag_type-855=X&flag_type-864=X&flag_type-916=X&flag_type-929=X&flag_type-930=X&flag_type-935=X&flag_type-936=X&flag_type-937=X&form_name=enter_bug&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Unspecified&priority=P3&&rep_platform=Unspecified&status_whiteboard=%5Btelemetry%3Aglean-rs%3Am%3F%5D&target_milestone=---&version=unspecified).
-- [User documentation for Glean](https://mozilla.github.io/glean/).
-- [`glean_parser` developer documentation](https://mozilla.github.io/glean_parser/).
-
-## Requirements
-
-- Python 3.8 (or later)
-
-The following library requirements are installed automatically when
-`glean_parser` is installed by `pip`.
-
-- appdirs
-- Click
-- diskcache
-- Jinja2
-- jsonschema
-- PyYAML
-
-## Usage
-
-```sh
-$ glean_parser --help
-```
-
-Read in `metrics.yaml`, translate to Kotlin format, and
-output to `output_dir`:
-
-```sh
-$ glean_parser translate -o output_dir -f kotlin metrics.yaml
-```
-
-Check a Glean ping against the ping schema:
-
-```sh
-$ glean_parser check < ping.json
-```
-
-
-# Changelog
-
-## Unreleased
-
-## 13.0.1
-
-- Use faster C yaml parser if available ([#677](https://github.com/mozilla/glean_parser/pull/677))
-
-## 13.0.0
-
-- BREAKING CHANGE: Support metadata field `include_info_sections` ([bug 1866559](https://bugzilla.mozilla.org/show_bug.cgi?id=1866559))
-
-## 12.0.1
-
-- Fix Rust codegen for object metric type ([#662](https://github.com/mozilla/glean_parser/pull/662))
-
-## 12.0.0
-
-- Add new metric type object (only Rust codegen support right now) ([#587](https://github.com/mozilla/glean_parser/pull/587))
-
-## 11.1.0
-
-- Add Go log outputter (`go_server`) ([#645](https://github.com/mozilla/glean_parser/pull/645))
-- Add Python log outputter (`python_server`) ([MPP-3642](https://mozilla-hub.atlassian.net/browse/MPP-3642))
-
-## 11.0.1
-
-- Fix javascript_server template to include non-event metric parameters in #record call for event metrics ([#643](https://github.com/mozilla/glean_parser/pull/643))
-- events: Increase extra key limit to 50 ([Bug 1869429](https://bugzilla.mozilla.org/show_bug.cgi?id=1869429))
-
-## 11.0.0
-
-- Add updated logging logic for Ruby Server ([#642](https://github.com/mozilla/glean_parser/pull/642))
-- Add support for event metric type in server-side JavaScript outputter ([DENG-1736](https://mozilla-hub.atlassian.net/browse/DENG-1736))
-- BREAKING CHANGE: Dropped support for Python 3.7 ([#638](https://github.com/mozilla/glean_parser/pull/638))
-- Add official support for Python 3.11+ ([#638](https://github.com/mozilla/glean_parser/pull/638))
-
-## 10.0.3
-
-- Warn about empty or TODO-tagged data reviews in the list ([#634](https://github.com/mozilla/glean_parser/pull/634))
-- Allow `unit` field on all metrics, but warn for all but quantity and custom distribution ([#636](https://github.com/mozilla/glean_parser/pull/636))
-
-## 10.0.2
-
-- Allow `unit` field for string again, but warn about it in the linter ([#634](https://github.com/mozilla/glean_parser/pull/634))
-
-## 10.0.1
-
-- Allow `unit` field for custom distribution again ([#633](https://github.com/mozilla/glean_parser/pull/633))
-
-## 10.0.0
-
-- Add Ruby log outputter (`ruby_server`) ([#620](https://github.com/mozilla/glean_parser/pull/620))
-- BREAKING CHANE: `ping` lifetime metrics on the events ping are now disallowed ([#625](https://github.com/mozilla/glean_parser/pull/625))
-- Disallow `unit` field for anything but quantity ([#630](https://github.com/mozilla/glean_parser/pull/630)).
- Note that this was already considered the case, now the code enforces it.
-
-## 9.0.0
-
-- BREAKING CHANGE: Dropped support for Python 3.6 ([#615](https://github.com/mozilla/glean_parser/issues/615))
-- Allow metadata to configure precise timestamps in pings ([#592](https://github.com/mozilla/glean_parser/pull/592))
-
-## 8.1.1
-
-- Small updates to the `javascript_server` tempalte to address lint warnings ([#598](https://github.com/mozilla/glean_parser/pull/598))
-
-## 8.1.0
-
-- Increased the maximum metric name length in version 2.0.0 schema ([#596](https://github.com/mozilla/glean_parser/pull/596))
-
-## 8.0.0
-
-- BREAKING CHANGE: Remove exposed `lint_yaml_files` function ([#580](https://github.com/mozilla/glean_parser/pull/580))
-- Rust: Removed `__glean_metric_maps` from the Rust Jinja template. This functionality is better placed downstream ([Bug 1816526](https://bugzilla.mozilla.org/show_bug.cgi?id=1816526))
-- New lint: check that all referenced pings are known ([#584](https://github.com/mozilla/glean_parser/pull/584))
-- Add experimental server-side JavaScript outputter ([FXA-7922](https://mozilla-hub.atlassian.net/browse/FXA-7922))
-
-## 7.2.1
-
-- Unbreak last minor release ([#579](https://github.com/mozilla/glean_parser/pull/579))
-
-## 7.2.0
-
-- Remove yamllint integration ([#578](https://github.com/mozilla/glean_parser/pull/578))
-
-## 7.1.0
-
-- ENHANCEMENT: Labels in `labels:` fields may now contain any printable ASCII characters ([bug 1672273](https://bugzilla.mozilla.org/show_bug.cgi?id=1672273))
-- BUGFIX: Enforce ordering of generation of Pings, Metrics and Tags such that order is deterministic ([bug 1820334](https://bugzilla.mozilla.org/show_bug.cgi?id=1820334))
-
-## 7.0.0
-
-- BUGFIX: Remove internal-only fields from serialized metrics data ([#550](https://github.com/mozilla/glean_parser/pull/550))
-- FEATURE: New subcommand: `dump` to dump the metrics data as JSON ([#550](https://github.com/mozilla/glean_parser/pull/550))
-- BUGFIX: Kotlin: Generate enums with the right generic bound for ping reason codes ([#551](https://github.com/mozilla/glean_parser/pull/551)).
-- **BREAKING CHANGE:** Fully remove support for the old events API ([#549](https://github.com/mozilla/glean_parser/pull/549))
- Adds a new lint `OLD_EVENT_API` to warn about missing `type` attributes on event extra keys.
- Note that the Glean SDK already dropped support for the old events API.
-
-## 6.4.0
-
-- BUGFIX: Correct code generation for labeled metrics in Rust ([#533](https://github.com/mozilla/glean_parser/pull/533))
-- BUGFIX: Correctly serialize `Rates` for Rust code ([#530](https://github.com/mozilla/glean_parser/pull/530))
-- Feature: Wrap labeled metric's static labels list as CoW strings (requires updated Glean support) ([#534](https://github.com/mozilla/glean_parser/pull/534))
-
-## 6.3.0
-
-- events: Increase extras limit to 15 ([bug 1798713](https://bugzilla.mozilla.org/show_bug.cgi?id=1798713))
-
-## 6.2.1
-
-- Add support for Rate, Denominator and Numerator metrics for JavaScript. ([bug 1793777](https://bugzilla.mozilla.org/show_bug.cgi?id=1793777))
-
-## 6.2.0
-
-- [data-review] Use a template to generate the Data Review Request template ([bug 1772605](https://bugzilla.mozilla.org/show_bug.cgi?id=1772605))
-- Make tag and no\_lint order deterministic ([#518](https://github.com/mozilla/glean_parser/pull/518))
-
-## 6.1.2
-
-- Swift: Add a conditional `import Foundation` to support generating metrics when Glean is delivered via the AppServices iOS megazord
-
-## 6.1.1
-
-- Rust: Use correct name for a ping in generated code.
-
-## 6.1.0
-
-- [data-review] Include extra keys' names and descriptions in data review template ([bug 1767027](https://bugzilla.mozilla.org/show_bug.cgi?id=1767027))
-- Raise limit on number of statically-defined labels to 4096. ([bug 1772163](https://bugzilla.mozilla.org/show_bug.cgi?id=1772163))
-- Fix Rust code generation for new UniFFI interface ([#491](https://github.com/mozilla/glean_parser/pull/491), [#494](https://github.com/mozilla/glean_parser/pull/494), [#495](https://github.com/mozilla/glean_parser/pull/495))
-
-## 6.0.1
-
-- Relax version requirement for MarkupSafe.
- Now works with MarkupSafe v1.1.1 to v2.0.1 inclusive again.
-
-## 6.0.0
-
-- BUGFIX: Add missing `extra_args` to Rust constructor generation ([bug 1765855](https://bugzilla.mozilla.org/show_bug.cgi?id=1765855))
-- **Breaking change:** `glean_parser` now generates metrics compatible with the UniFFI-powered Glean SDK.
- This is not backwards-compatible with previous versions.
-- Generate Rate, Denominator and Numerator metrics for Kotlin and Swift
-- Explicitly skip Rate, Denominator and Numerator metrics for JavaScript.
- These will cause a build failure by default, but can be turned into warnings on request.
- Use `-s fail_rates=false` to enable warning-only mode.
-
-## 5.1.2
-
-- BUGFIX: Revert changes made on v5.1.1.
- - The issues addressed by those changes, were non-issues and result of misuse of the APIs.
-
-## 5.1.1
-
-- BUGFIX: Fix issues with Swift templates ([bug 1749494](https://bugzilla.mozilla.org/show_bug.cgi?id=1749494))
- - Make metrics and pings all `public`
- - Make pings `static`
-
-## 5.1.0
-
-- Add support for build info generation for JavaScript and Typescript targets ([bug 1749494](https://bugzilla.mozilla.org/show_bug.cgi?id=1749494))
-
-## 5.0.1
-
-- Fix the logic for the metric expiration by version ([bug 1753194](https://bugzilla.mozilla.org/show_bug.cgi?id=1753194))
-
-## 5.0.0
-
-- Remove C# support ([#436](https://github.com/mozilla/glean_parser/pull/436)).
-- Add support for Rust code generation ([bug 1677434](https://bugzilla.mozilla.org/show_bug.cgi?id=1677434))
-- Report an error if no files are passed ([bug 1751730](https://bugzilla.mozilla.org/show_bug.cgi?id=1751730))
-- [data-review] Report an error if no metrics match provided bug number ([bug 1752576](https://bugzilla.mozilla.org/show_bug.cgi?id=1752576))
-- [data-review] Include notification_emails in list of those responsible ([bug 1752576](https://bugzilla.mozilla.org/show_bug.cgi?id=1752576))
-- Add support for expiring metrics by the provided major version ([bug 1753194](https://bugzilla.mozilla.org/show_bug.cgi?id=1753194))
-
-## 4.4.0
-
-- Support global file-level tags in metrics.yaml ([bug 1745283](https://bugzilla.mozilla.org/show_bug.cgi?id=1745283))
-- Glinter: Reject metric files if they use `unit` by mistake. It should be `time_unit` ([#432](https://github.com/mozilla/glean_parser/pull/432)).
-- Automatically generate a build date when generating build info ([#431](https://github.com/mozilla/glean_parser/pull/431)).
- Enabled for Kotlin and Swift.
- This can be changed with the `build_date` command line option.
- `build_date=0` will use a static unix epoch time.
- `build_date=2022-01-03T17:30:00` will parse the ISO8601 string to use (as a UTC timestamp).
- Other values will throw an error.
-
- Example:
-
- glean_parser translate --format kotlin --option build_date=2021-11-01T01:00:00 path/to/metrics.yaml
-
-## 4.3.1
-
-- BUGFIX: Skip tags for code generation ([#409](https://github.com/mozilla/glean_parser/pull/409))
-
-## 4.3.0
-
-- Support tags in glean parser ([bug 1734011](https://bugzilla.mozilla.org/show_bug.cgi?id=1734011))
-
-## 4.2.0
-
-- Improve the schema validation error messages. They will no longer include `OrderedDict(...)` on Python 3.7 and later ([bug 1733395](https://bugzilla.mozilla.org/show_bug.cgi?id=1733395))
-- Officially support Python 3.10
-
-## 4.1.1 (2021-09-28)
-
-- Update private import paths on Javascript / Typescript templates. ([bug 1702468](https://bugzilla.mozilla.org/show_bug.cgi?id=1702468))
-
-## 4.1.0 (2021-09-16)
-
-- Add support for Node.js platform on Javascript / Typescript templates. ([bug 1728982](https://bugzilla.mozilla.org/show_bug.cgi?id=1728982))
-
-## 4.0.0 (2021-08-20)
-
-- Add support for Text metric type ([#374](https://github.com/mozilla/glean_parser/pull/374))
-- Reserve the `default` ping name. It can't be used as a ping name, but it can be used in `send_in_pings` ([#376](https://github.com/mozilla/glean_parser/pull/376))
-
-## 3.8.0 (2021-08-18)
-
-- Expose ping reasons enum on JavaScript / TypeScript templates. ([bug 1719136](https://bugzilla.mozilla.org/show_bug.cgi?id=1719136))
-- Define an interface with the allowed extras for each event on the TypeScript template. ([bug 1693487](https://bugzilla.mozilla.org/show_bug.cgi?id=1693487))
-
-## 3.7.0 (2021-07-13)
-
-- New lint: Check for redundant words in ping names ([#355](https://github.com/mozilla/glean_parser/pull/355))
-- Add support for URL metric type ([#361](https://github.com/mozilla/glean_parser/pull/361))
-
-## 3.6.0 (2021-06-11)
-
-- Add a command `data-review` to generate a skeleton Data Review Request for all metrics matching a supplied bug number. ([bug 1704541](https://bugzilla.mozilla.org/show_bug.cgi?id=1704541))
-- Enable custom distribution outside of GeckoView (`gecko_datapoint` becomes optional)
-
-## 3.5.0 (2021-06-03)
-
-- Transform generated folder into QML Module when building Javascript templates for the Qt platform. ([bug 1707896](https://bugzilla.mozilla.org/show_bug.cgi?id=1707896)
- - Import the Glean QML module from inside each generated file, removing the requirement to import Glean before importing any of the generated files;
- - Prodive a `qmldir` file exposing all generated files;
- - Drop the `namespace` option for Javascript templates;
- - Add a new `version` option for Javascript templates, required when building for Qt, which expected the Glean QML module version.
-
-## 3.4.0 (2021-05-28)
-
-- Add missing import for Kotlin code ([#339](https://github.com/mozilla/glean_parser/pull/339))
-- Use a plain Kotlin type in the generated interface implementation ([#339](https://github.com/mozilla/glean_parser/pull/339))
-- Generate additional generics for event metrics ([#339](https://github.com/mozilla/glean_parser/pull/339))
-- For Kotlin skip generating `GleanBuildInfo.kt` when requested (with `with_buildinfo=false`) ([#341](https://github.com/mozilla/glean_parser/pull/341))
-
-## 3.3.2 (2021-05-18)
-
-- Fix another bug in the Swift code generation when generating extra keys ([#334](https://github.com/mozilla/glean_parser/pull/334))
-
-## 3.3.1 (2021-05-18)
-
-- Fix Swift code generation bug for pings ([#333](https://github.com/mozilla/glean_parser/pull/333))
-
-## 3.3.0 (2021-05-18)
-
-- Generate new event API construct ([#321](https://github.com/mozilla/glean_parser/pull/321))
-
-## 3.2.0 (2021-04-28)
-
-- Add option to add extra introductory text to generated markdown ([#298](https://github.com/mozilla/glean_parser/pull/298))
-- Add support for Qt in Javascript templates ([bug 1706252](https://bugzilla.mozilla.org/show_bug.cgi?id=1706252))
- - Javascript templates will now accept the `platform` option. If this option is set to `qt`
- the generated templates will be Qt compatible. Default value is `webext`.
-
-## 3.1.2 (2021-04-21)
-
-- BUGFIX: Remove the "DO NOT COMMIT" notice from the documentation.
-
-## 3.1.1 (2021-04-19)
-
-- Recommend to not commit as well as to not edit the generated files. ([bug 1706042](https://bugzilla.mozilla.org/show_bug.cgi?id=1706042))
-- BUGFIX: Include import statement for labeled metric subtypes in Javascript and Typescript templates.
-
-## 3.1.0 (2021-04-16)
-
-- Add support for labeled metric types in Javascript and Typescript templates.
-
-## 3.0.0 (2021-04-13)
-
-- Raise limit on number of statically-defined lables to 100. ([bug 1702263](https://bugzilla.mozilla.org/show_bug.cgi?id=1702263))
-- BUGFIX: Version 2.0.0 of the schema now allows the "special" `glean_.*` ping names for Glean-internal use again.
-- Remove support for JWE metric types.
-
-## 2.5.0 (2021-02-23)
-
-- Add parser and object model support for `rate` metric type. ([bug 1645166](https://bugzilla.mozilla.org/show_bug.cgi?id=1645166))
-- Add parser and object model support for telemetry_mirror property. ([bug 1685406](https://bugzilla.mozilla.org/show_bug.cgi?id=1685406))
-- Update the Javascript template to match Glean.js expectations. ([bug 1693516](https://bugzilla.mozilla.org/show_bug.cgi?id=1693516))
- - Glean.js has updated it's export strategy. It will now export each metric type as an independent module;
- - Glean.js has dropped support for non ES6 modules.
-- Add support for generating Typescript code. ([bug 1692157](https://bugzilla.mozilla.org/show_bug.cgi?id=1692157))
- - The templates added generate metrics and pings code for Glean.js.
-
-## 2.4.0 (2021-02-18)
-
-- **Experimental:** `glean_parser` has a new subcommand `coverage` to convert raw coverage reports
- into something consumable by coverage tools, such as codecov.io
-- The path to the file that each metric is defined in is now stored on the
- `Metric` object in `defined_in["filepath"]`.
-
-## 2.3.0 (2021-02-17)
-
-- Leverage the `glean_namespace` to provide correct import when building for Javascript.
-
-## 2.2.0 (2021-02-11)
-
-- The Kotlin generator now generates static build information that can be passed
- into `Glean.initialize` to avoid calling the package manager at runtime.
-
-## 2.1.0 (2021-02-10)
-
-- Add support for generating Javascript code.
- - The templates added generate metrics and pings code for Glean.js.
-
-## 2.0.0 (2021-02-05)
-
-- New versions 2.0.0 of the `metrics.yaml` and `pings.yaml` schemas now ship
- with `glean_parser`. These schemas are different from version 1.0.0 in the
- following ways:
-
- - Bugs must be specified as URLs. Bug numbers are disallowed.
- - The legacy ping names containing underscores are no longer allowed. These
- included `deletion_request`, `bookmarks_sync`, `history_sync`,
- `session_end`, `all_pings`, `glean_*`). In these cases, the `_` should be
- replaced with `-`.
-
- To upgrade your app or library to use the new schema, replace the version in
- the `$schema` value with `2-0-0`.
-
-- **Breaking change:** It is now an error to use bug numbers (rather than URLs)
- in ping definitions.
-
-- Add the line number that metrics and pings were originally defined in the yaml
- files.
-
-## 1.29.1 (2020-12-17)
-
-- BUGFIX: Linter output can now be redirected correctly (1675771).
-
-## 1.29.0 (2020-10-07)
-
-- **Breaking change:** `glean_parser` will now return an error code when any of
- the input files do not exist (unless the `--allow-missing-files` flag is
- passed).
-- Generated code now includes a comment next to each metric containing the name
- of the metric in its original `snake_case` form.
-- When metrics don't provide a `unit` parameter, it is not included in the
- output (as provided by probe-scraper).
-
-## 1.28.6 (2020-09-24)
-
-- BUGFIX: Ensure Kotlin arguments are deterministically ordered
-
-## 1.28.5 (2020-09-14)
-
-- Fix deploy step to update pip before deploying to pypi.
-
-## 1.28.4 (2020-09-14)
-
-- The `SUPERFLUOUS_NO_LINT` warning has been removed from the glinter.
- It likely did more harm than good, and makes it hard to make
- `metrics.yaml` files that pass across different versions of
- `glean_parser`.
-- Expired metrics will now produce a linter warning, `EXPIRED_METRIC`.
-- Expiry dates that are more than 730 days (\~2 years) in the future
- will produce a linter warning, `EXPIRATION_DATE_TOO_FAR`.
-- Allow using the Quantity metric type outside of Gecko.
-- New parser configs `custom_is_expired` and `custom_validate_expires`
- added. These are both functions that take the `expires` value of the
- metric and return a bool. (See `Metric.is_expired` and
- `Metric.validate_expires`). These will allow FOG to provide custom
- validation for its version-based `expires` values.
-
-## 1.28.3 (2020-07-28)
-
-- BUGFIX: Support HashSet and Dictionary in the C\## generated code.
-
-## 1.28.2 (2020-07-28)
-
-- BUGFIX: Generate valid C\## code when using Labeled metric types.
-
-## 1.28.1 (2020-07-24)
-
-- BUGFIX: Add missing column to correctly render markdown tables in generated
- documentation.
-
-## 1.28.0 (2020-07-23)
-
-- **Breaking change:** The internal ping `deletion-request` was misnamed in
- pings.py causing the linter to not allow use of the correctly named ping for
- adding legacy ids to. Consuming apps will need to update their metrics.yaml if
- they are using `deletion_request` in any `send_in_pings` to `deletion-request`
- after updating.
-
-## 1.27.0 (2020-07-21)
-
-- Rename the `data_category` field to `data_sensitivity` to be clearer.
-
-## 1.26.0 (2020-07-21)
-
-- Add support for JWE metric types.
-- Add a `data_sensitivity` field to all metrics for specifying the type of data
- collected in the field.
-
-## 1.25.0 (2020-07-17)
-
-- Add support for generating C\## code.
-- BUGFIX: The memory unit is now correctly passed to the MemoryDistribution
- metric type in Swift.
-
-## 1.24.0 (2020-06-30)
-
-- BUGFIX: look for metrics in send\_if\_empty pings. Metrics for these kinds of
- pings were being ignored.
-
-## 1.23.0 (2020-06-27)
-
-- Support for Python 3.5 has been dropped.
-- BUGFIX: The ordering of event extra keys will now match with their enum,
- fixing a serious bug where keys of extras may not match the correct values in
- the data payload. See <https://bugzilla.mozilla.org/show_bug.cgi?id=1648768>.
-
-## 1.22.0 (2020-05-28)
-
-- **Breaking change:** (Swift only) Combine all metrics and pings into a single
- generated file `Metrics.swift`.
-
-## 1.21.0 (2020-05-25)
-
-- `glinter` messages have been improved with more details and to be more
- actionable.
-- A maximum of 10 `extra_keys` is now enforced for `event` metric types.
-- BUGFIX: the `Lifetime` enum values now match the values of the implementation
- in mozilla/glean.
-
-## 1.20.4 (2020-05-07)
-
-- BUGFIX: yamllint errors are now reported using the correct file name.
-
-## 1.20.3 (2020-05-06)
-
-- Support for using `timing_distribution`'s `time_unit` parameter to control
- the range of acceptable values is documented. The default unit for this use
- case is `nanosecond` to avoid creating a breaking change. See [bug
- 1630997](https://bugzilla.mozilla.org/show_bug.cgi?id=1630997) for more
- information.
-
-## 1.20.2 (2020-04-24)
-
-- Dependencies that depend on the version of Python being used are now specified
- using the [Declaring platform specific dependencies syntax in
- setuptools](https://setuptools.readthedocs.io/en/latest/setuptools.html##declaring-platform-specific-dependencies).
- This means that more recent versions of dependencies are likely to be
- installed on Python 3.6 and later, and unnecessary backport libraries won't
- be installed on more recent Python versions.
-
-## 1.20.1 (2020-04-21)
-
-- The minimum version of the runtime dependencies has been lowered to increase
- compatibility with other tools. These minimum versions are now tested in CI,
- in addition to testing the latest versions of the dependencies that was
- already happening in CI.
-
-## 1.20.0 (2020-04-15)
-
-- **Breaking change:** glinter errors found during the `translate` command will
- now return an error code. glinter warnings will be displayed, but not return
- an error code.
-- `glean_parser` now produces a linter warning when `user` lifetime metrics are
- set to expire. See [bug
- 1604854](https://bugzilla.mozilla.org/show_bug.cgi?id=1604854) for additional
- context.
-
-## 1.19.0 (2020-03-18)
-
-- **Breaking change:** The regular expression used to validate labels is
- stricter and more correct.
-- Add more information about pings to markdown documentation:
- - State whether the ping includes client id;
- - Add list of data review links;
- - Add list of related bugs links.
-- `glean_parser` now makes it easier to write external translation
- functions for different language targets.
-- BUGFIX: `glean_parser` now works on 32-bit Windows.
-
-## 1.18.3 (2020-02-24)
-
-- Dropped the `inflection` dependency.
-- Constrained the `zipp` and `MarkupSafe` transitive dependencies to versions
- that support Python 3.5.
-
-## 1.18.2 (2020-02-14)
-
-- BUGFIX: Fix rendering of first element of reason list.
-
-## 1.18.1 (2020-02-14)
-
-- BUGFIX: Reason codes are displayed in markdown output for built-in
- pings as well.
-- BUGFIX: Reason descriptions are indented correctly in markdown
- output.
-- BUGFIX: To avoid a compiler error, the `@JvmName` annotation isn't
- added to private members.
-
-## 1.18.0 (2020-02-13)
-
-- **Breaking Change (Java API)** Have the metrics names in Java match the names
- in Kotlin. See [Bug
- 1588060](https://bugzilla.mozilla.org/show_bug.cgi?id=1588060).
-- The reasons a ping are sent are now included in the generated markdown
- documentation.
-
-## 1.17.3 (2020-02-05)
-
-- BUGFIX: The version of Jinja2 now specifies < 3.0, since that version no
- longer supports Python 3.5.
-
-## 1.17.2 (2020-02-05)
-
-- BUGFIX: Fixes an import error in generated Kotlin code.
-
-## 1.17.1 (2020-02-05)
-
-- BUGFIX: Generated Swift code now includes `import Glean`, unless generating
- for a Glean-internal build.
-
-## 1.17.0 (2020-02-03)
-
-- Remove default schema URL from `validate_ping`
-- Make `schema` argument required for CLI
-- BUGFIX: Avoid default import in Swift code for Glean itself
-- BUGFIX: Restore order of fields in generated Swift code
-
-## 1.16.0 (2020-01-15)
-
-- Support for `reason` codes on pings was added.
-
-## 1.15.6 (2020-02-06)
-
-- BUGFIX: The version of Jinja2 now specifies < 3.0, since that version no
- longer supports Python 3.5 (backported from 1.17.3).
-
-## 1.15.5 (2019-12-19)
-
-- BUGFIX: Also allow the legacy name `all_pings` for `send_in_pings` parameter
- on metrics
-
-## 1.15.4 (2019-12-19)
-
-- BUGFIX: Also allow the legacy name `all_pings`
-
-## 1.15.3 (2019-12-13)
-
-- Add project title to markdown template.
-- Remove "Sorry about that" from markdown template.
-- BUGFIX: Replace dashes in variable names to force proper naming
-
-## 1.15.2 (2019-12-12)
-
-- BUGFIX: Use a pure Python library for iso8601 so there is no compilation
- required.
-
-## 1.15.1 (2019-12-12)
-
-- BUGFIX: Add some additional ping names to the non-kebab-case allow list.
-
-## 1.15.0 (2019-12-12)
-
-- Restrict new pings names to be kebab-case and change `all_pings` to
- `all-pings`
-
-## 1.14.0 (2019-12-06)
-
-- `glean_parser` now supports Python versions 3.5, 3.6, 3.7 and 3.8.
-
-## 1.13.0 (2019-12-04)
-
-- The `translate` command will no longer clear extra files in the output
- directory.
-- BUGFIX: Ensure all newlines in comments are prefixed with comment markers
-- BUGFIX: Escape Swift keywords in variable names in generated code
-- Generate documentation for pings that are sent if empty
-
-## 1.12.0 (2019-11-27)
-
-- Reserve the `deletion_request` ping name
-- Added a new flag `send_if_empty` for pings
-
-## 1.11.0 (2019-11-13)
-
-- The `glinter` command now performs `yamllint` validation on registry files.
-
-## 1.10.0 (2019-11-11)
-
-- The Kotlin linter `detekt` is now run during CI, and for local
- testing if installed.
-- Python 3.8 is now tested in CI (in addition to Python 3.7). Using
- `tox` for this doesn't work in modern versions of CircleCI, so the
- `tox` configuration has been removed.
-- `yamllint` has been added to test the YAML files on CI.
-- ⚠ Metric types that don't yet have implementations in glean-core
- have been removed. This includes `enumeration`, `rate`, `usage`, and
- `use_counter`, as well as many labeled metrics that don't exist.
-
-## 1.9.5 (2019-10-22)
-
-- Allow a Swift lint for generated code
-- New lint: Restrict what metric can go into the `baseline` ping
-- New lint: Warn for slight misspellings in ping names
-- BUGFIX: change Labeled types labels from lists to sets.
-
-## 1.9.4 (2019-10-16)
-
-- Use lists instead of sets in Labeled types labels to ensure that the order of
- the labels passed to the `metrics.yaml` is kept.
-- `glinter` will now check for duplicate labels and error if there are any.
-
-## 1.9.3 (2019-10-09)
-
-- Add labels from Labeled types to the Extra column in the Markdown template.
-
-## 1.9.2 (2019-10-08)
-
-- BUGFIX: Don't call `is_internal_metric` on `Ping` objects.
-
-## 1.9.1 (2019-10-07)
-
-- Don't include Glean internal metrics in the generated markdown.
-
-## 1.9.0 (2019-10-04)
-
-- Glinter now warns when bug numbers (rather than URLs) are used.
-- BUGFIX: add `HistogramType` and `MemoryUnit` imports in Kotlin generated code.
-
-## 1.8.4 (2019-10-02)
-
-- Removed unsupported labeled metric types.
-
-## 1.8.3 (2019-10-02)
-
-- Fix indentation for generated Swift code
-
-## 1.8.2 (2019-10-01)
-
-- Created labeled metrics and events in Swift code and wrap it in a
- configured namespace
-
-## 1.8.1 (2019-09-27)
-
-- BUGFIX: `memory_unit` is now passed to the Kotlin generator.
-
-## 1.8.0 (2019-09-26)
-
-- A new parser config, `do_not_disable_expired`, was added to turn off the
- feature that expired metrics are automatically disabled. This is useful if you
- want to retain the disabled value that is explicitly in the `metrics.yaml`
- file.
-- `glinter` will now report about superfluous `no_lint` entries.
-
-## 1.7.0 (2019-09-24)
-
-- A `glinter` tool is now included to find common mistakes in metric naming
- and setup. This check is run during `translate` and warnings will be
- displayed. ⚠ These warnings will be treated as errors in a future revision.
-
-## 1.6.1 (2019-09-17)
-
-- BUGFIX: `GleanGeckoMetricsMapping` must include `LabeledMetricType`
- and `CounterMetricType`.
-
-## 1.6.0 (2019-09-17)
-
-- NEW: Support for outputting metrics in Swift.
-- BUGFIX: Provides a helpful error message when `geckoview_datapoint` is used on
- an metric type that doesn't support GeckoView exfiltration.
-- Generate a lookup table for Gecko categorical histograms in
- `GleanGeckoMetricsMapping`.
-- Introduce a 'Swift' output generator.
-
-## 1.4.1 (2019-08-28)
-
-- Documentation only.
-
-## 1.4.0 (2019-08-27)
-
-- Added support for generating markdown documentation from `metrics.yaml` files.
-
-## 1.3.0 (2019-08-22)
-
-- `quantity` metric type has been added.
-
-## 1.2.1 (2019-08-13)
-
-- BUGFIX: `includeClientId` was not being output for PingType.
-
-## 1.2.0 (2019-08-13)
-
-- `memory_distribution` metric type has been added.
-- `custom_distribution` metric type has been added.
-- `labeled_timespan` is no longer an allowed metric type.
-
-## 1.1.0 (2019-08-05)
-
-- Add a special `all_pings` value to `send_in_pings`.
-
-## 1.0.0 (2019-07-29)
-
-- First release to start following strict semver.
-
-## 0.1.0 (2018-10-15)
-
-- First release on PyPI.
diff --git a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/RECORD b/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/RECORD
deleted file mode 100644
index 8ebf523fd7..0000000000
--- a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/RECORD
+++ /dev/null
@@ -1,48 +0,0 @@
-glean_parser/__init__.py,sha256=bJljD052_0y-efcBhYpllICVCXOMHLcXRLNyrvfgt5A,533
-glean_parser/__main__.py,sha256=Rw0PpuQtAvdHJMK1YLozeZkc6x1yjeNZwidu4faovdk,8633
-glean_parser/coverage.py,sha256=2IwC4XMDtDamMkBFoYilmqJzW4gyypq65YVCur8SNas,4405
-glean_parser/data_review.py,sha256=BweeeTkNNS6HrIDkztawhbDByrk_-Avxpg7YeST3VAs,2152
-glean_parser/go_server.py,sha256=s6lxK9IAFY55pNl3Rv4MHlV-nQwSoyhO9ppTQE9VCik,5346
-glean_parser/javascript.py,sha256=w4ZhNBHBKWYk0h3t7G0Ud2tR__hRqzn9dlEXNKLdQrA,11230
-glean_parser/javascript_server.py,sha256=x75JfOaveEkPQe3ozYXdtDb1Zks-PxzncDOizsJbYos,7972
-glean_parser/kotlin.py,sha256=5z8_74xlqvHDsedwZhGf1_qb7swPEgIZumkJIuj3ef8,12598
-glean_parser/lint.py,sha256=STqdgyOhR4Q3fHivSizgn9bOOyqrNHhzjaqyJxz6qzI,19948
-glean_parser/markdown.py,sha256=GkCr1CrV6mnRQseT6FO1-JJ7Eup8X3lxUfRMBTxXpe4,9066
-glean_parser/metrics.py,sha256=YAO8wPuRHTLkdT9M4zh9ZwoFI1_VS8O9oQqwZNYyDp0,14612
-glean_parser/parser.py,sha256=cUOnvSXKfEBg8YTpRcWiPcMwpFpK1TTqsVO_zjUtpR4,15309
-glean_parser/pings.py,sha256=AQ-fBmIx2GKQv6J2NyTFfHHZzSnApZZoC770LlstkoI,3180
-glean_parser/python_server.py,sha256=ERpYcbSwF19xKFagxX0mZAvlR1y6D7Ah5DSvW8LipCY,4791
-glean_parser/ruby_server.py,sha256=e5lkfcLQAUMUBQDCjqNU82LkdUzT5x-G6HOnsUInbsU,5190
-glean_parser/rust.py,sha256=UEHeIZlToxCBelfec5sl_l_uLZfk8f_OUXqa_ZoEvnk,7330
-glean_parser/swift.py,sha256=T1BSGahd9wUd6VDeNC89SdN6M34jKXDlydMpSI0QLOs,8379
-glean_parser/tags.py,sha256=bemKYvcbMO4JrghiNSe-A4BNNDtx_FlUPkgrPPJy84Y,1391
-glean_parser/translate.py,sha256=luKQoraARZ2tjenHs0SVtCxflnYaMkzPYFfKEdKdSqQ,8403
-glean_parser/translation_options.py,sha256=Lxzr6G7MP0tC_ZYlZXftS4j0SLiqO-5mGVTEc7ggXis,2037
-glean_parser/util.py,sha256=v81watw5nSPGRlFNNpTb7iUv9NZObiFIbyyg2oZ6EnY,16149
-glean_parser/validate_ping.py,sha256=0TNvILH6dtzJDys3W8Kqorw6kk03me73OCUDtpoHcXU,2118
-glean_parser/schemas/metrics.1-0-0.schema.yaml,sha256=cND3cvi6iBfPUVmtfIBQfGJV9AALpbvN7nu8E33_J-o,19566
-glean_parser/schemas/metrics.2-0-0.schema.yaml,sha256=wx1q0L4C0-Vcwk1SPU6t8OfjDEQvgrwwEG6xfSHO1MI,26365
-glean_parser/schemas/pings.1-0-0.schema.yaml,sha256=hwCnsKpEysmrmVp-QHGBArEkVY3vaU1rVsxlTwhAzws,4315
-glean_parser/schemas/pings.2-0-0.schema.yaml,sha256=vDyvFT8KwAwaqyWHG4y6pFNrsc3NO7OyDDagA2eTeqM,5415
-glean_parser/schemas/tags.1-0-0.schema.yaml,sha256=OGXIJlvvVW1vaqB_NVZnwKeZ-sLlfH57vjBSHbj6DNI,1231
-glean_parser/templates/data_review.jinja2,sha256=jeYU29T1zLSyu9fKBBFu5BFPfIw8_hmOUXw8RXhRXK8,3287
-glean_parser/templates/go_server.jinja2,sha256=Jy1e0uQqr_WZNoj-AWnygRmygX2jyj_GQMMV8mSah2k,6825
-glean_parser/templates/javascript.buildinfo.jinja2,sha256=4mXiZCQIk9if4lxlA05kpSIL4a95IdwGwqle2OqqNAs,474
-glean_parser/templates/javascript.jinja2,sha256=cT_bG-jC6m4afECXmcsqHwiiHjRuVtJnfv90OD2Mwxw,2669
-glean_parser/templates/javascript_server.jinja2,sha256=H991yQOKJMwSgM0bLEA-Q5Z15LWsfEPh6bTYz_owSCU,9423
-glean_parser/templates/kotlin.buildinfo.jinja2,sha256=X0lk2SNu5OIIj2i6mUyF9CWFQIonLgfqkgT5fA-5G6c,920
-glean_parser/templates/kotlin.geckoview.jinja2,sha256=MJOgtoDXmBjE9pwk-G6T89y36RZuMbDWM_-DBN_gFJo,5099
-glean_parser/templates/kotlin.jinja2,sha256=3DqUMXJRkmTvSp_5IRyvGmw5iXYWdox7coMFe3YDxcc,5247
-glean_parser/templates/markdown.jinja2,sha256=vAHHGGm28HRDPd3zO_wQMAUZIuxE9uQ7hl3NpXxcKV4,3425
-glean_parser/templates/python_server.jinja2,sha256=gu2C1rkn760IqBCG2SWaK7o32T1ify94wDEsudLPUg8,7260
-glean_parser/templates/qmldir.jinja2,sha256=m6IGsp-tgTiOfQ7VN8XW6GqX0gJqJkt3B6Pkaul6FVo,156
-glean_parser/templates/ruby_server.jinja2,sha256=vm4BEenOqzomQNTLFfMOzlWHARnsWUjTBbnR-v2cadI,6247
-glean_parser/templates/rust.jinja2,sha256=wlV0OZvV3Mk2ulrqFkN1vGjdsahsupEy2TQvWxQKzww,5439
-glean_parser/templates/swift.jinja2,sha256=xkvVsTpfK0QK3tI32wGqzxm2hqFNaBQ6Y71rKIsCmAI,4944
-glean_parser-13.0.1.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455
-glean_parser-13.0.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
-glean_parser-13.0.1.dist-info/METADATA,sha256=UYz6ZRXyv3ODi3yl2vRQHZVdm0XGerFp8pIOGWGwOKw,31604
-glean_parser-13.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
-glean_parser-13.0.1.dist-info/entry_points.txt,sha256=mf9d3sv8BwSjjR58x9KDnpVkONCnv3fPQC2NjJl15Xg,68
-glean_parser-13.0.1.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13
-glean_parser-13.0.1.dist-info/RECORD,,
diff --git a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/AUTHORS.md b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/AUTHORS.md
index 525116ee7e..525116ee7e 100644
--- a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/AUTHORS.md
+++ b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/AUTHORS.md
diff --git a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/LICENSE b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/LICENSE
index a612ad9813..a612ad9813 100644
--- a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/LICENSE
+++ b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/LICENSE
diff --git a/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/METADATA b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/METADATA
new file mode 100644
index 0000000000..65030fd86b
--- /dev/null
+++ b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/METADATA
@@ -0,0 +1,799 @@
+Metadata-Version: 2.1
+Name: glean_parser
+Version: 14.0.1
+Summary: Parser tools for Mozilla's Glean telemetry
+Home-page: https://github.com/mozilla/glean_parser
+Author: The Glean Team
+Author-email: glean-team@mozilla.com
+Keywords: glean_parser
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Natural Language :: English
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Description-Content-Type: text/markdown
+License-File: LICENSE
+License-File: AUTHORS.md
+Requires-Dist: appdirs >=1.4
+Requires-Dist: Click >=7
+Requires-Dist: diskcache >=4
+Requires-Dist: Jinja2 >=2.10.1
+Requires-Dist: jsonschema >=3.0.2
+Requires-Dist: PyYAML >=5.3.1
+
+# Glean Parser
+
+Parser tools for Mozilla's Glean telemetry.
+
+## Features
+
+Contains various utilities for handling `metrics.yaml` and `pings.yaml` for [the
+Glean SDKs](https://mozilla.github.io/glean). This includes producing generated
+code for various integrations, linting and coverage testing.
+
+## Documentation
+
+- [How to Contribute](https://github.com/mozilla/glean_parser/blob/main/CONTRIBUTING.md). Please file bugs in [bugzilla](https://bugzilla.mozilla.org/enter_bug.cgi?assigned_to=nobody%40mozilla.org&bug_ignored=0&bug_severity=normal&bug_status=NEW&cf_fission_milestone=---&cf_fx_iteration=---&cf_fx_points=---&cf_status_firefox65=---&cf_status_firefox66=---&cf_status_firefox67=---&cf_status_firefox_esr60=---&cf_status_thunderbird_esr60=---&cf_tracking_firefox65=---&cf_tracking_firefox66=---&cf_tracking_firefox67=---&cf_tracking_firefox_esr60=---&cf_tracking_firefox_relnote=---&cf_tracking_thunderbird_esr60=---&product=Data%20Platform%20and%20Tools&component=Glean%3A%20SDK&contenttypemethod=list&contenttypeselection=text%2Fplain&defined_groups=1&flag_type-203=X&flag_type-37=X&flag_type-41=X&flag_type-607=X&flag_type-721=X&flag_type-737=X&flag_type-787=X&flag_type-799=X&flag_type-800=X&flag_type-803=X&flag_type-835=X&flag_type-846=X&flag_type-855=X&flag_type-864=X&flag_type-916=X&flag_type-929=X&flag_type-930=X&flag_type-935=X&flag_type-936=X&flag_type-937=X&form_name=enter_bug&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Unspecified&priority=P3&&rep_platform=Unspecified&status_whiteboard=%5Btelemetry%3Aglean-rs%3Am%3F%5D&target_milestone=---&version=unspecified).
+- [User documentation for Glean](https://mozilla.github.io/glean/).
+- [`glean_parser` developer documentation](https://mozilla.github.io/glean_parser/).
+
+## Requirements
+
+- Python 3.8 (or later)
+
+The following library requirements are installed automatically when
+`glean_parser` is installed by `pip`.
+
+- appdirs
+- Click
+- diskcache
+- Jinja2
+- jsonschema
+- PyYAML
+
+## Usage
+
+```sh
+$ glean_parser --help
+```
+
+Read in `metrics.yaml`, translate to Kotlin format, and
+output to `output_dir`:
+
+```sh
+$ glean_parser translate -o output_dir -f kotlin metrics.yaml
+```
+
+Check a Glean ping against the ping schema:
+
+```sh
+$ glean_parser check < ping.json
+```
+
+
+# Changelog
+
+## 14.0.1
+
+- BUGFIX: Fix missing `ping_arg` in util.py ([#687](https://github.com/mozilla/glean_parser/pull/687))
+
+## 14.0.0
+
+- BREAKING CHANGE: Expose the optional `enabled` property on pings, defaulting to `enabled: true` ([#681](https://github.com/mozilla/glean_parser/pull/681))
+- BREAKING CHANGE: Support metadata field `ping_schedule` for pings ([bug 1804711](https://bugzilla.mozilla.org/show_bug.cgi?id=1804711))
+- Add support for event metric type in server JavaScript outputter ([DENG-2407](https://mozilla-hub.atlassian.net/browse/DENG-2407))
+- Add Swift and Kotlin codegen support for the object metric type object ([#685](https://github.com/mozilla/glean_parser/pull/685))
+
+## 13.0.1
+
+- Use faster C yaml parser if available ([#677](https://github.com/mozilla/glean_parser/pull/677))
+
+## 13.0.0
+
+- BREAKING CHANGE: Support metadata field `include_info_sections` ([bug 1866559](https://bugzilla.mozilla.org/show_bug.cgi?id=1866559))
+
+## 12.0.1
+
+- Fix Rust codegen for object metric type ([#662](https://github.com/mozilla/glean_parser/pull/662))
+
+## 12.0.0
+
+- Add new metric type object (only Rust codegen support right now) ([#587](https://github.com/mozilla/glean_parser/pull/587))
+
+## 11.1.0
+
+- Add Go log outputter (`go_server`) ([#645](https://github.com/mozilla/glean_parser/pull/645))
+- Add Python log outputter (`python_server`) ([MPP-3642](https://mozilla-hub.atlassian.net/browse/MPP-3642))
+
+## 11.0.1
+
+- Fix javascript_server template to include non-event metric parameters in #record call for event metrics ([#643](https://github.com/mozilla/glean_parser/pull/643))
+- events: Increase extra key limit to 50 ([Bug 1869429](https://bugzilla.mozilla.org/show_bug.cgi?id=1869429))
+
+## 11.0.0
+
+- Add updated logging logic for Ruby Server ([#642](https://github.com/mozilla/glean_parser/pull/642))
+- Add support for event metric type in server-side JavaScript outputter ([DENG-1736](https://mozilla-hub.atlassian.net/browse/DENG-1736))
+- BREAKING CHANGE: Dropped support for Python 3.7 ([#638](https://github.com/mozilla/glean_parser/pull/638))
+- Add official support for Python 3.11+ ([#638](https://github.com/mozilla/glean_parser/pull/638))
+
+## 10.0.3
+
+- Warn about empty or TODO-tagged data reviews in the list ([#634](https://github.com/mozilla/glean_parser/pull/634))
+- Allow `unit` field on all metrics, but warn for all but quantity and custom distribution ([#636](https://github.com/mozilla/glean_parser/pull/636))
+
+## 10.0.2
+
+- Allow `unit` field for string again, but warn about it in the linter ([#634](https://github.com/mozilla/glean_parser/pull/634))
+
+## 10.0.1
+
+- Allow `unit` field for custom distribution again ([#633](https://github.com/mozilla/glean_parser/pull/633))
+
+## 10.0.0
+
+- Add Ruby log outputter (`ruby_server`) ([#620](https://github.com/mozilla/glean_parser/pull/620))
+- BREAKING CHANE: `ping` lifetime metrics on the events ping are now disallowed ([#625](https://github.com/mozilla/glean_parser/pull/625))
+- Disallow `unit` field for anything but quantity ([#630](https://github.com/mozilla/glean_parser/pull/630)).
+ Note that this was already considered the case, now the code enforces it.
+
+## 9.0.0
+
+- BREAKING CHANGE: Dropped support for Python 3.6 ([#615](https://github.com/mozilla/glean_parser/issues/615))
+- Allow metadata to configure precise timestamps in pings ([#592](https://github.com/mozilla/glean_parser/pull/592))
+
+## 8.1.1
+
+- Small updates to the `javascript_server` tempalte to address lint warnings ([#598](https://github.com/mozilla/glean_parser/pull/598))
+
+## 8.1.0
+
+- Increased the maximum metric name length in version 2.0.0 schema ([#596](https://github.com/mozilla/glean_parser/pull/596))
+
+## 8.0.0
+
+- BREAKING CHANGE: Remove exposed `lint_yaml_files` function ([#580](https://github.com/mozilla/glean_parser/pull/580))
+- Rust: Removed `__glean_metric_maps` from the Rust Jinja template. This functionality is better placed downstream ([Bug 1816526](https://bugzilla.mozilla.org/show_bug.cgi?id=1816526))
+- New lint: check that all referenced pings are known ([#584](https://github.com/mozilla/glean_parser/pull/584))
+- Add experimental server-side JavaScript outputter ([FXA-7922](https://mozilla-hub.atlassian.net/browse/FXA-7922))
+
+## 7.2.1
+
+- Unbreak last minor release ([#579](https://github.com/mozilla/glean_parser/pull/579))
+
+## 7.2.0
+
+- Remove yamllint integration ([#578](https://github.com/mozilla/glean_parser/pull/578))
+
+## 7.1.0
+
+- ENHANCEMENT: Labels in `labels:` fields may now contain any printable ASCII characters ([bug 1672273](https://bugzilla.mozilla.org/show_bug.cgi?id=1672273))
+- BUGFIX: Enforce ordering of generation of Pings, Metrics and Tags such that order is deterministic ([bug 1820334](https://bugzilla.mozilla.org/show_bug.cgi?id=1820334))
+
+## 7.0.0
+
+- BUGFIX: Remove internal-only fields from serialized metrics data ([#550](https://github.com/mozilla/glean_parser/pull/550))
+- FEATURE: New subcommand: `dump` to dump the metrics data as JSON ([#550](https://github.com/mozilla/glean_parser/pull/550))
+- BUGFIX: Kotlin: Generate enums with the right generic bound for ping reason codes ([#551](https://github.com/mozilla/glean_parser/pull/551)).
+- **BREAKING CHANGE:** Fully remove support for the old events API ([#549](https://github.com/mozilla/glean_parser/pull/549))
+ Adds a new lint `OLD_EVENT_API` to warn about missing `type` attributes on event extra keys.
+ Note that the Glean SDK already dropped support for the old events API.
+
+## 6.4.0
+
+- BUGFIX: Correct code generation for labeled metrics in Rust ([#533](https://github.com/mozilla/glean_parser/pull/533))
+- BUGFIX: Correctly serialize `Rates` for Rust code ([#530](https://github.com/mozilla/glean_parser/pull/530))
+- Feature: Wrap labeled metric's static labels list as CoW strings (requires updated Glean support) ([#534](https://github.com/mozilla/glean_parser/pull/534))
+
+## 6.3.0
+
+- events: Increase extras limit to 15 ([bug 1798713](https://bugzilla.mozilla.org/show_bug.cgi?id=1798713))
+
+## 6.2.1
+
+- Add support for Rate, Denominator and Numerator metrics for JavaScript. ([bug 1793777](https://bugzilla.mozilla.org/show_bug.cgi?id=1793777))
+
+## 6.2.0
+
+- [data-review] Use a template to generate the Data Review Request template ([bug 1772605](https://bugzilla.mozilla.org/show_bug.cgi?id=1772605))
+- Make tag and no\_lint order deterministic ([#518](https://github.com/mozilla/glean_parser/pull/518))
+
+## 6.1.2
+
+- Swift: Add a conditional `import Foundation` to support generating metrics when Glean is delivered via the AppServices iOS megazord
+
+## 6.1.1
+
+- Rust: Use correct name for a ping in generated code.
+
+## 6.1.0
+
+- [data-review] Include extra keys' names and descriptions in data review template ([bug 1767027](https://bugzilla.mozilla.org/show_bug.cgi?id=1767027))
+- Raise limit on number of statically-defined labels to 4096. ([bug 1772163](https://bugzilla.mozilla.org/show_bug.cgi?id=1772163))
+- Fix Rust code generation for new UniFFI interface ([#491](https://github.com/mozilla/glean_parser/pull/491), [#494](https://github.com/mozilla/glean_parser/pull/494), [#495](https://github.com/mozilla/glean_parser/pull/495))
+
+## 6.0.1
+
+- Relax version requirement for MarkupSafe.
+ Now works with MarkupSafe v1.1.1 to v2.0.1 inclusive again.
+
+## 6.0.0
+
+- BUGFIX: Add missing `extra_args` to Rust constructor generation ([bug 1765855](https://bugzilla.mozilla.org/show_bug.cgi?id=1765855))
+- **Breaking change:** `glean_parser` now generates metrics compatible with the UniFFI-powered Glean SDK.
+ This is not backwards-compatible with previous versions.
+- Generate Rate, Denominator and Numerator metrics for Kotlin and Swift
+- Explicitly skip Rate, Denominator and Numerator metrics for JavaScript.
+ These will cause a build failure by default, but can be turned into warnings on request.
+ Use `-s fail_rates=false` to enable warning-only mode.
+
+## 5.1.2
+
+- BUGFIX: Revert changes made on v5.1.1.
+ - The issues addressed by those changes, were non-issues and result of misuse of the APIs.
+
+## 5.1.1
+
+- BUGFIX: Fix issues with Swift templates ([bug 1749494](https://bugzilla.mozilla.org/show_bug.cgi?id=1749494))
+ - Make metrics and pings all `public`
+ - Make pings `static`
+
+## 5.1.0
+
+- Add support for build info generation for JavaScript and Typescript targets ([bug 1749494](https://bugzilla.mozilla.org/show_bug.cgi?id=1749494))
+
+## 5.0.1
+
+- Fix the logic for the metric expiration by version ([bug 1753194](https://bugzilla.mozilla.org/show_bug.cgi?id=1753194))
+
+## 5.0.0
+
+- Remove C# support ([#436](https://github.com/mozilla/glean_parser/pull/436)).
+- Add support for Rust code generation ([bug 1677434](https://bugzilla.mozilla.org/show_bug.cgi?id=1677434))
+- Report an error if no files are passed ([bug 1751730](https://bugzilla.mozilla.org/show_bug.cgi?id=1751730))
+- [data-review] Report an error if no metrics match provided bug number ([bug 1752576](https://bugzilla.mozilla.org/show_bug.cgi?id=1752576))
+- [data-review] Include notification_emails in list of those responsible ([bug 1752576](https://bugzilla.mozilla.org/show_bug.cgi?id=1752576))
+- Add support for expiring metrics by the provided major version ([bug 1753194](https://bugzilla.mozilla.org/show_bug.cgi?id=1753194))
+
+## 4.4.0
+
+- Support global file-level tags in metrics.yaml ([bug 1745283](https://bugzilla.mozilla.org/show_bug.cgi?id=1745283))
+- Glinter: Reject metric files if they use `unit` by mistake. It should be `time_unit` ([#432](https://github.com/mozilla/glean_parser/pull/432)).
+- Automatically generate a build date when generating build info ([#431](https://github.com/mozilla/glean_parser/pull/431)).
+ Enabled for Kotlin and Swift.
+ This can be changed with the `build_date` command line option.
+ `build_date=0` will use a static unix epoch time.
+ `build_date=2022-01-03T17:30:00` will parse the ISO8601 string to use (as a UTC timestamp).
+ Other values will throw an error.
+
+ Example:
+
+ glean_parser translate --format kotlin --option build_date=2021-11-01T01:00:00 path/to/metrics.yaml
+
+## 4.3.1
+
+- BUGFIX: Skip tags for code generation ([#409](https://github.com/mozilla/glean_parser/pull/409))
+
+## 4.3.0
+
+- Support tags in glean parser ([bug 1734011](https://bugzilla.mozilla.org/show_bug.cgi?id=1734011))
+
+## 4.2.0
+
+- Improve the schema validation error messages. They will no longer include `OrderedDict(...)` on Python 3.7 and later ([bug 1733395](https://bugzilla.mozilla.org/show_bug.cgi?id=1733395))
+- Officially support Python 3.10
+
+## 4.1.1 (2021-09-28)
+
+- Update private import paths on Javascript / Typescript templates. ([bug 1702468](https://bugzilla.mozilla.org/show_bug.cgi?id=1702468))
+
+## 4.1.0 (2021-09-16)
+
+- Add support for Node.js platform on Javascript / Typescript templates. ([bug 1728982](https://bugzilla.mozilla.org/show_bug.cgi?id=1728982))
+
+## 4.0.0 (2021-08-20)
+
+- Add support for Text metric type ([#374](https://github.com/mozilla/glean_parser/pull/374))
+- Reserve the `default` ping name. It can't be used as a ping name, but it can be used in `send_in_pings` ([#376](https://github.com/mozilla/glean_parser/pull/376))
+
+## 3.8.0 (2021-08-18)
+
+- Expose ping reasons enum on JavaScript / TypeScript templates. ([bug 1719136](https://bugzilla.mozilla.org/show_bug.cgi?id=1719136))
+- Define an interface with the allowed extras for each event on the TypeScript template. ([bug 1693487](https://bugzilla.mozilla.org/show_bug.cgi?id=1693487))
+
+## 3.7.0 (2021-07-13)
+
+- New lint: Check for redundant words in ping names ([#355](https://github.com/mozilla/glean_parser/pull/355))
+- Add support for URL metric type ([#361](https://github.com/mozilla/glean_parser/pull/361))
+
+## 3.6.0 (2021-06-11)
+
+- Add a command `data-review` to generate a skeleton Data Review Request for all metrics matching a supplied bug number. ([bug 1704541](https://bugzilla.mozilla.org/show_bug.cgi?id=1704541))
+- Enable custom distribution outside of GeckoView (`gecko_datapoint` becomes optional)
+
+## 3.5.0 (2021-06-03)
+
+- Transform generated folder into QML Module when building Javascript templates for the Qt platform. ([bug 1707896](https://bugzilla.mozilla.org/show_bug.cgi?id=1707896)
+ - Import the Glean QML module from inside each generated file, removing the requirement to import Glean before importing any of the generated files;
+ - Prodive a `qmldir` file exposing all generated files;
+ - Drop the `namespace` option for Javascript templates;
+ - Add a new `version` option for Javascript templates, required when building for Qt, which expected the Glean QML module version.
+
+## 3.4.0 (2021-05-28)
+
+- Add missing import for Kotlin code ([#339](https://github.com/mozilla/glean_parser/pull/339))
+- Use a plain Kotlin type in the generated interface implementation ([#339](https://github.com/mozilla/glean_parser/pull/339))
+- Generate additional generics for event metrics ([#339](https://github.com/mozilla/glean_parser/pull/339))
+- For Kotlin skip generating `GleanBuildInfo.kt` when requested (with `with_buildinfo=false`) ([#341](https://github.com/mozilla/glean_parser/pull/341))
+
+## 3.3.2 (2021-05-18)
+
+- Fix another bug in the Swift code generation when generating extra keys ([#334](https://github.com/mozilla/glean_parser/pull/334))
+
+## 3.3.1 (2021-05-18)
+
+- Fix Swift code generation bug for pings ([#333](https://github.com/mozilla/glean_parser/pull/333))
+
+## 3.3.0 (2021-05-18)
+
+- Generate new event API construct ([#321](https://github.com/mozilla/glean_parser/pull/321))
+
+## 3.2.0 (2021-04-28)
+
+- Add option to add extra introductory text to generated markdown ([#298](https://github.com/mozilla/glean_parser/pull/298))
+- Add support for Qt in Javascript templates ([bug 1706252](https://bugzilla.mozilla.org/show_bug.cgi?id=1706252))
+ - Javascript templates will now accept the `platform` option. If this option is set to `qt`
+ the generated templates will be Qt compatible. Default value is `webext`.
+
+## 3.1.2 (2021-04-21)
+
+- BUGFIX: Remove the "DO NOT COMMIT" notice from the documentation.
+
+## 3.1.1 (2021-04-19)
+
+- Recommend to not commit as well as to not edit the generated files. ([bug 1706042](https://bugzilla.mozilla.org/show_bug.cgi?id=1706042))
+- BUGFIX: Include import statement for labeled metric subtypes in Javascript and Typescript templates.
+
+## 3.1.0 (2021-04-16)
+
+- Add support for labeled metric types in Javascript and Typescript templates.
+
+## 3.0.0 (2021-04-13)
+
+- Raise limit on number of statically-defined lables to 100. ([bug 1702263](https://bugzilla.mozilla.org/show_bug.cgi?id=1702263))
+- BUGFIX: Version 2.0.0 of the schema now allows the "special" `glean_.*` ping names for Glean-internal use again.
+- Remove support for JWE metric types.
+
+## 2.5.0 (2021-02-23)
+
+- Add parser and object model support for `rate` metric type. ([bug 1645166](https://bugzilla.mozilla.org/show_bug.cgi?id=1645166))
+- Add parser and object model support for telemetry_mirror property. ([bug 1685406](https://bugzilla.mozilla.org/show_bug.cgi?id=1685406))
+- Update the Javascript template to match Glean.js expectations. ([bug 1693516](https://bugzilla.mozilla.org/show_bug.cgi?id=1693516))
+ - Glean.js has updated it's export strategy. It will now export each metric type as an independent module;
+ - Glean.js has dropped support for non ES6 modules.
+- Add support for generating Typescript code. ([bug 1692157](https://bugzilla.mozilla.org/show_bug.cgi?id=1692157))
+ - The templates added generate metrics and pings code for Glean.js.
+
+## 2.4.0 (2021-02-18)
+
+- **Experimental:** `glean_parser` has a new subcommand `coverage` to convert raw coverage reports
+ into something consumable by coverage tools, such as codecov.io
+- The path to the file that each metric is defined in is now stored on the
+ `Metric` object in `defined_in["filepath"]`.
+
+## 2.3.0 (2021-02-17)
+
+- Leverage the `glean_namespace` to provide correct import when building for Javascript.
+
+## 2.2.0 (2021-02-11)
+
+- The Kotlin generator now generates static build information that can be passed
+ into `Glean.initialize` to avoid calling the package manager at runtime.
+
+## 2.1.0 (2021-02-10)
+
+- Add support for generating Javascript code.
+ - The templates added generate metrics and pings code for Glean.js.
+
+## 2.0.0 (2021-02-05)
+
+- New versions 2.0.0 of the `metrics.yaml` and `pings.yaml` schemas now ship
+ with `glean_parser`. These schemas are different from version 1.0.0 in the
+ following ways:
+
+ - Bugs must be specified as URLs. Bug numbers are disallowed.
+ - The legacy ping names containing underscores are no longer allowed. These
+ included `deletion_request`, `bookmarks_sync`, `history_sync`,
+ `session_end`, `all_pings`, `glean_*`). In these cases, the `_` should be
+ replaced with `-`.
+
+ To upgrade your app or library to use the new schema, replace the version in
+ the `$schema` value with `2-0-0`.
+
+- **Breaking change:** It is now an error to use bug numbers (rather than URLs)
+ in ping definitions.
+
+- Add the line number that metrics and pings were originally defined in the yaml
+ files.
+
+## 1.29.1 (2020-12-17)
+
+- BUGFIX: Linter output can now be redirected correctly (1675771).
+
+## 1.29.0 (2020-10-07)
+
+- **Breaking change:** `glean_parser` will now return an error code when any of
+ the input files do not exist (unless the `--allow-missing-files` flag is
+ passed).
+- Generated code now includes a comment next to each metric containing the name
+ of the metric in its original `snake_case` form.
+- When metrics don't provide a `unit` parameter, it is not included in the
+ output (as provided by probe-scraper).
+
+## 1.28.6 (2020-09-24)
+
+- BUGFIX: Ensure Kotlin arguments are deterministically ordered
+
+## 1.28.5 (2020-09-14)
+
+- Fix deploy step to update pip before deploying to pypi.
+
+## 1.28.4 (2020-09-14)
+
+- The `SUPERFLUOUS_NO_LINT` warning has been removed from the glinter.
+ It likely did more harm than good, and makes it hard to make
+ `metrics.yaml` files that pass across different versions of
+ `glean_parser`.
+- Expired metrics will now produce a linter warning, `EXPIRED_METRIC`.
+- Expiry dates that are more than 730 days (\~2 years) in the future
+ will produce a linter warning, `EXPIRATION_DATE_TOO_FAR`.
+- Allow using the Quantity metric type outside of Gecko.
+- New parser configs `custom_is_expired` and `custom_validate_expires`
+ added. These are both functions that take the `expires` value of the
+ metric and return a bool. (See `Metric.is_expired` and
+ `Metric.validate_expires`). These will allow FOG to provide custom
+ validation for its version-based `expires` values.
+
+## 1.28.3 (2020-07-28)
+
+- BUGFIX: Support HashSet and Dictionary in the C\## generated code.
+
+## 1.28.2 (2020-07-28)
+
+- BUGFIX: Generate valid C\## code when using Labeled metric types.
+
+## 1.28.1 (2020-07-24)
+
+- BUGFIX: Add missing column to correctly render markdown tables in generated
+ documentation.
+
+## 1.28.0 (2020-07-23)
+
+- **Breaking change:** The internal ping `deletion-request` was misnamed in
+ pings.py causing the linter to not allow use of the correctly named ping for
+ adding legacy ids to. Consuming apps will need to update their metrics.yaml if
+ they are using `deletion_request` in any `send_in_pings` to `deletion-request`
+ after updating.
+
+## 1.27.0 (2020-07-21)
+
+- Rename the `data_category` field to `data_sensitivity` to be clearer.
+
+## 1.26.0 (2020-07-21)
+
+- Add support for JWE metric types.
+- Add a `data_sensitivity` field to all metrics for specifying the type of data
+ collected in the field.
+
+## 1.25.0 (2020-07-17)
+
+- Add support for generating C\## code.
+- BUGFIX: The memory unit is now correctly passed to the MemoryDistribution
+ metric type in Swift.
+
+## 1.24.0 (2020-06-30)
+
+- BUGFIX: look for metrics in send\_if\_empty pings. Metrics for these kinds of
+ pings were being ignored.
+
+## 1.23.0 (2020-06-27)
+
+- Support for Python 3.5 has been dropped.
+- BUGFIX: The ordering of event extra keys will now match with their enum,
+ fixing a serious bug where keys of extras may not match the correct values in
+ the data payload. See <https://bugzilla.mozilla.org/show_bug.cgi?id=1648768>.
+
+## 1.22.0 (2020-05-28)
+
+- **Breaking change:** (Swift only) Combine all metrics and pings into a single
+ generated file `Metrics.swift`.
+
+## 1.21.0 (2020-05-25)
+
+- `glinter` messages have been improved with more details and to be more
+ actionable.
+- A maximum of 10 `extra_keys` is now enforced for `event` metric types.
+- BUGFIX: the `Lifetime` enum values now match the values of the implementation
+ in mozilla/glean.
+
+## 1.20.4 (2020-05-07)
+
+- BUGFIX: yamllint errors are now reported using the correct file name.
+
+## 1.20.3 (2020-05-06)
+
+- Support for using `timing_distribution`'s `time_unit` parameter to control
+ the range of acceptable values is documented. The default unit for this use
+ case is `nanosecond` to avoid creating a breaking change. See [bug
+ 1630997](https://bugzilla.mozilla.org/show_bug.cgi?id=1630997) for more
+ information.
+
+## 1.20.2 (2020-04-24)
+
+- Dependencies that depend on the version of Python being used are now specified
+ using the [Declaring platform specific dependencies syntax in
+ setuptools](https://setuptools.readthedocs.io/en/latest/setuptools.html##declaring-platform-specific-dependencies).
+ This means that more recent versions of dependencies are likely to be
+ installed on Python 3.6 and later, and unnecessary backport libraries won't
+ be installed on more recent Python versions.
+
+## 1.20.1 (2020-04-21)
+
+- The minimum version of the runtime dependencies has been lowered to increase
+ compatibility with other tools. These minimum versions are now tested in CI,
+ in addition to testing the latest versions of the dependencies that was
+ already happening in CI.
+
+## 1.20.0 (2020-04-15)
+
+- **Breaking change:** glinter errors found during the `translate` command will
+ now return an error code. glinter warnings will be displayed, but not return
+ an error code.
+- `glean_parser` now produces a linter warning when `user` lifetime metrics are
+ set to expire. See [bug
+ 1604854](https://bugzilla.mozilla.org/show_bug.cgi?id=1604854) for additional
+ context.
+
+## 1.19.0 (2020-03-18)
+
+- **Breaking change:** The regular expression used to validate labels is
+ stricter and more correct.
+- Add more information about pings to markdown documentation:
+ - State whether the ping includes client id;
+ - Add list of data review links;
+ - Add list of related bugs links.
+- `glean_parser` now makes it easier to write external translation
+ functions for different language targets.
+- BUGFIX: `glean_parser` now works on 32-bit Windows.
+
+## 1.18.3 (2020-02-24)
+
+- Dropped the `inflection` dependency.
+- Constrained the `zipp` and `MarkupSafe` transitive dependencies to versions
+ that support Python 3.5.
+
+## 1.18.2 (2020-02-14)
+
+- BUGFIX: Fix rendering of first element of reason list.
+
+## 1.18.1 (2020-02-14)
+
+- BUGFIX: Reason codes are displayed in markdown output for built-in
+ pings as well.
+- BUGFIX: Reason descriptions are indented correctly in markdown
+ output.
+- BUGFIX: To avoid a compiler error, the `@JvmName` annotation isn't
+ added to private members.
+
+## 1.18.0 (2020-02-13)
+
+- **Breaking Change (Java API)** Have the metrics names in Java match the names
+ in Kotlin. See [Bug
+ 1588060](https://bugzilla.mozilla.org/show_bug.cgi?id=1588060).
+- The reasons a ping are sent are now included in the generated markdown
+ documentation.
+
+## 1.17.3 (2020-02-05)
+
+- BUGFIX: The version of Jinja2 now specifies < 3.0, since that version no
+ longer supports Python 3.5.
+
+## 1.17.2 (2020-02-05)
+
+- BUGFIX: Fixes an import error in generated Kotlin code.
+
+## 1.17.1 (2020-02-05)
+
+- BUGFIX: Generated Swift code now includes `import Glean`, unless generating
+ for a Glean-internal build.
+
+## 1.17.0 (2020-02-03)
+
+- Remove default schema URL from `validate_ping`
+- Make `schema` argument required for CLI
+- BUGFIX: Avoid default import in Swift code for Glean itself
+- BUGFIX: Restore order of fields in generated Swift code
+
+## 1.16.0 (2020-01-15)
+
+- Support for `reason` codes on pings was added.
+
+## 1.15.6 (2020-02-06)
+
+- BUGFIX: The version of Jinja2 now specifies < 3.0, since that version no
+ longer supports Python 3.5 (backported from 1.17.3).
+
+## 1.15.5 (2019-12-19)
+
+- BUGFIX: Also allow the legacy name `all_pings` for `send_in_pings` parameter
+ on metrics
+
+## 1.15.4 (2019-12-19)
+
+- BUGFIX: Also allow the legacy name `all_pings`
+
+## 1.15.3 (2019-12-13)
+
+- Add project title to markdown template.
+- Remove "Sorry about that" from markdown template.
+- BUGFIX: Replace dashes in variable names to force proper naming
+
+## 1.15.2 (2019-12-12)
+
+- BUGFIX: Use a pure Python library for iso8601 so there is no compilation
+ required.
+
+## 1.15.1 (2019-12-12)
+
+- BUGFIX: Add some additional ping names to the non-kebab-case allow list.
+
+## 1.15.0 (2019-12-12)
+
+- Restrict new pings names to be kebab-case and change `all_pings` to
+ `all-pings`
+
+## 1.14.0 (2019-12-06)
+
+- `glean_parser` now supports Python versions 3.5, 3.6, 3.7 and 3.8.
+
+## 1.13.0 (2019-12-04)
+
+- The `translate` command will no longer clear extra files in the output
+ directory.
+- BUGFIX: Ensure all newlines in comments are prefixed with comment markers
+- BUGFIX: Escape Swift keywords in variable names in generated code
+- Generate documentation for pings that are sent if empty
+
+## 1.12.0 (2019-11-27)
+
+- Reserve the `deletion_request` ping name
+- Added a new flag `send_if_empty` for pings
+
+## 1.11.0 (2019-11-13)
+
+- The `glinter` command now performs `yamllint` validation on registry files.
+
+## 1.10.0 (2019-11-11)
+
+- The Kotlin linter `detekt` is now run during CI, and for local
+ testing if installed.
+- Python 3.8 is now tested in CI (in addition to Python 3.7). Using
+ `tox` for this doesn't work in modern versions of CircleCI, so the
+ `tox` configuration has been removed.
+- `yamllint` has been added to test the YAML files on CI.
+- ⚠ Metric types that don't yet have implementations in glean-core
+ have been removed. This includes `enumeration`, `rate`, `usage`, and
+ `use_counter`, as well as many labeled metrics that don't exist.
+
+## 1.9.5 (2019-10-22)
+
+- Allow a Swift lint for generated code
+- New lint: Restrict what metric can go into the `baseline` ping
+- New lint: Warn for slight misspellings in ping names
+- BUGFIX: change Labeled types labels from lists to sets.
+
+## 1.9.4 (2019-10-16)
+
+- Use lists instead of sets in Labeled types labels to ensure that the order of
+ the labels passed to the `metrics.yaml` is kept.
+- `glinter` will now check for duplicate labels and error if there are any.
+
+## 1.9.3 (2019-10-09)
+
+- Add labels from Labeled types to the Extra column in the Markdown template.
+
+## 1.9.2 (2019-10-08)
+
+- BUGFIX: Don't call `is_internal_metric` on `Ping` objects.
+
+## 1.9.1 (2019-10-07)
+
+- Don't include Glean internal metrics in the generated markdown.
+
+## 1.9.0 (2019-10-04)
+
+- Glinter now warns when bug numbers (rather than URLs) are used.
+- BUGFIX: add `HistogramType` and `MemoryUnit` imports in Kotlin generated code.
+
+## 1.8.4 (2019-10-02)
+
+- Removed unsupported labeled metric types.
+
+## 1.8.3 (2019-10-02)
+
+- Fix indentation for generated Swift code
+
+## 1.8.2 (2019-10-01)
+
+- Created labeled metrics and events in Swift code and wrap it in a
+ configured namespace
+
+## 1.8.1 (2019-09-27)
+
+- BUGFIX: `memory_unit` is now passed to the Kotlin generator.
+
+## 1.8.0 (2019-09-26)
+
+- A new parser config, `do_not_disable_expired`, was added to turn off the
+ feature that expired metrics are automatically disabled. This is useful if you
+ want to retain the disabled value that is explicitly in the `metrics.yaml`
+ file.
+- `glinter` will now report about superfluous `no_lint` entries.
+
+## 1.7.0 (2019-09-24)
+
+- A `glinter` tool is now included to find common mistakes in metric naming
+ and setup. This check is run during `translate` and warnings will be
+ displayed. ⚠ These warnings will be treated as errors in a future revision.
+
+## 1.6.1 (2019-09-17)
+
+- BUGFIX: `GleanGeckoMetricsMapping` must include `LabeledMetricType`
+ and `CounterMetricType`.
+
+## 1.6.0 (2019-09-17)
+
+- NEW: Support for outputting metrics in Swift.
+- BUGFIX: Provides a helpful error message when `geckoview_datapoint` is used on
+ an metric type that doesn't support GeckoView exfiltration.
+- Generate a lookup table for Gecko categorical histograms in
+ `GleanGeckoMetricsMapping`.
+- Introduce a 'Swift' output generator.
+
+## 1.4.1 (2019-08-28)
+
+- Documentation only.
+
+## 1.4.0 (2019-08-27)
+
+- Added support for generating markdown documentation from `metrics.yaml` files.
+
+## 1.3.0 (2019-08-22)
+
+- `quantity` metric type has been added.
+
+## 1.2.1 (2019-08-13)
+
+- BUGFIX: `includeClientId` was not being output for PingType.
+
+## 1.2.0 (2019-08-13)
+
+- `memory_distribution` metric type has been added.
+- `custom_distribution` metric type has been added.
+- `labeled_timespan` is no longer an allowed metric type.
+
+## 1.1.0 (2019-08-05)
+
+- Add a special `all_pings` value to `send_in_pings`.
+
+## 1.0.0 (2019-07-29)
+
+- First release to start following strict semver.
+
+## 0.1.0 (2018-10-15)
+
+- First release on PyPI.
diff --git a/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/RECORD b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/RECORD
new file mode 100644
index 0000000000..700ca80797
--- /dev/null
+++ b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/RECORD
@@ -0,0 +1,48 @@
+glean_parser/__init__.py,sha256=bJljD052_0y-efcBhYpllICVCXOMHLcXRLNyrvfgt5A,533
+glean_parser/__main__.py,sha256=Rw0PpuQtAvdHJMK1YLozeZkc6x1yjeNZwidu4faovdk,8633
+glean_parser/coverage.py,sha256=2IwC4XMDtDamMkBFoYilmqJzW4gyypq65YVCur8SNas,4405
+glean_parser/data_review.py,sha256=BweeeTkNNS6HrIDkztawhbDByrk_-Avxpg7YeST3VAs,2152
+glean_parser/go_server.py,sha256=s6lxK9IAFY55pNl3Rv4MHlV-nQwSoyhO9ppTQE9VCik,5346
+glean_parser/javascript.py,sha256=w4ZhNBHBKWYk0h3t7G0Ud2tR__hRqzn9dlEXNKLdQrA,11230
+glean_parser/javascript_server.py,sha256=PZSTl63TR3cY8Y99jXMOLu-8rzgQarymzjnHJm9aYK0,8389
+glean_parser/kotlin.py,sha256=5nXnen4s2YOj503Z77HVTUgDHWdulB8BMl8vOie38o4,13365
+glean_parser/lint.py,sha256=STqdgyOhR4Q3fHivSizgn9bOOyqrNHhzjaqyJxz6qzI,19948
+glean_parser/markdown.py,sha256=GkCr1CrV6mnRQseT6FO1-JJ7Eup8X3lxUfRMBTxXpe4,9066
+glean_parser/metrics.py,sha256=YAO8wPuRHTLkdT9M4zh9ZwoFI1_VS8O9oQqwZNYyDp0,14612
+glean_parser/parser.py,sha256=3-uF-Hi5LlvdFc1NxZOKX0EoEyekZGnZV094eTIJut0,16361
+glean_parser/pings.py,sha256=-CIiMBVOTFULmNybV8YTFI7vmfOYOGQ5TD9hEfYPUII,3435
+glean_parser/python_server.py,sha256=ERpYcbSwF19xKFagxX0mZAvlR1y6D7Ah5DSvW8LipCY,4791
+glean_parser/ruby_server.py,sha256=e5lkfcLQAUMUBQDCjqNU82LkdUzT5x-G6HOnsUInbsU,5190
+glean_parser/rust.py,sha256=UEHeIZlToxCBelfec5sl_l_uLZfk8f_OUXqa_ZoEvnk,7330
+glean_parser/swift.py,sha256=paUzF6tItdktFwIQYCKsYpqXfn8zxR2coU_jMYrmwlc,8957
+glean_parser/tags.py,sha256=bemKYvcbMO4JrghiNSe-A4BNNDtx_FlUPkgrPPJy84Y,1391
+glean_parser/translate.py,sha256=luKQoraARZ2tjenHs0SVtCxflnYaMkzPYFfKEdKdSqQ,8403
+glean_parser/translation_options.py,sha256=Lxzr6G7MP0tC_ZYlZXftS4j0SLiqO-5mGVTEc7ggXis,2037
+glean_parser/util.py,sha256=wftmoWBUQM_o7pUwdhBp3HuDCVHIBw1PXtrfxwPLD0Q,16187
+glean_parser/validate_ping.py,sha256=0TNvILH6dtzJDys3W8Kqorw6kk03me73OCUDtpoHcXU,2118
+glean_parser/schemas/metrics.1-0-0.schema.yaml,sha256=cND3cvi6iBfPUVmtfIBQfGJV9AALpbvN7nu8E33_J-o,19566
+glean_parser/schemas/metrics.2-0-0.schema.yaml,sha256=wx1q0L4C0-Vcwk1SPU6t8OfjDEQvgrwwEG6xfSHO1MI,26365
+glean_parser/schemas/pings.1-0-0.schema.yaml,sha256=hwCnsKpEysmrmVp-QHGBArEkVY3vaU1rVsxlTwhAzws,4315
+glean_parser/schemas/pings.2-0-0.schema.yaml,sha256=f8PClAlMoLTmX6ANq8Ai0CpiE74i3LOgU5SoTJpoh0M,6149
+glean_parser/schemas/tags.1-0-0.schema.yaml,sha256=OGXIJlvvVW1vaqB_NVZnwKeZ-sLlfH57vjBSHbj6DNI,1231
+glean_parser/templates/data_review.jinja2,sha256=jeYU29T1zLSyu9fKBBFu5BFPfIw8_hmOUXw8RXhRXK8,3287
+glean_parser/templates/go_server.jinja2,sha256=Jy1e0uQqr_WZNoj-AWnygRmygX2jyj_GQMMV8mSah2k,6825
+glean_parser/templates/javascript.buildinfo.jinja2,sha256=4mXiZCQIk9if4lxlA05kpSIL4a95IdwGwqle2OqqNAs,474
+glean_parser/templates/javascript.jinja2,sha256=cT_bG-jC6m4afECXmcsqHwiiHjRuVtJnfv90OD2Mwxw,2669
+glean_parser/templates/javascript_server.jinja2,sha256=k-XI3QIhHQ1vbIPqSMTmCu93b1oZhm7KLmx9LfO3IJ0,9472
+glean_parser/templates/kotlin.buildinfo.jinja2,sha256=X0lk2SNu5OIIj2i6mUyF9CWFQIonLgfqkgT5fA-5G6c,920
+glean_parser/templates/kotlin.geckoview.jinja2,sha256=MJOgtoDXmBjE9pwk-G6T89y36RZuMbDWM_-DBN_gFJo,5099
+glean_parser/templates/kotlin.jinja2,sha256=npMgDdWD9OItOZQ-dyLQZn_IKgnzee2EdJynhUa1ig8,7690
+glean_parser/templates/markdown.jinja2,sha256=vAHHGGm28HRDPd3zO_wQMAUZIuxE9uQ7hl3NpXxcKV4,3425
+glean_parser/templates/python_server.jinja2,sha256=gu2C1rkn760IqBCG2SWaK7o32T1ify94wDEsudLPUg8,7260
+glean_parser/templates/qmldir.jinja2,sha256=m6IGsp-tgTiOfQ7VN8XW6GqX0gJqJkt3B6Pkaul6FVo,156
+glean_parser/templates/ruby_server.jinja2,sha256=vm4BEenOqzomQNTLFfMOzlWHARnsWUjTBbnR-v2cadI,6247
+glean_parser/templates/rust.jinja2,sha256=Ir_JqWRIUs1KLoYNDolgTRjWfWdzzBfouCP-YeTJa-c,5495
+glean_parser/templates/swift.jinja2,sha256=4f993l_zZk_Tz1efiz3nbvDK1H3Uq3dWQ2T6glT9XQ4,6695
+glean_parser-14.0.1.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455
+glean_parser-14.0.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
+glean_parser-14.0.1.dist-info/METADATA,sha256=Ghvw-Y7woQUJ38P8TYT5TFt8sL61GJoZPBajaB0WLeQ,32276
+glean_parser-14.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+glean_parser-14.0.1.dist-info/entry_points.txt,sha256=mf9d3sv8BwSjjR58x9KDnpVkONCnv3fPQC2NjJl15Xg,68
+glean_parser-14.0.1.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13
+glean_parser-14.0.1.dist-info/RECORD,,
diff --git a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/WHEEL b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/WHEEL
index bab98d6758..bab98d6758 100644
--- a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/WHEEL
+++ b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/WHEEL
diff --git a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/entry_points.txt b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/entry_points.txt
index 08fde9d655..08fde9d655 100644
--- a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/entry_points.txt
+++ b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/entry_points.txt
diff --git a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/top_level.txt b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/top_level.txt
index a7f3a37918..a7f3a37918 100644
--- a/third_party/python/glean_parser/glean_parser-13.0.1.dist-info/top_level.txt
+++ b/third_party/python/glean_parser/glean_parser-14.0.1.dist-info/top_level.txt
diff --git a/third_party/python/glean_parser/glean_parser/javascript_server.py b/third_party/python/glean_parser/glean_parser/javascript_server.py
index f5099d2660..060575f38c 100644
--- a/third_party/python/glean_parser/glean_parser/javascript_server.py
+++ b/third_party/python/glean_parser/glean_parser/javascript_server.py
@@ -42,9 +42,12 @@ from . import util
SUPPORTED_METRIC_TYPES = ["string", "event"]
-def event_class_name(ping_name: str, event_metric_exists: bool) -> str:
+def event_class_name(
+ ping_name: str, metrics_by_type: Dict[str, List[metrics.Metric]]
+) -> str:
# For compatibility with FxA codebase we don't want to add "Logger" suffix
# when custom pings without event metrics are used.
+ event_metric_exists = "event" in metrics_by_type
suffix = "Logger" if event_metric_exists else ""
return util.Camelize(ping_name) + "ServerEvent" + suffix
@@ -61,10 +64,13 @@ def generate_js_metric_type(metric: metrics.Metric) -> str:
return metric.type
-def generate_ping_factory_method(ping: str, event_metric_exists: bool) -> str:
+def generate_ping_factory_method(
+ ping: str, metrics_by_type: Dict[str, List[metrics.Metric]]
+) -> str:
# `ServerEventLogger` better describes role of the class that this factory
# method generates, but for compatibility with existing FxA codebase
# we use `Event` suffix if no event metrics are defined.
+ event_metric_exists = "event" in metrics_by_type
suffix = "ServerEventLogger" if event_metric_exists else "Event"
return f"create{util.Camelize(ping)}{suffix}"
@@ -136,6 +142,12 @@ def output(
metrics_list = metrics_by_type.setdefault(metric.type, [])
metrics_list.append(metric)
+ # Order pings_to_metrics for backwards compatibility with the existing FxA codebase.
+ # Put pings without `event` type metrics first.
+ ping_to_metrics = dict(
+ sorted(ping_to_metrics.items(), key=lambda item: "event" in item[1])
+ )
+
PING_METRIC_ERROR_MSG = (
" Server-side environment is simplified and this"
+ " parser doesn't generate individual metric files. Make sure to pass all"
diff --git a/third_party/python/glean_parser/glean_parser/kotlin.py b/third_party/python/glean_parser/glean_parser/kotlin.py
index 82cc63d237..6d9ea8dcf8 100644
--- a/third_party/python/glean_parser/glean_parser/kotlin.py
+++ b/third_party/python/glean_parser/glean_parser/kotlin.py
@@ -107,6 +107,11 @@ def type_name(obj: Union[metrics.Metric, pings.Ping]) -> str:
return "{}<{}>".format(class_name(obj.type), generic)
+ generate_structure = getattr(obj, "_generate_structure", [])
+ if len(generate_structure):
+ generic = util.Camelize(obj.name) + "Object"
+ return "{}<{}>".format(class_name(obj.type), generic)
+
return class_name(obj.type)
@@ -125,6 +130,21 @@ def extra_type_name(typ: str) -> str:
return "UNSUPPORTED"
+def structure_type_name(typ: str) -> str:
+ """
+ Returns the corresponding Kotlin type for structure items.
+ """
+
+ if typ == "boolean":
+ return "Boolean"
+ elif typ == "string":
+ return "String"
+ elif typ == "number":
+ return "Int"
+ else:
+ return "UNSUPPORTED"
+
+
def class_name(obj_type: str) -> str:
"""
Returns the Kotlin class name for a given metric or ping type.
@@ -320,6 +340,7 @@ def output_kotlin(
("type_name", type_name),
("extra_type_name", extra_type_name),
("class_name", class_name),
+ ("structure_type_name", structure_type_name),
),
)
@@ -333,6 +354,9 @@ def output_kotlin(
has_labeled_metrics = any(
getattr(metric, "labeled", False) for metric in category_val.values()
)
+ has_object_metrics = any(
+ isinstance(metric, metrics.Object) for metric in category_val.values()
+ )
with filepath.open("w", encoding="utf-8") as fd:
fd.write(
@@ -346,6 +370,7 @@ def output_kotlin(
ping_args=util.ping_args,
namespace=namespace,
has_labeled_metrics=has_labeled_metrics,
+ has_object_metrics=has_object_metrics,
glean_namespace=glean_namespace,
)
)
diff --git a/third_party/python/glean_parser/glean_parser/parser.py b/third_party/python/glean_parser/glean_parser/parser.py
index 5ca584ac1e..158676be73 100644
--- a/third_party/python/glean_parser/glean_parser/parser.py
+++ b/third_party/python/glean_parser/glean_parser/parser.py
@@ -11,7 +11,7 @@ Code for parsing metrics.yaml files.
import functools
from pathlib import Path
import textwrap
-from typing import Any, Dict, Generator, Iterable, Optional, Tuple, Union
+from typing import Any, cast, Dict, Generator, Iterable, Optional, Set, Tuple, Union
import jsonschema # type: ignore
from jsonschema.exceptions import ValidationError # type: ignore
@@ -267,6 +267,7 @@ def _instantiate_pings(
"""
global_no_lint = content.get("no_lint", [])
assert isinstance(global_no_lint, list)
+ ping_schedule_reverse_map: Dict[str, Set[str]] = dict()
for ping_key, ping_val in sorted(content.items()):
if ping_key.startswith("$"):
@@ -284,6 +285,22 @@ def _instantiate_pings(
if not isinstance(ping_val, dict):
raise TypeError(f"Invalid content for ping {ping_key}")
ping_val["name"] = ping_key
+
+ if "metadata" in ping_val and "ping_schedule" in ping_val["metadata"]:
+ if ping_key in ping_val["metadata"]["ping_schedule"]:
+ yield util.format_error(
+ filepath,
+ f"For ping '{ping_key}'",
+ "ping_schedule contains its own ping name",
+ )
+ continue
+ for ping_schedule in ping_val["metadata"]["ping_schedule"]:
+ if ping_schedule not in ping_schedule_reverse_map:
+ ping_schedule_reverse_map[ping_schedule] = set()
+ ping_schedule_reverse_map[ping_schedule].add(ping_key)
+
+ del ping_val["metadata"]["ping_schedule"]
+
try:
ping_obj = Ping(
defined_in=getattr(ping_val, "defined_in", None),
@@ -313,6 +330,11 @@ def _instantiate_pings(
all_objects.setdefault("pings", {})[ping_key] = ping_obj
sources[ping_key] = filepath
+ for scheduler, scheduled in ping_schedule_reverse_map.items():
+ if isinstance(all_objects["pings"][scheduler], Ping):
+ scheduler_obj: Ping = cast(Ping, all_objects["pings"][scheduler])
+ scheduler_obj.schedules_pings = sorted(list(scheduled))
+
def _instantiate_tags(
all_objects: ObjectTree,
diff --git a/third_party/python/glean_parser/glean_parser/pings.py b/third_party/python/glean_parser/glean_parser/pings.py
index b4145ea68d..b3f2476c9a 100644
--- a/third_party/python/glean_parser/glean_parser/pings.py
+++ b/third_party/python/glean_parser/glean_parser/pings.py
@@ -31,6 +31,7 @@ class Ping:
reasons: Optional[Dict[str, str]] = None,
defined_in: Optional[Dict] = None,
no_lint: Optional[List[str]] = None,
+ enabled: Optional[bool] = None,
_validated: bool = False,
):
# Avoid cyclical import
@@ -46,6 +47,10 @@ class Ping:
self.metadata = metadata
self.precise_timestamps = self.metadata.get("precise_timestamps", True)
self.include_info_sections = self.metadata.get("include_info_sections", True)
+ if enabled is None:
+ enabled = True
+ self.enabled = enabled
+ self.schedules_pings: List[str] = []
if data_reviews is None:
data_reviews = []
self.data_reviews = data_reviews
@@ -94,6 +99,7 @@ class Ping:
modified_dict = util.remove_output_params(
modified_dict, "include_info_sections"
)
+ modified_dict = util.remove_output_params(modified_dict, "schedules_pings")
return modified_dict
def identifier(self) -> str:
diff --git a/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml b/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml
index 6679a8066b..345812c805 100644
--- a/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml
+++ b/third_party/python/glean_parser/glean_parser/schemas/pings.2-0-0.schema.yaml
@@ -96,6 +96,16 @@ additionalProperties:
Interaction with `include_client_id`: `include_client_id` only takes
effect when `metadata.include_info_sections` is `true`.
type: boolean
+ ping_schedule:
+ title: Ping Schedule
+ description: |
+ An optional array of ping names. When one of the listed pings is
+ sent, then this ping will also be sent. A ping cannot list its own
+ name in `ping_schedule`.
+ type: array
+ items:
+ type: string
+ maxLength: 30
default: {}
@@ -175,6 +185,18 @@ additionalProperties:
additionalProperties:
type: string
+ enabled:
+ title: Whether or not this ping is enabled
+ description: |
+ **Optional.**
+
+ When `true`, the ping will be sent as usual.
+ When `false`, the ping will not be sent, but the data will continue to
+ be collected but will not be cleared when the ping is submitted.
+
+ Defaults to `true` if omitted.
+ type: boolean
+
no_lint:
title: Lint checks to skip
description: |
diff --git a/third_party/python/glean_parser/glean_parser/swift.py b/third_party/python/glean_parser/glean_parser/swift.py
index c745c4d9ac..b121933b0f 100644
--- a/third_party/python/glean_parser/glean_parser/swift.py
+++ b/third_party/python/glean_parser/glean_parser/swift.py
@@ -106,12 +106,17 @@ def type_name(obj: Union[metrics.Metric, pings.Ping]) -> str:
return "{}<{}>".format(class_name(obj.type), generic)
+ generate_structure = getattr(obj, "_generate_structure", [])
+ if len(generate_structure):
+ generic = util.Camelize(obj.name) + "Object"
+ return "{}<{}>".format(class_name(obj.type), generic)
+
return class_name(obj.type)
def extra_type_name(typ: str) -> str:
"""
- Returns the corresponding Kotlin type for event's extra key types.
+ Returns the corresponding Swift type for event's extra key types.
"""
if typ == "boolean":
@@ -124,6 +129,21 @@ def extra_type_name(typ: str) -> str:
return "UNSUPPORTED"
+def structure_type_name(typ: str) -> str:
+ """
+ Returns the corresponding Swift type for structure items.
+ """
+
+ if typ == "boolean":
+ return "Bool"
+ elif typ == "string":
+ return "String"
+ elif typ == "number":
+ return "Int64"
+ else:
+ return "UNSUPPORTED"
+
+
def class_name(obj_type: str) -> str:
"""
Returns the Swift class name for a given metric or ping type.
@@ -215,6 +235,7 @@ def output_swift(
("class_name", class_name),
("variable_name", variable_name),
("extra_type_name", extra_type_name),
+ ("structure_type_name", structure_type_name),
),
)
diff --git a/third_party/python/glean_parser/glean_parser/templates/javascript_server.jinja2 b/third_party/python/glean_parser/glean_parser/templates/javascript_server.jinja2
index 0a89f081f6..9df299fd2b 100644
--- a/third_party/python/glean_parser/glean_parser/templates/javascript_server.jinja2
+++ b/third_party/python/glean_parser/glean_parser/templates/javascript_server.jinja2
@@ -21,7 +21,7 @@ type LoggerOptions = { app: string; fmt?: 'heka' };
type Event = {
category: string;
name: string;
- extra: Record<string, any>;
+ extra?: Record<string, any>;
timestamp?: number;
};
{% endif %}
@@ -30,14 +30,14 @@ type Event = {
let _logger{% if lang == "typescript" %}: Logger{% endif %};
{% for ping, metrics_by_type in pings.items() %}
-class {{ ping|event_class_name(event_metric_exists) }} {
+class {{ ping|event_class_name(metrics_by_type) }} {
{% if lang == "typescript" %}
_applicationId: string;
_appDisplayVersion: string;
_channel: string;
{% endif %}
/**
- * Create {{ ping|event_class_name(event_metric_exists) }} instance.
+ * Create {{ ping|event_class_name(metrics_by_type) }} instance.
*
* @param {string} applicationId - The application ID.
* @param {string} appDisplayVersion - The application display version.
@@ -72,7 +72,7 @@ class {{ ping|event_class_name(event_metric_exists) }} {
{% endif %}
}
}
- {% if event_metric_exists %}
+ {% if 'event' in metrics_by_type %}
#record({
{% else %}
/**
@@ -99,28 +99,28 @@ class {{ ping|event_class_name(event_metric_exists) }} {
{% endfor %}
{% endif %}
{% endfor %}
- {% if event_metric_exists %}
+ {% if 'event' in metrics_by_type %}
event,
{% endif %}
{% if lang == "typescript" %}
}: {
- user_agent: string,
- ip_address: string,
+ user_agent: string;
+ ip_address: string;
{% for metric_type, metrics in metrics_by_type.items() %}
{% if metric_type != 'event' %}
{% for metric in metrics %}
- {{ metric|metric_argument_name }}: {{ metric|js_metric_type }},
+ {{ metric|metric_argument_name }}: {{ metric|js_metric_type }};
{% endfor %}
{% endif %}
{% endfor %}
- {% if event_metric_exists %}
- event: Event
+ {% if 'event' in metrics_by_type %}
+ event: Event;
{% endif %}
{% endif %}
}) {
const now = new Date();
const timestamp = now.toISOString();
- {% if event_metric_exists %}
+ {% if 'event' in metrics_by_type %}
event.timestamp = now.getTime();
{% endif %}
const eventPayload = {
@@ -135,7 +135,7 @@ class {{ ping|event_class_name(event_metric_exists) }} {
{% endif %}
{% endfor %}
},
- {% if event_metric_exists %}
+ {% if 'event' in metrics_by_type %}
events: [event],
{% endif %}
ping_info: {
@@ -171,7 +171,7 @@ class {{ ping|event_class_name(event_metric_exists) }} {
// this is similar to how FxA currently logs with mozlog: https://github.com/mozilla/fxa/blob/4c5c702a7fcbf6f8c6b1f175e9172cdd21471eac/packages/fxa-auth-server/lib/log.js#L289
_logger.info(GLEAN_EVENT_MOZLOG_TYPE, ping);
}
- {% if event_metric_exists %}
+ {% if 'event' in metrics_by_type %}
{% for event in metrics_by_type["event"] %}
/**
* Record and submit a {{ event.category }}_{{ event.name }} event:
@@ -209,27 +209,27 @@ class {{ ping|event_class_name(event_metric_exists) }} {
{% endfor %}
{% if lang == "typescript" %}
}: {
- user_agent: string,
- ip_address: string,
+ user_agent: string;
+ ip_address: string;
{% for metric_type, metrics in metrics_by_type.items() %}
{% if metric_type != 'event' %}
{% for metric in metrics %}
- {{ metric|metric_argument_name }}: {{ metric|js_metric_type }},
+ {{ metric|metric_argument_name }}: {{ metric|js_metric_type }};
{% endfor %}
{% endif %}
{% endfor %}
{% for extra, metadata in event.extra_keys.items() %}
- {{ extra }}: {{metadata.type}},
+ {{ extra }}: {{metadata.type}};
{% endfor %}
{% endif %}
}) {
- let event = {
- 'category': '{{ event.category }}',
- 'name': '{{ event.name }}',
+ const event = {
+ category: '{{ event.category }}',
+ name: '{{ event.name }}',
{% if event.extra_keys %}
- 'extra': {
+ extra: {
{% for extra, metadata in event.extra_keys.items() %}
- '{{ extra }}': {{ extra }},
+ {{ extra }}: {{ extra }},
{% endfor %}
},
{% endif %}
@@ -244,14 +244,14 @@ class {{ ping|event_class_name(event_metric_exists) }} {
{% endfor %}
{% endif %}
{% endfor %}
- event
+ event,
});
}
{% endfor %}
{% endif %}
}
{% endfor %}
-{% for ping in pings %}
+{% for ping, metrics_by_type in pings.items() %}
/**
* Factory function that creates an instance of Glean Server Event Logger to
@@ -262,11 +262,11 @@ class {{ ping|event_class_name(event_metric_exists) }} {
* @param {Object} logger_options - The logger options.
* @returns {EventsServerEventLogger} An instance of EventsServerEventLogger.
*/
-export const {{ ping|factory_method(event_metric_exists) }} = function ({
+export const {{ ping|factory_method(metrics_by_type) }} = function ({
applicationId,
appDisplayVersion,
channel,
- logger_options
+ logger_options,
{% if lang == "typescript" %}
}: {
applicationId: string;
@@ -275,7 +275,7 @@ export const {{ ping|factory_method(event_metric_exists) }} = function ({
logger_options: LoggerOptions;
{% endif %}
}) {
- return new {{ ping|event_class_name(event_metric_exists) }}(
+ return new {{ ping|event_class_name(metrics_by_type) }}(
applicationId,
appDisplayVersion,
channel,
diff --git a/third_party/python/glean_parser/glean_parser/templates/kotlin.jinja2 b/third_party/python/glean_parser/glean_parser/templates/kotlin.jinja2
index bd800af01d..71ba386a4c 100644
--- a/third_party/python/glean_parser/glean_parser/templates/kotlin.jinja2
+++ b/third_party/python/glean_parser/glean_parser/templates/kotlin.jinja2
@@ -66,6 +66,61 @@ data class {{ obj.name|Camelize }}{{ suffix }}(
}
{%- endmacro -%}
+{%- macro generate_structure(name, struct) %}
+{%- if struct.type == "array" -%}
+ @Serializable
+ data class {{ name }}(var items: MutableList<{{ name }}Item> = mutableListOf()) : ObjectSerialize {
+ fun add(elem: {{ name }}Item) = items.add(elem)
+
+ fun addAll(elements: Collection<{{ name }}Item>) = items.addAll(elements)
+
+ fun clear() = items.clear()
+
+ fun remove(element: {{ name }}Item) = items.remove(element)
+ fun removeAll(elements: Collection<{{ name }}Item>) = items.removeAll(elements)
+ fun removeAt(index: Int) = items.removeAt(index)
+
+ fun set(index: Int, element: {{ name }}Item) = items.set(index, element)
+
+ override fun intoSerializedObject(): String {
+ return Json.encodeToString(items)
+ }
+ }
+
+ {{ generate_structure(name ~ "Item", struct["items"]) }}
+
+{%- elif struct.type == "object" -%}
+ @Serializable
+ data class {{ name }}(
+ {% for itemname, val in struct.properties.items() %}
+ {% if val.type == "object" %}
+ var {{itemname|camelize}}: {{ name ~ "Item" ~ itemname|Camelize ~ "Object" }}? = null,
+ {% elif val.type == "array" %}
+ var {{itemname|camelize}}: {{ name ~ "Item" ~ itemname|Camelize }} = {{ name ~ "Item" ~ itemname|Camelize }}(),
+ {% else %}
+ var {{itemname|camelize}}: {{val.type|structure_type_name}}? = null,
+ {% endif %}
+ {% endfor %}
+ ): ObjectSerialize {
+ override fun intoSerializedObject(): String {
+ return Json.encodeToString(this)
+ }
+ }
+
+ {% for itemname, val in struct.properties.items() %}
+ {% if val.type == "array" %}
+ {% set nested_name = name ~ "Item" ~ itemname|Camelize %}
+ {{ generate_structure(nested_name, val) }}
+ {% elif val.type == "object" %}
+ {% set nested_name = name ~ "Item" ~ itemname|Camelize ~ "Object" %}
+ {{ generate_structure(nested_name, val) }}
+ {% endif %}
+ {% endfor %}
+
+{% endif %}
+
+{% endmacro %}
+
/* ktlint-disable no-blank-line-before-rbrace */
@file:Suppress("PackageNaming", "MaxLineLength")
package {{ namespace }}
@@ -76,8 +131,9 @@ import {{ glean_namespace }}.private.HistogramType // ktlint-disable import-orde
import {{ glean_namespace }}.private.Lifetime // ktlint-disable import-ordering no-unused-imports
import {{ glean_namespace }}.private.MemoryUnit // ktlint-disable import-ordering no-unused-imports
import {{ glean_namespace }}.private.NoExtras // ktlint-disable import-ordering no-unused-imports
-import {{ glean_namespace }}.private.ReasonCode // ktlint-disable import-ordering no-unused-imports
import {{ glean_namespace }}.private.NoReasonCodes // ktlint-disable import-ordering no-unused-imports
+import {{ glean_namespace }}.private.ObjectSerialize // ktlint-disable import-ordering no-unused-imports
+import {{ glean_namespace }}.private.ReasonCode // ktlint-disable import-ordering no-unused-imports
import {{ glean_namespace }}.private.TimeUnit // ktlint-disable import-ordering no-unused-imports
{% for obj_type in obj_types %}
import {{ glean_namespace }}.private.{{ obj_type }} // ktlint-disable import-ordering
@@ -85,6 +141,11 @@ import {{ glean_namespace }}.private.{{ obj_type }} // ktlint-disable import-ord
{% if has_labeled_metrics %}
import {{ glean_namespace }}.private.LabeledMetricType // ktlint-disable import-ordering
{% endif %}
+{% if has_object_metrics %}
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+{% endif %}
internal object {{ category_name|Camelize }} {
{% for obj in objs.values() %}
@@ -97,6 +158,9 @@ internal object {{ category_name|Camelize }} {
{% endfor %}
{% endif %}
{% else %}
+ {% if obj|attr("_generate_structure") %}
+ {{ generate_structure(obj.name|Camelize ~ "Object", obj._generate_structure) }}
+ {%- endif %}
{% if obj|attr("_generate_enums") %}
{% for name, suffix in obj["_generate_enums"] %}
{% if obj|attr(name)|length %}
diff --git a/third_party/python/glean_parser/glean_parser/templates/rust.jinja2 b/third_party/python/glean_parser/glean_parser/templates/rust.jinja2
index 4c54dd2b2c..269a007ac5 100644
--- a/third_party/python/glean_parser/glean_parser/templates/rust.jinja2
+++ b/third_party/python/glean_parser/glean_parser/templates/rust.jinja2
@@ -87,7 +87,7 @@ impl ExtraKeys for {{ obj.name|Camelize }}{{ suffix }} {
/// {{ obj.description|wordwrap() | replace('\n', '\n/// ') }}
#[rustfmt::skip]
pub static {{ obj.name|snake_case }}: ::glean::private::__export::Lazy<::glean::private::PingType> =
- ::glean::private::__export::Lazy::new(|| ::glean::private::PingType::new("{{ obj.name }}", {{ obj.include_client_id|rust }}, {{ obj.send_if_empty|rust }}, {{ obj.precise_timestamps|rust }}, {{ obj.include_info_sections|rust }}, {{ obj.reason_codes|rust }}));
+ ::glean::private::__export::Lazy::new(|| ::glean::private::PingType::new("{{ obj.name }}", {{ obj.include_client_id|rust }}, {{ obj.send_if_empty|rust }}, {{ obj.precise_timestamps|rust }}, {{ obj.include_info_sections|rust }}, {{ obj.enabled|rust }}, {{ obj.schedules_pings|rust }}, {{ obj.reason_codes|rust }}));
{% endfor %}
{% else %}
pub mod {{ category.name|snake_case }} {
diff --git a/third_party/python/glean_parser/glean_parser/templates/swift.jinja2 b/third_party/python/glean_parser/glean_parser/templates/swift.jinja2
index 714bf20ec2..fe51a078bc 100644
--- a/third_party/python/glean_parser/glean_parser/templates/swift.jinja2
+++ b/third_party/python/glean_parser/glean_parser/templates/swift.jinja2
@@ -11,7 +11,7 @@ Jinja2 template is not. Please file bugs! #}
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-{% macro obj_declaration(obj, suffix='', access='') %}
+{%- macro obj_declaration(obj, suffix='', access='') %}
{{ access }}static let {{ obj.name|camelize|variable_name }}{{ suffix }} = {{ obj|type_name }}( // generated from {{ obj.identifier() }}
CommonMetricData(
{% for arg_name in common_metric_args if obj[arg_name] is defined %}
@@ -24,7 +24,7 @@ Jinja2 template is not. Please file bugs! #}
)
{% endmacro %}
-{% macro struct_decl(obj, name, suffix) %}
+{%- macro struct_decl(obj, name, suffix) %}
struct {{ obj.name|Camelize }}{{ suffix }}: EventExtras {
{% for item, typ in obj|attr(name) %}
var {{ item|camelize|variable_name }}: {{typ|extra_type_name}}?
@@ -44,6 +44,46 @@ struct {{ obj.name|Camelize }}{{ suffix }}: EventExtras {
}
{% endmacro %}
+{%- macro generate_structure(name, struct) %}
+{%- if struct.type == "array" -%}
+ typealias {{ name }} = [{{ name }}Item]
+
+ {{ generate_structure(name ~ "Item", struct["items"]) }}
+
+{%- elif struct.type == "object" -%}
+ struct {{ name }}: Codable, Equatable, ObjectSerialize {
+ {% for itemname, val in struct.properties.items() %}
+ {% if val.type == "object" %}
+ var {{itemname|camelize|variable_name}}: {{ name ~ "Item" ~ itemname|Camelize ~ "Object" }}?
+ {% elif val.type == "array" %}
+ var {{itemname|camelize|variable_name}}: {{ name ~ "Item" ~ itemname|Camelize }}
+ {% else %}
+ var {{itemname|camelize|variable_name}}: {{val.type|structure_type_name}}?
+ {% endif %}
+ {% endfor %}
+
+ func intoSerializedObject() -> String {
+ let jsonEncoder = JSONEncoder()
+ let jsonData = try! jsonEncoder.encode(self)
+ let json = String(data: jsonData, encoding: String.Encoding.utf8)!
+ return json
+ }
+ }
+
+ {% for itemname, val in struct.properties.items() %}
+ {% if val.type == "array" %}
+ {% set nested_name = name ~ "Item" ~ itemname|Camelize %}
+ {{ generate_structure(nested_name, val) }}
+ {% elif val.type == "object" %}
+ {% set nested_name = name ~ "Item" ~ itemname|Camelize ~ "Object" %}
+ {{ generate_structure(nested_name, val) }}
+ {% endif %}
+ {% endfor %}
+
+{%- endif -%}
+
+{% endmacro %}
+
{% if not allow_reserved %}
import {{ glean_namespace }}
@@ -97,6 +137,8 @@ extension {{ namespace }} {
sendIfEmpty: {{obj.send_if_empty|swift}},
preciseTimestamps: {{obj.precise_timestamps|swift}},
includeInfoSections: {{obj.include_info_sections|swift}},
+ enabled: {{obj.enabled|swift}},
+ schedulesPings: {{obj.schedules_pings|swift}},
reasonCodes: {{obj.reason_codes|swift}}
)
@@ -106,6 +148,9 @@ extension {{ namespace }} {
{% else %}
enum {{ category.name|Camelize }} {
{% for obj in category.objs.values() %}
+ {% if obj|attr("_generate_structure") %}
+ {{ generate_structure(obj.name|Camelize ~ "Object", obj._generate_structure) }}
+ {%- endif %}
{% if obj|attr("_generate_enums") %}
{% for name, suffix in obj["_generate_enums"] %}
{% if obj|attr(name)|length %}
diff --git a/third_party/python/glean_parser/glean_parser/util.py b/third_party/python/glean_parser/glean_parser/util.py
index f8bc7d4f53..a61e318dbe 100644
--- a/third_party/python/glean_parser/glean_parser/util.py
+++ b/third_party/python/glean_parser/glean_parser/util.py
@@ -531,6 +531,8 @@ ping_args = [
"send_if_empty",
"precise_timestamps",
"include_info_sections",
+ "enabled",
+ "schedules_pings",
"reason_codes",
]
diff --git a/third_party/python/poetry.lock b/third_party/python/poetry.lock
index 97513f8ba5..0547486b27 100644
--- a/third_party/python/poetry.lock
+++ b/third_party/python/poetry.lock
@@ -592,14 +592,14 @@ files = [
[[package]]
name = "glean-parser"
-version = "13.0.1"
+version = "14.0.1"
description = "Parser tools for Mozilla's Glean telemetry"
category = "main"
optional = false
python-versions = "*"
files = [
- {file = "glean_parser-13.0.1-py3-none-any.whl", hash = "sha256:8421c88f3673dd195d0cde635f4f09c9bfd0c9709ad3d28c8b201b3b7145e257"},
- {file = "glean_parser-13.0.1.tar.gz", hash = "sha256:feead4cbec6930ed38a48df5bae9eb4ee486bb4026ddf2f3206b85f80279d1e7"},
+ {file = "glean_parser-14.0.1-py3-none-any.whl", hash = "sha256:3275ca235885c99da659fa7d9bf929b8fb020df79d26fcbec317328c369cd039"},
+ {file = "glean_parser-14.0.1.tar.gz", hash = "sha256:3e9e5f99ad8592300e364b70d6247b21c445774a73a2ad274677fb58a0065809"},
]
[package.dependencies]
@@ -1161,7 +1161,6 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
@@ -1376,14 +1375,14 @@ test = ["aiofiles", "coverage", "flake8", "httmock", "httptest", "hypothesis", "
[[package]]
name = "taskcluster-taskgraph"
-version = "6.3.0"
+version = "8.0.1"
description = "Build taskcluster taskgraphs"
category = "main"
optional = false
python-versions = "*"
files = [
- {file = "taskcluster-taskgraph-6.3.0.tar.gz", hash = "sha256:a32ac3aad6aa90c593268bee8864d9f773e86e1f53d0b513d128d59b52c1e20b"},
- {file = "taskcluster_taskgraph-6.3.0-py3-none-any.whl", hash = "sha256:43ce187215ab8658c06ad80f46c4606ce51b9986f4365d541416eecf9d6a2c28"},
+ {file = "taskcluster-taskgraph-8.0.1.tar.gz", hash = "sha256:21387537bbebab2a7b1890d03e20e49379bdda65efd45ca7fb8d01f5c29e1797"},
+ {file = "taskcluster_taskgraph-8.0.1-py3-none-any.whl", hash = "sha256:14500bc703f64eb002c0cd505caaf2d34ffc0ae66d109b108e738661da1ae09c"},
]
[package.dependencies]
@@ -1625,4 +1624,4 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "cef77da3299e7849f5039e8d9017216048d4ca56af298209e5bf3db7f92c2d4c"
+content-hash = "8e72dc9ba9b4f08d27d90f99666459a814d1bb293c68de222614ea57db5b70ef"
diff --git a/third_party/python/requirements.in b/third_party/python/requirements.in
index 9915e91957..abcfc79239 100644
--- a/third_party/python/requirements.in
+++ b/third_party/python/requirements.in
@@ -22,7 +22,7 @@ fluent.migrate==0.13.0
fluent.syntax==0.19.0
# Pin `frozenlist` as it is required for `aiohttp`. Use minimum required version.
frozenlist==1.1.1
-glean_parser==13.0.1
+glean_parser==14.0.1
importlib-metadata==6.0.0
# required for compatibility with Flask >= 2 in tools/tryselect/selectors/chooser
jinja2==3.1.2
@@ -53,7 +53,7 @@ setuptools==68.0.0
six==1.16.0
slugid==2.0.0
taskcluster==44.2.2
-taskcluster-taskgraph==6.3.0
+taskcluster-taskgraph==8.0.1
taskcluster-urls==13.0.1
toml==0.10.2
tomlkit==0.12.3
diff --git a/third_party/python/requirements.txt b/third_party/python/requirements.txt
index eedc022c50..3b8c897e8a 100644
--- a/third_party/python/requirements.txt
+++ b/third_party/python/requirements.txt
@@ -275,9 +275,9 @@ frozenlist==1.1.1 ; python_version >= "3.8" and python_version < "4.0" \
giturlparse==0.10.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:04ba1a3a099c3093fa8d24a422913c6a9b2c2cd22bcffc939cf72e3e98f672d7 \
--hash=sha256:2595ab291d30717cda8474b874c9fd509f1b9802ad7f6968c36a45e4b13eb337
-glean-parser==13.0.1 ; python_version >= "3.8" and python_version < "4.0" \
- --hash=sha256:8421c88f3673dd195d0cde635f4f09c9bfd0c9709ad3d28c8b201b3b7145e257 \
- --hash=sha256:feead4cbec6930ed38a48df5bae9eb4ee486bb4026ddf2f3206b85f80279d1e7
+glean-parser==14.0.1 ; python_version >= "3.8" and python_version < "4.0" \
+ --hash=sha256:3275ca235885c99da659fa7d9bf929b8fb020df79d26fcbec317328c369cd039 \
+ --hash=sha256:3e9e5f99ad8592300e364b70d6247b21c445774a73a2ad274677fb58a0065809
idna==2.10 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
@@ -492,7 +492,6 @@ pyyaml==6.0.1 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
- --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -540,9 +539,9 @@ six==1.16.0 ; python_version >= "3.8" and python_version < "4.0" \
slugid==2.0.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:a950d98b72691178bdd4d6c52743c4a2aa039207cf7a97d71060a111ff9ba297 \
--hash=sha256:aec8b0e01c4ad32e38e12d609eab3ec912fd129aaf6b2ded0199b56a5f8fd67c
-taskcluster-taskgraph==6.3.0 ; python_version >= "3.8" and python_version < "4.0" \
- --hash=sha256:43ce187215ab8658c06ad80f46c4606ce51b9986f4365d541416eecf9d6a2c28 \
- --hash=sha256:a32ac3aad6aa90c593268bee8864d9f773e86e1f53d0b513d128d59b52c1e20b
+taskcluster-taskgraph==8.0.1 ; python_version >= "3.8" and python_version < "4.0" \
+ --hash=sha256:14500bc703f64eb002c0cd505caaf2d34ffc0ae66d109b108e738661da1ae09c \
+ --hash=sha256:21387537bbebab2a7b1890d03e20e49379bdda65efd45ca7fb8d01f5c29e1797
taskcluster-urls==13.0.1 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:5e25e7e6818e8877178b175ff43d2e6548afad72694aa125f404a7329ece0973 \
--hash=sha256:b25e122ecec249c4299ac7b20b08db76e3e2025bdaeb699a9d444556de5fd367 \
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/METADATA b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/METADATA
deleted file mode 100644
index 536b4274f6..0000000000
--- a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/METADATA
+++ /dev/null
@@ -1,28 +0,0 @@
-Metadata-Version: 2.1
-Name: taskcluster-taskgraph
-Version: 6.3.0
-Summary: Build taskcluster taskgraphs
-Home-page: https://github.com/taskcluster/taskgraph
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Console
-Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: 3.11
-Classifier: Topic :: Software Development
-License-File: LICENSE
-Requires-Dist: appdirs (>=1.4)
-Requires-Dist: cookiecutter (~=2.1)
-Requires-Dist: json-e (>=2.7)
-Requires-Dist: mozilla-repo-urls
-Requires-Dist: PyYAML (>=5.3.1)
-Requires-Dist: redo (>=2.0)
-Requires-Dist: requests (>=2.25)
-Requires-Dist: slugid (>=2.0)
-Requires-Dist: taskcluster-urls (>=11.0)
-Requires-Dist: voluptuous (>=0.12.1)
-Provides-Extra: load-image
-Requires-Dist: zstandard ; extra == 'load-image'
-
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/RECORD b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/RECORD
deleted file mode 100644
index 3a6dfdfc35..0000000000
--- a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/RECORD
+++ /dev/null
@@ -1,80 +0,0 @@
-taskgraph/__init__.py,sha256=ILqRnb_Cy7WBFggPsK8BML-nmWySW-capstDs3pWb-c,729
-taskgraph/config.py,sha256=XJYKaA9Egn7aiyZ0v70VCq3Kc-XkK08CK2LDsDfsDR8,4822
-taskgraph/create.py,sha256=MeWVr5gKJefjwK_3_xZUcDDu2NVH97gbUuu1dw_I9hA,5184
-taskgraph/decision.py,sha256=qARBTlLYJ7NVw3aflrspRn_hFmvKcrXJ058yao_4b7A,12882
-taskgraph/docker.py,sha256=6tdGVrKFNonznRJSP4IDZEhKnjV-wYKsR0nXnoDOvZk,7924
-taskgraph/files_changed.py,sha256=W3_gEgUT-mVH9DaaU_8X6gYpftrqBU3kgveGbzPLziU,2793
-taskgraph/filter_tasks.py,sha256=R7tYXiaVPGIkQ6O1c9-QJrKZ59m9pFXCloUlPraVnZU,866
-taskgraph/generator.py,sha256=AmkMCVNmj5spJhRfpSx7-zP3v8OU7i8zAbGMROLLEG8,15668
-taskgraph/graph.py,sha256=bHUsv2pPa2SSaWgBY-ItIj7REPd0o4fFYrwoQbwFKTY,4680
-taskgraph/main.py,sha256=UHSywURHwD56w2vGHgjA8O7K1yaCltgMXlJuuFfFjvY,26802
-taskgraph/morph.py,sha256=Q6weAi-xpJM4XoKA2mM6gVXQYLnE1YSws53vTZygMkY,9192
-taskgraph/parameters.py,sha256=xaEUElvdKhxHeJNRMF-6JBFDFiVO1Es2fm38PJQ1JA4,12134
-taskgraph/target_tasks.py,sha256=41BIVwiATy8DCQujPduTtnFmgHlKOfw6RPGL4b20WO8,3324
-taskgraph/task.py,sha256=tRr7WhJ2qjYXi-77wva17CpfK53m6W_cl-xzks_GGaQ,3240
-taskgraph/taskgraph.py,sha256=Fh5cX8LrgYmkpVP_uhpfRgHSKHfZjO-VGSmnFUjEru0,2434
-taskgraph/actions/__init__.py,sha256=lVP1e0YyELg7-_42MWWDbT0cKv_p53BApVE6vWOiPww,416
-taskgraph/actions/add_new_jobs.py,sha256=HAfuRDzFti_YmeudxqVl6hgrEbm-ki5-jSCDMC0HBDE,1836
-taskgraph/actions/cancel.py,sha256=UQSt_6y3S6PXNmUo_mNaUOuDvK2bixWjzdjTKXieEEg,1309
-taskgraph/actions/cancel_all.py,sha256=zrKgnW63gMGS5yldJieDt-GAR_XTiGRgybWAipIUCqQ,1941
-taskgraph/actions/rebuild_cached_tasks.py,sha256=UrVAvTmkkF4TAB5vNSpK1kJqMhMkKAMGmrifxH9kQJQ,1086
-taskgraph/actions/registry.py,sha256=xmhoEGMyYj6TTRFwMowZAUp0aqvtLvdVfmRWM7Yh7xo,13122
-taskgraph/actions/retrigger.py,sha256=wF08p_CgsfqraYelc3JLmPcqBFcO-Yt8gZZLlJZBixQ,9387
-taskgraph/actions/util.py,sha256=TxWxMWiKZeuKRwqiUawzjzpa5VF5AWgAKCLy7YaKG80,10661
-taskgraph/loader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-taskgraph/loader/default.py,sha256=ND_Sx7yx7io1B-6rWEGkg3UIy7iO3DvSLMXwcEqF1N8,1185
-taskgraph/loader/transform.py,sha256=olUBPjxk3eEIg25sduxlcyqhjoig4ts5kPlT_zs6g9g,2147
-taskgraph/optimize/__init__.py,sha256=Oqpq1RW8QzOcu7zaMlNQ3BHT9ws9e_93FWfCqzNcQps,123
-taskgraph/optimize/base.py,sha256=WvoDNewyHG46IQbG3th-aau9OxSKegsYNfvdOEmunbA,18341
-taskgraph/optimize/strategies.py,sha256=IifMlxppVrIABsvn6UBwQYBFUdxkmyZz_FOtK6yNPps,2380
-taskgraph/run-task/fetch-content,sha256=G1aAvZlTg0yWHqxhSxi4RvfxW-KBJ5JwnGtWRqfH_bg,29990
-taskgraph/run-task/hgrc,sha256=BybWLDR89bWi3pE5T05UqmDHs02CbLypE-omLZWU6Uk,896
-taskgraph/run-task/robustcheckout.py,sha256=vPKvHb3fIIJli9ZVZG88XYoa8Sohy2JrpmH6pDgBDHI,30813
-taskgraph/run-task/run-task,sha256=Mpr195iq9eOh6B4MBpPzEDlxeNyJq0Fa2yrtlJunlXE,45434
-taskgraph/transforms/__init__.py,sha256=aw1dz2sRWZcbTILl6SVDuqIEw0mDdjSYu3LCVs-RLXE,110
-taskgraph/transforms/base.py,sha256=LFw2NwhrSriI3vbcCttArTFb7uHxckQpHeFZmatofvM,5146
-taskgraph/transforms/cached_tasks.py,sha256=Z10VD1kEBVXJvj8qSsNTq2mYpklh0V1EN8OT6QK3v_E,2607
-taskgraph/transforms/chunking.py,sha256=7z9oXiA2dDguYwJPaZYCi-fEzbc--O9avZAFS3vP_kg,2592
-taskgraph/transforms/code_review.py,sha256=eE2xrDtdD_n3HT3caQ2HGAkPm6Uutdm4hDCpCoFjEps,707
-taskgraph/transforms/docker_image.py,sha256=AUuWMx43FcQfgbXy4_2Sjae0cWrh5XWMMcJ3ItcoKes,7606
-taskgraph/transforms/fetch.py,sha256=ORnxpVidOQtI1q1xeHl1c1jlShXD8R_jTGC2CX3lLM4,10479
-taskgraph/transforms/from_deps.py,sha256=1mdjIWYshVI2zBywzB3JEqOyvqgVjFvarcQt9PLDSc4,8950
-taskgraph/transforms/notify.py,sha256=0sga-Ls9dhWLAsL0FBjXmVbbduee8LAZp_1pHBQR0iI,6019
-taskgraph/transforms/task.py,sha256=0oQYH7Upjus0-gzCrYbE0tUKZQUEv6Uq1adGBqiNM60,52254
-taskgraph/transforms/task_context.py,sha256=FxZwT69ozierogtlCTNvk7zCW52d0HdhCaJN7EDmI1s,4272
-taskgraph/transforms/job/__init__.py,sha256=JbNpqdoJRId24QVGe821r6u7Zvm2fTNvME_PMGunaoU,17706
-taskgraph/transforms/job/common.py,sha256=ldlbRI8sdEd-eUcre4GtXMerUg0RQZ_XSe9GwAkfI3I,5897
-taskgraph/transforms/job/index_search.py,sha256=Ngh9FFu1bx2kHVTChW2vcrbnb3SzMneRHopXk18RfB4,1220
-taskgraph/transforms/job/run_task.py,sha256=s9gq1bPdzBB0j2OguXJpWn1-S5Ctltqo4aLsB4kzpUc,8385
-taskgraph/transforms/job/toolchain.py,sha256=GOqIvp1MgtV-6whi2ofgSCFB7GolikZbfLXz0C1h0vc,6015
-taskgraph/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-taskgraph/util/archive.py,sha256=nzYn8cQ3NfLAeV-2SuTNoeQ6hg8m40f6FQcSTyVIKwQ,2855
-taskgraph/util/attributes.py,sha256=pPOFmwkDQQ-IqfDpVghZ10YI_qXRY4Bi5JP3xr6XVvc,2964
-taskgraph/util/cached_tasks.py,sha256=o-yJ91wlWbzoDB2GvKPpGcDE27_IEMgczp_figEBjV8,3406
-taskgraph/util/decision.py,sha256=uTC143FpTKQkGff5jIz3voWRYXBCHgx-XAm7FMW53hE,2433
-taskgraph/util/dependencies.py,sha256=3Qba3zI87JYR5fk5FndGzEVW-5NIzzZrBf9rVYcnLD0,2734
-taskgraph/util/docker.py,sha256=rTbzUt8S6s3N1r8gmwHrqsIY9VZ7TDWBM-jZQ5w0P_U,7762
-taskgraph/util/hash.py,sha256=31sQmDwQOavA5hWsmzWDNFoFTaTp5a7qLSQLNTEALD8,1661
-taskgraph/util/keyed_by.py,sha256=cgBH4tG8eH5UUrm5q4ODG7A4fzkGAOI7feVoZy3V8Ho,3419
-taskgraph/util/memoize.py,sha256=XDlwc-56gzoY8QTwOoiCOYL-igX7JoMcY-9Ih80Euc8,1331
-taskgraph/util/parameterization.py,sha256=dzxh8Bc8MBKoDMwj2V2AQab9UrC-JcM3tg0hDVTWpjc,3184
-taskgraph/util/path.py,sha256=e-JloOQV2-Oua_pe335bv4xWAB07vb82TKpu_zCOl0w,4466
-taskgraph/util/python_path.py,sha256=ed4F5z2mId56LauVczgxm_LGxgQi8XlxlYDgXOPZyII,1576
-taskgraph/util/readonlydict.py,sha256=XzTG-gqGqWVlSkDxSyOL6Ur7Z0ONhIJ9DVLWV3q4q1w,787
-taskgraph/util/schema.py,sha256=JGd0Imjfv6JKCY_tjJtOYwI6uwKUaNgzAcvcZj5WE6A,8323
-taskgraph/util/shell.py,sha256=MB9zHVSvxgOuszgmKr2rWUDahANZkbHHNkjjagZG_3I,1317
-taskgraph/util/taskcluster.py,sha256=cGUGvkrefRHngjyZm_iQRYKRlGi4jMIr7ky0fi_YBrg,12445
-taskgraph/util/taskgraph.py,sha256=ecKEvTfmLVvEKLPO_0g34CqVvc0iCzuNMh3064BZNrE,1969
-taskgraph/util/templates.py,sha256=HGTaIKCpAwEzBDHq0cDai1HJjPJrdnHsjJz6N4LVpKI,2139
-taskgraph/util/time.py,sha256=pNFcTH-iYRfm2-okm1lMATc4B5wO-_FXbOFXEtXD27g,3390
-taskgraph/util/treeherder.py,sha256=A3rpPUQB60Gn1Yx-OZgKuWWGJ8x0-6tcdeeslzco9ag,2687
-taskgraph/util/vcs.py,sha256=54Haq2XyC5CmPnjrPRQZY5wUeoFsaV9pWTYvBjPcVMA,18917
-taskgraph/util/verify.py,sha256=cSd7EeP9hUvp-5WOvKDHrvpFAGb_LuiNPxPp0-YmNEA,8947
-taskgraph/util/workertypes.py,sha256=1wgM6vLrlgtyv8854anVIs0Bx11kV8JJJaKcOHJc2j0,2498
-taskgraph/util/yaml.py,sha256=hfKI_D8Q7dimq4_VvO3WEh8CJsTrsIMwN6set7HIQbY,990
-taskcluster_taskgraph-6.3.0.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
-taskcluster_taskgraph-6.3.0.dist-info/METADATA,sha256=MgIgtvNBRjc0CjnoD-7KHLPpz3sGlja2CZU3GzUMW84,1046
-taskcluster_taskgraph-6.3.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
-taskcluster_taskgraph-6.3.0.dist-info/entry_points.txt,sha256=2hxDzE3qq_sHh-J3ROqwpxgQgxO-196phWAQREl2-XA,50
-taskcluster_taskgraph-6.3.0.dist-info/top_level.txt,sha256=3JNeYn_hNiNXC7DrdH_vcv-WYSE7QdgGjdvUYvSjVp0,10
-taskcluster_taskgraph-6.3.0.dist-info/RECORD,,
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/WHEEL b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/WHEEL
deleted file mode 100644
index becc9a66ea..0000000000
--- a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/WHEEL
+++ /dev/null
@@ -1,5 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.37.1)
-Root-Is-Purelib: true
-Tag: py3-none-any
-
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/LICENSE b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/LICENSE
index a612ad9813..a612ad9813 100644
--- a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/LICENSE
+++ b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/LICENSE
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/METADATA b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/METADATA
new file mode 100644
index 0000000000..e549db9aa3
--- /dev/null
+++ b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/METADATA
@@ -0,0 +1,123 @@
+Metadata-Version: 2.1
+Name: taskcluster-taskgraph
+Version: 8.0.1
+Summary: Build taskcluster taskgraphs
+Home-page: https://github.com/taskcluster/taskgraph
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Topic :: Software Development
+License-File: LICENSE
+Requires-Dist: appdirs >=1.4
+Requires-Dist: cookiecutter ~=2.1
+Requires-Dist: json-e >=2.7
+Requires-Dist: mozilla-repo-urls
+Requires-Dist: PyYAML >=5.3.1
+Requires-Dist: redo >=2.0
+Requires-Dist: requests >=2.25
+Requires-Dist: slugid >=2.0
+Requires-Dist: taskcluster-urls >=11.0
+Requires-Dist: voluptuous >=0.12.1
+Provides-Extra: load-image
+Requires-Dist: zstandard ; extra == 'load-image'
+
+
+.. image:: https://firefox-ci-tc.services.mozilla.com/api/github/v1/repository/taskcluster/taskgraph/main/badge.svg
+ :target: https://firefox-ci-tc.services.mozilla.com/api/github/v1/repository/taskcluster/taskgraph/main/latest
+ :alt: Task Status
+
+.. image:: https://results.pre-commit.ci/badge/github/taskcluster/taskgraph/main.svg
+ :target: https://results.pre-commit.ci/latest/github/taskcluster/taskgraph/main
+ :alt: pre-commit.ci status
+
+.. image:: https://codecov.io/gh/taskcluster/taskgraph/branch/main/graph/badge.svg?token=GJIV52ZQNP
+ :target: https://codecov.io/gh/taskcluster/taskgraph
+ :alt: Code Coverage
+
+.. image:: https://badge.fury.io/py/taskcluster-taskgraph.svg
+ :target: https://badge.fury.io/py/taskcluster-taskgraph
+ :alt: Pypi Version
+
+.. image:: https://readthedocs.org/projects/taskcluster-taskgraph/badge/?version=latest
+ :target: https://taskcluster-taskgraph.readthedocs.io/en/latest/?badge=latest
+ :alt: Documentation Status
+
+.. image:: https://img.shields.io/badge/license-MPL%202.0-orange.svg
+ :target: http://mozilla.org/MPL/2.0
+ :alt: License
+
+Taskgraph
+=========
+
+Taskgraph is a Python library to generate graphs of tasks for the `Taskcluster
+CI`_ service. It is the recommended approach for configuring tasks once your
+project outgrows a single `.taskcluster.yml`_ file and is what powers the over
+30,000 tasks and counting that make up Firefox's CI.
+
+For more information and usage instructions, `see the docs`_.
+
+How It Works
+------------
+
+Taskgraph leverages the fact that Taskcluster is a generic task execution
+platform. This means that tasks can be scheduled via its `comprehensive API`_,
+and aren't limited to being triggered in response to supported events.
+
+Taskgraph leverages this execution platform to allow CI systems to scale to any
+size or complexity.
+
+1. A *decision task* is created via Taskcluster's normal `.taskcluster.yml`_
+ file. This task invokes ``taskgraph``.
+2. Taskgraph evaluates a series of yaml based task definitions (similar to
+ those other CI offerings provide).
+3. Taskgraph applies transforms on top of these task definitions. Transforms
+ are Python functions that can programmatically alter or even clone a task
+ definition.
+4. Taskgraph applies some optional optimization logic to remove unnecessary
+ tasks.
+5. Taskgraph submits the resulting *task graph* to Taskcluster via its API.
+
+Taskgraph's combination of declarative task configuration combined with
+programmatic alteration are what allow it to support CI systems of any scale.
+Taskgraph is the library that powers the 30,000+ tasks making up `Firefox's
+CI`_.
+
+.. _Taskcluster CI: https://taskcluster.net/
+.. _comprehensive API: https://docs.taskcluster.net/docs/reference/platform/queue/api
+.. _.taskcluster.yml: https://docs.taskcluster.net/docs/reference/integrations/github/taskcluster-yml-v1
+.. _Firefox's CI: https://treeherder.mozilla.org/jobs?repo=mozilla-central
+.. _see the docs: https://taskcluster-taskgraph.readthedocs.io
+
+Installation
+------------
+
+Taskgraph supports Python 3.8 and up, and can be installed from Pypi:
+
+.. code-block::
+
+ pip install taskcluster-taskgraph
+
+
+Alternatively, the repo can be cloned and installed directly:
+
+.. code-block::
+
+ git clone https://github.com/taskcluster/taskgraph
+ cd taskgraph
+ python setup.py install
+
+In both cases, it's recommended to use a Python `virtual environment`_.
+
+.. _virtual environment: https://docs.python.org/3/tutorial/venv.html
+
+Get Involved
+------------
+
+If you'd like to get involved, please see our `contributing docs`_!
+
+.. _contributing docs: https://github.com/taskcluster/taskgraph/blob/main/CONTRIBUTING.rst
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/RECORD b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/RECORD
new file mode 100644
index 0000000000..c04e803ff2
--- /dev/null
+++ b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/RECORD
@@ -0,0 +1,79 @@
+taskgraph/__init__.py,sha256=hCl3NLzC-cVXlKhuzf0-_0wd0gYmNA3oshXfTaa9DNQ,729
+taskgraph/config.py,sha256=8vntWUrPwGds22mFKYAgcsD4Mr8hoONTv2ssGBcClLw,5108
+taskgraph/create.py,sha256=_zokjSM3ZaO04l2LiMhenE8qXDZVfYvueIIu5hGUhzc,5185
+taskgraph/decision.py,sha256=sG0CIj9OSOdfN65LSt6dRYFWbns9_JraVC5fQU1_7oc,13012
+taskgraph/docker.py,sha256=rk-tAMycHnapFyR2Q-XJXzC2A4uv0i-VykLZfwl-pRo,8417
+taskgraph/filter_tasks.py,sha256=R7tYXiaVPGIkQ6O1c9-QJrKZ59m9pFXCloUlPraVnZU,866
+taskgraph/generator.py,sha256=zrH1zfy-8akksKTSOf6e4FEsdOd5y7-h1Jne_2Jabcc,15703
+taskgraph/graph.py,sha256=bHUsv2pPa2SSaWgBY-ItIj7REPd0o4fFYrwoQbwFKTY,4680
+taskgraph/main.py,sha256=tgfAEcNUJfmADteL24yJR5u7tzU4v3mzmxiogVSCK8Y,29072
+taskgraph/morph.py,sha256=bwkaSGdTZLcK_rhF2st2mCGv9EHN5WdbnDeuZcqp9UA,9208
+taskgraph/parameters.py,sha256=hrwUHHu4PS79w-fQ3qNnLSyjRto1EDlidE8e1GzIy8U,12272
+taskgraph/target_tasks.py,sha256=9_v66bzmQFELPsfIDGITXrqzsmEiLq1EeuJFhycKL0M,3356
+taskgraph/task.py,sha256=tRr7WhJ2qjYXi-77wva17CpfK53m6W_cl-xzks_GGaQ,3240
+taskgraph/taskgraph.py,sha256=Fh5cX8LrgYmkpVP_uhpfRgHSKHfZjO-VGSmnFUjEru0,2434
+taskgraph/actions/__init__.py,sha256=lVP1e0YyELg7-_42MWWDbT0cKv_p53BApVE6vWOiPww,416
+taskgraph/actions/add_new_jobs.py,sha256=c8vGWGXMr4qqW2Axz9rbBrDopabZB3gf3SVFLBZH8ak,1865
+taskgraph/actions/cancel.py,sha256=xrIzlB5KzcnQ4_HultoIcnlxtbQhUi7723g5K2iQoY0,1263
+taskgraph/actions/cancel_all.py,sha256=zNiHtOiSQQxLyNJYtaW0JKPazHXSgZrq1C6o8DGYxG8,1887
+taskgraph/actions/rebuild_cached_tasks.py,sha256=r1QTri2ey30TdEztUgc-nkiHdJPe8Sbn7FvKeR_kt0Y,1115
+taskgraph/actions/registry.py,sha256=hubblOhL3fbWDRtKv7_6HiD0P94hzQrpjdMkj23CGCg,13564
+taskgraph/actions/retrigger.py,sha256=MKkoZDAe0SKIq6fHqwAc1Ici_wIGRd7MxeBNhwoDEGE,9388
+taskgraph/actions/util.py,sha256=gB8MZb8juP1S7EsLHJivr6BBY2bf5IUiIpN7Mq9-kXo,10964
+taskgraph/loader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+taskgraph/loader/default.py,sha256=_bBJG6l04v44Jm5HSIEnVndC05NpNmq5L28QfJHk0wo,1185
+taskgraph/loader/transform.py,sha256=olUBPjxk3eEIg25sduxlcyqhjoig4ts5kPlT_zs6g9g,2147
+taskgraph/optimize/__init__.py,sha256=Oqpq1RW8QzOcu7zaMlNQ3BHT9ws9e_93FWfCqzNcQps,123
+taskgraph/optimize/base.py,sha256=wTViUwVmY9sZvlzSuGwkVrETCo0v2OfyNxFFgzJrDNc,18982
+taskgraph/optimize/strategies.py,sha256=UryFI5TizzEF_2NO8MyuKwqVektHfJeG_t0_zZwxEds,2577
+taskgraph/run-task/fetch-content,sha256=G1aAvZlTg0yWHqxhSxi4RvfxW-KBJ5JwnGtWRqfH_bg,29990
+taskgraph/run-task/hgrc,sha256=BybWLDR89bWi3pE5T05UqmDHs02CbLypE-omLZWU6Uk,896
+taskgraph/run-task/robustcheckout.py,sha256=vPKvHb3fIIJli9ZVZG88XYoa8Sohy2JrpmH6pDgBDHI,30813
+taskgraph/run-task/run-task,sha256=ev64Ud2X3482B05aurUcWD93_sZS1aW2N-eVutRHF5k,45753
+taskgraph/transforms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+taskgraph/transforms/base.py,sha256=z20Yh619srbwuQJWASRtG2_j6NUbWlCujTTCHWLa0GY,5147
+taskgraph/transforms/cached_tasks.py,sha256=Z10VD1kEBVXJvj8qSsNTq2mYpklh0V1EN8OT6QK3v_E,2607
+taskgraph/transforms/chunking.py,sha256=7z9oXiA2dDguYwJPaZYCi-fEzbc--O9avZAFS3vP_kg,2592
+taskgraph/transforms/code_review.py,sha256=tevRFQli3MkzW_0Zhr-hwlVti8hFaXEz94llwhBu_ns,713
+taskgraph/transforms/docker_image.py,sha256=GScS7Lld3YcS57eC30wp3DJM_ATLrmmVfZzINKgC1fM,7546
+taskgraph/transforms/fetch.py,sha256=u1M57LQOi0kHz6FFP1qah3yJh15eXYqQCF_F6r5qjh0,10662
+taskgraph/transforms/from_deps.py,sha256=_cdIefdRkZYWaFJaWpsglivvG8bBGWd4beg7QgNl0Jc,8885
+taskgraph/transforms/notify.py,sha256=0sga-Ls9dhWLAsL0FBjXmVbbduee8LAZp_1pHBQR0iI,6019
+taskgraph/transforms/task.py,sha256=nRzNAxLjA6BsFktZAA9Upqb_pSFNhjoCzKm0QDxvVgM,52586
+taskgraph/transforms/task_context.py,sha256=9v3ke967atAYCtQxIblSFucJA1tum9Q8QpXQeTwNIzU,4278
+taskgraph/transforms/run/__init__.py,sha256=gVJ4eNquKNlygX18OtWTDnl6FFsZlA12bxfvB3kZz14,17761
+taskgraph/transforms/run/common.py,sha256=G3WdMHU5YWUfk1uR6xsxWY7MQKjU9tnqtRDmGttUqt4,5626
+taskgraph/transforms/run/index_search.py,sha256=ABIaX2FFx02o1StZgNAB_ZDXc1lTFO2aUIBH5BuUjtA,1224
+taskgraph/transforms/run/run_task.py,sha256=0GI8syzGtRDT07g_6SXG99JtxDBe09zsW5ltL-aUhYU,8403
+taskgraph/transforms/run/toolchain.py,sha256=KiuBfJ6CShwGYIIljy4i7iYSHFFXF_A_zSvRGUgYboA,6033
+taskgraph/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+taskgraph/util/archive.py,sha256=NIqg2Su5PUqOv4JM60uFixsMsOXN26u5paB1Uh6foSI,4707
+taskgraph/util/attributes.py,sha256=pPOFmwkDQQ-IqfDpVghZ10YI_qXRY4Bi5JP3xr6XVvc,2964
+taskgraph/util/cached_tasks.py,sha256=-AqmOjrkI5PMAlAlQl1wShCrs0HA5lWLBgkxTcFstFM,4150
+taskgraph/util/dependencies.py,sha256=3Qba3zI87JYR5fk5FndGzEVW-5NIzzZrBf9rVYcnLD0,2734
+taskgraph/util/docker.py,sha256=ffQ6KloQNz_kwYemSZEkh4xUMVMeotnnwphWZth1PqQ,8112
+taskgraph/util/hash.py,sha256=U5h6WwC3zs0ooX8odc7AjgPQKKFpDXL7PemoyENPJYo,1644
+taskgraph/util/keyed_by.py,sha256=EMWNRRqYB0AS7A4Y4lthYf2HB7G2ercGFf4hN9zwyaY,3348
+taskgraph/util/memoize.py,sha256=CvCGl-_qft062b3GZC4aHbPfEOPtqR9oOUEqvk9aojQ,294
+taskgraph/util/parameterization.py,sha256=DiPE-4jappGMPljDhhZI52BP7dLBGZHu5EI1cW4aRYg,3392
+taskgraph/util/path.py,sha256=e-JloOQV2-Oua_pe335bv4xWAB07vb82TKpu_zCOl0w,4466
+taskgraph/util/python_path.py,sha256=ed4F5z2mId56LauVczgxm_LGxgQi8XlxlYDgXOPZyII,1576
+taskgraph/util/readonlydict.py,sha256=XzTG-gqGqWVlSkDxSyOL6Ur7Z0ONhIJ9DVLWV3q4q1w,787
+taskgraph/util/schema.py,sha256=HmbbJ_i5uxZZHZSJ8sVWaD-VMhZI4ymx0STNcjO5t2M,8260
+taskgraph/util/set_name.py,sha256=cha9awo2nMQ9jfSEcbyNkZkCq_1Yg_kKJTfvDzabHSc,1134
+taskgraph/util/shell.py,sha256=nf__ly0Ikhj92AiEBCQtvyyckm8UfO_3DSgz0SU-7QA,1321
+taskgraph/util/taskcluster.py,sha256=LScpZknMycOOneIcRMf236rCTMRHHGxFTc9Lh7mRKaI,13057
+taskgraph/util/taskgraph.py,sha256=ecKEvTfmLVvEKLPO_0g34CqVvc0iCzuNMh3064BZNrE,1969
+taskgraph/util/templates.py,sha256=HGTaIKCpAwEzBDHq0cDai1HJjPJrdnHsjJz6N4LVpKI,2139
+taskgraph/util/time.py,sha256=XauJ0DbU0fyFvHLzJLG4ehHv9KaKixxETro89GPC1yk,3350
+taskgraph/util/treeherder.py,sha256=kc8jCy_lYduBxVMYOQzWpmI_6i2bRmkQLKq5DGmbiDI,2721
+taskgraph/util/vcs.py,sha256=FjS82fiTsoQ_ArjTCDOtDGfNdVUp_8zvVKB9SoAG3Rs,18019
+taskgraph/util/verify.py,sha256=htrNX7aXMMDzxymsFVcs0kaO5gErFHd62g9cQsZI_WE,8518
+taskgraph/util/workertypes.py,sha256=1wgM6vLrlgtyv8854anVIs0Bx11kV8JJJaKcOHJc2j0,2498
+taskgraph/util/yaml.py,sha256=-LaIf3RROuaSWckOOGN5Iviu-DHWxIChgHn9a7n6ec4,1059
+taskcluster_taskgraph-8.0.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
+taskcluster_taskgraph-8.0.1.dist-info/METADATA,sha256=qg-m62f4BGLh2jBAr_-OQZhraOSciTrv5EyNY0Wwq8I,4688
+taskcluster_taskgraph-8.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+taskcluster_taskgraph-8.0.1.dist-info/entry_points.txt,sha256=2hxDzE3qq_sHh-J3ROqwpxgQgxO-196phWAQREl2-XA,50
+taskcluster_taskgraph-8.0.1.dist-info/top_level.txt,sha256=3JNeYn_hNiNXC7DrdH_vcv-WYSE7QdgGjdvUYvSjVp0,10
+taskcluster_taskgraph-8.0.1.dist-info/RECORD,,
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/WHEEL b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/WHEEL
new file mode 100644
index 0000000000..bab98d6758
--- /dev/null
+++ b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.43.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/entry_points.txt b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/entry_points.txt
index dec40df69f..dec40df69f 100644
--- a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/entry_points.txt
+++ b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/entry_points.txt
diff --git a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/top_level.txt b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/top_level.txt
index f3840b68ef..f3840b68ef 100644
--- a/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-6.3.0.dist-info/top_level.txt
+++ b/third_party/python/taskcluster_taskgraph/taskcluster_taskgraph-8.0.1.dist-info/top_level.txt
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/__init__.py b/third_party/python/taskcluster_taskgraph/taskgraph/__init__.py
index 81cc763230..0bd794101c 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/__init__.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/__init__.py
@@ -2,7 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-__version__ = "6.3.0"
+__version__ = "8.0.1"
# Maximum number of dependencies a single task can have
# https://docs.taskcluster.net/reference/platform/taskcluster-queue/references/api#createTask
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/actions/add_new_jobs.py b/third_party/python/taskcluster_taskgraph/taskgraph/actions/add_new_jobs.py
index c5e1821546..f635250086 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/actions/add_new_jobs.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/actions/add_new_jobs.py
@@ -40,7 +40,7 @@ from taskgraph.actions.util import (
)
def add_new_jobs_action(parameters, graph_config, input, task_group_id, task_id):
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
- parameters, graph_config
+ parameters, graph_config, task_group_id=task_group_id
)
to_run = []
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel.py b/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel.py
index 03788c6538..33a5394e68 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel.py
@@ -34,9 +34,7 @@ def cancel_action(parameters, graph_config, input, task_group_id, task_id):
# cannot be cancelled at this time, but it's also not running
# anymore, so we can ignore this error.
logger.info(
- 'Task "{}" is past its deadline and cannot be cancelled.'.format(
- task_id
- )
+ f'Task "{task_id}" is past its deadline and cannot be cancelled.'
)
return
raise
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel_all.py b/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel_all.py
index d3e0440839..55453b7624 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel_all.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/actions/cancel_all.py
@@ -43,9 +43,7 @@ def cancel_all_action(parameters, graph_config, input, task_group_id, task_id):
# cannot be cancelled at this time, but it's also not running
# anymore, so we can ignore this error.
logger.info(
- "Task {} is past its deadline and cannot be cancelled.".format(
- task_id
- )
+ f"Task {task_id} is past its deadline and cannot be cancelled."
)
return
raise
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/actions/rebuild_cached_tasks.py b/third_party/python/taskcluster_taskgraph/taskgraph/actions/rebuild_cached_tasks.py
index 2b88e6a698..8ea2e37150 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/actions/rebuild_cached_tasks.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/actions/rebuild_cached_tasks.py
@@ -18,7 +18,7 @@ def rebuild_cached_tasks_action(
parameters, graph_config, input, task_group_id, task_id
):
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
- parameters, graph_config
+ parameters, graph_config, task_group_id=task_group_id
)
cached_tasks = [
label
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/actions/registry.py b/third_party/python/taskcluster_taskgraph/taskgraph/actions/registry.py
index 1e909d30c7..20955bd3f2 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/actions/registry.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/actions/registry.py
@@ -154,9 +154,7 @@ def register_callback_action(
], "register_callback_action must be used as decorator"
if not cb_name:
cb_name = name
- assert cb_name not in callbacks, "callback name {} is not unique".format(
- cb_name
- )
+ assert cb_name not in callbacks, f"callback name {cb_name} is not unique"
def action_builder(parameters, graph_config, decision_task_id):
if not available(parameters):
@@ -165,11 +163,11 @@ def register_callback_action(
actionPerm = "generic" if generic else cb_name
# gather up the common decision-task-supplied data for this action
- repo_param = "head_repository"
repository = {
- "url": parameters[repo_param],
+ "url": parameters["head_repository"],
"project": parameters["project"],
"level": parameters["level"],
+ "base_url": parameters["base_repository"],
}
revision = parameters["head_rev"]
@@ -181,6 +179,9 @@ def register_callback_action(
branch = parameters.get("head_ref")
if branch:
push["branch"] = branch
+ base_branch = parameters.get("base_ref")
+ if base_branch and branch != base_branch:
+ push["base_branch"] = base_branch
action = {
"name": name,
@@ -215,13 +216,16 @@ def register_callback_action(
if "/" in actionPerm:
raise Exception("`/` is not allowed in action names; use `-`")
+ if parameters["tasks_for"].startswith("github-pull-request"):
+ hookId = f"in-tree-pr-action-{level}-{actionPerm}/{tcyml_hash}"
+ else:
+ hookId = f"in-tree-action-{level}-{actionPerm}/{tcyml_hash}"
+
rv.update(
{
"kind": "hook",
"hookGroupId": f"project-{trustDomain}",
- "hookId": "in-tree-action-{}-{}/{}".format(
- level, actionPerm, tcyml_hash
- ),
+ "hookId": hookId,
"hookPayload": {
# provide the decision-task parameters as context for triggerHook
"decision": {
@@ -297,16 +301,20 @@ def sanity_check_task_scope(callback, parameters, graph_config):
actionPerm = "generic" if action.generic else action.cb_name
- repo_param = "head_repository"
- raw_url = parameters[repo_param]
+ raw_url = parameters["base_repository"]
parsed_url = parse(raw_url)
- expected_scope = f"assume:{parsed_url.taskcluster_role_prefix}:action:{actionPerm}"
+ action_scope = f"assume:{parsed_url.taskcluster_role_prefix}:action:{actionPerm}"
+ pr_action_scope = (
+ f"assume:{parsed_url.taskcluster_role_prefix}:pr-action:{actionPerm}"
+ )
# the scope should appear literally; no need for a satisfaction check. The use of
# get_current_scopes here calls the auth service through the Taskcluster Proxy, giving
# the precise scopes available to this task.
- if expected_scope not in taskcluster.get_current_scopes():
- raise ValueError(f"Expected task scope {expected_scope} for this action")
+ if not set((action_scope, pr_action_scope)) & set(taskcluster.get_current_scopes()):
+ raise ValueError(
+ f"Expected task scope {action_scope} or {pr_action_scope} for this action"
+ )
def trigger_action_callback(
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/actions/retrigger.py b/third_party/python/taskcluster_taskgraph/taskgraph/actions/retrigger.py
index fd488b35fc..6c6091a47a 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/actions/retrigger.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/actions/retrigger.py
@@ -33,9 +33,7 @@ def _should_retrigger(task_graph, label):
"""
if label not in task_graph:
logger.info(
- "Task {} not in full taskgraph, assuming task should not be retriggered.".format(
- label
- )
+ f"Task {label} not in full taskgraph, assuming task should not be retriggered."
)
return False
return task_graph[label].attributes.get("retrigger", False)
@@ -67,7 +65,9 @@ def retrigger_decision_action(parameters, graph_config, input, task_group_id, ta
# absolute timestamps relative to the current time.
task = taskcluster.get_task_definition(task_id)
task = relativize_datestamps(task)
- create_task_from_def(slugid(), task, parameters["level"])
+ create_task_from_def(
+ slugid(), task, parameters["level"], graph_config["trust-domain"]
+ )
@register_callback_action(
@@ -144,7 +144,7 @@ def retrigger_decision_action(parameters, graph_config, input, task_group_id, ta
)
def retrigger_action(parameters, graph_config, input, task_group_id, task_id):
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
- parameters, graph_config
+ parameters, graph_config, task_group_id=task_group_id
)
task = taskcluster.get_task_definition(task_id)
@@ -155,8 +155,8 @@ def retrigger_action(parameters, graph_config, input, task_group_id, task_id):
if not input.get("force", None) and not _should_retrigger(full_task_graph, label):
logger.info(
- "Not retriggering task {}, task should not be retrigged "
- "and force not specified.".format(label)
+ f"Not retriggering task {label}, task should not be retrigged "
+ "and force not specified."
)
sys.exit(1)
@@ -201,14 +201,12 @@ def rerun_action(parameters, graph_config, input, task_group_id, task_id):
task = taskcluster.get_task_definition(task_id)
parameters = dict(parameters)
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
- parameters, graph_config
+ parameters, graph_config, task_group_id=task_group_id
)
label = task["metadata"]["name"]
if task_id not in label_to_taskid.values():
logger.error(
- "Refusing to rerun {}: taskId {} not in decision task {} label_to_taskid!".format(
- label, task_id, decision_task_id
- )
+ f"Refusing to rerun {label}: taskId {task_id} not in decision task {decision_task_id} label_to_taskid!"
)
_rerun_task(task_id, label)
@@ -218,9 +216,7 @@ def _rerun_task(task_id, label):
state = taskcluster.state_task(task_id)
if state not in RERUN_STATES:
logger.warning(
- "No need to rerun {}: state '{}' not in {}!".format(
- label, state, RERUN_STATES
- )
+ f"No need to rerun {label}: state '{state}' not in {RERUN_STATES}!"
)
return
taskcluster.rerun_task(task_id)
@@ -261,7 +257,7 @@ def _rerun_task(task_id, label):
)
def retrigger_multiple(parameters, graph_config, input, task_group_id, task_id):
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
- parameters, graph_config
+ parameters, graph_config, task_group_id=task_group_id
)
suffixes = []
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/actions/util.py b/third_party/python/taskcluster_taskgraph/taskgraph/actions/util.py
index cf81029da2..41e3b035de 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/actions/util.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/actions/util.py
@@ -32,8 +32,15 @@ def get_parameters(decision_task_id):
return get_artifact(decision_task_id, "public/parameters.yml")
-def fetch_graph_and_labels(parameters, graph_config):
- decision_task_id = find_decision_task(parameters, graph_config)
+def fetch_graph_and_labels(parameters, graph_config, task_group_id=None):
+ try:
+ # Look up the decision_task id in the index
+ decision_task_id = find_decision_task(parameters, graph_config)
+ except KeyError:
+ if not task_group_id:
+ raise
+ # Not found (e.g. from github-pull-request), fall back to the task group id.
+ decision_task_id = task_group_id
# First grab the graph and labels generated during the initial decision task
full_task_graph = get_artifact(decision_task_id, "public/full-task-graph.json")
@@ -90,7 +97,7 @@ def fetch_graph_and_labels(parameters, graph_config):
return (decision_task_id, full_task_graph, label_to_taskid)
-def create_task_from_def(task_id, task_def, level):
+def create_task_from_def(task_id, task_def, level, trust_domain):
"""Create a new task from a definition rather than from a label
that is already in the full-task-graph. The task definition will
have {relative-datestamp': '..'} rendered just like in a decision task.
@@ -98,7 +105,7 @@ def create_task_from_def(task_id, task_def, level):
It is useful if you want to "edit" the full_task_graph and then hand
it to this function. No dependencies will be scheduled. You must handle
this yourself. Seeing how create_tasks handles it might prove helpful."""
- task_def["schedulerId"] = f"gecko-level-{level}"
+ task_def["schedulerId"] = f"{trust_domain}-level-{level}"
label = task_def["metadata"]["name"]
session = get_session()
create.create_task(session, task_id, label, task_def)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/config.py b/third_party/python/taskcluster_taskgraph/taskgraph/config.py
index 7ea7dc7b33..ac384eab86 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/config.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/config.py
@@ -40,6 +40,11 @@ graph_config_schema = Schema(
description="Default 'deadline' for tasks, in relative date format. "
"Eg: '1 week'",
): optionally_keyed_by("project", str),
+ Optional(
+ "task-expires-after",
+ description="Default 'expires-after' for level 1 tasks, in relative date format. "
+ "Eg: '90 days'",
+ ): str,
Required("workers"): {
Required("aliases"): {
str: {
@@ -62,6 +67,10 @@ graph_config_schema = Schema(
"Defaults to `trust-domain`.",
): str,
Optional(
+ "cache-pull-requests",
+ description="Should tasks from pull requests populate the cache",
+ ): bool,
+ Optional(
"index-path-regexes",
description="Regular expressions matching index paths to be summarized.",
): [str],
@@ -102,28 +111,27 @@ class GraphConfig:
Add the project's taskgraph directory to the python path, and register
any extensions present.
"""
- modify_path = os.path.dirname(self.root_dir)
if GraphConfig._PATH_MODIFIED:
- if GraphConfig._PATH_MODIFIED == modify_path:
+ if GraphConfig._PATH_MODIFIED == self.root_dir:
# Already modified path with the same root_dir.
# We currently need to do this to enable actions to call
# taskgraph_decision, e.g. relpro.
return
raise Exception("Can't register multiple directories on python path.")
- GraphConfig._PATH_MODIFIED = modify_path
- sys.path.insert(0, modify_path)
+ GraphConfig._PATH_MODIFIED = self.root_dir
+ sys.path.insert(0, self.root_dir)
register_path = self["taskgraph"].get("register")
if register_path:
find_object(register_path)(self)
@property
def vcs_root(self):
- if path.split(self.root_dir)[-2:] != ["taskcluster", "ci"]:
+ if path.split(self.root_dir)[-1:] != ["taskcluster"]:
raise Exception(
"Not guessing path to vcs root. "
"Graph config in non-standard location."
)
- return os.path.dirname(os.path.dirname(self.root_dir))
+ return os.path.dirname(self.root_dir)
@property
def taskcluster_yml(self):
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/create.py b/third_party/python/taskcluster_taskgraph/taskgraph/create.py
index deb1ac5348..e8baabb8a8 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/create.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/create.py
@@ -104,7 +104,7 @@ def create_tasks(graph_config, taskgraph, label_to_taskid, params, decision_task
def create_task(session, task_id, label, task_def):
# create the task using 'http://taskcluster/queue', which is proxied to the queue service
- # with credentials appropriate to this job.
+ # with credentials appropriate to this task.
# Resolve timestamps
now = current_json_time(datetime_format=True)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/decision.py b/third_party/python/taskcluster_taskgraph/taskgraph/decision.py
index ed412f4473..d9eb9f3e90 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/decision.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/decision.py
@@ -46,21 +46,21 @@ try_task_config_schema_v2 = Schema(
)
-def full_task_graph_to_runnable_jobs(full_task_json):
- runnable_jobs = {}
+def full_task_graph_to_runnable_tasks(full_task_json):
+ runnable_tasks = {}
for label, node in full_task_json.items():
if not ("extra" in node["task"] and "treeherder" in node["task"]["extra"]):
continue
th = node["task"]["extra"]["treeherder"]
- runnable_jobs[label] = {"symbol": th["symbol"]}
+ runnable_tasks[label] = {"symbol": th["symbol"]}
for i in ("groupName", "groupSymbol", "collection"):
if i in th:
- runnable_jobs[label][i] = th[i]
+ runnable_tasks[label][i] = th[i]
if th.get("machine", {}).get("platform"):
- runnable_jobs[label]["platform"] = th["machine"]["platform"]
- return runnable_jobs
+ runnable_tasks[label]["platform"] = th["machine"]["platform"]
+ return runnable_tasks
def taskgraph_decision(options, parameters=None):
@@ -104,7 +104,7 @@ def taskgraph_decision(options, parameters=None):
# write out the public/runnable-jobs.json file
write_artifact(
- "runnable-jobs.json", full_task_graph_to_runnable_jobs(full_task_json)
+ "runnable-jobs.json", full_task_graph_to_runnable_tasks(full_task_json)
)
# this is just a test to check whether the from_json() function is working
@@ -185,6 +185,9 @@ def get_decision_parameters(graph_config, options):
# Define default filter list, as most configurations shouldn't need
# custom filters.
+ parameters["files_changed"] = repo.get_changed_files(
+ rev=parameters["head_rev"], base_rev=parameters["base_rev"]
+ )
parameters["filters"] = [
"target_tasks_method",
]
@@ -214,9 +217,9 @@ def get_decision_parameters(graph_config, options):
parameters.update(PER_PROJECT_PARAMETERS[project])
except KeyError:
logger.warning(
- "using default project parameters; add {} to "
- "PER_PROJECT_PARAMETERS in {} to customize behavior "
- "for this project".format(project, __file__)
+ f"using default project parameters; add {project} to "
+ f"PER_PROJECT_PARAMETERS in {__file__} to customize behavior "
+ "for this project"
)
parameters.update(PER_PROJECT_PARAMETERS["default"])
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/docker.py b/third_party/python/taskcluster_taskgraph/taskgraph/docker.py
index 23897cbbee..9f849525fc 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/docker.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/docker.py
@@ -18,6 +18,22 @@ except ImportError as e:
from taskgraph.util import docker
from taskgraph.util.taskcluster import get_artifact_url, get_session
+DEPLOY_WARNING = """
+*****************************************************************
+WARNING: Image is not suitable for deploying/pushing.
+
+To automatically tag the image the following files are required:
+- {image_dir}/REGISTRY
+- {image_dir}/VERSION
+
+The REGISTRY file contains the Docker registry hosting the image.
+A default REGISTRY file may also be defined in the parent docker
+directory.
+
+The VERSION file contains the version of the image.
+*****************************************************************
+"""
+
def get_image_digest(image_name):
from taskgraph.generator import load_tasks_for_kind
@@ -34,7 +50,7 @@ def get_image_digest(image_name):
def load_image_by_name(image_name, tag=None):
from taskgraph.generator import load_tasks_for_kind
- from taskgraph.optimize import IndexSearch
+ from taskgraph.optimize.strategies import IndexSearch
from taskgraph.parameters import Parameters
params = Parameters(
@@ -43,8 +59,9 @@ def load_image_by_name(image_name, tag=None):
)
tasks = load_tasks_for_kind(params, "docker-image")
task = tasks[f"build-docker-image-{image_name}"]
+ deadline = None
task_id = IndexSearch().should_replace_task(
- task, {}, task.optimization.get("index-search", [])
+ task, {}, deadline, task.optimization.get("index-search", [])
)
if task_id in (True, False):
@@ -52,8 +69,10 @@ def load_image_by_name(image_name, tag=None):
"Could not find artifacts for a docker image "
"named `{image_name}`. Local commits and other changes "
"in your checkout may cause this error. Try "
- "updating to a fresh checkout of mozilla-central "
- "to download image.".format(image_name=image_name)
+ "updating to a fresh checkout of {project} "
+ "to download image.".format(
+ image_name=image_name, project=params["project"]
+ )
)
return False
@@ -102,19 +121,18 @@ def build_image(name, tag, args=None):
buf = BytesIO()
docker.stream_context_tar(".", image_dir, buf, "", args)
- subprocess.run(
- ["docker", "image", "build", "--no-cache", "-t", tag, "-"], input=buf.getvalue()
- )
+ cmdargs = ["docker", "image", "build", "--no-cache", "-"]
+ if tag:
+ cmdargs.insert(-1, f"-t={tag}")
+ subprocess.run(cmdargs, input=buf.getvalue())
- print(f"Successfully built {name} and tagged with {tag}")
+ msg = f"Successfully built {name}"
+ if tag:
+ msg += f" and tagged with {tag}"
+ print(msg)
- if tag.endswith(":latest"):
- print("*" * 50)
- print("WARNING: no VERSION file found in image directory.")
- print("Image is not suitable for deploying/pushing.")
- print("Create an image suitable for deploying/pushing by creating")
- print("a VERSION file in the image directory.")
- print("*" * 50)
+ if not tag or tag.endswith(":latest"):
+ print(DEPLOY_WARNING.format(image_dir=os.path.relpath(image_dir), image=name))
def load_image(url, imageName=None, imageTag=None):
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/files_changed.py b/third_party/python/taskcluster_taskgraph/taskgraph/files_changed.py
deleted file mode 100644
index 6be6e5eeee..0000000000
--- a/third_party/python/taskcluster_taskgraph/taskgraph/files_changed.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-"""
-Support for optimizing tasks based on the set of files that have changed.
-"""
-
-
-import logging
-import os
-
-import requests
-from redo import retry
-
-from .util.memoize import memoize
-from .util.path import match as match_path
-from .util.vcs import get_repository
-
-logger = logging.getLogger(__name__)
-
-
-@memoize
-def get_changed_files(head_repository_url, head_rev, base_rev=None):
- """
- Get the set of files changed between revisions.
- Responses are cached, so multiple calls with the same arguments are OK.
- """
- repo_path = os.getcwd()
- repository = get_repository(repo_path)
-
- if repository.tool == "hg":
- # TODO Use VCS version once tested enough
- return _get_changed_files_json_automationrelevance(
- head_repository_url, head_rev
- )
-
- return repository.get_changed_files(rev=head_rev, base_rev=base_rev)
-
-
-def _get_changed_files_json_automationrelevance(head_repository_url, head_rev):
- """
- Get the set of files changed in the push headed by the given revision.
- """
- url = "{}/json-automationrelevance/{}".format(
- head_repository_url.rstrip("/"), head_rev
- )
- logger.debug("Querying version control for metadata: %s", url)
-
- def get_automationrelevance():
- response = requests.get(url, timeout=30)
- return response.json()
-
- contents = retry(get_automationrelevance, attempts=10, sleeptime=10)
-
- logger.debug(
- "{} commits influencing task scheduling:".format(len(contents["changesets"]))
- )
- changed_files = set()
- for c in contents["changesets"]:
- desc = "" # Support empty desc
- if c["desc"]:
- desc = c["desc"].splitlines()[0].encode("ascii", "ignore")
- logger.debug(" {cset} {desc}".format(cset=c["node"][0:12], desc=desc))
- changed_files |= set(c["files"])
-
- return changed_files
-
-
-def check(params, file_patterns):
- """Determine whether any of the files changed between 2 revisions
- match any of the given file patterns."""
-
- head_repository_url = params.get("head_repository")
- head_rev = params.get("head_rev")
- if not head_repository_url or not head_rev:
- logger.warning(
- "Missing `head_repository` or `head_rev` parameters; "
- "assuming all files have changed"
- )
- return True
-
- base_rev = params.get("base_rev")
- changed_files = get_changed_files(head_repository_url, head_rev, base_rev)
-
- for pattern in file_patterns:
- for path in changed_files:
- if match_path(path, pattern):
- return True
-
- return False
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/generator.py b/third_party/python/taskcluster_taskgraph/taskgraph/generator.py
index 4ed2a41520..d649b91706 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/generator.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/generator.py
@@ -91,7 +91,7 @@ class Kind:
@classmethod
def load(cls, root_dir, graph_config, kind_name):
- path = os.path.join(root_dir, kind_name)
+ path = os.path.join(root_dir, "kinds", kind_name)
kind_yml = os.path.join(path, "kind.yml")
if not os.path.exists(kind_yml):
raise KindNotFound(kind_yml)
@@ -125,13 +125,13 @@ class TaskGraphGenerator:
write_artifacts=False,
):
"""
- @param root_dir: root directory, with subdirectories for each kind
+ @param root_dir: root directory containing the Taskgraph config.yml file
@param parameters: parameters for this task-graph generation, or callable
taking a `GraphConfig` and returning parameters
@type parameters: Union[Parameters, Callable[[GraphConfig], Parameters]]
"""
if root_dir is None:
- root_dir = "taskcluster/ci"
+ root_dir = "taskcluster"
self.root_dir = root_dir
self._parameters = parameters
self._decision_task_id = decision_task_id
@@ -243,7 +243,7 @@ class TaskGraphGenerator:
yield kind
queue.extend(kind.config.get("kind-dependencies", []))
else:
- for kind_name in os.listdir(self.root_dir):
+ for kind_name in os.listdir(os.path.join(self.root_dir, "kinds")):
try:
yield Kind.load(self.root_dir, graph_config, kind_name)
except KindNotFound:
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/loader/default.py b/third_party/python/taskcluster_taskgraph/taskgraph/loader/default.py
index 5b2c258917..f060a1d92d 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/loader/default.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/loader/default.py
@@ -11,7 +11,7 @@ logger = logging.getLogger(__name__)
DEFAULT_TRANSFORMS = [
- "taskgraph.transforms.job:transforms",
+ "taskgraph.transforms.run:transforms",
"taskgraph.transforms.task:transforms",
]
@@ -20,7 +20,7 @@ def loader(kind, path, config, params, loaded_tasks):
"""
This default loader builds on the `transform` loader by providing sensible
default transforms that the majority of simple tasks will need.
- Specifically, `job` and `task` transforms will be appended to the end of the
+ Specifically, `run` and `task` transforms will be appended to the end of the
list of transforms in the kind being loaded.
"""
transform_refs = config.setdefault("transforms", [])
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/main.py b/third_party/python/taskcluster_taskgraph/taskgraph/main.py
index 88a4e2539b..e68cd5a787 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/main.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/main.py
@@ -18,6 +18,7 @@ from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path
from textwrap import dedent
from typing import Any, List
+from urllib.parse import urlparse
import appdirs
import yaml
@@ -95,7 +96,7 @@ def get_filtered_taskgraph(taskgraph, tasksregex, exclude_keys):
for key in exclude_keys:
obj = task
attrs = key.split(".")
- while attrs[0] in obj:
+ while obj and attrs[0] in obj:
if len(attrs) == 1:
del obj[attrs[0]]
break
@@ -120,7 +121,7 @@ def get_taskgraph_generator(root, parameters):
return TaskGraphGenerator(root_dir=root, parameters=parameters)
-def format_taskgraph(options, parameters, logfile=None):
+def format_taskgraph(options, parameters, overrides, logfile=None):
import taskgraph
from taskgraph.parameters import parameters_loader
@@ -138,7 +139,7 @@ def format_taskgraph(options, parameters, logfile=None):
if isinstance(parameters, str):
parameters = parameters_loader(
parameters,
- overrides={"target-kinds": options.get("target_kinds")},
+ overrides=overrides,
strict=False,
)
@@ -172,7 +173,7 @@ def dump_output(out, path=None, params_spec=None):
print(out + "\n", file=fh)
-def generate_taskgraph(options, parameters, logdir):
+def generate_taskgraph(options, parameters, overrides, logdir):
from taskgraph.parameters import Parameters
def logfile(spec):
@@ -188,14 +189,16 @@ def generate_taskgraph(options, parameters, logdir):
# tracebacks a little more readable and avoids additional process overhead.
if len(parameters) == 1:
spec = parameters[0]
- out = format_taskgraph(options, spec, logfile(spec))
+ out = format_taskgraph(options, spec, overrides, logfile(spec))
dump_output(out, options["output_file"])
return 0
futures = {}
with ProcessPoolExecutor(max_workers=options["max_workers"]) as executor:
for spec in parameters:
- f = executor.submit(format_taskgraph, options, spec, logfile(spec))
+ f = executor.submit(
+ format_taskgraph, options, spec, overrides, logfile(spec)
+ )
futures[f] = spec
returncode = 0
@@ -293,6 +296,15 @@ def generate_taskgraph(options, parameters, logdir):
"specified).",
)
@argument(
+ "--force-local-files-changed",
+ default=False,
+ action="store_true",
+ help="Compute the 'files-changed' parameter from local version control, "
+ "even when explicitly using a parameter set that already has it defined. "
+ "Note that this is already the default behaviour when no parameters are "
+ "specified.",
+)
+@argument(
"--no-optimize",
dest="optimize",
action="store_false",
@@ -366,9 +378,11 @@ def show_taskgraph(options):
diffdir = None
output_file = options["output_file"]
- if options["diff"]:
+ if options["diff"] or options["force_local_files_changed"]:
repo = get_repository(os.getcwd())
+ if options["diff"]:
+ assert repo is not None
if not repo.working_directory_clean():
print(
"abort: can't diff taskgraph with dirty working directory",
@@ -392,15 +406,22 @@ def show_taskgraph(options):
)
print(f"Generating {options['graph_attr']} @ {cur_rev}", file=sys.stderr)
+ overrides = {
+ "target-kinds": options.get("target_kinds"),
+ }
parameters: List[Any[str, Parameters]] = options.pop("parameters")
if not parameters:
- overrides = {
- "target-kinds": options.get("target_kinds"),
- }
parameters = [
parameters_loader(None, strict=False, overrides=overrides)
] # will use default values
+ # This is the default behaviour anyway, so no need to re-compute.
+ options["force_local_files_changed"] = False
+
+ elif options["force_local_files_changed"]:
+ assert repo is not None
+ overrides["files-changed"] = sorted(repo.get_changed_files("AM"))
+
for param in parameters[:]:
if isinstance(param, str) and os.path.isdir(param):
parameters.remove(param)
@@ -426,7 +447,7 @@ def show_taskgraph(options):
# to setup its `mach` based logging.
setup_logging()
- ret = generate_taskgraph(options, parameters, logdir)
+ ret = generate_taskgraph(options, parameters, overrides, logdir)
if options["diff"]:
assert diffdir is not None
@@ -450,7 +471,7 @@ def show_taskgraph(options):
diffdir, f"{options['graph_attr']}_{base_rev_file}"
)
print(f"Generating {options['graph_attr']} @ {base_rev}", file=sys.stderr)
- ret |= generate_taskgraph(options, parameters, logdir)
+ ret |= generate_taskgraph(options, parameters, overrides, logdir)
finally:
repo.update(cur_rev)
@@ -463,6 +484,8 @@ def show_taskgraph(options):
f"--label={options['graph_attr']}@{cur_rev}",
]
+ non_fatal_failures = []
+
for spec in parameters:
base_path = os.path.join(
diffdir, f"{options['graph_attr']}_{base_rev_file}"
@@ -475,7 +498,20 @@ def show_taskgraph(options):
base_path += f"_{params_name}"
cur_path += f"_{params_name}"
+ # If the base or cur files are missing it means that generation
+ # failed. If one of them failed but not the other, the failure is
+ # likely due to the patch making changes to taskgraph in modules
+ # that don't get reloaded (safe to ignore). If both generations
+ # failed, there's likely a real issue.
+ base_missing = not os.path.isfile(base_path)
+ cur_missing = not os.path.isfile(cur_path)
+ if base_missing != cur_missing: # != is equivalent to XOR for booleans
+ non_fatal_failures.append(os.path.basename(base_path))
+ continue
+
try:
+ # If the output file(s) are missing, this command will raise
+ # CalledProcessError with a returncode > 1.
proc = subprocess.run(
diffcmd + [base_path, cur_path],
capture_output=True,
@@ -500,6 +536,16 @@ def show_taskgraph(options):
params_spec=spec if len(parameters) > 1 else None,
)
+ if non_fatal_failures:
+ failstr = "\n ".join(sorted(non_fatal_failures))
+ print(
+ "WARNING: Diff skipped for the following generation{s} "
+ "due to failures:\n {failstr}".format(
+ s="s" if len(non_fatal_failures) > 1 else "", failstr=failstr
+ ),
+ file=sys.stderr,
+ )
+
if options["format"] != "json":
print(
"If you were expecting differences in task bodies "
@@ -661,7 +707,7 @@ def decision(options):
@argument(
"--root",
"-r",
- default="taskcluster/ci",
+ default="taskcluster",
help="root of the taskgraph definition relative to topsrcdir",
)
def action_callback(options):
@@ -697,7 +743,7 @@ def action_callback(options):
@argument(
"--root",
"-r",
- default="taskcluster/ci",
+ default="taskcluster",
help="root of the taskgraph definition relative to topsrcdir",
)
@argument(
@@ -835,6 +881,10 @@ def init_taskgraph(options):
)
return 1
+ context["repo_name"] = urlparse(repo_url).path.rsplit("/", 1)[-1]
+ if context["repo_name"].endswith(".git"):
+ context["repo_name"] = context["repo_name"][: -len(".git")]
+
# Generate the project.
cookiecutter(
options["template"],
@@ -867,6 +917,11 @@ def setup_logging():
def main(args=sys.argv[1:]):
setup_logging()
parser = create_parser()
+
+ if not args:
+ parser.print_help()
+ sys.exit(1)
+
args = parser.parse_args(args)
try:
return args.command(vars(args))
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/morph.py b/third_party/python/taskcluster_taskgraph/taskgraph/morph.py
index bfa1560270..e4bb268ab8 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/morph.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/morph.py
@@ -38,6 +38,7 @@ registered_morphs = []
def register_morph(func):
registered_morphs.append(func)
+ return func
def amend_taskgraph(taskgraph, label_to_taskid, to_add):
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/optimize/base.py b/third_party/python/taskcluster_taskgraph/taskgraph/optimize/base.py
index 367b94e1de..e5477d35b7 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/optimize/base.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/optimize/base.py
@@ -271,14 +271,19 @@ def replace_tasks(
dependencies_of = target_task_graph.graph.links_dict()
for label in target_task_graph.graph.visit_postorder():
+ logger.debug(f"replace_tasks: {label}")
# if we're not allowed to optimize, that's easy..
if label in do_not_optimize:
+ logger.debug(f"replace_tasks: {label} is in do_not_optimize")
continue
# if this task depends on un-replaced, un-removed tasks, do not replace
if any(
l not in replaced and l not in removed_tasks for l in dependencies_of[label]
):
+ logger.debug(
+ f"replace_tasks: {label} depends on an unreplaced or unremoved task"
+ )
continue
# if the task already exists, that's an easy replacement
@@ -287,6 +292,7 @@ def replace_tasks(
label_to_taskid[label] = repl
replaced.add(label)
opt_counts["existing_tasks"] += 1
+ logger.debug(f"replace_tasks: {label} replaced from existing_tasks")
continue
# call the optimization strategy
@@ -304,14 +310,20 @@ def replace_tasks(
repl = opt.should_replace_task(task, params, deadline, arg)
if repl:
if repl is True:
+ logger.debug(f"replace_tasks: {label} removed by optimization strategy")
# True means remove this task; get_subgraph will catch any
# problems with removed tasks being depended on
removed_tasks.add(label)
else:
+ logger.debug(
+ f"replace_tasks: {label} replaced by optimization strategy"
+ )
label_to_taskid[label] = repl
replaced.add(label)
opt_counts[opt_by] += 1
continue
+ else:
+ logger.debug(f"replace_tasks: {label} kept by optimization strategy")
_log_optimization("replaced", opt_counts)
return replaced
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/optimize/strategies.py b/third_party/python/taskcluster_taskgraph/taskgraph/optimize/strategies.py
index 973b550632..5baecfe645 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/optimize/strategies.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/optimize/strategies.py
@@ -1,8 +1,8 @@
import logging
from datetime import datetime
-from taskgraph import files_changed
from taskgraph.optimize.base import OptimizationStrategy, register_strategy
+from taskgraph.util.path import match as match_path
from taskgraph.util.taskcluster import find_task_id, status_task
logger = logging.getLogger(__name__)
@@ -48,17 +48,23 @@ class IndexSearch(OptimizationStrategy):
@register_strategy("skip-unless-changed")
class SkipUnlessChanged(OptimizationStrategy):
+
+ def check(self, files_changed, patterns):
+ for pattern in patterns:
+ for path in files_changed:
+ if match_path(path, pattern):
+ return True
+ return False
+
def should_remove_task(self, task, params, file_patterns):
# pushlog_id == -1 - this is the case when run from a cron.yml job or on a git repository
if params.get("repository_type") == "hg" and params.get("pushlog_id") == -1:
return False
- changed = files_changed.check(params, file_patterns)
+ changed = self.check(params["files_changed"], file_patterns)
if not changed:
logger.debug(
- 'no files found matching a pattern in `skip-unless-changed` for "{}"'.format(
- task.label
- )
+ f'no files found matching a pattern in `skip-unless-changed` for "{task.label}"'
)
return True
return False
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/parameters.py b/third_party/python/taskcluster_taskgraph/taskgraph/parameters.py
index 48571d97ad..c69b201e34 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/parameters.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/parameters.py
@@ -40,6 +40,7 @@ base_schema = Schema(
Required("do_not_optimize"): [str],
Required("enable_always_target"): Any(bool, [str]),
Required("existing_tasks"): {str: str},
+ Required("files_changed"): [str],
Required("filters"): [str],
Required("head_ref"): str,
Required("head_repository"): str,
@@ -86,6 +87,7 @@ def _get_defaults(repo_root=None):
# Use fake values if no repo is detected.
repo = Mock(branch="", head_rev="", tool="git")
repo.get_url.return_value = ""
+ repo.get_changed_files.return_value = []
try:
repo_url = repo.get_url()
@@ -108,6 +110,7 @@ def _get_defaults(repo_root=None):
"do_not_optimize": [],
"enable_always_target": True,
"existing_tasks": {},
+ "files_changed": repo.get_changed_files("AM"),
"filters": ["target_tasks_method"],
"head_ref": repo.branch or repo.head_rev,
"head_repository": repo_url,
@@ -284,7 +287,7 @@ class Parameters(ReadOnlyDict):
else:
raise ParameterMismatch(
"Don't know how to determine file URL for non-github"
- "repo: {}".format(repo)
+ f"repo: {repo}"
)
else:
raise RuntimeError(
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/run-task/run-task b/third_party/python/taskcluster_taskgraph/taskgraph/run-task/run-task
index 267b5283ea..f3a343de33 100755
--- a/third_party/python/taskcluster_taskgraph/taskgraph/run-task/run-task
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/run-task/run-task
@@ -1,4 +1,4 @@
-#!/usr/bin/python3 -u
+#!/usr/bin/env -S python3 -u
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -624,6 +624,11 @@ def git_checkout(
"Must specify both ssh_key_file and ssh_known_hosts_file, if either are specified",
)
+ # Bypass Git's "safe directory" feature as the destination could be
+ # coming from a cache and therefore cloned by a different user.
+ args = ["git", "config", "--global", "--add", "safe.directory", Path(destination_path).as_posix()]
+ retry_required_command(b"vcs", args, extra_env=env)
+
if not os.path.exists(destination_path):
# Repository doesn't already exist, needs to be cloned
args = [
@@ -782,9 +787,7 @@ def hg_checkout(
branch: Optional[str],
revision: Optional[str],
):
- if IS_MACOSX:
- hg_bin = "/tools/python27-mercurial/bin/hg"
- elif IS_POSIX:
+ if IS_MACOSX or IS_POSIX:
hg_bin = "hg"
elif IS_WINDOWS:
# This is where OCC installs it in the AMIs.
@@ -1007,7 +1010,8 @@ def install_pip_requirements(repositories):
if not requirements:
return
- cmd = [sys.executable, "-mpip", "install"]
+ # TODO: Stop using system Python (#381)
+ cmd = [sys.executable, "-mpip", "install", "--break-system-packages"]
if os.environ.get("PIP_DISABLE_REQUIRE_HASHES") != "1":
cmd.append("--require-hashes")
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/target_tasks.py b/third_party/python/taskcluster_taskgraph/taskgraph/target_tasks.py
index 1119a1c960..7f44b6ab60 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/target_tasks.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/target_tasks.py
@@ -14,7 +14,7 @@ _target_task_methods = {}
_GIT_REFS_HEADS_PREFIX = "refs/heads/"
-def _target_task(name):
+def register_target_task(name):
def wrap(func):
_target_task_methods[name] = func
return func
@@ -81,7 +81,7 @@ def standard_filter(task, parameters):
)
-@_target_task("default")
+@register_target_task("default")
def target_tasks_default(full_task_graph, parameters, graph_config):
"""Target the tasks which have indicated they should be run on this project
via the `run_on_projects` attributes."""
@@ -90,7 +90,7 @@ def target_tasks_default(full_task_graph, parameters, graph_config):
]
-@_target_task("codereview")
+@register_target_task("codereview")
def target_tasks_codereview(full_task_graph, parameters, graph_config):
"""Target the tasks which have indicated they should be run on this project
via the `run_on_projects` attributes."""
@@ -101,7 +101,7 @@ def target_tasks_codereview(full_task_graph, parameters, graph_config):
]
-@_target_task("nothing")
+@register_target_task("nothing")
def target_tasks_nothing(full_task_graph, parameters, graph_config):
"""Select nothing, for DONTBUILD pushes"""
return []
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/__init__.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/__init__.py
index 4fa7b5fc0c..e69de29bb2 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/__init__.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/__init__.py
@@ -1,3 +0,0 @@
-from taskgraph.transforms import ( # noqa: Added for backwards compat
- notify as release_notifications,
-)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/base.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/base.py
index e6fcd2400c..fda0c584fc 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/base.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/base.py
@@ -147,7 +147,7 @@ class ValidateSchema:
kind=config.kind, name=task["name"]
)
elif "label" in task:
- error = "In job {label!r}:".format(label=task["label"])
+ error = "In task {label!r}:".format(label=task["label"])
elif "primary-dependency" in task:
error = "In {kind} kind task for {dependency!r}:".format(
kind=config.kind, dependency=task["primary-dependency"].label
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/code_review.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/code_review.py
index bdb655b97d..2c859c36f6 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/code_review.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/code_review.py
@@ -12,12 +12,12 @@ transforms = TransformSequence()
@transforms.add
-def add_dependencies(config, jobs):
- for job in jobs:
- job.setdefault("soft-dependencies", [])
- job["soft-dependencies"] += [
+def add_dependencies(config, tasks):
+ for task in tasks:
+ task.setdefault("soft-dependencies", [])
+ task["soft-dependencies"] += [
dep_task.label
for dep_task in config.kind_dependencies_tasks.values()
if dep_task.attributes.get("code-review") is True
]
- yield job
+ yield task
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/docker_image.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/docker_image.py
index d0c5b9c97b..b58320092b 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/docker_image.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/docker_image.py
@@ -92,9 +92,7 @@ def fill_template(config, tasks):
for p in packages:
if p not in available_packages:
raise Exception(
- "Missing package job for {}-{}: {}".format(
- config.kind, image_name, p
- )
+ f"Missing package job for {config.kind}-{image_name}: {p}"
)
if not taskgraph.fast:
@@ -119,9 +117,7 @@ def fill_template(config, tasks):
digest_data += [json.dumps(args, sort_keys=True)]
context_hashes[image_name] = context_hash
- description = "Build the docker image {} for use by dependent tasks".format(
- image_name
- )
+ description = f"Build the docker image {image_name} for use by dependent tasks"
args["DOCKER_IMAGE_PACKAGES"] = " ".join(f"<{p}>" for p in packages)
@@ -132,6 +128,8 @@ def fill_template(config, tasks):
# burn more CPU once to reduce image size.
zstd_level = "3" if int(config.params["level"]) == 1 else "10"
+ expires = config.graph_config._config.get("task-expires-after", "28 days")
+
# include some information that is useful in reconstructing this task
# from JSON
taskdesc = {
@@ -142,7 +140,7 @@ def fill_template(config, tasks):
"artifact_prefix": "public",
},
"always-target": True,
- "expires-after": "28 days" if config.params.is_try() else "1 year",
+ "expires-after": expires if config.params.is_try() else "1 year",
"scopes": [],
"run-on-projects": [],
"worker-type": "images",
@@ -158,9 +156,7 @@ def fill_template(config, tasks):
],
"env": {
"CONTEXT_TASK_ID": {"task-reference": "<decision>"},
- "CONTEXT_PATH": "public/docker-contexts/{}.tar.gz".format(
- image_name
- ),
+ "CONTEXT_PATH": f"public/docker-contexts/{image_name}.tar.gz",
"HASH": context_hash,
"PROJECT": config.params["project"],
"IMAGE_NAME": image_name,
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/fetch.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/fetch.py
index bcb8ff38a6..0e1b739677 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/fetch.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/fetch.py
@@ -32,11 +32,12 @@ FETCH_SCHEMA = Schema(
Optional("task-from"): str,
# Description of the task.
Required("description"): str,
+ Optional("expires-after"): str,
Optional("docker-image"): object,
Optional(
"fetch-alias",
- description="An alias that can be used instead of the real fetch job name in "
- "fetch stanzas for jobs.",
+ description="An alias that can be used instead of the real fetch task name in "
+ "fetch stanzas for tasks.",
): str,
Optional(
"artifact-prefix",
@@ -78,20 +79,20 @@ transforms.add_validate(FETCH_SCHEMA)
@transforms.add
-def process_fetch_job(config, jobs):
- # Converts fetch-url entries to the job schema.
- for job in jobs:
- typ = job["fetch"]["type"]
- name = job["name"]
- fetch = job.pop("fetch")
+def process_fetch_task(config, tasks):
+ # Converts fetch-url entries to the run schema.
+ for task in tasks:
+ typ = task["fetch"]["type"]
+ name = task["name"]
+ fetch = task.pop("fetch")
if typ not in fetch_builders:
raise Exception(f"Unknown fetch type {typ} in fetch {name}")
validate_schema(fetch_builders[typ].schema, fetch, f"In task.fetch {name!r}:")
- job.update(configure_fetch(config, typ, name, fetch))
+ task.update(configure_fetch(config, typ, name, fetch))
- yield job
+ yield task
def configure_fetch(config, typ, name, fetch):
@@ -103,41 +104,41 @@ def configure_fetch(config, typ, name, fetch):
@transforms.add
-def make_task(config, jobs):
+def make_task(config, tasks):
# Fetch tasks are idempotent and immutable. Have them live for
# essentially forever.
if config.params["level"] == "3":
expires = "1000 years"
else:
- expires = "28 days"
+ expires = config.graph_config._config.get("task-expires-after", "28 days")
- for job in jobs:
- name = job["name"]
- artifact_prefix = job.get("artifact-prefix", "public")
- env = job.get("env", {})
+ for task in tasks:
+ name = task["name"]
+ artifact_prefix = task.get("artifact-prefix", "public")
+ env = task.get("env", {})
env.update({"UPLOAD_DIR": "/builds/worker/artifacts"})
- attributes = job.get("attributes", {})
- attributes["fetch-artifact"] = path.join(artifact_prefix, job["artifact_name"])
- alias = job.get("fetch-alias")
+ attributes = task.get("attributes", {})
+ attributes["fetch-artifact"] = path.join(artifact_prefix, task["artifact_name"])
+ alias = task.get("fetch-alias")
if alias:
attributes["fetch-alias"] = alias
- task = {
+ task_desc = {
"attributes": attributes,
"name": name,
- "description": job["description"],
- "expires-after": expires,
+ "description": task["description"],
+ "expires-after": task.get("expires-after", expires),
"label": "fetch-%s" % name,
"run-on-projects": [],
"run": {
"using": "run-task",
"checkout": False,
- "command": job["command"],
+ "command": task["command"],
},
"worker-type": "images",
"worker": {
"chain-of-trust": True,
- "docker-image": job.get("docker-image", {"in-tree": "fetch"}),
+ "docker-image": task.get("docker-image", {"in-tree": "fetch"}),
"env": env,
"max-run-time": 900,
"artifacts": [
@@ -151,29 +152,29 @@ def make_task(config, jobs):
}
if "treeherder" in config.graph_config:
- task["treeherder"] = {
+ task_desc["treeherder"] = {
"symbol": join_symbol("Fetch", name),
"kind": "build",
"platform": "fetch/opt",
"tier": 1,
}
- if job.get("secret", None):
- task["scopes"] = ["secrets:get:" + job.get("secret")]
- task["worker"]["taskcluster-proxy"] = True
+ if task.get("secret", None):
+ task_desc["scopes"] = ["secrets:get:" + task.get("secret")]
+ task_desc["worker"]["taskcluster-proxy"] = True
if not taskgraph.fast:
- cache_name = task["label"].replace(f"{config.kind}-", "", 1)
+ cache_name = task_desc["label"].replace(f"{config.kind}-", "", 1)
# This adds the level to the index path automatically.
add_optimization(
config,
- task,
+ task_desc,
cache_type=CACHE_TYPE,
cache_name=cache_name,
- digest_data=job["digest_data"],
+ digest_data=task["digest_data"],
)
- yield task
+ yield task_desc
@fetch_builder(
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/from_deps.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/from_deps.py
index 337d68e4ba..191ef7d56a 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/from_deps.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/from_deps.py
@@ -16,10 +16,11 @@ from textwrap import dedent
from voluptuous import Any, Extra, Optional, Required
from taskgraph.transforms.base import TransformSequence
-from taskgraph.transforms.job import fetches_schema
+from taskgraph.transforms.run import fetches_schema
from taskgraph.util.attributes import attrmatch
from taskgraph.util.dependencies import GROUP_BY_MAP, get_dependencies
from taskgraph.util.schema import Schema, validate_schema
+from taskgraph.util.set_name import SET_NAME_MAP
FROM_DEPS_SCHEMA = Schema(
{
@@ -41,12 +42,14 @@ FROM_DEPS_SCHEMA = Schema(
"set-name",
description=dedent(
"""
- When True, `from_deps` will derive a name for the generated
- tasks from the name of the primary dependency. Defaults to
- True.
+ UPDATE ME AND DOCS
""".lstrip()
),
- ): bool,
+ ): Any(
+ None,
+ *SET_NAME_MAP,
+ {Any(*SET_NAME_MAP): object},
+ ),
Optional(
"with-attributes",
description=dedent(
@@ -170,7 +173,7 @@ def from_deps(config, tasks):
groups = func(config, deps)
# Split the task, one per group.
- set_name = from_deps.get("set-name", True)
+ set_name = from_deps.get("set-name", "strip-kind")
copy_attributes = from_deps.get("copy-attributes", False)
unique_kinds = from_deps.get("unique-kinds", True)
fetches = from_deps.get("fetches", [])
@@ -203,10 +206,8 @@ def from_deps(config, tasks):
primary_dep = [dep for dep in group if dep.kind == primary_kind][0]
if set_name:
- if primary_dep.label.startswith(primary_kind):
- new_task["name"] = primary_dep.label[len(primary_kind) + 1 :]
- else:
- new_task["name"] = primary_dep.label
+ func = SET_NAME_MAP[set_name]
+ new_task["name"] = func(config, deps, primary_dep, primary_kind)
if copy_attributes:
attrs = new_task.setdefault("attributes", {})
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/__init__.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/__init__.py
deleted file mode 100644
index 06978ff46d..0000000000
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/__init__.py
+++ /dev/null
@@ -1,453 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-"""
-Convert a job description into a task description.
-
-Jobs descriptions are similar to task descriptions, but they specify how to run
-the job at a higher level, using a "run" field that can be interpreted by
-run-using handlers in `taskcluster/taskgraph/transforms/job`.
-"""
-
-
-import copy
-import json
-import logging
-
-from voluptuous import Any, Exclusive, Extra, Optional, Required
-
-from taskgraph.transforms.base import TransformSequence
-from taskgraph.transforms.cached_tasks import order_tasks
-from taskgraph.transforms.task import task_description_schema
-from taskgraph.util import path as mozpath
-from taskgraph.util.python_path import import_sibling_modules
-from taskgraph.util.schema import Schema, validate_schema
-from taskgraph.util.taskcluster import get_artifact_prefix
-from taskgraph.util.workertypes import worker_type_implementation
-
-logger = logging.getLogger(__name__)
-
-# Fetches may be accepted in other transforms and eventually passed along
-# to a `job` (eg: from_deps). Defining this here allows them to re-use
-# the schema and avoid duplication.
-fetches_schema = {
- Required("artifact"): str,
- Optional("dest"): str,
- Optional("extract"): bool,
- Optional("verify-hash"): bool,
-}
-
-# Schema for a build description
-job_description_schema = Schema(
- {
- # The name of the job and the job's label. At least one must be specified,
- # and the label will be generated from the name if necessary, by prepending
- # the kind.
- Optional("name"): str,
- Optional("label"): str,
- # the following fields are passed directly through to the task description,
- # possibly modified by the run implementation. See
- # taskcluster/taskgraph/transforms/task.py for the schema details.
- Required("description"): task_description_schema["description"],
- Optional("attributes"): task_description_schema["attributes"],
- Optional("task-from"): task_description_schema["task-from"],
- Optional("dependencies"): task_description_schema["dependencies"],
- Optional("soft-dependencies"): task_description_schema["soft-dependencies"],
- Optional("if-dependencies"): task_description_schema["if-dependencies"],
- Optional("requires"): task_description_schema["requires"],
- Optional("expires-after"): task_description_schema["expires-after"],
- Optional("routes"): task_description_schema["routes"],
- Optional("scopes"): task_description_schema["scopes"],
- Optional("tags"): task_description_schema["tags"],
- Optional("extra"): task_description_schema["extra"],
- Optional("treeherder"): task_description_schema["treeherder"],
- Optional("index"): task_description_schema["index"],
- Optional("run-on-projects"): task_description_schema["run-on-projects"],
- Optional("run-on-tasks-for"): task_description_schema["run-on-tasks-for"],
- Optional("run-on-git-branches"): task_description_schema["run-on-git-branches"],
- Optional("shipping-phase"): task_description_schema["shipping-phase"],
- Optional("always-target"): task_description_schema["always-target"],
- Exclusive("optimization", "optimization"): task_description_schema[
- "optimization"
- ],
- Optional("needs-sccache"): task_description_schema["needs-sccache"],
- # The "when" section contains descriptions of the circumstances under which
- # this task should be included in the task graph. This will be converted
- # into an optimization, so it cannot be specified in a job description that
- # also gives 'optimization'.
- Exclusive("when", "optimization"): {
- # This task only needs to be run if a file matching one of the given
- # patterns has changed in the push. The patterns use the mozpack
- # match function (python/mozbuild/mozpack/path.py).
- Optional("files-changed"): [str],
- },
- # A list of artifacts to install from 'fetch' tasks.
- Optional("fetches"): {
- Any("toolchain", "fetch"): [str],
- str: [
- str,
- fetches_schema,
- ],
- },
- # A description of how to run this job.
- "run": {
- # The key to a job implementation in a peer module to this one
- "using": str,
- # Base work directory used to set up the task.
- Optional("workdir"): str,
- # Any remaining content is verified against that job implementation's
- # own schema.
- Extra: object,
- },
- Required("worker-type"): task_description_schema["worker-type"],
- # This object will be passed through to the task description, with additions
- # provided by the job's run-using function
- Optional("worker"): dict,
- }
-)
-
-transforms = TransformSequence()
-transforms.add_validate(job_description_schema)
-
-
-@transforms.add
-def rewrite_when_to_optimization(config, jobs):
- for job in jobs:
- when = job.pop("when", {})
- if not when:
- yield job
- continue
-
- files_changed = when.get("files-changed")
-
- # implicitly add task config directory.
- files_changed.append(f"{config.path}/**")
-
- # "only when files changed" implies "skip if files have not changed"
- job["optimization"] = {"skip-unless-changed": files_changed}
-
- assert "when" not in job
- yield job
-
-
-@transforms.add
-def set_implementation(config, jobs):
- for job in jobs:
- impl, os = worker_type_implementation(config.graph_config, job["worker-type"])
- if os:
- job.setdefault("tags", {})["os"] = os
- if impl:
- job.setdefault("tags", {})["worker-implementation"] = impl
- worker = job.setdefault("worker", {})
- assert "implementation" not in worker
- worker["implementation"] = impl
- if os:
- worker["os"] = os
- yield job
-
-
-@transforms.add
-def set_label(config, jobs):
- for job in jobs:
- if "label" not in job:
- if "name" not in job:
- raise Exception("job has neither a name nor a label")
- job["label"] = "{}-{}".format(config.kind, job["name"])
- if job.get("name"):
- del job["name"]
- yield job
-
-
-@transforms.add
-def add_resource_monitor(config, jobs):
- for job in jobs:
- if job.get("attributes", {}).get("resource-monitor"):
- worker_implementation, worker_os = worker_type_implementation(
- config.graph_config, job["worker-type"]
- )
- # Normalise worker os so that linux-bitbar and similar use linux tools.
- worker_os = worker_os.split("-")[0]
- if "win7" in job["worker-type"]:
- arch = "32"
- else:
- arch = "64"
- job.setdefault("fetches", {})
- job["fetches"].setdefault("toolchain", [])
- job["fetches"]["toolchain"].append(f"{worker_os}{arch}-resource-monitor")
-
- if worker_implementation == "docker-worker":
- artifact_source = "/builds/worker/monitoring/resource-monitor.json"
- else:
- artifact_source = "monitoring/resource-monitor.json"
- job["worker"].setdefault("artifacts", [])
- job["worker"]["artifacts"].append(
- {
- "name": "public/monitoring/resource-monitor.json",
- "type": "file",
- "path": artifact_source,
- }
- )
- # Set env for output file
- job["worker"].setdefault("env", {})
- job["worker"]["env"]["RESOURCE_MONITOR_OUTPUT"] = artifact_source
-
- yield job
-
-
-def get_attribute(dict, key, attributes, attribute_name):
- """Get `attribute_name` from the given `attributes` dict, and if there
- is a corresponding value, set `key` in `dict` to that value."""
- value = attributes.get(attribute_name)
- if value:
- dict[key] = value
-
-
-@transforms.add
-def use_fetches(config, jobs):
- artifact_names = {}
- aliases = {}
- extra_env = {}
-
- if config.kind in ("toolchain", "fetch"):
- jobs = list(jobs)
- for job in jobs:
- run = job.get("run", {})
- label = job["label"]
- get_attribute(artifact_names, label, run, "toolchain-artifact")
- value = run.get(f"{config.kind}-alias")
- if value:
- aliases[f"{config.kind}-{value}"] = label
-
- for task in config.kind_dependencies_tasks.values():
- if task.kind in ("fetch", "toolchain"):
- get_attribute(
- artifact_names,
- task.label,
- task.attributes,
- f"{task.kind}-artifact",
- )
- get_attribute(extra_env, task.label, task.attributes, f"{task.kind}-env")
- value = task.attributes.get(f"{task.kind}-alias")
- if value:
- aliases[f"{task.kind}-{value}"] = task.label
-
- artifact_prefixes = {}
- for job in order_tasks(config, jobs):
- artifact_prefixes[job["label"]] = get_artifact_prefix(job)
-
- fetches = job.pop("fetches", None)
- if not fetches:
- yield job
- continue
-
- job_fetches = []
- name = job.get("name", job.get("label"))
- dependencies = job.setdefault("dependencies", {})
- worker = job.setdefault("worker", {})
- env = worker.setdefault("env", {})
- prefix = get_artifact_prefix(job)
- for kind in sorted(fetches):
- artifacts = fetches[kind]
- if kind in ("fetch", "toolchain"):
- for fetch_name in sorted(artifacts):
- label = f"{kind}-{fetch_name}"
- label = aliases.get(label, label)
- if label not in artifact_names:
- raise Exception(
- "Missing fetch job for {kind}-{name}: {fetch}".format(
- kind=config.kind, name=name, fetch=fetch_name
- )
- )
- if label in extra_env:
- env.update(extra_env[label])
-
- path = artifact_names[label]
-
- dependencies[label] = label
- job_fetches.append(
- {
- "artifact": path,
- "task": f"<{label}>",
- "extract": True,
- }
- )
- else:
- if kind not in dependencies:
- raise Exception(
- "{name} can't fetch {kind} artifacts because "
- "it has no {kind} dependencies!".format(name=name, kind=kind)
- )
- dep_label = dependencies[kind]
- if dep_label in artifact_prefixes:
- prefix = artifact_prefixes[dep_label]
- else:
- dep_tasks = [
- task
- for label, task in config.kind_dependencies_tasks.items()
- if label == dep_label
- ]
- if len(dep_tasks) != 1:
- raise Exception(
- "{name} can't fetch {kind} artifacts because "
- "there are {tasks} with label {label} in kind dependencies!".format(
- name=name,
- kind=kind,
- label=dependencies[kind],
- tasks="no tasks"
- if len(dep_tasks) == 0
- else "multiple tasks",
- )
- )
-
- prefix = get_artifact_prefix(dep_tasks[0])
-
- def cmp_artifacts(a):
- if isinstance(a, str):
- return a
- else:
- return a["artifact"]
-
- for artifact in sorted(artifacts, key=cmp_artifacts):
- if isinstance(artifact, str):
- path = artifact
- dest = None
- extract = True
- verify_hash = False
- else:
- path = artifact["artifact"]
- dest = artifact.get("dest")
- extract = artifact.get("extract", True)
- verify_hash = artifact.get("verify-hash", False)
-
- fetch = {
- "artifact": f"{prefix}/{path}",
- "task": f"<{kind}>",
- "extract": extract,
- }
- if dest is not None:
- fetch["dest"] = dest
- if verify_hash:
- fetch["verify-hash"] = verify_hash
- job_fetches.append(fetch)
-
- job_artifact_prefixes = {
- mozpath.dirname(fetch["artifact"])
- for fetch in job_fetches
- if not fetch["artifact"].startswith("public/")
- }
- if job_artifact_prefixes:
- # Use taskcluster-proxy and request appropriate scope. For example, add
- # 'scopes: [queue:get-artifact:path/to/*]' for 'path/to/artifact.tar.xz'.
- worker["taskcluster-proxy"] = True
- for prefix in sorted(job_artifact_prefixes):
- scope = f"queue:get-artifact:{prefix}/*"
- if scope not in job.setdefault("scopes", []):
- job["scopes"].append(scope)
-
- env["MOZ_FETCHES"] = {"task-reference": json.dumps(job_fetches, sort_keys=True)}
-
- env.setdefault("MOZ_FETCHES_DIR", "fetches")
-
- yield job
-
-
-@transforms.add
-def make_task_description(config, jobs):
- """Given a build description, create a task description"""
- # import plugin modules first, before iterating over jobs
- import_sibling_modules(exceptions=("common.py",))
-
- for job in jobs:
- # always-optimized tasks never execute, so have no workdir
- if job["worker"]["implementation"] in ("docker-worker", "generic-worker"):
- job["run"].setdefault("workdir", "/builds/worker")
-
- taskdesc = copy.deepcopy(job)
-
- # fill in some empty defaults to make run implementations easier
- taskdesc.setdefault("attributes", {})
- taskdesc.setdefault("dependencies", {})
- taskdesc.setdefault("soft-dependencies", [])
- taskdesc.setdefault("routes", [])
- taskdesc.setdefault("scopes", [])
- taskdesc.setdefault("extra", {})
-
- # give the function for job.run.using on this worker implementation a
- # chance to set up the task description.
- configure_taskdesc_for_run(
- config, job, taskdesc, job["worker"]["implementation"]
- )
- del taskdesc["run"]
-
- # yield only the task description, discarding the job description
- yield taskdesc
-
-
-# A registry of all functions decorated with run_job_using
-registry = {}
-
-
-def run_job_using(worker_implementation, run_using, schema=None, defaults={}):
- """Register the decorated function as able to set up a task description for
- jobs with the given worker implementation and `run.using` property. If
- `schema` is given, the job's run field will be verified to match it.
-
- The decorated function should have the signature `using_foo(config, job, taskdesc)`
- and should modify the task description in-place. The skeleton of
- the task description is already set up, but without a payload."""
-
- def wrap(func):
- for_run_using = registry.setdefault(run_using, {})
- if worker_implementation in for_run_using:
- raise Exception(
- "run_job_using({!r}, {!r}) already exists: {!r}".format(
- run_using,
- worker_implementation,
- for_run_using[worker_implementation],
- )
- )
- for_run_using[worker_implementation] = (func, schema, defaults)
- return func
-
- return wrap
-
-
-@run_job_using(
- "always-optimized", "always-optimized", Schema({"using": "always-optimized"})
-)
-def always_optimized(config, job, taskdesc):
- pass
-
-
-def configure_taskdesc_for_run(config, job, taskdesc, worker_implementation):
- """
- Run the appropriate function for this job against the given task
- description.
-
- This will raise an appropriate error if no function exists, or if the job's
- run is not valid according to the schema.
- """
- run_using = job["run"]["using"]
- if run_using not in registry:
- raise Exception(f"no functions for run.using {run_using!r}")
-
- if worker_implementation not in registry[run_using]:
- raise Exception(
- "no functions for run.using {!r} on {!r}".format(
- run_using, worker_implementation
- )
- )
-
- func, schema, defaults = registry[run_using][worker_implementation]
- for k, v in defaults.items():
- job["run"].setdefault(k, v)
-
- if schema:
- validate_schema(
- schema,
- job["run"],
- "In job.run using {!r}/{!r} for job {!r}:".format(
- job["run"]["using"], worker_implementation, job["label"]
- ),
- )
- func(config, job, taskdesc)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/common.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/common.py
deleted file mode 100644
index 04708daf81..0000000000
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/common.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-"""
-Common support for various job types. These functions are all named after the
-worker implementation they operate on, and take the same three parameters, for
-consistency.
-"""
-
-
-import hashlib
-import json
-
-from taskgraph.util.taskcluster import get_artifact_prefix
-
-
-def get_vcsdir_name(os):
- if os == "windows":
- return "src"
- else:
- return "vcs"
-
-
-def add_cache(job, taskdesc, name, mount_point, skip_untrusted=False):
- """Adds a cache based on the worker's implementation.
-
- Args:
- job (dict): Task's job description.
- taskdesc (dict): Target task description to modify.
- name (str): Name of the cache.
- mount_point (path): Path on the host to mount the cache.
- skip_untrusted (bool): Whether cache is used in untrusted environments
- (default: False). Only applies to docker-worker.
- """
- if not job["run"].get("use-caches", True):
- return
-
- worker = job["worker"]
-
- if worker["implementation"] == "docker-worker":
- taskdesc["worker"].setdefault("caches", []).append(
- {
- "type": "persistent",
- "name": name,
- "mount-point": mount_point,
- "skip-untrusted": skip_untrusted,
- }
- )
-
- elif worker["implementation"] == "generic-worker":
- taskdesc["worker"].setdefault("mounts", []).append(
- {
- "cache-name": name,
- "directory": mount_point,
- }
- )
-
- else:
- # Caches not implemented
- pass
-
-
-def add_artifacts(config, job, taskdesc, path):
- taskdesc["worker"].setdefault("artifacts", []).append(
- {
- "name": get_artifact_prefix(taskdesc),
- "path": path,
- "type": "directory",
- }
- )
-
-
-def docker_worker_add_artifacts(config, job, taskdesc):
- """Adds an artifact directory to the task"""
- path = "{workdir}/artifacts/".format(**job["run"])
- taskdesc["worker"]["env"]["UPLOAD_DIR"] = path
- add_artifacts(config, job, taskdesc, path)
-
-
-def generic_worker_add_artifacts(config, job, taskdesc):
- """Adds an artifact directory to the task"""
- # The path is the location on disk; it doesn't necessarily
- # mean the artifacts will be public or private; that is set via the name
- # attribute in add_artifacts.
- add_artifacts(config, job, taskdesc, path=get_artifact_prefix(taskdesc))
-
-
-def support_vcs_checkout(config, job, taskdesc, repo_configs, sparse=False):
- """Update a job/task with parameters to enable a VCS checkout.
-
- This can only be used with ``run-task`` tasks, as the cache name is
- reserved for ``run-task`` tasks.
- """
- worker = job["worker"]
- is_mac = worker["os"] == "macosx"
- is_win = worker["os"] == "windows"
- is_linux = worker["os"] == "linux"
- is_docker = worker["implementation"] == "docker-worker"
- assert is_mac or is_win or is_linux
-
- if is_win:
- checkoutdir = "./build"
- hgstore = "y:/hg-shared"
- elif is_docker:
- checkoutdir = "{workdir}/checkouts".format(**job["run"])
- hgstore = f"{checkoutdir}/hg-store"
- else:
- checkoutdir = "./checkouts"
- hgstore = f"{checkoutdir}/hg-shared"
-
- vcsdir = checkoutdir + "/" + get_vcsdir_name(worker["os"])
- cache_name = "checkouts"
-
- # Robust checkout does not clean up subrepositories, so ensure that tasks
- # that checkout different sets of paths have separate caches.
- # See https://bugzilla.mozilla.org/show_bug.cgi?id=1631610
- if len(repo_configs) > 1:
- checkout_paths = {
- "\t".join([repo_config.path, repo_config.prefix])
- for repo_config in sorted(
- repo_configs.values(), key=lambda repo_config: repo_config.path
- )
- }
- checkout_paths_str = "\n".join(checkout_paths).encode("utf-8")
- digest = hashlib.sha256(checkout_paths_str).hexdigest()
- cache_name += f"-repos-{digest}"
-
- # Sparse checkouts need their own cache because they can interfere
- # with clients that aren't sparse aware.
- if sparse:
- cache_name += "-sparse"
-
- # Workers using Mercurial >= 5.8 will enable revlog-compression-zstd, which
- # workers using older versions can't understand, so they can't share cache.
- # At the moment, only docker workers use the newer version.
- if is_docker:
- cache_name += "-hg58"
-
- add_cache(job, taskdesc, cache_name, checkoutdir)
-
- env = taskdesc["worker"].setdefault("env", {})
- env.update(
- {
- "HG_STORE_PATH": hgstore,
- "REPOSITORIES": json.dumps(
- {repo.prefix: repo.name for repo in repo_configs.values()}
- ),
- "VCS_PATH": vcsdir,
- }
- )
- for repo_config in repo_configs.values():
- env.update(
- {
- f"{repo_config.prefix.upper()}_{key}": value
- for key, value in {
- "BASE_REPOSITORY": repo_config.base_repository,
- "HEAD_REPOSITORY": repo_config.head_repository,
- "HEAD_REV": repo_config.head_rev,
- "HEAD_REF": repo_config.head_ref,
- "REPOSITORY_TYPE": repo_config.type,
- "SSH_SECRET_NAME": repo_config.ssh_secret_name,
- }.items()
- if value is not None
- }
- )
- if repo_config.ssh_secret_name:
- taskdesc["scopes"].append(f"secrets:get:{repo_config.ssh_secret_name}")
-
- # only some worker platforms have taskcluster-proxy enabled
- if job["worker"]["implementation"] in ("docker-worker",):
- taskdesc["worker"]["taskcluster-proxy"] = True
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/__init__.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/__init__.py
new file mode 100644
index 0000000000..a783a0dc13
--- /dev/null
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/__init__.py
@@ -0,0 +1,451 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
+Convert a run description into a task description.
+
+Run descriptions are similar to task descriptions, but they specify how to run
+the task at a higher level, using a "run" field that can be interpreted by
+run-using handlers in `taskcluster/taskgraph/transforms/run`.
+"""
+
+
+import copy
+import json
+import logging
+
+from voluptuous import Any, Exclusive, Extra, Optional, Required
+
+from taskgraph.transforms.base import TransformSequence
+from taskgraph.transforms.cached_tasks import order_tasks
+from taskgraph.transforms.task import task_description_schema
+from taskgraph.util import path as mozpath
+from taskgraph.util.python_path import import_sibling_modules
+from taskgraph.util.schema import Schema, validate_schema
+from taskgraph.util.taskcluster import get_artifact_prefix
+from taskgraph.util.workertypes import worker_type_implementation
+
+logger = logging.getLogger(__name__)
+
+# Fetches may be accepted in other transforms and eventually passed along
+# to a `task` (eg: from_deps). Defining this here allows them to reuse
+# the schema and avoid duplication.
+fetches_schema = {
+ Required("artifact"): str,
+ Optional("dest"): str,
+ Optional("extract"): bool,
+ Optional("verify-hash"): bool,
+}
+
+# Schema for a build description
+run_description_schema = Schema(
+ {
+ # The name of the task and the task's label. At least one must be specified,
+ # and the label will be generated from the name if necessary, by prepending
+ # the kind.
+ Optional("name"): str,
+ Optional("label"): str,
+ # the following fields are passed directly through to the task description,
+ # possibly modified by the run implementation. See
+ # taskcluster/taskgraph/transforms/task.py for the schema details.
+ Required("description"): task_description_schema["description"],
+ Optional("attributes"): task_description_schema["attributes"],
+ Optional("task-from"): task_description_schema["task-from"],
+ Optional("dependencies"): task_description_schema["dependencies"],
+ Optional("soft-dependencies"): task_description_schema["soft-dependencies"],
+ Optional("if-dependencies"): task_description_schema["if-dependencies"],
+ Optional("requires"): task_description_schema["requires"],
+ Optional("deadline-after"): task_description_schema["deadline-after"],
+ Optional("expires-after"): task_description_schema["expires-after"],
+ Optional("routes"): task_description_schema["routes"],
+ Optional("scopes"): task_description_schema["scopes"],
+ Optional("tags"): task_description_schema["tags"],
+ Optional("extra"): task_description_schema["extra"],
+ Optional("treeherder"): task_description_schema["treeherder"],
+ Optional("index"): task_description_schema["index"],
+ Optional("run-on-projects"): task_description_schema["run-on-projects"],
+ Optional("run-on-tasks-for"): task_description_schema["run-on-tasks-for"],
+ Optional("run-on-git-branches"): task_description_schema["run-on-git-branches"],
+ Optional("shipping-phase"): task_description_schema["shipping-phase"],
+ Optional("always-target"): task_description_schema["always-target"],
+ Exclusive("optimization", "optimization"): task_description_schema[
+ "optimization"
+ ],
+ Optional("needs-sccache"): task_description_schema["needs-sccache"],
+ # The "when" section contains descriptions of the circumstances under which
+ # this task should be included in the task graph. This will be converted
+ # into an optimization, so it cannot be specified in a run description that
+ # also gives 'optimization'.
+ Exclusive("when", "optimization"): {
+ # This task only needs to be run if a file matching one of the given
+ # patterns has changed in the push. The patterns use the mozpack
+ # match function (python/mozbuild/mozpack/path.py).
+ Optional("files-changed"): [str],
+ },
+ # A list of artifacts to install from 'fetch' tasks.
+ Optional("fetches"): {
+ Any("toolchain", "fetch"): [str],
+ str: [
+ str,
+ fetches_schema,
+ ],
+ },
+ # A description of how to run this task.
+ "run": {
+ # The key to a run implementation in a peer module to this one
+ "using": str,
+ # Base work directory used to set up the task.
+ Optional("workdir"): str,
+ # Any remaining content is verified against that run implementation's
+ # own schema.
+ Extra: object,
+ },
+ Required("worker-type"): task_description_schema["worker-type"],
+ # This object will be passed through to the task description, with additions
+ # provided by the task's run-using function
+ Optional("worker"): dict,
+ }
+)
+
+transforms = TransformSequence()
+transforms.add_validate(run_description_schema)
+
+
+@transforms.add
+def rewrite_when_to_optimization(config, tasks):
+ for task in tasks:
+ when = task.pop("when", {})
+ if not when:
+ yield task
+ continue
+
+ files_changed = when.get("files-changed")
+
+ # implicitly add task config directory.
+ files_changed.append(f"{config.path}/**")
+
+ # "only when files changed" implies "skip if files have not changed"
+ task["optimization"] = {"skip-unless-changed": files_changed}
+
+ assert "when" not in task
+ yield task
+
+
+@transforms.add
+def set_implementation(config, tasks):
+ for task in tasks:
+ impl, os = worker_type_implementation(config.graph_config, task["worker-type"])
+ if os:
+ task.setdefault("tags", {})["os"] = os
+ if impl:
+ task.setdefault("tags", {})["worker-implementation"] = impl
+ worker = task.setdefault("worker", {})
+ assert "implementation" not in worker
+ worker["implementation"] = impl
+ if os:
+ worker["os"] = os
+ yield task
+
+
+@transforms.add
+def set_label(config, tasks):
+ for task in tasks:
+ if "label" not in task:
+ if "name" not in task:
+ raise Exception("task has neither a name nor a label")
+ task["label"] = "{}-{}".format(config.kind, task["name"])
+ if task.get("name"):
+ del task["name"]
+ yield task
+
+
+@transforms.add
+def add_resource_monitor(config, tasks):
+ for task in tasks:
+ if task.get("attributes", {}).get("resource-monitor"):
+ worker_implementation, worker_os = worker_type_implementation(
+ config.graph_config, task["worker-type"]
+ )
+ # Normalise worker os so that linux-bitbar and similar use linux tools.
+ if worker_os:
+ worker_os = worker_os.split("-")[0]
+ if "win7" in task["worker-type"]:
+ arch = "32"
+ else:
+ arch = "64"
+ task.setdefault("fetches", {})
+ task["fetches"].setdefault("toolchain", [])
+ task["fetches"]["toolchain"].append(f"{worker_os}{arch}-resource-monitor")
+
+ if worker_implementation == "docker-worker":
+ artifact_source = "/builds/worker/monitoring/resource-monitor.json"
+ else:
+ artifact_source = "monitoring/resource-monitor.json"
+ task["worker"].setdefault("artifacts", [])
+ task["worker"]["artifacts"].append(
+ {
+ "name": "public/monitoring/resource-monitor.json",
+ "type": "file",
+ "path": artifact_source,
+ }
+ )
+ # Set env for output file
+ task["worker"].setdefault("env", {})
+ task["worker"]["env"]["RESOURCE_MONITOR_OUTPUT"] = artifact_source
+
+ yield task
+
+
+def get_attribute(dict, key, attributes, attribute_name):
+ """Get `attribute_name` from the given `attributes` dict, and if there
+ is a corresponding value, set `key` in `dict` to that value."""
+ value = attributes.get(attribute_name)
+ if value:
+ dict[key] = value
+
+
+@transforms.add
+def use_fetches(config, tasks):
+ artifact_names = {}
+ aliases = {}
+ extra_env = {}
+
+ if config.kind in ("toolchain", "fetch"):
+ tasks = list(tasks)
+ for task in tasks:
+ run = task.get("run", {})
+ label = task["label"]
+ get_attribute(artifact_names, label, run, "toolchain-artifact")
+ value = run.get(f"{config.kind}-alias")
+ if value:
+ aliases[f"{config.kind}-{value}"] = label
+
+ for task in config.kind_dependencies_tasks.values():
+ if task.kind in ("fetch", "toolchain"):
+ get_attribute(
+ artifact_names,
+ task.label,
+ task.attributes,
+ f"{task.kind}-artifact",
+ )
+ get_attribute(extra_env, task.label, task.attributes, f"{task.kind}-env")
+ value = task.attributes.get(f"{task.kind}-alias")
+ if value:
+ aliases[f"{task.kind}-{value}"] = task.label
+
+ artifact_prefixes = {}
+ for task in order_tasks(config, tasks):
+ artifact_prefixes[task["label"]] = get_artifact_prefix(task)
+
+ fetches = task.pop("fetches", None)
+ if not fetches:
+ yield task
+ continue
+
+ task_fetches = []
+ name = task.get("name", task.get("label"))
+ dependencies = task.setdefault("dependencies", {})
+ worker = task.setdefault("worker", {})
+ env = worker.setdefault("env", {})
+ prefix = get_artifact_prefix(task)
+ for kind in sorted(fetches):
+ artifacts = fetches[kind]
+ if kind in ("fetch", "toolchain"):
+ for fetch_name in sorted(artifacts):
+ label = f"{kind}-{fetch_name}"
+ label = aliases.get(label, label)
+ if label not in artifact_names:
+ raise Exception(
+ f"Missing fetch task for {config.kind}-{name}: {fetch_name}"
+ )
+ if label in extra_env:
+ env.update(extra_env[label])
+
+ path = artifact_names[label]
+
+ dependencies[label] = label
+ task_fetches.append(
+ {
+ "artifact": path,
+ "task": f"<{label}>",
+ "extract": True,
+ }
+ )
+ else:
+ if kind not in dependencies:
+ raise Exception(
+ f"{name} can't fetch {kind} artifacts because "
+ f"it has no {kind} dependencies!"
+ )
+ dep_label = dependencies[kind]
+ if dep_label in artifact_prefixes:
+ prefix = artifact_prefixes[dep_label]
+ else:
+ dep_tasks = [
+ task
+ for label, task in config.kind_dependencies_tasks.items()
+ if label == dep_label
+ ]
+ if len(dep_tasks) != 1:
+ raise Exception(
+ "{name} can't fetch {kind} artifacts because "
+ "there are {tasks} with label {label} in kind dependencies!".format(
+ name=name,
+ kind=kind,
+ label=dependencies[kind],
+ tasks=(
+ "no tasks"
+ if len(dep_tasks) == 0
+ else "multiple tasks"
+ ),
+ )
+ )
+
+ prefix = get_artifact_prefix(dep_tasks[0])
+
+ def cmp_artifacts(a):
+ if isinstance(a, str):
+ return a
+ else:
+ return a["artifact"]
+
+ for artifact in sorted(artifacts, key=cmp_artifacts):
+ if isinstance(artifact, str):
+ path = artifact
+ dest = None
+ extract = True
+ verify_hash = False
+ else:
+ path = artifact["artifact"]
+ dest = artifact.get("dest")
+ extract = artifact.get("extract", True)
+ verify_hash = artifact.get("verify-hash", False)
+
+ fetch = {
+ "artifact": f"{prefix}/{path}",
+ "task": f"<{kind}>",
+ "extract": extract,
+ }
+ if dest is not None:
+ fetch["dest"] = dest
+ if verify_hash:
+ fetch["verify-hash"] = verify_hash
+ task_fetches.append(fetch)
+
+ task_artifact_prefixes = {
+ mozpath.dirname(fetch["artifact"])
+ for fetch in task_fetches
+ if not fetch["artifact"].startswith("public/")
+ }
+ if task_artifact_prefixes:
+ # Use taskcluster-proxy and request appropriate scope. For example, add
+ # 'scopes: [queue:get-artifact:path/to/*]' for 'path/to/artifact.tar.xz'.
+ worker["taskcluster-proxy"] = True
+ for prefix in sorted(task_artifact_prefixes):
+ scope = f"queue:get-artifact:{prefix}/*"
+ if scope not in task.setdefault("scopes", []):
+ task["scopes"].append(scope)
+
+ env["MOZ_FETCHES"] = {
+ "task-reference": json.dumps(task_fetches, sort_keys=True)
+ }
+
+ env.setdefault("MOZ_FETCHES_DIR", "fetches")
+
+ yield task
+
+
+@transforms.add
+def make_task_description(config, tasks):
+ """Given a build description, create a task description"""
+ # import plugin modules first, before iterating over tasks
+ import_sibling_modules(exceptions=("common.py",))
+
+ for task in tasks:
+ # always-optimized tasks never execute, so have no workdir
+ if task["worker"]["implementation"] in ("docker-worker", "generic-worker"):
+ task["run"].setdefault("workdir", "/builds/worker")
+
+ taskdesc = copy.deepcopy(task)
+
+ # fill in some empty defaults to make run implementations easier
+ taskdesc.setdefault("attributes", {})
+ taskdesc.setdefault("dependencies", {})
+ taskdesc.setdefault("soft-dependencies", [])
+ taskdesc.setdefault("routes", [])
+ taskdesc.setdefault("scopes", [])
+ taskdesc.setdefault("extra", {})
+
+ # give the function for task.run.using on this worker implementation a
+ # chance to set up the task description.
+ configure_taskdesc_for_run(
+ config, task, taskdesc, task["worker"]["implementation"]
+ )
+ del taskdesc["run"]
+
+ # yield only the task description, discarding the task description
+ yield taskdesc
+
+
+# A registry of all functions decorated with run_task_using
+registry = {}
+
+
+def run_task_using(worker_implementation, run_using, schema=None, defaults={}):
+ """Register the decorated function as able to set up a task description for
+ tasks with the given worker implementation and `run.using` property. If
+ `schema` is given, the task's run field will be verified to match it.
+
+ The decorated function should have the signature `using_foo(config, task, taskdesc)`
+ and should modify the task description in-place. The skeleton of
+ the task description is already set up, but without a payload."""
+
+ def wrap(func):
+ for_run_using = registry.setdefault(run_using, {})
+ if worker_implementation in for_run_using:
+ raise Exception(
+ f"run_task_using({run_using!r}, {worker_implementation!r}) already exists: {for_run_using[worker_implementation]!r}"
+ )
+ for_run_using[worker_implementation] = (func, schema, defaults)
+ return func
+
+ return wrap
+
+
+@run_task_using(
+ "always-optimized", "always-optimized", Schema({"using": "always-optimized"})
+)
+def always_optimized(config, task, taskdesc):
+ pass
+
+
+def configure_taskdesc_for_run(config, task, taskdesc, worker_implementation):
+ """
+ Run the appropriate function for this task against the given task
+ description.
+
+ This will raise an appropriate error if no function exists, or if the task's
+ run is not valid according to the schema.
+ """
+ run_using = task["run"]["using"]
+ if run_using not in registry:
+ raise Exception(f"no functions for run.using {run_using!r}")
+
+ if worker_implementation not in registry[run_using]:
+ raise Exception(
+ f"no functions for run.using {run_using!r} on {worker_implementation!r}"
+ )
+
+ func, schema, defaults = registry[run_using][worker_implementation]
+ for k, v in defaults.items():
+ task["run"].setdefault(k, v)
+
+ if schema:
+ validate_schema(
+ schema,
+ task["run"],
+ "In task.run using {!r}/{!r} for task {!r}:".format(
+ task["run"]["using"], worker_implementation, task["label"]
+ ),
+ )
+ func(config, task, taskdesc)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/common.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/common.py
new file mode 100644
index 0000000000..66466bc5f9
--- /dev/null
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/common.py
@@ -0,0 +1,165 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
+Common support for various task types. These functions are all named after the
+worker implementation they operate on, and take the same three parameters, for
+consistency.
+"""
+
+
+import hashlib
+import json
+
+from taskgraph.util.taskcluster import get_artifact_prefix
+
+
+def get_vcsdir_name(os):
+ if os == "windows":
+ return "src"
+ else:
+ return "vcs"
+
+
+def add_cache(task, taskdesc, name, mount_point, skip_untrusted=False):
+ """Adds a cache based on the worker's implementation.
+
+ Args:
+ task (dict): Tasks object.
+ taskdesc (dict): Target task description to modify.
+ name (str): Name of the cache.
+ mount_point (path): Path on the host to mount the cache.
+ skip_untrusted (bool): Whether cache is used in untrusted environments
+ (default: False). Only applies to docker-worker.
+ """
+ if not task["run"].get("use-caches", True):
+ return
+
+ worker = task["worker"]
+
+ if worker["implementation"] == "docker-worker":
+ taskdesc["worker"].setdefault("caches", []).append(
+ {
+ "type": "persistent",
+ "name": name,
+ "mount-point": mount_point,
+ "skip-untrusted": skip_untrusted,
+ }
+ )
+
+ elif worker["implementation"] == "generic-worker":
+ taskdesc["worker"].setdefault("mounts", []).append(
+ {
+ "cache-name": name,
+ "directory": mount_point,
+ }
+ )
+
+ else:
+ # Caches not implemented
+ pass
+
+
+def add_artifacts(config, task, taskdesc, path):
+ taskdesc["worker"].setdefault("artifacts", []).append(
+ {
+ "name": get_artifact_prefix(taskdesc),
+ "path": path,
+ "type": "directory",
+ }
+ )
+
+
+def docker_worker_add_artifacts(config, task, taskdesc):
+ """Adds an artifact directory to the task"""
+ path = "{workdir}/artifacts/".format(**task["run"])
+ taskdesc["worker"]["env"]["UPLOAD_DIR"] = path
+ add_artifacts(config, task, taskdesc, path)
+
+
+def generic_worker_add_artifacts(config, task, taskdesc):
+ """Adds an artifact directory to the task"""
+ # The path is the location on disk; it doesn't necessarily
+ # mean the artifacts will be public or private; that is set via the name
+ # attribute in add_artifacts.
+ add_artifacts(config, task, taskdesc, path=get_artifact_prefix(taskdesc))
+
+
+def support_vcs_checkout(config, task, taskdesc, repo_configs, sparse=False):
+ """Update a task with parameters to enable a VCS checkout.
+
+ This can only be used with ``run-task`` tasks, as the cache name is
+ reserved for ``run-task`` tasks.
+ """
+ worker = task["worker"]
+ is_mac = worker["os"] == "macosx"
+ is_win = worker["os"] == "windows"
+ is_linux = worker["os"] == "linux"
+ is_docker = worker["implementation"] == "docker-worker"
+ assert is_mac or is_win or is_linux
+
+ if is_win:
+ checkoutdir = "./build"
+ hgstore = "y:/hg-shared"
+ elif is_docker:
+ checkoutdir = "{workdir}/checkouts".format(**task["run"])
+ hgstore = f"{checkoutdir}/hg-store"
+ else:
+ checkoutdir = "./checkouts"
+ hgstore = f"{checkoutdir}/hg-shared"
+
+ vcsdir = checkoutdir + "/" + get_vcsdir_name(worker["os"])
+ cache_name = "checkouts"
+
+ # Robust checkout does not clean up subrepositories, so ensure that tasks
+ # that checkout different sets of paths have separate caches.
+ # See https://bugzilla.mozilla.org/show_bug.cgi?id=1631610
+ if len(repo_configs) > 1:
+ checkout_paths = {
+ "\t".join([repo_config.path, repo_config.prefix])
+ for repo_config in sorted(
+ repo_configs.values(), key=lambda repo_config: repo_config.path
+ )
+ }
+ checkout_paths_str = "\n".join(checkout_paths).encode("utf-8")
+ digest = hashlib.sha256(checkout_paths_str).hexdigest()
+ cache_name += f"-repos-{digest}"
+
+ # Sparse checkouts need their own cache because they can interfere
+ # with clients that aren't sparse aware.
+ if sparse:
+ cache_name += "-sparse"
+
+ add_cache(task, taskdesc, cache_name, checkoutdir)
+
+ env = taskdesc["worker"].setdefault("env", {})
+ env.update(
+ {
+ "HG_STORE_PATH": hgstore,
+ "REPOSITORIES": json.dumps(
+ {repo.prefix: repo.name for repo in repo_configs.values()}
+ ),
+ "VCS_PATH": vcsdir,
+ }
+ )
+ for repo_config in repo_configs.values():
+ env.update(
+ {
+ f"{repo_config.prefix.upper()}_{key}": value
+ for key, value in {
+ "BASE_REPOSITORY": repo_config.base_repository,
+ "HEAD_REPOSITORY": repo_config.head_repository,
+ "HEAD_REV": repo_config.head_rev,
+ "HEAD_REF": repo_config.head_ref,
+ "REPOSITORY_TYPE": repo_config.type,
+ "SSH_SECRET_NAME": repo_config.ssh_secret_name,
+ }.items()
+ if value is not None
+ }
+ )
+ if repo_config.ssh_secret_name:
+ taskdesc["scopes"].append(f"secrets:get:{repo_config.ssh_secret_name}")
+
+ # only some worker platforms have taskcluster-proxy enabled
+ if task["worker"]["implementation"] in ("docker-worker",):
+ taskdesc["worker"]["taskcluster-proxy"] = True
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/index_search.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/index_search.py
index 09b48fe594..c25946980e 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/index_search.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/index_search.py
@@ -12,7 +12,7 @@ phase will replace the task with the task from the other graph.
from voluptuous import Required
from taskgraph.transforms.base import TransformSequence
-from taskgraph.transforms.job import run_job_using
+from taskgraph.transforms.run import run_task_using
from taskgraph.util.schema import Schema
transforms = TransformSequence()
@@ -29,9 +29,9 @@ run_task_schema = Schema(
)
-@run_job_using("always-optimized", "index-search", schema=run_task_schema)
-def fill_template(config, job, taskdesc):
- run = job["run"]
+@run_task_using("always-optimized", "index-search", schema=run_task_schema)
+def fill_template(config, task, taskdesc):
+ run = task["run"]
taskdesc["optimization"] = {
"index-search": [index.format(**config.params) for index in run["index-search"]]
}
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/run_task.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/run_task.py
index 6337673611..c2fbef83b0 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/run_task.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/run_task.py
@@ -2,7 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
-Support for running jobs that are invoked via the `run-task` script.
+Support for running tasks that are invoked via the `run-task` script.
"""
import dataclasses
@@ -10,8 +10,8 @@ import os
from voluptuous import Any, Optional, Required
-from taskgraph.transforms.job import run_job_using
-from taskgraph.transforms.job.common import support_vcs_checkout
+from taskgraph.transforms.run import run_task_using
+from taskgraph.transforms.run.common import support_vcs_checkout
from taskgraph.transforms.task import taskref_or_string
from taskgraph.util import path, taskcluster
from taskgraph.util.schema import Schema
@@ -25,7 +25,7 @@ run_task_schema = Schema(
{
Required("using"): "run-task",
# if true, add a cache at ~worker/.cache, which is where things like pip
- # tend to hide their caches. This cache is never added for level-1 jobs.
+ # tend to hide their caches. This cache is never added for level-1 tasks.
# TODO Once bug 1526028 is fixed, this and 'use-caches' should be merged.
Required("cache-dotcache"): bool,
# Whether or not to use caches.
@@ -58,8 +58,8 @@ run_task_schema = Schema(
)
-def common_setup(config, job, taskdesc, command):
- run = job["run"]
+def common_setup(config, task, taskdesc, command):
+ run = task["run"]
if run["checkout"]:
repo_configs = config.repo_configs
if len(repo_configs) > 1 and run["checkout"] is True:
@@ -72,7 +72,7 @@ def common_setup(config, job, taskdesc, command):
support_vcs_checkout(
config,
- job,
+ task,
taskdesc,
repo_configs=repo_configs,
sparse=bool(run["sparse-profile"]),
@@ -97,7 +97,7 @@ def common_setup(config, job, taskdesc, command):
raise Exception(
"Found `{{checkout}}` interpolation in `cwd` for task {name} "
"but the task doesn't have a checkout: {cwd}".format(
- cwd=run["cwd"], name=job.get("name", job.get("label"))
+ cwd=run["cwd"], name=task.get("name", task.get("label"))
)
)
@@ -126,14 +126,14 @@ def script_url(config, script):
return f"{tc_url}/api/queue/v1/task/{task_id}/artifacts/public/{script}"
-@run_job_using(
+@run_task_using(
"docker-worker", "run-task", schema=run_task_schema, defaults=worker_defaults
)
-def docker_worker_run_task(config, job, taskdesc):
- run = job["run"]
- worker = taskdesc["worker"] = job["worker"]
+def docker_worker_run_task(config, task, taskdesc):
+ run = task["run"]
+ worker = taskdesc["worker"] = task["worker"]
command = run.pop("run-task-command", ["/usr/local/bin/run-task"])
- common_setup(config, job, taskdesc, command)
+ common_setup(config, task, taskdesc, command)
if run.get("cache-dotcache"):
worker["caches"].append(
@@ -158,12 +158,12 @@ def docker_worker_run_task(config, job, taskdesc):
worker["command"] = command
-@run_job_using(
+@run_task_using(
"generic-worker", "run-task", schema=run_task_schema, defaults=worker_defaults
)
-def generic_worker_run_task(config, job, taskdesc):
- run = job["run"]
- worker = taskdesc["worker"] = job["worker"]
+def generic_worker_run_task(config, task, taskdesc):
+ run = task["run"]
+ worker = taskdesc["worker"] = task["worker"]
is_win = worker["os"] == "windows"
is_mac = worker["os"] == "macosx"
is_bitbar = worker["os"] == "linux-bitbar"
@@ -177,7 +177,7 @@ def generic_worker_run_task(config, job, taskdesc):
else:
command = ["./run-task"]
- common_setup(config, job, taskdesc, command)
+ common_setup(config, task, taskdesc, command)
worker.setdefault("mounts", [])
if run.get("cache-dotcache"):
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/toolchain.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/toolchain.py
index c9c09542ff..59e66cb973 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/job/toolchain.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/run/toolchain.py
@@ -2,14 +2,14 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
-Support for running toolchain-building jobs via dedicated scripts
+Support for running toolchain-building tasks via dedicated scripts
"""
from voluptuous import ALLOW_EXTRA, Any, Optional, Required
import taskgraph
-from taskgraph.transforms.job import configure_taskdesc_for_run, run_job_using
-from taskgraph.transforms.job.common import (
+from taskgraph.transforms.run import configure_taskdesc_for_run, run_task_using
+from taskgraph.transforms.run.common import (
docker_worker_add_artifacts,
generic_worker_add_artifacts,
get_vcsdir_name,
@@ -36,12 +36,12 @@ toolchain_run_schema = Schema(
# Paths/patterns pointing to files that influence the outcome of a
# toolchain build.
Optional("resources"): [str],
- # Path to the artifact produced by the toolchain job
+ # Path to the artifact produced by the toolchain task
Required("toolchain-artifact"): str,
Optional(
"toolchain-alias",
- description="An alias that can be used instead of the real toolchain job name in "
- "fetch stanzas for jobs.",
+ description="An alias that can be used instead of the real toolchain task name in "
+ "fetch stanzas for tasks.",
): Any(str, [str]),
Optional(
"toolchain-env",
@@ -82,10 +82,10 @@ def get_digest_data(config, run, taskdesc):
return data
-def common_toolchain(config, job, taskdesc, is_docker):
- run = job["run"]
+def common_toolchain(config, task, taskdesc, is_docker):
+ run = task["run"]
- worker = taskdesc["worker"] = job["worker"]
+ worker = taskdesc["worker"] = task["worker"]
worker["chain-of-trust"] = True
srcdir = get_vcsdir_name(worker["os"])
@@ -94,14 +94,14 @@ def common_toolchain(config, job, taskdesc, is_docker):
# If the task doesn't have a docker-image, set a default
worker.setdefault("docker-image", {"in-tree": "toolchain-build"})
- # Allow the job to specify where artifacts come from, but add
+ # Allow the task to specify where artifacts come from, but add
# public/build if it's not there already.
artifacts = worker.setdefault("artifacts", [])
if not any(artifact.get("name") == "public/build" for artifact in artifacts):
if is_docker:
- docker_worker_add_artifacts(config, job, taskdesc)
+ docker_worker_add_artifacts(config, task, taskdesc)
else:
- generic_worker_add_artifacts(config, job, taskdesc)
+ generic_worker_add_artifacts(config, task, taskdesc)
env = worker["env"]
env.update(
@@ -147,7 +147,7 @@ def common_toolchain(config, job, taskdesc, is_docker):
run["command"] = command
- configure_taskdesc_for_run(config, job, taskdesc, worker["implementation"])
+ configure_taskdesc_for_run(config, task, taskdesc, worker["implementation"])
toolchain_defaults = {
@@ -155,21 +155,21 @@ toolchain_defaults = {
}
-@run_job_using(
+@run_task_using(
"docker-worker",
"toolchain-script",
schema=toolchain_run_schema,
defaults=toolchain_defaults,
)
-def docker_worker_toolchain(config, job, taskdesc):
- common_toolchain(config, job, taskdesc, is_docker=True)
+def docker_worker_toolchain(config, task, taskdesc):
+ common_toolchain(config, task, taskdesc, is_docker=True)
-@run_job_using(
+@run_task_using(
"generic-worker",
"toolchain-script",
schema=toolchain_run_schema,
defaults=toolchain_defaults,
)
-def generic_worker_toolchain(config, job, taskdesc):
- common_toolchain(config, job, taskdesc, is_docker=False)
+def generic_worker_toolchain(config, task, taskdesc):
+ common_toolchain(config, task, taskdesc, is_docker=False)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task.py
index c55de78513..168b8c00c9 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task.py
@@ -110,7 +110,7 @@ task_description_schema = Schema(
# section of the kind (delimited by "-") all smooshed together.
# Eg: "test" becomes "T", "docker-image" becomes "DI", etc.
"symbol": Optional(str),
- # the job kind
+ # the task kind
# If "build" or "test" is found in the kind name, this defaults
# to the appropriate value. Otherwise, defaults to "other"
"kind": Optional(Any("build", "test", "other")),
@@ -129,7 +129,7 @@ task_description_schema = Schema(
Optional("index"): {
# the name of the product this build produces
"product": str,
- # the names to use for this job in the TaskCluster index
+ # the names to use for this task in the TaskCluster index
"job-name": str,
# Type of gecko v2 index to use
"type": str,
@@ -179,7 +179,7 @@ task_description_schema = Schema(
# be substituted in this string:
# {level} -- the scm level of this push
"worker-type": str,
- # Whether the job should use sccache compiler caching.
+ # Whether the task should use sccache compiler caching.
Required("needs-sccache"): bool,
# information specific to the worker implementation that will run this task
Optional("worker"): {
@@ -196,7 +196,7 @@ TC_TREEHERDER_SCHEMA_URL = (
UNKNOWN_GROUP_NAME = (
- "Treeherder group {} (from {}) has no name; " "add it to taskcluster/ci/config.yml"
+ "Treeherder group {} (from {}) has no name; " "add it to taskcluster/config.yml"
)
V2_ROUTE_TEMPLATES = [
@@ -266,7 +266,7 @@ def index_builder(name):
UNSUPPORTED_INDEX_PRODUCT_ERROR = """\
The index product {product} is not in the list of configured products in
-`taskcluster/ci/config.yml'.
+`taskcluster/config.yml'.
"""
@@ -317,7 +317,7 @@ def verify_index(config, index):
{
# only one type is supported by any of the workers right now
"type": "persistent",
- # name of the cache, allowing re-use by subsequent tasks naming the
+ # name of the cache, allowing reuse by subsequent tasks naming the
# same cache
"name": str,
# location in the task image where the cache will be mounted
@@ -364,6 +364,9 @@ def build_docker_worker_payload(config, task, task_def):
if "in-tree" in image:
name = image["in-tree"]
docker_image_task = "build-docker-image-" + image["in-tree"]
+ assert "docker-image" not in task.get(
+ "dependencies", ()
+ ), "docker-image key in dependencies object is reserved"
task.setdefault("dependencies", {})["docker-image"] = docker_image_task
image = {
@@ -487,19 +490,19 @@ def build_docker_worker_payload(config, task, task_def):
# run-task knows how to validate caches.
#
- # To help ensure new run-task features and bug fixes don't interfere
- # with existing caches, we seed the hash of run-task into cache names.
- # So, any time run-task changes, we should get a fresh set of caches.
- # This means run-task can make changes to cache interaction at any time
- # without regards for backwards or future compatibility.
+ # To help ensure new run-task features and bug fixes, as well as the
+ # versions of tools such as mercurial or git, don't interfere with
+ # existing caches, we seed the underlying docker-image task id into
+ # cache names, for tasks using in-tree Docker images.
#
# But this mechanism only works for in-tree Docker images that are built
# with the current run-task! For out-of-tree Docker images, we have no
# way of knowing their content of run-task. So, in addition to varying
# cache names by the contents of run-task, we also take the Docker image
- # name into consideration. This means that different Docker images will
- # never share the same cache. This is a bit unfortunate. But it is the
- # safest thing to do. Fortunately, most images are defined in-tree.
+ # name into consideration.
+ #
+ # This means that different Docker images will never share the same
+ # cache. This is a bit unfortunate, but is the safest thing to do.
#
# For out-of-tree Docker images, we don't strictly need to incorporate
# the run-task content into the cache name. However, doing so preserves
@@ -520,6 +523,8 @@ def build_docker_worker_payload(config, task, task_def):
out_of_tree_image.encode("utf-8")
).hexdigest()
suffix += name_hash[0:12]
+ else:
+ suffix += "-<docker-image>"
else:
suffix = cache_version
@@ -539,13 +544,15 @@ def build_docker_worker_payload(config, task, task_def):
suffix=suffix,
)
caches[name] = cache["mount-point"]
- task_def["scopes"].append("docker-worker:cache:%s" % name)
+ task_def["scopes"].append(
+ {"task-reference": "docker-worker:cache:%s" % name}
+ )
# Assertion: only run-task is interested in this.
if run_task:
payload["env"]["TASKCLUSTER_CACHES"] = ";".join(sorted(caches.values()))
- payload["cache"] = caches
+ payload["cache"] = {"task-reference": caches}
# And send down volumes information to run-task as well.
if run_task and worker.get("volumes"):
@@ -752,7 +759,7 @@ def build_generic_worker_payload(config, task, task_def):
schema={
# the maximum time to run, in seconds
Required("max-run-time"): int,
- # locale key, if this is a locale beetmover job
+ # locale key, if this is a locale beetmover task
Optional("locale"): str,
Optional("partner-public"): bool,
Required("release-properties"): {
@@ -1075,7 +1082,11 @@ def build_task(config, tasks):
extra["parent"] = os.environ.get("TASK_ID", "")
if "expires-after" not in task:
- task["expires-after"] = "28 days" if config.params.is_try() else "1 year"
+ task["expires-after"] = (
+ config.graph_config._config.get("task-expires-after", "28 days")
+ if config.params.is_try()
+ else "1 year"
+ )
if "deadline-after" not in task:
if "task-deadline-after" in config.graph_config:
@@ -1142,9 +1153,9 @@ def build_task(config, tasks):
config.params["project"] + th_project_suffix, branch_rev
)
)
- task_def["metadata"]["description"] += " ([Treeherder push]({}))".format(
- th_push_link
- )
+ task_def["metadata"][
+ "description"
+ ] += f" ([Treeherder push]({th_push_link}))"
# add the payload and adjust anything else as required (e.g., scopes)
payload_builders[task["worker"]["implementation"]].builder(
@@ -1288,7 +1299,7 @@ def check_caches_are_volumes(task):
Caches and volumes are the only filesystem locations whose content
isn't defined by the Docker image itself. Some caches are optional
- depending on the job environment. We want paths that are potentially
+ depending on the task environment. We want paths that are potentially
caches to have as similar behavior regardless of whether a cache is
used. To help enforce this, we require that all paths used as caches
to be declared as Docker volumes. This check won't catch all offenders.
@@ -1343,7 +1354,9 @@ def check_run_task_caches(config, tasks):
main_command = command[0] if isinstance(command[0], str) else ""
run_task = main_command.endswith("run-task")
- for cache in payload.get("cache", {}):
+ for cache in payload.get("cache", {}).get(
+ "task-reference", payload.get("cache", {})
+ ):
if not cache.startswith(cache_prefix):
raise Exception(
"{} is using a cache ({}) which is not appropriate "
@@ -1364,7 +1377,7 @@ def check_run_task_caches(config, tasks):
"cache name"
)
- if not cache.endswith(suffix):
+ if suffix not in cache:
raise Exception(
f"{task['label']} is using a cache ({cache}) reserved for run-task "
"but the cache name is not dependent on the contents "
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task_context.py b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task_context.py
index 5c7ed6af80..bd36d827aa 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task_context.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/transforms/task_context.py
@@ -81,9 +81,9 @@ transforms.add_validate(SCHEMA)
@transforms.add
-def render_task(config, jobs):
- for job in jobs:
- sub_config = job.pop("task-context")
+def render_task(config, tasks):
+ for task in tasks:
+ sub_config = task.pop("task-context")
params_context = {}
for var, path in sub_config.pop("from-parameters", {}).items():
if isinstance(path, str):
@@ -111,11 +111,11 @@ def render_task(config, jobs):
# Now that we have our combined context, we can substitute.
for field in fields:
- container, subfield = job, field
+ container, subfield = task, field
while "." in subfield:
f, subfield = subfield.split(".", 1)
container = container[f]
container[subfield] = substitute(container[subfield], **subs)
- yield job
+ yield task
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/archive.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/archive.py
index ee59ba4548..261a031038 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/archive.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/archive.py
@@ -12,6 +12,40 @@ import tarfile
DEFAULT_MTIME = 1451606400
+# Python 3.9 contains this change:
+# https://github.com/python/cpython/commit/674935b8caf33e47c78f1b8e197b1b77a04992d2
+# which changes the output of tar creation compared to earlier versions.
+# As this code is used to generate tar files that are meant to be deterministic
+# across versions of python (specifically, it's used as part of computing the hash
+# of docker images, which needs to be identical between CI (which uses python 3.8),
+# and developer environments (using arbitrary versions of python, at this point,
+# most probably more recent than 3.9)).
+# What we do is subblass TarInfo so that if used on python >= 3.9, it reproduces the
+# behavior from python < 3.9.
+# Here's how it goes:
+# - the behavior in python >= 3.9 is the same as python < 3.9 when the type encoded
+# in the tarinfo is CHRTYPE or BLKTYPE.
+# - the value of the type is only compared in the context of choosing which behavior
+# to take
+# - we replace the type with the same value (so that using the value has no changes)
+# but that pretends to be the same as CHRTYPE so that the condition that enables the
+# old behavior is taken.
+class HackedType(bytes):
+ def __eq__(self, other):
+ if other == tarfile.CHRTYPE:
+ return True
+ return self == other
+
+
+class TarInfo(tarfile.TarInfo):
+ @staticmethod
+ def _create_header(info, format, encoding, errors):
+ info["type"] = HackedType(info["type"])
+ # ignore type checking because it looks like pyright complains because we're calling a
+ # non-public method
+ return tarfile.TarInfo._create_header(info, format, encoding, errors) # type: ignore
+
+
def create_tar_from_files(fp, files):
"""Create a tar file deterministically.
@@ -25,15 +59,23 @@ def create_tar_from_files(fp, files):
FUTURE accept a filename argument (or create APIs to write files)
"""
- with tarfile.open(name="", mode="w", fileobj=fp, dereference=True) as tf:
+ # The format is explicitly set to tarfile.GNU_FORMAT, because this default format
+ # has been changed in Python 3.8.
+ with tarfile.open(
+ name="", mode="w", fileobj=fp, dereference=True, format=tarfile.GNU_FORMAT
+ ) as tf:
for archive_path, f in sorted(files.items()):
if isinstance(f, str):
- mode = os.stat(f).st_mode
+ s = os.stat(f)
+ mode = s.st_mode
+ size = s.st_size
f = open(f, "rb")
else:
mode = 0o0644
+ size = len(f.read())
+ f.seek(0)
- ti = tarfile.TarInfo(archive_path)
+ ti = TarInfo(archive_path)
ti.mode = mode
ti.type = tarfile.REGTYPE
@@ -56,9 +98,7 @@ def create_tar_from_files(fp, files):
# Set mtime to a constant value.
ti.mtime = DEFAULT_MTIME
- f.seek(0, 2)
- ti.size = f.tell()
- f.seek(0, 0)
+ ti.size = size
# tarfile wants to pass a size argument to read(). So just
# wrap/buffer in a proper file object interface.
tf.addfile(ti, f)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/cached_tasks.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/cached_tasks.py
index 974b114902..1a3baad5be 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/cached_tasks.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/cached_tasks.py
@@ -7,6 +7,7 @@ import hashlib
import time
TARGET_CACHE_INDEX = "{cache_prefix}.cache.level-{level}.{type}.{name}.hash.{digest}"
+TARGET_PR_CACHE_INDEX = "{cache_prefix}.cache.pr.{type}.{name}.hash.{digest}"
EXTRA_CACHE_INDEXES = [
"{cache_prefix}.cache.level-{level}.{type}.{name}.latest",
"{cache_prefix}.cache.level-{level}.{type}.{name}.pushdate.{build_date_long}",
@@ -53,31 +54,45 @@ def add_optimization(
# We'll try to find a cached version of the toolchain at levels above and
# including the current level, starting at the highest level.
- # Chain-of-trust doesn't handle tasks not built on the tip of a
- # pull-request, so don't look for level-1 tasks if building a pull-request.
index_routes = []
min_level = int(config.params["level"])
- if config.params["tasks_for"] == "github-pull-request":
- min_level = max(min_level, 3)
for level in reversed(range(min_level, 4)):
subs["level"] = level
index_routes.append(TARGET_CACHE_INDEX.format(**subs))
- taskdesc["optimization"] = {"index-search": index_routes}
+ # Pull requests use a different target cache index route. This way we can
+ # be confident they won't be used by anything other than the pull request
+ # that created the cache in the first place.
+ if config.params["tasks_for"].startswith(
+ "github-pull-request"
+ ) and config.graph_config["taskgraph"].get("cache-pull-requests", True):
+ subs["head_ref"] = config.params["head_ref"]
+ if subs["head_ref"].startswith("refs/heads/"):
+ subs["head_ref"] = subs["head_ref"][11:]
+ index_routes.append(TARGET_PR_CACHE_INDEX.format(**subs))
+
+ taskdesc["optimization"] = {"index-search": index_routes}
# ... and cache at the lowest level.
subs["level"] = config.params["level"]
- taskdesc.setdefault("routes", []).append(
- f"index.{TARGET_CACHE_INDEX.format(**subs)}"
- )
- # ... and add some extra routes for humans
- subs["build_date_long"] = time.strftime(
- "%Y.%m.%d.%Y%m%d%H%M%S", time.gmtime(config.params["build_date"])
- )
- taskdesc["routes"].extend(
- [f"index.{route.format(**subs)}" for route in EXTRA_CACHE_INDEXES]
- )
+ if config.params["tasks_for"].startswith("github-pull-request"):
+ if config.graph_config["taskgraph"].get("cache-pull-requests", True):
+ taskdesc.setdefault("routes", []).append(
+ f"index.{TARGET_PR_CACHE_INDEX.format(**subs)}"
+ )
+ else:
+ taskdesc.setdefault("routes", []).append(
+ f"index.{TARGET_CACHE_INDEX.format(**subs)}"
+ )
+
+ # ... and add some extra routes for humans
+ subs["build_date_long"] = time.strftime(
+ "%Y.%m.%d.%Y%m%d%H%M%S", time.gmtime(config.params["build_date"])
+ )
+ taskdesc["routes"].extend(
+ [f"index.{route.format(**subs)}" for route in EXTRA_CACHE_INDEXES]
+ )
taskdesc["attributes"]["cached_task"] = {
"type": cache_type,
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/decision.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/decision.py
deleted file mode 100644
index d0e1e1079f..0000000000
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/decision.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-"""
-Utilities for generating a decision task from :file:`.taskcluster.yml`.
-"""
-
-
-import os
-
-import jsone
-import slugid
-import yaml
-
-from .templates import merge
-from .time import current_json_time
-from .vcs import find_hg_revision_push_info
-
-
-def make_decision_task(params, root, context, head_rev=None):
- """Generate a basic decision task, based on the root .taskcluster.yml"""
- with open(os.path.join(root, ".taskcluster.yml"), "rb") as f:
- taskcluster_yml = yaml.safe_load(f)
-
- if not head_rev:
- head_rev = params["head_rev"]
-
- if params["repository_type"] == "hg":
- pushlog = find_hg_revision_push_info(params["repository_url"], head_rev)
-
- hg_push_context = {
- "pushlog_id": pushlog["pushid"],
- "pushdate": pushlog["pushdate"],
- "owner": pushlog["user"],
- }
- else:
- hg_push_context = {}
-
- slugids = {}
-
- def as_slugid(name):
- # https://github.com/taskcluster/json-e/issues/164
- name = name[0]
- if name not in slugids:
- slugids[name] = slugid.nice()
- return slugids[name]
-
- # provide a similar JSON-e context to what mozilla-taskcluster provides:
- # https://docs.taskcluster.net/reference/integrations/mozilla-taskcluster/docs/taskcluster-yml
- # but with a different tasks_for and an extra `cron` section
- context = merge(
- {
- "repository": {
- "url": params["repository_url"],
- "project": params["project"],
- "level": params["level"],
- },
- "push": merge(
- {
- "revision": params["head_rev"],
- # remainder are fake values, but the decision task expects them anyway
- "comment": " ",
- },
- hg_push_context,
- ),
- "now": current_json_time(),
- "as_slugid": as_slugid,
- },
- context,
- )
-
- rendered = jsone.render(taskcluster_yml, context)
- if len(rendered["tasks"]) != 1:
- raise Exception("Expected .taskcluster.yml to only produce one cron task")
- task = rendered["tasks"][0]
-
- task_id = task.pop("taskId")
- return (task_id, task)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/docker.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/docker.py
index c37a69f98f..13815381ed 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/docker.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/docker.py
@@ -7,6 +7,7 @@ import hashlib
import io
import os
import re
+from typing import Optional
from taskgraph.util.archive import create_tar_gz_from_files
from taskgraph.util.memoize import memoize
@@ -16,17 +17,27 @@ IMAGE_DIR = os.path.join(".", "taskcluster", "docker")
from .yaml import load_yaml
-def docker_image(name, by_tag=False):
+def docker_image(name: str, by_tag: bool = False) -> Optional[str]:
"""
Resolve in-tree prebuilt docker image to ``<registry>/<repository>@sha256:<digest>``,
or ``<registry>/<repository>:<tag>`` if `by_tag` is `True`.
+
+ Args:
+ name (str): The image to build.
+ by_tag (bool): If True, will apply a tag based on VERSION file.
+ Otherwise will apply a hash based on HASH file.
+ Returns:
+ Optional[str]: Image if it can be resolved, otherwise None.
"""
try:
with open(os.path.join(IMAGE_DIR, name, "REGISTRY")) as f:
registry = f.read().strip()
except OSError:
- with open(os.path.join(IMAGE_DIR, "REGISTRY")) as f:
- registry = f.read().strip()
+ try:
+ with open(os.path.join(IMAGE_DIR, "REGISTRY")) as f:
+ registry = f.read().strip()
+ except OSError:
+ return None
if not by_tag:
hashfile = os.path.join(IMAGE_DIR, name, "HASH")
@@ -34,7 +45,7 @@ def docker_image(name, by_tag=False):
with open(hashfile) as f:
return f"{registry}/{name}@{f.read().strip()}"
except OSError:
- raise Exception(f"Failed to read HASH file {hashfile}")
+ return None
try:
with open(os.path.join(IMAGE_DIR, name, "VERSION")) as f:
@@ -197,7 +208,7 @@ def stream_context_tar(topsrcdir, context_dir, out_file, image_name=None, args=N
@memoize
def image_paths():
"""Return a map of image name to paths containing their Dockerfile."""
- config = load_yaml("taskcluster", "ci", "docker-image", "kind.yml")
+ config = load_yaml("taskcluster", "kinds", "docker-image", "kind.yml")
return {
k: os.path.join(IMAGE_DIR, v.get("definition", k))
for k, v in config["tasks"].items()
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/hash.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/hash.py
index 5d884fc318..d42b2ecef9 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/hash.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/hash.py
@@ -39,10 +39,7 @@ def hash_paths(base_path, patterns):
raise Exception("%s did not match anything" % pattern)
for path in sorted(found):
h.update(
- "{} {}\n".format(
- hash_path(mozpath.abspath(mozpath.join(base_path, path))),
- mozpath.normsep(path),
- ).encode("utf-8")
+ f"{hash_path(mozpath.abspath(mozpath.join(base_path, path)))} {mozpath.normsep(path)}\n".encode()
)
return h.hexdigest()
@@ -55,4 +52,8 @@ def _find_matching_files(base_path, pattern):
@memoize
def _get_all_files(base_path):
- return [str(path) for path in Path(base_path).rglob("*") if path.is_file()]
+ return [
+ mozpath.normsep(str(path))
+ for path in Path(base_path).rglob("*")
+ if path.is_file()
+ ]
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/keyed_by.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/keyed_by.py
index 9b0c5a44fb..00c84ba980 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/keyed_by.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/keyed_by.py
@@ -66,8 +66,8 @@ def evaluate_keyed_by(
# Error out when only 'default' is specified as only alternatives,
# because we don't need to by-{keyed_by} there.
raise Exception(
- "Keyed-by '{}' unnecessary with only value 'default' "
- "found, when determining item {}".format(keyed_by, item_name)
+ f"Keyed-by '{keyed_by}' unnecessary with only value 'default' "
+ f"found, when determining item {item_name}"
)
if key is None:
@@ -76,22 +76,20 @@ def evaluate_keyed_by(
continue
else:
raise Exception(
- "No attribute {} and no value for 'default' found "
- "while determining item {}".format(keyed_by, item_name)
+ f"No attribute {keyed_by} and no value for 'default' found "
+ f"while determining item {item_name}"
)
matches = keymatch(alternatives, key)
if enforce_single_match and len(matches) > 1:
raise Exception(
- "Multiple matching values for {} {!r} found while "
- "determining item {}".format(keyed_by, key, item_name)
+ f"Multiple matching values for {keyed_by} {key!r} found while "
+ f"determining item {item_name}"
)
elif matches:
value = matches[0]
continue
raise Exception(
- "No {} matching {!r} nor 'default' found while determining item {}".format(
- keyed_by, key, item_name
- )
+ f"No {keyed_by} matching {key!r} nor 'default' found while determining item {item_name}"
)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/memoize.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/memoize.py
index 56b513e74c..a4bc50cc26 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/memoize.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/memoize.py
@@ -2,39 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
-# Imported from
-# https://searchfox.org/mozilla-central/rev/c3ebaf6de2d481c262c04bb9657eaf76bf47e2ac/python/mozbuild/mozbuild/util.py#923-949
-
-
import functools
-
-class memoize(dict):
- """A decorator to memoize the results of function calls depending
- on its arguments.
- Both functions and instance methods are handled, although in the
- instance method case, the results are cache in the instance itself.
- """
-
- def __init__(self, func):
- self.func = func
- functools.update_wrapper(self, func)
-
- def __call__(self, *args):
- if args not in self:
- self[args] = self.func(*args)
- return self[args]
-
- def method_call(self, instance, *args):
- name = "_%s" % self.func.__name__
- if not hasattr(instance, name):
- setattr(instance, name, {})
- cache = getattr(instance, name)
- if args not in cache:
- cache[args] = self.func(instance, *args)
- return cache[args]
-
- def __get__(self, instance, cls):
- return functools.update_wrapper(
- functools.partial(self.method_call, instance), self.func
- )
+memoize = functools.lru_cache(maxsize=None) # backwards compatibility shim
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/parameterization.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/parameterization.py
index 6233a98a40..1973f6f7df 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/parameterization.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/parameterization.py
@@ -20,6 +20,12 @@ def _recurse(val, param_fns):
if len(val) == 1:
for param_key, param_fn in param_fns.items():
if set(val.keys()) == {param_key}:
+ if isinstance(val[param_key], dict):
+ # handle `{"task-reference": {"<foo>": "bar"}}`
+ return {
+ param_fn(key): recurse(v)
+ for key, v in val[param_key].items()
+ }
return param_fn(val[param_key])
return {k: recurse(v) for k, v in val.items()}
else:
@@ -74,17 +80,14 @@ def resolve_task_references(label, task_def, task_id, decision_task_id, dependen
task_id = dependencies[dependency]
except KeyError:
raise KeyError(
- "task '{}' has no dependency named '{}'".format(
- label, dependency
- )
+ f"task '{label}' has no dependency named '{dependency}'"
)
- assert artifact_name.startswith(
- "public/"
- ), "artifact-reference only supports public artifacts, not `{}`".format(
- artifact_name
- )
- return get_artifact_url(task_id, artifact_name)
+ use_proxy = False
+ if not artifact_name.startswith("public/"):
+ use_proxy = True
+
+ return get_artifact_url(task_id, artifact_name, use_proxy=use_proxy)
return ARTIFACT_REFERENCE_PATTERN.sub(repl, val)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/schema.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/schema.py
index 3989f71182..02e79a3a27 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/schema.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/schema.py
@@ -74,7 +74,7 @@ def resolve_keyed_by(
For example, given item::
- job:
+ task:
test-platform: linux128
chunks:
by-test-platform:
@@ -82,10 +82,10 @@ def resolve_keyed_by(
win.*: 6
default: 12
- a call to `resolve_keyed_by(item, 'job.chunks', item['thing-name'])`
+ a call to `resolve_keyed_by(item, 'task.chunks', item['thing-name'])`
would mutate item in-place to::
- job:
+ task:
test-platform: linux128
chunks: 12
@@ -182,7 +182,7 @@ def check_schema(schema):
if not identifier_re.match(k) and not excepted(path):
raise RuntimeError(
"YAML schemas should use dashed lower-case identifiers, "
- "not {!r} @ {}".format(k, path)
+ f"not {k!r} @ {path}"
)
elif isinstance(k, (voluptuous.Optional, voluptuous.Required)):
check_identifier(path, k.schema)
@@ -191,9 +191,7 @@ def check_schema(schema):
check_identifier(path, v)
elif not excepted(path):
raise RuntimeError(
- "Unexpected type in YAML schema: {} @ {}".format(
- type(k).__name__, path
- )
+ f"Unexpected type in YAML schema: {type(k).__name__} @ {path}"
)
if isinstance(sch, collections.abc.Mapping):
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/set_name.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/set_name.py
new file mode 100644
index 0000000000..4c27a9cca1
--- /dev/null
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/set_name.py
@@ -0,0 +1,34 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Define a collection of set_name functions
+# Note: this is stored here instead of where it is used in the `from_deps`
+# transform to give consumers a chance to register their own `set_name`
+# handlers before the `from_deps` schema is created.
+SET_NAME_MAP = {}
+
+
+def set_name(name, schema=None):
+ def wrapper(func):
+ assert (
+ name not in SET_NAME_MAP
+ ), f"duplicate set_name function name {name} ({func} and {SET_NAME_MAP[name]})"
+ SET_NAME_MAP[name] = func
+ func.schema = schema
+ return func
+
+ return wrapper
+
+
+@set_name("strip-kind")
+def set_name_strip_kind(config, tasks, primary_dep, primary_kind):
+ if primary_dep.label.startswith(primary_kind):
+ return primary_dep.label[len(primary_kind) + 1 :]
+ else:
+ return primary_dep.label
+
+
+@set_name("retain-kind")
+def set_name_retain_kind(config, tasks, primary_dep, primary_kind):
+ return primary_dep.label
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/shell.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/shell.py
index d695767f05..16b71b7d6a 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/shell.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/shell.py
@@ -14,7 +14,7 @@ def _quote(s):
As a special case, if given an int, returns a string containing the int,
not enclosed in quotes.
"""
- if type(s) == int:
+ if isinstance(s, int):
return "%d" % s
# Empty strings need to be quoted to have any significance
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/taskcluster.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/taskcluster.py
index a830a473b3..b467e98a97 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/taskcluster.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/taskcluster.py
@@ -3,10 +3,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+import copy
import datetime
import functools
import logging
import os
+from typing import Dict, List, Union
import requests
import taskcluster_urls as liburls
@@ -53,9 +55,11 @@ def get_root_url(use_proxy):
logger.debug(
"Running in Taskcluster instance {}{}".format(
os.environ["TASKCLUSTER_ROOT_URL"],
- " with taskcluster-proxy"
- if "TASKCLUSTER_PROXY_URL" in os.environ
- else "",
+ (
+ " with taskcluster-proxy"
+ if "TASKCLUSTER_PROXY_URL" in os.environ
+ else ""
+ ),
)
)
return liburls.normalize_root_url(os.environ["TASKCLUSTER_ROOT_URL"])
@@ -136,22 +140,9 @@ def _handle_artifact(path, response):
def get_artifact_url(task_id, path, use_proxy=False):
artifact_tmpl = liburls.api(
- get_root_url(False), "queue", "v1", "task/{}/artifacts/{}"
+ get_root_url(use_proxy), "queue", "v1", "task/{}/artifacts/{}"
)
- data = artifact_tmpl.format(task_id, path)
- if use_proxy:
- # Until Bug 1405889 is deployed, we can't download directly
- # from the taskcluster-proxy. Work around by using the /bewit
- # endpoint instead.
- # The bewit URL is the body of a 303 redirect, which we don't
- # want to follow (which fetches a potentially large resource).
- response = _do_request(
- os.environ["TASKCLUSTER_PROXY_URL"] + "/bewit",
- data=data,
- allow_redirects=False,
- )
- return response.text
- return data
+ return artifact_tmpl.format(task_id, path)
def get_artifact(task_id, path, use_proxy=False):
@@ -244,6 +235,7 @@ def get_task_url(task_id, use_proxy=False):
return task_tmpl.format(task_id)
+@memoize
def get_task_definition(task_id, use_proxy=False):
response = _do_request(get_task_url(task_id, use_proxy))
return response.json()
@@ -327,11 +319,7 @@ def get_purge_cache_url(provisioner_id, worker_type, use_proxy=False):
def purge_cache(provisioner_id, worker_type, cache_name, use_proxy=False):
"""Requests a cache purge from the purge-caches service."""
if testing:
- logger.info(
- "Would have purged {}/{}/{}.".format(
- provisioner_id, worker_type, cache_name
- )
- )
+ logger.info(f"Would have purged {provisioner_id}/{worker_type}/{cache_name}.")
else:
logger.info(f"Purging {provisioner_id}/{worker_type}/{cache_name}.")
purge_cache_url = get_purge_cache_url(provisioner_id, worker_type, use_proxy)
@@ -371,3 +359,40 @@ def list_task_group_incomplete_tasks(task_group_id):
params = {"continuationToken": resp.get("continuationToken")}
else:
break
+
+
+@memoize
+def _get_deps(task_ids, use_proxy):
+ upstream_tasks = {}
+ for task_id in task_ids:
+ task_def = get_task_definition(task_id, use_proxy)
+ upstream_tasks[task_def["metadata"]["name"]] = task_id
+
+ upstream_tasks.update(_get_deps(tuple(task_def["dependencies"]), use_proxy))
+
+ return upstream_tasks
+
+
+def get_ancestors(
+ task_ids: Union[List[str], str], use_proxy: bool = False
+) -> Dict[str, str]:
+ """Gets the ancestor tasks of the given task_ids as a dictionary of label -> taskid.
+
+ Args:
+ task_ids (str or [str]): A single task id or a list of task ids to find the ancestors of.
+ use_proxy (bool): See get_root_url.
+
+ Returns:
+ dict: A dict whose keys are task labels and values are task ids.
+ """
+ upstream_tasks: Dict[str, str] = {}
+
+ if isinstance(task_ids, str):
+ task_ids = [task_ids]
+
+ for task_id in task_ids:
+ task_def = get_task_definition(task_id, use_proxy)
+
+ upstream_tasks.update(_get_deps(tuple(task_def["dependencies"]), use_proxy))
+
+ return copy.deepcopy(upstream_tasks)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/time.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/time.py
index e511978b5f..6639e5dddd 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/time.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/time.py
@@ -73,9 +73,7 @@ def value_of(input_str):
if unit not in ALIASES:
raise UnknownTimeMeasurement(
- "{} is not a valid time measure use one of {}".format(
- unit, sorted(ALIASES.keys())
- )
+ f"{unit} is not a valid time measure use one of {sorted(ALIASES.keys())}"
)
return ALIASES[unit](value)
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/treeherder.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/treeherder.py
index cff5f286cc..6bb6dbd137 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/treeherder.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/treeherder.py
@@ -42,22 +42,25 @@ def replace_group(treeherder_symbol, new_group):
return join_symbol(new_group, symbol)
-def inherit_treeherder_from_dep(job, dep_job):
- """Inherit treeherder defaults from dep_job"""
- treeherder = job.get("treeherder", {})
+def inherit_treeherder_from_dep(task, dep_task):
+ """Inherit treeherder defaults from dep_task"""
+ treeherder = task.get("treeherder", {})
dep_th_platform = (
- dep_job.task.get("extra", {})
+ dep_task.task.get("extra", {})
.get("treeherder", {})
.get("machine", {})
.get("platform", "")
)
dep_th_collection = list(
- dep_job.task.get("extra", {}).get("treeherder", {}).get("collection", {}).keys()
+ dep_task.task.get("extra", {})
+ .get("treeherder", {})
+ .get("collection", {})
+ .keys()
)[0]
treeherder.setdefault("platform", f"{dep_th_platform}/{dep_th_collection}")
treeherder.setdefault(
- "tier", dep_job.task.get("extra", {}).get("treeherder", {}).get("tier", 1)
+ "tier", dep_task.task.get("extra", {}).get("treeherder", {}).get("tier", 1)
)
# Does not set symbol
treeherder.setdefault("kind", "build")
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/vcs.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/vcs.py
index 2d967d2645..c2fd0d3236 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/vcs.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/vcs.py
@@ -10,9 +10,6 @@ import subprocess
from abc import ABC, abstractmethod, abstractproperty
from shutil import which
-import requests
-from redo import retry
-
from taskgraph.util.path import ancestors
PUSHLOG_TMPL = "{}/json-pushes?version=2&changeset={}&tipsonly=1&full=1"
@@ -21,7 +18,7 @@ logger = logging.getLogger(__name__)
class Repository(ABC):
- # Both mercurial and git use sha1 as revision idenfiers. Luckily, both define
+ # Both mercurial and git use sha1 as revision identifiers. Luckily, both define
# the same value as the null revision.
#
# https://github.com/git/git/blob/dc04167d378fb29d30e1647ff6ff51dd182bc9a3/t/oid-info/hash-info#L7
@@ -519,34 +516,3 @@ def get_repository(path):
return GitRepository(path)
raise RuntimeError("Current directory is neither a git or hg repository")
-
-
-def find_hg_revision_push_info(repository, revision):
- """Given the parameters for this action and a revision, find the
- pushlog_id of the revision."""
- pushlog_url = PUSHLOG_TMPL.format(repository, revision)
-
- def query_pushlog(url):
- r = requests.get(pushlog_url, timeout=60)
- r.raise_for_status()
- return r
-
- r = retry(
- query_pushlog,
- args=(pushlog_url,),
- attempts=5,
- sleeptime=10,
- )
- pushes = r.json()["pushes"]
- if len(pushes) != 1:
- raise RuntimeError(
- "Unable to find a single pushlog_id for {} revision {}: {}".format(
- repository, revision, pushes
- )
- )
- pushid = list(pushes.keys())[0]
- return {
- "pushdate": pushes[pushid]["date"],
- "pushid": pushid,
- "user": pushes[pushid]["user"],
- }
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/verify.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/verify.py
index e6705c16cf..b5bb0889ae 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/verify.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/verify.py
@@ -134,10 +134,8 @@ def verify_task_graph_symbol(task, taskgraph, scratch_pad, graph_config, paramet
collection_keys = tuple(sorted(treeherder.get("collection", {}).keys()))
if len(collection_keys) != 1:
raise Exception(
- "Task {} can't be in multiple treeherder collections "
- "(the part of the platform after `/`): {}".format(
- task.label, collection_keys
- )
+ f"Task {task.label} can't be in multiple treeherder collections "
+ f"(the part of the platform after `/`): {collection_keys}"
)
platform = treeherder.get("machine", {}).get("platform")
group_symbol = treeherder.get("groupSymbol")
@@ -175,9 +173,7 @@ def verify_trust_domain_v2_routes(
if route.startswith(route_prefix):
if route in scratch_pad:
raise Exception(
- "conflict between {}:{} for route: {}".format(
- task.label, scratch_pad[route], route
- )
+ f"conflict between {task.label}:{scratch_pad[route]} for route: {route}"
)
else:
scratch_pad[route] = task.label
@@ -206,9 +202,7 @@ def verify_routes_notification_filters(
route_filter = route.split(".")[-1]
if route_filter not in valid_filters:
raise Exception(
- "{} has invalid notification filter ({})".format(
- task.label, route_filter
- )
+ f"{task.label} has invalid notification filter ({route_filter})"
)
@@ -235,12 +229,7 @@ def verify_dependency_tiers(task, taskgraph, scratch_pad, graph_config, paramete
continue
if tier < tiers[d]:
raise Exception(
- "{} (tier {}) cannot depend on {} (tier {})".format(
- task.label,
- printable_tier(tier),
- d,
- printable_tier(tiers[d]),
- )
+ f"{task.label} (tier {printable_tier(tier)}) cannot depend on {d} (tier {printable_tier(tiers[d])})"
)
@@ -262,11 +251,7 @@ def verify_toolchain_alias(task, taskgraph, scratch_pad, graph_config, parameter
if key in scratch_pad:
raise Exception(
"Duplicate toolchain-alias in tasks "
- "`{}`and `{}`: {}".format(
- task.label,
- scratch_pad[key],
- key,
- )
+ f"`{task.label}`and `{scratch_pad[key]}`: {key}"
)
else:
scratch_pad[key] = task.label
diff --git a/third_party/python/taskcluster_taskgraph/taskgraph/util/yaml.py b/third_party/python/taskcluster_taskgraph/taskgraph/util/yaml.py
index 141c7a16d3..a733521527 100644
--- a/third_party/python/taskcluster_taskgraph/taskgraph/util/yaml.py
+++ b/third_party/python/taskcluster_taskgraph/taskgraph/util/yaml.py
@@ -5,7 +5,10 @@
import os
-from yaml.loader import SafeLoader
+try:
+ from yaml import CSafeLoader as SafeLoader
+except ImportError:
+ from yaml import SafeLoader
class UnicodeLoader(SafeLoader):
diff --git a/third_party/rust/ahash/.cargo-checksum.json b/third_party/rust/ahash/.cargo-checksum.json
index d2fa45cb86..f72f808ffc 100644
--- a/third_party/rust/ahash/.cargo-checksum.json
+++ b/third_party/rust/ahash/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"a519809f46c9aad28d6c48748f330fe31e05029d234b6d1743522ec403441744","FAQ.md":"9eb41898523ee209a0a937f9bcb78afe45ad55ca0556f8a4d4063558098f6d1e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"72185284f100e149998fe5301f70489e617cc4415b51cc77e967c63c6e970a67","build.rs":"f80cb1cdb731a63d16513f1f0b0871d9c077d2c6bf2312af40a202f9c0fefe49","rustfmt.toml":"e090969e99df9360705680cc0097cfaddae10c22dc2e01470592cf3b9787fd36","src/aes_hash.rs":"0b11ce066931396222d2bed7eff678fdd7c8351819485efb721f62a30551866b","src/convert.rs":"f0e78840046493d0679a9ec077c8164cf57cf30d5e852b11bfadfdd996d29bd1","src/fallback_hash.rs":"ec00691bd555c69f7446afe893b6631cb84207cb7b512260dec8ef488e1905f3","src/hash_map.rs":"ed0c79c41c2218ad9591a585670a2b9b983807c9725880b780138a44c126cbfd","src/hash_quality_test.rs":"61695e5cac46ea25021a9d04199fb00c513e0c0c9c0f67aca0c647b9d2f7dd5a","src/hash_set.rs":"dc3d33e290aad62457ab1f5e64d3e33eb79e28c9468bfc8686339f0bbd8b19aa","src/lib.rs":"9fec7d1d412e414231c9b929081b1daa7c3b788a9f91eedd79a55efdf5d0d291","src/operations.rs":"10772e65b8b7106f195428c5eb8dbf6cbd49dd5a2165ac750e54af5995210f88","src/random_state.rs":"ce9689147659efa975887debe1481daddca09386ea8e1d5b4ee90ebeda6c8745","src/specialize.rs":"38d3b56ef4f264d564f48dbcb8ac137928babf90635090c9771c1a62140d1f30","tests/bench.rs":"0851dffebaffd7a437f6f9946ed5e03a957e9a6eb0da7911451af58778c411ec","tests/map_tests.rs":"e0f155f964dd965740b072ee1da110a8c6ef34491c95219f7c89064112c7840f","tests/nopanic.rs":"3363675c4c1a197b86604a0aebbe958fb5ec7c01a414fbfd70e9eb8a29707400"},"package":"891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"} \ No newline at end of file
+{"files":{"Cargo.toml":"ddcbd9309cebf3ffd26f87e09bb8f971793535955ebfd9a7196eba31a53471f8","FAQ.md":"9eb41898523ee209a0a937f9bcb78afe45ad55ca0556f8a4d4063558098f6d1e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0444c6991eead6822f7b9102e654448d51624431119546492e8b231db42c48bb","README.md":"d7f74d616a751bcca23d5d3b58a6daf556356a526c5f0b6aa0504715d176549a","build.rs":"23cbf4cf1b742e2c4da8bc58d06d1d021479dec80cec6a0bc3704c7172e2864a","rustfmt.toml":"e090969e99df9360705680cc0097cfaddae10c22dc2e01470592cf3b9787fd36","src/aes_hash.rs":"013602aec42150e59ba9ed6135525a624a4b42c1b1328b9857ec238aa12c3178","src/convert.rs":"54e49f93d51665366923d4d815cfd67790d3c769e84ab4386ba97f928d17d1bd","src/fallback_hash.rs":"a82451f6458a6e7a7e7da82a3c982e9bb825a2092ab79c41459d8011775fb0b1","src/hash_map.rs":"5ee97baa64fa528ba9c01bd018332c4974846c4813c6f8c30cee9f3546598f1c","src/hash_quality_test.rs":"1a560a181a804791bc6ad797df5352cdd87123fed7f19f659de0c2d883248bed","src/hash_set.rs":"360e55d066b44624f06e49efa140c03fda635fb17a59622cc29a83830bd1f263","src/lib.rs":"e2f4e7bfcf2807c73e3b8d3b1bd83c6789313b6b55edd59e15e04146e55e01b6","src/operations.rs":"38ed2b48a13d826c48ede5f304c9c2572c0c8f64ac8ac5a1ed4e112e536f3a97","src/random_state.rs":"03f40a654cfca2e00a2dabd21c85368ee50b8b6289efe98ea1745b25c721b9c6","src/specialize.rs":"56354db8a0f7e6ee1340a08f2ab6f79a0ff439fd61badac5e7e59fe4f4a653ba","tests/bench.rs":"7a425f564201560f9a8fb6c77f91f29bb88ec815b10bd27d15740c922a4f928e","tests/map_tests.rs":"e56b6f700e3b1176210e4b266d7a42b3263e966e5e565d53b1bc27af7a87168e","tests/nopanic.rs":"0d28a46248d77283941db1d9fd154c68b965c81a0e3db1fe4a43e06fc448da8f"},"package":"e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"} \ No newline at end of file
diff --git a/third_party/rust/ahash/Cargo.toml b/third_party/rust/ahash/Cargo.toml
index 5830a500d9..279954f9a7 100644
--- a/third_party/rust/ahash/Cargo.toml
+++ b/third_party/rust/ahash/Cargo.toml
@@ -11,8 +11,9 @@
[package]
edition = "2018"
+rust-version = "1.60.0"
name = "ahash"
-version = "0.7.8"
+version = "0.8.11"
authors = ["Tom Kaitchuck <Tom.Kaitchuck@gmail.com>"]
build = "./build.rs"
exclude = [
@@ -84,8 +85,33 @@ name = "map"
path = "tests/map_tests.rs"
harness = false
+[dependencies.atomic-polyfill]
+version = "1.0.1"
+optional = true
+
+[dependencies.cfg-if]
+version = "1.0"
+
+[dependencies.const-random]
+version = "0.1.17"
+optional = true
+
+[dependencies.getrandom]
+version = "0.2.7"
+optional = true
+
+[dependencies.serde]
+version = "1.0.117"
+optional = true
+
+[dependencies.zerocopy]
+version = "0.7.31"
+features = ["simd"]
+default-features = false
+
[dev-dependencies.criterion]
version = "0.3.2"
+features = ["html_reports"]
[dev-dependencies.fnv]
version = "1.0.5"
@@ -93,14 +119,20 @@ version = "1.0.5"
[dev-dependencies.fxhash]
version = "0.2.1"
+[dev-dependencies.hashbrown]
+version = "0.14.3"
+
[dev-dependencies.hex]
version = "0.4.2"
[dev-dependencies.no-panic]
version = "0.1.10"
+[dev-dependencies.pcg-mwc]
+version = "0.2.1"
+
[dev-dependencies.rand]
-version = "0.7.3"
+version = "0.8.5"
[dev-dependencies.seahash]
version = "4.0"
@@ -108,8 +140,11 @@ version = "4.0"
[dev-dependencies.serde_json]
version = "1.0.59"
+[dev-dependencies.smallvec]
+version = "1.13.1"
+
[build-dependencies.version_check]
-version = "0.9"
+version = "0.9.4"
[features]
atomic-polyfill = [
@@ -117,33 +152,16 @@ atomic-polyfill = [
"once_cell/atomic-polyfill",
]
compile-time-rng = ["const-random"]
-default = ["std"]
+default = [
+ "std",
+ "runtime-rng",
+]
+nightly-arm-aes = []
+no-rng = []
+runtime-rng = ["getrandom"]
std = []
-[target."cfg(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\"))".dependencies.const-random]
-version = "0.1.12"
-optional = true
-
-[target."cfg(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\"))".dependencies.getrandom]
-version = "0.2.3"
-
-[target."cfg(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\"))".dependencies.serde]
-version = "1.0.117"
-optional = true
-
[target."cfg(not(all(target_arch = \"arm\", target_os = \"none\")))".dependencies.once_cell]
-version = "1.13.1"
+version = "1.18.0"
features = ["alloc"]
default-features = false
-
-[target."cfg(not(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\")))".dependencies.atomic-polyfill]
-version = "1.0.1"
-optional = true
-
-[target."cfg(not(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\")))".dependencies.const-random]
-version = "0.1.12"
-optional = true
-
-[target."cfg(not(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\")))".dependencies.serde]
-version = "1.0.117"
-optional = true
diff --git a/third_party/rust/ahash/LICENSE-MIT b/third_party/rust/ahash/LICENSE-MIT
index 5afc2a7b0a..cba20106dd 100644
--- a/third_party/rust/ahash/LICENSE-MIT
+++ b/third_party/rust/ahash/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright (c) 2016 Amanieu d'Antras
+Copyright (c) 2018 Tom Kaitchuck
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
diff --git a/third_party/rust/ahash/README.md b/third_party/rust/ahash/README.md
index be365a79f1..aa071cf51d 100644
--- a/third_party/rust/ahash/README.md
+++ b/third_party/rust/ahash/README.md
@@ -1,4 +1,4 @@
-# aHash ![Build Status](https://img.shields.io/github/workflow/status/tkaitchuck/ahash/Rust) ![Licence](https://img.shields.io/crates/l/ahash) ![Downloads](https://img.shields.io/crates/d/ahash)
+# aHash ![Build Status](https://img.shields.io/github/actions/workflow/status/tkaitchuck/aHash/rust.yml?branch=master) ![Licence](https://img.shields.io/crates/l/ahash) ![Downloads](https://img.shields.io/crates/d/ahash)
AHash is the [fastest](https://github.com/tkaitchuck/aHash/blob/master/compare/readme.md#Speed),
[DOS resistant hash](https://github.com/tkaitchuck/aHash/wiki/How-aHash-is-resists-DOS-attacks) currently available in Rust.
@@ -53,18 +53,17 @@ map.insert(56, 78);
The aHash package has the following flags:
* `std`: This enables features which require the standard library. (On by default) This includes providing the utility classes `AHashMap` and `AHashSet`.
* `serde`: Enables `serde` support for the utility classes `AHashMap` and `AHashSet`.
-* `compile-time-rng`: Whenever possible aHash will seed hashers with random numbers using the [getrandom](https://github.com/rust-random/getrandom) crate.
-This is possible for OS targets which provide a source of randomness. (see the [full list](https://docs.rs/getrandom/0.2.0/getrandom/#supported-targets).)
-For OS targets without access to a random number generator, `compile-time-rng` provides an alternative.
+* `runtime-rng`: To obtain a seed for Hashers will obtain randomness from the operating system. (On by default)
+This is done using the [getrandom](https://github.com/rust-random/getrandom) crate.
+* `compile-time-rng`: For OS targets without access to a random number generator, `compile-time-rng` provides an alternative.
If `getrandom` is unavailable and `compile-time-rng` is enabled, aHash will generate random numbers at compile time and embed them in the binary.
+* `nightly-arm-aes`: To use AES instructions on 32-bit ARM, which requires nightly. This is not needed on AArch64.
This allows for DOS resistance even if there is no random number generator available at runtime (assuming the compiled binary is not public).
-This makes the binary non-deterministic, unless `getrandom` is available for the target in which case the flag does nothing.
-(If non-determinism is a problem see [constrandom's documentation](https://github.com/tkaitchuck/constrandom#deterministic-builds))
+This makes the binary non-deterministic. (If non-determinism is a problem see [constrandom's documentation](https://github.com/tkaitchuck/constrandom#deterministic-builds))
-**NOTE:** If `getrandom` is unavailable and `compile-time-rng` is disabled aHash will fall back on using the numeric
-value of memory addresses as a source of randomness. This is somewhat strong if ALSR is turned on (it is by default)
-but for embedded platforms this will result in weak keys. As a result, it is recommended to use `compile-time-rng` anytime
-random numbers will not be available at runtime.
+If both `runtime-rng` and `compile-time-rng` are enabled the `runtime-rng` will take precedence and `compile-time-rng` will do nothing.
+If neither flag is set, seeds can be supplied by the application. [Multiple apis](https://docs.rs/ahash/latest/ahash/random_state/struct.RandomState.html)
+are available to do this.
## Comparison with other hashers
diff --git a/third_party/rust/ahash/build.rs b/third_party/rust/ahash/build.rs
index 6aba02526b..a136b3666c 100644
--- a/third_party/rust/ahash/build.rs
+++ b/third_party/rust/ahash/build.rs
@@ -4,34 +4,8 @@ use std::env;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
- if let Some(channel) = version_check::Channel::read() {
- if channel.supports_features() {
- println!("cargo:rustc-cfg=feature=\"specialize\"");
- if version_check::Version::read().map_or(false, |v| v.at_most("1.77.9")) {
- println!("cargo:rustc-cfg=feature=\"stdsimd\"");
- }
- }
- }
- let os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set");
- if os.eq_ignore_ascii_case("linux")
- || os.eq_ignore_ascii_case("android")
- || os.eq_ignore_ascii_case("windows")
- || os.eq_ignore_ascii_case("macos")
- || os.eq_ignore_ascii_case("ios")
- || os.eq_ignore_ascii_case("freebsd")
- || os.eq_ignore_ascii_case("openbsd")
- || os.eq_ignore_ascii_case("dragonfly")
- || os.eq_ignore_ascii_case("solaris")
- || os.eq_ignore_ascii_case("illumos")
- || os.eq_ignore_ascii_case("fuchsia")
- || os.eq_ignore_ascii_case("redox")
- || os.eq_ignore_ascii_case("cloudabi")
- || os.eq_ignore_ascii_case("haiku")
- || os.eq_ignore_ascii_case("vxworks")
- || os.eq_ignore_ascii_case("emscripten")
- || os.eq_ignore_ascii_case("wasi")
- {
- println!("cargo:rustc-cfg=feature=\"runtime-rng\"");
+ if let Some(true) = version_check::supports_feature("specialize") {
+ println!("cargo:rustc-cfg=feature=\"specialize\"");
}
let arch = env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH was not set");
if arch.eq_ignore_ascii_case("x86_64")
@@ -43,5 +17,4 @@ fn main() {
{
println!("cargo:rustc-cfg=feature=\"folded_multiply\"");
}
-
}
diff --git a/third_party/rust/ahash/src/aes_hash.rs b/third_party/rust/ahash/src/aes_hash.rs
index 7e619b520b..daf3ae4fad 100644
--- a/third_party/rust/ahash/src/aes_hash.rs
+++ b/third_party/rust/ahash/src/aes_hash.rs
@@ -1,10 +1,8 @@
use crate::convert::*;
-#[cfg(feature = "specialize")]
-use crate::fallback_hash::MULTIPLE;
use crate::operations::*;
+use crate::random_state::PI;
use crate::RandomState;
use core::hash::Hasher;
-use crate::random_state::PI;
/// A `Hasher` for hashing an arbitrary stream of bytes.
///
@@ -50,7 +48,7 @@ impl AHasher {
/// println!("Hash is {:x}!", hasher.finish());
/// ```
#[inline]
- pub fn new_with_keys(key1: u128, key2: u128) -> Self {
+ pub(crate) fn new_with_keys(key1: u128, key2: u128) -> Self {
let pi: [u128; 2] = PI.convert();
let key1 = key1 ^ pi[0];
let key2 = key2 ^ pi[1];
@@ -70,7 +68,6 @@ impl AHasher {
}
}
-
#[inline]
pub(crate) fn from_random_state(rand_state: &RandomState) -> Self {
let key1 = [rand_state.k0, rand_state.k1].convert();
@@ -83,32 +80,24 @@ impl AHasher {
}
#[inline(always)]
- fn add_in_length(&mut self, length: u64) {
- //This will be scrambled by the next AES round.
- let mut enc: [u64; 2] = self.enc.convert();
- enc[0] = enc[0].wrapping_add(length);
- self.enc = enc.convert();
- }
-
- #[inline(always)]
fn hash_in(&mut self, new_value: u128) {
- self.enc = aesenc(self.enc, new_value);
+ self.enc = aesdec(self.enc, new_value);
self.sum = shuffle_and_add(self.sum, new_value);
}
#[inline(always)]
fn hash_in_2(&mut self, v1: u128, v2: u128) {
- self.enc = aesenc(self.enc, v1);
+ self.enc = aesdec(self.enc, v1);
self.sum = shuffle_and_add(self.sum, v1);
- self.enc = aesenc(self.enc, v2);
+ self.enc = aesdec(self.enc, v2);
self.sum = shuffle_and_add(self.sum, v2);
}
#[inline]
#[cfg(feature = "specialize")]
fn short_finish(&self) -> u64 {
- let combined = aesdec(self.sum, self.enc);
- let result: [u64; 2] = aesenc(combined, combined).convert();
+ let combined = aesenc(self.sum, self.enc);
+ let result: [u64; 2] = aesdec(combined, combined).convert();
result[0]
}
}
@@ -138,7 +127,11 @@ impl Hasher for AHasher {
}
#[inline]
- #[cfg(any(target_pointer_width = "64", target_pointer_width = "32", target_pointer_width = "16"))]
+ #[cfg(any(
+ target_pointer_width = "64",
+ target_pointer_width = "32",
+ target_pointer_width = "16"
+ ))]
fn write_usize(&mut self, i: usize) {
self.write_u64(i as u64);
}
@@ -159,7 +152,8 @@ impl Hasher for AHasher {
fn write(&mut self, input: &[u8]) {
let mut data = input;
let length = data.len();
- self.add_in_length(length as u64);
+ add_in_length(&mut self.enc, length as u64);
+
//A 'binary search' on sizes reduces the number of comparisons.
if data.len() <= 8 {
let value = read_small(data);
@@ -180,10 +174,10 @@ impl Hasher for AHasher {
sum[1] = shuffle_and_add(sum[1], tail[3]);
while data.len() > 64 {
let (blocks, rest) = data.read_u128x4();
- current[0] = aesenc(current[0], blocks[0]);
- current[1] = aesenc(current[1], blocks[1]);
- current[2] = aesenc(current[2], blocks[2]);
- current[3] = aesenc(current[3], blocks[3]);
+ current[0] = aesdec(current[0], blocks[0]);
+ current[1] = aesdec(current[1], blocks[1]);
+ current[2] = aesdec(current[2], blocks[2]);
+ current[3] = aesdec(current[3], blocks[3]);
sum[0] = shuffle_and_add(sum[0], blocks[0]);
sum[1] = shuffle_and_add(sum[1], blocks[1]);
sum[0] = shuffle_and_add(sum[0], blocks[2]);
@@ -214,9 +208,9 @@ impl Hasher for AHasher {
}
#[inline]
fn finish(&self) -> u64 {
- let combined = aesdec(self.sum, self.enc);
- let result: [u64; 2] = aesenc(aesenc(combined, self.key), combined).convert();
- result[1]
+ let combined = aesenc(self.sum, self.enc);
+ let result: [u64; 2] = aesdec(aesdec(combined, self.key), combined).convert();
+ result[0]
}
}
@@ -231,8 +225,7 @@ pub(crate) struct AHasherU64 {
impl Hasher for AHasherU64 {
#[inline]
fn finish(&self) -> u64 {
- let rot = (self.pad & 63) as u32;
- self.buffer.rotate_left(rot)
+ folded_multiply(self.buffer, self.pad)
}
#[inline]
@@ -327,7 +320,7 @@ pub(crate) struct AHasherStr(pub AHasher);
impl Hasher for AHasherStr {
#[inline]
fn finish(&self) -> u64 {
- let result : [u64; 2] = self.0.enc.convert();
+ let result: [u64; 2] = self.0.enc.convert();
result[0]
}
@@ -335,14 +328,15 @@ impl Hasher for AHasherStr {
fn write(&mut self, bytes: &[u8]) {
if bytes.len() > 8 {
self.0.write(bytes);
- self.0.enc = aesdec(self.0.sum, self.0.enc);
- self.0.enc = aesenc(aesenc(self.0.enc, self.0.key), self.0.enc);
+ self.0.enc = aesenc(self.0.sum, self.0.enc);
+ self.0.enc = aesdec(aesdec(self.0.enc, self.0.key), self.0.enc);
} else {
- self.0.add_in_length(bytes.len() as u64);
+ add_in_length(&mut self.0.enc, bytes.len() as u64);
+
let value = read_small(bytes).convert();
self.0.sum = shuffle_and_add(self.0.sum, value);
- self.0.enc = aesdec(self.0.sum, self.0.enc);
- self.0.enc = aesenc(aesenc(self.0.enc, self.0.key), self.0.enc);
+ self.0.enc = aesenc(self.0.sum, self.0.enc);
+ self.0.enc = aesdec(aesdec(self.0.enc, self.0.key), self.0.enc);
}
}
@@ -437,4 +431,3 @@ mod tests {
assert_eq!(bytes, 0x6464646464646464);
}
}
-
diff --git a/third_party/rust/ahash/src/convert.rs b/third_party/rust/ahash/src/convert.rs
index 4c0a00eb7c..712eae163b 100644
--- a/third_party/rust/ahash/src/convert.rs
+++ b/third_party/rust/ahash/src/convert.rs
@@ -7,17 +7,13 @@ macro_rules! convert {
impl Convert<$b> for $a {
#[inline(always)]
fn convert(self) -> $b {
- unsafe {
- core::mem::transmute::<$a, $b>(self)
- }
+ zerocopy::transmute!(self)
}
}
impl Convert<$a> for $b {
#[inline(always)]
fn convert(self) -> $a {
- unsafe {
- core::mem::transmute::<$b, $a>(self)
- }
+ zerocopy::transmute!(self)
}
}
};
@@ -69,8 +65,7 @@ macro_rules! as_array {
{
#[inline(always)]
fn as_array<T>(slice: &[T]) -> &[T; $len] {
- assert_eq!(slice.len(), $len);
- unsafe { &*(slice.as_ptr() as *const [_; $len]) }
+ core::convert::TryFrom::try_from(slice).unwrap()
}
as_array($input)
}
diff --git a/third_party/rust/ahash/src/fallback_hash.rs b/third_party/rust/ahash/src/fallback_hash.rs
index aad9efc859..bc5cbfeeec 100644
--- a/third_party/rust/ahash/src/fallback_hash.rs
+++ b/third_party/rust/ahash/src/fallback_hash.rs
@@ -1,12 +1,11 @@
use crate::convert::*;
use crate::operations::folded_multiply;
use crate::operations::read_small;
+use crate::operations::MULTIPLE;
use crate::random_state::PI;
use crate::RandomState;
use core::hash::Hasher;
-///This constant come from Kunth's prng (Empirically it works better than those from splitmix32).
-pub(crate) const MULTIPLE: u64 = 6364136223846793005;
const ROT: u32 = 23; //17
/// A `Hasher` for hashing an arbitrary stream of bytes.
@@ -31,7 +30,7 @@ impl AHasher {
/// Creates a new hasher keyed to the provided key.
#[inline]
#[allow(dead_code)] // Is not called if non-fallback hash is used.
- pub fn new_with_keys(key1: u128, key2: u128) -> AHasher {
+ pub(crate) fn new_with_keys(key1: u128, key2: u128) -> AHasher {
let pi: [u128; 2] = PI.convert();
let key1: [u64; 2] = (key1 ^ pi[0]).convert();
let key2: [u64; 2] = (key2 ^ pi[1]).convert();
@@ -57,8 +56,8 @@ impl AHasher {
#[allow(dead_code)] // Is not called if non-fallback hash is used.
pub(crate) fn from_random_state(rand_state: &RandomState) -> AHasher {
AHasher {
- buffer: rand_state.k0,
- pad: rand_state.k1,
+ buffer: rand_state.k1,
+ pad: rand_state.k0,
extra_keys: [rand_state.k2, rand_state.k3],
}
}
@@ -93,19 +92,10 @@ impl AHasher {
/// attacker somehow knew part of (but not all) the contents of the buffer before hand,
/// they would not be able to predict any of the bits in the buffer at the end.
#[inline(always)]
- #[cfg(feature = "folded_multiply")]
fn update(&mut self, new_data: u64) {
self.buffer = folded_multiply(new_data ^ self.buffer, MULTIPLE);
}
- #[inline(always)]
- #[cfg(not(feature = "folded_multiply"))]
- fn update(&mut self, new_data: u64) {
- let d1 = (new_data ^ self.buffer).wrapping_mul(MULTIPLE);
- self.pad = (self.pad ^ d1).rotate_left(8).wrapping_mul(MULTIPLE);
- self.buffer = (self.buffer ^ self.pad).rotate_left(24);
- }
-
/// Similar to the above this function performs an update using a "folded multiply".
/// However it takes in 128 bits of data instead of 64. Both halves must be masked.
///
@@ -118,25 +108,16 @@ impl AHasher {
/// can't be changed by the same set of input bits. To cancel this sequence with subsequent input would require
/// knowing the keys.
#[inline(always)]
- #[cfg(feature = "folded_multiply")]
fn large_update(&mut self, new_data: u128) {
let block: [u64; 2] = new_data.convert();
let combined = folded_multiply(block[0] ^ self.extra_keys[0], block[1] ^ self.extra_keys[1]);
self.buffer = (self.buffer.wrapping_add(self.pad) ^ combined).rotate_left(ROT);
}
- #[inline(always)]
- #[cfg(not(feature = "folded_multiply"))]
- fn large_update(&mut self, new_data: u128) {
- let block: [u64; 2] = new_data.convert();
- self.update(block[0] ^ self.extra_keys[0]);
- self.update(block[1] ^ self.extra_keys[1]);
- }
-
#[inline]
#[cfg(feature = "specialize")]
fn short_finish(&self) -> u64 {
- self.buffer.wrapping_add(self.pad)
+ folded_multiply(self.buffer, self.pad)
}
}
@@ -170,7 +151,11 @@ impl Hasher for AHasher {
}
#[inline]
- #[cfg(any(target_pointer_width = "64", target_pointer_width = "32", target_pointer_width = "16"))]
+ #[cfg(any(
+ target_pointer_width = "64",
+ target_pointer_width = "32",
+ target_pointer_width = "16"
+ ))]
fn write_usize(&mut self, i: usize) {
self.write_u64(i as u64);
}
@@ -208,18 +193,10 @@ impl Hasher for AHasher {
}
#[inline]
- #[cfg(feature = "folded_multiply")]
fn finish(&self) -> u64 {
let rot = (self.buffer & 63) as u32;
folded_multiply(self.buffer, self.pad).rotate_left(rot)
}
-
- #[inline]
- #[cfg(not(feature = "folded_multiply"))]
- fn finish(&self) -> u64 {
- let rot = (self.buffer & 63) as u32;
- (self.buffer.wrapping_mul(MULTIPLE) ^ self.pad).rotate_left(rot)
- }
}
#[cfg(feature = "specialize")]
@@ -233,8 +210,8 @@ pub(crate) struct AHasherU64 {
impl Hasher for AHasherU64 {
#[inline]
fn finish(&self) -> u64 {
- let rot = (self.pad & 63) as u32;
- self.buffer.rotate_left(rot)
+ folded_multiply(self.buffer, self.pad)
+ //self.buffer
}
#[inline]
@@ -338,8 +315,7 @@ impl Hasher for AHasherStr {
self.0.write(bytes)
} else {
let value = read_small(bytes);
- self.0.buffer = folded_multiply(value[0] ^ self.0.buffer,
- value[1] ^ self.0.extra_keys[1]);
+ self.0.buffer = folded_multiply(value[0] ^ self.0.buffer, value[1] ^ self.0.extra_keys[1]);
self.0.pad = self.0.pad.wrapping_add(bytes.len() as u64);
}
}
@@ -365,7 +341,6 @@ impl Hasher for AHasherStr {
#[cfg(test)]
mod tests {
- use crate::convert::Convert;
use crate::fallback_hash::*;
#[test]
diff --git a/third_party/rust/ahash/src/hash_map.rs b/third_party/rust/ahash/src/hash_map.rs
index ec8fa433bb..2b6fbdc89f 100644
--- a/third_party/rust/ahash/src/hash_map.rs
+++ b/third_party/rust/ahash/src/hash_map.rs
@@ -1,4 +1,5 @@
use std::borrow::Borrow;
+use std::collections::hash_map::{IntoKeys, IntoValues};
use std::collections::{hash_map, HashMap};
use std::fmt::{self, Debug};
use std::hash::{BuildHasher, Hash};
@@ -25,6 +26,24 @@ impl<K, V> From<HashMap<K, V, crate::RandomState>> for AHashMap<K, V> {
}
}
+impl<K, V, const N: usize> From<[(K, V); N]> for AHashMap<K, V>
+where
+ K: Eq + Hash,
+{
+ /// # Examples
+ ///
+ /// ```
+ /// use ahash::AHashMap;
+ ///
+ /// let map1 = AHashMap::from([(1, 2), (3, 4)]);
+ /// let map2: AHashMap<_, _> = [(1, 2), (3, 4)].into();
+ /// assert_eq!(map1, map2);
+ /// ```
+ fn from(arr: [(K, V); N]) -> Self {
+ Self::from_iter(arr)
+ }
+}
+
impl<K, V> Into<HashMap<K, V, crate::RandomState>> for AHashMap<K, V> {
fn into(self) -> HashMap<K, V, crate::RandomState> {
self.0
@@ -32,12 +51,16 @@ impl<K, V> Into<HashMap<K, V, crate::RandomState>> for AHashMap<K, V> {
}
impl<K, V> AHashMap<K, V, RandomState> {
+ /// This crates a hashmap using [RandomState::new] which obtains its keys from [RandomSource].
+ /// See the documentation in [RandomSource] for notes about key strength.
pub fn new() -> Self {
- AHashMap(HashMap::with_hasher(RandomState::default()))
+ AHashMap(HashMap::with_hasher(RandomState::new()))
}
+ /// This crates a hashmap with the specified capacity using [RandomState::new].
+ /// See the documentation in [RandomSource] for notes about key strength.
pub fn with_capacity(capacity: usize) -> Self {
- AHashMap(HashMap::with_capacity_and_hasher(capacity, RandomState::default()))
+ AHashMap(HashMap::with_capacity_and_hasher(capacity, RandomState::new()))
}
}
@@ -145,8 +168,6 @@ where
/// types that can be `==` without being identical. See the [module-level
/// documentation] for more.
///
- /// [module-level documentation]: crate::collections#insert-and-complex-keys
- ///
/// # Examples
///
/// ```
@@ -165,6 +186,68 @@ where
self.0.insert(k, v)
}
+ /// Creates a consuming iterator visiting all the keys in arbitrary order.
+ /// The map cannot be used after calling this.
+ /// The iterator element type is `K`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let map = HashMap::from([
+ /// ("a", 1),
+ /// ("b", 2),
+ /// ("c", 3),
+ /// ]);
+ ///
+ /// let mut vec: Vec<&str> = map.into_keys().collect();
+ /// // The `IntoKeys` iterator produces keys in arbitrary order, so the
+ /// // keys must be sorted to test them against a sorted array.
+ /// vec.sort_unstable();
+ /// assert_eq!(vec, ["a", "b", "c"]);
+ /// ```
+ ///
+ /// # Performance
+ ///
+ /// In the current implementation, iterating over keys takes O(capacity) time
+ /// instead of O(len) because it internally visits empty buckets too.
+ #[inline]
+ pub fn into_keys(self) -> IntoKeys<K, V> {
+ self.0.into_keys()
+ }
+
+ /// Creates a consuming iterator visiting all the values in arbitrary order.
+ /// The map cannot be used after calling this.
+ /// The iterator element type is `V`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let map = HashMap::from([
+ /// ("a", 1),
+ /// ("b", 2),
+ /// ("c", 3),
+ /// ]);
+ ///
+ /// let mut vec: Vec<i32> = map.into_values().collect();
+ /// // The `IntoValues` iterator produces values in arbitrary order, so
+ /// // the values must be sorted to test them against a sorted array.
+ /// vec.sort_unstable();
+ /// assert_eq!(vec, [1, 2, 3]);
+ /// ```
+ ///
+ /// # Performance
+ ///
+ /// In the current implementation, iterating over values takes O(capacity) time
+ /// instead of O(len) because it internally visits empty buckets too.
+ #[inline]
+ pub fn into_values(self) -> IntoValues<K, V> {
+ self.0.into_values()
+ }
+
/// Removes a key from the map, returning the value at the key if the key
/// was previously in the map.
///
@@ -261,13 +344,16 @@ where
}
}
-impl<K, V, S> FromIterator<(K, V)> for AHashMap<K, V, S>
+impl<K, V> FromIterator<(K, V)> for AHashMap<K, V, RandomState>
where
K: Eq + Hash,
- S: BuildHasher + Default,
{
+ /// This crates a hashmap from the provided iterator using [RandomState::new].
+ /// See the documentation in [RandomSource] for notes about key strength.
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
- AHashMap(HashMap::from_iter(iter))
+ let mut inner = HashMap::with_hasher(RandomState::new());
+ inner.extend(iter);
+ AHashMap(inner)
}
}
@@ -318,10 +404,14 @@ where
}
}
+/// NOTE: For safety this trait impl is only available available if either of the flags `runtime-rng` (on by default) or
+/// `compile-time-rng` are enabled. This is to prevent weakly keyed maps from being accidentally created. Instead one of
+/// constructors for [RandomState] must be used.
+#[cfg(any(feature = "compile-time-rng", feature = "runtime-rng", feature = "no-rng"))]
impl<K, V> Default for AHashMap<K, V, RandomState> {
#[inline]
fn default() -> AHashMap<K, V, RandomState> {
- AHashMap::new()
+ AHashMap(HashMap::default())
}
}
@@ -346,6 +436,40 @@ where
let hash_map = HashMap::deserialize(deserializer);
hash_map.map(|hash_map| Self(hash_map))
}
+
+ fn deserialize_in_place<D: Deserializer<'de>>(deserializer: D, place: &mut Self) -> Result<(), D::Error> {
+ use serde::de::{MapAccess, Visitor};
+
+ struct MapInPlaceVisitor<'a, K: 'a, V: 'a>(&'a mut AHashMap<K, V>);
+
+ impl<'a, 'de, K, V> Visitor<'de> for MapInPlaceVisitor<'a, K, V>
+ where
+ K: Deserialize<'de> + Eq + Hash,
+ V: Deserialize<'de>,
+ {
+ type Value = ();
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("a map")
+ }
+
+ fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
+ where
+ A: MapAccess<'de>,
+ {
+ self.0.clear();
+ self.0.reserve(map.size_hint().unwrap_or(0).min(4096));
+
+ while let Some((key, value)) = map.next_entry()? {
+ self.0.insert(key, value);
+ }
+
+ Ok(())
+ }
+ }
+
+ deserializer.deserialize_map(MapInPlaceVisitor(place))
+ }
}
#[cfg(test)]
@@ -364,8 +488,14 @@ mod test {
let mut map = AHashMap::new();
map.insert("for".to_string(), 0);
map.insert("bar".to_string(), 1);
- let serialization = serde_json::to_string(&map).unwrap();
- let deserialization: AHashMap<String, u64> = serde_json::from_str(&serialization).unwrap();
+ let mut serialization = serde_json::to_string(&map).unwrap();
+ let mut deserialization: AHashMap<String, u64> = serde_json::from_str(&serialization).unwrap();
+ assert_eq!(deserialization, map);
+
+ map.insert("baz".to_string(), 2);
+ serialization = serde_json::to_string(&map).unwrap();
+ let mut deserializer = serde_json::Deserializer::from_str(&serialization);
+ AHashMap::deserialize_in_place(&mut deserializer, &mut deserialization).unwrap();
assert_eq!(deserialization, map);
}
}
diff --git a/third_party/rust/ahash/src/hash_quality_test.rs b/third_party/rust/ahash/src/hash_quality_test.rs
index 17228d4716..f2fab16013 100644
--- a/third_party/rust/ahash/src/hash_quality_test.rs
+++ b/third_party/rust/ahash/src/hash_quality_test.rs
@@ -1,5 +1,5 @@
use core::hash::{Hash, Hasher};
-use std::collections::{HashMap};
+use std::collections::HashMap;
fn assert_sufficiently_different(a: u64, b: u64, tolerance: i32) {
let (same_byte_count, same_nibble_count) = count_same_bytes_and_nibbles(a, b);
@@ -50,7 +50,7 @@ fn count_same_bytes_and_nibbles(a: u64, b: u64) -> (i32, i32) {
(same_byte_count, same_nibble_count)
}
-fn gen_combinations(options: &[u32; 8], depth: u32, so_far: Vec<u32>, combinations: &mut Vec<Vec<u32>>) {
+fn gen_combinations(options: &[u32; 11], depth: u32, so_far: Vec<u32>, combinations: &mut Vec<Vec<u32>>) {
if depth == 0 {
return;
}
@@ -63,19 +63,15 @@ fn gen_combinations(options: &[u32; 8], depth: u32, so_far: Vec<u32>, combinatio
}
fn test_no_full_collisions<T: Hasher>(gen_hash: impl Fn() -> T) {
- let options: [u32; 8] = [
- 0x00000000, 0x20000000, 0x40000000, 0x60000000, 0x80000000, 0xA0000000, 0xC0000000, 0xE0000000,
+ let options: [u32; 11] = [
+ 0x00000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0xF0000000, 1, 2, 4, 8, 15,
];
let mut combinations = Vec::new();
gen_combinations(&options, 7, Vec::new(), &mut combinations);
let mut map: HashMap<u64, Vec<u8>> = HashMap::new();
for combination in combinations {
- let array = unsafe {
- let (begin, middle, end) = combination.align_to::<u8>();
- assert_eq!(0, begin.len());
- assert_eq!(0, end.len());
- middle.to_vec()
- };
+ use zerocopy::AsBytes;
+ let array = combination.as_slice().as_bytes().to_vec();
let mut hasher = gen_hash();
hasher.write(&array);
let hash = hasher.finish();
@@ -89,7 +85,7 @@ fn test_no_full_collisions<T: Hasher>(gen_hash: impl Fn() -> T) {
map.insert(hash, array);
}
}
- assert_eq!(2396744, map.len());
+ assert_eq!(21435887, map.len()); //11^7 + 11^6 ...
}
fn test_keys_change_output<T: Hasher>(constructor: impl Fn(u128, u128) -> T) {
@@ -112,13 +108,13 @@ fn test_keys_change_output<T: Hasher>(constructor: impl Fn(u128, u128) -> T) {
fn test_input_affect_every_byte<T: Hasher>(constructor: impl Fn(u128, u128) -> T) {
let base = hash_with(&0, constructor(0, 0));
for shift in 0..16 {
- let mut alternitives = vec![];
+ let mut alternatives = vec![];
for v in 0..256 {
let input = (v as u128) << (shift * 8);
let hasher = constructor(0, 0);
- alternitives.push(hash_with(&input, hasher));
+ alternatives.push(hash_with(&input, hasher));
}
- assert_each_byte_differs(shift, base, alternitives);
+ assert_each_byte_differs(shift, base, alternatives);
}
}
@@ -126,28 +122,35 @@ fn test_input_affect_every_byte<T: Hasher>(constructor: impl Fn(u128, u128) -> T
fn test_keys_affect_every_byte<H: Hash, T: Hasher>(item: H, constructor: impl Fn(u128, u128) -> T) {
let base = hash_with(&item, constructor(0, 0));
for shift in 0..16 {
- let mut alternitives1 = vec![];
- let mut alternitives2 = vec![];
+ let mut alternatives1 = vec![];
+ let mut alternatives2 = vec![];
for v in 0..256 {
let input = (v as u128) << (shift * 8);
let hasher1 = constructor(input, 0);
let hasher2 = constructor(0, input);
let h1 = hash_with(&item, hasher1);
let h2 = hash_with(&item, hasher2);
- alternitives1.push(h1);
- alternitives2.push(h2);
+ alternatives1.push(h1);
+ alternatives2.push(h2);
}
- assert_each_byte_differs(shift, base, alternitives1);
- assert_each_byte_differs(shift, base, alternitives2);
+ assert_each_byte_differs(shift, base, alternatives1);
+ assert_each_byte_differs(shift, base, alternatives2);
}
}
-fn assert_each_byte_differs(num: u64, base: u64, alternitives: Vec<u64>) {
+fn assert_each_byte_differs(num: u64, base: u64, alternatives: Vec<u64>) {
let mut changed_bits = 0_u64;
- for alternitive in alternitives {
- changed_bits |= base ^ alternitive
- }
- assert_eq!(core::u64::MAX, changed_bits, "Bits changed: {:x} on num: {:?}", changed_bits, num);
+ for alternative in alternatives {
+ changed_bits |= base ^ alternative
+ }
+ assert_eq!(
+ core::u64::MAX,
+ changed_bits,
+ "Bits changed: {:x} on num: {:?}. base {:x}",
+ changed_bits,
+ num,
+ base
+ );
}
fn test_finish_is_consistent<T: Hasher>(constructor: impl Fn(u128, u128) -> T) {
@@ -273,11 +276,19 @@ fn test_padding_doesnot_collide<T: Hasher>(hasher: impl Fn() -> T) {
let (same_bytes, same_nibbles) = count_same_bytes_and_nibbles(value, long.finish());
assert!(
same_bytes <= 3,
- "{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish()
+ "{} bytes of {} -> {:x} vs {:x}",
+ num,
+ c,
+ value,
+ long.finish()
);
assert!(
same_nibbles <= 8,
- "{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish()
+ "{} bytes of {} -> {:x} vs {:x}",
+ num,
+ c,
+ value,
+ long.finish()
);
let flipped_bits = (value ^ long.finish()).count_ones();
assert!(flipped_bits > 10);
@@ -327,19 +338,24 @@ fn test_length_extension<T: Hasher>(hasher: impl Fn(u128, u128) -> T) {
}
fn test_sparse<T: Hasher>(hasher: impl Fn() -> T) {
+ use smallvec::SmallVec;
+
let mut buf = [0u8; 256];
let mut hashes = HashMap::new();
- for idx_1 in 0..256 {
- for idx_2 in idx_1+1..256 {
+ for idx_1 in 0..255_u8 {
+ for idx_2 in idx_1 + 1..=255_u8 {
for value_1 in [1, 2, 4, 8, 16, 32, 64, 128] {
- for value_2 in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 16, 17, 18, 20, 24, 31, 32, 33, 48, 64, 96, 127, 128, 129, 192, 254, 255] {
- buf[idx_1] = value_1;
- buf[idx_2] = value_2;
+ for value_2 in [
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 16, 17, 18, 20, 24, 31, 32, 33, 48, 64, 96, 127, 128, 129,
+ 192, 254, 255,
+ ] {
+ buf[idx_1 as usize] = value_1;
+ buf[idx_2 as usize] = value_2;
let hash_value = hash_with(&buf, &mut hasher());
- let keys = hashes.entry(hash_value).or_insert(Vec::new());
- keys.push((idx_1, value_1, idx_2, value_2));
- buf[idx_1] = 0;
- buf[idx_2] = 0;
+ let keys = hashes.entry(hash_value).or_insert(SmallVec::<[[u8; 4]; 1]>::new());
+ keys.push([idx_1, value_1, idx_2, value_2]);
+ buf[idx_1 as usize] = 0;
+ buf[idx_2 as usize] = 0;
}
}
}
@@ -392,7 +408,7 @@ mod fallback_tests {
fn fallback_keys_affect_every_byte() {
//For fallback second key is not used in every hash.
#[cfg(all(not(feature = "specialize"), feature = "folded_multiply"))]
- test_keys_affect_every_byte(0, |a, b| AHasher::new_with_keys(a ^ b, a));
+ test_keys_affect_every_byte(0, |a, b| AHasher::new_with_keys(a ^ b, a));
test_keys_affect_every_byte("", |a, b| AHasher::new_with_keys(a ^ b, a));
test_keys_affect_every_byte((0, 0), |a, b| AHasher::new_with_keys(a ^ b, a));
}
@@ -425,7 +441,8 @@ mod fallback_tests {
///Basic sanity tests of the cypto properties of aHash.
#[cfg(any(
all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
+ all(target_arch = "aarch64", target_feature = "aes", not(miri)),
+ all(feature = "nightly-arm-aes", target_arch = "arm", target_feature = "aes", not(miri)),
))]
#[cfg(test)]
mod aes_tests {
@@ -488,7 +505,7 @@ mod aes_tests {
#[test]
fn aes_keys_affect_every_byte() {
#[cfg(not(feature = "specialize"))]
- test_keys_affect_every_byte(0, AHasher::test_with_keys);
+ test_keys_affect_every_byte(0, AHasher::test_with_keys);
test_keys_affect_every_byte("", AHasher::test_with_keys);
test_keys_affect_every_byte((0, 0), AHasher::test_with_keys);
}
diff --git a/third_party/rust/ahash/src/hash_set.rs b/third_party/rust/ahash/src/hash_set.rs
index 9766b676ff..d03bef580f 100644
--- a/third_party/rust/ahash/src/hash_set.rs
+++ b/third_party/rust/ahash/src/hash_set.rs
@@ -14,27 +14,49 @@ use serde::{
/// A [`HashSet`](std::collections::HashSet) using [`RandomState`](crate::RandomState) to hash the items.
/// (Requires the `std` feature to be enabled.)
#[derive(Clone)]
-pub struct AHashSet<T, S = crate::RandomState>(HashSet<T, S>);
+pub struct AHashSet<T, S = RandomState>(HashSet<T, S>);
-impl<T> From<HashSet<T, crate::RandomState>> for AHashSet<T> {
- fn from(item: HashSet<T, crate::RandomState>) -> Self {
+impl<T> From<HashSet<T, RandomState>> for AHashSet<T> {
+ fn from(item: HashSet<T, RandomState>) -> Self {
AHashSet(item)
}
}
-impl<T> Into<HashSet<T, crate::RandomState>> for AHashSet<T> {
- fn into(self) -> HashSet<T, crate::RandomState> {
+impl<T, const N: usize> From<[T; N]> for AHashSet<T>
+where
+ T: Eq + Hash,
+{
+ /// # Examples
+ ///
+ /// ```
+ /// use ahash::AHashSet;
+ ///
+ /// let set1 = AHashSet::from([1, 2, 3, 4]);
+ /// let set2: AHashSet<_> = [1, 2, 3, 4].into();
+ /// assert_eq!(set1, set2);
+ /// ```
+ fn from(arr: [T; N]) -> Self {
+ Self::from_iter(arr)
+ }
+}
+
+impl<T> Into<HashSet<T, RandomState>> for AHashSet<T> {
+ fn into(self) -> HashSet<T, RandomState> {
self.0
}
}
impl<T> AHashSet<T, RandomState> {
+ /// This crates a hashset using [RandomState::new].
+ /// See the documentation in [RandomSource] for notes about key strength.
pub fn new() -> Self {
- AHashSet(HashSet::with_hasher(RandomState::default()))
+ AHashSet(HashSet::with_hasher(RandomState::new()))
}
+ /// This crates a hashset with the specified capacity using [RandomState::new].
+ /// See the documentation in [RandomSource] for notes about key strength.
pub fn with_capacity(capacity: usize) -> Self {
- AHashSet(HashSet::with_capacity_and_hasher(capacity, RandomState::default()))
+ AHashSet(HashSet::with_capacity_and_hasher(capacity, RandomState::new()))
}
}
@@ -219,14 +241,17 @@ where
}
}
-impl<T, S> FromIterator<T> for AHashSet<T, S>
+impl<T> FromIterator<T> for AHashSet<T, RandomState>
where
T: Eq + Hash,
- S: BuildHasher + Default,
{
+ /// This crates a hashset from the provided iterator using [RandomState::new].
+ /// See the documentation in [RandomSource] for notes about key strength.
#[inline]
- fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> AHashSet<T, S> {
- AHashSet(HashSet::from_iter(iter))
+ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> AHashSet<T> {
+ let mut inner = HashSet::with_hasher(RandomState::new());
+ inner.extend(iter);
+ AHashSet(inner)
}
}
@@ -268,6 +293,10 @@ where
}
}
+/// NOTE: For safety this trait impl is only available available if either of the flags `runtime-rng` (on by default) or
+/// `compile-time-rng` are enabled. This is to prevent weakly keyed maps from being accidentally created. Instead one of
+/// constructors for [RandomState] must be used.
+#[cfg(any(feature = "compile-time-rng", feature = "runtime-rng", feature = "no-rng"))]
impl<T> Default for AHashSet<T, RandomState> {
/// Creates an empty `AHashSet<T, S>` with the `Default` value for the hasher.
#[inline]
@@ -295,6 +324,10 @@ where
let hash_set = HashSet::deserialize(deserializer);
hash_set.map(|hash_set| Self(hash_set))
}
+
+ fn deserialize_in_place<D: Deserializer<'de>>(deserializer: D, place: &mut Self) -> Result<(), D::Error> {
+ HashSet::deserialize_in_place(deserializer, place)
+ }
}
#[cfg(all(test, feature = "serde"))]
@@ -306,8 +339,14 @@ mod test {
let mut set = AHashSet::new();
set.insert("for".to_string());
set.insert("bar".to_string());
- let serialization = serde_json::to_string(&set).unwrap();
- let deserialization: AHashSet<String> = serde_json::from_str(&serialization).unwrap();
+ let mut serialization = serde_json::to_string(&set).unwrap();
+ let mut deserialization: AHashSet<String> = serde_json::from_str(&serialization).unwrap();
+ assert_eq!(deserialization, set);
+
+ set.insert("baz".to_string());
+ serialization = serde_json::to_string(&set).unwrap();
+ let mut deserializer = serde_json::Deserializer::from_str(&serialization);
+ AHashSet::deserialize_in_place(&mut deserializer, &mut deserialization).unwrap();
assert_eq!(deserialization, set);
}
}
diff --git a/third_party/rust/ahash/src/lib.rs b/third_party/rust/ahash/src/lib.rs
index 9964a7c47b..69fb2ca237 100644
--- a/third_party/rust/ahash/src/lib.rs
+++ b/third_party/rust/ahash/src/lib.rs
@@ -1,86 +1,208 @@
-//! AHash is a hashing algorithm is intended to be a high performance, (hardware specific), keyed hash function.
-//! This can be seen as a DOS resistant alternative to `FxHash`, or a fast equivalent to `SipHash`.
-//! It provides a high speed hash algorithm, but where the result is not predictable without knowing a Key.
-//! This allows it to be used in a `HashMap` without allowing for the possibility that an malicious user can
+//! AHash is a high performance keyed hash function.
+//!
+//! It quickly provides a high quality hash where the result is not predictable without knowing the Key.
+//! AHash works with `HashMap` to hash keys, but without allowing for the possibility that an malicious user can
//! induce a collision.
//!
//! # How aHash works
//!
-//! aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
-//! aHash is not a cryptographically secure hash.
-//!
-//! # Example
-//! ```
-//! use ahash::{AHasher, RandomState};
-//! use std::collections::HashMap;
+//! When it is available aHash uses the hardware AES instructions to provide a keyed hash function.
+//! When it is not, aHash falls back on a slightly slower alternative algorithm.
//!
-//! let mut map: HashMap<i32, i32, RandomState> = HashMap::default();
-//! map.insert(12, 34);
-//! ```
-//! For convinence wrappers called `AHashMap` and `AHashSet` are also provided.
-//! These to the same thing with slightly less typing.
-//! ```ignore
-//! use ahash::AHashMap;
-//!
-//! let mut map: AHashMap<i32, i32> = AHashMap::with_capacity(4);
-//! map.insert(12, 34);
-//! map.insert(56, 78);
-//! ```
+//! Because aHash does not have a fixed standard for its output, it is able to improve over time.
+//! But this also means that different computers or computers using different versions of ahash may observe different
+//! hash values for the same input.
+#![cfg_attr(
+ all(
+ feature = "std",
+ any(feature = "compile-time-rng", feature = "runtime-rng", feature = "no-rng")
+ ),
+ doc = r##"
+# Basic Usage
+AHash provides an implementation of the [Hasher] trait.
+To construct a HashMap using aHash as its hasher do the following:
+```
+use ahash::{AHasher, RandomState};
+use std::collections::HashMap;
+
+let mut map: HashMap<i32, i32, RandomState> = HashMap::default();
+map.insert(12, 34);
+```
+
+### Randomness
+
+The above requires a source of randomness to generate keys for the hashmap. By default this obtained from the OS.
+It is also possible to have randomness supplied via the `compile-time-rng` flag, or manually.
+
+### If randomess is not available
+
+[AHasher::default()] can be used to hash using fixed keys. This works with
+[BuildHasherDefault](std::hash::BuildHasherDefault). For example:
+
+```
+use std::hash::BuildHasherDefault;
+use std::collections::HashMap;
+use ahash::AHasher;
+
+let mut m: HashMap<_, _, BuildHasherDefault<AHasher>> = HashMap::default();
+ # m.insert(12, 34);
+```
+It is also possible to instantiate [RandomState] directly:
+
+```
+use ahash::HashMap;
+use ahash::RandomState;
+
+let mut m = HashMap::with_hasher(RandomState::with_seed(42));
+ # m.insert(1, 2);
+```
+Or for uses besides a hashhmap:
+```
+use std::hash::BuildHasher;
+use ahash::RandomState;
+
+let hash_builder = RandomState::with_seed(42);
+let hash = hash_builder.hash_one("Some Data");
+```
+There are several constructors for [RandomState] with different ways to supply seeds.
+
+# Convenience wrappers
+
+For convenience, both new-type wrappers and type aliases are provided.
+
+The new type wrappers are called called `AHashMap` and `AHashSet`.
+```
+use ahash::AHashMap;
+
+let mut map: AHashMap<i32, i32> = AHashMap::new();
+map.insert(12, 34);
+```
+This avoids the need to type "RandomState". (For convenience `From`, `Into`, and `Deref` are provided).
+
+# Aliases
+
+For even less typing and better interop with existing libraries (such as rayon) which require a `std::collection::HashMap` ,
+the type aliases [HashMap], [HashSet] are provided.
+
+```
+use ahash::{HashMap, HashMapExt};
+
+let mut map: HashMap<i32, i32> = HashMap::new();
+map.insert(12, 34);
+```
+Note the import of [HashMapExt]. This is needed for the constructor.
+
+"##
+)]
#![deny(clippy::correctness, clippy::complexity, clippy::perf)]
#![allow(clippy::pedantic, clippy::cast_lossless, clippy::unreadable_literal)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(feature = "specialize", feature(min_specialization))]
-#![cfg_attr(feature = "stdsimd", feature(stdsimd))]
+#![cfg_attr(feature = "nightly-arm-aes", feature(stdarch_arm_neon_intrinsics))]
#[macro_use]
mod convert;
-#[cfg(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-))]
-mod aes_hash;
mod fallback_hash;
+
+cfg_if::cfg_if! {
+ if #[cfg(any(
+ all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
+ all(feature = "nightly-arm-aes", target_arch = "aarch64", target_feature = "aes", not(miri)),
+ all(feature = "nightly-arm-aes", target_arch = "arm", target_feature = "aes", not(miri)),
+ ))] {
+ mod aes_hash;
+ pub use crate::aes_hash::AHasher;
+ } else {
+ pub use crate::fallback_hash::AHasher;
+ }
+}
+
+cfg_if::cfg_if! {
+ if #[cfg(feature = "std")] {
+ mod hash_map;
+ mod hash_set;
+
+ pub use crate::hash_map::AHashMap;
+ pub use crate::hash_set::AHashSet;
+
+ /// [Hasher]: std::hash::Hasher
+ /// [HashMap]: std::collections::HashMap
+ /// Type alias for [HashMap]<K, V, ahash::RandomState>
+ pub type HashMap<K, V> = std::collections::HashMap<K, V, crate::RandomState>;
+
+ /// Type alias for [HashSet]<K, ahash::RandomState>
+ pub type HashSet<K> = std::collections::HashSet<K, crate::RandomState>;
+ }
+}
+
#[cfg(test)]
mod hash_quality_test;
-#[cfg(feature = "std")]
-mod hash_map;
-#[cfg(feature = "std")]
-mod hash_set;
mod operations;
-mod random_state;
+pub mod random_state;
mod specialize;
-#[cfg(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-))]
-pub use crate::aes_hash::AHasher;
-
-#[cfg(not(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-)))]
-pub use crate::fallback_hash::AHasher;
pub use crate::random_state::RandomState;
-pub use crate::specialize::CallHasher;
-
-#[cfg(feature = "std")]
-pub use crate::hash_map::AHashMap;
-#[cfg(feature = "std")]
-pub use crate::hash_set::AHashSet;
use core::hash::BuildHasher;
use core::hash::Hash;
use core::hash::Hasher;
+#[cfg(feature = "std")]
+/// A convenience trait that can be used together with the type aliases defined to
+/// get access to the `new()` and `with_capacity()` methods for the HashMap type alias.
+pub trait HashMapExt {
+ /// Constructs a new HashMap
+ fn new() -> Self;
+ /// Constructs a new HashMap with a given initial capacity
+ fn with_capacity(capacity: usize) -> Self;
+}
+
+#[cfg(feature = "std")]
+/// A convenience trait that can be used together with the type aliases defined to
+/// get access to the `new()` and `with_capacity()` methods for the HashSet type aliases.
+pub trait HashSetExt {
+ /// Constructs a new HashSet
+ fn new() -> Self;
+ /// Constructs a new HashSet with a given initial capacity
+ fn with_capacity(capacity: usize) -> Self;
+}
+
+#[cfg(feature = "std")]
+impl<K, V, S> HashMapExt for std::collections::HashMap<K, V, S>
+where
+ S: BuildHasher + Default,
+{
+ fn new() -> Self {
+ std::collections::HashMap::with_hasher(S::default())
+ }
+
+ fn with_capacity(capacity: usize) -> Self {
+ std::collections::HashMap::with_capacity_and_hasher(capacity, S::default())
+ }
+}
+
+#[cfg(feature = "std")]
+impl<K, S> HashSetExt for std::collections::HashSet<K, S>
+where
+ S: BuildHasher + Default,
+{
+ fn new() -> Self {
+ std::collections::HashSet::with_hasher(S::default())
+ }
+
+ fn with_capacity(capacity: usize) -> Self {
+ std::collections::HashSet::with_capacity_and_hasher(capacity, S::default())
+ }
+}
+
/// Provides a default [Hasher] with fixed keys.
/// This is typically used in conjunction with [BuildHasherDefault] to create
/// [AHasher]s in order to hash the keys of the map.
///
/// Generally it is preferable to use [RandomState] instead, so that different
-/// hashmaps will have different keys. However if fixed keys are desireable this
+/// hashmaps will have different keys. However if fixed keys are desirable this
/// may be used instead.
///
/// # Example
@@ -194,9 +316,21 @@ impl<B: BuildHasher> BuildHasherExt for B {
#[cfg(test)]
mod test {
use crate::convert::Convert;
+ use crate::specialize::CallHasher;
use crate::*;
use std::collections::HashMap;
- use std::hash::Hash;
+
+ #[test]
+ fn test_ahash_alias_map_construction() {
+ let mut map = super::HashMap::with_capacity(1234);
+ map.insert(1, "test");
+ }
+
+ #[test]
+ fn test_ahash_alias_set_construction() {
+ let mut set = super::HashSet::with_capacity(1234);
+ set.insert(1);
+ }
#[test]
fn test_default_builder() {
@@ -219,7 +353,6 @@ mod test {
assert_eq!(bytes, 0x6464646464646464);
}
-
#[test]
fn test_non_zero() {
let mut hasher1 = AHasher::new_with_keys(0, 0);
@@ -241,7 +374,7 @@ mod test {
#[test]
fn test_non_zero_specialized() {
- let hasher_build = RandomState::with_seeds(0,0,0,0);
+ let hasher_build = RandomState::with_seeds(0, 0, 0, 0);
let h1 = str::get_hash("foo", &hasher_build);
let h2 = str::get_hash("bar", &hasher_build);
diff --git a/third_party/rust/ahash/src/operations.rs b/third_party/rust/ahash/src/operations.rs
index b71fd5a743..8395007535 100644
--- a/third_party/rust/ahash/src/operations.rs
+++ b/third_party/rust/ahash/src/operations.rs
@@ -1,4 +1,9 @@
use crate::convert::*;
+#[allow(unused)]
+use zerocopy::transmute;
+
+///This constant comes from Kunth's prng (Empirically it works better than those from splitmix32).
+pub(crate) const MULTIPLE: u64 = 6364136223846793005;
/// This is a constant with a lot of special properties found by automated search.
/// See the unit tests below. (Below are alternative values)
@@ -8,11 +13,19 @@ const SHUFFLE_MASK: u128 = 0x020a0700_0c01030e_050f0d08_06090b04_u128;
//const SHUFFLE_MASK: u128 = 0x040A0700_030E0106_0D050F08_020B0C09_u128;
#[inline(always)]
+#[cfg(feature = "folded_multiply")]
pub(crate) const fn folded_multiply(s: u64, by: u64) -> u64 {
let result = (s as u128).wrapping_mul(by as u128);
((result & 0xffff_ffff_ffff_ffff) as u64) ^ ((result >> 64) as u64)
}
+#[inline(always)]
+#[cfg(not(feature = "folded_multiply"))]
+pub(crate) const fn folded_multiply(s: u64, by: u64) -> u64 {
+ let b1 = s.wrapping_mul(by.swap_bytes());
+ let b2 = s.swap_bytes().wrapping_mul(!by);
+ b1 ^ b2.swap_bytes()
+}
/// Given a small (less than 8 byte slice) returns the same data stored in two u32s.
/// (order of and non-duplication of bytes is NOT guaranteed)
@@ -44,8 +57,7 @@ pub(crate) fn shuffle(a: u128) -> u128 {
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- use core::mem::transmute;
- unsafe { transmute(_mm_shuffle_epi8(transmute(a), transmute(SHUFFLE_MASK))) }
+ unsafe { transmute!(_mm_shuffle_epi8(transmute!(a), transmute!(SHUFFLE_MASK))) }
}
#[cfg(not(all(target_feature = "ssse3", not(miri))))]
{
@@ -60,7 +72,7 @@ pub(crate) fn add_and_shuffle(a: u128, b: u128) -> u128 {
shuffle(sum.convert())
}
-#[allow(unused)] //not used by fallbac
+#[allow(unused)] //not used by fallback
#[inline(always)]
pub(crate) fn shuffle_and_add(base: u128, to_add: u128) -> u128 {
let shuffled: [u64; 2] = shuffle(base).convert();
@@ -70,13 +82,12 @@ pub(crate) fn shuffle_and_add(base: u128, to_add: u128) -> u128 {
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2", not(miri)))]
#[inline(always)]
pub(crate) fn add_by_64s(a: [u64; 2], b: [u64; 2]) -> [u64; 2] {
- use core::mem::transmute;
unsafe {
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- transmute(_mm_add_epi64(transmute(a), transmute(b)))
+ transmute!(_mm_add_epi64(transmute!(a), transmute!(b)))
}
}
@@ -94,26 +105,26 @@ pub(crate) fn aesenc(value: u128, xor: u128) -> u128 {
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- use core::mem::transmute;
unsafe {
- let value = transmute(value);
- transmute(_mm_aesenc_si128(value, transmute(xor)))
+ let value = transmute!(value);
+ transmute!(_mm_aesenc_si128(value, transmute!(xor)))
}
}
-#[cfg(all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd"))]
+#[cfg(any(
+ all(feature = "nightly-arm-aes", target_arch = "aarch64", target_feature = "aes", not(miri)),
+ all(feature = "nightly-arm-aes", target_arch = "arm", target_feature = "aes", not(miri)),
+))]
#[allow(unused)]
#[inline(always)]
pub(crate) fn aesenc(value: u128, xor: u128) -> u128 {
- #[cfg(target_arch = "arm")]
- use core::arch::arm::*;
#[cfg(target_arch = "aarch64")]
use core::arch::aarch64::*;
- use core::mem::transmute;
- unsafe {
- let value = transmute(value);
- transmute(vaesmcq_u8(vaeseq_u8(value, transmute(xor))))
- }
+ #[cfg(target_arch = "arm")]
+ use core::arch::arm::*;
+ let res = unsafe { vaesmcq_u8(vaeseq_u8(transmute!(value), transmute!(0u128))) };
+ let value: u128 = transmute!(res);
+ xor ^ value
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
@@ -124,32 +135,55 @@ pub(crate) fn aesdec(value: u128, xor: u128) -> u128 {
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- use core::mem::transmute;
unsafe {
- let value = transmute(value);
- transmute(_mm_aesdec_si128(value, transmute(xor)))
+ let value = transmute!(value);
+ transmute!(_mm_aesdec_si128(value, transmute!(xor)))
}
}
-#[cfg(all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd"))]
+#[cfg(any(
+ all(feature = "nightly-arm-aes", target_arch = "aarch64", target_feature = "aes", not(miri)),
+ all(feature = "nightly-arm-aes", target_arch = "arm", target_feature = "aes", not(miri)),
+))]
#[allow(unused)]
#[inline(always)]
pub(crate) fn aesdec(value: u128, xor: u128) -> u128 {
- #[cfg(target_arch = "arm")]
- use core::arch::arm::*;
#[cfg(target_arch = "aarch64")]
use core::arch::aarch64::*;
- use core::mem::transmute;
- unsafe {
- let value = transmute(value);
- transmute(vaesimcq_u8(vaesdq_u8(value, transmute(xor))))
+ #[cfg(target_arch = "arm")]
+ use core::arch::arm::*;
+ let res = unsafe { vaesimcq_u8(vaesdq_u8(transmute!(value), transmute!(0u128))) };
+ let value: u128 = transmute!(res);
+ xor ^ value
+}
+
+#[allow(unused)]
+#[inline(always)]
+pub(crate) fn add_in_length(enc: &mut u128, len: u64) {
+ #[cfg(all(target_arch = "x86_64", target_feature = "sse2", not(miri)))]
+ {
+ #[cfg(target_arch = "x86_64")]
+ use core::arch::x86_64::*;
+
+ unsafe {
+ let enc = enc as *mut u128;
+ let len = _mm_cvtsi64_si128(len as i64);
+ let data = _mm_loadu_si128(enc.cast());
+ let sum = _mm_add_epi64(data, len);
+ _mm_storeu_si128(enc.cast(), sum);
+ }
+ }
+ #[cfg(not(all(target_arch = "x86_64", target_feature = "sse2", not(miri))))]
+ {
+ let mut t: [u64; 2] = enc.convert();
+ t[0] = t[0].wrapping_add(len);
+ *enc = t.convert();
}
}
#[cfg(test)]
mod test {
use super::*;
- use crate::convert::Convert;
// This is code to search for the shuffle constant
//
@@ -162,7 +196,7 @@ mod test {
// #[cfg(target_arch = "x86_64")]
// use core::arch::x86_64::*;
// MASK.with(|mask| {
- // unsafe { transmute(_mm_shuffle_epi8(transmute(a), transmute(mask.get()))) }
+ // unsafe { transmute!(_mm_shuffle_epi8(transmute!(a), transmute!(mask.get()))) }
// })
// }
//
@@ -327,4 +361,12 @@ mod test {
shuffled = shuffle(shuffled);
}
}
+
+ #[test]
+ fn test_add_length() {
+ let mut enc = (u64::MAX as u128) << 64 | 50;
+ add_in_length(&mut enc, u64::MAX);
+ assert_eq!(enc >> 64, u64::MAX as u128);
+ assert_eq!(enc as u64, 49);
+ }
}
diff --git a/third_party/rust/ahash/src/random_state.rs b/third_party/rust/ahash/src/random_state.rs
index 9ac2f3ec43..46a39ab068 100644
--- a/third_party/rust/ahash/src/random_state.rs
+++ b/third_party/rust/ahash/src/random_state.rs
@@ -1,33 +1,27 @@
-#[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
-use crate::convert::Convert;
-#[cfg(feature = "specialize")]
-use crate::BuildHasherExt;
-
-#[cfg(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-))]
-pub use crate::aes_hash::*;
-
-#[cfg(not(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-)))]
-pub use crate::fallback_hash::*;
-
-#[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
-use const_random::const_random;
-use core::any::{Any, TypeId};
-use core::fmt;
-use core::hash::BuildHasher;
-#[cfg(feature = "specialize")]
use core::hash::Hash;
-use core::hash::Hasher;
-
-#[cfg(not(feature = "std"))]
-extern crate alloc;
-#[cfg(feature = "std")]
-extern crate std as alloc;
+cfg_if::cfg_if! {
+ if #[cfg(any(
+ all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
+ all(feature = "nightly-arm-aes", target_arch = "aarch64", target_feature = "aes", not(miri)),
+ all(feature = "nightly-arm-aes", target_arch = "arm", target_feature = "aes", not(miri)),
+ ))] {
+ use crate::aes_hash::*;
+ } else {
+ use crate::fallback_hash::*;
+ }
+}
+cfg_if::cfg_if! {
+ if #[cfg(feature = "specialize")]{
+ use crate::BuildHasherExt;
+ }
+}
+cfg_if::cfg_if! {
+ if #[cfg(feature = "std")] {
+ extern crate std as alloc;
+ } else {
+ extern crate alloc;
+ }
+}
#[cfg(feature = "atomic-polyfill")]
use atomic_polyfill as atomic;
@@ -36,32 +30,10 @@ use core::sync::atomic;
use alloc::boxed::Box;
use atomic::{AtomicUsize, Ordering};
-#[cfg(not(all(target_arch = "arm", target_os = "none")))]
-use once_cell::race::OnceBox;
-
-#[cfg(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-))]
-use crate::aes_hash::*;
-#[cfg(not(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-)))]
-use crate::fallback_hash::*;
-
-#[cfg(not(all(target_arch = "arm", target_os = "none")))]
-static RAND_SOURCE: OnceBox<Box<dyn RandomSource + Send + Sync>> = OnceBox::new();
-
-/// A supplier of Randomness used for different hashers.
-/// See [RandomState.set_random_source].
-pub trait RandomSource {
-
- fn get_fixed_seeds(&self) -> &'static [[u64; 4]; 2];
-
- fn gen_hasher_seed(&self) -> usize;
-
-}
+use core::any::{Any, TypeId};
+use core::fmt;
+use core::hash::BuildHasher;
+use core::hash::Hasher;
pub(crate) const PI: [u64; 4] = [
0x243f_6a88_85a3_08d3,
@@ -77,6 +49,90 @@ pub(crate) const PI2: [u64; 4] = [
0x3f84_d5b5_b547_0917,
];
+cfg_if::cfg_if! {
+ if #[cfg(all(feature = "compile-time-rng", any(test, fuzzing)))] {
+ #[inline]
+ fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
+ use const_random::const_random;
+
+ const RAND: [[u64; 4]; 2] = [
+ [
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ ], [
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ ]
+ ];
+ &RAND
+ }
+ } else if #[cfg(all(feature = "runtime-rng", not(fuzzing)))] {
+ #[inline]
+ fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
+ use crate::convert::Convert;
+
+ static SEEDS: OnceBox<[[u64; 4]; 2]> = OnceBox::new();
+
+ SEEDS.get_or_init(|| {
+ let mut result: [u8; 64] = [0; 64];
+ getrandom::getrandom(&mut result).expect("getrandom::getrandom() failed.");
+ Box::new(result.convert())
+ })
+ }
+ } else if #[cfg(feature = "compile-time-rng")] {
+ #[inline]
+ fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
+ use const_random::const_random;
+
+ const RAND: [[u64; 4]; 2] = [
+ [
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ ], [
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ const_random!(u64),
+ ]
+ ];
+ &RAND
+ }
+ } else {
+ #[inline]
+ fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
+ &[PI, PI2]
+ }
+ }
+}
+
+cfg_if::cfg_if! {
+ if #[cfg(not(all(target_arch = "arm", target_os = "none")))] {
+ use once_cell::race::OnceBox;
+
+ static RAND_SOURCE: OnceBox<Box<dyn RandomSource + Send + Sync>> = OnceBox::new();
+ }
+}
+/// A supplier of Randomness used for different hashers.
+/// See [set_random_source].
+///
+/// If [set_random_source] aHash will default to the best available source of randomness.
+/// In order this is:
+/// 1. OS provided random number generator (available if the `runtime-rng` flag is enabled which it is by default) - This should be very strong.
+/// 2. Strong compile time random numbers used to permute a static "counter". (available if `compile-time-rng` is enabled.
+/// __Enabling this is recommended if `runtime-rng` is not possible__)
+/// 3. A static counter that adds the memory address of each [RandomState] created permuted with fixed constants.
+/// (Similar to above but with fixed keys) - This is the weakest option. The strength of this heavily depends on whether or not ASLR is enabled.
+/// (Rust enables ASLR by default)
+pub trait RandomSource {
+ fn gen_hasher_seed(&self) -> usize;
+}
+
struct DefaultRandomSource {
counter: AtomicUsize,
}
@@ -88,6 +144,7 @@ impl DefaultRandomSource {
}
}
+ #[cfg(all(target_arch = "arm", target_os = "none"))]
const fn default() -> DefaultRandomSource {
DefaultRandomSource {
counter: AtomicUsize::new(PI[3] as usize),
@@ -96,55 +153,50 @@ impl DefaultRandomSource {
}
impl RandomSource for DefaultRandomSource {
-
- #[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
- fn get_fixed_seeds(&self) -> &'static [[u64; 4]; 2] {
- static SEEDS: OnceBox<[[u64; 4]; 2]> = OnceBox::new();
-
- SEEDS.get_or_init(|| {
- let mut result: [u8; 64] = [0; 64];
- getrandom::getrandom(&mut result).expect("getrandom::getrandom() failed.");
- Box::new(result.convert())
- })
- }
-
- #[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
- fn get_fixed_seeds(&self) -> &'static [[u64; 4]; 2] {
- const RAND: [[u64; 4]; 2] = [
- [
- const_random!(u64),
- const_random!(u64),
- const_random!(u64),
- const_random!(u64),
- ], [
- const_random!(u64),
- const_random!(u64),
- const_random!(u64),
- const_random!(u64),
- ]
- ];
- &RAND
- }
-
- #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
- fn get_fixed_seeds(&self) -> &'static [[u64; 4]; 2] {
- &[PI, PI2]
- }
-
- #[cfg(not(all(target_arch = "arm", target_os = "none")))]
- fn gen_hasher_seed(&self) -> usize {
- let stack = self as *const _ as usize;
- self.counter.fetch_add(stack, Ordering::Relaxed)
+ cfg_if::cfg_if! {
+ if #[cfg(all(target_arch = "arm", target_os = "none"))] {
+ fn gen_hasher_seed(&self) -> usize {
+ let stack = self as *const _ as usize;
+ let previous = self.counter.load(Ordering::Relaxed);
+ let new = previous.wrapping_add(stack);
+ self.counter.store(new, Ordering::Relaxed);
+ new
+ }
+ } else {
+ fn gen_hasher_seed(&self) -> usize {
+ let stack = self as *const _ as usize;
+ self.counter.fetch_add(stack, Ordering::Relaxed)
+ }
+ }
}
+}
- #[cfg(all(target_arch = "arm", target_os = "none"))]
- fn gen_hasher_seed(&self) -> usize {
- let stack = self as *const _ as usize;
- let previous = self.counter.load(Ordering::Relaxed);
- let new = previous.wrapping_add(stack);
- self.counter.store(new, Ordering::Relaxed);
- new
- }
+cfg_if::cfg_if! {
+ if #[cfg(all(target_arch = "arm", target_os = "none"))] {
+ #[inline]
+ fn get_src() -> &'static dyn RandomSource {
+ static RAND_SOURCE: DefaultRandomSource = DefaultRandomSource::default();
+ &RAND_SOURCE
+ }
+ } else {
+ /// Provides an optional way to manually supply a source of randomness for Hasher keys.
+ ///
+ /// The provided [RandomSource] will be used to be used as a source of randomness by [RandomState] to generate new states.
+ /// If this method is not invoked the standard source of randomness is used as described in the Readme.
+ ///
+ /// The source of randomness can only be set once, and must be set before the first RandomState is created.
+ /// If the source has already been specified `Err` is returned with a `bool` indicating if the set failed because
+ /// method was previously invoked (true) or if the default source is already being used (false).
+ #[cfg(not(all(target_arch = "arm", target_os = "none")))]
+ pub fn set_random_source(source: impl RandomSource + Send + Sync + 'static) -> Result<(), bool> {
+ RAND_SOURCE.set(Box::new(Box::new(source))).map_err(|s| s.as_ref().type_id() != TypeId::of::<&DefaultRandomSource>())
+ }
+
+ #[inline]
+ fn get_src() -> &'static dyn RandomSource {
+ RAND_SOURCE.get_or_init(|| Box::new(Box::new(DefaultRandomSource::new()))).as_ref()
+ }
+ }
}
/// Provides a [Hasher] factory. This is typically used (e.g. by [HashMap]) to create
@@ -154,6 +206,16 @@ impl RandomSource for DefaultRandomSource {
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
+///
+/// There are multiple constructors each is documented in more detail below:
+///
+/// | Constructor | Dynamically random? | Seed |
+/// |---------------|---------------------|------|
+/// |`new` | Each instance unique|_[RandomSource]_|
+/// |`generate_with`| Each instance unique|`u64` x 4 + [RandomSource]|
+/// |`with_seed` | Fixed per process |`u64` + static random number|
+/// |`with_seeds` | Fixed |`u64` x 4|
+///
#[derive(Clone)]
pub struct RandomState {
pub(crate) k0: u64,
@@ -169,47 +231,30 @@ impl fmt::Debug for RandomState {
}
impl RandomState {
-
- /// Provides an optional way to manually supply a source of randomness for Hasher keys.
+ /// Create a new `RandomState` `BuildHasher` using random keys.
///
- /// The provided [RandomSource] will be used to be used as a source of randomness by [RandomState] to generate new states.
- /// If this method is not invoked the standard source of randomness is used as described in the Readme.
+ /// Each instance will have a unique set of keys derived from [RandomSource].
///
- /// The source of randomness can only be set once, and must be set before the first RandomState is created.
- /// If the source has already been specified `Err` is returned with a `bool` indicating if the set failed because
- /// method was previously invoked (true) or if the default source is already being used (false).
- #[cfg(not(all(target_arch = "arm", target_os = "none")))]
- pub fn set_random_source(source: impl RandomSource + Send + Sync + 'static) -> Result<(), bool> {
- RAND_SOURCE.set(Box::new(Box::new(source))).map_err(|s| s.as_ref().type_id() != TypeId::of::<&DefaultRandomSource>())
- }
-
- #[inline]
- #[cfg(not(all(target_arch = "arm", target_os = "none")))]
- fn get_src() -> &'static dyn RandomSource {
- RAND_SOURCE.get_or_init(|| Box::new(Box::new(DefaultRandomSource::new()))).as_ref()
- }
-
- #[inline]
- #[cfg(all(target_arch = "arm", target_os = "none"))]
- fn get_src() -> &'static dyn RandomSource {
- static RAND_SOURCE: DefaultRandomSource = DefaultRandomSource::default();
- &RAND_SOURCE
- }
-
- /// Use randomly generated keys
#[inline]
pub fn new() -> RandomState {
- let src = Self::get_src();
- let fixed = src.get_fixed_seeds();
+ let src = get_src();
+ let fixed = get_fixed_seeds();
Self::from_keys(&fixed[0], &fixed[1], src.gen_hasher_seed())
}
- /// Allows for supplying seeds, but each time it is called the resulting state will be different.
- /// This is done using a static counter, so it can safely be used with a fixed keys.
+ /// Create a new `RandomState` `BuildHasher` based on the provided seeds, but in such a way
+ /// that each time it is called the resulting state will be different and of high quality.
+ /// This allows fixed constant or poor quality seeds to be provided without the problem of different
+ /// `BuildHasher`s being identical or weak.
+ ///
+ /// This is done via permuting the provided values with the value of a static counter and memory address.
+ /// (This makes this method somewhat more expensive than `with_seeds` below which does not do this).
+ ///
+ /// The provided values (k0-k3) do not need to be of high quality but they should not all be the same value.
#[inline]
pub fn generate_with(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
- let src = Self::get_src();
- let fixed = src.get_fixed_seeds();
+ let src = get_src();
+ let fixed = get_fixed_seeds();
RandomState::from_keys(&fixed[0], &[k0, k1, k2, k3], src.gen_hasher_seed())
}
@@ -217,45 +262,117 @@ impl RandomState {
let &[k0, k1, k2, k3] = a;
let mut hasher = AHasher::from_random_state(&RandomState { k0, k1, k2, k3 });
hasher.write_usize(c);
- let mix = |k: u64| {
+ let mix = |l: u64, r: u64| {
let mut h = hasher.clone();
- h.write_u64(k);
+ h.write_u64(l);
+ h.write_u64(r);
h.finish()
};
RandomState {
- k0: mix(b[0]),
- k1: mix(b[1]),
- k2: mix(b[2]),
- k3: mix(b[3]),
+ k0: mix(b[0], b[2]),
+ k1: mix(b[1], b[3]),
+ k2: mix(b[2], b[1]),
+ k3: mix(b[3], b[0]),
}
}
/// Internal. Used by Default.
#[inline]
pub(crate) fn with_fixed_keys() -> RandomState {
- let [k0, k1, k2, k3] = Self::get_src().get_fixed_seeds()[0];
+ let [k0, k1, k2, k3] = get_fixed_seeds()[0];
RandomState { k0, k1, k2, k3 }
}
- /// Allows for explicitly setting a seed to used.
+ /// Build a `RandomState` from a single key. The provided key does not need to be of high quality,
+ /// but all `RandomState`s created from the same key will produce identical hashers.
+ /// (In contrast to `generate_with` above)
+ ///
+ /// This allows for explicitly setting the seed to be used.
///
/// Note: This method does not require the provided seed to be strong.
#[inline]
pub fn with_seed(key: usize) -> RandomState {
- let fixed = Self::get_src().get_fixed_seeds();
+ let fixed = get_fixed_seeds();
RandomState::from_keys(&fixed[0], &fixed[1], key)
}
/// Allows for explicitly setting the seeds to used.
+ /// All `RandomState`s created with the same set of keys key will produce identical hashers.
+ /// (In contrast to `generate_with` above)
///
- /// Note: This method is robust against 0s being passed for one or more of the parameters
- /// or the same value being passed for more than one parameter.
+ /// Note: If DOS resistance is desired one of these should be a decent quality random number.
+ /// If 4 high quality random number are not cheaply available this method is robust against 0s being passed for
+ /// one or more of the parameters or the same value being passed for more than one parameter.
+ /// It is recommended to pass numbers in order from highest to lowest quality (if there is any difference).
#[inline]
pub const fn with_seeds(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
- RandomState { k0: k0 ^ PI2[0], k1: k1 ^ PI2[1], k2: k2 ^ PI2[2], k3: k3 ^ PI2[3] }
+ RandomState {
+ k0: k0 ^ PI2[0],
+ k1: k1 ^ PI2[1],
+ k2: k2 ^ PI2[2],
+ k3: k3 ^ PI2[3],
+ }
+ }
+
+ /// Calculates the hash of a single value. This provides a more convenient (and faster) way to obtain a hash:
+ /// For example:
+ #[cfg_attr(
+ feature = "std",
+ doc = r##" # Examples
+```
+ use std::hash::BuildHasher;
+ use ahash::RandomState;
+
+ let hash_builder = RandomState::new();
+ let hash = hash_builder.hash_one("Some Data");
+```
+ "##
+ )]
+ /// This is similar to:
+ #[cfg_attr(
+ feature = "std",
+ doc = r##" # Examples
+```
+ use std::hash::{BuildHasher, Hash, Hasher};
+ use ahash::RandomState;
+
+ let hash_builder = RandomState::new();
+ let mut hasher = hash_builder.build_hasher();
+ "Some Data".hash(&mut hasher);
+ let hash = hasher.finish();
+```
+ "##
+ )]
+ /// (Note that these two ways to get a hash may not produce the same value for the same data)
+ ///
+ /// This is intended as a convenience for code which *consumes* hashes, such
+ /// as the implementation of a hash table or in unit tests that check
+ /// whether a custom [`Hash`] implementation behaves as expected.
+ ///
+ /// This must not be used in any code which *creates* hashes, such as in an
+ /// implementation of [`Hash`]. The way to create a combined hash of
+ /// multiple values is to call [`Hash::hash`] multiple times using the same
+ /// [`Hasher`], not to call this method repeatedly and combine the results.
+ #[inline]
+ pub fn hash_one<T: Hash>(&self, x: T) -> u64
+ where
+ Self: Sized,
+ {
+ use crate::specialize::CallHasher;
+ T::get_hash(&x, self)
}
}
+/// Creates an instance of RandomState using keys obtained from the random number generator.
+/// Each instance created in this way will have a unique set of keys. (But the resulting instance
+/// can be used to create many hashers each or which will have the same keys.)
+///
+/// This is the same as [RandomState::new()]
+///
+/// NOTE: For safety this trait impl is only available available if either of the flags `runtime-rng` (on by default) or
+/// `compile-time-rng` are enabled. This is to prevent weakly keyed maps from being accidentally created. Instead one of
+/// constructors for [RandomState] must be used.
+#[cfg(any(feature = "compile-time-rng", feature = "runtime-rng", feature = "no-rng"))]
impl Default for RandomState {
#[inline]
fn default() -> Self {
@@ -271,26 +388,29 @@ impl BuildHasher for RandomState {
/// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
/// will generate the same hashes for the same input data.
///
- /// # Examples
- ///
- /// ```
- /// use ahash::{AHasher, RandomState};
- /// use std::hash::{Hasher, BuildHasher};
- ///
- /// let build_hasher = RandomState::new();
- /// let mut hasher_1 = build_hasher.build_hasher();
- /// let mut hasher_2 = build_hasher.build_hasher();
- ///
- /// hasher_1.write_u32(1234);
- /// hasher_2.write_u32(1234);
- ///
- /// assert_eq!(hasher_1.finish(), hasher_2.finish());
- ///
- /// let other_build_hasher = RandomState::new();
- /// let mut different_hasher = other_build_hasher.build_hasher();
- /// different_hasher.write_u32(1234);
- /// assert_ne!(different_hasher.finish(), hasher_1.finish());
- /// ```
+ #[cfg_attr(
+ feature = "std",
+ doc = r##" # Examples
+```
+ use ahash::{AHasher, RandomState};
+ use std::hash::{Hasher, BuildHasher};
+
+ let build_hasher = RandomState::new();
+ let mut hasher_1 = build_hasher.build_hasher();
+ let mut hasher_2 = build_hasher.build_hasher();
+
+ hasher_1.write_u32(1234);
+ hasher_2.write_u32(1234);
+
+ assert_eq!(hasher_1.finish(), hasher_2.finish());
+
+ let other_build_hasher = RandomState::new();
+ let mut different_hasher = other_build_hasher.build_hasher();
+ different_hasher.write_u32(1234);
+ assert_ne!(different_hasher.finish(), hasher_1.finish());
+```
+ "##
+ )]
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
@@ -298,6 +418,51 @@ impl BuildHasher for RandomState {
fn build_hasher(&self) -> AHasher {
AHasher::from_random_state(self)
}
+
+ /// Calculates the hash of a single value. This provides a more convenient (and faster) way to obtain a hash:
+ /// For example:
+ #[cfg_attr(
+ feature = "std",
+ doc = r##" # Examples
+```
+ use std::hash::BuildHasher;
+ use ahash::RandomState;
+
+ let hash_builder = RandomState::new();
+ let hash = hash_builder.hash_one("Some Data");
+```
+ "##
+ )]
+ /// This is similar to:
+ #[cfg_attr(
+ feature = "std",
+ doc = r##" # Examples
+```
+ use std::hash::{BuildHasher, Hash, Hasher};
+ use ahash::RandomState;
+
+ let hash_builder = RandomState::new();
+ let mut hasher = hash_builder.build_hasher();
+ "Some Data".hash(&mut hasher);
+ let hash = hasher.finish();
+```
+ "##
+ )]
+ /// (Note that these two ways to get a hash may not produce the same value for the same data)
+ ///
+ /// This is intended as a convenience for code which *consumes* hashes, such
+ /// as the implementation of a hash table or in unit tests that check
+ /// whether a custom [`Hash`] implementation behaves as expected.
+ ///
+ /// This must not be used in any code which *creates* hashes, such as in an
+ /// implementation of [`Hash`]. The way to create a combined hash of
+ /// multiple values is to call [`Hash::hash`] multiple times using the same
+ /// [`Hasher`], not to call this method repeatedly and combine the results.
+ #[cfg(feature = "specialize")]
+ #[inline]
+ fn hash_one<T: Hash>(&self, x: T) -> u64 {
+ RandomState::hash_one(self, x)
+ }
}
#[cfg(feature = "specialize")]
@@ -305,8 +470,8 @@ impl BuildHasherExt for RandomState {
#[inline]
fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64 {
let mut hasher = AHasherU64 {
- buffer: self.k0,
- pad: self.k1,
+ buffer: self.k1,
+ pad: self.k0,
};
value.hash(&mut hasher);
hasher.finish()
@@ -333,27 +498,27 @@ mod test {
#[test]
fn test_unique() {
- let a = RandomState::new();
- let b = RandomState::new();
+ let a = RandomState::generate_with(1, 2, 3, 4);
+ let b = RandomState::generate_with(1, 2, 3, 4);
assert_ne!(a.build_hasher().finish(), b.build_hasher().finish());
}
#[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
#[test]
fn test_not_pi() {
- assert_ne!(PI, RandomState::get_src().get_fixed_seeds()[0]);
+ assert_ne!(PI, get_fixed_seeds()[0]);
}
#[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
#[test]
fn test_not_pi_const() {
- assert_ne!(PI, RandomState::get_src().get_fixed_seeds()[0]);
+ assert_ne!(PI, get_fixed_seeds()[0]);
}
#[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
#[test]
fn test_pi() {
- assert_eq!(PI, RandomState::get_src().get_fixed_seeds()[0]);
+ assert_eq!(PI, get_fixed_seeds()[0]);
}
#[test]
diff --git a/third_party/rust/ahash/src/specialize.rs b/third_party/rust/ahash/src/specialize.rs
index d94a4eed0d..05d335b191 100644
--- a/third_party/rust/ahash/src/specialize.rs
+++ b/third_party/rust/ahash/src/specialize.rs
@@ -17,28 +17,7 @@ use alloc::vec::Vec;
/// Provides a way to get an optimized hasher for a given data type.
/// Rather than using a Hasher generically which can hash any value, this provides a way to get a specialized hash
/// for a specific type. So this may be faster for primitive types.
-/// # Example
-/// ```
-/// use std::hash::BuildHasher;
-/// use ahash::RandomState;
-/// use ahash::CallHasher;
-///
-/// let hash_builder = RandomState::new();
-/// //...
-/// let value: u32 = 17;
-/// let hash = u32::get_hash(&value, &hash_builder);
-/// ```
-/// Note that the type used to invoke `get_hash` must be the same a the type of value passed.
-/// For example get a hasher specialized on `[u8]` can invoke:
-/// ```
-/// /// use std::hash::BuildHasher;
-/// # use ahash::RandomState;
-/// # use ahash::CallHasher;
-/// # let hash_builder = RandomState::new();
-/// let bytes: [u8; 4] = [1, 2, 3, 4];
-/// let hash = <[u8]>::get_hash(&bytes, &hash_builder);
-/// ```
-pub trait CallHasher {
+pub(crate) trait CallHasher {
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64;
}
diff --git a/third_party/rust/ahash/tests/bench.rs b/third_party/rust/ahash/tests/bench.rs
index 9e6dccc481..2d000c0a6a 100644
--- a/third_party/rust/ahash/tests/bench.rs
+++ b/third_party/rust/ahash/tests/bench.rs
@@ -1,39 +1,35 @@
-use ahash::{CallHasher, RandomState};
+#![cfg_attr(feature = "specialize", feature(build_hasher_simple_hash_one))]
+
+use ahash::{AHasher, RandomState};
use criterion::*;
use fxhash::FxHasher;
+use rand::Rng;
use std::collections::hash_map::DefaultHasher;
-use std::hash::{Hash, Hasher};
-
-#[cfg(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-))]
-fn aeshash<H: Hash>(b: &H) -> u64 {
+use std::hash::{BuildHasherDefault, Hash, Hasher};
+
+// Needs to be in sync with `src/lib.rs`
+const AHASH_IMPL: &str = if cfg!(any(
+ all(
+ any(target_arch = "x86", target_arch = "x86_64"),
+ target_feature = "aes",
+ not(miri),
+ ),
+ all(feature = "nightly-arm-aes", target_arch = "aarch64", target_feature = "aes", not(miri)),
+ all(
+ feature = "nightly-arm-aes",
+ target_arch = "arm",
+ target_feature = "aes",
+ not(miri)
+ ),
+)) {
+ "aeshash"
+} else {
+ "fallbackhash"
+};
+
+fn ahash<H: Hash>(b: &H) -> u64 {
let build_hasher = RandomState::with_seeds(1, 2, 3, 4);
- H::get_hash(b, &build_hasher)
-}
-#[cfg(not(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-)))]
-fn aeshash<H: Hash>(_b: &H) -> u64 {
- panic!("aes must be enabled")
-}
-
-#[cfg(not(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-)))]
-fn fallbackhash<H: Hash>(b: &H) -> u64 {
- let build_hasher = RandomState::with_seeds(1, 2, 3, 4);
- H::get_hash(b, &build_hasher)
-}
-#[cfg(any(
- all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
- all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
-))]
-fn fallbackhash<H: Hash>(_b: &H) -> u64 {
- panic!("aes must be disabled")
+ build_hasher.hash_one(b)
}
fn fnvhash<H: Hash>(b: &H) -> u64 {
@@ -76,79 +72,128 @@ fn gen_strings() -> Vec<String> {
.collect()
}
-const U8_VALUE: u8 = 123;
-const U16_VALUE: u16 = 1234;
-const U32_VALUE: u32 = 12345678;
-const U64_VALUE: u64 = 1234567890123456;
-const U128_VALUE: u128 = 12345678901234567890123456789012;
-
-fn bench_ahash(c: &mut Criterion) {
- let mut group = c.benchmark_group("aeshash");
- group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(aeshash(s))));
- group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(aeshash(s))));
- group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(aeshash(s))));
- group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(aeshash(s))));
- group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(aeshash(s))));
- group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(aeshash(s))));
+macro_rules! bench_inputs {
+ ($group:ident, $hash:ident) => {
+ // Number of iterations per batch should be high enough to hide timing overhead.
+ let size = BatchSize::NumIterations(50_000);
+
+ let mut rng = rand::thread_rng();
+ $group.bench_function("u8", |b| b.iter_batched(|| rng.gen::<u8>(), |v| $hash(&v), size));
+ $group.bench_function("u16", |b| b.iter_batched(|| rng.gen::<u16>(), |v| $hash(&v), size));
+ $group.bench_function("u32", |b| b.iter_batched(|| rng.gen::<u32>(), |v| $hash(&v), size));
+ $group.bench_function("u64", |b| b.iter_batched(|| rng.gen::<u64>(), |v| $hash(&v), size));
+ $group.bench_function("u128", |b| b.iter_batched(|| rng.gen::<u128>(), |v| $hash(&v), size));
+ $group.bench_with_input("strings", &gen_strings(), |b, s| b.iter(|| $hash(black_box(s))));
+ };
}
-fn bench_fallback(c: &mut Criterion) {
- let mut group = c.benchmark_group("fallback");
- group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s))));
- group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s))));
- group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s))));
- group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s))));
- group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(fallbackhash(s))));
- group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(fallbackhash(s))));
+fn bench_ahash(c: &mut Criterion) {
+ let mut group = c.benchmark_group(AHASH_IMPL);
+ bench_inputs!(group, ahash);
}
fn bench_fx(c: &mut Criterion) {
let mut group = c.benchmark_group("fx");
- group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(fxhash(s))));
- group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(fxhash(s))));
- group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(fxhash(s))));
- group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(fxhash(s))));
- group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(fxhash(s))));
- group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(fxhash(s))));
+ bench_inputs!(group, fxhash);
}
fn bench_fnv(c: &mut Criterion) {
let mut group = c.benchmark_group("fnv");
- group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(fnvhash(s))));
- group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(fnvhash(s))));
- group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(fnvhash(s))));
- group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(fnvhash(s))));
- group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(fnvhash(s))));
- group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(fnvhash(s))));
+ bench_inputs!(group, fnvhash);
}
fn bench_sea(c: &mut Criterion) {
let mut group = c.benchmark_group("sea");
- group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(seahash(s))));
- group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(seahash(s))));
- group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(seahash(s))));
- group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(seahash(s))));
- group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(seahash(s))));
- group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(seahash(s))));
+ bench_inputs!(group, seahash);
}
fn bench_sip(c: &mut Criterion) {
let mut group = c.benchmark_group("sip");
- group.bench_with_input("u8", &U8_VALUE, |b, s| b.iter(|| black_box(siphash(s))));
- group.bench_with_input("u16", &U16_VALUE, |b, s| b.iter(|| black_box(siphash(s))));
- group.bench_with_input("u32", &U32_VALUE, |b, s| b.iter(|| black_box(siphash(s))));
- group.bench_with_input("u64", &U64_VALUE, |b, s| b.iter(|| black_box(siphash(s))));
- group.bench_with_input("u128", &U128_VALUE, |b, s| b.iter(|| black_box(siphash(s))));
- group.bench_with_input("string", &gen_strings(), |b, s| b.iter(|| black_box(siphash(s))));
+ bench_inputs!(group, siphash);
+}
+
+fn bench_map(c: &mut Criterion) {
+ #[cfg(feature = "std")]
+ {
+ let mut group = c.benchmark_group("map");
+ group.bench_function("aHash-alias", |b| {
+ b.iter(|| {
+ let hm: ahash::HashMap<i32, i32> = (0..1_000_000).map(|i| (i, i)).collect();
+ let mut sum = 0;
+ for i in 0..1_000_000 {
+ if let Some(x) = hm.get(&i) {
+ sum += x;
+ }
+ }
+ })
+ });
+ group.bench_function("aHash-hashBrown", |b| {
+ b.iter(|| {
+ let hm: hashbrown::HashMap<i32, i32> = (0..1_000_000).map(|i| (i, i)).collect();
+ let mut sum = 0;
+ for i in 0..1_000_000 {
+ if let Some(x) = hm.get(&i) {
+ sum += x;
+ }
+ }
+ })
+ });
+ group.bench_function("aHash-hashBrown-explicit", |b| {
+ b.iter(|| {
+ let hm: hashbrown::HashMap<i32, i32, RandomState> = (0..1_000_000).map(|i| (i, i)).collect();
+ let mut sum = 0;
+ for i in 0..1_000_000 {
+ if let Some(x) = hm.get(&i) {
+ sum += x;
+ }
+ }
+ })
+ });
+ group.bench_function("aHash-wrapper", |b| {
+ b.iter(|| {
+ let hm: ahash::AHashMap<i32, i32> = (0..1_000_000).map(|i| (i, i)).collect();
+ let mut sum = 0;
+ for i in 0..1_000_000 {
+ if let Some(x) = hm.get(&i) {
+ sum += x;
+ }
+ }
+ })
+ });
+ group.bench_function("aHash-rand", |b| {
+ b.iter(|| {
+ let hm: std::collections::HashMap<i32, i32, RandomState> = (0..1_000_000).map(|i| (i, i)).collect();
+ let mut sum = 0;
+ for i in 0..1_000_000 {
+ if let Some(x) = hm.get(&i) {
+ sum += x;
+ }
+ }
+ })
+ });
+ group.bench_function("aHash-default", |b| {
+ b.iter(|| {
+ let hm: std::collections::HashMap<i32, i32, BuildHasherDefault<AHasher>> =
+ (0..1_000_000).map(|i| (i, i)).collect();
+ let mut sum = 0;
+ for i in 0..1_000_000 {
+ if let Some(x) = hm.get(&i) {
+ sum += x;
+ }
+ }
+ })
+ });
+ }
}
criterion_main!(benches);
+
criterion_group!(
benches,
bench_ahash,
- bench_fallback,
bench_fx,
bench_fnv,
bench_sea,
- bench_sip
+ bench_sip,
+ bench_map
);
diff --git a/third_party/rust/ahash/tests/map_tests.rs b/third_party/rust/ahash/tests/map_tests.rs
index be617a2e72..97fdbee0f9 100644
--- a/third_party/rust/ahash/tests/map_tests.rs
+++ b/third_party/rust/ahash/tests/map_tests.rs
@@ -1,10 +1,11 @@
+#![cfg_attr(feature = "specialize", feature(build_hasher_simple_hash_one))]
+
use std::hash::{BuildHasher, Hash, Hasher};
+use ahash::RandomState;
use criterion::*;
use fxhash::FxHasher;
-use ahash::{AHasher, CallHasher, RandomState};
-
fn gen_word_pairs() -> Vec<String> {
let words: Vec<_> = r#"
a, ability, able, about, above, accept, according, account, across, act, action,
@@ -150,9 +151,18 @@ fn check_for_collisions<H: Hash, B: BuildHasher>(build_hasher: &B, items: &[H],
);
}
+#[cfg(feature = "specialize")]
+#[allow(unused)] // False positive
+fn hash<H: Hash, B: BuildHasher>(b: &H, build_hasher: &B) -> u64 {
+ build_hasher.hash_one(b)
+}
+
+#[cfg(not(feature = "specialize"))]
#[allow(unused)] // False positive
fn hash<H: Hash, B: BuildHasher>(b: &H, build_hasher: &B) -> u64 {
- H::get_hash(b, build_hasher)
+ let mut hasher = build_hasher.build_hasher();
+ b.hash(&mut hasher);
+ hasher.finish()
}
#[test]
@@ -169,10 +179,107 @@ fn test_bucket_distribution() {
check_for_collisions(&build_hasher, &sequence, 256);
}
+#[cfg(feature = "std")]
+#[test]
+fn test_ahash_alias_map_construction() {
+ let mut map = ahash::HashMap::default();
+ map.insert(1, "test");
+ use ahash::HashMapExt;
+ let mut map = ahash::HashMap::with_capacity(1234);
+ map.insert(1, "test");
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn test_ahash_alias_set_construction() {
+ let mut set = ahash::HashSet::default();
+ set.insert(1);
+
+ use ahash::HashSetExt;
+ let mut set = ahash::HashSet::with_capacity(1235);
+ set.insert(1);
+}
+
+
+#[cfg(feature = "std")]
+#[test]
+fn test_key_ref() {
+ let mut map = ahash::HashMap::default();
+ map.insert(1, "test");
+ assert_eq!(Some((1, "test")), map.remove_entry(&1));
+
+ let mut map = ahash::HashMap::default();
+ map.insert(&1, "test");
+ assert_eq!(Some((&1, "test")), map.remove_entry(&&1));
+
+ let mut m = ahash::HashSet::<Box<String>>::default();
+ m.insert(Box::from("hello".to_string()));
+ assert!(m.contains(&"hello".to_string()));
+
+ let mut m = ahash::HashSet::<String>::default();
+ m.insert("hello".to_string());
+ assert!(m.contains("hello"));
+
+ let mut m = ahash::HashSet::<Box<[u8]>>::default();
+ m.insert(Box::from(&b"hello"[..]));
+ assert!(m.contains(&b"hello"[..]));
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn test_byte_dist() {
+ use rand::{SeedableRng, Rng, RngCore};
+ use pcg_mwc::Mwc256XXA64;
+
+ let mut r = Mwc256XXA64::seed_from_u64(0xe786_c22b_119c_1479);
+ let mut lowest = 2.541;
+ let mut highest = 2.541;
+ for _round in 0..100 {
+ let mut table: [bool; 256 * 8] = [false; 256 * 8];
+ let hasher = RandomState::with_seeds(r.gen(), r.gen(), r.gen(), r.gen());
+ for i in 0..128 {
+ let mut keys: [u8; 8] = hasher.hash_one((i as u64) << 30).to_ne_bytes();
+ //let mut keys = r.next_u64().to_ne_bytes(); //This is a control to test assert sensitivity.
+ for idx in 0..8 {
+ while table[idx * 256 + keys[idx] as usize] {
+ keys[idx] = keys[idx].wrapping_add(1);
+ }
+ table[idx * 256 + keys[idx] as usize] = true;
+ }
+ }
+
+ for idx in 0..8 {
+ let mut len = 0;
+ let mut total_len = 0;
+ let mut num_seq = 0;
+ for i in 0..256 {
+ if table[idx * 256 + i] {
+ len += 1;
+ } else if len != 0 {
+ num_seq += 1;
+ total_len += len;
+ len = 0;
+ }
+ }
+ let mean = total_len as f32 / num_seq as f32;
+ println!("Mean sequence length = {}", mean);
+ if mean > highest {
+ highest = mean;
+ }
+ if mean < lowest {
+ lowest = mean;
+ }
+ }
+ }
+ assert!(lowest > 1.9, "Lowest = {}", lowest);
+ assert!(highest < 3.9, "Highest = {}", highest);
+}
+
+
fn ahash_vec<H: Hash>(b: &Vec<H>) -> u64 {
let mut total: u64 = 0;
for item in b {
- let mut hasher = AHasher::new_with_keys(1234, 5678);
+ let mut hasher = RandomState::with_seeds(12, 34, 56, 78).build_hasher();
item.hash(&mut hasher);
total = total.wrapping_add(hasher.finish());
}
diff --git a/third_party/rust/ahash/tests/nopanic.rs b/third_party/rust/ahash/tests/nopanic.rs
index d48ff559d2..56f754cbee 100644
--- a/third_party/rust/ahash/tests/nopanic.rs
+++ b/third_party/rust/ahash/tests/nopanic.rs
@@ -1,5 +1,5 @@
-use ahash::{AHasher, CallHasher, RandomState};
-use std::hash::BuildHasher;
+use ahash::{AHasher, RandomState};
+use std::hash::{BuildHasher, Hash, Hasher};
#[macro_use]
extern crate no_panic;
@@ -8,8 +8,8 @@ extern crate no_panic;
#[no_panic]
fn hash_test_final(num: i32, string: &str) -> (u64, u64) {
use core::hash::Hasher;
- let mut hasher1 = AHasher::new_with_keys(1, 2);
- let mut hasher2 = AHasher::new_with_keys(3, 4);
+ let mut hasher1 = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
+ let mut hasher2 = RandomState::with_seeds(3, 4, 5, 6).build_hasher();
hasher1.write_i32(num);
hasher2.write(string.as_bytes());
(hasher1.finish(), hasher2.finish())
@@ -24,6 +24,17 @@ struct SimpleBuildHasher {
hasher: AHasher,
}
+impl SimpleBuildHasher {
+ fn hash_one<T: Hash>(&self, x: T) -> u64
+ where
+ Self: Sized,
+ {
+ let mut hasher = self.build_hasher();
+ x.hash(&mut hasher);
+ hasher.finish()
+ }
+}
+
impl BuildHasher for SimpleBuildHasher {
type Hasher = AHasher;
@@ -35,11 +46,11 @@ impl BuildHasher for SimpleBuildHasher {
#[inline(never)]
#[no_panic]
fn hash_test_specialize(num: i32, string: &str) -> (u64, u64) {
- let hasher1 = AHasher::new_with_keys(1, 2);
- let hasher2 = AHasher::new_with_keys(1, 2);
+ let hasher1 = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
+ let hasher2 = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
(
- i32::get_hash(&num, &SimpleBuildHasher { hasher: hasher1 }),
- <[u8]>::get_hash(string.as_bytes(), &SimpleBuildHasher { hasher: hasher2 }),
+ SimpleBuildHasher { hasher: hasher1 }.hash_one(num),
+ SimpleBuildHasher { hasher: hasher2 }.hash_one(string.as_bytes()),
)
}
@@ -53,10 +64,7 @@ fn hash_test_random_wrapper(num: i32, string: &str) {
fn hash_test_random(num: i32, string: &str) -> (u64, u64) {
let build_hasher1 = RandomState::with_seeds(1, 2, 3, 4);
let build_hasher2 = RandomState::with_seeds(1, 2, 3, 4);
- (
- i32::get_hash(&num, &build_hasher1),
- <[u8]>::get_hash(string.as_bytes(), &build_hasher2),
- )
+ (build_hasher1.hash_one(&num), build_hasher2.hash_one(string.as_bytes()))
}
#[inline(never)]
@@ -68,5 +76,6 @@ fn hash_test_specialize_wrapper(num: i32, string: &str) {
fn test_no_panic() {
hash_test_final_wrapper(2, "Foo");
hash_test_specialize_wrapper(2, "Bar");
- hash_test_random_wrapper(2, "Baz");
+ hash_test_random(2, "Baz");
+ hash_test_random_wrapper(2, "Bat");
}
diff --git a/third_party/rust/any_all_workaround/.cargo-checksum.json b/third_party/rust/any_all_workaround/.cargo-checksum.json
new file mode 100644
index 0000000000..8d16e68a7e
--- /dev/null
+++ b/third_party/rust/any_all_workaround/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"f8c127449dc9432d404c21c99833e4617ab88a797445af249a7fe3c989985d6d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","LICENSE-MIT-QCMS":"36d847ae882f6574ebc72f56a4f354e4f104fde4a584373496482e97d52d31bc","README.md":"4c617b8ced3a27b7edecf0e5e41ed451c04e88dab529e7a35fccc4e1551efbd7","build.rs":"56b29ab6da3e49075bfd0a7b690267c8016298bf0d332e2e68bbaf19decbbf71","src/lib.rs":"7118106690b9d25c5d0a3e2079feb83d76f1d434d0da36b9d0351806d27c850d"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/any_all_workaround/Cargo.toml b/third_party/rust/any_all_workaround/Cargo.toml
new file mode 100644
index 0000000000..4b03a35781
--- /dev/null
+++ b/third_party/rust/any_all_workaround/Cargo.toml
@@ -0,0 +1,28 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+name = "any_all_workaround"
+version = "0.1.0"
+authors = ["Henri Sivonen <hsivonen@hsivonen.fi>"]
+description = "Workaround for bad LLVM codegen for boolean reductions on 32-bit ARM"
+homepage = "https://docs.rs/any_all_workaround/"
+documentation = "https://docs.rs/any_all_workaround/"
+readme = "README.md"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/hsivonen/any_all_workaround"
+
+[dependencies]
+cfg-if = "1.0"
+
+[build-dependencies]
+version_check = "0.9"
diff --git a/third_party/rust/packed_simd/LICENSE-APACHE b/third_party/rust/any_all_workaround/LICENSE-APACHE
index 16fe87b06e..16fe87b06e 100644
--- a/third_party/rust/packed_simd/LICENSE-APACHE
+++ b/third_party/rust/any_all_workaround/LICENSE-APACHE
diff --git a/third_party/rust/packed_simd/LICENSE-MIT b/third_party/rust/any_all_workaround/LICENSE-MIT
index 39d4bdb5ac..39d4bdb5ac 100644
--- a/third_party/rust/packed_simd/LICENSE-MIT
+++ b/third_party/rust/any_all_workaround/LICENSE-MIT
diff --git a/third_party/rust/any_all_workaround/LICENSE-MIT-QCMS b/third_party/rust/any_all_workaround/LICENSE-MIT-QCMS
new file mode 100644
index 0000000000..eec8246dfa
--- /dev/null
+++ b/third_party/rust/any_all_workaround/LICENSE-MIT-QCMS
@@ -0,0 +1,21 @@
+qcms
+Copyright (C) 2009-2024 Mozilla Corporation
+Copyright (C) 1998-2007 Marti Maria
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/any_all_workaround/README.md b/third_party/rust/any_all_workaround/README.md
new file mode 100644
index 0000000000..9f83ac3695
--- /dev/null
+++ b/third_party/rust/any_all_workaround/README.md
@@ -0,0 +1,13 @@
+# any_all_workaround
+
+This is a workaround for bad codegen ([Rust bug](https://github.com/rust-lang/portable-simd/issues/146), [LLVM bug](https://github.com/llvm/llvm-project/issues/50466)) for the `any()` and `all()` reductions for NEON-backed SIMD vectors on 32-bit ARM. On other platforms these delegate to `any()` and `all()` in `core::simd`.
+
+The plan is to abandon this crate once the LLVM bug is fixed or `core::simd` works around the LLVM bug.
+
+The code is forked from the [`packed_simd` crate](https://raw.githubusercontent.com/hsivonen/packed_simd/d938e39bee9bc5c222f5f2f2a0df9e53b5ce36ae/src/codegen/reductions/mask/arm.rs).
+
+This crate requires Nightly Rust as it depends on the `portable_simd` feature.
+
+# License
+
+`MIT OR Apache-2.0`, since that's how `packed_simd` is licensed. (The ARM intrinsics Rust version workaround is from qcms, see LICENSE-MIT-QCMS.)
diff --git a/third_party/rust/any_all_workaround/build.rs b/third_party/rust/any_all_workaround/build.rs
new file mode 100644
index 0000000000..6810a8828e
--- /dev/null
+++ b/third_party/rust/any_all_workaround/build.rs
@@ -0,0 +1,7 @@
+extern crate version_check as rustc;
+
+fn main() {
+ if rustc::is_min_version("1.78.0").unwrap_or(false) {
+ println!("cargo:rustc-cfg=stdsimd_split");
+ }
+}
diff --git a/third_party/rust/any_all_workaround/src/lib.rs b/third_party/rust/any_all_workaround/src/lib.rs
new file mode 100644
index 0000000000..f0b8b13609
--- /dev/null
+++ b/third_party/rust/any_all_workaround/src/lib.rs
@@ -0,0 +1,110 @@
+// This code began as a fork of
+// https://raw.githubusercontent.com/rust-lang/packed_simd/d938e39bee9bc5c222f5f2f2a0df9e53b5ce36ae/src/codegen/reductions/mask/arm.rs
+// which didn't have a license header on the file, but Cargo.toml said "MIT OR Apache-2.0".
+// See LICENSE-MIT and LICENSE-APACHE.
+
+#![no_std]
+#![feature(portable_simd)]
+#![cfg_attr(
+ all(
+ stdsimd_split,
+ target_arch = "arm",
+ target_endian = "little",
+ target_feature = "neon",
+ target_feature = "v7"
+ ),
+ feature(stdarch_arm_neon_intrinsics)
+)]
+#![cfg_attr(
+ all(
+ not(stdsimd_split),
+ target_arch = "arm",
+ target_endian = "little",
+ target_feature = "neon",
+ target_feature = "v7"
+ ),
+ feature(stdsimd)
+)]
+
+use cfg_if::cfg_if;
+use core::simd::mask16x8;
+use core::simd::mask32x4;
+use core::simd::mask8x16;
+
+cfg_if! {
+ if #[cfg(all(target_arch = "arm", target_endian = "little", target_feature = "neon", target_feature = "v7"))] {
+ use core::simd::mask8x8;
+ use core::simd::mask16x4;
+ use core::simd::mask32x2;
+ macro_rules! arm_128_v7_neon_impl {
+ ($all:ident, $any:ident, $id:ident, $half:ident, $vpmin:ident, $vpmax:ident) => {
+ #[inline]
+ pub fn $all(s: $id) -> bool {
+ use core::arch::arm::$vpmin;
+ use core::mem::transmute;
+ unsafe {
+ union U {
+ halves: ($half, $half),
+ vec: $id,
+ }
+ let halves = U { vec: s }.halves;
+ let h: $half = transmute($vpmin(transmute(halves.0), transmute(halves.1)));
+ h.all()
+ }
+ }
+ #[inline]
+ pub fn $any(s: $id) -> bool {
+ use core::arch::arm::$vpmax;
+ use core::mem::transmute;
+ unsafe {
+ union U {
+ halves: ($half, $half),
+ vec: $id,
+ }
+ let halves = U { vec: s }.halves;
+ let h: $half = transmute($vpmax(transmute(halves.0), transmute(halves.1)));
+ h.any()
+ }
+ }
+ }
+ }
+ } else {
+ macro_rules! arm_128_v7_neon_impl {
+ ($all:ident, $any:ident, $id:ident, $half:ident, $vpmin:ident, $vpmax:ident) => {
+ #[inline(always)]
+ pub fn $all(s: $id) -> bool {
+ s.all()
+ }
+ #[inline(always)]
+ pub fn $any(s: $id) -> bool {
+ s.any()
+ }
+ }
+ }
+ }
+}
+
+arm_128_v7_neon_impl!(
+ all_mask8x16,
+ any_mask8x16,
+ mask8x16,
+ mask8x8,
+ vpmin_u8,
+ vpmax_u8
+);
+arm_128_v7_neon_impl!(
+ all_mask16x8,
+ any_mask16x8,
+ mask16x8,
+ mask16x4,
+ vpmin_u16,
+ vpmax_u16
+);
+arm_128_v7_neon_impl!(
+ all_mask32x4,
+ any_mask32x4,
+ mask32x4,
+ mask32x2,
+ vpmin_u32,
+ vpmax_u32
+);
diff --git a/third_party/rust/audio-mixer/.cargo-checksum.json b/third_party/rust/audio-mixer/.cargo-checksum.json
index 4fbdd1518d..9872eab023 100644
--- a/third_party/rust/audio-mixer/.cargo-checksum.json
+++ b/third_party/rust/audio-mixer/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"ac8d6a7af46ee8f72d22abb80575109b75bcb2a20ea6cacb6626a20f337fe51f","Cargo.toml":"9316753099606b9531ea52aec87270a83e74c15b6563f8f979b0e961e0cf73fd","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"e2e6b7d80550743e01faa26c19f6c8520fd0dc5db68021c042fd523eed46c799","benches/benchmark.rs":"33e9d85cee38fb7752e9315ccf5f816179309062bfb78118288f7e1495e3616f","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_sanitizers.sh":"e31b4a11559b52043920c63e6ad4e57051d6205883ecf2b2c48e105ba522015b","run_tests.sh":"21ca30cb6d41c6b35e6207e3283292933ef6628575dd587287fad6db2afb22bd","src/channel.rs":"d948d890219b810632277d2b04297334a47dc6639ef93309e74495ff408f82b6","src/coefficient.rs":"24f56281a1b800769feefc735d77c2ec03f1aa8d7c58c256b25ce1a9053a06cc","src/lib.rs":"f0ee59ac224ce6ba0cc6cb9e1796e85b9b751ba4d92c58fe3fb8b10c95b72cc4","src/main.rs":"b5ba05638c727040581c49ffd2d784493af658495cd424ce8c9365f779994baf"},"package":"c41dc008c1973ce58ff3cfc52df53814a9b7b78d73d95b071b5ff0ed4b2db3e1"} \ No newline at end of file
+{"files":{"Cargo.lock":"819b29d15e418e551415a161f56eee3d2848f4e2e0936a4d8f3d4be11d2ef598","Cargo.toml":"b3de055f40a2d1895630310c8b41d7dd86fcd99b5c719f625e5ddaa9c2a3775d","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"e2e6b7d80550743e01faa26c19f6c8520fd0dc5db68021c042fd523eed46c799","benches/benchmark.rs":"33e9d85cee38fb7752e9315ccf5f816179309062bfb78118288f7e1495e3616f","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_sanitizers.sh":"e31b4a11559b52043920c63e6ad4e57051d6205883ecf2b2c48e105ba522015b","run_tests.sh":"21ca30cb6d41c6b35e6207e3283292933ef6628575dd587287fad6db2afb22bd","src/channel.rs":"243a51c37d07755b67bcce54ca2a27e0f3099b4ea510a7b7e60c4b3f17402167","src/coefficient.rs":"64a6cda5fc8630f033c80717616183f6e172da5fd2d338028e52f77d8b7e0830","src/lib.rs":"f0ee59ac224ce6ba0cc6cb9e1796e85b9b751ba4d92c58fe3fb8b10c95b72cc4","src/main.rs":"b5ba05638c727040581c49ffd2d784493af658495cd424ce8c9365f779994baf"},"package":"4f1245ab2f85c284bac1ac1f03565539644566295ef6eb9c4eae42e9a40c51b2"} \ No newline at end of file
diff --git a/third_party/rust/audio-mixer/Cargo.lock b/third_party/rust/audio-mixer/Cargo.lock
index 68d1ba2441..ac92b80559 100644
--- a/third_party/rust/audio-mixer/Cargo.lock
+++ b/third_party/rust/audio-mixer/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "aho-corasick"
-version = "1.1.0"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
@@ -17,14 +17,14 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi 0.1.19",
+ "hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "audio-mixer"
-version = "0.1.3"
+version = "0.2.0"
dependencies = [
"bitflags",
"criterion",
@@ -33,9 +33,9 @@ dependencies = [
[[package]]
name = "autocfg"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "bitflags"
@@ -45,9 +45,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
-version = "3.14.0"
+version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "cast"
@@ -109,53 +109,35 @@ dependencies = [
]
[[package]]
-name = "crossbeam-channel"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
-[[package]]
name = "crossbeam-deque"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
- "cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
-version = "0.9.15"
+version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
- "autocfg",
- "cfg-if",
"crossbeam-utils",
- "memoffset",
- "scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.16"
+version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
-dependencies = [
- "cfg-if",
-]
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "csv"
-version = "1.2.2"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086"
+checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
dependencies = [
"csv-core",
"itoa",
@@ -165,18 +147,18 @@ dependencies = [
[[package]]
name = "csv-core"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
dependencies = [
"memchr",
]
[[package]]
name = "either"
-version = "1.9.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
[[package]]
name = "float-cmp"
@@ -189,9 +171,9 @@ dependencies = [
[[package]]
name = "half"
-version = "1.8.2"
+version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
+checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
[[package]]
name = "hermit-abi"
@@ -203,12 +185,6 @@ dependencies = [
]
[[package]]
-name = "hermit-abi"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
-
-[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -219,15 +195,15 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.9"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
-version = "0.3.64"
+version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
@@ -240,55 +216,36 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.148"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "log"
-version = "0.4.20"
+version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
-version = "2.6.3"
+version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
-
-[[package]]
-name = "memoffset"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
-dependencies = [
- "autocfg",
-]
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "num-traits"
-version = "0.2.16"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
-name = "num_cpus"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
-dependencies = [
- "hermit-abi 0.3.2",
- "libc",
-]
-
-[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oorandom"
@@ -326,27 +283,27 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.67"
+version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
+checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.33"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
-version = "1.7.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
@@ -354,21 +311,19 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.11.0"
+version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
- "crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
- "num_cpus",
]
[[package]]
name = "regex"
-version = "1.9.5"
+version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
+checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
@@ -378,9 +333,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.3.8"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
@@ -389,15 +344,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.7.5"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "ryu"
-version = "1.0.15"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "same-file"
@@ -409,16 +364,10 @@ dependencies = [
]
[[package]]
-name = "scopeguard"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-[[package]]
name = "serde"
-version = "1.0.188"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
@@ -435,9 +384,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.188"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
@@ -446,9 +395,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.107"
+version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
+checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
dependencies = [
"itoa",
"ryu",
@@ -457,9 +406,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.37"
+version = "2.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
+checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a"
dependencies = [
"proc-macro2",
"quote",
@@ -493,15 +442,15 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "walkdir"
-version = "2.4.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
@@ -509,9 +458,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -519,9 +468,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
@@ -534,9 +483,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -544,9 +493,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
@@ -557,15 +506,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "web-sys"
-version = "0.3.64"
+version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -589,9 +538,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
diff --git a/third_party/rust/audio-mixer/Cargo.toml b/third_party/rust/audio-mixer/Cargo.toml
index 92293f25db..703d89bd23 100644
--- a/third_party/rust/audio-mixer/Cargo.toml
+++ b/third_party/rust/audio-mixer/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "audio-mixer"
-version = "0.1.3"
+version = "0.2.0"
authors = ["Chun-Min Chang <chun.m.chang@gmail.com>"]
description = "Mixing audio by the input and output channel layout"
readme = "README.md"
diff --git a/third_party/rust/audio-mixer/src/channel.rs b/third_party/rust/audio-mixer/src/channel.rs
index b32936895e..d913df39e8 100644
--- a/third_party/rust/audio-mixer/src/channel.rs
+++ b/third_party/rust/audio-mixer/src/channel.rs
@@ -21,6 +21,7 @@ pub enum Channel {
TopBackCenter = 16,
TopBackRight = 17,
Silence = 18,
+ Discrete = 19, // To be used based on its index
}
impl Channel {
@@ -29,7 +30,7 @@ impl Channel {
}
pub const fn count() -> usize {
- Channel::Silence as usize + 1
+ Channel::Discrete as usize + 1
}
pub const fn bitmask(self) -> u32 {
@@ -58,6 +59,7 @@ bitflags! {
const TOP_BACK_CENTER = Channel::TopBackCenter.bitmask();
const TOP_BACK_RIGHT = Channel::TopBackRight.bitmask();
const SILENCE = Channel::Silence.bitmask();
+ const DISCRETE = Channel::Discrete.bitmask();
}
}
diff --git a/third_party/rust/audio-mixer/src/coefficient.rs b/third_party/rust/audio-mixer/src/coefficient.rs
index 799d50289c..c7999ee929 100644
--- a/third_party/rust/audio-mixer/src/coefficient.rs
+++ b/third_party/rust/audio-mixer/src/coefficient.rs
@@ -9,7 +9,7 @@ const CHANNELS: usize = Channel::count();
#[derive(Debug)]
enum Error {
- DuplicateNonSilenceChannel,
+ DuplicateChannel,
AsymmetricChannels,
}
@@ -28,13 +28,15 @@ impl ChannelLayout {
})
}
- // Except Silence channel, the duplicate channels are not allowed.
+ // Except Silence and Discrete channels, duplicate channels aren't allowed.
fn get_channel_map(channels: &[Channel]) -> Result<ChannelMap, Error> {
let mut map = ChannelMap::empty();
for channel in channels {
let bitmask = ChannelMap::from(*channel);
- if channel != &Channel::Silence && map.contains(bitmask) {
- return Err(Error::DuplicateNonSilenceChannel);
+ if (channel != &Channel::Silence && channel != &Channel::Discrete)
+ && map.contains(bitmask)
+ {
+ return Err(Error::DuplicateChannel);
}
map.insert(bitmask);
}
@@ -83,15 +85,41 @@ where
let input_layout = ChannelLayout::new(input_channels).expect("Invalid input layout");
let output_layout = ChannelLayout::new(output_channels).expect("Invalid output layout");
- let mixing_matrix =
- Self::build_mixing_matrix(input_layout.channel_map, output_layout.channel_map)
- .unwrap_or_else(|_| Self::get_basic_matrix());
-
- let coefficient_matrix = Self::pick_coefficients(
- &input_layout.channels,
- &output_layout.channels,
- &mixing_matrix,
- );
+ // Check if this is a professional audio interface rather than a sound card for playback, in
+ // which case it is expected to simply pass all the channel through without change.
+ // Those interfaces only have an explicit mapping for the stereo pair, but have lots of channels.
+ let mut only_stereo_or_discrete = true;
+ for channel in output_channels {
+ if *channel != Channel::Discrete
+ && *channel != Channel::FrontLeft
+ && *channel != Channel::FrontRight
+ {
+ only_stereo_or_discrete = false;
+ break;
+ }
+ }
+ let coefficient_matrix = if only_stereo_or_discrete && output_channels.len() > 2 {
+ let mut matrix = Vec::with_capacity(output_channels.len());
+ // Create a diagonal line of 1.0 for input channels
+ for (output_channel_index, _) in output_channels.iter().enumerate() {
+ let mut coefficients = Vec::with_capacity(input_channels.len());
+ coefficients.resize(input_channels.len(), 0.0);
+ if output_channel_index < coefficients.len() {
+ coefficients[output_channel_index] = 1.0;
+ }
+ matrix.push(coefficients);
+ }
+ matrix
+ } else {
+ let mixing_matrix =
+ Self::build_mixing_matrix(input_layout.channel_map, output_layout.channel_map)
+ .unwrap_or_else(|_| Self::get_basic_matrix());
+ Self::pick_coefficients(
+ &input_layout.channels,
+ &output_layout.channels,
+ &mixing_matrix,
+ )
+ };
let normalized_matrix = Self::normalize(T::max_coefficients_sum(), coefficient_matrix);
@@ -430,7 +458,7 @@ impl MixingCoefficient for f32 {
type Coef = f32;
fn max_coefficients_sum() -> f64 {
- f64::from(std::i32::MAX)
+ f64::from(i32::MAX)
}
fn coefficient_from_f64(value: f64) -> Self::Coef {
@@ -550,12 +578,12 @@ mod test {
#[test]
fn test_create_with_duplicate_silience_channels_f32() {
- test_create_with_duplicate_silience_channels::<f32>()
+ test_create_with_duplicate_channels::<f32>()
}
#[test]
fn test_create_with_duplicate_silience_channels_i16() {
- test_create_with_duplicate_silience_channels::<i16>()
+ test_create_with_duplicate_channels::<i16>()
}
#[test]
@@ -582,7 +610,7 @@ mod test {
test_create_with_duplicate_output_channels::<i16>()
}
- fn test_create_with_duplicate_silience_channels<T>()
+ fn test_create_with_duplicate_channels<T>()
where
T: MixingCoefficient,
T::Coef: Copy,
@@ -649,78 +677,155 @@ mod test {
}
#[test]
- fn test_get_redirect_matrix_f32() {
- test_get_redirect_matrix::<f32>();
+ fn test_get_discrete_mapping() {
+ test_get_discrete_mapping_matrix::<f32>();
+ test_get_discrete_mapping_matrix::<i16>();
}
#[test]
- fn test_get_redirect_matrix_i16() {
- test_get_redirect_matrix::<i16>();
+ fn test_get_discrete_mapping_too_many_channels() {
+ test_get_discrete_mapping_matrix_too_many_channels::<i16>();
+ test_get_discrete_mapping_matrix_too_many_channels::<f32>();
}
- fn test_get_redirect_matrix<T>()
- where
+ #[test]
+ fn test_get_regular_mapping_too_many_channels() {
+ test_get_regular_mapping_matrix_too_many_channels::<i16>();
+ test_get_regular_mapping_matrix_too_many_channels::<f32>();
+ }
+
+ // Check that a matrix is diagonal (1.0 on the diagnoal, 0.0 elsewhere). It's valid to have more input or output channels
+ fn assert_is_diagonal<T>(
+ coefficients: &Coefficient<T>,
+ input_channels: usize,
+ output_channels: usize,
+ ) where
T: MixingCoefficient,
T::Coef: Copy + Debug + PartialEq,
{
- // Create a matrix that only redirect the channels from input side to output side,
- // without mixing input audio data to output audio data.
- fn compute_redirect_matrix<T>(
- input_channels: &[Channel],
- output_channels: &[Channel],
- ) -> Vec<Vec<T::Coef>>
- where
- T: MixingCoefficient,
- {
- let mut matrix = Vec::with_capacity(output_channels.len());
- for output_channel in output_channels {
- let mut row = Vec::with_capacity(input_channels.len());
- for input_channel in input_channels {
- row.push(
- if input_channel != output_channel
- || input_channel == &Channel::Silence
- || output_channel == &Channel::Silence
- {
- 0.0
- } else {
- 1.0
- },
- );
+ for i in 0..input_channels {
+ for j in 0..output_channels {
+ if i == j {
+ assert_eq!(coefficients.get(i, j), T::coefficient_from_f64(1.0));
+ } else {
+ assert_eq!(coefficients.get(i, j), T::coefficient_from_f64(0.0));
}
- matrix.push(row);
}
-
- // Convert the type of the coefficients from f64 to T::Coef.
- matrix
- .into_iter()
- .map(|row| row.into_iter().map(T::coefficient_from_f64).collect())
- .collect()
}
+ println!(
+ "{:?} = {:?} * {:?}",
+ output_channels, coefficients.matrix, input_channels
+ );
+ }
+ fn test_get_discrete_mapping_matrix<T>()
+ where
+ T: MixingCoefficient,
+ T::Coef: Copy + Debug + PartialEq,
+ {
+ // typical 5.1
let input_channels = [
Channel::FrontLeft,
- Channel::Silence,
Channel::FrontRight,
Channel::FrontCenter,
+ Channel::BackLeft,
+ Channel::BackRight,
+ Channel::LowFrequency,
];
+ // going into 8 channels with a tagged stereo pair and discrete channels
let output_channels = [
- Channel::Silence,
Channel::FrontLeft,
- Channel::Silence,
+ Channel::FrontRight,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
+ ];
+
+ // Get a pass-through matrix in the first 6 channels
+ let coefficients = Coefficient::<T>::create(&input_channels, &output_channels);
+ assert_is_diagonal::<T>(&coefficients, input_channels.len(), output_channels.len());
+ }
+
+ fn test_get_discrete_mapping_matrix_too_many_channels<T>()
+ where
+ T: MixingCoefficient,
+ T::Coef: Copy + Debug + PartialEq,
+ {
+ // 5.1.4
+ let input_channels = [
+ Channel::FrontLeft,
+ Channel::FrontRight,
Channel::FrontCenter,
- Channel::BackCenter,
+ Channel::LowFrequency,
+ Channel::FrontLeftOfCenter,
+ Channel::FrontRightOfCenter,
+ Channel::TopFrontLeft,
+ Channel::TopFrontRight,
+ Channel::BackLeft,
+ Channel::BackRight,
+ ];
+ // going into 8 channels with a tagged stereo pair and discrete channels
+ let output_channels = [
+ Channel::FrontLeft,
+ Channel::FrontRight,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
+ Channel::Discrete,
];
- // Get a redirect matrix since the output layout is asymmetric.
- let coefficient = Coefficient::<T>::create(&input_channels, &output_channels);
+ // First 8 channels are to be played, last two are to be dropped.
+ let coefficients = Coefficient::<T>::create(&input_channels, &output_channels);
+ assert_is_diagonal(&coefficients, input_channels.len(), output_channels.len());
+ }
+
+ fn test_get_regular_mapping_matrix_too_many_channels<T>()
+ where
+ T: MixingCoefficient,
+ T::Coef: Copy + Debug + PartialEq,
+ {
+ // 5.1.4
+ let input_channels = [
+ Channel::FrontLeft,
+ Channel::FrontRight,
+ Channel::FrontCenter,
+ Channel::LowFrequency,
+ Channel::FrontLeftOfCenter,
+ Channel::FrontRightOfCenter,
+ Channel::TopFrontLeft,
+ Channel::TopFrontRight,
+ Channel::BackLeft,
+ Channel::BackRight,
+ ];
+ // going into a regular 5.1 sound card
+ let output_channels = [
+ Channel::FrontLeft,
+ Channel::FrontRight,
+ Channel::FrontCenter,
+ Channel::LowFrequency,
+ Channel::BackLeft,
+ Channel::BackRight,
+ ];
- let expected = compute_redirect_matrix::<T>(&input_channels, &output_channels);
- assert_eq!(coefficient.matrix, expected);
+ let coefficients = Coefficient::<T>::create(&input_channels, &output_channels);
- println!(
- "{:?} = {:?} * {:?}",
- output_channels, coefficient.matrix, input_channels
- );
+ // Non-unity gain non-silence coefficients must be present when down mixing.
+ let mut found_non_unity_non_silence = false;
+ for row in coefficients.matrix.iter() {
+ for coeff in row.iter() {
+ if T::coefficient_from_f64(1.0) != *coeff || T::coefficient_from_f64(0.0) != *coeff
+ {
+ found_non_unity_non_silence = true;
+ break;
+ }
+ }
+ }
+ assert!(found_non_unity_non_silence);
}
#[test]
@@ -732,7 +837,7 @@ mod test {
vec![4.0_f64, 6.0_f64, 10.0_f64],
];
- let mut max_row_sum: f64 = std::f64::MIN;
+ let mut max_row_sum: f64 = f64::MIN;
for row in &m {
max_row_sum = max_row_sum.max(row.iter().sum());
}
@@ -746,7 +851,7 @@ mod test {
let smaller_max = max_row_sum - 0.5_f64;
assert!(smaller_max > 0.0_f64);
let n = Coefficient::<f32>::normalize(smaller_max, m);
- let mut max_row_sum: f64 = std::f64::MIN;
+ let mut max_row_sum: f64 = f64::MIN;
for row in &n {
max_row_sum = max_row_sum.max(row.iter().sum());
assert!(row.iter().sum::<f64>() <= smaller_max);
diff --git a/third_party/rust/bindgen/clang.rs b/third_party/rust/bindgen/clang.rs
index 4a4ed89d69..19f3e703a7 100644
--- a/third_party/rust/bindgen/clang.rs
+++ b/third_party/rust/bindgen/clang.rs
@@ -1608,7 +1608,7 @@ impl SourceLocation {
let mut line = 0;
let mut col = 0;
let mut off = 0;
- clang_getSpellingLocation(
+ clang_getFileLocation(
self.x, &mut file, &mut line, &mut col, &mut off,
);
(File { x: file }, line as usize, col as usize, off as usize)
diff --git a/third_party/rust/bitflags/.cargo-checksum.json b/third_party/rust/bitflags/.cargo-checksum.json
index 99936c770d..bef288da56 100644
--- a/third_party/rust/bitflags/.cargo-checksum.json
+++ b/third_party/rust/bitflags/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"0905d91abfd8162750daeb51b69e1a4add85cd0e8e2b136a4fd20ea28df4da42","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","CONTRIBUTING.md":"6c9f96eacb20af877ae2d16f024904f3038b93448a8488e9dbcac0df7f6439a5","Cargo.lock":"fb581ed64bd34dbdbcc2386c394394d5f46db3186edc7b129f1669cef66a0b57","Cargo.toml":"418f0ef5e370bf88b0d7bd8c3b2f25b533ae2b671036d30f7c524dc39133045c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"a403792a6099aeda15dc7bf3da529409652039b5dd2227dfc5549bd2f3fad7db","SECURITY.md":"68704c8128fa2e776ed7cbda741fbf61ad52f998a96350ee7ee4dbf64c6573bc","benches/parse.rs":"f1390d62322c6880d65bd931e183d49b313f287879a6bfaa36b1cb1921090b51","examples/custom_bits_type.rs":"e53b32051adc5d97860e0b48c8f3a301a041d73b4939c0d7caa5f0cfcc0b9739","examples/custom_derive.rs":"29dd7b845345a103ca31e91b579aeb01fb74935b8223c29184eb42223edadb65","examples/fmt.rs":"87ba37a1fb8528570c74ea26d8e8948e1179c3d867b928bea1080880258e0a99","examples/macro_free.rs":"69e7f284b53b5214d51228a686e87f127b52a3b74711e45537ebfa5583a180e5","examples/serde.rs":"08b21b35d5c10fdca132fe0f36c8067bb44f559e96617a9257ab6316a20cbc75","spec.md":"fcdd939df30c59b0643be09027df664b71cbea9b9989185441482c5576160fed","src/example_generated.rs":"d018caf059f6ffc4c2403b771a6d76679fa5af03c329a91bd9252957df695e7f","src/external.rs":"11599248db17d395c6b45bf2400266f221d3eb1523908e5f17715964bf8d99ed","src/external/arbitrary.rs":"fa8c9187028b9bc54856977b0914676f62101010e7a9450abd577fd78c89552f","src/external/bytemuck.rs":"3afcef382122867040fddd5e4153d633d1ed5596fe5d7dfac66a8e61c2513df5","src/external/serde.rs":"4a09db12534a20fe554a08dc5f1c8124b379292d41fa75628abcd2ca21587573","src/internal.rs":"fd939154cbebf43bfc329a4a3cd08618ca30a6a5f6e6abea07d23f75bf5b3b2d","src/iter.rs":"dbaa6437c1c044f689185ce3fafe43df8796bed19bbdd2c20334a52de5eeee73","src/lib.rs":"e45c07f43b0e142c41e99de8d20ceb909148762c876d765c11ac8b8ceaca0af5","src/parser.rs":"52f6352620ce3d5973bc38b42d56a760307294162c9d5668eb774eb92a6ef941","src/public.rs":"72b41639711bab95e8e75f37401a487088e7be1a427715cea40563fb3f64ed60","src/tests.rs":"b120c27ff0c67a819527de9d8171f1f4c5d37ba4009c54abeb869c70e6035f14","src/traits.rs":"0a8764c3e2378043e2724cf1bfc514d4ff1985026db33509f6451a7897e2675d"},"package":"327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"cb81297fc686539a786805dfef959e6f7c9b5fd55e451150cea68bcacc73ee8c","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","CONTRIBUTING.md":"6c9f96eacb20af877ae2d16f024904f3038b93448a8488e9dbcac0df7f6439a5","Cargo.lock":"04c2a120060e71f281a3a3f26f9be8dbc5a80102204f1f982ae0e2089557e646","Cargo.toml":"ed18e06a8a26ae38abea369bb062b6e6c1b714913ee9e64c060151f5ec966f5b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"e37efef64c50b073d5afcb6d2d43649cec6bf26d4022f32b5d77665bcb4c9049","SECURITY.md":"68704c8128fa2e776ed7cbda741fbf61ad52f998a96350ee7ee4dbf64c6573bc","benches/parse.rs":"f1390d62322c6880d65bd931e183d49b313f287879a6bfaa36b1cb1921090b51","examples/custom_bits_type.rs":"e53b32051adc5d97860e0b48c8f3a301a041d73b4939c0d7caa5f0cfcc0b9739","examples/custom_derive.rs":"29dd7b845345a103ca31e91b579aeb01fb74935b8223c29184eb42223edadb65","examples/fmt.rs":"87ba37a1fb8528570c74ea26d8e8948e1179c3d867b928bea1080880258e0a99","examples/macro_free.rs":"69e7f284b53b5214d51228a686e87f127b52a3b74711e45537ebfa5583a180e5","examples/serde.rs":"08b21b35d5c10fdca132fe0f36c8067bb44f559e96617a9257ab6316a20cbc75","spec.md":"fcdd939df30c59b0643be09027df664b71cbea9b9989185441482c5576160fed","src/example_generated.rs":"d018caf059f6ffc4c2403b771a6d76679fa5af03c329a91bd9252957df695e7f","src/external.rs":"734d3f470e6a669297d2df421ce3976fe613d8aa9c071d5ce6fe3ca890e5b815","src/external/arbitrary.rs":"fa8c9187028b9bc54856977b0914676f62101010e7a9450abd577fd78c89552f","src/external/bytemuck.rs":"3afcef382122867040fddd5e4153d633d1ed5596fe5d7dfac66a8e61c2513df5","src/external/serde.rs":"4a09db12534a20fe554a08dc5f1c8124b379292d41fa75628abcd2ca21587573","src/internal.rs":"645b13af0c7302258df61239073a4b8203d09f27b6c17f8a6f1f8c3e427f5334","src/iter.rs":"dbaa6437c1c044f689185ce3fafe43df8796bed19bbdd2c20334a52de5eeee73","src/lib.rs":"c7ade9eb151425815a8fc5afc558951a256d14143be36c4442bcae477571783b","src/parser.rs":"4e788b29f5d0542c409a8b43c703bcb4a6c2a57c181cadd17f565f0abb39681e","src/public.rs":"d151f7db62fefdb6cd2cad1038a785f02d1ce32eaab4c4cc84376283699182cc","src/tests.rs":"b120c27ff0c67a819527de9d8171f1f4c5d37ba4009c54abeb869c70e6035f14","src/tests/all.rs":"e99a865cd4271a524c2fe95503e96d851b35990570aed6fb2e9dac7a14da31b6","src/tests/bits.rs":"3840c34b2ea5d1802404b9ce5bcc1d3fa6ccd8dfba2e29e6d07c605f817d90df","src/tests/complement.rs":"d0e6d4c3daf49e0a7438c9f1c1ac91fad1b37f258c03593f6cd6a695ee626f5e","src/tests/contains.rs":"58bb3cb8c86550e775d11134da1d4aca85c83f943ea454e3a5f222772c674a24","src/tests/difference.rs":"d0d2b96bb52658b8ac019210da74ca75a53e76622f668855142ea6e97c28cb0e","src/tests/empty.rs":"817d6e93ced7cb7576ff0e334aa1a44703f3f96871ff2c6bdcb8f207e6551f67","src/tests/eq.rs":"b816767680a029e9c163e37af074dd4e604c4a3e4936f829f0ca3774fd5f0e37","src/tests/extend.rs":"5fabb9fd0254c64da019149c24063fceff72da3eb4ad73b57c1cc4c04b008364","src/tests/flags.rs":"2f48d3a25db1cf66fe98c9959abc70875deb9f7b38b2c278dc70c46e0d4ec277","src/tests/fmt.rs":"a2d4148491f3202f030f63633eee941b741e3be29a68cf376f008dbe5cb11e5c","src/tests/from_bits.rs":"d94c65b88bf89961d0cfc1b3152a7f1acc285bae160a1628438effda11b8e2c1","src/tests/from_bits_retain.rs":"980591dfaf91e940f42d9a1ce890f237514dd59d458fc264abcf9ceabbc40677","src/tests/from_bits_truncate.rs":"d3406b5e107ebb6449b98a59eee6cc5d84f947d4aaee1ee7e80dc7202de179f0","src/tests/from_name.rs":"f4a055d1f3c86decef70ef8f3020cef5c4e229718c20b3d59d5a3abc3a8b1298","src/tests/insert.rs":"3fab5da800a6fc0654dfb5f859f95da65a507eb9fda8695083c2712266dff0b9","src/tests/intersection.rs":"baf1454c9e4eba552264870a556ee0032d9f2bb8cac361833d571235e0b52221","src/tests/intersects.rs":"c55e36179fd8bc636f04ea9bbce346dcaafe57915d13f1df28c5b83117dbd08e","src/tests/is_all.rs":"b2f11faa7c954bd85c8fb39999e0c37d983cf7895152bc13c7ddde106aa33b6d","src/tests/is_empty.rs":"11f21323cdca7ff92dd89e09de667dba69e8dce88e2d3e27ea68ace91d15d070","src/tests/iter.rs":"4ba121932b527e787b82745405c7c65c1084c242e2dda3290d475ec160d265e4","src/tests/parser.rs":"fa2fb8dedcf16601af609a5e21d9c5840c7f96a1e3a587f7f2ea3dc8387f7628","src/tests/remove.rs":"6e75f8508d2dc1a2cba89ef691f4387a665a4fd13853bb1dd0fd80c783b89947","src/tests/symmetric_difference.rs":"0a89f084f9de1dd5b1932fe72c3b10a3c93cbaa16832b3a31b6a85e3bbd3ba6e","src/tests/union.rs":"88f398ee4600bb1e59bf6d02d1f6ff33f5f853eab5a6c700bd8a683c6ee4651a","src/traits.rs":"b79d008daec546136fae4497966fc85a33663d86ea2d9213fd23b412d4d77b66"},"package":"cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"} \ No newline at end of file
diff --git a/third_party/rust/bitflags/CHANGELOG.md b/third_party/rust/bitflags/CHANGELOG.md
index 5081ed5767..5d410fc65a 100644
--- a/third_party/rust/bitflags/CHANGELOG.md
+++ b/third_party/rust/bitflags/CHANGELOG.md
@@ -1,3 +1,29 @@
+# 2.5.0
+
+## What's Changed
+* Derive `Debug` for `Flag<B>` by @tgross35 in https://github.com/bitflags/bitflags/pull/398
+* Support truncating or strict-named variants of parsing and formatting by @KodrAus in https://github.com/bitflags/bitflags/pull/400
+
+## New Contributors
+* @tgross35 made their first contribution in https://github.com/bitflags/bitflags/pull/398
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.4.2...2.5.0
+
+# 2.4.2
+
+## What's Changed
+* Cargo.toml: Anchor excludes to root of the package by @jamessan in https://github.com/bitflags/bitflags/pull/387
+* Update error messages by @KodrAus in https://github.com/bitflags/bitflags/pull/390
+* Add support for impl mode structs to be repr(packed) by @GnomedDev in https://github.com/bitflags/bitflags/pull/388
+* Remove old `unused_tuple_struct_fields` lint by @dtolnay in https://github.com/bitflags/bitflags/pull/393
+* Delete use of `local_inner_macros` by @dtolnay in https://github.com/bitflags/bitflags/pull/392
+
+## New Contributors
+* @jamessan made their first contribution in https://github.com/bitflags/bitflags/pull/387
+* @GnomedDev made their first contribution in https://github.com/bitflags/bitflags/pull/388
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.4.1...2.4.2
+
# 2.4.1
## What's Changed
diff --git a/third_party/rust/bitflags/Cargo.lock b/third_party/rust/bitflags/Cargo.lock
index 53d2d7a686..2c16b119fa 100644
--- a/third_party/rust/bitflags/Cargo.lock
+++ b/third_party/rust/bitflags/Cargo.lock
@@ -4,25 +4,16 @@ version = 3
[[package]]
name = "arbitrary"
-version = "1.3.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2e1373abdaa212b704512ec2bd8b26bd0b7d5c3f70117411a5d9a451383c859"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
[[package]]
-name = "basic-toml"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6"
-dependencies = [
- "serde",
-]
-
-[[package]]
name = "bitflags"
-version = "2.4.1"
+version = "2.5.0"
dependencies = [
"arbitrary",
"bytemuck",
@@ -39,18 +30,18 @@ dependencies = [
[[package]]
name = "bytemuck"
-version = "1.14.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
+checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
dependencies = [
"bytemuck_derive",
]
[[package]]
name = "bytemuck_derive"
-version = "1.5.0"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
+checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60"
dependencies = [
"proc-macro2",
"quote",
@@ -65,15 +56,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "compiler_builtins"
-version = "0.1.101"
+version = "0.1.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01a6d58e9c3408138099a396a98fd0d0e6cfb25d723594d2ae48b5004513fd5b"
+checksum = "d68bc55329711cd719c2687bb147bc06211b0521f97ef398280108ccb23227e9"
[[package]]
name = "derive_arbitrary"
-version = "1.3.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
+checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
@@ -81,37 +72,65 @@ dependencies = [
]
[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
+name = "hashbrown"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+
+[[package]]
+name = "indexmap"
+version = "2.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
name = "itoa"
-version = "1.0.9"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+
+[[package]]
+name = "memchr"
+version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "proc-macro2"
-version = "1.0.69"
+version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
+checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.33"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -130,24 +149,24 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
-version = "1.0.15"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "serde"
-version = "1.0.189"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.189"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
@@ -156,9 +175,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.107"
+version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
+checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
dependencies = [
"itoa",
"ryu",
@@ -166,6 +185,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "serde_test"
version = "1.0.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -176,9 +204,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.38"
+version = "2.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
+checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
dependencies = [
"proc-macro2",
"quote",
@@ -187,26 +215,60 @@ dependencies = [
[[package]]
name = "termcolor"
-version = "1.3.0"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
+name = "toml"
+version = "0.8.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c12219811e0c1ba077867254e5ad62ee2c9c190b0d957110750ac0cda1ae96cd"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
name = "trybuild"
-version = "1.0.85"
+version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "196a58260a906cedb9bf6d8034b6379d0c11f552416960452f267402ceeddff1"
+checksum = "2aa6f84ec205ebf87fb7a0abdbcd1467fa5af0e86878eb6d888b78ecbb10b6d5"
dependencies = [
- "basic-toml",
"glob",
"once_cell",
"serde",
"serde_derive",
"serde_json",
"termcolor",
+ "toml",
]
[[package]]
@@ -247,10 +309,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
+name = "winnow"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "zerocopy"
-version = "0.6.4"
+version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20707b61725734c595e840fb3704378a0cd2b9c74cc9e6e20724838fc6a1e2f9"
+checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6"
dependencies = [
"byteorder",
"zerocopy-derive",
@@ -258,9 +329,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
-version = "0.6.4"
+version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56097d5b91d711293a42be9289403896b68654625021732067eac7a4ca388a1f"
+checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91"
dependencies = [
"proc-macro2",
"quote",
diff --git a/third_party/rust/bitflags/Cargo.toml b/third_party/rust/bitflags/Cargo.toml
index 5fd2c7dc17..b274599a46 100644
--- a/third_party/rust/bitflags/Cargo.toml
+++ b/third_party/rust/bitflags/Cargo.toml
@@ -13,11 +13,11 @@
edition = "2021"
rust-version = "1.56.0"
name = "bitflags"
-version = "2.4.1"
+version = "2.5.0"
authors = ["The Rust Project Developers"]
exclude = [
- "tests",
- ".github",
+ "/tests",
+ "/.github",
]
description = """
A macro to generate structures which behave like bitflags.
diff --git a/third_party/rust/bitflags/README.md b/third_party/rust/bitflags/README.md
index ecad515e17..652a880f6b 100644
--- a/third_party/rust/bitflags/README.md
+++ b/third_party/rust/bitflags/README.md
@@ -28,7 +28,7 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
-bitflags = "2.4.1"
+bitflags = "2.5.0"
```
and this to your source code:
diff --git a/third_party/rust/bitflags/src/external.rs b/third_party/rust/bitflags/src/external.rs
index efeaa82796..716af83c0f 100644
--- a/third_party/rust/bitflags/src/external.rs
+++ b/third_party/rust/bitflags/src/external.rs
@@ -14,7 +14,7 @@ Next, re-export the library from the `__private` module here.
Next, define a macro like so:
```rust
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "serde")]
macro_rules! __impl_external_bitflags_my_library {
@@ -30,7 +30,7 @@ macro_rules! __impl_external_bitflags_my_library {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "my_library"))]
macro_rules! __impl_external_bitflags_my_library {
@@ -77,7 +77,7 @@ pub(crate) mod __private {
}
/// Implements traits from external libraries for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_external_bitflags {
(
@@ -92,7 +92,7 @@ macro_rules! __impl_external_bitflags {
// Use `serde` as an example: generate code when the feature is available,
// and a no-op when it isn't
- __impl_external_bitflags_serde! {
+ $crate::__impl_external_bitflags_serde! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -101,7 +101,7 @@ macro_rules! __impl_external_bitflags {
}
}
- __impl_external_bitflags_arbitrary! {
+ $crate::__impl_external_bitflags_arbitrary! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -110,7 +110,7 @@ macro_rules! __impl_external_bitflags {
}
}
- __impl_external_bitflags_bytemuck! {
+ $crate::__impl_external_bitflags_bytemuck! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -125,7 +125,7 @@ macro_rules! __impl_external_bitflags {
pub mod serde;
/// Implement `Serialize` and `Deserialize` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "serde")]
macro_rules! __impl_external_bitflags_serde {
@@ -161,7 +161,7 @@ macro_rules! __impl_external_bitflags_serde {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "serde"))]
macro_rules! __impl_external_bitflags_serde {
@@ -182,7 +182,7 @@ pub mod arbitrary;
mod bytemuck;
/// Implement `Arbitrary` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "arbitrary")]
macro_rules! __impl_external_bitflags_arbitrary {
@@ -204,7 +204,7 @@ macro_rules! __impl_external_bitflags_arbitrary {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "arbitrary"))]
macro_rules! __impl_external_bitflags_arbitrary {
@@ -219,7 +219,7 @@ macro_rules! __impl_external_bitflags_arbitrary {
}
/// Implement `Pod` and `Zeroable` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "bytemuck")]
macro_rules! __impl_external_bitflags_bytemuck {
@@ -247,7 +247,7 @@ macro_rules! __impl_external_bitflags_bytemuck {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "bytemuck"))]
macro_rules! __impl_external_bitflags_bytemuck {
diff --git a/third_party/rust/bitflags/src/internal.rs b/third_party/rust/bitflags/src/internal.rs
index aca1ac4db1..87d01cc0cb 100644
--- a/third_party/rust/bitflags/src/internal.rs
+++ b/third_party/rust/bitflags/src/internal.rs
@@ -6,7 +6,7 @@
/// Declare the `bitflags`-facing bitflags struct.
///
/// This type is part of the `bitflags` crate's public API, but not part of the user's.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __declare_internal_bitflags {
(
@@ -25,7 +25,7 @@ macro_rules! __declare_internal_bitflags {
///
/// Methods and trait implementations can be freely added here without breaking end-users.
/// If we want to expose new functionality to `#[derive]`, this is the place to do it.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_internal_bitflags {
(
@@ -97,7 +97,7 @@ macro_rules! __impl_internal_bitflags {
// The internal flags type offers a similar API to the public one
- __impl_public_bitflags! {
+ $crate::__impl_public_bitflags! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -106,11 +106,11 @@ macro_rules! __impl_internal_bitflags {
}
}
- __impl_public_bitflags_ops! {
+ $crate::__impl_public_bitflags_ops! {
$InternalBitFlags
}
- __impl_public_bitflags_iter! {
+ $crate::__impl_public_bitflags_iter! {
$InternalBitFlags: $T, $PublicBitFlags
}
diff --git a/third_party/rust/bitflags/src/lib.rs b/third_party/rust/bitflags/src/lib.rs
index c8aff6873f..8f7225915e 100644
--- a/third_party/rust/bitflags/src/lib.rs
+++ b/third_party/rust/bitflags/src/lib.rs
@@ -17,7 +17,7 @@ Add `bitflags` to your `Cargo.toml`:
```toml
[dependencies.bitflags]
-version = "2.4.1"
+version = "2.5.0"
```
## Generating flags types
@@ -252,6 +252,8 @@ mod traits;
#[doc(hidden)]
pub mod __private {
+ #[allow(unused_imports)]
+ // Easier than conditionally checking any optional external dependencies
pub use crate::{external::__private::*, traits::__private::*};
pub use core;
@@ -441,7 +443,7 @@ bitflags! {
}
```
*/
-#[macro_export(local_inner_macros)]
+#[macro_export]
macro_rules! bitflags {
(
$(#[$outer:meta])*
@@ -456,13 +458,13 @@ macro_rules! bitflags {
) => {
// Declared in the scope of the `bitflags!` call
// This type appears in the end-user's API
- __declare_public_bitflags! {
+ $crate::__declare_public_bitflags! {
$(#[$outer])*
$vis struct $BitFlags
}
// Workaround for: https://github.com/bitflags/bitflags/issues/320
- __impl_public_bitflags_consts! {
+ $crate::__impl_public_bitflags_consts! {
$BitFlags: $T {
$(
$(#[$inner $($args)*])*
@@ -487,11 +489,11 @@ macro_rules! bitflags {
const _: () = {
// Declared in a "hidden" scope that can't be reached directly
// These types don't appear in the end-user's API
- __declare_internal_bitflags! {
+ $crate::__declare_internal_bitflags! {
$vis struct InternalBitFlags: $T
}
- __impl_internal_bitflags! {
+ $crate::__impl_internal_bitflags! {
InternalBitFlags: $T, $BitFlags {
$(
$(#[$inner $($args)*])*
@@ -501,7 +503,7 @@ macro_rules! bitflags {
}
// This is where new library trait implementations can be added
- __impl_external_bitflags! {
+ $crate::__impl_external_bitflags! {
InternalBitFlags: $T, $BitFlags {
$(
$(#[$inner $($args)*])*
@@ -510,20 +512,20 @@ macro_rules! bitflags {
}
}
- __impl_public_bitflags_forward! {
+ $crate::__impl_public_bitflags_forward! {
$BitFlags: $T, InternalBitFlags
}
- __impl_public_bitflags_ops! {
+ $crate::__impl_public_bitflags_ops! {
$BitFlags
}
- __impl_public_bitflags_iter! {
+ $crate::__impl_public_bitflags_iter! {
$BitFlags: $T, $BitFlags
}
};
- bitflags! {
+ $crate::bitflags! {
$($t)*
}
};
@@ -537,7 +539,7 @@ macro_rules! bitflags {
$($t:tt)*
) => {
- __impl_public_bitflags_consts! {
+ $crate::__impl_public_bitflags_consts! {
$BitFlags: $T {
$(
$(#[$inner $($args)*])*
@@ -558,7 +560,7 @@ macro_rules! bitflags {
clippy::iter_without_into_iter,
)]
const _: () = {
- __impl_public_bitflags! {
+ $crate::__impl_public_bitflags! {
$BitFlags: $T, $BitFlags {
$(
$(#[$inner $($args)*])*
@@ -567,16 +569,16 @@ macro_rules! bitflags {
}
}
- __impl_public_bitflags_ops! {
+ $crate::__impl_public_bitflags_ops! {
$BitFlags
}
- __impl_public_bitflags_iter! {
+ $crate::__impl_public_bitflags_iter! {
$BitFlags: $T, $BitFlags
}
};
- bitflags! {
+ $crate::bitflags! {
$($t)*
}
};
@@ -587,7 +589,7 @@ macro_rules! bitflags {
///
/// We need to be careful about adding new methods and trait implementations here because they
/// could conflict with items added by the end-user.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_bitflags {
(
@@ -796,7 +798,7 @@ macro_rules! __impl_bitflags {
///
/// If you find yourself with an attribute that should be considered expression-safe
/// and isn't, it can be added here.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __bitflags_expr_safe_attrs {
// Entrypoint: Move all flags and all attributes into `unprocessed` lists
@@ -805,7 +807,7 @@ macro_rules! __bitflags_expr_safe_attrs {
$(#[$inner:ident $($args:tt)*])*
{ $e:expr }
) => {
- __bitflags_expr_safe_attrs! {
+ $crate::__bitflags_expr_safe_attrs! {
expr: { $e },
attrs: {
// All attributes start here
@@ -830,7 +832,7 @@ macro_rules! __bitflags_expr_safe_attrs {
processed: [$($expr:tt)*],
},
) => {
- __bitflags_expr_safe_attrs! {
+ $crate::__bitflags_expr_safe_attrs! {
expr: { $e },
attrs: {
unprocessed: [
@@ -857,7 +859,7 @@ macro_rules! __bitflags_expr_safe_attrs {
processed: [$($expr:tt)*],
},
) => {
- __bitflags_expr_safe_attrs! {
+ $crate::__bitflags_expr_safe_attrs! {
expr: { $e },
attrs: {
unprocessed: [
@@ -884,7 +886,7 @@ macro_rules! __bitflags_expr_safe_attrs {
}
/// Implement a flag, which may be a wildcard `_`.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __bitflags_flag {
(
diff --git a/third_party/rust/bitflags/src/parser.rs b/third_party/rust/bitflags/src/parser.rs
index 130dc2e1f8..34b432da39 100644
--- a/third_party/rust/bitflags/src/parser.rs
+++ b/third_party/rust/bitflags/src/parser.rs
@@ -77,8 +77,10 @@ where
fmt::Result::Ok(())
}
+#[cfg(feature = "serde")]
pub(crate) struct AsDisplay<'a, B>(pub(crate) &'a B);
+#[cfg(feature = "serde")]
impl<'a, B: Flags> fmt::Display for AsDisplay<'a, B>
where
B::Bits: WriteHex,
@@ -135,6 +137,89 @@ where
}
/**
+Write a flags value as text, ignoring any unknown bits.
+*/
+pub fn to_writer_truncate<B: Flags>(flags: &B, writer: impl Write) -> Result<(), fmt::Error>
+where
+ B::Bits: WriteHex,
+{
+ to_writer(&B::from_bits_truncate(flags.bits()), writer)
+}
+
+/**
+Parse a flags value from text.
+
+This function will fail on any names that don't correspond to defined flags.
+Unknown bits will be ignored.
+*/
+pub fn from_str_truncate<B: Flags>(input: &str) -> Result<B, ParseError>
+where
+ B::Bits: ParseHex,
+{
+ Ok(B::from_bits_truncate(from_str::<B>(input)?.bits()))
+}
+
+/**
+Write only the contained, defined, named flags in a flags value as text.
+*/
+pub fn to_writer_strict<B: Flags>(flags: &B, mut writer: impl Write) -> Result<(), fmt::Error> {
+ // This is a simplified version of `to_writer` that ignores
+ // any bits not corresponding to a named flag
+
+ let mut first = true;
+ let mut iter = flags.iter_names();
+ for (name, _) in &mut iter {
+ if !first {
+ writer.write_str(" | ")?;
+ }
+
+ first = false;
+ writer.write_str(name)?;
+ }
+
+ fmt::Result::Ok(())
+}
+
+/**
+Parse a flags value from text.
+
+This function will fail on any names that don't correspond to defined flags.
+This function will fail to parse hex values.
+*/
+pub fn from_str_strict<B: Flags>(input: &str) -> Result<B, ParseError> {
+ // This is a simplified version of `from_str` that ignores
+ // any bits not corresponding to a named flag
+
+ let mut parsed_flags = B::empty();
+
+ // If the input is empty then return an empty set of flags
+ if input.trim().is_empty() {
+ return Ok(parsed_flags);
+ }
+
+ for flag in input.split('|') {
+ let flag = flag.trim();
+
+ // If the flag is empty then we've got missing input
+ if flag.is_empty() {
+ return Err(ParseError::empty_flag());
+ }
+
+ // If the flag starts with `0x` then it's a hex number
+ // These aren't supported in the strict parser
+ if flag.starts_with("0x") {
+ return Err(ParseError::invalid_hex_flag("unsupported hex flag value"));
+ }
+
+ let parsed_flag = B::from_name(flag).ok_or_else(|| ParseError::invalid_named_flag(flag))?;
+
+ parsed_flags.insert(parsed_flag);
+ }
+
+ Ok(parsed_flags)
+}
+
+/**
Encode a value as a hex string.
Implementors of this trait should not write the `0x` prefix.
diff --git a/third_party/rust/bitflags/src/public.rs b/third_party/rust/bitflags/src/public.rs
index 967e0dacbf..dc2d726782 100644
--- a/third_party/rust/bitflags/src/public.rs
+++ b/third_party/rust/bitflags/src/public.rs
@@ -6,7 +6,7 @@
/// Declare the user-facing bitflags struct.
///
/// This type is guaranteed to be a newtype with a `bitflags`-facing type as its single field.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __declare_public_bitflags {
(
@@ -22,13 +22,13 @@ macro_rules! __declare_public_bitflags {
///
/// We need to be careful about adding new methods and trait implementations here because they
/// could conflict with items added by the end-user.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_forward {
(
$PublicBitFlags:ident: $T:ty, $InternalBitFlags:ident
) => {
- __impl_bitflags! {
+ $crate::__impl_bitflags! {
$PublicBitFlags: $T {
fn empty() {
Self($InternalBitFlags::empty())
@@ -124,7 +124,7 @@ macro_rules! __impl_public_bitflags_forward {
///
/// We need to be careful about adding new methods and trait implementations here because they
/// could conflict with items added by the end-user.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags {
(
@@ -135,7 +135,7 @@ macro_rules! __impl_public_bitflags {
)*
}
) => {
- __impl_bitflags! {
+ $crate::__impl_bitflags! {
$BitFlags: $T {
fn empty() {
Self(<$T as $crate::Bits>::EMPTY)
@@ -146,7 +146,7 @@ macro_rules! __impl_public_bitflags {
let mut i = 0;
$(
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{{
let flag = <$PublicBitFlags as $crate::Flags>::FLAGS[i].value().bits();
@@ -185,10 +185,10 @@ macro_rules! __impl_public_bitflags {
fn from_name(name) {
$(
- __bitflags_flag!({
+ $crate::__bitflags_flag!({
name: $Flag,
named: {
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{
if name == $crate::__private::core::stringify!($Flag) {
@@ -268,7 +268,7 @@ macro_rules! __impl_public_bitflags {
}
/// Implement iterators on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_iter {
($BitFlags:ident: $T:ty, $PublicBitFlags:ident) => {
@@ -312,7 +312,7 @@ macro_rules! __impl_public_bitflags_iter {
}
/// Implement traits on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_ops {
($PublicBitFlags:ident) => {
@@ -321,7 +321,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::Binary::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::Binary::fmt(&inner, f)
}
}
@@ -330,7 +331,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::Octal::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::Octal::fmt(&inner, f)
}
}
@@ -339,7 +341,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::LowerHex::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
@@ -348,7 +351,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::UpperHex::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
@@ -468,7 +472,7 @@ macro_rules! __impl_public_bitflags_ops {
}
/// Implement constants on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_consts {
(
@@ -481,7 +485,7 @@ macro_rules! __impl_public_bitflags_consts {
) => {
impl $PublicBitFlags {
$(
- __bitflags_flag!({
+ $crate::__bitflags_flag!({
name: $Flag,
named: {
$(#[$inner $($args)*])*
@@ -499,10 +503,10 @@ macro_rules! __impl_public_bitflags_consts {
impl $crate::Flags for $PublicBitFlags {
const FLAGS: &'static [$crate::Flag<$PublicBitFlags>] = &[
$(
- __bitflags_flag!({
+ $crate::__bitflags_flag!({
name: $Flag,
named: {
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{
#[allow(
@@ -514,7 +518,7 @@ macro_rules! __impl_public_bitflags_consts {
)
},
unnamed: {
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{
#[allow(
diff --git a/third_party/rust/bitflags/src/tests/all.rs b/third_party/rust/bitflags/src/tests/all.rs
new file mode 100644
index 0000000000..cceb93a469
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/all.rs
@@ -0,0 +1,23 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(1 | 1 << 1 | 1 << 2, TestFlags::all);
+
+ case(0, TestZero::all);
+
+ case(0, TestEmpty::all);
+
+ case(!0, TestExternal::all);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, inherent: impl FnOnce() -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent().bits(), "T::all()");
+ assert_eq!(expected, T::all().bits(), "Flags::all()");
+}
diff --git a/third_party/rust/bitflags/src/tests/bits.rs b/third_party/rust/bitflags/src/tests/bits.rs
new file mode 100644
index 0000000000..678f153e36
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/bits.rs
@@ -0,0 +1,36 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::empty(), TestFlags::bits);
+
+ case(1, TestFlags::A, TestFlags::bits);
+ case(1 | 1 << 1 | 1 << 2, TestFlags::ABC, TestFlags::bits);
+
+ case(!0, TestFlags::from_bits_retain(u8::MAX), TestFlags::bits);
+ case(1 << 3, TestFlags::from_bits_retain(1 << 3), TestFlags::bits);
+
+ case(1 << 3, TestZero::from_bits_retain(1 << 3), TestZero::bits);
+
+ case(1 << 3, TestEmpty::from_bits_retain(1 << 3), TestEmpty::bits);
+
+ case(
+ 1 << 4 | 1 << 6,
+ TestExternal::from_bits_retain(1 << 4 | 1 << 6),
+ TestExternal::bits,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(
+ expected: T::Bits,
+ value: T,
+ inherent: impl FnOnce(&T) -> T::Bits,
+) where
+ T::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent(&value), "{:?}.bits()", value);
+ assert_eq!(expected, Flags::bits(&value), "Flags::bits({:?})", value);
+}
diff --git a/third_party/rust/bitflags/src/tests/complement.rs b/third_party/rust/bitflags/src/tests/complement.rs
new file mode 100644
index 0000000000..ac7a421af0
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/complement.rs
@@ -0,0 +1,53 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::all(), TestFlags::complement);
+ case(0, TestFlags::from_bits_retain(!0), TestFlags::complement);
+
+ case(1 | 1 << 1, TestFlags::C, TestFlags::complement);
+ case(
+ 1 | 1 << 1,
+ TestFlags::C | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::complement,
+ );
+
+ case(
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::empty(),
+ TestFlags::complement,
+ );
+ case(
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::from_bits_retain(1 << 3),
+ TestFlags::complement,
+ );
+
+ case(0, TestZero::empty(), TestZero::complement);
+
+ case(0, TestEmpty::empty(), TestEmpty::complement);
+
+ case(1 << 2, TestOverlapping::AB, TestOverlapping::complement);
+
+ case(!0, TestExternal::empty(), TestExternal::complement);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::Not<Output = T> + Copy>(
+ expected: T::Bits,
+ value: T,
+ inherent: impl FnOnce(T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent(value).bits(), "{:?}.complement()", value);
+ assert_eq!(
+ expected,
+ Flags::complement(value).bits(),
+ "Flags::complement({:?})",
+ value
+ );
+ assert_eq!(expected, (!value).bits(), "!{:?}", value);
+}
diff --git a/third_party/rust/bitflags/src/tests/contains.rs b/third_party/rust/bitflags/src/tests/contains.rs
new file mode 100644
index 0000000000..12428ddcb0
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/contains.rs
@@ -0,0 +1,108 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, true),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::ABC, false),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ (TestFlags::from_bits_retain(1 | (1 << 3)), false),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestFlags::ABC,
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, true),
+ (TestFlags::B, true),
+ (TestFlags::C, true),
+ (TestFlags::ABC, true),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), true),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestZero::ZERO,
+ &[(TestZero::ZERO, true)],
+ TestZero::contains,
+ );
+
+ case(
+ TestOverlapping::AB,
+ &[
+ (TestOverlapping::AB, true),
+ (TestOverlapping::BC, false),
+ (TestOverlapping::from_bits_retain(1 << 1), true),
+ ],
+ TestOverlapping::contains,
+ );
+
+ case(
+ TestExternal::all(),
+ &[
+ (TestExternal::A, true),
+ (TestExternal::B, true),
+ (TestExternal::C, true),
+ (TestExternal::from_bits_retain(1 << 5 | 1 << 7), true),
+ ],
+ TestExternal::contains,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, bool)],
+ mut inherent: impl FnMut(&T, T) -> bool,
+) {
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(&value, *input),
+ "{:?}.contains({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::contains(&value, *input),
+ "Flags::contains({:?}, {:?})",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/difference.rs b/third_party/rust/bitflags/src/tests/difference.rs
new file mode 100644
index 0000000000..6ce9c0bf19
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/difference.rs
@@ -0,0 +1,92 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::A | TestFlags::B,
+ &[
+ (TestFlags::A, 1 << 1),
+ (TestFlags::B, 1),
+ (TestFlags::from_bits_retain(1 << 3), 1 | 1 << 1),
+ ],
+ TestFlags::difference,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 | 1 << 3),
+ &[
+ (TestFlags::A, 1 << 3),
+ (TestFlags::from_bits_retain(1 << 3), 1),
+ ],
+ TestFlags::difference,
+ );
+
+ case(
+ TestExternal::from_bits_retain(!0),
+ &[(TestExternal::A, 0b1111_1110)],
+ TestExternal::difference,
+ );
+
+ assert_eq!(
+ 0b1111_1110,
+ (TestExternal::from_bits_retain(!0) & !TestExternal::A).bits()
+ );
+
+ assert_eq!(
+ 0b1111_1110,
+ (TestFlags::from_bits_retain(!0).difference(TestFlags::A)).bits()
+ );
+
+ // The `!` operator unsets bits that don't correspond to known flags
+ assert_eq!(
+ 1 << 1 | 1 << 2,
+ (TestFlags::from_bits_retain(!0) & !TestFlags::A).bits()
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::Sub<Output = T> + std::ops::SubAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent: impl FnMut(T, T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(value, *input).bits(),
+ "{:?}.difference({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::difference(value, *input).bits(),
+ "Flags::difference({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value - *input).bits(),
+ "{:?} - {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value -= *input;
+ value
+ }
+ .bits(),
+ "{:?} -= {:?}",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/empty.rs b/third_party/rust/bitflags/src/tests/empty.rs
new file mode 100644
index 0000000000..57fb1c7cf1
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/empty.rs
@@ -0,0 +1,23 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::empty);
+
+ case(0, TestZero::empty);
+
+ case(0, TestEmpty::empty);
+
+ case(0, TestExternal::empty);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, inherent: impl FnOnce() -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent().bits(), "T::empty()");
+ assert_eq!(expected, T::empty().bits(), "Flags::empty()");
+}
diff --git a/third_party/rust/bitflags/src/tests/eq.rs b/third_party/rust/bitflags/src/tests/eq.rs
new file mode 100644
index 0000000000..9779af7629
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/eq.rs
@@ -0,0 +1,10 @@
+use super::*;
+
+#[test]
+fn cases() {
+ assert_eq!(TestFlags::empty(), TestFlags::empty());
+ assert_eq!(TestFlags::all(), TestFlags::all());
+
+ assert!(TestFlags::from_bits_retain(1) < TestFlags::from_bits_retain(2));
+ assert!(TestFlags::from_bits_retain(2) > TestFlags::from_bits_retain(1));
+}
diff --git a/third_party/rust/bitflags/src/tests/extend.rs b/third_party/rust/bitflags/src/tests/extend.rs
new file mode 100644
index 0000000000..869dc17fc8
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/extend.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+#[test]
+fn cases() {
+ let mut flags = TestFlags::empty();
+
+ flags.extend(TestFlags::A);
+
+ assert_eq!(TestFlags::A, flags);
+
+ flags.extend(TestFlags::A | TestFlags::B | TestFlags::C);
+
+ assert_eq!(TestFlags::ABC, flags);
+
+ flags.extend(TestFlags::from_bits_retain(1 << 5));
+
+ assert_eq!(TestFlags::ABC | TestFlags::from_bits_retain(1 << 5), flags);
+}
+
+mod external {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ let mut flags = TestExternal::empty();
+
+ flags.extend(TestExternal::A);
+
+ assert_eq!(TestExternal::A, flags);
+
+ flags.extend(TestExternal::A | TestExternal::B | TestExternal::C);
+
+ assert_eq!(TestExternal::ABC, flags);
+
+ flags.extend(TestExternal::from_bits_retain(1 << 5));
+
+ assert_eq!(
+ TestExternal::ABC | TestExternal::from_bits_retain(1 << 5),
+ flags
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/flags.rs b/third_party/rust/bitflags/src/tests/flags.rs
new file mode 100644
index 0000000000..7a625b312c
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/flags.rs
@@ -0,0 +1,46 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ let flags = TestFlags::FLAGS
+ .iter()
+ .map(|flag| (flag.name(), flag.value().bits()))
+ .collect::<Vec<_>>();
+
+ assert_eq!(
+ vec![
+ ("A", 1u8),
+ ("B", 1 << 1),
+ ("C", 1 << 2),
+ ("ABC", 1 | 1 << 1 | 1 << 2),
+ ],
+ flags,
+ );
+
+ assert_eq!(0, TestEmpty::FLAGS.iter().count());
+}
+
+mod external {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ let flags = TestExternal::FLAGS
+ .iter()
+ .map(|flag| (flag.name(), flag.value().bits()))
+ .collect::<Vec<_>>();
+
+ assert_eq!(
+ vec![
+ ("A", 1u8),
+ ("B", 1 << 1),
+ ("C", 1 << 2),
+ ("ABC", 1 | 1 << 1 | 1 << 2),
+ ("", !0),
+ ],
+ flags,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/fmt.rs b/third_party/rust/bitflags/src/tests/fmt.rs
new file mode 100644
index 0000000000..ed4571877d
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/fmt.rs
@@ -0,0 +1,97 @@
+use super::*;
+
+#[test]
+fn cases() {
+ case(TestFlags::empty(), "TestFlags(0x0)", "0", "0", "0", "0");
+ case(TestFlags::A, "TestFlags(A)", "1", "1", "1", "1");
+ case(
+ TestFlags::all(),
+ "TestFlags(A | B | C)",
+ "7",
+ "7",
+ "7",
+ "111",
+ );
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ "TestFlags(0x8)",
+ "8",
+ "8",
+ "10",
+ "1000",
+ );
+ case(
+ TestFlags::A | TestFlags::from_bits_retain(1 << 3),
+ "TestFlags(A | 0x8)",
+ "9",
+ "9",
+ "11",
+ "1001",
+ );
+
+ case(TestZero::ZERO, "TestZero(0x0)", "0", "0", "0", "0");
+ case(
+ TestZero::ZERO | TestZero::from_bits_retain(1),
+ "TestZero(0x1)",
+ "1",
+ "1",
+ "1",
+ "1",
+ );
+
+ case(TestZeroOne::ONE, "TestZeroOne(ONE)", "1", "1", "1", "1");
+
+ case(
+ TestOverlapping::from_bits_retain(1 << 1),
+ "TestOverlapping(0x2)",
+ "2",
+ "2",
+ "2",
+ "10",
+ );
+
+ case(
+ TestExternal::from_bits_retain(1 | 1 << 1 | 1 << 3),
+ "TestExternal(A | B | 0x8)",
+ "B",
+ "b",
+ "13",
+ "1011",
+ );
+
+ case(
+ TestExternal::all(),
+ "TestExternal(A | B | C | 0xf8)",
+ "FF",
+ "ff",
+ "377",
+ "11111111",
+ );
+
+ case(
+ TestExternalFull::all(),
+ "TestExternalFull(0xff)",
+ "FF",
+ "ff",
+ "377",
+ "11111111",
+ );
+}
+
+#[track_caller]
+fn case<
+ T: std::fmt::Debug + std::fmt::UpperHex + std::fmt::LowerHex + std::fmt::Octal + std::fmt::Binary,
+>(
+ value: T,
+ debug: &str,
+ uhex: &str,
+ lhex: &str,
+ oct: &str,
+ bin: &str,
+) {
+ assert_eq!(debug, format!("{:?}", value));
+ assert_eq!(uhex, format!("{:X}", value));
+ assert_eq!(lhex, format!("{:x}", value));
+ assert_eq!(oct, format!("{:o}", value));
+ assert_eq!(bin, format!("{:b}", value));
+}
diff --git a/third_party/rust/bitflags/src/tests/from_bits.rs b/third_party/rust/bitflags/src/tests/from_bits.rs
new file mode 100644
index 0000000000..dada9aff82
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_bits.rs
@@ -0,0 +1,45 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(Some(0), 0, TestFlags::from_bits);
+ case(Some(1), 1, TestFlags::from_bits);
+ case(
+ Some(1 | 1 << 1 | 1 << 2),
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::from_bits,
+ );
+
+ case(None, 1 << 3, TestFlags::from_bits);
+ case(None, 1 | 1 << 3, TestFlags::from_bits);
+
+ case(Some(1 | 1 << 1), 1 | 1 << 1, TestOverlapping::from_bits);
+
+ case(Some(1 << 1), 1 << 1, TestOverlapping::from_bits);
+
+ case(Some(1 << 5), 1 << 5, TestExternal::from_bits);
+}
+
+#[track_caller]
+fn case<T: Flags>(
+ expected: Option<T::Bits>,
+ input: T::Bits,
+ inherent: impl FnOnce(T::Bits) -> Option<T>,
+) where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ expected,
+ inherent(input).map(|f| f.bits()),
+ "T::from_bits({:?})",
+ input
+ );
+ assert_eq!(
+ expected,
+ T::from_bits(input).map(|f| f.bits()),
+ "Flags::from_bits({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/from_bits_retain.rs b/third_party/rust/bitflags/src/tests/from_bits_retain.rs
new file mode 100644
index 0000000000..1ae28a663f
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_bits_retain.rs
@@ -0,0 +1,38 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::from_bits_retain);
+ case(1, TestFlags::from_bits_retain);
+ case(1 | 1 << 1 | 1 << 2, TestFlags::from_bits_retain);
+
+ case(1 << 3, TestFlags::from_bits_retain);
+ case(1 | 1 << 3, TestFlags::from_bits_retain);
+
+ case(1 | 1 << 1, TestOverlapping::from_bits_retain);
+
+ case(1 << 1, TestOverlapping::from_bits_retain);
+
+ case(1 << 5, TestExternal::from_bits_retain);
+}
+
+#[track_caller]
+fn case<T: Flags>(input: T::Bits, inherent: impl FnOnce(T::Bits) -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ input,
+ inherent(input).bits(),
+ "T::from_bits_retain({:?})",
+ input
+ );
+ assert_eq!(
+ input,
+ T::from_bits_retain(input).bits(),
+ "Flags::from_bits_retain({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/from_bits_truncate.rs b/third_party/rust/bitflags/src/tests/from_bits_truncate.rs
new file mode 100644
index 0000000000..e4f3e537c4
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_bits_truncate.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, 0, TestFlags::from_bits_truncate);
+ case(1, 1, TestFlags::from_bits_truncate);
+ case(
+ 1 | 1 << 1 | 1 << 2,
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::from_bits_truncate,
+ );
+
+ case(0, 1 << 3, TestFlags::from_bits_truncate);
+ case(1, 1 | 1 << 3, TestFlags::from_bits_truncate);
+
+ case(1 | 1 << 1, 1 | 1 << 1, TestOverlapping::from_bits_truncate);
+
+ case(1 << 1, 1 << 1, TestOverlapping::from_bits_truncate);
+
+ case(1 << 5, 1 << 5, TestExternal::from_bits_truncate);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, input: T::Bits, inherent: impl FnOnce(T::Bits) -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ expected,
+ inherent(input).bits(),
+ "T::from_bits_truncate({:?})",
+ input
+ );
+ assert_eq!(
+ expected,
+ T::from_bits_truncate(input).bits(),
+ "Flags::from_bits_truncate({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/from_name.rs b/third_party/rust/bitflags/src/tests/from_name.rs
new file mode 100644
index 0000000000..1d9a4e48b6
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_name.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(Some(1), "A", TestFlags::from_name);
+ case(Some(1 << 1), "B", TestFlags::from_name);
+ case(Some(1 | 1 << 1 | 1 << 2), "ABC", TestFlags::from_name);
+
+ case(None, "", TestFlags::from_name);
+ case(None, "a", TestFlags::from_name);
+ case(None, "0x1", TestFlags::from_name);
+ case(None, "A | B", TestFlags::from_name);
+
+ case(Some(0), "ZERO", TestZero::from_name);
+
+ case(Some(2), "二", TestUnicode::from_name);
+
+ case(None, "_", TestExternal::from_name);
+
+ case(None, "", TestExternal::from_name);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: Option<T::Bits>, input: &str, inherent: impl FnOnce(&str) -> Option<T>)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ expected,
+ inherent(input).map(|f| f.bits()),
+ "T::from_name({:?})",
+ input
+ );
+ assert_eq!(
+ expected,
+ T::from_name(input).map(|f| f.bits()),
+ "Flags::from_name({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/insert.rs b/third_party/rust/bitflags/src/tests/insert.rs
new file mode 100644
index 0000000000..b18cd17235
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/insert.rs
@@ -0,0 +1,91 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::A, 1),
+ (TestFlags::A | TestFlags::B, 1 | 1 << 1),
+ (TestFlags::empty(), 0),
+ (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+ ],
+ TestFlags::insert,
+ TestFlags::set,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::A, 1),
+ (TestFlags::empty(), 1),
+ (TestFlags::B, 1 | 1 << 1),
+ ],
+ TestFlags::insert,
+ TestFlags::set,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent_insert: impl FnMut(&mut T, T),
+ mut inherent_set: impl FnMut(&mut T, T, bool),
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_insert(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.insert({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::insert(&mut value, *input);
+ value
+ }
+ .bits(),
+ "Flags::insert({:?}, {:?})",
+ value,
+ input
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_set(&mut value, *input, true);
+ value
+ }
+ .bits(),
+ "{:?}.set({:?}, true)",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::set(&mut value, *input, true);
+ value
+ }
+ .bits(),
+ "Flags::set({:?}, {:?}, true)",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/intersection.rs b/third_party/rust/bitflags/src/tests/intersection.rs
new file mode 100644
index 0000000000..10a8ae9fb6
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/intersection.rs
@@ -0,0 +1,79 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[(TestFlags::empty(), 0), (TestFlags::all(), 0)],
+ TestFlags::intersection,
+ );
+
+ case(
+ TestFlags::all(),
+ &[
+ (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+ (TestFlags::A, 1),
+ (TestFlags::from_bits_retain(1 << 3), 0),
+ ],
+ TestFlags::intersection,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ &[(TestFlags::from_bits_retain(1 << 3), 1 << 3)],
+ TestFlags::intersection,
+ );
+
+ case(
+ TestOverlapping::AB,
+ &[(TestOverlapping::BC, 1 << 1)],
+ TestOverlapping::intersection,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitAnd<Output = T> + std::ops::BitAndAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent: impl FnMut(T, T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(value, *input).bits(),
+ "{:?}.intersection({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::intersection(value, *input).bits(),
+ "Flags::intersection({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value & *input).bits(),
+ "{:?} & {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value &= *input;
+ value
+ }
+ .bits(),
+ "{:?} &= {:?}",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/intersects.rs b/third_party/rust/bitflags/src/tests/intersects.rs
new file mode 100644
index 0000000000..fe907981a2
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/intersects.rs
@@ -0,0 +1,91 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, true),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::ABC, true),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ (TestFlags::from_bits_retain(1 | (1 << 3)), true),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestFlags::ABC,
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, true),
+ (TestFlags::B, true),
+ (TestFlags::C, true),
+ (TestFlags::ABC, true),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), true),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestOverlapping::AB,
+ &[
+ (TestOverlapping::AB, true),
+ (TestOverlapping::BC, true),
+ (TestOverlapping::from_bits_retain(1 << 1), true),
+ ],
+ TestOverlapping::intersects,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, bool)],
+ mut inherent: impl FnMut(&T, T) -> bool,
+) {
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(&value, *input),
+ "{:?}.intersects({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::intersects(&value, *input),
+ "Flags::intersects({:?}, {:?})",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/is_all.rs b/third_party/rust/bitflags/src/tests/is_all.rs
new file mode 100644
index 0000000000..382a458f61
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/is_all.rs
@@ -0,0 +1,32 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(false, TestFlags::empty(), TestFlags::is_all);
+ case(false, TestFlags::A, TestFlags::is_all);
+
+ case(true, TestFlags::ABC, TestFlags::is_all);
+
+ case(
+ true,
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::is_all,
+ );
+
+ case(true, TestZero::empty(), TestZero::is_all);
+
+ case(true, TestEmpty::empty(), TestEmpty::is_all);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(expected: bool, value: T, inherent: impl FnOnce(&T) -> bool) {
+ assert_eq!(expected, inherent(&value), "{:?}.is_all()", value);
+ assert_eq!(
+ expected,
+ Flags::is_all(&value),
+ "Flags::is_all({:?})",
+ value
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/is_empty.rs b/third_party/rust/bitflags/src/tests/is_empty.rs
new file mode 100644
index 0000000000..92165f18e3
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/is_empty.rs
@@ -0,0 +1,31 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(true, TestFlags::empty(), TestFlags::is_empty);
+
+ case(false, TestFlags::A, TestFlags::is_empty);
+ case(false, TestFlags::ABC, TestFlags::is_empty);
+ case(
+ false,
+ TestFlags::from_bits_retain(1 << 3),
+ TestFlags::is_empty,
+ );
+
+ case(true, TestZero::empty(), TestZero::is_empty);
+
+ case(true, TestEmpty::empty(), TestEmpty::is_empty);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(expected: bool, value: T, inherent: impl FnOnce(&T) -> bool) {
+ assert_eq!(expected, inherent(&value), "{:?}.is_empty()", value);
+ assert_eq!(
+ expected,
+ Flags::is_empty(&value),
+ "Flags::is_empty({:?})",
+ value
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/iter.rs b/third_party/rust/bitflags/src/tests/iter.rs
new file mode 100644
index 0000000000..54b1d27d4c
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/iter.rs
@@ -0,0 +1,209 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip() {
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ assert_eq!(f, f.iter().collect::<TestFlags>());
+ assert_eq!(
+ TestFlags::from_bits_truncate(f.bits()),
+ f.iter_names().map(|(_, f)| f).collect::<TestFlags>()
+ );
+
+ let f = TestExternal::from_bits_retain(a | b);
+
+ assert_eq!(f, f.iter().collect::<TestExternal>());
+ }
+ }
+}
+
+mod collect {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!(0, [].into_iter().collect::<TestFlags>().bits());
+
+ assert_eq!(1, [TestFlags::A,].into_iter().collect::<TestFlags>().bits());
+
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ [TestFlags::A, TestFlags::B | TestFlags::C,]
+ .into_iter()
+ .collect::<TestFlags>()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 3,
+ [
+ TestFlags::from_bits_retain(1 << 3),
+ TestFlags::empty(),
+ TestFlags::A,
+ ]
+ .into_iter()
+ .collect::<TestFlags>()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 << 5 | 1 << 7,
+ [
+ TestExternal::empty(),
+ TestExternal::from_bits_retain(1 << 5),
+ TestExternal::from_bits_retain(1 << 7),
+ ]
+ .into_iter()
+ .collect::<TestExternal>()
+ .bits()
+ );
+ }
+}
+
+mod iter {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ case(&[], TestFlags::empty(), TestFlags::iter);
+
+ case(&[1], TestFlags::A, TestFlags::iter);
+ case(&[1, 1 << 1], TestFlags::A | TestFlags::B, TestFlags::iter);
+ case(
+ &[1, 1 << 1, 1 << 3],
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter,
+ );
+
+ case(&[1, 1 << 1, 1 << 2], TestFlags::ABC, TestFlags::iter);
+ case(
+ &[1, 1 << 1, 1 << 2, 1 << 3],
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter,
+ );
+
+ case(
+ &[1 | 1 << 1 | 1 << 2],
+ TestFlagsInvert::ABC,
+ TestFlagsInvert::iter,
+ );
+
+ case(&[], TestZero::ZERO, TestZero::iter);
+
+ case(
+ &[1, 1 << 1, 1 << 2, 0b1111_1000],
+ TestExternal::all(),
+ TestExternal::iter,
+ );
+ }
+
+ #[track_caller]
+ fn case<T: Flags + std::fmt::Debug + IntoIterator<Item = T> + Copy>(
+ expected: &[T::Bits],
+ value: T,
+ inherent: impl FnOnce(&T) -> crate::iter::Iter<T>,
+ ) where
+ T::Bits: std::fmt::Debug + PartialEq,
+ {
+ assert_eq!(
+ expected,
+ inherent(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+ "{:?}.iter()",
+ value
+ );
+ assert_eq!(
+ expected,
+ Flags::iter(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+ "Flags::iter({:?})",
+ value
+ );
+ assert_eq!(
+ expected,
+ value.into_iter().map(|f| f.bits()).collect::<Vec<_>>(),
+ "{:?}.into_iter()",
+ value
+ );
+ }
+}
+
+mod iter_names {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ case(&[], TestFlags::empty(), TestFlags::iter_names);
+
+ case(&[("A", 1)], TestFlags::A, TestFlags::iter_names);
+ case(
+ &[("A", 1), ("B", 1 << 1)],
+ TestFlags::A | TestFlags::B,
+ TestFlags::iter_names,
+ );
+ case(
+ &[("A", 1), ("B", 1 << 1)],
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter_names,
+ );
+
+ case(
+ &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+ TestFlags::ABC,
+ TestFlags::iter_names,
+ );
+ case(
+ &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter_names,
+ );
+
+ case(
+ &[("ABC", 1 | 1 << 1 | 1 << 2)],
+ TestFlagsInvert::ABC,
+ TestFlagsInvert::iter_names,
+ );
+
+ case(&[], TestZero::ZERO, TestZero::iter_names);
+
+ case(
+ &[("A", 1)],
+ TestOverlappingFull::A,
+ TestOverlappingFull::iter_names,
+ );
+ case(
+ &[("A", 1), ("D", 1 << 1)],
+ TestOverlappingFull::A | TestOverlappingFull::D,
+ TestOverlappingFull::iter_names,
+ );
+ }
+
+ #[track_caller]
+ fn case<T: Flags + std::fmt::Debug>(
+ expected: &[(&'static str, T::Bits)],
+ value: T,
+ inherent: impl FnOnce(&T) -> crate::iter::IterNames<T>,
+ ) where
+ T::Bits: std::fmt::Debug + PartialEq,
+ {
+ assert_eq!(
+ expected,
+ inherent(&value)
+ .map(|(n, f)| (n, f.bits()))
+ .collect::<Vec<_>>(),
+ "{:?}.iter_names()",
+ value
+ );
+ assert_eq!(
+ expected,
+ Flags::iter_names(&value)
+ .map(|(n, f)| (n, f.bits()))
+ .collect::<Vec<_>>(),
+ "Flags::iter_names({:?})",
+ value
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/parser.rs b/third_party/rust/bitflags/src/tests/parser.rs
new file mode 100644
index 0000000000..fb27225ece
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/parser.rs
@@ -0,0 +1,332 @@
+use super::*;
+
+use crate::{parser::*, Flags};
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip() {
+ let mut s = String::new();
+
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ s.clear();
+ to_writer(&f, &mut s).unwrap();
+
+ assert_eq!(f, from_str::<TestFlags>(&s).unwrap());
+ }
+ }
+}
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip_truncate() {
+ let mut s = String::new();
+
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ s.clear();
+ to_writer_truncate(&f, &mut s).unwrap();
+
+ assert_eq!(
+ TestFlags::from_bits_truncate(f.bits()),
+ from_str_truncate::<TestFlags>(&s).unwrap()
+ );
+ }
+ }
+}
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip_strict() {
+ let mut s = String::new();
+
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ s.clear();
+ to_writer_strict(&f, &mut s).unwrap();
+
+ let mut strict = TestFlags::empty();
+ for (_, flag) in f.iter_names() {
+ strict |= flag;
+ }
+ let f = strict;
+
+ if let Ok(s) = from_str_strict::<TestFlags>(&s) {
+ assert_eq!(f, s);
+ }
+ }
+ }
+}
+
+mod from_str {
+ use super::*;
+
+ #[test]
+ fn valid() {
+ assert_eq!(0, from_str::<TestFlags>("").unwrap().bits());
+
+ assert_eq!(1, from_str::<TestFlags>("A").unwrap().bits());
+ assert_eq!(1, from_str::<TestFlags>(" A ").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str::<TestFlags>("A | B | C").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str::<TestFlags>("A\n|\tB\r\n| C ").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str::<TestFlags>("A|B|C").unwrap().bits()
+ );
+
+ assert_eq!(1 << 3, from_str::<TestFlags>("0x8").unwrap().bits());
+ assert_eq!(1 | 1 << 3, from_str::<TestFlags>("A | 0x8").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 3,
+ from_str::<TestFlags>("0x1 | 0x8 | B").unwrap().bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str::<TestUnicode>("一 | 二").unwrap().bits()
+ );
+ }
+
+ #[test]
+ fn invalid() {
+ assert!(from_str::<TestFlags>("a")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+ assert!(from_str::<TestFlags>("A & B")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+
+ assert!(from_str::<TestFlags>("0xg")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ assert!(from_str::<TestFlags>("0xffffffffffff")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ }
+}
+
+mod to_writer {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!("", write(TestFlags::empty()));
+ assert_eq!("A", write(TestFlags::A));
+ assert_eq!("A | B | C", write(TestFlags::all()));
+ assert_eq!("0x8", write(TestFlags::from_bits_retain(1 << 3)));
+ assert_eq!(
+ "A | 0x8",
+ write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
+ );
+
+ assert_eq!("", write(TestZero::ZERO));
+
+ assert_eq!("ABC", write(TestFlagsInvert::all()));
+
+ assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
+
+ assert_eq!("A", write(TestOverlappingFull::C));
+ assert_eq!(
+ "A | D",
+ write(TestOverlappingFull::C | TestOverlappingFull::D)
+ );
+ }
+
+ fn write<F: Flags>(value: F) -> String
+ where
+ F::Bits: crate::parser::WriteHex,
+ {
+ let mut s = String::new();
+
+ to_writer(&value, &mut s).unwrap();
+ s
+ }
+}
+
+mod from_str_truncate {
+ use super::*;
+
+ #[test]
+ fn valid() {
+ assert_eq!(0, from_str_truncate::<TestFlags>("").unwrap().bits());
+
+ assert_eq!(1, from_str_truncate::<TestFlags>("A").unwrap().bits());
+ assert_eq!(1, from_str_truncate::<TestFlags>(" A ").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_truncate::<TestFlags>("A | B | C").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_truncate::<TestFlags>("A\n|\tB\r\n| C ")
+ .unwrap()
+ .bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_truncate::<TestFlags>("A|B|C").unwrap().bits()
+ );
+
+ assert_eq!(0, from_str_truncate::<TestFlags>("0x8").unwrap().bits());
+ assert_eq!(1, from_str_truncate::<TestFlags>("A | 0x8").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str_truncate::<TestFlags>("0x1 | 0x8 | B")
+ .unwrap()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str_truncate::<TestUnicode>("一 | 二").unwrap().bits()
+ );
+ }
+}
+
+mod to_writer_truncate {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!("", write(TestFlags::empty()));
+ assert_eq!("A", write(TestFlags::A));
+ assert_eq!("A | B | C", write(TestFlags::all()));
+ assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
+ assert_eq!(
+ "A",
+ write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
+ );
+
+ assert_eq!("", write(TestZero::ZERO));
+
+ assert_eq!("ABC", write(TestFlagsInvert::all()));
+
+ assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
+
+ assert_eq!("A", write(TestOverlappingFull::C));
+ assert_eq!(
+ "A | D",
+ write(TestOverlappingFull::C | TestOverlappingFull::D)
+ );
+ }
+
+ fn write<F: Flags>(value: F) -> String
+ where
+ F::Bits: crate::parser::WriteHex,
+ {
+ let mut s = String::new();
+
+ to_writer_truncate(&value, &mut s).unwrap();
+ s
+ }
+}
+
+mod from_str_strict {
+ use super::*;
+
+ #[test]
+ fn valid() {
+ assert_eq!(0, from_str_strict::<TestFlags>("").unwrap().bits());
+
+ assert_eq!(1, from_str_strict::<TestFlags>("A").unwrap().bits());
+ assert_eq!(1, from_str_strict::<TestFlags>(" A ").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_strict::<TestFlags>("A | B | C").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_strict::<TestFlags>("A\n|\tB\r\n| C ")
+ .unwrap()
+ .bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_strict::<TestFlags>("A|B|C").unwrap().bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str_strict::<TestUnicode>("一 | 二").unwrap().bits()
+ );
+ }
+
+ #[test]
+ fn invalid() {
+ assert!(from_str_strict::<TestFlags>("a")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+ assert!(from_str_strict::<TestFlags>("A & B")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+
+ assert!(from_str_strict::<TestFlags>("0x1")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ assert!(from_str_strict::<TestFlags>("0xg")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ assert!(from_str_strict::<TestFlags>("0xffffffffffff")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ }
+}
+
+mod to_writer_strict {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!("", write(TestFlags::empty()));
+ assert_eq!("A", write(TestFlags::A));
+ assert_eq!("A | B | C", write(TestFlags::all()));
+ assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
+ assert_eq!(
+ "A",
+ write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
+ );
+
+ assert_eq!("", write(TestZero::ZERO));
+
+ assert_eq!("ABC", write(TestFlagsInvert::all()));
+
+ assert_eq!("", write(TestOverlapping::from_bits_retain(1)));
+
+ assert_eq!("A", write(TestOverlappingFull::C));
+ assert_eq!(
+ "A | D",
+ write(TestOverlappingFull::C | TestOverlappingFull::D)
+ );
+ }
+
+ fn write<F: Flags>(value: F) -> String
+ where
+ F::Bits: crate::parser::WriteHex,
+ {
+ let mut s = String::new();
+
+ to_writer_strict(&value, &mut s).unwrap();
+ s
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/remove.rs b/third_party/rust/bitflags/src/tests/remove.rs
new file mode 100644
index 0000000000..574b1edbf2
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/remove.rs
@@ -0,0 +1,100 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::A, 0),
+ (TestFlags::empty(), 0),
+ (TestFlags::from_bits_retain(1 << 3), 0),
+ ],
+ TestFlags::remove,
+ TestFlags::set,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::A, 0),
+ (TestFlags::empty(), 1),
+ (TestFlags::B, 1),
+ ],
+ TestFlags::remove,
+ TestFlags::set,
+ );
+
+ case(
+ TestFlags::ABC,
+ &[
+ (TestFlags::A, 1 << 1 | 1 << 2),
+ (TestFlags::A | TestFlags::C, 1 << 1),
+ ],
+ TestFlags::remove,
+ TestFlags::set,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent_remove: impl FnMut(&mut T, T),
+ mut inherent_set: impl FnMut(&mut T, T, bool),
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_remove(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.remove({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::remove(&mut value, *input);
+ value
+ }
+ .bits(),
+ "Flags::remove({:?}, {:?})",
+ value,
+ input
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_set(&mut value, *input, false);
+ value
+ }
+ .bits(),
+ "{:?}.set({:?}, false)",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::set(&mut value, *input, false);
+ value
+ }
+ .bits(),
+ "Flags::set({:?}, {:?}, false)",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/symmetric_difference.rs b/third_party/rust/bitflags/src/tests/symmetric_difference.rs
new file mode 100644
index 0000000000..75e9123ac5
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/symmetric_difference.rs
@@ -0,0 +1,110 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::empty(), 0),
+ (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+ (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+ ],
+ TestFlags::symmetric_difference,
+ TestFlags::toggle,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::empty(), 1),
+ (TestFlags::A, 0),
+ (TestFlags::all(), 1 << 1 | 1 << 2),
+ ],
+ TestFlags::symmetric_difference,
+ TestFlags::toggle,
+ );
+
+ case(
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ &[
+ (TestFlags::ABC, 1 << 2 | 1 << 3),
+ (TestFlags::from_bits_retain(1 << 3), 1 | 1 << 1),
+ ],
+ TestFlags::symmetric_difference,
+ TestFlags::toggle,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitXor<Output = T> + std::ops::BitXorAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent_sym_diff: impl FnMut(T, T) -> T,
+ mut inherent_toggle: impl FnMut(&mut T, T),
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent_sym_diff(value, *input).bits(),
+ "{:?}.symmetric_difference({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::symmetric_difference(value, *input).bits(),
+ "Flags::symmetric_difference({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value ^ *input).bits(),
+ "{:?} ^ {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value ^= *input;
+ value
+ }
+ .bits(),
+ "{:?} ^= {:?}",
+ value,
+ input,
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_toggle(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.toggle({:?})",
+ value,
+ input,
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::toggle(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.toggle({:?})",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/union.rs b/third_party/rust/bitflags/src/tests/union.rs
new file mode 100644
index 0000000000..6190681931
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/union.rs
@@ -0,0 +1,71 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::A, 1),
+ (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+ (TestFlags::empty(), 0),
+ (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+ ],
+ TestFlags::union,
+ );
+
+ case(
+ TestFlags::A | TestFlags::C,
+ &[
+ (TestFlags::A | TestFlags::B, 1 | 1 << 1 | 1 << 2),
+ (TestFlags::A, 1 | 1 << 2),
+ ],
+ TestFlags::union,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitOr<Output = T> + std::ops::BitOrAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent: impl FnMut(T, T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(value, *input).bits(),
+ "{:?}.union({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::union(value, *input).bits(),
+ "Flags::union({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value | *input).bits(),
+ "{:?} | {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value |= *input;
+ value
+ }
+ .bits(),
+ "{:?} |= {:?}",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/traits.rs b/third_party/rust/bitflags/src/traits.rs
index 28235142de..3905d7d5b0 100644
--- a/third_party/rust/bitflags/src/traits.rs
+++ b/third_party/rust/bitflags/src/traits.rs
@@ -11,6 +11,7 @@ use crate::{
/**
A defined flags value that may be named or unnamed.
*/
+#[derive(Debug)]
pub struct Flag<B> {
name: &'static str,
value: B,
diff --git a/third_party/rust/byteorder/.cargo-checksum.json b/third_party/rust/byteorder/.cargo-checksum.json
index 434cc1a16f..bffae5de46 100644
--- a/third_party/rust/byteorder/.cargo-checksum.json
+++ b/third_party/rust/byteorder/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"3a745d94ee9dce0d9dc638c02078cd5001d3d9d12d58b4f220c0101e32cfc16a","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"8585455e5a0e638cf5d489a21e286e93680f835cb8a13595918b5eb7c8c7f212","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"9d57556868344534de2489317e3c6bb611348ecd44438dcb982bd8d2a55a5a1b","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"a80bf3cd446c9b6c0cca3865c4de047bdf4644b74cdf696822f8ff87adfa1fca","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/io.rs":"9612530634d0e7ce9887a23836b58c0d972c1f45b05d9ada8355961567075627","src/lib.rs":"813ce6a8beafee3fd4e63325d783108aa02e8c57e412bc97580191d84082fbc9"},"package":"14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"c1cb69be6db5933c4bb4ebb6591e0fe3e7b97d491face3abcf947383c218bb31","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"94ba374cb26f3c68fb83da2e5e7dce85920fc4fb827620b06b39d71a9d0e1e18","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"2f2d64924c35b7203e3e3f3d136fcb714281762d145ca3513246da5547b1d014","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"8b114080042d3292ec8de425904e4114b7f532fe3add0d807521e6cc166a17ea","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/io.rs":"9612530634d0e7ce9887a23836b58c0d972c1f45b05d9ada8355961567075627","src/lib.rs":"ab3394c385b32457795931440cfb8dbca70ba5d9e1a428fcf651f7ccb2d6c34f"},"package":"1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"} \ No newline at end of file
diff --git a/third_party/rust/byteorder/CHANGELOG.md b/third_party/rust/byteorder/CHANGELOG.md
index 6b51eb0760..9efb7ed29a 100644
--- a/third_party/rust/byteorder/CHANGELOG.md
+++ b/third_party/rust/byteorder/CHANGELOG.md
@@ -1,3 +1,7 @@
+**WARNING:** This CHANGELOG is no longer updated. The activity for this project
+is sparse enough that you should refer to the commit log instead.
+
+
1.3.4
=====
This patch release squashes deprecation warnings for the `try!` macro, in
diff --git a/third_party/rust/byteorder/Cargo.toml b/third_party/rust/byteorder/Cargo.toml
index c71f90ba9c..da515d9d90 100644
--- a/third_party/rust/byteorder/Cargo.toml
+++ b/third_party/rust/byteorder/Cargo.toml
@@ -3,33 +3,44 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
+edition = "2021"
+rust-version = "1.60"
name = "byteorder"
-version = "1.4.3"
+version = "1.5.0"
authors = ["Andrew Gallant <jamslam@gmail.com>"]
-exclude = ["/ci/*"]
description = "Library for reading/writing numbers in big-endian and little-endian."
homepage = "https://github.com/BurntSushi/byteorder"
documentation = "https://docs.rs/byteorder"
readme = "README.md"
-keywords = ["byte", "endian", "big-endian", "little-endian", "binary"]
-categories = ["encoding", "parsing", "no-std"]
+keywords = [
+ "byte",
+ "endian",
+ "big-endian",
+ "little-endian",
+ "binary",
+]
+categories = [
+ "encoding",
+ "parsing",
+ "no-std",
+]
license = "Unlicense OR MIT"
repository = "https://github.com/BurntSushi/byteorder"
+
[profile.bench]
opt-level = 3
[lib]
name = "byteorder"
bench = false
+
[dev-dependencies.quickcheck]
version = "0.9.2"
default-features = false
diff --git a/third_party/rust/byteorder/README.md b/third_party/rust/byteorder/README.md
index d8461c58f7..7c46019e0e 100644
--- a/third_party/rust/byteorder/README.md
+++ b/third_party/rust/byteorder/README.md
@@ -4,7 +4,7 @@ This crate provides convenience methods for encoding and decoding
numbers in either big-endian or little-endian order.
[![Build status](https://github.com/BurntSushi/byteorder/workflows/ci/badge.svg)](https://github.com/BurntSushi/byteorder/actions)
-[![](https://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder)
+[![crates.io](https://img.shields.io/crates/v/byteorder.svg)](https://crates.io/crates/byteorder)
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
@@ -56,6 +56,20 @@ byteorder = { version = "1", default-features = false }
```
+### Minimum Rust version policy
+
+This crate's minimum supported `rustc` version is `1.60.0`.
+
+The current policy is that the minimum Rust version required to use this crate
+can be increased in minor version updates. For example, if `crate 1.0` requires
+Rust 1.20.0, then `crate 1.0.z` for all values of `z` will also require Rust
+1.20.0 or newer. However, `crate 1.y` for `y > 0` may require a newer minimum
+version of Rust.
+
+In general, this crate will be conservative with respect to the minimum
+supported version of Rust.
+
+
### Alternatives
Note that as of Rust 1.32, the standard numeric types provide built-in methods
diff --git a/third_party/rust/byteorder/benches/bench.rs b/third_party/rust/byteorder/benches/bench.rs
index bb00422f79..963251ce56 100644
--- a/third_party/rust/byteorder/benches/bench.rs
+++ b/third_party/rust/byteorder/benches/bench.rs
@@ -321,4 +321,6 @@ macro_rules! bench_slice {
};
}
+bench_slice!(slice_u16, u16, read_u16_into, write_u16_into);
bench_slice!(slice_u64, u64, read_u64_into, write_u64_into);
+bench_slice!(slice_i64, i64, read_i64_into, write_i64_into);
diff --git a/third_party/rust/byteorder/src/lib.rs b/third_party/rust/byteorder/src/lib.rs
index cc37cca6ae..cfd53c3f95 100644
--- a/third_party/rust/byteorder/src/lib.rs
+++ b/third_party/rust/byteorder/src/lib.rs
@@ -69,9 +69,13 @@ cases.
#![deny(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
+// When testing under miri, we disable tests that take too long. But this
+// provokes lots of dead code warnings. So we just squash them.
+#![cfg_attr(miri, allow(dead_code, unused_macros))]
use core::{
- convert::TryInto, fmt::Debug, hash::Hash, ptr::copy_nonoverlapping, slice,
+ convert::TryInto, fmt::Debug, hash::Hash, mem::align_of,
+ ptr::copy_nonoverlapping, slice,
};
#[cfg(feature = "std")]
@@ -1202,6 +1206,7 @@ pub trait ByteOrder:
#[inline]
fn read_f32_into(src: &[u8], dst: &mut [f32]) {
let dst = unsafe {
+ const _: () = assert!(align_of::<u32>() <= align_of::<f32>());
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len())
};
Self::read_u32_into(src, dst);
@@ -1263,6 +1268,7 @@ pub trait ByteOrder:
#[inline]
fn read_f64_into(src: &[u8], dst: &mut [f64]) {
let dst = unsafe {
+ const _: () = assert!(align_of::<u64>() <= align_of::<f64>());
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len())
};
Self::read_u64_into(src, dst);
@@ -1895,74 +1901,36 @@ pub type NativeEndian = LittleEndian;
#[cfg(target_endian = "big")]
pub type NativeEndian = BigEndian;
-/// Copies $size bytes from a number $n to a &mut [u8] $dst. $ty represents the
-/// numeric type of $n and $which must be either to_be or to_le, depending on
-/// which endianness one wants to use when writing to $dst.
+/// Copies a &[u8] $src into a &mut [$ty] $dst for the endianness given by
+/// $from_bytes (must be either from_be_bytes or from_le_bytes).
///
-/// This macro is only safe to call when $ty is a numeric type and $size ==
-/// size_of::<$ty>() and where $dst is a &mut [u8].
-macro_rules! unsafe_write_num_bytes {
- ($ty:ty, $size:expr, $n:expr, $dst:expr, $which:ident) => {{
- assert!($size <= $dst.len());
- unsafe {
- // N.B. https://github.com/rust-lang/rust/issues/22776
- let bytes = *(&$n.$which() as *const _ as *const [u8; $size]);
- copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size);
+/// Panics if $src.len() != $dst.len() * size_of::<$ty>().
+macro_rules! read_slice {
+ ($src:expr, $dst:expr, $ty:ty, $from_bytes:ident) => {{
+ const SIZE: usize = core::mem::size_of::<$ty>();
+ // Check types:
+ let src: &[u8] = $src;
+ let dst: &mut [$ty] = $dst;
+ assert_eq!(src.len(), dst.len() * SIZE);
+ for (src, dst) in src.chunks_exact(SIZE).zip(dst.iter_mut()) {
+ *dst = <$ty>::$from_bytes(src.try_into().unwrap());
}
}};
}
-/// Copies a &[u8] $src into a &mut [<numeric>] $dst for the endianness given
-/// by $which (must be either to_be or to_le).
+/// Copies a &[$ty] $src into a &mut [u8] $dst for the endianness given by
+/// $from_bytes (must be either from_be_bytes or from_le_bytes).
///
-/// This macro is only safe to call when $src and $dst are &[u8] and &mut [u8],
-/// respectively. The macro will panic if $src.len() != $size * $dst.len(),
-/// where $size represents the size of the integers encoded in $src.
-macro_rules! unsafe_read_slice {
- ($src:expr, $dst:expr, $size:expr, $which:ident) => {{
- assert_eq!($src.len(), $size * $dst.len());
-
- unsafe {
- copy_nonoverlapping(
- $src.as_ptr(),
- $dst.as_mut_ptr() as *mut u8,
- $src.len(),
- );
- }
- for v in $dst.iter_mut() {
- *v = v.$which();
- }
- }};
-}
-
-/// Copies a &[$ty] $src into a &mut [u8] $dst, where $ty must be a numeric
-/// type. This panics if size_of::<$ty>() * $src.len() != $dst.len().
-///
-/// This macro is only safe to call when $src is a slice of numeric types and
-/// $dst is a &mut [u8] and where $ty represents the type of the integers in
-/// $src.
-macro_rules! unsafe_write_slice_native {
- ($src:expr, $dst:expr, $ty:ty) => {{
- let size = core::mem::size_of::<$ty>();
- assert_eq!(size * $src.len(), $dst.len());
-
- unsafe {
- copy_nonoverlapping(
- $src.as_ptr() as *const u8,
- $dst.as_mut_ptr(),
- $dst.len(),
- );
- }
- }};
-}
-
+/// Panics if $src.len() * size_of::<$ty>() != $dst.len().
macro_rules! write_slice {
- ($src:expr, $dst:expr, $ty:ty, $size:expr, $write:expr) => {{
- assert!($size == ::core::mem::size_of::<$ty>());
- assert_eq!($size * $src.len(), $dst.len());
-
- for (&n, chunk) in $src.iter().zip($dst.chunks_mut($size)) {
- $write(chunk, n);
+ ($src:expr, $dst:expr, $ty:ty, $to_bytes:ident) => {{
+ const SIZE: usize = core::mem::size_of::<$ty>();
+ // Check types:
+ let src: &[$ty] = $src;
+ let dst: &mut [u8] = $dst;
+ assert_eq!(src.len() * SIZE, dst.len());
+ for (src, dst) in src.iter().zip(dst.chunks_exact_mut(SIZE)) {
+ dst.copy_from_slice(&src.$to_bytes());
}
}};
}
@@ -1990,52 +1958,40 @@ impl ByteOrder for BigEndian {
#[inline]
fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
- assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len());
- let mut out = 0u64;
- let ptr_out = &mut out as *mut u64 as *mut u8;
- unsafe {
- copy_nonoverlapping(
- buf.as_ptr(),
- ptr_out.offset((8 - nbytes) as isize),
- nbytes,
- );
- }
- out.to_be()
+ let mut out = [0; 8];
+ assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len());
+ let start = out.len() - nbytes;
+ out[start..].copy_from_slice(&buf[..nbytes]);
+ u64::from_be_bytes(out)
}
#[inline]
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
- assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
- let mut out: u128 = 0;
- let ptr_out = &mut out as *mut u128 as *mut u8;
- unsafe {
- copy_nonoverlapping(
- buf.as_ptr(),
- ptr_out.offset((16 - nbytes) as isize),
- nbytes,
- );
- }
- out.to_be()
+ let mut out = [0; 16];
+ assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len());
+ let start = out.len() - nbytes;
+ out[start..].copy_from_slice(&buf[..nbytes]);
+ u128::from_be_bytes(out)
}
#[inline]
fn write_u16(buf: &mut [u8], n: u16) {
- unsafe_write_num_bytes!(u16, 2, n, buf, to_be);
+ buf[..2].copy_from_slice(&n.to_be_bytes());
}
#[inline]
fn write_u32(buf: &mut [u8], n: u32) {
- unsafe_write_num_bytes!(u32, 4, n, buf, to_be);
+ buf[..4].copy_from_slice(&n.to_be_bytes());
}
#[inline]
fn write_u64(buf: &mut [u8], n: u64) {
- unsafe_write_num_bytes!(u64, 8, n, buf, to_be);
+ buf[..8].copy_from_slice(&n.to_be_bytes());
}
#[inline]
fn write_u128(buf: &mut [u8], n: u128) {
- unsafe_write_num_bytes!(u128, 16, n, buf, to_be);
+ buf[..16].copy_from_slice(&n.to_be_bytes());
}
#[inline]
@@ -2068,58 +2024,42 @@ impl ByteOrder for BigEndian {
#[inline]
fn read_u16_into(src: &[u8], dst: &mut [u16]) {
- unsafe_read_slice!(src, dst, 2, to_be);
+ read_slice!(src, dst, u16, from_be_bytes);
}
#[inline]
fn read_u32_into(src: &[u8], dst: &mut [u32]) {
- unsafe_read_slice!(src, dst, 4, to_be);
+ read_slice!(src, dst, u32, from_be_bytes);
}
#[inline]
fn read_u64_into(src: &[u8], dst: &mut [u64]) {
- unsafe_read_slice!(src, dst, 8, to_be);
+ read_slice!(src, dst, u64, from_be_bytes);
}
#[inline]
fn read_u128_into(src: &[u8], dst: &mut [u128]) {
- unsafe_read_slice!(src, dst, 16, to_be);
+ read_slice!(src, dst, u128, from_be_bytes);
}
#[inline]
fn write_u16_into(src: &[u16], dst: &mut [u8]) {
- if cfg!(target_endian = "big") {
- unsafe_write_slice_native!(src, dst, u16);
- } else {
- write_slice!(src, dst, u16, 2, Self::write_u16);
- }
+ write_slice!(src, dst, u16, to_be_bytes);
}
#[inline]
fn write_u32_into(src: &[u32], dst: &mut [u8]) {
- if cfg!(target_endian = "big") {
- unsafe_write_slice_native!(src, dst, u32);
- } else {
- write_slice!(src, dst, u32, 4, Self::write_u32);
- }
+ write_slice!(src, dst, u32, to_be_bytes);
}
#[inline]
fn write_u64_into(src: &[u64], dst: &mut [u8]) {
- if cfg!(target_endian = "big") {
- unsafe_write_slice_native!(src, dst, u64);
- } else {
- write_slice!(src, dst, u64, 8, Self::write_u64);
- }
+ write_slice!(src, dst, u64, to_be_bytes);
}
#[inline]
fn write_u128_into(src: &[u128], dst: &mut [u8]) {
- if cfg!(target_endian = "big") {
- unsafe_write_slice_native!(src, dst, u128);
- } else {
- write_slice!(src, dst, u128, 16, Self::write_u128);
- }
+ write_slice!(src, dst, u128, to_be_bytes);
}
#[inline]
@@ -2206,44 +2146,38 @@ impl ByteOrder for LittleEndian {
#[inline]
fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
- assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len());
- let mut out = 0u64;
- let ptr_out = &mut out as *mut u64 as *mut u8;
- unsafe {
- copy_nonoverlapping(buf.as_ptr(), ptr_out, nbytes);
- }
- out.to_le()
+ let mut out = [0; 8];
+ assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len());
+ out[..nbytes].copy_from_slice(&buf[..nbytes]);
+ u64::from_le_bytes(out)
}
#[inline]
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
- assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
- let mut out: u128 = 0;
- let ptr_out = &mut out as *mut u128 as *mut u8;
- unsafe {
- copy_nonoverlapping(buf.as_ptr(), ptr_out, nbytes);
- }
- out.to_le()
+ let mut out = [0; 16];
+ assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len());
+ out[..nbytes].copy_from_slice(&buf[..nbytes]);
+ u128::from_le_bytes(out)
}
#[inline]
fn write_u16(buf: &mut [u8], n: u16) {
- unsafe_write_num_bytes!(u16, 2, n, buf, to_le);
+ buf[..2].copy_from_slice(&n.to_le_bytes());
}
#[inline]
fn write_u32(buf: &mut [u8], n: u32) {
- unsafe_write_num_bytes!(u32, 4, n, buf, to_le);
+ buf[..4].copy_from_slice(&n.to_le_bytes());
}
#[inline]
fn write_u64(buf: &mut [u8], n: u64) {
- unsafe_write_num_bytes!(u64, 8, n, buf, to_le);
+ buf[..8].copy_from_slice(&n.to_le_bytes());
}
#[inline]
fn write_u128(buf: &mut [u8], n: u128) {
- unsafe_write_num_bytes!(u128, 16, n, buf, to_le);
+ buf[..16].copy_from_slice(&n.to_le_bytes());
}
#[inline]
@@ -2268,58 +2202,42 @@ impl ByteOrder for LittleEndian {
#[inline]
fn read_u16_into(src: &[u8], dst: &mut [u16]) {
- unsafe_read_slice!(src, dst, 2, to_le);
+ read_slice!(src, dst, u16, from_le_bytes);
}
#[inline]
fn read_u32_into(src: &[u8], dst: &mut [u32]) {
- unsafe_read_slice!(src, dst, 4, to_le);
+ read_slice!(src, dst, u32, from_le_bytes);
}
#[inline]
fn read_u64_into(src: &[u8], dst: &mut [u64]) {
- unsafe_read_slice!(src, dst, 8, to_le);
+ read_slice!(src, dst, u64, from_le_bytes);
}
#[inline]
fn read_u128_into(src: &[u8], dst: &mut [u128]) {
- unsafe_read_slice!(src, dst, 16, to_le);
+ read_slice!(src, dst, u128, from_le_bytes);
}
#[inline]
fn write_u16_into(src: &[u16], dst: &mut [u8]) {
- if cfg!(target_endian = "little") {
- unsafe_write_slice_native!(src, dst, u16);
- } else {
- write_slice!(src, dst, u16, 2, Self::write_u16);
- }
+ write_slice!(src, dst, u16, to_le_bytes);
}
#[inline]
fn write_u32_into(src: &[u32], dst: &mut [u8]) {
- if cfg!(target_endian = "little") {
- unsafe_write_slice_native!(src, dst, u32);
- } else {
- write_slice!(src, dst, u32, 4, Self::write_u32);
- }
+ write_slice!(src, dst, u32, to_le_bytes);
}
#[inline]
fn write_u64_into(src: &[u64], dst: &mut [u8]) {
- if cfg!(target_endian = "little") {
- unsafe_write_slice_native!(src, dst, u64);
- } else {
- write_slice!(src, dst, u64, 8, Self::write_u64);
- }
+ write_slice!(src, dst, u64, to_le_bytes);
}
#[inline]
fn write_u128_into(src: &[u128], dst: &mut [u8]) {
- if cfg!(target_endian = "little") {
- unsafe_write_slice_native!(src, dst, u128);
- } else {
- write_slice!(src, dst, u128, 16, Self::write_u128);
- }
+ write_slice!(src, dst, u128, to_le_bytes);
}
#[inline]
@@ -2449,6 +2367,7 @@ mod test {
macro_rules! qc_byte_order {
($name:ident, $ty_int:ty, $max:expr,
$bytes:expr, $read:ident, $write:ident) => {
+ #[cfg(not(miri))]
mod $name {
#[allow(unused_imports)]
use super::{qc_sized, Wi128};
@@ -2489,6 +2408,7 @@ mod test {
};
($name:ident, $ty_int:ty, $max:expr,
$read:ident, $write:ident) => {
+ #[cfg(not(miri))]
mod $name {
#[allow(unused_imports)]
use super::{qc_sized, Wi128};
@@ -3405,6 +3325,7 @@ mod stdtests {
macro_rules! qc_bytes_ext {
($name:ident, $ty_int:ty, $max:expr,
$bytes:expr, $read:ident, $write:ident) => {
+ #[cfg(not(miri))]
mod $name {
#[allow(unused_imports)]
use crate::test::{qc_sized, Wi128};
@@ -3455,6 +3376,7 @@ mod stdtests {
}
};
($name:ident, $ty_int:ty, $max:expr, $read:ident, $write:ident) => {
+ #[cfg(not(miri))]
mod $name {
#[allow(unused_imports)]
use crate::test::{qc_sized, Wi128};
@@ -3951,6 +3873,7 @@ mod stdtests {
// Test slice serialization/deserialization.
macro_rules! qc_slice {
($name:ident, $ty_int:ty, $read:ident, $write:ident, $zero:expr) => {
+ #[cfg(not(miri))]
mod $name {
use super::qc_unsized;
#[allow(unused_imports)]
diff --git a/third_party/rust/core-foundation-sys/.cargo-checksum.json b/third_party/rust/core-foundation-sys/.cargo-checksum.json
index 0bdf990864..7dd167643b 100644
--- a/third_party/rust/core-foundation-sys/.cargo-checksum.json
+++ b/third_party/rust/core-foundation-sys/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"ddcd13ba60bd9368949654be284efac4a55e482b7233e42c9d2fef97ff825eb8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","build.rs":"9433ed3b20cc99e716dda4c6d8507c29bc04882544cbbea8d4e48ba80fd0fa12","src/array.rs":"40c305658e16b07d86353a5ad34e7b5fb98720f19cc2b5173360d6a61ce2642f","src/attributed_string.rs":"48c2d161d6f54136ae895a9f52efad1f831718ea331b875d25498039158a2d51","src/base.rs":"7b21281e9a01903c79a7891ee4e1865a11504b281b468815d1a3838e1744a3c2","src/bundle.rs":"2a3413e649e1cf5eb1557fa5e3e6d442389caa2978a4a0c2c7afdfa4c388c0bf","src/characterset.rs":"a10bbb42ddc74b3dc50b43ae6a50cc9d9a1cd08b975a1ce1b092be4bf64448a6","src/data.rs":"2b121f102b4c2778475f4902016820c4a70e2f8ac532af53913561d42757fa2e","src/date.rs":"c064ee4c3ebd1927532c34871e2e41179d6e3c3e400f6b409a18ad9e2337477f","src/dictionary.rs":"3327a6f90f1e0db5e3fde1973e2df4143ca896716a816d03f2b17c8e988c5159","src/error.rs":"6205ebeb7631daa8bcd560862b6daa10f640c8c117ce5f6f7184f268dcbcb42a","src/filedescriptor.rs":"49580654b657811fade7adaa256f5f895cb011c9baa4731e2f44a6ec7fdba235","src/lib.rs":"e0b6b9d16f6cae1328de772e056e90003b0a5aa5859f5cde58f6aac4683bb543","src/mach_port.rs":"bd413d44772eaeb24e74e1b7b4f234b159b916caa0896c8e82fe54ce1b9deeb6","src/messageport.rs":"e9227d5907cba8e29cdeea41bcb3ae5c7840220442953ab19aace31a84542f47","src/number.rs":"f28040accfbbec99c4e55f411facac7cde4ad89298af2d7d907312f18e4263bf","src/propertylist.rs":"7ec928438826c4ce40befedf3de0a37c8ecbc0fc17896dfa629d5864000b2cfe","src/runloop.rs":"26ca33e2472d191f583e01c24e8cd262f54de8b542fbe7278f33ab08b2925794","src/set.rs":"116c2f18008bfbeecac570d366dbd95b8fe5b9373e3e1bdd2c1d588314d776c5","src/string.rs":"b2856d0bf7a8583370d18d3f041ac5eb00fd6a1aabc69503e7c11a93d42036d8","src/timezone.rs":"c7dd9557646b7ff2bfd6a98bf92142b8304125b4e78dd651b687abc8da191159","src/url.rs":"4358f756ed3d5e9afd5a7f3e2e9115adc6133b47dc7ce59d6ebb32c6610b0e8f","src/uuid.rs":"82f75efa73d0842dff2e13d299c166c6593a77fcb69c4b7629a2df1c17ae507d"},"package":"5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"} \ No newline at end of file
+{"files":{"Cargo.toml":"f8b5e9fa6c6bbfad4e3c0acfbad03f05cbd98073e664e3ad2fe16a56dd492aa1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"4d469ca3f6aceb42dfaf7b26aa9ef14a8ebce05e02d0beda985fa32f2ec48963","src/attributed_string.rs":"7042f3fbf6904efecb15f01ce2e96eecf84973e0fef9be4c10d14944b0f90a24","src/bag.rs":"dec9ff467ac713526c3be8148ae41b21ab8840f393733bb53c77224ef089787c","src/base.rs":"5d0dee358519712e881e2edbea0ca6d3539958ed1ff3d70aa136af7e25292f22","src/binary_heap.rs":"0565125dbdb1fa578888e00f5b195ab91f0bf65881eabcd39de99ca811d756de","src/bit_vector.rs":"dcdaa573d90b25bdc6b98f2330110e8591b7c329601643dcc6aa23b1b9ec7210","src/bundle.rs":"83ac9d7c45f06161767588c465eed086a773714734da0614d98d000326df3603","src/calendar.rs":"b73796956e50d92f0479479e84246712804537d694e4cdd01d5440e5fbcbd333","src/characterset.rs":"ba60f78884cd860e151df35c1953bcd6eae46d9f27c36584b66e508e2301a7a8","src/data.rs":"fe4e2effbfd9348575507d06aa53cd583808c908f9e03ac1a076b077230c9c01","src/date.rs":"971d681f6eeefa3764d8a43e53cbf7c937c419331207c7bb003a25c9b0b0722f","src/date_formatter.rs":"05e84ac3cf4c0daae2e939a9bedddfd10dd5309ea1536bf8241de41971d11f8a","src/dictionary.rs":"ac23d99208131049c82c13b37a99b4fd129224d1dafcd65ff2f9de200d73e9d1","src/error.rs":"b523faa8c498e1115c72e71a10e7a3bf8bcc01588cb02e70dc9fd45cbdaa35f6","src/file_security.rs":"542c5d8eef22424479abcb448601611d85c9cc96e41cd6cd6de5ea3efe1213a6","src/filedescriptor.rs":"706eebde408713cc49bbab078e86fe51e95fe29b167420bbcbb573847dcf29e2","src/lib.rs":"8ae5082d92ebf6b1a53332211b87986aa7228534f5e341b62100e522b7fcadec","src/locale.rs":"372190a9cb5659fba0b92598c5dcbdaa3f90b29b3440ddcfe77931e85c1f96d9","src/mach_port.rs":"e52c2ce794e82ebeeb0cba170902409f18626b7d9e29d6dcd333e9c13411408a","src/messageport.rs":"d8e342f0eabe47f6f4746fdbf996bf9008b4b5f1fa24e0bc4ecd73b2de81b234","src/notification_center.rs":"0ab30523bc4ac799016970c9c59594cbb3afeda054705c15d0979eb07abb7c7d","src/number.rs":"28b10c9d2361cac18549ef66839f595e98490096e756e9a7f25536b6ceb1f687","src/number_formatter.rs":"024fbd3b2ecaecf19cfdb463e0f0096d1fa28bc4ce636659e53459d1b01af658","src/plugin.rs":"0904b1b4b882e626d5d63ac91c540dfdf65f5f4428cf38c9def6acfc7ed84cd3","src/preferences.rs":"49d8ac0c669a01678fa0dc26d6cb13bc72004c8422e525bf3e26f01feb5a3693","src/propertylist.rs":"f7f12cb8c67098e5b96cb8a63b4a947549a2cbf7a6523ce314141b4f8cc202c4","src/runloop.rs":"8fa6e5e74a013f8101d5a4f6616818573adc7ed197e28b799dca4c3a1cedaac9","src/set.rs":"0e619ec75a6b975be6b6d59ed3b01c803dd635020288b178db949b1c45442d17","src/socket.rs":"b67737b8c04142fa4d198c19f0867fd653837e529bf2665e78750c94f469a793","src/stream.rs":"f9b1099191010a96ce0aadcc22385732710dfc1521873096a9db67ad80472e36","src/string.rs":"fa46e7b7865709494bb05c9c7c6006f165fafa956ab41f053af0e4b41904efa4","src/string_tokenizer.rs":"0da4ae1a841591871602f21cc1c9b51289a0514a255b269e4b61afdeb0097c10","src/timezone.rs":"f584ea76627f12f33eba25d7ea054c2d2c10a2d96474fce12858ccb4bdf688c1","src/tree.rs":"50d513ea1801797c549218c51f5ebf77be4cf80901b12ce3ba0a223c602995d4","src/url.rs":"cb08b0bd24708e6572711f4f82b88370e811aabf4f58f22c34f0f873a44c7486","src/url_enumerator.rs":"bd531f31f6c62b2849d5ccbc82bfc3ae3866c4cdd6768b6c2fe380f24c290540","src/user_notification.rs":"e86b052817028847e62121752e7d58f8ed6f8ad15f5ef947c1fa93bbd0fcbf26","src/uuid.rs":"48af493dc6c8b00d804d6ae92a2fd71eabdae8a2be0500baaa55ce56345c350a","src/xml_node.rs":"c7894a4d08f695ba75d539b3c8d6cc3a90544000786fe3f9cd9c02ad7541213b","src/xml_parser.rs":"ac8a3d2c71ec8ec80603ce5ef214147c0e93bed211c1559a47f14fc31cb0bbaf"},"package":"06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"} \ No newline at end of file
diff --git a/third_party/rust/core-foundation-sys/Cargo.toml b/third_party/rust/core-foundation-sys/Cargo.toml
index bd17103b56..345cbab915 100644
--- a/third_party/rust/core-foundation-sys/Cargo.toml
+++ b/third_party/rust/core-foundation-sys/Cargo.toml
@@ -3,27 +3,30 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
+edition = "2018"
name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.6"
authors = ["The Servo Project Developers"]
-build = "build.rs"
description = "Bindings to Core Foundation for macOS"
homepage = "https://github.com/servo/core-foundation-rs"
-license = "MIT / Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/core-foundation-rs"
+
[package.metadata.docs.rs]
+all-features = true
default-target = "x86_64-apple-darwin"
[dependencies]
[features]
+default = ["link"]
+link = []
mac_os_10_7_support = []
mac_os_10_8_features = []
diff --git a/third_party/rust/core-foundation-sys/build.rs b/third_party/rust/core-foundation-sys/build.rs
deleted file mode 100644
index 1f03b0602e..0000000000
--- a/third_party/rust/core-foundation-sys/build.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- if std::env::var("TARGET").unwrap().contains("-apple") {
- println!("cargo:rustc-link-lib=framework=CoreFoundation");
- }
-}
diff --git a/third_party/rust/core-foundation-sys/src/array.rs b/third_party/rust/core-foundation-sys/src/array.rs
index 5090302fc2..1e521b3e48 100644
--- a/third_party/rust/core-foundation-sys/src/array.rs
+++ b/third_party/rust/core-foundation-sys/src/array.rs
@@ -9,16 +9,19 @@
use std::os::raw::c_void;
-use base::{CFRange, CFIndex, CFAllocatorRef, CFTypeID, Boolean};
-use string::CFStringRef;
+use crate::base::{Boolean, CFAllocatorRef, CFComparatorFunction, CFIndex, CFRange, CFTypeID};
+use crate::string::CFStringRef;
-pub type CFArrayRetainCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
+pub type CFArrayRetainCallBack =
+ extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
pub type CFArrayReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void);
pub type CFArrayCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef;
-pub type CFArrayEqualCallBack = extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
+pub type CFArrayEqualCallBack =
+ extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
+pub type CFArrayApplierFunction = extern "C" fn(value: *const c_void, context: *mut c_void);
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub struct CFArrayCallBacks {
pub version: CFIndex,
pub retain: CFArrayRetainCallBack,
@@ -31,25 +34,109 @@ pub struct CFArrayCallBacks {
pub struct __CFArray(c_void);
pub type CFArrayRef = *const __CFArray;
+pub type CFMutableArrayRef = *mut __CFArray;
-extern {
+extern "C" {
/*
* CFArray.h
*/
+
pub static kCFTypeArrayCallBacks: CFArrayCallBacks;
- pub fn CFArrayCreate(allocator: CFAllocatorRef, values: *const *const c_void,
- numValues: CFIndex, callBacks: *const CFArrayCallBacks) -> CFArrayRef;
- pub fn CFArrayCreateCopy(allocator: CFAllocatorRef , theArray: CFArrayRef) -> CFArrayRef;
-
- // CFArrayBSearchValues
- // CFArrayContainsValue
+ /* CFArray */
+ /* Creating an Array */
+ pub fn CFArrayCreate(
+ allocator: CFAllocatorRef,
+ values: *const *const c_void,
+ numValues: CFIndex,
+ callBacks: *const CFArrayCallBacks,
+ ) -> CFArrayRef;
+ pub fn CFArrayCreateCopy(allocator: CFAllocatorRef, theArray: CFArrayRef) -> CFArrayRef;
+
+ /* Examining an Array */
+ pub fn CFArrayBSearchValues(
+ theArray: CFArrayRef,
+ range: CFRange,
+ value: *const c_void,
+ comparator: CFComparatorFunction,
+ context: *mut c_void,
+ ) -> CFIndex;
+ pub fn CFArrayContainsValue(
+ theArray: CFArrayRef,
+ range: CFRange,
+ value: *const c_void,
+ ) -> Boolean;
pub fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex;
- // CFArrayGetCountOfValue
- // CFArrayGetFirstIndexOfValue
- // CFArrayGetLastIndexOfValue
+ pub fn CFArrayGetCountOfValue(
+ theArray: CFArrayRef,
+ range: CFRange,
+ value: *const c_void,
+ ) -> CFIndex;
+ pub fn CFArrayGetFirstIndexOfValue(
+ theArray: CFArrayRef,
+ range: CFRange,
+ value: *const c_void,
+ ) -> CFIndex;
+ pub fn CFArrayGetLastIndexOfValue(
+ theArray: CFArrayRef,
+ range: CFRange,
+ value: *const c_void,
+ ) -> CFIndex;
pub fn CFArrayGetValues(theArray: CFArrayRef, range: CFRange, values: *mut *const c_void);
pub fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *const c_void;
- // CFArrayApplyFunction
+
+ /* Applying a Function to Elements */
+ pub fn CFArrayApplyFunction(
+ theArray: CFArrayRef,
+ range: CFRange,
+ applier: CFArrayApplierFunction,
+ context: *mut c_void,
+ );
+
+ /* Getting the CFArray Type ID */
pub fn CFArrayGetTypeID() -> CFTypeID;
+
+ /* CFMutableArray */
+ /* CFMutableArray Miscellaneous Functions */
+ pub fn CFArrayAppendArray(
+ theArray: CFMutableArrayRef,
+ otherArray: CFArrayRef,
+ otherRange: CFRange,
+ );
+ pub fn CFArrayAppendValue(theArray: CFMutableArrayRef, value: *const c_void);
+ pub fn CFArrayCreateMutable(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ callBacks: *const CFArrayCallBacks,
+ ) -> CFMutableArrayRef;
+ pub fn CFArrayCreateMutableCopy(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ theArray: CFArrayRef,
+ ) -> CFMutableArrayRef;
+ pub fn CFArrayExchangeValuesAtIndices(
+ theArray: CFMutableArrayRef,
+ idx1: CFIndex,
+ idx2: CFIndex,
+ );
+ pub fn CFArrayInsertValueAtIndex(
+ theArray: CFMutableArrayRef,
+ idx: CFIndex,
+ value: *const c_void,
+ );
+ pub fn CFArrayRemoveAllValues(theArray: CFMutableArrayRef);
+ pub fn CFArrayRemoveValueAtIndex(theArray: CFMutableArrayRef, idx: CFIndex);
+ pub fn CFArrayReplaceValues(
+ theArray: CFMutableArrayRef,
+ range: CFRange,
+ newValues: *mut *const c_void,
+ newCount: CFIndex,
+ );
+ pub fn CFArraySetValueAtIndex(theArray: CFMutableArrayRef, idx: CFIndex, value: *const c_void);
+ pub fn CFArraySortValues(
+ theArray: CFMutableArrayRef,
+ range: CFRange,
+ comparator: CFComparatorFunction,
+ context: *mut c_void,
+ );
}
diff --git a/third_party/rust/core-foundation-sys/src/attributed_string.rs b/third_party/rust/core-foundation-sys/src/attributed_string.rs
index c91bf5be38..54c27ec416 100644
--- a/third_party/rust/core-foundation-sys/src/attributed_string.rs
+++ b/third_party/rust/core-foundation-sys/src/attributed_string.rs
@@ -7,49 +7,114 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFRange, CFTypeID, CFTypeRef};
+use crate::dictionary::CFDictionaryRef;
+use crate::string::CFMutableStringRef;
+use crate::string::CFStringRef;
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFTypeRef, CFIndex, CFRange, CFTypeID};
-use string::CFStringRef;
-use dictionary::CFDictionaryRef;
#[repr(C)]
pub struct __CFAttributedString(c_void);
pub type CFAttributedStringRef = *const __CFAttributedString;
-pub type CFMutableAttributedStringRef = *const __CFAttributedString;
+pub type CFMutableAttributedStringRef = *mut __CFAttributedString;
-extern {
- /* CFAttributedString */
+extern "C" {
+ /*
+ * CFAttributedString.h
+ */
+ /* CFAttributedString */
+ /* Creating a CFAttributedString */
pub fn CFAttributedStringCreate(
allocator: CFAllocatorRef,
str: CFStringRef,
attributes: CFDictionaryRef,
) -> CFAttributedStringRef;
-
+ pub fn CFAttributedStringCreateCopy(
+ alloc: CFAllocatorRef,
+ aStr: CFAttributedStringRef,
+ ) -> CFAttributedStringRef;
+ pub fn CFAttributedStringCreateWithSubstring(
+ alloc: CFAllocatorRef,
+ aStr: CFAttributedStringRef,
+ range: CFRange,
+ ) -> CFAttributedStringRef;
pub fn CFAttributedStringGetLength(astr: CFAttributedStringRef) -> CFIndex;
+ pub fn CFAttributedStringGetString(aStr: CFAttributedStringRef) -> CFStringRef;
+
+ /* Accessing Attributes */
+ pub fn CFAttributedStringGetAttribute(
+ aStr: CFAttributedStringRef,
+ loc: CFIndex,
+ attrName: CFStringRef,
+ effectiveRange: *mut CFRange,
+ ) -> CFTypeRef;
+ pub fn CFAttributedStringGetAttributes(
+ aStr: CFAttributedStringRef,
+ loc: CFIndex,
+ effectiveRange: *mut CFRange,
+ ) -> CFDictionaryRef;
+ pub fn CFAttributedStringGetAttributeAndLongestEffectiveRange(
+ aStr: CFAttributedStringRef,
+ loc: CFIndex,
+ attrName: CFStringRef,
+ inRange: CFRange,
+ longestEffectiveRange: *mut CFRange,
+ ) -> CFTypeRef;
+ pub fn CFAttributedStringGetAttributesAndLongestEffectiveRange(
+ aStr: CFAttributedStringRef,
+ loc: CFIndex,
+ inRange: CFRange,
+ longestEffectiveRange: *mut CFRange,
+ ) -> CFDictionaryRef;
+ /* Getting Attributed String Properties */
pub fn CFAttributedStringGetTypeID() -> CFTypeID;
/* CFMutableAttributedString */
-
- pub fn CFAttributedStringCreateMutableCopy(
- allocator: CFAllocatorRef, max_length: CFIndex, astr: CFAttributedStringRef
- ) -> CFMutableAttributedStringRef;
-
+ /* Creating a CFMutableAttributedString */
pub fn CFAttributedStringCreateMutable(
allocator: CFAllocatorRef,
max_length: CFIndex,
) -> CFMutableAttributedStringRef;
+ pub fn CFAttributedStringCreateMutableCopy(
+ allocator: CFAllocatorRef,
+ max_length: CFIndex,
+ astr: CFAttributedStringRef,
+ ) -> CFMutableAttributedStringRef;
+ /* Modifying a CFMutableAttributedString */
+ pub fn CFAttributedStringBeginEditing(aStr: CFMutableAttributedStringRef);
+ pub fn CFAttributedStringEndEditing(aStr: CFMutableAttributedStringRef);
+ pub fn CFAttributedStringGetMutableString(
+ aStr: CFMutableAttributedStringRef,
+ ) -> CFMutableStringRef;
+ pub fn CFAttributedStringRemoveAttribute(
+ aStr: CFMutableAttributedStringRef,
+ range: CFRange,
+ attrName: CFStringRef,
+ );
pub fn CFAttributedStringReplaceString(
- astr: CFMutableAttributedStringRef, range: CFRange, replacement: CFStringRef);
-
+ aStr: CFMutableAttributedStringRef,
+ range: CFRange,
+ replacement: CFStringRef,
+ );
+ pub fn CFAttributedStringReplaceAttributedString(
+ aStr: CFMutableAttributedStringRef,
+ range: CFRange,
+ replacement: CFAttributedStringRef,
+ );
pub fn CFAttributedStringSetAttribute(
- astr: CFMutableAttributedStringRef,
+ aStr: CFMutableAttributedStringRef,
range: CFRange,
- attr_name: CFStringRef,
+ attrName: CFStringRef,
value: CFTypeRef,
);
-
+ pub fn CFAttributedStringSetAttributes(
+ aStr: CFMutableAttributedStringRef,
+ range: CFRange,
+ replacement: CFDictionaryRef,
+ clearOtherAttributes: Boolean,
+ );
}
diff --git a/third_party/rust/core-foundation-sys/src/bag.rs b/third_party/rust/core-foundation-sys/src/bag.rs
new file mode 100644
index 0000000000..041caa59c2
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/bag.rs
@@ -0,0 +1,101 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{Boolean, CFAllocatorRef, CFHashCode, CFIndex, CFTypeID};
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFBag(c_void);
+
+pub type CFBagRef = *const __CFBag;
+pub type CFMutableBagRef = *mut __CFBag;
+
+pub type CFBagRetainCallBack =
+ extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
+pub type CFBagReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void);
+pub type CFBagCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef;
+pub type CFBagEqualCallBack =
+ extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
+pub type CFBagHashCallBack = extern "C" fn(value: *const c_void) -> CFHashCode;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFBagCallBacks {
+ pub version: CFIndex,
+ pub retain: CFBagRetainCallBack,
+ pub release: CFBagReleaseCallBack,
+ pub copyDescription: CFBagCopyDescriptionCallBack,
+ pub equal: CFBagEqualCallBack,
+ pub hash: CFBagHashCallBack,
+}
+
+pub type CFBagApplierFunction = extern "C" fn(value: *const c_void, context: *mut c_void);
+
+extern "C" {
+ /*
+ * CFBag.h
+ */
+ /* Predefined Callback Structures */
+ pub static kCFTypeBagCallBacks: CFBagCallBacks;
+ pub static kCFCopyStringBagCallBacks: CFBagCallBacks;
+
+ /* CFBag */
+ /* Creating a Bag */
+ pub fn CFBagCreate(
+ allocator: CFAllocatorRef,
+ values: *const *const c_void,
+ numValues: CFIndex,
+ callBacks: *const CFBagCallBacks,
+ ) -> CFBagRef;
+ pub fn CFBagCreateCopy(allocator: CFAllocatorRef, theBag: CFBagRef) -> CFBagRef;
+
+ /* Examining a Bag */
+ pub fn CFBagContainsValue(theBag: CFBagRef, value: *const c_void) -> Boolean;
+ pub fn CFBagGetCount(theBag: CFBagRef) -> CFIndex;
+ pub fn CFBagGetCountOfValue(theBag: CFBagRef, value: *const c_void) -> CFIndex;
+ pub fn CFBagGetValue(theBag: CFBagRef, value: *const c_void) -> *const c_void;
+ pub fn CFBagGetValueIfPresent(
+ theBag: CFBagRef,
+ candidate: *const c_void,
+ value: *const *const c_void,
+ ) -> Boolean;
+ pub fn CFBagGetValues(theBag: CFBagRef, values: *const *const c_void);
+
+ /* Applying a Function to the Contents of a Bag */
+ pub fn CFBagApplyFunction(
+ theBag: CFBagRef,
+ applier: CFBagApplierFunction,
+ context: *mut c_void,
+ );
+
+ /* Getting the CFBag Type ID */
+ pub fn CFBagGetTypeID() -> CFTypeID;
+
+ /* CFMutableBag */
+ /* Creating a Mutable Bag */
+ pub fn CFBagCreateMutable(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ callBacks: *const CFBagCallBacks,
+ ) -> CFMutableBagRef;
+ pub fn CFBagCreateMutableCopy(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ theBag: CFBagRef,
+ ) -> CFMutableBagRef;
+
+ /* Modifying a Mutable Bag */
+ pub fn CFBagAddValue(theBag: CFMutableBagRef, value: *const c_void);
+ pub fn CFBagRemoveAllValues(theBag: CFMutableBagRef);
+ pub fn CFBagRemoveValue(theBag: CFMutableBagRef, value: *const c_void);
+ pub fn CFBagReplaceValue(theBag: CFMutableBagRef, value: *const c_void);
+ pub fn CFBagSetValue(theBag: CFMutableBagRef, value: *const c_void);
+}
diff --git a/third_party/rust/core-foundation-sys/src/base.rs b/third_party/rust/core-foundation-sys/src/base.rs
index 52a166fdf6..78e06a65f5 100644
--- a/third_party/rust/core-foundation-sys/src/base.rs
+++ b/third_party/rust/core-foundation-sys/src/base.rs
@@ -7,21 +7,33 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use crate::string::CFStringRef;
use std::cmp::Ordering;
-use std::os::raw::{c_uint, c_void, c_int};
-use string::CFStringRef;
+use std::os::raw::{c_int, c_short, c_uchar, c_uint, c_ushort, c_void};
pub type Boolean = u8;
pub type mach_port_t = c_uint;
pub type CFAllocatorRef = *const c_void;
pub type CFNullRef = *const c_void;
pub type CFTypeRef = *const c_void;
+pub type ConstStr255Param = *const c_uchar;
+pub type StringPtr = *mut c_uchar;
+pub type ConstStringPtr = *const c_uchar;
pub type OSStatus = i32;
+pub type UInt8 = c_uchar;
+pub type UInt16 = c_ushort;
+pub type SInt16 = c_short;
pub type SInt32 = c_int;
+pub type UInt32 = c_uint;
pub type CFTypeID = usize;
pub type CFOptionFlags = usize;
pub type CFHashCode = usize;
pub type CFIndex = isize;
+pub type LangCode = SInt16;
+pub type RegionCode = SInt16;
+pub type UTF32Char = c_uint;
+pub type UTF16Char = c_ushort;
+pub type UTF8Char = c_uchar;
#[repr(isize)]
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -31,43 +43,53 @@ pub enum CFComparisonResult {
GreaterThan = 1,
}
-impl Into<Ordering> for CFComparisonResult {
- fn into(self) -> Ordering {
- match self {
+pub type CFComparatorFunction = extern "C" fn(
+ val1: *const c_void,
+ val2: *const c_void,
+ context: *mut c_void,
+) -> CFComparisonResult;
+
+impl From<CFComparisonResult> for Ordering {
+ fn from(val: CFComparisonResult) -> Self {
+ match val {
CFComparisonResult::LessThan => Ordering::Less,
CFComparisonResult::EqualTo => Ordering::Equal,
- CFComparisonResult::GreaterThan => Ordering::Greater
+ CFComparisonResult::GreaterThan => Ordering::Greater,
}
}
}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug, PartialEq)]
pub struct CFRange {
pub location: CFIndex,
- pub length: CFIndex
+ pub length: CFIndex,
}
// for back-compat
impl CFRange {
pub fn init(location: CFIndex, length: CFIndex) -> CFRange {
- CFRange {
- location: location,
- length: length,
- }
+ CFRange { location, length }
}
}
pub type CFAllocatorRetainCallBack = extern "C" fn(info: *mut c_void) -> *mut c_void;
pub type CFAllocatorReleaseCallBack = extern "C" fn(info: *mut c_void);
pub type CFAllocatorCopyDescriptionCallBack = extern "C" fn(info: *mut c_void) -> CFStringRef;
-pub type CFAllocatorAllocateCallBack = extern "C" fn(allocSize: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> *mut c_void;
-pub type CFAllocatorReallocateCallBack = extern "C" fn(ptr: *mut c_void, newsize: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> *mut c_void;
+pub type CFAllocatorAllocateCallBack =
+ extern "C" fn(allocSize: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> *mut c_void;
+pub type CFAllocatorReallocateCallBack = extern "C" fn(
+ ptr: *mut c_void,
+ newsize: CFIndex,
+ hint: CFOptionFlags,
+ info: *mut c_void,
+) -> *mut c_void;
pub type CFAllocatorDeallocateCallBack = extern "C" fn(ptr: *mut c_void, info: *mut c_void);
-pub type CFAllocatorPreferredSizeCallBack = extern "C" fn(size: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> CFIndex;
+pub type CFAllocatorPreferredSizeCallBack =
+ extern "C" fn(size: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> CFIndex;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub struct CFAllocatorContext {
pub version: CFIndex,
pub info: *mut c_void,
@@ -77,7 +99,7 @@ pub struct CFAllocatorContext {
pub allocate: Option<CFAllocatorAllocateCallBack>,
pub reallocate: Option<CFAllocatorReallocateCallBack>,
pub deallocate: Option<CFAllocatorDeallocateCallBack>,
- pub preferredSize: Option<CFAllocatorPreferredSizeCallBack>
+ pub preferredSize: Option<CFAllocatorPreferredSizeCallBack>,
}
/// Trait for all types which are Core Foundation reference types.
@@ -110,7 +132,7 @@ impl<T> TCFTypeRef for *mut T {
/// Constant used by some functions to indicate failed searches.
pub static kCFNotFound: CFIndex = -1;
-extern {
+extern "C" {
/*
* CFBase.h
*/
@@ -124,11 +146,27 @@ extern {
pub static kCFAllocatorNull: CFAllocatorRef;
pub static kCFAllocatorUseContext: CFAllocatorRef;
- pub fn CFAllocatorCreate(allocator: CFAllocatorRef, context: *mut CFAllocatorContext) -> CFAllocatorRef;
- pub fn CFAllocatorAllocate(allocator: CFAllocatorRef, size: CFIndex, hint: CFOptionFlags) -> *mut c_void;
+ pub fn CFAllocatorCreate(
+ allocator: CFAllocatorRef,
+ context: *mut CFAllocatorContext,
+ ) -> CFAllocatorRef;
+ pub fn CFAllocatorAllocate(
+ allocator: CFAllocatorRef,
+ size: CFIndex,
+ hint: CFOptionFlags,
+ ) -> *mut c_void;
pub fn CFAllocatorDeallocate(allocator: CFAllocatorRef, ptr: *mut c_void);
- pub fn CFAllocatorGetPreferredSizeForSize(allocator: CFAllocatorRef, size: CFIndex, hint: CFOptionFlags) -> CFIndex;
- pub fn CFAllocatorReallocate(allocator: CFAllocatorRef, ptr: *mut c_void, newsize: CFIndex, hint: CFOptionFlags) -> *mut c_void;
+ pub fn CFAllocatorGetPreferredSizeForSize(
+ allocator: CFAllocatorRef,
+ size: CFIndex,
+ hint: CFOptionFlags,
+ ) -> CFIndex;
+ pub fn CFAllocatorReallocate(
+ allocator: CFAllocatorRef,
+ ptr: *mut c_void,
+ newsize: CFIndex,
+ hint: CFOptionFlags,
+ ) -> *mut c_void;
pub fn CFAllocatorGetDefault() -> CFAllocatorRef;
pub fn CFAllocatorSetDefault(allocator: CFAllocatorRef);
pub fn CFAllocatorGetContext(allocator: CFAllocatorRef, context: *mut CFAllocatorContext);
@@ -138,10 +176,12 @@ extern {
pub static kCFNull: CFNullRef;
+ pub fn CFNullGetTypeID() -> CFTypeID;
+
/* CFType Reference */
- //fn CFCopyTypeIDDescription
- //fn CFGetAllocator
+ pub fn CFCopyTypeIDDescription(type_id: CFTypeID) -> CFStringRef;
+ pub fn CFGetAllocator(cf: CFTypeRef) -> CFAllocatorRef;
pub fn CFCopyDescription(cf: CFTypeRef) -> CFStringRef;
pub fn CFEqual(cf1: CFTypeRef, cf2: CFTypeRef) -> Boolean;
pub fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex;
diff --git a/third_party/rust/core-foundation-sys/src/binary_heap.rs b/third_party/rust/core-foundation-sys/src/binary_heap.rs
new file mode 100644
index 0000000000..8bcaa8e26e
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/binary_heap.rs
@@ -0,0 +1,83 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{Boolean, CFAllocatorRef, CFComparisonResult, CFIndex, CFTypeID};
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFBinaryHeap(c_void);
+
+pub type CFBinaryHeapRef = *mut __CFBinaryHeap;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFBinaryHeapCompareContext {
+ pub version: CFIndex,
+ pub info: *mut c_void,
+ pub retain: extern "C" fn(info: *const c_void) -> *const c_void,
+ pub release: extern "C" fn(info: *const c_void),
+ pub copyDescription: extern "C" fn(info: *const c_void) -> CFStringRef,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFBinaryHeapCallBacks {
+ pub version: CFIndex,
+ pub retain: extern "C" fn(allocator: CFAllocatorRef, ptr: *const c_void) -> *const c_void,
+ pub release: extern "C" fn(allocator: CFAllocatorRef, ptr: *const c_void),
+ pub copyDescription: extern "C" fn(ptr: *const c_void) -> CFStringRef,
+ pub compare: extern "C" fn(
+ ptr1: *const c_void,
+ ptr2: *const c_void,
+ context: *mut c_void,
+ ) -> CFComparisonResult,
+}
+
+pub type CFBinaryHeapApplierFunction = extern "C" fn(val: *const c_void, context: *const c_void);
+
+extern "C" {
+ /*
+ * CFBinaryHeap.h
+ */
+ /* Predefined Callback Structures */
+ pub static kCFStringBinaryHeapCallBacks: CFBinaryHeapCallBacks;
+
+ /* CFBinaryHeap Miscellaneous Functions */
+ pub fn CFBinaryHeapAddValue(heap: CFBinaryHeapRef, value: *const c_void);
+ pub fn CFBinaryHeapApplyFunction(
+ heap: CFBinaryHeapRef,
+ applier: CFBinaryHeapApplierFunction,
+ context: *mut c_void,
+ );
+ pub fn CFBinaryHeapContainsValue(heap: CFBinaryHeapRef, value: *const c_void) -> Boolean;
+ pub fn CFBinaryHeapCreate(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ callBacks: *const CFBinaryHeapCallBacks,
+ compareContext: *const CFBinaryHeapCompareContext,
+ ) -> CFBinaryHeapRef;
+ pub fn CFBinaryHeapCreateCopy(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ heap: CFBinaryHeapRef,
+ ) -> CFBinaryHeapRef;
+ pub fn CFBinaryHeapGetCount(heap: CFBinaryHeapRef) -> CFIndex;
+ pub fn CFBinaryHeapGetCountOfValue(heap: CFBinaryHeapRef, value: *const c_void) -> CFIndex;
+ pub fn CFBinaryHeapGetMinimum(heap: CFBinaryHeapRef) -> *const c_void;
+ pub fn CFBinaryHeapGetMinimumIfPresent(
+ heap: CFBinaryHeapRef,
+ value: *const *const c_void,
+ ) -> Boolean;
+ pub fn CFBinaryHeapGetTypeID() -> CFTypeID;
+ pub fn CFBinaryHeapGetValues(heap: CFBinaryHeapRef, values: *const *const c_void);
+ pub fn CFBinaryHeapRemoveAllValues(heap: CFBinaryHeapRef);
+ pub fn CFBinaryHeapRemoveMinimumValue(heap: CFBinaryHeapRef);
+}
diff --git a/third_party/rust/core-foundation-sys/src/bit_vector.rs b/third_party/rust/core-foundation-sys/src/bit_vector.rs
new file mode 100644
index 0000000000..f270c3d1d3
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/bit_vector.rs
@@ -0,0 +1,74 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFRange, CFTypeID, UInt32, UInt8};
+
+#[repr(C)]
+pub struct __CFBitVector(c_void);
+
+pub type CFBitVectorRef = *const __CFBitVector;
+pub type CFMutableBitVectorRef = *mut __CFBitVector;
+pub type CFBit = UInt32;
+
+extern "C" {
+ /*
+ * CFBitVector.h
+ */
+
+ /* CFBitVector */
+ /* Creating a Bit Vector */
+ pub fn CFBitVectorCreate(
+ allocator: CFAllocatorRef,
+ bytes: *const UInt8,
+ numBits: CFIndex,
+ ) -> CFBitVectorRef;
+ pub fn CFBitVectorCreateCopy(allocator: CFAllocatorRef, bv: CFBitVectorRef) -> CFBitVectorRef;
+
+ /* Getting Information About a Bit Vector */
+ pub fn CFBitVectorContainsBit(bv: CFBitVectorRef, range: CFRange, value: CFBit) -> Boolean;
+ pub fn CFBitVectorGetBitAtIndex(bv: CFBitVectorRef, idx: CFIndex) -> CFBit;
+ pub fn CFBitVectorGetBits(bv: CFBitVectorRef, range: CFRange, bytes: *mut UInt8);
+ pub fn CFBitVectorGetCount(bv: CFBitVectorRef) -> CFIndex;
+ pub fn CFBitVectorGetCountOfBit(bv: CFBitVectorRef, range: CFRange, value: CFBit) -> CFIndex;
+ pub fn CFBitVectorGetFirstIndexOfBit(
+ bv: CFBitVectorRef,
+ range: CFRange,
+ value: CFBit,
+ ) -> CFIndex;
+ pub fn CFBitVectorGetLastIndexOfBit(
+ bv: CFBitVectorRef,
+ range: CFRange,
+ value: CFBit,
+ ) -> CFIndex;
+
+ /* Getting the CFBitVector Type ID */
+ pub fn CFBitVectorGetTypeID() -> CFTypeID;
+
+ /* CFMutableBitVector */
+ /* Creating a CFMutableBitVector Object */
+ pub fn CFBitVectorCreateMutable(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ ) -> CFMutableBitVectorRef;
+ pub fn CFBitVectorCreateMutableCopy(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ bv: CFBitVectorRef,
+ ) -> CFMutableBitVectorRef;
+
+ /* Modifying a Bit Vector */
+ pub fn CFBitVectorFlipBitAtIndex(bv: CFMutableBitVectorRef, idx: CFIndex);
+ pub fn CFBitVectorFlipBits(bv: CFMutableBitVectorRef, range: CFRange);
+ pub fn CFBitVectorSetAllBits(bv: CFMutableBitVectorRef, value: CFBit);
+ pub fn CFBitVectorSetBitAtIndex(bv: CFMutableBitVectorRef, idx: CFIndex, value: CFBit);
+ pub fn CFBitVectorSetBits(bv: CFMutableBitVectorRef, range: CFRange, value: CFBit);
+ pub fn CFBitVectorSetCount(bv: CFMutableBitVectorRef, count: CFIndex);
+}
diff --git a/third_party/rust/core-foundation-sys/src/bundle.rs b/third_party/rust/core-foundation-sys/src/bundle.rs
index 29f8e1261f..60aaa4c777 100644
--- a/third_party/rust/core-foundation-sys/src/bundle.rs
+++ b/third_party/rust/core-foundation-sys/src/bundle.rs
@@ -9,31 +9,226 @@
use std::os::raw::c_void;
-use base::{CFTypeID, CFAllocatorRef};
-use url::CFURLRef;
-use dictionary::CFDictionaryRef;
-use string::CFStringRef;
+use crate::array::CFArrayRef;
+#[cfg(target_os = "macos")]
+use crate::base::SInt32;
+use crate::base::{Boolean, CFAllocatorRef, CFTypeID, CFTypeRef, UInt32};
+use crate::dictionary::CFDictionaryRef;
+use crate::error::CFErrorRef;
+use crate::string::CFStringRef;
+use crate::url::CFURLRef;
+use std::os::raw::{c_int, c_uint};
#[repr(C)]
pub struct __CFBundle(c_void);
pub type CFBundleRef = *mut __CFBundle;
+pub type CFPlugInRef = *mut __CFBundle;
+pub type CFBundleRefNum = c_int;
-extern {
+#[allow(unused)]
+#[inline(always)]
+pub unsafe fn CFCopyLocalizedString(key: CFStringRef, comment: CFStringRef) -> CFStringRef {
+ CFBundleCopyLocalizedString(CFBundleGetMainBundle(), key, key, std::ptr::null())
+}
+#[allow(unused)]
+#[inline(always)]
+pub unsafe fn CFCopyLocalizedStringFromTable(
+ key: CFStringRef,
+ tbl: CFStringRef,
+ comment: CFStringRef,
+) -> CFStringRef {
+ CFBundleCopyLocalizedString(CFBundleGetMainBundle(), key, key, tbl)
+}
+#[allow(unused)]
+#[inline(always)]
+pub unsafe fn CFCopyLocalizedStringFromTableInBundle(
+ key: CFStringRef,
+ tbl: CFStringRef,
+ bundle: CFBundleRef,
+ comment: CFStringRef,
+) -> CFStringRef {
+ CFBundleCopyLocalizedString(bundle, key, key, tbl)
+}
+#[allow(unused)]
+#[inline(always)]
+pub unsafe fn CFCopyLocalizedStringWithDefaultValue(
+ key: CFStringRef,
+ tbl: CFStringRef,
+ bundle: CFBundleRef,
+ value: CFStringRef,
+ comment: CFStringRef,
+) -> CFStringRef {
+ CFBundleCopyLocalizedString(bundle, key, value, tbl)
+}
+
+pub static kCFBundleExecutableArchitectureI386: c_uint = 0x00000007;
+pub static kCFBundleExecutableArchitecturePPC: c_uint = 0x00000012;
+pub static kCFBundleExecutableArchitectureX86_64: c_uint = 0x01000007;
+pub static kCFBundleExecutableArchitecturePPC64: c_uint = 0x01000012;
+//pub static kCFBundleExecutableArchitectureARM64: c_uint = 0x0100000c; //macos(11.0)+
+
+extern "C" {
/*
* CFBundle.h
*/
- pub fn CFBundleCreate(allocator: CFAllocatorRef, bundleURL: CFURLRef) -> CFBundleRef;
+ /* Information Property List Keys */
+ pub static kCFBundleInfoDictionaryVersionKey: CFStringRef;
+ pub static kCFBundleExecutableKey: CFStringRef;
+ pub static kCFBundleIdentifierKey: CFStringRef;
+ pub static kCFBundleVersionKey: CFStringRef;
+ pub static kCFBundleDevelopmentRegionKey: CFStringRef;
+ pub static kCFBundleNameKey: CFStringRef;
+ pub static kCFBundleLocalizationsKey: CFStringRef;
+
+ /* Creating and Accessing Bundles */
+ pub fn CFBundleCreate(allocator: CFAllocatorRef, bundleURL: CFURLRef) -> CFBundleRef;
+ pub fn CFBundleCreateBundlesFromDirectory(
+ allocator: CFAllocatorRef,
+ directoryURL: CFURLRef,
+ bundleType: CFStringRef,
+ ) -> CFArrayRef;
+ pub fn CFBundleGetAllBundles() -> CFArrayRef;
pub fn CFBundleGetBundleWithIdentifier(bundleID: CFStringRef) -> CFBundleRef;
- pub fn CFBundleGetFunctionPointerForName(bundle: CFBundleRef, function_name: CFStringRef) -> *const c_void;
pub fn CFBundleGetMainBundle() -> CFBundleRef;
- pub fn CFBundleGetInfoDictionary(bundle: CFBundleRef) -> CFDictionaryRef;
- pub fn CFBundleGetTypeID() -> CFTypeID;
+ /* Loading and Unloading a Bundle */
+ pub fn CFBundleIsExecutableLoaded(bundle: CFBundleRef) -> Boolean;
+ pub fn CFBundlePreflightExecutable(bundle: CFBundleRef, error: *mut CFErrorRef) -> Boolean;
+ pub fn CFBundleLoadExecutable(bundle: CFBundleRef) -> Boolean;
+ pub fn CFBundleLoadExecutableAndReturnError(
+ bundle: CFBundleRef,
+ error: *mut CFErrorRef,
+ ) -> Boolean;
+ pub fn CFBundleUnloadExecutable(bundle: CFBundleRef);
+
+ /* Finding Locations in a Bundle */
+ pub fn CFBundleCopyAuxiliaryExecutableURL(
+ bundle: CFBundleRef,
+ executableName: CFStringRef,
+ ) -> CFURLRef;
+ pub fn CFBundleCopyBuiltInPlugInsURL(bundle: CFBundleRef) -> CFURLRef;
pub fn CFBundleCopyExecutableURL(bundle: CFBundleRef) -> CFURLRef;
pub fn CFBundleCopyPrivateFrameworksURL(bundle: CFBundleRef) -> CFURLRef;
+ pub fn CFBundleCopyResourcesDirectoryURL(bundle: CFBundleRef) -> CFURLRef;
+ pub fn CFBundleCopySharedFrameworksURL(bundle: CFBundleRef) -> CFURLRef;
pub fn CFBundleCopySharedSupportURL(bundle: CFBundleRef) -> CFURLRef;
+ pub fn CFBundleCopySupportFilesDirectoryURL(bundle: CFBundleRef) -> CFURLRef;
+
+ /* Locating Bundle Resources */
+ #[cfg(target_os = "macos")]
+ pub fn CFBundleCloseBundleResourceMap(bundle: CFBundleRef, refNum: CFBundleRefNum); // DEPRECATED macosx(10.0, 10.15)
+ pub fn CFBundleCopyResourceURL(
+ bundle: CFBundleRef,
+ resourceName: CFStringRef,
+ resourceType: CFStringRef,
+ subDirName: CFStringRef,
+ ) -> CFURLRef;
+ pub fn CFBundleCopyResourceURLInDirectory(
+ bundleURL: CFURLRef,
+ resourceName: CFStringRef,
+ resourceType: CFStringRef,
+ subDirName: CFStringRef,
+ ) -> CFURLRef;
+ pub fn CFBundleCopyResourceURLsOfType(
+ bundle: CFBundleRef,
+ resourceType: CFStringRef,
+ subDirName: CFStringRef,
+ ) -> CFArrayRef;
+ pub fn CFBundleCopyResourceURLsOfTypeInDirectory(
+ bundleURL: CFURLRef,
+ resourceType: CFStringRef,
+ subDirName: CFStringRef,
+ ) -> CFArrayRef;
+ pub fn CFBundleCopyResourceURLForLocalization(
+ bundle: CFBundleRef,
+ resourceName: CFStringRef,
+ resourceType: CFStringRef,
+ subDirName: CFStringRef,
+ localizationName: CFStringRef,
+ ) -> CFURLRef;
+ pub fn CFBundleCopyResourceURLsOfTypeForLocalization(
+ bundle: CFBundleRef,
+ resourceType: CFStringRef,
+ subDirName: CFStringRef,
+ localizationName: CFStringRef,
+ ) -> CFArrayRef;
+ #[cfg(target_os = "macos")]
+ pub fn CFBundleOpenBundleResourceFiles(
+ bundle: CFBundleRef,
+ refNum: *mut CFBundleRefNum,
+ localizedRefNum: *mut CFBundleRefNum,
+ ) -> SInt32; // DEPRECATED macosx(10.0, 10.15)
+ #[cfg(target_os = "macos")]
+ pub fn CFBundleOpenBundleResourceMap(bundle: CFBundleRef) -> CFBundleRefNum; // DEPRECATED macosx(10.0, 10.15)
+
+ /* Managing Localizations */
+ pub fn CFBundleCopyBundleLocalizations(bundle: CFBundleRef) -> CFArrayRef;
+ pub fn CFBundleCopyLocalizedString(
+ bundle: CFBundleRef,
+ key: CFStringRef,
+ value: CFStringRef,
+ tableName: CFStringRef,
+ ) -> CFStringRef;
+ pub fn CFBundleCopyLocalizationsForPreferences(
+ locArray: CFArrayRef,
+ prefArray: CFArrayRef,
+ ) -> CFArrayRef;
+ pub fn CFBundleCopyLocalizationsForURL(url: CFURLRef) -> CFArrayRef;
+ pub fn CFBundleCopyPreferredLocalizationsFromArray(locArray: CFArrayRef) -> CFArrayRef;
+
+ /* Managing Executable Code */
+ pub fn CFBundleGetDataPointerForName(
+ bundle: CFBundleRef,
+ symbolName: CFStringRef,
+ ) -> *mut c_void;
+ pub fn CFBundleGetDataPointersForNames(
+ bundle: CFBundleRef,
+ symbolNames: CFArrayRef,
+ stbl: *mut [c_void],
+ );
+ pub fn CFBundleGetFunctionPointerForName(
+ bundle: CFBundleRef,
+ function_name: CFStringRef,
+ ) -> *const c_void;
+ pub fn CFBundleGetFunctionPointersForNames(
+ bundle: CFBundleRef,
+ functionNames: CFArrayRef,
+ ftbl: *mut [c_void],
+ );
+ pub fn CFBundleGetPlugIn(bundle: CFBundleRef) -> CFPlugInRef;
+
+ /* Getting Bundle Properties */
pub fn CFBundleCopyBundleURL(bundle: CFBundleRef) -> CFURLRef;
- pub fn CFBundleCopyResourcesDirectoryURL(bundle: CFBundleRef) -> CFURLRef;
+ pub fn CFBundleGetDevelopmentRegion(bundle: CFBundleRef) -> CFStringRef;
+ pub fn CFBundleGetIdentifier(bundle: CFBundleRef) -> CFStringRef;
+ pub fn CFBundleGetInfoDictionary(bundle: CFBundleRef) -> CFDictionaryRef;
+ pub fn CFBundleGetLocalInfoDictionary(bundle: CFBundleRef) -> CFDictionaryRef;
+ pub fn CFBundleGetValueForInfoDictionaryKey(bundle: CFBundleRef, key: CFStringRef)
+ -> CFTypeRef;
+ pub fn CFBundleCopyInfoDictionaryInDirectory(bundleURL: CFURLRef) -> CFDictionaryRef;
+ pub fn CFBundleCopyInfoDictionaryForURL(url: CFURLRef) -> CFDictionaryRef;
+ pub fn CFBundleGetPackageInfo(
+ bundle: CFBundleRef,
+ packageType: *mut UInt32,
+ packageCreator: *mut UInt32,
+ );
+ pub fn CFBundleGetPackageInfoInDirectory(
+ url: CFURLRef,
+ packageType: *mut UInt32,
+ packageCreator: *mut UInt32,
+ ) -> Boolean;
+ pub fn CFBundleCopyExecutableArchitectures(bundle: CFBundleRef) -> CFArrayRef;
+ pub fn CFBundleCopyExecutableArchitecturesForURL(url: CFURLRef) -> CFArrayRef;
+ pub fn CFBundleGetVersionNumber(bundle: CFBundleRef) -> UInt32;
+
+ /* macos(11.0)+
+ pub fn CFBundleIsExecutableLoadable(bundle: CFBundleRef) -> Boolean;
+ pub fn CFBundleIsExecutableLoadableForURL(url: CFURLRef) -> Boolean;
+ pub fn CFBundleIsArchitectureLoadable(arch: cpu_type_t) -> Boolean;
+ */
+
+ /* Getting the CFBundle Type ID */
+ pub fn CFBundleGetTypeID() -> CFTypeID;
}
diff --git a/third_party/rust/core-foundation-sys/src/calendar.rs b/third_party/rust/core-foundation-sys/src/calendar.rs
new file mode 100644
index 0000000000..54c2a00cd2
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/calendar.rs
@@ -0,0 +1,128 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::{c_char, c_void};
+
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFRange, CFTypeID};
+use crate::date::{CFAbsoluteTime, CFTimeInterval};
+use crate::locale::{CFCalendarIdentifier, CFLocaleRef};
+use crate::timezone::CFTimeZoneRef;
+
+#[repr(C)]
+pub struct __CFCalendar(c_void);
+pub type CFCalendarRef = *mut __CFCalendar;
+
+pub type CFCalendarUnit = CFOptionFlags;
+pub const kCFCalendarUnitEra: CFCalendarUnit = 1 << 1;
+pub const kCFCalendarUnitYear: CFCalendarUnit = 1 << 2;
+pub const kCFCalendarUnitMonth: CFCalendarUnit = 1 << 3;
+pub const kCFCalendarUnitDay: CFCalendarUnit = 1 << 4;
+pub const kCFCalendarUnitHour: CFCalendarUnit = 1 << 5;
+pub const kCFCalendarUnitMinute: CFCalendarUnit = 1 << 6;
+pub const kCFCalendarUnitSecond: CFCalendarUnit = 1 << 7;
+pub const kCFCalendarUnitWeek: CFCalendarUnit = 1 << 8; // deprecated since macos 10.10
+pub const kCFCalendarUnitWeekday: CFCalendarUnit = 1 << 9;
+pub const kCFCalendarUnitWeekdayOrdinal: CFCalendarUnit = 1 << 10;
+pub const kCFCalendarUnitQuarter: CFCalendarUnit = 1 << 11;
+pub const kCFCalendarUnitWeekOfMonth: CFCalendarUnit = 1 << 12;
+pub const kCFCalendarUnitWeekOfYear: CFCalendarUnit = 1 << 13;
+pub const kCFCalendarUnitYearForWeekOfYear: CFCalendarUnit = 1 << 14;
+
+pub const kCFCalendarComponentsWrap: CFOptionFlags = 1 << 0;
+
+extern "C" {
+ /*
+ * CFCalendar.h
+ */
+
+ /* Creating a Calendar */
+ pub fn CFCalendarCopyCurrent() -> CFCalendarRef;
+ pub fn CFCalendarCreateWithIdentifier(
+ allocator: CFAllocatorRef,
+ identifier: CFCalendarIdentifier,
+ ) -> CFCalendarRef;
+
+ /* Calendrical Calculations */
+ pub fn CFCalendarAddComponents(
+ identifier: CFCalendarIdentifier,
+ /* inout */ at: *mut CFAbsoluteTime,
+ options: CFOptionFlags,
+ componentDesc: *const char,
+ ...
+ ) -> Boolean;
+ pub fn CFCalendarComposeAbsoluteTime(
+ identifier: CFCalendarIdentifier,
+ /* out */ at: *mut CFAbsoluteTime,
+ componentDesc: *const c_char,
+ ...
+ ) -> Boolean;
+ pub fn CFCalendarDecomposeAbsoluteTime(
+ identifier: CFCalendarIdentifier,
+ at: CFAbsoluteTime,
+ componentDesc: *const c_char,
+ ...
+ ) -> Boolean;
+ pub fn CFCalendarGetComponentDifference(
+ identifier: CFCalendarIdentifier,
+ startingAT: CFAbsoluteTime,
+ resultAT: CFAbsoluteTime,
+ options: CFOptionFlags,
+ componentDesc: *const c_char,
+ ...
+ ) -> Boolean;
+
+ /* Getting Ranges of Units */
+ pub fn CFCalendarGetRangeOfUnit(
+ identifier: CFCalendarIdentifier,
+ smallerUnit: CFCalendarUnit,
+ biggerUnit: CFCalendarUnit,
+ at: CFAbsoluteTime,
+ ) -> CFRange;
+ pub fn CFCalendarGetOrdinalityOfUnit(
+ identifier: CFCalendarIdentifier,
+ smallerUnit: CFCalendarUnit,
+ biggerUnit: CFCalendarUnit,
+ at: CFAbsoluteTime,
+ ) -> CFIndex;
+ pub fn CFCalendarGetTimeRangeOfUnit(
+ identifier: CFCalendarIdentifier,
+ unit: CFCalendarUnit,
+ at: CFAbsoluteTime,
+ startp: *mut CFAbsoluteTime,
+ tip: *mut CFTimeInterval,
+ ) -> Boolean;
+ pub fn CFCalendarGetMaximumRangeOfUnit(
+ identifier: CFCalendarIdentifier,
+ unit: CFCalendarUnit,
+ ) -> CFRange;
+ pub fn CFCalendarGetMinimumRangeOfUnit(
+ identifier: CFCalendarIdentifier,
+ unit: CFCalendarUnit,
+ ) -> CFRange;
+
+ /* Getting and Setting the Time Zone */
+ pub fn CFCalendarCopyTimeZone(identifier: CFCalendarIdentifier) -> CFTimeZoneRef;
+ pub fn CFCalendarSetTimeZone(identifier: CFCalendarIdentifier, tz: CFTimeZoneRef);
+
+ /* Getting the Identifier */
+ pub fn CFCalendarGetIdentifier(identifier: CFCalendarIdentifier) -> CFCalendarIdentifier;
+
+ /* Getting and Setting the Locale */
+ pub fn CFCalendarCopyLocale(identifier: CFCalendarIdentifier) -> CFLocaleRef;
+ pub fn CFCalendarSetLocale(identifier: CFCalendarIdentifier, locale: CFLocaleRef);
+
+ /* Getting and Setting Day Information */
+ pub fn CFCalendarGetFirstWeekday(identifier: CFCalendarIdentifier) -> CFIndex;
+ pub fn CFCalendarSetFirstWeekday(identifier: CFCalendarIdentifier, wkdy: CFIndex);
+ pub fn CFCalendarGetMinimumDaysInFirstWeek(identifier: CFCalendarIdentifier) -> CFIndex;
+ pub fn CFCalendarSetMinimumDaysInFirstWeek(identifier: CFCalendarIdentifier, mwd: CFIndex);
+
+ /* Getting the Type ID */
+ pub fn CFCalendarGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/characterset.rs b/third_party/rust/core-foundation-sys/src/characterset.rs
index 6b347a5cdd..8d75679af9 100644
--- a/third_party/rust/core-foundation-sys/src/characterset.rs
+++ b/third_party/rust/core-foundation-sys/src/characterset.rs
@@ -7,10 +7,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFRange, CFTypeID, UTF32Char};
+use crate::data::CFDataRef;
+use crate::string::{CFStringRef, UniChar};
use std::os::raw::c_void;
-use base::{Boolean, CFAllocatorRef, CFIndex, CFRange, CFTypeID};
-use data::CFDataRef;
-use string::{CFStringRef, UniChar};
pub type CFCharacterSetPredefinedSet = CFIndex;
@@ -35,24 +35,90 @@ pub static kCFCharacterSetNewline: CFCharacterSetPredefinedSet = 15;
pub struct __CFCharacterSet(c_void);
pub type CFCharacterSetRef = *const __CFCharacterSet;
-pub type CFMutableCharacterSetRef = *const __CFCharacterSet;
+pub type CFMutableCharacterSetRef = *mut __CFCharacterSet;
-extern {
+extern "C" {
+ /*
+ * CFCharacterSet.h
+ */
+
+ /* CFCharacterSet */
+ /* Creating Character Sets */
+ pub fn CFCharacterSetCreateCopy(
+ alloc: CFAllocatorRef,
+ theSet: CFCharacterSetRef,
+ ) -> CFCharacterSetRef;
+ pub fn CFCharacterSetCreateInvertedSet(
+ alloc: CFAllocatorRef,
+ theSet: CFCharacterSetRef,
+ ) -> CFCharacterSetRef;
+ pub fn CFCharacterSetCreateWithCharactersInRange(
+ alloc: CFAllocatorRef,
+ theRange: CFRange,
+ ) -> CFCharacterSetRef;
+ pub fn CFCharacterSetCreateWithCharactersInString(
+ alloc: CFAllocatorRef,
+ theString: CFStringRef,
+ ) -> CFCharacterSetRef;
+ pub fn CFCharacterSetCreateWithBitmapRepresentation(
+ alloc: CFAllocatorRef,
+ theData: CFDataRef,
+ ) -> CFCharacterSetRef;
+
+ /* Getting Predefined Character Sets */
+ pub fn CFCharacterSetGetPredefined(
+ theSetIdentifier: CFCharacterSetPredefinedSet,
+ ) -> CFCharacterSetRef;
+
+ /* Querying Character Sets */
+ pub fn CFCharacterSetCreateBitmapRepresentation(
+ alloc: CFAllocatorRef,
+ theSet: CFCharacterSetRef,
+ ) -> CFDataRef;
+ pub fn CFCharacterSetHasMemberInPlane(theSet: CFCharacterSetRef, thePlane: CFIndex) -> Boolean;
+ pub fn CFCharacterSetIsCharacterMember(theSet: CFCharacterSetRef, theChar: UniChar) -> Boolean;
+ pub fn CFCharacterSetIsLongCharacterMember(
+ theSet: CFCharacterSetRef,
+ theChar: UTF32Char,
+ ) -> Boolean;
+ pub fn CFCharacterSetIsSupersetOfSet(
+ theSet: CFCharacterSetRef,
+ theOtherset: CFCharacterSetRef,
+ ) -> Boolean;
+
+ /* Getting the Character Set Type Identifier */
pub fn CFCharacterSetGetTypeID() -> CFTypeID;
- pub fn CFCharacterSetGetPredefined(theSetIdentifier: CFCharacterSetPredefinedSet) -> CFCharacterSetRef;
- pub fn CFCharacterSetCreateWithCharactersInRange(alloc: CFAllocatorRef, theRange: CFRange) -> CFCharacterSetRef;
- pub fn CFCharacterSetCreateWithCharactersInString(alloc: CFAllocatorRef, theString: CFStringRef) -> CFCharacterSetRef;
- pub fn CFCharacterSetCreateWithBitmapRepresentation(alloc: CFAllocatorRef, theData: CFDataRef) -> CFCharacterSetRef;
+
+ /* CFMutableCharacterSet */
+ /* Creating a Mutable Character Set */
pub fn CFCharacterSetCreateMutable(alloc: CFAllocatorRef) -> CFMutableCharacterSetRef;
- pub fn CFCharacterSetCreateCopy(alloc: CFAllocatorRef, theSet: CFCharacterSetRef) -> CFCharacterSetRef;
- pub fn CFCharacterSetCreateMutableCopy(alloc: CFAllocatorRef, theSet: CFCharacterSetRef) -> CFMutableCharacterSetRef;
- pub fn CFCharacterSetIsCharacterMember(theSet: CFCharacterSetRef, theChar: UniChar) -> Boolean;
- pub fn CFCharacterSetCreateBitmapRepresentation(alloc: CFAllocatorRef, theSet: CFCharacterSetRef) -> CFDataRef;
+ pub fn CFCharacterSetCreateMutableCopy(
+ alloc: CFAllocatorRef,
+ theSet: CFCharacterSetRef,
+ ) -> CFMutableCharacterSetRef;
+
+ /* Adding Characters */
pub fn CFCharacterSetAddCharactersInRange(theSet: CFMutableCharacterSetRef, theRange: CFRange);
- pub fn CFCharacterSetRemoveCharactersInRange(theSet: CFMutableCharacterSetRef, theRange: CFRange);
- pub fn CFCharacterSetAddCharactersInString(theSet: CFMutableCharacterSetRef, theString: CFStringRef);
- pub fn CFCharacterSetRemoveCharactersInString(theSet: CFMutableCharacterSetRef, theString: CFStringRef);
- pub fn CFCharacterSetUnion(theSet: CFMutableCharacterSetRef, theOtherSet: CFCharacterSetRef);
- pub fn CFCharacterSetIntersect(theSet: CFMutableCharacterSetRef, theOtherSet: CFCharacterSetRef);
+ pub fn CFCharacterSetAddCharactersInString(
+ theSet: CFMutableCharacterSetRef,
+ theString: CFStringRef,
+ );
+
+ /* Removing Characters */
+ pub fn CFCharacterSetRemoveCharactersInRange(
+ theSet: CFMutableCharacterSetRef,
+ theRange: CFRange,
+ );
+ pub fn CFCharacterSetRemoveCharactersInString(
+ theSet: CFMutableCharacterSetRef,
+ theString: CFStringRef,
+ );
+
+ /* Logical Operations */
+ pub fn CFCharacterSetIntersect(
+ theSet: CFMutableCharacterSetRef,
+ theOtherSet: CFCharacterSetRef,
+ );
pub fn CFCharacterSetInvert(theSet: CFMutableCharacterSetRef);
+ pub fn CFCharacterSetUnion(theSet: CFMutableCharacterSetRef, theOtherSet: CFCharacterSetRef);
}
diff --git a/third_party/rust/core-foundation-sys/src/data.rs b/third_party/rust/core-foundation-sys/src/data.rs
index e5ed0dc9f0..ba87d0c5d3 100644
--- a/third_party/rust/core-foundation-sys/src/data.rs
+++ b/third_party/rust/core-foundation-sys/src/data.rs
@@ -7,32 +7,71 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use crate::base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFRange, CFTypeID};
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFTypeID, CFIndex, CFRange};
-
#[repr(C)]
pub struct __CFData(c_void);
pub type CFDataRef = *const __CFData;
+pub type CFMutableDataRef = *mut __CFData;
+pub type CFDataSearchFlags = CFOptionFlags;
+
+// typedef CF_OPTIONS(CFOptionFlags, CFDataSearchFlags)
+pub const kCFDataSearchBackwards: CFDataSearchFlags = 1usize << 0;
+pub const kCFDataSearchAnchored: CFDataSearchFlags = 1usize << 1;
-extern {
+extern "C" {
/*
* CFData.h
*/
- pub fn CFDataCreate(allocator: CFAllocatorRef,
- bytes: *const u8, length: CFIndex) -> CFDataRef;
- //fn CFDataFind
- pub fn CFDataGetBytePtr(theData: CFDataRef) -> *const u8;
- pub fn CFDataGetBytes(theData: CFDataRef, range: CFRange, buffer: *mut u8);
- pub fn CFDataGetLength(theData: CFDataRef) -> CFIndex;
+ /* CFData */
+ /* Creating a CFData Object */
+ pub fn CFDataCreate(allocator: CFAllocatorRef, bytes: *const u8, length: CFIndex) -> CFDataRef;
+ pub fn CFDataCreateCopy(allocator: CFAllocatorRef, theData: CFDataRef) -> CFDataRef;
pub fn CFDataCreateWithBytesNoCopy(
allocator: CFAllocatorRef,
bytes: *const u8,
length: CFIndex,
- allocator: CFAllocatorRef,
+ bytesDeallocator: CFAllocatorRef,
) -> CFDataRef;
+ /* Examining a CFData Object */
+ pub fn CFDataGetBytePtr(theData: CFDataRef) -> *const u8;
+ pub fn CFDataGetBytes(theData: CFDataRef, range: CFRange, buffer: *mut u8);
+ pub fn CFDataGetLength(theData: CFDataRef) -> CFIndex;
+ pub fn CFDataFind(
+ theData: CFDataRef,
+ dataToFind: CFDataRef,
+ searchRange: CFRange,
+ compareOptions: CFDataSearchFlags,
+ ) -> CFRange;
+
+ /* Getting the CFData Type ID */
pub fn CFDataGetTypeID() -> CFTypeID;
+
+ /* CFMutableData */
+ /* Creating a Mutable Data Object */
+ pub fn CFDataCreateMutable(allocator: CFAllocatorRef, capacity: CFIndex) -> CFMutableDataRef;
+ pub fn CFDataCreateMutableCopy(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ theData: CFDataRef,
+ ) -> CFMutableDataRef;
+
+ /* Accessing Data */
+ pub fn CFDataGetMutableBytePtr(theData: CFMutableDataRef) -> *mut u8;
+
+ /* Modifying a Mutable Data Object */
+ pub fn CFDataAppendBytes(theData: CFMutableDataRef, bytes: *const u8, length: CFIndex);
+ pub fn CFDataDeleteBytes(theData: CFMutableDataRef, range: CFRange);
+ pub fn CFDataReplaceBytes(
+ theData: CFMutableDataRef,
+ range: CFRange,
+ newBytes: *const u8,
+ newLength: CFIndex,
+ );
+ pub fn CFDataIncreaseLength(theData: CFMutableDataRef, extraLength: CFIndex);
+ pub fn CFDataSetLength(theData: CFMutableDataRef, length: CFIndex);
}
diff --git a/third_party/rust/core-foundation-sys/src/date.rs b/third_party/rust/core-foundation-sys/src/date.rs
index f83ce1dd18..26b55d402a 100644
--- a/third_party/rust/core-foundation-sys/src/date.rs
+++ b/third_party/rust/core-foundation-sys/src/date.rs
@@ -9,7 +9,7 @@
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFComparisonResult, CFTypeID};
+use crate::base::{CFAllocatorRef, CFComparisonResult, CFTypeID};
#[repr(C)]
pub struct __CFDate(c_void);
@@ -19,7 +19,7 @@ pub type CFDateRef = *const __CFDate;
pub type CFTimeInterval = f64;
pub type CFAbsoluteTime = CFTimeInterval;
-extern {
+extern "C" {
pub static kCFAbsoluteTimeIntervalSince1904: CFTimeInterval;
pub static kCFAbsoluteTimeIntervalSince1970: CFTimeInterval;
@@ -28,7 +28,11 @@ extern {
pub fn CFDateCreate(allocator: CFAllocatorRef, at: CFAbsoluteTime) -> CFDateRef;
pub fn CFDateGetAbsoluteTime(date: CFDateRef) -> CFAbsoluteTime;
pub fn CFDateGetTimeIntervalSinceDate(date: CFDateRef, other: CFDateRef) -> CFTimeInterval;
- pub fn CFDateCompare(date: CFDateRef, other: CFDateRef, context: *mut c_void) -> CFComparisonResult;
+ pub fn CFDateCompare(
+ date: CFDateRef,
+ other: CFDateRef,
+ context: *mut c_void,
+ ) -> CFComparisonResult;
pub fn CFDateGetTypeID() -> CFTypeID;
}
diff --git a/third_party/rust/core-foundation-sys/src/date_formatter.rs b/third_party/rust/core-foundation-sys/src/date_formatter.rs
new file mode 100644
index 0000000000..83c6e1fa76
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/date_formatter.rs
@@ -0,0 +1,147 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFRange, CFTypeID, CFTypeRef};
+use crate::date::{CFAbsoluteTime, CFDateRef};
+use crate::locale::CFLocaleRef;
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFDateFormatter(c_void);
+pub type CFDateFormatterRef = *mut __CFDateFormatter;
+
+pub type CFDateFormatterKey = CFStringRef;
+pub type CFDateFormatterStyle = CFIndex;
+pub type CFISO8601DateFormatOptions = CFOptionFlags;
+
+/* Date Formatter Styles */
+pub const kCFDateFormatterNoStyle: CFDateFormatterStyle = 0;
+pub const kCFDateFormatterShortStyle: CFDateFormatterStyle = 1;
+pub const kCFDateFormatterMediumStyle: CFDateFormatterStyle = 2;
+pub const kCFDateFormatterLongStyle: CFDateFormatterStyle = 3;
+pub const kCFDateFormatterFullStyle: CFDateFormatterStyle = 4;
+
+//pub const kCFISO8601DateFormatWithYear: CFISO8601DateFormatOptions = 1 << 0; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithMonth: CFISO8601DateFormatOptions = 1 << 1; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithWeekOfYear: CFISO8601DateFormatOptions = 1 << 2; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithDay: CFISO8601DateFormatOptions = 1 << 4; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithTime: CFISO8601DateFormatOptions = 1 << 5; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithTimeZone: CFISO8601DateFormatOptions = 1 << 6; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithSpaceBetweenDateAndTime: CFISO8601DateFormatOptions = 1 << 7; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithDashSeparatorInDate: CFISO8601DateFormatOptions = 1 << 8; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithColonSeparatorInTime: CFISO8601DateFormatOptions = 1 << 9; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithColonSeparatorInTimeZone: CFISO8601DateFormatOptions = 1 << 10; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithFractionalSeconds: CFISO8601DateFormatOptions = 1 << 11; // macosx(10.13)+
+//pub const kCFISO8601DateFormatWithFullDate: CFISO8601DateFormatOptions = kCFISO8601DateFormatWithYear | kCFISO8601DateFormatWithMonth | kCFISO8601DateFormatWithDay | kCFISO8601DateFormatWithDashSeparatorInDate; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithFullTime: CFISO8601DateFormatOptions = kCFISO8601DateFormatWithTime | kCFISO8601DateFormatWithColonSeparatorInTime | kCFISO8601DateFormatWithTimeZone | kCFISO8601DateFormatWithColonSeparatorInTimeZone; // macosx(10.12)+
+//pub const kCFISO8601DateFormatWithInternetDateTime: CFISO8601DateFormatOptions = kCFISO8601DateFormatWithFullDate | kCFISO8601DateFormatWithFullTime; // macosx(10.12)+
+
+extern "C" {
+ /*
+ * CFDateFormatter.h
+ */
+
+ /* Date Formatter Property Keys */
+ // The values for these keys are all CFType objects.
+ // The specific types for each key are specified above.
+ pub static kCFDateFormatterIsLenient: CFDateFormatterKey; // CFBoolean
+ pub static kCFDateFormatterTimeZone: CFDateFormatterKey; // CFTimeZone
+ pub static kCFDateFormatterCalendarName: CFDateFormatterKey; // CFString
+ pub static kCFDateFormatterDefaultFormat: CFDateFormatterKey; // CFString
+ pub static kCFDateFormatterTwoDigitStartDate: CFDateFormatterKey; // CFDate
+ pub static kCFDateFormatterDefaultDate: CFDateFormatterKey; // CFDate
+ pub static kCFDateFormatterCalendar: CFDateFormatterKey; // CFCalendar
+ pub static kCFDateFormatterEraSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterMonthSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterShortMonthSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterWeekdaySymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterShortWeekdaySymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterAMSymbol: CFDateFormatterKey; // CFString
+ pub static kCFDateFormatterPMSymbol: CFDateFormatterKey; // CFString
+ pub static kCFDateFormatterLongEraSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterVeryShortMonthSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterStandaloneMonthSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterShortStandaloneMonthSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterVeryShortStandaloneMonthSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterVeryShortWeekdaySymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterStandaloneWeekdaySymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterShortStandaloneWeekdaySymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterVeryShortStandaloneWeekdaySymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterQuarterSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterShortQuarterSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterStandaloneQuarterSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterShortStandaloneQuarterSymbols: CFDateFormatterKey; // CFArray of CFString
+ pub static kCFDateFormatterGregorianStartDate: CFDateFormatterKey; // CFDate
+ pub static kCFDateFormatterDoesRelativeDateFormattingKey: CFDateFormatterKey; // CFBoolean
+
+ /* Creating a Date Formatter */
+ pub fn CFDateFormatterCreate(
+ allocator: CFAllocatorRef,
+ locale: CFLocaleRef,
+ dateStyle: CFDateFormatterStyle,
+ timeStyle: CFDateFormatterStyle,
+ ) -> CFDateFormatterRef;
+
+ /* Configuring a Date Formatter */
+ pub fn CFDateFormatterSetFormat(formatter: CFDateFormatterRef, formatString: CFStringRef);
+ pub fn CFDateFormatterSetProperty(
+ formatter: CFDateFormatterRef,
+ key: CFStringRef,
+ value: CFTypeRef,
+ );
+
+ /* Parsing Strings */
+ pub fn CFDateFormatterCreateDateFromString(
+ allocator: CFAllocatorRef,
+ formatter: CFDateFormatterRef,
+ string: CFStringRef,
+ rangep: *mut CFRange,
+ ) -> CFDateRef;
+ pub fn CFDateFormatterGetAbsoluteTimeFromString(
+ formatter: CFDateFormatterRef,
+ string: CFStringRef,
+ rangep: *mut CFRange,
+ atp: *mut CFAbsoluteTime,
+ ) -> Boolean;
+
+ /* Creating Strings From Data */
+ pub fn CFDateFormatterCreateStringWithAbsoluteTime(
+ allocator: CFAllocatorRef,
+ formatter: CFDateFormatterRef,
+ at: CFAbsoluteTime,
+ ) -> CFStringRef;
+ pub fn CFDateFormatterCreateStringWithDate(
+ allocator: CFAllocatorRef,
+ formatter: CFDateFormatterRef,
+ date: CFDateRef,
+ ) -> CFStringRef;
+ pub fn CFDateFormatterCreateDateFormatFromTemplate(
+ allocator: CFAllocatorRef,
+ tmplate: CFStringRef,
+ options: CFOptionFlags,
+ locale: CFLocaleRef,
+ ) -> CFStringRef;
+
+ /* Getting Information About a Date Formatter */
+ pub fn CFDateFormatterCopyProperty(
+ formatter: CFDateFormatterRef,
+ key: CFDateFormatterKey,
+ ) -> CFTypeRef;
+ pub fn CFDateFormatterGetDateStyle(formatter: CFDateFormatterRef) -> CFDateFormatterStyle;
+ pub fn CFDateFormatterGetFormat(formatter: CFDateFormatterRef) -> CFStringRef;
+ pub fn CFDateFormatterGetLocale(formatter: CFDateFormatterRef) -> CFLocaleRef;
+ pub fn CFDateFormatterGetTimeStyle(formatter: CFDateFormatterRef) -> CFDateFormatterStyle;
+
+ /* Getting the CFDateFormatter Type ID */
+ pub fn CFDateFormatterGetTypeID() -> CFTypeID;
+
+ //pub fn CFDateFormatterCreateISO8601Formatter(allocator: CFAllocatorRef, formatOptions: CFISO8601DateFormatOptions) -> CFDateFormatterRef; // macosx(10.12)+
+}
diff --git a/third_party/rust/core-foundation-sys/src/dictionary.rs b/third_party/rust/core-foundation-sys/src/dictionary.rs
index d10e9c1200..8c04d680df 100644
--- a/third_party/rust/core-foundation-sys/src/dictionary.rs
+++ b/third_party/rust/core-foundation-sys/src/dictionary.rs
@@ -9,15 +9,19 @@
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFHashCode, CFIndex, CFTypeID, Boolean};
-use string::CFStringRef;
+use crate::base::{Boolean, CFAllocatorRef, CFHashCode, CFIndex, CFTypeID};
+use crate::string::CFStringRef;
-pub type CFDictionaryApplierFunction = extern "C" fn(key: *const c_void, value: *const c_void, context: *mut c_void);
+pub type CFDictionaryApplierFunction =
+ extern "C" fn(key: *const c_void, value: *const c_void, context: *mut c_void);
-pub type CFDictionaryRetainCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
-pub type CFDictionaryReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void);
+pub type CFDictionaryRetainCallBack =
+ extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
+pub type CFDictionaryReleaseCallBack =
+ extern "C" fn(allocator: CFAllocatorRef, value: *const c_void);
pub type CFDictionaryCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef;
-pub type CFDictionaryEqualCallBack = extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
+pub type CFDictionaryEqualCallBack =
+ extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
pub type CFDictionaryHashCallBack = extern "C" fn(value: *const c_void) -> CFHashCode;
#[repr(C)]
@@ -28,7 +32,7 @@ pub struct CFDictionaryKeyCallBacks {
pub release: CFDictionaryReleaseCallBack,
pub copyDescription: CFDictionaryCopyDescriptionCallBack,
pub equal: CFDictionaryEqualCallBack,
- pub hash: CFDictionaryHashCallBack
+ pub hash: CFDictionaryHashCallBack,
}
#[repr(C)]
@@ -38,7 +42,7 @@ pub struct CFDictionaryValueCallBacks {
pub retain: CFDictionaryRetainCallBack,
pub release: CFDictionaryReleaseCallBack,
pub copyDescription: CFDictionaryCopyDescriptionCallBack,
- pub equal: CFDictionaryEqualCallBack
+ pub equal: CFDictionaryEqualCallBack,
}
#[repr(C)]
@@ -47,45 +51,89 @@ pub struct __CFDictionary(c_void);
pub type CFDictionaryRef = *const __CFDictionary;
pub type CFMutableDictionaryRef = *mut __CFDictionary;
-extern {
+extern "C" {
/*
* CFDictionary.h
*/
pub static kCFTypeDictionaryKeyCallBacks: CFDictionaryKeyCallBacks;
+ pub static kCFCopyStringDictionaryKeyCallBacks: CFDictionaryKeyCallBacks;
pub static kCFTypeDictionaryValueCallBacks: CFDictionaryValueCallBacks;
+ /* CFDictionary */
+ /* Creating a dictionary */
+ pub fn CFDictionaryCreate(
+ allocator: CFAllocatorRef,
+ keys: *const *const c_void,
+ values: *const *const c_void,
+ numValues: CFIndex,
+ keyCallBacks: *const CFDictionaryKeyCallBacks,
+ valueCallBacks: *const CFDictionaryValueCallBacks,
+ ) -> CFDictionaryRef;
+ pub fn CFDictionaryCreateCopy(
+ allocator: CFAllocatorRef,
+ theDict: CFDictionaryRef,
+ ) -> CFDictionaryRef;
+
+ /* Examining a dictionary */
pub fn CFDictionaryContainsKey(theDict: CFDictionaryRef, key: *const c_void) -> Boolean;
- pub fn CFDictionaryCreate(allocator: CFAllocatorRef, keys: *const *const c_void, values: *const *const c_void,
- numValues: CFIndex, keyCallBacks: *const CFDictionaryKeyCallBacks,
- valueCallBacks: *const CFDictionaryValueCallBacks)
- -> CFDictionaryRef;
+ pub fn CFDictionaryContainsValue(theDict: CFDictionaryRef, value: *const c_void) -> Boolean;
pub fn CFDictionaryGetCount(theDict: CFDictionaryRef) -> CFIndex;
+ pub fn CFDictionaryGetCountOfKey(theDict: CFDictionaryRef, key: *const c_void) -> CFIndex;
+ pub fn CFDictionaryGetCountOfValue(heDict: CFDictionaryRef, value: *const c_void) -> CFIndex;
+ pub fn CFDictionaryGetKeysAndValues(
+ theDict: CFDictionaryRef,
+ keys: *mut *const c_void,
+ values: *mut *const c_void,
+ );
+ pub fn CFDictionaryGetValue(theDict: CFDictionaryRef, key: *const c_void) -> *const c_void;
+ pub fn CFDictionaryGetValueIfPresent(
+ theDict: CFDictionaryRef,
+ key: *const c_void,
+ value: *mut *const c_void,
+ ) -> Boolean;
+
+ /* Applying a function to a dictionary */
+ pub fn CFDictionaryApplyFunction(
+ theDict: CFDictionaryRef,
+ applier: CFDictionaryApplierFunction,
+ context: *mut c_void,
+ );
+
+ /* Getting the CFDictionary type ID */
pub fn CFDictionaryGetTypeID() -> CFTypeID;
- pub fn CFDictionaryGetValueIfPresent(theDict: CFDictionaryRef, key: *const c_void, value: *mut *const c_void)
- -> Boolean;
- pub fn CFDictionaryApplyFunction(theDict: CFDictionaryRef,
- applier: CFDictionaryApplierFunction,
- context: *mut c_void);
- pub fn CFDictionaryGetKeysAndValues(theDict: CFDictionaryRef,
- keys: *mut *const c_void,
- values: *mut *const c_void);
-
- pub fn CFDictionaryCreateMutable(allocator: CFAllocatorRef, capacity: CFIndex,
- keyCallbacks: *const CFDictionaryKeyCallBacks,
- valueCallbacks: *const CFDictionaryValueCallBacks) -> CFMutableDictionaryRef;
- pub fn CFDictionaryCreateMutableCopy(allocator: CFAllocatorRef, capacity: CFIndex,
- theDict: CFDictionaryRef) -> CFMutableDictionaryRef;
- pub fn CFDictionaryAddValue(theDict: CFMutableDictionaryRef,
- key: *const c_void,
- value: *const c_void);
- pub fn CFDictionarySetValue(theDict: CFMutableDictionaryRef,
- key: *const c_void,
- value: *const c_void);
- pub fn CFDictionaryReplaceValue(theDict: CFMutableDictionaryRef,
- key: *const c_void,
- value: *const c_void);
- pub fn CFDictionaryRemoveValue(theDict: CFMutableDictionaryRef,
- key: *const c_void);
+
+ /* CFMutableDictionary */
+ /* Creating a Mutable Dictionary */
+ pub fn CFDictionaryCreateMutable(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ keyCallbacks: *const CFDictionaryKeyCallBacks,
+ valueCallbacks: *const CFDictionaryValueCallBacks,
+ ) -> CFMutableDictionaryRef;
+ pub fn CFDictionaryCreateMutableCopy(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ theDict: CFDictionaryRef,
+ ) -> CFMutableDictionaryRef;
+
+ /* Modifying a Dictionary */
+ pub fn CFDictionaryAddValue(
+ theDict: CFMutableDictionaryRef,
+ key: *const c_void,
+ value: *const c_void,
+ );
pub fn CFDictionaryRemoveAllValues(theDict: CFMutableDictionaryRef);
+ pub fn CFDictionaryRemoveValue(theDict: CFMutableDictionaryRef, key: *const c_void);
+ pub fn CFDictionaryReplaceValue(
+ theDict: CFMutableDictionaryRef,
+ key: *const c_void,
+ value: *const c_void,
+ );
+ pub fn CFDictionarySetValue(
+ theDict: CFMutableDictionaryRef,
+ key: *const c_void,
+ value: *const c_void,
+ );
+
}
diff --git a/third_party/rust/core-foundation-sys/src/error.rs b/third_party/rust/core-foundation-sys/src/error.rs
index 8a4c1d4940..e8ebd6c421 100644
--- a/third_party/rust/core-foundation-sys/src/error.rs
+++ b/third_party/rust/core-foundation-sys/src/error.rs
@@ -9,24 +9,54 @@
use std::os::raw::c_void;
-use base::{CFTypeID, CFIndex};
-use string::CFStringRef;
+use crate::base::{CFAllocatorRef, CFIndex, CFTypeID};
+use crate::dictionary::CFDictionaryRef;
+use crate::string::CFStringRef;
#[repr(C)]
pub struct __CFError(c_void);
pub type CFErrorRef = *mut __CFError;
+pub type CFErrorDomain = CFStringRef;
extern "C" {
- pub fn CFErrorGetTypeID() -> CFTypeID;
+ /*
+ * CFError.h
+ */
+ /* Error domains */
pub static kCFErrorDomainPOSIX: CFStringRef;
pub static kCFErrorDomainOSStatus: CFStringRef;
pub static kCFErrorDomainMach: CFStringRef;
pub static kCFErrorDomainCocoa: CFStringRef;
+ /* Keys for the user info dictionary */
+ pub static kCFErrorLocalizedDescriptionKey: CFStringRef;
+ // pub static kCFErrorLocalizedFailureKey: CFStringRef; // macos(10.13)+
+ pub static kCFErrorLocalizedFailureReasonKey: CFStringRef;
+ pub static kCFErrorLocalizedRecoverySuggestionKey: CFStringRef;
+ pub static kCFErrorDescriptionKey: CFStringRef;
+ pub static kCFErrorUnderlyingErrorKey: CFStringRef;
+ pub static kCFErrorURLKey: CFStringRef;
+ pub static kCFErrorFilePathKey: CFStringRef;
+
+ /* Creating a CFError */
+ pub fn CFErrorCreate(
+ allocator: CFAllocatorRef,
+ domain: CFErrorDomain,
+ code: CFIndex,
+ userInfo: CFDictionaryRef,
+ ) -> CFErrorRef;
+ //pub fn CFErrorCreateWithUserInfoKeysAndValues
+
+ /* Getting Information About an Error */
pub fn CFErrorGetDomain(err: CFErrorRef) -> CFStringRef;
pub fn CFErrorGetCode(err: CFErrorRef) -> CFIndex;
-
+ pub fn CFErrorCopyUserInfo(err: CFErrorRef) -> CFDictionaryRef;
pub fn CFErrorCopyDescription(err: CFErrorRef) -> CFStringRef;
+ pub fn CFErrorCopyFailureReason(err: CFErrorRef) -> CFStringRef;
+ pub fn CFErrorCopyRecoverySuggestion(err: CFErrorRef) -> CFStringRef;
+
+ /* Getting the CFError Type ID */
+ pub fn CFErrorGetTypeID() -> CFTypeID;
}
diff --git a/third_party/rust/core-foundation-sys/src/file_security.rs b/third_party/rust/core-foundation-sys/src/file_security.rs
new file mode 100644
index 0000000000..a4ec6112b5
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/file_security.rs
@@ -0,0 +1,71 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+#[cfg(feature = "mac_os_10_8_features")]
+use crate::base::CFOptionFlags;
+use crate::base::{Boolean, CFAllocatorRef, CFTypeID};
+use crate::uuid::CFUUIDRef;
+
+#[repr(C)]
+pub struct __CFFileSecurity(c_void);
+pub type CFFileSecurityRef = *mut __CFFileSecurity;
+
+#[cfg(feature = "mac_os_10_8_features")]
+pub type CFFileSecurityClearOptions = CFOptionFlags;
+#[cfg(feature = "mac_os_10_8_features")]
+pub const kCFFileSecurityClearOwner: CFFileSecurityClearOptions = 1 << 0;
+#[cfg(feature = "mac_os_10_8_features")]
+pub const kCFFileSecurityClearGroup: CFFileSecurityClearOptions = 1 << 1;
+#[cfg(feature = "mac_os_10_8_features")]
+pub const kCFFileSecurityClearMode: CFFileSecurityClearOptions = 1 << 2;
+#[cfg(feature = "mac_os_10_8_features")]
+pub const kCFFileSecurityClearOwnerUUID: CFFileSecurityClearOptions = 1 << 3;
+#[cfg(feature = "mac_os_10_8_features")]
+pub const kCFFileSecurityClearGroupUUID: CFFileSecurityClearOptions = 1 << 4;
+#[cfg(feature = "mac_os_10_8_features")]
+pub const kCFFileSecurityClearAccessControlList: CFFileSecurityClearOptions = 1 << 5;
+
+extern "C" {
+ /*
+ * CFFileSecurity.h
+ */
+ pub fn CFFileSecurityGetTypeID() -> CFTypeID;
+ pub fn CFFileSecurityCreate(allocator: CFAllocatorRef) -> CFFileSecurityRef;
+ pub fn CFFileSecurityCreateCopy(
+ allocator: CFAllocatorRef,
+ fileSec: CFFileSecurityRef,
+ ) -> CFFileSecurityRef;
+ pub fn CFFileSecurityCopyOwnerUUID(
+ fileSec: CFFileSecurityRef,
+ ownerUUID: *mut CFUUIDRef,
+ ) -> Boolean;
+ pub fn CFFileSecuritySetOwnerUUID(fileSec: CFFileSecurityRef, ownerUUID: CFUUIDRef) -> Boolean;
+ pub fn CFFileSecurityCopyGroupUUID(
+ fileSec: CFFileSecurityRef,
+ groupUUID: *mut CFUUIDRef,
+ ) -> Boolean;
+ pub fn CFFileSecuritySetGroupUUID(fileSec: CFFileSecurityRef, groupUUID: CFUUIDRef) -> Boolean;
+ //pub fn CFFileSecurityCopyAccessControlList(fileSec: CFFileSecurityRef, accessControlList: *mut acl_t) -> Boolean;
+ //pub fn CFFileSecuritySetAccessControlList(fileSec: CFFileSecurityRef, accessControlList: acl_t) -> Boolean;
+ //pub fn CFFileSecurityGetOwner(fileSec: CFFileSecurityRef, owner: *mut uid_t) -> Boolean;
+ //pub fn CFFileSecuritySetOwner(fileSec: CFFileSecurityRef, owner: uid_t) -> Boolean;
+ //pub fn CFFileSecurityGetGroup(fileSec: CFFileSecurityRef, group: *mut gid_t) -> Boolean;
+ //pub fn CFFileSecuritySetGroup(fileSec: CFFileSecurityRef, group: gid_t) -> Boolean;
+ //pub fn CFFileSecurityGetMode(fileSec: CFFileSecurityRef, mode: *mut mode_t) -> Boolean;
+ //pub fn CFFileSecuritySetMode(fileSec: CFFileSecurityRef, mode: mode_t) -> Boolean;
+
+ #[cfg(feature = "mac_os_10_8_features")]
+ #[cfg_attr(feature = "mac_os_10_7_support", linkage = "extern_weak")]
+ pub fn CFFileSecurityClearProperties(
+ fileSec: CFFileSecurityRef,
+ clearPropertyMask: CFFileSecurityClearOptions,
+ ) -> Boolean;
+}
diff --git a/third_party/rust/core-foundation-sys/src/filedescriptor.rs b/third_party/rust/core-foundation-sys/src/filedescriptor.rs
index 3f51d10729..271adb716c 100644
--- a/third_party/rust/core-foundation-sys/src/filedescriptor.rs
+++ b/third_party/rust/core-foundation-sys/src/filedescriptor.rs
@@ -9,9 +9,9 @@
use std::os::raw::{c_int, c_void};
-use base::{Boolean, CFIndex, CFTypeID, CFOptionFlags, CFAllocatorRef};
-use string::CFStringRef;
-use runloop::CFRunLoopSourceRef;
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeID};
+use crate::runloop::CFRunLoopSourceRef;
+use crate::string::CFStringRef;
pub type CFFileDescriptorNativeDescriptor = c_int;
@@ -21,38 +21,60 @@ pub struct __CFFileDescriptor(c_void);
pub type CFFileDescriptorRef = *mut __CFFileDescriptor;
/* Callback Reason Types */
-pub const kCFFileDescriptorReadCallBack: CFOptionFlags = 1 << 0;
+pub const kCFFileDescriptorReadCallBack: CFOptionFlags = 1 << 0;
pub const kCFFileDescriptorWriteCallBack: CFOptionFlags = 1 << 1;
-pub type CFFileDescriptorCallBack = extern "C" fn (f: CFFileDescriptorRef, callBackTypes: CFOptionFlags, info: *mut c_void);
+pub type CFFileDescriptorCallBack =
+ extern "C" fn(f: CFFileDescriptorRef, callBackTypes: CFOptionFlags, info: *mut c_void);
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Debug, Clone, Copy)]
pub struct CFFileDescriptorContext {
pub version: CFIndex,
pub info: *mut c_void,
- pub retain: Option<extern "C" fn (info: *const c_void) -> *const c_void>,
- pub release: Option<extern "C" fn (info: *const c_void)>,
- pub copyDescription: Option<extern "C" fn (info: *const c_void) -> CFStringRef>,
+ pub retain: Option<extern "C" fn(info: *const c_void) -> *const c_void>,
+ pub release: Option<extern "C" fn(info: *const c_void)>,
+ pub copyDescription: Option<extern "C" fn(info: *const c_void) -> CFStringRef>,
}
-extern {
+extern "C" {
/*
* CFFileDescriptor.h
*/
- pub fn CFFileDescriptorGetTypeID() -> CFTypeID;
- pub fn CFFileDescriptorCreate(allocator: CFAllocatorRef, fd: CFFileDescriptorNativeDescriptor, closeOnInvalidate: Boolean, callout: CFFileDescriptorCallBack, context: *const CFFileDescriptorContext) -> CFFileDescriptorRef;
+ /* Creating a CFFileDescriptor */
+ pub fn CFFileDescriptorCreate(
+ allocator: CFAllocatorRef,
+ fd: CFFileDescriptorNativeDescriptor,
+ closeOnInvalidate: Boolean,
+ callout: CFFileDescriptorCallBack,
+ context: *const CFFileDescriptorContext,
+ ) -> CFFileDescriptorRef;
- pub fn CFFileDescriptorGetNativeDescriptor(f: CFFileDescriptorRef) -> CFFileDescriptorNativeDescriptor;
+ /* Getting Information About a File Descriptor */
+ pub fn CFFileDescriptorGetNativeDescriptor(
+ f: CFFileDescriptorRef,
+ ) -> CFFileDescriptorNativeDescriptor;
+ pub fn CFFileDescriptorIsValid(f: CFFileDescriptorRef) -> Boolean;
+ pub fn CFFileDescriptorGetContext(
+ f: CFFileDescriptorRef,
+ context: *mut CFFileDescriptorContext,
+ );
- pub fn CFFileDescriptorGetContext(f: CFFileDescriptorRef, context: *mut CFFileDescriptorContext);
+ /* Invalidating a File Descriptor */
+ pub fn CFFileDescriptorInvalidate(f: CFFileDescriptorRef);
+ /* Managing Callbacks */
pub fn CFFileDescriptorEnableCallBacks(f: CFFileDescriptorRef, callBackTypes: CFOptionFlags);
pub fn CFFileDescriptorDisableCallBacks(f: CFFileDescriptorRef, callBackTypes: CFOptionFlags);
- pub fn CFFileDescriptorInvalidate(f: CFFileDescriptorRef);
- pub fn CFFileDescriptorIsValid(f: CFFileDescriptorRef) -> Boolean;
+ /* Creating a Run Loop Source */
+ pub fn CFFileDescriptorCreateRunLoopSource(
+ allocator: CFAllocatorRef,
+ f: CFFileDescriptorRef,
+ order: CFIndex,
+ ) -> CFRunLoopSourceRef;
- pub fn CFFileDescriptorCreateRunLoopSource(allocator: CFAllocatorRef, f: CFFileDescriptorRef, order: CFIndex) -> CFRunLoopSourceRef;
+ /* Getting the CFFileDescriptor Type ID */
+ pub fn CFFileDescriptorGetTypeID() -> CFTypeID;
}
diff --git a/third_party/rust/core-foundation-sys/src/lib.rs b/third_party/rust/core-foundation-sys/src/lib.rs
index f9a1884169..948ce807d3 100644
--- a/third_party/rust/core-foundation-sys/src/lib.rs
+++ b/third_party/rust/core-foundation-sys/src/lib.rs
@@ -6,27 +6,69 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals, improper_ctypes)]
+#![allow(
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals,
+ improper_ctypes
+)]
+#![cfg_attr(
+ all(feature = "mac_os_10_7_support", feature = "mac_os_10_8_features"),
+ feature(linkage)
+)] // back-compat requires weak linkage
-#![cfg_attr(all(feature="mac_os_10_7_support", feature="mac_os_10_8_features"), feature(linkage))] // back-compat requires weak linkage
+// Link to CoreFoundation on any Apple device.
+//
+// We don't use `target_vendor` since that is going to be deprecated:
+// https://github.com/rust-lang/lang-team/issues/102
+#[cfg_attr(
+ all(
+ any(target_os = "macos", target_os = "ios", target_os = "tvos"),
+ feature = "link"
+ ),
+ link(name = "CoreFoundation", kind = "framework")
+)]
+extern "C" {}
pub mod array;
pub mod attributed_string;
+pub mod bag;
pub mod base;
+pub mod binary_heap;
+pub mod bit_vector;
pub mod bundle;
+pub mod calendar;
pub mod characterset;
pub mod data;
pub mod date;
+pub mod date_formatter;
pub mod dictionary;
pub mod error;
+pub mod file_security;
pub mod filedescriptor;
+pub mod locale;
+pub mod mach_port;
pub mod messageport;
+pub mod notification_center;
pub mod number;
+pub mod number_formatter;
+pub mod plugin;
+pub mod preferences;
pub mod propertylist;
pub mod runloop;
pub mod set;
+pub mod socket;
+pub mod stream;
pub mod string;
+pub mod string_tokenizer;
pub mod timezone;
+pub mod tree;
pub mod url;
+pub mod url_enumerator;
+#[cfg(target_os = "macos")]
+pub mod user_notification;
pub mod uuid;
-pub mod mach_port;
+#[cfg(target_os = "macos")]
+pub mod xml_node;
+#[cfg(target_os = "macos")]
+pub mod xml_parser;
diff --git a/third_party/rust/core-foundation-sys/src/locale.rs b/third_party/rust/core-foundation-sys/src/locale.rs
new file mode 100644
index 0000000000..f80e5c4a6a
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/locale.rs
@@ -0,0 +1,146 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::array::CFArrayRef;
+use crate::base::{CFAllocatorRef, CFIndex, CFTypeID, CFTypeRef, LangCode, RegionCode};
+use crate::dictionary::CFDictionaryRef;
+use crate::notification_center::CFNotificationName;
+use crate::string::CFStringRef;
+use std::os::raw::c_void;
+
+#[repr(C)]
+pub struct __CFLocale(c_void);
+pub type CFLocaleRef = *const __CFLocale;
+
+pub type CFLocaleIdentifier = CFStringRef;
+pub type CFLocaleKey = CFStringRef;
+pub type CFCalendarIdentifier = CFStringRef;
+pub type CFLocaleLanguageDirection = CFIndex;
+
+pub const kCFLocaleLanguageDirectionUnknown: CFLocaleLanguageDirection = 0;
+pub const kCFLocaleLanguageDirectionLeftToRight: CFLocaleLanguageDirection = 1;
+pub const kCFLocaleLanguageDirectionRightToLeft: CFLocaleLanguageDirection = 2;
+pub const kCFLocaleLanguageDirectionTopToBottom: CFLocaleLanguageDirection = 3;
+pub const kCFLocaleLanguageDirectionBottomToTop: CFLocaleLanguageDirection = 4;
+
+extern "C" {
+ /*
+ * CFLocale.h
+ */
+
+ /* Locale Change Notification */
+ pub static kCFLocaleCurrentLocaleDidChangeNotification: CFNotificationName;
+
+ /* Locale Property Keys */
+ pub static kCFLocaleIdentifier: CFLocaleKey;
+ pub static kCFLocaleLanguageCode: CFLocaleKey;
+ pub static kCFLocaleCountryCode: CFLocaleKey;
+ pub static kCFLocaleScriptCode: CFLocaleKey;
+ pub static kCFLocaleVariantCode: CFLocaleKey;
+
+ pub static kCFLocaleExemplarCharacterSet: CFLocaleKey;
+ pub static kCFLocaleCalendarIdentifier: CFLocaleKey;
+ pub static kCFLocaleCalendar: CFLocaleKey;
+ pub static kCFLocaleCollationIdentifier: CFLocaleKey;
+ pub static kCFLocaleUsesMetricSystem: CFLocaleKey;
+ pub static kCFLocaleMeasurementSystem: CFLocaleKey;
+ pub static kCFLocaleDecimalSeparator: CFLocaleKey;
+ pub static kCFLocaleGroupingSeparator: CFLocaleKey;
+ pub static kCFLocaleCurrencySymbol: CFLocaleKey;
+ pub static kCFLocaleCurrencyCode: CFLocaleKey;
+ pub static kCFLocaleCollatorIdentifier: CFLocaleKey;
+ pub static kCFLocaleQuotationBeginDelimiterKey: CFLocaleKey;
+ pub static kCFLocaleQuotationEndDelimiterKey: CFLocaleKey;
+ pub static kCFLocaleAlternateQuotationBeginDelimiterKey: CFLocaleKey;
+ pub static kCFLocaleAlternateQuotationEndDelimiterKey: CFLocaleKey;
+
+ /* Locale Calendar Identifiers */
+ pub static kCFGregorianCalendar: CFCalendarIdentifier;
+ pub static kCFBuddhistCalendar: CFCalendarIdentifier;
+ pub static kCFChineseCalendar: CFCalendarIdentifier;
+ pub static kCFHebrewCalendar: CFCalendarIdentifier;
+ pub static kCFIslamicCalendar: CFCalendarIdentifier;
+ pub static kCFIslamicCivilCalendar: CFCalendarIdentifier;
+ pub static kCFJapaneseCalendar: CFCalendarIdentifier;
+ pub static kCFRepublicOfChinaCalendar: CFCalendarIdentifier;
+ pub static kCFPersianCalendar: CFCalendarIdentifier;
+ pub static kCFIndianCalendar: CFCalendarIdentifier;
+ pub static kCFISO8601Calendar: CFCalendarIdentifier;
+ //pub static kCFIslamicTabularCalendar: CFCalendarIdentifier; // macos(10.10)+
+ //pub static kCFIslamicUmmAlQuraCalendar: CFCalendarIdentifier; // macos(10.10)+
+
+ /* Creating a Locale */
+ pub fn CFLocaleCopyCurrent() -> CFLocaleRef;
+ pub fn CFLocaleCreate(
+ allocator: CFAllocatorRef,
+ localeIdentifier: CFLocaleIdentifier,
+ ) -> CFLocaleRef;
+ pub fn CFLocaleCreateCopy(allocator: CFAllocatorRef, locale: CFLocaleRef) -> CFLocaleRef;
+ pub fn CFLocaleGetSystem() -> CFLocaleRef;
+
+ /* Getting System Locale Information */
+ pub fn CFLocaleCopyAvailableLocaleIdentifiers() -> CFArrayRef;
+
+ /* Getting ISO Information */
+ pub fn CFLocaleCopyISOCountryCodes() -> CFArrayRef;
+ pub fn CFLocaleCopyISOLanguageCodes() -> CFArrayRef;
+ pub fn CFLocaleCopyISOCurrencyCodes() -> CFArrayRef;
+ pub fn CFLocaleCopyCommonISOCurrencyCodes() -> CFArrayRef;
+
+ /* Language Preferences */
+ pub fn CFLocaleCopyPreferredLanguages() -> CFArrayRef;
+
+ /* Getting Information About a Locale */
+ pub fn CFLocaleCopyDisplayNameForPropertyValue(
+ displayLocale: CFLocaleRef,
+ key: CFLocaleKey,
+ value: CFStringRef,
+ ) -> CFStringRef;
+ pub fn CFLocaleGetValue(locale: CFLocaleRef, key: CFLocaleKey) -> CFTypeRef;
+ pub fn CFLocaleGetIdentifier(locale: CFLocaleRef) -> CFLocaleIdentifier;
+
+ /* Getting and Creating Locale Identifiers */
+ pub fn CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(
+ allocator: CFAllocatorRef,
+ lcode: LangCode,
+ rcode: RegionCode,
+ ) -> CFLocaleIdentifier;
+ pub fn CFLocaleCreateCanonicalLanguageIdentifierFromString(
+ allocator: CFAllocatorRef,
+ localeIdentifier: CFStringRef,
+ ) -> CFLocaleIdentifier;
+ pub fn CFLocaleCreateCanonicalLocaleIdentifierFromString(
+ allocator: CFAllocatorRef,
+ localeIdentifier: CFStringRef,
+ ) -> CFLocaleIdentifier;
+ pub fn CFLocaleCreateComponentsFromLocaleIdentifier(
+ allocator: CFAllocatorRef,
+ localeID: CFLocaleIdentifier,
+ ) -> CFDictionaryRef;
+ pub fn CFLocaleCreateLocaleIdentifierFromComponents(
+ allocator: CFAllocatorRef,
+ dictionary: CFDictionaryRef,
+ ) -> CFLocaleIdentifier;
+ pub fn CFLocaleCreateLocaleIdentifierFromWindowsLocaleCode(
+ allocator: CFAllocatorRef,
+ lcid: u32,
+ ) -> CFLocaleIdentifier;
+ pub fn CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(
+ localeIdentifier: CFLocaleIdentifier,
+ ) -> u32;
+
+ /* Getting Line and Character Direction for a Language */
+ pub fn CFLocaleGetLanguageCharacterDirection(
+ isoLangCode: CFStringRef,
+ ) -> CFLocaleLanguageDirection;
+ pub fn CFLocaleGetLanguageLineDirection(isoLangCode: CFStringRef) -> CFLocaleLanguageDirection;
+
+ /* Getting the CFLocale Type ID */
+ pub fn CFLocaleGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/mach_port.rs b/third_party/rust/core-foundation-sys/src/mach_port.rs
index 2341fd4e74..1f47275dec 100644
--- a/third_party/rust/core-foundation-sys/src/mach_port.rs
+++ b/third_party/rust/core-foundation-sys/src/mach_port.rs
@@ -1,20 +1,75 @@
-pub use base::{CFAllocatorRef, CFIndex, CFTypeID};
-use runloop::CFRunLoopSourceRef;
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::base::{mach_port_t, Boolean};
+pub use crate::base::{CFAllocatorRef, CFIndex, CFTypeID};
+use crate::runloop::CFRunLoopSourceRef;
+use crate::string::CFStringRef;
use std::os::raw::c_void;
#[repr(C)]
pub struct __CFMachPort(c_void);
-pub type CFMachPortRef = *const __CFMachPort;
+pub type CFMachPortRef = *mut __CFMachPort;
+
+pub type CFMachPortCallBack =
+ extern "C" fn(port: CFMachPortRef, msg: *mut c_void, size: CFIndex, info: *mut c_void);
+pub type CFMachPortInvalidationCallBack = extern "C" fn(port: CFMachPortRef, info: *mut c_void);
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub struct CFMachPortContext {
+ pub version: CFIndex,
+ pub info: *mut c_void,
+ pub retain: extern "C" fn(info: *const c_void) -> *const c_void,
+ pub release: extern "C" fn(info: *const c_void),
+ pub copyDescription: extern "C" fn(info: *const c_void) -> CFStringRef,
+}
extern "C" {
/*
* CFMachPort.h
*/
+
+ /* Creating a CFMachPort Object */
+ pub fn CFMachPortCreate(
+ allocator: CFAllocatorRef,
+ callout: CFMachPortCallBack,
+ context: *mut CFMachPortContext,
+ shouldFreeInfo: *mut Boolean,
+ ) -> CFMachPortRef;
+ pub fn CFMachPortCreateWithPort(
+ allocator: CFAllocatorRef,
+ portNum: mach_port_t,
+ callout: CFMachPortCallBack,
+ context: *mut CFMachPortContext,
+ shouldFreeInfo: *mut Boolean,
+ ) -> CFMachPortRef;
+
+ /* Configuring a CFMachPort Object */
+ pub fn CFMachPortInvalidate(port: CFMachPortRef);
pub fn CFMachPortCreateRunLoopSource(
allocator: CFAllocatorRef,
port: CFMachPortRef,
order: CFIndex,
) -> CFRunLoopSourceRef;
-
+ pub fn CFMachPortSetInvalidationCallBack(
+ port: CFMachPortRef,
+ callout: CFMachPortInvalidationCallBack,
+ );
+
+ /* Examining a CFMachPort Object */
+ pub fn CFMachPortGetContext(port: CFMachPortRef, context: *mut CFMachPortContext);
+ pub fn CFMachPortGetInvalidationCallBack(port: CFMachPortRef)
+ -> CFMachPortInvalidationCallBack;
+ pub fn CFMachPortGetPort(port: CFMachPortRef) -> mach_port_t;
+ pub fn CFMachPortIsValid(port: CFMachPortRef) -> Boolean;
+
+ /* Getting the CFMachPort Type ID */
pub fn CFMachPortGetTypeID() -> CFTypeID;
}
diff --git a/third_party/rust/core-foundation-sys/src/messageport.rs b/third_party/rust/core-foundation-sys/src/messageport.rs
index e33d9aa4bc..4ccdcc8b37 100644
--- a/third_party/rust/core-foundation-sys/src/messageport.rs
+++ b/third_party/rust/core-foundation-sys/src/messageport.rs
@@ -9,71 +9,98 @@
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFIndex, CFTypeID, Boolean};
-use data::CFDataRef;
-use date::CFTimeInterval;
-use runloop::CFRunLoopSourceRef;
-use string::CFStringRef;
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFTypeID, SInt32};
+use crate::data::CFDataRef;
+use crate::date::CFTimeInterval;
+use crate::runloop::CFRunLoopSourceRef;
+use crate::string::CFStringRef;
#[repr(C)]
-#[derive(Copy, Clone)]
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug)]
pub struct CFMessagePortContext {
pub version: CFIndex,
pub info: *mut c_void,
- pub retain: Option<unsafe extern fn(info: *const c_void) -> *const c_void>,
- pub release: Option<unsafe extern fn(info: *const c_void)>,
- pub copyDescription: Option<unsafe extern fn(info: *const c_void)
- -> CFStringRef>,
+ pub retain: Option<unsafe extern "C" fn(info: *const c_void) -> *const c_void>,
+ pub release: Option<unsafe extern "C" fn(info: *const c_void)>,
+ pub copyDescription: Option<unsafe extern "C" fn(info: *const c_void) -> CFStringRef>,
}
pub type CFMessagePortCallBack = Option<
- unsafe extern fn(local: CFMessagePortRef,
- msgid: i32,
- data: CFDataRef,
- info: *mut c_void) -> CFDataRef>;
+ unsafe extern "C" fn(
+ local: CFMessagePortRef,
+ msgid: i32,
+ data: CFDataRef,
+ info: *mut c_void,
+ ) -> CFDataRef,
+>;
-pub type CFMessagePortInvalidationCallBack = Option<
- unsafe extern "C" fn(ms: CFMessagePortRef, info: *mut c_void)>;
+pub type CFMessagePortInvalidationCallBack =
+ Option<unsafe extern "C" fn(ms: CFMessagePortRef, info: *mut c_void)>;
+
+/* CFMessagePortSendRequest Error Codes */
+pub const kCFMessagePortSuccess: SInt32 = 0;
+pub const kCFMessagePortSendTimeout: SInt32 = -1;
+pub const kCFMessagePortReceiveTimeout: SInt32 = -2;
+pub const kCFMessagePortIsInvalid: SInt32 = -3;
+pub const kCFMessagePortTransportError: SInt32 = -4;
+pub const kCFMessagePortBecameInvalidError: SInt32 = -5;
#[repr(C)]
pub struct __CFMessagePort(c_void);
pub type CFMessagePortRef = *mut __CFMessagePort;
-extern {
+extern "C" {
/*
* CFMessagePort.h
*/
- pub fn CFMessagePortGetTypeID() -> CFTypeID;
- pub fn CFMessagePortCreateLocal(allocator: CFAllocatorRef,
- name: CFStringRef,
- callout: CFMessagePortCallBack,
- context: *const CFMessagePortContext,
- shouldFreeInfo: *mut Boolean)
- -> CFMessagePortRef;
- pub fn CFMessagePortCreateRemote(allocator: CFAllocatorRef,
- name: CFStringRef) -> CFMessagePortRef;
- pub fn CFMessagePortIsRemote(ms: CFMessagePortRef) -> Boolean;
- pub fn CFMessagePortGetName(ms: CFMessagePortRef) -> CFStringRef;
- pub fn CFMessagePortSetName(ms: CFMessagePortRef, newName: CFStringRef)
- -> Boolean;
- pub fn CFMessagePortGetContext(ms: CFMessagePortRef,
- context: *mut CFMessagePortContext);
+
+ /* Creating a CFMessagePort Object */
+ pub fn CFMessagePortCreateLocal(
+ allocator: CFAllocatorRef,
+ name: CFStringRef,
+ callout: CFMessagePortCallBack,
+ context: *const CFMessagePortContext,
+ shouldFreeInfo: *mut Boolean,
+ ) -> CFMessagePortRef;
+ pub fn CFMessagePortCreateRemote(
+ allocator: CFAllocatorRef,
+ name: CFStringRef,
+ ) -> CFMessagePortRef;
+
+ /* Configuring a CFMessagePort Object */
+ pub fn CFMessagePortCreateRunLoopSource(
+ allocator: CFAllocatorRef,
+ local: CFMessagePortRef,
+ order: CFIndex,
+ ) -> CFRunLoopSourceRef;
+ pub fn CFMessagePortSetInvalidationCallBack(
+ ms: CFMessagePortRef,
+ callout: CFMessagePortInvalidationCallBack,
+ );
+ pub fn CFMessagePortSetName(ms: CFMessagePortRef, newName: CFStringRef) -> Boolean;
+
+ /* Using a Message Port */
pub fn CFMessagePortInvalidate(ms: CFMessagePortRef);
+ pub fn CFMessagePortSendRequest(
+ remote: CFMessagePortRef,
+ msgid: i32,
+ data: CFDataRef,
+ sendTimeout: CFTimeInterval,
+ rcvTimeout: CFTimeInterval,
+ replyMode: CFStringRef,
+ returnData: *mut CFDataRef,
+ ) -> i32;
+ //pub fn CFMessagePortSetDispatchQueue(ms: CFMessagePortRef, queue: dispatch_queue_t);
+
+ /* Examining a Message Port */
+ pub fn CFMessagePortGetContext(ms: CFMessagePortRef, context: *mut CFMessagePortContext);
+ pub fn CFMessagePortGetInvalidationCallBack(
+ ms: CFMessagePortRef,
+ ) -> CFMessagePortInvalidationCallBack;
+ pub fn CFMessagePortGetName(ms: CFMessagePortRef) -> CFStringRef;
+ pub fn CFMessagePortIsRemote(ms: CFMessagePortRef) -> Boolean;
pub fn CFMessagePortIsValid(ms: CFMessagePortRef) -> Boolean;
- pub fn CFMessagePortGetInvalidationCallBack(ms: CFMessagePortRef)
- -> CFMessagePortInvalidationCallBack;
- pub fn CFMessagePortSetInvalidationCallBack(ms: CFMessagePortRef,
- callout: CFMessagePortInvalidationCallBack);
- pub fn CFMessagePortSendRequest(remote: CFMessagePortRef, msgid: i32,
- data: CFDataRef,
- sendTimeout: CFTimeInterval,
- rcvTimeout: CFTimeInterval,
- replyMode: CFStringRef,
- returnData: *mut CFDataRef) -> i32;
- pub fn CFMessagePortCreateRunLoopSource(allocator: CFAllocatorRef,
- local: CFMessagePortRef,
- order: CFIndex)
- -> CFRunLoopSourceRef;
- // CFMessagePortSetDispatchQueue
+
+ /* Getting the CFMessagePort Type ID */
+ pub fn CFMessagePortGetTypeID() -> CFTypeID;
}
diff --git a/third_party/rust/core-foundation-sys/src/notification_center.rs b/third_party/rust/core-foundation-sys/src/notification_center.rs
new file mode 100644
index 0000000000..2ed829233e
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/notification_center.rs
@@ -0,0 +1,89 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{Boolean, CFIndex, CFOptionFlags, CFTypeID};
+use crate::dictionary::CFDictionaryRef;
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFNotificationCenter(c_void);
+
+pub type CFNotificationCenterRef = *mut __CFNotificationCenter;
+
+pub type CFNotificationName = CFStringRef;
+pub type CFNotificationCallback = extern "C" fn(
+ center: CFNotificationCenterRef,
+ observer: *mut c_void,
+ name: CFNotificationName,
+ object: *const c_void,
+ userInfo: CFDictionaryRef,
+);
+pub type CFNotificationSuspensionBehavior = CFIndex;
+
+pub const CFNotificationSuspensionBehaviorDrop: CFNotificationSuspensionBehavior = 1;
+pub const CFNotificationSuspensionBehaviorCoalesce: CFNotificationSuspensionBehavior = 2;
+pub const CFNotificationSuspensionBehaviorHold: CFNotificationSuspensionBehavior = 3;
+pub const CFNotificationSuspensionBehaviorDeliverImmediately: CFNotificationSuspensionBehavior = 4;
+
+/* Notification Posting Options */
+pub const kCFNotificationDeliverImmediately: CFOptionFlags = 1usize << 0;
+pub const kCFNotificationPostToAllSessions: CFOptionFlags = 1usize << 1;
+
+extern "C" {
+ /*
+ * CFNotificationCenter.h
+ */
+
+ /* Accessing a Notification Center */
+ pub fn CFNotificationCenterGetDarwinNotifyCenter() -> CFNotificationCenterRef;
+ #[cfg(any(target_os = "macos", target_os = "windows"))]
+ pub fn CFNotificationCenterGetDistributedCenter() -> CFNotificationCenterRef;
+ pub fn CFNotificationCenterGetLocalCenter() -> CFNotificationCenterRef;
+
+ /* Posting a Notification */
+ pub fn CFNotificationCenterPostNotification(
+ center: CFNotificationCenterRef,
+ name: CFNotificationName,
+ object: *const c_void,
+ userInfo: CFDictionaryRef,
+ deliverImmediately: Boolean,
+ );
+ pub fn CFNotificationCenterPostNotificationWithOptions(
+ center: CFNotificationCenterRef,
+ name: CFNotificationName,
+ object: *const c_void,
+ userInfo: CFDictionaryRef,
+ options: CFOptionFlags,
+ );
+
+ /* Adding and Removing Observers */
+ pub fn CFNotificationCenterAddObserver(
+ center: CFNotificationCenterRef,
+ observer: *const c_void,
+ callBack: CFNotificationCallback,
+ name: CFStringRef,
+ object: *const c_void,
+ suspensionBehavior: CFNotificationSuspensionBehavior,
+ );
+ pub fn CFNotificationCenterRemoveEveryObserver(
+ center: CFNotificationCenterRef,
+ observer: *const c_void,
+ );
+ pub fn CFNotificationCenterRemoveObserver(
+ center: CFNotificationCenterRef,
+ observer: *const c_void,
+ name: CFNotificationName,
+ object: *const c_void,
+ );
+
+ /* Getting the CFNotificationCenter Type ID */
+ pub fn CFNotificationCenterGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/number.rs b/third_party/rust/core-foundation-sys/src/number.rs
index c056a245b0..d822d417d9 100644
--- a/third_party/rust/core-foundation-sys/src/number.rs
+++ b/third_party/rust/core-foundation-sys/src/number.rs
@@ -9,7 +9,7 @@
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFTypeID, CFComparisonResult};
+use crate::base::{Boolean, CFAllocatorRef, CFComparisonResult, CFIndex, CFTypeID};
#[repr(C)]
pub struct __CFBoolean(c_void);
@@ -19,23 +19,23 @@ pub type CFBooleanRef = *const __CFBoolean;
pub type CFNumberType = u32;
// members of enum CFNumberType
-pub const kCFNumberSInt8Type: CFNumberType = 1;
-pub const kCFNumberSInt16Type: CFNumberType = 2;
-pub const kCFNumberSInt32Type: CFNumberType = 3;
-pub const kCFNumberSInt64Type: CFNumberType = 4;
-pub const kCFNumberFloat32Type: CFNumberType = 5;
-pub const kCFNumberFloat64Type: CFNumberType = 6;
-pub const kCFNumberCharType: CFNumberType = 7;
-pub const kCFNumberShortType: CFNumberType = 8;
-pub const kCFNumberIntType: CFNumberType = 9;
-pub const kCFNumberLongType: CFNumberType = 10;
-pub const kCFNumberLongLongType: CFNumberType = 11;
-pub const kCFNumberFloatType: CFNumberType = 12;
-pub const kCFNumberDoubleType: CFNumberType = 13;
-pub const kCFNumberCFIndexType: CFNumberType = 14;
+pub const kCFNumberSInt8Type: CFNumberType = 1;
+pub const kCFNumberSInt16Type: CFNumberType = 2;
+pub const kCFNumberSInt32Type: CFNumberType = 3;
+pub const kCFNumberSInt64Type: CFNumberType = 4;
+pub const kCFNumberFloat32Type: CFNumberType = 5;
+pub const kCFNumberFloat64Type: CFNumberType = 6;
+pub const kCFNumberCharType: CFNumberType = 7;
+pub const kCFNumberShortType: CFNumberType = 8;
+pub const kCFNumberIntType: CFNumberType = 9;
+pub const kCFNumberLongType: CFNumberType = 10;
+pub const kCFNumberLongLongType: CFNumberType = 11;
+pub const kCFNumberFloatType: CFNumberType = 12;
+pub const kCFNumberDoubleType: CFNumberType = 13;
+pub const kCFNumberCFIndexType: CFNumberType = 14;
pub const kCFNumberNSIntegerType: CFNumberType = 15;
-pub const kCFNumberCGFloatType: CFNumberType = 16;
-pub const kCFNumberMaxType: CFNumberType = 16;
+pub const kCFNumberCGFloatType: CFNumberType = 16;
+pub const kCFNumberMaxType: CFNumberType = 16;
// This is an enum due to zero-sized types warnings.
// For more details see https://github.com/rust-lang/rust/issues/27303
@@ -43,23 +43,45 @@ pub enum __CFNumber {}
pub type CFNumberRef = *const __CFNumber;
-extern {
+extern "C" {
/*
* CFNumber.h
*/
pub static kCFBooleanTrue: CFBooleanRef;
pub static kCFBooleanFalse: CFBooleanRef;
+ pub static kCFNumberPositiveInfinity: CFNumberRef;
+ pub static kCFNumberNegativeInfinity: CFNumberRef;
+ pub static kCFNumberNaN: CFNumberRef;
- pub fn CFBooleanGetTypeID() -> CFTypeID;
- pub fn CFBooleanGetValue(boolean: CFBooleanRef) -> bool;
+ /* Creating a Number */
+ pub fn CFNumberCreate(
+ allocator: CFAllocatorRef,
+ theType: CFNumberType,
+ valuePtr: *const c_void,
+ ) -> CFNumberRef;
- pub fn CFNumberCreate(allocator: CFAllocatorRef, theType: CFNumberType, valuePtr: *const c_void)
- -> CFNumberRef;
- //fn CFNumberGetByteSize
- pub fn CFNumberGetValue(number: CFNumberRef, theType: CFNumberType, valuePtr: *mut c_void) -> bool;
- pub fn CFNumberCompare(date: CFNumberRef, other: CFNumberRef, context: *mut c_void) -> CFComparisonResult;
- pub fn CFNumberGetTypeID() -> CFTypeID;
+ /* Getting Information About Numbers */
+ pub fn CFNumberGetByteSize(number: CFNumberRef) -> CFIndex;
pub fn CFNumberGetType(number: CFNumberRef) -> CFNumberType;
+ pub fn CFNumberGetValue(
+ number: CFNumberRef,
+ theType: CFNumberType,
+ valuePtr: *mut c_void,
+ ) -> bool;
+ pub fn CFNumberIsFloatType(number: CFNumberRef) -> Boolean;
+
+ /* Comparing Numbers */
+ pub fn CFNumberCompare(
+ date: CFNumberRef,
+ other: CFNumberRef,
+ context: *mut c_void,
+ ) -> CFComparisonResult;
+
+ /* Getting the CFNumber Type ID */
+ pub fn CFNumberGetTypeID() -> CFTypeID;
+
+ pub fn CFBooleanGetValue(boolean: CFBooleanRef) -> bool;
+ pub fn CFBooleanGetTypeID() -> CFTypeID;
}
#[cfg(test)]
diff --git a/third_party/rust/core-foundation-sys/src/number_formatter.rs b/third_party/rust/core-foundation-sys/src/number_formatter.rs
new file mode 100644
index 0000000000..cae7b11b00
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/number_formatter.rs
@@ -0,0 +1,163 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::{c_double, c_void};
+
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFRange, CFTypeID, CFTypeRef};
+use crate::locale::CFLocaleRef;
+use crate::number::{CFNumberRef, CFNumberType};
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFNumberFormatter(c_void);
+
+pub type CFNumberFormatterRef = *mut __CFNumberFormatter;
+
+pub type CFNumberFormatterKey = CFStringRef;
+pub type CFNumberFormatterStyle = CFIndex;
+pub type CFNumberFormatterOptionFlags = CFOptionFlags;
+pub type CFNumberFormatterRoundingMode = CFIndex;
+pub type CFNumberFormatterPadPosition = CFIndex;
+
+/* Number Formatter Styles */
+pub const kCFNumberFormatterNoStyle: CFNumberFormatterStyle = 0;
+pub const kCFNumberFormatterDecimalStyle: CFNumberFormatterStyle = 1;
+pub const kCFNumberFormatterCurrencyStyle: CFNumberFormatterStyle = 2;
+pub const kCFNumberFormatterPercentStyle: CFNumberFormatterStyle = 3;
+pub const kCFNumberFormatterScientificStyle: CFNumberFormatterStyle = 4;
+pub const kCFNumberFormatterSpellOutStyle: CFNumberFormatterStyle = 5;
+//pub const kCFNumberFormatterOrdinalStyle: CFNumberFormatterStyle = 6; // macos(10.11)+
+//pub const kCFNumberFormatterCurrencyISOCodeStyle: CFNumberFormatterStyle = 8; // macos(10.11)+
+//pub const kCFNumberFormatterCurrencyPluralStyle: CFNumberFormatterStyle = 9; // macos(10.11)+
+//pub const kCFNumberFormatterCurrencyAccountingStyle: CFNumberFormatterStyle = 10; // macos(10.11)+
+
+/* Number Format Options */
+pub const kCFNumberFormatterParseIntegersOnly: CFNumberFormatterOptionFlags = 1;
+
+/* CFNumberFormatterRoundingMode */
+pub const kCFNumberFormatterRoundCeiling: CFNumberFormatterRoundingMode = 0;
+pub const kCFNumberFormatterRoundFloor: CFNumberFormatterRoundingMode = 1;
+pub const kCFNumberFormatterRoundDown: CFNumberFormatterRoundingMode = 2;
+pub const kCFNumberFormatterRoundUp: CFNumberFormatterRoundingMode = 3;
+pub const kCFNumberFormatterRoundHalfEven: CFNumberFormatterRoundingMode = 4;
+pub const kCFNumberFormatterRoundHalfDown: CFNumberFormatterRoundingMode = 5;
+pub const kCFNumberFormatterRoundHalfUp: CFNumberFormatterRoundingMode = 6;
+
+/* Padding Positions */
+pub const kCFNumberFormatterPadBeforePrefix: CFNumberFormatterPadPosition = 0;
+pub const kCFNumberFormatterPadAfterPrefix: CFNumberFormatterPadPosition = 1;
+pub const kCFNumberFormatterPadBeforeSuffix: CFNumberFormatterPadPosition = 2;
+pub const kCFNumberFormatterPadAfterSuffix: CFNumberFormatterPadPosition = 3;
+
+extern "C" {
+ /*
+ * CFNumberFormatter.h
+ */
+
+ /* Number Formatter Property Keys */
+ // The values for these keys are all CFType objects.
+ // The specific types for each key are specified above.
+ pub static kCFNumberFormatterCurrencyCode: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterDecimalSeparator: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterCurrencyDecimalSeparator: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterAlwaysShowDecimalSeparator: CFNumberFormatterKey; // CFBoolean
+ pub static kCFNumberFormatterGroupingSeparator: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterUseGroupingSeparator: CFNumberFormatterKey; // CFBoolean
+ pub static kCFNumberFormatterPercentSymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterZeroSymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterNaNSymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterInfinitySymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterMinusSign: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterPlusSign: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterCurrencySymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterExponentSymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterMinIntegerDigits: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterMaxIntegerDigits: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterMinFractionDigits: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterMaxFractionDigits: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterGroupingSize: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterSecondaryGroupingSize: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterRoundingMode: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterRoundingIncrement: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterFormatWidth: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterPaddingPosition: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterPaddingCharacter: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterDefaultFormat: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterMultiplier: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterPositivePrefix: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterPositiveSuffix: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterNegativePrefix: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterNegativeSuffix: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterPerMillSymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterInternationalCurrencySymbol: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterCurrencyGroupingSeparator: CFNumberFormatterKey; // CFString
+ pub static kCFNumberFormatterIsLenient: CFNumberFormatterKey; // CFBoolean
+ pub static kCFNumberFormatterUseSignificantDigits: CFNumberFormatterKey; // CFBoolean
+ pub static kCFNumberFormatterMinSignificantDigits: CFNumberFormatterKey; // CFNumber
+ pub static kCFNumberFormatterMaxSignificantDigits: CFNumberFormatterKey; // CFNumber
+
+ /* Creating a Number Formatter */
+ pub fn CFNumberFormatterCreate(
+ allocator: CFAllocatorRef,
+ locale: CFLocaleRef,
+ style: CFNumberFormatterStyle,
+ ) -> CFNumberFormatterRef;
+
+ /* Configuring a Number Formatter */
+ pub fn CFNumberFormatterSetFormat(formatter: CFNumberFormatterRef, formatString: CFStringRef);
+ pub fn CFNumberFormatterSetProperty(
+ formatter: CFNumberFormatterRef,
+ key: CFNumberFormatterKey,
+ value: CFTypeRef,
+ );
+
+ /* Formatting Values */
+ pub fn CFNumberFormatterCreateNumberFromString(
+ allocator: CFAllocatorRef,
+ formatter: CFNumberFormatterRef,
+ string: CFStringRef,
+ rangep: *mut CFRange,
+ options: CFOptionFlags,
+ ) -> CFNumberRef;
+ pub fn CFNumberFormatterCreateStringWithNumber(
+ allocator: CFAllocatorRef,
+ formatter: CFNumberFormatterRef,
+ number: CFNumberRef,
+ ) -> CFStringRef;
+ pub fn CFNumberFormatterCreateStringWithValue(
+ allocator: CFAllocatorRef,
+ formatter: CFNumberFormatterRef,
+ numberType: CFNumberType,
+ valuePtr: *const c_void,
+ ) -> CFStringRef;
+ pub fn CFNumberFormatterGetDecimalInfoForCurrencyCode(
+ currencyCode: CFStringRef,
+ defaultFractionDigits: *mut i32,
+ roundingIncrement: *mut c_double,
+ ) -> Boolean;
+ pub fn CFNumberFormatterGetValueFromString(
+ formatter: CFNumberFormatterRef,
+ string: CFStringRef,
+ rangep: *mut CFRange,
+ numberType: CFNumberType,
+ valuePtr: *mut c_void,
+ ) -> Boolean;
+
+ /* Examining a Number Formatter */
+ pub fn CFNumberFormatterCopyProperty(
+ formatter: CFNumberFormatterRef,
+ key: CFNumberFormatterKey,
+ ) -> CFTypeRef;
+ pub fn CFNumberFormatterGetFormat(formatter: CFNumberFormatterRef) -> CFStringRef;
+ pub fn CFNumberFormatterGetLocale(formatter: CFNumberFormatterRef) -> CFLocaleRef;
+ pub fn CFNumberFormatterGetStyle(formatter: CFNumberFormatterRef) -> CFNumberFormatterStyle;
+
+ /* Getting the CFNumberFormatter Type ID */
+ pub fn CFNumberFormatterGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/plugin.rs b/third_party/rust/core-foundation-sys/src/plugin.rs
new file mode 100644
index 0000000000..fa236777c2
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/plugin.rs
@@ -0,0 +1,99 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::array::CFArrayRef;
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFTypeID};
+use crate::bundle::{CFBundleRef, CFPlugInRef};
+use crate::string::CFStringRef;
+use crate::url::CFURLRef;
+use crate::uuid::CFUUIDRef;
+
+#[repr(C)]
+pub struct __CFPlugInInstance(c_void);
+pub type CFPlugInInstanceRef = *mut __CFPlugInInstance;
+
+pub type CFPlugInDynamicRegisterFunction = extern "C" fn(plugIn: CFPlugInRef);
+pub type CFPlugInUnloadFunction = extern "C" fn(plugIn: CFPlugInRef);
+pub type CFPlugInFactoryFunction =
+ extern "C" fn(allocator: CFAllocatorRef, typeUUID: CFUUIDRef) -> *mut c_void;
+
+pub type CFPlugInInstanceGetInterfaceFunction = extern "C" fn(
+ instance: CFPlugInInstanceRef,
+ interfaceName: CFStringRef,
+ ftbl: *mut *mut c_void,
+) -> Boolean;
+pub type CFPlugInInstanceDeallocateInstanceDataFunction = extern "C" fn(instanceData: *mut c_void);
+
+extern "C" {
+ /*
+ * CFPlugIn.h
+ */
+
+ /* CFPlugIn */
+ /* Information Property List Keys */
+ pub static kCFPlugInDynamicRegistrationKey: CFStringRef;
+ pub static kCFPlugInDynamicRegisterFunctionKey: CFStringRef;
+ pub static kCFPlugInUnloadFunctionKey: CFStringRef;
+ pub static kCFPlugInFactoriesKey: CFStringRef;
+ pub static kCFPlugInTypesKey: CFStringRef;
+
+ /* Creating Plug-ins */
+ pub fn CFPlugInCreate(allocator: CFAllocatorRef, plugInURL: CFURLRef) -> CFPlugInRef;
+ pub fn CFPlugInInstanceCreate(
+ allocator: CFAllocatorRef,
+ factoryUUID: CFUUIDRef,
+ typeUUID: CFUUIDRef,
+ ) -> *mut c_void;
+
+ /* Registration */
+ pub fn CFPlugInRegisterFactoryFunction(
+ factoryUUID: CFUUIDRef,
+ func: CFPlugInFactoryFunction,
+ ) -> Boolean;
+ pub fn CFPlugInRegisterFactoryFunctionByName(
+ CfactoryUUID: CFUUIDRef,
+ plugIn: CFPlugInRef,
+ functionName: CFStringRef,
+ ) -> Boolean;
+ pub fn CFPlugInRegisterPlugInType(factoryUUID: CFUUIDRef, typeUUID: CFUUIDRef) -> Boolean;
+ pub fn CFPlugInUnregisterFactory(factoryUUID: CFUUIDRef) -> Boolean;
+ pub fn CFPlugInUnregisterPlugInType(factoryUUID: CFUUIDRef, typeUUID: CFUUIDRef) -> Boolean;
+
+ /* CFPlugIn Miscellaneous Functions */
+ pub fn CFPlugInAddInstanceForFactory(factoryID: CFUUIDRef);
+ pub fn CFPlugInFindFactoriesForPlugInType(typeUUID: CFUUIDRef) -> CFArrayRef;
+ pub fn CFPlugInFindFactoriesForPlugInTypeInPlugIn(
+ typeUUID: CFUUIDRef,
+ plugIn: CFPlugInRef,
+ ) -> CFArrayRef;
+ pub fn CFPlugInGetBundle(plugIn: CFPlugInRef) -> CFBundleRef;
+ pub fn CFPlugInGetTypeID() -> CFTypeID;
+ pub fn CFPlugInIsLoadOnDemand(plugIn: CFPlugInRef) -> Boolean;
+ pub fn CFPlugInRemoveInstanceForFactory(factoryID: CFUUIDRef);
+ pub fn CFPlugInSetLoadOnDemand(plugIn: CFPlugInRef, flag: Boolean);
+
+ /* CFPlugInInstance: deprecated */
+ pub fn CFPlugInInstanceCreateWithInstanceDataSize(
+ allocator: CFAllocatorRef,
+ instanceDataSize: CFIndex,
+ deallocateInstanceFunction: CFPlugInInstanceDeallocateInstanceDataFunction,
+ factoryName: CFStringRef,
+ getInterfaceFunction: CFPlugInInstanceGetInterfaceFunction,
+ ) -> CFPlugInInstanceRef;
+ pub fn CFPlugInInstanceGetFactoryName(instance: CFPlugInInstanceRef) -> CFStringRef;
+ pub fn CFPlugInInstanceGetInstanceData(instance: CFPlugInInstanceRef) -> *mut c_void;
+ pub fn CFPlugInInstanceGetInterfaceFunctionTable(
+ instance: CFPlugInInstanceRef,
+ interfaceName: CFStringRef,
+ ftbl: *mut *mut c_void,
+ ) -> Boolean;
+ pub fn CFPlugInInstanceGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/preferences.rs b/third_party/rust/core-foundation-sys/src/preferences.rs
new file mode 100644
index 0000000000..0899938e58
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/preferences.rs
@@ -0,0 +1,103 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::array::CFArrayRef;
+use crate::base::{Boolean, CFIndex};
+use crate::dictionary::CFDictionaryRef;
+use crate::propertylist::CFPropertyListRef;
+use crate::string::CFStringRef;
+
+extern "C" {
+ /*
+ * CFPreferences.h
+ */
+ /* Application, Host, and User Keys */
+ pub static kCFPreferencesAnyApplication: CFStringRef;
+ pub static kCFPreferencesCurrentApplication: CFStringRef;
+ pub static kCFPreferencesAnyHost: CFStringRef;
+ pub static kCFPreferencesCurrentHost: CFStringRef;
+ pub static kCFPreferencesAnyUser: CFStringRef;
+ pub static kCFPreferencesCurrentUser: CFStringRef;
+
+ /* Getting Preference Values */
+ pub fn CFPreferencesCopyAppValue(
+ key: CFStringRef,
+ applicationID: CFStringRef,
+ ) -> CFPropertyListRef;
+ pub fn CFPreferencesCopyKeyList(
+ applicationID: CFStringRef,
+ userName: CFStringRef,
+ hostName: CFStringRef,
+ ) -> CFArrayRef;
+ pub fn CFPreferencesCopyMultiple(
+ keysToFetch: CFArrayRef,
+ applicationID: CFStringRef,
+ userName: CFStringRef,
+ hostName: CFStringRef,
+ ) -> CFDictionaryRef;
+ pub fn CFPreferencesCopyValue(
+ key: CFStringRef,
+ applicationID: CFStringRef,
+ userName: CFStringRef,
+ hostName: CFStringRef,
+ ) -> CFPropertyListRef;
+ pub fn CFPreferencesGetAppBooleanValue(
+ key: CFStringRef,
+ applicationID: CFStringRef,
+ keyExistsAndHasValidFormat: *mut Boolean,
+ ) -> Boolean;
+ pub fn CFPreferencesGetAppIntegerValue(
+ key: CFStringRef,
+ applicationID: CFStringRef,
+ keyExistsAndHasValidFormat: *mut Boolean,
+ ) -> CFIndex;
+
+ /* Setting Preference Values */
+ pub fn CFPreferencesSetAppValue(
+ key: CFStringRef,
+ value: CFPropertyListRef,
+ applicationID: CFStringRef,
+ );
+ pub fn CFPreferencesSetMultiple(
+ keysToSet: CFDictionaryRef,
+ keysToRemove: CFArrayRef,
+ applicationID: CFStringRef,
+ userName: CFStringRef,
+ hostName: CFStringRef,
+ );
+ pub fn CFPreferencesSetValue(
+ key: CFStringRef,
+ value: CFPropertyListRef,
+ applicationID: CFStringRef,
+ userName: CFStringRef,
+ hostName: CFStringRef,
+ );
+
+ /* Synchronizing Preferences */
+ pub fn CFPreferencesAppSynchronize(applicationID: CFStringRef) -> Boolean;
+ pub fn CFPreferencesSynchronize(
+ applicationID: CFStringRef,
+ userName: CFStringRef,
+ hostName: CFStringRef,
+ ) -> Boolean;
+
+ /* Adding and Removing Suite Preferences */
+ pub fn CFPreferencesAddSuitePreferencesToApp(applicationID: CFStringRef, suiteID: CFStringRef);
+ pub fn CFPreferencesRemoveSuitePreferencesFromApp(
+ applicationID: CFStringRef,
+ suiteID: CFStringRef,
+ );
+
+ /* Miscellaneous Functions */
+ pub fn CFPreferencesAppValueIsForced(key: CFStringRef, applicationID: CFStringRef) -> Boolean;
+ pub fn CFPreferencesCopyApplicationList(
+ userName: CFStringRef,
+ hostName: CFStringRef,
+ ) -> CFArrayRef; // deprecated since macos 10.9
+}
diff --git a/third_party/rust/core-foundation-sys/src/propertylist.rs b/third_party/rust/core-foundation-sys/src/propertylist.rs
index 574c4d13f3..d4ceb1b0c0 100644
--- a/third_party/rust/core-foundation-sys/src/propertylist.rs
+++ b/third_party/rust/core-foundation-sys/src/propertylist.rs
@@ -7,9 +7,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeRef};
-use data::CFDataRef;
-use error::CFErrorRef;
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeRef};
+use crate::data::CFDataRef;
+use crate::error::CFErrorRef;
+use crate::stream::{CFReadStreamRef, CFWriteStreamRef};
+use crate::string::CFStringRef;
pub type CFPropertyListRef = CFTypeRef;
@@ -23,24 +25,80 @@ pub const kCFPropertyListImmutable: CFPropertyListMutabilityOptions = 0;
pub const kCFPropertyListMutableContainers: CFPropertyListMutabilityOptions = 1;
pub const kCFPropertyListMutableContainersAndLeaves: CFPropertyListMutabilityOptions = 2;
+/* Reading and Writing Error Codes */
+pub const kCFPropertyListReadCorruptError: CFIndex = 3840;
+pub const kCFPropertyListReadUnknownVersionError: CFIndex = 3841;
+pub const kCFPropertyListReadStreamError: CFIndex = 3842;
+pub const kCFPropertyListWriteStreamError: CFIndex = 3851;
+
extern "C" {
- // CFPropertyList.h
- //
-
- // fn CFPropertyListCreateDeepCopy
- // fn CFPropertyListIsValid
- pub fn CFPropertyListCreateWithData(allocator: CFAllocatorRef,
- data: CFDataRef,
- options: CFPropertyListMutabilityOptions,
- format: *mut CFPropertyListFormat,
- error: *mut CFErrorRef)
- -> CFPropertyListRef;
- // fn CFPropertyListCreateWithStream
- // fn CFPropertyListWrite
- pub fn CFPropertyListCreateData(allocator: CFAllocatorRef,
- propertyList: CFPropertyListRef,
- format: CFPropertyListFormat,
- options: CFOptionFlags,
- error: *mut CFErrorRef)
- -> CFDataRef;
+ /*
+ * CFPropertyList.h
+ */
+
+ /* Creating a Property List */
+ pub fn CFPropertyListCreateWithData(
+ allocator: CFAllocatorRef,
+ data: CFDataRef,
+ options: CFPropertyListMutabilityOptions,
+ format: *mut CFPropertyListFormat,
+ error: *mut CFErrorRef,
+ ) -> CFPropertyListRef;
+ pub fn CFPropertyListCreateWithStream(
+ allocator: CFAllocatorRef,
+ stream: CFReadStreamRef,
+ streamLength: CFIndex,
+ options: CFOptionFlags,
+ format: *mut CFPropertyListFormat,
+ error: *mut CFErrorRef,
+ ) -> CFPropertyListRef;
+ pub fn CFPropertyListCreateDeepCopy(
+ allocator: CFAllocatorRef,
+ propertyList: CFPropertyListRef,
+ mutabilityOption: CFOptionFlags,
+ ) -> CFPropertyListRef;
+ pub fn CFPropertyListCreateFromXMLData(
+ allocator: CFAllocatorRef,
+ xmlData: CFDataRef,
+ mutabilityOption: CFOptionFlags,
+ errorString: *mut CFStringRef,
+ ) -> CFPropertyListRef; // deprecated
+ pub fn CFPropertyListCreateFromStream(
+ allocator: CFAllocatorRef,
+ stream: CFReadStreamRef,
+ streamLength: CFIndex,
+ mutabilityOption: CFOptionFlags,
+ format: *mut CFPropertyListFormat,
+ errorString: *mut CFStringRef,
+ ) -> CFPropertyListRef; // deprecated
+
+ /* Exporting a Property List */
+ pub fn CFPropertyListCreateData(
+ allocator: CFAllocatorRef,
+ propertyList: CFPropertyListRef,
+ format: CFPropertyListFormat,
+ options: CFOptionFlags,
+ error: *mut CFErrorRef,
+ ) -> CFDataRef;
+ pub fn CFPropertyListWrite(
+ propertyList: CFPropertyListRef,
+ stream: CFWriteStreamRef,
+ format: CFPropertyListFormat,
+ options: CFOptionFlags,
+ error: *mut CFErrorRef,
+ ) -> CFIndex;
+ pub fn CFPropertyListCreateXMLData(
+ allocator: CFAllocatorRef,
+ propertyList: CFPropertyListRef,
+ ) -> CFDataRef; // deprecated
+ pub fn CFPropertyListWriteToStream(
+ propertyList: CFPropertyListRef,
+ stream: CFWriteStreamRef,
+ format: CFPropertyListFormat,
+ errorString: *mut CFStringRef,
+ ) -> CFIndex;
+
+ /* Validating a Property List */
+ pub fn CFPropertyListIsValid(plist: CFPropertyListRef, format: CFPropertyListFormat)
+ -> Boolean;
}
diff --git a/third_party/rust/core-foundation-sys/src/runloop.rs b/third_party/rust/core-foundation-sys/src/runloop.rs
index 53035a2e75..5d5fda7a01 100644
--- a/third_party/rust/core-foundation-sys/src/runloop.rs
+++ b/third_party/rust/core-foundation-sys/src/runloop.rs
@@ -9,10 +9,12 @@
use std::os::raw::c_void;
-use array::CFArrayRef;
-use base::{Boolean, CFIndex, CFTypeID, CFAllocatorRef, CFOptionFlags, CFHashCode, mach_port_t};
-use date::{CFAbsoluteTime, CFTimeInterval};
-use string::CFStringRef;
+use crate::array::CFArrayRef;
+use crate::base::{
+ mach_port_t, Boolean, CFAllocatorRef, CFHashCode, CFIndex, CFOptionFlags, CFTypeID,
+};
+use crate::date::{CFAbsoluteTime, CFTimeInterval};
+use crate::string::CFStringRef;
#[repr(C)]
pub struct __CFRunLoop(c_void);
@@ -30,135 +32,225 @@ pub struct __CFRunLoopObserver(c_void);
pub type CFRunLoopObserverRef = *mut __CFRunLoopObserver;
// Reasons for CFRunLoopRunInMode() to Return
-pub const kCFRunLoopRunFinished: i32 = 1;
-pub const kCFRunLoopRunStopped: i32 = 2;
-pub const kCFRunLoopRunTimedOut: i32 = 3;
+pub const kCFRunLoopRunFinished: i32 = 1;
+pub const kCFRunLoopRunStopped: i32 = 2;
+pub const kCFRunLoopRunTimedOut: i32 = 3;
pub const kCFRunLoopRunHandledSource: i32 = 4;
// Run Loop Observer Activities
//typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
pub type CFRunLoopActivity = CFOptionFlags;
-pub const kCFRunLoopEntry: CFOptionFlags = 1 << 0;
-pub const kCFRunLoopBeforeTimers: CFOptionFlags = 1 << 1;
+pub const kCFRunLoopEntry: CFOptionFlags = 1 << 0;
+pub const kCFRunLoopBeforeTimers: CFOptionFlags = 1 << 1;
pub const kCFRunLoopBeforeSources: CFOptionFlags = 1 << 2;
pub const kCFRunLoopBeforeWaiting: CFOptionFlags = 1 << 5;
-pub const kCFRunLoopAfterWaiting: CFOptionFlags = 1 << 6;
-pub const kCFRunLoopExit: CFOptionFlags = 1 << 7;
+pub const kCFRunLoopAfterWaiting: CFOptionFlags = 1 << 6;
+pub const kCFRunLoopExit: CFOptionFlags = 1 << 7;
pub const kCFRunLoopAllActivities: CFOptionFlags = 0x0FFFFFFF;
#[repr(C)]
+#[derive(Debug, Clone, Copy)]
pub struct CFRunLoopSourceContext {
pub version: CFIndex,
pub info: *mut c_void,
- pub retain: Option<extern "C" fn (info: *const c_void) -> *const c_void>,
- pub release: Option<extern "C" fn (info: *const c_void)>,
- pub copyDescription: Option<extern "C" fn (info: *const c_void) -> CFStringRef>,
- pub equal: Option<extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean>,
- pub hash: Option<extern "C" fn (info: *const c_void) -> CFHashCode>,
- pub schedule: Option<extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef)>,
- pub cancel: Option<extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef)>,
- pub perform: extern "C" fn (info: *const c_void),
+ pub retain: Option<extern "C" fn(info: *const c_void) -> *const c_void>,
+ pub release: Option<extern "C" fn(info: *const c_void)>,
+ pub copyDescription: Option<extern "C" fn(info: *const c_void) -> CFStringRef>,
+ pub equal: Option<extern "C" fn(info1: *const c_void, info2: *const c_void) -> Boolean>,
+ pub hash: Option<extern "C" fn(info: *const c_void) -> CFHashCode>,
+ pub schedule: Option<extern "C" fn(info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef)>,
+ pub cancel: Option<extern "C" fn(info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef)>,
+ pub perform: extern "C" fn(info: *const c_void),
}
#[repr(C)]
+#[derive(Debug, Clone, Copy)]
pub struct CFRunLoopSourceContext1 {
pub version: CFIndex,
pub info: *mut c_void,
- pub retain: Option<extern "C" fn (info: *const c_void) -> *const c_void>,
- pub release: Option<extern "C" fn (info: *const c_void)>,
- pub copyDescription: Option<extern "C" fn (info: *const c_void) -> CFStringRef>,
- pub equal: Option<extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean>,
- pub hash: Option<extern "C" fn (info: *const c_void) -> CFHashCode>,
- // note that the following two fields are platform dependent in the C header, the ones here are for macOS
- pub getPort: extern "C" fn (info: *mut c_void) -> mach_port_t,
- pub perform: extern "C" fn (msg: *mut c_void, size: CFIndex, allocator: CFAllocatorRef, info: *mut c_void) -> *mut c_void,
+ pub retain: Option<extern "C" fn(info: *const c_void) -> *const c_void>,
+ pub release: Option<extern "C" fn(info: *const c_void)>,
+ pub copyDescription: Option<extern "C" fn(info: *const c_void) -> CFStringRef>,
+ pub equal: Option<extern "C" fn(info1: *const c_void, info2: *const c_void) -> Boolean>,
+ pub hash: Option<extern "C" fn(info: *const c_void) -> CFHashCode>,
+
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ pub getPort: extern "C" fn(info: *mut c_void) -> mach_port_t,
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ pub perform: extern "C" fn(
+ msg: *mut c_void,
+ size: CFIndex,
+ allocator: CFAllocatorRef,
+ info: *mut c_void,
+ ) -> *mut c_void,
+
+ #[cfg(not(any(target_os = "macos", target_os = "ios")))]
+ pub getPort: extern "C" fn(info: *mut c_void) -> *mut c_void,
+ #[cfg(not(any(target_os = "macos", target_os = "ios")))]
+ pub perform: extern "C" fn(info: *mut c_void) -> *mut c_void,
}
#[repr(C)]
+#[derive(Debug, Clone, Copy)]
pub struct CFRunLoopObserverContext {
pub version: CFIndex,
pub info: *mut c_void,
- pub retain: Option<extern "C" fn (info: *const c_void) -> *const c_void>,
- pub release: Option<extern "C" fn (info: *const c_void)>,
- pub copyDescription: Option<extern "C" fn (info: *const c_void) -> CFStringRef>,
+ pub retain: Option<extern "C" fn(info: *const c_void) -> *const c_void>,
+ pub release: Option<extern "C" fn(info: *const c_void)>,
+ pub copyDescription: Option<extern "C" fn(info: *const c_void) -> CFStringRef>,
}
-pub type CFRunLoopObserverCallBack = extern "C" fn (observer: CFRunLoopObserverRef, activity: CFRunLoopActivity, info: *mut c_void);
+pub type CFRunLoopObserverCallBack =
+ extern "C" fn(observer: CFRunLoopObserverRef, activity: CFRunLoopActivity, info: *mut c_void);
#[repr(C)]
+#[derive(Clone, Copy, Debug)]
pub struct CFRunLoopTimerContext {
pub version: CFIndex,
pub info: *mut c_void,
- pub retain: Option<extern "C" fn (info: *const c_void) -> *const c_void>,
- pub release: Option<extern "C" fn (info: *const c_void)>,
- pub copyDescription: Option<extern "C" fn (info: *const c_void) -> CFStringRef>,
+ pub retain: Option<extern "C" fn(info: *const c_void) -> *const c_void>,
+ pub release: Option<extern "C" fn(info: *const c_void)>,
+ pub copyDescription: Option<extern "C" fn(info: *const c_void) -> CFStringRef>,
}
-pub type CFRunLoopTimerCallBack = extern "C" fn (timer: CFRunLoopTimerRef, info: *mut c_void);
+pub type CFRunLoopTimerCallBack = extern "C" fn(timer: CFRunLoopTimerRef, info: *mut c_void);
#[repr(C)]
pub struct __CFRunLoopTimer(c_void);
pub type CFRunLoopTimerRef = *mut __CFRunLoopTimer;
-extern {
+extern "C" {
/*
* CFRunLoop.h
*/
+
pub static kCFRunLoopDefaultMode: CFStringRef;
pub static kCFRunLoopCommonModes: CFStringRef;
- pub fn CFRunLoopGetTypeID() -> CFTypeID;
+
+ /* CFRunLoop */
+ /* Getting a Run Loop */
pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;
pub fn CFRunLoopGetMain() -> CFRunLoopRef;
- pub fn CFRunLoopCopyCurrentMode(rl: CFRunLoopRef) -> CFStringRef;
- pub fn CFRunLoopCopyAllModes(rl: CFRunLoopRef) -> CFArrayRef;
- pub fn CFRunLoopAddCommonMode(rl: CFRunLoopRef, mode: CFStringRef);
- pub fn CFRunLoopGetNextTimerFireDate(rl: CFRunLoopRef, mode: CFStringRef) -> CFAbsoluteTime;
+
+ /* Starting and Stopping a Run Loop */
pub fn CFRunLoopRun();
- pub fn CFRunLoopRunInMode(mode: CFStringRef, seconds: CFTimeInterval, returnAfterSourceHandled: Boolean) -> i32;
- pub fn CFRunLoopIsWaiting(rl: CFRunLoopRef) -> Boolean;
+ pub fn CFRunLoopRunInMode(
+ mode: CFStringRef,
+ seconds: CFTimeInterval,
+ returnAfterSourceHandled: Boolean,
+ ) -> i32;
pub fn CFRunLoopWakeUp(rl: CFRunLoopRef);
pub fn CFRunLoopStop(rl: CFRunLoopRef);
- // fn CFRunLoopPerformBlock(rl: CFRunLoopRef, mode: CFTypeRef, block: void (^)(void));
- pub fn CFRunLoopContainsSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef) -> Boolean;
+ pub fn CFRunLoopIsWaiting(rl: CFRunLoopRef) -> Boolean;
+
+ /* Managing Sources */
pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
+ pub fn CFRunLoopContainsSource(
+ rl: CFRunLoopRef,
+ source: CFRunLoopSourceRef,
+ mode: CFStringRef,
+ ) -> Boolean;
pub fn CFRunLoopRemoveSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
- pub fn CFRunLoopContainsObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef) -> Boolean;
- pub fn CFRunLoopAddObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef);
- pub fn CFRunLoopRemoveObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef);
- pub fn CFRunLoopContainsTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef) -> Boolean;
+
+ /* Managing Observers */
+ pub fn CFRunLoopAddObserver(
+ rl: CFRunLoopRef,
+ observer: CFRunLoopObserverRef,
+ mode: CFStringRef,
+ );
+ pub fn CFRunLoopContainsObserver(
+ rl: CFRunLoopRef,
+ observer: CFRunLoopObserverRef,
+ mode: CFStringRef,
+ ) -> Boolean;
+ pub fn CFRunLoopRemoveObserver(
+ rl: CFRunLoopRef,
+ observer: CFRunLoopObserverRef,
+ mode: CFStringRef,
+ );
+
+ /* Managing Run Loop Modes */
+ pub fn CFRunLoopAddCommonMode(rl: CFRunLoopRef, mode: CFStringRef);
+ pub fn CFRunLoopCopyAllModes(rl: CFRunLoopRef) -> CFArrayRef;
+ pub fn CFRunLoopCopyCurrentMode(rl: CFRunLoopRef) -> CFStringRef;
+
+ /* Managing Timers */
pub fn CFRunLoopAddTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef);
+ pub fn CFRunLoopGetNextTimerFireDate(rl: CFRunLoopRef, mode: CFStringRef) -> CFAbsoluteTime;
pub fn CFRunLoopRemoveTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef);
+ pub fn CFRunLoopContainsTimer(
+ rl: CFRunLoopRef,
+ timer: CFRunLoopTimerRef,
+ mode: CFStringRef,
+ ) -> Boolean;
- pub fn CFRunLoopSourceGetTypeID() -> CFTypeID;
- pub fn CFRunLoopSourceCreate(allocator: CFAllocatorRef, order: CFIndex, context: *mut CFRunLoopSourceContext) -> CFRunLoopSourceRef;
+ /* Scheduling Blocks */
+ // fn CFRunLoopPerformBlock(rl: CFRunLoopRef, mode: CFTypeRef, block: void (^)(void));
+
+ /* Getting the CFRunLoop Type ID */
+ pub fn CFRunLoopGetTypeID() -> CFTypeID;
+
+ /* CFRunLoopSource */
+ /* CFRunLoopSource Miscellaneous Functions */
+ pub fn CFRunLoopSourceCreate(
+ allocator: CFAllocatorRef,
+ order: CFIndex,
+ context: *mut CFRunLoopSourceContext,
+ ) -> CFRunLoopSourceRef;
+ pub fn CFRunLoopSourceGetContext(
+ source: CFRunLoopSourceRef,
+ context: *mut CFRunLoopSourceContext,
+ );
pub fn CFRunLoopSourceGetOrder(source: CFRunLoopSourceRef) -> CFIndex;
+ pub fn CFRunLoopSourceGetTypeID() -> CFTypeID;
pub fn CFRunLoopSourceInvalidate(source: CFRunLoopSourceRef);
pub fn CFRunLoopSourceIsValid(source: CFRunLoopSourceRef) -> Boolean;
- pub fn CFRunLoopSourceGetContext(source: CFRunLoopSourceRef, context: *mut CFRunLoopSourceContext);
pub fn CFRunLoopSourceSignal(source: CFRunLoopSourceRef);
- pub fn CFRunLoopObserverGetTypeID() -> CFTypeID;
- pub fn CFRunLoopObserverCreate(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, callout: CFRunLoopObserverCallBack, context: *mut CFRunLoopObserverContext) -> CFRunLoopObserverRef;
+ /* CFRunLoopObserver */
+ /* CFRunLoopObserver Miscellaneous Functions */
// fn CFRunLoopObserverCreateWithHandler(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, block: void (^) (CFRunLoopObserverRef observer, CFRunLoopActivity activity)) -> CFRunLoopObserverRef;
- pub fn CFRunLoopObserverGetActivities(observer: CFRunLoopObserverRef) -> CFOptionFlags;
+ pub fn CFRunLoopObserverCreate(
+ allocator: CFAllocatorRef,
+ activities: CFOptionFlags,
+ repeats: Boolean,
+ order: CFIndex,
+ callout: CFRunLoopObserverCallBack,
+ context: *mut CFRunLoopObserverContext,
+ ) -> CFRunLoopObserverRef;
pub fn CFRunLoopObserverDoesRepeat(observer: CFRunLoopObserverRef) -> Boolean;
+ pub fn CFRunLoopObserverGetActivities(observer: CFRunLoopObserverRef) -> CFOptionFlags;
+ pub fn CFRunLoopObserverGetContext(
+ observer: CFRunLoopObserverRef,
+ context: *mut CFRunLoopObserverContext,
+ );
pub fn CFRunLoopObserverGetOrder(observer: CFRunLoopObserverRef) -> CFIndex;
+ pub fn CFRunLoopObserverGetTypeID() -> CFTypeID;
pub fn CFRunLoopObserverInvalidate(observer: CFRunLoopObserverRef);
pub fn CFRunLoopObserverIsValid(observer: CFRunLoopObserverRef) -> Boolean;
- pub fn CFRunLoopObserverGetContext(observer: CFRunLoopObserverRef, context: *mut CFRunLoopObserverContext);
- pub fn CFRunLoopTimerGetTypeID() -> CFTypeID;
- pub fn CFRunLoopTimerCreate(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimerRef;
+ /* CFRunLoopTimer */
+ /* CFRunLoopTimer Miscellaneous Functions */
// fn CFRunLoopTimerCreateWithHandler(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, block: void (^) (CFRunLoopTimerRef timer)) -> CFRunLoopTimerRef;
- pub fn CFRunLoopTimerGetNextFireDate(timer: CFRunLoopTimerRef) -> CFAbsoluteTime;
- pub fn CFRunLoopTimerSetNextFireDate(timer: CFRunLoopTimerRef, fireDate: CFAbsoluteTime);
- pub fn CFRunLoopTimerGetInterval(timer: CFRunLoopTimerRef) -> CFTimeInterval;
+ pub fn CFRunLoopTimerCreate(
+ allocator: CFAllocatorRef,
+ fireDate: CFAbsoluteTime,
+ interval: CFTimeInterval,
+ flags: CFOptionFlags,
+ order: CFIndex,
+ callout: CFRunLoopTimerCallBack,
+ context: *mut CFRunLoopTimerContext,
+ ) -> CFRunLoopTimerRef;
pub fn CFRunLoopTimerDoesRepeat(timer: CFRunLoopTimerRef) -> Boolean;
+ pub fn CFRunLoopTimerGetContext(timer: CFRunLoopTimerRef, context: *mut CFRunLoopTimerContext);
+ pub fn CFRunLoopTimerGetInterval(timer: CFRunLoopTimerRef) -> CFTimeInterval;
+ pub fn CFRunLoopTimerGetNextFireDate(timer: CFRunLoopTimerRef) -> CFAbsoluteTime;
pub fn CFRunLoopTimerGetOrder(timer: CFRunLoopTimerRef) -> CFIndex;
+ pub fn CFRunLoopTimerGetTypeID() -> CFTypeID;
pub fn CFRunLoopTimerInvalidate(timer: CFRunLoopTimerRef);
pub fn CFRunLoopTimerIsValid(timer: CFRunLoopTimerRef) -> Boolean;
- pub fn CFRunLoopTimerGetContext(timer: CFRunLoopTimerRef, context: *mut CFRunLoopTimerContext);
- pub fn CFRunLoopTimerGetTolerance(timer: CFRunLoopTimerRef) -> CFTimeInterval;
- pub fn CFRunLoopTimerSetTolerance(timer: CFRunLoopTimerRef, tolerance: CFTimeInterval);
+ pub fn CFRunLoopTimerSetNextFireDate(timer: CFRunLoopTimerRef, fireDate: CFAbsoluteTime);
+ pub fn CFRunLoopTimerGetTolerance(timer: CFRunLoopTimerRef) -> CFTimeInterval; //macos(10.9)+
+ pub fn CFRunLoopTimerSetTolerance(timer: CFRunLoopTimerRef, tolerance: CFTimeInterval); //macos(10.9)+
}
diff --git a/third_party/rust/core-foundation-sys/src/set.rs b/third_party/rust/core-foundation-sys/src/set.rs
index a5cc1b16f7..8141c5999d 100644
--- a/third_party/rust/core-foundation-sys/src/set.rs
+++ b/third_party/rust/core-foundation-sys/src/set.rs
@@ -9,15 +9,17 @@
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFIndex, CFTypeID, Boolean};
+use crate::base::{Boolean, CFAllocatorRef, CFHashCode, CFIndex, CFTypeID};
+use crate::string::CFStringRef;
-pub type CFSetApplierFunction = extern "C" fn (value: *const c_void,
- context: *const c_void);
-pub type CFSetRetainCallBack = *const u8;
-pub type CFSetReleaseCallBack = *const u8;
-pub type CFSetCopyDescriptionCallBack = *const u8;
-pub type CFSetEqualCallBack = *const u8;
-pub type CFSetHashCallBack = *const u8;
+pub type CFSetApplierFunction = extern "C" fn(value: *const c_void, context: *const c_void);
+pub type CFSetRetainCallBack =
+ extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
+pub type CFSetReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void);
+pub type CFSetCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef;
+pub type CFSetEqualCallBack =
+ extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
+pub type CFSetHashCallBack = extern "C" fn(value: *const c_void) -> CFHashCode;
#[repr(C)]
#[derive(Clone, Copy)]
@@ -34,17 +36,24 @@ pub struct CFSetCallBacks {
pub struct __CFSet(c_void);
pub type CFSetRef = *const __CFSet;
+pub type CFMutableSetRef = *mut __CFSet;
-extern {
+extern "C" {
/*
* CFSet.h
*/
pub static kCFTypeSetCallBacks: CFSetCallBacks;
+ pub static kCFCopyStringSetCallBacks: CFSetCallBacks;
+ /* CFSet */
/* Creating Sets */
- pub fn CFSetCreate(allocator: CFAllocatorRef, values: *const *const c_void, numValues: CFIndex,
- callBacks: *const CFSetCallBacks) -> CFSetRef;
+ pub fn CFSetCreate(
+ allocator: CFAllocatorRef,
+ values: *const *const c_void,
+ numValues: CFIndex,
+ callBacks: *const CFSetCallBacks,
+ ) -> CFSetRef;
pub fn CFSetCreateCopy(allocator: CFAllocatorRef, theSet: CFSetRef) -> CFSetRef;
/* Examining a Set */
@@ -52,15 +61,38 @@ extern {
pub fn CFSetGetCount(theSet: CFSetRef) -> CFIndex;
pub fn CFSetGetCountOfValue(theSet: CFSetRef, value: *const c_void) -> CFIndex;
pub fn CFSetGetValue(theSet: CFSetRef, value: *const c_void) -> *const c_void;
- pub fn CFSetGetValueIfPresent(theSet: CFSetRef, candidate: *const c_void, value: *mut *const c_void) -> Boolean;
+ pub fn CFSetGetValueIfPresent(
+ theSet: CFSetRef,
+ candidate: *const c_void,
+ value: *mut *const c_void,
+ ) -> Boolean;
pub fn CFSetGetValues(theSet: CFSetRef, values: *mut *const c_void);
/* Applying a Function to Set Members */
- pub fn CFSetApplyFunction(theSet: CFSetRef,
- applier: CFSetApplierFunction,
- context: *const c_void);
+ pub fn CFSetApplyFunction(
+ theSet: CFSetRef,
+ applier: CFSetApplierFunction,
+ context: *const c_void,
+ );
/* Getting the CFSet Type ID */
pub fn CFSetGetTypeID() -> CFTypeID;
-}
+ /* CFMutableSet */
+ /* CFMutableSet Miscellaneous Functions */
+ pub fn CFSetAddValue(theSet: CFMutableSetRef, value: *const c_void);
+ pub fn CFSetCreateMutable(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ callBacks: *const CFSetCallBacks,
+ ) -> CFMutableSetRef;
+ pub fn CFSetCreateMutableCopy(
+ allocator: CFAllocatorRef,
+ capacity: CFIndex,
+ theSet: CFSetRef,
+ ) -> CFMutableSetRef;
+ pub fn CFSetRemoveAllValues(theSet: CFMutableSetRef);
+ pub fn CFSetRemoveValue(theSet: CFMutableSetRef, value: *const c_void);
+ pub fn CFSetReplaceValue(theSet: CFMutableSetRef, value: *const c_void);
+ pub fn CFSetSetValue(theSet: CFMutableSetRef, value: *const c_void);
+}
diff --git a/third_party/rust/core-foundation-sys/src/socket.rs b/third_party/rust/core-foundation-sys/src/socket.rs
new file mode 100644
index 0000000000..6fb70a1080
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/socket.rs
@@ -0,0 +1,188 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeID, SInt32, UInt16};
+use crate::data::CFDataRef;
+use crate::date::CFTimeInterval;
+use crate::propertylist::CFPropertyListRef;
+use crate::runloop::CFRunLoopSourceRef;
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFSocket(c_void);
+
+pub type CFSocketRef = *mut __CFSocket;
+
+pub type CFSocketError = CFIndex;
+pub type CFSocketCallBackType = CFOptionFlags;
+pub type CFSocketCallBack = extern "C" fn(
+ s: CFSocketRef,
+ _type: CFSocketCallBackType,
+ address: CFDataRef,
+ cdata: *const c_void,
+ info: *mut c_void,
+);
+#[cfg(not(target_os = "windows"))]
+pub type CFSocketNativeHandle = std::os::raw::c_int;
+#[cfg(target_os = "windows")]
+pub type CFSocketNativeHandle = std::os::raw::c_ulong;
+
+pub const kCFSocketSuccess: CFSocketError = 0;
+pub const kCFSocketError: CFSocketError = -1;
+pub const kCFSocketTimeout: CFSocketError = -2;
+
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct CFSocketSignature {
+ pub protocolFamily: SInt32,
+ pub socketType: SInt32,
+ pub protocol: SInt32,
+ pub address: CFDataRef,
+}
+
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct CFSocketContext {
+ pub version: CFIndex,
+ pub info: *mut c_void,
+ pub retain: extern "C" fn(info: *const c_void) -> *const c_void,
+ pub release: extern "C" fn(info: *const c_void),
+ pub copyDescription: extern "C" fn(info: *const c_void) -> CFStringRef,
+}
+
+pub const kCFSocketNoCallBack: CFSocketError = 0;
+pub const kCFSocketReadCallBack: CFSocketError = 1;
+pub const kCFSocketAcceptCallBack: CFSocketError = 2;
+pub const kCFSocketDataCallBack: CFSocketError = 3;
+pub const kCFSocketConnectCallBack: CFSocketError = 4;
+pub const kCFSocketWriteCallBack: CFSocketError = 8;
+
+pub const kCFSocketAutomaticallyReenableReadCallBack: CFOptionFlags = 1;
+pub const kCFSocketAutomaticallyReenableAcceptCallBack: CFOptionFlags = 2;
+pub const kCFSocketAutomaticallyReenableDataCallBack: CFOptionFlags = 3;
+pub const kCFSocketAutomaticallyReenableWriteCallBack: CFOptionFlags = 8;
+pub const kCFSocketLeaveErrors: CFOptionFlags = 64;
+pub const kCFSocketCloseOnInvalidate: CFOptionFlags = 128;
+
+extern "C" {
+ /*
+ * CFSocket.h
+ */
+
+ /* CFSocket Name Server Keys: Not used */
+ pub static kCFSocketCommandKey: CFStringRef;
+ pub static kCFSocketNameKey: CFStringRef;
+ pub static kCFSocketValueKey: CFStringRef;
+ pub static kCFSocketResultKey: CFStringRef;
+ pub static kCFSocketErrorKey: CFStringRef;
+ pub static kCFSocketRegisterCommand: CFStringRef;
+ pub static kCFSocketRetrieveCommand: CFStringRef;
+
+ /* Creating Sockets */
+ pub fn CFSocketCreate(
+ allocator: CFAllocatorRef,
+ protocolFamily: SInt32,
+ socketType: SInt32,
+ protocol: SInt32,
+ callBackTypes: CFOptionFlags,
+ callout: CFSocketCallBack,
+ context: *const CFSocketContext,
+ ) -> CFSocketRef;
+ pub fn CFSocketCreateConnectedToSocketSignature(
+ allocator: CFAllocatorRef,
+ signature: *const CFSocketSignature,
+ callBackTypes: CFOptionFlags,
+ callout: CFSocketCallBack,
+ context: *const CFSocketContext,
+ timeout: CFTimeInterval,
+ ) -> CFSocketRef;
+ pub fn CFSocketCreateWithNative(
+ allocator: CFAllocatorRef,
+ sock: CFSocketNativeHandle,
+ callBackTypes: CFOptionFlags,
+ callout: CFSocketCallBack,
+ context: *const CFSocketContext,
+ ) -> CFSocketRef;
+ pub fn CFSocketCreateWithSocketSignature(
+ allocator: CFAllocatorRef,
+ signature: *const CFSocketSignature,
+ callBackTypes: CFOptionFlags,
+ callout: CFSocketCallBack,
+ context: *const CFSocketContext,
+ ) -> CFSocketRef;
+
+ /* Configuring Sockets */
+ pub fn CFSocketCopyAddress(s: CFSocketRef) -> CFDataRef;
+ pub fn CFSocketCopyPeerAddress(s: CFSocketRef) -> CFDataRef;
+ pub fn CFSocketDisableCallBacks(s: CFSocketRef, callBackTypes: CFOptionFlags);
+ pub fn CFSocketEnableCallBacks(s: CFSocketRef, callBackTypes: CFOptionFlags);
+ pub fn CFSocketGetContext(s: CFSocketRef, context: *mut CFSocketContext);
+ pub fn CFSocketGetNative(s: CFSocketRef) -> CFSocketNativeHandle;
+ pub fn CFSocketGetSocketFlags(s: CFSocketRef) -> CFOptionFlags;
+ pub fn CFSocketSetAddress(s: CFSocketRef, address: CFDataRef) -> CFSocketError;
+ pub fn CFSocketSetSocketFlags(s: CFSocketRef, flags: CFOptionFlags);
+
+ /* Using Sockets */
+ pub fn CFSocketConnectToAddress(
+ s: CFSocketRef,
+ address: CFDataRef,
+ timeout: CFTimeInterval,
+ ) -> CFSocketError;
+ pub fn CFSocketCreateRunLoopSource(
+ allocator: CFAllocatorRef,
+ s: CFSocketRef,
+ order: CFIndex,
+ ) -> CFRunLoopSourceRef;
+ pub fn CFSocketGetTypeID() -> CFTypeID;
+ pub fn CFSocketInvalidate(s: CFSocketRef);
+ pub fn CFSocketIsValid(s: CFSocketRef) -> Boolean;
+ pub fn CFSocketSendData(
+ s: CFSocketRef,
+ address: CFDataRef,
+ data: CFDataRef,
+ timeout: CFTimeInterval,
+ ) -> CFSocketError;
+
+ /* Socket Name Server Utilities */
+ pub fn CFSocketCopyRegisteredSocketSignature(
+ nameServerSignature: *const CFSocketSignature,
+ timeout: CFTimeInterval,
+ name: CFStringRef,
+ signature: *mut CFSocketSignature,
+ nameServerAddress: *mut CFDataRef,
+ ) -> CFSocketError;
+ pub fn CFSocketCopyRegisteredValue(
+ nameServerSignature: *const CFSocketSignature,
+ timeout: CFTimeInterval,
+ name: CFStringRef,
+ value: *mut CFPropertyListRef,
+ nameServerAddress: *mut CFDataRef,
+ ) -> CFSocketError;
+ pub fn CFSocketGetDefaultNameRegistryPortNumber() -> UInt16;
+ pub fn CFSocketRegisterSocketSignature(
+ nameServerSignature: *const CFSocketSignature,
+ timeout: CFTimeInterval,
+ name: CFStringRef,
+ signature: *const CFSocketSignature,
+ ) -> CFSocketError;
+ pub fn CFSocketRegisterValue(
+ nameServerSignature: *const CFSocketSignature,
+ timeout: CFTimeInterval,
+ name: CFStringRef,
+ value: CFPropertyListRef,
+ ) -> CFSocketError;
+ pub fn CFSocketSetDefaultNameRegistryPortNumber(port: UInt16);
+ pub fn CFSocketUnregister(
+ nameServerSignature: *const CFSocketSignature,
+ timeout: CFTimeInterval,
+ name: CFStringRef,
+ ) -> CFSocketError;
+}
diff --git a/third_party/rust/core-foundation-sys/src/stream.rs b/third_party/rust/core-foundation-sys/src/stream.rs
new file mode 100644
index 0000000000..922700e489
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/stream.rs
@@ -0,0 +1,281 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::{c_int, c_void};
+
+use crate::base::{
+ Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeID, CFTypeRef, SInt32, UInt32, UInt8,
+};
+use crate::error::CFErrorRef;
+use crate::runloop::CFRunLoopRef;
+use crate::socket::{CFSocketNativeHandle, CFSocketSignature};
+use crate::string::CFStringRef;
+use crate::url::CFURLRef;
+
+#[repr(C)]
+pub struct __CFReadStream(c_void);
+
+#[repr(C)]
+pub struct __CFWriteStream(c_void);
+
+pub type CFReadStreamRef = *mut __CFReadStream;
+pub type CFWriteStreamRef = *mut __CFWriteStream;
+pub type CFStreamPropertyKey = CFStringRef;
+pub type CFStreamStatus = CFIndex;
+pub type CFStreamEventType = CFOptionFlags;
+pub type CFStreamErrorDomain = CFIndex;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct CFStreamError {
+ pub domain: CFIndex,
+ pub error: SInt32,
+}
+
+/* CFStreamStatus: Constants that describe the status of a stream */
+pub const kCFStreamStatusNotOpen: CFStreamStatus = 0;
+pub const kCFStreamStatusOpening: CFStreamStatus = 1;
+pub const kCFStreamStatusOpen: CFStreamStatus = 2;
+pub const kCFStreamStatusReading: CFStreamStatus = 3;
+pub const kCFStreamStatusWriting: CFStreamStatus = 4;
+pub const kCFStreamStatusAtEnd: CFStreamStatus = 5;
+pub const kCFStreamStatusClosed: CFStreamStatus = 6;
+pub const kCFStreamStatusError: CFStreamStatus = 7;
+
+// deprecated
+pub const kCFStreamErrorDomainCustom: CFStreamErrorDomain = -1;
+pub const kCFStreamErrorDomainPOSIX: CFStreamErrorDomain = 1;
+pub const kCFStreamErrorDomainMacOSStatus: CFStreamErrorDomain = 2;
+
+/* CFStreamEventType: Defines constants for stream-related events */
+pub const kCFStreamEventNone: CFStreamEventType = 0;
+pub const kCFStreamEventOpenCompleted: CFStreamEventType = 1;
+pub const kCFStreamEventHasBytesAvailable: CFStreamEventType = 2;
+pub const kCFStreamEventCanAcceptBytes: CFStreamEventType = 4;
+pub const kCFStreamEventErrorOccurred: CFStreamEventType = 8;
+pub const kCFStreamEventEndEncountered: CFStreamEventType = 16;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFStreamClientContext {
+ pub version: CFIndex,
+ pub info: *mut c_void,
+ pub retain: extern "C" fn(info: *const c_void) -> *const c_void,
+ pub release: extern "C" fn(info: *const c_void),
+ pub copyDescription: extern "C" fn(info: *const c_void) -> CFStringRef,
+}
+
+pub type CFReadStreamClientCallBack = extern "C" fn(
+ stream: CFReadStreamRef,
+ _type: CFStreamEventType,
+ clientCallBackInfo: *mut c_void,
+);
+pub type CFWriteStreamClientCallBack = extern "C" fn(
+ stream: CFWriteStreamRef,
+ _type: CFStreamEventType,
+ clientCallBackInfo: *mut c_void,
+);
+
+extern "C" {
+ /*
+ * CFStream.h
+ */
+
+ /* Stream Properties */
+ pub static kCFStreamPropertyAppendToFile: CFStreamPropertyKey;
+ pub static kCFStreamPropertyDataWritten: CFStreamPropertyKey;
+ pub static kCFStreamPropertyFileCurrentOffset: CFStreamPropertyKey;
+ pub static kCFStreamPropertySocketNativeHandle: CFStreamPropertyKey;
+ pub static kCFStreamPropertySocketRemoteHostName: CFStreamPropertyKey;
+ pub static kCFStreamPropertySocketRemotePortNumber: CFStreamPropertyKey;
+ pub static kCFStreamPropertyShouldCloseNativeSocket: CFStringRef;
+ pub static kCFStreamPropertySocketSecurityLevel: CFStringRef;
+
+ /* CFStream Socket Security Level Constants */
+ pub static kCFStreamSocketSecurityLevelNone: CFStringRef;
+ pub static kCFStreamSocketSecurityLevelSSLv2: CFStringRef;
+ pub static kCFStreamSocketSecurityLevelSSLv3: CFStringRef;
+ pub static kCFStreamSocketSecurityLevelTLSv1: CFStringRef;
+ pub static kCFStreamSocketSecurityLevelNegotiatedSSL: CFStringRef;
+
+ /* CFStream SOCKS Proxy Key Constants */
+ pub static kCFStreamPropertySOCKSProxy: CFStringRef;
+ pub static kCFStreamPropertySOCKSProxyHost: CFStringRef;
+ pub static kCFStreamPropertySOCKSProxyPort: CFStringRef;
+ pub static kCFStreamPropertySOCKSVersion: CFStringRef;
+ pub static kCFStreamSocketSOCKSVersion4: CFStringRef;
+ pub static kCFStreamSocketSOCKSVersion5: CFStringRef;
+ pub static kCFStreamPropertySOCKSUser: CFStringRef;
+ pub static kCFStreamPropertySOCKSPassword: CFStringRef;
+
+ /* CFStream Error Domain Constants (CFHost) */
+ pub static kCFStreamErrorDomainSOCKS: c_int;
+ pub static kCFStreamErrorDomainSSL: c_int;
+
+ /* CFStream: Creating Streams */
+ pub fn CFStreamCreatePairWithPeerSocketSignature(
+ alloc: CFAllocatorRef,
+ signature: *const CFSocketSignature,
+ readStream: *mut CFReadStreamRef,
+ writeStream: *mut CFWriteStreamRef,
+ ); // deprecated
+ pub fn CFStreamCreatePairWithSocketToHost(
+ alloc: CFAllocatorRef,
+ host: CFStringRef,
+ port: UInt32,
+ readStream: *mut CFReadStreamRef,
+ writeStream: *mut CFWriteStreamRef,
+ ); // deprecated
+ pub fn CFStreamCreatePairWithSocket(
+ alloc: CFAllocatorRef,
+ sock: CFSocketNativeHandle,
+ readStream: *mut CFReadStreamRef,
+ writeStream: *mut CFWriteStreamRef,
+ ); // deprecated
+ pub fn CFStreamCreateBoundPair(
+ alloc: CFAllocatorRef,
+ readStream: *mut CFReadStreamRef,
+ writeStream: *mut CFWriteStreamRef,
+ transferBufferSize: CFIndex,
+ );
+
+ //pub fn CFReadStreamSetDispatchQueue(stream: CFReadStreamRef, q: dispatch_queue_t); // macos(10.9)+
+ //pub fn CFWriteStreamSetDispatchQueue(stream: CFWriteStreamRef, q: dispatch_queue_t); // macos(10.9)+
+ //pub fn CFReadStreamCopyDispatchQueue(stream: CFReadStreamRef) -> dispatch_queue_t; // macos(10.9)+
+ //pub fn CFWriteStreamCopyDispatchQueue(stream: CFReadStreamRef) -> dispatch_queue_t; // macos(10.9)+
+
+ /* CFReadStream */
+ /* Creating a Read Stream */
+ pub fn CFReadStreamCreateWithBytesNoCopy(
+ alloc: CFAllocatorRef,
+ bytes: *const UInt8,
+ length: CFIndex,
+ bytesDeallocator: CFAllocatorRef,
+ ) -> CFReadStreamRef;
+ pub fn CFReadStreamCreateWithFile(alloc: CFAllocatorRef, fileURL: CFURLRef) -> CFReadStreamRef;
+
+ /* Opening and Closing a Read Stream */
+ pub fn CFReadStreamClose(stream: CFReadStreamRef);
+ pub fn CFReadStreamOpen(stream: CFReadStreamRef) -> Boolean;
+
+ /* Reading from a Stream */
+ pub fn CFReadStreamRead(
+ stream: CFReadStreamRef,
+ buffer: *mut UInt8,
+ bufferLength: CFIndex,
+ ) -> CFIndex;
+
+ /* Scheduling a Read Stream */
+ pub fn CFReadStreamScheduleWithRunLoop(
+ stream: CFReadStreamRef,
+ runLoop: CFRunLoopRef,
+ runLoopMode: CFStringRef,
+ );
+ pub fn CFReadStreamUnscheduleFromRunLoop(
+ stream: CFReadStreamRef,
+ runLoop: CFRunLoopRef,
+ runLoopMode: CFStringRef,
+ );
+
+ /* Examining Stream Properties */
+ pub fn CFReadStreamCopyProperty(
+ stream: CFReadStreamRef,
+ propertyName: CFStreamPropertyKey,
+ ) -> CFTypeRef;
+ pub fn CFReadStreamGetBuffer(
+ stream: CFReadStreamRef,
+ maxBytesToRead: CFIndex,
+ numBytesRead: *mut CFIndex,
+ ) -> *const UInt8;
+ pub fn CFReadStreamCopyError(stream: CFReadStreamRef) -> CFErrorRef;
+ pub fn CFReadStreamGetError(stream: CFReadStreamRef) -> CFStreamError; // deprecated
+ pub fn CFReadStreamGetStatus(stream: CFReadStreamRef) -> CFStreamStatus;
+ pub fn CFReadStreamHasBytesAvailable(stream: CFReadStreamRef) -> Boolean;
+
+ /* Setting Stream Properties */
+ pub fn CFReadStreamSetClient(
+ stream: CFReadStreamRef,
+ streamEvents: CFOptionFlags,
+ clientCB: CFReadStreamClientCallBack,
+ clientContext: *mut CFStreamClientContext,
+ ) -> Boolean;
+ pub fn CFReadStreamSetProperty(
+ stream: CFReadStreamRef,
+ propertyName: CFStreamPropertyKey,
+ propertyValue: CFTypeRef,
+ ) -> Boolean;
+
+ /* Getting the CFReadStream Type ID */
+ pub fn CFReadStreamGetTypeID() -> CFTypeID;
+
+ /* CFWriteStream */
+ /* Creating a Write Stream */
+ pub fn CFWriteStreamCreateWithAllocatedBuffers(
+ alloc: CFAllocatorRef,
+ bufferAllocator: CFAllocatorRef,
+ ) -> CFWriteStreamRef;
+ pub fn CFWriteStreamCreateWithBuffer(
+ alloc: CFAllocatorRef,
+ buffer: *mut UInt8,
+ bufferCapacity: CFIndex,
+ ) -> CFWriteStreamRef;
+ pub fn CFWriteStreamCreateWithFile(
+ alloc: CFAllocatorRef,
+ fileURL: CFURLRef,
+ ) -> CFWriteStreamRef;
+
+ /* Opening and Closing a Stream */
+ pub fn CFWriteStreamClose(stream: CFWriteStreamRef);
+ pub fn CFWriteStreamOpen(stream: CFWriteStreamRef) -> Boolean;
+
+ /* Writing to a Stream */
+ pub fn CFWriteStreamWrite(
+ stream: CFWriteStreamRef,
+ buffer: *const UInt8,
+ bufferLength: CFIndex,
+ ) -> CFIndex;
+
+ /* Scheduling a Write Stream */
+ pub fn CFWriteStreamScheduleWithRunLoop(
+ stream: CFWriteStreamRef,
+ runLoop: CFRunLoopRef,
+ runLoopMode: CFStringRef,
+ );
+ pub fn CFWriteStreamUnscheduleFromRunLoop(
+ stream: CFWriteStreamRef,
+ runLoop: CFRunLoopRef,
+ runLoopMode: CFStringRef,
+ );
+
+ /* Examining Stream Properties */
+ pub fn CFWriteStreamCanAcceptBytes(stream: CFWriteStreamRef) -> Boolean;
+ pub fn CFWriteStreamCopyProperty(
+ stream: CFWriteStreamRef,
+ propertyName: CFStreamPropertyKey,
+ ) -> CFTypeRef;
+ pub fn CFWriteStreamCopyError(stream: CFWriteStreamRef) -> CFErrorRef;
+ pub fn CFWriteStreamGetError(stream: CFWriteStreamRef) -> CFStreamError; // deprecated
+ pub fn CFWriteStreamGetStatus(stream: CFWriteStreamRef) -> CFStreamStatus;
+
+ /* Setting Stream Properties */
+ pub fn CFWriteStreamSetClient(
+ stream: CFWriteStreamRef,
+ streamEvents: CFOptionFlags,
+ clientCB: CFWriteStreamClientCallBack,
+ clientContext: *mut CFStreamClientContext,
+ ) -> Boolean;
+ pub fn CFWriteStreamSetProperty(
+ stream: CFWriteStreamRef,
+ propertyName: CFStreamPropertyKey,
+ propertyValue: CFTypeRef,
+ ) -> Boolean;
+
+ /* Getting the CFWriteStream Type ID */
+ pub fn CFWriteStreamGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/string.rs b/third_party/rust/core-foundation-sys/src/string.rs
index d4f6550784..2cb6ae948a 100644
--- a/third_party/rust/core-foundation-sys/src/string.rs
+++ b/third_party/rust/core-foundation-sys/src/string.rs
@@ -7,317 +7,540 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os::raw::{c_char, c_ushort, c_void};
-
-use base::{Boolean, CFOptionFlags, CFIndex, CFAllocatorRef, CFRange, CFTypeID};
-
-pub type UniChar = c_ushort;
-
-// CFString.h
+use crate::array::CFArrayRef;
+use crate::base::{
+ Boolean, CFAllocatorRef, CFComparisonResult, CFIndex, CFOptionFlags, CFRange, CFTypeID,
+ ConstStr255Param, ConstStringPtr, SInt32, StringPtr, UInt32, UInt8, UTF32Char,
+};
+use crate::characterset::CFCharacterSetRef;
+use crate::data::CFDataRef;
+use crate::dictionary::CFDictionaryRef;
+use crate::locale::CFLocaleRef;
+use std::os::raw::{c_char, c_double, c_ulong, c_ushort, c_void};
pub type CFStringCompareFlags = CFOptionFlags;
-//static kCFCompareCaseInsensitive: CFStringCompareFlags = 1;
-//static kCFCompareBackwards: CFStringCompareFlags = 4;
-//static kCFCompareAnchored: CFStringCompareFlags = 8;
-//static kCFCompareNonliteral: CFStringCompareFlags = 16;
-//static kCFCompareLocalized: CFStringCompareFlags = 32;
-//static kCFCompareNumerically: CFStringCompareFlags = 64;
-//static kCFCompareDiacriticInsensitive: CFStringCompareFlags = 128;
-//static kCFCompareWidthInsensitive: CFStringCompareFlags = 256;
-//static kCFCompareForcedOrdering: CFStringCompareFlags = 512;
+pub const kCFCompareCaseInsensitive: CFStringCompareFlags = 1;
+pub const kCFCompareBackwards: CFStringCompareFlags = 4;
+pub const kCFCompareAnchored: CFStringCompareFlags = 8;
+pub const kCFCompareNonliteral: CFStringCompareFlags = 16;
+pub const kCFCompareLocalized: CFStringCompareFlags = 32;
+pub const kCFCompareNumerically: CFStringCompareFlags = 64;
+pub const kCFCompareDiacriticInsensitive: CFStringCompareFlags = 128;
+pub const kCFCompareWidthInsensitive: CFStringCompareFlags = 256;
+pub const kCFCompareForcedOrdering: CFStringCompareFlags = 512;
-pub type CFStringEncoding = u32;
+pub type CFStringEncoding = UInt32;
+pub type UniChar = c_ushort;
// macOS built-in encodings.
-//static kCFStringEncodingMacRoman: CFStringEncoding = 0;
-//static kCFStringEncodingWindowsLatin1: CFStringEncoding = 0x0500;
-//static kCFStringEncodingISOLatin1: CFStringEncoding = 0x0201;
-//static kCFStringEncodingNextStepLatin: CFStringEncoding = 0x0B01;
-//static kCFStringEncodingASCII: CFStringEncoding = 0x0600;
-//static kCFStringEncodingUnicode: CFStringEncoding = 0x0100;
-pub static kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;
-//static kCFStringEncodingNonLossyASCII: CFStringEncoding = 0x0BFF;
-
-//static kCFStringEncodingUTF16: CFStringEncoding = 0x0100;
-//static kCFStringEncodingUTF16BE: CFStringEncoding = 0x10000100;
-//static kCFStringEncodingUTF16LE: CFStringEncoding = 0x14000100;
-//static kCFStringEncodingUTF32: CFStringEncoding = 0x0c000100;
-//static kCFStringEncodingUTF32BE: CFStringEncoding = 0x18000100;
-//static kCFStringEncodingUTF32LE: CFStringEncoding = 0x1c000100;
+pub const kCFStringEncodingMacRoman: CFStringEncoding = 0;
+pub const kCFStringEncodingWindowsLatin1: CFStringEncoding = 0x0500;
+pub const kCFStringEncodingISOLatin1: CFStringEncoding = 0x0201;
+pub const kCFStringEncodingNextStepLatin: CFStringEncoding = 0x0B01;
+pub const kCFStringEncodingASCII: CFStringEncoding = 0x0600;
+pub const kCFStringEncodingUnicode: CFStringEncoding = 0x0100;
+pub const kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;
+pub const kCFStringEncodingNonLossyASCII: CFStringEncoding = 0x0BFF;
+pub const kCFStringEncodingUTF16: CFStringEncoding = 0x0100;
+pub const kCFStringEncodingUTF16BE: CFStringEncoding = 0x10000100;
+pub const kCFStringEncodingUTF16LE: CFStringEncoding = 0x14000100;
+pub const kCFStringEncodingUTF32: CFStringEncoding = 0x0c000100;
+pub const kCFStringEncodingUTF32BE: CFStringEncoding = 0x18000100;
+pub const kCFStringEncodingUTF32LE: CFStringEncoding = 0x1c000100;
// CFStringEncodingExt.h
+// External encodings, except those defined above.
+pub const kCFStringEncodingMacJapanese: CFStringEncoding = 1;
+pub const kCFStringEncodingMacChineseTrad: CFStringEncoding = 2;
+pub const kCFStringEncodingMacKorean: CFStringEncoding = 3;
+pub const kCFStringEncodingMacArabic: CFStringEncoding = 4;
+pub const kCFStringEncodingMacHebrew: CFStringEncoding = 5;
+pub const kCFStringEncodingMacGreek: CFStringEncoding = 6;
+pub const kCFStringEncodingMacCyrillic: CFStringEncoding = 7;
+pub const kCFStringEncodingMacDevanagari: CFStringEncoding = 9;
+pub const kCFStringEncodingMacGurmukhi: CFStringEncoding = 10;
+pub const kCFStringEncodingMacGujarati: CFStringEncoding = 11;
+pub const kCFStringEncodingMacOriya: CFStringEncoding = 12;
+pub const kCFStringEncodingMacBengali: CFStringEncoding = 13;
+pub const kCFStringEncodingMacTamil: CFStringEncoding = 14;
+pub const kCFStringEncodingMacTelugu: CFStringEncoding = 15;
+pub const kCFStringEncodingMacKannada: CFStringEncoding = 16;
+pub const kCFStringEncodingMacMalayalam: CFStringEncoding = 17;
+pub const kCFStringEncodingMacSinhalese: CFStringEncoding = 18;
+pub const kCFStringEncodingMacBurmese: CFStringEncoding = 19;
+pub const kCFStringEncodingMacKhmer: CFStringEncoding = 20;
+pub const kCFStringEncodingMacThai: CFStringEncoding = 21;
+pub const kCFStringEncodingMacLaotian: CFStringEncoding = 22;
+pub const kCFStringEncodingMacGeorgian: CFStringEncoding = 23;
+pub const kCFStringEncodingMacArmenian: CFStringEncoding = 24;
+pub const kCFStringEncodingMacChineseSimp: CFStringEncoding = 25;
+pub const kCFStringEncodingMacTibetan: CFStringEncoding = 26;
+pub const kCFStringEncodingMacMongolian: CFStringEncoding = 27;
+pub const kCFStringEncodingMacEthiopic: CFStringEncoding = 28;
+pub const kCFStringEncodingMacCentralEurRoman: CFStringEncoding = 29;
+pub const kCFStringEncodingMacVietnamese: CFStringEncoding = 30;
+pub const kCFStringEncodingMacExtArabic: CFStringEncoding = 31;
+pub const kCFStringEncodingMacSymbol: CFStringEncoding = 33;
+pub const kCFStringEncodingMacDingbats: CFStringEncoding = 34;
+pub const kCFStringEncodingMacTurkish: CFStringEncoding = 35;
+pub const kCFStringEncodingMacCroatian: CFStringEncoding = 36;
+pub const kCFStringEncodingMacIcelandic: CFStringEncoding = 37;
+pub const kCFStringEncodingMacRomanian: CFStringEncoding = 38;
+pub const kCFStringEncodingMacCeltic: CFStringEncoding = 39;
+pub const kCFStringEncodingMacGaelic: CFStringEncoding = 40;
+pub const kCFStringEncodingMacFarsi: CFStringEncoding = 0x8C;
+pub const kCFStringEncodingMacUkrainian: CFStringEncoding = 0x98;
+pub const kCFStringEncodingMacInuit: CFStringEncoding = 0xEC;
+pub const kCFStringEncodingMacVT100: CFStringEncoding = 0xFC;
+pub const kCFStringEncodingMacHFS: CFStringEncoding = 0xFF;
+pub const kCFStringEncodingISOLatin2: CFStringEncoding = 0x0202;
+pub const kCFStringEncodingISOLatin3: CFStringEncoding = 0x0203;
+pub const kCFStringEncodingISOLatin4: CFStringEncoding = 0x0204;
+pub const kCFStringEncodingISOLatinCyrillic: CFStringEncoding = 0x0205;
+pub const kCFStringEncodingISOLatinArabic: CFStringEncoding = 0x0206;
+pub const kCFStringEncodingISOLatinGreek: CFStringEncoding = 0x0207;
+pub const kCFStringEncodingISOLatinHebrew: CFStringEncoding = 0x0208;
+pub const kCFStringEncodingISOLatin5: CFStringEncoding = 0x0209;
+pub const kCFStringEncodingISOLatin6: CFStringEncoding = 0x020A;
+pub const kCFStringEncodingISOLatinThai: CFStringEncoding = 0x020B;
+pub const kCFStringEncodingISOLatin7: CFStringEncoding = 0x020D;
+pub const kCFStringEncodingISOLatin8: CFStringEncoding = 0x020E;
+pub const kCFStringEncodingISOLatin9: CFStringEncoding = 0x020F;
+pub const kCFStringEncodingISOLatin10: CFStringEncoding = 0x0210;
+pub const kCFStringEncodingDOSLatinUS: CFStringEncoding = 0x0400;
+pub const kCFStringEncodingDOSGreek: CFStringEncoding = 0x0405;
+pub const kCFStringEncodingDOSBalticRim: CFStringEncoding = 0x0406;
+pub const kCFStringEncodingDOSLatin1: CFStringEncoding = 0x0410;
+pub const kCFStringEncodingDOSGreek1: CFStringEncoding = 0x0411;
+pub const kCFStringEncodingDOSLatin2: CFStringEncoding = 0x0412;
+pub const kCFStringEncodingDOSCyrillic: CFStringEncoding = 0x0413;
+pub const kCFStringEncodingDOSTurkish: CFStringEncoding = 0x0414;
+pub const kCFStringEncodingDOSPortuguese: CFStringEncoding = 0x0415;
+pub const kCFStringEncodingDOSIcelandic: CFStringEncoding = 0x0416;
+pub const kCFStringEncodingDOSHebrew: CFStringEncoding = 0x0417;
+pub const kCFStringEncodingDOSCanadianFrench: CFStringEncoding = 0x0418;
+pub const kCFStringEncodingDOSArabic: CFStringEncoding = 0x0419;
+pub const kCFStringEncodingDOSNordic: CFStringEncoding = 0x041A;
+pub const kCFStringEncodingDOSRussian: CFStringEncoding = 0x041B;
+pub const kCFStringEncodingDOSGreek2: CFStringEncoding = 0x041C;
+pub const kCFStringEncodingDOSThai: CFStringEncoding = 0x041D;
+pub const kCFStringEncodingDOSJapanese: CFStringEncoding = 0x0420;
+pub const kCFStringEncodingDOSChineseSimplif: CFStringEncoding = 0x0421;
+pub const kCFStringEncodingDOSKorean: CFStringEncoding = 0x0422;
+pub const kCFStringEncodingDOSChineseTrad: CFStringEncoding = 0x0423;
+pub const kCFStringEncodingWindowsLatin2: CFStringEncoding = 0x0501;
+pub const kCFStringEncodingWindowsCyrillic: CFStringEncoding = 0x0502;
+pub const kCFStringEncodingWindowsGreek: CFStringEncoding = 0x0503;
+pub const kCFStringEncodingWindowsLatin5: CFStringEncoding = 0x0504;
+pub const kCFStringEncodingWindowsHebrew: CFStringEncoding = 0x0505;
+pub const kCFStringEncodingWindowsArabic: CFStringEncoding = 0x0506;
+pub const kCFStringEncodingWindowsBalticRim: CFStringEncoding = 0x0507;
+pub const kCFStringEncodingWindowsVietnamese: CFStringEncoding = 0x0508;
+pub const kCFStringEncodingWindowsKoreanJohab: CFStringEncoding = 0x0510;
+pub const kCFStringEncodingANSEL: CFStringEncoding = 0x0601;
+pub const kCFStringEncodingJIS_X0201_76: CFStringEncoding = 0x0620;
+pub const kCFStringEncodingJIS_X0208_83: CFStringEncoding = 0x0621;
+pub const kCFStringEncodingJIS_X0208_90: CFStringEncoding = 0x0622;
+pub const kCFStringEncodingJIS_X0212_90: CFStringEncoding = 0x0623;
+pub const kCFStringEncodingJIS_C6226_78: CFStringEncoding = 0x0624;
+pub const kCFStringEncodingShiftJIS_X0213: CFStringEncoding = 0x0628;
+pub const kCFStringEncodingShiftJIS_X0213_MenKuTen: CFStringEncoding = 0x0629;
+pub const kCFStringEncodingGB_2312_80: CFStringEncoding = 0x0630;
+pub const kCFStringEncodingGBK_95: CFStringEncoding = 0x0631;
+pub const kCFStringEncodingGB_18030_2000: CFStringEncoding = 0x0632;
+pub const kCFStringEncodingKSC_5601_87: CFStringEncoding = 0x0640;
+pub const kCFStringEncodingKSC_5601_92_Johab: CFStringEncoding = 0x0641;
+pub const kCFStringEncodingCNS_11643_92_P1: CFStringEncoding = 0x0651;
+pub const kCFStringEncodingCNS_11643_92_P2: CFStringEncoding = 0x0652;
+pub const kCFStringEncodingCNS_11643_92_P3: CFStringEncoding = 0x0653;
+pub const kCFStringEncodingISO_2022_JP: CFStringEncoding = 0x0820;
+pub const kCFStringEncodingISO_2022_JP_2: CFStringEncoding = 0x0821;
+pub const kCFStringEncodingISO_2022_JP_1: CFStringEncoding = 0x0822;
+pub const kCFStringEncodingISO_2022_JP_3: CFStringEncoding = 0x0823;
+pub const kCFStringEncodingISO_2022_CN: CFStringEncoding = 0x0830;
+pub const kCFStringEncodingISO_2022_CN_EXT: CFStringEncoding = 0x0831;
+pub const kCFStringEncodingISO_2022_KR: CFStringEncoding = 0x0840;
+pub const kCFStringEncodingEUC_JP: CFStringEncoding = 0x0920;
+pub const kCFStringEncodingEUC_CN: CFStringEncoding = 0x0930;
+pub const kCFStringEncodingEUC_TW: CFStringEncoding = 0x0931;
+pub const kCFStringEncodingEUC_KR: CFStringEncoding = 0x0940;
+pub const kCFStringEncodingShiftJIS: CFStringEncoding = 0x0A01;
+pub const kCFStringEncodingKOI8_R: CFStringEncoding = 0x0A02;
+pub const kCFStringEncodingBig5: CFStringEncoding = 0x0A03;
+pub const kCFStringEncodingMacRomanLatin1: CFStringEncoding = 0x0A04;
+pub const kCFStringEncodingHZ_GB_2312: CFStringEncoding = 0x0A05;
+pub const kCFStringEncodingBig5_HKSCS_1999: CFStringEncoding = 0x0A06;
+pub const kCFStringEncodingVISCII: CFStringEncoding = 0x0A07;
+pub const kCFStringEncodingKOI8_U: CFStringEncoding = 0x0A08;
+pub const kCFStringEncodingBig5_E: CFStringEncoding = 0x0A09;
+pub const kCFStringEncodingNextStepJapanese: CFStringEncoding = 0x0B02;
+pub const kCFStringEncodingEBCDIC_US: CFStringEncoding = 0x0C01;
+pub const kCFStringEncodingEBCDIC_CP037: CFStringEncoding = 0x0C02;
+pub const kCFStringEncodingUTF7: CFStringEncoding = 0x04000100;
+pub const kCFStringEncodingUTF7_IMAP: CFStringEncoding = 0x0A10;
+pub const kCFStringEncodingShiftJIS_X0213_00: CFStringEncoding = 0x0628; /* Deprecated */
-pub type CFStringEncodings = CFIndex;
+pub const kCFStringEncodingInvalidId: u32 = 0xffffffff;
-// External encodings, except those defined above.
-// Defined above: kCFStringEncodingMacRoman = 0
-//static kCFStringEncodingMacJapanese: CFStringEncoding = 1;
-//static kCFStringEncodingMacChineseTrad: CFStringEncoding = 2;
-//static kCFStringEncodingMacKorean: CFStringEncoding = 3;
-//static kCFStringEncodingMacArabic: CFStringEncoding = 4;
-//static kCFStringEncodingMacHebrew: CFStringEncoding = 5;
-//static kCFStringEncodingMacGreek: CFStringEncoding = 6;
-//static kCFStringEncodingMacCyrillic: CFStringEncoding = 7;
-//static kCFStringEncodingMacDevanagari: CFStringEncoding = 9;
-//static kCFStringEncodingMacGurmukhi: CFStringEncoding = 10;
-//static kCFStringEncodingMacGujarati: CFStringEncoding = 11;
-//static kCFStringEncodingMacOriya: CFStringEncoding = 12;
-//static kCFStringEncodingMacBengali: CFStringEncoding = 13;
-//static kCFStringEncodingMacTamil: CFStringEncoding = 14;
-//static kCFStringEncodingMacTelugu: CFStringEncoding = 15;
-//static kCFStringEncodingMacKannada: CFStringEncoding = 16;
-//static kCFStringEncodingMacMalayalam: CFStringEncoding = 17;
-//static kCFStringEncodingMacSinhalese: CFStringEncoding = 18;
-//static kCFStringEncodingMacBurmese: CFStringEncoding = 19;
-//static kCFStringEncodingMacKhmer: CFStringEncoding = 20;
-//static kCFStringEncodingMacThai: CFStringEncoding = 21;
-//static kCFStringEncodingMacLaotian: CFStringEncoding = 22;
-//static kCFStringEncodingMacGeorgian: CFStringEncoding = 23;
-//static kCFStringEncodingMacArmenian: CFStringEncoding = 24;
-//static kCFStringEncodingMacChineseSimp: CFStringEncoding = 25;
-//static kCFStringEncodingMacTibetan: CFStringEncoding = 26;
-//static kCFStringEncodingMacMongolian: CFStringEncoding = 27;
-//static kCFStringEncodingMacEthiopic: CFStringEncoding = 28;
-//static kCFStringEncodingMacCentralEurRoman: CFStringEncoding = 29;
-//static kCFStringEncodingMacVietnamese: CFStringEncoding = 30;
-//static kCFStringEncodingMacExtArabic: CFStringEncoding = 31;
-//static kCFStringEncodingMacSymbol: CFStringEncoding = 33;
-//static kCFStringEncodingMacDingbats: CFStringEncoding = 34;
-//static kCFStringEncodingMacTurkish: CFStringEncoding = 35;
-//static kCFStringEncodingMacCroatian: CFStringEncoding = 36;
-//static kCFStringEncodingMacIcelandic: CFStringEncoding = 37;
-//static kCFStringEncodingMacRomanian: CFStringEncoding = 38;
-//static kCFStringEncodingMacCeltic: CFStringEncoding = 39;
-//static kCFStringEncodingMacGaelic: CFStringEncoding = 40;
-//static kCFStringEncodingMacFarsi: CFStringEncoding = 0x8C;
-//static kCFStringEncodingMacUkrainian: CFStringEncoding = 0x98;
-//static kCFStringEncodingMacInuit: CFStringEncoding = 0xEC;
-//static kCFStringEncodingMacVT100: CFStringEncoding = 0xFC;
-//static kCFStringEncodingMacHFS: CFStringEncoding = 0xFF;
-// Defined above: kCFStringEncodingISOLatin1 = 0x0201
-//static kCFStringEncodingISOLatin2: CFStringEncoding = 0x0202;
-//static kCFStringEncodingISOLatin3: CFStringEncoding = 0x0203;
-//static kCFStringEncodingISOLatin4: CFStringEncoding = 0x0204;
-//static kCFStringEncodingISOLatinCyrillic: CFStringEncoding = 0x0205;
-//static kCFStringEncodingISOLatinArabic: CFStringEncoding = 0x0206;
-//static kCFStringEncodingISOLatinGreek: CFStringEncoding = 0x0207;
-//static kCFStringEncodingISOLatinHebrew: CFStringEncoding = 0x0208;
-//static kCFStringEncodingISOLatin5: CFStringEncoding = 0x0209;
-//static kCFStringEncodingISOLatin6: CFStringEncoding = 0x020A;
-//static kCFStringEncodingISOLatinThai: CFStringEncoding = 0x020B;
-//static kCFStringEncodingISOLatin7: CFStringEncoding = 0x020D;
-//static kCFStringEncodingISOLatin8: CFStringEncoding = 0x020E;
-//static kCFStringEncodingISOLatin9: CFStringEncoding = 0x020F;
-//static kCFStringEncodingISOLatin10: CFStringEncoding = 0x0210;
-//static kCFStringEncodingDOSLatinUS: CFStringEncoding = 0x0400;
-//static kCFStringEncodingDOSGreek: CFStringEncoding = 0x0405;
-//static kCFStringEncodingDOSBalticRim: CFStringEncoding = 0x0406;
-//static kCFStringEncodingDOSLatin1: CFStringEncoding = 0x0410;
-//static kCFStringEncodingDOSGreek1: CFStringEncoding = 0x0411;
-//static kCFStringEncodingDOSLatin2: CFStringEncoding = 0x0412;
-//static kCFStringEncodingDOSCyrillic: CFStringEncoding = 0x0413;
-//static kCFStringEncodingDOSTurkish: CFStringEncoding = 0x0414;
-//static kCFStringEncodingDOSPortuguese: CFStringEncoding = 0x0415;
-//static kCFStringEncodingDOSIcelandic: CFStringEncoding = 0x0416;
-//static kCFStringEncodingDOSHebrew: CFStringEncoding = 0x0417;
-//static kCFStringEncodingDOSCanadianFrench: CFStringEncoding = 0x0418;
-//static kCFStringEncodingDOSArabic: CFStringEncoding = 0x0419;
-//static kCFStringEncodingDOSNordic: CFStringEncoding = 0x041A;
-//static kCFStringEncodingDOSRussian: CFStringEncoding = 0x041B;
-//static kCFStringEncodingDOSGreek2: CFStringEncoding = 0x041C;
-//static kCFStringEncodingDOSThai: CFStringEncoding = 0x041D;
-//static kCFStringEncodingDOSJapanese: CFStringEncoding = 0x0420;
-//static kCFStringEncodingDOSChineseSimplif: CFStringEncoding = 0x0421;
-//static kCFStringEncodingDOSKorean: CFStringEncoding = 0x0422;
-//static kCFStringEncodingDOSChineseTrad: CFStringEncoding = 0x0423;
-// Defined above: kCFStringEncodingWindowsLatin1 = 0x0500
-//static kCFStringEncodingWindowsLatin2: CFStringEncoding = 0x0501;
-//static kCFStringEncodingWindowsCyrillic: CFStringEncoding = 0x0502;
-//static kCFStringEncodingWindowsGreek: CFStringEncoding = 0x0503;
-//static kCFStringEncodingWindowsLatin5: CFStringEncoding = 0x0504;
-//static kCFStringEncodingWindowsHebrew: CFStringEncoding = 0x0505;
-//static kCFStringEncodingWindowsArabic: CFStringEncoding = 0x0506;
-//static kCFStringEncodingWindowsBalticRim: CFStringEncoding = 0x0507;
-//static kCFStringEncodingWindowsVietnamese: CFStringEncoding = 0x0508;
-//static kCFStringEncodingWindowsKoreanJohab: CFStringEncoding = 0x0510;
-// Defined above: kCFStringEncodingASCII = 0x0600
-//static kCFStringEncodingANSEL: CFStringEncoding = 0x0601;
-//static kCFStringEncodingJIS_X0201_76: CFStringEncoding = 0x0620;
-//static kCFStringEncodingJIS_X0208_83: CFStringEncoding = 0x0621;
-//static kCFStringEncodingJIS_X0208_90: CFStringEncoding = 0x0622;
-//static kCFStringEncodingJIS_X0212_90: CFStringEncoding = 0x0623;
-//static kCFStringEncodingJIS_C6226_78: CFStringEncoding = 0x0624;
-//static kCFStringEncodingShiftJIS_X0213: CFStringEncoding = 0x0628;
-//static kCFStringEncodingShiftJIS_X0213_MenKuTen: CFStringEncoding = 0x0629;
-//static kCFStringEncodingGB_2312_80: CFStringEncoding = 0x0630;
-//static kCFStringEncodingGBK_95: CFStringEncoding = 0x0631;
-//static kCFStringEncodingGB_18030_2000: CFStringEncoding = 0x0632;
-//static kCFStringEncodingKSC_5601_87: CFStringEncoding = 0x0640;
-//static kCFStringEncodingKSC_5601_92_Johab: CFStringEncoding = 0x0641;
-//static kCFStringEncodingCNS_11643_92_P1: CFStringEncoding = 0x0651;
-//static kCFStringEncodingCNS_11643_92_P2: CFStringEncoding = 0x0652;
-//static kCFStringEncodingCNS_11643_92_P3: CFStringEncoding = 0x0653;
-//static kCFStringEncodingISO_2022_JP: CFStringEncoding = 0x0820;
-//static kCFStringEncodingISO_2022_JP_2: CFStringEncoding = 0x0821;
-//static kCFStringEncodingISO_2022_JP_1: CFStringEncoding = 0x0822;
-//static kCFStringEncodingISO_2022_JP_3: CFStringEncoding = 0x0823;
-//static kCFStringEncodingISO_2022_CN: CFStringEncoding = 0x0830;
-//static kCFStringEncodingISO_2022_CN_EXT: CFStringEncoding = 0x0831;
-//static kCFStringEncodingISO_2022_KR: CFStringEncoding = 0x0840;
-//static kCFStringEncodingEUC_JP: CFStringEncoding = 0x0920;
-//static kCFStringEncodingEUC_CN: CFStringEncoding = 0x0930;
-//static kCFStringEncodingEUC_TW: CFStringEncoding = 0x0931;
-//static kCFStringEncodingEUC_KR: CFStringEncoding = 0x0940;
-//static kCFStringEncodingShiftJIS: CFStringEncoding = 0x0A01;
-//static kCFStringEncodingKOI8_R: CFStringEncoding = 0x0A02;
-//static kCFStringEncodingBig5: CFStringEncoding = 0x0A03;
-//static kCFStringEncodingMacRomanLatin1: CFStringEncoding = 0x0A04;
-//static kCFStringEncodingHZ_GB_2312: CFStringEncoding = 0x0A05;
-//static kCFStringEncodingBig5_HKSCS_1999: CFStringEncoding = 0x0A06;
-//static kCFStringEncodingVISCII: CFStringEncoding = 0x0A07;
-//static kCFStringEncodingKOI8_U: CFStringEncoding = 0x0A08;
-//static kCFStringEncodingBig5_E: CFStringEncoding = 0x0A09;
-// Defined above: kCFStringEncodingNextStepLatin = 0x0B01
-//static kCFStringEncodingNextStepJapanese: CFStringEncoding = 0x0B02;
-//static kCFStringEncodingEBCDIC_US: CFStringEncoding = 0x0C01;
-//static kCFStringEncodingEBCDIC_CP037: CFStringEncoding = 0x0C02;
-//static kCFStringEncodingUTF7: CFStringEncoding = 0x04000100;
-//static kCFStringEncodingUTF7_IMAP: CFStringEncoding = 0x0A10;
-//static kCFStringEncodingShiftJIS_X0213_00: CFStringEncoding = 0x0628; /* Deprecated */
+pub type CFStringNormalizationForm = CFIndex;
+pub const kCFStringNormalizationFormD: CFStringNormalizationForm = 0;
+pub const kCFStringNormalizationFormKD: CFStringNormalizationForm = 1;
+pub const kCFStringNormalizationFormC: CFStringNormalizationForm = 2;
+pub const kCFStringNormalizationFormKC: CFStringNormalizationForm = 3;
#[repr(C)]
pub struct __CFString(c_void);
pub type CFStringRef = *const __CFString;
+pub type CFMutableStringRef = *mut __CFString;
+
+/* todo: The source code of the following functions is right in CFString.h */
+/*
+pub fn CFStringGetLongCharacterForSurrogatePair(surrogateHigh: UniChar, surrogateLow: UniChar) -> UTF32Char;
+pub fn CFStringGetSurrogatePairForLongCharacter(character: UTF32Char, surrogates: *mut UniChar) -> Boolean;
+pub fn CFStringIsSurrogateHighCharacter(character: UniChar) -> Boolean;
+pub fn CFStringIsSurrogateLowCharacter(character: UniChar) -> Boolean;
+pub fn CFStringInitInlineBuffer(str: CFStringRef, buf: *mut CFStringInlineBuffer, range: CFRange);
+pub fn CFStringGetCharacterFromInlineBuffer(buf: *mut CFStringInlineBuffer, idx: CFIndex) -> UniChar;
+*/
-extern {
+extern "C" {
/*
* CFString.h
*/
// N.B. organized according to "Functions by task" in docs
+ /* CFString */
/* Creating a CFString */
//fn CFSTR
- //fn CFStringCreateArrayBySeparatingStrings
- //fn CFStringCreateByCombiningStrings
- //fn CFStringCreateCopy
- //fn CFStringCreateFromExternalRepresentation
- pub fn CFStringCreateWithBytes(alloc: CFAllocatorRef,
- bytes: *const u8,
- numBytes: CFIndex,
- encoding: CFStringEncoding,
- isExternalRepresentation: Boolean)
- -> CFStringRef;
- pub fn CFStringCreateWithBytesNoCopy(alloc: CFAllocatorRef,
- bytes: *const u8,
- numBytes: CFIndex,
- encoding: CFStringEncoding,
- isExternalRepresentation: Boolean,
- contentsDeallocator: CFAllocatorRef)
- -> CFStringRef;
- //fn CFStringCreateWithCharacters
- pub fn CFStringCreateWithCharactersNoCopy(alloc: CFAllocatorRef,
- chars: *const UniChar,
- numChars: CFIndex,
- contentsDeallocator: CFAllocatorRef)
- -> CFStringRef;
- pub fn CFStringCreateWithCString(alloc: CFAllocatorRef,
- cStr: *const c_char,
- encoding: CFStringEncoding)
- -> CFStringRef;
- //fn CFStringCreateWithCStringNoCopy
- //fn CFStringCreateWithFormat
- //fn CFStringCreateWithFormatAndArguments
- //fn CFStringCreateWithPascalString
- //fn CFStringCreateWithPascalStringNoCopy
- //fn CFStringCreateWithSubstring
+ pub fn CFStringCreateArrayBySeparatingStrings(
+ alloc: CFAllocatorRef,
+ theString: CFStringRef,
+ separatorString: CFStringRef,
+ ) -> CFArrayRef;
+ pub fn CFStringCreateByCombiningStrings(
+ alloc: CFAllocatorRef,
+ theArray: CFArrayRef,
+ separatorString: CFStringRef,
+ ) -> CFStringRef;
+ pub fn CFStringCreateCopy(alloc: CFAllocatorRef, theString: CFStringRef) -> CFStringRef;
+ pub fn CFStringCreateFromExternalRepresentation(
+ alloc: CFAllocatorRef,
+ data: CFDataRef,
+ encoding: CFStringEncoding,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithBytes(
+ alloc: CFAllocatorRef,
+ bytes: *const UInt8,
+ numBytes: CFIndex,
+ encoding: CFStringEncoding,
+ isExternalRepresentation: Boolean,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithBytesNoCopy(
+ alloc: CFAllocatorRef,
+ bytes: *const UInt8,
+ numBytes: CFIndex,
+ encoding: CFStringEncoding,
+ isExternalRepresentation: Boolean,
+ contentsDeallocator: CFAllocatorRef,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithCharacters(
+ alloc: CFAllocatorRef,
+ chars: *const UniChar,
+ numChars: CFIndex,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithCharactersNoCopy(
+ alloc: CFAllocatorRef,
+ chars: *const UniChar,
+ numChars: CFIndex,
+ contentsDeallocator: CFAllocatorRef,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithCString(
+ alloc: CFAllocatorRef,
+ cStr: *const c_char,
+ encoding: CFStringEncoding,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithCStringNoCopy(
+ alloc: CFAllocatorRef,
+ cStr: *const c_char,
+ encoding: CFStringEncoding,
+ contentsDeallocator: CFAllocatorRef,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithFormat(
+ alloc: CFAllocatorRef,
+ formatOptions: CFDictionaryRef,
+ format: CFStringRef,
+ ...
+ ) -> CFStringRef;
+ //pub fn CFStringCreateWithFormatAndArguments(alloc: CFAllocatorRef, formatOptions: CFDictionaryRef, format: CFStringRef, arguments: va_list) -> CFStringRef;
+ pub fn CFStringCreateWithPascalString(
+ alloc: CFAllocatorRef,
+ pStr: ConstStr255Param,
+ encoding: CFStringEncoding,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithPascalStringNoCopy(
+ alloc: CFAllocatorRef,
+ pStr: ConstStr255Param,
+ encoding: CFStringEncoding,
+ contentsDeallocator: CFAllocatorRef,
+ ) -> CFStringRef;
+ pub fn CFStringCreateWithSubstring(
+ alloc: CFAllocatorRef,
+ str: CFStringRef,
+ range: CFRange,
+ ) -> CFStringRef;
/* Searching Strings */
- //fn CFStringCreateArrayWithFindResults
- //fn CFStringFind
- //fn CFStringFindCharacterFromSet
- //fn CFStringFindWithOptions
- //fn CFStringFindWithOptionsAndLocale
- //fn CFStringGetLineBounds
+ pub fn CFStringCreateArrayWithFindResults(
+ alloc: CFAllocatorRef,
+ theString: CFStringRef,
+ stringToFind: CFStringRef,
+ rangeToSearch: CFRange,
+ compareOptions: CFStringCompareFlags,
+ ) -> CFArrayRef;
+ pub fn CFStringFind(
+ theString: CFStringRef,
+ stringToFind: CFStringRef,
+ compareOptions: CFStringCompareFlags,
+ ) -> CFRange;
+ pub fn CFStringFindCharacterFromSet(
+ theString: CFStringRef,
+ theSet: CFCharacterSetRef,
+ rangeToSearch: CFRange,
+ searchOptions: CFStringCompareFlags,
+ result: *mut CFRange,
+ ) -> Boolean;
+ pub fn CFStringFindWithOptions(
+ theString: CFStringRef,
+ stringToFind: CFStringRef,
+ rangeToSearch: CFRange,
+ searchOptions: CFStringCompareFlags,
+ result: *mut CFRange,
+ ) -> Boolean;
+ pub fn CFStringFindWithOptionsAndLocale(
+ theString: CFStringRef,
+ stringToFind: CFStringRef,
+ rangeToSearch: CFRange,
+ searchOptions: CFStringCompareFlags,
+ locale: CFLocaleRef,
+ result: *mut CFRange,
+ ) -> Boolean;
+ pub fn CFStringGetLineBounds(
+ theString: CFStringRef,
+ range: CFRange,
+ lineBeginIndex: *mut CFIndex,
+ lineEndIndex: *mut CFIndex,
+ contentsEndIndex: *mut CFIndex,
+ );
/* Comparing Strings */
- //fn CFStringCompare
- //fn CFStringCompareWithOptions
- //fn CFStringCompareWithOptionsAndLocale
- //fn CFStringHasPrefix
- //fn CFStringHasSuffix
+ pub fn CFStringCompare(
+ theString1: CFStringRef,
+ theString2: CFStringRef,
+ compareOptions: CFStringCompareFlags,
+ ) -> CFComparisonResult;
+ pub fn CFStringCompareWithOptions(
+ theString1: CFStringRef,
+ theString2: CFStringRef,
+ rangeToCompare: CFRange,
+ compareOptions: CFStringCompareFlags,
+ ) -> CFComparisonResult;
+ pub fn CFStringCompareWithOptionsAndLocale(
+ theString1: CFStringRef,
+ theString2: CFStringRef,
+ rangeToCompare: CFRange,
+ compareOptions: CFStringCompareFlags,
+ locale: CFLocaleRef,
+ ) -> CFComparisonResult;
+ pub fn CFStringHasPrefix(theString: CFStringRef, prefix: CFStringRef) -> Boolean;
+ pub fn CFStringHasSuffix(theString: CFStringRef, suffix: CFStringRef) -> Boolean;
/* Accessing Characters */
- //fn CFStringCreateExternalRepresentation
- pub fn CFStringGetBytes(theString: CFStringRef,
- range: CFRange,
- encoding: CFStringEncoding,
- lossByte: u8,
- isExternalRepresentation: Boolean,
- buffer: *mut u8,
- maxBufLen: CFIndex,
- usedBufLen: *mut CFIndex)
- -> CFIndex;
- //fn CFStringGetCharacterAtIndex
- //fn CFStringGetCharacters
- //fn CFStringGetCharactersPtr
- //fn CFStringGetCharacterFromInlineBuffer
- pub fn CFStringGetCString(theString: CFStringRef,
- buffer: *mut c_char,
- bufferSize: CFIndex,
- encoding: CFStringEncoding)
- -> Boolean;
- pub fn CFStringGetCStringPtr(theString: CFStringRef,
- encoding: CFStringEncoding)
- -> *const c_char;
+ pub fn CFStringCreateExternalRepresentation(
+ alloc: CFAllocatorRef,
+ theString: CFStringRef,
+ encoding: CFStringEncoding,
+ lossByte: UInt8,
+ ) -> CFDataRef;
+ pub fn CFStringGetBytes(
+ theString: CFStringRef,
+ range: CFRange,
+ encoding: CFStringEncoding,
+ lossByte: UInt8,
+ isExternalRepresentation: Boolean,
+ buffer: *mut UInt8,
+ maxBufLen: CFIndex,
+ usedBufLen: *mut CFIndex,
+ ) -> CFIndex;
+ pub fn CFStringGetCharacterAtIndex(theString: CFStringRef, idx: CFIndex) -> UniChar;
+ pub fn CFStringGetCharacters(theString: CFStringRef, range: CFRange, buffer: *mut UniChar);
+ pub fn CFStringGetCharactersPtr(theString: CFStringRef) -> *const UniChar;
+ pub fn CFStringGetCString(
+ theString: CFStringRef,
+ buffer: *mut c_char,
+ bufferSize: CFIndex,
+ encoding: CFStringEncoding,
+ ) -> Boolean;
+ pub fn CFStringGetCStringPtr(
+ theString: CFStringRef,
+ encoding: CFStringEncoding,
+ ) -> *const c_char;
pub fn CFStringGetLength(theString: CFStringRef) -> CFIndex;
- //fn CFStringGetPascalString
- //fn CFStringGetPascalStringPtr
- //fn CFStringGetRangeOfComposedCharactersAtIndex
- //fn CFStringInitInlineBuffer
+ pub fn CFStringGetPascalString(
+ theString: CFStringRef,
+ buffer: StringPtr,
+ bufferSize: CFIndex,
+ encoding: CFStringEncoding,
+ ) -> Boolean;
+ pub fn CFStringGetPascalStringPtr(
+ theString: CFStringRef,
+ encoding: CFStringEncoding,
+ ) -> ConstStringPtr;
+ pub fn CFStringGetRangeOfComposedCharactersAtIndex(
+ theString: CFStringRef,
+ theIndex: CFIndex,
+ ) -> CFRange;
/* Working With Hyphenation */
- //fn CFStringGetHyphenationLocationBeforeIndex
- //fn CFStringIsHyphenationAvailableForLocale
+ pub fn CFStringGetHyphenationLocationBeforeIndex(
+ string: CFStringRef,
+ location: CFIndex,
+ limitRange: CFRange,
+ options: CFOptionFlags,
+ locale: CFLocaleRef,
+ character: *mut UTF32Char,
+ ) -> CFIndex;
+ pub fn CFStringIsHyphenationAvailableForLocale(locale: CFLocaleRef) -> Boolean;
/* Working With Encodings */
- //fn CFStringConvertEncodingToIANACharSetName
- //fn CFStringConvertEncodingToNSStringEncoding
- //fn CFStringConvertEncodingToWindowsCodepage
- //fn CFStringConvertIANACharSetNameToEncoding
- //fn CFStringConvertNSStringEncodingToEncoding
- //fn CFStringConvertWindowsCodepageToEncoding
- //fn CFStringGetFastestEncoding
- //fn CFStringGetListOfAvailableEncodings
- //fn CFStringGetMaximumSizeForEncoding
- //fn CFStringGetMostCompatibleMacStringEncoding
- //fn CFStringGetNameOfEncoding
- //fn CFStringGetSmallestEncoding
- //fn CFStringGetSystemEncoding
- //fn CFStringIsEncodingAvailable
+ pub fn CFStringConvertEncodingToIANACharSetName(encoding: CFStringEncoding) -> CFStringRef;
+ pub fn CFStringConvertEncodingToNSStringEncoding(encoding: CFStringEncoding) -> c_ulong;
+ pub fn CFStringConvertEncodingToWindowsCodepage(encoding: CFStringEncoding) -> UInt32;
+ pub fn CFStringConvertIANACharSetNameToEncoding(theString: CFStringRef) -> CFStringEncoding;
+ pub fn CFStringConvertNSStringEncodingToEncoding(encoding: c_ulong) -> CFStringEncoding;
+ pub fn CFStringConvertWindowsCodepageToEncoding(codepage: UInt32) -> CFStringEncoding;
+ pub fn CFStringGetFastestEncoding(theString: CFStringRef) -> CFStringEncoding;
+ pub fn CFStringGetListOfAvailableEncodings() -> *const CFStringEncoding;
+ pub fn CFStringGetMaximumSizeForEncoding(
+ length: CFIndex,
+ encoding: CFStringEncoding,
+ ) -> CFIndex;
+ pub fn CFStringGetMostCompatibleMacStringEncoding(
+ encoding: CFStringEncoding,
+ ) -> CFStringEncoding;
+ pub fn CFStringGetNameOfEncoding(encoding: CFStringEncoding) -> CFStringRef;
+ pub fn CFStringGetSmallestEncoding(theString: CFStringRef) -> CFStringEncoding;
+ pub fn CFStringGetSystemEncoding() -> CFStringEncoding;
+ pub fn CFStringIsEncodingAvailable(encoding: CFStringEncoding) -> Boolean;
/* Getting Numeric Values */
- //fn CFStringGetDoubleValue
- //fn CFStringGetIntValue
+ pub fn CFStringGetDoubleValue(str: CFStringRef) -> c_double;
+ pub fn CFStringGetIntValue(str: CFStringRef) -> SInt32;
/* Getting String Properties */
- //fn CFShowStr
+ pub fn CFShowStr(str: CFStringRef);
pub fn CFStringGetTypeID() -> CFTypeID;
/* String File System Representations */
- //fn CFStringCreateWithFileSystemRepresentation
- //fn CFStringGetFileSystemRepresentation
- //fn CFStringGetMaximumSizeOfFileSystemRepresentation
+ pub fn CFStringCreateWithFileSystemRepresentation(
+ alloc: CFAllocatorRef,
+ buffer: *const c_char,
+ ) -> CFStringRef;
+ pub fn CFStringGetFileSystemRepresentation(
+ string: CFStringRef,
+ buffer: *mut c_char,
+ maxBufLen: CFIndex,
+ ) -> Boolean;
+ pub fn CFStringGetMaximumSizeOfFileSystemRepresentation(string: CFStringRef) -> CFIndex;
/* Getting Paragraph Bounds */
- //fn CFStringGetParagraphBounds
+ pub fn CFStringGetParagraphBounds(
+ string: CFStringRef,
+ range: CFRange,
+ parBeginIndex: *mut CFIndex,
+ parEndIndex: *mut CFIndex,
+ contentsEndIndex: *mut CFIndex,
+ );
- /* Managing Surrogates */
- //fn CFStringGetLongCharacterForSurrogatePair
- //fn CFStringGetSurrogatePairForLongCharacter
- //fn CFStringIsSurrogateHighCharacter
- //fn CFStringIsSurrogateLowCharacter
+ /* CFMutableString */
+ /* CFMutableString Miscellaneous Functions */
+ pub fn CFStringAppend(theString: CFMutableStringRef, appendedString: CFStringRef);
+ pub fn CFStringAppendCharacters(
+ theString: CFMutableStringRef,
+ chars: *const UniChar,
+ numChars: CFIndex,
+ );
+ pub fn CFStringAppendCString(
+ theString: CFMutableStringRef,
+ cStr: *const c_char,
+ encoding: CFStringEncoding,
+ );
+ pub fn CFStringAppendFormat(
+ theString: CFMutableStringRef,
+ formatOptions: CFDictionaryRef,
+ format: CFStringRef,
+ ...
+ );
+ //pub fn CFStringAppendFormatAndArguments(theString: CFMutableStringRef, formatOptions: CFDictionaryRef, format: CFStringRef, arguments: va_list);
+ pub fn CFStringAppendPascalString(
+ theString: CFMutableStringRef,
+ pStr: ConstStr255Param,
+ encoding: CFStringEncoding,
+ );
+ pub fn CFStringCapitalize(theString: CFMutableStringRef, locale: CFLocaleRef);
+ pub fn CFStringCreateMutable(alloc: CFAllocatorRef, maxLength: CFIndex) -> CFMutableStringRef;
+ pub fn CFStringCreateMutableCopy(
+ alloc: CFAllocatorRef,
+ maxLength: CFIndex,
+ theString: CFStringRef,
+ ) -> CFMutableStringRef;
+ pub fn CFStringCreateMutableWithExternalCharactersNoCopy(
+ alloc: CFAllocatorRef,
+ chars: *mut UniChar,
+ numChars: CFIndex,
+ capacity: CFIndex,
+ externalCharactersAllocator: CFAllocatorRef,
+ ) -> CFMutableStringRef;
+ pub fn CFStringDelete(theString: CFMutableStringRef, range: CFRange);
+ pub fn CFStringFindAndReplace(
+ theString: CFMutableStringRef,
+ stringToFind: CFStringRef,
+ replacementString: CFStringRef,
+ rangeToSearch: CFRange,
+ compareOptions: CFStringCompareFlags,
+ ) -> CFIndex;
+ pub fn CFStringFold(
+ theString: CFMutableStringRef,
+ theFlags: CFStringCompareFlags,
+ theLocale: CFLocaleRef,
+ );
+ pub fn CFStringInsert(str: CFMutableStringRef, idx: CFIndex, insertedStr: CFStringRef);
+ pub fn CFStringLowercase(theString: CFMutableStringRef, locale: CFLocaleRef);
+ pub fn CFStringNormalize(theString: CFMutableStringRef, theForm: CFStringNormalizationForm);
+ pub fn CFStringPad(
+ theString: CFMutableStringRef,
+ padString: CFStringRef,
+ length: CFIndex,
+ indexIntoPad: CFIndex,
+ );
+ pub fn CFStringReplace(theString: CFMutableStringRef, range: CFRange, replacement: CFStringRef);
+ pub fn CFStringReplaceAll(theString: CFMutableStringRef, replacement: CFStringRef);
+ pub fn CFStringSetExternalCharactersNoCopy(
+ theString: CFMutableStringRef,
+ chars: *mut UniChar,
+ length: CFIndex,
+ capacity: CFIndex,
+ );
+ pub fn CFStringTransform(
+ string: CFMutableStringRef,
+ range: *mut CFRange,
+ transform: CFStringRef,
+ reverse: Boolean,
+ ) -> Boolean;
+ pub fn CFStringTrim(theString: CFMutableStringRef, trimString: CFStringRef);
+ pub fn CFStringTrimWhitespace(theString: CFMutableStringRef);
+ pub fn CFStringUppercase(theString: CFMutableStringRef, locale: CFLocaleRef);
}
diff --git a/third_party/rust/core-foundation-sys/src/string_tokenizer.rs b/third_party/rust/core-foundation-sys/src/string_tokenizer.rs
new file mode 100644
index 0000000000..b23d6a2d34
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/string_tokenizer.rs
@@ -0,0 +1,91 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::array::CFMutableArrayRef;
+use crate::base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFRange, CFTypeID, CFTypeRef};
+use crate::locale::CFLocaleRef;
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFStringTokenizer(c_void);
+pub type CFStringTokenizerRef = *mut __CFStringTokenizer;
+
+pub type CFStringTokenizerTokenType = CFOptionFlags;
+
+pub const kCFStringTokenizerTokenNone: CFStringTokenizerTokenType = 0;
+pub const kCFStringTokenizerTokenNormal: CFStringTokenizerTokenType = 1 << 0;
+pub const kCFStringTokenizerTokenHasSubTokensMask: CFStringTokenizerTokenType = 1 << 1;
+pub const kCFStringTokenizerTokenHasDerivedSubTokensMask: CFStringTokenizerTokenType = 1 << 2;
+pub const kCFStringTokenizerTokenHasHasNumbersMask: CFStringTokenizerTokenType = 1 << 3;
+pub const kCFStringTokenizerTokenHasNonLettersMask: CFStringTokenizerTokenType = 1 << 4;
+pub const kCFStringTokenizerTokenIsCJWordMask: CFStringTokenizerTokenType = 1 << 5;
+
+/* Tokenization Modifiers */
+pub const kCFStringTokenizerUnitWord: CFOptionFlags = 0;
+pub const kCFStringTokenizerUnitSentence: CFOptionFlags = 1;
+pub const kCFStringTokenizerUnitParagraph: CFOptionFlags = 2;
+pub const kCFStringTokenizerUnitLineBreak: CFOptionFlags = 3;
+pub const kCFStringTokenizerUnitWordBoundary: CFOptionFlags = 4;
+pub const kCFStringTokenizerAttributeLatinTranscription: CFOptionFlags = 1 << 16;
+pub const kCFStringTokenizerAttributeLanguage: CFOptionFlags = 1 << 17;
+
+extern "C" {
+ /*
+ * CFStringTokenizer.h
+ */
+
+ /* Creating a Tokenizer */
+ pub fn CFStringTokenizerCreate(
+ alloc: CFAllocatorRef,
+ string: CFStringRef,
+ range: CFRange,
+ options: CFOptionFlags,
+ locale: CFLocaleRef,
+ ) -> CFStringTokenizerRef;
+
+ /* Setting the String */
+ pub fn CFStringTokenizerSetString(
+ tokenizer: CFStringTokenizerRef,
+ string: CFStringRef,
+ range: CFRange,
+ );
+
+ /* Changing the Location */
+ pub fn CFStringTokenizerAdvanceToNextToken(
+ tokenizer: CFStringTokenizerRef,
+ ) -> CFStringTokenizerTokenType;
+ pub fn CFStringTokenizerGoToTokenAtIndex(
+ tokenizer: CFStringTokenizerRef,
+ index: CFIndex,
+ ) -> CFStringTokenizerTokenType;
+
+ /* Getting Information About the Current Token */
+ pub fn CFStringTokenizerCopyCurrentTokenAttribute(
+ tokenizer: CFStringTokenizerRef,
+ attribute: CFOptionFlags,
+ ) -> CFTypeRef;
+ pub fn CFStringTokenizerGetCurrentTokenRange(tokenizer: CFStringTokenizerRef) -> CFRange;
+ pub fn CFStringTokenizerGetCurrentSubTokens(
+ tokenizer: CFStringTokenizerRef,
+ ranges: *mut CFRange,
+ maxRangeLength: CFIndex,
+ derivedSubTokens: CFMutableArrayRef,
+ ) -> CFIndex;
+
+ /* Identifying a Language */
+ pub fn CFStringTokenizerCopyBestStringLanguage(
+ string: CFStringRef,
+ range: CFRange,
+ ) -> CFStringRef;
+
+ /* Getting the CFStringTokenizer Type ID */
+ pub fn CFStringTokenizerGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/timezone.rs b/third_party/rust/core-foundation-sys/src/timezone.rs
index 0b279db188..076062a491 100644
--- a/third_party/rust/core-foundation-sys/src/timezone.rs
+++ b/third_party/rust/core-foundation-sys/src/timezone.rs
@@ -9,21 +9,83 @@
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFTypeID};
-use date::{CFTimeInterval, CFAbsoluteTime};
-use string::CFStringRef;
+use crate::array::CFArrayRef;
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFTypeID};
+use crate::data::CFDataRef;
+use crate::date::{CFAbsoluteTime, CFTimeInterval};
+use crate::dictionary::CFDictionaryRef;
+use crate::locale::CFLocaleRef;
+use crate::notification_center::CFNotificationName;
+use crate::string::CFStringRef;
#[repr(C)]
pub struct __CFTimeZone(c_void);
pub type CFTimeZoneRef = *const __CFTimeZone;
+pub type CFTimeZoneNameStyle = CFIndex;
-extern {
- pub fn CFTimeZoneCopySystem() -> CFTimeZoneRef;
+/* Constants to specify styles for time zone names */
+pub const kCFTimeZoneNameStyleStandard: CFTimeZoneNameStyle = 0;
+pub const kCFTimeZoneNameStyleShortStandard: CFTimeZoneNameStyle = 1;
+pub const kCFTimeZoneNameStyleDaylightSaving: CFTimeZoneNameStyle = 2;
+pub const kCFTimeZoneNameStyleShortDaylightSaving: CFTimeZoneNameStyle = 3;
+pub const kCFTimeZoneNameStyleGeneric: CFTimeZoneNameStyle = 4;
+pub const kCFTimeZoneNameStyleShortGeneric: CFTimeZoneNameStyle = 5;
+
+extern "C" {
+ /*
+ * CFTimeZone.h
+ */
+
+ pub static kCFTimeZoneSystemTimeZoneDidChangeNotification: CFNotificationName;
+
+ /* Creating a Time Zone */
+ pub fn CFTimeZoneCreate(
+ allocator: CFAllocatorRef,
+ name: CFStringRef,
+ data: CFDataRef,
+ ) -> CFTimeZoneRef;
+ pub fn CFTimeZoneCreateWithName(
+ allocator: CFAllocatorRef,
+ name: CFStringRef,
+ tryAbbrev: Boolean,
+ ) -> CFTimeZoneRef;
+ pub fn CFTimeZoneCreateWithTimeIntervalFromGMT(
+ allocator: CFAllocatorRef,
+ interval: CFTimeInterval,
+ ) -> CFTimeZoneRef;
+
+ /* System and Default Time Zones and Information */
+ pub fn CFTimeZoneCopyAbbreviationDictionary() -> CFDictionaryRef;
+ pub fn CFTimeZoneCopyAbbreviation(tz: CFTimeZoneRef, at: CFAbsoluteTime) -> CFStringRef;
pub fn CFTimeZoneCopyDefault() -> CFTimeZoneRef;
- pub fn CFTimeZoneCreateWithTimeIntervalFromGMT(allocator: CFAllocatorRef, interval: CFTimeInterval) -> CFTimeZoneRef;
+ pub fn CFTimeZoneCopySystem() -> CFTimeZoneRef;
+ pub fn CFTimeZoneSetDefault(tz: CFTimeZoneRef);
+ pub fn CFTimeZoneCopyKnownNames() -> CFArrayRef;
+ pub fn CFTimeZoneResetSystem();
+ pub fn CFTimeZoneSetAbbreviationDictionary(dict: CFDictionaryRef);
+
+ /* Getting Information About Time Zones */
+ pub fn CFTimeZoneGetName(tz: CFTimeZoneRef) -> CFStringRef;
+ pub fn CFTimeZoneCopyLocalizedName(
+ tz: CFTimeZoneRef,
+ style: CFTimeZoneNameStyle,
+ locale: CFLocaleRef,
+ ) -> CFStringRef;
pub fn CFTimeZoneGetSecondsFromGMT(tz: CFTimeZoneRef, time: CFAbsoluteTime) -> CFTimeInterval;
+ pub fn CFTimeZoneGetData(tz: CFTimeZoneRef) -> CFDataRef;
+ /* Getting Daylight Savings Time Information */
+ pub fn CFTimeZoneIsDaylightSavingTime(tz: CFTimeZoneRef, at: CFAbsoluteTime) -> Boolean;
+ pub fn CFTimeZoneGetDaylightSavingTimeOffset(
+ tz: CFTimeZoneRef,
+ at: CFAbsoluteTime,
+ ) -> CFTimeInterval;
+ pub fn CFTimeZoneGetNextDaylightSavingTimeTransition(
+ tz: CFTimeZoneRef,
+ at: CFAbsoluteTime,
+ ) -> CFAbsoluteTime;
+
+ /* Getting the CFTimeZone Type ID */
pub fn CFTimeZoneGetTypeID() -> CFTypeID;
- pub fn CFTimeZoneGetName(tz: CFTimeZoneRef) -> CFStringRef;
}
diff --git a/third_party/rust/core-foundation-sys/src/tree.rs b/third_party/rust/core-foundation-sys/src/tree.rs
new file mode 100644
index 0000000000..da6fdd607d
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/tree.rs
@@ -0,0 +1,74 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{CFAllocatorRef, CFComparatorFunction, CFIndex, CFTypeID};
+use crate::string::CFStringRef;
+
+#[repr(C)]
+pub struct __CFTree(c_void);
+pub type CFTreeRef = *mut __CFTree;
+
+pub type CFTreeRetainCallBack = extern "C" fn(info: *const c_void) -> *const c_void;
+pub type CFTreeReleaseCallBack = extern "C" fn(info: *const c_void);
+pub type CFTreeCopyDescriptionCallBack = extern "C" fn(info: *const c_void) -> CFStringRef;
+pub type CFTreeApplierFunction = extern "C" fn(value: *const c_void, context: *mut c_void);
+
+#[repr(C)]
+pub struct CFTreeContext {
+ pub version: CFIndex,
+ pub info: *mut c_void,
+ pub retain: CFTreeRetainCallBack,
+ pub release: CFTreeReleaseCallBack,
+ pub copyDescription: CFTreeCopyDescriptionCallBack,
+}
+
+extern "C" {
+ /*
+ * CFTree.h
+ */
+ /* Creating Trees */
+ pub fn CFTreeCreate(allocator: CFAllocatorRef, context: *const CFTreeContext) -> CFTreeRef;
+
+ /* Modifying a Tree */
+ pub fn CFTreeAppendChild(tree: CFTreeRef, newChild: CFTreeRef);
+ pub fn CFTreeInsertSibling(tree: CFTreeRef, newSibling: CFTreeRef);
+ pub fn CFTreeRemoveAllChildren(tree: CFTreeRef);
+ pub fn CFTreePrependChild(tree: CFTreeRef, newChild: CFTreeRef);
+ pub fn CFTreeRemove(tree: CFTreeRef);
+ pub fn CFTreeSetContext(tree: CFTreeRef, context: *const CFTreeContext);
+
+ /* Sorting a Tree */
+ pub fn CFTreeSortChildren(
+ tree: CFTreeRef,
+ comparator: CFComparatorFunction,
+ context: *mut c_void,
+ );
+
+ /* Examining a Tree */
+ pub fn CFTreeFindRoot(tree: CFTreeRef) -> CFTreeRef;
+ pub fn CFTreeGetChildAtIndex(tree: CFTreeRef, idx: CFIndex) -> CFTreeRef;
+ pub fn CFTreeGetChildCount(tree: CFTreeRef) -> CFIndex;
+ pub fn CFTreeGetChildren(tree: CFTreeRef, children: *mut CFTreeRef);
+ pub fn CFTreeGetContext(tree: CFTreeRef, context: *mut CFTreeContext);
+ pub fn CFTreeGetFirstChild(tree: CFTreeRef) -> CFTreeRef;
+ pub fn CFTreeGetNextSibling(tree: CFTreeRef) -> CFTreeRef;
+ pub fn CFTreeGetParent(tree: CFTreeRef) -> CFTreeRef;
+
+ /* Performing an Operation on Tree Elements */
+ pub fn CFTreeApplyFunctionToChildren(
+ tree: CFTreeRef,
+ applier: CFTreeApplierFunction,
+ context: *mut c_void,
+ );
+
+ /* Getting the Tree Type ID */
+ pub fn CFTreeGetTypeID() -> CFTypeID;
+}
diff --git a/third_party/rust/core-foundation-sys/src/url.rs b/third_party/rust/core-foundation-sys/src/url.rs
index 08e7bcd9fe..2274d3608f 100644
--- a/third_party/rust/core-foundation-sys/src/url.rs
+++ b/third_party/rust/core-foundation-sys/src/url.rs
@@ -9,12 +9,14 @@
use std::os::raw::c_void;
-use base::{CFOptionFlags, CFIndex, CFAllocatorRef, Boolean, CFTypeID, CFTypeRef, SInt32};
-use data::CFDataRef;
-use array::CFArrayRef;
-use dictionary::CFDictionaryRef;
-use string::{CFStringRef, CFStringEncoding};
-use error::CFErrorRef;
+use crate::array::CFArrayRef;
+use crate::base::{
+ Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFRange, CFTypeID, CFTypeRef, SInt32,
+};
+use crate::data::CFDataRef;
+use crate::dictionary::CFDictionaryRef;
+use crate::error::CFErrorRef;
+use crate::string::{CFStringEncoding, CFStringRef};
#[repr(C)]
pub struct __CFURL(c_void);
@@ -28,95 +30,330 @@ pub type CFURLBookmarkFileCreationOptions = CFOptionFlags;
pub type CFURLPathStyle = CFIndex;
/* typedef CF_ENUM(CFIndex, CFURLPathStyle) */
-pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0;
-pub const kCFURLHFSPathStyle: CFURLPathStyle = 1;
+pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0;
+pub const kCFURLHFSPathStyle: CFURLPathStyle = 1;
pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2;
-pub static kCFURLBookmarkCreationPreferFileIDResolutionMask: CFURLBookmarkCreationOptions =
- (1u32 << 8) as usize;
+/* Bookmark Data Creation Options */
pub static kCFURLBookmarkCreationMinimalBookmarkMask: CFURLBookmarkCreationOptions =
(1u32 << 9) as usize;
pub static kCFURLBookmarkCreationSuitableForBookmarkFile: CFURLBookmarkCreationOptions =
(1u32 << 10) as usize;
+
+#[cfg(target_os = "macos")]
pub static kCFURLBookmarkCreationWithSecurityScope: CFURLBookmarkCreationOptions =
(1u32 << 11) as usize;
+
+#[cfg(target_os = "macos")]
pub static kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess: CFURLBookmarkCreationOptions =
(1u32 << 12) as usize;
-// TODO: there are a lot of missing keys and constants. Add if you are bored or need them.
+pub static kCFURLBookmarkCreationWithoutImplicitSecurityScope: CFURLBookmarkCreationOptions =
+ (1u32 << 29) as usize;
+
+pub static kCFURLBookmarkCreationPreferFileIDResolutionMask: CFURLBookmarkCreationOptions =
+ (1u32 << 8) as usize; // deprecated
+
+/* The types of components in a URL. */
+pub type CFURLComponentType = CFIndex;
+pub const kCFURLComponentScheme: CFIndex = 1;
+pub const kCFURLComponentNetLocation: CFIndex = 2;
+pub const kCFURLComponentPath: CFIndex = 3;
+pub const kCFURLComponentResourceSpecifier: CFIndex = 4;
+pub const kCFURLComponentUser: CFIndex = 5;
+pub const kCFURLComponentPassword: CFIndex = 6;
+pub const kCFURLComponentUserInfo: CFIndex = 7;
+pub const kCFURLComponentHost: CFIndex = 8;
+pub const kCFURLComponentPort: CFIndex = 9;
+pub const kCFURLComponentParameterString: CFIndex = 10;
+pub const kCFURLComponentQuery: CFIndex = 11;
+pub const kCFURLComponentFragment: CFIndex = 12;
-extern {
+/* Bookmark Data Resolution Options */
+pub const kCFURLBookmarkResolutionWithoutUIMask: CFURLBookmarkResolutionOptions =
+ (1u32 << 8) as usize;
+pub const kCFURLBookmarkResolutionWithoutMountingMask: CFURLBookmarkResolutionOptions =
+ (1u32 << 9) as usize;
+#[cfg(target_os = "macos")]
+pub const kCFURLBookmarkResolutionWithSecurityScope: CFURLBookmarkResolutionOptions =
+ (1u32 << 10) as usize;
+//pub const kCFURLBookmarkResolutionWithoutImplicitStartAccessing: CFURLBookmarkResolutionOptions = ( 1u32 << 15 ) as usize; // macos(11.2)+
+pub const kCFBookmarkResolutionWithoutUIMask: CFURLBookmarkResolutionOptions = (1u32 << 8) as usize;
+pub const kCFBookmarkResolutionWithoutMountingMask: CFURLBookmarkResolutionOptions =
+ (1u32 << 9) as usize;
+
+extern "C" {
/*
* CFURL.h
*/
/* Common File System Resource Keys */
- pub static kCFURLAttributeModificationDateKey: CFStringRef;
- pub static kCFURLContentAccessDateKey: CFStringRef;
- pub static kCFURLContentModificationDateKey: CFStringRef;
- pub static kCFURLCreationDateKey: CFStringRef;
- pub static kCFURLFileResourceIdentifierKey: CFStringRef;
- pub static kCFURLFileSecurityKey: CFStringRef;
- pub static kCFURLHasHiddenExtensionKey: CFStringRef;
- pub static kCFURLIsDirectoryKey: CFStringRef;
- pub static kCFURLIsExecutableKey: CFStringRef;
- pub static kCFURLIsHiddenKey: CFStringRef;
- pub static kCFURLIsPackageKey: CFStringRef;
- pub static kCFURLIsReadableKey: CFStringRef;
+ pub static kCFURLNameKey: CFStringRef;
+ pub static kCFURLLocalizedNameKey: CFStringRef;
pub static kCFURLIsRegularFileKey: CFStringRef;
+ pub static kCFURLIsDirectoryKey: CFStringRef;
pub static kCFURLIsSymbolicLinkKey: CFStringRef;
+ pub static kCFURLIsVolumeKey: CFStringRef;
+ pub static kCFURLIsPackageKey: CFStringRef;
+ pub static kCFURLIsApplicationKey: CFStringRef;
+ // pub static kCFURLApplicationIsScriptableKey: CFStringRef; //macos(10.11)+
+
pub static kCFURLIsSystemImmutableKey: CFStringRef;
pub static kCFURLIsUserImmutableKey: CFStringRef;
- pub static kCFURLIsVolumeKey: CFStringRef;
- pub static kCFURLIsWritableKey: CFStringRef;
- pub static kCFURLLabelNumberKey: CFStringRef;
+ pub static kCFURLIsHiddenKey: CFStringRef;
+ pub static kCFURLHasHiddenExtensionKey: CFStringRef;
+ pub static kCFURLCreationDateKey: CFStringRef;
+ pub static kCFURLContentAccessDateKey: CFStringRef;
+ pub static kCFURLContentModificationDateKey: CFStringRef;
+ pub static kCFURLAttributeModificationDateKey: CFStringRef;
+ // pub static kCFURLFileIdentifierKey: CFStringRef; //macos(13.3)+
+ // pub static kCFURLFileContentIdentifierKey: CFStringRef; //macos(11.0)+
+ // pub static kCFURLMayShareFileContentKey: CFStringRef; //macos(11.0)+
+ // pub static kCFURLMayHaveExtendedAttributesKey: CFStringRef; //macos(11.0)+
+ // pub static kCFURLIsPurgeableKey: CFStringRef; //macos(11.0)+
+ // pub static kCFURLIsSparseKey: CFStringRef; //macos(11.0)+
+
pub static kCFURLLinkCountKey: CFStringRef;
- pub static kCFURLLocalizedLabelKey: CFStringRef;
- pub static kCFURLLocalizedNameKey: CFStringRef;
- pub static kCFURLLocalizedTypeDescriptionKey: CFStringRef;
- pub static kCFURLNameKey: CFStringRef;
pub static kCFURLParentDirectoryURLKey: CFStringRef;
- pub static kCFURLPreferredIOBlockSizeKey: CFStringRef;
- pub static kCFURLTypeIdentifierKey: CFStringRef;
- pub static kCFURLVolumeIdentifierKey: CFStringRef;
pub static kCFURLVolumeURLKey: CFStringRef;
- #[cfg(feature="mac_os_10_8_features")]
+ pub static kCFURLTypeIdentifierKey: CFStringRef; //deprecated
+
+ pub static kCFURLLocalizedTypeDescriptionKey: CFStringRef;
+ pub static kCFURLLabelNumberKey: CFStringRef;
+ pub static kCFURLLabelColorKey: CFStringRef; //deprecated
+ pub static kCFURLLocalizedLabelKey: CFStringRef;
+ pub static kCFURLEffectiveIconKey: CFStringRef; //deprecated
+ pub static kCFURLCustomIconKey: CFStringRef; //deprecated
+
+ pub static kCFURLFileResourceIdentifierKey: CFStringRef;
+ pub static kCFURLVolumeIdentifierKey: CFStringRef;
+ pub static kCFURLPreferredIOBlockSizeKey: CFStringRef;
+ pub static kCFURLIsReadableKey: CFStringRef;
+ pub static kCFURLIsWritableKey: CFStringRef;
+ pub static kCFURLIsExecutableKey: CFStringRef;
+ pub static kCFURLFileSecurityKey: CFStringRef;
+
+ #[cfg(feature = "mac_os_10_8_features")]
#[cfg_attr(feature = "mac_os_10_7_support", linkage = "extern_weak")]
pub static kCFURLIsExcludedFromBackupKey: CFStringRef;
+ // pub static kCFURLTagNamesKey: CFStringRef; //macos(10.9)+
+ #[cfg(feature = "mac_os_10_8_features")]
+ #[cfg_attr(feature = "mac_os_10_7_support", linkage = "extern_weak")]
+ pub static kCFURLPathKey: CFStringRef; // macos(10.8)+
+ pub static kCFURLCanonicalPathKey: CFStringRef; // macos(10.12)+
+
+ pub static kCFURLIsMountTriggerKey: CFStringRef;
+
+ // pub static kCFURLGenerationIdentifierKey: CFStringRef; // macos(10.10)+
+ // pub static kCFURLDocumentIdentifierKey: CFStringRef; // macos(10.10)+
+ // pub static kCFURLAddedToDirectoryDateKey: CFStringRef; // macos(10.10)+
+ // pub static kCFURLQuarantinePropertiesKey: CFStringRef; // macos(10.10)+
+
pub static kCFURLFileResourceTypeKey: CFStringRef;
+ /* File Resource Types. The file system object type values returned for the kCFURLFileResourceTypeKey */
+ pub static kCFURLFileResourceTypeNamedPipe: CFStringRef;
+ pub static kCFURLFileResourceTypeCharacterSpecial: CFStringRef;
+ pub static kCFURLFileResourceTypeDirectory: CFStringRef;
+ pub static kCFURLFileResourceTypeBlockSpecial: CFStringRef;
+ pub static kCFURLFileResourceTypeRegular: CFStringRef;
+ pub static kCFURLFileResourceTypeSymbolicLink: CFStringRef;
+ pub static kCFURLFileResourceTypeSocket: CFStringRef;
+ pub static kCFURLFileResourceTypeUnknown: CFStringRef;
+
+ /* File Property Keys */
+ pub static kCFURLFileSizeKey: CFStringRef;
+ pub static kCFURLFileAllocatedSizeKey: CFStringRef;
+ pub static kCFURLTotalFileSizeKey: CFStringRef;
+ pub static kCFURLTotalFileAllocatedSizeKey: CFStringRef;
+ pub static kCFURLIsAliasFileKey: CFStringRef;
+
+ // pub static kCFURLFileProtectionKey: CFStringRef; // ios(9.0)+
+
+ /* The protection level values returned for the kCFURLFileProtectionKey */
+ // pub static kCFURLFileProtectionNone: CFStringRef; // ios(9.0)+
+ // pub static kCFURLFileProtectionComplete: CFStringRef; // ios(9.0)+
+ // pub static kCFURLFileProtectionCompleteUnlessOpen: CFStringRef; // ios(9.0)+
+ // pub static kCFURLFileProtectionCompleteUntilFirstUserAuthentication: CFStringRef; // ios(9.0)+
+
+ /* Volume Property Keys */
+ pub static kCFURLVolumeLocalizedFormatDescriptionKey: CFStringRef;
+ pub static kCFURLVolumeTotalCapacityKey: CFStringRef;
+ pub static kCFURLVolumeAvailableCapacityKey: CFStringRef;
+ //pub static kCFURLVolumeAvailableCapacityForImportantUsageKey: CFStringRef; //macos(10.13)+
+ //pub static kCFURLVolumeAvailableCapacityForOpportunisticUsageKey: CFStringRef; //macos(10.13)+
+
+ pub static kCFURLVolumeResourceCountKey: CFStringRef;
+ pub static kCFURLVolumeSupportsPersistentIDsKey: CFStringRef;
+ pub static kCFURLVolumeSupportsSymbolicLinksKey: CFStringRef;
+ pub static kCFURLVolumeSupportsHardLinksKey: CFStringRef;
+ pub static kCFURLVolumeSupportsJournalingKey: CFStringRef;
+ pub static kCFURLVolumeIsJournalingKey: CFStringRef;
+ pub static kCFURLVolumeSupportsSparseFilesKey: CFStringRef;
+ pub static kCFURLVolumeSupportsZeroRunsKey: CFStringRef;
+ pub static kCFURLVolumeSupportsCaseSensitiveNamesKey: CFStringRef;
+ pub static kCFURLVolumeSupportsCasePreservedNamesKey: CFStringRef;
+ pub static kCFURLVolumeSupportsRootDirectoryDatesKey: CFStringRef;
+ pub static kCFURLVolumeSupportsVolumeSizesKey: CFStringRef;
+ pub static kCFURLVolumeSupportsRenamingKey: CFStringRef;
+ pub static kCFURLVolumeSupportsAdvisoryFileLockingKey: CFStringRef;
+ pub static kCFURLVolumeSupportsExtendedSecurityKey: CFStringRef;
+ pub static kCFURLVolumeIsBrowsableKey: CFStringRef;
+ pub static kCFURLVolumeMaximumFileSizeKey: CFStringRef;
+ pub static kCFURLVolumeIsEjectableKey: CFStringRef;
+ pub static kCFURLVolumeIsRemovableKey: CFStringRef;
+ pub static kCFURLVolumeIsInternalKey: CFStringRef;
+ pub static kCFURLVolumeIsAutomountedKey: CFStringRef;
+ pub static kCFURLVolumeIsLocalKey: CFStringRef;
+ pub static kCFURLVolumeIsReadOnlyKey: CFStringRef;
+ pub static kCFURLVolumeCreationDateKey: CFStringRef;
+ pub static kCFURLVolumeURLForRemountingKey: CFStringRef;
+ pub static kCFURLVolumeUUIDStringKey: CFStringRef;
+ pub static kCFURLVolumeNameKey: CFStringRef;
+ pub static kCFURLVolumeLocalizedNameKey: CFStringRef;
+ // pub static kCFURLVolumeIsEncryptedKey: CFStringRef; //macos(10.12)+
+ // pub static kCFURLVolumeIsRootFileSystemKey: CFStringRef; //macos(10.12)+
+ // pub static kCFURLVolumeSupportsCompressionKey: CFStringRef; //macos(10.12)+
+ // pub static kCFURLVolumeSupportsFileCloningKey: CFStringRef; //macos(10.12)+
+ // pub static kCFURLVolumeSupportsSwapRenamingKey: CFStringRef; //macos(10.12)+
+ // pub static kCFURLVolumeSupportsExclusiveRenamingKey: CFStringRef; //macos(10.12)+
+ // pub static kCFURLVolumeSupportsImmutableFilesKey: CFStringRef; //macos(10.13)+
+ // pub static kCFURLVolumeSupportsAccessPermissionsKey: CFStringRef; //macos(10.13)+
+ // pub static kCFURLVolumeSupportsFileProtectionKey: CFStringRef; //macos(11.0)+
+ // pub static kCFURLVolumeTypeNameKey: CFStringRef; //macos(13.3)+
+ // pub static kCFURLVolumeSubtypeKey: CFStringRef; //macos(13.3)+
+ // pub static kCFURLVolumeMountFromLocationKey: CFStringRef; //macos(13.3)+
+
+ /* iCloud Constants */
+ pub static kCFURLIsUbiquitousItemKey: CFStringRef;
+ pub static kCFURLUbiquitousItemHasUnresolvedConflictsKey: CFStringRef;
+ pub static kCFURLUbiquitousItemIsDownloadedKey: CFStringRef; // deprecated
+ pub static kCFURLUbiquitousItemIsDownloadingKey: CFStringRef;
+ pub static kCFURLUbiquitousItemIsUploadedKey: CFStringRef;
+ pub static kCFURLUbiquitousItemIsUploadingKey: CFStringRef;
+ pub static kCFURLUbiquitousItemPercentDownloadedKey: CFStringRef; // deprecated
+ pub static kCFURLUbiquitousItemPercentUploadedKey: CFStringRef; // deprecated
+ // pub static kCFURLUbiquitousItemDownloadingStatusKey: CFStringRef; // macos(10.9)+
+ // pub static kCFURLUbiquitousItemDownloadingErrorKey: CFStringRef; // macos(10.9)+
+ // pub static kCFURLUbiquitousItemUploadingErrorKey: CFStringRef; // macos(10.9)+
+ // pub static kCFURLUbiquitousItemIsExcludedFromSyncKey: CFStringRef; // macos(11.3)+
+
+ /* The values returned for kCFURLUbiquitousItemDownloadingStatusKey */
+ // pub static kCFURLUbiquitousItemDownloadingStatusNotDownloaded: CFStringRef; // macos(10.9)+
+ // pub static kCFURLUbiquitousItemDownloadingStatusDownloaded: CFStringRef; // macos(10.9)+
+ // pub static kCFURLUbiquitousItemDownloadingStatusCurrent: CFStringRef; // macos(10.9)+
+
+ /* CFError userInfo Dictionary Keys */
+ pub static kCFURLKeysOfUnsetValuesKey: CFStringRef;
+
/* Creating a CFURL */
pub fn CFURLCopyAbsoluteURL(anURL: CFURLRef) -> CFURLRef;
- pub fn CFURLCreateAbsoluteURLWithBytes(allocator: CFAllocatorRef, relativeURLBytes: *const u8, length: CFIndex, encoding: CFStringEncoding, baseURL: CFURLRef, useCompatibilityMode: Boolean) -> CFURLRef;
- pub fn CFURLCreateByResolvingBookmarkData(allocator: CFAllocatorRef, bookmark: CFDataRef, options: CFURLBookmarkResolutionOptions, relativeToURL: CFURLRef, resourcePropertiesToInclude: CFArrayRef, isStale: *mut Boolean, error: *mut CFErrorRef) -> CFURLRef;
- //fn CFURLCreateCopyAppendingPathComponent
- //fn CFURLCreateCopyAppendingPathExtension
- //fn CFURLCreateCopyDeletingLastPathComponent
- //fn CFURLCreateCopyDeletingPathExtension
- pub fn CFURLCreateFilePathURL(allocator: CFAllocatorRef, url: CFURLRef, error: *mut CFErrorRef) -> CFURLRef;
- //fn CFURLCreateFileReferenceURL
- pub fn CFURLCreateFromFileSystemRepresentation(allocator: CFAllocatorRef, buffer: *const u8, bufLen: CFIndex, isDirectory: Boolean) -> CFURLRef;
- //fn CFURLCreateFromFileSystemRepresentationRelativeToBase
- //fn CFURLCreateFromFSRef
- pub fn CFURLCreateWithBytes(allocator: CFAllocatorRef, URLBytes: *const u8, length: CFIndex, encoding: CFStringEncoding, baseURL: CFURLRef) -> CFURLRef;
- pub fn CFURLCreateWithFileSystemPath(allocator: CFAllocatorRef, filePath: CFStringRef, pathStyle: CFURLPathStyle, isDirectory: Boolean) -> CFURLRef;
- pub fn CFURLCreateWithFileSystemPathRelativeToBase(allocator: CFAllocatorRef, filePath: CFStringRef, pathStyle: CFURLPathStyle, isDirectory: Boolean, baseURL: CFURLRef) -> CFURLRef;
- //fn CFURLCreateWithString(allocator: CFAllocatorRef, urlString: CFStringRef,
- // baseURL: CFURLRef) -> CFURLRef;
+ pub fn CFURLCreateAbsoluteURLWithBytes(
+ allocator: CFAllocatorRef,
+ relativeURLBytes: *const u8,
+ length: CFIndex,
+ encoding: CFStringEncoding,
+ baseURL: CFURLRef,
+ useCompatibilityMode: Boolean,
+ ) -> CFURLRef;
+ pub fn CFURLCreateByResolvingBookmarkData(
+ allocator: CFAllocatorRef,
+ bookmark: CFDataRef,
+ options: CFURLBookmarkResolutionOptions,
+ relativeToURL: CFURLRef,
+ resourcePropertiesToInclude: CFArrayRef,
+ isStale: *mut Boolean,
+ error: *mut CFErrorRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateCopyAppendingPathComponent(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ pathComponent: CFStringRef,
+ isDirectory: Boolean,
+ ) -> CFURLRef;
+ pub fn CFURLCreateCopyAppendingPathExtension(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ extension: CFStringRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateCopyDeletingLastPathComponent(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateCopyDeletingPathExtension(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateFilePathURL(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ error: *mut CFErrorRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateFileReferenceURL(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ error: *mut CFErrorRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateFromFileSystemRepresentation(
+ allocator: CFAllocatorRef,
+ buffer: *const u8,
+ bufLen: CFIndex,
+ isDirectory: Boolean,
+ ) -> CFURLRef;
+ pub fn CFURLCreateFromFileSystemRepresentationRelativeToBase(
+ allocator: CFAllocatorRef,
+ buffer: *const u8,
+ bufLen: CFIndex,
+ isDirectory: Boolean,
+ baseURL: CFURLRef,
+ ) -> CFURLRef;
+ //pub fn CFURLCreateFromFSRef(allocator: CFAllocatorRef, fsRef: *const FSRef) -> CFURLRef
+ pub fn CFURLCreateWithBytes(
+ allocator: CFAllocatorRef,
+ URLBytes: *const u8,
+ length: CFIndex,
+ encoding: CFStringEncoding,
+ baseURL: CFURLRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateWithFileSystemPath(
+ allocator: CFAllocatorRef,
+ filePath: CFStringRef,
+ pathStyle: CFURLPathStyle,
+ isDirectory: Boolean,
+ ) -> CFURLRef;
+ pub fn CFURLCreateWithFileSystemPathRelativeToBase(
+ allocator: CFAllocatorRef,
+ filePath: CFStringRef,
+ pathStyle: CFURLPathStyle,
+ isDirectory: Boolean,
+ baseURL: CFURLRef,
+ ) -> CFURLRef;
+ pub fn CFURLCreateWithString(
+ allocator: CFAllocatorRef,
+ URLString: CFStringRef,
+ baseURL: CFURLRef,
+ ) -> CFURLRef;
/* Accessing the Parts of a URL */
pub fn CFURLCanBeDecomposed(anURL: CFURLRef) -> Boolean;
pub fn CFURLCopyFileSystemPath(anURL: CFURLRef, pathStyle: CFURLPathStyle) -> CFStringRef;
- pub fn CFURLCopyFragment(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef;
+ pub fn CFURLCopyFragment(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef)
+ -> CFStringRef;
pub fn CFURLCopyHostName(anURL: CFURLRef) -> CFStringRef;
pub fn CFURLCopyLastPathComponent(anURL: CFURLRef) -> CFStringRef;
pub fn CFURLCopyNetLocation(anURL: CFURLRef) -> CFStringRef;
- pub fn CFURLCopyParameterString(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef;
+ pub fn CFURLCopyParameterString(
+ anURL: CFURLRef,
+ charactersToLeaveEscaped: CFStringRef,
+ ) -> CFStringRef; // deprecated
pub fn CFURLCopyPassword(anURL: CFURLRef) -> CFStringRef;
pub fn CFURLCopyPath(anURL: CFURLRef) -> CFStringRef;
pub fn CFURLCopyPathExtension(anURL: CFURLRef) -> CFStringRef;
- pub fn CFURLCopyQueryString(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef;
+ pub fn CFURLCopyQueryString(
+ anURL: CFURLRef,
+ charactersToLeaveEscaped: CFStringRef,
+ ) -> CFStringRef;
pub fn CFURLCopyResourceSpecifier(anURL: CFURLRef) -> CFStringRef;
pub fn CFURLCopyScheme(anURL: CFURLRef) -> CFStringRef;
pub fn CFURLCopyStrictPath(anURL: CFURLRef, isAbsolute: *mut Boolean) -> CFStringRef;
@@ -125,45 +362,120 @@ extern {
pub fn CFURLHasDirectoryPath(anURL: CFURLRef) -> Boolean;
/* Converting URLs to Other Representations */
- //fn CFURLCreateData(allocator: CFAllocatorRef, url: CFURLRef,
- // encoding: CFStringEncoding, escapeWhitespace: bool) -> CFDataRef;
- //fn CFURLCreateStringByAddingPercentEscapes
- //fn CFURLCreateStringByReplacingPercentEscapes
- //fn CFURLCreateStringByReplacingPercentEscapesUsingEncoding
- pub fn CFURLGetFileSystemRepresentation(anURL: CFURLRef, resolveAgainstBase: Boolean, buffer: *mut u8, maxBufLen: CFIndex) -> Boolean;
-
- //fn CFURLGetFSRef
+ pub fn CFURLCreateData(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ encoding: CFStringEncoding,
+ escapeWhitespace: Boolean,
+ ) -> CFDataRef;
+ pub fn CFURLCreateStringByAddingPercentEscapes(
+ allocator: CFAllocatorRef,
+ originalString: CFStringRef,
+ charactersToLeaveUnescaped: CFStringRef,
+ legalURLCharactersToBeEscaped: CFStringRef,
+ encoding: CFStringEncoding,
+ ) -> CFStringRef; // API_DEPRECATED("Use [NSString stringByAddingPercentEncodingWithAllowedCharacters:] instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent (since each URL component or subcomponent has different rules for what characters are valid).", macos(10.0,10.11), ios(2.0,9.0), watchos(2.0,2.0), tvos(9.0,9.0));
+ pub fn CFURLCreateStringByReplacingPercentEscapes(
+ allocator: CFAllocatorRef,
+ originalString: CFStringRef,
+ charactersToLeaveEscaped: CFStringRef,
+ ) -> CFStringRef;
+ pub fn CFURLCreateStringByReplacingPercentEscapesUsingEncoding(
+ allocator: CFAllocatorRef,
+ origString: CFStringRef,
+ charsToLeaveEscaped: CFStringRef,
+ encoding: CFStringEncoding,
+ ) -> CFStringRef; // deprecated
+ pub fn CFURLGetFileSystemRepresentation(
+ anURL: CFURLRef,
+ resolveAgainstBase: Boolean,
+ buffer: *mut u8,
+ maxBufLen: CFIndex,
+ ) -> Boolean;
+ //pub fn CFURLIsFileReferenceURL(url: CFURLRef) -> Boolean; // macos(10.9)+
+ //pub fn CFURLGetFSRef(url: CFURLRef, fsRef: *mut FSRef) -> Boolean;
pub fn CFURLGetString(anURL: CFURLRef) -> CFStringRef;
/* Getting URL Properties */
- //fn CFURLGetBaseURL(anURL: CFURLRef) -> CFURLRef;
+ pub fn CFURLGetBaseURL(anURL: CFURLRef) -> CFURLRef;
pub fn CFURLGetBytes(anURL: CFURLRef, buffer: *mut u8, bufferLength: CFIndex) -> CFIndex;
- //fn CFURLGetByteRangeForComponent
+ pub fn CFURLGetByteRangeForComponent(
+ url: CFURLRef,
+ component: CFURLComponentType,
+ rangeIncludingSeparators: *mut CFRange,
+ ) -> CFRange;
pub fn CFURLGetTypeID() -> CFTypeID;
- //fn CFURLResourceIsReachable
+ pub fn CFURLResourceIsReachable(url: CFURLRef, error: *mut CFErrorRef) -> Boolean;
/* Getting and Setting File System Resource Properties */
pub fn CFURLClearResourcePropertyCache(url: CFURLRef);
- //fn CFURLClearResourcePropertyCacheForKey
- //fn CFURLCopyResourcePropertiesForKeys
- //fn CFURLCopyResourcePropertyForKey
- pub fn CFURLCreateResourcePropertiesForKeysFromBookmarkData(allocator: CFAllocatorRef, resourcePropertiesToReturn: CFArrayRef, bookmark: CFDataRef) -> CFDictionaryRef;
- pub fn CFURLCreateResourcePropertyForKeyFromBookmarkData(allocator: CFAllocatorRef, resourcePropertyKey: CFStringRef, bookmark: CFDataRef) -> CFTypeRef;
- //fn CFURLSetResourcePropertiesForKeys
- pub fn CFURLSetResourcePropertyForKey(url: CFURLRef, key: CFStringRef, value: CFTypeRef, error: *mut CFErrorRef) -> Boolean;
- //fn CFURLSetTemporaryResourcePropertyForKey
+ pub fn CFURLClearResourcePropertyCacheForKey(url: CFURLRef, key: CFStringRef);
+ pub fn CFURLCopyResourcePropertiesForKeys(
+ url: CFURLRef,
+ keys: CFArrayRef,
+ error: *mut CFErrorRef,
+ ) -> CFDictionaryRef;
+ //pub fn CFURLCopyResourcePropertyForKey(url: CFURLRef, key: CFStringRef, propertyValueTypeRefPtr: *mut c_void, error: *mut CFErrorRef) -> Boolean
+ pub fn CFURLCreateResourcePropertiesForKeysFromBookmarkData(
+ allocator: CFAllocatorRef,
+ resourcePropertiesToReturn: CFArrayRef,
+ bookmark: CFDataRef,
+ ) -> CFDictionaryRef;
+ pub fn CFURLCreateResourcePropertyForKeyFromBookmarkData(
+ allocator: CFAllocatorRef,
+ resourcePropertyKey: CFStringRef,
+ bookmark: CFDataRef,
+ ) -> CFTypeRef;
+ pub fn CFURLSetResourcePropertiesForKeys(
+ url: CFURLRef,
+ keyedPropertyValues: CFDictionaryRef,
+ error: *mut CFErrorRef,
+ ) -> Boolean;
+ pub fn CFURLSetResourcePropertyForKey(
+ url: CFURLRef,
+ key: CFStringRef,
+ value: CFTypeRef,
+ error: *mut CFErrorRef,
+ ) -> Boolean;
+ pub fn CFURLSetTemporaryResourcePropertyForKey(
+ url: CFURLRef,
+ key: CFStringRef,
+ propertyValue: CFTypeRef,
+ );
/* Working with Bookmark Data */
- pub fn CFURLCreateBookmarkData(allocator: CFAllocatorRef, url: CFURLRef, options: CFURLBookmarkCreationOptions, resourcePropertiesToInclude: CFArrayRef, relativeToURL: CFURLRef, error: *mut CFErrorRef) -> CFDataRef;
- pub fn CFURLCreateBookmarkDataFromAliasRecord(allocator: CFAllocatorRef, aliasRecordDataRef: CFDataRef) -> CFDataRef;
- pub fn CFURLCreateBookmarkDataFromFile(allocator: CFAllocatorRef, fileURL: CFURLRef, errorRef: *mut CFErrorRef) -> CFDataRef;
- pub fn CFURLWriteBookmarkDataToFile(bookmarkRef: CFDataRef, fileURL: CFURLRef, options: CFURLBookmarkFileCreationOptions, errorRef: *mut CFErrorRef) -> Boolean;
+ pub fn CFURLCreateBookmarkData(
+ allocator: CFAllocatorRef,
+ url: CFURLRef,
+ options: CFURLBookmarkCreationOptions,
+ resourcePropertiesToInclude: CFArrayRef,
+ relativeToURL: CFURLRef,
+ error: *mut CFErrorRef,
+ ) -> CFDataRef;
+
+ #[cfg(target_os = "macos")]
+ pub fn CFURLCreateBookmarkDataFromAliasRecord(
+ allocator: CFAllocatorRef,
+ aliasRecordDataRef: CFDataRef,
+ ) -> CFDataRef; // deprecated
+
+ pub fn CFURLCreateBookmarkDataFromFile(
+ allocator: CFAllocatorRef,
+ fileURL: CFURLRef,
+ errorRef: *mut CFErrorRef,
+ ) -> CFDataRef;
+ pub fn CFURLWriteBookmarkDataToFile(
+ bookmarkRef: CFDataRef,
+ fileURL: CFURLRef,
+ options: CFURLBookmarkFileCreationOptions,
+ errorRef: *mut CFErrorRef,
+ ) -> Boolean;
pub fn CFURLStartAccessingSecurityScopedResource(url: CFURLRef) -> Boolean;
pub fn CFURLStopAccessingSecurityScopedResource(url: CFURLRef);
}
#[test]
-#[cfg(feature="mac_os_10_8_features")]
+#[cfg(feature = "mac_os_10_8_features")]
fn can_see_excluded_from_backup_key() {
let _ = unsafe { kCFURLIsExcludedFromBackupKey };
}
diff --git a/third_party/rust/core-foundation-sys/src/url_enumerator.rs b/third_party/rust/core-foundation-sys/src/url_enumerator.rs
new file mode 100644
index 0000000000..71b74beb5b
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/url_enumerator.rs
@@ -0,0 +1,62 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::array::CFArrayRef;
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeID};
+use crate::error::CFErrorRef;
+use crate::url::CFURLRef;
+
+#[repr(C)]
+pub struct __CFURLEnumerator(c_void);
+
+pub type CFURLEnumeratorRef = *mut __CFURLEnumerator;
+
+pub type CFURLEnumeratorOptions = CFOptionFlags;
+pub const kCFURLEnumeratorDefaultBehavior: CFURLEnumeratorOptions = 0;
+pub const kCFURLEnumeratorDescendRecursively: CFURLEnumeratorOptions = 1 << 0;
+pub const kCFURLEnumeratorSkipInvisibles: CFURLEnumeratorOptions = 1 << 1;
+pub const kCFURLEnumeratorGenerateFileReferenceURLs: CFURLEnumeratorOptions = 1 << 2;
+pub const kCFURLEnumeratorSkipPackageContents: CFURLEnumeratorOptions = 1 << 3;
+pub const kCFURLEnumeratorIncludeDirectoriesPreOrder: CFURLEnumeratorOptions = 1 << 4;
+pub const kCFURLEnumeratorIncludeDirectoriesPostOrder: CFURLEnumeratorOptions = 1 << 5;
+//pub const kCFURLEnumeratorGenerateRelativePathURLs = 1UL << 6; // macos(10.15)+
+
+pub type CFURLEnumeratorResult = CFIndex;
+pub const kCFURLEnumeratorSuccess: CFURLEnumeratorOptions = 1;
+pub const kCFURLEnumeratorEnd: CFURLEnumeratorOptions = 2;
+pub const kCFURLEnumeratorError: CFURLEnumeratorOptions = 3;
+pub const kCFURLEnumeratorDirectoryPostOrderSuccess: CFURLEnumeratorOptions = 4;
+
+extern "C" {
+ /*
+ * CFURLEnumerator.h
+ */
+ pub fn CFURLEnumeratorGetTypeID() -> CFTypeID;
+ pub fn CFURLEnumeratorCreateForDirectoryURL(
+ alloc: CFAllocatorRef,
+ directoryURL: CFURLRef,
+ option: CFURLEnumeratorOptions,
+ propertyKeys: CFArrayRef,
+ ) -> CFURLEnumeratorRef;
+ pub fn CFURLEnumeratorCreateForMountedVolumes(
+ alloc: CFAllocatorRef,
+ option: CFURLEnumeratorOptions,
+ propertyKeys: CFArrayRef,
+ ) -> CFURLEnumeratorRef;
+ pub fn CFURLEnumeratorGetNextURL(
+ enumerator: CFURLEnumeratorRef,
+ url: *mut CFURLRef,
+ error: *mut CFErrorRef,
+ ) -> CFURLEnumeratorResult;
+ pub fn CFURLEnumeratorSkipDescendents(enumerator: CFURLEnumeratorRef);
+ pub fn CFURLEnumeratorGetDescendentLevel(enumerator: CFURLEnumeratorRef) -> CFIndex;
+ pub fn CFURLEnumeratorGetSourceDidChange(enumerator: CFURLEnumeratorRef) -> Boolean; // deprecated since macos 10.7
+}
diff --git a/third_party/rust/core-foundation-sys/src/user_notification.rs b/third_party/rust/core-foundation-sys/src/user_notification.rs
new file mode 100644
index 0000000000..6432718261
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/user_notification.rs
@@ -0,0 +1,138 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeID, SInt32};
+use crate::date::CFTimeInterval;
+use crate::dictionary::CFDictionaryRef;
+use crate::runloop::CFRunLoopSourceRef;
+use crate::string::CFStringRef;
+use crate::url::CFURLRef;
+
+#[repr(C)]
+pub struct __CFUserNotification(c_void);
+
+pub type CFUserNotificationCallBack =
+ extern "C" fn(userNotification: CFUserNotificationRef, responseFlags: CFOptionFlags);
+pub type CFUserNotificationRef = *mut __CFUserNotification;
+
+/* Alert Levels */
+pub const kCFUserNotificationStopAlertLevel: CFOptionFlags = 0;
+pub const kCFUserNotificationNoteAlertLevel: CFOptionFlags = 1;
+pub const kCFUserNotificationCautionAlertLevel: CFOptionFlags = 2;
+pub const kCFUserNotificationPlainAlertLevel: CFOptionFlags = 3;
+
+/* Response Codes */
+pub const kCFUserNotificationDefaultResponse: CFOptionFlags = 0;
+pub const kCFUserNotificationAlternateResponse: CFOptionFlags = 1;
+pub const kCFUserNotificationOtherResponse: CFOptionFlags = 2;
+pub const kCFUserNotificationCancelResponse: CFOptionFlags = 3;
+
+/* Button Flags */
+pub const kCFUserNotificationNoDefaultButtonFlag: CFOptionFlags = 1usize << 5;
+pub const kCFUserNotificationUseRadioButtonsFlag: CFOptionFlags = 1usize << 6;
+
+#[inline(always)]
+pub fn CFUserNotificationCheckBoxChecked(i: CFIndex) -> CFOptionFlags {
+ (1u32 << (8 + i)) as CFOptionFlags
+}
+
+#[inline(always)]
+pub fn CFUserNotificationSecureTextField(i: CFIndex) -> CFOptionFlags {
+ (1u32 << (16 + i)) as CFOptionFlags
+}
+
+#[inline(always)]
+pub fn CFUserNotificationPopUpSelection(n: CFIndex) -> CFOptionFlags {
+ (n << 24) as CFOptionFlags
+}
+
+extern "C" {
+ /*
+ * CFUserNotification.h
+ */
+
+ /* Dialog Description Keys */
+ pub static kCFUserNotificationIconURLKey: CFStringRef;
+ pub static kCFUserNotificationSoundURLKey: CFStringRef;
+ pub static kCFUserNotificationLocalizationURLKey: CFStringRef;
+ pub static kCFUserNotificationAlertHeaderKey: CFStringRef;
+ pub static kCFUserNotificationAlertMessageKey: CFStringRef;
+ pub static kCFUserNotificationDefaultButtonTitleKey: CFStringRef;
+ pub static kCFUserNotificationAlternateButtonTitleKey: CFStringRef;
+ pub static kCFUserNotificationOtherButtonTitleKey: CFStringRef;
+ pub static kCFUserNotificationProgressIndicatorValueKey: CFStringRef;
+ pub static kCFUserNotificationPopUpTitlesKey: CFStringRef;
+ pub static kCFUserNotificationTextFieldTitlesKey: CFStringRef;
+ pub static kCFUserNotificationCheckBoxTitlesKey: CFStringRef;
+ pub static kCFUserNotificationTextFieldValuesKey: CFStringRef;
+ pub static kCFUserNotificationPopUpSelectionKey: CFStringRef;
+ pub static kCFUserNotificationAlertTopMostKey: CFStringRef;
+ pub static kCFUserNotificationKeyboardTypesKey: CFStringRef;
+
+ /* CFUserNotification Miscellaneous Functions */
+ pub fn CFUserNotificationCancel(userNotification: CFUserNotificationRef) -> SInt32;
+ pub fn CFUserNotificationCreate(
+ allocator: CFAllocatorRef,
+ timeout: CFTimeInterval,
+ flags: CFOptionFlags,
+ error: *mut SInt32,
+ dictionary: CFDictionaryRef,
+ ) -> CFUserNotificationRef;
+ pub fn CFUserNotificationCreateRunLoopSource(
+ allocator: CFAllocatorRef,
+ userNotification: CFUserNotificationRef,
+ callout: CFUserNotificationCallBack,
+ order: CFIndex,
+ ) -> CFRunLoopSourceRef;
+ pub fn CFUserNotificationDisplayAlert(
+ timeout: CFTimeInterval,
+ flags: CFOptionFlags,
+ iconURL: CFURLRef,
+ soundURL: CFURLRef,
+ localizationURL: CFURLRef,
+ alertHeader: CFStringRef,
+ alertMessage: CFStringRef,
+ defaultButtonTitle: CFStringRef,
+ alternateButtonTitle: CFStringRef,
+ otherButtonTitle: CFStringRef,
+ responseFlags: *mut CFOptionFlags,
+ ) -> SInt32;
+ pub fn CFUserNotificationDisplayNotice(
+ timeout: CFTimeInterval,
+ flags: CFOptionFlags,
+ iconURL: CFURLRef,
+ soundURL: CFURLRef,
+ localizationURL: CFURLRef,
+ alertHeader: CFStringRef,
+ alertMessage: CFStringRef,
+ defaultButtonTitle: CFStringRef,
+ ) -> SInt32;
+ pub fn CFUserNotificationGetTypeID() -> CFTypeID;
+ pub fn CFUserNotificationGetResponseDictionary(
+ userNotification: CFUserNotificationRef,
+ ) -> CFDictionaryRef;
+ pub fn CFUserNotificationGetResponseValue(
+ userNotification: CFUserNotificationRef,
+ key: CFStringRef,
+ idx: CFIndex,
+ ) -> CFStringRef;
+ pub fn CFUserNotificationReceiveResponse(
+ userNotification: CFUserNotificationRef,
+ timeout: CFTimeInterval,
+ responseFlags: *mut CFOptionFlags,
+ ) -> SInt32;
+ pub fn CFUserNotificationUpdate(
+ userNotification: CFUserNotificationRef,
+ timeout: CFTimeInterval,
+ flags: CFOptionFlags,
+ dictionary: CFDictionaryRef,
+ ) -> SInt32;
+}
diff --git a/third_party/rust/core-foundation-sys/src/uuid.rs b/third_party/rust/core-foundation-sys/src/uuid.rs
index 4253952938..a1714a8a8c 100644
--- a/third_party/rust/core-foundation-sys/src/uuid.rs
+++ b/third_party/rust/core-foundation-sys/src/uuid.rs
@@ -9,7 +9,8 @@
use std::os::raw::c_void;
-use base::{CFAllocatorRef, CFTypeID};
+use crate::base::{CFAllocatorRef, CFTypeID};
+use crate::string::CFStringRef;
#[repr(C)]
pub struct __CFUUID(c_void);
@@ -17,33 +18,78 @@ pub struct __CFUUID(c_void);
pub type CFUUIDRef = *const __CFUUID;
#[repr(C)]
-#[derive(Clone, Copy, Default)]
+#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct CFUUIDBytes {
- pub byte0: u8,
- pub byte1: u8,
- pub byte2: u8,
- pub byte3: u8,
- pub byte4: u8,
- pub byte5: u8,
- pub byte6: u8,
- pub byte7: u8,
- pub byte8: u8,
- pub byte9: u8,
+ pub byte0: u8,
+ pub byte1: u8,
+ pub byte2: u8,
+ pub byte3: u8,
+ pub byte4: u8,
+ pub byte5: u8,
+ pub byte6: u8,
+ pub byte7: u8,
+ pub byte8: u8,
+ pub byte9: u8,
pub byte10: u8,
pub byte11: u8,
pub byte12: u8,
pub byte13: u8,
pub byte14: u8,
- pub byte15: u8
+ pub byte15: u8,
}
-extern {
+extern "C" {
/*
* CFUUID.h
*/
+
+ /* Creating CFUUID Objects */
pub fn CFUUIDCreate(allocator: CFAllocatorRef) -> CFUUIDRef;
+ pub fn CFUUIDCreateFromString(alloc: CFAllocatorRef, uuidStr: CFStringRef) -> CFUUIDRef;
pub fn CFUUIDCreateFromUUIDBytes(allocator: CFAllocatorRef, bytes: CFUUIDBytes) -> CFUUIDRef;
+ pub fn CFUUIDCreateWithBytes(
+ alloc: CFAllocatorRef,
+ byte0: u8,
+ byte1: u8,
+ byte2: u8,
+ byte3: u8,
+ byte4: u8,
+ byte5: u8,
+ byte6: u8,
+ byte7: u8,
+ byte8: u8,
+ byte9: u8,
+ byte10: u8,
+ byte11: u8,
+ byte12: u8,
+ byte13: u8,
+ byte14: u8,
+ byte15: u8,
+ ) -> CFUUIDRef;
+
+ /* Getting Information About CFUUID Objects */
+ pub fn CFUUIDCreateString(allocator: CFAllocatorRef, uid: CFUUIDRef) -> CFStringRef;
+ pub fn CFUUIDGetConstantUUIDWithBytes(
+ alloc: CFAllocatorRef,
+ byte0: u8,
+ byte1: u8,
+ byte2: u8,
+ byte3: u8,
+ byte4: u8,
+ byte5: u8,
+ byte6: u8,
+ byte7: u8,
+ byte8: u8,
+ byte9: u8,
+ byte10: u8,
+ byte11: u8,
+ byte12: u8,
+ byte13: u8,
+ byte14: u8,
+ byte15: u8,
+ ) -> CFUUIDRef;
pub fn CFUUIDGetUUIDBytes(uuid: CFUUIDRef) -> CFUUIDBytes;
+ /* Getting the CFUUID Type Identifier */
pub fn CFUUIDGetTypeID() -> CFTypeID;
}
diff --git a/third_party/rust/core-foundation-sys/src/xml_node.rs b/third_party/rust/core-foundation-sys/src/xml_node.rs
new file mode 100644
index 0000000000..332beec823
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/xml_node.rs
@@ -0,0 +1,147 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::{c_char, c_void};
+
+use crate::array::CFArrayRef;
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFTypeID};
+use crate::dictionary::CFDictionaryRef;
+use crate::string::{CFStringEncoding, CFStringRef};
+use crate::tree::CFTreeRef;
+use crate::url::CFURLRef;
+
+#[repr(C)]
+pub struct __CFXMLNode(c_void);
+
+pub type CFXMLNodeRef = *mut __CFXMLNode;
+pub type CFXMLTreeRef = CFTreeRef;
+
+pub const kCFXMLNodeCurrentVersion: CFIndex = 1;
+
+pub type CFXMLNodeTypeCode = CFIndex;
+pub const kCFXMLNodeTypeDocument: CFXMLNodeTypeCode = 1;
+pub const kCFXMLNodeTypeElement: CFXMLNodeTypeCode = 2;
+pub const kCFXMLNodeTypeAttribute: CFXMLNodeTypeCode = 3;
+pub const kCFXMLNodeTypeProcessingInstruction: CFXMLNodeTypeCode = 4;
+pub const kCFXMLNodeTypeComment: CFXMLNodeTypeCode = 5;
+pub const kCFXMLNodeTypeText: CFXMLNodeTypeCode = 6;
+pub const kCFXMLNodeTypeCDATASection: CFXMLNodeTypeCode = 7;
+pub const kCFXMLNodeTypeDocumentFragment: CFXMLNodeTypeCode = 8;
+pub const kCFXMLNodeTypeEntity: CFXMLNodeTypeCode = 9;
+pub const kCFXMLNodeTypeEntityReference: CFXMLNodeTypeCode = 10;
+pub const kCFXMLNodeTypeDocumentType: CFXMLNodeTypeCode = 11;
+pub const kCFXMLNodeTypeWhitespace: CFXMLNodeTypeCode = 12;
+pub const kCFXMLNodeTypeNotation: CFXMLNodeTypeCode = 13;
+pub const kCFXMLNodeTypeElementTypeDeclaration: CFXMLNodeTypeCode = 14;
+pub const kCFXMLNodeTypeAttributeListDeclaration: CFXMLNodeTypeCode = 15;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLElementInfo {
+ pub attributes: CFDictionaryRef,
+ pub attributeOrder: CFArrayRef,
+ pub isEmpty: Boolean,
+ pub _reserved: [c_char; 3],
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLProcessingInstructionInfo {
+ pub dataString: CFStringRef,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLDocumentInfo {
+ pub sourceURL: CFURLRef,
+ pub encoding: CFStringEncoding,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLExternalID {
+ pub systemID: CFURLRef,
+ pub publicID: CFStringRef,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLDocumentTypeInfo {
+ pub externalID: CFXMLExternalID,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLNotationInfo {
+ pub externalID: CFXMLExternalID,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLElementTypeDeclarationInfo {
+ pub contentDescription: CFStringRef,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLAttributeDeclarationInfo {
+ pub attributeName: CFStringRef,
+ pub typeString: CFStringRef,
+ pub defaultString: CFStringRef,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLAttributeListDeclarationInfo {
+ pub numberOfAttributes: CFIndex,
+ pub attributes: *mut CFXMLAttributeDeclarationInfo,
+}
+
+pub type CFXMLEntityTypeCode = CFIndex;
+pub const kCFXMLEntityTypeParameter: CFXMLEntityTypeCode = 0;
+pub const kCFXMLEntityTypeParsedInternal: CFXMLEntityTypeCode = 1;
+pub const kCFXMLEntityTypeParsedExternal: CFXMLEntityTypeCode = 2;
+pub const kCFXMLEntityTypeUnparsed: CFXMLEntityTypeCode = 3;
+pub const kCFXMLEntityTypeCharacter: CFXMLEntityTypeCode = 4;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLEntityInfo {
+ pub entityType: CFXMLEntityTypeCode,
+ pub replacementText: CFStringRef,
+ pub entityID: CFXMLExternalID,
+ pub notationName: CFStringRef,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLEntityReferenceInfo {
+ pub entityType: CFXMLEntityTypeCode,
+}
+
+extern "C" {
+ /*
+ * CFXMLNode.h
+ */
+ pub fn CFXMLNodeGetTypeID() -> CFTypeID;
+ pub fn CFXMLNodeCreate(
+ alloc: CFAllocatorRef,
+ xmlType: CFXMLNodeTypeCode,
+ dataString: CFStringRef,
+ additionalInfoPtr: *const c_void,
+ version: CFIndex,
+ ) -> CFXMLNodeRef;
+ pub fn CFXMLNodeCreateCopy(alloc: CFAllocatorRef, origNode: CFXMLNodeRef) -> CFXMLNodeRef;
+ pub fn CFXMLNodeGetTypeCode(node: CFXMLNodeRef) -> CFXMLNodeTypeCode;
+ pub fn CFXMLNodeGetString(node: CFXMLNodeRef) -> CFStringRef;
+ pub fn CFXMLNodeGetInfoPtr(node: CFXMLNodeRef) -> *const c_void;
+ pub fn CFXMLNodeGetVersion(node: CFXMLNodeRef) -> CFIndex;
+ pub fn CFXMLTreeCreateWithNode(alloc: CFAllocatorRef, node: CFXMLNodeRef) -> CFXMLTreeRef;
+ pub fn CFXMLTreeGetNode(xmlTree: CFXMLTreeRef) -> CFXMLNodeRef;
+}
diff --git a/third_party/rust/core-foundation-sys/src/xml_parser.rs b/third_party/rust/core-foundation-sys/src/xml_parser.rs
new file mode 100644
index 0000000000..32dc709a60
--- /dev/null
+++ b/third_party/rust/core-foundation-sys/src/xml_parser.rs
@@ -0,0 +1,174 @@
+// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::raw::c_void;
+
+use crate::base::{Boolean, CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeID};
+use crate::data::CFDataRef;
+use crate::dictionary::CFDictionaryRef;
+use crate::string::CFStringRef;
+use crate::url::CFURLRef;
+use crate::xml_node::{CFXMLExternalID, CFXMLNodeRef, CFXMLTreeRef};
+
+#[repr(C)]
+pub struct __CFXMLParser(c_void);
+
+pub type CFXMLParserRef = *mut __CFXMLParser;
+
+pub type CFXMLParserOptions = CFOptionFlags;
+pub const kCFXMLParserValidateDocument: CFXMLParserOptions = 1 << 0;
+pub const kCFXMLParserSkipMetaData: CFXMLParserOptions = 1 << 1;
+pub const kCFXMLParserReplacePhysicalEntities: CFXMLParserOptions = 1 << 2;
+pub const kCFXMLParserSkipWhitespace: CFXMLParserOptions = 1 << 3;
+pub const kCFXMLParserResolveExternalEntities: CFXMLParserOptions = 1 << 4;
+pub const kCFXMLParserAddImpliedAttributes: CFXMLParserOptions = 1 << 5;
+pub const kCFXMLParserAllOptions: CFXMLParserOptions = 0x00FFFFFF;
+pub const kCFXMLParserNoOptions: CFXMLParserOptions = 0;
+
+pub type CFXMLParserStatusCode = CFIndex;
+pub const kCFXMLStatusParseNotBegun: CFIndex = -2;
+pub const kCFXMLStatusParseInProgress: CFIndex = -1;
+pub const kCFXMLStatusParseSuccessful: CFIndex = 0;
+pub const kCFXMLErrorUnexpectedEOF: CFIndex = 1;
+pub const kCFXMLErrorUnknownEncoding: CFIndex = 2;
+pub const kCFXMLErrorEncodingConversionFailure: CFIndex = 3;
+pub const kCFXMLErrorMalformedProcessingInstruction: CFIndex = 4;
+pub const kCFXMLErrorMalformedDTD: CFIndex = 5;
+pub const kCFXMLErrorMalformedName: CFIndex = 6;
+pub const kCFXMLErrorMalformedCDSect: CFIndex = 7;
+pub const kCFXMLErrorMalformedCloseTag: CFIndex = 8;
+pub const kCFXMLErrorMalformedStartTag: CFIndex = 9;
+pub const kCFXMLErrorMalformedDocument: CFIndex = 10;
+pub const kCFXMLErrorElementlessDocument: CFIndex = 11;
+pub const kCFXMLErrorMalformedComment: CFIndex = 12;
+pub const kCFXMLErrorMalformedCharacterReference: CFIndex = 13;
+pub const kCFXMLErrorMalformedParsedCharacterData: CFIndex = 14;
+pub const kCFXMLErrorNoData: CFIndex = 15;
+
+pub type CFXMLParserCreateXMLStructureCallBack =
+ extern "C" fn(parser: CFXMLParserRef, nodeDesc: CFXMLNodeRef, info: *mut c_void) -> *mut c_void;
+pub type CFXMLParserAddChildCallBack = extern "C" fn(
+ parser: CFXMLParserRef,
+ parent: *mut c_void,
+ child: *mut c_void,
+ info: *mut c_void,
+);
+pub type CFXMLParserEndXMLStructureCallBack =
+ extern "C" fn(parser: CFXMLParserRef, xmlType: *mut c_void, info: *mut c_void);
+pub type CFXMLParserResolveExternalEntityCallBack = extern "C" fn(
+ parser: CFXMLParserRef,
+ extID: *mut CFXMLExternalID,
+ info: *mut c_void,
+) -> CFDataRef;
+pub type CFXMLParserHandleErrorCallBack = extern "C" fn(
+ parser: CFXMLParserRef,
+ error: CFXMLParserStatusCode,
+ info: *mut c_void,
+) -> Boolean;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLParserCallBacks {
+ pub version: CFIndex,
+ pub createXMLStructure: CFXMLParserCreateXMLStructureCallBack,
+ pub addChild: CFXMLParserAddChildCallBack,
+ pub endXMLStructure: CFXMLParserEndXMLStructureCallBack,
+ pub resolveExternalEntity: CFXMLParserResolveExternalEntityCallBack,
+ pub handleError: CFXMLParserHandleErrorCallBack,
+}
+
+pub type CFXMLParserRetainCallBack = extern "C" fn(info: *const c_void) -> *const c_void;
+pub type CFXMLParserReleaseCallBack = extern "C" fn(info: *const c_void);
+pub type CFXMLParserCopyDescriptionCallBack = extern "C" fn(info: *const c_void) -> CFStringRef;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct CFXMLParserContext {
+ pub version: CFIndex,
+ pub info: *mut c_void,
+ pub retain: CFXMLParserRetainCallBack,
+ pub release: CFXMLParserReleaseCallBack,
+ pub copyDescription: CFXMLParserCopyDescriptionCallBack,
+}
+
+extern "C" {
+ /*
+ * CFXMLParser.h
+ */
+
+ pub static kCFXMLTreeErrorDescription: CFStringRef;
+ pub static kCFXMLTreeErrorLineNumber: CFStringRef;
+ pub static kCFXMLTreeErrorLocation: CFStringRef;
+ pub static kCFXMLTreeErrorStatusCode: CFStringRef;
+
+ pub fn CFXMLParserGetTypeID() -> CFTypeID;
+ pub fn CFXMLParserCreate(
+ allocator: CFAllocatorRef,
+ xmlData: CFDataRef,
+ dataSource: CFURLRef,
+ parseOptions: CFOptionFlags,
+ versionOfNodes: CFIndex,
+ callBacks: *mut CFXMLParserCallBacks,
+ context: *mut CFXMLParserContext,
+ ) -> CFXMLParserRef;
+ pub fn CFXMLParserCreateWithDataFromURL(
+ allocator: CFAllocatorRef,
+ dataSource: CFURLRef,
+ parseOptions: CFOptionFlags,
+ versionOfNodes: CFIndex,
+ callBacks: *mut CFXMLParserCallBacks,
+ context: *mut CFXMLParserContext,
+ ) -> CFXMLParserRef;
+ pub fn CFXMLParserGetContext(parser: CFXMLParserRef, context: *mut CFXMLParserContext);
+ pub fn CFXMLParserGetCallBacks(parser: CFXMLParserRef, callBacks: *mut CFXMLParserCallBacks);
+ pub fn CFXMLParserGetSourceURL(parser: CFXMLParserRef) -> CFURLRef;
+ pub fn CFXMLParserGetLocation(parser: CFXMLParserRef) -> CFIndex;
+ pub fn CFXMLParserGetLineNumber(parser: CFXMLParserRef) -> CFIndex;
+ pub fn CFXMLParserGetDocument(parser: CFXMLParserRef) -> *mut c_void;
+ pub fn CFXMLParserGetStatusCode(parser: CFXMLParserRef) -> CFXMLParserStatusCode;
+ pub fn CFXMLParserCopyErrorDescription(parser: CFXMLParserRef) -> CFStringRef;
+ pub fn CFXMLParserAbort(
+ parser: CFXMLParserRef,
+ errorCode: CFXMLParserStatusCode,
+ errorDescription: CFStringRef,
+ );
+ pub fn CFXMLParserParse(parser: CFXMLParserRef) -> Boolean;
+ pub fn CFXMLTreeCreateFromData(
+ allocator: CFAllocatorRef,
+ xmlData: CFDataRef,
+ dataSource: CFURLRef,
+ parseOptions: CFOptionFlags,
+ versionOfNodes: CFIndex,
+ ) -> CFXMLTreeRef;
+ pub fn CFXMLTreeCreateFromDataWithError(
+ allocator: CFAllocatorRef,
+ xmlData: CFDataRef,
+ dataSource: CFURLRef,
+ parseOptions: CFOptionFlags,
+ versionOfNodes: CFIndex,
+ errorDict: *mut CFDictionaryRef,
+ ) -> CFXMLTreeRef;
+ pub fn CFXMLTreeCreateWithDataFromURL(
+ allocator: CFAllocatorRef,
+ dataSource: CFURLRef,
+ parseOptions: CFOptionFlags,
+ versionOfNodes: CFIndex,
+ ) -> CFXMLTreeRef;
+ pub fn CFXMLTreeCreateXMLData(allocator: CFAllocatorRef, xmlTree: CFXMLTreeRef) -> CFDataRef;
+ pub fn CFXMLCreateStringByEscapingEntities(
+ allocator: CFAllocatorRef,
+ string: CFStringRef,
+ entitiesDictionary: CFDictionaryRef,
+ ) -> CFStringRef;
+ pub fn CFXMLCreateStringByUnescapingEntities(
+ allocator: CFAllocatorRef,
+ string: CFStringRef,
+ entitiesDictionary: CFDictionaryRef,
+ ) -> CFStringRef;
+}
diff --git a/third_party/rust/core-foundation/.cargo-checksum.json b/third_party/rust/core-foundation/.cargo-checksum.json
index 93d6c58e7c..05422dac50 100644
--- a/third_party/rust/core-foundation/.cargo-checksum.json
+++ b/third_party/rust/core-foundation/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"5909548b679fccc46cd25a91f3784139e4e53bbed284e3b7cc72c599e599e138","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"e5e6ea11e660e5e6676568c9b5b4595633c16fad770755b13bb4fde6c7436a4e","src/attributed_string.rs":"c04c5a3c912b6ab58d3081fa5dfa8fda07957b26396ebc907bba5ad07dc1087d","src/base.rs":"9ed46d59afdb22ecc65504ccd77f1c98108ea0ff96fad568dadb7ed49fde588c","src/boolean.rs":"f5b4d295aaf6cc3681212afebeae2974c5d551125badcc066e6089ac0d2a0873","src/bundle.rs":"c290a87d8bc43d8c9e1935c18e6d7127f46fd211cc2b041ed9e7b618b9df270c","src/characterset.rs":"a3ffb46c5463c99813eebfc177a65794f44a1b9343534e28bbccd262034714c2","src/data.rs":"c8d2ec30d8ac6249ef84afa0f7638d950b5c70d687aeb4ba9e3e46806aa872aa","src/date.rs":"a02f6cca7b6e8fbabc7713177429012658dba5146556e14a08e7baaf81958d83","src/dictionary.rs":"780599de45d64e8f4bca18ad50fc4a909f6e9aab1c3f2cea451f469d766f6782","src/error.rs":"22c21087d9c2c103d1bcb2c4af33b684317bbda5d4747902e510d410f8c1a14b","src/filedescriptor.rs":"022463c6dce8823231dc88064e5d9cffb494b410391388fe1feb50d3419d98b7","src/lib.rs":"2d0b007b264642cbad31e8c901f5f2235ed55515ef73e573a8d86306a7cd4f06","src/mach_port.rs":"87aa8dd28060bbb976197e7cc981eb733762b9bcc29eddd742f44aa8141e71b1","src/number.rs":"5a6cc9036c156e7e9d787864dd671087677abf4175cd840cbf123ccd89abcafe","src/propertylist.rs":"3c964d976709562b96f391265130c0f8fced307267a2b6385bab469048518b55","src/runloop.rs":"514a8ea7b185812fbb6d4835b0f7d26208f3121dadf1553a3a39c5013f2820af","src/set.rs":"da75b31f894bd04c0518211e113ca21a2781cd6ac71018104eeb354dd2f1a19e","src/string.rs":"bea7f3fd2528377442d1bebfeacf7e905d879320ae662fe6a8ef917b6a8e9c36","src/timezone.rs":"6dcf188db76303292b519d6283b71b71c7b3d6ed1afddc28de16d727075f5ef1","src/url.rs":"c544725399d3fbc4de54fd9d1c987e02f81760effd08c5c64c8deacd11478950","src/uuid.rs":"c3457e43fc22ba0f3fcab3ee8108500585ba005dbcbfa7edad0d389701ddf379","tests/use_macro_outside_crate.rs":"ed5e74ac9e988f2609c0b785189f1e6368d693f6401603ad065521f3ab51df94"},"package":"194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"} \ No newline at end of file
+{"files":{"Cargo.toml":"2e85272c5cffb75aadcbb83d8ca1a619af3ccb9d810c1e07349f3b618fa05b7e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"1ec64187ec7c3ff0a9cf9739fb83d1f0b6141d827e4f21a14203b7058ca12056","src/attributed_string.rs":"7c129d266872bf9e0f8cbd9477d8cc27405b806395e59e1647bedf9af06f8949","src/base.rs":"7ec2afcbc200aabaa01687efce2eb27c9effc9eae64d3c579827de731fbd290e","src/boolean.rs":"60aef5be531e867f03524c32a88609100d07d9166184545feab760af9eb3d7ec","src/bundle.rs":"00f7ae30df3cc59079e771da0eda2b1972f52b13cc7bd95ae48b0e9bd1836ff4","src/characterset.rs":"126884d51e75db5be4cb2988f4e97e0e1b592c900e0158082d8c0dda7a453b0f","src/data.rs":"bfaa4427b6bc4c838188506ee154622983bbfcc10641be3f58525b89a854d4cd","src/date.rs":"d1ec3f918cf6c62d0e36d50d495c125d275a9a89442a740eea5d41dcc71a96fa","src/dictionary.rs":"f6d73c08fa9afd30d1df70cceea55dd30c7b81b8a78117d8843f1b3390051dca","src/error.rs":"433982fb7b421f5bf386d7eba22a7ffb8673486bb6455ff3fa30c875b064f718","src/filedescriptor.rs":"d3ece69ff461b215f7ff98dc6139723c4a5a53849a9747cccd24e72c185c4ffd","src/lib.rs":"92502d5f7d0e2ba266ec3531c01dd996e1832f1e6e9e66b10596e6fb870480cb","src/mach_port.rs":"e5400039696a70bdc0e6e14b1a68c493b741136945ce0eb67208cd4d0f895e1b","src/number.rs":"48e2efe219a7eaa4bc7bc3a48fa45f32fbbfd6363620838fef16a98b86e05061","src/propertylist.rs":"23e9a42d506983374d0c3439ab80407bbd472a3487812693a411597ff5eb1bd8","src/runloop.rs":"ff5bbb8a145befa7f244d937161d87f059ea60c9c482ab32e845222ee6fabf34","src/set.rs":"39e41a3d4f9e4dd50864a9c3581508e1b09549dc89d57fa84935964d98469bad","src/string.rs":"3b25b169d0f18dae66e6f123a116a04c79096f9e44e4221d4dbdcea4e152355c","src/timezone.rs":"7b8e46bde9e8aa71a906ab26b8ff7b6251568ebf210bab10d11c6ba0ce64ecd5","src/url.rs":"dc125dd95e9b8386770b89f5437ab904ceff0843e1bf820f548bddfc31e1c40c","src/uuid.rs":"e290c592871b7cea6ec09d2b3e34ec9033968dda725cf49e410535f79d2b41f8","tests/use_macro_outside_crate.rs":"ed5e74ac9e988f2609c0b785189f1e6368d693f6401603ad065521f3ab51df94"},"package":"91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"} \ No newline at end of file
diff --git a/third_party/rust/core-foundation/Cargo.toml b/third_party/rust/core-foundation/Cargo.toml
index 7ea9578156..47cf3f2640 100644
--- a/third_party/rust/core-foundation/Cargo.toml
+++ b/third_party/rust/core-foundation/Cargo.toml
@@ -10,23 +10,32 @@
# See Cargo.toml.orig for the original contents.
[package]
+edition = "2018"
name = "core-foundation"
-version = "0.9.3"
+version = "0.9.4"
authors = ["The Servo Project Developers"]
description = "Bindings to Core Foundation for macOS"
homepage = "https://github.com/servo/core-foundation-rs"
-keywords = ["macos", "framework", "objc"]
+keywords = [
+ "macos",
+ "framework",
+ "objc",
+]
categories = ["os::macos-apis"]
-license = "MIT / Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/core-foundation-rs"
+
[package.metadata.docs.rs]
+all-features = true
default-target = "x86_64-apple-darwin"
+
[dependencies.chrono]
version = "0.4"
optional = true
[dependencies.core-foundation-sys]
-version = "0.8.3"
+version = "0.8.6"
+default-features = false
[dependencies.libc]
version = "0.2"
@@ -36,6 +45,8 @@ version = "0.5"
optional = true
[features]
+default = ["link"]
+link = ["core-foundation-sys/link"]
mac_os_10_7_support = ["core-foundation-sys/mac_os_10_7_support"]
mac_os_10_8_features = ["core-foundation-sys/mac_os_10_8_features"]
with-chrono = ["chrono"]
diff --git a/third_party/rust/core-foundation/src/array.rs b/third_party/rust/core-foundation/src/array.rs
index d66ffc5b82..b6f5d5c740 100644
--- a/third_party/rust/core-foundation/src/array.rs
+++ b/third_party/rust/core-foundation/src/array.rs
@@ -9,17 +9,17 @@
//! Heterogeneous immutable arrays.
+use crate::ConcreteCFType;
pub use core_foundation_sys::array::*;
pub use core_foundation_sys::base::CFIndex;
-use core_foundation_sys::base::{CFTypeRef, CFRelease, kCFAllocatorDefault};
-use std::mem;
+use core_foundation_sys::base::{kCFAllocatorDefault, CFRelease, CFTypeRef};
use std::marker::PhantomData;
+use std::mem;
use std::os::raw::c_void;
use std::ptr;
-use ConcreteCFType;
-use base::{CFIndexConvertible, TCFType, CFRange};
-use base::{FromVoid, ItemRef};
+use crate::base::{CFIndexConvertible, CFRange, TCFType};
+use crate::base::{FromVoid, ItemRef};
/// A heterogeneous immutable array.
pub struct CFArray<T = *const c_void>(CFArrayRef, PhantomData<T>);
@@ -63,24 +63,34 @@ unsafe impl ConcreteCFType for CFArray<*const c_void> {}
impl<T> CFArray<T> {
/// Creates a new `CFArray` with the given elements, which must implement `Copy`.
- pub fn from_copyable(elems: &[T]) -> CFArray<T> where T: Copy {
+ pub fn from_copyable(elems: &[T]) -> CFArray<T>
+ where
+ T: Copy,
+ {
unsafe {
- let array_ref = CFArrayCreate(kCFAllocatorDefault,
- elems.as_ptr() as *const *const c_void,
- elems.len().to_CFIndex(),
- ptr::null());
+ let array_ref = CFArrayCreate(
+ kCFAllocatorDefault,
+ elems.as_ptr() as *const *const c_void,
+ elems.len().to_CFIndex(),
+ ptr::null(),
+ );
TCFType::wrap_under_create_rule(array_ref)
}
}
/// Creates a new `CFArray` with the given elements, which must be `CFType` objects.
- pub fn from_CFTypes(elems: &[T]) -> CFArray<T> where T: TCFType {
+ pub fn from_CFTypes(elems: &[T]) -> CFArray<T>
+ where
+ T: TCFType,
+ {
unsafe {
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
- let array_ref = CFArrayCreate(kCFAllocatorDefault,
- elems.as_ptr(),
- elems.len().to_CFIndex(),
- &kCFTypeArrayCallBacks);
+ let array_ref = CFArrayCreate(
+ kCFAllocatorDefault,
+ elems.as_ptr(),
+ elems.len().to_CFIndex(),
+ &kCFTypeArrayCallBacks,
+ );
TCFType::wrap_under_create_rule(array_ref)
}
}
@@ -105,7 +115,7 @@ impl<T> CFArray<T> {
/// Core Foundation objects (not always true), they need to be wrapped with
/// `TCFType::wrap_under_get_rule()`.
#[inline]
- pub fn iter<'a>(&'a self) -> CFArrayIterator<'a, T> {
+ pub fn iter(&self) -> CFArrayIterator<'_, T> {
CFArrayIterator {
array: self,
index: 0,
@@ -115,20 +125,30 @@ impl<T> CFArray<T> {
#[inline]
pub fn len(&self) -> CFIndex {
- unsafe {
- CFArrayGetCount(self.0)
- }
+ unsafe { CFArrayGetCount(self.0) }
}
+ /// Returns `true` if the array contains no elements.
#[inline]
- pub unsafe fn get_unchecked<'a>(&'a self, index: CFIndex) -> ItemRef<'a, T> where T: FromVoid {
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ #[inline]
+ pub unsafe fn get_unchecked(&self, index: CFIndex) -> ItemRef<'_, T>
+ where
+ T: FromVoid,
+ {
T::from_void(CFArrayGetValueAtIndex(self.0, index))
}
#[inline]
- pub fn get<'a>(&'a self, index: CFIndex) -> Option<ItemRef<'a, T>> where T: FromVoid {
+ pub fn get(&self, index: CFIndex) -> Option<ItemRef<'_, T>>
+ where
+ T: FromVoid,
+ {
if index < self.len() {
- Some(unsafe { T::from_void(CFArrayGetValueAtIndex(self.0, index)) } )
+ Some(unsafe { T::from_void(CFArrayGetValueAtIndex(self.0, index)) })
} else {
None
}
@@ -146,7 +166,7 @@ impl<T> CFArray<T> {
pub fn get_all_values(&self) -> Vec<*const c_void> {
self.get_values(CFRange {
location: 0,
- length: self.len()
+ length: self.len(),
})
}
}
@@ -162,13 +182,15 @@ impl<'a, T: FromVoid> IntoIterator for &'a CFArray<T> {
#[cfg(test)]
mod tests {
+ use crate::number::CFNumber;
+
use super::*;
+ use crate::base::CFType;
use std::mem;
- use base::CFType;
#[test]
fn to_untyped_correct_retain_count() {
- let array = CFArray::<CFType>::from_CFTypes(&[]);
+ let array = CFArray::<CFType>::from_CFTypes(&[CFNumber::from(4).as_CFType()]);
assert_eq!(array.retain_count(), 1);
let untyped_array = array.to_untyped();
@@ -181,7 +203,7 @@ mod tests {
#[test]
fn into_untyped() {
- let array = CFArray::<CFType>::from_CFTypes(&[]);
+ let array = CFArray::<CFType>::from_CFTypes(&[CFNumber::from(4).as_CFType()]);
let array2 = array.to_untyped();
assert_eq!(array.retain_count(), 2);
@@ -194,9 +216,9 @@ mod tests {
#[test]
fn borrow() {
- use string::CFString;
+ use crate::string::CFString;
- let string = CFString::from_static_string("bar");
+ let string = CFString::from_static_string("alongerstring");
assert_eq!(string.retain_count(), 1);
let x;
{
@@ -208,7 +230,7 @@ mod tests {
{
x = arr.get(0).unwrap().clone();
assert_eq!(x.retain_count(), 2);
- assert_eq!(x.to_string(), "bar");
+ assert_eq!(x.to_string(), "alongerstring");
}
}
assert_eq!(x.retain_count(), 1);
@@ -216,23 +238,24 @@ mod tests {
#[test]
fn iter_untyped_array() {
- use string::{CFString, CFStringRef};
- use base::TCFTypeRef;
+ use crate::base::TCFTypeRef;
+ use crate::string::{CFString, CFStringRef};
- let cf_string = CFString::from_static_string("bar");
+ let cf_string = CFString::from_static_string("alongerstring");
let array: CFArray = CFArray::from_CFTypes(&[cf_string.clone()]).into_untyped();
- let cf_strings = array.iter().map(|ptr| {
- unsafe { CFString::wrap_under_get_rule(CFStringRef::from_void_ptr(*ptr)) }
- }).collect::<Vec<_>>();
+ let cf_strings = array
+ .iter()
+ .map(|ptr| unsafe { CFString::wrap_under_get_rule(CFStringRef::from_void_ptr(*ptr)) })
+ .collect::<Vec<_>>();
let strings = cf_strings.iter().map(|s| s.to_string()).collect::<Vec<_>>();
assert_eq!(cf_string.retain_count(), 3);
- assert_eq!(&strings[..], &["bar"]);
+ assert_eq!(&strings[..], &["alongerstring"]);
}
#[test]
fn should_box_and_unbox() {
- use number::CFNumber;
+ use crate::number::CFNumber;
let n0 = CFNumber::from(0);
let n1 = CFNumber::from(1);
diff --git a/third_party/rust/core-foundation/src/attributed_string.rs b/third_party/rust/core-foundation/src/attributed_string.rs
index d4a467946d..6a2b349f1a 100644
--- a/third_party/rust/core-foundation/src/attributed_string.rs
+++ b/third_party/rust/core-foundation/src/attributed_string.rs
@@ -9,22 +9,26 @@
pub use core_foundation_sys::attributed_string::*;
-use base::TCFType;
-use core_foundation_sys::base::{CFIndex, CFRange, kCFAllocatorDefault};
+use crate::base::TCFType;
+use crate::string::{CFString, CFStringRef};
+use core_foundation_sys::base::{kCFAllocatorDefault, CFIndex, CFRange};
use std::ptr::null;
-use string::{CFString, CFStringRef};
-declare_TCFType!{
+declare_TCFType! {
CFAttributedString, CFAttributedStringRef
}
-impl_TCFType!(CFAttributedString, CFAttributedStringRef, CFAttributedStringGetTypeID);
+impl_TCFType!(
+ CFAttributedString,
+ CFAttributedStringRef,
+ CFAttributedStringGetTypeID
+);
impl CFAttributedString {
#[inline]
pub fn new(string: &CFString) -> Self {
unsafe {
- let astr_ref = CFAttributedStringCreate(
- kCFAllocatorDefault, string.as_concrete_TypeRef(), null());
+ let astr_ref =
+ CFAttributedStringCreate(kCFAllocatorDefault, string.as_concrete_TypeRef(), null());
CFAttributedString::wrap_under_create_rule(astr_ref)
}
@@ -32,23 +36,24 @@ impl CFAttributedString {
#[inline]
pub fn char_len(&self) -> CFIndex {
- unsafe {
- CFAttributedStringGetLength(self.0)
- }
+ unsafe { CFAttributedStringGetLength(self.0) }
}
}
-declare_TCFType!{
+declare_TCFType! {
CFMutableAttributedString, CFMutableAttributedStringRef
}
-impl_TCFType!(CFMutableAttributedString, CFMutableAttributedStringRef, CFAttributedStringGetTypeID);
+impl_TCFType!(
+ CFMutableAttributedString,
+ CFMutableAttributedStringRef,
+ CFAttributedStringGetTypeID
+);
impl CFMutableAttributedString {
#[inline]
pub fn new() -> Self {
unsafe {
- let astr_ref = CFAttributedStringCreateMutable(
- kCFAllocatorDefault, 0);
+ let astr_ref = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFMutableAttributedString::wrap_under_create_rule(astr_ref)
}
@@ -56,24 +61,20 @@ impl CFMutableAttributedString {
#[inline]
pub fn char_len(&self) -> CFIndex {
- unsafe {
- CFAttributedStringGetLength(self.0)
- }
+ unsafe { CFAttributedStringGetLength(self.0) }
}
#[inline]
pub fn replace_str(&mut self, string: &CFString, range: CFRange) {
unsafe {
- CFAttributedStringReplaceString(
- self.0, range, string.as_concrete_TypeRef());
+ CFAttributedStringReplaceString(self.0, range, string.as_concrete_TypeRef());
}
}
#[inline]
pub fn set_attribute<T: TCFType>(&mut self, range: CFRange, name: CFStringRef, value: &T) {
unsafe {
- CFAttributedStringSetAttribute(
- self.0, range, name, value.as_CFTypeRef());
+ CFAttributedStringSetAttribute(self.0, range, name, value.as_CFTypeRef());
}
}
}
@@ -84,7 +85,6 @@ impl Default for CFMutableAttributedString {
}
}
-
#[cfg(test)]
mod tests {
use super::*;
@@ -93,6 +93,9 @@ mod tests {
fn attributed_string_type_id_comparison() {
// CFMutableAttributedString TypeID must be equal to CFAttributedString TypeID.
// Compilation must not fail.
- assert_eq!(<CFAttributedString as TCFType>::type_id(), <CFMutableAttributedString as TCFType>::type_id());
+ assert_eq!(
+ <CFAttributedString as TCFType>::type_id(),
+ <CFMutableAttributedString as TCFType>::type_id()
+ );
}
-} \ No newline at end of file
+}
diff --git a/third_party/rust/core-foundation/src/base.rs b/third_party/rust/core-foundation/src/base.rs
index f08f2b2e85..b44c1262ab 100644
--- a/third_party/rust/core-foundation/src/base.rs
+++ b/third_party/rust/core-foundation/src/base.rs
@@ -17,8 +17,8 @@ use std::os::raw::c_void;
pub use core_foundation_sys::base::*;
-use string::CFString;
-use ConcreteCFType;
+use crate::string::CFString;
+use crate::ConcreteCFType;
pub trait CFIndexConvertible {
/// Always use this method to construct a `CFIndex` value. It performs bounds checking to
@@ -37,7 +37,7 @@ impl CFIndexConvertible for usize {
}
}
-declare_TCFType!{
+declare_TCFType! {
/// Superclass of all Core Foundation objects.
CFType, CFTypeRef
}
@@ -111,13 +111,11 @@ impl CFType {
}
impl fmt::Debug for CFType {
- /// Formats the value using [`CFCopyDescription`].
- ///
- /// [`CFCopyDescription`]: https://developer.apple.com/documentation/corefoundation/1521252-cfcopydescription?language=objc
+ /// Formats the value using [`CFCopyDescription`].
+ ///
+ /// [`CFCopyDescription`]: https://developer.apple.com/documentation/corefoundation/1521252-cfcopydescription?language=objc
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let desc = unsafe {
- CFString::wrap_under_create_rule(CFCopyDescription(self.0))
- };
+ let desc = unsafe { CFString::wrap_under_create_rule(CFCopyDescription(self.0)) };
desc.fmt(f)
}
}
@@ -125,18 +123,14 @@ impl fmt::Debug for CFType {
impl Clone for CFType {
#[inline]
fn clone(&self) -> CFType {
- unsafe {
- TCFType::wrap_under_get_rule(self.0)
- }
+ unsafe { TCFType::wrap_under_get_rule(self.0) }
}
}
impl PartialEq for CFType {
#[inline]
fn eq(&self, other: &CFType) -> bool {
- unsafe {
- CFEqual(self.as_CFTypeRef(), other.as_CFTypeRef()) != 0
- }
+ unsafe { CFEqual(self.as_CFTypeRef(), other.as_CFTypeRef()) != 0 }
}
}
@@ -153,7 +147,6 @@ impl CFAllocator {
}
}
-
/// All Core Foundation types implement this trait. The associated type `Ref` specifies the
/// associated Core Foundation type: e.g. for `CFType` this is `CFTypeRef`; for `CFArray` this is
/// `CFArrayRef`.
@@ -165,7 +158,7 @@ pub trait TCFType {
/// The reference type wrapped inside this type.
type Ref: TCFTypeRef;
- /// Returns the object as its concrete TypeRef.
+ /// Returns the object as its concrete `TypeRef`.
fn as_concrete_TypeRef(&self) -> Self::Ref;
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
@@ -178,9 +171,7 @@ pub trait TCFType {
/// Returns the object as a wrapped `CFType`. The reference count is incremented by one.
#[inline]
fn as_CFType(&self) -> CFType {
- unsafe {
- TCFType::wrap_under_get_rule(self.as_CFTypeRef())
- }
+ unsafe { TCFType::wrap_under_get_rule(self.as_CFTypeRef()) }
}
/// Returns the object as a wrapped `CFType`. Consumes self and avoids changing the reference
@@ -206,27 +197,21 @@ pub trait TCFType {
/// whether the return value of this method is greater than zero.
#[inline]
fn retain_count(&self) -> CFIndex {
- unsafe {
- CFGetRetainCount(self.as_CFTypeRef())
- }
+ unsafe { CFGetRetainCount(self.as_CFTypeRef()) }
}
/// Returns the type ID of this object.
#[inline]
fn type_of(&self) -> CFTypeID {
- unsafe {
- CFGetTypeID(self.as_CFTypeRef())
- }
+ unsafe { CFGetTypeID(self.as_CFTypeRef()) }
}
/// Writes a debugging version of this object on standard error.
fn show(&self) {
- unsafe {
- CFShow(self.as_CFTypeRef())
- }
+ unsafe { CFShow(self.as_CFTypeRef()) }
}
- /// Returns true if this value is an instance of another type.
+ /// Returns `true` if this value is an instance of another type.
#[inline]
fn instance_of<OtherCFType: TCFType>(&self) -> bool {
self.type_of() == OtherCFType::type_id()
@@ -318,9 +303,11 @@ impl<'a, T: PartialEq> PartialEq for ItemMutRef<'a, T> {
}
}
-/// A trait describing how to convert from the stored *mut c_void to the desired T
+/// A trait describing how to convert from the stored `*mut c_void` to the desired `T`
pub unsafe trait FromMutVoid {
- unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> where Self: std::marker::Sized;
+ unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self>
+ where
+ Self: std::marker::Sized;
}
unsafe impl FromMutVoid for u32 {
@@ -337,13 +324,18 @@ unsafe impl FromMutVoid for *const c_void {
unsafe impl<T: TCFType> FromMutVoid for T {
unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
- ItemMutRef(ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))), PhantomData)
+ ItemMutRef(
+ ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))),
+ PhantomData,
+ )
}
}
-/// A trait describing how to convert from the stored *const c_void to the desired T
+/// A trait describing how to convert from the stored `*const c_void` to the desired `T`
pub unsafe trait FromVoid {
- unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> where Self: std::marker::Sized;
+ unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self>
+ where
+ Self: std::marker::Sized;
}
unsafe impl FromVoid for u32 {
@@ -362,11 +354,14 @@ unsafe impl FromVoid for *const c_void {
unsafe impl<T: TCFType> FromVoid for T {
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
- ItemRef(ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))), PhantomData)
+ ItemRef(
+ ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))),
+ PhantomData,
+ )
}
}
-/// A trait describing how to convert from the stored *const c_void to the desired T
+/// A trait describing how to convert from the stored `*const c_void` to the desired `T`
pub unsafe trait ToVoid<T> {
fn to_void(&self) -> *const c_void;
}
@@ -395,12 +390,11 @@ unsafe impl ToVoid<CFType> for CFTypeRef {
}
}
-
#[cfg(test)]
mod tests {
use super::*;
+ use crate::boolean::CFBoolean;
use std::mem;
- use boolean::CFBoolean;
#[test]
fn cftype_instance_of() {
@@ -413,7 +407,7 @@ mod tests {
#[test]
fn as_cftype_retain_count() {
- let string = CFString::from_static_string("bar");
+ let string = CFString::from_static_string("alongerstring");
assert_eq!(string.retain_count(), 1);
let cftype = string.as_CFType();
assert_eq!(cftype.retain_count(), 2);
@@ -423,7 +417,7 @@ mod tests {
#[test]
fn into_cftype_retain_count() {
- let string = CFString::from_static_string("bar");
+ let string = CFString::from_static_string("alongerstring");
assert_eq!(string.retain_count(), 1);
let cftype = string.into_CFType();
assert_eq!(cftype.retain_count(), 1);
@@ -431,10 +425,10 @@ mod tests {
#[test]
fn as_cftype_and_downcast() {
- let string = CFString::from_static_string("bar");
+ let string = CFString::from_static_string("alongerstring");
let cftype = string.as_CFType();
let string2 = cftype.downcast::<CFString>().unwrap();
- assert_eq!(string2.to_string(), "bar");
+ assert_eq!(string2.to_string(), "alongerstring");
assert_eq!(string.retain_count(), 3);
assert_eq!(cftype.retain_count(), 3);
@@ -443,10 +437,10 @@ mod tests {
#[test]
fn into_cftype_and_downcast_into() {
- let string = CFString::from_static_string("bar");
+ let string = CFString::from_static_string("alongerstring");
let cftype = string.into_CFType();
let string2 = cftype.downcast_into::<CFString>().unwrap();
- assert_eq!(string2.to_string(), "bar");
+ assert_eq!(string2.to_string(), "alongerstring");
assert_eq!(string2.retain_count(), 1);
}
}
diff --git a/third_party/rust/core-foundation/src/boolean.rs b/third_party/rust/core-foundation/src/boolean.rs
index 8c13b907da..e0e2ff762f 100644
--- a/third_party/rust/core-foundation/src/boolean.rs
+++ b/third_party/rust/core-foundation/src/boolean.rs
@@ -9,12 +9,13 @@
//! A Boolean type.
-pub use core_foundation_sys::number::{CFBooleanRef, CFBooleanGetTypeID, kCFBooleanTrue, kCFBooleanFalse};
+pub use core_foundation_sys::number::{
+ kCFBooleanFalse, kCFBooleanTrue, CFBooleanGetTypeID, CFBooleanRef,
+};
-use base::TCFType;
+use crate::base::TCFType;
-
-declare_TCFType!{
+declare_TCFType! {
/// A Boolean type.
///
/// FIXME(pcwalton): Should be a newtype struct, but that fails due to a Rust compiler bug.
@@ -25,15 +26,11 @@ impl_CFTypeDescription!(CFBoolean);
impl CFBoolean {
pub fn true_value() -> CFBoolean {
- unsafe {
- TCFType::wrap_under_get_rule(kCFBooleanTrue)
- }
+ unsafe { TCFType::wrap_under_get_rule(kCFBooleanTrue) }
}
pub fn false_value() -> CFBoolean {
- unsafe {
- TCFType::wrap_under_get_rule(kCFBooleanFalse)
- }
+ unsafe { TCFType::wrap_under_get_rule(kCFBooleanFalse) }
}
}
diff --git a/third_party/rust/core-foundation/src/bundle.rs b/third_party/rust/core-foundation/src/bundle.rs
index b9ab1f65f6..f6d53a991f 100644
--- a/third_party/rust/core-foundation/src/bundle.rs
+++ b/third_party/rust/core-foundation/src/bundle.rs
@@ -14,13 +14,13 @@ pub use core_foundation_sys::bundle::*;
use core_foundation_sys::url::kCFURLPOSIXPathStyle;
use std::path::PathBuf;
-use base::{CFType, TCFType};
-use url::CFURL;
-use dictionary::CFDictionary;
+use crate::base::{CFType, TCFType};
+use crate::dictionary::CFDictionary;
+use crate::string::CFString;
+use crate::url::CFURL;
use std::os::raw::c_void;
-use string::CFString;
-declare_TCFType!{
+declare_TCFType! {
/// A Bundle type.
CFBundle, CFBundleRef
}
@@ -51,8 +51,10 @@ impl CFBundle {
pub fn function_pointer_for_name(&self, function_name: CFString) -> *const c_void {
unsafe {
- CFBundleGetFunctionPointerForName(self.as_concrete_TypeRef(),
- function_name.as_concrete_TypeRef())
+ CFBundleGetFunctionPointerForName(
+ self.as_concrete_TypeRef(),
+ function_name.as_concrete_TypeRef(),
+ )
}
}
@@ -96,7 +98,9 @@ impl CFBundle {
/// Bundle's own location
pub fn path(&self) -> Option<PathBuf> {
let url = self.bundle_url()?;
- Some(PathBuf::from(url.get_file_system_path(kCFURLPOSIXPathStyle).to_string()))
+ Some(PathBuf::from(
+ url.get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
+ ))
}
/// Bundle's resources location
@@ -114,7 +118,9 @@ impl CFBundle {
/// Bundle's resources location
pub fn resources_path(&self) -> Option<PathBuf> {
let url = self.bundle_resources_url()?;
- Some(PathBuf::from(url.get_file_system_path(kCFURLPOSIXPathStyle).to_string()))
+ Some(PathBuf::from(
+ url.get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
+ ))
}
pub fn private_frameworks_url(&self) -> Option<CFURL> {
@@ -140,11 +146,10 @@ impl CFBundle {
}
}
-
#[test]
fn safari_executable_url() {
- use string::CFString;
- use url::{CFURL, kCFURLPOSIXPathStyle};
+ use crate::string::CFString;
+ use crate::url::{kCFURLPOSIXPathStyle, CFURL};
let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
@@ -152,18 +157,20 @@ fn safari_executable_url() {
.expect("Safari not present")
.executable_url();
assert!(cfurl_executable.is_some());
- assert_eq!(cfurl_executable
- .unwrap()
- .absolute()
- .get_file_system_path(kCFURLPOSIXPathStyle)
- .to_string(),
- "/Applications/Safari.app/Contents/MacOS/Safari");
+ assert_eq!(
+ cfurl_executable
+ .unwrap()
+ .absolute()
+ .get_file_system_path(kCFURLPOSIXPathStyle)
+ .to_string(),
+ "/Applications/Safari.app/Contents/MacOS/Safari"
+ );
}
#[test]
fn safari_private_frameworks_url() {
- use string::CFString;
- use url::{CFURL, kCFURLPOSIXPathStyle};
+ use crate::string::CFString;
+ use crate::url::{kCFURLPOSIXPathStyle, CFURL};
let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
@@ -171,18 +178,20 @@ fn safari_private_frameworks_url() {
.expect("Safari not present")
.private_frameworks_url();
assert!(cfurl_executable.is_some());
- assert_eq!(cfurl_executable
- .unwrap()
- .absolute()
- .get_file_system_path(kCFURLPOSIXPathStyle)
- .to_string(),
- "/Applications/Safari.app/Contents/Frameworks");
+ assert_eq!(
+ cfurl_executable
+ .unwrap()
+ .absolute()
+ .get_file_system_path(kCFURLPOSIXPathStyle)
+ .to_string(),
+ "/Applications/Safari.app/Contents/Frameworks"
+ );
}
#[test]
fn non_existant_bundle() {
- use string::CFString;
- use url::{CFURL, kCFURLPOSIXPathStyle};
+ use crate::string::CFString;
+ use crate::url::{kCFURLPOSIXPathStyle, CFURL};
let cfstr_path = CFString::from_static_string("/usr/local/foo");
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
diff --git a/third_party/rust/core-foundation/src/characterset.rs b/third_party/rust/core-foundation/src/characterset.rs
index d1b9439d6e..2a05a931d4 100644
--- a/third_party/rust/core-foundation/src/characterset.rs
+++ b/third_party/rust/core-foundation/src/characterset.rs
@@ -11,9 +11,9 @@
pub use core_foundation_sys::characterset::*;
-use base::TCFType;
+use crate::base::TCFType;
-declare_TCFType!{
+declare_TCFType! {
/// An immutable set of Unicde characters.
CFCharacterSet, CFCharacterSetRef
}
diff --git a/third_party/rust/core-foundation/src/data.rs b/third_party/rust/core-foundation/src/data.rs
index c510c7434d..9f952199aa 100644
--- a/third_party/rust/core-foundation/src/data.rs
+++ b/third_party/rust/core-foundation/src/data.rs
@@ -9,18 +9,16 @@
//! Core Foundation byte buffers.
-pub use core_foundation_sys::data::*;
+use core_foundation_sys::base::kCFAllocatorDefault;
use core_foundation_sys::base::CFIndex;
-use core_foundation_sys::base::{kCFAllocatorDefault};
+pub use core_foundation_sys::data::*;
use std::ops::Deref;
use std::slice;
use std::sync::Arc;
+use crate::base::{CFIndexConvertible, TCFType};
-use base::{CFIndexConvertible, TCFType};
-
-
-declare_TCFType!{
+declare_TCFType! {
/// A byte buffer.
CFData, CFDataRef
}
@@ -28,20 +26,22 @@ impl_TCFType!(CFData, CFDataRef, CFDataGetTypeID);
impl_CFTypeDescription!(CFData);
impl CFData {
- /// Creates a CFData around a copy `buffer`
+ /// Creates a [`CFData`] around a copy `buffer`
pub fn from_buffer(buffer: &[u8]) -> CFData {
unsafe {
- let data_ref = CFDataCreate(kCFAllocatorDefault,
- buffer.as_ptr(),
- buffer.len().to_CFIndex());
+ let data_ref = CFDataCreate(
+ kCFAllocatorDefault,
+ buffer.as_ptr(),
+ buffer.len().to_CFIndex(),
+ );
TCFType::wrap_under_create_rule(data_ref)
}
}
- /// Creates a CFData referencing `buffer` without creating a copy
+ /// Creates a [`CFData`] referencing `buffer` without creating a copy
pub fn from_arc<T: AsRef<[u8]> + Sync + Send>(buffer: Arc<T>) -> Self {
- use std::os::raw::c_void;
use crate::base::{CFAllocator, CFAllocatorContext};
+ use std::os::raw::c_void;
unsafe {
let ptr = (*buffer).as_ref().as_ptr() as *const _;
@@ -67,8 +67,12 @@ impl CFData {
deallocate: Some(deallocate::<T>),
preferredSize: None,
});
- let data_ref =
- CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ptr, len, allocator.as_CFTypeRef());
+ let data_ref = CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault,
+ ptr,
+ len,
+ allocator.as_CFTypeRef(),
+ );
TCFType::wrap_under_create_rule(data_ref)
}
}
@@ -76,18 +80,20 @@ impl CFData {
/// Returns a pointer to the underlying bytes in this data. Note that this byte buffer is
/// read-only.
#[inline]
- pub fn bytes<'a>(&'a self) -> &'a [u8] {
- unsafe {
- slice::from_raw_parts(CFDataGetBytePtr(self.0), self.len() as usize)
- }
+ pub fn bytes(&self) -> &[u8] {
+ unsafe { slice::from_raw_parts(CFDataGetBytePtr(self.0), self.len() as usize) }
}
/// Returns the length of this byte buffer.
#[inline]
pub fn len(&self) -> CFIndex {
- unsafe {
- CFDataGetLength(self.0)
- }
+ unsafe { CFDataGetLength(self.0) }
+ }
+
+ /// Returns `true` if this byte buffer is empty.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
}
}
@@ -133,7 +139,10 @@ mod test {
}
let dropped = Arc::new(AtomicBool::default());
- let l = Arc::new(VecWrapper {inner: vec![5], dropped: dropped.clone() });
+ let l = Arc::new(VecWrapper {
+ inner: vec![5],
+ dropped: dropped.clone(),
+ });
let m = l.clone();
let dp = CFData::from_arc(l);
drop(m);
diff --git a/third_party/rust/core-foundation/src/date.rs b/third_party/rust/core-foundation/src/date.rs
index 57ee7211e6..c27bad25d1 100644
--- a/third_party/rust/core-foundation/src/date.rs
+++ b/third_party/rust/core-foundation/src/date.rs
@@ -9,16 +9,15 @@
//! Core Foundation date objects.
-pub use core_foundation_sys::date::*;
use core_foundation_sys::base::kCFAllocatorDefault;
+pub use core_foundation_sys::date::*;
-use base::TCFType;
+use crate::base::TCFType;
#[cfg(feature = "with-chrono")]
use chrono::NaiveDateTime;
-
-declare_TCFType!{
+declare_TCFType! {
/// A date.
CFDate, CFDateRef
}
@@ -42,16 +41,12 @@ impl CFDate {
#[inline]
pub fn abs_time(&self) -> CFAbsoluteTime {
- unsafe {
- CFDateGetAbsoluteTime(self.0)
- }
+ unsafe { CFDateGetAbsoluteTime(self.0) }
}
#[cfg(feature = "with-chrono")]
pub fn naive_utc(&self) -> NaiveDateTime {
- let ts = unsafe {
- self.abs_time() + kCFAbsoluteTimeIntervalSince1970
- };
+ let ts = unsafe { self.abs_time() + kCFAbsoluteTimeIntervalSince1970 };
let (secs, nanos) = if ts.is_sign_positive() {
(ts.trunc() as i64, ts.fract())
} else {
@@ -65,9 +60,7 @@ impl CFDate {
pub fn from_naive_utc(time: NaiveDateTime) -> CFDate {
let secs = time.timestamp();
let nanos = time.timestamp_subsec_nanos();
- let ts = unsafe {
- secs as f64 + (nanos as f64 / 1e9) - kCFAbsoluteTimeIntervalSince1970
- };
+ let ts = unsafe { secs as f64 + (nanos as f64 / 1e9) - kCFAbsoluteTimeIntervalSince1970 };
CFDate::new(ts)
}
}
@@ -86,7 +79,7 @@ mod test {
let same_sign = a.is_sign_positive() == b.is_sign_positive();
let equal = ((a - b).abs() / f64::min(a.abs() + b.abs(), f64::MAX)) < f64::EPSILON;
- (same_sign && equal)
+ same_sign && equal
}
#[test]
@@ -119,9 +112,7 @@ mod test {
fn date_chrono_conversion_negative() {
use super::kCFAbsoluteTimeIntervalSince1970;
- let ts = unsafe {
- kCFAbsoluteTimeIntervalSince1970 - 420.0
- };
+ let ts = unsafe { kCFAbsoluteTimeIntervalSince1970 - 420.0 };
let date = CFDate::new(ts);
let datetime: NaiveDateTime = date.naive_utc();
let converted = CFDate::from_naive_utc(datetime);
diff --git a/third_party/rust/core-foundation/src/dictionary.rs b/third_party/rust/core-foundation/src/dictionary.rs
index efcbba1178..aad37f3c81 100644
--- a/third_party/rust/core-foundation/src/dictionary.rs
+++ b/third_party/rust/core-foundation/src/dictionary.rs
@@ -11,18 +11,22 @@
pub use core_foundation_sys::dictionary::*;
-use core_foundation_sys::base::{CFTypeRef, CFRelease, kCFAllocatorDefault};
+use core_foundation_sys::base::{kCFAllocatorDefault, CFRelease, CFTypeRef};
+use std::marker::PhantomData;
use std::mem;
use std::os::raw::c_void;
use std::ptr;
-use std::marker::PhantomData;
-use base::{ItemRef, FromVoid, ToVoid};
-use base::{CFIndexConvertible, TCFType};
-use ConcreteCFType;
+use crate::base::{CFIndexConvertible, TCFType};
+use crate::base::{FromVoid, ItemRef, ToVoid};
+use crate::ConcreteCFType;
// consume the type parameters with PhantomDatas
-pub struct CFDictionary<K = *const c_void, V = *const c_void>(CFDictionaryRef, PhantomData<K>, PhantomData<V>);
+pub struct CFDictionary<K = *const c_void, V = *const c_void>(
+ CFDictionaryRef,
+ PhantomData<K>,
+ PhantomData<V>,
+);
impl<K, V> Drop for CFDictionary<K, V> {
fn drop(&mut self) {
@@ -36,19 +40,25 @@ impl_CFTypeDescription!(CFDictionary<K, V>);
unsafe impl ConcreteCFType for CFDictionary<*const c_void, *const c_void> {}
impl<K, V> CFDictionary<K, V> {
- pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFDictionary<K, V> where K: TCFType, V: TCFType {
+ pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFDictionary<K, V>
+ where
+ K: TCFType,
+ V: TCFType,
+ {
let (keys, values): (Vec<CFTypeRef>, Vec<CFTypeRef>) = pairs
.iter()
- .map(|&(ref key, ref value)| (key.as_CFTypeRef(), value.as_CFTypeRef()))
+ .map(|(key, value)| (key.as_CFTypeRef(), value.as_CFTypeRef()))
.unzip();
unsafe {
- let dictionary_ref = CFDictionaryCreate(kCFAllocatorDefault,
- keys.as_ptr(),
- values.as_ptr(),
- keys.len().to_CFIndex(),
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
+ let dictionary_ref = CFDictionaryCreate(
+ kCFAllocatorDefault,
+ keys.as_ptr(),
+ values.as_ptr(),
+ keys.len().to_CFIndex(),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks,
+ );
TCFType::wrap_under_create_rule(dictionary_ref)
}
}
@@ -76,9 +86,7 @@ impl<K, V> CFDictionary<K, V> {
#[inline]
pub fn len(&self) -> usize {
- unsafe {
- CFDictionaryGetCount(self.0) as usize
- }
+ unsafe { CFDictionaryGetCount(self.0) as usize }
}
#[inline]
@@ -87,12 +95,19 @@ impl<K, V> CFDictionary<K, V> {
}
#[inline]
- pub fn contains_key(&self, key: &K) -> bool where K: ToVoid<K> {
+ pub fn contains_key(&self, key: &K) -> bool
+ where
+ K: ToVoid<K>,
+ {
unsafe { CFDictionaryContainsKey(self.0, key.to_void()) != 0 }
}
#[inline]
- pub fn find<'a, T: ToVoid<K>>(&'a self, key: T) -> Option<ItemRef<'a, V>> where V: FromVoid, K: ToVoid<K> {
+ pub fn find<T: ToVoid<K>>(&self, key: T) -> Option<ItemRef<'_, V>>
+ where
+ V: FromVoid,
+ K: ToVoid<K>,
+ {
unsafe {
let mut value: *const c_void = ptr::null();
if CFDictionaryGetValueIfPresent(self.0, key.to_void(), &mut value) != 0 {
@@ -108,9 +123,14 @@ impl<K, V> CFDictionary<K, V> {
/// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead
/// of panicking.
#[inline]
- pub fn get<'a, T: ToVoid<K>>(&'a self, key: T) -> ItemRef<'a, V> where V: FromVoid, K: ToVoid<K> {
+ pub fn get<T: ToVoid<K>>(&self, key: T) -> ItemRef<'_, V>
+ where
+ V: FromVoid,
+ K: ToVoid<K>,
+ {
let ptr = key.to_void();
- self.find(key).unwrap_or_else(|| panic!("No entry found for key {:p}", ptr))
+ self.find(key)
+ .unwrap_or_else(|| panic!("No entry found for key {:p}", ptr))
}
pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) {
@@ -129,7 +149,11 @@ impl<K, V> CFDictionary<K, V> {
}
// consume the type parameters with PhantomDatas
-pub struct CFMutableDictionary<K = *const c_void, V = *const c_void>(CFMutableDictionaryRef, PhantomData<K>, PhantomData<V>);
+pub struct CFMutableDictionary<K = *const c_void, V = *const c_void>(
+ CFMutableDictionaryRef,
+ PhantomData<K>,
+ PhantomData<V>,
+);
impl<K, V> Drop for CFMutableDictionary<K, V> {
fn drop(&mut self) {
@@ -147,24 +171,31 @@ impl<K, V> CFMutableDictionary<K, V> {
pub fn with_capacity(capacity: isize) -> Self {
unsafe {
- let dictionary_ref = CFDictionaryCreateMutable(kCFAllocatorDefault,
- capacity as _,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
+ let dictionary_ref = CFDictionaryCreateMutable(
+ kCFAllocatorDefault,
+ capacity as _,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks,
+ );
TCFType::wrap_under_create_rule(dictionary_ref)
}
}
pub fn copy_with_capacity(&self, capacity: isize) -> Self {
unsafe {
- let dictionary_ref = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, capacity as _, self.0);
+ let dictionary_ref =
+ CFDictionaryCreateMutableCopy(kCFAllocatorDefault, capacity as _, self.0);
TCFType::wrap_under_get_rule(dictionary_ref)
}
}
- pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFMutableDictionary<K, V> where K: ToVoid<K>, V: ToVoid<V> {
+ pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFMutableDictionary<K, V>
+ where
+ K: ToVoid<K>,
+ V: ToVoid<V>,
+ {
let mut result = Self::with_capacity(pairs.len() as _);
- for &(ref key, ref value) in pairs {
+ for (key, value) in pairs {
result.add(key, value);
}
result
@@ -194,9 +225,7 @@ impl<K, V> CFMutableDictionary<K, V> {
#[inline]
pub fn len(&self) -> usize {
- unsafe {
- CFDictionaryGetCount(self.0) as usize
- }
+ unsafe { CFDictionaryGetCount(self.0) as usize }
}
#[inline]
@@ -206,13 +235,15 @@ impl<K, V> CFMutableDictionary<K, V> {
#[inline]
pub fn contains_key(&self, key: *const c_void) -> bool {
- unsafe {
- CFDictionaryContainsKey(self.0, key) != 0
- }
+ unsafe { CFDictionaryContainsKey(self.0, key) != 0 }
}
#[inline]
- pub fn find<'a>(&'a self, key: &K) -> Option<ItemRef<'a, V>> where V: FromVoid, K: ToVoid<K> {
+ pub fn find<'a>(&'a self, key: &K) -> Option<ItemRef<'a, V>>
+ where
+ V: FromVoid,
+ K: ToVoid<K>,
+ {
unsafe {
let mut value: *const c_void = ptr::null();
if CFDictionaryGetValueIfPresent(self.0, key.to_void(), &mut value) != 0 {
@@ -228,9 +259,14 @@ impl<K, V> CFMutableDictionary<K, V> {
/// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead
/// of panicking.
#[inline]
- pub fn get<'a>(&'a self, key: &K) -> ItemRef<'a, V> where V: FromVoid, K: ToVoid<K> {
+ pub fn get<'a>(&'a self, key: &K) -> ItemRef<'a, V>
+ where
+ V: FromVoid,
+ K: ToVoid<K>,
+ {
let ptr = key.to_void();
- self.find(&key).unwrap_or_else(|| panic!("No entry found for key {:p}", ptr))
+ self.find(key)
+ .unwrap_or_else(|| panic!("No entry found for key {:p}", ptr))
}
pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) {
@@ -251,25 +287,40 @@ impl<K, V> CFMutableDictionary<K, V> {
/// Adds the key-value pair to the dictionary if no such key already exist.
#[inline]
- pub fn add(&mut self, key: &K, value: &V) where K: ToVoid<K>, V: ToVoid<V> {
+ pub fn add(&mut self, key: &K, value: &V)
+ where
+ K: ToVoid<K>,
+ V: ToVoid<V>,
+ {
unsafe { CFDictionaryAddValue(self.0, key.to_void(), value.to_void()) }
}
/// Sets the value of the key in the dictionary.
#[inline]
- pub fn set(&mut self, key: K, value: V) where K: ToVoid<K>, V: ToVoid<V> {
+ pub fn set(&mut self, key: K, value: V)
+ where
+ K: ToVoid<K>,
+ V: ToVoid<V>,
+ {
unsafe { CFDictionarySetValue(self.0, key.to_void(), value.to_void()) }
}
/// Replaces the value of the key in the dictionary.
#[inline]
- pub fn replace(&mut self, key: K, value: V) where K: ToVoid<K>, V: ToVoid<V> {
+ pub fn replace(&mut self, key: K, value: V)
+ where
+ K: ToVoid<K>,
+ V: ToVoid<V>,
+ {
unsafe { CFDictionaryReplaceValue(self.0, key.to_void(), value.to_void()) }
}
/// Removes the value of the key from the dictionary.
#[inline]
- pub fn remove(&mut self, key: K) where K: ToVoid<K> {
+ pub fn remove(&mut self, key: K)
+ where
+ K: ToVoid<K>,
+ {
unsafe { CFDictionaryRemoveValue(self.0, key.to_void()) }
}
@@ -296,15 +347,13 @@ impl<'a, K, V> From<&'a CFDictionary<K, V>> for CFMutableDictionary<K, V> {
}
}
-
#[cfg(test)]
pub mod test {
use super::*;
- use base::{CFType, TCFType};
- use boolean::CFBoolean;
- use number::CFNumber;
- use string::CFString;
-
+ use crate::base::{CFType, TCFType};
+ use crate::boolean::CFBoolean;
+ use crate::number::CFNumber;
+ use crate::string::CFString;
#[test]
fn dictionary() {
@@ -322,8 +371,14 @@ pub mod test {
]);
let (v1, v2) = d.get_keys_and_values();
- assert_eq!(v1, &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]);
- assert_eq!(v2, &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]);
+ assert_eq!(
+ v1,
+ &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]
+ );
+ assert_eq!(
+ v2,
+ &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]
+ );
}
#[test]
@@ -342,8 +397,14 @@ pub mod test {
assert_eq!(d.len(), 3);
let (v1, v2) = d.get_keys_and_values();
- assert_eq!(v1, &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]);
- assert_eq!(v2, &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]);
+ assert_eq!(
+ v1,
+ &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]
+ );
+ assert_eq!(
+ v2,
+ &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]
+ );
d.remove(baz);
assert_eq!(d.len(), 2);
@@ -358,12 +419,10 @@ pub mod test {
#[test]
fn dict_find_and_contains_key() {
- let dict = CFDictionary::from_CFType_pairs(&[
- (
- CFString::from_static_string("hello"),
- CFBoolean::true_value(),
- ),
- ]);
+ let dict = CFDictionary::from_CFType_pairs(&[(
+ CFString::from_static_string("hello"),
+ CFBoolean::true_value(),
+ )]);
let key = CFString::from_static_string("hello");
let invalid_key = CFString::from_static_string("foobar");
@@ -377,17 +436,24 @@ pub mod test {
#[test]
fn convert_immutable_to_mutable_dict() {
- let dict: CFDictionary<CFString, CFBoolean> = CFDictionary::from_CFType_pairs(&[
- (CFString::from_static_string("Foo"), CFBoolean::true_value()),
- ]);
+ let dict: CFDictionary<CFString, CFBoolean> = CFDictionary::from_CFType_pairs(&[(
+ CFString::from_static_string("Foo"),
+ CFBoolean::true_value(),
+ )]);
let mut mut_dict = CFMutableDictionary::from(&dict);
assert_eq!(dict.retain_count(), 1);
assert_eq!(mut_dict.retain_count(), 1);
assert_eq!(mut_dict.len(), 1);
- assert_eq!(*mut_dict.get(&CFString::from_static_string("Foo")), CFBoolean::true_value());
-
- mut_dict.add(&CFString::from_static_string("Bar"), &CFBoolean::false_value());
+ assert_eq!(
+ *mut_dict.get(&CFString::from_static_string("Foo")),
+ CFBoolean::true_value()
+ );
+
+ mut_dict.add(
+ &CFString::from_static_string("Bar"),
+ &CFBoolean::false_value(),
+ );
assert_eq!(dict.len(), 1);
assert_eq!(mut_dict.len(), 2);
}
@@ -395,13 +461,19 @@ pub mod test {
#[test]
fn mutable_dictionary_as_immutable() {
let mut mut_dict: CFMutableDictionary<CFString, CFBoolean> = CFMutableDictionary::new();
- mut_dict.add(&CFString::from_static_string("Bar"), &CFBoolean::false_value());
+ mut_dict.add(
+ &CFString::from_static_string("Bar"),
+ &CFBoolean::false_value(),
+ );
assert_eq!(mut_dict.retain_count(), 1);
let dict = mut_dict.to_immutable();
assert_eq!(mut_dict.retain_count(), 2);
assert_eq!(dict.retain_count(), 2);
- assert_eq!(*dict.get(&CFString::from_static_string("Bar")), CFBoolean::false_value());
+ assert_eq!(
+ *dict.get(&CFString::from_static_string("Bar")),
+ CFBoolean::false_value()
+ );
mem::drop(dict);
assert_eq!(mut_dict.retain_count(), 1);
diff --git a/third_party/rust/core-foundation/src/error.rs b/third_party/rust/core-foundation/src/error.rs
index f100171bc9..e5a2242596 100644
--- a/third_party/rust/core-foundation/src/error.rs
+++ b/third_party/rust/core-foundation/src/error.rs
@@ -14,11 +14,10 @@ pub use core_foundation_sys::error::*;
use std::error::Error;
use std::fmt;
-use base::{CFIndex, TCFType};
-use string::CFString;
+use crate::base::{CFIndex, TCFType};
+use crate::string::CFString;
-
-declare_TCFType!{
+declare_TCFType! {
/// An error value.
CFError, CFErrorRef
}
@@ -27,10 +26,10 @@ impl_TCFType!(CFError, CFErrorRef, CFErrorGetTypeID);
impl fmt::Debug for CFError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("CFError")
- .field("domain", &self.domain())
- .field("code", &self.code())
- .field("description", &self.description())
- .finish()
+ .field("domain", &self.domain())
+ .field("code", &self.code())
+ .field("description", &self.description())
+ .finish()
}
}
diff --git a/third_party/rust/core-foundation/src/filedescriptor.rs b/third_party/rust/core-foundation/src/filedescriptor.rs
index e153c70b2f..876d1cec0a 100644
--- a/third_party/rust/core-foundation/src/filedescriptor.rs
+++ b/third_party/rust/core-foundation/src/filedescriptor.rs
@@ -9,33 +9,41 @@
pub use core_foundation_sys::filedescriptor::*;
-use core_foundation_sys::base::{Boolean, CFIndex};
use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
+use core_foundation_sys::base::{Boolean, CFIndex};
-use base::TCFType;
-use runloop::CFRunLoopSource;
+use crate::base::TCFType;
+use crate::runloop::CFRunLoopSource;
use std::mem::MaybeUninit;
use std::os::unix::io::{AsRawFd, RawFd};
use std::ptr;
-declare_TCFType!{
+declare_TCFType! {
CFFileDescriptor, CFFileDescriptorRef
}
-impl_TCFType!(CFFileDescriptor, CFFileDescriptorRef, CFFileDescriptorGetTypeID);
+impl_TCFType!(
+ CFFileDescriptor,
+ CFFileDescriptorRef,
+ CFFileDescriptorGetTypeID
+);
impl CFFileDescriptor {
- pub fn new(fd: RawFd,
- closeOnInvalidate: bool,
- callout: CFFileDescriptorCallBack,
- context: Option<&CFFileDescriptorContext>) -> Option<CFFileDescriptor> {
+ pub fn new(
+ fd: RawFd,
+ closeOnInvalidate: bool,
+ callout: CFFileDescriptorCallBack,
+ context: Option<&CFFileDescriptorContext>,
+ ) -> Option<CFFileDescriptor> {
let context = context.map_or(ptr::null(), |c| c as *const _);
unsafe {
- let fd_ref = CFFileDescriptorCreate(kCFAllocatorDefault,
- fd,
- closeOnInvalidate as Boolean,
- callout,
- context);
+ let fd_ref = CFFileDescriptorCreate(
+ kCFAllocatorDefault,
+ fd,
+ closeOnInvalidate as Boolean,
+ callout,
+ context,
+ );
if fd_ref.is_null() {
None
} else {
@@ -53,36 +61,25 @@ impl CFFileDescriptor {
}
pub fn enable_callbacks(&self, callback_types: CFOptionFlags) {
- unsafe {
- CFFileDescriptorEnableCallBacks(self.0, callback_types)
- }
+ unsafe { CFFileDescriptorEnableCallBacks(self.0, callback_types) }
}
pub fn disable_callbacks(&self, callback_types: CFOptionFlags) {
- unsafe {
- CFFileDescriptorDisableCallBacks(self.0, callback_types)
- }
+ unsafe { CFFileDescriptorDisableCallBacks(self.0, callback_types) }
}
pub fn valid(&self) -> bool {
- unsafe {
- CFFileDescriptorIsValid(self.0) != 0
- }
+ unsafe { CFFileDescriptorIsValid(self.0) != 0 }
}
pub fn invalidate(&self) {
- unsafe {
- CFFileDescriptorInvalidate(self.0)
- }
+ unsafe { CFFileDescriptorInvalidate(self.0) }
}
pub fn to_run_loop_source(&self, order: CFIndex) -> Option<CFRunLoopSource> {
unsafe {
- let source_ref = CFFileDescriptorCreateRunLoopSource(
- kCFAllocatorDefault,
- self.0,
- order
- );
+ let source_ref =
+ CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, self.0, order);
if source_ref.is_null() {
None
} else {
@@ -94,24 +91,21 @@ impl CFFileDescriptor {
impl AsRawFd for CFFileDescriptor {
fn as_raw_fd(&self) -> RawFd {
- unsafe {
- CFFileDescriptorGetNativeDescriptor(self.0)
- }
+ unsafe { CFFileDescriptorGetNativeDescriptor(self.0) }
}
}
-
#[cfg(test)]
mod test {
extern crate libc;
use super::*;
+ use crate::runloop::CFRunLoop;
+ use core_foundation_sys::base::CFOptionFlags;
+ use core_foundation_sys::runloop::kCFRunLoopDefaultMode;
+ use libc::O_RDWR;
use std::ffi::CString;
use std::os::raw::c_void;
- use core_foundation_sys::base::{CFOptionFlags};
- use core_foundation_sys::runloop::{kCFRunLoopDefaultMode};
- use libc::O_RDWR;
- use runloop::{CFRunLoop};
#[test]
fn test_unconsumed() {
@@ -129,14 +123,16 @@ mod test {
assert_eq!(unsafe { libc::close(raw_fd) }, 0);
}
- extern "C" fn never_callback(_f: CFFileDescriptorRef,
- _callback_types: CFOptionFlags,
- _info_ptr: *mut c_void) {
+ extern "C" fn never_callback(
+ _f: CFFileDescriptorRef,
+ _callback_types: CFOptionFlags,
+ _info_ptr: *mut c_void,
+ ) {
unreachable!();
}
struct TestInfo {
- value: CFOptionFlags
+ value: CFOptionFlags,
}
#[test]
@@ -147,7 +143,7 @@ mod test {
info: &mut info as *mut _ as *mut c_void,
retain: None,
release: None,
- copyDescription: None
+ copyDescription: None,
};
let path = CString::new("/dev/null").unwrap();
@@ -182,7 +178,11 @@ mod test {
assert!(!cf_fd.valid());
}
- extern "C" fn callback(_f: CFFileDescriptorRef, callback_types: CFOptionFlags, info_ptr: *mut c_void) {
+ extern "C" fn callback(
+ _f: CFFileDescriptorRef,
+ callback_types: CFOptionFlags,
+ info_ptr: *mut c_void,
+ ) {
assert!(!info_ptr.is_null());
let info: *mut TestInfo = info_ptr as *mut TestInfo;
diff --git a/third_party/rust/core-foundation/src/lib.rs b/third_party/rust/core-foundation/src/lib.rs
index b935938996..767d45aad1 100644
--- a/third_party/rust/core-foundation/src/lib.rs
+++ b/third_party/rust/core-foundation/src/lib.rs
@@ -21,7 +21,7 @@ extern crate libc;
#[cfg(feature = "with-chrono")]
extern crate chrono;
-use base::TCFType;
+use crate::base::TCFType;
pub unsafe trait ConcreteCFType: TCFType {}
@@ -165,7 +165,6 @@ macro_rules! impl_TCFType {
(@Phantom $x:ident) => { ::std::marker::PhantomData };
}
-
/// Implement `std::fmt::Debug` for the given type.
///
/// This will invoke the implementation of `Debug` for [`CFType`]
@@ -200,7 +199,14 @@ macro_rules! impl_CFComparison {
#[inline]
fn partial_cmp(&self, other: &$ty) -> Option<::std::cmp::Ordering> {
unsafe {
- Some($compare(self.as_concrete_TypeRef(), other.as_concrete_TypeRef(), ::std::ptr::null_mut()).into())
+ Some(
+ $compare(
+ self.as_concrete_TypeRef(),
+ other.as_concrete_TypeRef(),
+ ::std::ptr::null_mut(),
+ )
+ .into(),
+ )
}
}
}
@@ -211,26 +217,26 @@ macro_rules! impl_CFComparison {
self.partial_cmp(other).unwrap()
}
}
- }
+ };
}
pub mod array;
pub mod attributed_string;
pub mod base;
pub mod boolean;
+pub mod bundle;
pub mod characterset;
pub mod data;
pub mod date;
pub mod dictionary;
pub mod error;
pub mod filedescriptor;
+pub mod mach_port;
pub mod number;
-pub mod set;
-pub mod string;
-pub mod url;
-pub mod bundle;
pub mod propertylist;
pub mod runloop;
+pub mod set;
+pub mod string;
pub mod timezone;
+pub mod url;
pub mod uuid;
-pub mod mach_port;
diff --git a/third_party/rust/core-foundation/src/mach_port.rs b/third_party/rust/core-foundation/src/mach_port.rs
index 6112e3aae0..f01847fff1 100644
--- a/third_party/rust/core-foundation/src/mach_port.rs
+++ b/third_party/rust/core-foundation/src/mach_port.rs
@@ -1,9 +1,8 @@
-use base::TCFType;
+use crate::base::TCFType;
+use crate::runloop::CFRunLoopSource;
use core_foundation_sys::base::kCFAllocatorDefault;
-use runloop::CFRunLoopSource;
pub use core_foundation_sys::mach_port::*;
-
declare_TCFType! {
/// An immutable numeric value.
CFMachPort, CFMachPortRef
@@ -12,12 +11,10 @@ impl_TCFType!(CFMachPort, CFMachPortRef, CFMachPortGetTypeID);
impl_CFTypeDescription!(CFMachPort);
impl CFMachPort {
- pub fn create_runloop_source(
- &self,
- order: CFIndex,
- ) -> Result<CFRunLoopSource, ()> {
+ pub fn create_runloop_source(&self, order: CFIndex) -> Result<CFRunLoopSource, ()> {
unsafe {
- let runloop_source_ref = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, self.0, order);
+ let runloop_source_ref =
+ CFMachPortCreateRunLoopSource(kCFAllocatorDefault, self.0, order);
if runloop_source_ref.is_null() {
Err(())
} else {
diff --git a/third_party/rust/core-foundation/src/number.rs b/third_party/rust/core-foundation/src/number.rs
index a4b2affaa7..c3b6fab96c 100644
--- a/third_party/rust/core-foundation/src/number.rs
+++ b/third_party/rust/core-foundation/src/number.rs
@@ -13,10 +13,9 @@ use core_foundation_sys::base::kCFAllocatorDefault;
pub use core_foundation_sys::number::*;
use std::os::raw::c_void;
-use base::TCFType;
+use crate::base::TCFType;
-
-declare_TCFType!{
+declare_TCFType! {
/// An immutable numeric value.
CFNumber, CFNumberRef
}
@@ -25,13 +24,20 @@ impl_CFTypeDescription!(CFNumber);
impl_CFComparison!(CFNumber, CFNumberCompare);
impl CFNumber {
-
#[inline]
pub fn to_i32(&self) -> Option<i32> {
unsafe {
let mut value: i32 = 0;
- let ok = CFNumberGetValue(self.0, kCFNumberSInt32Type, &mut value as *mut i32 as *mut c_void);
- if ok { Some(value) } else { None }
+ let ok = CFNumberGetValue(
+ self.0,
+ kCFNumberSInt32Type,
+ &mut value as *mut i32 as *mut c_void,
+ );
+ if ok {
+ Some(value)
+ } else {
+ None
+ }
}
}
@@ -39,8 +45,16 @@ impl CFNumber {
pub fn to_i64(&self) -> Option<i64> {
unsafe {
let mut value: i64 = 0;
- let ok = CFNumberGetValue(self.0, kCFNumberSInt64Type, &mut value as *mut i64 as *mut c_void);
- if ok { Some(value) } else { None }
+ let ok = CFNumberGetValue(
+ self.0,
+ kCFNumberSInt64Type,
+ &mut value as *mut i64 as *mut c_void,
+ );
+ if ok {
+ Some(value)
+ } else {
+ None
+ }
}
}
@@ -48,8 +62,16 @@ impl CFNumber {
pub fn to_f32(&self) -> Option<f32> {
unsafe {
let mut value: f32 = 0.0;
- let ok = CFNumberGetValue(self.0, kCFNumberFloat32Type, &mut value as *mut f32 as *mut c_void);
- if ok { Some(value) } else { None }
+ let ok = CFNumberGetValue(
+ self.0,
+ kCFNumberFloat32Type,
+ &mut value as *mut f32 as *mut c_void,
+ );
+ if ok {
+ Some(value)
+ } else {
+ None
+ }
}
}
@@ -57,8 +79,16 @@ impl CFNumber {
pub fn to_f64(&self) -> Option<f64> {
unsafe {
let mut value: f64 = 0.0;
- let ok = CFNumberGetValue(self.0, kCFNumberFloat64Type, &mut value as *mut f64 as *mut c_void);
- if ok { Some(value) } else { None }
+ let ok = CFNumberGetValue(
+ self.0,
+ kCFNumberFloat64Type,
+ &mut value as *mut f64 as *mut c_void,
+ );
+ if ok {
+ Some(value)
+ } else {
+ None
+ }
}
}
}
diff --git a/third_party/rust/core-foundation/src/propertylist.rs b/third_party/rust/core-foundation/src/propertylist.rs
index e8fceac58d..de5d1d87ba 100644
--- a/third_party/rust/core-foundation/src/propertylist.rs
+++ b/third_party/rust/core-foundation/src/propertylist.rs
@@ -9,30 +9,34 @@
//! Core Foundation property lists
-use std::ptr;
use std::mem;
use std::os::raw::c_void;
+use std::ptr;
-use error::CFError;
-use data::CFData;
-use base::{CFType, TCFType, TCFTypeRef};
+use crate::base::{CFType, TCFType, TCFTypeRef};
+use crate::data::CFData;
+use crate::error::CFError;
-pub use core_foundation_sys::propertylist::*;
+use core_foundation_sys::base::{
+ kCFAllocatorDefault, CFGetRetainCount, CFGetTypeID, CFIndex, CFRetain, CFShow, CFTypeID,
+};
use core_foundation_sys::error::CFErrorRef;
-use core_foundation_sys::base::{CFGetRetainCount, CFGetTypeID, CFIndex, CFRetain,
- CFShow, CFTypeID, kCFAllocatorDefault};
+pub use core_foundation_sys::propertylist::*;
-pub fn create_with_data(data: CFData,
- options: CFPropertyListMutabilityOptions)
- -> Result<(*const c_void, CFPropertyListFormat), CFError> {
+pub fn create_with_data(
+ data: CFData,
+ options: CFPropertyListMutabilityOptions,
+) -> Result<(*const c_void, CFPropertyListFormat), CFError> {
unsafe {
let mut error: CFErrorRef = ptr::null_mut();
let mut format: CFPropertyListFormat = 0;
- let property_list = CFPropertyListCreateWithData(kCFAllocatorDefault,
- data.as_concrete_TypeRef(),
- options,
- &mut format,
- &mut error);
+ let property_list = CFPropertyListCreateWithData(
+ kCFAllocatorDefault,
+ data.as_concrete_TypeRef(),
+ options,
+ &mut format,
+ &mut error,
+ );
if property_list.is_null() {
Err(TCFType::wrap_under_create_rule(error))
} else {
@@ -41,14 +45,14 @@ pub fn create_with_data(data: CFData,
}
}
-pub fn create_data(property_list: *const c_void, format: CFPropertyListFormat) -> Result<CFData, CFError> {
+pub fn create_data(
+ property_list: *const c_void,
+ format: CFPropertyListFormat,
+) -> Result<CFData, CFError> {
unsafe {
let mut error: CFErrorRef = ptr::null_mut();
- let data_ref = CFPropertyListCreateData(kCFAllocatorDefault,
- property_list,
- format,
- 0,
- &mut error);
+ let data_ref =
+ CFPropertyListCreateData(kCFAllocatorDefault, property_list, format, 0, &mut error);
if data_ref.is_null() {
Err(TCFType::wrap_under_create_rule(error))
} else {
@@ -57,7 +61,6 @@ pub fn create_data(property_list: *const c_void, format: CFPropertyListFormat) -
}
}
-
/// Trait for all subclasses of [`CFPropertyList`].
///
/// [`CFPropertyList`]: struct.CFPropertyList.html
@@ -84,16 +87,15 @@ pub trait CFPropertyListSubClass: TCFType {
}
}
-impl CFPropertyListSubClass for ::data::CFData {}
-impl CFPropertyListSubClass for ::string::CFString {}
-impl CFPropertyListSubClass for ::array::CFArray {}
-impl CFPropertyListSubClass for ::dictionary::CFDictionary {}
-impl CFPropertyListSubClass for ::date::CFDate {}
-impl CFPropertyListSubClass for ::boolean::CFBoolean {}
-impl CFPropertyListSubClass for ::number::CFNumber {}
-
+impl CFPropertyListSubClass for crate::data::CFData {}
+impl CFPropertyListSubClass for crate::string::CFString {}
+impl CFPropertyListSubClass for crate::array::CFArray {}
+impl CFPropertyListSubClass for crate::dictionary::CFDictionary {}
+impl CFPropertyListSubClass for crate::date::CFDate {}
+impl CFPropertyListSubClass for crate::boolean::CFBoolean {}
+impl CFPropertyListSubClass for crate::number::CFNumber {}
-declare_TCFType!{
+declare_TCFType! {
/// A CFPropertyList struct. This is superclass to [`CFData`], [`CFString`], [`CFArray`],
/// [`CFDictionary`], [`CFDate`], [`CFBoolean`], and [`CFNumber`].
///
@@ -161,8 +163,8 @@ impl CFPropertyList {
unsafe { CFGetRetainCount(self.as_CFTypeRef()) }
}
- /// Returns the type ID of this object. Will be one of CFData, CFString, CFArray, CFDictionary,
- /// CFDate, CFBoolean, or CFNumber.
+ /// Returns the type ID of this object. Will be one of `CFData`, `CFString`, `CFArray`,
+ /// `CFDictionary`, `CFDate`, `CFBoolean`, or `CFNumber`.
#[inline]
pub fn type_of(&self) -> CFTypeID {
unsafe { CFGetTypeID(self.as_CFTypeRef()) }
@@ -173,7 +175,7 @@ impl CFPropertyList {
unsafe { CFShow(self.as_CFTypeRef()) }
}
- /// Returns true if this value is an instance of another type.
+ /// Returns `true` if this value is an instance of another type.
#[inline]
pub fn instance_of<OtherCFType: TCFType>(&self) -> bool {
self.type_of() == OtherCFType::type_id()
@@ -244,33 +246,33 @@ impl CFPropertyList {
}
}
-
-
#[cfg(test)]
pub mod test {
use super::*;
- use string::CFString;
- use boolean::CFBoolean;
+ use crate::boolean::CFBoolean;
+ use crate::string::CFString;
#[test]
fn test_property_list_serialization() {
- use base::{TCFType, CFEqual};
- use boolean::CFBoolean;
- use number::CFNumber;
- use dictionary::CFDictionary;
- use string::CFString;
use super::*;
+ use crate::base::{CFEqual, TCFType};
+ use crate::boolean::CFBoolean;
+ use crate::dictionary::CFDictionary;
+ use crate::number::CFNumber;
+ use crate::string::CFString;
let bar = CFString::from_static_string("Bar");
let baz = CFString::from_static_string("Baz");
let boo = CFString::from_static_string("Boo");
let foo = CFString::from_static_string("Foo");
let tru = CFBoolean::true_value();
- let n42 = CFNumber::from(1i64<<33);
+ let n42 = CFNumber::from(1i64 << 33);
- let dict1 = CFDictionary::from_CFType_pairs(&[(bar.as_CFType(), boo.as_CFType()),
- (baz.as_CFType(), tru.as_CFType()),
- (foo.as_CFType(), n42.as_CFType())]);
+ let dict1 = CFDictionary::from_CFType_pairs(&[
+ (bar.as_CFType(), boo.as_CFType()),
+ (baz.as_CFType(), tru.as_CFType()),
+ (foo.as_CFType(), n42.as_CFType()),
+ ]);
let data = create_data(dict1.as_CFTypeRef(), kCFPropertyListXMLFormat_v1_0).unwrap();
let (dict2, _) = create_with_data(data, kCFPropertyListImmutable).unwrap();
@@ -281,7 +283,7 @@ pub mod test {
#[test]
fn to_propertylist_retain_count() {
- let string = CFString::from_static_string("Bar");
+ let string = CFString::from_static_string("alongerstring");
assert_eq!(string.retain_count(), 1);
let propertylist = string.to_CFPropertyList();
@@ -295,7 +297,10 @@ pub mod test {
#[test]
fn downcast_string() {
let propertylist = CFString::from_static_string("Bar").to_CFPropertyList();
- assert_eq!(propertylist.downcast::<CFString>().unwrap().to_string(), "Bar");
+ assert_eq!(
+ propertylist.downcast::<CFString>().unwrap().to_string(),
+ "Bar"
+ );
assert!(propertylist.downcast::<CFBoolean>().is_none());
}
@@ -308,7 +313,7 @@ pub mod test {
#[test]
fn downcast_into_fail() {
- let string = CFString::from_static_string("Bar");
+ let string = CFString::from_static_string("alongerstring");
let propertylist = string.to_CFPropertyList();
assert_eq!(string.retain_count(), 2);
@@ -318,12 +323,12 @@ pub mod test {
#[test]
fn downcast_into() {
- let string = CFString::from_static_string("Bar");
+ let string = CFString::from_static_string("alongerstring");
let propertylist = string.to_CFPropertyList();
assert_eq!(string.retain_count(), 2);
let string2 = propertylist.downcast_into::<CFString>().unwrap();
- assert_eq!(string2.to_string(), "Bar");
+ assert_eq!(string2.to_string(), "alongerstring");
assert_eq!(string2.retain_count(), 2);
}
}
diff --git a/third_party/rust/core-foundation/src/runloop.rs b/third_party/rust/core-foundation/src/runloop.rs
index be06f4ec7f..304c0716df 100644
--- a/third_party/rust/core-foundation/src/runloop.rs
+++ b/third_party/rust/core-foundation/src/runloop.rs
@@ -9,23 +9,26 @@
#![allow(non_upper_case_globals)]
-pub use core_foundation_sys::runloop::*;
use core_foundation_sys::base::CFIndex;
use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
+pub use core_foundation_sys::runloop::*;
use core_foundation_sys::string::CFStringRef;
-use base::{TCFType};
-use date::{CFAbsoluteTime, CFTimeInterval};
-use filedescriptor::CFFileDescriptor;
-use string::{CFString};
+use crate::base::TCFType;
+use crate::date::{CFAbsoluteTime, CFTimeInterval};
+use crate::filedescriptor::CFFileDescriptor;
+use crate::string::CFString;
pub type CFRunLoopMode = CFStringRef;
-
declare_TCFType!(CFRunLoop, CFRunLoopRef);
impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID);
impl_CFTypeDescription!(CFRunLoop);
+// https://github.com/servo/core-foundation-rs/issues/550
+unsafe impl Send for CFRunLoop {}
+unsafe impl Sync for CFRunLoop {}
+
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum CFRunLoopRunResult {
Finished = 1,
@@ -92,9 +95,7 @@ impl CFRunLoop {
}
pub fn contains_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) -> bool {
- unsafe {
- CFRunLoopContainsTimer(self.0, timer.0, mode) != 0
- }
+ unsafe { CFRunLoopContainsTimer(self.0, timer.0, mode) != 0 }
}
pub fn add_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
@@ -110,9 +111,7 @@ impl CFRunLoop {
}
pub fn contains_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) -> bool {
- unsafe {
- CFRunLoopContainsSource(self.0, source.0, mode) != 0
- }
+ unsafe { CFRunLoopContainsSource(self.0, source.0, mode) != 0 }
}
pub fn add_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
@@ -128,9 +127,7 @@ impl CFRunLoop {
}
pub fn contains_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) -> bool {
- unsafe {
- CFRunLoopContainsObserver(self.0, observer.0, mode) != 0
- }
+ unsafe { CFRunLoopContainsObserver(self.0, observer.0, mode) != 0 }
}
pub fn add_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
@@ -144,25 +141,41 @@ impl CFRunLoop {
CFRunLoopRemoveObserver(self.0, observer.0, mode);
}
}
-
}
-
declare_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef);
impl_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID);
impl CFRunLoopTimer {
- pub fn new(fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimer {
+ pub fn new(
+ fireDate: CFAbsoluteTime,
+ interval: CFTimeInterval,
+ flags: CFOptionFlags,
+ order: CFIndex,
+ callout: CFRunLoopTimerCallBack,
+ context: *mut CFRunLoopTimerContext,
+ ) -> CFRunLoopTimer {
unsafe {
- let timer_ref = CFRunLoopTimerCreate(kCFAllocatorDefault, fireDate, interval, flags, order, callout, context);
+ let timer_ref = CFRunLoopTimerCreate(
+ kCFAllocatorDefault,
+ fireDate,
+ interval,
+ flags,
+ order,
+ callout,
+ context,
+ );
TCFType::wrap_under_create_rule(timer_ref)
}
}
}
-
declare_TCFType!(CFRunLoopSource, CFRunLoopSourceRef);
-impl_TCFType!(CFRunLoopSource, CFRunLoopSourceRef, CFRunLoopSourceGetTypeID);
+impl_TCFType!(
+ CFRunLoopSource,
+ CFRunLoopSourceRef,
+ CFRunLoopSourceGetTypeID
+);
impl CFRunLoopSource {
pub fn from_file_descriptor(fd: &CFFileDescriptor, order: CFIndex) -> Option<CFRunLoopSource> {
@@ -171,15 +184,23 @@ impl CFRunLoopSource {
}
declare_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef);
-impl_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef, CFRunLoopObserverGetTypeID);
+impl_TCFType!(
+ CFRunLoopObserver,
+ CFRunLoopObserverRef,
+ CFRunLoopObserverGetTypeID
+);
#[cfg(test)]
mod test {
use super::*;
- use date::{CFDate, CFAbsoluteTime};
+ use crate::base::Boolean;
+ use crate::date::{CFAbsoluteTime, CFDate};
use std::mem;
use std::os::raw::c_void;
+ use std::ptr::null_mut;
use std::sync::mpsc;
+ use std::thread::spawn;
+ use std::time::Duration;
#[test]
fn wait_200_milliseconds() {
@@ -199,7 +220,8 @@ mod test {
copyDescription: None,
};
- let run_loop_timer = CFRunLoopTimer::new(now + 0.20f64, 0f64, 0, 0, timer_popped, &mut context);
+ let run_loop_timer =
+ CFRunLoopTimer::new(now + 0.20f64, 0f64, 0, 0, timer_popped, &mut context);
unsafe {
run_loop.add_timer(&run_loop_timer, kCFRunLoopDefaultMode);
}
@@ -221,4 +243,62 @@ mod test {
let _ = unsafe { (*info).elapsed_tx.send(elapsed) };
CFRunLoop::get_current().stop();
}
+
+ extern "C" fn observe(_: CFRunLoopObserverRef, _: CFRunLoopActivity, context: *mut c_void) {
+ let tx: &mpsc::Sender<CFRunLoop> = unsafe { &*(context as *const _) };
+ let _ = tx.send(CFRunLoop::get_current());
+ }
+
+ extern "C" fn observe_timer_popped(_: CFRunLoopTimerRef, _: *mut c_void) {
+ panic!("timer popped unexpectedly");
+ }
+
+ #[test]
+ fn observe_runloop() {
+ let (tx, rx) = mpsc::channel();
+ spawn(move || {
+ let mut context = CFRunLoopObserverContext {
+ version: 0,
+ info: &tx as *const _ as *mut c_void,
+ retain: None,
+ release: None,
+ copyDescription: None,
+ };
+
+ let observer = unsafe {
+ CFRunLoopObserver::wrap_under_create_rule(CFRunLoopObserverCreate(
+ kCFAllocatorDefault,
+ kCFRunLoopEntry,
+ false as Boolean,
+ 0,
+ observe,
+ &mut context,
+ ))
+ };
+
+ let runloop = CFRunLoop::get_current();
+ runloop.add_observer(&observer, unsafe { kCFRunLoopDefaultMode });
+
+ let timer = CFRunLoopTimer::new(
+ CFDate::now().abs_time() + 1f64,
+ 0f64,
+ 0,
+ 0,
+ observe_timer_popped,
+ null_mut(),
+ );
+ runloop.add_timer(&timer, unsafe { kCFRunLoopDefaultMode });
+
+ let result = unsafe {
+ CFRunLoop::run_in_mode(kCFRunLoopDefaultMode, Duration::from_secs(10), false)
+ };
+
+ assert_eq!(result, CFRunLoopRunResult::Stopped);
+
+ drop(tx);
+ });
+
+ let runloop: CFRunLoop = rx.recv().unwrap();
+ runloop.stop();
+ }
}
diff --git a/third_party/rust/core-foundation/src/set.rs b/third_party/rust/core-foundation/src/set.rs
index eb1d357a03..641202de8d 100644
--- a/third_party/rust/core-foundation/src/set.rs
+++ b/third_party/rust/core-foundation/src/set.rs
@@ -9,13 +9,13 @@
//! An immutable bag of elements.
+use core_foundation_sys::base::{kCFAllocatorDefault, CFRelease, CFTypeRef};
pub use core_foundation_sys::set::*;
-use core_foundation_sys::base::{CFTypeRef, CFRelease, kCFAllocatorDefault};
-use base::{CFIndexConvertible, TCFType};
+use crate::base::{CFIndexConvertible, TCFType};
-use std::os::raw::c_void;
use std::marker::PhantomData;
+use std::os::raw::c_void;
/// An immutable bag of elements.
pub struct CFSet<T = *const c_void>(CFSetRef, PhantomData<T>);
@@ -31,23 +31,31 @@ impl_CFTypeDescription!(CFSet);
impl CFSet {
/// Creates a new set from a list of `CFType` instances.
- pub fn from_slice<T>(elems: &[T]) -> CFSet<T> where T: TCFType {
+ pub fn from_slice<T>(elems: &[T]) -> CFSet<T>
+ where
+ T: TCFType,
+ {
unsafe {
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
- let set_ref = CFSetCreate(kCFAllocatorDefault,
- elems.as_ptr(),
- elems.len().to_CFIndex(),
- &kCFTypeSetCallBacks);
+ let set_ref = CFSetCreate(
+ kCFAllocatorDefault,
+ elems.as_ptr(),
+ elems.len().to_CFIndex(),
+ &kCFTypeSetCallBacks,
+ );
TCFType::wrap_under_create_rule(set_ref)
}
}
}
impl<T> CFSet<T> {
- /// Get the number of elements in the CFSet
+ /// Get the number of elements in the `CFSet`.
pub fn len(&self) -> usize {
- unsafe {
- CFSetGetCount(self.0) as usize
- }
+ unsafe { CFSetGetCount(self.0) as usize }
+ }
+
+ /// Returns `true` if the set contains no elements.
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
}
}
diff --git a/third_party/rust/core-foundation/src/string.rs b/third_party/rust/core-foundation/src/string.rs
index 3f5994bc5a..3358bab552 100644
--- a/third_party/rust/core-foundation/src/string.rs
+++ b/third_party/rust/core-foundation/src/string.rs
@@ -11,18 +11,17 @@
pub use core_foundation_sys::string::*;
-use base::{CFIndexConvertible, TCFType};
+use crate::base::{CFIndexConvertible, TCFType};
-use core_foundation_sys::base::{Boolean, CFIndex, CFRange};
use core_foundation_sys::base::{kCFAllocatorDefault, kCFAllocatorNull};
+use core_foundation_sys::base::{Boolean, CFIndex, CFRange};
use std::borrow::Cow;
+use std::ffi::CStr;
use std::fmt;
-use std::str::{self, FromStr};
use std::ptr;
-use std::ffi::CStr;
-
+use std::str::{self, FromStr};
-declare_TCFType!{
+declare_TCFType! {
/// An immutable string in one of a variety of encodings.
CFString, CFStringRef
}
@@ -31,7 +30,7 @@ impl_TCFType!(CFString, CFStringRef, CFStringGetTypeID);
impl FromStr for CFString {
type Err = ();
- /// See also CFString::new for a variant of this which does not return a Result
+ /// See also [`CFString::new()`] for a variant of this which does not return a `Result`.
#[inline]
fn from_str(string: &str) -> Result<CFString, ()> {
Ok(CFString::new(string))
@@ -58,27 +57,37 @@ impl<'a> From<&'a CFString> for Cow<'a, str> {
// First, ask how big the buffer ought to be.
let mut bytes_required: CFIndex = 0;
- CFStringGetBytes(cf_str.0,
- CFRange { location: 0, length: char_len },
- kCFStringEncodingUTF8,
- 0,
- false as Boolean,
- ptr::null_mut(),
- 0,
- &mut bytes_required);
+ CFStringGetBytes(
+ cf_str.0,
+ CFRange {
+ location: 0,
+ length: char_len,
+ },
+ kCFStringEncodingUTF8,
+ 0,
+ false as Boolean,
+ ptr::null_mut(),
+ 0,
+ &mut bytes_required,
+ );
// Then, allocate the buffer and actually copy.
let mut buffer = vec![b'\x00'; bytes_required as usize];
let mut bytes_used: CFIndex = 0;
- let chars_written = CFStringGetBytes(cf_str.0,
- CFRange { location: 0, length: char_len },
- kCFStringEncodingUTF8,
- 0,
- false as Boolean,
- buffer.as_mut_ptr(),
- buffer.len().to_CFIndex(),
- &mut bytes_used);
+ let chars_written = CFStringGetBytes(
+ cf_str.0,
+ CFRange {
+ location: 0,
+ length: char_len,
+ },
+ kCFStringEncodingUTF8,
+ 0,
+ false as Boolean,
+ buffer.as_mut_ptr(),
+ buffer.len().to_CFIndex(),
+ &mut bytes_used,
+ );
assert_eq!(chars_written, char_len);
// This is dangerous; we over-allocate and null-terminate the string (during
@@ -102,17 +111,18 @@ impl fmt::Debug for CFString {
}
}
-
impl CFString {
/// Creates a new `CFString` instance from a Rust string.
#[inline]
pub fn new(string: &str) -> CFString {
unsafe {
- let string_ref = CFStringCreateWithBytes(kCFAllocatorDefault,
- string.as_ptr(),
- string.len().to_CFIndex(),
- kCFStringEncodingUTF8,
- false as Boolean);
+ let string_ref = CFStringCreateWithBytes(
+ kCFAllocatorDefault,
+ string.as_ptr(),
+ string.len().to_CFIndex(),
+ kCFStringEncodingUTF8,
+ false as Boolean,
+ );
CFString::wrap_under_create_rule(string_ref)
}
}
@@ -122,12 +132,14 @@ impl CFString {
#[inline]
pub fn from_static_string(string: &'static str) -> CFString {
unsafe {
- let string_ref = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
- string.as_ptr(),
- string.len().to_CFIndex(),
- kCFStringEncodingUTF8,
- false as Boolean,
- kCFAllocatorNull);
+ let string_ref = CFStringCreateWithBytesNoCopy(
+ kCFAllocatorDefault,
+ string.as_ptr(),
+ string.len().to_CFIndex(),
+ kCFStringEncodingUTF8,
+ false as Boolean,
+ kCFAllocatorNull,
+ );
TCFType::wrap_under_create_rule(string_ref)
}
}
@@ -135,21 +147,21 @@ impl CFString {
/// Returns the number of characters in the string.
#[inline]
pub fn char_len(&self) -> CFIndex {
- unsafe {
- CFStringGetLength(self.0)
- }
+ unsafe { CFStringGetLength(self.0) }
}
}
impl<'a> PartialEq<&'a str> for CFString {
fn eq(&self, other: &&str) -> bool {
unsafe {
- let temp = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
- other.as_ptr(),
- other.len().to_CFIndex(),
- kCFStringEncodingUTF8,
- false as Boolean,
- kCFAllocatorNull);
+ let temp = CFStringCreateWithBytesNoCopy(
+ kCFAllocatorDefault,
+ other.as_ptr(),
+ other.len().to_CFIndex(),
+ kCFStringEncodingUTF8,
+ false as Boolean,
+ kCFAllocatorNull,
+ );
self.eq(&CFString::wrap_under_create_rule(temp))
}
}
diff --git a/third_party/rust/core-foundation/src/timezone.rs b/third_party/rust/core-foundation/src/timezone.rs
index a8bb2ed1d2..46123dcc22 100644
--- a/third_party/rust/core-foundation/src/timezone.rs
+++ b/third_party/rust/core-foundation/src/timezone.rs
@@ -9,18 +9,17 @@
//! Core Foundation time zone objects.
-pub use core_foundation_sys::timezone::*;
use core_foundation_sys::base::kCFAllocatorDefault;
+pub use core_foundation_sys::timezone::*;
-use base::TCFType;
-use date::{CFDate, CFTimeInterval};
-use string::CFString;
+use crate::base::TCFType;
+use crate::date::{CFDate, CFTimeInterval};
+use crate::string::CFString;
#[cfg(feature = "with-chrono")]
use chrono::{FixedOffset, NaiveDateTime};
-
-declare_TCFType!{
+declare_TCFType! {
/// A time zone.
CFTimeZone, CFTimeZoneRef
}
@@ -54,9 +53,7 @@ impl CFTimeZone {
}
pub fn seconds_from_gmt(&self, date: CFDate) -> CFTimeInterval {
- unsafe {
- CFTimeZoneGetSecondsFromGMT(self.0, date.abs_time())
- }
+ unsafe { CFTimeZoneGetSecondsFromGMT(self.0, date.abs_time()) }
}
#[cfg(feature = "with-chrono")]
@@ -70,12 +67,10 @@ impl CFTimeZone {
CFTimeZone::new(offset.local_minus_utc() as f64)
}
- /// The timezone database ID that identifies the time zone. E.g. "America/Los_Angeles" or
- /// "Europe/Paris".
+ /// The timezone database ID that identifies the time zone. E.g. `"America/Los_Angeles" `or
+ /// `"Europe/Paris"`.
pub fn name(&self) -> CFString {
- unsafe {
- CFString::wrap_under_get_rule(CFTimeZoneGetName(self.0))
- }
+ unsafe { CFString::wrap_under_get_rule(CFTimeZoneGetName(self.0)) }
}
}
@@ -84,7 +79,7 @@ mod test {
use super::CFTimeZone;
#[cfg(feature = "with-chrono")]
- use chrono::{NaiveDateTime, FixedOffset};
+ use chrono::{FixedOffset, NaiveDateTime};
#[test]
fn timezone_comparison() {
diff --git a/third_party/rust/core-foundation/src/url.rs b/third_party/rust/core-foundation/src/url.rs
index 064dd7b5e0..b929844385 100644
--- a/third_party/rust/core-foundation/src/url.rs
+++ b/third_party/rust/core-foundation/src/url.rs
@@ -11,21 +11,20 @@
pub use core_foundation_sys::url::*;
-use base::{TCFType, CFIndex};
-use string::{CFString};
+use crate::base::{CFIndex, TCFType};
+use crate::string::CFString;
use core_foundation_sys::base::{kCFAllocatorDefault, Boolean};
use std::fmt;
-use std::ptr;
use std::path::{Path, PathBuf};
+use std::ptr;
use libc::{c_char, strlen, PATH_MAX};
#[cfg(unix)]
-use std::os::unix::ffi::OsStrExt;
-#[cfg(unix)]
use std::ffi::OsStr;
-
+#[cfg(unix)]
+use std::os::unix::ffi::OsStrExt;
declare_TCFType!(CFURL, CFURLRef);
impl_TCFType!(CFURL, CFURLRef, CFURLGetTypeID);
@@ -35,7 +34,7 @@ impl fmt::Debug for CFURL {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unsafe {
let string: CFString = TCFType::wrap_under_get_rule(CFURLGetString(self.0));
- write!(f, "{}", string.to_string())
+ write!(f, "{}", string)
}
}
}
@@ -58,7 +57,12 @@ impl CFURL {
}
unsafe {
- let url_ref = CFURLCreateFromFileSystemRepresentation(ptr::null_mut(), path_bytes.as_ptr(), path_bytes.len() as CFIndex, isDirectory as u8);
+ let url_ref = CFURLCreateFromFileSystemRepresentation(
+ ptr::null_mut(),
+ path_bytes.as_ptr(),
+ path_bytes.len() as CFIndex,
+ isDirectory as u8,
+ );
if url_ref.is_null() {
return None;
}
@@ -66,9 +70,18 @@ impl CFURL {
}
}
- pub fn from_file_system_path(filePath: CFString, pathStyle: CFURLPathStyle, isDirectory: bool) -> CFURL {
+ pub fn from_file_system_path(
+ filePath: CFString,
+ pathStyle: CFURLPathStyle,
+ isDirectory: bool,
+ ) -> CFURL {
unsafe {
- let url_ref = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath.as_concrete_TypeRef(), pathStyle, isDirectory as u8);
+ let url_ref = CFURLCreateWithFileSystemPath(
+ kCFAllocatorDefault,
+ filePath.as_concrete_TypeRef(),
+ pathStyle,
+ isDirectory as u8,
+ );
TCFType::wrap_under_create_rule(url_ref)
}
}
@@ -78,7 +91,12 @@ impl CFURL {
// implementing this on Windows is more complicated because of the different OsStr representation
unsafe {
let mut buf = [0u8; PATH_MAX as usize];
- let result = CFURLGetFileSystemRepresentation(self.0, true as Boolean, buf.as_mut_ptr(), buf.len() as CFIndex);
+ let result = CFURLGetFileSystemRepresentation(
+ self.0,
+ true as Boolean,
+ buf.as_mut_ptr(),
+ buf.len() as CFIndex,
+ );
if result == false as Boolean {
return None;
}
@@ -89,21 +107,20 @@ impl CFURL {
}
pub fn get_string(&self) -> CFString {
- unsafe {
- TCFType::wrap_under_get_rule(CFURLGetString(self.0))
- }
+ unsafe { TCFType::wrap_under_get_rule(CFURLGetString(self.0)) }
}
pub fn get_file_system_path(&self, pathStyle: CFURLPathStyle) -> CFString {
unsafe {
- TCFType::wrap_under_create_rule(CFURLCopyFileSystemPath(self.as_concrete_TypeRef(), pathStyle))
+ TCFType::wrap_under_create_rule(CFURLCopyFileSystemPath(
+ self.as_concrete_TypeRef(),
+ pathStyle,
+ ))
}
}
pub fn absolute(&self) -> CFURL {
- unsafe {
- TCFType::wrap_under_create_rule(CFURLCopyAbsoluteURL(self.as_concrete_TypeRef()))
- }
+ unsafe { TCFType::wrap_under_create_rule(CFURLCopyAbsoluteURL(self.as_concrete_TypeRef())) }
}
}
@@ -138,18 +155,30 @@ fn absolute_file_url() {
let cfstr_file = CFString::from_static_string(file);
let cfurl_base = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
let cfurl_relative: CFURL = unsafe {
- let url_ref = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault,
+ let url_ref = CFURLCreateWithFileSystemPathRelativeToBase(
+ kCFAllocatorDefault,
cfstr_file.as_concrete_TypeRef(),
kCFURLPOSIXPathStyle,
false as u8,
- cfurl_base.as_concrete_TypeRef());
+ cfurl_base.as_concrete_TypeRef(),
+ );
TCFType::wrap_under_create_rule(url_ref)
};
let mut absolute_path = PathBuf::from(path);
absolute_path.push(file);
- assert_eq!(cfurl_relative.get_file_system_path(kCFURLPOSIXPathStyle).to_string(), file);
- assert_eq!(cfurl_relative.absolute().get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
- absolute_path.to_str().unwrap());
+ assert_eq!(
+ cfurl_relative
+ .get_file_system_path(kCFURLPOSIXPathStyle)
+ .to_string(),
+ file
+ );
+ assert_eq!(
+ cfurl_relative
+ .absolute()
+ .get_file_system_path(kCFURLPOSIXPathStyle)
+ .to_string(),
+ absolute_path.to_str().unwrap()
+ );
}
diff --git a/third_party/rust/core-foundation/src/uuid.rs b/third_party/rust/core-foundation/src/uuid.rs
index 6be734dabc..834a6dd9d2 100644
--- a/third_party/rust/core-foundation/src/uuid.rs
+++ b/third_party/rust/core-foundation/src/uuid.rs
@@ -12,15 +12,14 @@
#[cfg(feature = "with-uuid")]
extern crate uuid;
-pub use core_foundation_sys::uuid::*;
use core_foundation_sys::base::kCFAllocatorDefault;
+pub use core_foundation_sys::uuid::*;
-use base::TCFType;
+use crate::base::TCFType;
#[cfg(feature = "with-uuid")]
use self::uuid::Uuid;
-
declare_TCFType! {
/// A UUID.
CFUUID, CFUUIDRef
@@ -45,28 +44,12 @@ impl Default for CFUUID {
}
#[cfg(feature = "with-uuid")]
-impl Into<Uuid> for CFUUID {
- fn into(self) -> Uuid {
- let b = unsafe {
- CFUUIDGetUUIDBytes(self.0)
- };
+impl From<CFUUID> for Uuid {
+ fn from(val: CFUUID) -> Self {
+ let b = unsafe { CFUUIDGetUUIDBytes(val.0) };
let bytes = [
- b.byte0,
- b.byte1,
- b.byte2,
- b.byte3,
- b.byte4,
- b.byte5,
- b.byte6,
- b.byte7,
- b.byte8,
- b.byte9,
- b.byte10,
- b.byte11,
- b.byte12,
- b.byte13,
- b.byte14,
- b.byte15,
+ b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7, b.byte8,
+ b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15,
];
Uuid::from_bytes(&bytes).unwrap()
}
@@ -101,7 +84,6 @@ impl From<Uuid> for CFUUID {
}
}
-
#[cfg(test)]
#[cfg(feature = "with-uuid")]
mod test {
diff --git a/third_party/rust/core-graphics-types/.cargo-checksum.json b/third_party/rust/core-graphics-types/.cargo-checksum.json
index cc00991ad2..69613fe009 100644
--- a/third_party/rust/core-graphics-types/.cargo-checksum.json
+++ b/third_party/rust/core-graphics-types/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"cac07dfd7a2fcbb169a0c471a8a139ade8da91f92b7fbc198f3f2185d9c94d16","src/base.rs":"561db031cc746eab35a10fe72e10c314615b11e13cd48366fcdb2223196308a7","src/geometry.rs":"4ed03b07a4c5ba0f090689d31ef6eab8ec5b8f6eb7fb4e04fdf65e5ad8cd70ea","src/lib.rs":"31700ac9508fd32005bafd1c12a86a6803d198e9b1a71166a7391e642c091cd1"},"package":"2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"} \ No newline at end of file
+{"files":{"Cargo.toml":"a49bc6534c1e5be53c72f3016ff7f64509a5570868dc943178c75b541fa839da","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/base.rs":"7e4e9c23f874443d0095f82d2786dc65b6b6635cbe8b3514999be80445a92bc8","src/geometry.rs":"7eda026c3db65cac836531565f85120132ab1ec84f76467a68ff040b8dc437c4","src/lib.rs":"42baf24c75dc6627bd4ca8481c503febf54e7eafa50cce40804042ddc74881c8"},"package":"45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"} \ No newline at end of file
diff --git a/third_party/rust/core-graphics-types/Cargo.toml b/third_party/rust/core-graphics-types/Cargo.toml
index 365717dfb4..2c28237424 100644
--- a/third_party/rust/core-graphics-types/Cargo.toml
+++ b/third_party/rust/core-graphics-types/Cargo.toml
@@ -10,8 +10,9 @@
# See Cargo.toml.orig for the original contents.
[package]
+edition = "2018"
name = "core-graphics-types"
-version = "0.1.2"
+version = "0.1.3"
authors = ["The Servo Project Developers"]
description = "Bindings for some fundamental Core Graphics types"
homepage = "https://github.com/servo/core-foundation-rs"
@@ -25,7 +26,12 @@ default-target = "x86_64-apple-darwin"
version = "1.0"
[dependencies.core-foundation]
-version = "0.9"
+version = "0.9.4"
+default-features = false
[dependencies.libc]
version = "0.2"
+
+[features]
+default = ["link"]
+link = ["core-foundation/link"]
diff --git a/third_party/rust/core-graphics-types/LICENSE-APACHE b/third_party/rust/core-graphics-types/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/core-graphics-types/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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
+
+ http://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.
diff --git a/third_party/rust/core-graphics-types/LICENSE-MIT b/third_party/rust/core-graphics-types/LICENSE-MIT
new file mode 100644
index 0000000000..807526f57f
--- /dev/null
+++ b/third_party/rust/core-graphics-types/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2012-2013 Mozilla Foundation
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/core-graphics-types/src/base.rs b/third_party/rust/core-graphics-types/src/base.rs
index 03a85f1559..4d87233199 100644
--- a/third_party/rust/core-graphics-types/src/base.rs
+++ b/third_party/rust/core-graphics-types/src/base.rs
@@ -14,9 +14,7 @@
use libc;
-#[cfg(any(target_arch = "x86",
- target_arch = "arm",
- target_arch = "aarch64"))]
+#[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "aarch64"))]
pub type boolean_t = libc::c_int;
#[cfg(target_arch = "x86_64")]
pub type boolean_t = libc::c_uint;
diff --git a/third_party/rust/core-graphics-types/src/geometry.rs b/third_party/rust/core-graphics-types/src/geometry.rs
index 586075270c..b585afdcbd 100644
--- a/third_party/rust/core-graphics-types/src/geometry.rs
+++ b/third_party/rust/core-graphics-types/src/geometry.rs
@@ -7,14 +7,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use base::CGFloat;
+use crate::base::CGFloat;
use core_foundation::base::TCFType;
use core_foundation::dictionary::CFDictionary;
-pub const CG_ZERO_POINT: CGPoint = CGPoint {
- x: 0.0,
- y: 0.0,
-};
+pub const CG_ZERO_POINT: CGPoint = CGPoint { x: 0.0, y: 0.0 };
pub const CG_ZERO_SIZE: CGSize = CGSize {
width: 0.0,
@@ -27,9 +24,12 @@ pub const CG_ZERO_RECT: CGRect = CGRect {
};
pub const CG_AFFINE_TRANSFORM_IDENTITY: CGAffineTransform = CGAffineTransform {
- a: 1.0, b: 0.0,
- c: 0.0, d: 1.0,
- tx: 0.0, ty: 0.0,
+ a: 1.0,
+ b: 0.0,
+ c: 0.0,
+ d: 1.0,
+ tx: 0.0,
+ ty: 0.0,
};
#[repr(C)]
@@ -42,17 +42,12 @@ pub struct CGSize {
impl CGSize {
#[inline]
pub fn new(width: CGFloat, height: CGFloat) -> CGSize {
- CGSize {
- width: width,
- height: height,
- }
+ CGSize { width, height }
}
#[inline]
pub fn apply_transform(&self, t: &CGAffineTransform) -> CGSize {
- unsafe {
- ffi::CGSizeApplyAffineTransform(*self, *t)
- }
+ unsafe { ffi::CGSizeApplyAffineTransform(*self, *t) }
}
}
@@ -66,17 +61,12 @@ pub struct CGPoint {
impl CGPoint {
#[inline]
pub fn new(x: CGFloat, y: CGFloat) -> CGPoint {
- CGPoint {
- x: x,
- y: y,
- }
+ CGPoint { x, y }
}
#[inline]
pub fn apply_transform(&self, t: &CGAffineTransform) -> CGPoint {
- unsafe {
- ffi::CGPointApplyAffineTransform(*self, *t)
- }
+ unsafe { ffi::CGPointApplyAffineTransform(*self, *t) }
}
}
@@ -84,7 +74,7 @@ impl CGPoint {
#[derive(Clone, Copy, Debug, Default)]
pub struct CGRect {
pub origin: CGPoint,
- pub size: CGSize
+ pub size: CGSize,
}
impl CGRect {
@@ -98,9 +88,7 @@ impl CGRect {
#[inline]
pub fn inset(&self, size: &CGSize) -> CGRect {
- unsafe {
- ffi::CGRectInset(*self, size.width, size.height)
- }
+ unsafe { ffi::CGRectInset(*self, size.width, size.height) }
}
#[inline]
@@ -134,14 +122,12 @@ impl CGRect {
#[inline]
pub fn apply_transform(&self, t: &CGAffineTransform) -> CGRect {
- unsafe {
- ffi::CGRectApplyAffineTransform(*self, *t)
- }
+ unsafe { ffi::CGRectApplyAffineTransform(*self, *t) }
}
#[inline]
pub fn contains(&self, point: &CGPoint) -> bool {
- unsafe { ffi::CGRectContainsPoint(*self,*point) == 1 }
+ unsafe { ffi::CGRectContainsPoint(*self, *point) == 1 }
}
}
@@ -171,22 +157,22 @@ impl CGAffineTransform {
#[inline]
pub fn invert(&self) -> CGAffineTransform {
- unsafe {
- ffi::CGAffineTransformInvert(*self)
- }
+ unsafe { ffi::CGAffineTransformInvert(*self) }
}
}
mod ffi {
- use base::{CGFloat, boolean_t};
- use geometry::{CGAffineTransform, CGPoint, CGRect, CGSize};
+ use crate::base::{boolean_t, CGFloat};
+ use crate::geometry::{CGAffineTransform, CGPoint, CGRect, CGSize};
use core_foundation::dictionary::CFDictionaryRef;
- #[link(name = "CoreGraphics", kind = "framework")]
- extern {
+ #[cfg_attr(feature = "link", link(name = "CoreGraphics", kind = "framework"))]
+ extern "C" {
pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect;
- pub fn CGRectMakeWithDictionaryRepresentation(dict: CFDictionaryRef,
- rect: *mut CGRect) -> boolean_t;
+ pub fn CGRectMakeWithDictionaryRepresentation(
+ dict: CFDictionaryRef,
+ rect: *mut CGRect,
+ ) -> boolean_t;
pub fn CGRectIsEmpty(rect: CGRect) -> boolean_t;
pub fn CGRectIntersectsRect(rect1: CGRect, rect2: CGRect) -> boolean_t;
@@ -196,7 +182,6 @@ mod ffi {
pub fn CGRectApplyAffineTransform(rect: CGRect, t: CGAffineTransform) -> CGRect;
pub fn CGSizeApplyAffineTransform(size: CGSize, t: CGAffineTransform) -> CGSize;
- pub fn CGRectContainsPoint(rect:CGRect, point: CGPoint) -> boolean_t;
+ pub fn CGRectContainsPoint(rect: CGRect, point: CGPoint) -> boolean_t;
}
}
-
diff --git a/third_party/rust/core-graphics-types/src/lib.rs b/third_party/rust/core-graphics-types/src/lib.rs
index f34bf01207..94a4eb9797 100644
--- a/third_party/rust/core-graphics-types/src/lib.rs
+++ b/third_party/rust/core-graphics-types/src/lib.rs
@@ -7,8 +7,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate libc;
extern crate core_foundation;
+extern crate libc;
pub mod base;
pub mod geometry;
diff --git a/third_party/rust/cssparser-macros/.cargo-checksum.json b/third_party/rust/cssparser-macros/.cargo-checksum.json
index 7d765b8aa1..d6f57235d1 100644
--- a/third_party/rust/cssparser-macros/.cargo-checksum.json
+++ b/third_party/rust/cssparser-macros/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"b3a51cde73d95cac878371677b7e3a847b8726b49ab61204682c691dc1b1b81c","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","lib.rs":"10e68d5a92a053ff498cb1caa8290e508f691e32b73222a5a4737ee9a4097ce2"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"d4a43ad31d5048cf19ee80ec38de90fa98b9b9902b97d61e4edc940246806295","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","lib.rs":"10e68d5a92a053ff498cb1caa8290e508f691e32b73222a5a4737ee9a4097ce2"},"package":"13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"} \ No newline at end of file
diff --git a/third_party/rust/cssparser-macros/Cargo.toml b/third_party/rust/cssparser-macros/Cargo.toml
index 0cafd289af..601ac6a3af 100644
--- a/third_party/rust/cssparser-macros/Cargo.toml
+++ b/third_party/rust/cssparser-macros/Cargo.toml
@@ -23,8 +23,8 @@ repository = "https://github.com/servo/rust-cssparser"
path = "lib.rs"
proc-macro = true
-[dependencies]
-quote = "1"
+[dependencies.quote]
+version = "1"
[dependencies.syn]
version = "2"
diff --git a/third_party/rust/cssparser/.cargo-checksum.json b/third_party/rust/cssparser/.cargo-checksum.json
index 2c42f1420e..c4e19e50be 100644
--- a/third_party/rust/cssparser/.cargo-checksum.json
+++ b/third_party/rust/cssparser/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".github/workflows/main.yml":"9fb6be1c14d9107ac4613e660d111d469722839ddf8a59e781c54a3607676e9e","Cargo.toml":"2c12f0dd7e94af4ca4ae29a741d2de2447c705f83fec0ab601b3548d2b7c64f4","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"53a6805edd80f642473514cb93f1f4197e17a911d66a2dfcefc3dc5e82bac206","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"eedf03d8ba8ca54a744617fdd945c80cbae73f99b6dff06f43a39764a93a3ac5","src/cow_rc_str.rs":"4d172d3633ef55af815784fbaee03cbcf85796a380765a0af09bbb6ca5b6fbab","src/from_bytes.rs":"b1cf15c4e975523fef46b575598737a39f3c63e5ce0b2bfd6ec627c69c6ea54a","src/lib.rs":"13be989c091fb59ecab3e855e76e7c3468f465f63e7391303fa51f251441916a","src/macros.rs":"c6e06fd014ee8c6212c72928e8b474fb1cd13a0b604055e9943ed05179a0e63b","src/nth.rs":"2fc26915f0a36cb22ac45dd9a7ecbdc64c327b2ec135370258ec3db9f9985460","src/parser.rs":"51d86df7f788da4ee6bdef8e92474bf118ac26f8954f82a14d11f1f578b6998e","src/rules_and_declarations.rs":"180c797c75a1f7298c4e47dc819cd5f8c8d911d20492eac88f10d910fd5258d4","src/serializer.rs":"b3d59a3b72a67f7bcd0f949497445d756f584661424682d03a3a1030ed4862b1","src/size_of_tests.rs":"da0cbcaa304f7800e9122e2bce0a11d42a70b9012e646a723cb23ee74a6b858c","src/tests.rs":"aa67c41be76b2a944d4d6dd162c3e8a77be1f877e94ac62e8f065adb5407a669","src/tokenizer.rs":"1f690582d4cdba930a379e5808d54f4085e3c6b60345e55c1141df7e263c722a","src/unicode_range.rs":"20d96f06fbb73921e308cc340c9fe065e27f19843005689fb259007a6a372bcc"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"f93c7e90c8e06349e2c3faee56f48c9121ab0a1571db502143c8c50df75c98a4","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"95e81e8f22062ba196eb8229a749327c063620ccf31ce1dd01b7ea0529840280","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"5edc02f840f6837580e800c860e91c8ea28c77f0dd157bffdf648827c476d01c","src/cow_rc_str.rs":"9bb6f4ca76ec51bcf85ec3ff23b80c76a0113df0856a60f34fbcd43e869a19ad","src/from_bytes.rs":"b1cf15c4e975523fef46b575598737a39f3c63e5ce0b2bfd6ec627c69c6ea54a","src/lib.rs":"13be989c091fb59ecab3e855e76e7c3468f465f63e7391303fa51f251441916a","src/macros.rs":"64ad9e506e5cea52767a5177779ac4a1cbdac1b2188abaa1291e9feb8f1653bf","src/nth.rs":"972cc94275126e747c95621e8c5f56ce5d869924e60bb0dc990f4c98f3d74890","src/parser.rs":"beb4327ada3ae9f0f6cef29a88ef6d210b9942dc459369f7ffc4529a5f413f47","src/rules_and_declarations.rs":"4b16d61e017de50c81ac3aa7ff78eeb186af1e233bbd1e93b31c2c3aff944ddc","src/serializer.rs":"807ae7f49abd6a0a83172321ec95624de2266f6caa687b014c58e9f9660b629a","src/size_of_tests.rs":"da0cbcaa304f7800e9122e2bce0a11d42a70b9012e646a723cb23ee74a6b858c","src/tests.rs":"00c370284ff862faec40e580507593dad51bff608360f8562634fb6948eee2f0","src/tokenizer.rs":"99977cf09f2e8d1b45fe98a4db2eda89defd64cb99c948885c0cec2122951b41","src/unicode_range.rs":"db0217629bf70dafef5cc93a9615d54dd0f2a5bfd19d31e1d06bf4c7b006dd1e"},"package":"b7c66d1cd8ed61bf80b38432613a7a2f09401ab8d0501110655f8b341484a3e3"} \ No newline at end of file
diff --git a/third_party/rust/cssparser/.github/workflows/main.yml b/third_party/rust/cssparser/.github/workflows/main.yml
deleted file mode 100644
index 0d3c0229fb..0000000000
--- a/third_party/rust/cssparser/.github/workflows/main.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-name: CI
-
-on:
- push:
- branches: [master]
- pull_request:
- workflow_dispatch:
- merge_group:
- types: [checks_requested]
-
-jobs:
- linux-ci:
- name: Linux
- runs-on: ubuntu-latest
- strategy:
- matrix:
- toolchain:
- - nightly
- - beta
- - stable
- - 1.63.0
- features:
- -
- - --features dummy_match_byte
- include:
- - toolchain: nightly
- features: --features bench
- - toolchain: nightly
- features: --features bench,dummy_match_byte
- steps:
- - uses: actions/checkout@v2
-
- - name: Install toolchain
- uses: actions-rs/toolchain@v1
- with:
- profile: minimal
- toolchain: ${{ matrix.toolchain }}
- override: true
- components: ${{ matrix.toolchain == 'nightly' && 'miri,rust-src' || '' }}
-
- - name: Cargo build
- run: cargo build ${{ matrix.features }}
-
- - name: Cargo doc
- run: cargo doc ${{ matrix.features }}
-
- - name: Cargo test
- run: cargo test ${{ matrix.features }}
-
- - name: macros build
- run: cargo build
- working-directory: macros
-
- - name: Color build
- run: cargo build
- working-directory: color
-
- - name: Color test
- run: cargo test
- working-directory: color
-
- - name: Cargo miri test
- if: "matrix.toolchain == 'nightly'"
- run: cargo miri test --features skip_long_tests ${{ matrix.features }}
-
- build_result:
- name: Result
- runs-on: ubuntu-latest
- needs:
- - "linux-ci"
-
- steps:
- - name: Mark the job as successful
- run: exit 0
- if: success()
- - name: Mark the job as unsuccessful
- run: exit 1
- if: "!success()"
diff --git a/third_party/rust/cssparser/Cargo.toml b/third_party/rust/cssparser/Cargo.toml
index 28312541ae..bceceea9d2 100644
--- a/third_party/rust/cssparser/Cargo.toml
+++ b/third_party/rust/cssparser/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.63"
name = "cssparser"
-version = "0.33.0"
+version = "0.34.0"
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
exclude = [
"src/css-parsing-tests/**",
@@ -30,36 +30,41 @@ keywords = [
license = "MPL-2.0"
repository = "https://github.com/servo/rust-cssparser"
-[dependencies]
-dtoa-short = "0.3"
-itoa = "1.0"
-smallvec = "1.0"
+[profile.profiling]
+debug = 2
+inherits = "release"
[dependencies.cssparser-macros]
version = "0.6.1"
-path = "./macros"
+
+[dependencies.dtoa-short]
+version = "0.3"
+
+[dependencies.itoa]
+version = "1.0"
[dependencies.phf]
-version = ">=0.8,<=0.11"
+version = "0.11.2"
features = ["macros"]
[dependencies.serde]
version = "1.0"
+features = ["derive"]
optional = true
-[dev-dependencies]
-difference = "2.0"
-encoding_rs = "0.8"
-serde_json = "1.0"
+[dependencies.smallvec]
+version = "1.0"
+
+[dev-dependencies.difference]
+version = "2.0"
+
+[dev-dependencies.encoding_rs]
+version = "0.8"
+
+[dev-dependencies.serde_json]
+version = "1.0.25"
[features]
bench = []
dummy_match_byte = []
skip_long_tests = []
-
-[workspace]
-members = [
- ".",
- "./macros",
- "./color",
-]
diff --git a/third_party/rust/cssparser/README.md b/third_party/rust/cssparser/README.md
index 84d47d9e04..d9ca4ada84 100644
--- a/third_party/rust/cssparser/README.md
+++ b/third_party/rust/cssparser/README.md
@@ -3,7 +3,7 @@ rust-cssparser
[![Build Status](https://github.com/servo/rust-cssparser/actions/workflows/main.yml/badge.svg)](https://github.com/servo/rust-cssparser/actions)
-[Documentation](https://docs.rs/cssparser/)
+[Documentation](https://docs.rs/cssparser)
Rust implementation of
[CSS Syntax Module Level 3](https://drafts.csswg.org/css-syntax/)
@@ -53,5 +53,5 @@ Parsing CSS involves a series of steps:
It does however provide some helper functions to parse [CSS colors](src/color.rs)
and [An+B](src/nth.rs) (the argument to `:nth-child()` and related selectors.
- See [Servo’s `style` crate](https://github.com/servo/servo/tree/master/components/style)
+ See [Servo’s `style` crate](https://github.com/servo/stylo/tree/main/style)
for an example of a parser based on rust-cssparser.
diff --git a/third_party/rust/cssparser/src/color.rs b/third_party/rust/cssparser/src/color.rs
index d5f9a5c0e6..978936e01a 100644
--- a/third_party/rust/cssparser/src/color.rs
+++ b/third_party/rust/cssparser/src/color.rs
@@ -14,9 +14,8 @@
/// The opaque alpha value of 1.0.
pub const OPAQUE: f32 = 1.0;
-use crate::ToCss;
+use crate::{BasicParseError, Parser, ToCss, Token};
use std::fmt;
-use std::str::FromStr;
/// Clamp a 0..1 number to a 0..255 range to u8.
///
@@ -76,7 +75,9 @@ pub fn serialize_color_alpha(
/// A Predefined color space specified in:
/// <https://drafts.csswg.org/css-color-4/#predefined>
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, Eq, PartialEq, Debug)]
+#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
+#[cfg_attr(feature = "serde", serde(tag = "type"))]
pub enum PredefinedColorSpace {
/// <https://drafts.csswg.org/css-color-4/#predefined-sRGB>
Srgb,
@@ -97,36 +98,21 @@ pub enum PredefinedColorSpace {
}
impl PredefinedColorSpace {
- /// Returns the string value of the predefined color space.
- pub fn as_str(&self) -> &str {
- match self {
- PredefinedColorSpace::Srgb => "srgb",
- PredefinedColorSpace::SrgbLinear => "srgb-linear",
- PredefinedColorSpace::DisplayP3 => "display-p3",
- PredefinedColorSpace::A98Rgb => "a98-rgb",
- PredefinedColorSpace::ProphotoRgb => "prophoto-rgb",
- PredefinedColorSpace::Rec2020 => "rec2020",
- PredefinedColorSpace::XyzD50 => "xyz-d50",
- PredefinedColorSpace::XyzD65 => "xyz-d65",
- }
- }
-}
-
-impl FromStr for PredefinedColorSpace {
- type Err = ();
+ /// Parse a PredefinedColorSpace from the given input.
+ pub fn parse<'i>(input: &mut Parser<'i, '_>) -> Result<Self, BasicParseError<'i>> {
+ let location = input.current_source_location();
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- Ok(match_ignore_ascii_case! { s,
- "srgb" => PredefinedColorSpace::Srgb,
- "srgb-linear" => PredefinedColorSpace::SrgbLinear,
- "display-p3" => PredefinedColorSpace::DisplayP3,
- "a98-rgb" => PredefinedColorSpace::A98Rgb,
- "prophoto-rgb" => PredefinedColorSpace::ProphotoRgb,
- "rec2020" => PredefinedColorSpace::Rec2020,
- "xyz-d50" => PredefinedColorSpace::XyzD50,
- "xyz" | "xyz-d65" => PredefinedColorSpace::XyzD65,
-
- _ => return Err(()),
+ let ident = input.expect_ident()?;
+ Ok(match_ignore_ascii_case! { ident,
+ "srgb" => Self::Srgb,
+ "srgb-linear" => Self::SrgbLinear,
+ "display-p3" => Self::DisplayP3,
+ "a98-rgb" => Self::A98Rgb,
+ "prophoto-rgb" => Self::ProphotoRgb,
+ "rec2020" => Self::Rec2020,
+ "xyz-d50" => Self::XyzD50,
+ "xyz" | "xyz-d65" => Self::XyzD65,
+ _ => return Err(location.new_basic_unexpected_token_error(Token::Ident(ident.clone()))),
})
}
}
@@ -136,11 +122,21 @@ impl ToCss for PredefinedColorSpace {
where
W: fmt::Write,
{
- dest.write_str(self.as_str())
+ dest.write_str(match self {
+ Self::Srgb => "srgb",
+ Self::SrgbLinear => "srgb-linear",
+ Self::DisplayP3 => "display-p3",
+ Self::A98Rgb => "a98-rgb",
+ Self::ProphotoRgb => "prophoto-rgb",
+ Self::Rec2020 => "rec2020",
+ Self::XyzD50 => "xyz-d50",
+ Self::XyzD65 => "xyz-d65",
+ })
}
}
/// Parse a color hash, without the leading '#' character.
+#[allow(clippy::result_unit_err)]
#[inline]
pub fn parse_hash_color(value: &[u8]) -> Result<(u8, u8, u8, f32), ()> {
Ok(match value.len() {
@@ -328,6 +324,7 @@ ascii_case_insensitive_phf_map! {
/// Returns the named color with the given name.
/// <https://drafts.csswg.org/css-color-4/#typedef-named-color>
+#[allow(clippy::result_unit_err)]
#[inline]
pub fn parse_named_color(ident: &str) -> Result<(u8, u8, u8), ()> {
named_colors::get(ident).copied().ok_or(())
diff --git a/third_party/rust/cssparser/src/cow_rc_str.rs b/third_party/rust/cssparser/src/cow_rc_str.rs
index ecf14a0a75..2650848111 100644
--- a/third_party/rust/cssparser/src/cow_rc_str.rs
+++ b/third_party/rust/cssparser/src/cow_rc_str.rs
@@ -4,7 +4,7 @@
use std::borrow::{Borrow, Cow};
use std::rc::Rc;
-use std::{cmp, fmt, hash, marker, mem, ops, slice, str, ptr};
+use std::{cmp, fmt, hash, marker, mem, ops, ptr, slice, str};
/// A string that is either shared (heap-allocated and reference-counted) or borrowed.
///
@@ -23,9 +23,9 @@ pub struct CowRcStr<'a> {
phantom: marker::PhantomData<Result<&'a str, Rc<String>>>,
}
-fn _static_assert_same_size<'a>() {
+fn _static_assert_same_size() {
// "Instantiate" the generic function without calling it.
- let _ = mem::transmute::<CowRcStr<'a>, Option<CowRcStr<'a>>>;
+ let _ = mem::transmute::<CowRcStr<'_>, Option<CowRcStr<'_>>>;
}
impl<'a> From<Cow<'a, str>> for CowRcStr<'a> {
diff --git a/third_party/rust/cssparser/src/macros.rs b/third_party/rust/cssparser/src/macros.rs
index fc4b77a194..67d8365884 100644
--- a/third_party/rust/cssparser/src/macros.rs
+++ b/third_party/rust/cssparser/src/macros.rs
@@ -182,7 +182,7 @@ pub fn _cssparser_internal_to_lowercase<'a>(
let input_bytes =
unsafe { &*(input.as_bytes() as *const [u8] as *const [MaybeUninit<u8>]) };
- buffer.copy_from_slice(&*input_bytes);
+ buffer.copy_from_slice(input_bytes);
// Same as above re layout, plus these bytes have been initialized:
let buffer = unsafe { &mut *(buffer as *mut [MaybeUninit<u8>] as *mut [u8]) };
@@ -195,7 +195,7 @@ pub fn _cssparser_internal_to_lowercase<'a>(
}
Some(
- match input.bytes().position(|byte| matches!(byte, b'A'..=b'Z')) {
+ match input.bytes().position(|byte| byte.is_ascii_uppercase()) {
Some(first_uppercase) => make_ascii_lowercase(buffer, input, first_uppercase),
// common case: input is already lower-case
None => input,
diff --git a/third_party/rust/cssparser/src/nth.rs b/third_party/rust/cssparser/src/nth.rs
index 518de4d9b4..4fe5a6bc04 100644
--- a/third_party/rust/cssparser/src/nth.rs
+++ b/third_party/rust/cssparser/src/nth.rs
@@ -7,8 +7,8 @@ use super::{BasicParseError, Parser, ParserInput, Token};
/// Parse the *An+B* notation, as found in the `:nth-child()` selector.
/// The input is typically the arguments of a function,
/// in which case the caller needs to check if the arguments’ parser is exhausted.
-/// Return `Ok((A, B))`, or `Err(())` for a syntax error.
-pub fn parse_nth<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(i32, i32), BasicParseError<'i>> {
+/// Return `Ok((A, B))`, or an `Err(..)` for a syntax error.
+pub fn parse_nth<'i>(input: &mut Parser<'i, '_>) -> Result<(i32, i32), BasicParseError<'i>> {
match *input.next()? {
Token::Number {
int_value: Some(b), ..
@@ -22,7 +22,7 @@ pub fn parse_nth<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(i32, i32), Basic
unit,
"n" => Ok(parse_b(input, a)?),
"n-" => Ok(parse_signless_b(input, a, -1)?),
- _ => match parse_n_dash_digits(&*unit) {
+ _ => match parse_n_dash_digits(unit) {
Ok(b) => Ok((a, b)),
Err(()) => {
let unit = unit.clone();
@@ -40,8 +40,8 @@ pub fn parse_nth<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(i32, i32), Basic
"n-" => Ok(parse_signless_b(input, 1, -1)?),
"-n-" => Ok(parse_signless_b(input, -1, -1)?),
_ => {
- let (slice, a) = if value.starts_with("-") {
- (&value[1..], -1)
+ let (slice, a) = if let Some(stripped) = value.strip_prefix('-') {
+ (stripped, -1)
} else {
(&**value, 1)
};
@@ -81,7 +81,7 @@ pub fn parse_nth<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(i32, i32), Basic
}
}
-fn parse_b<'i, 't>(input: &mut Parser<'i, 't>, a: i32) -> Result<(i32, i32), BasicParseError<'i>> {
+fn parse_b<'i>(input: &mut Parser<'i, '_>, a: i32) -> Result<(i32, i32), BasicParseError<'i>> {
let start = input.state();
match input.next() {
Ok(&Token::Delim('+')) => parse_signless_b(input, a, 1),
@@ -98,8 +98,8 @@ fn parse_b<'i, 't>(input: &mut Parser<'i, 't>, a: i32) -> Result<(i32, i32), Bas
}
}
-fn parse_signless_b<'i, 't>(
- input: &mut Parser<'i, 't>,
+fn parse_signless_b<'i>(
+ input: &mut Parser<'i, '_>,
a: i32,
b_sign: i32,
) -> Result<(i32, i32), BasicParseError<'i>> {
@@ -118,7 +118,7 @@ fn parse_n_dash_digits(string: &str) -> Result<i32, ()> {
let bytes = string.as_bytes();
if bytes.len() >= 3
&& bytes[..2].eq_ignore_ascii_case(b"n-")
- && bytes[2..].iter().all(|&c| matches!(c, b'0'..=b'9'))
+ && bytes[2..].iter().all(|&c| c.is_ascii_digit())
{
Ok(parse_number_saturate(&string[1..]).unwrap()) // Include the minus sign
} else {
diff --git a/third_party/rust/cssparser/src/parser.rs b/third_party/rust/cssparser/src/parser.rs
index dd7777a2d8..dd35fc50ed 100644
--- a/third_party/rust/cssparser/src/parser.rs
+++ b/third_party/rust/cssparser/src/parser.rs
@@ -53,7 +53,7 @@ impl ParserState {
///
/// Would need to scan the whole {} block to find a semicolon, only for parsing getting restarted
/// as a qualified rule later.
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ParseUntilErrorBehavior {
/// Consume until we see the relevant delimiter or the end of the stream.
Consume,
@@ -116,18 +116,30 @@ impl<'i, T> From<BasicParseError<'i>> for ParseError<'i, T> {
impl SourceLocation {
/// Create a new BasicParseError at this location for an unexpected token
#[inline]
- pub fn new_basic_unexpected_token_error<'i>(self, token: Token<'i>) -> BasicParseError<'i> {
+ pub fn new_basic_unexpected_token_error(self, token: Token<'_>) -> BasicParseError<'_> {
+ self.new_basic_error(BasicParseErrorKind::UnexpectedToken(token))
+ }
+
+ /// Create a new BasicParseError at this location
+ #[inline]
+ pub fn new_basic_error(self, kind: BasicParseErrorKind<'_>) -> BasicParseError<'_> {
BasicParseError {
- kind: BasicParseErrorKind::UnexpectedToken(token),
+ kind,
location: self,
}
}
/// Create a new ParseError at this location for an unexpected token
#[inline]
- pub fn new_unexpected_token_error<'i, E>(self, token: Token<'i>) -> ParseError<'i, E> {
+ pub fn new_unexpected_token_error<E>(self, token: Token<'_>) -> ParseError<'_, E> {
+ self.new_error(BasicParseErrorKind::UnexpectedToken(token))
+ }
+
+ /// Create a new basic ParseError at the current location
+ #[inline]
+ pub fn new_error<E>(self, kind: BasicParseErrorKind<'_>) -> ParseError<'_, E> {
ParseError {
- kind: ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(token)),
+ kind: ParseErrorKind::Basic(kind),
location: self,
}
}
@@ -450,19 +462,13 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// Create a new BasicParseError at the current location
#[inline]
pub fn new_basic_error(&self, kind: BasicParseErrorKind<'i>) -> BasicParseError<'i> {
- BasicParseError {
- kind,
- location: self.current_source_location(),
- }
+ self.current_source_location().new_basic_error(kind)
}
/// Create a new basic ParseError at the current location
#[inline]
pub fn new_error<E>(&self, kind: BasicParseErrorKind<'i>) -> ParseError<'i, E> {
- ParseError {
- kind: ParseErrorKind::Basic(kind),
- location: self.current_source_location(),
- }
+ self.current_source_location().new_error(kind)
}
/// Create a new custom BasicParseError at the current location
@@ -606,6 +612,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// See the `Parser::parse_nested_block` method to parse the content of functions or blocks.
///
/// This only returns a closing token when it is unmatched (and therefore an error).
+ #[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Result<&Token<'i>, BasicParseError<'i>> {
self.skip_whitespace();
self.next_including_whitespace_and_comments()
@@ -652,9 +659,8 @@ impl<'i: 't, 't> Parser<'i, 't> {
let token = if using_cached_token {
let cached_token = self.input.cached_token.as_ref().unwrap();
self.input.tokenizer.reset(&cached_token.end_state);
- match cached_token.token {
- Token::Function(ref name) => self.input.tokenizer.see_function(name),
- _ => {}
+ if let Token::Function(ref name) = cached_token.token {
+ self.input.tokenizer.see_function(name)
}
&cached_token.token
} else {
@@ -678,7 +684,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
}
/// Have the given closure parse something, then check the the input is exhausted.
- /// The result is overridden to `Err(())` if some input remains.
+ /// The result is overridden to an `Err(..)` if some input remains.
///
/// This can help tell e.g. `color: green;` from `color: green 4px;`
#[inline]
@@ -699,7 +705,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
///
/// Successful results are accumulated in a vector.
///
- /// This method returns `Err(())` the first time that a closure call does,
+ /// This method returns an`Err(..)` the first time that a closure call does,
/// or if a closure call leaves some input before the next comma or the end
/// of the input.
#[inline]
@@ -748,7 +754,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
match self.parse_until_before(Delimiter::Comma, &mut parse_one) {
Ok(v) => values.push(v),
Err(e) if !ignore_errors => return Err(e),
- Err(_) => {},
+ Err(_) => {}
}
match self.next() {
Err(_) => return Ok(values),
@@ -768,7 +774,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// The given closure is called with a "delimited" parser
/// that stops at the end of the block or function (at the matching closing token).
///
- /// The result is overridden to `Err(())` if the closure leaves some input before that point.
+ /// The result is overridden to an `Err(..)` if the closure leaves some input before that point.
#[inline]
pub fn parse_nested_block<F, T, E>(&mut self, parse: F) -> Result<T, ParseError<'i, E>>
where
@@ -784,7 +790,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// that stops before the first character at this block/function nesting level
/// that matches the given set of delimiters, or at the end of the input.
///
- /// The result is overridden to `Err(())` if the closure leaves some input before that point.
+ /// The result is overridden to an `Err(..)` if the closure leaves some input before that point.
#[inline]
pub fn parse_until_before<F, T, E>(
&mut self,
@@ -835,7 +841,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// expect_ident, but clone the CowRcStr
#[inline]
pub fn expect_ident_cloned(&mut self) -> Result<CowRcStr<'i>, BasicParseError<'i>> {
- self.expect_ident().map(|s| s.clone())
+ self.expect_ident().cloned()
}
/// Parse a <ident-token> whose unescaped value is an ASCII-insensitive match for the given value.
@@ -860,7 +866,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// expect_string, but clone the CowRcStr
#[inline]
pub fn expect_string_cloned(&mut self) -> Result<CowRcStr<'i>, BasicParseError<'i>> {
- self.expect_string().map(|s| s.clone())
+ self.expect_string().cloned()
}
/// Parse either a <ident-token> or a <string-token>, and return the unescaped value.
@@ -879,7 +885,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
Token::UnquotedUrl(ref value) => Ok(value.clone()),
Token::Function(ref name) if name.eq_ignore_ascii_case("url") => {
self.parse_nested_block(|input| {
- input.expect_string().map_err(Into::into).map(|s| s.clone())
+ input.expect_string().map_err(Into::into).cloned()
})
.map_err(ParseError::<()>::basic)
}
@@ -894,7 +900,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
Token::QuotedString(ref value) => Ok(value.clone()),
Token::Function(ref name) if name.eq_ignore_ascii_case("url") => {
self.parse_nested_block(|input| {
- input.expect_string().map_err(Into::into).map(|s| s.clone())
+ input.expect_string().map_err(Into::into).cloned()
})
.map_err(ParseError::<()>::basic)
}
diff --git a/third_party/rust/cssparser/src/rules_and_declarations.rs b/third_party/rust/cssparser/src/rules_and_declarations.rs
index fb33a7d0cd..48da02b5cc 100644
--- a/third_party/rust/cssparser/src/rules_and_declarations.rs
+++ b/third_party/rust/cssparser/src/rules_and_declarations.rs
@@ -4,9 +4,7 @@
// https://drafts.csswg.org/css-syntax/#parsing
-use super::{
- BasicParseError, BasicParseErrorKind, Delimiter, Delimiters, ParseError, Parser, Token,
-};
+use super::{BasicParseError, BasicParseErrorKind, Delimiter, ParseError, Parser, Token};
use crate::cow_rc_str::CowRcStr;
use crate::parser::{parse_nested_block, parse_until_after, ParseUntilErrorBehavior, ParserState};
@@ -14,7 +12,7 @@ use crate::parser::{parse_nested_block, parse_until_after, ParseUntilErrorBehavi
///
/// Typical usage is `input.try_parse(parse_important).is_ok()`
/// at the end of a `DeclarationParser::parse_value` implementation.
-pub fn parse_important<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(), BasicParseError<'i>> {
+pub fn parse_important<'i>(input: &mut Parser<'i, '_>) -> Result<(), BasicParseError<'i>> {
input.expect_delim('!')?;
input.expect_ident_matching("important")
}
@@ -34,7 +32,7 @@ pub trait DeclarationParser<'i> {
///
/// Return the finished representation for the declaration
/// as returned by `DeclarationListParser::next`,
- /// or `Err(())` to ignore the entire declaration as invalid.
+ /// or an `Err(..)` to ignore the entire declaration as invalid.
///
/// Declaration name matching should be case-insensitive in the ASCII range.
/// This can be done with `std::ascii::Ascii::eq_ignore_ascii_case`,
@@ -78,7 +76,7 @@ pub trait AtRuleParser<'i> {
/// Parse the prelude of an at-rule with the given `name`.
///
/// Return the representation of the prelude and the type of at-rule,
- /// or `Err(())` to ignore the entire at-rule as invalid.
+ /// or an `Err(..)` to ignore the entire at-rule as invalid.
///
/// The prelude is the part after the at-keyword
/// and before the `;` semicolon or `{ /* ... */ }` block.
@@ -106,6 +104,7 @@ pub trait AtRuleParser<'i> {
/// This is only called when `parse_prelude` returned `WithoutBlock`, and
/// either the `;` semicolon indeed follows the prelude, or parser is at
/// the end of the input.
+ #[allow(clippy::result_unit_err)]
fn rule_without_block(
&mut self,
prelude: Self::Prelude,
@@ -122,7 +121,7 @@ pub trait AtRuleParser<'i> {
///
/// Return the finished representation of the at-rule
/// as returned by `RuleListParser::next` or `DeclarationListParser::next`,
- /// or `Err(())` to ignore the entire at-rule as invalid.
+ /// or an `Err(..)` to ignore the entire at-rule as invalid.
///
/// This is only called when `parse_prelude` returned `WithBlock`, and a block
/// was indeed found following the prelude.
@@ -161,7 +160,7 @@ pub trait QualifiedRuleParser<'i> {
/// Parse the prelude of a qualified rule. For style rules, this is as Selector list.
///
/// Return the representation of the prelude,
- /// or `Err(())` to ignore the entire at-rule as invalid.
+ /// or an `Err(..)` to ignore the entire at-rule as invalid.
///
/// The prelude is the part before the `{ /* ... */ }` block.
///
@@ -180,7 +179,7 @@ pub trait QualifiedRuleParser<'i> {
///
/// Return the finished representation of the qualified rule
/// as returned by `RuleListParser::next`,
- /// or `Err(())` to ignore the entire at-rule as invalid.
+ /// or an `Err(..)` to ignore the entire at-rule as invalid.
fn parse_block<'t>(
&mut self,
prelude: Self::Prelude,
@@ -253,10 +252,10 @@ where
self.input.skip_whitespace();
let start = self.input.state();
match self.input.next_including_whitespace_and_comments().ok()? {
- Token::CloseCurlyBracket |
- Token::WhiteSpace(..) |
- Token::Semicolon |
- Token::Comment(..) => continue,
+ Token::CloseCurlyBracket
+ | Token::WhiteSpace(..)
+ | Token::Semicolon
+ | Token::Comment(..) => continue,
Token::AtKeyword(ref name) => {
let name = name.clone();
return Some(parse_at_rule(&start, name, self.input, &mut *self.parser));
@@ -292,9 +291,9 @@ where
&start,
self.input,
&mut *self.parser,
- Delimiter::Semicolon | Delimiter::CurlyBracketBlock,
+ /* nested = */ true,
) {
- return Some(Ok(qual))
+ return Some(Ok(qual));
}
}
@@ -303,12 +302,8 @@ where
token => {
let result = if self.parser.parse_qualified() {
self.input.reset(&start);
- let delimiters = if self.parser.parse_declarations() {
- Delimiter::Semicolon | Delimiter::CurlyBracketBlock
- } else {
- Delimiter::CurlyBracketBlock
- };
- parse_qualified_rule(&start, self.input, &mut *self.parser, delimiters)
+ let nested = self.parser.parse_declarations();
+ parse_qualified_rule(&start, self.input, &mut *self.parser, nested)
} else {
let token = token.clone();
self.input.parse_until_after(Delimiter::Semicolon, |_| {
@@ -353,7 +348,7 @@ where
}
}
-/// `RuleListParser` is an iterator that yields `Ok(_)` for a rule or `Err(())` for an invalid one.
+/// `RuleListParser` is an iterator that yields `Ok(_)` for a rule or an `Err(..)` for an invalid one.
impl<'i, 't, 'a, R, P, E: 'i> Iterator for StyleSheetParser<'i, 't, 'a, P>
where
P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E>
@@ -367,7 +362,7 @@ where
let start = self.input.state();
let at_keyword = match self.input.next_byte()? {
b'@' => match self.input.next_including_whitespace_and_comments() {
- Ok(&Token::AtKeyword(ref name)) => Some(name.clone()),
+ Ok(Token::AtKeyword(name)) => Some(name.clone()),
_ => {
self.input.reset(&start);
None
@@ -397,7 +392,7 @@ where
&start,
self.input,
&mut *self.parser,
- Delimiter::CurlyBracketBlock,
+ /* nested = */ false,
);
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
}
@@ -450,7 +445,7 @@ where
if let Some(name) = at_keyword {
parse_at_rule(&start, name, input, parser).map_err(|e| e.0)
} else {
- parse_qualified_rule(&start, input, parser, Delimiter::CurlyBracketBlock)
+ parse_qualified_rule(&start, input, parser, /* nested = */ false)
}
})
}
@@ -490,18 +485,54 @@ where
}
}
+// If the first two non-<whitespace-token> values of rule’s prelude are an <ident-token> whose
+// value starts with "--" followed by a <colon-token>, then...
+fn looks_like_a_custom_property(input: &mut Parser) -> bool {
+ let ident = match input.expect_ident() {
+ Ok(i) => i,
+ Err(..) => return false,
+ };
+ ident.starts_with("--") && input.expect_colon().is_ok()
+}
+
+// https://drafts.csswg.org/css-syntax/#consume-a-qualified-rule
fn parse_qualified_rule<'i, 't, P, E>(
start: &ParserState,
input: &mut Parser<'i, 't>,
parser: &mut P,
- delimiters: Delimiters,
+ nested: bool,
) -> Result<<P as QualifiedRuleParser<'i>>::QualifiedRule, ParseError<'i, E>>
where
P: QualifiedRuleParser<'i, Error = E>,
{
- let prelude = input.parse_until_before(delimiters, |input| parser.parse_prelude(input));
+ input.skip_whitespace();
+ let prelude = {
+ let state = input.state();
+ if looks_like_a_custom_property(input) {
+ // If nested is true, consume the remnants of a bad declaration from input, with
+ // nested set to true, and return nothing.
+ // If nested is false, consume a block from input, and return nothing.
+ let delimiters = if nested {
+ Delimiter::Semicolon
+ } else {
+ Delimiter::CurlyBracketBlock
+ };
+ let _: Result<(), ParseError<()>> = input.parse_until_after(delimiters, |_| Ok(()));
+ return Err(state
+ .source_location()
+ .new_error(BasicParseErrorKind::QualifiedRuleInvalid));
+ }
+ let delimiters = if nested {
+ Delimiter::Semicolon | Delimiter::CurlyBracketBlock
+ } else {
+ Delimiter::CurlyBracketBlock
+ };
+ input.reset(&state);
+ input.parse_until_before(delimiters, |input| parser.parse_prelude(input))
+ };
+
input.expect_curly_bracket_block()?;
// Do this here so that we consume the `{` even if the prelude is `Err`.
let prelude = prelude?;
- parse_nested_block(input, |input| parser.parse_block(prelude, &start, input))
+ parse_nested_block(input, |input| parser.parse_block(prelude, start, input))
}
diff --git a/third_party/rust/cssparser/src/serializer.rs b/third_party/rust/cssparser/src/serializer.rs
index 09c224022d..3c6e31cb84 100644
--- a/third_party/rust/cssparser/src/serializer.rs
+++ b/third_party/rust/cssparser/src/serializer.rs
@@ -3,8 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use crate::match_byte;
-use dtoa_short::{self, Notation};
-use itoa;
+use dtoa_short::Notation;
use std::fmt::{self, Write};
use std::str;
@@ -49,10 +48,9 @@ where
dtoa_short::write(dest, value)?
};
- if int_value.is_none() && value.fract() == 0. {
- if !notation.decimal_point && !notation.scientific {
- dest.write_str(".0")?;
- }
+ if int_value.is_none() && value.fract() == 0. && !notation.decimal_point && !notation.scientific
+ {
+ dest.write_str(".0")?;
}
Ok(())
}
@@ -63,10 +61,10 @@ impl<'a> ToCss for Token<'a> {
W: fmt::Write,
{
match *self {
- Token::Ident(ref value) => serialize_identifier(&**value, dest)?,
+ Token::Ident(ref value) => serialize_identifier(value, dest)?,
Token::AtKeyword(ref value) => {
dest.write_str("@")?;
- serialize_identifier(&**value, dest)?;
+ serialize_identifier(value, dest)?;
}
Token::Hash(ref value) => {
dest.write_str("#")?;
@@ -74,12 +72,12 @@ impl<'a> ToCss for Token<'a> {
}
Token::IDHash(ref value) => {
dest.write_str("#")?;
- serialize_identifier(&**value, dest)?;
+ serialize_identifier(value, dest)?;
}
- Token::QuotedString(ref value) => serialize_string(&**value, dest)?,
+ Token::QuotedString(ref value) => serialize_string(value, dest)?,
Token::UnquotedUrl(ref value) => {
dest.write_str("url(")?;
- serialize_unquoted_url(&**value, dest)?;
+ serialize_unquoted_url(value, dest)?;
dest.write_str(")")?;
}
Token::Delim(value) => dest.write_char(value)?,
@@ -134,7 +132,7 @@ impl<'a> ToCss for Token<'a> {
Token::CDC => dest.write_str("-->")?,
Token::Function(ref name) => {
- serialize_identifier(&**name, dest)?;
+ serialize_identifier(name, dest)?;
dest.write_str("(")?;
}
Token::ParenthesisBlock => dest.write_str("(")?,
@@ -167,7 +165,7 @@ fn hex_escape<W>(ascii_byte: u8, dest: &mut W) -> fmt::Result
where
W: fmt::Write,
{
- static HEX_DIGITS: &'static [u8; 16] = b"0123456789abcdef";
+ static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
let b3;
let b4;
let bytes = if ascii_byte > 0x0F {
@@ -179,7 +177,7 @@ where
b3 = [b'\\', HEX_DIGITS[ascii_byte as usize], b' '];
&b3[..]
};
- dest.write_str(unsafe { str::from_utf8_unchecked(&bytes) })
+ dest.write_str(unsafe { str::from_utf8_unchecked(bytes) })
}
fn char_escape<W>(ascii_byte: u8, dest: &mut W) -> fmt::Result
@@ -199,9 +197,9 @@ where
return Ok(());
}
- if value.starts_with("--") {
+ if let Some(value) = value.strip_prefix("--") {
dest.write_str("--")?;
- serialize_name(&value[2..], dest)
+ serialize_name(value, dest)
} else if value == "-" {
dest.write_str("\\-")
} else {
@@ -240,7 +238,7 @@ where
dest.write_str(&value[chunk_start..i])?;
if let Some(escaped) = escaped {
dest.write_str(escaped)?;
- } else if (b >= b'\x01' && b <= b'\x1F') || b == b'\x7F' {
+ } else if (b'\x01'..=b'\x1F').contains(&b) || b == b'\x7F' {
hex_escape(b, dest)?;
} else {
char_escape(b, dest)?;
@@ -340,7 +338,7 @@ where
macro_rules! impl_tocss_for_int {
($T: ty) => {
- impl<'a> ToCss for $T {
+ impl ToCss for $T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where
W: fmt::Write,
@@ -363,7 +361,7 @@ impl_tocss_for_int!(u64);
macro_rules! impl_tocss_for_float {
($T: ty) => {
- impl<'a> ToCss for $T {
+ impl ToCss for $T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where
W: fmt::Write,
diff --git a/third_party/rust/cssparser/src/tests.rs b/third_party/rust/cssparser/src/tests.rs
index f9dea19325..7389664de4 100644
--- a/third_party/rust/cssparser/src/tests.rs
+++ b/third_party/rust/cssparser/src/tests.rs
@@ -5,8 +5,7 @@
#[cfg(feature = "bench")]
extern crate test;
-use encoding_rs;
-use serde_json::{self, json, Map, Value};
+use serde_json::{json, Map, Value};
#[cfg(feature = "bench")]
use self::test::Bencher;
@@ -25,25 +24,23 @@ macro_rules! JArray {
}
fn almost_equals(a: &Value, b: &Value) -> bool {
- match (a, b) {
- (&Value::Number(ref a), &Value::Number(ref b)) => {
+ let var_name = match (a, b) {
+ (Value::Number(a), Value::Number(b)) => {
let a = a.as_f64().unwrap();
let b = b.as_f64().unwrap();
(a - b).abs() <= a.abs() * 1e-6
}
(&Value::Bool(a), &Value::Bool(b)) => a == b,
- (&Value::String(ref a), &Value::String(ref b)) => a == b,
- (&Value::Array(ref a), &Value::Array(ref b)) => {
- a.len() == b.len()
- && a.iter()
- .zip(b.iter())
- .all(|(ref a, ref b)| almost_equals(*a, *b))
+ (Value::String(a), Value::String(b)) => a == b,
+ (Value::Array(a), Value::Array(b)) => {
+ a.len() == b.len() && a.iter().zip(b.iter()).all(|(a, b)| almost_equals(a, b))
}
(&Value::Object(_), &Value::Object(_)) => panic!("Not implemented"),
(&Value::Null, &Value::Null) => true,
_ => false,
- }
+ };
+ var_name
}
fn normalize(json: &mut Value) {
@@ -77,7 +74,7 @@ fn assert_json_eq(results: Value, mut expected: Value, message: &str) {
}
}
-fn run_raw_json_tests<F: Fn(Value, Value) -> ()>(json_data: &str, run: F) {
+fn run_raw_json_tests<F: Fn(Value, Value)>(json_data: &str, run: F) {
let items = match serde_json::from_str(json_data) {
Ok(Value::Array(items)) => items,
other => panic!("Invalid JSON: {:?}", other),
@@ -242,7 +239,7 @@ fn stylesheet_from_bytes() {
fn get_string<'a>(map: &'a Map<String, Value>, key: &str) -> Option<&'a str> {
match map.get(key) {
- Some(&Value::String(ref s)) => Some(s),
+ Some(Value::String(s)) => Some(s),
Some(&Value::Null) => None,
None => None,
_ => panic!("Unexpected JSON"),
@@ -393,7 +390,7 @@ fn unicode_range() {
if input.is_exhausted() {
Ok(result)
} else {
- while let Ok(_) = input.next() {}
+ while input.next().is_ok() {}
Ok(None)
}
});
@@ -433,11 +430,9 @@ fn serializer(preserve_comments: bool) {
preserve_comments: bool,
) {
while let Ok(token) = if preserve_comments {
- input
- .next_including_whitespace_and_comments()
- .map(|t| t.clone())
+ input.next_including_whitespace_and_comments().cloned()
} else {
- input.next_including_whitespace().map(|t| t.clone())
+ input.next_including_whitespace().cloned()
} {
let token_type = token.serialization_type();
if !preserve_comments && previous_token.needs_separator_when_before(token_type)
@@ -593,8 +588,6 @@ fn line_numbers() {
#[test]
fn overflow() {
- use std::iter::repeat;
-
let css = r"
2147483646
2147483647
@@ -619,7 +612,7 @@ fn overflow() {
-3.402824e+38
"
- .replace("{309 zeros}", &repeat('0').take(309).collect::<String>());
+ .replace("{309 zeros}", &"0".repeat(309));
let mut input = ParserInput::new(&css);
let mut input = Parser::new(&mut input);
@@ -637,15 +630,13 @@ fn overflow() {
assert_eq!(input.expect_integer(), Ok(-2147483648));
assert_eq!(input.expect_integer(), Ok(-2147483648));
- assert_eq!(input.expect_number(), Ok(3.30282347e+38));
+ assert_eq!(input.expect_number(), Ok(3.302_823_5e38));
assert_eq!(input.expect_number(), Ok(f32::MAX));
assert_eq!(input.expect_number(), Ok(f32::INFINITY));
- assert!(f32::MAX != f32::INFINITY);
- assert_eq!(input.expect_number(), Ok(-3.30282347e+38));
+ assert_eq!(input.expect_number(), Ok(-3.302_823_5e38));
assert_eq!(input.expect_number(), Ok(f32::MIN));
assert_eq!(input.expect_number(), Ok(f32::NEG_INFINITY));
- assert!(f32::MIN != f32::NEG_INFINITY);
}
#[test]
@@ -784,7 +775,7 @@ where
impl<'a> ToJson for CowRcStr<'a> {
fn to_json(&self) -> Value {
- let s: &str = &*self;
+ let s: &str = self;
s.to_json()
}
}
@@ -847,7 +838,7 @@ fn no_stack_overflow_multiple_nested_blocks() {
}
let mut input = ParserInput::new(&input);
let mut input = Parser::new(&mut input);
- while let Ok(..) = input.next() {}
+ while input.next().is_ok() {}
}
impl<'i> DeclarationParser<'i> for JsonParser {
@@ -863,18 +854,16 @@ impl<'i> DeclarationParser<'i> for JsonParser {
let mut important = false;
loop {
let start = input.state();
- if let Ok(mut token) = input.next_including_whitespace().map(|t| t.clone()) {
+ if let Ok(mut token) = input.next_including_whitespace().cloned() {
// Hack to deal with css-parsing-tests assuming that
// `!important` in the middle of a declaration value is OK.
// This can never happen per spec
// (even CSS Variables forbid top-level `!`)
if token == Token::Delim('!') {
input.reset(&start);
- if parse_important(input).is_ok() {
- if input.is_exhausted() {
- important = true;
- break;
- }
+ if parse_important(input).is_ok() && input.is_exhausted() {
+ important = true;
+ break;
}
input.reset(&start);
token = input.next_including_whitespace().unwrap().clone();
@@ -905,7 +894,7 @@ impl<'i> AtRuleParser<'i> for JsonParser {
];
match_ignore_ascii_case! { &*name,
"charset" => {
- Err(input.new_error(BasicParseErrorKind::AtRuleInvalid(name.clone()).into()))
+ Err(input.new_error(BasicParseErrorKind::AtRuleInvalid(name.clone())))
},
_ => Ok(prelude),
}
@@ -968,7 +957,7 @@ impl<'i> RuleBodyItemParser<'i, Value, ()> for JsonParser {
fn component_values_to_json(input: &mut Parser) -> Vec<Value> {
let mut values = vec![];
- while let Ok(token) = input.next_including_whitespace().map(|t| t.clone()) {
+ while let Ok(token) = input.next_including_whitespace().cloned() {
values.push(one_component_value_to_json(token, input));
}
values
@@ -978,9 +967,9 @@ fn one_component_value_to_json(token: Token, input: &mut Parser) -> Value {
fn numeric(value: f32, int_value: Option<i32>, has_sign: bool) -> Vec<Value> {
vec![
Token::Number {
- value: value,
- int_value: int_value,
- has_sign: has_sign,
+ value,
+ int_value,
+ has_sign,
}
.to_css_string()
.to_json(),
@@ -1137,7 +1126,7 @@ fn parse_until_before_stops_at_delimiter_or_end_of_input() {
let ox = ix.next();
let oy = iy.next();
assert_eq!(ox, oy);
- if let Err(_) = ox {
+ if ox.is_err() {
break;
}
}
@@ -1223,7 +1212,7 @@ fn parse_sourcemapping_comments() {
for test in tests {
let mut input = ParserInput::new(test.0);
let mut parser = Parser::new(&mut input);
- while let Ok(_) = parser.next_including_whitespace() {}
+ while parser.next_including_whitespace().is_ok() {}
assert_eq!(parser.current_source_map_url(), test.1);
}
}
@@ -1247,7 +1236,7 @@ fn parse_sourceurl_comments() {
for test in tests {
let mut input = ParserInput::new(test.0);
let mut parser = Parser::new(&mut input);
- while let Ok(_) = parser.next_including_whitespace() {}
+ while parser.next_including_whitespace().is_ok() {}
assert_eq!(parser.current_source_url(), test.1);
}
}
@@ -1321,7 +1310,8 @@ fn utf16_columns() {
break;
}
Err(_) => {
- assert!(false);
+ // should this be an explicit panic instead?
+ unreachable!();
}
Ok(_) => {}
};
diff --git a/third_party/rust/cssparser/src/tokenizer.rs b/third_party/rust/cssparser/src/tokenizer.rs
index a3b700632d..ea173a5e45 100644
--- a/third_party/rust/cssparser/src/tokenizer.rs
+++ b/third_party/rust/cssparser/src/tokenizer.rs
@@ -255,10 +255,10 @@ impl<'a> Tokenizer<'a> {
#[inline]
pub fn see_function(&mut self, name: &str) {
- if self.var_or_env_functions == SeenStatus::LookingForThem {
- if name.eq_ignore_ascii_case("var") || name.eq_ignore_ascii_case("env") {
- self.var_or_env_functions = SeenStatus::SeenAtLeastOne;
- }
+ if self.var_or_env_functions == SeenStatus::LookingForThem
+ && (name.eq_ignore_ascii_case("var") || name.eq_ignore_ascii_case("env"))
+ {
+ self.var_or_env_functions = SeenStatus::SeenAtLeastOne;
}
}
@@ -322,10 +322,12 @@ impl<'a> Tokenizer<'a> {
pub fn current_source_line(&self) -> &'a str {
let current = self.position();
- let start = self.slice(SourcePosition(0)..current)
+ let start = self
+ .slice(SourcePosition(0)..current)
.rfind(|c| matches!(c, '\r' | '\n' | '\x0C'))
.map_or(0, |start| start + 1);
- let end = self.slice(current..SourcePosition(self.input.len()))
+ let end = self
+ .slice(current..SourcePosition(self.input.len()))
.find(|c| matches!(c, '\r' | '\n' | '\x0C'))
.map_or(self.input.len(), |end| current.0 + end);
self.slice(SourcePosition(start)..SourcePosition(end))
@@ -424,7 +426,10 @@ impl<'a> Tokenizer<'a> {
#[inline]
fn next_char(&self) -> char {
- unsafe { self.input.get_unchecked(self.position().0..) }.chars().next().unwrap()
+ unsafe { self.input.get_unchecked(self.position().0..) }
+ .chars()
+ .next()
+ .unwrap()
}
// Given that a newline has been seen, advance over the newline
@@ -561,11 +566,11 @@ fn next_token<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>, ()> {
b'#' => {
tokenizer.advance(1);
if is_ident_start(tokenizer) { IDHash(consume_name(tokenizer)) }
- else if !tokenizer.is_eof() && match tokenizer.next_byte_unchecked() {
+ else if !tokenizer.is_eof() &&
+ matches!(tokenizer.next_byte_unchecked(), b'0'..=b'9' | b'-') {
// Any other valid case here already resulted in IDHash.
- b'0'..=b'9' | b'-' => true,
- _ => false,
- } { Hash(consume_name(tokenizer)) }
+ Hash(consume_name(tokenizer))
+ }
else { Delim('#') }
},
b'$' => {
@@ -582,11 +587,11 @@ fn next_token<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>, ()> {
b'+' => {
if (
tokenizer.has_at_least(1)
- && matches!(tokenizer.byte_at(1), b'0'..=b'9')
+ && tokenizer.byte_at(1).is_ascii_digit()
) || (
tokenizer.has_at_least(2)
&& tokenizer.byte_at(1) == b'.'
- && matches!(tokenizer.byte_at(2), b'0'..=b'9')
+ && tokenizer.byte_at(2).is_ascii_digit()
) {
consume_numeric(tokenizer)
} else {
@@ -598,11 +603,11 @@ fn next_token<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>, ()> {
b'-' => {
if (
tokenizer.has_at_least(1)
- && matches!(tokenizer.byte_at(1), b'0'..=b'9')
+ && tokenizer.byte_at(1).is_ascii_digit()
) || (
tokenizer.has_at_least(2)
&& tokenizer.byte_at(1) == b'.'
- && matches!(tokenizer.byte_at(2), b'0'..=b'9')
+ && tokenizer.byte_at(2).is_ascii_digit()
) {
consume_numeric(tokenizer)
} else if tokenizer.starts_with(b"-->") {
@@ -617,8 +622,7 @@ fn next_token<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>, ()> {
},
b'.' => {
if tokenizer.has_at_least(1)
- && matches!(tokenizer.byte_at(1), b'0'..=b'9'
- ) {
+ && tokenizer.byte_at(1).is_ascii_digit() {
consume_numeric(tokenizer)
} else {
tokenizer.advance(1);
@@ -1001,7 +1005,7 @@ fn byte_to_hex_digit(b: u8) -> Option<u32> {
}
fn byte_to_decimal_digit(b: u8) -> Option<u32> {
- if b >= b'0' && b <= b'9' {
+ if b.is_ascii_digit() {
Some((b - b'0') as u32)
} else {
None
@@ -1038,7 +1042,7 @@ fn consume_numeric<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> {
let mut fractional_part: f64 = 0.;
if tokenizer.has_at_least(1)
&& tokenizer.next_byte_unchecked() == b'.'
- && matches!(tokenizer.byte_at(1), b'0'..=b'9')
+ && tokenizer.byte_at(1).is_ascii_digit()
{
is_integer = false;
tokenizer.advance(1); // Consume '.'
@@ -1055,32 +1059,32 @@ fn consume_numeric<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> {
let mut value = sign * (integral_part + fractional_part);
- if tokenizer.has_at_least(1) && matches!(tokenizer.next_byte_unchecked(), b'e' | b'E') {
- if matches!(tokenizer.byte_at(1), b'0'..=b'9')
+ if tokenizer.has_at_least(1)
+ && matches!(tokenizer.next_byte_unchecked(), b'e' | b'E')
+ && (tokenizer.byte_at(1).is_ascii_digit()
|| (tokenizer.has_at_least(2)
&& matches!(tokenizer.byte_at(1), b'+' | b'-')
- && matches!(tokenizer.byte_at(2), b'0'..=b'9'))
- {
- is_integer = false;
+ && tokenizer.byte_at(2).is_ascii_digit()))
+ {
+ is_integer = false;
+ tokenizer.advance(1);
+ let (has_sign, sign) = match tokenizer.next_byte_unchecked() {
+ b'-' => (true, -1.),
+ b'+' => (true, 1.),
+ _ => (false, 1.),
+ };
+ if has_sign {
tokenizer.advance(1);
- let (has_sign, sign) = match tokenizer.next_byte_unchecked() {
- b'-' => (true, -1.),
- b'+' => (true, 1.),
- _ => (false, 1.),
- };
- if has_sign {
- tokenizer.advance(1);
- }
- let mut exponent: f64 = 0.;
- while let Some(digit) = byte_to_decimal_digit(tokenizer.next_byte_unchecked()) {
- exponent = exponent * 10. + digit as f64;
- tokenizer.advance(1);
- if tokenizer.is_eof() {
- break;
- }
+ }
+ let mut exponent: f64 = 0.;
+ while let Some(digit) = byte_to_decimal_digit(tokenizer.next_byte_unchecked()) {
+ exponent = exponent * 10. + digit as f64;
+ tokenizer.advance(1);
+ if tokenizer.is_eof() {
+ break;
}
- value *= f64::powf(10., sign * exponent);
}
+ value *= f64::powf(10., sign * exponent);
}
let int_value = if is_integer {
@@ -1339,7 +1343,7 @@ fn consume_unquoted_url<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>,
}
// (value, number of digits up to 6)
-fn consume_hex_digits<'a>(tokenizer: &mut Tokenizer<'a>) -> (u32, u32) {
+fn consume_hex_digits(tokenizer: &mut Tokenizer<'_>) -> (u32, u32) {
let mut value = 0;
let mut digits = 0;
while digits < 6 && !tokenizer.is_eof() {
diff --git a/third_party/rust/cssparser/src/unicode_range.rs b/third_party/rust/cssparser/src/unicode_range.rs
index b0a2017cbf..ce6bb3b5e7 100644
--- a/third_party/rust/cssparser/src/unicode_range.rs
+++ b/third_party/rust/cssparser/src/unicode_range.rs
@@ -24,7 +24,7 @@ pub struct UnicodeRange {
impl UnicodeRange {
/// https://drafts.csswg.org/css-syntax/#urange-syntax
- pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, BasicParseError<'i>> {
+ pub fn parse<'i>(input: &mut Parser<'i, '_>) -> Result<Self, BasicParseError<'i>> {
// <urange> =
// u '+' <ident-token> '?'* |
// u <dimension-token> '?'* |
@@ -57,7 +57,7 @@ impl UnicodeRange {
}
}
-fn parse_tokens<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(), BasicParseError<'i>> {
+fn parse_tokens<'i>(input: &mut Parser<'i, '_>) -> Result<(), BasicParseError<'i>> {
match input.next_including_whitespace()?.clone() {
Token::Delim('+') => {
match *input.next_including_whitespace()? {
@@ -123,15 +123,13 @@ fn parse_concatenated(text: &[u8]) -> Result<UnicodeRange, ()> {
start: first_hex_value,
end: first_hex_value,
});
- } else {
- if let Some((&b'-', mut text)) = text.split_first() {
- let (second_hex_value, hex_digit_count) = consume_hex(&mut text);
- if hex_digit_count > 0 && hex_digit_count <= 6 && text.is_empty() {
- return Ok(UnicodeRange {
- start: first_hex_value,
- end: second_hex_value,
- });
- }
+ } else if let Some((&b'-', mut text)) = text.split_first() {
+ let (second_hex_value, hex_digit_count) = consume_hex(&mut text);
+ if hex_digit_count > 0 && hex_digit_count <= 6 && text.is_empty() {
+ return Ok(UnicodeRange {
+ start: first_hex_value,
+ end: second_hex_value,
+ });
}
}
Err(())
diff --git a/third_party/rust/cubeb-coreaudio/.cargo-checksum.json b/third_party/rust/cubeb-coreaudio/.cargo-checksum.json
index fa6f229b4c..b0c27f353e 100644
--- a/third_party/rust/cubeb-coreaudio/.cargo-checksum.json
+++ b/third_party/rust/cubeb-coreaudio/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"ac8f4cf5b7631b5c738d50c0cf78113bd395940b9e76593904bbaf2d02d16a70",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"0fb7c56c04e05dacffa5176f885cb8019ee6ab7f885479be501aba0eaac2148f","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"90c2542fa3ff8a35fed894fae3a1aa0157117b7f0e28df14b8e6f7b1f1f43797","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"bae82f66dd47a060b6fdcc238520084aec1079d5b1b1d66d103baa1ffaa8773d","src/backend/aggregate_device.rs":"db7d644358090b1d65ff2d53ad854369790ae4ad7dfa12b79888c0002c1b4950","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"a7622feaa41db1cd76fd35a85a022e44f4894e396a104a59008d5b8757d2ab4e","src/backend/mixer.rs":"ed299d3954e2a823060c870a8244673a7d4bca530830cb66b964d047a80ee3af","src/backend/mod.rs":"e52b79a17dbf7faa072ec87cc3e4201b907772104c3be777498275733b9c334e","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"770cf90f32b5ab2203476031c1fbc8379b713baa97bec36f7fd0d77fef1efd60","src/backend/tests/api.rs":"d72d7c0de8d12e880966948be4686bcf8c789f0ef19cb435c242fd72f2d252f9","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"babf50326fb38db24fe80f24f546e1b6ad04319ae8835bb372d893fc9b3038a2","src/backend/tests/device_property.rs":"73c25f579a995e8a59c9b7d391813afb75f739b5e2f825480cba04499a1d46e8","src/backend/tests/interfaces.rs":"654333cd6d6023e72ba392d98872d33bc55f8f052205a9f701aec72069449e24","src/backend/tests/manual.rs":"e550cc8bb7619bb80b68e49bf7f475c029e0f1b34323d1d30edcbe322cf4efc7","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"a7ebd579339c40ca64c0757cc9da6baec641e670f226e1b2ec5049894700bd7a","src/backend/tests/tone.rs":"b028c67777b6453a26190b6a49785dfe28556adcbe179cb10862ce0d47ee8509","src/backend/tests/utils.rs":"80d7e4ebc06b23c63a4d2867e0c80e0bfe05449fa55edd21e785ed2c089bf7d5","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null} \ No newline at end of file
+{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"ac8f4cf5b7631b5c738d50c0cf78113bd395940b9e76593904bbaf2d02d16a70",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"a16b883e4fb41bdbbe5f68158040f181aeeffb4573ab0d493e9452f7c6f00541","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"90c2542fa3ff8a35fed894fae3a1aa0157117b7f0e28df14b8e6f7b1f1f43797","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"bae82f66dd47a060b6fdcc238520084aec1079d5b1b1d66d103baa1ffaa8773d","src/backend/aggregate_device.rs":"db7d644358090b1d65ff2d53ad854369790ae4ad7dfa12b79888c0002c1b4950","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"a7622feaa41db1cd76fd35a85a022e44f4894e396a104a59008d5b8757d2ab4e","src/backend/mixer.rs":"c4d09291598cbffb2217b551770ec590f34b6dd6b461dd99b019d5bb70f0eef3","src/backend/mod.rs":"d75e116a58d63c6a7cb281d160066f48c8c449702dad58c762ad50d9512d7bd3","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"770cf90f32b5ab2203476031c1fbc8379b713baa97bec36f7fd0d77fef1efd60","src/backend/tests/api.rs":"773e88b506efccf0eacbf408d34dea1fb2c5a8500e7fe8a494a97f15f1ea41fc","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"babf50326fb38db24fe80f24f546e1b6ad04319ae8835bb372d893fc9b3038a2","src/backend/tests/device_property.rs":"73c25f579a995e8a59c9b7d391813afb75f739b5e2f825480cba04499a1d46e8","src/backend/tests/interfaces.rs":"654333cd6d6023e72ba392d98872d33bc55f8f052205a9f701aec72069449e24","src/backend/tests/manual.rs":"e550cc8bb7619bb80b68e49bf7f475c029e0f1b34323d1d30edcbe322cf4efc7","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"a7ebd579339c40ca64c0757cc9da6baec641e670f226e1b2ec5049894700bd7a","src/backend/tests/tone.rs":"b028c67777b6453a26190b6a49785dfe28556adcbe179cb10862ce0d47ee8509","src/backend/tests/utils.rs":"80d7e4ebc06b23c63a4d2867e0c80e0bfe05449fa55edd21e785ed2c089bf7d5","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/cubeb-coreaudio/Cargo.toml b/third_party/rust/cubeb-coreaudio/Cargo.toml
index 8a73548f57..02fb9832ac 100644
--- a/third_party/rust/cubeb-coreaudio/Cargo.toml
+++ b/third_party/rust/cubeb-coreaudio/Cargo.toml
@@ -27,7 +27,7 @@ crate-type = [
[dependencies]
atomic = "0.4"
-audio-mixer = "0.1"
+audio-mixer = "0.2"
bitflags = "2"
cubeb-backend = "0.12.0"
float-cmp = "0.6"
@@ -43,3 +43,6 @@ path = "coreaudio-sys-utils"
[dev-dependencies]
itertools = "0.11"
+
+[features]
+audio-dump = []
diff --git a/third_party/rust/cubeb-coreaudio/src/backend/mixer.rs b/third_party/rust/cubeb-coreaudio/src/backend/mixer.rs
index a4f63926b1..8b80738736 100644
--- a/third_party/rust/cubeb-coreaudio/src/backend/mixer.rs
+++ b/third_party/rust/cubeb-coreaudio/src/backend/mixer.rs
@@ -5,7 +5,7 @@ use std::os::raw::{c_int, c_void};
extern crate audio_mixer;
pub use self::audio_mixer::Channel;
-const CHANNEL_OERDER: [audio_mixer::Channel; audio_mixer::Channel::count()] = [
+const CHANNEL_ORDER: [audio_mixer::Channel; audio_mixer::Channel::count()] = [
audio_mixer::Channel::FrontLeft,
audio_mixer::Channel::FrontRight,
audio_mixer::Channel::FrontCenter,
@@ -25,6 +25,7 @@ const CHANNEL_OERDER: [audio_mixer::Channel; audio_mixer::Channel::count()] = [
audio_mixer::Channel::TopBackCenter,
audio_mixer::Channel::TopBackRight,
audio_mixer::Channel::Silence,
+ audio_mixer::Channel::Discrete,
];
pub fn get_channel_order(channel_layout: ChannelLayout) -> Vec<audio_mixer::Channel> {
@@ -33,7 +34,7 @@ pub fn get_channel_order(channel_layout: ChannelLayout) -> Vec<audio_mixer::Chan
let mut channel_index: usize = 0;
while map != 0 {
if map & 1 == 1 {
- order.push(CHANNEL_OERDER[channel_index]);
+ order.push(CHANNEL_ORDER[channel_index]);
}
map >>= 1;
channel_index += 1;
@@ -44,14 +45,14 @@ pub fn get_channel_order(channel_layout: ChannelLayout) -> Vec<audio_mixer::Chan
fn get_default_channel_order(channel_count: usize) -> Vec<audio_mixer::Channel> {
assert_ne!(channel_count, 0);
let mut channels = Vec::with_capacity(channel_count);
- for channel in CHANNEL_OERDER.iter().take(channel_count) {
+ for channel in CHANNEL_ORDER.iter().take(channel_count) {
channels.push(*channel);
}
- if channel_count > CHANNEL_OERDER.len() {
+ if channel_count > CHANNEL_ORDER.len() {
channels.extend(vec![
audio_mixer::Channel::Silence;
- channel_count - CHANNEL_OERDER.len()
+ channel_count - CHANNEL_ORDER.len()
]);
}
@@ -214,7 +215,7 @@ impl Mixer {
if output_channels.is_empty()
|| out_channel_count != output_channels.len()
|| all_silence == output_channels
- || Self::non_silent_duplicate_channel_present(&output_channels)
+ || Self::duplicate_channel_present(&output_channels)
{
cubeb_log!("Use invalid layout. Apply default layout instead");
output_channels = get_default_channel_order(out_channel_count);
@@ -261,10 +262,10 @@ impl Mixer {
)
}
- fn non_silent_duplicate_channel_present(channels: &[audio_mixer::Channel]) -> bool {
+ fn duplicate_channel_present(channels: &[audio_mixer::Channel]) -> bool {
let mut bitmap: u32 = 0;
for channel in channels {
- if channel != &Channel::Silence {
+ if channel != &Channel::Silence && channel != &Channel::Discrete {
if (bitmap & channel.bitmask()) != 0 {
return true;
}
@@ -456,14 +457,14 @@ fn test_get_channel_order() {
#[test]
fn test_get_default_channel_order() {
- for len in 1..CHANNEL_OERDER.len() + 10 {
+ for len in 1..CHANNEL_ORDER.len() + 10 {
let channels = get_default_channel_order(len);
- if len <= CHANNEL_OERDER.len() {
- assert_eq!(channels, &CHANNEL_OERDER[..len]);
+ if len <= CHANNEL_ORDER.len() {
+ assert_eq!(channels, &CHANNEL_ORDER[..len]);
} else {
- let silences = vec![audio_mixer::Channel::Silence; len - CHANNEL_OERDER.len()];
- assert_eq!(channels[..CHANNEL_OERDER.len()], CHANNEL_OERDER);
- assert_eq!(&channels[CHANNEL_OERDER.len()..], silences.as_slice());
+ let silences = vec![audio_mixer::Channel::Silence; len - CHANNEL_ORDER.len()];
+ assert_eq!(channels[..CHANNEL_ORDER.len()], CHANNEL_ORDER);
+ assert_eq!(&channels[CHANNEL_ORDER.len()..], silences.as_slice());
}
}
}
@@ -478,7 +479,7 @@ fn test_non_silent_duplicate_channels() {
Channel::Silence,
Channel::FrontRight,
];
- assert!(Mixer::non_silent_duplicate_channel_present(&duplicate));
+ assert!(Mixer::duplicate_channel_present(&duplicate));
let non_duplicate = [
Channel::FrontLeft,
@@ -488,5 +489,25 @@ fn test_non_silent_duplicate_channels() {
Channel::Silence,
Channel::Silence,
];
- assert!(!Mixer::non_silent_duplicate_channel_present(&non_duplicate));
+ assert!(!Mixer::duplicate_channel_present(&non_duplicate));
+
+ let duplicate = [
+ Channel::FrontLeft,
+ Channel::Discrete,
+ Channel::FrontRight,
+ Channel::FrontCenter,
+ Channel::Discrete,
+ Channel::FrontRight,
+ ];
+ assert!(Mixer::duplicate_channel_present(&duplicate));
+
+ let non_duplicate = [
+ Channel::FrontLeft,
+ Channel::Discrete,
+ Channel::FrontRight,
+ Channel::FrontCenter,
+ Channel::Discrete,
+ Channel::Discrete,
+ ];
+ assert!(!Mixer::duplicate_channel_present(&non_duplicate));
}
diff --git a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
index e6be028a2e..855c119b63 100644
--- a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
+++ b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
@@ -33,6 +33,8 @@ use self::mixer::*;
use self::resampler::*;
use self::utils::*;
use backend::ringbuf::RingBuffer;
+#[cfg(feature = "audio_dump")]
+use cubeb_backend::ffi::cubeb_audio_dump_stream_t;
use cubeb_backend::{
ffi, ChannelLayout, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType,
Error, InputProcessingParams, Ops, Result, SampleFormat, State, Stream, StreamOps,
@@ -114,6 +116,16 @@ lazy_static! {
};
}
+#[cfg(feature = "audio_dump")]
+fn dump_audio(stream: cubeb_audio_dump_stream_t, audio_samples: *mut c_void, count: u32) {
+ unsafe {
+ let rv = ffi::cubeb_audio_dump_write(stream, audio_samples, count);
+ if rv != 0 {
+ cubeb_alog!("Error dumping audio data");
+ }
+ }
+}
+
fn make_sized_audio_channel_layout(sz: usize) -> AutoRelease<AudioChannelLayout> {
assert!(sz >= mem::size_of::<AudioChannelLayout>());
assert_eq!(
@@ -194,7 +206,12 @@ impl From<CAChannelLabel> for mixer::Channel {
sys::kAudioChannelLabel_TopBackLeft => mixer::Channel::TopBackLeft,
sys::kAudioChannelLabel_TopBackCenter => mixer::Channel::TopBackCenter,
sys::kAudioChannelLabel_TopBackRight => mixer::Channel::TopBackRight,
- _ => mixer::Channel::Silence,
+ sys::kAudioChannelLabel_Unknown => mixer::Channel::Discrete,
+ sys::kAudioChannelLabel_Unused => mixer::Channel::Silence,
+ v => {
+ eprintln!("Warning: channel label value {} isn't handled", v);
+ mixer::Channel::Silence
+ }
}
}
}
@@ -551,6 +568,16 @@ extern "C" fn audiounit_input_callback(
ErrorHandle::Reinit
} else {
assert_eq!(status, NO_ERR);
+
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_input,
+ input_buffer_list.mBuffers[0].mData,
+ input_frames * stm.core_stream_data.input_dev_desc.mChannelsPerFrame,
+ );
+ }
+
input_buffer_manager
.push_data(input_buffer_list.mBuffers[0].mData, input_frames as usize);
ErrorHandle::Return(status)
@@ -708,6 +735,14 @@ extern "C" fn audiounit_output_callback(
if stm.stopped.load(Ordering::SeqCst) {
cubeb_alog!("({:p}) output stopped.", stm as *const AudioUnitStream);
audiounit_make_silent(&buffers[0]);
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
return NO_ERR;
}
@@ -718,12 +753,20 @@ extern "C" fn audiounit_output_callback(
cubeb_alog!("({:p}) output drained.", stm as *const AudioUnitStream);
stm.notify_state_changed(State::Drained);
let queue = stm.queue.clone();
+ audiounit_make_silent(&buffers[0]);
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
// Use a new thread, through the queue, to avoid deadlock when calling
// AudioOutputUnitStop method from inside render callback
queue.run_async(move || {
stm.core_stream_data.stop_audiounits();
});
- audiounit_make_silent(&buffers[0]);
return NO_ERR;
}
@@ -846,12 +889,21 @@ extern "C" fn audiounit_output_callback(
stm.stopped.store(true, Ordering::SeqCst);
stm.notify_state_changed(State::Error);
let queue = stm.queue.clone();
+ audiounit_make_silent(&buffers[0]);
+
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
// Use a new thread, through the queue, to avoid deadlock when calling
// AudioOutputUnitStop method from inside render callback
queue.run_async(move || {
stm.core_stream_data.stop_audiounits();
});
- audiounit_make_silent(&buffers[0]);
return NO_ERR;
}
@@ -898,6 +950,15 @@ extern "C" fn audiounit_output_callback(
buffers[0].mDataByteSize as usize,
);
}
+
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
NO_ERR
}
@@ -3010,6 +3071,14 @@ struct CoreStreamData<'ctx> {
output_alive_listener: Option<device_property_listener>,
output_source_listener: Option<device_property_listener>,
input_logging: Option<InputCallbackLogger>,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session: ffi::cubeb_audio_dump_session_t,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session_running: bool,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_input: ffi::cubeb_audio_dump_stream_t,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_output: ffi::cubeb_audio_dump_stream_t,
}
impl<'ctx> Default for CoreStreamData<'ctx> {
@@ -3050,6 +3119,14 @@ impl<'ctx> Default for CoreStreamData<'ctx> {
output_alive_listener: None,
output_source_listener: None,
input_logging: None,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session_running: false,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_input: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_output: ptr::null_mut(),
}
}
}
@@ -3097,6 +3174,14 @@ impl<'ctx> CoreStreamData<'ctx> {
output_alive_listener: None,
output_source_listener: None,
input_logging: None,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session_running: false,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_input: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_output: ptr::null_mut(),
}
}
@@ -3454,6 +3539,11 @@ impl<'ctx> CoreStreamData<'ctx> {
assert!(!self.stm_ptr.is_null());
let stream = unsafe { &(*self.stm_ptr) };
+ #[cfg(feature = "audio_dump")]
+ unsafe {
+ ffi::cubeb_audio_dump_init(&mut self.audio_dump_session);
+ }
+
// Configure I/O stream
if self.has_input() {
assert!(!self.input_unit.is_null());
@@ -3543,6 +3633,26 @@ impl<'ctx> CoreStreamData<'ctx> {
e
})?;
+ #[cfg(feature = "audio_dump")]
+ {
+ let name = format!("input-{:p}.wav", self.stm_ptr);
+ let cname = CString::new(name).expect("OK");
+ let rv = unsafe {
+ ffi::cubeb_audio_dump_stream_init(
+ self.audio_dump_session,
+ &mut self.audio_dump_input,
+ *params.as_ptr(),
+ cname.as_ptr(),
+ )
+ };
+ if rv == 0 {
+ assert_ne!(self.audio_dump_input, ptr::null_mut(),);
+ cubeb_log!("Successfully inited audio dump for input");
+ } else {
+ cubeb_log!("Failed to init audio dump for input");
+ }
+ }
+
assert_eq!(self.input_dev_desc.mSampleRate, input_hw_desc.mSampleRate);
// Use latency to set buffer size
@@ -3739,6 +3849,26 @@ impl<'ctx> CoreStreamData<'ctx> {
e
})?;
+ #[cfg(feature = "audio_dump")]
+ {
+ let name = format!("output-{:p}.wav", self.stm_ptr);
+ let cname = CString::new(name).expect("OK");
+ let rv = unsafe {
+ ffi::cubeb_audio_dump_stream_init(
+ self.audio_dump_session,
+ &mut self.audio_dump_output,
+ *params.as_ptr(),
+ cname.as_ptr(),
+ )
+ };
+ if rv == 0 {
+ assert_ne!(self.audio_dump_output, ptr::null_mut(),);
+ cubeb_log!("Successfully inited audio dump for output");
+ } else {
+ cubeb_log!("Failed to init audio dump for output");
+ }
+ }
+
let device_layout = self
.get_output_channel_layout()
.map_err(|e| {
@@ -3908,6 +4038,12 @@ impl<'ctx> CoreStreamData<'ctx> {
self.input_logging = Some(InputCallbackLogger::new());
}
+ #[cfg(feature = "audio_dump")]
+ {
+ unsafe { ffi::cubeb_audio_dump_start(self.audio_dump_session) };
+ self.audio_dump_session_running = true;
+ }
+
if !self.input_unit.is_null() {
let r = audio_unit_initialize(self.input_unit);
if r != NO_ERR {
@@ -4081,6 +4217,36 @@ impl<'ctx> CoreStreamData<'ctx> {
// Return the VPIO unit if present.
self.voiceprocessing_unit_handle = None;
+ #[cfg(feature = "audio_dump")]
+ {
+ if !self.audio_dump_session.is_null() {
+ unsafe {
+ ffi::cubeb_audio_dump_stop(self.audio_dump_session);
+ if !self.audio_dump_input.is_null() {
+ let rv = ffi::cubeb_audio_dump_stream_shutdown(
+ self.audio_dump_session,
+ self.audio_dump_input,
+ );
+ if rv != 0 {
+ cubeb_log!("Failed to shutdown audio dump for input");
+ }
+ }
+ if !self.audio_dump_output.is_null() {
+ let rv = ffi::cubeb_audio_dump_stream_shutdown(
+ self.audio_dump_session,
+ self.audio_dump_output,
+ );
+ if rv != 0 {
+ cubeb_log!("Failed to shutdown audio dump for output");
+ }
+ }
+ ffi::cubeb_audio_dump_shutdown(self.audio_dump_session);
+ self.audio_dump_session = ptr::null_mut();
+ self.audio_dump_session_running = false;
+ }
+ }
+ }
+
self.resampler.destroy();
self.mixer = None;
self.aggregate_device = None;
diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs
index 5ce2374a3e..ea08a5ef45 100644
--- a/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs
+++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs
@@ -376,7 +376,6 @@ fn test_get_default_device_id_with_inout_type() {
#[test]
fn test_convert_channel_layout() {
let pairs = [
- (vec![kAudioObjectUnknown], vec![mixer::Channel::Silence]),
(
vec![kAudioChannelLabel_Mono],
vec![mixer::Channel::FrontCenter],
@@ -398,7 +397,7 @@ fn test_convert_channel_layout() {
vec![
mixer::Channel::FrontLeft,
mixer::Channel::FrontRight,
- mixer::Channel::Silence,
+ mixer::Channel::Discrete,
],
),
(
diff --git a/third_party/rust/d3d12/.cargo-checksum.json b/third_party/rust/d3d12/.cargo-checksum.json
index 8b27c96861..34bfd8a003 100644
--- a/third_party/rust/d3d12/.cargo-checksum.json
+++ b/third_party/rust/d3d12/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"45fa76b0e5bc51721887147000e9e78a5934cb04d1ad628e501ef2082763d353","Cargo.toml":"a3135c67216ba021525ebc8d18dc3de5d779f1a1ddde5f25f4439acabd45824a","README.md":"76cee3209f773a62535de6c9724b53f158406359f35b4d48b17ac3747b6c102e","src/com.rs":"cfd6556a7abf38cba57559038f9f2cf86274418448fb2745436c251a99575e05","src/command_allocator.rs":"ef01059a661749470f3772d188fe0fab0f002e1d154facdab4b9b2932f4b2d93","src/command_list.rs":"8723f3b755b721e0dbb234bd604956c1b7922a2368231197495daa3fa6548e63","src/debug.rs":"aa33b98f7c3e71cba75fc42c6ca9af72d96b45122422c16e48525e24590c57bf","src/descriptor.rs":"fea0b820de1566b54d17d8d0c67e6f5a2126eda19526397eb710ff7d6db9db9e","src/device.rs":"c1dd479aabd22bced0d407523d60629ad1da439fb47ad89fe7b48bae1c4b23e5","src/dxgi.rs":"1516186845b91bf3df813a29b4a0e00a85ca5649fb7a2755da43fba984c41a42","src/heap.rs":"dae2380684896c97e97ed022929f79ce2cc4f5418a3ec34883086f7c88f423d0","src/lib.rs":"612e2f471b84502d219da3fb86ee13f3cbd6faf17d77407bab6c84e51ec424d0","src/pso.rs":"ff819c321536695e34a3be9a6051cf3e57765049a4a2035db6ab27add5a7978a","src/query.rs":"ff61a2b76a108afc1f082724bb9b07ac8b52afbe97356e0fcf6df0ff7e53e07d","src/queue.rs":"bd32813d0b8a3bedf3223b69ade9f9c799a138a9e27d970f86435d9ce32d1557","src/resource.rs":"8989cdb7c3ee0687c826047f39f85148459d9219754f20a970bf8aaa09b96e27","src/sync.rs":"5c287fb7498242a397eb1f08887be9cff9b48dc7cb13af5792cce5f7182b55f8"},"package":null} \ No newline at end of file
+{"files":{"CHANGELOG.md":"45fa76b0e5bc51721887147000e9e78a5934cb04d1ad628e501ef2082763d353","Cargo.toml":"9938addd7ce2c7785a9ca11eb0049271317f9b05fdf0d7330d4a80f0e07ab500","README.md":"76cee3209f773a62535de6c9724b53f158406359f35b4d48b17ac3747b6c102e","src/com.rs":"cfd6556a7abf38cba57559038f9f2cf86274418448fb2745436c251a99575e05","src/command_allocator.rs":"ef01059a661749470f3772d188fe0fab0f002e1d154facdab4b9b2932f4b2d93","src/command_list.rs":"8723f3b755b721e0dbb234bd604956c1b7922a2368231197495daa3fa6548e63","src/debug.rs":"aa33b98f7c3e71cba75fc42c6ca9af72d96b45122422c16e48525e24590c57bf","src/descriptor.rs":"fea0b820de1566b54d17d8d0c67e6f5a2126eda19526397eb710ff7d6db9db9e","src/device.rs":"c1dd479aabd22bced0d407523d60629ad1da439fb47ad89fe7b48bae1c4b23e5","src/dxgi.rs":"1516186845b91bf3df813a29b4a0e00a85ca5649fb7a2755da43fba984c41a42","src/heap.rs":"dae2380684896c97e97ed022929f79ce2cc4f5418a3ec34883086f7c88f423d0","src/lib.rs":"612e2f471b84502d219da3fb86ee13f3cbd6faf17d77407bab6c84e51ec424d0","src/pso.rs":"ff819c321536695e34a3be9a6051cf3e57765049a4a2035db6ab27add5a7978a","src/query.rs":"ff61a2b76a108afc1f082724bb9b07ac8b52afbe97356e0fcf6df0ff7e53e07d","src/queue.rs":"bd32813d0b8a3bedf3223b69ade9f9c799a138a9e27d970f86435d9ce32d1557","src/resource.rs":"8989cdb7c3ee0687c826047f39f85148459d9219754f20a970bf8aaa09b96e27","src/sync.rs":"5c287fb7498242a397eb1f08887be9cff9b48dc7cb13af5792cce5f7182b55f8"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/d3d12/Cargo.toml b/third_party/rust/d3d12/Cargo.toml
index 1425e10b80..576d6e21bb 100644
--- a/third_party/rust/d3d12/Cargo.toml
+++ b/third_party/rust/d3d12/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "d3d12"
-version = "0.19.0"
+version = "0.20.0"
authors = ["gfx-rs developers"]
description = "Low level D3D12 API wrapper"
documentation = "https://docs.rs/d3d12"
diff --git a/third_party/rust/encoding_rs/.cargo-checksum.json b/third_party/rust/encoding_rs/.cargo-checksum.json
index a5e1f1ba25..d5e91dd7e2 100644
--- a/third_party/rust/encoding_rs/.cargo-checksum.json
+++ b/third_party/rust/encoding_rs/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"ca1901f3e8532fb4cec894fd3664f0eaa898c0c4b961d1b992d1ed54eacf362a","COPYRIGHT":"11789f45bb180841cd362a5eee6789c68ddb573a11105e30768c308a6add0190","Cargo.toml":"42fa83322aa9fd6723b77d35d0cacb92cbb6e7f573ce11c55f5225292866f8f4","Ideas.md":"b7452893f500163868d8de52c09addaf91e1632454ed02e892c467ed7ec39dbd","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"3fa4ca83dcc9237839b1bdeb2e6d16bdfb5ec0c5ce42b24694d8bbf0dcbef72c","LICENSE-WHATWG":"838118388fe5c2e7f1dbbaeed13e1c7f3ebf88be91319c7c1d77c18e987d1a50","README.md":"d938e8ab0b9ab67e74a1a4f48f23fdce956d0ad3a3f6147ae7612a92763c88d5","ci/miri.sh":"43cb8d82f49e3bfe2d2274b6ccd6f0714a4188ccef0cecc040829883cfdbee25","doc/Big5.txt":"f73a2edc5cb6c2d140ba6e07f4542e1c4a234950378acde1df93480f0ca0be0b","doc/EUC-JP.txt":"ee2818b907d0137f40a9ab9fd525fc700a44dbdddb6cf0c157a656566bae4bf1","doc/EUC-KR.txt":"71d9e2ccf3b124e8bdfb433c8cf2773fd878077038d0cec3c7237a50f4a78a30","doc/GBK.txt":"c1b522b5a799884e5001da661f42c5a8f4d0acb9ef1d74b206f22b5f65365606","doc/IBM866.txt":"a5a433e804d0f83af785015179fbc1d9b0eaf1f7960efcd04093e136b51fbd0e","doc/ISO-2022-JP.txt":"af86684f5a8f0e2868d7b2c292860140c3d2e5527530ca091f1b28198e8e2fe6","doc/ISO-8859-10.txt":"6d3949ad7c81ca176895101ed81a1db7df1060d64e262880b94bd31bb344ab4d","doc/ISO-8859-13.txt":"3951dd89cf93f7729148091683cf8511f4529388b7dc8dcd0d62eaed55be93fa","doc/ISO-8859-14.txt":"3d330784a0374fd255a38b47949675cc7168c800530534b0a01cac6edc623adc","doc/ISO-8859-15.txt":"24b1084aab5127a85aab99153f86e24694d0a3615f53b5ce23683f97cf66c47a","doc/ISO-8859-16.txt":"ce0272559b92ba76d7a7e476f6424ae4a5cc72e75b183611b08392e44add4d25","doc/ISO-8859-2.txt":"18ceff88c13d1b5ba455a3919b1e3de489045c4c3d2dd7e8527c125c75d54aad","doc/ISO-8859-3.txt":"21798404c68f4f5db59223362f24999da96968c0628427321fccce7d2849a130","doc/ISO-8859-4.txt":"d27f6520c6c5bfbcc19176b71d081cdb3bccde1622bb3e420d5680e812632d53","doc/ISO-8859-5.txt":"a10ec8d6ea7a78ad15da7275f6cb1a3365118527e28f9af6d0d5830501303f3a","doc/ISO-8859-6.txt":"ccda8a2efc96115336bdd77776637b9712425e44fbcf745353b9057fbef144e7","doc/ISO-8859-7.txt":"17900fa1f27a445958f0a77d7d9056be375a6bd7ee4492aa680c7c1500bab85e","doc/ISO-8859-8-I.txt":"8357555646d54265a9b9ffa3e68b08d132312f1561c60108ff9b8b1167b6ecf2","doc/ISO-8859-8.txt":"72cd6f3afb7b4a9c16a66a362473315770b7755d72c86c870e52fc3eba86c8af","doc/KOI8-R.txt":"839cf19a38da994488004ed7814b1f6151640156a9a2af02bf2efca745fb5966","doc/KOI8-U.txt":"0cc76624ed1f024183e2298b7e019957da2c70c8ca06e0fc4e6f353f50a5054f","doc/Shift_JIS.txt":"34c49141818cb9ddbcf59cc858f78a79be8ad148d563f26415108ae1f148443f","doc/UTF-16BE.txt":"e2e280d8acbaa6d2a6b3569d60e17500a285f2baa0df3363dd85537cd5a1ef8f","doc/UTF-16LE.txt":"70bdc170e3fc5298ba68f10125fb5eeb8b077036cc96bb4416c4de396f6d76c1","doc/UTF-8.txt":"ea7bae742e613010ced002cf4b601a737d2203fad65e115611451bc4428f548a","doc/gb18030.txt":"dc71378a8f07a2d8659f69ee81fb8791fef56ba86f124b429978285237bb4a7b","doc/macintosh.txt":"57491e53866711b4672d9b9ff35380b9dac9e0d8e3d6c20bdd6140603687c023","doc/replacement.txt":"4b6c3bbd7999d9d4108a281594bd02d13607e334a95465afff8c2c08d395f0e4","doc/windows-1250.txt":"61296bb6a21cdab602300d32ecfba434cb82de5ac3bc88d58710d2f125e28d39","doc/windows-1251.txt":"7deea1c61dea1485c8ff02db2c7d578db7a9aab63ab1cfd02ec04b515864689e","doc/windows-1252.txt":"933ef3bdddfce5ee132b9f1a1aa8b47423d2587bbe475b19028d0a6d38e180b6","doc/windows-1253.txt":"1a38748b88e99071a5c7b3d5456ead4caedeabab50d50d658be105bc113714de","doc/windows-1254.txt":"f8372f86c6f8d642563cd6ddc025260553292a39423df1683a98670bd7bf2b47","doc/windows-1255.txt":"4e5852494730054e2da258a74e1b9d780abbcdd8ce22ebc218ca2efe9e90493d","doc/windows-1256.txt":"c0879c5172abedead302a406e8f60d9cd9598694a0ffa4fd288ffe4fef7b8ea1","doc/windows-1257.txt":"c28a0c9f964fcb2b46d21f537c402446501a2800670481d6abf9fd9e9018d523","doc/windows-1258.txt":"5019ae4d61805c79aacbf17c93793342dbb098d65a1837783bc3e2c6d6a23602","doc/windows-874.txt":"4ef0e4501c5feba8b17aee1818602ed44b36ca8475db771ce2fc16d392cabecc","doc/x-mac-cyrillic.txt":"58be154d8a888ca3d484b83b44f749823ef339ab27f14d90ca9a856f5050a8bd","doc/x-user-defined.txt":"f9cd07c4321bf5cfb0be4bdddd251072999b04a6cf7a6f5bc63709a84e2c1ffc","generate-encoding-data.py":"be989dd25c6b946e3e8745fdc8e8a80fcf24b3be99ad0b4b78153ba3f6ab6310","rustfmt.toml":"85c1a3b4382fd89e991cbb81b70fb52780472edc064c963943cdaaa56e0a2030","src/ascii.rs":"c44c002641adb5ebc4368707a8cc0a076d2f33e6a5c27b1b69988eb515f5653d","src/big5.rs":"ec6e2913011a38e9a3e825a1731f139a7ca1d5b264fefae51a3cc1a68a57cef9","src/data.rs":"8a617cc57032092d65850eb27e00de687c80aea3299e839a1f58b42d0b35abf3","src/euc_jp.rs":"32047f5b540188c4cb19c07165f846b9786a09f18e315ed3e9bda1293dae52aa","src/euc_kr.rs":"9b25afc72d9378700eecfac58d55ad1c5946d6cd0ccde2c29c08200ef2de6bb9","src/gb18030.rs":"808587168d73f0c80f8520f0ca9b161866ed2efeb17a05e85fdf3b8efe7ba28a","src/handles.rs":"cc83dc0754751d67f5688a65c5e0191cba02f6bacce81a0813a243cba55eef7a","src/iso_2022_jp.rs":"9bb485e82574f4b7d4b2364f0ff276acb6a0bc111758420a3b0ec5e04c196652","src/lib.rs":"1dc07b818e45846b16ddcaf0de46c8862dd7df8099123ec38b95c3f8ad9c91ec","src/macros.rs":"200997f8870de8bfd8cdc475e92115df42108c0df661e49d3d1cbc32056e1d99","src/mem.rs":"0bf34103e0ad1b842a13a082dee2b920b05cf4fb0f145c9ee7f608f4cb4a544f","src/replacement.rs":"7660b34a53f8c1ca2bdfa0e51e843ec28326950952ad8bc96569feb93ac62308","src/shift_jis.rs":"6951ae67e36b1a12fa3a30734957f444d8b1b4ae0e2bde52060b29bd0f16d9d9","src/simd_funcs.rs":"2612aba86e1d201096d7e47a859bc3444f85934cc82d8adc6d39a4304d9eecfc","src/single_byte.rs":"3c9e9c1f946ae622c725ba9421240c1faa9a05e95fa10dd4642a25cb276a1edc","src/test_data/big5_in.txt":"4c5a8691f8dc717311889c63894026d2fb62725a86c4208ca274a9cc8d42a503","src/test_data/big5_in_ref.txt":"99d399e17750cf9c7cf30bb253dbfe35b81c4fcbdead93cfa48b1429213473c7","src/test_data/big5_out.txt":"6193ca97c297aa20e09396038d18e938bb7ea331c26f0f2454097296723a0b13","src/test_data/big5_out_ref.txt":"36567691f557df144f6cc520015a87038dfa156f296fcf103b56ae9a718be1fc","src/test_data/euc_kr_in.txt":"c86a7224f3215fa0d04e685622a752fdc72763e8ae076230c7fd62de57ec4074","src/test_data/euc_kr_in_ref.txt":"1f419f4ca47d708b54c73c461545a022ae2e20498fdbf8005a483d752a204883","src/test_data/euc_kr_out.txt":"e7f32e026f70be1e1b58e0047baf7d3d2c520269c4f9b9992e158b4decb0a1a3","src/test_data/euc_kr_out_ref.txt":"c9907857980b20b8e9e3b584482ed6567a2be6185d72237b6322f0404944924e","src/test_data/gb18030_in.txt":"ab7231b2d3e9afacdbd7d7f3b9e5361a7ff9f7e1cfdb4f3bd905b9362b309e53","src/test_data/gb18030_in_ref.txt":"dc5069421adca2043c55f5012b55a76fdff651d22e6e699fd0978f8d5706815c","src/test_data/gb18030_out.txt":"f0208d527f5ca63de7d9a0323be8d5cf12d8a104b2943d92c2701f0c3364dac1","src/test_data/gb18030_out_ref.txt":"6819fe47627e4ea01027003fc514b9f21a1322e732d7f1fb92cc6c5455bc6c07","src/test_data/iso_2022_jp_in.txt":"cd24bbdcb1834e25db54646fbf4c41560a13dc7540f6be3dba4f5d97d44513af","src/test_data/iso_2022_jp_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/iso_2022_jp_out.txt":"9b6f015329dda6c3f9ee5ce6dbd6fa9c89acc21283e886836c78b8d833480c21","src/test_data/iso_2022_jp_out_ref.txt":"78cb260093a20116ad9a42f43b05d1848c5ab100b6b9a850749809e943884b35","src/test_data/jis0208_in.txt":"6df3030553ffb0a6615bb33dc8ea9dca6d9623a9028e2ffec754ce3c3da824cc","src/test_data/jis0208_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/jis0208_out.txt":"4ec24477e1675ce750733bdc3c5add1cd27b6bd4ce1f09289564646e9654e857","src/test_data/jis0208_out_ref.txt":"c3e1cef5032b2b1d93a406f31ff940c4e2dfe8859b8b17ca2761fee7a75a0e48","src/test_data/jis0212_in.txt":"c011f0dd72bd7c8cd922df9374ef8d2769a77190514c77f6c62b415852eeb9fe","src/test_data/jis0212_in_ref.txt":"7d9458b3d2f73e7092a7f505c08ce1d233dde18aa679fbcf9889256239cc9e06","src/test_data/shift_jis_in.txt":"02e389ccef0dd2122e63f503899402cb7f797912c2444cc80ab93131116c5524","src/test_data/shift_jis_in_ref.txt":"512f985950ca902e643c88682dba9708b7c38d3c5ec2925168ab00ac94ab19f9","src/test_data/shift_jis_out.txt":"5fbc44da7bf639bf6cfe0fa1fd3eba7102b88f81919c9ea991302712f69426fb","src/test_data/shift_jis_out_ref.txt":"466322c6fed8286c64582731755290c2296508efdd258826e6279686649b481f","src/test_labels_names.rs":"23a2e11b02b3b8d15fb5613a625e3edb2c61e70e3c581abfd638719a4088200d","src/testing.rs":"f59e671e95a98a56f6b573e8c6be4d71e670bf52f7e20eb1605d990aafa1894e","src/utf_16.rs":"c071a147fad38d750c2c247e141b76b929a48007b99f26b2922b9caecdaf2f25","src/utf_8.rs":"7b7d887b347f1aefa03246b028a36a72758a4ce76c28f3b45c19467851aa7839","src/variant.rs":"1fab5363588a1554a7169de8731ea9cded7ac63ea35caabdd1c27a8dde68c27b","src/x_user_defined.rs":"c9c010730dfb9f141d4fed19350c08a21af240913a54bb64f5ca89ff93b6b7d1"},"package":"7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"} \ No newline at end of file
+{"files":{"CONTRIBUTING.md":"ca1901f3e8532fb4cec894fd3664f0eaa898c0c4b961d1b992d1ed54eacf362a","COPYRIGHT":"11789f45bb180841cd362a5eee6789c68ddb573a11105e30768c308a6add0190","Cargo.toml":"22a4d210c92dae9f32c6944ef340ee8fdd027f99c081577e8907123e2a93383e","Ideas.md":"b7452893f500163868d8de52c09addaf91e1632454ed02e892c467ed7ec39dbd","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"3fa4ca83dcc9237839b1bdeb2e6d16bdfb5ec0c5ce42b24694d8bbf0dcbef72c","LICENSE-WHATWG":"838118388fe5c2e7f1dbbaeed13e1c7f3ebf88be91319c7c1d77c18e987d1a50","README.md":"1d08aefcb92afa81b18154049c9abbcad4540a23f7172e9f9bbed5af33f1a087","ci/miri.sh":"43cb8d82f49e3bfe2d2274b6ccd6f0714a4188ccef0cecc040829883cfdbee25","doc/Big5.txt":"f73a2edc5cb6c2d140ba6e07f4542e1c4a234950378acde1df93480f0ca0be0b","doc/EUC-JP.txt":"ee2818b907d0137f40a9ab9fd525fc700a44dbdddb6cf0c157a656566bae4bf1","doc/EUC-KR.txt":"71d9e2ccf3b124e8bdfb433c8cf2773fd878077038d0cec3c7237a50f4a78a30","doc/GBK.txt":"c1b522b5a799884e5001da661f42c5a8f4d0acb9ef1d74b206f22b5f65365606","doc/IBM866.txt":"a5a433e804d0f83af785015179fbc1d9b0eaf1f7960efcd04093e136b51fbd0e","doc/ISO-2022-JP.txt":"af86684f5a8f0e2868d7b2c292860140c3d2e5527530ca091f1b28198e8e2fe6","doc/ISO-8859-10.txt":"6d3949ad7c81ca176895101ed81a1db7df1060d64e262880b94bd31bb344ab4d","doc/ISO-8859-13.txt":"3951dd89cf93f7729148091683cf8511f4529388b7dc8dcd0d62eaed55be93fa","doc/ISO-8859-14.txt":"3d330784a0374fd255a38b47949675cc7168c800530534b0a01cac6edc623adc","doc/ISO-8859-15.txt":"24b1084aab5127a85aab99153f86e24694d0a3615f53b5ce23683f97cf66c47a","doc/ISO-8859-16.txt":"ce0272559b92ba76d7a7e476f6424ae4a5cc72e75b183611b08392e44add4d25","doc/ISO-8859-2.txt":"18ceff88c13d1b5ba455a3919b1e3de489045c4c3d2dd7e8527c125c75d54aad","doc/ISO-8859-3.txt":"21798404c68f4f5db59223362f24999da96968c0628427321fccce7d2849a130","doc/ISO-8859-4.txt":"d27f6520c6c5bfbcc19176b71d081cdb3bccde1622bb3e420d5680e812632d53","doc/ISO-8859-5.txt":"a10ec8d6ea7a78ad15da7275f6cb1a3365118527e28f9af6d0d5830501303f3a","doc/ISO-8859-6.txt":"ccda8a2efc96115336bdd77776637b9712425e44fbcf745353b9057fbef144e7","doc/ISO-8859-7.txt":"17900fa1f27a445958f0a77d7d9056be375a6bd7ee4492aa680c7c1500bab85e","doc/ISO-8859-8-I.txt":"8357555646d54265a9b9ffa3e68b08d132312f1561c60108ff9b8b1167b6ecf2","doc/ISO-8859-8.txt":"72cd6f3afb7b4a9c16a66a362473315770b7755d72c86c870e52fc3eba86c8af","doc/KOI8-R.txt":"839cf19a38da994488004ed7814b1f6151640156a9a2af02bf2efca745fb5966","doc/KOI8-U.txt":"0cc76624ed1f024183e2298b7e019957da2c70c8ca06e0fc4e6f353f50a5054f","doc/Shift_JIS.txt":"34c49141818cb9ddbcf59cc858f78a79be8ad148d563f26415108ae1f148443f","doc/UTF-16BE.txt":"e2e280d8acbaa6d2a6b3569d60e17500a285f2baa0df3363dd85537cd5a1ef8f","doc/UTF-16LE.txt":"70bdc170e3fc5298ba68f10125fb5eeb8b077036cc96bb4416c4de396f6d76c1","doc/UTF-8.txt":"ea7bae742e613010ced002cf4b601a737d2203fad65e115611451bc4428f548a","doc/gb18030.txt":"dc71378a8f07a2d8659f69ee81fb8791fef56ba86f124b429978285237bb4a7b","doc/macintosh.txt":"57491e53866711b4672d9b9ff35380b9dac9e0d8e3d6c20bdd6140603687c023","doc/replacement.txt":"4b6c3bbd7999d9d4108a281594bd02d13607e334a95465afff8c2c08d395f0e4","doc/windows-1250.txt":"61296bb6a21cdab602300d32ecfba434cb82de5ac3bc88d58710d2f125e28d39","doc/windows-1251.txt":"7deea1c61dea1485c8ff02db2c7d578db7a9aab63ab1cfd02ec04b515864689e","doc/windows-1252.txt":"933ef3bdddfce5ee132b9f1a1aa8b47423d2587bbe475b19028d0a6d38e180b6","doc/windows-1253.txt":"1a38748b88e99071a5c7b3d5456ead4caedeabab50d50d658be105bc113714de","doc/windows-1254.txt":"f8372f86c6f8d642563cd6ddc025260553292a39423df1683a98670bd7bf2b47","doc/windows-1255.txt":"4e5852494730054e2da258a74e1b9d780abbcdd8ce22ebc218ca2efe9e90493d","doc/windows-1256.txt":"c0879c5172abedead302a406e8f60d9cd9598694a0ffa4fd288ffe4fef7b8ea1","doc/windows-1257.txt":"c28a0c9f964fcb2b46d21f537c402446501a2800670481d6abf9fd9e9018d523","doc/windows-1258.txt":"5019ae4d61805c79aacbf17c93793342dbb098d65a1837783bc3e2c6d6a23602","doc/windows-874.txt":"4ef0e4501c5feba8b17aee1818602ed44b36ca8475db771ce2fc16d392cabecc","doc/x-mac-cyrillic.txt":"58be154d8a888ca3d484b83b44f749823ef339ab27f14d90ca9a856f5050a8bd","doc/x-user-defined.txt":"f9cd07c4321bf5cfb0be4bdddd251072999b04a6cf7a6f5bc63709a84e2c1ffc","generate-encoding-data.py":"be989dd25c6b946e3e8745fdc8e8a80fcf24b3be99ad0b4b78153ba3f6ab6310","rustfmt.toml":"85c1a3b4382fd89e991cbb81b70fb52780472edc064c963943cdaaa56e0a2030","src/ascii.rs":"588e38b01e666d5e7462617ea7e90a108d608dec9e016f3d273ac0744af2e05d","src/big5.rs":"ec6e2913011a38e9a3e825a1731f139a7ca1d5b264fefae51a3cc1a68a57cef9","src/data.rs":"8a617cc57032092d65850eb27e00de687c80aea3299e839a1f58b42d0b35abf3","src/euc_jp.rs":"32047f5b540188c4cb19c07165f846b9786a09f18e315ed3e9bda1293dae52aa","src/euc_kr.rs":"9b25afc72d9378700eecfac58d55ad1c5946d6cd0ccde2c29c08200ef2de6bb9","src/gb18030.rs":"808587168d73f0c80f8520f0ca9b161866ed2efeb17a05e85fdf3b8efe7ba28a","src/handles.rs":"b08cef1f5785bb6a4822f2e844c6df1b046b737b7a075e4593eaa8c4208e9fe2","src/iso_2022_jp.rs":"9bb485e82574f4b7d4b2364f0ff276acb6a0bc111758420a3b0ec5e04c196652","src/lib.rs":"834f44b670ec48ee82c0e12223d1567313fdd9f88bca5f4b117c82c1828f559f","src/macros.rs":"200997f8870de8bfd8cdc475e92115df42108c0df661e49d3d1cbc32056e1d99","src/mem.rs":"948571137d3b151df8db4fb2c733e74ae595d055cdf0ad83abcab9341d6adabe","src/replacement.rs":"7660b34a53f8c1ca2bdfa0e51e843ec28326950952ad8bc96569feb93ac62308","src/shift_jis.rs":"6951ae67e36b1a12fa3a30734957f444d8b1b4ae0e2bde52060b29bd0f16d9d9","src/simd_funcs.rs":"05c6e77af74bfe73cd39a752067c11425d6b46e5da419910f54bf75a5c02a984","src/single_byte.rs":"3ad87116fb339434a4b58e8f2b15485f2b66b9f7814d708f16194ed08f6d6ccf","src/test_data/big5_in.txt":"4c5a8691f8dc717311889c63894026d2fb62725a86c4208ca274a9cc8d42a503","src/test_data/big5_in_ref.txt":"99d399e17750cf9c7cf30bb253dbfe35b81c4fcbdead93cfa48b1429213473c7","src/test_data/big5_out.txt":"6193ca97c297aa20e09396038d18e938bb7ea331c26f0f2454097296723a0b13","src/test_data/big5_out_ref.txt":"36567691f557df144f6cc520015a87038dfa156f296fcf103b56ae9a718be1fc","src/test_data/euc_kr_in.txt":"c86a7224f3215fa0d04e685622a752fdc72763e8ae076230c7fd62de57ec4074","src/test_data/euc_kr_in_ref.txt":"1f419f4ca47d708b54c73c461545a022ae2e20498fdbf8005a483d752a204883","src/test_data/euc_kr_out.txt":"e7f32e026f70be1e1b58e0047baf7d3d2c520269c4f9b9992e158b4decb0a1a3","src/test_data/euc_kr_out_ref.txt":"c9907857980b20b8e9e3b584482ed6567a2be6185d72237b6322f0404944924e","src/test_data/gb18030_in.txt":"ab7231b2d3e9afacdbd7d7f3b9e5361a7ff9f7e1cfdb4f3bd905b9362b309e53","src/test_data/gb18030_in_ref.txt":"dc5069421adca2043c55f5012b55a76fdff651d22e6e699fd0978f8d5706815c","src/test_data/gb18030_out.txt":"f0208d527f5ca63de7d9a0323be8d5cf12d8a104b2943d92c2701f0c3364dac1","src/test_data/gb18030_out_ref.txt":"6819fe47627e4ea01027003fc514b9f21a1322e732d7f1fb92cc6c5455bc6c07","src/test_data/iso_2022_jp_in.txt":"cd24bbdcb1834e25db54646fbf4c41560a13dc7540f6be3dba4f5d97d44513af","src/test_data/iso_2022_jp_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/iso_2022_jp_out.txt":"9b6f015329dda6c3f9ee5ce6dbd6fa9c89acc21283e886836c78b8d833480c21","src/test_data/iso_2022_jp_out_ref.txt":"78cb260093a20116ad9a42f43b05d1848c5ab100b6b9a850749809e943884b35","src/test_data/jis0208_in.txt":"6df3030553ffb0a6615bb33dc8ea9dca6d9623a9028e2ffec754ce3c3da824cc","src/test_data/jis0208_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/jis0208_out.txt":"4ec24477e1675ce750733bdc3c5add1cd27b6bd4ce1f09289564646e9654e857","src/test_data/jis0208_out_ref.txt":"c3e1cef5032b2b1d93a406f31ff940c4e2dfe8859b8b17ca2761fee7a75a0e48","src/test_data/jis0212_in.txt":"c011f0dd72bd7c8cd922df9374ef8d2769a77190514c77f6c62b415852eeb9fe","src/test_data/jis0212_in_ref.txt":"7d9458b3d2f73e7092a7f505c08ce1d233dde18aa679fbcf9889256239cc9e06","src/test_data/shift_jis_in.txt":"02e389ccef0dd2122e63f503899402cb7f797912c2444cc80ab93131116c5524","src/test_data/shift_jis_in_ref.txt":"512f985950ca902e643c88682dba9708b7c38d3c5ec2925168ab00ac94ab19f9","src/test_data/shift_jis_out.txt":"5fbc44da7bf639bf6cfe0fa1fd3eba7102b88f81919c9ea991302712f69426fb","src/test_data/shift_jis_out_ref.txt":"466322c6fed8286c64582731755290c2296508efdd258826e6279686649b481f","src/test_labels_names.rs":"23a2e11b02b3b8d15fb5613a625e3edb2c61e70e3c581abfd638719a4088200d","src/testing.rs":"f59e671e95a98a56f6b573e8c6be4d71e670bf52f7e20eb1605d990aafa1894e","src/utf_16.rs":"c071a147fad38d750c2c247e141b76b929a48007b99f26b2922b9caecdaf2f25","src/utf_8.rs":"7b7d887b347f1aefa03246b028a36a72758a4ce76c28f3b45c19467851aa7839","src/variant.rs":"1fab5363588a1554a7169de8731ea9cded7ac63ea35caabdd1c27a8dde68c27b","src/x_user_defined.rs":"9456ca46168ef86c98399a2536f577ef7be3cdde90c0c51392d8ac48519d3fae"},"package":"b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"} \ No newline at end of file
diff --git a/third_party/rust/encoding_rs/Cargo.toml b/third_party/rust/encoding_rs/Cargo.toml
index e9fd6c0af2..08bb61136b 100644
--- a/third_party/rust/encoding_rs/Cargo.toml
+++ b/third_party/rust/encoding_rs/Cargo.toml
@@ -11,8 +11,9 @@
[package]
edition = "2018"
+rust-version = "1.36"
name = "encoding_rs"
-version = "0.8.33"
+version = "0.8.34"
authors = ["Henri Sivonen <hsivonen@hsivonen.fi>"]
description = "A Gecko-oriented implementation of the Encoding Standard"
homepage = "https://docs.rs/encoding_rs/"
@@ -36,13 +37,13 @@ repository = "https://github.com/hsivonen/encoding_rs"
[profile.release]
lto = true
+[dependencies.any_all_workaround]
+version = "0.1.0"
+optional = true
+
[dependencies.cfg-if]
version = "1.0"
-[dependencies.packed_simd]
-version = "0.3.9"
-optional = true
-
[dependencies.serde]
version = "1.0"
optional = true
@@ -74,10 +75,4 @@ fast-legacy-encode = [
less-slow-big5-hanzi-encode = []
less-slow-gb-hanzi-encode = []
less-slow-kanji-encode = []
-simd-accel = [
- "packed_simd",
- "packed_simd/into_bits",
-]
-
-[badges.travis-ci]
-repository = "hsivonen/encoding_rs"
+simd-accel = ["any_all_workaround"]
diff --git a/third_party/rust/encoding_rs/README.md b/third_party/rust/encoding_rs/README.md
index c0b596c951..ed0e954630 100644
--- a/third_party/rust/encoding_rs/README.md
+++ b/third_party/rust/encoding_rs/README.md
@@ -167,13 +167,15 @@ There are currently these optional cargo features:
### `simd-accel`
-Enables SIMD acceleration using the nightly-dependent `packed_simd` crate.
+Enables SIMD acceleration using the nightly-dependent `portable_simd` standard
+library feature.
This is an opt-in feature, because enabling this feature _opts out_ of Rust's
guarantees of future compilers compiling old code (aka. "stability story").
Currently, this has not been tested to be an improvement except for these
-targets:
+targets and enabling the `simd-accel` feature is expected to break the build
+on other targets:
* x86_64
* i686
@@ -185,22 +187,6 @@ above, and you are prepared _to have to revise your configuration when updating
Rust_, you should enable this feature. Otherwise, please _do not_ enable this
feature.
-_Note!_ If you are compiling for a target that does not have 128-bit SIMD
-enabled as part of the target definition and you are enabling 128-bit SIMD
-using `-C target_feature`, you need to enable the `core_arch` Cargo feature
-for `packed_simd` to compile a crates.io snapshot of `core_arch` instead of
-using the standard-library copy of `core::arch`, because the `core::arch`
-module of the pre-compiled standard library has been compiled with the
-assumption that the CPU doesn't have 128-bit SIMD. At present this applies
-mainly to 32-bit ARM targets whose first component does not include the
-substring `neon`.
-
-The encoding_rs side of things has not been properly set up for POWER,
-PowerPC, MIPS, etc., SIMD at this time, so even if you were to follow
-the advice from the previous paragraph, you probably shouldn't use
-the `simd-accel` option on the less mainstream architectures at this
-time.
-
Used by Firefox.
### `serde`
@@ -381,8 +367,9 @@ as semver-breaking, because this crate depends on `cfg-if`, which doesn't
appear to treat MSRV changes as semver-breaking, so it would be useless for
this crate to treat MSRV changes as semver-breaking.
-As of 2021-02-04, MSRV appears to be Rust 1.36.0 for using the crate and
+As of 2024-04-04, MSRV appears to be Rust 1.36.0 for using the crate and
1.42.0 for doc tests to pass without errors about the global allocator.
+With the `simd-accel` feature, the MSRV is even higher.
## Compatibility with rust-encoding
@@ -446,10 +433,17 @@ To regenerate the generated code:
- [x] Add actually fast CJK encode options.
- [ ] ~Investigate [Bob Steagall's lookup table acceleration for UTF-8](https://github.com/BobSteagall/CppNow2018/blob/master/FastConversionFromUTF-8/Fast%20Conversion%20From%20UTF-8%20with%20C%2B%2B%2C%20DFAs%2C%20and%20SSE%20Intrinsics%20-%20Bob%20Steagall%20-%20C%2B%2BNow%202018.pdf).~
- [x] Provide a build mode that works without `alloc` (with lesser API surface).
-- [ ] Migrate to `std::simd` once it is stable and declare 1.0.
+- [x] Migrate to `std::simd` ~once it is stable and declare 1.0.~
+- [ ] Migrate `unsafe` slice access by larger types than `u8`/`u16` to `align_to`.
## Release Notes
+### 0.8.34
+
+* Use the `portable_simd` nightly feature of the standard library instead of the `packed_simd` crate. Only affects the `simd-accel` optional nightly feature.
+* Internal documentation improvements and minor code improvements around `unsafe`.
+* Added `rust-version` to `Cargo.toml`.
+
### 0.8.33
* Use `packed_simd` instead of `packed_simd_2` again now that updates are back under the `packed_simd` name. Only affects the `simd-accel` optional nightly feature.
diff --git a/third_party/rust/encoding_rs/src/ascii.rs b/third_party/rust/encoding_rs/src/ascii.rs
index 90644de7a4..80233f285e 100644
--- a/third_party/rust/encoding_rs/src/ascii.rs
+++ b/third_party/rust/encoding_rs/src/ascii.rs
@@ -51,6 +51,8 @@ cfg_if! {
}
}
+// Safety invariants for masks: data & mask = 0 for valid ASCII or basic latin utf-16
+
// `as` truncates, so works on 32-bit, too.
#[allow(dead_code)]
pub const ASCII_MASK: usize = 0x8080_8080_8080_8080u64 as usize;
@@ -62,6 +64,9 @@ pub const BASIC_LATIN_MASK: usize = 0xFF80_FF80_FF80_FF80u64 as usize;
#[allow(unused_macros)]
macro_rules! ascii_naive {
($name:ident, $src_unit:ty, $dst_unit:ty) => {
+ /// Safety: src and dst must have len_unit elements and be aligned
+ /// Safety-usable invariant: will return Some() when it fails
+ /// to convert. The first value will be a u8 that is > 127.
#[inline(always)]
pub unsafe fn $name(
src: *const $src_unit,
@@ -71,10 +76,13 @@ macro_rules! ascii_naive {
// Yes, manually omitting the bound check here matters
// a lot for perf.
for i in 0..len {
+ // Safety: len invariant used here
let code_unit = *(src.add(i));
+ // Safety: Upholds safety-usable invariant here
if code_unit > 127 {
return Some((code_unit, i));
}
+ // Safety: len invariant used here
*(dst.add(i)) = code_unit as $dst_unit;
}
return None;
@@ -85,9 +93,15 @@ macro_rules! ascii_naive {
#[allow(unused_macros)]
macro_rules! ascii_alu {
($name:ident,
+ // safety invariant: src/dst MUST be u8
$src_unit:ty,
$dst_unit:ty,
+ // Safety invariant: stride_fn must consume and produce two usizes, and return the index of the first non-ascii when it fails
$stride_fn:ident) => {
+ /// Safety: src and dst must have len elements, src is valid for read, dst is valid for
+ /// write
+ /// Safety-usable invariant: will return Some() when it fails
+ /// to convert. The first value will be a u8 that is > 127.
#[cfg_attr(feature = "cargo-clippy", allow(never_loop, cast_ptr_alignment))]
#[inline(always)]
pub unsafe fn $name(
@@ -98,6 +112,7 @@ macro_rules! ascii_alu {
let mut offset = 0usize;
// This loop is only broken out of as a `goto` forward
loop {
+ // Safety: until_alignment becomes the number of bytes we need to munch until we are aligned to usize
let mut until_alignment = {
// Check if the other unit aligns if we move the narrower unit
// to alignment.
@@ -106,6 +121,7 @@ macro_rules! ascii_alu {
let src_alignment = (src as usize) & ALU_ALIGNMENT_MASK;
let dst_alignment = (dst as usize) & ALU_ALIGNMENT_MASK;
if src_alignment != dst_alignment {
+ // Safety: bails early and ends up in the naïve branch where usize-alignment doesn't matter
break;
}
(ALU_ALIGNMENT - src_alignment) & ALU_ALIGNMENT_MASK
@@ -134,25 +150,40 @@ macro_rules! ascii_alu {
// x86_64 should be using SSE2 in due course, keeping the move
// to alignment here. It would be good to test on more ARM CPUs
// and on real MIPS and POWER hardware.
+ //
+ // Safety: This is the naïve code once again, for `until_alignment` bytes
while until_alignment != 0 {
let code_unit = *(src.add(offset));
if code_unit > 127 {
+ // Safety: Upholds safety-usable invariant here
return Some((code_unit, offset));
}
*(dst.add(offset)) = code_unit as $dst_unit;
+ // Safety: offset is the number of bytes copied so far
offset += 1;
until_alignment -= 1;
}
let len_minus_stride = len - ALU_STRIDE_SIZE;
loop {
+ // Safety: num_ascii is known to be a byte index of a non-ascii byte due to stride_fn's invariant
if let Some(num_ascii) = $stride_fn(
+ // Safety: These are known to be valid and aligned since we have at
+ // least ALU_STRIDE_SIZE data in these buffers, and offset is the
+ // number of elements copied so far, which according to the
+ // until_alignment calculation above will cause both src and dst to be
+ // aligned to usize after this add
src.add(offset) as *const usize,
dst.add(offset) as *mut usize,
) {
offset += num_ascii;
+ // Safety: Upholds safety-usable invariant here by indexing into non-ascii byte
return Some((*(src.add(offset)), offset));
}
+ // Safety: offset continues to be the number of bytes copied so far, and
+ // maintains usize alignment for the next loop iteration
offset += ALU_STRIDE_SIZE;
+ // Safety: This is `offset > len - stride. This loop will continue as long as
+ // `offset <= len - stride`, which means there are `stride` bytes to still be read.
if offset > len_minus_stride {
break;
}
@@ -160,11 +191,17 @@ macro_rules! ascii_alu {
}
break;
}
+
+ // Safety: This is the naïve code, same as ascii_naive, and has no requirements
+ // other than src/dst being valid for the the right lens
while offset < len {
+ // Safety: len invariant used here
let code_unit = *(src.add(offset));
if code_unit > 127 {
+ // Safety: Upholds safety-usable invariant here
return Some((code_unit, offset));
}
+ // Safety: len invariant used here
*(dst.add(offset)) = code_unit as $dst_unit;
offset += 1;
}
@@ -176,9 +213,16 @@ macro_rules! ascii_alu {
#[allow(unused_macros)]
macro_rules! basic_latin_alu {
($name:ident,
+ // safety invariant: use u8 for src/dest for ascii, and u16 for basic_latin
$src_unit:ty,
$dst_unit:ty,
+ // safety invariant: stride function must munch ALU_STRIDE_SIZE*size(src_unit) bytes off of src and
+ // write ALU_STRIDE_SIZE*size(dst_unit) bytes to dst
$stride_fn:ident) => {
+ /// Safety: src and dst must have len elements, src is valid for read, dst is valid for
+ /// write
+ /// Safety-usable invariant: will return Some() when it fails
+ /// to convert. The first value will be a u8 that is > 127.
#[cfg_attr(
feature = "cargo-clippy",
allow(never_loop, cast_ptr_alignment, cast_lossless)
@@ -192,6 +236,8 @@ macro_rules! basic_latin_alu {
let mut offset = 0usize;
// This loop is only broken out of as a `goto` forward
loop {
+ // Safety: until_alignment becomes the number of bytes we need to munch from src/dest until we are aligned to usize
+ // We ensure basic-latin has the same alignment as ascii, starting with ascii since it is smaller.
let mut until_alignment = {
// Check if the other unit aligns if we move the narrower unit
// to alignment.
@@ -237,24 +283,37 @@ macro_rules! basic_latin_alu {
// x86_64 should be using SSE2 in due course, keeping the move
// to alignment here. It would be good to test on more ARM CPUs
// and on real MIPS and POWER hardware.
+ //
+ // Safety: This is the naïve code once again, for `until_alignment` bytes
while until_alignment != 0 {
let code_unit = *(src.add(offset));
if code_unit > 127 {
+ // Safety: Upholds safety-usable invariant here
return Some((code_unit, offset));
}
*(dst.add(offset)) = code_unit as $dst_unit;
+ // Safety: offset is the number of bytes copied so far
offset += 1;
until_alignment -= 1;
}
let len_minus_stride = len - ALU_STRIDE_SIZE;
loop {
if !$stride_fn(
+ // Safety: These are known to be valid and aligned since we have at
+ // least ALU_STRIDE_SIZE data in these buffers, and offset is the
+ // number of elements copied so far, which according to the
+ // until_alignment calculation above will cause both src and dst to be
+ // aligned to usize after this add
src.add(offset) as *const usize,
dst.add(offset) as *mut usize,
) {
break;
}
+ // Safety: offset continues to be the number of bytes copied so far, and
+ // maintains usize alignment for the next loop iteration
offset += ALU_STRIDE_SIZE;
+ // Safety: This is `offset > len - stride. This loop will continue as long as
+ // `offset <= len - stride`, which means there are `stride` bytes to still be read.
if offset > len_minus_stride {
break;
}
@@ -262,11 +321,15 @@ macro_rules! basic_latin_alu {
}
break;
}
+ // Safety: This is the naïve code once again, for leftover bytes
while offset < len {
+ // Safety: len invariant used here
let code_unit = *(src.add(offset));
if code_unit > 127 {
+ // Safety: Upholds safety-usable invariant here
return Some((code_unit, offset));
}
+ // Safety: len invariant used here
*(dst.add(offset)) = code_unit as $dst_unit;
offset += 1;
}
@@ -277,7 +340,11 @@ macro_rules! basic_latin_alu {
#[allow(unused_macros)]
macro_rules! latin1_alu {
+ // safety invariant: stride function must munch ALU_STRIDE_SIZE*size(src_unit) bytes off of src and
+ // write ALU_STRIDE_SIZE*size(dst_unit) bytes to dst
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_fn:ident) => {
+ /// Safety: src and dst must have len elements, src is valid for read, dst is valid for
+ /// write
#[cfg_attr(
feature = "cargo-clippy",
allow(never_loop, cast_ptr_alignment, cast_lossless)
@@ -287,6 +354,8 @@ macro_rules! latin1_alu {
let mut offset = 0usize;
// This loop is only broken out of as a `goto` forward
loop {
+ // Safety: until_alignment becomes the number of bytes we need to munch from src/dest until we are aligned to usize
+ // We ensure the UTF-16 side has the same alignment as the Latin-1 side, starting with Latin-1 since it is smaller.
let mut until_alignment = {
if ::core::mem::size_of::<$src_unit>() < ::core::mem::size_of::<$dst_unit>() {
// unpack
@@ -313,19 +382,30 @@ macro_rules! latin1_alu {
}
};
if until_alignment + ALU_STRIDE_SIZE <= len {
+ // Safety: This is the naïve code once again, for `until_alignment` bytes
while until_alignment != 0 {
let code_unit = *(src.add(offset));
*(dst.add(offset)) = code_unit as $dst_unit;
+ // Safety: offset is the number of bytes copied so far
offset += 1;
until_alignment -= 1;
}
let len_minus_stride = len - ALU_STRIDE_SIZE;
loop {
$stride_fn(
+ // Safety: These are known to be valid and aligned since we have at
+ // least ALU_STRIDE_SIZE data in these buffers, and offset is the
+ // number of elements copied so far, which according to the
+ // until_alignment calculation above will cause both src and dst to be
+ // aligned to usize after this add
src.add(offset) as *const usize,
dst.add(offset) as *mut usize,
);
+ // Safety: offset continues to be the number of bytes copied so far, and
+ // maintains usize alignment for the next loop iteration
offset += ALU_STRIDE_SIZE;
+ // Safety: This is `offset > len - stride. This loop will continue as long as
+ // `offset <= len - stride`, which means there are `stride` bytes to still be read.
if offset > len_minus_stride {
break;
}
@@ -333,7 +413,9 @@ macro_rules! latin1_alu {
}
break;
}
+ // Safety: This is the naïve code once again, for leftover bytes
while offset < len {
+ // Safety: len invariant used here
let code_unit = *(src.add(offset));
*(dst.add(offset)) = code_unit as $dst_unit;
offset += 1;
@@ -348,11 +430,19 @@ macro_rules! ascii_simd_check_align {
$name:ident,
$src_unit:ty,
$dst_unit:ty,
+ // Safety: This function must require aligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_both_aligned:ident,
+ // Safety: This function must require aligned/unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_src_aligned:ident,
+ // Safety: This function must require unaligned/aligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_dst_aligned:ident,
+ // Safety: This function must require unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_neither_aligned:ident
) => {
+ /// Safety: src/dst must be valid for reads/writes of `len` elements of their units.
+ ///
+ /// Safety-usable invariant: will return Some() when it encounters non-ASCII, with the first element in the Some being
+ /// guaranteed to be non-ASCII (> 127), and the second being the offset where it is found
#[inline(always)]
pub unsafe fn $name(
src: *const $src_unit,
@@ -360,6 +450,7 @@ macro_rules! ascii_simd_check_align {
len: usize,
) -> Option<($src_unit, usize)> {
let mut offset = 0usize;
+ // Safety: if this check succeeds we're valid for reading/writing at least `SIMD_STRIDE_SIZE` elements.
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
// XXX Should we first process one stride unconditionally as unaligned to
@@ -368,23 +459,29 @@ macro_rules! ascii_simd_check_align {
// on Haswell, it would make sense to just use unaligned and not bother
// checking. Need to benchmark older architectures before deciding.
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
+ // Safety: checking whether src is aligned
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
+ // Safety: Checking whether dst is aligned
if dst_masked == 0 {
loop {
+ // Safety: We're valid to read/write SIMD_STRIDE_SIZE elements and have the appropriate alignments
if !$stride_both_aligned(src.add(offset), dst.add(offset)) {
break;
}
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE` which means we always have at least `SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride {
break;
}
}
} else {
loop {
+ // Safety: We're valid to read/write SIMD_STRIDE_SIZE elements and have the appropriate alignments
if !$stride_src_aligned(src.add(offset), dst.add(offset)) {
break;
}
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE` which means we always have at least `SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride {
break;
}
@@ -393,20 +490,24 @@ macro_rules! ascii_simd_check_align {
} else {
if dst_masked == 0 {
loop {
+ // Safety: We're valid to read/write SIMD_STRIDE_SIZE elements and have the appropriate alignments
if !$stride_dst_aligned(src.add(offset), dst.add(offset)) {
break;
}
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE` which means we always have at least `SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride {
break;
}
}
} else {
loop {
+ // Safety: We're valid to read/write SIMD_STRIDE_SIZE elements and have the appropriate alignments
if !$stride_neither_aligned(src.add(offset), dst.add(offset)) {
break;
}
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE` which means we always have at least `SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride {
break;
}
@@ -415,8 +516,10 @@ macro_rules! ascii_simd_check_align {
}
}
while offset < len {
+ // Safety: uses len invariant here and below
let code_unit = *(src.add(offset));
if code_unit > 127 {
+ // Safety: upholds safety-usable invariant
return Some((code_unit, offset));
}
*(dst.add(offset)) = code_unit as $dst_unit;
@@ -433,13 +536,21 @@ macro_rules! ascii_simd_check_align_unrolled {
$name:ident,
$src_unit:ty,
$dst_unit:ty,
+ // Safety: This function must require aligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_both_aligned:ident,
+ // Safety: This function must require aligned/unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_src_aligned:ident,
+ // Safety: This function must require unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_neither_aligned:ident,
+ // Safety: This function must require aligned src/dest that are valid for reading/writing 2*SIMD_STRIDE_SIZE src_unit/dst_unit
$double_stride_both_aligned:ident,
+ // Safety: This function must require aligned/unaligned src/dest that are valid for reading/writing 2*SIMD_STRIDE_SIZE src_unit/dst_unit
$double_stride_src_aligned:ident
) => {
- #[inline(always)]
+ /// Safety: src/dst must be valid for reads/writes of `len` elements of their units.
+ ///
+ /// Safety-usable invariant: will return Some() when it encounters non-ASCII, with the first element in the Some being
+ /// guaranteed to be non-ASCII (> 127), and the second being the offset where it is found #[inline(always)]
pub unsafe fn $name(
src: *const $src_unit,
dst: *mut $dst_unit,
@@ -450,8 +561,10 @@ macro_rules! ascii_simd_check_align_unrolled {
// This loop is only broken out of as a goto forward without
// actually looping
'outer: loop {
+ // Safety: if this check succeeds we're valid for reading/writing at least `SIMD_STRIDE_SIZE` elements.
if SIMD_STRIDE_SIZE <= len {
// First, process one unaligned
+ // Safety: this is safe to call since we're valid for this read/write
if !$stride_neither_aligned(src, dst) {
break 'outer;
}
@@ -461,37 +574,54 @@ macro_rules! ascii_simd_check_align_unrolled {
// there will be enough more to justify more expense
// in the case of non-ASCII.
// Use aligned reads for the sake of old microachitectures.
+ //
+ // Safety: this correctly calculates the number of src_units that need to be read before the remaining list is aligned.
+ // This is less that SIMD_ALIGNMENT, which is also SIMD_STRIDE_SIZE (as documented)
let until_alignment = ((SIMD_ALIGNMENT
- ((src.add(offset) as usize) & SIMD_ALIGNMENT_MASK))
& SIMD_ALIGNMENT_MASK)
/ unit_size;
- // This addition won't overflow, because even in the 32-bit PAE case the
+ // Safety: This addition won't overflow, because even in the 32-bit PAE case the
// address space holds enough code that the slice length can't be that
// close to address space size.
// offset now equals SIMD_STRIDE_SIZE, hence times 3 below.
+ //
+ // Safety: if this check succeeds we're valid for reading/writing at least `2 * SIMD_STRIDE_SIZE` elements plus `until_alignment`.
+ // The extra SIMD_STRIDE_SIZE in the condition is because `offset` is already `SIMD_STRIDE_SIZE`.
if until_alignment + (SIMD_STRIDE_SIZE * 3) <= len {
if until_alignment != 0 {
+ // Safety: this is safe to call since we're valid for this read/write (and more), and don't care about alignment
+ // This will copy over bytes that get decoded twice since it's not incrementing `offset` by SIMD_STRIDE_SIZE. This is fine.
if !$stride_neither_aligned(src.add(offset), dst.add(offset)) {
break;
}
offset += until_alignment;
}
+ // Safety: At this point we're valid for reading/writing 2*SIMD_STRIDE_SIZE elements
+ // Safety: Now `offset` is aligned for `src`
let len_minus_stride_times_two = len - (SIMD_STRIDE_SIZE * 2);
+ // Safety: This is whether dst is aligned
let dst_masked = (dst.add(offset) as usize) & SIMD_ALIGNMENT_MASK;
if dst_masked == 0 {
loop {
+ // Safety: both are aligned, we can call the aligned function. We're valid for reading/writing double stride from the initial condition
+ // and the loop break condition below
if let Some(advance) =
$double_stride_both_aligned(src.add(offset), dst.add(offset))
{
offset += advance;
let code_unit = *(src.add(offset));
+ // Safety: uses safety-usable invariant on ascii_to_ascii_simd_double_stride to return
+ // guaranteed non-ascii
return Some((code_unit, offset));
}
offset += SIMD_STRIDE_SIZE * 2;
+ // Safety: This is `offset > len - 2 * SIMD_STRIDE_SIZE` which means we always have at least `2 * SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride_times_two {
break;
}
}
+ // Safety: We're valid for reading/writing one more, and can still assume alignment
if offset + SIMD_STRIDE_SIZE <= len {
if !$stride_both_aligned(src.add(offset), dst.add(offset)) {
break 'outer;
@@ -500,18 +630,25 @@ macro_rules! ascii_simd_check_align_unrolled {
}
} else {
loop {
+ // Safety: only src is aligned here. We're valid for reading/writing double stride from the initial condition
+ // and the loop break condition below
if let Some(advance) =
$double_stride_src_aligned(src.add(offset), dst.add(offset))
{
offset += advance;
let code_unit = *(src.add(offset));
+ // Safety: uses safety-usable invariant on ascii_to_ascii_simd_double_stride to return
+ // guaranteed non-ascii
return Some((code_unit, offset));
}
offset += SIMD_STRIDE_SIZE * 2;
+ // Safety: This is `offset > len - 2 * SIMD_STRIDE_SIZE` which means we always have at least `2 * SIMD_STRIDE_SIZE` elements to munch next time.
+
if offset > len_minus_stride_times_two {
break;
}
}
+ // Safety: We're valid for reading/writing one more, and can still assume alignment
if offset + SIMD_STRIDE_SIZE <= len {
if !$stride_src_aligned(src.add(offset), dst.add(offset)) {
break 'outer;
@@ -522,11 +659,13 @@ macro_rules! ascii_simd_check_align_unrolled {
} else {
// At most two iterations, so unroll
if offset + SIMD_STRIDE_SIZE <= len {
+ // Safety: The check above ensures we're allowed to read/write this, and we don't use alignment
if !$stride_neither_aligned(src.add(offset), dst.add(offset)) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset + SIMD_STRIDE_SIZE <= len {
+ // Safety: The check above ensures we're allowed to read/write this, and we don't use alignment
if !$stride_neither_aligned(src.add(offset), dst.add(offset)) {
break;
}
@@ -538,8 +677,10 @@ macro_rules! ascii_simd_check_align_unrolled {
break 'outer;
}
while offset < len {
+ // Safety: relies straightforwardly on the `len` invariant
let code_unit = *(src.add(offset));
if code_unit > 127 {
+ // Safety-usable invariant upheld here
return Some((code_unit, offset));
}
*(dst.add(offset)) = code_unit as $dst_unit;
@@ -556,30 +697,45 @@ macro_rules! latin1_simd_check_align {
$name:ident,
$src_unit:ty,
$dst_unit:ty,
+ // Safety: This function must require aligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_both_aligned:ident,
+ // Safety: This function must require aligned/unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_src_aligned:ident,
+ // Safety: This function must require unaligned/aligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_dst_aligned:ident,
+ // Safety: This function must require unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_neither_aligned:ident
+
) => {
+ /// Safety: src/dst must be valid for reads/writes of `len` elements of their units.
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
+ // Safety: if this check succeeds we're valid for reading/writing at least `SIMD_STRIDE_SIZE` elements.
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
+ // Whether dst is aligned
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
+ // Whether src is aligned
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
if dst_masked == 0 {
loop {
+ // Safety: Both were aligned, we can use the aligned function
$stride_both_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE`, which means in the next iteration we're valid for
+ // reading/writing at least SIMD_STRIDE_SIZE elements.
if offset > len_minus_stride {
break;
}
}
} else {
loop {
+ // Safety: src was aligned, dst was not
$stride_src_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE`, which means in the next iteration we're valid for
+ // reading/writing at least SIMD_STRIDE_SIZE elements.
if offset > len_minus_stride {
break;
}
@@ -588,16 +744,22 @@ macro_rules! latin1_simd_check_align {
} else {
if dst_masked == 0 {
loop {
+ // Safety: src was aligned, dst was not
$stride_dst_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE`, which means in the next iteration we're valid for
+ // reading/writing at least SIMD_STRIDE_SIZE elements.
if offset > len_minus_stride {
break;
}
}
} else {
loop {
+ // Safety: Neither were aligned
$stride_neither_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE`, which means in the next iteration we're valid for
+ // reading/writing at least SIMD_STRIDE_SIZE elements.
if offset > len_minus_stride {
break;
}
@@ -606,6 +768,7 @@ macro_rules! latin1_simd_check_align {
}
}
while offset < len {
+ // Safety: relies straightforwardly on the `len` invariant
let code_unit = *(src.add(offset));
*(dst.add(offset)) = code_unit as $dst_unit;
offset += 1;
@@ -620,56 +783,74 @@ macro_rules! latin1_simd_check_align_unrolled {
$name:ident,
$src_unit:ty,
$dst_unit:ty,
+ // Safety: This function must require aligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_both_aligned:ident,
+ // Safety: This function must require aligned/unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_src_aligned:ident,
+ // Safety: This function must require unaligned/aligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_dst_aligned:ident,
+ // Safety: This function must require unaligned src/dest that are valid for reading/writing SIMD_STRIDE_SIZE src_unit/dst_unit
$stride_neither_aligned:ident
) => {
+ /// Safety: src/dst must be valid for reads/writes of `len` elements of their units.
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let unit_size = ::core::mem::size_of::<$src_unit>();
let mut offset = 0usize;
+ // Safety: if this check succeeds we're valid for reading/writing at least `SIMD_STRIDE_SIZE` elements.
if SIMD_STRIDE_SIZE <= len {
+ // Safety: this correctly calculates the number of src_units that need to be read before the remaining list is aligned.
+ // This is by definition less than SIMD_STRIDE_SIZE.
let mut until_alignment = ((SIMD_STRIDE_SIZE
- ((src as usize) & SIMD_ALIGNMENT_MASK))
& SIMD_ALIGNMENT_MASK)
/ unit_size;
while until_alignment != 0 {
+ // Safety: This is a straightforward copy, since until_alignment is < SIMD_STRIDE_SIZE < len, this is in-bounds
*(dst.add(offset)) = *(src.add(offset)) as $dst_unit;
offset += 1;
until_alignment -= 1;
}
+ // Safety: here offset will be `until_alignment`, i.e. enough to align `src`.
let len_minus_stride = len - SIMD_STRIDE_SIZE;
+ // Safety: if this check succeeds we're valid for reading/writing at least `2 * SIMD_STRIDE_SIZE` elements.
if offset + SIMD_STRIDE_SIZE * 2 <= len {
let len_minus_stride_times_two = len_minus_stride - SIMD_STRIDE_SIZE;
+ // Safety: at this point src is known to be aligned at offset, dst is not.
if (dst.add(offset) as usize) & SIMD_ALIGNMENT_MASK == 0 {
loop {
+ // Safety: We checked alignment of dst above, we can use the alignment functions. We're allowed to read/write 2*SIMD_STRIDE_SIZE elements, which we do.
$stride_both_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
$stride_both_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - 2 * SIMD_STRIDE_SIZE` which means we always have at least `2 * SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride_times_two {
break;
}
}
} else {
loop {
+ // Safety: we ensured alignment of src already.
$stride_src_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
$stride_src_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - 2 * SIMD_STRIDE_SIZE` which means we always have at least `2 * SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride_times_two {
break;
}
}
}
}
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE` which means we are valid to munch SIMD_STRIDE_SIZE more elements, which we do
if offset < len_minus_stride {
$stride_src_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
}
}
while offset < len {
+ // Safety: uses len invariant here and below
let code_unit = *(src.add(offset));
// On x86_64, this loop autovectorizes but in the pack
// case there are instructions whose purpose is to make sure
@@ -693,7 +874,12 @@ macro_rules! latin1_simd_check_align_unrolled {
#[allow(unused_macros)]
macro_rules! ascii_simd_unalign {
+ // Safety: stride_neither_aligned must be a function that requires src/dest be valid for unaligned reads/writes for SIMD_STRIDE_SIZE elements of type src_unit/dest_unit
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_neither_aligned:ident) => {
+ /// Safety: src and dst must be valid for reads/writes of len elements of type src_unit/dst_unit
+ ///
+ /// Safety-usable invariant: will return Some() when it encounters non-ASCII, with the first element in the Some being
+ /// guaranteed to be non-ASCII (> 127), and the second being the offset where it is found
#[inline(always)]
pub unsafe fn $name(
src: *const $src_unit,
@@ -701,21 +887,26 @@ macro_rules! ascii_simd_unalign {
len: usize,
) -> Option<($src_unit, usize)> {
let mut offset = 0usize;
+ // Safety: if this check succeeds we're valid for reading/writing at least `stride` elements.
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
+ // Safety: We know we're valid for `stride` reads/writes, so we can call this function. We don't need alignment.
if !$stride_neither_aligned(src.add(offset), dst.add(offset)) {
break;
}
offset += SIMD_STRIDE_SIZE;
+ // This is `offset > len - stride` which means we always have at least `stride` elements to munch next time.
if offset > len_minus_stride {
break;
}
}
}
while offset < len {
+ // Safety: Uses len invariant here and below
let code_unit = *(src.add(offset));
if code_unit > 127 {
+ // Safety-usable invariant upheld here
return Some((code_unit, offset));
}
*(dst.add(offset)) = code_unit as $dst_unit;
@@ -728,21 +919,27 @@ macro_rules! ascii_simd_unalign {
#[allow(unused_macros)]
macro_rules! latin1_simd_unalign {
+ // Safety: stride_neither_aligned must be a function that requires src/dest be valid for unaligned reads/writes for SIMD_STRIDE_SIZE elements of type src_unit/dest_unit
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_neither_aligned:ident) => {
+ /// Safety: src and dst must be valid for unaligned reads/writes of len elements of type src_unit/dst_unit
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
+ // Safety: if this check succeeds we're valid for reading/writing at least `stride` elements.
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
+ // Safety: We know we're valid for `stride` reads/writes, so we can call this function. We don't need alignment.
$stride_neither_aligned(src.add(offset), dst.add(offset));
offset += SIMD_STRIDE_SIZE;
+ // This is `offset > len - stride` which means we always have at least `stride` elements to munch next time.
if offset > len_minus_stride {
break;
}
}
}
while offset < len {
+ // Safety: Uses len invariant here
let code_unit = *(src.add(offset));
*(dst.add(offset)) = code_unit as $dst_unit;
offset += 1;
@@ -753,7 +950,11 @@ macro_rules! latin1_simd_unalign {
#[allow(unused_macros)]
macro_rules! ascii_to_ascii_simd_stride {
+ // Safety: load/store must be valid for 16 bytes of read/write, which may be unaligned. (candidates: `(load|store)(16|8)_(unaligned|aligned)` functions)
($name:ident, $load:ident, $store:ident) => {
+ /// Safety: src and dst must be valid for 16 bytes of read/write according to
+ /// the $load/$store fn, which may allow for unaligned reads/writes or require
+ /// alignment to either 16x8 or u8x16.
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u8) -> bool {
let simd = $load(src);
@@ -768,19 +969,32 @@ macro_rules! ascii_to_ascii_simd_stride {
#[allow(unused_macros)]
macro_rules! ascii_to_ascii_simd_double_stride {
+ // Safety: store must be valid for 32 bytes of write, which may be unaligned (candidates: `store(8|16)_(aligned|unaligned)`)
($name:ident, $store:ident) => {
+ /// Safety: src must be valid for 32 bytes of aligned u8x16 read
+ /// dst must be valid for 32 bytes of unaligned write according to
+ /// the $store fn, which may allow for unaligned writes or require
+ /// alignment to either 16x8 or u8x16.
+ ///
+ /// Safety-usable invariant: Returns Some(index) if the element at `index` is invalid ASCII
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u8) -> Option<usize> {
let first = load16_aligned(src);
let second = load16_aligned(src.add(SIMD_STRIDE_SIZE));
$store(dst, first);
if unlikely(!simd_is_ascii(first | second)) {
+ // Safety: mask_ascii produces a mask of all the high bits.
let mask_first = mask_ascii(first);
if mask_first != 0 {
+ // Safety: on little endian systems this will be the number of ascii bytes
+ // before the first non-ascii, i.e. valid for indexing src
+ // TODO SAFETY: What about big-endian systems?
return Some(mask_first.trailing_zeros() as usize);
}
$store(dst.add(SIMD_STRIDE_SIZE), second);
let mask_second = mask_ascii(second);
+ // Safety: on little endian systems this will be the number of ascii bytes
+ // before the first non-ascii, i.e. valid for indexing src
return Some(SIMD_STRIDE_SIZE + mask_second.trailing_zeros() as usize);
}
$store(dst.add(SIMD_STRIDE_SIZE), second);
@@ -791,7 +1005,11 @@ macro_rules! ascii_to_ascii_simd_double_stride {
#[allow(unused_macros)]
macro_rules! ascii_to_basic_latin_simd_stride {
+ // Safety: load/store must be valid for 16 bytes of read/write, which may be unaligned. (candidates: `(load|store)(16|8)_(unaligned|aligned)` functions)
($name:ident, $load:ident, $store:ident) => {
+ /// Safety: src and dst must be valid for 16/32 bytes of read/write according to
+ /// the $load/$store fn, which may allow for unaligned reads/writes or require
+ /// alignment to either 16x8 or u8x16.
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u16) -> bool {
let simd = $load(src);
@@ -808,13 +1026,18 @@ macro_rules! ascii_to_basic_latin_simd_stride {
#[allow(unused_macros)]
macro_rules! ascii_to_basic_latin_simd_double_stride {
+ // Safety: store must be valid for 16 bytes of write, which may be unaligned
($name:ident, $store:ident) => {
+ /// Safety: src must be valid for 2*SIMD_STRIDE_SIZE bytes of aligned reads,
+ /// aligned to either 16x8 or u8x16.
+ /// dst must be valid for 2*SIMD_STRIDE_SIZE bytes of aligned or unaligned reads
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u16) -> Option<usize> {
let first = load16_aligned(src);
let second = load16_aligned(src.add(SIMD_STRIDE_SIZE));
let (a, b) = simd_unpack(first);
$store(dst, a);
+ // Safety: divide by 2 since it's a u16 pointer
$store(dst.add(SIMD_STRIDE_SIZE / 2), b);
if unlikely(!simd_is_ascii(first | second)) {
let mask_first = mask_ascii(first);
@@ -837,7 +1060,11 @@ macro_rules! ascii_to_basic_latin_simd_double_stride {
#[allow(unused_macros)]
macro_rules! unpack_simd_stride {
+ // Safety: load/store must be valid for 16 bytes of read/write, which may be unaligned. (candidates: `(load|store)(16|8)_(unaligned|aligned)` functions)
($name:ident, $load:ident, $store:ident) => {
+ /// Safety: src and dst must be valid for 16 bytes of read/write according to
+ /// the $load/$store fn, which may allow for unaligned reads/writes or require
+ /// alignment to either 16x8 or u8x16.
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u16) {
let simd = $load(src);
@@ -850,7 +1077,11 @@ macro_rules! unpack_simd_stride {
#[allow(unused_macros)]
macro_rules! basic_latin_to_ascii_simd_stride {
+ // Safety: load/store must be valid for 16 bytes of read/write, which may be unaligned. (candidates: `(load|store)(16|8)_(unaligned|aligned)` functions)
($name:ident, $load:ident, $store:ident) => {
+ /// Safety: src and dst must be valid for 32/16 bytes of read/write according to
+ /// the $load/$store fn, which may allow for unaligned reads/writes or require
+ /// alignment to either 16x8 or u8x16.
#[inline(always)]
pub unsafe fn $name(src: *const u16, dst: *mut u8) -> bool {
let first = $load(src);
@@ -867,7 +1098,11 @@ macro_rules! basic_latin_to_ascii_simd_stride {
#[allow(unused_macros)]
macro_rules! pack_simd_stride {
+ // Safety: load/store must be valid for 16 bytes of read/write, which may be unaligned. (candidates: `(load|store)(16|8)_(unaligned|aligned)` functions)
($name:ident, $load:ident, $store:ident) => {
+ /// Safety: src and dst must be valid for 32/16 bytes of read/write according to
+ /// the $load/$store fn, which may allow for unaligned reads/writes or require
+ /// alignment to either 16x8 or u8x16.
#[inline(always)]
pub unsafe fn $name(src: *const u16, dst: *mut u8) {
let first = $load(src);
@@ -893,6 +1128,8 @@ cfg_if! {
pub const ALU_ALIGNMENT_MASK: usize = 7;
+ // Safety for stride macros: We stick to the load8_aligned/etc family of functions. We consistently produce
+ // neither_unaligned variants using only unaligned inputs.
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_neither_aligned, load16_unaligned, store16_unaligned);
ascii_to_basic_latin_simd_stride!(ascii_to_basic_latin_stride_neither_aligned, load16_unaligned, store8_unaligned);
@@ -901,6 +1138,8 @@ cfg_if! {
basic_latin_to_ascii_simd_stride!(basic_latin_to_ascii_stride_neither_aligned, load8_unaligned, store16_unaligned);
pack_simd_stride!(pack_stride_neither_aligned, load8_unaligned, store16_unaligned);
+ // Safety for conversion macros: We use the unalign macro with unalign functions above. All stride functions were produced
+ // by stride macros that universally munch a single SIMD_STRIDE_SIZE worth of elements.
ascii_simd_unalign!(ascii_to_ascii, u8, u8, ascii_to_ascii_stride_neither_aligned);
ascii_simd_unalign!(ascii_to_basic_latin, u8, u16, ascii_to_basic_latin_stride_neither_aligned);
ascii_simd_unalign!(basic_latin_to_ascii, u16, u8, basic_latin_to_ascii_stride_neither_aligned);
@@ -919,6 +1158,9 @@ cfg_if! {
pub const SIMD_ALIGNMENT_MASK: usize = 15;
+ // Safety for stride macros: We stick to the load8_aligned/etc family of functions. We consistently name
+ // aligned/unaligned functions according to src/dst being aligned/unaligned
+
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_both_aligned, load16_aligned, store16_aligned);
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_src_aligned, load16_aligned, store16_unaligned);
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_dst_aligned, load16_unaligned, store16_aligned);
@@ -944,6 +1186,9 @@ cfg_if! {
pack_simd_stride!(pack_stride_dst_aligned, load8_unaligned, store16_aligned);
pack_simd_stride!(pack_stride_neither_aligned, load8_unaligned, store16_unaligned);
+ // Safety for conversion macros: We use the correct pattern of both/src/dst/neither here. All stride functions were produced
+ // by stride macros that universally munch a single SIMD_STRIDE_SIZE worth of elements.
+
ascii_simd_check_align!(ascii_to_ascii, u8, u8, ascii_to_ascii_stride_both_aligned, ascii_to_ascii_stride_src_aligned, ascii_to_ascii_stride_dst_aligned, ascii_to_ascii_stride_neither_aligned);
ascii_simd_check_align!(ascii_to_basic_latin, u8, u16, ascii_to_basic_latin_stride_both_aligned, ascii_to_basic_latin_stride_src_aligned, ascii_to_basic_latin_stride_dst_aligned, ascii_to_basic_latin_stride_neither_aligned);
ascii_simd_check_align!(basic_latin_to_ascii, u16, u8, basic_latin_to_ascii_stride_both_aligned, basic_latin_to_ascii_stride_src_aligned, basic_latin_to_ascii_stride_dst_aligned, basic_latin_to_ascii_stride_neither_aligned);
@@ -958,12 +1203,16 @@ cfg_if! {
pub const SIMD_STRIDE_SIZE: usize = 16;
+ /// Safety-usable invariant: This should be identical to SIMD_STRIDE_SIZE (used by ascii_simd_check_align_unrolled)
pub const SIMD_ALIGNMENT: usize = 16;
pub const MAX_STRIDE_SIZE: usize = 16;
pub const SIMD_ALIGNMENT_MASK: usize = 15;
+ // Safety for stride macros: We stick to the load8_aligned/etc family of functions. We consistently name
+ // aligned/unaligned functions according to src/dst being aligned/unaligned
+
ascii_to_ascii_simd_double_stride!(ascii_to_ascii_simd_double_stride_both_aligned, store16_aligned);
ascii_to_ascii_simd_double_stride!(ascii_to_ascii_simd_double_stride_src_aligned, store16_unaligned);
@@ -989,6 +1238,9 @@ cfg_if! {
pack_simd_stride!(pack_stride_both_aligned, load8_aligned, store16_aligned);
pack_simd_stride!(pack_stride_src_aligned, load8_aligned, store16_unaligned);
+ // Safety for conversion macros: We use the correct pattern of both/src/dst/neither/double_both/double_src here. All stride functions were produced
+ // by stride macros that universally munch a single SIMD_STRIDE_SIZE worth of elements.
+
ascii_simd_check_align_unrolled!(ascii_to_ascii, u8, u8, ascii_to_ascii_stride_both_aligned, ascii_to_ascii_stride_src_aligned, ascii_to_ascii_stride_neither_aligned, ascii_to_ascii_simd_double_stride_both_aligned, ascii_to_ascii_simd_double_stride_src_aligned);
ascii_simd_check_align_unrolled!(ascii_to_basic_latin, u8, u16, ascii_to_basic_latin_stride_both_aligned, ascii_to_basic_latin_stride_src_aligned, ascii_to_basic_latin_stride_neither_aligned, ascii_to_basic_latin_simd_double_stride_both_aligned, ascii_to_basic_latin_simd_double_stride_src_aligned);
@@ -998,14 +1250,21 @@ cfg_if! {
} else if #[cfg(all(target_endian = "little", target_pointer_width = "64"))] {
// Aligned ALU word, little-endian, 64-bit
+ /// Safety invariant: this is the amount of bytes consumed by
+ /// unpack_alu. This will be twice the pointer width, as it consumes two usizes.
+ /// This is also the number of bytes produced by pack_alu.
+ /// This is also the number of u16 code units produced/consumed by unpack_alu/pack_alu respectively.
pub const ALU_STRIDE_SIZE: usize = 16;
pub const MAX_STRIDE_SIZE: usize = 16;
+ // Safety invariant: this is the pointer width in bytes
pub const ALU_ALIGNMENT: usize = 8;
+ // Safety invariant: this is a mask for getting the bits of a pointer not aligned to ALU_ALIGNMENT
pub const ALU_ALIGNMENT_MASK: usize = 7;
+ /// Safety: dst must point to valid space for writing four `usize`s
#[inline(always)]
unsafe fn unpack_alu(word: usize, second_word: usize, dst: *mut usize) {
let first = ((0x0000_0000_FF00_0000usize & word) << 24) |
@@ -1024,12 +1283,14 @@ cfg_if! {
((0x00FF_0000_0000_0000usize & second_word) >> 16) |
((0x0000_FF00_0000_0000usize & second_word) >> 24) |
((0x0000_00FF_0000_0000usize & second_word) >> 32);
+ // Safety: fn invariant used here
*dst = first;
*(dst.add(1)) = second;
*(dst.add(2)) = third;
*(dst.add(3)) = fourth;
}
+ /// Safety: dst must point to valid space for writing two `usize`s
#[inline(always)]
unsafe fn pack_alu(first: usize, second: usize, third: usize, fourth: usize, dst: *mut usize) {
let word = ((0x00FF_0000_0000_0000usize & second) << 8) |
@@ -1048,20 +1309,28 @@ cfg_if! {
((0x0000_00FF_0000_0000usize & third) >> 16) |
((0x0000_0000_00FF_0000usize & third) >> 8) |
(0x0000_0000_0000_00FFusize & third);
+ // Safety: fn invariant used here
*dst = word;
*(dst.add(1)) = second_word;
}
} else if #[cfg(all(target_endian = "little", target_pointer_width = "32"))] {
// Aligned ALU word, little-endian, 32-bit
+ /// Safety invariant: this is the amount of bytes consumed by
+ /// unpack_alu. This will be twice the pointer width, as it consumes two usizes.
+ /// This is also the number of bytes produced by pack_alu.
+ /// This is also the number of u16 code units produced/consumed by unpack_alu/pack_alu respectively.
pub const ALU_STRIDE_SIZE: usize = 8;
pub const MAX_STRIDE_SIZE: usize = 8;
+ // Safety invariant: this is the pointer width in bytes
pub const ALU_ALIGNMENT: usize = 4;
+ // Safety invariant: this is a mask for getting the bits of a pointer not aligned to ALU_ALIGNMENT
pub const ALU_ALIGNMENT_MASK: usize = 3;
+ /// Safety: dst must point to valid space for writing four `usize`s
#[inline(always)]
unsafe fn unpack_alu(word: usize, second_word: usize, dst: *mut usize) {
let first = ((0x0000_FF00usize & word) << 8) |
@@ -1072,12 +1341,14 @@ cfg_if! {
(0x0000_00FFusize & second_word);
let fourth = ((0xFF00_0000usize & second_word) >> 8) |
((0x00FF_0000usize & second_word) >> 16);
+ // Safety: fn invariant used here
*dst = first;
*(dst.add(1)) = second;
*(dst.add(2)) = third;
*(dst.add(3)) = fourth;
}
+ /// Safety: dst must point to valid space for writing two `usize`s
#[inline(always)]
unsafe fn pack_alu(first: usize, second: usize, third: usize, fourth: usize, dst: *mut usize) {
let word = ((0x00FF_0000usize & second) << 8) |
@@ -1088,20 +1359,28 @@ cfg_if! {
((0x0000_00FFusize & fourth) << 16) |
((0x00FF_0000usize & third) >> 8) |
(0x0000_00FFusize & third);
+ // Safety: fn invariant used here
*dst = word;
*(dst.add(1)) = second_word;
}
} else if #[cfg(all(target_endian = "big", target_pointer_width = "64"))] {
// Aligned ALU word, big-endian, 64-bit
+ /// Safety invariant: this is the amount of bytes consumed by
+ /// unpack_alu. This will be twice the pointer width, as it consumes two usizes.
+ /// This is also the number of bytes produced by pack_alu.
+ /// This is also the number of u16 code units produced/consumed by unpack_alu/pack_alu respectively.
pub const ALU_STRIDE_SIZE: usize = 16;
pub const MAX_STRIDE_SIZE: usize = 16;
+ // Safety invariant: this is the pointer width in bytes
pub const ALU_ALIGNMENT: usize = 8;
+ // Safety invariant: this is a mask for getting the bits of a pointer not aligned to ALU_ALIGNMENT
pub const ALU_ALIGNMENT_MASK: usize = 7;
+ /// Safety: dst must point to valid space for writing four `usize`s
#[inline(always)]
unsafe fn unpack_alu(word: usize, second_word: usize, dst: *mut usize) {
let first = ((0xFF00_0000_0000_0000usize & word) >> 8) |
@@ -1120,12 +1399,14 @@ cfg_if! {
((0x0000_0000_00FF_0000usize & second_word) << 16) |
((0x0000_0000_0000_FF00usize & second_word) << 8) |
(0x0000_0000_0000_00FFusize & second_word);
+ // Safety: fn invariant used here
*dst = first;
*(dst.add(1)) = second;
*(dst.add(2)) = third;
*(dst.add(3)) = fourth;
}
+ /// Safety: dst must point to valid space for writing two `usize`s
#[inline(always)]
unsafe fn pack_alu(first: usize, second: usize, third: usize, fourth: usize, dst: *mut usize) {
let word = ((0x00FF0000_00000000usize & first) << 8) |
@@ -1144,20 +1425,28 @@ cfg_if! {
((0x000000FF_00000000usize & fourth) >> 16) |
((0x00000000_00FF0000usize & fourth) >> 8) |
(0x00000000_000000FFusize & fourth);
+ // Safety: fn invariant used here
*dst = word;
*(dst.add(1)) = second_word;
}
} else if #[cfg(all(target_endian = "big", target_pointer_width = "32"))] {
// Aligned ALU word, big-endian, 32-bit
+ /// Safety invariant: this is the amount of bytes consumed by
+ /// unpack_alu. This will be twice the pointer width, as it consumes two usizes.
+ /// This is also the number of bytes produced by pack_alu.
+ /// This is also the number of u16 code units produced/consumed by unpack_alu/pack_alu respectively.
pub const ALU_STRIDE_SIZE: usize = 8;
pub const MAX_STRIDE_SIZE: usize = 8;
+ // Safety invariant: this is the pointer width in bytes
pub const ALU_ALIGNMENT: usize = 4;
+ // Safety invariant: this is a mask for getting the bits of a pointer not aligned to ALU_ALIGNMENT
pub const ALU_ALIGNMENT_MASK: usize = 3;
+ /// Safety: dst must point to valid space for writing four `usize`s
#[inline(always)]
unsafe fn unpack_alu(word: usize, second_word: usize, dst: *mut usize) {
let first = ((0xFF00_0000usize & word) >> 8) |
@@ -1168,12 +1457,14 @@ cfg_if! {
((0x00FF_0000usize & second_word) >> 16);
let fourth = ((0x0000_FF00usize & second_word) << 8) |
(0x0000_00FFusize & second_word);
+ // Safety: fn invariant used here
*dst = first;
*(dst.add(1)) = second;
*(dst.add(2)) = third;
*(dst.add(3)) = fourth;
}
+ /// Safety: dst must point to valid space for writing two `usize`s
#[inline(always)]
unsafe fn pack_alu(first: usize, second: usize, third: usize, fourth: usize, dst: *mut usize) {
let word = ((0x00FF_0000usize & first) << 8) |
@@ -1184,6 +1475,7 @@ cfg_if! {
((0x0000_00FFusize & third) << 16) |
((0x00FF_0000usize & fourth) >> 8) |
(0x0000_00FFusize & fourth);
+ // Safety: fn invariant used here
*dst = word;
*(dst.add(1)) = second_word;
}
@@ -1195,6 +1487,8 @@ cfg_if! {
}
cfg_if! {
+ // Safety-usable invariant: this counts the zeroes from the "first byte" of utf-8 data packed into a usize
+ // with the target endianness
if #[cfg(target_endian = "little")] {
#[allow(dead_code)]
#[inline(always)]
@@ -1212,19 +1506,24 @@ cfg_if! {
cfg_if! {
if #[cfg(all(feature = "simd-accel", target_endian = "little", target_arch = "disabled"))] {
+ /// Safety-usable invariant: Will return the value and position of the first non-ASCII byte in the slice in a Some if found.
+ /// In other words, the first element of the Some is always `> 127`
#[inline(always)]
pub fn validate_ascii(slice: &[u8]) -> Option<(u8, usize)> {
let src = slice.as_ptr();
let len = slice.len();
let mut offset = 0usize;
+ // Safety: if this check succeeds we're valid for reading/writing at least `stride` elements.
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
+ // Safety: src at offset is valid for a `SIMD_STRIDE_SIZE` read
let simd = unsafe { load16_unaligned(src.add(offset)) };
if !simd_is_ascii(simd) {
break;
}
offset += SIMD_STRIDE_SIZE;
+ // This is `offset > len - SIMD_STRIDE_SIZE` which means we always have at least `SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride {
break;
}
@@ -1233,6 +1532,7 @@ cfg_if! {
while offset < len {
let code_unit = slice[offset];
if code_unit > 127 {
+ // Safety: Safety-usable invariant upheld here
return Some((code_unit, offset));
}
offset += 1;
@@ -1240,13 +1540,17 @@ cfg_if! {
None
}
} else if #[cfg(all(feature = "simd-accel", target_feature = "sse2"))] {
+ /// Safety-usable invariant: will return Some() when it encounters non-ASCII, with the first element in the Some being
+ /// guaranteed to be non-ASCII (> 127), and the second being the offset where it is found
#[inline(always)]
pub fn validate_ascii(slice: &[u8]) -> Option<(u8, usize)> {
let src = slice.as_ptr();
let len = slice.len();
let mut offset = 0usize;
+ // Safety: if this check succeeds we're valid for reading at least `stride` elements.
if SIMD_STRIDE_SIZE <= len {
// First, process one unaligned vector
+ // Safety: src is valid for a `SIMD_STRIDE_SIZE` read
let simd = unsafe { load16_unaligned(src) };
let mask = mask_ascii(simd);
if mask != 0 {
@@ -1255,18 +1559,26 @@ cfg_if! {
return Some((non_ascii, offset));
}
offset = SIMD_STRIDE_SIZE;
+ // Safety: Now that offset has changed we don't yet know how much it is valid for
// We have now seen 16 ASCII bytes. Let's guess that
// there will be enough more to justify more expense
// in the case of non-ASCII.
// Use aligned reads for the sake of old microachitectures.
+ // Safety: this correctly calculates the number of src_units that need to be read before the remaining list is aligned.
+ // This is by definition less than SIMD_ALIGNMENT, which is defined to be equal to SIMD_STRIDE_SIZE.
let until_alignment = unsafe { (SIMD_ALIGNMENT - ((src.add(offset) as usize) & SIMD_ALIGNMENT_MASK)) & SIMD_ALIGNMENT_MASK };
// This addition won't overflow, because even in the 32-bit PAE case the
// address space holds enough code that the slice length can't be that
// close to address space size.
// offset now equals SIMD_STRIDE_SIZE, hence times 3 below.
+ //
+ // Safety: if this check succeeds we're valid for reading at least `2 * SIMD_STRIDE_SIZE` elements plus `until_alignment`.
+ // The extra SIMD_STRIDE_SIZE in the condition is because `offset` is already `SIMD_STRIDE_SIZE`.
if until_alignment + (SIMD_STRIDE_SIZE * 3) <= len {
if until_alignment != 0 {
+ // Safety: this is safe to call since we're valid for this read (and more), and don't care about alignment
+ // This will copy over bytes that get decoded twice since it's not incrementing `offset` by SIMD_STRIDE_SIZE. This is fine.
let simd = unsafe { load16_unaligned(src.add(offset)) };
let mask = mask_ascii(simd);
if mask != 0 {
@@ -1276,53 +1588,78 @@ cfg_if! {
}
offset += until_alignment;
}
+ // Safety: At this point we're valid for reading 2*SIMD_STRIDE_SIZE elements
+ // Safety: Now `offset` is aligned for `src`
let len_minus_stride_times_two = len - (SIMD_STRIDE_SIZE * 2);
loop {
+ // Safety: We were valid for this read, and were aligned.
let first = unsafe { load16_aligned(src.add(offset)) };
let second = unsafe { load16_aligned(src.add(offset + SIMD_STRIDE_SIZE)) };
if !simd_is_ascii(first | second) {
+ // Safety: mask_ascii produces a mask of all the high bits.
let mask_first = mask_ascii(first);
if mask_first != 0 {
+ // Safety: on little endian systems this will be the number of ascii bytes
+ // before the first non-ascii, i.e. valid for indexing src
+ // TODO SAFETY: What about big-endian systems?
offset += mask_first.trailing_zeros() as usize;
} else {
let mask_second = mask_ascii(second);
+ // Safety: on little endian systems this will be the number of ascii bytes
+ // before the first non-ascii, i.e. valid for indexing src
offset += SIMD_STRIDE_SIZE + mask_second.trailing_zeros() as usize;
}
+ // Safety: We know this is non-ASCII, and can uphold the safety-usable invariant here
let non_ascii = unsafe { *src.add(offset) };
+
return Some((non_ascii, offset));
}
offset += SIMD_STRIDE_SIZE * 2;
+ // Safety: This is `offset > len - 2 * SIMD_STRIDE_SIZE` which means we always have at least `2 * SIMD_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride_times_two {
break;
}
}
+ // Safety: if this check succeeds we're valid for reading at least `SIMD_STRIDE_SIZE`
if offset + SIMD_STRIDE_SIZE <= len {
- let simd = unsafe { load16_aligned(src.add(offset)) };
- let mask = mask_ascii(simd);
+ // Safety: We were valid for this read, and were aligned.
+ let simd = unsafe { load16_aligned(src.add(offset)) };
+ // Safety: mask_ascii produces a mask of all the high bits.
+ let mask = mask_ascii(simd);
if mask != 0 {
+ // Safety: on little endian systems this will be the number of ascii bytes
+ // before the first non-ascii, i.e. valid for indexing src
offset += mask.trailing_zeros() as usize;
let non_ascii = unsafe { *src.add(offset) };
+ // Safety: We know this is non-ASCII, and can uphold the safety-usable invariant here
return Some((non_ascii, offset));
}
offset += SIMD_STRIDE_SIZE;
}
} else {
+ // Safety: this is the unaligned branch
// At most two iterations, so unroll
+ // Safety: if this check succeeds we're valid for reading at least `SIMD_STRIDE_SIZE`
if offset + SIMD_STRIDE_SIZE <= len {
+ // Safety: We're valid for this read but must use an unaligned read
let simd = unsafe { load16_unaligned(src.add(offset)) };
let mask = mask_ascii(simd);
if mask != 0 {
offset += mask.trailing_zeros() as usize;
let non_ascii = unsafe { *src.add(offset) };
+ // Safety-usable invariant upheld here (same as above)
return Some((non_ascii, offset));
}
offset += SIMD_STRIDE_SIZE;
+ // Safety: if this check succeeds we're valid for reading at least `SIMD_STRIDE_SIZE`
if offset + SIMD_STRIDE_SIZE <= len {
+ // Safety: We're valid for this read but must use an unaligned read
let simd = unsafe { load16_unaligned(src.add(offset)) };
let mask = mask_ascii(simd);
if mask != 0 {
offset += mask.trailing_zeros() as usize;
let non_ascii = unsafe { *src.add(offset) };
+ // Safety-usable invariant upheld here (same as above)
return Some((non_ascii, offset));
}
offset += SIMD_STRIDE_SIZE;
@@ -1331,8 +1668,10 @@ cfg_if! {
}
}
while offset < len {
+ // Safety: relies straightforwardly on the `len` invariant
let code_unit = unsafe { *(src.add(offset)) };
if code_unit > 127 {
+ // Safety-usable invariant upheld here
return Some((code_unit, offset));
}
offset += 1;
@@ -1340,31 +1679,40 @@ cfg_if! {
None
}
} else {
+ // Safety-usable invariant: returns byte index of first non-ascii byte
#[inline(always)]
fn find_non_ascii(word: usize, second_word: usize) -> Option<usize> {
let word_masked = word & ASCII_MASK;
let second_masked = second_word & ASCII_MASK;
if (word_masked | second_masked) == 0 {
+ // Both are ascii, invariant upheld
return None;
}
if word_masked != 0 {
let zeros = count_zeros(word_masked);
- // `zeros` now contains 7 (for the seven bits of non-ASCII)
+ // `zeros` now contains 0 to 7 (for the seven bits of masked ASCII in little endian,
+ // or up to 7 bits of non-ASCII in big endian if the first byte is non-ASCII)
// plus 8 times the number of ASCII in text order before the
// non-ASCII byte in the little-endian case or 8 times the number of ASCII in
// text order before the non-ASCII byte in the big-endian case.
let num_ascii = (zeros >> 3) as usize;
+ // Safety-usable invariant upheld here
return Some(num_ascii);
}
let zeros = count_zeros(second_masked);
- // `zeros` now contains 7 (for the seven bits of non-ASCII)
+ // `zeros` now contains 0 to 7 (for the seven bits of masked ASCII in little endian,
+ // or up to 7 bits of non-ASCII in big endian if the first byte is non-ASCII)
// plus 8 times the number of ASCII in text order before the
// non-ASCII byte in the little-endian case or 8 times the number of ASCII in
// text order before the non-ASCII byte in the big-endian case.
let num_ascii = (zeros >> 3) as usize;
+ // Safety-usable invariant upheld here
Some(ALU_ALIGNMENT + num_ascii)
}
+ /// Safety: `src` must be valid for the reads of two `usize`s
+ ///
+ /// Safety-usable invariant: will return byte index of first non-ascii byte
#[inline(always)]
unsafe fn validate_ascii_stride(src: *const usize) -> Option<usize> {
let word = *src;
@@ -1372,6 +1720,8 @@ cfg_if! {
find_non_ascii(word, second_word)
}
+ /// Safety-usable invariant: will return Some() when it encounters non-ASCII, with the first element in the Some being
+ /// guaranteed to be non-ASCII (> 127), and the second being the offset where it is found
#[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
#[inline(always)]
pub fn validate_ascii(slice: &[u8]) -> Option<(u8, usize)> {
@@ -1379,23 +1729,30 @@ cfg_if! {
let len = slice.len();
let mut offset = 0usize;
let mut until_alignment = (ALU_ALIGNMENT - ((src as usize) & ALU_ALIGNMENT_MASK)) & ALU_ALIGNMENT_MASK;
+ // Safety: If this check fails we're valid to read `until_alignment + ALU_STRIDE_SIZE` elements
if until_alignment + ALU_STRIDE_SIZE <= len {
while until_alignment != 0 {
let code_unit = slice[offset];
if code_unit > 127 {
+ // Safety-usable invairant upheld here
return Some((code_unit, offset));
}
offset += 1;
until_alignment -= 1;
}
+ // Safety: At this point we have read until_alignment elements and
+ // are valid for `ALU_STRIDE_SIZE` more.
let len_minus_stride = len - ALU_STRIDE_SIZE;
loop {
+ // Safety: we were valid for this read
let ptr = unsafe { src.add(offset) as *const usize };
if let Some(num_ascii) = unsafe { validate_ascii_stride(ptr) } {
offset += num_ascii;
+ // Safety-usable invairant upheld here using the invariant from validate_ascii_stride()
return Some((unsafe { *(src.add(offset)) }, offset));
}
offset += ALU_STRIDE_SIZE;
+ // Safety: This is `offset > ALU_STRIDE_SIZE` which means we always have at least `2 * ALU_STRIDE_SIZE` elements to munch next time.
if offset > len_minus_stride {
break;
}
@@ -1404,6 +1761,7 @@ cfg_if! {
while offset < len {
let code_unit = slice[offset];
if code_unit > 127 {
+ // Safety-usable invairant upheld here
return Some((code_unit, offset));
}
offset += 1;
@@ -1428,36 +1786,47 @@ cfg_if! {
pub const ALU_ALIGNMENT_MASK: usize = 3;
} else {
+ // Safety: src points to two valid `usize`s, dst points to four valid `usize`s
#[inline(always)]
unsafe fn unpack_latin1_stride_alu(src: *const usize, dst: *mut usize) {
+ // Safety: src safety invariant used here
let word = *src;
let second_word = *(src.add(1));
+ // Safety: dst safety invariant passed down
unpack_alu(word, second_word, dst);
}
+ // Safety: src points to four valid `usize`s, dst points to two valid `usize`s
#[inline(always)]
unsafe fn pack_latin1_stride_alu(src: *const usize, dst: *mut usize) {
+ // Safety: src safety invariant used here
let first = *src;
let second = *(src.add(1));
let third = *(src.add(2));
let fourth = *(src.add(3));
+ // Safety: dst safety invariant passed down
pack_alu(first, second, third, fourth, dst);
}
+ // Safety: src points to two valid `usize`s, dst points to four valid `usize`s
#[inline(always)]
unsafe fn ascii_to_basic_latin_stride_alu(src: *const usize, dst: *mut usize) -> bool {
+ // Safety: src safety invariant used here
let word = *src;
let second_word = *(src.add(1));
// Check if the words contains non-ASCII
if (word & ASCII_MASK) | (second_word & ASCII_MASK) != 0 {
return false;
}
+ // Safety: dst safety invariant passed down
unpack_alu(word, second_word, dst);
true
}
+ // Safety: src points four valid `usize`s, dst points to two valid `usize`s
#[inline(always)]
unsafe fn basic_latin_to_ascii_stride_alu(src: *const usize, dst: *mut usize) -> bool {
+ // Safety: src safety invariant used here
let first = *src;
let second = *(src.add(1));
let third = *(src.add(2));
@@ -1465,16 +1834,22 @@ cfg_if! {
if (first & BASIC_LATIN_MASK) | (second & BASIC_LATIN_MASK) | (third & BASIC_LATIN_MASK) | (fourth & BASIC_LATIN_MASK) != 0 {
return false;
}
+ // Safety: dst safety invariant passed down
pack_alu(first, second, third, fourth, dst);
true
}
+ // Safety: src, dst both point to two valid `usize`s each
+ // Safety-usable invariant: Will return byte index of first non-ascii byte.
#[inline(always)]
unsafe fn ascii_to_ascii_stride(src: *const usize, dst: *mut usize) -> Option<usize> {
+ // Safety: src safety invariant used here
let word = *src;
let second_word = *(src.add(1));
+ // Safety: src safety invariant used here
*dst = word;
*(dst.add(1)) = second_word;
+ // Relies on safety-usable invariant here
find_non_ascii(word, second_word)
}
@@ -1482,6 +1857,7 @@ cfg_if! {
basic_latin_alu!(basic_latin_to_ascii, u16, u8, basic_latin_to_ascii_stride_alu);
latin1_alu!(unpack_latin1, u8, u16, unpack_latin1_stride_alu);
latin1_alu!(pack_latin1, u16, u8, pack_latin1_stride_alu);
+ // Safety invariant upheld: ascii_to_ascii_stride will return byte index of first non-ascii if found
ascii_alu!(ascii_to_ascii, u8, u8, ascii_to_ascii_stride);
}
}
diff --git a/third_party/rust/encoding_rs/src/handles.rs b/third_party/rust/encoding_rs/src/handles.rs
index b5404c01d9..f44a834672 100644
--- a/third_party/rust/encoding_rs/src/handles.rs
+++ b/third_party/rust/encoding_rs/src/handles.rs
@@ -34,7 +34,7 @@ use crate::simd_funcs::*;
all(target_endian = "little", target_feature = "neon")
)
))]
-use packed_simd::u16x8;
+use core::simd::u16x8;
use super::DecoderResult;
use super::EncoderResult;
@@ -90,19 +90,23 @@ impl Endian for LittleEndian {
#[derive(Debug, Copy, Clone)]
struct UnalignedU16Slice {
+ // Safety invariant: ptr must be valid for reading 2*len bytes
ptr: *const u8,
len: usize,
}
impl UnalignedU16Slice {
+ /// Safety: ptr must be valid for reading 2*len bytes
#[inline(always)]
pub unsafe fn new(ptr: *const u8, len: usize) -> UnalignedU16Slice {
+ // Safety: field invariant passed up to caller here
UnalignedU16Slice { ptr, len }
}
#[inline(always)]
pub fn trim_last(&mut self) {
assert!(self.len > 0);
+ // Safety: invariant upheld here: a slice is still valid with a shorter len
self.len -= 1;
}
@@ -113,7 +117,9 @@ impl UnalignedU16Slice {
assert!(i < self.len);
unsafe {
let mut u: MaybeUninit<u16> = MaybeUninit::uninit();
+ // Safety: i is at most len - 1, which works here
::core::ptr::copy_nonoverlapping(self.ptr.add(i * 2), u.as_mut_ptr() as *mut u8, 2);
+ // Safety: valid read above lets us do this
u.assume_init()
}
}
@@ -121,8 +127,13 @@ impl UnalignedU16Slice {
#[cfg(feature = "simd-accel")]
#[inline(always)]
pub fn simd_at(&self, i: usize) -> u16x8 {
+ // Safety: i/len are on the scale of u16s, each one corresponds to 2 u8s
assert!(i + SIMD_STRIDE_SIZE / 2 <= self.len);
let byte_index = i * 2;
+ // Safety: load16_unaligned needs SIMD_STRIDE_SIZE=16 u8 elements to read,
+ // or 16/2 = 8 u16 elements to read.
+ // We have checked that we have at least that many above.
+
unsafe { to_u16_lanes(load16_unaligned(self.ptr.add(byte_index))) }
}
@@ -136,6 +147,7 @@ impl UnalignedU16Slice {
// XXX the return value should be restricted not to
// outlive self.
assert!(from <= self.len);
+ // Safety: This upholds the same invariant: `from` is in bounds and we're returning a shorter slice
unsafe { UnalignedU16Slice::new(self.ptr.add(from * 2), self.len - from) }
}
@@ -144,6 +156,8 @@ impl UnalignedU16Slice {
pub fn copy_bmp_to<E: Endian>(&self, other: &mut [u16]) -> Option<(u16, usize)> {
assert!(self.len <= other.len());
let mut offset = 0;
+ // Safety: SIMD_STRIDE_SIZE is measured in bytes, whereas len is in u16s. We check we can
+ // munch SIMD_STRIDE_SIZE / 2 u16s which means we can write SIMD_STRIDE_SIZE u8s
if SIMD_STRIDE_SIZE / 2 <= self.len {
let len_minus_stride = self.len - SIMD_STRIDE_SIZE / 2;
loop {
@@ -151,6 +165,7 @@ impl UnalignedU16Slice {
if E::OPPOSITE_ENDIAN {
simd = simd_byte_swap(simd);
}
+ // Safety: we have enough space on the other side to write this
unsafe {
store8_unaligned(other.as_mut_ptr().add(offset), simd);
}
@@ -158,6 +173,7 @@ impl UnalignedU16Slice {
break;
}
offset += SIMD_STRIDE_SIZE / 2;
+ // Safety: This ensures we still have space for writing SIMD_STRIDE_SIZE u8s
if offset > len_minus_stride {
break;
}
@@ -236,6 +252,7 @@ fn copy_unaligned_basic_latin_to_ascii<E: Endian>(
) -> CopyAsciiResult<usize, (u16, usize)> {
let len = ::core::cmp::min(src.len(), dst.len());
let mut offset = 0;
+ // Safety: This check ensures we are able to read/write at least SIMD_STRIDE_SIZE elements
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
@@ -249,10 +266,13 @@ fn copy_unaligned_basic_latin_to_ascii<E: Endian>(
break;
}
let packed = simd_pack(first, second);
+ // Safety: We are able to write SIMD_STRIDE_SIZE elements in this iteration
unsafe {
store16_unaligned(dst.as_mut_ptr().add(offset), packed);
}
offset += SIMD_STRIDE_SIZE;
+ // Safety: This is `offset > len - SIMD_STRIDE_SIZE`, which ensures that we can write at least SIMD_STRIDE_SIZE elements
+ // in the next iteration
if offset > len_minus_stride {
break;
}
@@ -637,7 +657,7 @@ impl<'a> Utf16Destination<'a> {
self.write_code_unit((0xDC00 + (astral & 0x3FF)) as u16);
}
#[inline(always)]
- pub fn write_surrogate_pair(&mut self, high: u16, low: u16) {
+ fn write_surrogate_pair(&mut self, high: u16, low: u16) {
self.write_code_unit(high);
self.write_code_unit(low);
}
@@ -646,6 +666,7 @@ impl<'a> Utf16Destination<'a> {
self.write_bmp_excl_ascii(combined);
self.write_bmp_excl_ascii(combining);
}
+ // Safety-usable invariant: CopyAsciiResult::GoOn will only contain bytes >=0x80
#[inline(always)]
pub fn copy_ascii_from_check_space_bmp<'b>(
&'b mut self,
@@ -659,6 +680,8 @@ impl<'a> Utf16Destination<'a> {
} else {
(DecoderResult::InputEmpty, src_remaining.len())
};
+ // Safety: This function is documented as needing valid pointers for src/dest and len, which
+ // is true since we've passed the minumum length of the two
match unsafe {
ascii_to_basic_latin(src_remaining.as_ptr(), dst_remaining.as_mut_ptr(), length)
} {
@@ -667,16 +690,20 @@ impl<'a> Utf16Destination<'a> {
self.pos += length;
return CopyAsciiResult::Stop((pending, source.pos, self.pos));
}
+ // Safety: the function is documented as returning bytes >=0x80 in the Some
Some((non_ascii, consumed)) => {
source.pos += consumed;
self.pos += consumed;
source.pos += 1; // +1 for non_ascii
+ // Safety: non-ascii bubbled out here
non_ascii
}
}
};
+ // Safety: non-ascii returned here
CopyAsciiResult::GoOn((non_ascii_ret, Utf16BmpHandle::new(self)))
}
+ // Safety-usable invariant: CopyAsciiResult::GoOn will only contain bytes >=0x80
#[inline(always)]
pub fn copy_ascii_from_check_space_astral<'b>(
&'b mut self,
@@ -691,6 +718,8 @@ impl<'a> Utf16Destination<'a> {
} else {
(DecoderResult::InputEmpty, src_remaining.len())
};
+ // Safety: This function is documented as needing valid pointers for src/dest and len, which
+ // is true since we've passed the minumum length of the two
match unsafe {
ascii_to_basic_latin(src_remaining.as_ptr(), dst_remaining.as_mut_ptr(), length)
} {
@@ -699,11 +728,13 @@ impl<'a> Utf16Destination<'a> {
self.pos += length;
return CopyAsciiResult::Stop((pending, source.pos, self.pos));
}
+ // Safety: the function is documented as returning bytes >=0x80 in the Some
Some((non_ascii, consumed)) => {
source.pos += consumed;
self.pos += consumed;
if self.pos + 1 < dst_len {
source.pos += 1; // +1 for non_ascii
+ // Safety: non-ascii bubbled out here
non_ascii
} else {
return CopyAsciiResult::Stop((
@@ -715,6 +746,7 @@ impl<'a> Utf16Destination<'a> {
}
}
};
+ // Safety: non-ascii returned here
CopyAsciiResult::GoOn((non_ascii_ret, Utf16AstralHandle::new(self)))
}
#[inline(always)]
diff --git a/third_party/rust/encoding_rs/src/lib.rs b/third_party/rust/encoding_rs/src/lib.rs
index 6cc920ef88..1faf02e6bd 100644
--- a/third_party/rust/encoding_rs/src/lib.rs
+++ b/third_party/rust/encoding_rs/src/lib.rs
@@ -689,7 +689,7 @@
//! for discussion about the UTF-16 family.
#![no_std]
-#![cfg_attr(feature = "simd-accel", feature(core_intrinsics))]
+#![cfg_attr(feature = "simd-accel", feature(core_intrinsics, portable_simd))]
#[cfg(feature = "alloc")]
#[cfg_attr(test, macro_use)]
@@ -699,17 +699,6 @@ extern crate core;
#[macro_use]
extern crate cfg_if;
-#[cfg(all(
- feature = "simd-accel",
- any(
- target_feature = "sse2",
- all(target_endian = "little", target_arch = "aarch64"),
- all(target_endian = "little", target_feature = "neon")
- )
-))]
-#[macro_use(shuffle)]
-extern crate packed_simd;
-
#[cfg(feature = "serde")]
extern crate serde;
diff --git a/third_party/rust/encoding_rs/src/mem.rs b/third_party/rust/encoding_rs/src/mem.rs
index ba8d9e3f4c..0f9f3c1977 100644
--- a/third_party/rust/encoding_rs/src/mem.rs
+++ b/third_party/rust/encoding_rs/src/mem.rs
@@ -116,6 +116,11 @@ macro_rules! by_unit_check_alu {
}
let len_minus_stride = len - ALU_ALIGNMENT / unit_size;
if offset + (4 * (ALU_ALIGNMENT / unit_size)) <= len {
+ // Safety: the above check lets us perform 4 consecutive reads of
+ // length ALU_ALIGNMENT / unit_size. ALU_ALIGNMENT is the size of usize, and unit_size
+ // is the size of the `src` pointer, so this is equal to performing four usize reads.
+ //
+ // This invariant is upheld on all loop iterations
let len_minus_unroll = len - (4 * (ALU_ALIGNMENT / unit_size));
loop {
let unroll_accu = unsafe { *(src.add(offset) as *const usize) }
@@ -134,12 +139,14 @@ macro_rules! by_unit_check_alu {
return false;
}
offset += 4 * (ALU_ALIGNMENT / unit_size);
+ // Safety: this check lets us continue to perform the 4 reads earlier
if offset > len_minus_unroll {
break;
}
}
}
while offset <= len_minus_stride {
+ // Safety: the above check lets us perform one usize read.
accu |= unsafe { *(src.add(offset) as *const usize) };
offset += ALU_ALIGNMENT / unit_size;
}
@@ -189,6 +196,11 @@ macro_rules! by_unit_check_simd {
}
let len_minus_stride = len - SIMD_STRIDE_SIZE / unit_size;
if offset + (4 * (SIMD_STRIDE_SIZE / unit_size)) <= len {
+ // Safety: the above check lets us perform 4 consecutive reads of
+ // length SIMD_STRIDE_SIZE / unit_size. SIMD_STRIDE_SIZE is the size of $simd_ty, and unit_size
+ // is the size of the `src` pointer, so this is equal to performing four $simd_ty reads.
+ //
+ // This invariant is upheld on all loop iterations
let len_minus_unroll = len - (4 * (SIMD_STRIDE_SIZE / unit_size));
loop {
let unroll_accu = unsafe { *(src.add(offset) as *const $simd_ty) }
@@ -208,6 +220,7 @@ macro_rules! by_unit_check_simd {
return false;
}
offset += 4 * (SIMD_STRIDE_SIZE / unit_size);
+ // Safety: this check lets us continue to perform the 4 reads earlier
if offset > len_minus_unroll {
break;
}
@@ -215,6 +228,7 @@ macro_rules! by_unit_check_simd {
}
let mut simd_accu = $splat;
while offset <= len_minus_stride {
+ // Safety: the above check lets us perform one $simd_ty read.
simd_accu = simd_accu | unsafe { *(src.add(offset) as *const $simd_ty) };
offset += SIMD_STRIDE_SIZE / unit_size;
}
@@ -234,8 +248,8 @@ macro_rules! by_unit_check_simd {
cfg_if! {
if #[cfg(all(feature = "simd-accel", any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))] {
use crate::simd_funcs::*;
- use packed_simd::u8x16;
- use packed_simd::u16x8;
+ use core::simd::u8x16;
+ use core::simd::u16x8;
const SIMD_ALIGNMENT: usize = 16;
diff --git a/third_party/rust/encoding_rs/src/simd_funcs.rs b/third_party/rust/encoding_rs/src/simd_funcs.rs
index 96feeab5a6..5ae00e62e0 100644
--- a/third_party/rust/encoding_rs/src/simd_funcs.rs
+++ b/third_party/rust/encoding_rs/src/simd_funcs.rs
@@ -7,55 +7,74 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use packed_simd::u16x8;
-use packed_simd::u8x16;
-use packed_simd::IntoBits;
+use any_all_workaround::all_mask16x8;
+use any_all_workaround::all_mask8x16;
+use any_all_workaround::any_mask16x8;
+use any_all_workaround::any_mask8x16;
+use core::simd::cmp::SimdPartialEq;
+use core::simd::cmp::SimdPartialOrd;
+use core::simd::mask16x8;
+use core::simd::mask8x16;
+use core::simd::simd_swizzle;
+use core::simd::u16x8;
+use core::simd::u8x16;
+use core::simd::ToBytes;
// TODO: Migrate unaligned access to stdlib code if/when the RFC
// https://github.com/rust-lang/rfcs/pull/1725 is implemented.
+/// Safety invariant: ptr must be valid for an unaligned read of 16 bytes
#[inline(always)]
pub unsafe fn load16_unaligned(ptr: *const u8) -> u8x16 {
- let mut simd = ::core::mem::uninitialized();
- ::core::ptr::copy_nonoverlapping(ptr, &mut simd as *mut u8x16 as *mut u8, 16);
- simd
+ let mut simd = ::core::mem::MaybeUninit::<u8x16>::uninit();
+ ::core::ptr::copy_nonoverlapping(ptr, simd.as_mut_ptr() as *mut u8, 16);
+ // Safety: copied 16 bytes of initialized memory into this, it is now initialized
+ simd.assume_init()
}
+/// Safety invariant: ptr must be valid for an aligned-for-u8x16 read of 16 bytes
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn load16_aligned(ptr: *const u8) -> u8x16 {
*(ptr as *const u8x16)
}
+/// Safety invariant: ptr must be valid for an unaligned store of 16 bytes
#[inline(always)]
pub unsafe fn store16_unaligned(ptr: *mut u8, s: u8x16) {
::core::ptr::copy_nonoverlapping(&s as *const u8x16 as *const u8, ptr, 16);
}
+/// Safety invariant: ptr must be valid for an aligned-for-u8x16 store of 16 bytes
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn store16_aligned(ptr: *mut u8, s: u8x16) {
*(ptr as *mut u8x16) = s;
}
+/// Safety invariant: ptr must be valid for an unaligned read of 16 bytes
#[inline(always)]
pub unsafe fn load8_unaligned(ptr: *const u16) -> u16x8 {
- let mut simd = ::core::mem::uninitialized();
- ::core::ptr::copy_nonoverlapping(ptr as *const u8, &mut simd as *mut u16x8 as *mut u8, 16);
- simd
+ let mut simd = ::core::mem::MaybeUninit::<u16x8>::uninit();
+ ::core::ptr::copy_nonoverlapping(ptr as *const u8, simd.as_mut_ptr() as *mut u8, 16);
+ // Safety: copied 16 bytes of initialized memory into this, it is now initialized
+ simd.assume_init()
}
+/// Safety invariant: ptr must be valid for an aligned-for-u16x8 read of 16 bytes
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn load8_aligned(ptr: *const u16) -> u16x8 {
*(ptr as *const u16x8)
}
+/// Safety invariant: ptr must be valid for an unaligned store of 16 bytes
#[inline(always)]
pub unsafe fn store8_unaligned(ptr: *mut u16, s: u16x8) {
::core::ptr::copy_nonoverlapping(&s as *const u16x8 as *const u8, ptr as *mut u8, 16);
}
+/// Safety invariant: ptr must be valid for an aligned-for-u16x8 store of 16 bytes
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn store8_aligned(ptr: *mut u16, s: u16x8) {
@@ -100,7 +119,7 @@ pub fn simd_byte_swap(s: u16x8) -> u16x8 {
#[inline(always)]
pub fn to_u16_lanes(s: u8x16) -> u16x8 {
- s.into_bits()
+ u16x8::from_ne_bytes(s)
}
cfg_if! {
@@ -108,10 +127,11 @@ cfg_if! {
// Expose low-level mask instead of higher-level conclusion,
// because the non-ASCII case would perform less well otherwise.
+ // Safety-usable invariant: This returned value is whether each high bit is set
#[inline(always)]
pub fn mask_ascii(s: u8x16) -> i32 {
unsafe {
- _mm_movemask_epi8(s.into_bits())
+ _mm_movemask_epi8(s.into())
}
}
@@ -125,14 +145,16 @@ cfg_if! {
#[inline(always)]
pub fn simd_is_ascii(s: u8x16) -> bool {
unsafe {
- _mm_movemask_epi8(s.into_bits()) == 0
+ // Safety: We have cfg()d the correct platform
+ _mm_movemask_epi8(s.into()) == 0
}
}
} else if #[cfg(target_arch = "aarch64")]{
#[inline(always)]
pub fn simd_is_ascii(s: u8x16) -> bool {
unsafe {
- vmaxvq_u8(s.into_bits()) < 0x80
+ // Safety: We have cfg()d the correct platform
+ vmaxvq_u8(s.into()) < 0x80
}
}
} else {
@@ -141,7 +163,7 @@ cfg_if! {
// This optimizes better on ARM than
// the lt formulation.
let highest_ascii = u8x16::splat(0x7F);
- !s.gt(highest_ascii).any()
+ !any_mask8x16(s.simd_gt(highest_ascii))
}
}
}
@@ -154,20 +176,21 @@ cfg_if! {
return true;
}
let above_str_latin1 = u8x16::splat(0xC4);
- s.lt(above_str_latin1).all()
+ s.simd_lt(above_str_latin1).all()
}
} else if #[cfg(target_arch = "aarch64")]{
#[inline(always)]
pub fn simd_is_str_latin1(s: u8x16) -> bool {
unsafe {
- vmaxvq_u8(s.into_bits()) < 0xC4
+ // Safety: We have cfg()d the correct platform
+ vmaxvq_u8(s.into()) < 0xC4
}
}
} else {
#[inline(always)]
pub fn simd_is_str_latin1(s: u8x16) -> bool {
let above_str_latin1 = u8x16::splat(0xC4);
- s.lt(above_str_latin1).all()
+ all_mask8x16(s.simd_lt(above_str_latin1))
}
}
}
@@ -177,21 +200,23 @@ cfg_if! {
#[inline(always)]
pub fn simd_is_basic_latin(s: u16x8) -> bool {
unsafe {
- vmaxvq_u16(s.into_bits()) < 0x80
+ // Safety: We have cfg()d the correct platform
+ vmaxvq_u16(s.into()) < 0x80
}
}
#[inline(always)]
pub fn simd_is_latin1(s: u16x8) -> bool {
unsafe {
- vmaxvq_u16(s.into_bits()) < 0x100
+ // Safety: We have cfg()d the correct platform
+ vmaxvq_u16(s.into()) < 0x100
}
}
} else {
#[inline(always)]
pub fn simd_is_basic_latin(s: u16x8) -> bool {
let above_ascii = u16x8::splat(0x80);
- s.lt(above_ascii).all()
+ all_mask16x8(s.simd_lt(above_ascii))
}
#[inline(always)]
@@ -200,7 +225,7 @@ cfg_if! {
// seems faster in this case while the above
// function is better the other way round...
let highest_latin1 = u16x8::splat(0xFF);
- !s.gt(highest_latin1).any()
+ !any_mask16x8(s.simd_gt(highest_latin1))
}
}
}
@@ -209,7 +234,7 @@ cfg_if! {
pub fn contains_surrogates(s: u16x8) -> bool {
let mask = u16x8::splat(0xF800);
let surrogate_bits = u16x8::splat(0xD800);
- (s & mask).eq(surrogate_bits).any()
+ any_mask16x8((s & mask).simd_eq(surrogate_bits))
}
cfg_if! {
@@ -217,7 +242,8 @@ cfg_if! {
macro_rules! aarch64_return_false_if_below_hebrew {
($s:ident) => ({
unsafe {
- if vmaxvq_u16($s.into_bits()) < 0x0590 {
+ // Safety: We have cfg()d the correct platform
+ if vmaxvq_u16($s.into()) < 0x0590 {
return false;
}
}
@@ -234,7 +260,7 @@ cfg_if! {
macro_rules! non_aarch64_return_false_if_all {
($s:ident) => ({
- if $s.all() {
+ if all_mask16x8($s) {
return false;
}
})
@@ -245,7 +271,7 @@ cfg_if! {
macro_rules! in_range16x8 {
($s:ident, $start:expr, $end:expr) => {{
// SIMD sub is wrapping
- ($s - u16x8::splat($start)).lt(u16x8::splat($end - $start))
+ ($s - u16x8::splat($start)).simd_lt(u16x8::splat($end - $start))
}};
}
@@ -259,43 +285,44 @@ pub fn is_u16x8_bidi(s: u16x8) -> bool {
aarch64_return_false_if_below_hebrew!(s);
- let below_hebrew = s.lt(u16x8::splat(0x0590));
+ let below_hebrew = s.simd_lt(u16x8::splat(0x0590));
non_aarch64_return_false_if_all!(below_hebrew);
- if (below_hebrew | in_range16x8!(s, 0x0900, 0x200F) | in_range16x8!(s, 0x2068, 0xD802)).all() {
+ if all_mask16x8(
+ below_hebrew | in_range16x8!(s, 0x0900, 0x200F) | in_range16x8!(s, 0x2068, 0xD802),
+ ) {
return false;
}
// Quick refutation failed. Let's do the full check.
- (in_range16x8!(s, 0x0590, 0x0900)
- | in_range16x8!(s, 0xFB1D, 0xFE00)
- | in_range16x8!(s, 0xFE70, 0xFEFF)
- | in_range16x8!(s, 0xD802, 0xD804)
- | in_range16x8!(s, 0xD83A, 0xD83C)
- | s.eq(u16x8::splat(0x200F))
- | s.eq(u16x8::splat(0x202B))
- | s.eq(u16x8::splat(0x202E))
- | s.eq(u16x8::splat(0x2067)))
- .any()
+ any_mask16x8(
+ (in_range16x8!(s, 0x0590, 0x0900)
+ | in_range16x8!(s, 0xFB1D, 0xFE00)
+ | in_range16x8!(s, 0xFE70, 0xFEFF)
+ | in_range16x8!(s, 0xD802, 0xD804)
+ | in_range16x8!(s, 0xD83A, 0xD83C)
+ | s.simd_eq(u16x8::splat(0x200F))
+ | s.simd_eq(u16x8::splat(0x202B))
+ | s.simd_eq(u16x8::splat(0x202E))
+ | s.simd_eq(u16x8::splat(0x2067))),
+ )
}
#[inline(always)]
pub fn simd_unpack(s: u8x16) -> (u16x8, u16x8) {
- unsafe {
- let first: u8x16 = shuffle!(
- s,
- u8x16::splat(0),
- [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]
- );
- let second: u8x16 = shuffle!(
- s,
- u8x16::splat(0),
- [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]
- );
- (first.into_bits(), second.into_bits())
- }
+ let first: u8x16 = simd_swizzle!(
+ s,
+ u8x16::splat(0),
+ [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]
+ );
+ let second: u8x16 = simd_swizzle!(
+ s,
+ u8x16::splat(0),
+ [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]
+ );
+ (u16x8::from_ne_bytes(first), u16x8::from_ne_bytes(second))
}
cfg_if! {
@@ -303,21 +330,20 @@ cfg_if! {
#[inline(always)]
pub fn simd_pack(a: u16x8, b: u16x8) -> u8x16 {
unsafe {
- _mm_packus_epi16(a.into_bits(), b.into_bits()).into_bits()
+ // Safety: We have cfg()d the correct platform
+ _mm_packus_epi16(a.into(), b.into()).into()
}
}
} else {
#[inline(always)]
pub fn simd_pack(a: u16x8, b: u16x8) -> u8x16 {
- unsafe {
- let first: u8x16 = a.into_bits();
- let second: u8x16 = b.into_bits();
- shuffle!(
- first,
- second,
- [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
- )
- }
+ let first: u8x16 = a.to_ne_bytes();
+ let second: u8x16 = b.to_ne_bytes();
+ simd_swizzle!(
+ first,
+ second,
+ [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
+ )
}
}
}
diff --git a/third_party/rust/encoding_rs/src/single_byte.rs b/third_party/rust/encoding_rs/src/single_byte.rs
index b3b6089d31..b7a4bf23da 100644
--- a/third_party/rust/encoding_rs/src/single_byte.rs
+++ b/third_party/rust/encoding_rs/src/single_byte.rs
@@ -53,6 +53,9 @@ impl SingleByteDecoder {
// statically omit the bound check when accessing
// `[u16; 128]` with an index
// `non_ascii as usize - 0x80usize`.
+ //
+ // Safety: `non_ascii` is a u8 byte >=0x80, from the invariants
+ // on Utf8Destination::copy_ascii_from_check_space_bmp()
let mapped =
unsafe { *(self.table.get_unchecked(non_ascii as usize - 0x80usize)) };
// let mapped = self.table[non_ascii as usize - 0x80usize];
@@ -151,9 +154,12 @@ impl SingleByteDecoder {
} else {
(DecoderResult::InputEmpty, src.len())
};
+ // Safety invariant: converted <= length. Quite often we have `converted < length`
+ // which will be separately marked.
let mut converted = 0usize;
'outermost: loop {
match unsafe {
+ // Safety: length is the minimum length, `src/dst + x` will always be valid for reads/writes of `len - x`
ascii_to_basic_latin(
src.as_ptr().add(converted),
dst.as_mut_ptr().add(converted),
@@ -164,6 +170,12 @@ impl SingleByteDecoder {
return (pending, length, length);
}
Some((mut non_ascii, consumed)) => {
+ // Safety invariant: `converted <= length` upheld, since this can only consume
+ // up to `length - converted` bytes.
+ //
+ // Furthermore, in this context,
+ // we can assume `converted < length` since this branch is only ever hit when
+ // ascii_to_basic_latin fails to consume the entire slice
converted += consumed;
'middle: loop {
// `converted` doesn't count the reading of `non_ascii` yet.
@@ -172,6 +184,9 @@ impl SingleByteDecoder {
// statically omit the bound check when accessing
// `[u16; 128]` with an index
// `non_ascii as usize - 0x80usize`.
+ //
+ // Safety: We can rely on `non_ascii` being between `0x80` and `0xFF` due to
+ // the invariants of `ascii_to_basic_latin()`, and our table has enough space for that.
let mapped =
unsafe { *(self.table.get_unchecked(non_ascii as usize - 0x80usize)) };
// let mapped = self.table[non_ascii as usize - 0x80usize];
@@ -183,9 +198,10 @@ impl SingleByteDecoder {
);
}
unsafe {
- // The bound check has already been performed
+ // Safety: As mentioned above, `converted < length`
*(dst.get_unchecked_mut(converted)) = mapped;
}
+ // Safety: `converted <= length` upheld, since `converted < length` before this
converted += 1;
// Next, handle ASCII punctuation and non-ASCII without
// going back to ASCII acceleration. Non-ASCII scripts
@@ -198,7 +214,10 @@ impl SingleByteDecoder {
if converted == length {
return (pending, length, length);
}
+ // Safety: We are back to `converted < length` because of the == above
+ // and can perform this check.
let mut b = unsafe { *(src.get_unchecked(converted)) };
+ // Safety: `converted < length` is upheld for this loop
'innermost: loop {
if b > 127 {
non_ascii = b;
@@ -208,15 +227,20 @@ impl SingleByteDecoder {
// byte unconditionally instead of trying to unread it
// to make it part of the next SIMD stride.
unsafe {
+ // Safety: `converted < length` is true for this loop
*(dst.get_unchecked_mut(converted)) = u16::from(b);
}
+ // Safety: We are now at `converted <= length`. We should *not* `continue`
+ // the loop without reverifying
converted += 1;
if b < 60 {
// We've got punctuation
if converted == length {
return (pending, length, length);
}
+ // Safety: we're back to `converted <= length` because of the == above
b = unsafe { *(src.get_unchecked(converted)) };
+ // Safety: The loop continues as `converted < length`
continue 'innermost;
}
// We've got markup or ASCII text
@@ -234,6 +258,8 @@ impl SingleByteDecoder {
loop {
if let Some((non_ascii, offset)) = validate_ascii(bytes) {
total += offset;
+ // Safety: We can rely on `non_ascii` being between `0x80` and `0xFF` due to
+ // the invariants of `ascii_to_basic_latin()`, and our table has enough space for that.
let mapped = unsafe { *(self.table.get_unchecked(non_ascii as usize - 0x80usize)) };
if mapped != u16::from(non_ascii) {
return total;
@@ -384,9 +410,12 @@ impl SingleByteEncoder {
} else {
(EncoderResult::InputEmpty, src.len())
};
+ // Safety invariant: converted <= length. Quite often we have `converted < length`
+ // which will be separately marked.
let mut converted = 0usize;
'outermost: loop {
match unsafe {
+ // Safety: length is the minimum length, `src/dst + x` will always be valid for reads/writes of `len - x`
basic_latin_to_ascii(
src.as_ptr().add(converted),
dst.as_mut_ptr().add(converted),
@@ -397,15 +426,23 @@ impl SingleByteEncoder {
return (pending, length, length);
}
Some((mut non_ascii, consumed)) => {
+ // Safety invariant: `converted <= length` upheld, since this can only consume
+ // up to `length - converted` bytes.
+ //
+ // Furthermore, in this context,
+ // we can assume `converted < length` since this branch is only ever hit when
+ // ascii_to_basic_latin fails to consume the entire slice
converted += consumed;
'middle: loop {
// `converted` doesn't count the reading of `non_ascii` yet.
match self.encode_u16(non_ascii) {
Some(byte) => {
unsafe {
+ // Safety: we're allowed this access since `converted < length`
*(dst.get_unchecked_mut(converted)) = byte;
}
converted += 1;
+ // `converted <= length` now
}
None => {
// At this point, we need to know if we
@@ -421,6 +458,8 @@ impl SingleByteEncoder {
converted,
);
}
+ // Safety: convered < length from outside the match, and `converted + 1 != length`,
+ // So `converted + 1 < length` as well. We're in bounds
let second =
u32::from(unsafe { *src.get_unchecked(converted + 1) });
if second & 0xFC00u32 != 0xDC00u32 {
@@ -432,6 +471,18 @@ impl SingleByteEncoder {
}
// The next code unit is a low surrogate.
let astral: char = unsafe {
+ // Safety: We can rely on non_ascii being 0xD800-0xDBFF since the high bits are 0xD800
+ // Then, (non_ascii << 10 - 0xD800 << 10) becomes between (0 to 0x3FF) << 10, which is between
+ // 0x400 to 0xffc00. Adding the 0x10000 gives a range of 0x10400 to 0x10fc00. Subtracting the 0xDC00
+ // gives 0x2800 to 0x102000
+ // The second term is between 0xDC00 and 0xDFFF from the check above. This gives a maximum
+ // possible range of (0x10400 + 0xDC00) to (0x102000 + 0xDFFF) which is 0x1E000 to 0x10ffff.
+ // This is in range.
+ //
+ // From a Unicode principles perspective this can also be verified as we have checked that `non_ascii` is a high surrogate
+ // (0xD800..=0xDBFF), and that `second` is a low surrogate (`0xDC00..=0xDFFF`), and we are applying reverse of the UTC16 transformation
+ // algorithm <https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF>, by applying the high surrogate - 0xD800 to the
+ // high ten bits, and the low surrogate - 0xDc00 to the low ten bits, and then adding 0x10000
::core::char::from_u32_unchecked(
(u32::from(non_ascii) << 10) + second
- (((0xD800u32 << 10) - 0x1_0000u32) + 0xDC00u32),
@@ -456,6 +507,7 @@ impl SingleByteEncoder {
converted + 1, // +1 `for non_ascii`
converted,
);
+ // Safety: This branch diverges, so no need to uphold invariants on `converted`
}
}
// Next, handle ASCII punctuation and non-ASCII without
@@ -469,8 +521,12 @@ impl SingleByteEncoder {
if converted == length {
return (pending, length, length);
}
+ // Safety: we're back to `converted < length` due to the == above and can perform
+ // the unchecked read
let mut unit = unsafe { *(src.get_unchecked(converted)) };
'innermost: loop {
+ // Safety: This loop always begins with `converted < length`, see
+ // the invariant outside and the comment on the continue below
if unit > 127 {
non_ascii = unit;
continue 'middle;
@@ -479,19 +535,25 @@ impl SingleByteEncoder {
// byte unconditionally instead of trying to unread it
// to make it part of the next SIMD stride.
unsafe {
+ // Safety: Can rely on converted < length
*(dst.get_unchecked_mut(converted)) = unit as u8;
}
converted += 1;
+ // `converted <= length` here
if unit < 60 {
// We've got punctuation
if converted == length {
return (pending, length, length);
}
+ // Safety: `converted < length` due to the == above. The read is safe.
unit = unsafe { *(src.get_unchecked(converted)) };
+ // Safety: This only happens if `converted < length`, maintaining it
continue 'innermost;
}
// We've got markup or ASCII text
continue 'outermost;
+ // Safety: All other routes to here diverge so the continue is the only
+ // way to run the innermost loop.
}
}
}
diff --git a/third_party/rust/encoding_rs/src/x_user_defined.rs b/third_party/rust/encoding_rs/src/x_user_defined.rs
index 103c9afba9..7af7d5e3d6 100644
--- a/third_party/rust/encoding_rs/src/x_user_defined.rs
+++ b/third_party/rust/encoding_rs/src/x_user_defined.rs
@@ -14,12 +14,13 @@ use crate::variant::*;
cfg_if! {
if #[cfg(feature = "simd-accel")] {
use simd_funcs::*;
- use packed_simd::u16x8;
+ use core::simd::u16x8;
+ use core::simd::cmp::SimdPartialOrd;
#[inline(always)]
fn shift_upper(unpacked: u16x8) -> u16x8 {
let highest_ascii = u16x8::splat(0x7F);
- unpacked + unpacked.gt(highest_ascii).select(u16x8::splat(0xF700), u16x8::splat(0)) }
+ unpacked + unpacked.simd_gt(highest_ascii).select(u16x8::splat(0xF700), u16x8::splat(0)) }
} else {
}
}
@@ -116,10 +117,15 @@ impl UserDefinedDecoder {
let simd_iterations = length >> 4;
let src_ptr = src.as_ptr();
let dst_ptr = dst.as_mut_ptr();
+ // Safety: This is `for i in 0..length / 16`
for i in 0..simd_iterations {
+ // Safety: This is in bounds: length is the minumum valid length for both src/dst
+ // and i ranges to length/16, so multiplying by 16 will always be `< length` and can do
+ // a 16 byte read
let input = unsafe { load16_unaligned(src_ptr.add(i * 16)) };
let (first, second) = simd_unpack(input);
unsafe {
+ // Safety: same as above, but this is two consecutive 8-byte reads
store8_unaligned(dst_ptr.add(i * 16), shift_upper(first));
store8_unaligned(dst_ptr.add((i * 16) + 8), shift_upper(second));
}
diff --git a/third_party/rust/equivalent/.cargo-checksum.json b/third_party/rust/equivalent/.cargo-checksum.json
new file mode 100644
index 0000000000..18cb3e7d9a
--- /dev/null
+++ b/third_party/rust/equivalent/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"87d7f4d5b05a14966f11c5e40940ca2687a3ae8e751bb15d7f537ae95310ab7b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7365cc8878a1d7ce155a58c4ca09c3d7a6be413efa5334a80ea842912b669349","README.md":"bbcbb8419f9bb01a51d3d5e808fe35651d423014992a72be3e7acd518485f190","src/lib.rs":"1dd84363f561b30b1da713486c6b583900353e62c569d7ba1dd84eb2c04f1a14"},"package":"5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"} \ No newline at end of file
diff --git a/third_party/rust/equivalent/Cargo.toml b/third_party/rust/equivalent/Cargo.toml
new file mode 100644
index 0000000000..925d53e883
--- /dev/null
+++ b/third_party/rust/equivalent/Cargo.toml
@@ -0,0 +1,27 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+rust-version = "1.6"
+name = "equivalent"
+version = "1.0.1"
+description = "Traits for key comparison in maps."
+readme = "README.md"
+keywords = [
+ "hashmap",
+ "no_std",
+]
+categories = [
+ "data-structures",
+ "no-std",
+]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/cuviper/equivalent"
diff --git a/third_party/rust/equivalent/LICENSE-APACHE b/third_party/rust/equivalent/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/equivalent/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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
+
+ http://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.
diff --git a/third_party/rust/equivalent/LICENSE-MIT b/third_party/rust/equivalent/LICENSE-MIT
new file mode 100644
index 0000000000..5ac40dae7f
--- /dev/null
+++ b/third_party/rust/equivalent/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2016--2023
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/equivalent/README.md b/third_party/rust/equivalent/README.md
new file mode 100644
index 0000000000..8ff7e24c8c
--- /dev/null
+++ b/third_party/rust/equivalent/README.md
@@ -0,0 +1,25 @@
+# Equivalent
+
+[![crates.io](https://img.shields.io/crates/v/equivalent.svg)](https://crates.io/crates/equivalent)
+[![docs](https://docs.rs/equivalent/badge.svg)](https://docs.rs/equivalent)
+
+`Equivalent` and `Comparable` are Rust traits for key comparison in maps.
+
+These may be used in the implementation of maps where the lookup type `Q`
+may be different than the stored key type `K`.
+
+* `Q: Equivalent<K>` checks for equality, similar to the `HashMap<K, V>`
+ constraint `K: Borrow<Q>, Q: Eq`.
+* `Q: Comparable<K>` checks the ordering, similar to the `BTreeMap<K, V>`
+ constraint `K: Borrow<Q>, Q: Ord`.
+
+These traits are not used by the maps in the standard library, but they may
+add more flexibility in third-party map implementations, especially in
+situations where a strict `K: Borrow<Q>` relationship is not available.
+
+## License
+
+Equivalent is distributed under the terms of both the MIT license and the
+Apache License (Version 2.0). See [LICENSE-APACHE](LICENSE-APACHE) and
+[LICENSE-MIT](LICENSE-MIT) for details. Opening a pull request is
+assumed to signal agreement with these licensing terms.
diff --git a/third_party/rust/equivalent/src/lib.rs b/third_party/rust/equivalent/src/lib.rs
new file mode 100644
index 0000000000..09ba58dff3
--- /dev/null
+++ b/third_party/rust/equivalent/src/lib.rs
@@ -0,0 +1,113 @@
+//! [`Equivalent`] and [`Comparable`] are traits for key comparison in maps.
+//!
+//! These may be used in the implementation of maps where the lookup type `Q`
+//! may be different than the stored key type `K`.
+//!
+//! * `Q: Equivalent<K>` checks for equality, similar to the `HashMap<K, V>`
+//! constraint `K: Borrow<Q>, Q: Eq`.
+//! * `Q: Comparable<K>` checks the ordering, similar to the `BTreeMap<K, V>`
+//! constraint `K: Borrow<Q>, Q: Ord`.
+//!
+//! These traits are not used by the maps in the standard library, but they may
+//! add more flexibility in third-party map implementations, especially in
+//! situations where a strict `K: Borrow<Q>` relationship is not available.
+//!
+//! # Examples
+//!
+//! ```
+//! use equivalent::*;
+//! use std::cmp::Ordering;
+//!
+//! pub struct Pair<A, B>(pub A, pub B);
+//!
+//! impl<'a, A: ?Sized, B: ?Sized, C, D> Equivalent<(C, D)> for Pair<&'a A, &'a B>
+//! where
+//! A: Equivalent<C>,
+//! B: Equivalent<D>,
+//! {
+//! fn equivalent(&self, key: &(C, D)) -> bool {
+//! self.0.equivalent(&key.0) && self.1.equivalent(&key.1)
+//! }
+//! }
+//!
+//! impl<'a, A: ?Sized, B: ?Sized, C, D> Comparable<(C, D)> for Pair<&'a A, &'a B>
+//! where
+//! A: Comparable<C>,
+//! B: Comparable<D>,
+//! {
+//! fn compare(&self, key: &(C, D)) -> Ordering {
+//! match self.0.compare(&key.0) {
+//! Ordering::Equal => self.1.compare(&key.1),
+//! not_equal => not_equal,
+//! }
+//! }
+//! }
+//!
+//! fn main() {
+//! let key = (String::from("foo"), String::from("bar"));
+//! let q1 = Pair("foo", "bar");
+//! let q2 = Pair("boo", "bar");
+//! let q3 = Pair("foo", "baz");
+//!
+//! assert!(q1.equivalent(&key));
+//! assert!(!q2.equivalent(&key));
+//! assert!(!q3.equivalent(&key));
+//!
+//! assert_eq!(q1.compare(&key), Ordering::Equal);
+//! assert_eq!(q2.compare(&key), Ordering::Less);
+//! assert_eq!(q3.compare(&key), Ordering::Greater);
+//! }
+//! ```
+
+#![no_std]
+
+use core::borrow::Borrow;
+use core::cmp::Ordering;
+
+/// Key equivalence trait.
+///
+/// This trait allows hash table lookup to be customized. It has one blanket
+/// implementation that uses the regular solution with `Borrow` and `Eq`, just
+/// like `HashMap` does, so that you can pass `&str` to lookup into a map with
+/// `String` keys and so on.
+///
+/// # Contract
+///
+/// The implementor **must** hash like `K`, if it is hashable.
+pub trait Equivalent<K: ?Sized> {
+ /// Compare self to `key` and return `true` if they are equal.
+ fn equivalent(&self, key: &K) -> bool;
+}
+
+impl<Q: ?Sized, K: ?Sized> Equivalent<K> for Q
+where
+ Q: Eq,
+ K: Borrow<Q>,
+{
+ #[inline]
+ fn equivalent(&self, key: &K) -> bool {
+ PartialEq::eq(self, key.borrow())
+ }
+}
+
+/// Key ordering trait.
+///
+/// This trait allows ordered map lookup to be customized. It has one blanket
+/// implementation that uses the regular solution with `Borrow` and `Ord`, just
+/// like `BTreeMap` does, so that you can pass `&str` to lookup into a map with
+/// `String` keys and so on.
+pub trait Comparable<K: ?Sized>: Equivalent<K> {
+ /// Compare self to `key` and return their ordering.
+ fn compare(&self, key: &K) -> Ordering;
+}
+
+impl<Q: ?Sized, K: ?Sized> Comparable<K> for Q
+where
+ Q: Ord,
+ K: Borrow<Q>,
+{
+ #[inline]
+ fn compare(&self, key: &K) -> Ordering {
+ Ord::cmp(self, key.borrow())
+ }
+}
diff --git a/third_party/rust/fallible_collections/.cargo-checksum.json b/third_party/rust/fallible_collections/.cargo-checksum.json
index 7e41b87cf9..f09beee0e5 100644
--- a/third_party/rust/fallible_collections/.cargo-checksum.json
+++ b/third_party/rust/fallible_collections/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"8ecacb7ad2f59391ae3247157c01c6d6508095f53ba466c3e3b554891b3e941f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"5b817b980bb39f4bee82913daf9d1ef39d1cb9e790b85ab000f735a962ce596d","src/arc.rs":"3cf237ae0acb5b058a57b633170f079024455271e9420e5a9244bafbdeb90b1c","src/boxed.rs":"1f19ad48ab3a1f41cca3756f3fdbc22e97f50a9121511222afcfe1859faf50fa","src/btree.rs":"b83820fc2a00e2e34127b3037abde8b945f0ca2785f3def725787e6813c3d3e0","src/btree/map.rs":"557ce3ff2d02c425adcb2b4ac53b6b6607c25c535aee8ffa4f12bf773fbcd763","src/btree/node.rs":"d943949b8938b5888245d6560efd386c6ae78d23fc3a7a0cc5b06f4da8f4c1c1","src/btree/search.rs":"ae78f73f3e56ea277b0a02cc39454447b75e12a6c817ecfee00065b3ddbfff67","src/btree/set.rs":"607f0db0b189c39b41824fbbf6fd8d9c5fdf85cc40f4437b13152e7b86d2979f","src/format.rs":"5142970f6ac1fe66f667ee2565af786802e93e6728ec3a1b82ffaa9f6a6b5bce","src/hashmap.rs":"1b9bf03fd2f2d9412ea2dad6963e1d37d51662e7091424bfcdc44a502f4e64bc","src/lib.rs":"652532126fdc2a81a927d23e4e4ad810911ee5d398f35f82650b5b4ec9fc5576","src/rc.rs":"f327a0adcfd2b1e225913ae716deb96777ca562985ac64e3b83550111f809864","src/try_clone.rs":"725130e0ddacde1ff7c976de62fbe45d01c67412af395aa41cac4bcfb85f6a5f","src/vec.rs":"27369a12a66deff0fe3fc57eae0f3a639e98b968d92e10eff9d4b7af8354a9d4"},"package":"3f57ccc32870366ae684be48b32a1a2e196f98a42a9b4361fe77e13fd4a34755"} \ No newline at end of file
+{"files":{"Cargo.toml":"050bb460a70e6ddd572fdf118e5d52ae8dc1c7801af6475ef2ab9dfd34d963ab","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"63b0c7dac05e6dfba32dcd4cb8e671bb8b72525f67a6b17fa5b8f10fd2cab047","src/arc.rs":"fda02f28d359193cbc0ec988b7c8149e9212c1951dff9cba6041a9ebd7fa3f17","src/boxed.rs":"8d7b3afc19e27ca51a843490d346319807cfdcc268355272c3164756fd63c242","src/btree.rs":"b83820fc2a00e2e34127b3037abde8b945f0ca2785f3def725787e6813c3d3e0","src/btree/map.rs":"557ce3ff2d02c425adcb2b4ac53b6b6607c25c535aee8ffa4f12bf773fbcd763","src/btree/node.rs":"49feca8742513b1c29d2f949c1eb1b178b538097ae94ba9dc31b8323a6423ea6","src/btree/search.rs":"ae78f73f3e56ea277b0a02cc39454447b75e12a6c817ecfee00065b3ddbfff67","src/btree/set.rs":"607f0db0b189c39b41824fbbf6fd8d9c5fdf85cc40f4437b13152e7b86d2979f","src/format.rs":"5142970f6ac1fe66f667ee2565af786802e93e6728ec3a1b82ffaa9f6a6b5bce","src/hashmap.rs":"1b9bf03fd2f2d9412ea2dad6963e1d37d51662e7091424bfcdc44a502f4e64bc","src/lib.rs":"71c5dc986ad58a4515604a73a4b7f4d8b6f43d2831993ee8612c99978ff2bb42","src/rc.rs":"f327a0adcfd2b1e225913ae716deb96777ca562985ac64e3b83550111f809864","src/try_clone.rs":"725130e0ddacde1ff7c976de62fbe45d01c67412af395aa41cac4bcfb85f6a5f","src/try_reserve_error.rs":"5e8db6a538225e66fec5d9d3a4314939b5b0428180676eb55ab928875e4feefd","src/vec.rs":"4268ae1de90750c21503fc84bdbf46cd6ccf76e33ae7f7daf8050fb29b839db1"},"package":"a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd"} \ No newline at end of file
diff --git a/third_party/rust/fallible_collections/Cargo.toml b/third_party/rust/fallible_collections/Cargo.toml
index 27a8221a17..6f6f316693 100644
--- a/third_party/rust/fallible_collections/Cargo.toml
+++ b/third_party/rust/fallible_collections/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "fallible_collections"
-version = "0.4.6"
+version = "0.4.9"
authors = ["vcombey <vcombey@student.42.fr>"]
description = "a crate which adds fallible allocation api to std collections"
readme = "README.md"
@@ -24,9 +24,12 @@ license = "MIT/Apache-2.0"
repository = "https://github.com/vcombey/fallible_collections.git"
[dependencies.hashbrown]
-version = "0.12.1"
+version = "0.13"
+optional = true
[features]
+default = ["hashmap"]
+hashmap = ["hashbrown"]
rust_1_57 = []
std = []
std_io = ["std"]
diff --git a/third_party/rust/fallible_collections/README.md b/third_party/rust/fallible_collections/README.md
index b34825903d..623eedd5c7 100644
--- a/third_party/rust/fallible_collections/README.md
+++ b/third_party/rust/fallible_collections/README.md
@@ -17,7 +17,8 @@ It is recommended to look there for the newest released version, as well as link
At the point of the last update of this README, the latest published version could be used like this:
Add the following dependency to your Cargo manifest...
-Add feature std and rust_1_57 to use the stabilized try_reserve api and the std HashMap type.
+Add feature std and rust_1_57 to use the stabilized try_reserve api and the std HashMap type. Obviously, you cannot combine it with the 'unstable' feature.
+Add integration tests that can be run with the tiny_integration_tester command.
```toml
[dependencies]
diff --git a/third_party/rust/fallible_collections/src/arc.rs b/third_party/rust/fallible_collections/src/arc.rs
index 282b8e5555..26a6ec9407 100644
--- a/third_party/rust/fallible_collections/src/arc.rs
+++ b/third_party/rust/fallible_collections/src/arc.rs
@@ -1,15 +1,20 @@
//! Implement a Fallible Arc
+#[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))]
use super::FallibleBox;
use super::TryClone;
-
use crate::TryReserveError;
+
+#[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))]
use alloc::boxed::Box;
use alloc::sync::Arc;
/// trait to implement Fallible Arc
-#[deprecated(
- since = "0.3.1",
- note = "⚠️️️this function is not completely fallible, it can panic !, see [issue](https://github.com/vcombey/fallible_collections/issues/13). help wanted"
+#[cfg_attr(
+ any(not(feature = "unstable"), feature = "rust_1_57"),
+ deprecated(
+ since = "0.3.1",
+ note = "⚠️️️this function is not completely fallible, it can panic !, see [issue](https://github.com/vcombey/fallible_collections/issues/13). help wanted"
+ )
)]
pub trait FallibleArc<T> {
/// try creating a new Arc, returning a Result<Box<T>,
@@ -22,10 +27,24 @@ pub trait FallibleArc<T> {
#[allow(deprecated)]
impl<T> FallibleArc<T> for Arc<T> {
fn try_new(t: T) -> Result<Self, TryReserveError> {
- // doesn't work as the inner variable of arc are also stocked in the box
-
- let b = <Box<T> as FallibleBox<T>>::try_new(t)?;
- Ok(Arc::from(b))
+ #[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))]
+ {
+ // doesn't work as the inner variable of arc are also stocked in the box
+ let b = <Box<T> as FallibleBox<T>>::try_new(t)?;
+ Ok(Arc::from(b))
+ }
+ #[cfg(all(feature = "unstable", not(feature = "rust_1_57")))]
+ {
+ use alloc::alloc::Layout;
+ use alloc::collections::TryReserveErrorKind;
+ Arc::try_new(t).map_err(|_e| {
+ TryReserveErrorKind::AllocError {
+ layout: Layout::new::<Arc<T>>(), // This is bullshit
+ non_exhaustive: (),
+ }
+ .into()
+ })
+ }
}
}
diff --git a/third_party/rust/fallible_collections/src/boxed.rs b/third_party/rust/fallible_collections/src/boxed.rs
index 6040754716..6680c713f4 100644
--- a/third_party/rust/fallible_collections/src/boxed.rs
+++ b/third_party/rust/fallible_collections/src/boxed.rs
@@ -64,19 +64,22 @@ impl<T> Deref for TryBox<T> {
}
fn alloc(layout: Layout) -> Result<NonNull<u8>, TryReserveError> {
- #[cfg(feature = "unstable")] // requires allocator_api
+ #[cfg(all(feature = "unstable", not(feature = "rust_1_57")))] // requires allocator_api
{
+ use alloc::collections::TryReserveErrorKind;
use core::alloc::Allocator;
alloc::alloc::Global
.allocate(layout)
- .map_err(|_e| TryReserveError::AllocError {
- layout,
- #[cfg(not(feature = "rust_1_57"))]
- non_exhaustive: (),
+ .map_err(|_e| {
+ TryReserveErrorKind::AllocError {
+ layout,
+ non_exhaustive: (),
+ }
+ .into()
})
.map(|v| v.cast())
}
- #[cfg(not(feature = "unstable"))]
+ #[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))]
{
match layout.size() {
0 => {
diff --git a/third_party/rust/fallible_collections/src/btree/node.rs b/third_party/rust/fallible_collections/src/btree/node.rs
index 249aeb6598..bed459dcfe 100644
--- a/third_party/rust/fallible_collections/src/btree/node.rs
+++ b/third_party/rust/fallible_collections/src/btree/node.rs
@@ -670,8 +670,8 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
let idx = self.len();
unsafe {
- ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
- ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
+ ptr::write(self.keys_mut().as_mut_ptr().add(idx), key);
+ ptr::write(self.vals_mut().as_mut_ptr().add(idx), val);
(*self.as_leaf_mut()).len += 1;
}
@@ -703,11 +703,14 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
let idx = self.len();
unsafe {
- ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
- ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
+ ptr::write(self.keys_mut().as_mut_ptr().add(idx), key);
+ ptr::write(self.vals_mut().as_mut_ptr().add(idx), val);
self.as_internal_mut()
.edges
- .get_unchecked_mut(idx + 1)
+ .as_mut_ptr()
+ .add(idx + 1)
+ .as_mut()
+ .unwrap()
.write(edge.node);
(*self.as_leaf_mut()).len += 1;
@@ -1002,7 +1005,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
(*self.node.as_leaf_mut()).len += 1;
- self.node.vals_mut().get_unchecked_mut(self.idx)
+ self.node.vals_mut().as_mut_ptr().add(self.idx)
}
}
@@ -1156,8 +1159,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
let (keys, vals) = self.node.into_slices_mut();
unsafe {
(
- keys.get_unchecked_mut(self.idx),
- vals.get_unchecked_mut(self.idx),
+ keys.as_mut_ptr().add(self.idx).as_mut().unwrap(),
+ vals.as_mut_ptr().add(self.idx).as_mut().unwrap(),
)
}
}
@@ -1168,8 +1171,8 @@ impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker
unsafe {
let (keys, vals) = self.node.reborrow_mut().into_slices_mut();
(
- keys.get_unchecked_mut(self.idx),
- vals.get_unchecked_mut(self.idx),
+ keys.as_mut_ptr().add(self.idx).as_mut().unwrap(),
+ vals.as_mut_ptr().add(self.idx).as_mut().unwrap(),
)
}
}
@@ -1338,7 +1341,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
unsafe {
ptr::write(
- left_node.keys_mut().get_unchecked_mut(left_len),
+ left_node.keys_mut().as_mut_ptr().add(left_len),
slice_remove(self.node.keys_mut(), self.idx),
);
ptr::copy_nonoverlapping(
@@ -1347,7 +1350,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
right_len,
);
ptr::write(
- left_node.vals_mut().get_unchecked_mut(left_len),
+ left_node.vals_mut().as_mut_ptr().add(left_len),
slice_remove(self.node.vals_mut(), self.idx),
);
ptr::copy_nonoverlapping(
@@ -1662,7 +1665,7 @@ unsafe fn slice_insert<T>(slice: &mut [T], idx: usize, val: T) {
slice.as_mut_ptr().add(idx + 1),
slice.len() - idx,
);
- ptr::write(slice.get_unchecked_mut(idx), val);
+ ptr::write(slice.as_mut_ptr().add(idx), val);
}
unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T {
diff --git a/third_party/rust/fallible_collections/src/lib.rs b/third_party/rust/fallible_collections/src/lib.rs
index 45dcd48d17..9f525d71b7 100644
--- a/third_party/rust/fallible_collections/src/lib.rs
+++ b/third_party/rust/fallible_collections/src/lib.rs
@@ -22,16 +22,22 @@
//! can't return a Result to indicate allocation failure.
#![cfg_attr(not(test), no_std)]
-#![cfg_attr(all(feature = "unstable", not(feature = "rust_1_57")), feature(try_reserve))]
+#![cfg_attr(feature = "unstable", feature(try_reserve_kind))]
#![cfg_attr(feature = "unstable", feature(min_specialization))]
#![cfg_attr(feature = "unstable", feature(allocator_api))]
#![cfg_attr(feature = "unstable", feature(dropck_eyepatch))]
#![cfg_attr(feature = "unstable", feature(ptr_internals))]
#![cfg_attr(feature = "unstable", feature(core_intrinsics))]
-#![cfg_attr(all(feature = "unstable", not(feature = "rust_1_57")), feature(maybe_uninit_ref))]
#![cfg_attr(feature = "unstable", feature(maybe_uninit_slice))]
-#![cfg_attr(feature = "unstable", feature(maybe_uninit_extra))]
#![cfg_attr(feature = "unstable", feature(maybe_uninit_uninit_array))]
+
+#[cfg(all(feature = "unstable", feature = "rust_1_57"))]
+compile_error!(
+ "The use of the 'unstable' feature combined with the \
+'rust_1_57' feature, which is related to the partial stabilization \
+of the allocator API since rustc version 1.57, does not make sense!"
+);
+
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
@@ -47,18 +53,16 @@ pub mod arc;
pub use arc::*;
#[cfg(feature = "unstable")]
pub mod btree;
-#[cfg(not(feature = "unstable"))]
+#[cfg(all(feature = "hashmap", not(feature = "unstable")))]
pub mod hashmap;
-#[cfg(not(feature = "unstable"))]
+#[cfg(all(feature = "hashmap", not(feature = "unstable")))]
pub use hashmap::*;
#[macro_use]
pub mod format;
pub mod try_clone;
-#[cfg(all(feature = "unstable", not(feature = "rust_1_57")))]
-pub use alloc::collections::TryReserveError;
-#[cfg(not(all(feature = "unstable", not(feature = "rust_1_57"))))]
-pub use hashbrown::TryReserveError;
+pub mod try_reserve_error;
+pub use try_reserve_error::TryReserveError;
#[cfg(feature = "std_io")]
pub use vec::std_io::*;
@@ -81,7 +85,7 @@ pub trait TryClone {
}
#[cfg(feature = "rust_1_57")]
-fn make_try_reserve_error(len: usize, additional: usize, elem_size: usize, align: usize) -> hashbrown::TryReserveError {
+fn make_try_reserve_error(len: usize, additional: usize, elem_size: usize, align: usize) -> TryReserveError {
if let Some(size) = len.checked_add(additional).and_then(|l| l.checked_mul(elem_size)) {
if let Ok(layout) = alloc::alloc::Layout::from_size_align(size, align) {
return TryReserveError::AllocError { layout }
diff --git a/third_party/rust/fallible_collections/src/try_reserve_error.rs b/third_party/rust/fallible_collections/src/try_reserve_error.rs
new file mode 100644
index 0000000000..ec3a998f2e
--- /dev/null
+++ b/third_party/rust/fallible_collections/src/try_reserve_error.rs
@@ -0,0 +1,19 @@
+#[cfg(all(feature = "unstable", not(feature = "rust_1_57")))]
+pub use alloc::collections::TryReserveError;
+#[cfg(all(feature = "hashmap", not(all(feature = "unstable", not(feature = "rust_1_57")))))]
+pub use hashbrown::TryReserveError;
+
+/// The error type for `try_reserve` methods.
+#[cfg(all(not(feature = "hashmap"), not(all(feature = "unstable", not(feature = "rust_1_57")))))]
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum TryReserveError {
+ /// Error due to the computed capacity exceeding the collection's maximum
+ /// (usually `isize::MAX` bytes).
+ CapacityOverflow,
+
+ /// The memory allocator returned an error
+ AllocError {
+ /// The layout of the allocation request that failed.
+ layout: alloc::alloc::Layout,
+ },
+} \ No newline at end of file
diff --git a/third_party/rust/fallible_collections/src/vec.rs b/third_party/rust/fallible_collections/src/vec.rs
index 6197b5b5d6..d4ed4df74c 100644
--- a/third_party/rust/fallible_collections/src/vec.rs
+++ b/third_party/rust/fallible_collections/src/vec.rs
@@ -515,7 +515,7 @@ impl<T> FallibleVec<T> for Vec<T> {
self.try_reserve(additional)
}
- #[cfg(not(feature = "rust_1_57"))]
+ #[cfg(all(not(feature = "unstable"), not(feature = "rust_1_57")))]
{
vec_try_reserve(self, additional)
}
@@ -624,7 +624,7 @@ impl<T> FallibleVec<T> for Vec<T> {
let mut iterator = other.iter();
while let Some(element) = iterator.next() {
unsafe {
- core::ptr::write(self.get_unchecked_mut(len), element.try_clone()?);
+ core::ptr::write(self.as_mut_ptr().add(len), element.try_clone()?);
// NB can't overflow since we would have had to alloc the address space
len += 1;
self.set_len(len);
diff --git a/third_party/rust/getrandom/.cargo-checksum.json b/third_party/rust/getrandom/.cargo-checksum.json
index fc46f728c8..cdbd3bb230 100644
--- a/third_party/rust/getrandom/.cargo-checksum.json
+++ b/third_party/rust/getrandom/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"fe1a0dc50ac5c7bdd60591f6d1027072c68dcf142131945f782169c74b9e8188","Cargo.toml":"5506345251dee6e156a3d0072d2b3b6bc6894d8cf91adb85fefe211741e7c7f9","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"e5858de17fc28ec7a3a62cbefedd301ace8a85291d0aad5cb416824d1b5abadd","SECURITY.md":"816ea79f8c7937888ab5a972a1efb270c4bada028b448953a195359fe11d526e","benches/buffer.rs":"242f56eaeecd1d0a0f6f9419d1bf312b8d211215355022bd4aef5e5e0f53e2a5","src/3ds.rs":"e41b653723740ed89fa68f495b64125786e8dec002e3556d164c5795db62ea50","src/apple-other.rs":"3ff0abc72786a2ac063cdc5df4d18cc53dc493cd68fcb33734cf40cfdbb8f644","src/bsd_arandom.rs":"cfa0627a6b4d1f37065d415972ab813bf1c9f43979d2ff9440c92a53868123aa","src/custom.rs":"a256bd6e7e9bb560803f23a36bd437859ea8a9d8ec92608930b94b33e7314c64","src/dragonfly.rs":"047008e742a7a8050e61ed9626b9f4146dfaa0675e11d6f3680eb8af498d9a6d","src/emscripten.rs":"e0b3b44b52f54454ec3e0a9e7c5222003369d9d1575cc0652e3e7cbe1b3b6da7","src/error.rs":"ff09a7e02d7aff3e45eca6bbef6c686cc46f3c2371a0897a856e4dec4b942e46","src/error_impls.rs":"9c34832ebb99cd5e31bc5c8ffc5beb5b3fa6f7ff0226aaa1cdf8e10e6d64b324","src/espidf.rs":"915ca14cbf9299de51a3c67f34fdd252461d6545f33a7232dfb7fa247ccc0209","src/fuchsia.rs":"d307b15db9f2d67b43050ae6027779a6eb2b8a69e1e89931b55b767aa2622250","src/hermit.rs":"18fdd7917c73f8b16aa82b18003948d32f9b314da10e16ef9cd2fa077b17af00","src/hurd.rs":"1053908c4eaeae9e44078c9509aa80268caa1d66642b7c6a9a80f5b9f0e63fb0","src/js.rs":"c4cd60bcfe63f8affe947773197e288536ab205a73001059f39fc2e5688e98b6","src/lib.rs":"178b4b1dae3a41721f365ea5a4eda3f5b936b310afa4431935968e96edac3120","src/linux_android.rs":"e5f9e579bbde254fcab8f6b79b893d6b74054e023b21c56a3b2b21d8f4b4d825","src/macos.rs":"8f51e095906e751b68e837bfc63cc02b243e1698b66353566ccba507c81ddad3","src/openbsd.rs":"f6fd0aa74f704335a7e0532bf5e61a7ca90b0cbc398a9c01a0fd891b6fabca0c","src/rdrand.rs":"846ac7b8380a05a50e0592dca57338beb1634c0efc878d6d1e9421be3469a744","src/solaris_illumos.rs":"7209c8b1172fc4df5ad8a79f165556b403cdd90b9eb5f7f7f9ec97bf06f4d8d7","src/solid.rs":"58919109faf06e6d546f75f785d78d6c055e1f95110d1791d9191d1e404f1e20","src/use_file.rs":"ecfc1011b4a9c962ae9b4b75ca5149a4ee83cb0951a80224ce5417046ce11717","src/util.rs":"580fb7c4e41eb6007def8626e019829c22a63980fa4da68a1adef687c57953a2","src/util_libc.rs":"48c1fe251958c6c57b7c93d83f3648d97034feeee0d5cda0cbe7bc0ee0a73fca","src/vita.rs":"ecfa9d347ad5c480ba8ff80a9de968ae060ffb435f1e95777ee413642e62e50a","src/vxworks.rs":"984726b6dd9638a38ceda83124683419b9d69a9041ad9117a470eaec5b386ce4","src/wasi.rs":"229a58af3f13a629571fb83a0c11ef0ed696ba7a44ee2e811c9f348a19b2fb69","src/windows.rs":"dd3d833979fb6b96c04b84dbf8461d5fc819bde93ad9dc26bd0f6c282656c733","tests/common/mod.rs":"b9a36043d71963ba43a9e2899ba8eea80ff9f3284d243d9b9b9f941afa4f4aa4","tests/custom.rs":"1e944ae523b62dba53fe3daf1b964a2498c8fdd21dfa7afe53781bff2fcf276e","tests/normal.rs":"9e1c4b1e468a09ed0225370dfb6608f8b8135e0fabb09bbc1a718105164aade6","tests/rdrand.rs":"156676b57f1e6bd4d66d85b8a999f1cf7a8fb749a10b8b2b4dbbcf803e8c4cd3"},"package":"fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"d77ff9f599c3e313723df758f861e23f3caa696d0b8595af2975c2cc5be0f254","Cargo.toml":"822356b05121dcc6f3ec20d99814a93c9511e2bb3612266214e2e94fe844e9c3","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"42fa16951ce7f24b5a467a40e5b449a1d41e662f97ca779864f053f39e097737","README.md":"543f0efa922ff55d3cdc1c96a188dff669f57a2ff3b7dfa0c95368b8e646b5dd","SECURITY.md":"816ea79f8c7937888ab5a972a1efb270c4bada028b448953a195359fe11d526e","benches/buffer.rs":"242f56eaeecd1d0a0f6f9419d1bf312b8d211215355022bd4aef5e5e0f53e2a5","src/3ds.rs":"dae5b84328b063a3750a67e5086db530b905a661b152181f0d6b4d63e72b70e2","src/apple-other.rs":"75f2c3319068e06ec27135d516953ab645cc7c45033f045cba44136236ef5601","src/bsd_arandom.rs":"2ace9473afc3df95594884d87d8f484cf141c9d01f2c22ece2bb1118b73d51bb","src/custom.rs":"ae5dc94bc12a4a284762e99891b013c509942b1a802ea559e04e572ed44479dc","src/dragonfly.rs":"4cffb7af2b62d515f28790b906f0293b44af1d75b23c87fa9e50d5ef99bfa02c","src/emscripten.rs":"e0b3b44b52f54454ec3e0a9e7c5222003369d9d1575cc0652e3e7cbe1b3b6da7","src/error.rs":"ab5b82ddb8304e8ad75d905d7dc5ba8deec92096930e81e87d7a28f3da382dee","src/error_impls.rs":"4c068e81d876237a7e0a0e91519896bd670c2f999ca729f7fb970caf888cab46","src/espidf.rs":"50f70136fe46f9fe9a728aa7881cdc8144f430620168cf42519c2666a8edc11f","src/fuchsia.rs":"535ed84250cfe8f176494eba226d1c1df9687b5c30cf52d5949f56a591947656","src/hermit.rs":"c9d9d5c78e0e435c2678ef43d1296aef885fd62957d6b454d758ca475cd4e544","src/hurd.rs":"c0f807d7cc4ae6a5e0b1800bbd76639270503596c8f3cade2e59bf62e0bc7a89","src/js.rs":"4306b7a49441e0da2a0737f92f56d3258ddcd1566ec3aea4a4f4a865bbf0ff87","src/lazy.rs":"21764d7cffe5177a331ec37758cc550c6e3be8c5f6fdfb7606053dafbe6a994b","src/lib.rs":"085e7246d863322ef2031b8c6ac40245c77ce3cb0cc71ac5e0c102d188080780","src/linux_android.rs":"92c71e68adcb9bc4ee39e6b2db730e06af1e0c8db0389712b5ea8a1d86991277","src/linux_android_with_fallback.rs":"620577d889d92916aeed62ac0e4f711725fddb7e7bb331f02474160104354e8e","src/macos.rs":"6e4f8377c7ad3c5dea1816a7bac22a3bb5ba85260aee71d027e32cd6602cb2dd","src/openbsd.rs":"f22ffe151d1797785c32e165459e15a34643f8a441c12da736e8a22d7103db6e","src/rdrand.rs":"ffbe1bfb8f5b30a95f462fa85db07e251f63248c6c0daf3b5f586034cedfa976","src/solaris_illumos.rs":"2f0d03956d042249aed1c2f02fc9ad389ab4dcd1dfe5c5e7c189830545497259","src/solid.rs":"a5a6e4b2b43400548b36035b9a513e70ec17809d521757e7228d2214352d24ed","src/use_file.rs":"1d7cf9370697ae69d29792d0a50ae972b093676536eb0529d9a801efbecbb096","src/util.rs":"e2c1b86ea97ca5c61d562182890cbe24c7eaa37ff8945c17fcfa665b767da1b0","src/util_libc.rs":"9321ac241c1e2088e7a73d3323a79076f5d9253cf2f077ea7083be86ee313469","src/vita.rs":"97dc7ddd706c0c64273cc5b2a6c9cab47c221921908809a9f9a8b72a1753ce90","src/vxworks.rs":"3c132cd52df3a8cf903f430ce90d3432c4b4bb99bf069f5546dee43f4f10a555","src/wasi.rs":"45b95d98766cfdc0495cfe5da6c3b63e99dda34c334deee779cf146a29350344","src/windows.rs":"7e3e73fb29a7e2748d32344d1bb9327603c6d78eb0fc5e62f50c6fa93b648c60","tests/common/mod.rs":"b9a36043d71963ba43a9e2899ba8eea80ff9f3284d243d9b9b9f941afa4f4aa4","tests/custom.rs":"1e944ae523b62dba53fe3daf1b964a2498c8fdd21dfa7afe53781bff2fcf276e","tests/normal.rs":"9e1c4b1e468a09ed0225370dfb6608f8b8135e0fabb09bbc1a718105164aade6","tests/rdrand.rs":"fcf3f78e3078e1b262d0efae8f3c4a730f3fbf68df656fceb78e22ee4cc98990"},"package":"94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"} \ No newline at end of file
diff --git a/third_party/rust/getrandom/CHANGELOG.md b/third_party/rust/getrandom/CHANGELOG.md
index 7b1f46aabc..fb9d94b7dd 100644
--- a/third_party/rust/getrandom/CHANGELOG.md
+++ b/third_party/rust/getrandom/CHANGELOG.md
@@ -4,6 +4,42 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.2.14] - 2024-04-08
+### Fixed
+- Enable `/dev/urandom` fallback for MUSL-based Linux targets [#408]
+
+[#408]: https://github.com/rust-random/getrandom/pull/408
+
+## [0.2.13] - 2024-04-06
+### Added
+- `linux_disable_fallback` crate feature to disable `/dev/urandom`-based fallback on Linux and
+ Android targets. Enabling this feature bumps minimum supported Linux kernel version to 3.17 and
+ Android API level to 23 (Marshmallow). [#396]
+
+### Changed
+- Disable `/dev/urandom` fallback for Linux targets outside of the following `target_arch`es:
+ `aarch64`, `arm`, `powerpc`, `powerpc64`, `s390x`, `x86`, `x86_64` [#396]
+- Do not catch `EPERM` error code on Android while checking availability of
+ the `getrandom` syscall [#396]
+
+[#396]: https://github.com/rust-random/getrandom/pull/396
+
+## [0.2.12] - 2024-01-09
+### Fixed
+- Custom backend for targets without atomics [#385]
+
+### Changed
+- Improve robustness of the Hermit backend and `sys_fill_exact` [#386]
+- Raise minimum supported Apple OS versions to macOS 10.12 and iOS 10 [#388]
+
+### Added
+- Document platform support policy [#387]
+
+[#385]: https://github.com/rust-random/getrandom/pull/385
+[#386]: https://github.com/rust-random/getrandom/pull/386
+[#387]: https://github.com/rust-random/getrandom/pull/387
+[#388]: https://github.com/rust-random/getrandom/pull/388
+
## [0.2.11] - 2023-11-08
### Added
- GNU/Hurd support [#370]
@@ -403,6 +439,9 @@ Publish initial implementation.
## [0.0.0] - 2019-01-19
Publish an empty template library.
+[0.2.14]: https://github.com/rust-random/getrandom/compare/v0.2.13...v0.2.14
+[0.2.13]: https://github.com/rust-random/getrandom/compare/v0.2.12...v0.2.13
+[0.2.12]: https://github.com/rust-random/getrandom/compare/v0.2.11...v0.2.12
[0.2.11]: https://github.com/rust-random/getrandom/compare/v0.2.10...v0.2.11
[0.2.10]: https://github.com/rust-random/getrandom/compare/v0.2.9...v0.2.10
[0.2.9]: https://github.com/rust-random/getrandom/compare/v0.2.8...v0.2.9
diff --git a/third_party/rust/getrandom/Cargo.toml b/third_party/rust/getrandom/Cargo.toml
index a4c3946b73..1cb474ef6b 100644
--- a/third_party/rust/getrandom/Cargo.toml
+++ b/third_party/rust/getrandom/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "getrandom"
-version = "0.2.11"
+version = "0.2.14"
authors = ["The Rand Project Developers"]
exclude = [".*"]
description = "A small cross-platform library for retrieving random data from system source"
@@ -63,6 +63,7 @@ js = [
"wasm-bindgen",
"js-sys",
]
+linux_disable_fallback = []
rdrand = []
rustc-dep-of-std = [
"compiler_builtins",
diff --git a/third_party/rust/getrandom/LICENSE-MIT b/third_party/rust/getrandom/LICENSE-MIT
index d93b5baf34..8ca28a1a09 100644
--- a/third_party/rust/getrandom/LICENSE-MIT
+++ b/third_party/rust/getrandom/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright 2018 Developers of the Rand project
+Copyright (c) 2018-2024 The rust-random Project Developers
Copyright (c) 2014 The Rust Project Developers
Permission is hereby granted, free of charge, to any
diff --git a/third_party/rust/getrandom/README.md b/third_party/rust/getrandom/README.md
index c43ad42eb8..b4b5a2b566 100644
--- a/third_party/rust/getrandom/README.md
+++ b/third_party/rust/getrandom/README.md
@@ -54,11 +54,28 @@ crate features, WASM support and Custom RNGs see the
This crate requires Rust 1.36.0 or later.
-# License
+## Platform Support
+
+This crate generally supports the same operating system and platform versions that the Rust standard library does.
+Additional targets may be supported using pluggable custom implementations.
+
+This means that as Rust drops support for old versions of operating systems (such as old Linux kernel versions, Android API levels, etc)
+in stable releases, `getrandom` may create new patch releases (`0.N.x`) that remove support for outdated platform versions.
+
+## License
The `getrandom` library is distributed under either of
- * [Apache License, Version 2.0](LICENSE-APACHE)
- * [MIT license](LICENSE-MIT)
+ * [Apache License, Version 2.0][LICENSE-APACHE]
+ * [MIT license][LICENSE-MIT]
at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
+
+[LICENSE-APACHE]: https://github.com/rust-random/getrandom/blob/master/LICENSE-APACHE
+[LICENSE-MIT]: https://github.com/rust-random/getrandom/blob/master/LICENSE-MIT
diff --git a/third_party/rust/getrandom/src/3ds.rs b/third_party/rust/getrandom/src/3ds.rs
index 87a32a1e80..a5aae77d10 100644
--- a/third_party/rust/getrandom/src/3ds.rs
+++ b/third_party/rust/getrandom/src/3ds.rs
@@ -1,11 +1,3 @@
-// Copyright 2021 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for Nintendo 3DS
use crate::util_libc::sys_fill_exact;
use crate::Error;
diff --git a/third_party/rust/getrandom/src/apple-other.rs b/third_party/rust/getrandom/src/apple-other.rs
index 8f904859ca..167d8cf0fa 100644
--- a/third_party/rust/getrandom/src/apple-other.rs
+++ b/third_party/rust/getrandom/src/apple-other.rs
@@ -1,24 +1,21 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation for iOS
+//! Implementation for iOS, tvOS, and watchOS where `getentropy` is unavailable.
use crate::Error;
-use core::{ffi::c_void, mem::MaybeUninit, ptr::null};
+use core::{ffi::c_void, mem::MaybeUninit};
-#[link(name = "Security", kind = "framework")]
+// libsystem contains the libc of Darwin, and every binary ends up linked against it either way. This
+// makes it a more lightweight choice compared to `Security.framework`.
extern "C" {
- fn SecRandomCopyBytes(rnd: *const c_void, count: usize, bytes: *mut u8) -> i32;
+ // This RNG uses a thread-local CSPRNG to provide data, which is seeded by the operating system's root CSPRNG.
+ // Its the best option after `getentropy` on modern Darwin-based platforms that also avoids the
+ // high startup costs and linking of Security.framework.
+ //
+ // While its just an implementation detail, `Security.framework` just calls into this anyway.
+ fn CCRandomGenerateBytes(bytes: *mut c_void, size: usize) -> i32;
}
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
- // Apple's documentation guarantees kSecRandomDefault is a synonym for NULL.
- let ret = unsafe { SecRandomCopyBytes(null(), dest.len(), dest.as_mut_ptr() as *mut u8) };
- // errSecSuccess (from SecBase.h) is always zero.
+ let ret = unsafe { CCRandomGenerateBytes(dest.as_mut_ptr() as *mut c_void, dest.len()) };
+ // kCCSuccess (from CommonCryptoError.h) is always zero.
if ret != 0 {
Err(Error::IOS_SEC_RANDOM)
} else {
diff --git a/third_party/rust/getrandom/src/bsd_arandom.rs b/third_party/rust/getrandom/src/bsd_arandom.rs
index 5314c48f19..6e133d8957 100644
--- a/third_party/rust/getrandom/src/bsd_arandom.rs
+++ b/third_party/rust/getrandom/src/bsd_arandom.rs
@@ -1,11 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for FreeBSD and NetBSD
use crate::{
util_libc::{sys_fill_exact, Weak},
diff --git a/third_party/rust/getrandom/src/custom.rs b/third_party/rust/getrandom/src/custom.rs
index 66e4256fad..79be7fc26e 100644
--- a/third_party/rust/getrandom/src/custom.rs
+++ b/third_party/rust/getrandom/src/custom.rs
@@ -1,11 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! An implementation which calls out to an externally defined function.
use crate::{util::uninit_slice_fill_zero, Error};
use core::{mem::MaybeUninit, num::NonZeroU32};
@@ -73,7 +65,6 @@ use core::{mem::MaybeUninit, num::NonZeroU32};
/// [top-level documentation](index.html#custom-implementations) this
/// registration only has an effect on unsupported targets.
#[macro_export]
-#[cfg_attr(docsrs, doc(cfg(feature = "custom")))]
macro_rules! register_custom_getrandom {
($path:path) => {
// TODO(MSRV 1.37): change to unnamed block
diff --git a/third_party/rust/getrandom/src/dragonfly.rs b/third_party/rust/getrandom/src/dragonfly.rs
index d3ef00aa9c..ac4794cdd9 100644
--- a/third_party/rust/getrandom/src/dragonfly.rs
+++ b/third_party/rust/getrandom/src/dragonfly.rs
@@ -1,11 +1,3 @@
-// Copyright 2021 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for DragonFly BSD
use crate::{
use_file,
diff --git a/third_party/rust/getrandom/src/error.rs b/third_party/rust/getrandom/src/error.rs
index ab39a3c33a..13c81c7aff 100644
--- a/third_party/rust/getrandom/src/error.rs
+++ b/third_party/rust/getrandom/src/error.rs
@@ -1,10 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
use core::{fmt, num::NonZeroU32};
/// A small and `no_std` compatible error type
@@ -35,7 +28,11 @@ impl Error {
pub const UNSUPPORTED: Error = internal_error(0);
/// The platform-specific `errno` returned a non-positive value.
pub const ERRNO_NOT_POSITIVE: Error = internal_error(1);
- /// Call to iOS [`SecRandomCopyBytes`](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes) failed.
+ /// Encountered an unexpected situation which should not happen in practice.
+ pub const UNEXPECTED: Error = internal_error(2);
+ /// Call to [`CCRandomGenerateBytes`](https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html) failed
+ /// on iOS, tvOS, or waatchOS.
+ // TODO: Update this constant name in the next breaking release.
pub const IOS_SEC_RANDOM: Error = internal_error(3);
/// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
pub const WINDOWS_RTL_GEN_RANDOM: Error = internal_error(4);
@@ -164,6 +161,7 @@ fn internal_desc(error: Error) -> Option<&'static str> {
match error {
Error::UNSUPPORTED => Some("getrandom: this target is not supported"),
Error::ERRNO_NOT_POSITIVE => Some("errno: did not return a positive value"),
+ Error::UNEXPECTED => Some("unexpected situation"),
Error::IOS_SEC_RANDOM => Some("SecRandomCopyBytes: iOS Security framework failure"),
Error::WINDOWS_RTL_GEN_RANDOM => Some("RtlGenRandom: Windows system function failure"),
Error::FAILED_RDRAND => Some("RDRAND: failed multiple times: CPU issue likely"),
diff --git a/third_party/rust/getrandom/src/error_impls.rs b/third_party/rust/getrandom/src/error_impls.rs
index 61f46d2279..2c326012c8 100644
--- a/third_party/rust/getrandom/src/error_impls.rs
+++ b/third_party/rust/getrandom/src/error_impls.rs
@@ -1,15 +1,6 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-#![cfg_attr(docsrs, doc(cfg(feature = "std")))]
extern crate std;
use crate::Error;
-use core::convert::From;
use std::io;
impl From<Error> for io::Error {
diff --git a/third_party/rust/getrandom/src/espidf.rs b/third_party/rust/getrandom/src/espidf.rs
index d074dc4cec..7da5ca88ea 100644
--- a/third_party/rust/getrandom/src/espidf.rs
+++ b/third_party/rust/getrandom/src/espidf.rs
@@ -1,11 +1,3 @@
-// Copyright 2021 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for ESP-IDF
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};
diff --git a/third_party/rust/getrandom/src/fuchsia.rs b/third_party/rust/getrandom/src/fuchsia.rs
index 5a135f3430..11970685c0 100644
--- a/third_party/rust/getrandom/src/fuchsia.rs
+++ b/third_party/rust/getrandom/src/fuchsia.rs
@@ -1,11 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for Fuchsia Zircon
use crate::Error;
use core::mem::MaybeUninit;
diff --git a/third_party/rust/getrandom/src/hermit.rs b/third_party/rust/getrandom/src/hermit.rs
index 570b03d9a5..c4f619417e 100644
--- a/third_party/rust/getrandom/src/hermit.rs
+++ b/third_party/rust/getrandom/src/hermit.rs
@@ -1,5 +1,11 @@
+//! Implementation for Hermit
use crate::Error;
-use core::{cmp::min, mem::MaybeUninit, num::NonZeroU32};
+use core::{mem::MaybeUninit, num::NonZeroU32};
+
+/// Minimum return value which we should get from syscalls in practice,
+/// because Hermit uses positive `i32`s for error codes:
+/// https://github.com/hermitcore/libhermit-rs/blob/main/src/errno.rs
+const MIN_RET_CODE: isize = -(i32::MAX as isize);
extern "C" {
fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize;
@@ -8,14 +14,16 @@ extern "C" {
pub fn getrandom_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
while !dest.is_empty() {
let res = unsafe { sys_read_entropy(dest.as_mut_ptr() as *mut u8, dest.len(), 0) };
- if res < 0 {
- // SAFETY: all Hermit error codes use i32 under the hood:
- // https://github.com/hermitcore/libhermit-rs/blob/master/src/errno.rs
- let code = unsafe { NonZeroU32::new_unchecked((-res) as u32) };
- return Err(code.into());
+ // Positive `isize`s can be safely casted to `usize`
+ if res > 0 && (res as usize) <= dest.len() {
+ dest = &mut dest[res as usize..];
+ } else {
+ let err = match res {
+ MIN_RET_CODE..=-1 => NonZeroU32::new(-res as u32).unwrap().into(),
+ _ => Error::UNEXPECTED,
+ };
+ return Err(err);
}
- let len = min(res as usize, dest.len());
- dest = &mut dest[len..];
}
Ok(())
}
diff --git a/third_party/rust/getrandom/src/hurd.rs b/third_party/rust/getrandom/src/hurd.rs
index 842b9bc481..472a7d86b2 100644
--- a/third_party/rust/getrandom/src/hurd.rs
+++ b/third_party/rust/getrandom/src/hurd.rs
@@ -1,11 +1,3 @@
-// Copyright 2021 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for GNU/Hurd
use crate::util_libc::sys_fill_exact;
use crate::Error;
diff --git a/third_party/rust/getrandom/src/js.rs b/third_party/rust/getrandom/src/js.rs
index d031282261..e5428f50d1 100644
--- a/third_party/rust/getrandom/src/js.rs
+++ b/third_party/rust/getrandom/src/js.rs
@@ -1,10 +1,4 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
+//! Implementation for WASM based on Web and Node.js
use crate::Error;
extern crate std;
diff --git a/third_party/rust/getrandom/src/lazy.rs b/third_party/rust/getrandom/src/lazy.rs
new file mode 100644
index 0000000000..100ce1eaf5
--- /dev/null
+++ b/third_party/rust/getrandom/src/lazy.rs
@@ -0,0 +1,56 @@
+use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+
+// This structure represents a lazily initialized static usize value. Useful
+// when it is preferable to just rerun initialization instead of locking.
+// unsync_init will invoke an init() function until it succeeds, then return the
+// cached value for future calls.
+//
+// unsync_init supports init() "failing". If the init() method returns UNINIT,
+// that value will be returned as normal, but will not be cached.
+//
+// Users should only depend on the _value_ returned by init() functions.
+// Specifically, for the following init() function:
+// fn init() -> usize {
+// a();
+// let v = b();
+// c();
+// v
+// }
+// the effects of c() or writes to shared memory will not necessarily be
+// observed and additional synchronization methods may be needed.
+pub(crate) struct LazyUsize(AtomicUsize);
+
+impl LazyUsize {
+ pub const fn new() -> Self {
+ Self(AtomicUsize::new(Self::UNINIT))
+ }
+
+ // The initialization is not completed.
+ pub const UNINIT: usize = usize::max_value();
+
+ // Runs the init() function at most once, returning the value of some run of
+ // init(). Multiple callers can run their init() functions in parallel.
+ // init() should always return the same value, if it succeeds.
+ pub fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize {
+ // Relaxed ordering is fine, as we only have a single atomic variable.
+ let mut val = self.0.load(Relaxed);
+ if val == Self::UNINIT {
+ val = init();
+ self.0.store(val, Relaxed);
+ }
+ val
+ }
+}
+
+// Identical to LazyUsize except with bool instead of usize.
+pub(crate) struct LazyBool(LazyUsize);
+
+impl LazyBool {
+ pub const fn new() -> Self {
+ Self(LazyUsize::new())
+ }
+
+ pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool {
+ self.0.unsync_init(|| init() as usize) != 0
+ }
+}
diff --git a/third_party/rust/getrandom/src/lib.rs b/third_party/rust/getrandom/src/lib.rs
index 10cc227377..b3b3d0e24b 100644
--- a/third_party/rust/getrandom/src/lib.rs
+++ b/third_party/rust/getrandom/src/lib.rs
@@ -1,11 +1,3 @@
-// Copyright 2019 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Interface to the operating system's random number generator.
//!
//! # Supported targets
@@ -14,8 +6,8 @@
//! | ----------------- | ------------------ | --------------
//! | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
//! | Windows | `*‑windows‑*` | [`BCryptGenRandom`]
-//! | macOS | `*‑apple‑darwin` | [`getentropy`][3] if available, otherwise [`/dev/urandom`][4] (identical to `/dev/random`)
-//! | iOS, tvOS, watchOS | `*‑apple‑ios`, `*-apple-tvos`, `*-apple-watchos` | [`SecRandomCopyBytes`]
+//! | macOS | `*‑apple‑darwin` | [`getentropy`][3]
+//! | iOS, tvOS, watchOS | `*‑apple‑ios`, `*-apple-tvos`, `*-apple-watchos` | [`CCRandomGenerateBytes`]
//! | FreeBSD | `*‑freebsd` | [`getrandom`][5] if available, otherwise [`kern.arandom`][6]
//! | OpenBSD | `*‑openbsd` | [`getentropy`][7]
//! | NetBSD | `*‑netbsd` | [`getrandom`][16] if available, otherwise [`kern.arandom`][8]
@@ -55,6 +47,21 @@
//! This prevents a crate from overriding a secure source of randomness
//! (either accidentally or intentionally).
//!
+//! ## `/dev/urandom` fallback on Linux and Android
+//!
+//! On Linux targets the fallback is present only if either `target_env` is `musl`,
+//! or `target_arch` is one of the following: `aarch64`, `arm`, `powerpc`, `powerpc64`,
+//! `s390x`, `x86`, `x86_64`. Other supported targets [require][platform-support]
+//! kernel versions which support `getrandom` system call, so fallback is not needed.
+//!
+//! On Android targets the fallback is present only for the following `target_arch`es:
+//! `aarch64`, `arm`, `x86`, `x86_64`. Other `target_arch`es (e.g. RISC-V) require
+//! sufficiently high API levels.
+//!
+//! The fallback can be disabled by enabling the `linux_disable_fallback` crate feature.
+//! Note that doing so will bump minimum supported Linux kernel version to 3.17 and
+//! Android API level to 23 (Marshmallow).
+//!
//! ### RDRAND on x86
//!
//! *If the `rdrand` Cargo feature is enabled*, `getrandom` will fallback to using
@@ -106,6 +113,16 @@
//! ```
//! This crate will then use the provided `webcrypto` implementation.
//!
+//! ### Platform Support
+//! This crate generally supports the same operating system and platform versions
+//! that the Rust standard library does. Additional targets may be supported using
+//! pluggable custom implementations.
+//!
+//! This means that as Rust drops support for old versions of operating systems
+//! (such as old Linux kernel versions, Android API levels, etc) in stable releases,
+//! `getrandom` may create new patch releases (`0.N.x`) that remove support for
+//! outdated platform versions.
+//!
//! ### Custom implementations
//!
//! The [`register_custom_getrandom!`] macro allows a user to mark their own
@@ -151,8 +168,8 @@
//! on every call to `getrandom`, hence after the first successful call one
//! can be reasonably confident that no errors will occur.
//!
-//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
-//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
+//! [1]: https://manned.org/getrandom.2
+//! [2]: https://manned.org/urandom.4
//! [3]: https://www.unix.com/man-page/mojave/2/getentropy/
//! [4]: https://www.unix.com/man-page/mojave/4/urandom/
//! [5]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
@@ -172,7 +189,7 @@
//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
//! [`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
//! [`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
-//! [`SecRandomCopyBytes`]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
+//! [`CCRandomGenerateBytes`]: https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html
//! [`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
//! [`crypto.randomFillSync`]: https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size
//! [`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t
@@ -183,15 +200,16 @@
//! [CommonJS modules]: https://nodejs.org/api/modules.html
//! [ES modules]: https://nodejs.org/api/esm.html
//! [`sys_read_entropy`]: https://github.com/hermit-os/kernel/blob/315f58ff5efc81d9bf0618af85a59963ff55f8b1/src/syscalls/entropy.rs#L47-L55
+//! [platform-support]: https://doc.rust-lang.org/stable/rustc/platform-support.html
#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
- html_root_url = "https://docs.rs/getrandom/0.2.11"
+ html_root_url = "https://docs.rs/getrandom/0.2.14"
)]
#![no_std]
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
-#![cfg_attr(docsrs, feature(doc_cfg))]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#[macro_use]
extern crate cfg_if;
@@ -221,9 +239,52 @@ cfg_if! {
if #[cfg(any(target_os = "haiku", target_os = "redox", target_os = "nto", target_os = "aix"))] {
mod util_libc;
#[path = "use_file.rs"] mod imp;
- } else if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ } else if #[cfg(all(
+ not(feature = "linux_disable_fallback"),
+ any(
+ // Rust supports Android API level 19 (KitKat) [0] and the next upgrade targets
+ // level 21 (Lollipop) [1], while `getrandom(2)` was added only in
+ // level 23 (Marshmallow). Note that it applies only to the "old" `target_arch`es,
+ // RISC-V Android targets sufficiently new API level, same will apply for potential
+ // new Android `target_arch`es.
+ // [0]: https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html
+ // [1]: https://github.com/rust-lang/rust/pull/120593
+ all(
+ target_os = "android",
+ any(
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "x86",
+ target_arch = "x86_64",
+ ),
+ ),
+ // Only on these `target_arch`es Rust supports Linux kernel versions (3.2+)
+ // that precede the version (3.17) in which `getrandom(2)` was added:
+ // https://doc.rust-lang.org/stable/rustc/platform-support.html
+ all(
+ target_os = "linux",
+ any(
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+ target_arch = "s390x",
+ target_arch = "x86",
+ target_arch = "x86_64",
+ // Minimum supported Linux kernel version for MUSL targets
+ // is not specified explicitly (as of Rust 1.77) and they
+ // are used in practice to target pre-3.17 kernels.
+ target_env = "musl",
+ ),
+ )
+ ),
+ ))] {
mod util_libc;
mod use_file;
+ mod lazy;
+ #[path = "linux_android_with_fallback.rs"] mod imp;
+ } else if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ mod util_libc;
#[path = "linux_android.rs"] mod imp;
} else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] {
mod util_libc;
@@ -242,7 +303,6 @@ cfg_if! {
#[path = "apple-other.rs"] mod imp;
} else if #[cfg(target_os = "macos")] {
mod util_libc;
- mod use_file;
#[path = "macos.rs"] mod imp;
} else if #[cfg(target_os = "openbsd")] {
mod util_libc;
@@ -272,9 +332,11 @@ cfg_if! {
mod util_libc;
#[path = "emscripten.rs"] mod imp;
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
+ mod lazy;
#[path = "rdrand.rs"] mod imp;
} else if #[cfg(all(feature = "rdrand",
any(target_arch = "x86_64", target_arch = "x86")))] {
+ mod lazy;
#[path = "rdrand.rs"] mod imp;
} else if #[cfg(all(feature = "js",
any(target_arch = "wasm32", target_arch = "wasm64"),
diff --git a/third_party/rust/getrandom/src/linux_android.rs b/third_party/rust/getrandom/src/linux_android.rs
index e81f1e1533..93a649452f 100644
--- a/third_party/rust/getrandom/src/linux_android.rs
+++ b/third_party/rust/getrandom/src/linux_android.rs
@@ -1,48 +1,7 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation for Linux / Android
-use crate::{
- util::LazyBool,
- util_libc::{last_os_error, sys_fill_exact},
- {use_file, Error},
-};
+//! Implementation for Linux / Android without `/dev/urandom` fallback
+use crate::{util_libc, Error};
use core::mem::MaybeUninit;
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
- // getrandom(2) was introduced in Linux 3.17
- static HAS_GETRANDOM: LazyBool = LazyBool::new();
- if HAS_GETRANDOM.unsync_init(is_getrandom_available) {
- sys_fill_exact(dest, |buf| unsafe {
- getrandom(buf.as_mut_ptr() as *mut libc::c_void, buf.len(), 0)
- })
- } else {
- use_file::getrandom_inner(dest)
- }
-}
-
-fn is_getrandom_available() -> bool {
- let res = unsafe { getrandom(core::ptr::null_mut(), 0, libc::GRND_NONBLOCK) };
- if res < 0 {
- match last_os_error().raw_os_error() {
- Some(libc::ENOSYS) => false, // No kernel support
- Some(libc::EPERM) => false, // Blocked by seccomp
- _ => true,
- }
- } else {
- true
- }
-}
-
-unsafe fn getrandom(
- buf: *mut libc::c_void,
- buflen: libc::size_t,
- flags: libc::c_uint,
-) -> libc::ssize_t {
- libc::syscall(libc::SYS_getrandom, buf, buflen, flags) as libc::ssize_t
+ util_libc::sys_fill_exact(dest, util_libc::getrandom_syscall)
}
diff --git a/third_party/rust/getrandom/src/linux_android_with_fallback.rs b/third_party/rust/getrandom/src/linux_android_with_fallback.rs
new file mode 100644
index 0000000000..0f5ea8a992
--- /dev/null
+++ b/third_party/rust/getrandom/src/linux_android_with_fallback.rs
@@ -0,0 +1,33 @@
+//! Implementation for Linux / Android with `/dev/urandom` fallback
+use crate::{
+ lazy::LazyBool,
+ util_libc::{getrandom_syscall, last_os_error, sys_fill_exact},
+ {use_file, Error},
+};
+use core::mem::MaybeUninit;
+
+pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
+ // getrandom(2) was introduced in Linux 3.17
+ static HAS_GETRANDOM: LazyBool = LazyBool::new();
+ if HAS_GETRANDOM.unsync_init(is_getrandom_available) {
+ sys_fill_exact(dest, getrandom_syscall)
+ } else {
+ use_file::getrandom_inner(dest)
+ }
+}
+
+fn is_getrandom_available() -> bool {
+ if getrandom_syscall(&mut []) < 0 {
+ match last_os_error().raw_os_error() {
+ Some(libc::ENOSYS) => false, // No kernel support
+ // The fallback on EPERM is intentionally not done on Android since this workaround
+ // seems to be needed only for specific Linux-based products that aren't based
+ // on Android. See https://github.com/rust-random/getrandom/issues/229.
+ #[cfg(target_os = "linux")]
+ Some(libc::EPERM) => false, // Blocked by seccomp
+ _ => true,
+ }
+ } else {
+ true
+ }
+}
diff --git a/third_party/rust/getrandom/src/macos.rs b/third_party/rust/getrandom/src/macos.rs
index 312f9b27f0..44af76b03c 100644
--- a/third_party/rust/getrandom/src/macos.rs
+++ b/third_party/rust/getrandom/src/macos.rs
@@ -1,36 +1,18 @@
-// Copyright 2019 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for macOS
-use crate::{
- use_file,
- util_libc::{last_os_error, Weak},
- Error,
-};
-use core::mem::{self, MaybeUninit};
+use crate::{util_libc::last_os_error, Error};
+use core::mem::MaybeUninit;
-type GetEntropyFn = unsafe extern "C" fn(*mut u8, libc::size_t) -> libc::c_int;
+extern "C" {
+ // Supported as of macOS 10.12+.
+ fn getentropy(buf: *mut u8, size: libc::size_t) -> libc::c_int;
+}
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
- // getentropy(2) was added in 10.12, Rust supports 10.7+
- static GETENTROPY: Weak = unsafe { Weak::new("getentropy\0") };
- if let Some(fptr) = GETENTROPY.ptr() {
- let func: GetEntropyFn = unsafe { mem::transmute(fptr) };
- for chunk in dest.chunks_mut(256) {
- let ret = unsafe { func(chunk.as_mut_ptr() as *mut u8, chunk.len()) };
- if ret != 0 {
- return Err(last_os_error());
- }
+ for chunk in dest.chunks_mut(256) {
+ let ret = unsafe { getentropy(chunk.as_mut_ptr() as *mut u8, chunk.len()) };
+ if ret != 0 {
+ return Err(last_os_error());
}
- Ok(())
- } else {
- // We fallback to reading from /dev/random instead of SecRandomCopyBytes
- // to avoid high startup costs and linking the Security framework.
- use_file::getrandom_inner(dest)
}
+ Ok(())
}
diff --git a/third_party/rust/getrandom/src/openbsd.rs b/third_party/rust/getrandom/src/openbsd.rs
index 7a76f61d5b..f4d64daf6f 100644
--- a/third_party/rust/getrandom/src/openbsd.rs
+++ b/third_party/rust/getrandom/src/openbsd.rs
@@ -1,11 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for OpenBSD
use crate::{util_libc::last_os_error, Error};
use core::mem::MaybeUninit;
diff --git a/third_party/rust/getrandom/src/rdrand.rs b/third_party/rust/getrandom/src/rdrand.rs
index 69f6a5d13e..f527c8c643 100644
--- a/third_party/rust/getrandom/src/rdrand.rs
+++ b/third_party/rust/getrandom/src/rdrand.rs
@@ -1,14 +1,5 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-use crate::{
- util::{slice_as_uninit, LazyBool},
- Error,
-};
+//! RDRAND backend for x86(-64) targets
+use crate::{lazy::LazyBool, util::slice_as_uninit, Error};
use core::mem::{size_of, MaybeUninit};
cfg_if! {
diff --git a/third_party/rust/getrandom/src/solaris_illumos.rs b/third_party/rust/getrandom/src/solaris_illumos.rs
index 501c610d77..fbc239433f 100644
--- a/third_party/rust/getrandom/src/solaris_illumos.rs
+++ b/third_party/rust/getrandom/src/solaris_illumos.rs
@@ -1,11 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for the Solaris family
//!
//! `/dev/random` uses the Hash_DRBG with SHA512 algorithm from NIST SP 800-90A.
diff --git a/third_party/rust/getrandom/src/solid.rs b/third_party/rust/getrandom/src/solid.rs
index aeccc4e2bd..cae8caf667 100644
--- a/third_party/rust/getrandom/src/solid.rs
+++ b/third_party/rust/getrandom/src/solid.rs
@@ -1,11 +1,3 @@
-// Copyright 2021 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for SOLID
use crate::Error;
use core::{mem::MaybeUninit, num::NonZeroU32};
diff --git a/third_party/rust/getrandom/src/use_file.rs b/third_party/rust/getrandom/src/use_file.rs
index a6ef0d2350..333325b5a9 100644
--- a/third_party/rust/getrandom/src/use_file.rs
+++ b/third_party/rust/getrandom/src/use_file.rs
@@ -1,14 +1,5 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementations that just need to read from a file
use crate::{
- util::LazyUsize,
util_libc::{open_readonly, sys_fill_exact},
Error,
};
@@ -21,7 +12,7 @@ use core::{
// We prefer using /dev/urandom and only use /dev/random if the OS
// documentation indicates that /dev/urandom is insecure.
// On Solaris/Illumos, see src/solaris_illumos.rs
-// On Dragonfly, Haiku, macOS, and QNX Neutrino the devices are identical.
+// On Dragonfly, Haiku, and QNX Neutrino the devices are identical.
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
const FILE_PATH: &str = "/dev/random\0";
#[cfg(any(
@@ -31,10 +22,10 @@ const FILE_PATH: &str = "/dev/random\0";
target_os = "redox",
target_os = "dragonfly",
target_os = "haiku",
- target_os = "macos",
target_os = "nto",
))]
const FILE_PATH: &str = "/dev/urandom\0";
+const FD_UNINIT: usize = usize::max_value();
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let fd = get_rng_fd()?;
@@ -47,10 +38,10 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// bytes. The file will be opened exactly once. All subsequent calls will
// return the same file descriptor. This file descriptor is never closed.
fn get_rng_fd() -> Result<libc::c_int, Error> {
- static FD: AtomicUsize = AtomicUsize::new(LazyUsize::UNINIT);
+ static FD: AtomicUsize = AtomicUsize::new(FD_UNINIT);
fn get_fd() -> Option<libc::c_int> {
match FD.load(Relaxed) {
- LazyUsize::UNINIT => None,
+ FD_UNINIT => None,
val => Some(val as libc::c_int),
}
}
@@ -75,8 +66,8 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
wait_until_rng_ready()?;
let fd = unsafe { open_readonly(FILE_PATH)? };
- // The fd always fits in a usize without conflicting with UNINIT.
- debug_assert!(fd >= 0 && (fd as usize) < LazyUsize::UNINIT);
+ // The fd always fits in a usize without conflicting with FD_UNINIT.
+ debug_assert!(fd >= 0 && (fd as usize) < FD_UNINIT);
FD.store(fd as usize, Relaxed);
Ok(fd)
diff --git a/third_party/rust/getrandom/src/util.rs b/third_party/rust/getrandom/src/util.rs
index 3162afad35..1c4e70ba4e 100644
--- a/third_party/rust/getrandom/src/util.rs
+++ b/third_party/rust/getrandom/src/util.rs
@@ -1,71 +1,5 @@
-// Copyright 2019 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
#![allow(dead_code)]
-use core::{
- mem::MaybeUninit,
- ptr,
- sync::atomic::{AtomicUsize, Ordering::Relaxed},
-};
-
-// This structure represents a lazily initialized static usize value. Useful
-// when it is preferable to just rerun initialization instead of locking.
-// Both unsync_init and sync_init will invoke an init() function until it
-// succeeds, then return the cached value for future calls.
-//
-// Both methods support init() "failing". If the init() method returns UNINIT,
-// that value will be returned as normal, but will not be cached.
-//
-// Users should only depend on the _value_ returned by init() functions.
-// Specifically, for the following init() function:
-// fn init() -> usize {
-// a();
-// let v = b();
-// c();
-// v
-// }
-// the effects of c() or writes to shared memory will not necessarily be
-// observed and additional synchronization methods with be needed.
-pub struct LazyUsize(AtomicUsize);
-
-impl LazyUsize {
- pub const fn new() -> Self {
- Self(AtomicUsize::new(Self::UNINIT))
- }
-
- // The initialization is not completed.
- pub const UNINIT: usize = usize::max_value();
-
- // Runs the init() function at least once, returning the value of some run
- // of init(). Multiple callers can run their init() functions in parallel.
- // init() should always return the same value, if it succeeds.
- pub fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize {
- // Relaxed ordering is fine, as we only have a single atomic variable.
- let mut val = self.0.load(Relaxed);
- if val == Self::UNINIT {
- val = init();
- self.0.store(val, Relaxed);
- }
- val
- }
-}
-
-// Identical to LazyUsize except with bool instead of usize.
-pub struct LazyBool(LazyUsize);
-
-impl LazyBool {
- pub const fn new() -> Self {
- Self(LazyUsize::new())
- }
-
- pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool {
- self.0.unsync_init(|| init() as usize) != 0
- }
-}
+use core::{mem::MaybeUninit, ptr};
/// Polyfill for `maybe_uninit_slice` feature's
/// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have
diff --git a/third_party/rust/getrandom/src/util_libc.rs b/third_party/rust/getrandom/src/util_libc.rs
index 99bee3824b..e86ef77624 100644
--- a/third_party/rust/getrandom/src/util_libc.rs
+++ b/third_party/rust/getrandom/src/util_libc.rs
@@ -1,14 +1,6 @@
-// Copyright 2019 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
#![allow(dead_code)]
use crate::Error;
use core::{
- cmp::min,
mem::MaybeUninit,
num::NonZeroU32,
ptr::NonNull,
@@ -70,17 +62,19 @@ pub fn sys_fill_exact(
) -> Result<(), Error> {
while !buf.is_empty() {
let res = sys_fill(buf);
- if res < 0 {
- let err = last_os_error();
- // We should try again if the call was interrupted.
- if err.raw_os_error() != Some(libc::EINTR) {
- return Err(err);
+ match res {
+ res if res > 0 => buf = buf.get_mut(res as usize..).ok_or(Error::UNEXPECTED)?,
+ -1 => {
+ let err = last_os_error();
+ // We should try again if the call was interrupted.
+ if err.raw_os_error() != Some(libc::EINTR) {
+ return Err(err);
+ }
}
- } else {
- // We don't check for EOF (ret = 0) as the data we are reading
+ // Negative return codes not equal to -1 should be impossible.
+ // EOF (ret = 0) should be impossible, as the data we are reading
// should be an infinite stream of random bytes.
- let len = min(res as usize, buf.len());
- buf = &mut buf[len..];
+ _ => return Err(Error::UNEXPECTED),
}
}
Ok(())
@@ -157,3 +151,16 @@ pub unsafe fn open_readonly(path: &str) -> Result<libc::c_int, Error> {
}
}
}
+
+/// Thin wrapper around the `getrandom()` Linux system call
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub fn getrandom_syscall(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {
+ unsafe {
+ libc::syscall(
+ libc::SYS_getrandom,
+ buf.as_mut_ptr() as *mut libc::c_void,
+ buf.len(),
+ 0,
+ ) as libc::ssize_t
+ }
+}
diff --git a/third_party/rust/getrandom/src/vita.rs b/third_party/rust/getrandom/src/vita.rs
index 4f19b9cb08..20a9878245 100644
--- a/third_party/rust/getrandom/src/vita.rs
+++ b/third_party/rust/getrandom/src/vita.rs
@@ -1,11 +1,3 @@
-// Copyright 2021 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for PS Vita
use crate::{util_libc::last_os_error, Error};
use core::mem::MaybeUninit;
diff --git a/third_party/rust/getrandom/src/vxworks.rs b/third_party/rust/getrandom/src/vxworks.rs
index 9b2090fb0a..7ca9d6bfdd 100644
--- a/third_party/rust/getrandom/src/vxworks.rs
+++ b/third_party/rust/getrandom/src/vxworks.rs
@@ -1,11 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for VxWorks
use crate::{util_libc::last_os_error, Error};
use core::{
diff --git a/third_party/rust/getrandom/src/wasi.rs b/third_party/rust/getrandom/src/wasi.rs
index 9276ee74f8..d6c8a912c9 100644
--- a/third_party/rust/getrandom/src/wasi.rs
+++ b/third_party/rust/getrandom/src/wasi.rs
@@ -1,11 +1,3 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Implementation for WASI
use crate::Error;
use core::{
diff --git a/third_party/rust/getrandom/src/windows.rs b/third_party/rust/getrandom/src/windows.rs
index 92d70429e4..2d1c48351c 100644
--- a/third_party/rust/getrandom/src/windows.rs
+++ b/third_party/rust/getrandom/src/windows.rs
@@ -1,11 +1,4 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
+//! Implementation for Windows
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit, num::NonZeroU32, ptr};
diff --git a/third_party/rust/getrandom/tests/rdrand.rs b/third_party/rust/getrandom/tests/rdrand.rs
index 25678683f3..a355c31ee8 100644
--- a/third_party/rust/getrandom/tests/rdrand.rs
+++ b/third_party/rust/getrandom/tests/rdrand.rs
@@ -6,6 +6,8 @@
use getrandom::Error;
#[macro_use]
extern crate cfg_if;
+#[path = "../src/lazy.rs"]
+mod lazy;
#[path = "../src/rdrand.rs"]
mod rdrand;
#[path = "../src/util.rs"]
diff --git a/third_party/rust/glean-core/.cargo-checksum.json b/third_party/rust/glean-core/.cargo-checksum.json
index 663b3141c3..e9033c86e8 100644
--- a/third_party/rust/glean-core/.cargo-checksum.json
+++ b/third_party/rust/glean-core/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c590a29d01f2ccad65fdbed80578177ae3c02522d6c6c60eef9644d71f04a0e3","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"026495898699b54608eb4ec16074ffafc57920d80ccb59961c501a1ea28c9985","build.rs":"4857bea99c6b8c08db8818efa9d3738716f52d3acb68159323957ae52892a3eb","src/common_metric_data.rs":"864990a1e5770d5d5fdebcd2c36b58c3442334030fb60f53811395b56baac94b","src/core/mod.rs":"9880520967e9da0b475d280c17cd70debf9a1d15912018cbba775e5fde0ff588","src/core_metrics.rs":"a877e42e0f8b932adb52a5681ad76fd977808cb48c7eeb29b1e4bbe804f1ea96","src/coverage.rs":"49613fd310bd24d779472720975fbe6c97ec370a95eb55f10afa43f67539c942","src/database/mod.rs":"b3684bb6a11e0aa2a51306a53feddbc89bc21879d4930d5e9995869950af3413","src/debug.rs":"d0dfc0932a0953bbbe029f723bf2613c8d691f34b017e858030c46b02a46a17d","src/dispatcher/global.rs":"f69cd81a90a37c306d4e0ce8177ea5a3ae2ffda5b431ae46b9a22c9e38891271","src/dispatcher/mod.rs":"391310269947452d7e0de24c848c183110c60149d75e345ba6d5d146f222dace","src/error.rs":"b93c7d3e243b21bb9eafc95f17860aba1a942b2f2b0a7f43307690f05fece516","src/error_recording.rs":"1aba34e9d3c741755055f5b76415114b25b146b0aa90049c3457cfe12066deda","src/event_database/mod.rs":"78633293e1f3c9e9d51705615a7a4b603d7f85567bfdc2b0bad35ccda6a12d44","src/fd_logger.rs":"0c9def6fa53db1a2ab93c85795f8a7df57797bcfd3978146923e151752e291a6","src/glean.udl":"0fcf72a8e3304d98e896dd3dfd9787208776c2b21b59f1c241029978ee37a925","src/glean_metrics.rs":"9414fb1453d19f6832df33e4c6ef7383d62203e47026bf5bc9552b083101ddd1","src/histogram/exponential.rs":"58bb1770bae45770d92995515d328eb50a7e78726224f779446ae7d1632a6a3e","src/histogram/functional.rs":"1a63a305b48bcef7bc38136b40d916df4bb8f098dc602514ada54a9b091f6951","src/histogram/linear.rs":"4342a1733175d7f97b2b41adb18100537c206100c9fccb5bd13bd782c9cb3c9a","src/histogram/mod.rs":"bbb9535a633b5a85b6b11c6e4eed3314ab797950355a9bb8ccf3a22000f1e093","src/internal_metrics.rs":"263779535963a804c8c7fa6f8e284ac8ec7f415ceeadbb6a8f913a1e7073ae18","src/internal_pings.rs":"0e3b8ce673cf92bd085fd4f07aa43876c97472dbd921a2d0dc0f10c9fe6b1c6b","src/lib.rs":"fb50a72a7221358c5daa1a8c0e59c92d5d358adc10b1ba9b831d2f07c07d90e2","src/lib_unit_tests.rs":"76d1997f7608b735cc4e905cfa94f79dd71a4a2ed1eccaa89d3d72ccd8d348e2","src/metrics/boolean.rs":"2b9ef57e3582c9bd8b2cca8ab94c962a4871ecc00e837b913c9b0349ba9dff08","src/metrics/counter.rs":"b4a52a8167fb0edd6354f952525e59f3eadb4261de3483374f03c94449d30b92","src/metrics/custom_distribution.rs":"e1f2edfefb67da4bf369bab3d3047f4ff6539a1fea0eee81c78d96626e5b4bb0","src/metrics/datetime.rs":"e4405762fc71718299fa1b208e3d5fda654bd1b82fe908c884c284e3530de2ec","src/metrics/denominator.rs":"95e8442f90bad97f80fc74b146782f215344b52c5f3825ae0a8baffdc001a714","src/metrics/event.rs":"cd52e200d313e2e6f31707419d4a7fe1cab34916ee145f8136440d6da34aaad4","src/metrics/experiment.rs":"5f9278cca4e133eb8df33bbfe36d1fe0ef3eade8c09f1b46db3c4d0790515412","src/metrics/labeled.rs":"8d6e76a07064d132cd617c7901f2bc11ff6ba31e3483ba3b96354a4a3736b58d","src/metrics/memory_distribution.rs":"7f6ca51acb470df277ff14427c0e7bb07d921c0a0087d0cc56aebe038d198ccc","src/metrics/memory_unit.rs":"ee32e020cb303dd631457374048a3ed53a2e7cbacc29c54d17d836fb15507538","src/metrics/metrics_enabled_config.rs":"c45f2cd48b36f8706e0e1d402d6fc375f5bab50f7d0840e0fbbbeacb6f2732af","src/metrics/mod.rs":"8f8958b8cedfe01df6c97ec26b63f14fd7516f9de7ba62984062db96b5708720","src/metrics/numerator.rs":"937dfd583b797ac798a525cedca95c5a36262356760a89670d8113983c263154","src/metrics/object.rs":"89ce5190ed681b26b74a06a4ecaf9f96c36f96be1276f1fdb40f4406648e08c1","src/metrics/ping.rs":"86dc577422075c759edb998acbd890c239569d72b30a994e7777d6d0f7676c5a","src/metrics/quantity.rs":"aa13a8f8cf8e5e0281668fbbafc2998411df2a499479423558fd91b9bd7f8702","src/metrics/rate.rs":"603cc45c149c7a27c93b6a80146bf43f8ce70d9655f905bb5be6bc2c15bcb22b","src/metrics/recorded_experiment.rs":"33958abee79d8b55dec4cb5d20742640423713010f76314075cefde18b5c118a","src/metrics/string.rs":"0906b4d5ec1ec10b7a56fd6eb39dc30500531658df2c8bc3f55c9579e15c88db","src/metrics/string_list.rs":"ed53a095184c3e8224d0511809b5d7601ba3166505a39b0570f24ebeb0a5b97c","src/metrics/text.rs":"757f6919124d74e0512faa5bb9751a729b6bbc63ebe4d16ca81e9087f5595eaf","src/metrics/time_unit.rs":"4704703e19e799933aec3f39e3d3a125058756d7c7ba04f8729885c7843df447","src/metrics/timespan.rs":"1ad5233c7522cab70b4c095fb24cace66ace9741731f97bc001ede071f10d1ef","src/metrics/timing_distribution.rs":"261f971d012e80e93180caea69da549498597d47771264c9bb0667a9573f47ed","src/metrics/url.rs":"589ae1f8047367ad8c19b57a48ca8130d5f36cf3ce5954124150f0eb89c620ea","src/metrics/uuid.rs":"cacffd95ab30ed327ec2fa5feaf1359e667706746401f1e2c1195ad9553c4b54","src/ping/mod.rs":"fcadd52d2d536c9ace01f8a3812c3fb3c39b8094915db1b3656839fb87f771b5","src/scheduler.rs":"129863e31205404a3d1708627a62583324c347d143f976216f769893ec541ea0","src/storage/mod.rs":"91f02556f113799e0d88d732ab342bda443f43461369e8b41c424c074d742591","src/system.rs":"e3d1b54e1d39cafe6f4dc7ff5021b08c879733f909951b0e1332b3efa9ed97bd","src/traits/boolean.rs":"be0e130f8043215705becc956d45b126c340568f1b24a396c0af9b4334a41ced","src/traits/counter.rs":"c686d26e131d854cd7a7df83c900ca7c17a03c663a30cf58ab48c7259476ce85","src/traits/custom_distribution.rs":"0bd1d425e4c059cca6af2dfb13c78e5e4c6c07fb46c7e31489ad0c5959854833","src/traits/datetime.rs":"636ac1456b1b042e38cf5ae6193c5b232ea0b80df62f583a2097891baef9641b","src/traits/event.rs":"a02235aae630aba7a45a3166b756927252b397af3ecdfab7236931e62725ac49","src/traits/labeled.rs":"c633c68e70a44e73f8aff88aaab1029c0faded3cad08d822590ed8838f24b4fd","src/traits/memory_distribution.rs":"55bb8f45e948319fbba9d28a50d8742da134b066a42e480887db7c7e435f4096","src/traits/mod.rs":"d14b69d0946848c1f92cc8977cbc3fc9338ff1b53b7acc31ea0fe2f1122beecb","src/traits/numerator.rs":"6e4f236bdc448f1bde7a8c249dcd086204c2c69990d3f444e746290929226ed3","src/traits/object.rs":"c03bad670ec7affbc578247f9e1904e898c1870b9bf25750c5094113f995623f","src/traits/ping.rs":"8831c106c03afeb458b0b028fa1ce61f056ebf8e82bc0a171a1bff255d920748","src/traits/quantity.rs":"6ffe25c913bef4315573d747308c182de740b2a4e02ba22cd21d0c33ba521f31","src/traits/rate.rs":"f000790440e0f389f0b160526a9a9a266e58d1405915ae56ac550f482858222c","src/traits/string.rs":"0c3c88382ff2e8eba89c7cfe129c4b84e31140af717819533c14919541ad790c","src/traits/string_list.rs":"14e56b62c2c2be1dd8013f12001f235b084abd2a0d5aa2f7932843877af49ac0","src/traits/text.rs":"8af7d3a0c87cfd8c6d33d6ad47532b431055bbdd395f9110da5630222c23cf93","src/traits/timespan.rs":"52be325a9c061916f34c5b638a07a93b4a14aa89fe365783103d2e06b998f547","src/traits/timing_distribution.rs":"00ebdef647a7a208c01d13ba7b3996750e36de98d1f63859b609c80c8df25b6f","src/traits/url.rs":"c27f7add23214ff051078b65b88120b620560d2841a1056c7214d5237e86b9e4","src/traits/uuid.rs":"81322e71c7e847bacaf827a2cd58f6193bdc208355524207f7f38db039da6aa8","src/upload/directory.rs":"e42c62f27ace5c6504cc7703a4c1d9ffd0e6ac7c4fba7d7dee231430fb67f8f8","src/upload/mod.rs":"6151a6d3b4fccb3df7ef03207e2f77bf34dbf04b3b705e2af55dd02a731f99f8","src/upload/policy.rs":"c250957a37783e74af8002cd80ba06ef9780a389fb0f61b8b665b79688f0a360","src/upload/request.rs":"5891364d4254aafdb43751f476b0b908b681544793ac98802fe103de321ec326","src/upload/result.rs":"7efbbe50e8d36beb3f23e7bfd172d22e1c003472d2dd8055b06f6050c36437c5","src/util.rs":"ee7500434d9758a320dd410f18d7e18da956591e19d2555db87eef9623e4b916","tests/boolean.rs":"76d6014ff108cb6514d9bceb1b2b14749a55b09921f4595a5e30f1bd3546e9f0","tests/common/mod.rs":"c5bf5a9f3660ae1a1c1dbb659ab6be60438c58bc7c459f2f96dca467d05d4ab3","tests/counter.rs":"3663a3f5ec5c0bd2b758a9920cd20cc619a12566b445e4421ec7c98232bf5a32","tests/custom_distribution.rs":"41c593a0b4561e21f29d1a5b948de964a866253c58ca76ffefebe370fca150e0","tests/datetime.rs":"ec3c9760e70bb2cbc61ab23281c891bc1ec493c5c545466c29fd13e4f05c2c96","tests/event.rs":"0fbec0e8929c99603b79c62a1f57f8cabe614451fdafb6eb9d47f22116303245","tests/labeled.rs":"e9ea6dba17059d68114efce0c23373be9ceed922bf5e638a2158a6422c75a1c1","tests/memory_distribution.rs":"a5a7aa955e60823ea29a6f4bc96c61e41f1e41f08958aa4854668cf8fe04cde6","tests/object.rs":"8c35676e04f6ccf54a28764700915e753fc0355bfa5d7804d72caba66fd564cd","tests/ping.rs":"eb9f6be1aba21acc5dc670622bf622976718a706df1cc2095efa56a8e8b3fe1a","tests/ping_maker.rs":"7ad1f76a1eda2dabf0422fff74d9c2c1a39b9d1d315a4dbe6057dff44efcfae0","tests/quantity.rs":"55e7dca346fd1d27f0974b78ca3fb12427cb5da2ee637afc08a54f360f947361","tests/rate.rs":"1de571b9f0ee9a9006cbc8a31f91352d3ff1190b50840f0f668b470a7cd2a3a5","tests/storage.rs":"f0c8312bd789d7bda502cd45f35fef6b8591652bd194d07da4d81935ebe69b48","tests/string.rs":"7ece988a4b8efe6932ccb90bfe2f3c8aaea983777e99d7de6028bf6a29459ee6","tests/string_list.rs":"77188a2b90663c3f8dac5da89a6cb6b1d16a9f8c66ccd032d02966dfd14a3486","tests/text.rs":"1d43f6b90a43124311cacf0a6ee16f9e1e9263bcd11fee8b996d6efd81633638","tests/timespan.rs":"d50d75c7d75da3a878d67331cb0df8ae5e6a099ffab474361f71a408e02528d7","tests/timing_distribution.rs":"20860a7baccdcee6aed40c9cc8202b94f3b2e61164fbaf8f2af96b0f404a895a","tests/uuid.rs":"052ad26a6927c56272219340211cf4a059d200f14287b482fe8621d7bce3cc54","uniffi.toml":"6ddc98b686b0925a81abd9d1c769e5c98ac29771b210a1c535931a46dec9a8e3"},"package":"ea06a592b1395e0a16a5f4d6872f009ca7c98acc5127a8119088f1b435b5aaae"} \ No newline at end of file
+{"files":{"Cargo.toml":"76031a9e743406219c98ef0c831e573b693c0db01ae7702a80917ce4816424df","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"026495898699b54608eb4ec16074ffafc57920d80ccb59961c501a1ea28c9985","build.rs":"4857bea99c6b8c08db8818efa9d3738716f52d3acb68159323957ae52892a3eb","src/common_metric_data.rs":"02dd1628fed6587621c089952dd0cb80bed3c352cdacfb33be7e218ad1d847e9","src/core/mod.rs":"a6a919646309d94b6d8b729cd717d5b6f2925095b88f5d11b4222cfd38998b40","src/core_metrics.rs":"a877e42e0f8b932adb52a5681ad76fd977808cb48c7eeb29b1e4bbe804f1ea96","src/coverage.rs":"49613fd310bd24d779472720975fbe6c97ec370a95eb55f10afa43f67539c942","src/database/mod.rs":"fb3caafb1e9dd08bd2559e56c5e0713d742795599d604a01b58b92db207e2842","src/debug.rs":"d0dfc0932a0953bbbe029f723bf2613c8d691f34b017e858030c46b02a46a17d","src/dispatcher/global.rs":"f69cd81a90a37c306d4e0ce8177ea5a3ae2ffda5b431ae46b9a22c9e38891271","src/dispatcher/mod.rs":"391310269947452d7e0de24c848c183110c60149d75e345ba6d5d146f222dace","src/error.rs":"b93c7d3e243b21bb9eafc95f17860aba1a942b2f2b0a7f43307690f05fece516","src/error_recording.rs":"1aba34e9d3c741755055f5b76415114b25b146b0aa90049c3457cfe12066deda","src/event_database/mod.rs":"78633293e1f3c9e9d51705615a7a4b603d7f85567bfdc2b0bad35ccda6a12d44","src/fd_logger.rs":"0c9def6fa53db1a2ab93c85795f8a7df57797bcfd3978146923e151752e291a6","src/glean.udl":"ebc09d8b03eed846a79c9ddb6bc81dc57ca9c28586886805bbc0fb2d64a8e225","src/glean_metrics.rs":"9414fb1453d19f6832df33e4c6ef7383d62203e47026bf5bc9552b083101ddd1","src/histogram/exponential.rs":"58bb1770bae45770d92995515d328eb50a7e78726224f779446ae7d1632a6a3e","src/histogram/functional.rs":"1a63a305b48bcef7bc38136b40d916df4bb8f098dc602514ada54a9b091f6951","src/histogram/linear.rs":"4342a1733175d7f97b2b41adb18100537c206100c9fccb5bd13bd782c9cb3c9a","src/histogram/mod.rs":"bbb9535a633b5a85b6b11c6e4eed3314ab797950355a9bb8ccf3a22000f1e093","src/internal_metrics.rs":"263779535963a804c8c7fa6f8e284ac8ec7f415ceeadbb6a8f913a1e7073ae18","src/internal_pings.rs":"c54339cb2530eec7717a3f6dd81ce98adf5da5d615bcf0a071fd90f415016866","src/lib.rs":"0fab5462a6b2a86244cfd7b3cdf99996b4b410f34ee9f0f8e16758fafdcfa389","src/lib_unit_tests.rs":"6180628e46d3dbcd8dbd5e7f3cdbc12a3987c0b3a9d6638ab1341f3f3d666db7","src/metrics/boolean.rs":"2b9ef57e3582c9bd8b2cca8ab94c962a4871ecc00e837b913c9b0349ba9dff08","src/metrics/counter.rs":"b4a52a8167fb0edd6354f952525e59f3eadb4261de3483374f03c94449d30b92","src/metrics/custom_distribution.rs":"e1f2edfefb67da4bf369bab3d3047f4ff6539a1fea0eee81c78d96626e5b4bb0","src/metrics/datetime.rs":"e4405762fc71718299fa1b208e3d5fda654bd1b82fe908c884c284e3530de2ec","src/metrics/denominator.rs":"95e8442f90bad97f80fc74b146782f215344b52c5f3825ae0a8baffdc001a714","src/metrics/event.rs":"cd52e200d313e2e6f31707419d4a7fe1cab34916ee145f8136440d6da34aaad4","src/metrics/experiment.rs":"5f9278cca4e133eb8df33bbfe36d1fe0ef3eade8c09f1b46db3c4d0790515412","src/metrics/labeled.rs":"8d6e76a07064d132cd617c7901f2bc11ff6ba31e3483ba3b96354a4a3736b58d","src/metrics/memory_distribution.rs":"7f6ca51acb470df277ff14427c0e7bb07d921c0a0087d0cc56aebe038d198ccc","src/metrics/memory_unit.rs":"ee32e020cb303dd631457374048a3ed53a2e7cbacc29c54d17d836fb15507538","src/metrics/mod.rs":"cc99e7b27a5cecc974475790e1bd4cce86813b881e3c1d858aa446c9fe5183f8","src/metrics/numerator.rs":"937dfd583b797ac798a525cedca95c5a36262356760a89670d8113983c263154","src/metrics/object.rs":"2a1f1cc31973b576e55ba464b35c41b9420f62471eebba51273bca6856459538","src/metrics/ping.rs":"ac4cdda5cc94ddf2a2206188abcfa3517de4500ba3eadd976758fb9cffcb3624","src/metrics/quantity.rs":"aa13a8f8cf8e5e0281668fbbafc2998411df2a499479423558fd91b9bd7f8702","src/metrics/rate.rs":"603cc45c149c7a27c93b6a80146bf43f8ce70d9655f905bb5be6bc2c15bcb22b","src/metrics/recorded_experiment.rs":"33958abee79d8b55dec4cb5d20742640423713010f76314075cefde18b5c118a","src/metrics/remote_settings_config.rs":"3565514a0444cb322e1f7944417167233d727a195c837bd7aee5eae88d5f0766","src/metrics/string.rs":"0906b4d5ec1ec10b7a56fd6eb39dc30500531658df2c8bc3f55c9579e15c88db","src/metrics/string_list.rs":"ed53a095184c3e8224d0511809b5d7601ba3166505a39b0570f24ebeb0a5b97c","src/metrics/text.rs":"757f6919124d74e0512faa5bb9751a729b6bbc63ebe4d16ca81e9087f5595eaf","src/metrics/time_unit.rs":"4704703e19e799933aec3f39e3d3a125058756d7c7ba04f8729885c7843df447","src/metrics/timespan.rs":"1ad5233c7522cab70b4c095fb24cace66ace9741731f97bc001ede071f10d1ef","src/metrics/timing_distribution.rs":"261f971d012e80e93180caea69da549498597d47771264c9bb0667a9573f47ed","src/metrics/url.rs":"589ae1f8047367ad8c19b57a48ca8130d5f36cf3ce5954124150f0eb89c620ea","src/metrics/uuid.rs":"cacffd95ab30ed327ec2fa5feaf1359e667706746401f1e2c1195ad9553c4b54","src/ping/mod.rs":"4c427ee29a7555c8577bd97fc4b85de4158f10062f73a5ee16b2a5d335b838b9","src/scheduler.rs":"129863e31205404a3d1708627a62583324c347d143f976216f769893ec541ea0","src/storage/mod.rs":"91f02556f113799e0d88d732ab342bda443f43461369e8b41c424c074d742591","src/system.rs":"e3d1b54e1d39cafe6f4dc7ff5021b08c879733f909951b0e1332b3efa9ed97bd","src/traits/boolean.rs":"be0e130f8043215705becc956d45b126c340568f1b24a396c0af9b4334a41ced","src/traits/counter.rs":"c686d26e131d854cd7a7df83c900ca7c17a03c663a30cf58ab48c7259476ce85","src/traits/custom_distribution.rs":"0bd1d425e4c059cca6af2dfb13c78e5e4c6c07fb46c7e31489ad0c5959854833","src/traits/datetime.rs":"636ac1456b1b042e38cf5ae6193c5b232ea0b80df62f583a2097891baef9641b","src/traits/event.rs":"a02235aae630aba7a45a3166b756927252b397af3ecdfab7236931e62725ac49","src/traits/labeled.rs":"c633c68e70a44e73f8aff88aaab1029c0faded3cad08d822590ed8838f24b4fd","src/traits/memory_distribution.rs":"55bb8f45e948319fbba9d28a50d8742da134b066a42e480887db7c7e435f4096","src/traits/mod.rs":"d14b69d0946848c1f92cc8977cbc3fc9338ff1b53b7acc31ea0fe2f1122beecb","src/traits/numerator.rs":"6e4f236bdc448f1bde7a8c249dcd086204c2c69990d3f444e746290929226ed3","src/traits/object.rs":"c03bad670ec7affbc578247f9e1904e898c1870b9bf25750c5094113f995623f","src/traits/ping.rs":"8831c106c03afeb458b0b028fa1ce61f056ebf8e82bc0a171a1bff255d920748","src/traits/quantity.rs":"6ffe25c913bef4315573d747308c182de740b2a4e02ba22cd21d0c33ba521f31","src/traits/rate.rs":"f000790440e0f389f0b160526a9a9a266e58d1405915ae56ac550f482858222c","src/traits/string.rs":"0c3c88382ff2e8eba89c7cfe129c4b84e31140af717819533c14919541ad790c","src/traits/string_list.rs":"14e56b62c2c2be1dd8013f12001f235b084abd2a0d5aa2f7932843877af49ac0","src/traits/text.rs":"8af7d3a0c87cfd8c6d33d6ad47532b431055bbdd395f9110da5630222c23cf93","src/traits/timespan.rs":"52be325a9c061916f34c5b638a07a93b4a14aa89fe365783103d2e06b998f547","src/traits/timing_distribution.rs":"00ebdef647a7a208c01d13ba7b3996750e36de98d1f63859b609c80c8df25b6f","src/traits/url.rs":"c27f7add23214ff051078b65b88120b620560d2841a1056c7214d5237e86b9e4","src/traits/uuid.rs":"81322e71c7e847bacaf827a2cd58f6193bdc208355524207f7f38db039da6aa8","src/upload/directory.rs":"5545042c1d1f37ebb08445b88c0fa8b97aad145e81e34051fad3da2a94b1b52d","src/upload/mod.rs":"7b65a31ed8b12c4a7e708edb9bbf48ab6a4c99422b4bb1f50891cde07f5e6a3c","src/upload/policy.rs":"c250957a37783e74af8002cd80ba06ef9780a389fb0f61b8b665b79688f0a360","src/upload/request.rs":"5891364d4254aafdb43751f476b0b908b681544793ac98802fe103de321ec326","src/upload/result.rs":"7efbbe50e8d36beb3f23e7bfd172d22e1c003472d2dd8055b06f6050c36437c5","src/util.rs":"ee7500434d9758a320dd410f18d7e18da956591e19d2555db87eef9623e4b916","tests/boolean.rs":"76d6014ff108cb6514d9bceb1b2b14749a55b09921f4595a5e30f1bd3546e9f0","tests/common/mod.rs":"c5bf5a9f3660ae1a1c1dbb659ab6be60438c58bc7c459f2f96dca467d05d4ab3","tests/counter.rs":"3663a3f5ec5c0bd2b758a9920cd20cc619a12566b445e4421ec7c98232bf5a32","tests/custom_distribution.rs":"41c593a0b4561e21f29d1a5b948de964a866253c58ca76ffefebe370fca150e0","tests/datetime.rs":"ec3c9760e70bb2cbc61ab23281c891bc1ec493c5c545466c29fd13e4f05c2c96","tests/event.rs":"3cfe41e67d300683f690a672cc82ca2f29658c870ba78b824f9e1e3d3556a2b5","tests/labeled.rs":"e9ea6dba17059d68114efce0c23373be9ceed922bf5e638a2158a6422c75a1c1","tests/memory_distribution.rs":"a5a7aa955e60823ea29a6f4bc96c61e41f1e41f08958aa4854668cf8fe04cde6","tests/object.rs":"8c35676e04f6ccf54a28764700915e753fc0355bfa5d7804d72caba66fd564cd","tests/ping.rs":"6dd56b6ca2206b687fc5e67e8c603872a5b60c5847c6ecb0c8f789fdd94b2c09","tests/ping_maker.rs":"48d25109154033ccf6783f2e9bfc30d2ec26876e0092d648c40062fb67cc9925","tests/quantity.rs":"55e7dca346fd1d27f0974b78ca3fb12427cb5da2ee637afc08a54f360f947361","tests/rate.rs":"1de571b9f0ee9a9006cbc8a31f91352d3ff1190b50840f0f668b470a7cd2a3a5","tests/storage.rs":"f0c8312bd789d7bda502cd45f35fef6b8591652bd194d07da4d81935ebe69b48","tests/string.rs":"7ece988a4b8efe6932ccb90bfe2f3c8aaea983777e99d7de6028bf6a29459ee6","tests/string_list.rs":"77188a2b90663c3f8dac5da89a6cb6b1d16a9f8c66ccd032d02966dfd14a3486","tests/text.rs":"1d43f6b90a43124311cacf0a6ee16f9e1e9263bcd11fee8b996d6efd81633638","tests/timespan.rs":"d50d75c7d75da3a878d67331cb0df8ae5e6a099ffab474361f71a408e02528d7","tests/timing_distribution.rs":"20860a7baccdcee6aed40c9cc8202b94f3b2e61164fbaf8f2af96b0f404a895a","tests/uuid.rs":"052ad26a6927c56272219340211cf4a059d200f14287b482fe8621d7bce3cc54","uniffi.toml":"6ddc98b686b0925a81abd9d1c769e5c98ac29771b210a1c535931a46dec9a8e3"},"package":"86db1cca10118079e9ae34681a6f762f6c51150971552e98f0dfec1d7a556c21"} \ No newline at end of file
diff --git a/third_party/rust/glean-core/Cargo.toml b/third_party/rust/glean-core/Cargo.toml
index 932b16a4a7..fba18dd4d8 100644
--- a/third_party/rust/glean-core/Cargo.toml
+++ b/third_party/rust/glean-core/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.66"
name = "glean-core"
-version = "59.0.0"
+version = "60.0.1"
authors = [
"Jan-Erik Rediger <jrediger@mozilla.com>",
"The Glean Team <glean-team@mozilla.com>",
@@ -35,7 +35,7 @@ license = "MPL-2.0"
repository = "https://github.com/mozilla/glean"
[package.metadata.glean]
-glean-parser = "13.0.0"
+glean-parser = "14.0.1"
[dependencies.bincode]
version = "1.2.1"
diff --git a/third_party/rust/glean-core/src/common_metric_data.rs b/third_party/rust/glean-core/src/common_metric_data.rs
index 9bda9bb462..f5058d995f 100644
--- a/third_party/rust/glean-core/src/common_metric_data.rs
+++ b/third_party/rust/glean-core/src/common_metric_data.rs
@@ -90,9 +90,10 @@ impl Clone for CommonMetricDataInternal {
impl From<CommonMetricData> for CommonMetricDataInternal {
fn from(input_data: CommonMetricData) -> Self {
+ let disabled = input_data.disabled;
Self {
- inner: input_data.clone(),
- disabled: AtomicU8::new(u8::from(input_data.disabled)),
+ inner: input_data,
+ disabled: AtomicU8::new(u8::from(disabled)),
}
}
}
diff --git a/third_party/rust/glean-core/src/core/mod.rs b/third_party/rust/glean-core/src/core/mod.rs
index f69f0c3868..9b8cfe531b 100644
--- a/third_party/rust/glean-core/src/core/mod.rs
+++ b/third_party/rust/glean-core/src/core/mod.rs
@@ -16,7 +16,7 @@ use crate::event_database::EventDatabase;
use crate::internal_metrics::{AdditionalMetrics, CoreMetrics, DatabaseMetrics};
use crate::internal_pings::InternalPings;
use crate::metrics::{
- self, ExperimentMetric, Metric, MetricType, MetricsEnabledConfig, PingType, RecordedExperiment,
+ self, ExperimentMetric, Metric, MetricType, PingType, RecordedExperiment, RemoteSettingsConfig,
};
use crate::ping::PingMaker;
use crate::storage::{StorageManager, INTERNAL_STORAGE};
@@ -123,7 +123,7 @@ where
/// enable_internal_pings: true,
/// };
/// let mut glean = Glean::new(cfg).unwrap();
-/// let ping = PingType::new("sample", true, false, true, true, vec![]);
+/// let ping = PingType::new("sample", true, false, true, true, true, vec![], vec![]);
/// glean.register_ping_type(&ping);
///
/// let call_counter: CounterMetric = CounterMetric::new(CommonMetricData {
@@ -162,7 +162,7 @@ pub struct Glean {
pub(crate) app_build: String,
pub(crate) schedule_metrics_pings: bool,
pub(crate) remote_settings_epoch: AtomicU8,
- pub(crate) remote_settings_metrics_config: Arc<Mutex<MetricsEnabledConfig>>,
+ pub(crate) remote_settings_config: Arc<Mutex<RemoteSettingsConfig>>,
pub(crate) with_timestamps: bool,
}
@@ -222,7 +222,7 @@ impl Glean {
// Subprocess doesn't use "metrics" pings so has no need for a scheduler.
schedule_metrics_pings: false,
remote_settings_epoch: AtomicU8::new(0),
- remote_settings_metrics_config: Arc::new(Mutex::new(MetricsEnabledConfig::new())),
+ remote_settings_config: Arc::new(Mutex::new(RemoteSettingsConfig::new())),
with_timestamps: cfg.enable_event_timestamps,
};
@@ -758,19 +758,26 @@ impl Glean {
.get_value(self, None)
}
- /// Set configuration to override the default metric enabled/disabled state, typically from a
+ /// Set configuration to override the default state, typically initiated from a
/// remote_settings experiment or rollout
///
/// # Arguments
///
- /// * `json` - The stringified JSON representation of a `MetricsEnabledConfig` object
- pub fn set_metrics_enabled_config(&self, cfg: MetricsEnabledConfig) {
- // Set the current MetricsEnabledConfig, keeping the lock until the epoch is
+ /// * `cfg` - The stringified JSON representation of a `RemoteSettingsConfig` object
+ pub fn apply_server_knobs_config(&self, cfg: RemoteSettingsConfig) {
+ // Set the current RemoteSettingsConfig, keeping the lock until the epoch is
// updated to prevent against reading a "new" config but an "old" epoch
- let mut metric_config = self.remote_settings_metrics_config.lock().unwrap();
+ let mut remote_settings_config = self.remote_settings_config.lock().unwrap();
- // Merge the exising configuration with the supplied one
- metric_config.metrics_enabled.extend(cfg.metrics_enabled);
+ // Merge the exising metrics configuration with the supplied one
+ remote_settings_config
+ .metrics_enabled
+ .extend(cfg.metrics_enabled);
+
+ // Merge the exising ping configuration with the supplied one
+ remote_settings_config
+ .pings_enabled
+ .extend(cfg.pings_enabled);
// Update remote_settings epoch
self.remote_settings_epoch.fetch_add(1, Ordering::SeqCst);
diff --git a/third_party/rust/glean-core/src/database/mod.rs b/third_party/rust/glean-core/src/database/mod.rs
index 0dbf0220bc..75a068b42e 100644
--- a/third_party/rust/glean-core/src/database/mod.rs
+++ b/third_party/rust/glean-core/src/database/mod.rs
@@ -9,6 +9,8 @@ use std::io;
use std::num::NonZeroU64;
use std::path::Path;
use std::str;
+#[cfg(target_os = "android")]
+use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::RwLock;
use crate::ErrorKind;
@@ -167,6 +169,13 @@ use crate::Glean;
use crate::Lifetime;
use crate::Result;
+/// The number of writes we accept writes to the ping-lifetime in-memory map
+/// before data is flushed to disk.
+///
+/// Only considered if `delay_ping_lifetime_io` is set to `true`.
+#[cfg(target_os = "android")]
+const PING_LIFETIME_THRESHOLD: usize = 1000;
+
pub struct Database {
/// Handle to the database environment.
rkv: Rkv,
@@ -184,6 +193,14 @@ pub struct Database {
/// so as to persist them to disk using rkv in bulk on demand.
ping_lifetime_data: Option<RwLock<BTreeMap<String, Metric>>>,
+ /// A count of how many database writes have been done since the last ping-lifetime flush.
+ ///
+ /// A ping-lifetime flush is automatically done after `PING_LIFETIME_THRESHOLD` writes.
+ ///
+ /// Only relevant if `delay_ping_lifetime_io` is set to `true`,
+ #[cfg(target_os = "android")]
+ ping_lifetime_count: AtomicUsize,
+
/// Initial file size when opening the database.
file_size: Option<NonZeroU64>,
@@ -263,6 +280,8 @@ impl Database {
ping_store,
application_store,
ping_lifetime_data,
+ #[cfg(target_os = "android")]
+ ping_lifetime_count: AtomicUsize::new(0),
file_size,
rkv_load_state,
};
@@ -528,6 +547,9 @@ impl Database {
.write()
.expect("Can't read ping lifetime data");
data.insert(final_key, metric.clone());
+
+ // flush ping lifetime
+ self.persist_ping_lifetime_data_if_full(&data)?;
return Ok(());
}
}
@@ -609,6 +631,9 @@ impl Database {
entry.insert(transform(Some(old_value)));
}
}
+
+ // flush ping lifetime
+ self.persist_ping_lifetime_data_if_full(&data)?;
return Ok(());
}
}
@@ -802,6 +827,10 @@ impl Database {
.read()
.expect("Can't read ping lifetime data");
+ // We can reset the write-counter. Current data has been persisted.
+ #[cfg(target_os = "android")]
+ self.ping_lifetime_count.store(0, Ordering::Release);
+
self.write_with_store(Lifetime::Ping, |mut writer, store| {
for (key, value) in data.iter() {
let encoded =
@@ -817,6 +846,42 @@ impl Database {
}
Ok(())
}
+
+ pub fn persist_ping_lifetime_data_if_full(
+ &self,
+ data: &BTreeMap<String, Metric>,
+ ) -> Result<()> {
+ #[cfg(target_os = "android")]
+ {
+ self.ping_lifetime_count.fetch_add(1, Ordering::Release);
+
+ let write_count = self.ping_lifetime_count.load(Ordering::Relaxed);
+ if write_count < PING_LIFETIME_THRESHOLD {
+ return Ok(());
+ }
+
+ self.ping_lifetime_count.store(0, Ordering::Release);
+ let write_result = self.write_with_store(Lifetime::Ping, |mut writer, store| {
+ for (key, value) in data.iter() {
+ let encoded =
+ bincode::serialize(&value).expect("IMPOSSIBLE: Serializing metric failed");
+ // There is no need for `get_storage_key` here because
+ // the key is already formatted from when it was saved
+ // to ping_lifetime_data.
+ store.put(&mut writer, key, &rkv::Value::Blob(&encoded))?;
+ }
+ writer.commit()?;
+ Ok(())
+ });
+
+ return write_result;
+ }
+ #[cfg(not(target_os = "android"))]
+ {
+ _ = data; // suppress unused_variables warning.
+ Ok(())
+ }
+ }
}
#[cfg(test)]
diff --git a/third_party/rust/glean-core/src/glean.udl b/third_party/rust/glean-core/src/glean.udl
index dc71fea594..b107a36f28 100644
--- a/third_party/rust/glean-core/src/glean.udl
+++ b/third_party/rust/glean-core/src/glean.udl
@@ -47,12 +47,14 @@ namespace glean {
void glean_unregister_event_listener(string tag);
// Server Knobs API
- void glean_set_metrics_enabled_config(string json);
+ void glean_apply_server_knobs_config(string json);
boolean glean_set_debug_view_tag(string tag);
boolean glean_set_source_tags(sequence<string> tags);
void glean_set_log_pings(boolean value);
+ void glean_persist_ping_lifetime_data();
+
void glean_handle_client_active();
void glean_handle_client_inactive();
@@ -292,7 +294,7 @@ enum ErrorType {
};
interface PingType {
- constructor(string name, boolean include_client_id, boolean send_if_empty, boolean precise_timestamps, boolean include_info_sections, sequence<string> reason_codes);
+ constructor(string name, boolean include_client_id, boolean send_if_empty, boolean precise_timestamps, boolean include_info_sections, boolean enabled, sequence<string> schedules_pings, sequence<string> reason_codes);
void submit(optional string? reason = null);
};
@@ -640,3 +642,19 @@ interface TextMetric {
i32 test_get_num_recorded_errors(ErrorType error);
};
+
+// JSON data encoded into a string
+[Custom]
+typedef string JsonValue;
+
+interface ObjectMetric {
+ constructor(CommonMetricData meta);
+
+ void set_string(string object);
+
+ JsonValue? test_get_value(optional string? ping_name = null);
+
+ i32 test_get_num_recorded_errors(ErrorType error);
+
+ void record_schema_error();
+};
diff --git a/third_party/rust/glean-core/src/internal_pings.rs b/third_party/rust/glean-core/src/internal_pings.rs
index 1cf32feb60..4fe15352b2 100644
--- a/third_party/rust/glean-core/src/internal_pings.rs
+++ b/third_party/rust/glean-core/src/internal_pings.rs
@@ -21,25 +21,28 @@ pub struct InternalPings {
impl InternalPings {
pub fn new(enabled: bool) -> InternalPings {
InternalPings {
- baseline: PingType::new_internal(
+ baseline: PingType::new(
"baseline",
true,
true,
true,
true,
+ enabled,
+ vec![],
vec![
"active".to_string(),
"dirty_startup".to_string(),
"inactive".to_string(),
],
- enabled,
),
- metrics: PingType::new_internal(
+ metrics: PingType::new(
"metrics",
true,
false,
true,
true,
+ enabled,
+ vec![],
vec![
"overdue".to_string(),
"reschedule".to_string(),
@@ -47,20 +50,20 @@ impl InternalPings {
"tomorrow".to_string(),
"upgrade".to_string(),
],
- enabled,
),
- events: PingType::new_internal(
+ events: PingType::new(
"events",
true,
false,
true,
true,
+ enabled,
+ vec![],
vec![
"startup".to_string(),
"inactive".to_string(),
"max_capacity".to_string(),
],
- enabled,
),
deletion_request: PingType::new(
"deletion-request",
@@ -68,6 +71,8 @@ impl InternalPings {
true,
true,
true,
+ true, // The deletion-request should not be disabled
+ vec![],
vec!["at_init".to_string(), "set_upload_enabled".to_string()],
),
}
diff --git a/third_party/rust/glean-core/src/lib.rs b/third_party/rust/glean-core/src/lib.rs
index af68fde264..c79fa1e226 100644
--- a/third_party/rust/glean-core/src/lib.rs
+++ b/third_party/rust/glean-core/src/lib.rs
@@ -28,7 +28,7 @@ use log::LevelFilter;
use once_cell::sync::{Lazy, OnceCell};
use uuid::Uuid;
-use metrics::MetricsEnabledConfig;
+use metrics::RemoteSettingsConfig;
mod common_metric_data;
mod core;
@@ -68,9 +68,9 @@ pub use crate::metrics::labeled::{
pub use crate::metrics::{
BooleanMetric, CounterMetric, CustomDistributionMetric, Datetime, DatetimeMetric,
DenominatorMetric, DistributionData, EventMetric, MemoryDistributionMetric, MemoryUnit,
- NumeratorMetric, PingType, QuantityMetric, Rate, RateMetric, RecordedEvent, RecordedExperiment,
- StringListMetric, StringMetric, TextMetric, TimeUnit, TimerId, TimespanMetric,
- TimingDistributionMetric, UrlMetric, UuidMetric,
+ NumeratorMetric, ObjectMetric, PingType, QuantityMetric, Rate, RateMetric, RecordedEvent,
+ RecordedExperiment, StringListMetric, StringMetric, TextMetric, TimeUnit, TimerId,
+ TimespanMetric, TimingDistributionMetric, UrlMetric, UuidMetric,
};
pub use crate::upload::{PingRequest, PingUploadTask, UploadResult, UploadTaskAction};
@@ -693,7 +693,7 @@ pub fn shutdown() {
/// Only has effect when Glean is configured with `delay_ping_lifetime_io: true`.
/// If Glean hasn't been initialized this will dispatch and return Ok(()),
/// otherwise it will block until the persist is done and return its Result.
-pub fn persist_ping_lifetime_data() {
+pub fn glean_persist_ping_lifetime_data() {
// This is async, we can't get the Error back to the caller.
crate::launch_with_glean(|glean| {
let _ = glean.persist_ping_lifetime_data();
@@ -910,17 +910,17 @@ pub fn glean_test_get_experimentation_id() -> Option<String> {
/// Sets a remote configuration to override metrics' default enabled/disabled
/// state
///
-/// See [`core::Glean::set_metrics_enabled_config`].
-pub fn glean_set_metrics_enabled_config(json: String) {
+/// See [`core::Glean::apply_server_knobs_config`].
+pub fn glean_apply_server_knobs_config(json: String) {
// An empty config means it is not set,
// so we avoid logging an error about it.
if json.is_empty() {
return;
}
- match MetricsEnabledConfig::try_from(json) {
+ match RemoteSettingsConfig::try_from(json) {
Ok(cfg) => launch_with_glean(|glean| {
- glean.set_metrics_enabled_config(cfg);
+ glean.apply_server_knobs_config(cfg);
}),
Err(e) => {
log::error!("Error setting metrics feature config: {:?}", e);
@@ -1125,8 +1125,14 @@ pub fn glean_test_destroy_glean(clear_stores: bool, data_path: Option<String>) {
// Only useful if Glean initialization finished successfully
// and set up the storage.
- let has_storage =
- core::with_opt_glean(|glean| glean.storage_opt().is_some()).unwrap_or(false);
+ let has_storage = core::with_opt_glean(|glean| {
+ // We need to flush the ping lifetime data before a full shutdown.
+ glean
+ .storage_opt()
+ .map(|storage| storage.persist_ping_lifetime_data())
+ .is_some()
+ })
+ .unwrap_or(false);
if has_storage {
uploader_shutdown();
}
@@ -1229,6 +1235,20 @@ mod ffi {
obj.into_owned()
}
}
+
+ type JsonValue = serde_json::Value;
+
+ impl UniffiCustomTypeConverter for JsonValue {
+ type Builtin = String;
+
+ fn into_custom(val: Self::Builtin) -> uniffi::Result<Self> {
+ Ok(serde_json::from_str(&val)?)
+ }
+
+ fn from_custom(obj: Self) -> Self::Builtin {
+ serde_json::to_string(&obj).unwrap()
+ }
+ }
}
pub use ffi::*;
diff --git a/third_party/rust/glean-core/src/lib_unit_tests.rs b/third_party/rust/glean-core/src/lib_unit_tests.rs
index 14d3b98417..b74397317f 100644
--- a/third_party/rust/glean-core/src/lib_unit_tests.rs
+++ b/third_party/rust/glean-core/src/lib_unit_tests.rs
@@ -890,16 +890,17 @@ fn test_set_remote_metric_configuration() {
);
// 2. Set a configuration to disable the metrics
- let mut metrics_enabled_config = json!(
+ let mut remote_settings_config = json!(
{
- "category.string_metric": false,
- "category.labeled_string_metric": false,
+ "metrics_enabled": {
+ "category.string_metric": false,
+ "category.labeled_string_metric": false,
+ }
}
)
.to_string();
- glean.set_metrics_enabled_config(
- MetricsEnabledConfig::try_from(metrics_enabled_config).unwrap(),
- );
+ glean
+ .apply_server_knobs_config(RemoteSettingsConfig::try_from(remote_settings_config).unwrap());
// 3. Since the metrics were disabled, setting a new value will be ignored
metric.set_sync(&glean, "VALUE_AFTER_DISABLED");
@@ -921,15 +922,16 @@ fn test_set_remote_metric_configuration() {
);
// 4. Set a new configuration where one metric is enabled
- metrics_enabled_config = json!(
+ remote_settings_config = json!(
{
- "category.string_metric": true,
+ "metrics_enabled": {
+ "category.string_metric": true,
+ }
}
)
.to_string();
- glean.set_metrics_enabled_config(
- MetricsEnabledConfig::try_from(metrics_enabled_config).unwrap(),
- );
+ glean
+ .apply_server_knobs_config(RemoteSettingsConfig::try_from(remote_settings_config).unwrap());
// 5. Since the first metric is enabled, setting a new value should work
// on it but not the second metric
@@ -954,15 +956,16 @@ fn test_set_remote_metric_configuration() {
// 6. Set a new configuration where the second metric is enabled. This
// should be merged with the existing configuration and then both
// metrics should be enabled at that point.
- metrics_enabled_config = json!(
+ remote_settings_config = json!(
{
- "category.labeled_string_metric": true,
+ "metrics_enabled": {
+ "category.labeled_string_metric": true,
+ }
}
)
.to_string();
- glean.set_metrics_enabled_config(
- MetricsEnabledConfig::try_from(metrics_enabled_config).unwrap(),
- );
+ glean
+ .apply_server_knobs_config(RemoteSettingsConfig::try_from(remote_settings_config).unwrap());
// 7. Now both metrics are enabled, setting a new value should work for
// both metrics with the merged configurations
@@ -992,15 +995,16 @@ fn test_remote_settings_epoch() {
assert_eq!(0u8, current_epoch, "Current epoch must start at 0");
// 2. Set a configuration which will trigger incrementing the epoch
- let metrics_enabled_config = json!(
+ let remote_settings_config = json!(
{
- "category.string_metric": false
+ "metrics_enabled": {
+ "category.string_metric": false
+ }
}
)
.to_string();
- glean.set_metrics_enabled_config(
- MetricsEnabledConfig::try_from(metrics_enabled_config).unwrap(),
- );
+ glean
+ .apply_server_knobs_config(RemoteSettingsConfig::try_from(remote_settings_config).unwrap());
// 3. Ensure the epoch updated
current_epoch = glean.remote_settings_epoch.load(Ordering::Acquire);
@@ -1026,15 +1030,16 @@ fn test_remote_settings_epoch_updates_in_metric() {
);
// 2. Set a configuration to disable the `category.string_metric`
- let metrics_enabled_config = json!(
+ let remote_settings_config = json!(
{
- "category.string_metric": false
+ "metrics_enabled": {
+ "category.string_metric": false
+ }
}
)
.to_string();
- glean.set_metrics_enabled_config(
- MetricsEnabledConfig::try_from(metrics_enabled_config).unwrap(),
- );
+ glean
+ .apply_server_knobs_config(RemoteSettingsConfig::try_from(remote_settings_config).unwrap());
// 3. Ensure the epoch was updated
let current_epoch = glean.remote_settings_epoch.load(Ordering::Acquire);
@@ -1168,7 +1173,16 @@ fn disabled_pings_are_not_submitted() {
let dir = tempfile::tempdir().unwrap();
let (mut glean, _t) = new_glean(Some(dir));
- let ping = PingType::new_internal("custom-disabled", true, false, true, true, vec![], false);
+ let ping = PingType::new_internal(
+ "custom-disabled",
+ true,
+ false,
+ true,
+ true,
+ false,
+ vec![],
+ vec![],
+ );
glean.register_ping_type(&ping);
// We need to store a metric as an empty ping is not stored.
@@ -1203,3 +1217,53 @@ fn internal_pings_can_be_disabled() {
let submitted = glean.internal_pings.baseline.submit_sync(&glean, None);
assert!(!submitted);
}
+
+#[test]
+fn pings_are_controllable_from_remote_settings_config() {
+ let _ = env_logger::builder().is_test(true).try_init();
+
+ let dir = tempfile::tempdir().unwrap();
+ let (mut glean, _t) = new_glean(Some(dir));
+
+ let disabled_ping = PingType::new(
+ "custom-disabled",
+ true,
+ true,
+ true,
+ true,
+ false,
+ vec![],
+ vec![],
+ );
+ glean.register_ping_type(&disabled_ping);
+ let enabled_ping = PingType::new(
+ "custom-enabled",
+ true,
+ true,
+ true,
+ true,
+ true,
+ vec![],
+ vec![],
+ );
+ glean.register_ping_type(&enabled_ping);
+
+ assert!(!disabled_ping.submit_sync(&glean, None));
+ assert!(enabled_ping.submit_sync(&glean, None));
+
+ // Now, create a configuration to switch the enabled state of the two pings
+ let remote_settings_config = json!(
+ {
+ "pings_enabled": {
+ "custom-disabled": true,
+ "custom-enabled": false
+ }
+ }
+ )
+ .to_string();
+ glean
+ .apply_server_knobs_config(RemoteSettingsConfig::try_from(remote_settings_config).unwrap());
+
+ assert!(disabled_ping.submit_sync(&glean, None));
+ assert!(!enabled_ping.submit_sync(&glean, None));
+}
diff --git a/third_party/rust/glean-core/src/metrics/metrics_enabled_config.rs b/third_party/rust/glean-core/src/metrics/metrics_enabled_config.rs
deleted file mode 100644
index b36cbc150a..0000000000
--- a/third_party/rust/glean-core/src/metrics/metrics_enabled_config.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-use std::collections::HashMap;
-
-use serde::{Deserialize, Serialize};
-
-/// Represents a list of metrics and an associated boolean property
-/// indicating if the metric is enabledfrom the remote-settings
-/// configuration store. The expected format of this data is stringified JSON
-/// in the following format:
-/// ```json
-/// {
-/// "category.metric_name": true
-/// }
-/// ```
-#[derive(Serialize, Deserialize, Debug, Clone, Default)]
-pub struct MetricsEnabledConfig {
- /// This is a `HashMap` consisting of base_identifiers as keys
- /// and bool values representing an override for the `disabled`
- /// property of the metric, only inverted to reduce confusion.
- /// If a particular metric has a value of `true` here, it means
- /// the default of the metric will be overriden and set to the
- /// enabled state.
- #[serde(flatten)]
- pub metrics_enabled: HashMap<String, bool>,
-}
-
-impl MetricsEnabledConfig {
- /// Creates a new MetricsEnabledConfig
- pub fn new() -> Self {
- Default::default()
- }
-}
-
-impl TryFrom<String> for MetricsEnabledConfig {
- type Error = crate::ErrorKind;
-
- fn try_from(json: String) -> Result<Self, Self::Error> {
- match serde_json::from_str(json.as_str()) {
- Ok(config) => Ok(config),
- Err(e) => Err(crate::ErrorKind::Json(e)),
- }
- }
-}
diff --git a/third_party/rust/glean-core/src/metrics/mod.rs b/third_party/rust/glean-core/src/metrics/mod.rs
index 92001efd2a..9234fff2d1 100644
--- a/third_party/rust/glean-core/src/metrics/mod.rs
+++ b/third_party/rust/glean-core/src/metrics/mod.rs
@@ -22,13 +22,13 @@ mod experiment;
pub(crate) mod labeled;
mod memory_distribution;
mod memory_unit;
-mod metrics_enabled_config;
mod numerator;
mod object;
mod ping;
mod quantity;
mod rate;
mod recorded_experiment;
+mod remote_settings_config;
mod string;
mod string_list;
mod text;
@@ -72,7 +72,7 @@ pub use self::uuid::UuidMetric;
pub use crate::histogram::HistogramType;
pub use recorded_experiment::RecordedExperiment;
-pub use self::metrics_enabled_config::MetricsEnabledConfig;
+pub use self::remote_settings_config::RemoteSettingsConfig;
/// A snapshot of all buckets and the accumulated sum of a distribution.
//
@@ -180,7 +180,7 @@ pub trait MetricType {
// Technically nothing prevents multiple calls to should_record() to run in parallel,
// meaning both are reading self.meta().disabled and later writing it. In between it can
- // also read remote_settings_metrics_config, which also could be modified in between those 2 reads.
+ // also read remote_settings_config, which also could be modified in between those 2 reads.
// This means we could write the wrong remote_settings_epoch | current_disabled value. All in all
// at worst we would see that metric enabled/disabled wrongly once.
// But since everything is tunneled through the dispatcher, this should never ever happen.
@@ -200,11 +200,7 @@ pub trait MetricType {
}
// The epoch's didn't match so we need to look up the disabled flag
// by the base_identifier from the in-memory HashMap
- let metrics_enabled = &glean
- .remote_settings_metrics_config
- .lock()
- .unwrap()
- .metrics_enabled;
+ let remote_settings_config = &glean.remote_settings_config.lock().unwrap();
// Get the value from the remote configuration if it is there, otherwise return the default value.
let current_disabled = {
let base_id = self.meta().base_identifier();
@@ -215,8 +211,13 @@ pub trait MetricType {
// NOTE: The `!` preceding the `*is_enabled` is important for inverting the logic since the
// underlying property in the metrics.yaml is `disabled` and the outward API is treating it as
// if it were `enabled` to make it easier to understand.
- if let Some(is_enabled) = metrics_enabled.get(identifier) {
- u8::from(!*is_enabled)
+
+ if !remote_settings_config.metrics_enabled.is_empty() {
+ if let Some(is_enabled) = remote_settings_config.metrics_enabled.get(identifier) {
+ u8::from(!*is_enabled)
+ } else {
+ u8::from(self.meta().inner.disabled)
+ }
} else {
u8::from(self.meta().inner.disabled)
}
diff --git a/third_party/rust/glean-core/src/metrics/object.rs b/third_party/rust/glean-core/src/metrics/object.rs
index 6071e2b33a..58c8a04c73 100644
--- a/third_party/rust/glean-core/src/metrics/object.rs
+++ b/third_party/rust/glean-core/src/metrics/object.rs
@@ -48,6 +48,10 @@ impl ObjectMetric {
/// * `value` - the value to set.
#[doc(hidden)]
pub fn set_sync(&self, glean: &Glean, value: JsonValue) {
+ if !self.should_record(glean) {
+ return;
+ }
+
let value = Metric::Object(serde_json::to_string(&value).unwrap());
glean.storage().record(glean, &self.meta, &value)
}
@@ -65,6 +69,31 @@ impl ObjectMetric {
crate::launch_with_glean(move |glean| metric.set_sync(glean, value))
}
+ /// Sets to the specified structure.
+ ///
+ /// Parses the passed JSON string.
+ /// If it can't be parsed into a valid object it records an invalid value error.
+ ///
+ /// Note: This does not check the structure. This needs to be done by the wrapper.
+ ///
+ /// # Arguments
+ ///
+ /// * `object` - JSON representation of the object to set.
+ pub fn set_string(&self, object: String) {
+ let metric = self.clone();
+ crate::launch_with_glean(move |glean| {
+ let object = match serde_json::from_str(&object) {
+ Ok(object) => object,
+ Err(_) => {
+ let msg = "Value did not match predefined schema";
+ record_error(glean, &metric.meta, ErrorType::InvalidValue, msg, None);
+ return;
+ }
+ };
+ metric.set_sync(glean, object)
+ })
+ }
+
/// Record an `InvalidValue` error for this metric.
///
/// Only to be used by the RLB.
diff --git a/third_party/rust/glean-core/src/metrics/ping.rs b/third_party/rust/glean-core/src/metrics/ping.rs
index 5defab7a71..1c5b93c165 100644
--- a/third_party/rust/glean-core/src/metrics/ping.rs
+++ b/third_party/rust/glean-core/src/metrics/ping.rs
@@ -29,13 +29,12 @@ struct InnerPing {
pub precise_timestamps: bool,
/// Whether to include the {client|ping}_info sections on assembly.
pub include_info_sections: bool,
+ /// Whether this ping is enabled.
+ pub enabled: bool,
+ /// Other pings that should be scheduled when this ping is sent.
+ pub schedules_pings: Vec<String>,
/// The "reason" codes that this ping can send
pub reason_codes: Vec<String>,
-
- /// Whether this ping is enabled.
- /// Note: Data for disabled pings is still recorded.
- /// It will not be cleared out on submit.
- enabled: bool,
}
impl fmt::Debug for PingType {
@@ -46,6 +45,8 @@ impl fmt::Debug for PingType {
.field("send_if_empty", &self.0.send_if_empty)
.field("precise_timestamps", &self.0.precise_timestamps)
.field("include_info_sections", &self.0.include_info_sections)
+ .field("enabled", &self.0.enabled)
+ .field("schedules_pings", &self.0.schedules_pings)
.field("reason_codes", &self.0.reason_codes)
.finish()
}
@@ -64,13 +65,20 @@ impl PingType {
/// * `name` - The name of the ping.
/// * `include_client_id` - Whether to include the client ID in the assembled ping when submitting.
/// * `send_if_empty` - Whether the ping should be sent empty or not.
+ /// * `precise_timestamps` - Whether the ping should use precise timestamps for the start and end time.
+ /// * `include_info_sections` - Whether the ping should include the client/ping_info sections.
+ /// * `enabled` - Whether or not this ping is enabled. Note: Data that would be sent on a disabled
+ /// ping will still be collected but is discarded rather than being submitted.
/// * `reason_codes` - The valid reason codes for this ping.
+ #[allow(clippy::too_many_arguments)]
pub fn new<A: Into<String>>(
name: A,
include_client_id: bool,
send_if_empty: bool,
precise_timestamps: bool,
include_info_sections: bool,
+ enabled: bool,
+ schedules_pings: Vec<String>,
reason_codes: Vec<String>,
) -> Self {
Self::new_internal(
@@ -79,19 +87,22 @@ impl PingType {
send_if_empty,
precise_timestamps,
include_info_sections,
+ enabled,
+ schedules_pings,
reason_codes,
- true,
)
}
+ #[allow(clippy::too_many_arguments)]
pub(crate) fn new_internal<A: Into<String>>(
name: A,
include_client_id: bool,
send_if_empty: bool,
precise_timestamps: bool,
include_info_sections: bool,
- reason_codes: Vec<String>,
enabled: bool,
+ schedules_pings: Vec<String>,
+ reason_codes: Vec<String>,
) -> Self {
let this = Self(Arc::new(InnerPing {
name: name.into(),
@@ -99,8 +110,9 @@ impl PingType {
send_if_empty,
precise_timestamps,
include_info_sections,
- reason_codes,
enabled,
+ schedules_pings,
+ reason_codes,
}));
// Register this ping.
@@ -130,6 +142,22 @@ impl PingType {
self.0.include_info_sections
}
+ pub(crate) fn enabled(&self, glean: &Glean) -> bool {
+ let remote_settings_config = &glean.remote_settings_config.lock().unwrap();
+
+ if !remote_settings_config.pings_enabled.is_empty() {
+ if let Some(remote_enabled) = remote_settings_config.pings_enabled.get(self.name()) {
+ return *remote_enabled;
+ }
+ }
+
+ self.0.enabled
+ }
+
+ pub(crate) fn schedules_pings(&self) -> &[String] {
+ &self.0.schedules_pings
+ }
+
/// Submits the ping for eventual uploading.
///
/// The ping content is assembled as soon as possible, but upload is not
@@ -166,11 +194,6 @@ impl PingType {
/// Whether the ping was succesfully assembled and queued.
#[doc(hidden)]
pub fn submit_sync(&self, glean: &Glean, reason: Option<&str>) -> bool {
- if !self.0.enabled {
- log::info!("Ping disabled: not submitting '{}' ping.", self.0.name);
- return false;
- }
-
if !glean.is_upload_enabled() {
log::info!("Glean disabled: not submitting any pings.");
return false;
@@ -208,6 +231,15 @@ impl PingType {
false
}
Some(ping) => {
+ if !self.enabled(glean) {
+ log::info!(
+ "The ping '{}' is disabled and will be discarded and not submitted",
+ ping.name
+ );
+
+ return false;
+ }
+
// This metric is recorded *after* the ping is collected (since
// that is the only way to know *if* it will be submitted). The
// implication of this is that the count for a metrics ping will
@@ -219,7 +251,10 @@ impl PingType {
.add_sync(glean, 1);
if let Err(e) = ping_maker.store_ping(glean.get_data_path(), &ping) {
- log::warn!("IO error while writing ping to file: {}. Enqueuing upload of what we have in memory.", e);
+ log::warn!(
+ "IO error while writing ping to file: {}. Enqueuing upload of what we have in memory.",
+ e
+ );
glean.additional_metrics.io_errors.add_sync(glean, 1);
// `serde_json::to_string` only fails if serialization of the content
// fails or it contains maps with non-string keys.
@@ -248,6 +283,17 @@ impl PingType {
ping.name
);
+ if !ping.schedules_pings.is_empty() {
+ log::info!(
+ "The ping '{}' is being used to schedule other pings: {:?}",
+ ping.name,
+ ping.schedules_pings
+ );
+ for scheduled_ping_name in &ping.schedules_pings {
+ glean.submit_ping_by_name(scheduled_ping_name, reason);
+ }
+ }
+
true
}
}
diff --git a/third_party/rust/glean-core/src/metrics/remote_settings_config.rs b/third_party/rust/glean-core/src/metrics/remote_settings_config.rs
new file mode 100644
index 0000000000..e7a560e81c
--- /dev/null
+++ b/third_party/rust/glean-core/src/metrics/remote_settings_config.rs
@@ -0,0 +1,52 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+use std::collections::HashMap;
+
+use serde::{Deserialize, Serialize};
+
+/// Represents a list of metrics and an associated boolean property
+/// indicating if the metric is enabledfrom the remote-settings
+/// configuration store. The expected format of this data is stringified JSON
+/// in the following format:
+/// ```json
+/// {
+/// "category.metric_name": true
+/// }
+/// ```
+#[derive(Serialize, Deserialize, Debug, Clone, Default)]
+pub struct RemoteSettingsConfig {
+ /// This is a `HashMap` consisting of base_identifiers as keys
+ /// and bool values representing an override for the `disabled`
+ /// property of the metric, only inverted to reduce confusion.
+ /// If a particular metric has a value of `true` here, it means
+ /// the default of the metric will be overriden and set to the
+ /// enabled state.
+ #[serde(default)]
+ pub metrics_enabled: HashMap<String, bool>,
+
+ /// This is a `HashMap` consisting of ping names as keys and
+ /// boolean values representing on override for the default
+ /// enabled state of the ping of the same name.
+ #[serde(default)]
+ pub pings_enabled: HashMap<String, bool>,
+}
+
+impl RemoteSettingsConfig {
+ /// Creates a new RemoteSettingsConfig
+ pub fn new() -> Self {
+ Default::default()
+ }
+}
+
+impl TryFrom<String> for RemoteSettingsConfig {
+ type Error = crate::ErrorKind;
+
+ fn try_from(json: String) -> Result<Self, Self::Error> {
+ match serde_json::from_str(json.as_str()) {
+ Ok(config) => Ok(config),
+ Err(e) => Err(crate::ErrorKind::Json(e)),
+ }
+ }
+}
diff --git a/third_party/rust/glean-core/src/ping/mod.rs b/third_party/rust/glean-core/src/ping/mod.rs
index d1a67ae360..8af4cd27f4 100644
--- a/third_party/rust/glean-core/src/ping/mod.rs
+++ b/third_party/rust/glean-core/src/ping/mod.rs
@@ -32,6 +32,8 @@ pub struct Ping<'a> {
pub headers: HeaderMap,
/// Whether the content contains {client|ping}_info sections.
pub includes_info_sections: bool,
+ /// Other pings that should be scheduled when this ping is sent.
+ pub schedules_pings: Vec<String>,
}
/// Collect a ping's data, assemble it into its full payload and store it on disk.
@@ -314,6 +316,7 @@ impl PingMaker {
url_path,
headers: self.get_headers(glean),
includes_info_sections: ping.include_info_sections(),
+ schedules_pings: ping.schedules_pings().to_vec(),
})
}
diff --git a/third_party/rust/glean-core/src/upload/directory.rs b/third_party/rust/glean-core/src/upload/directory.rs
index 91a4d061d1..b083fa8f1f 100644
--- a/third_party/rust/glean-core/src/upload/directory.rs
+++ b/third_party/rust/glean-core/src/upload/directory.rs
@@ -337,7 +337,7 @@ mod test {
let (mut glean, dir) = new_glean(None);
// Register a ping for testing
- let ping_type = PingType::new("test", true, true, true, true, vec![]);
+ let ping_type = PingType::new("test", true, true, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
// Submit the ping to populate the pending_pings directory
@@ -364,7 +364,7 @@ mod test {
let (mut glean, dir) = new_glean(None);
// Register a ping for testing
- let ping_type = PingType::new("test", true, true, true, true, vec![]);
+ let ping_type = PingType::new("test", true, true, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
// Submit the ping to populate the pending_pings directory
@@ -400,7 +400,7 @@ mod test {
let (mut glean, dir) = new_glean(None);
// Register a ping for testing
- let ping_type = PingType::new("test", true, true, true, true, vec![]);
+ let ping_type = PingType::new("test", true, true, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
// Submit the ping to populate the pending_pings directory
diff --git a/third_party/rust/glean-core/src/upload/mod.rs b/third_party/rust/glean-core/src/upload/mod.rs
index f217137f00..83b06cca65 100644
--- a/third_party/rust/glean-core/src/upload/mod.rs
+++ b/third_party/rust/glean-core/src/upload/mod.rs
@@ -1031,6 +1031,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1070,6 +1072,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1107,6 +1111,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1144,6 +1150,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1181,6 +1189,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1220,6 +1230,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1335,6 +1347,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1408,6 +1422,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1465,6 +1481,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1543,6 +1561,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1622,6 +1642,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
@@ -1703,6 +1725,8 @@ mod test {
/* send_if_empty */ true,
true,
true,
+ true,
+ vec![],
vec![],
);
glean.register_ping_type(&ping_type);
diff --git a/third_party/rust/glean-core/tests/event.rs b/third_party/rust/glean-core/tests/event.rs
index 48120956d7..20bf943113 100644
--- a/third_party/rust/glean-core/tests/event.rs
+++ b/third_party/rust/glean-core/tests/event.rs
@@ -167,6 +167,8 @@ fn test_sending_of_event_ping_when_it_fills_up() {
false,
true,
true,
+ true,
+ vec![],
vec!["max_capacity".to_string()],
));
}
@@ -452,6 +454,8 @@ fn event_storage_trimming() {
false,
true,
true,
+ true,
+ vec![],
vec![],
));
diff --git a/third_party/rust/glean-core/tests/ping.rs b/third_party/rust/glean-core/tests/ping.rs
index 17944b4c24..42f93e08c7 100644
--- a/third_party/rust/glean-core/tests/ping.rs
+++ b/third_party/rust/glean-core/tests/ping.rs
@@ -15,7 +15,7 @@ use glean_core::Lifetime;
fn write_ping_to_disk() {
let (mut glean, _temp) = new_glean(None);
- let ping = PingType::new("metrics", true, false, true, true, vec![]);
+ let ping = PingType::new("metrics", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping);
// We need to store a metric as an empty ping is not stored.
@@ -36,7 +36,7 @@ fn write_ping_to_disk() {
fn disabling_upload_clears_pending_pings() {
let (mut glean, _t) = new_glean(None);
- let ping = PingType::new("metrics", true, false, true, true, vec![]);
+ let ping = PingType::new("metrics", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping);
// We need to store a metric as an empty ping is not stored.
@@ -105,9 +105,18 @@ fn deletion_request_only_when_toggled_from_on_to_off() {
fn empty_pings_with_flag_are_sent() {
let (mut glean, _t) = new_glean(None);
- let ping1 = PingType::new("custom-ping1", true, true, true, true, vec![]);
+ let ping1 = PingType::new("custom-ping1", true, true, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping1);
- let ping2 = PingType::new("custom-ping2", true, false, true, true, vec![]);
+ let ping2 = PingType::new(
+ "custom-ping2",
+ true,
+ false,
+ true,
+ true,
+ true,
+ vec![],
+ vec![],
+ );
glean.register_ping_type(&ping2);
// No data is stored in either of the custom pings
@@ -139,10 +148,10 @@ fn test_pings_submitted_metric() {
None,
);
- let metrics_ping = PingType::new("metrics", true, false, true, true, vec![]);
+ let metrics_ping = PingType::new("metrics", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&metrics_ping);
- let baseline_ping = PingType::new("baseline", true, false, true, true, vec![]);
+ let baseline_ping = PingType::new("baseline", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&baseline_ping);
// We need to store a metric as an empty ping is not stored.
@@ -218,7 +227,7 @@ fn test_pings_submitted_metric() {
fn events_ping_with_metric_but_no_events_is_not_sent() {
let (mut glean, _t) = new_glean(None);
- let events_ping = PingType::new("events", true, true, true, true, vec![]);
+ let events_ping = PingType::new("events", true, true, true, true, true, vec![], vec![]);
glean.register_ping_type(&events_ping);
let counter = CounterMetric::new(CommonMetricData {
name: "counter".into(),
@@ -247,3 +256,26 @@ fn events_ping_with_metric_but_no_events_is_not_sent() {
assert!(events_ping.submit_sync(&glean, None));
assert_eq!(1, get_queued_pings(glean.get_data_path()).unwrap().len());
}
+
+#[test]
+fn test_scheduled_pings_are_sent() {
+ let (mut glean, _t) = new_glean(None);
+
+ let piggyback_ping = PingType::new("piggyback", true, true, true, true, true, vec![], vec![]);
+ glean.register_ping_type(&piggyback_ping);
+
+ let trigger_ping = PingType::new(
+ "trigger",
+ true,
+ true,
+ true,
+ true,
+ true,
+ vec!["piggyback".into()],
+ vec![],
+ );
+ glean.register_ping_type(&trigger_ping);
+
+ assert!(trigger_ping.submit_sync(&glean, None));
+ assert_eq!(2, get_queued_pings(glean.get_data_path()).unwrap().len());
+}
diff --git a/third_party/rust/glean-core/tests/ping_maker.rs b/third_party/rust/glean-core/tests/ping_maker.rs
index f716dc4692..ac2dcbee11 100644
--- a/third_party/rust/glean-core/tests/ping_maker.rs
+++ b/third_party/rust/glean-core/tests/ping_maker.rs
@@ -13,7 +13,7 @@ fn set_up_basic_ping() -> (Glean, PingMaker, PingType, tempfile::TempDir) {
let (tempdir, _) = tempdir();
let (mut glean, t) = new_glean(Some(tempdir));
let ping_maker = PingMaker::new();
- let ping_type = PingType::new("store1", true, false, true, true, vec![]);
+ let ping_type = PingType::new("store1", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
// Record something, so the ping will have data
@@ -95,7 +95,7 @@ fn test_metrics_must_report_experimentation_id() {
})
.unwrap();
let ping_maker = PingMaker::new();
- let ping_type = PingType::new("store1", true, false, true, true, vec![]);
+ let ping_type = PingType::new("store1", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
// Record something, so the ping will have data
@@ -149,7 +149,7 @@ fn experimentation_id_is_removed_if_send_if_empty_is_false() {
.unwrap();
let ping_maker = PingMaker::new();
- let unknown_ping_type = PingType::new("unknown", true, false, true, true, vec![]);
+ let unknown_ping_type = PingType::new("unknown", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&unknown_ping_type);
assert!(ping_maker
@@ -165,7 +165,7 @@ fn collect_must_report_none_when_no_data_is_stored() {
let (mut glean, ping_maker, ping_type, _t) = set_up_basic_ping();
- let unknown_ping_type = PingType::new("unknown", true, false, true, true, vec![]);
+ let unknown_ping_type = PingType::new("unknown", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
assert!(ping_maker
@@ -189,7 +189,8 @@ fn seq_number_must_be_sequential() {
for i in 0..=1 {
for ping_name in ["store1", "store2"].iter() {
- let ping_type = PingType::new(*ping_name, true, false, true, true, vec![]);
+ let ping_type =
+ PingType::new(*ping_name, true, false, true, true, true, vec![], vec![]);
let ping = ping_maker
.collect(&glean, &ping_type, None, "", "")
.unwrap();
@@ -202,7 +203,7 @@ fn seq_number_must_be_sequential() {
// Test that ping sequence numbers increase independently.
{
- let ping_type = PingType::new("store1", true, false, true, true, vec![]);
+ let ping_type = PingType::new("store1", true, false, true, true, true, vec![], vec![]);
// 3rd ping of store1
let ping = ping_maker
@@ -220,7 +221,7 @@ fn seq_number_must_be_sequential() {
}
{
- let ping_type = PingType::new("store2", true, false, true, true, vec![]);
+ let ping_type = PingType::new("store2", true, false, true, true, true, vec![], vec![]);
// 3rd ping of store2
let ping = ping_maker
@@ -231,7 +232,7 @@ fn seq_number_must_be_sequential() {
}
{
- let ping_type = PingType::new("store1", true, false, true, true, vec![]);
+ let ping_type = PingType::new("store1", true, false, true, true, true, vec![], vec![]);
// 5th ping of store1
let ping = ping_maker
@@ -246,7 +247,7 @@ fn seq_number_must_be_sequential() {
fn clear_pending_pings() {
let (mut glean, _t) = new_glean(None);
let ping_maker = PingMaker::new();
- let ping_type = PingType::new("store1", true, false, true, true, vec![]);
+ let ping_type = PingType::new("store1", true, false, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
// Record something, so the ping will have data
@@ -274,7 +275,7 @@ fn no_pings_submitted_if_upload_disabled() {
// Regression test, bug 1603571
let (mut glean, _t) = new_glean(None);
- let ping_type = PingType::new("store1", true, true, true, true, vec![]);
+ let ping_type = PingType::new("store1", true, true, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
assert!(ping_type.submit_sync(&glean, None));
@@ -292,7 +293,7 @@ fn no_pings_submitted_if_upload_disabled() {
fn metadata_is_correctly_added_when_necessary() {
let (mut glean, _t) = new_glean(None);
glean.set_debug_view_tag("valid-tag");
- let ping_type = PingType::new("store1", true, true, true, true, vec![]);
+ let ping_type = PingType::new("store1", true, true, true, true, true, vec![], vec![]);
glean.register_ping_type(&ping_type);
assert!(ping_type.submit_sync(&glean, None));
diff --git a/third_party/rust/glean/.cargo-checksum.json b/third_party/rust/glean/.cargo-checksum.json
index 7cb5c7390c..76c4772b8e 100644
--- a/third_party/rust/glean/.cargo-checksum.json
+++ b/third_party/rust/glean/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"af0535de86b60e3e08cadcdb9e61ce4a699c168608d7e9e2ebb92d949e7f31ef","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"27075b12236021c54d0c99427bcbd417933ca02545275604d3c13f32ca25af13","src/core_metrics.rs":"fef8fb4e5fa57c179836c6eb2cf59278fe3b8b036dbe57b0ff02971b4acd822f","src/lib.rs":"d4010f265de330081467673df05bbd45efbdfeef28823f7dc11a903b11fb8976","src/net/http_uploader.rs":"01ad5bd91384411a12c74434cd1c5cd585078cb34faba4615c70bdb669a9bccb","src/net/mod.rs":"f47b96bb878f1a6c771cedbaeaeefb270bc87fb1d1bbbed1b282dddca16216ed","src/private/event.rs":"d7c70c02648584c19c73af89e5180d3c6153c911f2c6830f7d1599b18d6150eb","src/private/mod.rs":"3565eb569d2b96f938f130abe0fc3ee3f55e7e03fd6501e309d3ef6af72ef6ee","src/private/object.rs":"3f70363a196aea46cc163af025a53e48c117c6208babc4bce772bb4c337cced8","src/private/ping.rs":"a6262a3453c77cbf30766c19b535a1bf66a37b2a316e8f87baee03025255c33e","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"6388b9e8bf96e0fb56ad71b7a5b5630d209ae62f1a65c62e878cbc1757ddd585","tests/common/mod.rs":"08fb9483d9b6ed9fe873b4395245166ae8a15263be750c7a8e298c41d9604745","tests/init_fails.rs":"906bbf0faa613976623e0cf782bd86545b49d76afaab182af7634690b747ebf7","tests/never_init.rs":"19bad996e22f7d6958cc1a650528530aa7d1aeb4a8ab42229a90bbc0315c8ed1","tests/no_time_to_init.rs":"06c81148c27d383cb708c0c80a2e806024c9955337d7adfba8c53aaeade9be67","tests/overflowing_preinit.rs":"7ad4b2274dd9240b53430859a4eb1d2597cf508a5a678333f3d3abbadd2ed4a7","tests/persist_ping_lifetime.rs":"81415dc1d74743f02269f0d0dfa524003147056853f080276972e64a0b761d3c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"9615eded31a2582c8f04c729d551c0c81a57029ba62a19184221c2e1cd39baf0","tests/simple.rs":"1b8b227249ae9d3cc281db07ed779bc75252c7849b1c48b4ac3d765228d65b20","tests/test-shutdown-blocking.sh":"9b16a01c190c7062474dd92182298a3d9a27928c8fa990340fdd798e6cdb7ab2","tests/test-thread-crashing.sh":"ff1bc8e5d7e4ba3a10d0d38bef222db8bfba469e7d30e45b1053d177a4084f09","tests/upload_timing.rs":"3024b7999a0c23f2c3d7e59725b5455522e4e9fdf63e3265b93fea4cec18725f"},"package":"0ceede8fb9c90ba1b77fb8290d3ae7b62bfcb422ad1d6e46bae1c8af3f22f12d"} \ No newline at end of file
+{"files":{"Cargo.toml":"f6e4a46a08d708810f6f0fc0461c4ebc246d5d656b2ed3a1bff4bdd774911c84","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"27075b12236021c54d0c99427bcbd417933ca02545275604d3c13f32ca25af13","src/core_metrics.rs":"fef8fb4e5fa57c179836c6eb2cf59278fe3b8b036dbe57b0ff02971b4acd822f","src/lib.rs":"21d670de3713a20a7a741f8ff6d6bde4329be44beeca037e32f22cce53a1bea2","src/net/http_uploader.rs":"01ad5bd91384411a12c74434cd1c5cd585078cb34faba4615c70bdb669a9bccb","src/net/mod.rs":"f47b96bb878f1a6c771cedbaeaeefb270bc87fb1d1bbbed1b282dddca16216ed","src/private/event.rs":"d7c70c02648584c19c73af89e5180d3c6153c911f2c6830f7d1599b18d6150eb","src/private/mod.rs":"3565eb569d2b96f938f130abe0fc3ee3f55e7e03fd6501e309d3ef6af72ef6ee","src/private/object.rs":"3f70363a196aea46cc163af025a53e48c117c6208babc4bce772bb4c337cced8","src/private/ping.rs":"31d33d7f661a7a17ccb69351328700b4d7b80024d1e128f406c3534f9d163475","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"39dd7468dcdaf17593b8b07970ced25c07cbd76853aaef2532fdcad0281a21d3","tests/common/mod.rs":"08fb9483d9b6ed9fe873b4395245166ae8a15263be750c7a8e298c41d9604745","tests/init_fails.rs":"46d7064bba9386c3065635434e17ac9212c6c2236b3cd12bd985fc3229e659a3","tests/never_init.rs":"7a6e8a011fbd945f2544f204367eeceff3f6039c99d98799477e3b2352ae6227","tests/no_time_to_init.rs":"4a5bdddc2f8226d2ad17038229e8767a6dd195977af49527fbb84a9f6b0154bb","tests/overflowing_preinit.rs":"7ad4b2274dd9240b53430859a4eb1d2597cf508a5a678333f3d3abbadd2ed4a7","tests/persist_ping_lifetime.rs":"81415dc1d74743f02269f0d0dfa524003147056853f080276972e64a0b761d3c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"dde65bce8a715ca3bd9c54b2466d831dd5e0d559e0773fe7657827f22a66bb44","tests/simple.rs":"1835b5df6f76ff894b45805bd54eaab23ca2d9d2b0694ec64af3aa6132baf30e","tests/test-shutdown-blocking.sh":"a44d8d4bbe2ee3ede9e48121150ae7a5386025160c5cef2181ca142232c5fb27","tests/test-thread-crashing.sh":"8d5ed070754e09fbe55183bb2792ae6e234a95770e39397caf05e4ec4d6015db","tests/upload_timing.rs":"6a97aa355d808123af0914ffecf1da0ecb2cc441c95c63c600b14f97ce0d45a0"},"package":"188984f86678ca6ef88beb79cb743128549946858523d516466d6e94d05fc911"} \ No newline at end of file
diff --git a/third_party/rust/glean/Cargo.toml b/third_party/rust/glean/Cargo.toml
index edcc84d5d6..db7aa95f21 100644
--- a/third_party/rust/glean/Cargo.toml
+++ b/third_party/rust/glean/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.66"
name = "glean"
-version = "59.0.0"
+version = "60.0.1"
authors = [
"Jan-Erik Rediger <jrediger@mozilla.com>",
"The Glean Team <glean-team@mozilla.com>",
@@ -35,7 +35,7 @@ license = "MPL-2.0"
repository = "https://github.com/mozilla/glean"
[dependencies.glean-core]
-version = "59.0.0"
+version = "=60.0.1"
[dependencies.inherent]
version = "1"
diff --git a/third_party/rust/glean/src/lib.rs b/third_party/rust/glean/src/lib.rs
index 81899d42ee..7f7f2c48be 100644
--- a/third_party/rust/glean/src/lib.rs
+++ b/third_party/rust/glean/src/lib.rs
@@ -23,7 +23,7 @@
//! let cfg = ConfigurationBuilder::new(true, "/tmp/data", "org.mozilla.glean_core.example").build();
//! glean::initialize(cfg, ClientInfoMetrics::unknown());
//!
-//! let prototype_ping = PingType::new("prototype", true, true, true, true, vec!());
+//! let prototype_ping = PingType::new("prototype", true, true, true, true, true, vec!(), vec!());
//!
//! prototype_ping.submit(None);
//! ```
@@ -187,9 +187,9 @@ pub fn test_get_experimentation_id() -> Option<String> {
/// Set the remote configuration values for the metrics' disabled property
///
-/// See [`glean_core::Glean::set_metrics_enabled_config`].
-pub fn glean_set_metrics_enabled_config(json: String) {
- glean_core::glean_set_metrics_enabled_config(json)
+/// See [`glean_core::Glean::glean_apply_server_knobs_config`].
+pub fn glean_apply_server_knobs_config(json: String) {
+ glean_core::glean_apply_server_knobs_config(json)
}
/// Performs the collection/cleanup operations required by becoming active.
@@ -293,7 +293,7 @@ pub fn get_timestamp_ms() -> u64 {
/// If Glean hasn't been initialized this will dispatch and return Ok(()),
/// otherwise it will block until the persist is done and return its Result.
pub fn persist_ping_lifetime_data() {
- glean_core::persist_ping_lifetime_data();
+ glean_core::glean_persist_ping_lifetime_data();
}
#[cfg(test)]
diff --git a/third_party/rust/glean/src/private/ping.rs b/third_party/rust/glean/src/private/ping.rs
index 6c126992bc..b54eec91a6 100644
--- a/third_party/rust/glean/src/private/ping.rs
+++ b/third_party/rust/glean/src/private/ping.rs
@@ -27,13 +27,22 @@ impl PingType {
/// * `name` - The name of the ping.
/// * `include_client_id` - Whether to include the client ID in the assembled ping when.
/// * `send_if_empty` - Whether the ping should be sent empty or not.
+ /// * `precise_timestamps` - Whether the ping should use precise timestamps for the start and end time.
+ /// * `include_info_sections` - Whether the ping should include the client/ping_info sections.
+ /// * `enabled` - Whether or not this ping is enabled. Note: Data that would be sent on a disabled
+ /// ping will still be collected and is discarded instead of being submitted.
+ /// * `schedules_pings` - A list of pings which are triggered for submission when this ping is
+ /// submitted.
/// * `reason_codes` - The valid reason codes for this ping.
+ #[allow(clippy::too_many_arguments)]
pub fn new<A: Into<String>>(
name: A,
include_client_id: bool,
send_if_empty: bool,
precise_timestamps: bool,
include_info_sections: bool,
+ enabled: bool,
+ schedules_pings: Vec<String>,
reason_codes: Vec<String>,
) -> Self {
let inner = glean_core::metrics::PingType::new(
@@ -42,6 +51,8 @@ impl PingType {
send_if_empty,
precise_timestamps,
include_info_sections,
+ enabled,
+ schedules_pings,
reason_codes,
);
diff --git a/third_party/rust/glean/src/test.rs b/third_party/rust/glean/src/test.rs
index 16d6d05447..c547cabccd 100644
--- a/third_party/rust/glean/src/test.rs
+++ b/third_party/rust/glean/src/test.rs
@@ -49,7 +49,8 @@ fn send_a_ping() {
// Define a new ping and submit it.
const PING_NAME: &str = "test-ping";
- let custom_ping = private::PingType::new(PING_NAME, true, true, true, true, vec![]);
+ let custom_ping =
+ private::PingType::new(PING_NAME, true, true, true, true, true, vec![], vec![]);
custom_ping.submit(None);
// Wait for the ping to arrive.
@@ -90,7 +91,8 @@ fn send_a_ping_without_info_sections() {
// Define a new ping and submit it.
const PING_NAME: &str = "noinfo-ping";
- let custom_ping = private::PingType::new(PING_NAME, true, true, true, false, vec![]);
+ let custom_ping =
+ private::PingType::new(PING_NAME, true, true, true, false, true, vec![], vec![]);
custom_ping.submit(None);
// Wait for the ping to arrive.
@@ -594,7 +596,7 @@ fn ping_collection_must_happen_after_concurrently_scheduled_metrics_recordings()
);
let ping_name = "custom_ping_1";
- let ping = private::PingType::new(ping_name, true, false, true, true, vec![]);
+ let ping = private::PingType::new(ping_name, true, false, true, true, true, vec![], vec![]);
let metric = private::StringMetric::new(CommonMetricData {
name: "string_metric".into(),
category: "telemetry".into(),
@@ -1097,7 +1099,16 @@ fn flipping_upload_enabled_respects_order_of_events() {
.build();
// We create a ping and a metric before we initialize Glean
- let sample_ping = PingType::new("sample-ping-1", true, false, true, true, vec![]);
+ let sample_ping = PingType::new(
+ "sample-ping-1",
+ true,
+ false,
+ true,
+ true,
+ true,
+ vec![],
+ vec![],
+ );
let metric = private::StringMetric::new(CommonMetricData {
name: "string_metric".into(),
category: "telemetry".into(),
@@ -1141,7 +1152,7 @@ fn registering_pings_before_init_must_work() {
}
// Create a custom ping and attempt its registration.
- let sample_ping = PingType::new("pre-register", true, true, true, true, vec![]);
+ let sample_ping = PingType::new("pre-register", true, true, true, true, true, vec![], vec![]);
// Create a custom configuration to use a fake uploader.
let dir = tempfile::tempdir().unwrap();
@@ -1193,7 +1204,7 @@ fn test_a_ping_before_submission() {
let _t = new_glean(Some(cfg), true);
// Create a custom ping and register it.
- let sample_ping = PingType::new("custom1", true, true, true, true, vec![]);
+ let sample_ping = PingType::new("custom1", true, true, true, true, true, vec![], vec![]);
let metric = CounterMetric::new(CommonMetricData {
name: "counter_metric".into(),
@@ -1310,7 +1321,8 @@ fn signaling_done() {
// Define a new ping and submit it.
const PING_NAME: &str = "test-ping";
- let custom_ping = private::PingType::new(PING_NAME, true, true, true, true, vec![]);
+ let custom_ping =
+ private::PingType::new(PING_NAME, true, true, true, true, true, vec![], vec![]);
custom_ping.submit(None);
custom_ping.submit(None);
@@ -1381,7 +1393,8 @@ fn configure_ping_throttling() {
// Define a new ping.
const PING_NAME: &str = "test-ping";
- let custom_ping = private::PingType::new(PING_NAME, true, true, true, true, vec![]);
+ let custom_ping =
+ private::PingType::new(PING_NAME, true, true, true, true, true, vec![], vec![]);
// Submit and receive it `pings_per_interval` times.
for _ in 0..pings_per_interval {
diff --git a/third_party/rust/glean/tests/init_fails.rs b/third_party/rust/glean/tests/init_fails.rs
index a0c23ca277..2ae4a91f02 100644
--- a/third_party/rust/glean/tests/init_fails.rs
+++ b/third_party/rust/glean/tests/init_fails.rs
@@ -42,8 +42,9 @@ mod pings {
use once_cell::sync::Lazy;
#[allow(non_upper_case_globals)]
- pub static validation: Lazy<PingType> =
- Lazy::new(|| glean::private::PingType::new("validation", true, true, true, true, vec![]));
+ pub static validation: Lazy<PingType> = Lazy::new(|| {
+ glean::private::PingType::new("validation", true, true, true, true, true, vec![], vec![])
+ });
}
/// Test scenario: Glean initialization fails.
diff --git a/third_party/rust/glean/tests/never_init.rs b/third_party/rust/glean/tests/never_init.rs
index 0d0d3768ff..a991ce467e 100644
--- a/third_party/rust/glean/tests/never_init.rs
+++ b/third_party/rust/glean/tests/never_init.rs
@@ -38,8 +38,9 @@ mod pings {
use once_cell::sync::Lazy;
#[allow(non_upper_case_globals)]
- pub static validation: Lazy<PingType> =
- Lazy::new(|| glean::private::PingType::new("validation", true, true, true, true, vec![]));
+ pub static validation: Lazy<PingType> = Lazy::new(|| {
+ glean::private::PingType::new("validation", true, true, true, true, true, vec![], vec![])
+ });
}
/// Test scenario: Glean is never initialized.
diff --git a/third_party/rust/glean/tests/no_time_to_init.rs b/third_party/rust/glean/tests/no_time_to_init.rs
index c312b397af..c14129c168 100644
--- a/third_party/rust/glean/tests/no_time_to_init.rs
+++ b/third_party/rust/glean/tests/no_time_to_init.rs
@@ -40,8 +40,9 @@ mod pings {
use once_cell::sync::Lazy;
#[allow(non_upper_case_globals)]
- pub static validation: Lazy<PingType> =
- Lazy::new(|| glean::private::PingType::new("validation", true, true, true, true, vec![]));
+ pub static validation: Lazy<PingType> = Lazy::new(|| {
+ glean::private::PingType::new("validation", true, true, true, true, true, vec![], vec![])
+ });
}
/// Test scenario: Glean initialization fails.
diff --git a/third_party/rust/glean/tests/schema.rs b/third_party/rust/glean/tests/schema.rs
index 59132cd82a..2909ab1dd3 100644
--- a/third_party/rust/glean/tests/schema.rs
+++ b/third_party/rust/glean/tests/schema.rs
@@ -170,7 +170,8 @@ fn validate_against_schema() {
text_metric.set("loooooong text".repeat(100));
// Define a new ping and submit it.
- let custom_ping = glean::private::PingType::new(PING_NAME, true, true, true, true, vec![]);
+ let custom_ping =
+ glean::private::PingType::new(PING_NAME, true, true, true, true, true, vec![], vec![]);
custom_ping.submit(None);
// Wait for the ping to arrive.
diff --git a/third_party/rust/glean/tests/simple.rs b/third_party/rust/glean/tests/simple.rs
index 3baa4df14e..d5c6a5244c 100644
--- a/third_party/rust/glean/tests/simple.rs
+++ b/third_party/rust/glean/tests/simple.rs
@@ -40,8 +40,9 @@ mod pings {
use once_cell::sync::Lazy;
#[allow(non_upper_case_globals)]
- pub static validation: Lazy<PingType> =
- Lazy::new(|| glean::private::PingType::new("validation", true, true, true, true, vec![]));
+ pub static validation: Lazy<PingType> = Lazy::new(|| {
+ glean::private::PingType::new("validation", true, true, true, true, true, vec![], vec![])
+ });
}
/// Test scenario: A clean run
diff --git a/third_party/rust/glean/tests/test-shutdown-blocking.sh b/third_party/rust/glean/tests/test-shutdown-blocking.sh
index 2f5d82acf0..8591aa005a 100755
--- a/third_party/rust/glean/tests/test-shutdown-blocking.sh
+++ b/third_party/rust/glean/tests/test-shutdown-blocking.sh
@@ -17,7 +17,7 @@ trap cleanup INT ABRT TERM EXIT
tmp="${TMPDIR:-/tmp}"
datapath=$(mktemp -d "${tmp}/glean_long_running.XXXX")
-cargo run --example long-running -- "$datapath"
+cargo run -p glean --example long-running -- "$datapath"
count=$(ls -1q "$datapath/pending_pings" | wc -l)
if [[ "$count" -eq 0 ]]; then
diff --git a/third_party/rust/glean/tests/test-thread-crashing.sh b/third_party/rust/glean/tests/test-thread-crashing.sh
index 1657467a33..67a0f4099c 100755
--- a/third_party/rust/glean/tests/test-thread-crashing.sh
+++ b/third_party/rust/glean/tests/test-thread-crashing.sh
@@ -19,7 +19,7 @@ datapath=$(mktemp -d "${tmp}/glean_long_running.XXXX")
RUSTFLAGS="-C panic=abort" \
RUST_LOG=debug \
-cargo run --example crashing-threads -- "$datapath"
+cargo run -p glean --example crashing-threads -- "$datapath"
ret=$?
count=$(ls -1q "$datapath/pending_pings" | wc -l)
diff --git a/third_party/rust/glean/tests/upload_timing.rs b/third_party/rust/glean/tests/upload_timing.rs
index ba0eee3402..49007cf8dc 100644
--- a/third_party/rust/glean/tests/upload_timing.rs
+++ b/third_party/rust/glean/tests/upload_timing.rs
@@ -96,8 +96,9 @@ mod pings {
use once_cell::sync::Lazy;
#[allow(non_upper_case_globals)]
- pub static validation: Lazy<PingType> =
- Lazy::new(|| glean::private::PingType::new("validation", true, true, true, true, vec![]));
+ pub static validation: Lazy<PingType> = Lazy::new(|| {
+ glean::private::PingType::new("validation", true, true, true, true, true, vec![], vec![])
+ });
}
// Define a fake uploader that sleeps.
diff --git a/third_party/rust/gpu-descriptor-types/.cargo-checksum.json b/third_party/rust/gpu-descriptor-types/.cargo-checksum.json
index ff289fd42a..9a414739ec 100644
--- a/third_party/rust/gpu-descriptor-types/.cargo-checksum.json
+++ b/third_party/rust/gpu-descriptor-types/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"5e3f9842253279ef626cd67111b942c5ef8d011efb39cc00b8f3469f8b4bede9","src/device.rs":"ecb6aaefd8af7ac51eed42a01ebbe7a98f44f62ea3b8d193e11a6889d4cd01bb","src/lib.rs":"bcf06593c390a3999f300333f63ae69542613157d316b3246faf69eded07d896","src/types.rs":"65f8e4006280713668f96279ce96c2d21fc75b5fb0fe4240dc650dfe71f92b27"},"package":"363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126"} \ No newline at end of file
+{"files":{"Cargo.toml":"54164c8c1352852cce6f2330030365868815deb9bd717b8d493071790cd72d7b","src/device.rs":"0f9957fee64c4db767a2abb2e88d34ebbf48ed6062121e081e0116e14190b4fa","src/lib.rs":"0ca3f2a281ba43466fb4d29c05b35c9059806d6114cd929b85afc0c41ea9d3ac","src/types.rs":"d38b838827edf226f6bc82e8f0718d90d6e2376d027c118a6d397260996a12bd"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/gpu-descriptor-types/Cargo.toml b/third_party/rust/gpu-descriptor-types/Cargo.toml
index 18871bb18b..f63ba9b7b6 100644
--- a/third_party/rust/gpu-descriptor-types/Cargo.toml
+++ b/third_party/rust/gpu-descriptor-types/Cargo.toml
@@ -3,24 +3,29 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "gpu-descriptor-types"
-version = "0.1.1"
+version = "0.2.0"
authors = ["Zakarum <zakarumych@ya.ru>"]
description = "Core types of gpu-descriptor crate"
homepage = "https://github.com/zakarumych/gpu-descriptor"
-documentation = "https://docs.rs/gpu-descriptor-types/0.1.0"
-keywords = ["gpu", "vulkan", "allocation", "no-std"]
+documentation = "https://docs.rs/gpu-descriptor-types"
+keywords = [
+ "gpu",
+ "vulkan",
+ "allocation",
+ "no-std",
+]
license = "MIT OR Apache-2.0"
repository = "https://github.com/zakarumych/gpu-descriptor"
+
[dependencies.bitflags]
-version = "1.2"
+version = "2.4"
default-features = false
diff --git a/third_party/rust/gpu-descriptor-types/src/device.rs b/third_party/rust/gpu-descriptor-types/src/device.rs
index b10511f863..a73a58a79c 100644
--- a/third_party/rust/gpu-descriptor-types/src/device.rs
+++ b/third_party/rust/gpu-descriptor-types/src/device.rs
@@ -1,53 +1,75 @@
-use crate::types::{DescriptorPoolCreateFlags, DescriptorTotalCount};
-
-/// Memory exhausted error.
-#[derive(Debug)]
-pub enum CreatePoolError {
- /// Device memory exhausted.
- OutOfDeviceMemory,
-
- /// Host memory exhausted.
- OutOfHostMemory,
-
- /// A descriptor pool creation has failed due to fragmentation.
- Fragmentation,
-}
-
-/// Memory exhausted error.
-#[derive(Debug)]
-pub enum DeviceAllocationError {
- /// Device memory exhausted.
- OutOfDeviceMemory,
-
- /// Host memory exhausted.
- OutOfHostMemory,
-
- /// Failed to allocate memory from pool.
- OutOfPoolMemory,
-
- /// Pool allocation failed due to fragmentation of pool's memory.
- FragmentedPool,
-}
-
-/// Abstract device that can create pools of type `P` and allocate sets `S` with layout `L`.
-pub trait DescriptorDevice<L, P, S> {
- unsafe fn create_descriptor_pool(
- &self,
- descriptor_count: &DescriptorTotalCount,
- max_sets: u32,
- flags: DescriptorPoolCreateFlags,
- ) -> Result<P, CreatePoolError>;
-
- unsafe fn destroy_descriptor_pool(&self, pool: P);
-
- unsafe fn alloc_descriptor_sets<'a>(
- &self,
- pool: &mut P,
- layouts: impl ExactSizeIterator<Item = &'a L>,
- sets: &mut impl Extend<S>,
- ) -> Result<(), DeviceAllocationError>
- where
- L: 'a;
-
- unsafe fn dealloc_descriptor_sets<'a>(&self, pool: &mut P, sets: impl Iterator<Item = S>);
-}
+use crate::types::{DescriptorPoolCreateFlags, DescriptorTotalCount};
+
+/// Memory exhausted error.
+#[derive(Debug)]
+pub enum CreatePoolError {
+ /// Device memory exhausted.
+ OutOfDeviceMemory,
+
+ /// Host memory exhausted.
+ OutOfHostMemory,
+
+ /// A descriptor pool creation has failed due to fragmentation.
+ Fragmentation,
+}
+
+/// Memory exhausted error.
+#[derive(Debug)]
+pub enum DeviceAllocationError {
+ /// Device memory exhausted.
+ OutOfDeviceMemory,
+
+ /// Host memory exhausted.
+ OutOfHostMemory,
+
+ /// Failed to allocate memory from pool.
+ OutOfPoolMemory,
+
+ /// Pool allocation failed due to fragmentation of pool's memory.
+ FragmentedPool,
+}
+
+/// Abstract device that can create pools of type `P` and allocate sets `S` with layout `L`.
+pub trait DescriptorDevice<L, P, S> {
+ /// Creates a new descriptor pool.
+ ///
+ /// # Safety
+ ///
+ /// Actually safe.
+ /// TODO: Remove `unsafe` with next breaking change.
+ unsafe fn create_descriptor_pool(
+ &self,
+ descriptor_count: &DescriptorTotalCount,
+ max_sets: u32,
+ flags: DescriptorPoolCreateFlags,
+ ) -> Result<P, CreatePoolError>;
+
+ /// Destroys descriptor pool.
+ ///
+ /// # Safety
+ ///
+ /// Pool must be created from this device.
+ /// All descriptor sets allocated from this pool become invalid.
+ unsafe fn destroy_descriptor_pool(&self, pool: P);
+
+ /// Allocates descriptor sets.
+ ///
+ /// # Safety
+ ///
+ /// Pool must be created from this device.
+ unsafe fn alloc_descriptor_sets<'a>(
+ &self,
+ pool: &mut P,
+ layouts: impl ExactSizeIterator<Item = &'a L>,
+ sets: &mut impl Extend<S>,
+ ) -> Result<(), DeviceAllocationError>
+ where
+ L: 'a;
+
+ /// Deallocates descriptor sets.
+ ///
+ /// # Safety
+ ///
+ /// Sets must be allocated from specified pool and not deallocated before.
+ unsafe fn dealloc_descriptor_sets(&self, pool: &mut P, sets: impl Iterator<Item = S>);
+}
diff --git a/third_party/rust/gpu-descriptor-types/src/lib.rs b/third_party/rust/gpu-descriptor-types/src/lib.rs
index 37c0d861c6..2af448c654 100644
--- a/third_party/rust/gpu-descriptor-types/src/lib.rs
+++ b/third_party/rust/gpu-descriptor-types/src/lib.rs
@@ -1,6 +1,6 @@
-#![no_std]
-
-mod device;
-mod types;
-
-pub use self::{device::*, types::*};
+#![no_std]
+
+mod device;
+mod types;
+
+pub use self::{device::*, types::*};
diff --git a/third_party/rust/gpu-descriptor-types/src/types.rs b/third_party/rust/gpu-descriptor-types/src/types.rs
index f65ffc74ae..73b28dcea5 100644
--- a/third_party/rust/gpu-descriptor-types/src/types.rs
+++ b/third_party/rust/gpu-descriptor-types/src/types.rs
@@ -1,33 +1,53 @@
-bitflags::bitflags! {
- /// Flags to augment descriptor pool creation.
- ///
- /// Match corresponding bits in Vulkan.
- pub struct DescriptorPoolCreateFlags: u32 {
- /// Allows freeing individial sets.
- const FREE_DESCRIPTOR_SET = 0x1;
-
- /// Allows allocating sets with layout created with matching backend-specific flag.
- const UPDATE_AFTER_BIND = 0x2;
- }
-}
-
-/// Number of descriptors of each type.
-///
-/// For `InlineUniformBlock` this value is number of bytes instead.
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
-pub struct DescriptorTotalCount {
- pub sampler: u32,
- pub combined_image_sampler: u32,
- pub sampled_image: u32,
- pub storage_image: u32,
- pub uniform_texel_buffer: u32,
- pub storage_texel_buffer: u32,
- pub uniform_buffer: u32,
- pub storage_buffer: u32,
- pub uniform_buffer_dynamic: u32,
- pub storage_buffer_dynamic: u32,
- pub input_attachment: u32,
- pub acceleration_structure: u32,
- pub inline_uniform_block_bytes: u32,
- pub inline_uniform_block_bindings: u32,
-}
+bitflags::bitflags! {
+ /// Flags to augment descriptor pool creation.
+ ///
+ /// Match corresponding bits in Vulkan.
+ #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+ pub struct DescriptorPoolCreateFlags: u32 {
+ /// Allows freeing individual sets.
+ const FREE_DESCRIPTOR_SET = 0x1;
+
+ /// Allows allocating sets with layout created with matching backend-specific flag.
+ const UPDATE_AFTER_BIND = 0x2;
+ }
+}
+
+/// Number of descriptors of each type.
+///
+/// For `InlineUniformBlock` this value is number of bytes instead.
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
+pub struct DescriptorTotalCount {
+ pub sampler: u32,
+ pub combined_image_sampler: u32,
+ pub sampled_image: u32,
+ pub storage_image: u32,
+ pub uniform_texel_buffer: u32,
+ pub storage_texel_buffer: u32,
+ pub uniform_buffer: u32,
+ pub storage_buffer: u32,
+ pub uniform_buffer_dynamic: u32,
+ pub storage_buffer_dynamic: u32,
+ pub input_attachment: u32,
+ pub acceleration_structure: u32,
+ pub inline_uniform_block_bytes: u32,
+ pub inline_uniform_block_bindings: u32,
+}
+
+impl DescriptorTotalCount {
+ pub fn total(&self) -> u32 {
+ self.sampler
+ + self.combined_image_sampler
+ + self.sampled_image
+ + self.storage_image
+ + self.uniform_texel_buffer
+ + self.storage_texel_buffer
+ + self.uniform_buffer
+ + self.storage_buffer
+ + self.uniform_buffer_dynamic
+ + self.storage_buffer_dynamic
+ + self.input_attachment
+ + self.acceleration_structure
+ + self.inline_uniform_block_bytes
+ + self.inline_uniform_block_bindings
+ }
+}
diff --git a/third_party/rust/gpu-descriptor/.cargo-checksum.json b/third_party/rust/gpu-descriptor/.cargo-checksum.json
index b2cdaf5c8d..f4fb18bc58 100644
--- a/third_party/rust/gpu-descriptor/.cargo-checksum.json
+++ b/third_party/rust/gpu-descriptor/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"dfdf8bb8e5a78a8b8feff5d924bd3757fd1299fa015802314a89883036f20c80","src/allocator.rs":"d46bee4586b88a3a5988e59b3112da379a49688d7f12bd2716cebb9fa6076a7a","src/lib.rs":"6fb74a08ad9975e561f4fca7bd391f0cbd96a7cab79b17df7d979021099b50f9"},"package":"0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a"} \ No newline at end of file
+{"files":{"Cargo.toml":"0bd7a40cb614fe568b076fd5edd6d6e51791b6d1e0a174ae67a16d56618357e1","src/allocator.rs":"38d173f9b6ca608dee9a7898b6e2ad7e75d199284c99291da0112e4b6e908409","src/lib.rs":"6fb74a08ad9975e561f4fca7bd391f0cbd96a7cab79b17df7d979021099b50f9"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/gpu-descriptor/Cargo.toml b/third_party/rust/gpu-descriptor/Cargo.toml
index 1f8ff2851c..7524894008 100644
--- a/third_party/rust/gpu-descriptor/Cargo.toml
+++ b/third_party/rust/gpu-descriptor/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "gpu-descriptor"
-version = "0.2.3"
+version = "0.3.0"
authors = ["Zakarum <zakarumych@ya.ru>"]
description = "Implementation agnostic descriptor allocator for Vulkan like APIs"
homepage = "https://github.com/zakarumych/gpu-descriptor"
@@ -27,14 +27,20 @@ license = "MIT OR Apache-2.0"
repository = "https://github.com/zakarumych/gpu-descriptor"
[dependencies.bitflags]
-version = "1.2"
+version = "2.4"
default-features = false
[dependencies.gpu-descriptor-types]
-version = "0.1"
+version = "0.2"
+path = "../types"
[dependencies.hashbrown]
-version = "0.12"
+version = "0.14"
+features = [
+ "ahash",
+ "raw",
+]
+default-features = false
[dependencies.serde]
version = "1.0"
diff --git a/third_party/rust/gpu-descriptor/src/allocator.rs b/third_party/rust/gpu-descriptor/src/allocator.rs
index 077a8860ce..96fc073a48 100644
--- a/third_party/rust/gpu-descriptor/src/allocator.rs
+++ b/third_party/rust/gpu-descriptor/src/allocator.rs
@@ -13,6 +13,7 @@ use {
bitflags::bitflags! {
/// Flags to augment descriptor set allocation.
+ #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct DescriptorSetLayoutCreateFlags: u32 {
/// Specified that descriptor set must be allocated from\
/// pool with `DescriptorPoolCreateFlags::UPDATE_AFTER_BIND`.
@@ -107,7 +108,7 @@ struct DescriptorPool<P> {
struct DescriptorBucket<P> {
offset: u64,
pools: VecDeque<DescriptorPool<P>>,
- total: u64,
+ total: u32,
update_after_bind: bool,
size: DescriptorTotalCount,
}
@@ -158,7 +159,7 @@ impl<P> DescriptorBucket<P> {
fn new_pool_size(&self, minimal_set_count: u32) -> (DescriptorTotalCount, u32) {
let mut max_sets = MIN_SETS // at least MIN_SETS
.max(minimal_set_count) // at least enough for allocation
- .max(self.total.min(MAX_SETS as u64) as u32) // at least as much as was allocated so far capped to MAX_SETS
+ .max(self.total.min(MAX_SETS)) // at least as much as was allocated so far capped to MAX_SETS
.checked_next_power_of_two() // rounded up to nearest 2^N
.unwrap_or(i32::MAX as u32);
@@ -259,7 +260,7 @@ impl<P> DescriptorBucket<P> {
count -= allocate;
pool.available -= allocate;
pool.allocated += allocate;
- self.total += u64::from(allocate);
+ self.total += allocate;
if count == 0 {
return Ok(());
@@ -328,7 +329,7 @@ impl<P> DescriptorBucket<P> {
allocated: allocate,
available: max_sets - allocate,
});
- self.total += allocate as u64;
+ self.total += allocate;
}
Ok(())
@@ -356,7 +357,7 @@ impl<P> DescriptorBucket<P> {
pool.available += count;
pool.allocated -= count;
- self.total -= u64::from(count);
+ self.total -= count;
#[cfg(feature = "tracing")]
tracing::trace!("Freed {} from descriptor bucket", count);
@@ -395,10 +396,11 @@ impl<P> DescriptorBucket<P> {
#[derive(Debug)]
pub struct DescriptorAllocator<P, S> {
buckets: HashMap<(DescriptorTotalCount, bool), DescriptorBucket<P>>,
- total: u64,
sets_cache: Vec<DescriptorSet<S>>,
raw_sets_cache: Vec<S>,
max_update_after_bind_descriptors_in_all_pools: u32,
+ current_update_after_bind_descriptors_in_all_pools: u32,
+ total: u32,
}
impl<P, S> Drop for DescriptorAllocator<P, S> {
@@ -421,6 +423,7 @@ impl<P, S> DescriptorAllocator<P, S> {
sets_cache: Vec::new(),
raw_sets_cache: Vec::new(),
max_update_after_bind_descriptors_in_all_pools,
+ current_update_after_bind_descriptors_in_all_pools: 0,
}
}
@@ -449,8 +452,18 @@ impl<P, S> DescriptorAllocator<P, S> {
return Ok(Vec::new());
}
+ let descriptor_count = count * layout_descriptor_count.total();
+
let update_after_bind = flags.contains(DescriptorSetLayoutCreateFlags::UPDATE_AFTER_BIND);
+ if update_after_bind
+ && self.max_update_after_bind_descriptors_in_all_pools
+ - self.current_update_after_bind_descriptors_in_all_pools
+ < descriptor_count
+ {
+ return Err(AllocationError::Fragmentation);
+ }
+
#[cfg(feature = "tracing")]
tracing::trace!(
"Allocating {} sets with layout {:?} @ {:?}",
@@ -464,7 +477,14 @@ impl<P, S> DescriptorAllocator<P, S> {
.entry((*layout_descriptor_count, update_after_bind))
.or_insert_with(|| DescriptorBucket::new(update_after_bind, *layout_descriptor_count));
match bucket.allocate(device, layout, count, &mut self.sets_cache) {
- Ok(()) => Ok(core::mem::replace(&mut self.sets_cache, Vec::new())),
+ Ok(()) => {
+ self.total += descriptor_count;
+ if update_after_bind {
+ self.current_update_after_bind_descriptors_in_all_pools += descriptor_count;
+ }
+
+ Ok(core::mem::take(&mut self.sets_cache))
+ }
Err(err) => {
debug_assert!(self.raw_sets_cache.is_empty());
@@ -518,7 +538,7 @@ impl<P, S> DescriptorAllocator<P, S> {
.get_mut(&last_key)
.expect("Set must be allocated from this allocator");
- debug_assert!(u64::try_from(self.raw_sets_cache.len())
+ debug_assert!(u32::try_from(self.raw_sets_cache.len())
.ok()
.map_or(false, |count| count <= bucket.total));
@@ -536,7 +556,7 @@ impl<P, S> DescriptorAllocator<P, S> {
.get_mut(&last_key)
.expect("Set must be allocated from this allocator");
- debug_assert!(u64::try_from(self.raw_sets_cache.len())
+ debug_assert!(u32::try_from(self.raw_sets_cache.len())
.ok()
.map_or(false, |count| count <= bucket.total));
diff --git a/third_party/rust/hashbrown/.cargo-checksum.json b/third_party/rust/hashbrown/.cargo-checksum.json
index 5561cde80d..0c5744048e 100644
--- a/third_party/rust/hashbrown/.cargo-checksum.json
+++ b/third_party/rust/hashbrown/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"ade49a29d368e16ce508aee91b477ecbad7e2e52eb6fee7b4c1fc86199963f0e","Cargo.toml":"421b3a71d97faf0a7e52c3b2bfbe0f1c036b9dbf6232b4e5b41221bb54358f5a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"a536b3bb3f3521e59836080f05a4783150fa8484f759a31468ce3b6dba1f33eb","benches/bench.rs":"aadc39d815eadf094ed9357d946319df2d93194203bbccb7c33cea6951d654df","benches/insert_unique_unchecked.rs":"cb84275f22d5f95a5ac995ac6b2df74ffcf342765b401d27c95f2955c7b7cb9f","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"ba105bf0853ebc45157f22116ad0f55d3bdab75e721d8e7a677c7b912d0c0c6d","src/external_trait_impls/rayon/map.rs":"2809e2a0071db8101c38789deb955f3830c5c3455eb1794ff64a0cf2ceb53fc7","src/external_trait_impls/rayon/mod.rs":"156de9c1ad0123334ea3b7e5a17444faf1b8bf971aa88a1f23e2f2d1c3021141","src/external_trait_impls/rayon/raw.rs":"e62c5f3ca5fffea47357e64b6f8c34cec94af62d9bd28a2b87934da46c22b66e","src/external_trait_impls/rayon/set.rs":"c4c44d44e56c2f59e9e1355662e29d8744ac96645ca4414127a359fb46cb0fbf","src/external_trait_impls/serde.rs":"0bc1a1f218d1ae7a5262557a5e3737b9334caf7d50c136dbdc75ff75680c223b","src/lib.rs":"c82fbee9684bfff40ef55d5f0c9f855c11f71f9fd1720fb084ef8331bdbc41d8","src/macros.rs":"36fe532656879c80f7753d13354b889f5b45caef451a1bb3a27dbc32d74c9878","src/map.rs":"df39edae67c569378dea9a4d928685cb4d06569712c6ac36a54df76fb5d87fe3","src/raw/alloc.rs":"184a0345bc2c7544b65c28724063be26b1f2b28dbaaa028a0b01192ccac25557","src/raw/bitmask.rs":"820d90b19b7e3433a1048ace008c9526331cd53a576cb0cfc1ff9960b6fe52f8","src/raw/generic.rs":"f5013a50d6d82d5cc8bad8b8c26c24d00fa810197f9f123256c58ac92e0d98f9","src/raw/mod.rs":"fa38247c6b3bd70636be50400debb9966a3446d49ee13e4f4e2dfe4ceed1b201","src/raw/sse2.rs":"838cfdb1daa1e70951ed25f985283b8b7ab4b46fa130f92eda152047ce6086f6","src/rustc_entry.rs":"cdd70972cba5b79ca1cad79869cb5e184d6dc4798ef90822e966ef89679ba011","src/scopeguard.rs":"d13de1b12897add7fe1c3eba6f906c9cc09d86509b6cfe06b95d63803fe9265c","src/set.rs":"6877d4a42eeadd681e3b8881528e4b20f14cfedbc11e9318bfcf425ef96d1546","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"83d5289771542203f539a41cccb889fbe7ce70f5adf5b903ac9f051e3ba13cfa","tests/serde.rs":"6bac8054db722dd049901b37a6e006535bac30f425eb5cd91af19b5bc1dfe78e","tests/set.rs":"01cf39efb04646ef4c63a809ebb96dfa63cfec472bf8bdb6c121f6526d40c40e"},"package":"8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"1a844fe3b7466b41ca1d5914af197d5aeed7cb14f30ebe4be351367d7ca905d2","Cargo.toml":"c011f10385da722056537329f3fcf8c9b93af742e79e38885c0152a0105fc227","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"84c222ce49510535419d338b7532a72a2bf22b7466e44de78d92d25b6c7d636b","benches/bench.rs":"ef7bc025922f077d307c565640c005d056e3d6c1713448a95aae92d3c22c1005","benches/insert_unique_unchecked.rs":"cb84275f22d5f95a5ac995ac6b2df74ffcf342765b401d27c95f2955c7b7cb9f","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"0625e6a5e3b8ecc8901a12aeeea54393fd84617fb3a14d98a34d2d2bddb8d257","src/external_trait_impls/rayon/helpers.rs":"ba105bf0853ebc45157f22116ad0f55d3bdab75e721d8e7a677c7b912d0c0c6d","src/external_trait_impls/rayon/map.rs":"96fdf39b3f601f77152d7ce84541b8f51f32b9274b7da9c294862892e721a5d8","src/external_trait_impls/rayon/mod.rs":"126edc882501dddd25e442d9236508b5b386eb8c0a9f5d654f2dd081086c1616","src/external_trait_impls/rayon/raw.rs":"04012fb2e99648819b4bc0044107ed3cb94013e242b7865075c5bd9ebf1b6865","src/external_trait_impls/rayon/set.rs":"7539348ff7bc6e3cce6b3c019d62dc401eea0138c578fef729c2593e8ead1cfa","src/external_trait_impls/rayon/table.rs":"8778d29509c68b5b7cb66859db025d3939ce22e7cf370b20ff3dea4fe4b29fd0","src/external_trait_impls/rkyv/hash_map.rs":"7abe24318143b776016052b05840656afc858b1ba5252f3d418d61972477f53d","src/external_trait_impls/rkyv/hash_set.rs":"38d969125d17d606492ec4ec9fc06b7e7118eb903240dacf40de21b9b06fa5c8","src/external_trait_impls/rkyv/mod.rs":"54399ce5574fd1d84b7b0cb4238fa3e898575e89a6724299be009d2172bda02e","src/external_trait_impls/serde.rs":"6dbe104dee16b453b6b048b541c6e02c6d067d970dfafd243fc4360288b0168c","src/lib.rs":"74e250c18e55994a4a902eaa06aca034559d6de53501ed4bf9010fabc67e88a2","src/macros.rs":"98a26b908fc0fbe6a58d008a317e550013d615eb3cc17a5054a573c62c1d74cb","src/map.rs":"d484f2f81e5b4acf4b615f187241e34c3016aaaca53a5e71019cceb993c4ebd7","src/raw/alloc.rs":"902f8588d0fdee3e5c3dc02410f41d4b38ac88843727387f929f3186b3a2d322","src/raw/bitmask.rs":"3b3dce8d6a48856ada19085abf43908f124ab3419fcf434b9ca64d7bff243f67","src/raw/generic.rs":"efc5e603be3e9a17935aef1836a38ce01c78a0093b2af0671548eb5459b37921","src/raw/mod.rs":"16bbabf42dde9f3fb17c4f7e768aef47752d839bf624b81d24a48af3d418b3a2","src/raw/neon.rs":"9907d8ebc36fc3df562dde478ea9b72213fda65288a304718d8647f0029dc9ad","src/raw/sse2.rs":"39038e3344e49f4638e211bcdbf56565ac53e90dce56172cc3b526fea911c2af","src/rustc_entry.rs":"8142ed89b50155602ef8c1628382bd62d3ee903920fe49d403d4100a278c6ba4","src/scopeguard.rs":"1a246e08a63c06cd8ad934bd7da229421bf804f991ae93cd7e242da27ca6c601","src/set.rs":"a620ed68bd1610b76c4c1890615d71b2c04928bf5b345133a0588a065bce06fa","src/table.rs":"7b7174099d2e3cade0caeddd73e29b7395f3b9f4f1f21013f885b52cd93438cb","tests/equivalent_trait.rs":"84faa3fe9d67c375d03fec81f0f1412c47862477d42e84e7d235258236338d5b","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/raw.rs":"43ed2f98877533a0905611d9a30f26b183dd3e103e3856eeab80e7b8ac7894d3","tests/rayon.rs":"39cb24ab45fce8087bb54948715c8b6973ebfba1a325292b5b3cd9aab50b5fd2","tests/serde.rs":"6bac8054db722dd049901b37a6e006535bac30f425eb5cd91af19b5bc1dfe78e","tests/set.rs":"9f8011c29d1059aadb54b6dd4623521d5178b4278b4a56021ef2cee4bbb19fd9"},"package":"e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"} \ No newline at end of file
diff --git a/third_party/rust/hashbrown/CHANGELOG.md b/third_party/rust/hashbrown/CHANGELOG.md
index 3354b54bb3..8c4068089a 100644
--- a/third_party/rust/hashbrown/CHANGELOG.md
+++ b/third_party/rust/hashbrown/CHANGELOG.md
@@ -7,35 +7,157 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
+### Changed
+
+- Changed `hash_set::{Entry, VacantEntry}::insert` to return `OccupiedEntry`. (#495)
+
+## [v0.14.5] - 2024-04-28
+
+### Fixed
+
+- Fixed index calculation in panic guard of `clone_from_impl`. (#511)
+
+## ~~[v0.14.4] - 2024-03-19~~
+
+This release was _yanked_ due to a breaking change.
+
+## [v0.14.3] - 2023-11-26
+
+### Added
+
+- Specialized `fold` implementation of iterators. (#480)
+
+### Fixed
+
+- Avoid using unstable `ptr::invalid_mut` on nightly. (#481)
+
+## [v0.14.2] - 2023-10-19
+
+### Added
+
+- `HashTable` type which provides a low-level but safe API with explicit hashing. (#466)
+
+### Fixed
+
+- Disabled the use of NEON instructions on big-endian ARM. (#475)
+- Disabled the use of NEON instructions on Miri. (#476)
+
+## [v0.14.1] - 2023-09-28
+
+### Added
+
+- Allow serializing `HashMap`s that use a custom allocator. (#449)
+
+### Changed
+
+- Use the `Equivalent` trait from the `equivalent` crate. (#442)
+- Slightly improved performance of table resizing. (#451)
+- Relaxed MSRV to 1.63.0. (#457)
+- Removed `Clone` requirement from custom allocators. (#468)
+
+### Fixed
+
+- Fixed custom allocators being leaked in some situations. (#439, #465)
+
+## [v0.14.0] - 2023-06-01
+
+### Added
+
+- Support for `allocator-api2` crate
+ for interfacing with custom allocators on stable. (#417)
+- Optimized implementation for ARM using NEON instructions. (#430)
+- Support for rkyv serialization. (#432)
+- `Equivalent` trait to look up values without `Borrow`. (#345)
+- `Hash{Map,Set}::raw_table_mut` is added whic returns a mutable reference. (#404)
+- Fast path for `clear` on empty tables. (#428)
+
+### Changed
+
+- Optimized insertion to only perform a single lookup. (#277)
+- `DrainFilter` (`drain_filter`) has been renamed to `ExtractIf` and no longer drops remaining
+ elements when the iterator is dropped. #(374)
+- Bumped MSRV to 1.64.0. (#431)
+- `{Map,Set}::raw_table` now returns an immutable reference. (#404)
+- `VacantEntry` and `OccupiedEntry` now use the default hasher if none is
+ specified in generics. (#389)
+- `RawTable::data_start` now returns a `NonNull` to match `RawTable::data_end`. (#387)
+- `RawIter::{reflect_insert, reflect_remove}` are now unsafe. (#429)
+- `RawTable::find_potential` is renamed to `find_or_find_insert_slot` and returns an `InsertSlot`. (#429)
+- `RawTable::remove` now also returns an `InsertSlot`. (#429)
+- `InsertSlot` can be used to insert an element with `RawTable::insert_in_slot`. (#429)
+- `RawIterHash` no longer has a lifetime tied to that of the `RawTable`. (#427)
+- The trait bounds of `HashSet::raw_table` have been relaxed to not require `Eq + Hash`. (#423)
+- `EntryRef::and_replace_entry_with` and `OccupiedEntryRef::replace_entry_with`
+ were changed to give a `&K` instead of a `&Q` to the closure.
+
+### Removed
+
+- Support for `bumpalo` as an allocator with custom wrapper.
+ Use `allocator-api2` feature in `bumpalo` to use it as an allocator
+ for `hashbrown` collections. (#417)
+
+## [v0.13.2] - 2023-01-12
+
+### Fixed
+
+- Added `#[inline(always)]` to `find_inner`. (#375)
+- Fixed `RawTable::allocation_info` for empty tables. (#376)
+
+## [v0.13.1] - 2022-11-10
+
+### Added
+
+- Added `Equivalent` trait to customize key lookups. (#350)
+- Added support for 16-bit targets. (#368)
+- Added `RawTable::allocation_info` which provides information about the memory
+ usage of a table. (#371)
+
+### Changed
+
+- Bumped MSRV to 1.61.0.
+- Upgraded to `ahash` 0.8. (#357)
+- Make `with_hasher_in` const. (#355)
+- The following methods have been removed from the `RawTable` API in favor of
+ safer alternatives:
+ - `RawTable::erase_no_drop` => Use `RawTable::erase` or `RawTable::remove` instead.
+ - `Bucket::read` => Use `RawTable::remove` instead.
+ - `Bucket::drop` => Use `RawTable::erase` instead.
+ - `Bucket::write` => Use `Bucket::as_mut` instead.
+
+### Fixed
+
+- Ensure that `HashMap` allocations don't exceed `isize::MAX`. (#362)
+- Fixed issue with field retagging in scopeguard. (#359)
+
## [v0.12.3] - 2022-07-17
-## Fixed
+### Fixed
- Fixed double-drop in `RawTable::clone_from`. (#348)
## [v0.12.2] - 2022-07-09
-## Added
+### Added
- Added `Entry` API for `HashSet`. (#342)
- Added `Extend<&'a (K, V)> for HashMap<K, V, S, A>`. (#340)
- Added length-based short-circuiting for hash table iteration. (#338)
- Added a function to access the `RawTable` of a `HashMap`. (#335)
-## Changed
+### Changed
- Edited `do_alloc` to reduce LLVM IR generated. (#341)
## [v0.12.1] - 2022-05-02
-## Fixed
+### Fixed
- Fixed underflow in `RawIterRange::size_hint`. (#325)
- Fixed the implementation of `Debug` for `ValuesMut` and `IntoValues`. (#325)
## [v0.12.0] - 2022-01-17
-## Added
+### Added
- Added `From<[T; N]>` and `From<[(K, V); N]>` for `HashSet` and `HashMap` respectively. (#297)
- Added an `allocator()` getter to HashMap and HashSet. (#257)
@@ -44,7 +166,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Implement `From<array>` on `HashSet` and `HashMap`. (#298)
- Added `entry_ref` API to `HashMap`. (#201)
-## Changed
+### Changed
- Bumped minimum Rust version to 1.56.1 and edition to 2021.
- Use u64 for the GroupWord on WebAssembly. (#271)
@@ -56,7 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Rename `get_each_mut` to `get_many_mut` and align API with the stdlib. (#291)
- Don't hash the key when searching in an empty table. (#305)
-## Fixed
+### Fixed
- Guard against allocations exceeding isize::MAX. (#268)
- Made `RawTable::insert_no_grow` unsafe. (#254)
@@ -65,19 +187,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
## [v0.11.2] - 2021-03-25
-## Fixed
+### Fixed
- Added missing allocator type parameter to `HashMap`'s and `HashSet`'s `Clone` impls. (#252)
## [v0.11.1] - 2021-03-20
-## Fixed
+### Fixed
- Added missing `pub` modifier to `BumpWrapper`. (#251)
## [v0.11.0] - 2021-03-14
-## Added
+### Added
- Added safe `try_insert_no_grow` method to `RawTable`. (#229)
- Added support for `bumpalo` as an allocator without the `nightly` feature. (#231)
- Implemented `Default` for `RawTable`. (#237)
@@ -86,22 +208,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Added `From<HashMap<T, ()>>` for `HashSet<T>`. (#235)
- Added `try_insert` method to `HashMap`. (#247)
-## Changed
+### Changed
- The minimum Rust version has been bumped to 1.49.0. (#230)
- Significantly improved compilation times by reducing the amount of generated IR. (#205)
-## Removed
+### Removed
- We no longer re-export the unstable allocator items from the standard library, nor the stable shims approximating the same. (#227)
- Removed hasher specialization support from `aHash`, which was resulting in inconsistent hashes being generated for a key. (#248)
-## Fixed
+### Fixed
- Fixed union length comparison. (#228)
## ~~[v0.10.0] - 2021-01-16~~
This release was _yanked_ due to inconsistent hashes being generated with the `nightly` feature. (#248)
-## Changed
+### Changed
- Parametrized `RawTable`, `HashSet` and `HashMap` over an allocator. (#133)
- Improved branch prediction hints on stable. (#209)
- Optimized hashing of primitive types with AHash using specialization. (#207)
@@ -109,7 +231,7 @@ This release was _yanked_ due to inconsistent hashes being generated with the `n
## [v0.9.1] - 2020-09-28
-## Added
+### Added
- Added safe methods to `RawTable` (#202):
- `get`: `find` and `as_ref`
- `get_mut`: `find` and `as_mut`
@@ -117,7 +239,7 @@ This release was _yanked_ due to inconsistent hashes being generated with the `n
- `remove_entry`: `find` and `remove`
- `erase_entry`: `find` and `erase`
-## Changed
+### Changed
- Removed `from_key_hashed_nocheck`'s `Q: Hash`. (#200)
- Made `RawTable::drain` safe. (#201)
@@ -215,7 +337,7 @@ This release was _yanked_ due to inconsistent hashes being generated with the `n
## [v0.6.2] - 2019-10-23
### Added
-- Added an `inline-more` feature (enabled by default) which allows choosing a tradeoff between
+- Added an `inline-more` feature (enabled by default) which allows choosing a tradeoff between
runtime performance and compilation time. (#119)
## [v0.6.1] - 2019-10-04
@@ -363,7 +485,15 @@ This release was _yanked_ due to a breaking change for users of `no-default-feat
- Initial release
-[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.12.3...HEAD
+[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.14.5...HEAD
+[v0.14.5]: https://github.com/rust-lang/hashbrown/compare/v0.14.4...v0.14.5
+[v0.14.4]: https://github.com/rust-lang/hashbrown/compare/v0.14.3...v0.14.4
+[v0.14.3]: https://github.com/rust-lang/hashbrown/compare/v0.14.2...v0.14.3
+[v0.14.2]: https://github.com/rust-lang/hashbrown/compare/v0.14.1...v0.14.2
+[v0.14.1]: https://github.com/rust-lang/hashbrown/compare/v0.14.0...v0.14.1
+[v0.14.0]: https://github.com/rust-lang/hashbrown/compare/v0.13.2...v0.14.0
+[v0.13.2]: https://github.com/rust-lang/hashbrown/compare/v0.13.1...v0.13.2
+[v0.13.1]: https://github.com/rust-lang/hashbrown/compare/v0.12.3...v0.13.1
[v0.12.3]: https://github.com/rust-lang/hashbrown/compare/v0.12.2...v0.12.3
[v0.12.2]: https://github.com/rust-lang/hashbrown/compare/v0.12.1...v0.12.2
[v0.12.1]: https://github.com/rust-lang/hashbrown/compare/v0.12.0...v0.12.1
diff --git a/third_party/rust/hashbrown/Cargo.toml b/third_party/rust/hashbrown/Cargo.toml
index fb130d24d2..0a5434e494 100644
--- a/third_party/rust/hashbrown/Cargo.toml
+++ b/third_party/rust/hashbrown/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.56.0"
+rust-version = "1.63.0"
name = "hashbrown"
-version = "0.12.3"
+version = "0.14.5"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
exclude = [
".github",
@@ -33,7 +33,6 @@ categories = [
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/hashbrown"
-resolver = "2"
[package.metadata.docs.rs]
features = [
@@ -42,9 +41,10 @@ features = [
"serde",
"raw",
]
+rustdoc-args = ["--generate-link-to-definition"]
[dependencies.ahash]
-version = "0.7.0"
+version = "0.8.7"
optional = true
default-features = false
@@ -53,9 +53,11 @@ version = "1.0.0"
optional = true
package = "rustc-std-workspace-alloc"
-[dependencies.bumpalo]
-version = "3.5.0"
+[dependencies.allocator-api2]
+version = "0.2.9"
+features = ["alloc"]
optional = true
+default-features = false
[dependencies.compiler_builtins]
version = "0.1.2"
@@ -66,15 +68,30 @@ version = "1.0.0"
optional = true
package = "rustc-std-workspace-core"
+[dependencies.equivalent]
+version = "1.0"
+optional = true
+default-features = false
+
[dependencies.rayon]
version = "1.0"
optional = true
+[dependencies.rkyv]
+version = "0.7.42"
+features = ["alloc"]
+optional = true
+default-features = false
+
[dependencies.serde]
version = "1.0.25"
optional = true
default-features = false
+[dev-dependencies.bumpalo]
+version = "3.13.0"
+features = ["allocator-api2"]
+
[dev-dependencies.doc-comment]
version = "0.3.1"
@@ -91,17 +108,24 @@ features = ["small_rng"]
[dev-dependencies.rayon]
version = "1.0"
+[dev-dependencies.rkyv]
+version = "0.7.42"
+features = ["validation"]
+
[dev-dependencies.serde_test]
version = "1.0"
[features]
-ahash-compile-time-rng = ["ahash/compile-time-rng"]
default = [
"ahash",
"inline-more",
+ "allocator-api2",
]
inline-more = []
-nightly = []
+nightly = [
+ "allocator-api2?/nightly",
+ "bumpalo/allocator_api",
+]
raw = []
rustc-dep-of-std = [
"nightly",
diff --git a/third_party/rust/hashbrown/README.md b/third_party/rust/hashbrown/README.md
index 2eddcf3e29..5eaef8bd01 100644
--- a/third_party/rust/hashbrown/README.md
+++ b/third_party/rust/hashbrown/README.md
@@ -4,7 +4,7 @@ hashbrown
[![Build Status](https://github.com/rust-lang/hashbrown/actions/workflows/rust.yml/badge.svg)](https://github.com/rust-lang/hashbrown/actions)
[![Crates.io](https://img.shields.io/crates/v/hashbrown.svg)](https://crates.io/crates/hashbrown)
[![Documentation](https://docs.rs/hashbrown/badge.svg)](https://docs.rs/hashbrown)
-[![Rust](https://img.shields.io/badge/rust-1.56.1%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/hashbrown)
+[![Rust](https://img.shields.io/badge/rust-1.63.0%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/hashbrown)
This crate is a Rust port of Google's high-performance [SwissTable] hash
map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
@@ -40,44 +40,44 @@ Compared to the previous implementation of `std::collections::HashMap` (Rust 1.3
With the hashbrown default AHash hasher:
-| name | oldstdhash ns/iter | hashbrown ns/iter | diff ns/iter | diff % | speedup |
-|:------------------------|:-------------------:|------------------:|:------------:|---------:|---------|
-| insert_ahash_highbits | 18,865 | 8,020 | -10,845 | -57.49% | x 2.35 |
-| insert_ahash_random | 19,711 | 8,019 | -11,692 | -59.32% | x 2.46 |
-| insert_ahash_serial | 19,365 | 6,463 | -12,902 | -66.63% | x 3.00 |
-| insert_erase_ahash_highbits | 51,136 | 17,916 | -33,220 | -64.96% | x 2.85 |
-| insert_erase_ahash_random | 51,157 | 17,688 | -33,469 | -65.42% | x 2.89 |
-| insert_erase_ahash_serial | 45,479 | 14,895 | -30,584 | -67.25% | x 3.05 |
-| iter_ahash_highbits | 1,399 | 1,092 | -307 | -21.94% | x 1.28 |
-| iter_ahash_random | 1,586 | 1,059 | -527 | -33.23% | x 1.50 |
-| iter_ahash_serial | 3,168 | 1,079 | -2,089 | -65.94% | x 2.94 |
-| lookup_ahash_highbits | 32,351 | 4,792 | -27,559 | -85.19% | x 6.75 |
-| lookup_ahash_random | 17,419 | 4,817 | -12,602 | -72.35% | x 3.62 |
-| lookup_ahash_serial | 15,254 | 3,606 | -11,648 | -76.36% | x 4.23 |
-| lookup_fail_ahash_highbits | 21,187 | 4,369 | -16,818 | -79.38% | x 4.85 |
-| lookup_fail_ahash_random | 21,550 | 4,395 | -17,155 | -79.61% | x 4.90 |
-| lookup_fail_ahash_serial | 19,450 | 3,176 | -16,274 | -83.67% | x 6.12 |
+| name | oldstdhash ns/iter | hashbrown ns/iter | diff ns/iter | diff % | speedup |
+| :-------------------------- | :----------------: | ----------------: | :----------: | ------: | ------- |
+| insert_ahash_highbits | 18,865 | 8,020 | -10,845 | -57.49% | x 2.35 |
+| insert_ahash_random | 19,711 | 8,019 | -11,692 | -59.32% | x 2.46 |
+| insert_ahash_serial | 19,365 | 6,463 | -12,902 | -66.63% | x 3.00 |
+| insert_erase_ahash_highbits | 51,136 | 17,916 | -33,220 | -64.96% | x 2.85 |
+| insert_erase_ahash_random | 51,157 | 17,688 | -33,469 | -65.42% | x 2.89 |
+| insert_erase_ahash_serial | 45,479 | 14,895 | -30,584 | -67.25% | x 3.05 |
+| iter_ahash_highbits | 1,399 | 1,092 | -307 | -21.94% | x 1.28 |
+| iter_ahash_random | 1,586 | 1,059 | -527 | -33.23% | x 1.50 |
+| iter_ahash_serial | 3,168 | 1,079 | -2,089 | -65.94% | x 2.94 |
+| lookup_ahash_highbits | 32,351 | 4,792 | -27,559 | -85.19% | x 6.75 |
+| lookup_ahash_random | 17,419 | 4,817 | -12,602 | -72.35% | x 3.62 |
+| lookup_ahash_serial | 15,254 | 3,606 | -11,648 | -76.36% | x 4.23 |
+| lookup_fail_ahash_highbits | 21,187 | 4,369 | -16,818 | -79.38% | x 4.85 |
+| lookup_fail_ahash_random | 21,550 | 4,395 | -17,155 | -79.61% | x 4.90 |
+| lookup_fail_ahash_serial | 19,450 | 3,176 | -16,274 | -83.67% | x 6.12 |
With the libstd default SipHash hasher:
-|name | oldstdhash ns/iter | hashbrown ns/iter | diff ns/iter | diff % | speedup |
-|:------------------------|:-------------------:|------------------:|:------------:|---------:|---------|
-|insert_std_highbits |19,216 |16,885 | -2,331 | -12.13% | x 1.14 |
-|insert_std_random |19,179 |17,034 | -2,145 | -11.18% | x 1.13 |
-|insert_std_serial |19,462 |17,493 | -1,969 | -10.12% | x 1.11 |
-|insert_erase_std_highbits |50,825 |35,847 | -14,978 | -29.47% | x 1.42 |
-|insert_erase_std_random |51,448 |35,392 | -16,056 | -31.21% | x 1.45 |
-|insert_erase_std_serial |87,711 |38,091 | -49,620 | -56.57% | x 2.30 |
-|iter_std_highbits |1,378 |1,159 | -219 | -15.89% | x 1.19 |
-|iter_std_random |1,395 |1,132 | -263 | -18.85% | x 1.23 |
-|iter_std_serial |1,704 |1,105 | -599 | -35.15% | x 1.54 |
-|lookup_std_highbits |17,195 |13,642 | -3,553 | -20.66% | x 1.26 |
-|lookup_std_random |17,181 |13,773 | -3,408 | -19.84% | x 1.25 |
-|lookup_std_serial |15,483 |13,651 | -1,832 | -11.83% | x 1.13 |
-|lookup_fail_std_highbits |20,926 |13,474 | -7,452 | -35.61% | x 1.55 |
-|lookup_fail_std_random |21,766 |13,505 | -8,261 | -37.95% | x 1.61 |
-|lookup_fail_std_serial |19,336 |13,519 | -5,817 | -30.08% | x 1.43 |
+| name | oldstdhash ns/iter | hashbrown ns/iter | diff ns/iter | diff % | speedup |
+| :------------------------ | :----------------: | ----------------: | :----------: | ------: | ------- |
+| insert_std_highbits | 19,216 | 16,885 | -2,331 | -12.13% | x 1.14 |
+| insert_std_random | 19,179 | 17,034 | -2,145 | -11.18% | x 1.13 |
+| insert_std_serial | 19,462 | 17,493 | -1,969 | -10.12% | x 1.11 |
+| insert_erase_std_highbits | 50,825 | 35,847 | -14,978 | -29.47% | x 1.42 |
+| insert_erase_std_random | 51,448 | 35,392 | -16,056 | -31.21% | x 1.45 |
+| insert_erase_std_serial | 87,711 | 38,091 | -49,620 | -56.57% | x 2.30 |
+| iter_std_highbits | 1,378 | 1,159 | -219 | -15.89% | x 1.19 |
+| iter_std_random | 1,395 | 1,132 | -263 | -18.85% | x 1.23 |
+| iter_std_serial | 1,704 | 1,105 | -599 | -35.15% | x 1.54 |
+| lookup_std_highbits | 17,195 | 13,642 | -3,553 | -20.66% | x 1.26 |
+| lookup_std_random | 17,181 | 13,773 | -3,408 | -19.84% | x 1.25 |
+| lookup_std_serial | 15,483 | 13,651 | -1,832 | -11.83% | x 1.13 |
+| lookup_fail_std_highbits | 20,926 | 13,474 | -7,452 | -35.61% | x 1.55 |
+| lookup_fail_std_random | 21,766 | 13,505 | -8,261 | -37.95% | x 1.61 |
+| lookup_fail_std_serial | 19,336 | 13,519 | -5,817 | -30.08% | x 1.43 |
## Usage
@@ -85,7 +85,7 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
-hashbrown = "0.12"
+hashbrown = "0.14"
```
Then:
@@ -101,14 +101,13 @@ This crate has the following Cargo features:
- `nightly`: Enables nightly-only features including: `#[may_dangle]`.
- `serde`: Enables serde serialization support.
+- `rkyv`: Enables rkyv serialization support.
- `rayon`: Enables rayon parallel iterator support.
- `raw`: Enables access to the experimental and unsafe `RawTable` API.
- `inline-more`: Adds inline hints to most functions, improving run-time performance at the cost
of compilation time. (enabled by default)
-- `bumpalo`: Provides a `BumpWrapper` type which allows `bumpalo` to be used for memory allocation.
- `ahash`: Compiles with ahash as default hasher. (enabled by default)
-- `ahash-compile-time-rng`: Activates the `compile-time-rng` feature of ahash. For targets with no random number generator
-this pre-generates seeds at compile time and embeds them as constants. See [aHash's documentation](https://github.com/tkaitchuck/aHash#flags) (disabled by default)
+- `allocator-api2`: Enables support for allocators that support `allocator-api2`. (enabled by default)
## License
diff --git a/third_party/rust/hashbrown/benches/bench.rs b/third_party/rust/hashbrown/benches/bench.rs
index c393b9a706..346bd7ef89 100644
--- a/third_party/rust/hashbrown/benches/bench.rs
+++ b/third_party/rust/hashbrown/benches/bench.rs
@@ -311,7 +311,7 @@ fn rehash_in_place(b: &mut Bencher) {
// Each loop triggers one rehash
for _ in 0..10 {
- for i in 0..224 {
+ for i in 0..223 {
set.insert(i);
}
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/mod.rs b/third_party/rust/hashbrown/src/external_trait_impls/mod.rs
index ef497836cb..01d386b046 100644
--- a/third_party/rust/hashbrown/src/external_trait_impls/mod.rs
+++ b/third_party/rust/hashbrown/src/external_trait_impls/mod.rs
@@ -1,4 +1,6 @@
#[cfg(feature = "rayon")]
pub(crate) mod rayon;
+#[cfg(feature = "rkyv")]
+mod rkyv;
#[cfg(feature = "serde")]
mod serde;
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rayon/map.rs b/third_party/rust/hashbrown/src/external_trait_impls/rayon/map.rs
index 14d91c220c..2534dc9b2b 100644
--- a/third_party/rust/hashbrown/src/external_trait_impls/rayon/map.rs
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rayon/map.rs
@@ -232,11 +232,11 @@ impl<K: Eq + Hash, V: fmt::Debug> fmt::Debug for ParValuesMut<'_, K, V> {
/// [`into_par_iter`]: /hashbrown/struct.HashMap.html#method.into_par_iter
/// [`HashMap`]: /hashbrown/struct.HashMap.html
/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
-pub struct IntoParIter<K, V, A: Allocator + Clone = Global> {
+pub struct IntoParIter<K, V, A: Allocator = Global> {
inner: RawIntoParIter<(K, V), A>,
}
-impl<K: Send, V: Send, A: Allocator + Clone + Send> ParallelIterator for IntoParIter<K, V, A> {
+impl<K: Send, V: Send, A: Allocator + Send> ParallelIterator for IntoParIter<K, V, A> {
type Item = (K, V);
#[cfg_attr(feature = "inline-more", inline)]
@@ -248,9 +248,7 @@ impl<K: Send, V: Send, A: Allocator + Clone + Send> ParallelIterator for IntoPar
}
}
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug
- for IntoParIter<K, V, A>
-{
+impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator> fmt::Debug for IntoParIter<K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ParIter {
inner: unsafe { self.inner.par_iter() },
@@ -267,11 +265,11 @@ impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug
///
/// [`par_drain`]: /hashbrown/struct.HashMap.html#method.par_drain
/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParDrain<'a, K, V, A: Allocator + Clone = Global> {
+pub struct ParDrain<'a, K, V, A: Allocator = Global> {
inner: RawParDrain<'a, (K, V), A>,
}
-impl<K: Send, V: Send, A: Allocator + Clone + Sync> ParallelIterator for ParDrain<'_, K, V, A> {
+impl<K: Send, V: Send, A: Allocator + Sync> ParallelIterator for ParDrain<'_, K, V, A> {
type Item = (K, V);
#[cfg_attr(feature = "inline-more", inline)]
@@ -283,9 +281,7 @@ impl<K: Send, V: Send, A: Allocator + Clone + Sync> ParallelIterator for ParDrai
}
}
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug
- for ParDrain<'_, K, V, A>
-{
+impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator> fmt::Debug for ParDrain<'_, K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ParIter {
inner: unsafe { self.inner.par_iter() },
@@ -295,7 +291,7 @@ impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug
}
}
-impl<K: Sync, V: Sync, S, A: Allocator + Clone> HashMap<K, V, S, A> {
+impl<K: Sync, V: Sync, S, A: Allocator> HashMap<K, V, S, A> {
/// Visits (potentially in parallel) immutably borrowed keys in an arbitrary order.
#[cfg_attr(feature = "inline-more", inline)]
pub fn par_keys(&self) -> ParKeys<'_, K, V> {
@@ -315,7 +311,7 @@ impl<K: Sync, V: Sync, S, A: Allocator + Clone> HashMap<K, V, S, A> {
}
}
-impl<K: Send, V: Send, S, A: Allocator + Clone> HashMap<K, V, S, A> {
+impl<K: Send, V: Send, S, A: Allocator> HashMap<K, V, S, A> {
/// Visits (potentially in parallel) mutably borrowed values in an arbitrary order.
#[cfg_attr(feature = "inline-more", inline)]
pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V> {
@@ -340,7 +336,7 @@ where
K: Eq + Hash + Sync,
V: PartialEq + Sync,
S: BuildHasher + Sync,
- A: Allocator + Clone + Sync,
+ A: Allocator + Sync,
{
/// Returns `true` if the map is equal to another,
/// i.e. both maps contain the same keys mapped to the same values.
@@ -354,9 +350,7 @@ where
}
}
-impl<K: Send, V: Send, S, A: Allocator + Clone + Send> IntoParallelIterator
- for HashMap<K, V, S, A>
-{
+impl<K: Send, V: Send, S, A: Allocator + Send> IntoParallelIterator for HashMap<K, V, S, A> {
type Item = (K, V);
type Iter = IntoParIter<K, V, A>;
@@ -368,9 +362,7 @@ impl<K: Send, V: Send, S, A: Allocator + Clone + Send> IntoParallelIterator
}
}
-impl<'a, K: Sync, V: Sync, S, A: Allocator + Clone> IntoParallelIterator
- for &'a HashMap<K, V, S, A>
-{
+impl<'a, K: Sync, V: Sync, S, A: Allocator> IntoParallelIterator for &'a HashMap<K, V, S, A> {
type Item = (&'a K, &'a V);
type Iter = ParIter<'a, K, V>;
@@ -383,9 +375,7 @@ impl<'a, K: Sync, V: Sync, S, A: Allocator + Clone> IntoParallelIterator
}
}
-impl<'a, K: Sync, V: Send, S, A: Allocator + Clone> IntoParallelIterator
- for &'a mut HashMap<K, V, S, A>
-{
+impl<'a, K: Sync, V: Send, S, A: Allocator> IntoParallelIterator for &'a mut HashMap<K, V, S, A> {
type Item = (&'a K, &'a mut V);
type Iter = ParIterMut<'a, K, V>;
@@ -424,7 +414,7 @@ where
K: Eq + Hash + Send,
V: Send,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn par_extend<I>(&mut self, par_iter: I)
where
@@ -440,7 +430,7 @@ where
K: Copy + Eq + Hash + Sync,
V: Copy + Sync,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn par_extend<I>(&mut self, par_iter: I)
where
@@ -456,7 +446,7 @@ where
K: Eq + Hash,
S: BuildHasher,
I: IntoParallelIterator,
- A: Allocator + Clone,
+ A: Allocator,
HashMap<K, V, S, A>: Extend<I::Item>,
{
let (list, len) = super::helpers::collect(par_iter);
@@ -561,10 +551,7 @@ mod test_par_map {
assert_eq!(value.load(Ordering::Relaxed), 100);
// retain only half
- let _v: Vec<_> = hm
- .into_par_iter()
- .filter(|&(ref key, _)| key.k < 50)
- .collect();
+ let _v: Vec<_> = hm.into_par_iter().filter(|(key, _)| key.k < 50).collect();
assert_eq!(key.load(Ordering::Relaxed), 50);
assert_eq!(value.load(Ordering::Relaxed), 50);
@@ -611,7 +598,7 @@ mod test_par_map {
assert_eq!(value.load(Ordering::Relaxed), 100);
// retain only half
- let _v: Vec<_> = hm.drain().filter(|&(ref key, _)| key.k < 50).collect();
+ let _v: Vec<_> = hm.drain().filter(|(key, _)| key.k < 50).collect();
assert!(hm.is_empty());
assert_eq!(key.load(Ordering::Relaxed), 50);
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rayon/mod.rs b/third_party/rust/hashbrown/src/external_trait_impls/rayon/mod.rs
index 99337a1ce3..61ca69b61d 100644
--- a/third_party/rust/hashbrown/src/external_trait_impls/rayon/mod.rs
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rayon/mod.rs
@@ -2,3 +2,4 @@ mod helpers;
pub(crate) mod map;
pub(crate) mod raw;
pub(crate) mod set;
+pub(crate) mod table;
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rayon/raw.rs b/third_party/rust/hashbrown/src/external_trait_impls/rayon/raw.rs
index 883303e278..612be47a55 100644
--- a/third_party/rust/hashbrown/src/external_trait_impls/rayon/raw.rs
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rayon/raw.rs
@@ -1,7 +1,6 @@
use crate::raw::Bucket;
use crate::raw::{Allocator, Global, RawIter, RawIterRange, RawTable};
use crate::scopeguard::guard;
-use alloc::alloc::dealloc;
use core::marker::PhantomData;
use core::mem;
use core::ptr::NonNull;
@@ -76,18 +75,18 @@ impl<T> UnindexedProducer for ParIterProducer<T> {
}
/// Parallel iterator which consumes a table and returns elements.
-pub struct RawIntoParIter<T, A: Allocator + Clone = Global> {
+pub struct RawIntoParIter<T, A: Allocator = Global> {
table: RawTable<T, A>,
}
-impl<T, A: Allocator + Clone> RawIntoParIter<T, A> {
+impl<T, A: Allocator> RawIntoParIter<T, A> {
#[cfg_attr(feature = "inline-more", inline)]
pub(super) unsafe fn par_iter(&self) -> RawParIter<T> {
self.table.par_iter()
}
}
-impl<T: Send, A: Allocator + Clone + Send> ParallelIterator for RawIntoParIter<T, A> {
+impl<T: Send, A: Allocator + Send> ParallelIterator for RawIntoParIter<T, A> {
type Item = T;
#[cfg_attr(feature = "inline-more", inline)]
@@ -97,9 +96,9 @@ impl<T: Send, A: Allocator + Clone + Send> ParallelIterator for RawIntoParIter<T
{
let iter = unsafe { self.table.iter().iter };
let _guard = guard(self.table.into_allocation(), |alloc| {
- if let Some((ptr, layout)) = *alloc {
+ if let Some((ptr, layout, ref alloc)) = *alloc {
unsafe {
- dealloc(ptr.as_ptr(), layout);
+ alloc.deallocate(ptr, layout);
}
}
});
@@ -109,23 +108,23 @@ impl<T: Send, A: Allocator + Clone + Send> ParallelIterator for RawIntoParIter<T
}
/// Parallel iterator which consumes elements without freeing the table storage.
-pub struct RawParDrain<'a, T, A: Allocator + Clone = Global> {
+pub struct RawParDrain<'a, T, A: Allocator = Global> {
// We don't use a &'a mut RawTable<T> because we want RawParDrain to be
// covariant over T.
table: NonNull<RawTable<T, A>>,
marker: PhantomData<&'a RawTable<T, A>>,
}
-unsafe impl<T: Send, A: Allocator + Clone> Send for RawParDrain<'_, T, A> {}
+unsafe impl<T: Send, A: Allocator> Send for RawParDrain<'_, T, A> {}
-impl<T, A: Allocator + Clone> RawParDrain<'_, T, A> {
+impl<T, A: Allocator> RawParDrain<'_, T, A> {
#[cfg_attr(feature = "inline-more", inline)]
pub(super) unsafe fn par_iter(&self) -> RawParIter<T> {
self.table.as_ref().par_iter()
}
}
-impl<T: Send, A: Allocator + Clone> ParallelIterator for RawParDrain<'_, T, A> {
+impl<T: Send, A: Allocator> ParallelIterator for RawParDrain<'_, T, A> {
type Item = T;
#[cfg_attr(feature = "inline-more", inline)]
@@ -143,7 +142,7 @@ impl<T: Send, A: Allocator + Clone> ParallelIterator for RawParDrain<'_, T, A> {
}
}
-impl<T, A: Allocator + Clone> Drop for RawParDrain<'_, T, A> {
+impl<T, A: Allocator> Drop for RawParDrain<'_, T, A> {
fn drop(&mut self) {
// If drive_unindexed is not called then simply clear the table.
unsafe {
@@ -204,7 +203,7 @@ impl<T> Drop for ParDrainProducer<T> {
}
}
-impl<T, A: Allocator + Clone> RawTable<T, A> {
+impl<T, A: Allocator> RawTable<T, A> {
/// Returns a parallel iterator over the elements in a `RawTable`.
#[cfg_attr(feature = "inline-more", inline)]
pub unsafe fn par_iter(&self) -> RawParIter<T> {
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rayon/set.rs b/third_party/rust/hashbrown/src/external_trait_impls/rayon/set.rs
index ee4f6e6693..3de98fccb8 100644
--- a/third_party/rust/hashbrown/src/external_trait_impls/rayon/set.rs
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rayon/set.rs
@@ -16,11 +16,11 @@ use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, Pa
/// [`into_par_iter`]: /hashbrown/struct.HashSet.html#method.into_par_iter
/// [`HashSet`]: /hashbrown/struct.HashSet.html
/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
-pub struct IntoParIter<T, A: Allocator + Clone = Global> {
+pub struct IntoParIter<T, A: Allocator = Global> {
inner: map::IntoParIter<T, (), A>,
}
-impl<T: Send, A: Allocator + Clone + Send> ParallelIterator for IntoParIter<T, A> {
+impl<T: Send, A: Allocator + Send> ParallelIterator for IntoParIter<T, A> {
type Item = T;
fn drive_unindexed<C>(self, consumer: C) -> C::Result
@@ -38,11 +38,11 @@ impl<T: Send, A: Allocator + Clone + Send> ParallelIterator for IntoParIter<T, A
///
/// [`par_drain`]: /hashbrown/struct.HashSet.html#method.par_drain
/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParDrain<'a, T, A: Allocator + Clone = Global> {
+pub struct ParDrain<'a, T, A: Allocator = Global> {
inner: map::ParDrain<'a, T, (), A>,
}
-impl<T: Send, A: Allocator + Clone + Send + Sync> ParallelIterator for ParDrain<'_, T, A> {
+impl<T: Send, A: Allocator + Send + Sync> ParallelIterator for ParDrain<'_, T, A> {
type Item = T;
fn drive_unindexed<C>(self, consumer: C) -> C::Result
@@ -85,7 +85,7 @@ impl<'a, T: Sync> ParallelIterator for ParIter<'a, T> {
///
/// [`par_difference`]: /hashbrown/struct.HashSet.html#method.par_difference
/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParDifference<'a, T, S, A: Allocator + Clone = Global> {
+pub struct ParDifference<'a, T, S, A: Allocator = Global> {
a: &'a HashSet<T, S, A>,
b: &'a HashSet<T, S, A>,
}
@@ -94,7 +94,7 @@ impl<'a, T, S, A> ParallelIterator for ParDifference<'a, T, S, A>
where
T: Eq + Hash + Sync,
S: BuildHasher + Sync,
- A: Allocator + Clone + Sync,
+ A: Allocator + Sync,
{
type Item = &'a T;
@@ -118,7 +118,7 @@ where
///
/// [`par_symmetric_difference`]: /hashbrown/struct.HashSet.html#method.par_symmetric_difference
/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParSymmetricDifference<'a, T, S, A: Allocator + Clone = Global> {
+pub struct ParSymmetricDifference<'a, T, S, A: Allocator = Global> {
a: &'a HashSet<T, S, A>,
b: &'a HashSet<T, S, A>,
}
@@ -127,7 +127,7 @@ impl<'a, T, S, A> ParallelIterator for ParSymmetricDifference<'a, T, S, A>
where
T: Eq + Hash + Sync,
S: BuildHasher + Sync,
- A: Allocator + Clone + Sync,
+ A: Allocator + Sync,
{
type Item = &'a T;
@@ -150,7 +150,7 @@ where
///
/// [`par_intersection`]: /hashbrown/struct.HashSet.html#method.par_intersection
/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParIntersection<'a, T, S, A: Allocator + Clone = Global> {
+pub struct ParIntersection<'a, T, S, A: Allocator = Global> {
a: &'a HashSet<T, S, A>,
b: &'a HashSet<T, S, A>,
}
@@ -159,7 +159,7 @@ impl<'a, T, S, A> ParallelIterator for ParIntersection<'a, T, S, A>
where
T: Eq + Hash + Sync,
S: BuildHasher + Sync,
- A: Allocator + Clone + Sync,
+ A: Allocator + Sync,
{
type Item = &'a T;
@@ -181,7 +181,7 @@ where
///
/// [`par_union`]: /hashbrown/struct.HashSet.html#method.par_union
/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParUnion<'a, T, S, A: Allocator + Clone = Global> {
+pub struct ParUnion<'a, T, S, A: Allocator = Global> {
a: &'a HashSet<T, S, A>,
b: &'a HashSet<T, S, A>,
}
@@ -190,7 +190,7 @@ impl<'a, T, S, A> ParallelIterator for ParUnion<'a, T, S, A>
where
T: Eq + Hash + Sync,
S: BuildHasher + Sync,
- A: Allocator + Clone + Sync,
+ A: Allocator + Sync,
{
type Item = &'a T;
@@ -216,7 +216,7 @@ impl<T, S, A> HashSet<T, S, A>
where
T: Eq + Hash + Sync,
S: BuildHasher + Sync,
- A: Allocator + Clone + Sync,
+ A: Allocator + Sync,
{
/// Visits (potentially in parallel) the values representing the union,
/// i.e. all the values in `self` or `other`, without duplicates.
@@ -289,7 +289,7 @@ where
impl<T, S, A> HashSet<T, S, A>
where
T: Eq + Hash + Send,
- A: Allocator + Clone + Send,
+ A: Allocator + Send,
{
/// Consumes (potentially in parallel) all values in an arbitrary order,
/// while preserving the set's allocated memory for reuse.
@@ -301,7 +301,7 @@ where
}
}
-impl<T: Send, S, A: Allocator + Clone + Send> IntoParallelIterator for HashSet<T, S, A> {
+impl<T: Send, S, A: Allocator + Send> IntoParallelIterator for HashSet<T, S, A> {
type Item = T;
type Iter = IntoParIter<T, A>;
@@ -313,7 +313,7 @@ impl<T: Send, S, A: Allocator + Clone + Send> IntoParallelIterator for HashSet<T
}
}
-impl<'a, T: Sync, S, A: Allocator + Clone> IntoParallelIterator for &'a HashSet<T, S, A> {
+impl<'a, T: Sync, S, A: Allocator> IntoParallelIterator for &'a HashSet<T, S, A> {
type Item = &'a T;
type Iter = ParIter<'a, T>;
@@ -374,7 +374,7 @@ fn extend<T, S, I, A>(set: &mut HashSet<T, S, A>, par_iter: I)
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
I: IntoParallelIterator,
HashSet<T, S, A>: Extend<I::Item>,
{
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rayon/table.rs b/third_party/rust/hashbrown/src/external_trait_impls/rayon/table.rs
new file mode 100644
index 0000000000..e8e50944ad
--- /dev/null
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rayon/table.rs
@@ -0,0 +1,252 @@
+//! Rayon extensions for `HashTable`.
+
+use super::raw::{RawIntoParIter, RawParDrain, RawParIter};
+use crate::hash_table::HashTable;
+use crate::raw::{Allocator, Global};
+use core::fmt;
+use core::marker::PhantomData;
+use rayon::iter::plumbing::UnindexedConsumer;
+use rayon::iter::{IntoParallelIterator, ParallelIterator};
+
+/// Parallel iterator over shared references to entries in a map.
+///
+/// This iterator is created by the [`par_iter`] method on [`HashTable`]
+/// (provided by the [`IntoParallelRefIterator`] trait).
+/// See its documentation for more.
+///
+/// [`par_iter`]: /hashbrown/struct.HashTable.html#method.par_iter
+/// [`HashTable`]: /hashbrown/struct.HashTable.html
+/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
+pub struct ParIter<'a, T> {
+ inner: RawParIter<T>,
+ marker: PhantomData<&'a T>,
+}
+
+impl<'a, T: Sync> ParallelIterator for ParIter<'a, T> {
+ type Item = &'a T;
+
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn drive_unindexed<C>(self, consumer: C) -> C::Result
+ where
+ C: UnindexedConsumer<Self::Item>,
+ {
+ self.inner
+ .map(|x| unsafe { x.as_ref() })
+ .drive_unindexed(consumer)
+ }
+}
+
+impl<T> Clone for ParIter<'_, T> {
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn clone(&self) -> Self {
+ Self {
+ inner: self.inner.clone(),
+ marker: PhantomData,
+ }
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for ParIter<'_, T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = unsafe { self.inner.iter() }.map(|x| unsafe { x.as_ref() });
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+/// Parallel iterator over mutable references to entries in a map.
+///
+/// This iterator is created by the [`par_iter_mut`] method on [`HashTable`]
+/// (provided by the [`IntoParallelRefMutIterator`] trait).
+/// See its documentation for more.
+///
+/// [`par_iter_mut`]: /hashbrown/struct.HashTable.html#method.par_iter_mut
+/// [`HashTable`]: /hashbrown/struct.HashTable.html
+/// [`IntoParallelRefMutIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefMutIterator.html
+pub struct ParIterMut<'a, T> {
+ inner: RawParIter<T>,
+ marker: PhantomData<&'a mut T>,
+}
+
+impl<'a, T: Send> ParallelIterator for ParIterMut<'a, T> {
+ type Item = &'a mut T;
+
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn drive_unindexed<C>(self, consumer: C) -> C::Result
+ where
+ C: UnindexedConsumer<Self::Item>,
+ {
+ self.inner
+ .map(|x| unsafe { x.as_mut() })
+ .drive_unindexed(consumer)
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for ParIterMut<'_, T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ ParIter {
+ inner: self.inner.clone(),
+ marker: PhantomData,
+ }
+ .fmt(f)
+ }
+}
+
+/// Parallel iterator over entries of a consumed map.
+///
+/// This iterator is created by the [`into_par_iter`] method on [`HashTable`]
+/// (provided by the [`IntoParallelIterator`] trait).
+/// See its documentation for more.
+///
+/// [`into_par_iter`]: /hashbrown/struct.HashTable.html#method.into_par_iter
+/// [`HashTable`]: /hashbrown/struct.HashTable.html
+/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
+pub struct IntoParIter<T, A: Allocator = Global> {
+ inner: RawIntoParIter<T, A>,
+}
+
+impl<T: Send, A: Allocator + Send> ParallelIterator for IntoParIter<T, A> {
+ type Item = T;
+
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn drive_unindexed<C>(self, consumer: C) -> C::Result
+ where
+ C: UnindexedConsumer<Self::Item>,
+ {
+ self.inner.drive_unindexed(consumer)
+ }
+}
+
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoParIter<T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ ParIter {
+ inner: unsafe { self.inner.par_iter() },
+ marker: PhantomData,
+ }
+ .fmt(f)
+ }
+}
+
+/// Parallel draining iterator over entries of a map.
+///
+/// This iterator is created by the [`par_drain`] method on [`HashTable`].
+/// See its documentation for more.
+///
+/// [`par_drain`]: /hashbrown/struct.HashTable.html#method.par_drain
+/// [`HashTable`]: /hashbrown/struct.HashTable.html
+pub struct ParDrain<'a, T, A: Allocator = Global> {
+ inner: RawParDrain<'a, T, A>,
+}
+
+impl<T: Send, A: Allocator + Sync> ParallelIterator for ParDrain<'_, T, A> {
+ type Item = T;
+
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn drive_unindexed<C>(self, consumer: C) -> C::Result
+ where
+ C: UnindexedConsumer<Self::Item>,
+ {
+ self.inner.drive_unindexed(consumer)
+ }
+}
+
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for ParDrain<'_, T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ ParIter {
+ inner: unsafe { self.inner.par_iter() },
+ marker: PhantomData,
+ }
+ .fmt(f)
+ }
+}
+
+impl<T: Send, A: Allocator> HashTable<T, A> {
+ /// Consumes (potentially in parallel) all values in an arbitrary order,
+ /// while preserving the map's allocated memory for reuse.
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub fn par_drain(&mut self) -> ParDrain<'_, T, A> {
+ ParDrain {
+ inner: self.raw.par_drain(),
+ }
+ }
+}
+
+impl<T: Send, A: Allocator + Send> IntoParallelIterator for HashTable<T, A> {
+ type Item = T;
+ type Iter = IntoParIter<T, A>;
+
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn into_par_iter(self) -> Self::Iter {
+ IntoParIter {
+ inner: self.raw.into_par_iter(),
+ }
+ }
+}
+
+impl<'a, T: Sync, A: Allocator> IntoParallelIterator for &'a HashTable<T, A> {
+ type Item = &'a T;
+ type Iter = ParIter<'a, T>;
+
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn into_par_iter(self) -> Self::Iter {
+ ParIter {
+ inner: unsafe { self.raw.par_iter() },
+ marker: PhantomData,
+ }
+ }
+}
+
+impl<'a, T: Send, A: Allocator> IntoParallelIterator for &'a mut HashTable<T, A> {
+ type Item = &'a mut T;
+ type Iter = ParIterMut<'a, T>;
+
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn into_par_iter(self) -> Self::Iter {
+ ParIterMut {
+ inner: unsafe { self.raw.par_iter() },
+ marker: PhantomData,
+ }
+ }
+}
+
+#[cfg(test)]
+mod test_par_table {
+ use alloc::vec::Vec;
+ use core::sync::atomic::{AtomicUsize, Ordering};
+
+ use rayon::prelude::*;
+
+ use crate::{
+ hash_map::{make_hash, DefaultHashBuilder},
+ hash_table::HashTable,
+ };
+
+ #[test]
+ fn test_iterate() {
+ let hasher = DefaultHashBuilder::default();
+ let mut a = HashTable::new();
+ for i in 0..32 {
+ a.insert_unique(make_hash(&hasher, &i), i, |x| make_hash(&hasher, x));
+ }
+ let observed = AtomicUsize::new(0);
+ a.par_iter().for_each(|k| {
+ observed.fetch_or(1 << *k, Ordering::Relaxed);
+ });
+ assert_eq!(observed.into_inner(), 0xFFFF_FFFF);
+ }
+
+ #[test]
+ fn test_move_iter() {
+ let hasher = DefaultHashBuilder::default();
+ let hs = {
+ let mut hs = HashTable::new();
+
+ hs.insert_unique(make_hash(&hasher, &'a'), 'a', |x| make_hash(&hasher, x));
+ hs.insert_unique(make_hash(&hasher, &'b'), 'b', |x| make_hash(&hasher, x));
+
+ hs
+ };
+
+ let v = hs.into_par_iter().collect::<Vec<char>>();
+ assert!(v == ['a', 'b'] || v == ['b', 'a']);
+ }
+}
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_map.rs b/third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_map.rs
new file mode 100644
index 0000000000..fae7f76763
--- /dev/null
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_map.rs
@@ -0,0 +1,125 @@
+use crate::HashMap;
+use core::{
+ borrow::Borrow,
+ hash::{BuildHasher, Hash},
+};
+use rkyv::{
+ collections::hash_map::{ArchivedHashMap, HashMapResolver},
+ ser::{ScratchSpace, Serializer},
+ Archive, Deserialize, Fallible, Serialize,
+};
+
+impl<K: Archive + Hash + Eq, V: Archive, S> Archive for HashMap<K, V, S>
+where
+ K::Archived: Hash + Eq,
+{
+ type Archived = ArchivedHashMap<K::Archived, V::Archived>;
+ type Resolver = HashMapResolver;
+
+ #[inline]
+ unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
+ ArchivedHashMap::resolve_from_len(self.len(), pos, resolver, out);
+ }
+}
+
+impl<K, V, S, RandomState> Serialize<S> for HashMap<K, V, RandomState>
+where
+ K: Serialize<S> + Hash + Eq,
+ K::Archived: Hash + Eq,
+ V: Serialize<S>,
+ S: Serializer + ScratchSpace + ?Sized,
+{
+ #[inline]
+ fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
+ unsafe { ArchivedHashMap::serialize_from_iter(self.iter(), serializer) }
+ }
+}
+
+impl<K: Archive + Hash + Eq, V: Archive, D: Fallible + ?Sized, S: Default + BuildHasher>
+ Deserialize<HashMap<K, V, S>, D> for ArchivedHashMap<K::Archived, V::Archived>
+where
+ K::Archived: Deserialize<K, D> + Hash + Eq,
+ V::Archived: Deserialize<V, D>,
+{
+ #[inline]
+ fn deserialize(&self, deserializer: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
+ let mut result = HashMap::with_capacity_and_hasher(self.len(), S::default());
+ for (k, v) in self.iter() {
+ result.insert(k.deserialize(deserializer)?, v.deserialize(deserializer)?);
+ }
+ Ok(result)
+ }
+}
+
+impl<K: Hash + Eq + Borrow<AK>, V, AK: Hash + Eq, AV: PartialEq<V>, S: BuildHasher>
+ PartialEq<HashMap<K, V, S>> for ArchivedHashMap<AK, AV>
+{
+ #[inline]
+ fn eq(&self, other: &HashMap<K, V, S>) -> bool {
+ if self.len() != other.len() {
+ false
+ } else {
+ self.iter()
+ .all(|(key, value)| other.get(key).map_or(false, |v| value.eq(v)))
+ }
+ }
+}
+
+impl<K: Hash + Eq + Borrow<AK>, V, AK: Hash + Eq, AV: PartialEq<V>>
+ PartialEq<ArchivedHashMap<AK, AV>> for HashMap<K, V>
+{
+ #[inline]
+ fn eq(&self, other: &ArchivedHashMap<AK, AV>) -> bool {
+ other.eq(self)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::HashMap;
+ use alloc::string::String;
+ use rkyv::{
+ archived_root, check_archived_root,
+ ser::{serializers::AllocSerializer, Serializer},
+ Deserialize, Infallible,
+ };
+
+ #[test]
+ fn index_map() {
+ let mut value = HashMap::new();
+ value.insert(String::from("foo"), 10);
+ value.insert(String::from("bar"), 20);
+ value.insert(String::from("baz"), 40);
+ value.insert(String::from("bat"), 80);
+
+ let mut serializer = AllocSerializer::<4096>::default();
+ serializer.serialize_value(&value).unwrap();
+ let result = serializer.into_serializer().into_inner();
+ let archived = unsafe { archived_root::<HashMap<String, i32>>(result.as_ref()) };
+
+ assert_eq!(value.len(), archived.len());
+ for (k, v) in value.iter() {
+ let (ak, av) = archived.get_key_value(k.as_str()).unwrap();
+ assert_eq!(k, ak);
+ assert_eq!(v, av);
+ }
+
+ let deserialized: HashMap<String, i32> = archived.deserialize(&mut Infallible).unwrap();
+ assert_eq!(value, deserialized);
+ }
+
+ #[test]
+ fn validate_index_map() {
+ let mut value = HashMap::new();
+ value.insert(String::from("foo"), 10);
+ value.insert(String::from("bar"), 20);
+ value.insert(String::from("baz"), 40);
+ value.insert(String::from("bat"), 80);
+
+ let mut serializer = AllocSerializer::<4096>::default();
+ serializer.serialize_value(&value).unwrap();
+ let result = serializer.into_serializer().into_inner();
+ check_archived_root::<HashMap<String, i32>>(result.as_ref())
+ .expect("failed to validate archived index map");
+ }
+}
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_set.rs b/third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_set.rs
new file mode 100644
index 0000000000..c8a69cf4fc
--- /dev/null
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rkyv/hash_set.rs
@@ -0,0 +1,123 @@
+use crate::HashSet;
+use core::{
+ borrow::Borrow,
+ hash::{BuildHasher, Hash},
+};
+use rkyv::{
+ collections::hash_set::{ArchivedHashSet, HashSetResolver},
+ ser::{ScratchSpace, Serializer},
+ Archive, Deserialize, Fallible, Serialize,
+};
+
+impl<K: Archive + Hash + Eq, S> Archive for HashSet<K, S>
+where
+ K::Archived: Hash + Eq,
+{
+ type Archived = ArchivedHashSet<K::Archived>;
+ type Resolver = HashSetResolver;
+
+ #[inline]
+ unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
+ ArchivedHashSet::<K::Archived>::resolve_from_len(self.len(), pos, resolver, out);
+ }
+}
+
+impl<K, S, RS> Serialize<S> for HashSet<K, RS>
+where
+ K::Archived: Hash + Eq,
+ K: Serialize<S> + Hash + Eq,
+ S: ScratchSpace + Serializer + ?Sized,
+{
+ #[inline]
+ fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
+ unsafe { ArchivedHashSet::serialize_from_iter(self.iter(), serializer) }
+ }
+}
+
+impl<K, D, S> Deserialize<HashSet<K, S>, D> for ArchivedHashSet<K::Archived>
+where
+ K: Archive + Hash + Eq,
+ K::Archived: Deserialize<K, D> + Hash + Eq,
+ D: Fallible + ?Sized,
+ S: Default + BuildHasher,
+{
+ #[inline]
+ fn deserialize(&self, deserializer: &mut D) -> Result<HashSet<K, S>, D::Error> {
+ let mut result = HashSet::with_hasher(S::default());
+ for k in self.iter() {
+ result.insert(k.deserialize(deserializer)?);
+ }
+ Ok(result)
+ }
+}
+
+impl<K: Hash + Eq + Borrow<AK>, AK: Hash + Eq, S: BuildHasher> PartialEq<HashSet<K, S>>
+ for ArchivedHashSet<AK>
+{
+ #[inline]
+ fn eq(&self, other: &HashSet<K, S>) -> bool {
+ if self.len() != other.len() {
+ false
+ } else {
+ self.iter().all(|key| other.get(key).is_some())
+ }
+ }
+}
+
+impl<K: Hash + Eq + Borrow<AK>, AK: Hash + Eq, S: BuildHasher> PartialEq<ArchivedHashSet<AK>>
+ for HashSet<K, S>
+{
+ #[inline]
+ fn eq(&self, other: &ArchivedHashSet<AK>) -> bool {
+ other.eq(self)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::HashSet;
+ use alloc::string::String;
+ use rkyv::{
+ archived_root, check_archived_root,
+ ser::{serializers::AllocSerializer, Serializer},
+ Deserialize, Infallible,
+ };
+
+ #[test]
+ fn index_set() {
+ let mut value = HashSet::new();
+ value.insert(String::from("foo"));
+ value.insert(String::from("bar"));
+ value.insert(String::from("baz"));
+ value.insert(String::from("bat"));
+
+ let mut serializer = AllocSerializer::<4096>::default();
+ serializer.serialize_value(&value).unwrap();
+ let result = serializer.into_serializer().into_inner();
+ let archived = unsafe { archived_root::<HashSet<String>>(result.as_ref()) };
+
+ assert_eq!(value.len(), archived.len());
+ for k in value.iter() {
+ let ak = archived.get(k.as_str()).unwrap();
+ assert_eq!(k, ak);
+ }
+
+ let deserialized: HashSet<String> = archived.deserialize(&mut Infallible).unwrap();
+ assert_eq!(value, deserialized);
+ }
+
+ #[test]
+ fn validate_index_set() {
+ let mut value = HashSet::new();
+ value.insert(String::from("foo"));
+ value.insert(String::from("bar"));
+ value.insert(String::from("baz"));
+ value.insert(String::from("bat"));
+
+ let mut serializer = AllocSerializer::<4096>::default();
+ serializer.serialize_value(&value).unwrap();
+ let result = serializer.into_serializer().into_inner();
+ check_archived_root::<HashSet<String>>(result.as_ref())
+ .expect("failed to validate archived index set");
+ }
+}
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/rkyv/mod.rs b/third_party/rust/hashbrown/src/external_trait_impls/rkyv/mod.rs
new file mode 100644
index 0000000000..2bde6a0653
--- /dev/null
+++ b/third_party/rust/hashbrown/src/external_trait_impls/rkyv/mod.rs
@@ -0,0 +1,2 @@
+mod hash_map;
+mod hash_set;
diff --git a/third_party/rust/hashbrown/src/external_trait_impls/serde.rs b/third_party/rust/hashbrown/src/external_trait_impls/serde.rs
index 4d62deeb7a..0a76dbec25 100644
--- a/third_party/rust/hashbrown/src/external_trait_impls/serde.rs
+++ b/third_party/rust/hashbrown/src/external_trait_impls/serde.rs
@@ -11,6 +11,7 @@ mod size_hint {
}
mod map {
+ use crate::raw::Allocator;
use core::fmt;
use core::hash::{BuildHasher, Hash};
use core::marker::PhantomData;
@@ -21,11 +22,12 @@ mod map {
use super::size_hint;
- impl<K, V, H> Serialize for HashMap<K, V, H>
+ impl<K, V, H, A> Serialize for HashMap<K, V, H, A>
where
K: Serialize + Eq + Hash,
V: Serialize,
H: BuildHasher,
+ A: Allocator,
{
#[cfg_attr(feature = "inline-more", inline)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -36,40 +38,46 @@ mod map {
}
}
- impl<'de, K, V, S> Deserialize<'de> for HashMap<K, V, S>
+ impl<'de, K, V, S, A> Deserialize<'de> for HashMap<K, V, S, A>
where
K: Deserialize<'de> + Eq + Hash,
V: Deserialize<'de>,
S: BuildHasher + Default,
+ A: Allocator + Default,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
- struct MapVisitor<K, V, S> {
- marker: PhantomData<HashMap<K, V, S>>,
+ struct MapVisitor<K, V, S, A>
+ where
+ A: Allocator,
+ {
+ marker: PhantomData<HashMap<K, V, S, A>>,
}
- impl<'de, K, V, S> Visitor<'de> for MapVisitor<K, V, S>
+ impl<'de, K, V, S, A> Visitor<'de> for MapVisitor<K, V, S, A>
where
K: Deserialize<'de> + Eq + Hash,
V: Deserialize<'de>,
S: BuildHasher + Default,
+ A: Allocator + Default,
{
- type Value = HashMap<K, V, S>;
+ type Value = HashMap<K, V, S, A>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a map")
}
#[cfg_attr(feature = "inline-more", inline)]
- fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
+ fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
where
- A: MapAccess<'de>,
+ M: MapAccess<'de>,
{
- let mut values = HashMap::with_capacity_and_hasher(
+ let mut values = HashMap::with_capacity_and_hasher_in(
size_hint::cautious(map.size_hint()),
S::default(),
+ A::default(),
);
while let Some((key, value)) = map.next_entry()? {
@@ -89,6 +97,7 @@ mod map {
}
mod set {
+ use crate::raw::Allocator;
use core::fmt;
use core::hash::{BuildHasher, Hash};
use core::marker::PhantomData;
@@ -99,10 +108,11 @@ mod set {
use super::size_hint;
- impl<T, H> Serialize for HashSet<T, H>
+ impl<T, H, A> Serialize for HashSet<T, H, A>
where
T: Serialize + Eq + Hash,
H: BuildHasher,
+ A: Allocator,
{
#[cfg_attr(feature = "inline-more", inline)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -113,38 +123,44 @@ mod set {
}
}
- impl<'de, T, S> Deserialize<'de> for HashSet<T, S>
+ impl<'de, T, S, A> Deserialize<'de> for HashSet<T, S, A>
where
T: Deserialize<'de> + Eq + Hash,
S: BuildHasher + Default,
+ A: Allocator + Default,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
- struct SeqVisitor<T, S> {
- marker: PhantomData<HashSet<T, S>>,
+ struct SeqVisitor<T, S, A>
+ where
+ A: Allocator,
+ {
+ marker: PhantomData<HashSet<T, S, A>>,
}
- impl<'de, T, S> Visitor<'de> for SeqVisitor<T, S>
+ impl<'de, T, S, A> Visitor<'de> for SeqVisitor<T, S, A>
where
T: Deserialize<'de> + Eq + Hash,
S: BuildHasher + Default,
+ A: Allocator + Default,
{
- type Value = HashSet<T, S>;
+ type Value = HashSet<T, S, A>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence")
}
#[cfg_attr(feature = "inline-more", inline)]
- fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+ fn visit_seq<M>(self, mut seq: M) -> Result<Self::Value, M::Error>
where
- A: SeqAccess<'de>,
+ M: SeqAccess<'de>,
{
- let mut values = HashSet::with_capacity_and_hasher(
+ let mut values = HashSet::with_capacity_and_hasher_in(
size_hint::cautious(seq.size_hint()),
S::default(),
+ A::default(),
);
while let Some(value) = seq.next_element()? {
@@ -166,12 +182,15 @@ mod set {
where
D: Deserializer<'de>,
{
- struct SeqInPlaceVisitor<'a, T, S>(&'a mut HashSet<T, S>);
+ struct SeqInPlaceVisitor<'a, T, S, A>(&'a mut HashSet<T, S, A>)
+ where
+ A: Allocator;
- impl<'a, 'de, T, S> Visitor<'de> for SeqInPlaceVisitor<'a, T, S>
+ impl<'a, 'de, T, S, A> Visitor<'de> for SeqInPlaceVisitor<'a, T, S, A>
where
T: Deserialize<'de> + Eq + Hash,
S: BuildHasher + Default,
+ A: Allocator,
{
type Value = ();
@@ -180,9 +199,9 @@ mod set {
}
#[cfg_attr(feature = "inline-more", inline)]
- fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+ fn visit_seq<M>(self, mut seq: M) -> Result<Self::Value, M::Error>
where
- A: SeqAccess<'de>,
+ M: SeqAccess<'de>,
{
self.0.clear();
self.0.reserve(size_hint::cautious(seq.size_hint()));
diff --git a/third_party/rust/hashbrown/src/lib.rs b/third_party/rust/hashbrown/src/lib.rs
index bc1c971303..f03ddb6ad9 100644
--- a/third_party/rust/hashbrown/src/lib.rs
+++ b/third_party/rust/hashbrown/src/lib.rs
@@ -20,9 +20,8 @@
extend_one,
allocator_api,
slice_ptr_get,
- nonnull_slice_from_raw_parts,
maybe_uninit_array_assume_init,
- build_hasher_simple_hash_one
+ strict_provenance
)
)]
#![allow(
@@ -37,6 +36,8 @@
)]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
+#![cfg_attr(feature = "nightly", warn(fuzzy_provenance_casts))]
+#![cfg_attr(feature = "nightly", allow(internal_features))]
#[cfg(test)]
#[macro_use]
@@ -81,6 +82,7 @@ mod map;
mod rustc_entry;
mod scopeguard;
mod set;
+mod table;
pub mod hash_map {
//! A hash map implemented with quadratic probing and SIMD lookup.
@@ -113,9 +115,63 @@ pub mod hash_set {
pub use crate::external_trait_impls::rayon::set::*;
}
}
+pub mod hash_table {
+ //! A hash table implemented with quadratic probing and SIMD lookup.
+ pub use crate::table::*;
+
+ #[cfg(feature = "rayon")]
+ /// [rayon]-based parallel iterator types for hash tables.
+ /// You will rarely need to interact with it directly unless you have need
+ /// to name one of the iterator types.
+ ///
+ /// [rayon]: https://docs.rs/rayon/1.0/rayon
+ pub mod rayon {
+ pub use crate::external_trait_impls::rayon::table::*;
+ }
+}
pub use crate::map::HashMap;
pub use crate::set::HashSet;
+pub use crate::table::HashTable;
+
+#[cfg(feature = "equivalent")]
+pub use equivalent::Equivalent;
+
+// This is only used as a fallback when building as part of `std`.
+#[cfg(not(feature = "equivalent"))]
+/// Key equivalence trait.
+///
+/// This trait defines the function used to compare the input value with the
+/// map keys (or set values) during a lookup operation such as [`HashMap::get`]
+/// or [`HashSet::contains`].
+/// It is provided with a blanket implementation based on the
+/// [`Borrow`](core::borrow::Borrow) trait.
+///
+/// # Correctness
+///
+/// Equivalent values must hash to the same value.
+pub trait Equivalent<K: ?Sized> {
+ /// Checks if this value is equivalent to the given key.
+ ///
+ /// Returns `true` if both values are equivalent, and `false` otherwise.
+ ///
+ /// # Correctness
+ ///
+ /// When this function returns `true`, both `self` and `key` must hash to
+ /// the same value.
+ fn equivalent(&self, key: &K) -> bool;
+}
+
+#[cfg(not(feature = "equivalent"))]
+impl<Q: ?Sized, K: ?Sized> Equivalent<K> for Q
+where
+ Q: Eq,
+ K: core::borrow::Borrow<Q>,
+{
+ fn equivalent(&self, key: &K) -> bool {
+ self == key.borrow()
+ }
+}
/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -130,21 +186,3 @@ pub enum TryReserveError {
layout: alloc::alloc::Layout,
},
}
-
-/// Wrapper around `Bump` which allows it to be used as an allocator for
-/// `HashMap`, `HashSet` and `RawTable`.
-///
-/// `Bump` can be used directly without this wrapper on nightly if you enable
-/// the `allocator-api` feature of the `bumpalo` crate.
-#[cfg(feature = "bumpalo")]
-#[derive(Clone, Copy, Debug)]
-pub struct BumpWrapper<'a>(pub &'a bumpalo::Bump);
-
-#[cfg(feature = "bumpalo")]
-#[test]
-fn test_bumpalo() {
- use bumpalo::Bump;
- let bump = Bump::new();
- let mut map = HashMap::new_in(BumpWrapper(&bump));
- map.insert(0, 1);
-}
diff --git a/third_party/rust/hashbrown/src/macros.rs b/third_party/rust/hashbrown/src/macros.rs
index f8ef917b14..eaba6bed1f 100644
--- a/third_party/rust/hashbrown/src/macros.rs
+++ b/third_party/rust/hashbrown/src/macros.rs
@@ -37,7 +37,7 @@ macro_rules! cfg_if {
// semicolon is all the remaining items
(@__items ($($not:meta,)*) ; ) => {};
(@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
- // Emit all items within one block, applying an approprate #[cfg]. The
+ // Emit all items within one block, applying an appropriate #[cfg]. The
// #[cfg] will require all `$m` matchers specified and must also negate
// all previous matchers.
cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
diff --git a/third_party/rust/hashbrown/src/map.rs b/third_party/rust/hashbrown/src/map.rs
index a5d3ccb97e..88a826582b 100644
--- a/third_party/rust/hashbrown/src/map.rs
+++ b/third_party/rust/hashbrown/src/map.rs
@@ -1,16 +1,18 @@
-use crate::raw::{Allocator, Bucket, Global, RawDrain, RawIntoIter, RawIter, RawTable};
-use crate::TryReserveError;
+use crate::raw::{
+ Allocator, Bucket, Global, RawDrain, RawExtractIf, RawIntoIter, RawIter, RawTable,
+};
+use crate::{Equivalent, TryReserveError};
use core::borrow::Borrow;
use core::fmt::{self, Debug};
use core::hash::{BuildHasher, Hash};
-use core::iter::{FromIterator, FusedIterator};
+use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::mem;
use core::ops::Index;
/// Default hasher for `HashMap`.
#[cfg(feature = "ahash")]
-pub type DefaultHashBuilder = ahash::RandomState;
+pub type DefaultHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;
/// Dummy default hasher for `HashMap`.
#[cfg(not(feature = "ahash"))]
@@ -182,10 +184,10 @@ pub enum DefaultHashBuilder {}
/// use hashbrown::HashMap;
///
/// let timber_resources: HashMap<&str, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)]
-/// .iter().cloned().collect();
+/// .into_iter().collect();
/// // use the values stored in map
/// ```
-pub struct HashMap<K, V, S = DefaultHashBuilder, A: Allocator + Clone = Global> {
+pub struct HashMap<K, V, S = DefaultHashBuilder, A: Allocator = Global> {
pub(crate) hash_builder: S,
pub(crate) table: RawTable<(K, V), A>,
}
@@ -209,13 +211,12 @@ impl<K: Clone, V: Clone, S: Clone, A: Allocator + Clone> Clone for HashMap<K, V,
/// Ensures that a single closure type across uses of this which, in turn prevents multiple
/// instances of any functions like RawTable::reserve from being generated
#[cfg_attr(feature = "inline-more", inline)]
-pub(crate) fn make_hasher<K, Q, V, S>(hash_builder: &S) -> impl Fn(&(Q, V)) -> u64 + '_
+pub(crate) fn make_hasher<Q, V, S>(hash_builder: &S) -> impl Fn(&(Q, V)) -> u64 + '_
where
- K: Borrow<Q>,
Q: Hash,
S: BuildHasher,
{
- move |val| make_hash::<K, Q, S>(hash_builder, &val.0)
+ move |val| make_hash::<Q, S>(hash_builder, &val.0)
}
/// Ensures that a single closure type across uses of this which, in turn prevents multiple
@@ -223,10 +224,9 @@ where
#[cfg_attr(feature = "inline-more", inline)]
fn equivalent_key<Q, K, V>(k: &Q) -> impl Fn(&(K, V)) -> bool + '_
where
- K: Borrow<Q>,
- Q: ?Sized + Eq,
+ Q: ?Sized + Equivalent<K>,
{
- move |x| k.eq(x.0.borrow())
+ move |x| k.equivalent(&x.0)
}
/// Ensures that a single closure type across uses of this which, in turn prevents multiple
@@ -234,17 +234,15 @@ where
#[cfg_attr(feature = "inline-more", inline)]
fn equivalent<Q, K>(k: &Q) -> impl Fn(&K) -> bool + '_
where
- K: Borrow<Q>,
- Q: ?Sized + Eq,
+ Q: ?Sized + Equivalent<K>,
{
- move |x| k.eq(x.borrow())
+ move |x| k.equivalent(x)
}
#[cfg(not(feature = "nightly"))]
#[cfg_attr(feature = "inline-more", inline)]
-pub(crate) fn make_hash<K, Q, S>(hash_builder: &S, val: &Q) -> u64
+pub(crate) fn make_hash<Q, S>(hash_builder: &S, val: &Q) -> u64
where
- K: Borrow<Q>,
Q: Hash + ?Sized,
S: BuildHasher,
{
@@ -256,38 +254,14 @@ where
#[cfg(feature = "nightly")]
#[cfg_attr(feature = "inline-more", inline)]
-pub(crate) fn make_hash<K, Q, S>(hash_builder: &S, val: &Q) -> u64
+pub(crate) fn make_hash<Q, S>(hash_builder: &S, val: &Q) -> u64
where
- K: Borrow<Q>,
Q: Hash + ?Sized,
S: BuildHasher,
{
hash_builder.hash_one(val)
}
-#[cfg(not(feature = "nightly"))]
-#[cfg_attr(feature = "inline-more", inline)]
-pub(crate) fn make_insert_hash<K, S>(hash_builder: &S, val: &K) -> u64
-where
- K: Hash,
- S: BuildHasher,
-{
- use core::hash::Hasher;
- let mut state = hash_builder.build_hasher();
- val.hash(&mut state);
- state.finish()
-}
-
-#[cfg(feature = "nightly")]
-#[cfg_attr(feature = "inline-more", inline)]
-pub(crate) fn make_insert_hash<K, S>(hash_builder: &S, val: &K) -> u64
-where
- K: Hash,
- S: BuildHasher,
-{
- hash_builder.hash_one(val)
-}
-
#[cfg(feature = "ahash")]
impl<K, V> HashMap<K, V, DefaultHashBuilder> {
/// Creates an empty `HashMap`.
@@ -295,6 +269,18 @@ impl<K, V> HashMap<K, V, DefaultHashBuilder> {
/// The hash map is initially created with a capacity of 0, so it will not allocate until it
/// is first inserted into.
///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`], for example with
+ /// [`with_hasher`](HashMap::with_hasher) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
/// # Examples
///
/// ```
@@ -313,6 +299,18 @@ impl<K, V> HashMap<K, V, DefaultHashBuilder> {
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash map will not allocate.
///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`], for example with
+ /// [`with_capacity_and_hasher`](HashMap::with_capacity_and_hasher) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
/// # Examples
///
/// ```
@@ -328,11 +326,46 @@ impl<K, V> HashMap<K, V, DefaultHashBuilder> {
}
#[cfg(feature = "ahash")]
-impl<K, V, A: Allocator + Clone> HashMap<K, V, DefaultHashBuilder, A> {
+impl<K, V, A: Allocator> HashMap<K, V, DefaultHashBuilder, A> {
/// Creates an empty `HashMap` using the given allocator.
///
/// The hash map is initially created with a capacity of 0, so it will not allocate until it
/// is first inserted into.
+ ///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`], for example with
+ /// [`with_hasher_in`](HashMap::with_hasher_in) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use hashbrown::HashMap;
+ /// use bumpalo::Bump;
+ ///
+ /// let bump = Bump::new();
+ /// let mut map = HashMap::new_in(&bump);
+ ///
+ /// // The created HashMap holds none elements
+ /// assert_eq!(map.len(), 0);
+ ///
+ /// // The created HashMap also doesn't allocate memory
+ /// assert_eq!(map.capacity(), 0);
+ ///
+ /// // Now we insert element inside created HashMap
+ /// map.insert("One", 1);
+ /// // We can see that the HashMap holds 1 element
+ /// assert_eq!(map.len(), 1);
+ /// // And it also allocates some capacity
+ /// assert!(map.capacity() > 1);
+ /// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn new_in(alloc: A) -> Self {
Self::with_hasher_in(DefaultHashBuilder::default(), alloc)
@@ -342,6 +375,46 @@ impl<K, V, A: Allocator + Clone> HashMap<K, V, DefaultHashBuilder, A> {
///
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash map will not allocate.
+ ///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`], for example with
+ /// [`with_capacity_and_hasher_in`](HashMap::with_capacity_and_hasher_in) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use hashbrown::HashMap;
+ /// use bumpalo::Bump;
+ ///
+ /// let bump = Bump::new();
+ /// let mut map = HashMap::with_capacity_in(5, &bump);
+ ///
+ /// // The created HashMap holds none elements
+ /// assert_eq!(map.len(), 0);
+ /// // But it can hold at least 5 elements without reallocating
+ /// let empty_map_capacity = map.capacity();
+ /// assert!(empty_map_capacity >= 5);
+ ///
+ /// // Now we insert some 5 elements inside created HashMap
+ /// map.insert("One", 1);
+ /// map.insert("Two", 2);
+ /// map.insert("Three", 3);
+ /// map.insert("Four", 4);
+ /// map.insert("Five", 5);
+ ///
+ /// // We can see that the HashMap holds 5 elements
+ /// assert_eq!(map.len(), 5);
+ /// // But its capacity isn't changed
+ /// assert_eq!(map.capacity(), empty_map_capacity)
+ /// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
Self::with_capacity_and_hasher_in(capacity, DefaultHashBuilder::default(), alloc)
@@ -355,14 +428,21 @@ impl<K, V, S> HashMap<K, V, S> {
/// The hash map is initially created with a capacity of 0, so it will not
/// allocate until it is first inserted into.
///
- /// Warning: `hash_builder` is normally randomly generated, and
- /// is designed to allow HashMaps to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`].
///
/// The `hash_builder` passed should implement the [`BuildHasher`] trait for
/// the HashMap to be useful, see its documentation for details.
///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
+ ///
/// # Examples
///
/// ```
@@ -376,8 +456,6 @@ impl<K, V, S> HashMap<K, V, S> {
///
/// map.insert(1, 2);
/// ```
- ///
- /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
#[cfg_attr(feature = "inline-more", inline)]
pub const fn with_hasher(hash_builder: S) -> Self {
Self {
@@ -392,14 +470,21 @@ impl<K, V, S> HashMap<K, V, S> {
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash map will not allocate.
///
- /// Warning: `hash_builder` is normally randomly generated, and
- /// is designed to allow HashMaps to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`].
///
/// The `hash_builder` passed should implement the [`BuildHasher`] trait for
/// the HashMap to be useful, see its documentation for details.
///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
+ ///
/// # Examples
///
/// ```
@@ -413,8 +498,6 @@ impl<K, V, S> HashMap<K, V, S> {
///
/// map.insert(1, 2);
/// ```
- ///
- /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
#[cfg_attr(feature = "inline-more", inline)]
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
Self {
@@ -424,7 +507,7 @@ impl<K, V, S> HashMap<K, V, S> {
}
}
-impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
+impl<K, V, S, A: Allocator> HashMap<K, V, S, A> {
/// Returns a reference to the underlying allocator.
#[inline]
pub fn allocator(&self) -> &A {
@@ -434,12 +517,19 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
/// Creates an empty `HashMap` which will use the given hash builder to hash
/// keys. It will be allocated with the given allocator.
///
- /// The created map has the default initial capacity.
+ /// The hash map is initially created with a capacity of 0, so it will not allocate until it
+ /// is first inserted into.
+ ///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`].
///
- /// Warning: `hash_builder` is normally randomly generated, and
- /// is designed to allow HashMaps to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
///
/// # Examples
///
@@ -452,7 +542,7 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
/// map.insert(1, 2);
/// ```
#[cfg_attr(feature = "inline-more", inline)]
- pub fn with_hasher_in(hash_builder: S, alloc: A) -> Self {
+ pub const fn with_hasher_in(hash_builder: S, alloc: A) -> Self {
Self {
hash_builder,
table: RawTable::new_in(alloc),
@@ -465,10 +555,16 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash map will not allocate.
///
- /// Warning: `hash_builder` is normally randomly generated, and
- /// is designed to allow HashMaps to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashMap`].
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
///
/// # Examples
///
@@ -810,14 +906,11 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
///
/// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
/// assert_eq!(map.len(), 8);
- /// let capacity_before_retain = map.capacity();
///
/// map.retain(|&k, _| k % 2 == 0);
///
/// // We can see, that the number of elements inside map is changed.
/// assert_eq!(map.len(), 4);
- /// // But map capacity is equal to old one.
- /// assert_eq!(map.capacity(), capacity_before_retain);
///
/// let mut vec: Vec<(i32, i32)> = map.iter().map(|(&k, &v)| (k, v)).collect();
/// vec.sort_unstable();
@@ -844,26 +937,25 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
/// In other words, move all pairs `(k, v)` such that `f(&k, &mut v)` returns `true` out
/// into another iterator.
///
- /// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of
+ /// Note that `extract_if` lets you mutate every value in the filter closure, regardless of
/// whether you choose to keep or remove it.
///
- /// When the returned DrainedFilter is dropped, any remaining elements that satisfy
- /// the predicate are dropped from the table.
- ///
- /// It is unspecified how many more elements will be subjected to the closure
- /// if a panic occurs in the closure, or a panic occurs while dropping an element,
- /// or if the `DrainFilter` value is leaked.
+ /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
+ /// or the iteration short-circuits, then the remaining elements will be retained.
+ /// Use [`retain()`] with a negated predicate if you do not need the returned iterator.
///
/// Keeps the allocated memory for reuse.
///
+ /// [`retain()`]: HashMap::retain
+ ///
/// # Examples
///
/// ```
/// use hashbrown::HashMap;
///
/// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
- /// let capacity_before_drain_filter = map.capacity();
- /// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect();
+ ///
+ /// let drained: HashMap<i32, i32> = map.extract_if(|k, _v| k % 2 == 0).collect();
///
/// let mut evens = drained.keys().cloned().collect::<Vec<_>>();
/// let mut odds = map.keys().cloned().collect::<Vec<_>>();
@@ -872,27 +964,24 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
///
/// assert_eq!(evens, vec![0, 2, 4, 6]);
/// assert_eq!(odds, vec![1, 3, 5, 7]);
- /// // Map capacity is equal to old one.
- /// assert_eq!(map.capacity(), capacity_before_drain_filter);
///
/// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
///
/// { // Iterator is dropped without being consumed.
- /// let d = map.drain_filter(|k, _v| k % 2 != 0);
+ /// let d = map.extract_if(|k, _v| k % 2 != 0);
/// }
///
- /// // But the map lens have been reduced by half
- /// // even if we do not use DrainFilter iterator.
- /// assert_eq!(map.len(), 4);
+ /// // ExtractIf was not exhausted, therefore no elements were drained.
+ /// assert_eq!(map.len(), 8);
/// ```
#[cfg_attr(feature = "inline-more", inline)]
- pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F, A>
+ pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, K, V, F, A>
where
F: FnMut(&K, &mut V) -> bool,
{
- DrainFilter {
+ ExtractIf {
f,
- inner: DrainFilterInner {
+ inner: RawExtractIf {
iter: unsafe { self.table.iter() },
table: &mut self.table,
},
@@ -984,7 +1073,7 @@ impl<K, V, S, A> HashMap<K, V, S, A>
where
K: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
/// Reserves capacity for at least `additional` more elements to be inserted
/// in the `HashMap`. The collection may reserve more space to avoid
@@ -992,9 +1081,12 @@ where
///
/// # Panics
///
- /// Panics if the new allocation size overflows [`usize`].
+ /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program
+ /// in case of allocation error. Use [`try_reserve`](HashMap::try_reserve) instead
+ /// if you want to handle memory allocation failure.
///
- /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
+ /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html
+ /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
///
/// # Examples
///
@@ -1012,7 +1104,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn reserve(&mut self, additional: usize) {
self.table
- .reserve(additional, make_hasher::<K, _, V, S>(&self.hash_builder));
+ .reserve(additional, make_hasher::<_, V, S>(&self.hash_builder));
}
/// Tries to reserve capacity for at least `additional` more elements to be inserted
@@ -1062,7 +1154,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.table
- .try_reserve(additional, make_hasher::<K, _, V, S>(&self.hash_builder))
+ .try_reserve(additional, make_hasher::<_, V, S>(&self.hash_builder))
}
/// Shrinks the capacity of the map as much as possible. It will drop
@@ -1084,7 +1176,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn shrink_to_fit(&mut self) {
self.table
- .shrink_to(0, make_hasher::<K, _, V, S>(&self.hash_builder));
+ .shrink_to(0, make_hasher::<_, V, S>(&self.hash_builder));
}
/// Shrinks the capacity of the map with a lower limit. It will drop
@@ -1113,7 +1205,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn shrink_to(&mut self, min_capacity: usize) {
self.table
- .shrink_to(min_capacity, make_hasher::<K, _, V, S>(&self.hash_builder));
+ .shrink_to(min_capacity, make_hasher::<_, V, S>(&self.hash_builder));
}
/// Gets the given key's corresponding entry in the map for in-place manipulation.
@@ -1137,7 +1229,7 @@ where
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S, A> {
- let hash = make_insert_hash::<K, S>(&self.hash_builder, &key);
+ let hash = make_hash::<K, S>(&self.hash_builder, &key);
if let Some(elem) = self.table.find(hash, equivalent_key(&key)) {
Entry::Occupied(OccupiedEntry {
hash,
@@ -1174,10 +1266,9 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn entry_ref<'a, 'b, Q: ?Sized>(&'a mut self, key: &'b Q) -> EntryRef<'a, 'b, K, Q, V, S, A>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
- let hash = make_hash::<K, Q, S>(&self.hash_builder, key);
+ let hash = make_hash::<Q, S>(&self.hash_builder, key);
if let Some(elem) = self.table.find(hash, equivalent_key(key)) {
EntryRef::Occupied(OccupiedEntryRef {
hash,
@@ -1216,12 +1307,11 @@ where
#[inline]
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
// Avoid `Option::map` because it bloats LLVM IR.
match self.get_inner(k) {
- Some(&(_, ref v)) => Some(v),
+ Some((_, v)) => Some(v),
None => None,
}
}
@@ -1248,12 +1338,11 @@ where
#[inline]
pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
// Avoid `Option::map` because it bloats LLVM IR.
match self.get_inner(k) {
- Some(&(ref key, ref value)) => Some((key, value)),
+ Some((key, value)) => Some((key, value)),
None => None,
}
}
@@ -1261,13 +1350,12 @@ where
#[inline]
fn get_inner<Q: ?Sized>(&self, k: &Q) -> Option<&(K, V)>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
if self.table.is_empty() {
None
} else {
- let hash = make_hash::<K, Q, S>(&self.hash_builder, k);
+ let hash = make_hash::<Q, S>(&self.hash_builder, k);
self.table.get(hash, equivalent_key(k))
}
}
@@ -1298,8 +1386,7 @@ where
#[inline]
pub fn get_key_value_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<(&K, &mut V)>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
// Avoid `Option::map` because it bloats LLVM IR.
match self.get_inner_mut(k) {
@@ -1330,8 +1417,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
self.get_inner(k).is_some()
}
@@ -1362,8 +1448,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
// Avoid `Option::map` because it bloats LLVM IR.
match self.get_inner_mut(k) {
@@ -1375,13 +1460,12 @@ where
#[inline]
fn get_inner_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut (K, V)>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
if self.table.is_empty() {
None
} else {
- let hash = make_hash::<K, Q, S>(&self.hash_builder, k);
+ let hash = make_hash::<Q, S>(&self.hash_builder, k);
self.table.get_mut(hash, equivalent_key(k))
}
}
@@ -1431,8 +1515,7 @@ where
/// ```
pub fn get_many_mut<Q: ?Sized, const N: usize>(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
self.get_many_mut_inner(ks).map(|res| res.map(|(_, v)| v))
}
@@ -1487,8 +1570,7 @@ where
ks: [&Q; N],
) -> Option<[&'_ mut V; N]>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
self.get_many_unchecked_mut_inner(ks)
.map(|res| res.map(|(_, v)| v))
@@ -1543,8 +1625,7 @@ where
ks: [&Q; N],
) -> Option<[(&'_ K, &'_ mut V); N]>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
self.get_many_mut_inner(ks)
.map(|res| res.map(|(k, v)| (&*k, v)))
@@ -1599,8 +1680,7 @@ where
ks: [&Q; N],
) -> Option<[(&'_ K, &'_ mut V); N]>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
self.get_many_unchecked_mut_inner(ks)
.map(|res| res.map(|(k, v)| (&*k, v)))
@@ -1611,12 +1691,11 @@ where
ks: [&Q; N],
) -> Option<[&'_ mut (K, V); N]>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
let hashes = self.build_hashes_inner(ks);
self.table
- .get_many_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow()))
+ .get_many_mut(hashes, |i, (k, _)| ks[i].equivalent(k))
}
unsafe fn get_many_unchecked_mut_inner<Q: ?Sized, const N: usize>(
@@ -1624,22 +1703,20 @@ where
ks: [&Q; N],
) -> Option<[&'_ mut (K, V); N]>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
let hashes = self.build_hashes_inner(ks);
self.table
- .get_many_unchecked_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow()))
+ .get_many_unchecked_mut(hashes, |i, (k, _)| ks[i].equivalent(k))
}
fn build_hashes_inner<Q: ?Sized, const N: usize>(&self, ks: [&Q; N]) -> [u64; N]
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
let mut hashes = [0_u64; N];
for i in 0..N {
- hashes[i] = make_hash::<K, Q, S>(&self.hash_builder, ks[i]);
+ hashes[i] = make_hash::<Q, S>(&self.hash_builder, ks[i]);
}
hashes
}
@@ -1672,13 +1749,19 @@ where
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
- let hash = make_insert_hash::<K, S>(&self.hash_builder, &k);
- if let Some((_, item)) = self.table.get_mut(hash, equivalent_key(&k)) {
- Some(mem::replace(item, v))
- } else {
- self.table
- .insert(hash, (k, v), make_hasher::<K, _, V, S>(&self.hash_builder));
- None
+ let hash = make_hash::<K, S>(&self.hash_builder, &k);
+ let hasher = make_hasher::<_, V, S>(&self.hash_builder);
+ match self
+ .table
+ .find_or_find_insert_slot(hash, equivalent_key(&k), hasher)
+ {
+ Ok(bucket) => Some(mem::replace(unsafe { &mut bucket.as_mut().1 }, v)),
+ Err(slot) => {
+ unsafe {
+ self.table.insert_in_slot(hash, slot, (k, v));
+ }
+ None
+ }
}
}
@@ -1733,10 +1816,10 @@ where
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert_unique_unchecked(&mut self, k: K, v: V) -> (&K, &mut V) {
- let hash = make_insert_hash::<K, S>(&self.hash_builder, &k);
+ let hash = make_hash::<K, S>(&self.hash_builder, &k);
let bucket = self
.table
- .insert(hash, (k, v), make_hasher::<K, _, V, S>(&self.hash_builder));
+ .insert(hash, (k, v), make_hasher::<_, V, S>(&self.hash_builder));
let (k_ref, v_ref) = unsafe { bucket.as_mut() };
(k_ref, v_ref)
}
@@ -1801,19 +1884,17 @@ where
/// assert!(map.is_empty() && map.capacity() == 0);
///
/// map.insert(1, "a");
- /// let capacity_before_remove = map.capacity();
///
/// assert_eq!(map.remove(&1), Some("a"));
/// assert_eq!(map.remove(&1), None);
///
- /// // Now map holds none elements but capacity is equal to the old one
- /// assert!(map.len() == 0 && map.capacity() == capacity_before_remove);
+ /// // Now map holds none elements
+ /// assert!(map.is_empty());
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
// Avoid `Option::map` because it bloats LLVM IR.
match self.remove_entry(k) {
@@ -1842,26 +1923,24 @@ where
/// assert!(map.is_empty() && map.capacity() == 0);
///
/// map.insert(1, "a");
- /// let capacity_before_remove = map.capacity();
///
/// assert_eq!(map.remove_entry(&1), Some((1, "a")));
/// assert_eq!(map.remove(&1), None);
///
- /// // Now map hold none elements but capacity is equal to the old one
- /// assert!(map.len() == 0 && map.capacity() == capacity_before_remove);
+ /// // Now map hold none elements
+ /// assert!(map.is_empty());
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
where
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
- let hash = make_hash::<K, Q, S>(&self.hash_builder, k);
+ let hash = make_hash::<Q, S>(&self.hash_builder, k);
self.table.remove_entry(hash, equivalent_key(k))
}
}
-impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
+impl<K, V, S, A: Allocator> HashMap<K, V, S, A> {
/// Creates a raw entry builder for the HashMap.
///
/// Raw entries provide the lowest level of control for searching and
@@ -2013,19 +2092,31 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
RawEntryBuilder { map: self }
}
+ /// Returns a reference to the [`RawTable`] used underneath [`HashMap`].
+ /// This function is only available if the `raw` feature of the crate is enabled.
+ ///
+ /// See [`raw_table_mut`] for more.
+ ///
+ /// [`raw_table_mut`]: Self::raw_table_mut
+ #[cfg(feature = "raw")]
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub fn raw_table(&self) -> &RawTable<(K, V), A> {
+ &self.table
+ }
+
/// Returns a mutable reference to the [`RawTable`] used underneath [`HashMap`].
/// This function is only available if the `raw` feature of the crate is enabled.
///
/// # Note
///
- /// Calling the function safe, but using raw hash table API's may require
+ /// Calling this function is safe, but using the raw hash table API may require
/// unsafe functions or blocks.
///
/// `RawTable` API gives the lowest level of control under the map that can be useful
/// for extending the HashMap's API, but may lead to *[undefined behavior]*.
///
/// [`HashMap`]: struct.HashMap.html
- /// [`RawTable`]: raw/struct.RawTable.html
+ /// [`RawTable`]: crate::raw::RawTable
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// # Examples
@@ -2049,9 +2140,9 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
/// where
/// F: Fn(&(K, V)) -> bool,
/// {
- /// let raw_table = map.raw_table();
+ /// let raw_table = map.raw_table_mut();
/// match raw_table.find(hash, is_match) {
- /// Some(bucket) => Some(unsafe { raw_table.remove(bucket) }),
+ /// Some(bucket) => Some(unsafe { raw_table.remove(bucket).0 }),
/// None => None,
/// }
/// }
@@ -2070,7 +2161,7 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
/// ```
#[cfg(feature = "raw")]
#[cfg_attr(feature = "inline-more", inline)]
- pub fn raw_table(&mut self) -> &mut RawTable<(K, V), A> {
+ pub fn raw_table_mut(&mut self) -> &mut RawTable<(K, V), A> {
&mut self.table
}
}
@@ -2080,7 +2171,7 @@ where
K: Eq + Hash,
V: PartialEq,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
@@ -2097,7 +2188,7 @@ where
K: Eq + Hash,
V: Eq,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
}
@@ -2105,7 +2196,7 @@ impl<K, V, S, A> Debug for HashMap<K, V, S, A>
where
K: Debug,
V: Debug,
- A: Allocator + Clone,
+ A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
@@ -2115,7 +2206,7 @@ where
impl<K, V, S, A> Default for HashMap<K, V, S, A>
where
S: Default,
- A: Default + Allocator + Clone,
+ A: Default + Allocator,
{
/// Creates an empty `HashMap<K, V, S, A>`, with the `Default` value for the hasher and allocator.
///
@@ -2140,10 +2231,10 @@ where
impl<K, Q: ?Sized, V, S, A> Index<&Q> for HashMap<K, V, S, A>
where
- K: Eq + Hash + Borrow<Q>,
- Q: Eq + Hash,
+ K: Eq + Hash,
+ Q: Hash + Equivalent<K>,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
type Output = V;
@@ -2174,7 +2265,7 @@ where
impl<K, V, A, const N: usize> From<[(K, V); N]> for HashMap<K, V, DefaultHashBuilder, A>
where
K: Eq + Hash,
- A: Default + Allocator + Clone,
+ A: Default + Allocator,
{
/// # Examples
///
@@ -2319,11 +2410,11 @@ impl<K, V> IterMut<'_, K, V> {
/// assert_eq!(iter.next(), None);
/// assert_eq!(iter.next(), None);
/// ```
-pub struct IntoIter<K, V, A: Allocator + Clone = Global> {
+pub struct IntoIter<K, V, A: Allocator = Global> {
inner: RawIntoIter<(K, V), A>,
}
-impl<K, V, A: Allocator + Clone> IntoIter<K, V, A> {
+impl<K, V, A: Allocator> IntoIter<K, V, A> {
/// Returns a iterator of references over the remaining items.
#[cfg_attr(feature = "inline-more", inline)]
pub(super) fn iter(&self) -> Iter<'_, K, V> {
@@ -2363,11 +2454,11 @@ impl<K, V, A: Allocator + Clone> IntoIter<K, V, A> {
/// assert_eq!(keys.next(), None);
/// assert_eq!(keys.next(), None);
/// ```
-pub struct IntoKeys<K, V, A: Allocator + Clone = Global> {
+pub struct IntoKeys<K, V, A: Allocator = Global> {
inner: IntoIter<K, V, A>,
}
-impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> {
+impl<K, V, A: Allocator> Iterator for IntoKeys<K, V, A> {
type Item = K;
#[inline]
@@ -2378,18 +2469,26 @@ impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[inline]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, |acc, (k, _)| f(acc, k))
+ }
}
-impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoKeys<K, V, A> {
+impl<K, V, A: Allocator> ExactSizeIterator for IntoKeys<K, V, A> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
-impl<K, V, A: Allocator + Clone> FusedIterator for IntoKeys<K, V, A> {}
+impl<K, V, A: Allocator> FusedIterator for IntoKeys<K, V, A> {}
-impl<K: Debug, V: Debug, A: Allocator + Clone> fmt::Debug for IntoKeys<K, V, A> {
+impl<K: Debug, V: Debug, A: Allocator> fmt::Debug for IntoKeys<K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.inner.iter().map(|(k, _)| k))
@@ -2425,11 +2524,11 @@ impl<K: Debug, V: Debug, A: Allocator + Clone> fmt::Debug for IntoKeys<K, V, A>
/// assert_eq!(values.next(), None);
/// assert_eq!(values.next(), None);
/// ```
-pub struct IntoValues<K, V, A: Allocator + Clone = Global> {
+pub struct IntoValues<K, V, A: Allocator = Global> {
inner: IntoIter<K, V, A>,
}
-impl<K, V, A: Allocator + Clone> Iterator for IntoValues<K, V, A> {
+impl<K, V, A: Allocator> Iterator for IntoValues<K, V, A> {
type Item = V;
#[inline]
@@ -2440,18 +2539,26 @@ impl<K, V, A: Allocator + Clone> Iterator for IntoValues<K, V, A> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[inline]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, |acc, (_, v)| f(acc, v))
+ }
}
-impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoValues<K, V, A> {
+impl<K, V, A: Allocator> ExactSizeIterator for IntoValues<K, V, A> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
-impl<K, V, A: Allocator + Clone> FusedIterator for IntoValues<K, V, A> {}
+impl<K, V, A: Allocator> FusedIterator for IntoValues<K, V, A> {}
-impl<K, V: Debug, A: Allocator + Clone> fmt::Debug for IntoValues<K, V, A> {
+impl<K, V: Debug, A: Allocator> fmt::Debug for IntoValues<K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.inner.iter().map(|(_, v)| v))
@@ -2583,11 +2690,11 @@ impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
/// assert_eq!(drain_iter.next(), None);
/// assert_eq!(drain_iter.next(), None);
/// ```
-pub struct Drain<'a, K, V, A: Allocator + Clone = Global> {
+pub struct Drain<'a, K, V, A: Allocator = Global> {
inner: RawDrain<'a, (K, V), A>,
}
-impl<K, V, A: Allocator + Clone> Drain<'_, K, V, A> {
+impl<K, V, A: Allocator> Drain<'_, K, V, A> {
/// Returns a iterator of references over the remaining items.
#[cfg_attr(feature = "inline-more", inline)]
pub(super) fn iter(&self) -> Iter<'_, K, V> {
@@ -2601,10 +2708,10 @@ impl<K, V, A: Allocator + Clone> Drain<'_, K, V, A> {
/// A draining iterator over entries of a `HashMap` which don't satisfy the predicate
/// `f(&k, &mut v)` in arbitrary order. The iterator element type is `(K, V)`.
///
-/// This `struct` is created by the [`drain_filter`] method on [`HashMap`]. See its
+/// This `struct` is created by the [`extract_if`] method on [`HashMap`]. See its
/// documentation for more.
///
-/// [`drain_filter`]: struct.HashMap.html#method.drain_filter
+/// [`extract_if`]: struct.HashMap.html#method.extract_if
/// [`HashMap`]: struct.HashMap.html
///
/// # Examples
@@ -2614,63 +2721,40 @@ impl<K, V, A: Allocator + Clone> Drain<'_, K, V, A> {
///
/// let mut map: HashMap<i32, &str> = [(1, "a"), (2, "b"), (3, "c")].into();
///
-/// let mut drain_filter = map.drain_filter(|k, _v| k % 2 != 0);
-/// let mut vec = vec![drain_filter.next(), drain_filter.next()];
+/// let mut extract_if = map.extract_if(|k, _v| k % 2 != 0);
+/// let mut vec = vec![extract_if.next(), extract_if.next()];
///
-/// // The `DrainFilter` iterator produces items in arbitrary order, so the
+/// // The `ExtractIf` iterator produces items in arbitrary order, so the
/// // items must be sorted to test them against a sorted array.
/// vec.sort_unstable();
/// assert_eq!(vec, [Some((1, "a")),Some((3, "c"))]);
///
/// // It is fused iterator
-/// assert_eq!(drain_filter.next(), None);
-/// assert_eq!(drain_filter.next(), None);
-/// drop(drain_filter);
+/// assert_eq!(extract_if.next(), None);
+/// assert_eq!(extract_if.next(), None);
+/// drop(extract_if);
///
/// assert_eq!(map.len(), 1);
/// ```
-pub struct DrainFilter<'a, K, V, F, A: Allocator + Clone = Global>
+#[must_use = "Iterators are lazy unless consumed"]
+pub struct ExtractIf<'a, K, V, F, A: Allocator = Global>
where
F: FnMut(&K, &mut V) -> bool,
{
f: F,
- inner: DrainFilterInner<'a, K, V, A>,
-}
-
-impl<'a, K, V, F, A> Drop for DrainFilter<'a, K, V, F, A>
-where
- F: FnMut(&K, &mut V) -> bool,
- A: Allocator + Clone,
-{
- #[cfg_attr(feature = "inline-more", inline)]
- fn drop(&mut self) {
- while let Some(item) = self.next() {
- let guard = ConsumeAllOnDrop(self);
- drop(item);
- mem::forget(guard);
- }
- }
-}
-
-pub(super) struct ConsumeAllOnDrop<'a, T: Iterator>(pub &'a mut T);
-
-impl<T: Iterator> Drop for ConsumeAllOnDrop<'_, T> {
- #[cfg_attr(feature = "inline-more", inline)]
- fn drop(&mut self) {
- self.0.for_each(drop);
- }
+ inner: RawExtractIf<'a, (K, V), A>,
}
-impl<K, V, F, A> Iterator for DrainFilter<'_, K, V, F, A>
+impl<K, V, F, A> Iterator for ExtractIf<'_, K, V, F, A>
where
F: FnMut(&K, &mut V) -> bool,
- A: Allocator + Clone,
+ A: Allocator,
{
type Item = (K, V);
#[cfg_attr(feature = "inline-more", inline)]
fn next(&mut self) -> Option<Self::Item> {
- self.inner.next(&mut self.f)
+ self.inner.next(|&mut (ref k, ref mut v)| (self.f)(k, v))
}
#[inline]
@@ -2679,31 +2763,7 @@ where
}
}
-impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
-
-/// Portions of `DrainFilter` shared with `set::DrainFilter`
-pub(super) struct DrainFilterInner<'a, K, V, A: Allocator + Clone> {
- pub iter: RawIter<(K, V)>,
- pub table: &'a mut RawTable<(K, V), A>,
-}
-
-impl<K, V, A: Allocator + Clone> DrainFilterInner<'_, K, V, A> {
- #[cfg_attr(feature = "inline-more", inline)]
- pub(super) fn next<F>(&mut self, f: &mut F) -> Option<(K, V)>
- where
- F: FnMut(&K, &mut V) -> bool,
- {
- unsafe {
- for item in &mut self.iter {
- let &mut (ref key, ref mut value) = item.as_mut();
- if f(key, value) {
- return Some(self.table.remove(item));
- }
- }
- }
- None
- }
-}
+impl<K, V, F> FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
/// A mutable iterator over the values of a `HashMap` in arbitrary order.
/// The iterator element type is `&'a mut V`.
@@ -2791,7 +2851,7 @@ pub struct ValuesMut<'a, K, V> {
///
/// assert_eq!(map.len(), 6);
/// ```
-pub struct RawEntryBuilderMut<'a, K, V, S, A: Allocator + Clone = Global> {
+pub struct RawEntryBuilderMut<'a, K, V, S, A: Allocator = Global> {
map: &'a mut HashMap<K, V, S, A>,
}
@@ -2879,7 +2939,7 @@ pub struct RawEntryBuilderMut<'a, K, V, S, A: Allocator + Clone = Global> {
/// vec.sort_unstable();
/// assert_eq!(vec, [('a', 10), ('b', 20), ('c', 30), ('d', 40), ('e', 50), ('f', 60)]);
/// ```
-pub enum RawEntryMut<'a, K, V, S, A: Allocator + Clone = Global> {
+pub enum RawEntryMut<'a, K, V, S, A: Allocator = Global> {
/// An occupied entry.
///
/// # Examples
@@ -2970,7 +3030,7 @@ pub enum RawEntryMut<'a, K, V, S, A: Allocator + Clone = Global> {
/// assert_eq!(map.get(&"b"), None);
/// assert_eq!(map.len(), 1);
/// ```
-pub struct RawOccupiedEntryMut<'a, K, V, S, A: Allocator + Clone = Global> {
+pub struct RawOccupiedEntryMut<'a, K, V, S, A: Allocator = Global> {
elem: Bucket<(K, V)>,
table: &'a mut RawTable<(K, V), A>,
hash_builder: &'a S,
@@ -2981,7 +3041,7 @@ where
K: Send,
V: Send,
S: Send,
- A: Send + Allocator + Clone,
+ A: Send + Allocator,
{
}
unsafe impl<K, V, S, A> Sync for RawOccupiedEntryMut<'_, K, V, S, A>
@@ -2989,7 +3049,7 @@ where
K: Sync,
V: Sync,
S: Sync,
- A: Sync + Allocator + Clone,
+ A: Sync + Allocator,
{
}
@@ -3041,7 +3101,7 @@ where
/// }
/// assert!(map[&"c"] == 30 && map.len() == 3);
/// ```
-pub struct RawVacantEntryMut<'a, K, V, S, A: Allocator + Clone = Global> {
+pub struct RawVacantEntryMut<'a, K, V, S, A: Allocator = Global> {
table: &'a mut RawTable<(K, V), A>,
hash_builder: &'a S,
}
@@ -3080,11 +3140,11 @@ pub struct RawVacantEntryMut<'a, K, V, S, A: Allocator + Clone = Global> {
/// assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv);
/// }
/// ```
-pub struct RawEntryBuilder<'a, K, V, S, A: Allocator + Clone = Global> {
+pub struct RawEntryBuilder<'a, K, V, S, A: Allocator = Global> {
map: &'a HashMap<K, V, S, A>,
}
-impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilderMut<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> RawEntryBuilderMut<'a, K, V, S, A> {
/// Creates a `RawEntryMut` from the given key.
///
/// # Examples
@@ -3103,10 +3163,9 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilderMut<'a, K, V, S, A> {
pub fn from_key<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S, A>
where
S: BuildHasher,
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
- let hash = make_hash::<K, Q, S>(&self.map.hash_builder, k);
+ let hash = make_hash::<Q, S>(&self.map.hash_builder, k);
self.from_key_hashed_nocheck(hash, k)
}
@@ -3136,14 +3195,13 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilderMut<'a, K, V, S, A> {
#[allow(clippy::wrong_self_convention)]
pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S, A>
where
- K: Borrow<Q>,
- Q: Eq,
+ Q: Equivalent<K>,
{
self.from_hash(hash, equivalent(k))
}
}
-impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilderMut<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> RawEntryBuilderMut<'a, K, V, S, A> {
/// Creates a `RawEntryMut` from the given hash and matching function.
///
/// # Examples
@@ -3194,7 +3252,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilderMut<'a, K, V, S, A> {
}
}
-impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilder<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> RawEntryBuilder<'a, K, V, S, A> {
/// Access an immutable entry by key.
///
/// # Examples
@@ -3211,10 +3269,9 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilder<'a, K, V, S, A> {
pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
where
S: BuildHasher,
- K: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<K>,
{
- let hash = make_hash::<K, Q, S>(&self.map.hash_builder, k);
+ let hash = make_hash::<Q, S>(&self.map.hash_builder, k);
self.from_key_hashed_nocheck(hash, k)
}
@@ -3242,8 +3299,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilder<'a, K, V, S, A> {
#[allow(clippy::wrong_self_convention)]
pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)>
where
- K: Borrow<Q>,
- Q: Eq,
+ Q: Equivalent<K>,
{
self.from_hash(hash, equivalent(k))
}
@@ -3254,7 +3310,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilder<'a, K, V, S, A> {
F: FnMut(&K) -> bool,
{
match self.map.table.get(hash, |(k, _)| is_match(k)) {
- Some(&(ref key, ref value)) => Some((key, value)),
+ Some((key, value)) => Some((key, value)),
None => None,
}
}
@@ -3289,7 +3345,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilder<'a, K, V, S, A> {
}
}
-impl<'a, K, V, S, A: Allocator + Clone> RawEntryMut<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> RawEntryMut<'a, K, V, S, A> {
/// Sets the value of the entry, and returns a RawOccupiedEntryMut.
///
/// # Examples
@@ -3483,7 +3539,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawEntryMut<'a, K, V, S, A> {
}
}
-impl<'a, K, V, S, A: Allocator + Clone> RawOccupiedEntryMut<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> RawOccupiedEntryMut<'a, K, V, S, A> {
/// Gets a reference to the key in the entry.
///
/// # Examples
@@ -3650,7 +3706,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawOccupiedEntryMut<'a, K, V, S, A> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn get_key_value(&self) -> (&K, &V) {
unsafe {
- let &(ref key, ref value) = self.elem.as_ref();
+ let (key, value) = self.elem.as_ref();
(key, value)
}
}
@@ -3822,7 +3878,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawOccupiedEntryMut<'a, K, V, S, A> {
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove_entry(self) -> (K, V) {
- unsafe { self.table.remove(self.elem) }
+ unsafe { self.table.remove(self.elem).0 }
}
/// Provides shared access to the key and owned access to the value of
@@ -3882,7 +3938,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawOccupiedEntryMut<'a, K, V, S, A> {
}
}
-impl<'a, K, V, S, A: Allocator + Clone> RawVacantEntryMut<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> RawVacantEntryMut<'a, K, V, S, A> {
/// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it.
///
@@ -3906,7 +3962,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawVacantEntryMut<'a, K, V, S, A> {
K: Hash,
S: BuildHasher,
{
- let hash = make_insert_hash::<K, S>(self.hash_builder, &key);
+ let hash = make_hash::<K, S>(self.hash_builder, &key);
self.insert_hashed_nocheck(hash, key, value)
}
@@ -3950,7 +4006,7 @@ impl<'a, K, V, S, A: Allocator + Clone> RawVacantEntryMut<'a, K, V, S, A> {
let &mut (ref mut k, ref mut v) = self.table.insert_entry(
hash,
(key, value),
- make_hasher::<K, _, V, S>(self.hash_builder),
+ make_hasher::<_, V, S>(self.hash_builder),
);
(k, v)
}
@@ -4014,11 +4070,11 @@ impl<'a, K, V, S, A: Allocator + Clone> RawVacantEntryMut<'a, K, V, S, A> {
K: Hash,
S: BuildHasher,
{
- let hash = make_insert_hash::<K, S>(self.hash_builder, &key);
+ let hash = make_hash::<K, S>(self.hash_builder, &key);
let elem = self.table.insert(
hash,
(key, value),
- make_hasher::<K, _, V, S>(self.hash_builder),
+ make_hasher::<_, V, S>(self.hash_builder),
);
RawOccupiedEntryMut {
elem,
@@ -4028,13 +4084,13 @@ impl<'a, K, V, S, A: Allocator + Clone> RawVacantEntryMut<'a, K, V, S, A> {
}
}
-impl<K, V, S, A: Allocator + Clone> Debug for RawEntryBuilderMut<'_, K, V, S, A> {
+impl<K, V, S, A: Allocator> Debug for RawEntryBuilderMut<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawEntryBuilder").finish()
}
}
-impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for RawEntryMut<'_, K, V, S, A> {
+impl<K: Debug, V: Debug, S, A: Allocator> Debug for RawEntryMut<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(),
@@ -4043,7 +4099,7 @@ impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for RawEntryMut<'_, K, V
}
}
-impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for RawOccupiedEntryMut<'_, K, V, S, A> {
+impl<K: Debug, V: Debug, S, A: Allocator> Debug for RawOccupiedEntryMut<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawOccupiedEntryMut")
.field("key", self.key())
@@ -4052,13 +4108,13 @@ impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for RawOccupiedEntryMut<
}
}
-impl<K, V, S, A: Allocator + Clone> Debug for RawVacantEntryMut<'_, K, V, S, A> {
+impl<K, V, S, A: Allocator> Debug for RawVacantEntryMut<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawVacantEntryMut").finish()
}
}
-impl<K, V, S, A: Allocator + Clone> Debug for RawEntryBuilder<'_, K, V, S, A> {
+impl<K, V, S, A: Allocator> Debug for RawEntryBuilder<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawEntryBuilder").finish()
}
@@ -4109,7 +4165,7 @@ impl<K, V, S, A: Allocator + Clone> Debug for RawEntryBuilder<'_, K, V, S, A> {
/// ```
pub enum Entry<'a, K, V, S, A = Global>
where
- A: Allocator + Clone,
+ A: Allocator,
{
/// An occupied entry.
///
@@ -4142,7 +4198,7 @@ where
Vacant(VacantEntry<'a, K, V, S, A>),
}
-impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for Entry<'_, K, V, S, A> {
+impl<K: Debug, V: Debug, S, A: Allocator> Debug for Entry<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
@@ -4191,7 +4247,7 @@ impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for Entry<'_, K, V, S, A
/// assert_eq!(map.get(&"c"), None);
/// assert_eq!(map.len(), 2);
/// ```
-pub struct OccupiedEntry<'a, K, V, S, A: Allocator + Clone = Global> {
+pub struct OccupiedEntry<'a, K, V, S = DefaultHashBuilder, A: Allocator = Global> {
hash: u64,
key: Option<K>,
elem: Bucket<(K, V)>,
@@ -4203,7 +4259,7 @@ where
K: Send,
V: Send,
S: Send,
- A: Send + Allocator + Clone,
+ A: Send + Allocator,
{
}
unsafe impl<K, V, S, A> Sync for OccupiedEntry<'_, K, V, S, A>
@@ -4211,11 +4267,11 @@ where
K: Sync,
V: Sync,
S: Sync,
- A: Sync + Allocator + Clone,
+ A: Sync + Allocator,
{
}
-impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for OccupiedEntry<'_, K, V, S, A> {
+impl<K: Debug, V: Debug, S, A: Allocator> Debug for OccupiedEntry<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
@@ -4254,13 +4310,13 @@ impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for OccupiedEntry<'_, K,
/// }
/// assert!(map[&"b"] == 20 && map.len() == 2);
/// ```
-pub struct VacantEntry<'a, K, V, S, A: Allocator + Clone = Global> {
+pub struct VacantEntry<'a, K, V, S = DefaultHashBuilder, A: Allocator = Global> {
hash: u64,
key: K,
table: &'a mut HashMap<K, V, S, A>,
}
-impl<K: Debug, V, S, A: Allocator + Clone> Debug for VacantEntry<'_, K, V, S, A> {
+impl<K: Debug, V, S, A: Allocator> Debug for VacantEntry<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VacantEntry").field(self.key()).finish()
}
@@ -4320,7 +4376,7 @@ impl<K: Debug, V, S, A: Allocator + Clone> Debug for VacantEntry<'_, K, V, S, A>
/// ```
pub enum EntryRef<'a, 'b, K, Q: ?Sized, V, S, A = Global>
where
- A: Allocator + Clone,
+ A: Allocator,
{
/// An occupied entry.
///
@@ -4353,7 +4409,7 @@ where
Vacant(VacantEntryRef<'a, 'b, K, Q, V, S, A>),
}
-impl<K: Borrow<Q>, Q: ?Sized + Debug, V: Debug, S, A: Allocator + Clone> Debug
+impl<K: Borrow<Q>, Q: ?Sized + Debug, V: Debug, S, A: Allocator> Debug
for EntryRef<'_, '_, K, Q, V, S, A>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -4431,7 +4487,7 @@ impl<'a, K: Borrow<Q>, Q: ?Sized> AsRef<Q> for KeyOrRef<'a, K, Q> {
/// assert_eq!(map.get("c"), None);
/// assert_eq!(map.len(), 2);
/// ```
-pub struct OccupiedEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone = Global> {
+pub struct OccupiedEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator = Global> {
hash: u64,
key: Option<KeyOrRef<'b, K, Q>>,
elem: Bucket<(K, V)>,
@@ -4444,7 +4500,7 @@ where
Q: Sync + ?Sized,
V: Send,
S: Send,
- A: Send + Allocator + Clone,
+ A: Send + Allocator,
{
}
unsafe impl<'a, 'b, K, Q, V, S, A> Sync for OccupiedEntryRef<'a, 'b, K, Q, V, S, A>
@@ -4453,16 +4509,16 @@ where
Q: Sync + ?Sized,
V: Sync,
S: Sync,
- A: Sync + Allocator + Clone,
+ A: Sync + Allocator,
{
}
-impl<K: Borrow<Q>, Q: ?Sized + Debug, V: Debug, S, A: Allocator + Clone> Debug
+impl<K: Borrow<Q>, Q: ?Sized + Debug, V: Debug, S, A: Allocator> Debug
for OccupiedEntryRef<'_, '_, K, Q, V, S, A>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedEntryRef")
- .field("key", &self.key())
+ .field("key", &self.key().borrow())
.field("value", &self.get())
.finish()
}
@@ -4498,13 +4554,13 @@ impl<K: Borrow<Q>, Q: ?Sized + Debug, V: Debug, S, A: Allocator + Clone> Debug
/// }
/// assert!(map["b"] == 20 && map.len() == 2);
/// ```
-pub struct VacantEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone = Global> {
+pub struct VacantEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator = Global> {
hash: u64,
key: KeyOrRef<'b, K, Q>,
table: &'a mut HashMap<K, V, S, A>,
}
-impl<K: Borrow<Q>, Q: ?Sized + Debug, V, S, A: Allocator + Clone> Debug
+impl<K: Borrow<Q>, Q: ?Sized + Debug, V, S, A: Allocator> Debug
for VacantEntryRef<'_, '_, K, Q, V, S, A>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -4536,14 +4592,14 @@ impl<K: Borrow<Q>, Q: ?Sized + Debug, V, S, A: Allocator + Clone> Debug
/// }
/// assert_eq!(map[&"a"], 100);
/// ```
-pub struct OccupiedError<'a, K, V, S, A: Allocator + Clone = Global> {
+pub struct OccupiedError<'a, K, V, S, A: Allocator = Global> {
/// The entry in the map that was already occupied.
pub entry: OccupiedEntry<'a, K, V, S, A>,
/// The value which was not inserted, because the entry was already occupied.
pub value: V,
}
-impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for OccupiedError<'_, K, V, S, A> {
+impl<K: Debug, V: Debug, S, A: Allocator> Debug for OccupiedError<'_, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedError")
.field("key", self.entry.key())
@@ -4553,9 +4609,7 @@ impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for OccupiedError<'_, K,
}
}
-impl<'a, K: Debug, V: Debug, S, A: Allocator + Clone> fmt::Display
- for OccupiedError<'a, K, V, S, A>
-{
+impl<'a, K: Debug, V: Debug, S, A: Allocator> fmt::Display for OccupiedError<'a, K, V, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
@@ -4567,7 +4621,7 @@ impl<'a, K: Debug, V: Debug, S, A: Allocator + Clone> fmt::Display
}
}
-impl<'a, K, V, S, A: Allocator + Clone> IntoIterator for &'a HashMap<K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> IntoIterator for &'a HashMap<K, V, S, A> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
@@ -4599,7 +4653,7 @@ impl<'a, K, V, S, A: Allocator + Clone> IntoIterator for &'a HashMap<K, V, S, A>
}
}
-impl<'a, K, V, S, A: Allocator + Clone> IntoIterator for &'a mut HashMap<K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> IntoIterator for &'a mut HashMap<K, V, S, A> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
@@ -4636,7 +4690,7 @@ impl<'a, K, V, S, A: Allocator + Clone> IntoIterator for &'a mut HashMap<K, V, S
}
}
-impl<K, V, S, A: Allocator + Clone> IntoIterator for HashMap<K, V, S, A> {
+impl<K, V, S, A: Allocator> IntoIterator for HashMap<K, V, S, A> {
type Item = (K, V);
type IntoIter = IntoIter<K, V, A>;
@@ -4684,6 +4738,17 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, |acc, x| unsafe {
+ let (k, v) = x.as_ref();
+ f(acc, (k, v))
+ })
+ }
}
impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
#[cfg_attr(feature = "inline-more", inline)]
@@ -4712,6 +4777,17 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, |acc, x| unsafe {
+ let (k, v) = x.as_mut();
+ f(acc, (k, v))
+ })
+ }
}
impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
#[cfg_attr(feature = "inline-more", inline)]
@@ -4731,7 +4807,7 @@ where
}
}
-impl<K, V, A: Allocator + Clone> Iterator for IntoIter<K, V, A> {
+impl<K, V, A: Allocator> Iterator for IntoIter<K, V, A> {
type Item = (K, V);
#[cfg_attr(feature = "inline-more", inline)]
@@ -4742,16 +4818,24 @@ impl<K, V, A: Allocator + Clone> Iterator for IntoIter<K, V, A> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, f)
+ }
}
-impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoIter<K, V, A> {
+impl<K, V, A: Allocator> ExactSizeIterator for IntoIter<K, V, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn len(&self) -> usize {
self.inner.len()
}
}
-impl<K, V, A: Allocator + Clone> FusedIterator for IntoIter<K, V, A> {}
+impl<K, V, A: Allocator> FusedIterator for IntoIter<K, V, A> {}
-impl<K: Debug, V: Debug, A: Allocator + Clone> fmt::Debug for IntoIter<K, V, A> {
+impl<K: Debug, V: Debug, A: Allocator> fmt::Debug for IntoIter<K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
@@ -4772,6 +4856,14 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, |acc, (k, _)| f(acc, k))
+ }
}
impl<K, V> ExactSizeIterator for Keys<'_, K, V> {
#[cfg_attr(feature = "inline-more", inline)]
@@ -4796,6 +4888,14 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, |acc, (_, v)| f(acc, v))
+ }
}
impl<K, V> ExactSizeIterator for Values<'_, K, V> {
#[cfg_attr(feature = "inline-more", inline)]
@@ -4820,6 +4920,14 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, |acc, (_, v)| f(acc, v))
+ }
}
impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
#[cfg_attr(feature = "inline-more", inline)]
@@ -4837,7 +4945,7 @@ impl<K, V: Debug> fmt::Debug for ValuesMut<'_, K, V> {
}
}
-impl<'a, K, V, A: Allocator + Clone> Iterator for Drain<'a, K, V, A> {
+impl<'a, K, V, A: Allocator> Iterator for Drain<'a, K, V, A> {
type Item = (K, V);
#[cfg_attr(feature = "inline-more", inline)]
@@ -4848,27 +4956,35 @@ impl<'a, K, V, A: Allocator + Clone> Iterator for Drain<'a, K, V, A> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, f)
+ }
}
-impl<K, V, A: Allocator + Clone> ExactSizeIterator for Drain<'_, K, V, A> {
+impl<K, V, A: Allocator> ExactSizeIterator for Drain<'_, K, V, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn len(&self) -> usize {
self.inner.len()
}
}
-impl<K, V, A: Allocator + Clone> FusedIterator for Drain<'_, K, V, A> {}
+impl<K, V, A: Allocator> FusedIterator for Drain<'_, K, V, A> {}
impl<K, V, A> fmt::Debug for Drain<'_, K, V, A>
where
K: fmt::Debug,
V: fmt::Debug,
- A: Allocator + Clone,
+ A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
-impl<'a, K, V, S, A: Allocator + Clone> Entry<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> Entry<'a, K, V, S, A> {
/// Sets the value of the entry, and returns an OccupiedEntry.
///
/// # Examples
@@ -5115,7 +5231,7 @@ impl<'a, K, V, S, A: Allocator + Clone> Entry<'a, K, V, S, A> {
}
}
-impl<'a, K, V: Default, S, A: Allocator + Clone> Entry<'a, K, V, S, A> {
+impl<'a, K, V: Default, S, A: Allocator> Entry<'a, K, V, S, A> {
/// Ensures a value is in the entry by inserting the default value if empty,
/// and returns a mutable reference to the value in the entry.
///
@@ -5148,7 +5264,7 @@ impl<'a, K, V: Default, S, A: Allocator + Clone> Entry<'a, K, V, S, A> {
}
}
-impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
/// Gets a reference to the key in the entry.
///
/// # Examples
@@ -5183,7 +5299,6 @@ impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> {
/// assert!(map.is_empty() && map.capacity() == 0);
///
/// map.entry("poneyland").or_insert(12);
- /// let capacity_before_remove = map.capacity();
///
/// if let Entry::Occupied(o) = map.entry("poneyland") {
/// // We delete the entry from the map.
@@ -5191,12 +5306,12 @@ impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> {
/// }
///
/// assert_eq!(map.contains_key("poneyland"), false);
- /// // Now map hold none elements but capacity is equal to the old one
- /// assert!(map.len() == 0 && map.capacity() == capacity_before_remove);
+ /// // Now map hold none elements
+ /// assert!(map.is_empty());
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove_entry(self) -> (K, V) {
- unsafe { self.table.table.remove(self.elem) }
+ unsafe { self.table.table.remove(self.elem).0 }
}
/// Gets a reference to the value in the entry.
@@ -5319,15 +5434,14 @@ impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> {
/// assert!(map.is_empty() && map.capacity() == 0);
///
/// map.entry("poneyland").or_insert(12);
- /// let capacity_before_remove = map.capacity();
///
/// if let Entry::Occupied(o) = map.entry("poneyland") {
/// assert_eq!(o.remove(), 12);
/// }
///
/// assert_eq!(map.contains_key("poneyland"), false);
- /// // Now map hold none elements but capacity is equal to the old one
- /// assert!(map.len() == 0 && map.capacity() == capacity_before_remove);
+ /// // Now map hold none elements
+ /// assert!(map.is_empty());
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove(self) -> V {
@@ -5505,7 +5619,7 @@ impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> {
}
}
-impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> {
+impl<'a, K, V, S, A: Allocator> VacantEntry<'a, K, V, S, A> {
/// Gets a reference to the key that would be used when inserting a value
/// through the `VacantEntry`.
///
@@ -5567,7 +5681,7 @@ impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> {
let entry = table.insert_entry(
self.hash,
(self.key, value),
- make_hasher::<K, _, V, S>(&self.table.hash_builder),
+ make_hasher::<_, V, S>(&self.table.hash_builder),
);
&mut entry.1
}
@@ -5581,7 +5695,7 @@ impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> {
let elem = self.table.table.insert(
self.hash,
(self.key, value),
- make_hasher::<K, _, V, S>(&self.table.hash_builder),
+ make_hasher::<_, V, S>(&self.table.hash_builder),
);
OccupiedEntry {
hash: self.hash,
@@ -5592,7 +5706,7 @@ impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> {
}
}
-impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V, S, A> {
+impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> EntryRef<'a, 'b, K, Q, V, S, A> {
/// Sets the value of the entry, and returns an OccupiedEntryRef.
///
/// # Examples
@@ -5682,10 +5796,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V,
/// Ensures a value is in the entry by inserting, if empty, the result of the default function.
/// This method allows for generating key-derived values for insertion by providing the default
- /// function a reference to the key that was moved during the `.entry_ref(key)` method call.
- ///
- /// The reference to the moved key is provided so that cloning or copying the key is
- /// unnecessary, unlike with `.or_insert_with(|| ... )`.
+ /// function an access to the borrower form of the key.
///
/// # Examples
///
@@ -5737,7 +5848,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V,
K: Borrow<Q>,
{
match *self {
- EntryRef::Occupied(ref entry) => entry.key(),
+ EntryRef::Occupied(ref entry) => entry.key().borrow(),
EntryRef::Vacant(ref entry) => entry.key(),
}
}
@@ -5833,8 +5944,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V,
#[cfg_attr(feature = "inline-more", inline)]
pub fn and_replace_entry_with<F>(self, f: F) -> Self
where
- F: FnOnce(&Q, V) -> Option<V>,
- K: Borrow<Q>,
+ F: FnOnce(&K, V) -> Option<V>,
{
match self {
EntryRef::Occupied(entry) => entry.replace_entry_with(f),
@@ -5843,7 +5953,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V,
}
}
-impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V, S, A> {
+impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator> EntryRef<'a, 'b, K, Q, V, S, A> {
/// Ensures a value is in the entry by inserting the default value if empty,
/// and returns a mutable reference to the value in the entry.
///
@@ -5876,7 +5986,7 @@ impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator + Clone> EntryRef<'a, 'b,
}
}
-impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> {
+impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> {
/// Gets a reference to the key in the entry.
///
/// # Examples
@@ -5893,11 +6003,8 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
/// }
/// ```
#[cfg_attr(feature = "inline-more", inline)]
- pub fn key(&self) -> &Q
- where
- K: Borrow<Q>,
- {
- unsafe { &self.elem.as_ref().0 }.borrow()
+ pub fn key(&self) -> &K {
+ unsafe { &self.elem.as_ref().0 }
}
/// Take the ownership of the key and value from the map.
@@ -5914,7 +6021,6 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
/// assert!(map.is_empty() && map.capacity() == 0);
///
/// map.entry_ref("poneyland").or_insert(12);
- /// let capacity_before_remove = map.capacity();
///
/// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") {
/// // We delete the entry from the map.
@@ -5923,11 +6029,11 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
///
/// assert_eq!(map.contains_key("poneyland"), false);
/// // Now map hold none elements but capacity is equal to the old one
- /// assert!(map.len() == 0 && map.capacity() == capacity_before_remove);
+ /// assert!(map.is_empty());
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove_entry(self) -> (K, V) {
- unsafe { self.table.table.remove(self.elem) }
+ unsafe { self.table.table.remove(self.elem).0 }
}
/// Gets a reference to the value in the entry.
@@ -6048,7 +6154,6 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
/// assert!(map.is_empty() && map.capacity() == 0);
///
/// map.entry_ref("poneyland").or_insert(12);
- /// let capacity_before_remove = map.capacity();
///
/// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") {
/// assert_eq!(o.remove(), 12);
@@ -6056,7 +6161,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
///
/// assert_eq!(map.contains_key("poneyland"), false);
/// // Now map hold none elements but capacity is equal to the old one
- /// assert!(map.len() == 0 && map.capacity() == capacity_before_remove);
+ /// assert!(map.is_empty());
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove(self) -> V {
@@ -6068,7 +6173,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
///
/// # Panics
///
- /// Will panic if this OccupiedEntry was created through [`EntryRef::insert`].
+ /// Will panic if this OccupiedEntryRef was created through [`EntryRef::insert`].
///
/// # Examples
///
@@ -6110,7 +6215,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
///
/// # Panics
///
- /// Will panic if this OccupiedEntry was created through [`Entry::insert`].
+ /// Will panic if this OccupiedEntryRef was created through [`EntryRef::insert`].
///
/// # Examples
///
@@ -6138,7 +6243,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
/// fn reclaim_memory(map: &mut HashMap<Rc<str>, usize>, keys: &[Rc<str>]) {
/// for key in keys {
/// if let EntryRef::Occupied(entry) = map.entry_ref(key.as_ref()) {
- /// /// Replaces the entry's key with our version of it in `keys`.
+ /// // Replaces the entry's key with our version of it in `keys`.
/// entry.replace_key();
/// }
/// }
@@ -6204,8 +6309,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
#[cfg_attr(feature = "inline-more", inline)]
pub fn replace_entry_with<F>(self, f: F) -> EntryRef<'a, 'b, K, Q, V, S, A>
where
- F: FnOnce(&Q, V) -> Option<V>,
- K: Borrow<Q>,
+ F: FnOnce(&K, V) -> Option<V>,
{
unsafe {
let mut spare_key = None;
@@ -6213,7 +6317,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
self.table
.table
.replace_bucket_with(self.elem.clone(), |(key, value)| {
- if let Some(new_value) = f(key.borrow(), value) {
+ if let Some(new_value) = f(&key, value) {
Some((key, new_value))
} else {
spare_key = Some(KeyOrRef::Owned(key));
@@ -6234,7 +6338,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b,
}
}
-impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> VacantEntryRef<'a, 'b, K, Q, V, S, A> {
+impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S, A> {
/// Gets a reference to the key that would be used when inserting a value
/// through the `VacantEntryRef`.
///
@@ -6305,7 +6409,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> VacantEntryRef<'a, 'b, K,
let entry = table.insert_entry(
self.hash,
(self.key.into_owned(), value),
- make_hasher::<K, _, V, S>(&self.table.hash_builder),
+ make_hasher::<_, V, S>(&self.table.hash_builder),
);
&mut entry.1
}
@@ -6319,7 +6423,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> VacantEntryRef<'a, 'b, K,
let elem = self.table.table.insert(
self.hash,
(self.key.into_owned(), value),
- make_hasher::<K, _, V, S>(&self.table.hash_builder),
+ make_hasher::<_, V, S>(&self.table.hash_builder),
);
OccupiedEntryRef {
hash: self.hash,
@@ -6334,7 +6438,7 @@ impl<K, V, S, A> FromIterator<(K, V)> for HashMap<K, V, S, A>
where
K: Eq + Hash,
S: BuildHasher + Default,
- A: Default + Allocator + Clone,
+ A: Default + Allocator,
{
#[cfg_attr(feature = "inline-more", inline)]
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
@@ -6354,7 +6458,7 @@ impl<K, V, S, A> Extend<(K, V)> for HashMap<K, V, S, A>
where
K: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
/// Inserts all new key-values from the iterator to existing `HashMap<K, V, S, A>`.
/// Replace values with existing keys with new values returned from the iterator.
@@ -6438,7 +6542,7 @@ where
K: Eq + Hash + Copy,
V: Copy,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
/// Inserts all new key-values from the iterator to existing `HashMap<K, V, S, A>`.
/// Replace values with existing keys with new values returned from the iterator.
@@ -6455,17 +6559,17 @@ where
/// map.insert(1, 100);
///
/// let arr = [(1, 1), (2, 2)];
- /// let some_iter = arr.iter().map(|&(k, v)| (k, v));
+ /// let some_iter = arr.iter().map(|(k, v)| (k, v));
/// map.extend(some_iter);
/// // Replace values with existing keys with new values returned from the iterator.
/// // So that the map.get(&1) doesn't return Some(&100).
/// assert_eq!(map.get(&1), Some(&1));
///
/// let some_vec: Vec<_> = vec![(3, 3), (4, 4)];
- /// map.extend(some_vec.iter().map(|&(k, v)| (k, v)));
+ /// map.extend(some_vec.iter().map(|(k, v)| (k, v)));
///
/// let some_arr = [(5, 5), (6, 6)];
- /// map.extend(some_arr.iter().map(|&(k, v)| (k, v)));
+ /// map.extend(some_arr.iter().map(|(k, v)| (k, v)));
///
/// // You can also extend from another HashMap
/// let mut new_map = HashMap::new();
@@ -6503,7 +6607,7 @@ where
K: Eq + Hash + Copy,
V: Copy,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
/// Inserts all new key-values from the iterator to existing `HashMap<K, V, S, A>`.
/// Replace values with existing keys with new values returned from the iterator.
@@ -6570,12 +6674,12 @@ fn assert_covariance() {
fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> {
v
}
- fn into_iter_key<'new, A: Allocator + Clone>(
+ fn into_iter_key<'new, A: Allocator>(
v: IntoIter<&'static str, u8, A>,
) -> IntoIter<&'new str, u8, A> {
v
}
- fn into_iter_val<'new, A: Allocator + Clone>(
+ fn into_iter_val<'new, A: Allocator>(
v: IntoIter<u8, &'static str, A>,
) -> IntoIter<u8, &'new str, A> {
v
@@ -6605,6 +6709,12 @@ mod test_map {
use super::Entry::{Occupied, Vacant};
use super::EntryRef;
use super::{HashMap, RawEntryMut};
+ use alloc::string::{String, ToString};
+ use alloc::sync::Arc;
+ use allocator_api2::alloc::{AllocError, Allocator, Global};
+ use core::alloc::Layout;
+ use core::ptr::NonNull;
+ use core::sync::atomic::{AtomicI8, Ordering};
use rand::{rngs::SmallRng, Rng, SeedableRng};
use std::borrow::ToOwned;
use std::cell::RefCell;
@@ -6695,7 +6805,7 @@ mod test_map {
assert_eq!(m2.len(), 2);
}
- thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = RefCell::new(Vec::new()) }
+ thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = const { RefCell::new(Vec::new()) } }
#[derive(Hash, PartialEq, Eq)]
struct Droppable {
@@ -6827,7 +6937,6 @@ mod test_map {
}
});
- #[allow(clippy::let_underscore_drop)] // kind-of a false positive
for _ in half.by_ref() {}
DROP_VECTOR.with(|v| {
@@ -7155,10 +7264,10 @@ mod test_map {
map.insert(1, 2);
map.insert(3, 4);
- let map_str = format!("{:?}", map);
+ let map_str = format!("{map:?}");
assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
- assert_eq!(format!("{:?}", empty), "{}");
+ assert_eq!(format!("{empty:?}"), "{}");
}
#[test]
@@ -7474,7 +7583,7 @@ mod test_map {
// Test for #19292
fn check(m: &HashMap<i32, ()>) {
for k in m.keys() {
- assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
+ assert!(m.contains_key(k), "{k} is in keys() but not in the map?");
}
}
@@ -7510,7 +7619,7 @@ mod test_map {
// Test for #19292
fn check(m: &HashMap<std::string::String, ()>) {
for k in m.keys() {
- assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
+ assert!(m.contains_key(k), "{k} is in keys() but not in the map?");
}
}
@@ -7559,6 +7668,7 @@ mod test_map {
}
#[test]
+ #[allow(clippy::needless_borrow)]
fn test_extend_ref_kv_tuple() {
use std::ops::AddAssign;
let mut a = HashMap::new();
@@ -7580,7 +7690,7 @@ mod test_map {
let vec: Vec<_> = (100..200).map(|i| (i, i)).collect();
a.extend(iter);
a.extend(&vec);
- a.extend(&create_arr::<i32, 100>(200, 1));
+ a.extend(create_arr::<i32, 100>(200, 1));
assert_eq!(a.len(), 300);
@@ -7981,7 +8091,7 @@ mod test_map {
// Test for #19292
fn check(m: &HashMap<i32, ()>) {
for k in m.keys() {
- assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
+ assert!(m.contains_key(k), "{k} is in keys() but not in the map?");
}
}
@@ -8011,7 +8121,7 @@ mod test_map {
// Test for #19292
fn check(m: &HashMap<std::string::String, ()>) {
for k in m.keys() {
- assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
+ assert!(m.contains_key(k), "{k} is in keys() but not in the map?");
}
}
@@ -8049,10 +8159,10 @@ mod test_map {
}
#[test]
- fn test_drain_filter() {
+ fn test_extract_if() {
{
let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect();
- let drained = map.drain_filter(|&k, _| k % 2 == 0);
+ let drained = map.extract_if(|&k, _| k % 2 == 0);
let mut out = drained.collect::<Vec<_>>();
out.sort_unstable();
assert_eq!(vec![(0, 0), (2, 20), (4, 40), (6, 60)], out);
@@ -8060,7 +8170,7 @@ mod test_map {
}
{
let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect();
- drop(map.drain_filter(|&k, _| k % 2 == 0));
+ map.extract_if(|&k, _| k % 2 == 0).for_each(drop);
assert_eq!(map.len(), 4);
}
}
@@ -8070,27 +8180,32 @@ mod test_map {
fn test_try_reserve() {
use crate::TryReserveError::{AllocError, CapacityOverflow};
- const MAX_USIZE: usize = usize::MAX;
+ const MAX_ISIZE: usize = isize::MAX as usize;
let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
- if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
+ if let Err(CapacityOverflow) = empty_bytes.try_reserve(usize::MAX) {
} else {
panic!("usize::MAX should trigger an overflow!");
}
- if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 16) {
+ if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_ISIZE) {
+ } else {
+ panic!("isize::MAX should trigger an overflow!");
+ }
+
+ if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 5) {
} else {
// This may succeed if there is enough free memory. Attempt to
// allocate a few more hashmaps to ensure the allocation will fail.
let mut empty_bytes2: HashMap<u8, u8> = HashMap::new();
- let _ = empty_bytes2.try_reserve(MAX_USIZE / 16);
+ let _ = empty_bytes2.try_reserve(MAX_ISIZE / 5);
let mut empty_bytes3: HashMap<u8, u8> = HashMap::new();
- let _ = empty_bytes3.try_reserve(MAX_USIZE / 16);
+ let _ = empty_bytes3.try_reserve(MAX_ISIZE / 5);
let mut empty_bytes4: HashMap<u8, u8> = HashMap::new();
- if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_USIZE / 16) {
+ if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_ISIZE / 5) {
} else {
- panic!("usize::MAX / 8 should trigger an OOM!");
+ panic!("isize::MAX / 5 should trigger an OOM!");
}
}
}
@@ -8104,7 +8219,7 @@ mod test_map {
let mut map: HashMap<_, _> = xs.iter().copied().collect();
let compute_hash = |map: &HashMap<i32, i32>, k: i32| -> u64 {
- super::make_insert_hash::<i32, _>(map.hasher(), &k)
+ super::make_hash::<i32, _>(map.hasher(), &k)
};
// Existing key (insert)
@@ -8266,21 +8381,21 @@ mod test_map {
loop {
// occasionally remove some elements
if i < n && rng.gen_bool(0.1) {
- let hash_value = super::make_insert_hash(&hash_builder, &i);
+ let hash_value = super::make_hash(&hash_builder, &i);
unsafe {
let e = map.table.find(hash_value, |q| q.0.eq(&i));
if let Some(e) = e {
it.reflect_remove(&e);
- let t = map.table.remove(e);
+ let t = map.table.remove(e).0;
removed.push(t);
left -= 1;
} else {
- assert!(removed.contains(&(i, 2 * i)), "{} not in {:?}", i, removed);
+ assert!(removed.contains(&(i, 2 * i)), "{i} not in {removed:?}");
let e = map.table.insert(
hash_value,
(i, 2 * i),
- super::make_hasher::<usize, _, usize, _>(&hash_builder),
+ super::make_hasher::<_, usize, _>(&hash_builder),
);
it.reflect_insert(&e);
if let Some(p) = removed.iter().position(|e| e == &(i, 2 * i)) {
@@ -8405,4 +8520,441 @@ mod test_map {
map2.clone_from(&map1);
}
+
+ #[test]
+ #[should_panic = "panic in clone"]
+ fn test_clone_from_memory_leaks() {
+ use alloc::vec::Vec;
+
+ struct CheckedClone {
+ panic_in_clone: bool,
+ need_drop: Vec<i32>,
+ }
+ impl Clone for CheckedClone {
+ fn clone(&self) -> Self {
+ if self.panic_in_clone {
+ panic!("panic in clone")
+ }
+ Self {
+ panic_in_clone: self.panic_in_clone,
+ need_drop: self.need_drop.clone(),
+ }
+ }
+ }
+ let mut map1 = HashMap::new();
+ map1.insert(
+ 1,
+ CheckedClone {
+ panic_in_clone: false,
+ need_drop: vec![0, 1, 2],
+ },
+ );
+ map1.insert(
+ 2,
+ CheckedClone {
+ panic_in_clone: false,
+ need_drop: vec![3, 4, 5],
+ },
+ );
+ map1.insert(
+ 3,
+ CheckedClone {
+ panic_in_clone: true,
+ need_drop: vec![6, 7, 8],
+ },
+ );
+ let _map2 = map1.clone();
+ }
+
+ struct MyAllocInner {
+ drop_count: Arc<AtomicI8>,
+ }
+
+ #[derive(Clone)]
+ struct MyAlloc {
+ _inner: Arc<MyAllocInner>,
+ }
+
+ impl MyAlloc {
+ fn new(drop_count: Arc<AtomicI8>) -> Self {
+ MyAlloc {
+ _inner: Arc::new(MyAllocInner { drop_count }),
+ }
+ }
+ }
+
+ impl Drop for MyAllocInner {
+ fn drop(&mut self) {
+ println!("MyAlloc freed.");
+ self.drop_count.fetch_sub(1, Ordering::SeqCst);
+ }
+ }
+
+ unsafe impl Allocator for MyAlloc {
+ fn allocate(&self, layout: Layout) -> std::result::Result<NonNull<[u8]>, AllocError> {
+ let g = Global;
+ g.allocate(layout)
+ }
+
+ unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+ let g = Global;
+ g.deallocate(ptr, layout)
+ }
+ }
+
+ #[test]
+ fn test_hashmap_into_iter_bug() {
+ let dropped: Arc<AtomicI8> = Arc::new(AtomicI8::new(1));
+
+ {
+ let mut map = HashMap::with_capacity_in(10, MyAlloc::new(dropped.clone()));
+ for i in 0..10 {
+ map.entry(i).or_insert_with(|| "i".to_string());
+ }
+
+ for (k, v) in map {
+ println!("{}, {}", k, v);
+ }
+ }
+
+ // All allocator clones should already be dropped.
+ assert_eq!(dropped.load(Ordering::SeqCst), 0);
+ }
+
+ #[derive(Debug)]
+ struct CheckedCloneDrop<T> {
+ panic_in_clone: bool,
+ panic_in_drop: bool,
+ dropped: bool,
+ data: T,
+ }
+
+ impl<T> CheckedCloneDrop<T> {
+ fn new(panic_in_clone: bool, panic_in_drop: bool, data: T) -> Self {
+ CheckedCloneDrop {
+ panic_in_clone,
+ panic_in_drop,
+ dropped: false,
+ data,
+ }
+ }
+ }
+
+ impl<T: Clone> Clone for CheckedCloneDrop<T> {
+ fn clone(&self) -> Self {
+ if self.panic_in_clone {
+ panic!("panic in clone")
+ }
+ Self {
+ panic_in_clone: self.panic_in_clone,
+ panic_in_drop: self.panic_in_drop,
+ dropped: self.dropped,
+ data: self.data.clone(),
+ }
+ }
+ }
+
+ impl<T> Drop for CheckedCloneDrop<T> {
+ fn drop(&mut self) {
+ if self.panic_in_drop {
+ self.dropped = true;
+ panic!("panic in drop");
+ }
+ if self.dropped {
+ panic!("double drop");
+ }
+ self.dropped = true;
+ }
+ }
+
+ /// Return hashmap with predefined distribution of elements.
+ /// All elements will be located in the same order as elements
+ /// returned by iterator.
+ ///
+ /// This function does not panic, but returns an error as a `String`
+ /// to distinguish between a test panic and an error in the input data.
+ fn get_test_map<I, T, A>(
+ iter: I,
+ mut fun: impl FnMut(u64) -> T,
+ alloc: A,
+ ) -> Result<HashMap<u64, CheckedCloneDrop<T>, DefaultHashBuilder, A>, String>
+ where
+ I: Iterator<Item = (bool, bool)> + Clone + ExactSizeIterator,
+ A: Allocator,
+ T: PartialEq + core::fmt::Debug,
+ {
+ use crate::scopeguard::guard;
+
+ let mut map: HashMap<u64, CheckedCloneDrop<T>, _, A> =
+ HashMap::with_capacity_in(iter.size_hint().0, alloc);
+ {
+ let mut guard = guard(&mut map, |map| {
+ for (_, value) in map.iter_mut() {
+ value.panic_in_drop = false
+ }
+ });
+
+ let mut count = 0;
+ // Hash and Key must be equal to each other for controlling the elements placement.
+ for (panic_in_clone, panic_in_drop) in iter.clone() {
+ if core::mem::needs_drop::<T>() && panic_in_drop {
+ return Err(String::from(
+ "panic_in_drop can be set with a type that doesn't need to be dropped",
+ ));
+ }
+ guard.table.insert(
+ count,
+ (
+ count,
+ CheckedCloneDrop::new(panic_in_clone, panic_in_drop, fun(count)),
+ ),
+ |(k, _)| *k,
+ );
+ count += 1;
+ }
+
+ // Let's check that all elements are located as we wanted
+ let mut check_count = 0;
+ for ((key, value), (panic_in_clone, panic_in_drop)) in guard.iter().zip(iter) {
+ if *key != check_count {
+ return Err(format!(
+ "key != check_count,\nkey: `{}`,\ncheck_count: `{}`",
+ key, check_count
+ ));
+ }
+ if value.dropped
+ || value.panic_in_clone != panic_in_clone
+ || value.panic_in_drop != panic_in_drop
+ || value.data != fun(check_count)
+ {
+ return Err(format!(
+ "Value is not equal to expected,\nvalue: `{:?}`,\nexpected: \
+ `CheckedCloneDrop {{ panic_in_clone: {}, panic_in_drop: {}, dropped: {}, data: {:?} }}`",
+ value, panic_in_clone, panic_in_drop, false, fun(check_count)
+ ));
+ }
+ check_count += 1;
+ }
+
+ if guard.len() != check_count as usize {
+ return Err(format!(
+ "map.len() != check_count,\nmap.len(): `{}`,\ncheck_count: `{}`",
+ guard.len(),
+ check_count
+ ));
+ }
+
+ if count != check_count {
+ return Err(format!(
+ "count != check_count,\ncount: `{}`,\ncheck_count: `{}`",
+ count, check_count
+ ));
+ }
+ core::mem::forget(guard);
+ }
+ Ok(map)
+ }
+
+ const DISARMED: bool = false;
+ const ARMED: bool = true;
+
+ const ARMED_FLAGS: [bool; 8] = [
+ DISARMED, DISARMED, DISARMED, ARMED, DISARMED, DISARMED, DISARMED, DISARMED,
+ ];
+
+ const DISARMED_FLAGS: [bool; 8] = [
+ DISARMED, DISARMED, DISARMED, DISARMED, DISARMED, DISARMED, DISARMED, DISARMED,
+ ];
+
+ #[test]
+ #[should_panic = "panic in clone"]
+ fn test_clone_memory_leaks_and_double_drop_one() {
+ let dropped: Arc<AtomicI8> = Arc::new(AtomicI8::new(2));
+
+ {
+ assert_eq!(ARMED_FLAGS.len(), DISARMED_FLAGS.len());
+
+ let map: HashMap<u64, CheckedCloneDrop<Vec<u64>>, DefaultHashBuilder, MyAlloc> =
+ match get_test_map(
+ ARMED_FLAGS.into_iter().zip(DISARMED_FLAGS),
+ |n| vec![n],
+ MyAlloc::new(dropped.clone()),
+ ) {
+ Ok(map) => map,
+ Err(msg) => panic!("{msg}"),
+ };
+
+ // Clone should normally clone a few elements, and then (when the
+ // clone function panics), deallocate both its own memory, memory
+ // of `dropped: Arc<AtomicI8>` and the memory of already cloned
+ // elements (Vec<i32> memory inside CheckedCloneDrop).
+ let _map2 = map.clone();
+ }
+ }
+
+ #[test]
+ #[should_panic = "panic in drop"]
+ fn test_clone_memory_leaks_and_double_drop_two() {
+ let dropped: Arc<AtomicI8> = Arc::new(AtomicI8::new(2));
+
+ {
+ assert_eq!(ARMED_FLAGS.len(), DISARMED_FLAGS.len());
+
+ let map: HashMap<u64, CheckedCloneDrop<u64>, DefaultHashBuilder, _> = match get_test_map(
+ DISARMED_FLAGS.into_iter().zip(DISARMED_FLAGS),
+ |n| n,
+ MyAlloc::new(dropped.clone()),
+ ) {
+ Ok(map) => map,
+ Err(msg) => panic!("{msg}"),
+ };
+
+ let mut map2 = match get_test_map(
+ DISARMED_FLAGS.into_iter().zip(ARMED_FLAGS),
+ |n| n,
+ MyAlloc::new(dropped.clone()),
+ ) {
+ Ok(map) => map,
+ Err(msg) => panic!("{msg}"),
+ };
+
+ // The `clone_from` should try to drop the elements of `map2` without
+ // double drop and leaking the allocator. Elements that have not been
+ // dropped leak their memory.
+ map2.clone_from(&map);
+ }
+ }
+
+ /// We check that we have a working table if the clone operation from another
+ /// thread ended in a panic (when buckets of maps are equal to each other).
+ #[test]
+ fn test_catch_panic_clone_from_when_len_is_equal() {
+ use std::thread;
+
+ let dropped: Arc<AtomicI8> = Arc::new(AtomicI8::new(2));
+
+ {
+ assert_eq!(ARMED_FLAGS.len(), DISARMED_FLAGS.len());
+
+ let mut map = match get_test_map(
+ DISARMED_FLAGS.into_iter().zip(DISARMED_FLAGS),
+ |n| vec![n],
+ MyAlloc::new(dropped.clone()),
+ ) {
+ Ok(map) => map,
+ Err(msg) => panic!("{msg}"),
+ };
+
+ thread::scope(|s| {
+ let result: thread::ScopedJoinHandle<'_, String> = s.spawn(|| {
+ let scope_map =
+ match get_test_map(ARMED_FLAGS.into_iter().zip(DISARMED_FLAGS), |n| vec![n * 2], MyAlloc::new(dropped.clone())) {
+ Ok(map) => map,
+ Err(msg) => return msg,
+ };
+ if map.table.buckets() != scope_map.table.buckets() {
+ return format!(
+ "map.table.buckets() != scope_map.table.buckets(),\nleft: `{}`,\nright: `{}`",
+ map.table.buckets(), scope_map.table.buckets()
+ );
+ }
+ map.clone_from(&scope_map);
+ "We must fail the cloning!!!".to_owned()
+ });
+ if let Ok(msg) = result.join() {
+ panic!("{msg}")
+ }
+ });
+
+ // Let's check that all iterators work fine and do not return elements
+ // (especially `RawIterRange`, which does not depend on the number of
+ // elements in the table, but looks directly at the control bytes)
+ //
+ // SAFETY: We know for sure that `RawTable` will outlive
+ // the returned `RawIter / RawIterRange` iterator.
+ assert_eq!(map.len(), 0);
+ assert_eq!(map.iter().count(), 0);
+ assert_eq!(unsafe { map.table.iter().count() }, 0);
+ assert_eq!(unsafe { map.table.iter().iter.count() }, 0);
+
+ for idx in 0..map.table.buckets() {
+ let idx = idx as u64;
+ assert!(
+ map.table.find(idx, |(k, _)| *k == idx).is_none(),
+ "Index: {idx}"
+ );
+ }
+ }
+
+ // All allocator clones should already be dropped.
+ assert_eq!(dropped.load(Ordering::SeqCst), 0);
+ }
+
+ /// We check that we have a working table if the clone operation from another
+ /// thread ended in a panic (when buckets of maps are not equal to each other).
+ #[test]
+ fn test_catch_panic_clone_from_when_len_is_not_equal() {
+ use std::thread;
+
+ let dropped: Arc<AtomicI8> = Arc::new(AtomicI8::new(2));
+
+ {
+ assert_eq!(ARMED_FLAGS.len(), DISARMED_FLAGS.len());
+
+ let mut map = match get_test_map(
+ [DISARMED].into_iter().zip([DISARMED]),
+ |n| vec![n],
+ MyAlloc::new(dropped.clone()),
+ ) {
+ Ok(map) => map,
+ Err(msg) => panic!("{msg}"),
+ };
+
+ thread::scope(|s| {
+ let result: thread::ScopedJoinHandle<'_, String> = s.spawn(|| {
+ let scope_map = match get_test_map(
+ ARMED_FLAGS.into_iter().zip(DISARMED_FLAGS),
+ |n| vec![n * 2],
+ MyAlloc::new(dropped.clone()),
+ ) {
+ Ok(map) => map,
+ Err(msg) => return msg,
+ };
+ if map.table.buckets() == scope_map.table.buckets() {
+ return format!(
+ "map.table.buckets() == scope_map.table.buckets(): `{}`",
+ map.table.buckets()
+ );
+ }
+ map.clone_from(&scope_map);
+ "We must fail the cloning!!!".to_owned()
+ });
+ if let Ok(msg) = result.join() {
+ panic!("{msg}")
+ }
+ });
+
+ // Let's check that all iterators work fine and do not return elements
+ // (especially `RawIterRange`, which does not depend on the number of
+ // elements in the table, but looks directly at the control bytes)
+ //
+ // SAFETY: We know for sure that `RawTable` will outlive
+ // the returned `RawIter / RawIterRange` iterator.
+ assert_eq!(map.len(), 0);
+ assert_eq!(map.iter().count(), 0);
+ assert_eq!(unsafe { map.table.iter().count() }, 0);
+ assert_eq!(unsafe { map.table.iter().iter.count() }, 0);
+
+ for idx in 0..map.table.buckets() {
+ let idx = idx as u64;
+ assert!(
+ map.table.find(idx, |(k, _)| *k == idx).is_none(),
+ "Index: {idx}"
+ );
+ }
+ }
+
+ // All allocator clones should already be dropped.
+ assert_eq!(dropped.load(Ordering::SeqCst), 0);
+ }
}
diff --git a/third_party/rust/hashbrown/src/raw/alloc.rs b/third_party/rust/hashbrown/src/raw/alloc.rs
index ba09ea9de7..15299e7b09 100644
--- a/third_party/rust/hashbrown/src/raw/alloc.rs
+++ b/third_party/rust/hashbrown/src/raw/alloc.rs
@@ -1,5 +1,9 @@
pub(crate) use self::inner::{do_alloc, Allocator, Global};
+// Nightly-case.
+// Use unstable `allocator_api` feature.
+// This is compatible with `allocator-api2` which can be enabled or not.
+// This is used when building for `std`.
#[cfg(feature = "nightly")]
mod inner {
use crate::alloc::alloc::Layout;
@@ -7,28 +11,44 @@ mod inner {
use core::ptr::NonNull;
#[allow(clippy::map_err_ignore)]
- pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
+ pub(crate) fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
match alloc.allocate(layout) {
Ok(ptr) => Ok(ptr.as_non_null_ptr()),
Err(_) => Err(()),
}
}
+}
- #[cfg(feature = "bumpalo")]
- unsafe impl Allocator for crate::BumpWrapper<'_> {
- #[inline]
- fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
- match self.0.try_alloc_layout(layout) {
- Ok(ptr) => Ok(NonNull::slice_from_raw_parts(ptr, layout.size())),
- Err(_) => Err(core::alloc::AllocError),
- }
+// Basic non-nightly case.
+// This uses `allocator-api2` enabled by default.
+// If any crate enables "nightly" in `allocator-api2`,
+// this will be equivalent to the nightly case,
+// since `allocator_api2::alloc::Allocator` would be re-export of
+// `core::alloc::Allocator`.
+#[cfg(all(not(feature = "nightly"), feature = "allocator-api2"))]
+mod inner {
+ use crate::alloc::alloc::Layout;
+ pub use allocator_api2::alloc::{Allocator, Global};
+ use core::ptr::NonNull;
+
+ #[allow(clippy::map_err_ignore)]
+ pub(crate) fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
+ match alloc.allocate(layout) {
+ Ok(ptr) => Ok(ptr.cast()),
+ Err(_) => Err(()),
}
- #[inline]
- unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
}
}
-#[cfg(not(feature = "nightly"))]
+// No-defaults case.
+// When building with default-features turned off and
+// neither `nightly` nor `allocator-api2` is enabled,
+// this will be used.
+// Making it impossible to use any custom allocator with collections defined
+// in this crate.
+// Any crate in build-tree can enable `allocator-api2`,
+// or `nightly` without disturbing users that don't want to use it.
+#[cfg(not(any(feature = "nightly", feature = "allocator-api2")))]
mod inner {
use crate::alloc::alloc::{alloc, dealloc, Layout};
use core::ptr::NonNull;
@@ -41,6 +61,7 @@ mod inner {
#[derive(Copy, Clone)]
pub struct Global;
+
unsafe impl Allocator for Global {
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
@@ -51,6 +72,7 @@ mod inner {
dealloc(ptr.as_ptr(), layout);
}
}
+
impl Default for Global {
#[inline]
fn default() -> Self {
@@ -58,16 +80,7 @@ mod inner {
}
}
- pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
+ pub(crate) fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
alloc.allocate(layout)
}
-
- #[cfg(feature = "bumpalo")]
- unsafe impl Allocator for crate::BumpWrapper<'_> {
- #[allow(clippy::map_err_ignore)]
- fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
- self.0.try_alloc_layout(layout).map_err(|_| ())
- }
- unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
- }
}
diff --git a/third_party/rust/hashbrown/src/raw/bitmask.rs b/third_party/rust/hashbrown/src/raw/bitmask.rs
index 7d4f9fc387..6576b3c5c0 100644
--- a/third_party/rust/hashbrown/src/raw/bitmask.rs
+++ b/third_party/rust/hashbrown/src/raw/bitmask.rs
@@ -1,6 +1,6 @@
-use super::imp::{BitMaskWord, BITMASK_MASK, BITMASK_STRIDE};
-#[cfg(feature = "nightly")]
-use core::intrinsics;
+use super::imp::{
+ BitMaskWord, NonZeroBitMaskWord, BITMASK_ITER_MASK, BITMASK_MASK, BITMASK_STRIDE,
+};
/// A bit mask which contains the result of a `Match` operation on a `Group` and
/// allows iterating through them.
@@ -8,75 +8,55 @@ use core::intrinsics;
/// The bit mask is arranged so that low-order bits represent lower memory
/// addresses for group match results.
///
-/// For implementation reasons, the bits in the set may be sparsely packed, so
-/// that there is only one bit-per-byte used (the high bit, 7). If this is the
+/// For implementation reasons, the bits in the set may be sparsely packed with
+/// groups of 8 bits representing one element. If any of these bits are non-zero
+/// then this element is considered to true in the mask. If this is the
/// case, `BITMASK_STRIDE` will be 8 to indicate a divide-by-8 should be
/// performed on counts/indices to normalize this difference. `BITMASK_MASK` is
/// similarly a mask of all the actually-used bits.
+///
+/// To iterate over a bit mask, it must be converted to a form where only 1 bit
+/// is set per element. This is done by applying `BITMASK_ITER_MASK` on the
+/// mask bits.
#[derive(Copy, Clone)]
-pub struct BitMask(pub BitMaskWord);
+pub(crate) struct BitMask(pub(crate) BitMaskWord);
#[allow(clippy::use_self)]
impl BitMask {
/// Returns a new `BitMask` with all bits inverted.
#[inline]
#[must_use]
- pub fn invert(self) -> Self {
+ #[allow(dead_code)]
+ pub(crate) fn invert(self) -> Self {
BitMask(self.0 ^ BITMASK_MASK)
}
- /// Flip the bit in the mask for the entry at the given index.
- ///
- /// Returns the bit's previous state.
- #[inline]
- #[allow(clippy::cast_ptr_alignment)]
- #[cfg(feature = "raw")]
- pub unsafe fn flip(&mut self, index: usize) -> bool {
- // NOTE: The + BITMASK_STRIDE - 1 is to set the high bit.
- let mask = 1 << (index * BITMASK_STRIDE + BITMASK_STRIDE - 1);
- self.0 ^= mask;
- // The bit was set if the bit is now 0.
- self.0 & mask == 0
- }
-
/// Returns a new `BitMask` with the lowest bit removed.
#[inline]
#[must_use]
- pub fn remove_lowest_bit(self) -> Self {
+ fn remove_lowest_bit(self) -> Self {
BitMask(self.0 & (self.0 - 1))
}
+
/// Returns whether the `BitMask` has at least one set bit.
#[inline]
- pub fn any_bit_set(self) -> bool {
+ pub(crate) fn any_bit_set(self) -> bool {
self.0 != 0
}
/// Returns the first set bit in the `BitMask`, if there is one.
#[inline]
- pub fn lowest_set_bit(self) -> Option<usize> {
- if self.0 == 0 {
- None
+ pub(crate) fn lowest_set_bit(self) -> Option<usize> {
+ if let Some(nonzero) = NonZeroBitMaskWord::new(self.0) {
+ Some(Self::nonzero_trailing_zeros(nonzero))
} else {
- Some(unsafe { self.lowest_set_bit_nonzero() })
+ None
}
}
- /// Returns the first set bit in the `BitMask`, if there is one. The
- /// bitmask must not be empty.
- #[inline]
- #[cfg(feature = "nightly")]
- pub unsafe fn lowest_set_bit_nonzero(self) -> usize {
- intrinsics::cttz_nonzero(self.0) as usize / BITMASK_STRIDE
- }
- #[inline]
- #[cfg(not(feature = "nightly"))]
- pub unsafe fn lowest_set_bit_nonzero(self) -> usize {
- self.trailing_zeros()
- }
-
/// Returns the number of trailing zeroes in the `BitMask`.
#[inline]
- pub fn trailing_zeros(self) -> usize {
+ pub(crate) fn trailing_zeros(self) -> usize {
// ARM doesn't have a trailing_zeroes instruction, and instead uses
// reverse_bits (RBIT) + leading_zeroes (CLZ). However older ARM
// versions (pre-ARMv7) don't have RBIT and need to emulate it
@@ -89,9 +69,21 @@ impl BitMask {
}
}
+ /// Same as above but takes a `NonZeroBitMaskWord`.
+ #[inline]
+ fn nonzero_trailing_zeros(nonzero: NonZeroBitMaskWord) -> usize {
+ if cfg!(target_arch = "arm") && BITMASK_STRIDE % 8 == 0 {
+ // SAFETY: A byte-swapped non-zero value is still non-zero.
+ let swapped = unsafe { NonZeroBitMaskWord::new_unchecked(nonzero.get().swap_bytes()) };
+ swapped.leading_zeros() as usize / BITMASK_STRIDE
+ } else {
+ nonzero.trailing_zeros() as usize / BITMASK_STRIDE
+ }
+ }
+
/// Returns the number of leading zeroes in the `BitMask`.
#[inline]
- pub fn leading_zeros(self) -> usize {
+ pub(crate) fn leading_zeros(self) -> usize {
self.0.leading_zeros() as usize / BITMASK_STRIDE
}
}
@@ -102,13 +94,32 @@ impl IntoIterator for BitMask {
#[inline]
fn into_iter(self) -> BitMaskIter {
- BitMaskIter(self)
+ // A BitMask only requires each element (group of bits) to be non-zero.
+ // However for iteration we need each element to only contain 1 bit.
+ BitMaskIter(BitMask(self.0 & BITMASK_ITER_MASK))
}
}
/// Iterator over the contents of a `BitMask`, returning the indices of set
/// bits.
-pub struct BitMaskIter(BitMask);
+#[derive(Copy, Clone)]
+pub(crate) struct BitMaskIter(pub(crate) BitMask);
+
+impl BitMaskIter {
+ /// Flip the bit in the mask for the entry at the given index.
+ ///
+ /// Returns the bit's previous state.
+ #[inline]
+ #[allow(clippy::cast_ptr_alignment)]
+ #[cfg(feature = "raw")]
+ pub(crate) unsafe fn flip(&mut self, index: usize) -> bool {
+ // NOTE: The + BITMASK_STRIDE - 1 is to set the high bit.
+ let mask = 1 << (index * BITMASK_STRIDE + BITMASK_STRIDE - 1);
+ self.0 .0 ^= mask;
+ // The bit was set if the bit is now 0.
+ self.0 .0 & mask == 0
+ }
+}
impl Iterator for BitMaskIter {
type Item = usize;
diff --git a/third_party/rust/hashbrown/src/raw/generic.rs b/third_party/rust/hashbrown/src/raw/generic.rs
index b4d31e62c2..c668b0642a 100644
--- a/third_party/rust/hashbrown/src/raw/generic.rs
+++ b/third_party/rust/hashbrown/src/raw/generic.rs
@@ -5,26 +5,29 @@ use core::{mem, ptr};
// Use the native word size as the group size. Using a 64-bit group size on
// a 32-bit architecture will just end up being more expensive because
// shifts and multiplies will need to be emulated.
-#[cfg(any(
- target_pointer_width = "64",
- target_arch = "aarch64",
- target_arch = "x86_64",
- target_arch = "wasm32",
-))]
-type GroupWord = u64;
-#[cfg(all(
- target_pointer_width = "32",
- not(target_arch = "aarch64"),
- not(target_arch = "x86_64"),
- not(target_arch = "wasm32"),
-))]
-type GroupWord = u32;
-pub type BitMaskWord = GroupWord;
-pub const BITMASK_STRIDE: usize = 8;
+cfg_if! {
+ if #[cfg(any(
+ target_pointer_width = "64",
+ target_arch = "aarch64",
+ target_arch = "x86_64",
+ target_arch = "wasm32",
+ ))] {
+ type GroupWord = u64;
+ type NonZeroGroupWord = core::num::NonZeroU64;
+ } else {
+ type GroupWord = u32;
+ type NonZeroGroupWord = core::num::NonZeroU32;
+ }
+}
+
+pub(crate) type BitMaskWord = GroupWord;
+pub(crate) type NonZeroBitMaskWord = NonZeroGroupWord;
+pub(crate) const BITMASK_STRIDE: usize = 8;
// We only care about the highest bit of each byte for the mask.
#[allow(clippy::cast_possible_truncation, clippy::unnecessary_cast)]
-pub const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord;
+pub(crate) const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord;
+pub(crate) const BITMASK_ITER_MASK: BitMaskWord = !0;
/// Helper function to replicate a byte across a `GroupWord`.
#[inline]
@@ -37,7 +40,7 @@ fn repeat(byte: u8) -> GroupWord {
///
/// This implementation uses a word-sized integer.
#[derive(Copy, Clone)]
-pub struct Group(GroupWord);
+pub(crate) struct Group(GroupWord);
// We perform all operations in the native endianness, and convert to
// little-endian just before creating a BitMask. The can potentially
@@ -46,14 +49,14 @@ pub struct Group(GroupWord);
#[allow(clippy::use_self)]
impl Group {
/// Number of bytes in the group.
- pub const WIDTH: usize = mem::size_of::<Self>();
+ pub(crate) const WIDTH: usize = mem::size_of::<Self>();
/// Returns a full group of empty bytes, suitable for use as the initial
/// value for an empty hash table.
///
/// This is guaranteed to be aligned to the group size.
#[inline]
- pub const fn static_empty() -> &'static [u8; Group::WIDTH] {
+ pub(crate) const fn static_empty() -> &'static [u8; Group::WIDTH] {
#[repr(C)]
struct AlignedBytes {
_align: [Group; 0],
@@ -69,7 +72,7 @@ impl Group {
/// Loads a group of bytes starting at the given address.
#[inline]
#[allow(clippy::cast_ptr_alignment)] // unaligned load
- pub unsafe fn load(ptr: *const u8) -> Self {
+ pub(crate) unsafe fn load(ptr: *const u8) -> Self {
Group(ptr::read_unaligned(ptr.cast()))
}
@@ -77,7 +80,7 @@ impl Group {
/// aligned to `mem::align_of::<Group>()`.
#[inline]
#[allow(clippy::cast_ptr_alignment)]
- pub unsafe fn load_aligned(ptr: *const u8) -> Self {
+ pub(crate) unsafe fn load_aligned(ptr: *const u8) -> Self {
// FIXME: use align_offset once it stabilizes
debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
Group(ptr::read(ptr.cast()))
@@ -87,7 +90,7 @@ impl Group {
/// aligned to `mem::align_of::<Group>()`.
#[inline]
#[allow(clippy::cast_ptr_alignment)]
- pub unsafe fn store_aligned(self, ptr: *mut u8) {
+ pub(crate) unsafe fn store_aligned(self, ptr: *mut u8) {
// FIXME: use align_offset once it stabilizes
debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
ptr::write(ptr.cast(), self.0);
@@ -104,7 +107,7 @@ impl Group {
/// - This only happens if there is at least 1 true match.
/// - The chance of this happening is very low (< 1% chance per byte).
#[inline]
- pub fn match_byte(self, byte: u8) -> BitMask {
+ pub(crate) fn match_byte(self, byte: u8) -> BitMask {
// This algorithm is derived from
// https://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
let cmp = self.0 ^ repeat(byte);
@@ -114,7 +117,7 @@ impl Group {
/// Returns a `BitMask` indicating all bytes in the group which are
/// `EMPTY`.
#[inline]
- pub fn match_empty(self) -> BitMask {
+ pub(crate) fn match_empty(self) -> BitMask {
// If the high bit is set, then the byte must be either:
// 1111_1111 (EMPTY) or 1000_0000 (DELETED).
// So we can just check if the top two bits are 1 by ANDing them.
@@ -124,14 +127,14 @@ impl Group {
/// Returns a `BitMask` indicating all bytes in the group which are
/// `EMPTY` or `DELETED`.
#[inline]
- pub fn match_empty_or_deleted(self) -> BitMask {
+ pub(crate) fn match_empty_or_deleted(self) -> BitMask {
// A byte is EMPTY or DELETED iff the high bit is set
BitMask((self.0 & repeat(0x80)).to_le())
}
/// Returns a `BitMask` indicating all bytes in the group which are full.
#[inline]
- pub fn match_full(self) -> BitMask {
+ pub(crate) fn match_full(self) -> BitMask {
self.match_empty_or_deleted().invert()
}
@@ -140,7 +143,7 @@ impl Group {
/// - `DELETED => EMPTY`
/// - `FULL => DELETED`
#[inline]
- pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
+ pub(crate) fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
// Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
// and high_bit = 0 (FULL) to 1000_0000
//
diff --git a/third_party/rust/hashbrown/src/raw/mod.rs b/third_party/rust/hashbrown/src/raw/mod.rs
index 211b818a5f..c8e8e29122 100644
--- a/third_party/rust/hashbrown/src/raw/mod.rs
+++ b/third_party/rust/hashbrown/src/raw/mod.rs
@@ -4,7 +4,6 @@ use crate::TryReserveError;
use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::mem;
-use core::mem::ManuallyDrop;
use core::mem::MaybeUninit;
use core::ptr::NonNull;
use core::{hint, ptr};
@@ -21,12 +20,21 @@ cfg_if! {
if #[cfg(all(
target_feature = "sse2",
any(target_arch = "x86", target_arch = "x86_64"),
- not(miri)
+ not(miri),
))] {
mod sse2;
use sse2 as imp;
+ } else if #[cfg(all(
+ target_arch = "aarch64",
+ target_feature = "neon",
+ // NEON intrinsics are currently broken on big-endian targets.
+ // See https://github.com/rust-lang/stdarch/issues/1484.
+ target_endian = "little",
+ not(miri),
+ ))] {
+ mod neon;
+ use neon as imp;
} else {
- #[path = "generic.rs"]
mod generic;
use generic as imp;
}
@@ -37,36 +45,24 @@ pub(crate) use self::alloc::{do_alloc, Allocator, Global};
mod bitmask;
-use self::bitmask::{BitMask, BitMaskIter};
+use self::bitmask::BitMaskIter;
use self::imp::Group;
// Branch prediction hint. This is currently only available on nightly but it
// consistently improves performance by 10-15%.
+#[cfg(not(feature = "nightly"))]
+use core::convert::identity as likely;
+#[cfg(not(feature = "nightly"))]
+use core::convert::identity as unlikely;
#[cfg(feature = "nightly")]
use core::intrinsics::{likely, unlikely};
-// On stable we can use #[cold] to get a equivalent effect: this attributes
-// suggests that the function is unlikely to be called
-#[cfg(not(feature = "nightly"))]
-#[inline]
-#[cold]
-fn cold() {}
-
-#[cfg(not(feature = "nightly"))]
-#[inline]
-fn likely(b: bool) -> bool {
- if !b {
- cold();
- }
- b
-}
-#[cfg(not(feature = "nightly"))]
-#[inline]
-fn unlikely(b: bool) -> bool {
- if b {
- cold();
- }
- b
+// FIXME: use strict provenance functions once they are stable.
+// Implement it with a transmute for now.
+#[inline(always)]
+#[allow(clippy::useless_transmute)] // clippy is wrong, cast and transmute are different here
+fn invalid_mut<T>(addr: usize) -> *mut T {
+ unsafe { core::mem::transmute(addr) }
}
#[inline]
@@ -101,6 +97,13 @@ impl Fallibility {
}
}
+trait SizedTypeProperties: Sized {
+ const IS_ZERO_SIZED: bool = mem::size_of::<Self>() == 0;
+ const NEEDS_DROP: bool = mem::needs_drop::<Self>();
+}
+
+impl<T> SizedTypeProperties for T {}
+
/// Control byte value for an empty bucket.
const EMPTY: u8 = 0b1111_1111;
@@ -134,6 +137,13 @@ fn h1(hash: u64) -> usize {
hash as usize
}
+// Constant for h2 function that grabing the top 7 bits of the hash.
+const MIN_HASH_LEN: usize = if mem::size_of::<usize>() < mem::size_of::<u64>() {
+ mem::size_of::<usize>()
+} else {
+ mem::size_of::<u64>()
+};
+
/// Secondary hash function, saved in the low 7 bits of the control byte.
#[inline]
#[allow(clippy::cast_possible_truncation)]
@@ -141,8 +151,8 @@ fn h2(hash: u64) -> u8 {
// Grab the top 7 bits of the hash. While the hash is normally a full 64-bit
// value, some hash functions (such as FxHash) produce a usize result
// instead, which means that the top 32 bits are 0 on 32-bit platforms.
- let hash_len = usize::min(mem::size_of::<usize>(), mem::size_of::<u64>());
- let top7 = hash >> (hash_len * 8 - 7);
+ // So we use MIN_HASH_LEN constant to handle this.
+ let top7 = hash >> (MIN_HASH_LEN * 8 - 7);
(top7 & 0x7f) as u8 // truncation
}
@@ -230,11 +240,15 @@ struct TableLayout {
impl TableLayout {
#[inline]
- fn new<T>() -> Self {
+ const fn new<T>() -> Self {
let layout = Layout::new::<T>();
Self {
size: layout.size(),
- ctrl_align: usize::max(layout.align(), Group::WIDTH),
+ ctrl_align: if layout.align() > Group::WIDTH {
+ layout.align()
+ } else {
+ Group::WIDTH
+ },
}
}
@@ -248,6 +262,12 @@ impl TableLayout {
size.checked_mul(buckets)?.checked_add(ctrl_align - 1)? & !(ctrl_align - 1);
let len = ctrl_offset.checked_add(buckets + Group::WIDTH)?;
+ // We need an additional check to ensure that the allocation doesn't
+ // exceed `isize::MAX` (https://github.com/rust-lang/rust/pull/95295).
+ if len > isize::MAX as usize - (ctrl_align - 1) {
+ return None;
+ }
+
Some((
unsafe { Layout::from_size_align_unchecked(len, ctrl_align) },
ctrl_offset,
@@ -255,14 +275,9 @@ impl TableLayout {
}
}
-/// Returns a Layout which describes the allocation required for a hash table,
-/// and the offset of the control bytes in the allocation.
-/// (the offset is also one past last element of buckets)
-///
-/// Returns `None` if an overflow occurs.
-#[cfg_attr(feature = "inline-more", inline)]
-fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
- TableLayout::new::<T>().calculate_layout_for(buckets)
+/// A reference to an empty bucket into which an can be inserted.
+pub struct InsertSlot {
+ index: usize,
}
/// A reference to a hash table bucket containing a `T`.
@@ -290,11 +305,79 @@ impl<T> Clone for Bucket<T> {
}
impl<T> Bucket<T> {
+ /// Creates a [`Bucket`] that contain pointer to the data.
+ /// The pointer calculation is performed by calculating the
+ /// offset from given `base` pointer (convenience for
+ /// `base.as_ptr().sub(index)`).
+ ///
+ /// `index` is in units of `T`; e.g., an `index` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// If the `T` is a ZST, then we instead track the index of the element
+ /// in the table so that `erase` works properly (return
+ /// `NonNull::new_unchecked((index + 1) as *mut T)`)
+ ///
+ /// # Safety
+ ///
+ /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived
+ /// from the safety rules for [`<*mut T>::sub`] method of `*mut T` and the safety
+ /// rules of [`NonNull::new_unchecked`] function.
+ ///
+ /// Thus, in order to uphold the safety contracts for the [`<*mut T>::sub`] method
+ /// and [`NonNull::new_unchecked`] function, as well as for the correct
+ /// logic of the work of this crate, the following rules are necessary and
+ /// sufficient:
+ ///
+ /// * the `base` pointer must not be `dangling` and must points to the
+ /// end of the first `value element` from the `data part` of the table, i.e.
+ /// must be the pointer that returned by [`RawTable::data_end`] or by
+ /// [`RawTableInner::data_end<T>`];
+ ///
+ /// * `index` must not be greater than `RawTableInner.bucket_mask`, i.e.
+ /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)`
+ /// must be no greater than the number returned by the function
+ /// [`RawTable::buckets`] or [`RawTableInner::buckets`].
+ ///
+ /// If `mem::size_of::<T>() == 0`, then the only requirement is that the
+ /// `index` must not be greater than `RawTableInner.bucket_mask`, i.e.
+ /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)`
+ /// must be no greater than the number returned by the function
+ /// [`RawTable::buckets`] or [`RawTableInner::buckets`].
+ ///
+ /// [`Bucket`]: crate::raw::Bucket
+ /// [`<*mut T>::sub`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.sub-1
+ /// [`NonNull::new_unchecked`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.new_unchecked
+ /// [`RawTable::data_end`]: crate::raw::RawTable::data_end
+ /// [`RawTableInner::data_end<T>`]: RawTableInner::data_end<T>
+ /// [`RawTable::buckets`]: crate::raw::RawTable::buckets
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
#[inline]
unsafe fn from_base_index(base: NonNull<T>, index: usize) -> Self {
- let ptr = if mem::size_of::<T>() == 0 {
- // won't overflow because index must be less than length
- (index + 1) as *mut T
+ // If mem::size_of::<T>() != 0 then return a pointer to an `element` in
+ // the data part of the table (we start counting from "0", so that
+ // in the expression T[last], the "last" index actually one less than the
+ // "buckets" number in the table, i.e. "last = RawTableInner.bucket_mask"):
+ //
+ // `from_base_index(base, 1).as_ptr()` returns a pointer that
+ // points here in the data part of the table
+ // (to the start of T1)
+ // |
+ // | `base: NonNull<T>` must point here
+ // | (to the end of T0 or to the start of C0)
+ // v v
+ // [Padding], Tlast, ..., |T1|, T0, |C0, C1, ..., Clast
+ // ^
+ // `from_base_index(base, 1)` returns a pointer
+ // that points here in the data part of the table
+ // (to the end of T1)
+ //
+ // where: T0...Tlast - our stored data; C0...Clast - control bytes
+ // or metadata for data.
+ let ptr = if T::IS_ZERO_SIZED {
+ // won't overflow because index must be less than length (bucket_mask)
+ // and bucket_mask is guaranteed to be less than `isize::MAX`
+ // (see TableLayout::calculate_layout_for method)
+ invalid_mut(index + 1)
} else {
base.as_ptr().sub(index)
};
@@ -302,27 +385,183 @@ impl<T> Bucket<T> {
ptr: NonNull::new_unchecked(ptr),
}
}
+
+ /// Calculates the index of a [`Bucket`] as distance between two pointers
+ /// (convenience for `base.as_ptr().offset_from(self.ptr.as_ptr()) as usize`).
+ /// The returned value is in units of T: the distance in bytes divided by
+ /// [`core::mem::size_of::<T>()`].
+ ///
+ /// If the `T` is a ZST, then we return the index of the element in
+ /// the table so that `erase` works properly (return `self.ptr.as_ptr() as usize - 1`).
+ ///
+ /// This function is the inverse of [`from_base_index`].
+ ///
+ /// # Safety
+ ///
+ /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived
+ /// from the safety rules for [`<*const T>::offset_from`] method of `*const T`.
+ ///
+ /// Thus, in order to uphold the safety contracts for [`<*const T>::offset_from`]
+ /// method, as well as for the correct logic of the work of this crate, the
+ /// following rules are necessary and sufficient:
+ ///
+ /// * `base` contained pointer must not be `dangling` and must point to the
+ /// end of the first `element` from the `data part` of the table, i.e.
+ /// must be a pointer that returns by [`RawTable::data_end`] or by
+ /// [`RawTableInner::data_end<T>`];
+ ///
+ /// * `self` also must not contain dangling pointer;
+ ///
+ /// * both `self` and `base` must be created from the same [`RawTable`]
+ /// (or [`RawTableInner`]).
+ ///
+ /// If `mem::size_of::<T>() == 0`, this function is always safe.
+ ///
+ /// [`Bucket`]: crate::raw::Bucket
+ /// [`from_base_index`]: crate::raw::Bucket::from_base_index
+ /// [`RawTable::data_end`]: crate::raw::RawTable::data_end
+ /// [`RawTableInner::data_end<T>`]: RawTableInner::data_end<T>
+ /// [`RawTable`]: crate::raw::RawTable
+ /// [`RawTableInner`]: RawTableInner
+ /// [`<*const T>::offset_from`]: https://doc.rust-lang.org/nightly/core/primitive.pointer.html#method.offset_from
#[inline]
unsafe fn to_base_index(&self, base: NonNull<T>) -> usize {
- if mem::size_of::<T>() == 0 {
+ // If mem::size_of::<T>() != 0 then return an index under which we used to store the
+ // `element` in the data part of the table (we start counting from "0", so
+ // that in the expression T[last], the "last" index actually is one less than the
+ // "buckets" number in the table, i.e. "last = RawTableInner.bucket_mask").
+ // For example for 5th element in table calculation is performed like this:
+ //
+ // mem::size_of::<T>()
+ // |
+ // | `self = from_base_index(base, 5)` that returns pointer
+ // | that points here in tha data part of the table
+ // | (to the end of T5)
+ // | | `base: NonNull<T>` must point here
+ // v | (to the end of T0 or to the start of C0)
+ // /???\ v v
+ // [Padding], Tlast, ..., |T10|, ..., T5|, T4, T3, T2, T1, T0, |C0, C1, C2, C3, C4, C5, ..., C10, ..., Clast
+ // \__________ __________/
+ // \/
+ // `bucket.to_base_index(base)` = 5
+ // (base.as_ptr() as usize - self.ptr.as_ptr() as usize) / mem::size_of::<T>()
+ //
+ // where: T0...Tlast - our stored data; C0...Clast - control bytes or metadata for data.
+ if T::IS_ZERO_SIZED {
+ // this can not be UB
self.ptr.as_ptr() as usize - 1
} else {
offset_from(base.as_ptr(), self.ptr.as_ptr())
}
}
+
+ /// Acquires the underlying raw pointer `*mut T` to `data`.
+ ///
+ /// # Note
+ ///
+ /// If `T` is not [`Copy`], do not use `*mut T` methods that can cause calling the
+ /// destructor of `T` (for example the [`<*mut T>::drop_in_place`] method), because
+ /// for properly dropping the data we also need to clear `data` control bytes. If we
+ /// drop data, but do not clear `data control byte` it leads to double drop when
+ /// [`RawTable`] goes out of scope.
+ ///
+ /// If you modify an already initialized `value`, so [`Hash`] and [`Eq`] on the new
+ /// `T` value and its borrowed form *must* match those for the old `T` value, as the map
+ /// will not re-evaluate where the new value should go, meaning the value may become
+ /// "lost" if their location does not reflect their state.
+ ///
+ /// [`RawTable`]: crate::raw::RawTable
+ /// [`<*mut T>::drop_in_place`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.drop_in_place
+ /// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
+ /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "raw")]
+ /// # fn test() {
+ /// use core::hash::{BuildHasher, Hash};
+ /// use hashbrown::raw::{Bucket, RawTable};
+ ///
+ /// type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;
+ ///
+ /// fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
+ /// use core::hash::Hasher;
+ /// let mut state = hash_builder.build_hasher();
+ /// key.hash(&mut state);
+ /// state.finish()
+ /// }
+ ///
+ /// let hash_builder = NewHashBuilder::default();
+ /// let mut table = RawTable::new();
+ ///
+ /// let value = ("a", 100);
+ /// let hash = make_hash(&hash_builder, &value.0);
+ ///
+ /// table.insert(hash, value.clone(), |val| make_hash(&hash_builder, &val.0));
+ ///
+ /// let bucket: Bucket<(&str, i32)> = table.find(hash, |(k1, _)| k1 == &value.0).unwrap();
+ ///
+ /// assert_eq!(unsafe { &*bucket.as_ptr() }, &("a", 100));
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "raw")]
+ /// # test()
+ /// # }
+ /// ```
#[inline]
pub fn as_ptr(&self) -> *mut T {
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZERO_SIZED {
// Just return an arbitrary ZST pointer which is properly aligned
- mem::align_of::<T>() as *mut T
+ // invalid pointer is good enough for ZST
+ invalid_mut(mem::align_of::<T>())
} else {
unsafe { self.ptr.as_ptr().sub(1) }
}
}
+
+ /// Create a new [`Bucket`] that is offset from the `self` by the given
+ /// `offset`. The pointer calculation is performed by calculating the
+ /// offset from `self` pointer (convenience for `self.ptr.as_ptr().sub(offset)`).
+ /// This function is used for iterators.
+ ///
+ /// `offset` is in units of `T`; e.g., a `offset` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived
+ /// from the safety rules for [`<*mut T>::sub`] method of `*mut T` and safety
+ /// rules of [`NonNull::new_unchecked`] function.
+ ///
+ /// Thus, in order to uphold the safety contracts for [`<*mut T>::sub`] method
+ /// and [`NonNull::new_unchecked`] function, as well as for the correct
+ /// logic of the work of this crate, the following rules are necessary and
+ /// sufficient:
+ ///
+ /// * `self` contained pointer must not be `dangling`;
+ ///
+ /// * `self.to_base_index() + ofset` must not be greater than `RawTableInner.bucket_mask`,
+ /// i.e. `(self.to_base_index() + ofset) <= RawTableInner.bucket_mask` or, in other
+ /// words, `self.to_base_index() + ofset + 1` must be no greater than the number returned
+ /// by the function [`RawTable::buckets`] or [`RawTableInner::buckets`].
+ ///
+ /// If `mem::size_of::<T>() == 0`, then the only requirement is that the
+ /// `self.to_base_index() + ofset` must not be greater than `RawTableInner.bucket_mask`,
+ /// i.e. `(self.to_base_index() + ofset) <= RawTableInner.bucket_mask` or, in other words,
+ /// `self.to_base_index() + ofset + 1` must be no greater than the number returned by the
+ /// function [`RawTable::buckets`] or [`RawTableInner::buckets`].
+ ///
+ /// [`Bucket`]: crate::raw::Bucket
+ /// [`<*mut T>::sub`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.sub-1
+ /// [`NonNull::new_unchecked`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.new_unchecked
+ /// [`RawTable::buckets`]: crate::raw::RawTable::buckets
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
#[inline]
unsafe fn next_n(&self, offset: usize) -> Self {
- let ptr = if mem::size_of::<T>() == 0 {
- (self.ptr.as_ptr() as usize + offset) as *mut T
+ let ptr = if T::IS_ZERO_SIZED {
+ // invalid pointer is good enough for ZST
+ invalid_mut(self.ptr.as_ptr() as usize + offset)
} else {
self.ptr.as_ptr().sub(offset)
};
@@ -330,26 +569,212 @@ impl<T> Bucket<T> {
ptr: NonNull::new_unchecked(ptr),
}
}
+
+ /// Executes the destructor (if any) of the pointed-to `data`.
+ ///
+ /// # Safety
+ ///
+ /// See [`ptr::drop_in_place`] for safety concerns.
+ ///
+ /// You should use [`RawTable::erase`] instead of this function,
+ /// or be careful with calling this function directly, because for
+ /// properly dropping the data we need also clear `data` control bytes.
+ /// If we drop data, but do not erase `data control byte` it leads to
+ /// double drop when [`RawTable`] goes out of scope.
+ ///
+ /// [`ptr::drop_in_place`]: https://doc.rust-lang.org/core/ptr/fn.drop_in_place.html
+ /// [`RawTable`]: crate::raw::RawTable
+ /// [`RawTable::erase`]: crate::raw::RawTable::erase
#[cfg_attr(feature = "inline-more", inline)]
- pub unsafe fn drop(&self) {
+ pub(crate) unsafe fn drop(&self) {
self.as_ptr().drop_in_place();
}
+
+ /// Reads the `value` from `self` without moving it. This leaves the
+ /// memory in `self` unchanged.
+ ///
+ /// # Safety
+ ///
+ /// See [`ptr::read`] for safety concerns.
+ ///
+ /// You should use [`RawTable::remove`] instead of this function,
+ /// or be careful with calling this function directly, because compiler
+ /// calls its destructor when readed `value` goes out of scope. It
+ /// can cause double dropping when [`RawTable`] goes out of scope,
+ /// because of not erased `data control byte`.
+ ///
+ /// [`ptr::read`]: https://doc.rust-lang.org/core/ptr/fn.read.html
+ /// [`RawTable`]: crate::raw::RawTable
+ /// [`RawTable::remove`]: crate::raw::RawTable::remove
#[inline]
- pub unsafe fn read(&self) -> T {
+ pub(crate) unsafe fn read(&self) -> T {
self.as_ptr().read()
}
+
+ /// Overwrites a memory location with the given `value` without reading
+ /// or dropping the old value (like [`ptr::write`] function).
+ ///
+ /// # Safety
+ ///
+ /// See [`ptr::write`] for safety concerns.
+ ///
+ /// # Note
+ ///
+ /// [`Hash`] and [`Eq`] on the new `T` value and its borrowed form *must* match
+ /// those for the old `T` value, as the map will not re-evaluate where the new
+ /// value should go, meaning the value may become "lost" if their location
+ /// does not reflect their state.
+ ///
+ /// [`ptr::write`]: https://doc.rust-lang.org/core/ptr/fn.write.html
+ /// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
+ /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
#[inline]
- pub unsafe fn write(&self, val: T) {
+ pub(crate) unsafe fn write(&self, val: T) {
self.as_ptr().write(val);
}
+
+ /// Returns a shared immutable reference to the `value`.
+ ///
+ /// # Safety
+ ///
+ /// See [`NonNull::as_ref`] for safety concerns.
+ ///
+ /// [`NonNull::as_ref`]: https://doc.rust-lang.org/core/ptr/struct.NonNull.html#method.as_ref
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "raw")]
+ /// # fn test() {
+ /// use core::hash::{BuildHasher, Hash};
+ /// use hashbrown::raw::{Bucket, RawTable};
+ ///
+ /// type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;
+ ///
+ /// fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
+ /// use core::hash::Hasher;
+ /// let mut state = hash_builder.build_hasher();
+ /// key.hash(&mut state);
+ /// state.finish()
+ /// }
+ ///
+ /// let hash_builder = NewHashBuilder::default();
+ /// let mut table = RawTable::new();
+ ///
+ /// let value: (&str, String) = ("A pony", "is a small horse".to_owned());
+ /// let hash = make_hash(&hash_builder, &value.0);
+ ///
+ /// table.insert(hash, value.clone(), |val| make_hash(&hash_builder, &val.0));
+ ///
+ /// let bucket: Bucket<(&str, String)> = table.find(hash, |(k, _)| k == &value.0).unwrap();
+ ///
+ /// assert_eq!(
+ /// unsafe { bucket.as_ref() },
+ /// &("A pony", "is a small horse".to_owned())
+ /// );
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "raw")]
+ /// # test()
+ /// # }
+ /// ```
#[inline]
pub unsafe fn as_ref<'a>(&self) -> &'a T {
&*self.as_ptr()
}
+
+ /// Returns a unique mutable reference to the `value`.
+ ///
+ /// # Safety
+ ///
+ /// See [`NonNull::as_mut`] for safety concerns.
+ ///
+ /// # Note
+ ///
+ /// [`Hash`] and [`Eq`] on the new `T` value and its borrowed form *must* match
+ /// those for the old `T` value, as the map will not re-evaluate where the new
+ /// value should go, meaning the value may become "lost" if their location
+ /// does not reflect their state.
+ ///
+ /// [`NonNull::as_mut`]: https://doc.rust-lang.org/core/ptr/struct.NonNull.html#method.as_mut
+ /// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
+ /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "raw")]
+ /// # fn test() {
+ /// use core::hash::{BuildHasher, Hash};
+ /// use hashbrown::raw::{Bucket, RawTable};
+ ///
+ /// type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;
+ ///
+ /// fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
+ /// use core::hash::Hasher;
+ /// let mut state = hash_builder.build_hasher();
+ /// key.hash(&mut state);
+ /// state.finish()
+ /// }
+ ///
+ /// let hash_builder = NewHashBuilder::default();
+ /// let mut table = RawTable::new();
+ ///
+ /// let value: (&str, String) = ("A pony", "is a small horse".to_owned());
+ /// let hash = make_hash(&hash_builder, &value.0);
+ ///
+ /// table.insert(hash, value.clone(), |val| make_hash(&hash_builder, &val.0));
+ ///
+ /// let bucket: Bucket<(&str, String)> = table.find(hash, |(k, _)| k == &value.0).unwrap();
+ ///
+ /// unsafe {
+ /// bucket
+ /// .as_mut()
+ /// .1
+ /// .push_str(" less than 147 cm at the withers")
+ /// };
+ /// assert_eq!(
+ /// unsafe { bucket.as_ref() },
+ /// &(
+ /// "A pony",
+ /// "is a small horse less than 147 cm at the withers".to_owned()
+ /// )
+ /// );
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "raw")]
+ /// # test()
+ /// # }
+ /// ```
#[inline]
pub unsafe fn as_mut<'a>(&self) -> &'a mut T {
&mut *self.as_ptr()
}
+
+ /// Copies `size_of<T>` bytes from `other` to `self`. The source
+ /// and destination may *not* overlap.
+ ///
+ /// # Safety
+ ///
+ /// See [`ptr::copy_nonoverlapping`] for safety concerns.
+ ///
+ /// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
+ /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
+ /// in the region beginning at `*self` and the region beginning at `*other` can
+ /// [violate memory safety].
+ ///
+ /// # Note
+ ///
+ /// [`Hash`] and [`Eq`] on the new `T` value and its borrowed form *must* match
+ /// those for the old `T` value, as the map will not re-evaluate where the new
+ /// value should go, meaning the value may become "lost" if their location
+ /// does not reflect their state.
+ ///
+ /// [`ptr::copy_nonoverlapping`]: https://doc.rust-lang.org/core/ptr/fn.copy_nonoverlapping.html
+ /// [`read`]: https://doc.rust-lang.org/core/ptr/fn.read.html
+ /// [violate memory safety]: https://doc.rust-lang.org/std/ptr/fn.read.html#ownership-of-the-returned-value
+ /// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
+ /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
#[cfg(feature = "raw")]
#[inline]
pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) {
@@ -358,15 +783,16 @@ impl<T> Bucket<T> {
}
/// A raw hash table with an unsafe API.
-pub struct RawTable<T, A: Allocator + Clone = Global> {
- table: RawTableInner<A>,
+pub struct RawTable<T, A: Allocator = Global> {
+ table: RawTableInner,
+ alloc: A,
// Tell dropck that we own instances of T.
marker: PhantomData<T>,
}
/// Non-generic part of `RawTable` which allows functions to be instantiated only once regardless
/// of how many different key-value types are used.
-struct RawTableInner<A> {
+struct RawTableInner {
// Mask to get an index from a hash value. The value is one less than the
// number of buckets in the table.
bucket_mask: usize,
@@ -380,8 +806,6 @@ struct RawTableInner<A> {
// Number of elements in the table, only really used by len()
items: usize,
-
- alloc: A,
}
impl<T> RawTable<T, Global> {
@@ -393,7 +817,8 @@ impl<T> RawTable<T, Global> {
#[inline]
pub const fn new() -> Self {
Self {
- table: RawTableInner::new_in(Global),
+ table: RawTableInner::NEW,
+ alloc: Global,
marker: PhantomData,
}
}
@@ -412,7 +837,9 @@ impl<T> RawTable<T, Global> {
}
}
-impl<T, A: Allocator + Clone> RawTable<T, A> {
+impl<T, A: Allocator> RawTable<T, A> {
+ const TABLE_LAYOUT: TableLayout = TableLayout::new::<T>();
+
/// Creates a new empty hash table without allocating any memory, using the
/// given allocator.
///
@@ -420,9 +847,10 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
/// leave the data pointer dangling since that bucket is never written to
/// due to our load factor forcing us to always have at least 1 free bucket.
#[inline]
- pub fn new_in(alloc: A) -> Self {
+ pub const fn new_in(alloc: A) -> Self {
Self {
- table: RawTableInner::new_in(alloc),
+ table: RawTableInner::NEW,
+ alloc,
marker: PhantomData,
}
}
@@ -440,73 +868,97 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
Ok(Self {
table: RawTableInner::new_uninitialized(
- alloc,
- TableLayout::new::<T>(),
+ &alloc,
+ Self::TABLE_LAYOUT,
buckets,
fallibility,
)?,
+ alloc,
marker: PhantomData,
})
}
- /// Attempts to allocate a new hash table with at least enough capacity
- /// for inserting the given number of elements without reallocating.
- fn fallible_with_capacity(
- alloc: A,
- capacity: usize,
- fallibility: Fallibility,
- ) -> Result<Self, TryReserveError> {
+ /// Attempts to allocate a new hash table using the given allocator, with at least enough
+ /// capacity for inserting the given number of elements without reallocating.
+ #[cfg(feature = "raw")]
+ pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserveError> {
Ok(Self {
table: RawTableInner::fallible_with_capacity(
- alloc,
- TableLayout::new::<T>(),
+ &alloc,
+ Self::TABLE_LAYOUT,
capacity,
- fallibility,
+ Fallibility::Fallible,
)?,
+ alloc,
marker: PhantomData,
})
}
- /// Attempts to allocate a new hash table using the given allocator, with at least enough
- /// capacity for inserting the given number of elements without reallocating.
- #[cfg(feature = "raw")]
- pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserveError> {
- Self::fallible_with_capacity(alloc, capacity, Fallibility::Fallible)
- }
-
/// Allocates a new hash table using the given allocator, with at least enough capacity for
/// inserting the given number of elements without reallocating.
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
- // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
- match Self::fallible_with_capacity(alloc, capacity, Fallibility::Infallible) {
- Ok(capacity) => capacity,
- Err(_) => unsafe { hint::unreachable_unchecked() },
+ Self {
+ table: RawTableInner::with_capacity(&alloc, Self::TABLE_LAYOUT, capacity),
+ alloc,
+ marker: PhantomData,
}
}
/// Returns a reference to the underlying allocator.
#[inline]
pub fn allocator(&self) -> &A {
- &self.table.alloc
+ &self.alloc
}
- /// Deallocates the table without dropping any entries.
- #[cfg_attr(feature = "inline-more", inline)]
- unsafe fn free_buckets(&mut self) {
- self.table.free_buckets(TableLayout::new::<T>());
+ /// Returns pointer to one past last `data` element in the table as viewed from
+ /// the start point of the allocation.
+ ///
+ /// The caller must ensure that the `RawTable` outlives the returned [`NonNull<T>`],
+ /// otherwise using it may result in [`undefined behavior`].
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[inline]
+ pub fn data_end(&self) -> NonNull<T> {
+ // `self.table.ctrl.cast()` returns pointer that
+ // points here (to the end of `T0`)
+ // ∨
+ // [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, CTa_0, CTa_1, ..., CTa_m
+ // \________ ________/
+ // \/
+ // `n = buckets - 1`, i.e. `RawTable::buckets() - 1`
+ //
+ // where: T0...T_n - our stored data;
+ // CT0...CT_n - control bytes or metadata for `data`.
+ // CTa_0...CTa_m - additional control bytes, where `m = Group::WIDTH - 1` (so that the search
+ // with loading `Group` bytes from the heap works properly, even if the result
+ // of `h1(hash) & self.bucket_mask` is equal to `self.bucket_mask`). See also
+ // `RawTableInner::set_ctrl` function.
+ //
+ // P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
+ // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
+ self.table.ctrl.cast()
}
- /// Returns pointer to one past last element of data table.
+ /// Returns pointer to start of data table.
#[inline]
- pub unsafe fn data_end(&self) -> NonNull<T> {
- NonNull::new_unchecked(self.table.ctrl.as_ptr().cast())
+ #[cfg(any(feature = "raw", feature = "nightly"))]
+ pub unsafe fn data_start(&self) -> NonNull<T> {
+ NonNull::new_unchecked(self.data_end().as_ptr().wrapping_sub(self.buckets()))
}
- /// Returns pointer to start of data table.
+ /// Return the information about memory allocated by the table.
+ ///
+ /// `RawTable` allocates single memory block to store both data and metadata.
+ /// This function returns allocation size and alignment and the beginning of the area.
+ /// These are the arguments which will be passed to `dealloc` when the table is dropped.
+ ///
+ /// This function might be useful for memory profiling.
#[inline]
- #[cfg(feature = "nightly")]
- pub unsafe fn data_start(&self) -> *mut T {
- self.data_end().as_ptr().wrapping_sub(self.buckets())
+ #[cfg(feature = "raw")]
+ pub fn allocation_info(&self) -> (NonNull<u8>, Layout) {
+ // SAFETY: We use the same `table_layout` that was used to allocate
+ // this table.
+ unsafe { self.table.allocation_info_or_zero(Self::TABLE_LAYOUT) }
}
/// Returns the index of a bucket from a `Bucket`.
@@ -516,8 +968,55 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
}
/// Returns a pointer to an element in the table.
+ ///
+ /// The caller must ensure that the `RawTable` outlives the returned [`Bucket<T>`],
+ /// otherwise using it may result in [`undefined behavior`].
+ ///
+ /// # Safety
+ ///
+ /// If `mem::size_of::<T>() != 0`, then the caller of this function must observe the
+ /// following safety rules:
+ ///
+ /// * The table must already be allocated;
+ ///
+ /// * The `index` must not be greater than the number returned by the [`RawTable::buckets`]
+ /// function, i.e. `(index + 1) <= self.buckets()`.
+ ///
+ /// It is safe to call this function with index of zero (`index == 0`) on a table that has
+ /// not been allocated, but using the returned [`Bucket`] results in [`undefined behavior`].
+ ///
+ /// If `mem::size_of::<T>() == 0`, then the only requirement is that the `index` must
+ /// not be greater than the number returned by the [`RawTable::buckets`] function, i.e.
+ /// `(index + 1) <= self.buckets()`.
+ ///
+ /// [`RawTable::buckets`]: RawTable::buckets
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
pub unsafe fn bucket(&self, index: usize) -> Bucket<T> {
+ // If mem::size_of::<T>() != 0 then return a pointer to the `element` in the `data part` of the table
+ // (we start counting from "0", so that in the expression T[n], the "n" index actually one less than
+ // the "buckets" number of our `RawTable`, i.e. "n = RawTable::buckets() - 1"):
+ //
+ // `table.bucket(3).as_ptr()` returns a pointer that points here in the `data`
+ // part of the `RawTable`, i.e. to the start of T3 (see `Bucket::as_ptr`)
+ // |
+ // | `base = self.data_end()` points here
+ // | (to the start of CT0 or to the end of T0)
+ // v v
+ // [Pad], T_n, ..., |T3|, T2, T1, T0, |CT0, CT1, CT2, CT3, ..., CT_n, CTa_0, CTa_1, ..., CTa_m
+ // ^ \__________ __________/
+ // `table.bucket(3)` returns a pointer that points \/
+ // here in the `data` part of the `RawTable` (to additional control bytes
+ // the end of T3) `m = Group::WIDTH - 1`
+ //
+ // where: T0...T_n - our stored data;
+ // CT0...CT_n - control bytes or metadata for `data`;
+ // CTa_0...CTa_m - additional control bytes (so that the search with loading `Group` bytes from
+ // the heap works properly, even if the result of `h1(hash) & self.table.bucket_mask`
+ // is equal to `self.table.bucket_mask`). See also `RawTableInner::set_ctrl` function.
+ //
+ // P.S. `h1(hash) & self.table.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
+ // of buckets is a power of two, and `self.table.bucket_mask = self.buckets() - 1`.
debug_assert_ne!(self.table.bucket_mask, 0);
debug_assert!(index < self.buckets());
Bucket::from_base_index(self.data_end(), index)
@@ -525,8 +1024,7 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
/// Erases an element from the table without dropping it.
#[cfg_attr(feature = "inline-more", inline)]
- #[deprecated(since = "0.8.1", note = "use erase or remove instead")]
- pub unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) {
+ unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) {
let index = self.bucket_index(item);
self.table.erase(index);
}
@@ -534,7 +1032,6 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
/// Erases an element from the table, dropping it in place.
#[cfg_attr(feature = "inline-more", inline)]
#[allow(clippy::needless_pass_by_value)]
- #[allow(deprecated)]
pub unsafe fn erase(&mut self, item: Bucket<T>) {
// Erase the element from the table first since drop might panic.
self.erase_no_drop(&item);
@@ -558,12 +1055,18 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
}
/// Removes an element from the table, returning it.
+ ///
+ /// This also returns an `InsertSlot` pointing to the newly free bucket.
#[cfg_attr(feature = "inline-more", inline)]
#[allow(clippy::needless_pass_by_value)]
- #[allow(deprecated)]
- pub unsafe fn remove(&mut self, item: Bucket<T>) -> T {
+ pub unsafe fn remove(&mut self, item: Bucket<T>) -> (T, InsertSlot) {
self.erase_no_drop(&item);
- item.read()
+ (
+ item.read(),
+ InsertSlot {
+ index: self.bucket_index(&item),
+ },
+ )
}
/// Finds and removes an element from the table, returning it.
@@ -571,7 +1074,7 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
pub fn remove_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<T> {
// Avoid `Option::map` because it bloats LLVM IR.
match self.find(hash, eq) {
- Some(bucket) => Some(unsafe { self.remove(bucket) }),
+ Some(bucket) => Some(unsafe { self.remove(bucket).0 }),
None => None,
}
}
@@ -585,18 +1088,17 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
/// Removes all elements from the table without freeing the backing memory.
#[cfg_attr(feature = "inline-more", inline)]
pub fn clear(&mut self) {
+ if self.is_empty() {
+ // Special case empty table to avoid surprising O(capacity) time.
+ return;
+ }
// Ensure that the table is reset even if one of the drops panic
let mut self_ = guard(self, |self_| self_.clear_no_drop());
unsafe {
- self_.drop_elements();
- }
- }
-
- unsafe fn drop_elements(&mut self) {
- if mem::needs_drop::<T>() && !self.is_empty() {
- for item in self.iter() {
- item.drop();
- }
+ // SAFETY: ScopeGuard sets to zero the `items` field of the table
+ // even in case of panic during the dropping of the elements so
+ // that there will be no double drop of the elements.
+ self_.table.drop_elements::<T>();
}
}
@@ -607,7 +1109,16 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
// space for.
let min_size = usize::max(self.table.items, min_size);
if min_size == 0 {
- *self = Self::new_in(self.table.alloc.clone());
+ let mut old_inner = mem::replace(&mut self.table, RawTableInner::NEW);
+ unsafe {
+ // SAFETY:
+ // 1. We call the function only once;
+ // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
+ // and [`TableLayout`] that were used to allocate this table.
+ // 3. If any elements' drop function panics, then there will only be a memory leak,
+ // because we have replaced the inner table with a new one.
+ old_inner.drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
+ }
return;
}
@@ -624,14 +1135,33 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
if min_buckets < self.buckets() {
// Fast path if the table is empty
if self.table.items == 0 {
- *self = Self::with_capacity_in(min_size, self.table.alloc.clone());
+ let new_inner =
+ RawTableInner::with_capacity(&self.alloc, Self::TABLE_LAYOUT, min_size);
+ let mut old_inner = mem::replace(&mut self.table, new_inner);
+ unsafe {
+ // SAFETY:
+ // 1. We call the function only once;
+ // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
+ // and [`TableLayout`] that were used to allocate this table.
+ // 3. If any elements' drop function panics, then there will only be a memory leak,
+ // because we have replaced the inner table with a new one.
+ old_inner.drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
+ }
} else {
// Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
- if self
- .resize(min_size, hasher, Fallibility::Infallible)
- .is_err()
- {
- unsafe { hint::unreachable_unchecked() }
+ unsafe {
+ // SAFETY:
+ // 1. We know for sure that `min_size >= self.table.items`.
+ // 2. The [`RawTableInner`] must already have properly initialized control bytes since
+ // we will never expose RawTable::new_uninitialized in a public API.
+ if self
+ .resize(min_size, hasher, Fallibility::Infallible)
+ .is_err()
+ {
+ // SAFETY: The result of calling the `resize` function cannot be an error
+ // because `fallibility == Fallibility::Infallible.
+ hint::unreachable_unchecked()
+ }
}
}
}
@@ -641,13 +1171,18 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
/// without reallocation.
#[cfg_attr(feature = "inline-more", inline)]
pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) {
- if additional > self.table.growth_left {
+ if unlikely(additional > self.table.growth_left) {
// Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
- if self
- .reserve_rehash(additional, hasher, Fallibility::Infallible)
- .is_err()
- {
- unsafe { hint::unreachable_unchecked() }
+ unsafe {
+ // SAFETY: The [`RawTableInner`] must already have properly initialized control
+ // bytes since we will never expose RawTable::new_uninitialized in a public API.
+ if self
+ .reserve_rehash(additional, hasher, Fallibility::Infallible)
+ .is_err()
+ {
+ // SAFETY: All allocation errors will be caught inside `RawTableInner::reserve_rehash`.
+ hint::unreachable_unchecked()
+ }
}
}
}
@@ -661,28 +1196,45 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
hasher: impl Fn(&T) -> u64,
) -> Result<(), TryReserveError> {
if additional > self.table.growth_left {
- self.reserve_rehash(additional, hasher, Fallibility::Fallible)
+ // SAFETY: The [`RawTableInner`] must already have properly initialized control
+ // bytes since we will never expose RawTable::new_uninitialized in a public API.
+ unsafe { self.reserve_rehash(additional, hasher, Fallibility::Fallible) }
} else {
Ok(())
}
}
/// Out-of-line slow path for `reserve` and `try_reserve`.
+ ///
+ /// # Safety
+ ///
+ /// The [`RawTableInner`] must have properly initialized control bytes,
+ /// otherwise calling this function results in [`undefined behavior`]
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[cold]
#[inline(never)]
- fn reserve_rehash(
+ unsafe fn reserve_rehash(
&mut self,
additional: usize,
hasher: impl Fn(&T) -> u64,
fallibility: Fallibility,
) -> Result<(), TryReserveError> {
unsafe {
+ // SAFETY:
+ // 1. We know for sure that `alloc` and `layout` matches the [`Allocator`] and
+ // [`TableLayout`] that were used to allocate this table.
+ // 2. The `drop` function is the actual drop function of the elements stored in
+ // the table.
+ // 3. The caller ensures that the control bytes of the `RawTableInner`
+ // are already initialized.
self.table.reserve_rehash_inner(
+ &self.alloc,
additional,
&|table, index| hasher(table.bucket::<T>(index).as_ref()),
fallibility,
- TableLayout::new::<T>(),
- if mem::needs_drop::<T>() {
+ Self::TABLE_LAYOUT,
+ if T::NEEDS_DROP {
Some(mem::transmute(ptr::drop_in_place::<T> as unsafe fn(*mut T)))
} else {
None
@@ -693,20 +1245,50 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
/// Allocates a new table of a different size and moves the contents of the
/// current table into it.
- fn resize(
+ ///
+ /// # Safety
+ ///
+ /// The [`RawTableInner`] must have properly initialized control bytes,
+ /// otherwise calling this function results in [`undefined behavior`]
+ ///
+ /// The caller of this function must ensure that `capacity >= self.table.items`
+ /// otherwise:
+ ///
+ /// * If `self.table.items != 0`, calling of this function with `capacity`
+ /// equal to 0 (`capacity == 0`) results in [`undefined behavior`].
+ ///
+ /// * If `capacity_to_buckets(capacity) < Group::WIDTH` and
+ /// `self.table.items > capacity_to_buckets(capacity)`
+ /// calling this function results in [`undefined behavior`].
+ ///
+ /// * If `capacity_to_buckets(capacity) >= Group::WIDTH` and
+ /// `self.table.items > capacity_to_buckets(capacity)`
+ /// calling this function are never return (will go into an
+ /// infinite loop).
+ ///
+ /// See [`RawTableInner::find_insert_slot`] for more information.
+ ///
+ /// [`RawTableInner::find_insert_slot`]: RawTableInner::find_insert_slot
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ unsafe fn resize(
&mut self,
capacity: usize,
hasher: impl Fn(&T) -> u64,
fallibility: Fallibility,
) -> Result<(), TryReserveError> {
- unsafe {
- self.table.resize_inner(
- capacity,
- &|table, index| hasher(table.bucket::<T>(index).as_ref()),
- fallibility,
- TableLayout::new::<T>(),
- )
- }
+ // SAFETY:
+ // 1. The caller of this function guarantees that `capacity >= self.table.items`.
+ // 2. We know for sure that `alloc` and `layout` matches the [`Allocator`] and
+ // [`TableLayout`] that were used to allocate this table.
+ // 3. The caller ensures that the control bytes of the `RawTableInner`
+ // are already initialized.
+ self.table.resize_inner(
+ &self.alloc,
+ capacity,
+ &|table, index| hasher(table.bucket::<T>(index).as_ref()),
+ fallibility,
+ Self::TABLE_LAYOUT,
+ )
}
/// Inserts a new element into the table, and returns its raw bucket.
@@ -715,22 +1297,27 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> {
unsafe {
- let mut index = self.table.find_insert_slot(hash);
+ // SAFETY:
+ // 1. The [`RawTableInner`] must already have properly initialized control bytes since
+ // we will never expose `RawTable::new_uninitialized` in a public API.
+ //
+ // 2. We reserve additional space (if necessary) right after calling this function.
+ let mut slot = self.table.find_insert_slot(hash);
- // We can avoid growing the table once we have reached our load
- // factor if we are replacing a tombstone. This works since the
- // number of EMPTY slots does not change in this case.
- let old_ctrl = *self.table.ctrl(index);
+ // We can avoid growing the table once we have reached our load factor if we are replacing
+ // a tombstone. This works since the number of EMPTY slots does not change in this case.
+ //
+ // SAFETY: The function is guaranteed to return [`InsertSlot`] that contains an index
+ // in the range `0..=self.buckets()`.
+ let old_ctrl = *self.table.ctrl(slot.index);
if unlikely(self.table.growth_left == 0 && special_is_empty(old_ctrl)) {
self.reserve(1, hasher);
- index = self.table.find_insert_slot(hash);
+ // SAFETY: We know for sure that `RawTableInner` has control bytes
+ // initialized and that there is extra space in the table.
+ slot = self.table.find_insert_slot(hash);
}
- self.table.record_item_insert_at(index, old_ctrl, hash);
-
- let bucket = self.bucket(index);
- bucket.write(value);
- bucket
+ self.insert_in_slot(hash, slot, value)
}
}
@@ -796,9 +1383,9 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
{
let index = self.bucket_index(&bucket);
let old_ctrl = *self.table.ctrl(index);
- debug_assert!(is_full(old_ctrl));
+ debug_assert!(self.is_bucket_full(index));
let old_growth_left = self.table.growth_left;
- let item = self.remove(bucket);
+ let item = self.remove(bucket).0;
if let Some(new_item) = f(item) {
self.table.growth_left = old_growth_left;
self.table.set_ctrl(index, old_ctrl);
@@ -810,17 +1397,78 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
}
}
+ /// Searches for an element in the table. If the element is not found,
+ /// returns `Err` with the position of a slot where an element with the
+ /// same hash could be inserted.
+ ///
+ /// This function may resize the table if additional space is required for
+ /// inserting an element.
+ #[inline]
+ pub fn find_or_find_insert_slot(
+ &mut self,
+ hash: u64,
+ mut eq: impl FnMut(&T) -> bool,
+ hasher: impl Fn(&T) -> u64,
+ ) -> Result<Bucket<T>, InsertSlot> {
+ self.reserve(1, hasher);
+
+ unsafe {
+ // SAFETY:
+ // 1. We know for sure that there is at least one empty `bucket` in the table.
+ // 2. The [`RawTableInner`] must already have properly initialized control bytes since we will
+ // never expose `RawTable::new_uninitialized` in a public API.
+ // 3. The `find_or_find_insert_slot_inner` function returns the `index` of only the full bucket,
+ // which is in the range `0..self.buckets()` (since there is at least one empty `bucket` in
+ // the table), so calling `self.bucket(index)` and `Bucket::as_ref` is safe.
+ match self
+ .table
+ .find_or_find_insert_slot_inner(hash, &mut |index| eq(self.bucket(index).as_ref()))
+ {
+ // SAFETY: See explanation above.
+ Ok(index) => Ok(self.bucket(index)),
+ Err(slot) => Err(slot),
+ }
+ }
+ }
+
+ /// Inserts a new element into the table in the given slot, and returns its
+ /// raw bucket.
+ ///
+ /// # Safety
+ ///
+ /// `slot` must point to a slot previously returned by
+ /// `find_or_find_insert_slot`, and no mutation of the table must have
+ /// occurred since that call.
+ #[inline]
+ pub unsafe fn insert_in_slot(&mut self, hash: u64, slot: InsertSlot, value: T) -> Bucket<T> {
+ let old_ctrl = *self.table.ctrl(slot.index);
+ self.table.record_item_insert_at(slot.index, old_ctrl, hash);
+
+ let bucket = self.bucket(slot.index);
+ bucket.write(value);
+ bucket
+ }
+
/// Searches for an element in the table.
#[inline]
pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
- let result = self.table.find_inner(hash, &mut |index| unsafe {
- eq(self.bucket(index).as_ref())
- });
-
- // Avoid `Option::map` because it bloats LLVM IR.
- match result {
- Some(index) => Some(unsafe { self.bucket(index) }),
- None => None,
+ unsafe {
+ // SAFETY:
+ // 1. The [`RawTableInner`] must already have properly initialized control bytes since we
+ // will never expose `RawTable::new_uninitialized` in a public API.
+ // 1. The `find_inner` function returns the `index` of only the full bucket, which is in
+ // the range `0..self.buckets()`, so calling `self.bucket(index)` and `Bucket::as_ref`
+ // is safe.
+ let result = self
+ .table
+ .find_inner(hash, &mut |index| eq(self.bucket(index).as_ref()));
+
+ // Avoid `Option::map` because it bloats LLVM IR.
+ match result {
+ // SAFETY: See explanation above.
+ Some(index) => Some(self.bucket(index)),
+ None => None,
+ }
}
}
@@ -928,17 +1576,27 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
self.table.bucket_mask + 1
}
+ /// Checks whether the bucket at `index` is full.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure `index` is less than the number of buckets.
+ #[inline]
+ pub unsafe fn is_bucket_full(&self, index: usize) -> bool {
+ self.table.is_bucket_full(index)
+ }
+
/// Returns an iterator over every element in the table. It is up to
/// the caller to ensure that the `RawTable` outlives the `RawIter`.
/// Because we cannot make the `next` method unsafe on the `RawIter`
/// struct, we have to make the `iter` method unsafe.
#[inline]
pub unsafe fn iter(&self) -> RawIter<T> {
- let data = Bucket::from_base_index(self.data_end(), 0);
- RawIter {
- iter: RawIterRange::new(self.table.ctrl.as_ptr(), data, self.table.buckets()),
- items: self.table.items,
- }
+ // SAFETY:
+ // 1. The caller must uphold the safety contract for `iter` method.
+ // 2. The [`RawTableInner`] must already have properly initialized control bytes since
+ // we will never expose RawTable::new_uninitialized in a public API.
+ self.table.iter()
}
/// Returns an iterator over occupied buckets that could match a given hash.
@@ -952,7 +1610,7 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
/// `RawIterHash` struct, we have to make the `iter_hash` method unsafe.
#[cfg_attr(feature = "inline-more", inline)]
#[cfg(feature = "raw")]
- pub unsafe fn iter_hash(&self, hash: u64) -> RawIterHash<'_, T, A> {
+ pub unsafe fn iter_hash(&self, hash: u64) -> RawIterHash<T> {
RawIterHash::new(self, hash)
}
@@ -978,8 +1636,8 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
debug_assert_eq!(iter.len(), self.len());
RawDrain {
iter,
- table: ManuallyDrop::new(mem::replace(self, Self::new_in(self.table.alloc.clone()))),
- orig_table: NonNull::from(self),
+ table: mem::replace(&mut self.table, RawTableInner::NEW),
+ orig_table: NonNull::from(&mut self.table),
marker: PhantomData,
}
}
@@ -993,31 +1651,31 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
pub unsafe fn into_iter_from(self, iter: RawIter<T>) -> RawIntoIter<T, A> {
debug_assert_eq!(iter.len(), self.len());
- let alloc = self.table.alloc.clone();
let allocation = self.into_allocation();
RawIntoIter {
iter,
allocation,
marker: PhantomData,
- alloc,
}
}
/// Converts the table into a raw allocation. The contents of the table
/// should be dropped using a `RawIter` before freeing the allocation.
#[cfg_attr(feature = "inline-more", inline)]
- pub(crate) fn into_allocation(self) -> Option<(NonNull<u8>, Layout)> {
+ pub(crate) fn into_allocation(self) -> Option<(NonNull<u8>, Layout, A)> {
let alloc = if self.table.is_empty_singleton() {
None
} else {
// Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
- let (layout, ctrl_offset) = match calculate_layout::<T>(self.table.buckets()) {
- Some(lco) => lco,
- None => unsafe { hint::unreachable_unchecked() },
- };
+ let (layout, ctrl_offset) =
+ match Self::TABLE_LAYOUT.calculate_layout_for(self.table.buckets()) {
+ Some(lco) => lco,
+ None => unsafe { hint::unreachable_unchecked() },
+ };
Some((
unsafe { NonNull::new_unchecked(self.table.ctrl.as_ptr().sub(ctrl_offset)) },
layout,
+ unsafe { ptr::read(&self.alloc) },
))
};
mem::forget(self);
@@ -1025,41 +1683,62 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
}
}
-unsafe impl<T, A: Allocator + Clone> Send for RawTable<T, A>
+unsafe impl<T, A: Allocator> Send for RawTable<T, A>
where
T: Send,
A: Send,
{
}
-unsafe impl<T, A: Allocator + Clone> Sync for RawTable<T, A>
+unsafe impl<T, A: Allocator> Sync for RawTable<T, A>
where
T: Sync,
A: Sync,
{
}
-impl<A> RawTableInner<A> {
+impl RawTableInner {
+ const NEW: Self = RawTableInner::new();
+
+ /// Creates a new empty hash table without allocating any memory.
+ ///
+ /// In effect this returns a table with exactly 1 bucket. However we can
+ /// leave the data pointer dangling since that bucket is never accessed
+ /// due to our load factor forcing us to always have at least 1 free bucket.
#[inline]
- const fn new_in(alloc: A) -> Self {
+ const fn new() -> Self {
Self {
// Be careful to cast the entire slice to a raw pointer.
ctrl: unsafe { NonNull::new_unchecked(Group::static_empty() as *const _ as *mut u8) },
bucket_mask: 0,
items: 0,
growth_left: 0,
- alloc,
}
}
}
-impl<A: Allocator + Clone> RawTableInner<A> {
+impl RawTableInner {
+ /// Allocates a new [`RawTableInner`] with the given number of buckets.
+ /// The control bytes and buckets are left uninitialized.
+ ///
+ /// # Safety
+ ///
+ /// The caller of this function must ensure that the `buckets` is power of two
+ /// and also initialize all control bytes of the length `self.bucket_mask + 1 +
+ /// Group::WIDTH` with the [`EMPTY`] bytes.
+ ///
+ /// See also [`Allocator`] API for other safety concerns.
+ ///
+ /// [`Allocator`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html
#[cfg_attr(feature = "inline-more", inline)]
- unsafe fn new_uninitialized(
- alloc: A,
+ unsafe fn new_uninitialized<A>(
+ alloc: &A,
table_layout: TableLayout,
buckets: usize,
fallibility: Fallibility,
- ) -> Result<Self, TryReserveError> {
+ ) -> Result<Self, TryReserveError>
+ where
+ A: Allocator,
+ {
debug_assert!(buckets.is_power_of_two());
// Avoid `Option::ok_or_else` because it bloats LLVM IR.
@@ -1068,45 +1747,48 @@ impl<A: Allocator + Clone> RawTableInner<A> {
None => return Err(fallibility.capacity_overflow()),
};
- // We need an additional check to ensure that the allocation doesn't
- // exceed `isize::MAX`. We can skip this check on 64-bit systems since
- // such allocations will never succeed anyways.
- //
- // This mirrors what Vec does in the standard library.
- if mem::size_of::<usize>() < 8 && layout.size() > isize::MAX as usize {
- return Err(fallibility.capacity_overflow());
- }
-
- let ptr: NonNull<u8> = match do_alloc(&alloc, layout) {
+ let ptr: NonNull<u8> = match do_alloc(alloc, layout) {
Ok(block) => block.cast(),
Err(_) => return Err(fallibility.alloc_err(layout)),
};
+ // SAFETY: null pointer will be caught in above check
let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset));
Ok(Self {
ctrl,
bucket_mask: buckets - 1,
items: 0,
growth_left: bucket_mask_to_capacity(buckets - 1),
- alloc,
})
}
+ /// Attempts to allocate a new [`RawTableInner`] with at least enough
+ /// capacity for inserting the given number of elements without reallocating.
+ ///
+ /// All the control bytes are initialized with the [`EMPTY`] bytes.
#[inline]
- fn fallible_with_capacity(
- alloc: A,
+ fn fallible_with_capacity<A>(
+ alloc: &A,
table_layout: TableLayout,
capacity: usize,
fallibility: Fallibility,
- ) -> Result<Self, TryReserveError> {
+ ) -> Result<Self, TryReserveError>
+ where
+ A: Allocator,
+ {
if capacity == 0 {
- Ok(Self::new_in(alloc))
+ Ok(Self::NEW)
} else {
+ // SAFETY: We checked that we could successfully allocate the new table, and then
+ // initialized all control bytes with the constant `EMPTY` byte.
unsafe {
let buckets =
capacity_to_buckets(capacity).ok_or_else(|| fallibility.capacity_overflow())?;
let result = Self::new_uninitialized(alloc, table_layout, buckets, fallibility)?;
+ // SAFETY: We checked that the table is allocated and therefore the table already has
+ // `self.bucket_mask + 1 + Group::WIDTH` number of control bytes (see TableLayout::calculate_layout_for)
+ // so writing `self.num_ctrl_bytes() == bucket_mask + 1 + Group::WIDTH` bytes is safe.
result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes());
Ok(result)
@@ -1114,66 +1796,397 @@ impl<A: Allocator + Clone> RawTableInner<A> {
}
}
- /// Searches for an empty or deleted bucket which is suitable for inserting
- /// a new element and sets the hash for that slot.
+ /// Allocates a new [`RawTableInner`] with at least enough capacity for inserting
+ /// the given number of elements without reallocating.
+ ///
+ /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program
+ /// in case of allocation error. Use [`fallible_with_capacity`] instead if you want to
+ /// handle memory allocation failure.
+ ///
+ /// All the control bytes are initialized with the [`EMPTY`] bytes.
+ ///
+ /// [`fallible_with_capacity`]: RawTableInner::fallible_with_capacity
+ /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
+ fn with_capacity<A>(alloc: &A, table_layout: TableLayout, capacity: usize) -> Self
+ where
+ A: Allocator,
+ {
+ // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
+ match Self::fallible_with_capacity(alloc, table_layout, capacity, Fallibility::Infallible) {
+ Ok(table_inner) => table_inner,
+ // SAFETY: All allocation errors will be caught inside `RawTableInner::new_uninitialized`.
+ Err(_) => unsafe { hint::unreachable_unchecked() },
+ }
+ }
+
+ /// Fixes up an insertion slot returned by the [`RawTableInner::find_insert_slot_in_group`] method.
+ ///
+ /// In tables smaller than the group width (`self.buckets() < Group::WIDTH`), trailing control
+ /// bytes outside the range of the table are filled with [`EMPTY`] entries. These will unfortunately
+ /// trigger a match of [`RawTableInner::find_insert_slot_in_group`] function. This is because
+ /// the `Some(bit)` returned by `group.match_empty_or_deleted().lowest_set_bit()` after masking
+ /// (`(probe_seq.pos + bit) & self.bucket_mask`) may point to a full bucket that is already occupied.
+ /// We detect this situation here and perform a second scan starting at the beginning of the table.
+ /// This second scan is guaranteed to find an empty slot (due to the load factor) before hitting the
+ /// trailing control bytes (containing [`EMPTY`] bytes).
+ ///
+ /// If this function is called correctly, it is guaranteed to return [`InsertSlot`] with an
+ /// index of an empty or deleted bucket in the range `0..self.buckets()` (see `Warning` and
+ /// `Safety`).
+ ///
+ /// # Warning
+ ///
+ /// The table must have at least 1 empty or deleted `bucket`, otherwise if the table is less than
+ /// the group width (`self.buckets() < Group::WIDTH`) this function returns an index outside of the
+ /// table indices range `0..self.buckets()` (`0..=self.bucket_mask`). Attempt to write data at that
+ /// index will cause immediate [`undefined behavior`].
+ ///
+ /// # Safety
+ ///
+ /// The safety rules are directly derived from the safety rules for [`RawTableInner::ctrl`] method.
+ /// Thus, in order to uphold those safety contracts, as well as for the correct logic of the work
+ /// of this crate, the following rules are necessary and sufficient:
///
- /// There must be at least 1 empty bucket in the table.
+ /// * The [`RawTableInner`] must have properly initialized control bytes otherwise calling this
+ /// function results in [`undefined behavior`].
+ ///
+ /// * This function must only be used on insertion slots found by [`RawTableInner::find_insert_slot_in_group`]
+ /// (after the `find_insert_slot_in_group` function, but before insertion into the table).
+ ///
+ /// * The `index` must not be greater than the `self.bucket_mask`, i.e. `(index + 1) <= self.buckets()`
+ /// (this one is provided by the [`RawTableInner::find_insert_slot_in_group`] function).
+ ///
+ /// Calling this function with an index not provided by [`RawTableInner::find_insert_slot_in_group`]
+ /// may result in [`undefined behavior`] even if the index satisfies the safety rules of the
+ /// [`RawTableInner::ctrl`] function (`index < self.bucket_mask + 1 + Group::WIDTH`).
+ ///
+ /// [`RawTableInner::ctrl`]: RawTableInner::ctrl
+ /// [`RawTableInner::find_insert_slot_in_group`]: RawTableInner::find_insert_slot_in_group
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
- unsafe fn prepare_insert_slot(&self, hash: u64) -> (usize, u8) {
- let index = self.find_insert_slot(hash);
+ unsafe fn fix_insert_slot(&self, mut index: usize) -> InsertSlot {
+ // SAFETY: The caller of this function ensures that `index` is in the range `0..=self.bucket_mask`.
+ if unlikely(self.is_bucket_full(index)) {
+ debug_assert!(self.bucket_mask < Group::WIDTH);
+ // SAFETY:
+ //
+ // * Since the caller of this function ensures that the control bytes are properly
+ // initialized and `ptr = self.ctrl(0)` points to the start of the array of control
+ // bytes, therefore: `ctrl` is valid for reads, properly aligned to `Group::WIDTH`
+ // and points to the properly initialized control bytes (see also
+ // `TableLayout::calculate_layout_for` and `ptr::read`);
+ //
+ // * Because the caller of this function ensures that the index was provided by the
+ // `self.find_insert_slot_in_group()` function, so for for tables larger than the
+ // group width (self.buckets() >= Group::WIDTH), we will never end up in the given
+ // branch, since `(probe_seq.pos + bit) & self.bucket_mask` in `find_insert_slot_in_group`
+ // cannot return a full bucket index. For tables smaller than the group width, calling
+ // the `unwrap_unchecked` function is also safe, as the trailing control bytes outside
+ // the range of the table are filled with EMPTY bytes (and we know for sure that there
+ // is at least one FULL bucket), so this second scan either finds an empty slot (due to
+ // the load factor) or hits the trailing control bytes (containing EMPTY).
+ index = Group::load_aligned(self.ctrl(0))
+ .match_empty_or_deleted()
+ .lowest_set_bit()
+ .unwrap_unchecked();
+ }
+ InsertSlot { index }
+ }
+
+ /// Finds the position to insert something in a group.
+ ///
+ /// **This may have false positives and must be fixed up with `fix_insert_slot`
+ /// before it's used.**
+ ///
+ /// The function is guaranteed to return the index of an empty or deleted [`Bucket`]
+ /// in the range `0..self.buckets()` (`0..=self.bucket_mask`).
+ #[inline]
+ fn find_insert_slot_in_group(&self, group: &Group, probe_seq: &ProbeSeq) -> Option<usize> {
+ let bit = group.match_empty_or_deleted().lowest_set_bit();
+
+ if likely(bit.is_some()) {
+ // This is the same as `(probe_seq.pos + bit) % self.buckets()` because the number
+ // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
+ Some((probe_seq.pos + bit.unwrap()) & self.bucket_mask)
+ } else {
+ None
+ }
+ }
+
+ /// Searches for an element in the table, or a potential slot where that element could
+ /// be inserted (an empty or deleted [`Bucket`] index).
+ ///
+ /// This uses dynamic dispatch to reduce the amount of code generated, but that is
+ /// eliminated by LLVM optimizations.
+ ///
+ /// This function does not make any changes to the `data` part of the table, or any
+ /// changes to the `items` or `growth_left` field of the table.
+ ///
+ /// The table must have at least 1 empty or deleted `bucket`, otherwise, if the
+ /// `eq: &mut dyn FnMut(usize) -> bool` function does not return `true`, this function
+ /// will never return (will go into an infinite loop) for tables larger than the group
+ /// width, or return an index outside of the table indices range if the table is less
+ /// than the group width.
+ ///
+ /// This function is guaranteed to provide the `eq: &mut dyn FnMut(usize) -> bool`
+ /// function with only `FULL` buckets' indices and return the `index` of the found
+ /// element (as `Ok(index)`). If the element is not found and there is at least 1
+ /// empty or deleted [`Bucket`] in the table, the function is guaranteed to return
+ /// [InsertSlot] with an index in the range `0..self.buckets()`, but in any case,
+ /// if this function returns [`InsertSlot`], it will contain an index in the range
+ /// `0..=self.buckets()`.
+ ///
+ /// # Safety
+ ///
+ /// The [`RawTableInner`] must have properly initialized control bytes otherwise calling
+ /// this function results in [`undefined behavior`].
+ ///
+ /// Attempt to write data at the [`InsertSlot`] returned by this function when the table is
+ /// less than the group width and if there was not at least one empty or deleted bucket in
+ /// the table will cause immediate [`undefined behavior`]. This is because in this case the
+ /// function will return `self.bucket_mask + 1` as an index due to the trailing [`EMPTY]
+ /// control bytes outside the table range.
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[inline]
+ unsafe fn find_or_find_insert_slot_inner(
+ &self,
+ hash: u64,
+ eq: &mut dyn FnMut(usize) -> bool,
+ ) -> Result<usize, InsertSlot> {
+ let mut insert_slot = None;
+
+ let h2_hash = h2(hash);
+ let mut probe_seq = self.probe_seq(hash);
+
+ loop {
+ // SAFETY:
+ // * Caller of this function ensures that the control bytes are properly initialized.
+ //
+ // * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
+ // of the table due to masking with `self.bucket_mask` and also because mumber of
+ // buckets is a power of two (see `self.probe_seq` function).
+ //
+ // * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
+ // call `Group::load` due to the extended control bytes range, which is
+ // `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
+ // byte will never be read for the allocated table);
+ //
+ // * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
+ // always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
+ // bytes, which is safe (see RawTableInner::new).
+ let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
+
+ for bit in group.match_byte(h2_hash) {
+ let index = (probe_seq.pos + bit) & self.bucket_mask;
+
+ if likely(eq(index)) {
+ return Ok(index);
+ }
+ }
+
+ // We didn't find the element we were looking for in the group, try to get an
+ // insertion slot from the group if we don't have one yet.
+ if likely(insert_slot.is_none()) {
+ insert_slot = self.find_insert_slot_in_group(&group, &probe_seq);
+ }
+
+ // Only stop the search if the group contains at least one empty element.
+ // Otherwise, the element that we are looking for might be in a following group.
+ if likely(group.match_empty().any_bit_set()) {
+ // We must have found a insert slot by now, since the current group contains at
+ // least one. For tables smaller than the group width, there will still be an
+ // empty element in the current (and only) group due to the load factor.
+ unsafe {
+ // SAFETY:
+ // * Caller of this function ensures that the control bytes are properly initialized.
+ //
+ // * We use this function with the slot / index found by `self.find_insert_slot_in_group`
+ return Err(self.fix_insert_slot(insert_slot.unwrap_unchecked()));
+ }
+ }
+
+ probe_seq.move_next(self.bucket_mask);
+ }
+ }
+
+ /// Searches for an empty or deleted bucket which is suitable for inserting a new
+ /// element and sets the hash for that slot. Returns an index of that slot and the
+ /// old control byte stored in the found index.
+ ///
+ /// This function does not check if the given element exists in the table. Also,
+ /// this function does not check if there is enough space in the table to insert
+ /// a new element. Caller of the funtion must make ensure that the table has at
+ /// least 1 empty or deleted `bucket`, otherwise this function will never return
+ /// (will go into an infinite loop) for tables larger than the group width, or
+ /// return an index outside of the table indices range if the table is less than
+ /// the group width.
+ ///
+ /// If there is at least 1 empty or deleted `bucket` in the table, the function is
+ /// guaranteed to return an `index` in the range `0..self.buckets()`, but in any case,
+ /// if this function returns an `index` it will be in the range `0..=self.buckets()`.
+ ///
+ /// This function does not make any changes to the `data` parts of the table,
+ /// or any changes to the `items` or `growth_left` field of the table.
+ ///
+ /// # Safety
+ ///
+ /// The safety rules are directly derived from the safety rules for the
+ /// [`RawTableInner::set_ctrl_h2`] and [`RawTableInner::find_insert_slot`] methods.
+ /// Thus, in order to uphold the safety contracts for that methods, as well as for
+ /// the correct logic of the work of this crate, you must observe the following rules
+ /// when calling this function:
+ ///
+ /// * The [`RawTableInner`] has already been allocated and has properly initialized
+ /// control bytes otherwise calling this function results in [`undefined behavior`].
+ ///
+ /// * The caller of this function must ensure that the "data" parts of the table
+ /// will have an entry in the returned index (matching the given hash) right
+ /// after calling this function.
+ ///
+ /// Attempt to write data at the `index` returned by this function when the table is
+ /// less than the group width and if there was not at least one empty or deleted bucket in
+ /// the table will cause immediate [`undefined behavior`]. This is because in this case the
+ /// function will return `self.bucket_mask + 1` as an index due to the trailing [`EMPTY]
+ /// control bytes outside the table range.
+ ///
+ /// The caller must independently increase the `items` field of the table, and also,
+ /// if the old control byte was [`EMPTY`], then decrease the table's `growth_left`
+ /// field, and do not change it if the old control byte was [`DELETED`].
+ ///
+ /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
+ /// or saving `element` from / into the [`RawTable`] / [`RawTableInner`].
+ ///
+ /// [`Bucket::as_ptr`]: Bucket::as_ptr
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ /// [`RawTableInner::ctrl`]: RawTableInner::ctrl
+ /// [`RawTableInner::set_ctrl_h2`]: RawTableInner::set_ctrl_h2
+ /// [`RawTableInner::find_insert_slot`]: RawTableInner::find_insert_slot
+ #[inline]
+ unsafe fn prepare_insert_slot(&mut self, hash: u64) -> (usize, u8) {
+ // SAFETY: Caller of this function ensures that the control bytes are properly initialized.
+ let index: usize = self.find_insert_slot(hash).index;
+ // SAFETY:
+ // 1. The `find_insert_slot` function either returns an `index` less than or
+ // equal to `self.buckets() = self.bucket_mask + 1` of the table, or never
+ // returns if it cannot find an empty or deleted slot.
+ // 2. The caller of this function guarantees that the table has already been
+ // allocated
let old_ctrl = *self.ctrl(index);
self.set_ctrl_h2(index, hash);
(index, old_ctrl)
}
/// Searches for an empty or deleted bucket which is suitable for inserting
- /// a new element.
+ /// a new element, returning the `index` for the new [`Bucket`].
+ ///
+ /// This function does not make any changes to the `data` part of the table, or any
+ /// changes to the `items` or `growth_left` field of the table.
+ ///
+ /// The table must have at least 1 empty or deleted `bucket`, otherwise this function
+ /// will never return (will go into an infinite loop) for tables larger than the group
+ /// width, or return an index outside of the table indices range if the table is less
+ /// than the group width.
+ ///
+ /// If there is at least 1 empty or deleted `bucket` in the table, the function is
+ /// guaranteed to return [`InsertSlot`] with an index in the range `0..self.buckets()`,
+ /// but in any case, if this function returns [`InsertSlot`], it will contain an index
+ /// in the range `0..=self.buckets()`.
///
- /// There must be at least 1 empty bucket in the table.
+ /// # Safety
+ ///
+ /// The [`RawTableInner`] must have properly initialized control bytes otherwise calling
+ /// this function results in [`undefined behavior`].
+ ///
+ /// Attempt to write data at the [`InsertSlot`] returned by this function when the table is
+ /// less than the group width and if there was not at least one empty or deleted bucket in
+ /// the table will cause immediate [`undefined behavior`]. This is because in this case the
+ /// function will return `self.bucket_mask + 1` as an index due to the trailing [`EMPTY]
+ /// control bytes outside the table range.
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
- fn find_insert_slot(&self, hash: u64) -> usize {
+ unsafe fn find_insert_slot(&self, hash: u64) -> InsertSlot {
let mut probe_seq = self.probe_seq(hash);
loop {
- unsafe {
- let group = Group::load(self.ctrl(probe_seq.pos));
- if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() {
- let result = (probe_seq.pos + bit) & self.bucket_mask;
-
- // In tables smaller than the group width, trailing control
- // bytes outside the range of the table are filled with
- // EMPTY entries. These will unfortunately trigger a
- // match, but once masked may point to a full bucket that
- // is already occupied. We detect this situation here and
- // perform a second scan starting at the beginning of the
- // table. This second scan is guaranteed to find an empty
- // slot (due to the load factor) before hitting the trailing
- // control bytes (containing EMPTY).
- if unlikely(is_full(*self.ctrl(result))) {
- debug_assert!(self.bucket_mask < Group::WIDTH);
- debug_assert_ne!(probe_seq.pos, 0);
- return Group::load_aligned(self.ctrl(0))
- .match_empty_or_deleted()
- .lowest_set_bit_nonzero();
- }
+ // SAFETY:
+ // * Caller of this function ensures that the control bytes are properly initialized.
+ //
+ // * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
+ // of the table due to masking with `self.bucket_mask` and also because mumber of
+ // buckets is a power of two (see `self.probe_seq` function).
+ //
+ // * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
+ // call `Group::load` due to the extended control bytes range, which is
+ // `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
+ // byte will never be read for the allocated table);
+ //
+ // * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
+ // always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
+ // bytes, which is safe (see RawTableInner::new).
+ let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
- return result;
+ let index = self.find_insert_slot_in_group(&group, &probe_seq);
+ if likely(index.is_some()) {
+ // SAFETY:
+ // * Caller of this function ensures that the control bytes are properly initialized.
+ //
+ // * We use this function with the slot / index found by `self.find_insert_slot_in_group`
+ unsafe {
+ return self.fix_insert_slot(index.unwrap_unchecked());
}
}
probe_seq.move_next(self.bucket_mask);
}
}
- /// Searches for an element in the table. This uses dynamic dispatch to reduce the amount of
- /// code generated, but it is eliminated by LLVM optimizations.
- #[inline]
- fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option<usize> {
+ /// Searches for an element in a table, returning the `index` of the found element.
+ /// This uses dynamic dispatch to reduce the amount of code generated, but it is
+ /// eliminated by LLVM optimizations.
+ ///
+ /// This function does not make any changes to the `data` part of the table, or any
+ /// changes to the `items` or `growth_left` field of the table.
+ ///
+ /// The table must have at least 1 empty `bucket`, otherwise, if the
+ /// `eq: &mut dyn FnMut(usize) -> bool` function does not return `true`,
+ /// this function will also never return (will go into an infinite loop).
+ ///
+ /// This function is guaranteed to provide the `eq: &mut dyn FnMut(usize) -> bool`
+ /// function with only `FULL` buckets' indices and return the `index` of the found
+ /// element as `Some(index)`, so the index will always be in the range
+ /// `0..self.buckets()`.
+ ///
+ /// # Safety
+ ///
+ /// The [`RawTableInner`] must have properly initialized control bytes otherwise calling
+ /// this function results in [`undefined behavior`].
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[inline(always)]
+ unsafe fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option<usize> {
let h2_hash = h2(hash);
let mut probe_seq = self.probe_seq(hash);
loop {
+ // SAFETY:
+ // * Caller of this function ensures that the control bytes are properly initialized.
+ //
+ // * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
+ // of the table due to masking with `self.bucket_mask`.
+ //
+ // * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
+ // call `Group::load` due to the extended control bytes range, which is
+ // `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
+ // byte will never be read for the allocated table);
+ //
+ // * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
+ // always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
+ // bytes, which is safe (see RawTableInner::new_in).
let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
for bit in group.match_byte(h2_hash) {
+ // This is the same as `(probe_seq.pos + bit) % self.buckets()` because the number
+ // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
let index = (probe_seq.pos + bit) & self.bucket_mask;
if likely(eq(index)) {
@@ -1189,12 +2202,52 @@ impl<A: Allocator + Clone> RawTableInner<A> {
}
}
+ /// Prepares for rehashing data in place (that is, without allocating new memory).
+ /// Converts all full index `control bytes` to `DELETED` and all `DELETED` control
+ /// bytes to `EMPTY`, i.e. performs the following conversion:
+ ///
+ /// - `EMPTY` control bytes -> `EMPTY`;
+ /// - `DELETED` control bytes -> `EMPTY`;
+ /// - `FULL` control bytes -> `DELETED`.
+ ///
+ /// This function does not make any changes to the `data` parts of the table,
+ /// or any changes to the `items` or `growth_left` field of the table.
+ ///
+ /// # Safety
+ ///
+ /// You must observe the following safety rules when calling this function:
+ ///
+ /// * The [`RawTableInner`] has already been allocated;
+ ///
+ /// * The caller of this function must convert the `DELETED` bytes back to `FULL`
+ /// bytes when re-inserting them into their ideal position (which was impossible
+ /// to do during the first insert due to tombstones). If the caller does not do
+ /// this, then calling this function may result in a memory leak.
+ ///
+ /// * The [`RawTableInner`] must have properly initialized control bytes otherwise
+ /// calling this function results in [`undefined behavior`].
+ ///
+ /// Calling this function on a table that has not been allocated results in
+ /// [`undefined behavior`].
+ ///
+ /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
+ /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
+ ///
+ /// [`Bucket::as_ptr`]: Bucket::as_ptr
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[allow(clippy::mut_mut)]
#[inline]
unsafe fn prepare_rehash_in_place(&mut self) {
- // Bulk convert all full control bytes to DELETED, and all DELETED
- // control bytes to EMPTY. This effectively frees up all buckets
- // containing a DELETED entry.
+ // Bulk convert all full control bytes to DELETED, and all DELETED control bytes to EMPTY.
+ // This effectively frees up all buckets containing a DELETED entry.
+ //
+ // SAFETY:
+ // 1. `i` is guaranteed to be within bounds since we are iterating from zero to `buckets - 1`;
+ // 2. Even if `i` will be `i == self.bucket_mask`, it is safe to call `Group::load_aligned`
+ // due to the extended control bytes range, which is `self.bucket_mask + 1 + Group::WIDTH`;
+ // 3. The caller of this function guarantees that [`RawTableInner`] has already been allocated;
+ // 4. We can use `Group::load_aligned` and `Group::store_aligned` here since we start from 0
+ // and go to the end with a step equal to `Group::WIDTH` (see TableLayout::calculate_layout_for).
for i in (0..self.buckets()).step_by(Group::WIDTH) {
let group = Group::load_aligned(self.ctrl(i));
let group = group.convert_special_to_empty_and_full_to_deleted();
@@ -1203,15 +2256,245 @@ impl<A: Allocator + Clone> RawTableInner<A> {
// Fix up the trailing control bytes. See the comments in set_ctrl
// for the handling of tables smaller than the group width.
- if self.buckets() < Group::WIDTH {
+ //
+ // SAFETY: The caller of this function guarantees that [`RawTableInner`]
+ // has already been allocated
+ if unlikely(self.buckets() < Group::WIDTH) {
+ // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of control bytes,
+ // so copying `self.buckets() == self.bucket_mask + 1` bytes with offset equal to
+ // `Group::WIDTH` is safe
self.ctrl(0)
.copy_to(self.ctrl(Group::WIDTH), self.buckets());
} else {
+ // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of
+ // control bytes,so copying `Group::WIDTH` bytes with offset equal
+ // to `self.buckets() == self.bucket_mask + 1` is safe
self.ctrl(0)
.copy_to(self.ctrl(self.buckets()), Group::WIDTH);
}
}
+ /// Returns an iterator over every element in the table.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result
+ /// is [`undefined behavior`]:
+ ///
+ /// * The caller has to ensure that the `RawTableInner` outlives the
+ /// `RawIter`. Because we cannot make the `next` method unsafe on
+ /// the `RawIter` struct, we have to make the `iter` method unsafe.
+ ///
+ /// * The [`RawTableInner`] must have properly initialized control bytes.
+ ///
+ /// The type `T` must be the actual type of the elements stored in the table,
+ /// otherwise using the returned [`RawIter`] results in [`undefined behavior`].
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[inline]
+ unsafe fn iter<T>(&self) -> RawIter<T> {
+ // SAFETY:
+ // 1. Since the caller of this function ensures that the control bytes
+ // are properly initialized and `self.data_end()` points to the start
+ // of the array of control bytes, therefore: `ctrl` is valid for reads,
+ // properly aligned to `Group::WIDTH` and points to the properly initialized
+ // control bytes.
+ // 2. `data` bucket index in the table is equal to the `ctrl` index (i.e.
+ // equal to zero).
+ // 3. We pass the exact value of buckets of the table to the function.
+ //
+ // `ctrl` points here (to the start
+ // of the first control byte `CT0`)
+ // ∨
+ // [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, CTa_0, CTa_1, ..., CTa_m
+ // \________ ________/
+ // \/
+ // `n = buckets - 1`, i.e. `RawTableInner::buckets() - 1`
+ //
+ // where: T0...T_n - our stored data;
+ // CT0...CT_n - control bytes or metadata for `data`.
+ // CTa_0...CTa_m - additional control bytes, where `m = Group::WIDTH - 1` (so that the search
+ // with loading `Group` bytes from the heap works properly, even if the result
+ // of `h1(hash) & self.bucket_mask` is equal to `self.bucket_mask`). See also
+ // `RawTableInner::set_ctrl` function.
+ //
+ // P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
+ // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
+ let data = Bucket::from_base_index(self.data_end(), 0);
+ RawIter {
+ // SAFETY: See explanation above
+ iter: RawIterRange::new(self.ctrl.as_ptr(), data, self.buckets()),
+ items: self.items,
+ }
+ }
+
+ /// Executes the destructors (if any) of the values stored in the table.
+ ///
+ /// # Note
+ ///
+ /// This function does not erase the control bytes of the table and does
+ /// not make any changes to the `items` or `growth_left` fields of the
+ /// table. If necessary, the caller of this function must manually set
+ /// up these table fields, for example using the [`clear_no_drop`] function.
+ ///
+ /// Be careful during calling this function, because drop function of
+ /// the elements can panic, and this can leave table in an inconsistent
+ /// state.
+ ///
+ /// # Safety
+ ///
+ /// The type `T` must be the actual type of the elements stored in the table,
+ /// otherwise calling this function may result in [`undefined behavior`].
+ ///
+ /// If `T` is a type that should be dropped and **the table is not empty**,
+ /// calling this function more than once results in [`undefined behavior`].
+ ///
+ /// If `T` is not [`Copy`], attempting to use values stored in the table after
+ /// calling this function may result in [`undefined behavior`].
+ ///
+ /// It is safe to call this function on a table that has not been allocated,
+ /// on a table with uninitialized control bytes, and on a table with no actual
+ /// data but with `Full` control bytes if `self.items == 0`.
+ ///
+ /// See also [`Bucket::drop`] / [`Bucket::as_ptr`] methods, for more information
+ /// about of properly removing or saving `element` from / into the [`RawTable`] /
+ /// [`RawTableInner`].
+ ///
+ /// [`Bucket::drop`]: Bucket::drop
+ /// [`Bucket::as_ptr`]: Bucket::as_ptr
+ /// [`clear_no_drop`]: RawTableInner::clear_no_drop
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ unsafe fn drop_elements<T>(&mut self) {
+ // Check that `self.items != 0`. Protects against the possibility
+ // of creating an iterator on an table with uninitialized control bytes.
+ if T::NEEDS_DROP && self.items != 0 {
+ // SAFETY: We know for sure that RawTableInner will outlive the
+ // returned `RawIter` iterator, and the caller of this function
+ // must uphold the safety contract for `drop_elements` method.
+ for item in self.iter::<T>() {
+ // SAFETY: The caller must uphold the safety contract for
+ // `drop_elements` method.
+ item.drop();
+ }
+ }
+ }
+
+ /// Executes the destructors (if any) of the values stored in the table and than
+ /// deallocates the table.
+ ///
+ /// # Note
+ ///
+ /// Calling this function automatically makes invalid (dangling) all instances of
+ /// buckets ([`Bucket`]) and makes invalid (dangling) the `ctrl` field of the table.
+ ///
+ /// This function does not make any changes to the `bucket_mask`, `items` or `growth_left`
+ /// fields of the table. If necessary, the caller of this function must manually set
+ /// up these table fields.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is [`undefined behavior`]:
+ ///
+ /// * Calling this function more than once;
+ ///
+ /// * The type `T` must be the actual type of the elements stored in the table.
+ ///
+ /// * The `alloc` must be the same [`Allocator`] as the `Allocator` that was used
+ /// to allocate this table.
+ ///
+ /// * The `table_layout` must be the same [`TableLayout`] as the `TableLayout` that
+ /// was used to allocate this table.
+ ///
+ /// The caller of this function should pay attention to the possibility of the
+ /// elements' drop function panicking, because this:
+ ///
+ /// * May leave the table in an inconsistent state;
+ ///
+ /// * Memory is never deallocated, so a memory leak may occur.
+ ///
+ /// Attempt to use the `ctrl` field of the table (dereference) after calling this
+ /// function results in [`undefined behavior`].
+ ///
+ /// It is safe to call this function on a table that has not been allocated,
+ /// on a table with uninitialized control bytes, and on a table with no actual
+ /// data but with `Full` control bytes if `self.items == 0`.
+ ///
+ /// See also [`RawTableInner::drop_elements`] or [`RawTableInner::free_buckets`]
+ /// for more information.
+ ///
+ /// [`RawTableInner::drop_elements`]: RawTableInner::drop_elements
+ /// [`RawTableInner::free_buckets`]: RawTableInner::free_buckets
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ unsafe fn drop_inner_table<T, A: Allocator>(&mut self, alloc: &A, table_layout: TableLayout) {
+ if !self.is_empty_singleton() {
+ unsafe {
+ // SAFETY: The caller must uphold the safety contract for `drop_inner_table` method.
+ self.drop_elements::<T>();
+ // SAFETY:
+ // 1. We have checked that our table is allocated.
+ // 2. The caller must uphold the safety contract for `drop_inner_table` method.
+ self.free_buckets(alloc, table_layout);
+ }
+ }
+ }
+
+ /// Returns a pointer to an element in the table (convenience for
+ /// `Bucket::from_base_index(self.data_end::<T>(), index)`).
+ ///
+ /// The caller must ensure that the `RawTableInner` outlives the returned [`Bucket<T>`],
+ /// otherwise using it may result in [`undefined behavior`].
+ ///
+ /// # Safety
+ ///
+ /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived from the
+ /// safety rules of the [`Bucket::from_base_index`] function. Therefore, when calling
+ /// this function, the following safety rules must be observed:
+ ///
+ /// * The table must already be allocated;
+ ///
+ /// * The `index` must not be greater than the number returned by the [`RawTableInner::buckets`]
+ /// function, i.e. `(index + 1) <= self.buckets()`.
+ ///
+ /// * The type `T` must be the actual type of the elements stored in the table, otherwise
+ /// using the returned [`Bucket`] may result in [`undefined behavior`].
+ ///
+ /// It is safe to call this function with index of zero (`index == 0`) on a table that has
+ /// not been allocated, but using the returned [`Bucket`] results in [`undefined behavior`].
+ ///
+ /// If `mem::size_of::<T>() == 0`, then the only requirement is that the `index` must
+ /// not be greater than the number returned by the [`RawTable::buckets`] function, i.e.
+ /// `(index + 1) <= self.buckets()`.
+ ///
+ /// ```none
+ /// If mem::size_of::<T>() != 0 then return a pointer to the `element` in the `data part` of the table
+ /// (we start counting from "0", so that in the expression T[n], the "n" index actually one less than
+ /// the "buckets" number of our `RawTableInner`, i.e. "n = RawTableInner::buckets() - 1"):
+ ///
+ /// `table.bucket(3).as_ptr()` returns a pointer that points here in the `data`
+ /// part of the `RawTableInner`, i.e. to the start of T3 (see [`Bucket::as_ptr`])
+ /// |
+ /// | `base = table.data_end::<T>()` points here
+ /// | (to the start of CT0 or to the end of T0)
+ /// v v
+ /// [Pad], T_n, ..., |T3|, T2, T1, T0, |CT0, CT1, CT2, CT3, ..., CT_n, CTa_0, CTa_1, ..., CTa_m
+ /// ^ \__________ __________/
+ /// `table.bucket(3)` returns a pointer that points \/
+ /// here in the `data` part of the `RawTableInner` additional control bytes
+ /// (to the end of T3) `m = Group::WIDTH - 1`
+ ///
+ /// where: T0...T_n - our stored data;
+ /// CT0...CT_n - control bytes or metadata for `data`;
+ /// CTa_0...CTa_m - additional control bytes (so that the search with loading `Group` bytes from
+ /// the heap works properly, even if the result of `h1(hash) & self.bucket_mask`
+ /// is equal to `self.bucket_mask`). See also `RawTableInner::set_ctrl` function.
+ ///
+ /// P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
+ /// of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
+ /// ```
+ ///
+ /// [`Bucket::from_base_index`]: Bucket::from_base_index
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
unsafe fn bucket<T>(&self, index: usize) -> Bucket<T> {
debug_assert_ne!(self.bucket_mask, 0);
@@ -1219,6 +2502,52 @@ impl<A: Allocator + Clone> RawTableInner<A> {
Bucket::from_base_index(self.data_end(), index)
}
+ /// Returns a raw `*mut u8` pointer to the start of the `data` element in the table
+ /// (convenience for `self.data_end::<u8>().as_ptr().sub((index + 1) * size_of)`).
+ ///
+ /// The caller must ensure that the `RawTableInner` outlives the returned `*mut u8`,
+ /// otherwise using it may result in [`undefined behavior`].
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is [`undefined behavior`]:
+ ///
+ /// * The table must already be allocated;
+ ///
+ /// * The `index` must not be greater than the number returned by the [`RawTableInner::buckets`]
+ /// function, i.e. `(index + 1) <= self.buckets()`;
+ ///
+ /// * The `size_of` must be equal to the size of the elements stored in the table;
+ ///
+ /// ```none
+ /// If mem::size_of::<T>() != 0 then return a pointer to the `element` in the `data part` of the table
+ /// (we start counting from "0", so that in the expression T[n], the "n" index actually one less than
+ /// the "buckets" number of our `RawTableInner`, i.e. "n = RawTableInner::buckets() - 1"):
+ ///
+ /// `table.bucket_ptr(3, mem::size_of::<T>())` returns a pointer that points here in the
+ /// `data` part of the `RawTableInner`, i.e. to the start of T3
+ /// |
+ /// | `base = table.data_end::<u8>()` points here
+ /// | (to the start of CT0 or to the end of T0)
+ /// v v
+ /// [Pad], T_n, ..., |T3|, T2, T1, T0, |CT0, CT1, CT2, CT3, ..., CT_n, CTa_0, CTa_1, ..., CTa_m
+ /// \__________ __________/
+ /// \/
+ /// additional control bytes
+ /// `m = Group::WIDTH - 1`
+ ///
+ /// where: T0...T_n - our stored data;
+ /// CT0...CT_n - control bytes or metadata for `data`;
+ /// CTa_0...CTa_m - additional control bytes (so that the search with loading `Group` bytes from
+ /// the heap works properly, even if the result of `h1(hash) & self.bucket_mask`
+ /// is equal to `self.bucket_mask`). See also `RawTableInner::set_ctrl` function.
+ ///
+ /// P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
+ /// of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
+ /// ```
+ ///
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
unsafe fn bucket_ptr(&self, index: usize, size_of: usize) -> *mut u8 {
debug_assert_ne!(self.bucket_mask, 0);
@@ -1227,9 +2556,44 @@ impl<A: Allocator + Clone> RawTableInner<A> {
base.sub((index + 1) * size_of)
}
+ /// Returns pointer to one past last `data` element in the table as viewed from
+ /// the start point of the allocation (convenience for `self.ctrl.cast()`).
+ ///
+ /// This function actually returns a pointer to the end of the `data element` at
+ /// index "0" (zero).
+ ///
+ /// The caller must ensure that the `RawTableInner` outlives the returned [`NonNull<T>`],
+ /// otherwise using it may result in [`undefined behavior`].
+ ///
+ /// # Note
+ ///
+ /// The type `T` must be the actual type of the elements stored in the table, otherwise
+ /// using the returned [`NonNull<T>`] may result in [`undefined behavior`].
+ ///
+ /// ```none
+ /// `table.data_end::<T>()` returns pointer that points here
+ /// (to the end of `T0`)
+ /// ∨
+ /// [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, CTa_0, CTa_1, ..., CTa_m
+ /// \________ ________/
+ /// \/
+ /// `n = buckets - 1`, i.e. `RawTableInner::buckets() - 1`
+ ///
+ /// where: T0...T_n - our stored data;
+ /// CT0...CT_n - control bytes or metadata for `data`.
+ /// CTa_0...CTa_m - additional control bytes, where `m = Group::WIDTH - 1` (so that the search
+ /// with loading `Group` bytes from the heap works properly, even if the result
+ /// of `h1(hash) & self.bucket_mask` is equal to `self.bucket_mask`). See also
+ /// `RawTableInner::set_ctrl` function.
+ ///
+ /// P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
+ /// of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
+ /// ```
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
- unsafe fn data_end<T>(&self) -> NonNull<T> {
- NonNull::new_unchecked(self.ctrl.as_ptr().cast())
+ fn data_end<T>(&self) -> NonNull<T> {
+ self.ctrl.cast()
}
/// Returns an iterator-like object for a probe sequence on the table.
@@ -1240,6 +2604,8 @@ impl<A: Allocator + Clone> RawTableInner<A> {
#[inline]
fn probe_seq(&self, hash: u64) -> ProbeSeq {
ProbeSeq {
+ // This is the same as `hash as usize % self.buckets()` because the number
+ // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
pos: h1(hash) & self.bucket_mask,
stride: 0,
}
@@ -1250,7 +2616,7 @@ impl<A: Allocator + Clone> RawTableInner<A> {
#[cfg(feature = "raw")]
#[inline]
unsafe fn prepare_insert_no_grow(&mut self, hash: u64) -> Result<usize, ()> {
- let index = self.find_insert_slot(hash);
+ let index = self.find_insert_slot(hash).index;
let old_ctrl = *self.ctrl(index);
if unlikely(self.growth_left == 0 && special_is_empty(old_ctrl)) {
Err(())
@@ -1277,13 +2643,68 @@ impl<A: Allocator + Clone> RawTableInner<A> {
/// Sets a control byte to the hash, and possibly also the replicated control byte at
/// the end of the array.
+ ///
+ /// This function does not make any changes to the `data` parts of the table,
+ /// or any changes to the `items` or `growth_left` field of the table.
+ ///
+ /// # Safety
+ ///
+ /// The safety rules are directly derived from the safety rules for [`RawTableInner::set_ctrl`]
+ /// method. Thus, in order to uphold the safety contracts for the method, you must observe the
+ /// following rules when calling this function:
+ ///
+ /// * The [`RawTableInner`] has already been allocated;
+ ///
+ /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
+ /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
+ /// be no greater than the number returned by the function [`RawTableInner::buckets`].
+ ///
+ /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
+ ///
+ /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
+ /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
+ ///
+ /// [`RawTableInner::set_ctrl`]: RawTableInner::set_ctrl
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
+ /// [`Bucket::as_ptr`]: Bucket::as_ptr
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
- unsafe fn set_ctrl_h2(&self, index: usize, hash: u64) {
+ unsafe fn set_ctrl_h2(&mut self, index: usize, hash: u64) {
+ // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::set_ctrl_h2`]
self.set_ctrl(index, h2(hash));
}
+ /// Replaces the hash in the control byte at the given index with the provided one,
+ /// and possibly also replicates the new control byte at the end of the array of control
+ /// bytes, returning the old control byte.
+ ///
+ /// This function does not make any changes to the `data` parts of the table,
+ /// or any changes to the `items` or `growth_left` field of the table.
+ ///
+ /// # Safety
+ ///
+ /// The safety rules are directly derived from the safety rules for [`RawTableInner::set_ctrl_h2`]
+ /// and [`RawTableInner::ctrl`] methods. Thus, in order to uphold the safety contracts for both
+ /// methods, you must observe the following rules when calling this function:
+ ///
+ /// * The [`RawTableInner`] has already been allocated;
+ ///
+ /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
+ /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
+ /// be no greater than the number returned by the function [`RawTableInner::buckets`].
+ ///
+ /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
+ ///
+ /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
+ /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
+ ///
+ /// [`RawTableInner::set_ctrl_h2`]: RawTableInner::set_ctrl_h2
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
+ /// [`Bucket::as_ptr`]: Bucket::as_ptr
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
- unsafe fn replace_ctrl_h2(&self, index: usize, hash: u64) -> u8 {
+ unsafe fn replace_ctrl_h2(&mut self, index: usize, hash: u64) -> u8 {
+ // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::replace_ctrl_h2`]
let prev_ctrl = *self.ctrl(index);
self.set_ctrl_h2(index, hash);
prev_ctrl
@@ -1291,10 +2712,35 @@ impl<A: Allocator + Clone> RawTableInner<A> {
/// Sets a control byte, and possibly also the replicated control byte at
/// the end of the array.
+ ///
+ /// This function does not make any changes to the `data` parts of the table,
+ /// or any changes to the `items` or `growth_left` field of the table.
+ ///
+ /// # Safety
+ ///
+ /// You must observe the following safety rules when calling this function:
+ ///
+ /// * The [`RawTableInner`] has already been allocated;
+ ///
+ /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
+ /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
+ /// be no greater than the number returned by the function [`RawTableInner::buckets`].
+ ///
+ /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
+ ///
+ /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
+ /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
+ ///
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
+ /// [`Bucket::as_ptr`]: Bucket::as_ptr
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
- unsafe fn set_ctrl(&self, index: usize, ctrl: u8) {
+ unsafe fn set_ctrl(&mut self, index: usize, ctrl: u8) {
// Replicate the first Group::WIDTH control bytes at the end of
- // the array without using a branch:
+ // the array without using a branch. If the tables smaller than
+ // the group width (self.buckets() < Group::WIDTH),
+ // `index2 = Group::WIDTH + index`, otherwise `index2` is:
+ //
// - If index >= Group::WIDTH then index == index2.
// - Otherwise index2 == self.bucket_mask + 1 + index.
//
@@ -1311,16 +2757,43 @@ impl<A: Allocator + Clone> RawTableInner<A> {
// ---------------------------------------------
// | [A] | [B] | [EMPTY] | [EMPTY] | [A] | [B] |
// ---------------------------------------------
+
+ // This is the same as `(index.wrapping_sub(Group::WIDTH)) % self.buckets() + Group::WIDTH`
+ // because the number of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH;
+ // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::set_ctrl`]
*self.ctrl(index) = ctrl;
*self.ctrl(index2) = ctrl;
}
/// Returns a pointer to a control byte.
+ ///
+ /// # Safety
+ ///
+ /// For the allocated [`RawTableInner`], the result is [`Undefined Behavior`],
+ /// if the `index` is greater than the `self.bucket_mask + 1 + Group::WIDTH`.
+ /// In that case, calling this function with `index == self.bucket_mask + 1 + Group::WIDTH`
+ /// will return a pointer to the end of the allocated table and it is useless on its own.
+ ///
+ /// Calling this function with `index >= self.bucket_mask + 1 + Group::WIDTH` on a
+ /// table that has not been allocated results in [`Undefined Behavior`].
+ ///
+ /// So to satisfy both requirements you should always follow the rule that
+ /// `index < self.bucket_mask + 1 + Group::WIDTH`
+ ///
+ /// Calling this function on [`RawTableInner`] that are not already allocated is safe
+ /// for read-only purpose.
+ ///
+ /// See also [`Bucket::as_ptr()`] method, for more information about of properly removing
+ /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
+ ///
+ /// [`Bucket::as_ptr()`]: Bucket::as_ptr()
+ /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
unsafe fn ctrl(&self, index: usize) -> *mut u8 {
debug_assert!(index < self.num_ctrl_bytes());
+ // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::ctrl`]
self.ctrl.as_ptr().add(index)
}
@@ -1329,6 +2802,17 @@ impl<A: Allocator + Clone> RawTableInner<A> {
self.bucket_mask + 1
}
+ /// Checks whether the bucket at `index` is full.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure `index` is less than the number of buckets.
+ #[inline]
+ unsafe fn is_bucket_full(&self, index: usize) -> bool {
+ debug_assert!(index < self.buckets());
+ is_full(*self.ctrl(index))
+ }
+
#[inline]
fn num_ctrl_bytes(&self) -> usize {
self.bucket_mask + 1 + Group::WIDTH
@@ -1339,25 +2823,45 @@ impl<A: Allocator + Clone> RawTableInner<A> {
self.bucket_mask == 0
}
+ /// Attempts to allocate a new hash table with at least enough capacity
+ /// for inserting the given number of elements without reallocating,
+ /// and return it inside ScopeGuard to protect against panic in the hash
+ /// function.
+ ///
+ /// # Note
+ ///
+ /// It is recommended (but not required):
+ ///
+ /// * That the new table's `capacity` be greater than or equal to `self.items`.
+ ///
+ /// * The `alloc` is the same [`Allocator`] as the `Allocator` used
+ /// to allocate this table.
+ ///
+ /// * The `table_layout` is the same [`TableLayout`] as the `TableLayout` used
+ /// to allocate this table.
+ ///
+ /// If `table_layout` does not match the `TableLayout` that was used to allocate
+ /// this table, then using `mem::swap` with the `self` and the new table returned
+ /// by this function results in [`undefined behavior`].
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[allow(clippy::mut_mut)]
#[inline]
- unsafe fn prepare_resize(
+ fn prepare_resize<'a, A>(
&self,
+ alloc: &'a A,
table_layout: TableLayout,
capacity: usize,
fallibility: Fallibility,
- ) -> Result<crate::scopeguard::ScopeGuard<Self, impl FnMut(&mut Self)>, TryReserveError> {
+ ) -> Result<crate::scopeguard::ScopeGuard<Self, impl FnMut(&mut Self) + 'a>, TryReserveError>
+ where
+ A: Allocator,
+ {
debug_assert!(self.items <= capacity);
// Allocate and initialize the new table.
- let mut new_table = RawTableInner::fallible_with_capacity(
- self.alloc.clone(),
- table_layout,
- capacity,
- fallibility,
- )?;
- new_table.growth_left -= self.items;
- new_table.items = self.items;
+ let new_table =
+ RawTableInner::fallible_with_capacity(alloc, table_layout, capacity, fallibility)?;
// The hash function may panic, in which case we simply free the new
// table without dropping any elements that may have been copied into
@@ -1367,7 +2871,11 @@ impl<A: Allocator + Clone> RawTableInner<A> {
// the comment at the bottom of this function.
Ok(guard(new_table, move |self_| {
if !self_.is_empty_singleton() {
- self_.free_buckets(table_layout);
+ // SAFETY:
+ // 1. We have checked that our table is allocated.
+ // 2. We know for sure that the `alloc` and `table_layout` matches the
+ // [`Allocator`] and [`TableLayout`] used to allocate this table.
+ unsafe { self_.free_buckets(alloc, table_layout) };
}
}))
}
@@ -1376,16 +2884,38 @@ impl<A: Allocator + Clone> RawTableInner<A> {
///
/// This uses dynamic dispatch to reduce the amount of
/// code generated, but it is eliminated by LLVM optimizations when inlined.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is
+ /// [`undefined behavior`]:
+ ///
+ /// * The `alloc` must be the same [`Allocator`] as the `Allocator` used
+ /// to allocate this table.
+ ///
+ /// * The `layout` must be the same [`TableLayout`] as the `TableLayout`
+ /// used to allocate this table.
+ ///
+ /// * The `drop` function (`fn(*mut u8)`) must be the actual drop function of
+ /// the elements stored in the table.
+ ///
+ /// * The [`RawTableInner`] must have properly initialized control bytes.
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[allow(clippy::inline_always)]
#[inline(always)]
- unsafe fn reserve_rehash_inner(
+ unsafe fn reserve_rehash_inner<A>(
&mut self,
+ alloc: &A,
additional: usize,
hasher: &dyn Fn(&mut Self, usize) -> u64,
fallibility: Fallibility,
layout: TableLayout,
drop: Option<fn(*mut u8)>,
- ) -> Result<(), TryReserveError> {
+ ) -> Result<(), TryReserveError>
+ where
+ A: Allocator,
+ {
// Avoid `Option::ok_or_else` because it bloats LLVM IR.
let new_items = match self.items.checked_add(additional) {
Some(new_items) => new_items,
@@ -1395,12 +2925,30 @@ impl<A: Allocator + Clone> RawTableInner<A> {
if new_items <= full_capacity / 2 {
// Rehash in-place without re-allocating if we have plenty of spare
// capacity that is locked up due to DELETED entries.
+
+ // SAFETY:
+ // 1. We know for sure that `[`RawTableInner`]` has already been allocated
+ // (since new_items <= full_capacity / 2);
+ // 2. The caller ensures that `drop` function is the actual drop function of
+ // the elements stored in the table.
+ // 3. The caller ensures that `layout` matches the [`TableLayout`] that was
+ // used to allocate this table.
+ // 4. The caller ensures that the control bytes of the `RawTableInner`
+ // are already initialized.
self.rehash_in_place(hasher, layout.size, drop);
Ok(())
} else {
// Otherwise, conservatively resize to at least the next size up
// to avoid churning deletes into frequent rehashes.
+ //
+ // SAFETY:
+ // 1. We know for sure that `capacity >= self.items`.
+ // 2. The caller ensures that `alloc` and `layout` matches the [`Allocator`] and
+ // [`TableLayout`] that were used to allocate this table.
+ // 3. The caller ensures that the control bytes of the `RawTableInner`
+ // are already initialized.
self.resize_inner(
+ alloc,
usize::max(new_items, full_capacity + 1),
hasher,
fallibility,
@@ -1409,48 +2957,160 @@ impl<A: Allocator + Clone> RawTableInner<A> {
}
}
+ /// Returns an iterator over full buckets indices in the table.
+ ///
+ /// # Safety
+ ///
+ /// Behavior is undefined if any of the following conditions are violated:
+ ///
+ /// * The caller has to ensure that the `RawTableInner` outlives the
+ /// `FullBucketsIndices`. Because we cannot make the `next` method
+ /// unsafe on the `FullBucketsIndices` struct, we have to make the
+ /// `full_buckets_indices` method unsafe.
+ ///
+ /// * The [`RawTableInner`] must have properly initialized control bytes.
+ #[inline(always)]
+ unsafe fn full_buckets_indices(&self) -> FullBucketsIndices {
+ // SAFETY:
+ // 1. Since the caller of this function ensures that the control bytes
+ // are properly initialized and `self.ctrl(0)` points to the start
+ // of the array of control bytes, therefore: `ctrl` is valid for reads,
+ // properly aligned to `Group::WIDTH` and points to the properly initialized
+ // control bytes.
+ // 2. The value of `items` is equal to the amount of data (values) added
+ // to the table.
+ //
+ // `ctrl` points here (to the start
+ // of the first control byte `CT0`)
+ // ∨
+ // [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, Group::WIDTH
+ // \________ ________/
+ // \/
+ // `n = buckets - 1`, i.e. `RawTableInner::buckets() - 1`
+ //
+ // where: T0...T_n - our stored data;
+ // CT0...CT_n - control bytes or metadata for `data`.
+ let ctrl = NonNull::new_unchecked(self.ctrl(0));
+
+ FullBucketsIndices {
+ // Load the first group
+ // SAFETY: See explanation above.
+ current_group: Group::load_aligned(ctrl.as_ptr()).match_full().into_iter(),
+ group_first_index: 0,
+ ctrl,
+ items: self.items,
+ }
+ }
+
/// Allocates a new table of a different size and moves the contents of the
/// current table into it.
///
/// This uses dynamic dispatch to reduce the amount of
/// code generated, but it is eliminated by LLVM optimizations when inlined.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is
+ /// [`undefined behavior`]:
+ ///
+ /// * The `alloc` must be the same [`Allocator`] as the `Allocator` used
+ /// to allocate this table;
+ ///
+ /// * The `layout` must be the same [`TableLayout`] as the `TableLayout`
+ /// used to allocate this table;
+ ///
+ /// * The [`RawTableInner`] must have properly initialized control bytes.
+ ///
+ /// The caller of this function must ensure that `capacity >= self.items`
+ /// otherwise:
+ ///
+ /// * If `self.items != 0`, calling of this function with `capacity == 0`
+ /// results in [`undefined behavior`].
+ ///
+ /// * If `capacity_to_buckets(capacity) < Group::WIDTH` and
+ /// `self.items > capacity_to_buckets(capacity)` calling this function
+ /// results in [`undefined behavior`].
+ ///
+ /// * If `capacity_to_buckets(capacity) >= Group::WIDTH` and
+ /// `self.items > capacity_to_buckets(capacity)` calling this function
+ /// are never return (will go into an infinite loop).
+ ///
+ /// Note: It is recommended (but not required) that the new table's `capacity`
+ /// be greater than or equal to `self.items`. In case if `capacity <= self.items`
+ /// this function can never return. See [`RawTableInner::find_insert_slot`] for
+ /// more information.
+ ///
+ /// [`RawTableInner::find_insert_slot`]: RawTableInner::find_insert_slot
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[allow(clippy::inline_always)]
#[inline(always)]
- unsafe fn resize_inner(
+ unsafe fn resize_inner<A>(
&mut self,
+ alloc: &A,
capacity: usize,
hasher: &dyn Fn(&mut Self, usize) -> u64,
fallibility: Fallibility,
layout: TableLayout,
- ) -> Result<(), TryReserveError> {
- let mut new_table = self.prepare_resize(layout, capacity, fallibility)?;
-
- // Copy all elements to the new table.
- for i in 0..self.buckets() {
- if !is_full(*self.ctrl(i)) {
- continue;
- }
-
+ ) -> Result<(), TryReserveError>
+ where
+ A: Allocator,
+ {
+ // SAFETY: We know for sure that `alloc` and `layout` matches the [`Allocator`] and [`TableLayout`]
+ // that were used to allocate this table.
+ let mut new_table = self.prepare_resize(alloc, layout, capacity, fallibility)?;
+
+ // SAFETY: We know for sure that RawTableInner will outlive the
+ // returned `FullBucketsIndices` iterator, and the caller of this
+ // function ensures that the control bytes are properly initialized.
+ for full_byte_index in self.full_buckets_indices() {
// This may panic.
- let hash = hasher(self, i);
+ let hash = hasher(self, full_byte_index);
+ // SAFETY:
// We can use a simpler version of insert() here since:
- // - there are no DELETED entries.
- // - we know there is enough space in the table.
- // - all elements are unique.
- let (index, _) = new_table.prepare_insert_slot(hash);
-
+ // 1. There are no DELETED entries.
+ // 2. We know there is enough space in the table.
+ // 3. All elements are unique.
+ // 4. The caller of this function guarantees that `capacity > 0`
+ // so `new_table` must already have some allocated memory.
+ // 5. We set `growth_left` and `items` fields of the new table
+ // after the loop.
+ // 6. We insert into the table, at the returned index, the data
+ // matching the given hash immediately after calling this function.
+ let (new_index, _) = new_table.prepare_insert_slot(hash);
+
+ // SAFETY:
+ //
+ // * `src` is valid for reads of `layout.size` bytes, since the
+ // table is alive and the `full_byte_index` is guaranteed to be
+ // within bounds (see `FullBucketsIndices::next_impl`);
+ //
+ // * `dst` is valid for writes of `layout.size` bytes, since the
+ // caller ensures that `table_layout` matches the [`TableLayout`]
+ // that was used to allocate old table and we have the `new_index`
+ // returned by `prepare_insert_slot`.
+ //
+ // * Both `src` and `dst` are properly aligned.
+ //
+ // * Both `src` and `dst` point to different region of memory.
ptr::copy_nonoverlapping(
- self.bucket_ptr(i, layout.size),
- new_table.bucket_ptr(index, layout.size),
+ self.bucket_ptr(full_byte_index, layout.size),
+ new_table.bucket_ptr(new_index, layout.size),
layout.size,
);
}
+ // The hash function didn't panic, so we can safely set the
+ // `growth_left` and `items` fields of the new table.
+ new_table.growth_left -= self.items;
+ new_table.items = self.items;
+
// We successfully copied all elements without panicking. Now replace
// self with the new table. The old table will have its memory freed but
// the items will not be dropped (since they have been moved into the
// new table).
+ // SAFETY: The caller ensures that `table_layout` matches the [`TableLayout`]
+ // that was used to allocate this table.
mem::swap(self, &mut new_table);
Ok(())
@@ -1463,6 +3123,21 @@ impl<A: Allocator + Clone> RawTableInner<A> {
///
/// This uses dynamic dispatch to reduce the amount of
/// code generated, but it is eliminated by LLVM optimizations when inlined.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is [`undefined behavior`]:
+ ///
+ /// * The `size_of` must be equal to the size of the elements stored in the table;
+ ///
+ /// * The `drop` function (`fn(*mut u8)`) must be the actual drop function of
+ /// the elements stored in the table.
+ ///
+ /// * The [`RawTableInner`] has already been allocated;
+ ///
+ /// * The [`RawTableInner`] must have properly initialized control bytes.
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[allow(clippy::inline_always)]
#[cfg_attr(feature = "inline-more", inline(always))]
#[cfg_attr(not(feature = "inline-more"), inline)]
@@ -1506,8 +3181,10 @@ impl<A: Allocator + Clone> RawTableInner<A> {
let hash = hasher(*guard, i);
// Search for a suitable place to put it
- let new_i = guard.find_insert_slot(hash);
- let new_i_p = guard.bucket_ptr(new_i, size_of);
+ //
+ // SAFETY: Caller of this function ensures that the control bytes
+ // are properly initialized.
+ let new_i = guard.find_insert_slot(hash).index;
// Probing works by scanning through all of the control
// bytes in groups, which may not be aligned to the group
@@ -1519,6 +3196,8 @@ impl<A: Allocator + Clone> RawTableInner<A> {
continue 'outer;
}
+ let new_i_p = guard.bucket_ptr(new_i, size_of);
+
// We are moving the current item to a new position. Write
// our H2 to the control byte of the new position.
let prev_ctrl = guard.replace_ctrl_h2(new_i, hash);
@@ -1545,17 +3224,107 @@ impl<A: Allocator + Clone> RawTableInner<A> {
mem::forget(guard);
}
+ /// Deallocates the table without dropping any entries.
+ ///
+ /// # Note
+ ///
+ /// This function must be called only after [`drop_elements`](RawTableInner::drop_elements),
+ /// else it can lead to leaking of memory. Also calling this function automatically
+ /// makes invalid (dangling) all instances of buckets ([`Bucket`]) and makes invalid
+ /// (dangling) the `ctrl` field of the table.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is [`Undefined Behavior`]:
+ ///
+ /// * The [`RawTableInner`] has already been allocated;
+ ///
+ /// * The `alloc` must be the same [`Allocator`] as the `Allocator` that was used
+ /// to allocate this table.
+ ///
+ /// * The `table_layout` must be the same [`TableLayout`] as the `TableLayout` that was used
+ /// to allocate this table.
+ ///
+ /// See also [`GlobalAlloc::dealloc`] or [`Allocator::deallocate`] for more information.
+ ///
+ /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ /// [`GlobalAlloc::dealloc`]: https://doc.rust-lang.org/alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
+ /// [`Allocator::deallocate`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html#tymethod.deallocate
+ #[inline]
+ unsafe fn free_buckets<A>(&mut self, alloc: &A, table_layout: TableLayout)
+ where
+ A: Allocator,
+ {
+ // SAFETY: The caller must uphold the safety contract for `free_buckets`
+ // method.
+ let (ptr, layout) = self.allocation_info(table_layout);
+ alloc.deallocate(ptr, layout);
+ }
+
+ /// Returns a pointer to the allocated memory and the layout that was used to
+ /// allocate the table.
+ ///
+ /// # Safety
+ ///
+ /// Caller of this function must observe the following safety rules:
+ ///
+ /// * The [`RawTableInner`] has already been allocated, otherwise
+ /// calling this function results in [`undefined behavior`]
+ ///
+ /// * The `table_layout` must be the same [`TableLayout`] as the `TableLayout`
+ /// that was used to allocate this table. Failure to comply with this condition
+ /// may result in [`undefined behavior`].
+ ///
+ /// See also [`GlobalAlloc::dealloc`] or [`Allocator::deallocate`] for more information.
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ /// [`GlobalAlloc::dealloc`]: https://doc.rust-lang.org/alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
+ /// [`Allocator::deallocate`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html#tymethod.deallocate
#[inline]
- unsafe fn free_buckets(&mut self, table_layout: TableLayout) {
+ unsafe fn allocation_info(&self, table_layout: TableLayout) -> (NonNull<u8>, Layout) {
+ debug_assert!(
+ !self.is_empty_singleton(),
+ "this function can only be called on non-empty tables"
+ );
+
// Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) {
Some(lco) => lco,
- None => hint::unreachable_unchecked(),
+ None => unsafe { hint::unreachable_unchecked() },
};
- self.alloc.deallocate(
- NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)),
+ (
+ // SAFETY: The caller must uphold the safety contract for `allocation_info` method.
+ unsafe { NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)) },
layout,
- );
+ )
+ }
+
+ /// Returns a pointer to the allocated memory and the layout that was used to
+ /// allocate the table. If [`RawTableInner`] has not been allocated, this
+ /// function return `dangling` pointer and `()` (unit) layout.
+ ///
+ /// # Safety
+ ///
+ /// The `table_layout` must be the same [`TableLayout`] as the `TableLayout`
+ /// that was used to allocate this table. Failure to comply with this condition
+ /// may result in [`undefined behavior`].
+ ///
+ /// See also [`GlobalAlloc::dealloc`] or [`Allocator::deallocate`] for more information.
+ ///
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ /// [`GlobalAlloc::dealloc`]: https://doc.rust-lang.org/alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
+ /// [`Allocator::deallocate`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html#tymethod.deallocate
+ #[cfg(feature = "raw")]
+ unsafe fn allocation_info_or_zero(&self, table_layout: TableLayout) -> (NonNull<u8>, Layout) {
+ if self.is_empty_singleton() {
+ (NonNull::dangling(), Layout::new::<()>())
+ } else {
+ // SAFETY:
+ // 1. We have checked that our table is allocated.
+ // 2. The caller ensures that `table_layout` matches the [`TableLayout`]
+ // that was used to allocate this table.
+ unsafe { self.allocation_info(table_layout) }
+ }
}
/// Marks all table buckets as empty without dropping their contents.
@@ -1570,27 +3339,95 @@ impl<A: Allocator + Clone> RawTableInner<A> {
self.growth_left = bucket_mask_to_capacity(self.bucket_mask);
}
+ /// Erases the [`Bucket`]'s control byte at the given index so that it does not
+ /// triggered as full, decreases the `items` of the table and, if it can be done,
+ /// increases `self.growth_left`.
+ ///
+ /// This function does not actually erase / drop the [`Bucket`] itself, i.e. it
+ /// does not make any changes to the `data` parts of the table. The caller of this
+ /// function must take care to properly drop the `data`, otherwise calling this
+ /// function may result in a memory leak.
+ ///
+ /// # Safety
+ ///
+ /// You must observe the following safety rules when calling this function:
+ ///
+ /// * The [`RawTableInner`] has already been allocated;
+ ///
+ /// * It must be the full control byte at the given position;
+ ///
+ /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
+ /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
+ /// be no greater than the number returned by the function [`RawTableInner::buckets`].
+ ///
+ /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
+ ///
+ /// Calling this function on a table with no elements is unspecified, but calling subsequent
+ /// functions is likely to result in [`undefined behavior`] due to overflow subtraction
+ /// (`self.items -= 1 cause overflow when self.items == 0`).
+ ///
+ /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
+ /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
+ ///
+ /// [`RawTableInner::buckets`]: RawTableInner::buckets
+ /// [`Bucket::as_ptr`]: Bucket::as_ptr
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[inline]
unsafe fn erase(&mut self, index: usize) {
- debug_assert!(is_full(*self.ctrl(index)));
+ debug_assert!(self.is_bucket_full(index));
+
+ // This is the same as `index.wrapping_sub(Group::WIDTH) % self.buckets()` because
+ // the number of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask;
+ // SAFETY:
+ // - The caller must uphold the safety contract for `erase` method;
+ // - `index_before` is guaranteed to be in range due to masking with `self.bucket_mask`
let empty_before = Group::load(self.ctrl(index_before)).match_empty();
let empty_after = Group::load(self.ctrl(index)).match_empty();
- // If we are inside a continuous block of Group::WIDTH full or deleted
- // cells then a probe window may have seen a full block when trying to
- // insert. We therefore need to keep that block non-empty so that
- // lookups will continue searching to the next probe window.
+ // Inserting and searching in the map is performed by two key functions:
+ //
+ // - The `find_insert_slot` function that looks up the index of any `EMPTY` or `DELETED`
+ // slot in a group to be able to insert. If it doesn't find an `EMPTY` or `DELETED`
+ // slot immediately in the first group, it jumps to the next `Group` looking for it,
+ // and so on until it has gone through all the groups in the control bytes.
+ //
+ // - The `find_inner` function that looks for the index of the desired element by looking
+ // at all the `FULL` bytes in the group. If it did not find the element right away, and
+ // there is no `EMPTY` byte in the group, then this means that the `find_insert_slot`
+ // function may have found a suitable slot in the next group. Therefore, `find_inner`
+ // jumps further, and if it does not find the desired element and again there is no `EMPTY`
+ // byte, then it jumps further, and so on. The search stops only if `find_inner` function
+ // finds the desired element or hits an `EMPTY` slot/byte.
+ //
+ // Accordingly, this leads to two consequences:
//
- // Note that in this context `leading_zeros` refers to the bytes at the
- // end of a group, while `trailing_zeros` refers to the bytes at the
- // beginning of a group.
+ // - The map must have `EMPTY` slots (bytes);
+ //
+ // - You can't just mark the byte to be erased as `EMPTY`, because otherwise the `find_inner`
+ // function may stumble upon an `EMPTY` byte before finding the desired element and stop
+ // searching.
+ //
+ // Thus it is necessary to check all bytes after and before the erased element. If we are in
+ // a contiguous `Group` of `FULL` or `DELETED` bytes (the number of `FULL` or `DELETED` bytes
+ // before and after is greater than or equal to `Group::WIDTH`), then we must mark our byte as
+ // `DELETED` in order for the `find_inner` function to go further. On the other hand, if there
+ // is at least one `EMPTY` slot in the `Group`, then the `find_inner` function will still stumble
+ // upon an `EMPTY` byte, so we can safely mark our erased byte as `EMPTY` as well.
+ //
+ // Finally, since `index_before == (index.wrapping_sub(Group::WIDTH) & self.bucket_mask) == index`
+ // and given all of the above, tables smaller than the group width (self.buckets() < Group::WIDTH)
+ // cannot have `DELETED` bytes.
+ //
+ // Note that in this context `leading_zeros` refers to the bytes at the end of a group, while
+ // `trailing_zeros` refers to the bytes at the beginning of a group.
let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH {
DELETED
} else {
self.growth_left += 1;
EMPTY
};
+ // SAFETY: the caller must uphold the safety contract for `erase` method.
self.set_ctrl(index, ctrl);
self.items -= 1;
}
@@ -1599,12 +3436,16 @@ impl<A: Allocator + Clone> RawTableInner<A> {
impl<T: Clone, A: Allocator + Clone> Clone for RawTable<T, A> {
fn clone(&self) -> Self {
if self.table.is_empty_singleton() {
- Self::new_in(self.table.alloc.clone())
+ Self::new_in(self.alloc.clone())
} else {
unsafe {
// Avoid `Result::ok_or_else` because it bloats LLVM IR.
- let new_table = match Self::new_uninitialized(
- self.table.alloc.clone(),
+ //
+ // SAFETY: This is safe as we are taking the size of an already allocated table
+ // and therefore сapacity overflow cannot occur, `self.table.buckets()` is power
+ // of two and all allocator errors will be caught inside `RawTableInner::new_uninitialized`.
+ let mut new_table = match Self::new_uninitialized(
+ self.alloc.clone(),
self.table.buckets(),
Fallibility::Infallible,
) {
@@ -1612,24 +3453,32 @@ impl<T: Clone, A: Allocator + Clone> Clone for RawTable<T, A> {
Err(_) => hint::unreachable_unchecked(),
};
- // If cloning fails then we need to free the allocation for the
- // new table. However we don't run its drop since its control
- // bytes are not initialized yet.
- let mut guard = guard(ManuallyDrop::new(new_table), |new_table| {
- new_table.free_buckets();
- });
-
- guard.clone_from_spec(self);
-
- // Disarm the scope guard and return the newly created table.
- ManuallyDrop::into_inner(ScopeGuard::into_inner(guard))
+ // Cloning elements may fail (the clone function may panic). But we don't
+ // need to worry about uninitialized control bits, since:
+ // 1. The number of items (elements) in the table is zero, which means that
+ // the control bits will not be readed by Drop function.
+ // 2. The `clone_from_spec` method will first copy all control bits from
+ // `self` (thus initializing them). But this will not affect the `Drop`
+ // function, since the `clone_from_spec` function sets `items` only after
+ // successfully clonning all elements.
+ new_table.clone_from_spec(self);
+ new_table
}
}
}
fn clone_from(&mut self, source: &Self) {
if source.table.is_empty_singleton() {
- *self = Self::new_in(self.table.alloc.clone());
+ let mut old_inner = mem::replace(&mut self.table, RawTableInner::NEW);
+ unsafe {
+ // SAFETY:
+ // 1. We call the function only once;
+ // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
+ // and [`TableLayout`] that were used to allocate this table.
+ // 3. If any elements' drop function panics, then there will only be a memory leak,
+ // because we have replaced the inner table with a new one.
+ old_inner.drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
+ }
} else {
unsafe {
// Make sure that if any panics occurs, we clear the table and
@@ -1644,27 +3493,38 @@ impl<T: Clone, A: Allocator + Clone> Clone for RawTable<T, A> {
//
// This leak is unavoidable: we can't try dropping more elements
// since this could lead to another panic and abort the process.
- self_.drop_elements();
+ //
+ // SAFETY: If something gets wrong we clear our table right after
+ // dropping the elements, so there is no double drop, since `items`
+ // will be equal to zero.
+ self_.table.drop_elements::<T>();
// If necessary, resize our table to match the source.
if self_.buckets() != source.buckets() {
- // Skip our drop by using ptr::write.
- if !self_.table.is_empty_singleton() {
- self_.free_buckets();
+ let new_inner = match RawTableInner::new_uninitialized(
+ &self_.alloc,
+ Self::TABLE_LAYOUT,
+ source.buckets(),
+ Fallibility::Infallible,
+ ) {
+ Ok(table) => table,
+ Err(_) => hint::unreachable_unchecked(),
+ };
+ // Replace the old inner with new uninitialized one. It's ok, since if something gets
+ // wrong `ScopeGuard` will initialize all control bytes and leave empty table.
+ let mut old_inner = mem::replace(&mut self_.table, new_inner);
+ if !old_inner.is_empty_singleton() {
+ // SAFETY:
+ // 1. We have checked that our table is allocated.
+ // 2. We know for sure that `alloc` and `table_layout` matches
+ // the [`Allocator`] and [`TableLayout`] that were used to allocate this table.
+ old_inner.free_buckets(&self_.alloc, Self::TABLE_LAYOUT);
}
- (&mut **self_ as *mut Self).write(
- // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
- match Self::new_uninitialized(
- self_.table.alloc.clone(),
- source.buckets(),
- Fallibility::Infallible,
- ) {
- Ok(table) => table,
- Err(_) => hint::unreachable_unchecked(),
- },
- );
}
+ // Cloning elements may fail (the clone function may panic), but the `ScopeGuard`
+ // inside the `clone_from_impl` function will take care of that, dropping all
+ // cloned elements if necessary. Our `ScopeGuard` will clear the table.
self_.clone_from_spec(source);
// Disarm the scope guard if cloning was successful.
@@ -1696,7 +3556,8 @@ impl<T: Copy, A: Allocator + Clone> RawTableClone for RawTable<T, A> {
.copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes());
source
.data_start()
- .copy_to_nonoverlapping(self.data_start(), self.table.buckets());
+ .as_ptr()
+ .copy_to_nonoverlapping(self.data_start().as_ptr(), self.table.buckets());
self.table.items = source.table.items;
self.table.growth_left = source.table.growth_left;
@@ -1720,9 +3581,9 @@ impl<T: Clone, A: Allocator + Clone> RawTable<T, A> {
// to make sure we drop only the elements that have been
// cloned so far.
let mut guard = guard((0, &mut *self), |(index, self_)| {
- if mem::needs_drop::<T>() && !self_.is_empty() {
- for i in 0..=*index {
- if is_full(*self_.table.ctrl(i)) {
+ if T::NEEDS_DROP {
+ for i in 0..*index {
+ if self_.is_bucket_full(i) {
self_.bucket(i).drop();
}
}
@@ -1735,7 +3596,7 @@ impl<T: Clone, A: Allocator + Clone> RawTable<T, A> {
to.write(from.as_ref().clone());
// Update the index in case we need to unwind.
- guard.0 = index;
+ guard.0 = index + 1;
}
// Successfully cloned all items, no need to clean up.
@@ -1757,7 +3618,7 @@ impl<T: Clone, A: Allocator + Clone> RawTable<T, A> {
{
self.clear();
- let guard_self = guard(&mut *self, |self_| {
+ let mut guard_self = guard(&mut *self, |self_| {
// Clear the partially copied table if a panic occurs, otherwise
// items and growth_left will be out of sync with the contents
// of the table.
@@ -1790,7 +3651,7 @@ impl<T: Clone, A: Allocator + Clone> RawTable<T, A> {
}
}
-impl<T, A: Allocator + Clone + Default> Default for RawTable<T, A> {
+impl<T, A: Allocator + Default> Default for RawTable<T, A> {
#[inline]
fn default() -> Self {
Self::new_in(Default::default())
@@ -1798,31 +3659,41 @@ impl<T, A: Allocator + Clone + Default> Default for RawTable<T, A> {
}
#[cfg(feature = "nightly")]
-unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawTable<T, A> {
+unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawTable<T, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn drop(&mut self) {
- if !self.table.is_empty_singleton() {
- unsafe {
- self.drop_elements();
- self.free_buckets();
- }
+ unsafe {
+ // SAFETY:
+ // 1. We call the function only once;
+ // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
+ // and [`TableLayout`] that were used to allocate this table.
+ // 3. If the drop function of any elements fails, then only a memory leak will occur,
+ // and we don't care because we are inside the `Drop` function of the `RawTable`,
+ // so there won't be any table left in an inconsistent state.
+ self.table
+ .drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
}
}
}
#[cfg(not(feature = "nightly"))]
-impl<T, A: Allocator + Clone> Drop for RawTable<T, A> {
+impl<T, A: Allocator> Drop for RawTable<T, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn drop(&mut self) {
- if !self.table.is_empty_singleton() {
- unsafe {
- self.drop_elements();
- self.free_buckets();
- }
+ unsafe {
+ // SAFETY:
+ // 1. We call the function only once;
+ // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
+ // and [`TableLayout`] that were used to allocate this table.
+ // 3. If the drop function of any elements fails, then only a memory leak will occur,
+ // and we don't care because we are inside the `Drop` function of the `RawTable`,
+ // so there won't be any table left in an inconsistent state.
+ self.table
+ .drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
}
}
}
-impl<T, A: Allocator + Clone> IntoIterator for RawTable<T, A> {
+impl<T, A: Allocator> IntoIterator for RawTable<T, A> {
type Item = T;
type IntoIter = RawIntoIter<T, A>;
@@ -1840,7 +3711,7 @@ impl<T, A: Allocator + Clone> IntoIterator for RawTable<T, A> {
pub(crate) struct RawIterRange<T> {
// Mask of full buckets in the current group. Bits are cleared from this
// mask as each element is processed.
- current_group: BitMask,
+ current_group: BitMaskIter,
// Pointer to the buckets for the current group.
data: Bucket<T>,
@@ -1856,19 +3727,44 @@ pub(crate) struct RawIterRange<T> {
impl<T> RawIterRange<T> {
/// Returns a `RawIterRange` covering a subset of a table.
///
- /// The control byte address must be aligned to the group size.
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is
+ /// [`undefined behavior`]:
+ ///
+ /// * `ctrl` must be [valid] for reads, i.e. table outlives the `RawIterRange`;
+ ///
+ /// * `ctrl` must be properly aligned to the group size (Group::WIDTH);
+ ///
+ /// * `ctrl` must point to the array of properly initialized control bytes;
+ ///
+ /// * `data` must be the [`Bucket`] at the `ctrl` index in the table;
+ ///
+ /// * the value of `len` must be less than or equal to the number of table buckets,
+ /// and the returned value of `ctrl.as_ptr().add(len).offset_from(ctrl.as_ptr())`
+ /// must be positive.
+ ///
+ /// * The `ctrl.add(len)` pointer must be either in bounds or one
+ /// byte past the end of the same [allocated table].
+ ///
+ /// * The `len` must be a power of two.
+ ///
+ /// [valid]: https://doc.rust-lang.org/std/ptr/index.html#safety
+ /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[cfg_attr(feature = "inline-more", inline)]
unsafe fn new(ctrl: *const u8, data: Bucket<T>, len: usize) -> Self {
debug_assert_ne!(len, 0);
debug_assert_eq!(ctrl as usize % Group::WIDTH, 0);
+ // SAFETY: The caller must uphold the safety rules for the [`RawIterRange::new`]
let end = ctrl.add(len);
// Load the first group and advance ctrl to point to the next group
+ // SAFETY: The caller must uphold the safety rules for the [`RawIterRange::new`]
let current_group = Group::load_aligned(ctrl).match_full();
let next_ctrl = ctrl.add(Group::WIDTH);
Self {
- current_group,
+ current_group: current_group.into_iter(),
data,
next_ctrl,
end,
@@ -1925,8 +3821,7 @@ impl<T> RawIterRange<T> {
#[cfg_attr(feature = "inline-more", inline)]
unsafe fn next_impl<const DO_CHECK_PTR_RANGE: bool>(&mut self) -> Option<Bucket<T>> {
loop {
- if let Some(index) = self.current_group.lowest_set_bit() {
- self.current_group = self.current_group.remove_lowest_bit();
+ if let Some(index) = self.current_group.next() {
return Some(self.data.next_n(index));
}
@@ -1939,7 +3834,86 @@ impl<T> RawIterRange<T> {
// than the group size where the trailing control bytes are all
// EMPTY. On larger tables self.end is guaranteed to be aligned
// to the group size (since tables are power-of-two sized).
- self.current_group = Group::load_aligned(self.next_ctrl).match_full();
+ self.current_group = Group::load_aligned(self.next_ctrl).match_full().into_iter();
+ self.data = self.data.next_n(Group::WIDTH);
+ self.next_ctrl = self.next_ctrl.add(Group::WIDTH);
+ }
+ }
+
+ /// Folds every element into an accumulator by applying an operation,
+ /// returning the final result.
+ ///
+ /// `fold_impl()` takes three arguments: the number of items remaining in
+ /// the iterator, an initial value, and a closure with two arguments: an
+ /// 'accumulator', and an element. The closure returns the value that the
+ /// accumulator should have for the next iteration.
+ ///
+ /// The initial value is the value the accumulator will have on the first call.
+ ///
+ /// After applying this closure to every element of the iterator, `fold_impl()`
+ /// returns the accumulator.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is
+ /// [`Undefined Behavior`]:
+ ///
+ /// * The [`RawTableInner`] / [`RawTable`] must be alive and not moved,
+ /// i.e. table outlives the `RawIterRange`;
+ ///
+ /// * The provided `n` value must match the actual number of items
+ /// in the table.
+ ///
+ /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[allow(clippy::while_let_on_iterator)]
+ #[cfg_attr(feature = "inline-more", inline)]
+ unsafe fn fold_impl<F, B>(mut self, mut n: usize, mut acc: B, mut f: F) -> B
+ where
+ F: FnMut(B, Bucket<T>) -> B,
+ {
+ loop {
+ while let Some(index) = self.current_group.next() {
+ // The returned `index` will always be in the range `0..Group::WIDTH`,
+ // so that calling `self.data.next_n(index)` is safe (see detailed explanation below).
+ debug_assert!(n != 0);
+ let bucket = self.data.next_n(index);
+ acc = f(acc, bucket);
+ n -= 1;
+ }
+
+ if n == 0 {
+ return acc;
+ }
+
+ // SAFETY: The caller of this function ensures that:
+ //
+ // 1. The provided `n` value matches the actual number of items in the table;
+ // 2. The table is alive and did not moved.
+ //
+ // Taking the above into account, we always stay within the bounds, because:
+ //
+ // 1. For tables smaller than the group width (self.buckets() <= Group::WIDTH),
+ // we will never end up in the given branch, since we should have already
+ // yielded all the elements of the table.
+ //
+ // 2. For tables larger than the group width. The number of buckets is a
+ // power of two (2 ^ n), Group::WIDTH is also power of two (2 ^ k). Since
+ // `(2 ^ n) > (2 ^ k)`, than `(2 ^ n) % (2 ^ k) = 0`. As we start from the
+ // start of the array of control bytes, and never try to iterate after
+ // getting all the elements, the last `self.current_group` will read bytes
+ // from the `self.buckets() - Group::WIDTH` index. We know also that
+ // `self.current_group.next()` will always retun indices within the range
+ // `0..Group::WIDTH`.
+ //
+ // Knowing all of the above and taking into account that we are synchronizing
+ // the `self.data` index with the index we used to read the `self.current_group`,
+ // the subsequent `self.data.next_n(index)` will always return a bucket with
+ // an index number less than `self.buckets()`.
+ //
+ // The last `self.next_ctrl`, whose index would be `self.buckets()`, will never
+ // actually be read, since we should have already yielded all the elements of
+ // the table.
+ self.current_group = Group::load_aligned(self.next_ctrl).match_full().into_iter();
self.data = self.data.next_n(Group::WIDTH);
self.next_ctrl = self.next_ctrl.add(Group::WIDTH);
}
@@ -2016,7 +3990,7 @@ impl<T> RawIter<T> {
/// This method should be called _before_ the removal is made. It is not necessary to call this
/// method if you are removing an item that this iterator yielded in the past.
#[cfg(feature = "raw")]
- pub fn reflect_remove(&mut self, b: &Bucket<T>) {
+ pub unsafe fn reflect_remove(&mut self, b: &Bucket<T>) {
self.reflect_toggle_full(b, false);
}
@@ -2030,36 +4004,76 @@ impl<T> RawIter<T> {
///
/// This method should be called _after_ the given insert is made.
#[cfg(feature = "raw")]
- pub fn reflect_insert(&mut self, b: &Bucket<T>) {
+ pub unsafe fn reflect_insert(&mut self, b: &Bucket<T>) {
self.reflect_toggle_full(b, true);
}
/// Refresh the iterator so that it reflects a change to the state of the given bucket.
#[cfg(feature = "raw")]
- fn reflect_toggle_full(&mut self, b: &Bucket<T>, is_insert: bool) {
- unsafe {
- if b.as_ptr() > self.iter.data.as_ptr() {
- // The iterator has already passed the bucket's group.
- // So the toggle isn't relevant to this iterator.
- return;
+ unsafe fn reflect_toggle_full(&mut self, b: &Bucket<T>, is_insert: bool) {
+ if b.as_ptr() > self.iter.data.as_ptr() {
+ // The iterator has already passed the bucket's group.
+ // So the toggle isn't relevant to this iterator.
+ return;
+ }
+
+ if self.iter.next_ctrl < self.iter.end
+ && b.as_ptr() <= self.iter.data.next_n(Group::WIDTH).as_ptr()
+ {
+ // The iterator has not yet reached the bucket's group.
+ // We don't need to reload anything, but we do need to adjust the item count.
+
+ if cfg!(debug_assertions) {
+ // Double-check that the user isn't lying to us by checking the bucket state.
+ // To do that, we need to find its control byte. We know that self.iter.data is
+ // at self.iter.next_ctrl - Group::WIDTH, so we work from there:
+ let offset = offset_from(self.iter.data.as_ptr(), b.as_ptr());
+ let ctrl = self.iter.next_ctrl.sub(Group::WIDTH).add(offset);
+ // This method should be called _before_ a removal, or _after_ an insert,
+ // so in both cases the ctrl byte should indicate that the bucket is full.
+ assert!(is_full(*ctrl));
}
- if self.iter.next_ctrl < self.iter.end
- && b.as_ptr() <= self.iter.data.next_n(Group::WIDTH).as_ptr()
- {
- // The iterator has not yet reached the bucket's group.
- // We don't need to reload anything, but we do need to adjust the item count.
+ if is_insert {
+ self.items += 1;
+ } else {
+ self.items -= 1;
+ }
- if cfg!(debug_assertions) {
- // Double-check that the user isn't lying to us by checking the bucket state.
- // To do that, we need to find its control byte. We know that self.iter.data is
- // at self.iter.next_ctrl - Group::WIDTH, so we work from there:
- let offset = offset_from(self.iter.data.as_ptr(), b.as_ptr());
- let ctrl = self.iter.next_ctrl.sub(Group::WIDTH).add(offset);
- // This method should be called _before_ a removal, or _after_ an insert,
- // so in both cases the ctrl byte should indicate that the bucket is full.
- assert!(is_full(*ctrl));
- }
+ return;
+ }
+
+ // The iterator is at the bucket group that the toggled bucket is in.
+ // We need to do two things:
+ //
+ // - Determine if the iterator already yielded the toggled bucket.
+ // If it did, we're done.
+ // - Otherwise, update the iterator cached group so that it won't
+ // yield a to-be-removed bucket, or _will_ yield a to-be-added bucket.
+ // We'll also need to update the item count accordingly.
+ if let Some(index) = self.iter.current_group.0.lowest_set_bit() {
+ let next_bucket = self.iter.data.next_n(index);
+ if b.as_ptr() > next_bucket.as_ptr() {
+ // The toggled bucket is "before" the bucket the iterator would yield next. We
+ // therefore don't need to do anything --- the iterator has already passed the
+ // bucket in question.
+ //
+ // The item count must already be correct, since a removal or insert "prior" to
+ // the iterator's position wouldn't affect the item count.
+ } else {
+ // The removed bucket is an upcoming bucket. We need to make sure it does _not_
+ // get yielded, and also that it's no longer included in the item count.
+ //
+ // NOTE: We can't just reload the group here, both since that might reflect
+ // inserts we've already passed, and because that might inadvertently unset the
+ // bits for _other_ removals. If we do that, we'd have to also decrement the
+ // item count for those other bits that we unset. But the presumably subsequent
+ // call to reflect for those buckets might _also_ decrement the item count.
+ // Instead, we _just_ flip the bit for the particular bucket the caller asked
+ // us to reflect.
+ let our_bit = offset_from(self.iter.data.as_ptr(), b.as_ptr());
+ let was_full = self.iter.current_group.flip(our_bit);
+ debug_assert_ne!(was_full, is_insert);
if is_insert {
self.items += 1;
@@ -2067,65 +4081,23 @@ impl<T> RawIter<T> {
self.items -= 1;
}
- return;
- }
-
- // The iterator is at the bucket group that the toggled bucket is in.
- // We need to do two things:
- //
- // - Determine if the iterator already yielded the toggled bucket.
- // If it did, we're done.
- // - Otherwise, update the iterator cached group so that it won't
- // yield a to-be-removed bucket, or _will_ yield a to-be-added bucket.
- // We'll also need to update the item count accordingly.
- if let Some(index) = self.iter.current_group.lowest_set_bit() {
- let next_bucket = self.iter.data.next_n(index);
- if b.as_ptr() > next_bucket.as_ptr() {
- // The toggled bucket is "before" the bucket the iterator would yield next. We
- // therefore don't need to do anything --- the iterator has already passed the
- // bucket in question.
- //
- // The item count must already be correct, since a removal or insert "prior" to
- // the iterator's position wouldn't affect the item count.
- } else {
- // The removed bucket is an upcoming bucket. We need to make sure it does _not_
- // get yielded, and also that it's no longer included in the item count.
- //
- // NOTE: We can't just reload the group here, both since that might reflect
- // inserts we've already passed, and because that might inadvertently unset the
- // bits for _other_ removals. If we do that, we'd have to also decrement the
- // item count for those other bits that we unset. But the presumably subsequent
- // call to reflect for those buckets might _also_ decrement the item count.
- // Instead, we _just_ flip the bit for the particular bucket the caller asked
- // us to reflect.
- let our_bit = offset_from(self.iter.data.as_ptr(), b.as_ptr());
- let was_full = self.iter.current_group.flip(our_bit);
- debug_assert_ne!(was_full, is_insert);
-
- if is_insert {
- self.items += 1;
+ if cfg!(debug_assertions) {
+ if b.as_ptr() == next_bucket.as_ptr() {
+ // The removed bucket should no longer be next
+ debug_assert_ne!(self.iter.current_group.0.lowest_set_bit(), Some(index));
} else {
- self.items -= 1;
- }
-
- if cfg!(debug_assertions) {
- if b.as_ptr() == next_bucket.as_ptr() {
- // The removed bucket should no longer be next
- debug_assert_ne!(self.iter.current_group.lowest_set_bit(), Some(index));
- } else {
- // We should not have changed what bucket comes next.
- debug_assert_eq!(self.iter.current_group.lowest_set_bit(), Some(index));
- }
+ // We should not have changed what bucket comes next.
+ debug_assert_eq!(self.iter.current_group.0.lowest_set_bit(), Some(index));
}
}
- } else {
- // We must have already iterated past the removed item.
}
+ } else {
+ // We must have already iterated past the removed item.
}
}
unsafe fn drop_elements(&mut self) {
- if mem::needs_drop::<T>() && self.len() != 0 {
+ if T::NEEDS_DROP && self.items != 0 {
for item in self {
item.drop();
}
@@ -2159,9 +4131,8 @@ impl<T> Iterator for RawIter<T> {
self.iter.next_impl::<false>()
};
- if nxt.is_some() {
- self.items -= 1;
- }
+ debug_assert!(nxt.is_some());
+ self.items -= 1;
nxt
}
@@ -2170,33 +4141,160 @@ impl<T> Iterator for RawIter<T> {
fn size_hint(&self) -> (usize, Option<usize>) {
(self.items, Some(self.items))
}
+
+ #[inline]
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ unsafe { self.iter.fold_impl(self.items, init, f) }
+ }
}
impl<T> ExactSizeIterator for RawIter<T> {}
impl<T> FusedIterator for RawIter<T> {}
+/// Iterator which returns an index of every full bucket in the table.
+///
+/// For maximum flexibility this iterator is not bound by a lifetime, but you
+/// must observe several rules when using it:
+/// - You must not free the hash table while iterating (including via growing/shrinking).
+/// - It is fine to erase a bucket that has been yielded by the iterator.
+/// - Erasing a bucket that has not yet been yielded by the iterator may still
+/// result in the iterator yielding index of that bucket.
+/// - It is unspecified whether an element inserted after the iterator was
+/// created will be yielded by that iterator.
+/// - The order in which the iterator yields indices of the buckets is unspecified
+/// and may change in the future.
+pub(crate) struct FullBucketsIndices {
+ // Mask of full buckets in the current group. Bits are cleared from this
+ // mask as each element is processed.
+ current_group: BitMaskIter,
+
+ // Initial value of the bytes' indices of the current group (relative
+ // to the start of the control bytes).
+ group_first_index: usize,
+
+ // Pointer to the current group of control bytes,
+ // Must be aligned to the group size (Group::WIDTH).
+ ctrl: NonNull<u8>,
+
+ // Number of elements in the table.
+ items: usize,
+}
+
+impl FullBucketsIndices {
+ /// Advances the iterator and returns the next value.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is
+ /// [`Undefined Behavior`]:
+ ///
+ /// * The [`RawTableInner`] / [`RawTable`] must be alive and not moved,
+ /// i.e. table outlives the `FullBucketsIndices`;
+ ///
+ /// * It never tries to iterate after getting all elements.
+ ///
+ /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[inline(always)]
+ unsafe fn next_impl(&mut self) -> Option<usize> {
+ loop {
+ if let Some(index) = self.current_group.next() {
+ // The returned `self.group_first_index + index` will always
+ // be in the range `0..self.buckets()`. See explanation below.
+ return Some(self.group_first_index + index);
+ }
+
+ // SAFETY: The caller of this function ensures that:
+ //
+ // 1. It never tries to iterate after getting all the elements;
+ // 2. The table is alive and did not moved;
+ // 3. The first `self.ctrl` pointed to the start of the array of control bytes.
+ //
+ // Taking the above into account, we always stay within the bounds, because:
+ //
+ // 1. For tables smaller than the group width (self.buckets() <= Group::WIDTH),
+ // we will never end up in the given branch, since we should have already
+ // yielded all the elements of the table.
+ //
+ // 2. For tables larger than the group width. The number of buckets is a
+ // power of two (2 ^ n), Group::WIDTH is also power of two (2 ^ k). Since
+ // `(2 ^ n) > (2 ^ k)`, than `(2 ^ n) % (2 ^ k) = 0`. As we start from the
+ // the start of the array of control bytes, and never try to iterate after
+ // getting all the elements, the last `self.ctrl` will be equal to
+ // the `self.buckets() - Group::WIDTH`, so `self.current_group.next()`
+ // will always contains indices within the range `0..Group::WIDTH`,
+ // and subsequent `self.group_first_index + index` will always return a
+ // number less than `self.buckets()`.
+ self.ctrl = NonNull::new_unchecked(self.ctrl.as_ptr().add(Group::WIDTH));
+
+ // SAFETY: See explanation above.
+ self.current_group = Group::load_aligned(self.ctrl.as_ptr())
+ .match_full()
+ .into_iter();
+ self.group_first_index += Group::WIDTH;
+ }
+ }
+}
+
+impl Iterator for FullBucketsIndices {
+ type Item = usize;
+
+ /// Advances the iterator and returns the next value. It is up to
+ /// the caller to ensure that the `RawTable` outlives the `FullBucketsIndices`,
+ /// because we cannot make the `next` method unsafe.
+ #[inline(always)]
+ fn next(&mut self) -> Option<usize> {
+ // Return if we already yielded all items.
+ if self.items == 0 {
+ return None;
+ }
+
+ let nxt = unsafe {
+ // SAFETY:
+ // 1. We check number of items to yield using `items` field.
+ // 2. The caller ensures that the table is alive and has not moved.
+ self.next_impl()
+ };
+
+ debug_assert!(nxt.is_some());
+ self.items -= 1;
+
+ nxt
+ }
+
+ #[inline(always)]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.items, Some(self.items))
+ }
+}
+
+impl ExactSizeIterator for FullBucketsIndices {}
+impl FusedIterator for FullBucketsIndices {}
+
/// Iterator which consumes a table and returns elements.
-pub struct RawIntoIter<T, A: Allocator + Clone = Global> {
+pub struct RawIntoIter<T, A: Allocator = Global> {
iter: RawIter<T>,
- allocation: Option<(NonNull<u8>, Layout)>,
+ allocation: Option<(NonNull<u8>, Layout, A)>,
marker: PhantomData<T>,
- alloc: A,
}
-impl<T, A: Allocator + Clone> RawIntoIter<T, A> {
+impl<T, A: Allocator> RawIntoIter<T, A> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn iter(&self) -> RawIter<T> {
self.iter.clone()
}
}
-unsafe impl<T, A: Allocator + Clone> Send for RawIntoIter<T, A>
+unsafe impl<T, A: Allocator> Send for RawIntoIter<T, A>
where
T: Send,
A: Send,
{
}
-unsafe impl<T, A: Allocator + Clone> Sync for RawIntoIter<T, A>
+unsafe impl<T, A: Allocator> Sync for RawIntoIter<T, A>
where
T: Sync,
A: Sync,
@@ -2204,7 +4302,7 @@ where
}
#[cfg(feature = "nightly")]
-unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawIntoIter<T, A> {
+unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawIntoIter<T, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn drop(&mut self) {
unsafe {
@@ -2212,14 +4310,14 @@ unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawIntoIter<T, A> {
self.iter.drop_elements();
// Free the table
- if let Some((ptr, layout)) = self.allocation {
- self.alloc.deallocate(ptr, layout);
+ if let Some((ptr, layout, ref alloc)) = self.allocation {
+ alloc.deallocate(ptr, layout);
}
}
}
}
#[cfg(not(feature = "nightly"))]
-impl<T, A: Allocator + Clone> Drop for RawIntoIter<T, A> {
+impl<T, A: Allocator> Drop for RawIntoIter<T, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn drop(&mut self) {
unsafe {
@@ -2227,14 +4325,14 @@ impl<T, A: Allocator + Clone> Drop for RawIntoIter<T, A> {
self.iter.drop_elements();
// Free the table
- if let Some((ptr, layout)) = self.allocation {
- self.alloc.deallocate(ptr, layout);
+ if let Some((ptr, layout, ref alloc)) = self.allocation {
+ alloc.deallocate(ptr, layout);
}
}
}
}
-impl<T, A: Allocator + Clone> Iterator for RawIntoIter<T, A> {
+impl<T, A: Allocator> Iterator for RawIntoIter<T, A> {
type Item = T;
#[cfg_attr(feature = "inline-more", inline)]
@@ -2248,45 +4346,45 @@ impl<T, A: Allocator + Clone> Iterator for RawIntoIter<T, A> {
}
}
-impl<T, A: Allocator + Clone> ExactSizeIterator for RawIntoIter<T, A> {}
-impl<T, A: Allocator + Clone> FusedIterator for RawIntoIter<T, A> {}
+impl<T, A: Allocator> ExactSizeIterator for RawIntoIter<T, A> {}
+impl<T, A: Allocator> FusedIterator for RawIntoIter<T, A> {}
/// Iterator which consumes elements without freeing the table storage.
-pub struct RawDrain<'a, T, A: Allocator + Clone = Global> {
+pub struct RawDrain<'a, T, A: Allocator = Global> {
iter: RawIter<T>,
// The table is moved into the iterator for the duration of the drain. This
// ensures that an empty table is left if the drain iterator is leaked
// without dropping.
- table: ManuallyDrop<RawTable<T, A>>,
- orig_table: NonNull<RawTable<T, A>>,
+ table: RawTableInner,
+ orig_table: NonNull<RawTableInner>,
// We don't use a &'a mut RawTable<T> because we want RawDrain to be
// covariant over T.
marker: PhantomData<&'a RawTable<T, A>>,
}
-impl<T, A: Allocator + Clone> RawDrain<'_, T, A> {
+impl<T, A: Allocator> RawDrain<'_, T, A> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn iter(&self) -> RawIter<T> {
self.iter.clone()
}
}
-unsafe impl<T, A: Allocator + Copy> Send for RawDrain<'_, T, A>
+unsafe impl<T, A: Allocator> Send for RawDrain<'_, T, A>
where
T: Send,
A: Send,
{
}
-unsafe impl<T, A: Allocator + Copy> Sync for RawDrain<'_, T, A>
+unsafe impl<T, A: Allocator> Sync for RawDrain<'_, T, A>
where
T: Sync,
A: Sync,
{
}
-impl<T, A: Allocator + Clone> Drop for RawDrain<'_, T, A> {
+impl<T, A: Allocator> Drop for RawDrain<'_, T, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn drop(&mut self) {
unsafe {
@@ -2300,12 +4398,12 @@ impl<T, A: Allocator + Clone> Drop for RawDrain<'_, T, A> {
// Move the now empty table back to its original location.
self.orig_table
.as_ptr()
- .copy_from_nonoverlapping(&*self.table, 1);
+ .copy_from_nonoverlapping(&self.table, 1);
}
}
}
-impl<T, A: Allocator + Clone> Iterator for RawDrain<'_, T, A> {
+impl<T, A: Allocator> Iterator for RawDrain<'_, T, A> {
type Item = T;
#[cfg_attr(feature = "inline-more", inline)]
@@ -2322,21 +4420,36 @@ impl<T, A: Allocator + Clone> Iterator for RawDrain<'_, T, A> {
}
}
-impl<T, A: Allocator + Clone> ExactSizeIterator for RawDrain<'_, T, A> {}
-impl<T, A: Allocator + Clone> FusedIterator for RawDrain<'_, T, A> {}
+impl<T, A: Allocator> ExactSizeIterator for RawDrain<'_, T, A> {}
+impl<T, A: Allocator> FusedIterator for RawDrain<'_, T, A> {}
/// Iterator over occupied buckets that could match a given hash.
///
/// `RawTable` only stores 7 bits of the hash value, so this iterator may return
/// items that have a hash value different than the one provided. You should
/// always validate the returned values before using them.
-pub struct RawIterHash<'a, T, A: Allocator + Clone = Global> {
- inner: RawIterHashInner<'a, A>,
+///
+/// For maximum flexibility this iterator is not bound by a lifetime, but you
+/// must observe several rules when using it:
+/// - You must not free the hash table while iterating (including via growing/shrinking).
+/// - It is fine to erase a bucket that has been yielded by the iterator.
+/// - Erasing a bucket that has not yet been yielded by the iterator may still
+/// result in the iterator yielding that bucket.
+/// - It is unspecified whether an element inserted after the iterator was
+/// created will be yielded by that iterator.
+/// - The order in which the iterator yields buckets is unspecified and may
+/// change in the future.
+pub struct RawIterHash<T> {
+ inner: RawIterHashInner,
_marker: PhantomData<T>,
}
-struct RawIterHashInner<'a, A: Allocator + Clone> {
- table: &'a RawTableInner<A>,
+struct RawIterHashInner {
+ // See `RawTableInner`'s corresponding fields for details.
+ // We can't store a `*const RawTableInner` as it would get
+ // invalidated by the user calling `&mut` methods on `RawTable`.
+ bucket_mask: usize,
+ ctrl: NonNull<u8>,
// The top 7 bits of the hash.
h2_hash: u8,
@@ -2350,71 +4463,105 @@ struct RawIterHashInner<'a, A: Allocator + Clone> {
bitmask: BitMaskIter,
}
-impl<'a, T, A: Allocator + Clone> RawIterHash<'a, T, A> {
+impl<T> RawIterHash<T> {
#[cfg_attr(feature = "inline-more", inline)]
#[cfg(feature = "raw")]
- fn new(table: &'a RawTable<T, A>, hash: u64) -> Self {
+ unsafe fn new<A: Allocator>(table: &RawTable<T, A>, hash: u64) -> Self {
RawIterHash {
inner: RawIterHashInner::new(&table.table, hash),
_marker: PhantomData,
}
}
}
-impl<'a, A: Allocator + Clone> RawIterHashInner<'a, A> {
+impl RawIterHashInner {
#[cfg_attr(feature = "inline-more", inline)]
#[cfg(feature = "raw")]
- fn new(table: &'a RawTableInner<A>, hash: u64) -> Self {
- unsafe {
- let h2_hash = h2(hash);
- let probe_seq = table.probe_seq(hash);
- let group = Group::load(table.ctrl(probe_seq.pos));
- let bitmask = group.match_byte(h2_hash).into_iter();
-
- RawIterHashInner {
- table,
- h2_hash,
- probe_seq,
- group,
- bitmask,
- }
+ unsafe fn new(table: &RawTableInner, hash: u64) -> Self {
+ let h2_hash = h2(hash);
+ let probe_seq = table.probe_seq(hash);
+ let group = Group::load(table.ctrl(probe_seq.pos));
+ let bitmask = group.match_byte(h2_hash).into_iter();
+
+ RawIterHashInner {
+ bucket_mask: table.bucket_mask,
+ ctrl: table.ctrl,
+ h2_hash,
+ probe_seq,
+ group,
+ bitmask,
}
}
}
-impl<'a, T, A: Allocator + Clone> Iterator for RawIterHash<'a, T, A> {
+impl<T> Iterator for RawIterHash<T> {
type Item = Bucket<T>;
fn next(&mut self) -> Option<Bucket<T>> {
unsafe {
match self.inner.next() {
- Some(index) => Some(self.inner.table.bucket(index)),
+ Some(index) => {
+ // Can't use `RawTable::bucket` here as we don't have
+ // an actual `RawTable` reference to use.
+ debug_assert!(index <= self.inner.bucket_mask);
+ let bucket = Bucket::from_base_index(self.inner.ctrl.cast(), index);
+ Some(bucket)
+ }
None => None,
}
}
}
}
-impl<'a, A: Allocator + Clone> Iterator for RawIterHashInner<'a, A> {
+impl Iterator for RawIterHashInner {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
loop {
if let Some(bit) = self.bitmask.next() {
- let index = (self.probe_seq.pos + bit) & self.table.bucket_mask;
+ let index = (self.probe_seq.pos + bit) & self.bucket_mask;
return Some(index);
}
if likely(self.group.match_empty().any_bit_set()) {
return None;
}
- self.probe_seq.move_next(self.table.bucket_mask);
- self.group = Group::load(self.table.ctrl(self.probe_seq.pos));
+ self.probe_seq.move_next(self.bucket_mask);
+
+ // Can't use `RawTableInner::ctrl` here as we don't have
+ // an actual `RawTableInner` reference to use.
+ let index = self.probe_seq.pos;
+ debug_assert!(index < self.bucket_mask + 1 + Group::WIDTH);
+ let group_ctrl = self.ctrl.as_ptr().add(index);
+
+ self.group = Group::load(group_ctrl);
self.bitmask = self.group.match_byte(self.h2_hash).into_iter();
}
}
}
}
+pub(crate) struct RawExtractIf<'a, T, A: Allocator> {
+ pub iter: RawIter<T>,
+ pub table: &'a mut RawTable<T, A>,
+}
+
+impl<T, A: Allocator> RawExtractIf<'_, T, A> {
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub(crate) fn next<F>(&mut self, mut f: F) -> Option<T>
+ where
+ F: FnMut(&mut T) -> bool,
+ {
+ unsafe {
+ for item in &mut self.iter {
+ if f(item.as_mut()) {
+ return Some(self.table.remove(item).0);
+ }
+ }
+ }
+ None
+ }
+}
+
#[cfg(test)]
mod test_map {
use super::*;
@@ -2457,4 +4604,214 @@ mod test_map {
assert!(table.find(i + 100, |x| *x == i + 100).is_none());
}
}
+
+ /// CHECKING THAT WE ARE NOT TRYING TO READ THE MEMORY OF
+ /// AN UNINITIALIZED TABLE DURING THE DROP
+ #[test]
+ fn test_drop_uninitialized() {
+ use ::alloc::vec::Vec;
+
+ let table = unsafe {
+ // SAFETY: The `buckets` is power of two and we're not
+ // trying to actually use the returned RawTable.
+ RawTable::<(u64, Vec<i32>)>::new_uninitialized(Global, 8, Fallibility::Infallible)
+ .unwrap()
+ };
+ drop(table);
+ }
+
+ /// CHECKING THAT WE DON'T TRY TO DROP DATA IF THE `ITEMS`
+ /// ARE ZERO, EVEN IF WE HAVE `FULL` CONTROL BYTES.
+ #[test]
+ fn test_drop_zero_items() {
+ use ::alloc::vec::Vec;
+ unsafe {
+ // SAFETY: The `buckets` is power of two and we're not
+ // trying to actually use the returned RawTable.
+ let table =
+ RawTable::<(u64, Vec<i32>)>::new_uninitialized(Global, 8, Fallibility::Infallible)
+ .unwrap();
+
+ // WE SIMULATE, AS IT WERE, A FULL TABLE.
+
+ // SAFETY: We checked that the table is allocated and therefore the table already has
+ // `self.bucket_mask + 1 + Group::WIDTH` number of control bytes (see TableLayout::calculate_layout_for)
+ // so writing `table.table.num_ctrl_bytes() == bucket_mask + 1 + Group::WIDTH` bytes is safe.
+ table
+ .table
+ .ctrl(0)
+ .write_bytes(EMPTY, table.table.num_ctrl_bytes());
+
+ // SAFETY: table.capacity() is guaranteed to be smaller than table.buckets()
+ table.table.ctrl(0).write_bytes(0, table.capacity());
+
+ // Fix up the trailing control bytes. See the comments in set_ctrl
+ // for the handling of tables smaller than the group width.
+ if table.buckets() < Group::WIDTH {
+ // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of control bytes,
+ // so copying `self.buckets() == self.bucket_mask + 1` bytes with offset equal to
+ // `Group::WIDTH` is safe
+ table
+ .table
+ .ctrl(0)
+ .copy_to(table.table.ctrl(Group::WIDTH), table.table.buckets());
+ } else {
+ // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of
+ // control bytes,so copying `Group::WIDTH` bytes with offset equal
+ // to `self.buckets() == self.bucket_mask + 1` is safe
+ table
+ .table
+ .ctrl(0)
+ .copy_to(table.table.ctrl(table.table.buckets()), Group::WIDTH);
+ }
+ drop(table);
+ }
+ }
+
+ /// CHECKING THAT WE DON'T TRY TO DROP DATA IF THE `ITEMS`
+ /// ARE ZERO, EVEN IF WE HAVE `FULL` CONTROL BYTES.
+ #[test]
+ fn test_catch_panic_clone_from() {
+ use ::alloc::sync::Arc;
+ use ::alloc::vec::Vec;
+ use allocator_api2::alloc::{AllocError, Allocator, Global};
+ use core::sync::atomic::{AtomicI8, Ordering};
+ use std::thread;
+
+ struct MyAllocInner {
+ drop_count: Arc<AtomicI8>,
+ }
+
+ #[derive(Clone)]
+ struct MyAlloc {
+ _inner: Arc<MyAllocInner>,
+ }
+
+ impl Drop for MyAllocInner {
+ fn drop(&mut self) {
+ println!("MyAlloc freed.");
+ self.drop_count.fetch_sub(1, Ordering::SeqCst);
+ }
+ }
+
+ unsafe impl Allocator for MyAlloc {
+ fn allocate(&self, layout: Layout) -> std::result::Result<NonNull<[u8]>, AllocError> {
+ let g = Global;
+ g.allocate(layout)
+ }
+
+ unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+ let g = Global;
+ g.deallocate(ptr, layout)
+ }
+ }
+
+ const DISARMED: bool = false;
+ const ARMED: bool = true;
+
+ struct CheckedCloneDrop {
+ panic_in_clone: bool,
+ dropped: bool,
+ need_drop: Vec<u64>,
+ }
+
+ impl Clone for CheckedCloneDrop {
+ fn clone(&self) -> Self {
+ if self.panic_in_clone {
+ panic!("panic in clone")
+ }
+ Self {
+ panic_in_clone: self.panic_in_clone,
+ dropped: self.dropped,
+ need_drop: self.need_drop.clone(),
+ }
+ }
+ }
+
+ impl Drop for CheckedCloneDrop {
+ fn drop(&mut self) {
+ if self.dropped {
+ panic!("double drop");
+ }
+ self.dropped = true;
+ }
+ }
+
+ let dropped: Arc<AtomicI8> = Arc::new(AtomicI8::new(2));
+
+ let mut table = RawTable::new_in(MyAlloc {
+ _inner: Arc::new(MyAllocInner {
+ drop_count: dropped.clone(),
+ }),
+ });
+
+ for (idx, panic_in_clone) in core::iter::repeat(DISARMED).take(7).enumerate() {
+ let idx = idx as u64;
+ table.insert(
+ idx,
+ (
+ idx,
+ CheckedCloneDrop {
+ panic_in_clone,
+ dropped: false,
+ need_drop: vec![idx],
+ },
+ ),
+ |(k, _)| *k,
+ );
+ }
+
+ assert_eq!(table.len(), 7);
+
+ thread::scope(|s| {
+ let result = s.spawn(|| {
+ let armed_flags = [
+ DISARMED, DISARMED, ARMED, DISARMED, DISARMED, DISARMED, DISARMED,
+ ];
+ let mut scope_table = RawTable::new_in(MyAlloc {
+ _inner: Arc::new(MyAllocInner {
+ drop_count: dropped.clone(),
+ }),
+ });
+ for (idx, &panic_in_clone) in armed_flags.iter().enumerate() {
+ let idx = idx as u64;
+ scope_table.insert(
+ idx,
+ (
+ idx,
+ CheckedCloneDrop {
+ panic_in_clone,
+ dropped: false,
+ need_drop: vec![idx + 100],
+ },
+ ),
+ |(k, _)| *k,
+ );
+ }
+ table.clone_from(&scope_table);
+ });
+ assert!(result.join().is_err());
+ });
+
+ // Let's check that all iterators work fine and do not return elements
+ // (especially `RawIterRange`, which does not depend on the number of
+ // elements in the table, but looks directly at the control bytes)
+ //
+ // SAFETY: We know for sure that `RawTable` will outlive
+ // the returned `RawIter / RawIterRange` iterator.
+ assert_eq!(table.len(), 0);
+ assert_eq!(unsafe { table.iter().count() }, 0);
+ assert_eq!(unsafe { table.iter().iter.count() }, 0);
+
+ for idx in 0..table.buckets() {
+ let idx = idx as u64;
+ assert!(
+ table.find(idx, |(k, _)| *k == idx).is_none(),
+ "Index: {idx}"
+ );
+ }
+
+ // All allocator clones should already be dropped.
+ assert_eq!(dropped.load(Ordering::SeqCst), 1);
+ }
}
diff --git a/third_party/rust/hashbrown/src/raw/neon.rs b/third_party/rust/hashbrown/src/raw/neon.rs
new file mode 100644
index 0000000000..44e82d57d5
--- /dev/null
+++ b/third_party/rust/hashbrown/src/raw/neon.rs
@@ -0,0 +1,124 @@
+use super::bitmask::BitMask;
+use super::EMPTY;
+use core::arch::aarch64 as neon;
+use core::mem;
+use core::num::NonZeroU64;
+
+pub(crate) type BitMaskWord = u64;
+pub(crate) type NonZeroBitMaskWord = NonZeroU64;
+pub(crate) const BITMASK_STRIDE: usize = 8;
+pub(crate) const BITMASK_MASK: BitMaskWord = !0;
+pub(crate) const BITMASK_ITER_MASK: BitMaskWord = 0x8080_8080_8080_8080;
+
+/// Abstraction over a group of control bytes which can be scanned in
+/// parallel.
+///
+/// This implementation uses a 64-bit NEON value.
+#[derive(Copy, Clone)]
+pub(crate) struct Group(neon::uint8x8_t);
+
+#[allow(clippy::use_self)]
+impl Group {
+ /// Number of bytes in the group.
+ pub(crate) const WIDTH: usize = mem::size_of::<Self>();
+
+ /// Returns a full group of empty bytes, suitable for use as the initial
+ /// value for an empty hash table.
+ ///
+ /// This is guaranteed to be aligned to the group size.
+ #[inline]
+ pub(crate) const fn static_empty() -> &'static [u8; Group::WIDTH] {
+ #[repr(C)]
+ struct AlignedBytes {
+ _align: [Group; 0],
+ bytes: [u8; Group::WIDTH],
+ }
+ const ALIGNED_BYTES: AlignedBytes = AlignedBytes {
+ _align: [],
+ bytes: [EMPTY; Group::WIDTH],
+ };
+ &ALIGNED_BYTES.bytes
+ }
+
+ /// Loads a group of bytes starting at the given address.
+ #[inline]
+ #[allow(clippy::cast_ptr_alignment)] // unaligned load
+ pub(crate) unsafe fn load(ptr: *const u8) -> Self {
+ Group(neon::vld1_u8(ptr))
+ }
+
+ /// Loads a group of bytes starting at the given address, which must be
+ /// aligned to `mem::align_of::<Group>()`.
+ #[inline]
+ #[allow(clippy::cast_ptr_alignment)]
+ pub(crate) unsafe fn load_aligned(ptr: *const u8) -> Self {
+ // FIXME: use align_offset once it stabilizes
+ debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
+ Group(neon::vld1_u8(ptr))
+ }
+
+ /// Stores the group of bytes to the given address, which must be
+ /// aligned to `mem::align_of::<Group>()`.
+ #[inline]
+ #[allow(clippy::cast_ptr_alignment)]
+ pub(crate) unsafe fn store_aligned(self, ptr: *mut u8) {
+ // FIXME: use align_offset once it stabilizes
+ debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
+ neon::vst1_u8(ptr, self.0);
+ }
+
+ /// Returns a `BitMask` indicating all bytes in the group which *may*
+ /// have the given value.
+ #[inline]
+ pub(crate) fn match_byte(self, byte: u8) -> BitMask {
+ unsafe {
+ let cmp = neon::vceq_u8(self.0, neon::vdup_n_u8(byte));
+ BitMask(neon::vget_lane_u64(neon::vreinterpret_u64_u8(cmp), 0))
+ }
+ }
+
+ /// Returns a `BitMask` indicating all bytes in the group which are
+ /// `EMPTY`.
+ #[inline]
+ pub(crate) fn match_empty(self) -> BitMask {
+ self.match_byte(EMPTY)
+ }
+
+ /// Returns a `BitMask` indicating all bytes in the group which are
+ /// `EMPTY` or `DELETED`.
+ #[inline]
+ pub(crate) fn match_empty_or_deleted(self) -> BitMask {
+ unsafe {
+ let cmp = neon::vcltz_s8(neon::vreinterpret_s8_u8(self.0));
+ BitMask(neon::vget_lane_u64(neon::vreinterpret_u64_u8(cmp), 0))
+ }
+ }
+
+ /// Returns a `BitMask` indicating all bytes in the group which are full.
+ #[inline]
+ pub(crate) fn match_full(self) -> BitMask {
+ unsafe {
+ let cmp = neon::vcgez_s8(neon::vreinterpret_s8_u8(self.0));
+ BitMask(neon::vget_lane_u64(neon::vreinterpret_u64_u8(cmp), 0))
+ }
+ }
+
+ /// Performs the following transformation on all bytes in the group:
+ /// - `EMPTY => EMPTY`
+ /// - `DELETED => EMPTY`
+ /// - `FULL => DELETED`
+ #[inline]
+ pub(crate) fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
+ // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
+ // and high_bit = 0 (FULL) to 1000_0000
+ //
+ // Here's this logic expanded to concrete values:
+ // let special = 0 > byte = 1111_1111 (true) or 0000_0000 (false)
+ // 1111_1111 | 1000_0000 = 1111_1111
+ // 0000_0000 | 1000_0000 = 1000_0000
+ unsafe {
+ let special = neon::vcltz_s8(neon::vreinterpret_s8_u8(self.0));
+ Group(neon::vorr_u8(special, neon::vdup_n_u8(0x80)))
+ }
+ }
+}
diff --git a/third_party/rust/hashbrown/src/raw/sse2.rs b/third_party/rust/hashbrown/src/raw/sse2.rs
index a0bf6da804..956ba5d265 100644
--- a/third_party/rust/hashbrown/src/raw/sse2.rs
+++ b/third_party/rust/hashbrown/src/raw/sse2.rs
@@ -1,28 +1,31 @@
use super::bitmask::BitMask;
use super::EMPTY;
use core::mem;
+use core::num::NonZeroU16;
#[cfg(target_arch = "x86")]
use core::arch::x86;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64 as x86;
-pub type BitMaskWord = u16;
-pub const BITMASK_STRIDE: usize = 1;
-pub const BITMASK_MASK: BitMaskWord = 0xffff;
+pub(crate) type BitMaskWord = u16;
+pub(crate) type NonZeroBitMaskWord = NonZeroU16;
+pub(crate) const BITMASK_STRIDE: usize = 1;
+pub(crate) const BITMASK_MASK: BitMaskWord = 0xffff;
+pub(crate) const BITMASK_ITER_MASK: BitMaskWord = !0;
/// Abstraction over a group of control bytes which can be scanned in
/// parallel.
///
/// This implementation uses a 128-bit SSE value.
#[derive(Copy, Clone)]
-pub struct Group(x86::__m128i);
+pub(crate) struct Group(x86::__m128i);
// FIXME: https://github.com/rust-lang/rust-clippy/issues/3859
#[allow(clippy::use_self)]
impl Group {
/// Number of bytes in the group.
- pub const WIDTH: usize = mem::size_of::<Self>();
+ pub(crate) const WIDTH: usize = mem::size_of::<Self>();
/// Returns a full group of empty bytes, suitable for use as the initial
/// value for an empty hash table.
@@ -30,7 +33,7 @@ impl Group {
/// This is guaranteed to be aligned to the group size.
#[inline]
#[allow(clippy::items_after_statements)]
- pub const fn static_empty() -> &'static [u8; Group::WIDTH] {
+ pub(crate) const fn static_empty() -> &'static [u8; Group::WIDTH] {
#[repr(C)]
struct AlignedBytes {
_align: [Group; 0],
@@ -46,7 +49,7 @@ impl Group {
/// Loads a group of bytes starting at the given address.
#[inline]
#[allow(clippy::cast_ptr_alignment)] // unaligned load
- pub unsafe fn load(ptr: *const u8) -> Self {
+ pub(crate) unsafe fn load(ptr: *const u8) -> Self {
Group(x86::_mm_loadu_si128(ptr.cast()))
}
@@ -54,7 +57,7 @@ impl Group {
/// aligned to `mem::align_of::<Group>()`.
#[inline]
#[allow(clippy::cast_ptr_alignment)]
- pub unsafe fn load_aligned(ptr: *const u8) -> Self {
+ pub(crate) unsafe fn load_aligned(ptr: *const u8) -> Self {
// FIXME: use align_offset once it stabilizes
debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
Group(x86::_mm_load_si128(ptr.cast()))
@@ -64,7 +67,7 @@ impl Group {
/// aligned to `mem::align_of::<Group>()`.
#[inline]
#[allow(clippy::cast_ptr_alignment)]
- pub unsafe fn store_aligned(self, ptr: *mut u8) {
+ pub(crate) unsafe fn store_aligned(self, ptr: *mut u8) {
// FIXME: use align_offset once it stabilizes
debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
x86::_mm_store_si128(ptr.cast(), self.0);
@@ -73,7 +76,7 @@ impl Group {
/// Returns a `BitMask` indicating all bytes in the group which have
/// the given value.
#[inline]
- pub fn match_byte(self, byte: u8) -> BitMask {
+ pub(crate) fn match_byte(self, byte: u8) -> BitMask {
#[allow(
clippy::cast_possible_wrap, // byte: u8 as i8
// byte: i32 as u16
@@ -91,14 +94,14 @@ impl Group {
/// Returns a `BitMask` indicating all bytes in the group which are
/// `EMPTY`.
#[inline]
- pub fn match_empty(self) -> BitMask {
+ pub(crate) fn match_empty(self) -> BitMask {
self.match_byte(EMPTY)
}
/// Returns a `BitMask` indicating all bytes in the group which are
/// `EMPTY` or `DELETED`.
#[inline]
- pub fn match_empty_or_deleted(self) -> BitMask {
+ pub(crate) fn match_empty_or_deleted(self) -> BitMask {
#[allow(
// byte: i32 as u16
// note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the
@@ -114,7 +117,7 @@ impl Group {
/// Returns a `BitMask` indicating all bytes in the group which are full.
#[inline]
- pub fn match_full(&self) -> BitMask {
+ pub(crate) fn match_full(&self) -> BitMask {
self.match_empty_or_deleted().invert()
}
@@ -123,7 +126,7 @@ impl Group {
/// - `DELETED => EMPTY`
/// - `FULL => DELETED`
#[inline]
- pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
+ pub(crate) fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
// Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
// and high_bit = 0 (FULL) to 1000_0000
//
diff --git a/third_party/rust/hashbrown/src/rustc_entry.rs b/third_party/rust/hashbrown/src/rustc_entry.rs
index 2e84595269..defbd4bb88 100644
--- a/third_party/rust/hashbrown/src/rustc_entry.rs
+++ b/third_party/rust/hashbrown/src/rustc_entry.rs
@@ -1,5 +1,5 @@
use self::RustcEntry::*;
-use crate::map::{make_insert_hash, Drain, HashMap, IntoIter, Iter, IterMut};
+use crate::map::{make_hash, Drain, HashMap, IntoIter, Iter, IterMut};
use crate::raw::{Allocator, Bucket, Global, RawTable};
use core::fmt::{self, Debug};
use core::hash::{BuildHasher, Hash};
@@ -9,7 +9,7 @@ impl<K, V, S, A> HashMap<K, V, S, A>
where
K: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
/// Gets the given key's corresponding entry in the map for in-place manipulation.
///
@@ -32,7 +32,7 @@ where
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn rustc_entry(&mut self, key: K) -> RustcEntry<'_, K, V, A> {
- let hash = make_insert_hash(&self.hash_builder, &key);
+ let hash = make_hash(&self.hash_builder, &key);
if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) {
RustcEntry::Occupied(RustcOccupiedEntry {
key: Some(key),
@@ -62,7 +62,7 @@ where
/// [`rustc_entry`]: struct.HashMap.html#method.rustc_entry
pub enum RustcEntry<'a, K, V, A = Global>
where
- A: Allocator + Clone,
+ A: Allocator,
{
/// An occupied entry.
Occupied(RustcOccupiedEntry<'a, K, V, A>),
@@ -71,7 +71,7 @@ where
Vacant(RustcVacantEntry<'a, K, V, A>),
}
-impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for RustcEntry<'_, K, V, A> {
+impl<K: Debug, V: Debug, A: Allocator> Debug for RustcEntry<'_, K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
@@ -86,7 +86,7 @@ impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for RustcEntry<'_, K, V, A>
/// [`RustcEntry`]: enum.RustcEntry.html
pub struct RustcOccupiedEntry<'a, K, V, A = Global>
where
- A: Allocator + Clone,
+ A: Allocator,
{
key: Option<K>,
elem: Bucket<(K, V)>,
@@ -97,18 +97,18 @@ unsafe impl<K, V, A> Send for RustcOccupiedEntry<'_, K, V, A>
where
K: Send,
V: Send,
- A: Allocator + Clone + Send,
+ A: Allocator + Send,
{
}
unsafe impl<K, V, A> Sync for RustcOccupiedEntry<'_, K, V, A>
where
K: Sync,
V: Sync,
- A: Allocator + Clone + Sync,
+ A: Allocator + Sync,
{
}
-impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for RustcOccupiedEntry<'_, K, V, A> {
+impl<K: Debug, V: Debug, A: Allocator> Debug for RustcOccupiedEntry<'_, K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
@@ -123,20 +123,20 @@ impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for RustcOccupiedEntry<'_,
/// [`RustcEntry`]: enum.RustcEntry.html
pub struct RustcVacantEntry<'a, K, V, A = Global>
where
- A: Allocator + Clone,
+ A: Allocator,
{
hash: u64,
key: K,
table: &'a mut RawTable<(K, V), A>,
}
-impl<K: Debug, V, A: Allocator + Clone> Debug for RustcVacantEntry<'_, K, V, A> {
+impl<K: Debug, V, A: Allocator> Debug for RustcVacantEntry<'_, K, V, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VacantEntry").field(self.key()).finish()
}
}
-impl<'a, K, V, A: Allocator + Clone> RustcEntry<'a, K, V, A> {
+impl<'a, K, V, A: Allocator> RustcEntry<'a, K, V, A> {
/// Sets the value of the entry, and returns a RustcOccupiedEntry.
///
/// # Examples
@@ -265,7 +265,7 @@ impl<'a, K, V, A: Allocator + Clone> RustcEntry<'a, K, V, A> {
}
}
-impl<'a, K, V: Default, A: Allocator + Clone> RustcEntry<'a, K, V, A> {
+impl<'a, K, V: Default, A: Allocator> RustcEntry<'a, K, V, A> {
/// Ensures a value is in the entry by inserting the default value if empty,
/// and returns a mutable reference to the value in the entry.
///
@@ -293,7 +293,7 @@ impl<'a, K, V: Default, A: Allocator + Clone> RustcEntry<'a, K, V, A> {
}
}
-impl<'a, K, V, A: Allocator + Clone> RustcOccupiedEntry<'a, K, V, A> {
+impl<'a, K, V, A: Allocator> RustcOccupiedEntry<'a, K, V, A> {
/// Gets a reference to the key in the entry.
///
/// # Examples
@@ -330,7 +330,7 @@ impl<'a, K, V, A: Allocator + Clone> RustcOccupiedEntry<'a, K, V, A> {
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove_entry(self) -> (K, V) {
- unsafe { self.table.remove(self.elem) }
+ unsafe { self.table.remove(self.elem).0 }
}
/// Gets a reference to the value in the entry.
@@ -518,7 +518,7 @@ impl<'a, K, V, A: Allocator + Clone> RustcOccupiedEntry<'a, K, V, A> {
}
}
-impl<'a, K, V, A: Allocator + Clone> RustcVacantEntry<'a, K, V, A> {
+impl<'a, K, V, A: Allocator> RustcVacantEntry<'a, K, V, A> {
/// Gets a reference to the key that would be used when inserting a value
/// through the `RustcVacantEntry`.
///
diff --git a/third_party/rust/hashbrown/src/scopeguard.rs b/third_party/rust/hashbrown/src/scopeguard.rs
index f85e6ab0ed..382d06043e 100644
--- a/third_party/rust/hashbrown/src/scopeguard.rs
+++ b/third_party/rust/hashbrown/src/scopeguard.rs
@@ -1,6 +1,6 @@
// Extracted from the scopeguard crate
use core::{
- mem,
+ mem::ManuallyDrop,
ops::{Deref, DerefMut},
ptr,
};
@@ -28,15 +28,13 @@ where
#[inline]
pub fn into_inner(guard: Self) -> T {
// Cannot move out of Drop-implementing types, so
- // ptr::read the value and forget the guard.
+ // ptr::read the value out of a ManuallyDrop<Self>
+ // Don't use mem::forget as that might invalidate value
+ let guard = ManuallyDrop::new(guard);
unsafe {
let value = ptr::read(&guard.value);
- // read the closure so that it is dropped, and assign it to a local
- // variable to ensure that it is only dropped after the guard has
- // been forgotten. (In case the Drop impl of the closure, or that
- // of any consumed captured variable, panics).
- let _dropfn = ptr::read(&guard.dropfn);
- mem::forget(guard);
+ // read the closure so that it is dropped
+ let _ = ptr::read(&guard.dropfn);
value
}
}
diff --git a/third_party/rust/hashbrown/src/set.rs b/third_party/rust/hashbrown/src/set.rs
index 2a4dcea52c..2125a7ac81 100644
--- a/third_party/rust/hashbrown/src/set.rs
+++ b/third_party/rust/hashbrown/src/set.rs
@@ -1,14 +1,14 @@
-use crate::TryReserveError;
+#[cfg(feature = "raw")]
+use crate::raw::RawTable;
+use crate::{Equivalent, TryReserveError};
use alloc::borrow::ToOwned;
-use core::borrow::Borrow;
use core::fmt;
use core::hash::{BuildHasher, Hash};
-use core::iter::{Chain, FromIterator, FusedIterator};
-use core::mem;
+use core::iter::{Chain, FusedIterator};
use core::ops::{BitAnd, BitOr, BitXor, Sub};
-use super::map::{self, ConsumeAllOnDrop, DefaultHashBuilder, DrainFilterInner, HashMap, Keys};
-use crate::raw::{Allocator, Global};
+use super::map::{self, DefaultHashBuilder, HashMap, Keys};
+use crate::raw::{Allocator, Global, RawExtractIf};
// Future Optimization (FIXME!)
// =============================
@@ -102,7 +102,7 @@ use crate::raw::{Allocator, Global};
/// use hashbrown::HashSet;
///
/// let viking_names: HashSet<&'static str> =
-/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
+/// [ "Einar", "Olaf", "Harald" ].into_iter().collect();
/// // use the values stored in the set
/// ```
///
@@ -112,7 +112,7 @@ use crate::raw::{Allocator, Global};
/// [`HashMap`]: struct.HashMap.html
/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
-pub struct HashSet<T, S = DefaultHashBuilder, A: Allocator + Clone = Global> {
+pub struct HashSet<T, S = DefaultHashBuilder, A: Allocator = Global> {
pub(crate) map: HashMap<T, (), S, A>,
}
@@ -135,6 +135,18 @@ impl<T> HashSet<T, DefaultHashBuilder> {
/// The hash set is initially created with a capacity of 0, so it will not allocate until it
/// is first inserted into.
///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`], for example with
+ /// [`with_hasher`](HashSet::with_hasher) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
/// # Examples
///
/// ```
@@ -153,6 +165,18 @@ impl<T> HashSet<T, DefaultHashBuilder> {
/// The hash set will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash set will not allocate.
///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`], for example with
+ /// [`with_capacity_and_hasher`](HashSet::with_capacity_and_hasher) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
/// # Examples
///
/// ```
@@ -169,12 +193,24 @@ impl<T> HashSet<T, DefaultHashBuilder> {
}
#[cfg(feature = "ahash")]
-impl<T: Hash + Eq, A: Allocator + Clone> HashSet<T, DefaultHashBuilder, A> {
+impl<T: Hash + Eq, A: Allocator> HashSet<T, DefaultHashBuilder, A> {
/// Creates an empty `HashSet`.
///
/// The hash set is initially created with a capacity of 0, so it will not allocate until it
/// is first inserted into.
///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`], for example with
+ /// [`with_hasher_in`](HashSet::with_hasher_in) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
/// # Examples
///
/// ```
@@ -193,6 +229,18 @@ impl<T: Hash + Eq, A: Allocator + Clone> HashSet<T, DefaultHashBuilder, A> {
/// The hash set will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash set will not allocate.
///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`], for example with
+ /// [`with_capacity_and_hasher_in`](HashSet::with_capacity_and_hasher_in) method.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ ///
/// # Examples
///
/// ```
@@ -208,7 +256,7 @@ impl<T: Hash + Eq, A: Allocator + Clone> HashSet<T, DefaultHashBuilder, A> {
}
}
-impl<T, S, A: Allocator + Clone> HashSet<T, S, A> {
+impl<T, S, A: Allocator> HashSet<T, S, A> {
/// Returns the number of elements the set can hold without reallocating.
///
/// # Examples
@@ -287,7 +335,7 @@ impl<T, S, A: Allocator + Clone> HashSet<T, S, A> {
/// ```
/// use hashbrown::HashSet;
///
- /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let mut set: HashSet<_> = [1, 2, 3].into_iter().collect();
/// assert!(!set.is_empty());
///
/// // print 1, 2, 3 in an arbitrary order
@@ -314,7 +362,7 @@ impl<T, S, A: Allocator + Clone> HashSet<T, S, A> {
/// use hashbrown::HashSet;
///
/// let xs = [1,2,3,4,5,6];
- /// let mut set: HashSet<i32> = xs.iter().cloned().collect();
+ /// let mut set: HashSet<i32> = xs.into_iter().collect();
/// set.retain(|&k| k % 2 == 0);
/// assert_eq!(set.len(), 3);
/// ```
@@ -331,8 +379,11 @@ impl<T, S, A: Allocator + Clone> HashSet<T, S, A> {
/// In other words, move all elements `e` such that `f(&e)` returns `true` out
/// into another iterator.
///
- /// When the returned DrainedFilter is dropped, any remaining elements that satisfy
- /// the predicate are dropped from the set.
+ /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
+ /// or the iteration short-circuits, then the remaining elements will be retained.
+ /// Use [`retain()`] with a negated predicate if you do not need the returned iterator.
+ ///
+ /// [`retain()`]: HashSet::retain
///
/// # Examples
///
@@ -340,7 +391,7 @@ impl<T, S, A: Allocator + Clone> HashSet<T, S, A> {
/// use hashbrown::HashSet;
///
/// let mut set: HashSet<i32> = (0..8).collect();
- /// let drained: HashSet<i32> = set.drain_filter(|v| v % 2 == 0).collect();
+ /// let drained: HashSet<i32> = set.extract_if(|v| v % 2 == 0).collect();
///
/// let mut evens = drained.into_iter().collect::<Vec<_>>();
/// let mut odds = set.into_iter().collect::<Vec<_>>();
@@ -351,13 +402,13 @@ impl<T, S, A: Allocator + Clone> HashSet<T, S, A> {
/// assert_eq!(odds, vec![1, 3, 5, 7]);
/// ```
#[cfg_attr(feature = "inline-more", inline)]
- pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, T, F, A>
+ pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, T, F, A>
where
F: FnMut(&T) -> bool,
{
- DrainFilter {
+ ExtractIf {
f,
- inner: DrainFilterInner {
+ inner: RawExtractIf {
iter: unsafe { self.map.table.iter() },
table: &mut self.map.table,
},
@@ -386,16 +437,23 @@ impl<T, S> HashSet<T, S, Global> {
/// Creates a new empty hash set which will use the given hasher to hash
/// keys.
///
- /// The hash set is also created with the default initial capacity.
+ /// The hash set is initially created with a capacity of 0, so it will not
+ /// allocate until it is first inserted into.
+ ///
+ /// # HashDoS resistance
///
- /// Warning: `hasher` is normally randomly generated, and
- /// is designed to allow `HashSet`s to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`].
///
/// The `hash_builder` passed should implement the [`BuildHasher`] trait for
- /// the HashMap to be useful, see its documentation for details.
+ /// the HashSet to be useful, see its documentation for details.
///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
///
/// # Examples
///
@@ -407,8 +465,6 @@ impl<T, S> HashSet<T, S, Global> {
/// let mut set = HashSet::with_hasher(s);
/// set.insert(2);
/// ```
- ///
- /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
#[cfg_attr(feature = "inline-more", inline)]
pub const fn with_hasher(hasher: S) -> Self {
Self {
@@ -422,13 +478,20 @@ impl<T, S> HashSet<T, S, Global> {
/// The hash set will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash set will not allocate.
///
- /// Warning: `hasher` is normally randomly generated, and
- /// is designed to allow `HashSet`s to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`].
///
/// The `hash_builder` passed should implement the [`BuildHasher`] trait for
- /// the HashMap to be useful, see its documentation for details.
+ /// the HashSet to be useful, see its documentation for details.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
///
/// # Examples
///
@@ -440,8 +503,6 @@ impl<T, S> HashSet<T, S, Global> {
/// let mut set = HashSet::with_capacity_and_hasher(10, s);
/// set.insert(1);
/// ```
- ///
- /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
#[cfg_attr(feature = "inline-more", inline)]
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
Self {
@@ -452,7 +513,7 @@ impl<T, S> HashSet<T, S, Global> {
impl<T, S, A> HashSet<T, S, A>
where
- A: Allocator + Clone,
+ A: Allocator,
{
/// Returns a reference to the underlying allocator.
#[inline]
@@ -463,12 +524,23 @@ where
/// Creates a new empty hash set which will use the given hasher to hash
/// keys.
///
- /// The hash set is also created with the default initial capacity.
+ /// The hash set is initially created with a capacity of 0, so it will not
+ /// allocate until it is first inserted into.
+ ///
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`].
+ ///
+ /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
+ /// the HashSet to be useful, see its documentation for details.
///
- /// Warning: `hasher` is normally randomly generated, and
- /// is designed to allow `HashSet`s to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
///
/// # Examples
///
@@ -481,7 +553,7 @@ where
/// set.insert(2);
/// ```
#[cfg_attr(feature = "inline-more", inline)]
- pub fn with_hasher_in(hasher: S, alloc: A) -> Self {
+ pub const fn with_hasher_in(hasher: S, alloc: A) -> Self {
Self {
map: HashMap::with_hasher_in(hasher, alloc),
}
@@ -493,10 +565,20 @@ where
/// The hash set will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash set will not allocate.
///
- /// Warning: `hasher` is normally randomly generated, and
- /// is designed to allow `HashSet`s to be resistant to attacks that
- /// cause many collisions and very poor performance. Setting it
- /// manually using this function can expose a DoS attack vector.
+ /// # HashDoS resistance
+ ///
+ /// The `hash_builder` normally use a fixed key by default and that does
+ /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
+ /// Users who require HashDoS resistance should explicitly use
+ /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
+ /// as the hasher when creating a [`HashSet`].
+ ///
+ /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
+ /// the HashSet to be useful, see its documentation for details.
+ ///
+ /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
+ /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+ /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
///
/// # Examples
///
@@ -539,7 +621,7 @@ impl<T, S, A> HashSet<T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
/// Reserves capacity for at least `additional` more elements to be inserted
/// in the `HashSet`. The collection may reserve more space to avoid
@@ -547,7 +629,12 @@ where
///
/// # Panics
///
- /// Panics if the new allocation size overflows `usize`.
+ /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program
+ /// in case of allocation error. Use [`try_reserve`](HashSet::try_reserve) instead
+ /// if you want to handle memory allocation failure.
+ ///
+ /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html
+ /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
///
/// # Examples
///
@@ -637,8 +724,8 @@ where
///
/// ```
/// use hashbrown::HashSet;
- /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
- /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
+ /// let a: HashSet<_> = [1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = [4, 2, 3, 4].into_iter().collect();
///
/// // Can be seen as `a - b`.
/// for x in a.difference(&b) {
@@ -668,8 +755,8 @@ where
///
/// ```
/// use hashbrown::HashSet;
- /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
- /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
+ /// let a: HashSet<_> = [1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = [4, 2, 3, 4].into_iter().collect();
///
/// // Print 1, 4 in arbitrary order.
/// for x in a.symmetric_difference(&b) {
@@ -696,8 +783,8 @@ where
///
/// ```
/// use hashbrown::HashSet;
- /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
- /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
+ /// let a: HashSet<_> = [1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = [4, 2, 3, 4].into_iter().collect();
///
/// // Print 2, 3 in arbitrary order.
/// for x in a.intersection(&b) {
@@ -727,8 +814,8 @@ where
///
/// ```
/// use hashbrown::HashSet;
- /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
- /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
+ /// let a: HashSet<_> = [1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = [4, 2, 3, 4].into_iter().collect();
///
/// // Print 1, 2, 3, 4 in arbitrary order.
/// for x in a.union(&b) {
@@ -763,7 +850,7 @@ where
/// ```
/// use hashbrown::HashSet;
///
- /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let set: HashSet<_> = [1, 2, 3].into_iter().collect();
/// assert_eq!(set.contains(&1), true);
/// assert_eq!(set.contains(&4), false);
/// ```
@@ -773,8 +860,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where
- T: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<T>,
{
self.map.contains_key(value)
}
@@ -790,7 +876,7 @@ where
/// ```
/// use hashbrown::HashSet;
///
- /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let set: HashSet<_> = [1, 2, 3].into_iter().collect();
/// assert_eq!(set.get(&2), Some(&2));
/// assert_eq!(set.get(&4), None);
/// ```
@@ -800,8 +886,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
where
- T: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<T>,
{
// Avoid `Option::map` because it bloats LLVM IR.
match self.map.get_key_value(value) {
@@ -818,7 +903,7 @@ where
/// ```
/// use hashbrown::HashSet;
///
- /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let mut set: HashSet<_> = [1, 2, 3].into_iter().collect();
/// assert_eq!(set.len(), 3);
/// assert_eq!(set.get_or_insert(2), &2);
/// assert_eq!(set.get_or_insert(100), &100);
@@ -856,8 +941,7 @@ where
#[inline]
pub fn get_or_insert_owned<Q: ?Sized>(&mut self, value: &Q) -> &T
where
- T: Borrow<Q>,
- Q: Hash + Eq + ToOwned<Owned = T>,
+ Q: Hash + Equivalent<T> + ToOwned<Owned = T>,
{
// Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
// `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
@@ -889,8 +973,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn get_or_insert_with<Q: ?Sized, F>(&mut self, value: &Q, f: F) -> &T
where
- T: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<T>,
F: FnOnce(&Q) -> T,
{
// Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
@@ -951,7 +1034,7 @@ where
/// ```
/// use hashbrown::HashSet;
///
- /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let a: HashSet<_> = [1, 2, 3].into_iter().collect();
/// let mut b = HashSet::new();
///
/// assert_eq!(a.is_disjoint(&b), true);
@@ -972,7 +1055,7 @@ where
/// ```
/// use hashbrown::HashSet;
///
- /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let sup: HashSet<_> = [1, 2, 3].into_iter().collect();
/// let mut set = HashSet::new();
///
/// assert_eq!(set.is_subset(&sup), true);
@@ -993,7 +1076,7 @@ where
/// ```
/// use hashbrown::HashSet;
///
- /// let sub: HashSet<_> = [1, 2].iter().cloned().collect();
+ /// let sub: HashSet<_> = [1, 2].into_iter().collect();
/// let mut set = HashSet::new();
///
/// assert_eq!(set.is_superset(&sub), false);
@@ -1106,8 +1189,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
where
- T: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<T>,
{
self.map.remove(value).is_some()
}
@@ -1123,7 +1205,7 @@ where
/// ```
/// use hashbrown::HashSet;
///
- /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let mut set: HashSet<_> = [1, 2, 3].into_iter().collect();
/// assert_eq!(set.take(&2), Some(2));
/// assert_eq!(set.take(&2), None);
/// ```
@@ -1133,8 +1215,7 @@ where
#[cfg_attr(feature = "inline-more", inline)]
pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
where
- T: Borrow<Q>,
- Q: Hash + Eq,
+ Q: Hash + Equivalent<T>,
{
// Avoid `Option::map` because it bloats LLVM IR.
match self.map.remove_entry(value) {
@@ -1144,11 +1225,53 @@ where
}
}
+impl<T, S, A: Allocator> HashSet<T, S, A> {
+ /// Returns a reference to the [`RawTable`] used underneath [`HashSet`].
+ /// This function is only available if the `raw` feature of the crate is enabled.
+ ///
+ /// # Note
+ ///
+ /// Calling this function is safe, but using the raw hash table API may require
+ /// unsafe functions or blocks.
+ ///
+ /// `RawTable` API gives the lowest level of control under the set that can be useful
+ /// for extending the HashSet's API, but may lead to *[undefined behavior]*.
+ ///
+ /// [`HashSet`]: struct.HashSet.html
+ /// [`RawTable`]: crate::raw::RawTable
+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[cfg(feature = "raw")]
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub fn raw_table(&self) -> &RawTable<(T, ()), A> {
+ self.map.raw_table()
+ }
+
+ /// Returns a mutable reference to the [`RawTable`] used underneath [`HashSet`].
+ /// This function is only available if the `raw` feature of the crate is enabled.
+ ///
+ /// # Note
+ ///
+ /// Calling this function is safe, but using the raw hash table API may require
+ /// unsafe functions or blocks.
+ ///
+ /// `RawTable` API gives the lowest level of control under the set that can be useful
+ /// for extending the HashSet's API, but may lead to *[undefined behavior]*.
+ ///
+ /// [`HashSet`]: struct.HashSet.html
+ /// [`RawTable`]: crate::raw::RawTable
+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[cfg(feature = "raw")]
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub fn raw_table_mut(&mut self) -> &mut RawTable<(T, ()), A> {
+ self.map.raw_table_mut()
+ }
+}
+
impl<T, S, A> PartialEq for HashSet<T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
@@ -1163,14 +1286,14 @@ impl<T, S, A> Eq for HashSet<T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
}
impl<T, S, A> fmt::Debug for HashSet<T, S, A>
where
T: fmt::Debug,
- A: Allocator + Clone,
+ A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
@@ -1179,7 +1302,7 @@ where
impl<T, S, A> From<HashMap<T, (), S, A>> for HashSet<T, S, A>
where
- A: Allocator + Clone,
+ A: Allocator,
{
fn from(map: HashMap<T, (), S, A>) -> Self {
Self { map }
@@ -1190,7 +1313,7 @@ impl<T, S, A> FromIterator<T> for HashSet<T, S, A>
where
T: Eq + Hash,
S: BuildHasher + Default,
- A: Default + Allocator + Clone,
+ A: Default + Allocator,
{
#[cfg_attr(feature = "inline-more", inline)]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
@@ -1205,7 +1328,7 @@ where
impl<T, A, const N: usize> From<[T; N]> for HashSet<T, DefaultHashBuilder, A>
where
T: Eq + Hash,
- A: Default + Allocator + Clone,
+ A: Default + Allocator,
{
/// # Examples
///
@@ -1225,7 +1348,7 @@ impl<T, S, A> Extend<T> for HashSet<T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
#[cfg_attr(feature = "inline-more", inline)]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
@@ -1249,7 +1372,7 @@ impl<'a, T, S, A> Extend<&'a T> for HashSet<T, S, A>
where
T: 'a + Eq + Hash + Copy,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
#[cfg_attr(feature = "inline-more", inline)]
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
@@ -1272,7 +1395,7 @@ where
impl<T, S, A> Default for HashSet<T, S, A>
where
S: Default,
- A: Default + Allocator + Clone,
+ A: Default + Allocator,
{
/// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
#[cfg_attr(feature = "inline-more", inline)]
@@ -1287,7 +1410,7 @@ impl<T, S, A> BitOr<&HashSet<T, S, A>> for &HashSet<T, S, A>
where
T: Eq + Hash + Clone,
S: BuildHasher + Default,
- A: Allocator + Clone,
+ A: Allocator,
{
type Output = HashSet<T, S>;
@@ -1320,7 +1443,7 @@ impl<T, S, A> BitAnd<&HashSet<T, S, A>> for &HashSet<T, S, A>
where
T: Eq + Hash + Clone,
S: BuildHasher + Default,
- A: Allocator + Clone,
+ A: Allocator,
{
type Output = HashSet<T, S>;
@@ -1431,7 +1554,7 @@ pub struct Iter<'a, K> {
///
/// [`HashSet`]: struct.HashSet.html
/// [`into_iter`]: struct.HashSet.html#method.into_iter
-pub struct IntoIter<K, A: Allocator + Clone = Global> {
+pub struct IntoIter<K, A: Allocator = Global> {
iter: map::IntoIter<K, (), A>,
}
@@ -1442,23 +1565,24 @@ pub struct IntoIter<K, A: Allocator + Clone = Global> {
///
/// [`HashSet`]: struct.HashSet.html
/// [`drain`]: struct.HashSet.html#method.drain
-pub struct Drain<'a, K, A: Allocator + Clone = Global> {
+pub struct Drain<'a, K, A: Allocator = Global> {
iter: map::Drain<'a, K, (), A>,
}
/// A draining iterator over entries of a `HashSet` which don't satisfy the predicate `f`.
///
-/// This `struct` is created by the [`drain_filter`] method on [`HashSet`]. See its
+/// This `struct` is created by the [`extract_if`] method on [`HashSet`]. See its
/// documentation for more.
///
-/// [`drain_filter`]: struct.HashSet.html#method.drain_filter
+/// [`extract_if`]: struct.HashSet.html#method.extract_if
/// [`HashSet`]: struct.HashSet.html
-pub struct DrainFilter<'a, K, F, A: Allocator + Clone = Global>
+#[must_use = "Iterators are lazy unless consumed"]
+pub struct ExtractIf<'a, K, F, A: Allocator = Global>
where
F: FnMut(&K) -> bool,
{
f: F,
- inner: DrainFilterInner<'a, K, (), A>,
+ inner: RawExtractIf<'a, (K, ()), A>,
}
/// A lazy iterator producing elements in the intersection of `HashSet`s.
@@ -1468,7 +1592,7 @@ where
///
/// [`HashSet`]: struct.HashSet.html
/// [`intersection`]: struct.HashSet.html#method.intersection
-pub struct Intersection<'a, T, S, A: Allocator + Clone = Global> {
+pub struct Intersection<'a, T, S, A: Allocator = Global> {
// iterator of the first set
iter: Iter<'a, T>,
// the second set
@@ -1482,7 +1606,7 @@ pub struct Intersection<'a, T, S, A: Allocator + Clone = Global> {
///
/// [`HashSet`]: struct.HashSet.html
/// [`difference`]: struct.HashSet.html#method.difference
-pub struct Difference<'a, T, S, A: Allocator + Clone = Global> {
+pub struct Difference<'a, T, S, A: Allocator = Global> {
// iterator of the first set
iter: Iter<'a, T>,
// the second set
@@ -1496,7 +1620,7 @@ pub struct Difference<'a, T, S, A: Allocator + Clone = Global> {
///
/// [`HashSet`]: struct.HashSet.html
/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference
-pub struct SymmetricDifference<'a, T, S, A: Allocator + Clone = Global> {
+pub struct SymmetricDifference<'a, T, S, A: Allocator = Global> {
iter: Chain<Difference<'a, T, S, A>, Difference<'a, T, S, A>>,
}
@@ -1507,11 +1631,11 @@ pub struct SymmetricDifference<'a, T, S, A: Allocator + Clone = Global> {
///
/// [`HashSet`]: struct.HashSet.html
/// [`union`]: struct.HashSet.html#method.union
-pub struct Union<'a, T, S, A: Allocator + Clone = Global> {
+pub struct Union<'a, T, S, A: Allocator = Global> {
iter: Chain<Iter<'a, T>, Difference<'a, T, S, A>>,
}
-impl<'a, T, S, A: Allocator + Clone> IntoIterator for &'a HashSet<T, S, A> {
+impl<'a, T, S, A: Allocator> IntoIterator for &'a HashSet<T, S, A> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
@@ -1521,7 +1645,7 @@ impl<'a, T, S, A: Allocator + Clone> IntoIterator for &'a HashSet<T, S, A> {
}
}
-impl<T, S, A: Allocator + Clone> IntoIterator for HashSet<T, S, A> {
+impl<T, S, A: Allocator> IntoIterator for HashSet<T, S, A> {
type Item = T;
type IntoIter = IntoIter<T, A>;
@@ -1572,6 +1696,14 @@ impl<'a, K> Iterator for Iter<'a, K> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, f)
+ }
}
impl<'a, K> ExactSizeIterator for Iter<'a, K> {
#[cfg_attr(feature = "inline-more", inline)]
@@ -1587,7 +1719,7 @@ impl<K: fmt::Debug> fmt::Debug for Iter<'_, K> {
}
}
-impl<K, A: Allocator + Clone> Iterator for IntoIter<K, A> {
+impl<K, A: Allocator> Iterator for IntoIter<K, A> {
type Item = K;
#[cfg_attr(feature = "inline-more", inline)]
@@ -1602,23 +1734,31 @@ impl<K, A: Allocator + Clone> Iterator for IntoIter<K, A> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, |acc, (k, ())| f(acc, k))
+ }
}
-impl<K, A: Allocator + Clone> ExactSizeIterator for IntoIter<K, A> {
+impl<K, A: Allocator> ExactSizeIterator for IntoIter<K, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn len(&self) -> usize {
self.iter.len()
}
}
-impl<K, A: Allocator + Clone> FusedIterator for IntoIter<K, A> {}
+impl<K, A: Allocator> FusedIterator for IntoIter<K, A> {}
-impl<K: fmt::Debug, A: Allocator + Clone> fmt::Debug for IntoIter<K, A> {
+impl<K: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<K, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let entries_iter = self.iter.iter().map(|(k, _)| k);
f.debug_list().entries(entries_iter).finish()
}
}
-impl<K, A: Allocator + Clone> Iterator for Drain<'_, K, A> {
+impl<K, A: Allocator> Iterator for Drain<'_, K, A> {
type Item = K;
#[cfg_attr(feature = "inline-more", inline)]
@@ -1633,37 +1773,31 @@ impl<K, A: Allocator + Clone> Iterator for Drain<'_, K, A> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, |acc, (k, ())| f(acc, k))
+ }
}
-impl<K, A: Allocator + Clone> ExactSizeIterator for Drain<'_, K, A> {
+impl<K, A: Allocator> ExactSizeIterator for Drain<'_, K, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn len(&self) -> usize {
self.iter.len()
}
}
-impl<K, A: Allocator + Clone> FusedIterator for Drain<'_, K, A> {}
+impl<K, A: Allocator> FusedIterator for Drain<'_, K, A> {}
-impl<K: fmt::Debug, A: Allocator + Clone> fmt::Debug for Drain<'_, K, A> {
+impl<K: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, K, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let entries_iter = self.iter.iter().map(|(k, _)| k);
f.debug_list().entries(entries_iter).finish()
}
}
-impl<'a, K, F, A: Allocator + Clone> Drop for DrainFilter<'a, K, F, A>
-where
- F: FnMut(&K) -> bool,
-{
- #[cfg_attr(feature = "inline-more", inline)]
- fn drop(&mut self) {
- while let Some(item) = self.next() {
- let guard = ConsumeAllOnDrop(self);
- drop(item);
- mem::forget(guard);
- }
- }
-}
-
-impl<K, F, A: Allocator + Clone> Iterator for DrainFilter<'_, K, F, A>
+impl<K, F, A: Allocator> Iterator for ExtractIf<'_, K, F, A>
where
F: FnMut(&K) -> bool,
{
@@ -1671,9 +1805,9 @@ where
#[cfg_attr(feature = "inline-more", inline)]
fn next(&mut self) -> Option<Self::Item> {
- let f = &mut self.f;
- let (k, _) = self.inner.next(&mut |k, _| f(k))?;
- Some(k)
+ self.inner
+ .next(|&mut (ref k, ())| (self.f)(k))
+ .map(|(k, ())| k)
}
#[inline]
@@ -1682,12 +1816,9 @@ where
}
}
-impl<K, F, A: Allocator + Clone> FusedIterator for DrainFilter<'_, K, F, A> where
- F: FnMut(&K) -> bool
-{
-}
+impl<K, F, A: Allocator> FusedIterator for ExtractIf<'_, K, F, A> where F: FnMut(&K) -> bool {}
-impl<T, S, A: Allocator + Clone> Clone for Intersection<'_, T, S, A> {
+impl<T, S, A: Allocator> Clone for Intersection<'_, T, S, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn clone(&self) -> Self {
Intersection {
@@ -1701,7 +1832,7 @@ impl<'a, T, S, A> Iterator for Intersection<'a, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
type Item = &'a T;
@@ -1720,13 +1851,27 @@ where
let (_, upper) = self.iter.size_hint();
(0, upper)
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, |acc, elt| {
+ if self.other.contains(elt) {
+ f(acc, elt)
+ } else {
+ acc
+ }
+ })
+ }
}
impl<T, S, A> fmt::Debug for Intersection<'_, T, S, A>
where
T: fmt::Debug + Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
@@ -1737,11 +1882,11 @@ impl<T, S, A> FusedIterator for Intersection<'_, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
}
-impl<T, S, A: Allocator + Clone> Clone for Difference<'_, T, S, A> {
+impl<T, S, A: Allocator> Clone for Difference<'_, T, S, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn clone(&self) -> Self {
Difference {
@@ -1755,7 +1900,7 @@ impl<'a, T, S, A> Iterator for Difference<'a, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
type Item = &'a T;
@@ -1774,13 +1919,27 @@ where
let (_, upper) = self.iter.size_hint();
(0, upper)
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, |acc, elt| {
+ if self.other.contains(elt) {
+ acc
+ } else {
+ f(acc, elt)
+ }
+ })
+ }
}
impl<T, S, A> FusedIterator for Difference<'_, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
}
@@ -1788,14 +1947,14 @@ impl<T, S, A> fmt::Debug for Difference<'_, T, S, A>
where
T: fmt::Debug + Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
-impl<T, S, A: Allocator + Clone> Clone for SymmetricDifference<'_, T, S, A> {
+impl<T, S, A: Allocator> Clone for SymmetricDifference<'_, T, S, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn clone(&self) -> Self {
SymmetricDifference {
@@ -1808,7 +1967,7 @@ impl<'a, T, S, A> Iterator for SymmetricDifference<'a, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
type Item = &'a T;
@@ -1820,13 +1979,21 @@ where
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, f)
+ }
}
impl<T, S, A> FusedIterator for SymmetricDifference<'_, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
}
@@ -1834,14 +2001,14 @@ impl<T, S, A> fmt::Debug for SymmetricDifference<'_, T, S, A>
where
T: fmt::Debug + Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
-impl<T, S, A: Allocator + Clone> Clone for Union<'_, T, S, A> {
+impl<T, S, A: Allocator> Clone for Union<'_, T, S, A> {
#[cfg_attr(feature = "inline-more", inline)]
fn clone(&self) -> Self {
Union {
@@ -1854,7 +2021,7 @@ impl<T, S, A> FusedIterator for Union<'_, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
}
@@ -1862,7 +2029,7 @@ impl<T, S, A> fmt::Debug for Union<'_, T, S, A>
where
T: fmt::Debug + Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
@@ -1873,7 +2040,7 @@ impl<'a, T, S, A> Iterator for Union<'a, T, S, A>
where
T: Eq + Hash,
S: BuildHasher,
- A: Allocator + Clone,
+ A: Allocator,
{
type Item = &'a T;
@@ -1885,6 +2052,14 @@ where
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+ #[cfg_attr(feature = "inline-more", inline)]
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, f)
+ }
}
/// A view into a single entry in a set, which may either be vacant or occupied.
@@ -1925,7 +2100,7 @@ where
/// ```
pub enum Entry<'a, T, S, A = Global>
where
- A: Allocator + Clone,
+ A: Allocator,
{
/// An occupied entry.
///
@@ -1958,7 +2133,7 @@ where
Vacant(VacantEntry<'a, T, S, A>),
}
-impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for Entry<'_, T, S, A> {
+impl<T: fmt::Debug, S, A: Allocator> fmt::Debug for Entry<'_, T, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
@@ -2003,11 +2178,11 @@ impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for Entry<'_, T, S, A> {
/// assert_eq!(set.get(&"c"), None);
/// assert_eq!(set.len(), 2);
/// ```
-pub struct OccupiedEntry<'a, T, S, A: Allocator + Clone = Global> {
+pub struct OccupiedEntry<'a, T, S, A: Allocator = Global> {
inner: map::OccupiedEntry<'a, T, (), S, A>,
}
-impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for OccupiedEntry<'_, T, S, A> {
+impl<T: fmt::Debug, S, A: Allocator> fmt::Debug for OccupiedEntry<'_, T, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("value", self.get())
@@ -2041,17 +2216,17 @@ impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for OccupiedEntry<'_, T,
/// }
/// assert!(set.contains("b") && set.len() == 2);
/// ```
-pub struct VacantEntry<'a, T, S, A: Allocator + Clone = Global> {
+pub struct VacantEntry<'a, T, S, A: Allocator = Global> {
inner: map::VacantEntry<'a, T, (), S, A>,
}
-impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for VacantEntry<'_, T, S, A> {
+impl<T: fmt::Debug, S, A: Allocator> fmt::Debug for VacantEntry<'_, T, S, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VacantEntry").field(self.get()).finish()
}
}
-impl<'a, T, S, A: Allocator + Clone> Entry<'a, T, S, A> {
+impl<'a, T, S, A: Allocator> Entry<'a, T, S, A> {
/// Sets the value of the entry, and returns an OccupiedEntry.
///
/// # Examples
@@ -2128,7 +2303,7 @@ impl<'a, T, S, A: Allocator + Clone> Entry<'a, T, S, A> {
}
}
-impl<T, S, A: Allocator + Clone> OccupiedEntry<'_, T, S, A> {
+impl<T, S, A: Allocator> OccupiedEntry<'_, T, S, A> {
/// Gets a reference to the value in the entry.
///
/// # Examples
@@ -2215,7 +2390,7 @@ impl<T, S, A: Allocator + Clone> OccupiedEntry<'_, T, S, A> {
}
}
-impl<'a, T, S, A: Allocator + Clone> VacantEntry<'a, T, S, A> {
+impl<'a, T, S, A: Allocator> VacantEntry<'a, T, S, A> {
/// Gets a reference to the value that would be used when inserting
/// through the `VacantEntry`.
///
@@ -2295,34 +2470,30 @@ fn assert_covariance() {
fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
v
}
- fn into_iter<'new, A: Allocator + Clone>(
- v: IntoIter<&'static str, A>,
- ) -> IntoIter<&'new str, A> {
+ fn into_iter<'new, A: Allocator>(v: IntoIter<&'static str, A>) -> IntoIter<&'new str, A> {
v
}
- fn difference<'a, 'new, A: Allocator + Clone>(
+ fn difference<'a, 'new, A: Allocator>(
v: Difference<'a, &'static str, DefaultHashBuilder, A>,
) -> Difference<'a, &'new str, DefaultHashBuilder, A> {
v
}
- fn symmetric_difference<'a, 'new, A: Allocator + Clone>(
+ fn symmetric_difference<'a, 'new, A: Allocator>(
v: SymmetricDifference<'a, &'static str, DefaultHashBuilder, A>,
) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder, A> {
v
}
- fn intersection<'a, 'new, A: Allocator + Clone>(
+ fn intersection<'a, 'new, A: Allocator>(
v: Intersection<'a, &'static str, DefaultHashBuilder, A>,
) -> Intersection<'a, &'new str, DefaultHashBuilder, A> {
v
}
- fn union<'a, 'new, A: Allocator + Clone>(
+ fn union<'a, 'new, A: Allocator>(
v: Union<'a, &'static str, DefaultHashBuilder, A>,
) -> Union<'a, &'new str, DefaultHashBuilder, A> {
v
}
- fn drain<'new, A: Allocator + Clone>(
- d: Drain<'static, &'static str, A>,
- ) -> Drain<'new, &'new str, A> {
+ fn drain<'new, A: Allocator>(d: Drain<'static, &'static str, A>) -> Drain<'new, &'new str, A> {
d
}
}
@@ -2613,10 +2784,10 @@ mod test_set {
set.insert(1);
set.insert(2);
- let set_str = format!("{:?}", set);
+ let set_str = format!("{set:?}");
assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
- assert_eq!(format!("{:?}", empty), "{}");
+ assert_eq!(format!("{empty:?}"), "{}");
}
#[test]
@@ -2649,7 +2820,7 @@ mod test_set {
assert_eq!(last_i, 49);
}
- for _ in &s {
+ if !s.is_empty() {
panic!("s should be empty!");
}
@@ -2663,6 +2834,7 @@ mod test_set {
use core::hash;
#[derive(Debug)]
+ #[allow(dead_code)]
struct Foo(&'static str, i32);
impl PartialEq for Foo {
@@ -2691,11 +2863,12 @@ mod test_set {
}
#[test]
+ #[allow(clippy::needless_borrow)]
fn test_extend_ref() {
let mut a = HashSet::new();
a.insert(1);
- a.extend(&[2, 3, 4]);
+ a.extend([2, 3, 4]);
assert_eq!(a.len(), 4);
assert!(a.contains(&1));
@@ -2730,10 +2903,10 @@ mod test_set {
}
#[test]
- fn test_drain_filter() {
+ fn test_extract_if() {
{
let mut set: HashSet<i32> = (0..8).collect();
- let drained = set.drain_filter(|&k| k % 2 == 0);
+ let drained = set.extract_if(|&k| k % 2 == 0);
let mut out = drained.collect::<Vec<_>>();
out.sort_unstable();
assert_eq!(vec![0, 2, 4, 6], out);
@@ -2741,7 +2914,7 @@ mod test_set {
}
{
let mut set: HashSet<i32> = (0..8).collect();
- drop(set.drain_filter(|&k| k % 2 == 0));
+ set.extract_if(|&k| k % 2 == 0).for_each(drop);
assert_eq!(set.len(), 4, "Removes non-matching items on drop");
}
}
@@ -2787,4 +2960,11 @@ mod test_set {
set.insert(i);
}
}
+
+ #[test]
+ fn collect() {
+ // At the time of writing, this hits the ZST case in from_base_index
+ // (and without the `map`, it does not).
+ let mut _set: HashSet<_> = (0..3).map(|_| ()).collect();
+ }
}
diff --git a/third_party/rust/hashbrown/src/table.rs b/third_party/rust/hashbrown/src/table.rs
new file mode 100644
index 0000000000..faf8a6330f
--- /dev/null
+++ b/third_party/rust/hashbrown/src/table.rs
@@ -0,0 +1,2070 @@
+use core::{fmt, iter::FusedIterator, marker::PhantomData};
+
+use crate::{
+ raw::{
+ Allocator, Bucket, Global, InsertSlot, RawDrain, RawExtractIf, RawIntoIter, RawIter,
+ RawTable,
+ },
+ TryReserveError,
+};
+
+/// Low-level hash table with explicit hashing.
+///
+/// The primary use case for this type over [`HashMap`] or [`HashSet`] is to
+/// support types that do not implement the [`Hash`] and [`Eq`] traits, but
+/// instead require additional data not contained in the key itself to compute a
+/// hash and compare two elements for equality.
+///
+/// Examples of when this can be useful include:
+/// - An `IndexMap` implementation where indices into a `Vec` are stored as
+/// elements in a `HashTable<usize>`. Hashing and comparing the elements
+/// requires indexing the associated `Vec` to get the actual value referred to
+/// by the index.
+/// - Avoiding re-computing a hash when it is already known.
+/// - Mutating the key of an element in a way that doesn't affect its hash.
+///
+/// To achieve this, `HashTable` methods that search for an element in the table
+/// require a hash value and equality function to be explicitly passed in as
+/// arguments. The method will then iterate over the elements with the given
+/// hash and call the equality function on each of them, until a match is found.
+///
+/// In most cases, a `HashTable` will not be exposed directly in an API. It will
+/// instead be wrapped in a helper type which handles the work of calculating
+/// hash values and comparing elements.
+///
+/// Due to its low-level nature, this type provides fewer guarantees than
+/// [`HashMap`] and [`HashSet`]. Specifically, the API allows you to shoot
+/// yourself in the foot by having multiple elements with identical keys in the
+/// table. The table itself will still function correctly and lookups will
+/// arbitrarily return one of the matching elements. However you should avoid
+/// doing this because it changes the runtime of hash table operations from
+/// `O(1)` to `O(k)` where `k` is the number of duplicate entries.
+///
+/// [`HashMap`]: super::HashMap
+/// [`HashSet`]: super::HashSet
+pub struct HashTable<T, A = Global>
+where
+ A: Allocator,
+{
+ pub(crate) raw: RawTable<T, A>,
+}
+
+impl<T> HashTable<T, Global> {
+ /// Creates an empty `HashTable`.
+ ///
+ /// The hash table is initially created with a capacity of 0, so it will not allocate until it
+ /// is first inserted into.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use hashbrown::HashTable;
+ /// let mut table: HashTable<&str> = HashTable::new();
+ /// assert_eq!(table.len(), 0);
+ /// assert_eq!(table.capacity(), 0);
+ /// ```
+ pub const fn new() -> Self {
+ Self {
+ raw: RawTable::new(),
+ }
+ }
+
+ /// Creates an empty `HashTable` with the specified capacity.
+ ///
+ /// The hash table will be able to hold at least `capacity` elements without
+ /// reallocating. If `capacity` is 0, the hash table will not allocate.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use hashbrown::HashTable;
+ /// let mut table: HashTable<&str> = HashTable::with_capacity(10);
+ /// assert_eq!(table.len(), 0);
+ /// assert!(table.capacity() >= 10);
+ /// ```
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self {
+ raw: RawTable::with_capacity(capacity),
+ }
+ }
+}
+
+impl<T, A> HashTable<T, A>
+where
+ A: Allocator,
+{
+ /// Creates an empty `HashTable` using the given allocator.
+ ///
+ /// The hash table is initially created with a capacity of 0, so it will not allocate until it
+ /// is first inserted into.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use bumpalo::Bump;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let bump = Bump::new();
+ /// let mut table = HashTable::new_in(&bump);
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// // The created HashTable holds none elements
+ /// assert_eq!(table.len(), 0);
+ ///
+ /// // The created HashTable also doesn't allocate memory
+ /// assert_eq!(table.capacity(), 0);
+ ///
+ /// // Now we insert element inside created HashTable
+ /// table.insert_unique(hasher(&"One"), "One", hasher);
+ /// // We can see that the HashTable holds 1 element
+ /// assert_eq!(table.len(), 1);
+ /// // And it also allocates some capacity
+ /// assert!(table.capacity() > 1);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub const fn new_in(alloc: A) -> Self {
+ Self {
+ raw: RawTable::new_in(alloc),
+ }
+ }
+
+ /// Creates an empty `HashTable` with the specified capacity using the given allocator.
+ ///
+ /// The hash table will be able to hold at least `capacity` elements without
+ /// reallocating. If `capacity` is 0, the hash table will not allocate.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use bumpalo::Bump;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let bump = Bump::new();
+ /// let mut table = HashTable::with_capacity_in(5, &bump);
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// // The created HashTable holds none elements
+ /// assert_eq!(table.len(), 0);
+ /// // But it can hold at least 5 elements without reallocating
+ /// let empty_map_capacity = table.capacity();
+ /// assert!(empty_map_capacity >= 5);
+ ///
+ /// // Now we insert some 5 elements inside created HashTable
+ /// table.insert_unique(hasher(&"One"), "One", hasher);
+ /// table.insert_unique(hasher(&"Two"), "Two", hasher);
+ /// table.insert_unique(hasher(&"Three"), "Three", hasher);
+ /// table.insert_unique(hasher(&"Four"), "Four", hasher);
+ /// table.insert_unique(hasher(&"Five"), "Five", hasher);
+ ///
+ /// // We can see that the HashTable holds 5 elements
+ /// assert_eq!(table.len(), 5);
+ /// // But its capacity isn't changed
+ /// assert_eq!(table.capacity(), empty_map_capacity)
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
+ Self {
+ raw: RawTable::with_capacity_in(capacity, alloc),
+ }
+ }
+
+ /// Returns a reference to the underlying allocator.
+ pub fn allocator(&self) -> &A {
+ self.raw.allocator()
+ }
+
+ /// Returns a reference to an entry in the table with the given hash and
+ /// which satisfies the equality function passed.
+ ///
+ /// This method will call `eq` for all entries with the given hash, but may
+ /// also call it for entries with a different hash. `eq` should only return
+ /// true for the desired entry, at which point the search is stopped.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&1), 1, hasher);
+ /// table.insert_unique(hasher(&2), 2, hasher);
+ /// table.insert_unique(hasher(&3), 3, hasher);
+ /// assert_eq!(table.find(hasher(&2), |&val| val == 2), Some(&2));
+ /// assert_eq!(table.find(hasher(&4), |&val| val == 4), None);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn find(&self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&T> {
+ self.raw.get(hash, eq)
+ }
+
+ /// Returns a mutable reference to an entry in the table with the given hash
+ /// and which satisfies the equality function passed.
+ ///
+ /// This method will call `eq` for all entries with the given hash, but may
+ /// also call it for entries with a different hash. `eq` should only return
+ /// true for the desired entry, at which point the search is stopped.
+ ///
+ /// When mutating an entry, you should ensure that it still retains the same
+ /// hash value as when it was inserted, otherwise lookups of that entry may
+ /// fail to find it.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&1), (1, "a"), |val| hasher(&val.0));
+ /// if let Some(val) = table.find_mut(hasher(&1), |val| val.0 == 1) {
+ /// val.1 = "b";
+ /// }
+ /// assert_eq!(table.find(hasher(&1), |val| val.0 == 1), Some(&(1, "b")));
+ /// assert_eq!(table.find(hasher(&2), |val| val.0 == 2), None);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn find_mut(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&mut T> {
+ self.raw.get_mut(hash, eq)
+ }
+
+ /// Returns an `OccupiedEntry` for an entry in the table with the given hash
+ /// and which satisfies the equality function passed.
+ ///
+ /// This can be used to remove the entry from the table. Call
+ /// [`HashTable::entry`] instead if you wish to insert an entry if the
+ /// lookup fails.
+ ///
+ /// This method will call `eq` for all entries with the given hash, but may
+ /// also call it for entries with a different hash. `eq` should only return
+ /// true for the desired entry, at which point the search is stopped.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&1), (1, "a"), |val| hasher(&val.0));
+ /// if let Ok(entry) = table.find_entry(hasher(&1), |val| val.0 == 1) {
+ /// entry.remove();
+ /// }
+ /// assert_eq!(table.find(hasher(&1), |val| val.0 == 1), None);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub fn find_entry(
+ &mut self,
+ hash: u64,
+ eq: impl FnMut(&T) -> bool,
+ ) -> Result<OccupiedEntry<'_, T, A>, AbsentEntry<'_, T, A>> {
+ match self.raw.find(hash, eq) {
+ Some(bucket) => Ok(OccupiedEntry {
+ hash,
+ bucket,
+ table: self,
+ }),
+ None => Err(AbsentEntry { table: self }),
+ }
+ }
+
+ /// Returns an `Entry` for an entry in the table with the given hash
+ /// and which satisfies the equality function passed.
+ ///
+ /// This can be used to remove the entry from the table, or insert a new
+ /// entry with the given hash if one doesn't already exist.
+ ///
+ /// This method will call `eq` for all entries with the given hash, but may
+ /// also call it for entries with a different hash. `eq` should only return
+ /// true for the desired entry, at which point the search is stopped.
+ ///
+ /// This method may grow the table in preparation for an insertion. Call
+ /// [`HashTable::find_entry`] if this is undesirable.
+ ///
+ /// `hasher` is called if entries need to be moved or copied to a new table.
+ /// This must return the same hash value that each entry was inserted with.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&1), (1, "a"), |val| hasher(&val.0));
+ /// if let Entry::Occupied(entry) = table.entry(hasher(&1), |val| val.0 == 1, |val| hasher(&val.0))
+ /// {
+ /// entry.remove();
+ /// }
+ /// if let Entry::Vacant(entry) = table.entry(hasher(&2), |val| val.0 == 2, |val| hasher(&val.0)) {
+ /// entry.insert((2, "b"));
+ /// }
+ /// assert_eq!(table.find(hasher(&1), |val| val.0 == 1), None);
+ /// assert_eq!(table.find(hasher(&2), |val| val.0 == 2), Some(&(2, "b")));
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub fn entry(
+ &mut self,
+ hash: u64,
+ eq: impl FnMut(&T) -> bool,
+ hasher: impl Fn(&T) -> u64,
+ ) -> Entry<'_, T, A> {
+ match self.raw.find_or_find_insert_slot(hash, eq, hasher) {
+ Ok(bucket) => Entry::Occupied(OccupiedEntry {
+ hash,
+ bucket,
+ table: self,
+ }),
+ Err(insert_slot) => Entry::Vacant(VacantEntry {
+ hash,
+ insert_slot,
+ table: self,
+ }),
+ }
+ }
+
+ /// Inserts an element into the `HashTable` with the given hash value, but
+ /// without checking whether an equivalent element already exists within the
+ /// table.
+ ///
+ /// `hasher` is called if entries need to be moved or copied to a new table.
+ /// This must return the same hash value that each entry was inserted with.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut v = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// v.insert_unique(hasher(&1), 1, hasher);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn insert_unique(
+ &mut self,
+ hash: u64,
+ value: T,
+ hasher: impl Fn(&T) -> u64,
+ ) -> OccupiedEntry<'_, T, A> {
+ let bucket = self.raw.insert(hash, value, hasher);
+ OccupiedEntry {
+ hash,
+ bucket,
+ table: self,
+ }
+ }
+
+ /// Clears the table, removing all values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut v = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// v.insert_unique(hasher(&1), 1, hasher);
+ /// v.clear();
+ /// assert!(v.is_empty());
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn clear(&mut self) {
+ self.raw.clear();
+ }
+
+ /// Shrinks the capacity of the table as much as possible. It will drop
+ /// down as much as possible while maintaining the internal rules
+ /// and possibly leaving some space in accordance with the resize policy.
+ ///
+ /// `hasher` is called if entries need to be moved or copied to a new table.
+ /// This must return the same hash value that each entry was inserted with.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::with_capacity(100);
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&1), 1, hasher);
+ /// table.insert_unique(hasher(&2), 2, hasher);
+ /// assert!(table.capacity() >= 100);
+ /// table.shrink_to_fit(hasher);
+ /// assert!(table.capacity() >= 2);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn shrink_to_fit(&mut self, hasher: impl Fn(&T) -> u64) {
+ self.raw.shrink_to(self.len(), hasher)
+ }
+
+ /// Shrinks the capacity of the table with a lower limit. It will drop
+ /// down no lower than the supplied limit while maintaining the internal rules
+ /// and possibly leaving some space in accordance with the resize policy.
+ ///
+ /// `hasher` is called if entries need to be moved or copied to a new table.
+ /// This must return the same hash value that each entry was inserted with.
+ ///
+ /// Panics if the current capacity is smaller than the supplied
+ /// minimum capacity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::with_capacity(100);
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&1), 1, hasher);
+ /// table.insert_unique(hasher(&2), 2, hasher);
+ /// assert!(table.capacity() >= 100);
+ /// table.shrink_to(10, hasher);
+ /// assert!(table.capacity() >= 10);
+ /// table.shrink_to(0, hasher);
+ /// assert!(table.capacity() >= 2);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn shrink_to(&mut self, min_capacity: usize, hasher: impl Fn(&T) -> u64) {
+ self.raw.shrink_to(min_capacity, hasher);
+ }
+
+ /// Reserves capacity for at least `additional` more elements to be inserted
+ /// in the `HashTable`. The collection may reserve more space to avoid
+ /// frequent reallocations.
+ ///
+ /// `hasher` is called if entries need to be moved or copied to a new table.
+ /// This must return the same hash value that each entry was inserted with.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program
+ /// in case of allocation error. Use [`try_reserve`](HashTable::try_reserve) instead
+ /// if you want to handle memory allocation failure.
+ ///
+ /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html
+ /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<i32> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.reserve(10, hasher);
+ /// assert!(table.capacity() >= 10);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) {
+ self.raw.reserve(additional, hasher)
+ }
+
+ /// Tries to reserve capacity for at least `additional` more elements to be inserted
+ /// in the given `HashTable`. The collection may reserve more space to avoid
+ /// frequent reallocations.
+ ///
+ /// `hasher` is called if entries need to be moved or copied to a new table.
+ /// This must return the same hash value that each entry was inserted with.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<i32> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table
+ /// .try_reserve(10, hasher)
+ /// .expect("why is the test harness OOMing on 10 bytes?");
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn try_reserve(
+ &mut self,
+ additional: usize,
+ hasher: impl Fn(&T) -> u64,
+ ) -> Result<(), TryReserveError> {
+ self.raw.try_reserve(additional, hasher)
+ }
+
+ /// Returns the number of elements the table can hold without reallocating.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use hashbrown::HashTable;
+ /// let table: HashTable<i32> = HashTable::with_capacity(100);
+ /// assert!(table.capacity() >= 100);
+ /// ```
+ pub fn capacity(&self) -> usize {
+ self.raw.capacity()
+ }
+
+ /// Returns the number of elements in the table.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// let mut v = HashTable::new();
+ /// assert_eq!(v.len(), 0);
+ /// v.insert_unique(hasher(&1), 1, hasher);
+ /// assert_eq!(v.len(), 1);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn len(&self) -> usize {
+ self.raw.len()
+ }
+
+ /// Returns `true` if the set contains no elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// let mut v = HashTable::new();
+ /// assert!(v.is_empty());
+ /// v.insert_unique(hasher(&1), 1, hasher);
+ /// assert!(!v.is_empty());
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ self.raw.is_empty()
+ }
+
+ /// An iterator visiting all elements in arbitrary order.
+ /// The iterator element type is `&'a T`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&"a"), "b", hasher);
+ /// table.insert_unique(hasher(&"b"), "b", hasher);
+ ///
+ /// // Will print in an arbitrary order.
+ /// for x in table.iter() {
+ /// println!("{}", x);
+ /// }
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn iter(&self) -> Iter<'_, T> {
+ Iter {
+ inner: unsafe { self.raw.iter() },
+ marker: PhantomData,
+ }
+ }
+
+ /// An iterator visiting all elements in arbitrary order,
+ /// with mutable references to the elements.
+ /// The iterator element type is `&'a mut T`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&1), 1, hasher);
+ /// table.insert_unique(hasher(&2), 2, hasher);
+ /// table.insert_unique(hasher(&3), 3, hasher);
+ ///
+ /// // Update all values
+ /// for val in table.iter_mut() {
+ /// *val *= 2;
+ /// }
+ ///
+ /// assert_eq!(table.len(), 3);
+ /// let mut vec: Vec<i32> = Vec::new();
+ ///
+ /// for val in &table {
+ /// println!("val: {}", val);
+ /// vec.push(*val);
+ /// }
+ ///
+ /// // The `Iter` iterator produces items in arbitrary order, so the
+ /// // items must be sorted to test them against a sorted array.
+ /// vec.sort_unstable();
+ /// assert_eq!(vec, [2, 4, 6]);
+ ///
+ /// assert_eq!(table.len(), 3);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn iter_mut(&mut self) -> IterMut<'_, T> {
+ IterMut {
+ inner: unsafe { self.raw.iter() },
+ marker: PhantomData,
+ }
+ }
+
+ /// Retains only the elements specified by the predicate.
+ ///
+ /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// for x in 1..=6 {
+ /// table.insert_unique(hasher(&x), x, hasher);
+ /// }
+ /// table.retain(|&mut x| x % 2 == 0);
+ /// assert_eq!(table.len(), 3);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn retain(&mut self, mut f: impl FnMut(&mut T) -> bool) {
+ // Here we only use `iter` as a temporary, preventing use-after-free
+ unsafe {
+ for item in self.raw.iter() {
+ if !f(item.as_mut()) {
+ self.raw.erase(item);
+ }
+ }
+ }
+ }
+
+ /// Clears the set, returning all elements in an iterator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// for x in 1..=3 {
+ /// table.insert_unique(hasher(&x), x, hasher);
+ /// }
+ /// assert!(!table.is_empty());
+ ///
+ /// // print 1, 2, 3 in an arbitrary order
+ /// for i in table.drain() {
+ /// println!("{}", i);
+ /// }
+ ///
+ /// assert!(table.is_empty());
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn drain(&mut self) -> Drain<'_, T, A> {
+ Drain {
+ inner: self.raw.drain(),
+ }
+ }
+
+ /// Drains elements which are true under the given predicate,
+ /// and returns an iterator over the removed items.
+ ///
+ /// In other words, move all elements `e` such that `f(&e)` returns `true` out
+ /// into another iterator.
+ ///
+ /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
+ /// or the iteration short-circuits, then the remaining elements will be retained.
+ /// Use [`retain()`] with a negated predicate if you do not need the returned iterator.
+ ///
+ /// [`retain()`]: HashTable::retain
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// for x in 0..8 {
+ /// table.insert_unique(hasher(&x), x, hasher);
+ /// }
+ /// let drained: Vec<i32> = table.extract_if(|&mut v| v % 2 == 0).collect();
+ ///
+ /// let mut evens = drained.into_iter().collect::<Vec<_>>();
+ /// let mut odds = table.into_iter().collect::<Vec<_>>();
+ /// evens.sort();
+ /// odds.sort();
+ ///
+ /// assert_eq!(evens, vec![0, 2, 4, 6]);
+ /// assert_eq!(odds, vec![1, 3, 5, 7]);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, T, F, A>
+ where
+ F: FnMut(&mut T) -> bool,
+ {
+ ExtractIf {
+ f,
+ inner: RawExtractIf {
+ iter: unsafe { self.raw.iter() },
+ table: &mut self.raw,
+ },
+ }
+ }
+
+ /// Attempts to get mutable references to `N` values in the map at once.
+ ///
+ /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
+ /// the `i`th key to be looked up.
+ ///
+ /// Returns an array of length `N` with the results of each query. For soundness, at most one
+ /// mutable reference will be returned to any value. `None` will be returned if any of the
+ /// keys are duplicates or missing.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut libraries: HashTable<(&str, u32)> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// for (k, v) in [
+ /// ("Bodleian Library", 1602),
+ /// ("Athenæum", 1807),
+ /// ("Herzogin-Anna-Amalia-Bibliothek", 1691),
+ /// ("Library of Congress", 1800),
+ /// ] {
+ /// libraries.insert_unique(hasher(&k), (k, v), |(k, _)| hasher(&k));
+ /// }
+ ///
+ /// let keys = ["Athenæum", "Library of Congress"];
+ /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
+ /// assert_eq!(
+ /// got,
+ /// Some([&mut ("Athenæum", 1807), &mut ("Library of Congress", 1800),]),
+ /// );
+ ///
+ /// // Missing keys result in None
+ /// let keys = ["Athenæum", "New York Public Library"];
+ /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
+ /// assert_eq!(got, None);
+ ///
+ /// // Duplicate keys result in None
+ /// let keys = ["Athenæum", "Athenæum"];
+ /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
+ /// assert_eq!(got, None);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn get_many_mut<const N: usize>(
+ &mut self,
+ hashes: [u64; N],
+ eq: impl FnMut(usize, &T) -> bool,
+ ) -> Option<[&'_ mut T; N]> {
+ self.raw.get_many_mut(hashes, eq)
+ }
+
+ /// Attempts to get mutable references to `N` values in the map at once, without validating that
+ /// the values are unique.
+ ///
+ /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
+ /// the `i`th key to be looked up.
+ ///
+ /// Returns an array of length `N` with the results of each query. `None` will be returned if
+ /// any of the keys are missing.
+ ///
+ /// For a safe alternative see [`get_many_mut`](`HashTable::get_many_mut`).
+ ///
+ /// # Safety
+ ///
+ /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
+ /// references are not used.
+ ///
+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut libraries: HashTable<(&str, u32)> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// for (k, v) in [
+ /// ("Bodleian Library", 1602),
+ /// ("Athenæum", 1807),
+ /// ("Herzogin-Anna-Amalia-Bibliothek", 1691),
+ /// ("Library of Congress", 1800),
+ /// ] {
+ /// libraries.insert_unique(hasher(&k), (k, v), |(k, _)| hasher(&k));
+ /// }
+ ///
+ /// let keys = ["Athenæum", "Library of Congress"];
+ /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
+ /// assert_eq!(
+ /// got,
+ /// Some([&mut ("Athenæum", 1807), &mut ("Library of Congress", 1800),]),
+ /// );
+ ///
+ /// // Missing keys result in None
+ /// let keys = ["Athenæum", "New York Public Library"];
+ /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
+ /// assert_eq!(got, None);
+ ///
+ /// // Duplicate keys result in None
+ /// let keys = ["Athenæum", "Athenæum"];
+ /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
+ /// assert_eq!(got, None);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub unsafe fn get_many_unchecked_mut<const N: usize>(
+ &mut self,
+ hashes: [u64; N],
+ eq: impl FnMut(usize, &T) -> bool,
+ ) -> Option<[&'_ mut T; N]> {
+ self.raw.get_many_unchecked_mut(hashes, eq)
+ }
+}
+
+impl<T, A> IntoIterator for HashTable<T, A>
+where
+ A: Allocator,
+{
+ type Item = T;
+ type IntoIter = IntoIter<T, A>;
+
+ fn into_iter(self) -> IntoIter<T, A> {
+ IntoIter {
+ inner: self.raw.into_iter(),
+ }
+ }
+}
+
+impl<'a, T, A> IntoIterator for &'a HashTable<T, A>
+where
+ A: Allocator,
+{
+ type Item = &'a T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Iter<'a, T> {
+ self.iter()
+ }
+}
+
+impl<'a, T, A> IntoIterator for &'a mut HashTable<T, A>
+where
+ A: Allocator,
+{
+ type Item = &'a mut T;
+ type IntoIter = IterMut<'a, T>;
+
+ fn into_iter(self) -> IterMut<'a, T> {
+ self.iter_mut()
+ }
+}
+
+impl<T, A> Default for HashTable<T, A>
+where
+ A: Allocator + Default,
+{
+ fn default() -> Self {
+ Self {
+ raw: Default::default(),
+ }
+ }
+}
+
+impl<T, A> Clone for HashTable<T, A>
+where
+ T: Clone,
+ A: Allocator + Clone,
+{
+ fn clone(&self) -> Self {
+ Self {
+ raw: self.raw.clone(),
+ }
+ }
+}
+
+impl<T, A> fmt::Debug for HashTable<T, A>
+where
+ T: fmt::Debug,
+ A: Allocator,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_set().entries(self.iter()).finish()
+ }
+}
+
+/// A view into a single entry in a table, which may either be vacant or occupied.
+///
+/// This `enum` is constructed from the [`entry`] method on [`HashTable`].
+///
+/// [`HashTable`]: struct.HashTable.html
+/// [`entry`]: struct.HashTable.html#method.entry
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "nightly")]
+/// # fn test() {
+/// use ahash::AHasher;
+/// use hashbrown::hash_table::{Entry, HashTable, OccupiedEntry};
+/// use std::hash::{BuildHasher, BuildHasherDefault};
+///
+/// let mut table = HashTable::new();
+/// let hasher = BuildHasherDefault::<AHasher>::default();
+/// let hasher = |val: &_| hasher.hash_one(val);
+/// for x in ["a", "b", "c"] {
+/// table.insert_unique(hasher(&x), x, hasher);
+/// }
+/// assert_eq!(table.len(), 3);
+///
+/// // Existing value (insert)
+/// let entry: Entry<_> = table.entry(hasher(&"a"), |&x| x == "a", hasher);
+/// let _raw_o: OccupiedEntry<_, _> = entry.insert("a");
+/// assert_eq!(table.len(), 3);
+/// // Nonexistent value (insert)
+/// table.entry(hasher(&"d"), |&x| x == "d", hasher).insert("d");
+///
+/// // Existing value (or_insert)
+/// table
+/// .entry(hasher(&"b"), |&x| x == "b", hasher)
+/// .or_insert("b");
+/// // Nonexistent value (or_insert)
+/// table
+/// .entry(hasher(&"e"), |&x| x == "e", hasher)
+/// .or_insert("e");
+///
+/// println!("Our HashTable: {:?}", table);
+///
+/// let mut vec: Vec<_> = table.iter().copied().collect();
+/// // The `Iter` iterator produces items in arbitrary order, so the
+/// // items must be sorted to test them against a sorted array.
+/// vec.sort_unstable();
+/// assert_eq!(vec, ["a", "b", "c", "d", "e"]);
+/// # }
+/// # fn main() {
+/// # #[cfg(feature = "nightly")]
+/// # test()
+/// # }
+/// ```
+pub enum Entry<'a, T, A = Global>
+where
+ A: Allocator,
+{
+ /// An occupied entry.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::{Entry, HashTable, OccupiedEntry};
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// for x in ["a", "b"] {
+ /// table.insert_unique(hasher(&x), x, hasher);
+ /// }
+ ///
+ /// match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
+ /// Entry::Vacant(_) => unreachable!(),
+ /// Entry::Occupied(_) => {}
+ /// }
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ Occupied(OccupiedEntry<'a, T, A>),
+
+ /// A vacant entry.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::{Entry, HashTable, OccupiedEntry};
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table = HashTable::<&str>::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
+ /// Entry::Vacant(_) => {}
+ /// Entry::Occupied(_) => unreachable!(),
+ /// }
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ Vacant(VacantEntry<'a, T, A>),
+}
+
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for Entry<'_, T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
+ Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
+ }
+ }
+}
+
+impl<'a, T, A> Entry<'a, T, A>
+where
+ A: Allocator,
+{
+ /// Sets the value of the entry, replacing any existing value if there is
+ /// one, and returns an [`OccupiedEntry`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<&str> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// let entry = table
+ /// .entry(hasher(&"horseyland"), |&x| x == "horseyland", hasher)
+ /// .insert("horseyland");
+ ///
+ /// assert_eq!(entry.get(), &"horseyland");
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn insert(self, value: T) -> OccupiedEntry<'a, T, A> {
+ match self {
+ Entry::Occupied(mut entry) => {
+ *entry.get_mut() = value;
+ entry
+ }
+ Entry::Vacant(entry) => entry.insert(value),
+ }
+ }
+
+ /// Ensures a value is in the entry by inserting if it was vacant.
+ ///
+ /// Returns an [`OccupiedEntry`] pointing to the now-occupied entry.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<&str> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// // nonexistent key
+ /// table
+ /// .entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher)
+ /// .or_insert("poneyland");
+ /// assert!(table
+ /// .find(hasher(&"poneyland"), |&x| x == "poneyland")
+ /// .is_some());
+ ///
+ /// // existing key
+ /// table
+ /// .entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher)
+ /// .or_insert("poneyland");
+ /// assert!(table
+ /// .find(hasher(&"poneyland"), |&x| x == "poneyland")
+ /// .is_some());
+ /// assert_eq!(table.len(), 1);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn or_insert(self, default: T) -> OccupiedEntry<'a, T, A> {
+ match self {
+ Entry::Occupied(entry) => entry,
+ Entry::Vacant(entry) => entry.insert(default),
+ }
+ }
+
+ /// Ensures a value is in the entry by inserting the result of the default function if empty..
+ ///
+ /// Returns an [`OccupiedEntry`] pointing to the now-occupied entry.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<String> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// table
+ /// .entry(hasher("poneyland"), |x| x == "poneyland", |val| hasher(val))
+ /// .or_insert_with(|| "poneyland".to_string());
+ ///
+ /// assert!(table
+ /// .find(hasher(&"poneyland"), |x| x == "poneyland")
+ /// .is_some());
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn or_insert_with(self, default: impl FnOnce() -> T) -> OccupiedEntry<'a, T, A> {
+ match self {
+ Entry::Occupied(entry) => entry,
+ Entry::Vacant(entry) => entry.insert(default()),
+ }
+ }
+
+ /// Provides in-place mutable access to an occupied entry before any
+ /// potential inserts into the table.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<(&str, u32)> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// table
+ /// .entry(
+ /// hasher(&"poneyland"),
+ /// |&(x, _)| x == "poneyland",
+ /// |(k, _)| hasher(&k),
+ /// )
+ /// .and_modify(|(_, v)| *v += 1)
+ /// .or_insert(("poneyland", 42));
+ /// assert_eq!(
+ /// table.find(hasher(&"poneyland"), |&(k, _)| k == "poneyland"),
+ /// Some(&("poneyland", 42))
+ /// );
+ ///
+ /// table
+ /// .entry(
+ /// hasher(&"poneyland"),
+ /// |&(x, _)| x == "poneyland",
+ /// |(k, _)| hasher(&k),
+ /// )
+ /// .and_modify(|(_, v)| *v += 1)
+ /// .or_insert(("poneyland", 42));
+ /// assert_eq!(
+ /// table.find(hasher(&"poneyland"), |&(k, _)| k == "poneyland"),
+ /// Some(&("poneyland", 43))
+ /// );
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn and_modify(self, f: impl FnOnce(&mut T)) -> Self {
+ match self {
+ Entry::Occupied(mut entry) => {
+ f(entry.get_mut());
+ Entry::Occupied(entry)
+ }
+ Entry::Vacant(entry) => Entry::Vacant(entry),
+ }
+ }
+}
+
+/// A view into an occupied entry in a `HashTable`.
+/// It is part of the [`Entry`] enum.
+///
+/// [`Entry`]: enum.Entry.html
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "nightly")]
+/// # fn test() {
+/// use ahash::AHasher;
+/// use hashbrown::hash_table::{Entry, HashTable, OccupiedEntry};
+/// use std::hash::{BuildHasher, BuildHasherDefault};
+///
+/// let mut table = HashTable::new();
+/// let hasher = BuildHasherDefault::<AHasher>::default();
+/// let hasher = |val: &_| hasher.hash_one(val);
+/// for x in ["a", "b", "c"] {
+/// table.insert_unique(hasher(&x), x, hasher);
+/// }
+/// assert_eq!(table.len(), 3);
+///
+/// let _entry_o: OccupiedEntry<_, _> = table.find_entry(hasher(&"a"), |&x| x == "a").unwrap();
+/// assert_eq!(table.len(), 3);
+///
+/// // Existing key
+/// match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
+/// Entry::Vacant(_) => unreachable!(),
+/// Entry::Occupied(view) => {
+/// assert_eq!(view.get(), &"a");
+/// }
+/// }
+///
+/// assert_eq!(table.len(), 3);
+///
+/// // Existing key (take)
+/// match table.entry(hasher(&"c"), |&x| x == "c", hasher) {
+/// Entry::Vacant(_) => unreachable!(),
+/// Entry::Occupied(view) => {
+/// assert_eq!(view.remove().0, "c");
+/// }
+/// }
+/// assert_eq!(table.find(hasher(&"c"), |&x| x == "c"), None);
+/// assert_eq!(table.len(), 2);
+/// # }
+/// # fn main() {
+/// # #[cfg(feature = "nightly")]
+/// # test()
+/// # }
+/// ```
+pub struct OccupiedEntry<'a, T, A = Global>
+where
+ A: Allocator,
+{
+ hash: u64,
+ bucket: Bucket<T>,
+ table: &'a mut HashTable<T, A>,
+}
+
+unsafe impl<T, A> Send for OccupiedEntry<'_, T, A>
+where
+ T: Send,
+ A: Send + Allocator,
+{
+}
+unsafe impl<T, A> Sync for OccupiedEntry<'_, T, A>
+where
+ T: Sync,
+ A: Sync + Allocator,
+{
+}
+
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for OccupiedEntry<'_, T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("OccupiedEntry")
+ .field("value", self.get())
+ .finish()
+ }
+}
+
+impl<'a, T, A> OccupiedEntry<'a, T, A>
+where
+ A: Allocator,
+{
+ /// Takes the value out of the entry, and returns it along with a
+ /// `VacantEntry` that can be used to insert another value with the same
+ /// hash as the one that was just removed.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<&str> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// // The table is empty
+ /// assert!(table.is_empty() && table.capacity() == 0);
+ ///
+ /// table.insert_unique(hasher(&"poneyland"), "poneyland", hasher);
+ /// let capacity_before_remove = table.capacity();
+ ///
+ /// if let Entry::Occupied(o) = table.entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher) {
+ /// assert_eq!(o.remove().0, "poneyland");
+ /// }
+ ///
+ /// assert!(table
+ /// .find(hasher(&"poneyland"), |&x| x == "poneyland")
+ /// .is_none());
+ /// // Now table hold none elements but capacity is equal to the old one
+ /// assert!(table.len() == 0 && table.capacity() == capacity_before_remove);
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ #[cfg_attr(feature = "inline-more", inline)]
+ pub fn remove(self) -> (T, VacantEntry<'a, T, A>) {
+ let (val, slot) = unsafe { self.table.raw.remove(self.bucket) };
+ (
+ val,
+ VacantEntry {
+ hash: self.hash,
+ insert_slot: slot,
+ table: self.table,
+ },
+ )
+ }
+
+ /// Gets a reference to the value in the entry.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<&str> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&"poneyland"), "poneyland", hasher);
+ ///
+ /// match table.entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher) {
+ /// Entry::Vacant(_) => panic!(),
+ /// Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"),
+ /// }
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ #[inline]
+ pub fn get(&self) -> &T {
+ unsafe { self.bucket.as_ref() }
+ }
+
+ /// Gets a mutable reference to the value in the entry.
+ ///
+ /// If you need a reference to the `OccupiedEntry` which may outlive the
+ /// destruction of the `Entry` value, see [`into_mut`].
+ ///
+ /// [`into_mut`]: #method.into_mut
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<(&str, u32)> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&"poneyland"), ("poneyland", 12), |(k, _)| hasher(&k));
+ ///
+ /// assert_eq!(
+ /// table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
+ /// Some(&("poneyland", 12))
+ /// );
+ ///
+ /// if let Entry::Occupied(mut o) = table.entry(
+ /// hasher(&"poneyland"),
+ /// |&(x, _)| x == "poneyland",
+ /// |(k, _)| hasher(&k),
+ /// ) {
+ /// o.get_mut().1 += 10;
+ /// assert_eq!(o.get().1, 22);
+ ///
+ /// // We can use the same Entry multiple times.
+ /// o.get_mut().1 += 2;
+ /// }
+ ///
+ /// assert_eq!(
+ /// table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
+ /// Some(&("poneyland", 24))
+ /// );
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ #[inline]
+ pub fn get_mut(&mut self) -> &mut T {
+ unsafe { self.bucket.as_mut() }
+ }
+
+ /// Converts the OccupiedEntry into a mutable reference to the value in the entry
+ /// with a lifetime bound to the table itself.
+ ///
+ /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
+ ///
+ /// [`get_mut`]: #method.get_mut
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<(&str, u32)> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ /// table.insert_unique(hasher(&"poneyland"), ("poneyland", 12), |(k, _)| hasher(&k));
+ ///
+ /// assert_eq!(
+ /// table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
+ /// Some(&("poneyland", 12))
+ /// );
+ ///
+ /// let value: &mut (&str, u32);
+ /// match table.entry(
+ /// hasher(&"poneyland"),
+ /// |&(x, _)| x == "poneyland",
+ /// |(k, _)| hasher(&k),
+ /// ) {
+ /// Entry::Occupied(entry) => value = entry.into_mut(),
+ /// Entry::Vacant(_) => panic!(),
+ /// }
+ /// value.1 += 10;
+ ///
+ /// assert_eq!(
+ /// table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
+ /// Some(&("poneyland", 22))
+ /// );
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ pub fn into_mut(self) -> &'a mut T {
+ unsafe { self.bucket.as_mut() }
+ }
+
+ /// Converts the OccupiedEntry into a mutable reference to the underlying
+ /// table.
+ pub fn into_table(self) -> &'a mut HashTable<T, A> {
+ self.table
+ }
+}
+
+/// A view into a vacant entry in a `HashTable`.
+/// It is part of the [`Entry`] enum.
+///
+/// [`Entry`]: enum.Entry.html
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "nightly")]
+/// # fn test() {
+/// use ahash::AHasher;
+/// use hashbrown::hash_table::{Entry, HashTable, VacantEntry};
+/// use std::hash::{BuildHasher, BuildHasherDefault};
+///
+/// let mut table: HashTable<&str> = HashTable::new();
+/// let hasher = BuildHasherDefault::<AHasher>::default();
+/// let hasher = |val: &_| hasher.hash_one(val);
+///
+/// let entry_v: VacantEntry<_, _> = match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
+/// Entry::Vacant(view) => view,
+/// Entry::Occupied(_) => unreachable!(),
+/// };
+/// entry_v.insert("a");
+/// assert!(table.find(hasher(&"a"), |&x| x == "a").is_some() && table.len() == 1);
+///
+/// // Nonexistent key (insert)
+/// match table.entry(hasher(&"b"), |&x| x == "b", hasher) {
+/// Entry::Vacant(view) => {
+/// view.insert("b");
+/// }
+/// Entry::Occupied(_) => unreachable!(),
+/// }
+/// assert!(table.find(hasher(&"b"), |&x| x == "b").is_some() && table.len() == 2);
+/// # }
+/// # fn main() {
+/// # #[cfg(feature = "nightly")]
+/// # test()
+/// # }
+/// ```
+pub struct VacantEntry<'a, T, A = Global>
+where
+ A: Allocator,
+{
+ hash: u64,
+ insert_slot: InsertSlot,
+ table: &'a mut HashTable<T, A>,
+}
+
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for VacantEntry<'_, T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("VacantEntry")
+ }
+}
+
+impl<'a, T, A> VacantEntry<'a, T, A>
+where
+ A: Allocator,
+{
+ /// Inserts a new element into the table with the hash that was used to
+ /// obtain the `VacantEntry`.
+ ///
+ /// An `OccupiedEntry` is returned for the newly inserted element.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[cfg(feature = "nightly")]
+ /// # fn test() {
+ /// use ahash::AHasher;
+ /// use hashbrown::hash_table::Entry;
+ /// use hashbrown::HashTable;
+ /// use std::hash::{BuildHasher, BuildHasherDefault};
+ ///
+ /// let mut table: HashTable<&str> = HashTable::new();
+ /// let hasher = BuildHasherDefault::<AHasher>::default();
+ /// let hasher = |val: &_| hasher.hash_one(val);
+ ///
+ /// if let Entry::Vacant(o) = table.entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher) {
+ /// o.insert("poneyland");
+ /// }
+ /// assert_eq!(
+ /// table.find(hasher(&"poneyland"), |&x| x == "poneyland"),
+ /// Some(&"poneyland")
+ /// );
+ /// # }
+ /// # fn main() {
+ /// # #[cfg(feature = "nightly")]
+ /// # test()
+ /// # }
+ /// ```
+ #[inline]
+ pub fn insert(self, value: T) -> OccupiedEntry<'a, T, A> {
+ let bucket = unsafe {
+ self.table
+ .raw
+ .insert_in_slot(self.hash, self.insert_slot, value)
+ };
+ OccupiedEntry {
+ hash: self.hash,
+ bucket,
+ table: self.table,
+ }
+ }
+
+ /// Converts the VacantEntry into a mutable reference to the underlying
+ /// table.
+ pub fn into_table(self) -> &'a mut HashTable<T, A> {
+ self.table
+ }
+}
+
+/// Type representing the absence of an entry, as returned by [`HashTable::find_entry`].
+///
+/// This type only exists due to [limitations] in Rust's NLL borrow checker. In
+/// the future, `find_entry` will return an `Option<OccupiedEntry>` and this
+/// type will be removed.
+///
+/// [limitations]: https://smallcultfollowing.com/babysteps/blog/2018/06/15/mir-based-borrow-check-nll-status-update/#polonius
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "nightly")]
+/// # fn test() {
+/// use ahash::AHasher;
+/// use hashbrown::hash_table::{AbsentEntry, Entry, HashTable};
+/// use std::hash::{BuildHasher, BuildHasherDefault};
+///
+/// let mut table: HashTable<&str> = HashTable::new();
+/// let hasher = BuildHasherDefault::<AHasher>::default();
+/// let hasher = |val: &_| hasher.hash_one(val);
+///
+/// let entry_v: AbsentEntry<_, _> = table.find_entry(hasher(&"a"), |&x| x == "a").unwrap_err();
+/// entry_v
+/// .into_table()
+/// .insert_unique(hasher(&"a"), "a", hasher);
+/// assert!(table.find(hasher(&"a"), |&x| x == "a").is_some() && table.len() == 1);
+///
+/// // Nonexistent key (insert)
+/// match table.entry(hasher(&"b"), |&x| x == "b", hasher) {
+/// Entry::Vacant(view) => {
+/// view.insert("b");
+/// }
+/// Entry::Occupied(_) => unreachable!(),
+/// }
+/// assert!(table.find(hasher(&"b"), |&x| x == "b").is_some() && table.len() == 2);
+/// # }
+/// # fn main() {
+/// # #[cfg(feature = "nightly")]
+/// # test()
+/// # }
+/// ```
+pub struct AbsentEntry<'a, T, A = Global>
+where
+ A: Allocator,
+{
+ table: &'a mut HashTable<T, A>,
+}
+
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for AbsentEntry<'_, T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("AbsentEntry")
+ }
+}
+
+impl<'a, T, A> AbsentEntry<'a, T, A>
+where
+ A: Allocator,
+{
+ /// Converts the AbsentEntry into a mutable reference to the underlying
+ /// table.
+ pub fn into_table(self) -> &'a mut HashTable<T, A> {
+ self.table
+ }
+}
+
+/// An iterator over the entries of a `HashTable` in arbitrary order.
+/// The iterator element type is `&'a T`.
+///
+/// This `struct` is created by the [`iter`] method on [`HashTable`]. See its
+/// documentation for more.
+///
+/// [`iter`]: struct.HashTable.html#method.iter
+/// [`HashTable`]: struct.HashTable.html
+pub struct Iter<'a, T> {
+ inner: RawIter<T>,
+ marker: PhantomData<&'a T>,
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // Avoid `Option::map` because it bloats LLVM IR.
+ match self.inner.next() {
+ Some(bucket) => Some(unsafe { bucket.as_ref() }),
+ None => None,
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner
+ .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_ref()) })
+ }
+}
+
+impl<T> ExactSizeIterator for Iter<'_, T> {
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+}
+
+impl<T> FusedIterator for Iter<'_, T> {}
+
+/// A mutable iterator over the entries of a `HashTable` in arbitrary order.
+/// The iterator element type is `&'a mut T`.
+///
+/// This `struct` is created by the [`iter_mut`] method on [`HashTable`]. See its
+/// documentation for more.
+///
+/// [`iter_mut`]: struct.HashTable.html#method.iter_mut
+/// [`HashTable`]: struct.HashTable.html
+pub struct IterMut<'a, T> {
+ inner: RawIter<T>,
+ marker: PhantomData<&'a mut T>,
+}
+
+impl<'a, T> Iterator for IterMut<'a, T> {
+ type Item = &'a mut T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // Avoid `Option::map` because it bloats LLVM IR.
+ match self.inner.next() {
+ Some(bucket) => Some(unsafe { bucket.as_mut() }),
+ None => None,
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner
+ .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_mut()) })
+ }
+}
+
+impl<T> ExactSizeIterator for IterMut<'_, T> {
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+}
+
+impl<T> FusedIterator for IterMut<'_, T> {}
+
+/// An owning iterator over the entries of a `HashTable` in arbitrary order.
+/// The iterator element type is `T`.
+///
+/// This `struct` is created by the [`into_iter`] method on [`HashTable`]
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
+/// The table cannot be used after calling that method.
+///
+/// [`into_iter`]: struct.HashTable.html#method.into_iter
+/// [`HashTable`]: struct.HashTable.html
+/// [`IntoIterator`]: https://doc.rust-lang.org/core/iter/trait.IntoIterator.html
+pub struct IntoIter<T, A = Global>
+where
+ A: Allocator,
+{
+ inner: RawIntoIter<T, A>,
+}
+
+impl<T, A> Iterator for IntoIter<T, A>
+where
+ A: Allocator,
+{
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.inner.fold(init, f)
+ }
+}
+
+impl<T, A> ExactSizeIterator for IntoIter<T, A>
+where
+ A: Allocator,
+{
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+}
+
+impl<T, A> FusedIterator for IntoIter<T, A> where A: Allocator {}
+
+/// A draining iterator over the items of a `HashTable`.
+///
+/// This `struct` is created by the [`drain`] method on [`HashTable`].
+/// See its documentation for more.
+///
+/// [`HashTable`]: struct.HashTable.html
+/// [`drain`]: struct.HashTable.html#method.drain
+pub struct Drain<'a, T, A: Allocator = Global> {
+ inner: RawDrain<'a, T, A>,
+}
+
+impl<T, A: Allocator> Drain<'_, T, A> {
+ /// Returns a iterator of references over the remaining items.
+ fn iter(&self) -> Iter<'_, T> {
+ Iter {
+ inner: self.inner.iter(),
+ marker: PhantomData,
+ }
+ }
+}
+
+impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<T> {
+ self.inner.next()
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+}
+impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+}
+impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}
+
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.iter()).finish()
+ }
+}
+
+/// A draining iterator over entries of a `HashTable` which don't satisfy the predicate `f`.
+///
+/// This `struct` is created by [`HashTable::extract_if`]. See its
+/// documentation for more.
+#[must_use = "Iterators are lazy unless consumed"]
+pub struct ExtractIf<'a, T, F, A: Allocator = Global>
+where
+ F: FnMut(&mut T) -> bool,
+{
+ f: F,
+ inner: RawExtractIf<'a, T, A>,
+}
+
+impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A>
+where
+ F: FnMut(&mut T) -> bool,
+{
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner.next(|val| (self.f)(val))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, self.inner.iter.size_hint().1)
+ }
+}
+
+impl<T, F, A: Allocator> FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool {}
diff --git a/third_party/rust/hashbrown/tests/equivalent_trait.rs b/third_party/rust/hashbrown/tests/equivalent_trait.rs
new file mode 100644
index 0000000000..713dddd53c
--- /dev/null
+++ b/third_party/rust/hashbrown/tests/equivalent_trait.rs
@@ -0,0 +1,53 @@
+use hashbrown::Equivalent;
+use hashbrown::HashMap;
+
+use std::hash::Hash;
+
+#[derive(Debug, Hash)]
+pub struct Pair<A, B>(pub A, pub B);
+
+impl<A, B, C, D> PartialEq<(A, B)> for Pair<C, D>
+where
+ C: PartialEq<A>,
+ D: PartialEq<B>,
+{
+ fn eq(&self, rhs: &(A, B)) -> bool {
+ self.0 == rhs.0 && self.1 == rhs.1
+ }
+}
+
+impl<A, B, X> Equivalent<X> for Pair<A, B>
+where
+ Pair<A, B>: PartialEq<X>,
+ A: Hash + Eq,
+ B: Hash + Eq,
+{
+ fn equivalent(&self, other: &X) -> bool {
+ *self == *other
+ }
+}
+
+#[test]
+fn test_lookup() {
+ let s = String::from;
+ let mut map = HashMap::new();
+ map.insert((s("a"), s("b")), 1);
+ map.insert((s("a"), s("x")), 2);
+
+ assert!(map.contains_key(&Pair("a", "b")));
+ assert!(!map.contains_key(&Pair("b", "a")));
+}
+
+#[test]
+fn test_string_str() {
+ let s = String::from;
+ let mut map = HashMap::new();
+ map.insert(s("a"), 1);
+ map.insert(s("b"), 2);
+ map.insert(s("x"), 3);
+ map.insert(s("y"), 4);
+
+ assert!(map.contains_key("a"));
+ assert!(!map.contains_key("z"));
+ assert_eq!(map.remove("b"), Some(2));
+}
diff --git a/third_party/rust/hashbrown/tests/raw.rs b/third_party/rust/hashbrown/tests/raw.rs
new file mode 100644
index 0000000000..858836e63b
--- /dev/null
+++ b/third_party/rust/hashbrown/tests/raw.rs
@@ -0,0 +1,11 @@
+#![cfg(feature = "raw")]
+
+use hashbrown::raw::RawTable;
+use std::mem;
+
+#[test]
+fn test_allocation_info() {
+ assert_eq!(RawTable::<()>::new().allocation_info().1.size(), 0);
+ assert_eq!(RawTable::<u32>::new().allocation_info().1.size(), 0);
+ assert!(RawTable::<u32>::with_capacity(1).allocation_info().1.size() > mem::size_of::<u32>());
+}
diff --git a/third_party/rust/hashbrown/tests/rayon.rs b/third_party/rust/hashbrown/tests/rayon.rs
index 8c603c5c41..d55e5a9804 100644
--- a/third_party/rust/hashbrown/tests/rayon.rs
+++ b/third_party/rust/hashbrown/tests/rayon.rs
@@ -356,7 +356,9 @@ fn set_seq_par_equivalence_into_iter_empty() {
let vec_seq = SET_EMPTY.clone().into_iter().collect::<Vec<_>>();
let vec_par = SET_EMPTY.clone().into_par_iter().collect::<Vec<_>>();
- assert_eq3!(vec_seq, vec_par, []);
+ // Work around type inference failure introduced by rend dev-dependency.
+ let empty: [char; 0] = [];
+ assert_eq3!(vec_seq, vec_par, empty);
}
#[test]
diff --git a/third_party/rust/hashbrown/tests/set.rs b/third_party/rust/hashbrown/tests/set.rs
index 5ae1ec98ec..86ec964766 100644
--- a/third_party/rust/hashbrown/tests/set.rs
+++ b/third_party/rust/hashbrown/tests/set.rs
@@ -27,7 +27,7 @@ fn test_hashset_insert_remove() {
assert_eq!(m.insert(x.clone()), true);
}
for (i, x) in tx.iter().enumerate() {
- println!("removing {} {:?}", i, x);
+ println!("removing {i} {x:?}");
assert_eq!(m.remove(x), true);
}
}
diff --git a/third_party/rust/hashlink/.cargo-checksum.json b/third_party/rust/hashlink/.cargo-checksum.json
index 2eca6e96e0..fdc962b32f 100644
--- a/third_party/rust/hashlink/.cargo-checksum.json
+++ b/third_party/rust/hashlink/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"198cbb28cb803006c074811eece27e07e2cce6b463750fffcc47c6255d10e82c","Cargo.toml":"ff6fc403d9a7b64a597026915c1bc52c70d990d9929dd414667e78798dfaf1f7","LICENSE-APACHE":"c144680885b29e4719e2a51f0aab5439a1e02d980692b5aaf086cae12727f28b","LICENSE-MIT":"e915669a595b11a200873df8286561881b0e04932f6412a585db6297ba0bc97c","README.md":"acc16f95f79df4789a0f116c8748242aac2c17e38ab91d6d5e59c89271ca51e9","src/lib.rs":"12f7bf2e1bdc312fd9740b639983916a2e7a8582c588902af8c4ac71b9032fde","src/linked_hash_map.rs":"cd88b14beac407986d23ea3ab944dd666f62a7a75c99151296b2b1eef54d3569","src/linked_hash_set.rs":"36892b3a9a3388fe2a5454051a691dd38d512771f08a1638ba8322afc65dfe61","src/lru_cache.rs":"d2322af90780a3ef192f25d213f5af38e1dc6492a323fb361757d53692058774","src/serde.rs":"451a34dec0e29d205f997710bf9e733836832f6402e36640f3b6de272a1fd9d4","tests/linked_hash_map.rs":"c2d259c9d0325f4b73268dc686b8cca8fc3c778c757012825a82474026f28634","tests/linked_hash_set.rs":"bfaa3018a99c5c36cf0059bf7836142c2cc69be7f03a8c20bd52131f877e2eec","tests/lru_cache.rs":"c0328001d53e2a0d1ef6fb36550e8cbb989ef1914cef3657f1832b280f4d4572","tests/serde.rs":"d359b4125009705dcba9219ee5f027bbe8bb18008c111e3541c41e141f9b02f2"},"package":"69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"3479e430ed4bfcd38ac0d9bff95873d8e018e462e0c2dd370a58c282a47caa59","Cargo.toml":"ab72ee61c8eebd28e3904c50b819f13f5be04441b8bfc1fba06607877f94a344","LICENSE-APACHE":"c144680885b29e4719e2a51f0aab5439a1e02d980692b5aaf086cae12727f28b","LICENSE-MIT":"e915669a595b11a200873df8286561881b0e04932f6412a585db6297ba0bc97c","README.md":"acc16f95f79df4789a0f116c8748242aac2c17e38ab91d6d5e59c89271ca51e9","src/lib.rs":"12f7bf2e1bdc312fd9740b639983916a2e7a8582c588902af8c4ac71b9032fde","src/linked_hash_map.rs":"cd88b14beac407986d23ea3ab944dd666f62a7a75c99151296b2b1eef54d3569","src/linked_hash_set.rs":"36892b3a9a3388fe2a5454051a691dd38d512771f08a1638ba8322afc65dfe61","src/lru_cache.rs":"d2322af90780a3ef192f25d213f5af38e1dc6492a323fb361757d53692058774","src/serde.rs":"451a34dec0e29d205f997710bf9e733836832f6402e36640f3b6de272a1fd9d4","tests/linked_hash_map.rs":"c2d259c9d0325f4b73268dc686b8cca8fc3c778c757012825a82474026f28634","tests/linked_hash_set.rs":"bfaa3018a99c5c36cf0059bf7836142c2cc69be7f03a8c20bd52131f877e2eec","tests/lru_cache.rs":"c0328001d53e2a0d1ef6fb36550e8cbb989ef1914cef3657f1832b280f4d4572","tests/serde.rs":"4e0b1c19c3c542f0b9adac72f6ff32907da6bb58b4f1810dcdf9cd4e2eef34b1"},"package":"0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa"} \ No newline at end of file
diff --git a/third_party/rust/hashlink/CHANGELOG.md b/third_party/rust/hashlink/CHANGELOG.md
index 0cec7be6c0..9d4bd44470 100644
--- a/third_party/rust/hashlink/CHANGELOG.md
+++ b/third_party/rust/hashlink/CHANGELOG.md
@@ -1,3 +1,6 @@
+## [0.8.2]
+- bump hashbrown to 0.13
+
## [0.8.1]
- Add `retain_with_order` methods, equivalent to `retain` but which iterate
through the map in the proper linked list order
diff --git a/third_party/rust/hashlink/Cargo.toml b/third_party/rust/hashlink/Cargo.toml
index 308f9f77c3..474901d947 100644
--- a/third_party/rust/hashlink/Cargo.toml
+++ b/third_party/rust/hashlink/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "hashlink"
-version = "0.8.1"
+version = "0.8.2"
authors = ["kyren <kerriganw@gmail.com>"]
description = "HashMap-like containers that hold their key-value pairs in a user controllable order"
documentation = "https://docs.rs/hashlink"
@@ -22,14 +22,14 @@ license = "MIT OR Apache-2.0"
repository = "https://github.com/kyren/hashlink"
[dependencies.hashbrown]
-version = "0.12.0"
+version = "0.13"
[dependencies.serde]
version = "1.0"
optional = true
-[dev-dependencies.fxhash]
-version = "0.2.1"
+[dev-dependencies.rustc-hash]
+version = "1.1"
[dev-dependencies.serde_test]
version = "1.0"
diff --git a/third_party/rust/hashlink/tests/serde.rs b/third_party/rust/hashlink/tests/serde.rs
index d397a245fa..2cf4a3e3fb 100644
--- a/third_party/rust/hashlink/tests/serde.rs
+++ b/third_party/rust/hashlink/tests/serde.rs
@@ -1,7 +1,9 @@
#![cfg(feature = "serde_impl")]
-use fxhash::FxBuildHasher;
+use std::hash::BuildHasherDefault;
+
use hashlink::{LinkedHashMap, LinkedHashSet};
+use rustc_hash::FxHasher;
use serde_test::{assert_tokens, Token};
#[test]
@@ -35,14 +37,14 @@ fn map_serde_tokens() {
#[test]
fn map_serde_tokens_empty_generic() {
- let map = LinkedHashMap::<char, u32, FxBuildHasher>::with_hasher(FxBuildHasher::default());
+ let map = LinkedHashMap::<char, u32, BuildHasherDefault<FxHasher>>::default();
assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]);
}
#[test]
fn map_serde_tokens_generic() {
- let mut map = LinkedHashMap::with_hasher(FxBuildHasher::default());
+ let mut map = LinkedHashMap::<char, i32, BuildHasherDefault<FxHasher>>::default();
map.insert('a', 10);
map.insert('b', 20);
map.insert('c', 30);
@@ -90,7 +92,7 @@ fn set_serde_tokens() {
#[test]
fn set_serde_tokens_generic() {
- let mut set = LinkedHashSet::with_hasher(FxBuildHasher::default());
+ let mut set = LinkedHashSet::<char, BuildHasherDefault<FxHasher>>::default();
set.insert('a');
set.insert('b');
set.insert('c');
diff --git a/third_party/rust/indexmap/.cargo-checksum.json b/third_party/rust/indexmap/.cargo-checksum.json
index 0f44683d7f..50a4338741 100644
--- a/third_party/rust/indexmap/.cargo-checksum.json
+++ b/third_party/rust/indexmap/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"1290d383adfdcd24f158a4619afb5547d633c83c0a1ab3b5c1ee0dabe4fb1f36","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ecc269ef87fd38a1d98e30bfac9ba964a9dbd9315c3770fed98d4d7cb5882055","README.md":"f8b02aa7c20fc0f5bc13de9e9e78899ec8cdbc16c2db880a1d0bc14c25b07542","RELEASES.md":"85d9d9bc78e94df7ce90300bb94099b9ab2696d1b3f6b815c22761522878e679","benches/bench.rs":"3b2900abbc9e8a60af78b0395222ee75e86bc68519a0f38477387d1572eed397","benches/faststring.rs":"5fdd6cdb19d0557ed58f241e809a240cf8939d9e5b87a72d5f127f81ab98380b","build.rs":"558b4d0b9e9b3a44f7e1a2b69f7a7567ea721cd45cb54f4e458e850bf702f35c","src/arbitrary.rs":"bb8bda10f686abe57eef1446d3fc3fc6fb251f95629b28c20e620a4838c43db8","src/equivalent.rs":"2e6ae24ef09a09b917f4e2b0f6288f901878e42f5080f61b1bd1afdcc90aba87","src/lib.rs":"ea2cbe4f6cc2c4a75f42c9fc936503e6bee0f136c60f6811a2a9907ed8886443","src/macros.rs":"80c22f630e7f81e6fa663ca4c9e50cf5f332c8905d72d1338bd16f24eb353c2a","src/map.rs":"2e9cbfa240865cfd6b6b972bdbdb39283e6302dd2d0d72b3c2bfce4414bf5729","src/map/core.rs":"8422cd774c5db7d83cdeb0c5836c10f29caa1bee8d95b0d674b01b32e7ce80d8","src/map/core/raw.rs":"4e5fac4fecccc352268351d8b1f82b345067b5c029bba7e6ab88e8f8bc799c6a","src/mutable_keys.rs":"a919065b59000286eb11c7d46f6896bf0a1d484c9dac5e61d80bb8990c9fbedb","src/rayon/map.rs":"1a508c7c95c5d56113b851f7ce140d62ad541f1c6129352a7ec62d5bea7af4a1","src/rayon/mod.rs":"019e9379ccab57a299ab5b5a2c0efc7561b77a715a5afe8f797c7e8330c6206c","src/rayon/set.rs":"ba00e88e90fb7ab803589f99f24b595d60309e541aae3d01fdde21bff3840194","src/rustc.rs":"fe7a348c5a10a66880cb6c737593fe79d3b6de40f44ba0d7b89204aa95e14a3a","src/serde.rs":"d45ec8fb9c02594ca6f2e9b20764778b2b4193a24a52f1e233160a33efc6e683","src/serde_seq.rs":"c54a52fa607b6ccddda1e76e829778ca304c49b5f434edc5e582a5386c35d662","src/set.rs":"0a57affb623fa6b28df18cc14841e4f076cbd1da5c809635d202f865640af1ee","src/util.rs":"ab712bce71b54cf2763e6010e64bb5944d1d59ce15e2f2beffa7ceed204d6a68","tests/equivalent_trait.rs":"efe9393069e3cfc893d2c9c0343679979578e437fdb98a10baefeced027ba310","tests/macros_full_path.rs":"c33c86d7341581fdd08e2e6375a4afca507fa603540c54a3b9e51c4cd011cd71","tests/quick.rs":"1addbc6cbcb1aae5b8bde0fb0e18197d947e8f13244e4ae7ebf97bdda00eafea","tests/tests.rs":"f6dbeeb0e2950402b0e66ac52bf74c9e4197d3c5d9c0dde64a7998a2ef74d327"},"package":"bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"} \ No newline at end of file
+{"files":{"Cargo.toml":"34db4bcb2f85a5e3980eb06d3ec4aac3fa0ef6ff48b57ef28aba6dfc1fbeedbb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ecc269ef87fd38a1d98e30bfac9ba964a9dbd9315c3770fed98d4d7cb5882055","README.md":"98781168dcaf64ed3eecbf7146311045433773486259a372b985c9ae28545017","RELEASES.md":"0f8b4d3a352bddda55384f2ffa804b39e7d73aefa27364c56378d0043756e491","benches/bench.rs":"3b2900abbc9e8a60af78b0395222ee75e86bc68519a0f38477387d1572eed397","benches/faststring.rs":"5fdd6cdb19d0557ed58f241e809a240cf8939d9e5b87a72d5f127f81ab98380b","src/arbitrary.rs":"068713b1e8e762dbe9e4d19d555e77c17e59408335a40f4777d6100340605655","src/borsh.rs":"74121b426379d4f7365757ffd4f3dd469543fa1635193460fe268799a78a0706","src/lib.rs":"57ca834c31a7bb70821f476de916486ab58b9ad3922761153972b5f3923fe078","src/macros.rs":"1493afee2db2c9744be99e5fc32d0cd3742b8a3dbb31fa786ebbe28f1387e7d6","src/map.rs":"d1422353531e6114778033e901b30c8138da048075582fb396d299211958044c","src/map/core.rs":"eb291748598e1aa9112ee068a9a5fea7b1190114c4007de179528408f7439faa","src/map/core/entry.rs":"7d987cc5099099e0c9020afa7b3c23d20f11812dce9d684db03ff390f4068691","src/map/core/raw.rs":"30cc048f7c7f0deb2eb1c699a15e6b18dff1187404228c55e404c0d5bfe11f3e","src/map/core/raw_entry_v1.rs":"0942938c167aca6c892bd78e431d2b7366443e1d6f4f0d930b0bf72ca3ab8054","src/map/iter.rs":"ae0023c1ccc78ac765dc43fe51f233f2fca1ebba132490db8429941183d2c497","src/map/mutable.rs":"9d8dded5a95a21fba2d97ef64610627fae97dffc096e872b0c378ae8b63de53b","src/map/serde_seq.rs":"ce06b5bb816c15ea8fe3d2c358baa90fe6f45ecb585623a69592d6de69319194","src/map/slice.rs":"c0d770a6ce47fa4f3d9c82b468504c567dc4031d8f3694603e2b5bcc295cf3e1","src/map/tests.rs":"714674a55103dc57c16d9fe2916d462a655dc217e079a7e0ed5a62ab0f9749f1","src/rayon/map.rs":"0fad36851fdf6894695e526c684c9b3afeac82e29016e6a523eea68cc3b2d19d","src/rayon/mod.rs":"1c9c13b5cf6974f652ded53b014774944c761f079a77a61b3bc52eaa3d4b972b","src/rayon/set.rs":"4b076dbfd9a7eb2fd65783f1c8a5acabe075403f3d05e30c337676acec25d8ee","src/rustc.rs":"fe7a348c5a10a66880cb6c737593fe79d3b6de40f44ba0d7b89204aa95e14a3a","src/serde.rs":"23fd6b5e8f6795e4121693ac16dab61e76c4d8c83e6da1b3ef26d081fae28e79","src/set.rs":"fe9ca3fea8c1156a13ffccdf49d8acb9c79433586c1dfc71ef21ecfcebfd8b14","src/set/iter.rs":"a387c48eff0338b5c8f4e2059403bd665a9c8037634cc5860f80b72a4fbbed30","src/set/mutable.rs":"83ac1719a5eb5bdefac0e9eaa87b80ed98e39c5f2bb4cb69143e3fbff4302e6d","src/set/slice.rs":"9b5aa57e3510d5e17a91a6eaa2ee66a3d79d40b171beb86f7dd9208277135900","src/set/tests.rs":"d9c182cd776ca9182b5284f06eacc70c5f33a66aff3021c35134ffd1d7630c05","src/util.rs":"dbd57cfdac2a72db8c5ce83bf288bcaf33b5ae59adddcd088792a624c4c0e909","tests/equivalent_trait.rs":"efe9393069e3cfc893d2c9c0343679979578e437fdb98a10baefeced027ba310","tests/macros_full_path.rs":"c33c86d7341581fdd08e2e6375a4afca507fa603540c54a3b9e51c4cd011cd71","tests/quick.rs":"9759dcc34d86d9635d9d18be6358f5f3e3c0f995874b64b5a7ca4b582f4acedb","tests/tests.rs":"f6dbeeb0e2950402b0e66ac52bf74c9e4197d3c5d9c0dde64a7998a2ef74d327"},"package":"168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"} \ No newline at end of file
diff --git a/third_party/rust/indexmap/Cargo.toml b/third_party/rust/indexmap/Cargo.toml
index 28f3618f01..51d6e6e97c 100644
--- a/third_party/rust/indexmap/Cargo.toml
+++ b/third_party/rust/indexmap/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.56"
+rust-version = "1.63"
name = "indexmap"
-version = "1.9.3"
+version = "2.2.6"
description = "A hash table with consistent order and fast iteration."
documentation = "https://docs.rs/indexmap/"
readme = "README.md"
@@ -26,22 +26,27 @@ categories = [
"no-std",
]
license = "Apache-2.0 OR MIT"
-repository = "https://github.com/bluss/indexmap"
-
-[package.metadata.release]
-no-dev-version = true
-tag-name = "{{version}}"
+repository = "https://github.com/indexmap-rs/indexmap"
[package.metadata.docs.rs]
features = [
"arbitrary",
"quickcheck",
- "serde-1",
+ "serde",
+ "borsh",
"rayon",
]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[package.metadata.release]
+no-dev-version = true
+tag-name = "{{version}}"
[profile.bench]
-debug = true
+debug = 2
[lib]
bench = false
@@ -51,8 +56,17 @@ version = "1.0"
optional = true
default-features = false
+[dependencies.borsh]
+version = "1.2"
+optional = true
+default-features = false
+
+[dependencies.equivalent]
+version = "1.0"
+default-features = false
+
[dependencies.hashbrown]
-version = "0.12"
+version = "0.14.1"
features = ["raw"]
default-features = false
@@ -62,7 +76,7 @@ optional = true
default-features = false
[dependencies.rayon]
-version = "1.4.1"
+version = "1.5.3"
optional = true
[dependencies.rustc-rayon]
@@ -82,7 +96,7 @@ version = "1.0"
version = "0.2.1"
[dev-dependencies.itertools]
-version = "0.10"
+version = "0.12"
[dev-dependencies.lazy_static]
version = "1.3"
@@ -98,11 +112,10 @@ features = ["small_rng"]
[dev-dependencies.serde_derive]
version = "1.0"
-[build-dependencies.autocfg]
-version = "1"
-
[features]
-serde-1 = ["serde"]
+default = ["std"]
std = []
test_debug = []
-test_low_transition_point = []
+
+[lints.clippy]
+style = "allow"
diff --git a/third_party/rust/indexmap/README.md b/third_party/rust/indexmap/README.md
index d80b7099ce..9112d52893 100644
--- a/third_party/rust/indexmap/README.md
+++ b/third_party/rust/indexmap/README.md
@@ -1,9 +1,9 @@
# indexmap
-[![build status](https://github.com/bluss/indexmap/workflows/Continuous%20integration/badge.svg?branch=master)](https://github.com/bluss/indexmap/actions)
+[![build status](https://github.com/indexmap-rs/indexmap/workflows/Continuous%20integration/badge.svg?branch=master)](https://github.com/indexmap-rs/indexmap/actions)
[![crates.io](https://img.shields.io/crates/v/indexmap.svg)](https://crates.io/crates/indexmap)
[![docs](https://docs.rs/indexmap/badge.svg)](https://docs.rs/indexmap)
-[![rustc](https://img.shields.io/badge/rust-1.56%2B-orange.svg)](https://img.shields.io/badge/rust-1.56%2B-orange.svg)
+[![rustc](https://img.shields.io/badge/rust-1.63%2B-orange.svg)](https://img.shields.io/badge/rust-1.63%2B-orange.svg)
A pure-Rust hash table which preserves (in a limited sense) insertion order.
@@ -26,7 +26,9 @@ was indexmap, a hash table that has following properties:
- Order is **independent of hash function** and hash values of keys.
- Fast to iterate.
- Indexed in compact space.
-- Preserves insertion order **as long** as you don't call `.remove()`.
+- Preserves insertion order **as long** as you don't call `.remove()`,
+ `.swap_remove()`, or other methods that explicitly change order.
+ The alternate `.shift_remove()` does preserve relative order.
- Uses hashbrown for the inner table, just like Rust's libstd `HashMap` does.
## Performance
@@ -52,4 +54,4 @@ which is roughly:
# Recent Changes
-See [RELEASES.md](https://github.com/bluss/indexmap/blob/master/RELEASES.md).
+See [RELEASES.md](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md).
diff --git a/third_party/rust/indexmap/RELEASES.md b/third_party/rust/indexmap/RELEASES.md
index 7ea8b702e0..8c033db042 100644
--- a/third_party/rust/indexmap/RELEASES.md
+++ b/third_party/rust/indexmap/RELEASES.md
@@ -1,388 +1,508 @@
-- 1.9.3
+# Releases
- - Bump the `rustc-rayon` dependency, for compiler use only.
+## 2.2.6
-- 1.9.2
+- Added trait `MutableValues` for opt-in mutable access to set values.
- - `IndexMap` and `IndexSet` both implement `arbitrary::Arbitrary<'_>` and
- `quickcheck::Arbitrary` if those optional dependency features are enabled.
+## 2.2.5
-- 1.9.1
+- Added optional `borsh` serialization support.
- - The MSRV now allows Rust 1.56.0 as well. However, currently `hashbrown`
- 0.12.1 requires 1.56.1, so users on 1.56.0 should downgrade that to 0.12.0
- until there is a later published version relaxing its requirement.
+## 2.2.4
-- 1.9.0
+- Added an `insert_sorted` method on `IndexMap`, `IndexSet`, and `VacantEntry`.
+- Avoid hashing for lookups in single-entry maps.
+- Limit preallocated memory in `serde` deserializers.
- - **MSRV**: Rust 1.56.1 or later is now required.
+## 2.2.3
- - The `hashbrown` dependency has been updated to version 0.12.
+- Added `move_index` and `swap_indices` methods to `IndexedEntry`,
+ `OccupiedEntry`, and `RawOccupiedEntryMut`, functioning like the existing
+ methods on `IndexMap`.
+- Added `shift_insert` methods on `VacantEntry` and `RawVacantEntryMut`, as
+ well as `shift_insert_hashed_nocheck` on the latter, to insert the new entry
+ at a particular index.
+- Added `shift_insert` methods on `IndexMap` and `IndexSet` to insert a new
+ entry at a particular index, or else move an existing entry there.
- - `IterMut` and `ValuesMut` now implement `Debug`.
+## 2.2.2
- - The new `IndexMap::shrink_to` and `IndexSet::shrink_to` methods shrink
- the capacity with a lower bound.
+- Added indexing methods to raw entries: `RawEntryBuilder::from_hash_full`,
+ `RawEntryBuilder::index_from_hash`, and `RawEntryMut::index`.
- - The new `IndexMap::move_index` and `IndexSet::move_index` methods change
- the position of an item from one index to another, shifting the items
- between to accommodate the move.
+## 2.2.1
-- 1.8.2
+- Corrected the signature of `RawOccupiedEntryMut::into_key(self) -> &'a mut K`,
+ This a breaking change from 2.2.0, but that version was published for less
+ than a day and has now been yanked.
- - Bump the `rustc-rayon` dependency, for compiler use only.
+## 2.2.0
-- 1.8.1
+- The new `IndexMap::get_index_entry` method finds an entry by its index for
+ in-place manipulation.
- - The new `IndexSet::replace_full` will return the index of the item along
- with the replaced value, if any, by @zakcutner in PR [222].
+- The `Keys` iterator now implements `Index<usize>` for quick access to the
+ entry's key, compared to indexing the map to get the value.
-[222]: https://github.com/bluss/indexmap/pull/222
+- The new `IndexMap::splice` and `IndexSet::splice` methods will drain the
+ given range as an iterator, and then replace that range with entries from
+ an input iterator.
-- 1.8.0
+- The new trait `RawEntryApiV1` offers opt-in access to a raw entry API for
+ `IndexMap`, corresponding to the unstable API on `HashSet` as of Rust 1.75.
- - The new `IndexMap::into_keys` and `IndexMap::into_values` will consume
- the map into keys or values, respectively, matching Rust 1.54's `HashMap`
- methods, by @taiki-e in PR [195].
+- Many `IndexMap` and `IndexSet` methods have relaxed their type constraints,
+ e.g. removing `K: Hash` on methods that don't actually need to hash.
- - More of the iterator types implement `Debug`, `ExactSizeIterator`, and
- `FusedIterator`, by @cuviper in PR [196].
+- Removal methods `remove`, `remove_entry`, and `take` are now deprecated
+ in favor of their `shift_` or `swap_` prefixed variants, which are more
+ explicit about their effect on the index and order of remaining items.
+ The deprecated methods will remain to guide drop-in replacements from
+ `HashMap` and `HashSet` toward the prefixed methods.
- - `IndexMap` and `IndexSet` now implement rayon's `ParallelDrainRange`,
- by @cuviper in PR [197].
+## 2.1.0
- - `IndexMap::with_hasher` and `IndexSet::with_hasher` are now `const`
- functions, allowing static maps and sets, by @mwillsey in PR [203].
+- Empty slices can now be created with `map::Slice::{new, new_mut}` and
+ `set::Slice::new`. In addition, `Slice::new`, `len`, and `is_empty` are
+ now `const` functions on both types.
- - `IndexMap` and `IndexSet` now implement `From` for arrays, matching
- Rust 1.56's implementation for `HashMap`, by @rouge8 in PR [205].
+- `IndexMap`, `IndexSet`, and their respective `Slice`s all have binary
+ search methods for sorted data: map `binary_search_keys` and set
+ `binary_search` for plain comparison, `binary_search_by` for custom
+ comparators, `binary_search_by_key` for key extraction, and
+ `partition_point` for boolean conditions.
- - `IndexMap` and `IndexSet` now have methods `sort_unstable_keys`,
- `sort_unstable_by`, `sorted_unstable_by`, and `par_*` equivalents,
- which sort in-place without preserving the order of equal items, by
- @bhgomes in PR [211].
+## 2.0.2
-[195]: https://github.com/bluss/indexmap/pull/195
-[196]: https://github.com/bluss/indexmap/pull/196
-[197]: https://github.com/bluss/indexmap/pull/197
-[203]: https://github.com/bluss/indexmap/pull/203
-[205]: https://github.com/bluss/indexmap/pull/205
-[211]: https://github.com/bluss/indexmap/pull/211
+- The `hashbrown` dependency has been updated to version 0.14.1 to
+ complete the support for Rust 1.63.
-- 1.7.0
+## 2.0.1
- - **MSRV**: Rust 1.49 or later is now required.
+- **MSRV**: Rust 1.63.0 is now supported as well, pending publication of
+ `hashbrown`'s relaxed MSRV (or use cargo `--ignore-rust-version`).
- - The `hashbrown` dependency has been updated to version 0.11.
+## 2.0.0
-- 1.6.2
+- **MSRV**: Rust 1.64.0 or later is now required.
- - Fixed to match `std` behavior, `OccupiedEntry::key` now references the
- existing key in the map instead of the lookup key, by @cuviper in PR [170].
+- The `"std"` feature is no longer auto-detected. It is included in the
+ default feature set, or else can be enabled like any other Cargo feature.
- - The new `Entry::or_insert_with_key` matches Rust 1.50's `Entry` method,
- passing `&K` to the callback to create a value, by @cuviper in PR [175].
+- The `"serde-1"` feature has been removed, leaving just the optional
+ `"serde"` dependency to be enabled like a feature itself.
-[170]: https://github.com/bluss/indexmap/pull/170
-[175]: https://github.com/bluss/indexmap/pull/175
+- `IndexMap::get_index_mut` now returns `Option<(&K, &mut V)>`, changing
+ the key part from `&mut K` to `&K`. There is also a new alternative
+ `MutableKeys::get_index_mut2` to access the former behavior.
-- 1.6.1
+- The new `map::Slice<K, V>` and `set::Slice<T>` offer a linear view of maps
+ and sets, behaving a lot like normal `[(K, V)]` and `[T]` slices. Notably,
+ comparison traits like `Eq` only consider items in order, rather than hash
+ lookups, and slices even implement `Hash`.
- - The new `serde_seq` module implements `IndexMap` serialization as a
- sequence to ensure order is preserved, by @cuviper in PR [158].
+- `IndexMap` and `IndexSet` now have `sort_by_cached_key` and
+ `par_sort_by_cached_key` methods which perform stable sorts in place
+ using a key extraction function.
- - New methods on maps and sets work like the `Vec`/slice methods by the same name:
- `truncate`, `split_off`, `first`, `first_mut`, `last`, `last_mut`, and
- `swap_indices`, by @cuviper in PR [160].
+- `IndexMap` and `IndexSet` now have `reserve_exact`, `try_reserve`, and
+ `try_reserve_exact` methods that correspond to the same methods on `Vec`.
+ However, exactness only applies to the direct capacity for items, while the
+ raw hash table still follows its own rules for capacity and load factor.
-[158]: https://github.com/bluss/indexmap/pull/158
-[160]: https://github.com/bluss/indexmap/pull/160
+- The `Equivalent` trait is now re-exported from the `equivalent` crate,
+ intended as a common base to allow types to work with multiple map types.
-- 1.6.0
+- The `hashbrown` dependency has been updated to version 0.14.
- - **MSRV**: Rust 1.36 or later is now required.
+- The `serde_seq` module has been moved from the crate root to below the
+ `map` module.
- - The `hashbrown` dependency has been updated to version 0.9.
+## 1.9.3
-- 1.5.2
+- Bump the `rustc-rayon` dependency, for compiler use only.
- - The new "std" feature will force the use of `std` for users that explicitly
- want the default `S = RandomState`, bypassing the autodetection added in 1.3.0,
- by @cuviper in PR [145].
+## 1.9.2
-[145]: https://github.com/bluss/indexmap/pull/145
+- `IndexMap` and `IndexSet` both implement `arbitrary::Arbitrary<'_>` and
+ `quickcheck::Arbitrary` if those optional dependency features are enabled.
-- 1.5.1
+## 1.9.1
- - Values can now be indexed by their `usize` position by @cuviper in PR [132].
+- The MSRV now allows Rust 1.56.0 as well. However, currently `hashbrown`
+ 0.12.1 requires 1.56.1, so users on 1.56.0 should downgrade that to 0.12.0
+ until there is a later published version relaxing its requirement.
- - Some of the generic bounds have been relaxed to match `std` by @cuviper in PR [141].
+## 1.9.0
- - `drain` now accepts any `R: RangeBounds<usize>` by @cuviper in PR [142].
+- **MSRV**: Rust 1.56.1 or later is now required.
-[132]: https://github.com/bluss/indexmap/pull/132
-[141]: https://github.com/bluss/indexmap/pull/141
-[142]: https://github.com/bluss/indexmap/pull/142
+- The `hashbrown` dependency has been updated to version 0.12.
-- 1.5.0
+- `IterMut` and `ValuesMut` now implement `Debug`.
- - **MSRV**: Rust 1.32 or later is now required.
+- The new `IndexMap::shrink_to` and `IndexSet::shrink_to` methods shrink
+ the capacity with a lower bound.
- - The inner hash table is now based on `hashbrown` by @cuviper in PR [131].
- This also completes the method `reserve` and adds `shrink_to_fit`.
+- The new `IndexMap::move_index` and `IndexSet::move_index` methods change
+ the position of an item from one index to another, shifting the items
+ between to accommodate the move.
- - Add new methods `get_key_value`, `remove_entry`, `swap_remove_entry`,
- and `shift_remove_entry`, by @cuviper in PR [136]
+## 1.8.2
- - `Clone::clone_from` reuses allocations by @cuviper in PR [125]
+- Bump the `rustc-rayon` dependency, for compiler use only.
- - Add new method `reverse` by @linclelinkpart5 in PR [128]
+## 1.8.1
-[125]: https://github.com/bluss/indexmap/pull/125
-[128]: https://github.com/bluss/indexmap/pull/128
-[131]: https://github.com/bluss/indexmap/pull/131
-[136]: https://github.com/bluss/indexmap/pull/136
+- The new `IndexSet::replace_full` will return the index of the item along
+ with the replaced value, if any, by @zakcutner in PR [222].
-- 1.4.0
+[222]: https://github.com/indexmap-rs/indexmap/pull/222
- - Add new method `get_index_of` by @Thermatrix in PR [115] and [120]
+## 1.8.0
- - Fix build script rebuild-if-changed configuration to use "build.rs";
- fixes issue [123]. Fix by @cuviper.
+- The new `IndexMap::into_keys` and `IndexMap::into_values` will consume
+ the map into keys or values, respectively, matching Rust 1.54's `HashMap`
+ methods, by @taiki-e in PR [195].
- - Dev-dependencies (rand and quickcheck) have been updated. The crate's tests
- now run using Rust 1.32 or later (MSRV for building the crate has not changed).
- by @kjeremy and @bluss
+- More of the iterator types implement `Debug`, `ExactSizeIterator`, and
+ `FusedIterator`, by @cuviper in PR [196].
-[123]: https://github.com/bluss/indexmap/issues/123
-[115]: https://github.com/bluss/indexmap/pull/115
-[120]: https://github.com/bluss/indexmap/pull/120
+- `IndexMap` and `IndexSet` now implement rayon's `ParallelDrainRange`,
+ by @cuviper in PR [197].
-- 1.3.2
+- `IndexMap::with_hasher` and `IndexSet::with_hasher` are now `const`
+ functions, allowing static maps and sets, by @mwillsey in PR [203].
- - Maintenance update to regenerate the published `Cargo.toml`.
+- `IndexMap` and `IndexSet` now implement `From` for arrays, matching
+ Rust 1.56's implementation for `HashMap`, by @rouge8 in PR [205].
-- 1.3.1
+- `IndexMap` and `IndexSet` now have methods `sort_unstable_keys`,
+ `sort_unstable_by`, `sorted_unstable_by`, and `par_*` equivalents,
+ which sort in-place without preserving the order of equal items, by
+ @bhgomes in PR [211].
- - Maintenance update for formatting and `autocfg` 1.0.
+[195]: https://github.com/indexmap-rs/indexmap/pull/195
+[196]: https://github.com/indexmap-rs/indexmap/pull/196
+[197]: https://github.com/indexmap-rs/indexmap/pull/197
+[203]: https://github.com/indexmap-rs/indexmap/pull/203
+[205]: https://github.com/indexmap-rs/indexmap/pull/205
+[211]: https://github.com/indexmap-rs/indexmap/pull/211
-- 1.3.0
+## 1.7.0
- - The deprecation messages in the previous version have been removed.
- (The methods have not otherwise changed.) Docs for removal methods have been
- improved.
- - From Rust 1.36, this crate supports being built **without std**, requiring
- `alloc` instead. This is enabled automatically when it is detected that
- `std` is not available. There is no crate feature to enable/disable to
- trigger this. The new build-dep `autocfg` enables this.
+- **MSRV**: Rust 1.49 or later is now required.
-- 1.2.0
+- The `hashbrown` dependency has been updated to version 0.11.
- - Plain `.remove()` now has a deprecation message, it informs the user
- about picking one of the removal functions `swap_remove` and `shift_remove`
- which have different performance and order semantics.
- Plain `.remove()` will not be removed, the warning message and method
- will remain until further.
+## 1.6.2
- - Add new method `shift_remove` for order preserving removal on the map,
- and `shift_take` for the corresponding operation on the set.
+- Fixed to match `std` behavior, `OccupiedEntry::key` now references the
+ existing key in the map instead of the lookup key, by @cuviper in PR [170].
- - Add methods `swap_remove`, `swap_remove_entry` to `Entry`.
+- The new `Entry::or_insert_with_key` matches Rust 1.50's `Entry` method,
+ passing `&K` to the callback to create a value, by @cuviper in PR [175].
- - Fix indexset/indexmap to support full paths, like `indexmap::indexmap!()`
+[170]: https://github.com/indexmap-rs/indexmap/pull/170
+[175]: https://github.com/indexmap-rs/indexmap/pull/175
- - Internal improvements: fix warnings, deprecations and style lints
+## 1.6.1
-- 1.1.0
+- The new `serde_seq` module implements `IndexMap` serialization as a
+ sequence to ensure order is preserved, by @cuviper in PR [158].
- - Added optional feature `"rayon"` that adds parallel iterator support
- to `IndexMap` and `IndexSet` using Rayon. This includes all the regular
- iterators in parallel versions, and parallel sort.
+- New methods on maps and sets work like the `Vec`/slice methods by the same name:
+ `truncate`, `split_off`, `first`, `first_mut`, `last`, `last_mut`, and
+ `swap_indices`, by @cuviper in PR [160].
- - Implemented `Clone` for `map::{Iter, Keys, Values}` and
- `set::{Difference, Intersection, Iter, SymmetricDifference, Union}`
+[158]: https://github.com/indexmap-rs/indexmap/pull/158
+[160]: https://github.com/indexmap-rs/indexmap/pull/160
- - Implemented `Debug` for `map::{Entry, IntoIter, Iter, Keys, Values}` and
- `set::{Difference, Intersection, IntoIter, Iter, SymmetricDifference, Union}`
+## 1.6.0
- - Serde trait `IntoDeserializer` are implemented for `IndexMap` and `IndexSet`.
+- **MSRV**: Rust 1.36 or later is now required.
- - Minimum Rust version requirement increased to Rust 1.30 for development builds.
+- The `hashbrown` dependency has been updated to version 0.9.
-- 1.0.2
+## 1.5.2
- - The new methods `IndexMap::insert_full` and `IndexSet::insert_full` are
- both like `insert` with the index included in the return value.
+- The new "std" feature will force the use of `std` for users that explicitly
+ want the default `S = RandomState`, bypassing the autodetection added in 1.3.0,
+ by @cuviper in PR [145].
- - The new method `Entry::and_modify` can be used to modify occupied
- entries, matching the new methods of `std` maps in Rust 1.26.
+[145]: https://github.com/indexmap-rs/indexmap/pull/145
- - The new method `Entry::or_default` inserts a default value in unoccupied
- entries, matching the new methods of `std` maps in Rust 1.28.
+## 1.5.1
-- 1.0.1
+- Values can now be indexed by their `usize` position by @cuviper in PR [132].
- - Document Rust version policy for the crate (see rustdoc)
+- Some of the generic bounds have been relaxed to match `std` by @cuviper in PR [141].
-- 1.0.0
+- `drain` now accepts any `R: RangeBounds<usize>` by @cuviper in PR [142].
- - This is the 1.0 release for `indexmap`! (the crate and datastructure
- formerly known as “ordermap”)
- - `OccupiedEntry::insert` changed its signature, to use `&mut self` for
- the method receiver, matching the equivalent method for a standard
- `HashMap`. Thanks to @dtolnay for finding this bug.
- - The deprecated old names from ordermap were removed: `OrderMap`,
- `OrderSet`, `ordermap!{}`, `orderset!{}`. Use the new `IndexMap`
- etc names instead.
+[132]: https://github.com/indexmap-rs/indexmap/pull/132
+[141]: https://github.com/indexmap-rs/indexmap/pull/141
+[142]: https://github.com/indexmap-rs/indexmap/pull/142
-- 0.4.1
+## 1.5.0
- - Renamed crate to `indexmap`; the `ordermap` crate is now deprecated
- and the types `OrderMap/Set` now have a deprecation notice.
+- **MSRV**: Rust 1.32 or later is now required.
-- 0.4.0
+- The inner hash table is now based on `hashbrown` by @cuviper in PR [131].
+ This also completes the method `reserve` and adds `shrink_to_fit`.
- - This is the last release series for this `ordermap` under that name,
- because the crate is **going to be renamed** to `indexmap` (with types
- `IndexMap`, `IndexSet`) and no change in functionality!
- - The map and its associated structs moved into the `map` submodule of the
- crate, so that the map and set are symmetric
+- Add new methods `get_key_value`, `remove_entry`, `swap_remove_entry`,
+ and `shift_remove_entry`, by @cuviper in PR [136]
+
+- `Clone::clone_from` reuses allocations by @cuviper in PR [125]
+
+- Add new method `reverse` by @linclelinkpart5 in PR [128]
+
+[125]: https://github.com/indexmap-rs/indexmap/pull/125
+[128]: https://github.com/indexmap-rs/indexmap/pull/128
+[131]: https://github.com/indexmap-rs/indexmap/pull/131
+[136]: https://github.com/indexmap-rs/indexmap/pull/136
+
+## 1.4.0
+
+- Add new method `get_index_of` by @Thermatrix in PR [115] and [120]
+
+- Fix build script rebuild-if-changed configuration to use "build.rs";
+ fixes issue [123]. Fix by @cuviper.
+
+- Dev-dependencies (rand and quickcheck) have been updated. The crate's tests
+ now run using Rust 1.32 or later (MSRV for building the crate has not changed).
+ by @kjeremy and @bluss
+
+[123]: https://github.com/indexmap-rs/indexmap/issues/123
+[115]: https://github.com/indexmap-rs/indexmap/pull/115
+[120]: https://github.com/indexmap-rs/indexmap/pull/120
+
+## 1.3.2
+
+- Maintenance update to regenerate the published `Cargo.toml`.
+
+## 1.3.1
+
+- Maintenance update for formatting and `autocfg` 1.0.
+
+## 1.3.0
+
+- The deprecation messages in the previous version have been removed.
+ (The methods have not otherwise changed.) Docs for removal methods have been
+ improved.
+- From Rust 1.36, this crate supports being built **without std**, requiring
+ `alloc` instead. This is enabled automatically when it is detected that
+ `std` is not available. There is no crate feature to enable/disable to
+ trigger this. The new build-dep `autocfg` enables this.
+
+## 1.2.0
+
+- Plain `.remove()` now has a deprecation message, it informs the user
+ about picking one of the removal functions `swap_remove` and `shift_remove`
+ which have different performance and order semantics.
+ Plain `.remove()` will not be removed, the warning message and method
+ will remain until further.
+
+- Add new method `shift_remove` for order preserving removal on the map,
+ and `shift_take` for the corresponding operation on the set.
+
+- Add methods `swap_remove`, `swap_remove_entry` to `Entry`.
+
+- Fix indexset/indexmap to support full paths, like `indexmap::indexmap!()`
+
+- Internal improvements: fix warnings, deprecations and style lints
+
+## 1.1.0
+
+- Added optional feature `"rayon"` that adds parallel iterator support
+ to `IndexMap` and `IndexSet` using Rayon. This includes all the regular
+ iterators in parallel versions, and parallel sort.
+
+- Implemented `Clone` for `map::{Iter, Keys, Values}` and
+ `set::{Difference, Intersection, Iter, SymmetricDifference, Union}`
+
+- Implemented `Debug` for `map::{Entry, IntoIter, Iter, Keys, Values}` and
+ `set::{Difference, Intersection, IntoIter, Iter, SymmetricDifference, Union}`
+
+- Serde trait `IntoDeserializer` are implemented for `IndexMap` and `IndexSet`.
+
+- Minimum Rust version requirement increased to Rust 1.30 for development builds.
+
+## 1.0.2
+
+- The new methods `IndexMap::insert_full` and `IndexSet::insert_full` are
+ both like `insert` with the index included in the return value.
+
+- The new method `Entry::and_modify` can be used to modify occupied
+ entries, matching the new methods of `std` maps in Rust 1.26.
+
+- The new method `Entry::or_default` inserts a default value in unoccupied
+ entries, matching the new methods of `std` maps in Rust 1.28.
+
+## 1.0.1
+
+- Document Rust version policy for the crate (see rustdoc)
+
+## 1.0.0
+
+- This is the 1.0 release for `indexmap`! (the crate and datastructure
+ formerly known as “ordermap”)
+- `OccupiedEntry::insert` changed its signature, to use `&mut self` for
+ the method receiver, matching the equivalent method for a standard
+ `HashMap`. Thanks to @dtolnay for finding this bug.
+- The deprecated old names from ordermap were removed: `OrderMap`,
+ `OrderSet`, `ordermap!{}`, `orderset!{}`. Use the new `IndexMap`
+ etc names instead.
+
+## 0.4.1
+
+- Renamed crate to `indexmap`; the `ordermap` crate is now deprecated
+ and the types `OrderMap/Set` now have a deprecation notice.
+
+## 0.4.0
+
+- This is the last release series for this `ordermap` under that name,
+ because the crate is **going to be renamed** to `indexmap` (with types
+ `IndexMap`, `IndexSet`) and no change in functionality!
+- The map and its associated structs moved into the `map` submodule of the
+ crate, so that the map and set are symmetric
+ The iterators, `Entry` and other structs are now under `ordermap::map::`
- - Internally refactored `OrderMap<K, V, S>` so that all the main algorithms
- (insertion, lookup, removal etc) that don't use the `S` parameter (the
- hasher) are compiled without depending on `S`, which reduces generics bloat.
+- Internally refactored `OrderMap<K, V, S>` so that all the main algorithms
+ (insertion, lookup, removal etc) that don't use the `S` parameter (the
+ hasher) are compiled without depending on `S`, which reduces generics bloat.
- - `Entry<K, V>` no longer has a type parameter `S`, which is just like
- the standard `HashMap`'s entry.
+- `Entry<K, V>` no longer has a type parameter `S`, which is just like
+ the standard `HashMap`'s entry.
- - Minimum Rust version requirement increased to Rust 1.18
+- Minimum Rust version requirement increased to Rust 1.18
-- 0.3.5
+## 0.3.5
- - Documentation improvements
+- Documentation improvements
-- 0.3.4
+## 0.3.4
- - The `.retain()` methods for `OrderMap` and `OrderSet` now
- traverse the elements in order, and the retained elements **keep their order**
- - Added new methods `.sort_by()`, `.sort_keys()` to `OrderMap` and
- `.sort_by()`, `.sort()` to `OrderSet`. These methods allow you to
- sort the maps in place efficiently.
+- The `.retain()` methods for `OrderMap` and `OrderSet` now
+ traverse the elements in order, and the retained elements **keep their order**
+- Added new methods `.sort_by()`, `.sort_keys()` to `OrderMap` and
+ `.sort_by()`, `.sort()` to `OrderSet`. These methods allow you to
+ sort the maps in place efficiently.
-- 0.3.3
+## 0.3.3
- - Document insertion behaviour better by @lucab
- - Updated dependences (no feature changes) by @ignatenkobrain
+- Document insertion behaviour better by @lucab
+- Updated dependences (no feature changes) by @ignatenkobrain
-- 0.3.2
+## 0.3.2
- - Add `OrderSet` by @cuviper!
- - `OrderMap::drain` is now (too) a double ended iterator.
+- Add `OrderSet` by @cuviper!
+- `OrderMap::drain` is now (too) a double ended iterator.
-- 0.3.1
+## 0.3.1
- - In all ordermap iterators, forward the `collect` method to the underlying
- iterator as well.
- - Add crates.io categories.
+- In all ordermap iterators, forward the `collect` method to the underlying
+ iterator as well.
+- Add crates.io categories.
-- 0.3.0
+## 0.3.0
- - The methods `get_pair`, `get_pair_index` were both replaced by
- `get_full` (and the same for the mutable case).
- - Method `swap_remove_pair` replaced by `swap_remove_full`.
- - Add trait `MutableKeys` for opt-in mutable key access. Mutable key access
- is only possible through the methods of this extension trait.
- - Add new trait `Equivalent` for key equivalence. This extends the
- `Borrow` trait mechanism for `OrderMap::get` in a backwards compatible
- way, just some minor type inference related issues may become apparent.
- See [#10] for more information.
- - Implement `Extend<(&K, &V)>` by @xfix.
+- The methods `get_pair`, `get_pair_index` were both replaced by
+ `get_full` (and the same for the mutable case).
+- Method `swap_remove_pair` replaced by `swap_remove_full`.
+- Add trait `MutableKeys` for opt-in mutable key access. Mutable key access
+ is only possible through the methods of this extension trait.
+- Add new trait `Equivalent` for key equivalence. This extends the
+ `Borrow` trait mechanism for `OrderMap::get` in a backwards compatible
+ way, just some minor type inference related issues may become apparent.
+ See [#10] for more information.
+- Implement `Extend<(&K, &V)>` by @xfix.
-[#10]: https://github.com/bluss/ordermap/pull/10
+[#10]: https://github.com/indexmap-rs/indexmap/pull/10
-- 0.2.13
+## 0.2.13
- - Fix deserialization to support custom hashers by @Techcable.
- - Add methods `.index()` on the entry types by @garro95.
+- Fix deserialization to support custom hashers by @Techcable.
+- Add methods `.index()` on the entry types by @garro95.
-- 0.2.12
+## 0.2.12
- - Add methods `.with_hasher()`, `.hasher()`.
+- Add methods `.with_hasher()`, `.hasher()`.
-- 0.2.11
+## 0.2.11
- - Support `ExactSizeIterator` for the iterators. By @Binero.
- - Use `Box<[Pos]>` internally, saving a word in the `OrderMap` struct.
- - Serde support, with crate feature `"serde-1"`. By @xfix.
+- Support `ExactSizeIterator` for the iterators. By @Binero.
+- Use `Box<[Pos]>` internally, saving a word in the `OrderMap` struct.
+- Serde support, with crate feature `"serde-1"`. By @xfix.
-- 0.2.10
+## 0.2.10
- - Add iterator `.drain(..)` by @stevej.
+- Add iterator `.drain(..)` by @stevej.
-- 0.2.9
+## 0.2.9
- - Add method `.is_empty()` by @overvenus.
- - Implement `PartialEq, Eq` by @overvenus.
- - Add method `.sorted_by()`.
+- Add method `.is_empty()` by @overvenus.
+- Implement `PartialEq, Eq` by @overvenus.
+- Add method `.sorted_by()`.
-- 0.2.8
+## 0.2.8
- - Add iterators `.values()` and `.values_mut()`.
- - Fix compatibility with 32-bit platforms.
+- Add iterators `.values()` and `.values_mut()`.
+- Fix compatibility with 32-bit platforms.
-- 0.2.7
+## 0.2.7
- - Add `.retain()`.
+- Add `.retain()`.
-- 0.2.6
+## 0.2.6
- - Add `OccupiedEntry::remove_entry` and other minor entry methods,
- so that it now has all the features of `HashMap`'s entries.
+- Add `OccupiedEntry::remove_entry` and other minor entry methods,
+ so that it now has all the features of `HashMap`'s entries.
-- 0.2.5
+## 0.2.5
- - Improved `.pop()` slightly.
+- Improved `.pop()` slightly.
-- 0.2.4
+## 0.2.4
- - Improved performance of `.insert()` ([#3]) by @pczarn.
+- Improved performance of `.insert()` ([#3]) by @pczarn.
-[#3]: https://github.com/bluss/ordermap/pull/3
+[#3]: https://github.com/indexmap-rs/indexmap/pull/3
-- 0.2.3
+## 0.2.3
- - Generalize `Entry` for now, so that it works on hashmaps with non-default
- hasher. However, there's a lingering compat issue since libstd `HashMap`
- does not parameterize its entries by the hasher (`S` typarm).
- - Special case some iterator methods like `.nth()`.
+- Generalize `Entry` for now, so that it works on hashmaps with non-default
+ hasher. However, there's a lingering compat issue since libstd `HashMap`
+ does not parameterize its entries by the hasher (`S` typarm).
+- Special case some iterator methods like `.nth()`.
-- 0.2.2
+## 0.2.2
- - Disable the verbose `Debug` impl by default.
+- Disable the verbose `Debug` impl by default.
-- 0.2.1
+## 0.2.1
- - Fix doc links and clarify docs.
+- Fix doc links and clarify docs.
-- 0.2.0
+## 0.2.0
- - Add more `HashMap` methods & compat with its API.
- - Experimental support for `.entry()` (the simplest parts of the API).
- - Add `.reserve()` (placeholder impl).
- - Add `.remove()` as synonym for `.swap_remove()`.
- - Changed `.insert()` to swap value if the entry already exists, and
- return `Option`.
- - Experimental support as an *indexed* hash map! Added methods
- `.get_index()`, `.get_index_mut()`, `.swap_remove_index()`,
- `.get_pair_index()`, `.get_pair_index_mut()`.
+- Add more `HashMap` methods & compat with its API.
+- Experimental support for `.entry()` (the simplest parts of the API).
+- Add `.reserve()` (placeholder impl).
+- Add `.remove()` as synonym for `.swap_remove()`.
+- Changed `.insert()` to swap value if the entry already exists, and
+ return `Option`.
+- Experimental support as an *indexed* hash map! Added methods
+ `.get_index()`, `.get_index_mut()`, `.swap_remove_index()`,
+ `.get_pair_index()`, `.get_pair_index_mut()`.
-- 0.1.2
+## 0.1.2
- - Implement the 32/32 split idea for `Pos` which improves cache utilization
- and lookup performance.
+- Implement the 32/32 split idea for `Pos` which improves cache utilization
+ and lookup performance.
-- 0.1.1
+## 0.1.1
- - Initial release.
+- Initial release.
diff --git a/third_party/rust/indexmap/build.rs b/third_party/rust/indexmap/build.rs
deleted file mode 100644
index 9f9fa054f8..0000000000
--- a/third_party/rust/indexmap/build.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-fn main() {
- // If "std" is explicitly requested, don't bother probing the target for it.
- match std::env::var_os("CARGO_FEATURE_STD") {
- Some(_) => autocfg::emit("has_std"),
- None => autocfg::new().emit_sysroot_crate("std"),
- }
- autocfg::rerun_path("build.rs");
-}
diff --git a/third_party/rust/indexmap/src/arbitrary.rs b/third_party/rust/indexmap/src/arbitrary.rs
index 1347c8b54f..7798438c15 100644
--- a/third_party/rust/indexmap/src/arbitrary.rs
+++ b/third_party/rust/indexmap/src/arbitrary.rs
@@ -1,4 +1,5 @@
#[cfg(feature = "arbitrary")]
+#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
mod impl_arbitrary {
use crate::{IndexMap, IndexSet};
use arbitrary::{Arbitrary, Result, Unstructured};
@@ -35,6 +36,7 @@ mod impl_arbitrary {
}
#[cfg(feature = "quickcheck")]
+#[cfg_attr(docsrs, doc(cfg(feature = "quickcheck")))]
mod impl_quickcheck {
use crate::{IndexMap, IndexSet};
use alloc::boxed::Box;
diff --git a/third_party/rust/indexmap/src/borsh.rs b/third_party/rust/indexmap/src/borsh.rs
new file mode 100644
index 0000000000..c485bd5222
--- /dev/null
+++ b/third_party/rust/indexmap/src/borsh.rs
@@ -0,0 +1,122 @@
+#![cfg_attr(docsrs, doc(cfg(feature = "borsh")))]
+
+use alloc::vec::Vec;
+use core::hash::BuildHasher;
+use core::hash::Hash;
+use core::mem::size_of;
+
+use borsh::error::ERROR_ZST_FORBIDDEN;
+use borsh::io::{Error, ErrorKind, Read, Result, Write};
+use borsh::{BorshDeserialize, BorshSerialize};
+
+use crate::map::IndexMap;
+use crate::set::IndexSet;
+
+impl<K, V, S> BorshSerialize for IndexMap<K, V, S>
+where
+ K: BorshSerialize,
+ V: BorshSerialize,
+{
+ #[inline]
+ fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
+ check_zst::<K>()?;
+
+ let iterator = self.iter();
+
+ u32::try_from(iterator.len())
+ .map_err(|_| ErrorKind::InvalidData)?
+ .serialize(writer)?;
+
+ for (key, value) in iterator {
+ key.serialize(writer)?;
+ value.serialize(writer)?;
+ }
+
+ Ok(())
+ }
+}
+
+impl<K, V, S> BorshDeserialize for IndexMap<K, V, S>
+where
+ K: BorshDeserialize + Eq + Hash,
+ V: BorshDeserialize,
+ S: BuildHasher + Default,
+{
+ #[inline]
+ fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self> {
+ check_zst::<K>()?;
+ let vec = <Vec<(K, V)>>::deserialize_reader(reader)?;
+ Ok(vec.into_iter().collect::<IndexMap<K, V, S>>())
+ }
+}
+
+impl<T, S> BorshSerialize for IndexSet<T, S>
+where
+ T: BorshSerialize,
+{
+ #[inline]
+ fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
+ check_zst::<T>()?;
+
+ let iterator = self.iter();
+
+ u32::try_from(iterator.len())
+ .map_err(|_| ErrorKind::InvalidData)?
+ .serialize(writer)?;
+
+ for item in iterator {
+ item.serialize(writer)?;
+ }
+
+ Ok(())
+ }
+}
+
+impl<T, S> BorshDeserialize for IndexSet<T, S>
+where
+ T: BorshDeserialize + Eq + Hash,
+ S: BuildHasher + Default,
+{
+ #[inline]
+ fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self> {
+ check_zst::<T>()?;
+ let vec = <Vec<T>>::deserialize_reader(reader)?;
+ Ok(vec.into_iter().collect::<IndexSet<T, S>>())
+ }
+}
+
+fn check_zst<T>() -> Result<()> {
+ if size_of::<T>() == 0 {
+ return Err(Error::new(ErrorKind::InvalidData, ERROR_ZST_FORBIDDEN));
+ }
+ Ok(())
+}
+
+#[cfg(test)]
+mod borsh_tests {
+ use super::*;
+
+ #[test]
+ fn map_borsh_roundtrip() {
+ let original_map: IndexMap<i32, i32> = {
+ let mut map = IndexMap::new();
+ map.insert(1, 2);
+ map.insert(3, 4);
+ map.insert(5, 6);
+ map
+ };
+ let serialized_map = borsh::to_vec(&original_map).unwrap();
+ let deserialized_map: IndexMap<i32, i32> =
+ BorshDeserialize::try_from_slice(&serialized_map).unwrap();
+ assert_eq!(original_map, deserialized_map);
+ }
+
+ #[test]
+ fn set_borsh_roundtrip() {
+ let original_map: IndexSet<i32> = [1, 2, 3, 4, 5, 6].into_iter().collect();
+ let serialized_map = borsh::to_vec(&original_map).unwrap();
+ let deserialized_map: IndexSet<i32> =
+ BorshDeserialize::try_from_slice(&serialized_map).unwrap();
+ assert_eq!(original_map, deserialized_map);
+ }
+}
diff --git a/third_party/rust/indexmap/src/equivalent.rs b/third_party/rust/indexmap/src/equivalent.rs
deleted file mode 100644
index ad6635ffac..0000000000
--- a/third_party/rust/indexmap/src/equivalent.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use core::borrow::Borrow;
-
-/// Key equivalence trait.
-///
-/// This trait allows hash table lookup to be customized.
-/// It has one blanket implementation that uses the regular `Borrow` solution,
-/// just like `HashMap` and `BTreeMap` do, so that you can pass `&str` to lookup
-/// into a map with `String` keys and so on.
-///
-/// # Contract
-///
-/// The implementor **must** hash like `K`, if it is hashable.
-pub trait Equivalent<K: ?Sized> {
- /// Compare self to `key` and return `true` if they are equal.
- fn equivalent(&self, key: &K) -> bool;
-}
-
-impl<Q: ?Sized, K: ?Sized> Equivalent<K> for Q
-where
- Q: Eq,
- K: Borrow<Q>,
-{
- #[inline]
- fn equivalent(&self, key: &K) -> bool {
- *self == *key.borrow()
- }
-}
diff --git a/third_party/rust/indexmap/src/lib.rs b/third_party/rust/indexmap/src/lib.rs
index 6e94936124..7d88ffef08 100644
--- a/third_party/rust/indexmap/src/lib.rs
+++ b/third_party/rust/indexmap/src/lib.rs
@@ -1,7 +1,6 @@
// We *mostly* avoid unsafe code, but `map::core::raw` allows it to use `RawTable` buckets.
#![deny(unsafe_code)]
#![warn(rust_2018_idioms)]
-#![doc(html_root_url = "https://docs.rs/indexmap/1/")]
#![no_std]
//! [`IndexMap`] is a hash table where the iteration order of the key-value
@@ -10,11 +9,7 @@
//! [`IndexSet`] is a corresponding hash set using the same implementation and
//! with similar properties.
//!
-//! [`IndexMap`]: map/struct.IndexMap.html
-//! [`IndexSet`]: set/struct.IndexSet.html
-//!
-//!
-//! ### Feature Highlights
+//! ### Highlights
//!
//! [`IndexMap`] and [`IndexSet`] are drop-in compatible with the std `HashMap`
//! and `HashSet`, but they also have some features of note:
@@ -24,11 +19,44 @@
//! - The [`Equivalent`] trait, which offers more flexible equality definitions
//! between borrowed and owned versions of keys.
//! - The [`MutableKeys`][map::MutableKeys] trait, which gives opt-in mutable
-//! access to hash map keys.
+//! access to map keys, and [`MutableValues`][set::MutableValues] for sets.
+//!
+//! ### Feature Flags
+//!
+//! To reduce the amount of compiled code in the crate by default, certain
+//! features are gated behind [feature flags]. These allow you to opt in to (or
+//! out of) functionality. Below is a list of the features available in this
+//! crate.
+//!
+//! * `std`: Enables features which require the Rust standard library. For more
+//! information see the section on [`no_std`].
+//! * `rayon`: Enables parallel iteration and other parallel methods.
+//! * `serde`: Adds implementations for [`Serialize`] and [`Deserialize`]
+//! to [`IndexMap`] and [`IndexSet`]. Alternative implementations for
+//! (de)serializing [`IndexMap`] as an ordered sequence are available in the
+//! [`map::serde_seq`] module.
+//! * `borsh`: Adds implementations for [`BorshSerialize`] and [`BorshDeserialize`]
+//! to [`IndexMap`] and [`IndexSet`].
+//! * `arbitrary`: Adds implementations for the [`arbitrary::Arbitrary`] trait
+//! to [`IndexMap`] and [`IndexSet`].
+//! * `quickcheck`: Adds implementations for the [`quickcheck::Arbitrary`] trait
+//! to [`IndexMap`] and [`IndexSet`].
+//!
+//! _Note: only the `std` feature is enabled by default._
+//!
+//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
+//! [`no_std`]: #no-standard-library-targets
+//! [`Serialize`]: `::serde::Serialize`
+//! [`Deserialize`]: `::serde::Deserialize`
+//! [`BorshSerialize`]: `::borsh::BorshSerialize`
+//! [`BorshDeserialize`]: `::borsh::BorshDeserialize`
+//! [`arbitrary::Arbitrary`]: `::arbitrary::Arbitrary`
+//! [`quickcheck::Arbitrary`]: `::quickcheck::Arbitrary`
//!
//! ### Alternate Hashers
//!
-//! [`IndexMap`] and [`IndexSet`] have a default hasher type `S = RandomState`,
+//! [`IndexMap`] and [`IndexSet`] have a default hasher type
+//! [`S = RandomState`][std::collections::hash_map::RandomState],
//! just like the standard `HashMap` and `HashSet`, which is resistant to
//! HashDoS attacks but not the most performant. Type aliases can make it easier
//! to use alternate hashers:
@@ -53,33 +81,31 @@
//!
//! ### Rust Version
//!
-//! This version of indexmap requires Rust 1.56 or later.
+//! This version of indexmap requires Rust 1.63 or later.
//!
-//! The indexmap 1.x release series will use a carefully considered version
-//! upgrade policy, where in a later 1.x version, we will raise the minimum
+//! The indexmap 2.x release series will use a carefully considered version
+//! upgrade policy, where in a later 2.x version, we will raise the minimum
//! required Rust version.
//!
//! ## No Standard Library Targets
//!
-//! This crate supports being built without `std`, requiring
-//! `alloc` instead. This is enabled automatically when it is detected that
-//! `std` is not available. There is no crate feature to enable/disable to
-//! trigger this. It can be tested by building for a std-less target.
+//! This crate supports being built without `std`, requiring `alloc` instead.
+//! This is chosen by disabling the default "std" cargo feature, by adding
+//! `default-features = false` to your dependency specification.
//!
//! - Creating maps and sets using [`new`][IndexMap::new] and
-//! [`with_capacity`][IndexMap::with_capacity] is unavailable without `std`.
-//! Use methods [`IndexMap::default`][def],
-//! [`with_hasher`][IndexMap::with_hasher],
+//! [`with_capacity`][IndexMap::with_capacity] is unavailable without `std`.
+//! Use methods [`IndexMap::default`], [`with_hasher`][IndexMap::with_hasher],
//! [`with_capacity_and_hasher`][IndexMap::with_capacity_and_hasher] instead.
//! A no-std compatible hasher will be needed as well, for example
//! from the crate `twox-hash`.
//! - Macros [`indexmap!`] and [`indexset!`] are unavailable without `std`.
-//!
-//! [def]: map/struct.IndexMap.html#impl-Default
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
extern crate alloc;
-#[cfg(has_std)]
+#[cfg(feature = "std")]
#[macro_use]
extern crate std;
@@ -88,12 +114,10 @@ use alloc::vec::{self, Vec};
mod arbitrary;
#[macro_use]
mod macros;
-mod equivalent;
-mod mutable_keys;
+#[cfg(feature = "borsh")]
+mod borsh;
#[cfg(feature = "serde")]
mod serde;
-#[cfg(feature = "serde")]
-pub mod serde_seq;
mod util;
pub mod map;
@@ -107,9 +131,9 @@ mod rayon;
#[cfg(feature = "rustc-rayon")]
mod rustc;
-pub use crate::equivalent::Equivalent;
pub use crate::map::IndexMap;
pub use crate::set::IndexSet;
+pub use equivalent::Equivalent;
// shared private items
@@ -192,3 +216,59 @@ trait Entries {
where
F: FnOnce(&mut [Self::Entry]);
}
+
+/// The error type for [`try_reserve`][IndexMap::try_reserve] methods.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct TryReserveError {
+ kind: TryReserveErrorKind,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+enum TryReserveErrorKind {
+ // The standard library's kind is currently opaque to us, otherwise we could unify this.
+ Std(alloc::collections::TryReserveError),
+ CapacityOverflow,
+ AllocError { layout: alloc::alloc::Layout },
+}
+
+// These are not `From` so we don't expose them in our public API.
+impl TryReserveError {
+ fn from_alloc(error: alloc::collections::TryReserveError) -> Self {
+ Self {
+ kind: TryReserveErrorKind::Std(error),
+ }
+ }
+
+ fn from_hashbrown(error: hashbrown::TryReserveError) -> Self {
+ Self {
+ kind: match error {
+ hashbrown::TryReserveError::CapacityOverflow => {
+ TryReserveErrorKind::CapacityOverflow
+ }
+ hashbrown::TryReserveError::AllocError { layout } => {
+ TryReserveErrorKind::AllocError { layout }
+ }
+ },
+ }
+ }
+}
+
+impl core::fmt::Display for TryReserveError {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ let reason = match &self.kind {
+ TryReserveErrorKind::Std(e) => return core::fmt::Display::fmt(e, f),
+ TryReserveErrorKind::CapacityOverflow => {
+ " because the computed capacity exceeded the collection's maximum"
+ }
+ TryReserveErrorKind::AllocError { .. } => {
+ " because the memory allocator returned an error"
+ }
+ };
+ f.write_str("memory allocation failed")?;
+ f.write_str(reason)
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl std::error::Error for TryReserveError {}
diff --git a/third_party/rust/indexmap/src/macros.rs b/third_party/rust/indexmap/src/macros.rs
index ca26287be9..b347de22dd 100644
--- a/third_party/rust/indexmap/src/macros.rs
+++ b/third_party/rust/indexmap/src/macros.rs
@@ -1,6 +1,7 @@
-#[cfg(has_std)]
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[macro_export]
-/// Create an `IndexMap` from a list of key-value pairs
+/// Create an [`IndexMap`][crate::IndexMap] from a list of key-value pairs
///
/// ## Example
///
@@ -19,25 +20,25 @@
/// assert_eq!(map.keys().next(), Some(&"a"));
/// ```
macro_rules! indexmap {
- (@single $($x:tt)*) => (());
- (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::indexmap!(@single $rest)),*]));
-
($($key:expr => $value:expr,)+) => { $crate::indexmap!($($key => $value),+) };
($($key:expr => $value:expr),*) => {
{
- let _cap = $crate::indexmap!(@count $($key),*);
- let mut _map = $crate::IndexMap::with_capacity(_cap);
+ // Note: `stringify!($key)` is just here to consume the repetition,
+ // but we throw away that string literal during constant evaluation.
+ const CAP: usize = <[()]>::len(&[$({ stringify!($key); }),*]);
+ let mut map = $crate::IndexMap::with_capacity(CAP);
$(
- _map.insert($key, $value);
+ map.insert($key, $value);
)*
- _map
+ map
}
};
}
-#[cfg(has_std)]
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[macro_export]
-/// Create an `IndexSet` from a list of values
+/// Create an [`IndexSet`][crate::IndexSet] from a list of values
///
/// ## Example
///
@@ -56,18 +57,17 @@ macro_rules! indexmap {
/// assert_eq!(set.iter().next(), Some(&"a"));
/// ```
macro_rules! indexset {
- (@single $($x:tt)*) => (());
- (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::indexset!(@single $rest)),*]));
-
($($value:expr,)+) => { $crate::indexset!($($value),+) };
($($value:expr),*) => {
{
- let _cap = $crate::indexset!(@count $($value),*);
- let mut _set = $crate::IndexSet::with_capacity(_cap);
+ // Note: `stringify!($value)` is just here to consume the repetition,
+ // but we throw away that string literal during constant evaluation.
+ const CAP: usize = <[()]>::len(&[$({ stringify!($value); }),*]);
+ let mut set = $crate::IndexSet::with_capacity(CAP);
$(
- _set.insert($value);
+ set.insert($value);
)*
- _set
+ set
}
};
}
diff --git a/third_party/rust/indexmap/src/map.rs b/third_party/rust/indexmap/src/map.rs
index d39448d06d..82824c9002 100644
--- a/third_party/rust/indexmap/src/map.rs
+++ b/third_party/rust/indexmap/src/map.rs
@@ -1,36 +1,50 @@
-//! `IndexMap` is a hash table where the iteration order of the key-value
+//! [`IndexMap`] is a hash table where the iteration order of the key-value
//! pairs is independent of the hash values of the keys.
mod core;
+mod iter;
+mod mutable;
+mod slice;
-pub use crate::mutable_keys::MutableKeys;
+#[cfg(feature = "serde")]
+#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
+pub mod serde_seq;
+
+#[cfg(test)]
+mod tests;
+
+pub use self::core::raw_entry_v1::{self, RawEntryApiV1};
+pub use self::core::{Entry, IndexedEntry, OccupiedEntry, VacantEntry};
+pub use self::iter::{
+ Drain, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Splice, Values, ValuesMut,
+};
+pub use self::mutable::MutableKeys;
+pub use self::slice::Slice;
#[cfg(feature = "rayon")]
pub use crate::rayon::map as rayon;
-use crate::vec::{self, Vec};
use ::core::cmp::Ordering;
use ::core::fmt;
use ::core::hash::{BuildHasher, Hash, Hasher};
-use ::core::iter::FusedIterator;
+use ::core::mem;
use ::core::ops::{Index, IndexMut, RangeBounds};
-use ::core::slice::{Iter as SliceIter, IterMut as SliceIterMut};
+use alloc::boxed::Box;
+use alloc::vec::Vec;
-#[cfg(has_std)]
+#[cfg(feature = "std")]
use std::collections::hash_map::RandomState;
use self::core::IndexMapCore;
-use crate::equivalent::Equivalent;
-use crate::util::third;
-use crate::{Bucket, Entries, HashValue};
-
-pub use self::core::{Entry, OccupiedEntry, VacantEntry};
+use crate::util::{third, try_simplify_range};
+use crate::{Bucket, Entries, Equivalent, HashValue, TryReserveError};
/// A hash table where the iteration order of the key-value pairs is independent
/// of the hash values of the keys.
///
-/// The interface is closely compatible with the standard `HashMap`, but also
-/// has additional features.
+/// The interface is closely compatible with the standard
+/// [`HashMap`][std::collections::HashMap],
+/// but also has additional features.
///
/// # Order
///
@@ -41,7 +55,8 @@ pub use self::core::{Entry, OccupiedEntry, VacantEntry};
/// All iterators traverse the map in *the order*.
///
/// The insertion order is preserved, with **notable exceptions** like the
-/// `.remove()` or `.swap_remove()` methods. Methods such as `.sort_by()` of
+/// [`.remove()`][Self::remove] or [`.swap_remove()`][Self::swap_remove] methods.
+/// Methods such as [`.sort_by()`][Self::sort_by] of
/// course result in a new order, depending on the sorting order.
///
/// # Indices
@@ -67,12 +82,12 @@ pub use self::core::{Entry, OccupiedEntry, VacantEntry};
/// assert_eq!(letters[&'u'], 1);
/// assert_eq!(letters.get(&'y'), None);
/// ```
-#[cfg(has_std)]
+#[cfg(feature = "std")]
pub struct IndexMap<K, V, S = RandomState> {
pub(crate) core: IndexMapCore<K, V>,
hash_builder: S,
}
-#[cfg(not(has_std))]
+#[cfg(not(feature = "std"))]
pub struct IndexMap<K, V, S> {
pub(crate) core: IndexMapCore<K, V>,
hash_builder: S,
@@ -128,19 +143,22 @@ where
K: fmt::Debug,
V: fmt::Debug,
{
+ #[cfg(not(feature = "test_debug"))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- if cfg!(not(feature = "test_debug")) {
- f.debug_map().entries(self.iter()).finish()
- } else {
- // Let the inner `IndexMapCore` print all of its details
- f.debug_struct("IndexMap")
- .field("core", &self.core)
- .finish()
- }
+ f.debug_map().entries(self.iter()).finish()
+ }
+
+ #[cfg(feature = "test_debug")]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Let the inner `IndexMapCore` print all of its details
+ f.debug_struct("IndexMap")
+ .field("core", &self.core)
+ .finish()
}
}
-#[cfg(has_std)]
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<K, V> IndexMap<K, V> {
/// Create a new map. (Does not allocate.)
#[inline]
@@ -186,6 +204,11 @@ impl<K, V, S> IndexMap<K, V, S> {
}
}
+ /// Return the number of elements the map can hold without reallocating.
+ ///
+ /// This number is a lower bound; the map might be able to hold more,
+ /// but is guaranteed to be able to hold at least this many.
+ ///
/// Computes in **O(1)** time.
pub fn capacity(&self) -> usize {
self.core.capacity()
@@ -214,52 +237,38 @@ impl<K, V, S> IndexMap<K, V, S> {
/// Return an iterator over the key-value pairs of the map, in their order
pub fn iter(&self) -> Iter<'_, K, V> {
- Iter {
- iter: self.as_entries().iter(),
- }
+ Iter::new(self.as_entries())
}
/// Return an iterator over the key-value pairs of the map, in their order
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
- IterMut {
- iter: self.as_entries_mut().iter_mut(),
- }
+ IterMut::new(self.as_entries_mut())
}
/// Return an iterator over the keys of the map, in their order
pub fn keys(&self) -> Keys<'_, K, V> {
- Keys {
- iter: self.as_entries().iter(),
- }
+ Keys::new(self.as_entries())
}
/// Return an owning iterator over the keys of the map, in their order
pub fn into_keys(self) -> IntoKeys<K, V> {
- IntoKeys {
- iter: self.into_entries().into_iter(),
- }
+ IntoKeys::new(self.into_entries())
}
/// Return an iterator over the values of the map, in their order
pub fn values(&self) -> Values<'_, K, V> {
- Values {
- iter: self.as_entries().iter(),
- }
+ Values::new(self.as_entries())
}
/// Return an iterator over mutable references to the values of the map,
/// in their order
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
- ValuesMut {
- iter: self.as_entries_mut().iter_mut(),
- }
+ ValuesMut::new(self.as_entries_mut())
}
/// Return an owning iterator over the values of the map, in their order
pub fn into_values(self) -> IntoValues<K, V> {
- IntoValues {
- iter: self.into_entries().into_iter(),
- }
+ IntoValues::new(self.into_entries())
}
/// Remove all key-value pairs in the map, while preserving its capacity.
@@ -279,7 +288,7 @@ impl<K, V, S> IndexMap<K, V, S> {
/// Clears the `IndexMap` in the given index range, returning those
/// key-value pairs as a drain iterator.
///
- /// The range may be any type that implements `RangeBounds<usize>`,
+ /// The range may be any type that implements [`RangeBounds<usize>`],
/// including all of the `std::ops::Range*` types, or even a tuple pair of
/// `Bound` start and end values. To drain the map entirely, use `RangeFull`
/// like `map.drain(..)`.
@@ -293,9 +302,7 @@ impl<K, V, S> IndexMap<K, V, S> {
where
R: RangeBounds<usize>,
{
- Drain {
- iter: self.core.drain(range),
- }
+ Drain::new(self.core.drain(range))
}
/// Splits the collection into two at the given index.
@@ -314,13 +321,7 @@ impl<K, V, S> IndexMap<K, V, S> {
hash_builder: self.hash_builder.clone(),
}
}
-}
-impl<K, V, S> IndexMap<K, V, S>
-where
- K: Hash + Eq,
- S: BuildHasher,
-{
/// Reserve capacity for `additional` more key-value pairs.
///
/// Computes in **O(n)** time.
@@ -328,6 +329,37 @@ where
self.core.reserve(additional);
}
+ /// Reserve capacity for `additional` more key-value pairs, without over-allocating.
+ ///
+ /// Unlike `reserve`, this does not deliberately over-allocate the entry capacity to avoid
+ /// frequent re-allocations. However, the underlying data structures may still have internal
+ /// capacity requirements, and the allocator itself may give more space than requested, so this
+ /// cannot be relied upon to be precisely minimal.
+ ///
+ /// Computes in **O(n)** time.
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.core.reserve_exact(additional);
+ }
+
+ /// Try to reserve capacity for `additional` more key-value pairs.
+ ///
+ /// Computes in **O(n)** time.
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.core.try_reserve(additional)
+ }
+
+ /// Try to reserve capacity for `additional` more key-value pairs, without over-allocating.
+ ///
+ /// Unlike `try_reserve`, this does not deliberately over-allocate the entry capacity to avoid
+ /// frequent re-allocations. However, the underlying data structures may still have internal
+ /// capacity requirements, and the allocator itself may give more space than requested, so this
+ /// cannot be relied upon to be precisely minimal.
+ ///
+ /// Computes in **O(n)** time.
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.core.try_reserve_exact(additional)
+ }
+
/// Shrink the capacity of the map as much as possible.
///
/// Computes in **O(n)** time.
@@ -341,26 +373,27 @@ where
pub fn shrink_to(&mut self, min_capacity: usize) {
self.core.shrink_to(min_capacity);
}
+}
- fn hash<Q: ?Sized + Hash>(&self, key: &Q) -> HashValue {
- let mut h = self.hash_builder.build_hasher();
- key.hash(&mut h);
- HashValue(h.finish() as usize)
- }
-
+impl<K, V, S> IndexMap<K, V, S>
+where
+ K: Hash + Eq,
+ S: BuildHasher,
+{
/// Insert a key-value pair in the map.
///
/// If an equivalent key already exists in the map: the key remains and
/// retains in its place in the order, its corresponding value is updated
- /// with `value` and the older value is returned inside `Some(_)`.
+ /// with `value`, and the older value is returned inside `Some(_)`.
///
/// If no equivalent key existed in the map: the new key-value pair is
/// inserted, last in order, and `None` is returned.
///
/// Computes in **O(1)** time (amortized average).
///
- /// See also [`entry`](#method.entry) if you you want to insert *or* modify
- /// or if you need to get the index of the corresponding key-value pair.
+ /// See also [`entry`][Self::entry] if you want to insert *or* modify,
+ /// or [`insert_full`][Self::insert_full] if you need to get the index of
+ /// the corresponding key-value pair.
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
self.insert_full(key, value).1
}
@@ -369,20 +402,77 @@ where
///
/// If an equivalent key already exists in the map: the key remains and
/// retains in its place in the order, its corresponding value is updated
- /// with `value` and the older value is returned inside `(index, Some(_))`.
+ /// with `value`, and the older value is returned inside `(index, Some(_))`.
///
/// If no equivalent key existed in the map: the new key-value pair is
/// inserted, last in order, and `(index, None)` is returned.
///
/// Computes in **O(1)** time (amortized average).
///
- /// See also [`entry`](#method.entry) if you you want to insert *or* modify
- /// or if you need to get the index of the corresponding key-value pair.
+ /// See also [`entry`][Self::entry] if you want to insert *or* modify.
pub fn insert_full(&mut self, key: K, value: V) -> (usize, Option<V>) {
let hash = self.hash(&key);
self.core.insert_full(hash, key, value)
}
+ /// Insert a key-value pair in the map at its ordered position among sorted keys.
+ ///
+ /// This is equivalent to finding the position with
+ /// [`binary_search_keys`][Self::binary_search_keys], then either updating
+ /// it or calling [`shift_insert`][Self::shift_insert] for a new key.
+ ///
+ /// If the sorted key is found in the map, its corresponding value is
+ /// updated with `value`, and the older value is returned inside
+ /// `(index, Some(_))`. Otherwise, the new key-value pair is inserted at
+ /// the sorted position, and `(index, None)` is returned.
+ ///
+ /// If the existing keys are **not** already sorted, then the insertion
+ /// index is unspecified (like [`slice::binary_search`]), but the key-value
+ /// pair is moved to or inserted at that position regardless.
+ ///
+ /// Computes in **O(n)** time (average). Instead of repeating calls to
+ /// `insert_sorted`, it may be faster to call batched [`insert`][Self::insert]
+ /// or [`extend`][Self::extend] and only call [`sort_keys`][Self::sort_keys]
+ /// or [`sort_unstable_keys`][Self::sort_unstable_keys] once.
+ pub fn insert_sorted(&mut self, key: K, value: V) -> (usize, Option<V>)
+ where
+ K: Ord,
+ {
+ match self.binary_search_keys(&key) {
+ Ok(i) => (i, Some(mem::replace(&mut self[i], value))),
+ Err(i) => (i, self.shift_insert(i, key, value)),
+ }
+ }
+
+ /// Insert a key-value pair in the map at the given index.
+ ///
+ /// If an equivalent key already exists in the map: the key remains and
+ /// is moved to the new position in the map, its corresponding value is updated
+ /// with `value`, and the older value is returned inside `Some(_)`.
+ ///
+ /// If no equivalent key existed in the map: the new key-value pair is
+ /// inserted at the given index, and `None` is returned.
+ ///
+ /// ***Panics*** if `index` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ ///
+ /// See also [`entry`][Self::entry] if you want to insert *or* modify,
+ /// perhaps only using the index for new entries with [`VacantEntry::shift_insert`].
+ pub fn shift_insert(&mut self, index: usize, key: K, value: V) -> Option<V> {
+ match self.entry(key) {
+ Entry::Occupied(mut entry) => {
+ let old = mem::replace(entry.get_mut(), value);
+ entry.move_index(index);
+ Some(old)
+ }
+ Entry::Vacant(entry) => {
+ entry.shift_insert(index, value);
+ None
+ }
+ }
+ }
+
/// Get the given key’s corresponding entry in the map for insertion and/or
/// in-place manipulation.
///
@@ -392,12 +482,61 @@ where
self.core.entry(hash, key)
}
+ /// Creates a splicing iterator that replaces the specified range in the map
+ /// with the given `replace_with` key-value iterator and yields the removed
+ /// items. `replace_with` does not need to be the same length as `range`.
+ ///
+ /// The `range` is removed even if the iterator is not consumed until the
+ /// end. It is unspecified how many elements are removed from the map if the
+ /// `Splice` value is leaked.
+ ///
+ /// The input iterator `replace_with` is only consumed when the `Splice`
+ /// value is dropped. If a key from the iterator matches an existing entry
+ /// in the map (outside of `range`), then the value will be updated in that
+ /// position. Otherwise, the new key-value pair will be inserted in the
+ /// replaced `range`.
+ ///
+ /// ***Panics*** if the starting point is greater than the end point or if
+ /// the end point is greater than the length of the map.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use indexmap::IndexMap;
+ ///
+ /// let mut map = IndexMap::from([(0, '_'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]);
+ /// let new = [(5, 'E'), (4, 'D'), (3, 'C'), (2, 'B'), (1, 'A')];
+ /// let removed: Vec<_> = map.splice(2..4, new).collect();
+ ///
+ /// // 1 and 4 got new values, while 5, 3, and 2 were newly inserted.
+ /// assert!(map.into_iter().eq([(0, '_'), (1, 'A'), (5, 'E'), (3, 'C'), (2, 'B'), (4, 'D')]));
+ /// assert_eq!(removed, &[(2, 'b'), (3, 'c')]);
+ /// ```
+ pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, K, V, S>
+ where
+ R: RangeBounds<usize>,
+ I: IntoIterator<Item = (K, V)>,
+ {
+ Splice::new(self, range, replace_with.into_iter())
+ }
+}
+
+impl<K, V, S> IndexMap<K, V, S>
+where
+ S: BuildHasher,
+{
+ pub(crate) fn hash<Q: ?Sized + Hash>(&self, key: &Q) -> HashValue {
+ let mut h = self.hash_builder.build_hasher();
+ key.hash(&mut h);
+ HashValue(h.finish() as usize)
+ }
+
/// Return `true` if an equivalent to `key` exists in the map.
///
/// Computes in **O(1)** time (average).
- pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
+ pub fn contains_key<Q>(&self, key: &Q) -> bool
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
self.get_index_of(key).is_some()
}
@@ -406,9 +545,9 @@ where
/// else `None`.
///
/// Computes in **O(1)** time (average).
- pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
+ pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
if let Some(i) = self.get_index_of(key) {
let entry = &self.as_entries()[i];
@@ -422,9 +561,9 @@ where
/// if it is present, else `None`.
///
/// Computes in **O(1)** time (average).
- pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
+ pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
if let Some(i) = self.get_index_of(key) {
let entry = &self.as_entries()[i];
@@ -435,9 +574,9 @@ where
}
/// Return item index, key and value
- pub fn get_full<Q: ?Sized>(&self, key: &Q) -> Option<(usize, &K, &V)>
+ pub fn get_full<Q>(&self, key: &Q) -> Option<(usize, &K, &V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
if let Some(i) = self.get_index_of(key) {
let entry = &self.as_entries()[i];
@@ -450,21 +589,23 @@ where
/// Return item index, if it exists in the map
///
/// Computes in **O(1)** time (average).
- pub fn get_index_of<Q: ?Sized>(&self, key: &Q) -> Option<usize>
+ pub fn get_index_of<Q>(&self, key: &Q) -> Option<usize>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
- if self.is_empty() {
- None
- } else {
- let hash = self.hash(key);
- self.core.get_index_of(hash, key)
+ match self.as_entries() {
+ [] => None,
+ [x] => key.equivalent(&x.key).then_some(0),
+ _ => {
+ let hash = self.hash(key);
+ self.core.get_index_of(hash, key)
+ }
}
}
- pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
+ pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
if let Some(i) = self.get_index_of(key) {
let entry = &mut self.as_entries_mut()[i];
@@ -474,9 +615,9 @@ where
}
}
- pub fn get_full_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<(usize, &K, &mut V)>
+ pub fn get_full_mut<Q>(&mut self, key: &Q) -> Option<(usize, &K, &mut V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
if let Some(i) = self.get_index_of(key) {
let entry = &mut self.as_entries_mut()[i];
@@ -486,46 +627,33 @@ where
}
}
- pub(crate) fn get_full_mut2_impl<Q: ?Sized>(
- &mut self,
- key: &Q,
- ) -> Option<(usize, &mut K, &mut V)>
- where
- Q: Hash + Equivalent<K>,
- {
- if let Some(i) = self.get_index_of(key) {
- let entry = &mut self.as_entries_mut()[i];
- Some((i, &mut entry.key, &mut entry.value))
- } else {
- None
- }
- }
-
/// Remove the key-value pair equivalent to `key` and return
/// its value.
///
- /// **NOTE:** This is equivalent to `.swap_remove(key)`, if you need to
- /// preserve the order of the keys in the map, use `.shift_remove(key)`
- /// instead.
- ///
- /// Computes in **O(1)** time (average).
- pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
+ /// **NOTE:** This is equivalent to [`.swap_remove(key)`][Self::swap_remove], replacing this
+ /// entry's position with the last element, and it is deprecated in favor of calling that
+ /// explicitly. If you need to preserve the relative order of the keys in the map, use
+ /// [`.shift_remove(key)`][Self::shift_remove] instead.
+ #[deprecated(note = "`remove` disrupts the map order -- \
+ use `swap_remove` or `shift_remove` for explicit behavior.")]
+ pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
self.swap_remove(key)
}
/// Remove and return the key-value pair equivalent to `key`.
///
- /// **NOTE:** This is equivalent to `.swap_remove_entry(key)`, if you need to
- /// preserve the order of the keys in the map, use `.shift_remove_entry(key)`
- /// instead.
- ///
- /// Computes in **O(1)** time (average).
- pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
+ /// **NOTE:** This is equivalent to [`.swap_remove_entry(key)`][Self::swap_remove_entry],
+ /// replacing this entry's position with the last element, and it is deprecated in favor of
+ /// calling that explicitly. If you need to preserve the relative order of the keys in the map,
+ /// use [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead.
+ #[deprecated(note = "`remove_entry` disrupts the map order -- \
+ use `swap_remove_entry` or `shift_remove_entry` for explicit behavior.")]
+ pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
self.swap_remove_entry(key)
}
@@ -533,32 +661,32 @@ where
/// Remove the key-value pair equivalent to `key` and return
/// its value.
///
- /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the pair is removed by swapping it with the
/// last element of the map and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
/// Return `None` if `key` is not in map.
///
/// Computes in **O(1)** time (average).
- pub fn swap_remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
+ pub fn swap_remove<Q>(&mut self, key: &Q) -> Option<V>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
self.swap_remove_full(key).map(third)
}
/// Remove and return the key-value pair equivalent to `key`.
///
- /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the pair is removed by swapping it with the
/// last element of the map and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
/// Return `None` if `key` is not in map.
///
/// Computes in **O(1)** time (average).
- pub fn swap_remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
+ pub fn swap_remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
match self.swap_remove_full(key) {
Some((_, key, value)) => Some((key, value)),
@@ -569,53 +697,59 @@ where
/// Remove the key-value pair equivalent to `key` and return it and
/// the index it had.
///
- /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the pair is removed by swapping it with the
/// last element of the map and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
/// Return `None` if `key` is not in map.
///
/// Computes in **O(1)** time (average).
- pub fn swap_remove_full<Q: ?Sized>(&mut self, key: &Q) -> Option<(usize, K, V)>
+ pub fn swap_remove_full<Q>(&mut self, key: &Q) -> Option<(usize, K, V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
- if self.is_empty() {
- return None;
+ match self.as_entries() {
+ [x] if key.equivalent(&x.key) => {
+ let (k, v) = self.core.pop()?;
+ Some((0, k, v))
+ }
+ [_] | [] => None,
+ _ => {
+ let hash = self.hash(key);
+ self.core.swap_remove_full(hash, key)
+ }
}
- let hash = self.hash(key);
- self.core.swap_remove_full(hash, key)
}
/// Remove the key-value pair equivalent to `key` and return
/// its value.
///
- /// Like `Vec::remove`, the pair is removed by shifting all of the
+ /// Like [`Vec::remove`], the pair is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
/// Return `None` if `key` is not in map.
///
/// Computes in **O(n)** time (average).
- pub fn shift_remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
+ pub fn shift_remove<Q>(&mut self, key: &Q) -> Option<V>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
self.shift_remove_full(key).map(third)
}
/// Remove and return the key-value pair equivalent to `key`.
///
- /// Like `Vec::remove`, the pair is removed by shifting all of the
+ /// Like [`Vec::remove`], the pair is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
/// Return `None` if `key` is not in map.
///
/// Computes in **O(n)** time (average).
- pub fn shift_remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
+ pub fn shift_remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
match self.shift_remove_full(key) {
Some((_, key, value)) => Some((key, value)),
@@ -626,24 +760,32 @@ where
/// Remove the key-value pair equivalent to `key` and return it and
/// the index it had.
///
- /// Like `Vec::remove`, the pair is removed by shifting all of the
+ /// Like [`Vec::remove`], the pair is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
/// Return `None` if `key` is not in map.
///
/// Computes in **O(n)** time (average).
- pub fn shift_remove_full<Q: ?Sized>(&mut self, key: &Q) -> Option<(usize, K, V)>
+ pub fn shift_remove_full<Q>(&mut self, key: &Q) -> Option<(usize, K, V)>
where
- Q: Hash + Equivalent<K>,
+ Q: ?Sized + Hash + Equivalent<K>,
{
- if self.is_empty() {
- return None;
+ match self.as_entries() {
+ [x] if key.equivalent(&x.key) => {
+ let (k, v) = self.core.pop()?;
+ Some((0, k, v))
+ }
+ [_] | [] => None,
+ _ => {
+ let hash = self.hash(key);
+ self.core.shift_remove_full(hash, key)
+ }
}
- let hash = self.hash(key);
- self.core.shift_remove_full(hash, key)
}
+}
+impl<K, V, S> IndexMap<K, V, S> {
/// Remove the last key-value pair
///
/// This preserves the order of the remaining elements.
@@ -667,15 +809,12 @@ where
self.core.retain_in_order(move |k, v| keep(k, v));
}
- pub(crate) fn retain_mut<F>(&mut self, keep: F)
- where
- F: FnMut(&mut K, &mut V) -> bool,
- {
- self.core.retain_in_order(keep);
- }
-
/// Sort the map’s key-value pairs by the default ordering of the keys.
///
+ /// This is a stable sort -- but equivalent keys should not normally coexist in
+ /// a map at all, so [`sort_unstable_keys`][Self::sort_unstable_keys] is preferred
+ /// because it is generally faster and doesn't allocate auxiliary memory.
+ ///
/// See [`sort_by`](Self::sort_by) for details.
pub fn sort_keys(&mut self)
where
@@ -713,9 +852,7 @@ where
{
let mut entries = self.into_entries();
entries.sort_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value));
- IntoIter {
- iter: entries.into_iter(),
- }
+ IntoIter::new(entries)
}
/// Sort the map's key-value pairs by the default ordering of the keys, but
@@ -759,9 +896,82 @@ where
{
let mut entries = self.into_entries();
entries.sort_unstable_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value));
- IntoIter {
- iter: entries.into_iter(),
- }
+ IntoIter::new(entries)
+ }
+
+ /// Sort the map’s key-value pairs in place using a sort-key extraction function.
+ ///
+ /// During sorting, the function is called at most once per entry, by using temporary storage
+ /// to remember the results of its evaluation. The order of calls to the function is
+ /// unspecified and may change between versions of `indexmap` or the standard library.
+ ///
+ /// Computes in **O(m n + n log n + c)** time () and **O(n)** space, where the function is
+ /// **O(m)**, *n* is the length of the map, and *c* the capacity. The sort is stable.
+ pub fn sort_by_cached_key<T, F>(&mut self, mut sort_key: F)
+ where
+ T: Ord,
+ F: FnMut(&K, &V) -> T,
+ {
+ self.with_entries(move |entries| {
+ entries.sort_by_cached_key(move |a| sort_key(&a.key, &a.value));
+ });
+ }
+
+ /// Search over a sorted map for a key.
+ ///
+ /// Returns the position where that key is present, or the position where it can be inserted to
+ /// maintain the sort. See [`slice::binary_search`] for more details.
+ ///
+ /// Computes in **O(log(n))** time, which is notably less scalable than looking the key up
+ /// using [`get_index_of`][IndexMap::get_index_of], but this can also position missing keys.
+ pub fn binary_search_keys(&self, x: &K) -> Result<usize, usize>
+ where
+ K: Ord,
+ {
+ self.as_slice().binary_search_keys(x)
+ }
+
+ /// Search over a sorted map with a comparator function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a K, &'a V) -> Ordering,
+ {
+ self.as_slice().binary_search_by(f)
+ }
+
+ /// Search over a sorted map with an extraction function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by_key`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a K, &'a V) -> B,
+ B: Ord,
+ {
+ self.as_slice().binary_search_by_key(b, f)
+ }
+
+ /// Returns the index of the partition point of a sorted map according to the given predicate
+ /// (the index of the first element of the second partition).
+ ///
+ /// See [`slice::partition_point`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[must_use]
+ pub fn partition_point<P>(&self, pred: P) -> usize
+ where
+ P: FnMut(&K, &V) -> bool,
+ {
+ self.as_slice().partition_point(pred)
}
/// Reverses the order of the map’s key-value pairs in place.
@@ -770,9 +980,28 @@ where
pub fn reverse(&mut self) {
self.core.reverse()
}
-}
-impl<K, V, S> IndexMap<K, V, S> {
+ /// Returns a slice of all the key-value pairs in the map.
+ ///
+ /// Computes in **O(1)** time.
+ pub fn as_slice(&self) -> &Slice<K, V> {
+ Slice::from_slice(self.as_entries())
+ }
+
+ /// Returns a mutable slice of all the key-value pairs in the map.
+ ///
+ /// Computes in **O(1)** time.
+ pub fn as_mut_slice(&mut self) -> &mut Slice<K, V> {
+ Slice::from_mut_slice(self.as_entries_mut())
+ }
+
+ /// Converts into a boxed slice of all the key-value pairs in the map.
+ ///
+ /// Note that this will drop the inner hash table and any excess capacity.
+ pub fn into_boxed_slice(self) -> Box<Slice<K, V>> {
+ Slice::from_boxed(self.into_entries().into_boxed_slice())
+ }
+
/// Get a key-value pair by index
///
/// Valid indices are *0 <= index < self.len()*
@@ -787,8 +1016,42 @@ impl<K, V, S> IndexMap<K, V, S> {
/// Valid indices are *0 <= index < self.len()*
///
/// Computes in **O(1)** time.
- pub fn get_index_mut(&mut self, index: usize) -> Option<(&mut K, &mut V)> {
- self.as_entries_mut().get_mut(index).map(Bucket::muts)
+ pub fn get_index_mut(&mut self, index: usize) -> Option<(&K, &mut V)> {
+ self.as_entries_mut().get_mut(index).map(Bucket::ref_mut)
+ }
+
+ /// Get an entry in the map by index for in-place manipulation.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ ///
+ /// Computes in **O(1)** time.
+ pub fn get_index_entry(&mut self, index: usize) -> Option<IndexedEntry<'_, K, V>> {
+ if index >= self.len() {
+ return None;
+ }
+ Some(IndexedEntry::new(&mut self.core, index))
+ }
+
+ /// Returns a slice of key-value pairs in the given range of indices.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ ///
+ /// Computes in **O(1)** time.
+ pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Slice<K, V>> {
+ let entries = self.as_entries();
+ let range = try_simplify_range(range, entries.len())?;
+ entries.get(range).map(Slice::from_slice)
+ }
+
+ /// Returns a mutable slice of key-value pairs in the given range of indices.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ ///
+ /// Computes in **O(1)** time.
+ pub fn get_range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Slice<K, V>> {
+ let entries = self.as_entries_mut();
+ let range = try_simplify_range(range, entries.len())?;
+ entries.get_mut(range).map(Slice::from_mut_slice)
}
/// Get the first key-value pair
@@ -823,7 +1086,7 @@ impl<K, V, S> IndexMap<K, V, S> {
///
/// Valid indices are *0 <= index < self.len()*
///
- /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the pair is removed by swapping it with the
/// last element of the map and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
@@ -836,7 +1099,7 @@ impl<K, V, S> IndexMap<K, V, S> {
///
/// Valid indices are *0 <= index < self.len()*
///
- /// Like `Vec::remove`, the pair is removed by shifting all of the
+ /// Like [`Vec::remove`], the pair is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
@@ -861,386 +1124,14 @@ impl<K, V, S> IndexMap<K, V, S> {
/// Swaps the position of two key-value pairs in the map.
///
/// ***Panics*** if `a` or `b` are out of bounds.
+ ///
+ /// Computes in **O(1)** time (average).
pub fn swap_indices(&mut self, a: usize, b: usize) {
self.core.swap_indices(a, b)
}
}
-/// An iterator over the keys of a `IndexMap`.
-///
-/// This `struct` is created by the [`keys`] method on [`IndexMap`]. See its
-/// documentation for more.
-///
-/// [`keys`]: struct.IndexMap.html#method.keys
-/// [`IndexMap`]: struct.IndexMap.html
-pub struct Keys<'a, K, V> {
- iter: SliceIter<'a, Bucket<K, V>>,
-}
-
-impl<'a, K, V> Iterator for Keys<'a, K, V> {
- type Item = &'a K;
-
- iterator_methods!(Bucket::key_ref);
-}
-
-impl<K, V> DoubleEndedIterator for Keys<'_, K, V> {
- double_ended_iterator_methods!(Bucket::key_ref);
-}
-
-impl<K, V> ExactSizeIterator for Keys<'_, K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for Keys<'_, K, V> {}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Keys<'_, K, V> {
- fn clone(&self) -> Self {
- Keys {
- iter: self.iter.clone(),
- }
- }
-}
-
-impl<K: fmt::Debug, V> fmt::Debug for Keys<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-/// An owning iterator over the keys of a `IndexMap`.
-///
-/// This `struct` is created by the [`into_keys`] method on [`IndexMap`].
-/// See its documentation for more.
-///
-/// [`IndexMap`]: struct.IndexMap.html
-/// [`into_keys`]: struct.IndexMap.html#method.into_keys
-pub struct IntoKeys<K, V> {
- iter: vec::IntoIter<Bucket<K, V>>,
-}
-
-impl<K, V> Iterator for IntoKeys<K, V> {
- type Item = K;
-
- iterator_methods!(Bucket::key);
-}
-
-impl<K, V> DoubleEndedIterator for IntoKeys<K, V> {
- double_ended_iterator_methods!(Bucket::key);
-}
-
-impl<K, V> ExactSizeIterator for IntoKeys<K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for IntoKeys<K, V> {}
-
-impl<K: fmt::Debug, V> fmt::Debug for IntoKeys<K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::key_ref);
- f.debug_list().entries(iter).finish()
- }
-}
-
-/// An iterator over the values of a `IndexMap`.
-///
-/// This `struct` is created by the [`values`] method on [`IndexMap`]. See its
-/// documentation for more.
-///
-/// [`values`]: struct.IndexMap.html#method.values
-/// [`IndexMap`]: struct.IndexMap.html
-pub struct Values<'a, K, V> {
- iter: SliceIter<'a, Bucket<K, V>>,
-}
-
-impl<'a, K, V> Iterator for Values<'a, K, V> {
- type Item = &'a V;
-
- iterator_methods!(Bucket::value_ref);
-}
-
-impl<K, V> DoubleEndedIterator for Values<'_, K, V> {
- double_ended_iterator_methods!(Bucket::value_ref);
-}
-
-impl<K, V> ExactSizeIterator for Values<'_, K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for Values<'_, K, V> {}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Values<'_, K, V> {
- fn clone(&self) -> Self {
- Values {
- iter: self.iter.clone(),
- }
- }
-}
-
-impl<K, V: fmt::Debug> fmt::Debug for Values<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-/// A mutable iterator over the values of a `IndexMap`.
-///
-/// This `struct` is created by the [`values_mut`] method on [`IndexMap`]. See its
-/// documentation for more.
-///
-/// [`values_mut`]: struct.IndexMap.html#method.values_mut
-/// [`IndexMap`]: struct.IndexMap.html
-pub struct ValuesMut<'a, K, V> {
- iter: SliceIterMut<'a, Bucket<K, V>>,
-}
-
-impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
- type Item = &'a mut V;
-
- iterator_methods!(Bucket::value_mut);
-}
-
-impl<K, V> DoubleEndedIterator for ValuesMut<'_, K, V> {
- double_ended_iterator_methods!(Bucket::value_mut);
-}
-
-impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
-
-impl<K, V: fmt::Debug> fmt::Debug for ValuesMut<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::value_ref);
- f.debug_list().entries(iter).finish()
- }
-}
-
-/// An owning iterator over the values of a `IndexMap`.
-///
-/// This `struct` is created by the [`into_values`] method on [`IndexMap`].
-/// See its documentation for more.
-///
-/// [`IndexMap`]: struct.IndexMap.html
-/// [`into_values`]: struct.IndexMap.html#method.into_values
-pub struct IntoValues<K, V> {
- iter: vec::IntoIter<Bucket<K, V>>,
-}
-
-impl<K, V> Iterator for IntoValues<K, V> {
- type Item = V;
-
- iterator_methods!(Bucket::value);
-}
-
-impl<K, V> DoubleEndedIterator for IntoValues<K, V> {
- double_ended_iterator_methods!(Bucket::value);
-}
-
-impl<K, V> ExactSizeIterator for IntoValues<K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for IntoValues<K, V> {}
-
-impl<K, V: fmt::Debug> fmt::Debug for IntoValues<K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::value_ref);
- f.debug_list().entries(iter).finish()
- }
-}
-
-/// An iterator over the entries of a `IndexMap`.
-///
-/// This `struct` is created by the [`iter`] method on [`IndexMap`]. See its
-/// documentation for more.
-///
-/// [`iter`]: struct.IndexMap.html#method.iter
-/// [`IndexMap`]: struct.IndexMap.html
-pub struct Iter<'a, K, V> {
- iter: SliceIter<'a, Bucket<K, V>>,
-}
-
-impl<'a, K, V> Iterator for Iter<'a, K, V> {
- type Item = (&'a K, &'a V);
-
- iterator_methods!(Bucket::refs);
-}
-
-impl<K, V> DoubleEndedIterator for Iter<'_, K, V> {
- double_ended_iterator_methods!(Bucket::refs);
-}
-
-impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for Iter<'_, K, V> {}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Iter<'_, K, V> {
- fn clone(&self) -> Self {
- Iter {
- iter: self.iter.clone(),
- }
- }
-}
-
-impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-/// A mutable iterator over the entries of a `IndexMap`.
-///
-/// This `struct` is created by the [`iter_mut`] method on [`IndexMap`]. See its
-/// documentation for more.
-///
-/// [`iter_mut`]: struct.IndexMap.html#method.iter_mut
-/// [`IndexMap`]: struct.IndexMap.html
-pub struct IterMut<'a, K, V> {
- iter: SliceIterMut<'a, Bucket<K, V>>,
-}
-
-impl<'a, K, V> Iterator for IterMut<'a, K, V> {
- type Item = (&'a K, &'a mut V);
-
- iterator_methods!(Bucket::ref_mut);
-}
-
-impl<K, V> DoubleEndedIterator for IterMut<'_, K, V> {
- double_ended_iterator_methods!(Bucket::ref_mut);
-}
-
-impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for IterMut<'_, K, V> {}
-
-impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::refs);
- f.debug_list().entries(iter).finish()
- }
-}
-
-/// An owning iterator over the entries of a `IndexMap`.
-///
-/// This `struct` is created by the [`into_iter`] method on [`IndexMap`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
-///
-/// [`into_iter`]: struct.IndexMap.html#method.into_iter
-/// [`IndexMap`]: struct.IndexMap.html
-pub struct IntoIter<K, V> {
- iter: vec::IntoIter<Bucket<K, V>>,
-}
-
-impl<K, V> Iterator for IntoIter<K, V> {
- type Item = (K, V);
-
- iterator_methods!(Bucket::key_value);
-}
-
-impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
- double_ended_iterator_methods!(Bucket::key_value);
-}
-
-impl<K, V> ExactSizeIterator for IntoIter<K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for IntoIter<K, V> {}
-
-impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::refs);
- f.debug_list().entries(iter).finish()
- }
-}
-
-/// A draining iterator over the entries of a `IndexMap`.
-///
-/// This `struct` is created by the [`drain`] method on [`IndexMap`]. See its
-/// documentation for more.
-///
-/// [`drain`]: struct.IndexMap.html#method.drain
-/// [`IndexMap`]: struct.IndexMap.html
-pub struct Drain<'a, K, V> {
- pub(crate) iter: vec::Drain<'a, Bucket<K, V>>,
-}
-
-impl<K, V> Iterator for Drain<'_, K, V> {
- type Item = (K, V);
-
- iterator_methods!(Bucket::key_value);
-}
-
-impl<K, V> DoubleEndedIterator for Drain<'_, K, V> {
- double_ended_iterator_methods!(Bucket::key_value);
-}
-
-impl<K, V> ExactSizeIterator for Drain<'_, K, V> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<K, V> FusedIterator for Drain<'_, K, V> {}
-
-impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Drain<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::refs);
- f.debug_list().entries(iter).finish()
- }
-}
-
-impl<'a, K, V, S> IntoIterator for &'a IndexMap<K, V, S> {
- type Item = (&'a K, &'a V);
- type IntoIter = Iter<'a, K, V>;
- fn into_iter(self) -> Self::IntoIter {
- self.iter()
- }
-}
-
-impl<'a, K, V, S> IntoIterator for &'a mut IndexMap<K, V, S> {
- type Item = (&'a K, &'a mut V);
- type IntoIter = IterMut<'a, K, V>;
- fn into_iter(self) -> Self::IntoIter {
- self.iter_mut()
- }
-}
-
-impl<K, V, S> IntoIterator for IndexMap<K, V, S> {
- type Item = (K, V);
- type IntoIter = IntoIter<K, V>;
- fn into_iter(self) -> Self::IntoIter {
- IntoIter {
- iter: self.into_entries().into_iter(),
- }
- }
-}
-
-/// Access `IndexMap` values corresponding to a key.
+/// Access [`IndexMap`] values corresponding to a key.
///
/// # Examples
///
@@ -1265,7 +1156,6 @@ impl<K, V, S> IntoIterator for IndexMap<K, V, S> {
impl<K, V, Q: ?Sized, S> Index<&Q> for IndexMap<K, V, S>
where
Q: Hash + Equivalent<K>,
- K: Hash + Eq,
S: BuildHasher,
{
type Output = V;
@@ -1278,7 +1168,7 @@ where
}
}
-/// Access `IndexMap` values corresponding to a key.
+/// Access [`IndexMap`] values corresponding to a key.
///
/// Mutable indexing allows changing / updating values of key-value
/// pairs that are already present.
@@ -1310,7 +1200,6 @@ where
impl<K, V, Q: ?Sized, S> IndexMut<&Q> for IndexMap<K, V, S>
where
Q: Hash + Equivalent<K>,
- K: Hash + Eq,
S: BuildHasher,
{
/// Returns a mutable reference to the value corresponding to the supplied `key`.
@@ -1321,7 +1210,11 @@ where
}
}
-/// Access `IndexMap` values at indexed positions.
+/// Access [`IndexMap`] values at indexed positions.
+///
+/// See [`Index<usize> for Keys`][keys] to access a map's keys instead.
+///
+/// [keys]: Keys#impl-Index<usize>-for-Keys<'a,+K,+V>
///
/// # Examples
///
@@ -1362,12 +1255,12 @@ impl<K, V, S> Index<usize> for IndexMap<K, V, S> {
}
}
-/// Access `IndexMap` values at indexed positions.
+/// Access [`IndexMap`] values at indexed positions.
///
/// Mutable indexing allows changing / updating indexed values
/// that are already present.
///
-/// You can **not** insert new values with index syntax, use `.insert()`.
+/// You can **not** insert new values with index syntax -- use [`.insert()`][IndexMap::insert].
///
/// # Examples
///
@@ -1411,7 +1304,7 @@ where
/// iterable.
///
/// `from_iter` uses the same logic as `extend`. See
- /// [`extend`](#method.extend) for more details.
+ /// [`extend`][IndexMap::extend] for more details.
fn from_iter<I: IntoIterator<Item = (K, V)>>(iterable: I) -> Self {
let iter = iterable.into_iter();
let (low, _) = iter.size_hint();
@@ -1421,7 +1314,8 @@ where
}
}
-#[cfg(has_std)]
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<K, V, const N: usize> From<[(K, V); N]> for IndexMap<K, V, RandomState>
where
K: Hash + Eq,
@@ -1447,7 +1341,7 @@ where
{
/// Extend the map with all key-value pairs in the iterable.
///
- /// This is equivalent to calling [`insert`](#method.insert) for each of
+ /// This is equivalent to calling [`insert`][IndexMap::insert] for each of
/// them in order, which means that for keys that already existed
/// in the map, their value is updated but it keeps the existing order.
///
@@ -1491,7 +1385,7 @@ impl<K, V, S> Default for IndexMap<K, V, S>
where
S: Default,
{
- /// Return an empty `IndexMap`
+ /// Return an empty [`IndexMap`]
fn default() -> Self {
Self::with_capacity_and_hasher(0, S::default())
}
@@ -1521,427 +1415,3 @@ where
S: BuildHasher,
{
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::string::String;
-
- #[test]
- fn it_works() {
- let mut map = IndexMap::new();
- assert_eq!(map.is_empty(), true);
- map.insert(1, ());
- map.insert(1, ());
- assert_eq!(map.len(), 1);
- assert!(map.get(&1).is_some());
- assert_eq!(map.is_empty(), false);
- }
-
- #[test]
- fn new() {
- let map = IndexMap::<String, String>::new();
- println!("{:?}", map);
- assert_eq!(map.capacity(), 0);
- assert_eq!(map.len(), 0);
- assert_eq!(map.is_empty(), true);
- }
-
- #[test]
- fn insert() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5];
- let not_present = [1, 3, 6, 9, 10];
- let mut map = IndexMap::with_capacity(insert.len());
-
- for (i, &elt) in insert.iter().enumerate() {
- assert_eq!(map.len(), i);
- map.insert(elt, elt);
- assert_eq!(map.len(), i + 1);
- assert_eq!(map.get(&elt), Some(&elt));
- assert_eq!(map[&elt], elt);
- }
- println!("{:?}", map);
-
- for &elt in &not_present {
- assert!(map.get(&elt).is_none());
- }
- }
-
- #[test]
- fn insert_full() {
- let insert = vec![9, 2, 7, 1, 4, 6, 13];
- let present = vec![1, 6, 2];
- let mut map = IndexMap::with_capacity(insert.len());
-
- for (i, &elt) in insert.iter().enumerate() {
- assert_eq!(map.len(), i);
- let (index, existing) = map.insert_full(elt, elt);
- assert_eq!(existing, None);
- assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0));
- assert_eq!(map.len(), i + 1);
- }
-
- let len = map.len();
- for &elt in &present {
- let (index, existing) = map.insert_full(elt, elt);
- assert_eq!(existing, Some(elt));
- assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0));
- assert_eq!(map.len(), len);
- }
- }
-
- #[test]
- fn insert_2() {
- let mut map = IndexMap::with_capacity(16);
-
- let mut keys = vec![];
- keys.extend(0..16);
- keys.extend(if cfg!(miri) { 32..64 } else { 128..267 });
-
- for &i in &keys {
- let old_map = map.clone();
- map.insert(i, ());
- for key in old_map.keys() {
- if map.get(key).is_none() {
- println!("old_map: {:?}", old_map);
- println!("map: {:?}", map);
- panic!("did not find {} in map", key);
- }
- }
- }
-
- for &i in &keys {
- assert!(map.get(&i).is_some(), "did not find {}", i);
- }
- }
-
- #[test]
- fn insert_order() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
- let mut map = IndexMap::new();
-
- for &elt in &insert {
- map.insert(elt, ());
- }
-
- assert_eq!(map.keys().count(), map.len());
- assert_eq!(map.keys().count(), insert.len());
- for (a, b) in insert.iter().zip(map.keys()) {
- assert_eq!(a, b);
- }
- for (i, k) in (0..insert.len()).zip(map.keys()) {
- assert_eq!(map.get_index(i).unwrap().0, k);
- }
- }
-
- #[test]
- fn grow() {
- let insert = [0, 4, 2, 12, 8, 7, 11];
- let not_present = [1, 3, 6, 9, 10];
- let mut map = IndexMap::with_capacity(insert.len());
-
- for (i, &elt) in insert.iter().enumerate() {
- assert_eq!(map.len(), i);
- map.insert(elt, elt);
- assert_eq!(map.len(), i + 1);
- assert_eq!(map.get(&elt), Some(&elt));
- assert_eq!(map[&elt], elt);
- }
-
- println!("{:?}", map);
- for &elt in &insert {
- map.insert(elt * 10, elt);
- }
- for &elt in &insert {
- map.insert(elt * 100, elt);
- }
- for (i, &elt) in insert.iter().cycle().enumerate().take(100) {
- map.insert(elt * 100 + i as i32, elt);
- }
- println!("{:?}", map);
- for &elt in &not_present {
- assert!(map.get(&elt).is_none());
- }
- }
-
- #[test]
- fn reserve() {
- let mut map = IndexMap::<usize, usize>::new();
- assert_eq!(map.capacity(), 0);
- map.reserve(100);
- let capacity = map.capacity();
- assert!(capacity >= 100);
- for i in 0..capacity {
- assert_eq!(map.len(), i);
- map.insert(i, i * i);
- assert_eq!(map.len(), i + 1);
- assert_eq!(map.capacity(), capacity);
- assert_eq!(map.get(&i), Some(&(i * i)));
- }
- map.insert(capacity, std::usize::MAX);
- assert_eq!(map.len(), capacity + 1);
- assert!(map.capacity() > capacity);
- assert_eq!(map.get(&capacity), Some(&std::usize::MAX));
- }
-
- #[test]
- fn shrink_to_fit() {
- let mut map = IndexMap::<usize, usize>::new();
- assert_eq!(map.capacity(), 0);
- for i in 0..100 {
- assert_eq!(map.len(), i);
- map.insert(i, i * i);
- assert_eq!(map.len(), i + 1);
- assert!(map.capacity() >= i + 1);
- assert_eq!(map.get(&i), Some(&(i * i)));
- map.shrink_to_fit();
- assert_eq!(map.len(), i + 1);
- assert_eq!(map.capacity(), i + 1);
- assert_eq!(map.get(&i), Some(&(i * i)));
- }
- }
-
- #[test]
- fn remove() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
- let mut map = IndexMap::new();
-
- for &elt in &insert {
- map.insert(elt, elt);
- }
-
- assert_eq!(map.keys().count(), map.len());
- assert_eq!(map.keys().count(), insert.len());
- for (a, b) in insert.iter().zip(map.keys()) {
- assert_eq!(a, b);
- }
-
- let remove_fail = [99, 77];
- let remove = [4, 12, 8, 7];
-
- for &key in &remove_fail {
- assert!(map.swap_remove_full(&key).is_none());
- }
- println!("{:?}", map);
- for &key in &remove {
- //println!("{:?}", map);
- let index = map.get_full(&key).unwrap().0;
- assert_eq!(map.swap_remove_full(&key), Some((index, key, key)));
- }
- println!("{:?}", map);
-
- for key in &insert {
- assert_eq!(map.get(key).is_some(), !remove.contains(key));
- }
- assert_eq!(map.len(), insert.len() - remove.len());
- assert_eq!(map.keys().count(), insert.len() - remove.len());
- }
-
- #[test]
- fn remove_to_empty() {
- let mut map = indexmap! { 0 => 0, 4 => 4, 5 => 5 };
- map.swap_remove(&5).unwrap();
- map.swap_remove(&4).unwrap();
- map.swap_remove(&0).unwrap();
- assert!(map.is_empty());
- }
-
- #[test]
- fn swap_remove_index() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
- let mut map = IndexMap::new();
-
- for &elt in &insert {
- map.insert(elt, elt * 2);
- }
-
- let mut vector = insert.to_vec();
- let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1];
-
- // check that the same swap remove sequence on vec and map
- // have the same result.
- for &rm in remove_sequence {
- let out_vec = vector.swap_remove(rm);
- let (out_map, _) = map.swap_remove_index(rm).unwrap();
- assert_eq!(out_vec, out_map);
- }
- assert_eq!(vector.len(), map.len());
- for (a, b) in vector.iter().zip(map.keys()) {
- assert_eq!(a, b);
- }
- }
-
- #[test]
- fn partial_eq_and_eq() {
- let mut map_a = IndexMap::new();
- map_a.insert(1, "1");
- map_a.insert(2, "2");
- let mut map_b = map_a.clone();
- assert_eq!(map_a, map_b);
- map_b.swap_remove(&1);
- assert_ne!(map_a, map_b);
-
- let map_c: IndexMap<_, String> = map_b.into_iter().map(|(k, v)| (k, v.into())).collect();
- assert_ne!(map_a, map_c);
- assert_ne!(map_c, map_a);
- }
-
- #[test]
- fn extend() {
- let mut map = IndexMap::new();
- map.extend(vec![(&1, &2), (&3, &4)]);
- map.extend(vec![(5, 6)]);
- assert_eq!(
- map.into_iter().collect::<Vec<_>>(),
- vec![(1, 2), (3, 4), (5, 6)]
- );
- }
-
- #[test]
- fn entry() {
- let mut map = IndexMap::new();
-
- map.insert(1, "1");
- map.insert(2, "2");
- {
- let e = map.entry(3);
- assert_eq!(e.index(), 2);
- let e = e.or_insert("3");
- assert_eq!(e, &"3");
- }
-
- let e = map.entry(2);
- assert_eq!(e.index(), 1);
- assert_eq!(e.key(), &2);
- match e {
- Entry::Occupied(ref e) => assert_eq!(e.get(), &"2"),
- Entry::Vacant(_) => panic!(),
- }
- assert_eq!(e.or_insert("4"), &"2");
- }
-
- #[test]
- fn entry_and_modify() {
- let mut map = IndexMap::new();
-
- map.insert(1, "1");
- map.entry(1).and_modify(|x| *x = "2");
- assert_eq!(Some(&"2"), map.get(&1));
-
- map.entry(2).and_modify(|x| *x = "doesn't exist");
- assert_eq!(None, map.get(&2));
- }
-
- #[test]
- fn entry_or_default() {
- let mut map = IndexMap::new();
-
- #[derive(Debug, PartialEq)]
- enum TestEnum {
- DefaultValue,
- NonDefaultValue,
- }
-
- impl Default for TestEnum {
- fn default() -> Self {
- TestEnum::DefaultValue
- }
- }
-
- map.insert(1, TestEnum::NonDefaultValue);
- assert_eq!(&mut TestEnum::NonDefaultValue, map.entry(1).or_default());
-
- assert_eq!(&mut TestEnum::DefaultValue, map.entry(2).or_default());
- }
-
- #[test]
- fn occupied_entry_key() {
- // These keys match hash and equality, but their addresses are distinct.
- let (k1, k2) = (&mut 1, &mut 1);
- let k1_ptr = k1 as *const i32;
- let k2_ptr = k2 as *const i32;
- assert_ne!(k1_ptr, k2_ptr);
-
- let mut map = IndexMap::new();
- map.insert(k1, "value");
- match map.entry(k2) {
- Entry::Occupied(ref e) => {
- // `OccupiedEntry::key` should reference the key in the map,
- // not the key that was used to find the entry.
- let ptr = *e.key() as *const i32;
- assert_eq!(ptr, k1_ptr);
- assert_ne!(ptr, k2_ptr);
- }
- Entry::Vacant(_) => panic!(),
- }
- }
-
- #[test]
- fn keys() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map: IndexMap<_, _> = vec.into_iter().collect();
- let keys: Vec<_> = map.keys().copied().collect();
- assert_eq!(keys.len(), 3);
- assert!(keys.contains(&1));
- assert!(keys.contains(&2));
- assert!(keys.contains(&3));
- }
-
- #[test]
- fn into_keys() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map: IndexMap<_, _> = vec.into_iter().collect();
- let keys: Vec<i32> = map.into_keys().collect();
- assert_eq!(keys.len(), 3);
- assert!(keys.contains(&1));
- assert!(keys.contains(&2));
- assert!(keys.contains(&3));
- }
-
- #[test]
- fn values() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map: IndexMap<_, _> = vec.into_iter().collect();
- let values: Vec<_> = map.values().copied().collect();
- assert_eq!(values.len(), 3);
- assert!(values.contains(&'a'));
- assert!(values.contains(&'b'));
- assert!(values.contains(&'c'));
- }
-
- #[test]
- fn values_mut() {
- let vec = vec![(1, 1), (2, 2), (3, 3)];
- let mut map: IndexMap<_, _> = vec.into_iter().collect();
- for value in map.values_mut() {
- *value *= 2
- }
- let values: Vec<_> = map.values().copied().collect();
- assert_eq!(values.len(), 3);
- assert!(values.contains(&2));
- assert!(values.contains(&4));
- assert!(values.contains(&6));
- }
-
- #[test]
- fn into_values() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map: IndexMap<_, _> = vec.into_iter().collect();
- let values: Vec<char> = map.into_values().collect();
- assert_eq!(values.len(), 3);
- assert!(values.contains(&'a'));
- assert!(values.contains(&'b'));
- assert!(values.contains(&'c'));
- }
-
- #[test]
- #[cfg(has_std)]
- fn from_array() {
- let map = IndexMap::from([(1, 2), (3, 4)]);
- let mut expected = IndexMap::new();
- expected.insert(1, 2);
- expected.insert(3, 4);
-
- assert_eq!(map, expected)
- }
-}
diff --git a/third_party/rust/indexmap/src/map/core.rs b/third_party/rust/indexmap/src/map/core.rs
index ea7aaae62e..16e87c7c6a 100644
--- a/third_party/rust/indexmap/src/map/core.rs
+++ b/third_party/rust/indexmap/src/map/core.rs
@@ -7,19 +7,22 @@
//!
//! However, we should probably not let this show in the public API or docs.
+mod entry;
mod raw;
+pub mod raw_entry_v1;
+
use hashbrown::raw::RawTable;
-use crate::vec::{Drain, Vec};
-use core::cmp;
-use core::fmt;
-use core::mem::replace;
+use crate::vec::{self, Vec};
+use crate::TryReserveError;
+use core::mem;
use core::ops::RangeBounds;
-use crate::equivalent::Equivalent;
use crate::util::simplify_range;
-use crate::{Bucket, Entries, HashValue};
+use crate::{Bucket, Entries, Equivalent, HashValue};
+
+pub use entry::{Entry, IndexedEntry, OccupiedEntry, VacantEntry};
/// Core of the map that does not depend on S
pub(crate) struct IndexMapCore<K, V> {
@@ -62,29 +65,30 @@ where
V: Clone,
{
fn clone(&self) -> Self {
- let indices = self.indices.clone();
- let mut entries = Vec::with_capacity(indices.capacity());
- entries.clone_from(&self.entries);
- IndexMapCore { indices, entries }
+ let mut new = Self::new();
+ new.clone_from(self);
+ new
}
fn clone_from(&mut self, other: &Self) {
let hasher = get_hash(&other.entries);
self.indices.clone_from_with_hasher(&other.indices, hasher);
if self.entries.capacity() < other.entries.len() {
- // If we must resize, match the indices capacity
- self.reserve_entries();
+ // If we must resize, match the indices capacity.
+ let additional = other.entries.len() - self.entries.len();
+ self.reserve_entries(additional);
}
self.entries.clone_from(&other.entries);
}
}
-impl<K, V> fmt::Debug for IndexMapCore<K, V>
+#[cfg(feature = "test_debug")]
+impl<K, V> core::fmt::Debug for IndexMapCore<K, V>
where
- K: fmt::Debug,
- V: fmt::Debug,
+ K: core::fmt::Debug,
+ V: core::fmt::Debug,
{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("IndexMapCore")
.field("indices", &raw::DebugIndices(&self.indices))
.field("entries", &self.entries)
@@ -120,6 +124,9 @@ impl<K, V> Entries for IndexMapCore<K, V> {
}
impl<K, V> IndexMapCore<K, V> {
+ /// The maximum capacity before the `entries` allocation would exceed `isize::MAX`.
+ const MAX_ENTRIES_CAPACITY: usize = (isize::MAX as usize) / mem::size_of::<Bucket<K, V>>();
+
#[inline]
pub(crate) const fn new() -> Self {
IndexMapCore {
@@ -143,7 +150,7 @@ impl<K, V> IndexMapCore<K, V> {
#[inline]
pub(crate) fn capacity(&self) -> usize {
- cmp::min(self.indices.capacity(), self.entries.capacity())
+ Ord::min(self.indices.capacity(), self.entries.capacity())
}
pub(crate) fn clear(&mut self) {
@@ -158,7 +165,7 @@ impl<K, V> IndexMapCore<K, V> {
}
}
- pub(crate) fn drain<R>(&mut self, range: R) -> Drain<'_, Bucket<K, V>>
+ pub(crate) fn drain<R>(&mut self, range: R) -> vec::Drain<'_, Bucket<K, V>>
where
R: RangeBounds<usize>,
{
@@ -190,18 +197,92 @@ impl<K, V> IndexMapCore<K, V> {
Self { indices, entries }
}
+ pub(crate) fn split_splice<R>(&mut self, range: R) -> (Self, vec::IntoIter<Bucket<K, V>>)
+ where
+ R: RangeBounds<usize>,
+ {
+ let range = simplify_range(range, self.len());
+ self.erase_indices(range.start, self.entries.len());
+ let entries = self.entries.split_off(range.end);
+ let drained = self.entries.split_off(range.start);
+
+ let mut indices = RawTable::with_capacity(entries.len());
+ raw::insert_bulk_no_grow(&mut indices, &entries);
+ (Self { indices, entries }, drained.into_iter())
+ }
+
+ /// Append from another map without checking whether items already exist.
+ pub(crate) fn append_unchecked(&mut self, other: &mut Self) {
+ self.reserve(other.len());
+ raw::insert_bulk_no_grow(&mut self.indices, &other.entries);
+ self.entries.append(&mut other.entries);
+ other.indices.clear();
+ }
+
/// Reserve capacity for `additional` more key-value pairs.
pub(crate) fn reserve(&mut self, additional: usize) {
self.indices.reserve(additional, get_hash(&self.entries));
- self.reserve_entries();
+ // Only grow entries if necessary, since we also round up capacity.
+ if additional > self.entries.capacity() - self.entries.len() {
+ self.reserve_entries(additional);
+ }
+ }
+
+ /// Reserve entries capacity, rounded up to match the indices
+ fn reserve_entries(&mut self, additional: usize) {
+ // Use a soft-limit on the maximum capacity, but if the caller explicitly
+ // requested more, do it and let them have the resulting panic.
+ let new_capacity = Ord::min(self.indices.capacity(), Self::MAX_ENTRIES_CAPACITY);
+ let try_add = new_capacity - self.entries.len();
+ if try_add > additional && self.entries.try_reserve_exact(try_add).is_ok() {
+ return;
+ }
+ self.entries.reserve_exact(additional);
}
- /// Reserve entries capacity to match the indices
- fn reserve_entries(&mut self) {
- let additional = self.indices.capacity() - self.entries.len();
+ /// Reserve capacity for `additional` more key-value pairs, without over-allocating.
+ pub(crate) fn reserve_exact(&mut self, additional: usize) {
+ self.indices.reserve(additional, get_hash(&self.entries));
self.entries.reserve_exact(additional);
}
+ /// Try to reserve capacity for `additional` more key-value pairs.
+ pub(crate) fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.indices
+ .try_reserve(additional, get_hash(&self.entries))
+ .map_err(TryReserveError::from_hashbrown)?;
+ // Only grow entries if necessary, since we also round up capacity.
+ if additional > self.entries.capacity() - self.entries.len() {
+ self.try_reserve_entries(additional)
+ } else {
+ Ok(())
+ }
+ }
+
+ /// Try to reserve entries capacity, rounded up to match the indices
+ fn try_reserve_entries(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ // Use a soft-limit on the maximum capacity, but if the caller explicitly
+ // requested more, do it and let them have the resulting error.
+ let new_capacity = Ord::min(self.indices.capacity(), Self::MAX_ENTRIES_CAPACITY);
+ let try_add = new_capacity - self.entries.len();
+ if try_add > additional && self.entries.try_reserve_exact(try_add).is_ok() {
+ return Ok(());
+ }
+ self.entries
+ .try_reserve_exact(additional)
+ .map_err(TryReserveError::from_alloc)
+ }
+
+ /// Try to reserve capacity for `additional` more key-value pairs, without over-allocating.
+ pub(crate) fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.indices
+ .try_reserve(additional, get_hash(&self.entries))
+ .map_err(TryReserveError::from_hashbrown)?;
+ self.entries
+ .try_reserve_exact(additional)
+ .map_err(TryReserveError::from_alloc)
+ }
+
/// Shrink the capacity of the map with a lower bound
pub(crate) fn shrink_to(&mut self, min_capacity: usize) {
self.indices
@@ -220,18 +301,25 @@ impl<K, V> IndexMapCore<K, V> {
}
}
- /// Append a key-value pair, *without* checking whether it already exists,
- /// and return the pair's new index.
- fn push(&mut self, hash: HashValue, key: K, value: V) -> usize {
- let i = self.entries.len();
- self.indices.insert(hash.get(), i, get_hash(&self.entries));
- if i == self.entries.capacity() {
+ /// Append a key-value pair to `entries`, *without* checking whether it already exists.
+ fn push_entry(&mut self, hash: HashValue, key: K, value: V) {
+ if self.entries.len() == self.entries.capacity() {
// Reserve our own capacity synced to the indices,
// rather than letting `Vec::push` just double it.
- self.reserve_entries();
+ self.reserve_entries(1);
}
self.entries.push(Bucket { hash, key, value });
- i
+ }
+
+ /// Insert a key-value pair in `entries` at a particular index,
+ /// *without* checking whether it already exists.
+ fn insert_entry(&mut self, index: usize, hash: HashValue, key: K, value: V) {
+ if self.entries.len() == self.entries.capacity() {
+ // Reserve our own capacity synced to the indices,
+ // rather than letting `Vec::insert` just double it.
+ self.reserve_entries(1);
+ }
+ self.entries.insert(index, Bucket { hash, key, value });
}
/// Return the index in `entries` where an equivalent key can be found
@@ -247,12 +335,66 @@ impl<K, V> IndexMapCore<K, V> {
where
K: Eq,
{
- match self.get_index_of(hash, &key) {
- Some(i) => (i, Some(replace(&mut self.entries[i].value, value))),
- None => (self.push(hash, key, value), None),
+ match self.find_or_insert(hash, &key) {
+ Ok(i) => (i, Some(mem::replace(&mut self.entries[i].value, value))),
+ Err(i) => {
+ debug_assert_eq!(i, self.entries.len());
+ self.push_entry(hash, key, value);
+ (i, None)
+ }
+ }
+ }
+
+ /// Same as `insert_full`, except it also replaces the key
+ pub(crate) fn replace_full(
+ &mut self,
+ hash: HashValue,
+ key: K,
+ value: V,
+ ) -> (usize, Option<(K, V)>)
+ where
+ K: Eq,
+ {
+ match self.find_or_insert(hash, &key) {
+ Ok(i) => {
+ let entry = &mut self.entries[i];
+ let kv = (
+ mem::replace(&mut entry.key, key),
+ mem::replace(&mut entry.value, value),
+ );
+ (i, Some(kv))
+ }
+ Err(i) => {
+ debug_assert_eq!(i, self.entries.len());
+ self.push_entry(hash, key, value);
+ (i, None)
+ }
}
}
+ fn insert_unique(&mut self, hash: HashValue, key: K, value: V) -> usize {
+ let i = self.indices.len();
+ self.indices.insert(hash.get(), i, get_hash(&self.entries));
+ debug_assert_eq!(i, self.entries.len());
+ self.push_entry(hash, key, value);
+ i
+ }
+
+ fn shift_insert_unique(&mut self, index: usize, hash: HashValue, key: K, value: V) {
+ let end = self.indices.len();
+ assert!(index <= end);
+ // Increment others first so we don't have duplicate indices.
+ self.increment_indices(index, end);
+ let entries = &*self.entries;
+ self.indices.insert(hash.get(), index, move |&i| {
+ // Adjust for the incremented indices to find hashes.
+ debug_assert_ne!(i, index);
+ let i = if i < index { i } else { i - 1 };
+ entries[i].hash.get()
+ });
+ self.insert_entry(index, hash, key, value);
+ }
+
/// Remove an entry by shifting all entries that follow it
pub(crate) fn shift_remove_full<Q>(&mut self, hash: HashValue, key: &Q) -> Option<(usize, K, V)>
where
@@ -339,7 +481,7 @@ impl<K, V> IndexMapCore<K, V> {
pub(super) fn move_index(&mut self, from: usize, to: usize) {
let from_hash = self.entries[from].hash;
if from != to {
- // Use a sentinal index so other indices don't collide.
+ // Use a sentinel index so other indices don't collide.
update_index(&mut self.indices, from_hash, from, usize::MAX);
// Update all other indices and rotate the entry positions.
@@ -351,11 +493,31 @@ impl<K, V> IndexMapCore<K, V> {
self.entries[to..=from].rotate_right(1);
}
- // Change the sentinal index to its final position.
+ // Change the sentinel index to its final position.
update_index(&mut self.indices, from_hash, usize::MAX, to);
}
}
+ pub(crate) fn swap_indices(&mut self, a: usize, b: usize) {
+ // If they're equal and in-bounds, there's nothing to do.
+ if a == b && a < self.entries.len() {
+ return;
+ }
+
+ // We'll get a "nice" bounds-check from indexing `self.entries`,
+ // and then we expect to find it in the table as well.
+ let [ref_a, ref_b] = self
+ .indices
+ .get_many_mut(
+ [self.entries[a].hash.get(), self.entries[b].hash.get()],
+ move |i, &x| if i == 0 { x == a } else { x == b },
+ )
+ .expect("indices not found");
+
+ mem::swap(ref_a, ref_b);
+ self.entries.swap(a, b);
+ }
+
/// Remove an entry by swapping it with the last
pub(crate) fn swap_remove_full<Q>(&mut self, hash: HashValue, key: &Q) -> Option<(usize, K, V)>
where
@@ -447,25 +609,9 @@ impl<K, V> IndexMapCore<K, V> {
where
F: FnMut(&mut K, &mut V) -> bool,
{
- // FIXME: This could use Vec::retain_mut with MSRV 1.61.
- // Like Vec::retain in self.entries, but with mutable K and V.
- // We swap-shift all the items we want to keep, truncate the rest,
- // then rebuild the raw hash table with the new indexes.
- let len = self.entries.len();
- let mut n_deleted = 0;
- for i in 0..len {
- let will_keep = {
- let entry = &mut self.entries[i];
- keep(&mut entry.key, &mut entry.value)
- };
- if !will_keep {
- n_deleted += 1;
- } else if n_deleted > 0 {
- self.entries.swap(i - n_deleted, i);
- }
- }
- if n_deleted > 0 {
- self.entries.truncate(len - n_deleted);
+ self.entries
+ .retain_mut(|entry| keep(&mut entry.key, &mut entry.value));
+ if self.entries.len() < self.indices.len() {
self.rebuild_hash_table();
}
}
@@ -487,214 +633,10 @@ impl<K, V> IndexMapCore<K, V> {
}
}
-/// Entry for an existing key-value pair or a vacant location to
-/// insert one.
-pub enum Entry<'a, K, V> {
- /// Existing slot with equivalent key.
- Occupied(OccupiedEntry<'a, K, V>),
- /// Vacant slot (no equivalent key in the map).
- Vacant(VacantEntry<'a, K, V>),
-}
-
-impl<'a, K, V> Entry<'a, K, V> {
- /// Inserts the given default value in the entry if it is vacant and returns a mutable
- /// reference to it. Otherwise a mutable reference to an already existent value is returned.
- ///
- /// Computes in **O(1)** time (amortized average).
- pub fn or_insert(self, default: V) -> &'a mut V {
- match self {
- Entry::Occupied(entry) => entry.into_mut(),
- Entry::Vacant(entry) => entry.insert(default),
- }
- }
-
- /// Inserts the result of the `call` function in the entry if it is vacant and returns a mutable
- /// reference to it. Otherwise a mutable reference to an already existent value is returned.
- ///
- /// Computes in **O(1)** time (amortized average).
- pub fn or_insert_with<F>(self, call: F) -> &'a mut V
- where
- F: FnOnce() -> V,
- {
- match self {
- Entry::Occupied(entry) => entry.into_mut(),
- Entry::Vacant(entry) => entry.insert(call()),
- }
- }
-
- /// Inserts the result of the `call` function with a reference to the entry's key if it is
- /// vacant, and returns a mutable reference to the new value. Otherwise a mutable reference to
- /// an already existent value is returned.
- ///
- /// Computes in **O(1)** time (amortized average).
- pub fn or_insert_with_key<F>(self, call: F) -> &'a mut V
- where
- F: FnOnce(&K) -> V,
- {
- match self {
- Entry::Occupied(entry) => entry.into_mut(),
- Entry::Vacant(entry) => {
- let value = call(&entry.key);
- entry.insert(value)
- }
- }
- }
-
- /// Gets a reference to the entry's key, either within the map if occupied,
- /// or else the new key that was used to find the entry.
- pub fn key(&self) -> &K {
- match *self {
- Entry::Occupied(ref entry) => entry.key(),
- Entry::Vacant(ref entry) => entry.key(),
- }
- }
-
- /// Return the index where the key-value pair exists or will be inserted.
- pub fn index(&self) -> usize {
- match *self {
- Entry::Occupied(ref entry) => entry.index(),
- Entry::Vacant(ref entry) => entry.index(),
- }
- }
-
- /// Modifies the entry if it is occupied.
- pub fn and_modify<F>(self, f: F) -> Self
- where
- F: FnOnce(&mut V),
- {
- match self {
- Entry::Occupied(mut o) => {
- f(o.get_mut());
- Entry::Occupied(o)
- }
- x => x,
- }
- }
-
- /// Inserts a default-constructed value in the entry if it is vacant and returns a mutable
- /// reference to it. Otherwise a mutable reference to an already existent value is returned.
- ///
- /// Computes in **O(1)** time (amortized average).
- pub fn or_default(self) -> &'a mut V
- where
- V: Default,
- {
- match self {
- Entry::Occupied(entry) => entry.into_mut(),
- Entry::Vacant(entry) => entry.insert(V::default()),
- }
- }
-}
-
-impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Entry<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match *self {
- Entry::Vacant(ref v) => f.debug_tuple(stringify!(Entry)).field(v).finish(),
- Entry::Occupied(ref o) => f.debug_tuple(stringify!(Entry)).field(o).finish(),
- }
- }
-}
-
-pub use self::raw::OccupiedEntry;
-
-// Extra methods that don't threaten the unsafe encapsulation.
-impl<K, V> OccupiedEntry<'_, K, V> {
- /// Sets the value of the entry to `value`, and returns the entry's old value.
- pub fn insert(&mut self, value: V) -> V {
- replace(self.get_mut(), value)
- }
-
- /// Remove the key, value pair stored in the map for this entry, and return the value.
- ///
- /// **NOTE:** This is equivalent to `.swap_remove()`.
- pub fn remove(self) -> V {
- self.swap_remove()
- }
-
- /// Remove the key, value pair stored in the map for this entry, and return the value.
- ///
- /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
- /// last element of the map and popping it off. **This perturbs
- /// the position of what used to be the last element!**
- ///
- /// Computes in **O(1)** time (average).
- pub fn swap_remove(self) -> V {
- self.swap_remove_entry().1
- }
-
- /// Remove the key, value pair stored in the map for this entry, and return the value.
- ///
- /// Like `Vec::remove`, the pair is removed by shifting all of the
- /// elements that follow it, preserving their relative order.
- /// **This perturbs the index of all of those elements!**
- ///
- /// Computes in **O(n)** time (average).
- pub fn shift_remove(self) -> V {
- self.shift_remove_entry().1
- }
-
- /// Remove and return the key, value pair stored in the map for this entry
- ///
- /// **NOTE:** This is equivalent to `.swap_remove_entry()`.
- pub fn remove_entry(self) -> (K, V) {
- self.swap_remove_entry()
- }
-}
-
-impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for OccupiedEntry<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct(stringify!(OccupiedEntry))
- .field("key", self.key())
- .field("value", self.get())
- .finish()
- }
-}
-
-/// A view into a vacant entry in a `IndexMap`.
-/// It is part of the [`Entry`] enum.
-///
-/// [`Entry`]: enum.Entry.html
-pub struct VacantEntry<'a, K, V> {
- map: &'a mut IndexMapCore<K, V>,
- hash: HashValue,
- key: K,
-}
-
-impl<'a, K, V> VacantEntry<'a, K, V> {
- /// Gets a reference to the key that was used to find the entry.
- pub fn key(&self) -> &K {
- &self.key
- }
-
- /// Takes ownership of the key, leaving the entry vacant.
- pub fn into_key(self) -> K {
- self.key
- }
-
- /// Return the index where the key-value pair will be inserted.
- pub fn index(&self) -> usize {
- self.map.len()
- }
-
- /// Inserts the entry's key and the given value into the map, and returns a mutable reference
- /// to the value.
- pub fn insert(self, value: V) -> &'a mut V {
- let i = self.map.push(self.hash, self.key, value);
- &mut self.map.entries[i].value
- }
-}
-
-impl<K: fmt::Debug, V> fmt::Debug for VacantEntry<'_, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_tuple(stringify!(VacantEntry))
- .field(self.key())
- .finish()
- }
-}
-
#[test]
fn assert_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<IndexMapCore<i32, i32>>();
assert_send_sync::<Entry<'_, i32, i32>>();
+ assert_send_sync::<IndexedEntry<'_, i32, i32>>();
}
diff --git a/third_party/rust/indexmap/src/map/core/entry.rs b/third_party/rust/indexmap/src/map/core/entry.rs
new file mode 100644
index 0000000000..6c31070788
--- /dev/null
+++ b/third_party/rust/indexmap/src/map/core/entry.rs
@@ -0,0 +1,481 @@
+use super::raw::RawTableEntry;
+use super::IndexMapCore;
+use crate::HashValue;
+use core::{fmt, mem};
+
+impl<K, V> IndexMapCore<K, V> {
+ pub(crate) fn entry(&mut self, hash: HashValue, key: K) -> Entry<'_, K, V>
+ where
+ K: Eq,
+ {
+ match self.raw_entry(hash, |k| *k == key) {
+ Ok(raw) => Entry::Occupied(OccupiedEntry { raw }),
+ Err(map) => Entry::Vacant(VacantEntry { map, hash, key }),
+ }
+ }
+}
+
+/// Entry for an existing key-value pair in an [`IndexMap`][crate::IndexMap]
+/// or a vacant location to insert one.
+pub enum Entry<'a, K, V> {
+ /// Existing slot with equivalent key.
+ Occupied(OccupiedEntry<'a, K, V>),
+ /// Vacant slot (no equivalent key in the map).
+ Vacant(VacantEntry<'a, K, V>),
+}
+
+impl<'a, K, V> Entry<'a, K, V> {
+ /// Return the index where the key-value pair exists or will be inserted.
+ pub fn index(&self) -> usize {
+ match *self {
+ Entry::Occupied(ref entry) => entry.index(),
+ Entry::Vacant(ref entry) => entry.index(),
+ }
+ }
+
+ /// Inserts the given default value in the entry if it is vacant and returns a mutable
+ /// reference to it. Otherwise a mutable reference to an already existent value is returned.
+ ///
+ /// Computes in **O(1)** time (amortized average).
+ pub fn or_insert(self, default: V) -> &'a mut V {
+ match self {
+ Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Vacant(entry) => entry.insert(default),
+ }
+ }
+
+ /// Inserts the result of the `call` function in the entry if it is vacant and returns a mutable
+ /// reference to it. Otherwise a mutable reference to an already existent value is returned.
+ ///
+ /// Computes in **O(1)** time (amortized average).
+ pub fn or_insert_with<F>(self, call: F) -> &'a mut V
+ where
+ F: FnOnce() -> V,
+ {
+ match self {
+ Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Vacant(entry) => entry.insert(call()),
+ }
+ }
+
+ /// Inserts the result of the `call` function with a reference to the entry's key if it is
+ /// vacant, and returns a mutable reference to the new value. Otherwise a mutable reference to
+ /// an already existent value is returned.
+ ///
+ /// Computes in **O(1)** time (amortized average).
+ pub fn or_insert_with_key<F>(self, call: F) -> &'a mut V
+ where
+ F: FnOnce(&K) -> V,
+ {
+ match self {
+ Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Vacant(entry) => {
+ let value = call(&entry.key);
+ entry.insert(value)
+ }
+ }
+ }
+
+ /// Gets a reference to the entry's key, either within the map if occupied,
+ /// or else the new key that was used to find the entry.
+ pub fn key(&self) -> &K {
+ match *self {
+ Entry::Occupied(ref entry) => entry.key(),
+ Entry::Vacant(ref entry) => entry.key(),
+ }
+ }
+
+ /// Modifies the entry if it is occupied.
+ pub fn and_modify<F>(mut self, f: F) -> Self
+ where
+ F: FnOnce(&mut V),
+ {
+ if let Entry::Occupied(entry) = &mut self {
+ f(entry.get_mut());
+ }
+ self
+ }
+
+ /// Inserts a default-constructed value in the entry if it is vacant and returns a mutable
+ /// reference to it. Otherwise a mutable reference to an already existent value is returned.
+ ///
+ /// Computes in **O(1)** time (amortized average).
+ pub fn or_default(self) -> &'a mut V
+ where
+ V: Default,
+ {
+ match self {
+ Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Vacant(entry) => entry.insert(V::default()),
+ }
+ }
+}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Entry<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut tuple = f.debug_tuple("Entry");
+ match self {
+ Entry::Vacant(v) => tuple.field(v),
+ Entry::Occupied(o) => tuple.field(o),
+ };
+ tuple.finish()
+ }
+}
+
+/// A view into an occupied entry in an [`IndexMap`][crate::IndexMap].
+/// It is part of the [`Entry`] enum.
+pub struct OccupiedEntry<'a, K, V> {
+ raw: RawTableEntry<'a, K, V>,
+}
+
+impl<'a, K, V> OccupiedEntry<'a, K, V> {
+ /// Return the index of the key-value pair
+ #[inline]
+ pub fn index(&self) -> usize {
+ self.raw.index()
+ }
+
+ /// Gets a reference to the entry's key in the map.
+ ///
+ /// Note that this is not the key that was used to find the entry. There may be an observable
+ /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like
+ /// extra fields or the memory address of an allocation.
+ pub fn key(&self) -> &K {
+ &self.raw.bucket().key
+ }
+
+ /// Gets a reference to the entry's value in the map.
+ pub fn get(&self) -> &V {
+ &self.raw.bucket().value
+ }
+
+ /// Gets a mutable reference to the entry's value in the map.
+ ///
+ /// If you need a reference which may outlive the destruction of the
+ /// [`Entry`] value, see [`into_mut`][Self::into_mut].
+ pub fn get_mut(&mut self) -> &mut V {
+ &mut self.raw.bucket_mut().value
+ }
+
+ /// Converts into a mutable reference to the entry's value in the map,
+ /// with a lifetime bound to the map itself.
+ pub fn into_mut(self) -> &'a mut V {
+ &mut self.raw.into_bucket().value
+ }
+
+ /// Sets the value of the entry to `value`, and returns the entry's old value.
+ pub fn insert(&mut self, value: V) -> V {
+ mem::replace(self.get_mut(), value)
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// **NOTE:** This is equivalent to [`.swap_remove()`][Self::swap_remove], replacing this
+ /// entry's position with the last element, and it is deprecated in favor of calling that
+ /// explicitly. If you need to preserve the relative order of the keys in the map, use
+ /// [`.shift_remove()`][Self::shift_remove] instead.
+ #[deprecated(note = "`remove` disrupts the map order -- \
+ use `swap_remove` or `shift_remove` for explicit behavior.")]
+ pub fn remove(self) -> V {
+ self.swap_remove()
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with
+ /// the last element of the map and popping it off.
+ /// **This perturbs the position of what used to be the last element!**
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_remove(self) -> V {
+ self.swap_remove_entry().1
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the
+ /// elements that follow it, preserving their relative order.
+ /// **This perturbs the index of all of those elements!**
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_remove(self) -> V {
+ self.shift_remove_entry().1
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// **NOTE:** This is equivalent to [`.swap_remove_entry()`][Self::swap_remove_entry],
+ /// replacing this entry's position with the last element, and it is deprecated in favor of
+ /// calling that explicitly. If you need to preserve the relative order of the keys in the map,
+ /// use [`.shift_remove_entry()`][Self::shift_remove_entry] instead.
+ #[deprecated(note = "`remove_entry` disrupts the map order -- \
+ use `swap_remove_entry` or `shift_remove_entry` for explicit behavior.")]
+ pub fn remove_entry(self) -> (K, V) {
+ self.swap_remove_entry()
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with
+ /// the last element of the map and popping it off.
+ /// **This perturbs the position of what used to be the last element!**
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_remove_entry(self) -> (K, V) {
+ let (map, index) = self.raw.remove_index();
+ map.swap_remove_finish(index)
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the
+ /// elements that follow it, preserving their relative order.
+ /// **This perturbs the index of all of those elements!**
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_remove_entry(self) -> (K, V) {
+ let (map, index) = self.raw.remove_index();
+ map.shift_remove_finish(index)
+ }
+
+ /// Moves the position of the entry to a new index
+ /// by shifting all other entries in-between.
+ ///
+ /// This is equivalent to [`IndexMap::move_index`][`crate::IndexMap::move_index`]
+ /// coming `from` the current [`.index()`][Self::index].
+ ///
+ /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up.
+ /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down.
+ ///
+ /// ***Panics*** if `to` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn move_index(self, to: usize) {
+ let (map, index) = self.raw.into_inner();
+ map.move_index(index, to);
+ }
+
+ /// Swaps the position of entry with another.
+ ///
+ /// This is equivalent to [`IndexMap::swap_indices`][`crate::IndexMap::swap_indices`]
+ /// with the current [`.index()`][Self::index] as one of the two being swapped.
+ ///
+ /// ***Panics*** if the `other` index is out of bounds.
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_indices(self, other: usize) {
+ let (map, index) = self.raw.into_inner();
+ map.swap_indices(index, other)
+ }
+}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for OccupiedEntry<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("OccupiedEntry")
+ .field("key", self.key())
+ .field("value", self.get())
+ .finish()
+ }
+}
+
+/// A view into a vacant entry in an [`IndexMap`][crate::IndexMap].
+/// It is part of the [`Entry`] enum.
+pub struct VacantEntry<'a, K, V> {
+ map: &'a mut IndexMapCore<K, V>,
+ hash: HashValue,
+ key: K,
+}
+
+impl<'a, K, V> VacantEntry<'a, K, V> {
+ /// Return the index where a key-value pair may be inserted.
+ pub fn index(&self) -> usize {
+ self.map.indices.len()
+ }
+
+ /// Gets a reference to the key that was used to find the entry.
+ pub fn key(&self) -> &K {
+ &self.key
+ }
+
+ /// Takes ownership of the key, leaving the entry vacant.
+ pub fn into_key(self) -> K {
+ self.key
+ }
+
+ /// Inserts the entry's key and the given value into the map, and returns a mutable reference
+ /// to the value.
+ pub fn insert(self, value: V) -> &'a mut V {
+ let Self { map, hash, key } = self;
+ let i = map.insert_unique(hash, key, value);
+ &mut map.entries[i].value
+ }
+
+ /// Inserts the entry's key and the given value into the map at its ordered
+ /// position among sorted keys, and returns the new index and a mutable
+ /// reference to the value.
+ ///
+ /// If the existing keys are **not** already sorted, then the insertion
+ /// index is unspecified (like [`slice::binary_search`]), but the key-value
+ /// pair is inserted at that position regardless.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn insert_sorted(self, value: V) -> (usize, &'a mut V)
+ where
+ K: Ord,
+ {
+ let slice = crate::map::Slice::from_slice(&self.map.entries);
+ let i = slice.binary_search_keys(&self.key).unwrap_err();
+ (i, self.shift_insert(i, value))
+ }
+
+ /// Inserts the entry's key and the given value into the map at the given index,
+ /// shifting others to the right, and returns a mutable reference to the value.
+ ///
+ /// ***Panics*** if `index` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_insert(self, index: usize, value: V) -> &'a mut V {
+ let Self { map, hash, key } = self;
+ map.shift_insert_unique(index, hash, key, value);
+ &mut map.entries[index].value
+ }
+}
+
+impl<K: fmt::Debug, V> fmt::Debug for VacantEntry<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("VacantEntry").field(self.key()).finish()
+ }
+}
+
+/// A view into an occupied entry in an [`IndexMap`][crate::IndexMap] obtained by index.
+///
+/// This `struct` is created from the [`get_index_entry`][crate::IndexMap::get_index_entry] method.
+pub struct IndexedEntry<'a, K, V> {
+ map: &'a mut IndexMapCore<K, V>,
+ // We have a mutable reference to the map, which keeps the index
+ // valid and pointing to the correct entry.
+ index: usize,
+}
+
+impl<'a, K, V> IndexedEntry<'a, K, V> {
+ pub(crate) fn new(map: &'a mut IndexMapCore<K, V>, index: usize) -> Self {
+ Self { map, index }
+ }
+
+ /// Return the index of the key-value pair
+ #[inline]
+ pub fn index(&self) -> usize {
+ self.index
+ }
+
+ /// Gets a reference to the entry's key in the map.
+ pub fn key(&self) -> &K {
+ &self.map.entries[self.index].key
+ }
+
+ /// Gets a reference to the entry's value in the map.
+ pub fn get(&self) -> &V {
+ &self.map.entries[self.index].value
+ }
+
+ /// Gets a mutable reference to the entry's value in the map.
+ ///
+ /// If you need a reference which may outlive the destruction of the
+ /// `IndexedEntry` value, see [`into_mut`][Self::into_mut].
+ pub fn get_mut(&mut self) -> &mut V {
+ &mut self.map.entries[self.index].value
+ }
+
+ /// Sets the value of the entry to `value`, and returns the entry's old value.
+ pub fn insert(&mut self, value: V) -> V {
+ mem::replace(self.get_mut(), value)
+ }
+
+ /// Converts into a mutable reference to the entry's value in the map,
+ /// with a lifetime bound to the map itself.
+ pub fn into_mut(self) -> &'a mut V {
+ &mut self.map.entries[self.index].value
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with
+ /// the last element of the map and popping it off.
+ /// **This perturbs the position of what used to be the last element!**
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_remove_entry(self) -> (K, V) {
+ self.map.swap_remove_index(self.index).unwrap()
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the
+ /// elements that follow it, preserving their relative order.
+ /// **This perturbs the index of all of those elements!**
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_remove_entry(self) -> (K, V) {
+ self.map.shift_remove_index(self.index).unwrap()
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with
+ /// the last element of the map and popping it off.
+ /// **This perturbs the position of what used to be the last element!**
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_remove(self) -> V {
+ self.swap_remove_entry().1
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the
+ /// elements that follow it, preserving their relative order.
+ /// **This perturbs the index of all of those elements!**
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_remove(self) -> V {
+ self.shift_remove_entry().1
+ }
+
+ /// Moves the position of the entry to a new index
+ /// by shifting all other entries in-between.
+ ///
+ /// This is equivalent to [`IndexMap::move_index`][`crate::IndexMap::move_index`]
+ /// coming `from` the current [`.index()`][Self::index].
+ ///
+ /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up.
+ /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down.
+ ///
+ /// ***Panics*** if `to` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn move_index(self, to: usize) {
+ self.map.move_index(self.index, to);
+ }
+
+ /// Swaps the position of entry with another.
+ ///
+ /// This is equivalent to [`IndexMap::swap_indices`][`crate::IndexMap::swap_indices`]
+ /// with the current [`.index()`][Self::index] as one of the two being swapped.
+ ///
+ /// ***Panics*** if the `other` index is out of bounds.
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_indices(self, other: usize) {
+ self.map.swap_indices(self.index, other)
+ }
+}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IndexedEntry<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("IndexedEntry")
+ .field("index", &self.index)
+ .field("key", self.key())
+ .field("value", self.get())
+ .finish()
+ }
+}
diff --git a/third_party/rust/indexmap/src/map/core/raw.rs b/third_party/rust/indexmap/src/map/core/raw.rs
index bf1672d52a..451994339a 100644
--- a/third_party/rust/indexmap/src/map/core/raw.rs
+++ b/third_party/rust/indexmap/src/map/core/raw.rs
@@ -2,9 +2,7 @@
//! This module encapsulates the `unsafe` access to `hashbrown::raw::RawTable`,
//! mostly in dealing with its bucket "pointers".
-use super::{equivalent, Bucket, Entry, HashValue, IndexMapCore, VacantEntry};
-use core::fmt;
-use core::mem::replace;
+use super::{equivalent, get_hash, Bucket, HashValue, IndexMapCore};
use hashbrown::raw::RawTable;
type RawBucket = hashbrown::raw::Bucket<usize>;
@@ -22,11 +20,14 @@ pub(super) fn insert_bulk_no_grow<K, V>(indices: &mut RawTable<usize>, entries:
}
}
+#[cfg(feature = "test_debug")]
pub(super) struct DebugIndices<'a>(pub &'a RawTable<usize>);
-impl fmt::Debug for DebugIndices<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+
+#[cfg(feature = "test_debug")]
+impl core::fmt::Debug for DebugIndices<'_> {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
// SAFETY: we're not letting any of the buckets escape this function
- let indices = unsafe { self.0.iter().map(|raw_bucket| raw_bucket.read()) };
+ let indices = unsafe { self.0.iter().map(|raw_bucket| *raw_bucket.as_ref()) };
f.debug_list().entries(indices).finish()
}
}
@@ -38,34 +39,57 @@ impl<K, V> IndexMapCore<K, V> {
unsafe {
let offset = end - start;
for bucket in self.indices.iter() {
- let i = bucket.read();
- if i >= end {
- bucket.write(i - offset);
- } else if i >= start {
+ let i = bucket.as_mut();
+ if *i >= end {
+ *i -= offset;
+ } else if *i >= start {
self.indices.erase(bucket);
}
}
}
}
- pub(crate) fn entry(&mut self, hash: HashValue, key: K) -> Entry<'_, K, V>
+ /// Search for a key in the table and return `Ok(entry_index)` if found.
+ /// Otherwise, insert the key and return `Err(new_index)`.
+ ///
+ /// Note that hashbrown may resize the table to reserve space for insertion,
+ /// even before checking if it's already present, so this is somewhat biased
+ /// towards new items.
+ pub(crate) fn find_or_insert(&mut self, hash: HashValue, key: &K) -> Result<usize, usize>
where
K: Eq,
{
- let eq = equivalent(&key, &self.entries);
+ let hash = hash.get();
+ let eq = equivalent(key, &self.entries);
+ let hasher = get_hash(&self.entries);
+ // SAFETY: We're not mutating between find and read/insert.
+ unsafe {
+ match self.indices.find_or_find_insert_slot(hash, eq, hasher) {
+ Ok(raw_bucket) => Ok(*raw_bucket.as_ref()),
+ Err(slot) => {
+ let index = self.indices.len();
+ self.indices.insert_in_slot(hash, slot, index);
+ Err(index)
+ }
+ }
+ }
+ }
+
+ pub(super) fn raw_entry(
+ &mut self,
+ hash: HashValue,
+ mut is_match: impl FnMut(&K) -> bool,
+ ) -> Result<RawTableEntry<'_, K, V>, &mut Self> {
+ let entries = &*self.entries;
+ let eq = move |&i: &usize| is_match(&entries[i].key);
match self.indices.find(hash.get(), eq) {
// SAFETY: The entry is created with a live raw bucket, at the same time
// we have a &mut reference to the map, so it can not be modified further.
- Some(raw_bucket) => Entry::Occupied(OccupiedEntry {
+ Some(raw_bucket) => Ok(RawTableEntry {
map: self,
raw_bucket,
- key,
- }),
- None => Entry::Vacant(VacantEntry {
- map: self,
- hash,
- key,
}),
+ None => Err(self),
}
}
@@ -74,118 +98,56 @@ impl<K, V> IndexMapCore<K, V> {
// only the item references that are appropriately bound to `&mut self`.
unsafe { self.indices.iter().map(|bucket| bucket.as_mut()) }
}
-
- /// Return the raw bucket for the given index
- fn find_index(&self, index: usize) -> RawBucket {
- // We'll get a "nice" bounds-check from indexing `self.entries`,
- // and then we expect to find it in the table as well.
- let hash = self.entries[index].hash.get();
- self.indices
- .find(hash, move |&i| i == index)
- .expect("index not found")
- }
-
- pub(crate) fn swap_indices(&mut self, a: usize, b: usize) {
- // SAFETY: Can't take two `get_mut` references from one table, so we
- // must use raw buckets to do the swap. This is still safe because we
- // are locally sure they won't dangle, and we write them individually.
- unsafe {
- let raw_bucket_a = self.find_index(a);
- let raw_bucket_b = self.find_index(b);
- raw_bucket_a.write(b);
- raw_bucket_b.write(a);
- }
- self.entries.swap(a, b);
- }
}
-/// A view into an occupied entry in a `IndexMap`.
-/// It is part of the [`Entry`] enum.
-///
-/// [`Entry`]: enum.Entry.html
+/// A view into an occupied raw entry in an `IndexMap`.
// SAFETY: The lifetime of the map reference also constrains the raw bucket,
// which is essentially a raw pointer into the map indices.
-pub struct OccupiedEntry<'a, K, V> {
+pub(super) struct RawTableEntry<'a, K, V> {
map: &'a mut IndexMapCore<K, V>,
raw_bucket: RawBucket,
- key: K,
}
// `hashbrown::raw::Bucket` is only `Send`, not `Sync`.
// SAFETY: `&self` only accesses the bucket to read it.
-unsafe impl<K: Sync, V: Sync> Sync for OccupiedEntry<'_, K, V> {}
-
-// The parent module also adds methods that don't threaten the unsafe encapsulation.
-impl<'a, K, V> OccupiedEntry<'a, K, V> {
- /// Gets a reference to the entry's key in the map.
- ///
- /// Note that this is not the key that was used to find the entry. There may be an observable
- /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like
- /// extra fields or the memory address of an allocation.
- pub fn key(&self) -> &K {
- &self.map.entries[self.index()].key
- }
+unsafe impl<K: Sync, V: Sync> Sync for RawTableEntry<'_, K, V> {}
- /// Gets a reference to the entry's value in the map.
- pub fn get(&self) -> &V {
- &self.map.entries[self.index()].value
+impl<'a, K, V> RawTableEntry<'a, K, V> {
+ /// Return the index of the key-value pair
+ #[inline]
+ pub(super) fn index(&self) -> usize {
+ // SAFETY: we have `&mut map` keeping the bucket stable
+ unsafe { *self.raw_bucket.as_ref() }
}
- /// Gets a mutable reference to the entry's value in the map.
- ///
- /// If you need a reference which may outlive the destruction of the
- /// `Entry` value, see `into_mut`.
- pub fn get_mut(&mut self) -> &mut V {
- let index = self.index();
- &mut self.map.entries[index].value
+ #[inline]
+ pub(super) fn bucket(&self) -> &Bucket<K, V> {
+ &self.map.entries[self.index()]
}
- /// Put the new key in the occupied entry's key slot
- pub(crate) fn replace_key(self) -> K {
+ #[inline]
+ pub(super) fn bucket_mut(&mut self) -> &mut Bucket<K, V> {
let index = self.index();
- let old_key = &mut self.map.entries[index].key;
- replace(old_key, self.key)
+ &mut self.map.entries[index]
}
- /// Return the index of the key-value pair
#[inline]
- pub fn index(&self) -> usize {
- // SAFETY: we have &mut map keep keeping the bucket stable
- unsafe { self.raw_bucket.read() }
- }
-
- /// Converts into a mutable reference to the entry's value in the map,
- /// with a lifetime bound to the map itself.
- pub fn into_mut(self) -> &'a mut V {
+ pub(super) fn into_bucket(self) -> &'a mut Bucket<K, V> {
let index = self.index();
- &mut self.map.entries[index].value
+ &mut self.map.entries[index]
}
- /// Remove and return the key, value pair stored in the map for this entry
- ///
- /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
- /// last element of the map and popping it off. **This perturbs
- /// the position of what used to be the last element!**
- ///
- /// Computes in **O(1)** time (average).
- pub fn swap_remove_entry(self) -> (K, V) {
+ /// Remove the index from indices, leaving the actual entries to the caller.
+ pub(super) fn remove_index(self) -> (&'a mut IndexMapCore<K, V>, usize) {
// SAFETY: This is safe because it can only happen once (self is consumed)
// and map.indices have not been modified since entry construction
- let index = unsafe { self.map.indices.remove(self.raw_bucket) };
- self.map.swap_remove_finish(index)
+ let (index, _slot) = unsafe { self.map.indices.remove(self.raw_bucket) };
+ (self.map, index)
}
- /// Remove and return the key, value pair stored in the map for this entry
- ///
- /// Like `Vec::remove`, the pair is removed by shifting all of the
- /// elements that follow it, preserving their relative order.
- /// **This perturbs the index of all of those elements!**
- ///
- /// Computes in **O(n)** time (average).
- pub fn shift_remove_entry(self) -> (K, V) {
- // SAFETY: This is safe because it can only happen once (self is consumed)
- // and map.indices have not been modified since entry construction
- let index = unsafe { self.map.indices.remove(self.raw_bucket) };
- self.map.shift_remove_finish(index)
+ /// Take no action, just return the index and the original map reference.
+ pub(super) fn into_inner(self) -> (&'a mut IndexMapCore<K, V>, usize) {
+ let index = self.index();
+ (self.map, index)
}
}
diff --git a/third_party/rust/indexmap/src/map/core/raw_entry_v1.rs b/third_party/rust/indexmap/src/map/core/raw_entry_v1.rs
new file mode 100644
index 0000000000..87e532d557
--- /dev/null
+++ b/third_party/rust/indexmap/src/map/core/raw_entry_v1.rs
@@ -0,0 +1,652 @@
+//! Opt-in access to the experimental raw entry API.
+//!
+//! This module is designed to mimic the raw entry API of [`HashMap`][std::collections::hash_map],
+//! matching its unstable state as of Rust 1.75. See the tracking issue
+//! [rust#56167](https://github.com/rust-lang/rust/issues/56167) for more details.
+//!
+//! The trait [`RawEntryApiV1`] and the `_v1` suffix on its methods are meant to insulate this for
+//! the future, in case later breaking changes are needed. If the standard library stabilizes its
+//! `hash_raw_entry` feature (or some replacement), matching *inherent* methods will be added to
+//! `IndexMap` without such an opt-in trait.
+
+use super::raw::RawTableEntry;
+use super::IndexMapCore;
+use crate::{Equivalent, HashValue, IndexMap};
+use core::fmt;
+use core::hash::{BuildHasher, Hash, Hasher};
+use core::marker::PhantomData;
+use core::mem;
+
+/// Opt-in access to the experimental raw entry API.
+///
+/// See the [`raw_entry_v1`][self] module documentation for more information.
+pub trait RawEntryApiV1<K, V, S>: private::Sealed {
+ /// Creates a raw immutable entry builder for the [`IndexMap`].
+ ///
+ /// Raw entries provide the lowest level of control for searching and
+ /// manipulating a map. They must be manually initialized with a hash and
+ /// then manually searched.
+ ///
+ /// This is useful for
+ /// * Hash memoization
+ /// * Using a search key that doesn't work with the [`Equivalent`] trait
+ /// * Using custom comparison logic without newtype wrappers
+ ///
+ /// Unless you are in such a situation, higher-level and more foolproof APIs like
+ /// [`get`][IndexMap::get] should be preferred.
+ ///
+ /// Immutable raw entries have very limited use; you might instead want
+ /// [`raw_entry_mut_v1`][Self::raw_entry_mut_v1].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use core::hash::{BuildHasher, Hash};
+ /// use indexmap::map::{IndexMap, RawEntryApiV1};
+ ///
+ /// let mut map = IndexMap::new();
+ /// map.extend([("a", 100), ("b", 200), ("c", 300)]);
+ ///
+ /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
+ /// use core::hash::Hasher;
+ /// let mut state = hash_builder.build_hasher();
+ /// key.hash(&mut state);
+ /// state.finish()
+ /// }
+ ///
+ /// for k in ["a", "b", "c", "d", "e", "f"] {
+ /// let hash = compute_hash(map.hasher(), k);
+ /// let i = map.get_index_of(k);
+ /// let v = map.get(k);
+ /// let kv = map.get_key_value(k);
+ /// let ikv = map.get_full(k);
+ ///
+ /// println!("Key: {} and value: {:?}", k, v);
+ ///
+ /// assert_eq!(map.raw_entry_v1().from_key(k), kv);
+ /// assert_eq!(map.raw_entry_v1().from_hash(hash, |q| *q == k), kv);
+ /// assert_eq!(map.raw_entry_v1().from_key_hashed_nocheck(hash, k), kv);
+ /// assert_eq!(map.raw_entry_v1().from_hash_full(hash, |q| *q == k), ikv);
+ /// assert_eq!(map.raw_entry_v1().index_from_hash(hash, |q| *q == k), i);
+ /// }
+ /// ```
+ fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S>;
+
+ /// Creates a raw entry builder for the [`IndexMap`].
+ ///
+ /// Raw entries provide the lowest level of control for searching and
+ /// manipulating a map. They must be manually initialized with a hash and
+ /// then manually searched. After this, insertions into a vacant entry
+ /// still require an owned key to be provided.
+ ///
+ /// Raw entries are useful for such exotic situations as:
+ ///
+ /// * Hash memoization
+ /// * Deferring the creation of an owned key until it is known to be required
+ /// * Using a search key that doesn't work with the [`Equivalent`] trait
+ /// * Using custom comparison logic without newtype wrappers
+ ///
+ /// Because raw entries provide much more low-level control, it's much easier
+ /// to put the `IndexMap` into an inconsistent state which, while memory-safe,
+ /// will cause the map to produce seemingly random results. Higher-level and more
+ /// foolproof APIs like [`entry`][IndexMap::entry] should be preferred when possible.
+ ///
+ /// Raw entries give mutable access to the keys. This must not be used
+ /// to modify how the key would compare or hash, as the map will not re-evaluate
+ /// where the key should go, meaning the keys may become "lost" if their
+ /// location does not reflect their state. For instance, if you change a key
+ /// so that the map now contains keys which compare equal, search may start
+ /// acting erratically, with two keys randomly masking each other. Implementations
+ /// are free to assume this doesn't happen (within the limits of memory-safety).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use core::hash::{BuildHasher, Hash};
+ /// use indexmap::map::{IndexMap, RawEntryApiV1};
+ /// use indexmap::map::raw_entry_v1::RawEntryMut;
+ ///
+ /// let mut map = IndexMap::new();
+ /// map.extend([("a", 100), ("b", 200), ("c", 300)]);
+ ///
+ /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
+ /// use core::hash::Hasher;
+ /// let mut state = hash_builder.build_hasher();
+ /// key.hash(&mut state);
+ /// state.finish()
+ /// }
+ ///
+ /// // Existing key (insert and update)
+ /// match map.raw_entry_mut_v1().from_key("a") {
+ /// RawEntryMut::Vacant(_) => unreachable!(),
+ /// RawEntryMut::Occupied(mut view) => {
+ /// assert_eq!(view.index(), 0);
+ /// assert_eq!(view.get(), &100);
+ /// let v = view.get_mut();
+ /// let new_v = (*v) * 10;
+ /// *v = new_v;
+ /// assert_eq!(view.insert(1111), 1000);
+ /// }
+ /// }
+ ///
+ /// assert_eq!(map["a"], 1111);
+ /// assert_eq!(map.len(), 3);
+ ///
+ /// // Existing key (take)
+ /// let hash = compute_hash(map.hasher(), "c");
+ /// match map.raw_entry_mut_v1().from_key_hashed_nocheck(hash, "c") {
+ /// RawEntryMut::Vacant(_) => unreachable!(),
+ /// RawEntryMut::Occupied(view) => {
+ /// assert_eq!(view.index(), 2);
+ /// assert_eq!(view.shift_remove_entry(), ("c", 300));
+ /// }
+ /// }
+ /// assert_eq!(map.raw_entry_v1().from_key("c"), None);
+ /// assert_eq!(map.len(), 2);
+ ///
+ /// // Nonexistent key (insert and update)
+ /// let key = "d";
+ /// let hash = compute_hash(map.hasher(), key);
+ /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
+ /// RawEntryMut::Occupied(_) => unreachable!(),
+ /// RawEntryMut::Vacant(view) => {
+ /// assert_eq!(view.index(), 2);
+ /// let (k, value) = view.insert("d", 4000);
+ /// assert_eq!((*k, *value), ("d", 4000));
+ /// *value = 40000;
+ /// }
+ /// }
+ /// assert_eq!(map["d"], 40000);
+ /// assert_eq!(map.len(), 3);
+ ///
+ /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
+ /// RawEntryMut::Vacant(_) => unreachable!(),
+ /// RawEntryMut::Occupied(view) => {
+ /// assert_eq!(view.index(), 2);
+ /// assert_eq!(view.swap_remove_entry(), ("d", 40000));
+ /// }
+ /// }
+ /// assert_eq!(map.get("d"), None);
+ /// assert_eq!(map.len(), 2);
+ /// ```
+ fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S>;
+}
+
+impl<K, V, S> RawEntryApiV1<K, V, S> for IndexMap<K, V, S> {
+ fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S> {
+ RawEntryBuilder { map: self }
+ }
+
+ fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S> {
+ RawEntryBuilderMut { map: self }
+ }
+}
+
+/// A builder for computing where in an [`IndexMap`] a key-value pair would be stored.
+///
+/// This `struct` is created by the [`IndexMap::raw_entry_v1`] method, provided by the
+/// [`RawEntryApiV1`] trait. See its documentation for more.
+pub struct RawEntryBuilder<'a, K, V, S> {
+ map: &'a IndexMap<K, V, S>,
+}
+
+impl<K, V, S> fmt::Debug for RawEntryBuilder<'_, K, V, S> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("RawEntryBuilder").finish_non_exhaustive()
+ }
+}
+
+impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> {
+ /// Access an entry by key.
+ pub fn from_key<Q>(self, key: &Q) -> Option<(&'a K, &'a V)>
+ where
+ S: BuildHasher,
+ Q: ?Sized + Hash + Equivalent<K>,
+ {
+ self.map.get_key_value(key)
+ }
+
+ /// Access an entry by a key and its hash.
+ pub fn from_key_hashed_nocheck<Q>(self, hash: u64, key: &Q) -> Option<(&'a K, &'a V)>
+ where
+ Q: ?Sized + Equivalent<K>,
+ {
+ let hash = HashValue(hash as usize);
+ let i = self.map.core.get_index_of(hash, key)?;
+ self.map.get_index(i)
+ }
+
+ /// Access an entry by hash.
+ pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
+ where
+ F: FnMut(&K) -> bool,
+ {
+ let map = self.map;
+ let i = self.index_from_hash(hash, is_match)?;
+ map.get_index(i)
+ }
+
+ /// Access an entry by hash, including its index.
+ pub fn from_hash_full<F>(self, hash: u64, is_match: F) -> Option<(usize, &'a K, &'a V)>
+ where
+ F: FnMut(&K) -> bool,
+ {
+ let map = self.map;
+ let i = self.index_from_hash(hash, is_match)?;
+ let (key, value) = map.get_index(i)?;
+ Some((i, key, value))
+ }
+
+ /// Access the index of an entry by hash.
+ pub fn index_from_hash<F>(self, hash: u64, mut is_match: F) -> Option<usize>
+ where
+ F: FnMut(&K) -> bool,
+ {
+ let hash = HashValue(hash as usize);
+ let entries = &*self.map.core.entries;
+ let eq = move |&i: &usize| is_match(&entries[i].key);
+ self.map.core.indices.get(hash.get(), eq).copied()
+ }
+}
+
+/// A builder for computing where in an [`IndexMap`] a key-value pair would be stored.
+///
+/// This `struct` is created by the [`IndexMap::raw_entry_mut_v1`] method, provided by the
+/// [`RawEntryApiV1`] trait. See its documentation for more.
+pub struct RawEntryBuilderMut<'a, K, V, S> {
+ map: &'a mut IndexMap<K, V, S>,
+}
+
+impl<K, V, S> fmt::Debug for RawEntryBuilderMut<'_, K, V, S> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("RawEntryBuilderMut").finish_non_exhaustive()
+ }
+}
+
+impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> {
+ /// Access an entry by key.
+ pub fn from_key<Q>(self, key: &Q) -> RawEntryMut<'a, K, V, S>
+ where
+ S: BuildHasher,
+ Q: ?Sized + Hash + Equivalent<K>,
+ {
+ let hash = self.map.hash(key);
+ self.from_key_hashed_nocheck(hash.get(), key)
+ }
+
+ /// Access an entry by a key and its hash.
+ pub fn from_key_hashed_nocheck<Q>(self, hash: u64, key: &Q) -> RawEntryMut<'a, K, V, S>
+ where
+ Q: ?Sized + Equivalent<K>,
+ {
+ self.from_hash(hash, |k| Q::equivalent(key, k))
+ }
+
+ /// Access an entry by hash.
+ pub fn from_hash<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
+ where
+ F: FnMut(&K) -> bool,
+ {
+ let hash = HashValue(hash as usize);
+ match self.map.core.raw_entry(hash, is_match) {
+ Ok(raw) => RawEntryMut::Occupied(RawOccupiedEntryMut {
+ raw,
+ hash_builder: PhantomData,
+ }),
+ Err(map) => RawEntryMut::Vacant(RawVacantEntryMut {
+ map,
+ hash_builder: &self.map.hash_builder,
+ }),
+ }
+ }
+}
+
+/// Raw entry for an existing key-value pair or a vacant location to
+/// insert one.
+pub enum RawEntryMut<'a, K, V, S> {
+ /// Existing slot with equivalent key.
+ Occupied(RawOccupiedEntryMut<'a, K, V, S>),
+ /// Vacant slot (no equivalent key in the map).
+ Vacant(RawVacantEntryMut<'a, K, V, S>),
+}
+
+impl<K: fmt::Debug, V: fmt::Debug, S> fmt::Debug for RawEntryMut<'_, K, V, S> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut tuple = f.debug_tuple("RawEntryMut");
+ match self {
+ Self::Vacant(v) => tuple.field(v),
+ Self::Occupied(o) => tuple.field(o),
+ };
+ tuple.finish()
+ }
+}
+
+impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
+ /// Return the index where the key-value pair exists or may be inserted.
+ #[inline]
+ pub fn index(&self) -> usize {
+ match self {
+ Self::Occupied(entry) => entry.index(),
+ Self::Vacant(entry) => entry.index(),
+ }
+ }
+
+ /// Inserts the given default key and value in the entry if it is vacant and returns mutable
+ /// references to them. Otherwise mutable references to an already existent pair are returned.
+ pub fn or_insert(self, default_key: K, default_value: V) -> (&'a mut K, &'a mut V)
+ where
+ K: Hash,
+ S: BuildHasher,
+ {
+ match self {
+ Self::Occupied(entry) => entry.into_key_value_mut(),
+ Self::Vacant(entry) => entry.insert(default_key, default_value),
+ }
+ }
+
+ /// Inserts the result of the `call` function in the entry if it is vacant and returns mutable
+ /// references to them. Otherwise mutable references to an already existent pair are returned.
+ pub fn or_insert_with<F>(self, call: F) -> (&'a mut K, &'a mut V)
+ where
+ F: FnOnce() -> (K, V),
+ K: Hash,
+ S: BuildHasher,
+ {
+ match self {
+ Self::Occupied(entry) => entry.into_key_value_mut(),
+ Self::Vacant(entry) => {
+ let (key, value) = call();
+ entry.insert(key, value)
+ }
+ }
+ }
+
+ /// Modifies the entry if it is occupied.
+ pub fn and_modify<F>(mut self, f: F) -> Self
+ where
+ F: FnOnce(&mut K, &mut V),
+ {
+ if let Self::Occupied(entry) = &mut self {
+ let (k, v) = entry.get_key_value_mut();
+ f(k, v);
+ }
+ self
+ }
+}
+
+/// A raw view into an occupied entry in an [`IndexMap`].
+/// It is part of the [`RawEntryMut`] enum.
+pub struct RawOccupiedEntryMut<'a, K, V, S> {
+ raw: RawTableEntry<'a, K, V>,
+ hash_builder: PhantomData<&'a S>,
+}
+
+impl<K: fmt::Debug, V: fmt::Debug, S> fmt::Debug for RawOccupiedEntryMut<'_, K, V, S> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("RawOccupiedEntryMut")
+ .field("key", self.key())
+ .field("value", self.get())
+ .finish_non_exhaustive()
+ }
+}
+
+impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> {
+ /// Return the index of the key-value pair
+ #[inline]
+ pub fn index(&self) -> usize {
+ self.raw.index()
+ }
+
+ /// Gets a reference to the entry's key in the map.
+ ///
+ /// Note that this is not the key that was used to find the entry. There may be an observable
+ /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like
+ /// extra fields or the memory address of an allocation.
+ pub fn key(&self) -> &K {
+ &self.raw.bucket().key
+ }
+
+ /// Gets a mutable reference to the entry's key in the map.
+ ///
+ /// Note that this is not the key that was used to find the entry. There may be an observable
+ /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like
+ /// extra fields or the memory address of an allocation.
+ pub fn key_mut(&mut self) -> &mut K {
+ &mut self.raw.bucket_mut().key
+ }
+
+ /// Converts into a mutable reference to the entry's key in the map,
+ /// with a lifetime bound to the map itself.
+ ///
+ /// Note that this is not the key that was used to find the entry. There may be an observable
+ /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like
+ /// extra fields or the memory address of an allocation.
+ pub fn into_key(self) -> &'a mut K {
+ &mut self.raw.into_bucket().key
+ }
+
+ /// Gets a reference to the entry's value in the map.
+ pub fn get(&self) -> &V {
+ &self.raw.bucket().value
+ }
+
+ /// Gets a mutable reference to the entry's value in the map.
+ ///
+ /// If you need a reference which may outlive the destruction of the
+ /// [`RawEntryMut`] value, see [`into_mut`][Self::into_mut].
+ pub fn get_mut(&mut self) -> &mut V {
+ &mut self.raw.bucket_mut().value
+ }
+
+ /// Converts into a mutable reference to the entry's value in the map,
+ /// with a lifetime bound to the map itself.
+ pub fn into_mut(self) -> &'a mut V {
+ &mut self.raw.into_bucket().value
+ }
+
+ /// Gets a reference to the entry's key and value in the map.
+ pub fn get_key_value(&self) -> (&K, &V) {
+ self.raw.bucket().refs()
+ }
+
+ /// Gets a reference to the entry's key and value in the map.
+ pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) {
+ self.raw.bucket_mut().muts()
+ }
+
+ /// Converts into a mutable reference to the entry's key and value in the map,
+ /// with a lifetime bound to the map itself.
+ pub fn into_key_value_mut(self) -> (&'a mut K, &'a mut V) {
+ self.raw.into_bucket().muts()
+ }
+
+ /// Sets the value of the entry, and returns the entry's old value.
+ pub fn insert(&mut self, value: V) -> V {
+ mem::replace(self.get_mut(), value)
+ }
+
+ /// Sets the key of the entry, and returns the entry's old key.
+ pub fn insert_key(&mut self, key: K) -> K {
+ mem::replace(self.key_mut(), key)
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// **NOTE:** This is equivalent to [`.swap_remove()`][Self::swap_remove], replacing this
+ /// entry's position with the last element, and it is deprecated in favor of calling that
+ /// explicitly. If you need to preserve the relative order of the keys in the map, use
+ /// [`.shift_remove()`][Self::shift_remove] instead.
+ #[deprecated(note = "`remove` disrupts the map order -- \
+ use `swap_remove` or `shift_remove` for explicit behavior.")]
+ pub fn remove(self) -> V {
+ self.swap_remove()
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with
+ /// the last element of the map and popping it off.
+ /// **This perturbs the position of what used to be the last element!**
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_remove(self) -> V {
+ self.swap_remove_entry().1
+ }
+
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
+ ///
+ /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the
+ /// elements that follow it, preserving their relative order.
+ /// **This perturbs the index of all of those elements!**
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_remove(self) -> V {
+ self.shift_remove_entry().1
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// **NOTE:** This is equivalent to [`.swap_remove_entry()`][Self::swap_remove_entry],
+ /// replacing this entry's position with the last element, and it is deprecated in favor of
+ /// calling that explicitly. If you need to preserve the relative order of the keys in the map,
+ /// use [`.shift_remove_entry()`][Self::shift_remove_entry] instead.
+ #[deprecated(note = "`remove_entry` disrupts the map order -- \
+ use `swap_remove_entry` or `shift_remove_entry` for explicit behavior.")]
+ pub fn remove_entry(self) -> (K, V) {
+ self.swap_remove_entry()
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with
+ /// the last element of the map and popping it off.
+ /// **This perturbs the position of what used to be the last element!**
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_remove_entry(self) -> (K, V) {
+ let (map, index) = self.raw.remove_index();
+ map.swap_remove_finish(index)
+ }
+
+ /// Remove and return the key, value pair stored in the map for this entry
+ ///
+ /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the
+ /// elements that follow it, preserving their relative order.
+ /// **This perturbs the index of all of those elements!**
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_remove_entry(self) -> (K, V) {
+ let (map, index) = self.raw.remove_index();
+ map.shift_remove_finish(index)
+ }
+
+ /// Moves the position of the entry to a new index
+ /// by shifting all other entries in-between.
+ ///
+ /// This is equivalent to [`IndexMap::move_index`]
+ /// coming `from` the current [`.index()`][Self::index].
+ ///
+ /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up.
+ /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down.
+ ///
+ /// ***Panics*** if `to` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn move_index(self, to: usize) {
+ let (map, index) = self.raw.into_inner();
+ map.move_index(index, to);
+ }
+
+ /// Swaps the position of entry with another.
+ ///
+ /// This is equivalent to [`IndexMap::swap_indices`]
+ /// with the current [`.index()`][Self::index] as one of the two being swapped.
+ ///
+ /// ***Panics*** if the `other` index is out of bounds.
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn swap_indices(self, other: usize) {
+ let (map, index) = self.raw.into_inner();
+ map.swap_indices(index, other)
+ }
+}
+
+/// A view into a vacant raw entry in an [`IndexMap`].
+/// It is part of the [`RawEntryMut`] enum.
+pub struct RawVacantEntryMut<'a, K, V, S> {
+ map: &'a mut IndexMapCore<K, V>,
+ hash_builder: &'a S,
+}
+
+impl<K, V, S> fmt::Debug for RawVacantEntryMut<'_, K, V, S> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("RawVacantEntryMut").finish_non_exhaustive()
+ }
+}
+
+impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
+ /// Return the index where a key-value pair may be inserted.
+ pub fn index(&self) -> usize {
+ self.map.indices.len()
+ }
+
+ /// Inserts the given key and value into the map,
+ /// and returns mutable references to them.
+ pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V)
+ where
+ K: Hash,
+ S: BuildHasher,
+ {
+ let mut h = self.hash_builder.build_hasher();
+ key.hash(&mut h);
+ self.insert_hashed_nocheck(h.finish(), key, value)
+ }
+
+ /// Inserts the given key and value into the map with the provided hash,
+ /// and returns mutable references to them.
+ pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) {
+ let hash = HashValue(hash as usize);
+ let i = self.map.insert_unique(hash, key, value);
+ self.map.entries[i].muts()
+ }
+
+ /// Inserts the given key and value into the map at the given index,
+ /// shifting others to the right, and returns mutable references to them.
+ ///
+ /// ***Panics*** if `index` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_insert(self, index: usize, key: K, value: V) -> (&'a mut K, &'a mut V)
+ where
+ K: Hash,
+ S: BuildHasher,
+ {
+ let mut h = self.hash_builder.build_hasher();
+ key.hash(&mut h);
+ self.shift_insert_hashed_nocheck(index, h.finish(), key, value)
+ }
+
+ /// Inserts the given key and value into the map with the provided hash
+ /// at the given index, and returns mutable references to them.
+ ///
+ /// ***Panics*** if `index` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_insert_hashed_nocheck(
+ self,
+ index: usize,
+ hash: u64,
+ key: K,
+ value: V,
+ ) -> (&'a mut K, &'a mut V) {
+ let hash = HashValue(hash as usize);
+ self.map.shift_insert_unique(index, hash, key, value);
+ self.map.entries[index].muts()
+ }
+}
+
+mod private {
+ pub trait Sealed {}
+
+ impl<K, V, S> Sealed for super::IndexMap<K, V, S> {}
+}
diff --git a/third_party/rust/indexmap/src/map/iter.rs b/third_party/rust/indexmap/src/map/iter.rs
new file mode 100644
index 0000000000..1ec3703cfb
--- /dev/null
+++ b/third_party/rust/indexmap/src/map/iter.rs
@@ -0,0 +1,713 @@
+use super::core::IndexMapCore;
+use super::{Bucket, Entries, IndexMap, Slice};
+
+use alloc::vec::{self, Vec};
+use core::fmt;
+use core::hash::{BuildHasher, Hash};
+use core::iter::FusedIterator;
+use core::ops::{Index, RangeBounds};
+use core::slice;
+
+impl<'a, K, V, S> IntoIterator for &'a IndexMap<K, V, S> {
+ type Item = (&'a K, &'a V);
+ type IntoIter = Iter<'a, K, V>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a, K, V, S> IntoIterator for &'a mut IndexMap<K, V, S> {
+ type Item = (&'a K, &'a mut V);
+ type IntoIter = IterMut<'a, K, V>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter_mut()
+ }
+}
+
+impl<K, V, S> IntoIterator for IndexMap<K, V, S> {
+ type Item = (K, V);
+ type IntoIter = IntoIter<K, V>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ IntoIter::new(self.into_entries())
+ }
+}
+
+/// An iterator over the entries of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::iter`] method.
+/// See its documentation for more.
+pub struct Iter<'a, K, V> {
+ iter: slice::Iter<'a, Bucket<K, V>>,
+}
+
+impl<'a, K, V> Iter<'a, K, V> {
+ pub(super) fn new(entries: &'a [Bucket<K, V>]) -> Self {
+ Self {
+ iter: entries.iter(),
+ }
+ }
+
+ /// Returns a slice of the remaining entries in the iterator.
+ pub fn as_slice(&self) -> &'a Slice<K, V> {
+ Slice::from_slice(self.iter.as_slice())
+ }
+}
+
+impl<'a, K, V> Iterator for Iter<'a, K, V> {
+ type Item = (&'a K, &'a V);
+
+ iterator_methods!(Bucket::refs);
+}
+
+impl<K, V> DoubleEndedIterator for Iter<'_, K, V> {
+ double_ended_iterator_methods!(Bucket::refs);
+}
+
+impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for Iter<'_, K, V> {}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+impl<K, V> Clone for Iter<'_, K, V> {
+ fn clone(&self) -> Self {
+ Iter {
+ iter: self.iter.clone(),
+ }
+ }
+}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+impl<K, V> Default for Iter<'_, K, V> {
+ fn default() -> Self {
+ Self { iter: [].iter() }
+ }
+}
+
+/// A mutable iterator over the entries of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::iter_mut`] method.
+/// See its documentation for more.
+pub struct IterMut<'a, K, V> {
+ iter: slice::IterMut<'a, Bucket<K, V>>,
+}
+
+impl<'a, K, V> IterMut<'a, K, V> {
+ pub(super) fn new(entries: &'a mut [Bucket<K, V>]) -> Self {
+ Self {
+ iter: entries.iter_mut(),
+ }
+ }
+
+ /// Returns a slice of the remaining entries in the iterator.
+ pub fn as_slice(&self) -> &Slice<K, V> {
+ Slice::from_slice(self.iter.as_slice())
+ }
+
+ /// Returns a mutable slice of the remaining entries in the iterator.
+ ///
+ /// To avoid creating `&mut` references that alias, this is forced to consume the iterator.
+ pub fn into_slice(self) -> &'a mut Slice<K, V> {
+ Slice::from_mut_slice(self.iter.into_slice())
+ }
+}
+
+impl<'a, K, V> Iterator for IterMut<'a, K, V> {
+ type Item = (&'a K, &'a mut V);
+
+ iterator_methods!(Bucket::ref_mut);
+}
+
+impl<K, V> DoubleEndedIterator for IterMut<'_, K, V> {
+ double_ended_iterator_methods!(Bucket::ref_mut);
+}
+
+impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for IterMut<'_, K, V> {}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::refs);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+impl<K, V> Default for IterMut<'_, K, V> {
+ fn default() -> Self {
+ Self {
+ iter: [].iter_mut(),
+ }
+ }
+}
+
+/// An owning iterator over the entries of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::into_iter`] method
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
+pub struct IntoIter<K, V> {
+ iter: vec::IntoIter<Bucket<K, V>>,
+}
+
+impl<K, V> IntoIter<K, V> {
+ pub(super) fn new(entries: Vec<Bucket<K, V>>) -> Self {
+ Self {
+ iter: entries.into_iter(),
+ }
+ }
+
+ /// Returns a slice of the remaining entries in the iterator.
+ pub fn as_slice(&self) -> &Slice<K, V> {
+ Slice::from_slice(self.iter.as_slice())
+ }
+
+ /// Returns a mutable slice of the remaining entries in the iterator.
+ pub fn as_mut_slice(&mut self) -> &mut Slice<K, V> {
+ Slice::from_mut_slice(self.iter.as_mut_slice())
+ }
+}
+
+impl<K, V> Iterator for IntoIter<K, V> {
+ type Item = (K, V);
+
+ iterator_methods!(Bucket::key_value);
+}
+
+impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
+ double_ended_iterator_methods!(Bucket::key_value);
+}
+
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for IntoIter<K, V> {}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::refs);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+impl<K, V> Default for IntoIter<K, V> {
+ fn default() -> Self {
+ Self {
+ iter: Vec::new().into_iter(),
+ }
+ }
+}
+
+/// A draining iterator over the entries of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::drain`] method.
+/// See its documentation for more.
+pub struct Drain<'a, K, V> {
+ iter: vec::Drain<'a, Bucket<K, V>>,
+}
+
+impl<'a, K, V> Drain<'a, K, V> {
+ pub(super) fn new(iter: vec::Drain<'a, Bucket<K, V>>) -> Self {
+ Self { iter }
+ }
+
+ /// Returns a slice of the remaining entries in the iterator.
+ pub fn as_slice(&self) -> &Slice<K, V> {
+ Slice::from_slice(self.iter.as_slice())
+ }
+}
+
+impl<K, V> Iterator for Drain<'_, K, V> {
+ type Item = (K, V);
+
+ iterator_methods!(Bucket::key_value);
+}
+
+impl<K, V> DoubleEndedIterator for Drain<'_, K, V> {
+ double_ended_iterator_methods!(Bucket::key_value);
+}
+
+impl<K, V> ExactSizeIterator for Drain<'_, K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for Drain<'_, K, V> {}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Drain<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::refs);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+/// An iterator over the keys of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::keys`] method.
+/// See its documentation for more.
+pub struct Keys<'a, K, V> {
+ iter: slice::Iter<'a, Bucket<K, V>>,
+}
+
+impl<'a, K, V> Keys<'a, K, V> {
+ pub(super) fn new(entries: &'a [Bucket<K, V>]) -> Self {
+ Self {
+ iter: entries.iter(),
+ }
+ }
+}
+
+impl<'a, K, V> Iterator for Keys<'a, K, V> {
+ type Item = &'a K;
+
+ iterator_methods!(Bucket::key_ref);
+}
+
+impl<K, V> DoubleEndedIterator for Keys<'_, K, V> {
+ double_ended_iterator_methods!(Bucket::key_ref);
+}
+
+impl<K, V> ExactSizeIterator for Keys<'_, K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for Keys<'_, K, V> {}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+impl<K, V> Clone for Keys<'_, K, V> {
+ fn clone(&self) -> Self {
+ Keys {
+ iter: self.iter.clone(),
+ }
+ }
+}
+
+impl<K: fmt::Debug, V> fmt::Debug for Keys<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+impl<K, V> Default for Keys<'_, K, V> {
+ fn default() -> Self {
+ Self { iter: [].iter() }
+ }
+}
+
+/// Access [`IndexMap`] keys at indexed positions.
+///
+/// While [`Index<usize> for IndexMap`][values] accesses a map's values,
+/// indexing through [`IndexMap::keys`] offers an alternative to access a map's
+/// keys instead.
+///
+/// [values]: IndexMap#impl-Index<usize>-for-IndexMap<K,+V,+S>
+///
+/// Since `Keys` is also an iterator, consuming items from the iterator will
+/// offset the effective indexes. Similarly, if `Keys` is obtained from
+/// [`Slice::keys`], indexes will be interpreted relative to the position of
+/// that slice.
+///
+/// # Examples
+///
+/// ```
+/// use indexmap::IndexMap;
+///
+/// let mut map = IndexMap::new();
+/// for word in "Lorem ipsum dolor sit amet".split_whitespace() {
+/// map.insert(word.to_lowercase(), word.to_uppercase());
+/// }
+///
+/// assert_eq!(map[0], "LOREM");
+/// assert_eq!(map.keys()[0], "lorem");
+/// assert_eq!(map[1], "IPSUM");
+/// assert_eq!(map.keys()[1], "ipsum");
+///
+/// map.reverse();
+/// assert_eq!(map.keys()[0], "amet");
+/// assert_eq!(map.keys()[1], "sit");
+///
+/// map.sort_keys();
+/// assert_eq!(map.keys()[0], "amet");
+/// assert_eq!(map.keys()[1], "dolor");
+///
+/// // Advancing the iterator will offset the indexing
+/// let mut keys = map.keys();
+/// assert_eq!(keys[0], "amet");
+/// assert_eq!(keys.next().map(|s| &**s), Some("amet"));
+/// assert_eq!(keys[0], "dolor");
+/// assert_eq!(keys[1], "ipsum");
+///
+/// // Slices may have an offset as well
+/// let slice = &map[2..];
+/// assert_eq!(slice[0], "IPSUM");
+/// assert_eq!(slice.keys()[0], "ipsum");
+/// ```
+///
+/// ```should_panic
+/// use indexmap::IndexMap;
+///
+/// let mut map = IndexMap::new();
+/// map.insert("foo", 1);
+/// println!("{:?}", map.keys()[10]); // panics!
+/// ```
+impl<'a, K, V> Index<usize> for Keys<'a, K, V> {
+ type Output = K;
+
+ /// Returns a reference to the key at the supplied `index`.
+ ///
+ /// ***Panics*** if `index` is out of bounds.
+ fn index(&self, index: usize) -> &K {
+ &self.iter.as_slice()[index].key
+ }
+}
+
+/// An owning iterator over the keys of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::into_keys`] method.
+/// See its documentation for more.
+pub struct IntoKeys<K, V> {
+ iter: vec::IntoIter<Bucket<K, V>>,
+}
+
+impl<K, V> IntoKeys<K, V> {
+ pub(super) fn new(entries: Vec<Bucket<K, V>>) -> Self {
+ Self {
+ iter: entries.into_iter(),
+ }
+ }
+}
+
+impl<K, V> Iterator for IntoKeys<K, V> {
+ type Item = K;
+
+ iterator_methods!(Bucket::key);
+}
+
+impl<K, V> DoubleEndedIterator for IntoKeys<K, V> {
+ double_ended_iterator_methods!(Bucket::key);
+}
+
+impl<K, V> ExactSizeIterator for IntoKeys<K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for IntoKeys<K, V> {}
+
+impl<K: fmt::Debug, V> fmt::Debug for IntoKeys<K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::key_ref);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+impl<K, V> Default for IntoKeys<K, V> {
+ fn default() -> Self {
+ Self {
+ iter: Vec::new().into_iter(),
+ }
+ }
+}
+
+/// An iterator over the values of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::values`] method.
+/// See its documentation for more.
+pub struct Values<'a, K, V> {
+ iter: slice::Iter<'a, Bucket<K, V>>,
+}
+
+impl<'a, K, V> Values<'a, K, V> {
+ pub(super) fn new(entries: &'a [Bucket<K, V>]) -> Self {
+ Self {
+ iter: entries.iter(),
+ }
+ }
+}
+
+impl<'a, K, V> Iterator for Values<'a, K, V> {
+ type Item = &'a V;
+
+ iterator_methods!(Bucket::value_ref);
+}
+
+impl<K, V> DoubleEndedIterator for Values<'_, K, V> {
+ double_ended_iterator_methods!(Bucket::value_ref);
+}
+
+impl<K, V> ExactSizeIterator for Values<'_, K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for Values<'_, K, V> {}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+impl<K, V> Clone for Values<'_, K, V> {
+ fn clone(&self) -> Self {
+ Values {
+ iter: self.iter.clone(),
+ }
+ }
+}
+
+impl<K, V: fmt::Debug> fmt::Debug for Values<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+impl<K, V> Default for Values<'_, K, V> {
+ fn default() -> Self {
+ Self { iter: [].iter() }
+ }
+}
+
+/// A mutable iterator over the values of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::values_mut`] method.
+/// See its documentation for more.
+pub struct ValuesMut<'a, K, V> {
+ iter: slice::IterMut<'a, Bucket<K, V>>,
+}
+
+impl<'a, K, V> ValuesMut<'a, K, V> {
+ pub(super) fn new(entries: &'a mut [Bucket<K, V>]) -> Self {
+ Self {
+ iter: entries.iter_mut(),
+ }
+ }
+}
+
+impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
+ type Item = &'a mut V;
+
+ iterator_methods!(Bucket::value_mut);
+}
+
+impl<K, V> DoubleEndedIterator for ValuesMut<'_, K, V> {
+ double_ended_iterator_methods!(Bucket::value_mut);
+}
+
+impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
+
+impl<K, V: fmt::Debug> fmt::Debug for ValuesMut<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::value_ref);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+impl<K, V> Default for ValuesMut<'_, K, V> {
+ fn default() -> Self {
+ Self {
+ iter: [].iter_mut(),
+ }
+ }
+}
+
+/// An owning iterator over the values of an [`IndexMap`].
+///
+/// This `struct` is created by the [`IndexMap::into_values`] method.
+/// See its documentation for more.
+pub struct IntoValues<K, V> {
+ iter: vec::IntoIter<Bucket<K, V>>,
+}
+
+impl<K, V> IntoValues<K, V> {
+ pub(super) fn new(entries: Vec<Bucket<K, V>>) -> Self {
+ Self {
+ iter: entries.into_iter(),
+ }
+ }
+}
+
+impl<K, V> Iterator for IntoValues<K, V> {
+ type Item = V;
+
+ iterator_methods!(Bucket::value);
+}
+
+impl<K, V> DoubleEndedIterator for IntoValues<K, V> {
+ double_ended_iterator_methods!(Bucket::value);
+}
+
+impl<K, V> ExactSizeIterator for IntoValues<K, V> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<K, V> FusedIterator for IntoValues<K, V> {}
+
+impl<K, V: fmt::Debug> fmt::Debug for IntoValues<K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::value_ref);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+impl<K, V> Default for IntoValues<K, V> {
+ fn default() -> Self {
+ Self {
+ iter: Vec::new().into_iter(),
+ }
+ }
+}
+
+/// A splicing iterator for `IndexMap`.
+///
+/// This `struct` is created by [`IndexMap::splice()`].
+/// See its documentation for more.
+pub struct Splice<'a, I, K, V, S>
+where
+ I: Iterator<Item = (K, V)>,
+ K: Hash + Eq,
+ S: BuildHasher,
+{
+ map: &'a mut IndexMap<K, V, S>,
+ tail: IndexMapCore<K, V>,
+ drain: vec::IntoIter<Bucket<K, V>>,
+ replace_with: I,
+}
+
+impl<'a, I, K, V, S> Splice<'a, I, K, V, S>
+where
+ I: Iterator<Item = (K, V)>,
+ K: Hash + Eq,
+ S: BuildHasher,
+{
+ pub(super) fn new<R>(map: &'a mut IndexMap<K, V, S>, range: R, replace_with: I) -> Self
+ where
+ R: RangeBounds<usize>,
+ {
+ let (tail, drain) = map.core.split_splice(range);
+ Self {
+ map,
+ tail,
+ drain,
+ replace_with,
+ }
+ }
+}
+
+impl<I, K, V, S> Drop for Splice<'_, I, K, V, S>
+where
+ I: Iterator<Item = (K, V)>,
+ K: Hash + Eq,
+ S: BuildHasher,
+{
+ fn drop(&mut self) {
+ // Finish draining unconsumed items. We don't strictly *have* to do this
+ // manually, since we already split it into separate memory, but it will
+ // match the drop order of `vec::Splice` items this way.
+ let _ = self.drain.nth(usize::MAX);
+
+ // Now insert all the new items. If a key matches an existing entry, it
+ // keeps the original position and only replaces the value, like `insert`.
+ while let Some((key, value)) = self.replace_with.next() {
+ // Since the tail is disjoint, we can try to update it first,
+ // or else insert (update or append) the primary map.
+ let hash = self.map.hash(&key);
+ if let Some(i) = self.tail.get_index_of(hash, &key) {
+ self.tail.as_entries_mut()[i].value = value;
+ } else {
+ self.map.core.insert_full(hash, key, value);
+ }
+ }
+
+ // Finally, re-append the tail
+ self.map.core.append_unchecked(&mut self.tail);
+ }
+}
+
+impl<I, K, V, S> Iterator for Splice<'_, I, K, V, S>
+where
+ I: Iterator<Item = (K, V)>,
+ K: Hash + Eq,
+ S: BuildHasher,
+{
+ type Item = (K, V);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.drain.next().map(Bucket::key_value)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.drain.size_hint()
+ }
+}
+
+impl<I, K, V, S> DoubleEndedIterator for Splice<'_, I, K, V, S>
+where
+ I: Iterator<Item = (K, V)>,
+ K: Hash + Eq,
+ S: BuildHasher,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.drain.next_back().map(Bucket::key_value)
+ }
+}
+
+impl<I, K, V, S> ExactSizeIterator for Splice<'_, I, K, V, S>
+where
+ I: Iterator<Item = (K, V)>,
+ K: Hash + Eq,
+ S: BuildHasher,
+{
+ fn len(&self) -> usize {
+ self.drain.len()
+ }
+}
+
+impl<I, K, V, S> FusedIterator for Splice<'_, I, K, V, S>
+where
+ I: Iterator<Item = (K, V)>,
+ K: Hash + Eq,
+ S: BuildHasher,
+{
+}
+
+impl<'a, I, K, V, S> fmt::Debug for Splice<'a, I, K, V, S>
+where
+ I: fmt::Debug + Iterator<Item = (K, V)>,
+ K: fmt::Debug + Hash + Eq,
+ V: fmt::Debug,
+ S: BuildHasher,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Follow `vec::Splice` in only printing the drain and replacement
+ f.debug_struct("Splice")
+ .field("drain", &self.drain)
+ .field("replace_with", &self.replace_with)
+ .finish()
+ }
+}
diff --git a/third_party/rust/indexmap/src/map/mutable.rs b/third_party/rust/indexmap/src/map/mutable.rs
new file mode 100644
index 0000000000..7df325948f
--- /dev/null
+++ b/third_party/rust/indexmap/src/map/mutable.rs
@@ -0,0 +1,87 @@
+use core::hash::{BuildHasher, Hash};
+
+use super::{Bucket, Entries, Equivalent, IndexMap};
+
+/// Opt-in mutable access to [`IndexMap`] keys.
+///
+/// These methods expose `&mut K`, mutable references to the key as it is stored
+/// in the map.
+/// You are allowed to modify the keys in the map **if the modification
+/// does not change the key’s hash and equality**.
+///
+/// If keys are modified erroneously, you can no longer look them up.
+/// This is sound (memory safe) but a logical error hazard (just like
+/// implementing `PartialEq`, `Eq`, or `Hash` incorrectly would be).
+///
+/// `use` this trait to enable its methods for `IndexMap`.
+///
+/// This trait is sealed and cannot be implemented for types outside this crate.
+pub trait MutableKeys: private::Sealed {
+ type Key;
+ type Value;
+
+ /// Return item index, mutable reference to key and value
+ ///
+ /// Computes in **O(1)** time (average).
+ fn get_full_mut2<Q>(&mut self, key: &Q) -> Option<(usize, &mut Self::Key, &mut Self::Value)>
+ where
+ Q: ?Sized + Hash + Equivalent<Self::Key>;
+
+ /// Return mutable reference to key and value at an index.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ ///
+ /// Computes in **O(1)** time.
+ fn get_index_mut2(&mut self, index: usize) -> Option<(&mut Self::Key, &mut Self::Value)>;
+
+ /// Scan through each key-value pair in the map and keep those where the
+ /// closure `keep` returns `true`.
+ ///
+ /// The elements are visited in order, and remaining elements keep their
+ /// order.
+ ///
+ /// Computes in **O(n)** time (average).
+ fn retain2<F>(&mut self, keep: F)
+ where
+ F: FnMut(&mut Self::Key, &mut Self::Value) -> bool;
+}
+
+/// Opt-in mutable access to [`IndexMap`] keys.
+///
+/// See [`MutableKeys`] for more information.
+impl<K, V, S> MutableKeys for IndexMap<K, V, S>
+where
+ S: BuildHasher,
+{
+ type Key = K;
+ type Value = V;
+
+ fn get_full_mut2<Q>(&mut self, key: &Q) -> Option<(usize, &mut K, &mut V)>
+ where
+ Q: ?Sized + Hash + Equivalent<K>,
+ {
+ if let Some(i) = self.get_index_of(key) {
+ let entry = &mut self.as_entries_mut()[i];
+ Some((i, &mut entry.key, &mut entry.value))
+ } else {
+ None
+ }
+ }
+
+ fn get_index_mut2(&mut self, index: usize) -> Option<(&mut K, &mut V)> {
+ self.as_entries_mut().get_mut(index).map(Bucket::muts)
+ }
+
+ fn retain2<F>(&mut self, keep: F)
+ where
+ F: FnMut(&mut K, &mut V) -> bool,
+ {
+ self.core.retain_in_order(keep);
+ }
+}
+
+mod private {
+ pub trait Sealed {}
+
+ impl<K, V, S> Sealed for super::IndexMap<K, V, S> {}
+}
diff --git a/third_party/rust/indexmap/src/map/serde_seq.rs b/third_party/rust/indexmap/src/map/serde_seq.rs
new file mode 100644
index 0000000000..602ae7dc74
--- /dev/null
+++ b/third_party/rust/indexmap/src/map/serde_seq.rs
@@ -0,0 +1,138 @@
+//! Functions to serialize and deserialize an [`IndexMap`] as an ordered sequence.
+//!
+//! The default `serde` implementation serializes `IndexMap` as a normal map,
+//! but there is no guarantee that serialization formats will preserve the order
+//! of the key-value pairs. This module serializes `IndexMap` as a sequence of
+//! `(key, value)` elements instead, in order.
+//!
+//! This module may be used in a field attribute for derived implementations:
+//!
+//! ```
+//! # use indexmap::IndexMap;
+//! # use serde_derive::{Deserialize, Serialize};
+//! #[derive(Deserialize, Serialize)]
+//! struct Data {
+//! #[serde(with = "indexmap::map::serde_seq")]
+//! map: IndexMap<i32, u64>,
+//! // ...
+//! }
+//! ```
+
+use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
+use serde::ser::{Serialize, Serializer};
+
+use core::fmt::{self, Formatter};
+use core::hash::{BuildHasher, Hash};
+use core::marker::PhantomData;
+
+use crate::map::Slice as MapSlice;
+use crate::serde::cautious_capacity;
+use crate::set::Slice as SetSlice;
+use crate::IndexMap;
+
+/// Serializes a [`map::Slice`][MapSlice] as an ordered sequence.
+///
+/// This behaves like [`crate::map::serde_seq`] for `IndexMap`, serializing a sequence
+/// of `(key, value)` pairs, rather than as a map that might not preserve order.
+impl<K, V> Serialize for MapSlice<K, V>
+where
+ K: Serialize,
+ V: Serialize,
+{
+ fn serialize<T>(&self, serializer: T) -> Result<T::Ok, T::Error>
+ where
+ T: Serializer,
+ {
+ serializer.collect_seq(self)
+ }
+}
+
+/// Serializes a [`set::Slice`][SetSlice] as an ordered sequence.
+impl<T> Serialize for SetSlice<T>
+where
+ T: Serialize,
+{
+ fn serialize<Se>(&self, serializer: Se) -> Result<Se::Ok, Se::Error>
+ where
+ Se: Serializer,
+ {
+ serializer.collect_seq(self)
+ }
+}
+
+/// Serializes an [`IndexMap`] as an ordered sequence.
+///
+/// This function may be used in a field attribute for deriving [`Serialize`]:
+///
+/// ```
+/// # use indexmap::IndexMap;
+/// # use serde_derive::Serialize;
+/// #[derive(Serialize)]
+/// struct Data {
+/// #[serde(serialize_with = "indexmap::map::serde_seq::serialize")]
+/// map: IndexMap<i32, u64>,
+/// // ...
+/// }
+/// ```
+pub fn serialize<K, V, S, T>(map: &IndexMap<K, V, S>, serializer: T) -> Result<T::Ok, T::Error>
+where
+ K: Serialize,
+ V: Serialize,
+ T: Serializer,
+{
+ serializer.collect_seq(map)
+}
+
+/// Visitor to deserialize a *sequenced* `IndexMap`
+struct SeqVisitor<K, V, S>(PhantomData<(K, V, S)>);
+
+impl<'de, K, V, S> Visitor<'de> for SeqVisitor<K, V, S>
+where
+ K: Deserialize<'de> + Eq + Hash,
+ V: Deserialize<'de>,
+ S: Default + BuildHasher,
+{
+ type Value = IndexMap<K, V, S>;
+
+ fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
+ write!(formatter, "a sequenced map")
+ }
+
+ fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+ where
+ A: SeqAccess<'de>,
+ {
+ let capacity = cautious_capacity::<K, V>(seq.size_hint());
+ let mut map = IndexMap::with_capacity_and_hasher(capacity, S::default());
+
+ while let Some((key, value)) = seq.next_element()? {
+ map.insert(key, value);
+ }
+
+ Ok(map)
+ }
+}
+
+/// Deserializes an [`IndexMap`] from an ordered sequence.
+///
+/// This function may be used in a field attribute for deriving [`Deserialize`]:
+///
+/// ```
+/// # use indexmap::IndexMap;
+/// # use serde_derive::Deserialize;
+/// #[derive(Deserialize)]
+/// struct Data {
+/// #[serde(deserialize_with = "indexmap::map::serde_seq::deserialize")]
+/// map: IndexMap<i32, u64>,
+/// // ...
+/// }
+/// ```
+pub fn deserialize<'de, D, K, V, S>(deserializer: D) -> Result<IndexMap<K, V, S>, D::Error>
+where
+ D: Deserializer<'de>,
+ K: Deserialize<'de> + Eq + Hash,
+ V: Deserialize<'de>,
+ S: Default + BuildHasher,
+{
+ deserializer.deserialize_seq(SeqVisitor(PhantomData))
+}
diff --git a/third_party/rust/indexmap/src/map/slice.rs b/third_party/rust/indexmap/src/map/slice.rs
new file mode 100644
index 0000000000..b2f00f4807
--- /dev/null
+++ b/third_party/rust/indexmap/src/map/slice.rs
@@ -0,0 +1,539 @@
+use super::{
+ Bucket, Entries, IndexMap, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values,
+ ValuesMut,
+};
+use crate::util::try_simplify_range;
+
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::cmp::Ordering;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ops::{self, Bound, Index, IndexMut, RangeBounds};
+
+/// A dynamically-sized slice of key-value pairs in an [`IndexMap`].
+///
+/// This supports indexed operations much like a `[(K, V)]` slice,
+/// but not any hashed operations on the map keys.
+///
+/// Unlike `IndexMap`, `Slice` does consider the order for [`PartialEq`]
+/// and [`Eq`], and it also implements [`PartialOrd`], [`Ord`], and [`Hash`].
+#[repr(transparent)]
+pub struct Slice<K, V> {
+ pub(crate) entries: [Bucket<K, V>],
+}
+
+// SAFETY: `Slice<K, V>` is a transparent wrapper around `[Bucket<K, V>]`,
+// and reference lifetimes are bound together in function signatures.
+#[allow(unsafe_code)]
+impl<K, V> Slice<K, V> {
+ pub(super) const fn from_slice(entries: &[Bucket<K, V>]) -> &Self {
+ unsafe { &*(entries as *const [Bucket<K, V>] as *const Self) }
+ }
+
+ pub(super) fn from_mut_slice(entries: &mut [Bucket<K, V>]) -> &mut Self {
+ unsafe { &mut *(entries as *mut [Bucket<K, V>] as *mut Self) }
+ }
+
+ pub(super) fn from_boxed(entries: Box<[Bucket<K, V>]>) -> Box<Self> {
+ unsafe { Box::from_raw(Box::into_raw(entries) as *mut Self) }
+ }
+
+ fn into_boxed(self: Box<Self>) -> Box<[Bucket<K, V>]> {
+ unsafe { Box::from_raw(Box::into_raw(self) as *mut [Bucket<K, V>]) }
+ }
+}
+
+impl<K, V> Slice<K, V> {
+ pub(crate) fn into_entries(self: Box<Self>) -> Vec<Bucket<K, V>> {
+ self.into_boxed().into_vec()
+ }
+
+ /// Returns an empty slice.
+ pub const fn new<'a>() -> &'a Self {
+ Self::from_slice(&[])
+ }
+
+ /// Returns an empty mutable slice.
+ pub fn new_mut<'a>() -> &'a mut Self {
+ Self::from_mut_slice(&mut [])
+ }
+
+ /// Return the number of key-value pairs in the map slice.
+ #[inline]
+ pub const fn len(&self) -> usize {
+ self.entries.len()
+ }
+
+ /// Returns true if the map slice contains no elements.
+ #[inline]
+ pub const fn is_empty(&self) -> bool {
+ self.entries.is_empty()
+ }
+
+ /// Get a key-value pair by index.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ pub fn get_index(&self, index: usize) -> Option<(&K, &V)> {
+ self.entries.get(index).map(Bucket::refs)
+ }
+
+ /// Get a key-value pair by index, with mutable access to the value.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ pub fn get_index_mut(&mut self, index: usize) -> Option<(&K, &mut V)> {
+ self.entries.get_mut(index).map(Bucket::ref_mut)
+ }
+
+ /// Returns a slice of key-value pairs in the given range of indices.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self> {
+ let range = try_simplify_range(range, self.entries.len())?;
+ self.entries.get(range).map(Slice::from_slice)
+ }
+
+ /// Returns a mutable slice of key-value pairs in the given range of indices.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ pub fn get_range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Self> {
+ let range = try_simplify_range(range, self.entries.len())?;
+ self.entries.get_mut(range).map(Slice::from_mut_slice)
+ }
+
+ /// Get the first key-value pair.
+ pub fn first(&self) -> Option<(&K, &V)> {
+ self.entries.first().map(Bucket::refs)
+ }
+
+ /// Get the first key-value pair, with mutable access to the value.
+ pub fn first_mut(&mut self) -> Option<(&K, &mut V)> {
+ self.entries.first_mut().map(Bucket::ref_mut)
+ }
+
+ /// Get the last key-value pair.
+ pub fn last(&self) -> Option<(&K, &V)> {
+ self.entries.last().map(Bucket::refs)
+ }
+
+ /// Get the last key-value pair, with mutable access to the value.
+ pub fn last_mut(&mut self) -> Option<(&K, &mut V)> {
+ self.entries.last_mut().map(Bucket::ref_mut)
+ }
+
+ /// Divides one slice into two at an index.
+ ///
+ /// ***Panics*** if `index > len`.
+ pub fn split_at(&self, index: usize) -> (&Self, &Self) {
+ let (first, second) = self.entries.split_at(index);
+ (Self::from_slice(first), Self::from_slice(second))
+ }
+
+ /// Divides one mutable slice into two at an index.
+ ///
+ /// ***Panics*** if `index > len`.
+ pub fn split_at_mut(&mut self, index: usize) -> (&mut Self, &mut Self) {
+ let (first, second) = self.entries.split_at_mut(index);
+ (Self::from_mut_slice(first), Self::from_mut_slice(second))
+ }
+
+ /// Returns the first key-value pair and the rest of the slice,
+ /// or `None` if it is empty.
+ pub fn split_first(&self) -> Option<((&K, &V), &Self)> {
+ if let [first, rest @ ..] = &self.entries {
+ Some((first.refs(), Self::from_slice(rest)))
+ } else {
+ None
+ }
+ }
+
+ /// Returns the first key-value pair and the rest of the slice,
+ /// with mutable access to the value, or `None` if it is empty.
+ pub fn split_first_mut(&mut self) -> Option<((&K, &mut V), &mut Self)> {
+ if let [first, rest @ ..] = &mut self.entries {
+ Some((first.ref_mut(), Self::from_mut_slice(rest)))
+ } else {
+ None
+ }
+ }
+
+ /// Returns the last key-value pair and the rest of the slice,
+ /// or `None` if it is empty.
+ pub fn split_last(&self) -> Option<((&K, &V), &Self)> {
+ if let [rest @ .., last] = &self.entries {
+ Some((last.refs(), Self::from_slice(rest)))
+ } else {
+ None
+ }
+ }
+
+ /// Returns the last key-value pair and the rest of the slice,
+ /// with mutable access to the value, or `None` if it is empty.
+ pub fn split_last_mut(&mut self) -> Option<((&K, &mut V), &mut Self)> {
+ if let [rest @ .., last] = &mut self.entries {
+ Some((last.ref_mut(), Self::from_mut_slice(rest)))
+ } else {
+ None
+ }
+ }
+
+ /// Return an iterator over the key-value pairs of the map slice.
+ pub fn iter(&self) -> Iter<'_, K, V> {
+ Iter::new(&self.entries)
+ }
+
+ /// Return an iterator over the key-value pairs of the map slice.
+ pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
+ IterMut::new(&mut self.entries)
+ }
+
+ /// Return an iterator over the keys of the map slice.
+ pub fn keys(&self) -> Keys<'_, K, V> {
+ Keys::new(&self.entries)
+ }
+
+ /// Return an owning iterator over the keys of the map slice.
+ pub fn into_keys(self: Box<Self>) -> IntoKeys<K, V> {
+ IntoKeys::new(self.into_entries())
+ }
+
+ /// Return an iterator over the values of the map slice.
+ pub fn values(&self) -> Values<'_, K, V> {
+ Values::new(&self.entries)
+ }
+
+ /// Return an iterator over mutable references to the the values of the map slice.
+ pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
+ ValuesMut::new(&mut self.entries)
+ }
+
+ /// Return an owning iterator over the values of the map slice.
+ pub fn into_values(self: Box<Self>) -> IntoValues<K, V> {
+ IntoValues::new(self.into_entries())
+ }
+
+ /// Search over a sorted map for a key.
+ ///
+ /// Returns the position where that key is present, or the position where it can be inserted to
+ /// maintain the sort. See [`slice::binary_search`] for more details.
+ ///
+ /// Computes in **O(log(n))** time, which is notably less scalable than looking the key up in
+ /// the map this is a slice from using [`IndexMap::get_index_of`], but this can also position
+ /// missing keys.
+ pub fn binary_search_keys(&self, x: &K) -> Result<usize, usize>
+ where
+ K: Ord,
+ {
+ self.binary_search_by(|p, _| p.cmp(x))
+ }
+
+ /// Search over a sorted map with a comparator function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a K, &'a V) -> Ordering,
+ {
+ self.entries.binary_search_by(move |a| f(&a.key, &a.value))
+ }
+
+ /// Search over a sorted map with an extraction function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by_key`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a K, &'a V) -> B,
+ B: Ord,
+ {
+ self.binary_search_by(|k, v| f(k, v).cmp(b))
+ }
+
+ /// Returns the index of the partition point of a sorted map according to the given predicate
+ /// (the index of the first element of the second partition).
+ ///
+ /// See [`slice::partition_point`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[must_use]
+ pub fn partition_point<P>(&self, mut pred: P) -> usize
+ where
+ P: FnMut(&K, &V) -> bool,
+ {
+ self.entries
+ .partition_point(move |a| pred(&a.key, &a.value))
+ }
+}
+
+impl<'a, K, V> IntoIterator for &'a Slice<K, V> {
+ type IntoIter = Iter<'a, K, V>;
+ type Item = (&'a K, &'a V);
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a, K, V> IntoIterator for &'a mut Slice<K, V> {
+ type IntoIter = IterMut<'a, K, V>;
+ type Item = (&'a K, &'a mut V);
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter_mut()
+ }
+}
+
+impl<K, V> IntoIterator for Box<Slice<K, V>> {
+ type IntoIter = IntoIter<K, V>;
+ type Item = (K, V);
+
+ fn into_iter(self) -> Self::IntoIter {
+ IntoIter::new(self.into_entries())
+ }
+}
+
+impl<K, V> Default for &'_ Slice<K, V> {
+ fn default() -> Self {
+ Slice::from_slice(&[])
+ }
+}
+
+impl<K, V> Default for &'_ mut Slice<K, V> {
+ fn default() -> Self {
+ Slice::from_mut_slice(&mut [])
+ }
+}
+
+impl<K, V> Default for Box<Slice<K, V>> {
+ fn default() -> Self {
+ Slice::from_boxed(Box::default())
+ }
+}
+
+impl<K: Clone, V: Clone> Clone for Box<Slice<K, V>> {
+ fn clone(&self) -> Self {
+ Slice::from_boxed(self.entries.to_vec().into_boxed_slice())
+ }
+}
+
+impl<K: Copy, V: Copy> From<&Slice<K, V>> for Box<Slice<K, V>> {
+ fn from(slice: &Slice<K, V>) -> Self {
+ Slice::from_boxed(Box::from(&slice.entries))
+ }
+}
+
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Slice<K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self).finish()
+ }
+}
+
+impl<K: PartialEq, V: PartialEq> PartialEq for Slice<K, V> {
+ fn eq(&self, other: &Self) -> bool {
+ self.len() == other.len() && self.iter().eq(other)
+ }
+}
+
+impl<K: Eq, V: Eq> Eq for Slice<K, V> {}
+
+impl<K: PartialOrd, V: PartialOrd> PartialOrd for Slice<K, V> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.iter().partial_cmp(other)
+ }
+}
+
+impl<K: Ord, V: Ord> Ord for Slice<K, V> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.iter().cmp(other)
+ }
+}
+
+impl<K: Hash, V: Hash> Hash for Slice<K, V> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.len().hash(state);
+ for (key, value) in self {
+ key.hash(state);
+ value.hash(state);
+ }
+ }
+}
+
+impl<K, V> Index<usize> for Slice<K, V> {
+ type Output = V;
+
+ fn index(&self, index: usize) -> &V {
+ &self.entries[index].value
+ }
+}
+
+impl<K, V> IndexMut<usize> for Slice<K, V> {
+ fn index_mut(&mut self, index: usize) -> &mut V {
+ &mut self.entries[index].value
+ }
+}
+
+// We can't have `impl<I: RangeBounds<usize>> Index<I>` because that conflicts
+// both upstream with `Index<usize>` and downstream with `Index<&Q>`.
+// Instead, we repeat the implementations for all the core range types.
+macro_rules! impl_index {
+ ($($range:ty),*) => {$(
+ impl<K, V, S> Index<$range> for IndexMap<K, V, S> {
+ type Output = Slice<K, V>;
+
+ fn index(&self, range: $range) -> &Self::Output {
+ Slice::from_slice(&self.as_entries()[range])
+ }
+ }
+
+ impl<K, V, S> IndexMut<$range> for IndexMap<K, V, S> {
+ fn index_mut(&mut self, range: $range) -> &mut Self::Output {
+ Slice::from_mut_slice(&mut self.as_entries_mut()[range])
+ }
+ }
+
+ impl<K, V> Index<$range> for Slice<K, V> {
+ type Output = Slice<K, V>;
+
+ fn index(&self, range: $range) -> &Self {
+ Self::from_slice(&self.entries[range])
+ }
+ }
+
+ impl<K, V> IndexMut<$range> for Slice<K, V> {
+ fn index_mut(&mut self, range: $range) -> &mut Self {
+ Self::from_mut_slice(&mut self.entries[range])
+ }
+ }
+ )*}
+}
+impl_index!(
+ ops::Range<usize>,
+ ops::RangeFrom<usize>,
+ ops::RangeFull,
+ ops::RangeInclusive<usize>,
+ ops::RangeTo<usize>,
+ ops::RangeToInclusive<usize>,
+ (Bound<usize>, Bound<usize>)
+);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn slice_index() {
+ fn check(
+ vec_slice: &[(i32, i32)],
+ map_slice: &Slice<i32, i32>,
+ sub_slice: &Slice<i32, i32>,
+ ) {
+ assert_eq!(map_slice as *const _, sub_slice as *const _);
+ itertools::assert_equal(
+ vec_slice.iter().copied(),
+ map_slice.iter().map(|(&k, &v)| (k, v)),
+ );
+ itertools::assert_equal(vec_slice.iter().map(|(k, _)| k), map_slice.keys());
+ itertools::assert_equal(vec_slice.iter().map(|(_, v)| v), map_slice.values());
+ }
+
+ let vec: Vec<(i32, i32)> = (0..10).map(|i| (i, i * i)).collect();
+ let map: IndexMap<i32, i32> = vec.iter().cloned().collect();
+ let slice = map.as_slice();
+
+ // RangeFull
+ check(&vec[..], &map[..], &slice[..]);
+
+ for i in 0usize..10 {
+ // Index
+ assert_eq!(vec[i].1, map[i]);
+ assert_eq!(vec[i].1, slice[i]);
+ assert_eq!(map[&(i as i32)], map[i]);
+ assert_eq!(map[&(i as i32)], slice[i]);
+
+ // RangeFrom
+ check(&vec[i..], &map[i..], &slice[i..]);
+
+ // RangeTo
+ check(&vec[..i], &map[..i], &slice[..i]);
+
+ // RangeToInclusive
+ check(&vec[..=i], &map[..=i], &slice[..=i]);
+
+ // (Bound<usize>, Bound<usize>)
+ let bounds = (Bound::Excluded(i), Bound::Unbounded);
+ check(&vec[i + 1..], &map[bounds], &slice[bounds]);
+
+ for j in i..=10 {
+ // Range
+ check(&vec[i..j], &map[i..j], &slice[i..j]);
+ }
+
+ for j in i..10 {
+ // RangeInclusive
+ check(&vec[i..=j], &map[i..=j], &slice[i..=j]);
+ }
+ }
+ }
+
+ #[test]
+ fn slice_index_mut() {
+ fn check_mut(
+ vec_slice: &[(i32, i32)],
+ map_slice: &mut Slice<i32, i32>,
+ sub_slice: &mut Slice<i32, i32>,
+ ) {
+ assert_eq!(map_slice, sub_slice);
+ itertools::assert_equal(
+ vec_slice.iter().copied(),
+ map_slice.iter_mut().map(|(&k, &mut v)| (k, v)),
+ );
+ itertools::assert_equal(
+ vec_slice.iter().map(|&(_, v)| v),
+ map_slice.values_mut().map(|&mut v| v),
+ );
+ }
+
+ let vec: Vec<(i32, i32)> = (0..10).map(|i| (i, i * i)).collect();
+ let mut map: IndexMap<i32, i32> = vec.iter().cloned().collect();
+ let mut map2 = map.clone();
+ let slice = map2.as_mut_slice();
+
+ // RangeFull
+ check_mut(&vec[..], &mut map[..], &mut slice[..]);
+
+ for i in 0usize..10 {
+ // IndexMut
+ assert_eq!(&mut map[i], &mut slice[i]);
+
+ // RangeFrom
+ check_mut(&vec[i..], &mut map[i..], &mut slice[i..]);
+
+ // RangeTo
+ check_mut(&vec[..i], &mut map[..i], &mut slice[..i]);
+
+ // RangeToInclusive
+ check_mut(&vec[..=i], &mut map[..=i], &mut slice[..=i]);
+
+ // (Bound<usize>, Bound<usize>)
+ let bounds = (Bound::Excluded(i), Bound::Unbounded);
+ check_mut(&vec[i + 1..], &mut map[bounds], &mut slice[bounds]);
+
+ for j in i..=10 {
+ // Range
+ check_mut(&vec[i..j], &mut map[i..j], &mut slice[i..j]);
+ }
+
+ for j in i..10 {
+ // RangeInclusive
+ check_mut(&vec[i..=j], &mut map[i..=j], &mut slice[i..=j]);
+ }
+ }
+ }
+}
diff --git a/third_party/rust/indexmap/src/map/tests.rs b/third_party/rust/indexmap/src/map/tests.rs
new file mode 100644
index 0000000000..bba78ff54c
--- /dev/null
+++ b/third_party/rust/indexmap/src/map/tests.rs
@@ -0,0 +1,727 @@
+use super::*;
+use std::string::String;
+
+#[test]
+fn it_works() {
+ let mut map = IndexMap::new();
+ assert_eq!(map.is_empty(), true);
+ map.insert(1, ());
+ map.insert(1, ());
+ assert_eq!(map.len(), 1);
+ assert!(map.get(&1).is_some());
+ assert_eq!(map.is_empty(), false);
+}
+
+#[test]
+fn new() {
+ let map = IndexMap::<String, String>::new();
+ println!("{:?}", map);
+ assert_eq!(map.capacity(), 0);
+ assert_eq!(map.len(), 0);
+ assert_eq!(map.is_empty(), true);
+}
+
+#[test]
+fn insert() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5];
+ let not_present = [1, 3, 6, 9, 10];
+ let mut map = IndexMap::with_capacity(insert.len());
+
+ for (i, &elt) in insert.iter().enumerate() {
+ assert_eq!(map.len(), i);
+ map.insert(elt, elt);
+ assert_eq!(map.len(), i + 1);
+ assert_eq!(map.get(&elt), Some(&elt));
+ assert_eq!(map[&elt], elt);
+ }
+ println!("{:?}", map);
+
+ for &elt in &not_present {
+ assert!(map.get(&elt).is_none());
+ }
+}
+
+#[test]
+fn insert_full() {
+ let insert = vec![9, 2, 7, 1, 4, 6, 13];
+ let present = vec![1, 6, 2];
+ let mut map = IndexMap::with_capacity(insert.len());
+
+ for (i, &elt) in insert.iter().enumerate() {
+ assert_eq!(map.len(), i);
+ let (index, existing) = map.insert_full(elt, elt);
+ assert_eq!(existing, None);
+ assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0));
+ assert_eq!(map.len(), i + 1);
+ }
+
+ let len = map.len();
+ for &elt in &present {
+ let (index, existing) = map.insert_full(elt, elt);
+ assert_eq!(existing, Some(elt));
+ assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0));
+ assert_eq!(map.len(), len);
+ }
+}
+
+#[test]
+fn insert_2() {
+ let mut map = IndexMap::with_capacity(16);
+
+ let mut keys = vec![];
+ keys.extend(0..16);
+ keys.extend(if cfg!(miri) { 32..64 } else { 128..267 });
+
+ for &i in &keys {
+ let old_map = map.clone();
+ map.insert(i, ());
+ for key in old_map.keys() {
+ if map.get(key).is_none() {
+ println!("old_map: {:?}", old_map);
+ println!("map: {:?}", map);
+ panic!("did not find {} in map", key);
+ }
+ }
+ }
+
+ for &i in &keys {
+ assert!(map.get(&i).is_some(), "did not find {}", i);
+ }
+}
+
+#[test]
+fn insert_order() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut map = IndexMap::new();
+
+ for &elt in &insert {
+ map.insert(elt, ());
+ }
+
+ assert_eq!(map.keys().count(), map.len());
+ assert_eq!(map.keys().count(), insert.len());
+ for (a, b) in insert.iter().zip(map.keys()) {
+ assert_eq!(a, b);
+ }
+ for (i, k) in (0..insert.len()).zip(map.keys()) {
+ assert_eq!(map.get_index(i).unwrap().0, k);
+ }
+}
+
+#[test]
+fn shift_insert() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut map = IndexMap::new();
+
+ for &elt in &insert {
+ map.shift_insert(0, elt, ());
+ }
+
+ assert_eq!(map.keys().count(), map.len());
+ assert_eq!(map.keys().count(), insert.len());
+ for (a, b) in insert.iter().rev().zip(map.keys()) {
+ assert_eq!(a, b);
+ }
+ for (i, k) in (0..insert.len()).zip(map.keys()) {
+ assert_eq!(map.get_index(i).unwrap().0, k);
+ }
+
+ // "insert" that moves an existing entry
+ map.shift_insert(0, insert[0], ());
+ assert_eq!(map.keys().count(), insert.len());
+ assert_eq!(insert[0], map.keys()[0]);
+ for (a, b) in insert[1..].iter().rev().zip(map.keys().skip(1)) {
+ assert_eq!(a, b);
+ }
+}
+
+#[test]
+fn grow() {
+ let insert = [0, 4, 2, 12, 8, 7, 11];
+ let not_present = [1, 3, 6, 9, 10];
+ let mut map = IndexMap::with_capacity(insert.len());
+
+ for (i, &elt) in insert.iter().enumerate() {
+ assert_eq!(map.len(), i);
+ map.insert(elt, elt);
+ assert_eq!(map.len(), i + 1);
+ assert_eq!(map.get(&elt), Some(&elt));
+ assert_eq!(map[&elt], elt);
+ }
+
+ println!("{:?}", map);
+ for &elt in &insert {
+ map.insert(elt * 10, elt);
+ }
+ for &elt in &insert {
+ map.insert(elt * 100, elt);
+ }
+ for (i, &elt) in insert.iter().cycle().enumerate().take(100) {
+ map.insert(elt * 100 + i as i32, elt);
+ }
+ println!("{:?}", map);
+ for &elt in &not_present {
+ assert!(map.get(&elt).is_none());
+ }
+}
+
+#[test]
+fn reserve() {
+ let mut map = IndexMap::<usize, usize>::new();
+ assert_eq!(map.capacity(), 0);
+ map.reserve(100);
+ let capacity = map.capacity();
+ assert!(capacity >= 100);
+ for i in 0..capacity {
+ assert_eq!(map.len(), i);
+ map.insert(i, i * i);
+ assert_eq!(map.len(), i + 1);
+ assert_eq!(map.capacity(), capacity);
+ assert_eq!(map.get(&i), Some(&(i * i)));
+ }
+ map.insert(capacity, std::usize::MAX);
+ assert_eq!(map.len(), capacity + 1);
+ assert!(map.capacity() > capacity);
+ assert_eq!(map.get(&capacity), Some(&std::usize::MAX));
+}
+
+#[test]
+fn try_reserve() {
+ let mut map = IndexMap::<usize, usize>::new();
+ assert_eq!(map.capacity(), 0);
+ assert_eq!(map.try_reserve(100), Ok(()));
+ assert!(map.capacity() >= 100);
+ assert!(map.try_reserve(usize::MAX).is_err());
+}
+
+#[test]
+fn shrink_to_fit() {
+ let mut map = IndexMap::<usize, usize>::new();
+ assert_eq!(map.capacity(), 0);
+ for i in 0..100 {
+ assert_eq!(map.len(), i);
+ map.insert(i, i * i);
+ assert_eq!(map.len(), i + 1);
+ assert!(map.capacity() >= i + 1);
+ assert_eq!(map.get(&i), Some(&(i * i)));
+ map.shrink_to_fit();
+ assert_eq!(map.len(), i + 1);
+ assert_eq!(map.capacity(), i + 1);
+ assert_eq!(map.get(&i), Some(&(i * i)));
+ }
+}
+
+#[test]
+fn remove() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut map = IndexMap::new();
+
+ for &elt in &insert {
+ map.insert(elt, elt);
+ }
+
+ assert_eq!(map.keys().count(), map.len());
+ assert_eq!(map.keys().count(), insert.len());
+ for (a, b) in insert.iter().zip(map.keys()) {
+ assert_eq!(a, b);
+ }
+
+ let remove_fail = [99, 77];
+ let remove = [4, 12, 8, 7];
+
+ for &key in &remove_fail {
+ assert!(map.swap_remove_full(&key).is_none());
+ }
+ println!("{:?}", map);
+ for &key in &remove {
+ //println!("{:?}", map);
+ let index = map.get_full(&key).unwrap().0;
+ assert_eq!(map.swap_remove_full(&key), Some((index, key, key)));
+ }
+ println!("{:?}", map);
+
+ for key in &insert {
+ assert_eq!(map.get(key).is_some(), !remove.contains(key));
+ }
+ assert_eq!(map.len(), insert.len() - remove.len());
+ assert_eq!(map.keys().count(), insert.len() - remove.len());
+}
+
+#[test]
+fn remove_to_empty() {
+ let mut map = indexmap! { 0 => 0, 4 => 4, 5 => 5 };
+ map.swap_remove(&5).unwrap();
+ map.swap_remove(&4).unwrap();
+ map.swap_remove(&0).unwrap();
+ assert!(map.is_empty());
+}
+
+#[test]
+fn swap_remove_index() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut map = IndexMap::new();
+
+ for &elt in &insert {
+ map.insert(elt, elt * 2);
+ }
+
+ let mut vector = insert.to_vec();
+ let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1];
+
+ // check that the same swap remove sequence on vec and map
+ // have the same result.
+ for &rm in remove_sequence {
+ let out_vec = vector.swap_remove(rm);
+ let (out_map, _) = map.swap_remove_index(rm).unwrap();
+ assert_eq!(out_vec, out_map);
+ }
+ assert_eq!(vector.len(), map.len());
+ for (a, b) in vector.iter().zip(map.keys()) {
+ assert_eq!(a, b);
+ }
+}
+
+#[test]
+fn partial_eq_and_eq() {
+ let mut map_a = IndexMap::new();
+ map_a.insert(1, "1");
+ map_a.insert(2, "2");
+ let mut map_b = map_a.clone();
+ assert_eq!(map_a, map_b);
+ map_b.swap_remove(&1);
+ assert_ne!(map_a, map_b);
+
+ let map_c: IndexMap<_, String> = map_b.into_iter().map(|(k, v)| (k, v.into())).collect();
+ assert_ne!(map_a, map_c);
+ assert_ne!(map_c, map_a);
+}
+
+#[test]
+fn extend() {
+ let mut map = IndexMap::new();
+ map.extend(vec![(&1, &2), (&3, &4)]);
+ map.extend(vec![(5, 6)]);
+ assert_eq!(
+ map.into_iter().collect::<Vec<_>>(),
+ vec![(1, 2), (3, 4), (5, 6)]
+ );
+}
+
+#[test]
+fn entry() {
+ let mut map = IndexMap::new();
+
+ map.insert(1, "1");
+ map.insert(2, "2");
+ {
+ let e = map.entry(3);
+ assert_eq!(e.index(), 2);
+ let e = e.or_insert("3");
+ assert_eq!(e, &"3");
+ }
+
+ let e = map.entry(2);
+ assert_eq!(e.index(), 1);
+ assert_eq!(e.key(), &2);
+ match e {
+ Entry::Occupied(ref e) => assert_eq!(e.get(), &"2"),
+ Entry::Vacant(_) => panic!(),
+ }
+ assert_eq!(e.or_insert("4"), &"2");
+}
+
+#[test]
+fn entry_and_modify() {
+ let mut map = IndexMap::new();
+
+ map.insert(1, "1");
+ map.entry(1).and_modify(|x| *x = "2");
+ assert_eq!(Some(&"2"), map.get(&1));
+
+ map.entry(2).and_modify(|x| *x = "doesn't exist");
+ assert_eq!(None, map.get(&2));
+}
+
+#[test]
+fn entry_or_default() {
+ let mut map = IndexMap::new();
+
+ #[derive(Debug, PartialEq)]
+ enum TestEnum {
+ DefaultValue,
+ NonDefaultValue,
+ }
+
+ impl Default for TestEnum {
+ fn default() -> Self {
+ TestEnum::DefaultValue
+ }
+ }
+
+ map.insert(1, TestEnum::NonDefaultValue);
+ assert_eq!(&mut TestEnum::NonDefaultValue, map.entry(1).or_default());
+
+ assert_eq!(&mut TestEnum::DefaultValue, map.entry(2).or_default());
+}
+
+#[test]
+fn occupied_entry_key() {
+ // These keys match hash and equality, but their addresses are distinct.
+ let (k1, k2) = (&mut 1, &mut 1);
+ let k1_ptr = k1 as *const i32;
+ let k2_ptr = k2 as *const i32;
+ assert_ne!(k1_ptr, k2_ptr);
+
+ let mut map = IndexMap::new();
+ map.insert(k1, "value");
+ match map.entry(k2) {
+ Entry::Occupied(ref e) => {
+ // `OccupiedEntry::key` should reference the key in the map,
+ // not the key that was used to find the entry.
+ let ptr = *e.key() as *const i32;
+ assert_eq!(ptr, k1_ptr);
+ assert_ne!(ptr, k2_ptr);
+ }
+ Entry::Vacant(_) => panic!(),
+ }
+}
+
+#[test]
+fn get_index_entry() {
+ let mut map = IndexMap::new();
+
+ assert!(map.get_index_entry(0).is_none());
+
+ map.insert(0, "0");
+ map.insert(1, "1");
+ map.insert(2, "2");
+ map.insert(3, "3");
+
+ assert!(map.get_index_entry(4).is_none());
+
+ {
+ let e = map.get_index_entry(1).unwrap();
+ assert_eq!(*e.key(), 1);
+ assert_eq!(*e.get(), "1");
+ assert_eq!(e.swap_remove(), "1");
+ }
+
+ {
+ let mut e = map.get_index_entry(1).unwrap();
+ assert_eq!(*e.key(), 3);
+ assert_eq!(*e.get(), "3");
+ assert_eq!(e.insert("4"), "3");
+ }
+
+ assert_eq!(*map.get(&3).unwrap(), "4");
+}
+
+#[test]
+fn keys() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: IndexMap<_, _> = vec.into_iter().collect();
+ let keys: Vec<_> = map.keys().copied().collect();
+ assert_eq!(keys.len(), 3);
+ assert!(keys.contains(&1));
+ assert!(keys.contains(&2));
+ assert!(keys.contains(&3));
+}
+
+#[test]
+fn into_keys() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: IndexMap<_, _> = vec.into_iter().collect();
+ let keys: Vec<i32> = map.into_keys().collect();
+ assert_eq!(keys.len(), 3);
+ assert!(keys.contains(&1));
+ assert!(keys.contains(&2));
+ assert!(keys.contains(&3));
+}
+
+#[test]
+fn values() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: IndexMap<_, _> = vec.into_iter().collect();
+ let values: Vec<_> = map.values().copied().collect();
+ assert_eq!(values.len(), 3);
+ assert!(values.contains(&'a'));
+ assert!(values.contains(&'b'));
+ assert!(values.contains(&'c'));
+}
+
+#[test]
+fn values_mut() {
+ let vec = vec![(1, 1), (2, 2), (3, 3)];
+ let mut map: IndexMap<_, _> = vec.into_iter().collect();
+ for value in map.values_mut() {
+ *value *= 2
+ }
+ let values: Vec<_> = map.values().copied().collect();
+ assert_eq!(values.len(), 3);
+ assert!(values.contains(&2));
+ assert!(values.contains(&4));
+ assert!(values.contains(&6));
+}
+
+#[test]
+fn into_values() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: IndexMap<_, _> = vec.into_iter().collect();
+ let values: Vec<char> = map.into_values().collect();
+ assert_eq!(values.len(), 3);
+ assert!(values.contains(&'a'));
+ assert!(values.contains(&'b'));
+ assert!(values.contains(&'c'));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn from_array() {
+ let map = IndexMap::from([(1, 2), (3, 4)]);
+ let mut expected = IndexMap::new();
+ expected.insert(1, 2);
+ expected.insert(3, 4);
+
+ assert_eq!(map, expected)
+}
+
+#[test]
+fn iter_default() {
+ struct K;
+ struct V;
+ fn assert_default<T>()
+ where
+ T: Default + Iterator,
+ {
+ assert!(T::default().next().is_none());
+ }
+ assert_default::<Iter<'static, K, V>>();
+ assert_default::<IterMut<'static, K, V>>();
+ assert_default::<IntoIter<K, V>>();
+ assert_default::<Keys<'static, K, V>>();
+ assert_default::<IntoKeys<K, V>>();
+ assert_default::<Values<'static, K, V>>();
+ assert_default::<ValuesMut<'static, K, V>>();
+ assert_default::<IntoValues<K, V>>();
+}
+
+#[test]
+fn test_binary_search_by() {
+ // adapted from std's test for binary_search
+ let b: IndexMap<_, i32> = []
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&5)), Err(0));
+
+ let b: IndexMap<_, i32> = [4]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&3)), Err(0));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&4)), Ok(0));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&5)), Err(1));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 6, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&5)), Err(3));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&6)), Ok(3));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&7)), Err(4));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&8)), Ok(4));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 5, 6, 8]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&9)), Err(6));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 6, 7, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&6)), Ok(3));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&5)), Err(3));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&8)), Ok(5));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 5, 6, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&7)), Err(5));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&0)), Err(0));
+
+ let b: IndexMap<_, i32> = [1, 3, 3, 3, 7]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&0)), Err(0));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&1)), Ok(0));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&2)), Err(1));
+ assert!(match b.binary_search_by(|_, x| x.cmp(&3)) {
+ Ok(1..=3) => true,
+ _ => false,
+ });
+ assert!(match b.binary_search_by(|_, x| x.cmp(&3)) {
+ Ok(1..=3) => true,
+ _ => false,
+ });
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&4)), Err(4));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&5)), Err(4));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&6)), Err(4));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&7)), Ok(4));
+ assert_eq!(b.binary_search_by(|_, x| x.cmp(&8)), Err(5));
+}
+
+#[test]
+fn test_binary_search_by_key() {
+ // adapted from std's test for binary_search
+ let b: IndexMap<_, i32> = []
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by_key(&5, |_, &x| x), Err(0));
+
+ let b: IndexMap<_, i32> = [4]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by_key(&3, |_, &x| x), Err(0));
+ assert_eq!(b.binary_search_by_key(&4, |_, &x| x), Ok(0));
+ assert_eq!(b.binary_search_by_key(&5, |_, &x| x), Err(1));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 6, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by_key(&5, |_, &x| x), Err(3));
+ assert_eq!(b.binary_search_by_key(&6, |_, &x| x), Ok(3));
+ assert_eq!(b.binary_search_by_key(&7, |_, &x| x), Err(4));
+ assert_eq!(b.binary_search_by_key(&8, |_, &x| x), Ok(4));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 5, 6, 8]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by_key(&9, |_, &x| x), Err(6));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 6, 7, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by_key(&6, |_, &x| x), Ok(3));
+ assert_eq!(b.binary_search_by_key(&5, |_, &x| x), Err(3));
+ assert_eq!(b.binary_search_by_key(&8, |_, &x| x), Ok(5));
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 5, 6, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by_key(&7, |_, &x| x), Err(5));
+ assert_eq!(b.binary_search_by_key(&0, |_, &x| x), Err(0));
+
+ let b: IndexMap<_, i32> = [1, 3, 3, 3, 7]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.binary_search_by_key(&0, |_, &x| x), Err(0));
+ assert_eq!(b.binary_search_by_key(&1, |_, &x| x), Ok(0));
+ assert_eq!(b.binary_search_by_key(&2, |_, &x| x), Err(1));
+ assert!(match b.binary_search_by_key(&3, |_, &x| x) {
+ Ok(1..=3) => true,
+ _ => false,
+ });
+ assert!(match b.binary_search_by_key(&3, |_, &x| x) {
+ Ok(1..=3) => true,
+ _ => false,
+ });
+ assert_eq!(b.binary_search_by_key(&4, |_, &x| x), Err(4));
+ assert_eq!(b.binary_search_by_key(&5, |_, &x| x), Err(4));
+ assert_eq!(b.binary_search_by_key(&6, |_, &x| x), Err(4));
+ assert_eq!(b.binary_search_by_key(&7, |_, &x| x), Ok(4));
+ assert_eq!(b.binary_search_by_key(&8, |_, &x| x), Err(5));
+}
+
+#[test]
+fn test_partition_point() {
+ // adapted from std's test for partition_point
+ let b: IndexMap<_, i32> = []
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.partition_point(|_, &x| x < 5), 0);
+
+ let b: IndexMap<_, i32> = [4]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.partition_point(|_, &x| x < 3), 0);
+ assert_eq!(b.partition_point(|_, &x| x < 4), 0);
+ assert_eq!(b.partition_point(|_, &x| x < 5), 1);
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 6, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.partition_point(|_, &x| x < 5), 3);
+ assert_eq!(b.partition_point(|_, &x| x < 6), 3);
+ assert_eq!(b.partition_point(|_, &x| x < 7), 4);
+ assert_eq!(b.partition_point(|_, &x| x < 8), 4);
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 5, 6, 8]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.partition_point(|_, &x| x < 9), 6);
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 6, 7, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.partition_point(|_, &x| x < 6), 3);
+ assert_eq!(b.partition_point(|_, &x| x < 5), 3);
+ assert_eq!(b.partition_point(|_, &x| x < 8), 5);
+
+ let b: IndexMap<_, i32> = [1, 2, 4, 5, 6, 8, 9]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.partition_point(|_, &x| x < 7), 5);
+ assert_eq!(b.partition_point(|_, &x| x < 0), 0);
+
+ let b: IndexMap<_, i32> = [1, 3, 3, 3, 7]
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (i + 100, x))
+ .collect();
+ assert_eq!(b.partition_point(|_, &x| x < 0), 0);
+ assert_eq!(b.partition_point(|_, &x| x < 1), 0);
+ assert_eq!(b.partition_point(|_, &x| x < 2), 1);
+ assert_eq!(b.partition_point(|_, &x| x < 3), 1);
+ assert_eq!(b.partition_point(|_, &x| x < 4), 4);
+ assert_eq!(b.partition_point(|_, &x| x < 5), 4);
+ assert_eq!(b.partition_point(|_, &x| x < 6), 4);
+ assert_eq!(b.partition_point(|_, &x| x < 7), 4);
+ assert_eq!(b.partition_point(|_, &x| x < 8), 5);
+}
diff --git a/third_party/rust/indexmap/src/mutable_keys.rs b/third_party/rust/indexmap/src/mutable_keys.rs
deleted file mode 100644
index 35a90c4723..0000000000
--- a/third_party/rust/indexmap/src/mutable_keys.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use core::hash::{BuildHasher, Hash};
-
-use super::{Equivalent, IndexMap};
-
-pub struct PrivateMarker {}
-
-/// Opt-in mutable access to keys.
-///
-/// These methods expose `&mut K`, mutable references to the key as it is stored
-/// in the map.
-/// You are allowed to modify the keys in the hashmap **if the modification
-/// does not change the key’s hash and equality**.
-///
-/// If keys are modified erroneously, you can no longer look them up.
-/// This is sound (memory safe) but a logical error hazard (just like
-/// implementing PartialEq, Eq, or Hash incorrectly would be).
-///
-/// `use` this trait to enable its methods for `IndexMap`.
-pub trait MutableKeys {
- type Key;
- type Value;
-
- /// Return item index, mutable reference to key and value
- fn get_full_mut2<Q: ?Sized>(
- &mut self,
- key: &Q,
- ) -> Option<(usize, &mut Self::Key, &mut Self::Value)>
- where
- Q: Hash + Equivalent<Self::Key>;
-
- /// Scan through each key-value pair in the map and keep those where the
- /// closure `keep` returns `true`.
- ///
- /// The elements are visited in order, and remaining elements keep their
- /// order.
- ///
- /// Computes in **O(n)** time (average).
- fn retain2<F>(&mut self, keep: F)
- where
- F: FnMut(&mut Self::Key, &mut Self::Value) -> bool;
-
- /// This method is not useful in itself – it is there to “seal” the trait
- /// for external implementation, so that we can add methods without
- /// causing breaking changes.
- fn __private_marker(&self) -> PrivateMarker;
-}
-
-/// Opt-in mutable access to keys.
-///
-/// See [`MutableKeys`](trait.MutableKeys.html) for more information.
-impl<K, V, S> MutableKeys for IndexMap<K, V, S>
-where
- K: Eq + Hash,
- S: BuildHasher,
-{
- type Key = K;
- type Value = V;
- fn get_full_mut2<Q: ?Sized>(&mut self, key: &Q) -> Option<(usize, &mut K, &mut V)>
- where
- Q: Hash + Equivalent<K>,
- {
- self.get_full_mut2_impl(key)
- }
-
- fn retain2<F>(&mut self, keep: F)
- where
- F: FnMut(&mut K, &mut V) -> bool,
- {
- self.retain_mut(keep)
- }
-
- fn __private_marker(&self) -> PrivateMarker {
- PrivateMarker {}
- }
-}
diff --git a/third_party/rust/indexmap/src/rayon/map.rs b/third_party/rust/indexmap/src/rayon/map.rs
index 8819f13ed7..8236cf70f0 100644
--- a/third_party/rust/indexmap/src/rayon/map.rs
+++ b/third_party/rust/indexmap/src/rayon/map.rs
@@ -1,25 +1,24 @@
-//! Parallel iterator types for `IndexMap` with [rayon](https://docs.rs/rayon/1.0/rayon).
+//! Parallel iterator types for [`IndexMap`] with [`rayon`][::rayon].
//!
//! You will rarely need to interact with this module directly unless you need to name one of the
//! iterator types.
-//!
-//! Requires crate feature `"rayon"`
use super::collect;
use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer};
use rayon::prelude::*;
use crate::vec::Vec;
+use alloc::boxed::Box;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{BuildHasher, Hash};
use core::ops::RangeBounds;
+use crate::map::Slice;
use crate::Bucket;
use crate::Entries;
use crate::IndexMap;
-/// Requires crate feature `"rayon"`.
impl<K, V, S> IntoParallelIterator for IndexMap<K, V, S>
where
K: Send,
@@ -35,13 +34,25 @@ where
}
}
-/// A parallel owning iterator over the entries of a `IndexMap`.
-///
-/// This `struct` is created by the [`into_par_iter`] method on [`IndexMap`]
-/// (provided by rayon's `IntoParallelIterator` trait). See its documentation for more.
+impl<K, V> IntoParallelIterator for Box<Slice<K, V>>
+where
+ K: Send,
+ V: Send,
+{
+ type Item = (K, V);
+ type Iter = IntoParIter<K, V>;
+
+ fn into_par_iter(self) -> Self::Iter {
+ IntoParIter {
+ entries: self.into_entries(),
+ }
+ }
+}
+
+/// A parallel owning iterator over the entries of an [`IndexMap`].
///
-/// [`into_par_iter`]: ../struct.IndexMap.html#method.into_par_iter
-/// [`IndexMap`]: ../struct.IndexMap.html
+/// This `struct` is created by the [`IndexMap::into_par_iter`] method
+/// (provided by rayon's [`IntoParallelIterator`] trait). See its documentation for more.
pub struct IntoParIter<K, V> {
entries: Vec<Bucket<K, V>>,
}
@@ -63,7 +74,6 @@ impl<K: Send, V: Send> IndexedParallelIterator for IntoParIter<K, V> {
indexed_parallel_iterator_methods!(Bucket::key_value);
}
-/// Requires crate feature `"rayon"`.
impl<'a, K, V, S> IntoParallelIterator for &'a IndexMap<K, V, S>
where
K: Sync,
@@ -79,13 +89,27 @@ where
}
}
-/// A parallel iterator over the entries of a `IndexMap`.
+impl<'a, K, V> IntoParallelIterator for &'a Slice<K, V>
+where
+ K: Sync,
+ V: Sync,
+{
+ type Item = (&'a K, &'a V);
+ type Iter = ParIter<'a, K, V>;
+
+ fn into_par_iter(self) -> Self::Iter {
+ ParIter {
+ entries: &self.entries,
+ }
+ }
+}
+
+/// A parallel iterator over the entries of an [`IndexMap`].
///
-/// This `struct` is created by the [`par_iter`] method on [`IndexMap`]
-/// (provided by rayon's `IntoParallelRefIterator` trait). See its documentation for more.
+/// This `struct` is created by the [`IndexMap::par_iter`] method
+/// (provided by rayon's [`IntoParallelRefIterator`] trait). See its documentation for more.
///
-/// [`par_iter`]: ../struct.IndexMap.html#method.par_iter
-/// [`IndexMap`]: ../struct.IndexMap.html
+/// [`IndexMap::par_iter`]: ../struct.IndexMap.html#method.par_iter
pub struct ParIter<'a, K, V> {
entries: &'a [Bucket<K, V>],
}
@@ -113,7 +137,6 @@ impl<K: Sync, V: Sync> IndexedParallelIterator for ParIter<'_, K, V> {
indexed_parallel_iterator_methods!(Bucket::refs);
}
-/// Requires crate feature `"rayon"`.
impl<'a, K, V, S> IntoParallelIterator for &'a mut IndexMap<K, V, S>
where
K: Sync + Send,
@@ -129,13 +152,27 @@ where
}
}
-/// A parallel mutable iterator over the entries of a `IndexMap`.
+impl<'a, K, V> IntoParallelIterator for &'a mut Slice<K, V>
+where
+ K: Sync + Send,
+ V: Send,
+{
+ type Item = (&'a K, &'a mut V);
+ type Iter = ParIterMut<'a, K, V>;
+
+ fn into_par_iter(self) -> Self::Iter {
+ ParIterMut {
+ entries: &mut self.entries,
+ }
+ }
+}
+
+/// A parallel mutable iterator over the entries of an [`IndexMap`].
///
-/// This `struct` is created by the [`par_iter_mut`] method on [`IndexMap`]
-/// (provided by rayon's `IntoParallelRefMutIterator` trait). See its documentation for more.
+/// This `struct` is created by the [`IndexMap::par_iter_mut`] method
+/// (provided by rayon's [`IntoParallelRefMutIterator`] trait). See its documentation for more.
///
-/// [`par_iter_mut`]: ../struct.IndexMap.html#method.par_iter_mut
-/// [`IndexMap`]: ../struct.IndexMap.html
+/// [`IndexMap::par_iter_mut`]: ../struct.IndexMap.html#method.par_iter_mut
pub struct ParIterMut<'a, K, V> {
entries: &'a mut [Bucket<K, V>],
}
@@ -157,7 +194,6 @@ impl<K: Sync + Send, V: Send> IndexedParallelIterator for ParIterMut<'_, K, V> {
indexed_parallel_iterator_methods!(Bucket::ref_mut);
}
-/// Requires crate feature `"rayon"`.
impl<'a, K, V, S> ParallelDrainRange<usize> for &'a mut IndexMap<K, V, S>
where
K: Send,
@@ -173,13 +209,12 @@ where
}
}
-/// A parallel draining iterator over the entries of a `IndexMap`.
+/// A parallel draining iterator over the entries of an [`IndexMap`].
///
-/// This `struct` is created by the [`par_drain`] method on [`IndexMap`]
-/// (provided by rayon's `ParallelDrainRange` trait). See its documentation for more.
+/// This `struct` is created by the [`IndexMap::par_drain`] method
+/// (provided by rayon's [`ParallelDrainRange`] trait). See its documentation for more.
///
-/// [`par_drain`]: ../struct.IndexMap.html#method.par_drain
-/// [`IndexMap`]: ../struct.IndexMap.html
+/// [`IndexMap::par_drain`]: ../struct.IndexMap.html#method.par_drain
pub struct ParDrain<'a, K: Send, V: Send> {
entries: rayon::vec::Drain<'a, Bucket<K, V>>,
}
@@ -225,6 +260,37 @@ where
}
}
+/// Parallel iterator methods and other parallel methods.
+///
+/// The following methods **require crate feature `"rayon"`**.
+///
+/// See also the `IntoParallelIterator` implementations.
+impl<K, V> Slice<K, V>
+where
+ K: Sync,
+ V: Sync,
+{
+ /// Return a parallel iterator over the keys of the map slice.
+ ///
+ /// While parallel iterators can process items in any order, their relative order
+ /// in the slice is still preserved for operations like `reduce` and `collect`.
+ pub fn par_keys(&self) -> ParKeys<'_, K, V> {
+ ParKeys {
+ entries: &self.entries,
+ }
+ }
+
+ /// Return a parallel iterator over the values of the map slice.
+ ///
+ /// While parallel iterators can process items in any order, their relative order
+ /// in the slice is still preserved for operations like `reduce` and `collect`.
+ pub fn par_values(&self) -> ParValues<'_, K, V> {
+ ParValues {
+ entries: &self.entries,
+ }
+ }
+}
+
impl<K, V, S> IndexMap<K, V, S>
where
K: Hash + Eq + Sync,
@@ -246,13 +312,10 @@ where
}
}
-/// A parallel iterator over the keys of a `IndexMap`.
+/// A parallel iterator over the keys of an [`IndexMap`].
///
-/// This `struct` is created by the [`par_keys`] method on [`IndexMap`]. See its
-/// documentation for more.
-///
-/// [`par_keys`]: ../struct.IndexMap.html#method.par_keys
-/// [`IndexMap`]: ../struct.IndexMap.html
+/// This `struct` is created by the [`IndexMap::par_keys`] method.
+/// See its documentation for more.
pub struct ParKeys<'a, K, V> {
entries: &'a [Bucket<K, V>],
}
@@ -280,13 +343,10 @@ impl<K: Sync, V: Sync> IndexedParallelIterator for ParKeys<'_, K, V> {
indexed_parallel_iterator_methods!(Bucket::key_ref);
}
-/// A parallel iterator over the values of a `IndexMap`.
-///
-/// This `struct` is created by the [`par_values`] method on [`IndexMap`]. See its
-/// documentation for more.
+/// A parallel iterator over the values of an [`IndexMap`].
///
-/// [`par_values`]: ../struct.IndexMap.html#method.par_values
-/// [`IndexMap`]: ../struct.IndexMap.html
+/// This `struct` is created by the [`IndexMap::par_values`] method.
+/// See its documentation for more.
pub struct ParValues<'a, K, V> {
entries: &'a [Bucket<K, V>],
}
@@ -314,7 +374,6 @@ impl<K: Sync, V: Sync> IndexedParallelIterator for ParValues<'_, K, V> {
indexed_parallel_iterator_methods!(Bucket::value_ref);
}
-/// Requires crate feature `"rayon"`.
impl<K, V, S> IndexMap<K, V, S>
where
K: Send,
@@ -331,11 +390,26 @@ where
}
}
+impl<K, V> Slice<K, V>
+where
+ K: Send,
+ V: Send,
+{
+ /// Return a parallel iterator over mutable references to the the values of the map slice.
+ ///
+ /// While parallel iterators can process items in any order, their relative order
+ /// in the slice is still preserved for operations like `reduce` and `collect`.
+ pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V> {
+ ParValuesMut {
+ entries: &mut self.entries,
+ }
+ }
+}
+
impl<K, V, S> IndexMap<K, V, S>
where
- K: Hash + Eq + Send,
+ K: Send,
V: Send,
- S: BuildHasher,
{
/// Sort the map’s key-value pairs in parallel, by the default ordering of the keys.
pub fn par_sort_keys(&mut self)
@@ -406,15 +480,24 @@ where
entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value));
IntoParIter { entries }
}
+
+ /// Sort the map’s key-value pairs in place and in parallel, using a sort-key extraction
+ /// function.
+ pub fn par_sort_by_cached_key<T, F>(&mut self, sort_key: F)
+ where
+ T: Ord + Send,
+ F: Fn(&K, &V) -> T + Sync,
+ {
+ self.with_entries(move |entries| {
+ entries.par_sort_by_cached_key(move |a| sort_key(&a.key, &a.value));
+ });
+ }
}
-/// A parallel mutable iterator over the values of a `IndexMap`.
-///
-/// This `struct` is created by the [`par_values_mut`] method on [`IndexMap`]. See its
-/// documentation for more.
+/// A parallel mutable iterator over the values of an [`IndexMap`].
///
-/// [`par_values_mut`]: ../struct.IndexMap.html#method.par_values_mut
-/// [`IndexMap`]: ../struct.IndexMap.html
+/// This `struct` is created by the [`IndexMap::par_values_mut`] method.
+/// See its documentation for more.
pub struct ParValuesMut<'a, K, V> {
entries: &'a mut [Bucket<K, V>],
}
@@ -436,7 +519,6 @@ impl<K: Send, V: Send> IndexedParallelIterator for ParValuesMut<'_, K, V> {
indexed_parallel_iterator_methods!(Bucket::value_mut);
}
-/// Requires crate feature `"rayon"`.
impl<K, V, S> FromParallelIterator<(K, V)> for IndexMap<K, V, S>
where
K: Eq + Hash + Send,
@@ -457,7 +539,6 @@ where
}
}
-/// Requires crate feature `"rayon"`.
impl<K, V, S> ParallelExtend<(K, V)> for IndexMap<K, V, S>
where
K: Eq + Hash + Send,
@@ -474,7 +555,6 @@ where
}
}
-/// Requires crate feature `"rayon"`.
impl<'a, K: 'a, V: 'a, S> ParallelExtend<(&'a K, &'a V)> for IndexMap<K, V, S>
where
K: Copy + Eq + Hash + Send + Sync,
diff --git a/third_party/rust/indexmap/src/rayon/mod.rs b/third_party/rust/indexmap/src/rayon/mod.rs
index ebb1ac2d1e..1d21569c18 100644
--- a/third_party/rust/indexmap/src/rayon/mod.rs
+++ b/third_party/rust/indexmap/src/rayon/mod.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
+
use rayon::prelude::*;
use alloc::collections::LinkedList;
diff --git a/third_party/rust/indexmap/src/rayon/set.rs b/third_party/rust/indexmap/src/rayon/set.rs
index 6749dc0d7f..3904234b20 100644
--- a/third_party/rust/indexmap/src/rayon/set.rs
+++ b/third_party/rust/indexmap/src/rayon/set.rs
@@ -1,26 +1,25 @@
-//! Parallel iterator types for `IndexSet` with [rayon](https://docs.rs/rayon/1.0/rayon).
+//! Parallel iterator types for [`IndexSet`] with [rayon][::rayon].
//!
//! You will rarely need to interact with this module directly unless you need to name one of the
//! iterator types.
-//!
-//! Requires crate feature `"rayon"`.
use super::collect;
use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer};
use rayon::prelude::*;
use crate::vec::Vec;
+use alloc::boxed::Box;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{BuildHasher, Hash};
use core::ops::RangeBounds;
+use crate::set::Slice;
use crate::Entries;
use crate::IndexSet;
type Bucket<T> = crate::Bucket<T, ()>;
-/// Requires crate feature `"rayon"`.
impl<T, S> IntoParallelIterator for IndexSet<T, S>
where
T: Send,
@@ -35,13 +34,24 @@ where
}
}
-/// A parallel owning iterator over the items of a `IndexSet`.
-///
-/// This `struct` is created by the [`into_par_iter`] method on [`IndexSet`]
-/// (provided by rayon's `IntoParallelIterator` trait). See its documentation for more.
+impl<T> IntoParallelIterator for Box<Slice<T>>
+where
+ T: Send,
+{
+ type Item = T;
+ type Iter = IntoParIter<T>;
+
+ fn into_par_iter(self) -> Self::Iter {
+ IntoParIter {
+ entries: self.into_entries(),
+ }
+ }
+}
+
+/// A parallel owning iterator over the items of an [`IndexSet`].
///
-/// [`IndexSet`]: ../struct.IndexSet.html
-/// [`into_par_iter`]: ../struct.IndexSet.html#method.into_par_iter
+/// This `struct` is created by the [`IndexSet::into_par_iter`] method
+/// (provided by rayon's [`IntoParallelIterator`] trait). See its documentation for more.
pub struct IntoParIter<T> {
entries: Vec<Bucket<T>>,
}
@@ -63,7 +73,6 @@ impl<T: Send> IndexedParallelIterator for IntoParIter<T> {
indexed_parallel_iterator_methods!(Bucket::key);
}
-/// Requires crate feature `"rayon"`.
impl<'a, T, S> IntoParallelIterator for &'a IndexSet<T, S>
where
T: Sync,
@@ -78,13 +87,26 @@ where
}
}
-/// A parallel iterator over the items of a `IndexSet`.
+impl<'a, T> IntoParallelIterator for &'a Slice<T>
+where
+ T: Sync,
+{
+ type Item = &'a T;
+ type Iter = ParIter<'a, T>;
+
+ fn into_par_iter(self) -> Self::Iter {
+ ParIter {
+ entries: &self.entries,
+ }
+ }
+}
+
+/// A parallel iterator over the items of an [`IndexSet`].
///
-/// This `struct` is created by the [`par_iter`] method on [`IndexSet`]
-/// (provided by rayon's `IntoParallelRefIterator` trait). See its documentation for more.
+/// This `struct` is created by the [`IndexSet::par_iter`] method
+/// (provided by rayon's [`IntoParallelRefIterator`] trait). See its documentation for more.
///
-/// [`IndexSet`]: ../struct.IndexSet.html
-/// [`par_iter`]: ../struct.IndexSet.html#method.par_iter
+/// [`IndexSet::par_iter`]: ../struct.IndexSet.html#method.par_iter
pub struct ParIter<'a, T> {
entries: &'a [Bucket<T>],
}
@@ -112,7 +134,6 @@ impl<T: Sync> IndexedParallelIterator for ParIter<'_, T> {
indexed_parallel_iterator_methods!(Bucket::key_ref);
}
-/// Requires crate feature `"rayon"`.
impl<'a, T, S> ParallelDrainRange<usize> for &'a mut IndexSet<T, S>
where
T: Send,
@@ -127,13 +148,12 @@ where
}
}
-/// A parallel draining iterator over the items of a `IndexSet`.
+/// A parallel draining iterator over the items of an [`IndexSet`].
///
-/// This `struct` is created by the [`par_drain`] method on [`IndexSet`]
-/// (provided by rayon's `ParallelDrainRange` trait). See its documentation for more.
+/// This `struct` is created by the [`IndexSet::par_drain`] method
+/// (provided by rayon's [`ParallelDrainRange`] trait). See its documentation for more.
///
-/// [`par_drain`]: ../struct.IndexSet.html#method.par_drain
-/// [`IndexSet`]: ../struct.IndexSet.html
+/// [`IndexSet::par_drain`]: ../struct.IndexSet.html#method.par_drain
pub struct ParDrain<'a, T: Send> {
entries: rayon::vec::Drain<'a, Bucket<T>>,
}
@@ -269,13 +289,10 @@ where
}
}
-/// A parallel iterator producing elements in the difference of `IndexSet`s.
+/// A parallel iterator producing elements in the difference of [`IndexSet`]s.
///
-/// This `struct` is created by the [`par_difference`] method on [`IndexSet`].
+/// This `struct` is created by the [`IndexSet::par_difference`] method.
/// See its documentation for more.
-///
-/// [`IndexSet`]: ../struct.IndexSet.html
-/// [`par_difference`]: ../struct.IndexSet.html#method.par_difference
pub struct ParDifference<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
@@ -320,13 +337,10 @@ where
}
}
-/// A parallel iterator producing elements in the intersection of `IndexSet`s.
+/// A parallel iterator producing elements in the intersection of [`IndexSet`]s.
///
-/// This `struct` is created by the [`par_intersection`] method on [`IndexSet`].
+/// This `struct` is created by the [`IndexSet::par_intersection`] method.
/// See its documentation for more.
-///
-/// [`IndexSet`]: ../struct.IndexSet.html
-/// [`par_intersection`]: ../struct.IndexSet.html#method.par_intersection
pub struct ParIntersection<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
@@ -371,13 +385,10 @@ where
}
}
-/// A parallel iterator producing elements in the symmetric difference of `IndexSet`s.
-///
-/// This `struct` is created by the [`par_symmetric_difference`] method on
-/// [`IndexSet`]. See its documentation for more.
+/// A parallel iterator producing elements in the symmetric difference of [`IndexSet`]s.
///
-/// [`IndexSet`]: ../struct.IndexSet.html
-/// [`par_symmetric_difference`]: ../struct.IndexSet.html#method.par_symmetric_difference
+/// This `struct` is created by the [`IndexSet::par_symmetric_difference`] method.
+/// See its documentation for more.
pub struct ParSymmetricDifference<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
@@ -422,13 +433,10 @@ where
}
}
-/// A parallel iterator producing elements in the union of `IndexSet`s.
+/// A parallel iterator producing elements in the union of [`IndexSet`]s.
///
-/// This `struct` is created by the [`par_union`] method on [`IndexSet`].
+/// This `struct` is created by the [`IndexSet::par_union`] method.
/// See its documentation for more.
-///
-/// [`IndexSet`]: ../struct.IndexSet.html
-/// [`par_union`]: ../struct.IndexSet.html#method.par_union
pub struct ParUnion<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
@@ -476,8 +484,7 @@ where
/// The following methods **require crate feature `"rayon"`**.
impl<T, S> IndexSet<T, S>
where
- T: Hash + Eq + Send,
- S: BuildHasher + Send,
+ T: Send,
{
/// Sort the set’s values in parallel by their default ordering.
pub fn par_sort(&mut self)
@@ -540,9 +547,19 @@ where
entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
IntoParIter { entries }
}
+
+ /// Sort the set’s values in place and in parallel, using a key extraction function.
+ pub fn par_sort_by_cached_key<K, F>(&mut self, sort_key: F)
+ where
+ K: Ord + Send,
+ F: Fn(&T) -> K + Sync,
+ {
+ self.with_entries(move |entries| {
+ entries.par_sort_by_cached_key(move |a| sort_key(&a.key));
+ });
+ }
}
-/// Requires crate feature `"rayon"`.
impl<T, S> FromParallelIterator<T> for IndexSet<T, S>
where
T: Eq + Hash + Send,
@@ -562,7 +579,6 @@ where
}
}
-/// Requires crate feature `"rayon"`.
impl<T, S> ParallelExtend<T> for IndexSet<T, S>
where
T: Eq + Hash + Send,
@@ -578,7 +594,6 @@ where
}
}
-/// Requires crate feature `"rayon"`.
impl<'a, T: 'a, S> ParallelExtend<&'a T> for IndexSet<T, S>
where
T: Copy + Eq + Hash + Send + Sync,
diff --git a/third_party/rust/indexmap/src/serde.rs b/third_party/rust/indexmap/src/serde.rs
index c6dd6d5ea0..25546d531b 100644
--- a/third_party/rust/indexmap/src/serde.rs
+++ b/third_party/rust/indexmap/src/serde.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(docsrs, doc(cfg(feature = "serde")))]
+
use serde::de::value::{MapDeserializer, SeqDeserializer};
use serde::de::{
Deserialize, Deserializer, Error, IntoDeserializer, MapAccess, SeqAccess, Visitor,
@@ -7,15 +9,30 @@ use serde::ser::{Serialize, Serializer};
use core::fmt::{self, Formatter};
use core::hash::{BuildHasher, Hash};
use core::marker::PhantomData;
+use core::{cmp, mem};
+
+use crate::{Bucket, IndexMap, IndexSet};
+
+/// Limit our preallocated capacity from a deserializer `size_hint()`.
+///
+/// We do account for the `Bucket` overhead from its saved `hash` field, but we don't count the
+/// `RawTable` allocation or the fact that its raw capacity will be rounded up to a power of two.
+/// The "max" is an arbitrary choice anyway, not something that needs precise adherence.
+///
+/// This is based on the internal `serde::de::size_hint::cautious(hint)` function.
+pub(crate) fn cautious_capacity<K, V>(hint: Option<usize>) -> usize {
+ const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
+
+ cmp::min(
+ hint.unwrap_or(0),
+ MAX_PREALLOC_BYTES / mem::size_of::<Bucket<K, V>>(),
+ )
+}
-use crate::IndexMap;
-
-/// Requires crate feature `"serde"` or `"serde-1"`
impl<K, V, S> Serialize for IndexMap<K, V, S>
where
- K: Serialize + Hash + Eq,
+ K: Serialize,
V: Serialize,
- S: BuildHasher,
{
fn serialize<T>(&self, serializer: T) -> Result<T::Ok, T::Error>
where
@@ -43,8 +60,8 @@ where
where
A: MapAccess<'de>,
{
- let mut values =
- IndexMap::with_capacity_and_hasher(map.size_hint().unwrap_or(0), S::default());
+ let capacity = cautious_capacity::<K, V>(map.size_hint());
+ let mut values = IndexMap::with_capacity_and_hasher(capacity, S::default());
while let Some((key, value)) = map.next_entry()? {
values.insert(key, value);
@@ -54,7 +71,6 @@ where
}
}
-/// Requires crate feature `"serde"` or `"serde-1"`
impl<'de, K, V, S> Deserialize<'de> for IndexMap<K, V, S>
where
K: Deserialize<'de> + Eq + Hash,
@@ -83,13 +99,9 @@ where
}
}
-use crate::IndexSet;
-
-/// Requires crate feature `"serde"` or `"serde-1"`
impl<T, S> Serialize for IndexSet<T, S>
where
- T: Serialize + Hash + Eq,
- S: BuildHasher,
+ T: Serialize,
{
fn serialize<Se>(&self, serializer: Se) -> Result<Se::Ok, Se::Error>
where
@@ -116,8 +128,8 @@ where
where
A: SeqAccess<'de>,
{
- let mut values =
- IndexSet::with_capacity_and_hasher(seq.size_hint().unwrap_or(0), S::default());
+ let capacity = cautious_capacity::<T, ()>(seq.size_hint());
+ let mut values = IndexSet::with_capacity_and_hasher(capacity, S::default());
while let Some(value) = seq.next_element()? {
values.insert(value);
@@ -127,7 +139,6 @@ where
}
}
-/// Requires crate feature `"serde"` or `"serde-1"`
impl<'de, T, S> Deserialize<'de> for IndexSet<T, S>
where
T: Deserialize<'de> + Eq + Hash,
diff --git a/third_party/rust/indexmap/src/serde_seq.rs b/third_party/rust/indexmap/src/serde_seq.rs
deleted file mode 100644
index d326a02e37..0000000000
--- a/third_party/rust/indexmap/src/serde_seq.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-//! Functions to serialize and deserialize an `IndexMap` as an ordered sequence.
-//!
-//! The default `serde` implementation serializes `IndexMap` as a normal map,
-//! but there is no guarantee that serialization formats will preserve the order
-//! of the key-value pairs. This module serializes `IndexMap` as a sequence of
-//! `(key, value)` elements instead, in order.
-//!
-//! This module may be used in a field attribute for derived implementations:
-//!
-//! ```
-//! # use indexmap::IndexMap;
-//! # use serde_derive::{Deserialize, Serialize};
-//! #[derive(Deserialize, Serialize)]
-//! struct Data {
-//! #[serde(with = "indexmap::serde_seq")]
-//! map: IndexMap<i32, u64>,
-//! // ...
-//! }
-//! ```
-//!
-//! Requires crate feature `"serde"` or `"serde-1"`
-
-use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
-use serde::ser::{Serialize, Serializer};
-
-use core::fmt::{self, Formatter};
-use core::hash::{BuildHasher, Hash};
-use core::marker::PhantomData;
-
-use crate::IndexMap;
-
-/// Serializes an `IndexMap` as an ordered sequence.
-///
-/// This function may be used in a field attribute for deriving `Serialize`:
-///
-/// ```
-/// # use indexmap::IndexMap;
-/// # use serde_derive::Serialize;
-/// #[derive(Serialize)]
-/// struct Data {
-/// #[serde(serialize_with = "indexmap::serde_seq::serialize")]
-/// map: IndexMap<i32, u64>,
-/// // ...
-/// }
-/// ```
-///
-/// Requires crate feature `"serde"` or `"serde-1"`
-pub fn serialize<K, V, S, T>(map: &IndexMap<K, V, S>, serializer: T) -> Result<T::Ok, T::Error>
-where
- K: Serialize + Hash + Eq,
- V: Serialize,
- S: BuildHasher,
- T: Serializer,
-{
- serializer.collect_seq(map)
-}
-
-/// Visitor to deserialize a *sequenced* `IndexMap`
-struct SeqVisitor<K, V, S>(PhantomData<(K, V, S)>);
-
-impl<'de, K, V, S> Visitor<'de> for SeqVisitor<K, V, S>
-where
- K: Deserialize<'de> + Eq + Hash,
- V: Deserialize<'de>,
- S: Default + BuildHasher,
-{
- type Value = IndexMap<K, V, S>;
-
- fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
- write!(formatter, "a sequenced map")
- }
-
- fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
- where
- A: SeqAccess<'de>,
- {
- let capacity = seq.size_hint().unwrap_or(0);
- let mut map = IndexMap::with_capacity_and_hasher(capacity, S::default());
-
- while let Some((key, value)) = seq.next_element()? {
- map.insert(key, value);
- }
-
- Ok(map)
- }
-}
-
-/// Deserializes an `IndexMap` from an ordered sequence.
-///
-/// This function may be used in a field attribute for deriving `Deserialize`:
-///
-/// ```
-/// # use indexmap::IndexMap;
-/// # use serde_derive::Deserialize;
-/// #[derive(Deserialize)]
-/// struct Data {
-/// #[serde(deserialize_with = "indexmap::serde_seq::deserialize")]
-/// map: IndexMap<i32, u64>,
-/// // ...
-/// }
-/// ```
-///
-/// Requires crate feature `"serde"` or `"serde-1"`
-pub fn deserialize<'de, D, K, V, S>(deserializer: D) -> Result<IndexMap<K, V, S>, D::Error>
-where
- D: Deserializer<'de>,
- K: Deserialize<'de> + Eq + Hash,
- V: Deserialize<'de>,
- S: Default + BuildHasher,
-{
- deserializer.deserialize_seq(SeqVisitor(PhantomData))
-}
diff --git a/third_party/rust/indexmap/src/set.rs b/third_party/rust/indexmap/src/set.rs
index 3728947426..b5bd05f1bc 100644
--- a/third_party/rust/indexmap/src/set.rs
+++ b/third_party/rust/indexmap/src/set.rs
@@ -1,18 +1,32 @@
-//! A hash set implemented using `IndexMap`
+//! A hash set implemented using [`IndexMap`]
+
+mod iter;
+mod mutable;
+mod slice;
+
+#[cfg(test)]
+mod tests;
+
+pub use self::iter::{
+ Difference, Drain, Intersection, IntoIter, Iter, Splice, SymmetricDifference, Union,
+};
+pub use self::mutable::MutableValues;
+pub use self::slice::Slice;
#[cfg(feature = "rayon")]
pub use crate::rayon::set as rayon;
+use crate::TryReserveError;
-#[cfg(has_std)]
+#[cfg(feature = "std")]
use std::collections::hash_map::RandomState;
-use crate::vec::{self, Vec};
+use crate::util::try_simplify_range;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{BuildHasher, Hash};
-use core::iter::{Chain, FusedIterator};
use core::ops::{BitAnd, BitOr, BitXor, Index, RangeBounds, Sub};
-use core::slice;
use super::{Entries, Equivalent, IndexMap};
@@ -21,8 +35,9 @@ type Bucket<T> = super::Bucket<T, ()>;
/// A hash set where the iteration order of the values is independent of their
/// hash values.
///
-/// The interface is closely compatible with the standard `HashSet`, but also
-/// has additional features.
+/// The interface is closely compatible with the standard
+/// [`HashSet`][std::collections::HashSet],
+/// but also has additional features.
///
/// # Order
///
@@ -33,11 +48,12 @@ type Bucket<T> = super::Bucket<T, ()>;
/// already present.
///
/// All iterators traverse the set *in order*. Set operation iterators like
-/// `union` produce a concatenated order, as do their matching "bitwise"
+/// [`IndexSet::union`] produce a concatenated order, as do their matching "bitwise"
/// operators. See their documentation for specifics.
///
/// The insertion order is preserved, with **notable exceptions** like the
-/// `.remove()` or `.swap_remove()` methods. Methods such as `.sort_by()` of
+/// [`.remove()`][Self::remove] or [`.swap_remove()`][Self::swap_remove] methods.
+/// Methods such as [`.sort_by()`][Self::sort_by] of
/// course result in a new order, depending on the sorting order.
///
/// # Indices
@@ -46,6 +62,11 @@ type Bucket<T> = super::Bucket<T, ()>;
/// `0..self.len()`. For example, the method `.get_full` looks up the index for
/// a value, and the method `.get_index` looks up the value by index.
///
+/// # Complexity
+///
+/// Internally, `IndexSet<T, S>` just holds an [`IndexMap<T, (), S>`](IndexMap). Thus the complexity
+/// of the two are the same for most methods.
+///
/// # Examples
///
/// ```
@@ -59,11 +80,11 @@ type Bucket<T> = super::Bucket<T, ()>;
/// assert!(letters.contains(&'u'));
/// assert!(!letters.contains(&'y'));
/// ```
-#[cfg(has_std)]
+#[cfg(feature = "std")]
pub struct IndexSet<T, S = RandomState> {
pub(crate) map: IndexMap<T, (), S>,
}
-#[cfg(not(has_std))]
+#[cfg(not(feature = "std"))]
pub struct IndexSet<T, S> {
pub(crate) map: IndexMap<T, (), S>,
}
@@ -114,17 +135,20 @@ impl<T, S> fmt::Debug for IndexSet<T, S>
where
T: fmt::Debug,
{
+ #[cfg(not(feature = "test_debug"))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- if cfg!(not(feature = "test_debug")) {
- f.debug_set().entries(self.iter()).finish()
- } else {
- // Let the inner `IndexMap` print all of its details
- f.debug_struct("IndexSet").field("map", &self.map).finish()
- }
+ f.debug_set().entries(self.iter()).finish()
+ }
+
+ #[cfg(feature = "test_debug")]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Let the inner `IndexMap` print all of its details
+ f.debug_struct("IndexSet").field("map", &self.map).finish()
}
}
-#[cfg(has_std)]
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T> IndexSet<T> {
/// Create a new set. (Does not allocate.)
pub fn new() -> Self {
@@ -165,6 +189,11 @@ impl<T, S> IndexSet<T, S> {
}
}
+ /// Return the number of elements the set can hold without reallocating.
+ ///
+ /// This number is a lower bound; the set might be able to hold more,
+ /// but is guaranteed to be able to hold at least this many.
+ ///
/// Computes in **O(1)** time.
pub fn capacity(&self) -> usize {
self.map.capacity()
@@ -191,9 +220,7 @@ impl<T, S> IndexSet<T, S> {
/// Return an iterator over the values of the set, in their order
pub fn iter(&self) -> Iter<'_, T> {
- Iter {
- iter: self.map.as_entries().iter(),
- }
+ Iter::new(self.as_entries())
}
/// Remove all elements in the set, while preserving its capacity.
@@ -213,7 +240,7 @@ impl<T, S> IndexSet<T, S> {
/// Clears the `IndexSet` in the given index range, returning those values
/// as a drain iterator.
///
- /// The range may be any type that implements `RangeBounds<usize>`,
+ /// The range may be any type that implements [`RangeBounds<usize>`],
/// including all of the `std::ops::Range*` types, or even a tuple pair of
/// `Bound` start and end values. To drain the set entirely, use `RangeFull`
/// like `set.drain(..)`.
@@ -227,9 +254,7 @@ impl<T, S> IndexSet<T, S> {
where
R: RangeBounds<usize>,
{
- Drain {
- iter: self.map.drain(range).iter,
- }
+ Drain::new(self.map.core.drain(range))
}
/// Splits the collection into two at the given index.
@@ -247,13 +272,7 @@ impl<T, S> IndexSet<T, S> {
map: self.map.split_off(at),
}
}
-}
-impl<T, S> IndexSet<T, S>
-where
- T: Hash + Eq,
- S: BuildHasher,
-{
/// Reserve capacity for `additional` more values.
///
/// Computes in **O(n)** time.
@@ -261,6 +280,37 @@ where
self.map.reserve(additional);
}
+ /// Reserve capacity for `additional` more values, without over-allocating.
+ ///
+ /// Unlike `reserve`, this does not deliberately over-allocate the entry capacity to avoid
+ /// frequent re-allocations. However, the underlying data structures may still have internal
+ /// capacity requirements, and the allocator itself may give more space than requested, so this
+ /// cannot be relied upon to be precisely minimal.
+ ///
+ /// Computes in **O(n)** time.
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.map.reserve_exact(additional);
+ }
+
+ /// Try to reserve capacity for `additional` more values.
+ ///
+ /// Computes in **O(n)** time.
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.map.try_reserve(additional)
+ }
+
+ /// Try to reserve capacity for `additional` more values, without over-allocating.
+ ///
+ /// Unlike `try_reserve`, this does not deliberately over-allocate the entry capacity to avoid
+ /// frequent re-allocations. However, the underlying data structures may still have internal
+ /// capacity requirements, and the allocator itself may give more space than requested, so this
+ /// cannot be relied upon to be precisely minimal.
+ ///
+ /// Computes in **O(n)** time.
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.map.try_reserve_exact(additional)
+ }
+
/// Shrink the capacity of the set as much as possible.
///
/// Computes in **O(n)** time.
@@ -274,7 +324,13 @@ where
pub fn shrink_to(&mut self, min_capacity: usize) {
self.map.shrink_to(min_capacity);
}
+}
+impl<T, S> IndexSet<T, S>
+where
+ T: Hash + Eq,
+ S: BuildHasher,
+{
/// Insert the value into the set.
///
/// If an equivalent item already exists in the set, it returns
@@ -297,15 +353,69 @@ where
///
/// Computes in **O(1)** time (amortized average).
pub fn insert_full(&mut self, value: T) -> (usize, bool) {
- use super::map::Entry::*;
-
- match self.map.entry(value) {
- Occupied(e) => (e.index(), false),
- Vacant(e) => {
- let index = e.index();
- e.insert(());
- (index, true)
- }
+ let (index, existing) = self.map.insert_full(value, ());
+ (index, existing.is_none())
+ }
+
+ /// Insert the value into the set at its ordered position among sorted values.
+ ///
+ /// This is equivalent to finding the position with
+ /// [`binary_search`][Self::binary_search], and if needed calling
+ /// [`shift_insert`][Self::shift_insert] for a new value.
+ ///
+ /// If the sorted item is found in the set, it returns the index of that
+ /// existing item and `false`, without any change. Otherwise, it inserts the
+ /// new item and returns its sorted index and `true`.
+ ///
+ /// If the existing items are **not** already sorted, then the insertion
+ /// index is unspecified (like [`slice::binary_search`]), but the value
+ /// is moved to or inserted at that position regardless.
+ ///
+ /// Computes in **O(n)** time (average). Instead of repeating calls to
+ /// `insert_sorted`, it may be faster to call batched [`insert`][Self::insert]
+ /// or [`extend`][Self::extend] and only call [`sort`][Self::sort] or
+ /// [`sort_unstable`][Self::sort_unstable] once.
+ pub fn insert_sorted(&mut self, value: T) -> (usize, bool)
+ where
+ T: Ord,
+ {
+ let (index, existing) = self.map.insert_sorted(value, ());
+ (index, existing.is_none())
+ }
+
+ /// Insert the value into the set at the given index.
+ ///
+ /// If an equivalent item already exists in the set, it returns
+ /// `false` leaving the original value in the set, but moving it to
+ /// the new position in the set. Otherwise, it inserts the new
+ /// item at the given index and returns `true`.
+ ///
+ /// ***Panics*** if `index` is out of bounds.
+ ///
+ /// Computes in **O(n)** time (average).
+ pub fn shift_insert(&mut self, index: usize, value: T) -> bool {
+ self.map.shift_insert(index, value, ()).is_none()
+ }
+
+ /// Adds a value to the set, replacing the existing value, if any, that is
+ /// equal to the given one, without altering its insertion order. Returns
+ /// the replaced value.
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn replace(&mut self, value: T) -> Option<T> {
+ self.replace_full(value).1
+ }
+
+ /// Adds a value to the set, replacing the existing value, if any, that is
+ /// equal to the given one, without altering its insertion order. Returns
+ /// the index of the item and its replaced value.
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn replace_full(&mut self, value: T) -> (usize, Option<T>) {
+ let hash = self.map.hash(&value);
+ match self.map.core.replace_full(hash, value, ()) {
+ (i, Some((replaced, ()))) => (i, Some(replaced)),
+ (i, None) => (i, None),
}
}
@@ -316,10 +426,7 @@ where
where
S2: BuildHasher,
{
- Difference {
- iter: self.iter(),
- other,
- }
+ Difference::new(self, other)
}
/// Return an iterator over the values that are in `self` or `other`,
@@ -334,9 +441,7 @@ where
where
S2: BuildHasher,
{
- SymmetricDifference {
- iter: self.difference(other).chain(other.difference(self)),
- }
+ SymmetricDifference::new(self, other)
}
/// Return an iterator over the values that are in both `self` and `other`.
@@ -346,10 +451,7 @@ where
where
S2: BuildHasher,
{
- Intersection {
- iter: self.iter(),
- other,
- }
+ Intersection::new(self, other)
}
/// Return an iterator over all values that are in `self` or `other`.
@@ -360,17 +462,57 @@ where
where
S2: BuildHasher,
{
- Union {
- iter: self.iter().chain(other.difference(self)),
- }
+ Union::new(self, other)
}
+ /// Creates a splicing iterator that replaces the specified range in the set
+ /// with the given `replace_with` iterator and yields the removed items.
+ /// `replace_with` does not need to be the same length as `range`.
+ ///
+ /// The `range` is removed even if the iterator is not consumed until the
+ /// end. It is unspecified how many elements are removed from the set if the
+ /// `Splice` value is leaked.
+ ///
+ /// The input iterator `replace_with` is only consumed when the `Splice`
+ /// value is dropped. If a value from the iterator matches an existing entry
+ /// in the set (outside of `range`), then the original will be unchanged.
+ /// Otherwise, the new value will be inserted in the replaced `range`.
+ ///
+ /// ***Panics*** if the starting point is greater than the end point or if
+ /// the end point is greater than the length of the set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use indexmap::IndexSet;
+ ///
+ /// let mut set = IndexSet::from([0, 1, 2, 3, 4]);
+ /// let new = [5, 4, 3, 2, 1];
+ /// let removed: Vec<_> = set.splice(2..4, new).collect();
+ ///
+ /// // 1 and 4 kept their positions, while 5, 3, and 2 were newly inserted.
+ /// assert!(set.into_iter().eq([0, 1, 5, 3, 2, 4]));
+ /// assert_eq!(removed, &[2, 3]);
+ /// ```
+ pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, T, S>
+ where
+ R: RangeBounds<usize>,
+ I: IntoIterator<Item = T>,
+ {
+ Splice::new(self, range, replace_with.into_iter())
+ }
+}
+
+impl<T, S> IndexSet<T, S>
+where
+ S: BuildHasher,
+{
/// Return `true` if an equivalent to `value` exists in the set.
///
/// Computes in **O(1)** time (average).
- pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
+ pub fn contains<Q>(&self, value: &Q) -> bool
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.contains_key(value)
}
@@ -379,97 +521,74 @@ where
/// else `None`.
///
/// Computes in **O(1)** time (average).
- pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
+ pub fn get<Q>(&self, value: &Q) -> Option<&T>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_key_value(value).map(|(x, &())| x)
}
/// Return item index and value
- pub fn get_full<Q: ?Sized>(&self, value: &Q) -> Option<(usize, &T)>
+ pub fn get_full<Q>(&self, value: &Q) -> Option<(usize, &T)>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_full(value).map(|(i, x, &())| (i, x))
}
/// Return item index, if it exists in the set
- pub fn get_index_of<Q: ?Sized>(&self, value: &Q) -> Option<usize>
+ ///
+ /// Computes in **O(1)** time (average).
+ pub fn get_index_of<Q>(&self, value: &Q) -> Option<usize>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_index_of(value)
}
- /// Adds a value to the set, replacing the existing value, if any, that is
- /// equal to the given one, without altering its insertion order. Returns
- /// the replaced value.
- ///
- /// Computes in **O(1)** time (average).
- pub fn replace(&mut self, value: T) -> Option<T> {
- self.replace_full(value).1
- }
-
- /// Adds a value to the set, replacing the existing value, if any, that is
- /// equal to the given one, without altering its insertion order. Returns
- /// the index of the item and its replaced value.
- ///
- /// Computes in **O(1)** time (average).
- pub fn replace_full(&mut self, value: T) -> (usize, Option<T>) {
- use super::map::Entry::*;
-
- match self.map.entry(value) {
- Vacant(e) => {
- let index = e.index();
- e.insert(());
- (index, None)
- }
- Occupied(e) => (e.index(), Some(e.replace_key())),
- }
- }
-
/// Remove the value from the set, and return `true` if it was present.
///
- /// **NOTE:** This is equivalent to `.swap_remove(value)`, if you want
- /// to preserve the order of the values in the set, use `.shift_remove(value)`.
- ///
- /// Computes in **O(1)** time (average).
- pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
+ /// **NOTE:** This is equivalent to [`.swap_remove(value)`][Self::swap_remove], replacing this
+ /// value's position with the last element, and it is deprecated in favor of calling that
+ /// explicitly. If you need to preserve the relative order of the values in the set, use
+ /// [`.shift_remove(value)`][Self::shift_remove] instead.
+ #[deprecated(note = "`remove` disrupts the set order -- \
+ use `swap_remove` or `shift_remove` for explicit behavior.")]
+ pub fn remove<Q>(&mut self, value: &Q) -> bool
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.swap_remove(value)
}
/// Remove the value from the set, and return `true` if it was present.
///
- /// Like `Vec::swap_remove`, the value is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the value is removed by swapping it with the
/// last element of the set and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
/// Return `false` if `value` was not in the set.
///
/// Computes in **O(1)** time (average).
- pub fn swap_remove<Q: ?Sized>(&mut self, value: &Q) -> bool
+ pub fn swap_remove<Q>(&mut self, value: &Q) -> bool
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.swap_remove(value).is_some()
}
/// Remove the value from the set, and return `true` if it was present.
///
- /// Like `Vec::remove`, the value is removed by shifting all of the
+ /// Like [`Vec::remove`], the value is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
/// Return `false` if `value` was not in the set.
///
/// Computes in **O(n)** time (average).
- pub fn shift_remove<Q: ?Sized>(&mut self, value: &Q) -> bool
+ pub fn shift_remove<Q>(&mut self, value: &Q) -> bool
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.shift_remove(value).is_some()
}
@@ -477,14 +596,15 @@ where
/// Removes and returns the value in the set, if any, that is equal to the
/// given one.
///
- /// **NOTE:** This is equivalent to `.swap_take(value)`, if you need to
- /// preserve the order of the values in the set, use `.shift_take(value)`
- /// instead.
- ///
- /// Computes in **O(1)** time (average).
- pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
+ /// **NOTE:** This is equivalent to [`.swap_take(value)`][Self::swap_take], replacing this
+ /// value's position with the last element, and it is deprecated in favor of calling that
+ /// explicitly. If you need to preserve the relative order of the values in the set, use
+ /// [`.shift_take(value)`][Self::shift_take] instead.
+ #[deprecated(note = "`take` disrupts the set order -- \
+ use `swap_take` or `shift_take` for explicit behavior.")]
+ pub fn take<Q>(&mut self, value: &Q) -> Option<T>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.swap_take(value)
}
@@ -492,16 +612,16 @@ where
/// Removes and returns the value in the set, if any, that is equal to the
/// given one.
///
- /// Like `Vec::swap_remove`, the value is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the value is removed by swapping it with the
/// last element of the set and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
/// Return `None` if `value` was not in the set.
///
/// Computes in **O(1)** time (average).
- pub fn swap_take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
+ pub fn swap_take<Q>(&mut self, value: &Q) -> Option<T>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.swap_remove_entry(value).map(|(x, ())| x)
}
@@ -509,48 +629,50 @@ where
/// Removes and returns the value in the set, if any, that is equal to the
/// given one.
///
- /// Like `Vec::remove`, the value is removed by shifting all of the
+ /// Like [`Vec::remove`], the value is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
/// Return `None` if `value` was not in the set.
///
/// Computes in **O(n)** time (average).
- pub fn shift_take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
+ pub fn shift_take<Q>(&mut self, value: &Q) -> Option<T>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.shift_remove_entry(value).map(|(x, ())| x)
}
/// Remove the value from the set return it and the index it had.
///
- /// Like `Vec::swap_remove`, the value is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the value is removed by swapping it with the
/// last element of the set and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
/// Return `None` if `value` was not in the set.
- pub fn swap_remove_full<Q: ?Sized>(&mut self, value: &Q) -> Option<(usize, T)>
+ pub fn swap_remove_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.swap_remove_full(value).map(|(i, x, ())| (i, x))
}
/// Remove the value from the set return it and the index it had.
///
- /// Like `Vec::remove`, the value is removed by shifting all of the
+ /// Like [`Vec::remove`], the value is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
/// Return `None` if `value` was not in the set.
- pub fn shift_remove_full<Q: ?Sized>(&mut self, value: &Q) -> Option<(usize, T)>
+ pub fn shift_remove_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
- Q: Hash + Equivalent<T>,
+ Q: ?Sized + Hash + Equivalent<T>,
{
self.map.shift_remove_full(value).map(|(i, x, ())| (i, x))
}
+}
+impl<T, S> IndexSet<T, S> {
/// Remove the last value
///
/// This preserves the order of the remaining elements.
@@ -576,6 +698,10 @@ where
/// Sort the set’s values by their default ordering.
///
+ /// This is a stable sort -- but equivalent values should not normally coexist in
+ /// a set at all, so [`sort_unstable`][Self::sort_unstable] is preferred
+ /// because it is generally faster and doesn't allocate auxiliary memory.
+ ///
/// See [`sort_by`](Self::sort_by) for details.
pub fn sort(&mut self)
where
@@ -604,9 +730,7 @@ where
{
let mut entries = self.into_entries();
entries.sort_by(move |a, b| cmp(&a.key, &b.key));
- IntoIter {
- iter: entries.into_iter(),
- }
+ IntoIter::new(entries)
}
/// Sort the set's values by their default ordering.
@@ -619,7 +743,7 @@ where
self.map.sort_unstable_keys()
}
- /// Sort the set's values in place using the comparison funtion `cmp`.
+ /// Sort the set's values in place using the comparison function `cmp`.
///
/// Computes in **O(n log n)** time. The sort is unstable.
pub fn sort_unstable_by<F>(&mut self, mut cmp: F)
@@ -637,9 +761,82 @@ where
{
let mut entries = self.into_entries();
entries.sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
- IntoIter {
- iter: entries.into_iter(),
- }
+ IntoIter::new(entries)
+ }
+
+ /// Sort the set’s values in place using a key extraction function.
+ ///
+ /// During sorting, the function is called at most once per entry, by using temporary storage
+ /// to remember the results of its evaluation. The order of calls to the function is
+ /// unspecified and may change between versions of `indexmap` or the standard library.
+ ///
+ /// Computes in **O(m n + n log n + c)** time () and **O(n)** space, where the function is
+ /// **O(m)**, *n* is the length of the map, and *c* the capacity. The sort is stable.
+ pub fn sort_by_cached_key<K, F>(&mut self, mut sort_key: F)
+ where
+ K: Ord,
+ F: FnMut(&T) -> K,
+ {
+ self.with_entries(move |entries| {
+ entries.sort_by_cached_key(move |a| sort_key(&a.key));
+ });
+ }
+
+ /// Search over a sorted set for a value.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search`] for more details.
+ ///
+ /// Computes in **O(log(n))** time, which is notably less scalable than looking the value up
+ /// using [`get_index_of`][IndexSet::get_index_of], but this can also position missing values.
+ pub fn binary_search(&self, x: &T) -> Result<usize, usize>
+ where
+ T: Ord,
+ {
+ self.as_slice().binary_search(x)
+ }
+
+ /// Search over a sorted set with a comparator function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a T) -> Ordering,
+ {
+ self.as_slice().binary_search_by(f)
+ }
+
+ /// Search over a sorted set with an extraction function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by_key`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a T) -> B,
+ B: Ord,
+ {
+ self.as_slice().binary_search_by_key(b, f)
+ }
+
+ /// Returns the index of the partition point of a sorted set according to the given predicate
+ /// (the index of the first element of the second partition).
+ ///
+ /// See [`slice::partition_point`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[must_use]
+ pub fn partition_point<P>(&self, pred: P) -> usize
+ where
+ P: FnMut(&T) -> bool,
+ {
+ self.as_slice().partition_point(pred)
}
/// Reverses the order of the set’s values in place.
@@ -648,9 +845,21 @@ where
pub fn reverse(&mut self) {
self.map.reverse()
}
-}
-impl<T, S> IndexSet<T, S> {
+ /// Returns a slice of all the values in the set.
+ ///
+ /// Computes in **O(1)** time.
+ pub fn as_slice(&self) -> &Slice<T> {
+ Slice::from_slice(self.as_entries())
+ }
+
+ /// Converts into a boxed slice of all the values in the set.
+ ///
+ /// Note that this will drop the inner hash table and any excess capacity.
+ pub fn into_boxed_slice(self) -> Box<Slice<T>> {
+ Slice::from_boxed(self.into_entries().into_boxed_slice())
+ }
+
/// Get a value by index
///
/// Valid indices are *0 <= index < self.len()*
@@ -660,6 +869,17 @@ impl<T, S> IndexSet<T, S> {
self.as_entries().get(index).map(Bucket::key_ref)
}
+ /// Returns a slice of values in the given range of indices.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ ///
+ /// Computes in **O(1)** time.
+ pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Slice<T>> {
+ let entries = self.as_entries();
+ let range = try_simplify_range(range, entries.len())?;
+ entries.get(range).map(Slice::from_slice)
+ }
+
/// Get the first value
///
/// Computes in **O(1)** time.
@@ -678,7 +898,7 @@ impl<T, S> IndexSet<T, S> {
///
/// Valid indices are *0 <= index < self.len()*
///
- /// Like `Vec::swap_remove`, the value is removed by swapping it with the
+ /// Like [`Vec::swap_remove`], the value is removed by swapping it with the
/// last element of the set and popping it off. **This perturbs
/// the position of what used to be the last element!**
///
@@ -691,7 +911,7 @@ impl<T, S> IndexSet<T, S> {
///
/// Valid indices are *0 <= index < self.len()*
///
- /// Like `Vec::remove`, the value is removed by shifting all of the
+ /// Like [`Vec::remove`], the value is removed by shifting all of the
/// elements that follow it, preserving their relative order.
/// **This perturbs the index of all of those elements!**
///
@@ -716,12 +936,14 @@ impl<T, S> IndexSet<T, S> {
/// Swaps the position of two values in the set.
///
/// ***Panics*** if `a` or `b` are out of bounds.
+ ///
+ /// Computes in **O(1)** time (average).
pub fn swap_indices(&mut self, a: usize, b: usize) {
self.map.swap_indices(a, b)
}
}
-/// Access `IndexSet` values at indexed positions.
+/// Access [`IndexSet`] values at indexed positions.
///
/// # Examples
///
@@ -761,141 +983,6 @@ impl<T, S> Index<usize> for IndexSet<T, S> {
}
}
-/// An owning iterator over the items of a `IndexSet`.
-///
-/// This `struct` is created by the [`into_iter`] method on [`IndexSet`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
-///
-/// [`IndexSet`]: struct.IndexSet.html
-/// [`into_iter`]: struct.IndexSet.html#method.into_iter
-pub struct IntoIter<T> {
- iter: vec::IntoIter<Bucket<T>>,
-}
-
-impl<T> Iterator for IntoIter<T> {
- type Item = T;
-
- iterator_methods!(Bucket::key);
-}
-
-impl<T> DoubleEndedIterator for IntoIter<T> {
- double_ended_iterator_methods!(Bucket::key);
-}
-
-impl<T> ExactSizeIterator for IntoIter<T> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<T> FusedIterator for IntoIter<T> {}
-
-impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::key_ref);
- f.debug_list().entries(iter).finish()
- }
-}
-
-/// An iterator over the items of a `IndexSet`.
-///
-/// This `struct` is created by the [`iter`] method on [`IndexSet`].
-/// See its documentation for more.
-///
-/// [`IndexSet`]: struct.IndexSet.html
-/// [`iter`]: struct.IndexSet.html#method.iter
-pub struct Iter<'a, T> {
- iter: slice::Iter<'a, Bucket<T>>,
-}
-
-impl<'a, T> Iterator for Iter<'a, T> {
- type Item = &'a T;
-
- iterator_methods!(Bucket::key_ref);
-}
-
-impl<T> DoubleEndedIterator for Iter<'_, T> {
- double_ended_iterator_methods!(Bucket::key_ref);
-}
-
-impl<T> ExactSizeIterator for Iter<'_, T> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<T> FusedIterator for Iter<'_, T> {}
-
-impl<T> Clone for Iter<'_, T> {
- fn clone(&self) -> Self {
- Iter {
- iter: self.iter.clone(),
- }
- }
-}
-
-impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-/// A draining iterator over the items of a `IndexSet`.
-///
-/// This `struct` is created by the [`drain`] method on [`IndexSet`].
-/// See its documentation for more.
-///
-/// [`IndexSet`]: struct.IndexSet.html
-/// [`drain`]: struct.IndexSet.html#method.drain
-pub struct Drain<'a, T> {
- iter: vec::Drain<'a, Bucket<T>>,
-}
-
-impl<T> Iterator for Drain<'_, T> {
- type Item = T;
-
- iterator_methods!(Bucket::key);
-}
-
-impl<T> DoubleEndedIterator for Drain<'_, T> {
- double_ended_iterator_methods!(Bucket::key);
-}
-
-impl<T> ExactSizeIterator for Drain<'_, T> {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl<T> FusedIterator for Drain<'_, T> {}
-
-impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let iter = self.iter.as_slice().iter().map(Bucket::key_ref);
- f.debug_list().entries(iter).finish()
- }
-}
-
-impl<'a, T, S> IntoIterator for &'a IndexSet<T, S> {
- type Item = &'a T;
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Self::IntoIter {
- self.iter()
- }
-}
-
-impl<T, S> IntoIterator for IndexSet<T, S> {
- type Item = T;
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> Self::IntoIter {
- IntoIter {
- iter: self.into_entries().into_iter(),
- }
- }
-}
-
impl<T, S> FromIterator<T> for IndexSet<T, S>
where
T: Hash + Eq,
@@ -909,7 +996,8 @@ where
}
}
-#[cfg(has_std)]
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T, const N: usize> From<[T; N]> for IndexSet<T, RandomState>
where
T: Eq + Hash,
@@ -954,7 +1042,7 @@ impl<T, S> Default for IndexSet<T, S>
where
S: Default,
{
- /// Return an empty `IndexSet`
+ /// Return an empty [`IndexSet`]
fn default() -> Self {
IndexSet {
map: IndexMap::default(),
@@ -1014,310 +1102,6 @@ where
}
}
-/// A lazy iterator producing elements in the difference of `IndexSet`s.
-///
-/// This `struct` is created by the [`difference`] method on [`IndexSet`].
-/// See its documentation for more.
-///
-/// [`IndexSet`]: struct.IndexSet.html
-/// [`difference`]: struct.IndexSet.html#method.difference
-pub struct Difference<'a, T, S> {
- iter: Iter<'a, T>,
- other: &'a IndexSet<T, S>,
-}
-
-impl<'a, T, S> Iterator for Difference<'a, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
- type Item = &'a T;
-
- fn next(&mut self) -> Option<Self::Item> {
- while let Some(item) = self.iter.next() {
- if !self.other.contains(item) {
- return Some(item);
- }
- }
- None
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (0, self.iter.size_hint().1)
- }
-}
-
-impl<T, S> DoubleEndedIterator for Difference<'_, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
- fn next_back(&mut self) -> Option<Self::Item> {
- while let Some(item) = self.iter.next_back() {
- if !self.other.contains(item) {
- return Some(item);
- }
- }
- None
- }
-}
-
-impl<T, S> FusedIterator for Difference<'_, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
-}
-
-impl<T, S> Clone for Difference<'_, T, S> {
- fn clone(&self) -> Self {
- Difference {
- iter: self.iter.clone(),
- ..*self
- }
- }
-}
-
-impl<T, S> fmt::Debug for Difference<'_, T, S>
-where
- T: fmt::Debug + Eq + Hash,
- S: BuildHasher,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-/// A lazy iterator producing elements in the intersection of `IndexSet`s.
-///
-/// This `struct` is created by the [`intersection`] method on [`IndexSet`].
-/// See its documentation for more.
-///
-/// [`IndexSet`]: struct.IndexSet.html
-/// [`intersection`]: struct.IndexSet.html#method.intersection
-pub struct Intersection<'a, T, S> {
- iter: Iter<'a, T>,
- other: &'a IndexSet<T, S>,
-}
-
-impl<'a, T, S> Iterator for Intersection<'a, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
- type Item = &'a T;
-
- fn next(&mut self) -> Option<Self::Item> {
- while let Some(item) = self.iter.next() {
- if self.other.contains(item) {
- return Some(item);
- }
- }
- None
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (0, self.iter.size_hint().1)
- }
-}
-
-impl<T, S> DoubleEndedIterator for Intersection<'_, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
- fn next_back(&mut self) -> Option<Self::Item> {
- while let Some(item) = self.iter.next_back() {
- if self.other.contains(item) {
- return Some(item);
- }
- }
- None
- }
-}
-
-impl<T, S> FusedIterator for Intersection<'_, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
-}
-
-impl<T, S> Clone for Intersection<'_, T, S> {
- fn clone(&self) -> Self {
- Intersection {
- iter: self.iter.clone(),
- ..*self
- }
- }
-}
-
-impl<T, S> fmt::Debug for Intersection<'_, T, S>
-where
- T: fmt::Debug + Eq + Hash,
- S: BuildHasher,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-/// A lazy iterator producing elements in the symmetric difference of `IndexSet`s.
-///
-/// This `struct` is created by the [`symmetric_difference`] method on
-/// [`IndexSet`]. See its documentation for more.
-///
-/// [`IndexSet`]: struct.IndexSet.html
-/// [`symmetric_difference`]: struct.IndexSet.html#method.symmetric_difference
-pub struct SymmetricDifference<'a, T, S1, S2> {
- iter: Chain<Difference<'a, T, S2>, Difference<'a, T, S1>>,
-}
-
-impl<'a, T, S1, S2> Iterator for SymmetricDifference<'a, T, S1, S2>
-where
- T: Eq + Hash,
- S1: BuildHasher,
- S2: BuildHasher,
-{
- type Item = &'a T;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-
- fn fold<B, F>(self, init: B, f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter.fold(init, f)
- }
-}
-
-impl<T, S1, S2> DoubleEndedIterator for SymmetricDifference<'_, T, S1, S2>
-where
- T: Eq + Hash,
- S1: BuildHasher,
- S2: BuildHasher,
-{
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-
- fn rfold<B, F>(self, init: B, f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter.rfold(init, f)
- }
-}
-
-impl<T, S1, S2> FusedIterator for SymmetricDifference<'_, T, S1, S2>
-where
- T: Eq + Hash,
- S1: BuildHasher,
- S2: BuildHasher,
-{
-}
-
-impl<T, S1, S2> Clone for SymmetricDifference<'_, T, S1, S2> {
- fn clone(&self) -> Self {
- SymmetricDifference {
- iter: self.iter.clone(),
- }
- }
-}
-
-impl<T, S1, S2> fmt::Debug for SymmetricDifference<'_, T, S1, S2>
-where
- T: fmt::Debug + Eq + Hash,
- S1: BuildHasher,
- S2: BuildHasher,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-/// A lazy iterator producing elements in the union of `IndexSet`s.
-///
-/// This `struct` is created by the [`union`] method on [`IndexSet`].
-/// See its documentation for more.
-///
-/// [`IndexSet`]: struct.IndexSet.html
-/// [`union`]: struct.IndexSet.html#method.union
-pub struct Union<'a, T, S> {
- iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
-}
-
-impl<'a, T, S> Iterator for Union<'a, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
- type Item = &'a T;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-
- fn fold<B, F>(self, init: B, f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter.fold(init, f)
- }
-}
-
-impl<T, S> DoubleEndedIterator for Union<'_, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-
- fn rfold<B, F>(self, init: B, f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter.rfold(init, f)
- }
-}
-
-impl<T, S> FusedIterator for Union<'_, T, S>
-where
- T: Eq + Hash,
- S: BuildHasher,
-{
-}
-
-impl<T, S> Clone for Union<'_, T, S> {
- fn clone(&self) -> Self {
- Union {
- iter: self.iter.clone(),
- }
- }
-}
-
-impl<T, S> fmt::Debug for Union<'_, T, S>
-where
- T: fmt::Debug + Eq + Hash,
- S: BuildHasher,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
impl<T, S1, S2> BitAnd<&IndexSet<T, S2>> for &IndexSet<T, S1>
where
T: Eq + Hash + Clone,
@@ -1383,530 +1167,3 @@ where
self.difference(other).cloned().collect()
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::string::String;
-
- #[test]
- fn it_works() {
- let mut set = IndexSet::new();
- assert_eq!(set.is_empty(), true);
- set.insert(1);
- set.insert(1);
- assert_eq!(set.len(), 1);
- assert!(set.get(&1).is_some());
- assert_eq!(set.is_empty(), false);
- }
-
- #[test]
- fn new() {
- let set = IndexSet::<String>::new();
- println!("{:?}", set);
- assert_eq!(set.capacity(), 0);
- assert_eq!(set.len(), 0);
- assert_eq!(set.is_empty(), true);
- }
-
- #[test]
- fn insert() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5];
- let not_present = [1, 3, 6, 9, 10];
- let mut set = IndexSet::with_capacity(insert.len());
-
- for (i, &elt) in insert.iter().enumerate() {
- assert_eq!(set.len(), i);
- set.insert(elt);
- assert_eq!(set.len(), i + 1);
- assert_eq!(set.get(&elt), Some(&elt));
- }
- println!("{:?}", set);
-
- for &elt in &not_present {
- assert!(set.get(&elt).is_none());
- }
- }
-
- #[test]
- fn insert_full() {
- let insert = vec![9, 2, 7, 1, 4, 6, 13];
- let present = vec![1, 6, 2];
- let mut set = IndexSet::with_capacity(insert.len());
-
- for (i, &elt) in insert.iter().enumerate() {
- assert_eq!(set.len(), i);
- let (index, success) = set.insert_full(elt);
- assert!(success);
- assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
- assert_eq!(set.len(), i + 1);
- }
-
- let len = set.len();
- for &elt in &present {
- let (index, success) = set.insert_full(elt);
- assert!(!success);
- assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
- assert_eq!(set.len(), len);
- }
- }
-
- #[test]
- fn insert_2() {
- let mut set = IndexSet::with_capacity(16);
-
- let mut values = vec![];
- values.extend(0..16);
- values.extend(if cfg!(miri) { 32..64 } else { 128..267 });
-
- for &i in &values {
- let old_set = set.clone();
- set.insert(i);
- for value in old_set.iter() {
- if set.get(value).is_none() {
- println!("old_set: {:?}", old_set);
- println!("set: {:?}", set);
- panic!("did not find {} in set", value);
- }
- }
- }
-
- for &i in &values {
- assert!(set.get(&i).is_some(), "did not find {}", i);
- }
- }
-
- #[test]
- fn insert_dup() {
- let mut elements = vec![0, 2, 4, 6, 8];
- let mut set: IndexSet<u8> = elements.drain(..).collect();
- {
- let (i, v) = set.get_full(&0).unwrap();
- assert_eq!(set.len(), 5);
- assert_eq!(i, 0);
- assert_eq!(*v, 0);
- }
- {
- let inserted = set.insert(0);
- let (i, v) = set.get_full(&0).unwrap();
- assert_eq!(set.len(), 5);
- assert_eq!(inserted, false);
- assert_eq!(i, 0);
- assert_eq!(*v, 0);
- }
- }
-
- #[test]
- fn insert_order() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
- let mut set = IndexSet::new();
-
- for &elt in &insert {
- set.insert(elt);
- }
-
- assert_eq!(set.iter().count(), set.len());
- assert_eq!(set.iter().count(), insert.len());
- for (a, b) in insert.iter().zip(set.iter()) {
- assert_eq!(a, b);
- }
- for (i, v) in (0..insert.len()).zip(set.iter()) {
- assert_eq!(set.get_index(i).unwrap(), v);
- }
- }
-
- #[test]
- fn replace() {
- let replace = [0, 4, 2, 12, 8, 7, 11, 5];
- let not_present = [1, 3, 6, 9, 10];
- let mut set = IndexSet::with_capacity(replace.len());
-
- for (i, &elt) in replace.iter().enumerate() {
- assert_eq!(set.len(), i);
- set.replace(elt);
- assert_eq!(set.len(), i + 1);
- assert_eq!(set.get(&elt), Some(&elt));
- }
- println!("{:?}", set);
-
- for &elt in &not_present {
- assert!(set.get(&elt).is_none());
- }
- }
-
- #[test]
- fn replace_full() {
- let replace = vec![9, 2, 7, 1, 4, 6, 13];
- let present = vec![1, 6, 2];
- let mut set = IndexSet::with_capacity(replace.len());
-
- for (i, &elt) in replace.iter().enumerate() {
- assert_eq!(set.len(), i);
- let (index, replaced) = set.replace_full(elt);
- assert!(replaced.is_none());
- assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
- assert_eq!(set.len(), i + 1);
- }
-
- let len = set.len();
- for &elt in &present {
- let (index, replaced) = set.replace_full(elt);
- assert_eq!(Some(elt), replaced);
- assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
- assert_eq!(set.len(), len);
- }
- }
-
- #[test]
- fn replace_2() {
- let mut set = IndexSet::with_capacity(16);
-
- let mut values = vec![];
- values.extend(0..16);
- values.extend(if cfg!(miri) { 32..64 } else { 128..267 });
-
- for &i in &values {
- let old_set = set.clone();
- set.replace(i);
- for value in old_set.iter() {
- if set.get(value).is_none() {
- println!("old_set: {:?}", old_set);
- println!("set: {:?}", set);
- panic!("did not find {} in set", value);
- }
- }
- }
-
- for &i in &values {
- assert!(set.get(&i).is_some(), "did not find {}", i);
- }
- }
-
- #[test]
- fn replace_dup() {
- let mut elements = vec![0, 2, 4, 6, 8];
- let mut set: IndexSet<u8> = elements.drain(..).collect();
- {
- let (i, v) = set.get_full(&0).unwrap();
- assert_eq!(set.len(), 5);
- assert_eq!(i, 0);
- assert_eq!(*v, 0);
- }
- {
- let replaced = set.replace(0);
- let (i, v) = set.get_full(&0).unwrap();
- assert_eq!(set.len(), 5);
- assert_eq!(replaced, Some(0));
- assert_eq!(i, 0);
- assert_eq!(*v, 0);
- }
- }
-
- #[test]
- fn replace_order() {
- let replace = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
- let mut set = IndexSet::new();
-
- for &elt in &replace {
- set.replace(elt);
- }
-
- assert_eq!(set.iter().count(), set.len());
- assert_eq!(set.iter().count(), replace.len());
- for (a, b) in replace.iter().zip(set.iter()) {
- assert_eq!(a, b);
- }
- for (i, v) in (0..replace.len()).zip(set.iter()) {
- assert_eq!(set.get_index(i).unwrap(), v);
- }
- }
-
- #[test]
- fn grow() {
- let insert = [0, 4, 2, 12, 8, 7, 11];
- let not_present = [1, 3, 6, 9, 10];
- let mut set = IndexSet::with_capacity(insert.len());
-
- for (i, &elt) in insert.iter().enumerate() {
- assert_eq!(set.len(), i);
- set.insert(elt);
- assert_eq!(set.len(), i + 1);
- assert_eq!(set.get(&elt), Some(&elt));
- }
-
- println!("{:?}", set);
- for &elt in &insert {
- set.insert(elt * 10);
- }
- for &elt in &insert {
- set.insert(elt * 100);
- }
- for (i, &elt) in insert.iter().cycle().enumerate().take(100) {
- set.insert(elt * 100 + i as i32);
- }
- println!("{:?}", set);
- for &elt in &not_present {
- assert!(set.get(&elt).is_none());
- }
- }
-
- #[test]
- fn reserve() {
- let mut set = IndexSet::<usize>::new();
- assert_eq!(set.capacity(), 0);
- set.reserve(100);
- let capacity = set.capacity();
- assert!(capacity >= 100);
- for i in 0..capacity {
- assert_eq!(set.len(), i);
- set.insert(i);
- assert_eq!(set.len(), i + 1);
- assert_eq!(set.capacity(), capacity);
- assert_eq!(set.get(&i), Some(&i));
- }
- set.insert(capacity);
- assert_eq!(set.len(), capacity + 1);
- assert!(set.capacity() > capacity);
- assert_eq!(set.get(&capacity), Some(&capacity));
- }
-
- #[test]
- fn shrink_to_fit() {
- let mut set = IndexSet::<usize>::new();
- assert_eq!(set.capacity(), 0);
- for i in 0..100 {
- assert_eq!(set.len(), i);
- set.insert(i);
- assert_eq!(set.len(), i + 1);
- assert!(set.capacity() >= i + 1);
- assert_eq!(set.get(&i), Some(&i));
- set.shrink_to_fit();
- assert_eq!(set.len(), i + 1);
- assert_eq!(set.capacity(), i + 1);
- assert_eq!(set.get(&i), Some(&i));
- }
- }
-
- #[test]
- fn remove() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
- let mut set = IndexSet::new();
-
- for &elt in &insert {
- set.insert(elt);
- }
-
- assert_eq!(set.iter().count(), set.len());
- assert_eq!(set.iter().count(), insert.len());
- for (a, b) in insert.iter().zip(set.iter()) {
- assert_eq!(a, b);
- }
-
- let remove_fail = [99, 77];
- let remove = [4, 12, 8, 7];
-
- for &value in &remove_fail {
- assert!(set.swap_remove_full(&value).is_none());
- }
- println!("{:?}", set);
- for &value in &remove {
- //println!("{:?}", set);
- let index = set.get_full(&value).unwrap().0;
- assert_eq!(set.swap_remove_full(&value), Some((index, value)));
- }
- println!("{:?}", set);
-
- for value in &insert {
- assert_eq!(set.get(value).is_some(), !remove.contains(value));
- }
- assert_eq!(set.len(), insert.len() - remove.len());
- assert_eq!(set.iter().count(), insert.len() - remove.len());
- }
-
- #[test]
- fn swap_remove_index() {
- let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
- let mut set = IndexSet::new();
-
- for &elt in &insert {
- set.insert(elt);
- }
-
- let mut vector = insert.to_vec();
- let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1];
-
- // check that the same swap remove sequence on vec and set
- // have the same result.
- for &rm in remove_sequence {
- let out_vec = vector.swap_remove(rm);
- let out_set = set.swap_remove_index(rm).unwrap();
- assert_eq!(out_vec, out_set);
- }
- assert_eq!(vector.len(), set.len());
- for (a, b) in vector.iter().zip(set.iter()) {
- assert_eq!(a, b);
- }
- }
-
- #[test]
- fn partial_eq_and_eq() {
- let mut set_a = IndexSet::new();
- set_a.insert(1);
- set_a.insert(2);
- let mut set_b = set_a.clone();
- assert_eq!(set_a, set_b);
- set_b.swap_remove(&1);
- assert_ne!(set_a, set_b);
-
- let set_c: IndexSet<_> = set_b.into_iter().collect();
- assert_ne!(set_a, set_c);
- assert_ne!(set_c, set_a);
- }
-
- #[test]
- fn extend() {
- let mut set = IndexSet::new();
- set.extend(vec![&1, &2, &3, &4]);
- set.extend(vec![5, 6]);
- assert_eq!(set.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6]);
- }
-
- #[test]
- fn comparisons() {
- let set_a: IndexSet<_> = (0..3).collect();
- let set_b: IndexSet<_> = (3..6).collect();
- let set_c: IndexSet<_> = (0..6).collect();
- let set_d: IndexSet<_> = (3..9).collect();
-
- assert!(!set_a.is_disjoint(&set_a));
- assert!(set_a.is_subset(&set_a));
- assert!(set_a.is_superset(&set_a));
-
- assert!(set_a.is_disjoint(&set_b));
- assert!(set_b.is_disjoint(&set_a));
- assert!(!set_a.is_subset(&set_b));
- assert!(!set_b.is_subset(&set_a));
- assert!(!set_a.is_superset(&set_b));
- assert!(!set_b.is_superset(&set_a));
-
- assert!(!set_a.is_disjoint(&set_c));
- assert!(!set_c.is_disjoint(&set_a));
- assert!(set_a.is_subset(&set_c));
- assert!(!set_c.is_subset(&set_a));
- assert!(!set_a.is_superset(&set_c));
- assert!(set_c.is_superset(&set_a));
-
- assert!(!set_c.is_disjoint(&set_d));
- assert!(!set_d.is_disjoint(&set_c));
- assert!(!set_c.is_subset(&set_d));
- assert!(!set_d.is_subset(&set_c));
- assert!(!set_c.is_superset(&set_d));
- assert!(!set_d.is_superset(&set_c));
- }
-
- #[test]
- fn iter_comparisons() {
- use std::iter::empty;
-
- fn check<'a, I1, I2>(iter1: I1, iter2: I2)
- where
- I1: Iterator<Item = &'a i32>,
- I2: Iterator<Item = i32>,
- {
- assert!(iter1.copied().eq(iter2));
- }
-
- let set_a: IndexSet<_> = (0..3).collect();
- let set_b: IndexSet<_> = (3..6).collect();
- let set_c: IndexSet<_> = (0..6).collect();
- let set_d: IndexSet<_> = (3..9).rev().collect();
-
- check(set_a.difference(&set_a), empty());
- check(set_a.symmetric_difference(&set_a), empty());
- check(set_a.intersection(&set_a), 0..3);
- check(set_a.union(&set_a), 0..3);
-
- check(set_a.difference(&set_b), 0..3);
- check(set_b.difference(&set_a), 3..6);
- check(set_a.symmetric_difference(&set_b), 0..6);
- check(set_b.symmetric_difference(&set_a), (3..6).chain(0..3));
- check(set_a.intersection(&set_b), empty());
- check(set_b.intersection(&set_a), empty());
- check(set_a.union(&set_b), 0..6);
- check(set_b.union(&set_a), (3..6).chain(0..3));
-
- check(set_a.difference(&set_c), empty());
- check(set_c.difference(&set_a), 3..6);
- check(set_a.symmetric_difference(&set_c), 3..6);
- check(set_c.symmetric_difference(&set_a), 3..6);
- check(set_a.intersection(&set_c), 0..3);
- check(set_c.intersection(&set_a), 0..3);
- check(set_a.union(&set_c), 0..6);
- check(set_c.union(&set_a), 0..6);
-
- check(set_c.difference(&set_d), 0..3);
- check(set_d.difference(&set_c), (6..9).rev());
- check(
- set_c.symmetric_difference(&set_d),
- (0..3).chain((6..9).rev()),
- );
- check(set_d.symmetric_difference(&set_c), (6..9).rev().chain(0..3));
- check(set_c.intersection(&set_d), 3..6);
- check(set_d.intersection(&set_c), (3..6).rev());
- check(set_c.union(&set_d), (0..6).chain((6..9).rev()));
- check(set_d.union(&set_c), (3..9).rev().chain(0..3));
- }
-
- #[test]
- fn ops() {
- let empty = IndexSet::<i32>::new();
- let set_a: IndexSet<_> = (0..3).collect();
- let set_b: IndexSet<_> = (3..6).collect();
- let set_c: IndexSet<_> = (0..6).collect();
- let set_d: IndexSet<_> = (3..9).rev().collect();
-
- #[allow(clippy::eq_op)]
- {
- assert_eq!(&set_a & &set_a, set_a);
- assert_eq!(&set_a | &set_a, set_a);
- assert_eq!(&set_a ^ &set_a, empty);
- assert_eq!(&set_a - &set_a, empty);
- }
-
- assert_eq!(&set_a & &set_b, empty);
- assert_eq!(&set_b & &set_a, empty);
- assert_eq!(&set_a | &set_b, set_c);
- assert_eq!(&set_b | &set_a, set_c);
- assert_eq!(&set_a ^ &set_b, set_c);
- assert_eq!(&set_b ^ &set_a, set_c);
- assert_eq!(&set_a - &set_b, set_a);
- assert_eq!(&set_b - &set_a, set_b);
-
- assert_eq!(&set_a & &set_c, set_a);
- assert_eq!(&set_c & &set_a, set_a);
- assert_eq!(&set_a | &set_c, set_c);
- assert_eq!(&set_c | &set_a, set_c);
- assert_eq!(&set_a ^ &set_c, set_b);
- assert_eq!(&set_c ^ &set_a, set_b);
- assert_eq!(&set_a - &set_c, empty);
- assert_eq!(&set_c - &set_a, set_b);
-
- assert_eq!(&set_c & &set_d, set_b);
- assert_eq!(&set_d & &set_c, set_b);
- assert_eq!(&set_c | &set_d, &set_a | &set_d);
- assert_eq!(&set_d | &set_c, &set_a | &set_d);
- assert_eq!(&set_c ^ &set_d, &set_a | &(&set_d - &set_b));
- assert_eq!(&set_d ^ &set_c, &set_a | &(&set_d - &set_b));
- assert_eq!(&set_c - &set_d, set_a);
- assert_eq!(&set_d - &set_c, &set_d - &set_b);
- }
-
- #[test]
- #[cfg(has_std)]
- fn from_array() {
- let set1 = IndexSet::from([1, 2, 3, 4]);
- let set2: IndexSet<_> = [1, 2, 3, 4].into();
-
- assert_eq!(set1, set2);
- }
-}
diff --git a/third_party/rust/indexmap/src/set/iter.rs b/third_party/rust/indexmap/src/set/iter.rs
new file mode 100644
index 0000000000..3f8033c2db
--- /dev/null
+++ b/third_party/rust/indexmap/src/set/iter.rs
@@ -0,0 +1,626 @@
+use super::{Bucket, Entries, IndexSet, Slice};
+
+use alloc::vec::{self, Vec};
+use core::fmt;
+use core::hash::{BuildHasher, Hash};
+use core::iter::{Chain, FusedIterator};
+use core::ops::RangeBounds;
+use core::slice::Iter as SliceIter;
+
+impl<'a, T, S> IntoIterator for &'a IndexSet<T, S> {
+ type Item = &'a T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<T, S> IntoIterator for IndexSet<T, S> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ IntoIter::new(self.into_entries())
+ }
+}
+
+/// An iterator over the items of an [`IndexSet`].
+///
+/// This `struct` is created by the [`IndexSet::iter`] method.
+/// See its documentation for more.
+pub struct Iter<'a, T> {
+ iter: SliceIter<'a, Bucket<T>>,
+}
+
+impl<'a, T> Iter<'a, T> {
+ pub(super) fn new(entries: &'a [Bucket<T>]) -> Self {
+ Self {
+ iter: entries.iter(),
+ }
+ }
+
+ /// Returns a slice of the remaining entries in the iterator.
+ pub fn as_slice(&self) -> &'a Slice<T> {
+ Slice::from_slice(self.iter.as_slice())
+ }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ iterator_methods!(Bucket::key_ref);
+}
+
+impl<T> DoubleEndedIterator for Iter<'_, T> {
+ double_ended_iterator_methods!(Bucket::key_ref);
+}
+
+impl<T> ExactSizeIterator for Iter<'_, T> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<T> FusedIterator for Iter<'_, T> {}
+
+impl<T> Clone for Iter<'_, T> {
+ fn clone(&self) -> Self {
+ Iter {
+ iter: self.iter.clone(),
+ }
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+impl<T> Default for Iter<'_, T> {
+ fn default() -> Self {
+ Self { iter: [].iter() }
+ }
+}
+
+/// An owning iterator over the items of an [`IndexSet`].
+///
+/// This `struct` is created by the [`IndexSet::into_iter`] method
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
+pub struct IntoIter<T> {
+ iter: vec::IntoIter<Bucket<T>>,
+}
+
+impl<T> IntoIter<T> {
+ pub(super) fn new(entries: Vec<Bucket<T>>) -> Self {
+ Self {
+ iter: entries.into_iter(),
+ }
+ }
+
+ /// Returns a slice of the remaining entries in the iterator.
+ pub fn as_slice(&self) -> &Slice<T> {
+ Slice::from_slice(self.iter.as_slice())
+ }
+}
+
+impl<T> Iterator for IntoIter<T> {
+ type Item = T;
+
+ iterator_methods!(Bucket::key);
+}
+
+impl<T> DoubleEndedIterator for IntoIter<T> {
+ double_ended_iterator_methods!(Bucket::key);
+}
+
+impl<T> ExactSizeIterator for IntoIter<T> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<T> FusedIterator for IntoIter<T> {}
+
+impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::key_ref);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+impl<T> Default for IntoIter<T> {
+ fn default() -> Self {
+ Self {
+ iter: Vec::new().into_iter(),
+ }
+ }
+}
+
+/// A draining iterator over the items of an [`IndexSet`].
+///
+/// This `struct` is created by the [`IndexSet::drain`] method.
+/// See its documentation for more.
+pub struct Drain<'a, T> {
+ iter: vec::Drain<'a, Bucket<T>>,
+}
+
+impl<'a, T> Drain<'a, T> {
+ pub(super) fn new(iter: vec::Drain<'a, Bucket<T>>) -> Self {
+ Self { iter }
+ }
+
+ /// Returns a slice of the remaining entries in the iterator.
+ pub fn as_slice(&self) -> &Slice<T> {
+ Slice::from_slice(self.iter.as_slice())
+ }
+}
+
+impl<T> Iterator for Drain<'_, T> {
+ type Item = T;
+
+ iterator_methods!(Bucket::key);
+}
+
+impl<T> DoubleEndedIterator for Drain<'_, T> {
+ double_ended_iterator_methods!(Bucket::key);
+}
+
+impl<T> ExactSizeIterator for Drain<'_, T> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<T> FusedIterator for Drain<'_, T> {}
+
+impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let iter = self.iter.as_slice().iter().map(Bucket::key_ref);
+ f.debug_list().entries(iter).finish()
+ }
+}
+
+/// A lazy iterator producing elements in the difference of [`IndexSet`]s.
+///
+/// This `struct` is created by the [`IndexSet::difference`] method.
+/// See its documentation for more.
+pub struct Difference<'a, T, S> {
+ iter: Iter<'a, T>,
+ other: &'a IndexSet<T, S>,
+}
+
+impl<'a, T, S> Difference<'a, T, S> {
+ pub(super) fn new<S1>(set: &'a IndexSet<T, S1>, other: &'a IndexSet<T, S>) -> Self {
+ Self {
+ iter: set.iter(),
+ other,
+ }
+ }
+}
+
+impl<'a, T, S> Iterator for Difference<'a, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ while let Some(item) = self.iter.next() {
+ if !self.other.contains(item) {
+ return Some(item);
+ }
+ }
+ None
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, self.iter.size_hint().1)
+ }
+}
+
+impl<T, S> DoubleEndedIterator for Difference<'_, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ while let Some(item) = self.iter.next_back() {
+ if !self.other.contains(item) {
+ return Some(item);
+ }
+ }
+ None
+ }
+}
+
+impl<T, S> FusedIterator for Difference<'_, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+}
+
+impl<T, S> Clone for Difference<'_, T, S> {
+ fn clone(&self) -> Self {
+ Difference {
+ iter: self.iter.clone(),
+ ..*self
+ }
+ }
+}
+
+impl<T, S> fmt::Debug for Difference<'_, T, S>
+where
+ T: fmt::Debug + Eq + Hash,
+ S: BuildHasher,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+/// A lazy iterator producing elements in the intersection of [`IndexSet`]s.
+///
+/// This `struct` is created by the [`IndexSet::intersection`] method.
+/// See its documentation for more.
+pub struct Intersection<'a, T, S> {
+ iter: Iter<'a, T>,
+ other: &'a IndexSet<T, S>,
+}
+
+impl<'a, T, S> Intersection<'a, T, S> {
+ pub(super) fn new<S1>(set: &'a IndexSet<T, S1>, other: &'a IndexSet<T, S>) -> Self {
+ Self {
+ iter: set.iter(),
+ other,
+ }
+ }
+}
+
+impl<'a, T, S> Iterator for Intersection<'a, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ while let Some(item) = self.iter.next() {
+ if self.other.contains(item) {
+ return Some(item);
+ }
+ }
+ None
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, self.iter.size_hint().1)
+ }
+}
+
+impl<T, S> DoubleEndedIterator for Intersection<'_, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ while let Some(item) = self.iter.next_back() {
+ if self.other.contains(item) {
+ return Some(item);
+ }
+ }
+ None
+ }
+}
+
+impl<T, S> FusedIterator for Intersection<'_, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+}
+
+impl<T, S> Clone for Intersection<'_, T, S> {
+ fn clone(&self) -> Self {
+ Intersection {
+ iter: self.iter.clone(),
+ ..*self
+ }
+ }
+}
+
+impl<T, S> fmt::Debug for Intersection<'_, T, S>
+where
+ T: fmt::Debug + Eq + Hash,
+ S: BuildHasher,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+/// A lazy iterator producing elements in the symmetric difference of [`IndexSet`]s.
+///
+/// This `struct` is created by the [`IndexSet::symmetric_difference`] method.
+/// See its documentation for more.
+pub struct SymmetricDifference<'a, T, S1, S2> {
+ iter: Chain<Difference<'a, T, S2>, Difference<'a, T, S1>>,
+}
+
+impl<'a, T, S1, S2> SymmetricDifference<'a, T, S1, S2>
+where
+ T: Eq + Hash,
+ S1: BuildHasher,
+ S2: BuildHasher,
+{
+ pub(super) fn new(set1: &'a IndexSet<T, S1>, set2: &'a IndexSet<T, S2>) -> Self {
+ let diff1 = set1.difference(set2);
+ let diff2 = set2.difference(set1);
+ Self {
+ iter: diff1.chain(diff2),
+ }
+ }
+}
+
+impl<'a, T, S1, S2> Iterator for SymmetricDifference<'a, T, S1, S2>
+where
+ T: Eq + Hash,
+ S1: BuildHasher,
+ S2: BuildHasher,
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, f)
+ }
+}
+
+impl<T, S1, S2> DoubleEndedIterator for SymmetricDifference<'_, T, S1, S2>
+where
+ T: Eq + Hash,
+ S1: BuildHasher,
+ S2: BuildHasher,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+
+ fn rfold<B, F>(self, init: B, f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.rfold(init, f)
+ }
+}
+
+impl<T, S1, S2> FusedIterator for SymmetricDifference<'_, T, S1, S2>
+where
+ T: Eq + Hash,
+ S1: BuildHasher,
+ S2: BuildHasher,
+{
+}
+
+impl<T, S1, S2> Clone for SymmetricDifference<'_, T, S1, S2> {
+ fn clone(&self) -> Self {
+ SymmetricDifference {
+ iter: self.iter.clone(),
+ }
+ }
+}
+
+impl<T, S1, S2> fmt::Debug for SymmetricDifference<'_, T, S1, S2>
+where
+ T: fmt::Debug + Eq + Hash,
+ S1: BuildHasher,
+ S2: BuildHasher,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+/// A lazy iterator producing elements in the union of [`IndexSet`]s.
+///
+/// This `struct` is created by the [`IndexSet::union`] method.
+/// See its documentation for more.
+pub struct Union<'a, T, S> {
+ iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
+}
+
+impl<'a, T, S> Union<'a, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+ pub(super) fn new<S2>(set1: &'a IndexSet<T, S>, set2: &'a IndexSet<T, S2>) -> Self
+ where
+ S2: BuildHasher,
+ {
+ Self {
+ iter: set1.iter().chain(set2.difference(set1)),
+ }
+ }
+}
+
+impl<'a, T, S> Iterator for Union<'a, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.fold(init, f)
+ }
+}
+
+impl<T, S> DoubleEndedIterator for Union<'_, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+
+ fn rfold<B, F>(self, init: B, f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter.rfold(init, f)
+ }
+}
+
+impl<T, S> FusedIterator for Union<'_, T, S>
+where
+ T: Eq + Hash,
+ S: BuildHasher,
+{
+}
+
+impl<T, S> Clone for Union<'_, T, S> {
+ fn clone(&self) -> Self {
+ Union {
+ iter: self.iter.clone(),
+ }
+ }
+}
+
+impl<T, S> fmt::Debug for Union<'_, T, S>
+where
+ T: fmt::Debug + Eq + Hash,
+ S: BuildHasher,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+/// A splicing iterator for `IndexSet`.
+///
+/// This `struct` is created by [`IndexSet::splice()`].
+/// See its documentation for more.
+pub struct Splice<'a, I, T, S>
+where
+ I: Iterator<Item = T>,
+ T: Hash + Eq,
+ S: BuildHasher,
+{
+ iter: crate::map::Splice<'a, UnitValue<I>, T, (), S>,
+}
+
+impl<'a, I, T, S> Splice<'a, I, T, S>
+where
+ I: Iterator<Item = T>,
+ T: Hash + Eq,
+ S: BuildHasher,
+{
+ pub(super) fn new<R>(set: &'a mut IndexSet<T, S>, range: R, replace_with: I) -> Self
+ where
+ R: RangeBounds<usize>,
+ {
+ Self {
+ iter: set.map.splice(range, UnitValue(replace_with)),
+ }
+ }
+}
+
+impl<I, T, S> Iterator for Splice<'_, I, T, S>
+where
+ I: Iterator<Item = T>,
+ T: Hash + Eq,
+ S: BuildHasher,
+{
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ Some(self.iter.next()?.0)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<I, T, S> DoubleEndedIterator for Splice<'_, I, T, S>
+where
+ I: Iterator<Item = T>,
+ T: Hash + Eq,
+ S: BuildHasher,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ Some(self.iter.next_back()?.0)
+ }
+}
+
+impl<I, T, S> ExactSizeIterator for Splice<'_, I, T, S>
+where
+ I: Iterator<Item = T>,
+ T: Hash + Eq,
+ S: BuildHasher,
+{
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<I, T, S> FusedIterator for Splice<'_, I, T, S>
+where
+ I: Iterator<Item = T>,
+ T: Hash + Eq,
+ S: BuildHasher,
+{
+}
+
+struct UnitValue<I>(I);
+
+impl<I: Iterator> Iterator for UnitValue<I> {
+ type Item = (I::Item, ());
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next().map(|x| (x, ()))
+ }
+}
+
+impl<'a, I, T, S> fmt::Debug for Splice<'a, I, T, S>
+where
+ I: fmt::Debug + Iterator<Item = T>,
+ T: fmt::Debug + Hash + Eq,
+ S: BuildHasher,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.iter, f)
+ }
+}
+
+impl<I: fmt::Debug> fmt::Debug for UnitValue<I> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.0, f)
+ }
+}
diff --git a/third_party/rust/indexmap/src/set/mutable.rs b/third_party/rust/indexmap/src/set/mutable.rs
new file mode 100644
index 0000000000..20eaa11221
--- /dev/null
+++ b/third_party/rust/indexmap/src/set/mutable.rs
@@ -0,0 +1,86 @@
+use core::hash::{BuildHasher, Hash};
+
+use super::{Equivalent, IndexSet};
+use crate::map::MutableKeys;
+
+/// Opt-in mutable access to [`IndexSet`] values.
+///
+/// These methods expose `&mut T`, mutable references to the value as it is stored
+/// in the set.
+/// You are allowed to modify the values in the set **if the modification
+/// does not change the value’s hash and equality**.
+///
+/// If values are modified erroneously, you can no longer look them up.
+/// This is sound (memory safe) but a logical error hazard (just like
+/// implementing `PartialEq`, `Eq`, or `Hash` incorrectly would be).
+///
+/// `use` this trait to enable its methods for `IndexSet`.
+///
+/// This trait is sealed and cannot be implemented for types outside this crate.
+pub trait MutableValues: private::Sealed {
+ type Value;
+
+ /// Return item index and mutable reference to the value
+ ///
+ /// Computes in **O(1)** time (average).
+ fn get_full_mut2<Q>(&mut self, value: &Q) -> Option<(usize, &mut Self::Value)>
+ where
+ Q: ?Sized + Hash + Equivalent<Self::Value>;
+
+ /// Return mutable reference to the value at an index.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ ///
+ /// Computes in **O(1)** time.
+ fn get_index_mut2(&mut self, index: usize) -> Option<&mut Self::Value>;
+
+ /// Scan through each value in the set and keep those where the
+ /// closure `keep` returns `true`.
+ ///
+ /// The values are visited in order, and remaining values keep their order.
+ ///
+ /// Computes in **O(n)** time (average).
+ fn retain2<F>(&mut self, keep: F)
+ where
+ F: FnMut(&mut Self::Value) -> bool;
+}
+
+/// Opt-in mutable access to [`IndexSet`] values.
+///
+/// See [`MutableValues`] for more information.
+impl<T, S> MutableValues for IndexSet<T, S>
+where
+ S: BuildHasher,
+{
+ type Value = T;
+
+ fn get_full_mut2<Q>(&mut self, value: &Q) -> Option<(usize, &mut T)>
+ where
+ Q: ?Sized + Hash + Equivalent<T>,
+ {
+ match self.map.get_full_mut2(value) {
+ Some((index, value, ())) => Some((index, value)),
+ None => None,
+ }
+ }
+
+ fn get_index_mut2(&mut self, index: usize) -> Option<&mut T> {
+ match self.map.get_index_mut2(index) {
+ Some((value, ())) => Some(value),
+ None => None,
+ }
+ }
+
+ fn retain2<F>(&mut self, mut keep: F)
+ where
+ F: FnMut(&mut T) -> bool,
+ {
+ self.map.retain2(move |value, ()| keep(value));
+ }
+}
+
+mod private {
+ pub trait Sealed {}
+
+ impl<T, S> Sealed for super::IndexSet<T, S> {}
+}
diff --git a/third_party/rust/indexmap/src/set/slice.rs b/third_party/rust/indexmap/src/set/slice.rs
new file mode 100644
index 0000000000..9fc208c706
--- /dev/null
+++ b/third_party/rust/indexmap/src/set/slice.rs
@@ -0,0 +1,340 @@
+use super::{Bucket, Entries, IndexSet, IntoIter, Iter};
+use crate::util::try_simplify_range;
+
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::cmp::Ordering;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ops::{self, Bound, Index, RangeBounds};
+
+/// A dynamically-sized slice of values in an [`IndexSet`].
+///
+/// This supports indexed operations much like a `[T]` slice,
+/// but not any hashed operations on the values.
+///
+/// Unlike `IndexSet`, `Slice` does consider the order for [`PartialEq`]
+/// and [`Eq`], and it also implements [`PartialOrd`], [`Ord`], and [`Hash`].
+#[repr(transparent)]
+pub struct Slice<T> {
+ pub(crate) entries: [Bucket<T>],
+}
+
+// SAFETY: `Slice<T>` is a transparent wrapper around `[Bucket<T>]`,
+// and reference lifetimes are bound together in function signatures.
+#[allow(unsafe_code)]
+impl<T> Slice<T> {
+ pub(super) const fn from_slice(entries: &[Bucket<T>]) -> &Self {
+ unsafe { &*(entries as *const [Bucket<T>] as *const Self) }
+ }
+
+ pub(super) fn from_boxed(entries: Box<[Bucket<T>]>) -> Box<Self> {
+ unsafe { Box::from_raw(Box::into_raw(entries) as *mut Self) }
+ }
+
+ fn into_boxed(self: Box<Self>) -> Box<[Bucket<T>]> {
+ unsafe { Box::from_raw(Box::into_raw(self) as *mut [Bucket<T>]) }
+ }
+}
+
+impl<T> Slice<T> {
+ pub(crate) fn into_entries(self: Box<Self>) -> Vec<Bucket<T>> {
+ self.into_boxed().into_vec()
+ }
+
+ /// Returns an empty slice.
+ pub const fn new<'a>() -> &'a Self {
+ Self::from_slice(&[])
+ }
+
+ /// Return the number of elements in the set slice.
+ pub const fn len(&self) -> usize {
+ self.entries.len()
+ }
+
+ /// Returns true if the set slice contains no elements.
+ pub const fn is_empty(&self) -> bool {
+ self.entries.is_empty()
+ }
+
+ /// Get a value by index.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ pub fn get_index(&self, index: usize) -> Option<&T> {
+ self.entries.get(index).map(Bucket::key_ref)
+ }
+
+ /// Returns a slice of values in the given range of indices.
+ ///
+ /// Valid indices are *0 <= index < self.len()*
+ pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self> {
+ let range = try_simplify_range(range, self.entries.len())?;
+ self.entries.get(range).map(Self::from_slice)
+ }
+
+ /// Get the first value.
+ pub fn first(&self) -> Option<&T> {
+ self.entries.first().map(Bucket::key_ref)
+ }
+
+ /// Get the last value.
+ pub fn last(&self) -> Option<&T> {
+ self.entries.last().map(Bucket::key_ref)
+ }
+
+ /// Divides one slice into two at an index.
+ ///
+ /// ***Panics*** if `index > len`.
+ pub fn split_at(&self, index: usize) -> (&Self, &Self) {
+ let (first, second) = self.entries.split_at(index);
+ (Self::from_slice(first), Self::from_slice(second))
+ }
+
+ /// Returns the first value and the rest of the slice,
+ /// or `None` if it is empty.
+ pub fn split_first(&self) -> Option<(&T, &Self)> {
+ if let [first, rest @ ..] = &self.entries {
+ Some((&first.key, Self::from_slice(rest)))
+ } else {
+ None
+ }
+ }
+
+ /// Returns the last value and the rest of the slice,
+ /// or `None` if it is empty.
+ pub fn split_last(&self) -> Option<(&T, &Self)> {
+ if let [rest @ .., last] = &self.entries {
+ Some((&last.key, Self::from_slice(rest)))
+ } else {
+ None
+ }
+ }
+
+ /// Return an iterator over the values of the set slice.
+ pub fn iter(&self) -> Iter<'_, T> {
+ Iter::new(&self.entries)
+ }
+
+ /// Search over a sorted set for a value.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search`] for more details.
+ ///
+ /// Computes in **O(log(n))** time, which is notably less scalable than looking the value up in
+ /// the set this is a slice from using [`IndexSet::get_index_of`], but this can also position
+ /// missing values.
+ pub fn binary_search(&self, x: &T) -> Result<usize, usize>
+ where
+ T: Ord,
+ {
+ self.binary_search_by(|p| p.cmp(x))
+ }
+
+ /// Search over a sorted set with a comparator function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a T) -> Ordering,
+ {
+ self.entries.binary_search_by(move |a| f(&a.key))
+ }
+
+ /// Search over a sorted set with an extraction function.
+ ///
+ /// Returns the position where that value is present, or the position where it can be inserted
+ /// to maintain the sort. See [`slice::binary_search_by_key`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[inline]
+ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a T) -> B,
+ B: Ord,
+ {
+ self.binary_search_by(|k| f(k).cmp(b))
+ }
+
+ /// Returns the index of the partition point of a sorted set according to the given predicate
+ /// (the index of the first element of the second partition).
+ ///
+ /// See [`slice::partition_point`] for more details.
+ ///
+ /// Computes in **O(log(n))** time.
+ #[must_use]
+ pub fn partition_point<P>(&self, mut pred: P) -> usize
+ where
+ P: FnMut(&T) -> bool,
+ {
+ self.entries.partition_point(move |a| pred(&a.key))
+ }
+}
+
+impl<'a, T> IntoIterator for &'a Slice<T> {
+ type IntoIter = Iter<'a, T>;
+ type Item = &'a T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<T> IntoIterator for Box<Slice<T>> {
+ type IntoIter = IntoIter<T>;
+ type Item = T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ IntoIter::new(self.into_entries())
+ }
+}
+
+impl<T> Default for &'_ Slice<T> {
+ fn default() -> Self {
+ Slice::from_slice(&[])
+ }
+}
+
+impl<T> Default for Box<Slice<T>> {
+ fn default() -> Self {
+ Slice::from_boxed(Box::default())
+ }
+}
+
+impl<T: Clone> Clone for Box<Slice<T>> {
+ fn clone(&self) -> Self {
+ Slice::from_boxed(self.entries.to_vec().into_boxed_slice())
+ }
+}
+
+impl<T: Copy> From<&Slice<T>> for Box<Slice<T>> {
+ fn from(slice: &Slice<T>) -> Self {
+ Slice::from_boxed(Box::from(&slice.entries))
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for Slice<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self).finish()
+ }
+}
+
+impl<T: PartialEq> PartialEq for Slice<T> {
+ fn eq(&self, other: &Self) -> bool {
+ self.len() == other.len() && self.iter().eq(other)
+ }
+}
+
+impl<T: Eq> Eq for Slice<T> {}
+
+impl<T: PartialOrd> PartialOrd for Slice<T> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.iter().partial_cmp(other)
+ }
+}
+
+impl<T: Ord> Ord for Slice<T> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.iter().cmp(other)
+ }
+}
+
+impl<T: Hash> Hash for Slice<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.len().hash(state);
+ for value in self {
+ value.hash(state);
+ }
+ }
+}
+
+impl<T> Index<usize> for Slice<T> {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self.entries[index].key
+ }
+}
+
+// We can't have `impl<I: RangeBounds<usize>> Index<I>` because that conflicts with `Index<usize>`.
+// Instead, we repeat the implementations for all the core range types.
+macro_rules! impl_index {
+ ($($range:ty),*) => {$(
+ impl<T, S> Index<$range> for IndexSet<T, S> {
+ type Output = Slice<T>;
+
+ fn index(&self, range: $range) -> &Self::Output {
+ Slice::from_slice(&self.as_entries()[range])
+ }
+ }
+
+ impl<T> Index<$range> for Slice<T> {
+ type Output = Self;
+
+ fn index(&self, range: $range) -> &Self::Output {
+ Slice::from_slice(&self.entries[range])
+ }
+ }
+ )*}
+}
+impl_index!(
+ ops::Range<usize>,
+ ops::RangeFrom<usize>,
+ ops::RangeFull,
+ ops::RangeInclusive<usize>,
+ ops::RangeTo<usize>,
+ ops::RangeToInclusive<usize>,
+ (Bound<usize>, Bound<usize>)
+);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn slice_index() {
+ fn check(vec_slice: &[i32], set_slice: &Slice<i32>, sub_slice: &Slice<i32>) {
+ assert_eq!(set_slice as *const _, sub_slice as *const _);
+ itertools::assert_equal(vec_slice, set_slice);
+ }
+
+ let vec: Vec<i32> = (0..10).map(|i| i * i).collect();
+ let set: IndexSet<i32> = vec.iter().cloned().collect();
+ let slice = set.as_slice();
+
+ // RangeFull
+ check(&vec[..], &set[..], &slice[..]);
+
+ for i in 0usize..10 {
+ // Index
+ assert_eq!(vec[i], set[i]);
+ assert_eq!(vec[i], slice[i]);
+
+ // RangeFrom
+ check(&vec[i..], &set[i..], &slice[i..]);
+
+ // RangeTo
+ check(&vec[..i], &set[..i], &slice[..i]);
+
+ // RangeToInclusive
+ check(&vec[..=i], &set[..=i], &slice[..=i]);
+
+ // (Bound<usize>, Bound<usize>)
+ let bounds = (Bound::Excluded(i), Bound::Unbounded);
+ check(&vec[i + 1..], &set[bounds], &slice[bounds]);
+
+ for j in i..=10 {
+ // Range
+ check(&vec[i..j], &set[i..j], &slice[i..j]);
+ }
+
+ for j in i..10 {
+ // RangeInclusive
+ check(&vec[i..=j], &set[i..=j], &slice[i..=j]);
+ }
+ }
+ }
+}
diff --git a/third_party/rust/indexmap/src/set/tests.rs b/third_party/rust/indexmap/src/set/tests.rs
new file mode 100644
index 0000000000..35a076e8de
--- /dev/null
+++ b/third_party/rust/indexmap/src/set/tests.rs
@@ -0,0 +1,723 @@
+use super::*;
+use std::string::String;
+
+#[test]
+fn it_works() {
+ let mut set = IndexSet::new();
+ assert_eq!(set.is_empty(), true);
+ set.insert(1);
+ set.insert(1);
+ assert_eq!(set.len(), 1);
+ assert!(set.get(&1).is_some());
+ assert_eq!(set.is_empty(), false);
+}
+
+#[test]
+fn new() {
+ let set = IndexSet::<String>::new();
+ println!("{:?}", set);
+ assert_eq!(set.capacity(), 0);
+ assert_eq!(set.len(), 0);
+ assert_eq!(set.is_empty(), true);
+}
+
+#[test]
+fn insert() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5];
+ let not_present = [1, 3, 6, 9, 10];
+ let mut set = IndexSet::with_capacity(insert.len());
+
+ for (i, &elt) in insert.iter().enumerate() {
+ assert_eq!(set.len(), i);
+ set.insert(elt);
+ assert_eq!(set.len(), i + 1);
+ assert_eq!(set.get(&elt), Some(&elt));
+ }
+ println!("{:?}", set);
+
+ for &elt in &not_present {
+ assert!(set.get(&elt).is_none());
+ }
+}
+
+#[test]
+fn insert_full() {
+ let insert = vec![9, 2, 7, 1, 4, 6, 13];
+ let present = vec![1, 6, 2];
+ let mut set = IndexSet::with_capacity(insert.len());
+
+ for (i, &elt) in insert.iter().enumerate() {
+ assert_eq!(set.len(), i);
+ let (index, success) = set.insert_full(elt);
+ assert!(success);
+ assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
+ assert_eq!(set.len(), i + 1);
+ }
+
+ let len = set.len();
+ for &elt in &present {
+ let (index, success) = set.insert_full(elt);
+ assert!(!success);
+ assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
+ assert_eq!(set.len(), len);
+ }
+}
+
+#[test]
+fn insert_2() {
+ let mut set = IndexSet::with_capacity(16);
+
+ let mut values = vec![];
+ values.extend(0..16);
+ values.extend(if cfg!(miri) { 32..64 } else { 128..267 });
+
+ for &i in &values {
+ let old_set = set.clone();
+ set.insert(i);
+ for value in old_set.iter() {
+ if set.get(value).is_none() {
+ println!("old_set: {:?}", old_set);
+ println!("set: {:?}", set);
+ panic!("did not find {} in set", value);
+ }
+ }
+ }
+
+ for &i in &values {
+ assert!(set.get(&i).is_some(), "did not find {}", i);
+ }
+}
+
+#[test]
+fn insert_dup() {
+ let mut elements = vec![0, 2, 4, 6, 8];
+ let mut set: IndexSet<u8> = elements.drain(..).collect();
+ {
+ let (i, v) = set.get_full(&0).unwrap();
+ assert_eq!(set.len(), 5);
+ assert_eq!(i, 0);
+ assert_eq!(*v, 0);
+ }
+ {
+ let inserted = set.insert(0);
+ let (i, v) = set.get_full(&0).unwrap();
+ assert_eq!(set.len(), 5);
+ assert_eq!(inserted, false);
+ assert_eq!(i, 0);
+ assert_eq!(*v, 0);
+ }
+}
+
+#[test]
+fn insert_order() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut set = IndexSet::new();
+
+ for &elt in &insert {
+ set.insert(elt);
+ }
+
+ assert_eq!(set.iter().count(), set.len());
+ assert_eq!(set.iter().count(), insert.len());
+ for (a, b) in insert.iter().zip(set.iter()) {
+ assert_eq!(a, b);
+ }
+ for (i, v) in (0..insert.len()).zip(set.iter()) {
+ assert_eq!(set.get_index(i).unwrap(), v);
+ }
+}
+
+#[test]
+fn shift_insert() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut set = IndexSet::new();
+
+ for &elt in &insert {
+ set.shift_insert(0, elt);
+ }
+
+ assert_eq!(set.iter().count(), set.len());
+ assert_eq!(set.iter().count(), insert.len());
+ for (a, b) in insert.iter().rev().zip(set.iter()) {
+ assert_eq!(a, b);
+ }
+ for (i, v) in (0..insert.len()).zip(set.iter()) {
+ assert_eq!(set.get_index(i).unwrap(), v);
+ }
+
+ // "insert" that moves an existing entry
+ set.shift_insert(0, insert[0]);
+ assert_eq!(set.iter().count(), insert.len());
+ assert_eq!(insert[0], set[0]);
+ for (a, b) in insert[1..].iter().rev().zip(set.iter().skip(1)) {
+ assert_eq!(a, b);
+ }
+}
+
+#[test]
+fn replace() {
+ let replace = [0, 4, 2, 12, 8, 7, 11, 5];
+ let not_present = [1, 3, 6, 9, 10];
+ let mut set = IndexSet::with_capacity(replace.len());
+
+ for (i, &elt) in replace.iter().enumerate() {
+ assert_eq!(set.len(), i);
+ set.replace(elt);
+ assert_eq!(set.len(), i + 1);
+ assert_eq!(set.get(&elt), Some(&elt));
+ }
+ println!("{:?}", set);
+
+ for &elt in &not_present {
+ assert!(set.get(&elt).is_none());
+ }
+}
+
+#[test]
+fn replace_full() {
+ let replace = vec![9, 2, 7, 1, 4, 6, 13];
+ let present = vec![1, 6, 2];
+ let mut set = IndexSet::with_capacity(replace.len());
+
+ for (i, &elt) in replace.iter().enumerate() {
+ assert_eq!(set.len(), i);
+ let (index, replaced) = set.replace_full(elt);
+ assert!(replaced.is_none());
+ assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
+ assert_eq!(set.len(), i + 1);
+ }
+
+ let len = set.len();
+ for &elt in &present {
+ let (index, replaced) = set.replace_full(elt);
+ assert_eq!(Some(elt), replaced);
+ assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
+ assert_eq!(set.len(), len);
+ }
+}
+
+#[test]
+fn replace_2() {
+ let mut set = IndexSet::with_capacity(16);
+
+ let mut values = vec![];
+ values.extend(0..16);
+ values.extend(if cfg!(miri) { 32..64 } else { 128..267 });
+
+ for &i in &values {
+ let old_set = set.clone();
+ set.replace(i);
+ for value in old_set.iter() {
+ if set.get(value).is_none() {
+ println!("old_set: {:?}", old_set);
+ println!("set: {:?}", set);
+ panic!("did not find {} in set", value);
+ }
+ }
+ }
+
+ for &i in &values {
+ assert!(set.get(&i).is_some(), "did not find {}", i);
+ }
+}
+
+#[test]
+fn replace_dup() {
+ let mut elements = vec![0, 2, 4, 6, 8];
+ let mut set: IndexSet<u8> = elements.drain(..).collect();
+ {
+ let (i, v) = set.get_full(&0).unwrap();
+ assert_eq!(set.len(), 5);
+ assert_eq!(i, 0);
+ assert_eq!(*v, 0);
+ }
+ {
+ let replaced = set.replace(0);
+ let (i, v) = set.get_full(&0).unwrap();
+ assert_eq!(set.len(), 5);
+ assert_eq!(replaced, Some(0));
+ assert_eq!(i, 0);
+ assert_eq!(*v, 0);
+ }
+}
+
+#[test]
+fn replace_order() {
+ let replace = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut set = IndexSet::new();
+
+ for &elt in &replace {
+ set.replace(elt);
+ }
+
+ assert_eq!(set.iter().count(), set.len());
+ assert_eq!(set.iter().count(), replace.len());
+ for (a, b) in replace.iter().zip(set.iter()) {
+ assert_eq!(a, b);
+ }
+ for (i, v) in (0..replace.len()).zip(set.iter()) {
+ assert_eq!(set.get_index(i).unwrap(), v);
+ }
+}
+
+#[test]
+fn replace_change() {
+ // Check pointers to make sure it really changes
+ let mut set = indexset!(vec![42]);
+ let old_ptr = set[0].as_ptr();
+ let new = set[0].clone();
+ let new_ptr = new.as_ptr();
+ assert_ne!(old_ptr, new_ptr);
+ let replaced = set.replace(new).unwrap();
+ assert_eq!(replaced.as_ptr(), old_ptr);
+}
+
+#[test]
+fn grow() {
+ let insert = [0, 4, 2, 12, 8, 7, 11];
+ let not_present = [1, 3, 6, 9, 10];
+ let mut set = IndexSet::with_capacity(insert.len());
+
+ for (i, &elt) in insert.iter().enumerate() {
+ assert_eq!(set.len(), i);
+ set.insert(elt);
+ assert_eq!(set.len(), i + 1);
+ assert_eq!(set.get(&elt), Some(&elt));
+ }
+
+ println!("{:?}", set);
+ for &elt in &insert {
+ set.insert(elt * 10);
+ }
+ for &elt in &insert {
+ set.insert(elt * 100);
+ }
+ for (i, &elt) in insert.iter().cycle().enumerate().take(100) {
+ set.insert(elt * 100 + i as i32);
+ }
+ println!("{:?}", set);
+ for &elt in &not_present {
+ assert!(set.get(&elt).is_none());
+ }
+}
+
+#[test]
+fn reserve() {
+ let mut set = IndexSet::<usize>::new();
+ assert_eq!(set.capacity(), 0);
+ set.reserve(100);
+ let capacity = set.capacity();
+ assert!(capacity >= 100);
+ for i in 0..capacity {
+ assert_eq!(set.len(), i);
+ set.insert(i);
+ assert_eq!(set.len(), i + 1);
+ assert_eq!(set.capacity(), capacity);
+ assert_eq!(set.get(&i), Some(&i));
+ }
+ set.insert(capacity);
+ assert_eq!(set.len(), capacity + 1);
+ assert!(set.capacity() > capacity);
+ assert_eq!(set.get(&capacity), Some(&capacity));
+}
+
+#[test]
+fn try_reserve() {
+ let mut set = IndexSet::<usize>::new();
+ assert_eq!(set.capacity(), 0);
+ assert_eq!(set.try_reserve(100), Ok(()));
+ assert!(set.capacity() >= 100);
+ assert!(set.try_reserve(usize::MAX).is_err());
+}
+
+#[test]
+fn shrink_to_fit() {
+ let mut set = IndexSet::<usize>::new();
+ assert_eq!(set.capacity(), 0);
+ for i in 0..100 {
+ assert_eq!(set.len(), i);
+ set.insert(i);
+ assert_eq!(set.len(), i + 1);
+ assert!(set.capacity() >= i + 1);
+ assert_eq!(set.get(&i), Some(&i));
+ set.shrink_to_fit();
+ assert_eq!(set.len(), i + 1);
+ assert_eq!(set.capacity(), i + 1);
+ assert_eq!(set.get(&i), Some(&i));
+ }
+}
+
+#[test]
+fn remove() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut set = IndexSet::new();
+
+ for &elt in &insert {
+ set.insert(elt);
+ }
+
+ assert_eq!(set.iter().count(), set.len());
+ assert_eq!(set.iter().count(), insert.len());
+ for (a, b) in insert.iter().zip(set.iter()) {
+ assert_eq!(a, b);
+ }
+
+ let remove_fail = [99, 77];
+ let remove = [4, 12, 8, 7];
+
+ for &value in &remove_fail {
+ assert!(set.swap_remove_full(&value).is_none());
+ }
+ println!("{:?}", set);
+ for &value in &remove {
+ //println!("{:?}", set);
+ let index = set.get_full(&value).unwrap().0;
+ assert_eq!(set.swap_remove_full(&value), Some((index, value)));
+ }
+ println!("{:?}", set);
+
+ for value in &insert {
+ assert_eq!(set.get(value).is_some(), !remove.contains(value));
+ }
+ assert_eq!(set.len(), insert.len() - remove.len());
+ assert_eq!(set.iter().count(), insert.len() - remove.len());
+}
+
+#[test]
+fn swap_remove_index() {
+ let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
+ let mut set = IndexSet::new();
+
+ for &elt in &insert {
+ set.insert(elt);
+ }
+
+ let mut vector = insert.to_vec();
+ let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1];
+
+ // check that the same swap remove sequence on vec and set
+ // have the same result.
+ for &rm in remove_sequence {
+ let out_vec = vector.swap_remove(rm);
+ let out_set = set.swap_remove_index(rm).unwrap();
+ assert_eq!(out_vec, out_set);
+ }
+ assert_eq!(vector.len(), set.len());
+ for (a, b) in vector.iter().zip(set.iter()) {
+ assert_eq!(a, b);
+ }
+}
+
+#[test]
+fn partial_eq_and_eq() {
+ let mut set_a = IndexSet::new();
+ set_a.insert(1);
+ set_a.insert(2);
+ let mut set_b = set_a.clone();
+ assert_eq!(set_a, set_b);
+ set_b.swap_remove(&1);
+ assert_ne!(set_a, set_b);
+
+ let set_c: IndexSet<_> = set_b.into_iter().collect();
+ assert_ne!(set_a, set_c);
+ assert_ne!(set_c, set_a);
+}
+
+#[test]
+fn extend() {
+ let mut set = IndexSet::new();
+ set.extend(vec![&1, &2, &3, &4]);
+ set.extend(vec![5, 6]);
+ assert_eq!(set.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6]);
+}
+
+#[test]
+fn comparisons() {
+ let set_a: IndexSet<_> = (0..3).collect();
+ let set_b: IndexSet<_> = (3..6).collect();
+ let set_c: IndexSet<_> = (0..6).collect();
+ let set_d: IndexSet<_> = (3..9).collect();
+
+ assert!(!set_a.is_disjoint(&set_a));
+ assert!(set_a.is_subset(&set_a));
+ assert!(set_a.is_superset(&set_a));
+
+ assert!(set_a.is_disjoint(&set_b));
+ assert!(set_b.is_disjoint(&set_a));
+ assert!(!set_a.is_subset(&set_b));
+ assert!(!set_b.is_subset(&set_a));
+ assert!(!set_a.is_superset(&set_b));
+ assert!(!set_b.is_superset(&set_a));
+
+ assert!(!set_a.is_disjoint(&set_c));
+ assert!(!set_c.is_disjoint(&set_a));
+ assert!(set_a.is_subset(&set_c));
+ assert!(!set_c.is_subset(&set_a));
+ assert!(!set_a.is_superset(&set_c));
+ assert!(set_c.is_superset(&set_a));
+
+ assert!(!set_c.is_disjoint(&set_d));
+ assert!(!set_d.is_disjoint(&set_c));
+ assert!(!set_c.is_subset(&set_d));
+ assert!(!set_d.is_subset(&set_c));
+ assert!(!set_c.is_superset(&set_d));
+ assert!(!set_d.is_superset(&set_c));
+}
+
+#[test]
+fn iter_comparisons() {
+ use std::iter::empty;
+
+ fn check<'a, I1, I2>(iter1: I1, iter2: I2)
+ where
+ I1: Iterator<Item = &'a i32>,
+ I2: Iterator<Item = i32>,
+ {
+ assert!(iter1.copied().eq(iter2));
+ }
+
+ let set_a: IndexSet<_> = (0..3).collect();
+ let set_b: IndexSet<_> = (3..6).collect();
+ let set_c: IndexSet<_> = (0..6).collect();
+ let set_d: IndexSet<_> = (3..9).rev().collect();
+
+ check(set_a.difference(&set_a), empty());
+ check(set_a.symmetric_difference(&set_a), empty());
+ check(set_a.intersection(&set_a), 0..3);
+ check(set_a.union(&set_a), 0..3);
+
+ check(set_a.difference(&set_b), 0..3);
+ check(set_b.difference(&set_a), 3..6);
+ check(set_a.symmetric_difference(&set_b), 0..6);
+ check(set_b.symmetric_difference(&set_a), (3..6).chain(0..3));
+ check(set_a.intersection(&set_b), empty());
+ check(set_b.intersection(&set_a), empty());
+ check(set_a.union(&set_b), 0..6);
+ check(set_b.union(&set_a), (3..6).chain(0..3));
+
+ check(set_a.difference(&set_c), empty());
+ check(set_c.difference(&set_a), 3..6);
+ check(set_a.symmetric_difference(&set_c), 3..6);
+ check(set_c.symmetric_difference(&set_a), 3..6);
+ check(set_a.intersection(&set_c), 0..3);
+ check(set_c.intersection(&set_a), 0..3);
+ check(set_a.union(&set_c), 0..6);
+ check(set_c.union(&set_a), 0..6);
+
+ check(set_c.difference(&set_d), 0..3);
+ check(set_d.difference(&set_c), (6..9).rev());
+ check(
+ set_c.symmetric_difference(&set_d),
+ (0..3).chain((6..9).rev()),
+ );
+ check(set_d.symmetric_difference(&set_c), (6..9).rev().chain(0..3));
+ check(set_c.intersection(&set_d), 3..6);
+ check(set_d.intersection(&set_c), (3..6).rev());
+ check(set_c.union(&set_d), (0..6).chain((6..9).rev()));
+ check(set_d.union(&set_c), (3..9).rev().chain(0..3));
+}
+
+#[test]
+fn ops() {
+ let empty = IndexSet::<i32>::new();
+ let set_a: IndexSet<_> = (0..3).collect();
+ let set_b: IndexSet<_> = (3..6).collect();
+ let set_c: IndexSet<_> = (0..6).collect();
+ let set_d: IndexSet<_> = (3..9).rev().collect();
+
+ #[allow(clippy::eq_op)]
+ {
+ assert_eq!(&set_a & &set_a, set_a);
+ assert_eq!(&set_a | &set_a, set_a);
+ assert_eq!(&set_a ^ &set_a, empty);
+ assert_eq!(&set_a - &set_a, empty);
+ }
+
+ assert_eq!(&set_a & &set_b, empty);
+ assert_eq!(&set_b & &set_a, empty);
+ assert_eq!(&set_a | &set_b, set_c);
+ assert_eq!(&set_b | &set_a, set_c);
+ assert_eq!(&set_a ^ &set_b, set_c);
+ assert_eq!(&set_b ^ &set_a, set_c);
+ assert_eq!(&set_a - &set_b, set_a);
+ assert_eq!(&set_b - &set_a, set_b);
+
+ assert_eq!(&set_a & &set_c, set_a);
+ assert_eq!(&set_c & &set_a, set_a);
+ assert_eq!(&set_a | &set_c, set_c);
+ assert_eq!(&set_c | &set_a, set_c);
+ assert_eq!(&set_a ^ &set_c, set_b);
+ assert_eq!(&set_c ^ &set_a, set_b);
+ assert_eq!(&set_a - &set_c, empty);
+ assert_eq!(&set_c - &set_a, set_b);
+
+ assert_eq!(&set_c & &set_d, set_b);
+ assert_eq!(&set_d & &set_c, set_b);
+ assert_eq!(&set_c | &set_d, &set_a | &set_d);
+ assert_eq!(&set_d | &set_c, &set_a | &set_d);
+ assert_eq!(&set_c ^ &set_d, &set_a | &(&set_d - &set_b));
+ assert_eq!(&set_d ^ &set_c, &set_a | &(&set_d - &set_b));
+ assert_eq!(&set_c - &set_d, set_a);
+ assert_eq!(&set_d - &set_c, &set_d - &set_b);
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn from_array() {
+ let set1 = IndexSet::from([1, 2, 3, 4]);
+ let set2: IndexSet<_> = [1, 2, 3, 4].into();
+
+ assert_eq!(set1, set2);
+}
+
+#[test]
+fn iter_default() {
+ struct Item;
+ fn assert_default<T>()
+ where
+ T: Default + Iterator,
+ {
+ assert!(T::default().next().is_none());
+ }
+ assert_default::<Iter<'static, Item>>();
+ assert_default::<IntoIter<Item>>();
+}
+
+#[test]
+fn test_binary_search_by() {
+ // adapted from std's test for binary_search
+ let b: IndexSet<i32> = [].into();
+ assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(0));
+
+ let b: IndexSet<i32> = [4].into();
+ assert_eq!(b.binary_search_by(|x| x.cmp(&3)), Err(0));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&4)), Ok(0));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(1));
+
+ let b: IndexSet<i32> = [1, 2, 4, 6, 8, 9].into();
+ assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(3));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&6)), Ok(3));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&7)), Err(4));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&8)), Ok(4));
+
+ let b: IndexSet<i32> = [1, 2, 4, 5, 6, 8].into();
+ assert_eq!(b.binary_search_by(|x| x.cmp(&9)), Err(6));
+
+ let b: IndexSet<i32> = [1, 2, 4, 6, 7, 8, 9].into();
+ assert_eq!(b.binary_search_by(|x| x.cmp(&6)), Ok(3));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(3));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&8)), Ok(5));
+
+ let b: IndexSet<i32> = [1, 2, 4, 5, 6, 8, 9].into();
+ assert_eq!(b.binary_search_by(|x| x.cmp(&7)), Err(5));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&0)), Err(0));
+
+ let b: IndexSet<i32> = [1, 3, 3, 3, 7].into();
+ assert_eq!(b.binary_search_by(|x| x.cmp(&0)), Err(0));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&1)), Ok(0));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&2)), Err(1));
+ // diff from std as set merges the duplicate keys
+ assert!(match b.binary_search_by(|x| x.cmp(&3)) {
+ Ok(1..=2) => true,
+ _ => false,
+ });
+ assert!(match b.binary_search_by(|x| x.cmp(&3)) {
+ Ok(1..=2) => true,
+ _ => false,
+ });
+ assert_eq!(b.binary_search_by(|x| x.cmp(&4)), Err(2));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(2));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&6)), Err(2));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&7)), Ok(2));
+ assert_eq!(b.binary_search_by(|x| x.cmp(&8)), Err(3));
+}
+
+#[test]
+fn test_binary_search_by_key() {
+ // adapted from std's test for binary_search
+ let b: IndexSet<i32> = [].into();
+ assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(0));
+
+ let b: IndexSet<i32> = [4].into();
+ assert_eq!(b.binary_search_by_key(&3, |&x| x), Err(0));
+ assert_eq!(b.binary_search_by_key(&4, |&x| x), Ok(0));
+ assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(1));
+
+ let b: IndexSet<i32> = [1, 2, 4, 6, 8, 9].into();
+ assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(3));
+ assert_eq!(b.binary_search_by_key(&6, |&x| x), Ok(3));
+ assert_eq!(b.binary_search_by_key(&7, |&x| x), Err(4));
+ assert_eq!(b.binary_search_by_key(&8, |&x| x), Ok(4));
+
+ let b: IndexSet<i32> = [1, 2, 4, 5, 6, 8].into();
+ assert_eq!(b.binary_search_by_key(&9, |&x| x), Err(6));
+
+ let b: IndexSet<i32> = [1, 2, 4, 6, 7, 8, 9].into();
+ assert_eq!(b.binary_search_by_key(&6, |&x| x), Ok(3));
+ assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(3));
+ assert_eq!(b.binary_search_by_key(&8, |&x| x), Ok(5));
+
+ let b: IndexSet<i32> = [1, 2, 4, 5, 6, 8, 9].into();
+ assert_eq!(b.binary_search_by_key(&7, |&x| x), Err(5));
+ assert_eq!(b.binary_search_by_key(&0, |&x| x), Err(0));
+
+ let b: IndexSet<i32> = [1, 3, 3, 3, 7].into();
+ assert_eq!(b.binary_search_by_key(&0, |&x| x), Err(0));
+ assert_eq!(b.binary_search_by_key(&1, |&x| x), Ok(0));
+ assert_eq!(b.binary_search_by_key(&2, |&x| x), Err(1));
+ // diff from std as set merges the duplicate keys
+ assert!(match b.binary_search_by_key(&3, |&x| x) {
+ Ok(1..=2) => true,
+ _ => false,
+ });
+ assert!(match b.binary_search_by_key(&3, |&x| x) {
+ Ok(1..=2) => true,
+ _ => false,
+ });
+ assert_eq!(b.binary_search_by_key(&4, |&x| x), Err(2));
+ assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(2));
+ assert_eq!(b.binary_search_by_key(&6, |&x| x), Err(2));
+ assert_eq!(b.binary_search_by_key(&7, |&x| x), Ok(2));
+ assert_eq!(b.binary_search_by_key(&8, |&x| x), Err(3));
+}
+
+#[test]
+fn test_partition_point() {
+ // adapted from std's test for partition_point
+ let b: IndexSet<i32> = [].into();
+ assert_eq!(b.partition_point(|&x| x < 5), 0);
+
+ let b: IndexSet<_> = [4].into();
+ assert_eq!(b.partition_point(|&x| x < 3), 0);
+ assert_eq!(b.partition_point(|&x| x < 4), 0);
+ assert_eq!(b.partition_point(|&x| x < 5), 1);
+
+ let b: IndexSet<_> = [1, 2, 4, 6, 8, 9].into();
+ assert_eq!(b.partition_point(|&x| x < 5), 3);
+ assert_eq!(b.partition_point(|&x| x < 6), 3);
+ assert_eq!(b.partition_point(|&x| x < 7), 4);
+ assert_eq!(b.partition_point(|&x| x < 8), 4);
+
+ let b: IndexSet<_> = [1, 2, 4, 5, 6, 8].into();
+ assert_eq!(b.partition_point(|&x| x < 9), 6);
+
+ let b: IndexSet<_> = [1, 2, 4, 6, 7, 8, 9].into();
+ assert_eq!(b.partition_point(|&x| x < 6), 3);
+ assert_eq!(b.partition_point(|&x| x < 5), 3);
+ assert_eq!(b.partition_point(|&x| x < 8), 5);
+
+ let b: IndexSet<_> = [1, 2, 4, 5, 6, 8, 9].into();
+ assert_eq!(b.partition_point(|&x| x < 7), 5);
+ assert_eq!(b.partition_point(|&x| x < 0), 0);
+
+ let b: IndexSet<_> = [1, 3, 3, 3, 7].into();
+ assert_eq!(b.partition_point(|&x| x < 0), 0);
+ assert_eq!(b.partition_point(|&x| x < 1), 0);
+ assert_eq!(b.partition_point(|&x| x < 2), 1);
+ assert_eq!(b.partition_point(|&x| x < 3), 1);
+ assert_eq!(b.partition_point(|&x| x < 4), 2); // diff from std as set merges the duplicate keys
+ assert_eq!(b.partition_point(|&x| x < 5), 2);
+ assert_eq!(b.partition_point(|&x| x < 6), 2);
+ assert_eq!(b.partition_point(|&x| x < 7), 2);
+ assert_eq!(b.partition_point(|&x| x < 8), 3);
+}
diff --git a/third_party/rust/indexmap/src/util.rs b/third_party/rust/indexmap/src/util.rs
index a24dfafde7..377ff516f0 100644
--- a/third_party/rust/indexmap/src/util.rs
+++ b/third_party/rust/indexmap/src/util.rs
@@ -29,3 +29,25 @@ where
}
start..end
}
+
+pub(crate) fn try_simplify_range<R>(range: R, len: usize) -> Option<Range<usize>>
+where
+ R: RangeBounds<usize>,
+{
+ let start = match range.start_bound() {
+ Bound::Unbounded => 0,
+ Bound::Included(&i) if i <= len => i,
+ Bound::Excluded(&i) if i < len => i + 1,
+ _ => return None,
+ };
+ let end = match range.end_bound() {
+ Bound::Unbounded => len,
+ Bound::Excluded(&i) if i <= len => i,
+ Bound::Included(&i) if i < len => i + 1,
+ _ => return None,
+ };
+ if start > end {
+ return None;
+ }
+ Some(start..end)
+}
diff --git a/third_party/rust/indexmap/tests/quick.rs b/third_party/rust/indexmap/tests/quick.rs
index e9d96acccb..56afee7239 100644
--- a/third_party/rust/indexmap/tests/quick.rs
+++ b/third_party/rust/indexmap/tests/quick.rs
@@ -19,8 +19,8 @@ use std::hash::Hash;
use std::ops::Bound;
use std::ops::Deref;
-use indexmap::map::Entry as OEntry;
-use std::collections::hash_map::Entry as HEntry;
+use indexmap::map::Entry;
+use std::collections::hash_map::Entry as StdEntry;
fn set<'a, T: 'a, I>(iter: I) -> HashSet<T>
where
@@ -113,6 +113,23 @@ quickcheck_limit! {
true
}
+ fn insert_sorted(insert: Vec<(u32, u32)>) -> bool {
+ let mut hmap = HashMap::new();
+ let mut map = IndexMap::new();
+ let mut map2 = IndexMap::new();
+ for &(key, value) in &insert {
+ hmap.insert(key, value);
+ map.insert_sorted(key, value);
+ match map2.entry(key) {
+ Entry::Occupied(e) => *e.into_mut() = value,
+ Entry::Vacant(e) => { e.insert_sorted(value); }
+ }
+ }
+ itertools::assert_equal(hmap.iter().sorted(), &map);
+ itertools::assert_equal(&map, &map2);
+ true
+ }
+
fn pop(insert: Vec<u8>) -> bool {
let mut map = IndexMap::new();
for &key in &insert {
@@ -218,7 +235,7 @@ quickcheck_limit! {
}
// Use `u8` test indices so quickcheck is less likely to go out of bounds.
- fn swap_indices(vec: Vec<u8>, a: u8, b: u8) -> TestResult {
+ fn set_swap_indices(vec: Vec<u8>, a: u8, b: u8) -> TestResult {
let mut set = IndexSet::<u8>::from_iter(vec);
let a = usize::from(a);
let b = usize::from(b);
@@ -240,8 +257,39 @@ quickcheck_limit! {
TestResult::passed()
}
+ fn map_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ test_map_swap_indices(vec, from, to, IndexMap::swap_indices)
+ }
+
+ fn occupied_entry_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ test_map_swap_indices(vec, from, to, |map, from, to| {
+ let key = map.keys()[from];
+ match map.entry(key) {
+ Entry::Occupied(entry) => entry.swap_indices(to),
+ _ => unreachable!(),
+ }
+ })
+ }
+
+ fn indexed_entry_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ test_map_swap_indices(vec, from, to, |map, from, to| {
+ map.get_index_entry(from).unwrap().swap_indices(to);
+ })
+ }
+
+ fn raw_occupied_entry_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ use indexmap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut};
+ test_map_swap_indices(vec, from, to, |map, from, to| {
+ let key = map.keys()[from];
+ match map.raw_entry_mut_v1().from_key(&key) {
+ RawEntryMut::Occupied(entry) => entry.swap_indices(to),
+ _ => unreachable!(),
+ }
+ })
+ }
+
// Use `u8` test indices so quickcheck is less likely to go out of bounds.
- fn move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ fn set_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
let mut set = IndexSet::<u8>::from_iter(vec);
let from = usize::from(from);
let to = usize::from(to);
@@ -263,6 +311,138 @@ quickcheck_limit! {
}));
TestResult::passed()
}
+
+ fn map_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ test_map_move_index(vec, from, to, IndexMap::move_index)
+ }
+
+ fn occupied_entry_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ test_map_move_index(vec, from, to, |map, from, to| {
+ let key = map.keys()[from];
+ match map.entry(key) {
+ Entry::Occupied(entry) => entry.move_index(to),
+ _ => unreachable!(),
+ }
+ })
+ }
+
+ fn indexed_entry_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ test_map_move_index(vec, from, to, |map, from, to| {
+ map.get_index_entry(from).unwrap().move_index(to);
+ })
+ }
+
+ fn raw_occupied_entry_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
+ use indexmap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut};
+ test_map_move_index(vec, from, to, |map, from, to| {
+ let key = map.keys()[from];
+ match map.raw_entry_mut_v1().from_key(&key) {
+ RawEntryMut::Occupied(entry) => entry.move_index(to),
+ _ => unreachable!(),
+ }
+ })
+ }
+
+ fn occupied_entry_shift_insert(vec: Vec<u8>, i: u8) -> TestResult {
+ test_map_shift_insert(vec, i, |map, i, key| {
+ match map.entry(key) {
+ Entry::Vacant(entry) => entry.shift_insert(i, ()),
+ _ => unreachable!(),
+ };
+ })
+ }
+
+ fn raw_occupied_entry_shift_insert(vec: Vec<u8>, i: u8) -> TestResult {
+ use indexmap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut};
+ test_map_shift_insert(vec, i, |map, i, key| {
+ match map.raw_entry_mut_v1().from_key(&key) {
+ RawEntryMut::Vacant(entry) => entry.shift_insert(i, key, ()),
+ _ => unreachable!(),
+ };
+ })
+ }
+}
+
+fn test_map_swap_indices<F>(vec: Vec<u8>, a: u8, b: u8, swap_indices: F) -> TestResult
+where
+ F: FnOnce(&mut IndexMap<u8, ()>, usize, usize),
+{
+ let mut map = IndexMap::<u8, ()>::from_iter(vec.into_iter().map(|k| (k, ())));
+ let a = usize::from(a);
+ let b = usize::from(b);
+
+ if a >= map.len() || b >= map.len() {
+ return TestResult::discard();
+ }
+
+ let mut vec = Vec::from_iter(map.keys().copied());
+ vec.swap(a, b);
+
+ swap_indices(&mut map, a, b);
+
+ // Check both iteration order and hash lookups
+ assert!(map.keys().eq(vec.iter()));
+ assert!(vec
+ .iter()
+ .enumerate()
+ .all(|(i, x)| { map.get_index_of(x) == Some(i) }));
+ TestResult::passed()
+}
+
+fn test_map_move_index<F>(vec: Vec<u8>, from: u8, to: u8, move_index: F) -> TestResult
+where
+ F: FnOnce(&mut IndexMap<u8, ()>, usize, usize),
+{
+ let mut map = IndexMap::<u8, ()>::from_iter(vec.into_iter().map(|k| (k, ())));
+ let from = usize::from(from);
+ let to = usize::from(to);
+
+ if from >= map.len() || to >= map.len() {
+ return TestResult::discard();
+ }
+
+ let mut vec = Vec::from_iter(map.keys().copied());
+ let x = vec.remove(from);
+ vec.insert(to, x);
+
+ move_index(&mut map, from, to);
+
+ // Check both iteration order and hash lookups
+ assert!(map.keys().eq(vec.iter()));
+ assert!(vec
+ .iter()
+ .enumerate()
+ .all(|(i, x)| { map.get_index_of(x) == Some(i) }));
+ TestResult::passed()
+}
+
+fn test_map_shift_insert<F>(vec: Vec<u8>, i: u8, shift_insert: F) -> TestResult
+where
+ F: FnOnce(&mut IndexMap<u8, ()>, usize, u8),
+{
+ let mut map = IndexMap::<u8, ()>::from_iter(vec.into_iter().map(|k| (k, ())));
+ let i = usize::from(i);
+ if i >= map.len() {
+ return TestResult::discard();
+ }
+
+ let mut vec = Vec::from_iter(map.keys().copied());
+ let x = vec.pop().unwrap();
+ vec.insert(i, x);
+
+ let (last, ()) = map.pop().unwrap();
+ assert_eq!(x, last);
+ map.shrink_to_fit(); // so we might have to grow and rehash the table
+
+ shift_insert(&mut map, i, last);
+
+ // Check both iteration order and hash lookups
+ assert!(map.keys().eq(vec.iter()));
+ assert!(vec
+ .iter()
+ .enumerate()
+ .all(|(i, x)| { map.get_index_of(x) == Some(i) }));
+ TestResult::passed()
}
use crate::Op::*;
@@ -310,10 +490,10 @@ where
b.remove(k);
}
RemoveEntry(ref k) => {
- if let OEntry::Occupied(ent) = a.entry(k.clone()) {
+ if let Entry::Occupied(ent) = a.entry(k.clone()) {
ent.swap_remove_entry();
}
- if let HEntry::Occupied(ent) = b.entry(k.clone()) {
+ if let StdEntry::Occupied(ent) = b.entry(k.clone()) {
ent.remove_entry();
}
}
@@ -452,6 +632,12 @@ quickcheck_limit! {
assert_sorted_by_key(map, |t| t.1);
}
+ fn sort_3(keyvals: Large<Vec<(i8, i8)>>) -> () {
+ let mut map: IndexMap<_, _> = IndexMap::from_iter(keyvals.to_vec());
+ map.sort_by_cached_key(|&k, _| std::cmp::Reverse(k));
+ assert_sorted_by_key(map, |t| std::cmp::Reverse(t.0));
+ }
+
fn reverse(keyvals: Large<Vec<(i8, i8)>>) -> () {
let mut map: IndexMap<_, _> = IndexMap::from_iter(keyvals.to_vec());
diff --git a/third_party/rust/interrupt-support/.cargo-checksum.json b/third_party/rust/interrupt-support/.cargo-checksum.json
index 052b3da11a..89a260dc6e 100644
--- a/third_party/rust/interrupt-support/.cargo-checksum.json
+++ b/third_party/rust/interrupt-support/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c2ca168a6ba35961681f351e010d21696d8779ddac06436338431bd39ed16ebb","README.md":"7f1418b4a7c138ba20bcaea077fe6cf0d6ffbaf6df6b90c80efc52aa0d0e2e9f","src/error.rs":"b83cbe8abd22a9d687508d236a2a77e28b3fc6c39673633e5820cc0e3fc86cba","src/interruptee.rs":"c56f9ac610d0b24a128a907266432287558c4b73f6c24b82674ca7894181d18f","src/lib.rs":"cf44a84310913be5264e1c4a3e004a9f7a6cd82d01a109bb6ac4d6002b5dd560","src/shutdown.rs":"b9dfdb717932301035001a0398967384f1b993e14505860415d023febbe82d63","src/sql.rs":"7e050313884a281e6b3fc7a4514374e08cb9e5f3c5aefb873be92e56f30af660"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"f31bc542c5a3e5dfe82a7c62fa4a0a3e5b56424b77eb7ad913aa322e5e070c60","README.md":"7f1418b4a7c138ba20bcaea077fe6cf0d6ffbaf6df6b90c80efc52aa0d0e2e9f","build.rs":"49840f26c73c5db19cb4e7f02930e49d7a19648168b83f2313ac1a0303c103df","src/error.rs":"b83cbe8abd22a9d687508d236a2a77e28b3fc6c39673633e5820cc0e3fc86cba","src/interrupt_support.udl":"5472e585280576de4fab587278e6e24cc26a7c74e0489aeef3c41671c768f662","src/interruptee.rs":"c56f9ac610d0b24a128a907266432287558c4b73f6c24b82674ca7894181d18f","src/lib.rs":"cf44a84310913be5264e1c4a3e004a9f7a6cd82d01a109bb6ac4d6002b5dd560","src/shutdown.rs":"881a358b053fdd01b56b59864547b6456625dea4ee311b2e0ed3762009516ce6","src/sql.rs":"ba04479f740a25310fd171a473b9870580ad9f02bb2f1109c0171694cad4c2cd"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/interrupt-support/Cargo.toml b/third_party/rust/interrupt-support/Cargo.toml
index ced41d7c4e..78dfc448f9 100644
--- a/third_party/rust/interrupt-support/Cargo.toml
+++ b/third_party/rust/interrupt-support/Cargo.toml
@@ -20,6 +20,7 @@ license = "MPL-2.0"
[dependencies]
lazy_static = "1.4"
parking_lot = ">=0.11,<=0.12"
+uniffi = "0.27.1"
[dependencies.rusqlite]
version = "0.30.0"
@@ -29,3 +30,7 @@ features = [
"bundled",
"unlock_notify",
]
+
+[build-dependencies.uniffi]
+version = "0.27.1"
+features = ["build"]
diff --git a/third_party/rust/interrupt-support/build.rs b/third_party/rust/interrupt-support/build.rs
new file mode 100644
index 0000000000..20533b7a2f
--- /dev/null
+++ b/third_party/rust/interrupt-support/build.rs
@@ -0,0 +1,8 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+fn main() {
+ uniffi::generate_scaffolding("./src/interrupt_support.udl").unwrap();
+}
diff --git a/third_party/rust/interrupt-support/src/interrupt_support.udl b/third_party/rust/interrupt-support/src/interrupt_support.udl
new file mode 100644
index 0000000000..06264fec0e
--- /dev/null
+++ b/third_party/rust/interrupt-support/src/interrupt_support.udl
@@ -0,0 +1,5 @@
+namespace interrupt_support {
+ // Enter shutdown mode, causing all current and future interruptable operations to be interrupted.
+ void shutdown();
+};
+
diff --git a/third_party/rust/interrupt-support/src/shutdown.rs b/third_party/rust/interrupt-support/src/shutdown.rs
index 9c64df27e8..88a56029b8 100644
--- a/third_party/rust/interrupt-support/src/shutdown.rs
+++ b/third_party/rust/interrupt-support/src/shutdown.rs
@@ -12,13 +12,14 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
///
/// Here's how add shutdown support to a component:
///
-/// - Use `SqlInterruptScope::new_with_shutdown_check()` to create a new
-/// `SqlInterruptScope`
/// - Database connections need to be wrapped in a type that:
/// - Implements `AsRef<SqlInterruptHandle>`.
/// - Gets wrapped in an `Arc<>`. This is needed so the shutdown code can get a weak reference to
/// the instance.
/// - Calls `register_interrupt()` on creation
+/// - Use `SqlInterruptScope::begin_interrupt_scope()` before each operation.
+/// This will return an error if shutdown mode is in effect.
+/// The interrupt scope should be periodically checked to handle the operation being interrupted/shutdown after it started.
///
/// See `PlacesDb::begin_interrupt_scope()` and `PlacesApi::new_connection()` for an example of
/// how this works.
diff --git a/third_party/rust/interrupt-support/src/sql.rs b/third_party/rust/interrupt-support/src/sql.rs
index 6f361013fc..a9f10f8cf8 100644
--- a/third_party/rust/interrupt-support/src/sql.rs
+++ b/third_party/rust/interrupt-support/src/sql.rs
@@ -120,3 +120,10 @@ impl Interruptee for SqlInterruptScope {
self.was_interrupted()
}
}
+
+// Needed to allow Weak<SqlInterruptHandle> to be passed to `interrupt::register_interrupt`
+impl AsRef<SqlInterruptHandle> for SqlInterruptHandle {
+ fn as_ref(&self) -> &SqlInterruptHandle {
+ self
+ }
+}
diff --git a/third_party/rust/libc/.cargo-checksum.json b/third_party/rust/libc/.cargo-checksum.json
index 2ff314778c..f2b650512a 100644
--- a/third_party/rust/libc/.cargo-checksum.json
+++ b/third_party/rust/libc/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"a93fcda0a76e1975fcfb0aa2ba00c9b1864f9ae6062704a294d81a3688898e10","Cargo.toml":"0d743c123c9c30b09413dce51344d4dfaf958e8eef3e1f4e7682931a8d781ec3","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"4da2919bb509f3f06163778478494f780ca6627cb79ccab5d2c828c8d88dc133","build.rs":"01bc1b8934bb80982a36f46c61508f32cb05c4deab15cb9afb5bf9da285d5c1b","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"893fcec48142d273063ffd814dca33fbec92205fd39ada97075f85201d803996","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"07410f511835da540e5bdc55f7384c71cd7836fe63bbca6be547de825f823c03","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/riscv64.rs":"617cd75e79e0e20f664db764a4dc2a396d9fd11a4d95371acd91ed4811293b11","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"2d04cfa0d55dc0a2e36fdc4a45819b9d3722af19bb1932778b44feb4c2f81036","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"9d7030ba3e21064a0f3a8e79927c70d5a95a0026be61be084f3ab021e243e503","src/macros.rs":"5f985b3de7b18833f866bf832b8ffb0430f0f70aa9a468b6a2c855c1bf9d33e4","src/psp.rs":"0a7d5121a8cc2903009f586c00e4ae2d6126d24eb90531dafaba6f59823aa6b2","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/teeos/mod.rs":"eb664b3e94bcd44d8c8147b56c2187139d01bf8402ee0bb81967a5a50a3e927f","src/unix/aix/mod.rs":"d4ed2a4eff43c60a251bba150868d0249bf79dd6fb835d5287c352577452712b","src/unix/aix/powerpc64.rs":"cf374d81139d45f9d77c6a764f640bfbf7e0a5903689652c8296f8e10d55169b","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/long_array.rs":"3cf1f19b812e6d093c819dc65ce55b13491963e0780eda0d0bd1577603e81948","src/unix/bsd/apple/mod.rs":"1da404688e9d67171403f2486456aac9d36a2db31ee7ebc308f14d6277754eef","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"2777f94909a798df1b8030fb86d02e2118d0ac3e49e9a542df54a569ca5ae2f9","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"6c8e216385f53a4bf5f171749b57602fc34a4e4b160a44ca31c058cb0c8a2126","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"e243ae0e89623d4fa9f85afe14369cc5fd5f2028ea715773dbec722ba80dac1f","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"bef9fae288a4f29e941ea369be1cd20b170040e60665a4d49a4a9e79009b72d8","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"88be47524b28b6635ccb1e85ea511bf17337be0af7e9baa740c341ac9e83a6f7","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"6ddc6abf6d5ccaea0d8cccf521e8ca6457efcad3086af4155628d5d06d672346","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs":"93115c1a9faa43ebf58b7dee3582aed5a54291b284764e370e7f649b2e6a9565","src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/mod.rs":"5669c341804bccf27eb03965f11bd640a762a9898a5baa18b5a319fb1d8abddf","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"fa4bed4c58cad24ba3395941c7fa6b11e089551a04714f9561078e400f5b2b62","src/unix/bsd/freebsdlike/freebsd/x86.rs":"6766e2ce85e187b306cd3b0b8d7e15b8f4042c5cff81d89b3af69ecc99c70ab0","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"29f5ae7c8bcd64219e77f99ba9b26527299cf4908b20f7d1ec4f625b5194a44c","src/unix/bsd/mod.rs":"f5974098ef3d1a29774bc0bde27dc9c89c3880f9ed7b4d7ea334b595dc39ff94","src/unix/bsd/netbsdlike/mod.rs":"ea60540aa4edd4e43136749d5df497b1dc072b9912b6030dd1ab794a6d1c3c3c","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"057ee877db7193ba0dc10801b9a6563ac6dbdb78376d6851a84cb12b30841759","src/unix/bsd/netbsdlike/netbsd/arm.rs":"949b55e4dee1c8c511f4f061a6a57ac876a6c0eabfaf5cc20e9ab40d8f41b2e0","src/unix/bsd/netbsdlike/netbsd/mips.rs":"88be18ac43ba224c77e78e4179b6761debc5e6c30a258fac56263809c7af4fbc","src/unix/bsd/netbsdlike/netbsd/mod.rs":"b8d6f089fc8eb2cb59e45335a26c9ce871b846216c9859b553c6b91982f8de33","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/riscv64.rs":"1cbe2e5ed681cb1054b699da37daaf6c714267df7d332c90fc2a589b11579625","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"532b76199d6c71ff996eade9f906c55a72c9aff489595d25a21e21878cfd740b","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"7b93b5b24b3c72a79b2de19b47ac2f56b29d87e9fc8f4c721a63d1e87ec83fcc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1fe3332dc705a13e6242219970f5449d6d7a73e2e6c8537ab8e421d8a6f2e3ff","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"ad70cc42ed83ac38664941418b0b9bfe1ead7a0ff82b121ea8df65483e3b7e1c","src/unix/haiku/native.rs":"3bbf42c3e3e437e8b626be67c72b6adcec60646eb5dd4bf8471a603cbbb5e5a4","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hurd/align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/hurd/b32.rs":"2ba90ed973f90366c36a6387833a3df42abfee9622d4a0352635937d4a89eaf4","src/unix/hurd/b64.rs":"d919b4aec9b3080ad24c125c57b2c8b2e483d72045f1554c429d14560355846f","src/unix/hurd/mod.rs":"6a2f0db80a3cd34b55ef82e357da4d453d5d190a2dd4501bfa5d0bb9bca0de4f","src/unix/hurd/no_align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/linux_like/android/b32/arm.rs":"ce582de7e983a33d3bfad13075c53aac9016cee35f06ad8653ee9072c3ec2564","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"e6d107efbcd37b5b85dfa18f683300cbf768ffa0237997a9fa52b184a53323ac","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"10e963e29ff209703de6336c99cca96fd79789438d34c82a693eae56e8916c3c","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"19d4bf2237c47127eba9144e0b82e995bc079315e719179a91813b0ae7b0e49d","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"4ec2de11a9b65c4325b7b991f0b99a414975e0e61ba8668caca5d921e9b314d1","src/unix/linux_like/android/mod.rs":"e7e87cb2aa2665a7113e3cbcad58c6b4c8a04c9989a6773895b5ecc806348258","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/lfs64.rs":"3776af30a758d765a88920ec4fde442ab89040da13d3b3625c7fbcb8a958559f","src/unix/linux_like/emscripten/mod.rs":"70d4591730a731ee32788a9d8d2de379592844ec36b7d1723514179605587713","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"bc5abcd38e2320171e0981e773c9c5fe3e0d5a66fdff049228f6a1acad80ef8b","src/unix/linux_like/linux/arch/generic/mod.rs":"ebb6a0a96bcbfbe3432bf67d88ea5d006ccb47f345dab33562bb052d110a6946","src/unix/linux_like/linux/arch/mips/mod.rs":"18dade308bf04717630fd6467b92c23560c83ac5274a8469569f260aa4671239","src/unix/linux_like/linux/arch/mod.rs":"5bd5361f8a6ab4e18bbba6da9f92c164ae252b15a0ed10064812544aa1fdf198","src/unix/linux_like/linux/arch/powerpc/mod.rs":"0bc2d2667a00eca81f4abeb6d613a90848a947f51224103f83268928b8197629","src/unix/linux_like/linux/arch/sparc/mod.rs":"5e6777863e74a9e2aa9dc487f1059783dd211babc2b32d6bf676f311e49c55d6","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"f68ec59b6407f9d4e326f3e71a41ec21f19ecfc703edf9a93e496f661fed5506","src/unix/linux_like/linux/gnu/b32/csky/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/csky/mod.rs":"8729b68e433e94c2128e51a7db4fd555938e4be4dc64584c352b24a20d9c8e91","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"80956d3fef163ecf248828a6f38782dd8ae856d86b1bb5aac2de36032dbd8ea0","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"96e22350d5d132d917c743d6560464500652c67b52c3d0e8474494487df3365d","src/unix/linux_like/linux/gnu/b32/mod.rs":"b56625dd20dd48a8699034d349ef089c540c0ddcbf8a3481d598d101f8b40b78","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"20fc3cc4fe1ef6617b63b61b897f782ceb9c2842fc718f504a1840537229bf47","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"887288a0a1cfff319d0e15edcdc4fcb31fd643ff41715ec5244c8f2413624169","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"cc4342b949e4d796f304acd9dfe3f721a1c2f37fec16b42d3bb27dc94723af37","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"06d4db4ee8352f62a0a5ead0c4d6ea0a78feff522f19b9bc5772f6dd920ffd80","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"fdf1c72375a2167699157e0dd825422690bb6719f7bc69515a2e5846d0431d7c","src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs":"832e7487249c1c0bb6e9911ce3f7d32ca22378e42392ab83c56915cbc59d8be3","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"bf4611b737813deef6787babf6c01698605f3b75482269b8546318667bc68e29","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"11a950697fdda0258c6e37c6b13993348c8de4134105ed4faa79358e53175072","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"8202614484da36c388d2ffdd2554c56bb4f9db8e5bd621f8c36114cdcfeec644","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"dc29dfdadd754ec355b82a7ca6636de7ed97f7ba98f132b71cb49f39d6bd8e3f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"73532be4b5775acf9524c77feeefe1f6d1936ceffef908d01dd2586986520f2d","src/unix/linux_like/linux/gnu/b64/mod.rs":"6a160ef25439c4fecdb0e3bd0b818742263c791364da874d4febd3aa644ec8e2","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a90c2641616c620e9d1fea87695ce046e14f9da2282bb93f761eeb4077c74741","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"68a2a20fa4ef92cdf382d8095168eb88875b7aa8c9c47ee5f1e527393b6c16fa","src/unix/linux_like/linux/gnu/b64/s390x.rs":"1ea9e39432ce6bf68779d33546dacd7d39477a9f8fc3da4f4f339e4538cb74c3","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"bed381c44cec2a5b50125f7e548ab487d4c829006c971d152a611b7141760052","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"332846e4a5920d7e6b05df0448a2333c5dd00fb27cb33654648f507ee89dbec5","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"38f74ce15d9662ce4818815a2b87be1618d5e45f190f7e4db84ff3285b4421fb","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"b20218a11364a6dec87f96d6c0d8b19e660697ab09ad5ee0e9b3a9dafedaaebb","src/unix/linux_like/linux/gnu/mod.rs":"583d04f92435da76fd3f87182ab67b5e6dd8c35a63b240d8c4555fb1ab70f3f8","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"e5000a0746c354b26e3c469ed7802a86a7bcca67446047c4e2d5526ea80c4d32","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"af10147d7c3661751750a58ffad089d5d18d180cd18303c653aef126c07ccd91","src/unix/linux_like/linux/musl/b32/hexagon.rs":"d079cab42529f7dab699334d43168c74ff4aa0282f11040a8b7d274b65767a7a","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"e44043766f7cd26de7ffa4232654afb6feb03e58dbd5890717970887bd003151","src/unix/linux_like/linux/musl/b32/mod.rs":"31677597fd9544c4b1ec1477628288f6273fabbc06e38f33da862ad55f019ce1","src/unix/linux_like/linux/musl/b32/powerpc.rs":"3dae56a4e7789bcc5314e419fea5e4b2495367b4f1a49d1c9477c60225d65eef","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"3ee845d272f91a1908d5f421d7c353e1f14681bbdfef64410e408f4c14365a91","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"f2b53ae0034c833244b7cdb8c670349bf8272a03abf04152eba65cf62810484d","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"45ce6897afcc960267bb7505702b639daf94dc69428a213bf1aefd367ca32adc","src/unix/linux_like/linux/musl/b64/mips64.rs":"a968ef9c54fa22293085f318c8472c1754482df92cc500568dc33bd807d71ea6","src/unix/linux_like/linux/musl/b64/mod.rs":"1a8391febf3e750185ffc5c69c9f9e411f4e8c53b5d994cb231df24480169686","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"140e579800a67315f4cb8a42b22aa8157eae34ffe626e77e421b43c53c23b34d","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"c5944526d7e19cd43e9d14d119a1d98f8780db7ecbcc79e69d7b9348e596b520","src/unix/linux_like/linux/musl/b64/s390x.rs":"8557b3477ca8cefef7fce764a3c25441929a54e50ead4091f6f7823c427cd728","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"a91c4f18027c9958037f78ae48f6352d23cb4e6f2995b2cc8de7dce0e5759470","src/unix/linux_like/linux/musl/lfs64.rs":"3e4fb381f3a0756520bde0f1692d4fa45e4ae8133bf7d7c64b0e3fdd512f235f","src/unix/linux_like/linux/musl/mod.rs":"f0a23b77e5465c05a5dd95c3c6b7959c597010416226503ff3719796367ba98e","src/unix/linux_like/linux/no_align.rs":"62cdca0e011937aaf09a51ca86d9f0ee0fdb05f61ec3c058e6a5d5fa6357d784","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"50288ff9e411ab0966da24838f2c2a5618021bc19c422a04f577b2979ef4081e","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"d0c4434e2bf813372c418a8f516c706cdccc9f7be2f0921b2207b0afdb66fe81","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"3f38ee6a4690b9d7594be20d216467a34d955f7653c2c8ce1e6147daeb53f1e0","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"a048fce1c2d9b1ad57305642e8ad05ca0f0c7e4753267a2e2d6b4fee5db3b072","src/unix/linux_like/linux/uclibc/mod.rs":"193a03fa4aa5345394e39d2115c9427e806c9f28b0fde685719119e1c90ca08a","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"8485b9182b7c67f7344fab377e7cc2a72afefd9ab63837c860514abba9728d76","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"196d03affbefb85716937c15904831e731eb222ee906e05e42102d639a8152ea","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"86dbbd81484df25ad7c6a82d2d3b5eab2f8e7751853c1dd4308b7eee57b5fbca","src/unix/mod.rs":"923a32e8fd9e462eda4e90ae7ee501da1d12aaadc1bf2e9722f02581a5d3fc6c","src/unix/newlib/aarch64/mod.rs":"964c096288da836b53c0c71d7f3a97048d177da220a69314c5ce93ba330d72af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cf754f8b1197489fca01e881a4b4b146e814998e4b365f116fa1a102c00e6a4e","src/unix/newlib/espidf/mod.rs":"29969da41f0042197b21cfa7c0ad2244b4519ecab0fb7de3d0a7655b4f3937e1","src/unix/newlib/generic.rs":"5f0b5d07ddb5a5d60580f9561fdb05e9218d9751d4068c4aadad2ba6b950aabf","src/unix/newlib/horizon/mod.rs":"3a521d22bf932fc01c1d26d1f9bff20f11b1855b03c8236a8eb18310f6cab5a8","src/unix/newlib/mod.rs":"e5d5faf27a6336b9f1c02b8726427801d906a14dae766852b4e85c1a92df06c8","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"cc9e188711b9bf614323ad6c48e0d2e1a1ecc5d3bc64961ba451f29c6c22d2d8","src/unix/newlib/vita/mod.rs":"d849a01841744ea5e04635c8f69c9e2b44791320eb9d629b9d0fee0a4c5d502a","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/nto/aarch64.rs":"4709c9afdc8d583be876598e7c238499ee3e8da5bd2baa614d9c7dd414851555","src/unix/nto/mod.rs":"07268897fc8810f2fed22ab56f87757f71c73ba401abd848bccca6b183a13b02","src/unix/nto/neutrino.rs":"799bff4ab01a6424db6c5a2b76aa5679826d41495f9d13c63485bf13bc80026b","src/unix/nto/x86_64.rs":"a3e18e93c2999da1cd7a6f748a4b60c07aefb73d8ea2aafec19a84cfb040bc8e","src/unix/redox/mod.rs":"a9f54687307883beb4a410216dc8e36b85d72b0463bc6b1520bd91edf3947d23","src/unix/solarish/compat.rs":"00f1ee3faec9da69204e42f025f6735dd13d894071a154425dcc43ecbdd06e7f","src/unix/solarish/illumos.rs":"cd93c2d84722bbf9933a92842a8998eb0b2afc962f50bc2546ad127b82809fa7","src/unix/solarish/mod.rs":"10b2369edc027fcb2e41e5342f24946aa01ee1549a6d7f06b9a3956ff84518bc","src/unix/solarish/solaris.rs":"41b350a89ddf01cd12a10f93640f92be53be0b0d976021cdc08da17bf3e72edf","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"4105a2e6a6c9908fc1f2a770ede052bb0d6a5d9d49e32d815f557081efc49860","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"d4147353537d7556076ff1a1c4cb96cc2dae9416a5d176ba8a077ad55ab7ec18","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"9fdc5e1c62c441abef7bc62a7343efb2041edc24db9ac0efc0f74df55b69e249","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","src/xous.rs":"eb0675f25ba01f73072d2b70907fb8abb1148facefe5a20756c49250f3d65fae","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"} \ No newline at end of file
+{"files":{"CONTRIBUTING.md":"a93fcda0a76e1975fcfb0aa2ba00c9b1864f9ae6062704a294d81a3688898e10","Cargo.toml":"c7d137b327d60cad5b7bd3ef97ec93f57fdde1101b14250b56fe1a1d3afc98ef","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"4da2919bb509f3f06163778478494f780ca6627cb79ccab5d2c828c8d88dc133","build.rs":"01bc1b8934bb80982a36f46c61508f32cb05c4deab15cb9afb5bf9da285d5c1b","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"893fcec48142d273063ffd814dca33fbec92205fd39ada97075f85201d803996","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"07410f511835da540e5bdc55f7384c71cd7836fe63bbca6be547de825f823c03","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/riscv64.rs":"617cd75e79e0e20f664db764a4dc2a396d9fd11a4d95371acd91ed4811293b11","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"2d04cfa0d55dc0a2e36fdc4a45819b9d3722af19bb1932778b44feb4c2f81036","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"9d7030ba3e21064a0f3a8e79927c70d5a95a0026be61be084f3ab021e243e503","src/macros.rs":"5f985b3de7b18833f866bf832b8ffb0430f0f70aa9a468b6a2c855c1bf9d33e4","src/psp.rs":"0a7d5121a8cc2903009f586c00e4ae2d6126d24eb90531dafaba6f59823aa6b2","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/teeos/mod.rs":"eb664b3e94bcd44d8c8147b56c2187139d01bf8402ee0bb81967a5a50a3e927f","src/unix/aix/mod.rs":"d4ed2a4eff43c60a251bba150868d0249bf79dd6fb835d5287c352577452712b","src/unix/aix/powerpc64.rs":"cf374d81139d45f9d77c6a764f640bfbf7e0a5903689652c8296f8e10d55169b","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/long_array.rs":"3cf1f19b812e6d093c819dc65ce55b13491963e0780eda0d0bd1577603e81948","src/unix/bsd/apple/mod.rs":"1da404688e9d67171403f2486456aac9d36a2db31ee7ebc308f14d6277754eef","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"2777f94909a798df1b8030fb86d02e2118d0ac3e49e9a542df54a569ca5ae2f9","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"6c8e216385f53a4bf5f171749b57602fc34a4e4b160a44ca31c058cb0c8a2126","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"e243ae0e89623d4fa9f85afe14369cc5fd5f2028ea715773dbec722ba80dac1f","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"bef9fae288a4f29e941ea369be1cd20b170040e60665a4d49a4a9e79009b72d8","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"88be47524b28b6635ccb1e85ea511bf17337be0af7e9baa740c341ac9e83a6f7","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"6ddc6abf6d5ccaea0d8cccf521e8ca6457efcad3086af4155628d5d06d672346","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs":"93115c1a9faa43ebf58b7dee3582aed5a54291b284764e370e7f649b2e6a9565","src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/mod.rs":"5669c341804bccf27eb03965f11bd640a762a9898a5baa18b5a319fb1d8abddf","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"fa4bed4c58cad24ba3395941c7fa6b11e089551a04714f9561078e400f5b2b62","src/unix/bsd/freebsdlike/freebsd/x86.rs":"6766e2ce85e187b306cd3b0b8d7e15b8f4042c5cff81d89b3af69ecc99c70ab0","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"29f5ae7c8bcd64219e77f99ba9b26527299cf4908b20f7d1ec4f625b5194a44c","src/unix/bsd/mod.rs":"f5974098ef3d1a29774bc0bde27dc9c89c3880f9ed7b4d7ea334b595dc39ff94","src/unix/bsd/netbsdlike/mod.rs":"ea60540aa4edd4e43136749d5df497b1dc072b9912b6030dd1ab794a6d1c3c3c","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"057ee877db7193ba0dc10801b9a6563ac6dbdb78376d6851a84cb12b30841759","src/unix/bsd/netbsdlike/netbsd/arm.rs":"949b55e4dee1c8c511f4f061a6a57ac876a6c0eabfaf5cc20e9ab40d8f41b2e0","src/unix/bsd/netbsdlike/netbsd/mips.rs":"88be18ac43ba224c77e78e4179b6761debc5e6c30a258fac56263809c7af4fbc","src/unix/bsd/netbsdlike/netbsd/mod.rs":"b8d6f089fc8eb2cb59e45335a26c9ce871b846216c9859b553c6b91982f8de33","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/riscv64.rs":"1cbe2e5ed681cb1054b699da37daaf6c714267df7d332c90fc2a589b11579625","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"532b76199d6c71ff996eade9f906c55a72c9aff489595d25a21e21878cfd740b","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"7b93b5b24b3c72a79b2de19b47ac2f56b29d87e9fc8f4c721a63d1e87ec83fcc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1fe3332dc705a13e6242219970f5449d6d7a73e2e6c8537ab8e421d8a6f2e3ff","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"ad70cc42ed83ac38664941418b0b9bfe1ead7a0ff82b121ea8df65483e3b7e1c","src/unix/haiku/native.rs":"3bbf42c3e3e437e8b626be67c72b6adcec60646eb5dd4bf8471a603cbbb5e5a4","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hurd/align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/hurd/b32.rs":"2ba90ed973f90366c36a6387833a3df42abfee9622d4a0352635937d4a89eaf4","src/unix/hurd/b64.rs":"d919b4aec9b3080ad24c125c57b2c8b2e483d72045f1554c429d14560355846f","src/unix/hurd/mod.rs":"6a2f0db80a3cd34b55ef82e357da4d453d5d190a2dd4501bfa5d0bb9bca0de4f","src/unix/hurd/no_align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/linux_like/android/b32/arm.rs":"ce582de7e983a33d3bfad13075c53aac9016cee35f06ad8653ee9072c3ec2564","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"e6d107efbcd37b5b85dfa18f683300cbf768ffa0237997a9fa52b184a53323ac","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"10e963e29ff209703de6336c99cca96fd79789438d34c82a693eae56e8916c3c","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"19d4bf2237c47127eba9144e0b82e995bc079315e719179a91813b0ae7b0e49d","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"4ec2de11a9b65c4325b7b991f0b99a414975e0e61ba8668caca5d921e9b314d1","src/unix/linux_like/android/mod.rs":"5f923c89c8fd6a672d695ddd690aeac6a025c947f565acbd829c0e69d72ca049","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/lfs64.rs":"3776af30a758d765a88920ec4fde442ab89040da13d3b3625c7fbcb8a958559f","src/unix/linux_like/emscripten/mod.rs":"70d4591730a731ee32788a9d8d2de379592844ec36b7d1723514179605587713","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"bc5abcd38e2320171e0981e773c9c5fe3e0d5a66fdff049228f6a1acad80ef8b","src/unix/linux_like/linux/arch/generic/mod.rs":"feff53cb116f60c302121f9a5701adf1e2a16ff7d52a6de161fe58a28553f870","src/unix/linux_like/linux/arch/mips/mod.rs":"18dade308bf04717630fd6467b92c23560c83ac5274a8469569f260aa4671239","src/unix/linux_like/linux/arch/mod.rs":"5bd5361f8a6ab4e18bbba6da9f92c164ae252b15a0ed10064812544aa1fdf198","src/unix/linux_like/linux/arch/powerpc/mod.rs":"0bc2d2667a00eca81f4abeb6d613a90848a947f51224103f83268928b8197629","src/unix/linux_like/linux/arch/sparc/mod.rs":"5e6777863e74a9e2aa9dc487f1059783dd211babc2b32d6bf676f311e49c55d6","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"f68ec59b6407f9d4e326f3e71a41ec21f19ecfc703edf9a93e496f661fed5506","src/unix/linux_like/linux/gnu/b32/csky/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/csky/mod.rs":"8729b68e433e94c2128e51a7db4fd555938e4be4dc64584c352b24a20d9c8e91","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"80956d3fef163ecf248828a6f38782dd8ae856d86b1bb5aac2de36032dbd8ea0","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"96e22350d5d132d917c743d6560464500652c67b52c3d0e8474494487df3365d","src/unix/linux_like/linux/gnu/b32/mod.rs":"b56625dd20dd48a8699034d349ef089c540c0ddcbf8a3481d598d101f8b40b78","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"20fc3cc4fe1ef6617b63b61b897f782ceb9c2842fc718f504a1840537229bf47","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"887288a0a1cfff319d0e15edcdc4fcb31fd643ff41715ec5244c8f2413624169","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"cc4342b949e4d796f304acd9dfe3f721a1c2f37fec16b42d3bb27dc94723af37","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"06d4db4ee8352f62a0a5ead0c4d6ea0a78feff522f19b9bc5772f6dd920ffd80","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"fdf1c72375a2167699157e0dd825422690bb6719f7bc69515a2e5846d0431d7c","src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs":"832e7487249c1c0bb6e9911ce3f7d32ca22378e42392ab83c56915cbc59d8be3","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"bf4611b737813deef6787babf6c01698605f3b75482269b8546318667bc68e29","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"11a950697fdda0258c6e37c6b13993348c8de4134105ed4faa79358e53175072","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"8202614484da36c388d2ffdd2554c56bb4f9db8e5bd621f8c36114cdcfeec644","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"dc29dfdadd754ec355b82a7ca6636de7ed97f7ba98f132b71cb49f39d6bd8e3f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"73532be4b5775acf9524c77feeefe1f6d1936ceffef908d01dd2586986520f2d","src/unix/linux_like/linux/gnu/b64/mod.rs":"6a160ef25439c4fecdb0e3bd0b818742263c791364da874d4febd3aa644ec8e2","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a90c2641616c620e9d1fea87695ce046e14f9da2282bb93f761eeb4077c74741","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"68a2a20fa4ef92cdf382d8095168eb88875b7aa8c9c47ee5f1e527393b6c16fa","src/unix/linux_like/linux/gnu/b64/s390x.rs":"1ea9e39432ce6bf68779d33546dacd7d39477a9f8fc3da4f4f339e4538cb74c3","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"bed381c44cec2a5b50125f7e548ab487d4c829006c971d152a611b7141760052","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"332846e4a5920d7e6b05df0448a2333c5dd00fb27cb33654648f507ee89dbec5","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"38f74ce15d9662ce4818815a2b87be1618d5e45f190f7e4db84ff3285b4421fb","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"b20218a11364a6dec87f96d6c0d8b19e660697ab09ad5ee0e9b3a9dafedaaebb","src/unix/linux_like/linux/gnu/mod.rs":"583d04f92435da76fd3f87182ab67b5e6dd8c35a63b240d8c4555fb1ab70f3f8","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"099ae3b59e379cad0e57df710a81a3f8f208a5993051e6e0fcfb61595889ce18","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"af10147d7c3661751750a58ffad089d5d18d180cd18303c653aef126c07ccd91","src/unix/linux_like/linux/musl/b32/hexagon.rs":"d079cab42529f7dab699334d43168c74ff4aa0282f11040a8b7d274b65767a7a","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"e44043766f7cd26de7ffa4232654afb6feb03e58dbd5890717970887bd003151","src/unix/linux_like/linux/musl/b32/mod.rs":"31677597fd9544c4b1ec1477628288f6273fabbc06e38f33da862ad55f019ce1","src/unix/linux_like/linux/musl/b32/powerpc.rs":"3dae56a4e7789bcc5314e419fea5e4b2495367b4f1a49d1c9477c60225d65eef","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"3ee845d272f91a1908d5f421d7c353e1f14681bbdfef64410e408f4c14365a91","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"f2b53ae0034c833244b7cdb8c670349bf8272a03abf04152eba65cf62810484d","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"45ce6897afcc960267bb7505702b639daf94dc69428a213bf1aefd367ca32adc","src/unix/linux_like/linux/musl/b64/mips64.rs":"a968ef9c54fa22293085f318c8472c1754482df92cc500568dc33bd807d71ea6","src/unix/linux_like/linux/musl/b64/mod.rs":"1a8391febf3e750185ffc5c69c9f9e411f4e8c53b5d994cb231df24480169686","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"140e579800a67315f4cb8a42b22aa8157eae34ffe626e77e421b43c53c23b34d","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"c5944526d7e19cd43e9d14d119a1d98f8780db7ecbcc79e69d7b9348e596b520","src/unix/linux_like/linux/musl/b64/s390x.rs":"8557b3477ca8cefef7fce764a3c25441929a54e50ead4091f6f7823c427cd728","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"a91c4f18027c9958037f78ae48f6352d23cb4e6f2995b2cc8de7dce0e5759470","src/unix/linux_like/linux/musl/lfs64.rs":"3e4fb381f3a0756520bde0f1692d4fa45e4ae8133bf7d7c64b0e3fdd512f235f","src/unix/linux_like/linux/musl/mod.rs":"f0a23b77e5465c05a5dd95c3c6b7959c597010416226503ff3719796367ba98e","src/unix/linux_like/linux/no_align.rs":"62cdca0e011937aaf09a51ca86d9f0ee0fdb05f61ec3c058e6a5d5fa6357d784","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"50288ff9e411ab0966da24838f2c2a5618021bc19c422a04f577b2979ef4081e","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"d0c4434e2bf813372c418a8f516c706cdccc9f7be2f0921b2207b0afdb66fe81","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"3f38ee6a4690b9d7594be20d216467a34d955f7653c2c8ce1e6147daeb53f1e0","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"a048fce1c2d9b1ad57305642e8ad05ca0f0c7e4753267a2e2d6b4fee5db3b072","src/unix/linux_like/linux/uclibc/mod.rs":"193a03fa4aa5345394e39d2115c9427e806c9f28b0fde685719119e1c90ca08a","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"8485b9182b7c67f7344fab377e7cc2a72afefd9ab63837c860514abba9728d76","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"196d03affbefb85716937c15904831e731eb222ee906e05e42102d639a8152ea","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"86dbbd81484df25ad7c6a82d2d3b5eab2f8e7751853c1dd4308b7eee57b5fbca","src/unix/mod.rs":"923a32e8fd9e462eda4e90ae7ee501da1d12aaadc1bf2e9722f02581a5d3fc6c","src/unix/newlib/aarch64/mod.rs":"964c096288da836b53c0c71d7f3a97048d177da220a69314c5ce93ba330d72af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cf754f8b1197489fca01e881a4b4b146e814998e4b365f116fa1a102c00e6a4e","src/unix/newlib/espidf/mod.rs":"29969da41f0042197b21cfa7c0ad2244b4519ecab0fb7de3d0a7655b4f3937e1","src/unix/newlib/generic.rs":"5f0b5d07ddb5a5d60580f9561fdb05e9218d9751d4068c4aadad2ba6b950aabf","src/unix/newlib/horizon/mod.rs":"3a521d22bf932fc01c1d26d1f9bff20f11b1855b03c8236a8eb18310f6cab5a8","src/unix/newlib/mod.rs":"e5d5faf27a6336b9f1c02b8726427801d906a14dae766852b4e85c1a92df06c8","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"cc9e188711b9bf614323ad6c48e0d2e1a1ecc5d3bc64961ba451f29c6c22d2d8","src/unix/newlib/vita/mod.rs":"ff1caf74bb0696fe15d60dbac598db4520cd538aa0f5989713d97d008eee6ad8","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/nto/aarch64.rs":"4709c9afdc8d583be876598e7c238499ee3e8da5bd2baa614d9c7dd414851555","src/unix/nto/mod.rs":"07268897fc8810f2fed22ab56f87757f71c73ba401abd848bccca6b183a13b02","src/unix/nto/neutrino.rs":"799bff4ab01a6424db6c5a2b76aa5679826d41495f9d13c63485bf13bc80026b","src/unix/nto/x86_64.rs":"a3e18e93c2999da1cd7a6f748a4b60c07aefb73d8ea2aafec19a84cfb040bc8e","src/unix/redox/mod.rs":"a9f54687307883beb4a410216dc8e36b85d72b0463bc6b1520bd91edf3947d23","src/unix/solarish/compat.rs":"00f1ee3faec9da69204e42f025f6735dd13d894071a154425dcc43ecbdd06e7f","src/unix/solarish/illumos.rs":"cd93c2d84722bbf9933a92842a8998eb0b2afc962f50bc2546ad127b82809fa7","src/unix/solarish/mod.rs":"10b2369edc027fcb2e41e5342f24946aa01ee1549a6d7f06b9a3956ff84518bc","src/unix/solarish/solaris.rs":"41b350a89ddf01cd12a10f93640f92be53be0b0d976021cdc08da17bf3e72edf","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"4105a2e6a6c9908fc1f2a770ede052bb0d6a5d9d49e32d815f557081efc49860","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"d4147353537d7556076ff1a1c4cb96cc2dae9416a5d176ba8a077ad55ab7ec18","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"9fdc5e1c62c441abef7bc62a7343efb2041edc24db9ac0efc0f74df55b69e249","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","src/xous.rs":"eb0675f25ba01f73072d2b70907fb8abb1148facefe5a20756c49250f3d65fae","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"} \ No newline at end of file
diff --git a/third_party/rust/libc/Cargo.toml b/third_party/rust/libc/Cargo.toml
index 266fb56093..46ec3b4074 100644
--- a/third_party/rust/libc/Cargo.toml
+++ b/third_party/rust/libc/Cargo.toml
@@ -11,7 +11,7 @@
[package]
name = "libc"
-version = "0.2.152"
+version = "0.2.153"
authors = ["The Rust Project Developers"]
build = "build.rs"
exclude = [
diff --git a/third_party/rust/libc/src/unix/linux_like/android/mod.rs b/third_party/rust/libc/src/unix/linux_like/android/mod.rs
index 94c4eace85..2c1c1e9b91 100644
--- a/third_party/rust/libc/src/unix/linux_like/android/mod.rs
+++ b/third_party/rust/libc/src/unix/linux_like/android/mod.rs
@@ -2275,6 +2275,8 @@ pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
pub const MFD_CLOEXEC: ::c_uint = 0x0001;
pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002;
pub const MFD_HUGETLB: ::c_uint = 0x0004;
+pub const MFD_NOEXEC_SEAL: ::c_uint = 0x0008;
+pub const MFD_EXEC: ::c_uint = 0x0010;
pub const MFD_HUGE_64KB: ::c_uint = 0x40000000;
pub const MFD_HUGE_512KB: ::c_uint = 0x4c000000;
pub const MFD_HUGE_1MB: ::c_uint = 0x50000000;
@@ -3468,6 +3470,37 @@ pub const NET_DCCP: ::c_int = 20;
pub const HUGETLB_FLAG_ENCODE_SHIFT: ::c_int = 26;
pub const MAP_HUGE_SHIFT: ::c_int = HUGETLB_FLAG_ENCODE_SHIFT;
+// include/linux/sched.h
+pub const PF_VCPU: ::c_int = 0x00000001;
+pub const PF_IDLE: ::c_int = 0x00000002;
+pub const PF_EXITING: ::c_int = 0x00000004;
+pub const PF_POSTCOREDUMP: ::c_int = 0x00000008;
+pub const PF_IO_WORKER: ::c_int = 0x00000010;
+pub const PF_WQ_WORKER: ::c_int = 0x00000020;
+pub const PF_FORKNOEXEC: ::c_int = 0x00000040;
+pub const PF_MCE_PROCESS: ::c_int = 0x00000080;
+pub const PF_SUPERPRIV: ::c_int = 0x00000100;
+pub const PF_DUMPCORE: ::c_int = 0x00000200;
+pub const PF_SIGNALED: ::c_int = 0x00000400;
+pub const PF_MEMALLOC: ::c_int = 0x00000800;
+pub const PF_NPROC_EXCEEDED: ::c_int = 0x00001000;
+pub const PF_USED_MATH: ::c_int = 0x00002000;
+pub const PF_USER_WORKER: ::c_int = 0x00004000;
+pub const PF_NOFREEZE: ::c_int = 0x00008000;
+
+pub const PF_KSWAPD: ::c_int = 0x00020000;
+pub const PF_MEMALLOC_NOFS: ::c_int = 0x00040000;
+pub const PF_MEMALLOC_NOIO: ::c_int = 0x00080000;
+pub const PF_LOCAL_THROTTLE: ::c_int = 0x00100000;
+pub const PF_KTHREAD: ::c_int = 0x00200000;
+pub const PF_RANDOMIZE: ::c_int = 0x00400000;
+
+pub const PF_NO_SETAFFINITY: ::c_int = 0x04000000;
+pub const PF_MCE_EARLY: ::c_int = 0x08000000;
+pub const PF_MEMALLOC_PIN: ::c_int = 0x10000000;
+
+pub const PF_SUSPEND_TASK: ::c_int = 0x80000000;
+
// Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the
// following are only available on newer Linux versions than the versions
// currently used in CI in some configurations, so we define them here.
diff --git a/third_party/rust/libc/src/unix/linux_like/linux/arch/generic/mod.rs b/third_party/rust/libc/src/unix/linux_like/linux/arch/generic/mod.rs
index b8e459631e..83f97fbd92 100644
--- a/third_party/rust/libc/src/unix/linux_like/linux/arch/generic/mod.rs
+++ b/third_party/rust/libc/src/unix/linux_like/linux/arch/generic/mod.rs
@@ -227,7 +227,11 @@ cfg_if! {
pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x40046602;
pub const FS_IOC32_GETVERSION: ::Ioctl = 0x80047601;
pub const FS_IOC32_SETVERSION: ::Ioctl = 0x40047602;
- } else if #[cfg(any(target_arch = "x86_64", target_arch = "riscv64", target_arch = "aarch64", target_arch = "s390x"))] {
+ } else if #[cfg(any(target_arch = "x86_64",
+ target_arch = "riscv64",
+ target_arch = "aarch64",
+ target_arch = "s390x",
+ target_arch = "loongarch64"))] {
pub const FS_IOC_GETFLAGS: ::Ioctl = 0x80086601;
pub const FS_IOC_SETFLAGS: ::Ioctl = 0x40086602;
pub const FS_IOC_GETVERSION: ::Ioctl = 0x80087601;
diff --git a/third_party/rust/libc/src/unix/linux_like/linux/mod.rs b/third_party/rust/libc/src/unix/linux_like/linux/mod.rs
index acb10c603f..cbb3f7bdf5 100644
--- a/third_party/rust/libc/src/unix/linux_like/linux/mod.rs
+++ b/third_party/rust/libc/src/unix/linux_like/linux/mod.rs
@@ -2433,6 +2433,8 @@ pub const CMSPAR: ::tcflag_t = 0o10000000000;
pub const MFD_CLOEXEC: ::c_uint = 0x0001;
pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002;
pub const MFD_HUGETLB: ::c_uint = 0x0004;
+pub const MFD_NOEXEC_SEAL: ::c_uint = 0x0008;
+pub const MFD_EXEC: ::c_uint = 0x0010;
pub const MFD_HUGE_64KB: ::c_uint = 0x40000000;
pub const MFD_HUGE_512KB: ::c_uint = 0x4c000000;
pub const MFD_HUGE_1MB: ::c_uint = 0x50000000;
diff --git a/third_party/rust/libc/src/unix/newlib/vita/mod.rs b/third_party/rust/libc/src/unix/newlib/vita/mod.rs
index e80f061ea0..d4c6955f36 100644
--- a/third_party/rust/libc/src/unix/newlib/vita/mod.rs
+++ b/third_party/rust/libc/src/unix/newlib/vita/mod.rs
@@ -94,6 +94,8 @@ pub const SOCK_RAW: ::c_int = 3;
pub const SOCK_RDM: ::c_int = 4;
pub const SOCK_SEQPACKET: ::c_int = 5;
+pub const SOMAXCONN: ::c_int = 128;
+
pub const FIONBIO: ::c_ulong = 1;
pub const POLLIN: ::c_short = 0x0001;
diff --git a/third_party/rust/libloading/.cargo-checksum.json b/third_party/rust/libloading/.cargo-checksum.json
index 04164017dd..4874dbade8 100644
--- a/third_party/rust/libloading/.cargo-checksum.json
+++ b/third_party/rust/libloading/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"30f23c025249e7779afd2a52fdaba7145dd75c2a3e5a0a23f3322261d6b94c59","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"973a5fa332a8f33abc73ffc0ed509f81c66dbd681d8f50969cac32cdfe16ecb2","src/changelog.rs":"a49ff30e81a245fdcef957a3fffed5a5a5b56825bc51f6ed26fe4c12f75d359c","src/error.rs":"156c53e299e8f1cd4694b277a5d92772a8a9e7ec4004bae067367f4c2502de8b","src/lib.rs":"2eebab93230a59cd87c7884e95c91b3a8736c0a76814dd040864b8c25f0d5f9e","src/os/mod.rs":"6c59ef8c1120953ae6b6c32f27766c643ca90d85075c49c3545d2fe1ed82cedd","src/os/unix/consts.rs":"1418cc26329d01ee6bc9c1144881873a66ac2183c1bf1d589904d569656c80f2","src/os/unix/mod.rs":"dff9590acbbb9a02baea9d2eb870515104c9d519b1896887f3bf1434db442929","src/os/windows/mod.rs":"b14478d7f9d4e8edc8afcbc7aa695ede1ccdd739a94242cb8dbb154fe04e4999","src/safe.rs":"b0dc1cb5c8e0216e365063b5e84218b2377bb7a62714fca9a6215a22a7bc58b8","src/test_helpers.rs":"201403e143e5b3204864124cd38067cf8813d5273dc1a9099288a9dc4bdd15b6","src/util.rs":"0b6dcfb9eafff2d87966460ef6b1b99980f888813037e787ed92deee602f8c2b","tests/constants.rs":"4778c062605ed22238c1bed16de4c076d0857282f090f36e6d985dafb7b4544d","tests/functions.rs":"0cbcc193f8aad71df626aefab9881a76f17c5a4b241855b602ce874018392db7","tests/library_filename.rs":"b1481f0bb374687c5f24e25113426d2a95f08a45fb8bc41a41e8702bd5a7b4bf","tests/markers.rs":"0ebc8f807b92e39452d35732988012cdca7ce96231c57eaac9c3f4217225ad39","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/windows.rs":"35584a46658b305cd539712d3ba3c21fe7a130fd693aa1389e4886a67625d532"},"package":"b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"} \ No newline at end of file
+{"files":{"Cargo.toml":"d97d9cdce69985cab52ba027b089854906d4cf653d581e9742530a536b4599fc","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"707e1cae9fa4b691ce5cb8a3976573158fc60b67cb89948f8f5d51c5908bd0a8","src/changelog.rs":"e7c18ebb9be9624b64bcca3f39d714084cbbaa2ffbc35bfc033967b81be1af66","src/error.rs":"488004e68022adba1002c95d1c8f568fdf1f7bc88aedb6a0f5e31a3dab6f8509","src/lib.rs":"0142a630bb27d1443a8a79d1d5559ea10e859d587442c596d2be7d837507afa0","src/os/mod.rs":"6c59ef8c1120953ae6b6c32f27766c643ca90d85075c49c3545d2fe1ed82cedd","src/os/unix/consts.rs":"a1f98372a58acc6d00a1df19550e0593ede60a53f2aa3ff26cf678cf1015594c","src/os/unix/mod.rs":"15e284c70b61c2728cdf312c2c8740d1671a53dbc7161d8ad5c8a909416644cc","src/os/windows/mod.rs":"8a8792569d43140d982edd6d401abb82023894eb02f2eeba321ee9887568cf3b","src/safe.rs":"b0dc1cb5c8e0216e365063b5e84218b2377bb7a62714fca9a6215a22a7bc58b8","src/test_helpers.rs":"201403e143e5b3204864124cd38067cf8813d5273dc1a9099288a9dc4bdd15b6","src/util.rs":"0b6dcfb9eafff2d87966460ef6b1b99980f888813037e787ed92deee602f8c2b","tests/constants.rs":"4778c062605ed22238c1bed16de4c076d0857282f090f36e6d985dafb7b4544d","tests/functions.rs":"c3d4770704de40e9592cfd109cf506e6b04f0738d8a1ee02ec858b4fa4632a2b","tests/library_filename.rs":"b1481f0bb374687c5f24e25113426d2a95f08a45fb8bc41a41e8702bd5a7b4bf","tests/markers.rs":"0ebc8f807b92e39452d35732988012cdca7ce96231c57eaac9c3f4217225ad39","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/windows.rs":"35584a46658b305cd539712d3ba3c21fe7a130fd693aa1389e4886a67625d532"},"package":"0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"} \ No newline at end of file
diff --git a/third_party/rust/libloading/Cargo.toml b/third_party/rust/libloading/Cargo.toml
index 65168d5858..d5e55487b7 100644
--- a/third_party/rust/libloading/Cargo.toml
+++ b/third_party/rust/libloading/Cargo.toml
@@ -10,9 +10,9 @@
# See Cargo.toml.orig for the original contents.
[package]
-rust-version = "1.40.0"
+rust-version = "1.56.0"
name = "libloading"
-version = "0.7.4"
+version = "0.8.3"
authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
description = "Bindings around the platform's dynamic library loading primitives with greatly improved memory safety."
documentation = "https://docs.rs/libloading/"
@@ -43,9 +43,9 @@ version = "1.1"
[target."cfg(unix)".dependencies.cfg-if]
version = "1"
-[target."cfg(windows)".dependencies.winapi]
-version = "0.3"
-features = [
- "errhandlingapi",
- "libloaderapi",
-]
+[target."cfg(windows)".dependencies.windows-targets]
+version = ">=0.48, <0.53"
+
+[target."cfg(windows)".dev-dependencies.windows-sys]
+version = "0.52"
+features = ["Win32_Foundation"]
diff --git a/third_party/rust/libloading/README.mkd b/third_party/rust/libloading/README.mkd
index 66abb30b6e..7ff55b04b2 100644
--- a/third_party/rust/libloading/README.mkd
+++ b/third_party/rust/libloading/README.mkd
@@ -1,8 +1,11 @@
# libloading
-Bindings around the platform's dynamic library loading primitives with greatly improved memory safety. The most important safety guarantee of this library is the prevention of dangling `Symbol`s that may occur after a `Library` is unloaded.
+Bindings around the platform's dynamic library loading primitives with greatly improved memory
+safety. The most important safety guarantee of this library is the prevention of dangling `Symbol`s
+that may occur after a `Library` is unloaded.
-Using this library allows the loading of dynamic libraries, also known as shared libraries, as well as the use of the functions and static variables that these libraries may contain.
+Using this library allows the loading of dynamic libraries, also known as shared libraries, as well
+as the use of the functions and static variables that these libraries may contain.
* [Documentation][docs]
* [Changelog][changelog]
diff --git a/third_party/rust/libloading/src/changelog.rs b/third_party/rust/libloading/src/changelog.rs
index 162544f34f..58101aecf9 100644
--- a/third_party/rust/libloading/src/changelog.rs
+++ b/third_party/rust/libloading/src/changelog.rs
@@ -1,5 +1,50 @@
//! The change log.
+/// Release 0.8.3 (2024-03-05)
+///
+/// ## Non-breaking changes
+///
+/// A `dev-dependency` on `windows-sys` that was unconditionally introduced in
+/// [0.8.2](r0_8_2) has been made conditional.
+pub mod r0_8_3 {}
+
+/// Release 0.8.2 (2024-03-01)
+///
+/// ## (Potentially) breaking changes
+///
+/// MSRV has been increased to 1.56.0. Since both rustc versions are ancient, this has been deemed
+/// to not be breaking enough to warrant a semver-breaking release of libloading. If you're stick
+/// with a version of rustc older than 1.56.0, lock `libloading` dependency to `0.8.1`.
+///
+/// ## Non-breaking changes
+///
+/// * The crate switches the dependency on `windows-sys` to a `windows-target` one for Windows
+/// bindings. In order to enable this `libloading` defines any bindings necessary for its operation
+/// internally, just like has been done for `unix` targets. This should result in leaner dependency
+/// trees.
+/// * `os::unix::with_dlerror` has been exposed for the users who need to invoke `dl*` family of
+/// functions manually.
+pub mod r0_8_2 {}
+
+/// Release 0.8.1 (2023-09-30)
+///
+/// ## Non-breaking changes
+///
+/// * Support for GNU Hurd.
+pub mod r0_8_1 {}
+
+/// Release 0.8.0 (2023-04-11)
+///
+/// ## (Potentially) breaking changes
+///
+/// * `winapi` dependency has been replaced with `windows-sys`.
+/// * As a result the MSRV has been increased to 1.48.
+///
+/// ## Non-breaking changes
+///
+/// * Support for the QNX Neutrino target has been added.
+pub mod r0_8_0 {}
+
/// Release 0.7.4 (2022-11-07)
///
/// This release has no functional changes.
diff --git a/third_party/rust/libloading/src/error.rs b/third_party/rust/libloading/src/error.rs
index bd70ec39ce..ff4891c901 100644
--- a/third_party/rust/libloading/src/error.rs
+++ b/third_party/rust/libloading/src/error.rs
@@ -1,4 +1,4 @@
-use std::ffi::CString;
+use std::ffi::{CString, CStr};
/// A `dlerror` error.
pub struct DlDescription(pub(crate) CString);
@@ -9,6 +9,12 @@ impl std::fmt::Debug for DlDescription {
}
}
+impl From<&CStr> for DlDescription {
+ fn from(value: &CStr) -> Self {
+ Self(value.into())
+ }
+}
+
/// A Windows API error.
pub struct WindowsError(pub(crate) std::io::Error);
diff --git a/third_party/rust/libloading/src/lib.rs b/third_party/rust/libloading/src/lib.rs
index 6f0e4cb7f7..3ddf98a34b 100644
--- a/third_party/rust/libloading/src/lib.rs
+++ b/third_party/rust/libloading/src/lib.rs
@@ -16,7 +16,7 @@
//!
//! ```toml
//! [dependencies]
-//! libloading = "0.7"
+//! libloading = "0.8"
//! ```
//!
//! # Usage
@@ -41,15 +41,13 @@
pub mod changelog;
pub mod os;
mod util;
-
mod error;
-pub use self::error::Error;
-
#[cfg(any(unix, windows, libloading_docs))]
mod safe;
+
+pub use self::error::Error;
#[cfg(any(unix, windows, libloading_docs))]
pub use self::safe::{Library, Symbol};
-
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::ffi::{OsStr, OsString};
diff --git a/third_party/rust/libloading/src/os/unix/consts.rs b/third_party/rust/libloading/src/os/unix/consts.rs
index ea7a6a102d..ed3edaf829 100644
--- a/third_party/rust/libloading/src/os/unix/consts.rs
+++ b/third_party/rust/libloading/src/os/unix/consts.rs
@@ -82,6 +82,8 @@ mod posix {
target_os = "fuchsia",
target_os = "redox",
+ target_os = "nto",
+ target_os = "hurd",
))] {
pub(super) const RTLD_LAZY: c_int = 1;
} else {
@@ -115,6 +117,8 @@ mod posix {
target_os = "fuchsia",
target_os = "redox",
+ target_os = "nto",
+ target_os = "hurd",
))] {
pub(super) const RTLD_NOW: c_int = 2;
} else if #[cfg(all(target_os = "android",target_pointer_width = "32"))] {
@@ -162,6 +166,8 @@ mod posix {
target_os = "fuchsia",
target_os = "redox",
+ target_os = "nto",
+ target_os = "hurd",
))] {
pub(super) const RTLD_GLOBAL: c_int = 0x100;
} else {
@@ -172,7 +178,10 @@ mod posix {
}
cfg_if! {
- if #[cfg(target_os = "netbsd")] {
+ if #[cfg(any(
+ target_os = "netbsd",
+ target_os = "nto",
+ ))] {
pub(super) const RTLD_LOCAL: c_int = 0x200;
} else if #[cfg(target_os = "aix")] {
pub(super) const RTLD_LOCAL: c_int = 0x80000;
@@ -200,6 +209,7 @@ mod posix {
target_os = "fuchsia",
target_os = "redox",
+ target_os = "hurd",
))] {
pub(super) const RTLD_LOCAL: c_int = 0;
} else {
diff --git a/third_party/rust/libloading/src/os/unix/mod.rs b/third_party/rust/libloading/src/os/unix/mod.rs
index df7efdad54..6347e02700 100644
--- a/third_party/rust/libloading/src/os/unix/mod.rs
+++ b/third_party/rust/libloading/src/os/unix/mod.rs
@@ -16,18 +16,33 @@ use util::{cstr_cow_from_bytes, ensure_compatible_types};
mod consts;
-// dl* family of functions did not have enough thought put into it.
-//
-// Whole error handling scheme is done via setting and querying some global state, therefore it is
-// not safe to use dynamic library loading in MT-capable environment at all. Only in POSIX 2008+TC1
-// a thread-local state was allowed for `dlerror`, making the dl* family of functions MT-safe.
-//
-// In practice (as of 2020-04-01) most of the widely used targets use a thread-local for error
-// state and have been doing so for a long time. Regardless the comments in this function shall
-// remain as a documentation for the future generations.
-fn with_dlerror<T, F>(wrap: fn(crate::error::DlDescription) -> crate::Error, closure: F)
--> Result<T, Option<crate::Error>>
-where F: FnOnce() -> Option<T> {
+/// Run code and handle errors reported by `dlerror`.
+///
+/// This function first executes the `closure` function containing calls to the functions that
+/// report their errors via `dlerror`. This closure may return either `None` or `Some(*)` to
+/// further affect operation of this function.
+///
+/// In case the `closure` returns `None`, `with_dlerror` inspects the `dlerror`. `dlerror` may
+/// decide to not provide any error description, in which case `Err(None)` is returned to the
+/// caller. Otherwise the `error` callback is invoked to allow inspection and conversion of the
+/// error message. The conversion result is returned as `Err(Some(Error))`.
+///
+/// If the operations that report their errors via `dlerror` were all successful, `closure` should
+/// return `Some(T)` instead. In this case `dlerror` is not inspected at all.
+///
+/// # Notes
+///
+/// The whole `dlerror` handling scheme is done via setting and querying some global state. For
+/// that reason it is not safe to use dynamic library loading in MT-capable environment at all.
+/// Only in POSIX 2008+TC1 a thread-local state was allowed for `dlerror`, making the dl* family of
+/// functions possibly MT-safe, depending on the implementation of `dlerror`.
+///
+/// In practice (as of 2020-04-01) most of the widely used targets use a thread-local for error
+/// state and have been doing so for a long time.
+pub fn with_dlerror<T, F, Error>(closure: F, error: fn(&CStr) -> Error) -> Result<T, Option<Error>>
+where
+ F: FnOnce() -> Option<T>,
+{
// We used to guard all uses of dl* functions with our own mutex. This made them safe to use in
// MT programs provided the only way a program used dl* was via this library. However, it also
// had a number of downsides or cases where it failed to handle the problems. For instance,
@@ -53,8 +68,8 @@ where F: FnOnce() -> Option<T> {
// or a bug in implementation of dl* family of functions.
closure().ok_or_else(|| unsafe {
// This code will only get executed if the `closure` returns `None`.
- let error = dlerror();
- if error.is_null() {
+ let dlerror_str = dlerror();
+ if dlerror_str.is_null() {
// In non-dlsym case this may happen when there’re bugs in our bindings or there’s
// non-libloading user of libdl; possibly in another thread.
None
@@ -64,8 +79,7 @@ where F: FnOnce() -> Option<T> {
// ownership over the message?
// TODO: should do locale-aware conversion here. OTOH Rust doesn’t seem to work well in
// any system that uses non-utf8 locale, so I doubt there’s a problem here.
- let message = CStr::from_ptr(error).into();
- Some(wrap(crate::error::DlDescription(message)))
+ Some(error(CStr::from_ptr(dlerror_str)))
// Since we do a copy of the error string above, maybe we should call dlerror again to
// let libdl know it may free its copy of the string now?
}
@@ -74,7 +88,7 @@ where F: FnOnce() -> Option<T> {
/// A platform-specific counterpart of the cross-platform [`Library`](crate::Library).
pub struct Library {
- handle: *mut raw::c_void
+ handle: *mut raw::c_void,
}
unsafe impl Send for Library {}
@@ -164,30 +178,38 @@ impl Library {
/// termination routines contained within the library is safe as well. These routines may be
/// executed when the library is unloaded.
pub unsafe fn open<P>(filename: Option<P>, flags: raw::c_int) -> Result<Library, crate::Error>
- where P: AsRef<OsStr> {
+ where
+ P: AsRef<OsStr>,
+ {
let filename = match filename {
None => None,
Some(ref f) => Some(cstr_cow_from_bytes(f.as_ref().as_bytes())?),
};
- with_dlerror(|desc| crate::Error::DlOpen { desc }, move || {
- let result = dlopen(match filename {
- None => ptr::null(),
- Some(ref f) => f.as_ptr()
- }, flags);
- // ensure filename lives until dlopen completes
- drop(filename);
- if result.is_null() {
- None
- } else {
- Some(Library {
- handle: result
- })
- }
- }).map_err(|e| e.unwrap_or(crate::Error::DlOpenUnknown))
+ with_dlerror(
+ move || {
+ let result = dlopen(
+ match filename {
+ None => ptr::null(),
+ Some(ref f) => f.as_ptr(),
+ },
+ flags,
+ );
+ // ensure filename lives until dlopen completes
+ drop(filename);
+ if result.is_null() {
+ None
+ } else {
+ Some(Library { handle: result })
+ }
+ },
+ |desc| crate::Error::DlOpen { desc: desc.into() },
+ )
+ .map_err(|e| e.unwrap_or(crate::Error::DlOpenUnknown))
}
unsafe fn get_impl<T, F>(&self, symbol: &[u8], on_null: F) -> Result<Symbol<T>, crate::Error>
- where F: FnOnce() -> Result<Symbol<T>, crate::Error>
+ where
+ F: FnOnce() -> Result<Symbol<T>, crate::Error>,
{
ensure_compatible_types::<T, *mut raw::c_void>()?;
let symbol = cstr_cow_from_bytes(symbol)?;
@@ -197,23 +219,26 @@ impl Library {
//
// We try to leave as little space as possible for this to occur, but we can’t exactly
// fully prevent it.
- match with_dlerror(|desc| crate::Error::DlSym { desc }, || {
- dlerror();
- let symbol = dlsym(self.handle, symbol.as_ptr());
- if symbol.is_null() {
- None
- } else {
- Some(Symbol {
- pointer: symbol,
- pd: marker::PhantomData
- })
- }
- }) {
+ let result = with_dlerror(
+ || {
+ dlerror();
+ let symbol = dlsym(self.handle, symbol.as_ptr());
+ if symbol.is_null() {
+ None
+ } else {
+ Some(Symbol {
+ pointer: symbol,
+ pd: marker::PhantomData,
+ })
+ }
+ },
+ |desc| crate::Error::DlSym { desc: desc.into() },
+ );
+ match result {
Err(None) => on_null(),
Err(Some(e)) => Err(e),
- Ok(x) => Ok(x)
+ Ok(x) => Ok(x),
}
-
}
/// Get a pointer to a function or static variable by symbol name.
@@ -284,10 +309,12 @@ impl Library {
/// variables that work on e.g. Linux may have unintended behaviour on other targets.
#[inline(always)]
pub unsafe fn get_singlethreaded<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
- self.get_impl(symbol, || Ok(Symbol {
- pointer: ptr::null_mut(),
- pd: marker::PhantomData
- }))
+ self.get_impl(symbol, || {
+ Ok(Symbol {
+ pointer: ptr::null_mut(),
+ pd: marker::PhantomData,
+ })
+ })
}
/// Convert the `Library` to a raw handle.
@@ -308,9 +335,7 @@ impl Library {
/// pointer previously returned by `Library::into_raw` call. It must be valid to call `dlclose`
/// with this pointer as an argument.
pub unsafe fn from_raw(handle: *mut raw::c_void) -> Library {
- Library {
- handle
- }
+ Library { handle }
}
/// Unload the library.
@@ -324,13 +349,17 @@ impl Library {
///
/// The underlying data structures may still get leaked if an error does occur.
pub fn close(self) -> Result<(), crate::Error> {
- let result = with_dlerror(|desc| crate::Error::DlClose { desc }, || {
- if unsafe { dlclose(self.handle) } == 0 {
- Some(())
- } else {
- None
- }
- }).map_err(|e| e.unwrap_or(crate::Error::DlCloseUnknown));
+ let result = with_dlerror(
+ || {
+ if unsafe { dlclose(self.handle) } == 0 {
+ Some(())
+ } else {
+ None
+ }
+ },
+ |desc| crate::Error::DlClose { desc: desc.into() },
+ )
+ .map_err(|e| e.unwrap_or(crate::Error::DlCloseUnknown));
// While the library is not free'd yet in case of an error, there is no reason to try
// dropping it again, because all that will do is try calling `dlclose` again. only
// this time it would ignore the return result, which we already seen failing…
@@ -359,7 +388,7 @@ impl fmt::Debug for Library {
/// `Symbol` does not outlive the `Library` it comes from.
pub struct Symbol<T> {
pointer: *mut raw::c_void,
- pd: marker::PhantomData<T>
+ pd: marker::PhantomData<T>,
}
impl<T> Symbol<T> {
@@ -409,13 +438,18 @@ impl<T> fmt::Debug for Symbol<T> {
if dladdr(self.pointer, info.as_mut_ptr()) != 0 {
let info = info.assume_init();
if info.dli_sname.is_null() {
- f.write_str(&format!("Symbol@{:p} from {:?}",
- self.pointer,
- CStr::from_ptr(info.dli_fname)))
+ f.write_str(&format!(
+ "Symbol@{:p} from {:?}",
+ self.pointer,
+ CStr::from_ptr(info.dli_fname)
+ ))
} else {
- f.write_str(&format!("Symbol {:?}@{:p} from {:?}",
- CStr::from_ptr(info.dli_sname), self.pointer,
- CStr::from_ptr(info.dli_fname)))
+ f.write_str(&format!(
+ "Symbol {:?}@{:p} from {:?}",
+ CStr::from_ptr(info.dli_sname),
+ self.pointer,
+ CStr::from_ptr(info.dli_fname)
+ ))
}
} else {
f.write_str(&format!("Symbol@{:p}", self.pointer))
@@ -425,9 +459,9 @@ impl<T> fmt::Debug for Symbol<T> {
}
// Platform specific things
-#[cfg_attr(any(target_os = "linux", target_os = "android"), link(name="dl"))]
-#[cfg_attr(any(target_os = "freebsd", target_os = "dragonfly"), link(name="c"))]
-extern {
+#[cfg_attr(any(target_os = "linux", target_os = "android"), link(name = "dl"))]
+#[cfg_attr(any(target_os = "freebsd", target_os = "dragonfly"), link(name = "c"))]
+extern "C" {
fn dlopen(filename: *const raw::c_char, flags: raw::c_int) -> *mut raw::c_void;
fn dlclose(handle: *mut raw::c_void) -> raw::c_int;
fn dlsym(handle: *mut raw::c_void, symbol: *const raw::c_char) -> *mut raw::c_void;
@@ -437,8 +471,8 @@ extern {
#[repr(C)]
struct DlInfo {
- dli_fname: *const raw::c_char,
- dli_fbase: *mut raw::c_void,
- dli_sname: *const raw::c_char,
- dli_saddr: *mut raw::c_void
+ dli_fname: *const raw::c_char,
+ dli_fbase: *mut raw::c_void,
+ dli_sname: *const raw::c_char,
+ dli_saddr: *mut raw::c_void,
}
diff --git a/third_party/rust/libloading/src/os/windows/mod.rs b/third_party/rust/libloading/src/os/windows/mod.rs
index e3da940a29..172801e168 100644
--- a/third_party/rust/libloading/src/os/windows/mod.rs
+++ b/third_party/rust/libloading/src/os/windows/mod.rs
@@ -1,53 +1,18 @@
// A hack for docs.rs to build documentation that has both windows and linux documentation in the
// same rustdoc build visible.
#[cfg(all(libloading_docs, not(windows)))]
-mod windows_imports {
- pub(super) enum WORD {}
- pub(super) struct DWORD;
- pub(super) enum HMODULE {}
- pub(super) enum FARPROC {}
-
- pub(super) mod consts {
- use super::DWORD;
- pub(crate) const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_AS_DATAFILE: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = DWORD;
- pub(crate) const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = DWORD;
- pub(crate) const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = DWORD;
- }
-}
+mod windows_imports {}
#[cfg(any(not(libloading_docs), windows))]
mod windows_imports {
- extern crate winapi;
- pub(super) use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
- pub(super) use self::winapi::shared::ntdef::WCHAR;
- pub(super) use self::winapi::um::{errhandlingapi, libloaderapi};
+ use super::{DWORD, BOOL, HANDLE, HMODULE, FARPROC};
pub(super) use std::os::windows::ffi::{OsStrExt, OsStringExt};
- pub(super) const SEM_FAILCE: DWORD = 1;
-
- pub(super) mod consts {
- pub(crate) use super::winapi::um::libloaderapi::{
- LOAD_IGNORE_CODE_AUTHZ_LEVEL,
- LOAD_LIBRARY_AS_DATAFILE,
- LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE,
- LOAD_LIBRARY_AS_IMAGE_RESOURCE,
- LOAD_LIBRARY_SEARCH_APPLICATION_DIR,
- LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
- LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR,
- LOAD_LIBRARY_SEARCH_SYSTEM32,
- LOAD_LIBRARY_SEARCH_USER_DIRS,
- LOAD_WITH_ALTERED_SEARCH_PATH,
- LOAD_LIBRARY_REQUIRE_SIGNED_TARGET,
- LOAD_LIBRARY_SAFE_CURRENT_DIRS,
- };
- }
+ windows_targets::link!("kernel32.dll" "system" fn GetLastError() -> DWORD);
+ windows_targets::link!("kernel32.dll" "system" fn SetThreadErrorMode(new_mode: DWORD, old_mode: *mut DWORD) -> BOOL);
+ windows_targets::link!("kernel32.dll" "system" fn GetModuleHandleExW(flags: u32, module_name: *const u16, module: *mut HMODULE) -> BOOL);
+ windows_targets::link!("kernel32.dll" "system" fn FreeLibrary(module: HMODULE) -> BOOL);
+ windows_targets::link!("kernel32.dll" "system" fn LoadLibraryExW(filename: *const u16, file: HANDLE, flags: DWORD) -> HMODULE);
+ windows_targets::link!("kernel32.dll" "system" fn GetModuleFileNameW(module: HMODULE, filename: *mut u16, size: DWORD) -> DWORD);
+ windows_targets::link!("kernel32.dll" "system" fn GetProcAddress(module: HMODULE, procname: *const u8) -> FARPROC);
}
use self::windows_imports::*;
@@ -116,9 +81,9 @@ impl Library {
/// [MSDN]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
pub fn this() -> Result<Library, crate::Error> {
unsafe {
- let mut handle: HMODULE = std::ptr::null_mut();
+ let mut handle: HMODULE = 0;
with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
- let result = libloaderapi::GetModuleHandleExW(0, std::ptr::null_mut(), &mut handle);
+ let result = GetModuleHandleExW(0, std::ptr::null_mut(), &mut handle);
if result == 0 {
None
} else {
@@ -149,11 +114,11 @@ impl Library {
let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
let ret = unsafe {
- let mut handle: HMODULE = std::ptr::null_mut();
+ let mut handle: HMODULE = 0;
with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
// Make sure no winapi calls as a result of drop happen inside this closure, because
// otherwise that might change the return value of the GetLastError.
- let result = libloaderapi::GetModuleHandleExW(0, wide_filename.as_ptr(), &mut handle);
+ let result = GetModuleHandleExW(0, wide_filename.as_ptr(), &mut handle);
if result == 0 {
None
} else {
@@ -186,16 +151,15 @@ impl Library {
/// Additionally, the callers of this function must also ensure that execution of the
/// termination routines contained within the library is safe as well. These routines may be
/// executed when the library is unloaded.
- pub unsafe fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
+ pub unsafe fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: LOAD_LIBRARY_FLAGS) -> Result<Library, crate::Error> {
let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
let _guard = ErrorModeGuard::new();
let ret = with_get_last_error(|source| crate::Error::LoadLibraryExW { source }, || {
// Make sure no winapi calls as a result of drop happen inside this closure, because
// otherwise that might change the return value of the GetLastError.
- let handle =
- libloaderapi::LoadLibraryExW(wide_filename.as_ptr(), std::ptr::null_mut(), flags);
- if handle.is_null() {
+ let handle = LoadLibraryExW(wide_filename.as_ptr(), 0, flags);
+ if handle == 0 {
None
} else {
Some(Library(handle))
@@ -221,8 +185,8 @@ impl Library {
ensure_compatible_types::<T, FARPROC>()?;
let symbol = cstr_cow_from_bytes(symbol)?;
with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
- let symbol = libloaderapi::GetProcAddress(self.0, symbol.as_ptr());
- if symbol.is_null() {
+ let symbol = GetProcAddress(self.0, symbol.as_ptr().cast());
+ if symbol.is_none() {
None
} else {
Some(Symbol {
@@ -238,12 +202,12 @@ impl Library {
/// # Safety
///
/// Users of this API must specify the correct type of the function or variable loaded.
- pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error> {
+ pub unsafe fn get_ordinal<T>(&self, ordinal: u16) -> Result<Symbol<T>, crate::Error> {
ensure_compatible_types::<T, FARPROC>()?;
with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
- let ordinal = ordinal as usize as *mut _;
- let symbol = libloaderapi::GetProcAddress(self.0, ordinal);
- if symbol.is_null() {
+ let ordinal = ordinal as usize as *const _;
+ let symbol = GetProcAddress(self.0, ordinal);
+ if symbol.is_none() {
None
} else {
Some(Symbol {
@@ -280,7 +244,7 @@ impl Library {
/// The underlying data structures may still get leaked if an error does occur.
pub fn close(self) -> Result<(), crate::Error> {
let result = with_get_last_error(|source| crate::Error::FreeLibrary { source }, || {
- if unsafe { libloaderapi::FreeLibrary(self.0) == 0 } {
+ if unsafe { FreeLibrary(self.0) == 0 } {
None
} else {
Some(())
@@ -296,7 +260,7 @@ impl Library {
impl Drop for Library {
fn drop(&mut self) {
- unsafe { libloaderapi::FreeLibrary(self.0); }
+ unsafe { FreeLibrary(self.0); }
}
}
@@ -305,17 +269,17 @@ impl fmt::Debug for Library {
unsafe {
// FIXME: use Maybeuninit::uninit_array when stable
let mut buf =
- mem::MaybeUninit::<[mem::MaybeUninit::<WCHAR>; 1024]>::uninit().assume_init();
- let len = libloaderapi::GetModuleFileNameW(self.0,
+ mem::MaybeUninit::<[mem::MaybeUninit<u16>; 1024]>::uninit().assume_init();
+ let len = GetModuleFileNameW(self.0,
buf[..].as_mut_ptr().cast(), 1024) as usize;
if len == 0 {
- f.write_str(&format!("Library@{:p}", self.0))
+ f.write_str(&format!("Library@{:#x}", self.0))
} else {
let string: OsString = OsString::from_wide(
// FIXME: use Maybeuninit::slice_get_ref when stable
- &*(&buf[..len] as *const [_] as *const [WCHAR])
+ &*(&buf[..len] as *const [_] as *const [u16]),
);
- f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
+ f.write_str(&format!("Library@{:#x} from {:?}", self.0, string))
}
}
}
@@ -340,7 +304,7 @@ impl<T> Symbol<T> {
impl<T> Symbol<Option<T>> {
/// Lift Option out of the symbol.
pub fn lift_option(self) -> Option<Symbol<T>> {
- if self.pointer.is_null() {
+ if self.pointer.is_none() {
None
} else {
Some(Symbol {
@@ -363,16 +327,16 @@ impl<T> Clone for Symbol<T> {
impl<T> ::std::ops::Deref for Symbol<T> {
type Target = T;
fn deref(&self) -> &T {
- unsafe {
- // Additional reference level for a dereference on `deref` return value.
- &*(&self.pointer as *const *mut _ as *const T)
- }
+ unsafe { &*((&self.pointer) as *const FARPROC as *const T) }
}
}
impl<T> fmt::Debug for Symbol<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str(&format!("Symbol@{:p}", self.pointer))
+ match self.pointer {
+ None => f.write_str("Symbol@0x0"),
+ Some(ptr) => f.write_str(&format!("Symbol@{:p}", ptr as *const ())),
+ }
}
}
@@ -383,13 +347,13 @@ impl ErrorModeGuard {
fn new() -> Option<ErrorModeGuard> {
unsafe {
let mut previous_mode = 0;
- if errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) == 0 {
+ if SetThreadErrorMode(SEM_FAILCRITICALERRORS, &mut previous_mode) == 0 {
// How in the world is it possible for what is essentially a simple variable swap
// to fail? For now we just ignore the error -- the worst that can happen here is
// the previous mode staying on and user seeing a dialog error on older Windows
// machines.
None
- } else if previous_mode == SEM_FAILCE {
+ } else if previous_mode == SEM_FAILCRITICALERRORS {
None
} else {
Some(ErrorModeGuard(previous_mode))
@@ -401,7 +365,7 @@ impl ErrorModeGuard {
impl Drop for ErrorModeGuard {
fn drop(&mut self) {
unsafe {
- errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
+ SetThreadErrorMode(self.0, ptr::null_mut());
}
}
}
@@ -410,7 +374,7 @@ fn with_get_last_error<T, F>(wrap: fn(crate::error::WindowsError) -> crate::Erro
-> Result<T, Option<crate::Error>>
where F: FnOnce() -> Option<T> {
closure().ok_or_else(|| {
- let error = unsafe { errhandlingapi::GetLastError() };
+ let error = unsafe { GetLastError() };
if error == 0 {
None
} else {
@@ -419,13 +383,29 @@ where F: FnOnce() -> Option<T> {
})
}
+
+#[allow(clippy::upper_case_acronyms)]
+type BOOL = i32;
+#[allow(clippy::upper_case_acronyms)]
+type DWORD = u32;
+#[allow(clippy::upper_case_acronyms)]
+type HANDLE = isize;
+#[allow(clippy::upper_case_acronyms)]
+type HMODULE = isize;
+#[allow(clippy::upper_case_acronyms)]
+type FARPROC = Option<unsafe extern "system" fn() -> isize>;
+#[allow(non_camel_case_types)]
+type LOAD_LIBRARY_FLAGS = DWORD;
+
+const SEM_FAILCRITICALERRORS: DWORD = 1;
+
/// Do not check AppLocker rules or apply Software Restriction Policies for the DLL.
///
/// This action applies only to the DLL being loaded and not to its dependencies. This value is
/// recommended for use in setup programs that must run extracted DLLs during installation.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = consts::LOAD_IGNORE_CODE_AUTHZ_LEVEL;
+pub const LOAD_IGNORE_CODE_AUTHZ_LEVEL: LOAD_LIBRARY_FLAGS = 0x00000010;
/// Map the file into the calling process’ virtual address space as if it were a data file.
///
@@ -435,7 +415,7 @@ pub const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = consts::LOAD_IGNORE_CODE_AUTHZ_L
/// messages or resources from it.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_AS_DATAFILE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE;
+pub const LOAD_LIBRARY_AS_DATAFILE: LOAD_LIBRARY_FLAGS = 0x00000002;
/// Map the file into the calling process’ virtual address space as if it were a data file.
///
@@ -444,7 +424,7 @@ pub const LOAD_LIBRARY_AS_DATAFILE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE;
/// while it is in use. However, the DLL can still be opened by other processes.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE;
+pub const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: LOAD_LIBRARY_FLAGS = 0x00000040;
/// Map the file into the process’ virtual address space as an image file.
///
@@ -456,7 +436,7 @@ pub const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = consts::LOAD_LIBRARY_AS_DA
/// [`LOAD_LIBRARY_AS_DATAFILE`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = consts::LOAD_LIBRARY_AS_IMAGE_RESOURCE;
+pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: LOAD_LIBRARY_FLAGS = 0x00000020;
/// Search the application's installation directory for the DLL and its dependencies.
///
@@ -464,7 +444,7 @@ pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = consts::LOAD_LIBRARY_AS_IMAGE_
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_APPLICATION_DIR;
+pub const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: LOAD_LIBRARY_FLAGS = 0x00000200;
/// Search default directories when looking for the DLL and its dependencies.
///
@@ -474,7 +454,7 @@ pub const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = consts::LOAD_LIBRARY_SEAR
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;
+pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: LOAD_LIBRARY_FLAGS = 0x00001000;
/// Directory that contains the DLL is temporarily added to the beginning of the list of
/// directories that are searched for the DLL’s dependencies.
@@ -485,7 +465,7 @@ pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_
/// with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
+pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: LOAD_LIBRARY_FLAGS = 0x00000100;
/// Search `%windows%\system32` for the DLL and its dependencies.
///
@@ -493,7 +473,7 @@ pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = consts::LOAD_LIBRARY_SEARCH_SYSTEM32;
+pub const LOAD_LIBRARY_SEARCH_SYSTEM32: LOAD_LIBRARY_FLAGS = 0x00000800;
/// Directories added using the `AddDllDirectory` or the `SetDllDirectory` function are searched
/// for the DLL and its dependencies.
@@ -503,7 +483,7 @@ pub const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = consts::LOAD_LIBRARY_SEARCH_SYST
/// combined with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_USER_DIRS;
+pub const LOAD_LIBRARY_SEARCH_USER_DIRS: LOAD_LIBRARY_FLAGS = 0x00000400;
/// If `filename` specifies an absolute path, the system uses the alternate file search strategy
/// discussed in the [Remarks section] to find associated executable modules that the specified
@@ -518,15 +498,15 @@ pub const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_USE
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
///
/// [Remarks]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#remarks
-pub const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = consts::LOAD_WITH_ALTERED_SEARCH_PATH;
+pub const LOAD_WITH_ALTERED_SEARCH_PATH: LOAD_LIBRARY_FLAGS = 0x00000008;
/// Specifies that the digital signature of the binary image must be checked at load time.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = consts::LOAD_LIBRARY_REQUIRE_SIGNED_TARGET;
+pub const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: LOAD_LIBRARY_FLAGS = 0x00000080;
/// Allow loading a DLL for execution from the current directory only if it is under a directory in
/// the Safe load list.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
-pub const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = consts::LOAD_LIBRARY_SAFE_CURRENT_DIRS;
+pub const LOAD_LIBRARY_SAFE_CURRENT_DIRS: LOAD_LIBRARY_FLAGS = 0x00002000;
diff --git a/third_party/rust/libloading/tests/functions.rs b/third_party/rust/libloading/tests/functions.rs
index c8d1952b3c..a0175a6747 100644
--- a/third_party/rust/libloading/tests/functions.rs
+++ b/third_party/rust/libloading/tests/functions.rs
@@ -1,5 +1,5 @@
#[cfg(windows)]
-extern crate winapi;
+extern crate windows_sys;
extern crate libloading;
use libloading::{Library, Symbol};
@@ -237,14 +237,13 @@ fn library_this() {
#[test]
fn works_getlasterror() {
use libloading::os::windows::{Library, Symbol};
- use winapi::shared::minwindef::DWORD;
- use winapi::um::errhandlingapi;
+ use windows_sys::Win32::Foundation::{GetLastError, SetLastError};
unsafe {
let lib = Library::new("kernel32.dll").unwrap();
- let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError").unwrap();
- errhandlingapi::SetLastError(42);
- assert_eq!(errhandlingapi::GetLastError(), gle())
+ let gle: Symbol<unsafe extern "system" fn() -> u32> = lib.get(b"GetLastError").unwrap();
+ SetLastError(42);
+ assert_eq!(GetLastError(), gle())
}
}
@@ -252,14 +251,13 @@ fn works_getlasterror() {
#[test]
fn works_getlasterror0() {
use libloading::os::windows::{Library, Symbol};
- use winapi::shared::minwindef::DWORD;
- use winapi::um::errhandlingapi;
+ use windows_sys::Win32::Foundation::{GetLastError, SetLastError};
unsafe {
let lib = Library::new("kernel32.dll").unwrap();
- let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError\0").unwrap();
- errhandlingapi::SetLastError(42);
- assert_eq!(errhandlingapi::GetLastError(), gle())
+ let gle: Symbol<unsafe extern "system" fn() -> u32> = lib.get(b"GetLastError\0").unwrap();
+ SetLastError(42);
+ assert_eq!(GetLastError(), gle())
}
}
diff --git a/third_party/rust/metal/.cargo-checksum.json b/third_party/rust/metal/.cargo-checksum.json
index a14acdb20b..792477e782 100644
--- a/third_party/rust/metal/.cargo-checksum.json
+++ b/third_party/rust/metal/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"ff54827be57e86ac1a50fb371f128cfc0fa87b26de767444e4f59905c98cacfd","Cargo.toml":"eb5025605544e8c4506fea4fa153171c5adaf9bc4a8a2741aaf79c153a1bb7df","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","Makefile":"99c4c592467981921d1257a4e9e841dce53624448738d0ed52a75431a406f7bc","README.md":"b61a350d23e7c88c34b1cd703083978e17c28a286e4231f1dc0a2383a1f85902","assets/metal.svg":"3a295bd130785bc2fea2f3a91a4f6c7b4b3c40682c3fcb7a75f9887b66b06264","bors.toml":"c2733ec512a08bf76b6a1ed77270810a0edeb888ba24c2a75679e1eb1bd563a5","examples/argument-buffer/main.rs":"a087db6648a4b092520de29616521c704d892e0d3ace935d16f3f339415c4361","examples/bind/main.rs":"a0c85aad05f08666f9b380a7146a8473a6a6fe0db5d523760373093a0af20e5f","examples/bindless/main.rs":"0aaad9e42634c1ea204342a76c1bfe80c8fcf9d3ebe8247846cf63ecb08fb0d5","examples/caps/main.rs":"b7be00c1cc9042140d34ea05051152a7035f316f0bdcd31ac5a660a97e0c4f70","examples/circle/README.md":"e1c97cf5252f0d1f2934ace78b5d839c5f45911f3007dbd2925eeceefb8f0af6","examples/circle/main.rs":"22bd52ccba85debc1ccb3f277750e4759283d3c9b135b9a0da496c747e4cf637","examples/circle/screenshot.png":"97bf07c85bf02367447b9c8a81707c124e4a3b420fa386b95ba08b21938f4f2a","examples/circle/shaders.metal":"5e4f40efca5bb386204a09e1b983cc6c634fdf1ca9dd4974227313adbf50e8b5","examples/circle/shaders.metallib":"666a9491d795ef9c0b9c122c7ada571cc2c0e8774d2d89e5b4b996f3dc47962b","examples/compute/compute-argument-buffer.metal":"6530bbd6a0101d9db2893805436f5dc877959e81ea97a27014c0fc52fc9fa77b","examples/compute/compute-argument-buffer.rs":"e3de61fd7cc2f14d9d52300e4878601dbc072bc26d9dafc66115df58f94e0470","examples/compute/embedded-lib.rs":"55f701810fa5270c27ca771e713f9f8cf09e124a997b0b03790b38435593a7ea","examples/compute/main.rs":"bf160f3aba9f7492e3f4b6cf3198f8e454a49d6a29225312a84fdb9d784ffec4","examples/compute/shaders.metal":"f2b15551bb5247b88a3029c3d8ef37c6fa04a4a6cca9f90f069894ed6822b4bf","examples/compute/shaders.metallib":"fef91643e60c0ec99ad2bd2f3916299bcc3e6a80038ea27bed59681badfea7d1","examples/events/main.rs":"9cb35381b0a3918bd7d530171de8f7cceafe3d4851c0f430b4aff1f5c2aae749","examples/fence/main.rs":"47741327e62db1d8bd344b6a9ec26ef13ffb0b56b0dd7077c5d926d43faaeff7","examples/headless-render/README.md":"b1c97b52701cfb41fc0b9e269ba7a7a454d9161746198e2f5789f2636f60842d","examples/headless-render/main.rs":"2e6eb5db66f28833d1b53df3f134b4b53907a00036eeb6cdd9e428478e164aae","examples/headless-render/screenshot.png":"01d6ea5791b63b0f01190198756446cf313fc25dc64d0138c1b4f62c9f862dd1","examples/library/main.rs":"a1420ec28a471f28a789b75b3ecf5abb699ed352b337747169914812fb98045a","examples/mesh-shader/main.rs":"49899300f80f2d1e64366176313f69b597b69f3728a52a6a6f56ff7cd54c3c23","examples/mesh-shader/shaders.metal":"6ba934c3edd3ba0b8f6c4ac37be0fd0fe35eeef004e371521b7bf5a2fae9a223","examples/mesh-shader/shaders.metallib":"0af3b7ab0cd6186a90163550b76fab5bd2ef6ba97e791354d4281ca92d4887ff","examples/mps/main.rs":"2cbb532635270bc55cdfa3ee231cc2ee20dd8b3a5e6bf76062cca89ef1e3498f","examples/mps/shaders.metal":"155922d6a4184078ae7ee29504a268e1218f07d908f921eef60e5bfa8a793bda","examples/mps/shaders.metallib":"b62451223549b1e7eb90ec3d3534c0ed4cdfdc581c7df3ffcdc4786a5fcacde4","examples/raytracing/README.md":"6f0d683efac74572099c317ce9f65c3e6ff3c5252c6870c0c38c67f08b37bb01","examples/raytracing/camera.rs":"bed7a1787e1a52060dd0d64ff630a6fb769f15098d0a9d3ea68d4b57aee78b53","examples/raytracing/geometry.rs":"d3db29b4ab2d3d39de74718e0a7133a4e576dc26dcc6b6728c047865fb78952a","examples/raytracing/main.rs":"c3571854cbaaaeea386d7eb8af1fe9ea0492eae9af62b60203f4b6937dc4999a","examples/raytracing/renderer.rs":"d4e704b8f8e61919882aafc009b3a20928902d5b7edb9122d05f3e468d32f613","examples/raytracing/scene.rs":"fc2f214e0ad90e916fdbe2a339567a5dd323ef45b916fa8432c1156b4e94b998","examples/raytracing/screenshot.png":"400bb138f5adb69e4db8626681fb17667e5e112c94864879d9282d5348d970db","examples/raytracing/shaders.metal":"696f6a0ba79d82e2fa0e03eadbff2f6cdeac87acc805c2b7df657b85c1173174","examples/raytracing/shaders.metallib":"249b71998f58ddf8b3de37d79e9cc1f4a3494fba4bd7ba3f5411fb603de9dd5a","examples/reflection/main.rs":"563b49f5c057f1f8d17f3480cbc466e073ea575bfafaf84018a331a984d90a62","examples/shader-dylib/main.rs":"f18f4eb01420e12c196848c42657d41390cf10a3e47e8870025c20a1b29ddc71","examples/shader-dylib/test_dylib.metal":"3469de785c2c0da784e84758fc0da5a81e474ca15588485d9e04398690641cc8","examples/shader-dylib/test_shader.metal":"1a04ff8ab3288b09d14cd35440b2557e92ddedbff9d07c4144a22e9062e6e1e4","examples/window/README.md":"69655cff298e07887fe70e8a13e27d8a87efcd0cc0da4e15485134e064e1aceb","examples/window/main.rs":"09c508013223de859f33fb69410bde30e8d7f04952850504d8b1f8faf7049b1b","examples/window/screenshot.png":"da7369d7cc297c7f7f6bd773c93e7d708d72442c9c5ff5a20c2f2ee6852552dc","examples/window/shaders.metal":"90dee6c752add5c617dfdca93064b2824b44ff8c01ef63986826f6a1531e95d6","examples/window/shaders.metallib":"16fa82beb70bf16c3501970cae0d5028a747a08164337161dc9c2e8965d4c366","src/accelerator_structure.rs":"3b014b17a30e96d32d6fc69b6d067c08a9d4356cb10dc9121824117711211449","src/argument.rs":"347a5a01d4804044641e09d120d37bba140fc6a364782a96470b753e1ee74b30","src/blitpass.rs":"67b561b319e0650aa8438ce056998d4abd86b765a345f382013ab3cae7a2e71f","src/buffer.rs":"78d9021ab75ef0dad09ff92d126f1ceea241cca606cd7b05553c9351458babed","src/capturedescriptor.rs":"c687c4db298fb83ef640eb34929758c2d7955174a68725e986838e367291e302","src/capturemanager.rs":"c8a42854eebcfb6a7b777d931e368e04a5e35dff2e46c38c481d266dba9b792d","src/commandbuffer.rs":"464d504969ba1c213f6f8812b414c1581e39490cd048888404e04fbb5a1bd4ce","src/commandqueue.rs":"a7d6dee5d064093521465e1da30bded851aa9d59f078942d88926d0f38de82fd","src/computepass.rs":"7c209dc60abc3cb45ed4b1648fd01faaeb561ef980d2b37c3d69a7e5fed9129d","src/constants.rs":"bbfeecf910d4f9ed149a7988d8a79df6e9ad479de81f7fc1294d3434a721b7fd","src/counters.rs":"d36d88f95015eef3655fc114eba1ef680d6a5bf74849389da2d09178244a01c4","src/depthstencil.rs":"71f221640a2031ef40449697297f09cd42d23833854c51759b3006ba55c84de9","src/device.rs":"20a30e95a7e32ee22df068bbdc0ee84790c76fa0fb3ab57f1641b8c5aedf98c6","src/drawable.rs":"2006151031fced10a8b347d9cf465ef15f62551f134d3ff1715e3f3831155f23","src/encoder.rs":"55030f58a4ababcd4c0b4c5b99884ac3bbeae6f16407fc258dce85656c71f276","src/heap.rs":"843536c73cb19643bf7d286433daebf703c28238775d5e006865247c50dabfbf","src/indirect_encoder.rs":"eee68af3cef45555864472622152fcb7a529341b27a98adec882324975fda3f1","src/lib.rs":"e5491ebe9c38e10a28ca5f3f5626bebd4c3901eb55400849c3a0921772f23afe","src/library.rs":"380ff5704b4068a1ff6415a64ff7559691340d059c3c6cd5a87270f00cba1598","src/mps.rs":"b5c5bceb8766a26c50782db80ac15b524890479bab4077685faa02af8d6265a3","src/pipeline/compute.rs":"01a0c8a9485b87a62183c22eaea85afc3345c81c30eb503d05fcf19b3a2c9baf","src/pipeline/mod.rs":"280916e71b6f3c5fffda6ffee31c616bf4aba6e5a186401ea2febe71c3264145","src/pipeline/render.rs":"611ac6d65348cd753ad897ed7a485328e5fd8c87d6f43f9c53868a58883706ed","src/renderpass.rs":"01d4bd8001b6b224f8d7ac5fe5cde45bc34712308e2c1ef05c2e1a4b50397c41","src/resource.rs":"910aa947ba979ad7ed5c5fdd3998b3a334637fe11ee45d3115c0f1363106be75","src/sampler.rs":"780b75b22ab1f6a6675d6e1bd04bd7457660c3325519bffb13a08b1abc64a79c","src/sync.rs":"d0db320dea7609992650062d341f506bf74b60efa761309730fc14bdb682539c","src/texture.rs":"334a7e6e32914ef72d40a7eba87ee90e5ed3dacc763da80b82e1076e0a77cbe2","src/types.rs":"d255f9c1b449acdb971616255e1c98d35b3b1ac54d9c388f7cdff6cfc3a8b944","src/vertexdescriptor.rs":"6a1378f270f7adf631319bcc8c8d6831c9f9be55e7b39a7ccfe151af9a9363c4"},"package":"c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"} \ No newline at end of file
+{"files":{"Cargo.lock":"64c3498f7a31ea043d974120cfaf294b3b6b32a6ba2fd6ddd72e3ee7983c8b57","Cargo.toml":"ac538c2ce2cfde5b76d9fba33bcb11765c11eb556e541c59e3261cee0d1ed17e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","Makefile":"99c4c592467981921d1257a4e9e841dce53624448738d0ed52a75431a406f7bc","README.md":"5cc24c3a06efb2be2280529bc0252b39c55bac347b3a558bc64047f9f421b9e2","assets/metal.svg":"3a295bd130785bc2fea2f3a91a4f6c7b4b3c40682c3fcb7a75f9887b66b06264","bors.toml":"c2733ec512a08bf76b6a1ed77270810a0edeb888ba24c2a75679e1eb1bd563a5","examples/argument-buffer/main.rs":"a087db6648a4b092520de29616521c704d892e0d3ace935d16f3f339415c4361","examples/bind/main.rs":"a0c85aad05f08666f9b380a7146a8473a6a6fe0db5d523760373093a0af20e5f","examples/bindless/main.rs":"0aaad9e42634c1ea204342a76c1bfe80c8fcf9d3ebe8247846cf63ecb08fb0d5","examples/caps/main.rs":"b7be00c1cc9042140d34ea05051152a7035f316f0bdcd31ac5a660a97e0c4f70","examples/circle/README.md":"e1c97cf5252f0d1f2934ace78b5d839c5f45911f3007dbd2925eeceefb8f0af6","examples/circle/main.rs":"22bd52ccba85debc1ccb3f277750e4759283d3c9b135b9a0da496c747e4cf637","examples/circle/screenshot.png":"97bf07c85bf02367447b9c8a81707c124e4a3b420fa386b95ba08b21938f4f2a","examples/circle/shaders.metal":"5e4f40efca5bb386204a09e1b983cc6c634fdf1ca9dd4974227313adbf50e8b5","examples/circle/shaders.metallib":"666a9491d795ef9c0b9c122c7ada571cc2c0e8774d2d89e5b4b996f3dc47962b","examples/compute/compute-argument-buffer.metal":"6530bbd6a0101d9db2893805436f5dc877959e81ea97a27014c0fc52fc9fa77b","examples/compute/compute-argument-buffer.rs":"e3de61fd7cc2f14d9d52300e4878601dbc072bc26d9dafc66115df58f94e0470","examples/compute/embedded-lib.rs":"55f701810fa5270c27ca771e713f9f8cf09e124a997b0b03790b38435593a7ea","examples/compute/main.rs":"bf160f3aba9f7492e3f4b6cf3198f8e454a49d6a29225312a84fdb9d784ffec4","examples/compute/shaders.metal":"f2b15551bb5247b88a3029c3d8ef37c6fa04a4a6cca9f90f069894ed6822b4bf","examples/compute/shaders.metallib":"fef91643e60c0ec99ad2bd2f3916299bcc3e6a80038ea27bed59681badfea7d1","examples/events/main.rs":"9cb35381b0a3918bd7d530171de8f7cceafe3d4851c0f430b4aff1f5c2aae749","examples/fence/main.rs":"47741327e62db1d8bd344b6a9ec26ef13ffb0b56b0dd7077c5d926d43faaeff7","examples/headless-render/README.md":"b1c97b52701cfb41fc0b9e269ba7a7a454d9161746198e2f5789f2636f60842d","examples/headless-render/main.rs":"2e6eb5db66f28833d1b53df3f134b4b53907a00036eeb6cdd9e428478e164aae","examples/headless-render/screenshot.png":"01d6ea5791b63b0f01190198756446cf313fc25dc64d0138c1b4f62c9f862dd1","examples/library/main.rs":"a1420ec28a471f28a789b75b3ecf5abb699ed352b337747169914812fb98045a","examples/mesh-shader/main.rs":"49899300f80f2d1e64366176313f69b597b69f3728a52a6a6f56ff7cd54c3c23","examples/mesh-shader/shaders.metal":"6ba934c3edd3ba0b8f6c4ac37be0fd0fe35eeef004e371521b7bf5a2fae9a223","examples/mesh-shader/shaders.metallib":"0af3b7ab0cd6186a90163550b76fab5bd2ef6ba97e791354d4281ca92d4887ff","examples/mps/main.rs":"2cbb532635270bc55cdfa3ee231cc2ee20dd8b3a5e6bf76062cca89ef1e3498f","examples/mps/shaders.metal":"155922d6a4184078ae7ee29504a268e1218f07d908f921eef60e5bfa8a793bda","examples/mps/shaders.metallib":"b62451223549b1e7eb90ec3d3534c0ed4cdfdc581c7df3ffcdc4786a5fcacde4","examples/raytracing/README.md":"6f0d683efac74572099c317ce9f65c3e6ff3c5252c6870c0c38c67f08b37bb01","examples/raytracing/camera.rs":"bed7a1787e1a52060dd0d64ff630a6fb769f15098d0a9d3ea68d4b57aee78b53","examples/raytracing/geometry.rs":"d3db29b4ab2d3d39de74718e0a7133a4e576dc26dcc6b6728c047865fb78952a","examples/raytracing/main.rs":"c3571854cbaaaeea386d7eb8af1fe9ea0492eae9af62b60203f4b6937dc4999a","examples/raytracing/renderer.rs":"d4e704b8f8e61919882aafc009b3a20928902d5b7edb9122d05f3e468d32f613","examples/raytracing/scene.rs":"fc2f214e0ad90e916fdbe2a339567a5dd323ef45b916fa8432c1156b4e94b998","examples/raytracing/screenshot.png":"400bb138f5adb69e4db8626681fb17667e5e112c94864879d9282d5348d970db","examples/raytracing/shaders.metal":"696f6a0ba79d82e2fa0e03eadbff2f6cdeac87acc805c2b7df657b85c1173174","examples/raytracing/shaders.metallib":"249b71998f58ddf8b3de37d79e9cc1f4a3494fba4bd7ba3f5411fb603de9dd5a","examples/reflection/main.rs":"563b49f5c057f1f8d17f3480cbc466e073ea575bfafaf84018a331a984d90a62","examples/shader-dylib/main.rs":"f18f4eb01420e12c196848c42657d41390cf10a3e47e8870025c20a1b29ddc71","examples/shader-dylib/test_dylib.metal":"3469de785c2c0da784e84758fc0da5a81e474ca15588485d9e04398690641cc8","examples/shader-dylib/test_shader.metal":"1a04ff8ab3288b09d14cd35440b2557e92ddedbff9d07c4144a22e9062e6e1e4","examples/window/README.md":"69655cff298e07887fe70e8a13e27d8a87efcd0cc0da4e15485134e064e1aceb","examples/window/main.rs":"09c508013223de859f33fb69410bde30e8d7f04952850504d8b1f8faf7049b1b","examples/window/screenshot.png":"da7369d7cc297c7f7f6bd773c93e7d708d72442c9c5ff5a20c2f2ee6852552dc","examples/window/shaders.metal":"90dee6c752add5c617dfdca93064b2824b44ff8c01ef63986826f6a1531e95d6","examples/window/shaders.metallib":"16fa82beb70bf16c3501970cae0d5028a747a08164337161dc9c2e8965d4c366","src/accelerator_structure.rs":"3b014b17a30e96d32d6fc69b6d067c08a9d4356cb10dc9121824117711211449","src/argument.rs":"347a5a01d4804044641e09d120d37bba140fc6a364782a96470b753e1ee74b30","src/blitpass.rs":"67b561b319e0650aa8438ce056998d4abd86b765a345f382013ab3cae7a2e71f","src/buffer.rs":"78d9021ab75ef0dad09ff92d126f1ceea241cca606cd7b05553c9351458babed","src/capturedescriptor.rs":"c687c4db298fb83ef640eb34929758c2d7955174a68725e986838e367291e302","src/capturemanager.rs":"c8a42854eebcfb6a7b777d931e368e04a5e35dff2e46c38c481d266dba9b792d","src/commandbuffer.rs":"464d504969ba1c213f6f8812b414c1581e39490cd048888404e04fbb5a1bd4ce","src/commandqueue.rs":"a7d6dee5d064093521465e1da30bded851aa9d59f078942d88926d0f38de82fd","src/computepass.rs":"7c209dc60abc3cb45ed4b1648fd01faaeb561ef980d2b37c3d69a7e5fed9129d","src/constants.rs":"bbfeecf910d4f9ed149a7988d8a79df6e9ad479de81f7fc1294d3434a721b7fd","src/counters.rs":"d36d88f95015eef3655fc114eba1ef680d6a5bf74849389da2d09178244a01c4","src/depthstencil.rs":"71f221640a2031ef40449697297f09cd42d23833854c51759b3006ba55c84de9","src/device.rs":"4fe4e0d3dd56a7f5bb0b80c016479f7844f779b5e255ecfec2f6b7995c804584","src/drawable.rs":"2006151031fced10a8b347d9cf465ef15f62551f134d3ff1715e3f3831155f23","src/encoder.rs":"55030f58a4ababcd4c0b4c5b99884ac3bbeae6f16407fc258dce85656c71f276","src/heap.rs":"843536c73cb19643bf7d286433daebf703c28238775d5e006865247c50dabfbf","src/indirect_encoder.rs":"eee68af3cef45555864472622152fcb7a529341b27a98adec882324975fda3f1","src/lib.rs":"54765ef6ca93d35aeed2022fd765b811b9f396292c024e44da28f1c1c5809309","src/library.rs":"a550201b0076d646134728c2fde0ed2257254f3d941e461f71fc258781dcc4df","src/mps.rs":"b02dd94d31f7252265ebca5d22a13307d8b61e418887047b3a22a04562f681cc","src/pipeline/compute.rs":"01a0c8a9485b87a62183c22eaea85afc3345c81c30eb503d05fcf19b3a2c9baf","src/pipeline/mod.rs":"280916e71b6f3c5fffda6ffee31c616bf4aba6e5a186401ea2febe71c3264145","src/pipeline/render.rs":"611ac6d65348cd753ad897ed7a485328e5fd8c87d6f43f9c53868a58883706ed","src/renderpass.rs":"01d4bd8001b6b224f8d7ac5fe5cde45bc34712308e2c1ef05c2e1a4b50397c41","src/resource.rs":"910aa947ba979ad7ed5c5fdd3998b3a334637fe11ee45d3115c0f1363106be75","src/sampler.rs":"780b75b22ab1f6a6675d6e1bd04bd7457660c3325519bffb13a08b1abc64a79c","src/sync.rs":"5d56ccbe4948683486bae1f0a3f0d4192b5b3e09c76457aecbd3a21569923639","src/texture.rs":"334a7e6e32914ef72d40a7eba87ee90e5ed3dacc763da80b82e1076e0a77cbe2","src/types.rs":"d255f9c1b449acdb971616255e1c98d35b3b1ac54d9c388f7cdff6cfc3a8b944","src/vertexdescriptor.rs":"6a1378f270f7adf631319bcc8c8d6831c9f9be55e7b39a7ccfe151af9a9363c4"},"package":"5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb"} \ No newline at end of file
diff --git a/third_party/rust/metal/Cargo.lock b/third_party/rust/metal/Cargo.lock
index d2717b65ee..75c1bf69e1 100644
--- a/third_party/rust/metal/Cargo.lock
+++ b/third_party/rust/metal/Cargo.lock
@@ -34,9 +34,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.4.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "block"
@@ -46,15 +46,15 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "bumpalo"
-version = "3.14.0"
+version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
-version = "1.14.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
+checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
[[package]]
name = "calloop"
@@ -103,7 +103,7 @@ dependencies = [
"core-foundation",
"core-graphics",
"foreign-types 0.3.2",
- "libc 0.2.149",
+ "libc 0.2.153",
"objc",
]
@@ -118,25 +118,25 @@ dependencies = [
"core-foundation",
"core-graphics-types",
"foreign-types 0.3.2",
- "libc 0.2.149",
+ "libc 0.2.153",
"objc",
]
[[package]]
name = "core-foundation"
-version = "0.9.3"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
- "libc 0.2.149",
+ "libc 0.2.153",
]
[[package]]
name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "core-graphics"
@@ -148,19 +148,18 @@ dependencies = [
"core-foundation",
"core-graphics-types",
"foreign-types 0.3.2",
- "libc 0.2.149",
+ "libc 0.2.153",
]
[[package]]
name = "core-graphics-types"
-version = "0.1.1"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
+checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
- "foreign-types 0.3.2",
- "libc 0.2.149",
+ "libc 0.2.153",
]
[[package]]
@@ -172,7 +171,7 @@ dependencies = [
"core-foundation",
"core-graphics",
"foreign-types 0.3.2",
- "libc 0.2.149",
+ "libc 0.2.153",
]
[[package]]
@@ -198,7 +197,7 @@ dependencies = [
"dwrote",
"foreign-types 0.5.0",
"freetype-rs",
- "libc 0.2.149",
+ "libc 0.2.153",
"log",
"objc",
"once_cell",
@@ -276,7 +275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b"
dependencies = [
"lazy_static",
- "libc 0.2.149",
+ "libc 0.2.153",
"serde",
"serde_derive",
"winapi",
@@ -301,18 +300,18 @@ dependencies = [
[[package]]
name = "fdeflate"
-version = "0.3.0"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
+checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
dependencies = [
"simd-adler32",
]
[[package]]
name = "flate2"
-version = "1.0.28"
+version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
+checksum = "4556222738635b7a3417ae6130d8f52201e45a0c4d1a907f0826383adb5f85e7"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -351,7 +350,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.38",
+ "syn 2.0.60",
]
[[package]]
@@ -374,7 +373,7 @@ checksum = "74eadec9d0a5c28c54bb9882e54787275152a4e36ce206b45d7451384e5bf5fb"
dependencies = [
"bitflags 1.3.2",
"freetype-sys",
- "libc 0.2.149",
+ "libc 0.2.153",
]
[[package]]
@@ -384,7 +383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a"
dependencies = [
"cmake",
- "libc 0.2.149",
+ "libc 0.2.153",
"pkg-config",
]
@@ -401,7 +400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
- "libc 0.2.149",
+ "libc 0.2.153",
"wasi 0.11.0+wasi-snapshot-preview1",
]
@@ -413,9 +412,9 @@ checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774"
[[package]]
name = "hashbrown"
-version = "0.14.2"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "ident_case"
@@ -425,9 +424,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
-version = "2.0.2"
+version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
+checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
"hashbrown",
@@ -453,9 +452,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
-version = "0.3.64"
+version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
@@ -474,9 +473,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
-version = "0.2.149"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libloading"
@@ -513,7 +512,7 @@ version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
- "libc 0.1.12",
+ "libc 0.2.153",
]
[[package]]
@@ -528,7 +527,7 @@ version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
dependencies = [
- "libc 0.2.149",
+ "libc 0.2.153",
]
[[package]]
@@ -542,9 +541,9 @@ dependencies = [
[[package]]
name = "metal"
-version = "0.27.0"
+version = "0.28.0"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.5.0",
"block",
"cocoa",
"core-graphics-types",
@@ -569,9 +568,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
"simd-adler32",
@@ -579,11 +578,11 @@ dependencies = [
[[package]]
name = "mio"
-version = "0.8.9"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
- "libc 0.2.149",
+ "libc 0.2.153",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.48.0",
@@ -615,7 +614,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f"
dependencies = [
- "libc 0.2.149",
+ "libc 0.2.153",
"log",
"ndk",
"ndk-context",
@@ -655,7 +654,7 @@ checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
dependencies = [
"bitflags 1.3.2",
"cfg-if",
- "libc 0.2.149",
+ "libc 0.2.153",
"memoffset",
]
@@ -668,7 +667,7 @@ dependencies = [
"autocfg",
"bitflags 1.3.2",
"cfg-if",
- "libc 0.2.149",
+ "libc 0.2.153",
"memoffset",
]
@@ -710,29 +709,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
"malloc_buf",
- "objc_exception",
-]
-
-[[package]]
-name = "objc_exception"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
-dependencies = [
- "cc",
]
[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "parking_lot"
-version = "0.12.1"
+version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -740,15 +729,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.9"
+version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
- "libc 0.2.149",
+ "libc 0.2.153",
"redox_syscall",
"smallvec",
- "windows-targets",
+ "windows-targets 0.52.5",
]
[[package]]
@@ -771,9 +760,9 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "png"
-version = "0.17.10"
+version = "0.17.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
+checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
dependencies = [
"bitflags 1.3.2",
"crc32fast",
@@ -800,18 +789,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.69"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.33"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
@@ -822,7 +811,7 @@ version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
dependencies = [
- "libc 0.2.149",
+ "libc 0.2.153",
"rand 0.4.6",
]
@@ -833,7 +822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
- "libc 0.2.149",
+ "libc 0.2.153",
"rand_core 0.3.1",
"rdrand",
"winapi",
@@ -845,7 +834,7 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
- "libc 0.2.149",
+ "libc 0.2.153",
"rand_chacha",
"rand_core 0.6.4",
]
@@ -910,11 +899,11 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.4.1"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.5.0",
]
[[package]]
@@ -969,13 +958,13 @@ checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
[[package]]
name = "serde_derive"
-version = "1.0.189"
+version = "1.0.199"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
+checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.38",
+ "syn 2.0.60",
]
[[package]]
@@ -984,7 +973,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c"
dependencies = [
- "libc 0.2.149",
+ "libc 0.2.153",
"servo-fontconfig-sys",
]
@@ -1007,9 +996,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "slotmap"
-version = "1.0.6"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342"
+checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
dependencies = [
"version_check",
]
@@ -1058,9 +1047,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.38"
+version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [
"proc-macro2",
"quote",
@@ -1093,7 +1082,7 @@ version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
- "libc 0.2.149",
+ "libc 0.2.153",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
@@ -1172,9 +1161,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -1182,24 +1171,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.38",
+ "syn 2.0.60",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1207,22 +1196,22 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.38",
+ "syn 2.0.60",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.87"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "wayland-client"
@@ -1232,7 +1221,7 @@ checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"
dependencies = [
"bitflags 1.3.2",
"downcast-rs",
- "libc 0.2.149",
+ "libc 0.2.153",
"nix 0.24.3",
"scoped-tls",
"wayland-commons",
@@ -1299,9 +1288,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.64"
+version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -1348,7 +1337,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -1357,22 +1346,44 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
- "windows_aarch64_gnullvm",
+ "windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm",
+ "windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
+]
+
+[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1385,6 +1396,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1397,6 +1414,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1409,6 +1438,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1421,12 +1456,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1439,6 +1486,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+
+[[package]]
name = "winit"
version = "0.27.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1450,7 +1503,7 @@ dependencies = [
"core-graphics",
"dispatch",
"instant",
- "libc 0.2.149",
+ "libc 0.2.153",
"log",
"mio",
"ndk",
@@ -1473,9 +1526,9 @@ dependencies = [
[[package]]
name = "winnow"
-version = "0.5.17"
+version = "0.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c"
+checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
dependencies = [
"memchr",
]
@@ -1496,7 +1549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59"
dependencies = [
"lazy_static",
- "libc 0.2.149",
+ "libc 0.2.153",
"pkg-config",
]
diff --git a/third_party/rust/metal/Cargo.toml b/third_party/rust/metal/Cargo.toml
index a81b535fd0..152460eb2d 100644
--- a/third_party/rust/metal/Cargo.toml
+++ b/third_party/rust/metal/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "metal"
-version = "0.27.0"
+version = "0.28.0"
authors = ["gfx-rs developers"]
exclude = [
"guide/**/*",
@@ -97,7 +97,7 @@ version = "2"
version = "0.1.6"
[dependencies.core-graphics-types]
-version = "0.1"
+version = "0.1.3"
[dependencies.dispatch]
version = "0.2"
@@ -111,7 +111,6 @@ version = "0.4"
[dependencies.objc]
version = "0.2.4"
-features = ["objc_exception"]
[dependencies.paste]
version = "1"
@@ -139,6 +138,6 @@ version = "0.27"
[features]
default = ["link"]
-link = []
+link = ["core-graphics-types/link"]
mps = []
private = []
diff --git a/third_party/rust/metal/README.md b/third_party/rust/metal/README.md
index ef94a72da8..1311edfbe1 100644
--- a/third_party/rust/metal/README.md
+++ b/third_party/rust/metal/README.md
@@ -8,13 +8,6 @@
<p align="center">Unsafe Rust bindings for the Metal 3D Graphics API.</p>
-## Documentation
-
-Note that [docs.rs](docs.rs) will fail to build the (albeit limited) documentation for this crate!
-They build in a Linux container, but of course this will only compile on MacOS.
-
-Please build the documentation yourself with `cargo docs`.
-
## Examples
The [examples](/examples) directory highlights different ways of using the Metal graphics API for rendering
diff --git a/third_party/rust/metal/src/device.rs b/third_party/rust/metal/src/device.rs
index 11b5575577..75061cc497 100644
--- a/third_party/rust/metal/src/device.rs
+++ b/third_party/rust/metal/src/device.rs
@@ -8,8 +8,7 @@
use super::*;
use block::{Block, ConcreteBlock};
-use foreign_types::ForeignType;
-use objc::runtime::{Object, NO, YES};
+use objc::runtime::{NO, YES};
use std::{ffi::CStr, os::raw::c_char, path::Path, ptr};
diff --git a/third_party/rust/metal/src/lib.rs b/third_party/rust/metal/src/lib.rs
index b79acf6e84..535c01da68 100644
--- a/third_party/rust/metal/src/lib.rs
+++ b/third_party/rust/metal/src/lib.rs
@@ -20,13 +20,7 @@ pub extern crate foreign_types;
#[macro_use]
pub extern crate paste;
-use std::{
- borrow::{Borrow, ToOwned},
- marker::PhantomData,
- mem,
- ops::Deref,
- os::raw::c_void,
-};
+use std::{borrow::Borrow, marker::PhantomData, mem, ops::Deref, os::raw::c_void};
use core_graphics_types::{base::CGFloat, geometry::CGSize};
use foreign_types::ForeignType;
diff --git a/third_party/rust/metal/src/library.rs b/third_party/rust/metal/src/library.rs
index 2c7d0c92ce..9f7d58cc7c 100644
--- a/third_party/rust/metal/src/library.rs
+++ b/third_party/rust/metal/src/library.rs
@@ -7,11 +7,10 @@
use super::*;
-use foreign_types::ForeignType;
-use objc::runtime::{Object, BOOL, NO, YES};
+use objc::runtime::{BOOL, NO, YES};
use std::ffi::CStr;
-use std::os::raw::{c_char, c_void};
+use std::os::raw::c_char;
use std::ptr;
/// Only available on (macos(10.12), ios(10.0)
@@ -361,6 +360,10 @@ pub enum MTLLanguageVersion {
V2_3 = 0x20003,
/// available on macOS 12.0+, iOS 15.0+
V2_4 = 0x20004,
+ /// available on macOS 13.0+, iOS 16.0+
+ V3_0 = 0x30000,
+ /// available on macOS 14.0+, iOS 17.0+
+ V3_1 = 0x30001,
}
/// See <https://developer.apple.com/documentation/metal/mtlfunctionconstantvalues/>
diff --git a/third_party/rust/metal/src/mps.rs b/third_party/rust/metal/src/mps.rs
index edd4936e8e..f4c9fc89a2 100644
--- a/third_party/rust/metal/src/mps.rs
+++ b/third_party/rust/metal/src/mps.rs
@@ -7,9 +7,12 @@
use super::*;
-use objc::runtime::{BOOL, YES};
+use objc::runtime::BOOL;
-#[cfg_attr(feature = "link", link(name = "MetalPerformanceShaders", kind = "framework"))]
+#[cfg_attr(
+ feature = "link",
+ link(name = "MetalPerformanceShaders", kind = "framework")
+)]
extern "C" {
fn MPSSupportsMTLDevice(device: *const std::ffi::c_void) -> BOOL;
}
diff --git a/third_party/rust/metal/src/sync.rs b/third_party/rust/metal/src/sync.rs
index 550e06be12..c36804813e 100644
--- a/third_party/rust/metal/src/sync.rs
+++ b/third_party/rust/metal/src/sync.rs
@@ -7,7 +7,7 @@
use super::*;
use block::{Block, RcBlock};
-use std::mem;
+use std::ptr;
#[cfg(feature = "dispatch_queue")]
use dispatch;
@@ -63,7 +63,7 @@ impl SharedEventRef {
*mut BlockBase<(&SharedEventRef, u64), ()>,
>(block);
(*block).flags |= BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE;
- (*block).extra = &BLOCK_EXTRA;
+ (*block).extra = ptr::addr_of!(BLOCK_EXTRA);
let () = msg_send![self, notifyListener:listener atValue:value block:block];
}
diff --git a/third_party/rust/minidump-common/.cargo-checksum.json b/third_party/rust/minidump-common/.cargo-checksum.json
index 1ddebcac04..84e8ed9037 100644
--- a/third_party/rust/minidump-common/.cargo-checksum.json
+++ b/third_party/rust/minidump-common/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"e0f49679fe070718b42d9e9bed49860a29471f6e2854a501dceba286301888b1","LICENSE":"06de63df29199a394442b57a28e886059ddc940973e10646877a0793fd53e2c9","README.md":"4c2a1448aab9177fd5f033faaf704af7bb222bf0804079fd3cff90fa1df4b812","src/errors/linux.rs":"df743ac9478e39f8a577f4f10f2d1317babad7b7c0d26cdbba2ea6b5426f4126","src/errors/macos.rs":"02ac6427f376e6f587c1f3e4d5df2a72e4cf13c4858409e73f26d47ad8e54340","src/errors/mod.rs":"f224af66124fd31a040c8da11bbab7b7795b48e4edea76e01c1f4dee537ea38a","src/errors/windows.rs":"0567af7bfac3ae2a8dff418e10873d8a5bf15a8b8ac6892c5ffdab08ec3ac901","src/format.rs":"f453ada36ffcb986a62391f9451b7826bdde9d5024beb11a495d1ed1e93bb52c","src/lib.rs":"0900c00594b3c386b86127055889006f0d7d0004b08455fadb0e60d55a469cab","src/traits.rs":"93127ad69a849325ed66a0626e0bdae05868488f81c539d35c71a7bfbb9e51ac","src/utils.rs":"17e8777b05998a8149fc5168af3bca1e0f9aeffe28cb3d6dbfb89c546f75e5ed"},"package":"3dbc11dfb55b3b7b5684fb16d98e0fc9d1e93a64d6b00bf383eabfc4541aaac2"} \ No newline at end of file
+{"files":{"Cargo.toml":"32470c1f1471a46161eb9fda47e6e7d50e2615bfb0722bcd9355fbb90174319e","LICENSE":"06de63df29199a394442b57a28e886059ddc940973e10646877a0793fd53e2c9","README.md":"4c2a1448aab9177fd5f033faaf704af7bb222bf0804079fd3cff90fa1df4b812","src/errors/linux.rs":"df743ac9478e39f8a577f4f10f2d1317babad7b7c0d26cdbba2ea6b5426f4126","src/errors/macos.rs":"4516aaeb7abf6209f5cd94e86a1e55a9675ef77262f52e3b2d5596fd4b858458","src/errors/mod.rs":"f224af66124fd31a040c8da11bbab7b7795b48e4edea76e01c1f4dee537ea38a","src/errors/windows.rs":"0567af7bfac3ae2a8dff418e10873d8a5bf15a8b8ac6892c5ffdab08ec3ac901","src/format.rs":"4d9baaa3b3b52b4311efaadb12921088141becba8890ae977f0a2807eaa7f820","src/lib.rs":"0900c00594b3c386b86127055889006f0d7d0004b08455fadb0e60d55a469cab","src/traits.rs":"93127ad69a849325ed66a0626e0bdae05868488f81c539d35c71a7bfbb9e51ac","src/utils.rs":"17e8777b05998a8149fc5168af3bca1e0f9aeffe28cb3d6dbfb89c546f75e5ed"},"package":"1bb6eaf88cc770fa58e6ae721cf2e40c2ca6a4c942ae8c7aa324d680bd3c6717"} \ No newline at end of file
diff --git a/third_party/rust/minidump-common/Cargo.toml b/third_party/rust/minidump-common/Cargo.toml
index 798d7a27d3..416d3b703e 100644
--- a/third_party/rust/minidump-common/Cargo.toml
+++ b/third_party/rust/minidump-common/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "minidump-common"
-version = "0.19.1"
+version = "0.21.1"
authors = ["Ted Mielczarek <ted@mielczarek.org>"]
description = "Some common types for working with minidump files."
homepage = "https://github.com/rust-minidump/rust-minidump"
@@ -42,7 +42,7 @@ version = "0.2"
version = "0.2"
[dependencies.scroll]
-version = "0.11.0"
+version = "0.12.0"
features = ["derive"]
[dependencies.smart-default]
diff --git a/third_party/rust/minidump-common/src/errors/macos.rs b/third_party/rust/minidump-common/src/errors/macos.rs
index d27c772e2a..667bb3919c 100644
--- a/third_party/rust/minidump-common/src/errors/macos.rs
+++ b/third_party/rust/minidump-common/src/errors/macos.rs
@@ -330,7 +330,7 @@ pub enum ExceptionCodeMacResourceThreadsFlavor {
///
/// See the [osfmk/kern/exc_guard.h][header] header in Apple's kernel sources
///
-/// [header]: https://github.com/apple/darwin-xnu/blob/main/osfmk/kern/exc_guard.h
+/// [header]: https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/kern/exc_guard.h
#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
pub enum ExceptionCodeMacGuardType {
GUARD_TYPE_NONE = 0,
@@ -339,18 +339,21 @@ pub enum ExceptionCodeMacGuardType {
GUARD_TYPE_USER = 3,
GUARD_TYPE_VN = 4,
GUARD_TYPE_VIRT_MEMORY = 5,
+ GUARD_TYPE_REJECTED_SC = 6,
}
/// Mac/iOS Mach port guard exception flavors
///
/// See the [osfmk/mach/port.h][header] header in Apple's kernel sources
///
-/// [header]: https://github.com/apple/darwin-xnu/blob/main/osfmk/mach/port.h
+/// [header]: https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/mach/port.h
#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
pub enum ExceptionCodeMacGuardMachPortFlavor {
- GUARD_EXC_DESTROY = 0x00000001,
- GUARD_EXC_MOD_REFS = 0x00000002,
- GUARD_EXC_SET_CONTEXT = 0x00000004,
+ GUARD_EXC_DESTROY = 1,
+ GUARD_EXC_MOD_REFS = 2,
+ GUARD_EXC_INVALID_OPTIONS = 3,
+ GUARD_EXC_SET_CONTEXT = 4,
+ GUARD_EXC_THREAD_SET_STATE = 5,
GUARD_EXC_UNGUARDED = 0x00000008,
GUARD_EXC_INCORRECT_GUARD = 0x00000010,
GUARD_EXC_IMMOVABLE = 0x00000020,
@@ -371,6 +374,8 @@ pub enum ExceptionCodeMacGuardMachPortFlavor {
GUARD_EXC_RCV_GUARDED_DESC = 0x00100000,
GUARD_EXC_MOD_REFS_NON_FATAL = 0x00200000,
GUARD_EXC_IMMOVABLE_NON_FATAL = 0x00400000,
+ GUARD_EXC_REQUIRE_REPLY_PORT_SEMANTICS = 0x00800000,
+ GUARD_EXC_EXCEPTION_BEHAVIOR_ENFORCE = 0x01000000,
}
/// Mac/iOS fd guard exception flavors
@@ -414,3 +419,13 @@ pub enum ExceptionCodeMacGuardVNFlavor {
pub enum ExceptionCodeMacGuardVirtMemoryFlavor {
GUARD_EXC_DEALLOC_GAP = 0x00000001,
}
+
+/// Mac/iOS rejected syscall guard exception flavors
+///
+/// See the [osfmk/kern/exc_guard.h][header] header in Apple's kernel sources
+///
+/// [header]: https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/osfmk/kern/exc_guard.h#L149-L163
+#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
+pub enum ExceptionCodeMacGuardRejecteSysCallFlavor {
+ GUARD_EXC_MACH_TRAP = 0x00000000,
+}
diff --git a/third_party/rust/minidump-common/src/format.rs b/third_party/rust/minidump-common/src/format.rs
index 2b610ef559..d6a8f629b5 100644
--- a/third_party/rust/minidump-common/src/format.rs
+++ b/third_party/rust/minidump-common/src/format.rs
@@ -2552,3 +2552,27 @@ pub struct MINIDUMP_HANDLE_DATA_STREAM {
/// Reserved for future use; must be zero.
pub reserved: u32,
}
+
+#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
+pub struct MINIDUMP_THREAD_INFO {
+ /// Thread identifier
+ pub thread_id: u32,
+ /// Thread state flags
+ pub dump_flags: u32,
+ /// HRESULT value of dump status
+ pub dump_error: u32,
+ /// The thread's exit code
+ pub exit_status: u32,
+ /// UTC time the thread was created
+ pub create_time: u64,
+ /// UTC time the thread exited
+ pub exit_time: u64,
+ /// Time executed in kernel mode
+ pub kernel_time: u64,
+ /// Time executed in user mode
+ pub user_time: u64,
+ /// Start address of the thread
+ pub start_address: u64,
+ /// Processor affinity mask
+ pub affinity: u64,
+}
diff --git a/third_party/rust/minidump-writer/.cargo-checksum.json b/third_party/rust/minidump-writer/.cargo-checksum.json
index 461af91038..1036c5f77f 100644
--- a/third_party/rust/minidump-writer/.cargo-checksum.json
+++ b/third_party/rust/minidump-writer/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"bd47a727b96e7175b86cb9384fa9a4174ef6172869ad535374c38825fd2c3b38","Cargo.lock":"9bf0a7576a9f71f2a06a1ebf886af125fcd11fb771cb6491804ad2e1c07bf408","Cargo.toml":"34acafdc4e13be804e847b771c2a9da6928d161bddab467f4d9a4085c79e9210","LICENSE":"1ecdd8e8977af83c07c5f97bec87b47d27059b7ea323ca3160fbfa2314f5d99c","README.md":"ba247891c565089e59211c414755ed4693b81371233fa3b398a501b545f6b962","build.rs":"689cd32a441f5011f694a9f86bc03bc27c2a09bcb4130f47e04fe00bb069b1b5","deny.toml":"d0eab3030d061ba5bf0b7b11ce3001cc2e5b49ea0add047602edd334fdceb5bc","examples/synthetic.rs":"cd13bd0bba64a1d8c8c326bb1ce1818bead6904e5708418fd09edeaef1437c24","release.toml":"f554067378aec602383b96e5fa63427136533a7dd00137fd0664b279fb8fcc56","src/bin/test.rs":"3b6b59e7205b2f51184d169b7902b52cf9c8a863bb27f91a45f4466e1f0d1359","src/dir_section.rs":"b7c83b16acefb4327b406612e1a667dffb91f86bec40f9330171dba8d10346ff","src/lib.rs":"6f393273ea6b354f412e70c9a4925fe2e646bc477591962c96a61aed9fde4e3b","src/linux.rs":"65d1249e80a3c3b6ab8c4361891b5ef35fe68f91253f6378ae03a0ad59ecd807","src/linux/android.rs":"9f2fd633de0d545b400c479a70f000cb9d04bb6e322f62098f4a7ebe7299f051","src/linux/app_memory.rs":"5f093e4ed0aecc6086366a9c09658761fdd3b0e6e9ff2111690719e56612df64","src/linux/auxv_reader.rs":"e9c75b0093c845da8dd321c6582e65678772c57658358213098aa6267f3679e1","src/linux/crash_context.rs":"069d949c7a9fc23a1e8710f7c018cacf71af2326a2dd6ca0283d492c5253107a","src/linux/crash_context/aarch64.rs":"158d02200b25a7ca029ff5132ba3b7f76a05c9976ff529a5658523aff370e4d2","src/linux/crash_context/arm.rs":"a4f41aae015937d3dccdf759df84bc657cf457d8baaf07711617d17f4b40f6f1","src/linux/crash_context/x86.rs":"d464680ee9df8a7f11dae2bb199cc4efb66dfc790a87c9b773c3a9b44b9339d8","src/linux/crash_context/x86_64.rs":"dceabbcf4d3c4ff5ad7658daa7dec3349cad9b61091385bcd868de6b11eb4957","src/linux/dso_debug.rs":"39beabf0598fe6bfaf0edd068bbe20442b45a7c0567588e978e8d9f5c331888b","src/linux/dumper_cpu_info.rs":"76558ffc85386e416bbfc49adc550f61fb206dfbfb0b6a25f620a5fc91f32bc1","src/linux/dumper_cpu_info/arm.rs":"6fc140181f3a32504c3b66f0235136e730424be830602c87cfbeb1dfb4c1cec3","src/linux/dumper_cpu_info/x86_mips.rs":"1b7f554190c2c0f0575e36995aae5211a0fc9f29f3949ac7521a9d148566f6e9","src/linux/errors.rs":"f0bc2a400a16d322f8d0dd5c76afa61fa32cf8a86f1b4e937298f767de031cb8","src/linux/maps_reader.rs":"0fde4c432f718e38d3ff35abcf00d3d3b478836fec2113ee11a8a1419921fe7b","src/linux/minidump_writer.rs":"b85eadb008c2f92d3d86c2c44c10bd139f793a0988d79aa51969848773bfb0fc","src/linux/ptrace_dumper.rs":"a2d6a06bb088caad1254746d842cb2c8d4fed918cfc318ec562aa160af3526d1","src/linux/sections.rs":"98aabd7e4b0542201783af90cafdc66bb3845585d0ed24af7476c1ea3ab40fb9","src/linux/sections/app_memory.rs":"52fdfe9622a395763fef94c5fea924935fcd86103c3eb1b0fb8d7ea61fd3e783","src/linux/sections/exception_stream.rs":"e1b73b5168506f8804479206ef0941aca5f792500cc56c5c17db55cd6b273a99","src/linux/sections/handle_data_stream.rs":"3aae030c009543142555d493f9273e3445454b18085dfdb3b44bc83d43b510dd","src/linux/sections/mappings.rs":"3b3bdf51e8e11f5b579d51b1a06244f1785cdfcdda3ee835472e5ab58756e71c","src/linux/sections/memory_info_list_stream.rs":"bd927824e859e2fcbc85ef9d5e3d8b7be13c4918a636f70f0712070d6c65b002","src/linux/sections/memory_list_stream.rs":"f2d5b33fb4167b502dc8e74371d50b4ad66e0b48f541fe16bcbf5fb62491bf2d","src/linux/sections/systeminfo_stream.rs":"02373c97d4caeb66f4601c066d430ad2929b5584eaa0af3be1dc51ef818e5cb8","src/linux/sections/thread_list_stream.rs":"9ea966c00a878ef1a6e6781005ddf9909c18177f2c455cb250c4ac191040fc69","src/linux/sections/thread_names_stream.rs":"2a123335626e941cf0a3349f9327c3e7606af593a8370ef5f71325012107b91f","src/linux/thread_info.rs":"b57a989a97418821a40c019d8edcb3143b43d3f76d7172d55a05001c9bfc210f","src/linux/thread_info/aarch64.rs":"fcbdd6b9185f00b4f42eef27076a8c9edab8afcaf22e1c005e32702be16e2264","src/linux/thread_info/arm.rs":"cf927d9f0ea48e07a874e8d6049e447c0f12a0715ed166448c3b07a410dd958a","src/linux/thread_info/mips.rs":"332d7888bb08a36d3b77023a4a0385193a07b1c6c5bf0e91aacb5d948ba8b903","src/linux/thread_info/x86.rs":"a759b2298f0831298c56e49717b4f188c213ebeb30b38be23af5bcbe6fd96369","src/mac.rs":"4671ad90c433db559ec633c880c3fe083f38a2e185ef4fc99577318526076519","src/mac/errors.rs":"696473d1187a0f003409e3ac0fc83a02cafbad8451a62bda868b08acc36e7443","src/mac/mach.rs":"1ae13287b6d76075473b0179b2a106bd2422c5234561770c0fedb5597c4128e9","src/mac/minidump_writer.rs":"d6f07685779c45f6b773d4163965f5dc5e0a73421937d9ec6b8e4d3320d23e85","src/mac/streams.rs":"82e1b9fefa26d98f1c0efdd98de0aed9a9ee9edf3e4b4f636212c73f8d3e464e","src/mac/streams/breakpad_info.rs":"9aafbc3f376050e39a2295e77a1b764223403ffdd47bded39efa9450a53b5a06","src/mac/streams/exception.rs":"316cf3b9ccb6b1bb3b431b4e927e4d68201f845d80e31fcaa6b80bcc30748147","src/mac/streams/memory_list.rs":"e507a1ada858ef535e3e211d91195901e9976ba0ff6cf601919d7cacb48c5e9f","src/mac/streams/misc_info.rs":"ed9fe394ded145cae62094adf3a9e454e23bfd5b6fab7871f0cf62c6a5e79017","src/mac/streams/module_list.rs":"0d735c07d162311d386aa40d5a80ebcbdc644df0dfc811d7c4b85a2fae51c5f9","src/mac/streams/system_info.rs":"4bd0d171c9d7c97afbacf6fd144d5554f0e46d47ae78f00b85331d6d1a1d24b3","src/mac/streams/thread_list.rs":"2b003e3409daebbd38ebc8a49a2c24e7a75b296d28f58a2c85114cf611174c1b","src/mac/streams/thread_names.rs":"2c8ca3a98b0c4ac9bd0373721324f32038569b70eb5b47bafe7de4cc3f76483b","src/mac/task_dumper.rs":"b22f42b11bb7e9af5976ec04cbf9f8bf4d1d70c3c7738b1072e7bd41e8d5af3c","src/mem_writer.rs":"44d594e4b8a4bedf28c61f89c34f13be42deb9a8820a1d3267dd9572d65d0c97","src/minidump_cpu.rs":"ccb3dc179699159883e539e29285f8f6ba936afb8ce8980dbcb5060a80b6618c","src/minidump_format.rs":"9d5940d71da3a543efa90279e287e0dbbe303de386a4d5aab15e8ccfdd556116","src/windows.rs":"7aae8747519b203f1889c369cb1122ff308d255e9514cf9d4d3f09257a3bb96c","src/windows/errors.rs":"9b8752122784417ed48b9c3fccc9bdabc6c4e6285cdb77c79723cba56cb0de82","src/windows/ffi.rs":"24a6f99de9f25ae7bc80f2763d8c5b97e65699682a99ec6265ebc435c3310999","src/windows/minidump_writer.rs":"1c89d43c31f59c9091e84155d7062bf85d4674c54899a4e92b4ba2bd5fcd1354","tests/common/mod.rs":"457d8c26f41d2c883c42ede5f7f2b604368581ef299f41a18b5d8c4ee7974c21","tests/linux_minidump_writer.rs":"128273f06bad3bcc316ea4cd3ba7ef1bc74f1fb349c5d38129fcfdf30ddc5037","tests/mac_minidump_writer.rs":"355e28635e9f8ccc831627e3323fe37907915047cd525f07eefd15d658cf4823","tests/ptrace_dumper.rs":"c4ec7f903cbe2181891951680efa9aaf21875b42184068436b3a17f412ece227","tests/task_dumper.rs":"3881899e4cfef0dae772d16b1a783497eebd2b58025394e0819cb03a0960d480","tests/windows_minidump_writer.rs":"138551179c4e610141d56ba99305a0fc05531c8e9924805dd071d380338f0f74"},"package":"017101620fe5d413ac2d98224ab8b1fff0d4bacaf2803c130ad4a6db3e5d3e70"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"dd79b025c48c70745cf60d41443191ad6ed92034efe8dd3db4b8c6cef031e4ab","Cargo.lock":"34813428631324758b699a604e0a077c56338cae5312b09f42949e8e341948fc","Cargo.toml":"84688c1ccef09106253992cb34a263e2eee168ad824fc52fe19e845d5169c169","LICENSE":"1ecdd8e8977af83c07c5f97bec87b47d27059b7ea323ca3160fbfa2314f5d99c","README.md":"71742b170ac34ceecf317d6d69456063bf5d8974453075e9cd2838785717fcdb","build.rs":"689cd32a441f5011f694a9f86bc03bc27c2a09bcb4130f47e04fe00bb069b1b5","deny.toml":"872e0c050720257cf85e660834ffe3d9e39f9fb7b3c795c0c44af3702ec2ff21","examples/synthetic.rs":"cd13bd0bba64a1d8c8c326bb1ce1818bead6904e5708418fd09edeaef1437c24","release.toml":"f554067378aec602383b96e5fa63427136533a7dd00137fd0664b279fb8fcc56","src/bin/test.rs":"dc408d74b7d142687b5d450c20ff0e9af7c508bd78af84988472e5dd4e940f29","src/dir_section.rs":"b7c83b16acefb4327b406612e1a667dffb91f86bec40f9330171dba8d10346ff","src/lib.rs":"6f393273ea6b354f412e70c9a4925fe2e646bc477591962c96a61aed9fde4e3b","src/linux.rs":"65d1249e80a3c3b6ab8c4361891b5ef35fe68f91253f6378ae03a0ad59ecd807","src/linux/android.rs":"9f2fd633de0d545b400c479a70f000cb9d04bb6e322f62098f4a7ebe7299f051","src/linux/app_memory.rs":"5f093e4ed0aecc6086366a9c09658761fdd3b0e6e9ff2111690719e56612df64","src/linux/auxv_reader.rs":"e9c75b0093c845da8dd321c6582e65678772c57658358213098aa6267f3679e1","src/linux/crash_context.rs":"069d949c7a9fc23a1e8710f7c018cacf71af2326a2dd6ca0283d492c5253107a","src/linux/crash_context/aarch64.rs":"158d02200b25a7ca029ff5132ba3b7f76a05c9976ff529a5658523aff370e4d2","src/linux/crash_context/arm.rs":"a4f41aae015937d3dccdf759df84bc657cf457d8baaf07711617d17f4b40f6f1","src/linux/crash_context/x86.rs":"d464680ee9df8a7f11dae2bb199cc4efb66dfc790a87c9b773c3a9b44b9339d8","src/linux/crash_context/x86_64.rs":"dceabbcf4d3c4ff5ad7658daa7dec3349cad9b61091385bcd868de6b11eb4957","src/linux/dso_debug.rs":"2f117049a71362797af88ce6f8aaa9d43ba4572a3fec46a1c5642c46f78a9abf","src/linux/dumper_cpu_info.rs":"76558ffc85386e416bbfc49adc550f61fb206dfbfb0b6a25f620a5fc91f32bc1","src/linux/dumper_cpu_info/arm.rs":"6fc140181f3a32504c3b66f0235136e730424be830602c87cfbeb1dfb4c1cec3","src/linux/dumper_cpu_info/x86_mips.rs":"1b7f554190c2c0f0575e36995aae5211a0fc9f29f3949ac7521a9d148566f6e9","src/linux/errors.rs":"f0bc2a400a16d322f8d0dd5c76afa61fa32cf8a86f1b4e937298f767de031cb8","src/linux/maps_reader.rs":"0831f0775336eb4123bdc92a734b8c4b1235c0d34a06fb09e363dcc83eda8b5c","src/linux/minidump_writer.rs":"048ffcebb95f899494bbeed84b79a2294375ce240f6293ad95fa5bba41187e95","src/linux/ptrace_dumper.rs":"c35a790e381d96b312bb3ffe864b4a55069da194fc4c6eeb1cf12a89d0a7ca9d","src/linux/sections.rs":"98aabd7e4b0542201783af90cafdc66bb3845585d0ed24af7476c1ea3ab40fb9","src/linux/sections/app_memory.rs":"52fdfe9622a395763fef94c5fea924935fcd86103c3eb1b0fb8d7ea61fd3e783","src/linux/sections/exception_stream.rs":"e1b73b5168506f8804479206ef0941aca5f792500cc56c5c17db55cd6b273a99","src/linux/sections/handle_data_stream.rs":"3aae030c009543142555d493f9273e3445454b18085dfdb3b44bc83d43b510dd","src/linux/sections/mappings.rs":"833f1783a4d9b761f1360ba438d6f7f032f831b8a1b15585dea1c90d7637f58a","src/linux/sections/memory_info_list_stream.rs":"bd927824e859e2fcbc85ef9d5e3d8b7be13c4918a636f70f0712070d6c65b002","src/linux/sections/memory_list_stream.rs":"f2d5b33fb4167b502dc8e74371d50b4ad66e0b48f541fe16bcbf5fb62491bf2d","src/linux/sections/systeminfo_stream.rs":"02373c97d4caeb66f4601c066d430ad2929b5584eaa0af3be1dc51ef818e5cb8","src/linux/sections/thread_list_stream.rs":"9ea966c00a878ef1a6e6781005ddf9909c18177f2c455cb250c4ac191040fc69","src/linux/sections/thread_names_stream.rs":"2a123335626e941cf0a3349f9327c3e7606af593a8370ef5f71325012107b91f","src/linux/thread_info.rs":"3588e6c9deedfd88bd024c30405172c05cea1bd37dcc64df687d6c218d2e4c5a","src/linux/thread_info/aarch64.rs":"fcbdd6b9185f00b4f42eef27076a8c9edab8afcaf22e1c005e32702be16e2264","src/linux/thread_info/arm.rs":"cf927d9f0ea48e07a874e8d6049e447c0f12a0715ed166448c3b07a410dd958a","src/linux/thread_info/mips.rs":"332d7888bb08a36d3b77023a4a0385193a07b1c6c5bf0e91aacb5d948ba8b903","src/linux/thread_info/x86.rs":"a759b2298f0831298c56e49717b4f188c213ebeb30b38be23af5bcbe6fd96369","src/mac.rs":"4671ad90c433db559ec633c880c3fe083f38a2e185ef4fc99577318526076519","src/mac/errors.rs":"696473d1187a0f003409e3ac0fc83a02cafbad8451a62bda868b08acc36e7443","src/mac/mach.rs":"f5f5b3bde9fd3ea85903b75c80ddb15931a56d5d4425f01fda9643fba8e419d3","src/mac/minidump_writer.rs":"d6f07685779c45f6b773d4163965f5dc5e0a73421937d9ec6b8e4d3320d23e85","src/mac/streams.rs":"82e1b9fefa26d98f1c0efdd98de0aed9a9ee9edf3e4b4f636212c73f8d3e464e","src/mac/streams/breakpad_info.rs":"9aafbc3f376050e39a2295e77a1b764223403ffdd47bded39efa9450a53b5a06","src/mac/streams/exception.rs":"6ad730ff0fbba4ec8a7c8576effb737138ca92e0f676eeff5d8e3c47d20a1434","src/mac/streams/memory_list.rs":"e507a1ada858ef535e3e211d91195901e9976ba0ff6cf601919d7cacb48c5e9f","src/mac/streams/misc_info.rs":"ed9fe394ded145cae62094adf3a9e454e23bfd5b6fab7871f0cf62c6a5e79017","src/mac/streams/module_list.rs":"959239425c1ea4c9766303fd10a12c82d1fed27b462f836a8a317a470ea0ace7","src/mac/streams/system_info.rs":"4bd0d171c9d7c97afbacf6fd144d5554f0e46d47ae78f00b85331d6d1a1d24b3","src/mac/streams/thread_list.rs":"2b003e3409daebbd38ebc8a49a2c24e7a75b296d28f58a2c85114cf611174c1b","src/mac/streams/thread_names.rs":"cc1464c2610e6022046b5322d9b48a72a6b5d35923d75afd7aa4b82d355c7dc4","src/mac/task_dumper.rs":"b22f42b11bb7e9af5976ec04cbf9f8bf4d1d70c3c7738b1072e7bd41e8d5af3c","src/mem_writer.rs":"44d594e4b8a4bedf28c61f89c34f13be42deb9a8820a1d3267dd9572d65d0c97","src/minidump_cpu.rs":"ccb3dc179699159883e539e29285f8f6ba936afb8ce8980dbcb5060a80b6618c","src/minidump_format.rs":"9d5940d71da3a543efa90279e287e0dbbe303de386a4d5aab15e8ccfdd556116","src/windows.rs":"7aae8747519b203f1889c369cb1122ff308d255e9514cf9d4d3f09257a3bb96c","src/windows/errors.rs":"9b8752122784417ed48b9c3fccc9bdabc6c4e6285cdb77c79723cba56cb0de82","src/windows/ffi.rs":"24a6f99de9f25ae7bc80f2763d8c5b97e65699682a99ec6265ebc435c3310999","src/windows/minidump_writer.rs":"fbbb576161f753d9572c5e8c78a85066070948917e0ee2c111e63f3fc14fd5d3","tests/common/mod.rs":"7f340f28206924af467b09f190393ff81be8f542af1b5f9d8847b2bc409bf828","tests/linux_minidump_writer.rs":"bc81920c3dc48b0026bce0a1da3994c541a712c3e36ea2cf1037887843876511","tests/mac_minidump_writer.rs":"355e28635e9f8ccc831627e3323fe37907915047cd525f07eefd15d658cf4823","tests/ptrace_dumper.rs":"5596925274589697153657a010dd77866f94852ac8db487c86b5a9ca0f5395ea","tests/task_dumper.rs":"3881899e4cfef0dae772d16b1a783497eebd2b58025394e0819cb03a0960d480","tests/windows_minidump_writer.rs":"138551179c4e610141d56ba99305a0fc05531c8e9924805dd071d380338f0f74"},"package":"e2abcd9c8a1e6e1e9d56ce3627851f39a17ea83e17c96bc510f29d7e43d78a7d"} \ No newline at end of file
diff --git a/third_party/rust/minidump-writer/CHANGELOG.md b/third_party/rust/minidump-writer/CHANGELOG.md
index 770d621be3..96c4584d78 100644
--- a/third_party/rust/minidump-writer/CHANGELOG.md
+++ b/third_party/rust/minidump-writer/CHANGELOG.md
@@ -8,6 +8,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- next-header -->
## [Unreleased] - ReleaseDate
+## [0.8.9] - 2024-04-01
+### Fixed
+- [PR#110](https://github.com/rust-minidump/minidump-writer/pull/110) changed it so that `SIGCONT` is sent regardless if the process was not able to be `SIGSTOP`ed quickly enough.
+- [PR#113](https://github.com/rust-minidump/minidump-writer/pull/113) fixed a segfault(!) on linux if it was compiled with rustc 1.77.0 in release mode.
+
+## [0.8.8] - 2024-03-21
+### Fixed
+- [PR#108](https://github.com/rust-minidump/minidump-writer/pull/108) resolved [#28](https://github.com/rust-minidump/minidump-writer/issues/28) by sending a `SIGSTOP` to the process that is about to be dumped to (hopefully) increase the robustness of the dumping process by reducing the chance of errors, particularly with regard to threads. This is done as a best effort, and will perform the old behavior if the process has not stopped within a timeout (by default 100ms), which can be overriden by the user.
+
+## [0.8.7] - 2024-03-04
+### Changed
+- [PR#106](https://github.com/rust-minidump/minidump-writer/pull/106) bumped `minidump-common`, `minidump`, `minidump-processor`, and `minidump-unwind` -> 0.21.
+
+## [0.8.6] - 2024-02-26
+### Changed
+- [PR#104](https://github.com/rust-minidump/minidump-writer/pull/104) slightly tweaked .so version parsing in the case of more "exotic" versions such as `libdbus-1.so.3.34.2rc5`. Previously this was parsed as `3.34.25` but would cause ambiguity if there was ever an _actual_ .25 patch/age in the future. Now, the last version is parsed as 1-2 numbers, ignoring non-digit characters if the last component has them. If 2 numbers are parsed, the last number is now placed in [VS_FIXEDFILEINFO::product_version_lo](https://docs.rs/minidump-common/latest/minidump_common/format/struct.VS_FIXEDFILEINFO.html#structfield.product_version_lo) so that it is distinct from the patch/age component placed in [VS_FIXEDFILEINFO::product_version_hi](https://docs.rs/minidump-common/latest/minidump_common/format/struct.VS_FIXEDFILEINFO.html#structfield.product_version_hi).
+
+## [0.8.5] - 2024-02-23
+### Added
+- [PR#103](https://github.com/rust-minidump/minidump-writer/pull/103) added `.so` file versions as additional metadata to minidumps, resolving [this Mozilla bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1847098). There is no true standard for .so file versions, so this is a best effort to pull what version information we can from the .so filename. The version components are `major.minor.release` similarly to semver, where `major` -> [VS_FIXEDFILEINFO::file_version_hi](https://docs.rs/minidump-common/latest/minidump_common/format/struct.VS_FIXEDFILEINFO.html#structfield.file_version_hi), `major` -> [VS_FIXEDFILEINFO::file_version_lo](https://docs.rs/minidump-common/latest/minidump_common/format/struct.VS_FIXEDFILEINFO.html#structfield.file_version_lo), and `release` -> [VS_FIXEDFILEINFO::product_version_hi](https://docs.rs/minidump-common/latest/minidump_common/format/struct.VS_FIXEDFILEINFO.html#structfield.product_version_hi)
+ - `libmozsandbox.so` -> `0.0.0`
+ - `libstdc++.so.6.0.32` -> `6.0.32`
+ - `libcairo-gobject.so.2.11800.0` -> `2.11800.0`
+ - `libm.so.6` -> `6.0.0`
+ - `libabsl_time_zone.so.20220623.0.0` -> `20220623.0.0`
+ - `libdbus-1.so.3.34.2rc5` -> `3.34.25`
+
+## [0.8.4] - 2024-02-15
+### Changed
+- [PR#97](https://github.com/rust-minidump/minidump-writer/pull/97) bumped `goblin` -> 0.8.
+- [PR#99](https://github.com/rust-minidump/minidump-writer/pull/99) bumped `minidump-common` -> 0.20, `scroll` -> 0.12, `memmap2` -> 0.9.
+
## [0.8.3] - 2023-11-07
### Added
- [PR#94](https://github.com/rust-minidump/minidump-writer/pull/94) added support for writing [file information](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_handle_descriptor) for every file open in the process the dump is being performed for into the [`MINIDUMP_HANDLE_DATA_STREAM`](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_handle_data_stream) stream.
@@ -103,7 +135,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Initial release, including basic support for `x86_64-unknown-linux-gnu/musl` and `x86_64-pc-windows-msvc`
<!-- next-url -->
-[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.8.3...HEAD
+[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.8.9...HEAD
+[0.8.9]: https://github.com/rust-minidump/minidump-writer/compare/0.8.8...0.8.9
+[0.8.8]: https://github.com/rust-minidump/minidump-writer/compare/0.8.7...0.8.8
+[0.8.7]: https://github.com/rust-minidump/minidump-writer/compare/0.8.6...0.8.7
+[0.8.6]: https://github.com/rust-minidump/minidump-writer/compare/0.8.5...0.8.6
+[0.8.5]: https://github.com/rust-minidump/minidump-writer/compare/0.8.4...0.8.5
+[0.8.4]: https://github.com/rust-minidump/minidump-writer/compare/0.8.3...0.8.4
[0.8.3]: https://github.com/rust-minidump/minidump-writer/compare/0.8.2...0.8.3
[0.8.2]: https://github.com/rust-minidump/minidump-writer/compare/0.8.1...0.8.2
[0.8.1]: https://github.com/rust-minidump/minidump-writer/compare/0.8.0...0.8.1
diff --git a/third_party/rust/minidump-writer/Cargo.lock b/third_party/rust/minidump-writer/Cargo.lock
index 514186142d..0b6c79825c 100644
--- a/third_party/rust/minidump-writer/Cargo.lock
+++ b/third_party/rust/minidump-writer/Cargo.lock
@@ -3,6 +3,16 @@
version = 3
[[package]]
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "fallible-iterator 0.3.0",
+ "gimli",
+]
+
+[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -10,9 +20,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd"
+checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
dependencies = [
"getrandom",
"once_cell",
@@ -21,18 +31,33 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.0.2"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
+name = "alloc-no-stdlib"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
+
+[[package]]
+name = "alloc-stdlib"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
+dependencies = [
+ "alloc-no-stdlib",
+]
+
+[[package]]
name = "anyhow"
-version = "1.0.71"
+version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
[[package]]
name = "arrayvec"
@@ -41,14 +66,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
+name = "async-compression"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c"
+dependencies = [
+ "brotli",
+ "flate2",
+ "futures-core",
+ "memchr",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
name = "async-trait"
-version = "0.1.68"
+version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.52",
]
[[package]]
@@ -58,6 +97,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
+name = "backtrace"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "base64"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
+[[package]]
name = "binary-merge"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -71,21 +131,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.4.0"
+version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
-
-[[package]]
-name = "bitvec"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
-dependencies = [
- "funty",
- "radium",
- "tap",
- "wyz",
-]
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "block-buffer"
@@ -98,9 +146,9 @@ dependencies = [
[[package]]
name = "breakpad-symbols"
-version = "0.19.1"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b002797414ffc34425bdf5b21a9e50d102013292625749eeba0a59923176ab05"
+checksum = "14722511e9c032b38689b0e952a633826850873adb10de56ec775b217a519366"
dependencies = [
"async-trait",
"cachemap2",
@@ -115,6 +163,27 @@ dependencies = [
]
[[package]]
+name = "brotli"
+version = "3.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+ "brotli-decompressor",
+]
+
+[[package]]
+name = "brotli-decompressor"
+version = "2.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+]
+
+[[package]]
name = "brownstone"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -131,14 +200,26 @@ checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
- "regex-automata",
+ "regex-automata 0.1.10",
]
[[package]]
+name = "bumpalo"
+version = "3.15.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
+
+[[package]]
name = "byteorder"
-version = "1.4.3"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "bytes"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cab"
@@ -148,21 +229,33 @@ checksum = "ae6b4de23c7d39c0631fd3cc952d87951c86c75a13812d7247cb7a896e7b3551"
dependencies = [
"byteorder",
"flate2",
- "lzxd",
+ "lzxd 0.1.4",
+ "time",
+]
+
+[[package]]
+name = "cab"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e8636d870cf15918e416b7904f0db1cbd06de0ffe392986c3b16662552df00c"
+dependencies = [
+ "byteorder",
+ "flate2",
+ "lzxd 0.2.5",
"time",
]
[[package]]
name = "cachemap2"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7bba2f68a9fefca870fed897de7c655f9d5c1eaf1cd9517db96c9a3861f648b"
+checksum = "68ccbd3153aa153b2f5eff557537ffce81e4dd6c50ae0eddc41dc8d0c388436f"
[[package]]
name = "cc"
-version = "1.0.79"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
[[package]]
name = "cfg-if"
@@ -171,6 +264,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
+[[package]]
name = "circular"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -178,30 +277,46 @@ checksum = "b0fc239e0f6cb375d2402d48afb92f76f5404fd1df208a41930ec81eda078bea"
[[package]]
name = "console"
-version = "0.15.7"
+version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
+checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
- "windows-sys 0.45.0",
+ "windows-sys 0.52.0",
]
[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
name = "cpp_demangle"
-version = "0.4.1"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c76f98bdfc7f66172e6c7065f981ebb576ffc903fe4c0561d9f0c2509226dc6"
+checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119"
dependencies = [
"cfg-if",
]
[[package]]
name = "cpufeatures"
-version = "0.2.8"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
@@ -228,26 +343,25 @@ dependencies = [
[[package]]
name = "crc-catalog"
-version = "2.2.0"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484"
+checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
[[package]]
name = "crc32fast"
-version = "1.3.2"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam"
-version = "0.8.2"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
+checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
dependencies = [
- "cfg-if",
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
@@ -257,56 +371,46 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
-version = "0.5.8"
+version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
dependencies = [
- "cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
- "cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
-version = "0.9.15"
+version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
- "autocfg",
- "cfg-if",
"crossbeam-utils",
- "memoffset",
- "scopeguard",
]
[[package]]
name = "crossbeam-queue"
-version = "0.3.8"
+version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
+checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
dependencies = [
- "cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.16"
+version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
-dependencies = [
- "cfg-if",
-]
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "crypto-common"
@@ -319,6 +423,12 @@ dependencies = [
]
[[package]]
+name = "current_platform"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a74858bcfe44b22016cb49337d7b6f04618c58e5dbfdef61b06b8c434324a0bc"
+
+[[package]]
name = "debugid"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -329,6 +439,26 @@ dependencies = [
]
[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -344,7 +474,16 @@ version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
- "dirs-sys",
+ "dirs-sys 0.3.7",
+]
+
+[[package]]
+name = "dirs"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
+dependencies = [
+ "dirs-sys 0.4.1",
]
[[package]]
@@ -359,6 +498,18 @@ dependencies = [
]
[[package]]
+name = "dirs-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
+dependencies = [
+ "libc",
+ "option-ext",
+ "redox_users",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "dmsort"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -366,17 +517,17 @@ checksum = "f0bc8fbe9441c17c9f46f75dfe27fa1ddb6c68a461ccaed0481419219d4f10d3"
[[package]]
name = "dump_syms"
-version = "2.2.1"
+version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0640a83419dce0966981ccf5f41359cf858ce786314e55af12bff22e782585d5"
+checksum = "f33fc75a82f02047c9f4cebd1c6f0e12872aea9c217d841a5b57dd42fdf82990"
dependencies = [
"anyhow",
- "bitflags 1.3.2",
- "cab",
+ "bitflags 2.4.2",
+ "cab 0.4.1",
"crossbeam",
- "dirs",
- "goblin 0.6.1",
- "hashbrown",
+ "dirs 4.0.0",
+ "goblin 0.7.1",
+ "hashbrown 0.12.3",
"log",
"lzma-rs",
"num_cpus",
@@ -401,9 +552,9 @@ dependencies = [
[[package]]
name = "elsa"
-version = "1.8.1"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e0aca8dce8856e420195bd13b6a64de3334235ccc9214e824b86b12bf26283"
+checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10"
dependencies = [
"stable_deref_trait",
]
@@ -416,32 +567,27 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "encoding_rs"
-version = "0.8.32"
+version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
+checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if",
]
[[package]]
-name = "errno"
-version = "0.3.1"
+name = "equivalent"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
-dependencies = [
- "errno-dragonfly",
- "libc",
- "windows-sys 0.48.0",
-]
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
+name = "errno"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
- "cc",
"libc",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -451,41 +597,74 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
+name = "fallible-iterator"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+
+[[package]]
name = "fastrand"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "flate2"
-version = "1.0.26"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
name = "form_urlencoded"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
-name = "funty"
-version = "2.0.0"
+name = "framehop"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+checksum = "38bb3ea0d42943711eafa7a6182b47a21d51247d2ecad6641ff61d9213d099ea"
+dependencies = [
+ "arrayvec",
+ "fallible-iterator 0.3.0",
+ "gimli",
+ "macho-unwind-info",
+ "object",
+ "pe-unwind-info",
+ "thiserror",
+]
+
+[[package]]
+name = "fs4"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29f9df8a11882c4e3335eb2d18a0137c505d9ca927470b0cac9c6f0ae07d28f7"
+dependencies = [
+ "async-trait",
+ "rustix",
+ "tokio",
+ "windows-sys 0.48.0",
+]
[[package]]
name = "futures"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
@@ -498,9 +677,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
@@ -508,15 +687,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
@@ -525,38 +704,38 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.52",
]
[[package]]
name = "futures-sink"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
@@ -582,9 +761,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.10"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
@@ -593,34 +772,54 @@ dependencies = [
[[package]]
name = "gimli"
-version = "0.27.3"
+version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
dependencies = [
- "fallible-iterator",
+ "fallible-iterator 0.3.0",
+ "indexmap",
"stable_deref_trait",
]
[[package]]
name = "goblin"
-version = "0.6.1"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68"
+checksum = "f27c1b4369c2cd341b5de549380158b105a04c331be5db9110eef7b6d2742134"
dependencies = [
"log",
"plain",
- "scroll",
+ "scroll 0.11.0",
]
[[package]]
name = "goblin"
-version = "0.7.1"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f27c1b4369c2cd341b5de549380158b105a04c331be5db9110eef7b6d2742134"
+checksum = "bb07a4ffed2093b118a525b1d8f5204ae274faed5604537caf7135d0f18d9887"
dependencies = [
"log",
"plain",
- "scroll",
+ "scroll 0.12.0",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
]
[[package]]
@@ -634,13 +833,16 @@ dependencies = [
]
[[package]]
+name = "hashbrown"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+
+[[package]]
name = "hermit-abi"
-version = "0.2.6"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
-dependencies = [
- "libc",
-]
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hex"
@@ -649,10 +851,82 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "0.14.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-rustls"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
+dependencies = [
+ "futures-util",
+ "http",
+ "hyper",
+ "rustls",
+ "tokio",
+ "tokio-rustls",
+]
+
+[[package]]
name = "idna"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@@ -666,12 +940,12 @@ checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3"
[[package]]
name = "indexmap"
-version = "1.9.3"
+version = "2.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
dependencies = [
- "autocfg",
- "hashbrown",
+ "equivalent",
+ "hashbrown 0.14.3",
]
[[package]]
@@ -684,10 +958,16 @@ dependencies = [
]
[[package]]
+name = "ipnet"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
+
+[[package]]
name = "itoa"
-version = "1.0.6"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "joinery"
@@ -696,6 +976,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5"
[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -709,21 +998,63 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
-version = "0.2.148"
+version = "0.2.153"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "libredox"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
+dependencies = [
+ "bitflags 2.4.2",
+ "libc",
+ "redox_syscall",
+]
+
+[[package]]
+name = "linear-map"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
+checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee"
+
+[[package]]
+name = "linux-perf-data"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51e5edc4ed86c4995d6fe86ed4153727d27b4f8be7167d14b05d74e41c16b087"
+dependencies = [
+ "byteorder",
+ "linear-map",
+ "linux-perf-event-reader",
+ "memchr",
+ "thiserror",
+]
+
+[[package]]
+name = "linux-perf-event-reader"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e93938b52460a3e539c9465592c5f645c7ca3847da1d7dbee20e3564d55c5a90"
+dependencies = [
+ "bitflags 1.3.2",
+ "byteorder",
+ "memchr",
+ "thiserror",
+]
[[package]]
name = "linux-raw-sys"
-version = "0.4.7"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_api"
-version = "0.4.10"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
@@ -731,9 +1062,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.19"
+version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "lzma-rs"
@@ -752,15 +1083,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784462f20dddd9dfdb45de963fa4ad4a288cb10a7889ac5d2c34fb6481c6b213"
[[package]]
+name = "lzxd"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de7336a183103429ad66d11d56d8bdc9c4a2916f6b85a8f11e5b127bde12001"
+
+[[package]]
name = "mach2"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
+checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
dependencies = [
"libc",
]
[[package]]
+name = "macho-unwind-info"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b6086acc74bc23f56b60e88bb082d505e23849d68d6c0f12bb6a7ad5c60e03e"
+dependencies = [
+ "thiserror",
+ "zerocopy",
+ "zerocopy-derive",
+]
+
+[[package]]
name = "maybe-owned"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -768,24 +1116,15 @@ checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4"
[[package]]
name = "memchr"
-version = "2.5.0"
+version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-
-[[package]]
-name = "memmap2"
-version = "0.5.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
-dependencies = [
- "libc",
-]
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "memmap2"
-version = "0.8.0"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
+checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
dependencies = [
"libc",
]
@@ -800,18 +1139,25 @@ dependencies = [
]
[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
name = "minidump"
-version = "0.19.1"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c671544a05d0e8daa3018c8fb6687c11935c4ae8f122de8f2386c2896b4e9b8"
+checksum = "64cb8353fdcd59c0caaf7525cb83b29ee02e6eac4c85d5a7944a9773d0f33f2e"
dependencies = [
"debugid",
"encoding_rs",
- "memmap2 0.8.0",
+ "memmap2",
"minidump-common",
"num-traits",
+ "procfs-core",
"range-map",
- "scroll",
+ "scroll 0.12.0",
"thiserror",
"time",
"tracing",
@@ -820,34 +1166,33 @@ dependencies = [
[[package]]
name = "minidump-common"
-version = "0.19.1"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dbc11dfb55b3b7b5684fb16d98e0fc9d1e93a64d6b00bf383eabfc4541aaac2"
+checksum = "1bb6eaf88cc770fa58e6ae721cf2e40c2ca6a4c942ae8c7aa324d680bd3c6717"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.2",
"debugid",
"num-derive",
"num-traits",
"range-map",
- "scroll",
+ "scroll 0.12.0",
"smart-default",
]
[[package]]
name = "minidump-processor"
-version = "0.19.1"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76b49bde7c0ae9a7142c540c27c7fc29db2288fd9614f11a9ce57badeb74af43"
+checksum = "62bc8e39bb830c2e92ff0f3af8166f3fbc3ad2dc0c843c66de3b918b71190a6c"
dependencies = [
"async-trait",
"breakpad-symbols",
"debugid",
"futures-util",
- "memmap2 0.8.0",
"minidump",
"minidump-common",
"minidump-unwind",
- "scroll",
+ "scroll 0.12.0",
"serde",
"serde_json",
"thiserror",
@@ -856,39 +1201,40 @@ dependencies = [
[[package]]
name = "minidump-unwind"
-version = "0.19.1"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63aef4cd2e018881680b152296ae28e674242823faa1767b417b6669a1896cdc"
+checksum = "2096876dbb3d5a0bbc5c42a913d44e935cb7f6139dcf9eda043ae1ce702ab529"
dependencies = [
"async-trait",
"breakpad-symbols",
"cachemap2",
+ "framehop",
"futures-util",
- "memmap2 0.8.0",
+ "memmap2",
"minidump",
"minidump-common",
- "scroll",
- "symbolic-cfi",
- "symbolic-common",
- "symbolic-debuginfo",
- "symbolic-demangle",
+ "object",
+ "scroll 0.12.0",
"tracing",
+ "wholesym",
]
[[package]]
name = "minidump-writer"
-version = "0.8.3"
+version = "0.8.9"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.2",
"byteorder",
"cfg-if",
"crash-context",
+ "current_platform",
"dump_syms",
"futures",
- "goblin 0.7.1",
+ "goblin 0.8.0",
"libc",
+ "log",
"mach2",
- "memmap2 0.8.0",
+ "memmap2",
"memoffset",
"minidump",
"minidump-common",
@@ -896,7 +1242,7 @@ dependencies = [
"minidump-unwind",
"nix",
"procfs-core",
- "scroll",
+ "scroll 0.12.0",
"similar-asserts",
"tempfile",
"thiserror",
@@ -911,14 +1257,25 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]]
+name = "mio"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "msvc-demangler"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -928,6 +1285,15 @@ dependencies = [
]
[[package]]
+name = "msvc-demangler"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2588c982e3a7fbfbd73b21f824cacc43fc6392a1103c709ffd6001c0bf33fdb3"
+dependencies = [
+ "bitflags 2.4.2",
+]
+
+[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -935,12 +1301,13 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nix"
-version = "0.27.1"
+version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
+checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.2",
"cfg-if",
+ "cfg_aliases",
"libc",
]
@@ -968,40 +1335,63 @@ dependencies = [
]
[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
name = "num-derive"
-version = "0.4.0"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e"
+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.52",
]
[[package]]
name = "num-traits"
-version = "0.2.15"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
-version = "1.15.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
+name = "object"
+version = "0.32.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+dependencies = [
+ "flate2",
+ "memchr",
+ "ruzstd",
+]
+
+[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "option-ext"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "parking_lot"
@@ -1015,15 +1405,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.8"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.3.5",
+ "redox_syscall",
"smallvec",
- "windows-targets 0.48.0",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -1032,8 +1422,8 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82040a392923abe6279c00ab4aff62d5250d1c8555dc780e4b02783a7aa74863"
dependencies = [
- "fallible-iterator",
- "scroll",
+ "fallible-iterator 0.2.0",
+ "scroll 0.11.0",
"uuid",
]
@@ -1047,15 +1437,53 @@ dependencies = [
"elsa",
"maybe-owned",
"pdb",
- "range-collections",
+ "range-collections 0.2.4",
+ "thiserror",
+]
+
+[[package]]
+name = "pdb-addr2line"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb51ef7ed9998e108891711812822831daac0b17d67768c3bdc69aa909366123"
+dependencies = [
+ "bitflags 2.4.2",
+ "elsa",
+ "maybe-owned",
+ "pdb2",
+ "range-collections 0.4.5",
"thiserror",
]
[[package]]
+name = "pdb2"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00e30e131bcab0d41a2e471cf777ea9b1402f2a0764bcf1780251eab1b0d175d"
+dependencies = [
+ "fallible-iterator 0.2.0",
+ "scroll 0.11.0",
+ "uuid",
+]
+
+[[package]]
+name = "pe-unwind-info"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ec3b43050c38ffb9de87e17d874e9956e3a9131b343c9b7b7002597727c3891"
+dependencies = [
+ "arrayvec",
+ "bitflags 2.4.2",
+ "thiserror",
+ "zerocopy",
+ "zerocopy-derive",
+]
+
+[[package]]
name = "percent-encoding"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf_shared"
@@ -1068,9 +1496,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
-version = "0.2.9"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
@@ -1085,6 +1513,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1092,9 +1526,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "proc-macro2"
-version = "1.0.60"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -1105,33 +1539,39 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.2",
"hex",
]
[[package]]
name = "quote"
-version = "1.0.28"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
-name = "radium"
-version = "0.7.0"
+name = "range-collections"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+checksum = "61fdfd79629e2b44a1d34b4d227957174cb858e6b86ee45fad114edbcfc903ab"
+dependencies = [
+ "binary-merge",
+ "inplace-vec-builder",
+ "smallvec",
+]
[[package]]
name = "range-collections"
-version = "0.2.4"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61fdfd79629e2b44a1d34b4d227957174cb858e6b86ee45fad114edbcfc903ab"
+checksum = "ca9edd21e2db51000ac63eccddabba622f826e631a60be7bade9bd6a76b69537"
dependencies = [
"binary-merge",
"inplace-vec-builder",
+ "ref-cast",
"smallvec",
]
@@ -1145,42 +1585,60 @@ dependencies = [
]
[[package]]
-name = "redox_syscall"
-version = "0.2.16"
+name = "rangemap"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
-dependencies = [
- "bitflags 1.3.2",
-]
+checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
[[package]]
name = "redox_syscall"
-version = "0.3.5"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
-version = "0.4.3"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
dependencies = [
"getrandom",
- "redox_syscall 0.2.16",
+ "libredox",
"thiserror",
]
[[package]]
+name = "ref-cast"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f"
+dependencies = [
+ "ref-cast-impl",
+]
+
+[[package]]
+name = "ref-cast-impl"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
+
+[[package]]
name = "regex"
-version = "1.8.4"
+version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
+ "regex-automata 0.4.6",
"regex-syntax",
]
@@ -1191,10 +1649,80 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
+name = "regex-automata"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
name = "regex-syntax"
-version = "0.7.2"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+
+[[package]]
+name = "reqwest"
+version = "0.11.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
+checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
+dependencies = [
+ "async-compression",
+ "base64",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-rustls",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls",
+ "rustls-pemfile",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "system-configuration",
+ "tokio",
+ "tokio-rustls",
+ "tokio-util",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-streams",
+ "web-sys",
+ "webpki-roots",
+ "winreg",
+]
+
+[[package]]
+name = "ring"
+version = "0.17.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
+dependencies = [
+ "cc",
+ "cfg-if",
+ "getrandom",
+ "libc",
+ "spin",
+ "untrusted",
+ "windows-sys 0.52.0",
+]
[[package]]
name = "rustc-demangle"
@@ -1204,28 +1732,102 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
-version = "0.38.14"
+version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"
+checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.2",
"errno",
"libc",
"linux-raw-sys",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rustls"
+version = "0.21.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
+dependencies = [
+ "log",
+ "ring",
+ "rustls-webpki",
+ "sct",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
+dependencies = [
+ "base64",
+]
+
+[[package]]
+name = "rustls-webpki"
+version = "0.101.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "ruzstd"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
+dependencies = [
+ "byteorder",
+ "derive_more",
+ "twox-hash",
]
[[package]]
name = "ryu"
-version = "1.0.13"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+
+[[package]]
+name = "samply-symbols"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b02bfab817ed66f35a0afa07216a02325b82faf777e20fdcd0dadd5ebfd8eb"
+dependencies = [
+ "addr2line",
+ "bitflags 2.4.2",
+ "cpp_demangle",
+ "debugid",
+ "elsa",
+ "flate2",
+ "gimli",
+ "linux-perf-data",
+ "lzma-rs",
+ "macho-unwind-info",
+ "memchr",
+ "msvc-demangler 0.10.0",
+ "nom",
+ "object",
+ "pdb-addr2line 0.11.0",
+ "rangemap",
+ "rustc-demangle",
+ "srcsrv",
+ "thiserror",
+ "uuid",
+ "yoke",
+ "yoke-derive",
+ "zerocopy",
+ "zerocopy-derive",
+]
[[package]]
name = "scopeguard"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "scroll"
@@ -1233,46 +1835,94 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
dependencies = [
- "scroll_derive",
+ "scroll_derive 0.11.1",
+]
+
+[[package]]
+name = "scroll"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6"
+dependencies = [
+ "scroll_derive 0.12.0",
]
[[package]]
name = "scroll_derive"
-version = "0.11.0"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e"
+checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.52",
]
[[package]]
+name = "scroll_derive"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
+
+[[package]]
+name = "sct"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
+
+[[package]]
name = "serde"
-version = "1.0.164"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.164"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.52",
]
[[package]]
name = "serde_json"
-version = "1.0.97"
+version = "1.0.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
+ "form_urlencoded",
"itoa",
"ryu",
"serde",
@@ -1280,9 +1930,9 @@ dependencies = [
[[package]]
name = "sha2"
-version = "0.10.7"
+version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -1291,9 +1941,9 @@ dependencies = [
[[package]]
name = "similar"
-version = "2.2.1"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf"
+checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21"
dependencies = [
"bstr",
"unicode-segmentation",
@@ -1311,24 +1961,24 @@ dependencies = [
[[package]]
name = "siphasher"
-version = "0.3.10"
+version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "slab"
-version = "0.4.8"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
-version = "1.10.0"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]]
name = "smart-default"
@@ -1338,7 +1988,33 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.52",
+]
+
+[[package]]
+name = "socket2"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+
+[[package]]
+name = "srcsrv"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "022437a70e522e49b1952cb1d923589d629cb4aee97eb56d65ce938c04e8ac70"
+dependencies = [
+ "memchr",
+ "thiserror",
]
[[package]]
@@ -1348,6 +2024,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
name = "string_cache"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1363,9 +2045,9 @@ dependencies = [
[[package]]
name = "symbolic"
-version = "12.1.5"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d311bfa722c01294e838091c455ed4e63c96ea7b8fb65b7fd7acdc72a4b0309"
+checksum = "05ec4f53c56d7ee8809c2322925d362e193bcc7bbe7e777a3304b34ea7e85a36"
dependencies = [
"symbolic-cfi",
"symbolic-common",
@@ -1375,9 +2057,9 @@ dependencies = [
[[package]]
name = "symbolic-cfi"
-version = "12.1.5"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d568f889388e2d96b4b3c258a9e36ebe4ad95bd941ee245719c30cbc2c1ad51"
+checksum = "0a3724d1d1a3e531038da32de84725fd93d0afeeee51de4d3871cf657f283ad9"
dependencies = [
"symbolic-common",
"symbolic-debuginfo",
@@ -1386,39 +2068,38 @@ dependencies = [
[[package]]
name = "symbolic-common"
-version = "12.1.5"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eb6682826c7186b16c5c0ed2a68f419609f8af62f070c688871caae4911432d"
+checksum = "1cccfffbc6bb3bb2d3a26cd2077f4d055f6808d266f9d4d158797a4c60510dfe"
dependencies = [
"debugid",
- "memmap2 0.5.10",
+ "memmap2",
"stable_deref_trait",
"uuid",
]
[[package]]
name = "symbolic-debuginfo"
-version = "12.1.5"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "222363f4ca5fb00cdd4915afba4a6aa18549d3438b27c048db2c41f0ea7a1e58"
+checksum = "eb52777be67777947c5a159f1b6e8bfe4473d91fad7e5d4aff85ee4d3963cc04"
dependencies = [
- "bitvec",
"debugid",
"dmsort",
"elementtree",
"elsa",
- "fallible-iterator",
+ "fallible-iterator 0.3.0",
"flate2",
"gimli",
- "goblin 0.6.1",
+ "goblin 0.7.1",
"lazy_static",
"nom",
"nom-supreme",
"once_cell",
"parking_lot",
- "pdb-addr2line",
+ "pdb-addr2line 0.10.4",
"regex",
- "scroll",
+ "scroll 0.11.0",
"serde",
"serde_json",
"smallvec",
@@ -1431,25 +2112,26 @@ dependencies = [
[[package]]
name = "symbolic-demangle"
-version = "12.1.5"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7597986728aebeae5b865266b6158b134a4d61f078049552b5c897bb0a61985"
+checksum = "76a99812da4020a67e76c4eb41f08c87364c14170495ff780f30dd519c221a68"
dependencies = [
"cc",
"cpp_demangle",
- "msvc-demangler",
+ "msvc-demangler 0.9.0",
"rustc-demangle",
"symbolic-common",
]
[[package]]
name = "symbolic-ppdb"
-version = "12.1.5"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e3c9b6cc654de90c05d841af02f3dd37415278538fa23534cbcb58a1a74ae8b"
+checksum = "dace84623ccc926886fc880c36e2a81af4b17f8276abc4d77dc947ca3c6c8f8c"
dependencies = [
"flate2",
"indexmap",
+ "serde",
"serde_json",
"symbolic-common",
"thiserror",
@@ -1458,6 +2140,21 @@ dependencies = [
]
[[package]]
+name = "symsrv"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b6a9f40855a5ba9f9008b2c12eef13a67d2655459ba9f74970aea341e0fb5e9"
+dependencies = [
+ "cab 0.5.0",
+ "dirs 5.0.1",
+ "fs4",
+ "futures-util",
+ "reqwest",
+ "thiserror",
+ "tokio",
+]
+
+[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1470,9 +2167,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.18"
+version = "2.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
+checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
dependencies = [
"proc-macro2",
"quote",
@@ -1480,51 +2177,85 @@ dependencies = [
]
[[package]]
-name = "tap"
-version = "1.0.1"
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
+[[package]]
+name = "synstructure"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
+
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
[[package]]
name = "tempfile"
-version = "3.8.0"
+version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if",
"fastrand",
- "redox_syscall 0.3.5",
"rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
name = "thiserror"
-version = "1.0.40"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.40"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.52",
]
[[package]]
name = "time"
-version = "0.3.22"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
+checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
dependencies = [
+ "deranged",
"itoa",
+ "num-conv",
+ "powerfmt",
"serde",
"time-core",
"time-macros",
@@ -1532,16 +2263,17 @@ dependencies = [
[[package]]
name = "time-core"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
-version = "0.2.9"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
+checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
dependencies = [
+ "num-conv",
"time-core",
]
@@ -1561,12 +2293,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
+name = "tokio"
+version = "1.36.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tokio-rustls"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
+dependencies = [
+ "rustls",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
name = "tracing"
-version = "0.1.37"
+version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
- "cfg-if",
"log",
"pin-project-lite",
"tracing-attributes",
@@ -1575,62 +2351,84 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.24"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.52",
]
[[package]]
name = "tracing-core"
-version = "0.1.31"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "twox-hash"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
+dependencies = [
+ "cfg-if",
+ "static_assertions",
+]
+
+[[package]]
name = "typenum"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-bidi"
-version = "0.3.13"
+version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
-version = "1.0.9"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
-version = "1.10.1"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+
+[[package]]
+name = "untrusted"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
-version = "2.4.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
@@ -1639,9 +2437,9 @@ dependencies = [
[[package]]
name = "uuid"
-version = "1.4.1"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
+checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
[[package]]
name = "version_check"
@@ -1650,19 +2448,107 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
+[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
+name = "wasm-streams"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
+dependencies = [
+ "futures-util",
+ "js-sys",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
+[[package]]
name = "wasmparser"
-version = "0.102.0"
+version = "0.118.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48134de3d7598219ab9eaf6b91b15d8e50d31da76b8519fe4ecfcec2cf35104b"
+checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c"
dependencies = [
"indexmap",
- "url",
+ "semver",
]
[[package]]
@@ -1676,6 +2562,44 @@ dependencies = [
]
[[package]]
+name = "web-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.25.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
+
+[[package]]
+name = "wholesym"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9050809aead9c09ea73d2719d7639b55ea2803287b008dc1bb24b647661afa7c"
+dependencies = [
+ "bytes",
+ "core-foundation",
+ "core-foundation-sys",
+ "debugid",
+ "futures-util",
+ "libc",
+ "memmap2",
+ "reqwest",
+ "samply-symbols",
+ "symsrv",
+ "tokio",
+ "uuid",
+ "yoke",
+ "yoke-derive",
+]
+
+[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1699,146 +2623,197 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
-version = "0.45.0"
+version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets 0.42.2",
+ "windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets 0.48.0",
+ "windows-targets 0.52.4",
]
[[package]]
name = "windows-targets"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm 0.52.4",
+ "windows_aarch64_msvc 0.52.4",
+ "windows_i686_gnu 0.52.4",
+ "windows_i686_msvc 0.52.4",
+ "windows_x86_64_gnu 0.52.4",
+ "windows_x86_64_gnullvm 0.52.4",
+ "windows_x86_64_msvc 0.52.4",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.42.2"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.48.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
-name = "wyz"
-version = "0.5.1"
+name = "winreg"
+version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
- "tap",
+ "cfg-if",
+ "windows-sys 0.48.0",
]
[[package]]
+name = "yoke"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65e71b2e4f287f467794c671e2b8f8a5f3716b3c829079a1c44740148eff07e4"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+ "synstructure",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7"
+
+[[package]]
name = "zip"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/third_party/rust/minidump-writer/Cargo.toml b/third_party/rust/minidump-writer/Cargo.toml
index 6b33b5eebf..d137677165 100644
--- a/third_party/rust/minidump-writer/Cargo.toml
+++ b/third_party/rust/minidump-writer/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "minidump-writer"
-version = "0.8.3"
+version = "0.8.9"
authors = ["Martin Sirringhaus"]
description = "Rust rewrite of Breakpad's minidump_writer"
homepage = "https://github.com/rust-minidump/minidump-writer"
@@ -32,14 +32,17 @@ version = "1.0"
[dependencies.crash-context]
version = "0.6"
+[dependencies.log]
+version = "0.4"
+
[dependencies.memoffset]
version = "0.9"
[dependencies.minidump-common]
-version = "0.19.1"
+version = "0.21"
[dependencies.scroll]
-version = "0.11"
+version = "0.12"
[dependencies.tempfile]
version = "3.8"
@@ -47,22 +50,26 @@ version = "3.8"
[dependencies.thiserror]
version = "1.0"
+[dev-dependencies.current_platform]
+version = "0.2"
+
[dev-dependencies.futures]
version = "0.3"
features = ["executor"]
[dev-dependencies.memmap2]
-version = "0.8"
+version = "0.9"
[dev-dependencies.minidump]
-version = "0.19"
+version = "0.21"
[target."cfg(any(target_os = \"linux\", target_os = \"android\"))".dependencies.nix]
-version = "0.27"
+version = "0.28"
features = [
"mman",
"process",
"ptrace",
+ "signal",
"user",
]
default-features = false
@@ -79,11 +86,11 @@ version = "2.2"
default-features = false
[target."cfg(target_os = \"macos\")".dev-dependencies.minidump-processor]
-version = "0.19"
+version = "0.21"
default-features = false
[target."cfg(target_os = \"macos\")".dev-dependencies.minidump-unwind]
-version = "0.19"
+version = "0.21"
features = ["debuginfo"]
[target."cfg(target_os = \"macos\")".dev-dependencies.similar-asserts]
@@ -96,10 +103,10 @@ version = "1.4"
version = "2.4"
[target."cfg(unix)".dependencies.goblin]
-version = "0.7.1"
+version = "0.8"
[target."cfg(unix)".dependencies.libc]
version = "0.2"
[target."cfg(unix)".dependencies.memmap2]
-version = "0.8"
+version = "0.9"
diff --git a/third_party/rust/minidump-writer/README.md b/third_party/rust/minidump-writer/README.md
index 20962c913f..9c9ed9d789 100644
--- a/third_party/rust/minidump-writer/README.md
+++ b/third_party/rust/minidump-writer/README.md
@@ -22,31 +22,7 @@ For more information on how to dump an external process you can check out the do
#### Local process
-```rust
-fn write_minidump() {
- // At a minimum, the crashdump writer needs to know the process and thread that you want to dump
- let mut writer = minidump_writer::minidump_writer::MinidumpWriter::new(
- std::process::id() as _,
- // This gets the current thread, but you could get the id for any thread
- // in the current process
- unsafe { libc::syscall(libc::SYS_gettid) } as i32
- );
-
- // If provided with a full [crash_context::CrashContext](https://docs.rs/crash-context/latest/crash_context/struct.CrashContext.html),
- // the crash will contain more info on the crash cause, such as the signal
- //writer.set_crash_context(minidump_writer::crash_context::CrashContext { inner: crash_context });
-
- // Here we could add more context or modify how the minidump is written, eg
- // Add application specific memory blocks to the minidump
- //writer.set_app_memory()
- // Sanitize stack memory before it is written to the minidump by replacing
- // non-pointer values with a sentinel value
- //writer.sanitize_stack();
-
- let mut minidump_file = std::fs::File::create("example_dump.mdmp").expect("failed to create file");
- writer.dump(&mut minidump_file).expect("failed to write minidump");
-}
-```
+The Linux implementation uses ptrace to gather information about the process when writing a minidump for it, which cannot be done from the process itself. It's possible to clone the process and dump the current process from that clone, but that's out of scope for an example.
#### External process
diff --git a/third_party/rust/minidump-writer/deny.toml b/third_party/rust/minidump-writer/deny.toml
index 3cadd53b23..ed28113432 100644
--- a/third_party/rust/minidump-writer/deny.toml
+++ b/third_party/rust/minidump-writer/deny.toml
@@ -13,10 +13,10 @@ ignore = []
[bans]
multiple-versions = "deny"
-skip = [
- # scroll still depends on 1.0
- { name = "syn", version = "=1.0.109" },
+deny = [
+ #{ crate = "chrono", use-instead = "time", reason = "unneccessary dependency" },
]
+skip-tree = []
[licenses]
allow = ["MIT", "Apache-2.0"]
diff --git a/third_party/rust/minidump-writer/src/bin/test.rs b/third_party/rust/minidump-writer/src/bin/test.rs
index 85b6fa6a93..df39b28655 100644
--- a/third_party/rust/minidump-writer/src/bin/test.rs
+++ b/third_party/rust/minidump-writer/src/bin/test.rs
@@ -8,14 +8,14 @@ pub type Result<T> = std::result::Result<T, Error>;
mod linux {
use super::*;
use minidump_writer::{
+ minidump_writer::STOP_TIMEOUT,
ptrace_dumper::{PtraceDumper, AT_SYSINFO_EHDR},
LINUX_GATE_LIBRARY_NAME,
};
use nix::{
- sys::mman::{mmap, MapFlags, ProtFlags},
+ sys::mman::{mmap_anonymous, MapFlags, ProtFlags},
unistd::getppid,
};
- use std::os::fd::BorrowedFd;
macro_rules! test {
($x:expr, $errmsg:expr) => {
@@ -29,13 +29,13 @@ mod linux {
fn test_setup() -> Result<()> {
let ppid = getppid();
- PtraceDumper::new(ppid.as_raw())?;
+ PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT)?;
Ok(())
}
fn test_thread_list() -> Result<()> {
let ppid = getppid();
- let dumper = PtraceDumper::new(ppid.as_raw())?;
+ let dumper = PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT)?;
test!(!dumper.threads.is_empty(), "No threads")?;
test!(
dumper
@@ -51,7 +51,7 @@ mod linux {
fn test_copy_from_process(stack_var: usize, heap_var: usize) -> Result<()> {
let ppid = getppid().as_raw();
- let mut dumper = PtraceDumper::new(ppid)?;
+ let mut dumper = PtraceDumper::new(ppid, STOP_TIMEOUT)?;
dumper.suspend_threads()?;
let stack_res = PtraceDumper::copy_from_process(ppid, stack_var as *mut libc::c_void, 1)?;
@@ -73,7 +73,7 @@ mod linux {
fn test_find_mappings(addr1: usize, addr2: usize) -> Result<()> {
let ppid = getppid();
- let dumper = PtraceDumper::new(ppid.as_raw())?;
+ let dumper = PtraceDumper::new(ppid.as_raw(), STOP_TIMEOUT)?;
dumper
.find_mapping(addr1)
.ok_or("No mapping for addr1 found")?;
@@ -90,7 +90,7 @@ mod linux {
let ppid = getppid().as_raw();
let exe_link = format!("/proc/{}/exe", ppid);
let exe_name = std::fs::read_link(exe_link)?.into_os_string();
- let mut dumper = PtraceDumper::new(getppid().as_raw())?;
+ let mut dumper = PtraceDumper::new(getppid().as_raw(), STOP_TIMEOUT)?;
let mut found_exe = None;
for (idx, mapping) in dumper.mappings.iter().enumerate() {
if mapping.name.as_ref().map(|x| x.into()).as_ref() == Some(&exe_name) {
@@ -107,7 +107,7 @@ mod linux {
fn test_merged_mappings(path: String, mapped_mem: usize, mem_size: usize) -> Result<()> {
// Now check that PtraceDumper interpreted the mappings properly.
- let dumper = PtraceDumper::new(getppid().as_raw())?;
+ let dumper = PtraceDumper::new(getppid().as_raw(), STOP_TIMEOUT)?;
let mut mapping_count = 0;
for map in &dumper.mappings {
if map
@@ -129,7 +129,7 @@ mod linux {
fn test_linux_gate_mapping_id() -> Result<()> {
let ppid = getppid().as_raw();
- let mut dumper = PtraceDumper::new(ppid)?;
+ let mut dumper = PtraceDumper::new(ppid, STOP_TIMEOUT)?;
let mut found_linux_gate = false;
for mut mapping in dumper.mappings.clone() {
if mapping.name == Some(LINUX_GATE_LIBRARY_NAME.into()) {
@@ -148,7 +148,7 @@ mod linux {
fn test_mappings_include_linux_gate() -> Result<()> {
let ppid = getppid().as_raw();
- let dumper = PtraceDumper::new(ppid)?;
+ let dumper = PtraceDumper::new(ppid, STOP_TIMEOUT)?;
let linux_gate_loc = dumper.auxv[&AT_SYSINFO_EHDR];
test!(linux_gate_loc != 0, "linux_gate_loc == 0")?;
let mut found_linux_gate = false;
@@ -215,18 +215,16 @@ mod linux {
let memory_size = std::num::NonZeroUsize::new(page_size.unwrap() as usize).unwrap();
// Get some memory to be mapped by the child-process
let mapped_mem = unsafe {
- mmap::<BorrowedFd>(
+ mmap_anonymous(
None,
memory_size,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_PRIVATE | MapFlags::MAP_ANON,
- None,
- 0,
)
.unwrap()
};
- println!("{} {}", mapped_mem as usize, memory_size);
+ println!("{} {}", mapped_mem.as_ptr() as usize, memory_size);
loop {
std::thread::park();
}
diff --git a/third_party/rust/minidump-writer/src/linux/dso_debug.rs b/third_party/rust/minidump-writer/src/linux/dso_debug.rs
index b9f466261f..01c0a73505 100644
--- a/third_party/rust/minidump-writer/src/linux/dso_debug.rs
+++ b/third_party/rust/minidump-writer/src/linux/dso_debug.rs
@@ -161,11 +161,6 @@ pub fn write_dso_debug_stream(
assert!(head.is_empty(), "Data was not aligned");
let dyn_struct = &body[0];
- // #ifdef __mips__
- // const int32_t debug_tag = DT_MIPS_RLD_MAP;
- // #else
- // const int32_t debug_tag = DT_DEBUG;
- // #endif
let debug_tag = goblin::elf::dynamic::DT_DEBUG;
if dyn_struct.d_tag == debug_tag {
r_debug = dyn_struct.d_val as usize;
diff --git a/third_party/rust/minidump-writer/src/linux/maps_reader.rs b/third_party/rust/minidump-writer/src/linux/maps_reader.rs
index 4d0d3b5aaa..b5b7fb23e6 100644
--- a/third_party/rust/minidump-writer/src/linux/maps_reader.rs
+++ b/third_party/rust/minidump-writer/src/linux/maps_reader.rs
@@ -289,10 +289,9 @@ impl MappingInfo {
true
}
- fn elf_file_so_name(&self) -> Result<String> {
- // Find the shared object name (SONAME) by examining the ELF information
- // for |mapping|. If the SONAME is found copy it into the passed buffer
- // |soname| and return true. The size of the buffer is |soname_size|.
+ /// Find the shared object name (SONAME) by examining the ELF information
+ /// for the mapping.
+ fn so_name(&self) -> Result<String> {
let mapped_file = MappingInfo::get_mmap(&self.name, self.offset)?;
let elf_obj = elf::Elf::parse(&mapped_file)?;
@@ -303,7 +302,14 @@ impl MappingInfo {
Ok(soname.to_string())
}
- pub fn get_mapping_effective_path_and_name(&self) -> Result<(PathBuf, String)> {
+ #[inline]
+ fn so_version(&self) -> Option<SoVersion> {
+ SoVersion::parse(self.name.as_deref()?)
+ }
+
+ pub fn get_mapping_effective_path_name_and_version(
+ &self,
+ ) -> Result<(PathBuf, String, Option<SoVersion>)> {
let mut file_path = PathBuf::from(self.name.clone().unwrap_or_default());
// Tools such as minidump_stackwalk use the name of the module to look up
@@ -312,16 +318,15 @@ impl MappingInfo {
// filesystem name of the module.
// Just use the filesystem name if no SONAME is present.
- let file_name = if let Ok(name) = self.elf_file_so_name() {
- name
- } else {
+ let Ok(file_name) = self.so_name() else {
// file_path := /path/to/libname.so
// file_name := libname.so
let file_name = file_path
.file_name()
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default();
- return Ok((file_path, file_name));
+
+ return Ok((file_path, file_name, self.so_version()));
};
if self.is_executable() && self.offset != 0 {
@@ -337,7 +342,7 @@ impl MappingInfo {
file_path.set_file_name(&file_name);
}
- Ok((file_path, file_name))
+ Ok((file_path, file_name, self.so_version()))
}
pub fn is_contained_in(&self, user_mapping_list: &MappingList) -> bool {
@@ -382,6 +387,97 @@ impl MappingInfo {
}
}
+/// Version metadata retrieved from an .so filename
+///
+/// There is no standard for .so version numbers so this implementation just
+/// does a best effort to pull as much data as it can based on real .so schemes
+/// seen
+///
+/// That being said, the [libtool](https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html)
+/// versioning scheme is fairly common
+#[cfg_attr(test, derive(Debug))]
+pub struct SoVersion {
+ /// Might be non-zero if there is at least one non-zero numeric component after .so.
+ ///
+ /// Equivalent to `current` in libtool versions
+ pub major: u32,
+ /// The numeric component after the major version, if any
+ ///
+ /// Equivalent to `revision` in libtool versions
+ pub minor: u32,
+ /// The numeric component after the minor version, if any
+ ///
+ /// Equivalent to `age` in libtool versions
+ pub patch: u32,
+ /// The patch component may contain additional non-numeric metadata similar
+ /// to a semver prelease, this is any numeric data that suffixes that prerelease
+ /// string
+ pub prerelease: u32,
+}
+
+impl SoVersion {
+ /// Attempts to retrieve the .so version of the elf path via its filename
+ fn parse(so_path: &OsStr) -> Option<Self> {
+ let filename = std::path::Path::new(so_path).file_name()?;
+
+ // Avoid an allocation unless the string contains non-utf8
+ let filename = filename.to_string_lossy();
+
+ let (_, version) = filename.split_once(".so.")?;
+
+ let mut sov = Self {
+ major: 0,
+ minor: 0,
+ patch: 0,
+ prerelease: 0,
+ };
+
+ let comps = [
+ &mut sov.major,
+ &mut sov.minor,
+ &mut sov.patch,
+ &mut sov.prerelease,
+ ];
+
+ for (i, comp) in version.split('.').enumerate() {
+ if i <= 1 {
+ *comps[i] = comp.parse().unwrap_or_default();
+ } else if i >= 4 {
+ break;
+ } else {
+ // In some cases the release/patch version is alphanumeric (eg. '2rc5'),
+ // so try to parse either a single or two numbers
+ if let Some(pend) = comp.find(|c: char| !c.is_ascii_digit()) {
+ if let Ok(patch) = comp[..pend].parse() {
+ *comps[i] = patch;
+ }
+
+ if i >= comps.len() - 1 {
+ break;
+ }
+ if let Some(pre) = comp.rfind(|c: char| !c.is_ascii_digit()) {
+ if let Ok(pre) = comp[pre + 1..].parse() {
+ *comps[i + 1] = pre;
+ break;
+ }
+ }
+ } else {
+ *comps[i] = comp.parse().unwrap_or_default();
+ }
+ }
+ }
+
+ Some(sov)
+ }
+}
+
+#[cfg(test)]
+impl PartialEq<(u32, u32, u32, u32)> for SoVersion {
+ fn eq(&self, o: &(u32, u32, u32, u32)) -> bool {
+ self.major == o.0 && self.minor == o.1 && self.patch == o.2 && self.prerelease == o.3
+ }
+}
+
#[cfg(test)]
#[cfg(target_pointer_width = "64")] // All addresses are 64 bit and I'm currently too lazy to adjust it to work for both
mod tests {
@@ -628,14 +724,41 @@ a4840000-a4873000 rw-p 09021000 08:12 393449 /data/app/org.mozilla.firefox-1
);
assert_eq!(mappings.len(), 1);
- let (file_path, file_name) = mappings[0]
- .get_mapping_effective_path_and_name()
+ let (file_path, file_name, _version) = mappings[0]
+ .get_mapping_effective_path_name_and_version()
.expect("Couldn't get effective name for mapping");
assert_eq!(file_name, "libmozgtk.so");
assert_eq!(file_path, PathBuf::from("/home/martin/Documents/mozilla/devel/mozilla-central/obj/widget/gtk/mozgtk/gtk3/libmozgtk.so"));
}
#[test]
+ fn test_elf_file_so_version() {
+ #[rustfmt::skip]
+ let test_cases = [
+ ("/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.32", (6, 0, 32, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libcairo-gobject.so.2.11800.0", (2, 11800, 0, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libm.so.6", (6, 0, 0, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libpthread.so.0", (0, 0, 0, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.7800.0", (0, 7800, 0, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libabsl_time_zone.so.20220623.0.0", (20220623, 0, 0, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc5", (3, 34, 2, 5)),
+ ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.2rc", (3, 34, 2, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.34.rc5", (3, 34, 0, 5)),
+ ("/usr/lib/x86_64-linux-gnu/libtoto.so.AAA", (0, 0, 0, 0)),
+ ("/usr/lib/x86_64-linux-gnu/libsemver-1.so.1.2.alpha.1", (1, 2, 0, 1)),
+ ("/usr/lib/x86_64-linux-gnu/libboop.so.1.2.3.4.5", (1, 2, 3, 4)),
+ ("/usr/lib/x86_64-linux-gnu/libboop.so.1.2.3pre4.5", (1, 2, 3, 4)),
+ ];
+
+ assert!(SoVersion::parse(OsStr::new("/home/alex/bin/firefox/libmozsandbox.so")).is_none());
+
+ for (path, expected) in test_cases {
+ let actual = SoVersion::parse(OsStr::new(path)).unwrap();
+ assert_eq!(actual, expected);
+ }
+ }
+
+ #[test]
fn test_whitespaces_in_name() {
let mappings = get_mappings_for(
"\
diff --git a/third_party/rust/minidump-writer/src/linux/minidump_writer.rs b/third_party/rust/minidump-writer/src/linux/minidump_writer.rs
index da395b53f5..c83308f576 100644
--- a/third_party/rust/minidump-writer/src/linux/minidump_writer.rs
+++ b/third_party/rust/minidump-writer/src/linux/minidump_writer.rs
@@ -13,7 +13,10 @@ use crate::{
mem_writer::{Buffer, MemoryArrayWriter, MemoryWriter, MemoryWriterError},
minidump_format::*,
};
-use std::io::{Seek, Write};
+use std::{
+ io::{Seek, Write},
+ time::Duration,
+};
pub enum CrashingThreadContext {
None,
@@ -21,6 +24,10 @@ pub enum CrashingThreadContext {
CrashContextPlusAddress((MDLocationDescriptor, usize)),
}
+/// The default timeout after a `SIGSTOP` after which minidump writing proceeds
+/// regardless of the process state
+pub const STOP_TIMEOUT: Duration = Duration::from_millis(100);
+
pub struct MinidumpWriter {
pub process_id: Pid,
pub blamed_thread: Pid,
@@ -34,6 +41,7 @@ pub struct MinidumpWriter {
pub sanitize_stack: bool,
pub crash_context: Option<CrashContext>,
pub crashing_thread_context: CrashingThreadContext,
+ pub stop_timeout: Duration,
}
// This doesn't work yet:
@@ -62,6 +70,7 @@ impl MinidumpWriter {
sanitize_stack: false,
crash_context: None,
crashing_thread_context: CrashingThreadContext::None,
+ stop_timeout: STOP_TIMEOUT,
}
}
@@ -100,10 +109,18 @@ impl MinidumpWriter {
self
}
+ /// Sets the timeout after `SIGSTOP` is sent to the process, if the process
+ /// has not stopped by the time the timeout has reached, we proceed with
+ /// minidump generation
+ pub fn stop_timeout(&mut self, duration: Duration) -> &mut Self {
+ self.stop_timeout = duration;
+ self
+ }
+
/// Generates a minidump and writes to the destination provided. Returns the in-memory
/// version of the minidump as well.
pub fn dump(&mut self, destination: &mut (impl Write + Seek)) -> Result<Vec<u8>> {
- let mut dumper = PtraceDumper::new(self.process_id)?;
+ let mut dumper = PtraceDumper::new(self.process_id, self.stop_timeout)?;
dumper.suspend_threads()?;
dumper.late_init()?;
@@ -215,31 +232,24 @@ impl MinidumpWriter {
dir_section.write_to_file(buffer, None)?;
let dirent = thread_list_stream::write(self, buffer, dumper)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = mappings::write(self, buffer, dumper)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
app_memory::write(self, buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, None)?;
let dirent = memory_list_stream::write(self, buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = exception_stream::write(self, buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = systeminfo_stream::write(buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = memory_info_list_stream::write(self, buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, "/proc/cpuinfo") {
@@ -249,7 +259,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/status", self.blamed_thread))
@@ -260,7 +269,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self
@@ -273,7 +281,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/cmdline", self.blamed_thread))
@@ -284,7 +291,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/environ", self.blamed_thread))
@@ -295,7 +301,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/auxv", self.blamed_thread)) {
@@ -305,7 +310,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/maps", self.blamed_thread)) {
@@ -315,12 +319,10 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = dso_debug::write_dso_debug_stream(buffer, self.process_id, &dumper.auxv)
.unwrap_or_default();
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/limits", self.blamed_thread))
@@ -331,11 +333,9 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = thread_names_stream::write(buffer, dumper)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
// This section is optional, so we ignore errors when writing it
diff --git a/third_party/rust/minidump-writer/src/linux/ptrace_dumper.rs b/third_party/rust/minidump-writer/src/linux/ptrace_dumper.rs
index f75499bcdd..0dd0fa2719 100644
--- a/third_party/rust/minidump-writer/src/linux/ptrace_dumper.rs
+++ b/third_party/rust/minidump-writer/src/linux/ptrace_dumper.rs
@@ -15,10 +15,20 @@ use crate::{
use goblin::elf;
use nix::{
errno::Errno,
- sys::{ptrace, wait},
+ sys::{ptrace, signal, wait},
+};
+use procfs_core::{
+ process::{MMPermissions, ProcState, Stat},
+ FromRead, ProcError,
+};
+use std::{
+ collections::HashMap,
+ ffi::c_void,
+ io::BufReader,
+ path,
+ result::Result,
+ time::{Duration, Instant},
};
-use procfs_core::process::MMPermissions;
-use std::{collections::HashMap, ffi::c_void, io::BufReader, path, result::Result};
#[derive(Debug, Clone)]
pub struct Thread {
@@ -45,9 +55,27 @@ impl Drop for PtraceDumper {
fn drop(&mut self) {
// Always try to resume all threads (e.g. in case of error)
let _ = self.resume_threads();
+ // Always allow the process to continue.
+ let _ = self.continue_process();
}
}
+#[derive(Debug, thiserror::Error)]
+enum StopProcessError {
+ #[error("Failed to stop the process")]
+ Stop(#[from] Errno),
+ #[error("Failed to get the process state")]
+ State(#[from] ProcError),
+ #[error("Timeout waiting for process to stop")]
+ Timeout,
+}
+
+#[derive(Debug, thiserror::Error)]
+enum ContinueProcessError {
+ #[error("Failed to continue the process")]
+ Continue(#[from] Errno),
+}
+
/// PTRACE_DETACH the given pid.
///
/// This handles special errno cases (ESRCH) which we won't consider errors.
@@ -67,7 +95,7 @@ fn ptrace_detach(child: Pid) -> Result<(), DumperError> {
impl PtraceDumper {
/// Constructs a dumper for extracting information of a given process
/// with a process ID of |pid|.
- pub fn new(pid: Pid) -> Result<Self, InitError> {
+ pub fn new(pid: Pid, stop_timeout: Duration) -> Result<Self, InitError> {
let mut dumper = PtraceDumper {
pid,
threads_suspended: false,
@@ -76,12 +104,16 @@ impl PtraceDumper {
mappings: Vec::new(),
page_size: 0,
};
- dumper.init()?;
+ dumper.init(stop_timeout)?;
Ok(dumper)
}
// TODO: late_init for chromeos and android
- pub fn init(&mut self) -> Result<(), InitError> {
+ pub fn init(&mut self, stop_timeout: Duration) -> Result<(), InitError> {
+ // Stopping the process is best-effort.
+ if let Err(e) = self.stop_process(stop_timeout) {
+ log::warn!("failed to stop process {}: {e}", self.pid);
+ }
self.read_auxv()?;
self.enumerate_threads()?;
self.enumerate_mappings()?;
@@ -207,6 +239,38 @@ impl PtraceDumper {
result
}
+ /// Send SIGSTOP to the process so that we can get a consistent state.
+ ///
+ /// This will block waiting for the process to stop until `timeout` has passed.
+ fn stop_process(&mut self, timeout: Duration) -> Result<(), StopProcessError> {
+ signal::kill(nix::unistd::Pid::from_raw(self.pid), Some(signal::SIGSTOP))?;
+
+ // Something like waitpid for non-child processes would be better, but we have no such
+ // tool, so we poll the status.
+ const POLL_INTERVAL: Duration = Duration::from_millis(1);
+ let proc_file = format!("/proc/{}/stat", self.pid);
+ let end = Instant::now() + timeout;
+
+ loop {
+ if let Ok(ProcState::Stopped) = Stat::from_file(&proc_file)?.state() {
+ return Ok(());
+ }
+
+ std::thread::sleep(POLL_INTERVAL);
+ if Instant::now() > end {
+ return Err(StopProcessError::Timeout);
+ }
+ }
+ }
+
+ /// Send SIGCONT to the process to continue.
+ ///
+ /// Unlike `stop_process`, this function does not wait for the process to continue.
+ fn continue_process(&mut self) -> Result<(), ContinueProcessError> {
+ signal::kill(nix::unistd::Pid::from_raw(self.pid), Some(signal::SIGCONT))?;
+ Ok(())
+ }
+
/// Parse /proc/$pid/task to list all the threads of the process identified by
/// pid.
fn enumerate_threads(&mut self) -> Result<(), InitError> {
@@ -334,8 +398,9 @@ impl PtraceDumper {
let mut mapping = self.find_mapping(stack_pointer);
// The guard page has been 1 MiB in size since kernel 4.12, older
- // kernels used a 4 KiB one instead.
- let guard_page_max_addr = stack_pointer + (1024 * 1024);
+ // kernels used a 4 KiB one instead. Note the saturating add, as 32-bit
+ // processes can have a stack pointer within 1MiB of usize::MAX
+ let guard_page_max_addr = stack_pointer.saturating_add(1024 * 1024);
// If we found no mapping, or the mapping we found has no permissions
// then we might have hit a guard page, try looking for a mapping in
diff --git a/third_party/rust/minidump-writer/src/linux/sections/mappings.rs b/third_party/rust/minidump-writer/src/linux/sections/mappings.rs
index de19c54068..9012ae351b 100644
--- a/third_party/rust/minidump-writer/src/linux/sections/mappings.rs
+++ b/third_party/rust/minidump-writer/src/linux/sections/mappings.rs
@@ -83,16 +83,29 @@ fn fill_raw_module(
sig_section.location()
};
- let (file_path, _) = mapping
- .get_mapping_effective_path_and_name()
+ let (file_path, _, so_version) = mapping
+ .get_mapping_effective_path_name_and_version()
.map_err(|e| errors::SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?;
let name_header = write_string_to_location(buffer, file_path.to_string_lossy().as_ref())?;
- Ok(MDRawModule {
+ let version_info = so_version.map_or(Default::default(), |sov| format::VS_FIXEDFILEINFO {
+ signature: format::VS_FFI_SIGNATURE,
+ struct_version: format::VS_FFI_STRUCVERSION,
+ file_version_hi: sov.major,
+ file_version_lo: sov.minor,
+ product_version_hi: sov.patch,
+ product_version_lo: sov.prerelease,
+ ..Default::default()
+ });
+
+ let raw_module = MDRawModule {
base_of_image: mapping.start_address as u64,
size_of_image: mapping.size as u32,
cv_record,
module_name_rva: name_header.rva,
+ version_info,
..Default::default()
- })
+ };
+
+ Ok(raw_module)
}
diff --git a/third_party/rust/minidump-writer/src/linux/thread_info.rs b/third_party/rust/minidump-writer/src/linux/thread_info.rs
index 5bb1f9e8fb..a3fbed952f 100644
--- a/third_party/rust/minidump-writer/src/linux/thread_info.rs
+++ b/third_party/rust/minidump-writer/src/linux/thread_info.rs
@@ -38,19 +38,17 @@ enum NT_Elf {
}
#[inline]
-pub fn to_u128(slice: &[u32]) -> &[u128] {
- unsafe { std::slice::from_raw_parts(slice.as_ptr().cast(), slice.len().saturating_div(4)) }
-}
-
-#[inline]
-pub fn copy_registers(dst: &mut [u128], src: &[u128]) {
- let to_copy = std::cmp::min(dst.len(), src.len());
- dst[..to_copy].copy_from_slice(&src[..to_copy]);
-}
-
-#[inline]
pub fn copy_u32_registers(dst: &mut [u128], src: &[u32]) {
- copy_registers(dst, to_u128(src));
+ // SAFETY: We are copying a block of memory from ptrace as u32s to the u128
+ // format of minidump-common
+ unsafe {
+ let dst: &mut [u8] =
+ std::slice::from_raw_parts_mut(dst.as_mut_ptr().cast(), dst.len() * 16);
+ let src: &[u8] = std::slice::from_raw_parts(src.as_ptr().cast(), src.len() * 4);
+
+ let to_copy = std::cmp::min(dst.len(), src.len());
+ dst[..to_copy].copy_from_slice(&src[..to_copy]);
+ }
}
trait CommonThreadInfo {
diff --git a/third_party/rust/minidump-writer/src/mac/mach.rs b/third_party/rust/minidump-writer/src/mac/mach.rs
index f95211dc64..9b0179fad4 100644
--- a/third_party/rust/minidump-writer/src/mac/mach.rs
+++ b/third_party/rust/minidump-writer/src/mac/mach.rs
@@ -590,7 +590,8 @@ pub fn sysctl_by_name<T: Sized + Default>(name: &[u8]) -> T {
0,
) != 0
{
- // log?
+ // TODO convert to ascii characters when logging?
+ log::warn!("failed to get sysctl for {name:?}");
T::default()
} else {
out
diff --git a/third_party/rust/minidump-writer/src/mac/streams/exception.rs b/third_party/rust/minidump-writer/src/mac/streams/exception.rs
index e594dd8d95..7dd7f8fae4 100644
--- a/third_party/rust/minidump-writer/src/mac/streams/exception.rs
+++ b/third_party/rust/minidump-writer/src/mac/streams/exception.rs
@@ -69,9 +69,11 @@ impl MinidumpWriter {
} else {
// For all other exceptions types, the value in the code
// _should_ never exceed 32 bits, crashpad does an actual
- // range check here, but since we don't really log anything
- // else at the moment I'll punt that for now
- // TODO: log/do something if exc.code > u32::MAX
+ // range check here.
+ if code > u32::MAX.into() {
+ // TODO: do something more than logging?
+ log::warn!("exception code {code:#018x} exceeds the expected 32 bits");
+ }
code as u32
};
diff --git a/third_party/rust/minidump-writer/src/mac/streams/module_list.rs b/third_party/rust/minidump-writer/src/mac/streams/module_list.rs
index 2b4d13ea74..d1307c80a8 100644
--- a/third_party/rust/minidump-writer/src/mac/streams/module_list.rs
+++ b/third_party/rust/minidump-writer/src/mac/streams/module_list.rs
@@ -344,6 +344,14 @@ mod test {
/// both the local and intra-process scenarios
#[test]
fn images_match() {
+ if std::env::var_os("CI").is_some() && cfg!(target_arch = "aarch64") {
+ // https://github.com/rust-minidump/minidump-writer/issues/101
+ println!(
+ "this fails on github actions but works on a local aarch64-apple-darwin machine..."
+ );
+ return;
+ }
+
let mdw = MinidumpWriter::new(None, None);
let td = TaskDumper::new(mdw.task);
diff --git a/third_party/rust/minidump-writer/src/mac/streams/thread_names.rs b/third_party/rust/minidump-writer/src/mac/streams/thread_names.rs
index 42242a6397..016dd48eb8 100644
--- a/third_party/rust/minidump-writer/src/mac/streams/thread_names.rs
+++ b/third_party/rust/minidump-writer/src/mac/streams/thread_names.rs
@@ -25,8 +25,8 @@ impl MinidumpWriter {
// not a critical failure
let name_loc = match Self::write_thread_name(buffer, dumper, tid) {
Ok(loc) => loc,
- Err(_err) => {
- // TODO: log error
+ Err(err) => {
+ log::warn!("failed to write thread name for thread {tid}: {err}");
write_string_to_location(buffer, "")?
}
};
diff --git a/third_party/rust/minidump-writer/src/windows/minidump_writer.rs b/third_party/rust/minidump-writer/src/windows/minidump_writer.rs
index 70cc420e57..2175368935 100644
--- a/third_party/rust/minidump-writer/src/windows/minidump_writer.rs
+++ b/third_party/rust/minidump-writer/src/windows/minidump_writer.rs
@@ -185,13 +185,13 @@ impl MinidumpWriter {
// This is a mut pointer for some reason...I don't _think_ it is
// actually mut in practice...?
ExceptionPointers: crash_context.exception_pointers as *mut _,
- /// The `EXCEPTION_POINTERS` contained in crash context is a pointer into the
- /// memory of the process that crashed, as it contains an `EXCEPTION_RECORD`
- /// record which is an internally linked list, so in the case that we are
- /// dumping a process other than the current one, we need to tell
- /// `MiniDumpWriteDump` that the pointers come from an external process so that
- /// it can use eg `ReadProcessMemory` to get the contextual information from
- /// the crash, rather than from the current process
+ // The `EXCEPTION_POINTERS` contained in crash context is a pointer into the
+ // memory of the process that crashed, as it contains an `EXCEPTION_RECORD`
+ // record which is an internally linked list, so in the case that we are
+ // dumping a process other than the current one, we need to tell
+ // `MiniDumpWriteDump` that the pointers come from an external process so that
+ // it can use eg `ReadProcessMemory` to get the contextual information from
+ // the crash, rather than from the current process
ClientPointers: i32::from(is_external_process),
},
);
diff --git a/third_party/rust/minidump-writer/tests/common/mod.rs b/third_party/rust/minidump-writer/tests/common/mod.rs
index bbb6abf35c..1d5497b3ba 100644
--- a/third_party/rust/minidump-writer/tests/common/mod.rs
+++ b/third_party/rust/minidump-writer/tests/common/mod.rs
@@ -8,21 +8,27 @@ type Error = Box<dyn error::Error + std::marker::Send + std::marker::Sync>;
#[allow(unused)]
pub type Result<T> = result::Result<T, Error>;
+fn build_command() -> Command {
+ let mut cmd = Command::new("cargo");
+
+ cmd.env("RUST_BACKTRACE", "1")
+ .args(["run", "-q", "--bin", "test"]);
+
+ // In normal cases where the host and target are the same this won't matter,
+ // but tests will fail if you are eg running in a cross container which will
+ // likely be x86_64 but may be targetting aarch64 or i686, which will result
+ // in tests failing, or at the least not testing what you think
+ cmd.args(["--target", current_platform::CURRENT_PLATFORM, "--"]);
+
+ cmd
+}
+
#[allow(unused)]
pub fn spawn_child(command: &str, args: &[&str]) {
- let mut cmd_object = Command::new("cargo");
- let mut cmd_ref = cmd_object
- .env("RUST_BACKTRACE", "1")
- .arg("run")
- .arg("-q")
- .arg("--bin")
- .arg("test")
- .arg("--")
- .arg(command);
- for arg in args {
- cmd_ref = cmd_ref.arg(arg);
- }
- let child = cmd_ref.output().expect("failed to execute child");
+ let mut cmd = build_command();
+ cmd.arg(command).args(args);
+
+ let child = cmd.output().expect("failed to execute child");
println!("Child output:");
std::io::stdout().write_all(&child.stdout).unwrap();
@@ -30,20 +36,12 @@ pub fn spawn_child(command: &str, args: &[&str]) {
assert_eq!(child.status.code().expect("No return value"), 0);
}
-fn start_child_and_wait_for_threads_helper(cmd: &str, num: usize) -> Child {
- let mut child = Command::new("cargo")
- .env("RUST_BACKTRACE", "1")
- .arg("run")
- .arg("-q")
- .arg("--bin")
- .arg("test")
- .arg("--")
- .arg(cmd)
- .arg(format!("{}", num))
- .stdout(Stdio::piped())
- .spawn()
- .expect("failed to execute child");
+fn start_child_and_wait_for_threads_helper(command: &str, num: usize) -> Child {
+ let mut cmd = build_command();
+ cmd.arg(command).arg(num.to_string());
+ cmd.stdout(Stdio::piped());
+ let mut child = cmd.spawn().expect("failed to spawn cargo");
wait_for_threads(&mut child, num);
child
}
@@ -84,17 +82,10 @@ pub fn wait_for_threads(child: &mut Child, num: usize) {
#[allow(unused)]
pub fn start_child_and_return(args: &[&str]) -> Child {
- let mut child = Command::new("cargo")
- .env("RUST_BACKTRACE", "1")
- .arg("run")
- .arg("-q")
- .arg("--bin")
- .arg("test")
- .arg("--")
- .args(args)
- .stdout(Stdio::piped())
- .spawn()
- .expect("failed to execute child");
+ let mut cmd = build_command();
+ cmd.args(args);
- child
+ cmd.stdout(Stdio::piped())
+ .spawn()
+ .expect("failed to execute child")
}
diff --git a/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs b/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs
index d9864bae13..c8458b1583 100644
--- a/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs
+++ b/third_party/rust/minidump-writer/tests/linux_minidump_writer.rs
@@ -72,31 +72,31 @@ fn get_crash_context(tid: Pid) -> CrashContext {
}
}
-macro_rules! contextual_tests {
- () => {};
- ( fn $name:ident ($ctx:ident : Context) $body:block $($rest:tt)* ) => {
+macro_rules! contextual_test {
+ ( $(#[$attr:meta])? fn $name:ident ($ctx:ident : Context) $body:block ) => {
mod $name {
use super::*;
fn test($ctx: Context) $body
#[test]
- fn run() {
+ $(#[$attr])?
+ fn without_context() {
test(Context::Without)
}
#[cfg(not(target_arch = "mips"))]
#[test]
- fn run_with_context() {
+ $(#[$attr])?
+ fn with_context() {
test(Context::With)
}
}
- contextual_tests! { $($rest)* }
}
}
-contextual_tests! {
- fn test_write_dump(context: Context) {
+contextual_test! {
+ fn write_dump(context: Context) {
let num_of_threads = 3;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
@@ -123,8 +123,11 @@ contextual_tests! {
assert_eq!(mem_slice.len(), in_memory_buffer.len());
assert_eq!(mem_slice, in_memory_buffer);
}
+}
- fn test_write_and_read_dump_from_parent(context: Context) {
+contextual_test! {
+ #[ignore]
+ fn write_and_read_dump_from_parent(context: Context) {
let mut child = start_child_and_return(&["spawn_mmap_wait"]);
let pid = child.id() as i32;
@@ -228,8 +231,10 @@ contextual_tests! {
.get_raw_stream(MozLinuxLimits as u32)
.expect("Couldn't find MozLinuxLimits");
}
+}
- fn test_write_with_additional_memory(context: Context) {
+contextual_test! {
+ fn write_with_additional_memory(context: Context) {
let mut child = start_child_and_return(&["spawn_alloc_wait"]);
let pid = child.id() as i32;
@@ -289,8 +294,10 @@ contextual_tests! {
// Verify memory contents.
assert_eq!(region.bytes, values);
}
+}
- fn test_skip_if_requested(context: Context) {
+contextual_test! {
+ fn skip_if_requested(context: Context) {
let num_of_threads = 1;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
@@ -325,8 +332,10 @@ contextual_tests! {
assert!(res.is_err());
}
+}
- fn test_sanitized_stacks(context: Context) {
+contextual_test! {
+ fn sanitized_stacks(context: Context) {
if context == Context::With {
// FIXME the context's stack pointer very often doesn't lie in mapped memory, resulting
// in the stack memory having 0 size (so no slice will match `defaced` in the
@@ -378,8 +387,10 @@ contextual_tests! {
assert!(slice.windows(defaced.len()).any(|window| window == defaced));
}
}
+}
- fn test_write_early_abort(context: Context) {
+contextual_test! {
+ fn write_early_abort(context: Context) {
let mut child = start_child_and_return(&["spawn_alloc_wait"]);
let pid = child.id() as i32;
@@ -434,8 +445,10 @@ contextual_tests! {
// Should be missing:
assert!(dump.get_stream::<MinidumpMemoryList>().is_err());
}
+}
- fn test_named_threads(context: Context) {
+contextual_test! {
+ fn named_threads(context: Context) {
let num_of_threads = 5;
let mut child = start_child_and_wait_for_named_threads(num_of_threads);
let pid = child.id() as i32;
@@ -476,10 +489,11 @@ contextual_tests! {
expected.insert(format!("thread_{}", id));
}
assert_eq!(expected, names);
-
}
+}
- fn test_file_descriptors(context: Context) {
+contextual_test! {
+ fn file_descriptors(context: Context) {
let num_of_files = 5;
let mut child = start_child_and_wait_for_create_files(num_of_files);
let pid = child.id() as i32;
@@ -520,7 +534,7 @@ contextual_tests! {
}
#[test]
-fn test_minidump_size_limit() {
+fn minidump_size_limit() {
let num_of_threads = 40;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
@@ -662,7 +676,7 @@ fn test_minidump_size_limit() {
}
#[test]
-fn test_with_deleted_binary() {
+fn with_deleted_binary() {
let num_of_threads = 1;
let binary_copy_dir = tempfile::Builder::new()
.prefix("deleted_binary")
@@ -686,36 +700,9 @@ fn test_with_deleted_binary() {
let pid = child.id() as i32;
- let build_id = PtraceDumper::elf_file_identifier_from_mapped_file(&mem_slice)
+ let mut build_id = PtraceDumper::elf_file_identifier_from_mapped_file(&mem_slice)
.expect("Failed to get build_id");
- let guid = GUID {
- data1: u32::from_ne_bytes(build_id[0..4].try_into().unwrap()),
- data2: u16::from_ne_bytes(build_id[4..6].try_into().unwrap()),
- data3: u16::from_ne_bytes(build_id[6..8].try_into().unwrap()),
- data4: build_id[8..16].try_into().unwrap(),
- };
-
- // guid_to_string() is not public in minidump, so copied it here
- // And append a zero, because module IDs include an "age" field
- // which is always zero on Linux.
- let filtered = format!(
- "{:08X}{:04X}{:04X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}0",
- guid.data1,
- guid.data2,
- guid.data3,
- guid.data4[0],
- guid.data4[1],
- guid.data4[2],
- guid.data4[3],
- guid.data4[4],
- guid.data4[5],
- guid.data4[6],
- guid.data4[7],
- );
- // Strip out dashes
- //let mut filtered: String = identifier.chars().filter(|x| *x != '-').collect();
-
std::fs::remove_file(&binary_copy).expect("Failed to remove binary");
let mut tmpfile = tempfile::Builder::new()
@@ -747,11 +734,34 @@ fn test_with_deleted_binary() {
.main_module()
.expect("Could not get main module");
assert_eq!(main_module.code_file(), binary_copy.to_string_lossy());
- assert_eq!(main_module.debug_identifier(), filtered.parse().ok());
+
+ let did = main_module
+ .debug_identifier()
+ .expect("expected value debug id");
+ {
+ let uuid = did.uuid();
+ let uuid = uuid.as_bytes();
+
+ // Swap bytes in the original to match the expected uuid
+ if cfg!(target_endian = "little") {
+ build_id[..4].reverse();
+ build_id[4..6].reverse();
+ build_id[6..8].reverse();
+ }
+
+ // The build_id from the binary can be as little as 8 bytes, eg LLD uses
+ // xxhash to calculate the build_id by default from 10+
+ build_id.resize(16, 0);
+
+ assert_eq!(uuid.as_slice(), &build_id);
+ }
+
+ // The 'age'/appendix, always 0 on non-windows targets
+ assert_eq!(did.appendix(), 0);
}
#[test]
-fn test_memory_info_list_stream() {
+fn memory_info_list_stream() {
let mut child = start_child_and_wait_for_threads(1);
let pid = child.id() as i32;
diff --git a/third_party/rust/minidump-writer/tests/ptrace_dumper.rs b/third_party/rust/minidump-writer/tests/ptrace_dumper.rs
index 1be27f0809..6b62a4f6f3 100644
--- a/third_party/rust/minidump-writer/tests/ptrace_dumper.rs
+++ b/third_party/rust/minidump-writer/tests/ptrace_dumper.rs
@@ -7,7 +7,6 @@ use nix::sys::signal::Signal;
use std::convert::TryInto;
use std::io::{BufRead, BufReader};
use std::mem::size_of;
-use std::os::unix::io::AsFd;
use std::os::unix::process::ExitStatusExt;
mod common;
@@ -29,7 +28,8 @@ fn test_thread_list_from_parent() {
let num_of_threads = 5;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
- let mut dumper = PtraceDumper::new(pid).expect("Couldn't init dumper");
+ let mut dumper = PtraceDumper::new(pid, minidump_writer::minidump_writer::STOP_TIMEOUT)
+ .expect("Couldn't init dumper");
assert_eq!(dumper.threads.len(), num_of_threads);
dumper.suspend_threads().expect("Could not suspend threads");
@@ -129,20 +129,22 @@ fn test_merged_mappings() {
map_size,
ProtFlags::PROT_READ,
MapFlags::MAP_SHARED,
- Some(file.as_fd()),
+ &file,
0,
)
.unwrap()
};
+ let mapped = mapped_mem.as_ptr() as usize;
+
// Carve a page out of the first mapping with different permissions.
let _inside_mapping = unsafe {
mmap(
- std::num::NonZeroUsize::new(mapped_mem as usize + 2 * page_size.get()),
+ std::num::NonZeroUsize::new(mapped + 2 * page_size.get()),
page_size,
ProtFlags::PROT_NONE,
MapFlags::MAP_SHARED | MapFlags::MAP_FIXED,
- Some(file.as_fd()),
+ &file,
// Map a different offset just to
// better test real-world conditions.
page_size.get().try_into().unwrap(), // try_into() in order to work for 32 and 64 bit
@@ -151,11 +153,7 @@ fn test_merged_mappings() {
spawn_child(
"merged_mappings",
- &[
- path,
- &format!("{}", mapped_mem as usize),
- &format!("{map_size}"),
- ],
+ &[path, &format!("{mapped}"), &format!("{map_size}")],
);
}
@@ -209,7 +207,8 @@ fn test_sanitize_stack_copy() {
let heap_addr = usize::from_str_radix(output.next().unwrap().trim_start_matches("0x"), 16)
.expect("unable to parse mmap_addr");
- let mut dumper = PtraceDumper::new(pid).expect("Couldn't init dumper");
+ let mut dumper = PtraceDumper::new(pid, minidump_writer::minidump_writer::STOP_TIMEOUT)
+ .expect("Couldn't init dumper");
assert_eq!(dumper.threads.len(), num_of_threads);
dumper.suspend_threads().expect("Could not suspend threads");
let thread_info = dumper
diff --git a/third_party/rust/naga/.cargo-checksum.json b/third_party/rust/naga/.cargo-checksum.json
index 8a1163971f..d01b0848ce 100644
--- a/third_party/rust/naga/.cargo-checksum.json
+++ b/third_party/rust/naga/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".cargo/config.toml":"d7389d2a0c08ec72b79e83a3c76980903e3f9123625c32e69c798721193e2e74","CHANGELOG.md":"6b2c4d8dfd8c537811c33744703b4c03fa8aa15f5fab8f0e2be76f597cb7e273","Cargo.toml":"dd06bf980497dcb0d35c2c33d845ba80cb7a2f78bd0e824e3d6be6b950b8088b","README.md":"468211bb7457683510ff862f31f27e3ba07514f851a4390570d0e9259cbeaf6f","benches/criterion.rs":"f45e38b26e1323e934d32623572ff5395a53fed06f760eb1e07b22ed07858a38","src/arena.rs":"33ed2ec7b36429b133ed2a7de6fb9735827f69ea8b6c2ce97f64746a24a5bf36","src/back/dot/mod.rs":"a40050a73ac00c8fa43dd0b45a84fca6959d28c8c99ab3046b01f33c02f8c8f4","src/back/glsl/features.rs":"3d12147d201aaed746a94741356458a435a1ff7cf30b66baf44ba0b8dfe4b0ca","src/back/glsl/keywords.rs":"1546facbaddf696602102f32e47db7afc875f8ca3fbccc2122e0bcc45e022b53","src/back/glsl/mod.rs":"9e8b34a09401744a2ad4deae4d4863bd0be1d7d5da6ca72a98ca80fe0e3dfde6","src/back/hlsl/conv.rs":"2d7a8e7753b8fb21659e582612eea82e42e353abd23df719de450074a4da731e","src/back/hlsl/help.rs":"06da97ea0d58e2b94823ca1dae67a8611be6d5d047649b1d83755acb4c110808","src/back/hlsl/keywords.rs":"a7164690a4da866e6bfb18ced20e32cc8c42dd7387e0e84addf0c2674f529cf5","src/back/hlsl/mod.rs":"2f5296c45a2147093cae17250321580e7f01c57f907e529d19521eccd0cd4147","src/back/hlsl/storage.rs":"2c2a0071cafe487a398e396dddc85bdb319b1a5d74c097d529078e247a904359","src/back/hlsl/writer.rs":"36f0410edf9c0a8295e4916ca0e7a4e98cd170fcd5ecf6826df6051bef003b9c","src/back/mod.rs":"6101d92bff1c5b7fe3e503188554dfdcce56d4eb610237e0126bf6d8c4e1a85d","src/back/msl/keywords.rs":"e6a4ef77363f995de1f8079c0b8591497cbf9520c5d3b2d41c7e1f483e8abd24","src/back/msl/mod.rs":"15fdb90b8cd2b98273b22b9569fc322eb473fd135865eef82cc615d27320d779","src/back/msl/sampler.rs":"9b01d68669e12ff7123243284b85e1a9d2c4d49140bd74ca32dedc007cbf15af","src/back/msl/writer.rs":"27e8604a5d11391b91b328f420e93f7cf475364a783b3dc5ba8bb720f17d9d86","src/back/spv/block.rs":"e2326e10cc8ca64398636c1b27166b406611006ffc2388c20fca4a271d609afe","src/back/spv/helpers.rs":"a4e260130f39c7345decec40dadf1e94419c8f6d236ce7a53b5300aa72952a1b","src/back/spv/image.rs":"e4b982ce430e17881d6370191d849dbe6bb8f6d86f4896815eb1736e43b4e302","src/back/spv/index.rs":"54bb90176be12a9a243099343e62b8dd35dd019d237d4d7dcdb9f0da7747df09","src/back/spv/instructions.rs":"d0ced535fdec49323105a7d6ee40a8ed6b4966ac5f0f40b062f0eb11a531b106","src/back/spv/layout.rs":"e263de53cd2f9a03ad94b82b434ce636609bc1ed435a2d1132951663bfaa8ebd","src/back/spv/mod.rs":"bd0589e0f6ce33b294f1f907dd5a1c03b46429b1b0d77986f8bb98ad317b11e3","src/back/spv/ray.rs":"a34bf6b26d873f7270caa45841d9ef291aca8d9732ecd086b14d8856038e1e41","src/back/spv/recyclable.rs":"114db0ea12774d6514f995d07295cb9a42631ab75165fc60980c10e9b5ecb832","src/back/spv/selection.rs":"81e404abfa0a977f7c1f76ccb37a78d13ccadbda229048dad53cc67687cc39db","src/back/spv/writer.rs":"87460df9918c1f104213394c0532e384ae282d132fdb7e09823eeb10c2392e3d","src/back/wgsl/mod.rs":"2dd12bbea9ace835850192bb68c5760953da6bac6a636073d1eca19381c0c0b6","src/back/wgsl/writer.rs":"96795df390cffade8ca27baea88ab29592d7e425c4351a9e2591d4f4ecdc73f3","src/block.rs":"c69089e5bbb6de6ba24efb15b21d5d434fcabfbc4d48feae948d2a4da135aae7","src/compact/expressions.rs":"7a4c916282a5b484519ed29ab451c7b595d8dea73c83c5c2cf7efc6fbc648fda","src/compact/functions.rs":"174bd9167ecf6353afb8c36d365ba3f9b483233eb4bacf578e50183c7433aa15","src/compact/handle_set_map.rs":"817c5193352d5fd6a61a5c970daba23224e14a65aea15f8f1c8679c99f834ca2","src/compact/mod.rs":"f1a606e8732f3c5837ab40ba5569eb1687336ef412f7f4b6cc348dd52b8076b3","src/compact/statements.rs":"4df33ee9589300e769e75c674bdc30578e93704ec3eb2aabc7132121745b55c8","src/compact/types.rs":"18343f2ca2c123eea2531cffc1d54a7798797caccecaa1f9b8c4fd5dd6ca1a05","src/front/glsl/ast.rs":"a4615f0c52b0dc9fdb07f816b4534c1ca547c2d176008ca86d66f9e6874f227d","src/front/glsl/builtins.rs":"d35501d5b42b61c261da24436b82eafdf96371b1600d148648d90d041f736ae4","src/front/glsl/context.rs":"066203c24ff5bc6154aa671f4492b5e8dfede8b57ef886f093cc95470d66411b","src/front/glsl/error.rs":"cca4a3aa9de2808952ff68c183755df5fdf6a7cb81f170ba747795176c0342fd","src/front/glsl/functions.rs":"b420be6b54195e9cdabdf76bb854e3e1f3be6542c6c129656fd0b1bd900dcebd","src/front/glsl/lex.rs":"08736ae8beb955da5b0e6e3e0f45995a824995f7096d516a2910417e9c7afa32","src/front/glsl/mod.rs":"c6e81710ae94a52583ba6f2a80a505d6bcd6ea6552008b80b27539af48838df1","src/front/glsl/offset.rs":"9358602ca4f9ef21d5066d674dae757bf88fdf5c289c4360534354d13bd41dc0","src/front/glsl/parser.rs":"fe5291512db412b33b6c09d5b3dcf7c54ff6ec55b47f0a078dcc11695e78471d","src/front/glsl/parser/declarations.rs":"d637cc52e553910a2e97b70b3366c15aefbe737f413adb11c27efd184c1fbf9d","src/front/glsl/parser/expressions.rs":"520cfc9402d5fbd48e52ef1d36562c6b74794c09ec33ec1ebb10aa48d129b66f","src/front/glsl/parser/functions.rs":"75aedcea4133bc4aba06ef49b1697eac96cc28d191e9830689fc4a6c0c4856eb","src/front/glsl/parser/types.rs":"aeb97e1a5fb03205cd5630c29da59d81a376ce9a83a603b62b037e63ad948e88","src/front/glsl/parser_tests.rs":"bfd4dff2580f4369a57edbcace47d23e2666751ffc3ab55f8d7dfe01f1a66311","src/front/glsl/token.rs":"c25c489b152ee2d445ace3c2046473abe64d558b8d27fa08709110e58718b6ac","src/front/glsl/types.rs":"58c9cf3d570dff8cb68f2931faf5b18e875e510741bf035ec10b9ff6df27c5d8","src/front/glsl/variables.rs":"bfed08368b56dc1f55fe487b240cf7b8e09443e508ea410cfac48df477591eee","src/front/interpolator.rs":"9b6ca498d5fbd9bc1515510a04e303a00b324121d7285da3c955cfe18eb4224c","src/front/mod.rs":"77acd7fb71d004969d1ee69fc728647f03242762988786c4e15fadf8315600af","src/front/spv/convert.rs":"dccc6671e6a4a7f1139aecdf979faa3689609081af5fa2cbbd6a2e8c4128c004","src/front/spv/error.rs":"6438aac57cfcf5d3858dd7652ccda1967a3123c6374f1cab829092b00549f70f","src/front/spv/function.rs":"1acb7bdd34ecfe08c6f4b4d06c2a0ea74aaf9975352e8804e3e4fab90745132f","src/front/spv/image.rs":"5d55cfbf6752732a594114cd09a9a207216e1ee85d8f2c9bc4310217a55ea321","src/front/spv/mod.rs":"22d0de7c43c42279e788144ff806cadfe3a3ea7923d961d11740af22492c4087","src/front/spv/null.rs":"e1446d99d04c76a9c3bbd24dd9b20c4711ce8a918a9b403be6cccbde1175b3b4","src/front/type_gen.rs":"b4f1df23380e06c9fdad4140810ce96ab041dbb1d371a07045b4e0069aa8ba55","src/front/wgsl/error.rs":"e1efd61062a5eb5f7e0413dc05d17abdbe0679c08f2fbdb7478e2b6e8dd13b25","src/front/wgsl/index.rs":"2b9a4929a46bd822d3ed6f9a150e24d437e5bdca8293eb748aebe80ce7e74153","src/front/wgsl/lower/construction.rs":"92342e27f5bdeb598e178799b74aa610788549c19a49fe0ae8914916bfa3c7be","src/front/wgsl/lower/conversion.rs":"961b19bf8ddd4667c6caf854a1889f3d6477757f4125538c3e9ca7d730975dd7","src/front/wgsl/lower/mod.rs":"08eece7a5460e414e2f8398cec96f12a8b9f6a457270426d8e4f045b62290d1f","src/front/wgsl/mod.rs":"02b194a0a29ef7281f71b424564e18ada4a8b1a0d8c26ec40b6be195bd4c4904","src/front/wgsl/parse/ast.rs":"c7eaae40179f0889f2b142d3b31968cbfab6d3cfe02e425912c6da8dadac51df","src/front/wgsl/parse/conv.rs":"9b2a06b5fd577e1881b2212e1d675d3aefe4d1fee99a17b5f7b07c36913e8186","src/front/wgsl/parse/lexer.rs":"17db87d0017f8f9a80fa151b8545f04e1b40c4e5feef6197f4a117efa03488bf","src/front/wgsl/parse/mod.rs":"3b4895a2baf91c719b95f0afb6441ffac2036c2a9ff817e633882fd257afcc38","src/front/wgsl/parse/number.rs":"dafd3d8651cfa1389cb359d76d39bd689e54f8d5025aa23e06c6edd871369efd","src/front/wgsl/tests.rs":"7a0a083a5b66af8e7d4b1a02401b27f077eb72d07181b610693f35b11f107c6c","src/front/wgsl/to_wgsl.rs":"2e2e30d86b07f209b866e530d3a882803bf28b39ce379052561a749f628e8e28","src/keywords/mod.rs":"0138f3931f8af0b0a05174549d0fd2152945b027dc3febefc1bbd676581d2e45","src/keywords/wgsl.rs":"c648ac44241ad55c8c8bad3d8f1bab973d11ddb9c380dcca369b735ed3975309","src/lib.rs":"f2072172957699d4282f247c452d8d8f0a0da08b9d78b279ee010296669d28d8","src/proc/constant_evaluator.rs":"bea5d259dbc4d9f9dacf3717dcb17a0774a22f1b3e5251b7e5b6991330ed3057","src/proc/emitter.rs":"39ac886c651e2ad33c06a676a7e4826a0e93de0af660c01e8e4b1f7406742f88","src/proc/index.rs":"f4250f6944c2b631e8140979024e8deb86fa8d5352d8641ba954a388b2c0940e","src/proc/layouter.rs":"b3d061c87424f36981c902716f37ab7b72f2bb2d0c2d7e900c51149318ea1a0a","src/proc/mod.rs":"4be5dcb137147cd8182a291f90959c46f1681c2d2c7da9e63f702a5f84c8809d","src/proc/namer.rs":"7328fac41e40890c64c7ee2fa985a4395424f18b08d30f30ca2583fdabd2fd35","src/proc/terminator.rs":"13c59bf00f5b26171d971effc421091f5e00dedddd246c2daa44fe65aeda060a","src/proc/typifier.rs":"99de19270d01c12ec49d14323aa1d9b8774f1ee715804af7235deff70739ba3d","src/span.rs":"47d92ea25ce7178ad903ac4f5acd0bc40ebd90de1e470e538a2aa3063d980890","src/valid/analyzer.rs":"65ed1487c5a169688714a7386046b30ec380eaf44e5500f366b9c9a308f59464","src/valid/compose.rs":"83e4c09c39f853cf085b83b87e48b3db571da619132960d3ec954ebdfb0a74f2","src/valid/expression.rs":"7a8d5f74677c627dee3e15d223e83453ea7f6567dc806fcdfeebd32081012779","src/valid/function.rs":"40754e51906b053becdd8813b189fe709b7693c08babd28b5d3f5c576475b171","src/valid/handles.rs":"0878915e67b16d7c41cf8245d9ab3b3f4a604e7d4e87527ea40e03efcbf1f74a","src/valid/interface.rs":"32ef8e4665106b5c71540833e17ee9cd1dde5a900c9b81f61e0b7b8192c4aaf2","src/valid/mod.rs":"3b2772c88561aeb4dc8f5ce0d8ed5169bcdf5f7db04a62aaf22d04c171cb4f35","src/valid/type.rs":"635a4f7b2681d2cc7645a5589640098efb3cdaf3c492d79924c9e80c806c7890"},"package":null} \ No newline at end of file
+{"files":{".cargo/config.toml":"d7389d2a0c08ec72b79e83a3c76980903e3f9123625c32e69c798721193e2e74","CHANGELOG.md":"6b2c4d8dfd8c537811c33744703b4c03fa8aa15f5fab8f0e2be76f597cb7e273","Cargo.toml":"52d6fbc7cdb6af39f63af59159fa60aa2c230bb73689cb12dd024ff72c2459aa","README.md":"468211bb7457683510ff862f31f27e3ba07514f851a4390570d0e9259cbeaf6f","benches/criterion.rs":"f45e38b26e1323e934d32623572ff5395a53fed06f760eb1e07b22ed07858a38","src/arena.rs":"2b9cc6eafa2083171b9b053f309c4506796784f8770e8b62d9cfb322cdffef2a","src/back/dot/mod.rs":"559d7bb9abc214a2ae8448cb3718ca249c55a24cddfa368eb765ee5c0c977524","src/back/glsl/features.rs":"382f01bec9db166f14348e60fd5347c55ddb87487b2c0040301d9a6da366a86c","src/back/glsl/keywords.rs":"1546facbaddf696602102f32e47db7afc875f8ca3fbccc2122e0bcc45e022b53","src/back/glsl/mod.rs":"e621689676095d978a5d64af1dfa1fd18e02181a1c759ac957aea1408858d122","src/back/hlsl/conv.rs":"62639a33f59fecb9fee53fcf22c77ab9f1b04b4fa81396b3bd53d217a3d424d3","src/back/hlsl/help.rs":"9ee290466c4d27ee565dc7fe3dc9ec79e7aa498790fe345dcf1d09e6e80cfdcf","src/back/hlsl/keywords.rs":"a7164690a4da866e6bfb18ced20e32cc8c42dd7387e0e84addf0c2674f529cf5","src/back/hlsl/mod.rs":"09ea1c58f0c25938935747ad5a5a94dc9643038193f01269a5c4c30f19d7669a","src/back/hlsl/storage.rs":"2c2a0071cafe487a398e396dddc85bdb319b1a5d74c097d529078e247a904359","src/back/hlsl/writer.rs":"8aa5a3916f8f4c4fb69e048102681563fa2de06ff449c1802ac3535b10b4163c","src/back/mod.rs":"de0579806ca2b341a77725defd56d5e8758ec921e48344affaffc0656d67b84f","src/back/msl/keywords.rs":"e6a4ef77363f995de1f8079c0b8591497cbf9520c5d3b2d41c7e1f483e8abd24","src/back/msl/mod.rs":"1edba5f84857b0fbd3abf0eee56c7d5cf42b54bcea7e549428ff3ec2df1f70e0","src/back/msl/sampler.rs":"9b01d68669e12ff7123243284b85e1a9d2c4d49140bd74ca32dedc007cbf15af","src/back/msl/writer.rs":"205ed801d6ebde745dc1f9cab9d5eb321d784e8b7beeb771419a8546fb647269","src/back/pipeline_constants.rs":"ffb1817d2fa1356f73798bce9baf739fcf7f82a98935a8370f279db06310d1a1","src/back/spv/block.rs":"5229b297df23fc99897d3f387604c61268532cc6f89a61a27124ff06d6b93c62","src/back/spv/helpers.rs":"bd666bf519a5d5561c2fab6ff78229739853ae6877d132911e71b57cfd656e42","src/back/spv/image.rs":"e4b982ce430e17881d6370191d849dbe6bb8f6d86f4896815eb1736e43b4e302","src/back/spv/index.rs":"54bb90176be12a9a243099343e62b8dd35dd019d237d4d7dcdb9f0da7747df09","src/back/spv/instructions.rs":"105e38c29889b9b2be7edd7dd228246a91189a829eab7afc18ba92337401213f","src/back/spv/layout.rs":"e263de53cd2f9a03ad94b82b434ce636609bc1ed435a2d1132951663bfaa8ebd","src/back/spv/mod.rs":"c00fb2089bee377bb892b7bd51fcccf64380f3a197152a087cf8918352278b4b","src/back/spv/ray.rs":"a34bf6b26d873f7270caa45841d9ef291aca8d9732ecd086b14d8856038e1e41","src/back/spv/recyclable.rs":"114db0ea12774d6514f995d07295cb9a42631ab75165fc60980c10e9b5ecb832","src/back/spv/selection.rs":"81e404abfa0a977f7c1f76ccb37a78d13ccadbda229048dad53cc67687cc39db","src/back/spv/subgroup.rs":"cb68fb9581064ec9ef79e56a0c94c802b2f04cc5e2173a953ae9a7b2776042d5","src/back/spv/writer.rs":"04305d6b5b2047af2026bb0f93cd9bc8ed09cdf25a233692b38314e436c36737","src/back/wgsl/mod.rs":"2dd12bbea9ace835850192bb68c5760953da6bac6a636073d1eca19381c0c0b6","src/back/wgsl/writer.rs":"718dd8695a6630a66989b507fb0deddcceb3d229872e4eb3e605d945ac9e24fa","src/block.rs":"e447f7e041fd67052b23d1139cf0574eea93220a818af71691d960bdf026d45f","src/compact/expressions.rs":"6d876dfbaf7d6ce6e66d4ec4ef6cb783455cc85cc67b30991e975b2f52f2b843","src/compact/functions.rs":"e10945ca13aa0bb556cd675be31c85e1ac3698293e79b8c5e1a984bbd6fda800","src/compact/handle_set_map.rs":"817c5193352d5fd6a61a5c970daba23224e14a65aea15f8f1c8679c99f834ca2","src/compact/mod.rs":"f03f1876f14c111757152de8661497593cff23a4a638e441d2201c8383698ef5","src/compact/statements.rs":"4c12ab531f9aa696bd662b44e3834a6e2b151dd1859f960eba6f4c2cec3b793a","src/compact/types.rs":"18343f2ca2c123eea2531cffc1d54a7798797caccecaa1f9b8c4fd5dd6ca1a05","src/error.rs":"588e0ca123e8923d3bb3392e6b46f2386122c21f7a487ab2bfb458c72a52a0f1","src/front/glsl/ast.rs":"a4615f0c52b0dc9fdb07f816b4534c1ca547c2d176008ca86d66f9e6874f227d","src/front/glsl/builtins.rs":"d35501d5b42b61c261da24436b82eafdf96371b1600d148648d90d041f736ae4","src/front/glsl/context.rs":"e82bc54d0bf7bc65b70e2caf298374eed591fd181170c2ee5a35f96b6349dff0","src/front/glsl/error.rs":"ec74419598635e818f70f4080eadfaa3b499202affff3aed437e59c4451f9224","src/front/glsl/functions.rs":"3ff5b5ad5707146fa50c517329414cf8f63ec5cb28e481db07120e88986a78c9","src/front/glsl/lex.rs":"08736ae8beb955da5b0e6e3e0f45995a824995f7096d516a2910417e9c7afa32","src/front/glsl/mod.rs":"bf97bf1710d5d1f8facb77913cb82868697920914a96ed309adf0f19154a2ab4","src/front/glsl/offset.rs":"9358602ca4f9ef21d5066d674dae757bf88fdf5c289c4360534354d13bd41dc0","src/front/glsl/parser.rs":"a752f2abac17e6d35c0eb406f2f1c24d2b622a55b1bececbdd13614edb686622","src/front/glsl/parser/declarations.rs":"796514c1d571b324817bf1236d4c1227a91a512c0660ce5bb1264cd900027158","src/front/glsl/parser/expressions.rs":"520cfc9402d5fbd48e52ef1d36562c6b74794c09ec33ec1ebb10aa48d129b66f","src/front/glsl/parser/functions.rs":"d7d25be7790213dd358080b52355b06e2d286c37c301fa1ad16e35bc301492c4","src/front/glsl/parser/types.rs":"aeb97e1a5fb03205cd5630c29da59d81a376ce9a83a603b62b037e63ad948e88","src/front/glsl/parser_tests.rs":"c44ed3252096c83a0ce1ea9be8d2b867784cdc1c11aa4501aee1a85d86c62511","src/front/glsl/token.rs":"c25c489b152ee2d445ace3c2046473abe64d558b8d27fa08709110e58718b6ac","src/front/glsl/types.rs":"91c3a4e4d11b397ea647ff287e17a48baedf2f2c310e81b04618675daeb83f69","src/front/glsl/variables.rs":"dbab566eb24c2efb97d1b036e05be7f42619feab837ea01e872a7c389186e9ca","src/front/interpolator.rs":"9b6ca498d5fbd9bc1515510a04e303a00b324121d7285da3c955cfe18eb4224c","src/front/mod.rs":"77acd7fb71d004969d1ee69fc728647f03242762988786c4e15fadf8315600af","src/front/spv/convert.rs":"b52ffba12a51b2f2f3cf0098b8451daa8db61c6b8b5194ba4d7d8cd3bc521a42","src/front/spv/error.rs":"d1f9e8b3cf34a436e0c2793ce1446617d0de77739f9d668fd08a313dd23d7ffd","src/front/spv/function.rs":"6254b4d600a52cf8ded6f19718d8fbcbef4b44ffe860059ce51b1a6fecc28406","src/front/spv/image.rs":"a5ac477c01894a9c9ce5ec9d6751f991622d610f5581a759fc2e72034677d9e4","src/front/spv/mod.rs":"c211f4c8dc838dbcde8240d1e606ea9b8b0a95f31f212197cf63e9f6f29b1e8c","src/front/spv/null.rs":"a8ff44e97ffe42a4773d89b88fdb3a8ef8fba58bf6645c73b7a66470234ccf10","src/front/type_gen.rs":"b4f1df23380e06c9fdad4140810ce96ab041dbb1d371a07045b4e0069aa8ba55","src/front/wgsl/error.rs":"8554557ff38abf04a05bf32e9ee7935c36564b8555dfc43b4eb3fcdfa8a991ac","src/front/wgsl/index.rs":"c5928ac405ffbd74de60b96360f7e07a3470b39f8f76c6e0b06544b4b5f61f57","src/front/wgsl/lower/construction.rs":"92342e27f5bdeb598e178799b74aa610788549c19a49fe0ae8914916bfa3c7be","src/front/wgsl/lower/conversion.rs":"961b19bf8ddd4667c6caf854a1889f3d6477757f4125538c3e9ca7d730975dd7","src/front/wgsl/lower/mod.rs":"e1bc9d1312cbe98607aea0f79b85a944faad0b6fa46dd565c271e6d4f5be504e","src/front/wgsl/mod.rs":"cebe3f61843cca32d6764b93b07cb369ae22d1240d81eabe25f5c42dc603fca1","src/front/wgsl/parse/ast.rs":"31d10aaf229b2e40d690d9fe50481d4f8c8edffd07356e344597a6ea2e3bd1d8","src/front/wgsl/parse/conv.rs":"e9bde6f186278475f35e8808bcdc5bb760e2fd26d8df054e69f81a840b3d346e","src/front/wgsl/parse/lexer.rs":"17db87d0017f8f9a80fa151b8545f04e1b40c4e5feef6197f4a117efa03488bf","src/front/wgsl/parse/mod.rs":"26e3119adbe142bf0ad313dd53873d87f783f46379a9e33368d3f2a29274ffc5","src/front/wgsl/parse/number.rs":"dafd3d8651cfa1389cb359d76d39bd689e54f8d5025aa23e06c6edd871369efd","src/front/wgsl/tests.rs":"7a0a083a5b66af8e7d4b1a02401b27f077eb72d07181b610693f35b11f107c6c","src/front/wgsl/to_wgsl.rs":"5bd13063bcb86682185b895892219ec3763cf3f06bcbf4c2dec261d23e7f9dac","src/keywords/mod.rs":"0138f3931f8af0b0a05174549d0fd2152945b027dc3febefc1bbd676581d2e45","src/keywords/wgsl.rs":"c648ac44241ad55c8c8bad3d8f1bab973d11ddb9c380dcca369b735ed3975309","src/lib.rs":"e2b808f5a1d0173e18f130e1dbf8810db6fd22f8b2c228d31f7dd1f42749b0fb","src/proc/constant_evaluator.rs":"f8cf5aa74e6178ac694b5f600dc80b1dafa4b2db07eb484ea19a5ea8b5573d68","src/proc/emitter.rs":"39ac886c651e2ad33c06a676a7e4826a0e93de0af660c01e8e4b1f7406742f88","src/proc/index.rs":"ab083e3740d6e9e0d1abd9db32498d16ebc564587b589962b7056b059b220eff","src/proc/layouter.rs":"b3d061c87424f36981c902716f37ab7b72f2bb2d0c2d7e900c51149318ea1a0a","src/proc/mod.rs":"df786d2602d4a7c3e3780b066cadef9ac0f0c2cc4c28c903b8673f9ad33931cf","src/proc/namer.rs":"7328fac41e40890c64c7ee2fa985a4395424f18b08d30f30ca2583fdabd2fd35","src/proc/terminator.rs":"fef2160473fcddd670c6b5806a8ea0ecbdcc0fdf6ed793dce131ecd08cce3944","src/proc/typifier.rs":"493664b4396353470b10ae82f9a92932066a02925eb97324401aac1d19d9e97e","src/span.rs":"fd3b338256f9301fc5289c37af9ccec704d2e5db92923b0dec45da371e84ce6a","src/valid/analyzer.rs":"fdd84e34adfc2f77868bfb74bf3df12eb0dbfa32d13e5997232c28d06c9fd09e","src/valid/compose.rs":"83e4c09c39f853cf085b83b87e48b3db571da619132960d3ec954ebdfb0a74f2","src/valid/expression.rs":"149efe7d0958df6272361b79bbc62715f0a7041f13fa9e736d066d727f4c5aa2","src/valid/function.rs":"1dec6a302a070c3d16e91f45e07c2cf37c3af4dc138acf7411bcebdf4930a42a","src/valid/handles.rs":"dfdb1cdd54b751a930f873ebeb8f71fae8a13fe644a25a750d5c1eec27fa1a8f","src/valid/interface.rs":"a668d727178292dd0ce25d824b61a00e855a03045532fb6b9380178813c4130a","src/valid/mod.rs":"a0db031aec6fd9b5f31fc90e067b27f7b884ae4bbbfff988bf694c1261ec1b46","src/valid/type.rs":"6c192dc3517656daf330da74ad1e85bc5a1d371e0cb3f323de2bc177239f1636"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/naga/Cargo.toml b/third_party/rust/naga/Cargo.toml
index 04375a9960..f645cc53f4 100644
--- a/third_party/rust/naga/Cargo.toml
+++ b/third_party/rust/naga/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.74"
name = "naga"
-version = "0.19.0"
+version = "0.20.0"
authors = ["gfx-rs developers"]
exclude = [
"bin/**/*",
@@ -48,11 +48,11 @@ harness = false
[dependencies]
arrayvec = "0.7"
bit-set = "0.5"
-bitflags = "2.4"
+bitflags = "2.5"
log = "0.4"
num-traits = "0.2"
rustc-hash = "1.1.0"
-thiserror = "1.0.57"
+thiserror = "1.0.59"
[dependencies.arbitrary]
version = "1.3"
@@ -79,7 +79,7 @@ version = "0.2.1"
optional = true
[dependencies.serde]
-version = "1.0.196"
+version = "1.0.198"
features = ["derive"]
optional = true
@@ -122,7 +122,6 @@ arbitrary = [
"bitflags/arbitrary",
"indexmap/arbitrary",
]
-clone = []
compact = []
default = []
deserialize = [
diff --git a/third_party/rust/naga/src/arena.rs b/third_party/rust/naga/src/arena.rs
index c37538667f..740df85b86 100644
--- a/third_party/rust/naga/src/arena.rs
+++ b/third_party/rust/naga/src/arena.rs
@@ -122,6 +122,7 @@ impl<T> Handle<T> {
serde(transparent)
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
+#[cfg_attr(test, derive(PartialEq))]
pub struct Range<T> {
inner: ops::Range<u32>,
#[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))]
@@ -140,6 +141,7 @@ impl<T> Range<T> {
// NOTE: Keep this diagnostic in sync with that of [`BadHandle`].
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
#[error("Handle range {range:?} of {kind} is either not present, or inaccessible yet")]
pub struct BadRangeError {
// This error is used for many `Handle` types, but there's no point in making this generic, so
@@ -239,7 +241,7 @@ impl<T> Range<T> {
/// Adding new items to the arena produces a strongly-typed [`Handle`].
/// The arena can be indexed using the given handle to obtain
/// a reference to the stored item.
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "serialize", serde(transparent))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
@@ -297,6 +299,17 @@ impl<T> Arena<T> {
.map(|(i, v)| unsafe { (Handle::from_usize_unchecked(i), v) })
}
+ /// Drains the arena, returning an iterator over the items stored.
+ pub fn drain(&mut self) -> impl DoubleEndedIterator<Item = (Handle<T>, T, Span)> {
+ let arena = std::mem::take(self);
+ arena
+ .data
+ .into_iter()
+ .zip(arena.span_info)
+ .enumerate()
+ .map(|(i, (v, span))| unsafe { (Handle::from_usize_unchecked(i), v, span) })
+ }
+
/// Returns a iterator over the items stored in this arena,
/// returning both the item's handle and a mutable reference to it.
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (Handle<T>, &mut T)> {
@@ -531,7 +544,7 @@ mod tests {
///
/// `UniqueArena` is similar to [`Arena`]: If `Arena` is vector-like,
/// `UniqueArena` is `HashSet`-like.
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Clone)]
pub struct UniqueArena<T> {
set: FastIndexSet<T>,
diff --git a/third_party/rust/naga/src/back/dot/mod.rs b/third_party/rust/naga/src/back/dot/mod.rs
index 1556371df1..9a7702b3f6 100644
--- a/third_party/rust/naga/src/back/dot/mod.rs
+++ b/third_party/rust/naga/src/back/dot/mod.rs
@@ -279,6 +279,94 @@ impl StatementGraph {
crate::RayQueryFunction::Terminate => "RayQueryTerminate",
}
}
+ S::SubgroupBallot { result, predicate } => {
+ if let Some(predicate) = predicate {
+ self.dependencies.push((id, predicate, "predicate"));
+ }
+ self.emits.push((id, result));
+ "SubgroupBallot"
+ }
+ S::SubgroupCollectiveOperation {
+ op,
+ collective_op,
+ argument,
+ result,
+ } => {
+ self.dependencies.push((id, argument, "arg"));
+ self.emits.push((id, result));
+ match (collective_op, op) {
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::All) => {
+ "SubgroupAll"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Any) => {
+ "SubgroupAny"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Add) => {
+ "SubgroupAdd"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Mul) => {
+ "SubgroupMul"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Max) => {
+ "SubgroupMax"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Min) => {
+ "SubgroupMin"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::And) => {
+ "SubgroupAnd"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Or) => {
+ "SubgroupOr"
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Xor) => {
+ "SubgroupXor"
+ }
+ (
+ crate::CollectiveOperation::ExclusiveScan,
+ crate::SubgroupOperation::Add,
+ ) => "SubgroupExclusiveAdd",
+ (
+ crate::CollectiveOperation::ExclusiveScan,
+ crate::SubgroupOperation::Mul,
+ ) => "SubgroupExclusiveMul",
+ (
+ crate::CollectiveOperation::InclusiveScan,
+ crate::SubgroupOperation::Add,
+ ) => "SubgroupInclusiveAdd",
+ (
+ crate::CollectiveOperation::InclusiveScan,
+ crate::SubgroupOperation::Mul,
+ ) => "SubgroupInclusiveMul",
+ _ => unimplemented!(),
+ }
+ }
+ S::SubgroupGather {
+ mode,
+ argument,
+ result,
+ } => {
+ match mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ self.dependencies.push((id, index, "index"))
+ }
+ }
+ self.dependencies.push((id, argument, "arg"));
+ self.emits.push((id, result));
+ match mode {
+ crate::GatherMode::BroadcastFirst => "SubgroupBroadcastFirst",
+ crate::GatherMode::Broadcast(_) => "SubgroupBroadcast",
+ crate::GatherMode::Shuffle(_) => "SubgroupShuffle",
+ crate::GatherMode::ShuffleDown(_) => "SubgroupShuffleDown",
+ crate::GatherMode::ShuffleUp(_) => "SubgroupShuffleUp",
+ crate::GatherMode::ShuffleXor(_) => "SubgroupShuffleXor",
+ }
+ }
};
// Set the last node to the merge node
last_node = merge_id;
@@ -404,6 +492,7 @@ fn write_function_expressions(
let (label, color_id) = match *expression {
E::Literal(_) => ("Literal".into(), 2),
E::Constant(_) => ("Constant".into(), 2),
+ E::Override(_) => ("Override".into(), 2),
E::ZeroValue(_) => ("ZeroValue".into(), 2),
E::Compose { ref components, .. } => {
payload = Some(Payload::Arguments(components));
@@ -586,6 +675,8 @@ fn write_function_expressions(
let ty = if committed { "Committed" } else { "Candidate" };
(format!("rayQueryGet{}Intersection", ty).into(), 4)
}
+ E::SubgroupBallotResult => ("SubgroupBallotResult".into(), 4),
+ E::SubgroupOperationResult { .. } => ("SubgroupOperationResult".into(), 4),
};
// give uniform expressions an outline
diff --git a/third_party/rust/naga/src/back/glsl/features.rs b/third_party/rust/naga/src/back/glsl/features.rs
index 99c128c6d9..e5a43f3e02 100644
--- a/third_party/rust/naga/src/back/glsl/features.rs
+++ b/third_party/rust/naga/src/back/glsl/features.rs
@@ -50,6 +50,8 @@ bitflags::bitflags! {
const INSTANCE_INDEX = 1 << 22;
/// Sample specific LODs of cube / array shadow textures
const TEXTURE_SHADOW_LOD = 1 << 23;
+ /// Subgroup operations
+ const SUBGROUP_OPERATIONS = 1 << 24;
}
}
@@ -117,6 +119,7 @@ impl FeaturesManager {
check_feature!(SAMPLE_VARIABLES, 400, 300);
check_feature!(DYNAMIC_ARRAY_SIZE, 430, 310);
check_feature!(DUAL_SOURCE_BLENDING, 330, 300 /* with extension */);
+ check_feature!(SUBGROUP_OPERATIONS, 430, 310);
match version {
Version::Embedded { is_webgl: true, .. } => check_feature!(MULTI_VIEW, 140, 300),
_ => check_feature!(MULTI_VIEW, 140, 310),
@@ -259,6 +262,22 @@ impl FeaturesManager {
writeln!(out, "#extension GL_EXT_texture_shadow_lod : require")?;
}
+ if self.0.contains(Features::SUBGROUP_OPERATIONS) {
+ // https://registry.khronos.org/OpenGL/extensions/KHR/KHR_shader_subgroup.txt
+ writeln!(out, "#extension GL_KHR_shader_subgroup_basic : require")?;
+ writeln!(out, "#extension GL_KHR_shader_subgroup_vote : require")?;
+ writeln!(
+ out,
+ "#extension GL_KHR_shader_subgroup_arithmetic : require"
+ )?;
+ writeln!(out, "#extension GL_KHR_shader_subgroup_ballot : require")?;
+ writeln!(out, "#extension GL_KHR_shader_subgroup_shuffle : require")?;
+ writeln!(
+ out,
+ "#extension GL_KHR_shader_subgroup_shuffle_relative : require"
+ )?;
+ }
+
Ok(())
}
}
@@ -518,6 +537,10 @@ impl<'a, W> Writer<'a, W> {
}
}
}
+ Expression::SubgroupBallotResult |
+ Expression::SubgroupOperationResult { .. } => {
+ features.request(Features::SUBGROUP_OPERATIONS)
+ }
_ => {}
}
}
diff --git a/third_party/rust/naga/src/back/glsl/mod.rs b/third_party/rust/naga/src/back/glsl/mod.rs
index 9bda594610..c8c7ea557d 100644
--- a/third_party/rust/naga/src/back/glsl/mod.rs
+++ b/third_party/rust/naga/src/back/glsl/mod.rs
@@ -282,7 +282,7 @@ impl Default for Options {
}
/// A subset of options meant to be changed per pipeline.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct PipelineOptions {
@@ -497,6 +497,8 @@ pub enum Error {
ImageMultipleSamplers,
#[error("{0}")]
Custom(String),
+ #[error("overrides should not be present at this stage")]
+ Override,
}
/// Binary operation with a different logic on the GLSL side.
@@ -565,6 +567,10 @@ impl<'a, W: Write> Writer<'a, W> {
pipeline_options: &'a PipelineOptions,
policies: proc::BoundsCheckPolicies,
) -> Result<Self, Error> {
+ if !module.overrides.is_empty() {
+ return Err(Error::Override);
+ }
+
// Check if the requested version is supported
if !options.version.is_supported() {
log::error!("Version {}", options.version);
@@ -2384,6 +2390,125 @@ impl<'a, W: Write> Writer<'a, W> {
writeln!(self.out, ");")?;
}
Statement::RayQuery { .. } => unreachable!(),
+ Statement::SubgroupBallot { result, predicate } => {
+ write!(self.out, "{level}")?;
+ let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ let res_ty = ctx.info[result].ty.inner_with(&self.module.types);
+ self.write_value_type(res_ty)?;
+ write!(self.out, " {res_name} = ")?;
+ self.named_expressions.insert(result, res_name);
+
+ write!(self.out, "subgroupBallot(")?;
+ match predicate {
+ Some(predicate) => self.write_expr(predicate, ctx)?,
+ None => write!(self.out, "true")?,
+ }
+ writeln!(self.out, ");")?;
+ }
+ Statement::SubgroupCollectiveOperation {
+ op,
+ collective_op,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ let res_ty = ctx.info[result].ty.inner_with(&self.module.types);
+ self.write_value_type(res_ty)?;
+ write!(self.out, " {res_name} = ")?;
+ self.named_expressions.insert(result, res_name);
+
+ match (collective_op, op) {
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::All) => {
+ write!(self.out, "subgroupAll(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Any) => {
+ write!(self.out, "subgroupAny(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Add) => {
+ write!(self.out, "subgroupAdd(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "subgroupMul(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Max) => {
+ write!(self.out, "subgroupMax(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Min) => {
+ write!(self.out, "subgroupMin(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::And) => {
+ write!(self.out, "subgroupAnd(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Or) => {
+ write!(self.out, "subgroupOr(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Xor) => {
+ write!(self.out, "subgroupXor(")?
+ }
+ (crate::CollectiveOperation::ExclusiveScan, crate::SubgroupOperation::Add) => {
+ write!(self.out, "subgroupExclusiveAdd(")?
+ }
+ (crate::CollectiveOperation::ExclusiveScan, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "subgroupExclusiveMul(")?
+ }
+ (crate::CollectiveOperation::InclusiveScan, crate::SubgroupOperation::Add) => {
+ write!(self.out, "subgroupInclusiveAdd(")?
+ }
+ (crate::CollectiveOperation::InclusiveScan, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "subgroupInclusiveMul(")?
+ }
+ _ => unimplemented!(),
+ }
+ self.write_expr(argument, ctx)?;
+ writeln!(self.out, ");")?;
+ }
+ Statement::SubgroupGather {
+ mode,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ let res_ty = ctx.info[result].ty.inner_with(&self.module.types);
+ self.write_value_type(res_ty)?;
+ write!(self.out, " {res_name} = ")?;
+ self.named_expressions.insert(result, res_name);
+
+ match mode {
+ crate::GatherMode::BroadcastFirst => {
+ write!(self.out, "subgroupBroadcastFirst(")?;
+ }
+ crate::GatherMode::Broadcast(_) => {
+ write!(self.out, "subgroupBroadcast(")?;
+ }
+ crate::GatherMode::Shuffle(_) => {
+ write!(self.out, "subgroupShuffle(")?;
+ }
+ crate::GatherMode::ShuffleDown(_) => {
+ write!(self.out, "subgroupShuffleDown(")?;
+ }
+ crate::GatherMode::ShuffleUp(_) => {
+ write!(self.out, "subgroupShuffleUp(")?;
+ }
+ crate::GatherMode::ShuffleXor(_) => {
+ write!(self.out, "subgroupShuffleXor(")?;
+ }
+ }
+ self.write_expr(argument, ctx)?;
+ match mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ write!(self.out, ", ")?;
+ self.write_expr(index, ctx)?;
+ }
+ }
+ writeln!(self.out, ");")?;
+ }
}
Ok(())
@@ -2402,7 +2527,7 @@ impl<'a, W: Write> Writer<'a, W> {
fn write_const_expr(&mut self, expr: Handle<crate::Expression>) -> BackendResult {
self.write_possibly_const_expr(
expr,
- &self.module.const_expressions,
+ &self.module.global_expressions,
|expr| &self.info[expr],
|writer, expr| writer.write_const_expr(expr),
)
@@ -2536,6 +2661,7 @@ impl<'a, W: Write> Writer<'a, W> {
|writer, expr| writer.write_expr(expr, ctx),
)?;
}
+ Expression::Override(_) => return Err(Error::Override),
// `Access` is applied to arrays, vectors and matrices and is written as indexing
Expression::Access { base, index } => {
self.write_expr(base, ctx)?;
@@ -3411,7 +3537,8 @@ impl<'a, W: Write> Writer<'a, W> {
let scalar_bits = ctx
.resolve_type(arg, &self.module.types)
.scalar_width()
- .unwrap();
+ .unwrap()
+ * 8;
write!(self.out, "bitfieldExtract(")?;
self.write_expr(arg, ctx)?;
@@ -3430,7 +3557,8 @@ impl<'a, W: Write> Writer<'a, W> {
let scalar_bits = ctx
.resolve_type(arg, &self.module.types)
.scalar_width()
- .unwrap();
+ .unwrap()
+ * 8;
write!(self.out, "bitfieldInsert(")?;
self.write_expr(arg, ctx)?;
@@ -3649,7 +3777,9 @@ impl<'a, W: Write> Writer<'a, W> {
Expression::CallResult(_)
| Expression::AtomicResult { .. }
| Expression::RayQueryProceedResult
- | Expression::WorkGroupUniformLoadResult { .. } => unreachable!(),
+ | Expression::WorkGroupUniformLoadResult { .. }
+ | Expression::SubgroupOperationResult { .. }
+ | Expression::SubgroupBallotResult => unreachable!(),
// `ArrayLength` is written as `expr.length()` and we convert it to a uint
Expression::ArrayLength(expr) => {
write!(self.out, "uint(")?;
@@ -4218,6 +4348,9 @@ impl<'a, W: Write> Writer<'a, W> {
if flags.contains(crate::Barrier::WORK_GROUP) {
writeln!(self.out, "{level}memoryBarrierShared();")?;
}
+ if flags.contains(crate::Barrier::SUB_GROUP) {
+ writeln!(self.out, "{level}subgroupMemoryBarrier();")?;
+ }
writeln!(self.out, "{level}barrier();")?;
Ok(())
}
@@ -4487,6 +4620,11 @@ const fn glsl_built_in(built_in: crate::BuiltIn, options: VaryingOptions) -> &'s
Bi::WorkGroupId => "gl_WorkGroupID",
Bi::WorkGroupSize => "gl_WorkGroupSize",
Bi::NumWorkGroups => "gl_NumWorkGroups",
+ // subgroup
+ Bi::NumSubgroups => "gl_NumSubgroups",
+ Bi::SubgroupId => "gl_SubgroupID",
+ Bi::SubgroupSize => "gl_SubgroupSize",
+ Bi::SubgroupInvocationId => "gl_SubgroupInvocationID",
}
}
diff --git a/third_party/rust/naga/src/back/hlsl/conv.rs b/third_party/rust/naga/src/back/hlsl/conv.rs
index 2a6db35db8..7d15f43f6c 100644
--- a/third_party/rust/naga/src/back/hlsl/conv.rs
+++ b/third_party/rust/naga/src/back/hlsl/conv.rs
@@ -179,6 +179,11 @@ impl crate::BuiltIn {
// to this field will get replaced with references to `SPECIAL_CBUF_VAR`
// in `Writer::write_expr`.
Self::NumWorkGroups => "SV_GroupID",
+ // These builtins map to functions
+ Self::SubgroupSize
+ | Self::SubgroupInvocationId
+ | Self::NumSubgroups
+ | Self::SubgroupId => unreachable!(),
Self::BaseInstance | Self::BaseVertex | Self::WorkGroupSize => {
return Err(Error::Unimplemented(format!("builtin {self:?}")))
}
diff --git a/third_party/rust/naga/src/back/hlsl/help.rs b/third_party/rust/naga/src/back/hlsl/help.rs
index 4dd9ea5987..d3bb1ce7f5 100644
--- a/third_party/rust/naga/src/back/hlsl/help.rs
+++ b/third_party/rust/naga/src/back/hlsl/help.rs
@@ -70,6 +70,11 @@ pub(super) struct WrappedMath {
pub(super) components: Option<u32>,
}
+#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
+pub(super) struct WrappedZeroValue {
+ pub(super) ty: Handle<crate::Type>,
+}
+
/// HLSL backend requires its own `ImageQuery` enum.
///
/// It is used inside `WrappedImageQuery` and should be unique per ImageQuery function.
@@ -359,7 +364,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
}
/// Helper function that write wrapped function for `Expression::Compose` for structures.
- pub(super) fn write_wrapped_constructor_function(
+ fn write_wrapped_constructor_function(
&mut self,
module: &crate::Module,
constructor: WrappedConstructor,
@@ -862,6 +867,25 @@ impl<'a, W: Write> super::Writer<'a, W> {
Ok(())
}
+ // TODO: we could merge this with iteration in write_wrapped_compose_functions...
+ //
+ /// Helper function that writes zero value wrapped functions
+ pub(super) fn write_wrapped_zero_value_functions(
+ &mut self,
+ module: &crate::Module,
+ expressions: &crate::Arena<crate::Expression>,
+ ) -> BackendResult {
+ for (handle, _) in expressions.iter() {
+ if let crate::Expression::ZeroValue(ty) = expressions[handle] {
+ let zero_value = WrappedZeroValue { ty };
+ if self.wrapped.zero_values.insert(zero_value) {
+ self.write_wrapped_zero_value_function(module, zero_value)?;
+ }
+ }
+ }
+ Ok(())
+ }
+
pub(super) fn write_wrapped_math_functions(
&mut self,
module: &crate::Module,
@@ -1006,6 +1030,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
) -> BackendResult {
self.write_wrapped_math_functions(module, func_ctx)?;
self.write_wrapped_compose_functions(module, func_ctx.expressions)?;
+ self.write_wrapped_zero_value_functions(module, func_ctx.expressions)?;
for (handle, _) in func_ctx.expressions.iter() {
match func_ctx.expressions[handle] {
@@ -1283,4 +1308,71 @@ impl<'a, W: Write> super::Writer<'a, W> {
Ok(())
}
+
+ pub(super) fn write_wrapped_zero_value_function_name(
+ &mut self,
+ module: &crate::Module,
+ zero_value: WrappedZeroValue,
+ ) -> BackendResult {
+ let name = crate::TypeInner::hlsl_type_id(zero_value.ty, module.to_ctx(), &self.names)?;
+ write!(self.out, "ZeroValue{name}")?;
+ Ok(())
+ }
+
+ /// Helper function that write wrapped function for `Expression::ZeroValue`
+ ///
+ /// This is necessary since we might have a member access after the zero value expression, e.g.
+ /// `.y` (in practice this can come up when consuming SPIRV that's been produced by glslc).
+ ///
+ /// So we can't just write `(float4)0` since `(float4)0.y` won't parse correctly.
+ ///
+ /// Parenthesizing the expression like `((float4)0).y` would work... except DXC can't handle
+ /// cases like:
+ ///
+ /// ```ignore
+ /// tests\out\hlsl\access.hlsl:183:41: error: cannot compile this l-value expression yet
+ /// t_1.am = (__mat4x2[2])((float4x2[2])0);
+ /// ^
+ /// ```
+ fn write_wrapped_zero_value_function(
+ &mut self,
+ module: &crate::Module,
+ zero_value: WrappedZeroValue,
+ ) -> BackendResult {
+ use crate::back::INDENT;
+
+ const RETURN_VARIABLE_NAME: &str = "ret";
+
+ // Write function return type and name
+ if let crate::TypeInner::Array { base, size, .. } = module.types[zero_value.ty].inner {
+ write!(self.out, "typedef ")?;
+ self.write_type(module, zero_value.ty)?;
+ write!(self.out, " ret_")?;
+ self.write_wrapped_zero_value_function_name(module, zero_value)?;
+ self.write_array_size(module, base, size)?;
+ writeln!(self.out, ";")?;
+
+ write!(self.out, "ret_")?;
+ self.write_wrapped_zero_value_function_name(module, zero_value)?;
+ } else {
+ self.write_type(module, zero_value.ty)?;
+ }
+ write!(self.out, " ")?;
+ self.write_wrapped_zero_value_function_name(module, zero_value)?;
+
+ // Write function parameters (none) and start function body
+ writeln!(self.out, "() {{")?;
+
+ // Write `ZeroValue` function.
+ write!(self.out, "{INDENT}return ")?;
+ self.write_default_init(module, zero_value.ty)?;
+ writeln!(self.out, ";")?;
+
+ // End of function body
+ writeln!(self.out, "}}")?;
+ // Write extra new line
+ writeln!(self.out)?;
+
+ Ok(())
+ }
}
diff --git a/third_party/rust/naga/src/back/hlsl/mod.rs b/third_party/rust/naga/src/back/hlsl/mod.rs
index f37a223f47..28edbf70e1 100644
--- a/third_party/rust/naga/src/back/hlsl/mod.rs
+++ b/third_party/rust/naga/src/back/hlsl/mod.rs
@@ -131,6 +131,13 @@ pub enum ShaderModel {
V5_0,
V5_1,
V6_0,
+ V6_1,
+ V6_2,
+ V6_3,
+ V6_4,
+ V6_5,
+ V6_6,
+ V6_7,
}
impl ShaderModel {
@@ -139,6 +146,13 @@ impl ShaderModel {
Self::V5_0 => "5_0",
Self::V5_1 => "5_1",
Self::V6_0 => "6_0",
+ Self::V6_1 => "6_1",
+ Self::V6_2 => "6_2",
+ Self::V6_3 => "6_3",
+ Self::V6_4 => "6_4",
+ Self::V6_5 => "6_5",
+ Self::V6_6 => "6_6",
+ Self::V6_7 => "6_7",
}
}
}
@@ -247,10 +261,13 @@ pub enum Error {
Unimplemented(String), // TODO: Error used only during development
#[error("{0}")]
Custom(String),
+ #[error("overrides should not be present at this stage")]
+ Override,
}
#[derive(Default)]
struct Wrapped {
+ zero_values: crate::FastHashSet<help::WrappedZeroValue>,
array_lengths: crate::FastHashSet<help::WrappedArrayLength>,
image_queries: crate::FastHashSet<help::WrappedImageQuery>,
constructors: crate::FastHashSet<help::WrappedConstructor>,
diff --git a/third_party/rust/naga/src/back/hlsl/writer.rs b/third_party/rust/naga/src/back/hlsl/writer.rs
index 4ba856946b..86d8f89035 100644
--- a/third_party/rust/naga/src/back/hlsl/writer.rs
+++ b/third_party/rust/naga/src/back/hlsl/writer.rs
@@ -1,5 +1,8 @@
use super::{
- help::{WrappedArrayLength, WrappedConstructor, WrappedImageQuery, WrappedStructMatrixAccess},
+ help::{
+ WrappedArrayLength, WrappedConstructor, WrappedImageQuery, WrappedStructMatrixAccess,
+ WrappedZeroValue,
+ },
storage::StoreValue,
BackendResult, Error, Options,
};
@@ -77,6 +80,19 @@ enum Io {
Output,
}
+const fn is_subgroup_builtin_binding(binding: &Option<crate::Binding>) -> bool {
+ let &Some(crate::Binding::BuiltIn(builtin)) = binding else {
+ return false;
+ };
+ matches!(
+ builtin,
+ crate::BuiltIn::SubgroupSize
+ | crate::BuiltIn::SubgroupInvocationId
+ | crate::BuiltIn::NumSubgroups
+ | crate::BuiltIn::SubgroupId
+ )
+}
+
impl<'a, W: fmt::Write> super::Writer<'a, W> {
pub fn new(out: W, options: &'a Options) -> Self {
Self {
@@ -161,6 +177,19 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
}
}
+ for statement in func.body.iter() {
+ match *statement {
+ crate::Statement::SubgroupCollectiveOperation {
+ op: _,
+ collective_op: crate::CollectiveOperation::InclusiveScan,
+ argument,
+ result: _,
+ } => {
+ self.need_bake_expressions.insert(argument);
+ }
+ _ => {}
+ }
+ }
}
pub fn write(
@@ -168,6 +197,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
module: &Module,
module_info: &valid::ModuleInfo,
) -> Result<super::ReflectionInfo, Error> {
+ if !module.overrides.is_empty() {
+ return Err(Error::Override);
+ }
+
self.reset(module);
// Write special constants, if needed
@@ -233,7 +266,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
self.write_special_functions(module)?;
- self.write_wrapped_compose_functions(module, &module.const_expressions)?;
+ self.write_wrapped_compose_functions(module, &module.global_expressions)?;
+ self.write_wrapped_zero_value_functions(module, &module.global_expressions)?;
// Write all named constants
let mut constants = module
@@ -397,31 +431,32 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
// if they are struct, so that the `stage` argument here could be omitted.
fn write_semantic(
&mut self,
- binding: &crate::Binding,
+ binding: &Option<crate::Binding>,
stage: Option<(ShaderStage, Io)>,
) -> BackendResult {
match *binding {
- crate::Binding::BuiltIn(builtin) => {
+ Some(crate::Binding::BuiltIn(builtin)) if !is_subgroup_builtin_binding(binding) => {
let builtin_str = builtin.to_hlsl_str()?;
write!(self.out, " : {builtin_str}")?;
}
- crate::Binding::Location {
+ Some(crate::Binding::Location {
second_blend_source: true,
..
- } => {
+ }) => {
write!(self.out, " : SV_Target1")?;
}
- crate::Binding::Location {
+ Some(crate::Binding::Location {
location,
second_blend_source: false,
..
- } => {
+ }) => {
if stage == Some((crate::ShaderStage::Fragment, Io::Output)) {
write!(self.out, " : SV_Target{location}")?;
} else {
write!(self.out, " : {LOCATION_SEMANTIC}{location}")?;
}
}
+ _ => {}
}
Ok(())
@@ -442,17 +477,30 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(self.out, "struct {struct_name}")?;
writeln!(self.out, " {{")?;
for m in members.iter() {
+ if is_subgroup_builtin_binding(&m.binding) {
+ continue;
+ }
write!(self.out, "{}", back::INDENT)?;
if let Some(ref binding) = m.binding {
self.write_modifier(binding)?;
}
self.write_type(module, m.ty)?;
write!(self.out, " {}", &m.name)?;
- if let Some(ref binding) = m.binding {
- self.write_semantic(binding, Some(shader_stage))?;
- }
+ self.write_semantic(&m.binding, Some(shader_stage))?;
writeln!(self.out, ";")?;
}
+ if members.iter().any(|arg| {
+ matches!(
+ arg.binding,
+ Some(crate::Binding::BuiltIn(crate::BuiltIn::SubgroupId))
+ )
+ }) {
+ writeln!(
+ self.out,
+ "{}uint __local_invocation_index : SV_GroupIndex;",
+ back::INDENT
+ )?;
+ }
writeln!(self.out, "}};")?;
writeln!(self.out)?;
@@ -553,8 +601,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
/// Writes special interface structures for an entry point. The special structures have
- /// all the fields flattened into them and sorted by binding. They are only needed for
- /// VS outputs and FS inputs, so that these interfaces match.
+ /// all the fields flattened into them and sorted by binding. They are needed to emulate
+ /// subgroup built-ins and to make the interfaces between VS outputs and FS inputs match.
fn write_ep_interface(
&mut self,
module: &Module,
@@ -563,7 +611,13 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
ep_name: &str,
) -> Result<EntryPointInterface, Error> {
Ok(EntryPointInterface {
- input: if !func.arguments.is_empty() && stage == ShaderStage::Fragment {
+ input: if !func.arguments.is_empty()
+ && (stage == ShaderStage::Fragment
+ || func
+ .arguments
+ .iter()
+ .any(|arg| is_subgroup_builtin_binding(&arg.binding)))
+ {
Some(self.write_ep_input_struct(module, func, stage, ep_name)?)
} else {
None
@@ -577,6 +631,38 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
})
}
+ fn write_ep_argument_initialization(
+ &mut self,
+ ep: &crate::EntryPoint,
+ ep_input: &EntryPointBinding,
+ fake_member: &EpStructMember,
+ ) -> BackendResult {
+ match fake_member.binding {
+ Some(crate::Binding::BuiltIn(crate::BuiltIn::SubgroupSize)) => {
+ write!(self.out, "WaveGetLaneCount()")?
+ }
+ Some(crate::Binding::BuiltIn(crate::BuiltIn::SubgroupInvocationId)) => {
+ write!(self.out, "WaveGetLaneIndex()")?
+ }
+ Some(crate::Binding::BuiltIn(crate::BuiltIn::NumSubgroups)) => write!(
+ self.out,
+ "({}u + WaveGetLaneCount() - 1u) / WaveGetLaneCount()",
+ ep.workgroup_size[0] * ep.workgroup_size[1] * ep.workgroup_size[2]
+ )?,
+ Some(crate::Binding::BuiltIn(crate::BuiltIn::SubgroupId)) => {
+ write!(
+ self.out,
+ "{}.__local_invocation_index / WaveGetLaneCount()",
+ ep_input.arg_name
+ )?;
+ }
+ _ => {
+ write!(self.out, "{}.{}", ep_input.arg_name, fake_member.name)?;
+ }
+ }
+ Ok(())
+ }
+
/// Write an entry point preface that initializes the arguments as specified in IR.
fn write_ep_arguments_initialization(
&mut self,
@@ -584,6 +670,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
func: &crate::Function,
ep_index: u16,
) -> BackendResult {
+ let ep = &module.entry_points[ep_index as usize];
let ep_input = match self.entry_point_io[ep_index as usize].input.take() {
Some(ep_input) => ep_input,
None => return Ok(()),
@@ -597,8 +684,13 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
match module.types[arg.ty].inner {
TypeInner::Array { base, size, .. } => {
self.write_array_size(module, base, size)?;
- let fake_member = fake_iter.next().unwrap();
- writeln!(self.out, " = {}.{};", ep_input.arg_name, fake_member.name)?;
+ write!(self.out, " = ")?;
+ self.write_ep_argument_initialization(
+ ep,
+ &ep_input,
+ fake_iter.next().unwrap(),
+ )?;
+ writeln!(self.out, ";")?;
}
TypeInner::Struct { ref members, .. } => {
write!(self.out, " = {{ ")?;
@@ -606,14 +698,22 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
if index != 0 {
write!(self.out, ", ")?;
}
- let fake_member = fake_iter.next().unwrap();
- write!(self.out, "{}.{}", ep_input.arg_name, fake_member.name)?;
+ self.write_ep_argument_initialization(
+ ep,
+ &ep_input,
+ fake_iter.next().unwrap(),
+ )?;
}
writeln!(self.out, " }};")?;
}
_ => {
- let fake_member = fake_iter.next().unwrap();
- writeln!(self.out, " = {}.{};", ep_input.arg_name, fake_member.name)?;
+ write!(self.out, " = ")?;
+ self.write_ep_argument_initialization(
+ ep,
+ &ep_input,
+ fake_iter.next().unwrap(),
+ )?;
+ writeln!(self.out, ";")?;
}
}
}
@@ -928,9 +1028,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
}
- if let Some(ref binding) = member.binding {
- self.write_semantic(binding, shader_stage)?;
- };
+ self.write_semantic(&member.binding, shader_stage)?;
writeln!(self.out, ";")?;
}
@@ -1143,7 +1241,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
back::FunctionType::EntryPoint(ep_index) => {
if let Some(ref ep_input) = self.entry_point_io[ep_index as usize].input {
- write!(self.out, "{} {}", ep_input.ty_name, ep_input.arg_name,)?;
+ write!(self.out, "{} {}", ep_input.ty_name, ep_input.arg_name)?;
} else {
let stage = module.entry_points[ep_index as usize].stage;
for (index, arg) in func.arguments.iter().enumerate() {
@@ -1160,17 +1258,16 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
self.write_array_size(module, base, size)?;
}
- if let Some(ref binding) = arg.binding {
- self.write_semantic(binding, Some((stage, Io::Input)))?;
- }
+ self.write_semantic(&arg.binding, Some((stage, Io::Input)))?;
}
-
- if need_workgroup_variables_initialization {
- if !func.arguments.is_empty() {
- write!(self.out, ", ")?;
- }
- write!(self.out, "uint3 __local_invocation_id : SV_GroupThreadID")?;
+ }
+ if need_workgroup_variables_initialization {
+ if self.entry_point_io[ep_index as usize].input.is_some()
+ || !func.arguments.is_empty()
+ {
+ write!(self.out, ", ")?;
}
+ write!(self.out, "uint3 __local_invocation_id : SV_GroupThreadID")?;
}
}
}
@@ -1180,11 +1277,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
// Write semantic if it present
if let back::FunctionType::EntryPoint(index) = func_ctx.ty {
let stage = module.entry_points[index as usize].stage;
- if let Some(crate::FunctionResult {
- binding: Some(ref binding),
- ..
- }) = func.result
- {
+ if let Some(crate::FunctionResult { ref binding, .. }) = func.result {
self.write_semantic(binding, Some((stage, Io::Output)))?;
}
}
@@ -1984,6 +2077,129 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
writeln!(self.out, "{level}}}")?
}
Statement::RayQuery { .. } => unreachable!(),
+ Statement::SubgroupBallot { result, predicate } => {
+ write!(self.out, "{level}")?;
+ let name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ write!(self.out, "const uint4 {name} = ")?;
+ self.named_expressions.insert(result, name);
+
+ write!(self.out, "WaveActiveBallot(")?;
+ match predicate {
+ Some(predicate) => self.write_expr(module, predicate, func_ctx)?,
+ None => write!(self.out, "true")?,
+ }
+ writeln!(self.out, ");")?;
+ }
+ Statement::SubgroupCollectiveOperation {
+ op,
+ collective_op,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ write!(self.out, "const ")?;
+ let name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ match func_ctx.info[result].ty {
+ proc::TypeResolution::Handle(handle) => self.write_type(module, handle)?,
+ proc::TypeResolution::Value(ref value) => {
+ self.write_value_type(module, value)?
+ }
+ };
+ write!(self.out, " {name} = ")?;
+ self.named_expressions.insert(result, name);
+
+ match (collective_op, op) {
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::All) => {
+ write!(self.out, "WaveActiveAllTrue(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Any) => {
+ write!(self.out, "WaveActiveAnyTrue(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Add) => {
+ write!(self.out, "WaveActiveSum(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "WaveActiveProduct(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Max) => {
+ write!(self.out, "WaveActiveMax(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Min) => {
+ write!(self.out, "WaveActiveMin(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::And) => {
+ write!(self.out, "WaveActiveBitAnd(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Or) => {
+ write!(self.out, "WaveActiveBitOr(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Xor) => {
+ write!(self.out, "WaveActiveBitXor(")?
+ }
+ (crate::CollectiveOperation::ExclusiveScan, crate::SubgroupOperation::Add) => {
+ write!(self.out, "WavePrefixSum(")?
+ }
+ (crate::CollectiveOperation::ExclusiveScan, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "WavePrefixProduct(")?
+ }
+ (crate::CollectiveOperation::InclusiveScan, crate::SubgroupOperation::Add) => {
+ self.write_expr(module, argument, func_ctx)?;
+ write!(self.out, " + WavePrefixSum(")?;
+ }
+ (crate::CollectiveOperation::InclusiveScan, crate::SubgroupOperation::Mul) => {
+ self.write_expr(module, argument, func_ctx)?;
+ write!(self.out, " * WavePrefixProduct(")?;
+ }
+ _ => unimplemented!(),
+ }
+ self.write_expr(module, argument, func_ctx)?;
+ writeln!(self.out, ");")?;
+ }
+ Statement::SubgroupGather {
+ mode,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ write!(self.out, "const ")?;
+ let name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ match func_ctx.info[result].ty {
+ proc::TypeResolution::Handle(handle) => self.write_type(module, handle)?,
+ proc::TypeResolution::Value(ref value) => {
+ self.write_value_type(module, value)?
+ }
+ };
+ write!(self.out, " {name} = ")?;
+ self.named_expressions.insert(result, name);
+
+ if matches!(mode, crate::GatherMode::BroadcastFirst) {
+ write!(self.out, "WaveReadLaneFirst(")?;
+ self.write_expr(module, argument, func_ctx)?;
+ } else {
+ write!(self.out, "WaveReadLaneAt(")?;
+ self.write_expr(module, argument, func_ctx)?;
+ write!(self.out, ", ")?;
+ match mode {
+ crate::GatherMode::BroadcastFirst => unreachable!(),
+ crate::GatherMode::Broadcast(index) | crate::GatherMode::Shuffle(index) => {
+ self.write_expr(module, index, func_ctx)?;
+ }
+ crate::GatherMode::ShuffleDown(index) => {
+ write!(self.out, "WaveGetLaneIndex() + ")?;
+ self.write_expr(module, index, func_ctx)?;
+ }
+ crate::GatherMode::ShuffleUp(index) => {
+ write!(self.out, "WaveGetLaneIndex() - ")?;
+ self.write_expr(module, index, func_ctx)?;
+ }
+ crate::GatherMode::ShuffleXor(index) => {
+ write!(self.out, "WaveGetLaneIndex() ^ ")?;
+ self.write_expr(module, index, func_ctx)?;
+ }
+ }
+ }
+ writeln!(self.out, ");")?;
+ }
}
Ok(())
@@ -1997,7 +2213,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
self.write_possibly_const_expression(
module,
expr,
- &module.const_expressions,
+ &module.global_expressions,
|writer, expr| writer.write_const_expression(module, expr),
)
}
@@ -2039,7 +2255,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
self.write_const_expression(module, constant.init)?;
}
}
- Expression::ZeroValue(ty) => self.write_default_init(module, ty)?,
+ Expression::ZeroValue(ty) => {
+ self.write_wrapped_zero_value_function_name(module, WrappedZeroValue { ty })?;
+ write!(self.out, "()")?;
+ }
Expression::Compose { ty, ref components } => {
match module.types[ty].inner {
TypeInner::Struct { .. } | TypeInner::Array { .. } => {
@@ -2140,6 +2359,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|writer, expr| writer.write_expr(module, expr, func_ctx),
)?;
}
+ Expression::Override(_) => return Err(Error::Override),
// All of the multiplication can be expressed as `mul`,
// except vector * vector, which needs to use the "*" operator.
Expression::Binary {
@@ -2588,7 +2808,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
true
}
None => {
- if inner.scalar_width() == Some(64) {
+ if inner.scalar_width() == Some(8) {
false
} else {
write!(self.out, "{}(", kind.to_hlsl_cast(),)?;
@@ -3129,7 +3349,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
Expression::CallResult(_)
| Expression::AtomicResult { .. }
| Expression::WorkGroupUniformLoadResult { .. }
- | Expression::RayQueryProceedResult => {}
+ | Expression::RayQueryProceedResult
+ | Expression::SubgroupBallotResult
+ | Expression::SubgroupOperationResult { .. } => {}
}
if !closing_bracket.is_empty() {
@@ -3179,7 +3401,11 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
/// Helper function that write default zero initialization
- fn write_default_init(&mut self, module: &Module, ty: Handle<crate::Type>) -> BackendResult {
+ pub(super) fn write_default_init(
+ &mut self,
+ module: &Module,
+ ty: Handle<crate::Type>,
+ ) -> BackendResult {
write!(self.out, "(")?;
self.write_type(module, ty)?;
if let TypeInner::Array { base, size, .. } = module.types[ty].inner {
@@ -3196,6 +3422,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
if barrier.contains(crate::Barrier::WORK_GROUP) {
writeln!(self.out, "{level}GroupMemoryBarrierWithGroupSync();")?;
}
+ if barrier.contains(crate::Barrier::SUB_GROUP) {
+ // Does not exist in DirectX
+ }
Ok(())
}
}
diff --git a/third_party/rust/naga/src/back/mod.rs b/third_party/rust/naga/src/back/mod.rs
index c8f091decb..0c9c5e4761 100644
--- a/third_party/rust/naga/src/back/mod.rs
+++ b/third_party/rust/naga/src/back/mod.rs
@@ -16,6 +16,14 @@ pub mod spv;
#[cfg(feature = "wgsl-out")]
pub mod wgsl;
+#[cfg(any(
+ feature = "hlsl-out",
+ feature = "msl-out",
+ feature = "spv-out",
+ feature = "glsl-out"
+))]
+pub mod pipeline_constants;
+
/// Names of vector components.
pub const COMPONENTS: &[char] = &['x', 'y', 'z', 'w'];
/// Indent for backends.
@@ -26,6 +34,15 @@ pub const BAKE_PREFIX: &str = "_e";
/// Expressions that need baking.
pub type NeedBakeExpressions = crate::FastHashSet<crate::Handle<crate::Expression>>;
+/// Specifies the values of pipeline-overridable constants in the shader module.
+///
+/// If an `@id` attribute was specified on the declaration,
+/// the key must be the pipeline constant ID as a decimal ASCII number; if not,
+/// the key must be the constant's identifier name.
+///
+/// The value may represent any of WGSL's concrete scalar types.
+pub type PipelineConstants = std::collections::HashMap<String, f64>;
+
/// Indentation level.
#[derive(Clone, Copy)]
pub struct Level(pub usize);
diff --git a/third_party/rust/naga/src/back/msl/mod.rs b/third_party/rust/naga/src/back/msl/mod.rs
index 68e5b79906..8b03e20376 100644
--- a/third_party/rust/naga/src/back/msl/mod.rs
+++ b/third_party/rust/naga/src/back/msl/mod.rs
@@ -143,6 +143,8 @@ pub enum Error {
UnsupportedArrayOfType(Handle<crate::Type>),
#[error("ray tracing is not supported prior to MSL 2.3")]
UnsupportedRayTracing,
+ #[error("overrides should not be present at this stage")]
+ Override,
}
#[derive(Clone, Debug, PartialEq, thiserror::Error)]
@@ -221,7 +223,7 @@ impl Default for Options {
}
/// A subset of options that are meant to be changed per pipeline.
-#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct PipelineOptions {
@@ -434,6 +436,11 @@ impl ResolvedBinding {
Bi::WorkGroupId => "threadgroup_position_in_grid",
Bi::WorkGroupSize => "dispatch_threads_per_threadgroup",
Bi::NumWorkGroups => "threadgroups_per_grid",
+ // subgroup
+ Bi::NumSubgroups => "simdgroups_per_threadgroup",
+ Bi::SubgroupId => "simdgroup_index_in_threadgroup",
+ Bi::SubgroupSize => "threads_per_simdgroup",
+ Bi::SubgroupInvocationId => "thread_index_in_simdgroup",
Bi::CullDistance | Bi::ViewIndex => {
return Err(Error::UnsupportedBuiltIn(built_in))
}
@@ -536,3 +543,21 @@ fn test_error_size() {
use std::mem::size_of;
assert_eq!(size_of::<Error>(), 32);
}
+
+impl crate::AtomicFunction {
+ fn to_msl(self) -> Result<&'static str, Error> {
+ Ok(match self {
+ Self::Add => "fetch_add",
+ Self::Subtract => "fetch_sub",
+ Self::And => "fetch_and",
+ Self::InclusiveOr => "fetch_or",
+ Self::ExclusiveOr => "fetch_xor",
+ Self::Min => "fetch_min",
+ Self::Max => "fetch_max",
+ Self::Exchange { compare: None } => "exchange",
+ Self::Exchange { compare: Some(_) } => Err(Error::FeatureNotImplemented(
+ "atomic CompareExchange".to_string(),
+ ))?,
+ })
+ }
+}
diff --git a/third_party/rust/naga/src/back/msl/writer.rs b/third_party/rust/naga/src/back/msl/writer.rs
index 5227d8e7db..e250d0b72c 100644
--- a/third_party/rust/naga/src/back/msl/writer.rs
+++ b/third_party/rust/naga/src/back/msl/writer.rs
@@ -1131,21 +1131,10 @@ impl<W: Write> Writer<W> {
Ok(())
}
- fn put_atomic_fetch(
- &mut self,
- pointer: Handle<crate::Expression>,
- key: &str,
- value: Handle<crate::Expression>,
- context: &ExpressionContext,
- ) -> BackendResult {
- self.put_atomic_operation(pointer, "fetch_", key, value, context)
- }
-
fn put_atomic_operation(
&mut self,
pointer: Handle<crate::Expression>,
- key1: &str,
- key2: &str,
+ key: &str,
value: Handle<crate::Expression>,
context: &ExpressionContext,
) -> BackendResult {
@@ -1163,7 +1152,7 @@ impl<W: Write> Writer<W> {
write!(
self.out,
- "{NAMESPACE}::atomic_{key1}{key2}_explicit({ATOMIC_REFERENCE}"
+ "{NAMESPACE}::atomic_{key}_explicit({ATOMIC_REFERENCE}"
)?;
self.put_access_chain(pointer, policy, context)?;
write!(self.out, ", ")?;
@@ -1248,7 +1237,7 @@ impl<W: Write> Writer<W> {
) -> BackendResult {
self.put_possibly_const_expression(
expr_handle,
- &module.const_expressions,
+ &module.global_expressions,
module,
mod_info,
&(module, mod_info),
@@ -1431,6 +1420,7 @@ impl<W: Write> Writer<W> {
|writer, context, expr| writer.put_expression(expr, context, true),
)?;
}
+ crate::Expression::Override(_) => return Err(Error::Override),
crate::Expression::Access { base, .. }
| crate::Expression::AccessIndex { base, .. } => {
// This is an acceptable place to generate a `ReadZeroSkipWrite` check.
@@ -1944,7 +1934,7 @@ impl<W: Write> Writer<W> {
//
// extract_bits(e, min(offset, w), min(count, w - min(offset, w))))
- let scalar_bits = context.resolve_type(arg).scalar_width().unwrap();
+ let scalar_bits = context.resolve_type(arg).scalar_width().unwrap() * 8;
write!(self.out, "{NAMESPACE}::extract_bits(")?;
self.put_expression(arg, context, true)?;
@@ -1960,7 +1950,7 @@ impl<W: Write> Writer<W> {
//
// insertBits(e, newBits, min(offset, w), min(count, w - min(offset, w))))
- let scalar_bits = context.resolve_type(arg).scalar_width().unwrap();
+ let scalar_bits = context.resolve_type(arg).scalar_width().unwrap() * 8;
write!(self.out, "{NAMESPACE}::insert_bits(")?;
self.put_expression(arg, context, true)?;
@@ -2041,6 +2031,8 @@ impl<W: Write> Writer<W> {
crate::Expression::CallResult(_)
| crate::Expression::AtomicResult { .. }
| crate::Expression::WorkGroupUniformLoadResult { .. }
+ | crate::Expression::SubgroupBallotResult
+ | crate::Expression::SubgroupOperationResult { .. }
| crate::Expression::RayQueryProceedResult => {
unreachable!()
}
@@ -2994,43 +2986,8 @@ impl<W: Write> Writer<W> {
let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
self.start_baking_expression(result, &context.expression, &res_name)?;
self.named_expressions.insert(result, res_name);
- match *fun {
- crate::AtomicFunction::Add => {
- self.put_atomic_fetch(pointer, "add", value, &context.expression)?;
- }
- crate::AtomicFunction::Subtract => {
- self.put_atomic_fetch(pointer, "sub", value, &context.expression)?;
- }
- crate::AtomicFunction::And => {
- self.put_atomic_fetch(pointer, "and", value, &context.expression)?;
- }
- crate::AtomicFunction::InclusiveOr => {
- self.put_atomic_fetch(pointer, "or", value, &context.expression)?;
- }
- crate::AtomicFunction::ExclusiveOr => {
- self.put_atomic_fetch(pointer, "xor", value, &context.expression)?;
- }
- crate::AtomicFunction::Min => {
- self.put_atomic_fetch(pointer, "min", value, &context.expression)?;
- }
- crate::AtomicFunction::Max => {
- self.put_atomic_fetch(pointer, "max", value, &context.expression)?;
- }
- crate::AtomicFunction::Exchange { compare: None } => {
- self.put_atomic_operation(
- pointer,
- "exchange",
- "",
- value,
- &context.expression,
- )?;
- }
- crate::AtomicFunction::Exchange { .. } => {
- return Err(Error::FeatureNotImplemented(
- "atomic CompareExchange".to_string(),
- ));
- }
- }
+ let fun_str = fun.to_msl()?;
+ self.put_atomic_operation(pointer, fun_str, value, &context.expression)?;
// done
writeln!(self.out, ";")?;
}
@@ -3144,6 +3101,121 @@ impl<W: Write> Writer<W> {
}
}
}
+ crate::Statement::SubgroupBallot { result, predicate } => {
+ write!(self.out, "{level}")?;
+ let name = self.namer.call("");
+ self.start_baking_expression(result, &context.expression, &name)?;
+ self.named_expressions.insert(result, name);
+ write!(self.out, "uint4((uint64_t){NAMESPACE}::simd_ballot(")?;
+ if let Some(predicate) = predicate {
+ self.put_expression(predicate, &context.expression, true)?;
+ } else {
+ write!(self.out, "true")?;
+ }
+ writeln!(self.out, "), 0, 0, 0);")?;
+ }
+ crate::Statement::SubgroupCollectiveOperation {
+ op,
+ collective_op,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ let name = self.namer.call("");
+ self.start_baking_expression(result, &context.expression, &name)?;
+ self.named_expressions.insert(result, name);
+ match (collective_op, op) {
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::All) => {
+ write!(self.out, "{NAMESPACE}::simd_all(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Any) => {
+ write!(self.out, "{NAMESPACE}::simd_any(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Add) => {
+ write!(self.out, "{NAMESPACE}::simd_sum(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "{NAMESPACE}::simd_product(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Max) => {
+ write!(self.out, "{NAMESPACE}::simd_max(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Min) => {
+ write!(self.out, "{NAMESPACE}::simd_min(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::And) => {
+ write!(self.out, "{NAMESPACE}::simd_and(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Or) => {
+ write!(self.out, "{NAMESPACE}::simd_or(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Xor) => {
+ write!(self.out, "{NAMESPACE}::simd_xor(")?
+ }
+ (
+ crate::CollectiveOperation::ExclusiveScan,
+ crate::SubgroupOperation::Add,
+ ) => write!(self.out, "{NAMESPACE}::simd_prefix_exclusive_sum(")?,
+ (
+ crate::CollectiveOperation::ExclusiveScan,
+ crate::SubgroupOperation::Mul,
+ ) => write!(self.out, "{NAMESPACE}::simd_prefix_exclusive_product(")?,
+ (
+ crate::CollectiveOperation::InclusiveScan,
+ crate::SubgroupOperation::Add,
+ ) => write!(self.out, "{NAMESPACE}::simd_prefix_inclusive_sum(")?,
+ (
+ crate::CollectiveOperation::InclusiveScan,
+ crate::SubgroupOperation::Mul,
+ ) => write!(self.out, "{NAMESPACE}::simd_prefix_inclusive_product(")?,
+ _ => unimplemented!(),
+ }
+ self.put_expression(argument, &context.expression, true)?;
+ writeln!(self.out, ");")?;
+ }
+ crate::Statement::SubgroupGather {
+ mode,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ let name = self.namer.call("");
+ self.start_baking_expression(result, &context.expression, &name)?;
+ self.named_expressions.insert(result, name);
+ match mode {
+ crate::GatherMode::BroadcastFirst => {
+ write!(self.out, "{NAMESPACE}::simd_broadcast_first(")?;
+ }
+ crate::GatherMode::Broadcast(_) => {
+ write!(self.out, "{NAMESPACE}::simd_broadcast(")?;
+ }
+ crate::GatherMode::Shuffle(_) => {
+ write!(self.out, "{NAMESPACE}::simd_shuffle(")?;
+ }
+ crate::GatherMode::ShuffleDown(_) => {
+ write!(self.out, "{NAMESPACE}::simd_shuffle_down(")?;
+ }
+ crate::GatherMode::ShuffleUp(_) => {
+ write!(self.out, "{NAMESPACE}::simd_shuffle_up(")?;
+ }
+ crate::GatherMode::ShuffleXor(_) => {
+ write!(self.out, "{NAMESPACE}::simd_shuffle_xor(")?;
+ }
+ }
+ self.put_expression(argument, &context.expression, true)?;
+ match mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ write!(self.out, ", ")?;
+ self.put_expression(index, &context.expression, true)?;
+ }
+ }
+ writeln!(self.out, ");")?;
+ }
}
}
@@ -3220,6 +3292,10 @@ impl<W: Write> Writer<W> {
options: &Options,
pipeline_options: &PipelineOptions,
) -> Result<TranslationInfo, Error> {
+ if !module.overrides.is_empty() {
+ return Err(Error::Override);
+ }
+
self.names.clear();
self.namer.reset(
module,
@@ -4487,6 +4563,12 @@ impl<W: Write> Writer<W> {
"{level}{NAMESPACE}::threadgroup_barrier({NAMESPACE}::mem_flags::mem_threadgroup);",
)?;
}
+ if flags.contains(crate::Barrier::SUB_GROUP) {
+ writeln!(
+ self.out,
+ "{level}{NAMESPACE}::simdgroup_barrier({NAMESPACE}::mem_flags::mem_threadgroup);",
+ )?;
+ }
Ok(())
}
}
@@ -4757,8 +4839,8 @@ fn test_stack_size() {
}
let stack_size = addresses_end - addresses_start;
// check the size (in debug only)
- // last observed macOS value: 19152 (CI)
- if !(9000..=20000).contains(&stack_size) {
+ // last observed macOS value: 22256 (CI)
+ if !(15000..=25000).contains(&stack_size) {
panic!("`put_block` stack size {stack_size} has changed!");
}
}
diff --git a/third_party/rust/naga/src/back/pipeline_constants.rs b/third_party/rust/naga/src/back/pipeline_constants.rs
new file mode 100644
index 0000000000..0dbe9cf4e8
--- /dev/null
+++ b/third_party/rust/naga/src/back/pipeline_constants.rs
@@ -0,0 +1,957 @@
+use super::PipelineConstants;
+use crate::{
+ proc::{ConstantEvaluator, ConstantEvaluatorError, Emitter},
+ valid::{Capabilities, ModuleInfo, ValidationError, ValidationFlags, Validator},
+ Arena, Block, Constant, Expression, Function, Handle, Literal, Module, Override, Range, Scalar,
+ Span, Statement, TypeInner, WithSpan,
+};
+use std::{borrow::Cow, collections::HashSet, mem};
+use thiserror::Error;
+
+#[derive(Error, Debug, Clone)]
+#[cfg_attr(test, derive(PartialEq))]
+pub enum PipelineConstantError {
+ #[error("Missing value for pipeline-overridable constant with identifier string: '{0}'")]
+ MissingValue(String),
+ #[error("Source f64 value needs to be finite (NaNs and Inifinites are not allowed) for number destinations")]
+ SrcNeedsToBeFinite,
+ #[error("Source f64 value doesn't fit in destination")]
+ DstRangeTooSmall,
+ #[error(transparent)]
+ ConstantEvaluatorError(#[from] ConstantEvaluatorError),
+ #[error(transparent)]
+ ValidationError(#[from] WithSpan<ValidationError>),
+}
+
+/// Replace all overrides in `module` with constants.
+///
+/// If no changes are needed, this just returns `Cow::Borrowed`
+/// references to `module` and `module_info`. Otherwise, it clones
+/// `module`, edits its [`global_expressions`] arena to contain only
+/// fully-evaluated expressions, and returns `Cow::Owned` values
+/// holding the simplified module and its validation results.
+///
+/// In either case, the module returned has an empty `overrides`
+/// arena, and the `global_expressions` arena contains only
+/// fully-evaluated expressions.
+///
+/// [`global_expressions`]: Module::global_expressions
+pub fn process_overrides<'a>(
+ module: &'a Module,
+ module_info: &'a ModuleInfo,
+ pipeline_constants: &PipelineConstants,
+) -> Result<(Cow<'a, Module>, Cow<'a, ModuleInfo>), PipelineConstantError> {
+ if module.overrides.is_empty() {
+ return Ok((Cow::Borrowed(module), Cow::Borrowed(module_info)));
+ }
+
+ let mut module = module.clone();
+
+ // A map from override handles to the handles of the constants
+ // we've replaced them with.
+ let mut override_map = Vec::with_capacity(module.overrides.len());
+
+ // A map from `module`'s original global expression handles to
+ // handles in the new, simplified global expression arena.
+ let mut adjusted_global_expressions = Vec::with_capacity(module.global_expressions.len());
+
+ // The set of constants whose initializer handles we've already
+ // updated to refer to the newly built global expression arena.
+ //
+ // All constants in `module` must have their `init` handles
+ // updated to point into the new, simplified global expression
+ // arena. Some of these we can most easily handle as a side effect
+ // during the simplification process, but we must handle the rest
+ // in a final fixup pass, guided by `adjusted_global_expressions`. We
+ // add their handles to this set, so that the final fixup step can
+ // leave them alone.
+ let mut adjusted_constant_initializers = HashSet::with_capacity(module.constants.len());
+
+ let mut global_expression_kind_tracker = crate::proc::ExpressionKindTracker::new();
+
+ // An iterator through the original overrides table, consumed in
+ // approximate tandem with the global expressions.
+ let mut override_iter = module.overrides.drain();
+
+ // Do two things in tandem:
+ //
+ // - Rebuild the global expression arena from scratch, fully
+ // evaluating all expressions, and replacing each `Override`
+ // expression in `module.global_expressions` with a `Constant`
+ // expression.
+ //
+ // - Build a new `Constant` in `module.constants` to take the
+ // place of each `Override`.
+ //
+ // Build a map from old global expression handles to their
+ // fully-evaluated counterparts in `adjusted_global_expressions` as we
+ // go.
+ //
+ // Why in tandem? Overrides refer to expressions, and expressions
+ // refer to overrides, so we can't disentangle the two into
+ // separate phases. However, we can take advantage of the fact
+ // that the overrides and expressions must form a DAG, and work
+ // our way from the leaves to the roots, replacing and evaluating
+ // as we go.
+ //
+ // Although the two loops are nested, this is really two
+ // alternating phases: we adjust and evaluate constant expressions
+ // until we hit an `Override` expression, at which point we switch
+ // to building `Constant`s for `Overrides` until we've handled the
+ // one used by the expression. Then we switch back to processing
+ // expressions. Because we know they form a DAG, we know the
+ // `Override` expressions we encounter can only have initializers
+ // referring to global expressions we've already simplified.
+ for (old_h, expr, span) in module.global_expressions.drain() {
+ let mut expr = match expr {
+ Expression::Override(h) => {
+ let c_h = if let Some(new_h) = override_map.get(h.index()) {
+ *new_h
+ } else {
+ let mut new_h = None;
+ for entry in override_iter.by_ref() {
+ let stop = entry.0 == h;
+ new_h = Some(process_override(
+ entry,
+ pipeline_constants,
+ &mut module,
+ &mut override_map,
+ &adjusted_global_expressions,
+ &mut adjusted_constant_initializers,
+ &mut global_expression_kind_tracker,
+ )?);
+ if stop {
+ break;
+ }
+ }
+ new_h.unwrap()
+ };
+ Expression::Constant(c_h)
+ }
+ Expression::Constant(c_h) => {
+ if adjusted_constant_initializers.insert(c_h) {
+ let init = &mut module.constants[c_h].init;
+ *init = adjusted_global_expressions[init.index()];
+ }
+ expr
+ }
+ expr => expr,
+ };
+ let mut evaluator = ConstantEvaluator::for_wgsl_module(
+ &mut module,
+ &mut global_expression_kind_tracker,
+ false,
+ );
+ adjust_expr(&adjusted_global_expressions, &mut expr);
+ let h = evaluator.try_eval_and_append(expr, span)?;
+ debug_assert_eq!(old_h.index(), adjusted_global_expressions.len());
+ adjusted_global_expressions.push(h);
+ }
+
+ // Finish processing any overrides we didn't visit in the loop above.
+ for entry in override_iter {
+ process_override(
+ entry,
+ pipeline_constants,
+ &mut module,
+ &mut override_map,
+ &adjusted_global_expressions,
+ &mut adjusted_constant_initializers,
+ &mut global_expression_kind_tracker,
+ )?;
+ }
+
+ // Update the initialization expression handles of all `Constant`s
+ // and `GlobalVariable`s. Skip `Constant`s we'd already updated en
+ // passant.
+ for (_, c) in module
+ .constants
+ .iter_mut()
+ .filter(|&(c_h, _)| !adjusted_constant_initializers.contains(&c_h))
+ {
+ c.init = adjusted_global_expressions[c.init.index()];
+ }
+
+ for (_, v) in module.global_variables.iter_mut() {
+ if let Some(ref mut init) = v.init {
+ *init = adjusted_global_expressions[init.index()];
+ }
+ }
+
+ let mut functions = mem::take(&mut module.functions);
+ for (_, function) in functions.iter_mut() {
+ process_function(&mut module, &override_map, function)?;
+ }
+ module.functions = functions;
+
+ let mut entry_points = mem::take(&mut module.entry_points);
+ for ep in entry_points.iter_mut() {
+ process_function(&mut module, &override_map, &mut ep.function)?;
+ }
+ module.entry_points = entry_points;
+
+ // Now that we've rewritten all the expressions, we need to
+ // recompute their types and other metadata. For the time being,
+ // do a full re-validation.
+ let mut validator = Validator::new(ValidationFlags::all(), Capabilities::all());
+ let module_info = validator.validate_no_overrides(&module)?;
+
+ Ok((Cow::Owned(module), Cow::Owned(module_info)))
+}
+
+/// Add a [`Constant`] to `module` for the override `old_h`.
+///
+/// Add the new `Constant` to `override_map` and `adjusted_constant_initializers`.
+fn process_override(
+ (old_h, override_, span): (Handle<Override>, Override, Span),
+ pipeline_constants: &PipelineConstants,
+ module: &mut Module,
+ override_map: &mut Vec<Handle<Constant>>,
+ adjusted_global_expressions: &[Handle<Expression>],
+ adjusted_constant_initializers: &mut HashSet<Handle<Constant>>,
+ global_expression_kind_tracker: &mut crate::proc::ExpressionKindTracker,
+) -> Result<Handle<Constant>, PipelineConstantError> {
+ // Determine which key to use for `override_` in `pipeline_constants`.
+ let key = if let Some(id) = override_.id {
+ Cow::Owned(id.to_string())
+ } else if let Some(ref name) = override_.name {
+ Cow::Borrowed(name)
+ } else {
+ unreachable!();
+ };
+
+ // Generate a global expression for `override_`'s value, either
+ // from the provided `pipeline_constants` table or its initializer
+ // in the module.
+ let init = if let Some(value) = pipeline_constants.get::<str>(&key) {
+ let literal = match module.types[override_.ty].inner {
+ TypeInner::Scalar(scalar) => map_value_to_literal(*value, scalar)?,
+ _ => unreachable!(),
+ };
+ let expr = module
+ .global_expressions
+ .append(Expression::Literal(literal), Span::UNDEFINED);
+ global_expression_kind_tracker.insert(expr, crate::proc::ExpressionKind::Const);
+ expr
+ } else if let Some(init) = override_.init {
+ adjusted_global_expressions[init.index()]
+ } else {
+ return Err(PipelineConstantError::MissingValue(key.to_string()));
+ };
+
+ // Generate a new `Constant` to represent the override's value.
+ let constant = Constant {
+ name: override_.name,
+ ty: override_.ty,
+ init,
+ };
+ let h = module.constants.append(constant, span);
+ debug_assert_eq!(old_h.index(), override_map.len());
+ override_map.push(h);
+ adjusted_constant_initializers.insert(h);
+ Ok(h)
+}
+
+/// Replace all override expressions in `function` with fully-evaluated constants.
+///
+/// Replace all `Expression::Override`s in `function`'s expression arena with
+/// the corresponding `Expression::Constant`s, as given in `override_map`.
+/// Replace any expressions whose values are now known with their fully
+/// evaluated form.
+///
+/// If `h` is a `Handle<Override>`, then `override_map[h.index()]` is the
+/// `Handle<Constant>` for the override's final value.
+fn process_function(
+ module: &mut Module,
+ override_map: &[Handle<Constant>],
+ function: &mut Function,
+) -> Result<(), ConstantEvaluatorError> {
+ // A map from original local expression handles to
+ // handles in the new, local expression arena.
+ let mut adjusted_local_expressions = Vec::with_capacity(function.expressions.len());
+
+ let mut local_expression_kind_tracker = crate::proc::ExpressionKindTracker::new();
+
+ let mut expressions = mem::take(&mut function.expressions);
+
+ // Dummy `emitter` and `block` for the constant evaluator.
+ // We can ignore the concept of emitting expressions here since
+ // expressions have already been covered by a `Statement::Emit`
+ // in the frontend.
+ // The only thing we might have to do is remove some expressions
+ // that have been covered by a `Statement::Emit`. See the docs of
+ // `filter_emits_in_block` for the reasoning.
+ let mut emitter = Emitter::default();
+ let mut block = Block::new();
+
+ let mut evaluator = ConstantEvaluator::for_wgsl_function(
+ module,
+ &mut function.expressions,
+ &mut local_expression_kind_tracker,
+ &mut emitter,
+ &mut block,
+ );
+
+ for (old_h, mut expr, span) in expressions.drain() {
+ if let Expression::Override(h) = expr {
+ expr = Expression::Constant(override_map[h.index()]);
+ }
+ adjust_expr(&adjusted_local_expressions, &mut expr);
+ let h = evaluator.try_eval_and_append(expr, span)?;
+ debug_assert_eq!(old_h.index(), adjusted_local_expressions.len());
+ adjusted_local_expressions.push(h);
+ }
+
+ adjust_block(&adjusted_local_expressions, &mut function.body);
+
+ filter_emits_in_block(&mut function.body, &function.expressions);
+
+ // Update local expression initializers.
+ for (_, local) in function.local_variables.iter_mut() {
+ if let &mut Some(ref mut init) = &mut local.init {
+ *init = adjusted_local_expressions[init.index()];
+ }
+ }
+
+ // We've changed the keys of `function.named_expression`, so we have to
+ // rebuild it from scratch.
+ let named_expressions = mem::take(&mut function.named_expressions);
+ for (expr_h, name) in named_expressions {
+ function
+ .named_expressions
+ .insert(adjusted_local_expressions[expr_h.index()], name);
+ }
+
+ Ok(())
+}
+
+/// Replace every expression handle in `expr` with its counterpart
+/// given by `new_pos`.
+fn adjust_expr(new_pos: &[Handle<Expression>], expr: &mut Expression) {
+ let adjust = |expr: &mut Handle<Expression>| {
+ *expr = new_pos[expr.index()];
+ };
+ match *expr {
+ Expression::Compose {
+ ref mut components,
+ ty: _,
+ } => {
+ for c in components.iter_mut() {
+ adjust(c);
+ }
+ }
+ Expression::Access {
+ ref mut base,
+ ref mut index,
+ } => {
+ adjust(base);
+ adjust(index);
+ }
+ Expression::AccessIndex {
+ ref mut base,
+ index: _,
+ } => {
+ adjust(base);
+ }
+ Expression::Splat {
+ ref mut value,
+ size: _,
+ } => {
+ adjust(value);
+ }
+ Expression::Swizzle {
+ ref mut vector,
+ size: _,
+ pattern: _,
+ } => {
+ adjust(vector);
+ }
+ Expression::Load { ref mut pointer } => {
+ adjust(pointer);
+ }
+ Expression::ImageSample {
+ ref mut image,
+ ref mut sampler,
+ ref mut coordinate,
+ ref mut array_index,
+ ref mut offset,
+ ref mut level,
+ ref mut depth_ref,
+ gather: _,
+ } => {
+ adjust(image);
+ adjust(sampler);
+ adjust(coordinate);
+ if let Some(e) = array_index.as_mut() {
+ adjust(e);
+ }
+ if let Some(e) = offset.as_mut() {
+ adjust(e);
+ }
+ match *level {
+ crate::SampleLevel::Exact(ref mut expr)
+ | crate::SampleLevel::Bias(ref mut expr) => {
+ adjust(expr);
+ }
+ crate::SampleLevel::Gradient {
+ ref mut x,
+ ref mut y,
+ } => {
+ adjust(x);
+ adjust(y);
+ }
+ _ => {}
+ }
+ if let Some(e) = depth_ref.as_mut() {
+ adjust(e);
+ }
+ }
+ Expression::ImageLoad {
+ ref mut image,
+ ref mut coordinate,
+ ref mut array_index,
+ ref mut sample,
+ ref mut level,
+ } => {
+ adjust(image);
+ adjust(coordinate);
+ if let Some(e) = array_index.as_mut() {
+ adjust(e);
+ }
+ if let Some(e) = sample.as_mut() {
+ adjust(e);
+ }
+ if let Some(e) = level.as_mut() {
+ adjust(e);
+ }
+ }
+ Expression::ImageQuery {
+ ref mut image,
+ ref mut query,
+ } => {
+ adjust(image);
+ match *query {
+ crate::ImageQuery::Size { ref mut level } => {
+ if let Some(e) = level.as_mut() {
+ adjust(e);
+ }
+ }
+ crate::ImageQuery::NumLevels
+ | crate::ImageQuery::NumLayers
+ | crate::ImageQuery::NumSamples => {}
+ }
+ }
+ Expression::Unary {
+ ref mut expr,
+ op: _,
+ } => {
+ adjust(expr);
+ }
+ Expression::Binary {
+ ref mut left,
+ ref mut right,
+ op: _,
+ } => {
+ adjust(left);
+ adjust(right);
+ }
+ Expression::Select {
+ ref mut condition,
+ ref mut accept,
+ ref mut reject,
+ } => {
+ adjust(condition);
+ adjust(accept);
+ adjust(reject);
+ }
+ Expression::Derivative {
+ ref mut expr,
+ axis: _,
+ ctrl: _,
+ } => {
+ adjust(expr);
+ }
+ Expression::Relational {
+ ref mut argument,
+ fun: _,
+ } => {
+ adjust(argument);
+ }
+ Expression::Math {
+ ref mut arg,
+ ref mut arg1,
+ ref mut arg2,
+ ref mut arg3,
+ fun: _,
+ } => {
+ adjust(arg);
+ if let Some(e) = arg1.as_mut() {
+ adjust(e);
+ }
+ if let Some(e) = arg2.as_mut() {
+ adjust(e);
+ }
+ if let Some(e) = arg3.as_mut() {
+ adjust(e);
+ }
+ }
+ Expression::As {
+ ref mut expr,
+ kind: _,
+ convert: _,
+ } => {
+ adjust(expr);
+ }
+ Expression::ArrayLength(ref mut expr) => {
+ adjust(expr);
+ }
+ Expression::RayQueryGetIntersection {
+ ref mut query,
+ committed: _,
+ } => {
+ adjust(query);
+ }
+ Expression::Literal(_)
+ | Expression::FunctionArgument(_)
+ | Expression::GlobalVariable(_)
+ | Expression::LocalVariable(_)
+ | Expression::CallResult(_)
+ | Expression::RayQueryProceedResult
+ | Expression::Constant(_)
+ | Expression::Override(_)
+ | Expression::ZeroValue(_)
+ | Expression::AtomicResult {
+ ty: _,
+ comparison: _,
+ }
+ | Expression::WorkGroupUniformLoadResult { ty: _ }
+ | Expression::SubgroupBallotResult
+ | Expression::SubgroupOperationResult { .. } => {}
+ }
+}
+
+/// Replace every expression handle in `block` with its counterpart
+/// given by `new_pos`.
+fn adjust_block(new_pos: &[Handle<Expression>], block: &mut Block) {
+ for stmt in block.iter_mut() {
+ adjust_stmt(new_pos, stmt);
+ }
+}
+
+/// Replace every expression handle in `stmt` with its counterpart
+/// given by `new_pos`.
+fn adjust_stmt(new_pos: &[Handle<Expression>], stmt: &mut Statement) {
+ let adjust = |expr: &mut Handle<Expression>| {
+ *expr = new_pos[expr.index()];
+ };
+ match *stmt {
+ Statement::Emit(ref mut range) => {
+ if let Some((mut first, mut last)) = range.first_and_last() {
+ adjust(&mut first);
+ adjust(&mut last);
+ *range = Range::new_from_bounds(first, last);
+ }
+ }
+ Statement::Block(ref mut block) => {
+ adjust_block(new_pos, block);
+ }
+ Statement::If {
+ ref mut condition,
+ ref mut accept,
+ ref mut reject,
+ } => {
+ adjust(condition);
+ adjust_block(new_pos, accept);
+ adjust_block(new_pos, reject);
+ }
+ Statement::Switch {
+ ref mut selector,
+ ref mut cases,
+ } => {
+ adjust(selector);
+ for case in cases.iter_mut() {
+ adjust_block(new_pos, &mut case.body);
+ }
+ }
+ Statement::Loop {
+ ref mut body,
+ ref mut continuing,
+ ref mut break_if,
+ } => {
+ adjust_block(new_pos, body);
+ adjust_block(new_pos, continuing);
+ if let Some(e) = break_if.as_mut() {
+ adjust(e);
+ }
+ }
+ Statement::Return { ref mut value } => {
+ if let Some(e) = value.as_mut() {
+ adjust(e);
+ }
+ }
+ Statement::Store {
+ ref mut pointer,
+ ref mut value,
+ } => {
+ adjust(pointer);
+ adjust(value);
+ }
+ Statement::ImageStore {
+ ref mut image,
+ ref mut coordinate,
+ ref mut array_index,
+ ref mut value,
+ } => {
+ adjust(image);
+ adjust(coordinate);
+ if let Some(e) = array_index.as_mut() {
+ adjust(e);
+ }
+ adjust(value);
+ }
+ crate::Statement::Atomic {
+ ref mut pointer,
+ ref mut value,
+ ref mut result,
+ ref mut fun,
+ } => {
+ adjust(pointer);
+ adjust(value);
+ adjust(result);
+ match *fun {
+ crate::AtomicFunction::Exchange {
+ compare: Some(ref mut compare),
+ } => {
+ adjust(compare);
+ }
+ crate::AtomicFunction::Add
+ | crate::AtomicFunction::Subtract
+ | crate::AtomicFunction::And
+ | crate::AtomicFunction::ExclusiveOr
+ | crate::AtomicFunction::InclusiveOr
+ | crate::AtomicFunction::Min
+ | crate::AtomicFunction::Max
+ | crate::AtomicFunction::Exchange { compare: None } => {}
+ }
+ }
+ Statement::WorkGroupUniformLoad {
+ ref mut pointer,
+ ref mut result,
+ } => {
+ adjust(pointer);
+ adjust(result);
+ }
+ Statement::SubgroupBallot {
+ ref mut result,
+ ref mut predicate,
+ } => {
+ if let Some(ref mut predicate) = *predicate {
+ adjust(predicate);
+ }
+ adjust(result);
+ }
+ Statement::SubgroupCollectiveOperation {
+ ref mut argument,
+ ref mut result,
+ ..
+ } => {
+ adjust(argument);
+ adjust(result);
+ }
+ Statement::SubgroupGather {
+ ref mut mode,
+ ref mut argument,
+ ref mut result,
+ } => {
+ match *mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(ref mut index)
+ | crate::GatherMode::Shuffle(ref mut index)
+ | crate::GatherMode::ShuffleDown(ref mut index)
+ | crate::GatherMode::ShuffleUp(ref mut index)
+ | crate::GatherMode::ShuffleXor(ref mut index) => {
+ adjust(index);
+ }
+ }
+ adjust(argument);
+ adjust(result)
+ }
+ Statement::Call {
+ ref mut arguments,
+ ref mut result,
+ function: _,
+ } => {
+ for argument in arguments.iter_mut() {
+ adjust(argument);
+ }
+ if let Some(e) = result.as_mut() {
+ adjust(e);
+ }
+ }
+ Statement::RayQuery {
+ ref mut query,
+ ref mut fun,
+ } => {
+ adjust(query);
+ match *fun {
+ crate::RayQueryFunction::Initialize {
+ ref mut acceleration_structure,
+ ref mut descriptor,
+ } => {
+ adjust(acceleration_structure);
+ adjust(descriptor);
+ }
+ crate::RayQueryFunction::Proceed { ref mut result } => {
+ adjust(result);
+ }
+ crate::RayQueryFunction::Terminate => {}
+ }
+ }
+ Statement::Break | Statement::Continue | Statement::Kill | Statement::Barrier(_) => {}
+ }
+}
+
+/// Adjust [`Emit`] statements in `block` to skip [`needs_pre_emit`] expressions we have introduced.
+///
+/// According to validation, [`Emit`] statements must not cover any expressions
+/// for which [`Expression::needs_pre_emit`] returns true. All expressions built
+/// by successful constant evaluation fall into that category, meaning that
+/// `process_function` will usually rewrite [`Override`] expressions and those
+/// that use their values into pre-emitted expressions, leaving any [`Emit`]
+/// statements that cover them invalid.
+///
+/// This function rewrites all [`Emit`] statements into zero or more new
+/// [`Emit`] statements covering only those expressions in the original range
+/// that are not pre-emitted.
+///
+/// [`Emit`]: Statement::Emit
+/// [`needs_pre_emit`]: Expression::needs_pre_emit
+/// [`Override`]: Expression::Override
+fn filter_emits_in_block(block: &mut Block, expressions: &Arena<Expression>) {
+ let original = std::mem::replace(block, Block::with_capacity(block.len()));
+ for (stmt, span) in original.span_into_iter() {
+ match stmt {
+ Statement::Emit(range) => {
+ let mut current = None;
+ for expr_h in range {
+ if expressions[expr_h].needs_pre_emit() {
+ if let Some((first, last)) = current {
+ block.push(Statement::Emit(Range::new_from_bounds(first, last)), span);
+ }
+
+ current = None;
+ } else if let Some((_, ref mut last)) = current {
+ *last = expr_h;
+ } else {
+ current = Some((expr_h, expr_h));
+ }
+ }
+ if let Some((first, last)) = current {
+ block.push(Statement::Emit(Range::new_from_bounds(first, last)), span);
+ }
+ }
+ Statement::Block(mut child) => {
+ filter_emits_in_block(&mut child, expressions);
+ block.push(Statement::Block(child), span);
+ }
+ Statement::If {
+ condition,
+ mut accept,
+ mut reject,
+ } => {
+ filter_emits_in_block(&mut accept, expressions);
+ filter_emits_in_block(&mut reject, expressions);
+ block.push(
+ Statement::If {
+ condition,
+ accept,
+ reject,
+ },
+ span,
+ );
+ }
+ Statement::Switch {
+ selector,
+ mut cases,
+ } => {
+ for case in &mut cases {
+ filter_emits_in_block(&mut case.body, expressions);
+ }
+ block.push(Statement::Switch { selector, cases }, span);
+ }
+ Statement::Loop {
+ mut body,
+ mut continuing,
+ break_if,
+ } => {
+ filter_emits_in_block(&mut body, expressions);
+ filter_emits_in_block(&mut continuing, expressions);
+ block.push(
+ Statement::Loop {
+ body,
+ continuing,
+ break_if,
+ },
+ span,
+ );
+ }
+ stmt => block.push(stmt.clone(), span),
+ }
+ }
+}
+
+fn map_value_to_literal(value: f64, scalar: Scalar) -> Result<Literal, PipelineConstantError> {
+ // note that in rust 0.0 == -0.0
+ match scalar {
+ Scalar::BOOL => {
+ // https://webidl.spec.whatwg.org/#js-boolean
+ let value = value != 0.0 && !value.is_nan();
+ Ok(Literal::Bool(value))
+ }
+ Scalar::I32 => {
+ // https://webidl.spec.whatwg.org/#js-long
+ if !value.is_finite() {
+ return Err(PipelineConstantError::SrcNeedsToBeFinite);
+ }
+
+ let value = value.trunc();
+ if value < f64::from(i32::MIN) || value > f64::from(i32::MAX) {
+ return Err(PipelineConstantError::DstRangeTooSmall);
+ }
+
+ let value = value as i32;
+ Ok(Literal::I32(value))
+ }
+ Scalar::U32 => {
+ // https://webidl.spec.whatwg.org/#js-unsigned-long
+ if !value.is_finite() {
+ return Err(PipelineConstantError::SrcNeedsToBeFinite);
+ }
+
+ let value = value.trunc();
+ if value < f64::from(u32::MIN) || value > f64::from(u32::MAX) {
+ return Err(PipelineConstantError::DstRangeTooSmall);
+ }
+
+ let value = value as u32;
+ Ok(Literal::U32(value))
+ }
+ Scalar::F32 => {
+ // https://webidl.spec.whatwg.org/#js-float
+ if !value.is_finite() {
+ return Err(PipelineConstantError::SrcNeedsToBeFinite);
+ }
+
+ let value = value as f32;
+ if !value.is_finite() {
+ return Err(PipelineConstantError::DstRangeTooSmall);
+ }
+
+ Ok(Literal::F32(value))
+ }
+ Scalar::F64 => {
+ // https://webidl.spec.whatwg.org/#js-double
+ if !value.is_finite() {
+ return Err(PipelineConstantError::SrcNeedsToBeFinite);
+ }
+
+ Ok(Literal::F64(value))
+ }
+ _ => unreachable!(),
+ }
+}
+
+#[test]
+fn test_map_value_to_literal() {
+ let bool_test_cases = [
+ (0.0, false),
+ (-0.0, false),
+ (f64::NAN, false),
+ (1.0, true),
+ (f64::INFINITY, true),
+ (f64::NEG_INFINITY, true),
+ ];
+ for (value, out) in bool_test_cases {
+ let res = Ok(Literal::Bool(out));
+ assert_eq!(map_value_to_literal(value, Scalar::BOOL), res);
+ }
+
+ for scalar in [Scalar::I32, Scalar::U32, Scalar::F32, Scalar::F64] {
+ for value in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
+ let res = Err(PipelineConstantError::SrcNeedsToBeFinite);
+ assert_eq!(map_value_to_literal(value, scalar), res);
+ }
+ }
+
+ // i32
+ assert_eq!(
+ map_value_to_literal(f64::from(i32::MIN), Scalar::I32),
+ Ok(Literal::I32(i32::MIN))
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from(i32::MAX), Scalar::I32),
+ Ok(Literal::I32(i32::MAX))
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from(i32::MIN) - 1.0, Scalar::I32),
+ Err(PipelineConstantError::DstRangeTooSmall)
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from(i32::MAX) + 1.0, Scalar::I32),
+ Err(PipelineConstantError::DstRangeTooSmall)
+ );
+
+ // u32
+ assert_eq!(
+ map_value_to_literal(f64::from(u32::MIN), Scalar::U32),
+ Ok(Literal::U32(u32::MIN))
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from(u32::MAX), Scalar::U32),
+ Ok(Literal::U32(u32::MAX))
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from(u32::MIN) - 1.0, Scalar::U32),
+ Err(PipelineConstantError::DstRangeTooSmall)
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from(u32::MAX) + 1.0, Scalar::U32),
+ Err(PipelineConstantError::DstRangeTooSmall)
+ );
+
+ // f32
+ assert_eq!(
+ map_value_to_literal(f64::from(f32::MIN), Scalar::F32),
+ Ok(Literal::F32(f32::MIN))
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from(f32::MAX), Scalar::F32),
+ Ok(Literal::F32(f32::MAX))
+ );
+ assert_eq!(
+ map_value_to_literal(-f64::from_bits(0x47efffffefffffff), Scalar::F32),
+ Ok(Literal::F32(f32::MIN))
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from_bits(0x47efffffefffffff), Scalar::F32),
+ Ok(Literal::F32(f32::MAX))
+ );
+ assert_eq!(
+ map_value_to_literal(-f64::from_bits(0x47effffff0000000), Scalar::F32),
+ Err(PipelineConstantError::DstRangeTooSmall)
+ );
+ assert_eq!(
+ map_value_to_literal(f64::from_bits(0x47effffff0000000), Scalar::F32),
+ Err(PipelineConstantError::DstRangeTooSmall)
+ );
+
+ // f64
+ assert_eq!(
+ map_value_to_literal(f64::MIN, Scalar::F64),
+ Ok(Literal::F64(f64::MIN))
+ );
+ assert_eq!(
+ map_value_to_literal(f64::MAX, Scalar::F64),
+ Ok(Literal::F64(f64::MAX))
+ );
+}
diff --git a/third_party/rust/naga/src/back/spv/block.rs b/third_party/rust/naga/src/back/spv/block.rs
index 81f2fc10e0..120d60fc40 100644
--- a/third_party/rust/naga/src/back/spv/block.rs
+++ b/third_party/rust/naga/src/back/spv/block.rs
@@ -239,6 +239,7 @@ impl<'w> BlockContext<'w> {
let init = self.ir_module.constants[handle].init;
self.writer.constant_ids[init.index()]
}
+ crate::Expression::Override(_) => return Err(Error::Override),
crate::Expression::ZeroValue(_) => self.writer.get_constant_null(result_type_id),
crate::Expression::Compose { ty, ref components } => {
self.temp_list.clear();
@@ -1072,7 +1073,7 @@ impl<'w> BlockContext<'w> {
//
// bitfieldExtract(x, o, c)
- let bit_width = arg_ty.scalar_width().unwrap();
+ let bit_width = arg_ty.scalar_width().unwrap() * 8;
let width_constant = self
.writer
.get_constant_scalar(crate::Literal::U32(bit_width as u32));
@@ -1128,7 +1129,7 @@ impl<'w> BlockContext<'w> {
Mf::InsertBits => {
// The behavior of InsertBits has the same undefined behavior as ExtractBits.
- let bit_width = arg_ty.scalar_width().unwrap();
+ let bit_width = arg_ty.scalar_width().unwrap() * 8;
let width_constant = self
.writer
.get_constant_scalar(crate::Literal::U32(bit_width as u32));
@@ -1184,7 +1185,7 @@ impl<'w> BlockContext<'w> {
}
Mf::FindLsb => MathOp::Ext(spirv::GLOp::FindILsb),
Mf::FindMsb => {
- if arg_ty.scalar_width() == Some(32) {
+ if arg_ty.scalar_width() == Some(4) {
let thing = match arg_scalar_kind {
Some(crate::ScalarKind::Uint) => spirv::GLOp::FindUMsb,
Some(crate::ScalarKind::Sint) => spirv::GLOp::FindSMsb,
@@ -1278,7 +1279,9 @@ impl<'w> BlockContext<'w> {
crate::Expression::CallResult(_)
| crate::Expression::AtomicResult { .. }
| crate::Expression::WorkGroupUniformLoadResult { .. }
- | crate::Expression::RayQueryProceedResult => self.cached[expr_handle],
+ | crate::Expression::RayQueryProceedResult
+ | crate::Expression::SubgroupBallotResult
+ | crate::Expression::SubgroupOperationResult { .. } => self.cached[expr_handle],
crate::Expression::As {
expr,
kind,
@@ -2489,6 +2492,27 @@ impl<'w> BlockContext<'w> {
crate::Statement::RayQuery { query, ref fun } => {
self.write_ray_query_function(query, fun, &mut block);
}
+ crate::Statement::SubgroupBallot {
+ result,
+ ref predicate,
+ } => {
+ self.write_subgroup_ballot(predicate, result, &mut block)?;
+ }
+ crate::Statement::SubgroupCollectiveOperation {
+ ref op,
+ ref collective_op,
+ argument,
+ result,
+ } => {
+ self.write_subgroup_operation(op, collective_op, argument, result, &mut block)?;
+ }
+ crate::Statement::SubgroupGather {
+ ref mode,
+ argument,
+ result,
+ } => {
+ self.write_subgroup_gather(mode, argument, result, &mut block)?;
+ }
}
}
diff --git a/third_party/rust/naga/src/back/spv/helpers.rs b/third_party/rust/naga/src/back/spv/helpers.rs
index 5b6226db85..1fb447e384 100644
--- a/third_party/rust/naga/src/back/spv/helpers.rs
+++ b/third_party/rust/naga/src/back/spv/helpers.rs
@@ -10,8 +10,12 @@ pub(super) fn bytes_to_words(bytes: &[u8]) -> Vec<Word> {
pub(super) fn string_to_words(input: &str) -> Vec<Word> {
let bytes = input.as_bytes();
- let mut words = bytes_to_words(bytes);
+ str_bytes_to_words(bytes)
+}
+
+pub(super) fn str_bytes_to_words(bytes: &[u8]) -> Vec<Word> {
+ let mut words = bytes_to_words(bytes);
if bytes.len() % 4 == 0 {
// nul-termination
words.push(0x0u32);
@@ -20,6 +24,21 @@ pub(super) fn string_to_words(input: &str) -> Vec<Word> {
words
}
+/// split a string into chunks and keep utf8 valid
+#[allow(unstable_name_collisions)]
+pub(super) fn string_to_byte_chunks(input: &str, limit: usize) -> Vec<&[u8]> {
+ let mut offset: usize = 0;
+ let mut start: usize = 0;
+ let mut words = vec![];
+ while offset < input.len() {
+ offset = input.floor_char_boundary(offset + limit);
+ words.push(input[start..offset].as_bytes());
+ start = offset;
+ }
+
+ words
+}
+
pub(super) const fn map_storage_class(space: crate::AddressSpace) -> spirv::StorageClass {
match space {
crate::AddressSpace::Handle => spirv::StorageClass::UniformConstant,
@@ -107,3 +126,35 @@ pub fn global_needs_wrapper(ir_module: &crate::Module, var: &crate::GlobalVariab
_ => true,
}
}
+
+///HACK: this is taken from std unstable, remove it when std's floor_char_boundary is stable
+trait U8Internal {
+ fn is_utf8_char_boundary(&self) -> bool;
+}
+
+impl U8Internal for u8 {
+ fn is_utf8_char_boundary(&self) -> bool {
+ // This is bit magic equivalent to: b < 128 || b >= 192
+ (*self as i8) >= -0x40
+ }
+}
+
+trait StrUnstable {
+ fn floor_char_boundary(&self, index: usize) -> usize;
+}
+
+impl StrUnstable for str {
+ fn floor_char_boundary(&self, index: usize) -> usize {
+ if index >= self.len() {
+ self.len()
+ } else {
+ let lower_bound = index.saturating_sub(3);
+ let new_index = self.as_bytes()[lower_bound..=index]
+ .iter()
+ .rposition(|b| b.is_utf8_char_boundary());
+
+ // SAFETY: we know that the character boundary will be within four bytes
+ unsafe { lower_bound + new_index.unwrap_unchecked() }
+ }
+ }
+}
diff --git a/third_party/rust/naga/src/back/spv/instructions.rs b/third_party/rust/naga/src/back/spv/instructions.rs
index b963793ad3..df2774ab9c 100644
--- a/third_party/rust/naga/src/back/spv/instructions.rs
+++ b/third_party/rust/naga/src/back/spv/instructions.rs
@@ -43,6 +43,42 @@ impl super::Instruction {
instruction
}
+ pub(super) fn source_continued(source: &[u8]) -> Self {
+ let mut instruction = Self::new(Op::SourceContinued);
+ instruction.add_operands(helpers::str_bytes_to_words(source));
+ instruction
+ }
+
+ pub(super) fn source_auto_continued(
+ source_language: spirv::SourceLanguage,
+ version: u32,
+ source: &Option<DebugInfoInner>,
+ ) -> Vec<Self> {
+ let mut instructions = vec![];
+
+ let with_continue = source.as_ref().and_then(|debug_info| {
+ (debug_info.source_code.len() > u16::MAX as usize).then_some(debug_info)
+ });
+ if let Some(debug_info) = with_continue {
+ let mut instruction = Self::new(Op::Source);
+ instruction.add_operand(source_language as u32);
+ instruction.add_operands(helpers::bytes_to_words(&version.to_le_bytes()));
+
+ let words = helpers::string_to_byte_chunks(debug_info.source_code, u16::MAX as usize);
+ instruction.add_operand(debug_info.source_file_id);
+ instruction.add_operands(helpers::str_bytes_to_words(words[0]));
+ instructions.push(instruction);
+ for word_bytes in words[1..].iter() {
+ let instruction_continue = Self::source_continued(word_bytes);
+ instructions.push(instruction_continue);
+ }
+ } else {
+ let instruction = Self::source(source_language, version, source);
+ instructions.push(instruction);
+ }
+ instructions
+ }
+
pub(super) fn name(target_id: Word, name: &str) -> Self {
let mut instruction = Self::new(Op::Name);
instruction.add_operand(target_id);
@@ -1037,6 +1073,73 @@ impl super::Instruction {
instruction.add_operand(semantics_id);
instruction
}
+
+ // Group Instructions
+
+ pub(super) fn group_non_uniform_ballot(
+ result_type_id: Word,
+ id: Word,
+ exec_scope_id: Word,
+ predicate: Word,
+ ) -> Self {
+ let mut instruction = Self::new(Op::GroupNonUniformBallot);
+ instruction.set_type(result_type_id);
+ instruction.set_result(id);
+ instruction.add_operand(exec_scope_id);
+ instruction.add_operand(predicate);
+
+ instruction
+ }
+ pub(super) fn group_non_uniform_broadcast_first(
+ result_type_id: Word,
+ id: Word,
+ exec_scope_id: Word,
+ value: Word,
+ ) -> Self {
+ let mut instruction = Self::new(Op::GroupNonUniformBroadcastFirst);
+ instruction.set_type(result_type_id);
+ instruction.set_result(id);
+ instruction.add_operand(exec_scope_id);
+ instruction.add_operand(value);
+
+ instruction
+ }
+ pub(super) fn group_non_uniform_gather(
+ op: Op,
+ result_type_id: Word,
+ id: Word,
+ exec_scope_id: Word,
+ value: Word,
+ index: Word,
+ ) -> Self {
+ let mut instruction = Self::new(op);
+ instruction.set_type(result_type_id);
+ instruction.set_result(id);
+ instruction.add_operand(exec_scope_id);
+ instruction.add_operand(value);
+ instruction.add_operand(index);
+
+ instruction
+ }
+ pub(super) fn group_non_uniform_arithmetic(
+ op: Op,
+ result_type_id: Word,
+ id: Word,
+ exec_scope_id: Word,
+ group_op: Option<spirv::GroupOperation>,
+ value: Word,
+ ) -> Self {
+ let mut instruction = Self::new(op);
+ instruction.set_type(result_type_id);
+ instruction.set_result(id);
+ instruction.add_operand(exec_scope_id);
+ if let Some(group_op) = group_op {
+ instruction.add_operand(group_op as u32);
+ }
+ instruction.add_operand(value);
+
+ instruction
+ }
}
impl From<crate::StorageFormat> for spirv::ImageFormat {
diff --git a/third_party/rust/naga/src/back/spv/mod.rs b/third_party/rust/naga/src/back/spv/mod.rs
index eb29e3cd8b..38a87049e6 100644
--- a/third_party/rust/naga/src/back/spv/mod.rs
+++ b/third_party/rust/naga/src/back/spv/mod.rs
@@ -13,6 +13,7 @@ mod layout;
mod ray;
mod recyclable;
mod selection;
+mod subgroup;
mod writer;
pub use spirv::Capability;
@@ -70,6 +71,8 @@ pub enum Error {
FeatureNotImplemented(&'static str),
#[error("module is not validated properly: {0}")]
Validation(&'static str),
+ #[error("overrides should not be present at this stage")]
+ Override,
}
#[derive(Default)]
@@ -245,7 +248,7 @@ impl LocalImageType {
/// this, by converting everything possible to a `LocalType` before inspecting
/// it.
///
-/// ## `Localtype` equality and SPIR-V `OpType` uniqueness
+/// ## `LocalType` equality and SPIR-V `OpType` uniqueness
///
/// The definition of `Eq` on `LocalType` is carefully chosen to help us follow
/// certain SPIR-V rules. SPIR-V §2.8 requires some classes of `OpType...`
@@ -454,7 +457,7 @@ impl recyclable::Recyclable for CachedExpressions {
#[derive(Eq, Hash, PartialEq)]
enum CachedConstant {
- Literal(crate::Literal),
+ Literal(crate::proc::HashableLiteral),
Composite {
ty: LookupType,
constituent_ids: Vec<Word>,
@@ -527,6 +530,42 @@ struct FunctionArgument {
handle_id: Word,
}
+/// Tracks the expressions for which the backend emits the following instructions:
+/// - OpConstantTrue
+/// - OpConstantFalse
+/// - OpConstant
+/// - OpConstantComposite
+/// - OpConstantNull
+struct ExpressionConstnessTracker {
+ inner: bit_set::BitSet,
+}
+
+impl ExpressionConstnessTracker {
+ fn from_arena(arena: &crate::Arena<crate::Expression>) -> Self {
+ let mut inner = bit_set::BitSet::new();
+ for (handle, expr) in arena.iter() {
+ let insert = match *expr {
+ crate::Expression::Literal(_)
+ | crate::Expression::ZeroValue(_)
+ | crate::Expression::Constant(_) => true,
+ crate::Expression::Compose { ref components, .. } => {
+ components.iter().all(|h| inner.contains(h.index()))
+ }
+ crate::Expression::Splat { value, .. } => inner.contains(value.index()),
+ _ => false,
+ };
+ if insert {
+ inner.insert(handle.index());
+ }
+ }
+ Self { inner }
+ }
+
+ fn is_const(&self, value: Handle<crate::Expression>) -> bool {
+ self.inner.contains(value.index())
+ }
+}
+
/// General information needed to emit SPIR-V for Naga statements.
struct BlockContext<'w> {
/// The writer handling the module to which this code belongs.
@@ -552,7 +591,7 @@ struct BlockContext<'w> {
temp_list: Vec<Word>,
/// Tracks the constness of `Expression`s residing in `self.ir_function.expressions`
- expression_constness: crate::proc::ExpressionConstnessTracker,
+ expression_constness: ExpressionConstnessTracker,
}
impl BlockContext<'_> {
@@ -725,7 +764,7 @@ impl<'a> Default for Options<'a> {
}
// A subset of options meant to be changed per pipeline.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct PipelineOptions {
diff --git a/third_party/rust/naga/src/back/spv/subgroup.rs b/third_party/rust/naga/src/back/spv/subgroup.rs
new file mode 100644
index 0000000000..c952cb11a7
--- /dev/null
+++ b/third_party/rust/naga/src/back/spv/subgroup.rs
@@ -0,0 +1,207 @@
+use super::{Block, BlockContext, Error, Instruction};
+use crate::{
+ arena::Handle,
+ back::spv::{LocalType, LookupType},
+ TypeInner,
+};
+
+impl<'w> BlockContext<'w> {
+ pub(super) fn write_subgroup_ballot(
+ &mut self,
+ predicate: &Option<Handle<crate::Expression>>,
+ result: Handle<crate::Expression>,
+ block: &mut Block,
+ ) -> Result<(), Error> {
+ self.writer.require_any(
+ "GroupNonUniformBallot",
+ &[spirv::Capability::GroupNonUniformBallot],
+ )?;
+ let vec4_u32_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
+ vector_size: Some(crate::VectorSize::Quad),
+ scalar: crate::Scalar::U32,
+ pointer_space: None,
+ }));
+ let exec_scope_id = self.get_index_constant(spirv::Scope::Subgroup as u32);
+ let predicate = if let Some(predicate) = *predicate {
+ self.cached[predicate]
+ } else {
+ self.writer.get_constant_scalar(crate::Literal::Bool(true))
+ };
+ let id = self.gen_id();
+ block.body.push(Instruction::group_non_uniform_ballot(
+ vec4_u32_type_id,
+ id,
+ exec_scope_id,
+ predicate,
+ ));
+ self.cached[result] = id;
+ Ok(())
+ }
+ pub(super) fn write_subgroup_operation(
+ &mut self,
+ op: &crate::SubgroupOperation,
+ collective_op: &crate::CollectiveOperation,
+ argument: Handle<crate::Expression>,
+ result: Handle<crate::Expression>,
+ block: &mut Block,
+ ) -> Result<(), Error> {
+ use crate::SubgroupOperation as sg;
+ match *op {
+ sg::All | sg::Any => {
+ self.writer.require_any(
+ "GroupNonUniformVote",
+ &[spirv::Capability::GroupNonUniformVote],
+ )?;
+ }
+ _ => {
+ self.writer.require_any(
+ "GroupNonUniformArithmetic",
+ &[spirv::Capability::GroupNonUniformArithmetic],
+ )?;
+ }
+ }
+
+ let id = self.gen_id();
+ let result_ty = &self.fun_info[result].ty;
+ let result_type_id = self.get_expression_type_id(result_ty);
+ let result_ty_inner = result_ty.inner_with(&self.ir_module.types);
+
+ let (is_scalar, scalar) = match *result_ty_inner {
+ TypeInner::Scalar(kind) => (true, kind),
+ TypeInner::Vector { scalar: kind, .. } => (false, kind),
+ _ => unimplemented!(),
+ };
+
+ use crate::ScalarKind as sk;
+ let spirv_op = match (scalar.kind, *op) {
+ (sk::Bool, sg::All) if is_scalar => spirv::Op::GroupNonUniformAll,
+ (sk::Bool, sg::Any) if is_scalar => spirv::Op::GroupNonUniformAny,
+ (_, sg::All | sg::Any) => unimplemented!(),
+
+ (sk::Sint | sk::Uint, sg::Add) => spirv::Op::GroupNonUniformIAdd,
+ (sk::Float, sg::Add) => spirv::Op::GroupNonUniformFAdd,
+ (sk::Sint | sk::Uint, sg::Mul) => spirv::Op::GroupNonUniformIMul,
+ (sk::Float, sg::Mul) => spirv::Op::GroupNonUniformFMul,
+ (sk::Sint, sg::Max) => spirv::Op::GroupNonUniformSMax,
+ (sk::Uint, sg::Max) => spirv::Op::GroupNonUniformUMax,
+ (sk::Float, sg::Max) => spirv::Op::GroupNonUniformFMax,
+ (sk::Sint, sg::Min) => spirv::Op::GroupNonUniformSMin,
+ (sk::Uint, sg::Min) => spirv::Op::GroupNonUniformUMin,
+ (sk::Float, sg::Min) => spirv::Op::GroupNonUniformFMin,
+ (_, sg::Add | sg::Mul | sg::Min | sg::Max) => unimplemented!(),
+
+ (sk::Sint | sk::Uint, sg::And) => spirv::Op::GroupNonUniformBitwiseAnd,
+ (sk::Sint | sk::Uint, sg::Or) => spirv::Op::GroupNonUniformBitwiseOr,
+ (sk::Sint | sk::Uint, sg::Xor) => spirv::Op::GroupNonUniformBitwiseXor,
+ (sk::Bool, sg::And) => spirv::Op::GroupNonUniformLogicalAnd,
+ (sk::Bool, sg::Or) => spirv::Op::GroupNonUniformLogicalOr,
+ (sk::Bool, sg::Xor) => spirv::Op::GroupNonUniformLogicalXor,
+ (_, sg::And | sg::Or | sg::Xor) => unimplemented!(),
+ };
+
+ let exec_scope_id = self.get_index_constant(spirv::Scope::Subgroup as u32);
+
+ use crate::CollectiveOperation as c;
+ let group_op = match *op {
+ sg::All | sg::Any => None,
+ _ => Some(match *collective_op {
+ c::Reduce => spirv::GroupOperation::Reduce,
+ c::InclusiveScan => spirv::GroupOperation::InclusiveScan,
+ c::ExclusiveScan => spirv::GroupOperation::ExclusiveScan,
+ }),
+ };
+
+ let arg_id = self.cached[argument];
+ block.body.push(Instruction::group_non_uniform_arithmetic(
+ spirv_op,
+ result_type_id,
+ id,
+ exec_scope_id,
+ group_op,
+ arg_id,
+ ));
+ self.cached[result] = id;
+ Ok(())
+ }
+ pub(super) fn write_subgroup_gather(
+ &mut self,
+ mode: &crate::GatherMode,
+ argument: Handle<crate::Expression>,
+ result: Handle<crate::Expression>,
+ block: &mut Block,
+ ) -> Result<(), Error> {
+ self.writer.require_any(
+ "GroupNonUniformBallot",
+ &[spirv::Capability::GroupNonUniformBallot],
+ )?;
+ match *mode {
+ crate::GatherMode::BroadcastFirst | crate::GatherMode::Broadcast(_) => {
+ self.writer.require_any(
+ "GroupNonUniformBallot",
+ &[spirv::Capability::GroupNonUniformBallot],
+ )?;
+ }
+ crate::GatherMode::Shuffle(_) | crate::GatherMode::ShuffleXor(_) => {
+ self.writer.require_any(
+ "GroupNonUniformShuffle",
+ &[spirv::Capability::GroupNonUniformShuffle],
+ )?;
+ }
+ crate::GatherMode::ShuffleDown(_) | crate::GatherMode::ShuffleUp(_) => {
+ self.writer.require_any(
+ "GroupNonUniformShuffleRelative",
+ &[spirv::Capability::GroupNonUniformShuffleRelative],
+ )?;
+ }
+ }
+
+ let id = self.gen_id();
+ let result_ty = &self.fun_info[result].ty;
+ let result_type_id = self.get_expression_type_id(result_ty);
+
+ let exec_scope_id = self.get_index_constant(spirv::Scope::Subgroup as u32);
+
+ let arg_id = self.cached[argument];
+ match *mode {
+ crate::GatherMode::BroadcastFirst => {
+ block
+ .body
+ .push(Instruction::group_non_uniform_broadcast_first(
+ result_type_id,
+ id,
+ exec_scope_id,
+ arg_id,
+ ));
+ }
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ let index_id = self.cached[index];
+ let op = match *mode {
+ crate::GatherMode::BroadcastFirst => unreachable!(),
+ // Use shuffle to emit broadcast to allow the index to
+ // be dynamically uniform on Vulkan 1.1. The argument to
+ // OpGroupNonUniformBroadcast must be a constant pre SPIR-V
+ // 1.5 (vulkan 1.2)
+ crate::GatherMode::Broadcast(_) => spirv::Op::GroupNonUniformShuffle,
+ crate::GatherMode::Shuffle(_) => spirv::Op::GroupNonUniformShuffle,
+ crate::GatherMode::ShuffleDown(_) => spirv::Op::GroupNonUniformShuffleDown,
+ crate::GatherMode::ShuffleUp(_) => spirv::Op::GroupNonUniformShuffleUp,
+ crate::GatherMode::ShuffleXor(_) => spirv::Op::GroupNonUniformShuffleXor,
+ };
+ block.body.push(Instruction::group_non_uniform_gather(
+ op,
+ result_type_id,
+ id,
+ exec_scope_id,
+ arg_id,
+ index_id,
+ ));
+ }
+ }
+ self.cached[result] = id;
+ Ok(())
+ }
+}
diff --git a/third_party/rust/naga/src/back/spv/writer.rs b/third_party/rust/naga/src/back/spv/writer.rs
index a5065e0623..73a16c273e 100644
--- a/third_party/rust/naga/src/back/spv/writer.rs
+++ b/third_party/rust/naga/src/back/spv/writer.rs
@@ -615,7 +615,7 @@ impl Writer {
// Steal the Writer's temp list for a bit.
temp_list: std::mem::take(&mut self.temp_list),
writer: self,
- expression_constness: crate::proc::ExpressionConstnessTracker::from_arena(
+ expression_constness: super::ExpressionConstnessTracker::from_arena(
&ir_function.expressions,
),
};
@@ -970,6 +970,11 @@ impl Writer {
handle: Handle<crate::Type>,
) -> Result<Word, Error> {
let ty = &arena[handle];
+ // If it's a type that needs SPIR-V capabilities, request them now.
+ // This needs to happen regardless of the LocalType lookup succeeding,
+ // because some types which map to the same LocalType have different
+ // capability requirements. See https://github.com/gfx-rs/wgpu/issues/5569
+ self.request_type_capabilities(&ty.inner)?;
let id = if let Some(local) = make_local(&ty.inner) {
// This type can be represented as a `LocalType`, so check if we've
// already written an instruction for it. If not, do so now, with
@@ -985,10 +990,6 @@ impl Writer {
self.write_type_declaration_local(id, local);
- // If it's a type that needs SPIR-V capabilities, request them now,
- // so write_type_declaration_local can stay infallible.
- self.request_type_capabilities(&ty.inner)?;
-
id
}
}
@@ -1150,7 +1151,7 @@ impl Writer {
}
pub(super) fn get_constant_scalar(&mut self, value: crate::Literal) -> Word {
- let scalar = CachedConstant::Literal(value);
+ let scalar = CachedConstant::Literal(value.into());
if let Some(&id) = self.cached_constants.get(&scalar) {
return id;
}
@@ -1258,7 +1259,7 @@ impl Writer {
ir_module: &crate::Module,
mod_info: &ModuleInfo,
) -> Result<Word, Error> {
- let id = match ir_module.const_expressions[handle] {
+ let id = match ir_module.global_expressions[handle] {
crate::Expression::Literal(literal) => self.get_constant_scalar(literal),
crate::Expression::Constant(constant) => {
let constant = &ir_module.constants[constant];
@@ -1272,7 +1273,7 @@ impl Writer {
let component_ids: Vec<_> = crate::proc::flatten_compose(
ty,
components,
- &ir_module.const_expressions,
+ &ir_module.global_expressions,
&ir_module.types,
)
.map(|component| self.constant_ids[component.index()])
@@ -1310,7 +1311,11 @@ impl Writer {
spirv::MemorySemantics::WORKGROUP_MEMORY,
flags.contains(crate::Barrier::WORK_GROUP),
);
- let exec_scope_id = self.get_index_constant(spirv::Scope::Workgroup as u32);
+ let exec_scope_id = if flags.contains(crate::Barrier::SUB_GROUP) {
+ self.get_index_constant(spirv::Scope::Subgroup as u32)
+ } else {
+ self.get_index_constant(spirv::Scope::Workgroup as u32)
+ };
let mem_scope_id = self.get_index_constant(memory_scope as u32);
let semantics_id = self.get_index_constant(semantics.bits());
block.body.push(Instruction::control_barrier(
@@ -1585,6 +1590,41 @@ impl Writer {
Bi::WorkGroupId => BuiltIn::WorkgroupId,
Bi::WorkGroupSize => BuiltIn::WorkgroupSize,
Bi::NumWorkGroups => BuiltIn::NumWorkgroups,
+ // Subgroup
+ Bi::NumSubgroups => {
+ self.require_any(
+ "`num_subgroups` built-in",
+ &[spirv::Capability::GroupNonUniform],
+ )?;
+ BuiltIn::NumSubgroups
+ }
+ Bi::SubgroupId => {
+ self.require_any(
+ "`subgroup_id` built-in",
+ &[spirv::Capability::GroupNonUniform],
+ )?;
+ BuiltIn::SubgroupId
+ }
+ Bi::SubgroupSize => {
+ self.require_any(
+ "`subgroup_size` built-in",
+ &[
+ spirv::Capability::GroupNonUniform,
+ spirv::Capability::SubgroupBallotKHR,
+ ],
+ )?;
+ BuiltIn::SubgroupSize
+ }
+ Bi::SubgroupInvocationId => {
+ self.require_any(
+ "`subgroup_invocation_id` built-in",
+ &[
+ spirv::Capability::GroupNonUniform,
+ spirv::Capability::SubgroupBallotKHR,
+ ],
+ )?;
+ BuiltIn::SubgroupLocalInvocationId
+ }
};
self.decorate(id, Decoration::BuiltIn, &[built_in as u32]);
@@ -1899,7 +1939,7 @@ impl Writer {
source_code: debug_info.source_code,
source_file_id,
});
- self.debugs.push(Instruction::source(
+ self.debugs.append(&mut Instruction::source_auto_continued(
spirv::SourceLanguage::Unknown,
0,
&debug_info_inner,
@@ -1914,8 +1954,8 @@ impl Writer {
// write all const-expressions as constants
self.constant_ids
- .resize(ir_module.const_expressions.len(), 0);
- for (handle, _) in ir_module.const_expressions.iter() {
+ .resize(ir_module.global_expressions.len(), 0);
+ for (handle, _) in ir_module.global_expressions.iter() {
self.write_constant_expr(handle, ir_module, mod_info)?;
}
debug_assert!(self.constant_ids.iter().all(|&id| id != 0));
@@ -2029,6 +2069,10 @@ impl Writer {
debug_info: &Option<DebugInfo>,
words: &mut Vec<Word>,
) -> Result<(), Error> {
+ if !ir_module.overrides.is_empty() {
+ return Err(Error::Override);
+ }
+
self.reset();
// Try to find the entry point and corresponding index
diff --git a/third_party/rust/naga/src/back/wgsl/writer.rs b/third_party/rust/naga/src/back/wgsl/writer.rs
index 3039cbbbe4..789f6f62bf 100644
--- a/third_party/rust/naga/src/back/wgsl/writer.rs
+++ b/third_party/rust/naga/src/back/wgsl/writer.rs
@@ -106,6 +106,12 @@ impl<W: Write> Writer<W> {
}
pub fn write(&mut self, module: &Module, info: &valid::ModuleInfo) -> BackendResult {
+ if !module.overrides.is_empty() {
+ return Err(Error::Unimplemented(
+ "Pipeline constants are not yet supported for this back-end".to_string(),
+ ));
+ }
+
self.reset(module);
// Save all ep result types
@@ -918,8 +924,124 @@ impl<W: Write> Writer<W> {
if barrier.contains(crate::Barrier::WORK_GROUP) {
writeln!(self.out, "{level}workgroupBarrier();")?;
}
+
+ if barrier.contains(crate::Barrier::SUB_GROUP) {
+ writeln!(self.out, "{level}subgroupBarrier();")?;
+ }
}
Statement::RayQuery { .. } => unreachable!(),
+ Statement::SubgroupBallot { result, predicate } => {
+ write!(self.out, "{level}")?;
+ let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ self.start_named_expr(module, result, func_ctx, &res_name)?;
+ self.named_expressions.insert(result, res_name);
+
+ write!(self.out, "subgroupBallot(")?;
+ if let Some(predicate) = predicate {
+ self.write_expr(module, predicate, func_ctx)?;
+ }
+ writeln!(self.out, ");")?;
+ }
+ Statement::SubgroupCollectiveOperation {
+ op,
+ collective_op,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ self.start_named_expr(module, result, func_ctx, &res_name)?;
+ self.named_expressions.insert(result, res_name);
+
+ match (collective_op, op) {
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::All) => {
+ write!(self.out, "subgroupAll(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Any) => {
+ write!(self.out, "subgroupAny(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Add) => {
+ write!(self.out, "subgroupAdd(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "subgroupMul(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Max) => {
+ write!(self.out, "subgroupMax(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Min) => {
+ write!(self.out, "subgroupMin(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::And) => {
+ write!(self.out, "subgroupAnd(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Or) => {
+ write!(self.out, "subgroupOr(")?
+ }
+ (crate::CollectiveOperation::Reduce, crate::SubgroupOperation::Xor) => {
+ write!(self.out, "subgroupXor(")?
+ }
+ (crate::CollectiveOperation::ExclusiveScan, crate::SubgroupOperation::Add) => {
+ write!(self.out, "subgroupExclusiveAdd(")?
+ }
+ (crate::CollectiveOperation::ExclusiveScan, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "subgroupExclusiveMul(")?
+ }
+ (crate::CollectiveOperation::InclusiveScan, crate::SubgroupOperation::Add) => {
+ write!(self.out, "subgroupInclusiveAdd(")?
+ }
+ (crate::CollectiveOperation::InclusiveScan, crate::SubgroupOperation::Mul) => {
+ write!(self.out, "subgroupInclusiveMul(")?
+ }
+ _ => unimplemented!(),
+ }
+ self.write_expr(module, argument, func_ctx)?;
+ writeln!(self.out, ");")?;
+ }
+ Statement::SubgroupGather {
+ mode,
+ argument,
+ result,
+ } => {
+ write!(self.out, "{level}")?;
+ let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
+ self.start_named_expr(module, result, func_ctx, &res_name)?;
+ self.named_expressions.insert(result, res_name);
+
+ match mode {
+ crate::GatherMode::BroadcastFirst => {
+ write!(self.out, "subgroupBroadcastFirst(")?;
+ }
+ crate::GatherMode::Broadcast(_) => {
+ write!(self.out, "subgroupBroadcast(")?;
+ }
+ crate::GatherMode::Shuffle(_) => {
+ write!(self.out, "subgroupShuffle(")?;
+ }
+ crate::GatherMode::ShuffleDown(_) => {
+ write!(self.out, "subgroupShuffleDown(")?;
+ }
+ crate::GatherMode::ShuffleUp(_) => {
+ write!(self.out, "subgroupShuffleUp(")?;
+ }
+ crate::GatherMode::ShuffleXor(_) => {
+ write!(self.out, "subgroupShuffleXor(")?;
+ }
+ }
+ self.write_expr(module, argument, func_ctx)?;
+ match mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ write!(self.out, ", ")?;
+ self.write_expr(module, index, func_ctx)?;
+ }
+ }
+ writeln!(self.out, ");")?;
+ }
}
Ok(())
@@ -1070,7 +1192,7 @@ impl<W: Write> Writer<W> {
self.write_possibly_const_expression(
module,
expr,
- &module.const_expressions,
+ &module.global_expressions,
|writer, expr| writer.write_const_expression(module, expr),
)
}
@@ -1199,6 +1321,7 @@ impl<W: Write> Writer<W> {
|writer, expr| writer.write_expr(module, expr, func_ctx),
)?;
}
+ Expression::Override(_) => unreachable!(),
Expression::FunctionArgument(pos) => {
let name_key = func_ctx.argument_key(pos);
let name = &self.names[&name_key];
@@ -1691,6 +1814,8 @@ impl<W: Write> Writer<W> {
Expression::CallResult(_)
| Expression::AtomicResult { .. }
| Expression::RayQueryProceedResult
+ | Expression::SubgroupBallotResult
+ | Expression::SubgroupOperationResult { .. }
| Expression::WorkGroupUniformLoadResult { .. } => {}
}
@@ -1792,6 +1917,10 @@ fn builtin_str(built_in: crate::BuiltIn) -> Result<&'static str, Error> {
Bi::SampleMask => "sample_mask",
Bi::PrimitiveIndex => "primitive_index",
Bi::ViewIndex => "view_index",
+ Bi::NumSubgroups => "num_subgroups",
+ Bi::SubgroupId => "subgroup_id",
+ Bi::SubgroupSize => "subgroup_size",
+ Bi::SubgroupInvocationId => "subgroup_invocation_id",
Bi::BaseInstance
| Bi::BaseVertex
| Bi::ClipDistance
diff --git a/third_party/rust/naga/src/block.rs b/third_party/rust/naga/src/block.rs
index 0abda9da7c..2e86a928f1 100644
--- a/third_party/rust/naga/src/block.rs
+++ b/third_party/rust/naga/src/block.rs
@@ -65,6 +65,12 @@ impl Block {
self.span_info.splice(range.clone(), other.span_info);
self.body.splice(range, other.body);
}
+
+ pub fn span_into_iter(self) -> impl Iterator<Item = (Statement, Span)> {
+ let Block { body, span_info } = self;
+ body.into_iter().zip(span_info)
+ }
+
pub fn span_iter(&self) -> impl Iterator<Item = (&Statement, &Span)> {
let span_iter = self.span_info.iter();
self.body.iter().zip(span_iter)
diff --git a/third_party/rust/naga/src/compact/expressions.rs b/third_party/rust/naga/src/compact/expressions.rs
index 301bbe3240..a418bde301 100644
--- a/third_party/rust/naga/src/compact/expressions.rs
+++ b/third_party/rust/naga/src/compact/expressions.rs
@@ -3,6 +3,7 @@ use crate::arena::{Arena, Handle};
pub struct ExpressionTracer<'tracer> {
pub constants: &'tracer Arena<crate::Constant>,
+ pub overrides: &'tracer Arena<crate::Override>,
/// The arena in which we are currently tracing expressions.
pub expressions: &'tracer Arena<crate::Expression>,
@@ -20,11 +21,11 @@ pub struct ExpressionTracer<'tracer> {
/// the module's constant expression arena.
pub expressions_used: &'tracer mut HandleSet<crate::Expression>,
- /// The used set for the module's `const_expressions` arena.
+ /// The used set for the module's `global_expressions` arena.
///
/// If `None`, we are already tracing the constant expressions,
/// and `expressions_used` already refers to their handle set.
- pub const_expressions_used: Option<&'tracer mut HandleSet<crate::Expression>>,
+ pub global_expressions_used: Option<&'tracer mut HandleSet<crate::Expression>>,
}
impl<'tracer> ExpressionTracer<'tracer> {
@@ -39,11 +40,11 @@ impl<'tracer> ExpressionTracer<'tracer> {
/// marked.
///
/// [fe]: crate::Function::expressions
- /// [ce]: crate::Module::const_expressions
+ /// [ce]: crate::Module::global_expressions
pub fn trace_expressions(&mut self) {
log::trace!(
"entering trace_expression of {}",
- if self.const_expressions_used.is_some() {
+ if self.global_expressions_used.is_some() {
"function expressions"
} else {
"const expressions"
@@ -71,6 +72,7 @@ impl<'tracer> ExpressionTracer<'tracer> {
| Ex::GlobalVariable(_)
| Ex::LocalVariable(_)
| Ex::CallResult(_)
+ | Ex::SubgroupBallotResult
| Ex::RayQueryProceedResult => {}
Ex::Constant(handle) => {
@@ -83,11 +85,16 @@ impl<'tracer> ExpressionTracer<'tracer> {
// and the constant refers to the initializer, it must
// precede `expr` in the arena.
let init = self.constants[handle].init;
- match self.const_expressions_used {
+ match self.global_expressions_used {
Some(ref mut used) => used.insert(init),
None => self.expressions_used.insert(init),
}
}
+ Ex::Override(_) => {
+ // All overrides are considered used by definition. We mark
+ // their types and initialization expressions as used in
+ // `compact::compact`, so we have no more work to do here.
+ }
Ex::ZeroValue(ty) => self.types_used.insert(ty),
Ex::Compose { ty, ref components } => {
self.types_used.insert(ty);
@@ -116,7 +123,7 @@ impl<'tracer> ExpressionTracer<'tracer> {
self.expressions_used
.insert_iter([image, sampler, coordinate]);
self.expressions_used.insert_iter(array_index);
- match self.const_expressions_used {
+ match self.global_expressions_used {
Some(ref mut used) => used.insert_iter(offset),
None => self.expressions_used.insert_iter(offset),
}
@@ -186,6 +193,7 @@ impl<'tracer> ExpressionTracer<'tracer> {
Ex::AtomicResult { ty, comparison: _ } => self.types_used.insert(ty),
Ex::WorkGroupUniformLoadResult { ty } => self.types_used.insert(ty),
Ex::ArrayLength(expr) => self.expressions_used.insert(expr),
+ Ex::SubgroupOperationResult { ty } => self.types_used.insert(ty),
Ex::RayQueryGetIntersection {
query,
committed: _,
@@ -217,8 +225,12 @@ impl ModuleMap {
| Ex::GlobalVariable(_)
| Ex::LocalVariable(_)
| Ex::CallResult(_)
+ | Ex::SubgroupBallotResult
| Ex::RayQueryProceedResult => {}
+ // All overrides are retained, so their handles never change.
+ Ex::Override(_) => {}
+
// Expressions that contain handles that need to be adjusted.
Ex::Constant(ref mut constant) => self.constants.adjust(constant),
Ex::ZeroValue(ref mut ty) => self.types.adjust(ty),
@@ -267,7 +279,7 @@ impl ModuleMap {
adjust(coordinate);
operand_map.adjust_option(array_index);
if let Some(ref mut offset) = *offset {
- self.const_expressions.adjust(offset);
+ self.global_expressions.adjust(offset);
}
self.adjust_sample_level(level, operand_map);
operand_map.adjust_option(depth_ref);
@@ -344,6 +356,7 @@ impl ModuleMap {
comparison: _,
} => self.types.adjust(ty),
Ex::WorkGroupUniformLoadResult { ref mut ty } => self.types.adjust(ty),
+ Ex::SubgroupOperationResult { ref mut ty } => self.types.adjust(ty),
Ex::ArrayLength(ref mut expr) => adjust(expr),
Ex::RayQueryGetIntersection {
ref mut query,
diff --git a/third_party/rust/naga/src/compact/functions.rs b/third_party/rust/naga/src/compact/functions.rs
index b0d08c7e96..4ac2223eb7 100644
--- a/third_party/rust/naga/src/compact/functions.rs
+++ b/third_party/rust/naga/src/compact/functions.rs
@@ -4,10 +4,11 @@ use super::{FunctionMap, ModuleMap};
pub struct FunctionTracer<'a> {
pub function: &'a crate::Function,
pub constants: &'a crate::Arena<crate::Constant>,
+ pub overrides: &'a crate::Arena<crate::Override>,
pub types_used: &'a mut HandleSet<crate::Type>,
pub constants_used: &'a mut HandleSet<crate::Constant>,
- pub const_expressions_used: &'a mut HandleSet<crate::Expression>,
+ pub global_expressions_used: &'a mut HandleSet<crate::Expression>,
/// Function-local expressions used.
pub expressions_used: HandleSet<crate::Expression>,
@@ -47,12 +48,13 @@ impl<'a> FunctionTracer<'a> {
fn as_expression(&mut self) -> super::expressions::ExpressionTracer {
super::expressions::ExpressionTracer {
constants: self.constants,
+ overrides: self.overrides,
expressions: &self.function.expressions,
types_used: self.types_used,
constants_used: self.constants_used,
expressions_used: &mut self.expressions_used,
- const_expressions_used: Some(&mut self.const_expressions_used),
+ global_expressions_used: Some(&mut self.global_expressions_used),
}
}
}
diff --git a/third_party/rust/naga/src/compact/mod.rs b/third_party/rust/naga/src/compact/mod.rs
index b4e57ed5c9..0d7a37b579 100644
--- a/third_party/rust/naga/src/compact/mod.rs
+++ b/third_party/rust/naga/src/compact/mod.rs
@@ -38,7 +38,7 @@ pub fn compact(module: &mut crate::Module) {
log::trace!("tracing global {:?}", global.name);
module_tracer.types_used.insert(global.ty);
if let Some(init) = global.init {
- module_tracer.const_expressions_used.insert(init);
+ module_tracer.global_expressions_used.insert(init);
}
}
}
@@ -50,7 +50,15 @@ pub fn compact(module: &mut crate::Module) {
for (handle, constant) in module.constants.iter() {
if constant.name.is_some() {
module_tracer.constants_used.insert(handle);
- module_tracer.const_expressions_used.insert(constant.init);
+ module_tracer.global_expressions_used.insert(constant.init);
+ }
+ }
+
+ // We treat all overrides as used by definition.
+ for (_, override_) in module.overrides.iter() {
+ module_tracer.types_used.insert(override_.ty);
+ if let Some(init) = override_.init {
+ module_tracer.global_expressions_used.insert(init);
}
}
@@ -137,9 +145,9 @@ pub fn compact(module: &mut crate::Module) {
// Drop unused constant expressions, reusing existing storage.
log::trace!("adjusting constant expressions");
- module.const_expressions.retain_mut(|handle, expr| {
- if module_map.const_expressions.used(handle) {
- module_map.adjust_expression(expr, &module_map.const_expressions);
+ module.global_expressions.retain_mut(|handle, expr| {
+ if module_map.global_expressions.used(handle) {
+ module_map.adjust_expression(expr, &module_map.global_expressions);
true
} else {
false
@@ -151,20 +159,29 @@ pub fn compact(module: &mut crate::Module) {
module.constants.retain_mut(|handle, constant| {
if module_map.constants.used(handle) {
module_map.types.adjust(&mut constant.ty);
- module_map.const_expressions.adjust(&mut constant.init);
+ module_map.global_expressions.adjust(&mut constant.init);
true
} else {
false
}
});
+ // Adjust override types and initializers.
+ log::trace!("adjusting overrides");
+ for (_, override_) in module.overrides.iter_mut() {
+ module_map.types.adjust(&mut override_.ty);
+ if let Some(init) = override_.init.as_mut() {
+ module_map.global_expressions.adjust(init);
+ }
+ }
+
// Adjust global variables' types and initializers.
log::trace!("adjusting global variables");
for (_, global) in module.global_variables.iter_mut() {
log::trace!("adjusting global {:?}", global.name);
module_map.types.adjust(&mut global.ty);
if let Some(ref mut init) = global.init {
- module_map.const_expressions.adjust(init);
+ module_map.global_expressions.adjust(init);
}
}
@@ -193,7 +210,7 @@ struct ModuleTracer<'module> {
module: &'module crate::Module,
types_used: HandleSet<crate::Type>,
constants_used: HandleSet<crate::Constant>,
- const_expressions_used: HandleSet<crate::Expression>,
+ global_expressions_used: HandleSet<crate::Expression>,
}
impl<'module> ModuleTracer<'module> {
@@ -202,7 +219,7 @@ impl<'module> ModuleTracer<'module> {
module,
types_used: HandleSet::for_arena(&module.types),
constants_used: HandleSet::for_arena(&module.constants),
- const_expressions_used: HandleSet::for_arena(&module.const_expressions),
+ global_expressions_used: HandleSet::for_arena(&module.global_expressions),
}
}
@@ -233,12 +250,13 @@ impl<'module> ModuleTracer<'module> {
fn as_const_expression(&mut self) -> expressions::ExpressionTracer {
expressions::ExpressionTracer {
- expressions: &self.module.const_expressions,
+ expressions: &self.module.global_expressions,
constants: &self.module.constants,
+ overrides: &self.module.overrides,
types_used: &mut self.types_used,
constants_used: &mut self.constants_used,
- expressions_used: &mut self.const_expressions_used,
- const_expressions_used: None,
+ expressions_used: &mut self.global_expressions_used,
+ global_expressions_used: None,
}
}
@@ -249,9 +267,10 @@ impl<'module> ModuleTracer<'module> {
FunctionTracer {
function,
constants: &self.module.constants,
+ overrides: &self.module.overrides,
types_used: &mut self.types_used,
constants_used: &mut self.constants_used,
- const_expressions_used: &mut self.const_expressions_used,
+ global_expressions_used: &mut self.global_expressions_used,
expressions_used: HandleSet::for_arena(&function.expressions),
}
}
@@ -260,7 +279,7 @@ impl<'module> ModuleTracer<'module> {
struct ModuleMap {
types: HandleMap<crate::Type>,
constants: HandleMap<crate::Constant>,
- const_expressions: HandleMap<crate::Expression>,
+ global_expressions: HandleMap<crate::Expression>,
}
impl From<ModuleTracer<'_>> for ModuleMap {
@@ -268,7 +287,7 @@ impl From<ModuleTracer<'_>> for ModuleMap {
ModuleMap {
types: HandleMap::from_set(used.types_used),
constants: HandleMap::from_set(used.constants_used),
- const_expressions: HandleMap::from_set(used.const_expressions_used),
+ global_expressions: HandleMap::from_set(used.global_expressions_used),
}
}
}
diff --git a/third_party/rust/naga/src/compact/statements.rs b/third_party/rust/naga/src/compact/statements.rs
index 0698b57258..a124281bc1 100644
--- a/third_party/rust/naga/src/compact/statements.rs
+++ b/third_party/rust/naga/src/compact/statements.rs
@@ -97,6 +97,39 @@ impl FunctionTracer<'_> {
self.expressions_used.insert(query);
self.trace_ray_query_function(fun);
}
+ St::SubgroupBallot { result, predicate } => {
+ if let Some(predicate) = predicate {
+ self.expressions_used.insert(predicate)
+ }
+ self.expressions_used.insert(result)
+ }
+ St::SubgroupCollectiveOperation {
+ op: _,
+ collective_op: _,
+ argument,
+ result,
+ } => {
+ self.expressions_used.insert(argument);
+ self.expressions_used.insert(result)
+ }
+ St::SubgroupGather {
+ mode,
+ argument,
+ result,
+ } => {
+ match mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ self.expressions_used.insert(index)
+ }
+ }
+ self.expressions_used.insert(argument);
+ self.expressions_used.insert(result)
+ }
// Trivial statements.
St::Break
@@ -250,6 +283,40 @@ impl FunctionMap {
adjust(query);
self.adjust_ray_query_function(fun);
}
+ St::SubgroupBallot {
+ ref mut result,
+ ref mut predicate,
+ } => {
+ if let Some(ref mut predicate) = *predicate {
+ adjust(predicate);
+ }
+ adjust(result);
+ }
+ St::SubgroupCollectiveOperation {
+ op: _,
+ collective_op: _,
+ ref mut argument,
+ ref mut result,
+ } => {
+ adjust(argument);
+ adjust(result);
+ }
+ St::SubgroupGather {
+ ref mut mode,
+ ref mut argument,
+ ref mut result,
+ } => {
+ match *mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(ref mut index)
+ | crate::GatherMode::Shuffle(ref mut index)
+ | crate::GatherMode::ShuffleDown(ref mut index)
+ | crate::GatherMode::ShuffleUp(ref mut index)
+ | crate::GatherMode::ShuffleXor(ref mut index) => adjust(index),
+ }
+ adjust(argument);
+ adjust(result);
+ }
// Trivial statements.
St::Break
diff --git a/third_party/rust/naga/src/error.rs b/third_party/rust/naga/src/error.rs
new file mode 100644
index 0000000000..5f2e28360b
--- /dev/null
+++ b/third_party/rust/naga/src/error.rs
@@ -0,0 +1,74 @@
+use std::{error::Error, fmt};
+
+#[derive(Clone, Debug)]
+pub struct ShaderError<E> {
+ /// The source code of the shader.
+ pub source: String,
+ pub label: Option<String>,
+ pub inner: Box<E>,
+}
+
+#[cfg(feature = "wgsl-in")]
+impl fmt::Display for ShaderError<crate::front::wgsl::ParseError> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let label = self.label.as_deref().unwrap_or_default();
+ let string = self.inner.emit_to_string(&self.source);
+ write!(f, "\nShader '{label}' parsing {string}")
+ }
+}
+#[cfg(feature = "glsl-in")]
+impl fmt::Display for ShaderError<crate::front::glsl::ParseErrors> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let label = self.label.as_deref().unwrap_or_default();
+ let string = self.inner.emit_to_string(&self.source);
+ write!(f, "\nShader '{label}' parsing {string}")
+ }
+}
+#[cfg(feature = "spv-in")]
+impl fmt::Display for ShaderError<crate::front::spv::Error> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let label = self.label.as_deref().unwrap_or_default();
+ let string = self.inner.emit_to_string(&self.source);
+ write!(f, "\nShader '{label}' parsing {string}")
+ }
+}
+impl fmt::Display for ShaderError<crate::WithSpan<crate::valid::ValidationError>> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use codespan_reporting::{
+ diagnostic::{Diagnostic, Label},
+ files::SimpleFile,
+ term,
+ };
+
+ let label = self.label.as_deref().unwrap_or_default();
+ let files = SimpleFile::new(label, &self.source);
+ let config = term::Config::default();
+ let mut writer = term::termcolor::NoColor::new(Vec::new());
+
+ let diagnostic = Diagnostic::error().with_labels(
+ self.inner
+ .spans()
+ .map(|&(span, ref desc)| {
+ Label::primary((), span.to_range().unwrap()).with_message(desc.to_owned())
+ })
+ .collect(),
+ );
+
+ term::emit(&mut writer, &config, &files, &diagnostic).expect("cannot write error");
+
+ write!(
+ f,
+ "\nShader validation {}",
+ String::from_utf8_lossy(&writer.into_inner())
+ )
+ }
+}
+impl<E> Error for ShaderError<E>
+where
+ ShaderError<E>: fmt::Display,
+ E: Error + 'static,
+{
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ Some(&self.inner)
+ }
+}
diff --git a/third_party/rust/naga/src/front/glsl/context.rs b/third_party/rust/naga/src/front/glsl/context.rs
index f26c57965d..6ba7df593a 100644
--- a/third_party/rust/naga/src/front/glsl/context.rs
+++ b/third_party/rust/naga/src/front/glsl/context.rs
@@ -77,12 +77,19 @@ pub struct Context<'a> {
pub body: Block,
pub module: &'a mut crate::Module,
pub is_const: bool,
- /// Tracks the constness of `Expression`s residing in `self.expressions`
- pub expression_constness: crate::proc::ExpressionConstnessTracker,
+ /// Tracks the expression kind of `Expression`s residing in `self.expressions`
+ pub local_expression_kind_tracker: crate::proc::ExpressionKindTracker,
+ /// Tracks the expression kind of `Expression`s residing in `self.module.global_expressions`
+ pub global_expression_kind_tracker: &'a mut crate::proc::ExpressionKindTracker,
}
impl<'a> Context<'a> {
- pub fn new(frontend: &Frontend, module: &'a mut crate::Module, is_const: bool) -> Result<Self> {
+ pub fn new(
+ frontend: &Frontend,
+ module: &'a mut crate::Module,
+ is_const: bool,
+ global_expression_kind_tracker: &'a mut crate::proc::ExpressionKindTracker,
+ ) -> Result<Self> {
let mut this = Context {
expressions: Arena::new(),
locals: Arena::new(),
@@ -101,7 +108,8 @@ impl<'a> Context<'a> {
body: Block::new(),
module,
is_const: false,
- expression_constness: crate::proc::ExpressionConstnessTracker::new(),
+ local_expression_kind_tracker: crate::proc::ExpressionKindTracker::new(),
+ global_expression_kind_tracker,
};
this.emit_start();
@@ -249,40 +257,24 @@ impl<'a> Context<'a> {
pub fn add_expression(&mut self, expr: Expression, meta: Span) -> Result<Handle<Expression>> {
let mut eval = if self.is_const {
- crate::proc::ConstantEvaluator::for_glsl_module(self.module)
+ crate::proc::ConstantEvaluator::for_glsl_module(
+ self.module,
+ self.global_expression_kind_tracker,
+ )
} else {
crate::proc::ConstantEvaluator::for_glsl_function(
self.module,
&mut self.expressions,
- &mut self.expression_constness,
+ &mut self.local_expression_kind_tracker,
&mut self.emitter,
&mut self.body,
)
};
- let res = eval.try_eval_and_append(&expr, meta).map_err(|e| Error {
+ eval.try_eval_and_append(expr, meta).map_err(|e| Error {
kind: e.into(),
meta,
- });
-
- match res {
- Ok(expr) => Ok(expr),
- Err(e) => {
- if self.is_const {
- Err(e)
- } else {
- let needs_pre_emit = expr.needs_pre_emit();
- if needs_pre_emit {
- self.body.extend(self.emitter.finish(&self.expressions));
- }
- let h = self.expressions.append(expr, meta);
- if needs_pre_emit {
- self.emitter.start(&self.expressions);
- }
- Ok(h)
- }
- }
- }
+ })
}
/// Add variable to current scope
@@ -1479,7 +1471,7 @@ impl Index<Handle<Expression>> for Context<'_> {
fn index(&self, index: Handle<Expression>) -> &Self::Output {
if self.is_const {
- &self.module.const_expressions[index]
+ &self.module.global_expressions[index]
} else {
&self.expressions[index]
}
diff --git a/third_party/rust/naga/src/front/glsl/error.rs b/third_party/rust/naga/src/front/glsl/error.rs
index bd16ee30bc..e0771437e6 100644
--- a/third_party/rust/naga/src/front/glsl/error.rs
+++ b/third_party/rust/naga/src/front/glsl/error.rs
@@ -1,4 +1,5 @@
use super::token::TokenValue;
+use crate::SourceLocation;
use crate::{proc::ConstantEvaluatorError, Span};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
@@ -137,14 +138,21 @@ pub struct Error {
pub meta: Span,
}
+impl Error {
+ /// Returns a [`SourceLocation`] for the error message.
+ pub fn location(&self, source: &str) -> Option<SourceLocation> {
+ Some(self.meta.location(source))
+ }
+}
+
/// A collection of errors returned during shader parsing.
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq))]
-pub struct ParseError {
+pub struct ParseErrors {
pub errors: Vec<Error>,
}
-impl ParseError {
+impl ParseErrors {
pub fn emit_to_writer(&self, writer: &mut impl WriteColor, source: &str) {
self.emit_to_writer_with_path(writer, source, "glsl");
}
@@ -172,19 +180,19 @@ impl ParseError {
}
}
-impl std::fmt::Display for ParseError {
+impl std::fmt::Display for ParseErrors {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.errors.iter().try_for_each(|e| write!(f, "{e:?}"))
}
}
-impl std::error::Error for ParseError {
+impl std::error::Error for ParseErrors {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
-impl From<Vec<Error>> for ParseError {
+impl From<Vec<Error>> for ParseErrors {
fn from(errors: Vec<Error>) -> Self {
Self { errors }
}
diff --git a/third_party/rust/naga/src/front/glsl/functions.rs b/third_party/rust/naga/src/front/glsl/functions.rs
index 01846eb814..fa1bbef56b 100644
--- a/third_party/rust/naga/src/front/glsl/functions.rs
+++ b/third_party/rust/naga/src/front/glsl/functions.rs
@@ -1236,6 +1236,8 @@ impl Frontend {
let pointer = ctx
.expressions
.append(Expression::GlobalVariable(arg.handle), Default::default());
+ ctx.local_expression_kind_tracker
+ .insert(pointer, crate::proc::ExpressionKind::Runtime);
let ty = ctx.module.global_variables[arg.handle].ty;
@@ -1256,6 +1258,8 @@ impl Frontend {
let value = ctx
.expressions
.append(Expression::FunctionArgument(idx), Default::default());
+ ctx.local_expression_kind_tracker
+ .insert(value, crate::proc::ExpressionKind::Runtime);
ctx.body
.push(Statement::Store { pointer, value }, Default::default());
},
@@ -1285,6 +1289,8 @@ impl Frontend {
let pointer = ctx
.expressions
.append(Expression::GlobalVariable(arg.handle), Default::default());
+ ctx.local_expression_kind_tracker
+ .insert(pointer, crate::proc::ExpressionKind::Runtime);
let ty = ctx.module.global_variables[arg.handle].ty;
@@ -1307,6 +1313,8 @@ impl Frontend {
let load = ctx
.expressions
.append(Expression::Load { pointer }, Default::default());
+ ctx.local_expression_kind_tracker
+ .insert(load, crate::proc::ExpressionKind::Runtime);
ctx.body.push(
Statement::Emit(ctx.expressions.range_from(len)),
Default::default(),
@@ -1329,6 +1337,8 @@ impl Frontend {
let res = ctx
.expressions
.append(Expression::Compose { ty, components }, Default::default());
+ ctx.local_expression_kind_tracker
+ .insert(res, crate::proc::ExpressionKind::Runtime);
ctx.body.push(
Statement::Emit(ctx.expressions.range_from(len)),
Default::default(),
diff --git a/third_party/rust/naga/src/front/glsl/mod.rs b/third_party/rust/naga/src/front/glsl/mod.rs
index 75f3929db4..ea202b2445 100644
--- a/third_party/rust/naga/src/front/glsl/mod.rs
+++ b/third_party/rust/naga/src/front/glsl/mod.rs
@@ -13,7 +13,7 @@ To begin, take a look at the documentation for the [`Frontend`].
*/
pub use ast::{Precision, Profile};
-pub use error::{Error, ErrorKind, ExpectedToken, ParseError};
+pub use error::{Error, ErrorKind, ExpectedToken, ParseErrors};
pub use token::TokenValue;
use crate::{proc::Layouter, FastHashMap, FastHashSet, Handle, Module, ShaderStage, Span, Type};
@@ -196,7 +196,7 @@ impl Frontend {
&mut self,
options: &Options,
source: &str,
- ) -> std::result::Result<Module, ParseError> {
+ ) -> std::result::Result<Module, ParseErrors> {
self.reset(options.stage);
let lexer = lex::Lexer::new(source, &options.defines);
diff --git a/third_party/rust/naga/src/front/glsl/parser.rs b/third_party/rust/naga/src/front/glsl/parser.rs
index 851d2e1d79..28e0808063 100644
--- a/third_party/rust/naga/src/front/glsl/parser.rs
+++ b/third_party/rust/naga/src/front/glsl/parser.rs
@@ -164,9 +164,15 @@ impl<'source> ParsingContext<'source> {
pub fn parse(&mut self, frontend: &mut Frontend) -> Result<Module> {
let mut module = Module::default();
+ let mut global_expression_kind_tracker = crate::proc::ExpressionKindTracker::new();
// Body and expression arena for global initialization
- let mut ctx = Context::new(frontend, &mut module, false)?;
+ let mut ctx = Context::new(
+ frontend,
+ &mut module,
+ false,
+ &mut global_expression_kind_tracker,
+ )?;
while self.peek(frontend).is_some() {
self.parse_external_declaration(frontend, &mut ctx)?;
@@ -196,7 +202,11 @@ impl<'source> ParsingContext<'source> {
frontend: &mut Frontend,
ctx: &mut Context,
) -> Result<(u32, Span)> {
- let (const_expr, meta) = self.parse_constant_expression(frontend, ctx.module)?;
+ let (const_expr, meta) = self.parse_constant_expression(
+ frontend,
+ ctx.module,
+ ctx.global_expression_kind_tracker,
+ )?;
let res = ctx.module.to_ctx().eval_expr_to_u32(const_expr);
@@ -219,8 +229,9 @@ impl<'source> ParsingContext<'source> {
&mut self,
frontend: &mut Frontend,
module: &mut Module,
+ global_expression_kind_tracker: &mut crate::proc::ExpressionKindTracker,
) -> Result<(Handle<Expression>, Span)> {
- let mut ctx = Context::new(frontend, module, true)?;
+ let mut ctx = Context::new(frontend, module, true, global_expression_kind_tracker)?;
let mut stmt_ctx = ctx.stmt_ctx();
let expr = self.parse_conditional(frontend, &mut ctx, &mut stmt_ctx, None)?;
diff --git a/third_party/rust/naga/src/front/glsl/parser/declarations.rs b/third_party/rust/naga/src/front/glsl/parser/declarations.rs
index f5e38fb016..2d253a378d 100644
--- a/third_party/rust/naga/src/front/glsl/parser/declarations.rs
+++ b/third_party/rust/naga/src/front/glsl/parser/declarations.rs
@@ -251,7 +251,7 @@ impl<'source> ParsingContext<'source> {
init.and_then(|expr| ctx.ctx.lift_up_const_expression(expr).ok());
late_initializer = None;
} else if let Some(init) = init {
- if ctx.is_inside_loop || !ctx.ctx.expression_constness.is_const(init) {
+ if ctx.is_inside_loop || !ctx.ctx.local_expression_kind_tracker.is_const(init) {
decl_initializer = None;
late_initializer = Some(init);
} else {
@@ -326,7 +326,12 @@ impl<'source> ParsingContext<'source> {
let result = ty.map(|ty| FunctionResult { ty, binding: None });
- let mut context = Context::new(frontend, ctx.module, false)?;
+ let mut context = Context::new(
+ frontend,
+ ctx.module,
+ false,
+ ctx.global_expression_kind_tracker,
+ )?;
self.parse_function_args(frontend, &mut context)?;
diff --git a/third_party/rust/naga/src/front/glsl/parser/functions.rs b/third_party/rust/naga/src/front/glsl/parser/functions.rs
index d428d74761..d0c889e4d3 100644
--- a/third_party/rust/naga/src/front/glsl/parser/functions.rs
+++ b/third_party/rust/naga/src/front/glsl/parser/functions.rs
@@ -192,10 +192,13 @@ impl<'source> ParsingContext<'source> {
TokenValue::Case => {
self.bump(frontend)?;
- let (const_expr, meta) =
- self.parse_constant_expression(frontend, ctx.module)?;
+ let (const_expr, meta) = self.parse_constant_expression(
+ frontend,
+ ctx.module,
+ ctx.global_expression_kind_tracker,
+ )?;
- match ctx.module.const_expressions[const_expr] {
+ match ctx.module.global_expressions[const_expr] {
Expression::Literal(Literal::I32(value)) => match uint {
// This unchecked cast isn't good, but since
// we only reach this code when the selector
diff --git a/third_party/rust/naga/src/front/glsl/parser_tests.rs b/third_party/rust/naga/src/front/glsl/parser_tests.rs
index 259052cd27..135765ca58 100644
--- a/third_party/rust/naga/src/front/glsl/parser_tests.rs
+++ b/third_party/rust/naga/src/front/glsl/parser_tests.rs
@@ -1,7 +1,7 @@
use super::{
ast::Profile,
error::ExpectedToken,
- error::{Error, ErrorKind, ParseError},
+ error::{Error, ErrorKind, ParseErrors},
token::TokenValue,
Frontend, Options, Span,
};
@@ -21,7 +21,7 @@ fn version() {
)
.err()
.unwrap(),
- ParseError {
+ ParseErrors {
errors: vec![Error {
kind: ErrorKind::InvalidVersion(99000),
meta: Span::new(9, 14)
@@ -37,7 +37,7 @@ fn version() {
)
.err()
.unwrap(),
- ParseError {
+ ParseErrors {
errors: vec![Error {
kind: ErrorKind::InvalidVersion(449),
meta: Span::new(9, 12)
@@ -53,7 +53,7 @@ fn version() {
)
.err()
.unwrap(),
- ParseError {
+ ParseErrors {
errors: vec![Error {
kind: ErrorKind::InvalidProfile("smart".into()),
meta: Span::new(13, 18),
@@ -69,7 +69,7 @@ fn version() {
)
.err()
.unwrap(),
- ParseError {
+ ParseErrors {
errors: vec![
Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedHash,),
@@ -455,7 +455,7 @@ fn functions() {
)
.err()
.unwrap(),
- ParseError {
+ ParseErrors {
errors: vec![Error {
kind: ErrorKind::SemanticError("Function already defined".into()),
meta: Span::new(134, 152),
@@ -539,7 +539,7 @@ fn constants() {
let mut types = module.types.iter();
let mut constants = module.constants.iter();
- let mut const_expressions = module.const_expressions.iter();
+ let mut global_expressions = module.global_expressions.iter();
let (ty_handle, ty) = types.next().unwrap();
assert_eq!(
@@ -550,14 +550,13 @@ fn constants() {
}
);
- let (init_handle, init) = const_expressions.next().unwrap();
+ let (init_handle, init) = global_expressions.next().unwrap();
assert_eq!(init, &Expression::Literal(crate::Literal::F32(1.0)));
assert_eq!(
constants.next().unwrap().1,
&Constant {
name: Some("a".to_owned()),
- r#override: crate::Override::None,
ty: ty_handle,
init: init_handle
}
@@ -567,7 +566,6 @@ fn constants() {
constants.next().unwrap().1,
&Constant {
name: Some("b".to_owned()),
- r#override: crate::Override::None,
ty: ty_handle,
init: init_handle
}
@@ -636,7 +634,7 @@ fn implicit_conversions() {
)
.err()
.unwrap(),
- ParseError {
+ ParseErrors {
errors: vec![Error {
kind: ErrorKind::SemanticError("Unknown function \'test\'".into()),
meta: Span::new(156, 165),
@@ -660,7 +658,7 @@ fn implicit_conversions() {
)
.err()
.unwrap(),
- ParseError {
+ ParseErrors {
errors: vec![Error {
kind: ErrorKind::SemanticError("Ambiguous best function for \'test\'".into()),
meta: Span::new(158, 165),
diff --git a/third_party/rust/naga/src/front/glsl/types.rs b/third_party/rust/naga/src/front/glsl/types.rs
index e87d76fffc..f6836169c0 100644
--- a/third_party/rust/naga/src/front/glsl/types.rs
+++ b/third_party/rust/naga/src/front/glsl/types.rs
@@ -233,7 +233,7 @@ impl Context<'_> {
};
let expressions = if self.is_const {
- &self.module.const_expressions
+ &self.module.global_expressions
} else {
&self.expressions
};
@@ -330,23 +330,25 @@ impl Context<'_> {
expr: Handle<Expression>,
) -> Result<Handle<Expression>> {
let meta = self.expressions.get_span(expr);
- Ok(match self.expressions[expr] {
+ let h = match self.expressions[expr] {
ref expr @ (Expression::Literal(_)
| Expression::Constant(_)
- | Expression::ZeroValue(_)) => self.module.const_expressions.append(expr.clone(), meta),
+ | Expression::ZeroValue(_)) => {
+ self.module.global_expressions.append(expr.clone(), meta)
+ }
Expression::Compose { ty, ref components } => {
let mut components = components.clone();
for component in &mut components {
*component = self.lift_up_const_expression(*component)?;
}
self.module
- .const_expressions
+ .global_expressions
.append(Expression::Compose { ty, components }, meta)
}
Expression::Splat { size, value } => {
let value = self.lift_up_const_expression(value)?;
self.module
- .const_expressions
+ .global_expressions
.append(Expression::Splat { size, value }, meta)
}
_ => {
@@ -355,6 +357,9 @@ impl Context<'_> {
meta,
})
}
- })
+ };
+ self.global_expression_kind_tracker
+ .insert(h, crate::proc::ExpressionKind::Const);
+ Ok(h)
}
}
diff --git a/third_party/rust/naga/src/front/glsl/variables.rs b/third_party/rust/naga/src/front/glsl/variables.rs
index 9d2e7a0e7b..0725fbd94f 100644
--- a/third_party/rust/naga/src/front/glsl/variables.rs
+++ b/third_party/rust/naga/src/front/glsl/variables.rs
@@ -472,7 +472,6 @@ impl Frontend {
let constant = Constant {
name: name.clone(),
- r#override: crate::Override::None,
ty,
init,
};
diff --git a/third_party/rust/naga/src/front/spv/convert.rs b/third_party/rust/naga/src/front/spv/convert.rs
index f0a714fbeb..a6bf0e0451 100644
--- a/third_party/rust/naga/src/front/spv/convert.rs
+++ b/third_party/rust/naga/src/front/spv/convert.rs
@@ -153,6 +153,11 @@ pub(super) fn map_builtin(word: spirv::Word, invariant: bool) -> Result<crate::B
Some(Bi::WorkgroupId) => crate::BuiltIn::WorkGroupId,
Some(Bi::WorkgroupSize) => crate::BuiltIn::WorkGroupSize,
Some(Bi::NumWorkgroups) => crate::BuiltIn::NumWorkGroups,
+ // subgroup
+ Some(Bi::NumSubgroups) => crate::BuiltIn::NumSubgroups,
+ Some(Bi::SubgroupId) => crate::BuiltIn::SubgroupId,
+ Some(Bi::SubgroupSize) => crate::BuiltIn::SubgroupSize,
+ Some(Bi::SubgroupLocalInvocationId) => crate::BuiltIn::SubgroupInvocationId,
_ => return Err(Error::UnsupportedBuiltIn(word)),
})
}
diff --git a/third_party/rust/naga/src/front/spv/error.rs b/third_party/rust/naga/src/front/spv/error.rs
index af025636c0..44beadce98 100644
--- a/third_party/rust/naga/src/front/spv/error.rs
+++ b/third_party/rust/naga/src/front/spv/error.rs
@@ -5,7 +5,7 @@ use codespan_reporting::files::SimpleFile;
use codespan_reporting::term;
use termcolor::{NoColor, WriteColor};
-#[derive(Debug, thiserror::Error)]
+#[derive(Clone, Debug, thiserror::Error)]
pub enum Error {
#[error("invalid header")]
InvalidHeader,
@@ -58,6 +58,8 @@ pub enum Error {
UnknownBinaryOperator(spirv::Op),
#[error("unknown relational function {0:?}")]
UnknownRelationalFunction(spirv::Op),
+ #[error("unsupported group operation %{0}")]
+ UnsupportedGroupOperation(spirv::Word),
#[error("invalid parameter {0:?}")]
InvalidParameter(spirv::Op),
#[error("invalid operand count {1} for {0:?}")]
@@ -118,8 +120,8 @@ pub enum Error {
ControlFlowGraphCycle(crate::front::spv::BlockId),
#[error("recursive function call %{0}")]
FunctionCallCycle(spirv::Word),
- #[error("invalid array size {0:?}")]
- InvalidArraySize(Handle<crate::Constant>),
+ #[error("invalid array size %{0}")]
+ InvalidArraySize(spirv::Word),
#[error("invalid barrier scope %{0}")]
InvalidBarrierScope(spirv::Word),
#[error("invalid barrier memory semantics %{0}")]
@@ -130,6 +132,8 @@ pub enum Error {
come from a binding)"
)]
NonBindingArrayOfImageOrSamplers,
+ #[error("naga only supports specialization constant IDs up to 65535 but was given {0}")]
+ SpecIdTooHigh(u32),
}
impl Error {
diff --git a/third_party/rust/naga/src/front/spv/function.rs b/third_party/rust/naga/src/front/spv/function.rs
index e81ecf5c9b..113ca56313 100644
--- a/third_party/rust/naga/src/front/spv/function.rs
+++ b/third_party/rust/naga/src/front/spv/function.rs
@@ -59,8 +59,11 @@ impl<I: Iterator<Item = u32>> super::Frontend<I> {
})
},
local_variables: Arena::new(),
- expressions: self
- .make_expression_storage(&module.global_variables, &module.constants),
+ expressions: self.make_expression_storage(
+ &module.global_variables,
+ &module.constants,
+ &module.overrides,
+ ),
named_expressions: crate::NamedExpressions::default(),
body: crate::Block::new(),
}
@@ -128,7 +131,8 @@ impl<I: Iterator<Item = u32>> super::Frontend<I> {
expressions: &mut fun.expressions,
local_arena: &mut fun.local_variables,
const_arena: &mut module.constants,
- const_expressions: &mut module.const_expressions,
+ overrides: &mut module.overrides,
+ global_expressions: &mut module.global_expressions,
type_arena: &module.types,
global_arena: &module.global_variables,
arguments: &fun.arguments,
@@ -581,7 +585,8 @@ impl<'function> BlockContext<'function> {
crate::proc::GlobalCtx {
types: self.type_arena,
constants: self.const_arena,
- const_expressions: self.const_expressions,
+ overrides: self.overrides,
+ global_expressions: self.global_expressions,
}
}
diff --git a/third_party/rust/naga/src/front/spv/image.rs b/third_party/rust/naga/src/front/spv/image.rs
index 0f25dd626b..284c4cf7fd 100644
--- a/third_party/rust/naga/src/front/spv/image.rs
+++ b/third_party/rust/naga/src/front/spv/image.rs
@@ -507,11 +507,14 @@ impl<I: Iterator<Item = u32>> super::Frontend<I> {
}
spirv::ImageOperands::CONST_OFFSET => {
let offset_constant = self.next()?;
- let offset_handle = self.lookup_constant.lookup(offset_constant)?.handle;
- let offset_handle = ctx.const_expressions.append(
- crate::Expression::Constant(offset_handle),
- Default::default(),
- );
+ let offset_expr = self
+ .lookup_constant
+ .lookup(offset_constant)?
+ .inner
+ .to_expr();
+ let offset_handle = ctx
+ .global_expressions
+ .append(offset_expr, Default::default());
offset = Some(offset_handle);
words_left -= 1;
}
diff --git a/third_party/rust/naga/src/front/spv/mod.rs b/third_party/rust/naga/src/front/spv/mod.rs
index b793448597..7ac5a18cd6 100644
--- a/third_party/rust/naga/src/front/spv/mod.rs
+++ b/third_party/rust/naga/src/front/spv/mod.rs
@@ -196,7 +196,7 @@ struct Decoration {
location: Option<spirv::Word>,
desc_set: Option<spirv::Word>,
desc_index: Option<spirv::Word>,
- specialization: Option<spirv::Word>,
+ specialization_constant_id: Option<spirv::Word>,
storage_buffer: bool,
offset: Option<spirv::Word>,
array_stride: Option<NonZeroU32>,
@@ -216,11 +216,6 @@ impl Decoration {
}
}
- fn specialization(&self) -> crate::Override {
- self.specialization
- .map_or(crate::Override::None, crate::Override::ByNameOrId)
- }
-
const fn resource_binding(&self) -> Option<crate::ResourceBinding> {
match *self {
Decoration {
@@ -284,8 +279,23 @@ struct LookupType {
}
#[derive(Debug)]
+enum Constant {
+ Constant(Handle<crate::Constant>),
+ Override(Handle<crate::Override>),
+}
+
+impl Constant {
+ const fn to_expr(&self) -> crate::Expression {
+ match *self {
+ Self::Constant(c) => crate::Expression::Constant(c),
+ Self::Override(o) => crate::Expression::Override(o),
+ }
+ }
+}
+
+#[derive(Debug)]
struct LookupConstant {
- handle: Handle<crate::Constant>,
+ inner: Constant,
type_id: spirv::Word,
}
@@ -537,7 +547,8 @@ struct BlockContext<'function> {
local_arena: &'function mut Arena<crate::LocalVariable>,
/// Constants arena of the module being processed
const_arena: &'function mut Arena<crate::Constant>,
- const_expressions: &'function mut Arena<crate::Expression>,
+ overrides: &'function mut Arena<crate::Override>,
+ global_expressions: &'function mut Arena<crate::Expression>,
/// Type arena of the module being processed
type_arena: &'function UniqueArena<crate::Type>,
/// Global arena of the module being processed
@@ -757,7 +768,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
dec.matrix_major = Some(Majority::Row);
}
spirv::Decoration::SpecId => {
- dec.specialization = Some(self.next()?);
+ dec.specialization_constant_id = Some(self.next()?);
}
other => {
log::warn!("Unknown decoration {:?}", other);
@@ -1393,10 +1404,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
inst.expect(5)?;
let init_id = self.next()?;
let lconst = self.lookup_constant.lookup(init_id)?;
- Some(
- ctx.expressions
- .append(crate::Expression::Constant(lconst.handle), span),
- )
+ Some(ctx.expressions.append(lconst.inner.to_expr(), span))
} else {
None
};
@@ -3650,9 +3658,9 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let exec_scope_const = self.lookup_constant.lookup(exec_scope_id)?;
let semantics_const = self.lookup_constant.lookup(semantics_id)?;
- let exec_scope = resolve_constant(ctx.gctx(), exec_scope_const.handle)
+ let exec_scope = resolve_constant(ctx.gctx(), &exec_scope_const.inner)
.ok_or(Error::InvalidBarrierScope(exec_scope_id))?;
- let semantics = resolve_constant(ctx.gctx(), semantics_const.handle)
+ let semantics = resolve_constant(ctx.gctx(), &semantics_const.inner)
.ok_or(Error::InvalidBarrierMemorySemantics(semantics_id))?;
if exec_scope == spirv::Scope::Workgroup as u32 {
@@ -3692,6 +3700,254 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
},
);
}
+ Op::GroupNonUniformBallot => {
+ inst.expect(5)?;
+ block.extend(emitter.finish(ctx.expressions));
+ let result_type_id = self.next()?;
+ let result_id = self.next()?;
+ let exec_scope_id = self.next()?;
+ let predicate_id = self.next()?;
+
+ let exec_scope_const = self.lookup_constant.lookup(exec_scope_id)?;
+ let _exec_scope = resolve_constant(ctx.gctx(), &exec_scope_const.inner)
+ .filter(|exec_scope| *exec_scope == spirv::Scope::Subgroup as u32)
+ .ok_or(Error::InvalidBarrierScope(exec_scope_id))?;
+
+ let predicate = if self
+ .lookup_constant
+ .lookup(predicate_id)
+ .ok()
+ .filter(|predicate_const| match predicate_const.inner {
+ Constant::Constant(constant) => matches!(
+ ctx.gctx().global_expressions[ctx.gctx().constants[constant].init],
+ crate::Expression::Literal(crate::Literal::Bool(true)),
+ ),
+ Constant::Override(_) => false,
+ })
+ .is_some()
+ {
+ None
+ } else {
+ let predicate_lookup = self.lookup_expression.lookup(predicate_id)?;
+ let predicate_handle = get_expr_handle!(predicate_id, predicate_lookup);
+ Some(predicate_handle)
+ };
+
+ let result_handle = ctx
+ .expressions
+ .append(crate::Expression::SubgroupBallotResult, span);
+ self.lookup_expression.insert(
+ result_id,
+ LookupExpression {
+ handle: result_handle,
+ type_id: result_type_id,
+ block_id,
+ },
+ );
+
+ block.push(
+ crate::Statement::SubgroupBallot {
+ result: result_handle,
+ predicate,
+ },
+ span,
+ );
+ emitter.start(ctx.expressions);
+ }
+ spirv::Op::GroupNonUniformAll
+ | spirv::Op::GroupNonUniformAny
+ | spirv::Op::GroupNonUniformIAdd
+ | spirv::Op::GroupNonUniformFAdd
+ | spirv::Op::GroupNonUniformIMul
+ | spirv::Op::GroupNonUniformFMul
+ | spirv::Op::GroupNonUniformSMax
+ | spirv::Op::GroupNonUniformUMax
+ | spirv::Op::GroupNonUniformFMax
+ | spirv::Op::GroupNonUniformSMin
+ | spirv::Op::GroupNonUniformUMin
+ | spirv::Op::GroupNonUniformFMin
+ | spirv::Op::GroupNonUniformBitwiseAnd
+ | spirv::Op::GroupNonUniformBitwiseOr
+ | spirv::Op::GroupNonUniformBitwiseXor
+ | spirv::Op::GroupNonUniformLogicalAnd
+ | spirv::Op::GroupNonUniformLogicalOr
+ | spirv::Op::GroupNonUniformLogicalXor => {
+ block.extend(emitter.finish(ctx.expressions));
+ inst.expect(
+ if matches!(
+ inst.op,
+ spirv::Op::GroupNonUniformAll | spirv::Op::GroupNonUniformAny
+ ) {
+ 5
+ } else {
+ 6
+ },
+ )?;
+ let result_type_id = self.next()?;
+ let result_id = self.next()?;
+ let exec_scope_id = self.next()?;
+ let collective_op_id = match inst.op {
+ spirv::Op::GroupNonUniformAll | spirv::Op::GroupNonUniformAny => {
+ crate::CollectiveOperation::Reduce
+ }
+ _ => {
+ let group_op_id = self.next()?;
+ match spirv::GroupOperation::from_u32(group_op_id) {
+ Some(spirv::GroupOperation::Reduce) => {
+ crate::CollectiveOperation::Reduce
+ }
+ Some(spirv::GroupOperation::InclusiveScan) => {
+ crate::CollectiveOperation::InclusiveScan
+ }
+ Some(spirv::GroupOperation::ExclusiveScan) => {
+ crate::CollectiveOperation::ExclusiveScan
+ }
+ _ => return Err(Error::UnsupportedGroupOperation(group_op_id)),
+ }
+ }
+ };
+ let argument_id = self.next()?;
+
+ let argument_lookup = self.lookup_expression.lookup(argument_id)?;
+ let argument_handle = get_expr_handle!(argument_id, argument_lookup);
+
+ let exec_scope_const = self.lookup_constant.lookup(exec_scope_id)?;
+ let _exec_scope = resolve_constant(ctx.gctx(), &exec_scope_const.inner)
+ .filter(|exec_scope| *exec_scope == spirv::Scope::Subgroup as u32)
+ .ok_or(Error::InvalidBarrierScope(exec_scope_id))?;
+
+ let op_id = match inst.op {
+ spirv::Op::GroupNonUniformAll => crate::SubgroupOperation::All,
+ spirv::Op::GroupNonUniformAny => crate::SubgroupOperation::Any,
+ spirv::Op::GroupNonUniformIAdd | spirv::Op::GroupNonUniformFAdd => {
+ crate::SubgroupOperation::Add
+ }
+ spirv::Op::GroupNonUniformIMul | spirv::Op::GroupNonUniformFMul => {
+ crate::SubgroupOperation::Mul
+ }
+ spirv::Op::GroupNonUniformSMax
+ | spirv::Op::GroupNonUniformUMax
+ | spirv::Op::GroupNonUniformFMax => crate::SubgroupOperation::Max,
+ spirv::Op::GroupNonUniformSMin
+ | spirv::Op::GroupNonUniformUMin
+ | spirv::Op::GroupNonUniformFMin => crate::SubgroupOperation::Min,
+ spirv::Op::GroupNonUniformBitwiseAnd
+ | spirv::Op::GroupNonUniformLogicalAnd => crate::SubgroupOperation::And,
+ spirv::Op::GroupNonUniformBitwiseOr
+ | spirv::Op::GroupNonUniformLogicalOr => crate::SubgroupOperation::Or,
+ spirv::Op::GroupNonUniformBitwiseXor
+ | spirv::Op::GroupNonUniformLogicalXor => crate::SubgroupOperation::Xor,
+ _ => unreachable!(),
+ };
+
+ let result_type = self.lookup_type.lookup(result_type_id)?;
+
+ let result_handle = ctx.expressions.append(
+ crate::Expression::SubgroupOperationResult {
+ ty: result_type.handle,
+ },
+ span,
+ );
+ self.lookup_expression.insert(
+ result_id,
+ LookupExpression {
+ handle: result_handle,
+ type_id: result_type_id,
+ block_id,
+ },
+ );
+
+ block.push(
+ crate::Statement::SubgroupCollectiveOperation {
+ result: result_handle,
+ op: op_id,
+ collective_op: collective_op_id,
+ argument: argument_handle,
+ },
+ span,
+ );
+ emitter.start(ctx.expressions);
+ }
+ Op::GroupNonUniformBroadcastFirst
+ | Op::GroupNonUniformBroadcast
+ | Op::GroupNonUniformShuffle
+ | Op::GroupNonUniformShuffleDown
+ | Op::GroupNonUniformShuffleUp
+ | Op::GroupNonUniformShuffleXor => {
+ inst.expect(
+ if matches!(inst.op, spirv::Op::GroupNonUniformBroadcastFirst) {
+ 5
+ } else {
+ 6
+ },
+ )?;
+ block.extend(emitter.finish(ctx.expressions));
+ let result_type_id = self.next()?;
+ let result_id = self.next()?;
+ let exec_scope_id = self.next()?;
+ let argument_id = self.next()?;
+
+ let argument_lookup = self.lookup_expression.lookup(argument_id)?;
+ let argument_handle = get_expr_handle!(argument_id, argument_lookup);
+
+ let exec_scope_const = self.lookup_constant.lookup(exec_scope_id)?;
+ let _exec_scope = resolve_constant(ctx.gctx(), &exec_scope_const.inner)
+ .filter(|exec_scope| *exec_scope == spirv::Scope::Subgroup as u32)
+ .ok_or(Error::InvalidBarrierScope(exec_scope_id))?;
+
+ let mode = if matches!(inst.op, spirv::Op::GroupNonUniformBroadcastFirst) {
+ crate::GatherMode::BroadcastFirst
+ } else {
+ let index_id = self.next()?;
+ let index_lookup = self.lookup_expression.lookup(index_id)?;
+ let index_handle = get_expr_handle!(index_id, index_lookup);
+ match inst.op {
+ spirv::Op::GroupNonUniformBroadcast => {
+ crate::GatherMode::Broadcast(index_handle)
+ }
+ spirv::Op::GroupNonUniformShuffle => {
+ crate::GatherMode::Shuffle(index_handle)
+ }
+ spirv::Op::GroupNonUniformShuffleDown => {
+ crate::GatherMode::ShuffleDown(index_handle)
+ }
+ spirv::Op::GroupNonUniformShuffleUp => {
+ crate::GatherMode::ShuffleUp(index_handle)
+ }
+ spirv::Op::GroupNonUniformShuffleXor => {
+ crate::GatherMode::ShuffleXor(index_handle)
+ }
+ _ => unreachable!(),
+ }
+ };
+
+ let result_type = self.lookup_type.lookup(result_type_id)?;
+
+ let result_handle = ctx.expressions.append(
+ crate::Expression::SubgroupOperationResult {
+ ty: result_type.handle,
+ },
+ span,
+ );
+ self.lookup_expression.insert(
+ result_id,
+ LookupExpression {
+ handle: result_handle,
+ type_id: result_type_id,
+ block_id,
+ },
+ );
+
+ block.push(
+ crate::Statement::SubgroupGather {
+ result: result_handle,
+ mode,
+ argument: argument_handle,
+ },
+ span,
+ );
+ emitter.start(ctx.expressions);
+ }
_ => return Err(Error::UnsupportedInstruction(self.state, inst.op)),
}
};
@@ -3713,6 +3969,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
&mut self,
globals: &Arena<crate::GlobalVariable>,
constants: &Arena<crate::Constant>,
+ overrides: &Arena<crate::Override>,
) -> Arena<crate::Expression> {
let mut expressions = Arena::new();
#[allow(clippy::panic)]
@@ -3737,8 +3994,11 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
}
// register constants
for (&id, con) in self.lookup_constant.iter() {
- let span = constants.get_span(con.handle);
- let handle = expressions.append(crate::Expression::Constant(con.handle), span);
+ let (expr, span) = match con.inner {
+ Constant::Constant(c) => (crate::Expression::Constant(c), constants.get_span(c)),
+ Constant::Override(o) => (crate::Expression::Override(o), overrides.get_span(o)),
+ };
+ let handle = expressions.append(expr, span);
self.lookup_expression.insert(
id,
LookupExpression {
@@ -3812,7 +4072,10 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
| S::Store { .. }
| S::ImageStore { .. }
| S::Atomic { .. }
- | S::RayQuery { .. } => {}
+ | S::RayQuery { .. }
+ | S::SubgroupBallot { .. }
+ | S::SubgroupCollectiveOperation { .. }
+ | S::SubgroupGather { .. } => {}
S::Call {
function: ref mut callee,
ref arguments,
@@ -3944,10 +4207,16 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
Op::TypeSampledImage => self.parse_type_sampled_image(inst),
Op::TypeSampler => self.parse_type_sampler(inst, &mut module),
Op::Constant | Op::SpecConstant => self.parse_constant(inst, &mut module),
- Op::ConstantComposite => self.parse_composite_constant(inst, &mut module),
+ Op::ConstantComposite | Op::SpecConstantComposite => {
+ self.parse_composite_constant(inst, &mut module)
+ }
Op::ConstantNull | Op::Undef => self.parse_null_constant(inst, &mut module),
- Op::ConstantTrue => self.parse_bool_constant(inst, true, &mut module),
- Op::ConstantFalse => self.parse_bool_constant(inst, false, &mut module),
+ Op::ConstantTrue | Op::SpecConstantTrue => {
+ self.parse_bool_constant(inst, true, &mut module)
+ }
+ Op::ConstantFalse | Op::SpecConstantFalse => {
+ self.parse_bool_constant(inst, false, &mut module)
+ }
Op::Variable => self.parse_global_variable(inst, &mut module),
Op::Function => {
self.switch(ModuleState::Function, inst.op)?;
@@ -4504,9 +4773,9 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let length_id = self.next()?;
let length_const = self.lookup_constant.lookup(length_id)?;
- let size = resolve_constant(module.to_ctx(), length_const.handle)
+ let size = resolve_constant(module.to_ctx(), &length_const.inner)
.and_then(NonZeroU32::new)
- .ok_or(Error::InvalidArraySize(length_const.handle))?;
+ .ok_or(Error::InvalidArraySize(length_id))?;
let decor = self.future_decor.remove(&id).unwrap_or_default();
let base = self.lookup_type.lookup(type_id)?.handle;
@@ -4919,29 +5188,13 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
_ => return Err(Error::UnsupportedType(type_lookup.handle)),
};
- let decor = self.future_decor.remove(&id).unwrap_or_default();
-
let span = self.span_from_with_op(start);
let init = module
- .const_expressions
+ .global_expressions
.append(crate::Expression::Literal(literal), span);
- self.lookup_constant.insert(
- id,
- LookupConstant {
- handle: module.constants.append(
- crate::Constant {
- r#override: decor.specialization(),
- name: decor.name,
- ty,
- init,
- },
- span,
- ),
- type_id,
- },
- );
- Ok(())
+
+ self.insert_parsed_constant(module, id, type_id, ty, init, span)
}
fn parse_composite_constant(
@@ -4965,34 +5218,18 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let span = self.span_from_with_op(start);
let constant = self.lookup_constant.lookup(component_id)?;
let expr = module
- .const_expressions
- .append(crate::Expression::Constant(constant.handle), span);
+ .global_expressions
+ .append(constant.inner.to_expr(), span);
components.push(expr);
}
- let decor = self.future_decor.remove(&id).unwrap_or_default();
-
let span = self.span_from_with_op(start);
let init = module
- .const_expressions
+ .global_expressions
.append(crate::Expression::Compose { ty, components }, span);
- self.lookup_constant.insert(
- id,
- LookupConstant {
- handle: module.constants.append(
- crate::Constant {
- r#override: decor.specialization(),
- name: decor.name,
- ty,
- init,
- },
- span,
- ),
- type_id,
- },
- );
- Ok(())
+
+ self.insert_parsed_constant(module, id, type_id, ty, init, span)
}
fn parse_null_constant(
@@ -5010,23 +5247,11 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let type_lookup = self.lookup_type.lookup(type_id)?;
let ty = type_lookup.handle;
- let decor = self.future_decor.remove(&id).unwrap_or_default();
-
let init = module
- .const_expressions
+ .global_expressions
.append(crate::Expression::ZeroValue(ty), span);
- let handle = module.constants.append(
- crate::Constant {
- r#override: decor.specialization(),
- name: decor.name,
- ty,
- init,
- },
- span,
- );
- self.lookup_constant
- .insert(id, LookupConstant { handle, type_id });
- Ok(())
+
+ self.insert_parsed_constant(module, id, type_id, ty, init, span)
}
fn parse_bool_constant(
@@ -5045,27 +5270,44 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let type_lookup = self.lookup_type.lookup(type_id)?;
let ty = type_lookup.handle;
- let decor = self.future_decor.remove(&id).unwrap_or_default();
-
- let init = module.const_expressions.append(
+ let init = module.global_expressions.append(
crate::Expression::Literal(crate::Literal::Bool(value)),
span,
);
- self.lookup_constant.insert(
- id,
- LookupConstant {
- handle: module.constants.append(
- crate::Constant {
- r#override: decor.specialization(),
- name: decor.name,
- ty,
- init,
- },
- span,
- ),
- type_id,
- },
- );
+
+ self.insert_parsed_constant(module, id, type_id, ty, init, span)
+ }
+
+ fn insert_parsed_constant(
+ &mut self,
+ module: &mut crate::Module,
+ id: u32,
+ type_id: u32,
+ ty: Handle<crate::Type>,
+ init: Handle<crate::Expression>,
+ span: crate::Span,
+ ) -> Result<(), Error> {
+ let decor = self.future_decor.remove(&id).unwrap_or_default();
+
+ let inner = if let Some(id) = decor.specialization_constant_id {
+ let o = crate::Override {
+ name: decor.name,
+ id: Some(id.try_into().map_err(|_| Error::SpecIdTooHigh(id))?),
+ ty,
+ init: Some(init),
+ };
+ Constant::Override(module.overrides.append(o, span))
+ } else {
+ let c = crate::Constant {
+ name: decor.name,
+ ty,
+ init,
+ };
+ Constant::Constant(module.constants.append(c, span))
+ };
+
+ self.lookup_constant
+ .insert(id, LookupConstant { inner, type_id });
Ok(())
}
@@ -5087,8 +5329,8 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let span = self.span_from_with_op(start);
let lconst = self.lookup_constant.lookup(init_id)?;
let expr = module
- .const_expressions
- .append(crate::Expression::Constant(lconst.handle), span);
+ .global_expressions
+ .append(lconst.inner.to_expr(), span);
Some(expr)
} else {
None
@@ -5209,7 +5451,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
match null::generate_default_built_in(
Some(built_in),
ty,
- &mut module.const_expressions,
+ &mut module.global_expressions,
span,
) {
Ok(handle) => Some(handle),
@@ -5231,14 +5473,14 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let handle = null::generate_default_built_in(
built_in,
member.ty,
- &mut module.const_expressions,
+ &mut module.global_expressions,
span,
)?;
components.push(handle);
}
Some(
module
- .const_expressions
+ .global_expressions
.append(crate::Expression::Compose { ty, components }, span),
)
}
@@ -5303,11 +5545,12 @@ fn make_index_literal(
Ok(expr)
}
-fn resolve_constant(
- gctx: crate::proc::GlobalCtx,
- constant: Handle<crate::Constant>,
-) -> Option<u32> {
- match gctx.const_expressions[gctx.constants[constant].init] {
+fn resolve_constant(gctx: crate::proc::GlobalCtx, constant: &Constant) -> Option<u32> {
+ let constant = match *constant {
+ Constant::Constant(constant) => constant,
+ Constant::Override(_) => return None,
+ };
+ match gctx.global_expressions[gctx.constants[constant].init] {
crate::Expression::Literal(crate::Literal::U32(id)) => Some(id),
crate::Expression::Literal(crate::Literal::I32(id)) => Some(id as u32),
_ => None,
diff --git a/third_party/rust/naga/src/front/spv/null.rs b/third_party/rust/naga/src/front/spv/null.rs
index 42cccca80a..c7d3776841 100644
--- a/third_party/rust/naga/src/front/spv/null.rs
+++ b/third_party/rust/naga/src/front/spv/null.rs
@@ -5,14 +5,14 @@ use crate::arena::{Arena, Handle};
pub fn generate_default_built_in(
built_in: Option<crate::BuiltIn>,
ty: Handle<crate::Type>,
- const_expressions: &mut Arena<crate::Expression>,
+ global_expressions: &mut Arena<crate::Expression>,
span: crate::Span,
) -> Result<Handle<crate::Expression>, Error> {
let expr = match built_in {
Some(crate::BuiltIn::Position { .. }) => {
- let zero = const_expressions
+ let zero = global_expressions
.append(crate::Expression::Literal(crate::Literal::F32(0.0)), span);
- let one = const_expressions
+ let one = global_expressions
.append(crate::Expression::Literal(crate::Literal::F32(1.0)), span);
crate::Expression::Compose {
ty,
@@ -27,5 +27,5 @@ pub fn generate_default_built_in(
// Note: `crate::BuiltIn::ClipDistance` is intentionally left for the default path
_ => crate::Expression::ZeroValue(ty),
};
- Ok(const_expressions.append(expr, span))
+ Ok(global_expressions.append(expr, span))
}
diff --git a/third_party/rust/naga/src/front/wgsl/error.rs b/third_party/rust/naga/src/front/wgsl/error.rs
index 54aa8296b1..dc1339521c 100644
--- a/third_party/rust/naga/src/front/wgsl/error.rs
+++ b/third_party/rust/naga/src/front/wgsl/error.rs
@@ -13,6 +13,7 @@ use thiserror::Error;
#[derive(Clone, Debug)]
pub struct ParseError {
message: String,
+ // The first span should be the primary span, and the other ones should be complementary.
labels: Vec<(Span, Cow<'static, str>)>,
notes: Vec<String>,
}
@@ -190,7 +191,7 @@ pub enum Error<'a> {
expected: String,
got: String,
},
- MissingType(Span),
+ DeclMissingTypeAndInit(Span),
MissingAttribute(&'static str, Span),
InvalidAtomicPointer(Span),
InvalidAtomicOperandType(Span),
@@ -269,6 +270,11 @@ pub enum Error<'a> {
scalar: String,
inner: ConstantEvaluatorError,
},
+ ExceededLimitForNestedBraces {
+ span: Span,
+ limit: u8,
+ },
+ PipelineConstantIDValue(Span),
}
impl<'a> Error<'a> {
@@ -518,11 +524,11 @@ impl<'a> Error<'a> {
notes: vec![],
}
}
- Error::MissingType(name_span) => ParseError {
- message: format!("variable `{}` needs a type", &source[name_span]),
+ Error::DeclMissingTypeAndInit(name_span) => ParseError {
+ message: format!("declaration of `{}` needs a type specifier or initializer", &source[name_span]),
labels: vec![(
name_span,
- format!("definition of `{}`", &source[name_span]).into(),
+ "needs a type specifier or initializer".into(),
)],
notes: vec![],
},
@@ -770,6 +776,21 @@ impl<'a> Error<'a> {
format!("the expression should have been converted to have {} scalar type", scalar),
]
},
+ Error::ExceededLimitForNestedBraces { span, limit } => ParseError {
+ message: "brace nesting limit reached".into(),
+ labels: vec![(span, "limit reached at this brace".into())],
+ notes: vec![
+ format!("nesting limit is currently set to {limit}"),
+ ],
+ },
+ Error::PipelineConstantIDValue(span) => ParseError {
+ message: "pipeline constant ID must be between 0 and 65535 inclusive".to_string(),
+ labels: vec![(
+ span,
+ "must be between 0 and 65535 inclusive".into(),
+ )],
+ notes: vec![],
+ },
}
}
}
diff --git a/third_party/rust/naga/src/front/wgsl/index.rs b/third_party/rust/naga/src/front/wgsl/index.rs
index a5524fe8f1..593405508f 100644
--- a/third_party/rust/naga/src/front/wgsl/index.rs
+++ b/third_party/rust/naga/src/front/wgsl/index.rs
@@ -187,6 +187,7 @@ const fn decl_ident<'a>(decl: &ast::GlobalDecl<'a>) -> ast::Ident<'a> {
ast::GlobalDeclKind::Fn(ref f) => f.name,
ast::GlobalDeclKind::Var(ref v) => v.name,
ast::GlobalDeclKind::Const(ref c) => c.name,
+ ast::GlobalDeclKind::Override(ref o) => o.name,
ast::GlobalDeclKind::Struct(ref s) => s.name,
ast::GlobalDeclKind::Type(ref t) => t.name,
}
diff --git a/third_party/rust/naga/src/front/wgsl/lower/mod.rs b/third_party/rust/naga/src/front/wgsl/lower/mod.rs
index 2ca6c182b7..e7cce17723 100644
--- a/third_party/rust/naga/src/front/wgsl/lower/mod.rs
+++ b/third_party/rust/naga/src/front/wgsl/lower/mod.rs
@@ -86,6 +86,8 @@ pub struct GlobalContext<'source, 'temp, 'out> {
module: &'out mut crate::Module,
const_typifier: &'temp mut Typifier,
+
+ global_expression_kind_tracker: &'temp mut crate::proc::ExpressionKindTracker,
}
impl<'source> GlobalContext<'source, '_, '_> {
@@ -97,6 +99,19 @@ impl<'source> GlobalContext<'source, '_, '_> {
module: self.module,
const_typifier: self.const_typifier,
expr_type: ExpressionContextType::Constant,
+ global_expression_kind_tracker: self.global_expression_kind_tracker,
+ }
+ }
+
+ fn as_override(&mut self) -> ExpressionContext<'source, '_, '_> {
+ ExpressionContext {
+ ast_expressions: self.ast_expressions,
+ globals: self.globals,
+ types: self.types,
+ module: self.module,
+ const_typifier: self.const_typifier,
+ expr_type: ExpressionContextType::Override,
+ global_expression_kind_tracker: self.global_expression_kind_tracker,
}
}
@@ -164,7 +179,8 @@ pub struct StatementContext<'source, 'temp, 'out> {
/// with the form of the expressions; it is also tracking whether WGSL says
/// we should consider them to be const. See the use of `force_non_const` in
/// the code for lowering `let` bindings.
- expression_constness: &'temp mut crate::proc::ExpressionConstnessTracker,
+ local_expression_kind_tracker: &'temp mut crate::proc::ExpressionKindTracker,
+ global_expression_kind_tracker: &'temp mut crate::proc::ExpressionKindTracker,
}
impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
@@ -181,6 +197,7 @@ impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
types: self.types,
ast_expressions: self.ast_expressions,
const_typifier: self.const_typifier,
+ global_expression_kind_tracker: self.global_expression_kind_tracker,
module: self.module,
expr_type: ExpressionContextType::Runtime(RuntimeExpressionContext {
local_table: self.local_table,
@@ -188,7 +205,7 @@ impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
block,
emitter,
typifier: self.typifier,
- expression_constness: self.expression_constness,
+ local_expression_kind_tracker: self.local_expression_kind_tracker,
}),
}
}
@@ -200,6 +217,7 @@ impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
types: self.types,
module: self.module,
const_typifier: self.const_typifier,
+ global_expression_kind_tracker: self.global_expression_kind_tracker,
}
}
@@ -232,8 +250,8 @@ pub struct RuntimeExpressionContext<'temp, 'out> {
/// Which `Expression`s in `self.naga_expressions` are const expressions, in
/// the WGSL sense.
///
- /// See [`StatementContext::expression_constness`] for details.
- expression_constness: &'temp mut crate::proc::ExpressionConstnessTracker,
+ /// See [`StatementContext::local_expression_kind_tracker`] for details.
+ local_expression_kind_tracker: &'temp mut crate::proc::ExpressionKindTracker,
}
/// The type of Naga IR expression we are lowering an [`ast::Expression`] to.
@@ -253,6 +271,14 @@ pub enum ExpressionContextType<'temp, 'out> {
/// available in the [`ExpressionContext`], so this variant
/// carries no further information.
Constant,
+
+ /// We are lowering to an override expression, to be included in the module's
+ /// constant expression arena.
+ ///
+ /// Everything override expressions are allowed to refer to is
+ /// available in the [`ExpressionContext`], so this variant
+ /// carries no further information.
+ Override,
}
/// State for lowering an [`ast::Expression`] to Naga IR.
@@ -307,10 +333,11 @@ pub struct ExpressionContext<'source, 'temp, 'out> {
/// [`Module`]: crate::Module
module: &'out mut crate::Module,
- /// Type judgments for [`module::const_expressions`].
+ /// Type judgments for [`module::global_expressions`].
///
- /// [`module::const_expressions`]: crate::Module::const_expressions
+ /// [`module::global_expressions`]: crate::Module::global_expressions
const_typifier: &'temp mut Typifier,
+ global_expression_kind_tracker: &'temp mut crate::proc::ExpressionKindTracker,
/// Whether we are lowering a constant expression or a general
/// runtime expression, and the data needed in each case.
@@ -326,6 +353,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
const_typifier: self.const_typifier,
module: self.module,
expr_type: ExpressionContextType::Constant,
+ global_expression_kind_tracker: self.global_expression_kind_tracker,
}
}
@@ -336,6 +364,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
types: self.types,
module: self.module,
const_typifier: self.const_typifier,
+ global_expression_kind_tracker: self.global_expression_kind_tracker,
}
}
@@ -344,11 +373,20 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
ExpressionContextType::Runtime(ref mut rctx) => ConstantEvaluator::for_wgsl_function(
self.module,
&mut rctx.function.expressions,
- rctx.expression_constness,
+ rctx.local_expression_kind_tracker,
rctx.emitter,
rctx.block,
),
- ExpressionContextType::Constant => ConstantEvaluator::for_wgsl_module(self.module),
+ ExpressionContextType::Constant => ConstantEvaluator::for_wgsl_module(
+ self.module,
+ self.global_expression_kind_tracker,
+ false,
+ ),
+ ExpressionContextType::Override => ConstantEvaluator::for_wgsl_module(
+ self.module,
+ self.global_expression_kind_tracker,
+ true,
+ ),
}
}
@@ -358,24 +396,14 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
span: Span,
) -> Result<Handle<crate::Expression>, Error<'source>> {
let mut eval = self.as_const_evaluator();
- match eval.try_eval_and_append(&expr, span) {
- Ok(expr) => Ok(expr),
-
- // `expr` is not a constant expression. This is fine as
- // long as we're not building `Module::const_expressions`.
- Err(err) => match self.expr_type {
- ExpressionContextType::Runtime(ref mut rctx) => {
- Ok(rctx.function.expressions.append(expr, span))
- }
- ExpressionContextType::Constant => Err(Error::ConstantEvaluatorError(err, span)),
- },
- }
+ eval.try_eval_and_append(expr, span)
+ .map_err(|e| Error::ConstantEvaluatorError(e, span))
}
fn const_access(&self, handle: Handle<crate::Expression>) -> Option<u32> {
match self.expr_type {
ExpressionContextType::Runtime(ref ctx) => {
- if !ctx.expression_constness.is_const(handle) {
+ if !ctx.local_expression_kind_tracker.is_const(handle) {
return None;
}
@@ -385,20 +413,25 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
.ok()
}
ExpressionContextType::Constant => self.module.to_ctx().eval_expr_to_u32(handle).ok(),
+ ExpressionContextType::Override => None,
}
}
fn get_expression_span(&self, handle: Handle<crate::Expression>) -> Span {
match self.expr_type {
ExpressionContextType::Runtime(ref ctx) => ctx.function.expressions.get_span(handle),
- ExpressionContextType::Constant => self.module.const_expressions.get_span(handle),
+ ExpressionContextType::Constant | ExpressionContextType::Override => {
+ self.module.global_expressions.get_span(handle)
+ }
}
}
fn typifier(&self) -> &Typifier {
match self.expr_type {
ExpressionContextType::Runtime(ref ctx) => ctx.typifier,
- ExpressionContextType::Constant => self.const_typifier,
+ ExpressionContextType::Constant | ExpressionContextType::Override => {
+ self.const_typifier
+ }
}
}
@@ -408,7 +441,9 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
) -> Result<&mut RuntimeExpressionContext<'temp, 'out>, Error<'source>> {
match self.expr_type {
ExpressionContextType::Runtime(ref mut ctx) => Ok(ctx),
- ExpressionContextType::Constant => Err(Error::UnexpectedOperationInConstContext(span)),
+ ExpressionContextType::Constant | ExpressionContextType::Override => {
+ Err(Error::UnexpectedOperationInConstContext(span))
+ }
}
}
@@ -420,7 +455,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
) -> Result<crate::SwizzleComponent, Error<'source>> {
match self.expr_type {
ExpressionContextType::Runtime(ref rctx) => {
- if !rctx.expression_constness.is_const(expr) {
+ if !rctx.local_expression_kind_tracker.is_const(expr) {
return Err(Error::ExpectedConstExprConcreteIntegerScalar(
component_span,
));
@@ -445,7 +480,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
}
// This means a `gather` operation appeared in a constant expression.
// This error refers to the `gather` itself, not its "component" argument.
- ExpressionContextType::Constant => {
+ ExpressionContextType::Constant | ExpressionContextType::Override => {
Err(Error::UnexpectedOperationInConstContext(gather_span))
}
}
@@ -471,7 +506,9 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
// to also borrow self.module.types mutably below.
let typifier = match self.expr_type {
ExpressionContextType::Runtime(ref ctx) => ctx.typifier,
- ExpressionContextType::Constant => &*self.const_typifier,
+ ExpressionContextType::Constant | ExpressionContextType::Override => {
+ &*self.const_typifier
+ }
};
Ok(typifier.register_type(handle, &mut self.module.types))
}
@@ -514,10 +551,10 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
typifier = &mut *ctx.typifier;
expressions = &ctx.function.expressions;
}
- ExpressionContextType::Constant => {
+ ExpressionContextType::Constant | ExpressionContextType::Override => {
resolve_ctx = ResolveContext::with_locals(self.module, &empty_arena, &[]);
typifier = self.const_typifier;
- expressions = &self.module.const_expressions;
+ expressions = &self.module.global_expressions;
}
};
typifier
@@ -610,14 +647,14 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
rctx.block
.extend(rctx.emitter.finish(&rctx.function.expressions));
}
- ExpressionContextType::Constant => {}
+ ExpressionContextType::Constant | ExpressionContextType::Override => {}
}
let result = self.append_expression(expression, span);
match self.expr_type {
ExpressionContextType::Runtime(ref mut rctx) => {
rctx.emitter.start(&rctx.function.expressions);
}
- ExpressionContextType::Constant => {}
+ ExpressionContextType::Constant | ExpressionContextType::Override => {}
}
result
}
@@ -786,6 +823,7 @@ enum LoweredGlobalDecl {
Function(Handle<crate::Function>),
Var(Handle<crate::GlobalVariable>),
Const(Handle<crate::Constant>),
+ Override(Handle<crate::Override>),
Type(Handle<crate::Type>),
EntryPoint,
}
@@ -836,6 +874,29 @@ impl Texture {
}
}
+enum SubgroupGather {
+ BroadcastFirst,
+ Broadcast,
+ Shuffle,
+ ShuffleDown,
+ ShuffleUp,
+ ShuffleXor,
+}
+
+impl SubgroupGather {
+ pub fn map(word: &str) -> Option<Self> {
+ Some(match word {
+ "subgroupBroadcastFirst" => Self::BroadcastFirst,
+ "subgroupBroadcast" => Self::Broadcast,
+ "subgroupShuffle" => Self::Shuffle,
+ "subgroupShuffleDown" => Self::ShuffleDown,
+ "subgroupShuffleUp" => Self::ShuffleUp,
+ "subgroupShuffleXor" => Self::ShuffleXor,
+ _ => return None,
+ })
+ }
+}
+
pub struct Lowerer<'source, 'temp> {
index: &'temp Index<'source>,
layouter: Layouter,
@@ -861,6 +922,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
types: &tu.types,
module: &mut module,
const_typifier: &mut Typifier::new(),
+ global_expression_kind_tracker: &mut crate::proc::ExpressionKindTracker::new(),
};
for decl_handle in self.index.visit_ordered() {
@@ -877,7 +939,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let init;
if let Some(init_ast) = v.init {
- let mut ectx = ctx.as_const();
+ let mut ectx = ctx.as_override();
let lowered = self.expression_for_abstract(init_ast, &mut ectx)?;
let ty_res = crate::proc::TypeResolution::Handle(ty);
let converted = ectx
@@ -956,7 +1018,6 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let handle = ctx.module.constants.append(
crate::Constant {
name: Some(c.name.name.to_string()),
- r#override: crate::Override::None,
ty,
init,
},
@@ -966,6 +1027,65 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
ctx.globals
.insert(c.name.name, LoweredGlobalDecl::Const(handle));
}
+ ast::GlobalDeclKind::Override(ref o) => {
+ let init = o
+ .init
+ .map(|init| self.expression(init, &mut ctx.as_override()))
+ .transpose()?;
+ let inferred_type = init
+ .map(|init| ctx.as_const().register_type(init))
+ .transpose()?;
+
+ let explicit_ty =
+ o.ty.map(|ty| self.resolve_ast_type(ty, &mut ctx))
+ .transpose()?;
+
+ let id =
+ o.id.map(|id| self.const_u32(id, &mut ctx.as_const()))
+ .transpose()?;
+
+ let id = if let Some((id, id_span)) = id {
+ Some(
+ u16::try_from(id)
+ .map_err(|_| Error::PipelineConstantIDValue(id_span))?,
+ )
+ } else {
+ None
+ };
+
+ let ty = match (explicit_ty, inferred_type) {
+ (Some(explicit_ty), Some(inferred_type)) => {
+ if explicit_ty == inferred_type {
+ explicit_ty
+ } else {
+ let gctx = ctx.module.to_ctx();
+ return Err(Error::InitializationTypeMismatch {
+ name: o.name.span,
+ expected: explicit_ty.to_wgsl(&gctx),
+ got: inferred_type.to_wgsl(&gctx),
+ });
+ }
+ }
+ (Some(explicit_ty), None) => explicit_ty,
+ (None, Some(inferred_type)) => inferred_type,
+ (None, None) => {
+ return Err(Error::DeclMissingTypeAndInit(o.name.span));
+ }
+ };
+
+ let handle = ctx.module.overrides.append(
+ crate::Override {
+ name: Some(o.name.name.to_string()),
+ id,
+ ty,
+ init,
+ },
+ span,
+ );
+
+ ctx.globals
+ .insert(o.name.name, LoweredGlobalDecl::Override(handle));
+ }
ast::GlobalDeclKind::Struct(ref s) => {
let handle = self.r#struct(s, span, &mut ctx)?;
ctx.globals
@@ -1000,6 +1120,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let mut local_table = FastHashMap::default();
let mut expressions = Arena::new();
let mut named_expressions = FastIndexMap::default();
+ let mut local_expression_kind_tracker = crate::proc::ExpressionKindTracker::new();
let arguments = f
.arguments
@@ -1011,6 +1132,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
.append(crate::Expression::FunctionArgument(i as u32), arg.name.span);
local_table.insert(arg.handle, Typed::Plain(expr));
named_expressions.insert(expr, (arg.name.name.to_string(), arg.name.span));
+ local_expression_kind_tracker.insert(expr, crate::proc::ExpressionKind::Runtime);
Ok(crate::FunctionArgument {
name: Some(arg.name.name.to_string()),
@@ -1053,7 +1175,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
named_expressions: &mut named_expressions,
types: ctx.types,
module: ctx.module,
- expression_constness: &mut crate::proc::ExpressionConstnessTracker::new(),
+ local_expression_kind_tracker: &mut local_expression_kind_tracker,
+ global_expression_kind_tracker: ctx.global_expression_kind_tracker,
};
let mut body = self.block(&f.body, false, &mut stmt_ctx)?;
ensure_block_returns(&mut body);
@@ -1132,7 +1255,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
// affects when errors must be reported, so we can't even
// treat suitable `let` bindings as constant as an
// optimization.
- ctx.expression_constness.force_non_const(value);
+ ctx.local_expression_kind_tracker.force_non_const(value);
let explicit_ty =
l.ty.map(|ty| self.resolve_ast_type(ty, &mut ctx.as_global()))
@@ -1203,7 +1326,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
ty = explicit_ty;
initializer = None;
}
- (None, None) => return Err(Error::MissingType(v.name.span)),
+ (None, None) => return Err(Error::DeclMissingTypeAndInit(v.name.span)),
}
let (const_initializer, initializer) = {
@@ -1216,7 +1339,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
// - the initialization is not a constant
// expression, so its value depends on the
// state at the point of initialization.
- if is_inside_loop || !ctx.expression_constness.is_const(init) {
+ if is_inside_loop
+ || !ctx.local_expression_kind_tracker.is_const_or_override(init)
+ {
(None, Some(init))
} else {
(Some(init), None)
@@ -1469,6 +1594,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
.function
.expressions
.append(crate::Expression::Binary { op, left, right }, stmt.span);
+ rctx.local_expression_kind_tracker
+ .insert(left, crate::proc::ExpressionKind::Runtime);
+ rctx.local_expression_kind_tracker
+ .insert(value, crate::proc::ExpressionKind::Runtime);
block.extend(emitter.finish(&ctx.function.expressions));
crate::Statement::Store {
@@ -1562,7 +1691,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
LoweredGlobalDecl::Const(handle) => {
Typed::Plain(crate::Expression::Constant(handle))
}
- _ => {
+ LoweredGlobalDecl::Override(handle) => {
+ Typed::Plain(crate::Expression::Override(handle))
+ }
+ LoweredGlobalDecl::Function(_)
+ | LoweredGlobalDecl::Type(_)
+ | LoweredGlobalDecl::EntryPoint => {
return Err(Error::Unexpected(span, ExpectedToken::Variable));
}
};
@@ -1819,9 +1953,11 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
)?;
Ok(Some(handle))
}
- Some(&LoweredGlobalDecl::Const(_) | &LoweredGlobalDecl::Var(_)) => {
- Err(Error::Unexpected(function.span, ExpectedToken::Function))
- }
+ Some(
+ &LoweredGlobalDecl::Const(_)
+ | &LoweredGlobalDecl::Override(_)
+ | &LoweredGlobalDecl::Var(_),
+ ) => Err(Error::Unexpected(function.span, ExpectedToken::Function)),
Some(&LoweredGlobalDecl::EntryPoint) => Err(Error::CalledEntryPoint(function.span)),
Some(&LoweredGlobalDecl::Function(function)) => {
let arguments = arguments
@@ -1835,9 +1971,13 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
rctx.block
.extend(rctx.emitter.finish(&rctx.function.expressions));
let result = has_result.then(|| {
- rctx.function
+ let result = rctx
+ .function
.expressions
- .append(crate::Expression::CallResult(function), span)
+ .append(crate::Expression::CallResult(function), span);
+ rctx.local_expression_kind_tracker
+ .insert(result, crate::proc::ExpressionKind::Runtime);
+ result
});
rctx.emitter.start(&rctx.function.expressions);
rctx.block.push(
@@ -1937,6 +2077,16 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
}
} else if let Some(fun) = Texture::map(function.name) {
self.texture_sample_helper(fun, arguments, span, ctx)?
+ } else if let Some((op, cop)) = conv::map_subgroup_operation(function.name) {
+ return Ok(Some(
+ self.subgroup_operation_helper(span, op, cop, arguments, ctx)?,
+ ));
+ } else if let Some(mode) = SubgroupGather::map(function.name) {
+ return Ok(Some(
+ self.subgroup_gather_helper(span, mode, arguments, ctx)?,
+ ));
+ } else if let Some(fun) = crate::AtomicFunction::map(function.name) {
+ return Ok(Some(self.atomic_helper(span, fun, arguments, ctx)?));
} else {
match function.name {
"select" => {
@@ -1982,70 +2132,6 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
.push(crate::Statement::Store { pointer, value }, span);
return Ok(None);
}
- "atomicAdd" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::Add,
- arguments,
- ctx,
- )?))
- }
- "atomicSub" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::Subtract,
- arguments,
- ctx,
- )?))
- }
- "atomicAnd" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::And,
- arguments,
- ctx,
- )?))
- }
- "atomicOr" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::InclusiveOr,
- arguments,
- ctx,
- )?))
- }
- "atomicXor" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::ExclusiveOr,
- arguments,
- ctx,
- )?))
- }
- "atomicMin" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::Min,
- arguments,
- ctx,
- )?))
- }
- "atomicMax" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::Max,
- arguments,
- ctx,
- )?))
- }
- "atomicExchange" => {
- return Ok(Some(self.atomic_helper(
- span,
- crate::AtomicFunction::Exchange { compare: None },
- arguments,
- ctx,
- )?))
- }
"atomicCompareExchangeWeak" => {
let mut args = ctx.prepare_args(arguments, 3, span);
@@ -2104,6 +2190,14 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
.push(crate::Statement::Barrier(crate::Barrier::WORK_GROUP), span);
return Ok(None);
}
+ "subgroupBarrier" => {
+ ctx.prepare_args(arguments, 0, span).finish()?;
+
+ let rctx = ctx.runtime_expression_ctx(span)?;
+ rctx.block
+ .push(crate::Statement::Barrier(crate::Barrier::SUB_GROUP), span);
+ return Ok(None);
+ }
"workgroupUniformLoad" => {
let mut args = ctx.prepare_args(arguments, 1, span);
let expr = args.next()?;
@@ -2311,6 +2405,22 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
)?;
return Ok(Some(handle));
}
+ "subgroupBallot" => {
+ let mut args = ctx.prepare_args(arguments, 0, span);
+ let predicate = if arguments.len() == 1 {
+ Some(self.expression(args.next()?, ctx)?)
+ } else {
+ None
+ };
+ args.finish()?;
+
+ let result = ctx
+ .interrupt_emitter(crate::Expression::SubgroupBallotResult, span)?;
+ let rctx = ctx.runtime_expression_ctx(span)?;
+ rctx.block
+ .push(crate::Statement::SubgroupBallot { result, predicate }, span);
+ return Ok(Some(result));
+ }
_ => return Err(Error::UnknownIdent(function.span, function.name)),
}
};
@@ -2502,6 +2612,80 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
})
}
+ fn subgroup_operation_helper(
+ &mut self,
+ span: Span,
+ op: crate::SubgroupOperation,
+ collective_op: crate::CollectiveOperation,
+ arguments: &[Handle<ast::Expression<'source>>],
+ ctx: &mut ExpressionContext<'source, '_, '_>,
+ ) -> Result<Handle<crate::Expression>, Error<'source>> {
+ let mut args = ctx.prepare_args(arguments, 1, span);
+
+ let argument = self.expression(args.next()?, ctx)?;
+ args.finish()?;
+
+ let ty = ctx.register_type(argument)?;
+
+ let result =
+ ctx.interrupt_emitter(crate::Expression::SubgroupOperationResult { ty }, span)?;
+ let rctx = ctx.runtime_expression_ctx(span)?;
+ rctx.block.push(
+ crate::Statement::SubgroupCollectiveOperation {
+ op,
+ collective_op,
+ argument,
+ result,
+ },
+ span,
+ );
+ Ok(result)
+ }
+
+ fn subgroup_gather_helper(
+ &mut self,
+ span: Span,
+ mode: SubgroupGather,
+ arguments: &[Handle<ast::Expression<'source>>],
+ ctx: &mut ExpressionContext<'source, '_, '_>,
+ ) -> Result<Handle<crate::Expression>, Error<'source>> {
+ let mut args = ctx.prepare_args(arguments, 2, span);
+
+ let argument = self.expression(args.next()?, ctx)?;
+
+ use SubgroupGather as Sg;
+ let mode = if let Sg::BroadcastFirst = mode {
+ crate::GatherMode::BroadcastFirst
+ } else {
+ let index = self.expression(args.next()?, ctx)?;
+ match mode {
+ Sg::Broadcast => crate::GatherMode::Broadcast(index),
+ Sg::Shuffle => crate::GatherMode::Shuffle(index),
+ Sg::ShuffleDown => crate::GatherMode::ShuffleDown(index),
+ Sg::ShuffleUp => crate::GatherMode::ShuffleUp(index),
+ Sg::ShuffleXor => crate::GatherMode::ShuffleXor(index),
+ Sg::BroadcastFirst => unreachable!(),
+ }
+ };
+
+ args.finish()?;
+
+ let ty = ctx.register_type(argument)?;
+
+ let result =
+ ctx.interrupt_emitter(crate::Expression::SubgroupOperationResult { ty }, span)?;
+ let rctx = ctx.runtime_expression_ctx(span)?;
+ rctx.block.push(
+ crate::Statement::SubgroupGather {
+ mode,
+ argument,
+ result,
+ },
+ span,
+ );
+ Ok(result)
+ }
+
fn r#struct(
&mut self,
s: &ast::Struct<'source>,
@@ -2760,3 +2944,19 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
}
}
}
+
+impl crate::AtomicFunction {
+ pub fn map(word: &str) -> Option<Self> {
+ Some(match word {
+ "atomicAdd" => crate::AtomicFunction::Add,
+ "atomicSub" => crate::AtomicFunction::Subtract,
+ "atomicAnd" => crate::AtomicFunction::And,
+ "atomicOr" => crate::AtomicFunction::InclusiveOr,
+ "atomicXor" => crate::AtomicFunction::ExclusiveOr,
+ "atomicMin" => crate::AtomicFunction::Min,
+ "atomicMax" => crate::AtomicFunction::Max,
+ "atomicExchange" => crate::AtomicFunction::Exchange { compare: None },
+ _ => return None,
+ })
+ }
+}
diff --git a/third_party/rust/naga/src/front/wgsl/mod.rs b/third_party/rust/naga/src/front/wgsl/mod.rs
index b6151fe1c0..aec1e657fc 100644
--- a/third_party/rust/naga/src/front/wgsl/mod.rs
+++ b/third_party/rust/naga/src/front/wgsl/mod.rs
@@ -44,6 +44,17 @@ impl Frontend {
}
}
+/// <div class="warning">
+// NOTE: Keep this in sync with `wgpu::Device::create_shader_module`!
+// NOTE: Keep this in sync with `wgpu_core::Global::device_create_shader_module`!
+///
+/// This function may consume a lot of stack space. Compiler-enforced limits for parsing recursion
+/// exist; if shader compilation runs into them, it will return an error gracefully. However, on
+/// some build profiles and platforms, the default stack size for a thread may be exceeded before
+/// this limit is reached during parsing. Callers should ensure that there is enough stack space
+/// for this, particularly if calls to this method are exposed to user input.
+///
+/// </div>
pub fn parse_str(source: &str) -> Result<crate::Module, ParseError> {
Frontend::new().parse(source)
}
diff --git a/third_party/rust/naga/src/front/wgsl/parse/ast.rs b/third_party/rust/naga/src/front/wgsl/parse/ast.rs
index dbaac523cb..ea8013ee7c 100644
--- a/third_party/rust/naga/src/front/wgsl/parse/ast.rs
+++ b/third_party/rust/naga/src/front/wgsl/parse/ast.rs
@@ -82,6 +82,7 @@ pub enum GlobalDeclKind<'a> {
Fn(Function<'a>),
Var(GlobalVariable<'a>),
Const(Const<'a>),
+ Override(Override<'a>),
Struct(Struct<'a>),
Type(TypeAlias<'a>),
}
@@ -200,6 +201,14 @@ pub struct Const<'a> {
pub init: Handle<Expression<'a>>,
}
+#[derive(Debug)]
+pub struct Override<'a> {
+ pub name: Ident<'a>,
+ pub id: Option<Handle<Expression<'a>>>,
+ pub ty: Option<Handle<Type<'a>>>,
+ pub init: Option<Handle<Expression<'a>>>,
+}
+
/// The size of an [`Array`] or [`BindingArray`].
///
/// [`Array`]: Type::Array
diff --git a/third_party/rust/naga/src/front/wgsl/parse/conv.rs b/third_party/rust/naga/src/front/wgsl/parse/conv.rs
index 1a4911a3bd..207f0eda41 100644
--- a/third_party/rust/naga/src/front/wgsl/parse/conv.rs
+++ b/third_party/rust/naga/src/front/wgsl/parse/conv.rs
@@ -35,6 +35,11 @@ pub fn map_built_in(word: &str, span: Span) -> Result<crate::BuiltIn, Error<'_>>
"local_invocation_index" => crate::BuiltIn::LocalInvocationIndex,
"workgroup_id" => crate::BuiltIn::WorkGroupId,
"num_workgroups" => crate::BuiltIn::NumWorkGroups,
+ // subgroup
+ "num_subgroups" => crate::BuiltIn::NumSubgroups,
+ "subgroup_id" => crate::BuiltIn::SubgroupId,
+ "subgroup_size" => crate::BuiltIn::SubgroupSize,
+ "subgroup_invocation_id" => crate::BuiltIn::SubgroupInvocationId,
_ => return Err(Error::UnknownBuiltin(span)),
})
}
@@ -260,3 +265,26 @@ pub fn map_conservative_depth(
_ => Err(Error::UnknownConservativeDepth(span)),
}
}
+
+pub fn map_subgroup_operation(
+ word: &str,
+) -> Option<(crate::SubgroupOperation, crate::CollectiveOperation)> {
+ use crate::CollectiveOperation as co;
+ use crate::SubgroupOperation as sg;
+ Some(match word {
+ "subgroupAll" => (sg::All, co::Reduce),
+ "subgroupAny" => (sg::Any, co::Reduce),
+ "subgroupAdd" => (sg::Add, co::Reduce),
+ "subgroupMul" => (sg::Mul, co::Reduce),
+ "subgroupMin" => (sg::Min, co::Reduce),
+ "subgroupMax" => (sg::Max, co::Reduce),
+ "subgroupAnd" => (sg::And, co::Reduce),
+ "subgroupOr" => (sg::Or, co::Reduce),
+ "subgroupXor" => (sg::Xor, co::Reduce),
+ "subgroupExclusiveAdd" => (sg::Add, co::ExclusiveScan),
+ "subgroupExclusiveMul" => (sg::Mul, co::ExclusiveScan),
+ "subgroupInclusiveAdd" => (sg::Add, co::InclusiveScan),
+ "subgroupInclusiveMul" => (sg::Mul, co::InclusiveScan),
+ _ => return None,
+ })
+}
diff --git a/third_party/rust/naga/src/front/wgsl/parse/mod.rs b/third_party/rust/naga/src/front/wgsl/parse/mod.rs
index 51fc2f013b..79ea1ae609 100644
--- a/third_party/rust/naga/src/front/wgsl/parse/mod.rs
+++ b/third_party/rust/naga/src/front/wgsl/parse/mod.rs
@@ -1619,22 +1619,21 @@ impl Parser {
lexer: &mut Lexer<'a>,
ctx: &mut ExpressionContext<'a, '_, '_>,
block: &mut ast::Block<'a>,
+ brace_nesting_level: u8,
) -> Result<(), Error<'a>> {
self.push_rule_span(Rule::Statement, lexer);
match lexer.peek() {
(Token::Separator(';'), _) => {
let _ = lexer.next();
self.pop_rule_span(lexer);
- return Ok(());
}
(Token::Paren('{'), _) => {
- let (inner, span) = self.block(lexer, ctx)?;
+ let (inner, span) = self.block(lexer, ctx, brace_nesting_level)?;
block.stmts.push(ast::Statement {
kind: ast::StatementKind::Block(inner),
span,
});
self.pop_rule_span(lexer);
- return Ok(());
}
(Token::Word(word), _) => {
let kind = match word {
@@ -1711,7 +1710,7 @@ impl Parser {
let _ = lexer.next();
let condition = self.general_expression(lexer, ctx)?;
- let accept = self.block(lexer, ctx)?.0;
+ let accept = self.block(lexer, ctx, brace_nesting_level)?.0;
let mut elsif_stack = Vec::new();
let mut elseif_span_start = lexer.start_byte_offset();
@@ -1722,12 +1721,12 @@ impl Parser {
if !lexer.skip(Token::Word("if")) {
// ... else { ... }
- break self.block(lexer, ctx)?.0;
+ break self.block(lexer, ctx, brace_nesting_level)?.0;
}
// ... else if (...) { ... }
let other_condition = self.general_expression(lexer, ctx)?;
- let other_block = self.block(lexer, ctx)?;
+ let other_block = self.block(lexer, ctx, brace_nesting_level)?;
elsif_stack.push((elseif_span_start, other_condition, other_block));
elseif_span_start = lexer.start_byte_offset();
};
@@ -1759,7 +1758,9 @@ impl Parser {
"switch" => {
let _ = lexer.next();
let selector = self.general_expression(lexer, ctx)?;
- lexer.expect(Token::Paren('{'))?;
+ let brace_span = lexer.expect_span(Token::Paren('{'))?;
+ let brace_nesting_level =
+ Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
let mut cases = Vec::new();
loop {
@@ -1784,7 +1785,7 @@ impl Parser {
});
};
- let body = self.block(lexer, ctx)?.0;
+ let body = self.block(lexer, ctx, brace_nesting_level)?.0;
cases.push(ast::SwitchCase {
value,
@@ -1794,7 +1795,7 @@ impl Parser {
}
(Token::Word("default"), _) => {
lexer.skip(Token::Separator(':'));
- let body = self.block(lexer, ctx)?.0;
+ let body = self.block(lexer, ctx, brace_nesting_level)?.0;
cases.push(ast::SwitchCase {
value: ast::SwitchValue::Default,
body,
@@ -1810,7 +1811,7 @@ impl Parser {
ast::StatementKind::Switch { selector, cases }
}
- "loop" => self.r#loop(lexer, ctx)?,
+ "loop" => self.r#loop(lexer, ctx, brace_nesting_level)?,
"while" => {
let _ = lexer.next();
let mut body = ast::Block::default();
@@ -1834,7 +1835,7 @@ impl Parser {
span,
});
- let (block, span) = self.block(lexer, ctx)?;
+ let (block, span) = self.block(lexer, ctx, brace_nesting_level)?;
body.stmts.push(ast::Statement {
kind: ast::StatementKind::Block(block),
span,
@@ -1857,7 +1858,9 @@ impl Parser {
let (_, span) = {
let ctx = &mut *ctx;
let block = &mut *block;
- lexer.capture_span(|lexer| self.statement(lexer, ctx, block))?
+ lexer.capture_span(|lexer| {
+ self.statement(lexer, ctx, block, brace_nesting_level)
+ })?
};
if block.stmts.len() != num_statements {
@@ -1902,7 +1905,7 @@ impl Parser {
lexer.expect(Token::Paren(')'))?;
}
- let (block, span) = self.block(lexer, ctx)?;
+ let (block, span) = self.block(lexer, ctx, brace_nesting_level)?;
body.stmts.push(ast::Statement {
kind: ast::StatementKind::Block(block),
span,
@@ -1964,13 +1967,15 @@ impl Parser {
&mut self,
lexer: &mut Lexer<'a>,
ctx: &mut ExpressionContext<'a, '_, '_>,
+ brace_nesting_level: u8,
) -> Result<ast::StatementKind<'a>, Error<'a>> {
let _ = lexer.next();
let mut body = ast::Block::default();
let mut continuing = ast::Block::default();
let mut break_if = None;
- lexer.expect(Token::Paren('{'))?;
+ let brace_span = lexer.expect_span(Token::Paren('{'))?;
+ let brace_nesting_level = Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
ctx.local_table.push_scope();
@@ -1980,7 +1985,9 @@ impl Parser {
// the last thing in the loop body
// Expect a opening brace to start the continuing block
- lexer.expect(Token::Paren('{'))?;
+ let brace_span = lexer.expect_span(Token::Paren('{'))?;
+ let brace_nesting_level =
+ Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
loop {
if lexer.skip(Token::Word("break")) {
// Branch for the `break if` statement, this statement
@@ -2009,7 +2016,7 @@ impl Parser {
break;
} else {
// Otherwise try to parse a statement
- self.statement(lexer, ctx, &mut continuing)?;
+ self.statement(lexer, ctx, &mut continuing, brace_nesting_level)?;
}
}
// Since the continuing block must be the last part of the loop body,
@@ -2023,7 +2030,7 @@ impl Parser {
break;
}
// Otherwise try to parse a statement
- self.statement(lexer, ctx, &mut body)?;
+ self.statement(lexer, ctx, &mut body, brace_nesting_level)?;
}
ctx.local_table.pop_scope();
@@ -2040,15 +2047,17 @@ impl Parser {
&mut self,
lexer: &mut Lexer<'a>,
ctx: &mut ExpressionContext<'a, '_, '_>,
+ brace_nesting_level: u8,
) -> Result<(ast::Block<'a>, Span), Error<'a>> {
self.push_rule_span(Rule::Block, lexer);
ctx.local_table.push_scope();
- lexer.expect(Token::Paren('{'))?;
+ let brace_span = lexer.expect_span(Token::Paren('{'))?;
+ let brace_nesting_level = Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
let mut block = ast::Block::default();
while !lexer.skip(Token::Paren('}')) {
- self.statement(lexer, ctx, &mut block)?;
+ self.statement(lexer, ctx, &mut block, brace_nesting_level)?;
}
ctx.local_table.pop_scope();
@@ -2135,9 +2144,10 @@ impl Parser {
// do not use `self.block` here, since we must not push a new scope
lexer.expect(Token::Paren('{'))?;
+ let brace_nesting_level = 1;
let mut body = ast::Block::default();
while !lexer.skip(Token::Paren('}')) {
- self.statement(lexer, &mut ctx, &mut body)?;
+ self.statement(lexer, &mut ctx, &mut body, brace_nesting_level)?;
}
ctx.local_table.pop_scope();
@@ -2170,6 +2180,7 @@ impl Parser {
let mut early_depth_test = ParsedAttribute::default();
let (mut bind_index, mut bind_group) =
(ParsedAttribute::default(), ParsedAttribute::default());
+ let mut id = ParsedAttribute::default();
let mut dependencies = FastIndexSet::default();
let mut ctx = ExpressionContext {
@@ -2193,6 +2204,11 @@ impl Parser {
bind_group.set(self.general_expression(lexer, &mut ctx)?, name_span)?;
lexer.expect(Token::Paren(')'))?;
}
+ ("id", name_span) => {
+ lexer.expect(Token::Paren('('))?;
+ id.set(self.general_expression(lexer, &mut ctx)?, name_span)?;
+ lexer.expect(Token::Paren(')'))?;
+ }
("vertex", name_span) => {
stage.set(crate::ShaderStage::Vertex, name_span)?;
}
@@ -2283,6 +2299,30 @@ impl Parser {
Some(ast::GlobalDeclKind::Const(ast::Const { name, ty, init }))
}
+ (Token::Word("override"), _) => {
+ let name = lexer.next_ident()?;
+
+ let ty = if lexer.skip(Token::Separator(':')) {
+ Some(self.type_decl(lexer, &mut ctx)?)
+ } else {
+ None
+ };
+
+ let init = if lexer.skip(Token::Operation('=')) {
+ Some(self.general_expression(lexer, &mut ctx)?)
+ } else {
+ None
+ };
+
+ lexer.expect(Token::Separator(';'))?;
+
+ Some(ast::GlobalDeclKind::Override(ast::Override {
+ name,
+ id: id.value,
+ ty,
+ init,
+ }))
+ }
(Token::Word("var"), _) => {
let mut var = self.variable_decl(lexer, &mut ctx)?;
var.binding = binding.take();
@@ -2347,4 +2387,30 @@ impl Parser {
Ok(tu)
}
+
+ const fn increase_brace_nesting(
+ brace_nesting_level: u8,
+ brace_span: Span,
+ ) -> Result<u8, Error<'static>> {
+ // From [spec.](https://gpuweb.github.io/gpuweb/wgsl/#limits):
+ //
+ // > § 2.4. Limits
+ // >
+ // > …
+ // >
+ // > Maximum nesting depth of brace-enclosed statements in a function[:] 127
+ //
+ // _However_, we choose 64 instead because (a) it avoids stack overflows in CI and
+ // (b) we expect the limit to be decreased to 63 based on this conversation in
+ // WebGPU CTS upstream:
+ // <https://github.com/gpuweb/cts/pull/3389#discussion_r1543742701>
+ const BRACE_NESTING_MAXIMUM: u8 = 64;
+ if brace_nesting_level + 1 > BRACE_NESTING_MAXIMUM {
+ return Err(Error::ExceededLimitForNestedBraces {
+ span: brace_span,
+ limit: BRACE_NESTING_MAXIMUM,
+ });
+ }
+ Ok(brace_nesting_level + 1)
+ }
}
diff --git a/third_party/rust/naga/src/front/wgsl/to_wgsl.rs b/third_party/rust/naga/src/front/wgsl/to_wgsl.rs
index c8331ace09..63bc9f7317 100644
--- a/third_party/rust/naga/src/front/wgsl/to_wgsl.rs
+++ b/third_party/rust/naga/src/front/wgsl/to_wgsl.rs
@@ -226,7 +226,8 @@ mod tests {
let gctx = crate::proc::GlobalCtx {
types: &types,
constants: &crate::Arena::new(),
- const_expressions: &crate::Arena::new(),
+ overrides: &crate::Arena::new(),
+ global_expressions: &crate::Arena::new(),
};
let array = crate::TypeInner::Array {
base: mytype1,
diff --git a/third_party/rust/naga/src/lib.rs b/third_party/rust/naga/src/lib.rs
index 4b45174300..24e1b02c76 100644
--- a/third_party/rust/naga/src/lib.rs
+++ b/third_party/rust/naga/src/lib.rs
@@ -34,9 +34,6 @@ with optional span info, representing a series of statements executed in order.
`EntryPoint`s or `Function` is a `Block`, and `Statement` has a
[`Block`][Statement::Block] variant.
-If the `clone` feature is enabled, [`Arena`], [`UniqueArena`], [`Type`], [`TypeInner`],
-[`Constant`], [`Function`], [`EntryPoint`] and [`Module`] can be cloned.
-
## Arenas
To improve translator performance and reduce memory usage, most structures are
@@ -175,7 +172,7 @@ tree.
A Naga *constant expression* is one of the following [`Expression`]
variants, whose operands (if any) are also constant expressions:
- [`Literal`]
-- [`Constant`], for [`Constant`s][const_type] whose [`override`] is [`None`]
+- [`Constant`], for [`Constant`]s
- [`ZeroValue`], for fixed-size types
- [`Compose`]
- [`Access`]
@@ -194,8 +191,7 @@ A constant expression can be evaluated at module translation time.
## Override expressions
A Naga *override expression* is the same as a [constant expression],
-except that it is also allowed to refer to [`Constant`s][const_type]
-whose [`override`] is something other than [`None`].
+except that it is also allowed to reference other [`Override`]s.
An override expression can be evaluated at pipeline creation time.
@@ -238,10 +234,6 @@ An override expression can be evaluated at pipeline creation time.
[`Math`]: Expression::Math
[`As`]: Expression::As
-[const_type]: Constant
-[`override`]: Constant::override
-[`None`]: Override::None
-
[constant expression]: index.html#constant-expressions
*/
@@ -282,6 +274,7 @@ pub mod back;
mod block;
#[cfg(feature = "compact")]
pub mod compact;
+pub mod error;
pub mod front;
pub mod keywords;
pub mod proc;
@@ -439,6 +432,11 @@ pub enum BuiltIn {
WorkGroupId,
WorkGroupSize,
NumWorkGroups,
+ // subgroup
+ NumSubgroups,
+ SubgroupId,
+ SubgroupSize,
+ SubgroupInvocationId,
}
/// Number of bytes per scalar.
@@ -874,7 +872,7 @@ pub enum TypeInner {
BindingArray { base: Handle<Type>, size: ArraySize },
}
-#[derive(Debug, Clone, Copy, PartialOrd)]
+#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
@@ -892,41 +890,37 @@ pub enum Literal {
AbstractFloat(f64),
}
-#[derive(Debug, PartialEq)]
-#[cfg_attr(feature = "clone", derive(Clone))]
+/// Pipeline-overridable constant.
+#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
-pub enum Override {
- None,
- ByName,
- ByNameOrId(u32),
+pub struct Override {
+ pub name: Option<String>,
+ /// Pipeline Constant ID.
+ pub id: Option<u16>,
+ pub ty: Handle<Type>,
+
+ /// The default value of the pipeline-overridable constant.
+ ///
+ /// This [`Handle`] refers to [`Module::global_expressions`], not
+ /// any [`Function::expressions`] arena.
+ pub init: Option<Handle<Expression>>,
}
/// Constant value.
-#[derive(Debug, PartialEq)]
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct Constant {
pub name: Option<String>,
- pub r#override: Override,
pub ty: Handle<Type>,
/// The value of the constant.
///
- /// This [`Handle`] refers to [`Module::const_expressions`], not
+ /// This [`Handle`] refers to [`Module::global_expressions`], not
/// any [`Function::expressions`] arena.
- ///
- /// If [`override`] is [`None`], then this must be a Naga
- /// [constant expression]. Otherwise, this may be a Naga
- /// [override expression] or [constant expression].
- ///
- /// [`override`]: Constant::override
- /// [`None`]: Override::None
- /// [constant expression]: index.html#constant-expressions
- /// [override expression]: index.html#override-expressions
pub init: Handle<Expression>,
}
@@ -992,7 +986,7 @@ pub struct GlobalVariable {
pub ty: Handle<Type>,
/// Initial value for this variable.
///
- /// Expression handle lives in const_expressions
+ /// Expression handle lives in global_expressions
pub init: Option<Handle<Expression>>,
}
@@ -1010,7 +1004,7 @@ pub struct LocalVariable {
///
/// This handle refers to this `LocalVariable`'s function's
/// [`expressions`] arena, but it is required to be an evaluated
- /// constant expression.
+ /// override expression.
///
/// [`expressions`]: Function::expressions
pub init: Option<Handle<Expression>>,
@@ -1289,6 +1283,51 @@ pub enum SwizzleComponent {
W = 3,
}
+#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
+#[cfg_attr(feature = "deserialize", derive(Deserialize))]
+#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
+pub enum GatherMode {
+ /// All gather from the active lane with the smallest index
+ BroadcastFirst,
+ /// All gather from the same lane at the index given by the expression
+ Broadcast(Handle<Expression>),
+ /// Each gathers from a different lane at the index given by the expression
+ Shuffle(Handle<Expression>),
+ /// Each gathers from their lane plus the shift given by the expression
+ ShuffleDown(Handle<Expression>),
+ /// Each gathers from their lane minus the shift given by the expression
+ ShuffleUp(Handle<Expression>),
+ /// Each gathers from their lane xored with the given by the expression
+ ShuffleXor(Handle<Expression>),
+}
+
+#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
+#[cfg_attr(feature = "deserialize", derive(Deserialize))]
+#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
+pub enum SubgroupOperation {
+ All = 0,
+ Any = 1,
+ Add = 2,
+ Mul = 3,
+ Min = 4,
+ Max = 5,
+ And = 6,
+ Or = 7,
+ Xor = 8,
+}
+
+#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
+#[cfg_attr(feature = "deserialize", derive(Deserialize))]
+#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
+pub enum CollectiveOperation {
+ Reduce = 0,
+ InclusiveScan = 1,
+ ExclusiveScan = 2,
+}
+
bitflags::bitflags! {
/// Memory barrier flags.
#[cfg_attr(feature = "serialize", derive(Serialize))]
@@ -1297,9 +1336,11 @@ bitflags::bitflags! {
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Barrier: u32 {
/// Barrier affects all `AddressSpace::Storage` accesses.
- const STORAGE = 0x1;
+ const STORAGE = 1 << 0;
/// Barrier affects all `AddressSpace::WorkGroup` accesses.
- const WORK_GROUP = 0x2;
+ const WORK_GROUP = 1 << 1;
+ /// Barrier synchronizes execution across all invocations within a subgroup that exectue this instruction.
+ const SUB_GROUP = 1 << 2;
}
}
@@ -1315,6 +1356,8 @@ pub enum Expression {
Literal(Literal),
/// Constant value.
Constant(Handle<Constant>),
+ /// Pipeline-overridable constant.
+ Override(Handle<Override>),
/// Zero value of a type.
ZeroValue(Handle<Type>),
/// Composite expression.
@@ -1440,7 +1483,7 @@ pub enum Expression {
gather: Option<SwizzleComponent>,
coordinate: Handle<Expression>,
array_index: Option<Handle<Expression>>,
- /// Expression handle lives in const_expressions
+ /// Expression handle lives in global_expressions
offset: Option<Handle<Expression>>,
level: SampleLevel,
depth_ref: Option<Handle<Expression>>,
@@ -1598,6 +1641,15 @@ pub enum Expression {
query: Handle<Expression>,
committed: bool,
},
+ /// Result of a [`SubgroupBallot`] statement.
+ ///
+ /// [`SubgroupBallot`]: Statement::SubgroupBallot
+ SubgroupBallotResult,
+ /// Result of a [`SubgroupCollectiveOperation`] or [`SubgroupGather`] statement.
+ ///
+ /// [`SubgroupCollectiveOperation`]: Statement::SubgroupCollectiveOperation
+ /// [`SubgroupGather`]: Statement::SubgroupGather
+ SubgroupOperationResult { ty: Handle<Type> },
}
pub use block::Block;
@@ -1882,6 +1934,39 @@ pub enum Statement {
/// The specific operation we're performing on `query`.
fun: RayQueryFunction,
},
+ /// Calculate a bitmask using a boolean from each active thread in the subgroup
+ SubgroupBallot {
+ /// The [`SubgroupBallotResult`] expression representing this load's result.
+ ///
+ /// [`SubgroupBallotResult`]: Expression::SubgroupBallotResult
+ result: Handle<Expression>,
+ /// The value from this thread to store in the ballot
+ predicate: Option<Handle<Expression>>,
+ },
+ /// Gather a value from another active thread in the subgroup
+ SubgroupGather {
+ /// Specifies which thread to gather from
+ mode: GatherMode,
+ /// The value to broadcast over
+ argument: Handle<Expression>,
+ /// The [`SubgroupOperationResult`] expression representing this load's result.
+ ///
+ /// [`SubgroupOperationResult`]: Expression::SubgroupOperationResult
+ result: Handle<Expression>,
+ },
+ /// Compute a collective operation across all active threads in the subgroup
+ SubgroupCollectiveOperation {
+ /// What operation to compute
+ op: SubgroupOperation,
+ /// How to combine the results
+ collective_op: CollectiveOperation,
+ /// The value to compute over
+ argument: Handle<Expression>,
+ /// The [`SubgroupOperationResult`] expression representing this load's result.
+ ///
+ /// [`SubgroupOperationResult`]: Expression::SubgroupOperationResult
+ result: Handle<Expression>,
+ },
}
/// A function argument.
@@ -1913,8 +1998,7 @@ pub struct FunctionResult {
}
/// A function defined in the module.
-#[derive(Debug, Default)]
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
@@ -1978,8 +2062,7 @@ pub struct Function {
/// [`Location`]: Binding::Location
/// [`function`]: EntryPoint::function
/// [`stage`]: EntryPoint::stage
-#[derive(Debug)]
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
@@ -2003,8 +2086,7 @@ pub struct EntryPoint {
/// These cannot be spelled in WGSL source.
///
/// Stored in [`SpecialTypes::predeclared_types`] and created by [`Module::generate_predeclared_type`].
-#[derive(Debug, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
@@ -2021,8 +2103,7 @@ pub enum PredeclaredType {
}
/// Set of special types that can be optionally generated by the frontends.
-#[derive(Debug, Default)]
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
@@ -2057,8 +2138,7 @@ pub struct SpecialTypes {
/// Alternatively, you can load an existing shader using one of the [available front ends][front].
///
/// When finished, you can export modules using one of the [available backends][back].
-#[derive(Debug, Default)]
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
@@ -2069,6 +2149,8 @@ pub struct Module {
pub special_types: SpecialTypes,
/// Arena for the constants defined in this module.
pub constants: Arena<Constant>,
+ /// Arena for the pipeline-overridable constants defined in this module.
+ pub overrides: Arena<Override>,
/// Arena for the global variables defined in this module.
pub global_variables: Arena<GlobalVariable>,
/// [Constant expressions] and [override expressions] used by this module.
@@ -2078,7 +2160,7 @@ pub struct Module {
///
/// [Constant expressions]: index.html#constant-expressions
/// [override expressions]: index.html#override-expressions
- pub const_expressions: Arena<Expression>,
+ pub global_expressions: Arena<Expression>,
/// Arena for the functions defined in this module.
///
/// Each function must appear in this arena strictly before all its callers.
diff --git a/third_party/rust/naga/src/proc/constant_evaluator.rs b/third_party/rust/naga/src/proc/constant_evaluator.rs
index 983af3718c..ead3d00980 100644
--- a/third_party/rust/naga/src/proc/constant_evaluator.rs
+++ b/third_party/rust/naga/src/proc/constant_evaluator.rs
@@ -4,8 +4,8 @@ use arrayvec::ArrayVec;
use crate::{
arena::{Arena, Handle, UniqueArena},
- ArraySize, BinaryOperator, Constant, Expression, Literal, ScalarKind, Span, Type, TypeInner,
- UnaryOperator,
+ ArraySize, BinaryOperator, Constant, Expression, Literal, Override, ScalarKind, Span, Type,
+ TypeInner, UnaryOperator,
};
/// A macro that allows dollar signs (`$`) to be emitted by other macros. Useful for generating
@@ -253,9 +253,20 @@ gen_component_wise_extractor! {
}
#[derive(Debug)]
-enum Behavior {
- Wgsl,
- Glsl,
+enum Behavior<'a> {
+ Wgsl(WgslRestrictions<'a>),
+ Glsl(GlslRestrictions<'a>),
+}
+
+impl Behavior<'_> {
+ /// Returns `true` if the inner WGSL/GLSL restrictions are runtime restrictions.
+ const fn has_runtime_restrictions(&self) -> bool {
+ matches!(
+ self,
+ &Behavior::Wgsl(WgslRestrictions::Runtime(_))
+ | &Behavior::Glsl(GlslRestrictions::Runtime(_))
+ )
+ }
}
/// A context for evaluating constant expressions.
@@ -278,7 +289,7 @@ enum Behavior {
#[derive(Debug)]
pub struct ConstantEvaluator<'a> {
/// Which language's evaluation rules we should follow.
- behavior: Behavior,
+ behavior: Behavior<'a>,
/// The module's type arena.
///
@@ -291,71 +302,155 @@ pub struct ConstantEvaluator<'a> {
/// The module's constant arena.
constants: &'a Arena<Constant>,
+ /// The module's override arena.
+ overrides: &'a Arena<Override>,
+
/// The arena to which we are contributing expressions.
expressions: &'a mut Arena<Expression>,
- /// When `self.expressions` refers to a function's local expression
- /// arena, this needs to be populated
- function_local_data: Option<FunctionLocalData<'a>>,
+ /// Tracks the constness of expressions residing in [`Self::expressions`]
+ expression_kind_tracker: &'a mut ExpressionKindTracker,
+}
+
+#[derive(Debug)]
+enum WgslRestrictions<'a> {
+ /// - const-expressions will be evaluated and inserted in the arena
+ Const,
+ /// - const-expressions will be evaluated and inserted in the arena
+ /// - override-expressions will be inserted in the arena
+ Override,
+ /// - const-expressions will be evaluated and inserted in the arena
+ /// - override-expressions will be inserted in the arena
+ /// - runtime-expressions will be inserted in the arena
+ Runtime(FunctionLocalData<'a>),
+}
+
+#[derive(Debug)]
+enum GlslRestrictions<'a> {
+ /// - const-expressions will be evaluated and inserted in the arena
+ Const,
+ /// - const-expressions will be evaluated and inserted in the arena
+ /// - override-expressions will be inserted in the arena
+ /// - runtime-expressions will be inserted in the arena
+ Runtime(FunctionLocalData<'a>),
}
#[derive(Debug)]
struct FunctionLocalData<'a> {
/// Global constant expressions
- const_expressions: &'a Arena<Expression>,
- /// Tracks the constness of expressions residing in `ConstantEvaluator.expressions`
- expression_constness: &'a mut ExpressionConstnessTracker,
+ global_expressions: &'a Arena<Expression>,
emitter: &'a mut super::Emitter,
block: &'a mut crate::Block,
}
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+pub enum ExpressionKind {
+ Const,
+ Override,
+ Runtime,
+}
+
#[derive(Debug)]
-pub struct ExpressionConstnessTracker {
- inner: bit_set::BitSet,
+pub struct ExpressionKindTracker {
+ inner: Vec<ExpressionKind>,
}
-impl ExpressionConstnessTracker {
- pub fn new() -> Self {
- Self {
- inner: bit_set::BitSet::new(),
- }
+impl ExpressionKindTracker {
+ pub const fn new() -> Self {
+ Self { inner: Vec::new() }
}
/// Forces the the expression to not be const
pub fn force_non_const(&mut self, value: Handle<Expression>) {
- self.inner.remove(value.index());
+ self.inner[value.index()] = ExpressionKind::Runtime;
}
- fn insert(&mut self, value: Handle<Expression>) {
- self.inner.insert(value.index());
+ pub fn insert(&mut self, value: Handle<Expression>, expr_type: ExpressionKind) {
+ assert_eq!(self.inner.len(), value.index());
+ self.inner.push(expr_type);
+ }
+ pub fn is_const(&self, h: Handle<Expression>) -> bool {
+ matches!(self.type_of(h), ExpressionKind::Const)
+ }
+
+ pub fn is_const_or_override(&self, h: Handle<Expression>) -> bool {
+ matches!(
+ self.type_of(h),
+ ExpressionKind::Const | ExpressionKind::Override
+ )
}
- pub fn is_const(&self, value: Handle<Expression>) -> bool {
- self.inner.contains(value.index())
+ fn type_of(&self, value: Handle<Expression>) -> ExpressionKind {
+ self.inner[value.index()]
}
pub fn from_arena(arena: &Arena<Expression>) -> Self {
- let mut tracker = Self::new();
- for (handle, expr) in arena.iter() {
- let insert = match *expr {
- crate::Expression::Literal(_)
- | crate::Expression::ZeroValue(_)
- | crate::Expression::Constant(_) => true,
- crate::Expression::Compose { ref components, .. } => {
- components.iter().all(|h| tracker.is_const(*h))
- }
- crate::Expression::Splat { value, .. } => tracker.is_const(value),
- _ => false,
- };
- if insert {
- tracker.insert(handle);
- }
+ let mut tracker = Self {
+ inner: Vec::with_capacity(arena.len()),
+ };
+ for (_, expr) in arena.iter() {
+ tracker.inner.push(tracker.type_of_with_expr(expr));
}
tracker
}
+
+ fn type_of_with_expr(&self, expr: &Expression) -> ExpressionKind {
+ match *expr {
+ Expression::Literal(_) | Expression::ZeroValue(_) | Expression::Constant(_) => {
+ ExpressionKind::Const
+ }
+ Expression::Override(_) => ExpressionKind::Override,
+ Expression::Compose { ref components, .. } => {
+ let mut expr_type = ExpressionKind::Const;
+ for component in components {
+ expr_type = expr_type.max(self.type_of(*component))
+ }
+ expr_type
+ }
+ Expression::Splat { value, .. } => self.type_of(value),
+ Expression::AccessIndex { base, .. } => self.type_of(base),
+ Expression::Access { base, index } => self.type_of(base).max(self.type_of(index)),
+ Expression::Swizzle { vector, .. } => self.type_of(vector),
+ Expression::Unary { expr, .. } => self.type_of(expr),
+ Expression::Binary { left, right, .. } => self.type_of(left).max(self.type_of(right)),
+ Expression::Math {
+ arg,
+ arg1,
+ arg2,
+ arg3,
+ ..
+ } => self
+ .type_of(arg)
+ .max(
+ arg1.map(|arg| self.type_of(arg))
+ .unwrap_or(ExpressionKind::Const),
+ )
+ .max(
+ arg2.map(|arg| self.type_of(arg))
+ .unwrap_or(ExpressionKind::Const),
+ )
+ .max(
+ arg3.map(|arg| self.type_of(arg))
+ .unwrap_or(ExpressionKind::Const),
+ ),
+ Expression::As { expr, .. } => self.type_of(expr),
+ Expression::Select {
+ condition,
+ accept,
+ reject,
+ } => self
+ .type_of(condition)
+ .max(self.type_of(accept))
+ .max(self.type_of(reject)),
+ Expression::Relational { argument, .. } => self.type_of(argument),
+ Expression::ArrayLength(expr) => self.type_of(expr),
+ _ => ExpressionKind::Runtime,
+ }
+ }
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum ConstantEvaluatorError {
#[error("Constants cannot access function arguments")]
FunctionArg,
@@ -381,6 +476,8 @@ pub enum ConstantEvaluatorError {
ImageExpression,
#[error("Constants don't support ray query expressions")]
RayQueryExpression,
+ #[error("Constants don't support subgroup expressions")]
+ SubgroupExpression,
#[error("Cannot access the type")]
InvalidAccessBase,
#[error("Cannot access at the index")]
@@ -432,6 +529,12 @@ pub enum ConstantEvaluatorError {
ShiftedMoreThan32Bits,
#[error(transparent)]
Literal(#[from] crate::valid::LiteralError),
+ #[error("Can't use pipeline-overridable constants in const-expressions")]
+ Override,
+ #[error("Unexpected runtime-expression")]
+ RuntimeExpr,
+ #[error("Unexpected override-expression")]
+ OverrideExpr,
}
impl<'a> ConstantEvaluator<'a> {
@@ -439,25 +542,49 @@ impl<'a> ConstantEvaluator<'a> {
/// constant expression arena.
///
/// Report errors according to WGSL's rules for constant evaluation.
- pub fn for_wgsl_module(module: &'a mut crate::Module) -> Self {
- Self::for_module(Behavior::Wgsl, module)
+ pub fn for_wgsl_module(
+ module: &'a mut crate::Module,
+ global_expression_kind_tracker: &'a mut ExpressionKindTracker,
+ in_override_ctx: bool,
+ ) -> Self {
+ Self::for_module(
+ Behavior::Wgsl(if in_override_ctx {
+ WgslRestrictions::Override
+ } else {
+ WgslRestrictions::Const
+ }),
+ module,
+ global_expression_kind_tracker,
+ )
}
/// Return a [`ConstantEvaluator`] that will add expressions to `module`'s
/// constant expression arena.
///
/// Report errors according to GLSL's rules for constant evaluation.
- pub fn for_glsl_module(module: &'a mut crate::Module) -> Self {
- Self::for_module(Behavior::Glsl, module)
+ pub fn for_glsl_module(
+ module: &'a mut crate::Module,
+ global_expression_kind_tracker: &'a mut ExpressionKindTracker,
+ ) -> Self {
+ Self::for_module(
+ Behavior::Glsl(GlslRestrictions::Const),
+ module,
+ global_expression_kind_tracker,
+ )
}
- fn for_module(behavior: Behavior, module: &'a mut crate::Module) -> Self {
+ fn for_module(
+ behavior: Behavior<'a>,
+ module: &'a mut crate::Module,
+ global_expression_kind_tracker: &'a mut ExpressionKindTracker,
+ ) -> Self {
Self {
behavior,
types: &mut module.types,
constants: &module.constants,
- expressions: &mut module.const_expressions,
- function_local_data: None,
+ overrides: &module.overrides,
+ expressions: &mut module.global_expressions,
+ expression_kind_tracker: global_expression_kind_tracker,
}
}
@@ -468,18 +595,22 @@ impl<'a> ConstantEvaluator<'a> {
pub fn for_wgsl_function(
module: &'a mut crate::Module,
expressions: &'a mut Arena<Expression>,
- expression_constness: &'a mut ExpressionConstnessTracker,
+ local_expression_kind_tracker: &'a mut ExpressionKindTracker,
emitter: &'a mut super::Emitter,
block: &'a mut crate::Block,
) -> Self {
- Self::for_function(
- Behavior::Wgsl,
- module,
+ Self {
+ behavior: Behavior::Wgsl(WgslRestrictions::Runtime(FunctionLocalData {
+ global_expressions: &module.global_expressions,
+ emitter,
+ block,
+ })),
+ types: &mut module.types,
+ constants: &module.constants,
+ overrides: &module.overrides,
expressions,
- expression_constness,
- emitter,
- block,
- )
+ expression_kind_tracker: local_expression_kind_tracker,
+ }
}
/// Return a [`ConstantEvaluator`] that will add expressions to `function`'s
@@ -489,39 +620,21 @@ impl<'a> ConstantEvaluator<'a> {
pub fn for_glsl_function(
module: &'a mut crate::Module,
expressions: &'a mut Arena<Expression>,
- expression_constness: &'a mut ExpressionConstnessTracker,
- emitter: &'a mut super::Emitter,
- block: &'a mut crate::Block,
- ) -> Self {
- Self::for_function(
- Behavior::Glsl,
- module,
- expressions,
- expression_constness,
- emitter,
- block,
- )
- }
-
- fn for_function(
- behavior: Behavior,
- module: &'a mut crate::Module,
- expressions: &'a mut Arena<Expression>,
- expression_constness: &'a mut ExpressionConstnessTracker,
+ local_expression_kind_tracker: &'a mut ExpressionKindTracker,
emitter: &'a mut super::Emitter,
block: &'a mut crate::Block,
) -> Self {
Self {
- behavior,
+ behavior: Behavior::Glsl(GlslRestrictions::Runtime(FunctionLocalData {
+ global_expressions: &module.global_expressions,
+ emitter,
+ block,
+ })),
types: &mut module.types,
constants: &module.constants,
+ overrides: &module.overrides,
expressions,
- function_local_data: Some(FunctionLocalData {
- const_expressions: &module.const_expressions,
- expression_constness,
- emitter,
- block,
- }),
+ expression_kind_tracker: local_expression_kind_tracker,
}
}
@@ -529,19 +642,18 @@ impl<'a> ConstantEvaluator<'a> {
crate::proc::GlobalCtx {
types: self.types,
constants: self.constants,
- const_expressions: match self.function_local_data {
- Some(ref data) => data.const_expressions,
+ overrides: self.overrides,
+ global_expressions: match self.function_local_data() {
+ Some(data) => data.global_expressions,
None => self.expressions,
},
}
}
fn check(&self, expr: Handle<Expression>) -> Result<(), ConstantEvaluatorError> {
- if let Some(ref function_local_data) = self.function_local_data {
- if !function_local_data.expression_constness.is_const(expr) {
- log::debug!("check: SubexpressionsAreNotConstant");
- return Err(ConstantEvaluatorError::SubexpressionsAreNotConstant);
- }
+ if !self.expression_kind_tracker.is_const(expr) {
+ log::debug!("check: SubexpressionsAreNotConstant");
+ return Err(ConstantEvaluatorError::SubexpressionsAreNotConstant);
}
Ok(())
}
@@ -554,11 +666,11 @@ impl<'a> ConstantEvaluator<'a> {
Expression::Constant(c) => {
// Are we working in a function's expression arena, or the
// module's constant expression arena?
- if let Some(ref function_local_data) = self.function_local_data {
+ if let Some(function_local_data) = self.function_local_data() {
// Deep-copy the constant's value into our arena.
self.copy_from(
self.constants[c].init,
- function_local_data.const_expressions,
+ function_local_data.global_expressions,
)
} else {
// "See through" the constant and use its initializer.
@@ -580,9 +692,11 @@ impl<'a> ConstantEvaluator<'a> {
/// [`ZeroValue`], and [`Swizzle`] expressions - to the expression arena
/// `self` contributes to.
///
- /// If `expr`'s value cannot be determined at compile time, return a an
- /// error. If it's acceptable to evaluate `expr` at runtime, this error can
- /// be ignored, and the caller can append `expr` to the arena itself.
+ /// If `expr`'s value cannot be determined at compile time, and `self` is
+ /// contributing to some function's expression arena, then append `expr` to
+ /// that arena unchanged (and thus unevaluated). Otherwise, `self` must be
+ /// contributing to the module's constant expression arena; since `expr`'s
+ /// value is not a constant, return an error.
///
/// We only consider `expr` itself, without recursing into its operands. Its
/// operands must all have been produced by prior calls to
@@ -595,16 +709,81 @@ impl<'a> ConstantEvaluator<'a> {
/// [`Swizzle`]: Expression::Swizzle
pub fn try_eval_and_append(
&mut self,
+ expr: Expression,
+ span: Span,
+ ) -> Result<Handle<Expression>, ConstantEvaluatorError> {
+ match self.expression_kind_tracker.type_of_with_expr(&expr) {
+ ExpressionKind::Const => {
+ let eval_result = self.try_eval_and_append_impl(&expr, span);
+ // We should be able to evaluate `Const` expressions at this
+ // point. If we failed to, then that probably means we just
+ // haven't implemented that part of constant evaluation. Work
+ // around this by simply emitting it as a run-time expression.
+ if self.behavior.has_runtime_restrictions()
+ && matches!(
+ eval_result,
+ Err(ConstantEvaluatorError::NotImplemented(_)
+ | ConstantEvaluatorError::InvalidBinaryOpArgs,)
+ )
+ {
+ Ok(self.append_expr(expr, span, ExpressionKind::Runtime))
+ } else {
+ eval_result
+ }
+ }
+ ExpressionKind::Override => match self.behavior {
+ Behavior::Wgsl(WgslRestrictions::Override | WgslRestrictions::Runtime(_)) => {
+ Ok(self.append_expr(expr, span, ExpressionKind::Override))
+ }
+ Behavior::Wgsl(WgslRestrictions::Const) => {
+ Err(ConstantEvaluatorError::OverrideExpr)
+ }
+ Behavior::Glsl(_) => {
+ unreachable!()
+ }
+ },
+ ExpressionKind::Runtime => {
+ if self.behavior.has_runtime_restrictions() {
+ Ok(self.append_expr(expr, span, ExpressionKind::Runtime))
+ } else {
+ Err(ConstantEvaluatorError::RuntimeExpr)
+ }
+ }
+ }
+ }
+
+ /// Is the [`Self::expressions`] arena the global module expression arena?
+ const fn is_global_arena(&self) -> bool {
+ matches!(
+ self.behavior,
+ Behavior::Wgsl(WgslRestrictions::Const | WgslRestrictions::Override)
+ | Behavior::Glsl(GlslRestrictions::Const)
+ )
+ }
+
+ const fn function_local_data(&self) -> Option<&FunctionLocalData<'a>> {
+ match self.behavior {
+ Behavior::Wgsl(WgslRestrictions::Runtime(ref function_local_data))
+ | Behavior::Glsl(GlslRestrictions::Runtime(ref function_local_data)) => {
+ Some(function_local_data)
+ }
+ _ => None,
+ }
+ }
+
+ fn try_eval_and_append_impl(
+ &mut self,
expr: &Expression,
span: Span,
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
log::trace!("try_eval_and_append: {:?}", expr);
match *expr {
- Expression::Constant(c) if self.function_local_data.is_none() => {
+ Expression::Constant(c) if self.is_global_arena() => {
// "See through" the constant and use its initializer.
// This is mainly done to avoid having constants pointing to other constants.
Ok(self.constants[c].init)
}
+ Expression::Override(_) => Err(ConstantEvaluatorError::Override),
Expression::Literal(_) | Expression::ZeroValue(_) | Expression::Constant(_) => {
self.register_evaluated_expr(expr.clone(), span)
}
@@ -685,8 +864,8 @@ impl<'a> ConstantEvaluator<'a> {
format!("{fun:?} built-in function"),
)),
Expression::ArrayLength(expr) => match self.behavior {
- Behavior::Wgsl => Err(ConstantEvaluatorError::ArrayLength),
- Behavior::Glsl => {
+ Behavior::Wgsl(_) => Err(ConstantEvaluatorError::ArrayLength),
+ Behavior::Glsl(_) => {
let expr = self.check_and_get(expr)?;
self.array_length(expr, span)
}
@@ -707,6 +886,12 @@ impl<'a> ConstantEvaluator<'a> {
Expression::RayQueryProceedResult | Expression::RayQueryGetIntersection { .. } => {
Err(ConstantEvaluatorError::RayQueryExpression)
}
+ Expression::SubgroupBallotResult { .. } => {
+ Err(ConstantEvaluatorError::SubgroupExpression)
+ }
+ Expression::SubgroupOperationResult { .. } => {
+ Err(ConstantEvaluatorError::SubgroupExpression)
+ }
}
}
@@ -765,10 +950,10 @@ impl<'a> ConstantEvaluator<'a> {
pattern: [crate::SwizzleComponent; 4],
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
let mut get_dst_ty = |ty| match self.types[ty].inner {
- crate::TypeInner::Vector { size: _, scalar } => Ok(self.types.insert(
+ TypeInner::Vector { size: _, scalar } => Ok(self.types.insert(
Type {
name: None,
- inner: crate::TypeInner::Vector { size, scalar },
+ inner: TypeInner::Vector { size, scalar },
},
span,
)),
@@ -1059,13 +1244,11 @@ impl<'a> ConstantEvaluator<'a> {
Expression::ZeroValue(ty) | Expression::Compose { ty, .. } => {
match self.types[ty].inner {
TypeInner::Array { size, .. } => match size {
- crate::ArraySize::Constant(len) => {
+ ArraySize::Constant(len) => {
let expr = Expression::Literal(Literal::U32(len.get()));
self.register_evaluated_expr(expr, span)
}
- crate::ArraySize::Dynamic => {
- Err(ConstantEvaluatorError::ArrayLengthDynamic)
- }
+ ArraySize::Dynamic => Err(ConstantEvaluatorError::ArrayLengthDynamic),
},
_ => Err(ConstantEvaluatorError::InvalidArrayLengthArg),
}
@@ -1128,7 +1311,7 @@ impl<'a> ConstantEvaluator<'a> {
Expression::ZeroValue(ty)
if matches!(
self.types[ty].inner,
- crate::TypeInner::Scalar(crate::Scalar {
+ TypeInner::Scalar(crate::Scalar {
kind: ScalarKind::Uint,
..
})
@@ -1443,7 +1626,7 @@ impl<'a> ConstantEvaluator<'a> {
return self.cast(expr, target, span);
};
- let crate::TypeInner::Array {
+ let TypeInner::Array {
base: _,
size,
stride: _,
@@ -1853,29 +2036,35 @@ impl<'a> ConstantEvaluator<'a> {
crate::valid::check_literal_value(literal)?;
}
- if let Some(FunctionLocalData {
- ref mut emitter,
- ref mut block,
- ref mut expression_constness,
- ..
- }) = self.function_local_data
- {
- let is_running = emitter.is_running();
- let needs_pre_emit = expr.needs_pre_emit();
- if is_running && needs_pre_emit {
- block.extend(emitter.finish(self.expressions));
- let h = self.expressions.append(expr, span);
- emitter.start(self.expressions);
- expression_constness.insert(h);
- Ok(h)
- } else {
- let h = self.expressions.append(expr, span);
- expression_constness.insert(h);
- Ok(h)
+ Ok(self.append_expr(expr, span, ExpressionKind::Const))
+ }
+
+ fn append_expr(
+ &mut self,
+ expr: Expression,
+ span: Span,
+ expr_type: ExpressionKind,
+ ) -> Handle<Expression> {
+ let h = match self.behavior {
+ Behavior::Wgsl(WgslRestrictions::Runtime(ref mut function_local_data))
+ | Behavior::Glsl(GlslRestrictions::Runtime(ref mut function_local_data)) => {
+ let is_running = function_local_data.emitter.is_running();
+ let needs_pre_emit = expr.needs_pre_emit();
+ if is_running && needs_pre_emit {
+ function_local_data
+ .block
+ .extend(function_local_data.emitter.finish(self.expressions));
+ let h = self.expressions.append(expr, span);
+ function_local_data.emitter.start(self.expressions);
+ h
+ } else {
+ self.expressions.append(expr, span)
+ }
}
- } else {
- Ok(self.expressions.append(expr, span))
- }
+ _ => self.expressions.append(expr, span),
+ };
+ self.expression_kind_tracker.insert(h, expr_type);
+ h
}
fn resolve_type(
@@ -2029,13 +2218,14 @@ mod tests {
UniqueArena, VectorSize,
};
- use super::{Behavior, ConstantEvaluator};
+ use super::{Behavior, ConstantEvaluator, ExpressionKindTracker, WgslRestrictions};
#[test]
fn unary_op() {
let mut types = UniqueArena::new();
let mut constants = Arena::new();
- let mut const_expressions = Arena::new();
+ let overrides = Arena::new();
+ let mut global_expressions = Arena::new();
let scalar_ty = types.insert(
Type {
@@ -2059,9 +2249,8 @@ mod tests {
let h = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: scalar_ty,
- init: const_expressions
+ init: global_expressions
.append(Expression::Literal(Literal::I32(4)), Default::default()),
},
Default::default(),
@@ -2070,9 +2259,8 @@ mod tests {
let h1 = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: scalar_ty,
- init: const_expressions
+ init: global_expressions
.append(Expression::Literal(Literal::I32(8)), Default::default()),
},
Default::default(),
@@ -2081,9 +2269,8 @@ mod tests {
let vec_h = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: vec_ty,
- init: const_expressions.append(
+ init: global_expressions.append(
Expression::Compose {
ty: vec_ty,
components: vec![constants[h].init, constants[h1].init],
@@ -2094,8 +2281,8 @@ mod tests {
Default::default(),
);
- let expr = const_expressions.append(Expression::Constant(h), Default::default());
- let expr1 = const_expressions.append(Expression::Constant(vec_h), Default::default());
+ let expr = global_expressions.append(Expression::Constant(h), Default::default());
+ let expr1 = global_expressions.append(Expression::Constant(vec_h), Default::default());
let expr2 = Expression::Unary {
op: UnaryOperator::Negate,
@@ -2112,35 +2299,37 @@ mod tests {
expr: expr1,
};
+ let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
let mut solver = ConstantEvaluator {
- behavior: Behavior::Wgsl,
+ behavior: Behavior::Wgsl(WgslRestrictions::Const),
types: &mut types,
constants: &constants,
- expressions: &mut const_expressions,
- function_local_data: None,
+ overrides: &overrides,
+ expressions: &mut global_expressions,
+ expression_kind_tracker,
};
let res1 = solver
- .try_eval_and_append(&expr2, Default::default())
+ .try_eval_and_append(expr2, Default::default())
.unwrap();
let res2 = solver
- .try_eval_and_append(&expr3, Default::default())
+ .try_eval_and_append(expr3, Default::default())
.unwrap();
let res3 = solver
- .try_eval_and_append(&expr4, Default::default())
+ .try_eval_and_append(expr4, Default::default())
.unwrap();
assert_eq!(
- const_expressions[res1],
+ global_expressions[res1],
Expression::Literal(Literal::I32(-4))
);
assert_eq!(
- const_expressions[res2],
+ global_expressions[res2],
Expression::Literal(Literal::I32(!4))
);
- let res3_inner = &const_expressions[res3];
+ let res3_inner = &global_expressions[res3];
match *res3_inner {
Expression::Compose {
@@ -2150,11 +2339,11 @@ mod tests {
assert_eq!(*ty, vec_ty);
let mut components_iter = components.iter().copied();
assert_eq!(
- const_expressions[components_iter.next().unwrap()],
+ global_expressions[components_iter.next().unwrap()],
Expression::Literal(Literal::I32(!4))
);
assert_eq!(
- const_expressions[components_iter.next().unwrap()],
+ global_expressions[components_iter.next().unwrap()],
Expression::Literal(Literal::I32(!8))
);
assert!(components_iter.next().is_none());
@@ -2167,7 +2356,8 @@ mod tests {
fn cast() {
let mut types = UniqueArena::new();
let mut constants = Arena::new();
- let mut const_expressions = Arena::new();
+ let overrides = Arena::new();
+ let mut global_expressions = Arena::new();
let scalar_ty = types.insert(
Type {
@@ -2180,15 +2370,14 @@ mod tests {
let h = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: scalar_ty,
- init: const_expressions
+ init: global_expressions
.append(Expression::Literal(Literal::I32(4)), Default::default()),
},
Default::default(),
);
- let expr = const_expressions.append(Expression::Constant(h), Default::default());
+ let expr = global_expressions.append(Expression::Constant(h), Default::default());
let root = Expression::As {
expr,
@@ -2196,20 +2385,22 @@ mod tests {
convert: Some(crate::BOOL_WIDTH),
};
+ let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
let mut solver = ConstantEvaluator {
- behavior: Behavior::Wgsl,
+ behavior: Behavior::Wgsl(WgslRestrictions::Const),
types: &mut types,
constants: &constants,
- expressions: &mut const_expressions,
- function_local_data: None,
+ overrides: &overrides,
+ expressions: &mut global_expressions,
+ expression_kind_tracker,
};
let res = solver
- .try_eval_and_append(&root, Default::default())
+ .try_eval_and_append(root, Default::default())
.unwrap();
assert_eq!(
- const_expressions[res],
+ global_expressions[res],
Expression::Literal(Literal::Bool(true))
);
}
@@ -2218,7 +2409,8 @@ mod tests {
fn access() {
let mut types = UniqueArena::new();
let mut constants = Arena::new();
- let mut const_expressions = Arena::new();
+ let overrides = Arena::new();
+ let mut global_expressions = Arena::new();
let matrix_ty = types.insert(
Type {
@@ -2247,7 +2439,7 @@ mod tests {
let mut vec2_components = Vec::with_capacity(3);
for i in 0..3 {
- let h = const_expressions.append(
+ let h = global_expressions.append(
Expression::Literal(Literal::F32(i as f32)),
Default::default(),
);
@@ -2256,7 +2448,7 @@ mod tests {
}
for i in 3..6 {
- let h = const_expressions.append(
+ let h = global_expressions.append(
Expression::Literal(Literal::F32(i as f32)),
Default::default(),
);
@@ -2267,9 +2459,8 @@ mod tests {
let vec1 = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: vec_ty,
- init: const_expressions.append(
+ init: global_expressions.append(
Expression::Compose {
ty: vec_ty,
components: vec1_components,
@@ -2283,9 +2474,8 @@ mod tests {
let vec2 = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: vec_ty,
- init: const_expressions.append(
+ init: global_expressions.append(
Expression::Compose {
ty: vec_ty,
components: vec2_components,
@@ -2299,9 +2489,8 @@ mod tests {
let h = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: matrix_ty,
- init: const_expressions.append(
+ init: global_expressions.append(
Expression::Compose {
ty: matrix_ty,
components: vec![constants[vec1].init, constants[vec2].init],
@@ -2312,20 +2501,22 @@ mod tests {
Default::default(),
);
- let base = const_expressions.append(Expression::Constant(h), Default::default());
+ let base = global_expressions.append(Expression::Constant(h), Default::default());
+ let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
let mut solver = ConstantEvaluator {
- behavior: Behavior::Wgsl,
+ behavior: Behavior::Wgsl(WgslRestrictions::Const),
types: &mut types,
constants: &constants,
- expressions: &mut const_expressions,
- function_local_data: None,
+ overrides: &overrides,
+ expressions: &mut global_expressions,
+ expression_kind_tracker,
};
let root1 = Expression::AccessIndex { base, index: 1 };
let res1 = solver
- .try_eval_and_append(&root1, Default::default())
+ .try_eval_and_append(root1, Default::default())
.unwrap();
let root2 = Expression::AccessIndex {
@@ -2334,10 +2525,10 @@ mod tests {
};
let res2 = solver
- .try_eval_and_append(&root2, Default::default())
+ .try_eval_and_append(root2, Default::default())
.unwrap();
- match const_expressions[res1] {
+ match global_expressions[res1] {
Expression::Compose {
ref ty,
ref components,
@@ -2345,15 +2536,15 @@ mod tests {
assert_eq!(*ty, vec_ty);
let mut components_iter = components.iter().copied();
assert_eq!(
- const_expressions[components_iter.next().unwrap()],
+ global_expressions[components_iter.next().unwrap()],
Expression::Literal(Literal::F32(3.))
);
assert_eq!(
- const_expressions[components_iter.next().unwrap()],
+ global_expressions[components_iter.next().unwrap()],
Expression::Literal(Literal::F32(4.))
);
assert_eq!(
- const_expressions[components_iter.next().unwrap()],
+ global_expressions[components_iter.next().unwrap()],
Expression::Literal(Literal::F32(5.))
);
assert!(components_iter.next().is_none());
@@ -2362,7 +2553,7 @@ mod tests {
}
assert_eq!(
- const_expressions[res2],
+ global_expressions[res2],
Expression::Literal(Literal::F32(5.))
);
}
@@ -2371,7 +2562,8 @@ mod tests {
fn compose_of_constants() {
let mut types = UniqueArena::new();
let mut constants = Arena::new();
- let mut const_expressions = Arena::new();
+ let overrides = Arena::new();
+ let mut global_expressions = Arena::new();
let i32_ty = types.insert(
Type {
@@ -2395,27 +2587,28 @@ mod tests {
let h = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: i32_ty,
- init: const_expressions
+ init: global_expressions
.append(Expression::Literal(Literal::I32(4)), Default::default()),
},
Default::default(),
);
- let h_expr = const_expressions.append(Expression::Constant(h), Default::default());
+ let h_expr = global_expressions.append(Expression::Constant(h), Default::default());
+ let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
let mut solver = ConstantEvaluator {
- behavior: Behavior::Wgsl,
+ behavior: Behavior::Wgsl(WgslRestrictions::Const),
types: &mut types,
constants: &constants,
- expressions: &mut const_expressions,
- function_local_data: None,
+ overrides: &overrides,
+ expressions: &mut global_expressions,
+ expression_kind_tracker,
};
let solved_compose = solver
.try_eval_and_append(
- &Expression::Compose {
+ Expression::Compose {
ty: vec2_i32_ty,
components: vec![h_expr, h_expr],
},
@@ -2424,7 +2617,7 @@ mod tests {
.unwrap();
let solved_negate = solver
.try_eval_and_append(
- &Expression::Unary {
+ Expression::Unary {
op: UnaryOperator::Negate,
expr: solved_compose,
},
@@ -2432,11 +2625,11 @@ mod tests {
)
.unwrap();
- let pass = match const_expressions[solved_negate] {
+ let pass = match global_expressions[solved_negate] {
Expression::Compose { ty, ref components } => {
ty == vec2_i32_ty
&& components.iter().all(|&component| {
- let component = &const_expressions[component];
+ let component = &global_expressions[component];
matches!(*component, Expression::Literal(Literal::I32(-4)))
})
}
@@ -2451,7 +2644,8 @@ mod tests {
fn splat_of_constant() {
let mut types = UniqueArena::new();
let mut constants = Arena::new();
- let mut const_expressions = Arena::new();
+ let overrides = Arena::new();
+ let mut global_expressions = Arena::new();
let i32_ty = types.insert(
Type {
@@ -2475,27 +2669,28 @@ mod tests {
let h = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: i32_ty,
- init: const_expressions
+ init: global_expressions
.append(Expression::Literal(Literal::I32(4)), Default::default()),
},
Default::default(),
);
- let h_expr = const_expressions.append(Expression::Constant(h), Default::default());
+ let h_expr = global_expressions.append(Expression::Constant(h), Default::default());
+ let expression_kind_tracker = &mut ExpressionKindTracker::from_arena(&global_expressions);
let mut solver = ConstantEvaluator {
- behavior: Behavior::Wgsl,
+ behavior: Behavior::Wgsl(WgslRestrictions::Const),
types: &mut types,
constants: &constants,
- expressions: &mut const_expressions,
- function_local_data: None,
+ overrides: &overrides,
+ expressions: &mut global_expressions,
+ expression_kind_tracker,
};
let solved_compose = solver
.try_eval_and_append(
- &Expression::Splat {
+ Expression::Splat {
size: VectorSize::Bi,
value: h_expr,
},
@@ -2504,7 +2699,7 @@ mod tests {
.unwrap();
let solved_negate = solver
.try_eval_and_append(
- &Expression::Unary {
+ Expression::Unary {
op: UnaryOperator::Negate,
expr: solved_compose,
},
@@ -2512,11 +2707,11 @@ mod tests {
)
.unwrap();
- let pass = match const_expressions[solved_negate] {
+ let pass = match global_expressions[solved_negate] {
Expression::Compose { ty, ref components } => {
ty == vec2_i32_ty
&& components.iter().all(|&component| {
- let component = &const_expressions[component];
+ let component = &global_expressions[component];
matches!(*component, Expression::Literal(Literal::I32(-4)))
})
}
diff --git a/third_party/rust/naga/src/proc/index.rs b/third_party/rust/naga/src/proc/index.rs
index af3221c0fe..e2c3de8eb0 100644
--- a/third_party/rust/naga/src/proc/index.rs
+++ b/third_party/rust/naga/src/proc/index.rs
@@ -239,7 +239,7 @@ pub enum GuardedIndex {
pub fn find_checked_indexes(
module: &crate::Module,
function: &crate::Function,
- info: &crate::valid::FunctionInfo,
+ info: &valid::FunctionInfo,
policies: BoundsCheckPolicies,
) -> BitSet {
use crate::Expression as Ex;
@@ -321,7 +321,7 @@ pub fn access_needs_check(
mut index: GuardedIndex,
module: &crate::Module,
function: &crate::Function,
- info: &crate::valid::FunctionInfo,
+ info: &valid::FunctionInfo,
) -> Option<IndexableLength> {
let base_inner = info[base].ty.inner_with(&module.types);
// Unwrap safety: `Err` here indicates unindexable base types and invalid
diff --git a/third_party/rust/naga/src/proc/mod.rs b/third_party/rust/naga/src/proc/mod.rs
index 46cbb6c3b3..93aac5b3e5 100644
--- a/third_party/rust/naga/src/proc/mod.rs
+++ b/third_party/rust/naga/src/proc/mod.rs
@@ -11,7 +11,7 @@ mod terminator;
mod typifier;
pub use constant_evaluator::{
- ConstantEvaluator, ConstantEvaluatorError, ExpressionConstnessTracker,
+ ConstantEvaluator, ConstantEvaluatorError, ExpressionKind, ExpressionKindTracker,
};
pub use emitter::Emitter;
pub use index::{BoundsCheckPolicies, BoundsCheckPolicy, IndexableLength, IndexableLengthError};
@@ -153,56 +153,31 @@ impl super::Scalar {
}
}
-impl PartialEq for crate::Literal {
- fn eq(&self, other: &Self) -> bool {
- match (*self, *other) {
- (Self::F64(a), Self::F64(b)) => a.to_bits() == b.to_bits(),
- (Self::F32(a), Self::F32(b)) => a.to_bits() == b.to_bits(),
- (Self::U32(a), Self::U32(b)) => a == b,
- (Self::I32(a), Self::I32(b)) => a == b,
- (Self::U64(a), Self::U64(b)) => a == b,
- (Self::I64(a), Self::I64(b)) => a == b,
- (Self::Bool(a), Self::Bool(b)) => a == b,
- _ => false,
- }
- }
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum HashableLiteral {
+ F64(u64),
+ F32(u32),
+ U32(u32),
+ I32(i32),
+ U64(u64),
+ I64(i64),
+ Bool(bool),
+ AbstractInt(i64),
+ AbstractFloat(u64),
}
-impl Eq for crate::Literal {}
-impl std::hash::Hash for crate::Literal {
- fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
- match *self {
- Self::F64(v) | Self::AbstractFloat(v) => {
- hasher.write_u8(0);
- v.to_bits().hash(hasher);
- }
- Self::F32(v) => {
- hasher.write_u8(1);
- v.to_bits().hash(hasher);
- }
- Self::U32(v) => {
- hasher.write_u8(2);
- v.hash(hasher);
- }
- Self::I32(v) => {
- hasher.write_u8(3);
- v.hash(hasher);
- }
- Self::Bool(v) => {
- hasher.write_u8(4);
- v.hash(hasher);
- }
- Self::I64(v) => {
- hasher.write_u8(5);
- v.hash(hasher);
- }
- Self::U64(v) => {
- hasher.write_u8(6);
- v.hash(hasher);
- }
- Self::AbstractInt(v) => {
- hasher.write_u8(7);
- v.hash(hasher);
- }
+
+impl From<crate::Literal> for HashableLiteral {
+ fn from(l: crate::Literal) -> Self {
+ match l {
+ crate::Literal::F64(v) => Self::F64(v.to_bits()),
+ crate::Literal::F32(v) => Self::F32(v.to_bits()),
+ crate::Literal::U32(v) => Self::U32(v),
+ crate::Literal::I32(v) => Self::I32(v),
+ crate::Literal::U64(v) => Self::U64(v),
+ crate::Literal::I64(v) => Self::I64(v),
+ crate::Literal::Bool(v) => Self::Bool(v),
+ crate::Literal::AbstractInt(v) => Self::AbstractInt(v),
+ crate::Literal::AbstractFloat(v) => Self::AbstractFloat(v.to_bits()),
}
}
}
@@ -216,8 +191,8 @@ impl crate::Literal {
(value, crate::ScalarKind::Sint, 4) => Some(Self::I32(value as _)),
(value, crate::ScalarKind::Uint, 8) => Some(Self::U64(value as _)),
(value, crate::ScalarKind::Sint, 8) => Some(Self::I64(value as _)),
- (1, crate::ScalarKind::Bool, 4) => Some(Self::Bool(true)),
- (0, crate::ScalarKind::Bool, 4) => Some(Self::Bool(false)),
+ (1, crate::ScalarKind::Bool, crate::BOOL_WIDTH) => Some(Self::Bool(true)),
+ (0, crate::ScalarKind::Bool, crate::BOOL_WIDTH) => Some(Self::Bool(false)),
_ => None,
}
}
@@ -279,8 +254,9 @@ impl super::TypeInner {
self.scalar().map(|scalar| scalar.kind)
}
+ /// Returns the scalar width in bytes
pub fn scalar_width(&self) -> Option<u8> {
- self.scalar().map(|scalar| scalar.width * 8)
+ self.scalar().map(|scalar| scalar.width)
}
pub const fn pointer_space(&self) -> Option<crate::AddressSpace> {
@@ -532,6 +508,7 @@ impl crate::Expression {
match *self {
Self::Literal(_)
| Self::Constant(_)
+ | Self::Override(_)
| Self::ZeroValue(_)
| Self::FunctionArgument(_)
| Self::GlobalVariable(_)
@@ -553,13 +530,9 @@ impl crate::Expression {
///
/// [`Access`]: crate::Expression::Access
/// [`ResolveContext`]: crate::proc::ResolveContext
- pub fn is_dynamic_index(&self, module: &crate::Module) -> bool {
+ pub const fn is_dynamic_index(&self) -> bool {
match *self {
- Self::Literal(_) | Self::ZeroValue(_) => false,
- Self::Constant(handle) => {
- let constant = &module.constants[handle];
- !matches!(constant.r#override, crate::Override::None)
- }
+ Self::Literal(_) | Self::ZeroValue(_) | Self::Constant(_) => false,
_ => true,
}
}
@@ -652,7 +625,8 @@ impl crate::Module {
GlobalCtx {
types: &self.types,
constants: &self.constants,
- const_expressions: &self.const_expressions,
+ overrides: &self.overrides,
+ global_expressions: &self.global_expressions,
}
}
}
@@ -667,17 +641,18 @@ pub(super) enum U32EvalError {
pub struct GlobalCtx<'a> {
pub types: &'a crate::UniqueArena<crate::Type>,
pub constants: &'a crate::Arena<crate::Constant>,
- pub const_expressions: &'a crate::Arena<crate::Expression>,
+ pub overrides: &'a crate::Arena<crate::Override>,
+ pub global_expressions: &'a crate::Arena<crate::Expression>,
}
impl GlobalCtx<'_> {
- /// Try to evaluate the expression in `self.const_expressions` using its `handle` and return it as a `u32`.
+ /// Try to evaluate the expression in `self.global_expressions` using its `handle` and return it as a `u32`.
#[allow(dead_code)]
pub(super) fn eval_expr_to_u32(
&self,
handle: crate::Handle<crate::Expression>,
) -> Result<u32, U32EvalError> {
- self.eval_expr_to_u32_from(handle, self.const_expressions)
+ self.eval_expr_to_u32_from(handle, self.global_expressions)
}
/// Try to evaluate the expression in the `arena` using its `handle` and return it as a `u32`.
@@ -700,7 +675,7 @@ impl GlobalCtx<'_> {
&self,
handle: crate::Handle<crate::Expression>,
) -> Option<crate::Literal> {
- self.eval_expr_to_literal_from(handle, self.const_expressions)
+ self.eval_expr_to_literal_from(handle, self.global_expressions)
}
fn eval_expr_to_literal_from(
@@ -724,7 +699,7 @@ impl GlobalCtx<'_> {
}
match arena[handle] {
crate::Expression::Constant(c) => {
- get(*self, self.constants[c].init, self.const_expressions)
+ get(*self, self.constants[c].init, self.global_expressions)
}
_ => get(*self, handle, arena),
}
diff --git a/third_party/rust/naga/src/proc/terminator.rs b/third_party/rust/naga/src/proc/terminator.rs
index a5239d4eca..5edf55cb73 100644
--- a/third_party/rust/naga/src/proc/terminator.rs
+++ b/third_party/rust/naga/src/proc/terminator.rs
@@ -37,6 +37,9 @@ pub fn ensure_block_returns(block: &mut crate::Block) {
| S::RayQuery { .. }
| S::Atomic { .. }
| S::WorkGroupUniformLoad { .. }
+ | S::SubgroupBallot { .. }
+ | S::SubgroupCollectiveOperation { .. }
+ | S::SubgroupGather { .. }
| S::Barrier(_)),
)
| None => block.push(S::Return { value: None }, Default::default()),
diff --git a/third_party/rust/naga/src/proc/typifier.rs b/third_party/rust/naga/src/proc/typifier.rs
index 9c4403445c..3936e7efbe 100644
--- a/third_party/rust/naga/src/proc/typifier.rs
+++ b/third_party/rust/naga/src/proc/typifier.rs
@@ -185,6 +185,7 @@ pub enum ResolveError {
pub struct ResolveContext<'a> {
pub constants: &'a Arena<crate::Constant>,
+ pub overrides: &'a Arena<crate::Override>,
pub types: &'a UniqueArena<crate::Type>,
pub special_types: &'a crate::SpecialTypes,
pub global_vars: &'a Arena<crate::GlobalVariable>,
@@ -202,6 +203,7 @@ impl<'a> ResolveContext<'a> {
) -> Self {
Self {
constants: &module.constants,
+ overrides: &module.overrides,
types: &module.types,
special_types: &module.special_types,
global_vars: &module.global_variables,
@@ -407,6 +409,7 @@ impl<'a> ResolveContext<'a> {
},
crate::Expression::Literal(lit) => TypeResolution::Value(lit.ty_inner()),
crate::Expression::Constant(h) => TypeResolution::Handle(self.constants[h].ty),
+ crate::Expression::Override(h) => TypeResolution::Handle(self.overrides[h].ty),
crate::Expression::ZeroValue(ty) => TypeResolution::Handle(ty),
crate::Expression::Compose { ty, .. } => TypeResolution::Handle(ty),
crate::Expression::FunctionArgument(index) => {
@@ -595,6 +598,7 @@ impl<'a> ResolveContext<'a> {
| crate::BinaryOperator::ShiftRight => past(left)?.clone(),
},
crate::Expression::AtomicResult { ty, .. } => TypeResolution::Handle(ty),
+ crate::Expression::SubgroupOperationResult { ty } => TypeResolution::Handle(ty),
crate::Expression::WorkGroupUniformLoadResult { ty } => TypeResolution::Handle(ty),
crate::Expression::Select { accept, .. } => past(accept)?.clone(),
crate::Expression::Derivative { expr, .. } => past(expr)?.clone(),
@@ -882,6 +886,10 @@ impl<'a> ResolveContext<'a> {
.ok_or(ResolveError::MissingSpecialType)?;
TypeResolution::Handle(result)
}
+ crate::Expression::SubgroupBallotResult => TypeResolution::Value(Ti::Vector {
+ scalar: crate::Scalar::U32,
+ size: crate::VectorSize::Quad,
+ }),
})
}
}
diff --git a/third_party/rust/naga/src/span.rs b/third_party/rust/naga/src/span.rs
index 10744647e9..82cfbe5a4b 100644
--- a/third_party/rust/naga/src/span.rs
+++ b/third_party/rust/naga/src/span.rs
@@ -72,8 +72,8 @@ impl Span {
pub fn location(&self, source: &str) -> SourceLocation {
let prefix = &source[..self.start as usize];
let line_number = prefix.matches('\n').count() as u32 + 1;
- let line_start = prefix.rfind('\n').map(|pos| pos + 1).unwrap_or(0);
- let line_position = source[line_start..self.start as usize].chars().count() as u32 + 1;
+ let line_start = prefix.rfind('\n').map(|pos| pos + 1).unwrap_or(0) as u32;
+ let line_position = self.start - line_start + 1;
SourceLocation {
line_number,
@@ -107,14 +107,14 @@ impl std::ops::Index<Span> for str {
/// Roughly corresponds to the positional members of [`GPUCompilationMessage`][gcm] from
/// the WebGPU specification, except
/// - `offset` and `length` are in bytes (UTF-8 code units), instead of UTF-16 code units.
-/// - `line_position` counts entire Unicode code points, instead of UTF-16 code units.
+/// - `line_position` is in bytes (UTF-8 code units), instead of UTF-16 code units.
///
/// [gcm]: https://www.w3.org/TR/webgpu/#gpucompilationmessage
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SourceLocation {
/// 1-based line number.
pub line_number: u32,
- /// 1-based column of the start of this span, counted in Unicode code points.
+ /// 1-based column in code units (in bytes) of the start of the span.
pub line_position: u32,
/// 0-based Offset in code units (in bytes) of the start of the span.
pub offset: u32,
@@ -136,7 +136,7 @@ impl<E> fmt::Display for WithSpan<E>
where
E: fmt::Display,
{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
@@ -304,7 +304,7 @@ impl<E> WithSpan<E> {
use term::termcolor::NoColor;
let files = files::SimpleFile::new(path, source);
- let config = codespan_reporting::term::Config::default();
+ let config = term::Config::default();
let mut writer = NoColor::new(Vec::new());
term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
String::from_utf8(writer.into_inner()).unwrap()
diff --git a/third_party/rust/naga/src/valid/analyzer.rs b/third_party/rust/naga/src/valid/analyzer.rs
index 03fbc4089b..6799e5db27 100644
--- a/third_party/rust/naga/src/valid/analyzer.rs
+++ b/third_party/rust/naga/src/valid/analyzer.rs
@@ -226,7 +226,7 @@ struct Sampling {
sampler: GlobalOrArgument,
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct FunctionInfo {
@@ -574,7 +574,7 @@ impl FunctionInfo {
non_uniform_result: self.add_ref(vector),
requirements: UniformityRequirements::empty(),
},
- E::Literal(_) | E::Constant(_) | E::ZeroValue(_) => Uniformity::new(),
+ E::Literal(_) | E::Constant(_) | E::Override(_) | E::ZeroValue(_) => Uniformity::new(),
E::Compose { ref components, .. } => {
let non_uniform_result = components
.iter()
@@ -787,6 +787,14 @@ impl FunctionInfo {
non_uniform_result: self.add_ref(query),
requirements: UniformityRequirements::empty(),
},
+ E::SubgroupBallotResult => Uniformity {
+ non_uniform_result: Some(handle),
+ requirements: UniformityRequirements::empty(),
+ },
+ E::SubgroupOperationResult { .. } => Uniformity {
+ non_uniform_result: Some(handle),
+ requirements: UniformityRequirements::empty(),
+ },
};
let ty = resolve_context.resolve(expression, |h| Ok(&self[h].ty))?;
@@ -827,7 +835,7 @@ impl FunctionInfo {
let req = self.expressions[expr.index()].uniformity.requirements;
if self
.flags
- .contains(super::ValidationFlags::CONTROL_FLOW_UNIFORMITY)
+ .contains(ValidationFlags::CONTROL_FLOW_UNIFORMITY)
&& !req.is_empty()
{
if let Some(cause) = disruptor {
@@ -1029,6 +1037,42 @@ impl FunctionInfo {
}
FunctionUniformity::new()
}
+ S::SubgroupBallot {
+ result: _,
+ predicate,
+ } => {
+ if let Some(predicate) = predicate {
+ let _ = self.add_ref(predicate);
+ }
+ FunctionUniformity::new()
+ }
+ S::SubgroupCollectiveOperation {
+ op: _,
+ collective_op: _,
+ argument,
+ result: _,
+ } => {
+ let _ = self.add_ref(argument);
+ FunctionUniformity::new()
+ }
+ S::SubgroupGather {
+ mode,
+ argument,
+ result: _,
+ } => {
+ let _ = self.add_ref(argument);
+ match mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ let _ = self.add_ref(index);
+ }
+ }
+ FunctionUniformity::new()
+ }
};
disruptor = disruptor.or(uniformity.exit_disruptor());
@@ -1047,7 +1091,7 @@ impl ModuleInfo {
gctx: crate::proc::GlobalCtx,
) -> Result<(), super::ConstExpressionError> {
self.const_expression_types[handle.index()] =
- resolve_context.resolve(&gctx.const_expressions[handle], |h| Ok(&self[h]))?;
+ resolve_context.resolve(&gctx.global_expressions[handle], |h| Ok(&self[h]))?;
Ok(())
}
@@ -1186,6 +1230,7 @@ fn uniform_control_flow() {
};
let resolve_context = ResolveContext {
constants: &Arena::new(),
+ overrides: &Arena::new(),
types: &type_arena,
special_types: &crate::SpecialTypes::default(),
global_vars: &global_var_arena,
diff --git a/third_party/rust/naga/src/valid/expression.rs b/third_party/rust/naga/src/valid/expression.rs
index 838ecc4e27..525bd28c17 100644
--- a/third_party/rust/naga/src/valid/expression.rs
+++ b/third_party/rust/naga/src/valid/expression.rs
@@ -90,6 +90,8 @@ pub enum ExpressionError {
sampler: bool,
has_ref: bool,
},
+ #[error("Sample offset must be a const-expression")]
+ InvalidSampleOffsetExprType,
#[error("Sample offset constant {1:?} doesn't match the image dimension {0:?}")]
InvalidSampleOffset(crate::ImageDimension, Handle<crate::Expression>),
#[error("Depth reference {0:?} is not a scalar float")]
@@ -129,9 +131,12 @@ pub enum ExpressionError {
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum ConstExpressionError {
- #[error("The expression is not a constant expression")]
- NonConst,
+ #[error("The expression is not a constant or override expression")]
+ NonConstOrOverride,
+ #[error("The expression is not a fully evaluated constant expression")]
+ NonFullyEvaluatedConst,
#[error(transparent)]
Compose(#[from] super::ComposeError),
#[error("Splatting {0:?} can't be done")]
@@ -184,10 +189,15 @@ impl super::Validator {
handle: Handle<crate::Expression>,
gctx: crate::proc::GlobalCtx,
mod_info: &ModuleInfo,
+ global_expr_kind: &crate::proc::ExpressionKindTracker,
) -> Result<(), ConstExpressionError> {
use crate::Expression as E;
- match gctx.const_expressions[handle] {
+ if !global_expr_kind.is_const_or_override(handle) {
+ return Err(ConstExpressionError::NonConstOrOverride);
+ }
+
+ match gctx.global_expressions[handle] {
E::Literal(literal) => {
self.validate_literal(literal)?;
}
@@ -201,14 +211,19 @@ impl super::Validator {
}
E::Splat { value, .. } => match *mod_info[value].inner_with(gctx.types) {
crate::TypeInner::Scalar { .. } => {}
- _ => return Err(super::ConstExpressionError::InvalidSplatType(value)),
+ _ => return Err(ConstExpressionError::InvalidSplatType(value)),
},
- _ => return Err(super::ConstExpressionError::NonConst),
+ _ if global_expr_kind.is_const(handle) || !self.allow_overrides => {
+ return Err(ConstExpressionError::NonFullyEvaluatedConst)
+ }
+ // the constant evaluator will report errors about override-expressions
+ _ => {}
}
Ok(())
}
+ #[allow(clippy::too_many_arguments)]
pub(super) fn validate_expression(
&self,
root: Handle<crate::Expression>,
@@ -217,6 +232,7 @@ impl super::Validator {
module: &crate::Module,
info: &FunctionInfo,
mod_info: &ModuleInfo,
+ global_expr_kind: &crate::proc::ExpressionKindTracker,
) -> Result<ShaderStages, ExpressionError> {
use crate::{Expression as E, Scalar as Sc, ScalarKind as Sk, TypeInner as Ti};
@@ -252,9 +268,7 @@ impl super::Validator {
return Err(ExpressionError::InvalidIndexType(index));
}
}
- if dynamic_indexing_restricted
- && function.expressions[index].is_dynamic_index(module)
- {
+ if dynamic_indexing_restricted && function.expressions[index].is_dynamic_index() {
return Err(ExpressionError::IndexMustBeConstant(base));
}
@@ -347,7 +361,7 @@ impl super::Validator {
self.validate_literal(literal)?;
ShaderStages::all()
}
- E::Constant(_) | E::ZeroValue(_) => ShaderStages::all(),
+ E::Constant(_) | E::Override(_) | E::ZeroValue(_) => ShaderStages::all(),
E::Compose { ref components, ty } => {
validate_compose(
ty,
@@ -464,6 +478,10 @@ impl super::Validator {
// check constant offset
if let Some(const_expr) = offset {
+ if !global_expr_kind.is_const(const_expr) {
+ return Err(ExpressionError::InvalidSampleOffsetExprType);
+ }
+
match *mod_info[const_expr].inner_with(&module.types) {
Ti::Scalar(Sc { kind: Sk::Sint, .. }) if num_components == 1 => {}
Ti::Vector {
@@ -1623,6 +1641,7 @@ impl super::Validator {
return Err(ExpressionError::InvalidRayQueryType(query));
}
},
+ E::SubgroupBallotResult | E::SubgroupOperationResult { .. } => self.subgroup_stages,
};
Ok(stages)
}
@@ -1716,7 +1735,7 @@ fn validate_with_const_expression(
use crate::span::Span;
let mut module = crate::Module::default();
- module.const_expressions.append(expr, Span::default());
+ module.global_expressions.append(expr, Span::default());
let mut validator = super::Validator::new(super::ValidationFlags::CONSTANTS, caps);
diff --git a/third_party/rust/naga/src/valid/function.rs b/third_party/rust/naga/src/valid/function.rs
index f0ca22cbda..71128fc86d 100644
--- a/third_party/rust/naga/src/valid/function.rs
+++ b/third_party/rust/naga/src/valid/function.rs
@@ -49,13 +49,26 @@ pub enum AtomicError {
#[derive(Clone, Debug, thiserror::Error)]
#[cfg_attr(test, derive(PartialEq))]
+pub enum SubgroupError {
+ #[error("Operand {0:?} has invalid type.")]
+ InvalidOperand(Handle<crate::Expression>),
+ #[error("Result type for {0:?} doesn't match the statement")]
+ ResultTypeMismatch(Handle<crate::Expression>),
+ #[error("Support for subgroup operation {0:?} is required")]
+ UnsupportedOperation(super::SubgroupOperationSet),
+ #[error("Unknown operation")]
+ UnknownOperation,
+}
+
+#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum LocalVariableError {
#[error("Local variable has a type {0:?} that can't be stored in a local variable.")]
InvalidType(Handle<crate::Type>),
#[error("Initializer doesn't match the variable type")]
InitializerType,
- #[error("Initializer is not const")]
- NonConstInitializer,
+ #[error("Initializer is not a const or override expression")]
+ NonConstOrOverrideInitializer,
}
#[derive(Clone, Debug, thiserror::Error)]
@@ -135,6 +148,8 @@ pub enum FunctionError {
InvalidRayDescriptor(Handle<crate::Expression>),
#[error("Ray Query {0:?} does not have a matching type")]
InvalidRayQueryType(Handle<crate::Type>),
+ #[error("Shader requires capability {0:?}")]
+ MissingCapability(super::Capabilities),
#[error(
"Required uniformity of control flow for {0:?} in {1:?} is not fulfilled because of {2:?}"
)]
@@ -155,6 +170,8 @@ pub enum FunctionError {
WorkgroupUniformLoadExpressionMismatch(Handle<crate::Expression>),
#[error("The expression {0:?} is not valid as a WorkGroupUniformLoad argument. It should be a Pointer in Workgroup address space")]
WorkgroupUniformLoadInvalidPointer(Handle<crate::Expression>),
+ #[error("Subgroup operation is invalid")]
+ InvalidSubgroup(#[from] SubgroupError),
}
bitflags::bitflags! {
@@ -399,6 +416,127 @@ impl super::Validator {
}
Ok(())
}
+ fn validate_subgroup_operation(
+ &mut self,
+ op: &crate::SubgroupOperation,
+ collective_op: &crate::CollectiveOperation,
+ argument: Handle<crate::Expression>,
+ result: Handle<crate::Expression>,
+ context: &BlockContext,
+ ) -> Result<(), WithSpan<FunctionError>> {
+ let argument_inner = context.resolve_type(argument, &self.valid_expression_set)?;
+
+ let (is_scalar, scalar) = match *argument_inner {
+ crate::TypeInner::Scalar(scalar) => (true, scalar),
+ crate::TypeInner::Vector { scalar, .. } => (false, scalar),
+ _ => {
+ log::error!("Subgroup operand type {:?}", argument_inner);
+ return Err(SubgroupError::InvalidOperand(argument)
+ .with_span_handle(argument, context.expressions)
+ .into_other());
+ }
+ };
+
+ use crate::ScalarKind as sk;
+ use crate::SubgroupOperation as sg;
+ match (scalar.kind, *op) {
+ (sk::Bool, sg::All | sg::Any) if is_scalar => {}
+ (sk::Sint | sk::Uint | sk::Float, sg::Add | sg::Mul | sg::Min | sg::Max) => {}
+ (sk::Sint | sk::Uint, sg::And | sg::Or | sg::Xor) => {}
+
+ (_, _) => {
+ log::error!("Subgroup operand type {:?}", argument_inner);
+ return Err(SubgroupError::InvalidOperand(argument)
+ .with_span_handle(argument, context.expressions)
+ .into_other());
+ }
+ };
+
+ use crate::CollectiveOperation as co;
+ match (*collective_op, *op) {
+ (
+ co::Reduce,
+ sg::All
+ | sg::Any
+ | sg::Add
+ | sg::Mul
+ | sg::Min
+ | sg::Max
+ | sg::And
+ | sg::Or
+ | sg::Xor,
+ ) => {}
+ (co::InclusiveScan | co::ExclusiveScan, sg::Add | sg::Mul) => {}
+
+ (_, _) => {
+ return Err(SubgroupError::UnknownOperation.with_span().into_other());
+ }
+ };
+
+ self.emit_expression(result, context)?;
+ match context.expressions[result] {
+ crate::Expression::SubgroupOperationResult { ty }
+ if { &context.types[ty].inner == argument_inner } => {}
+ _ => {
+ return Err(SubgroupError::ResultTypeMismatch(result)
+ .with_span_handle(result, context.expressions)
+ .into_other())
+ }
+ }
+ Ok(())
+ }
+ fn validate_subgroup_gather(
+ &mut self,
+ mode: &crate::GatherMode,
+ argument: Handle<crate::Expression>,
+ result: Handle<crate::Expression>,
+ context: &BlockContext,
+ ) -> Result<(), WithSpan<FunctionError>> {
+ match *mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => {
+ let index_ty = context.resolve_type(index, &self.valid_expression_set)?;
+ match *index_ty {
+ crate::TypeInner::Scalar(crate::Scalar::U32) => {}
+ _ => {
+ log::error!(
+ "Subgroup gather index type {:?}, expected unsigned int",
+ index_ty
+ );
+ return Err(SubgroupError::InvalidOperand(argument)
+ .with_span_handle(index, context.expressions)
+ .into_other());
+ }
+ }
+ }
+ }
+ let argument_inner = context.resolve_type(argument, &self.valid_expression_set)?;
+ if !matches!(*argument_inner,
+ crate::TypeInner::Scalar ( scalar, .. ) | crate::TypeInner::Vector { scalar, .. }
+ if matches!(scalar.kind, crate::ScalarKind::Uint | crate::ScalarKind::Sint | crate::ScalarKind::Float)
+ ) {
+ log::error!("Subgroup gather operand type {:?}", argument_inner);
+ return Err(SubgroupError::InvalidOperand(argument)
+ .with_span_handle(argument, context.expressions)
+ .into_other());
+ }
+
+ self.emit_expression(result, context)?;
+ match context.expressions[result] {
+ crate::Expression::SubgroupOperationResult { ty }
+ if { &context.types[ty].inner == argument_inner } => {}
+ _ => {
+ return Err(SubgroupError::ResultTypeMismatch(result)
+ .with_span_handle(result, context.expressions)
+ .into_other())
+ }
+ }
+ Ok(())
+ }
fn validate_block_impl(
&mut self,
@@ -613,8 +751,30 @@ impl super::Validator {
stages &= super::ShaderStages::FRAGMENT;
finished = true;
}
- S::Barrier(_) => {
+ S::Barrier(barrier) => {
stages &= super::ShaderStages::COMPUTE;
+ if barrier.contains(crate::Barrier::SUB_GROUP) {
+ if !self.capabilities.contains(
+ super::Capabilities::SUBGROUP | super::Capabilities::SUBGROUP_BARRIER,
+ ) {
+ return Err(FunctionError::MissingCapability(
+ super::Capabilities::SUBGROUP
+ | super::Capabilities::SUBGROUP_BARRIER,
+ )
+ .with_span_static(span, "missing capability for this operation"));
+ }
+ if !self
+ .subgroup_operations
+ .contains(super::SubgroupOperationSet::BASIC)
+ {
+ return Err(FunctionError::InvalidSubgroup(
+ SubgroupError::UnsupportedOperation(
+ super::SubgroupOperationSet::BASIC,
+ ),
+ )
+ .with_span_static(span, "support for this operation is not present"));
+ }
+ }
}
S::Store { pointer, value } => {
let mut current = pointer;
@@ -904,6 +1064,86 @@ impl super::Validator {
crate::RayQueryFunction::Terminate => {}
}
}
+ S::SubgroupBallot { result, predicate } => {
+ stages &= self.subgroup_stages;
+ if !self.capabilities.contains(super::Capabilities::SUBGROUP) {
+ return Err(FunctionError::MissingCapability(
+ super::Capabilities::SUBGROUP,
+ )
+ .with_span_static(span, "missing capability for this operation"));
+ }
+ if !self
+ .subgroup_operations
+ .contains(super::SubgroupOperationSet::BALLOT)
+ {
+ return Err(FunctionError::InvalidSubgroup(
+ SubgroupError::UnsupportedOperation(
+ super::SubgroupOperationSet::BALLOT,
+ ),
+ )
+ .with_span_static(span, "support for this operation is not present"));
+ }
+ if let Some(predicate) = predicate {
+ let predicate_inner =
+ context.resolve_type(predicate, &self.valid_expression_set)?;
+ if !matches!(
+ *predicate_inner,
+ crate::TypeInner::Scalar(crate::Scalar::BOOL,)
+ ) {
+ log::error!(
+ "Subgroup ballot predicate type {:?} expected bool",
+ predicate_inner
+ );
+ return Err(SubgroupError::InvalidOperand(predicate)
+ .with_span_handle(predicate, context.expressions)
+ .into_other());
+ }
+ }
+ self.emit_expression(result, context)?;
+ }
+ S::SubgroupCollectiveOperation {
+ ref op,
+ ref collective_op,
+ argument,
+ result,
+ } => {
+ stages &= self.subgroup_stages;
+ if !self.capabilities.contains(super::Capabilities::SUBGROUP) {
+ return Err(FunctionError::MissingCapability(
+ super::Capabilities::SUBGROUP,
+ )
+ .with_span_static(span, "missing capability for this operation"));
+ }
+ let operation = op.required_operations();
+ if !self.subgroup_operations.contains(operation) {
+ return Err(FunctionError::InvalidSubgroup(
+ SubgroupError::UnsupportedOperation(operation),
+ )
+ .with_span_static(span, "support for this operation is not present"));
+ }
+ self.validate_subgroup_operation(op, collective_op, argument, result, context)?;
+ }
+ S::SubgroupGather {
+ ref mode,
+ argument,
+ result,
+ } => {
+ stages &= self.subgroup_stages;
+ if !self.capabilities.contains(super::Capabilities::SUBGROUP) {
+ return Err(FunctionError::MissingCapability(
+ super::Capabilities::SUBGROUP,
+ )
+ .with_span_static(span, "missing capability for this operation"));
+ }
+ let operation = mode.required_operations();
+ if !self.subgroup_operations.contains(operation) {
+ return Err(FunctionError::InvalidSubgroup(
+ SubgroupError::UnsupportedOperation(operation),
+ )
+ .with_span_static(span, "support for this operation is not present"));
+ }
+ self.validate_subgroup_gather(mode, argument, result, context)?;
+ }
}
}
Ok(BlockInfo { stages, finished })
@@ -927,7 +1167,7 @@ impl super::Validator {
var: &crate::LocalVariable,
gctx: crate::proc::GlobalCtx,
fun_info: &FunctionInfo,
- expression_constness: &crate::proc::ExpressionConstnessTracker,
+ local_expr_kind: &crate::proc::ExpressionKindTracker,
) -> Result<(), LocalVariableError> {
log::debug!("var {:?}", var);
let type_info = self
@@ -945,8 +1185,8 @@ impl super::Validator {
return Err(LocalVariableError::InitializerType);
}
- if !expression_constness.is_const(init) {
- return Err(LocalVariableError::NonConstInitializer);
+ if !local_expr_kind.is_const_or_override(init) {
+ return Err(LocalVariableError::NonConstOrOverrideInitializer);
}
}
@@ -959,14 +1199,14 @@ impl super::Validator {
module: &crate::Module,
mod_info: &ModuleInfo,
entry_point: bool,
+ global_expr_kind: &crate::proc::ExpressionKindTracker,
) -> Result<FunctionInfo, WithSpan<FunctionError>> {
let mut info = mod_info.process_function(fun, module, self.flags, self.capabilities)?;
- let expression_constness =
- crate::proc::ExpressionConstnessTracker::from_arena(&fun.expressions);
+ let local_expr_kind = crate::proc::ExpressionKindTracker::from_arena(&fun.expressions);
for (var_handle, var) in fun.local_variables.iter() {
- self.validate_local_var(var, module.to_ctx(), &info, &expression_constness)
+ self.validate_local_var(var, module.to_ctx(), &info, &local_expr_kind)
.map_err(|source| {
FunctionError::LocalVariable {
handle: var_handle,
@@ -1032,7 +1272,15 @@ impl super::Validator {
self.valid_expression_set.insert(handle.index());
}
if self.flags.contains(super::ValidationFlags::EXPRESSIONS) {
- match self.validate_expression(handle, expr, fun, module, &info, mod_info) {
+ match self.validate_expression(
+ handle,
+ expr,
+ fun,
+ module,
+ &info,
+ mod_info,
+ global_expr_kind,
+ ) {
Ok(stages) => info.available_stages &= stages,
Err(source) => {
return Err(FunctionError::Expression { handle, source }
diff --git a/third_party/rust/naga/src/valid/handles.rs b/third_party/rust/naga/src/valid/handles.rs
index e482f293bb..8f78204055 100644
--- a/third_party/rust/naga/src/valid/handles.rs
+++ b/third_party/rust/naga/src/valid/handles.rs
@@ -31,12 +31,13 @@ impl super::Validator {
pub(super) fn validate_module_handles(module: &crate::Module) -> Result<(), ValidationError> {
let &crate::Module {
ref constants,
+ ref overrides,
ref entry_points,
ref functions,
ref global_variables,
ref types,
ref special_types,
- ref const_expressions,
+ ref global_expressions,
} = module;
// NOTE: Types being first is important. All other forms of validation depend on this.
@@ -67,23 +68,31 @@ impl super::Validator {
}
}
- for handle_and_expr in const_expressions.iter() {
- Self::validate_const_expression_handles(handle_and_expr, constants, types)?;
+ for handle_and_expr in global_expressions.iter() {
+ Self::validate_const_expression_handles(handle_and_expr, constants, overrides, types)?;
}
let validate_type = |handle| Self::validate_type_handle(handle, types);
let validate_const_expr =
- |handle| Self::validate_expression_handle(handle, const_expressions);
+ |handle| Self::validate_expression_handle(handle, global_expressions);
for (_handle, constant) in constants.iter() {
- let &crate::Constant {
+ let &crate::Constant { name: _, ty, init } = constant;
+ validate_type(ty)?;
+ validate_const_expr(init)?;
+ }
+
+ for (_handle, override_) in overrides.iter() {
+ let &crate::Override {
name: _,
- r#override: _,
+ id: _,
ty,
init,
- } = constant;
+ } = override_;
validate_type(ty)?;
- validate_const_expr(init)?;
+ if let Some(init_expr) = init {
+ validate_const_expr(init_expr)?;
+ }
}
for (_handle, global_variable) in global_variables.iter() {
@@ -140,7 +149,8 @@ impl super::Validator {
Self::validate_expression_handles(
handle_and_expr,
constants,
- const_expressions,
+ overrides,
+ global_expressions,
types,
local_variables,
global_variables,
@@ -186,6 +196,13 @@ impl super::Validator {
handle.check_valid_for(constants).map(|_| ())
}
+ fn validate_override_handle(
+ handle: Handle<crate::Override>,
+ overrides: &Arena<crate::Override>,
+ ) -> Result<(), InvalidHandleError> {
+ handle.check_valid_for(overrides).map(|_| ())
+ }
+
fn validate_expression_handle(
handle: Handle<crate::Expression>,
expressions: &Arena<crate::Expression>,
@@ -203,9 +220,11 @@ impl super::Validator {
fn validate_const_expression_handles(
(handle, expression): (Handle<crate::Expression>, &crate::Expression),
constants: &Arena<crate::Constant>,
+ overrides: &Arena<crate::Override>,
types: &UniqueArena<crate::Type>,
) -> Result<(), InvalidHandleError> {
let validate_constant = |handle| Self::validate_constant_handle(handle, constants);
+ let validate_override = |handle| Self::validate_override_handle(handle, overrides);
let validate_type = |handle| Self::validate_type_handle(handle, types);
match *expression {
@@ -214,6 +233,12 @@ impl super::Validator {
validate_constant(constant)?;
handle.check_dep(constants[constant].init)?;
}
+ crate::Expression::Override(override_) => {
+ validate_override(override_)?;
+ if let Some(init) = overrides[override_].init {
+ handle.check_dep(init)?;
+ }
+ }
crate::Expression::ZeroValue(ty) => {
validate_type(ty)?;
}
@@ -230,7 +255,8 @@ impl super::Validator {
fn validate_expression_handles(
(handle, expression): (Handle<crate::Expression>, &crate::Expression),
constants: &Arena<crate::Constant>,
- const_expressions: &Arena<crate::Expression>,
+ overrides: &Arena<crate::Override>,
+ global_expressions: &Arena<crate::Expression>,
types: &UniqueArena<crate::Type>,
local_variables: &Arena<crate::LocalVariable>,
global_variables: &Arena<crate::GlobalVariable>,
@@ -239,8 +265,9 @@ impl super::Validator {
current_function: Option<Handle<crate::Function>>,
) -> Result<(), InvalidHandleError> {
let validate_constant = |handle| Self::validate_constant_handle(handle, constants);
+ let validate_override = |handle| Self::validate_override_handle(handle, overrides);
let validate_const_expr =
- |handle| Self::validate_expression_handle(handle, const_expressions);
+ |handle| Self::validate_expression_handle(handle, global_expressions);
let validate_type = |handle| Self::validate_type_handle(handle, types);
match *expression {
@@ -260,6 +287,9 @@ impl super::Validator {
crate::Expression::Constant(constant) => {
validate_constant(constant)?;
}
+ crate::Expression::Override(override_) => {
+ validate_override(override_)?;
+ }
crate::Expression::ZeroValue(ty) => {
validate_type(ty)?;
}
@@ -390,6 +420,8 @@ impl super::Validator {
}
crate::Expression::AtomicResult { .. }
| crate::Expression::RayQueryProceedResult
+ | crate::Expression::SubgroupBallotResult
+ | crate::Expression::SubgroupOperationResult { .. }
| crate::Expression::WorkGroupUniformLoadResult { .. } => (),
crate::Expression::ArrayLength(array) => {
handle.check_dep(array)?;
@@ -535,6 +567,38 @@ impl super::Validator {
}
Ok(())
}
+ crate::Statement::SubgroupBallot { result, predicate } => {
+ validate_expr_opt(predicate)?;
+ validate_expr(result)?;
+ Ok(())
+ }
+ crate::Statement::SubgroupCollectiveOperation {
+ op: _,
+ collective_op: _,
+ argument,
+ result,
+ } => {
+ validate_expr(argument)?;
+ validate_expr(result)?;
+ Ok(())
+ }
+ crate::Statement::SubgroupGather {
+ mode,
+ argument,
+ result,
+ } => {
+ validate_expr(argument)?;
+ match mode {
+ crate::GatherMode::BroadcastFirst => {}
+ crate::GatherMode::Broadcast(index)
+ | crate::GatherMode::Shuffle(index)
+ | crate::GatherMode::ShuffleDown(index)
+ | crate::GatherMode::ShuffleUp(index)
+ | crate::GatherMode::ShuffleXor(index) => validate_expr(index)?,
+ }
+ validate_expr(result)?;
+ Ok(())
+ }
crate::Statement::Break
| crate::Statement::Continue
| crate::Statement::Kill
@@ -562,6 +626,7 @@ impl From<BadRangeError> for ValidationError {
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum InvalidHandleError {
#[error(transparent)]
BadHandle(#[from] BadHandle),
@@ -572,6 +637,7 @@ pub enum InvalidHandleError {
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
#[error(
"{subject:?} of kind {subject_kind:?} depends on {depends_on:?} of kind {depends_on_kind}, \
which has not been processed yet"
@@ -664,6 +730,7 @@ fn constant_deps() {
let mut const_exprs = Arena::new();
let mut fun_exprs = Arena::new();
let mut constants = Arena::new();
+ let overrides = Arena::new();
let i32_handle = types.insert(
Type {
@@ -679,7 +746,6 @@ fn constant_deps() {
let self_referential_const = constants.append(
Constant {
name: None,
- r#override: crate::Override::None,
ty: i32_handle,
init: fun_expr,
},
@@ -692,6 +758,7 @@ fn constant_deps() {
assert!(super::Validator::validate_const_expression_handles(
handle_and_expr,
&constants,
+ &overrides,
&types,
)
.is_err());
diff --git a/third_party/rust/naga/src/valid/interface.rs b/third_party/rust/naga/src/valid/interface.rs
index 84c8b09ddb..db890ddbac 100644
--- a/third_party/rust/naga/src/valid/interface.rs
+++ b/third_party/rust/naga/src/valid/interface.rs
@@ -10,6 +10,7 @@ use bit_set::BitSet;
const MAX_WORKGROUP_SIZE: u32 = 0x4000;
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum GlobalVariableError {
#[error("Usage isn't compatible with address space {0:?}")]
InvalidUsage(crate::AddressSpace),
@@ -30,6 +31,8 @@ pub enum GlobalVariableError {
Handle<crate::Type>,
#[source] Disalignment,
),
+ #[error("Initializer must be an override-expression")]
+ InitializerExprType,
#[error("Initializer doesn't match the variable type")]
InitializerType,
#[error("Initializer can't be used with address space {0:?}")]
@@ -39,6 +42,7 @@ pub enum GlobalVariableError {
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum VaryingError {
#[error("The type {0:?} does not match the varying")]
InvalidType(Handle<crate::Type>),
@@ -73,9 +77,12 @@ pub enum VaryingError {
location: u32,
attribute: &'static str,
},
+ #[error("Workgroup size is multi dimensional, @builtin(subgroup_id) and @builtin(subgroup_invocation_id) are not supported.")]
+ InvalidMultiDimensionalSubgroupBuiltIn,
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum EntryPointError {
#[error("Multiple conflicting entry points")]
Conflict,
@@ -135,6 +142,7 @@ struct VaryingContext<'a> {
impl VaryingContext<'_> {
fn validate_impl(
&mut self,
+ ep: &crate::EntryPoint,
ty: Handle<crate::Type>,
binding: &crate::Binding,
) -> Result<(), VaryingError> {
@@ -162,12 +170,24 @@ impl VaryingContext<'_> {
Bi::PrimitiveIndex => Capabilities::PRIMITIVE_INDEX,
Bi::ViewIndex => Capabilities::MULTIVIEW,
Bi::SampleIndex => Capabilities::MULTISAMPLED_SHADING,
+ Bi::NumSubgroups
+ | Bi::SubgroupId
+ | Bi::SubgroupSize
+ | Bi::SubgroupInvocationId => Capabilities::SUBGROUP,
_ => Capabilities::empty(),
};
if !self.capabilities.contains(required) {
return Err(VaryingError::UnsupportedCapability(required));
}
+ if matches!(
+ built_in,
+ crate::BuiltIn::SubgroupId | crate::BuiltIn::SubgroupInvocationId
+ ) && ep.workgroup_size[1..].iter().any(|&s| s > 1)
+ {
+ return Err(VaryingError::InvalidMultiDimensionalSubgroupBuiltIn);
+ }
+
let (visible, type_good) = match built_in {
Bi::BaseInstance | Bi::BaseVertex | Bi::InstanceIndex | Bi::VertexIndex => (
self.stage == St::Vertex && !self.output,
@@ -249,6 +269,17 @@ impl VaryingContext<'_> {
scalar: crate::Scalar::U32,
},
),
+ Bi::NumSubgroups | Bi::SubgroupId => (
+ self.stage == St::Compute && !self.output,
+ *ty_inner == Ti::Scalar(crate::Scalar::U32),
+ ),
+ Bi::SubgroupSize | Bi::SubgroupInvocationId => (
+ match self.stage {
+ St::Compute | St::Fragment => !self.output,
+ St::Vertex => false,
+ },
+ *ty_inner == Ti::Scalar(crate::Scalar::U32),
+ ),
};
if !visible {
@@ -349,13 +380,14 @@ impl VaryingContext<'_> {
fn validate(
&mut self,
+ ep: &crate::EntryPoint,
ty: Handle<crate::Type>,
binding: Option<&crate::Binding>,
) -> Result<(), WithSpan<VaryingError>> {
let span_context = self.types.get_span_context(ty);
match binding {
Some(binding) => self
- .validate_impl(ty, binding)
+ .validate_impl(ep, ty, binding)
.map_err(|e| e.with_span_context(span_context)),
None => {
match self.types[ty].inner {
@@ -372,7 +404,7 @@ impl VaryingContext<'_> {
}
}
Some(ref binding) => self
- .validate_impl(member.ty, binding)
+ .validate_impl(ep, member.ty, binding)
.map_err(|e| e.with_span_context(span_context))?,
}
}
@@ -395,6 +427,7 @@ impl super::Validator {
var: &crate::GlobalVariable,
gctx: crate::proc::GlobalCtx,
mod_info: &ModuleInfo,
+ global_expr_kind: &crate::proc::ExpressionKindTracker,
) -> Result<(), GlobalVariableError> {
use super::TypeFlags;
@@ -523,6 +556,10 @@ impl super::Validator {
}
}
+ if !global_expr_kind.is_const_or_override(init) {
+ return Err(GlobalVariableError::InitializerExprType);
+ }
+
let decl_ty = &gctx.types[var.ty].inner;
let init_ty = mod_info[init].inner_with(gctx.types);
if !decl_ty.equivalent(init_ty, gctx.types) {
@@ -538,6 +575,7 @@ impl super::Validator {
ep: &crate::EntryPoint,
module: &crate::Module,
mod_info: &ModuleInfo,
+ global_expr_kind: &crate::proc::ExpressionKindTracker,
) -> Result<FunctionInfo, WithSpan<EntryPointError>> {
if ep.early_depth_test.is_some() {
let required = Capabilities::EARLY_DEPTH_TEST;
@@ -566,7 +604,7 @@ impl super::Validator {
}
let mut info = self
- .validate_function(&ep.function, module, mod_info, true)
+ .validate_function(&ep.function, module, mod_info, true, global_expr_kind)
.map_err(WithSpan::into_other)?;
{
@@ -598,7 +636,7 @@ impl super::Validator {
capabilities: self.capabilities,
flags: self.flags,
};
- ctx.validate(fa.ty, fa.binding.as_ref())
+ ctx.validate(ep, fa.ty, fa.binding.as_ref())
.map_err_inner(|e| EntryPointError::Argument(index as u32, e).with_span())?;
}
@@ -616,7 +654,7 @@ impl super::Validator {
capabilities: self.capabilities,
flags: self.flags,
};
- ctx.validate(fr.ty, fr.binding.as_ref())
+ ctx.validate(ep, fr.ty, fr.binding.as_ref())
.map_err_inner(|e| EntryPointError::Result(e).with_span())?;
if ctx.second_blend_source {
// Only the first location may be used when dual source blending
diff --git a/third_party/rust/naga/src/valid/mod.rs b/third_party/rust/naga/src/valid/mod.rs
index 5459434f33..a0057f39ac 100644
--- a/third_party/rust/naga/src/valid/mod.rs
+++ b/third_party/rust/naga/src/valid/mod.rs
@@ -12,7 +12,7 @@ mod r#type;
use crate::{
arena::Handle,
- proc::{LayoutError, Layouter, TypeResolution},
+ proc::{ExpressionKindTracker, LayoutError, Layouter, TypeResolution},
FastHashSet,
};
use bit_set::BitSet;
@@ -77,7 +77,7 @@ bitflags::bitflags! {
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct Capabilities: u16 {
+ pub struct Capabilities: u32 {
/// Support for [`AddressSpace:PushConstant`].
const PUSH_CONSTANT = 0x1;
/// Float values with width = 8.
@@ -110,6 +110,10 @@ bitflags::bitflags! {
const CUBE_ARRAY_TEXTURES = 0x4000;
/// Support for 64-bit signed and unsigned integers.
const SHADER_INT64 = 0x8000;
+ /// Support for subgroup operations.
+ const SUBGROUP = 0x10000;
+ /// Support for subgroup barriers.
+ const SUBGROUP_BARRIER = 0x20000;
}
}
@@ -120,6 +124,57 @@ impl Default for Capabilities {
}
bitflags::bitflags! {
+ /// Supported subgroup operations
+ #[cfg_attr(feature = "serialize", derive(serde::Serialize))]
+ #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
+ #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
+ pub struct SubgroupOperationSet: u8 {
+ /// Elect, Barrier
+ const BASIC = 1 << 0;
+ /// Any, All
+ const VOTE = 1 << 1;
+ /// reductions, scans
+ const ARITHMETIC = 1 << 2;
+ /// ballot, broadcast
+ const BALLOT = 1 << 3;
+ /// shuffle, shuffle xor
+ const SHUFFLE = 1 << 4;
+ /// shuffle up, down
+ const SHUFFLE_RELATIVE = 1 << 5;
+ // We don't support these operations yet
+ // /// Clustered
+ // const CLUSTERED = 1 << 6;
+ // /// Quad supported
+ // const QUAD_FRAGMENT_COMPUTE = 1 << 7;
+ // /// Quad supported in all stages
+ // const QUAD_ALL_STAGES = 1 << 8;
+ }
+}
+
+impl super::SubgroupOperation {
+ const fn required_operations(&self) -> SubgroupOperationSet {
+ use SubgroupOperationSet as S;
+ match *self {
+ Self::All | Self::Any => S::VOTE,
+ Self::Add | Self::Mul | Self::Min | Self::Max | Self::And | Self::Or | Self::Xor => {
+ S::ARITHMETIC
+ }
+ }
+ }
+}
+
+impl super::GatherMode {
+ const fn required_operations(&self) -> SubgroupOperationSet {
+ use SubgroupOperationSet as S;
+ match *self {
+ Self::BroadcastFirst | Self::Broadcast(_) => S::BALLOT,
+ Self::Shuffle(_) | Self::ShuffleXor(_) => S::SHUFFLE,
+ Self::ShuffleUp(_) | Self::ShuffleDown(_) => S::SHUFFLE_RELATIVE,
+ }
+ }
+}
+
+bitflags::bitflags! {
/// Validation flags.
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
@@ -131,7 +186,7 @@ bitflags::bitflags! {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct ModuleInfo {
@@ -166,6 +221,8 @@ impl ops::Index<Handle<crate::Expression>> for ModuleInfo {
pub struct Validator {
flags: ValidationFlags,
capabilities: Capabilities,
+ subgroup_stages: ShaderStages,
+ subgroup_operations: SubgroupOperationSet,
types: Vec<r#type::TypeInfo>,
layouter: Layouter,
location_mask: BitSet,
@@ -174,10 +231,15 @@ pub struct Validator {
switch_values: FastHashSet<crate::SwitchValue>,
valid_expression_list: Vec<Handle<crate::Expression>>,
valid_expression_set: BitSet,
+ override_ids: FastHashSet<u16>,
+ allow_overrides: bool,
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum ConstantError {
+ #[error("Initializer must be a const-expression")]
+ InitializerExprType,
#[error("The type doesn't match the constant")]
InvalidType,
#[error("The type is not constructible")]
@@ -185,6 +247,26 @@ pub enum ConstantError {
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
+pub enum OverrideError {
+ #[error("Override name and ID are missing")]
+ MissingNameAndID,
+ #[error("Override ID must be unique")]
+ DuplicateID,
+ #[error("Initializer must be a const-expression or override-expression")]
+ InitializerExprType,
+ #[error("The type doesn't match the override")]
+ InvalidType,
+ #[error("The type is not constructible")]
+ NonConstructibleType,
+ #[error("The type is not a scalar")]
+ TypeNotScalar,
+ #[error("Override declarations are not allowed")]
+ NotAllowed,
+}
+
+#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum ValidationError {
#[error(transparent)]
InvalidHandle(#[from] InvalidHandleError),
@@ -207,6 +289,12 @@ pub enum ValidationError {
name: String,
source: ConstantError,
},
+ #[error("Override {handle:?} '{name}' is invalid")]
+ Override {
+ handle: Handle<crate::Override>,
+ name: String,
+ source: OverrideError,
+ },
#[error("Global variable {handle:?} '{name}' is invalid")]
GlobalVariable {
handle: Handle<crate::GlobalVariable>,
@@ -286,6 +374,8 @@ impl Validator {
Validator {
flags,
capabilities,
+ subgroup_stages: ShaderStages::empty(),
+ subgroup_operations: SubgroupOperationSet::empty(),
types: Vec::new(),
layouter: Layouter::default(),
location_mask: BitSet::new(),
@@ -293,9 +383,21 @@ impl Validator {
switch_values: FastHashSet::default(),
valid_expression_list: Vec::new(),
valid_expression_set: BitSet::new(),
+ override_ids: FastHashSet::default(),
+ allow_overrides: true,
}
}
+ pub fn subgroup_stages(&mut self, stages: ShaderStages) -> &mut Self {
+ self.subgroup_stages = stages;
+ self
+ }
+
+ pub fn subgroup_operations(&mut self, operations: SubgroupOperationSet) -> &mut Self {
+ self.subgroup_operations = operations;
+ self
+ }
+
/// Reset the validator internals
pub fn reset(&mut self) {
self.types.clear();
@@ -305,6 +407,7 @@ impl Validator {
self.switch_values.clear();
self.valid_expression_list.clear();
self.valid_expression_set.clear();
+ self.override_ids.clear();
}
fn validate_constant(
@@ -312,6 +415,7 @@ impl Validator {
handle: Handle<crate::Constant>,
gctx: crate::proc::GlobalCtx,
mod_info: &ModuleInfo,
+ global_expr_kind: &ExpressionKindTracker,
) -> Result<(), ConstantError> {
let con = &gctx.constants[handle];
@@ -320,6 +424,10 @@ impl Validator {
return Err(ConstantError::NonConstructibleType);
}
+ if !global_expr_kind.is_const(con.init) {
+ return Err(ConstantError::InitializerExprType);
+ }
+
let decl_ty = &gctx.types[con.ty].inner;
let init_ty = mod_info[con.init].inner_with(gctx.types);
if !decl_ty.equivalent(init_ty, gctx.types) {
@@ -329,11 +437,80 @@ impl Validator {
Ok(())
}
+ fn validate_override(
+ &mut self,
+ handle: Handle<crate::Override>,
+ gctx: crate::proc::GlobalCtx,
+ mod_info: &ModuleInfo,
+ ) -> Result<(), OverrideError> {
+ if !self.allow_overrides {
+ return Err(OverrideError::NotAllowed);
+ }
+
+ let o = &gctx.overrides[handle];
+
+ if o.name.is_none() && o.id.is_none() {
+ return Err(OverrideError::MissingNameAndID);
+ }
+
+ if let Some(id) = o.id {
+ if !self.override_ids.insert(id) {
+ return Err(OverrideError::DuplicateID);
+ }
+ }
+
+ let type_info = &self.types[o.ty.index()];
+ if !type_info.flags.contains(TypeFlags::CONSTRUCTIBLE) {
+ return Err(OverrideError::NonConstructibleType);
+ }
+
+ let decl_ty = &gctx.types[o.ty].inner;
+ match decl_ty {
+ &crate::TypeInner::Scalar(scalar) => match scalar {
+ crate::Scalar::BOOL
+ | crate::Scalar::I32
+ | crate::Scalar::U32
+ | crate::Scalar::F32
+ | crate::Scalar::F64 => {}
+ _ => return Err(OverrideError::TypeNotScalar),
+ },
+ _ => return Err(OverrideError::TypeNotScalar),
+ }
+
+ if let Some(init) = o.init {
+ let init_ty = mod_info[init].inner_with(gctx.types);
+ if !decl_ty.equivalent(init_ty, gctx.types) {
+ return Err(OverrideError::InvalidType);
+ }
+ }
+
+ Ok(())
+ }
+
/// Check the given module to be valid.
pub fn validate(
&mut self,
module: &crate::Module,
) -> Result<ModuleInfo, WithSpan<ValidationError>> {
+ self.allow_overrides = true;
+ self.validate_impl(module)
+ }
+
+ /// Check the given module to be valid.
+ ///
+ /// With the additional restriction that overrides are not present.
+ pub fn validate_no_overrides(
+ &mut self,
+ module: &crate::Module,
+ ) -> Result<ModuleInfo, WithSpan<ValidationError>> {
+ self.allow_overrides = false;
+ self.validate_impl(module)
+ }
+
+ fn validate_impl(
+ &mut self,
+ module: &crate::Module,
+ ) -> Result<ModuleInfo, WithSpan<ValidationError>> {
self.reset();
self.reset_types(module.types.len());
@@ -354,7 +531,7 @@ impl Validator {
type_flags: Vec::with_capacity(module.types.len()),
functions: Vec::with_capacity(module.functions.len()),
entry_points: Vec::with_capacity(module.entry_points.len()),
- const_expression_types: vec![placeholder; module.const_expressions.len()]
+ const_expression_types: vec![placeholder; module.global_expressions.len()]
.into_boxed_slice(),
};
@@ -376,27 +553,34 @@ impl Validator {
{
let t = crate::Arena::new();
let resolve_context = crate::proc::ResolveContext::with_locals(module, &t, &[]);
- for (handle, _) in module.const_expressions.iter() {
+ for (handle, _) in module.global_expressions.iter() {
mod_info
.process_const_expression(handle, &resolve_context, module.to_ctx())
.map_err(|source| {
ValidationError::ConstExpression { handle, source }
- .with_span_handle(handle, &module.const_expressions)
+ .with_span_handle(handle, &module.global_expressions)
})?
}
}
+ let global_expr_kind = ExpressionKindTracker::from_arena(&module.global_expressions);
+
if self.flags.contains(ValidationFlags::CONSTANTS) {
- for (handle, _) in module.const_expressions.iter() {
- self.validate_const_expression(handle, module.to_ctx(), &mod_info)
- .map_err(|source| {
- ValidationError::ConstExpression { handle, source }
- .with_span_handle(handle, &module.const_expressions)
- })?
+ for (handle, _) in module.global_expressions.iter() {
+ self.validate_const_expression(
+ handle,
+ module.to_ctx(),
+ &mod_info,
+ &global_expr_kind,
+ )
+ .map_err(|source| {
+ ValidationError::ConstExpression { handle, source }
+ .with_span_handle(handle, &module.global_expressions)
+ })?
}
for (handle, constant) in module.constants.iter() {
- self.validate_constant(handle, module.to_ctx(), &mod_info)
+ self.validate_constant(handle, module.to_ctx(), &mod_info, &global_expr_kind)
.map_err(|source| {
ValidationError::Constant {
handle,
@@ -406,10 +590,22 @@ impl Validator {
.with_span_handle(handle, &module.constants)
})?
}
+
+ for (handle, override_) in module.overrides.iter() {
+ self.validate_override(handle, module.to_ctx(), &mod_info)
+ .map_err(|source| {
+ ValidationError::Override {
+ handle,
+ name: override_.name.clone().unwrap_or_default(),
+ source,
+ }
+ .with_span_handle(handle, &module.overrides)
+ })?
+ }
}
for (var_handle, var) in module.global_variables.iter() {
- self.validate_global_var(var, module.to_ctx(), &mod_info)
+ self.validate_global_var(var, module.to_ctx(), &mod_info, &global_expr_kind)
.map_err(|source| {
ValidationError::GlobalVariable {
handle: var_handle,
@@ -421,7 +617,7 @@ impl Validator {
}
for (handle, fun) in module.functions.iter() {
- match self.validate_function(fun, module, &mod_info, false) {
+ match self.validate_function(fun, module, &mod_info, false, &global_expr_kind) {
Ok(info) => mod_info.functions.push(info),
Err(error) => {
return Err(error.and_then(|source| {
@@ -447,7 +643,7 @@ impl Validator {
.with_span()); // TODO: keep some EP span information?
}
- match self.validate_entry_point(ep, module, &mod_info) {
+ match self.validate_entry_point(ep, module, &mod_info, &global_expr_kind) {
Ok(info) => mod_info.entry_points.push(info),
Err(error) => {
return Err(error.and_then(|source| {
diff --git a/third_party/rust/naga/src/valid/type.rs b/third_party/rust/naga/src/valid/type.rs
index b8eb618ed4..f5b9856074 100644
--- a/third_party/rust/naga/src/valid/type.rs
+++ b/third_party/rust/naga/src/valid/type.rs
@@ -63,6 +63,7 @@ bitflags::bitflags! {
}
#[derive(Clone, Copy, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum Disalignment {
#[error("The array stride {stride} is not a multiple of the required alignment {alignment}")]
ArrayStride { stride: u32, alignment: Alignment },
@@ -87,6 +88,7 @@ pub enum Disalignment {
}
#[derive(Clone, Debug, thiserror::Error)]
+#[cfg_attr(test, derive(PartialEq))]
pub enum TypeError {
#[error("Capability {0:?} is required")]
MissingCapability(Capabilities),
@@ -326,7 +328,6 @@ impl super::Validator {
TypeFlags::DATA
| TypeFlags::SIZED
| TypeFlags::COPY
- | TypeFlags::HOST_SHAREABLE
| TypeFlags::ARGUMENT
| TypeFlags::CONSTRUCTIBLE
| shareable,
diff --git a/third_party/rust/neqo-common/.cargo-checksum.json b/third_party/rust/neqo-common/.cargo-checksum.json
index 64d5739014..d94920d26f 100644
--- a/third_party/rust/neqo-common/.cargo-checksum.json
+++ b/third_party/rust/neqo-common/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"28a963b1a9067fef18e945a938a6ae5ea14a3a29a937f3be2ec4c0e3ae33854f","benches/timer.rs":"52d35abe1e06b92e913f43d95295b4eded0f19809677a7a63857fe92dad2c6fa","build.rs":"306b2f909a25ae38daf5404a4e128d2a94e8975b70870864c2a71cafec9717c7","src/codec.rs":"fd239f75d374db6ff744211344c82bcd19ecf753e07410e1fe37732bbb81dfe9","src/datagram.rs":"691ad94a3618d6bf5202a7911419b5e75e318d09c8cc57a9a542a864dcc764ec","src/event.rs":"106ca6c4afb107fa49a1bc72f5eb4ae95f4baa1ba19736aa38c8ba973774c160","src/header.rs":"467b947f78bfe354d8bb51e8df0c2be69e75a45e2be688d81f0d268aa77c89ef","src/hrtime.rs":"112dc758e65301b8a7a508b125d3d61063180d432bffaec566a050d4f907ab18","src/incrdecoder.rs":"577c32b9ace51f2daaf940be6d0c391c4f55cd42ef6848c68c1ffc970d8c57b5","src/lib.rs":"c917282134f43d0ddfbd67bbceea9f615a7db8a23608f809b4746808c08a9b3f","src/log.rs":"6ed99e15707c4256ae793011ed2f4b33aa81fed70205aaf5f8d3cd11ad451cf0","src/qlog.rs":"9b081f32bf158fd340300693acc97fe0554b617ae664eba86e4d3572e2b1e16e","src/timer.rs":"f6da86baf3b5d91c1230d5296ef886fb7233cdefa8c8e2b4197fcf82425a54fa","src/tos.rs":"baec87b4f8a6253b88cd257730bd1e3147c046ef993288b08235d54a24f88fbe","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"3459350f69e0272710e4d5d861f9646225f9c187698e721f01d38f2d9b1b3394","benches/timer.rs":"52d35abe1e06b92e913f43d95295b4eded0f19809677a7a63857fe92dad2c6fa","build.rs":"306b2f909a25ae38daf5404a4e128d2a94e8975b70870864c2a71cafec9717c7","src/codec.rs":"fd239f75d374db6ff744211344c82bcd19ecf753e07410e1fe37732bbb81dfe9","src/datagram.rs":"19882ecf3d3b03d6e87a1b8f871429f07f5b0db6d891c9362c91306a0cee33c7","src/event.rs":"106ca6c4afb107fa49a1bc72f5eb4ae95f4baa1ba19736aa38c8ba973774c160","src/fuzz.rs":"1ca74a34bdc97fedecf8a63c4a13cc487d1b2212398fb76f67792c822002138d","src/header.rs":"467b947f78bfe354d8bb51e8df0c2be69e75a45e2be688d81f0d268aa77c89ef","src/hrtime.rs":"112dc758e65301b8a7a508b125d3d61063180d432bffaec566a050d4f907ab18","src/incrdecoder.rs":"577c32b9ace51f2daaf940be6d0c391c4f55cd42ef6848c68c1ffc970d8c57b5","src/lib.rs":"bc585a11daf56f9680fc5a652c5ca79e00eb0f3fa34a45ecd1b6c60200b95cf1","src/log.rs":"6ed99e15707c4256ae793011ed2f4b33aa81fed70205aaf5f8d3cd11ad451cf0","src/qlog.rs":"9b081f32bf158fd340300693acc97fe0554b617ae664eba86e4d3572e2b1e16e","src/timer.rs":"f6da86baf3b5d91c1230d5296ef886fb7233cdefa8c8e2b4197fcf82425a54fa","src/tos.rs":"087cd9b12a2510f05605e755d85c07179817c22670fe1b5d6db987357f77b38e","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/neqo-common/Cargo.toml b/third_party/rust/neqo-common/Cargo.toml
index 90b254c888..0659508aeb 100644
--- a/third_party/rust/neqo-common/Cargo.toml
+++ b/third_party/rust/neqo-common/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.74.0"
+rust-version = "1.76.0"
name = "neqo-common"
-version = "0.7.5"
+version = "0.7.7"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
homepage = "https://github.com/mozilla/neqo/"
@@ -35,12 +35,18 @@ default-features = false
version = "0.10"
default-features = false
+[dependencies.hex]
+version = "0.4"
+features = ["alloc"]
+optional = true
+default-features = false
+
[dependencies.log]
version = "0.4"
default-features = false
[dependencies.qlog]
-version = "0.12"
+version = "0.13"
default-features = false
[dependencies.time]
@@ -57,6 +63,7 @@ default-features = false
path = "../test-fixture"
[features]
+build-fuzzing-corpus = ["hex"]
ci = []
[target."cfg(windows)".dependencies.winapi]
diff --git a/third_party/rust/neqo-common/src/datagram.rs b/third_party/rust/neqo-common/src/datagram.rs
index cc2cb7d113..2f2bb53766 100644
--- a/third_party/rust/neqo-common/src/datagram.rs
+++ b/third_party/rust/neqo-common/src/datagram.rs
@@ -95,6 +95,6 @@ fn fmt_datagram() {
let d = datagram([0; 1].to_vec());
assert_eq!(
&format!("{d:?}"),
- "Datagram IpTos(Cs0, NotEct) TTL Some(128) [fe80::1]:443->[fe80::1]:443: [1]: 00"
+ "Datagram IpTos(Cs0, Ect0) TTL Some(128) [fe80::1]:443->[fe80::1]:443: [1]: 00"
);
}
diff --git a/third_party/rust/neqo-common/src/fuzz.rs b/third_party/rust/neqo-common/src/fuzz.rs
new file mode 100644
index 0000000000..d0a35a49ae
--- /dev/null
+++ b/third_party/rust/neqo-common/src/fuzz.rs
@@ -0,0 +1,43 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+ collections::hash_map::DefaultHasher,
+ fs::File,
+ hash::{Hash, Hasher},
+ io::Write,
+ path::Path,
+};
+
+/// Write a data item `data` for the fuzzing target `target` to the fuzzing corpus. The caller needs
+/// to make sure that `target` is the correct fuzzing target name for the data written.
+///
+/// # Panics
+///
+/// Panics if the corpus directory does not exist or if the corpus item cannot be written.
+pub fn write_item_to_fuzzing_corpus(target: &str, data: &[u8]) {
+ // This bakes in the assumption that we're executing in the root of the neqo workspace.
+ // Unfortunately, `cargo fuzz` doesn't provide a way to learn the location of the corpus
+ // directory.
+ let corpus = Path::new("../fuzz/corpus").join(target);
+ if !corpus.exists() {
+ std::fs::create_dir_all(&corpus).expect("failed to create corpus directory");
+ }
+
+ // Hash the data to get a unique name for the corpus item.
+ let mut hasher = DefaultHasher::new();
+ data.hash(&mut hasher);
+ let item_name = hex::encode(hasher.finish().to_be_bytes());
+ let item_path = corpus.join(item_name);
+ if item_path.exists() {
+ // Don't overwrite existing corpus items.
+ return;
+ }
+
+ // Write the data to the corpus item.
+ let mut file = File::create(item_path).expect("failed to create corpus item");
+ Write::write_all(&mut file, data).expect("failed to write to corpus item");
+}
diff --git a/third_party/rust/neqo-common/src/lib.rs b/third_party/rust/neqo-common/src/lib.rs
index e988c6071d..3a72425e44 100644
--- a/third_party/rust/neqo-common/src/lib.rs
+++ b/third_party/rust/neqo-common/src/lib.rs
@@ -9,6 +9,8 @@
mod codec;
mod datagram;
pub mod event;
+#[cfg(feature = "build-fuzzing-corpus")]
+mod fuzz;
pub mod header;
pub mod hrtime;
mod incrdecoder;
@@ -21,6 +23,8 @@ use std::fmt::Write;
use enum_map::Enum;
+#[cfg(feature = "build-fuzzing-corpus")]
+pub use self::fuzz::write_item_to_fuzzing_corpus;
pub use self::{
codec::{Decoder, Encoder},
datagram::Datagram,
diff --git a/third_party/rust/neqo-common/src/tos.rs b/third_party/rust/neqo-common/src/tos.rs
index 533c5447e2..c7e5228dee 100644
--- a/third_party/rust/neqo-common/src/tos.rs
+++ b/third_party/rust/neqo-common/src/tos.rs
@@ -52,6 +52,16 @@ impl From<IpTos> for IpTosEcn {
}
}
+impl IpTosEcn {
+ #[must_use]
+ pub fn is_ecn_marked(&self) -> bool {
+ match self {
+ IpTosEcn::Ect0 | IpTosEcn::Ect1 | IpTosEcn::Ce => true,
+ IpTosEcn::NotEct => false,
+ }
+ }
+}
+
/// Diffserv Codepoints, mapped to the upper six bits of the TOS field.
/// <https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml>
#[derive(Copy, Clone, PartialEq, Eq, Enum, Default, Debug)]
@@ -228,6 +238,11 @@ impl IpTos {
pub fn set_dscp(&mut self, dscp: IpTosDscp) {
self.0 = u8::from(IpTosEcn::from(*self)) | u8::from(dscp);
}
+
+ #[must_use]
+ pub fn is_ecn_marked(&self) -> bool {
+ IpTosEcn::from(*self).is_ecn_marked()
+ }
}
#[cfg(test)]
@@ -346,4 +361,16 @@ mod tests {
iptos.set_dscp(IpTosDscp::Le);
assert_eq!(u8::from(iptos), 0b0000_0101);
}
+
+ #[test]
+ fn iptos_is_ecn_marked() {
+ let iptos: IpTos = (IpTosDscp::Af41, IpTosEcn::Ce).into();
+ assert!(iptos.is_ecn_marked());
+ }
+
+ #[test]
+ fn iptosecn_is_ecn_marked() {
+ assert!(IpTosEcn::Ce.is_ecn_marked());
+ assert!(!IpTosEcn::NotEct.is_ecn_marked());
+ }
}
diff --git a/third_party/rust/neqo-crypto/.cargo-checksum.json b/third_party/rust/neqo-crypto/.cargo-checksum.json
index c3e603bd5a..1b9e9cee87 100644
--- a/third_party/rust/neqo-crypto/.cargo-checksum.json
+++ b/third_party/rust/neqo-crypto/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"e0ddb5aa433c742c87b94760fc995afb8091b8fa1360bf1ce66ed59d4e34a44d","bindings/bindings.toml":"29ec7a8ef3d5f1e4a632003e2d36c270e1caf12fd3fcf108a22d1893b90a41a6","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"cbf6a7d912314784c8c124cf7319c910a786d0e263f466843edd3f43826f036c","min_version.txt":"7e98f86c69cddb4f65cf96a6de1f4297e3ce224a4c4628609e29042b6c4dcfb9","src/aead.rs":"fc42bc20b84d2e5ccfd56271ae2d2db082e55586ea2926470c102da177f22296","src/aead_null.rs":"664f80bbb56d0abd3794b99cc927fd5f678ddb4ce95456001413ec18a6c6a6a9","src/agent.rs":"b12004faee4a136c10e8168848d397443b5927e9497edb62c72e6db3eb1c10a0","src/agentio.rs":"c4cb1b3cd92ef53eb0b4fb0b34a597068d82d78ba470dae5821670a0f06c9cda","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8942cb3ce25a61f92b6ffc30fb286052ed6f56eeda3be12fd46ea76ceba6c1cf","src/constants.rs":"f22bf16bd8cb539862cb1e47138dbba79e93fe738f4b907e465891326f98883c","src/ech.rs":"9d322fcc01c0886f1dfe9bb6273cb9f88a746452ac9a802761b1816a05930c1f","src/err.rs":"ae979f334604aba89640c4491262641910033f0bd790d58671f649f5039b291c","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"ef32f20e30a9bd7f094199536d19c87c4231b7fbbe4a9c54c70e84ca9c6575be","src/hp.rs":"644f1bed67f1c6189a67c8d02ab3358aaa7f63af4b913dd7395becbc01a84291","src/lib.rs":"6b2d0eb2c55f6351d673d3a3e5fc5adac8d1030c67dae9af4c79552de0f57455","src/min_version.rs":"89b7ef6f9d2301db4f689f4d963b58375d577f705b92003a804048441e00cfd1","src/p11.rs":"e8c366def0df470101f3d120dcc4391f74f921fe59e2f3db2a56832e2852b855","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"96b7af8eff9e14313e79303092018b12e8834f780c96b8e247c497fdc680c696","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"b7cc1c896c7661c37461fc3a8bcbfdf2589433b907fa5f968ae4f6907704b441","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"c71a01ff8aa2c0e97fb16ad620df4ed6b7cc1819ff93f46634e2f1c9551627ec","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"824735f88e487a3748200844e9481e81a72163ad74d82faa9aa16594d9b9bb25","tests/ext.rs":"1b047d23d9b224ad06eb65d8f3a7b351e263774e404c79bbcbe8f43790e29c18","tests/handshake.rs":"e892a2839b31414be16e96cdf3b1a65978716094700c1a4989229f7edbf578a0","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"b24fec53771c169be788772532d2617a5349196cf87d6444dc74214f7c73e92c","tests/init.rs":"616313cb38eac44b8c71a1d23a52a7d7b4c7c07d4c20dc9ea6600c3317f92613","tests/selfencrypt.rs":"8d10840b41629bf449a6b3a551377315e8a05ca26c6b041548748196652c5909"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"c3bbe27a12dc333744b81b97fec121b1e016524ab22bd4cf553a43b7e7f4cd68","bindings/bindings.toml":"29ec7a8ef3d5f1e4a632003e2d36c270e1caf12fd3fcf108a22d1893b90a41a6","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"cbf6a7d912314784c8c124cf7319c910a786d0e263f466843edd3f43826f036c","min_version.txt":"7e98f86c69cddb4f65cf96a6de1f4297e3ce224a4c4628609e29042b6c4dcfb9","src/aead.rs":"fc42bc20b84d2e5ccfd56271ae2d2db082e55586ea2926470c102da177f22296","src/aead_null.rs":"3a553f21126c9ca0116c2be81e5a777011b33c159fd88c4f384614bbdb06bb2e","src/agent.rs":"b12004faee4a136c10e8168848d397443b5927e9497edb62c72e6db3eb1c10a0","src/agentio.rs":"415f70b95312d3ee6d74ba6f28094246101ab6d535aa9df880c38d8bb5a9279e","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8942cb3ce25a61f92b6ffc30fb286052ed6f56eeda3be12fd46ea76ceba6c1cf","src/constants.rs":"f5c779db128a8b0607841ca18c376971017eb327e102e5e6959a7d8effe4b3a6","src/ech.rs":"9d322fcc01c0886f1dfe9bb6273cb9f88a746452ac9a802761b1816a05930c1f","src/err.rs":"ae979f334604aba89640c4491262641910033f0bd790d58671f649f5039b291c","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"ef32f20e30a9bd7f094199536d19c87c4231b7fbbe4a9c54c70e84ca9c6575be","src/hp.rs":"644f1bed67f1c6189a67c8d02ab3358aaa7f63af4b913dd7395becbc01a84291","src/lib.rs":"6b2d0eb2c55f6351d673d3a3e5fc5adac8d1030c67dae9af4c79552de0f57455","src/min_version.rs":"89b7ef6f9d2301db4f689f4d963b58375d577f705b92003a804048441e00cfd1","src/p11.rs":"704c5f164c4f195c8051c5bf1e69a912c34b613a8cf6bed5f577dc5674eea34e","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"96b7af8eff9e14313e79303092018b12e8834f780c96b8e247c497fdc680c696","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"b7cc1c896c7661c37461fc3a8bcbfdf2589433b907fa5f968ae4f6907704b441","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"c71a01ff8aa2c0e97fb16ad620df4ed6b7cc1819ff93f46634e2f1c9551627ec","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"824735f88e487a3748200844e9481e81a72163ad74d82faa9aa16594d9b9bb25","tests/ext.rs":"1b047d23d9b224ad06eb65d8f3a7b351e263774e404c79bbcbe8f43790e29c18","tests/handshake.rs":"e892a2839b31414be16e96cdf3b1a65978716094700c1a4989229f7edbf578a0","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"b24fec53771c169be788772532d2617a5349196cf87d6444dc74214f7c73e92c","tests/init.rs":"616313cb38eac44b8c71a1d23a52a7d7b4c7c07d4c20dc9ea6600c3317f92613","tests/selfencrypt.rs":"8d10840b41629bf449a6b3a551377315e8a05ca26c6b041548748196652c5909"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/neqo-crypto/Cargo.toml b/third_party/rust/neqo-crypto/Cargo.toml
index 9507a066df..a0eaef87f5 100644
--- a/third_party/rust/neqo-crypto/Cargo.toml
+++ b/third_party/rust/neqo-crypto/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.74.0"
+rust-version = "1.76.0"
name = "neqo-crypto"
-version = "0.7.5"
+version = "0.7.7"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
homepage = "https://github.com/mozilla/neqo/"
@@ -61,6 +61,7 @@ default-features = false
[features]
disable-encryption = []
+disable-random = []
gecko = ["mozbuild"]
[lints.clippy.pedantic]
diff --git a/third_party/rust/neqo-crypto/src/aead_null.rs b/third_party/rust/neqo-crypto/src/aead_null.rs
index 2d5656de73..6fcb72871f 100644
--- a/third_party/rust/neqo-crypto/src/aead_null.rs
+++ b/third_party/rust/neqo-crypto/src/aead_null.rs
@@ -4,8 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![cfg(feature = "disable-encryption")]
-
use std::fmt;
use crate::{
diff --git a/third_party/rust/neqo-crypto/src/agentio.rs b/third_party/rust/neqo-crypto/src/agentio.rs
index 7c57a0ef45..3beede5c12 100644
--- a/third_party/rust/neqo-crypto/src/agentio.rs
+++ b/third_party/rust/neqo-crypto/src/agentio.rs
@@ -29,7 +29,7 @@ const PR_FAILURE: PrStatus = prio::PRStatus::PR_FAILURE;
/// Convert a pinned, boxed object into a void pointer.
pub fn as_c_void<T: Unpin>(pin: &mut Pin<Box<T>>) -> *mut c_void {
- (Pin::into_inner(pin.as_mut()) as *mut T).cast()
+ (std::ptr::from_mut::<T>(Pin::into_inner(pin.as_mut()))).cast()
}
/// A slice of the output.
diff --git a/third_party/rust/neqo-crypto/src/constants.rs b/third_party/rust/neqo-crypto/src/constants.rs
index 76db972290..daef3d3c56 100644
--- a/third_party/rust/neqo-crypto/src/constants.rs
+++ b/third_party/rust/neqo-crypto/src/constants.rs
@@ -27,7 +27,7 @@ pub const TLS_EPOCH_APPLICATION_DATA: Epoch = 3_u16;
macro_rules! remap_enum {
{ $t:ident: $s:ty { $( $n:ident = $v:path ),+ $(,)? } } => {
pub type $t = $s;
- $( pub const $n: $t = $v as $t; )+
+ $(#[allow(clippy::cast_possible_truncation)] pub const $n: $t = $v as $t; )+
};
{ $t:ident: $s:ty => $e:ident { $( $n:ident = $v:ident ),+ $(,)? } } => {
remap_enum!{ $t: $s { $( $n = $e::$v ),+ } }
diff --git a/third_party/rust/neqo-crypto/src/p11.rs b/third_party/rust/neqo-crypto/src/p11.rs
index 5552882e2e..c235bb869c 100644
--- a/third_party/rust/neqo-crypto/src/p11.rs
+++ b/third_party/rust/neqo-crypto/src/p11.rs
@@ -13,7 +13,7 @@ use std::{
cell::RefCell,
mem,
ops::{Deref, DerefMut},
- os::raw::{c_int, c_uint},
+ os::raw::c_uint,
ptr::null_mut,
};
@@ -290,14 +290,31 @@ impl Item {
}
}
+#[cfg(feature = "disable-random")]
+thread_local! {
+ static CURRENT_VALUE: std::cell::Cell<u8> = const { std::cell::Cell::new(0) };
+}
+
+#[cfg(feature = "disable-random")]
+/// Fill a buffer with a predictable sequence of bytes.
+pub fn randomize<B: AsMut<[u8]>>(mut buf: B) -> B {
+ let m_buf = buf.as_mut();
+ for v in m_buf.iter_mut() {
+ *v = CURRENT_VALUE.get();
+ CURRENT_VALUE.set(v.wrapping_add(1));
+ }
+ buf
+}
+
/// Fill a buffer with randomness.
///
/// # Panics
///
/// When `size` is too large or NSS fails.
+#[cfg(not(feature = "disable-random"))]
pub fn randomize<B: AsMut<[u8]>>(mut buf: B) -> B {
let m_buf = buf.as_mut();
- let len = c_int::try_from(m_buf.len()).unwrap();
+ let len = std::os::raw::c_int::try_from(m_buf.len()).unwrap();
secstatus_to_res(unsafe { PK11_GenerateRandom(m_buf.as_mut_ptr(), len) }).unwrap();
buf
}
@@ -359,10 +376,13 @@ mod test {
use test_fixture::fixture_init;
use super::RandomCache;
- use crate::{random, randomize};
+ use crate::random;
+ #[cfg(not(feature = "disable-random"))]
#[test]
fn randomness() {
+ use crate::randomize;
+
fixture_init();
// If any of these ever fail, there is either a bug, or it's time to buy a lottery ticket.
assert_ne!(random::<16>(), randomize([0; 16]));
diff --git a/third_party/rust/neqo-http3/.cargo-checksum.json b/third_party/rust/neqo-http3/.cargo-checksum.json
index dff33cc964..f456e3f62d 100644
--- a/third_party/rust/neqo-http3/.cargo-checksum.json
+++ b/third_party/rust/neqo-http3/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"f3d4e7ace03bbc6ee36fb30540e0a96aebdf5222090cd95abdff14b840cfa68e","src/buffered_send_stream.rs":"f45bdf9ad2a04b3828c74ff5440681d3c9d1af39b55470e4f729842dc2412295","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"224a8ea6ef632930a7788a1cabf47ce69ad41bd4bc8dcf3053fbd998fdb38e82","src/connection.rs":"e9c869ec4c650162927543cfe608721fad037554c5101962b323496bf69e29a5","src/connection_client.rs":"2026e7b2c11f4d5a71b35eedaf14175d7d7cf96ce2bb64c4a97d6062cbb646c7","src/connection_server.rs":"de5a6cb42b8c4dc08fb1f626f681b45cd22435892b11e6053b61a5401490db94","src/control_stream_local.rs":"ae52e3286f1686ca1265e7de841392addd42616db02799bb967a59feb6039cb5","src/control_stream_remote.rs":"59eb4041e366d92f9f294e8446755caa5e91fd943bba7b79b726698ba13be248","src/features/extended_connect/mod.rs":"3b02f6b18627f3855465a81b1d9b285e6f13839e75a8a6db648ed9082908d7f0","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"4c85a90afb753ce588e3fdeb773669bc49c013aebc28912340359eb01b74fd70","src/features/extended_connect/tests/webtransport/mod.rs":"a30ea715f5271a826a739278b18e145964dedbce7026eed45f1b7d0355c407d5","src/features/extended_connect/tests/webtransport/negotiation.rs":"98254ef8446581ec520026b04ef9549645602181b61602c9936f6660141edf0b","src/features/extended_connect/tests/webtransport/sessions.rs":"de3d836f666c2bec31e70b33bdc2669572cabbe17df2225db7282613a224a364","src/features/extended_connect/tests/webtransport/streams.rs":"8b3c34cac1b2171252a4bb53d420ac2098549a20309c327bf56e2e9ba9e33538","src/features/extended_connect/webtransport_session.rs":"239d92c06fbc5f6226078bb411a803f57b555dea0077349d49d7f57671cf2eab","src/features/extended_connect/webtransport_streams.rs":"5d7507aaf6a819d266fbea9b7a415c8324329df0f6936d9045b73e17a5b844ee","src/features/mod.rs":"925aae4427ad82e4d019354802b223d53db5e5585d4a940f5417a24a9503d7ee","src/frames/hframe.rs":"56c36ac597504f28c73cf2370acd82104f8c7a7b9ffc0f6d222378abc524482d","src/frames/mod.rs":"7d0a46ca147336d14781edb8dbee8b03c2e4bcd6646f5473a9d93d31fe73fecb","src/frames/reader.rs":"e07ee9de74bc499c10afcda592fefd9a7eef3381c045aa14f6596d67313546ca","src/frames/tests/hframe.rs":"01ec74eb3eb25d95042aa0263f9267f89535e6b7b8c1161fab4ba9ee5352d4a7","src/frames/tests/mod.rs":"0610609b316767a6a022837d32ee0452e37ea296fde37e51bec87e7c77e923a3","src/frames/tests/reader.rs":"2bfadc7afbc41bff9f5f930b31550259a8a92484d35f6c5d8dd8fd9acfb88f5b","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"1d9d0256ace2ba7262343ed035df795f21a4d45065792d3fd45b3391b6916b2f","src/headers_checks.rs":"be0f0109298dcc3a40350b7c0950076ddfe20617d195b305e3ffc8582557ab18","src/lib.rs":"4f908a021222bcc79b9d569bc3759a493379a20b47dfa228fddf51600bf6e446","src/priority.rs":"f3b77c208962e44a4e2d13138c6998b703d40e7bcf8f73ea84d8ef5b556e0aee","src/push_controller.rs":"13bccf2834ae19109504cf695a5948c3b2d03fd101bc032a92bb77a033423854","src/qlog.rs":"2debd75c7ea103c95ff79e44412f1408c3e496e324976100c55d5a833912b6c3","src/qpack_decoder_receiver.rs":"c927dfc3e58c71d282210ba79280f6f03e789733bc3bedc247e68bab516b9e9e","src/qpack_encoder_receiver.rs":"d0ac03cc111b6e1c555a8654d3234116f2b135b5b040edac23cefe2d640beba9","src/recv_message.rs":"7ac8d4057ba53874e4edfc62cd25ad5d3f0b10aaac5bf6e156103c3bc44e18cc","src/request_target.rs":"6041a69a0a74969ec08bc164509c055e9bad99f53bbeb16c0aa17d108dd68b8c","src/send_message.rs":"374e168f60063b8102a2aff52c719ae2e1e5078527cf50d095b3e7217f6ec7d2","src/server.rs":"b9e6060da36cfb467478f5b78b17e22a123214ad2d64c919ce688ea2bc0e24bb","src/server_connection_events.rs":"12d353ca6301467f6d475dde3b789951a5716c89ddd7dbf1383efef8082361f3","src/server_events.rs":"1cda8d6c413fad0fa67fcfd7cb78e795bf7ef7f0e09b5720992646a82d51ce16","src/settings.rs":"476b154b5eea4c8d69a4a790fee3e527cef4d375df1cfb5eed04ec56406fe15a","src/stream_type_reader.rs":"7a7226b7911d69f7e00ec4987c2a32a5e8a33463203398cbee1e6645d2691478","tests/httpconn.rs":"bb6927801a8c75e4f05eb6cdb1e7f2d57be69b74e68ddad2a1614f2aeed04369","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"b5435045b16429d9e626ea94a8f10e2937e1a5a878af0035763a4f5ec09bf53c","tests/webtransport.rs":"25794305017ff58e57dc3c3b9b078e5bfc1814ea82a521b7b7156228e613c092"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"08e52a9eb3d14c9b985d5ab9e88f2bfec51bc9f13b6d62d84e143aece1f55654","src/buffered_send_stream.rs":"0e8ad3f443a33e213d55ba26a1ff266692c9087a1627c9b3d10c5025dee550ac","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"224a8ea6ef632930a7788a1cabf47ce69ad41bd4bc8dcf3053fbd998fdb38e82","src/connection.rs":"f5f49dd72170f7e42c180b738ff8bddae92fd0c71acc5a08736e298bf53483e7","src/connection_client.rs":"77cf08711b89e03c7cea47bf3cf02c76397485877121e42c321206cf7bef4ddc","src/connection_server.rs":"de5a6cb42b8c4dc08fb1f626f681b45cd22435892b11e6053b61a5401490db94","src/control_stream_local.rs":"ae52e3286f1686ca1265e7de841392addd42616db02799bb967a59feb6039cb5","src/control_stream_remote.rs":"59eb4041e366d92f9f294e8446755caa5e91fd943bba7b79b726698ba13be248","src/features/extended_connect/mod.rs":"3b02f6b18627f3855465a81b1d9b285e6f13839e75a8a6db648ed9082908d7f0","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"4c85a90afb753ce588e3fdeb773669bc49c013aebc28912340359eb01b74fd70","src/features/extended_connect/tests/webtransport/mod.rs":"a30ea715f5271a826a739278b18e145964dedbce7026eed45f1b7d0355c407d5","src/features/extended_connect/tests/webtransport/negotiation.rs":"a8940b99e21a6b29fef2fc32f3dce05d12de8b09079dfdc0502c13e4582dbdb6","src/features/extended_connect/tests/webtransport/sessions.rs":"de3d836f666c2bec31e70b33bdc2669572cabbe17df2225db7282613a224a364","src/features/extended_connect/tests/webtransport/streams.rs":"8b3c34cac1b2171252a4bb53d420ac2098549a20309c327bf56e2e9ba9e33538","src/features/extended_connect/webtransport_session.rs":"239d92c06fbc5f6226078bb411a803f57b555dea0077349d49d7f57671cf2eab","src/features/extended_connect/webtransport_streams.rs":"5d7507aaf6a819d266fbea9b7a415c8324329df0f6936d9045b73e17a5b844ee","src/features/mod.rs":"925aae4427ad82e4d019354802b223d53db5e5585d4a940f5417a24a9503d7ee","src/frames/hframe.rs":"56c36ac597504f28c73cf2370acd82104f8c7a7b9ffc0f6d222378abc524482d","src/frames/mod.rs":"7d0a46ca147336d14781edb8dbee8b03c2e4bcd6646f5473a9d93d31fe73fecb","src/frames/reader.rs":"e07ee9de74bc499c10afcda592fefd9a7eef3381c045aa14f6596d67313546ca","src/frames/tests/hframe.rs":"01ec74eb3eb25d95042aa0263f9267f89535e6b7b8c1161fab4ba9ee5352d4a7","src/frames/tests/mod.rs":"0610609b316767a6a022837d32ee0452e37ea296fde37e51bec87e7c77e923a3","src/frames/tests/reader.rs":"2bfadc7afbc41bff9f5f930b31550259a8a92484d35f6c5d8dd8fd9acfb88f5b","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"1d9d0256ace2ba7262343ed035df795f21a4d45065792d3fd45b3391b6916b2f","src/headers_checks.rs":"be0f0109298dcc3a40350b7c0950076ddfe20617d195b305e3ffc8582557ab18","src/lib.rs":"4f908a021222bcc79b9d569bc3759a493379a20b47dfa228fddf51600bf6e446","src/priority.rs":"f3b77c208962e44a4e2d13138c6998b703d40e7bcf8f73ea84d8ef5b556e0aee","src/push_controller.rs":"13bccf2834ae19109504cf695a5948c3b2d03fd101bc032a92bb77a033423854","src/qlog.rs":"2debd75c7ea103c95ff79e44412f1408c3e496e324976100c55d5a833912b6c3","src/qpack_decoder_receiver.rs":"c927dfc3e58c71d282210ba79280f6f03e789733bc3bedc247e68bab516b9e9e","src/qpack_encoder_receiver.rs":"d0ac03cc111b6e1c555a8654d3234116f2b135b5b040edac23cefe2d640beba9","src/recv_message.rs":"7ac8d4057ba53874e4edfc62cd25ad5d3f0b10aaac5bf6e156103c3bc44e18cc","src/request_target.rs":"6041a69a0a74969ec08bc164509c055e9bad99f53bbeb16c0aa17d108dd68b8c","src/send_message.rs":"bc1bb096e56560088db961ab0f7a4e08acd3d3977f483ffcbdcfeec7ed8d855a","src/server.rs":"24822b9b164271862777cf5afcc74edbecaa4ce648978b0a6559e1490e3cea55","src/server_connection_events.rs":"12d353ca6301467f6d475dde3b789951a5716c89ddd7dbf1383efef8082361f3","src/server_events.rs":"1cda8d6c413fad0fa67fcfd7cb78e795bf7ef7f0e09b5720992646a82d51ce16","src/settings.rs":"476b154b5eea4c8d69a4a790fee3e527cef4d375df1cfb5eed04ec56406fe15a","src/stream_type_reader.rs":"7a7226b7911d69f7e00ec4987c2a32a5e8a33463203398cbee1e6645d2691478","tests/httpconn.rs":"ee2f29c6104f5379bee2606f160005683f00ae85f2c43216e7ffaa89ff633466","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"b5435045b16429d9e626ea94a8f10e2937e1a5a878af0035763a4f5ec09bf53c","tests/webtransport.rs":"25794305017ff58e57dc3c3b9b078e5bfc1814ea82a521b7b7156228e613c092"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/neqo-http3/Cargo.toml b/third_party/rust/neqo-http3/Cargo.toml
index c844ba43ef..6ab5f166f4 100644
--- a/third_party/rust/neqo-http3/Cargo.toml
+++ b/third_party/rust/neqo-http3/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.74.0"
+rust-version = "1.76.0"
name = "neqo-http3"
-version = "0.7.5"
+version = "0.7.7"
authors = ["The Neqo Authors <necko@mozilla.com>"]
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
@@ -43,7 +43,7 @@ path = "./../neqo-qpack"
path = "./../neqo-transport"
[dependencies.qlog]
-version = "0.12"
+version = "0.13"
default-features = false
[dependencies.sfv]
diff --git a/third_party/rust/neqo-http3/src/buffered_send_stream.rs b/third_party/rust/neqo-http3/src/buffered_send_stream.rs
index 4f6761fa80..60da0512b5 100644
--- a/third_party/rust/neqo-http3/src/buffered_send_stream.rs
+++ b/third_party/rust/neqo-http3/src/buffered_send_stream.rs
@@ -7,7 +7,7 @@
use neqo_common::qtrace;
use neqo_transport::{Connection, StreamId};
-use crate::Res;
+use crate::{qlog, Res};
#[derive(Debug, PartialEq, Eq)]
pub enum BufferedStream {
@@ -38,7 +38,7 @@ impl BufferedStream {
/// # Panics
///
- /// If the `BufferedStream` is initialized more than one it will panic.
+ /// If the `BufferedStream` is initialized more than once, it will panic.
pub fn init(&mut self, stream_id: StreamId) {
debug_assert!(&Self::Uninitialized == self);
*self = Self::Initialized {
@@ -63,19 +63,23 @@ impl BufferedStream {
/// Returns `neqo_transport` errors.
pub fn send_buffer(&mut self, conn: &mut Connection) -> Res<usize> {
let label = ::neqo_common::log_subject!(::log::Level::Debug, self);
- let mut sent = 0;
- if let Self::Initialized { stream_id, buf } = self {
- if !buf.is_empty() {
- qtrace!([label], "sending data.");
- sent = conn.stream_send(*stream_id, &buf[..])?;
- if sent == buf.len() {
- buf.clear();
- } else {
- let b = buf.split_off(sent);
- *buf = b;
- }
- }
+ let Self::Initialized { stream_id, buf } = self else {
+ return Ok(0);
+ };
+ if buf.is_empty() {
+ return Ok(0);
+ }
+ qtrace!([label], "sending data.");
+ let sent = conn.stream_send(*stream_id, &buf[..])?;
+ if sent == 0 {
+ return Ok(0);
+ } else if sent == buf.len() {
+ buf.clear();
+ } else {
+ let b = buf.split_off(sent);
+ *buf = b;
}
+ qlog::h3_data_moved_down(conn.qlog_mut(), *stream_id, sent);
Ok(sent)
}
@@ -85,16 +89,17 @@ impl BufferedStream {
pub fn send_atomic(&mut self, conn: &mut Connection, to_send: &[u8]) -> Res<bool> {
// First try to send anything that is in the buffer.
self.send_buffer(conn)?;
- if let Self::Initialized { stream_id, buf } = self {
- if buf.is_empty() {
- let res = conn.stream_send_atomic(*stream_id, to_send)?;
- Ok(res)
- } else {
- Ok(false)
- }
- } else {
- Ok(false)
+ let Self::Initialized { stream_id, buf } = self else {
+ return Ok(false);
+ };
+ if !buf.is_empty() {
+ return Ok(false);
+ }
+ let res = conn.stream_send_atomic(*stream_id, to_send)?;
+ if res {
+ qlog::h3_data_moved_down(conn.qlog_mut(), *stream_id, to_send.len());
}
+ Ok(res)
}
#[must_use]
diff --git a/third_party/rust/neqo-http3/src/connection.rs b/third_party/rust/neqo-http3/src/connection.rs
index dd45797baa..d14eb6f2a5 100644
--- a/third_party/rust/neqo-http3/src/connection.rs
+++ b/third_party/rust/neqo-http3/src/connection.rs
@@ -17,7 +17,7 @@ use std::{
use neqo_common::{qdebug, qerror, qinfo, qtrace, qwarn, Decoder, Header, MessageType, Role};
use neqo_qpack::{decoder::QPackDecoder, encoder::QPackEncoder};
use neqo_transport::{
- streams::SendOrder, AppError, Connection, ConnectionError, DatagramTracking, State, StreamId,
+ streams::SendOrder, AppError, CloseReason, Connection, DatagramTracking, State, StreamId,
StreamType, ZeroRttState,
};
@@ -81,22 +81,22 @@ enum Http3RemoteSettingsState {
/// - `ZeroRtt`: 0-RTT has been enabled and is active
/// - Connected
/// - GoingAway(StreamId): The connection has received a `GOAWAY` frame
-/// - Closing(ConnectionError): The connection is closed. The closing has been initiated by this end
-/// of the connection, e.g., the `CONNECTION_CLOSE` frame has been sent. In this state, the
+/// - Closing(CloseReason): The connection is closed. The closing has been initiated by this end of
+/// the connection, e.g., the `CONNECTION_CLOSE` frame has been sent. In this state, the
/// connection waits a certain amount of time to retransmit the `CONNECTION_CLOSE` frame if
/// needed.
-/// - Closed(ConnectionError): This is the final close state: closing has been initialized by the
-/// peer and an ack for the `CONNECTION_CLOSE` frame has been sent or the closing has been
-/// initiated by this end of the connection and the ack for the `CONNECTION_CLOSE` has been
-/// received or the waiting time has passed.
+/// - Closed(CloseReason): This is the final close state: closing has been initialized by the peer
+/// and an ack for the `CONNECTION_CLOSE` frame has been sent or the closing has been initiated by
+/// this end of the connection and the ack for the `CONNECTION_CLOSE` has been received or the
+/// waiting time has passed.
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Clone)]
pub enum Http3State {
Initializing,
ZeroRtt,
Connected,
GoingAway(StreamId),
- Closing(ConnectionError),
- Closed(ConnectionError),
+ Closing(CloseReason),
+ Closed(CloseReason),
}
impl Http3State {
@@ -767,7 +767,7 @@ impl Http3Connection {
/// This is called when an application closes the connection.
pub fn close(&mut self, error: AppError) {
qdebug!([self], "Close connection error {:?}.", error);
- self.state = Http3State::Closing(ConnectionError::Application(error));
+ self.state = Http3State::Closing(CloseReason::Application(error));
if (!self.send_streams.is_empty() || !self.recv_streams.is_empty()) && (error == 0) {
qwarn!("close(0) called when streams still active");
}
diff --git a/third_party/rust/neqo-http3/src/connection_client.rs b/third_party/rust/neqo-http3/src/connection_client.rs
index 4c8772d14a..18e513e743 100644
--- a/third_party/rust/neqo-http3/src/connection_client.rs
+++ b/third_party/rust/neqo-http3/src/connection_client.rs
@@ -1291,8 +1291,8 @@ mod tests {
use neqo_crypto::{AllowZeroRtt, AntiReplay, ResumptionToken};
use neqo_qpack::{encoder::QPackEncoder, QpackSettings};
use neqo_transport::{
- ConnectionError, ConnectionEvent, ConnectionParameters, Output, State, StreamId,
- StreamType, Version, RECV_BUFFER_SIZE, SEND_BUFFER_SIZE,
+ CloseReason, ConnectionEvent, ConnectionParameters, Output, State, StreamId, StreamType,
+ Version, RECV_BUFFER_SIZE, SEND_BUFFER_SIZE,
};
use test_fixture::{
anti_replay, default_server_h3, fixture_init, new_server, now,
@@ -1314,7 +1314,7 @@ mod tests {
fn assert_closed(client: &Http3Client, expected: &Error) {
match client.state() {
Http3State::Closing(err) | Http3State::Closed(err) => {
- assert_eq!(err, ConnectionError::Application(expected.code()));
+ assert_eq!(err, CloseReason::Application(expected.code()));
}
_ => panic!("Wrong state {:?}", client.state()),
};
@@ -4419,7 +4419,7 @@ mod tests {
HSetting::new(HSettingType::BlockedStreams, 100),
HSetting::new(HSettingType::MaxHeaderListSize, 10000),
],
- &Http3State::Closing(ConnectionError::Application(265)),
+ &Http3State::Closing(CloseReason::Application(265)),
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
);
}
@@ -4437,7 +4437,7 @@ mod tests {
HSetting::new(HSettingType::MaxTableCapacity, 100),
HSetting::new(HSettingType::MaxHeaderListSize, 10000),
],
- &Http3State::Closing(ConnectionError::Application(265)),
+ &Http3State::Closing(CloseReason::Application(265)),
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
);
}
@@ -4474,7 +4474,7 @@ mod tests {
HSetting::new(HSettingType::BlockedStreams, 100),
HSetting::new(HSettingType::MaxHeaderListSize, 10000),
],
- &Http3State::Closing(ConnectionError::Application(514)),
+ &Http3State::Closing(CloseReason::Application(514)),
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
);
}
@@ -4493,7 +4493,7 @@ mod tests {
HSetting::new(HSettingType::BlockedStreams, 100),
HSetting::new(HSettingType::MaxHeaderListSize, 10000),
],
- &Http3State::Closing(ConnectionError::Application(265)),
+ &Http3State::Closing(CloseReason::Application(265)),
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
);
}
@@ -4531,7 +4531,7 @@ mod tests {
HSetting::new(HSettingType::BlockedStreams, 50),
HSetting::new(HSettingType::MaxHeaderListSize, 10000),
],
- &Http3State::Closing(ConnectionError::Application(265)),
+ &Http3State::Closing(CloseReason::Application(265)),
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
);
}
@@ -4569,7 +4569,7 @@ mod tests {
HSetting::new(HSettingType::BlockedStreams, 100),
HSetting::new(HSettingType::MaxHeaderListSize, 5000),
],
- &Http3State::Closing(ConnectionError::Application(265)),
+ &Http3State::Closing(CloseReason::Application(265)),
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
);
}
@@ -4626,7 +4626,7 @@ mod tests {
HSetting::new(HSettingType::BlockedStreams, 100),
HSetting::new(HSettingType::MaxHeaderListSize, 10000),
],
- &Http3State::Closing(ConnectionError::Application(265)),
+ &Http3State::Closing(CloseReason::Application(265)),
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
);
}
diff --git a/third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/negotiation.rs b/third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/negotiation.rs
index 27f669861d..9b54f1dc46 100644
--- a/third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/negotiation.rs
+++ b/third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/negotiation.rs
@@ -8,7 +8,7 @@ use std::time::Duration;
use neqo_common::{event::Provider, Encoder};
use neqo_crypto::AuthenticationStatus;
-use neqo_transport::{Connection, ConnectionError, StreamType};
+use neqo_transport::{CloseReason, Connection, StreamType};
use test_fixture::{default_server_h3, now};
use super::{connect, default_http3_client, default_http3_server, exchange_packets};
@@ -270,10 +270,7 @@ fn wrong_setting_value() {
exchange_packets2(&mut client, &mut server);
match client.state() {
Http3State::Closing(err) | Http3State::Closed(err) => {
- assert_eq!(
- err,
- ConnectionError::Application(Error::HttpSettings.code())
- );
+ assert_eq!(err, CloseReason::Application(Error::HttpSettings.code()));
}
_ => panic!("Wrong state {:?}", client.state()),
};
diff --git a/third_party/rust/neqo-http3/src/send_message.rs b/third_party/rust/neqo-http3/src/send_message.rs
index 15965c44f6..7fb37beb70 100644
--- a/third_party/rust/neqo-http3/src/send_message.rs
+++ b/third_party/rust/neqo-http3/src/send_message.rs
@@ -13,7 +13,7 @@ use neqo_transport::{Connection, StreamId};
use crate::{
frames::HFrame,
headers_checks::{headers_valid, is_interim, trailers_valid},
- qlog, BufferedStream, CloseType, Error, Http3StreamInfo, Http3StreamType, HttpSendStream, Res,
+ BufferedStream, CloseType, Error, Http3StreamInfo, Http3StreamType, HttpSendStream, Res,
SendStream, SendStreamEvents, Stream,
};
@@ -216,7 +216,6 @@ impl SendStream for SendMessage {
.send_atomic(conn, &buf[..to_send])
.map_err(|e| Error::map_stream_send_errors(&e))?;
debug_assert!(sent);
- qlog::h3_data_moved_down(conn.qlog_mut(), self.stream_id(), to_send);
Ok(to_send)
}
@@ -243,7 +242,6 @@ impl SendStream for SendMessage {
/// info that the stream has been closed.)
fn send(&mut self, conn: &mut Connection) -> Res<()> {
let sent = Error::map_error(self.stream.send_buffer(conn), Error::HttpInternal(5))?;
- qlog::h3_data_moved_down(conn.qlog_mut(), self.stream_id(), sent);
qtrace!([self], "{} bytes sent", sent);
if !self.stream.has_buffered_data() {
diff --git a/third_party/rust/neqo-http3/src/server.rs b/third_party/rust/neqo-http3/src/server.rs
index 1396a4e4cf..8fce803fb3 100644
--- a/third_party/rust/neqo-http3/src/server.rs
+++ b/third_party/rust/neqo-http3/src/server.rs
@@ -323,7 +323,7 @@ mod tests {
use neqo_crypto::{AuthenticationStatus, ZeroRttCheckResult, ZeroRttChecker};
use neqo_qpack::{encoder::QPackEncoder, QpackSettings};
use neqo_transport::{
- Connection, ConnectionError, ConnectionEvent, State, StreamId, StreamType, ZeroRttState,
+ CloseReason, Connection, ConnectionEvent, State, StreamId, StreamType, ZeroRttState,
};
use test_fixture::{
anti_replay, default_client, fixture_init, now, CountingConnectionIdGenerator,
@@ -366,7 +366,7 @@ mod tests {
}
fn assert_closed(hconn: &mut Http3Server, expected: &Error) {
- let err = ConnectionError::Application(expected.code());
+ let err = CloseReason::Application(expected.code());
let closed = |e| matches!(e, Http3ServerEvent::StateChange{ state: Http3State::Closing(e) | Http3State::Closed(e), .. } if e == err);
assert!(hconn.events().any(closed));
}
diff --git a/third_party/rust/neqo-http3/tests/httpconn.rs b/third_party/rust/neqo-http3/tests/httpconn.rs
index a0b2bcdb80..c0c62de9c9 100644
--- a/third_party/rust/neqo-http3/tests/httpconn.rs
+++ b/third_party/rust/neqo-http3/tests/httpconn.rs
@@ -17,7 +17,7 @@ use neqo_http3::{
Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
Http3ServerEvent, Http3State, Priority,
};
-use neqo_transport::{ConnectionError, ConnectionParameters, Error, Output, StreamType};
+use neqo_transport::{CloseReason, ConnectionParameters, Error, Output, StreamType};
use test_fixture::*;
const RESPONSE_DATA: &[u8] = &[0x61, 0x62, 0x63];
@@ -448,7 +448,7 @@ fn fetch_noresponse_will_idletimeout() {
if let Http3ClientEvent::StateChange(state) = event {
match state {
Http3State::Closing(error_code) | Http3State::Closed(error_code) => {
- assert_eq!(error_code, ConnectionError::Transport(Error::IdleTimeout));
+ assert_eq!(error_code, CloseReason::Transport(Error::IdleTimeout));
done = true;
}
_ => {}
diff --git a/third_party/rust/neqo-qpack/.cargo-checksum.json b/third_party/rust/neqo-qpack/.cargo-checksum.json
index d717487018..d322bc4d81 100644
--- a/third_party/rust/neqo-qpack/.cargo-checksum.json
+++ b/third_party/rust/neqo-qpack/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"b963363c6eb1b0b3318d5901d372599db89dff87131e0979b2eb09f42c84d72a","src/decoder.rs":"0675444129e074e9d5d56f0d45d2eaed614c85e22cfe9f2d28cdee912c15b420","src/decoder_instructions.rs":"d991d70e51f079bc5b30d3982fd0176edfa9bb7ba14c17a20ec3eea878c56206","src/encoder.rs":"84649cbee81e050f55d7ea691ac871e072741abd8bbf96303eb2e98aa8ee0aea","src/encoder_instructions.rs":"86e3abbd9cf94332041326ac6cf806ed64623e3fd38dbc0385b1f63c37e73fd9","src/header_block.rs":"3925476df69b90d950594faadc5cb24c374d46de8c75a374a235f0d27323a7d8","src/huffman.rs":"71ec740426eee0abb6205104e504f5b97f525a76c4a5f5827b78034d28ce1876","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"fd673630b5ed64197851c9a9758685096d3c0aa04f4994290733a38057004ee6","src/prefix.rs":"fb4a9acbcf6fd3178f4474404cd3d3b131abca934f69fe14a9d744bc7e636dc5","src/qlog.rs":"e320007ea8309546b26f9c0019ab8722da80dbd38fa976233fd8ae19a0af637c","src/qpack_send_buf.rs":"755af90fe077b1bcca34a1a2a1bdce5ce601ea490b2ca3f1313e0107d13e67e2","src/reader.rs":"1581261741a0922b147a6975cc8b1a3503846f6dbfdb771d254760c298996982","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"ddf055a228bed575d640d9a06e19e1e9fd98a48e393a7d326f8254438fb94889"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"e0a99f1f9f0580d7166549bb90c603fbfc88babd675a84191fe6fb5124104d01","src/decoder.rs":"0675444129e074e9d5d56f0d45d2eaed614c85e22cfe9f2d28cdee912c15b420","src/decoder_instructions.rs":"d991d70e51f079bc5b30d3982fd0176edfa9bb7ba14c17a20ec3eea878c56206","src/encoder.rs":"84649cbee81e050f55d7ea691ac871e072741abd8bbf96303eb2e98aa8ee0aea","src/encoder_instructions.rs":"86e3abbd9cf94332041326ac6cf806ed64623e3fd38dbc0385b1f63c37e73fd9","src/header_block.rs":"3925476df69b90d950594faadc5cb24c374d46de8c75a374a235f0d27323a7d8","src/huffman.rs":"71ec740426eee0abb6205104e504f5b97f525a76c4a5f5827b78034d28ce1876","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"fd673630b5ed64197851c9a9758685096d3c0aa04f4994290733a38057004ee6","src/prefix.rs":"fb4a9acbcf6fd3178f4474404cd3d3b131abca934f69fe14a9d744bc7e636dc5","src/qlog.rs":"e320007ea8309546b26f9c0019ab8722da80dbd38fa976233fd8ae19a0af637c","src/qpack_send_buf.rs":"755af90fe077b1bcca34a1a2a1bdce5ce601ea490b2ca3f1313e0107d13e67e2","src/reader.rs":"1581261741a0922b147a6975cc8b1a3503846f6dbfdb771d254760c298996982","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"ddf055a228bed575d640d9a06e19e1e9fd98a48e393a7d326f8254438fb94889"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/neqo-qpack/Cargo.toml b/third_party/rust/neqo-qpack/Cargo.toml
index 822cddd9c0..0758437fa7 100644
--- a/third_party/rust/neqo-qpack/Cargo.toml
+++ b/third_party/rust/neqo-qpack/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.74.0"
+rust-version = "1.76.0"
name = "neqo-qpack"
-version = "0.7.5"
+version = "0.7.7"
authors = ["The Neqo Authors <necko@mozilla.com>"]
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
@@ -36,7 +36,7 @@ path = "./../neqo-crypto"
path = "./../neqo-transport"
[dependencies.qlog]
-version = "0.12"
+version = "0.13"
default-features = false
[dependencies.static_assertions]
diff --git a/third_party/rust/neqo-transport/.cargo-checksum.json b/third_party/rust/neqo-transport/.cargo-checksum.json
index 3fc724515c..4d0f39c2b4 100644
--- a/third_party/rust/neqo-transport/.cargo-checksum.json
+++ b/third_party/rust/neqo-transport/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"28025605522925d25700870cd043f2a169acad5193b2da09c7a296bd9f73d389","benches/range_tracker.rs":"590dd1f81c92e89ce28af1efdda583d85240438bd9c4c68767286d22a299ad4b","benches/rx_stream_orderer.rs":"53a008357703251a18100521a12d8fa9443c5601ddc3cbd1b3c2899074da4c4f","benches/transfer.rs":"94eb0ec1a0a7d0a4863ddc1c6d006521e52c1f2e7f03c69428b18f7eb827d33f","src/ackrate.rs":"4bb882e1069a0707dc85338b75327e2910c93ee5f36575767a0d58c4c41c9d4f","src/addr_valid.rs":"03c0b2ff85254179c5d425b12acfdcc6b1ea5735aeb0f604b9b3603451b3ef0a","src/cc/classic_cc.rs":"aaaf3670bfaacf10c2ab77b547b4aeec2618ec6b2bb2d921000a8b795f38ea87","src/cc/cubic.rs":"24c6913cc6346e5361007221c26e8096ece51583431fc3ab9c99e4ce4b0a9f5d","src/cc/mod.rs":"e0837937c9991b37edad15cd870ea9e0623489babfccc340074dd8322e1ef401","src/cc/new_reno.rs":"25d0921005688e0f0666efd0a4931b4f8cd44363587d98e5b6404818c5d05dd4","src/cc/tests/cubic.rs":"109fc8be5efba8959e777288c32ae8f2db581fc08719f318ad676e187f655478","src/cc/tests/mod.rs":"44f8df551e742ae1037cd1cdb85b2c1334c2e5ab3c23ed63d856dbc6b8743afc","src/cc/tests/new_reno.rs":"5414e26b6c928c5f82c5eeb42f04772b05be1ec2c8ee21c2b698ce8cb32829a1","src/cid.rs":"9686a3070c593cfca846d7549863728e31211b304b9fa876220f79bff5e24173","src/connection/dump.rs":"bd4fb55785fe42f5c94f7bcc14ccf4ae377d28b691fb55dbf1139ae9412b0ea9","src/connection/idle.rs":"b3bc2ad1290e54278d8703092d135eda973eb12316d1f6dffedaffdf25e2a47e","src/connection/mod.rs":"907ded3ba14ec8ef675e1ea55c5698d6ffe023de5e81a006746d9759eb243640","src/connection/params.rs":"38e0b47c8cc5fbe602e3174d7a70df410829bc240b42f21cebd10818e606ef7c","src/connection/saved.rs":"97eb19792be3c4d721057021a43ea50a52f89a3cfa583d3d3dcf5d9144b332f5","src/connection/state.rs":"c0c4b1c15624a8762eabc8d5fa76f169f3f93945a9ee86f30fbd7714f1ac1d37","src/connection/test_internal.rs":"f3ebfe97b25c9c716d41406066295e5aff4e96a3051ef4e2b5fb258282bbc14c","src/connection/tests/ackrate.rs":"4a2b835575850ae4a14209d3e51883ecb1e69afb44ef91b5e13a5e6cb7174fab","src/connection/tests/cc.rs":"d0d6ac038572ad3dcd9e6734596eaeedc6d3222d24e31b023aaab3540d195e46","src/connection/tests/close.rs":"20bf9b044ba52517693c2bd10820ff04a8c07de01d59c8c47b4e9478aa730211","src/connection/tests/datagram.rs":"f4c85099b6a8739fb99eadd8711b02066ad80fc8341a2e5e0dae2520378af9fe","src/connection/tests/handshake.rs":"c759737ee98c7b33b2327eb7d521f45c63aed15dc8f272b7bbcc510ee8e48877","src/connection/tests/idle.rs":"f3bcb12cd79cb8eabc969ce3fb0fab4eea26d6383b81a323c0e18ca9c42cfb59","src/connection/tests/keys.rs":"55558c057beb4221245beb262076de3991dca3f2661411db61c09d21194873df","src/connection/tests/migration.rs":"624985d925236be197eee52208dbdebe35c0df5bd9d30982d6f183dfda4cbab5","src/connection/tests/mod.rs":"280077d4e69faabd2fc1fe03f754096b8b83a8e2b2438fd05b3d7cd924154489","src/connection/tests/null.rs":"38f76a4ea15e6b11634d4374cb0f2a68bd250e5d35831edfce0fa48deeaa420d","src/connection/tests/priority.rs":"dd3504f52d3fce7a96441624bc1c82c733e6bb556b9b79d24d0f4fb4efaf5a9e","src/connection/tests/recovery.rs":"7f28767f3cca2ff60e3dcfa803e12ef043486a222f54681a8faf2ea2fee564a1","src/connection/tests/resumption.rs":"1a0de0993cd325224fc79a3c094d22636d5b122ab1123d16265d4fafb23574bd","src/connection/tests/stream.rs":"8e4af07d8033a951fc57f2afda570a08843b36931eca53ba3781a5992978afb2","src/connection/tests/vn.rs":"550eb6b4d39d5960aafc70037c25a1a0f5db1232ce0ec6080b2c29a731a9574e","src/connection/tests/zerortt.rs":"67f77721e33d9fa2691c5ea3ef4a90935987541d81f0f42fbcfca31e690b352a","src/crypto.rs":"416b73c06fcc2812cc252936bcb039fc13cf0b715e7e22a54314a3f72aee743c","src/events.rs":"6e115f309c5c46f30f6223e1347bea477ada457f8bb2189ecccc6d65483318d6","src/fc.rs":"ec9de1028286870c0adf88a92e1355acf13dede8b1e91179230df3263e3827a9","src/frame.rs":"5c8e5bc21e1052367f7db31523ee422efa4278ccdfc8cd581bb44a50ee205f16","src/lib.rs":"95810fd3ec1b7da9e42f4786e1360a6e40444d69c427065856e751fd1cf411bb","src/pace.rs":"86a674ac4d086148ea297214910458c3705918bd627b996ba8bbb12f2c4bf99e","src/packet/mod.rs":"e21e594c28c568c5d21bfa1dff2903ff3fe6f9dcb98c478eeca120c535d763ef","src/packet/retry.rs":"d5f999485f21b388a7383cd011fc6e96109c1a9fb5aef79b19017df6844271ff","src/path.rs":"610e6ce83da91b785d0690995591fa4da7b5a1add3d0022eea0be5050612cee9","src/qlog.rs":"f3d3661835a29e6023014f7a0996494fc8dc1f2d062154b94346a0c21bbf6fd1","src/quic_datagrams.rs":"3d33ecb9e6e80c77b812e8260fc807352300fb2305a29b797259ae34c52b67c5","src/recovery.rs":"1dadc6717dd133007943e762231a50680087392466904c2f2e6fface084e2ba9","src/recv_stream.rs":"f21ae0bb786901bb7d726a94cb3352607b0057128beaa331808137f2f57a330b","src/rtt.rs":"4635dc0c401b78a1fd9d34da6f9bf7f6e7f5be3a57ed9716e0efc8f0f94f1e47","src/send_stream.rs":"f717f64b75e368cf5fa4ca43078aa7c1b5aff48b4f6266713e6fa7dc458328aa","src/sender.rs":"5f760988bdd6fbbd5956877a97abe7c17370dd531f68b751a9e4e4459583f87b","src/server.rs":"048aaac84e15d49fd25850294759107fe1855bbbc0481c16f8bd888d8f2a8f6d","src/stats.rs":"257ab1242ea2e6bfac0900e6c4bdad794bc67b666930323d24e022e46b9be82b","src/stream_id.rs":"fd07cbb81709a54bdb0659f676ef851cd145c004b817044ede5b21e54fdb60e4","src/streams.rs":"062b1b61edd1a76a86914f2cc1ca007c03edd9136c0c3409d960ddb805805fc6","src/tparams.rs":"10d62ac64865e0606c3c14141f9674631c610b3f042e274e110bdcef5d388491","src/tracking.rs":"f9a9aa01abc79fdd7a2cfb2c3ae342b9ab709e6a2a11076ec5c475fc89c1f598","src/version.rs":"182484ed9ecc2e17cab73cc61914a86a2d206936cab313825ae76fd37eeade77","tests/common/mod.rs":"a6584d268da0157190f8f61842a655ffe81ee68702b3e6569ae300a169080eab","tests/conn_vectors.rs":"997702f4d8b8fa3b987b33077a0eb325e968b25b61fb4703532f8d97e1d4c98c","tests/connection.rs":"d1bc28294d70a5a484eb869162115e399862742caa791749fbd6b923b702b7cc","tests/network.rs":"9e30b8610124250262fceef27d09fdecf2d6e9c3a96b1e676ff4189b9e06d5ba","tests/retry.rs":"3225b64c0c0ca918df12d94df21f6023091e72606701c1dc8c060ce3c1e09c52","tests/server.rs":"cb83de909d858950bfd75a789fc23c3c44fcdf1d965b63800b2c7b498507987f"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"8082901bf0395c450584af1084608a1568f051acf376b369a82d402d11519acc","benches/range_tracker.rs":"590dd1f81c92e89ce28af1efdda583d85240438bd9c4c68767286d22a299ad4b","benches/rx_stream_orderer.rs":"53a008357703251a18100521a12d8fa9443c5601ddc3cbd1b3c2899074da4c4f","benches/transfer.rs":"94eb0ec1a0a7d0a4863ddc1c6d006521e52c1f2e7f03c69428b18f7eb827d33f","src/ackrate.rs":"4bb882e1069a0707dc85338b75327e2910c93ee5f36575767a0d58c4c41c9d4f","src/addr_valid.rs":"03c0b2ff85254179c5d425b12acfdcc6b1ea5735aeb0f604b9b3603451b3ef0a","src/cc/classic_cc.rs":"b8007d623b07772806b676b760bcc1ccd5a37ddcd6a99f5562da39a5b03777df","src/cc/cubic.rs":"24c6913cc6346e5361007221c26e8096ece51583431fc3ab9c99e4ce4b0a9f5d","src/cc/mod.rs":"f4febe164fcbdc5881a53850eafd4011650ed394b7ec3d0977ec4803a1ec8543","src/cc/new_reno.rs":"25d0921005688e0f0666efd0a4931b4f8cd44363587d98e5b6404818c5d05dd4","src/cc/tests/cubic.rs":"87c6b95572fe5eebc54c46411f76026984d3bdaa75e356a87a16a5cc4b8dd4e1","src/cc/tests/mod.rs":"44f8df551e742ae1037cd1cdb85b2c1334c2e5ab3c23ed63d856dbc6b8743afc","src/cc/tests/new_reno.rs":"c5c39855353e99041abceba62bab2e5b58b77b92847eda1ef6f48ae91c8e4aea","src/cid.rs":"9686a3070c593cfca846d7549863728e31211b304b9fa876220f79bff5e24173","src/connection/dump.rs":"bd4fb55785fe42f5c94f7bcc14ccf4ae377d28b691fb55dbf1139ae9412b0ea9","src/connection/idle.rs":"b3bc2ad1290e54278d8703092d135eda973eb12316d1f6dffedaffdf25e2a47e","src/connection/mod.rs":"33eee67314c5f8c6dcd1085c6e39b8f0f5d1b5538b2e4bd50083dcd523a980cf","src/connection/params.rs":"38e0b47c8cc5fbe602e3174d7a70df410829bc240b42f21cebd10818e606ef7c","src/connection/saved.rs":"97eb19792be3c4d721057021a43ea50a52f89a3cfa583d3d3dcf5d9144b332f5","src/connection/state.rs":"b1d4bdda3479e7957d1949a969281ecd8a3d88f4fbaff6dcf7ebbb576759339c","src/connection/test_internal.rs":"f3ebfe97b25c9c716d41406066295e5aff4e96a3051ef4e2b5fb258282bbc14c","src/connection/tests/ackrate.rs":"4a2b835575850ae4a14209d3e51883ecb1e69afb44ef91b5e13a5e6cb7174fab","src/connection/tests/cc.rs":"d9a0f00a8f439c4ea8d4b6fa689fbde8bd283256afdd68ec4a27f6638b729704","src/connection/tests/close.rs":"5f245fd134bc0759ef0c83a6d53e0a8d5a8e58dcdf203c750ec9121940272461","src/connection/tests/datagram.rs":"908cfa6881963841d54ea2deb812f8eb217d68f149b5058036d979db1181abf0","src/connection/tests/ecn.rs":"3ff05893154fb6a895fe4453db7cc54684ba3bdf268a36b69c36c4070768d7b4","src/connection/tests/handshake.rs":"67a6f090ed89ef6c63129f7e662dc1cfff3f291711a866dff3d779caa40e51c7","src/connection/tests/idle.rs":"f3bcb12cd79cb8eabc969ce3fb0fab4eea26d6383b81a323c0e18ca9c42cfb59","src/connection/tests/keys.rs":"7c58b255e9732711e13f2a3e1daa13ac9481d8c919a32ca62e70c850845a6b38","src/connection/tests/migration.rs":"40d4feba9957de7eef7391009996016af1a3052fabc7659680b64796cf9fb8bf","src/connection/tests/mod.rs":"43b7745e9722333f7bc851c70ccdfdd1dc4da3991a4b821fac677664719e760f","src/connection/tests/null.rs":"38f76a4ea15e6b11634d4374cb0f2a68bd250e5d35831edfce0fa48deeaa420d","src/connection/tests/priority.rs":"dd3504f52d3fce7a96441624bc1c82c733e6bb556b9b79d24d0f4fb4efaf5a9e","src/connection/tests/recovery.rs":"7f28767f3cca2ff60e3dcfa803e12ef043486a222f54681a8faf2ea2fee564a1","src/connection/tests/resumption.rs":"1a0de0993cd325224fc79a3c094d22636d5b122ab1123d16265d4fafb23574bd","src/connection/tests/stream.rs":"3a6b23be63e1901ea479749d8132db86959279329121fe5d51b34c3fef4d4d05","src/connection/tests/vn.rs":"5307221790560598a7f771acf504fb153c753e005aca7370b772186f0f0c8655","src/connection/tests/zerortt.rs":"67f77721e33d9fa2691c5ea3ef4a90935987541d81f0f42fbcfca31e690b352a","src/crypto.rs":"416b73c06fcc2812cc252936bcb039fc13cf0b715e7e22a54314a3f72aee743c","src/ecn.rs":"3e9c9151dced7a1ec31e6a6d1bc5b0e4ce37cbb5cc361f5801be477c34249740","src/events.rs":"3cdd7d5496b2745626db4ceb863b5a91ae943090a43a5816a1f9bcf873fba2be","src/fc.rs":"ec9de1028286870c0adf88a92e1355acf13dede8b1e91179230df3263e3827a9","src/frame.rs":"4262717662f155e62bb29c9f0cac295bbae96076eb2d92c27052a35f979aa196","src/lib.rs":"6ed3732a020d0c9550ed295e660059b2747cbc647c24cc654cdde9de6f589a8f","src/pace.rs":"86a674ac4d086148ea297214910458c3705918bd627b996ba8bbb12f2c4bf99e","src/packet/mod.rs":"121a6dbfc3b3a9b6b5ebc94442d2d20a3148fc588dc1a1c4f9eb6c213741dca1","src/packet/retry.rs":"d5f999485f21b388a7383cd011fc6e96109c1a9fb5aef79b19017df6844271ff","src/path.rs":"8214a1683155bd0a82b53cc6bd957147286f6d4df527b5f3f640c266130122c0","src/qlog.rs":"c8ab11eca4712eba42cf26e17d07e88555e3976519a91f2d82d93afb1b420fc9","src/quic_datagrams.rs":"3d33ecb9e6e80c77b812e8260fc807352300fb2305a29b797259ae34c52b67c5","src/recovery.rs":"ad45dc9c94d716d9703601db40adc3eb4d353d5a173429d826829a2c50e52d9c","src/recv_stream.rs":"f21ae0bb786901bb7d726a94cb3352607b0057128beaa331808137f2f57a330b","src/rtt.rs":"4635dc0c401b78a1fd9d34da6f9bf7f6e7f5be3a57ed9716e0efc8f0f94f1e47","src/send_stream.rs":"ae0b6aa87649c1afee39b0e0a73bb713752f95f83199132f939e7f48ec2bbc7f","src/sender.rs":"ccde9e9a544670f403b82108ad04b5fecf8a00c1c3e26432ce0e23b2fa30436e","src/server.rs":"00b3e8d5ded84520bf30aadcb379332ad6ee2a0268a23a2893857a6c88673fd1","src/stats.rs":"257ab1242ea2e6bfac0900e6c4bdad794bc67b666930323d24e022e46b9be82b","src/stream_id.rs":"fd07cbb81709a54bdb0659f676ef851cd145c004b817044ede5b21e54fdb60e4","src/streams.rs":"062b1b61edd1a76a86914f2cc1ca007c03edd9136c0c3409d960ddb805805fc6","src/tparams.rs":"10d62ac64865e0606c3c14141f9674631c610b3f042e274e110bdcef5d388491","src/tracking.rs":"307e8cd007619e28000ce229df63ef73cfa07afb602e5399331c4624f787ad0c","src/version.rs":"182484ed9ecc2e17cab73cc61914a86a2d206936cab313825ae76fd37eeade77","tests/common/mod.rs":"7f9437d5efc38f4b9cabfece575e9168580e78e8638f46e538de58607f46ebb8","tests/conn_vectors.rs":"997702f4d8b8fa3b987b33077a0eb325e968b25b61fb4703532f8d97e1d4c98c","tests/connection.rs":"4c4d5adcde2413c105acc76567037fbeb1fe433e95e0aadf36d95e604541cb9b","tests/network.rs":"04921aa5af583e842e6d2176a898fbfea747e831bbe292b5ef8441eaf546b93a","tests/retry.rs":"a4250be3b104c754d6334784c3a6a258dd8b218645688fe3a61267ca7b773835","tests/server.rs":"e9eda467b0cb68e213f2b9ab124a35e05042f06d1aa3783deb1de1d8d1e1d7e7"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/neqo-transport/Cargo.toml b/third_party/rust/neqo-transport/Cargo.toml
index 9abdf9b984..78e551072e 100644
--- a/third_party/rust/neqo-transport/Cargo.toml
+++ b/third_party/rust/neqo-transport/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.74.0"
+rust-version = "1.76.0"
name = "neqo-transport"
-version = "0.7.5"
+version = "0.7.7"
authors = ["The Neqo Authors <necko@mozilla.com>"]
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
@@ -37,8 +37,12 @@ name = "range_tracker"
harness = false
required-features = ["bench"]
+[dependencies.enum-map]
+version = "2.7"
+default-features = false
+
[dependencies.indexmap]
-version = "1.9"
+version = "2.2"
default-features = false
[dependencies.log]
@@ -52,7 +56,7 @@ path = "../neqo-common"
path = "../neqo-crypto"
[dependencies.qlog]
-version = "0.12"
+version = "0.13"
default-features = false
[dependencies.smallvec]
@@ -64,15 +68,17 @@ version = "0.5"
features = ["html_reports"]
default-features = false
-[dev-dependencies.enum-map]
-version = "2.7"
-default-features = false
-
[dev-dependencies.test-fixture]
path = "../test-fixture"
[features]
bench = []
+build-fuzzing-corpus = [
+ "neqo-common/build-fuzzing-corpus",
+ "neqo-crypto/disable-encryption",
+ "neqo-crypto/disable-random",
+ "test-fixture/disable-random",
+]
disable-encryption = ["neqo-crypto/disable-encryption"]
[lints.clippy.pedantic]
diff --git a/third_party/rust/neqo-transport/src/cc/classic_cc.rs b/third_party/rust/neqo-transport/src/cc/classic_cc.rs
index f8bcee6722..6914e91f67 100644
--- a/third_party/rust/neqo-transport/src/cc/classic_cc.rs
+++ b/third_party/rust/neqo-transport/src/cc/classic_cc.rs
@@ -298,6 +298,14 @@ impl<T: WindowAdjustment> CongestionControl for ClassicCongestionControl<T> {
congestion || persistent_congestion
}
+ /// Report received ECN CE mark(s) to the congestion controller as a
+ /// congestion event.
+ ///
+ /// See <https://datatracker.ietf.org/doc/html/rfc9002#section-b.7>.
+ fn on_ecn_ce_received(&mut self, largest_acked_pkt: &SentPacket) -> bool {
+ self.on_congestion_event(largest_acked_pkt)
+ }
+
fn discard(&mut self, pkt: &SentPacket) {
if pkt.cc_outstanding() {
assert!(self.bytes_in_flight >= pkt.size);
@@ -488,8 +496,8 @@ impl<T: WindowAdjustment> ClassicCongestionControl<T> {
/// Handle a congestion event.
/// Returns true if this was a true congestion event.
fn on_congestion_event(&mut self, last_packet: &SentPacket) -> bool {
- // Start a new congestion event if lost packet was sent after the start
- // of the previous congestion recovery period.
+ // Start a new congestion event if lost or ECN CE marked packet was sent
+ // after the start of the previous congestion recovery period.
if !self.after_recovery_start(last_packet) {
return false;
}
@@ -538,7 +546,7 @@ impl<T: WindowAdjustment> ClassicCongestionControl<T> {
mod tests {
use std::time::{Duration, Instant};
- use neqo_common::qinfo;
+ use neqo_common::{qinfo, IpTosEcn};
use test_fixture::now;
use super::{
@@ -582,6 +590,7 @@ mod tests {
SentPacket::new(
PacketType::Short,
pn,
+ IpTosEcn::default(),
now() + t,
ack_eliciting,
Vec::new(),
@@ -795,6 +804,7 @@ mod tests {
SentPacket::new(
PacketType::Short,
u64::try_from(i).unwrap(),
+ IpTosEcn::default(),
by_pto(t),
true,
Vec::new(),
@@ -915,6 +925,7 @@ mod tests {
lost[0] = SentPacket::new(
lost[0].pt,
lost[0].pn,
+ lost[0].ecn_mark,
lost[0].time_sent,
false,
Vec::new(),
@@ -1015,11 +1026,12 @@ mod tests {
for _ in 0..packet_burst_size {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1039,11 +1051,12 @@ mod tests {
for _ in 0..ABOVE_APP_LIMIT_PKTS {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1082,11 +1095,12 @@ mod tests {
let p_lost = SentPacket::new(
PacketType::Short,
- 1, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 1,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packet_sent(&p_lost);
cwnd_is_default(&cc);
@@ -1095,11 +1109,12 @@ mod tests {
cwnd_is_halved(&cc);
let p_not_lost = SentPacket::new(
PacketType::Short,
- 2, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 2,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packet_sent(&p_not_lost);
now += RTT;
@@ -1118,11 +1133,12 @@ mod tests {
for _ in 0..packet_burst_size {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1148,11 +1164,12 @@ mod tests {
for _ in 0..ABOVE_APP_LIMIT_PKTS {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1180,4 +1197,26 @@ mod tests {
last_acked_bytes = cc.acked_bytes;
}
}
+
+ #[test]
+ fn ecn_ce() {
+ let mut cc = ClassicCongestionControl::new(NewReno::default());
+ let p_ce = SentPacket::new(
+ PacketType::Short,
+ 1,
+ IpTosEcn::default(),
+ now(),
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
+ );
+ cc.on_packet_sent(&p_ce);
+ cwnd_is_default(&cc);
+ assert_eq!(cc.state, State::SlowStart);
+
+ // Signal congestion (ECN CE) and thus change state to recovery start.
+ cc.on_ecn_ce_received(&p_ce);
+ cwnd_is_halved(&cc);
+ assert_eq!(cc.state, State::RecoveryStart);
+ }
}
diff --git a/third_party/rust/neqo-transport/src/cc/mod.rs b/third_party/rust/neqo-transport/src/cc/mod.rs
index 486d15e67e..2adffbc0c4 100644
--- a/third_party/rust/neqo-transport/src/cc/mod.rs
+++ b/third_party/rust/neqo-transport/src/cc/mod.rs
@@ -53,6 +53,9 @@ pub trait CongestionControl: Display + Debug {
lost_packets: &[SentPacket],
) -> bool;
+ /// Returns true if the congestion window was reduced.
+ fn on_ecn_ce_received(&mut self, largest_acked_pkt: &SentPacket) -> bool;
+
#[must_use]
fn recovery_packet(&self) -> bool;
diff --git a/third_party/rust/neqo-transport/src/cc/tests/cubic.rs b/third_party/rust/neqo-transport/src/cc/tests/cubic.rs
index 2e0200fd6d..8ff591cb47 100644
--- a/third_party/rust/neqo-transport/src/cc/tests/cubic.rs
+++ b/third_party/rust/neqo-transport/src/cc/tests/cubic.rs
@@ -12,6 +12,7 @@ use std::{
time::{Duration, Instant},
};
+use neqo_common::IpTosEcn;
use test_fixture::now;
use crate::{
@@ -41,11 +42,12 @@ fn fill_cwnd(cc: &mut ClassicCongestionControl<Cubic>, mut next_pn: u64, now: In
while cc.bytes_in_flight() < cc.cwnd() {
let sent = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packet_sent(&sent);
next_pn += 1;
@@ -56,11 +58,12 @@ fn fill_cwnd(cc: &mut ClassicCongestionControl<Cubic>, mut next_pn: u64, now: In
fn ack_packet(cc: &mut ClassicCongestionControl<Cubic>, pn: u64, now: Instant) {
let acked = SentPacket::new(
PacketType::Short,
- pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packets_acked(&[acked], &RTT_ESTIMATE, now);
}
@@ -69,11 +72,12 @@ fn packet_lost(cc: &mut ClassicCongestionControl<Cubic>, pn: u64) {
const PTO: Duration = Duration::from_millis(120);
let p_lost = SentPacket::new(
PacketType::Short,
- pn, // pn
- now(), // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ pn,
+ IpTosEcn::default(),
+ now(),
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packets_lost(None, None, PTO, &[p_lost]);
}
diff --git a/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs b/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs
index 4cc20de5a7..0cc560bf2b 100644
--- a/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs
+++ b/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs
@@ -8,6 +8,7 @@
use std::time::Duration;
+use neqo_common::IpTosEcn;
use test_fixture::now;
use crate::{
@@ -44,59 +45,66 @@ fn issue_876() {
let sent_packets = &[
SentPacket::new(
PacketType::Short,
- 1, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE - 1, // size
+ 1,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE - 1,
),
SentPacket::new(
PacketType::Short,
- 2, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE - 2, // size
+ 2,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE - 2,
),
SentPacket::new(
PacketType::Short,
- 3, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 3,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 4, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 4,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 5, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 5,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 6, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 6,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 7, // pn
- time_after, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE - 3, // size
+ 7,
+ IpTosEcn::default(),
+ time_after,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE - 3,
),
];
@@ -146,11 +154,12 @@ fn issue_1465() {
let mut next_packet = |now| {
let p = SentPacket::new(
PacketType::Short,
- pn, // pn
- now, // time_sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
pn += 1;
p
diff --git a/third_party/rust/neqo-transport/src/connection/mod.rs b/third_party/rust/neqo-transport/src/connection/mod.rs
index 8522507a69..f955381414 100644
--- a/third_party/rust/neqo-transport/src/connection/mod.rs
+++ b/third_party/rust/neqo-transport/src/connection/mod.rs
@@ -19,7 +19,7 @@ use std::{
use neqo_common::{
event::Provider as EventProvider, hex, hex_snip_middle, hrtime, qdebug, qerror, qinfo,
- qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, IpTos, Role,
+ qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, Role,
};
use neqo_crypto::{
agent::CertificateInfo, Agent, AntiReplay, AuthenticationStatus, Cipher, Client, Group,
@@ -35,6 +35,7 @@ use crate::{
ConnectionIdRef, ConnectionIdStore, LOCAL_ACTIVE_CID_LIMIT,
},
crypto::{Crypto, CryptoDxState, CryptoSpace},
+ ecn::EcnCount,
events::{ConnectionEvent, ConnectionEvents, OutgoingDatagramOutcome},
frame::{
CloseError, Frame, FrameType, FRAME_TYPE_CONNECTION_CLOSE_APPLICATION,
@@ -46,7 +47,7 @@ use crate::{
quic_datagrams::{DatagramTracking, QuicDatagrams},
recovery::{LossRecovery, RecoveryToken, SendProfile},
recv_stream::RecvStreamStats,
- rtt::GRANULARITY,
+ rtt::{RttEstimate, GRANULARITY},
send_stream::SendStream,
stats::{Stats, StatsCell},
stream_id::StreamType,
@@ -55,9 +56,9 @@ use crate::{
self, TransportParameter, TransportParameterId, TransportParameters,
TransportParametersHandler,
},
- tracking::{AckTracker, PacketNumberSpace, SentPacket},
+ tracking::{AckTracker, PacketNumberSpace, RecvdPackets, SentPacket},
version::{Version, WireVersion},
- AppError, ConnectionError, Error, Res, StreamId,
+ AppError, CloseReason, Error, Res, StreamId,
};
mod dump;
@@ -291,7 +292,7 @@ impl Debug for Connection {
"{:?} Connection: {:?} {:?}",
self.role,
self.state,
- self.paths.primary_fallible()
+ self.paths.primary()
)
}
}
@@ -591,7 +592,11 @@ impl Connection {
fn make_resumption_token(&mut self) -> ResumptionToken {
debug_assert_eq!(self.role, Role::Client);
debug_assert!(self.crypto.has_resumption_token());
- let rtt = self.paths.primary().borrow().rtt().estimate();
+ let rtt = self.paths.primary().map_or_else(
+ || RttEstimate::default().estimate(),
+ |p| p.borrow().rtt().estimate(),
+ );
+
self.crypto
.create_resumption_token(
self.new_token.take_token(),
@@ -610,11 +615,10 @@ impl Connection {
/// a value of this approximate order. Don't use this for loss recovery,
/// only use it where a more precise value is not important.
fn pto(&self) -> Duration {
- self.paths
- .primary()
- .borrow()
- .rtt()
- .pto(PacketNumberSpace::ApplicationData)
+ self.paths.primary().map_or_else(
+ || RttEstimate::default().pto(PacketNumberSpace::ApplicationData),
+ |p| p.borrow().rtt().pto(PacketNumberSpace::ApplicationData),
+ )
}
fn create_resumption_token(&mut self, now: Instant) {
@@ -746,7 +750,12 @@ impl Connection {
if !init_token.is_empty() {
self.address_validation = AddressValidationInfo::NewToken(init_token.to_vec());
}
- self.paths.primary().borrow_mut().rtt_mut().set_initial(rtt);
+ self.paths
+ .primary()
+ .ok_or(Error::InternalError)?
+ .borrow_mut()
+ .rtt_mut()
+ .set_initial(rtt);
self.set_initial_limits();
// Start up TLS, which has the effect of setting up all the necessary
// state for 0-RTT. This only stages the CRYPTO frames.
@@ -786,7 +795,7 @@ impl Connection {
// If we are able, also send a NEW_TOKEN frame.
// This should be recording all remote addresses that are valid,
// but there are just 0 or 1 in the current implementation.
- if let Some(path) = self.paths.primary_fallible() {
+ if let Some(path) = self.paths.primary() {
if let Some(token) = self
.address_validation
.generate_new_token(path.borrow().remote_address(), now)
@@ -858,7 +867,7 @@ impl Connection {
#[must_use]
pub fn stats(&self) -> Stats {
let mut v = self.stats.borrow().clone();
- if let Some(p) = self.paths.primary_fallible() {
+ if let Some(p) = self.paths.primary() {
let p = p.borrow();
v.rtt = p.rtt().estimate();
v.rttvar = p.rtt().rttvar();
@@ -880,7 +889,7 @@ impl Connection {
let msg = format!("{v:?}");
#[cfg(not(debug_assertions))]
let msg = "";
- let error = ConnectionError::Transport(v.clone());
+ let error = CloseReason::Transport(v.clone());
match &self.state {
State::Closing { error: err, .. }
| State::Draining { error: err, .. }
@@ -895,14 +904,14 @@ impl Connection {
State::WaitInitial => {
// We don't have any state yet, so don't bother with
// the closing state, just send one CONNECTION_CLOSE.
- if let Some(path) = path.or_else(|| self.paths.primary_fallible()) {
+ if let Some(path) = path.or_else(|| self.paths.primary()) {
self.state_signaling
.close(path, error.clone(), frame_type, msg);
}
self.set_state(State::Closed(error));
}
_ => {
- if let Some(path) = path.or_else(|| self.paths.primary_fallible()) {
+ if let Some(path) = path.or_else(|| self.paths.primary()) {
self.state_signaling
.close(path, error.clone(), frame_type, msg);
if matches!(v, Error::KeysExhausted) {
@@ -951,9 +960,7 @@ impl Connection {
let pto = self.pto();
if self.idle_timeout.expired(now, pto) {
qinfo!([self], "idle timeout expired");
- self.set_state(State::Closed(ConnectionError::Transport(
- Error::IdleTimeout,
- )));
+ self.set_state(State::Closed(CloseReason::Transport(Error::IdleTimeout)));
return;
}
@@ -962,9 +969,11 @@ impl Connection {
let res = self.crypto.states.check_key_update(now);
self.absorb_error(now, res);
- let lost = self.loss_recovery.timeout(&self.paths.primary(), now);
- self.handle_lost_packets(&lost);
- qlog::packets_lost(&mut self.qlog, &lost);
+ if let Some(path) = self.paths.primary() {
+ let lost = self.loss_recovery.timeout(&path, now);
+ self.handle_lost_packets(&lost);
+ qlog::packets_lost(&mut self.qlog, &lost);
+ }
if self.release_resumption_token_timer.is_some() {
self.create_resumption_token(now);
@@ -1014,7 +1023,7 @@ impl Connection {
delays.push(ack_time);
}
- if let Some(p) = self.paths.primary_fallible() {
+ if let Some(p) = self.paths.primary() {
let path = p.borrow();
let rtt = path.rtt();
let pto = rtt.pto(PacketNumberSpace::ApplicationData);
@@ -1102,7 +1111,15 @@ impl Connection {
self.input(d, now, now);
self.process_saved(now);
}
- self.process_output(now)
+ #[allow(clippy::let_and_return)]
+ let output = self.process_output(now);
+ #[cfg(all(feature = "build-fuzzing-corpus", test))]
+ if self.test_frame_writer.is_none() {
+ if let Some(d) = output.clone().dgram() {
+ neqo_common::write_item_to_fuzzing_corpus("packet", &d);
+ }
+ }
+ output
}
fn handle_retry(&mut self, packet: &PublicPacket, now: Instant) {
@@ -1123,7 +1140,13 @@ impl Connection {
}
// At this point, we should only have the connection ID that we generated.
// Update to the one that the server prefers.
- let path = self.paths.primary();
+ let Some(path) = self.paths.primary() else {
+ self.stats
+ .borrow_mut()
+ .pkt_dropped("Retry without an existing path");
+ return;
+ };
+
path.borrow_mut().set_remote_cid(packet.scid());
let retry_scid = ConnectionId::from(packet.scid());
@@ -1151,8 +1174,9 @@ impl Connection {
fn discard_keys(&mut self, space: PacketNumberSpace, now: Instant) {
if self.crypto.discard(space) {
qdebug!([self], "Drop packet number space {}", space);
- let primary = self.paths.primary();
- self.loss_recovery.discard(&primary, space, now);
+ if let Some(path) = self.paths.primary() {
+ self.loss_recovery.discard(&path, space, now);
+ }
self.acks.drop_space(space);
}
}
@@ -1180,7 +1204,7 @@ impl Connection {
qdebug!([self], "Stateless reset: {}", hex(&d[d.len() - 16..]));
self.state_signaling.reset();
self.set_state(State::Draining {
- error: ConnectionError::Transport(Error::StatelessReset),
+ error: CloseReason::Transport(Error::StatelessReset),
timeout: self.get_closing_period_time(now),
});
Err(Error::StatelessReset)
@@ -1227,8 +1251,9 @@ impl Connection {
assert_ne!(self.version, version);
qinfo!([self], "Version negotiation: trying {:?}", version);
- let local_addr = self.paths.primary().borrow().local_address();
- let remote_addr = self.paths.primary().borrow().remote_address();
+ let path = self.paths.primary().ok_or(Error::NoAvailablePath)?;
+ let local_addr = path.borrow().local_address();
+ let remote_addr = path.borrow().remote_address();
let conn_params = self
.conn_params
.clone()
@@ -1256,7 +1281,7 @@ impl Connection {
} else {
qinfo!([self], "Version negotiation: failed with {:?}", supported);
// This error goes straight to closed.
- self.set_state(State::Closed(ConnectionError::Transport(
+ self.set_state(State::Closed(CloseReason::Transport(
Error::VersionNegotiation,
)));
Err(Error::VersionNegotiation)
@@ -1417,6 +1442,13 @@ impl Connection {
migrate: bool,
now: Instant,
) {
+ let space = PacketNumberSpace::from(packet.packet_type());
+ if let Some(space) = self.acks.get_mut(space) {
+ *space.ecn_marks() += d.tos().into();
+ } else {
+ qtrace!("Not tracking ECN for dropped packet number space");
+ }
+
if self.state == State::WaitInitial {
self.start_handshake(path, packet, now);
}
@@ -1491,6 +1523,16 @@ impl Connection {
d.tos(),
);
+ #[cfg(feature = "build-fuzzing-corpus")]
+ if packet.packet_type() == PacketType::Initial {
+ let target = if self.role == Role::Client {
+ "server_initial"
+ } else {
+ "client_initial"
+ };
+ neqo_common::write_item_to_fuzzing_corpus(target, &payload[..]);
+ }
+
qlog::packet_received(&mut self.qlog, &packet, &payload);
let space = PacketNumberSpace::from(payload.packet_type());
if self.acks.get_mut(space).unwrap().is_duplicate(payload.pn()) {
@@ -1562,7 +1604,11 @@ impl Connection {
let mut probing = true;
let mut d = Decoder::from(&packet[..]);
while d.remaining() > 0 {
+ #[cfg(feature = "build-fuzzing-corpus")]
+ let pos = d.offset();
let f = Frame::decode(&mut d)?;
+ #[cfg(feature = "build-fuzzing-corpus")]
+ neqo_common::write_item_to_fuzzing_corpus("frame", &packet[pos..d.offset()]);
ack_eliciting |= f.ack_eliciting();
probing &= f.path_probing();
let t = f.get_type();
@@ -1623,10 +1669,15 @@ impl Connection {
if let Some(cid) = self.connection_ids.next() {
self.paths.make_permanent(path, None, cid);
Ok(())
- } else if self.paths.primary().borrow().remote_cid().is_empty() {
- self.paths
- .make_permanent(path, None, ConnectionIdEntry::empty_remote());
- Ok(())
+ } else if let Some(primary) = self.paths.primary() {
+ if primary.borrow().remote_cid().is_empty() {
+ self.paths
+ .make_permanent(path, None, ConnectionIdEntry::empty_remote());
+ Ok(())
+ } else {
+ qtrace!([self], "Unable to make path permanent: {}", path.borrow());
+ Err(Error::InvalidMigration)
+ }
} else {
qtrace!([self], "Unable to make path permanent: {}", path.borrow());
Err(Error::InvalidMigration)
@@ -1719,8 +1770,10 @@ impl Connection {
// Pointless migration is pointless.
return Err(Error::InvalidMigration);
}
- let local = local.unwrap_or_else(|| self.paths.primary().borrow().local_address());
- let remote = remote.unwrap_or_else(|| self.paths.primary().borrow().remote_address());
+
+ let path = self.paths.primary().ok_or(Error::InvalidMigration)?;
+ let local = local.unwrap_or_else(|| path.borrow().local_address());
+ let remote = remote.unwrap_or_else(|| path.borrow().remote_address());
if mem::discriminant(&local.ip()) != mem::discriminant(&remote.ip()) {
// Can't mix address families.
@@ -1773,7 +1826,12 @@ impl Connection {
// has to use the existing address. So only pay attention to a preferred
// address from the same family as is currently in use. More thought will
// be needed to work out how to get addresses from a different family.
- let prev = self.paths.primary().borrow().remote_address();
+ let prev = self
+ .paths
+ .primary()
+ .ok_or(Error::NoAvailablePath)?
+ .borrow()
+ .remote_address();
let remote = match prev.ip() {
IpAddr::V4(_) => addr.ipv4().map(SocketAddr::V4),
IpAddr::V6(_) => addr.ipv6().map(SocketAddr::V6),
@@ -1937,20 +1995,15 @@ impl Connection {
}
}
- self.streams
- .write_frames(TransmissionPriority::Critical, builder, tokens, frame_stats);
- if builder.is_full() {
- return;
- }
-
- self.streams.write_frames(
+ for prio in [
+ TransmissionPriority::Critical,
TransmissionPriority::Important,
- builder,
- tokens,
- frame_stats,
- );
- if builder.is_full() {
- return;
+ ] {
+ self.streams
+ .write_frames(prio, builder, tokens, frame_stats);
+ if builder.is_full() {
+ return;
+ }
}
// NEW_CONNECTION_ID, RETIRE_CONNECTION_ID, and ACK_FREQUENCY.
@@ -1958,21 +2011,18 @@ impl Connection {
if builder.is_full() {
return;
}
- self.paths.write_frames(builder, tokens, frame_stats);
- if builder.is_full() {
- return;
- }
- self.streams
- .write_frames(TransmissionPriority::High, builder, tokens, frame_stats);
+ self.paths.write_frames(builder, tokens, frame_stats);
if builder.is_full() {
return;
}
- self.streams
- .write_frames(TransmissionPriority::Normal, builder, tokens, frame_stats);
- if builder.is_full() {
- return;
+ for prio in [TransmissionPriority::High, TransmissionPriority::Normal] {
+ self.streams
+ .write_frames(prio, builder, tokens, &mut stats.frame_tx);
+ if builder.is_full() {
+ return;
+ }
}
// Datagrams are best-effort and unreliable. Let streams starve them for now.
@@ -1981,9 +2031,9 @@ impl Connection {
return;
}
- let frame_stats = &mut stats.frame_tx;
// CRYPTO here only includes NewSessionTicket, plus NEW_TOKEN.
// Both of these are only used for resumption and so can be relatively low priority.
+ let frame_stats = &mut stats.frame_tx;
self.crypto.write_frame(
PacketNumberSpace::ApplicationData,
builder,
@@ -1993,6 +2043,7 @@ impl Connection {
if builder.is_full() {
return;
}
+
self.new_token.write_frames(builder, tokens, frame_stats);
if builder.is_full() {
return;
@@ -2002,10 +2053,8 @@ impl Connection {
.write_frames(TransmissionPriority::Low, builder, tokens, frame_stats);
#[cfg(test)]
- {
- if let Some(w) = &mut self.test_frame_writer {
- w.write_frames(builder);
- }
+ if let Some(w) = &mut self.test_frame_writer {
+ w.write_frames(builder);
}
}
@@ -2138,6 +2187,40 @@ impl Connection {
(tokens, ack_eliciting, padded)
}
+ fn write_closing_frames(
+ &mut self,
+ close: &ClosingFrame,
+ builder: &mut PacketBuilder,
+ space: PacketNumberSpace,
+ now: Instant,
+ path: &PathRef,
+ tokens: &mut Vec<RecoveryToken>,
+ ) {
+ if builder.remaining() > ClosingFrame::MIN_LENGTH + RecvdPackets::USEFUL_ACK_LEN {
+ // Include an ACK frame with the CONNECTION_CLOSE.
+ let limit = builder.limit();
+ builder.set_limit(limit - ClosingFrame::MIN_LENGTH);
+ self.acks.immediate_ack(now);
+ self.acks.write_frame(
+ space,
+ now,
+ path.borrow().rtt().estimate(),
+ builder,
+ tokens,
+ &mut self.stats.borrow_mut().frame_tx,
+ );
+ builder.set_limit(limit);
+ }
+ // CloseReason::Application is only allowed at 1RTT.
+ let sanitized = if space == PacketNumberSpace::ApplicationData {
+ None
+ } else {
+ close.sanitize()
+ };
+ sanitized.as_ref().unwrap_or(close).write_frame(builder);
+ self.stats.borrow_mut().frame_tx.connection_close += 1;
+ }
+
/// Build a datagram, possibly from multiple packets (for different PN
/// spaces) and each containing 1+ frames.
#[allow(clippy::too_many_lines)] // Yeah, that's just the way it is.
@@ -2201,17 +2284,7 @@ impl Connection {
let payload_start = builder.len();
let (mut tokens, mut ack_eliciting, mut padded) = (Vec::new(), false, false);
if let Some(ref close) = closing_frame {
- // ConnectionError::Application is only allowed at 1RTT.
- let sanitized = if *space == PacketNumberSpace::ApplicationData {
- None
- } else {
- close.sanitize()
- };
- sanitized
- .as_ref()
- .unwrap_or(close)
- .write_frame(&mut builder);
- self.stats.borrow_mut().frame_tx.connection_close += 1;
+ self.write_closing_frames(close, &mut builder, *space, now, path, &mut tokens);
} else {
(tokens, ack_eliciting, padded) =
self.write_frames(path, *space, &profile, &mut builder, now);
@@ -2229,7 +2302,7 @@ impl Connection {
pt,
pn,
&builder.as_ref()[payload_start..],
- IpTos::default(), // TODO: set from path
+ path.borrow().tos(),
);
qlog::packet_sent(
&mut self.qlog,
@@ -2251,6 +2324,7 @@ impl Connection {
let sent = SentPacket::new(
pt,
pn,
+ path.borrow().tos().into(),
now,
ack_eliciting,
tokens,
@@ -2303,7 +2377,7 @@ impl Connection {
self.loss_recovery.on_packet_sent(path, initial);
}
path.borrow_mut().add_sent(packets.len());
- Ok(SendOption::Yes(path.borrow().datagram(packets)))
+ Ok(SendOption::Yes(path.borrow_mut().datagram(packets)))
}
}
@@ -2330,7 +2404,9 @@ impl Connection {
fn client_start(&mut self, now: Instant) -> Res<()> {
qdebug!([self], "client_start");
debug_assert_eq!(self.role, Role::Client);
- qlog::client_connection_started(&mut self.qlog, &self.paths.primary());
+ if let Some(path) = self.paths.primary() {
+ qlog::client_connection_started(&mut self.qlog, &path);
+ }
qlog::client_version_information_initiated(&mut self.qlog, self.conn_params.get_versions());
self.handshake(now, self.version, PacketNumberSpace::Initial, None)?;
@@ -2351,9 +2427,9 @@ impl Connection {
/// Close the connection.
pub fn close(&mut self, now: Instant, app_error: AppError, msg: impl AsRef<str>) {
- let error = ConnectionError::Application(app_error);
+ let error = CloseReason::Application(app_error);
let timeout = self.get_closing_period_time(now);
- if let Some(path) = self.paths.primary_fallible() {
+ if let Some(path) = self.paths.primary() {
self.state_signaling.close(path, error.clone(), 0, msg);
self.set_state(State::Closing { error, timeout });
} else {
@@ -2411,10 +2487,8 @@ impl Connection {
// That's OK, they can try guessing this.
ConnectionIdEntry::random_srt()
};
- self.paths
- .primary()
- .borrow_mut()
- .set_reset_token(reset_token);
+ let path = self.paths.primary().ok_or(Error::NoAvailablePath)?;
+ path.borrow_mut().set_reset_token(reset_token);
let max_ad = Duration::from_millis(remote.get_integer(tparams::MAX_ACK_DELAY));
let min_ad = if remote.has_value(tparams::MIN_ACK_DELAY) {
@@ -2426,11 +2500,8 @@ impl Connection {
} else {
None
};
- self.paths.primary().borrow_mut().set_ack_delay(
- max_ad,
- min_ad,
- self.conn_params.get_ack_ratio(),
- );
+ path.borrow_mut()
+ .set_ack_delay(max_ad, min_ad, self.conn_params.get_ack_ratio());
let max_active_cids = remote.get_integer(tparams::ACTIVE_CONNECTION_ID_LIMIT);
self.cid_manager.set_limit(max_active_cids);
@@ -2673,10 +2744,18 @@ impl Connection {
ack_delay,
first_ack_range,
ack_ranges,
+ ecn_count,
} => {
let ranges =
Frame::decode_ack_frame(largest_acknowledged, first_ack_range, &ack_ranges)?;
- self.handle_ack(space, largest_acknowledged, ranges, ack_delay, now);
+ self.handle_ack(
+ space,
+ largest_acknowledged,
+ ranges,
+ ecn_count,
+ ack_delay,
+ now,
+ );
}
Frame::Crypto { offset, data } => {
qtrace!(
@@ -2747,7 +2826,6 @@ impl Connection {
reason_phrase,
} => {
self.stats.borrow_mut().frame_rx.connection_close += 1;
- let reason_phrase = String::from_utf8_lossy(&reason_phrase);
qinfo!(
[self],
"ConnectionClose received. Error code: {:?} frame type {:x} reason {}",
@@ -2768,7 +2846,7 @@ impl Connection {
FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT,
)
};
- let error = ConnectionError::Transport(detail);
+ let error = CloseReason::Transport(detail);
self.state_signaling
.drain(Rc::clone(path), error.clone(), frame_type, "");
self.set_state(State::Draining {
@@ -2853,6 +2931,7 @@ impl Connection {
space: PacketNumberSpace,
largest_acknowledged: u64,
ack_ranges: R,
+ ack_ecn: Option<EcnCount>,
ack_delay: u64,
now: Instant,
) where
@@ -2861,11 +2940,15 @@ impl Connection {
{
qdebug!([self], "Rx ACK space={}, ranges={:?}", space, ack_ranges);
+ let Some(path) = self.paths.primary() else {
+ return;
+ };
let (acked_packets, lost_packets) = self.loss_recovery.on_ack_received(
- &self.paths.primary(),
+ &path,
space,
largest_acknowledged,
ack_ranges,
+ ack_ecn,
self.decode_ack_delay(ack_delay),
now,
);
@@ -2903,8 +2986,10 @@ impl Connection {
qdebug!([self], "0-RTT rejected");
// Tell 0-RTT packets that they were "lost".
- let dropped = self.loss_recovery.drop_0rtt(&self.paths.primary(), now);
- self.handle_lost_packets(&dropped);
+ if let Some(path) = self.paths.primary() {
+ let dropped = self.loss_recovery.drop_0rtt(&path, now);
+ self.handle_lost_packets(&dropped);
+ }
self.streams.zero_rtt_rejected();
@@ -2923,7 +3008,7 @@ impl Connection {
// Remove the randomized client CID from the list of acceptable CIDs.
self.cid_manager.remove_odcid();
// Mark the path as validated, if it isn't already.
- let path = self.paths.primary();
+ let path = self.paths.primary().ok_or(Error::NoAvailablePath)?;
path.borrow_mut().set_valid(now);
// Generate a qlog event that the server connection started.
qlog::server_connection_started(&mut self.qlog, &path);
@@ -3191,7 +3276,7 @@ impl Connection {
else {
return Err(Error::NotAvailable);
};
- let path = self.paths.primary_fallible().ok_or(Error::NotAvailable)?;
+ let path = self.paths.primary().ok_or(Error::NotAvailable)?;
let mtu = path.borrow().mtu();
let encoder = Encoder::with_capacity(mtu);
diff --git a/third_party/rust/neqo-transport/src/connection/state.rs b/third_party/rust/neqo-transport/src/connection/state.rs
index cc2f6e30d2..e76f937938 100644
--- a/third_party/rust/neqo-transport/src/connection/state.rs
+++ b/third_party/rust/neqo-transport/src/connection/state.rs
@@ -21,7 +21,7 @@ use crate::{
packet::PacketBuilder,
path::PathRef,
recovery::RecoveryToken,
- ConnectionError, Error,
+ CloseReason, Error,
};
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -42,14 +42,14 @@ pub enum State {
Connected,
Confirmed,
Closing {
- error: ConnectionError,
+ error: CloseReason,
timeout: Instant,
},
Draining {
- error: ConnectionError,
+ error: CloseReason,
timeout: Instant,
},
- Closed(ConnectionError),
+ Closed(CloseReason),
}
impl State {
@@ -67,7 +67,7 @@ impl State {
}
#[must_use]
- pub fn error(&self) -> Option<&ConnectionError> {
+ pub fn error(&self) -> Option<&CloseReason> {
if let Self::Closing { error, .. } | Self::Draining { error, .. } | Self::Closed(error) =
self
{
@@ -116,7 +116,7 @@ impl Ord for State {
#[derive(Debug, Clone)]
pub struct ClosingFrame {
path: PathRef,
- error: ConnectionError,
+ error: CloseReason,
frame_type: FrameType,
reason_phrase: Vec<u8>,
}
@@ -124,7 +124,7 @@ pub struct ClosingFrame {
impl ClosingFrame {
fn new(
path: PathRef,
- error: ConnectionError,
+ error: CloseReason,
frame_type: FrameType,
message: impl AsRef<str>,
) -> Self {
@@ -142,12 +142,12 @@ impl ClosingFrame {
}
pub fn sanitize(&self) -> Option<Self> {
- if let ConnectionError::Application(_) = self.error {
+ if let CloseReason::Application(_) = self.error {
// The default CONNECTION_CLOSE frame that is sent when an application
// error code needs to be sent in an Initial or Handshake packet.
Some(Self {
path: Rc::clone(&self.path),
- error: ConnectionError::Transport(Error::ApplicationError),
+ error: CloseReason::Transport(Error::ApplicationError),
frame_type: 0,
reason_phrase: Vec::new(),
})
@@ -156,19 +156,22 @@ impl ClosingFrame {
}
}
+ /// Length of a closing frame with a truncated `reason_length`. Allow 8 bytes for the reason
+ /// phrase to ensure that if it needs to be truncated there is still at least a few bytes of
+ /// the value.
+ pub const MIN_LENGTH: usize = 1 + 8 + 8 + 2 + 8;
+
pub fn write_frame(&self, builder: &mut PacketBuilder) {
- // Allow 8 bytes for the reason phrase to ensure that if it needs to be
- // truncated there is still at least a few bytes of the value.
- if builder.remaining() < 1 + 8 + 8 + 2 + 8 {
+ if builder.remaining() < ClosingFrame::MIN_LENGTH {
return;
}
match &self.error {
- ConnectionError::Transport(e) => {
+ CloseReason::Transport(e) => {
builder.encode_varint(FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT);
builder.encode_varint(e.code());
builder.encode_varint(self.frame_type);
}
- ConnectionError::Application(code) => {
+ CloseReason::Application(code) => {
builder.encode_varint(FRAME_TYPE_CONNECTION_CLOSE_APPLICATION);
builder.encode_varint(*code);
}
@@ -209,10 +212,6 @@ pub enum StateSignaling {
impl StateSignaling {
pub fn handshake_done(&mut self) {
if !matches!(self, Self::Idle) {
- debug_assert!(
- false,
- "StateSignaling must be in Idle state but is in {self:?} state.",
- );
return;
}
*self = Self::HandshakeDone;
@@ -231,7 +230,7 @@ impl StateSignaling {
pub fn close(
&mut self,
path: PathRef,
- error: ConnectionError,
+ error: CloseReason,
frame_type: FrameType,
message: impl AsRef<str>,
) {
@@ -243,7 +242,7 @@ impl StateSignaling {
pub fn drain(
&mut self,
path: PathRef,
- error: ConnectionError,
+ error: CloseReason,
frame_type: FrameType,
message: impl AsRef<str>,
) {
diff --git a/third_party/rust/neqo-transport/src/connection/tests/cc.rs b/third_party/rust/neqo-transport/src/connection/tests/cc.rs
index b708bc421d..f21f4e184f 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/cc.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/cc.rs
@@ -6,7 +6,7 @@
use std::{mem, time::Duration};
-use neqo_common::{qdebug, qinfo, Datagram};
+use neqo_common::{qdebug, qinfo, Datagram, IpTosEcn};
use super::{
super::Output, ack_bytes, assert_full_cwnd, connect_rtt_idle, cwnd, cwnd_avail, cwnd_packets,
@@ -36,9 +36,13 @@ fn cc_slow_start() {
assert!(cwnd_avail(&client) < ACK_ONLY_SIZE_LIMIT);
}
-#[test]
-/// Verify that CC moves to cong avoidance when a packet is marked lost.
-fn cc_slow_start_to_cong_avoidance_recovery_period() {
+#[derive(PartialEq, Eq, Clone, Copy)]
+enum CongestionSignal {
+ PacketLoss,
+ EcnCe,
+}
+
+fn cc_slow_start_to_cong_avoidance_recovery_period(congestion_signal: CongestionSignal) {
let mut client = default_client();
let mut server = default_server();
let now = connect_rtt_idle(&mut client, &mut server, DEFAULT_RTT);
@@ -78,9 +82,17 @@ fn cc_slow_start_to_cong_avoidance_recovery_period() {
assert_full_cwnd(&c_tx_dgrams, POST_HANDSHAKE_CWND * 2);
let flight2_largest = flight1_largest + u64::try_from(c_tx_dgrams.len()).unwrap();
- // Server: Receive and generate ack again, but drop first packet
+ // Server: Receive and generate ack again, but this time add congestion
+ // signal first.
now += DEFAULT_RTT / 2;
- c_tx_dgrams.remove(0);
+ match congestion_signal {
+ CongestionSignal::PacketLoss => {
+ c_tx_dgrams.remove(0);
+ }
+ CongestionSignal::EcnCe => {
+ c_tx_dgrams.last_mut().unwrap().set_tos(IpTosEcn::Ce.into());
+ }
+ }
let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams, now);
assert_eq!(
server.stats().frame_tx.largest_acknowledged,
@@ -98,6 +110,18 @@ fn cc_slow_start_to_cong_avoidance_recovery_period() {
}
#[test]
+/// Verify that CC moves to cong avoidance when a packet is marked lost.
+fn cc_slow_start_to_cong_avoidance_recovery_period_due_to_packet_loss() {
+ cc_slow_start_to_cong_avoidance_recovery_period(CongestionSignal::PacketLoss);
+}
+
+/// Verify that CC moves to cong avoidance when ACK is marked with ECN CE.
+#[test]
+fn cc_slow_start_to_cong_avoidance_recovery_period_due_to_ecn_ce() {
+ cc_slow_start_to_cong_avoidance_recovery_period(CongestionSignal::EcnCe);
+}
+
+#[test]
/// Verify that CC stays in recovery period when packet sent before start of
/// recovery period is acked.
fn cc_cong_avoidance_recovery_period_unchanged() {
diff --git a/third_party/rust/neqo-transport/src/connection/tests/close.rs b/third_party/rust/neqo-transport/src/connection/tests/close.rs
index 5351dd0d5c..7c620de17e 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/close.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/close.rs
@@ -14,13 +14,13 @@ use super::{
};
use crate::{
tparams::{self, TransportParameter},
- AppError, ConnectionError, Error, ERROR_APPLICATION_CLOSE,
+ AppError, CloseReason, Error, ERROR_APPLICATION_CLOSE,
};
fn assert_draining(c: &Connection, expected: &Error) {
assert!(c.state().closed());
if let State::Draining {
- error: ConnectionError::Transport(error),
+ error: CloseReason::Transport(error),
..
} = c.state()
{
@@ -40,7 +40,14 @@ fn connection_close() {
client.close(now, 42, "");
+ let stats_before = client.stats().frame_tx;
let out = client.process(None, now);
+ let stats_after = client.stats().frame_tx;
+ assert_eq!(
+ stats_after.connection_close,
+ stats_before.connection_close + 1
+ );
+ assert_eq!(stats_after.ack, stats_before.ack + 1);
server.process_input(&out.dgram().unwrap(), now);
assert_draining(&server, &Error::PeerApplicationError(42));
@@ -57,7 +64,14 @@ fn connection_close_with_long_reason_string() {
let long_reason = String::from_utf8([0x61; 2048].to_vec()).unwrap();
client.close(now, 42, long_reason);
+ let stats_before = client.stats().frame_tx;
let out = client.process(None, now);
+ let stats_after = client.stats().frame_tx;
+ assert_eq!(
+ stats_after.connection_close,
+ stats_before.connection_close + 1
+ );
+ assert_eq!(stats_after.ack, stats_before.ack + 1);
server.process_input(&out.dgram().unwrap(), now);
assert_draining(&server, &Error::PeerApplicationError(42));
@@ -100,7 +114,7 @@ fn bad_tls_version() {
let dgram = server.process(dgram.as_ref(), now()).dgram();
assert_eq!(
*server.state(),
- State::Closed(ConnectionError::Transport(Error::ProtocolViolation))
+ State::Closed(CloseReason::Transport(Error::ProtocolViolation))
);
assert!(dgram.is_some());
client.process_input(&dgram.unwrap(), now());
@@ -154,7 +168,6 @@ fn closing_and_draining() {
assert!(client_close.is_some());
let client_close_timer = client.process(None, now()).callback();
assert_ne!(client_close_timer, Duration::from_secs(0));
-
// The client will spit out the same packet in response to anything it receives.
let p3 = send_something(&mut server, now());
let client_close2 = client.process(Some(&p3), now()).dgram();
@@ -168,7 +181,7 @@ fn closing_and_draining() {
assert_eq!(end, Output::None);
assert_eq!(
*client.state(),
- State::Closed(ConnectionError::Application(APP_ERROR))
+ State::Closed(CloseReason::Application(APP_ERROR))
);
// When the server receives the close, it too should generate CONNECTION_CLOSE.
@@ -186,7 +199,7 @@ fn closing_and_draining() {
assert_eq!(end, Output::None);
assert_eq!(
*server.state(),
- State::Closed(ConnectionError::Transport(Error::PeerApplicationError(
+ State::Closed(CloseReason::Transport(Error::PeerApplicationError(
APP_ERROR
)))
);
diff --git a/third_party/rust/neqo-transport/src/connection/tests/datagram.rs b/third_party/rust/neqo-transport/src/connection/tests/datagram.rs
index ade8c753be..f1b64b3c8f 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/datagram.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/datagram.rs
@@ -19,7 +19,7 @@ use crate::{
packet::PacketBuilder,
quic_datagrams::MAX_QUIC_DATAGRAM,
send_stream::{RetransmissionPriority, TransmissionPriority},
- Connection, ConnectionError, ConnectionParameters, Error, StreamType,
+ CloseReason, Connection, ConnectionParameters, Error, StreamType,
};
const DATAGRAM_LEN_MTU: u64 = 1310;
@@ -362,10 +362,7 @@ fn dgram_no_allowed() {
client.process_input(&out, now());
- assert_error(
- &client,
- &ConnectionError::Transport(Error::ProtocolViolation),
- );
+ assert_error(&client, &CloseReason::Transport(Error::ProtocolViolation));
}
#[test]
@@ -383,10 +380,7 @@ fn dgram_too_big() {
client.process_input(&out, now());
- assert_error(
- &client,
- &ConnectionError::Transport(Error::ProtocolViolation),
- );
+ assert_error(&client, &CloseReason::Transport(Error::ProtocolViolation));
}
#[test]
@@ -587,7 +581,7 @@ fn datagram_fill() {
// Work out how much space we have for a datagram.
let space = {
- let p = client.paths.primary();
+ let p = client.paths.primary().unwrap();
let path = p.borrow();
// Minimum overhead is connection ID length, 1 byte short header, 1 byte packet number,
// 1 byte for the DATAGRAM frame type, and 16 bytes for the AEAD.
diff --git a/third_party/rust/neqo-transport/src/connection/tests/ecn.rs b/third_party/rust/neqo-transport/src/connection/tests/ecn.rs
new file mode 100644
index 0000000000..87957297e5
--- /dev/null
+++ b/third_party/rust/neqo-transport/src/connection/tests/ecn.rs
@@ -0,0 +1,392 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::time::Duration;
+
+use neqo_common::{Datagram, IpTos, IpTosEcn};
+use test_fixture::{
+ assertions::{assert_v4_path, assert_v6_path},
+ fixture_init, now, DEFAULT_ADDR_V4,
+};
+
+use super::send_something_with_modifier;
+use crate::{
+ connection::tests::{
+ connect_force_idle, connect_force_idle_with_modifier, default_client, default_server,
+ migration::get_cid, new_client, new_server, send_something,
+ },
+ ecn::ECN_TEST_COUNT,
+ ConnectionId, ConnectionParameters, StreamType,
+};
+
+fn assert_ecn_enabled(tos: IpTos) {
+ assert!(tos.is_ecn_marked());
+}
+
+fn assert_ecn_disabled(tos: IpTos) {
+ assert!(!tos.is_ecn_marked());
+}
+
+fn set_tos(mut d: Datagram, ecn: IpTosEcn) -> Datagram {
+ d.set_tos(ecn.into());
+ d
+}
+
+fn noop() -> fn(Datagram) -> Option<Datagram> {
+ Some
+}
+
+fn bleach() -> fn(Datagram) -> Option<Datagram> {
+ |d| Some(set_tos(d, IpTosEcn::NotEct))
+}
+
+fn remark() -> fn(Datagram) -> Option<Datagram> {
+ |d| {
+ if d.tos().is_ecn_marked() {
+ Some(set_tos(d, IpTosEcn::Ect1))
+ } else {
+ Some(d)
+ }
+ }
+}
+
+fn ce() -> fn(Datagram) -> Option<Datagram> {
+ |d| {
+ if d.tos().is_ecn_marked() {
+ Some(set_tos(d, IpTosEcn::Ce))
+ } else {
+ Some(d)
+ }
+ }
+}
+
+fn drop() -> fn(Datagram) -> Option<Datagram> {
+ |_| None
+}
+
+#[test]
+fn disables_on_loss() {
+ let now = now();
+ let mut client = default_client();
+ let mut server = default_server();
+ connect_force_idle(&mut client, &mut server);
+
+ // Right after the handshake, the ECN validation should still be in progress.
+ let client_pkt = send_something(&mut client, now);
+ assert_ecn_enabled(client_pkt.tos());
+
+ for _ in 0..ECN_TEST_COUNT {
+ send_something(&mut client, now);
+ }
+
+ // ECN should now be disabled.
+ let client_pkt = send_something(&mut client, now);
+ assert_ecn_disabled(client_pkt.tos());
+}
+
+/// This function performs a handshake over a path that modifies packets via `orig_path_modifier`.
+/// It then sends `burst` packets on that path, and then migrates to a new path that
+/// modifies packets via `new_path_modifier`. It sends `burst` packets on the new path.
+/// The function returns the TOS value of the last packet sent on the old path and the TOS value
+/// of the last packet sent on the new path to allow for verification of correct behavior.
+pub fn migration_with_modifiers(
+ orig_path_modifier: fn(Datagram) -> Option<Datagram>,
+ new_path_modifier: fn(Datagram) -> Option<Datagram>,
+ burst: usize,
+) -> (IpTos, IpTos, bool) {
+ fixture_init();
+ let mut client = new_client(ConnectionParameters::default().max_streams(StreamType::UniDi, 64));
+ let mut server = new_server(ConnectionParameters::default().max_streams(StreamType::UniDi, 64));
+
+ connect_force_idle_with_modifier(&mut client, &mut server, orig_path_modifier);
+ let mut now = now();
+
+ // Right after the handshake, the ECN validation should still be in progress.
+ let client_pkt = send_something(&mut client, now);
+ assert_ecn_enabled(client_pkt.tos());
+ server.process_input(&orig_path_modifier(client_pkt).unwrap(), now);
+
+ // Send some data on the current path.
+ for _ in 0..burst {
+ let client_pkt = send_something_with_modifier(&mut client, now, orig_path_modifier);
+ server.process_input(&client_pkt, now);
+ }
+
+ if let Some(ack) = server.process_output(now).dgram() {
+ client.process_input(&ack, now);
+ }
+
+ let client_pkt = send_something(&mut client, now);
+ let tos_before_migration = client_pkt.tos();
+ server.process_input(&orig_path_modifier(client_pkt).unwrap(), now);
+
+ client
+ .migrate(Some(DEFAULT_ADDR_V4), Some(DEFAULT_ADDR_V4), false, now)
+ .unwrap();
+
+ let mut migrated = false;
+ let probe = new_path_modifier(client.process_output(now).dgram().unwrap());
+ if let Some(probe) = probe {
+ assert_v4_path(&probe, true); // Contains PATH_CHALLENGE.
+ assert_eq!(client.stats().frame_tx.path_challenge, 1);
+ let probe_cid = ConnectionId::from(get_cid(&probe));
+
+ let resp = new_path_modifier(server.process(Some(&probe), now).dgram().unwrap()).unwrap();
+ assert_v4_path(&resp, true);
+ assert_eq!(server.stats().frame_tx.path_response, 1);
+ assert_eq!(server.stats().frame_tx.path_challenge, 1);
+
+ // Data continues to be exchanged on the old path.
+ let client_data = send_something_with_modifier(&mut client, now, orig_path_modifier);
+ assert_ne!(get_cid(&client_data), probe_cid);
+ assert_v6_path(&client_data, false);
+ server.process_input(&client_data, now);
+ let server_data = send_something_with_modifier(&mut server, now, orig_path_modifier);
+ assert_v6_path(&server_data, false);
+ client.process_input(&server_data, now);
+
+ // Once the client receives the probe response, it migrates to the new path.
+ client.process_input(&resp, now);
+ assert_eq!(client.stats().frame_rx.path_challenge, 1);
+ migrated = true;
+
+ let migrate_client = send_something_with_modifier(&mut client, now, new_path_modifier);
+ assert_v4_path(&migrate_client, true); // Responds to server probe.
+
+ // The server now sees the migration and will switch over.
+ // However, it will probe the old path again, even though it has just
+ // received a response to its last probe, because it needs to verify
+ // that the migration is genuine.
+ server.process_input(&migrate_client, now);
+ }
+
+ let stream_before = server.stats().frame_tx.stream;
+ let probe_old_server = send_something_with_modifier(&mut server, now, orig_path_modifier);
+ // This is just the double-check probe; no STREAM frames.
+ assert_v6_path(&probe_old_server, migrated);
+ assert_eq!(
+ server.stats().frame_tx.path_challenge,
+ if migrated { 2 } else { 0 }
+ );
+ assert_eq!(
+ server.stats().frame_tx.stream,
+ if migrated { stream_before } else { 1 }
+ );
+
+ if migrated {
+ // The server then sends data on the new path.
+ let migrate_server =
+ new_path_modifier(server.process_output(now).dgram().unwrap()).unwrap();
+ assert_v4_path(&migrate_server, false);
+ assert_eq!(server.stats().frame_tx.path_challenge, 2);
+ assert_eq!(server.stats().frame_tx.stream, stream_before + 1);
+
+ // The client receives these checks and responds to the probe, but uses the new path.
+ client.process_input(&migrate_server, now);
+ client.process_input(&probe_old_server, now);
+ let old_probe_resp = send_something_with_modifier(&mut client, now, new_path_modifier);
+ assert_v6_path(&old_probe_resp, true);
+ let client_confirmation = client.process_output(now).dgram().unwrap();
+ assert_v4_path(&client_confirmation, false);
+
+ // The server has now sent 2 packets, so it is blocked on the pacer. Wait.
+ let server_pacing = server.process_output(now).callback();
+ assert_ne!(server_pacing, Duration::new(0, 0));
+ // ... then confirm that the server sends on the new path still.
+ let server_confirmation =
+ send_something_with_modifier(&mut server, now + server_pacing, new_path_modifier);
+ assert_v4_path(&server_confirmation, false);
+ client.process_input(&server_confirmation, now);
+
+ // Send some data on the new path.
+ for _ in 0..burst {
+ now += client.process_output(now).callback();
+ let client_pkt = send_something_with_modifier(&mut client, now, new_path_modifier);
+ server.process_input(&client_pkt, now);
+ }
+
+ if let Some(ack) = server.process_output(now).dgram() {
+ client.process_input(&ack, now);
+ }
+ }
+
+ now += client.process_output(now).callback();
+ let mut client_pkt = send_something(&mut client, now);
+ while !migrated && client_pkt.source() == DEFAULT_ADDR_V4 {
+ client_pkt = send_something(&mut client, now);
+ }
+ let tos_after_migration = client_pkt.tos();
+ (tos_before_migration, tos_after_migration, migrated)
+}
+
+#[test]
+fn ecn_migration_zero_burst_all_cases() {
+ for orig_path_mod in &[noop(), bleach(), remark(), ce()] {
+ for new_path_mod in &[noop(), bleach(), remark(), ce(), drop()] {
+ let (before, after, migrated) =
+ migration_with_modifiers(*orig_path_mod, *new_path_mod, 0);
+ // Too few packets sent before and after migration to conclude ECN validation.
+ assert_ecn_enabled(before);
+ assert_ecn_enabled(after);
+ // Migration succeeds except if the new path drops ECN.
+ assert!(*new_path_mod == drop() || migrated);
+ }
+ }
+}
+
+#[test]
+fn ecn_migration_noop_bleach_data() {
+ let (before, after, migrated) = migration_with_modifiers(noop(), bleach(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to bleaching.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_noop_remark_data() {
+ let (before, after, migrated) = migration_with_modifiers(noop(), remark(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to remarking.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_noop_ce_data() {
+ let (before, after, migrated) = migration_with_modifiers(noop(), ce(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration.
+ assert_ecn_enabled(after); // ECN validation concludes after migration, despite all CE marks.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_noop_drop_data() {
+ let (before, after, migrated) = migration_with_modifiers(noop(), drop(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration.
+ assert_ecn_enabled(after); // Migration failed, ECN on original path is still validated.
+ assert!(!migrated);
+}
+
+#[test]
+fn ecn_migration_bleach_noop_data() {
+ let (before, after, migrated) = migration_with_modifiers(bleach(), noop(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to bleaching.
+ assert_ecn_enabled(after); // ECN validation concludes after migration.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_bleach_bleach_data() {
+ let (before, after, migrated) = migration_with_modifiers(bleach(), bleach(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to bleaching.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to bleaching.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_bleach_remark_data() {
+ let (before, after, migrated) = migration_with_modifiers(bleach(), remark(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to bleaching.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to remarking.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_bleach_ce_data() {
+ let (before, after, migrated) = migration_with_modifiers(bleach(), ce(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to bleaching.
+ assert_ecn_enabled(after); // ECN validation concludes after migration, despite all CE marks.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_bleach_drop_data() {
+ let (before, after, migrated) = migration_with_modifiers(bleach(), drop(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to bleaching.
+ // Migration failed, ECN on original path is still disabled.
+ assert_ecn_disabled(after);
+ assert!(!migrated);
+}
+
+#[test]
+fn ecn_migration_remark_noop_data() {
+ let (before, after, migrated) = migration_with_modifiers(remark(), noop(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to remarking.
+ assert_ecn_enabled(after); // ECN validation succeeds after migration.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_remark_bleach_data() {
+ let (before, after, migrated) = migration_with_modifiers(remark(), bleach(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to remarking.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to bleaching.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_remark_remark_data() {
+ let (before, after, migrated) = migration_with_modifiers(remark(), remark(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to remarking.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to remarking.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_remark_ce_data() {
+ let (before, after, migrated) = migration_with_modifiers(remark(), ce(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to remarking.
+ assert_ecn_enabled(after); // ECN validation concludes after migration, despite all CE marks.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_remark_drop_data() {
+ let (before, after, migrated) = migration_with_modifiers(remark(), drop(), ECN_TEST_COUNT);
+ assert_ecn_disabled(before); // ECN validation fails before migration due to remarking.
+ assert_ecn_disabled(after); // Migration failed, ECN on original path is still disabled.
+ assert!(!migrated);
+}
+
+#[test]
+fn ecn_migration_ce_noop_data() {
+ let (before, after, migrated) = migration_with_modifiers(ce(), noop(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration, despite all CE marks.
+ assert_ecn_enabled(after); // ECN validation concludes after migration.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_ce_bleach_data() {
+ let (before, after, migrated) = migration_with_modifiers(ce(), bleach(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration, despite all CE marks.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to bleaching
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_ce_remark_data() {
+ let (before, after, migrated) = migration_with_modifiers(ce(), remark(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration, despite all CE marks.
+ assert_ecn_disabled(after); // ECN validation fails after migration due to remarking.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_ce_ce_data() {
+ let (before, after, migrated) = migration_with_modifiers(ce(), ce(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration, despite all CE marks.
+ assert_ecn_enabled(after); // ECN validation concludes after migration, despite all CE marks.
+ assert!(migrated);
+}
+
+#[test]
+fn ecn_migration_ce_drop_data() {
+ let (before, after, migrated) = migration_with_modifiers(ce(), drop(), ECN_TEST_COUNT);
+ assert_ecn_enabled(before); // ECN validation concludes before migration, despite all CE marks.
+ // Migration failed, ECN on original path is still enabled.
+ assert_ecn_enabled(after);
+ assert!(!migrated);
+}
diff --git a/third_party/rust/neqo-transport/src/connection/tests/handshake.rs b/third_party/rust/neqo-transport/src/connection/tests/handshake.rs
index f2103523ec..c908340616 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/handshake.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/handshake.rs
@@ -35,7 +35,7 @@ use crate::{
server::ValidateAddress,
tparams::{TransportParameter, MIN_ACK_DELAY},
tracking::DEFAULT_ACK_DELAY,
- ConnectionError, ConnectionParameters, EmptyConnectionIdGenerator, Error, StreamType, Version,
+ CloseReason, ConnectionParameters, EmptyConnectionIdGenerator, Error, StreamType, Version,
};
const ECH_CONFIG_ID: u8 = 7;
@@ -111,8 +111,8 @@ fn handshake_failed_authentication() {
qdebug!("---- server: Alert(certificate_revoked)");
let out = server.process(out.as_dgram_ref(), now());
assert!(out.as_dgram_ref().is_some());
- assert_error(&client, &ConnectionError::Transport(Error::CryptoAlert(44)));
- assert_error(&server, &ConnectionError::Transport(Error::PeerError(300)));
+ assert_error(&client, &CloseReason::Transport(Error::CryptoAlert(44)));
+ assert_error(&server, &CloseReason::Transport(Error::PeerError(300)));
}
#[test]
@@ -133,11 +133,8 @@ fn no_alpn() {
handshake(&mut client, &mut server, now(), Duration::new(0, 0));
// TODO (mt): errors are immediate, which means that we never send CONNECTION_CLOSE
// and the client never sees the server's rejection of its handshake.
- // assert_error(&client, ConnectionError::Transport(Error::CryptoAlert(120)));
- assert_error(
- &server,
- &ConnectionError::Transport(Error::CryptoAlert(120)),
- );
+ // assert_error(&client, CloseReason::Transport(Error::CryptoAlert(120)));
+ assert_error(&server, &CloseReason::Transport(Error::CryptoAlert(120)));
}
#[test]
@@ -934,10 +931,10 @@ fn ech_retry() {
server.process_input(&dgram.unwrap(), now());
assert_eq!(
server.state().error(),
- Some(&ConnectionError::Transport(Error::PeerError(0x100 + 121)))
+ Some(&CloseReason::Transport(Error::PeerError(0x100 + 121)))
);
- let Some(ConnectionError::Transport(Error::EchRetry(updated_config))) = client.state().error()
+ let Some(CloseReason::Transport(Error::EchRetry(updated_config))) = client.state().error()
else {
panic!(
"Client state should be failed with EchRetry, is {:?}",
@@ -984,7 +981,7 @@ fn ech_retry_fallback_rejected() {
client.authenticated(AuthenticationStatus::PolicyRejection, now());
assert!(client.state().error().is_some());
- if let Some(ConnectionError::Transport(Error::EchRetry(_))) = client.state().error() {
+ if let Some(CloseReason::Transport(Error::EchRetry(_))) = client.state().error() {
panic!("Client should not get EchRetry error");
}
@@ -993,14 +990,13 @@ fn ech_retry_fallback_rejected() {
server.process_input(&dgram.unwrap(), now());
assert_eq!(
server.state().error(),
- Some(&ConnectionError::Transport(Error::PeerError(298)))
+ Some(&CloseReason::Transport(Error::PeerError(298)))
); // A bad_certificate alert.
}
#[test]
fn bad_min_ack_delay() {
- const EXPECTED_ERROR: ConnectionError =
- ConnectionError::Transport(Error::TransportParameterError);
+ const EXPECTED_ERROR: CloseReason = CloseReason::Transport(Error::TransportParameterError);
let mut server = default_server();
let max_ad = u64::try_from(DEFAULT_ACK_DELAY.as_micros()).unwrap();
server
@@ -1018,7 +1014,7 @@ fn bad_min_ack_delay() {
server.process_input(&dgram.unwrap(), now());
assert_eq!(
server.state().error(),
- Some(&ConnectionError::Transport(Error::PeerError(
+ Some(&CloseReason::Transport(Error::PeerError(
Error::TransportParameterError.code()
)))
);
diff --git a/third_party/rust/neqo-transport/src/connection/tests/keys.rs b/third_party/rust/neqo-transport/src/connection/tests/keys.rs
index 847b253284..c2ae9529bf 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/keys.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/keys.rs
@@ -11,7 +11,7 @@ use test_fixture::now;
use super::{
super::{
- super::{ConnectionError, ERROR_AEAD_LIMIT_REACHED},
+ super::{CloseReason, ERROR_AEAD_LIMIT_REACHED},
Connection, ConnectionParameters, Error, Output, State, StreamType,
},
connect, connect_force_idle, default_client, default_server, maybe_authenticate,
@@ -269,7 +269,7 @@ fn exhaust_write_keys() {
assert!(dgram.is_none());
assert!(matches!(
client.state(),
- State::Closed(ConnectionError::Transport(Error::KeysExhausted))
+ State::Closed(CloseReason::Transport(Error::KeysExhausted))
));
}
@@ -285,14 +285,14 @@ fn exhaust_read_keys() {
let dgram = server.process(Some(&dgram), now()).dgram();
assert!(matches!(
server.state(),
- State::Closed(ConnectionError::Transport(Error::KeysExhausted))
+ State::Closed(CloseReason::Transport(Error::KeysExhausted))
));
client.process_input(&dgram.unwrap(), now());
assert!(matches!(
client.state(),
State::Draining {
- error: ConnectionError::Transport(Error::PeerError(ERROR_AEAD_LIMIT_REACHED)),
+ error: CloseReason::Transport(Error::PeerError(ERROR_AEAD_LIMIT_REACHED)),
..
}
));
@@ -341,6 +341,6 @@ fn automatic_update_write_keys_blocked() {
assert!(dgram.is_none());
assert!(matches!(
client.state(),
- State::Closed(ConnectionError::Transport(Error::KeysExhausted))
+ State::Closed(CloseReason::Transport(Error::KeysExhausted))
));
}
diff --git a/third_party/rust/neqo-transport/src/connection/tests/migration.rs b/third_party/rust/neqo-transport/src/connection/tests/migration.rs
index 405ae161a4..779cc78c53 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/migration.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/migration.rs
@@ -30,7 +30,7 @@ use crate::{
packet::PacketBuilder,
path::{PATH_MTU_V4, PATH_MTU_V6},
tparams::{self, PreferredAddress, TransportParameter},
- ConnectionError, ConnectionId, ConnectionIdDecoder, ConnectionIdGenerator, ConnectionIdRef,
+ CloseReason, ConnectionId, ConnectionIdDecoder, ConnectionIdGenerator, ConnectionIdRef,
ConnectionParameters, EmptyConnectionIdGenerator, Error,
};
@@ -357,13 +357,13 @@ fn migrate_same_fail() {
assert!(matches!(res, Output::None));
assert!(matches!(
client.state(),
- State::Closed(ConnectionError::Transport(Error::NoAvailablePath))
+ State::Closed(CloseReason::Transport(Error::NoAvailablePath))
));
}
/// This gets the connection ID from a datagram using the default
/// connection ID generator/decoder.
-fn get_cid(d: &Datagram) -> ConnectionIdRef {
+pub fn get_cid(d: &Datagram) -> ConnectionIdRef {
let gen = CountingConnectionIdGenerator::default();
assert_eq!(d[0] & 0x80, 0); // Only support short packets for now.
gen.decode_cid(&mut Decoder::from(&d[1..])).unwrap()
@@ -894,7 +894,7 @@ fn retire_prior_to_migration_failure() {
assert!(matches!(
client.state(),
State::Closing {
- error: ConnectionError::Transport(Error::InvalidMigration),
+ error: CloseReason::Transport(Error::InvalidMigration),
..
}
));
diff --git a/third_party/rust/neqo-transport/src/connection/tests/mod.rs b/third_party/rust/neqo-transport/src/connection/tests/mod.rs
index c8c87a0df0..65283b8eb8 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/mod.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/mod.rs
@@ -17,7 +17,7 @@ use neqo_common::{event::Provider, qdebug, qtrace, Datagram, Decoder, Role};
use neqo_crypto::{random, AllowZeroRtt, AuthenticationStatus, ResumptionToken};
use test_fixture::{fixture_init, new_neqo_qlog, now, DEFAULT_ADDR};
-use super::{Connection, ConnectionError, ConnectionId, Output, State};
+use super::{CloseReason, Connection, ConnectionId, Output, State};
use crate::{
addr_valid::{AddressValidation, ValidateAddress},
cc::{CWND_INITIAL_PKTS, CWND_MIN},
@@ -37,6 +37,7 @@ mod ackrate;
mod cc;
mod close;
mod datagram;
+mod ecn;
mod handshake;
mod idle;
mod keys;
@@ -170,17 +171,13 @@ impl crate::connection::test_internal::FrameWriter for PingWriter {
}
}
-trait DatagramModifier: FnMut(Datagram) -> Option<Datagram> {}
-
-impl<T> DatagramModifier for T where T: FnMut(Datagram) -> Option<Datagram> {}
-
/// Drive the handshake between the client and server.
fn handshake_with_modifier(
client: &mut Connection,
server: &mut Connection,
now: Instant,
rtt: Duration,
- mut modifier: impl DatagramModifier,
+ modifier: fn(Datagram) -> Option<Datagram>,
) -> Instant {
let mut a = client;
let mut b = server;
@@ -248,8 +245,8 @@ fn connect_fail(
server_error: Error,
) {
handshake(client, server, now(), Duration::new(0, 0));
- assert_error(client, &ConnectionError::Transport(client_error));
- assert_error(server, &ConnectionError::Transport(server_error));
+ assert_error(client, &CloseReason::Transport(client_error));
+ assert_error(server, &CloseReason::Transport(server_error));
}
fn connect_with_rtt_and_modifier(
@@ -257,7 +254,7 @@ fn connect_with_rtt_and_modifier(
server: &mut Connection,
now: Instant,
rtt: Duration,
- modifier: impl DatagramModifier,
+ modifier: fn(Datagram) -> Option<Datagram>,
) -> Instant {
fn check_rtt(stats: &Stats, rtt: Duration) {
assert_eq!(stats.rtt, rtt);
@@ -287,7 +284,7 @@ fn connect(client: &mut Connection, server: &mut Connection) {
connect_with_rtt(client, server, now(), Duration::new(0, 0));
}
-fn assert_error(c: &Connection, expected: &ConnectionError) {
+fn assert_error(c: &Connection, expected: &CloseReason) {
match c.state() {
State::Closing { error, .. } | State::Draining { error, .. } | State::Closed(error) => {
assert_eq!(*error, *expected, "{c} error mismatch");
@@ -333,7 +330,7 @@ fn connect_rtt_idle_with_modifier(
client: &mut Connection,
server: &mut Connection,
rtt: Duration,
- modifier: impl DatagramModifier,
+ modifier: fn(Datagram) -> Option<Datagram>,
) -> Instant {
let now = connect_with_rtt_and_modifier(client, server, now(), rtt, modifier);
assert_idle(client, server, rtt, now);
@@ -351,7 +348,7 @@ fn connect_rtt_idle(client: &mut Connection, server: &mut Connection, rtt: Durat
fn connect_force_idle_with_modifier(
client: &mut Connection,
server: &mut Connection,
- modifier: impl DatagramModifier,
+ modifier: fn(Datagram) -> Option<Datagram>,
) {
connect_rtt_idle_with_modifier(client, server, Duration::new(0, 0), modifier);
}
@@ -380,7 +377,7 @@ fn fill_stream(c: &mut Connection, stream: StreamId) {
fn fill_cwnd(c: &mut Connection, stream: StreamId, mut now: Instant) -> (Vec<Datagram>, Instant) {
// Train wreck function to get the remaining congestion window on the primary path.
fn cwnd(c: &Connection) -> usize {
- c.paths.primary().borrow().sender().cwnd_avail()
+ c.paths.primary().unwrap().borrow().sender().cwnd_avail()
}
qtrace!("fill_cwnd starting cwnd: {}", cwnd(c));
@@ -478,10 +475,10 @@ where
// Get the current congestion window for the connection.
fn cwnd(c: &Connection) -> usize {
- c.paths.primary().borrow().sender().cwnd()
+ c.paths.primary().unwrap().borrow().sender().cwnd()
}
fn cwnd_avail(c: &Connection) -> usize {
- c.paths.primary().borrow().sender().cwnd_avail()
+ c.paths.primary().unwrap().borrow().sender().cwnd_avail()
}
fn induce_persistent_congestion(
@@ -576,7 +573,7 @@ fn send_something_paced_with_modifier(
sender: &mut Connection,
mut now: Instant,
allow_pacing: bool,
- mut modifier: impl DatagramModifier,
+ modifier: fn(Datagram) -> Option<Datagram>,
) -> (Datagram, Instant) {
let stream_id = sender.stream_create(StreamType::UniDi).unwrap();
assert!(sender.stream_send(stream_id, DEFAULT_STREAM_DATA).is_ok());
@@ -608,7 +605,7 @@ fn send_something_paced(
fn send_something_with_modifier(
sender: &mut Connection,
now: Instant,
- modifier: impl DatagramModifier,
+ modifier: fn(Datagram) -> Option<Datagram>,
) -> Datagram {
send_something_paced_with_modifier(sender, now, false, modifier).0
}
diff --git a/third_party/rust/neqo-transport/src/connection/tests/stream.rs b/third_party/rust/neqo-transport/src/connection/tests/stream.rs
index 66d3bf32f3..f7472d917f 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/stream.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/stream.rs
@@ -19,9 +19,9 @@ use crate::{
send_stream::{OrderGroup, SendStreamState, SEND_BUFFER_SIZE},
streams::{SendOrder, StreamOrder},
tparams::{self, TransportParameter},
+ CloseReason,
// tracking::DEFAULT_ACK_PACKET_TOLERANCE,
Connection,
- ConnectionError,
ConnectionParameters,
Error,
StreamId,
@@ -494,12 +494,9 @@ fn exceed_max_data() {
assert_error(
&client,
- &ConnectionError::Transport(Error::PeerError(Error::FlowControlError.code())),
- );
- assert_error(
- &server,
- &ConnectionError::Transport(Error::FlowControlError),
+ &CloseReason::Transport(Error::PeerError(Error::FlowControlError.code())),
);
+ assert_error(&server, &CloseReason::Transport(Error::FlowControlError));
}
#[test]
diff --git a/third_party/rust/neqo-transport/src/connection/tests/vn.rs b/third_party/rust/neqo-transport/src/connection/tests/vn.rs
index 93872a94f4..815868d78d 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/vn.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/vn.rs
@@ -10,7 +10,7 @@ use neqo_common::{event::Provider, Decoder, Encoder};
use test_fixture::{assertions, datagram, now};
use super::{
- super::{ConnectionError, ConnectionEvent, Output, State, ZeroRttState},
+ super::{CloseReason, ConnectionEvent, Output, State, ZeroRttState},
connect, connect_fail, default_client, default_server, exchange_ticket, new_client, new_server,
send_something,
};
@@ -124,7 +124,7 @@ fn version_negotiation_only_reserved() {
assert_eq!(client.process(Some(&dgram), now()), Output::None);
match client.state() {
State::Closed(err) => {
- assert_eq!(*err, ConnectionError::Transport(Error::VersionNegotiation));
+ assert_eq!(*err, CloseReason::Transport(Error::VersionNegotiation));
}
_ => panic!("Invalid client state"),
}
@@ -183,7 +183,7 @@ fn version_negotiation_not_supported() {
assert_eq!(client.process(Some(&dgram), now()), Output::None);
match client.state() {
State::Closed(err) => {
- assert_eq!(*err, ConnectionError::Transport(Error::VersionNegotiation));
+ assert_eq!(*err, CloseReason::Transport(Error::VersionNegotiation));
}
_ => panic!("Invalid client state"),
}
@@ -338,7 +338,7 @@ fn invalid_server_version() {
// The server effectively hasn't reacted here.
match server.state() {
State::Closed(err) => {
- assert_eq!(*err, ConnectionError::Transport(Error::CryptoAlert(47)));
+ assert_eq!(*err, CloseReason::Transport(Error::CryptoAlert(47)));
}
_ => panic!("invalid server state"),
}
diff --git a/third_party/rust/neqo-transport/src/ecn.rs b/third_party/rust/neqo-transport/src/ecn.rs
new file mode 100644
index 0000000000..20eb4da003
--- /dev/null
+++ b/third_party/rust/neqo-transport/src/ecn.rs
@@ -0,0 +1,225 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::{AddAssign, Deref, DerefMut, Sub};
+
+use enum_map::EnumMap;
+use neqo_common::{qdebug, qinfo, qwarn, IpTosEcn};
+
+use crate::{packet::PacketNumber, tracking::SentPacket};
+
+/// The number of packets to use for testing a path for ECN capability.
+pub const ECN_TEST_COUNT: usize = 10;
+
+/// The state information related to testing a path for ECN capability.
+/// See RFC9000, Appendix A.4.
+#[derive(Debug, PartialEq, Clone)]
+enum EcnValidationState {
+ /// The path is currently being tested for ECN capability, with the number of probes sent so
+ /// far on the path during the ECN validation.
+ Testing(usize),
+ /// The validation test has concluded but the path's ECN capability is not yet known.
+ Unknown,
+ /// The path is known to **not** be ECN capable.
+ Failed,
+ /// The path is known to be ECN capable.
+ Capable,
+}
+
+impl Default for EcnValidationState {
+ fn default() -> Self {
+ EcnValidationState::Testing(0)
+ }
+}
+
+/// The counts for different ECN marks.
+#[derive(PartialEq, Eq, Debug, Clone, Copy, Default)]
+pub struct EcnCount(EnumMap<IpTosEcn, u64>);
+
+impl Deref for EcnCount {
+ type Target = EnumMap<IpTosEcn, u64>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl DerefMut for EcnCount {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+impl EcnCount {
+ pub fn new(not_ect: u64, ect0: u64, ect1: u64, ce: u64) -> Self {
+ // Yes, the enum array order is different from the argument order.
+ Self(EnumMap::from_array([not_ect, ect1, ect0, ce]))
+ }
+
+ /// Whether any of the ECN counts are non-zero.
+ pub fn is_some(&self) -> bool {
+ self[IpTosEcn::Ect0] > 0 || self[IpTosEcn::Ect1] > 0 || self[IpTosEcn::Ce] > 0
+ }
+}
+
+impl Sub<EcnCount> for EcnCount {
+ type Output = EcnCount;
+
+ /// Subtract the ECN counts in `other` from `self`.
+ fn sub(self, other: EcnCount) -> EcnCount {
+ let mut diff = EcnCount::default();
+ for (ecn, count) in &mut *diff {
+ *count = self[ecn].saturating_sub(other[ecn]);
+ }
+ diff
+ }
+}
+
+impl AddAssign<IpTosEcn> for EcnCount {
+ fn add_assign(&mut self, ecn: IpTosEcn) {
+ self[ecn] += 1;
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct EcnInfo {
+ /// The current state of ECN validation on this path.
+ state: EcnValidationState,
+
+ /// The largest ACK seen so far.
+ largest_acked: PacketNumber,
+
+ /// The ECN counts from the last ACK frame that increased `largest_acked`.
+ baseline: EcnCount,
+}
+
+impl EcnInfo {
+ /// Set the baseline (= the ECN counts from the last ACK Frame).
+ pub fn set_baseline(&mut self, baseline: EcnCount) {
+ self.baseline = baseline;
+ }
+
+ /// Expose the current baseline.
+ pub fn baseline(&self) -> EcnCount {
+ self.baseline
+ }
+
+ /// Count the number of packets sent out on this path during ECN validation.
+ /// Exit ECN validation if the number of packets sent exceeds `ECN_TEST_COUNT`.
+ /// We do not implement the part of the RFC that says to exit ECN validation if the time since
+ /// the start of ECN validation exceeds 3 * PTO, since this seems to happen much too quickly.
+ pub fn on_packet_sent(&mut self) {
+ if let EcnValidationState::Testing(ref mut probes_sent) = &mut self.state {
+ *probes_sent += 1;
+ qdebug!("ECN probing: sent {} probes", probes_sent);
+ if *probes_sent == ECN_TEST_COUNT {
+ qdebug!("ECN probing concluded with {} probes sent", probes_sent);
+ self.state = EcnValidationState::Unknown;
+ }
+ }
+ }
+
+ /// Process ECN counts from an ACK frame.
+ ///
+ /// Returns whether ECN counts contain new valid ECN CE marks.
+ pub fn on_packets_acked(
+ &mut self,
+ acked_packets: &[SentPacket],
+ ack_ecn: Option<EcnCount>,
+ ) -> bool {
+ let prev_baseline = self.baseline;
+
+ self.validate_ack_ecn_and_update(acked_packets, ack_ecn);
+
+ matches!(self.state, EcnValidationState::Capable)
+ && (self.baseline - prev_baseline)[IpTosEcn::Ce] > 0
+ }
+
+ /// After the ECN validation test has ended, check if the path is ECN capable.
+ pub fn validate_ack_ecn_and_update(
+ &mut self,
+ acked_packets: &[SentPacket],
+ ack_ecn: Option<EcnCount>,
+ ) {
+ // RFC 9000, Appendix A.4:
+ //
+ // > From the "unknown" state, successful validation of the ECN counts in an ACK frame
+ // > (see Section 13.4.2.1) causes the ECN state for the path to become "capable", unless
+ // > no marked packet has been acknowledged.
+ match self.state {
+ EcnValidationState::Testing { .. } | EcnValidationState::Failed => return,
+ EcnValidationState::Unknown | EcnValidationState::Capable => {}
+ }
+
+ // RFC 9000, Section 13.4.2.1:
+ //
+ // > Validating ECN counts from reordered ACK frames can result in failure. An endpoint MUST
+ // > NOT fail ECN validation as a result of processing an ACK frame that does not increase
+ // > the largest acknowledged packet number.
+ let largest_acked = acked_packets.first().expect("must be there").pn;
+ if largest_acked <= self.largest_acked {
+ return;
+ }
+
+ // RFC 9000, Section 13.4.2.1:
+ //
+ // > An endpoint that receives an ACK frame with ECN counts therefore validates
+ // > the counts before using them. It performs this validation by comparing newly
+ // > received counts against those from the last successfully processed ACK frame.
+ //
+ // > If an ACK frame newly acknowledges a packet that the endpoint sent with
+ // > either the ECT(0) or ECT(1) codepoint set, ECN validation fails if the
+ // > corresponding ECN counts are not present in the ACK frame.
+ let Some(ack_ecn) = ack_ecn else {
+ qwarn!("ECN validation failed, no ECN counts in ACK frame");
+ self.state = EcnValidationState::Failed;
+ return;
+ };
+
+ // We always mark with ECT(0) - if at all - so we only need to check for that.
+ //
+ // > ECN validation also fails if the sum of the increase in ECT(0) and ECN-CE counts is
+ // > less than the number of newly acknowledged packets that were originally sent with an
+ // > ECT(0) marking.
+ let newly_acked_sent_with_ect0: u64 = acked_packets
+ .iter()
+ .filter(|p| p.ecn_mark == IpTosEcn::Ect0)
+ .count()
+ .try_into()
+ .unwrap();
+ if newly_acked_sent_with_ect0 == 0 {
+ qwarn!("ECN validation failed, no ECT(0) packets were newly acked");
+ self.state = EcnValidationState::Failed;
+ return;
+ }
+ let ecn_diff = ack_ecn - self.baseline;
+ let sum_inc = ecn_diff[IpTosEcn::Ect0] + ecn_diff[IpTosEcn::Ce];
+ if sum_inc < newly_acked_sent_with_ect0 {
+ qwarn!(
+ "ECN validation failed, ACK counted {} new marks, but {} of newly acked packets were sent with ECT(0)",
+ sum_inc,
+ newly_acked_sent_with_ect0
+ );
+ self.state = EcnValidationState::Failed;
+ } else if ecn_diff[IpTosEcn::Ect1] > 0 {
+ qwarn!("ECN validation failed, ACK counted ECT(1) marks that were never sent");
+ self.state = EcnValidationState::Failed;
+ } else {
+ qinfo!("ECN validation succeeded, path is capable",);
+ self.state = EcnValidationState::Capable;
+ }
+ self.baseline = ack_ecn;
+ self.largest_acked = largest_acked;
+ }
+
+ /// The ECN mark to use for packets sent on this path.
+ pub fn ecn_mark(&self) -> IpTosEcn {
+ match self.state {
+ EcnValidationState::Testing { .. } | EcnValidationState::Capable => IpTosEcn::Ect0,
+ EcnValidationState::Failed | EcnValidationState::Unknown => IpTosEcn::NotEct,
+ }
+ }
+}
diff --git a/third_party/rust/neqo-transport/src/events.rs b/third_party/rust/neqo-transport/src/events.rs
index a892e384b9..68ef0d6798 100644
--- a/third_party/rust/neqo-transport/src/events.rs
+++ b/third_party/rust/neqo-transport/src/events.rs
@@ -256,7 +256,7 @@ impl EventProvider for ConnectionEvents {
mod tests {
use neqo_common::event::Provider;
- use crate::{ConnectionError, ConnectionEvent, ConnectionEvents, Error, State, StreamId};
+ use crate::{CloseReason, ConnectionEvent, ConnectionEvents, Error, State, StreamId};
#[test]
fn event_culling() {
@@ -314,7 +314,7 @@ mod tests {
evts.send_stream_writable(9.into());
evts.send_stream_stop_sending(10.into(), 55);
- evts.connection_state_change(State::Closed(ConnectionError::Transport(
+ evts.connection_state_change(State::Closed(CloseReason::Transport(
Error::StreamStateError,
)));
assert_eq!(evts.events().count(), 1);
diff --git a/third_party/rust/neqo-transport/src/frame.rs b/third_party/rust/neqo-transport/src/frame.rs
index d84eb61ce8..7d009f3b46 100644
--- a/third_party/rust/neqo-transport/src/frame.rs
+++ b/third_party/rust/neqo-transport/src/frame.rs
@@ -8,13 +8,14 @@
use std::ops::RangeInclusive;
-use neqo_common::{qtrace, Decoder};
+use neqo_common::{qtrace, Decoder, Encoder};
use crate::{
cid::MAX_CONNECTION_ID_LEN,
+ ecn::EcnCount,
packet::PacketType,
stream_id::{StreamId, StreamType},
- AppError, ConnectionError, Error, Res, TransportError,
+ AppError, CloseReason, Error, Res, TransportError,
};
#[allow(clippy::module_name_repetitions)]
@@ -23,7 +24,7 @@ pub type FrameType = u64;
pub const FRAME_TYPE_PADDING: FrameType = 0x0;
pub const FRAME_TYPE_PING: FrameType = 0x1;
pub const FRAME_TYPE_ACK: FrameType = 0x2;
-const FRAME_TYPE_ACK_ECN: FrameType = 0x3;
+pub const FRAME_TYPE_ACK_ECN: FrameType = 0x3;
pub const FRAME_TYPE_RESET_STREAM: FrameType = 0x4;
pub const FRAME_TYPE_STOP_SENDING: FrameType = 0x5;
pub const FRAME_TYPE_CRYPTO: FrameType = 0x6;
@@ -86,11 +87,11 @@ impl CloseError {
}
}
-impl From<ConnectionError> for CloseError {
- fn from(err: ConnectionError) -> Self {
+impl From<CloseReason> for CloseError {
+ fn from(err: CloseReason) -> Self {
match err {
- ConnectionError::Transport(c) => Self::Transport(c.code()),
- ConnectionError::Application(c) => Self::Application(c),
+ CloseReason::Transport(c) => Self::Transport(c.code()),
+ CloseReason::Application(c) => Self::Application(c),
}
}
}
@@ -116,6 +117,7 @@ pub enum Frame<'a> {
ack_delay: u64,
first_ack_range: u64,
ack_ranges: Vec<AckRange>,
+ ecn_count: Option<EcnCount>,
},
ResetStream {
stream_id: StreamId,
@@ -182,7 +184,7 @@ pub enum Frame<'a> {
frame_type: u64,
// Not a reference as we use this to hold the value.
// This is not used in optimized builds anyway.
- reason_phrase: Vec<u8>,
+ reason_phrase: String,
},
HandshakeDone,
AckFrequency {
@@ -224,7 +226,7 @@ impl<'a> Frame<'a> {
match self {
Self::Padding { .. } => FRAME_TYPE_PADDING,
Self::Ping => FRAME_TYPE_PING,
- Self::Ack { .. } => FRAME_TYPE_ACK, // We don't do ACK ECN.
+ Self::Ack { .. } => FRAME_TYPE_ACK,
Self::ResetStream { .. } => FRAME_TYPE_RESET_STREAM,
Self::StopSending { .. } => FRAME_TYPE_STOP_SENDING,
Self::Crypto { .. } => FRAME_TYPE_CRYPTO,
@@ -426,8 +428,54 @@ impl<'a> Frame<'a> {
d(dec.decode_varint())
}
- // TODO(ekr@rtfm.com): check for minimal encoding
+ fn decode_ack<'a>(dec: &mut Decoder<'a>, ecn: bool) -> Res<Frame<'a>> {
+ let la = dv(dec)?;
+ let ad = dv(dec)?;
+ let nr = dv(dec).and_then(|nr| {
+ if nr < MAX_ACK_RANGE_COUNT {
+ Ok(nr)
+ } else {
+ Err(Error::TooMuchData)
+ }
+ })?;
+ let fa = dv(dec)?;
+ let mut arr: Vec<AckRange> = Vec::with_capacity(usize::try_from(nr)?);
+ for _ in 0..nr {
+ let ar = AckRange {
+ gap: dv(dec)?,
+ range: dv(dec)?,
+ };
+ arr.push(ar);
+ }
+
+ // Now check for the values for ACK_ECN.
+ let ecn_count = if ecn {
+ Some(EcnCount::new(0, dv(dec)?, dv(dec)?, dv(dec)?))
+ } else {
+ None
+ };
+
+ Ok(Frame::Ack {
+ largest_acknowledged: la,
+ ack_delay: ad,
+ first_ack_range: fa,
+ ack_ranges: arr,
+ ecn_count,
+ })
+ }
+
+ // Check for minimal encoding of frame type.
+ let pos = dec.offset();
let t = dv(dec)?;
+ // RFC 9000, Section 12.4:
+ //
+ // The Frame Type field uses a variable-length integer encoding [...],
+ // with one exception. To ensure simple and efficient implementations of
+ // frame parsing, a frame type MUST use the shortest possible encoding.
+ if Encoder::varint_len(t) != dec.offset() - pos {
+ return Err(Error::ProtocolViolation);
+ }
+
match t {
FRAME_TYPE_PADDING => {
let mut length: u16 = 1;
@@ -449,40 +497,8 @@ impl<'a> Frame<'a> {
_ => return Err(Error::NoMoreData),
},
}),
- FRAME_TYPE_ACK | FRAME_TYPE_ACK_ECN => {
- let la = dv(dec)?;
- let ad = dv(dec)?;
- let nr = dv(dec).and_then(|nr| {
- if nr < MAX_ACK_RANGE_COUNT {
- Ok(nr)
- } else {
- Err(Error::TooMuchData)
- }
- })?;
- let fa = dv(dec)?;
- let mut arr: Vec<AckRange> = Vec::with_capacity(usize::try_from(nr)?);
- for _ in 0..nr {
- let ar = AckRange {
- gap: dv(dec)?,
- range: dv(dec)?,
- };
- arr.push(ar);
- }
-
- // Now check for the values for ACK_ECN.
- if t == FRAME_TYPE_ACK_ECN {
- dv(dec)?;
- dv(dec)?;
- dv(dec)?;
- }
-
- Ok(Self::Ack {
- largest_acknowledged: la,
- ack_delay: ad,
- first_ack_range: fa,
- ack_ranges: arr,
- })
- }
+ FRAME_TYPE_ACK => decode_ack(dec, false),
+ FRAME_TYPE_ACK_ECN => decode_ack(dec, true),
FRAME_TYPE_STOP_SENDING => Ok(Self::StopSending {
stream_id: StreamId::from(dv(dec)?),
application_error_code: dv(dec)?,
@@ -598,7 +614,7 @@ impl<'a> Frame<'a> {
0
};
// We can tolerate this copy for now.
- let reason_phrase = d(dec.decode_vvec())?.to_vec();
+ let reason_phrase = String::from_utf8_lossy(d(dec.decode_vvec())?).to_string();
Ok(Self::ConnectionClose {
error_code,
frame_type,
@@ -647,13 +663,14 @@ mod tests {
use crate::{
cid::MAX_CONNECTION_ID_LEN,
+ ecn::EcnCount,
frame::{AckRange, Frame, FRAME_TYPE_ACK},
CloseError, Error, StreamId, StreamType,
};
fn just_dec(f: &Frame, s: &str) {
let encoded = Encoder::from_hex(s);
- let decoded = Frame::decode(&mut encoded.as_decoder()).unwrap();
+ let decoded = Frame::decode(&mut encoded.as_decoder()).expect("Failed to decode frame");
assert_eq!(*f, decoded);
}
@@ -679,7 +696,8 @@ mod tests {
largest_acknowledged: 0x1234,
ack_delay: 0x1235,
first_ack_range: 0x1236,
- ack_ranges: ar,
+ ack_ranges: ar.clone(),
+ ecn_count: None,
};
just_dec(&f, "025234523502523601020304");
@@ -689,10 +707,18 @@ mod tests {
let mut dec = enc.as_decoder();
assert_eq!(Frame::decode(&mut dec).unwrap_err(), Error::NoMoreData);
- // Try to parse ACK_ECN without ECN values
+ // Try to parse ACK_ECN with ECN values
+ let ecn_count = Some(EcnCount::new(0, 1, 2, 3));
+ let fe = Frame::Ack {
+ largest_acknowledged: 0x1234,
+ ack_delay: 0x1235,
+ first_ack_range: 0x1236,
+ ack_ranges: ar,
+ ecn_count,
+ };
let enc = Encoder::from_hex("035234523502523601020304010203");
let mut dec = enc.as_decoder();
- assert_eq!(Frame::decode(&mut dec).unwrap(), f);
+ assert_eq!(Frame::decode(&mut dec).unwrap(), fe);
}
#[test]
@@ -899,7 +925,7 @@ mod tests {
let f = Frame::ConnectionClose {
error_code: CloseError::Transport(0x5678),
frame_type: 0x1234,
- reason_phrase: vec![0x01, 0x02, 0x03],
+ reason_phrase: String::from("\x01\x02\x03"),
};
just_dec(&f, "1c80005678523403010203");
@@ -910,7 +936,7 @@ mod tests {
let f = Frame::ConnectionClose {
error_code: CloseError::Application(0x5678),
frame_type: 0,
- reason_phrase: vec![0x01, 0x02, 0x03],
+ reason_phrase: String::from("\x01\x02\x03"),
};
just_dec(&f, "1d8000567803010203");
@@ -989,14 +1015,14 @@ mod tests {
fill: true,
};
- just_dec(&f, "4030010203");
+ just_dec(&f, "30010203");
// With the length bit.
let f = Frame::Datagram {
data: &[1, 2, 3],
fill: false,
};
- just_dec(&f, "403103010203");
+ just_dec(&f, "3103010203");
}
#[test]
@@ -1010,4 +1036,15 @@ mod tests {
assert_eq!(Err(Error::TooMuchData), Frame::decode(&mut e.as_decoder()));
}
+
+ #[test]
+ #[should_panic(expected = "Failed to decode frame")]
+ fn invalid_frame_type_len() {
+ let f = Frame::Datagram {
+ data: &[1, 2, 3],
+ fill: true,
+ };
+
+ just_dec(&f, "4030010203");
+ }
}
diff --git a/third_party/rust/neqo-transport/src/lib.rs b/third_party/rust/neqo-transport/src/lib.rs
index 5488472b58..723a86980e 100644
--- a/third_party/rust/neqo-transport/src/lib.rs
+++ b/third_party/rust/neqo-transport/src/lib.rs
@@ -15,10 +15,17 @@ mod cc;
mod cid;
mod connection;
mod crypto;
+mod ecn;
mod events;
mod fc;
+#[cfg(fuzzing)]
+pub mod frame;
+#[cfg(not(fuzzing))]
mod frame;
mod pace;
+#[cfg(fuzzing)]
+pub mod packet;
+#[cfg(not(fuzzing))]
mod packet;
mod path;
mod qlog;
@@ -202,13 +209,17 @@ impl ::std::fmt::Display for Error {
pub type AppError = u64;
+#[deprecated(note = "use `CloseReason` instead")]
+pub type ConnectionError = CloseReason;
+
+/// Reason why a connection closed.
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
-pub enum ConnectionError {
+pub enum CloseReason {
Transport(Error),
Application(AppError),
}
-impl ConnectionError {
+impl CloseReason {
#[must_use]
pub fn app_code(&self) -> Option<AppError> {
match self {
@@ -216,9 +227,19 @@ impl ConnectionError {
Self::Transport(_) => None,
}
}
+
+ /// Checks enclosed error for [`Error::NoError`] and
+ /// [`CloseReason::Application(0)`].
+ #[must_use]
+ pub fn is_error(&self) -> bool {
+ !matches!(
+ self,
+ CloseReason::Transport(Error::NoError) | CloseReason::Application(0),
+ )
+ }
}
-impl From<CloseError> for ConnectionError {
+impl From<CloseError> for CloseReason {
fn from(err: CloseError) -> Self {
match err {
CloseError::Transport(c) => Self::Transport(Error::PeerError(c)),
diff --git a/third_party/rust/neqo-transport/src/packet/mod.rs b/third_party/rust/neqo-transport/src/packet/mod.rs
index ce611a9664..10d9b13208 100644
--- a/third_party/rust/neqo-transport/src/packet/mod.rs
+++ b/third_party/rust/neqo-transport/src/packet/mod.rs
@@ -740,6 +740,7 @@ impl<'a> PublicPacket<'a> {
}
#[must_use]
+ #[allow(clippy::len_without_is_empty)] // is_empty() would always return false in this case
pub fn len(&self) -> usize {
self.data.len()
}
diff --git a/third_party/rust/neqo-transport/src/path.rs b/third_party/rust/neqo-transport/src/path.rs
index 50e458ff36..0e4c82b1ca 100644
--- a/third_party/rust/neqo-transport/src/path.rs
+++ b/third_party/rust/neqo-transport/src/path.rs
@@ -22,6 +22,7 @@ use crate::{
ackrate::{AckRate, PeerAckDelay},
cc::CongestionControlAlgorithm,
cid::{ConnectionId, ConnectionIdRef, ConnectionIdStore, RemoteConnectionIdEntry},
+ ecn::{EcnCount, EcnInfo},
frame::{FRAME_TYPE_PATH_CHALLENGE, FRAME_TYPE_PATH_RESPONSE, FRAME_TYPE_RETIRE_CONNECTION_ID},
packet::PacketBuilder,
recovery::RecoveryToken,
@@ -145,15 +146,8 @@ impl Paths {
})
}
- /// Get a reference to the primary path. This will assert if there is no primary
- /// path, which happens at a server prior to receiving a valid Initial packet
- /// from a client. So be careful using this method.
- pub fn primary(&self) -> PathRef {
- self.primary_fallible().unwrap()
- }
-
- /// Get a reference to the primary path. Use this prior to handshake completion.
- pub fn primary_fallible(&self) -> Option<PathRef> {
+ /// Get a reference to the primary path, if one exists.
+ pub fn primary(&self) -> Option<PathRef> {
self.primary.clone()
}
@@ -242,6 +236,11 @@ impl Paths {
/// Returns `true` if the path was migrated.
pub fn migrate(&mut self, path: &PathRef, force: bool, now: Instant) -> bool {
debug_assert!(!self.is_temporary(path));
+ let baseline = self.primary().map_or_else(
+ || EcnInfo::default().baseline(),
+ |p| p.borrow().ecn_info.baseline(),
+ );
+ path.borrow_mut().set_ecn_baseline(baseline);
if force || path.borrow().is_valid() {
path.borrow_mut().set_valid(now);
mem::drop(self.select_primary(path));
@@ -307,7 +306,6 @@ impl Paths {
/// Set the identified path to be primary.
/// This panics if `make_permanent` hasn't been called.
pub fn handle_migration(&mut self, path: &PathRef, remote: SocketAddr, now: Instant) {
- qtrace!([self.primary().borrow()], "handle_migration");
// The update here needs to match the checks in `Path::received_on`.
// Here, we update the remote port number to match the source port on the
// datagram that was received. This ensures that we send subsequent
@@ -425,10 +423,10 @@ impl Paths {
stats.retire_connection_id += 1;
}
- // Write out any ACK_FREQUENCY frames.
- self.primary()
- .borrow_mut()
- .write_cc_frames(builder, tokens, stats);
+ if let Some(path) = self.primary() {
+ // Write out any ACK_FREQUENCY frames.
+ path.borrow_mut().write_cc_frames(builder, tokens, stats);
+ }
}
pub fn lost_retire_cid(&mut self, lost: u64) {
@@ -440,11 +438,15 @@ impl Paths {
}
pub fn lost_ack_frequency(&mut self, lost: &AckRate) {
- self.primary().borrow_mut().lost_ack_frequency(lost);
+ if let Some(path) = self.primary() {
+ path.borrow_mut().lost_ack_frequency(lost);
+ }
}
pub fn acked_ack_frequency(&mut self, acked: &AckRate) {
- self.primary().borrow_mut().acked_ack_frequency(acked);
+ if let Some(path) = self.primary() {
+ path.borrow_mut().acked_ack_frequency(acked);
+ }
}
/// Get an estimate of the RTT on the primary path.
@@ -454,7 +456,7 @@ impl Paths {
// make a new RTT esimate and interrogate that.
// That is more expensive, but it should be rare and breaking encapsulation
// is worse, especially as this is only used in tests.
- self.primary_fallible()
+ self.primary()
.map_or(RttEstimate::default().estimate(), |p| {
p.borrow().rtt().estimate()
})
@@ -532,8 +534,6 @@ pub struct Path {
rtt: RttEstimate,
/// A packet sender for the path, which includes congestion control and a pacer.
sender: PacketSender,
- /// The DSCP/ECN marking to use for outgoing packets on this path.
- tos: IpTos,
/// The IP TTL to use for outgoing packets on this path.
ttl: u8,
@@ -543,7 +543,8 @@ pub struct Path {
received_bytes: usize,
/// The number of bytes sent on this path.
sent_bytes: usize,
-
+ /// The ECN-related state for this path (see RFC9000, Section 13.4 and Appendix A.4)
+ ecn_info: EcnInfo,
/// For logging of events.
qlog: NeqoQlog,
}
@@ -572,14 +573,23 @@ impl Path {
challenge: None,
rtt: RttEstimate::default(),
sender,
- tos: IpTos::default(), // TODO: Default to Ect0 when ECN is supported.
- ttl: 64, // This is the default TTL on many OSes.
+ ttl: 64, // This is the default TTL on many OSes.
received_bytes: 0,
sent_bytes: 0,
+ ecn_info: EcnInfo::default(),
qlog,
}
}
+ pub fn set_ecn_baseline(&mut self, baseline: EcnCount) {
+ self.ecn_info.set_baseline(baseline);
+ }
+
+ /// Return the DSCP/ECN marking to use for outgoing packets on this path.
+ pub fn tos(&self) -> IpTos {
+ self.ecn_info.ecn_mark().into()
+ }
+
/// Whether this path is the primary or current path for the connection.
pub fn is_primary(&self) -> bool {
self.primary
@@ -695,8 +705,9 @@ impl Path {
}
/// Make a datagram.
- pub fn datagram<V: Into<Vec<u8>>>(&self, payload: V) -> Datagram {
- Datagram::new(self.local, self.remote, self.tos, Some(self.ttl), payload)
+ pub fn datagram<V: Into<Vec<u8>>>(&mut self, payload: V) -> Datagram {
+ self.ecn_info.on_packet_sent();
+ Datagram::new(self.local, self.remote, self.tos(), Some(self.ttl), payload)
}
/// Get local address as `SocketAddr`
@@ -959,8 +970,24 @@ impl Path {
}
/// Record packets as acknowledged with the sender.
- pub fn on_packets_acked(&mut self, acked_pkts: &[SentPacket], now: Instant) {
+ pub fn on_packets_acked(
+ &mut self,
+ acked_pkts: &[SentPacket],
+ ack_ecn: Option<EcnCount>,
+ now: Instant,
+ ) {
debug_assert!(self.is_primary());
+
+ let ecn_ce_received = self.ecn_info.on_packets_acked(acked_pkts, ack_ecn);
+ if ecn_ce_received {
+ let cwnd_reduced = self
+ .sender
+ .on_ecn_ce_received(acked_pkts.first().expect("must be there"));
+ if cwnd_reduced {
+ self.rtt.update_ack_delay(self.sender.cwnd(), self.mtu());
+ }
+ }
+
self.sender.on_packets_acked(acked_pkts, &self.rtt, now);
}
diff --git a/third_party/rust/neqo-transport/src/qlog.rs b/third_party/rust/neqo-transport/src/qlog.rs
index a8ad986d2a..715ba85e81 100644
--- a/third_party/rust/neqo-transport/src/qlog.rs
+++ b/third_party/rust/neqo-transport/src/qlog.rs
@@ -11,7 +11,7 @@ use std::{
time::Duration,
};
-use neqo_common::{hex, qinfo, qlog::NeqoQlog, Decoder};
+use neqo_common::{hex, qinfo, qlog::NeqoQlog, Decoder, IpTosEcn};
use qlog::events::{
connectivity::{ConnectionStarted, ConnectionState, ConnectionStateUpdated},
quic::{
@@ -205,7 +205,7 @@ pub fn packet_sent(
let mut frames = SmallVec::new();
while d.remaining() > 0 {
if let Ok(f) = Frame::decode(&mut d) {
- frames.push(QuicFrame::from(&f));
+ frames.push(QuicFrame::from(f));
} else {
qinfo!("qlog: invalid frame");
break;
@@ -293,7 +293,7 @@ pub fn packet_received(
while d.remaining() > 0 {
if let Ok(f) = Frame::decode(&mut d) {
- frames.push(QuicFrame::from(&f));
+ frames.push(QuicFrame::from(f));
} else {
qinfo!("qlog: invalid frame");
break;
@@ -387,21 +387,26 @@ pub fn metrics_updated(qlog: &mut NeqoQlog, updated_metrics: &[QlogMetric]) {
#[allow(clippy::too_many_lines)] // Yeah, but it's a nice match.
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)] // No choice here.
-impl From<&Frame<'_>> for QuicFrame {
- fn from(frame: &Frame) -> Self {
+impl From<Frame<'_>> for QuicFrame {
+ fn from(frame: Frame) -> Self {
match frame {
- // TODO: Add payload length to `QuicFrame::Padding` once
- // https://github.com/cloudflare/quiche/pull/1745 is available via the qlog crate.
- Frame::Padding { .. } => QuicFrame::Padding,
- Frame::Ping => QuicFrame::Ping,
+ Frame::Padding(len) => QuicFrame::Padding {
+ length: None,
+ payload_length: u32::from(len),
+ },
+ Frame::Ping => QuicFrame::Ping {
+ length: None,
+ payload_length: None,
+ },
Frame::Ack {
largest_acknowledged,
ack_delay,
first_ack_range,
ack_ranges,
+ ecn_count,
} => {
let ranges =
- Frame::decode_ack_frame(*largest_acknowledged, *first_ack_range, ack_ranges)
+ Frame::decode_ack_frame(largest_acknowledged, first_ack_range, &ack_ranges)
.ok();
let acked_ranges = ranges.map(|all| {
@@ -413,11 +418,13 @@ impl From<&Frame<'_>> for QuicFrame {
});
QuicFrame::Ack {
- ack_delay: Some(*ack_delay as f32 / 1000.0),
+ ack_delay: Some(ack_delay as f32 / 1000.0),
acked_ranges,
- ect1: None,
- ect0: None,
- ce: None,
+ ect1: ecn_count.map(|c| c[IpTosEcn::Ect1]),
+ ect0: ecn_count.map(|c| c[IpTosEcn::Ect0]),
+ ce: ecn_count.map(|c| c[IpTosEcn::Ce]),
+ length: None,
+ payload_length: None,
}
}
Frame::ResetStream {
@@ -426,18 +433,22 @@ impl From<&Frame<'_>> for QuicFrame {
final_size,
} => QuicFrame::ResetStream {
stream_id: stream_id.as_u64(),
- error_code: *application_error_code,
- final_size: *final_size,
+ error_code: application_error_code,
+ final_size,
+ length: None,
+ payload_length: None,
},
Frame::StopSending {
stream_id,
application_error_code,
} => QuicFrame::StopSending {
stream_id: stream_id.as_u64(),
- error_code: *application_error_code,
+ error_code: application_error_code,
+ length: None,
+ payload_length: None,
},
Frame::Crypto { offset, data } => QuicFrame::Crypto {
- offset: *offset,
+ offset,
length: data.len() as u64,
},
Frame::NewToken { token } => QuicFrame::NewToken {
@@ -459,20 +470,20 @@ impl From<&Frame<'_>> for QuicFrame {
..
} => QuicFrame::Stream {
stream_id: stream_id.as_u64(),
- offset: *offset,
+ offset,
length: data.len() as u64,
- fin: Some(*fin),
+ fin: Some(fin),
raw: None,
},
Frame::MaxData { maximum_data } => QuicFrame::MaxData {
- maximum: *maximum_data,
+ maximum: maximum_data,
},
Frame::MaxStreamData {
stream_id,
maximum_stream_data,
} => QuicFrame::MaxStreamData {
stream_id: stream_id.as_u64(),
- maximum: *maximum_stream_data,
+ maximum: maximum_stream_data,
},
Frame::MaxStreams {
stream_type,
@@ -482,15 +493,15 @@ impl From<&Frame<'_>> for QuicFrame {
NeqoStreamType::BiDi => StreamType::Bidirectional,
NeqoStreamType::UniDi => StreamType::Unidirectional,
},
- maximum: *maximum_streams,
+ maximum: maximum_streams,
},
- Frame::DataBlocked { data_limit } => QuicFrame::DataBlocked { limit: *data_limit },
+ Frame::DataBlocked { data_limit } => QuicFrame::DataBlocked { limit: data_limit },
Frame::StreamDataBlocked {
stream_id,
stream_data_limit,
} => QuicFrame::StreamDataBlocked {
stream_id: stream_id.as_u64(),
- limit: *stream_data_limit,
+ limit: stream_data_limit,
},
Frame::StreamsBlocked {
stream_type,
@@ -500,7 +511,7 @@ impl From<&Frame<'_>> for QuicFrame {
NeqoStreamType::BiDi => StreamType::Bidirectional,
NeqoStreamType::UniDi => StreamType::Unidirectional,
},
- limit: *stream_limit,
+ limit: stream_limit,
},
Frame::NewConnectionId {
sequence_number,
@@ -508,14 +519,14 @@ impl From<&Frame<'_>> for QuicFrame {
connection_id,
stateless_reset_token,
} => QuicFrame::NewConnectionId {
- sequence_number: *sequence_number as u32,
- retire_prior_to: *retire_prior as u32,
+ sequence_number: sequence_number as u32,
+ retire_prior_to: retire_prior as u32,
connection_id_length: Some(connection_id.len() as u8),
connection_id: hex(connection_id),
stateless_reset_token: Some(hex(stateless_reset_token)),
},
Frame::RetireConnectionId { sequence_number } => QuicFrame::RetireConnectionId {
- sequence_number: *sequence_number as u32,
+ sequence_number: sequence_number as u32,
},
Frame::PathChallenge { data } => QuicFrame::PathChallenge {
data: Some(hex(data)),
@@ -534,8 +545,8 @@ impl From<&Frame<'_>> for QuicFrame {
},
error_code: Some(error_code.code()),
error_code_value: Some(0),
- reason: Some(String::from_utf8_lossy(reason_phrase).to_string()),
- trigger_frame_type: Some(*frame_type),
+ reason: Some(reason_phrase),
+ trigger_frame_type: Some(frame_type),
},
Frame::HandshakeDone => QuicFrame::HandshakeDone,
Frame::AckFrequency { .. } => QuicFrame::Unknown {
diff --git a/third_party/rust/neqo-transport/src/recovery.rs b/third_party/rust/neqo-transport/src/recovery.rs
index dbea3aaf57..22a635d9f3 100644
--- a/third_party/rust/neqo-transport/src/recovery.rs
+++ b/third_party/rust/neqo-transport/src/recovery.rs
@@ -21,6 +21,7 @@ use crate::{
ackrate::AckRate,
cid::ConnectionIdEntry,
crypto::CryptoRecoveryToken,
+ ecn::EcnCount,
packet::PacketNumber,
path::{Path, PathRef},
qlog::{self, QlogMetric},
@@ -665,12 +666,14 @@ impl LossRecovery {
}
/// Returns (acked packets, lost packets)
+ #[allow(clippy::too_many_arguments)]
pub fn on_ack_received<R>(
&mut self,
primary_path: &PathRef,
pn_space: PacketNumberSpace,
largest_acked: u64,
acked_ranges: R,
+ ack_ecn: Option<EcnCount>,
ack_delay: Duration,
now: Instant,
) -> (Vec<SentPacket>, Vec<SentPacket>)
@@ -692,10 +695,10 @@ impl LossRecovery {
let (acked_packets, any_ack_eliciting) =
space.remove_acked(acked_ranges, &mut self.stats.borrow_mut());
- if acked_packets.is_empty() {
+ let Some(largest_acked_pkt) = acked_packets.first() else {
// No new information.
return (Vec::new(), Vec::new());
- }
+ };
// Track largest PN acked per space
let prev_largest_acked = space.largest_acked_sent_time;
@@ -704,7 +707,6 @@ impl LossRecovery {
// If the largest acknowledged is newly acked and any newly acked
// packet was ack-eliciting, update the RTT. (-recovery 5.1)
- let largest_acked_pkt = acked_packets.first().expect("must be there");
space.largest_acked_sent_time = Some(largest_acked_pkt.time_sent);
if any_ack_eliciting && largest_acked_pkt.on_primary_path() {
self.rtt_sample(
@@ -744,7 +746,7 @@ impl LossRecovery {
// when it shouldn't.
primary_path
.borrow_mut()
- .on_packets_acked(&acked_packets, now);
+ .on_packets_acked(&acked_packets, ack_ecn, now);
self.pto_state = None;
@@ -1022,7 +1024,7 @@ mod tests {
time::{Duration, Instant},
};
- use neqo_common::qlog::NeqoQlog;
+ use neqo_common::{qlog::NeqoQlog, IpTosEcn};
use test_fixture::{now, DEFAULT_ADDR};
use super::{
@@ -1031,6 +1033,7 @@ mod tests {
use crate::{
cc::CongestionControlAlgorithm,
cid::{ConnectionId, ConnectionIdEntry},
+ ecn::EcnCount,
packet::PacketType,
path::{Path, PathRef},
rtt::RttEstimate,
@@ -1060,6 +1063,7 @@ mod tests {
pn_space: PacketNumberSpace,
largest_acked: u64,
acked_ranges: Vec<RangeInclusive<u64>>,
+ ack_ecn: Option<EcnCount>,
ack_delay: Duration,
now: Instant,
) -> (Vec<SentPacket>, Vec<SentPacket>) {
@@ -1068,6 +1072,7 @@ mod tests {
pn_space,
largest_acked,
acked_ranges,
+ ack_ecn,
ack_delay,
now,
)
@@ -1208,6 +1213,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Short,
pn,
+ IpTosEcn::default(),
pn_time(pn),
true,
Vec::new(),
@@ -1223,6 +1229,7 @@ mod tests {
PacketNumberSpace::ApplicationData,
pn,
vec![pn..=pn],
+ None,
ACK_DELAY,
pn_time(pn) + delay,
);
@@ -1233,6 +1240,7 @@ mod tests {
lrs.on_packet_sent(SentPacket::new(
PacketType::Short,
pn,
+ IpTosEcn::default(),
pn_time(pn),
true,
Vec::new(),
@@ -1353,6 +1361,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Short,
0,
+ IpTosEcn::default(),
pn_time(0),
true,
Vec::new(),
@@ -1361,6 +1370,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Short,
1,
+ IpTosEcn::default(),
pn_time(0) + TEST_RTT / 4,
true,
Vec::new(),
@@ -1370,6 +1380,7 @@ mod tests {
PacketNumberSpace::ApplicationData,
1,
vec![1..=1],
+ None,
ACK_DELAY,
pn_time(0) + (TEST_RTT * 5 / 4),
);
@@ -1393,6 +1404,7 @@ mod tests {
PacketNumberSpace::ApplicationData,
2,
vec![2..=2],
+ None,
ACK_DELAY,
pn2_ack_time,
);
@@ -1422,6 +1434,7 @@ mod tests {
PacketNumberSpace::ApplicationData,
4,
vec![2..=4],
+ None,
ACK_DELAY,
pn_time(4),
);
@@ -1450,6 +1463,7 @@ mod tests {
PacketNumberSpace::Initial,
0,
vec![],
+ None,
Duration::from_millis(0),
pn_time(0),
);
@@ -1463,6 +1477,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Initial,
0,
+ IpTosEcn::default(),
pn_time(0),
true,
Vec::new(),
@@ -1471,6 +1486,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Handshake,
0,
+ IpTosEcn::default(),
pn_time(1),
true,
Vec::new(),
@@ -1479,6 +1495,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Short,
0,
+ IpTosEcn::default(),
pn_time(2),
true,
Vec::new(),
@@ -1491,10 +1508,25 @@ mod tests {
PacketType::Handshake,
PacketType::Short,
] {
- let sent_pkt = SentPacket::new(*sp, 1, pn_time(3), true, Vec::new(), ON_SENT_SIZE);
+ let sent_pkt = SentPacket::new(
+ *sp,
+ 1,
+ IpTosEcn::default(),
+ pn_time(3),
+ true,
+ Vec::new(),
+ ON_SENT_SIZE,
+ );
let pn_space = PacketNumberSpace::from(sent_pkt.pt);
lr.on_packet_sent(sent_pkt);
- lr.on_ack_received(pn_space, 1, vec![1..=1], Duration::from_secs(0), pn_time(3));
+ lr.on_ack_received(
+ pn_space,
+ 1,
+ vec![1..=1],
+ None,
+ Duration::from_secs(0),
+ pn_time(3),
+ );
let mut lost = Vec::new();
lr.spaces.get_mut(pn_space).unwrap().detect_lost_packets(
pn_time(3),
@@ -1516,6 +1548,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Initial,
0,
+ IpTosEcn::default(),
pn_time(3),
true,
Vec::new(),
@@ -1530,6 +1563,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Initial,
0,
+ IpTosEcn::default(),
now(),
true,
Vec::new(),
@@ -1542,6 +1576,7 @@ mod tests {
PacketNumberSpace::Initial,
0,
vec![0..=0],
+ None,
Duration::new(0, 0),
now() + rtt,
);
@@ -1549,6 +1584,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Handshake,
0,
+ IpTosEcn::default(),
now(),
true,
Vec::new(),
@@ -1557,6 +1593,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Short,
0,
+ IpTosEcn::default(),
now(),
true,
Vec::new(),
@@ -1594,6 +1631,7 @@ mod tests {
lr.on_packet_sent(SentPacket::new(
PacketType::Initial,
1,
+ IpTosEcn::default(),
now(),
true,
Vec::new(),
diff --git a/third_party/rust/neqo-transport/src/send_stream.rs b/third_party/rust/neqo-transport/src/send_stream.rs
index 8771ec7765..98476e9d18 100644
--- a/third_party/rust/neqo-transport/src/send_stream.rs
+++ b/third_party/rust/neqo-transport/src/send_stream.rs
@@ -1269,7 +1269,7 @@ impl SendStream {
return Err(Error::FinalSizeError);
}
- let buf = if buf.is_empty() || (self.avail() == 0) {
+ let buf = if self.avail() == 0 {
return Ok(0);
} else if self.avail() < buf.len() {
if atomic {
@@ -1634,20 +1634,16 @@ impl SendStreams {
}
pub fn remove_terminal(&mut self) {
- let map: &mut IndexMap<StreamId, SendStream> = &mut self.map;
- let regular: &mut OrderGroup = &mut self.regular;
- let sendordered: &mut BTreeMap<SendOrder, OrderGroup> = &mut self.sendordered;
-
- // Take refs to all the items we need to modify instead of &mut
- // self to keep the compiler happy (if we use self.map.retain it
- // gets upset due to borrows)
- map.retain(|stream_id, stream| {
+ self.map.retain(|stream_id, stream| {
if stream.is_terminal() {
if stream.is_fair() {
match stream.sendorder() {
- None => regular.remove(*stream_id),
+ None => self.regular.remove(*stream_id),
Some(sendorder) => {
- sendordered.get_mut(&sendorder).unwrap().remove(*stream_id);
+ self.sendordered
+ .get_mut(&sendorder)
+ .unwrap()
+ .remove(*stream_id);
}
};
}
diff --git a/third_party/rust/neqo-transport/src/sender.rs b/third_party/rust/neqo-transport/src/sender.rs
index 3a54851533..abb14d0a25 100644
--- a/third_party/rust/neqo-transport/src/sender.rs
+++ b/third_party/rust/neqo-transport/src/sender.rs
@@ -97,6 +97,11 @@ impl PacketSender {
)
}
+ /// Called when ECN CE mark received. Returns true if the congestion window was reduced.
+ pub fn on_ecn_ce_received(&mut self, largest_acked_pkt: &SentPacket) -> bool {
+ self.cc.on_ecn_ce_received(largest_acked_pkt)
+ }
+
pub fn discard(&mut self, pkt: &SentPacket) {
self.cc.discard(pkt);
}
diff --git a/third_party/rust/neqo-transport/src/server.rs b/third_party/rust/neqo-transport/src/server.rs
index 96a6244ef1..60909d71e1 100644
--- a/third_party/rust/neqo-transport/src/server.rs
+++ b/third_party/rust/neqo-transport/src/server.rs
@@ -689,6 +689,13 @@ impl Server {
mem::take(&mut self.active).into_iter().collect()
}
+ /// Whether any connections have received new events as a result of calling
+ /// `process()`.
+ #[must_use]
+ pub fn has_active_connections(&self) -> bool {
+ !self.active.is_empty()
+ }
+
pub fn add_to_waiting(&mut self, c: &ActiveConnectionRef) {
self.waiting.push_back(c.connection());
}
diff --git a/third_party/rust/neqo-transport/src/tracking.rs b/third_party/rust/neqo-transport/src/tracking.rs
index bdd0f250c7..6643d516e3 100644
--- a/third_party/rust/neqo-transport/src/tracking.rs
+++ b/third_party/rust/neqo-transport/src/tracking.rs
@@ -13,18 +13,21 @@ use std::{
time::{Duration, Instant},
};
-use neqo_common::{qdebug, qinfo, qtrace, qwarn};
+use enum_map::Enum;
+use neqo_common::{qdebug, qinfo, qtrace, qwarn, IpTosEcn};
use neqo_crypto::{Epoch, TLS_EPOCH_HANDSHAKE, TLS_EPOCH_INITIAL};
use smallvec::{smallvec, SmallVec};
use crate::{
+ ecn::EcnCount,
+ frame::{FRAME_TYPE_ACK, FRAME_TYPE_ACK_ECN},
packet::{PacketBuilder, PacketNumber, PacketType},
recovery::RecoveryToken,
stats::FrameStats,
};
// TODO(mt) look at enabling EnumMap for this: https://stackoverflow.com/a/44905797/1375574
-#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Enum)]
pub enum PacketNumberSpace {
Initial,
Handshake,
@@ -134,6 +137,7 @@ impl std::fmt::Debug for PacketNumberSpaceSet {
pub struct SentPacket {
pub pt: PacketType,
pub pn: PacketNumber,
+ pub ecn_mark: IpTosEcn,
ack_eliciting: bool,
pub time_sent: Instant,
primary_path: bool,
@@ -150,6 +154,7 @@ impl SentPacket {
pub fn new(
pt: PacketType,
pn: PacketNumber,
+ ecn_mark: IpTosEcn,
time_sent: Instant,
ack_eliciting: bool,
tokens: Vec<RecoveryToken>,
@@ -158,6 +163,7 @@ impl SentPacket {
Self {
pt,
pn,
+ ecn_mark,
time_sent,
ack_eliciting,
primary_path: true,
@@ -377,6 +383,8 @@ pub struct RecvdPackets {
/// Whether we are ignoring packets that arrive out of order
/// for the purposes of generating immediate acknowledgment.
ignore_order: bool,
+ // The counts of different ECN marks that have been received.
+ ecn_count: EcnCount,
}
impl RecvdPackets {
@@ -394,9 +402,15 @@ impl RecvdPackets {
unacknowledged_count: 0,
unacknowledged_tolerance: DEFAULT_ACK_PACKET_TOLERANCE,
ignore_order: false,
+ ecn_count: EcnCount::default(),
}
}
+ /// Get the ECN counts.
+ pub fn ecn_marks(&mut self) -> &mut EcnCount {
+ &mut self.ecn_count
+ }
+
/// Get the time at which the next ACK should be sent.
pub fn ack_time(&self) -> Option<Instant> {
self.ack_time
@@ -545,6 +559,10 @@ impl RecvdPackets {
}
}
+ /// Length of the worst possible ACK frame, assuming only one range and ECN counts.
+ /// Note that this assumes one byte for the type and count of extra ranges.
+ pub const USEFUL_ACK_LEN: usize = 1 + 8 + 8 + 1 + 8 + 3 * 8;
+
/// Generate an ACK frame for this packet number space.
///
/// Unlike other frame generators this doesn't modify the underlying instance
@@ -563,10 +581,6 @@ impl RecvdPackets {
tokens: &mut Vec<RecoveryToken>,
stats: &mut FrameStats,
) {
- // The worst possible ACK frame, assuming only one range.
- // Note that this assumes one byte for the type and count of extra ranges.
- const LONGEST_ACK_HEADER: usize = 1 + 8 + 8 + 1 + 8;
-
// Check that we aren't delaying ACKs.
if !self.ack_now(now, rtt) {
return;
@@ -578,7 +592,10 @@ impl RecvdPackets {
// When congestion limited, ACK-only packets are 255 bytes at most
// (`recovery::ACK_ONLY_SIZE_LIMIT - 1`). This results in limiting the
// ranges to 13 here.
- let max_ranges = if let Some(avail) = builder.remaining().checked_sub(LONGEST_ACK_HEADER) {
+ let max_ranges = if let Some(avail) = builder
+ .remaining()
+ .checked_sub(RecvdPackets::USEFUL_ACK_LEN)
+ {
// Apply a hard maximum to keep plenty of space for other stuff.
min(1 + (avail / 16), MAX_ACKS_PER_FRAME)
} else {
@@ -593,7 +610,11 @@ impl RecvdPackets {
.cloned()
.collect::<Vec<_>>();
- builder.encode_varint(crate::frame::FRAME_TYPE_ACK);
+ builder.encode_varint(if self.ecn_count.is_some() {
+ FRAME_TYPE_ACK_ECN
+ } else {
+ FRAME_TYPE_ACK
+ });
let mut iter = ranges.iter();
let Some(first) = iter.next() else { return };
builder.encode_varint(first.largest);
@@ -617,6 +638,12 @@ impl RecvdPackets {
last = r.smallest;
}
+ if self.ecn_count.is_some() {
+ builder.encode_varint(self.ecn_count[IpTosEcn::Ect0]);
+ builder.encode_varint(self.ecn_count[IpTosEcn::Ect1]);
+ builder.encode_varint(self.ecn_count[IpTosEcn::Ce]);
+ }
+
// We've sent an ACK, reset the timer.
self.ack_time = None;
self.last_ack_time = Some(now);
@@ -1134,7 +1161,9 @@ mod tests {
.is_some());
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
- builder.set_limit(32);
+ // The code pessimistically assumes that each range needs 16 bytes to express.
+ // So this won't be enough for a second range.
+ builder.set_limit(RecvdPackets::USEFUL_ACK_LEN + 8);
let mut stats = FrameStats::default();
tracker.write_frame(
diff --git a/third_party/rust/neqo-transport/tests/common/mod.rs b/third_party/rust/neqo-transport/tests/common/mod.rs
index e36e66f753..ecbbe1c3ce 100644
--- a/third_party/rust/neqo-transport/tests/common/mod.rs
+++ b/third_party/rust/neqo-transport/tests/common/mod.rs
@@ -84,114 +84,6 @@ pub fn connect(client: &mut Connection, server: &mut Server) -> ActiveConnection
connected_server(server)
}
-// Decode the header of a client Initial packet, returning three values:
-// * the entire header short of the packet number,
-// * just the DCID,
-// * just the SCID, and
-// * the protected payload including the packet number.
-// Any token is thrown away.
-#[must_use]
-pub fn decode_initial_header(dgram: &Datagram, role: Role) -> (&[u8], &[u8], &[u8], &[u8]) {
- let mut dec = Decoder::new(&dgram[..]);
- let type_and_ver = dec.decode(5).unwrap().to_vec();
- // The client sets the QUIC bit, the server might not.
- match role {
- Role::Client => assert_eq!(type_and_ver[0] & 0xf0, 0xc0),
- Role::Server => assert_eq!(type_and_ver[0] & 0xb0, 0x80),
- }
- let dest_cid = dec.decode_vec(1).unwrap();
- let src_cid = dec.decode_vec(1).unwrap();
- dec.skip_vvec(); // Ignore any the token.
-
- // Need to read of the length separately so that we can find the packet number.
- let payload_len = usize::try_from(dec.decode_varint().unwrap()).unwrap();
- let pn_offset = dgram.len() - dec.remaining();
- (
- &dgram[..pn_offset],
- dest_cid,
- src_cid,
- dec.decode(payload_len).unwrap(),
- )
-}
-
-/// Generate an AEAD and header protection object for a client Initial.
-/// Note that this works for QUIC version 1 only.
-#[must_use]
-pub fn initial_aead_and_hp(dcid: &[u8], role: Role) -> (Aead, HpKey) {
- const INITIAL_SALT: &[u8] = &[
- 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c,
- 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
- ];
- let initial_secret = hkdf::extract(
- TLS_VERSION_1_3,
- TLS_AES_128_GCM_SHA256,
- Some(
- hkdf::import_key(TLS_VERSION_1_3, INITIAL_SALT)
- .as_ref()
- .unwrap(),
- ),
- hkdf::import_key(TLS_VERSION_1_3, dcid).as_ref().unwrap(),
- )
- .unwrap();
-
- let secret = hkdf::expand_label(
- TLS_VERSION_1_3,
- TLS_AES_128_GCM_SHA256,
- &initial_secret,
- &[],
- match role {
- Role::Client => "client in",
- Role::Server => "server in",
- },
- )
- .unwrap();
- (
- Aead::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic ").unwrap(),
- HpKey::extract(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic hp").unwrap(),
- )
-}
-
-// Remove header protection, returning the unmasked header and the packet number.
-#[must_use]
-pub fn remove_header_protection(hp: &HpKey, header: &[u8], payload: &[u8]) -> (Vec<u8>, u64) {
- // Make a copy of the header that can be modified.
- let mut fixed_header = header.to_vec();
- let pn_offset = header.len();
- // Save 4 extra in case the packet number is that long.
- fixed_header.extend_from_slice(&payload[..4]);
-
- // Sample for masking and apply the mask.
- let mask = hp.mask(&payload[4..20]).unwrap();
- fixed_header[0] ^= mask[0] & 0xf;
- let pn_len = 1 + usize::from(fixed_header[0] & 0x3);
- for i in 0..pn_len {
- fixed_header[pn_offset + i] ^= mask[1 + i];
- }
- // Trim down to size.
- fixed_header.truncate(pn_offset + pn_len);
- // The packet number should be 1.
- let pn = Decoder::new(&fixed_header[pn_offset..])
- .decode_uint(pn_len)
- .unwrap();
-
- (fixed_header, pn)
-}
-
-pub fn apply_header_protection(hp: &HpKey, packet: &mut [u8], pn_bytes: Range<usize>) {
- let sample_start = pn_bytes.start + 4;
- let sample_end = sample_start + 16;
- let mask = hp.mask(&packet[sample_start..sample_end]).unwrap();
- qtrace!(
- "sample={} mask={}",
- hex_with_len(&packet[sample_start..sample_end]),
- hex_with_len(&mask)
- );
- packet[0] ^= mask[0] & 0xf;
- for i in 0..(pn_bytes.end - pn_bytes.start) {
- packet[pn_bytes.start + i] ^= mask[1 + i];
- }
-}
-
/// Scrub through client events to find a resumption token.
pub fn find_ticket(client: &mut Connection) -> ResumptionToken {
client
diff --git a/third_party/rust/neqo-transport/tests/connection.rs b/third_party/rust/neqo-transport/tests/connection.rs
index b8877b946d..3cc711f80b 100644
--- a/third_party/rust/neqo-transport/tests/connection.rs
+++ b/third_party/rust/neqo-transport/tests/connection.rs
@@ -6,12 +6,16 @@
mod common;
-use common::{
- apply_header_protection, decode_initial_header, initial_aead_and_hp, remove_header_protection,
-};
use neqo_common::{Datagram, Decoder, Encoder, Role};
-use neqo_transport::{ConnectionError, ConnectionParameters, Error, State, Version};
-use test_fixture::{default_client, default_server, new_client, now, split_datagram};
+use neqo_transport::{CloseReason, ConnectionParameters, Error, State, Version};
+use test_fixture::{
+ default_client, default_server,
+ header_protection::{
+ apply_header_protection, decode_initial_header, initial_aead_and_hp,
+ remove_header_protection,
+ },
+ new_client, now, split_datagram,
+};
#[test]
fn connect() {
@@ -58,8 +62,8 @@ fn truncate_long_packet() {
/// Test that reordering parts of the server Initial doesn't change things.
#[test]
fn reorder_server_initial() {
- // A simple ACK frame for a single packet with packet number 0.
- const ACK_FRAME: &[u8] = &[0x02, 0x00, 0x00, 0x00, 0x00];
+ // A simple ACK_ECN frame for a single packet with packet number 0 with a single ECT(0) mark.
+ const ACK_FRAME: &[u8] = &[0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00];
let mut client = new_client(
ConnectionParameters::default().versions(Version::Version1, vec![Version::Version1]),
@@ -68,12 +72,13 @@ fn reorder_server_initial() {
let client_initial = client.process_output(now());
let (_, client_dcid, _, _) =
- decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client);
+ decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client).unwrap();
let client_dcid = client_dcid.to_owned();
let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram();
let (server_initial, server_hs) = split_datagram(server_packet.as_ref().unwrap());
- let (protected_header, _, _, payload) = decode_initial_header(&server_initial, Role::Server);
+ let (protected_header, _, _, payload) =
+ decode_initial_header(&server_initial, Role::Server).unwrap();
// Now decrypt the packet.
let (aead, hp) = initial_aead_and_hp(&client_dcid, Role::Server);
@@ -130,7 +135,7 @@ fn reorder_server_initial() {
fn set_payload(server_packet: &Option<Datagram>, client_dcid: &[u8], payload: &[u8]) -> Datagram {
let (server_initial, _server_hs) = split_datagram(server_packet.as_ref().unwrap());
let (protected_header, _, _, orig_payload) =
- decode_initial_header(&server_initial, Role::Server);
+ decode_initial_header(&server_initial, Role::Server).unwrap();
// Now decrypt the packet.
let (aead, hp) = initial_aead_and_hp(client_dcid, Role::Server);
@@ -168,14 +173,14 @@ fn packet_without_frames() {
let client_initial = client.process_output(now());
let (_, client_dcid, _, _) =
- decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client);
+ decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client).unwrap();
let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram();
let modified = set_payload(&server_packet, client_dcid, &[]);
client.process_input(&modified, now());
assert_eq!(
client.state(),
- &State::Closed(ConnectionError::Transport(Error::ProtocolViolation))
+ &State::Closed(CloseReason::Transport(Error::ProtocolViolation))
);
}
@@ -189,7 +194,7 @@ fn packet_with_only_padding() {
let client_initial = client.process_output(now());
let (_, client_dcid, _, _) =
- decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client);
+ decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client).unwrap();
let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram();
let modified = set_payload(&server_packet, client_dcid, &[0]);
@@ -208,7 +213,7 @@ fn overflow_crypto() {
let client_initial = client.process_output(now()).dgram();
let (_, client_dcid, _, _) =
- decode_initial_header(client_initial.as_ref().unwrap(), Role::Client);
+ decode_initial_header(client_initial.as_ref().unwrap(), Role::Client).unwrap();
let client_dcid = client_dcid.to_owned();
let server_packet = server.process(client_initial.as_ref(), now()).dgram();
@@ -217,7 +222,8 @@ fn overflow_crypto() {
// Now decrypt the server packet to get AEAD and HP instances.
// We won't be using the packet, but making new ones.
let (aead, hp) = initial_aead_and_hp(&client_dcid, Role::Server);
- let (_, server_dcid, server_scid, _) = decode_initial_header(&server_initial, Role::Server);
+ let (_, server_dcid, server_scid, _) =
+ decode_initial_header(&server_initial, Role::Server).unwrap();
// Send in 100 packets, each with 1000 bytes of crypto frame data each,
// eventually this will overrun the buffer we keep for crypto data.
@@ -260,10 +266,7 @@ fn overflow_crypto() {
client.process_input(&dgram, now());
if let State::Closing { error, .. } = client.state() {
assert!(
- matches!(
- error,
- ConnectionError::Transport(Error::CryptoBufferExceeded),
- ),
+ matches!(error, CloseReason::Transport(Error::CryptoBufferExceeded),),
"the connection need to abort on crypto buffer"
);
assert!(pn > 64, "at least 64000 bytes of data is buffered");
diff --git a/third_party/rust/neqo-transport/tests/network.rs b/third_party/rust/neqo-transport/tests/network.rs
index 27e5a83cd6..68a835a436 100644
--- a/third_party/rust/neqo-transport/tests/network.rs
+++ b/third_party/rust/neqo-transport/tests/network.rs
@@ -6,7 +6,7 @@
use std::{ops::Range, time::Duration};
-use neqo_transport::{ConnectionError, ConnectionParameters, Error, State};
+use neqo_transport::{CloseReason, ConnectionParameters, Error, State};
use test_fixture::{
boxed,
sim::{
@@ -48,10 +48,10 @@ simulate!(
idle_timeout,
[
ConnectionNode::default_client(boxed![ReachState::new(State::Closed(
- ConnectionError::Transport(Error::IdleTimeout)
+ CloseReason::Transport(Error::IdleTimeout)
))]),
ConnectionNode::default_server(boxed![ReachState::new(State::Closed(
- ConnectionError::Transport(Error::IdleTimeout)
+ CloseReason::Transport(Error::IdleTimeout)
))]),
]
);
@@ -62,7 +62,7 @@ simulate!(
ConnectionNode::new_client(
ConnectionParameters::default().idle_timeout(weeks(1000)),
boxed![ReachState::new(State::Confirmed),],
- boxed![ReachState::new(State::Closed(ConnectionError::Transport(
+ boxed![ReachState::new(State::Closed(CloseReason::Transport(
Error::IdleTimeout
)))]
),
@@ -71,7 +71,7 @@ simulate!(
ConnectionNode::new_server(
ConnectionParameters::default().idle_timeout(weeks(1000)),
boxed![ReachState::new(State::Confirmed),],
- boxed![ReachState::new(State::Closed(ConnectionError::Transport(
+ boxed![ReachState::new(State::Closed(CloseReason::Transport(
Error::IdleTimeout
)))]
),
diff --git a/third_party/rust/neqo-transport/tests/retry.rs b/third_party/rust/neqo-transport/tests/retry.rs
index 36eff71e7b..3f95511c3e 100644
--- a/third_party/rust/neqo-transport/tests/retry.rs
+++ b/third_party/rust/neqo-transport/tests/retry.rs
@@ -14,14 +14,18 @@ use std::{
time::Duration,
};
-use common::{
- apply_header_protection, connected_server, decode_initial_header, default_server,
- generate_ticket, initial_aead_and_hp, remove_header_protection,
-};
+use common::{connected_server, default_server, generate_ticket};
use neqo_common::{hex_with_len, qdebug, qtrace, Datagram, Encoder, Role};
use neqo_crypto::AuthenticationStatus;
-use neqo_transport::{server::ValidateAddress, ConnectionError, Error, State, StreamType};
-use test_fixture::{assertions, datagram, default_client, now, split_datagram};
+use neqo_transport::{server::ValidateAddress, CloseReason, Error, State, StreamType};
+use test_fixture::{
+ assertions, datagram, default_client,
+ header_protection::{
+ apply_header_protection, decode_initial_header, initial_aead_and_hp,
+ remove_header_protection,
+ },
+ now, split_datagram,
+};
#[test]
fn retry_basic() {
@@ -400,7 +404,7 @@ fn mitm_retry() {
// rewriting the header to remove the token, and then re-encrypting.
let client_initial2 = client_initial2.unwrap();
let (protected_header, d_cid, s_cid, payload) =
- decode_initial_header(&client_initial2, Role::Client);
+ decode_initial_header(&client_initial2, Role::Client).unwrap();
// Now we have enough information to make keys.
let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client);
@@ -465,7 +469,7 @@ fn mitm_retry() {
assert!(matches!(
*client.state(),
State::Closing {
- error: ConnectionError::Transport(Error::ProtocolViolation),
+ error: CloseReason::Transport(Error::ProtocolViolation),
..
}
));
diff --git a/third_party/rust/neqo-transport/tests/server.rs b/third_party/rust/neqo-transport/tests/server.rs
index 7388e0fee7..4740d26ded 100644
--- a/third_party/rust/neqo-transport/tests/server.rs
+++ b/third_party/rust/neqo-transport/tests/server.rs
@@ -8,21 +8,22 @@ mod common;
use std::{cell::RefCell, mem, net::SocketAddr, rc::Rc, time::Duration};
-use common::{
- apply_header_protection, connect, connected_server, decode_initial_header, default_server,
- find_ticket, generate_ticket, initial_aead_and_hp, new_server, remove_header_protection,
-};
+use common::{connect, connected_server, default_server, find_ticket, generate_ticket, new_server};
use neqo_common::{qtrace, Datagram, Decoder, Encoder, Role};
use neqo_crypto::{
generate_ech_keys, AllowZeroRtt, AuthenticationStatus, ZeroRttCheckResult, ZeroRttChecker,
};
use neqo_transport::{
server::{ActiveConnectionRef, Server, ValidateAddress},
- Connection, ConnectionError, ConnectionParameters, Error, Output, State, StreamType, Version,
+ CloseReason, Connection, ConnectionParameters, Error, Output, State, StreamType, Version,
};
use test_fixture::{
- assertions, datagram, default_client, new_client, now, split_datagram,
- CountingConnectionIdGenerator,
+ assertions, datagram, default_client,
+ header_protection::{
+ apply_header_protection, decode_initial_header, initial_aead_and_hp,
+ remove_header_protection,
+ },
+ new_client, now, split_datagram, CountingConnectionIdGenerator,
};
/// Take a pair of connections in any state and complete the handshake.
@@ -389,7 +390,7 @@ fn bad_client_initial() {
let mut server = default_server();
let dgram = client.process(None, now()).dgram().expect("a datagram");
- let (header, d_cid, s_cid, payload) = decode_initial_header(&dgram, Role::Client);
+ let (header, d_cid, s_cid, payload) = decode_initial_header(&dgram, Role::Client).unwrap();
let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client);
let (fixed_header, pn) = remove_header_protection(&hp, header, payload);
let payload = &payload[(fixed_header.len() - header.len())..];
@@ -462,13 +463,13 @@ fn bad_client_initial() {
assert_ne!(delay, Duration::from_secs(0));
assert!(matches!(
*client.state(),
- State::Draining { error: ConnectionError::Transport(Error::PeerError(code)), .. } if code == Error::ProtocolViolation.code()
+ State::Draining { error: CloseReason::Transport(Error::PeerError(code)), .. } if code == Error::ProtocolViolation.code()
));
for server in server.active_connections() {
assert_eq!(
*server.borrow().state(),
- State::Closed(ConnectionError::Transport(Error::ProtocolViolation))
+ State::Closed(CloseReason::Transport(Error::ProtocolViolation))
);
}
@@ -478,6 +479,65 @@ fn bad_client_initial() {
}
#[test]
+fn bad_client_initial_connection_close() {
+ let mut client = default_client();
+ let mut server = default_server();
+
+ let dgram = client.process(None, now()).dgram().expect("a datagram");
+ let (header, d_cid, s_cid, payload) = decode_initial_header(&dgram, Role::Client).unwrap();
+ let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client);
+ let (_, pn) = remove_header_protection(&hp, header, payload);
+
+ let mut payload_enc = Encoder::with_capacity(1200);
+ payload_enc.encode(&[0x1c, 0x01, 0x00, 0x00]); // Add a CONNECTION_CLOSE frame.
+
+ // Make a new header with a 1 byte packet number length.
+ let mut header_enc = Encoder::new();
+ header_enc
+ .encode_byte(0xc0) // Initial with 1 byte packet number.
+ .encode_uint(4, Version::default().wire_version())
+ .encode_vec(1, d_cid)
+ .encode_vec(1, s_cid)
+ .encode_vvec(&[])
+ .encode_varint(u64::try_from(payload_enc.len() + aead.expansion() + 1).unwrap())
+ .encode_byte(u8::try_from(pn).unwrap());
+
+ let mut ciphertext = header_enc.as_ref().to_vec();
+ ciphertext.resize(header_enc.len() + payload_enc.len() + aead.expansion(), 0);
+ let v = aead
+ .encrypt(
+ pn,
+ header_enc.as_ref(),
+ payload_enc.as_ref(),
+ &mut ciphertext[header_enc.len()..],
+ )
+ .unwrap();
+ assert_eq!(header_enc.len() + v.len(), ciphertext.len());
+ // Pad with zero to get up to 1200.
+ ciphertext.resize(1200, 0);
+
+ apply_header_protection(
+ &hp,
+ &mut ciphertext,
+ (header_enc.len() - 1)..header_enc.len(),
+ );
+ let bad_dgram = Datagram::new(
+ dgram.source(),
+ dgram.destination(),
+ dgram.tos(),
+ dgram.ttl(),
+ ciphertext,
+ );
+
+ // The server should ignore this and go to Draining.
+ let mut now = now();
+ let response = server.process(Some(&bad_dgram), now);
+ now += response.callback();
+ let response = server.process(None, now);
+ assert_eq!(response, Output::None);
+}
+
+#[test]
fn version_negotiation_ignored() {
let mut server = default_server();
let mut client = default_client();
@@ -774,3 +834,16 @@ fn ech() {
.ech_accepted()
.unwrap());
}
+
+#[test]
+fn has_active_connections() {
+ let mut server = default_server();
+ let mut client = default_client();
+
+ assert!(!server.has_active_connections());
+
+ let initial = client.process(None, now());
+ let _ = server.process(initial.as_dgram_ref(), now()).dgram();
+
+ assert!(server.has_active_connections());
+}
diff --git a/third_party/rust/nix/.cargo-checksum.json b/third_party/rust/nix/.cargo-checksum.json
index d48e123da2..3cd04958ea 100644
--- a/third_party/rust/nix/.cargo-checksum.json
+++ b/third_party/rust/nix/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"92468d08ccd20acf93bac25d983dbaedbd6dafbfdebf45d670a557e1dd993650","Cargo.toml":"8e68a73dcb2ac8fd7a01b714c3c08c0148d0cbeb1b8a2bbb30ff10cf0332b505","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"693748b472aa697105dbaf37ad95e41b9b3ed6480533e03a5a93b10ec70c987a","src/dir.rs":"d40e2bc1df553898e718de552ddb57a160b9957b7d6a0f7e27e3e7fe6af536ab","src/env.rs":"028bc5e20139ebba418a655a2978a53335dc7680bf1de43d2c8333dd72cfa5c4","src/errno.rs":"3c2935cc3238c13a545ab8ceb6a8aa9fd03a9cbf72be041e9ea032f6ee19c2f4","src/fcntl.rs":"8cda1abc82c562b2340b3d27176b674b65d0e1c4bf888e7700c6b50e63c3bf0d","src/features.rs":"5381d43a7759c0bf4a26fc25c602d507beafa85282764bdbae6eff59f98fd16d","src/ifaddrs.rs":"377865eb48040d28c392a1aec0221320108e3392ea285d23405ae2cfa5c54b20","src/kmod.rs":"d2ef26c35db790e589f6418c1631aa48b01d4ea5674e050c12d1cfa7a18681ef","src/lib.rs":"571f418caf6a9646939ae4976ec4bde5f9325e9b4320715c9586590b9d8d4963","src/macros.rs":"73ab3b56f4b7cd08d3c70f035cd74bcbdac17ff05946adc875e05fd93280eb7e","src/mount/bsd.rs":"9f12470d33d9b3d18fdba5a10952f6e76b254df3d8794f296437d266db9623c4","src/mount/linux.rs":"6b0ea0c4598f5537e2dc57bdad6d3acc86e29d258aef3a639e1a2308f38bdb0e","src/mount/mod.rs":"ba9f60eb831224ab73bdd87e00e15d13b9ce9efb70b18bf8f3fe60406d522b3e","src/mqueue.rs":"0c78ef1a52c2df05a48b390707764dfca27c056033e01d604a1aa91058c7e9b4","src/net/if_.rs":"fa7413a9676e552b3fa0576081b83ac91278bb0d7240b7cdd962ea911336bba0","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"8b26383af51ff0733e07e6a5a2e174462e8849b1118ca12bdf3540d40a298602","src/pty.rs":"6a1122c4e7ea236cc4e1e36e2eb587eddf1e323edacdbcdd3b3c1619a60eedbf","src/sched.rs":"217055e50a54398e5b75a247e1be9a81a764aadd0267bcf6367f633e9b277f84","src/sys/aio.rs":"3e2e93dff85180a98b2b09b1ea926f89ee17d235c60fd2a96adf0ff7db601e5c","src/sys/epoll.rs":"5c45733ea19802443cc3f9e21766013d4ff0125a52dbf5f5a13f10ff19914e1e","src/sys/event.rs":"9b3b02c42f471e3d9f974be1b60aab11ff4d1fc79692c3d40991f0c22ca9ea83","src/sys/eventfd.rs":"22c1205c948aeb29f7a8a0f298644eb393778585ecbd2091d40559e0ed2de06b","src/sys/inotify.rs":"68b80856937286a23917638ed8f5fc057e396fe7c4f4d1178865e720ba7dba95","src/sys/ioctl/bsd.rs":"bbd02e30b0a78c1cb22777d9b00cfcbba9c68505cffc06118ac68474cf6fea39","src/sys/ioctl/linux.rs":"2aec4b3b3beb8119b9bb0c8001b9bb66cba3f2ff778c432e62f2da4243787184","src/sys/ioctl/mod.rs":"80e683efac7d1e2bd88680f028370f7c778e6a5097cae7845566bc8f43f4ff4f","src/sys/memfd.rs":"e2653a3c476585e993d9e8551cd0f991ba141c6bb46d9ece7fa6fd5cdeb862ae","src/sys/mman.rs":"4604656656a061606f99ff2f117c8f7463cd87aedaa4b3de5de863056bec5499","src/sys/mod.rs":"f5a5f1b51bbd2c865bbda2652bf0d2fd38e0773bd1a37460869c5a7008d27f03","src/sys/personality.rs":"8fbd8b522b8be4591a4cf25cba023884d3ad39b26666708d43eb79b81bf1c203","src/sys/prctl.rs":"d5b695099d4ac1b44e552988f488d7b88d285e68968ac29b93c153da52acd2bf","src/sys/pthread.rs":"258cdf7ff0b61a4afa6d228109e4cb4fb88d859bb8dfe6c959d95130fb010906","src/sys/ptrace/bsd.rs":"4c590d8f023ff52f396f8b6f2150c08e5c9486d3088d9c173db33a70d616b800","src/sys/ptrace/linux.rs":"b14114c4cbefd58f9df48e93e47d8f82992167942d4e683018cd31ceed184bc6","src/sys/ptrace/mod.rs":"3b5e4cc9cf447e989f40c73cb1951a4705322852009023c5a3d7e39ec1e9c39b","src/sys/quota.rs":"421ff70a0749dd0cea37a22a971bf3e9474f627bfa0e37874d9893787271996b","src/sys/reboot.rs":"eacdf57694a6629fb05787e16450446102a62818274495f2ad4e445807d09221","src/sys/resource.rs":"84eba41f288c97b4ab9060a6046d0d34e66a1f8e12655032c60a703280cca832","src/sys/select.rs":"2520086330bc1978a7db183bee92d96ba2711a4505839179a5f082ad555045b2","src/sys/sendfile.rs":"2075cea1ea5967b5de18e5cecb94bc041ff2675f7eb9e223051aa8a52dd8f733","src/sys/signal.rs":"39492bd9a98a48616a2f66a717def527574c6429251b533d8406d2b25cc2cb3f","src/sys/signalfd.rs":"af9eee01d712e48609fddf6b0ec332cd5f80b9940081b4c2e16cc338e959b5f3","src/sys/socket/addr.rs":"1b6f4e1ca16004cd5fa511264076b2c24ccc9cf3d7727157a0fabc62c47fe94a","src/sys/socket/mod.rs":"e65112b3b54905166b7a412fd9811e1e123c5eb1b3b46286937082fa6e86973d","src/sys/socket/sockopt.rs":"386bc08c0faf49a9d0ef99c70538c66b7d426d3deeb7b0ebedee1ef917d7bafc","src/sys/stat.rs":"3928598e6428d7e44b42d36aeb59ac353eaf0270801a6ac72c511804c5fdf358","src/sys/statfs.rs":"852c7e68c094ea8b1f978ee811c1e0bf6a38661c7a07114527697e7aae584dff","src/sys/statvfs.rs":"f699280f3ee2645ce39631d404355e7b49818849c4afa0bdf4f5020931cb1bef","src/sys/sysinfo.rs":"b4519b1ca091c9dbe94d2a6fd6304944bf3df5626973d2c6884022559706f0d9","src/sys/termios.rs":"7c0d9f4bc0062a510cf0f799264f807530c3d1e9e23a0d405d595f395ad7e01c","src/sys/time.rs":"c991d69a892cd7201c53d1399533e45802d581a1afa109016014aa9872d8db53","src/sys/timer.rs":"8c10f0e7cfac857ad00460be30bc68b957909cc9296e70718d3b5d4a0babafde","src/sys/timerfd.rs":"8958120030ed7bb58028b75e7e1829d4d231fa0da2c65f9335df7b7f1e0f6074","src/sys/uio.rs":"0ed960748eb4a85ce8f8413ab478d451f4460e85130cc3b803c85d72c057a529","src/sys/utsname.rs":"0cdda0cc111caaa0e4ebe2d4588bdc825d878e5bcb7a9136073b15f87a20e11f","src/sys/wait.rs":"c4c19ce13ea96c47fd51e227a1982d2aaafdb6b75edd726159848dd617f70da8","src/time.rs":"d4e0872361a57810837f5bd790cbca3a2b9db1ac4694a3c52d1564ad3532d3be","src/ucontext.rs":"b8f2e04757a9c2bc38c3b1e259d3a013da8a730fe9bfbe5487637395681b43d3","src/unistd.rs":"e9d24b6490d0578fc3e31200023e131df9471c09b7553b452a9ad76399eea753","test/common/mod.rs":"1d7e28e3635754664cd056f3a1079232ff5c118df619e1d0551a9972eb0b3cd6","test/sys/mod.rs":"87b2891d83067ff21f72b8ff7fde3019dc45b6877282ac278b6da151de45c7a7","test/sys/test_aio.rs":"ea9c0af6632739439d7f8187d2c82aeca7ac177d817210815b1a3edcd7a84e9b","test/sys/test_aio_drop.rs":"614070155fa16a979b7341d001639c5ce24a1d6f632c3abce45a5a6d49c4039b","test/sys/test_epoll.rs":"c30b08d665a1fe7d7a04fe51d50ec78fc74c2ac707ae0f95f82104d5c76ceaf2","test/sys/test_inotify.rs":"a141b9a995892547b51ceeb6761a70a6b86d37e8f38d13ea2c497b81b4b0f49f","test/sys/test_ioctl.rs":"00ccc5afb665e533a0a4b6d6a6be438bcaea19fce335390feef4e91d17b3036c","test/sys/test_mman.rs":"fe9019927ed3ca51d2d59d3305a53cc31797a1460044d24e2631f120c9289552","test/sys/test_prctl.rs":"9c3d0fb16a41c3fd80541b313c2bb63de75634ad4711a71af106e58b0cec9ea8","test/sys/test_pthread.rs":"ace36a2f5587f1874854281b4fd84e4e4d892a1e3c5cc38ced57975739522ad6","test/sys/test_ptrace.rs":"0385eebc8b1b8c72f655b745769decd9143ad83018198375982da0896310456b","test/sys/test_select.rs":"2843bc2484d51ba335567cc50bbc4eb6848ac6c6702ced42b177ffe04b49f7f3","test/sys/test_signal.rs":"19c267ffe9a37452719c2b030c62ab8e123d20e3f6ba4da6902375283e3b9593","test/sys/test_signalfd.rs":"0e1060143e2612c490bc3d0168d0bbb042ef55e3f1d91d2578b9e42e4310a14d","test/sys/test_socket.rs":"de724f58d1d703d28be1d4e35fd72df41f835082cdcb4fb579330d0be31dc74f","test/sys/test_sockopt.rs":"4a7fbb08719ae99803280f8af94e134ad90d92bf3ca4fbee0ef0ab398aadecea","test/sys/test_stat.rs":"6630a28217fd708bb84cd4f7e7101836b74f2420f9888923fdab664ccc331c1d","test/sys/test_sysinfo.rs":"ffd49bc96375914a2c4a4a59730cae8072f85771e2c4a80d3403df38d967e272","test/sys/test_termios.rs":"f38dfe45ab4ac9760b1d8c49e18da900d544927080a4a0bbb02b0c854c130455","test/sys/test_timerfd.rs":"cfed3abf58118611d08f6985251a7739cff67108e11214222a1d2394a3a026ce","test/sys/test_uio.rs":"90d973858f3e303c9fb99bc49d8d9a2e184be17e4e771cf3682af80b2ebd1533","test/sys/test_wait.rs":"6fd59fffeeb09ff620c359baefd062ba777598982b6cb001ccc07b6bc7605493","test/test.rs":"58a302e9055555806942c35e0edd0aaa63b2ebb3205c9a7e29491b726a5e2abe","test/test_clearenv.rs":"45ca548035b3c20ec87314715feaba2be973709a635d85b8cde46fd1d9f1ecd4","test/test_dir.rs":"ae3c11c58cb06da6557aa2a839c6653c54cd7724283fffe9df5a5d3feabdd89a","test/test_fcntl.rs":"7a23635451ed4a7b061cdc3015723c803c901e665e2beffde726b7f20ddf61d2","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c90333ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"b4ae25841c2f06f32de9f1acd8230eeccd7095721302ebe78ad454e4e4f9c783","test/test_mount.rs":"7d04b7e0f0f56e8129a0e68a6a338d7d46fdedde863dae4732d3c899e7864c66","test/test_mq.rs":"84dffb2201e2a4bb19f476fa7c23bbc2615453d27e5b958d3841ff371b6faa81","test/test_net.rs":"f2912327ebb2a3d37e6cff02a5ac3106cf889cc5c74404db4ef0034059ba26f1","test/test_nix_path.rs":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","test/test_nmount.rs":"d6c112547bb80968170b5497cda4b6cbf69dabec6f51d494bd52298995ceff18","test/test_poll.rs":"d6eef82848734e47cc9e1f1ce521e35587e63f69876baea660ef22eebc2b1ea6","test/test_pty.rs":"4184e446af7a365ead628596cd77ad168c835a5dea6abca3ee614d86a4412dda","test/test_resource.rs":"40aef790ab745cec31a4b333d2ca406b462aa9bdf4a6d3756371e498b8d51e9a","test/test_sched.rs":"c4579bd376fab8816e63b07fa9ace31dc08e63ebb7c855a2c450698090d1d1e8","test/test_sendfile.rs":"f7d52f6aa680b5667b966d5c046917ba43924e9b9fca6adbcf68479459e06366","test/test_stat.rs":"c407ca47a5258750076d041afad2f6add4c3563be36628bde1c5b314f5d0765d","test/test_time.rs":"f7a21b1e279e60e84909d5dadda97ded66d3326b131fe317badf9af0a1b50335","test/test_timer.rs":"3ae20d364f075d2811f3ff94eda9886682cc21d8807656007d2464fe36d1e361","test/test_unistd.rs":"3ef7b335639747b6d57a04c2264a38ad379b680cebc0b8d8b8e247610630e58a"},"package":"2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"67c8efb2646c390f76029cf2fbb6205bd23e6e15c149ed32a1549e25bef1babe","Cargo.toml":"cd8795ba96b904a16c840e69c94b9493d8032b966579e4589b9adb35efdfec5a","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"de89eb5b6e00eff6eb3043475da16abf3ae63906cbe3103a450c4bf27cad3f3e","build.rs":"f4b3c533039fe39f167251372b4f378ebef43203654f0ac2340dc0e222206787","src/dir.rs":"10a6ff94e56b849ac8ea762905efa85d11812e5539587ce8e5cce932961c7141","src/env.rs":"9d1e7d52c6c5f46d790a8cbc6d5d2ff9097fb7728594c518d51824ebfb70c9b3","src/errno.rs":"204dd49244d461da6827142386a6b491aaeb6c4ca3760bbe9df5fd2f90e9f4ea","src/fcntl.rs":"1014853b9782285f1467dbe79cff435d0bb1d4122dca0b23d7872ddbeb7688c0","src/features.rs":"6edc53dbbadf56a193dc71053f6512b6cf0d09feb5efb8eb991877de1d70c43c","src/ifaddrs.rs":"40ed9c631b5bff403a697889971f44ad87d6fd6bebbd99cb047cf47c190ee87e","src/kmod.rs":"1e77141714fc7da27fcc59caaae0e31b5801f6e164a57f8d6d399a1b4051d5b1","src/lib.rs":"268b7ad111b99ceaf7c78a348824e8a2be84380bdfe8826e8378b6510eac6b9e","src/macros.rs":"ea6b3a5c117f82ab97d0a410501e7ec250ee11baf3c44b1f207ec404ea682d85","src/mount/bsd.rs":"47477e79ee2862b1d7a5afaf099884036fd81e6384624e60d5d2719a9ddbc112","src/mount/linux.rs":"57ada5949a7a393c427e8076e8556938104f70a73c51452d95ab3d78838f442b","src/mount/mod.rs":"8d8c51f25130e02c860f1d85959d02322b4d9ec748295dfc5a4544e6231725a0","src/mqueue.rs":"0c094b340c918796aff8aa43bc78da566c6203c779a41ce5f490fd41110628f1","src/net/if_.rs":"3d32aceb516606271d8edd2dffd5c710a11868aab54119aebec5a70b35cd963b","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"6d27611db0bc1a64bee80cc74155bb593b1e488092d753fdee102404e7e408ec","src/poll_timeout.rs":"c32412689fcafa561514df9d974206c11bb1276ef79fc10964f11b5416f51a00","src/pty.rs":"d30a7bb587bf727615fc505bc8987d5cae543be0d79d2a8f71a41d9cec2afb6e","src/sched.rs":"542bd9b1d8e1ed132c9a16c3485c70d3d47e30f702c4da1b39906fc64da4c308","src/sys/aio.rs":"b57cc89b70b1052c699264427661c293425536db9577f2fa2c6bdfc805fe06ae","src/sys/epoll.rs":"49ce070f560c8ac7a6f338b4b182f70049303c7d895320a7186fb98b666cafa9","src/sys/event.rs":"3e6e737a880f802644b7c5656a6579d747a66b595ba26ab6cb59df1141ac6eda","src/sys/eventfd.rs":"244ec41689cf90ba0527dd3501ea9f2623873b35cb66577dfc652c35e8492fe4","src/sys/fanotify.rs":"769282c558c7ceb3ea3f9661b6717d507641add46b8b033d4bd200c87df2a66d","src/sys/inotify.rs":"5ce6d83beb2f328c33acf0dd3639a1bdd7b5c2e362745b3cb0fa4c549a641e90","src/sys/ioctl/bsd.rs":"e6affc2babd4fa4539574426e416b330b7e32ba4fd2821899a67417261e7089e","src/sys/ioctl/linux.rs":"8c8bdfc239aa175efb4fc2f666a6ecc799b7d614f85e9143595fff05d37f76f0","src/sys/ioctl/mod.rs":"304a959e9eb24dccfd3fc6153719b417367d9208dc7e6859239fb020c407d103","src/sys/memfd.rs":"a7c2c446143f1dda5537a4342a84b83bb536072215ca973de71f87a33ed8bd37","src/sys/mman.rs":"e75b3ae89c18f541ba8fed01b9147661078f9d035eeb4eaf792ba0e4ff1167fe","src/sys/mod.rs":"30057a1c687859394f27581247ae9e412f5f68d4484bd5196797c1bc1939a6c7","src/sys/personality.rs":"f7fa4e97de0943aa6a969465ca7d2d69ac98015f7c339fdbb88d83ffe26db4ce","src/sys/prctl.rs":"785f97a545e010069d67ef11b22a70ca5000e131ee8ca990a2652a596ade77e5","src/sys/pthread.rs":"258cdf7ff0b61a4afa6d228109e4cb4fb88d859bb8dfe6c959d95130fb010906","src/sys/ptrace/bsd.rs":"54b92e1ffe6455a545f807ed7de9011be05251adfdc71a5823b1965579650939","src/sys/ptrace/linux.rs":"c347075fc8d9afd63d6eaf1acf84afb3a2c956b236eef9f17c19e883a6aaa73d","src/sys/ptrace/mod.rs":"a9aefa2b10cc63c8b40adcd3e7dd612a8f4677bf6f37420cdd09e7129ba02c95","src/sys/quota.rs":"1638e34bddd955c7f98f1814d239eb76647101295c8a1ae40c78dd7dd7638f20","src/sys/reboot.rs":"b748217e4877c94c1870885407b9ab1ab9e059c9fb7d04818a1b29477eac81c6","src/sys/resource.rs":"e701020b893666321f44c08df9e60f8927d00ac1035c89965e967dc0b44c6222","src/sys/select.rs":"9cfcb3a9d15a46b2f209e66cbaf136dab6894c711031313557bc58534ecedc70","src/sys/sendfile.rs":"fc7ac628424eb1132674c73bbe19f0d82a28d6752b0beffbf111965ea3885760","src/sys/signal.rs":"da1720190cdedc854649a525f2cd2556daec1c069d3fe32ad65c4302cca8efd9","src/sys/signalfd.rs":"f0b4d32e642a3a02d349b38d317a805eedc6e60e9e773f650fb0ee4ad7f655a7","src/sys/socket/addr.rs":"75d94b8404711b4ec08b44c3d43c7854f7cd9cf8e17665056dddaf6398d1df2a","src/sys/socket/mod.rs":"12c1a291648553516437bec168602fbebcae3d1ad657a7e55cd86f842db29d50","src/sys/socket/sockopt.rs":"69ab0440767e808c0fe2f2d269eae67653b4657e51b8fe356fab95b7ab26546a","src/sys/stat.rs":"074401a0b0fe74d9516640e0790fe67b7727213115accfdb331a9767ae20064c","src/sys/statfs.rs":"991370ce27196f8721a03a88c3b906cc248f46f147ebd6524d45c61433dc0239","src/sys/statvfs.rs":"526c2e69b640f49331e8ca7a2e59cdb803887c91a53fa41f866364fec93bce24","src/sys/sysinfo.rs":"b4519b1ca091c9dbe94d2a6fd6304944bf3df5626973d2c6884022559706f0d9","src/sys/termios.rs":"dd68b78e4a87786d22334c014d258e43d12f4e9370acda61209eb2c9ed176c86","src/sys/time.rs":"a63f6b5cf67a9323ccc3a225ffec88bb078c5dcf22d0eba78ae071db67aefc53","src/sys/timer.rs":"8c10f0e7cfac857ad00460be30bc68b957909cc9296e70718d3b5d4a0babafde","src/sys/timerfd.rs":"569d662725018427b517ffcfa78d8d03e150a344b8b8533d3f16e3bfd5c762da","src/sys/uio.rs":"d0886bf517e9b21af8ad6a25d332003fe9e132fed43cd642ec61b32d27622bd6","src/sys/utsname.rs":"e1f81d363621445633101800ba34debdb222eaf3a25553f8b486f74d49e4be41","src/sys/wait.rs":"338235d42a2ec29633cf64dada7b9b1d434ed0005776bffdecfd5c69922eed89","src/time.rs":"30038bbe683857469d106631cea13ee1e43f149cb4c947a8353824270ee4267c","src/ucontext.rs":"b8f2e04757a9c2bc38c3b1e259d3a013da8a730fe9bfbe5487637395681b43d3","src/unistd.rs":"5bb3b5ad2984793be4eed6adf653bbc52592c2459b9063009b92edb83ed562cf","test/common/mod.rs":"953155de9a50974fda7a43a66269211154bbb5898791e0abd97dc4184d482f23","test/sys/mod.rs":"f08046850a4b7a9bbf203d8eba0ee3ae9c32b6bd4d9c7bf52ca29efb3eb74f35","test/sys/test_aio.rs":"902ae4abda9286db551e65a7eccf267baee16eeefd1cdddac8399bef2ede0060","test/sys/test_aio_drop.rs":"e9e45333b24381bba99235372d5917a22fbd8692eddfbebcf519697c603de812","test/sys/test_epoll.rs":"c30b08d665a1fe7d7a04fe51d50ec78fc74c2ac707ae0f95f82104d5c76ceaf2","test/sys/test_event.rs":"be4b1b1abd25f87f00b3d115105ef832b2c654fd7028c42f1a304a935935b479","test/sys/test_fanotify.rs":"55b0917f8b85fdc8277e6a796d06251a39398b9f2da88d9eec98a763ff03e918","test/sys/test_inotify.rs":"a141b9a995892547b51ceeb6761a70a6b86d37e8f38d13ea2c497b81b4b0f49f","test/sys/test_ioctl.rs":"07d08a46c4ac84161974b655a0d040e03efc9338e7a7505e0d16826b7653b5c2","test/sys/test_mman.rs":"f129659d6995fcada15e7c923cb943d8dd4c6e4aaa141c6cc5bacfa3257793f5","test/sys/test_prctl.rs":"9c3d0fb16a41c3fd80541b313c2bb63de75634ad4711a71af106e58b0cec9ea8","test/sys/test_pthread.rs":"ace36a2f5587f1874854281b4fd84e4e4d892a1e3c5cc38ced57975739522ad6","test/sys/test_ptrace.rs":"ac4fff669bfc58955e94ed0171e4d47ecf2366fce62509c659e78192f9de7a6d","test/sys/test_resource.rs":"aa58f566efb8132b42ae98be6e50b72fee86ef50c4bcc4a7bf49b275f6762008","test/sys/test_select.rs":"09fe9d020e4f1cdb0951ebd27a6c3f408b23471ce2c51d2f1e4708500fc15261","test/sys/test_signal.rs":"ac6cbd345cbd93b1c9bead56794bd978dc44435beea921bedbdb8a2761e557d5","test/sys/test_signalfd.rs":"8db0c371d0cac7d68208505990291ebc2b2cb8671b0edba16ef22b6b9e56dab2","test/sys/test_socket.rs":"8c6190cbea80d5b2866d0891c6f44fddaba337b655af7e5628dc9537e1cbfab9","test/sys/test_sockopt.rs":"dd1839c495ce37535b2fbf78290dfbb1350f40ed7ed92c7fcedc16a88730ecf1","test/sys/test_stat.rs":"6630a28217fd708bb84cd4f7e7101836b74f2420f9888923fdab664ccc331c1d","test/sys/test_statfs.rs":"a32f6319ea7e989747707de27b06332e7942b07e07ab1602af408be91fae7e73","test/sys/test_statvfs.rs":"05cf8f1bcab0f0cd8fbefe8a2a72f9ac6d95aa760c355ac6d4b6f9c61649bc38","test/sys/test_sysinfo.rs":"ffd49bc96375914a2c4a4a59730cae8072f85771e2c4a80d3403df38d967e272","test/sys/test_termios.rs":"6c6897e0320d063a758f6702228c64ef2b459b4a5affa07ae7e76c1142432f0a","test/sys/test_time.rs":"aff97dd1bfc4aa9b616cc71e9cc11f25fb3ad983f1406c856648736847778c19","test/sys/test_timer.rs":"3ae20d364f075d2811f3ff94eda9886682cc21d8807656007d2464fe36d1e361","test/sys/test_timerfd.rs":"cfed3abf58118611d08f6985251a7739cff67108e11214222a1d2394a3a026ce","test/sys/test_uio.rs":"dda569818e3256ff45aa07b33cffb59828983c83b20266b864cdfa38103cffc9","test/sys/test_utsname.rs":"b8371dca02c9cdfc0c8e93df9b5cf5b5cb8a92b114977966854918abeb01ad73","test/sys/test_wait.rs":"c958e51b10a7d0396d0013e9d637a2848ad9d061d526408b40dfefb850c22beb","test/test.rs":"e1da3bf8ef929a9e4aca354bf72578f6649c80dd5f32400eb124b229bd4506f8","test/test_clearenv.rs":"45ca548035b3c20ec87314715feaba2be973709a635d85b8cde46fd1d9f1ecd4","test/test_dir.rs":"e6a100685f945b6007312d22575ac5e27363c649f3fed19fb10b18ac5d905449","test/test_errno.rs":"e7a1320e97350c2883368ffe9fc47fd041f4f9ecdee360d21d36254a63a305a3","test/test_fcntl.rs":"4467e1e8698256c982df17108dacd1fcb6ba0eda18044fe198eff25629827e66","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c90333ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"b4ae25841c2f06f32de9f1acd8230eeccd7095721302ebe78ad454e4e4f9c783","test/test_mount.rs":"9fc453613eab116841a7f2ba57098eebec853fc16ce0e59cb459a203e006115b","test/test_mq.rs":"d8ec2a3f3acad4369851663b3f7fef03177d9f8395b585dee8e2c53f6a2a9b4a","test/test_net.rs":"cfa1d3b4e252193a4b119141f8e93d637e3c32e9029aef72f8bb83e00be6c3b5","test/test_nix_path.rs":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","test/test_nmount.rs":"d6c112547bb80968170b5497cda4b6cbf69dabec6f51d494bd52298995ceff18","test/test_poll.rs":"25b4fa094bbcda5a5317a25d2f292465965dbe3e066374b04a9b27a8d55897ac","test/test_pty.rs":"ec54c5fe096396b5aed5677276acaf80b4c58be7222ee285cfd4eaadf7b34ce0","test/test_sched.rs":"c4579bd376fab8816e63b07fa9ace31dc08e63ebb7c855a2c450698090d1d1e8","test/test_sendfile.rs":"6f82e9f66359a85a7aa819ffd38c7c3326c1bb2384950d681085dc7823fc4a20","test/test_stat.rs":"dae37bd9b5e46e1a76696bed435d8bc4e98ecb91bb3476e7133a6197178d6644","test/test_time.rs":"6eb3536936c67bcfbc80a73a902b4a485943aab5375fc7e3880da6695a4eafce","test/test_unistd.rs":"828a990974b4d843d59f3d134758d4b6a9afa43da3d07dcaf314fcc1615bd732"},"package":"ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"} \ No newline at end of file
diff --git a/third_party/rust/nix/CHANGELOG.md b/third_party/rust/nix/CHANGELOG.md
index 3a171afd68..37e4ab2d4c 100644
--- a/third_party/rust/nix/CHANGELOG.md
+++ b/third_party/rust/nix/CHANGELOG.md
@@ -1,8 +1,205 @@
-# Change Log
-
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).
+# Change Log
+
+## [0.28.0] - 2024-02-24
+
+
+### Added
+
+- Added `mkdtemp` wrapper ([#1297](https://github.com/nix-rust/nix/pull/1297))
+- Add associated constants `UTIME_OMIT` `UTIME_NOW` for `TimeSpec`
+ ([#1879](https://github.com/nix-rust/nix/pull/1879))
+- Added `EventFd` type. ([#1945](https://github.com/nix-rust/nix/pull/1945))
+- - Added `impl From<Signal> for SigSet`.
+ - Added `impl std::ops::BitOr for SigSet`.
+ - Added `impl std::ops::BitOr for Signal`.
+ - Added `impl std::ops::BitOr<Signal> for SigSet`
+
+ ([#1959](https://github.com/nix-rust/nix/pull/1959))
+- Added `TlsGetRecordType` control message type and corresponding enum for
+ linux ([#2065](https://github.com/nix-rust/nix/pull/2065))
+- Added `Ipv6HopLimit` to `::nix::sys::socket::ControlMessage` for Linux,
+ MacOS, FreeBSD, DragonflyBSD, Android, iOS and Haiku.
+ ([#2074](https://github.com/nix-rust/nix/pull/2074))
+- Added `Icmp` and `IcmpV6` to `SockProtocol`
+ ([#2103](https://github.com/nix-rust/nix/pull/2103))
+- Added rfork support for FreeBSD in `unistd`
+ ([#2121](https://github.com/nix-rust/nix/pull/2121))
+- Added `MapFlags::map_hugetlb_with_size_log2` method for Linux targets
+ ([#2125](https://github.com/nix-rust/nix/pull/2125))
+- Added `mmap_anonymous` function
+ ([#2127](https://github.com/nix-rust/nix/pull/2127))
+- Added `mips32r6` and `mips64r6` support for signal, ioctl and ptrace
+ ([#2138](https://github.com/nix-rust/nix/pull/2138))
+- Added `F_GETPATH` FcntlFlags entry on Apple/NetBSD/DragonflyBSD for
+ `::nix::fcntl`. ([#2142](https://github.com/nix-rust/nix/pull/2142))
+- Added `F_KINFO` FcntlFlags entry on FreeBSD for `::nix::fcntl`.
+ ([#2152](https://github.com/nix-rust/nix/pull/2152))
+- Added `F_GETPATH_NOFIRMLINK` and `F_BARRIERFSYNC` FcntlFlags entry
+ on Apple for `::nix::fcntl`.
+ ([#2155](https://github.com/nix-rust/nix/pull/2155))
+- Added newtype `Flock` to automatically unlock a held flock upon drop.
+ Added `Flockable` trait to represent valid types for `Flock`.
+ ([#2170](https://github.com/nix-rust/nix/pull/2170))
+- Added `SetSockOpt` impls to enable Linux Kernel TLS on a TCP socket and to
+ import TLS parameters. ([#2175](https://github.com/nix-rust/nix/pull/2175))
+- - Added the `::nix::sys::socket::SocketTimestamp` enum for configuring the
+ `TsClock` (a.k.a `SO_TS_CLOCK`) sockopt
+ - Added FreeBSD's `ScmRealtime` and `ScmMonotonic` as new options in
+ `::nix::sys::socket::ControlMessageOwned`
+
+ ([#2187](https://github.com/nix-rust/nix/pull/2187))
+- Added new fanotify API: wrappers for `fanotify_init` and `fanotify_mark`
+ ([#2194](https://github.com/nix-rust/nix/pull/2194))
+- Added `SpecialCharacterindices` support for haiku.
+ ([#2195](https://github.com/nix-rust/nix/pull/2195))
+- Added `sys::sendfile` support for solaris/illumos.
+ ([#2198](https://github.com/nix-rust/nix/pull/2198))
+- impl Display for InterfaceFlags
+ ([#2206](https://github.com/nix-rust/nix/pull/2206))
+- Added `sendfilev` in sys::sendfile for solarish
+ ([#2207](https://github.com/nix-rust/nix/pull/2207))
+- Added `fctrl::SealFlag::F_SEAL_FUTURE_WRITE`
+ ([#2213](https://github.com/nix-rust/nix/pull/2213))
+- Added `Ipv6MulticastHops` as socket option to set and read.
+ ([#2234](https://github.com/nix-rust/nix/pull/2234))
+- Enable `ControlMessageOwned::Ipv4RecvIf` and
+ `ControlMessageOwned::Ipv4RecvDstAddr` for DragonFlyBSD
+ ([#2240](https://github.com/nix-rust/nix/pull/2240))
+- `ClockId::set_time()` and `time::clock_settime()` are now enabled on macOS
+ ([#2241](https://github.com/nix-rust/nix/pull/2241))
+- Added `IpBindAddressNoPort` sockopt to support `IP_BIND_ADDRESS_NO_PORT`
+ available on linux. ([#2244](https://github.com/nix-rust/nix/pull/2244))
+- Enable `MapFlags::map_hugetlb_with_size_log2` method for Android/Fuchsia
+ ([#2245](https://github.com/nix-rust/nix/pull/2245))
+- Added `TcpFastOpenConnect` sockopt to support `TCP_FASTOPEN_CONNECT`
+ available on linux. ([#2247](https://github.com/nix-rust/nix/pull/2247))
+- Add `reboot(2)` for OpenBSD/NetBSD
+ ([#2251](https://github.com/nix-rust/nix/pull/2251))
+- Added new `MemFdCreateFlag` constants to `sys::memfd` on Linux and Android
+ related to hugetlbfs support.
+ ([#2252](https://github.com/nix-rust/nix/pull/2252))
+- Expose the inner fd of `Kqueue` through:
+
+ * impl AsFd for Kqueue
+ * impl From\<Kqueue\> for OwnedFd
+
+ ([#2258](https://github.com/nix-rust/nix/pull/2258))
+- Added `sys::eventfd` support on FreeBSD
+ ([#2259](https://github.com/nix-rust/nix/pull/2259))
+- Added `MmapFlags::MAP_FIXED` constant in `sys::mman` for netbsd and openbsd
+ ([#2260](https://github.com/nix-rust/nix/pull/2260))
+- Added the `SO_LISTENQLIMIT` sockopt.
+ ([#2263](https://github.com/nix-rust/nix/pull/2263))
+- Enable the `AT_EMPTY_PATH` flag for the `fchownat()` function
+ ([#2267](https://github.com/nix-rust/nix/pull/2267))
+- Add `AtFlags::AT_EMPTY_PATH` for FreeBSD and Hurd
+ ([#2270](https://github.com/nix-rust/nix/pull/2270))
+- Enable `OFlag::O_DIRECTORY for Solarish
+ ([#2275](https://github.com/nix-rust/nix/pull/2275))
+- Added the `Backlog` wrapper type for the `listen` call.
+ ([#2276](https://github.com/nix-rust/nix/pull/2276))
+- Add `clock_nanosleep()` ([#2277](https://github.com/nix-rust/nix/pull/2277))
+- Enabled `O_DIRECT` in `fcntl::OFlags` for solarish
+ ([#2278](https://github.com/nix-rust/nix/pull/2278))
+- Added a new API sigsuspend.
+ ([#2279](https://github.com/nix-rust/nix/pull/2279))
+- - Added `errno::Errno::set` function
+ - Added `errno::Errno::set_raw` function
+ - Added `errno::Errno::last_raw` function
+ - Added `errno::Errno::from_raw` function
+
+ ([#2283](https://github.com/nix-rust/nix/pull/2283))
+- Enable the `AT_EMPTY_PATH` flag for the `linkat()` function
+ ([#2284](https://github.com/nix-rust/nix/pull/2284))
+- Enable unistd::{sync, syncfs} for Android
+ ([#2296](https://github.com/nix-rust/nix/pull/2296))
+
+### Changed
+
+- `poll` now takes `PollTimeout` replacing `libc::c_int`.
+ ([#1876](https://github.com/nix-rust/nix/pull/1876))
+- Deprecated `sys::eventfd::eventfd`.
+ ([#1945](https://github.com/nix-rust/nix/pull/1945))
+- `mmap`, `mmap_anonymous`, `munmap`, `mremap`, `madvise`, `msync`, `mprotect`,
+ `munlock` and `mlock` updated to use `NonNull`.
+ ([#2000](https://github.com/nix-rust/nix/pull/2000))
+- `mmap` function now accepts `F` instead of `Option<F>`
+ ([#2127](https://github.com/nix-rust/nix/pull/2127))
+- `PollFd::new` now takes a `BorrowedFd` argument, with relaxed lifetime
+ requirements relative to the previous version.
+ ([#2134](https://github.com/nix-rust/nix/pull/2134))
+- `FdSet::{insert, remove, contains}` now take `BorrowedFd` arguments, and have
+ relaxed lifetime requirements relative to 0.27.1.
+ ([#2136](https://github.com/nix-rust/nix/pull/2136))
+- The following APIs now take an implementation of `AsFd` rather than a
+ `RawFd`:
+
+ - `unistd::tcgetpgrp`
+ - `unistd::tcsetpgrp`
+ - `unistd::fpathconf`
+ - `unistd::ttyname`
+ - `unistd::getpeereid` ([#2137](https://github.com/nix-rust/nix/pull/2137))
+- Changed `openat()` and `Dir::openat()`, now take optional `dirfd`s
+ ([#2139](https://github.com/nix-rust/nix/pull/2139))
+- The MSRV is now 1.69 ([#2144](https://github.com/nix-rust/nix/pull/2144))
+- Changed function `SockaddrIn::ip()` to return `net::Ipv4Addr` and refactored
+ `SocketAddrV6::ip()` to be `const`
+ ([#2151](https://github.com/nix-rust/nix/pull/2151))
+- The following APIs now take optional `dirfd`s:
+
+ - `readlinkat()`
+ - `fstatat()`
+ - `mknodat()`
+ - `mkdirat()`
+ - `execveat()`
+
+ ([#2157](https://github.com/nix-rust/nix/pull/2157))
+- `Epoll::wait` now takes `EpollTimeout` replacing `isize`.
+ ([#2202](https://github.com/nix-rust/nix/pull/2202))
+- - Deprecated `errno::errno()` function (use `Errno::last_raw()`)
+ - Deprecated `errno::from_i32()` function (use `Errno::from_raw()`)
+ - Deprecated `errno::Errno::from_i32()` function (use `Errno::from_raw()`)
+
+ ([#2283](https://github.com/nix-rust/nix/pull/2283))
+
+### Fixed
+
+- Fix `SigSet` incorrect implementation of `Eq`, `PartialEq` and `Hash`
+ ([#1946](https://github.com/nix-rust/nix/pull/1946))
+- Fixed `::sys::socket::sockopt::IpMulticastTtl` by fixing the value of optlen
+ passed to `libc::setsockopt` and added tests.
+ ([#2072](https://github.com/nix-rust/nix/pull/2072))
+- Fixed the function signature of `recvmmsg`, potentially causing UB
+ ([#2119](https://github.com/nix-rust/nix/pull/2119))
+- Fix `SignalFd::set_mask`. In 0.27.0 it would actually close the file
+ descriptor. ([#2141](https://github.com/nix-rust/nix/pull/2141))
+- Fixed UnixAddr::new for haiku, it did not record the `sun_len` value as
+ needed.
+ Fixed `sys::socket::addr::from_raw_parts` and
+ `sys::socket::Sockaddrlike::len` build for solaris.
+ ([#2242](https://github.com/nix-rust/nix/pull/2242))
+- Fixed solaris build globally.
+ ([#2248](https://github.com/nix-rust/nix/pull/2248))
+- Changed the `dup3` wrapper to perform a real call to `dup3` instead of
+ emulating it via `dup2` and `fcntl` to get rid of race condition
+ ([#2268](https://github.com/nix-rust/nix/pull/2268))
+- Fixed `::unistd::Group::members` using read_unaligned to avoid crash on
+ misaligned pointers ([#2311](https://github.com/nix-rust/nix/pull/2311))
+
+### Removed
+
+- The `FchownatFlags` type has been deprecated, please use `AtFlags` instead.
+ ([#2267](https://github.com/nix-rust/nix/pull/2267))
+- Removed the `dup3` wrapper on macOS, which was emulated via `dup2` and
+ `fcntl` and could cause a race condition. The `dup3` system call is not
+ supported on macOS. ([#2268](https://github.com/nix-rust/nix/pull/2268))
+- The `LinkatFlags` type has been deprecated, please use `AtFlags` instead.
+ ([#2284](https://github.com/nix-rust/nix/pull/2284))
+
+
## [0.27.1] - 2023-08-28
### Fixed
@@ -99,7 +296,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
## [0.26.3] - 2023-08-27
### Fixed
-- Fix: send `ETH_P_ALL` in htons format
+- Fix: send `ETH_P_ALL` in htons format
([#1925](https://github.com/nix-rust/nix/pull/1925))
- Fix: `recvmsg` now sets the length of the received `sockaddr_un` field
correctly on Linux platforms. ([#2041](https://github.com/nix-rust/nix/pull/2041))
@@ -187,7 +384,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
([#1824](https://github.com/nix-rust/nix/pull/1824))
- Workaround XNU bug causing netmasks returned by `getifaddrs` to misbehave.
([#1788](https://github.com/nix-rust/nix/pull/1788))
-
+
### Removed
- Removed deprecated error constants and conversions.
diff --git a/third_party/rust/nix/Cargo.toml b/third_party/rust/nix/Cargo.toml
index bb04ab2702..34bc897c54 100644
--- a/third_party/rust/nix/Cargo.toml
+++ b/third_party/rust/nix/Cargo.toml
@@ -11,11 +11,12 @@
[package]
edition = "2021"
-rust-version = "1.65"
+rust-version = "1.69"
name = "nix"
-version = "0.27.1"
+version = "0.28.0"
authors = ["The nix-rust Project Developers"]
include = [
+ "build.rs",
"src/**/*",
"test/**/*",
"LICENSE",
@@ -61,11 +62,6 @@ name = "test-clearenv"
path = "test/test_clearenv.rs"
[[test]]
-name = "test-mount"
-path = "test/test_mount.rs"
-harness = false
-
-[[test]]
name = "test-prctl"
path = "test/sys/test_prctl.rs"
@@ -76,7 +72,7 @@ version = "2.3.1"
version = "1.0"
[dependencies.libc]
-version = "0.2.147"
+version = "0.2.153"
features = ["extra_traits"]
[dependencies.memoffset]
@@ -102,6 +98,9 @@ version = "1.0.7"
[dev-dependencies.tempfile]
version = "3.7.1"
+[build-dependencies.cfg_aliases]
+version = "0.1.1"
+
[features]
acct = []
aio = ["pin-utils"]
@@ -109,6 +108,7 @@ default = []
dir = ["fs"]
env = []
event = []
+fanotify = []
feature = []
fs = []
hostname = []
diff --git a/third_party/rust/nix/README.md b/third_party/rust/nix/README.md
index e172de2750..fb9f84ca44 100644
--- a/third_party/rust/nix/README.md
+++ b/third_party/rust/nix/README.md
@@ -2,6 +2,7 @@
[![Cirrus Build Status](https://api.cirrus-ci.com/github/nix-rust/nix.svg)](https://cirrus-ci.com/github/nix-rust/nix)
[![crates.io](https://img.shields.io/crates/v/nix.svg)](https://crates.io/crates/nix)
+[![maintenance-status](https://img.shields.io/badge/maintenance-looking--for--maintainer-orange.svg)](https://github.com/nix-rust/nix/issues/2132)
[Documentation (Releases)](https://docs.rs/nix/)
@@ -98,13 +99,14 @@ The following targets are supported by `nix`:
<li>x86_64-unknown-linux-gnux32</li>
<li>x86_64-unknown-openbsd</li>
<li>x86_64-unknown-redox</li>
+ <li>i686-unknown-hurd-gnu</li>
</td>
</tr>
</table>
## Minimum Supported Rust Version (MSRV)
-nix is supported on Rust 1.65 and higher. Its MSRV will not be
+nix is supported on Rust 1.69 and higher. Its MSRV will not be
changed in the future without bumping the major or minor version.
## Contributing
diff --git a/third_party/rust/nix/build.rs b/third_party/rust/nix/build.rs
new file mode 100644
index 0000000000..4535af1f04
--- /dev/null
+++ b/third_party/rust/nix/build.rs
@@ -0,0 +1,25 @@
+use cfg_aliases::cfg_aliases;
+
+fn main() {
+ cfg_aliases! {
+ android: { target_os = "android" },
+ dragonfly: { target_os = "dragonfly" },
+ ios: { target_os = "ios" },
+ freebsd: { target_os = "freebsd" },
+ illumos: { target_os = "illumos" },
+ linux: { target_os = "linux" },
+ macos: { target_os = "macos" },
+ netbsd: { target_os = "netbsd" },
+ openbsd: { target_os = "openbsd" },
+ solaris: { target_os = "solaris" },
+ watchos: { target_os = "watchos" },
+ tvos: { target_os = "tvos" },
+
+ apple_targets: { any(ios, macos, watchos, tvos) },
+ bsd: { any(freebsd, dragonfly, netbsd, openbsd, apple_targets) },
+ linux_android: { any(android, linux) },
+ freebsdlike: { any(dragonfly, freebsd) },
+ netbsdlike: { any(netbsd, openbsd) },
+ solarish: { any(illumos, solaris) },
+ }
+}
diff --git a/third_party/rust/nix/src/dir.rs b/third_party/rust/nix/src/dir.rs
index 96a5843bc6..ab70f064cc 100644
--- a/third_party/rust/nix/src/dir.rs
+++ b/third_party/rust/nix/src/dir.rs
@@ -44,7 +44,7 @@ impl Dir {
/// Opens the given path as with `fcntl::openat`.
pub fn openat<P: ?Sized + NixPath>(
- dirfd: RawFd,
+ dirfd: Option<RawFd>,
path: &P,
oflag: OFlag,
mode: sys::stat::Mode,
@@ -225,16 +225,13 @@ impl Entry {
pub fn ino(&self) -> u64 {
cfg_if! {
if #[cfg(any(target_os = "aix",
- target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "ios",
- target_os = "l4re",
- target_os = "linux",
- target_os = "macos",
- target_os = "solaris"))] {
+ target_os = "hurd",
+ solarish,
+ linux_android,
+ apple_targets))] {
self.0.d_ino as u64
} else {
u64::from(self.0.d_fileno)
@@ -253,12 +250,7 @@ impl Entry {
/// notably, some Linux filesystems don't implement this. The caller should use `stat` or
/// `fstat` if this returns `None`.
pub fn file_type(&self) -> Option<Type> {
- #[cfg(not(any(
- target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku"
- )))]
+ #[cfg(not(any(solarish, target_os = "aix", target_os = "haiku")))]
match self.0.d_type {
libc::DT_FIFO => Some(Type::Fifo),
libc::DT_CHR => Some(Type::CharacterDevice),
@@ -271,12 +263,7 @@ impl Entry {
}
// illumos, Solaris, and Haiku systems do not have the d_type member at all:
- #[cfg(any(
- target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku"
- ))]
+ #[cfg(any(solarish, target_os = "aix", target_os = "haiku"))]
None
}
}
diff --git a/third_party/rust/nix/src/env.rs b/third_party/rust/nix/src/env.rs
index 95177a1d2a..510bbb0924 100644
--- a/third_party/rust/nix/src/env.rs
+++ b/third_party/rust/nix/src/env.rs
@@ -40,13 +40,12 @@ impl std::error::Error for ClearEnvError {}
/// thread safety must still be upheld.
pub unsafe fn clearenv() -> std::result::Result<(), ClearEnvError> {
cfg_if! {
- if #[cfg(any(target_os = "fuchsia",
+ if #[cfg(any(linux_android,
+ target_os = "fuchsia",
target_os = "wasi",
target_env = "uclibc",
- target_os = "linux",
- target_os = "android",
target_os = "emscripten"))] {
- let ret = libc::clearenv();
+ let ret = unsafe { libc::clearenv() };
} else {
use std::env;
for (name, _) in env::vars_os() {
diff --git a/third_party/rust/nix/src/errno.rs b/third_party/rust/nix/src/errno.rs
index 50b35248f8..2e74a84454 100644
--- a/third_party/rust/nix/src/errno.rs
+++ b/third_party/rust/nix/src/errno.rs
@@ -1,74 +1,127 @@
+//! Safe wrappers around errno functions
+//!
+//! # Example
+//! ```
+//! use nix::errno::Errno;
+//!
+//! Errno::EIO.set();
+//! assert_eq!(Errno::last(), Errno::EIO);
+//!
+//! Errno::clear();
+//! assert_eq!(Errno::last(), Errno::from_raw(0));
+//! ```
+
use crate::Result;
use cfg_if::cfg_if;
use libc::{c_int, c_void};
-use std::convert::TryFrom;
use std::{error, fmt, io};
pub use self::consts::*;
cfg_if! {
if #[cfg(any(target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))] {
+ apple_targets,))] {
unsafe fn errno_location() -> *mut c_int {
- libc::__error()
+ unsafe { libc::__error() }
}
- } else if #[cfg(any(target_os = "android",
- target_os = "netbsd",
- target_os = "openbsd"))] {
+ } else if #[cfg(any(target_os = "android", netbsdlike))] {
unsafe fn errno_location() -> *mut c_int {
- libc::__errno()
+ unsafe { libc::__errno() }
}
} else if #[cfg(any(target_os = "linux",
target_os = "redox",
target_os = "dragonfly",
- target_os = "fuchsia"))] {
+ target_os = "fuchsia",
+ target_os = "hurd"))] {
unsafe fn errno_location() -> *mut c_int {
- libc::__errno_location()
+ unsafe { libc::__errno_location() }
}
- } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] {
+ } else if #[cfg(solarish)] {
unsafe fn errno_location() -> *mut c_int {
- libc::___errno()
+ unsafe { libc::___errno() }
}
} else if #[cfg(any(target_os = "haiku",))] {
unsafe fn errno_location() -> *mut c_int {
- libc::_errnop()
+ unsafe { libc::_errnop() }
}
} else if #[cfg(any(target_os = "aix"))] {
unsafe fn errno_location() -> *mut c_int {
- libc::_Errno()
+ unsafe { libc::_Errno() }
}
}
}
-/// Sets the platform-specific errno to no-error
-fn clear() {
- // Safe because errno is a thread-local variable
- unsafe {
- *errno_location() = 0;
- }
-}
-
/// Returns the platform-specific value of errno
+#[deprecated(since = "0.28.0", note = "please use `Errno::last_raw()` instead")]
pub fn errno() -> i32 {
- unsafe { *errno_location() }
+ Errno::last_raw()
}
impl Errno {
+ /// Returns the current value of errno
pub fn last() -> Self {
- last()
+ Self::from_raw(Self::last_raw())
}
- pub fn desc(self) -> &'static str {
- desc(self)
+ /// Returns the current raw i32 value of errno
+ pub fn last_raw() -> i32 {
+ unsafe { *errno_location() }
+ }
+
+ /// Sets the value of errno.
+ ///
+ /// # Example
+ /// ```
+ /// use nix::errno::Errno;
+ ///
+ /// Errno::EIO.set();
+ ///
+ /// assert_eq!(Errno::last(), Errno::EIO);
+ /// ```
+ pub fn set(self) {
+ Self::set_raw(self as i32)
}
+ /// Sets the raw i32 value of errno.
+ pub fn set_raw(errno: i32) {
+ // Safe because errno is a thread-local variable
+ unsafe {
+ *errno_location() = errno;
+ }
+ }
+
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(err: i32) -> Errno {
+ Self::from_raw(err)
+ }
+
+ pub const fn from_raw(err: i32) -> Errno {
+ #[allow(deprecated)]
from_i32(err)
}
+ pub fn desc(self) -> &'static str {
+ desc(self)
+ }
+
+ /// Sets the platform-specific errno to no-error
+ ///
+ /// ```
+ /// use nix::errno::Errno;
+ ///
+ /// Errno::EIO.set();
+ ///
+ /// Errno::clear();
+ ///
+ /// let err = Errno::last();
+ /// assert_ne!(err, Errno::EIO);
+ /// assert_eq!(err, Errno::from_raw(0));
+ /// ```
pub fn clear() {
- clear()
+ Self::set_raw(0)
}
/// Returns `Ok(value)` if it does not contain the sentinel value. This
@@ -137,14 +190,10 @@ impl TryFrom<io::Error> for Errno {
type Error = io::Error;
fn try_from(ioerror: io::Error) -> std::result::Result<Self, io::Error> {
- ioerror.raw_os_error().map(Errno::from_i32).ok_or(ioerror)
+ ioerror.raw_os_error().map(Errno::from_raw).ok_or(ioerror)
}
}
-fn last() -> Errno {
- Errno::from_i32(errno())
-}
-
fn desc(errno: Errno) -> &'static str {
use self::Errno::*;
match errno {
@@ -225,467 +274,270 @@ fn desc(errno: Errno) -> &'static str {
EHOSTUNREACH => "No route to host",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
ECHRNG => "Channel number out of range",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
EL2NSYNC => "Level 2 not synchronized",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
EL3HLT => "Level 3 halted",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
EL3RST => "Level 3 reset",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
ELNRNG => "Link number out of range",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
EUNATCH => "Protocol driver not attached",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
ENOCSI => "No CSI structure available",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
EL2HLT => "Level 2 halted",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EBADE => "Invalid exchange",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EBADR => "Invalid request descriptor",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EXFULL => "Exchange full",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ENOANO => "No anode",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EBADRQC => "Invalid request code",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EBADSLT => "Invalid slot",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EBFONT => "Bad font file format",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
+ linux_android,
+ solarish,
+ target_os = "fuchsia",
+ target_os = "hurd"
))]
ENOSTR => "Device not a stream",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
+ linux_android,
+ solarish,
+ target_os = "fuchsia",
+ target_os = "hurd"
))]
ENODATA => "No data available",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
+ linux_android,
+ solarish,
+ target_os = "fuchsia",
+ target_os = "hurd"
))]
ETIME => "Timer expired",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
+ linux_android,
+ solarish,
+ target_os = "fuchsia",
+ target_os = "hurd"
))]
ENOSR => "Out of streams resources",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ENONET => "Machine is not on the network",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ENOPKG => "Package not installed",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
+ linux_android,
+ solarish,
+ target_os = "fuchsia",
+ target_os = "hurd"
))]
EREMOTE => "Object is remote",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
ENOLINK => "Link has been severed",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EADV => "Advertise error",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ESRMNT => "Srmount error",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ECOMM => "Communication error on send",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
+ target_os = "fuchsia",
))]
EPROTO => "Protocol error",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
EMULTIHOP => "Multihop attempted",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EDOTDOT => "RFS specific error",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "aix",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "aix", target_os = "fuchsia"))]
EBADMSG => "Not a data message",
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ #[cfg(solarish)]
EBADMSG => "Trying to read unreadable message",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "aix",
target_os = "fuchsia",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "hurd"
))]
EOVERFLOW => "Value too large for defined data type",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ENOTUNIQ => "Name not unique on network",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EBADFD => "File descriptor in bad state",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EREMCHG => "Remote address changed",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ELIBACC => "Can not access a needed shared library",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ELIBBAD => "Accessing a corrupted shared library",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ELIBSCN => ".lib section in a.out corrupted",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ELIBMAX => "Attempting to link in too many shared libraries",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
+ linux_android,
+ solarish,
+ target_os = "fuchsia",
+ target_os = "hurd"
))]
ELIBEXEC => "Cannot exec a shared library directly",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia",
target_os = "openbsd"
))]
EILSEQ => "Illegal byte sequence",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "fuchsia"
))]
ERESTART => "Interrupted system call should be restarted",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
ESTRPIPE => "Streams pipe error",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
EUSERS => "Too many users",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "fuchsia",
target_os = "netbsd",
target_os = "redox"
))]
EOPNOTSUPP => "Operation not supported on transport endpoint",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia", target_os = "hurd"))]
ESTALE => "Stale file handle",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EUCLEAN => "Structure needs cleaning",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ENOTNAM => "Not a XENIX named type file",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ENAVAIL => "No XENIX semaphores available",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EISNAM => "Is a named type file",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EREMOTEIO => "Remote I/O error",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EDQUOT => "Quota exceeded",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "fuchsia",
target_os = "openbsd",
target_os = "dragonfly"
@@ -693,71 +545,47 @@ fn desc(errno: Errno) -> &'static str {
ENOMEDIUM => "No medium found",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "fuchsia",
target_os = "openbsd"
))]
EMEDIUMTYPE => "Wrong medium type",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "illumos",
- target_os = "solaris",
+ linux_android,
+ solarish,
target_os = "fuchsia",
target_os = "haiku"
))]
ECANCELED => "Operation canceled",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ENOKEY => "Required key not available",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EKEYEXPIRED => "Key has expired",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EKEYREVOKED => "Key has been revoked",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
EKEYREJECTED => "Key was rejected by service",
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "aix",
- target_os = "fuchsia"
+ target_os = "fuchsia",
+ target_os = "hurd"
))]
EOWNERDEAD => "Owner died",
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ #[cfg(solarish)]
EOWNERDEAD => "Process died with lock",
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "aix",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "aix", target_os = "fuchsia"))]
ENOTRECOVERABLE => "State not recoverable",
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ #[cfg(solarish)]
ENOTRECOVERABLE => "Lock is not recoverable",
#[cfg(any(
@@ -772,21 +600,13 @@ fn desc(errno: Errno) -> &'static str {
))]
EHWPOISON => "Memory page has hardware error",
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
EDOOFUS => "Programming error",
- #[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "redox"
- ))]
+ #[cfg(any(freebsdlike, target_os = "hurd", target_os = "redox"))]
EMULTIHOP => "Multihop attempted",
- #[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "redox"
- ))]
+ #[cfg(any(freebsdlike, target_os = "hurd", target_os = "redox"))]
ENOLINK => "Link has been severed",
#[cfg(target_os = "freebsd")]
@@ -795,300 +615,157 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(target_os = "freebsd")]
ECAPMODE => "Not permitted in capability mode",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
ENEEDAUTH => "Need authenticator",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "redox",
- target_os = "illumos",
- target_os = "solaris"
- ))]
+ #[cfg(any(bsd, target_os = "redox", solarish))]
EOVERFLOW => "Value too large to be stored in data type",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "netbsd",
target_os = "redox",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "hurd"
))]
EILSEQ => "Illegal byte sequence",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "haiku"
- ))]
+ #[cfg(any(bsd, target_os = "haiku"))]
ENOATTR => "Attribute not found",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd",
+ bsd,
target_os = "redox",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "hurd"
))]
EBADMSG => "Bad message",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "redox",
- target_os = "haiku"
+ bsd,
+ target_os = "haiku",
+ target_os = "hurd",
+ target_os = "redox"
))]
EPROTO => "Protocol error",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd"
+ freebsdlike,
+ apple_targets,
+ target_os = "openbsd",
+ target_os = "hurd"
))]
ENOTRECOVERABLE => "State not recoverable",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd"
- ))]
+ #[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))]
EOWNERDEAD => "Previous owner died",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd",
+ bsd,
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku"
+ solarish,
+ target_os = "haiku",
+ target_os = "hurd"
))]
ENOTSUP => "Operation not supported",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "aix",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "aix", target_os = "hurd"))]
EPROCLIM => "Too many processes",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
+ bsd,
target_os = "aix",
- target_os = "openbsd",
- target_os = "netbsd",
+ target_os = "hurd",
target_os = "redox"
))]
EUSERS => "Too many users",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd",
+ bsd,
+ solarish,
target_os = "redox",
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "hurd"
))]
EDQUOT => "Disc quota exceeded",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd",
+ bsd,
+ solarish,
target_os = "redox",
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
target_os = "haiku"
))]
ESTALE => "Stale NFS file handle",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "aix",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "redox"
- ))]
+ #[cfg(any(bsd, target_os = "aix", target_os = "redox"))]
EREMOTE => "Too many levels of remote in path",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
EBADRPC => "RPC struct is bad",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
ERPCMISMATCH => "RPC version wrong",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
EPROGUNAVAIL => "RPC prog. not avail",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
EPROGMISMATCH => "Program version wrong",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
EPROCUNAVAIL => "Bad procedure for program",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
EFTYPE => "Inappropriate file type or format",
- #[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "openbsd",
- target_os = "netbsd"
- ))]
+ #[cfg(any(bsd, target_os = "hurd"))]
EAUTH => "Authentication error",
#[cfg(any(
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
+ bsd,
target_os = "aix",
- target_os = "openbsd",
- target_os = "netbsd",
+ target_os = "hurd",
target_os = "redox"
))]
ECANCELED => "Operation canceled",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
EPWROFF => "Device power is off",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
EDEVERR => "Device error, e.g. paper out",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
EBADEXEC => "Bad executable",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
EBADARCH => "Bad CPU type in executable",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
ESHLIBVERS => "Shared library version mismatch",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
EBADMACHO => "Malformed Macho file",
- #[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "netbsd",
- target_os = "haiku"
- ))]
+ #[cfg(any(apple_targets, target_os = "netbsd", target_os = "haiku"))]
EMULTIHOP => "Reserved",
#[cfg(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
))]
ENODATA => "No message available on STREAM",
- #[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "netbsd",
- target_os = "haiku"
- ))]
+ #[cfg(any(apple_targets, target_os = "netbsd", target_os = "haiku"))]
ENOLINK => "Reserved",
#[cfg(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
@@ -1096,8 +773,7 @@ fn desc(errno: Errno) -> &'static str {
ENOSR => "No STREAM resources",
#[cfg(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
@@ -1105,30 +781,23 @@ fn desc(errno: Errno) -> &'static str {
ENOSTR => "Not a STREAM",
#[cfg(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
))]
ETIME => "STREAM ioctl timeout",
- #[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "aix",
- target_os = "illumos",
- target_os = "solaris"
- ))]
+ #[cfg(any(apple_targets, solarish, target_os = "aix"))]
EOPNOTSUPP => "Operation not supported on socket",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
ENOPOLICY => "No such policy registered",
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
EQFULL => "Interface output queue is full",
- #[cfg(target_os = "openbsd")]
+ #[cfg(any(target_os = "openbsd", target_os = "hurd"))]
EOPNOTSUPP => "Operation not supported",
#[cfg(target_os = "openbsd")]
@@ -1137,18 +806,33 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(target_os = "dragonfly")]
EASYNC => "Async",
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ #[cfg(solarish)]
EDEADLOCK => "Resource deadlock would occur",
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ #[cfg(solarish)]
ELOCKUNMAPPED => "Locked lock was unmapped",
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ #[cfg(solarish)]
ENOTACTIVE => "Facility is not active",
+
+ #[cfg(target_os = "hurd")]
+ EBACKGROUND => "Inappropriate operation for background process",
+
+ #[cfg(target_os = "hurd")]
+ EDIED => "Translator died",
+
+ #[cfg(target_os = "hurd")]
+ EGREGIOUS => "You really blew it this time",
+
+ #[cfg(target_os = "hurd")]
+ EIEIO => "Computer bought the farm",
+
+ #[cfg(target_os = "hurd")]
+ EGRATUITOUS => "Gratuitous error",
}
}
-#[cfg(any(target_os = "linux", target_os = "android", target_os = "fuchsia"))]
+#[cfg(any(linux_android, target_os = "fuchsia"))]
mod consts {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(i32)]
@@ -1296,6 +980,10 @@ mod consts {
pub const ENOTSUP: Errno = Errno::EOPNOTSUPP;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -1438,7 +1126,7 @@ mod consts {
}
}
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(apple_targets)]
mod consts {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(i32)]
@@ -1559,6 +1247,10 @@ mod consts {
pub const EDEADLOCK: Errno = Errno::EDEADLK;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -1786,6 +1478,10 @@ mod consts {
pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -2003,6 +1699,10 @@ mod consts {
pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -2215,6 +1915,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -2429,6 +2133,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -2632,6 +2340,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -2726,7 +2438,7 @@ mod consts {
}
}
-#[cfg(any(target_os = "illumos", target_os = "solaris"))]
+#[cfg(solarish)]
mod consts {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(i32)]
@@ -2861,6 +2573,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -3081,6 +2797,10 @@ mod consts {
pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -3272,6 +2992,10 @@ mod consts {
EOPNOTSUPP = libc::EOPNOTSUPP,
}
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
@@ -3378,3 +3102,235 @@ mod consts {
}
}
}
+
+#[cfg(target_os = "hurd")]
+mod consts {
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+ #[repr(i32)]
+ #[non_exhaustive]
+ pub enum Errno {
+ UnknownErrno = 0,
+ EPERM = libc::EPERM,
+ ENOENT = libc::ENOENT,
+ ESRCH = libc::ESRCH,
+ EINTR = libc::EINTR,
+ EIO = libc::EIO,
+ ENXIO = libc::ENXIO,
+ E2BIG = libc::E2BIG,
+ ENOEXEC = libc::ENOEXEC,
+ EBADF = libc::EBADF,
+ ECHILD = libc::ECHILD,
+ EDEADLK = libc::EDEADLK,
+ ENOMEM = libc::ENOMEM,
+ EACCES = libc::EACCES,
+ EFAULT = libc::EFAULT,
+ ENOTBLK = libc::ENOTBLK,
+ EBUSY = libc::EBUSY,
+ EEXIST = libc::EEXIST,
+ EXDEV = libc::EXDEV,
+ ENODEV = libc::ENODEV,
+ ENOTDIR = libc::ENOTDIR,
+ EISDIR = libc::EISDIR,
+ EINVAL = libc::EINVAL,
+ EMFILE = libc::EMFILE,
+ ENFILE = libc::ENFILE,
+ ENOTTY = libc::ENOTTY,
+ ETXTBSY = libc::ETXTBSY,
+ EFBIG = libc::EFBIG,
+ ENOSPC = libc::ENOSPC,
+ ESPIPE = libc::ESPIPE,
+ EROFS = libc::EROFS,
+ EMLINK = libc::EMLINK,
+ EPIPE = libc::EPIPE,
+ EDOM = libc::EDOM,
+ ERANGE = libc::ERANGE,
+ EAGAIN = libc::EAGAIN,
+ EINPROGRESS = libc::EINPROGRESS,
+ EALREADY = libc::EALREADY,
+ ENOTSOCK = libc::ENOTSOCK,
+ EMSGSIZE = libc::EMSGSIZE,
+ EPROTOTYPE = libc::EPROTOTYPE,
+ ENOPROTOOPT = libc::ENOPROTOOPT,
+ EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
+ ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
+ EOPNOTSUPP = libc::EOPNOTSUPP,
+ EPFNOSUPPORT = libc::EPFNOSUPPORT,
+ EAFNOSUPPORT = libc::EAFNOSUPPORT,
+ EADDRINUSE = libc::EADDRINUSE,
+ EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
+ ENETDOWN = libc::ENETDOWN,
+ ENETUNREACH = libc::ENETUNREACH,
+ ENETRESET = libc::ENETRESET,
+ ECONNABORTED = libc::ECONNABORTED,
+ ECONNRESET = libc::ECONNRESET,
+ ENOBUFS = libc::ENOBUFS,
+ EISCONN = libc::EISCONN,
+ ENOTCONN = libc::ENOTCONN,
+ EDESTADDRREQ = libc::EDESTADDRREQ,
+ ESHUTDOWN = libc::ESHUTDOWN,
+ ETOOMANYREFS = libc::ETOOMANYREFS,
+ ETIMEDOUT = libc::ETIMEDOUT,
+ ECONNREFUSED = libc::ECONNREFUSED,
+ ELOOP = libc::ELOOP,
+ ENAMETOOLONG = libc::ENAMETOOLONG,
+ EHOSTDOWN = libc::EHOSTDOWN,
+ EHOSTUNREACH = libc::EHOSTUNREACH,
+ ENOTEMPTY = libc::ENOTEMPTY,
+ EPROCLIM = libc::EPROCLIM,
+ EUSERS = libc::EUSERS,
+ EDQUOT = libc::EDQUOT,
+ ESTALE = libc::ESTALE,
+ EREMOTE = libc::EREMOTE,
+ EBADRPC = libc::EBADRPC,
+ ERPCMISMATCH = libc::ERPCMISMATCH,
+ EPROGUNAVAIL = libc::EPROGUNAVAIL,
+ EPROGMISMATCH = libc::EPROGMISMATCH,
+ EPROCUNAVAIL = libc::EPROCUNAVAIL,
+ ENOLCK = libc::ENOLCK,
+ EFTYPE = libc::EFTYPE,
+ EAUTH = libc::EAUTH,
+ ENEEDAUTH = libc::ENEEDAUTH,
+ ENOSYS = libc::ENOSYS,
+ ELIBEXEC = libc::ELIBEXEC,
+ ENOTSUP = libc::ENOTSUP,
+ EILSEQ = libc::EILSEQ,
+ EBACKGROUND = libc::EBACKGROUND,
+ EDIED = libc::EDIED,
+ EGREGIOUS = libc::EGREGIOUS,
+ EIEIO = libc::EIEIO,
+ EGRATUITOUS = libc::EGRATUITOUS,
+ EBADMSG = libc::EBADMSG,
+ EIDRM = libc::EIDRM,
+ EMULTIHOP = libc::EMULTIHOP,
+ ENODATA = libc::ENODATA,
+ ENOLINK = libc::ENOLINK,
+ ENOMSG = libc::ENOMSG,
+ ENOSR = libc::ENOSR,
+ ENOSTR = libc::ENOSTR,
+ EOVERFLOW = libc::EOVERFLOW,
+ EPROTO = libc::EPROTO,
+ ETIME = libc::ETIME,
+ ECANCELED = libc::ECANCELED,
+ EOWNERDEAD = libc::EOWNERDEAD,
+ ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
+ }
+
+ impl Errno {
+ pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
+ }
+
+ #[deprecated(
+ since = "0.28.0",
+ note = "please use `Errno::from_raw()` instead"
+ )]
+ pub const fn from_i32(e: i32) -> Errno {
+ use self::Errno::*;
+
+ match e {
+ libc::EPERM => EPERM,
+ libc::ENOENT => ENOENT,
+ libc::ESRCH => ESRCH,
+ libc::EINTR => EINTR,
+ libc::EIO => EIO,
+ libc::ENXIO => ENXIO,
+ libc::E2BIG => E2BIG,
+ libc::ENOEXEC => ENOEXEC,
+ libc::EBADF => EBADF,
+ libc::ECHILD => ECHILD,
+ libc::EDEADLK => EDEADLK,
+ libc::ENOMEM => ENOMEM,
+ libc::EACCES => EACCES,
+ libc::EFAULT => EFAULT,
+ libc::ENOTBLK => ENOTBLK,
+ libc::EBUSY => EBUSY,
+ libc::EEXIST => EEXIST,
+ libc::EXDEV => EXDEV,
+ libc::ENODEV => ENODEV,
+ libc::ENOTDIR => ENOTDIR,
+ libc::EISDIR => EISDIR,
+ libc::EINVAL => EINVAL,
+ libc::EMFILE => EMFILE,
+ libc::ENFILE => ENFILE,
+ libc::ENOTTY => ENOTTY,
+ libc::ETXTBSY => ETXTBSY,
+ libc::EFBIG => EFBIG,
+ libc::ENOSPC => ENOSPC,
+ libc::ESPIPE => ESPIPE,
+ libc::EROFS => EROFS,
+ libc::EMLINK => EMLINK,
+ libc::EPIPE => EPIPE,
+ libc::EDOM => EDOM,
+ libc::ERANGE => ERANGE,
+ libc::EAGAIN => EAGAIN,
+ libc::EINPROGRESS => EINPROGRESS,
+ libc::EALREADY => EALREADY,
+ libc::ENOTSOCK => ENOTSOCK,
+ libc::EMSGSIZE => EMSGSIZE,
+ libc::EPROTOTYPE => EPROTOTYPE,
+ libc::ENOPROTOOPT => ENOPROTOOPT,
+ libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
+ libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
+ libc::EOPNOTSUPP => EOPNOTSUPP,
+ libc::EPFNOSUPPORT => EPFNOSUPPORT,
+ libc::EAFNOSUPPORT => EAFNOSUPPORT,
+ libc::EADDRINUSE => EADDRINUSE,
+ libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
+ libc::ENETDOWN => ENETDOWN,
+ libc::ENETUNREACH => ENETUNREACH,
+ libc::ENETRESET => ENETRESET,
+ libc::ECONNABORTED => ECONNABORTED,
+ libc::ECONNRESET => ECONNRESET,
+ libc::ENOBUFS => ENOBUFS,
+ libc::EISCONN => EISCONN,
+ libc::ENOTCONN => ENOTCONN,
+ libc::EDESTADDRREQ => EDESTADDRREQ,
+ libc::ESHUTDOWN => ESHUTDOWN,
+ libc::ETOOMANYREFS => ETOOMANYREFS,
+ libc::ETIMEDOUT => ETIMEDOUT,
+ libc::ECONNREFUSED => ECONNREFUSED,
+ libc::ELOOP => ELOOP,
+ libc::ENAMETOOLONG => ENAMETOOLONG,
+ libc::EHOSTDOWN => EHOSTDOWN,
+ libc::EHOSTUNREACH => EHOSTUNREACH,
+ libc::ENOTEMPTY => ENOTEMPTY,
+ libc::EPROCLIM => EPROCLIM,
+ libc::EUSERS => EUSERS,
+ libc::EDQUOT => EDQUOT,
+ libc::ESTALE => ESTALE,
+ libc::EREMOTE => EREMOTE,
+ libc::EBADRPC => EBADRPC,
+ libc::ERPCMISMATCH => ERPCMISMATCH,
+ libc::EPROGUNAVAIL => EPROGUNAVAIL,
+ libc::EPROGMISMATCH => EPROGMISMATCH,
+ libc::EPROCUNAVAIL => EPROCUNAVAIL,
+ libc::ENOLCK => ENOLCK,
+ libc::EFTYPE => EFTYPE,
+ libc::EAUTH => EAUTH,
+ libc::ENEEDAUTH => ENEEDAUTH,
+ libc::ENOSYS => ENOSYS,
+ libc::ELIBEXEC => ELIBEXEC,
+ libc::ENOTSUP => ENOTSUP,
+ libc::EILSEQ => EILSEQ,
+ libc::EBACKGROUND => EBACKGROUND,
+ libc::EDIED => EDIED,
+ libc::EGREGIOUS => EGREGIOUS,
+ libc::EIEIO => EIEIO,
+ libc::EGRATUITOUS => EGRATUITOUS,
+ libc::EBADMSG => EBADMSG,
+ libc::EIDRM => EIDRM,
+ libc::EMULTIHOP => EMULTIHOP,
+ libc::ENODATA => ENODATA,
+ libc::ENOLINK => ENOLINK,
+ libc::ENOMSG => ENOMSG,
+ libc::ENOSR => ENOSR,
+ libc::ENOSTR => ENOSTR,
+ libc::EOVERFLOW => EOVERFLOW,
+ libc::EPROTO => EPROTO,
+ libc::ETIME => ETIME,
+ libc::ECANCELED => ECANCELED,
+ libc::EOWNERDEAD => EOWNERDEAD,
+ libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
+ _ => UnknownErrno,
+ }
+ }
+}
diff --git a/third_party/rust/nix/src/fcntl.rs b/third_party/rust/nix/src/fcntl.rs
index 9bfecda5ac..ccefe955de 100644
--- a/third_party/rust/nix/src/fcntl.rs
+++ b/third_party/rust/nix/src/fcntl.rs
@@ -1,27 +1,39 @@
+//! file control options
use crate::errno::Errno;
-use libc::{self, c_char, c_int, c_uint, size_t, ssize_t};
+#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
+use core::slice;
+use libc::{c_int, c_uint, size_t, ssize_t};
+#[cfg(any(
+ target_os = "netbsd",
+ apple_targets,
+ target_os = "dragonfly",
+ all(target_os = "freebsd", target_arch = "x86_64"),
+))]
+use std::ffi::CStr;
use std::ffi::OsString;
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+use std::ops::{Deref, DerefMut};
#[cfg(not(target_os = "redox"))]
use std::os::raw;
use std::os::unix::ffi::OsStringExt;
use std::os::unix::io::RawFd;
-// For splice and copy_file_range
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+use std::os::unix::io::{AsRawFd, OwnedFd};
#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "linux"
+ target_os = "netbsd",
+ apple_targets,
+ target_os = "dragonfly",
+ all(target_os = "freebsd", target_arch = "x86_64"),
))]
-use std::{
- os::unix::io::{AsFd, AsRawFd},
- ptr,
-};
+use std::path::PathBuf;
+#[cfg(any(linux_android, target_os = "freebsd"))]
+use std::{os::unix::io::AsFd, ptr};
#[cfg(feature = "fs")]
use crate::{sys::stat::Mode, NixPath, Result};
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "wasi",
@@ -32,41 +44,58 @@ use crate::{sys::stat::Mode, NixPath, Result};
pub use self::posix_fadvise::{posix_fadvise, PosixFadviseAdvice};
#[cfg(not(target_os = "redox"))]
-#[cfg(any(feature = "fs", feature = "process"))]
+#[cfg(any(feature = "fs", feature = "process", feature = "user"))]
libc_bitflags! {
+ /// Flags that control how the various *at syscalls behave.
#[cfg_attr(docsrs, doc(cfg(any(feature = "fs", feature = "process"))))]
pub struct AtFlags: c_int {
+ #[allow(missing_docs)]
+ #[doc(hidden)]
+ // Should not be used by the public API, but only internally.
AT_REMOVEDIR;
+ /// Used with [`linkat`](crate::unistd::linkat`) to create a link to a symbolic link's
+ /// target, instead of to the symbolic link itself.
AT_SYMLINK_FOLLOW;
+ /// Used with functions like [`fstatat`](crate::sys::stat::fstatat`) to operate on a link
+ /// itself, instead of the symbolic link's target.
AT_SYMLINK_NOFOLLOW;
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ /// Don't automount the terminal ("basename") component of pathname if it is a directory
+ /// that is an automount point.
+ #[cfg(linux_android)]
AT_NO_AUTOMOUNT;
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ /// If the provided path is an empty string, operate on the provided directory file
+ /// descriptor instead.
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "hurd"))]
AT_EMPTY_PATH;
+ /// Used with [`faccessat`](crate::unistd::faccessat), the checks for accessibility are
+ /// performed using the effective user and group IDs instead of the real user and group ID
#[cfg(not(target_os = "android"))]
AT_EACCESS;
}
}
-#[cfg(any(feature = "fs", feature = "term"))]
+#[cfg(any(
+ feature = "fs",
+ feature = "term",
+ all(feature = "fanotify", target_os = "linux")
+))]
libc_bitflags!(
/// Configuration options for opened files.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "fs", feature = "term"))))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "fs", feature = "term", all(feature = "fanotify", target_os = "linux")))))]
pub struct OFlag: c_int {
/// Mask for the access mode of the file.
O_ACCMODE;
/// Use alternate I/O semantics.
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_ALT_IO;
/// Open the file in append-only mode.
O_APPEND;
/// Generate a signal when input or output becomes possible.
- #[cfg(not(any(target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(any(
+ solarish,
+ target_os = "aix",
+ target_os = "haiku"
+ )))]
O_ASYNC;
/// Closes the file descriptor once an `execve` call is made.
///
@@ -75,68 +104,42 @@ libc_bitflags!(
/// Create the file if it does not exist.
O_CREAT;
/// Try to minimize cache effects of the I/O for this file.
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(
+ freebsdlike,
+ linux_android,
+ solarish,
+ target_os = "netbsd"
+ ))]
O_DIRECT;
/// If the specified path isn't a directory, fail.
- #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_DIRECTORY;
/// Implicitly follow each `write()` with an `fdatasync()`.
- #[cfg(any(target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, apple_targets, netbsdlike))]
O_DSYNC;
/// Error out if a file was not created.
O_EXCL;
/// Open for execute only.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_EXEC;
/// Open with an exclusive file lock.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "redox"))]
O_EXLOCK;
/// Same as `O_SYNC`.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- all(target_os = "linux", not(target_env = "musl")),
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
+ #[cfg(any(bsd,
+ all(target_os = "linux", not(target_env = "musl"), not(target_env = "ohos")),
target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_FSYNC;
/// Allow files whose sizes can't be represented in an `off_t` to be opened.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
O_LARGEFILE;
/// Do not update the file last access time during `read(2)`s.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
O_NOATIME;
/// Don't attach the device as the process' controlling terminal.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_NOCTTY;
/// Same as `O_NONBLOCK`.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_NDELAY;
/// `open()` will fail if the given path is a symbolic link.
O_NOFOLLOW;
@@ -144,13 +147,11 @@ libc_bitflags!(
O_NONBLOCK;
/// Don't deliver `SIGPIPE`.
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_NOSIGPIPE;
/// Obtain a file descriptor for low-level access.
///
/// The file itself is not opened and other file operations will fail.
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "redox"))]
O_PATH;
/// Only allow reading.
///
@@ -161,36 +162,24 @@ libc_bitflags!(
/// This should not be combined with `O_WRONLY` or `O_RDONLY`.
O_RDWR;
/// Similar to `O_DSYNC` but applies to `read`s instead.
- #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(target_os = "linux", netbsdlike))]
O_RSYNC;
/// Skip search permission checks.
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_SEARCH;
/// Open with a shared file lock.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "redox"))]
O_SHLOCK;
/// Implicitly follow each `write()` with an `fsync()`.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_SYNC;
/// Create an unnamed temporary file.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
O_TMPFILE;
/// Truncate an existing regular file to 0 length if it allows writing.
O_TRUNC;
/// Restore default TTY attributes.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
O_TTY_INIT;
/// Only allow writing.
///
@@ -199,9 +188,23 @@ libc_bitflags!(
}
);
+/// Computes the raw fd consumed by a function of the form `*at`.
+#[cfg(any(
+ all(feature = "fs", not(target_os = "redox")),
+ all(feature = "process", linux_android),
+ all(feature = "fanotify", target_os = "linux")
+))]
+pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
+ fd.unwrap_or(libc::AT_FDCWD)
+}
+
feature! {
#![feature = "fs"]
+/// open or create a file for reading, writing or executing
+///
+/// # See Also
+/// [`open`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html)
// The conversion is not identical on all operating systems.
#[allow(clippy::useless_conversion)]
pub fn open<P: ?Sized + NixPath>(
@@ -216,21 +219,37 @@ pub fn open<P: ?Sized + NixPath>(
Errno::result(fd)
}
+/// open or create a file for reading, writing or executing
+///
+/// The `openat` function is equivalent to the [`open`] function except in the case where the path
+/// specifies a relative path. In that case, the file to be opened is determined relative to the
+/// directory associated with the file descriptor `fd`.
+///
+/// # See Also
+/// [`openat`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/openat.html)
// The conversion is not identical on all operating systems.
#[allow(clippy::useless_conversion)]
#[cfg(not(target_os = "redox"))]
pub fn openat<P: ?Sized + NixPath>(
- dirfd: RawFd,
+ dirfd: Option<RawFd>,
path: &P,
oflag: OFlag,
mode: Mode,
) -> Result<RawFd> {
let fd = path.with_nix_path(|cstr| unsafe {
- libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint)
+ libc::openat(at_rawfd(dirfd), cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint)
})?;
Errno::result(fd)
}
+/// Change the name of a file.
+///
+/// The `renameat` function is equivalent to `rename` except in the case where either `old_path`
+/// or `new_path` specifies a relative path. In such cases, the file to be renamed (or the its new
+/// name, respectively) is located relative to `old_dirfd` or `new_dirfd`, respectively
+///
+/// # See Also
+/// [`renameat`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html)
#[cfg(not(target_os = "redox"))]
pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
old_dirfd: Option<RawFd>,
@@ -255,16 +274,30 @@ pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
#[cfg(all(target_os = "linux", target_env = "gnu"))]
#[cfg(feature = "fs")]
libc_bitflags! {
+ /// Flags for use with [`renameat2`].
#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
pub struct RenameFlags: u32 {
+ /// Atomically exchange `old_path` and `new_path`.
RENAME_EXCHANGE;
+ /// Don't overwrite `new_path` of the rename. Return an error if `new_path` already
+ /// exists.
RENAME_NOREPLACE;
+ /// creates a "whiteout" object at the source of the rename at the same time as performing
+ /// the rename.
+ ///
+ /// This operation makes sense only for overlay/union filesystem implementations.
RENAME_WHITEOUT;
}
}
feature! {
#![feature = "fs"]
+/// Like [`renameat`], but with an additional `flags` argument.
+///
+/// A `renameat2` call with an empty flags argument is equivalent to `renameat`.
+///
+/// # See Also
+/// * [`rename`](https://man7.org/linux/man-pages/man2/rename.2.html)
#[cfg(all(target_os = "linux", target_env = "gnu"))]
pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
old_dirfd: Option<RawFd>,
@@ -306,12 +339,12 @@ fn readlink_maybe_at<P: ?Sized + NixPath>(
Some(dirfd) => libc::readlinkat(
dirfd,
cstr.as_ptr(),
- v.as_mut_ptr() as *mut c_char,
+ v.as_mut_ptr().cast(),
v.capacity() as size_t,
),
None => libc::readlink(
cstr.as_ptr(),
- v.as_mut_ptr() as *mut c_char,
+ v.as_mut_ptr().cast(),
v.capacity() as size_t,
),
}
@@ -322,7 +355,11 @@ fn inner_readlink<P: ?Sized + NixPath>(
dirfd: Option<RawFd>,
path: &P,
) -> Result<OsString> {
- let mut v = Vec::with_capacity(libc::PATH_MAX as usize);
+ #[cfg(not(target_os = "hurd"))]
+ const PATH_MAX: usize = libc::PATH_MAX as usize;
+ #[cfg(target_os = "hurd")]
+ const PATH_MAX: usize = 1024; // Hurd does not define a hard limit, so try a guess first
+ let mut v = Vec::with_capacity(PATH_MAX);
{
// simple case: result is strictly less than `PATH_MAX`
@@ -340,7 +377,7 @@ fn inner_readlink<P: ?Sized + NixPath>(
let reported_size = match dirfd {
#[cfg(target_os = "redox")]
Some(_) => unreachable!(),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "hurd"))]
Some(dirfd) => {
let flags = if path.is_empty() {
AtFlags::AT_EMPTY_PATH
@@ -348,18 +385,19 @@ fn inner_readlink<P: ?Sized + NixPath>(
AtFlags::empty()
};
super::sys::stat::fstatat(
- dirfd,
+ Some(dirfd),
path,
flags | AtFlags::AT_SYMLINK_NOFOLLOW,
)
}
#[cfg(not(any(
- target_os = "android",
- target_os = "linux",
- target_os = "redox"
+ linux_android,
+ target_os = "redox",
+ target_os = "freebsd",
+ target_os = "hurd"
)))]
Some(dirfd) => super::sys::stat::fstatat(
- dirfd,
+ Some(dirfd),
path,
AtFlags::AT_SYMLINK_NOFOLLOW,
),
@@ -375,7 +413,7 @@ fn inner_readlink<P: ?Sized + NixPath>(
} else {
// If lstat doesn't cooperate, or reports an error, be a little less
// precise.
- (libc::PATH_MAX as usize).max(128) << 1
+ PATH_MAX.max(128) << 1
}
};
@@ -400,29 +438,32 @@ fn inner_readlink<P: ?Sized + NixPath>(
}
}
+/// Read value of a symbolic link
+///
+/// # See Also
+/// * [`readlink`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html)
pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
inner_readlink(None, path)
}
+/// Read value of a symbolic link.
+///
+/// Equivalent to [`readlink` ] except where `path` specifies a relative path. In that case,
+/// interpret `path` relative to open file specified by `dirfd`.
+///
+/// # See Also
+/// * [`readlink`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html)
#[cfg(not(target_os = "redox"))]
pub fn readlinkat<P: ?Sized + NixPath>(
- dirfd: RawFd,
+ dirfd: Option<RawFd>,
path: &P,
) -> Result<OsString> {
+ let dirfd = at_rawfd(dirfd);
inner_readlink(Some(dirfd), path)
}
-
-/// Computes the raw fd consumed by a function of the form `*at`.
-#[cfg(not(target_os = "redox"))]
-pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
- match fd {
- None => libc::AT_FDCWD,
- Some(fd) => fd,
- }
-}
}
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "fs")]
libc_bitflags!(
/// Additional flags for file sealing, which allows for limiting operations on a file.
@@ -436,6 +477,10 @@ libc_bitflags!(
F_SEAL_GROW;
/// The file contents cannot be modified.
F_SEAL_WRITE;
+ /// The file contents cannot be modified, except via shared writable mappings that were
+ /// created prior to the seal being set. Since Linux 5.1.
+ #[cfg(linux_android)]
+ F_SEAL_FUTURE_WRITE;
}
);
@@ -452,59 +497,105 @@ libc_bitflags!(
feature! {
#![feature = "fs"]
+/// Commands for use with [`fcntl`].
#[cfg(not(target_os = "redox"))]
#[derive(Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum FcntlArg<'a> {
+ /// Duplicate the provided file descriptor
F_DUPFD(RawFd),
+ /// Duplicate the provided file descriptor and set the `FD_CLOEXEC` flag on it.
F_DUPFD_CLOEXEC(RawFd),
+ /// Get the close-on-exec flag associated with the file descriptor
F_GETFD,
+ /// Set the close-on-exec flag associated with the file descriptor
F_SETFD(FdFlag), // FD_FLAGS
+ /// Get descriptor status flags
F_GETFL,
+ /// Set descriptor status flags
F_SETFL(OFlag), // O_NONBLOCK
+ /// Set or clear a file segment lock
F_SETLK(&'a libc::flock),
+ /// Like [`F_SETLK`](FcntlArg::F_SETLK) except that if a shared or exclusive lock is blocked by
+ /// other locks, the process waits until the request can be satisfied.
F_SETLKW(&'a libc::flock),
+ /// Get the first lock that blocks the lock description
F_GETLK(&'a mut libc::flock),
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ /// Acquire or release an open file description lock
+ #[cfg(linux_android)]
F_OFD_SETLK(&'a libc::flock),
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ /// Like [`F_OFD_SETLK`](FcntlArg::F_OFD_SETLK) except that if a conflicting lock is held on
+ /// the file, then wait for that lock to be released.
+ #[cfg(linux_android)]
F_OFD_SETLKW(&'a libc::flock),
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ /// Determine whether it would be possible to create the given lock. If not, return details
+ /// about one existing lock that would prevent it.
+ #[cfg(linux_android)]
F_OFD_GETLK(&'a mut libc::flock),
+ /// Add seals to the file
#[cfg(any(
- target_os = "android",
- target_os = "linux",
+ linux_android,
target_os = "freebsd"
))]
F_ADD_SEALS(SealFlag),
+ /// Get seals associated with the file
#[cfg(any(
- target_os = "android",
- target_os = "linux",
+ linux_android,
target_os = "freebsd"
))]
F_GET_SEALS,
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ /// Asks the drive to flush all buffered data to permanent storage.
+ #[cfg(apple_targets)]
F_FULLFSYNC,
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ /// fsync + issue barrier to drive
+ #[cfg(apple_targets)]
+ F_BARRIERFSYNC,
+ /// Return the capacity of a pipe
+ #[cfg(linux_android)]
F_GETPIPE_SZ,
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ /// Change the capacity of a pipe
+ #[cfg(linux_android)]
F_SETPIPE_SZ(c_int),
+ /// Look up the path of an open file descriptor, if possible.
+ #[cfg(any(
+ target_os = "netbsd",
+ target_os = "dragonfly",
+ apple_targets,
+ ))]
+ F_GETPATH(&'a mut PathBuf),
+ /// Look up the path of an open file descriptor, if possible.
+ #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
+ F_KINFO(&'a mut PathBuf),
+ /// Return the full path without firmlinks of the fd.
+ #[cfg(apple_targets)]
+ F_GETPATH_NOFIRMLINK(&'a mut PathBuf),
// TODO: Rest of flags
}
+/// Commands for use with [`fcntl`].
#[cfg(target_os = "redox")]
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum FcntlArg {
+ /// Duplicate the provided file descriptor
F_DUPFD(RawFd),
+ /// Duplicate the provided file descriptor and set the `FD_CLOEXEC` flag on it.
F_DUPFD_CLOEXEC(RawFd),
+ /// Get the close-on-exec flag associated with the file descriptor
F_GETFD,
+ /// Set the close-on-exec flag associated with the file descriptor
F_SETFD(FdFlag), // FD_FLAGS
+ /// Get descriptor status flags
F_GETFL,
+ /// Set descriptor status flags
F_SETFL(OFlag), // O_NONBLOCK
}
pub use self::FcntlArg::*;
+/// Perform various operations on open file descriptors.
+///
+/// # See Also
+/// * [`fcntl`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html)
// TODO: Figure out how to handle value fcntl returns
pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
let res = unsafe {
@@ -523,51 +614,95 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
#[cfg(not(target_os = "redox"))]
F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
F_OFD_SETLK(flock) => libc::fcntl(fd, libc::F_OFD_SETLK, flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
F_OFD_SETLKW(flock) => libc::fcntl(fd, libc::F_OFD_SETLKW, flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock),
#[cfg(any(
- target_os = "android",
- target_os = "linux",
+ linux_android,
target_os = "freebsd"
))]
F_ADD_SEALS(flag) => {
libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits())
}
#[cfg(any(
- target_os = "android",
- target_os = "linux",
+ linux_android,
target_os = "freebsd"
))]
F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ #[cfg(apple_targets)]
+ F_BARRIERFSYNC => libc::fcntl(fd, libc::F_BARRIERFSYNC),
+ #[cfg(linux_android)]
F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ),
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ #[cfg(linux_android)]
F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size),
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "netbsd",
+ apple_targets,
+ ))]
+ F_GETPATH(path) => {
+ let mut buffer = vec![0; libc::PATH_MAX as usize];
+ let res = libc::fcntl(fd, libc::F_GETPATH, buffer.as_mut_ptr());
+ let ok_res = Errno::result(res)?;
+ let optr = CStr::from_bytes_until_nul(&buffer).unwrap();
+ *path = PathBuf::from(OsString::from(optr.to_str().unwrap()));
+ return Ok(ok_res)
+ },
+ #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
+ F_KINFO(path) => {
+ let mut info: libc::kinfo_file = std::mem::zeroed();
+ info.kf_structsize = std::mem::size_of::<libc::kinfo_file>() as i32;
+ let res = libc::fcntl(fd, libc::F_KINFO, &mut info);
+ let ok_res = Errno::result(res)?;
+ let p = info.kf_path;
+ let u8_slice = slice::from_raw_parts(p.as_ptr().cast(), p.len());
+ let optr = CStr::from_bytes_until_nul(u8_slice).unwrap();
+ *path = PathBuf::from(OsString::from(optr.to_str().unwrap()));
+ return Ok(ok_res)
+ },
+ #[cfg(apple_targets)]
+ F_GETPATH_NOFIRMLINK(path) => {
+ let mut buffer = vec![0; libc::PATH_MAX as usize];
+ let res = libc::fcntl(fd, libc::F_GETPATH_NOFIRMLINK, buffer.as_mut_ptr());
+ let ok_res = Errno::result(res)?;
+ let optr = CStr::from_bytes_until_nul(&buffer).unwrap();
+ *path = PathBuf::from(OsString::from(optr.to_str().unwrap()));
+ return Ok(ok_res)
+ },
}
};
Errno::result(res)
}
-// TODO: convert to libc_enum
+/// Operations for use with [`Flock::lock`].
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum FlockArg {
+ /// shared file lock
LockShared,
+ /// exclusive file lock
LockExclusive,
+ /// Unlock file
Unlock,
+ /// Shared lock. Do not block when locking.
LockSharedNonblock,
+ /// Exclusive lock. Do not block when locking.
LockExclusiveNonblock,
+ #[allow(missing_docs)]
+ #[deprecated(since = "0.28.0", note = "Use FlockArg::Unlock instead")]
UnlockNonblock,
}
+#[allow(missing_docs)]
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+#[deprecated(since = "0.28.0", note = "`fcntl::Flock` should be used instead.")]
pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
use self::FlockArg::*;
@@ -582,15 +717,133 @@ pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
LockExclusiveNonblock => {
libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB)
}
+ #[allow(deprecated)]
UnlockNonblock => libc::flock(fd, libc::LOCK_UN | libc::LOCK_NB),
}
};
Errno::result(res).map(drop)
}
+
+/// Represents valid types for flock.
+///
+/// # Safety
+/// Types implementing this must not be `Clone`.
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+pub unsafe trait Flockable: AsRawFd {}
+
+/// Represents an owned flock, which unlocks on drop.
+///
+/// See [flock(2)](https://linux.die.net/man/2/flock) for details on locking semantics.
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+#[derive(Debug)]
+pub struct Flock<T: Flockable>(T);
+
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+impl<T: Flockable> Drop for Flock<T> {
+ fn drop(&mut self) {
+ let res = Errno::result(unsafe { libc::flock(self.0.as_raw_fd(), libc::LOCK_UN) });
+ if res.is_err() && !std::thread::panicking() {
+ panic!("Failed to remove flock: {}", res.unwrap_err());
+ }
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+impl<T: Flockable> Deref for Flock<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+impl<T: Flockable> DerefMut for Flock<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+impl<T: Flockable> Flock<T> {
+ /// Obtain a/an flock.
+ ///
+ /// # Example
+ /// ```
+ /// # use std::io::Write;
+ /// # use std::fs::File;
+ /// # use nix::fcntl::{Flock, FlockArg};
+ /// # fn do_stuff(file: File) {
+ /// let mut file = match Flock::lock(file, FlockArg::LockExclusive) {
+ /// Ok(l) => l,
+ /// Err(_) => return,
+ /// };
+ ///
+ /// // Do stuff
+ /// let data = "Foo bar";
+ /// _ = file.write(data.as_bytes());
+ /// _ = file.sync_data();
+ /// # }
+ pub fn lock(t: T, args: FlockArg) -> std::result::Result<Self, (T, Errno)> {
+ let flags = match args {
+ FlockArg::LockShared => libc::LOCK_SH,
+ FlockArg::LockExclusive => libc::LOCK_EX,
+ FlockArg::LockSharedNonblock => libc::LOCK_SH | libc::LOCK_NB,
+ FlockArg::LockExclusiveNonblock => libc::LOCK_EX | libc::LOCK_NB,
+ #[allow(deprecated)]
+ FlockArg::Unlock | FlockArg::UnlockNonblock => return Err((t, Errno::EINVAL)),
+ };
+ match Errno::result(unsafe { libc::flock(t.as_raw_fd(), flags) }) {
+ Ok(_) => Ok(Self(t)),
+ Err(errno) => Err((t, errno)),
+ }
+ }
+
+ /// Remove the lock and return the object wrapped within.
+ ///
+ /// # Example
+ /// ```
+ /// # use std::fs::File;
+ /// # use nix::fcntl::{Flock, FlockArg};
+ /// fn do_stuff(file: File) -> nix::Result<()> {
+ /// let mut lock = match Flock::lock(file, FlockArg::LockExclusive) {
+ /// Ok(l) => l,
+ /// Err((_,e)) => return Err(e),
+ /// };
+ ///
+ /// // Do critical section
+ ///
+ /// // Unlock
+ /// let file = match lock.unlock() {
+ /// Ok(f) => f,
+ /// Err((_, e)) => return Err(e),
+ /// };
+ ///
+ /// // Do anything else
+ ///
+ /// Ok(())
+ /// }
+ pub fn unlock(self) -> std::result::Result<T, (Self, Errno)> {
+ let inner = unsafe { match Errno::result(libc::flock(self.0.as_raw_fd(), libc::LOCK_UN)) {
+ Ok(_) => std::ptr::read(&self.0),
+ Err(errno) => return Err((self, errno)),
+ }};
+
+ std::mem::forget(self);
+ Ok(inner)
+ }
+}
+
+// Safety: `File` is not [std::clone::Clone].
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+unsafe impl Flockable for std::fs::File {}
+
+// Safety: `OwnedFd` is not [std::clone::Clone].
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+unsafe impl Flockable for OwnedFd {}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[cfg(feature = "zerocopy")]
libc_bitflags! {
/// Additional flags to `splice` and friends.
@@ -636,7 +889,7 @@ feature! {
// Note: FreeBSD defines the offset argument as "off_t". Linux and Android
// define it as "loff_t". But on both OSes, on all supported platforms, those
// are 64 bits. So Nix uses i64 to make the docs simple and consistent.
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
fd_in: Fd1,
off_in: Option<&mut i64>,
@@ -669,7 +922,7 @@ pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
let ret = unsafe {
libc::syscall(
libc::SYS_copy_file_range,
- fd_in,
+ fd_in.as_fd().as_raw_fd(),
off_in,
fd_out.as_fd().as_raw_fd(),
off_out,
@@ -682,7 +935,11 @@ pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
Errno::result(ret).map(|r| r as usize)
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+/// Splice data to/from a pipe
+///
+/// # See Also
+/// *[`splice`](https://man7.org/linux/man-pages/man2/splice.2.html)
+#[cfg(linux_android)]
pub fn splice(
fd_in: RawFd,
off_in: Option<&mut libc::loff_t>,
@@ -704,7 +961,11 @@ pub fn splice(
Errno::result(ret).map(|r| r as usize)
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+/// Duplicate pipe content
+///
+/// # See Also
+/// *[`tee`](https://man7.org/linux/man-pages/man2/tee.2.html)
+#[cfg(linux_android)]
pub fn tee(
fd_in: RawFd,
fd_out: RawFd,
@@ -715,7 +976,11 @@ pub fn tee(
Errno::result(ret).map(|r| r as usize)
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+/// Splice user pages to/from a pipe
+///
+/// # See Also
+/// *[`vmsplice`](https://man7.org/linux/man-pages/man2/vmsplice.2.html)
+#[cfg(linux_android)]
pub fn vmsplice(
fd: RawFd,
iov: &[std::io::IoSlice<'_>],
@@ -724,7 +989,7 @@ pub fn vmsplice(
let ret = unsafe {
libc::vmsplice(
fd,
- iov.as_ptr() as *const libc::iovec,
+ iov.as_ptr().cast(),
iov.len(),
flags.bits(),
)
@@ -793,16 +1058,22 @@ pub struct SpacectlRange(pub libc::off_t, pub libc::off_t);
#[cfg(any(target_os = "freebsd"))]
impl SpacectlRange {
+ /// Is the range empty?
+ ///
+ /// After a successful call to [`fspacectl`], A value of `true` for `SpacectlRange::is_empty`
+ /// indicates that the operation is complete.
#[inline]
pub fn is_empty(&self) -> bool {
self.1 == 0
}
+ /// Remaining length of the range
#[inline]
pub fn len(&self) -> libc::off_t {
self.1
}
+ /// Next file offset to operate on
#[inline]
pub fn offset(&self) -> libc::off_t {
self.0
@@ -849,6 +1120,7 @@ impl SpacectlRange {
/// assert_eq!(buf, b"012\0\0\0\0\0\09abcdef");
/// ```
#[cfg(target_os = "freebsd")]
+#[inline] // Delays codegen, preventing linker errors with dylibs and --no-allow-shlib-undefined
pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result<SpacectlRange> {
let mut rqsr = libc::spacectl_range {
r_offset: range.0,
@@ -897,6 +1169,7 @@ pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result<SpacectlRange> {
/// assert_eq!(buf, b"012\0\0\0\0\0\09abcdef");
/// ```
#[cfg(target_os = "freebsd")]
+#[inline] // Delays codegen, preventing linker errors with dylibs and --no-allow-shlib-undefined
pub fn fspacectl_all(
fd: RawFd,
offset: libc::off_t,
@@ -922,8 +1195,7 @@ pub fn fspacectl_all(
}
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "wasi",
@@ -937,21 +1209,34 @@ mod posix_fadvise {
#[cfg(feature = "fs")]
libc_enum! {
+ /// The specific advice provided to [`posix_fadvise`].
#[repr(i32)]
#[non_exhaustive]
#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
pub enum PosixFadviseAdvice {
+ /// Revert to the default data access behavior.
POSIX_FADV_NORMAL,
+ /// The file data will be accessed sequentially.
POSIX_FADV_SEQUENTIAL,
+ /// A hint that file data will be accessed randomly, and prefetching is likely not
+ /// advantageous.
POSIX_FADV_RANDOM,
+ /// The specified data will only be accessed once and then not reused.
POSIX_FADV_NOREUSE,
+ /// The specified data will be accessed in the near future.
POSIX_FADV_WILLNEED,
+ /// The specified data will not be accessed in the near future.
POSIX_FADV_DONTNEED,
}
}
feature! {
#![feature = "fs"]
+ /// Allows a process to describe to the system its data access behavior for an open file
+ /// descriptor.
+ ///
+ /// # See Also
+ /// * [`posix_fadvise`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fadvise.html)
pub fn posix_fadvise(
fd: RawFd,
offset: libc::off_t,
@@ -963,20 +1248,22 @@ mod posix_fadvise {
if res == 0 {
Ok(())
} else {
- Err(Errno::from_i32(res))
+ Err(Errno::from_raw(res))
}
}
}
}
+/// Pre-allocate storage for a range in a file
+///
+/// # See Also
+/// * [`posix_fallocate`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html)
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "dragonfly",
+ linux_android,
+ freebsdlike,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "wasi",
- target_os = "freebsd"
))]
pub fn posix_fallocate(
fd: RawFd,
@@ -987,7 +1274,7 @@ pub fn posix_fallocate(
match Errno::result(res) {
Err(err) => Err(err),
Ok(0) => Ok(()),
- Ok(errno) => Err(Errno::from_i32(errno)),
+ Ok(errno) => Err(Errno::from_raw(errno)),
}
}
}
diff --git a/third_party/rust/nix/src/features.rs b/third_party/rust/nix/src/features.rs
index 9e292cbf5d..0a0c618096 100644
--- a/third_party/rust/nix/src/features.rs
+++ b/third_party/rust/nix/src/features.rs
@@ -1,7 +1,7 @@
//! Feature tests for OS functionality
pub use self::os::*;
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
mod os {
use crate::sys::utsname::uname;
use crate::Result;
@@ -98,11 +98,10 @@ mod os {
}
#[cfg(any(
- target_os = "dragonfly", // Since ???
- target_os = "freebsd", // Since 10.0
+ freebsdlike, // FreeBSD since 10.0 DragonFlyBSD since ???
+ netbsdlike, // NetBSD since 6.0 OpenBSD since 5.7
+ target_os = "hurd", // Since glibc 2.28
target_os = "illumos", // Since ???
- target_os = "netbsd", // Since 6.0
- target_os = "openbsd", // Since 5.7
target_os = "redox", // Since 1-july-2020
))]
mod os {
@@ -114,8 +113,7 @@ mod os {
#[cfg(any(
target_os = "aix",
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "fuchsia",
target_os = "haiku",
target_os = "solaris"
diff --git a/third_party/rust/nix/src/ifaddrs.rs b/third_party/rust/nix/src/ifaddrs.rs
index 70b50b01eb..b3de64b01a 100644
--- a/third_party/rust/nix/src/ifaddrs.rs
+++ b/third_party/rust/nix/src/ifaddrs.rs
@@ -4,7 +4,7 @@
//! of interfaces and their associated addresses.
use cfg_if::cfg_if;
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
use std::convert::TryFrom;
use std::ffi;
use std::iter::Iterator;
@@ -33,7 +33,7 @@ pub struct InterfaceAddress {
}
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] {
+ if #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))] {
fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr {
info.ifa_ifu
}
@@ -53,7 +53,7 @@ cfg_if! {
/// ss_len field to sizeof(sockaddr_storage). This is supposedly valid as all
/// members of the sockaddr_storage are "ok" with being zeroed out (there are
/// no pointers).
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
unsafe fn workaround_xnu_bug(info: &libc::ifaddrs) -> Option<SockaddrStorage> {
let src_sock = info.ifa_netmask;
if src_sock.is_null() {
@@ -62,22 +62,24 @@ unsafe fn workaround_xnu_bug(info: &libc::ifaddrs) -> Option<SockaddrStorage> {
let mut dst_sock = mem::MaybeUninit::<libc::sockaddr_storage>::zeroed();
- // memcpy only sa_len bytes, assume the rest is zero
- std::ptr::copy_nonoverlapping(
- src_sock as *const u8,
- dst_sock.as_mut_ptr() as *mut u8,
- (*src_sock).sa_len.into(),
- );
+ let dst_sock = unsafe {
+ // memcpy only sa_len bytes, assume the rest is zero
+ std::ptr::copy_nonoverlapping(
+ src_sock as *const u8,
+ dst_sock.as_mut_ptr().cast(),
+ (*src_sock).sa_len.into(),
+ );
- // Initialize ss_len to sizeof(libc::sockaddr_storage).
- (*dst_sock.as_mut_ptr()).ss_len =
- u8::try_from(mem::size_of::<libc::sockaddr_storage>()).unwrap();
- let dst_sock = dst_sock.assume_init();
+ // Initialize ss_len to sizeof(libc::sockaddr_storage).
+ (*dst_sock.as_mut_ptr()).ss_len =
+ u8::try_from(mem::size_of::<libc::sockaddr_storage>()).unwrap();
+ dst_sock.assume_init()
+ };
let dst_sock_ptr =
&dst_sock as *const libc::sockaddr_storage as *const libc::sockaddr;
- SockaddrStorage::from_raw(dst_sock_ptr, None)
+ unsafe { SockaddrStorage::from_raw(dst_sock_ptr, None) }
}
impl InterfaceAddress {
@@ -85,14 +87,16 @@ impl InterfaceAddress {
fn from_libc_ifaddrs(info: &libc::ifaddrs) -> InterfaceAddress {
let ifname = unsafe { ffi::CStr::from_ptr(info.ifa_name) };
let address = unsafe { SockaddrStorage::from_raw(info.ifa_addr, None) };
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
let netmask = unsafe { workaround_xnu_bug(info) };
- #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+ #[cfg(not(apple_targets))]
let netmask =
unsafe { SockaddrStorage::from_raw(info.ifa_netmask, None) };
let mut addr = InterfaceAddress {
interface_name: ifname.to_string_lossy().to_string(),
- flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
+ flags: InterfaceFlags::from_bits_truncate(
+ info.ifa_flags as IflagsType,
+ ),
address,
netmask,
broadcast: None,
diff --git a/third_party/rust/nix/src/kmod.rs b/third_party/rust/nix/src/kmod.rs
index d3725c3f8a..5cf2ed2c39 100644
--- a/third_party/rust/nix/src/kmod.rs
+++ b/third_party/rust/nix/src/kmod.rs
@@ -102,7 +102,11 @@ libc_bitflags!(
/// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html)
/// for a detailed description how these flags work.
pub struct DeleteModuleFlags: libc::c_int {
+ /// `delete_module` will return immediately, with an error, if the module has a nonzero
+ /// reference count.
O_NONBLOCK;
+ /// `delete_module` will unload the module immediately, regardless of whether it has a
+ /// nonzero reference count.
O_TRUNC;
}
);
diff --git a/third_party/rust/nix/src/lib.rs b/third_party/rust/nix/src/lib.rs
index af0c67b0f3..dffac29b54 100644
--- a/third_party/rust/nix/src/lib.rs
+++ b/third_party/rust/nix/src/lib.rs
@@ -12,6 +12,7 @@
//! * `dir` - Stuff relating to directory iteration
//! * `env` - Manipulate environment variables
//! * `event` - Event-driven APIs, like `kqueue` and `epoll`
+//! * `fanotify` - Linux's `fanotify` filesystem events monitoring API
//! * `feature` - Query characteristics of the OS at runtime
//! * `fs` - File system functionality
//! * `hostname` - Get and set the system's hostname
@@ -41,7 +42,6 @@
//! * `zerocopy` - APIs like `sendfile` and `copy_file_range`
#![crate_name = "nix"]
#![cfg(unix)]
-#![cfg_attr(docsrs, doc(cfg(all())))]
#![allow(non_camel_case_types)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
@@ -54,6 +54,7 @@
feature = "dir",
feature = "env",
feature = "event",
+ feature = "fanotify",
feature = "feature",
feature = "fs",
feature = "hostname",
@@ -90,6 +91,7 @@
#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(clippy::cast_ptr_alignment)]
+#![deny(unsafe_op_in_unsafe_fn)]
// Re-exported external crates
pub use libc;
@@ -116,42 +118,29 @@ feature! {
#[deny(missing_docs)]
pub mod features;
}
-#[allow(missing_docs)]
pub mod fcntl;
feature! {
#![feature = "net"]
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"))]
+ #[cfg(any(linux_android,
+ bsd,
+ solarish))]
#[deny(missing_docs)]
pub mod ifaddrs;
#[cfg(not(target_os = "redox"))]
#[deny(missing_docs)]
pub mod net;
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
feature! {
#![feature = "kmod"]
- #[allow(missing_docs)]
pub mod kmod;
}
feature! {
#![feature = "mount"]
pub mod mount;
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"
-))]
+#[cfg(any(freebsdlike, target_os = "linux", target_os = "netbsd"))]
feature! {
#![feature = "mqueue"]
pub mod mqueue;
@@ -173,7 +162,6 @@ feature! {
pub mod sys;
feature! {
#![feature = "time"]
- #[allow(missing_docs)]
pub mod time;
}
// This can be implemented for other platforms as soon as libc
@@ -192,9 +180,11 @@ feature! {
#[allow(missing_docs)]
pub mod ucontext;
}
-#[allow(missing_docs)]
pub mod unistd;
+#[cfg(any(feature = "poll", feature = "event"))]
+mod poll_timeout;
+
use std::ffi::{CStr, CString, OsStr};
use std::mem::MaybeUninit;
use std::os::unix::ffi::OsStrExt;
@@ -311,7 +301,7 @@ impl NixPath for [u8] {
}
let mut buf = MaybeUninit::<[u8; MAX_STACK_ALLOCATION]>::uninit();
- let buf_ptr = buf.as_mut_ptr() as *mut u8;
+ let buf_ptr = buf.as_mut_ptr().cast();
unsafe {
ptr::copy_nonoverlapping(self.as_ptr(), buf_ptr, self.len());
diff --git a/third_party/rust/nix/src/macros.rs b/third_party/rust/nix/src/macros.rs
index adff2bc6be..3010a1a053 100644
--- a/third_party/rust/nix/src/macros.rs
+++ b/third_party/rust/nix/src/macros.rs
@@ -27,9 +27,9 @@ macro_rules! feature {
/// /// PROT_WRITE enables write protect
/// PROT_WRITE;
/// PROT_EXEC;
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
+/// #[cfg(linux_android)]
/// PROT_GROWSDOWN;
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
+/// #[cfg(linux_android)]
/// PROT_GROWSUP;
/// }
/// }
@@ -89,9 +89,9 @@ macro_rules! libc_bitflags {
/// PROT_READ,
/// PROT_WRITE,
/// PROT_EXEC,
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
+/// #[cfg(linux_android)]
/// PROT_GROWSDOWN,
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
+/// #[cfg(linux_android)]
/// PROT_GROWSUP,
/// }
/// }
diff --git a/third_party/rust/nix/src/mount/bsd.rs b/third_party/rust/nix/src/mount/bsd.rs
index 6ed2dc7fbf..248e0ab1d2 100644
--- a/third_party/rust/nix/src/mount/bsd.rs
+++ b/third_party/rust/nix/src/mount/bsd.rs
@@ -17,36 +17,29 @@ libc_bitflags!(
pub struct MntFlags: c_int {
/// ACL support enabled.
#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MNT_ACLS;
/// All I/O to the file system should be done asynchronously.
MNT_ASYNC;
/// dir should instead be a file system ID encoded as “FSID:val0:val1”.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MNT_BYFSID;
/// Force a read-write mount even if the file system appears to be
/// unclean.
MNT_FORCE;
/// GEOM journal support enabled.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MNT_GJOURNAL;
/// MAC support for objects.
- #[cfg(any(target_os = "macos", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(apple_targets, target_os = "freebsd"))]
MNT_MULTILABEL;
/// Disable read clustering.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MNT_NOCLUSTERR;
/// Disable write clustering.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MNT_NOCLUSTERW;
/// Enable NFS version 4 ACLs.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MNT_NFS4ACLS;
/// Do not update access times.
MNT_NOATIME;
@@ -55,8 +48,7 @@ libc_bitflags!(
/// Do not honor setuid or setgid bits on files when executing them.
MNT_NOSUID;
/// Do not follow symlinks.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MNT_NOSYMFOLLOW;
/// Mount read-only.
MNT_RDONLY;
@@ -66,39 +58,29 @@ libc_bitflags!(
/// Create a snapshot of the file system.
///
/// See [mksnap_ffs(8)](https://www.freebsd.org/cgi/man.cgi?query=mksnap_ffs)
- #[cfg(any(target_os = "macos", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(apple_targets, target_os = "freebsd"))]
MNT_SNAPSHOT;
/// Using soft updates.
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(freebsdlike, netbsdlike))]
MNT_SOFTDEP;
/// Directories with the SUID bit set chown new files to their own
/// owner.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MNT_SUIDDIR;
/// All I/O to the file system should be done synchronously.
MNT_SYNCHRONOUS;
/// Union with underlying fs.
#[cfg(any(
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MNT_UNION;
/// Indicates that the mount command is being applied to an already
/// mounted file system.
MNT_UPDATE;
/// Check vnode use counts.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MNT_NONBUSY;
}
);
@@ -198,7 +180,6 @@ pub type NmountResult = std::result::Result<(), NmountError>;
/// * [`nmount(2)`](https://www.freebsd.org/cgi/man.cgi?query=nmount)
/// * [`nullfs(5)`](https://www.freebsd.org/cgi/man.cgi?query=nullfs)
#[cfg(target_os = "freebsd")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
#[derive(Debug, Default)]
pub struct Nmount<'a> {
// n.b. notgull: In reality, this is a list that contains
@@ -210,12 +191,11 @@ pub struct Nmount<'a> {
}
#[cfg(target_os = "freebsd")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
impl<'a> Nmount<'a> {
/// Helper function to push a slice onto the `iov` array.
fn push_slice(&mut self, val: &'a [u8], is_owned: bool) {
self.iov.push(libc::iovec {
- iov_base: val.as_ptr() as *mut _,
+ iov_base: val.as_ptr().cast_mut().cast(),
iov_len: val.len(),
});
self.is_owned.push(is_owned);
@@ -386,7 +366,7 @@ impl<'a> Nmount<'a> {
// SAFETY: we are pushing a mutable iovec here, so we can't use
// the above method
self.iov.push(libc::iovec {
- iov_base: errmsg.as_mut_ptr() as *mut c_void,
+ iov_base: errmsg.as_mut_ptr().cast(),
iov_len: errmsg.len(),
});
@@ -396,13 +376,10 @@ impl<'a> Nmount<'a> {
match Errno::result(res) {
Ok(_) => Ok(()),
Err(error) => {
- let errmsg = match errmsg.iter().position(|&x| x == 0) {
- None => None,
- Some(0) => None,
- Some(n) => {
- let sl = &errmsg[0..n + 1];
- Some(CStr::from_bytes_with_nul(sl).unwrap())
- }
+ let errmsg = if errmsg[0] == 0 {
+ None
+ } else {
+ CStr::from_bytes_until_nul(&errmsg[..]).ok()
};
Err(NmountError::new(error, errmsg))
}
diff --git a/third_party/rust/nix/src/mount/linux.rs b/third_party/rust/nix/src/mount/linux.rs
index e987603786..aa166bc9d3 100644
--- a/third_party/rust/nix/src/mount/linux.rs
+++ b/third_party/rust/nix/src/mount/linux.rs
@@ -85,7 +85,7 @@ libc_bitflags!(
MNT_DETACH;
/// Mark the mount point as expired.
MNT_EXPIRE;
- /// Don't dereference `target` if it is a symlink.
+ /// Don't dereference `target` if it is a symlink.
UMOUNT_NOFOLLOW;
}
);
diff --git a/third_party/rust/nix/src/mount/mod.rs b/third_party/rust/nix/src/mount/mod.rs
index e98b49c343..8caf27f7df 100644
--- a/third_party/rust/nix/src/mount/mod.rs
+++ b/third_party/rust/nix/src/mount/mod.rs
@@ -1,26 +1,12 @@
//! Mount file systems
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(linux_android)]
mod linux;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
pub use self::linux::*;
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(bsd)]
mod bsd;
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(bsd)]
pub use self::bsd::*;
diff --git a/third_party/rust/nix/src/mqueue.rs b/third_party/rust/nix/src/mqueue.rs
index fb07d2accb..7f9d687521 100644
--- a/third_party/rust/nix/src/mqueue.rs
+++ b/third_party/rust/nix/src/mqueue.rs
@@ -35,7 +35,7 @@ use crate::NixPath;
use crate::Result;
use crate::sys::stat::Mode;
-use libc::{self, c_char, mqd_t, size_t};
+use libc::{self, mqd_t, size_t};
use std::mem;
#[cfg(any(
target_os = "linux",
@@ -88,11 +88,9 @@ pub struct MqdT(mqd_t);
// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
/// Size of a message queue attribute member
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub type mq_attr_member_t = i64;
/// Size of a message queue attribute member
#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub type mq_attr_member_t = libc::c_long;
impl MqAttr {
@@ -205,7 +203,7 @@ pub fn mq_receive(
let res = unsafe {
libc::mq_receive(
mqdes.0,
- message.as_mut_ptr() as *mut c_char,
+ message.as_mut_ptr().cast(),
len,
msg_prio as *mut u32,
)
@@ -229,7 +227,7 @@ feature! {
let res = unsafe {
libc::mq_timedreceive(
mqdes.0,
- message.as_mut_ptr() as *mut c_char,
+ message.as_mut_ptr().cast(),
len,
msg_prio as *mut u32,
abstime.as_ref(),
@@ -244,12 +242,7 @@ feature! {
/// See also [`mq_send(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
pub fn mq_send(mqdes: &MqdT, message: &[u8], msq_prio: u32) -> Result<()> {
let res = unsafe {
- libc::mq_send(
- mqdes.0,
- message.as_ptr() as *const c_char,
- message.len(),
- msq_prio,
- )
+ libc::mq_send(mqdes.0, message.as_ptr().cast(), message.len(), msq_prio)
};
Errno::result(res).map(drop)
}
diff --git a/third_party/rust/nix/src/net/if_.rs b/third_party/rust/nix/src/net/if_.rs
index ec46260714..c66b5dc0b3 100644
--- a/third_party/rust/nix/src/net/if_.rs
+++ b/third_party/rust/nix/src/net/if_.rs
@@ -3,9 +3,17 @@
//! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
//! or "socan1" into device numbers.
+use std::fmt;
use crate::{Error, NixPath, Result};
use libc::c_uint;
+#[cfg(not(solarish))]
+/// type alias for InterfaceFlags
+pub type IflagsType = libc::c_int;
+#[cfg(solarish)]
+/// type alias for InterfaceFlags
+pub type IflagsType = libc::c_longlong;
+
/// Resolve an interface into a interface number.
pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
let if_index = name
@@ -20,323 +28,236 @@ pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
libc_bitflags!(
/// Standard interface flags, used by `getifaddrs`
- pub struct InterfaceFlags: libc::c_int {
+ pub struct InterfaceFlags: IflagsType {
+
/// Interface is running. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_UP;
+ IFF_UP as IflagsType;
/// Valid broadcast address set. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_BROADCAST;
+ IFF_BROADCAST as IflagsType;
/// Internal debugging flag. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
#[cfg(not(target_os = "haiku"))]
- IFF_DEBUG;
+ IFF_DEBUG as IflagsType;
/// Interface is a loopback interface. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_LOOPBACK;
+ IFF_LOOPBACK as IflagsType;
/// Interface is a point-to-point link. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_POINTOPOINT;
+ IFF_POINTOPOINT as IflagsType;
/// Avoid use of trailers. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android",
+ #[cfg(any(
+ linux_android,
+ solarish,
+ apple_targets,
target_os = "fuchsia",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_NOTRAILERS;
+ target_os = "netbsd"))]
+ IFF_NOTRAILERS as IflagsType;
/// Interface manages own routes.
#[cfg(any(target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_SMART;
+ IFF_SMART as IflagsType;
/// Resources allocated. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_RUNNING;
+ #[cfg(any(
+ linux_android,
+ bsd,
+ solarish,
+ target_os = "fuchsia"))]
+ IFF_RUNNING as IflagsType;
/// No arp protocol, L2 destination address not set. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_NOARP;
+ IFF_NOARP as IflagsType;
/// Interface is in promiscuous mode. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_PROMISC;
+ IFF_PROMISC as IflagsType;
/// Receive all multicast packets. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_ALLMULTI;
+ IFF_ALLMULTI as IflagsType;
/// Master of a load balancing bundle. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_MASTER;
/// transmission in progress, tx hardware queue is full
- #[cfg(any(target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(target_os = "freebsd", apple_targets, netbsdlike))]
IFF_OACTIVE;
/// Protocol code on board.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_INTELLIGENT;
+ #[cfg(solarish)]
+ IFF_INTELLIGENT as IflagsType;
/// Slave of a load balancing bundle. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_SLAVE;
/// Can't hear own transmissions.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
IFF_SIMPLEX;
/// Supports multicast. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_MULTICAST;
+ IFF_MULTICAST as IflagsType;
/// Per link layer defined bit.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
IFF_LINK0;
/// Multicast using broadcast.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_MULTI_BCAST;
+ #[cfg(solarish)]
+ IFF_MULTI_BCAST as IflagsType;
/// Is able to select media type via ifmap. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_PORTSEL;
/// Per link layer defined bit.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
IFF_LINK1;
/// Non-unique address.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_UNNUMBERED;
+ #[cfg(solarish)]
+ IFF_UNNUMBERED as IflagsType;
/// Auto media selection active. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_AUTOMEDIA;
/// Per link layer defined bit.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
IFF_LINK2;
/// Use alternate physical connection.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(freebsdlike, apple_targets))]
IFF_ALTPHYS;
/// DHCP controls interface.
- #[cfg(any(target_os = "solaris", target_os = "illumos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_DHCPRUNNING;
+ #[cfg(solarish)]
+ IFF_DHCPRUNNING as IflagsType;
/// The addresses are lost when the interface goes down. (see
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_DYNAMIC;
/// Do not advertise.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_PRIVATE;
+ #[cfg(solarish)]
+ IFF_PRIVATE as IflagsType;
/// Driver signals L1 up. Volatile.
#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_LOWER_UP;
/// Interface is in polling mode.
#[cfg(any(target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_POLLING_COMPAT;
/// Unconfigurable using ioctl(2).
#[cfg(any(target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_CANTCONFIG;
/// Do not transmit packets.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_NOXMIT;
+ #[cfg(solarish)]
+ IFF_NOXMIT as IflagsType;
/// Driver signals dormant. Volatile.
#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_DORMANT;
/// User-requested promisc mode.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
IFF_PPROMISC;
/// Just on-link subnet.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_NOLOCAL;
+ #[cfg(solarish)]
+ IFF_NOLOCAL as IflagsType;
/// Echo sent packets. Volatile.
#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_ECHO;
/// User-requested monitor mode.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
IFF_MONITOR;
/// Address is deprecated.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_DEPRECATED;
+ #[cfg(solarish)]
+ IFF_DEPRECATED as IflagsType;
/// Static ARP.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
IFF_STATICARP;
/// Address from stateless addrconf.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_ADDRCONF;
+ #[cfg(solarish)]
+ IFF_ADDRCONF as IflagsType;
/// Interface is in polling mode.
#[cfg(any(target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_NPOLLING;
/// Router on interface.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_ROUTER;
+ #[cfg(solarish)]
+ IFF_ROUTER as IflagsType;
/// Interface is in polling mode.
#[cfg(any(target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_IDIRECT;
/// Interface is winding down
#[cfg(any(target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_DYING;
/// No NUD on interface.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_NONUD;
+ #[cfg(solarish)]
+ IFF_NONUD as IflagsType;
/// Interface is being renamed
#[cfg(any(target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IFF_RENAMING;
/// Anycast address.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_ANYCAST;
+ #[cfg(solarish)]
+ IFF_ANYCAST as IflagsType;
/// Don't exchange routing info.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_NORTEXCH;
+ #[cfg(solarish)]
+ IFF_NORTEXCH as IflagsType;
/// Do not provide packet information
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_NO_PI as libc::c_int;
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
+ IFF_NO_PI as IflagsType;
/// TUN device (no Ethernet headers)
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_TUN as libc::c_int;
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
+ IFF_TUN as IflagsType;
/// TAP device
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_TAP as libc::c_int;
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
+ IFF_TAP as IflagsType;
/// IPv4 interface.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_IPV4;
+ #[cfg(solarish)]
+ IFF_IPV4 as IflagsType;
/// IPv6 interface.
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_IPV6;
+ #[cfg(solarish)]
+ IFF_IPV6 as IflagsType;
/// in.mpathd test address
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_NOFAILOVER;
+ #[cfg(solarish)]
+ IFF_NOFAILOVER as IflagsType;
/// Interface has failed
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_FAILED;
+ #[cfg(solarish)]
+ IFF_FAILED as IflagsType;
/// Interface is a hot-spare
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_STANDBY;
+ #[cfg(solarish)]
+ IFF_STANDBY as IflagsType;
/// Functioning but not used
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_INACTIVE;
+ #[cfg(solarish)]
+ IFF_INACTIVE as IflagsType;
/// Interface is offline
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_OFFLINE;
- #[cfg(target_os = "solaris")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_COS_ENABLED;
- /// Prefer as source addr.
- #[cfg(target_os = "solaris")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_PREFERRED;
+ #[cfg(solarish)]
+ IFF_OFFLINE as IflagsType;
+ /// Has CoS marking supported
+ #[cfg(solarish)]
+ IFF_COS_ENABLED as IflagsType;
+ /// Prefer as source addr
+ #[cfg(solarish)]
+ IFF_PREFERRED as IflagsType;
/// RFC3041
- #[cfg(target_os = "solaris")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_TEMPORARY;
- /// MTU set with SIOCSLIFMTU
- #[cfg(target_os = "solaris")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_FIXEDMTU;
- /// Cannot send / receive packets
- #[cfg(target_os = "solaris")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_VIRTUAL;
+ #[cfg(solarish)]
+ IFF_TEMPORARY as IflagsType;
+ /// MTU set
+ #[cfg(solarish)]
+ IFF_FIXEDMTU as IflagsType;
+ /// Cannot send/receive packets
+ #[cfg(solarish)]
+ IFF_VIRTUAL as IflagsType;
/// Local address in use
- #[cfg(target_os = "solaris")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_DUPLICATE;
+ #[cfg(solarish)]
+ IFF_DUPLICATE as IflagsType;
/// IPMP IP interface
- #[cfg(target_os = "solaris")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IFF_IPMP;
+ #[cfg(solarish)]
+ IFF_IPMP as IflagsType;
}
);
+impl fmt::Display for InterfaceFlags {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ bitflags::parser::to_writer(self, f)
+ }
+}
+
+
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
+ bsd,
target_os = "fuchsia",
- target_os = "ios",
target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "illumos",
+ solarish,
))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
mod if_nameindex {
use super::*;
@@ -373,6 +294,7 @@ mod if_nameindex {
}
/// A list of the network interfaces available on this system. Obtained from [`if_nameindex()`].
+ #[repr(transparent)]
pub struct Interfaces {
ptr: NonNull<libc::if_nameindex>,
}
@@ -388,7 +310,7 @@ mod if_nameindex {
/// null-terminated, so calling this calculates the length. If random access isn't needed,
/// [`Interfaces::iter()`] should be used instead.
pub fn to_slice(&self) -> &[Interface] {
- let ifs = self.ptr.as_ptr() as *const Interface;
+ let ifs = self.ptr.as_ptr().cast();
let len = self.iter().count();
unsafe { std::slice::from_raw_parts(ifs, len) }
}
@@ -458,14 +380,9 @@ mod if_nameindex {
}
}
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
+ bsd,
target_os = "fuchsia",
- target_os = "ios",
target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "illumos",
+ solarish,
))]
pub use if_nameindex::*;
diff --git a/third_party/rust/nix/src/poll.rs b/third_party/rust/nix/src/poll.rs
index 9181bf7f30..0ad9f40d3b 100644
--- a/third_party/rust/nix/src/poll.rs
+++ b/third_party/rust/nix/src/poll.rs
@@ -2,6 +2,7 @@
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd};
use crate::errno::Errno;
+pub use crate::poll_timeout::PollTimeout;
use crate::Result;
/// This is a wrapper around `libc::pollfd`.
@@ -22,24 +23,35 @@ pub struct PollFd<'fd> {
impl<'fd> PollFd<'fd> {
/// Creates a new `PollFd` specifying the events of interest
/// for a given file descriptor.
- //
- // Different from other I/O-safe interfaces, here, we have to take `AsFd`
- // by reference to prevent the case where the `fd` is closed but it is
- // still in use. For example:
+ ///
+ /// # Examples
+ /// ```no_run
+ /// # use std::os::unix::io::{AsFd, AsRawFd, FromRawFd};
+ /// # use nix::{
+ /// # poll::{PollTimeout, PollFd, PollFlags, poll},
+ /// # unistd::{pipe, read}
+ /// # };
+ /// let (r, w) = pipe().unwrap();
+ /// let pfd = PollFd::new(r.as_fd(), PollFlags::POLLIN);
+ /// let mut fds = [pfd];
+ /// poll(&mut fds, PollTimeout::NONE).unwrap();
+ /// let mut buf = [0u8; 80];
+ /// read(r.as_raw_fd(), &mut buf[..]);
+ /// ```
+ // Unlike I/O functions, constructors like this must take `BorrowedFd`
+ // instead of AsFd or &AsFd. Otherwise, an `OwnedFd` argument would be
+ // dropped at the end of the method, leaving the structure referencing a
+ // closed file descriptor. For example:
//
// ```rust
- // let (reader, _) = pipe().unwrap();
- //
- // // If `PollFd::new()` takes `AsFd` by value, then `reader` will be consumed,
- // // but the file descriptor of `reader` will still be in use.
- // let pollfd = PollFd::new(reader, flag);
- //
+ // let (r, _) = pipe().unwrap();
+ // let pollfd = PollFd::new(r, flag); // Drops the OwnedFd
// // Do something with `pollfd`, which uses the CLOSED fd.
// ```
- pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> PollFd<'fd> {
+ pub fn new(fd: BorrowedFd<'fd>, events: PollFlags) -> PollFd<'fd> {
PollFd {
pollfd: libc::pollfd {
- fd: fd.as_fd().as_raw_fd(),
+ fd: fd.as_raw_fd(),
events: events.bits(),
revents: PollFlags::empty().bits(),
},
@@ -133,19 +145,15 @@ libc_bitflags! {
POLLOUT;
/// Equivalent to [`POLLIN`](constant.POLLIN.html)
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
POLLRDNORM;
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
POLLWRNORM;
/// Priority band data can be read (generally unused on Linux).
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
POLLRDBAND;
/// Priority data may be written.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
POLLWRBAND;
/// Error condition (only returned in
/// [`PollFd::revents`](struct.PollFd.html#method.revents);
@@ -184,16 +192,19 @@ libc_bitflags! {
///
/// Note that the timeout interval will be rounded up to the system clock
/// granularity, and kernel scheduling delays mean that the blocking
-/// interval may overrun by a small amount. Specifying a negative value
-/// in timeout means an infinite timeout. Specifying a timeout of zero
-/// causes `poll()` to return immediately, even if no file descriptors are
-/// ready.
-pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
+/// interval may overrun by a small amount. Specifying a [`PollTimeout::NONE`]
+/// in timeout means an infinite timeout. Specifying a timeout of
+/// [`PollTimeout::ZERO`] causes `poll()` to return immediately, even if no file
+/// descriptors are ready.
+pub fn poll<T: Into<PollTimeout>>(
+ fds: &mut [PollFd],
+ timeout: T,
+) -> Result<libc::c_int> {
let res = unsafe {
libc::poll(
- fds.as_mut_ptr() as *mut libc::pollfd,
+ fds.as_mut_ptr().cast(),
fds.len() as libc::nfds_t,
- timeout,
+ i32::from(timeout.into()),
)
};
@@ -213,7 +224,7 @@ feature! {
/// so in that case `ppoll` differs from `poll` only in the precision of the
/// timeout argument.
///
-#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, freebsdlike))]
pub fn ppoll(
fds: &mut [PollFd],
timeout: Option<crate::sys::time::TimeSpec>,
@@ -223,7 +234,7 @@ pub fn ppoll(
let timeout = timeout.as_ref().map_or(core::ptr::null(), |r| r.as_ref());
let sigmask = sigmask.as_ref().map_or(core::ptr::null(), |r| r.as_ref());
let res = unsafe {
- libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
+ libc::ppoll(fds.as_mut_ptr().cast(),
fds.len() as libc::nfds_t,
timeout,
sigmask)
diff --git a/third_party/rust/nix/src/poll_timeout.rs b/third_party/rust/nix/src/poll_timeout.rs
new file mode 100644
index 0000000000..f7d9015f56
--- /dev/null
+++ b/third_party/rust/nix/src/poll_timeout.rs
@@ -0,0 +1,224 @@
+use std::time::Duration;
+
+/// PollTimeout argument for polling.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
+pub struct PollTimeout(i32);
+
+impl PollTimeout {
+ /// Blocks indefinitely.
+ ///
+ /// > Specifying a negative value in timeout means an infinite timeout.
+ pub const NONE: Self = Self(-1);
+ /// Returns immediately.
+ ///
+ /// > Specifying a timeout of zero causes poll() to return immediately, even if no file
+ /// > descriptors are ready.
+ pub const ZERO: Self = Self(0);
+ /// Blocks for at most [`i32::MAX`] milliseconds.
+ pub const MAX: Self = Self(i32::MAX);
+ /// Returns if `self` equals [`PollTimeout::NONE`].
+ pub fn is_none(&self) -> bool {
+ // > Specifying a negative value in timeout means an infinite timeout.
+ *self <= Self::NONE
+ }
+ /// Returns if `self` does not equal [`PollTimeout::NONE`].
+ pub fn is_some(&self) -> bool {
+ !self.is_none()
+ }
+ /// Returns the timeout in milliseconds if there is some, otherwise returns `None`.
+ pub fn as_millis(&self) -> Option<u32> {
+ self.is_some().then_some(u32::try_from(self.0).unwrap())
+ }
+ /// Returns the timeout as a `Duration` if there is some, otherwise returns `None`.
+ pub fn duration(&self) -> Option<Duration> {
+ self.as_millis()
+ .map(|x| Duration::from_millis(u64::from(x)))
+ }
+}
+
+/// Error type for integer conversions into `PollTimeout`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum PollTimeoutTryFromError {
+ /// Passing a value less than -1 is invalid on some systems, see
+ /// <https://man.freebsd.org/cgi/man.cgi?poll#end>.
+ TooNegative,
+ /// Passing a value greater than `i32::MAX` is invalid.
+ TooPositive,
+}
+
+impl std::fmt::Display for PollTimeoutTryFromError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::TooNegative => write!(f, "Passed a negative timeout less than -1."),
+ Self::TooPositive => write!(f, "Passed a positive timeout greater than `i32::MAX` milliseconds.")
+ }
+ }
+}
+
+impl std::error::Error for PollTimeoutTryFromError {}
+
+impl<T: Into<PollTimeout>> From<Option<T>> for PollTimeout {
+ fn from(x: Option<T>) -> Self {
+ x.map_or(Self::NONE, |x| x.into())
+ }
+}
+impl TryFrom<Duration> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: Duration) -> std::result::Result<Self, Self::Error> {
+ Ok(Self(
+ i32::try_from(x.as_millis())
+ .map_err(|_| PollTimeoutTryFromError::TooPositive)?,
+ ))
+ }
+}
+impl TryFrom<u128> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: u128) -> std::result::Result<Self, Self::Error> {
+ Ok(Self(
+ i32::try_from(x)
+ .map_err(|_| PollTimeoutTryFromError::TooPositive)?,
+ ))
+ }
+}
+impl TryFrom<u64> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: u64) -> std::result::Result<Self, Self::Error> {
+ Ok(Self(
+ i32::try_from(x)
+ .map_err(|_| PollTimeoutTryFromError::TooPositive)?,
+ ))
+ }
+}
+impl TryFrom<u32> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: u32) -> std::result::Result<Self, Self::Error> {
+ Ok(Self(
+ i32::try_from(x)
+ .map_err(|_| PollTimeoutTryFromError::TooPositive)?,
+ ))
+ }
+}
+impl From<u16> for PollTimeout {
+ fn from(x: u16) -> Self {
+ Self(i32::from(x))
+ }
+}
+impl From<u8> for PollTimeout {
+ fn from(x: u8) -> Self {
+ Self(i32::from(x))
+ }
+}
+impl TryFrom<i128> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: i128) -> std::result::Result<Self, Self::Error> {
+ match x {
+ ..=-2 => Err(PollTimeoutTryFromError::TooNegative),
+ -1.. => Ok(Self(
+ i32::try_from(x)
+ .map_err(|_| PollTimeoutTryFromError::TooPositive)?,
+ )),
+ }
+ }
+}
+impl TryFrom<i64> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: i64) -> std::result::Result<Self, Self::Error> {
+ match x {
+ ..=-2 => Err(PollTimeoutTryFromError::TooNegative),
+ -1.. => Ok(Self(
+ i32::try_from(x)
+ .map_err(|_| PollTimeoutTryFromError::TooPositive)?,
+ )),
+ }
+ }
+}
+impl TryFrom<i32> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: i32) -> std::result::Result<Self, Self::Error> {
+ match x {
+ ..=-2 => Err(PollTimeoutTryFromError::TooNegative),
+ -1.. => Ok(Self(x)),
+ }
+ }
+}
+impl TryFrom<i16> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: i16) -> std::result::Result<Self, Self::Error> {
+ match x {
+ ..=-2 => Err(PollTimeoutTryFromError::TooNegative),
+ -1.. => Ok(Self(i32::from(x))),
+ }
+ }
+}
+impl TryFrom<i8> for PollTimeout {
+ type Error = PollTimeoutTryFromError;
+ fn try_from(x: i8) -> std::result::Result<Self, Self::Error> {
+ match x {
+ ..=-2 => Err(PollTimeoutTryFromError::TooNegative),
+ -1.. => Ok(Self(i32::from(x))),
+ }
+ }
+}
+impl TryFrom<PollTimeout> for Duration {
+ type Error = ();
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, ()> {
+ x.duration().ok_or(())
+ }
+}
+impl TryFrom<PollTimeout> for u128 {
+ type Error = <Self as TryFrom<i32>>::Error;
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, Self::Error> {
+ Self::try_from(x.0)
+ }
+}
+impl TryFrom<PollTimeout> for u64 {
+ type Error = <Self as TryFrom<i32>>::Error;
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, Self::Error> {
+ Self::try_from(x.0)
+ }
+}
+impl TryFrom<PollTimeout> for u32 {
+ type Error = <Self as TryFrom<i32>>::Error;
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, Self::Error> {
+ Self::try_from(x.0)
+ }
+}
+impl TryFrom<PollTimeout> for u16 {
+ type Error = <Self as TryFrom<i32>>::Error;
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, Self::Error> {
+ Self::try_from(x.0)
+ }
+}
+impl TryFrom<PollTimeout> for u8 {
+ type Error = <Self as TryFrom<i32>>::Error;
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, Self::Error> {
+ Self::try_from(x.0)
+ }
+}
+impl From<PollTimeout> for i128 {
+ fn from(x: PollTimeout) -> Self {
+ Self::from(x.0)
+ }
+}
+impl From<PollTimeout> for i64 {
+ fn from(x: PollTimeout) -> Self {
+ Self::from(x.0)
+ }
+}
+impl From<PollTimeout> for i32 {
+ fn from(x: PollTimeout) -> Self {
+ x.0
+ }
+}
+impl TryFrom<PollTimeout> for i16 {
+ type Error = <Self as TryFrom<i32>>::Error;
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, Self::Error> {
+ Self::try_from(x.0)
+ }
+}
+impl TryFrom<PollTimeout> for i8 {
+ type Error = <Self as TryFrom<i32>>::Error;
+ fn try_from(x: PollTimeout) -> std::result::Result<Self, Self::Error> {
+ Self::try_from(x.0)
+ }
+}
diff --git a/third_party/rust/nix/src/pty.rs b/third_party/rust/nix/src/pty.rs
index 455828b703..74f8ecf0df 100644
--- a/third_party/rust/nix/src/pty.rs
+++ b/third_party/rust/nix/src/pty.rs
@@ -71,7 +71,7 @@ impl io::Read for PtyMaster {
impl io::Write for PtyMaster {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from)
+ unistd::write(&self.0, buf).map_err(io::Error::from)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
@@ -86,7 +86,7 @@ impl io::Read for &PtyMaster {
impl io::Write for &PtyMaster {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from)
+ unistd::write(&self.0, buf).map_err(io::Error::from)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
@@ -169,12 +169,12 @@ pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`.
#[inline]
pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
- let name_ptr = libc::ptsname(fd.as_raw_fd());
+ let name_ptr = unsafe { libc::ptsname(fd.as_raw_fd()) };
if name_ptr.is_null() {
return Err(Errno::last());
}
- let name = CStr::from_ptr(name_ptr);
+ let name = unsafe { CStr::from_ptr(name_ptr) };
Ok(name.to_string_lossy().into_owned())
}
@@ -187,8 +187,7 @@ pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
///
/// This value is useful for opening the slave ptty once the master has already been opened with
/// `posix_openpt()`.
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(linux_android)]
#[inline]
pub fn ptsname_r(fd: &PtyMaster) -> Result<String> {
let mut name_buf = Vec::<libc::c_char>::with_capacity(64);
@@ -342,7 +341,7 @@ pub unsafe fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b T
.map(|ws| ws as *const Winsize as *mut _)
.unwrap_or(ptr::null_mut());
- let res = libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win);
+ let res = unsafe { libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win) };
let fork_result = Errno::result(res).map(|res| match res {
0 => ForkResult::Child,
@@ -350,7 +349,7 @@ pub unsafe fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b T
})?;
Ok(ForkptyResult {
- master: OwnedFd::from_raw_fd(master.assume_init()),
+ master: unsafe { OwnedFd::from_raw_fd( master.assume_init() ) },
fork_result,
})
}
diff --git a/third_party/rust/nix/src/sched.rs b/third_party/rust/nix/src/sched.rs
index c9d5d6d8a1..d76d5581d1 100644
--- a/third_party/rust/nix/src/sched.rs
+++ b/third_party/rust/nix/src/sched.rs
@@ -4,11 +4,10 @@
//! [sched.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html)
use crate::{Errno, Result};
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
pub use self::sched_linux_like::*;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(linux_android)]
mod sched_linux_like {
use crate::errno::Errno;
use crate::unistd::Pid;
@@ -117,17 +116,19 @@ mod sched_linux_like {
}
let combined = flags.bits() | signal.unwrap_or(0);
- let ptr = stack.as_mut_ptr().add(stack.len());
- let ptr_aligned = ptr.sub(ptr as usize % 16);
- let res = libc::clone(
- mem::transmute(
- callback
- as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
- ),
- ptr_aligned as *mut c_void,
- combined,
- &mut cb as *mut _ as *mut c_void,
- );
+ let res = unsafe {
+ let ptr = stack.as_mut_ptr().add(stack.len());
+ let ptr_aligned = ptr.sub(ptr as usize % 16);
+ libc::clone(
+ mem::transmute(
+ callback
+ as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
+ ),
+ ptr_aligned as *mut c_void,
+ combined,
+ &mut cb as *mut _ as *mut c_void,
+ )
+ };
Errno::result(res).map(Pid::from_raw)
}
@@ -151,20 +152,10 @@ mod sched_linux_like {
}
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"
-))]
+#[cfg(any(linux_android, freebsdlike))]
pub use self::sched_affinity::*;
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"
-))]
+#[cfg(any(linux_android, freebsdlike))]
mod sched_affinity {
use crate::errno::Errno;
use crate::unistd::Pid;
diff --git a/third_party/rust/nix/src/sys/aio.rs b/third_party/rust/nix/src/sys/aio.rs
index 5471177e3e..e9213c6434 100644
--- a/third_party/rust/nix/src/sys/aio.rs
+++ b/third_party/rust/nix/src/sys/aio.rs
@@ -35,7 +35,7 @@ use std::{
ptr, thread,
};
-use libc::{c_void, off_t};
+use libc::off_t;
use pin_utils::unsafe_pinned;
use crate::{
@@ -53,12 +53,9 @@ libc_enum! {
/// do it like `fsync`
O_SYNC,
/// on supported operating systems only, do it like `fdatasync`
- #[cfg(any(target_os = "ios",
+ #[cfg(any(apple_targets,
target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ netbsdlike))]
O_DSYNC
}
impl TryFrom<i32>
@@ -161,7 +158,7 @@ impl AioCb {
let r = unsafe { libc::aio_error(&self.aiocb().0) };
match r {
0 => Ok(()),
- num if num > 0 => Err(Errno::from_i32(num)),
+ num if num > 0 => Err(Errno::from_raw(num)),
-1 => Err(Errno::last()),
num => panic!("unknown aio_error return value {num:?}"),
}
@@ -581,7 +578,7 @@ impl<'a> AioRead<'a> {
) -> Self {
let mut aiocb = AioCb::common_init(fd, prio, sigev_notify);
aiocb.aiocb.0.aio_nbytes = buf.len();
- aiocb.aiocb.0.aio_buf = buf.as_mut_ptr() as *mut c_void;
+ aiocb.aiocb.0.aio_buf = buf.as_mut_ptr().cast();
aiocb.aiocb.0.aio_lio_opcode = libc::LIO_READ;
aiocb.aiocb.0.aio_offset = offs;
AioRead {
@@ -702,7 +699,7 @@ impl<'a> AioReadv<'a> {
// In vectored mode, aio_nbytes stores the length of the iovec array,
// not the byte count.
aiocb.aiocb.0.aio_nbytes = bufs.len();
- aiocb.aiocb.0.aio_buf = bufs.as_mut_ptr() as *mut c_void;
+ aiocb.aiocb.0.aio_buf = bufs.as_mut_ptr().cast();
aiocb.aiocb.0.aio_lio_opcode = libc::LIO_READV;
aiocb.aiocb.0.aio_offset = offs;
AioReadv {
@@ -817,7 +814,7 @@ impl<'a> AioWrite<'a> {
// but technically its only unsafe to dereference it, not to create
// it. Type Safety guarantees that we'll never pass aiocb to
// aio_read or aio_readv.
- aiocb.aiocb.0.aio_buf = buf.as_ptr() as *mut c_void;
+ aiocb.aiocb.0.aio_buf = buf.as_ptr().cast_mut().cast();
aiocb.aiocb.0.aio_lio_opcode = libc::LIO_WRITE;
aiocb.aiocb.0.aio_offset = offs;
AioWrite {
@@ -935,7 +932,7 @@ impl<'a> AioWritev<'a> {
// but technically its only unsafe to dereference it, not to create
// it. Type Safety guarantees that we'll never pass aiocb to
// aio_read or aio_readv.
- aiocb.aiocb.0.aio_buf = bufs.as_ptr() as *mut c_void;
+ aiocb.aiocb.0.aio_buf = bufs.as_ptr().cast_mut().cast();
aiocb.aiocb.0.aio_lio_opcode = libc::LIO_WRITEV;
aiocb.aiocb.0.aio_offset = offs;
AioWritev {
@@ -1055,7 +1052,8 @@ pub fn aio_suspend(
// generic, and accepting arguments like &[AioWrite]. But that would
// prevent using aio_suspend to wait on a heterogeneous list of mixed
// operations.
- let v = list.iter()
+ let v = list
+ .iter()
.map(|x| x.as_ref() as *const libc::aiocb)
.collect::<Vec<*const libc::aiocb>>();
let p = v.as_ptr();
@@ -1175,7 +1173,10 @@ pub fn aio_suspend(
/// // notification, we know that all operations are complete.
/// assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
/// ```
-#[deprecated(since = "0.27.0", note = "https://github.com/nix-rust/nix/issues/2017")]
+#[deprecated(
+ since = "0.27.0",
+ note = "https://github.com/nix-rust/nix/issues/2017"
+)]
pub fn lio_listio(
mode: LioMode,
list: &mut [Pin<&mut dyn AsMut<libc::aiocb>>],
@@ -1190,56 +1191,3 @@ pub fn lio_listio(
})
.map(drop)
}
-
-#[cfg(test)]
-mod t {
- use super::*;
-
- /// aio_suspend relies on casting Rust Aio* struct pointers to libc::aiocb
- /// pointers. This test ensures that such casts are valid.
- #[test]
- fn casting() {
- let sev = SigevNotify::SigevNone;
- let aiof = AioFsync::new(666, AioFsyncMode::O_SYNC, 0, sev);
- assert_eq!(
- aiof.as_ref() as *const libc::aiocb,
- &aiof as *const AioFsync as *const libc::aiocb
- );
-
- let mut rbuf = [];
- let aior = AioRead::new(666, 0, &mut rbuf, 0, sev);
- assert_eq!(
- aior.as_ref() as *const libc::aiocb,
- &aior as *const AioRead as *const libc::aiocb
- );
-
- let wbuf = [];
- let aiow = AioWrite::new(666, 0, &wbuf, 0, sev);
- assert_eq!(
- aiow.as_ref() as *const libc::aiocb,
- &aiow as *const AioWrite as *const libc::aiocb
- );
- }
-
- #[cfg(target_os = "freebsd")]
- #[test]
- fn casting_vectored() {
- let sev = SigevNotify::SigevNone;
-
- let mut rbuf = [];
- let mut rbufs = [IoSliceMut::new(&mut rbuf)];
- let aiorv = AioReadv::new(666, 0, &mut rbufs[..], 0, sev);
- assert_eq!(
- aiorv.as_ref() as *const libc::aiocb,
- &aiorv as *const AioReadv as *const libc::aiocb
- );
-
- let wbuf = [];
- let wbufs = [IoSlice::new(&wbuf)];
- let aiowv = AioWritev::new(666, 0, &wbufs, 0, sev);
- assert_eq!(
- aiowv.as_ref() as *const libc::aiocb,
- &aiowv as *const AioWritev as *const libc::aiocb
- );
- }
-}
diff --git a/third_party/rust/nix/src/sys/epoll.rs b/third_party/rust/nix/src/sys/epoll.rs
index 36f9c17d0e..ec146a8c53 100644
--- a/third_party/rust/nix/src/sys/epoll.rs
+++ b/third_party/rust/nix/src/sys/epoll.rs
@@ -1,4 +1,5 @@
use crate::errno::Errno;
+pub use crate::poll_timeout::PollTimeout as EpollTimeout;
use crate::Result;
use libc::{self, c_int};
use std::mem;
@@ -71,32 +72,32 @@ impl EpollEvent {
/// A safe wrapper around [`epoll`](https://man7.org/linux/man-pages/man7/epoll.7.html).
/// ```
-/// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}};
+/// # use nix::sys::{epoll::{EpollTimeout, Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{EventFd, EfdFlags}};
/// # use nix::unistd::write;
-/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd};
+/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsFd};
/// # use std::time::{Instant, Duration};
/// # fn main() -> nix::Result<()> {
/// const DATA: u64 = 17;
-/// const MILLIS: u64 = 100;
+/// const MILLIS: u8 = 100;
///
/// // Create epoll
/// let epoll = Epoll::new(EpollCreateFlags::empty())?;
///
/// // Create eventfd & Add event
-/// let eventfd = eventfd(0, EfdFlags::empty())?;
+/// let eventfd = EventFd::new()?;
/// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
///
/// // Arm eventfd & Time wait
-/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?;
+/// eventfd.arm()?;
/// let now = Instant::now();
///
/// // Wait on event
/// let mut events = [EpollEvent::empty()];
-/// epoll.wait(&mut events, MILLIS as isize)?;
+/// epoll.wait(&mut events, MILLIS)?;
///
/// // Assert data correct & timeout didn't occur
/// assert_eq!(events[0].data(), DATA);
-/// assert!(now.elapsed() < Duration::from_millis(MILLIS));
+/// assert!(now.elapsed().as_millis() < MILLIS.into());
/// # Ok(())
/// # }
/// ```
@@ -140,17 +141,17 @@ impl Epoll {
/// (This can be thought of as fetching items from the ready list of the epoll instance.)
///
/// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html)
- pub fn wait(
+ pub fn wait<T: Into<EpollTimeout>>(
&self,
events: &mut [EpollEvent],
- timeout: isize,
+ timeout: T,
) -> Result<usize> {
let res = unsafe {
libc::epoll_wait(
self.0.as_raw_fd(),
- events.as_mut_ptr() as *mut libc::epoll_event,
+ events.as_mut_ptr().cast(),
events.len() as c_int,
- timeout as c_int,
+ timeout.into().into(),
)
};
@@ -240,7 +241,7 @@ pub fn epoll_wait(
let res = unsafe {
libc::epoll_wait(
epfd,
- events.as_mut_ptr() as *mut libc::epoll_event,
+ events.as_mut_ptr().cast(),
events.len() as c_int,
timeout_ms as c_int,
)
diff --git a/third_party/rust/nix/src/sys/event.rs b/third_party/rust/nix/src/sys/event.rs
index ec7f7e277a..b294d27c70 100644
--- a/third_party/rust/nix/src/sys/event.rs
+++ b/third_party/rust/nix/src/sys/event.rs
@@ -10,6 +10,7 @@ use libc::{c_int, c_long, intptr_t, time_t, timespec, uintptr_t};
use libc::{c_long, intptr_t, size_t, time_t, timespec, uintptr_t};
use std::convert::TryInto;
use std::mem;
+use std::os::fd::{AsFd, BorrowedFd};
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
use std::ptr;
@@ -29,6 +30,18 @@ pub struct KEvent {
#[derive(Debug)]
pub struct Kqueue(OwnedFd);
+impl AsFd for Kqueue {
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.0.as_fd()
+ }
+}
+
+impl From<Kqueue> for OwnedFd {
+ fn from(value: Kqueue) -> Self {
+ value.0
+ }
+}
+
impl Kqueue {
/// Create a new kernel event queue.
pub fn new() -> Result<Self> {
@@ -63,9 +76,9 @@ impl Kqueue {
let res = unsafe {
libc::kevent(
self.0.as_raw_fd(),
- changelist.as_ptr() as *const libc::kevent,
+ changelist.as_ptr().cast(),
changelist.len() as type_of_nchanges,
- eventlist.as_mut_ptr() as *mut libc::kevent,
+ eventlist.as_mut_ptr().cast(),
eventlist.len() as type_of_nchanges,
if let Some(ref timeout) = timeout_opt {
timeout as *const timespec
@@ -78,13 +91,7 @@ impl Kqueue {
}
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "openbsd"
-))]
+#[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))]
type type_of_udata = *mut libc::c_void;
#[cfg(target_os = "netbsd")]
type type_of_udata = intptr_t;
@@ -109,10 +116,7 @@ libc_enum! {
/// Takes a descriptor as the identifier, and returns whenever one of
/// the specified exceptional conditions has occurred on the descriptor.
EVFILT_EXCEPT,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))]
+ #[cfg(any(freebsdlike, apple_targets))]
/// Establishes a file system monitor.
EVFILT_FS,
#[cfg(target_os = "freebsd")]
@@ -120,7 +124,7 @@ libc_enum! {
/// # See Also
/// [lio_listio(2)](https://www.freebsd.org/cgi/man.cgi?query=lio_listio)
EVFILT_LIO,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
/// Mach portsets
EVFILT_MACHPORT,
/// Notifies when a process performs one or more of the requested
@@ -144,13 +148,10 @@ libc_enum! {
EVFILT_SIGNAL,
/// Establishes a timer and notifies when the timer expires.
EVFILT_TIMER,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))]
+ #[cfg(any(freebsdlike, apple_targets))]
/// Notifies only when explicitly requested by the user.
EVFILT_USER,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
/// Virtual memory events
EVFILT_VM,
/// Notifies when a requested event happens on a specified file.
@@ -162,13 +163,7 @@ libc_enum! {
impl TryFrom<type_of_event_filter>
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "openbsd"
-))]
+#[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))]
#[doc(hidden)]
pub type type_of_event_flag = u16;
#[cfg(target_os = "netbsd")]
@@ -187,9 +182,7 @@ libc_bitflags! {
EV_DELETE;
#[allow(missing_docs)]
EV_DISABLE;
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
+ #[cfg(bsd)]
#[allow(missing_docs)]
EV_DISPATCH;
#[cfg(target_os = "freebsd")]
@@ -201,7 +194,7 @@ libc_bitflags! {
EV_EOF;
#[allow(missing_docs)]
EV_ERROR;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
EV_FLAG0;
#[allow(missing_docs)]
@@ -211,15 +204,13 @@ libc_bitflags! {
EV_NODATA;
#[allow(missing_docs)]
EV_ONESHOT;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
EV_OOBAND;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
EV_POLL;
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
+ #[cfg(bsd)]
#[allow(missing_docs)]
EV_RECEIPT;
}
@@ -231,7 +222,7 @@ libc_bitflags!(
// that wouldn't simply be repeating the man page.
#[allow(missing_docs)]
pub struct FilterFlag: u32 {
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_ABSOLUTE;
#[allow(missing_docs)]
@@ -247,45 +238,27 @@ libc_bitflags!(
NOTE_EXEC;
#[allow(missing_docs)]
NOTE_EXIT;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_EXITSTATUS;
#[allow(missing_docs)]
NOTE_EXTEND;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
+ #[cfg(any(apple_targets, freebsdlike))]
#[allow(missing_docs)]
NOTE_FFAND;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
+ #[cfg(any(apple_targets, freebsdlike))]
#[allow(missing_docs)]
NOTE_FFCOPY;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
+ #[cfg(any(apple_targets, freebsdlike))]
#[allow(missing_docs)]
NOTE_FFCTRLMASK;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
+ #[cfg(any(apple_targets, freebsdlike))]
#[allow(missing_docs)]
NOTE_FFLAGSMASK;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
+ #[cfg(any(apple_targets, freebsdlike))]
#[allow(missing_docs)]
NOTE_FFNOP;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
+ #[cfg(any(apple_targets, freebsdlike))]
#[allow(missing_docs)]
NOTE_FFOR;
#[allow(missing_docs)]
@@ -297,10 +270,12 @@ libc_bitflags!(
#[cfg(target_os = "freebsd")]
#[allow(missing_docs)]
NOTE_MSECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_NONE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
+ #[cfg(any(
+ apple_targets,
+ target_os = "freebsd"))]
#[allow(missing_docs)]
NOTE_NSECONDS;
#[cfg(target_os = "dragonfly")]
@@ -314,38 +289,39 @@ libc_bitflags!(
NOTE_RENAME;
#[allow(missing_docs)]
NOTE_REVOKE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
+ #[cfg(any(
+ apple_targets,
+ target_os = "freebsd"))]
#[allow(missing_docs)]
NOTE_SECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_SIGNAL;
#[allow(missing_docs)]
NOTE_TRACK;
#[allow(missing_docs)]
NOTE_TRACKERR;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
+ #[cfg(any(apple_targets, freebsdlike))]
#[allow(missing_docs)]
NOTE_TRIGGER;
#[cfg(target_os = "openbsd")]
#[allow(missing_docs)]
NOTE_TRUNCATE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
+ #[cfg(any(
+ apple_targets,
+ target_os = "freebsd"))]
#[allow(missing_docs)]
NOTE_USECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_VM_ERROR;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_VM_PRESSURE;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_VM_PRESSURE_SUDDEN_TERMINATE;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
NOTE_VM_PRESSURE_TERMINATE;
#[allow(missing_docs)]
@@ -443,13 +419,7 @@ pub fn kevent(
kq.kevent(changelist, eventlist, Some(timeout))
}
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "openbsd"
-))]
+#[cfg(any(apple_targets, freebsdlike, target_os = "openbsd"))]
type type_of_nchanges = c_int;
#[cfg(target_os = "netbsd")]
type type_of_nchanges = size_t;
@@ -484,42 +454,3 @@ pub fn ev_set(
ev.kevent.data = 0;
ev.kevent.udata = udata as type_of_udata;
}
-
-#[test]
-fn test_struct_kevent() {
- use std::mem;
-
- let udata: intptr_t = 12345;
-
- let actual = KEvent::new(
- 0xdead_beef,
- EventFilter::EVFILT_READ,
- EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
- FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
- 0x1337,
- udata,
- );
- assert_eq!(0xdead_beef, actual.ident());
- let filter = actual.kevent.filter;
- assert_eq!(libc::EVFILT_READ, filter);
- assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
- assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
- assert_eq!(0x1337, actual.data());
- assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
- assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
-}
-
-#[test]
-fn test_kevent_filter() {
- let udata: intptr_t = 12345;
-
- let actual = KEvent::new(
- 0xdead_beef,
- EventFilter::EVFILT_READ,
- EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
- FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
- 0x1337,
- udata,
- );
- assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
-}
diff --git a/third_party/rust/nix/src/sys/eventfd.rs b/third_party/rust/nix/src/sys/eventfd.rs
index f1723519cf..50a4f091bd 100644
--- a/third_party/rust/nix/src/sys/eventfd.rs
+++ b/third_party/rust/nix/src/sys/eventfd.rs
@@ -1,17 +1,84 @@
use crate::errno::Errno;
-use crate::Result;
-use std::os::unix::io::{FromRawFd, OwnedFd};
+use crate::{Result,unistd};
+use std::os::unix::io::{FromRawFd, OwnedFd, AsRawFd, AsFd, RawFd, BorrowedFd};
libc_bitflags! {
pub struct EfdFlags: libc::c_int {
- EFD_CLOEXEC; // Since Linux 2.6.27
- EFD_NONBLOCK; // Since Linux 2.6.27
- EFD_SEMAPHORE; // Since Linux 2.6.30
+ EFD_CLOEXEC; // Since Linux 2.6.27/FreeBSD 13.0
+ EFD_NONBLOCK; // Since Linux 2.6.27/FreeBSD 13.0
+ EFD_SEMAPHORE; // Since Linux 2.6.30/FreeBSD 13.0
}
}
+#[deprecated(since = "0.28.0", note = "Use EventFd::from_value_and_flags() instead")]
pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> {
let res = unsafe { libc::eventfd(initval, flags.bits()) };
Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) })
}
+
+#[derive(Debug)]
+#[repr(transparent)]
+pub struct EventFd(OwnedFd);
+impl EventFd {
+ /// [`EventFd::from_value_and_flags`] with `init_val = 0` and `flags = EfdFlags::empty()`.
+ pub fn new() -> Result<Self> {
+ Self::from_value_and_flags(0, EfdFlags::empty())
+ }
+ /// Constructs [`EventFd`] with the given `init_val` and `flags`.
+ ///
+ /// Wrapper around [`libc::eventfd`].
+ pub fn from_value_and_flags(init_val: u32, flags: EfdFlags) -> Result<Self> {
+ let res = unsafe { libc::eventfd(init_val, flags.bits()) };
+ Errno::result(res).map(|r| Self(unsafe { OwnedFd::from_raw_fd(r) }))
+ }
+ /// [`EventFd::from_value_and_flags`] with `init_val = 0` and given `flags`.
+ pub fn from_flags(flags: EfdFlags) -> Result<Self> {
+ Self::from_value_and_flags(0, flags)
+ }
+ /// [`EventFd::from_value_and_flags`] with given `init_val` and `flags = EfdFlags::empty()`.
+ pub fn from_value(init_val: u32) -> Result<Self> {
+ Self::from_value_and_flags(init_val, EfdFlags::empty())
+ }
+ /// Arms `self`, a following call to `poll`, `select` or `epoll` will return immediately.
+ ///
+ /// [`EventFd::write`] with `1`.
+ pub fn arm(&self) -> Result<usize> {
+ self.write(1)
+ }
+ /// Defuses `self`, a following call to `poll`, `select` or `epoll` will block.
+ ///
+ /// [`EventFd::write`] with `0`.
+ pub fn defuse(&self) -> Result<usize> {
+ self.write(0)
+ }
+ /// Enqueues `value` triggers.
+ ///
+ /// The next `value` calls to `poll`, `select` or `epoll` will return immediately.
+ ///
+ /// [`EventFd::write`] with `value`.
+ pub fn write(&self, value: u64) -> Result<usize> {
+ unistd::write(&self.0,&value.to_ne_bytes())
+ }
+ // Reads the value from the file descriptor.
+ pub fn read(&self) -> Result<u64> {
+ let mut arr = [0; std::mem::size_of::<u64>()];
+ unistd::read(self.0.as_raw_fd(),&mut arr)?;
+ Ok(u64::from_ne_bytes(arr))
+ }
+}
+impl AsFd for EventFd {
+ fn as_fd(&self) -> BorrowedFd {
+ self.0.as_fd()
+ }
+}
+impl AsRawFd for EventFd {
+ fn as_raw_fd(&self) -> RawFd {
+ self.0.as_raw_fd()
+ }
+}
+impl From<EventFd> for OwnedFd {
+ fn from(x: EventFd) -> OwnedFd {
+ x.0
+ }
+}
diff --git a/third_party/rust/nix/src/sys/fanotify.rs b/third_party/rust/nix/src/sys/fanotify.rs
new file mode 100644
index 0000000000..e217406e02
--- /dev/null
+++ b/third_party/rust/nix/src/sys/fanotify.rs
@@ -0,0 +1,416 @@
+//! Monitoring API for filesystem events.
+//!
+//! Fanotify is a Linux-only API to monitor filesystems events.
+//!
+//! Additional capabilities compared to the `inotify` API include the ability to
+//! monitor all of the objects in a mounted filesystem, the ability to make
+//! access permission decisions, and the possibility to read or modify files
+//! before access by other applications.
+//!
+//! For more documentation, please read
+//! [fanotify(7)](https://man7.org/linux/man-pages/man7/fanotify.7.html).
+
+use crate::errno::Errno;
+use crate::fcntl::{at_rawfd, OFlag};
+use crate::unistd::{close, read, write};
+use crate::{NixPath, Result};
+use std::marker::PhantomData;
+use std::mem::{size_of, MaybeUninit};
+use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
+use std::ptr;
+
+libc_bitflags! {
+ /// Mask for defining which events shall be listened with
+ /// [`fanotify_mark`](fn.fanotify_mark.html) and for querying notifications.
+ pub struct MaskFlags: u64 {
+ /// File was accessed.
+ FAN_ACCESS;
+ /// File was modified.
+ FAN_MODIFY;
+ /// Metadata has changed. Since Linux 5.1.
+ FAN_ATTRIB;
+ /// Writtable file was closed.
+ FAN_CLOSE_WRITE;
+ /// Unwrittable file was closed.
+ FAN_CLOSE_NOWRITE;
+ /// File was opened.
+ FAN_OPEN;
+ /// File was moved from X. Since Linux 5.1.
+ FAN_MOVED_FROM;
+ /// File was moved to Y. Since Linux 5.1.
+ FAN_MOVED_TO;
+ /// Subfile was created. Since Linux 5.1.
+ FAN_CREATE;
+ /// Subfile was deleted. Since Linux 5.1.
+ FAN_DELETE;
+ /// Self was deleted. Since Linux 5.1.
+ FAN_DELETE_SELF;
+ /// Self was moved. Since Linux 5.1.
+ FAN_MOVE_SELF;
+ /// File was opened for execution. Since Linux 5.0.
+ FAN_OPEN_EXEC;
+
+ /// Event queue overflowed.
+ FAN_Q_OVERFLOW;
+ /// Filesystem error. Since Linux 5.16.
+ FAN_FS_ERROR;
+
+ /// Permission to open file was requested.
+ FAN_OPEN_PERM;
+ /// Permission to access file was requested.
+ FAN_ACCESS_PERM;
+ /// Permission to open file for execution was requested. Since Linux
+ /// 5.0.
+ FAN_OPEN_EXEC_PERM;
+
+ /// Interested in child events.
+ FAN_EVENT_ON_CHILD;
+
+ /// File was renamed. Since Linux 5.17.
+ FAN_RENAME;
+
+ /// Event occurred against dir.
+ FAN_ONDIR;
+
+ /// Combination of `FAN_CLOSE_WRITE` and `FAN_CLOSE_NOWRITE`.
+ FAN_CLOSE;
+ /// Combination of `FAN_MOVED_FROM` and `FAN_MOVED_TO`.
+ FAN_MOVE;
+ }
+}
+
+libc_bitflags! {
+ /// Configuration options for [`fanotify_init`](fn.fanotify_init.html).
+ pub struct InitFlags: libc::c_uint {
+ /// Close-on-exec flag set on the file descriptor.
+ FAN_CLOEXEC;
+ /// Nonblocking flag set on the file descriptor.
+ FAN_NONBLOCK;
+
+ /// Receipt of events notifications.
+ FAN_CLASS_NOTIF;
+ /// Receipt of events for permission decisions, after they contain final
+ /// data.
+ FAN_CLASS_CONTENT;
+ /// Receipt of events for permission decisions, before they contain
+ /// final data.
+ FAN_CLASS_PRE_CONTENT;
+
+ /// Remove the limit of 16384 events for the event queue.
+ FAN_UNLIMITED_QUEUE;
+ /// Remove the limit of 8192 marks.
+ FAN_UNLIMITED_MARKS;
+
+ /// Make `FanotifyEvent::pid` return pidfd. Since Linux 5.15.
+ FAN_REPORT_PIDFD;
+ /// Make `FanotifyEvent::pid` return thread id. Since Linux 4.20.
+ FAN_REPORT_TID;
+ }
+}
+
+libc_bitflags! {
+ /// File status flags for fanotify events file descriptors.
+ pub struct EventFFlags: libc::c_uint {
+ /// Read only access.
+ O_RDONLY as libc::c_uint;
+ /// Write only access.
+ O_WRONLY as libc::c_uint;
+ /// Read and write access.
+ O_RDWR as libc::c_uint;
+ /// Support for files exceeded 2 GB.
+ O_LARGEFILE as libc::c_uint;
+ /// Close-on-exec flag for the file descriptor. Since Linux 3.18.
+ O_CLOEXEC as libc::c_uint;
+ /// Append mode for the file descriptor.
+ O_APPEND as libc::c_uint;
+ /// Synchronized I/O data integrity completion.
+ O_DSYNC as libc::c_uint;
+ /// No file last access time update.
+ O_NOATIME as libc::c_uint;
+ /// Nonblocking mode for the file descriptor.
+ O_NONBLOCK as libc::c_uint;
+ /// Synchronized I/O file integrity completion.
+ O_SYNC as libc::c_uint;
+ }
+}
+
+impl TryFrom<OFlag> for EventFFlags {
+ type Error = Errno;
+
+ fn try_from(o_flag: OFlag) -> Result<Self> {
+ EventFFlags::from_bits(o_flag.bits() as u32).ok_or(Errno::EINVAL)
+ }
+}
+
+impl From<EventFFlags> for OFlag {
+ fn from(event_f_flags: EventFFlags) -> Self {
+ OFlag::from_bits_retain(event_f_flags.bits() as i32)
+ }
+}
+
+libc_bitflags! {
+ /// Configuration options for [`fanotify_mark`](fn.fanotify_mark.html).
+ pub struct MarkFlags: libc::c_uint {
+ /// Add the events to the marks.
+ FAN_MARK_ADD;
+ /// Remove the events to the marks.
+ FAN_MARK_REMOVE;
+ /// Don't follow symlinks, mark them.
+ FAN_MARK_DONT_FOLLOW;
+ /// Raise an error if filesystem to be marked is not a directory.
+ FAN_MARK_ONLYDIR;
+ /// Events added to or removed from the marks.
+ FAN_MARK_IGNORED_MASK;
+ /// Ignore mask shall survive modify events.
+ FAN_MARK_IGNORED_SURV_MODIFY;
+ /// Remove all marks.
+ FAN_MARK_FLUSH;
+ /// Do not pin inode object in the inode cache. Since Linux 5.19.
+ FAN_MARK_EVICTABLE;
+ /// Events added to or removed from the marks. Since Linux 6.0.
+ FAN_MARK_IGNORE;
+
+ /// Default flag.
+ FAN_MARK_INODE;
+ /// Mark the mount specified by pathname.
+ FAN_MARK_MOUNT;
+ /// Mark the filesystem specified by pathname. Since Linux 4.20.
+ FAN_MARK_FILESYSTEM;
+
+ /// Combination of `FAN_MARK_IGNORE` and `FAN_MARK_IGNORED_SURV_MODIFY`.
+ FAN_MARK_IGNORE_SURV;
+ }
+}
+
+/// Compile version number of fanotify API.
+pub const FANOTIFY_METADATA_VERSION: u8 = libc::FANOTIFY_METADATA_VERSION;
+
+/// Abstract over `libc::fanotify_event_metadata`, which represents an event
+/// received via `Fanotify::read_events`.
+// Is not Clone due to fd field, to avoid use-after-close scenarios.
+#[derive(Debug, Eq, Hash, PartialEq)]
+#[repr(transparent)]
+#[allow(missing_copy_implementations)]
+pub struct FanotifyEvent(libc::fanotify_event_metadata);
+
+impl FanotifyEvent {
+ /// Version number for the structure. It must be compared to
+ /// `FANOTIFY_METADATA_VERSION` to verify compile version and runtime
+ /// version does match. It can be done with the
+ /// `FanotifyEvent::check_version` method.
+ pub fn version(&self) -> u8 {
+ self.0.vers
+ }
+
+ /// Checks that compile fanotify API version is equal to the version of the
+ /// event.
+ pub fn check_version(&self) -> bool {
+ self.version() == FANOTIFY_METADATA_VERSION
+ }
+
+ /// Mask flags of the events.
+ pub fn mask(&self) -> MaskFlags {
+ MaskFlags::from_bits_truncate(self.0.mask)
+ }
+
+ /// The file descriptor of the event. If the value is `None` when reading
+ /// from the fanotify group, this event is to notify that a group queue
+ /// overflow occured.
+ pub fn fd(&self) -> Option<BorrowedFd> {
+ if self.0.fd == libc::FAN_NOFD {
+ None
+ } else {
+ // SAFETY: self.0.fd will be opened for the lifetime of `Self`,
+ // which is longer than the lifetime of the returned BorrowedFd, so
+ // it is safe.
+ Some(unsafe { BorrowedFd::borrow_raw(self.0.fd) })
+ }
+ }
+
+ /// PID of the process that caused the event. TID in case flag
+ /// `FAN_REPORT_TID` was set at group initialization.
+ pub fn pid(&self) -> i32 {
+ self.0.pid
+ }
+}
+
+impl Drop for FanotifyEvent {
+ fn drop(&mut self) {
+ let e = close(self.0.fd);
+ if !std::thread::panicking() && e == Err(Errno::EBADF) {
+ panic!("Closing an invalid file descriptor!");
+ };
+ }
+}
+
+/// Abstraction over the structure to be sent to allow or deny a given event.
+#[derive(Debug)]
+#[repr(transparent)]
+pub struct FanotifyResponse<'a> {
+ inner: libc::fanotify_response,
+ _borrowed_fd: PhantomData<BorrowedFd<'a>>,
+}
+
+impl<'a> FanotifyResponse<'a> {
+ /// Create a new response.
+ pub fn new(fd: BorrowedFd<'a>, response: Response) -> Self {
+ Self {
+ inner: libc::fanotify_response {
+ fd: fd.as_raw_fd(),
+ response: response.bits(),
+ },
+ _borrowed_fd: PhantomData,
+ }
+ }
+}
+
+libc_bitflags! {
+ /// Response to be wrapped in `FanotifyResponse` and sent to the `Fanotify`
+ /// group to allow or deny an event.
+ pub struct Response: u32 {
+ /// Allow the event.
+ FAN_ALLOW;
+ /// Deny the event.
+ FAN_DENY;
+ }
+}
+
+/// A fanotify group. This is also a file descriptor that can feed to other
+/// interfaces consuming file descriptors.
+#[derive(Debug)]
+pub struct Fanotify {
+ fd: OwnedFd,
+}
+
+impl Fanotify {
+ /// Initialize a new fanotify group.
+ ///
+ /// Returns a Result containing a Fanotify instance.
+ ///
+ /// For more information, see [fanotify_init(2)](https://man7.org/linux/man-pages/man7/fanotify_init.2.html).
+ pub fn init(
+ flags: InitFlags,
+ event_f_flags: EventFFlags,
+ ) -> Result<Fanotify> {
+ let res = Errno::result(unsafe {
+ libc::fanotify_init(flags.bits(), event_f_flags.bits())
+ });
+ res.map(|fd| Fanotify {
+ fd: unsafe { OwnedFd::from_raw_fd(fd) },
+ })
+ }
+
+ /// Add, remove, or modify an fanotify mark on a filesystem object.
+ /// If `dirfd` is `None`, `AT_FDCWD` is used.
+ ///
+ /// Returns a Result containing either `()` on success or errno otherwise.
+ ///
+ /// For more information, see [fanotify_mark(2)](https://man7.org/linux/man-pages/man7/fanotify_mark.2.html).
+ pub fn mark<P: ?Sized + NixPath>(
+ &self,
+ flags: MarkFlags,
+ mask: MaskFlags,
+ dirfd: Option<RawFd>,
+ path: Option<&P>,
+ ) -> Result<()> {
+ fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
+ where
+ P: ?Sized + NixPath,
+ F: FnOnce(*const libc::c_char) -> T,
+ {
+ match p {
+ Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
+ None => Ok(f(std::ptr::null())),
+ }
+ }
+
+ let res = with_opt_nix_path(path, |p| unsafe {
+ libc::fanotify_mark(
+ self.fd.as_raw_fd(),
+ flags.bits(),
+ mask.bits(),
+ at_rawfd(dirfd),
+ p,
+ )
+ })?;
+
+ Errno::result(res).map(|_| ())
+ }
+
+ /// Read incoming events from the fanotify group.
+ ///
+ /// Returns a Result containing either a `Vec` of events on success or errno
+ /// otherwise.
+ ///
+ /// # Errors
+ ///
+ /// Possible errors can be those that are explicitly listed in
+ /// [fanotify(2)](https://man7.org/linux/man-pages/man7/fanotify.2.html) in
+ /// addition to the possible errors caused by `read` call.
+ /// In particular, `EAGAIN` is returned when no event is available on a
+ /// group that has been initialized with the flag `InitFlags::FAN_NONBLOCK`,
+ /// thus making this method nonblocking.
+ pub fn read_events(&self) -> Result<Vec<FanotifyEvent>> {
+ let metadata_size = size_of::<libc::fanotify_event_metadata>();
+ const BUFSIZ: usize = 4096;
+ let mut buffer = [0u8; BUFSIZ];
+ let mut events = Vec::new();
+ let mut offset = 0;
+
+ let nread = read(self.fd.as_raw_fd(), &mut buffer)?;
+
+ while (nread - offset) >= metadata_size {
+ let metadata = unsafe {
+ let mut metadata =
+ MaybeUninit::<libc::fanotify_event_metadata>::uninit();
+ ptr::copy_nonoverlapping(
+ buffer.as_ptr().add(offset),
+ metadata.as_mut_ptr().cast(),
+ (BUFSIZ - offset).min(metadata_size),
+ );
+ metadata.assume_init()
+ };
+
+ events.push(FanotifyEvent(metadata));
+ offset += metadata.event_len as usize;
+ }
+
+ Ok(events)
+ }
+
+ /// Write an event response on the fanotify group.
+ ///
+ /// Returns a Result containing either `()` on success or errno otherwise.
+ ///
+ /// # Errors
+ ///
+ /// Possible errors can be those that are explicitly listed in
+ /// [fanotify(2)](https://man7.org/linux/man-pages/man7/fanotify.2.html) in
+ /// addition to the possible errors caused by `write` call.
+ /// In particular, `EAGAIN` or `EWOULDBLOCK` is returned when no event is
+ /// available on a group that has been initialized with the flag
+ /// `InitFlags::FAN_NONBLOCK`, thus making this method nonblocking.
+ pub fn write_response(&self, response: FanotifyResponse) -> Result<()> {
+ write(self.fd.as_fd(), unsafe {
+ std::slice::from_raw_parts(
+ (&response.inner as *const libc::fanotify_response).cast(),
+ size_of::<libc::fanotify_response>(),
+ )
+ })?;
+ Ok(())
+ }
+}
+
+impl FromRawFd for Fanotify {
+ unsafe fn from_raw_fd(fd: RawFd) -> Self {
+ Fanotify {
+ fd: unsafe { OwnedFd::from_raw_fd(fd) },
+ }
+ }
+}
+
+impl AsFd for Fanotify {
+ fn as_fd(&'_ self) -> BorrowedFd<'_> {
+ self.fd.as_fd()
+ }
+}
diff --git a/third_party/rust/nix/src/sys/inotify.rs b/third_party/rust/nix/src/sys/inotify.rs
index e5fe930f49..9cbeb53973 100644
--- a/third_party/rust/nix/src/sys/inotify.rs
+++ b/third_party/rust/nix/src/sys/inotify.rs
@@ -143,7 +143,9 @@ impl Inotify {
pub fn init(flags: InitFlags) -> Result<Inotify> {
let res = Errno::result(unsafe { libc::inotify_init1(flags.bits()) });
- res.map(|fd| Inotify { fd: unsafe { OwnedFd::from_raw_fd(fd) } })
+ res.map(|fd| Inotify {
+ fd: unsafe { OwnedFd::from_raw_fd(fd) },
+ })
}
/// Adds a new watch on the target file or directory.
@@ -157,7 +159,11 @@ impl Inotify {
mask: AddWatchFlags,
) -> Result<WatchDescriptor> {
let res = path.with_nix_path(|cstr| unsafe {
- libc::inotify_add_watch(self.fd.as_raw_fd(), cstr.as_ptr(), mask.bits())
+ libc::inotify_add_watch(
+ self.fd.as_raw_fd(),
+ cstr.as_ptr(),
+ mask.bits(),
+ )
})?;
Errno::result(res).map(|wd| WatchDescriptor { wd })
@@ -202,7 +208,7 @@ impl Inotify {
let mut event = MaybeUninit::<libc::inotify_event>::uninit();
ptr::copy_nonoverlapping(
buffer.as_ptr().add(offset),
- event.as_mut_ptr() as *mut u8,
+ event.as_mut_ptr().cast(),
(BUFSIZ - offset).min(header_size),
);
event.assume_init()
@@ -237,7 +243,9 @@ impl Inotify {
impl FromRawFd for Inotify {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
- Inotify { fd: OwnedFd::from_raw_fd(fd) }
+ Inotify {
+ fd: unsafe { OwnedFd::from_raw_fd(fd) },
+ }
}
}
diff --git a/third_party/rust/nix/src/sys/ioctl/bsd.rs b/third_party/rust/nix/src/sys/ioctl/bsd.rs
index 307994cb96..cedc8e63fe 100644
--- a/third_party/rust/nix/src/sys/ioctl/bsd.rs
+++ b/third_party/rust/nix/src/sys/ioctl/bsd.rs
@@ -1,10 +1,10 @@
/// The datatype used for the ioctl number
#[doc(hidden)]
-#[cfg(not(target_os = "illumos"))]
+#[cfg(not(solarish))]
pub type ioctl_num_type = ::libc::c_ulong;
#[doc(hidden)]
-#[cfg(target_os = "illumos")]
+#[cfg(solarish)]
pub type ioctl_num_type = ::libc::c_int;
/// The datatype used for the 3rd argument
diff --git a/third_party/rust/nix/src/sys/ioctl/linux.rs b/third_party/rust/nix/src/sys/ioctl/linux.rs
index 610b8ddac0..52312f4f04 100644
--- a/third_party/rust/nix/src/sys/ioctl/linux.rs
+++ b/third_party/rust/nix/src/sys/ioctl/linux.rs
@@ -19,7 +19,9 @@ pub const TYPEBITS: ioctl_num_type = 8;
cfg_if! {
if #[cfg(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "sparc64"
diff --git a/third_party/rust/nix/src/sys/ioctl/mod.rs b/third_party/rust/nix/src/sys/ioctl/mod.rs
index 0b3fe3e769..e1e808f19e 100644
--- a/third_party/rust/nix/src/sys/ioctl/mod.rs
+++ b/third_party/rust/nix/src/sys/ioctl/mod.rs
@@ -72,7 +72,7 @@
//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
//! # const SPI_IOC_TYPE_MODE: u8 = 1;
//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> {
-//! let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data);
+//! let res = unsafe { libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data) };
//! Errno::result(res)
//! }
//! # fn main() {}
@@ -121,11 +121,11 @@
//!
//! ```
//! # #[macro_use] extern crate nix;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
+//! # #[cfg(linux_android)]
//! # use nix::libc::TCGETS as TCGETS;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
+//! # #[cfg(linux_android)]
//! # use nix::libc::termios as termios;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
+//! # #[cfg(linux_android)]
//! ioctl_read_bad!(tcgets, TCGETS, termios);
//! # fn main() {}
//! ```
@@ -179,9 +179,13 @@
//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0;
//! # pub struct spi_ioc_transfer(u64);
//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> {
-//! let res = libc::ioctl(fd,
-//! request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()),
-//! data);
+//! let res = unsafe {
+//! libc::ioctl(
+//! fd,
+//! request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()),
+//! data
+//! )
+//! };
//! Errno::result(res)
//! }
//! # fn main() {}
@@ -223,40 +227,18 @@
//! ```
use cfg_if::cfg_if;
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+#[cfg(any(linux_android, target_os = "redox"))]
#[macro_use]
mod linux;
-#[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "redox"
-))]
+#[cfg(any(linux_android, target_os = "redox"))]
pub use self::linux::*;
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
-))]
+#[cfg(any(bsd, solarish, target_os = "haiku",))]
#[macro_use]
mod bsd;
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
-))]
+#[cfg(any(bsd, solarish, target_os = "haiku",))]
pub use self::bsd::*;
/// Convert raw ioctl return value to a Nix result
@@ -305,7 +287,9 @@ macro_rules! ioctl_none {
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
+ }
}
)
}
@@ -345,7 +329,9 @@ macro_rules! ioctl_none_bad {
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
+ }
}
)
}
@@ -383,7 +369,9 @@ macro_rules! ioctl_read {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -408,7 +396,7 @@ macro_rules! ioctl_read {
///
/// ```
/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
+/// # #[cfg(linux_android)]
/// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
/// # fn main() {}
/// ```
@@ -419,7 +407,9 @@ macro_rules! ioctl_read_bad {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -456,7 +446,9 @@ macro_rules! ioctl_write_ptr {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *const $ty)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -481,7 +473,7 @@ macro_rules! ioctl_write_ptr {
///
/// ```
/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
+/// # #[cfg(linux_android)]
/// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
/// # fn main() {}
/// ```
@@ -492,13 +484,15 @@ macro_rules! ioctl_write_ptr_bad {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *const $ty)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
cfg_if! {
- if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] {
+ if #[cfg(freebsdlike)] {
/// Generates a wrapper function for a ioctl that writes an integer to the kernel.
///
/// The arguments to this macro are:
@@ -533,7 +527,9 @@ cfg_if! {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: $crate::sys::ioctl::ioctl_param_type)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -574,7 +570,9 @@ cfg_if! {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: $crate::sys::ioctl::ioctl_param_type)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -600,7 +598,7 @@ cfg_if! {
///
/// ```
/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
+/// # #[cfg(linux_android)]
/// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
/// # fn main() {}
/// ```
@@ -618,7 +616,9 @@ macro_rules! ioctl_write_int_bad {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: $crate::libc::c_int)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -655,7 +655,9 @@ macro_rules! ioctl_readwrite {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -683,7 +685,9 @@ macro_rules! ioctl_readwrite_bad {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
+ }
}
)
}
@@ -712,7 +716,9 @@ macro_rules! ioctl_read_buf {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &mut [$ty])
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data.as_mut_ptr()))
+ }
}
)
}
@@ -751,7 +757,9 @@ macro_rules! ioctl_write_buf {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &[$ty])
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data.as_ptr()))
+ }
}
)
}
@@ -780,7 +788,9 @@ macro_rules! ioctl_readwrite_buf {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &mut [$ty])
-> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data))
+ unsafe {
+ convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data.as_mut_ptr()))
+ }
}
)
}
diff --git a/third_party/rust/nix/src/sys/memfd.rs b/third_party/rust/nix/src/sys/memfd.rs
index 516ffd3262..22ee5fc5b7 100644
--- a/third_party/rust/nix/src/sys/memfd.rs
+++ b/third_party/rust/nix/src/sys/memfd.rs
@@ -29,6 +29,49 @@ libc_bitflags!(
///
/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
MFD_ALLOW_SEALING;
+ /// Anonymous file will be created using huge pages. It should be safe now to
+ /// combine with [`MFD_ALLOW_SEALING`] too.
+ /// However, despite its presence, on FreeBSD it is unimplemented for now (ENOSYS).
+ ///
+ /// See also the hugetlb filesystem in [`memfd_create(2)`].
+ ///
+ /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
+ #[cfg(linux_android)]
+ MFD_HUGETLB;
+ /// Following are to be used with [`MFD_HUGETLB`], indicating the desired hugetlb size.
+ ///
+ /// See also the hugetlb filesystem in [`memfd_create(2)`].
+ ///
+ /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
+ #[cfg(linux_android)]
+ MFD_HUGE_1MB;
+ /// hugetlb size of 2MB.
+ #[cfg(linux_android)]
+ MFD_HUGE_2MB;
+ /// hugetlb size of 8MB.
+ #[cfg(linux_android)]
+ MFD_HUGE_8MB;
+ /// hugetlb size of 16MB.
+ #[cfg(linux_android)]
+ MFD_HUGE_16MB;
+ /// hugetlb size of 32MB.
+ #[cfg(linux_android)]
+ MFD_HUGE_32MB;
+ /// hugetlb size of 256MB.
+ #[cfg(linux_android)]
+ MFD_HUGE_256MB;
+ /// hugetlb size of 512MB.
+ #[cfg(linux_android)]
+ MFD_HUGE_512MB;
+ /// hugetlb size of 1GB.
+ #[cfg(linux_android)]
+ MFD_HUGE_1GB;
+ /// hugetlb size of 2GB.
+ #[cfg(linux_android)]
+ MFD_HUGE_2GB;
+ /// hugetlb size of 16GB.
+ #[cfg(linux_android)]
+ MFD_HUGE_16GB;
}
);
diff --git a/third_party/rust/nix/src/sys/mman.rs b/third_party/rust/nix/src/sys/mman.rs
index 8cfd6d6d54..a64f14f588 100644
--- a/third_party/rust/nix/src/sys/mman.rs
+++ b/third_party/rust/nix/src/sys/mman.rs
@@ -8,7 +8,11 @@ use crate::Result;
#[cfg(feature = "fs")]
use crate::{fcntl::OFlag, sys::stat::Mode};
use libc::{self, c_int, c_void, off_t, size_t};
-use std::{num::NonZeroUsize, os::unix::io::{AsRawFd, AsFd}};
+use std::ptr::NonNull;
+use std::{
+ num::NonZeroUsize,
+ os::unix::io::{AsFd, AsRawFd},
+};
libc_bitflags! {
/// Desired memory protection of a memory mapping.
@@ -22,12 +26,10 @@ libc_bitflags! {
/// Pages can be executed
PROT_EXEC;
/// Apply protection up to the end of a mapping that grows upwards.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
PROT_GROWSDOWN;
/// Apply protection down to the beginning of a mapping that grows downwards.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
PROT_GROWSUP;
}
}
@@ -45,145 +47,143 @@ libc_bitflags! {
MAP_FIXED;
/// Place the mapping at exactly the address specified in `addr`, but never clobber an existing range.
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_FIXED_NOREPLACE;
/// To be used with `MAP_FIXED`, to forbid the system
/// to select a different address than the one specified.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_EXCL;
/// Synonym for `MAP_ANONYMOUS`.
MAP_ANON;
/// The mapping is not backed by any file.
MAP_ANONYMOUS;
/// Put the mapping into the first 2GB of the process address space.
- #[cfg(any(all(any(target_os = "android", target_os = "linux"),
+ #[cfg(any(all(linux_android,
any(target_arch = "x86", target_arch = "x86_64")),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
all(target_os = "freebsd", target_pointer_width = "64")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_32BIT;
/// Used for stacks; indicates to the kernel that the mapping should extend downward in memory.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MAP_GROWSDOWN;
/// Compatibility flag. Ignored.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MAP_DENYWRITE;
/// Compatibility flag. Ignored.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MAP_EXECUTABLE;
/// Mark the mmaped region to be locked in the same way as `mlock(2)`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MAP_LOCKED;
/// Do not reserve swap space for this mapping.
///
/// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
- #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "aix")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(any(freebsdlike, target_os = "aix", target_os = "hurd")))]
MAP_NORESERVE;
/// Populate page tables for a mapping.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MAP_POPULATE;
/// Only meaningful when used with `MAP_POPULATE`. Don't perform read-ahead.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MAP_NONBLOCK;
/// Allocate the mapping using "huge pages."
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MAP_HUGETLB;
/// Make use of 64KB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_64KB;
/// Make use of 512KB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_512KB;
/// Make use of 1MB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_1MB;
/// Make use of 2MB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_2MB;
/// Make use of 8MB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_8MB;
/// Make use of 16MB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_16MB;
/// Make use of 32MB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_32MB;
/// Make use of 256MB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_256MB;
/// Make use of 512MB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_512MB;
/// Make use of 1GB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_1GB;
/// Make use of 2GB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_2GB;
/// Make use of 16GB huge page (must be supported by the system)
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_16GB;
/// Lock the mapped region into memory as with `mlock(2)`.
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_WIRED;
/// Causes dirtied data in the specified range to be flushed to disk only when necessary.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MAP_NOSYNC;
/// Rename private pages to a file.
///
/// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
- #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(netbsdlike)]
MAP_RENAME;
/// Region may contain semaphores.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(freebsdlike, netbsdlike))]
MAP_HASSEMAPHORE;
/// Region grows down, like a stack.
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
MAP_STACK;
/// Pages in this mapping are not retained in the kernel's memory cache.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
MAP_NOCACHE;
/// Allows the W/X bit on the page, it's necessary on aarch64 architecture.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
MAP_JIT;
/// Allows to use large pages, underlying alignment based on size.
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_ALIGNED_SUPER;
/// Pages will be discarded in the core dumps.
#[cfg(target_os = "openbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_CONCEAL;
+ /// Attempt to place the mapping at exactly the address specified in `addr`.
+ /// it's a default behavior on OpenBSD.
+ #[cfg(netbsdlike)]
+ MAP_TRYFIXED;
+ }
+}
+
+impl MapFlags {
+ /// Create `MAP_HUGETLB` with provided size of huge page.
+ ///
+ /// Under the hood it computes `MAP_HUGETLB | (huge_page_size_log2 << libc::MAP_HUGE_SHIFT`).
+ /// `huge_page_size_log2` denotes logarithm of huge page size to use and should be
+ /// between 16 and 63 (inclusively).
+ ///
+ /// ```
+ /// # use nix::sys::mman::MapFlags;
+ /// let f = MapFlags::map_hugetlb_with_size_log2(30).unwrap();
+ /// assert_eq!(f, MapFlags::MAP_HUGETLB | MapFlags::MAP_HUGE_1GB);
+ /// ```
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
+ pub fn map_hugetlb_with_size_log2(
+ huge_page_size_log2: u32,
+ ) -> Option<Self> {
+ if (16..=63).contains(&huge_page_size_log2) {
+ let flag = libc::MAP_HUGETLB
+ | (huge_page_size_log2 << libc::MAP_HUGE_SHIFT) as i32;
+ Some(Self(flag.into()))
+ } else {
+ None
+ }
}
}
@@ -193,19 +193,15 @@ libc_bitflags! {
pub struct MRemapFlags: c_int {
/// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MREMAP_MAYMOVE;
/// Place the mapping at exactly the address specified in `new_address`.
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MREMAP_FIXED;
/// Place the mapping at exactly the address specified in `new_address`.
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_FIXED;
/// Allows to duplicate the mapping to be able to apply different flags on the copy.
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MAP_REMAPDUP;
}
}
@@ -228,30 +224,24 @@ libc_enum! {
/// Do not expect access in the near future.
MADV_DONTNEED,
/// Free up a given range of pages and its associated backing store.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_REMOVE,
/// Do not make pages in this range available to the child after a `fork(2)`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_DONTFORK,
/// Undo the effect of `MADV_DONTFORK`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_DOFORK,
/// Poison the given pages.
///
/// Subsequent references to those pages are treated like hardware memory corruption.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_HWPOISON,
/// Enable Kernel Samepage Merging (KSM) for the given pages.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_MERGEABLE,
/// Undo the effect of `MADV_MERGEABLE`
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_UNMERGEABLE,
/// Preserve the memory of each page but offline the original page.
#[cfg(any(target_os = "android",
@@ -266,68 +256,52 @@ libc_enum! {
target_arch = "sparc64"))))]
MADV_SOFT_OFFLINE,
/// Enable Transparent Huge Pages (THP) for pages in the given range.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_HUGEPAGE,
/// Undo the effect of `MADV_HUGEPAGE`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_NOHUGEPAGE,
/// Exclude the given range from a core dump.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_DONTDUMP,
/// Undo the effect of an earlier `MADV_DONTDUMP`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MADV_DODUMP,
/// Specify that the application no longer needs the pages in the given range.
- #[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(any(target_os = "aix", target_os = "hurd")))]
MADV_FREE,
/// Request that the system not flush the current range to disk unless it needs to.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MADV_NOSYNC,
/// Undoes the effects of `MADV_NOSYNC` for any future pages dirtied within the given range.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MADV_AUTOSYNC,
/// Region is not included in a core file.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MADV_NOCORE,
/// Include region in a core file
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
MADV_CORE,
/// This process should not be killed when swap space is exhausted.
#[cfg(any(target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MADV_PROTECT,
/// Invalidate the hardware page table for the given region.
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MADV_INVAL,
/// Set the offset of the page directory page to `value` for the virtual page table.
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MADV_SETMAP,
/// Indicates that the application will not need the data in the given range.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
MADV_ZERO_WIRED_PAGES,
/// Pages can be reused (by anyone).
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
MADV_FREE_REUSABLE,
/// Caller wants to reuse those pages.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
MADV_FREE_REUSE,
// Darwin doesn't document this flag's behavior.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
#[allow(missing_docs)]
MADV_CAN_REUSE,
}
@@ -341,12 +315,10 @@ libc_bitflags! {
/// Invalidate all cached data.
MS_INVALIDATE;
/// Invalidate pages, but leave them mapped.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
MS_KILLPAGES;
/// Deactivate pages, but leave them mapped.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
MS_DEACTIVATE;
/// Perform an update and wait for it to complete.
MS_SYNC;
@@ -374,8 +346,8 @@ libc_bitflags! {
/// `addr` must meet all the requirements described in the [`mlock(2)`] man page.
///
/// [`mlock(2)`]: https://man7.org/linux/man-pages/man2/mlock.2.html
-pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
- Errno::result(libc::mlock(addr, length)).map(drop)
+pub unsafe fn mlock(addr: NonNull<c_void>, length: size_t) -> Result<()> {
+ unsafe { Errno::result(libc::mlock(addr.as_ptr(), length)).map(drop) }
}
/// Unlocks all memory pages that contain part of the address range with
@@ -387,8 +359,8 @@ pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
/// page.
///
/// [`munlock(2)`]: https://man7.org/linux/man-pages/man2/munlock.2.html
-pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
- Errno::result(libc::munlock(addr, length)).map(drop)
+pub unsafe fn munlock(addr: NonNull<c_void>, length: size_t) -> Result<()> {
+ unsafe { Errno::result(libc::munlock(addr.as_ptr(), length)).map(drop) }
}
/// Locks all memory pages mapped into this process' address space.
@@ -411,7 +383,9 @@ pub fn munlockall() -> Result<()> {
unsafe { Errno::result(libc::munlockall()) }.map(drop)
}
-/// allocate memory, or map files or devices into memory
+/// Allocate memory, or map files or devices into memory
+///
+/// For anonymous mappings (`MAP_ANON`/`MAP_ANONYMOUS`), see [mmap_anonymous].
///
/// # Safety
///
@@ -423,20 +397,54 @@ pub unsafe fn mmap<F: AsFd>(
length: NonZeroUsize,
prot: ProtFlags,
flags: MapFlags,
- f: Option<F>,
+ f: F,
offset: off_t,
-) -> Result<*mut c_void> {
- let ptr =
- addr.map_or(std::ptr::null_mut(), |a| usize::from(a) as *mut c_void);
+) -> Result<NonNull<c_void>> {
+ let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void);
- let fd = f.map(|f| f.as_fd().as_raw_fd()).unwrap_or(-1);
- let ret =
- libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset);
+ let fd = f.as_fd().as_raw_fd();
+ let ret = unsafe {
+ libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset)
+ };
+
+ if ret == libc::MAP_FAILED {
+ Err(Errno::last())
+ } else {
+ // SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
+ // will be non-null here.
+ Ok(unsafe { NonNull::new_unchecked(ret) })
+ }
+}
+
+/// Create an anonymous memory mapping.
+///
+/// This function is a wrapper around [`mmap`]:
+/// `mmap(ptr, len, prot, MAP_ANONYMOUS | flags, -1, 0)`.
+///
+/// # Safety
+///
+/// See the [`mmap(2)`] man page for detailed requirements.
+///
+/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
+pub unsafe fn mmap_anonymous(
+ addr: Option<NonZeroUsize>,
+ length: NonZeroUsize,
+ prot: ProtFlags,
+ flags: MapFlags,
+) -> Result<NonNull<c_void>> {
+ let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void);
+
+ let flags = MapFlags::MAP_ANONYMOUS | flags;
+ let ret = unsafe {
+ libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), -1, 0)
+ };
if ret == libc::MAP_FAILED {
Err(Errno::last())
} else {
- Ok(ret)
+ // SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
+ // will be non-null here.
+ Ok(unsafe { NonNull::new_unchecked(ret) })
}
}
@@ -449,33 +457,43 @@ pub unsafe fn mmap<F: AsFd>(
/// detailed requirements.
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
pub unsafe fn mremap(
- addr: *mut c_void,
+ addr: NonNull<c_void>,
old_size: size_t,
new_size: size_t,
flags: MRemapFlags,
- new_address: Option<*mut c_void>,
-) -> Result<*mut c_void> {
+ new_address: Option<NonNull<c_void>>,
+) -> Result<NonNull<c_void>> {
#[cfg(target_os = "linux")]
- let ret = libc::mremap(
- addr,
- old_size,
- new_size,
- flags.bits(),
- new_address.unwrap_or(std::ptr::null_mut()),
- );
+ let ret = unsafe {
+ libc::mremap(
+ addr.as_ptr(),
+ old_size,
+ new_size,
+ flags.bits(),
+ new_address
+ .map(NonNull::as_ptr)
+ .unwrap_or(std::ptr::null_mut()),
+ )
+ };
#[cfg(target_os = "netbsd")]
- let ret = libc::mremap(
- addr,
- old_size,
- new_address.unwrap_or(std::ptr::null_mut()),
- new_size,
- flags.bits(),
- );
+ let ret = unsafe {
+ libc::mremap(
+ addr.as_ptr(),
+ old_size,
+ new_address
+ .map(NonNull::as_ptr)
+ .unwrap_or(std::ptr::null_mut()),
+ new_size,
+ flags.bits(),
+ )
+ };
if ret == libc::MAP_FAILED {
Err(Errno::last())
} else {
- Ok(ret)
+ // SAFETY: `libc::mremap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
+ // will be non-null here.
+ Ok(unsafe { NonNull::new_unchecked(ret) })
}
}
@@ -487,8 +505,8 @@ pub unsafe fn mremap(
/// page.
///
/// [`munmap(2)`]: https://man7.org/linux/man-pages/man2/munmap.2.html
-pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
- Errno::result(libc::munmap(addr, len)).map(drop)
+pub unsafe fn munmap(addr: NonNull<c_void>, len: size_t) -> Result<()> {
+ unsafe { Errno::result(libc::munmap(addr.as_ptr(), len)).map(drop) }
}
/// give advice about use of memory
@@ -499,12 +517,16 @@ pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
/// [`MmapAdvise::MADV_FREE`].
///
/// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html
+#[allow(rustdoc::broken_intra_doc_links)] // For Hurd as `MADV_FREE` is not available on it
pub unsafe fn madvise(
- addr: *mut c_void,
+ addr: NonNull<c_void>,
length: size_t,
advise: MmapAdvise,
) -> Result<()> {
- Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
+ unsafe {
+ Errno::result(libc::madvise(addr.as_ptr(), length, advise as i32))
+ .map(drop)
+ }
}
/// Set protection of memory mapping.
@@ -519,27 +541,30 @@ pub unsafe fn madvise(
///
/// ```
/// # use nix::libc::size_t;
-/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
+/// # use nix::sys::mman::{mmap_anonymous, mprotect, MapFlags, ProtFlags};
/// # use std::ptr;
/// # use std::os::unix::io::BorrowedFd;
/// const ONE_K: size_t = 1024;
/// let one_k_non_zero = std::num::NonZeroUsize::new(ONE_K).unwrap();
/// let mut slice: &mut [u8] = unsafe {
-/// let mem = mmap::<BorrowedFd>(None, one_k_non_zero, ProtFlags::PROT_NONE,
-/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, None, 0).unwrap();
+/// let mem = mmap_anonymous(None, one_k_non_zero, ProtFlags::PROT_NONE, MapFlags::MAP_PRIVATE)
+/// .unwrap();
/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
-/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
+/// std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
/// };
/// assert_eq!(slice[0], 0x00);
/// slice[0] = 0xFF;
/// assert_eq!(slice[0], 0xFF);
/// ```
pub unsafe fn mprotect(
- addr: *mut c_void,
+ addr: NonNull<c_void>,
length: size_t,
prot: ProtFlags,
) -> Result<()> {
- Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
+ unsafe {
+ Errno::result(libc::mprotect(addr.as_ptr(), length, prot.bits()))
+ .map(drop)
+ }
}
/// synchronize a mapped region
@@ -551,11 +576,14 @@ pub unsafe fn mprotect(
///
/// [`msync(2)`]: https://man7.org/linux/man-pages/man2/msync.2.html
pub unsafe fn msync(
- addr: *mut c_void,
+ addr: NonNull<c_void>,
length: size_t,
flags: MsFlags,
) -> Result<()> {
- Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
+ unsafe {
+ Errno::result(libc::msync(addr.as_ptr(), length, flags.bits()))
+ .map(drop)
+ }
}
#[cfg(not(target_os = "android"))]
@@ -576,11 +604,11 @@ pub fn shm_open<P>(
use std::os::unix::io::{FromRawFd, OwnedFd};
let ret = name.with_nix_path(|cstr| {
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
unsafe {
libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint)
}
- #[cfg(not(any(target_os = "macos", target_os = "ios")))]
+ #[cfg(not(apple_targets))]
unsafe {
libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t)
}
diff --git a/third_party/rust/nix/src/sys/mod.rs b/third_party/rust/nix/src/sys/mod.rs
index bf047b3dda..93339d1935 100644
--- a/third_party/rust/nix/src/sys/mod.rs
+++ b/third_party/rust/nix/src/sys/mod.rs
@@ -1,10 +1,8 @@
//! Mostly platform-specific functionality
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "macos",
+ apple_targets,
target_os = "netbsd"
))]
feature! {
@@ -15,41 +13,31 @@ feature! {
feature! {
#![feature = "event"]
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[allow(missing_docs)]
pub mod epoll;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(bsd)]
pub mod event;
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[allow(missing_docs)]
pub mod eventfd;
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"
-))]
+#[cfg(target_os = "linux")]
+feature! {
+ #![feature = "fanotify"]
+ pub mod fanotify;
+}
+
+#[cfg(any(bsd, linux_android, target_os = "redox", solarish))]
#[cfg(feature = "ioctl")]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
#[macro_use]
pub mod ioctl;
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
feature! {
#![feature = "fs"]
pub mod memfd;
@@ -78,15 +66,7 @@ feature! {
pub mod pthread;
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(any(linux_android, bsd))]
feature! {
#![feature = "ptrace"]
#[allow(missing_docs)]
@@ -99,7 +79,7 @@ feature! {
pub mod quota;
}
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", netbsdlike))]
feature! {
#![feature = "reboot"]
pub mod reboot;
@@ -108,7 +88,7 @@ feature! {
#[cfg(not(any(
target_os = "redox",
target_os = "fuchsia",
- target_os = "illumos",
+ solarish,
target_os = "haiku"
)))]
feature! {
@@ -121,14 +101,7 @@ feature! {
pub mod select;
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"
-))]
+#[cfg(any(linux_android, freebsdlike, apple_targets, solarish))]
feature! {
#![feature = "zerocopy"]
pub mod sendfile;
@@ -136,7 +109,7 @@ feature! {
pub mod signal;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
feature! {
#![feature = "signal"]
#[allow(missing_docs)]
@@ -155,15 +128,7 @@ feature! {
pub mod stat;
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "openbsd"
-))]
+#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "openbsd"))]
feature! {
#![feature = "fs"]
pub mod statfs;
@@ -174,8 +139,7 @@ feature! {
pub mod statvfs;
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub mod sysinfo;
@@ -203,13 +167,13 @@ feature! {
pub mod wait;
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
feature! {
#![feature = "inotify"]
pub mod inotify;
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
feature! {
#![feature = "time"]
pub mod timerfd;
@@ -218,7 +182,7 @@ feature! {
#[cfg(all(
any(
target_os = "freebsd",
- target_os = "illumos",
+ solarish,
target_os = "linux",
target_os = "netbsd"
),
diff --git a/third_party/rust/nix/src/sys/personality.rs b/third_party/rust/nix/src/sys/personality.rs
index 30231dd7b8..a4cfb5ef4f 100644
--- a/third_party/rust/nix/src/sys/personality.rs
+++ b/third_party/rust/nix/src/sys/personality.rs
@@ -21,7 +21,6 @@ libc_bitflags! {
ADDR_LIMIT_3GB;
/// User-space function pointers to signal handlers point to descriptors.
#[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
FDPIC_FUNCPTRS;
/// Map page 0 as read-only.
MMAP_PAGE_ZERO;
@@ -43,7 +42,6 @@ libc_bitflags! {
///
/// [`uname(2)`]: https://man7.org/linux/man-pages/man2/uname.2.html
#[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
UNAME26;
/// No effects.
WHOLE_SECONDS;
diff --git a/third_party/rust/nix/src/sys/prctl.rs b/third_party/rust/nix/src/sys/prctl.rs
index 995382cb0c..42324beab2 100644
--- a/third_party/rust/nix/src/sys/prctl.rs
+++ b/third_party/rust/nix/src/sys/prctl.rs
@@ -50,7 +50,9 @@ pub fn get_child_subreaper() -> Result<bool> {
// prctl writes into this var
let mut subreaper: c_int = 0;
- let res = unsafe { libc::prctl(libc::PR_GET_CHILD_SUBREAPER, &mut subreaper, 0, 0, 0) };
+ let res = unsafe {
+ libc::prctl(libc::PR_GET_CHILD_SUBREAPER, &mut subreaper, 0, 0, 0)
+ };
Errno::result(res).map(|_| subreaper != 0)
}
@@ -78,7 +80,9 @@ pub fn get_keepcaps() -> Result<bool> {
/// Clear the thread memory corruption kill policy and use the system-wide default
pub fn clear_mce_kill() -> Result<()> {
- let res = unsafe { libc::prctl(libc::PR_MCE_KILL, libc::PR_MCE_KILL_CLEAR, 0, 0, 0) };
+ let res = unsafe {
+ libc::prctl(libc::PR_MCE_KILL, libc::PR_MCE_KILL_CLEAR, 0, 0, 0)
+ };
Errno::result(res).map(drop)
}
@@ -151,10 +155,11 @@ pub fn get_name() -> Result<CString> {
let res = unsafe { libc::prctl(libc::PR_GET_NAME, &buf, 0, 0, 0) };
- let len = buf.iter().position(|&c| c == 0).unwrap_or(buf.len());
- let name = CStr::from_bytes_with_nul(&buf[..=len]).map_err(|_| Errno::EINVAL)?;
-
- Errno::result(res).map(|_| name.to_owned())
+ Errno::result(res).and_then(|_| {
+ CStr::from_bytes_until_nul(&buf)
+ .map(CStr::to_owned)
+ .map_err(|_| Errno::EINVAL)
+ })
}
/// Sets the timer slack value for the calling thread. Timer slack is used by the kernel to group
@@ -174,14 +179,16 @@ pub fn get_timerslack() -> Result<i32> {
/// Disable all performance counters attached to the calling process.
pub fn task_perf_events_disable() -> Result<()> {
- let res = unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_DISABLE, 0, 0, 0, 0) };
+ let res =
+ unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_DISABLE, 0, 0, 0, 0) };
Errno::result(res).map(drop)
}
/// Enable all performance counters attached to the calling process.
pub fn task_perf_events_enable() -> Result<()> {
- let res = unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_ENABLE, 0, 0, 0, 0) };
+ let res =
+ unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_ENABLE, 0, 0, 0, 0) };
Errno::result(res).map(drop)
}
diff --git a/third_party/rust/nix/src/sys/ptrace/bsd.rs b/third_party/rust/nix/src/sys/ptrace/bsd.rs
index ba267c6577..3dd486210c 100644
--- a/third_party/rust/nix/src/sys/ptrace/bsd.rs
+++ b/third_party/rust/nix/src/sys/ptrace/bsd.rs
@@ -9,10 +9,7 @@ use std::ptr;
pub type RequestType = c_int;
cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "openbsd"))] {
+ if #[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))] {
#[doc(hidden)]
pub type AddressType = *mut ::libc::c_char;
} else {
@@ -29,33 +26,26 @@ libc_enum! {
PT_TRACE_ME,
PT_READ_I,
PT_READ_D,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
PT_READ_U,
PT_WRITE_I,
PT_WRITE_D,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
PT_WRITE_U,
PT_CONTINUE,
PT_KILL,
- #[cfg(any(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos"),
+ #[cfg(any(any(freebsdlike, apple_targets),
all(target_os = "openbsd", target_arch = "x86_64"),
all(target_os = "netbsd", any(target_arch = "x86_64",
target_arch = "powerpc"))))]
PT_STEP,
PT_ATTACH,
PT_DETACH,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
PT_SIGEXC,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
PT_THUPDATE,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
PT_ATTACHEXC
}
}
@@ -66,13 +56,15 @@ unsafe fn ptrace_other(
addr: AddressType,
data: c_int,
) -> Result<c_int> {
- Errno::result(libc::ptrace(
- request as RequestType,
- libc::pid_t::from(pid),
- addr,
- data,
- ))
- .map(|_| 0)
+ unsafe {
+ Errno::result(libc::ptrace(
+ request as RequestType,
+ libc::pid_t::from(pid),
+ addr,
+ data,
+ ))
+ .map(|_| 0)
+ }
}
/// Sets the process as traceable, as with `ptrace(PT_TRACEME, ...)`
@@ -157,7 +149,7 @@ pub fn kill(pid: Pid) -> Result<()> {
/// }
/// ```
#[cfg(any(
- any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"),
+ any(freebsdlike, apple_targets),
all(target_os = "openbsd", target_arch = "x86_64"),
all(
target_os = "netbsd",
diff --git a/third_party/rust/nix/src/sys/ptrace/linux.rs b/third_party/rust/nix/src/sys/ptrace/linux.rs
index 8c134cf7ee..26544e134b 100644
--- a/third_party/rust/nix/src/sys/ptrace/linux.rs
+++ b/third_party/rust/nix/src/sys/ptrace/linux.rs
@@ -53,28 +53,36 @@ libc_enum! {
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
all(target_os = "linux", any(target_env = "musl",
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "x86_64",
target_pointer_width = "32"))))]
PTRACE_GETREGS,
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
all(target_os = "linux", any(target_env = "musl",
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "x86_64",
target_pointer_width = "32"))))]
PTRACE_SETREGS,
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
all(target_os = "linux", any(target_env = "musl",
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "x86_64",
target_pointer_width = "32"))))]
PTRACE_GETFPREGS,
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
all(target_os = "linux", any(target_env = "musl",
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "x86_64",
target_pointer_width = "32"))))]
PTRACE_SETFPREGS,
@@ -82,13 +90,17 @@ libc_enum! {
PTRACE_DETACH,
#[cfg(all(target_os = "linux", any(target_env = "musl",
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "x86",
target_arch = "x86_64")))]
PTRACE_GETFPXREGS,
#[cfg(all(target_os = "linux", any(target_env = "musl",
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "x86",
target_arch = "x86_64")))]
PTRACE_SETFPXREGS,
@@ -98,22 +110,28 @@ libc_enum! {
PTRACE_GETSIGINFO,
PTRACE_SETSIGINFO,
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"))))]
PTRACE_GETREGSET,
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"))))]
PTRACE_SETREGSET,
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
PTRACE_SEIZE,
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
PTRACE_INTERRUPT,
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"))))]
PTRACE_LISTEN,
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"))))]
PTRACE_PEEKSIGINFO,
#[cfg(all(target_os = "linux", target_env = "gnu",
any(target_arch = "x86", target_arch = "x86_64")))]
@@ -241,13 +259,13 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
/// and therefore use the data field to return values. This function handles these
/// requests.
fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
- let mut data = mem::MaybeUninit::uninit();
+ let mut data = mem::MaybeUninit::<T>::uninit();
let res = unsafe {
libc::ptrace(
request as RequestType,
libc::pid_t::from(pid),
ptr::null_mut::<T>(),
- data.as_mut_ptr() as *const _ as *const c_void,
+ data.as_mut_ptr(),
)
};
Errno::result(res)?;
@@ -260,13 +278,15 @@ unsafe fn ptrace_other(
addr: AddressType,
data: *mut c_void,
) -> Result<c_long> {
- Errno::result(libc::ptrace(
- request as RequestType,
- libc::pid_t::from(pid),
- addr,
- data,
- ))
- .map(|_| 0)
+ unsafe {
+ Errno::result(libc::ptrace(
+ request as RequestType,
+ libc::pid_t::from(pid),
+ addr,
+ data,
+ ))
+ .map(|_| 0)
+ }
}
/// Set options, as with `ptrace(PTRACE_SETOPTIONS, ...)`.
@@ -381,7 +401,6 @@ pub fn attach(pid: Pid) -> Result<()> {
///
/// Attaches to the process specified in pid, making it a tracee of the calling process.
#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn seize(pid: Pid, options: Options) -> Result<()> {
unsafe {
ptrace_other(
@@ -428,7 +447,6 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
///
/// This request is equivalent to `ptrace(PTRACE_INTERRUPT, ...)`
#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn interrupt(pid: Pid) -> Result<()> {
unsafe {
ptrace_other(
@@ -535,7 +553,7 @@ pub unsafe fn write(
addr: AddressType,
data: *mut c_void,
) -> Result<()> {
- ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
+ unsafe { ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop) }
}
/// Reads a word from a user area at `offset`, as with ptrace(PTRACE_PEEKUSER, ...).
@@ -556,5 +574,7 @@ pub unsafe fn write_user(
offset: AddressType,
data: *mut c_void,
) -> Result<()> {
- ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data).map(drop)
+ unsafe {
+ ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data).map(drop)
+ }
}
diff --git a/third_party/rust/nix/src/sys/ptrace/mod.rs b/third_party/rust/nix/src/sys/ptrace/mod.rs
index 88648acabc..c059797df9 100644
--- a/third_party/rust/nix/src/sys/ptrace/mod.rs
+++ b/third_party/rust/nix/src/sys/ptrace/mod.rs
@@ -1,25 +1,13 @@
//! Provides helpers for making ptrace system calls
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod linux;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
pub use self::linux::*;
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(bsd)]
mod bsd;
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(bsd)]
pub use self::bsd::*;
diff --git a/third_party/rust/nix/src/sys/quota.rs b/third_party/rust/nix/src/sys/quota.rs
index a32d07aa1e..2d12b858bf 100644
--- a/third_party/rust/nix/src/sys/quota.rs
+++ b/third_party/rust/nix/src/sys/quota.rs
@@ -264,7 +264,7 @@ pub fn quotactl_on<P: ?Sized + NixPath>(
) -> Result<()> {
quota_file.with_nix_path(|path| {
let mut path_copy = path.to_bytes_with_nul().to_owned();
- let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char;
+ let p: *mut c_char = path_copy.as_mut_ptr().cast();
quotactl(
QuotaCmd(QuotaSubCmd::Q_QUOTAON, which),
Some(special),
@@ -308,12 +308,12 @@ pub fn quotactl_get<P: ?Sized + NixPath>(
special: &P,
id: c_int,
) -> Result<Dqblk> {
- let mut dqblk = mem::MaybeUninit::uninit();
+ let mut dqblk = mem::MaybeUninit::<libc::dqblk>::uninit();
quotactl(
QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which),
Some(special),
id,
- dqblk.as_mut_ptr() as *mut c_char,
+ dqblk.as_mut_ptr().cast(),
)?;
Ok(unsafe { Dqblk(dqblk.assume_init()) })
}
diff --git a/third_party/rust/nix/src/sys/reboot.rs b/third_party/rust/nix/src/sys/reboot.rs
index 02d98162bd..2e4d888de4 100644
--- a/third_party/rust/nix/src/sys/reboot.rs
+++ b/third_party/rust/nix/src/sys/reboot.rs
@@ -1,48 +1,141 @@
-//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
+//! Reboot/shutdown
+//!
+//! On Linux, This can also be used to enable/disable Ctrl-Alt-Delete.
use crate::errno::Errno;
use crate::Result;
+use cfg_if::cfg_if;
use std::convert::Infallible;
-use std::mem::drop;
-
-libc_enum! {
- /// How exactly should the system be rebooted.
- ///
- /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
- /// enabling/disabling Ctrl-Alt-Delete.
- #[repr(i32)]
- #[non_exhaustive]
- pub enum RebootMode {
- /// Halt the system.
- RB_HALT_SYSTEM,
- /// Execute a kernel that has been loaded earlier with
- /// [`kexec_load(2)`](https://man7.org/linux/man-pages/man2/kexec_load.2.html).
- RB_KEXEC,
- /// Stop the system and switch off power, if possible.
- RB_POWER_OFF,
- /// Restart the system.
- RB_AUTOBOOT,
- // we do not support Restart2.
- /// Suspend the system using software suspend.
- RB_SW_SUSPEND,
- }
-}
-/// Reboots or shuts down the system.
-pub fn reboot(how: RebootMode) -> Result<Infallible> {
- unsafe { libc::reboot(how as libc::c_int) };
- Err(Errno::last())
-}
+cfg_if! {
+ if #[cfg(target_os = "linux")] {
+ use std::mem::drop;
+
+ libc_enum! {
+ /// How exactly should the system be rebooted.
+ ///
+ /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
+ /// enabling/disabling Ctrl-Alt-Delete.
+ #[repr(i32)]
+ #[non_exhaustive]
+ pub enum RebootMode {
+ /// Halt the system.
+ RB_HALT_SYSTEM,
+ /// Execute a kernel that has been loaded earlier with
+ /// [`kexec_load(2)`](https://man7.org/linux/man-pages/man2/kexec_load.2.html).
+ RB_KEXEC,
+ /// Stop the system and switch off power, if possible.
+ RB_POWER_OFF,
+ /// Restart the system.
+ RB_AUTOBOOT,
+ // we do not support Restart2.
+ /// Suspend the system using software suspend.
+ RB_SW_SUSPEND,
+ }
+ }
+
+ /// Reboots or shuts down the system.
+ pub fn reboot(how: RebootMode) -> Result<Infallible> {
+ unsafe { libc::reboot(how as libc::c_int) };
+ Err(Errno::last())
+ }
-/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
-///
-/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
-pub fn set_cad_enabled(enable: bool) -> Result<()> {
- let cmd = if enable {
- libc::RB_ENABLE_CAD
- } else {
- libc::RB_DISABLE_CAD
- };
- let res = unsafe { libc::reboot(cmd) };
- Errno::result(res).map(drop)
+ /// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
+ ///
+ /// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
+ pub fn set_cad_enabled(enable: bool) -> Result<()> {
+ let cmd = if enable {
+ libc::RB_ENABLE_CAD
+ } else {
+ libc::RB_DISABLE_CAD
+ };
+ let res = unsafe { libc::reboot(cmd) };
+ Errno::result(res).map(drop)
+ }
+ } else if #[cfg(netbsdlike)] {
+ use libc::c_int;
+
+ libc_bitflags! {
+ /// How exactly should the system be rebooted.
+ pub struct RebootMode: c_int {
+ /// The default, causing the system to reboot in its usual fashion.
+ RB_AUTOBOOT;
+ /// Interpreted by the bootstrap program itself, causing it to
+ /// prompt on the console as to what file should be booted.
+ /// Normally, the system is booted from the file “xx(0,0)bsd”,
+ /// where xx is the default disk name, without prompting for
+ /// the file name.
+ RB_ASKNAME;
+ /// Dump kernel memory before rebooting; see `savecore(8)` for
+ /// more information.
+ RB_DUMP;
+ /// The processor is simply halted; no reboot takes place.
+ RB_HALT;
+ /// Power off the system if the system hardware supports the
+ /// function, otherwise it has no effect.
+ ///
+ /// Should be used in conjunction with `RB_HALT`.
+ RB_POWERDOWN;
+ /// By default, the system will halt if `reboot()` is called during
+ /// startup (before the system has finished autoconfiguration), even
+ /// if `RB_HALT` is not specified. This is because `panic(9)`s
+ /// during startup will probably just repeat on the next boot.
+ /// Use of this option implies that the user has requested the
+ /// action specified (for example, using the `ddb(4)` boot reboot
+ /// command), so the system will reboot if a halt is not explicitly
+ /// requested.
+ #[cfg(target_os = "openbsd")]
+ RB_USERREQ;
+ /// Load the symbol table and enable a built-in debugger in the
+ /// system. This option will have no useful function if the kernel
+ /// is not configured for debugging. Several other options have
+ /// different meaning if combined with this option, although their
+ /// use may not be possible via the `reboot()` call. See `ddb(4)` for
+ /// more information.
+ RB_KDB;
+ /// Normally, the disks are sync'd (see `sync(8)`) before the
+ /// processor is halted or rebooted. This option may be useful
+ /// if file system changes have been made manually or if the
+ /// processor is on fire.
+ RB_NOSYNC;
+ /// Normally, the reboot procedure involves an automatic disk
+ /// consistency check and then multi-user operations. `RB_SINGLE`
+ /// prevents this, booting the system with a single-user shell on
+ /// the console. `RB_SINGLE` is actually interpreted by the `init(8)`
+ /// program in the newly booted system.
+ ///
+ /// When no options are given (i.e., `RB_AUTOBOOT` is used), the
+ /// system is rebooted from file /bsd in the root file system of
+ /// unit 0 of a disk chosen in a processor specific way. An automatic
+ /// consistency check of the disks is normally performed (see `fsck(8)`).
+ RB_SINGLE;
+ /// Initially invoke the `userconf(4)` facility when the system
+ /// starts up again, if it has been compiled into the kernel
+ /// that is loaded.
+ #[cfg(target_os = "netbsd")]
+ RB_USERCONF;
+ /// Don't update the hardware clock from the system clock, presumably
+ /// because the system clock is suspect.
+ #[cfg(target_os = "openbsd")]
+ RB_TIMEBAD;
+ }
+ }
+
+ /// Reboot system or halt processor
+ ///
+ /// For more information, see the man pages:
+ ///
+ /// * [NetBSD](https://man.netbsd.org/reboot.2)
+ /// * [OpenBSD](https://man.openbsd.org/reboot.2)
+ #[cfg(netbsdlike)]
+ pub fn reboot(how: RebootMode) -> Result<Infallible> {
+ #[cfg(target_os = "openbsd")]
+ unsafe { libc::reboot(how.bits()) };
+ #[cfg(target_os = "netbsd")]
+ unsafe { libc::reboot(how.bits(), std::ptr::null_mut()) };
+
+ Err(Errno::last())
+ }
+ }
}
+
diff --git a/third_party/rust/nix/src/sys/resource.rs b/third_party/rust/nix/src/sys/resource.rs
index f42d32e3ca..71315072d4 100644
--- a/third_party/rust/nix/src/sys/resource.rs
+++ b/third_party/rust/nix/src/sys/resource.rs
@@ -10,16 +10,14 @@ pub use libc::RLIM_INFINITY;
use std::mem;
cfg_if! {
- if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
+ if #[cfg(any(
+ all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
+ target_os = "hurd"
+ ))]{
use libc::{__rlimit_resource_t, rlimit};
} else if #[cfg(any(
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "macos",
- target_os = "ios",
+ bsd,
target_os = "android",
- target_os = "dragonfly",
target_os = "aix",
all(target_os = "linux", not(target_env = "gnu"))
))]{
@@ -43,22 +41,19 @@ libc_enum! {
//
// https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
// https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
- #[cfg_attr(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), repr(u32))]
#[cfg_attr(any(
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "macos",
- target_os = "ios",
+ all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
+ target_os = "hurd"
+ ), repr(u32))]
+ #[cfg_attr(any(
+ bsd,
target_os = "android",
- target_os = "dragonfly",
target_os = "aix",
all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
), repr(i32))]
#[non_exhaustive]
pub enum Resource {
- #[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(any(target_os = "freebsd", netbsdlike)))]
/// The maximum amount (in bytes) of virtual memory the process is
/// allowed to map.
RLIMIT_AS,
@@ -77,102 +72,78 @@ libc_enum! {
RLIMIT_STACK,
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The maximum number of kqueues this user id is allowed to create.
RLIMIT_KQUEUES,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
/// A limit on the combined number of flock locks and fcntl leases that
/// this process may establish.
RLIMIT_LOCKS,
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "linux",
- target_os = "netbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "freebsd", netbsdlike))]
/// The maximum size (in bytes) which a process may lock into memory
/// using the mlock(2) system call.
RLIMIT_MEMLOCK,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
/// A limit on the number of bytes that can be allocated for POSIX
/// message queues for the real user ID of the calling process.
RLIMIT_MSGQUEUE,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
/// A ceiling to which the process's nice value can be raised using
/// setpriority or nice.
RLIMIT_NICE,
#[cfg(any(
- target_os = "android",
+ linux_android,
target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "linux",
+ netbsdlike,
target_os = "aix",
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The maximum number of simultaneous processes for this user id.
RLIMIT_NPROC,
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The maximum number of pseudo-terminals this user id is allowed to
/// create.
RLIMIT_NPTS,
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "linux",
+ netbsdlike,
target_os = "aix",
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// When there is memory pressure and swap is available, prioritize
/// eviction of a process' resident pages beyond this amount (in bytes).
RLIMIT_RSS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
/// A ceiling on the real-time priority that may be set for this process
/// using sched_setscheduler and sched_set‐ param.
RLIMIT_RTPRIO,
#[cfg(any(target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// A limit (in microseconds) on the amount of CPU time that a process
/// scheduled under a real-time scheduling policy may con‐ sume without
/// making a blocking system call.
RLIMIT_RTTIME,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
/// A limit on the number of signals that may be queued for the real
/// user ID of the calling process.
RLIMIT_SIGPENDING,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
/// The maximum size (in bytes) of socket buffer usage for this user.
RLIMIT_SBSIZE,
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The maximum size (in bytes) of the swap space that may be reserved
/// or used by all of this user id's processes.
RLIMIT_SWAP,
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// An alias for RLIMIT_AS.
RLIMIT_VMEM,
}
@@ -206,7 +177,10 @@ pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
cfg_if! {
- if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
+ if #[cfg(any(
+ all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
+ target_os = "hurd"
+ ))] {
let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
} else {
let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
@@ -259,7 +233,10 @@ pub fn setrlimit(
rlim_max: hard_limit,
};
cfg_if! {
- if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
+ if #[cfg(any(
+ all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
+ target_os = "hurd",
+ ))]{
let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
}else{
let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
@@ -281,7 +258,6 @@ libc_enum! {
RUSAGE_CHILDREN,
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Resource usage for the calling thread.
RUSAGE_THREAD,
}
@@ -420,28 +396,3 @@ pub fn getrusage(who: UsageWho) -> Result<Usage> {
Errno::result(res).map(|_| Usage(rusage.assume_init()))
}
}
-
-#[cfg(test)]
-mod test {
- use super::{getrusage, UsageWho};
-
- #[test]
- pub fn test_self_cpu_time() {
- // Make sure some CPU time is used.
- let mut numbers: Vec<i32> = (1..1_000_000).collect();
- numbers.iter_mut().for_each(|item| *item *= 2);
-
- // FIXME: this is here to help ensure the compiler does not optimize the whole
- // thing away. Replace the assert with test::black_box once stabilized.
- assert_eq!(numbers[100..200].iter().sum::<i32>(), 30_100);
-
- let usage = getrusage(UsageWho::RUSAGE_SELF)
- .expect("Failed to call getrusage for SELF");
- let rusage = usage.as_ref();
-
- let user = usage.user_time();
- assert!(user.tv_sec() > 0 || user.tv_usec() > 0);
- assert_eq!(user.tv_sec(), rusage.ru_utime.tv_sec);
- assert_eq!(user.tv_usec(), rusage.ru_utime.tv_usec);
- }
-}
diff --git a/third_party/rust/nix/src/sys/select.rs b/third_party/rust/nix/src/sys/select.rs
index 0e2193b130..64a8e258cf 100644
--- a/third_party/rust/nix/src/sys/select.rs
+++ b/third_party/rust/nix/src/sys/select.rs
@@ -7,7 +7,7 @@ use std::convert::TryFrom;
use std::iter::FusedIterator;
use std::mem;
use std::ops::Range;
-use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
+use std::os::unix::io::{AsRawFd, BorrowedFd, RawFd};
use std::ptr::{null, null_mut};
pub use libc::FD_SETSIZE;
@@ -41,21 +41,21 @@ impl<'fd> FdSet<'fd> {
}
/// Add a file descriptor to an `FdSet`
- pub fn insert<Fd: AsFd>(&mut self, fd: &'fd Fd) {
- assert_fd_valid(fd.as_fd().as_raw_fd());
- unsafe { libc::FD_SET(fd.as_fd().as_raw_fd(), &mut self.set) };
+ pub fn insert(&mut self, fd: BorrowedFd<'fd>) {
+ assert_fd_valid(fd.as_raw_fd());
+ unsafe { libc::FD_SET(fd.as_raw_fd(), &mut self.set) };
}
/// Remove a file descriptor from an `FdSet`
- pub fn remove<Fd: AsFd>(&mut self, fd: &'fd Fd) {
- assert_fd_valid(fd.as_fd().as_raw_fd());
- unsafe { libc::FD_CLR(fd.as_fd().as_raw_fd(), &mut self.set) };
+ pub fn remove(&mut self, fd: BorrowedFd<'fd>) {
+ assert_fd_valid(fd.as_raw_fd());
+ unsafe { libc::FD_CLR(fd.as_raw_fd(), &mut self.set) };
}
/// Test an `FdSet` for the presence of a certain file descriptor.
- pub fn contains<Fd: AsFd>(&self, fd: &'fd Fd) -> bool {
- assert_fd_valid(fd.as_fd().as_raw_fd());
- unsafe { libc::FD_ISSET(fd.as_fd().as_raw_fd(), &self.set) }
+ pub fn contains(&self, fd: BorrowedFd<'fd>) -> bool {
+ assert_fd_valid(fd.as_raw_fd());
+ unsafe { libc::FD_ISSET(fd.as_raw_fd(), &self.set) }
}
/// Remove all file descriptors from this `FdSet`.
@@ -77,8 +77,8 @@ impl<'fd> FdSet<'fd> {
/// let fd_four = unsafe {BorrowedFd::borrow_raw(4)};
/// let fd_nine = unsafe {BorrowedFd::borrow_raw(9)};
/// let mut set = FdSet::new();
- /// set.insert(&fd_four);
- /// set.insert(&fd_nine);
+ /// set.insert(fd_four);
+ /// set.insert(fd_nine);
/// assert_eq!(set.highest().map(|borrowed_fd|borrowed_fd.as_raw_fd()), Some(9));
/// ```
///
@@ -101,8 +101,8 @@ impl<'fd> FdSet<'fd> {
/// let mut set = FdSet::new();
/// let fd_four = unsafe {BorrowedFd::borrow_raw(4)};
/// let fd_nine = unsafe {BorrowedFd::borrow_raw(9)};
- /// set.insert(&fd_four);
- /// set.insert(&fd_nine);
+ /// set.insert(fd_four);
+ /// set.insert(fd_nine);
/// let fds: Vec<RawFd> = set.fds(None).map(|borrowed_fd|borrowed_fd.as_raw_fd()).collect();
/// assert_eq!(fds, vec![4, 9]);
/// ```
@@ -134,7 +134,7 @@ impl<'a, 'fd> Iterator for Fds<'a, 'fd> {
fn next(&mut self) -> Option<Self::Item> {
for i in &mut self.range {
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
- if self.set.contains(&borrowed_i) {
+ if self.set.contains(borrowed_i) {
return Some(borrowed_i);
}
}
@@ -153,7 +153,7 @@ impl<'a, 'fd> DoubleEndedIterator for Fds<'a, 'fd> {
fn next_back(&mut self) -> Option<BorrowedFd<'fd>> {
while let Some(i) = self.range.next_back() {
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
- if self.set.contains(&borrowed_i) {
+ if self.set.contains(borrowed_i) {
return Some(borrowed_i);
}
}
@@ -317,238 +317,3 @@ where
Errno::result(res)
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::sys::time::{TimeVal, TimeValLike};
- use crate::unistd::{close, pipe, write};
- use std::os::unix::io::{FromRawFd, OwnedFd, RawFd};
-
- #[test]
- fn fdset_insert() {
- let mut fd_set = FdSet::new();
-
- for i in 0..FD_SETSIZE {
- let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
- assert!(!fd_set.contains(&borrowed_i));
- }
-
- let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
- fd_set.insert(&fd_seven);
-
- assert!(fd_set.contains(&fd_seven));
- }
-
- #[test]
- fn fdset_remove() {
- let mut fd_set = FdSet::new();
-
- for i in 0..FD_SETSIZE {
- let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
- assert!(!fd_set.contains(&borrowed_i));
- }
-
- let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
- fd_set.insert(&fd_seven);
- fd_set.remove(&fd_seven);
-
- for i in 0..FD_SETSIZE {
- let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
- assert!(!fd_set.contains(&borrowed_i));
- }
- }
-
- #[test]
- #[allow(non_snake_case)]
- fn fdset_clear() {
- let mut fd_set = FdSet::new();
- let fd_one = unsafe { BorrowedFd::borrow_raw(1) };
- let fd_FD_SETSIZE_devided_by_two =
- unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) };
- let fd_FD_SETSIZE_minus_one =
- unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) };
- fd_set.insert(&fd_one);
- fd_set.insert(&fd_FD_SETSIZE_devided_by_two);
- fd_set.insert(&fd_FD_SETSIZE_minus_one);
-
- fd_set.clear();
-
- for i in 0..FD_SETSIZE {
- let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
- assert!(!fd_set.contains(&borrowed_i));
- }
- }
-
- #[test]
- fn fdset_highest() {
- let mut set = FdSet::new();
- assert_eq!(
- set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
- None
- );
- let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
- let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
- set.insert(&fd_zero);
- assert_eq!(
- set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
- Some(0)
- );
- set.insert(&fd_ninety);
- assert_eq!(
- set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
- Some(90)
- );
- set.remove(&fd_zero);
- assert_eq!(
- set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
- Some(90)
- );
- set.remove(&fd_ninety);
- assert_eq!(
- set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
- None
- );
-
- let fd_four = unsafe { BorrowedFd::borrow_raw(4) };
- let fd_five = unsafe { BorrowedFd::borrow_raw(5) };
- let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
- set.insert(&fd_four);
- set.insert(&fd_five);
- set.insert(&fd_seven);
- assert_eq!(
- set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
- Some(7)
- );
- }
-
- #[test]
- fn fdset_fds() {
- let mut set = FdSet::new();
- let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
- let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
- assert_eq!(
- set.fds(None)
- .map(|borrowed_fd| borrowed_fd.as_raw_fd())
- .collect::<Vec<_>>(),
- vec![]
- );
- set.insert(&fd_zero);
- assert_eq!(
- set.fds(None)
- .map(|borrowed_fd| borrowed_fd.as_raw_fd())
- .collect::<Vec<_>>(),
- vec![0]
- );
- set.insert(&fd_ninety);
- assert_eq!(
- set.fds(None)
- .map(|borrowed_fd| borrowed_fd.as_raw_fd())
- .collect::<Vec<_>>(),
- vec![0, 90]
- );
-
- // highest limit
- assert_eq!(
- set.fds(Some(89))
- .map(|borrowed_fd| borrowed_fd.as_raw_fd())
- .collect::<Vec<_>>(),
- vec![0]
- );
- assert_eq!(
- set.fds(Some(90))
- .map(|borrowed_fd| borrowed_fd.as_raw_fd())
- .collect::<Vec<_>>(),
- vec![0, 90]
- );
- }
-
- #[test]
- fn test_select() {
- let (r1, w1) = pipe().unwrap();
- let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
- let w1 = unsafe { OwnedFd::from_raw_fd(w1) };
- let (r2, _w2) = pipe().unwrap();
- let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
-
- write(w1.as_raw_fd(), b"hi!").unwrap();
- let mut fd_set = FdSet::new();
- fd_set.insert(&r1);
- fd_set.insert(&r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(
- 1,
- select(None, &mut fd_set, None, None, &mut timeout).unwrap()
- );
- assert!(fd_set.contains(&r1));
- assert!(!fd_set.contains(&r2));
- close(_w2).unwrap();
- }
-
- #[test]
- fn test_select_nfds() {
- let (r1, w1) = pipe().unwrap();
- let (r2, _w2) = pipe().unwrap();
- let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
- let w1 = unsafe { OwnedFd::from_raw_fd(w1) };
- let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
-
- write(w1.as_raw_fd(), b"hi!").unwrap();
- let mut fd_set = FdSet::new();
- fd_set.insert(&r1);
- fd_set.insert(&r2);
-
- let mut timeout = TimeVal::seconds(10);
- {
- assert_eq!(
- 1,
- select(
- Some(
- fd_set
- .highest()
- .map(|borrowed_fd| borrowed_fd.as_raw_fd())
- .unwrap()
- + 1
- ),
- &mut fd_set,
- None,
- None,
- &mut timeout
- )
- .unwrap()
- );
- }
- assert!(fd_set.contains(&r1));
- assert!(!fd_set.contains(&r2));
- close(_w2).unwrap();
- }
-
- #[test]
- fn test_select_nfds2() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
- let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
- let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
- let mut fd_set = FdSet::new();
- fd_set.insert(&r1);
- fd_set.insert(&r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(
- 1,
- select(
- std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1,
- &mut fd_set,
- None,
- None,
- &mut timeout
- )
- .unwrap()
- );
- assert!(fd_set.contains(&r1));
- assert!(!fd_set.contains(&r2));
- close(_w2).unwrap();
- }
-}
diff --git a/third_party/rust/nix/src/sys/sendfile.rs b/third_party/rust/nix/src/sys/sendfile.rs
index 9f3c333f97..d7452edd7c 100644
--- a/third_party/rust/nix/src/sys/sendfile.rs
+++ b/third_party/rust/nix/src/sys/sendfile.rs
@@ -20,9 +20,9 @@ use crate::Result;
///
/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket.
///
-/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html) for Linux,
+/// see [the sendfile(2) man page.](https://docs.oracle.com/cd/E88353_01/html/E37843/sendfile-3c.html) for Solaris.
+#[cfg(any(linux_android, solarish))]
pub fn sendfile<F1: AsFd, F2: AsFd>(
out_fd: F1,
in_fd: F2,
@@ -56,7 +56,6 @@ pub fn sendfile<F1: AsFd, F2: AsFd>(
///
/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn sendfile64<F1: AsFd, F2: AsFd>(
out_fd: F1,
in_fd: F2,
@@ -78,46 +77,82 @@ pub fn sendfile64<F1: AsFd, F2: AsFd>(
}
cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))] {
+ if #[cfg(any(freebsdlike, apple_targets))] {
use std::io::IoSlice;
#[derive(Clone, Debug)]
- struct SendfileHeaderTrailer<'a>(
- libc::sf_hdtr,
- Option<Vec<IoSlice<'a>>>,
- Option<Vec<IoSlice<'a>>>,
- );
+ struct SendfileHeaderTrailer<'a> {
+ raw: libc::sf_hdtr,
+ _headers: Option<Vec<IoSlice<'a>>>,
+ _trailers: Option<Vec<IoSlice<'a>>>,
+ }
impl<'a> SendfileHeaderTrailer<'a> {
fn new(
headers: Option<&'a [&'a [u8]]>,
trailers: Option<&'a [&'a [u8]]>
) -> SendfileHeaderTrailer<'a> {
- let header_iovecs: Option<Vec<IoSlice<'_>>> =
+ let mut header_iovecs: Option<Vec<IoSlice<'_>>> =
headers.map(|s| s.iter().map(|b| IoSlice::new(b)).collect());
- let trailer_iovecs: Option<Vec<IoSlice<'_>>> =
+ let mut trailer_iovecs: Option<Vec<IoSlice<'_>>> =
trailers.map(|s| s.iter().map(|b| IoSlice::new(b)).collect());
- SendfileHeaderTrailer(
- libc::sf_hdtr {
+
+ SendfileHeaderTrailer {
+ raw: libc::sf_hdtr {
headers: {
header_iovecs
- .as_ref()
- .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
+ .as_mut()
+ .map_or(ptr::null_mut(), |v| v.as_mut_ptr())
+ .cast()
},
hdr_cnt: header_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32,
trailers: {
trailer_iovecs
- .as_ref()
- .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
+ .as_mut()
+ .map_or(ptr::null_mut(), |v| v.as_mut_ptr())
+ .cast()
},
trl_cnt: trailer_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32
},
- header_iovecs,
- trailer_iovecs,
- )
+ _headers: header_iovecs,
+ _trailers: trailer_iovecs,
+ }
+ }
+ }
+ } else if #[cfg(solarish)] {
+ use std::os::unix::io::BorrowedFd;
+ use std::marker::PhantomData;
+
+ #[derive(Debug, Copy, Clone)]
+ /// Mapping of the raw C sendfilevec_t struct
+ pub struct SendfileVec<'fd> {
+ raw: libc::sendfilevec_t,
+ phantom: PhantomData<BorrowedFd<'fd>>
+ }
+
+ impl<'fd> SendfileVec<'fd> {
+ /// initialises SendfileVec to send data directly from the process's address space
+ /// same in C with sfv_fd set to SFV_FD_SELF.
+ pub fn newself(
+ off: off_t,
+ len: usize
+ ) -> Self {
+ Self{raw: libc::sendfilevec_t{sfv_fd: libc::SFV_FD_SELF, sfv_flag: 0, sfv_off: off, sfv_len: len}, phantom: PhantomData}
+ }
+
+ /// initialises SendfileVec to send data from `fd`.
+ pub fn new(
+ fd: BorrowedFd<'fd>,
+ off: off_t,
+ len: usize
+ ) -> SendfileVec<'fd> {
+ Self{raw: libc::sendfilevec_t{sfv_fd: fd.as_raw_fd(), sfv_flag: 0, sfv_off:off, sfv_len: len}, phantom: PhantomData}
+ }
+ }
+
+ impl From<SendfileVec<'_>> for libc::sendfilevec_t {
+ fn from<'fd>(vec: SendfileVec) -> libc::sendfilevec_t {
+ vec.raw
}
}
}
@@ -187,7 +222,7 @@ cfg_if! {
let flags: u32 = (ra32 << 16) | (flags.bits() as u32);
let mut bytes_sent: off_t = 0;
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
+ let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.raw as *const libc::sf_hdtr);
let return_code = unsafe {
libc::sendfile(in_fd.as_fd().as_raw_fd(),
out_sock.as_fd().as_raw_fd(),
@@ -230,7 +265,7 @@ cfg_if! {
) -> (Result<()>, off_t) {
let mut bytes_sent: off_t = 0;
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
+ let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.raw as *const libc::sf_hdtr);
let return_code = unsafe {
libc::sendfile(in_fd.as_fd().as_raw_fd(),
out_sock.as_fd().as_raw_fd(),
@@ -242,7 +277,7 @@ cfg_if! {
};
(Errno::result(return_code).and(Ok(())), bytes_sent)
}
- } else if #[cfg(any(target_os = "ios", target_os = "macos"))] {
+ } else if #[cfg(apple_targets)] {
/// Read bytes from `in_fd` starting at `offset` and write up to `count` bytes to
/// `out_sock`.
///
@@ -276,7 +311,7 @@ cfg_if! {
) -> (Result<()>, off_t) {
let mut len = count.unwrap_or(0);
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
+ let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.raw as *const libc::sf_hdtr);
let return_code = unsafe {
libc::sendfile(in_fd.as_fd().as_raw_fd(),
out_sock.as_fd().as_raw_fd(),
@@ -287,5 +322,30 @@ cfg_if! {
};
(Errno::result(return_code).and(Ok(())), len)
}
+ } else if #[cfg(solarish)] {
+ /// Write data from the vec arrays to `out_sock` and returns a `Result` and a
+ /// count of bytes written.
+ ///
+ /// Each `SendfileVec` set needs to be instantiated either with `SendfileVec::new` or
+ /// `SendfileVec::newself`.
+ ///
+ /// The former allows to send data from a file descriptor through `fd`,
+ /// from an offset `off` and for a given amount of data `len`.
+ ///
+ /// The latter allows to send data from the process's address space, from an offset `off`
+ /// and for a given amount of data `len`.
+ ///
+ /// For more information, see
+ /// [the sendfilev(3) man page.](https://illumos.org/man/3EXT/sendfilev)
+ pub fn sendfilev<F: AsFd>(
+ out_sock: F,
+ vec: &[SendfileVec]
+ ) -> (Result<()>, usize) {
+ let mut len = 0usize;
+ let return_code = unsafe {
+ libc::sendfilev(out_sock.as_fd().as_raw_fd(), vec.as_ptr() as *const libc::sendfilevec_t, vec.len() as i32, &mut len)
+ };
+ (Errno::result(return_code).and(Ok(())), len)
+ }
}
}
diff --git a/third_party/rust/nix/src/sys/signal.rs b/third_party/rust/nix/src/sys/signal.rs
index c946e4a0b1..c9b593d0db 100644
--- a/third_party/rust/nix/src/sys/signal.rs
+++ b/third_party/rust/nix/src/sys/signal.rs
@@ -7,14 +7,17 @@ use crate::errno::Errno;
use crate::{Error, Result};
use cfg_if::cfg_if;
use std::fmt;
+use std::hash::{Hash, Hasher};
use std::mem;
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+use std::ops::BitOr;
+#[cfg(freebsdlike)]
use std::os::unix::io::RawFd;
use std::ptr;
use std::str::FromStr;
#[cfg(not(any(
target_os = "fuchsia",
+ target_os = "hurd",
target_os = "openbsd",
target_os = "redox"
)))]
@@ -63,9 +66,12 @@ libc_enum! {
/// Software termination signal from kill
SIGTERM,
/// Stack fault (obsolete)
- #[cfg(all(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"),
- not(any(target_arch = "mips", target_arch = "mips64",
+ #[cfg(all(any(linux_android, target_os = "emscripten",
+ target_os = "fuchsia"),
+ not(any(target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "sparc64"))))]
SIGSTKFLT,
/// To parent on child stop or exit
@@ -94,27 +100,21 @@ libc_enum! {
SIGWINCH,
/// Input/output possible signal
#[cfg(not(target_os = "haiku"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SIGIO,
- #[cfg(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "emscripten",
+ target_os = "fuchsia", target_os = "aix"))]
/// Power failure imminent.
SIGPWR,
/// Bad system call
SIGSYS,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
+ #[cfg(not(any(linux_android, target_os = "emscripten",
+ target_os = "fuchsia",
target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Emulator trap
SIGEMT,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox", target_os = "haiku",
- target_os = "aix")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(any(linux_android, target_os = "emscripten",
+ target_os = "fuchsia", target_os = "redox",
+ target_os = "haiku", target_os = "aix")))]
/// Information request
SIGINFO,
}
@@ -143,14 +143,15 @@ impl FromStr for Signal {
"SIGTERM" => Signal::SIGTERM,
#[cfg(all(
any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "linux"
),
not(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "sparc64"
))
))]
@@ -170,27 +171,24 @@ impl FromStr for Signal {
#[cfg(not(target_os = "haiku"))]
"SIGIO" => Signal::SIGIO,
#[cfg(any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "linux"
))]
"SIGPWR" => Signal::SIGPWR,
"SIGSYS" => Signal::SIGSYS,
#[cfg(not(any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "linux",
target_os = "redox",
target_os = "haiku"
)))]
"SIGEMT" => Signal::SIGEMT,
#[cfg(not(any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "linux",
target_os = "redox",
target_os = "aix",
target_os = "haiku"
@@ -227,14 +225,15 @@ impl Signal {
Signal::SIGTERM => "SIGTERM",
#[cfg(all(
any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "linux"
),
not(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "sparc64"
))
))]
@@ -254,28 +253,25 @@ impl Signal {
#[cfg(not(target_os = "haiku"))]
Signal::SIGIO => "SIGIO",
#[cfg(any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "aix",
- target_os = "linux"
))]
Signal::SIGPWR => "SIGPWR",
Signal::SIGSYS => "SIGSYS",
#[cfg(not(any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "linux",
target_os = "redox",
target_os = "haiku"
)))]
Signal::SIGEMT => "SIGEMT",
#[cfg(not(any(
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "linux",
target_os = "redox",
target_os = "aix",
target_os = "haiku"
@@ -319,15 +315,12 @@ const SIGNALS: [Signal; 28] = [
SIGPROF, SIGWINCH, SIGSYS,
];
#[cfg(all(
- any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia"
- ),
+ any(linux_android, target_os = "emscripten", target_os = "fuchsia"),
not(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "sparc64"
))
))]
@@ -339,13 +332,14 @@ const SIGNALS: [Signal; 31] = [
SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
];
#[cfg(all(
+ any(linux_android, target_os = "emscripten", target_os = "fuchsia"),
any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia"
- ),
- any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6",
+ target_arch = "sparc64"
+ )
))]
#[cfg(feature = "signal")]
const SIGNALS: [Signal; 30] = [
@@ -363,8 +357,7 @@ const SIGNALS: [Signal; 30] = [
SIGVTALRM, SIGPROF, SIGXCPU, SIGXFSZ, SIGTRAP,
];
#[cfg(not(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "fuchsia",
target_os = "emscripten",
target_os = "aix",
@@ -439,6 +432,7 @@ libc_bitflags! {
SA_NOCLDSTOP;
/// When catching a [`Signal::SIGCHLD`] signal, the system will not
/// create zombie processes when children of the calling process exit.
+ #[cfg(not(target_os = "hurd"))]
SA_NOCLDWAIT;
/// Further occurrences of the delivered signal are not masked during
/// the execution of the handler.
@@ -486,7 +480,7 @@ use std::iter::IntoIterator;
// We are using `transparent` here to be super sure that `SigSet`
// is represented exactly like the `sigset_t` struct from C.
#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq)]
pub struct SigSet {
sigset: libc::sigset_t
}
@@ -577,7 +571,6 @@ impl SigSet {
/// Suspends execution of the calling thread until one of the signals in the
/// signal mask becomes pending, and returns the accepted signal.
#[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn wait(&self) -> Result<Signal> {
use std::convert::TryFrom;
@@ -589,6 +582,35 @@ impl SigSet {
})
}
+ /// Wait for a signal
+ ///
+ /// # Return value
+ /// If `sigsuspend(2)` is interrupted (EINTR), this function returns `Ok`.
+ /// If `sigsuspend(2)` set other error, this function returns `Err`.
+ ///
+ /// For more information see the
+ /// [`sigsuspend(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html).
+ #[cfg(any(
+ bsd,
+ linux_android,
+ solarish,
+ target_os = "haiku",
+ target_os = "hurd",
+ target_os = "aix",
+ target_os = "fushsia"
+ ))]
+ #[doc(alias("sigsuspend"))]
+ pub fn suspend(&self) -> Result<()> {
+ let res = unsafe {
+ libc::sigsuspend(&self.sigset as *const libc::sigset_t)
+ };
+ match Errno::result(res).map(drop) {
+ Err(Errno::EINTR) => Ok(()),
+ Err(e) => Err(e),
+ Ok(_) => unreachable!("because this syscall always returns -1 if returns"),
+ }
+ }
+
/// Converts a `libc::sigset_t` object to a [`SigSet`] without checking whether the
/// `libc::sigset_t` is already initialized.
///
@@ -603,6 +625,42 @@ impl SigSet {
}
}
+impl From<Signal> for SigSet {
+ fn from(signal: Signal) -> SigSet {
+ let mut sigset = SigSet::empty();
+ sigset.add(signal);
+ sigset
+ }
+}
+
+impl BitOr for Signal {
+ type Output = SigSet;
+
+ fn bitor(self, rhs: Self) -> Self::Output {
+ let mut sigset = SigSet::empty();
+ sigset.add(self);
+ sigset.add(rhs);
+ sigset
+ }
+}
+
+impl BitOr<Signal> for SigSet {
+ type Output = SigSet;
+
+ fn bitor(mut self, rhs: Signal) -> Self::Output {
+ self.add(rhs);
+ self
+ }
+}
+
+impl BitOr for SigSet {
+ type Output = Self;
+
+ fn bitor(self, rhs: Self) -> Self::Output {
+ self.iter().chain(rhs.iter()).collect()
+ }
+}
+
impl AsRef<libc::sigset_t> for SigSet {
fn as_ref(&self) -> &libc::sigset_t {
&self.sigset
@@ -628,6 +686,27 @@ impl FromIterator<Signal> for SigSet {
}
}
+impl PartialEq for SigSet {
+ fn eq(&self, other: &Self) -> bool {
+ for signal in Signal::iterator() {
+ if self.contains(signal) != other.contains(signal) {
+ return false;
+ }
+ }
+ true
+ }
+}
+
+impl Hash for SigSet {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ for signal in Signal::iterator() {
+ if self.contains(signal) {
+ signal.hash(state);
+ }
+ }
+ }
+}
+
/// Iterator for a [`SigSet`].
///
/// Call [`SigSet::iter`] to create an iterator.
@@ -670,7 +749,6 @@ pub enum SigHandler {
/// Use the given signal-catching function, which takes in the signal, information about how
/// the signal was generated, and a pointer to the threads `ucontext_t`.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
}
@@ -689,23 +767,27 @@ impl SigAction {
pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
#[cfg(not(target_os = "aix"))]
unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
- (*p).sa_sigaction = match handler {
- SigHandler::SigDfl => libc::SIG_DFL,
- SigHandler::SigIgn => libc::SIG_IGN,
- SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
- #[cfg(not(target_os = "redox"))]
- SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
- };
+ unsafe {
+ (*p).sa_sigaction = match handler {
+ SigHandler::SigDfl => libc::SIG_DFL,
+ SigHandler::SigIgn => libc::SIG_IGN,
+ SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
+ #[cfg(not(target_os = "redox"))]
+ SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
+ };
+ }
}
#[cfg(target_os = "aix")]
unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
- (*p).sa_union.__su_sigaction = match handler {
- SigHandler::SigDfl => mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL),
- SigHandler::SigIgn => mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN),
- SigHandler::Handler(f) => mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f),
- SigHandler::SigAction(f) => f,
- };
+ unsafe {
+ (*p).sa_union.__su_sigaction = match handler {
+ SigHandler::SigDfl => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL) },
+ SigHandler::SigIgn => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN) },
+ SigHandler::Handler(f) => unsafe { mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f) },
+ SigHandler::SigAction(f) => f,
+ };
+ }
}
let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
@@ -810,11 +892,11 @@ impl SigAction {
pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
- let res = libc::sigaction(signal as libc::c_int,
+ let res = unsafe { libc::sigaction(signal as libc::c_int,
&sigaction.sigaction as *const libc::sigaction,
- oldact.as_mut_ptr());
+ oldact.as_mut_ptr()) };
- Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
+ Errno::result(res).map(|_| SigAction { sigaction: unsafe { oldact.assume_init() } })
}
/// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
@@ -872,9 +954,9 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi
pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
let signal = signal as libc::c_int;
let res = match handler {
- SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
- SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
- SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
+ SigHandler::SigDfl => unsafe { libc::signal(signal, libc::SIG_DFL) },
+ SigHandler::SigIgn => unsafe { libc::signal(signal, libc::SIG_IGN) },
+ SigHandler::Handler(handler) => unsafe { libc::signal(signal, handler as libc::sighandler_t) },
#[cfg(not(target_os = "redox"))]
SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
};
@@ -883,9 +965,7 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
libc::SIG_DFL => SigHandler::SigDfl,
libc::SIG_IGN => SigHandler::SigIgn,
p => SigHandler::Handler(
- *(&p as *const usize
- as *const extern fn(libc::c_int))
- as extern fn(libc::c_int)),
+ unsafe { *(&p as *const usize as *const extern fn(libc::c_int)) } as extern fn(libc::c_int)),
}
})
}
@@ -1019,14 +1099,14 @@ feature! {
#[cfg(target_os = "freebsd")]
pub type type_of_thread_id = libc::lwpid_t;
/// Identifies a thread for [`SigevNotify::SigevThreadId`]
-#[cfg(any(target_env = "gnu", target_env = "uclibc"))]
+#[cfg(all(not(target_os = "hurd"), any(target_env = "gnu", target_env = "uclibc")))]
pub type type_of_thread_id = libc::pid_t;
/// Specifies the notification method used by a [`SigEvent`]
// sigval is actually a union of a int and a void*. But it's never really used
// as a pointer, because neither libc nor the kernel ever dereference it. nix
// therefore presents it as an intptr_t, which is how kevent uses it.
-#[cfg(not(any(target_os = "fuchsia", target_os = "openbsd", target_os = "redox")))]
+#[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SigevNotify {
/// No notification will be delivered
@@ -1041,8 +1121,7 @@ pub enum SigevNotify {
},
// Note: SIGEV_THREAD is not implemented, but could be if desired.
/// Notify by delivering an event to a kqueue.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
SigevKevent {
/// File descriptor of the kqueue to notify.
kq: RawFd,
@@ -1051,7 +1130,6 @@ pub enum SigevNotify {
},
/// Notify by delivering an event to a kqueue, with optional event flags set
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
#[cfg(feature = "event")]
SigevKeventFlags {
/// File descriptor of the kqueue to notify.
@@ -1067,7 +1145,6 @@ pub enum SigevNotify {
target_env = "gnu",
target_env = "uclibc",
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SigevThreadId {
/// Signal to send
signal: Signal,
@@ -1082,10 +1159,10 @@ pub enum SigevNotify {
#[cfg(not(any(
target_os = "fuchsia",
+ target_os = "hurd",
target_os = "openbsd",
target_os = "redox"
)))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
mod sigevent {
feature! {
#![any(feature = "aio", feature = "signal")]
@@ -1251,7 +1328,7 @@ mod sigevent {
sev.sigev_signo = signal as libc::c_int;
sev.sigev_value.sival_ptr = si_value as *mut libc::c_void
},
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+ #[cfg(freebsdlike)]
SigevNotify::SigevKevent{kq, udata} => {
sev.sigev_notify = libc::SIGEV_KEVENT;
sev.sigev_signo = kq;
@@ -1331,227 +1408,3 @@ mod sigevent {
}
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- #[cfg(not(target_os = "redox"))]
- use std::thread;
-
- #[test]
- fn test_contains() {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- assert!(mask.contains(SIGUSR1));
- assert!(!mask.contains(SIGUSR2));
-
- let all = SigSet::all();
- assert!(all.contains(SIGUSR1));
- assert!(all.contains(SIGUSR2));
- }
-
- #[test]
- fn test_clear() {
- let mut set = SigSet::all();
- set.clear();
- for signal in Signal::iterator() {
- assert!(!set.contains(signal));
- }
- }
-
- #[test]
- fn test_from_str_round_trips() {
- for signal in Signal::iterator() {
- assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
- assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
- }
- }
-
- #[test]
- fn test_from_str_invalid_value() {
- let errval = Err(Errno::EINVAL);
- assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
- assert_eq!("kill".parse::<Signal>(), errval);
- assert_eq!("9".parse::<Signal>(), errval);
- }
-
- #[test]
- fn test_extend() {
- let mut one_signal = SigSet::empty();
- one_signal.add(SIGUSR1);
-
- let mut two_signals = SigSet::empty();
- two_signals.add(SIGUSR2);
- two_signals.extend(&one_signal);
-
- assert!(two_signals.contains(SIGUSR1));
- assert!(two_signals.contains(SIGUSR2));
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_set_mask() {
- thread::spawn(|| {
- let prev_mask = SigSet::thread_get_mask()
- .expect("Failed to get existing signal mask!");
-
- let mut test_mask = prev_mask;
- test_mask.add(SIGUSR1);
-
- test_mask.thread_set_mask().expect("assertion failed");
- let new_mask =
- SigSet::thread_get_mask().expect("Failed to get new mask!");
-
- assert!(new_mask.contains(SIGUSR1));
- assert!(!new_mask.contains(SIGUSR2));
-
- prev_mask
- .thread_set_mask()
- .expect("Failed to revert signal mask!");
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_block() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- mask.thread_block().expect("assertion failed");
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_unblock() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- mask.thread_unblock().expect("assertion failed");
-
- assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_swap() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
- mask.thread_block().unwrap();
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
-
- let mut mask2 = SigSet::empty();
- mask2.add(SIGUSR2);
-
- let oldmask =
- mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap();
-
- assert!(oldmask.contains(SIGUSR1));
- assert!(!oldmask.contains(SIGUSR2));
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
- })
- .join()
- .unwrap();
- }
-
- #[test]
- fn test_from_and_into_iterator() {
- let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
- let signals = sigset.into_iter().collect::<Vec<Signal>>();
- assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_sigaction() {
- thread::spawn(|| {
- extern "C" fn test_sigaction_handler(_: libc::c_int) {}
- extern "C" fn test_sigaction_action(
- _: libc::c_int,
- _: *mut libc::siginfo_t,
- _: *mut libc::c_void,
- ) {
- }
-
- let handler_sig = SigHandler::Handler(test_sigaction_handler);
-
- let flags =
- SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO;
-
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- let action_sig = SigAction::new(handler_sig, flags, mask);
-
- assert_eq!(
- action_sig.flags(),
- SaFlags::SA_ONSTACK | SaFlags::SA_RESTART
- );
- assert_eq!(action_sig.handler(), handler_sig);
-
- mask = action_sig.mask();
- assert!(mask.contains(SIGUSR1));
- assert!(!mask.contains(SIGUSR2));
-
- let handler_act = SigHandler::SigAction(test_sigaction_action);
- let action_act = SigAction::new(handler_act, flags, mask);
- assert_eq!(action_act.handler(), handler_act);
-
- let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
- assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
-
- let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
- assert_eq!(action_ign.handler(), SigHandler::SigIgn);
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_sigwait() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
- mask.add(SIGUSR2);
- mask.thread_block().unwrap();
-
- raise(SIGUSR1).unwrap();
- assert_eq!(mask.wait().unwrap(), SIGUSR1);
- })
- .join()
- .unwrap();
- }
-
- #[test]
- fn test_from_sigset_t_unchecked() {
- let src_set = SigSet::empty();
- let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
-
- for signal in Signal::iterator() {
- assert!(!set.contains(signal));
- }
-
- let src_set = SigSet::all();
- let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
-
- for signal in Signal::iterator() {
- assert!(set.contains(signal));
- }
- }
-}
diff --git a/third_party/rust/nix/src/sys/signalfd.rs b/third_party/rust/nix/src/sys/signalfd.rs
index 2b80ea643f..ccba774d1a 100644
--- a/third_party/rust/nix/src/sys/signalfd.rs
+++ b/third_party/rust/nix/src/sys/signalfd.rs
@@ -21,7 +21,7 @@ use crate::Result;
pub use libc::signalfd_siginfo as siginfo;
use std::mem;
-use std::os::unix::io::{AsRawFd, RawFd, FromRawFd, OwnedFd, AsFd, BorrowedFd};
+use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
libc_bitflags! {
pub struct SfdFlags: libc::c_int {
@@ -45,18 +45,23 @@ pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
///
/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
#[deprecated(since = "0.27.0", note = "Use SignalFd instead")]
-pub fn signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> {
+pub fn signalfd<F: AsFd>(
+ fd: Option<F>,
+ mask: &SigSet,
+ flags: SfdFlags,
+) -> Result<OwnedFd> {
_signalfd(fd, mask, flags)
}
-fn _signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> {
- let raw_fd = fd.map_or(-1, |x|x.as_fd().as_raw_fd());
+fn _signalfd<F: AsFd>(
+ fd: Option<F>,
+ mask: &SigSet,
+ flags: SfdFlags,
+) -> Result<OwnedFd> {
+ let raw_fd = fd.map_or(-1, |x| x.as_fd().as_raw_fd());
unsafe {
- Errno::result(libc::signalfd(
- raw_fd,
- mask.as_ref(),
- flags.bits(),
- )).map(|raw_fd|FromRawFd::from_raw_fd(raw_fd))
+ Errno::result(libc::signalfd(raw_fd, mask.as_ref(), flags.bits()))
+ .map(|raw_fd| FromRawFd::from_raw_fd(raw_fd))
}
}
@@ -101,7 +106,7 @@ impl SignalFd {
}
pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
- _signalfd(Some(self.0.as_fd()), mask, SfdFlags::empty()).map(drop)
+ self.update(mask, SfdFlags::empty())
}
pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
@@ -109,7 +114,7 @@ impl SignalFd {
let size = mem::size_of_val(&buffer);
let res = Errno::result(unsafe {
- libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr() as *mut libc::c_void, size)
+ libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr().cast(), size)
})
.map(|r| r as usize);
match res {
@@ -119,6 +124,14 @@ impl SignalFd {
Err(error) => Err(error),
}
}
+
+ fn update(&self, mask: &SigSet, flags: SfdFlags) -> Result<()> {
+ let raw_fd = self.0.as_raw_fd();
+ unsafe {
+ Errno::result(libc::signalfd(raw_fd, mask.as_ref(), flags.bits()))
+ .map(drop)
+ }
+ }
}
impl AsFd for SignalFd {
@@ -142,34 +155,3 @@ impl Iterator for SignalFd {
}
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn create_signalfd() {
- let mask = SigSet::empty();
- SignalFd::new(&mask).unwrap();
- }
-
- #[test]
- fn create_signalfd_with_opts() {
- let mask = SigSet::empty();
- SignalFd::with_flags(
- &mask,
- SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK,
- )
- .unwrap();
- }
-
- #[test]
- fn read_empty_signalfd() {
- let mask = SigSet::empty();
- let mut fd =
- SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
-
- let res = fd.read_signal();
- assert!(res.unwrap().is_none());
- }
-}
diff --git a/third_party/rust/nix/src/sys/socket/addr.rs b/third_party/rust/nix/src/sys/socket/addr.rs
index 1783531d49..f6800aa5d0 100644
--- a/third_party/rust/nix/src/sys/socket/addr.rs
+++ b/third_party/rust/nix/src/sys/socket/addr.rs
@@ -1,31 +1,22 @@
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd",
+ bsd,
+ linux_android,
+ solarish,
target_os = "haiku",
target_os = "fuchsia",
target_os = "aix",
))]
#[cfg(feature = "net")]
pub use self::datalink::LinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+#[cfg(any(linux_android, apple_targets))]
pub use self::vsock::VsockAddr;
use super::sa_family_t;
use crate::errno::Errno;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
-))]
+#[cfg(all(feature = "ioctl", apple_targets))]
use crate::sys::socket::addr::sys_control::SysControlAddr;
use crate::{NixPath, Result};
use cfg_if::cfg_if;
@@ -33,6 +24,7 @@ use memoffset::offset_of;
use std::convert::TryInto;
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
+use std::net::{Ipv4Addr, Ipv6Addr};
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::{fmt, mem, net, ptr, slice};
@@ -41,7 +33,7 @@ use std::{fmt, mem, net, ptr, slice};
#[cfg(feature = "net")]
pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
libc::in_addr {
- s_addr: u32::from_ne_bytes(addr.octets())
+ s_addr: u32::from_ne_bytes(addr.octets()),
}
}
@@ -49,7 +41,7 @@ pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
#[cfg(feature = "net")]
pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
libc::in6_addr {
- s6_addr: addr.octets()
+ s6_addr: addr.octets(),
}
}
@@ -71,346 +63,188 @@ pub enum AddressFamily {
/// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
Inet6 = libc::AF_INET6,
/// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Netlink = libc::AF_NETLINK,
/// Kernel interface for interacting with the routing table
- #[cfg(not(any(
- target_os = "redox",
- target_os = "linux",
- target_os = "android"
- )))]
+ #[cfg(not(any(linux_android, target_os = "redox")))]
Route = libc::PF_ROUTE,
/// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "illumos",
- target_os = "fuchsia",
- target_os = "solaris"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
Packet = libc::AF_PACKET,
/// KEXT Controls and Notifications
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
System = libc::AF_SYSTEM,
/// Amateur radio AX.25 protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Ax25 = libc::AF_AX25,
/// IPX - Novell protocols
#[cfg(not(any(target_os = "aix", target_os = "redox")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
Ipx = libc::AF_IPX,
/// AppleTalk
#[cfg(not(target_os = "redox"))]
AppleTalk = libc::AF_APPLETALK,
/// AX.25 packet layer protocol.
/// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetRom = libc::AF_NETROM,
/// Can't be used for creating sockets; mostly used for bridge
/// links in
/// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html)
/// protocol commands.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Bridge = libc::AF_BRIDGE,
/// Access to raw ATM PVCs
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AtmPvc = libc::AF_ATMPVC,
/// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
X25 = libc::AF_X25,
/// RATS (Radio Amateur Telecommunications Society) Open
/// Systems environment (ROSE) AX.25 packet layer protocol.
/// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Rose = libc::AF_ROSE,
/// DECet protocol sockets.
#[cfg(not(any(target_os = "haiku", target_os = "redox")))]
Decnet = libc::AF_DECnet,
/// Reserved for "802.2LLC project"; never used.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetBeui = libc::AF_NETBEUI,
/// This was a short-lived (between Linux 2.1.30 and
/// 2.1.99pre2) protocol family for firewall upcalls.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Security = libc::AF_SECURITY,
/// Key management protocol.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Key = libc::AF_KEY,
#[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Ash = libc::AF_ASH,
/// Acorn Econet protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Econet = libc::AF_ECONET,
/// Access to ATM Switched Virtual Circuits
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AtmSvc = libc::AF_ATMSVC,
/// Reliable Datagram Sockets (RDS) protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Rds = libc::AF_RDS,
/// IBM SNA
#[cfg(not(any(target_os = "haiku", target_os = "redox")))]
Sna = libc::AF_SNA,
/// Socket interface over IrDA
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Irda = libc::AF_IRDA,
/// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Pppox = libc::AF_PPPOX,
/// Legacy protocol for wide area network (WAN) connectivity that was used
/// by Sangoma WAN cards
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Wanpipe = libc::AF_WANPIPE,
/// Logical link control (IEEE 802.2 LLC) protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Llc = libc::AF_LLC,
/// InfiniBand native addressing
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
Ib = libc::AF_IB,
/// Multiprotocol Label Switching
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
Mpls = libc::AF_MPLS,
/// Controller Area Network automotive bus protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Can = libc::AF_CAN,
/// TIPC, "cluster domain sockets" protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Tipc = libc::AF_TIPC,
/// Bluetooth low-level socket protocol
#[cfg(not(any(
target_os = "aix",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "solaris",
+ solarish,
+ apple_targets,
+ target_os = "hurd",
target_os = "redox",
)))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
Bluetooth = libc::AF_BLUETOOTH,
/// IUCV (inter-user communication vehicle) z/VM protocol for
/// hypervisor-guest interaction
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Iucv = libc::AF_IUCV,
/// Rx, Andrew File System remote procedure call protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
RxRpc = libc::AF_RXRPC,
/// New "modular ISDN" driver interface protocol
#[cfg(not(any(
target_os = "aix",
- target_os = "illumos",
- target_os = "solaris",
+ solarish,
target_os = "haiku",
+ target_os = "hurd",
target_os = "redox",
)))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
Isdn = libc::AF_ISDN,
/// Nokia cellular modem IPC/RPC interface
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Phonet = libc::AF_PHONET,
/// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Ieee802154 = libc::AF_IEEE802154,
/// Ericsson's Communication CPU to Application CPU interface (CAIF)
/// protocol.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Caif = libc::AF_CAIF,
/// Interface to kernel crypto API
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Alg = libc::AF_ALG,
/// Near field communication
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
Nfc = libc::AF_NFC,
/// VMWare VSockets protocol for hypervisor-guest interaction.
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, apple_targets))]
Vsock = libc::AF_VSOCK,
/// ARPANet IMP addresses
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
ImpLink = libc::AF_IMPLINK,
/// PUP protocols, e.g. BSP
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Pup = libc::AF_PUP,
/// MIT CHAOS protocols
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Chaos = libc::AF_CHAOS,
/// Novell and Xerox protocol
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(apple_targets, netbsdlike))]
Ns = libc::AF_NS,
#[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Iso = libc::AF_ISO,
/// Bell Labs virtual circuit switch ?
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Datakit = libc::AF_DATAKIT,
/// CCITT protocols, X.25 etc
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Ccitt = libc::AF_CCITT,
/// DEC Direct data link interface
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Dli = libc::AF_DLI,
#[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Lat = libc::AF_LAT,
/// NSC Hyperchannel
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Hylink = libc::AF_HYLINK,
/// Link layer interface
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, solarish))]
Link = libc::AF_LINK,
/// connection-oriented IP, aka ST II
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Coip = libc::AF_COIP,
/// Computer Network Technology
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Cnt = libc::AF_CNT,
/// Native ATM access
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
Natm = libc::AF_NATM,
/// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
Unspec = libc::AF_UNSPEC,
}
@@ -425,29 +259,17 @@ impl AddressFamily {
libc::AF_UNIX => Some(AddressFamily::Unix),
libc::AF_INET => Some(AddressFamily::Inet),
libc::AF_INET6 => Some(AddressFamily::Inet6),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
libc::AF_NETLINK => Some(AddressFamily::Netlink),
- #[cfg(any(target_os = "macos", target_os = "macos"))]
+ #[cfg(apple_targets)]
libc::AF_SYSTEM => Some(AddressFamily::System),
- #[cfg(not(any(
- target_os = "redox",
- target_os = "linux",
- target_os = "android"
- )))]
+ #[cfg(not(any(linux_android, target_os = "redox")))]
libc::PF_ROUTE => Some(AddressFamily::Route),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
libc::AF_PACKET => Some(AddressFamily::Packet),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"
- ))]
+ #[cfg(any(bsd, solarish))]
libc::AF_LINK => Some(AddressFamily::Link),
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+ #[cfg(any(linux_android, apple_targets))]
libc::AF_VSOCK => Some(AddressFamily::Vsock),
_ => None,
}
@@ -463,13 +285,7 @@ pub struct UnixAddr {
/// The length of the valid part of `sun`, including the sun_family field
/// but excluding any trailing nul.
// On the BSDs, this field is built into sun
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
- target_os = "redox",
- ))]
+ #[cfg(not(any(bsd, target_os = "haiku", target_os = "hurd")))]
sun_len: u8,
}
@@ -483,12 +299,12 @@ pub struct UnixAddr {
enum UnixAddrKind<'a> {
Pathname(&'a Path),
Unnamed,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
Abstract(&'a [u8]),
}
impl<'a> UnixAddrKind<'a> {
/// Safety: sun & sun_len must be valid
- #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
+ #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
let path_len =
@@ -496,16 +312,19 @@ impl<'a> UnixAddrKind<'a> {
if path_len == 0 {
return Self::Unnamed;
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
if sun.sun_path[0] == 0 {
- let name = slice::from_raw_parts(
- sun.sun_path.as_ptr().add(1) as *const u8,
- path_len - 1,
- );
+ let name = unsafe {
+ slice::from_raw_parts(
+ sun.sun_path.as_ptr().add(1).cast(),
+ path_len - 1,
+ )
+ };
return Self::Abstract(name);
}
- let pathname =
- slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len);
+ let pathname = unsafe {
+ slice::from_raw_parts(sun.sun_path.as_ptr().cast(), path_len)
+ };
if pathname.last() == Some(&0) {
// A trailing NUL is not considered part of the path, and it does
// not need to be included in the addrlen passed to functions like
@@ -525,7 +344,7 @@ impl<'a> UnixAddrKind<'a> {
impl UnixAddr {
/// Create a new sockaddr_un representing a filesystem path.
- #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
+ #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
path.with_nix_path(|cstr| unsafe {
let mut ret = libc::sockaddr_un {
@@ -544,20 +363,13 @@ impl UnixAddr {
.try_into()
.unwrap();
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+ #[cfg(any(bsd, target_os = "haiku", target_os = "hurd"))]
{
ret.sun_len = sun_len;
}
ptr::copy_nonoverlapping(
bytes.as_ptr(),
- ret.sun_path.as_mut_ptr() as *mut u8,
+ ret.sun_path.as_mut_ptr().cast(),
bytes.len(),
);
@@ -571,9 +383,8 @@ impl UnixAddr {
/// thus the input `path` is expected to be the bare name, not NUL-prefixed.
/// This is a Linux-specific extension, primarily used to allow chrooted
/// processes to communicate with processes having a different filesystem view.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
+ #[cfg(linux_android)]
+ #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
unsafe {
let mut ret = libc::sockaddr_un {
@@ -593,7 +404,7 @@ impl UnixAddr {
// b'\0', so copy starting one byte in.
ptr::copy_nonoverlapping(
path.as_ptr(),
- ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
+ ret.sun_path.as_mut_ptr().offset(1).cast(),
path.len(),
);
@@ -602,8 +413,7 @@ impl UnixAddr {
}
/// Create a new `sockaddr_un` representing an "unnamed" unix socket address.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
pub fn new_unnamed() -> UnixAddr {
let ret = libc::sockaddr_un {
sun_family: AddressFamily::Unix as sa_family_t,
@@ -632,10 +442,9 @@ impl UnixAddr {
sun_len: u8,
) -> UnixAddr {
cfg_if! {
- if #[cfg(any(target_os = "android",
+ if #[cfg(any(linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
+ solarish,
target_os = "redox",
))]
{
@@ -664,8 +473,7 @@ impl UnixAddr {
///
/// For abstract sockets only the bare name is returned, without the
/// leading NUL byte. `None` is returned for unnamed or path-backed sockets.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
pub fn as_abstract(&self) -> Option<&[u8]> {
match self.kind() {
UnixAddrKind::Abstract(name) => Some(name),
@@ -674,8 +482,7 @@ impl UnixAddr {
}
/// Check if this address is an "unnamed" unix socket address.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
#[inline]
pub fn is_unnamed(&self) -> bool {
matches!(self.kind(), UnixAddrKind::Unnamed)
@@ -699,10 +506,9 @@ impl UnixAddr {
fn sun_len(&self) -> u8 {
cfg_if! {
- if #[cfg(any(target_os = "android",
+ if #[cfg(any(linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
+ solarish,
target_os = "redox",
))]
{
@@ -717,10 +523,10 @@ impl UnixAddr {
impl private::SockaddrLikePriv for UnixAddr {}
impl SockaddrLike for UnixAddr {
#[cfg(any(
- target_os = "android",
+ linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
+ solarish,
+ target_os = "redox"
))]
fn len(&self) -> libc::socklen_t {
self.sun_len.into()
@@ -740,27 +546,26 @@ impl SockaddrLike for UnixAddr {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_UNIX {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_UNIX } {
return None;
}
- let mut su: libc::sockaddr_un = mem::zeroed();
+ let mut su: libc::sockaddr_un = unsafe { mem::zeroed() };
let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
cfg_if! {
- if #[cfg(any(target_os = "android",
+ if #[cfg(any(linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
+ solarish,
target_os = "redox",
))] {
let su_len = len.unwrap_or(
mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
);
} else {
- let su_len = len.unwrap_or((*addr).sa_len as libc::socklen_t);
+ let su_len = unsafe { len.unwrap_or((*addr).sa_len as libc::socklen_t) };
}
- };
- ptr::copy(addr as *const u8, sup, su_len as usize);
- Some(Self::from_raw_parts(su, su_len as u8))
+ }
+ unsafe { ptr::copy(addr as *const u8, sup, su_len as usize) };
+ Some(unsafe { Self::from_raw_parts(su, su_len as u8) })
}
fn size() -> libc::socklen_t
@@ -770,14 +575,16 @@ impl SockaddrLike for UnixAddr {
mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
}
- unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
+ unsafe fn set_length(
+ &mut self,
+ new_length: usize,
+ ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
// `new_length` is only used on some platforms, so it must be provided even when not used
#![allow(unused_variables)]
cfg_if! {
- if #[cfg(any(target_os = "android",
+ if #[cfg(any(linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
+ solarish,
target_os = "redox",
))] {
self.sun_len = new_length as u8;
@@ -793,7 +600,7 @@ impl AsRef<libc::sockaddr_un> for UnixAddr {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
use fmt::Write;
f.write_str("@\"")?;
@@ -810,7 +617,7 @@ impl fmt::Display for UnixAddr {
match self.kind() {
UnixAddrKind::Pathname(path) => path.display().fmt(f),
UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
}
}
@@ -894,12 +701,7 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
}
cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
+ if #[cfg(bsd)] {
/// Return the length of valid data in the sockaddr structure.
///
/// For fixed-size sockaddrs, this should be the size of the
@@ -946,7 +748,10 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
/// `new_length` must be a valid length for this type of address. Specifically, reads of that
/// length from `self` must be valid.
#[doc(hidden)]
- unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
+ unsafe fn set_length(
+ &mut self,
+ _new_length: usize,
+ ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
Err(SocketAddressLengthNotDynamic)
}
}
@@ -1006,22 +811,20 @@ pub struct SockaddrIn(libc::sockaddr_in);
impl SockaddrIn {
/// Returns the IP address associated with this socket address, in native
/// endian.
- pub const fn ip(&self) -> libc::in_addr_t {
- u32::from_be(self.0.sin_addr.s_addr)
+ pub const fn ip(&self) -> net::Ipv4Addr {
+ let bytes = self.0.sin_addr.s_addr.to_ne_bytes();
+ let (a, b, c, d) = (bytes[0], bytes[1], bytes[2], bytes[3]);
+ Ipv4Addr::new(a, b, c, d)
}
/// Creates a new socket address from IPv4 octets and a port number.
pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
Self(libc::sockaddr_in {
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
+ bsd,
target_os = "aix",
target_os = "haiku",
- target_os = "openbsd"
+ target_os = "hurd"
))]
sin_len: Self::size() as u8,
sin_family: AddressFamily::Inet as sa_family_t,
@@ -1056,10 +859,10 @@ impl SockaddrLike for SockaddrIn {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_INET {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_INET } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
}
}
@@ -1092,14 +895,10 @@ impl From<net::SocketAddrV4> for SockaddrIn {
fn from(addr: net::SocketAddrV4) -> Self {
Self(libc::sockaddr_in {
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
+ bsd,
target_os = "haiku",
target_os = "hermit",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
+ target_os = "hurd"
))]
sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
sin_family: AddressFamily::Inet as sa_family_t,
@@ -1143,8 +942,19 @@ impl SockaddrIn6 {
}
/// Returns the IP address associated with this socket address.
- pub fn ip(&self) -> net::Ipv6Addr {
- net::Ipv6Addr::from(self.0.sin6_addr.s6_addr)
+ pub const fn ip(&self) -> net::Ipv6Addr {
+ let bytes = self.0.sin6_addr.s6_addr;
+ let (a, b, c, d, e, f, g, h) = (
+ ((bytes[0] as u16) << 8) | bytes[1] as u16,
+ ((bytes[2] as u16) << 8) | bytes[3] as u16,
+ ((bytes[4] as u16) << 8) | bytes[5] as u16,
+ ((bytes[6] as u16) << 8) | bytes[7] as u16,
+ ((bytes[8] as u16) << 8) | bytes[9] as u16,
+ ((bytes[10] as u16) << 8) | bytes[11] as u16,
+ ((bytes[12] as u16) << 8) | bytes[13] as u16,
+ ((bytes[14] as u16) << 8) | bytes[15] as u16,
+ );
+ Ipv6Addr::new(a, b, c, d, e, f, g, h)
}
/// Returns the port number associated with this socket address, in native
@@ -1175,10 +985,10 @@ impl SockaddrLike for SockaddrIn6 {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_INET6 {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_INET6 } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
}
}
@@ -1210,14 +1020,10 @@ impl From<net::SocketAddrV6> for SockaddrIn6 {
#[allow(clippy::needless_update)] // It isn't needless on Illumos
Self(libc::sockaddr_in6 {
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
+ bsd,
target_os = "haiku",
target_os = "hermit",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
+ target_os = "hurd"
))]
sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
sin6_family: AddressFamily::Inet6 as sa_family_t,
@@ -1273,18 +1079,17 @@ impl std::str::FromStr for SockaddrIn6 {
#[derive(Clone, Copy, Eq)]
#[repr(C)]
pub union SockaddrStorage {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
alg: AlgAddr,
- #[cfg(all(feature = "net", not(target_os = "redox")))]
+ #[cfg(all(
+ feature = "net",
+ not(any(target_os = "hurd", target_os = "redox"))
+ ))]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
dl: LinkAddr,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
nl: NetlinkAddr,
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
+ #[cfg(all(feature = "ioctl", apple_targets))]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
sctl: SysControlAddr,
#[cfg(feature = "net")]
@@ -1293,8 +1098,7 @@ pub union SockaddrStorage {
sin6: SockaddrIn6,
ss: libc::sockaddr_storage,
su: UnixAddr,
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, apple_targets))]
vsock: VsockAddr,
}
impl private::SockaddrLikePriv for SockaddrStorage {}
@@ -1316,21 +1120,22 @@ impl SockaddrLike for SockaddrStorage {
{
None
} else {
- let mut ss: libc::sockaddr_storage = mem::zeroed();
+ let mut ss: libc::sockaddr_storage = unsafe { mem::zeroed() };
let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
- ptr::copy(addr as *const u8, ssp, len as usize);
+ unsafe { ptr::copy(addr as *const u8, ssp, len as usize) };
#[cfg(any(
- target_os = "android",
+ linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
+ solarish,
))]
if i32::from(ss.ss_family) == libc::AF_UNIX {
// Safe because we UnixAddr is strictly smaller than
// SockaddrStorage, and we just initialized the structure.
- (*(&mut ss as *mut libc::sockaddr_storage
- as *mut UnixAddr))
- .sun_len = len as u8;
+ unsafe {
+ (*(&mut ss as *mut libc::sockaddr_storage
+ as *mut UnixAddr))
+ .sun_len = len as u8;
+ }
}
Some(Self { ss })
}
@@ -1338,68 +1143,47 @@ impl SockaddrLike for SockaddrStorage {
// If length is not available and addr is of a fixed-length type,
// copy it. If addr is of a variable length type and len is not
// available, then there's nothing we can do.
- match (*addr).sa_family as i32 {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_ALG => {
+ match unsafe { (*addr).sa_family as i32 } {
+ #[cfg(linux_android)]
+ libc::AF_ALG => unsafe {
AlgAddr::from_raw(addr, l).map(|alg| Self { alg })
- }
+ },
#[cfg(feature = "net")]
- libc::AF_INET => {
+ libc::AF_INET => unsafe {
SockaddrIn::from_raw(addr, l).map(|sin| Self { sin })
- }
+ },
#[cfg(feature = "net")]
- libc::AF_INET6 => {
+ libc::AF_INET6 => unsafe {
SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 })
- }
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
- ))]
+ },
+ #[cfg(any(bsd, solarish, target_os = "haiku"))]
#[cfg(feature = "net")]
- libc::AF_LINK => {
+ libc::AF_LINK => unsafe {
LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => {
+ },
+ #[cfg(linux_android)]
+ libc::AF_NETLINK => unsafe {
NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl })
- }
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
+ },
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
#[cfg(feature = "net")]
- libc::AF_PACKET => {
+ libc::AF_PACKET => unsafe {
LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
- }
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- libc::AF_SYSTEM => {
+ },
+ #[cfg(all(feature = "ioctl", apple_targets))]
+ libc::AF_SYSTEM => unsafe {
SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
- }
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))]
- libc::AF_VSOCK => {
+ },
+ #[cfg(any(linux_android, apple_targets))]
+ libc::AF_VSOCK => unsafe {
VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
- }
+ },
_ => None,
}
}
}
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia", solarish))]
fn len(&self) -> libc::socklen_t {
match self.as_unix_addr() {
// The UnixAddr type knows its own length
@@ -1409,11 +1193,12 @@ impl SockaddrLike for SockaddrStorage {
}
}
- unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
+ unsafe fn set_length(
+ &mut self,
+ new_length: usize,
+ ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
match self.as_unix_addr_mut() {
- Some(addr) => {
- addr.set_length(new_length)
- },
+ Some(addr) => unsafe { addr.set_length(new_length) },
None => Err(SocketAddressLengthNotDynamic),
}
}
@@ -1457,10 +1242,9 @@ impl SockaddrStorage {
/// Downcast to an immutable `[UnixAddr]` reference.
pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
cfg_if! {
- if #[cfg(any(target_os = "android",
+ if #[cfg(any(linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
+ solarish,
))]
{
let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
@@ -1487,10 +1271,9 @@ impl SockaddrStorage {
/// Downcast to a mutable `[UnixAddr]` reference.
pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
cfg_if! {
- if #[cfg(any(target_os = "android",
+ if #[cfg(any(linux_android,
target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
+ solarish,
))]
{
let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
@@ -1514,29 +1297,17 @@ impl SockaddrStorage {
}
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
AddressFamily::Alg, libc::sockaddr_alg, alg}
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
#[cfg(feature = "net")]
accessors! {
as_link_addr, as_link_addr_mut, LinkAddr,
AddressFamily::Packet, libc::sockaddr_ll, dl}
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+ #[cfg(any(bsd, solarish))]
#[cfg(feature = "net")]
accessors! {
as_link_addr, as_link_addr_mut, LinkAddr,
@@ -1552,17 +1323,16 @@ impl SockaddrStorage {
as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
AddressFamily::Inet6, libc::sockaddr_in6, sin6}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
AddressFamily::Netlink, libc::sockaddr_nl, nl}
- #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
+ #[cfg(all(feature = "ioctl", apple_targets))]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
AddressFamily::System, libc::sockaddr_ctl, sctl}
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, apple_targets))]
accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
AddressFamily::Vsock, libc::sockaddr_vm, vsock}
}
@@ -1581,37 +1351,25 @@ impl fmt::Display for SockaddrStorage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unsafe {
match self.ss.ss_family as i32 {
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
libc::AF_ALG => self.alg.fmt(f),
#[cfg(feature = "net")]
libc::AF_INET => self.sin.fmt(f),
#[cfg(feature = "net")]
libc::AF_INET6 => self.sin6.fmt(f),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+ #[cfg(any(bsd, solarish))]
#[cfg(feature = "net")]
libc::AF_LINK => self.dl.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
libc::AF_NETLINK => self.nl.fmt(f),
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
#[cfg(feature = "net")]
libc::AF_PACKET => self.dl.fmt(f),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
#[cfg(feature = "ioctl")]
libc::AF_SYSTEM => self.sctl.fmt(f),
libc::AF_UNIX => self.su.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+ #[cfg(any(linux_android, apple_targets))]
libc::AF_VSOCK => self.vsock.fmt(f),
_ => "<Address family unspecified>".fmt(f),
}
@@ -1655,37 +1413,25 @@ impl Hash for SockaddrStorage {
fn hash<H: Hasher>(&self, s: &mut H) {
unsafe {
match self.ss.ss_family as i32 {
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
libc::AF_ALG => self.alg.hash(s),
#[cfg(feature = "net")]
libc::AF_INET => self.sin.hash(s),
#[cfg(feature = "net")]
libc::AF_INET6 => self.sin6.hash(s),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+ #[cfg(any(bsd, solarish))]
#[cfg(feature = "net")]
libc::AF_LINK => self.dl.hash(s),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
libc::AF_NETLINK => self.nl.hash(s),
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "fuchsia"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
#[cfg(feature = "net")]
libc::AF_PACKET => self.dl.hash(s),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
#[cfg(feature = "ioctl")]
libc::AF_SYSTEM => self.sctl.hash(s),
libc::AF_UNIX => self.su.hash(s),
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+ #[cfg(any(linux_android, apple_targets))]
libc::AF_VSOCK => self.vsock.hash(s),
_ => self.ss.hash(s),
}
@@ -1697,37 +1443,25 @@ impl PartialEq for SockaddrStorage {
fn eq(&self, other: &Self) -> bool {
unsafe {
match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
(libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
#[cfg(feature = "net")]
(libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
#[cfg(feature = "net")]
(libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+ #[cfg(any(bsd, solarish))]
#[cfg(feature = "net")]
(libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
(libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
#[cfg(feature = "net")]
(libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
#[cfg(feature = "ioctl")]
(libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
(libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+ #[cfg(any(linux_android, apple_targets))]
(libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
_ => false,
}
@@ -1751,8 +1485,7 @@ pub(super) mod private {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(linux_android)]
pub mod netlink {
use super::*;
use crate::sys::socket::addr::AddressFamily;
@@ -1805,10 +1538,10 @@ pub mod netlink {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_NETLINK {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_NETLINK } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
}
}
@@ -1825,11 +1558,10 @@ pub mod netlink {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(linux_android)]
pub mod alg {
use super::*;
- use libc::{c_char, sockaddr_alg, AF_ALG};
+ use libc::{sockaddr_alg, AF_ALG};
use std::ffi::CStr;
use std::hash::{Hash, Hasher};
use std::{fmt, mem, str};
@@ -1854,10 +1586,10 @@ pub mod alg {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_ALG {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_ALG } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
}
}
@@ -1918,16 +1650,12 @@ pub mod alg {
/// Return the socket's cipher type, for example `hash` or `aead`.
pub fn alg_type(&self) -> &CStr {
- unsafe {
- CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char)
- }
+ unsafe { CStr::from_ptr(self.0.salg_type.as_ptr().cast()) }
}
/// Return the socket's cipher name, for example `sha1`.
pub fn alg_name(&self) -> &CStr {
- unsafe {
- CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char)
- }
+ unsafe { CStr::from_ptr(self.0.salg_name.as_ptr().cast()) }
}
}
@@ -1951,7 +1679,7 @@ pub mod alg {
feature! {
#![feature = "ioctl"]
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
pub mod sys_control {
use crate::sys::socket::addr::AddressFamily;
use libc::{self, c_uchar};
@@ -1994,10 +1722,10 @@ pub mod sys_control {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_SYSTEM {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_SYSTEM } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ Some(Self(unsafe { ptr::read_unaligned(addr as *const _) } ))
}
}
@@ -2058,8 +1786,7 @@ pub mod sys_control {
}
}
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(any(linux_android, target_os = "fuchsia"))]
mod datalink {
feature! {
#![feature = "net"]
@@ -2136,10 +1863,10 @@ mod datalink {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_PACKET {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_PACKET } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
}
}
@@ -2152,18 +1879,7 @@ mod datalink {
}
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "aix",
- target_os = "openbsd"
-))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(any(bsd, solarish, target_os = "haiku", target_os = "aix"))]
mod datalink {
feature! {
#![feature = "net"]
@@ -2261,10 +1977,10 @@ mod datalink {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_LINK {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_LINK } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
}
}
@@ -2276,8 +1992,7 @@ mod datalink {
}
}
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(any(linux_android, apple_targets))]
pub mod vsock {
use super::*;
use crate::sys::socket::addr::AddressFamily;
@@ -2308,10 +2023,10 @@ pub mod vsock {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_VSOCK {
+ if unsafe { (*addr).sa_family as i32 != libc::AF_VSOCK } {
return None;
}
- Some(Self(ptr::read_unaligned(addr as *const _)))
+ unsafe { Some(Self(ptr::read_unaligned(addr as *const _))) }
}
}
@@ -2322,32 +2037,47 @@ pub mod vsock {
}
impl PartialEq for VsockAddr {
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
(inner.svm_family, inner.svm_cid, inner.svm_port)
== (other.svm_family, other.svm_cid, other.svm_port)
}
- #[cfg(target_os = "macos")]
+ #[cfg(apple_targets)]
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
- (inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len)
- == (other.svm_family, other.svm_cid, other.svm_port, inner.svm_len)
+ (
+ inner.svm_family,
+ inner.svm_cid,
+ inner.svm_port,
+ inner.svm_len,
+ ) == (
+ other.svm_family,
+ other.svm_cid,
+ other.svm_port,
+ inner.svm_len,
+ )
}
}
impl Eq for VsockAddr {}
impl Hash for VsockAddr {
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
fn hash<H: Hasher>(&self, s: &mut H) {
let inner = self.0;
(inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
}
- #[cfg(target_os = "macos")]
+ #[cfg(apple_targets)]
fn hash<H: Hasher>(&self, s: &mut H) {
let inner = self.0;
- (inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len).hash(s);
+ (
+ inner.svm_family,
+ inner.svm_cid,
+ inner.svm_port,
+ inner.svm_len,
+ )
+ .hash(s);
}
}
@@ -2363,9 +2093,9 @@ pub mod vsock {
addr.svm_cid = cid;
addr.svm_port = port;
- #[cfg(target_os = "macos")]
+ #[cfg(apple_targets)]
{
- addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8;
+ addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8;
}
VsockAddr(addr)
}
@@ -2419,27 +2149,16 @@ mod tests {
}
}
- #[cfg(not(target_os = "redox"))]
+ #[cfg(not(any(target_os = "hurd", target_os = "redox")))]
mod link {
#![allow(clippy::cast_ptr_alignment)]
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos"
- ))]
+ #[cfg(any(apple_targets, solarish))]
use super::super::super::socklen_t;
use super::*;
/// Don't panic when trying to display an empty datalink address
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+ #[cfg(bsd)]
#[test]
fn test_datalink_display() {
use super::super::LinkAddr;
@@ -2459,11 +2178,7 @@ mod tests {
}
#[cfg(all(
- any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ),
+ any(linux_android, target_os = "fuchsia"),
target_endian = "little"
))]
#[test]
@@ -2474,7 +2189,7 @@ mod tests {
let bytes = Raw([
17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0,
]);
- let sa = bytes.0.as_ptr() as *const libc::sockaddr;
+ let sa = bytes.0.as_ptr().cast();
let len = None;
let sock_addr =
unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
@@ -2485,12 +2200,12 @@ mod tests {
}
}
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
#[test]
fn macos_loopback() {
let bytes =
[20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
- let sa = bytes.as_ptr() as *const libc::sockaddr;
+ let sa = bytes.as_ptr().cast();
let len = Some(bytes.len() as socklen_t);
let sock_addr =
unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
@@ -2503,7 +2218,7 @@ mod tests {
}
}
- #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(apple_targets)]
#[test]
fn macos_tap() {
let bytes = [
@@ -2525,9 +2240,9 @@ mod tests {
}
}
- #[cfg(target_os = "illumos")]
+ #[cfg(solarish)]
#[test]
- fn illumos_tap() {
+ fn solarish_tap() {
let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
let ptr = bytes.as_ptr();
let sa = ptr as *const libc::sockaddr;
@@ -2548,23 +2263,9 @@ mod tests {
#[test]
fn size() {
- #[cfg(any(
- target_os = "aix",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd",
- target_os = "haiku"
- ))]
+ #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))]
let l = mem::size_of::<libc::sockaddr_dl>();
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
let l = mem::size_of::<libc::sockaddr_ll>();
assert_eq!(LinkAddr::size() as usize, l);
}
@@ -2588,6 +2289,13 @@ mod tests {
SockaddrIn::size() as usize
);
}
+
+ #[test]
+ fn ip() {
+ let s = "127.0.0.1:8082";
+ let ip = SockaddrIn::from_str(s).unwrap().ip();
+ assert_eq!("127.0.0.1", format!("{ip}"));
+ }
}
mod sockaddr_in6 {
@@ -2610,6 +2318,13 @@ mod tests {
}
#[test]
+ fn ip() {
+ let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
+ let ip = SockaddrIn6::from_str(s).unwrap().ip();
+ assert_eq!("1234:5678:90ab:cdef::1111:2222", format!("{ip}"));
+ }
+
+ #[test]
// Ensure that we can convert to-and-from std::net variants without change.
fn to_and_from() {
let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
@@ -2628,28 +2343,28 @@ mod tests {
#[test]
fn from_sockaddr_un_named() {
let ua = UnixAddr::new("/var/run/mysock").unwrap();
- let ptr = ua.as_ptr() as *const libc::sockaddr;
+ let ptr = ua.as_ptr().cast();
let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
.unwrap();
assert_eq!(ss.len(), ua.len());
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[test]
fn from_sockaddr_un_abstract_named() {
let name = String::from("nix\0abstract\0test");
let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
- let ptr = ua.as_ptr() as *const libc::sockaddr;
+ let ptr = ua.as_ptr().cast();
let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
.unwrap();
assert_eq!(ss.len(), ua.len());
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[test]
fn from_sockaddr_un_abstract_unnamed() {
let ua = UnixAddr::new_unnamed();
- let ptr = ua.as_ptr() as *const libc::sockaddr;
+ let ptr = ua.as_ptr().cast();
let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
.unwrap();
assert_eq!(ss.len(), ua.len());
@@ -2659,7 +2374,7 @@ mod tests {
mod unixaddr {
use super::*;
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[test]
fn abstract_sun_path() {
let name = String::from("nix\0abstract\0test");
diff --git a/third_party/rust/nix/src/sys/socket/mod.rs b/third_party/rust/nix/src/sys/socket/mod.rs
index 78dd617c55..3d1651bd3f 100644
--- a/third_party/rust/nix/src/sys/socket/mod.rs
+++ b/third_party/rust/nix/src/sys/socket/mod.rs
@@ -1,7 +1,7 @@
//! Socket interface functions
//!
//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(any(target_os = "freebsd", linux_android))]
#[cfg(feature = "uio")]
use crate::sys::time::TimeSpec;
#[cfg(not(target_os = "redox"))]
@@ -9,16 +9,16 @@ use crate::sys::time::TimeSpec;
use crate::sys::time::TimeVal;
use crate::{errno::Errno, Result};
use cfg_if::cfg_if;
-use libc::{self, c_int, c_void, size_t, socklen_t};
+use libc::{self, c_int, size_t, socklen_t};
#[cfg(all(feature = "uio", not(target_os = "redox")))]
use libc::{
- iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE,
+ c_void, iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE,
};
#[cfg(not(target_os = "redox"))]
use std::io::{IoSlice, IoSliceMut};
#[cfg(feature = "net")]
use std::net;
-use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, RawFd, OwnedFd};
+use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd};
use std::{mem, ptr};
#[deny(missing_docs)]
@@ -34,35 +34,25 @@ pub mod sockopt;
pub use self::addr::{SockaddrLike, SockaddrStorage};
-#[cfg(any(target_os = "illumos", target_os = "solaris"))]
+#[cfg(solarish)]
pub use self::addr::{AddressFamily, UnixAddr};
-#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
+#[cfg(not(solarish))]
pub use self::addr::{AddressFamily, UnixAddr};
-#[cfg(not(any(
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku",
- target_os = "redox",
-)))]
+#[cfg(not(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox")))]
#[cfg(feature = "net")]
pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6};
-#[cfg(any(
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku",
- target_os = "redox",
-))]
+#[cfg(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox"))]
#[cfg(feature = "net")]
pub use self::addr::{SockaddrIn, SockaddrIn6};
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
pub use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
pub use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
#[cfg(feature = "ioctl")]
pub use crate::sys::socket::addr::sys_control::SysControlAddr;
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+#[cfg(any(linux_android, apple_targets))]
pub use crate::sys::socket::addr::vsock::VsockAddr;
#[cfg(all(feature = "uio", not(target_os = "redox")))]
@@ -132,121 +122,108 @@ pub enum SockProtocol {
Udp = libc::IPPROTO_UDP,
/// Raw sockets ([raw(7)](https://man7.org/linux/man-pages/man7/raw.7.html))
Raw = libc::IPPROTO_RAW,
- /// Allows applications and other KEXTs to be notified when certain kernel events occur
- /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- KextEvent = libc::SYSPROTO_EVENT,
/// Allows applications to configure and control a KEXT
/// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
KextControl = libc::SYSPROTO_CONTROL,
/// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
// parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkRoute = libc::NETLINK_ROUTE,
/// Reserved for user-mode socket protocols
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkUserSock = libc::NETLINK_USERSOCK,
/// Query information about sockets of various protocol families from the kernel
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
/// Netfilter/iptables ULOG.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkNFLOG = libc::NETLINK_NFLOG,
/// SELinux event notifications.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkSELinux = libc::NETLINK_SELINUX,
/// Open-iSCSI
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkISCSI = libc::NETLINK_ISCSI,
/// Auditing
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkAudit = libc::NETLINK_AUDIT,
/// Access to FIB lookup from user space
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
/// Netfilter subsystem
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkNetFilter = libc::NETLINK_NETFILTER,
/// SCSI Transports
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
/// Infiniband RDMA
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkRDMA = libc::NETLINK_RDMA,
/// Transport IPv6 packets from netfilter to user space. Used by ip6_queue kernel module.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
/// DECnet routing messages
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
/// Kernel messages to user space
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
/// Generic netlink family for simplified netlink usage.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkGeneric = libc::NETLINK_GENERIC,
/// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
/// configuration of the kernel crypto API.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkCrypto = libc::NETLINK_CRYPTO,
/// Non-DIX type protocol number defined for the Ethernet IEEE 802.3 interface that allows packets of all protocols
/// defined in the interface to be received.
/// ([ref](https://man7.org/linux/man-pages/man7/packet.7.html))
// The protocol number is fed into the socket syscall in network byte order.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
EthAll = (libc::ETH_P_ALL as u16).to_be() as i32,
+ /// ICMP protocol ([icmp(7)](https://man7.org/linux/man-pages/man7/icmp.7.html))
+ Icmp = libc::IPPROTO_ICMP,
+ /// ICMPv6 protocol (ICMP over IPv6)
+ IcmpV6 = libc::IPPROTO_ICMPV6,
+}
+
+impl SockProtocol {
/// The Controller Area Network raw socket protocol
/// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CanRaw = libc::CAN_RAW,
-}
+ #[allow(non_upper_case_globals)]
+ pub const CanRaw: SockProtocol = SockProtocol::Icmp; // Matches libc::CAN_RAW
-impl SockProtocol {
/// The Controller Area Network broadcast manager protocol
/// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(non_upper_case_globals)]
pub const CanBcm: SockProtocol = SockProtocol::NetlinkUserSock; // Matches libc::CAN_BCM
+
+ /// Allows applications and other KEXTs to be notified when certain kernel events occur
+ /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
+ #[cfg(apple_targets)]
+ #[allow(non_upper_case_globals)]
+ pub const KextEvent: SockProtocol = SockProtocol::Icmp; // Matches libc::SYSPROTO_EVENT
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
libc_bitflags! {
/// Configuration flags for `SO_TIMESTAMPING` interface
///
@@ -276,33 +253,23 @@ libc_bitflags! {
/// Additional socket options
pub struct SockFlag: c_int {
/// Set non-blocking mode on the new socket
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android,
+ freebsdlike,
+ netbsdlike,
+ solarish))]
SOCK_NONBLOCK;
/// Set close-on-exec on the new descriptor
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android,
+ freebsdlike,
+ netbsdlike,
+ solarish))]
SOCK_CLOEXEC;
/// Return `EPIPE` instead of raising `SIGPIPE`
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SOCK_NOSIGPIPE;
/// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
/// to the DNS port (typically 53)
#[cfg(target_os = "openbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SOCK_DNS;
}
}
@@ -333,7 +300,6 @@ libc_bitflags! {
/// the calling process and as well as other processes that hold
/// file descriptors referring to the same open file description.
#[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MSG_DONTWAIT;
/// Receive flags: Control Data was discarded (buffer too small)
MSG_CTRUNC;
@@ -352,8 +318,7 @@ libc_bitflags! {
/// This flag specifies that queued errors should be received from
/// the socket error queue. (For more details, see
/// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MSG_ERRQUEUE;
/// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
/// file descriptor using the `SCM_RIGHTS` operation (described in
@@ -362,44 +327,48 @@ libc_bitflags! {
/// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
///
/// Only used in [`recvmsg`](fn.recvmsg.html) function.
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, freebsdlike, netbsdlike))]
MSG_CMSG_CLOEXEC;
/// Requests not to send `SIGPIPE` errors when the other end breaks the connection.
/// (For more details, see [send(2)](https://linux.die.net/man/2/send)).
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
+ #[cfg(any(linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike,
target_os = "fuchsia",
- target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ target_os = "haiku"))]
MSG_NOSIGNAL;
/// Turns on [`MSG_DONTWAIT`] after the first message has been received (only for
/// `recvmmsg()`).
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
+ netbsdlike,
target_os = "fuchsia",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ target_os = "freebsd"))]
MSG_WAITFORONE;
}
}
+#[cfg(target_os = "freebsd")]
+libc_enum! {
+ /// A selector for which clock to use when generating packet timestamps.
+ /// Used when setting [`TsClock`](crate::sys::socket::sockopt::TsClock) on a socket.
+ /// (For more details, see [setsockopt(2)](https://man.freebsd.org/cgi/man.cgi?setsockopt)).
+ #[repr(i32)]
+ #[non_exhaustive]
+ pub enum SocketTimestamp {
+ /// Microsecond resolution, realtime. This is the default.
+ SO_TS_REALTIME_MICRO,
+ /// Sub-nanosecond resolution, realtime.
+ SO_TS_BINTIME,
+ /// Nanosecond resolution, realtime.
+ SO_TS_REALTIME,
+ /// Nanosecond resolution, monotonic.
+ SO_TS_MONOTONIC,
+ }
+}
+
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
/// Unix credentials of the sending process.
///
/// This struct is used with the `SO_PEERCRED` ancillary message
@@ -454,7 +423,7 @@ cfg_if! {
uc.0
}
}
- } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
+ } else if #[cfg(freebsdlike)] {
/// Unix credentials of the sending process.
///
/// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
@@ -487,7 +456,7 @@ cfg_if! {
pub fn groups(&self) -> &[libc::gid_t] {
unsafe {
std::slice::from_raw_parts(
- self.0.cmcred_groups.as_ptr() as *const libc::gid_t,
+ self.0.cmcred_groups.as_ptr(),
self.0.cmcred_ngroups as _
)
}
@@ -503,12 +472,7 @@ cfg_if! {
}
cfg_if! {
- if #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
- ))] {
+ if #[cfg(any(freebsdlike, apple_targets))] {
/// Return type of [`LocalPeerCred`](crate::sys::socket::sockopt::LocalPeerCred)
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -603,8 +567,6 @@ feature! {
/// let _ = cmsg_space!(RawFd, TimeVal);
/// # }
/// ```
-// Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
-// stack-allocated array.
#[macro_export]
macro_rules! cmsg_space {
( $( $x:ty ),* ) => {
@@ -617,7 +579,7 @@ macro_rules! cmsg_space {
#[inline]
#[doc(hidden)]
-pub fn cmsg_space<T>() -> usize {
+pub const fn cmsg_space<T>() -> usize {
// SAFETY: CMSG_SPACE is always safe
unsafe { libc::CMSG_SPACE(mem::size_of::<T>() as libc::c_uint) as usize }
}
@@ -677,7 +639,7 @@ impl<'a> Iterator for CmsgIterator<'a> {
}
/// A type-safe wrapper around a single control message, as used with
-/// [`recvmsg`](#fn.recvmsg).
+/// [`recvmsg`].
///
/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
// Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
@@ -692,12 +654,10 @@ pub enum ControlMessageOwned {
/// Received version of [`ControlMessage::ScmRights`]
ScmRights(Vec<RawFd>),
/// Received version of [`ControlMessage::ScmCredentials`]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ScmCredentials(UnixCredentials),
/// Received version of [`ControlMessage::ScmCreds`]
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
ScmCreds(UnixCredentials),
/// A message of type `SCM_TIMESTAMP`, containing the time the
/// packet was received by the kernel.
@@ -760,62 +720,44 @@ pub enum ControlMessageOwned {
/// A set of nanosecond resolution timestamps
///
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ScmTimestampsns(Timestamps),
/// Nanoseconds resolution timestamp
///
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ScmTimestampns(TimeSpec),
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
+ /// Realtime clock timestamp
+ ///
+ /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
+ #[cfg(target_os = "freebsd")]
+ ScmRealtime(TimeSpec),
+ /// Monotonic clock timestamp
+ ///
+ /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
+ #[cfg(target_os = "freebsd")]
+ ScmMonotonic(TimeSpec),
+ #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4PacketInfo(libc::in_pktinfo),
- #[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "openbsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, bsd))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6PacketInfo(libc::in6_pktinfo),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4RecvIf(libc::sockaddr_dl),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4RecvDstAddr(libc::in_addr),
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4OrigDstAddr(libc::sockaddr_in),
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6OrigDstAddr(libc::sockaddr_in6),
@@ -841,28 +783,31 @@ pub enum ControlMessageOwned {
///
/// `RxqOvfl` socket option should be enabled on a socket
/// to allow receiving the drop counter.
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
RxqOvfl(u32),
/// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4RecvErr(libc::sock_extended_err, Option<sockaddr_in>),
/// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6RecvErr(libc::sock_extended_err, Option<sockaddr_in6>),
+ /// `SOL_TLS` messages of type `TLS_GET_RECORD_TYPE`
+ #[cfg(any(target_os = "linux"))]
+ TlsGetRecordType(TlsGetRecordType),
+
/// Catch-all variant for unimplemented cmsg types.
#[doc(hidden)]
Unknown(UnknownCmsg),
}
/// For representing packet timestamps via `SO_TIMESTAMPING` interface
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Timestamps {
/// software based timestamp, usually one containing data
@@ -873,6 +818,33 @@ pub struct Timestamps {
pub hw_raw: TimeSpec,
}
+/// These constants correspond to TLS 1.2 message types, as defined in
+/// RFC 5246, Appendix A.1
+#[cfg(any(target_os = "linux"))]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[repr(u8)]
+#[non_exhaustive]
+pub enum TlsGetRecordType {
+ ChangeCipherSpec ,
+ Alert,
+ Handshake,
+ ApplicationData,
+ Unknown(u8),
+}
+
+#[cfg(any(target_os = "linux"))]
+impl From<u8> for TlsGetRecordType {
+ fn from(x: u8) -> Self {
+ match x {
+ 20 => TlsGetRecordType::ChangeCipherSpec,
+ 21 => TlsGetRecordType::Alert,
+ 22 => TlsGetRecordType::Handshake,
+ 23 => TlsGetRecordType::ApplicationData,
+ _ => TlsGetRecordType::Unknown(x),
+ }
+ }
+}
+
impl ControlMessageOwned {
/// Decodes a `ControlMessageOwned` from raw bytes.
///
@@ -885,7 +857,7 @@ impl ControlMessageOwned {
#[allow(clippy::cast_ptr_alignment)]
unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
{
- let p = CMSG_DATA(header);
+ let p = unsafe { CMSG_DATA(header) };
// The cast is not unnecessary on all platforms.
#[allow(clippy::unnecessary_cast)]
let len = header as *const _ as usize + header.cmsg_len as usize
@@ -895,158 +867,151 @@ impl ControlMessageOwned {
let n = len / mem::size_of::<RawFd>();
let mut fds = Vec::with_capacity(n);
for i in 0..n {
- let fdp = (p as *const RawFd).add(i);
- fds.push(ptr::read_unaligned(fdp));
+ unsafe {
+ let fdp = (p as *const RawFd).add(i);
+ fds.push(ptr::read_unaligned(fdp));
+ }
}
ControlMessageOwned::ScmRights(fds)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
(libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
- let cred: libc::ucred = ptr::read_unaligned(p as *const _);
+ let cred: libc::ucred = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmCredentials(cred.into())
}
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
(libc::SOL_SOCKET, libc::SCM_CREDS) => {
- let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
+ let cred: libc::cmsgcred = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmCreds(cred.into())
}
#[cfg(not(any(target_os = "aix", target_os = "haiku")))]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
- let tv: libc::timeval = ptr::read_unaligned(p as *const _);
+ let tv: libc::timeval = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
- let ts: libc::timespec = ptr::read_unaligned(p as *const _);
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(target_os = "freebsd")]
+ (libc::SOL_SOCKET, libc::SCM_REALTIME) => {
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
+ ControlMessageOwned::ScmRealtime(TimeSpec::from(ts))
+ }
+ #[cfg(target_os = "freebsd")]
+ (libc::SOL_SOCKET, libc::SCM_MONOTONIC) => {
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
+ ControlMessageOwned::ScmMonotonic(TimeSpec::from(ts))
+ }
+ #[cfg(linux_android)]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => {
let tp = p as *const libc::timespec;
- let ts: libc::timespec = ptr::read_unaligned(tp);
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(tp) };
let system = TimeSpec::from(ts);
- let ts: libc::timespec = ptr::read_unaligned(tp.add(1));
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(1)) };
let hw_trans = TimeSpec::from(ts);
- let ts: libc::timespec = ptr::read_unaligned(tp.add(2));
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(2)) };
let hw_raw = TimeSpec::from(ts);
let timestamping = Timestamps { system, hw_trans, hw_raw };
ControlMessageOwned::ScmTimestampsns(timestamping)
}
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"
- ))]
+ #[cfg(any(target_os = "freebsd", linux_android, apple_targets))]
#[cfg(feature = "net")]
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
+ let info = unsafe { ptr::read_unaligned(p as *const libc::in6_pktinfo) };
ControlMessageOwned::Ipv6PacketInfo(info)
}
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
+ let info = unsafe { ptr::read_unaligned(p as *const libc::in_pktinfo) };
ControlMessageOwned::Ipv4PacketInfo(info)
}
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_RECVIF) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_dl) };
ControlMessageOwned::Ipv4RecvIf(dl)
},
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::in_addr);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::in_addr) };
ControlMessageOwned::Ipv4RecvDstAddr(dl)
},
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_in);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in) };
ControlMessageOwned::Ipv4OrigDstAddr(dl)
},
#[cfg(target_os = "linux")]
#[cfg(feature = "net")]
(libc::SOL_UDP, libc::UDP_GRO) => {
- let gso_size: u16 = ptr::read_unaligned(p as *const _);
+ let gso_size: u16 = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::UdpGroSegments(gso_size)
},
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
(libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => {
- let drop_counter = ptr::read_unaligned(p as *const u32);
+ let drop_counter = unsafe { ptr::read_unaligned(p as *const u32) };
ControlMessageOwned::RxqOvfl(drop_counter)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_RECVERR) => {
- let (err, addr) = Self::recv_err_helper::<sockaddr_in>(p, len);
+ let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in>(p, len) };
ControlMessageOwned::Ipv4RecvErr(err, addr)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
(libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => {
- let (err, addr) = Self::recv_err_helper::<sockaddr_in6>(p, len);
+ let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in6>(p, len) };
ControlMessageOwned::Ipv6RecvErr(err, addr)
},
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
(libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_in6);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in6) };
ControlMessageOwned::Ipv6OrigDstAddr(dl)
},
+ #[cfg(any(target_os = "linux"))]
+ (libc::SOL_TLS, libc::TLS_GET_RECORD_TYPE) => {
+ let content_type = unsafe { ptr::read_unaligned(p as *const u8) };
+ ControlMessageOwned::TlsGetRecordType(content_type.into())
+ },
(_, _) => {
- let sl = std::slice::from_raw_parts(p, len);
+ let sl = unsafe { std::slice::from_raw_parts(p, len) };
let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
ControlMessageOwned::Unknown(ucmsg)
}
}
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
#[allow(clippy::cast_ptr_alignment)] // False positive
unsafe fn recv_err_helper<T>(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option<T>) {
let ee = p as *const libc::sock_extended_err;
- let err = ptr::read_unaligned(ee);
+ let err = unsafe { ptr::read_unaligned(ee) };
// For errors originating on the network, SO_EE_OFFENDER(ee) points inside the p[..len]
// CMSG_DATA buffer. For local errors, there is no address included in the control
// message, and SO_EE_OFFENDER(ee) points beyond the end of the buffer. So, we need to
// validate that the address object is in-bounds before we attempt to copy it.
- let addrp = libc::SO_EE_OFFENDER(ee) as *const T;
+ let addrp = unsafe { libc::SO_EE_OFFENDER(ee) as *const T };
- if addrp.offset(1) as usize - (p as usize) > len {
+ if unsafe { addrp.offset(1) } as usize - (p as usize) > len {
(err, None)
} else {
- (err, Some(ptr::read_unaligned(addrp)))
+ (err, Some(unsafe { ptr::read_unaligned(addrp) }))
}
}
}
-/// A type-safe zero-copy wrapper around a single control message, as used wih
-/// [`sendmsg`](#fn.sendmsg). More types may be added to this enum; do not
-/// exhaustively pattern-match it.
+/// A type-safe zero-copy wrapper around a single control message, as used with
+/// [`sendmsg`]. More types may be added to this enum; do not exhaustively
+/// pattern-match it.
///
/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -1074,8 +1039,7 @@ pub enum ControlMessage<'a> {
///
/// For further information, please refer to the
/// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ScmCredentials(&'a UnixCredentials),
/// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
/// a process connected to the socket.
@@ -1089,41 +1053,28 @@ pub enum ControlMessage<'a> {
///
/// For further information, please refer to the
/// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
ScmCreds,
/// Set IV for `AF_ALG` crypto API.
///
/// For further information, please refer to the
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AlgSetIv(&'a [u8]),
/// Set crypto operation for `AF_ALG` crypto API. It may be one of
/// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
///
/// For further information, please refer to the
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AlgSetOp(&'a libc::c_int),
/// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
/// for `AF_ALG` crypto API.
///
/// For further information, please refer to the
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AlgSetAeadAssoclen(&'a u32),
/// UDP GSO makes it possible for applications to generate network packets
@@ -1139,51 +1090,52 @@ pub enum ControlMessage<'a> {
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
UdpGsoSegments(&'a u16),
- /// Configure the sending addressing and interface for v4
+ /// Configure the sending addressing and interface for v4.
///
/// For further information, please refer to the
/// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
- #[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4PacketInfo(&'a libc::in_pktinfo),
- /// Configure the sending addressing and interface for v6
+ /// Configure the sending addressing and interface for v6.
///
/// For further information, please refer to the
/// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
- #[cfg(any(target_os = "linux",
- target_os = "macos",
+ #[cfg(any(linux_android,
target_os = "netbsd",
target_os = "freebsd",
- target_os = "android",
- target_os = "ios",))]
+ apple_targets))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6PacketInfo(&'a libc::in6_pktinfo),
/// Configure the IPv4 source address with `IP_SENDSRCADDR`.
- #[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- ))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4SendSrcAddr(&'a libc::in_addr),
+ /// Configure the hop limit for v6 multicast traffic.
+ ///
+ /// Set the IPv6 hop limit for this message. The argument is an integer
+ /// between 0 and 255. A value of -1 will set the hop limit to the route
+ /// default if possible on the interface. Without this cmsg, packets sent
+ /// with sendmsg have a hop limit of 1 and will not leave the local network.
+ /// For further information, please refer to the
+ /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ Ipv6HopLimit(&'a libc::c_int),
+
/// SO_RXQ_OVFL indicates that an unsigned 32 bit value
/// ancilliary msg (cmsg) should be attached to recieved
/// skbs indicating the number of packets dropped by the
/// socket between the last recieved packet and this
/// received packet.
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
RxqOvfl(&'a u32),
/// Configure the transmission time of packets.
@@ -1227,18 +1179,18 @@ impl<'a> ControlMessage<'a> {
ControlMessage::ScmRights(fds) => {
fds as *const _ as *const u8
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(creds) => {
&creds.0 as *const libc::ucred as *const u8
}
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => {
// The kernel overwrites the data, we just zero it
// to make sure it's not uninitialized memory
unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
return
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(iv) => {
#[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
let af_alg_iv = libc::af_alg_iv {
@@ -1263,11 +1215,11 @@ impl<'a> ControlMessage<'a> {
return
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetOp(op) => {
op as *const _ as *const u8
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetAeadAssoclen(len) => {
len as *const _ as *const u8
},
@@ -1276,21 +1228,20 @@ impl<'a> ControlMessage<'a> {
ControlMessage::UdpGsoSegments(gso_size) => {
gso_size as *const _ as *const u8
},
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(addr) => addr as *const _ as *const u8,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(limit) => limit as *const _ as *const u8,
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(drop_count) => {
drop_count as *const _ as *const u8
},
@@ -1314,23 +1265,23 @@ impl<'a> ControlMessage<'a> {
ControlMessage::ScmRights(fds) => {
mem::size_of_val(fds)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(creds) => {
mem::size_of_val(creds)
}
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => {
mem::size_of::<libc::cmsgcred>()
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(iv) => {
mem::size_of::<&[u8]>() + iv.len()
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetOp(op) => {
mem::size_of_val(op)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetAeadAssoclen(len) => {
mem::size_of_val(len)
},
@@ -1339,21 +1290,22 @@ impl<'a> ControlMessage<'a> {
ControlMessage::UdpGsoSegments(gso_size) => {
mem::size_of_val(gso_size)
},
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(addr) => mem::size_of_val(addr),
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(limit) => {
+ mem::size_of_val(limit)
+ },
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(drop_count) => {
mem::size_of_val(drop_count)
},
@@ -1368,31 +1320,30 @@ impl<'a> ControlMessage<'a> {
fn cmsg_level(&self) -> libc::c_int {
match *self {
ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
#[cfg(target_os = "linux")]
#[cfg(feature = "net")]
ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(_) => libc::IPPROTO_IP,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(_) => libc::IPPROTO_IPV6,
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
#[cfg(target_os = "linux")]
ControlMessage::TxTime(_) => libc::SOL_SOCKET,
@@ -1403,19 +1354,19 @@ impl<'a> ControlMessage<'a> {
fn cmsg_type(&self) -> libc::c_int {
match *self {
ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => libc::SCM_CREDS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(_) => {
libc::ALG_SET_IV
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetOp(_) => {
libc::ALG_SET_OP
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetAeadAssoclen(_) => {
libc::ALG_SET_AEAD_ASSOCLEN
},
@@ -1424,21 +1375,20 @@ impl<'a> ControlMessage<'a> {
ControlMessage::UdpGsoSegments(_) => {
libc::UDP_SEGMENT
},
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(_) => libc::IP_SENDSRCADDR,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(_) => libc::IPV6_HOPLIMIT,
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(_) => {
libc::SO_RXQ_OVFL
},
@@ -1452,10 +1402,12 @@ impl<'a> ControlMessage<'a> {
// Unsafe: cmsg must point to a valid cmsghdr with enough space to
// encode self.
unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
- (*cmsg).cmsg_level = self.cmsg_level();
- (*cmsg).cmsg_type = self.cmsg_type();
- (*cmsg).cmsg_len = self.cmsg_len();
- self.copy_to_cmsg_data(CMSG_DATA(cmsg));
+ unsafe {
+ (*cmsg).cmsg_level = self.cmsg_level();
+ (*cmsg).cmsg_type = self.cmsg_type();
+ (*cmsg).cmsg_len = self.cmsg_len();
+ self.copy_to_cmsg_data( CMSG_DATA(cmsg) );
+ }
}
}
@@ -1479,7 +1431,7 @@ impl<'a> ControlMessage<'a> {
/// let (r, w) = pipe().unwrap();
///
/// let iov = [IoSlice::new(b"hello")];
-/// let fds = [r];
+/// let fds = [r.as_raw_fd()];
/// let cmsg = ControlMessage::ScmRights(&fds);
/// sendmsg::<()>(fd1.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
/// ```
@@ -1496,7 +1448,7 @@ impl<'a> ControlMessage<'a> {
/// let (r, w) = pipe().unwrap();
///
/// let iov = [IoSlice::new(b"hello")];
-/// let fds = [r];
+/// let fds = [r.as_raw_fd()];
/// let cmsg = ControlMessage::ScmRights(&fds);
/// sendmsg(fd.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
/// ```
@@ -1535,12 +1487,7 @@ pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
///
/// # References
/// [`sendmsg`](fn.sendmsg.html)
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
pub fn sendmmsg<'a, XS, AS, C, I, S>(
fd: RawFd,
data: &'a mut MultiHeaders<S>,
@@ -1556,7 +1503,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
AS: AsRef<[Option<S>]>,
I: AsRef<[IoSlice<'a>]> + 'a,
C: AsRef<[ControlMessage<'a>]> + 'a,
- S: SockaddrLike + 'a
+ S: SockaddrLike + 'a,
{
let mut count = 0;
@@ -1564,11 +1511,11 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() {
let p = &mut mmsghdr.msg_hdr;
- p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
+ p.msg_iov = slice.as_ref().as_ptr().cast_mut().cast();
p.msg_iovlen = slice.as_ref().len() as _;
p.msg_namelen = addr.as_ref().map_or(0, S::len);
- p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr) as _;
+ p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr).cast_mut().cast();
// Encode each cmsg. This must happen after initializing the header because
// CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
@@ -1583,9 +1530,16 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) };
}
- count = i+1;
+ // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
+ // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
+ // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
+ // other words: `count` doesn't overflow
+ count = i + 1;
}
+ // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
+ // maximum number of messages that can be sent safely (i.e. `count` is the minimum of the sizes of `slices`,
+ // `data.items` and `addrs`)
let sent = Errno::result(unsafe {
libc::sendmmsg(
fd,
@@ -1604,12 +1558,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[derive(Debug)]
/// Preallocated structures needed for [`recvmmsg`] and [`sendmmsg`] functions
pub struct MultiHeaders<S> {
@@ -1622,12 +1571,7 @@ pub struct MultiHeaders<S> {
msg_controllen: usize,
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
impl<S> MultiHeaders<S> {
/// Preallocate structure used by [`recvmmsg`] and [`sendmmsg`] takes number of headers to preallocate
///
@@ -1652,7 +1596,7 @@ impl<S> MultiHeaders<S> {
.enumerate()
.map(|(ix, address)| {
let (ptr, cap) = match &mut cmsg_buffers {
- Some(v) => ((&mut v[ix * msg_controllen] as *mut u8), msg_controllen),
+ Some(v) => (&mut v[ix * msg_controllen] as *mut u8, msg_controllen),
None => (std::ptr::null_mut(), 0),
};
let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, address.as_mut_ptr()) };
@@ -1697,12 +1641,7 @@ impl<S> MultiHeaders<S> {
// always produce the desired results - see https://github.com/nix-rust/nix/pull/1744 for more
// details
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
pub fn recvmmsg<'a, XS, S, I>(
fd: RawFd,
data: &'a mut MultiHeaders<S>,
@@ -1711,14 +1650,19 @@ pub fn recvmmsg<'a, XS, S, I>(
mut timeout: Option<crate::sys::time::TimeSpec>,
) -> crate::Result<MultiResults<'a, S>>
where
- XS: IntoIterator<Item = &'a I>,
- I: AsRef<[IoSliceMut<'a>]> + 'a,
+ XS: IntoIterator<Item = &'a mut I>,
+ I: AsMut<[IoSliceMut<'a>]> + 'a,
{
let mut count = 0;
for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() {
let p = &mut mmsghdr.msg_hdr;
- p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
- p.msg_iovlen = slice.as_ref().len() as _;
+ p.msg_iov = slice.as_mut().as_mut_ptr().cast();
+ p.msg_iovlen = slice.as_mut().len() as _;
+
+ // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
+ // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
+ // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
+ // other words: `count` doesn't overflow
count = i + 1;
}
@@ -1726,6 +1670,8 @@ where
.as_mut()
.map_or_else(std::ptr::null_mut, |t| t as *mut _ as *mut libc::timespec);
+ // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
+ // maximum number of messages that can be received safely (i.e. `count` is the minimum of the sizes of `slices` and `data.items`)
let received = Errno::result(unsafe {
libc::recvmmsg(
fd,
@@ -1743,16 +1689,9 @@ where
})
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-#[derive(Debug)]
/// Iterator over results of [`recvmmsg`]/[`sendmmsg`]
-///
-///
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
+#[derive(Debug)]
pub struct MultiResults<'a, S> {
// preallocated structures
rmm: &'a MultiHeaders<S>,
@@ -1760,12 +1699,7 @@ pub struct MultiResults<'a, S> {
received: usize,
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
impl<'a, S> Iterator for MultiResults<'a, S>
where
S: Copy + SockaddrLike,
@@ -1838,108 +1772,6 @@ impl<'a> Iterator for IoSliceIterator<'a> {
}
}
-// test contains both recvmmsg and timestaping which is linux only
-// there are existing tests for recvmmsg only in tests/
-#[cfg(target_os = "linux")]
-#[cfg(test)]
-mod test {
- use crate::sys::socket::{AddressFamily, ControlMessageOwned};
- use crate::*;
- use std::str::FromStr;
- use std::os::unix::io::AsRawFd;
-
- #[cfg_attr(qemu, ignore)]
- #[test]
- fn test_recvmm2() -> crate::Result<()> {
- use crate::sys::socket::{
- sendmsg, setsockopt, socket, sockopt::Timestamping, MsgFlags, SockFlag, SockType,
- SockaddrIn, TimestampingFlag,
- };
- use std::io::{IoSlice, IoSliceMut};
-
- let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
-
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- )?;
-
- let rsock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::SOCK_NONBLOCK,
- None,
- )?;
-
- crate::sys::socket::bind(rsock.as_raw_fd(), &sock_addr)?;
-
- setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?;
-
- let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
-
- let mut recv_buf = vec![0; 1024];
-
- let mut recv_iovs = Vec::new();
- let mut pkt_iovs = Vec::new();
-
- for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() {
- pkt_iovs.push(IoSliceMut::new(chunk));
- if ix % 2 == 1 {
- recv_iovs.push(pkt_iovs);
- pkt_iovs = Vec::new();
- }
- }
- drop(pkt_iovs);
-
- let flags = MsgFlags::empty();
- let iov1 = [IoSlice::new(&sbuf)];
-
- let cmsg = cmsg_space!(crate::sys::socket::Timestamps);
- sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
-
- let mut data = super::MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
-
- let t = sys::time::TimeSpec::from_duration(std::time::Duration::from_secs(10));
-
- let recv = super::recvmmsg(rsock.as_raw_fd(), &mut data, recv_iovs.iter(), flags, Some(t))?;
-
- for rmsg in recv {
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- let mut saw_time = false;
- let mut recvd = 0;
- for cmsg in rmsg.cmsgs() {
- if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
- let ts = timestamps.system;
-
- let sys_time =
- crate::time::clock_gettime(crate::time::ClockId::CLOCK_REALTIME)?;
- let diff = if ts > sys_time {
- ts - sys_time
- } else {
- sys_time - ts
- };
- assert!(std::time::Duration::from(diff).as_secs() < 60);
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- {
- saw_time = true;
- }
- }
- }
-
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- assert!(saw_time);
-
- for iov in rmsg.iovs() {
- recvd += iov.len();
- }
- assert_eq!(recvd, 400);
- }
-
- Ok(())
- }
-}
unsafe fn read_mhdr<'a, 'i, S>(
mhdr: msghdr,
r: isize,
@@ -1951,19 +1783,23 @@ unsafe fn read_mhdr<'a, 'i, S>(
// The cast is not unnecessary on all platforms.
#[allow(clippy::unnecessary_cast)]
let cmsghdr = {
- if mhdr.msg_controllen > 0 {
+ let ptr = if mhdr.msg_controllen > 0 {
debug_assert!(!mhdr.msg_control.is_null());
debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
- CMSG_FIRSTHDR(&mhdr as *const msghdr)
+ unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) }
} else {
ptr::null()
- }.as_ref()
+ };
+
+ unsafe {
+ ptr.as_ref()
+ }
};
// Ignore errors if this socket address has statically-known length
//
// This is to ensure that unix socket addresses have their length set appropriately.
- let _ = address.set_length(mhdr.msg_namelen as usize);
+ let _ = unsafe { address.set_length(mhdr.msg_namelen as usize) };
RecvMsg {
bytes: r as usize,
@@ -2000,14 +1836,16 @@ unsafe fn pack_mhdr_to_receive<S>(
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
- (*p).msg_name = address as *mut c_void;
- (*p).msg_namelen = S::size();
- (*p).msg_iov = iov_buffer as *mut iovec;
- (*p).msg_iovlen = iov_buffer_len as _;
- (*p).msg_control = cmsg_buffer as *mut c_void;
- (*p).msg_controllen = cmsg_capacity as _;
- (*p).msg_flags = 0;
- mhdr.assume_init()
+ unsafe {
+ (*p).msg_name = address as *mut c_void;
+ (*p).msg_namelen = S::size();
+ (*p).msg_iov = iov_buffer as *mut iovec;
+ (*p).msg_iovlen = iov_buffer_len as _;
+ (*p).msg_control = cmsg_buffer as *mut c_void;
+ (*p).msg_controllen = cmsg_capacity as _;
+ (*p).msg_flags = 0;
+ mhdr.assume_init()
+ }
}
fn pack_mhdr_to_send<'a, I, C, S>(
@@ -2025,7 +1863,7 @@ fn pack_mhdr_to_send<'a, I, C, S>(
// The message header must be initialized before the individual cmsgs.
let cmsg_ptr = if capacity > 0 {
- cmsg_buffer.as_mut_ptr() as *mut c_void
+ cmsg_buffer.as_mut_ptr().cast()
} else {
ptr::null_mut()
};
@@ -2035,11 +1873,11 @@ fn pack_mhdr_to_send<'a, I, C, S>(
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
- (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()) as *mut _;
+ (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()).cast_mut().cast();
(*p).msg_namelen = addr.map(S::len).unwrap_or(0);
// transmute iov into a mutable pointer. sendmsg doesn't really mutate
// the buffer, but the standard says that it takes a mutable pointer
- (*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
+ (*p).msg_iov = iov.as_ref().as_ptr().cast_mut().cast();
(*p).msg_iovlen = iov.as_ref().len() as _;
(*p).msg_control = cmsg_ptr;
(*p).msg_controllen = capacity as _;
@@ -2166,17 +2004,51 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>(
Errno::result(res)?;
// Safe because socketpair returned success.
- unsafe {
- Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1])))
+ unsafe { Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1]))) }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Backlog(i32);
+
+impl Backlog {
+ /// Sets the listen queue size to system `SOMAXCONN` value
+ pub const MAXCONN: Self = Self(libc::SOMAXCONN);
+ /// Sets the listen queue size to -1 for system supporting it
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
+ pub const MAXALLOWABLE: Self = Self(-1);
+
+ /// Create a `Backlog`, an `EINVAL` will be returned if `val` is invalid.
+ pub fn new<I: Into<i32>>(val: I) -> Result<Self> {
+ cfg_if! {
+ if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
+ const MIN: i32 = -1;
+ } else {
+ const MIN: i32 = 0;
+ }
+ }
+
+ let val = val.into();
+
+ if !(MIN..Self::MAXCONN.0).contains(&val) {
+ return Err(Errno::EINVAL);
+ }
+
+ Ok(Self(val))
+ }
+}
+
+impl From<Backlog> for i32 {
+ fn from(backlog: Backlog) -> Self {
+ backlog.0
}
}
/// Listen for connections on a socket
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
-pub fn listen<F: AsFd>(sock: &F, backlog: usize) -> Result<()> {
+pub fn listen<F: AsFd>(sock: &F, backlog: Backlog) -> Result<()> {
let fd = sock.as_fd().as_raw_fd();
- let res = unsafe { libc::listen(fd, backlog as c_int) };
+ let res = unsafe { libc::listen(fd, backlog.into()) };
Errno::result(res).map(drop)
}
@@ -2211,14 +2083,12 @@ pub fn accept(sockfd: RawFd) -> Result<RawFd> {
target_arch = "x86_64"
)
),
- target_os = "dragonfly",
+ freebsdlike,
+ netbsdlike,
target_os = "emscripten",
- target_os = "freebsd",
target_os = "fuchsia",
- target_os = "illumos",
+ solarish,
target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"
))]
pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
let res = unsafe {
@@ -2245,7 +2115,7 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
unsafe {
let ret = libc::recv(
sockfd,
- buf.as_mut_ptr() as *mut c_void,
+ buf.as_mut_ptr().cast(),
buf.len() as size_t,
flags.bits(),
);
@@ -2269,20 +2139,14 @@ pub fn recvfrom<T: SockaddrLike>(
let ret = Errno::result(libc::recvfrom(
sockfd,
- buf.as_mut_ptr() as *mut c_void,
+ buf.as_mut_ptr().cast(),
buf.len() as size_t,
0,
- addr.as_mut_ptr() as *mut sockaddr,
+ addr.as_mut_ptr().cast(),
&mut len as *mut socklen_t,
))? as usize;
- Ok((
- ret,
- T::from_raw(
- addr.assume_init().as_ptr(),
- Some(len),
- ),
- ))
+ Ok((ret, T::from_raw(addr.assume_init().as_ptr(), Some(len))))
}
}
@@ -2298,7 +2162,7 @@ pub fn sendto(
let ret = unsafe {
libc::sendto(
fd,
- buf.as_ptr() as *const c_void,
+ buf.as_ptr().cast(),
buf.len() as size_t,
flags.bits(),
addr.as_ptr(),
@@ -2314,12 +2178,7 @@ pub fn sendto(
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
let ret = unsafe {
- libc::send(
- fd,
- buf.as_ptr() as *const c_void,
- buf.len() as size_t,
- flags.bits(),
- )
+ libc::send(fd, buf.as_ptr().cast(), buf.len() as size_t, flags.bits())
};
Errno::result(ret).map(|r| r as usize)
@@ -2386,8 +2245,7 @@ pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let mut addr = mem::MaybeUninit::<T>::uninit();
let mut len = T::size();
- let ret =
- libc::getpeername(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len);
+ let ret = libc::getpeername(fd, addr.as_mut_ptr().cast(), &mut len);
Errno::result(ret)?;
@@ -2403,8 +2261,7 @@ pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let mut addr = mem::MaybeUninit::<T>::uninit();
let mut len = T::size();
- let ret =
- libc::getsockname(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len);
+ let ret = libc::getsockname(fd, addr.as_mut_ptr().cast(), &mut len);
Errno::result(ret)?;
@@ -2439,27 +2296,3 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
}
}
-#[cfg(test)]
-mod tests {
- #[cfg(not(target_os = "redox"))]
- #[test]
- fn can_use_cmsg_space() {
- let _ = cmsg_space!(u8);
- }
-
- #[cfg(not(any(
- target_os = "redox",
- target_os = "linux",
- target_os = "android"
- )))]
- #[test]
- fn can_open_routing_socket() {
- let _ = super::socket(
- super::AddressFamily::Route,
- super::SockType::Raw,
- super::SockFlag::empty(),
- None,
- )
- .expect("Failed to open routing socket");
- }
-}
diff --git a/third_party/rust/nix/src/sys/socket/sockopt.rs b/third_party/rust/nix/src/sys/socket/sockopt.rs
index 44f3ebbc1d..4357695f56 100644
--- a/third_party/rust/nix/src/sys/socket/sockopt.rs
+++ b/third_party/rust/nix/src/sys/socket/sockopt.rs
@@ -7,7 +7,6 @@ use cfg_if::cfg_if;
use libc::{self, c_int, c_void, socklen_t};
use std::ffi::{OsStr, OsString};
use std::mem::{self, MaybeUninit};
-#[cfg(target_family = "unix")]
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{AsFd, AsRawFd};
@@ -128,7 +127,7 @@ macro_rules! getsockopt_impl {
/// both of them.
/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for.
/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets*
-/// (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
+/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
/// and more. Please refer to your system manual for more options. Will be passed as the second
/// argument (`level`) to the `getsockopt`/`setsockopt` call.
/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
@@ -261,7 +260,7 @@ sockopt_impl!(
libc::SO_REUSEADDR,
bool
);
-#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
+#[cfg(not(solarish))]
sockopt_impl!(
/// Permits multiple AF_INET or AF_INET6 sockets to be bound to an
/// identical socket address.
@@ -318,7 +317,7 @@ sockopt_impl!(
super::IpMembershipRequest
);
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -329,14 +328,7 @@ cfg_if! {
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Leave an IPv6 multicast group.
Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
- } else if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))] {
+ } else if #[cfg(any(bsd, solarish))] {
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -365,6 +357,17 @@ sockopt_impl!(
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ /// Set or read the hop limit value of outgoing IPv6 multicast packets for
+ /// this socket.
+ Ipv6MulticastHops,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_MULTICAST_HOPS,
+ libc::c_int
+);
+#[cfg(feature = "net")]
+sockopt_impl!(
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Set or read a boolean integer argument that determines whether sent
/// multicast packets should be looped back to the local sockets.
IpMulticastLoop,
@@ -408,7 +411,7 @@ sockopt_impl!(
libc::IPV6_TCLASS,
libc::c_int
);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "fuchsia"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -420,6 +423,20 @@ sockopt_impl!(
libc::IP_FREEBIND,
bool
);
+#[cfg(linux_android)]
+#[cfg(feature = "net")]
+sockopt_impl!(
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ /// If enabled, the kernel will not reserve an ephemeral port when binding
+ /// socket with a port number of 0. The port will later be automatically
+ /// chosen at connect time, in a way that allows sharing a source port as
+ /// long as the 4-tuple is unique.
+ IpBindAddressNoPort,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_BIND_ADDRESS_NO_PORT,
+ bool
+);
sockopt_impl!(
/// Specify the receiving timeout until reporting an error.
ReceiveTimeout,
@@ -477,12 +494,7 @@ sockopt_impl!(
libc::SO_KEEPALIVE,
bool
);
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
-))]
+#[cfg(any(freebsdlike, apple_targets))]
sockopt_impl!(
/// Get the credentials of the peer process of a connected unix domain
/// socket.
@@ -492,7 +504,7 @@ sockopt_impl!(
libc::LOCAL_PEERCRED,
super::XuCred
);
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(apple_targets)]
sockopt_impl!(
/// Get the PID of the peer process of a connected unix domain socket.
LocalPeerPid,
@@ -501,7 +513,7 @@ sockopt_impl!(
libc::LOCAL_PEERPID,
libc::c_int
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Return the credentials of the foreign process connected to this socket.
PeerCredentials,
@@ -510,7 +522,18 @@ sockopt_impl!(
libc::SO_PEERCRED,
super::UnixCredentials
);
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(target_os = "freebsd")]
+#[cfg(feature = "net")]
+sockopt_impl!(
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ /// Get backlog limit of the socket
+ ListenQLimit,
+ GetOnly,
+ libc::SOL_SOCKET,
+ libc::SO_LISTENQLIMIT,
+ u32
+);
+#[cfg(apple_targets)]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -522,12 +545,7 @@ sockopt_impl!(
libc::TCP_KEEPALIVE,
u32
);
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"
-))]
+#[cfg(any(freebsdlike, linux_android))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -540,7 +558,7 @@ sockopt_impl!(
u32
);
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
sockopt_impl!(
/// The maximum segment size for outgoing TCP packets.
TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
@@ -550,7 +568,11 @@ cfg_if! {
TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
}
}
-#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "redox")))]
+#[cfg(not(any(
+ target_os = "openbsd",
+ target_os = "haiku",
+ target_os = "redox"
+)))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -562,7 +584,7 @@ sockopt_impl!(
libc::TCP_KEEPCNT,
u32
);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "fuchsia"))]
sockopt_impl!(
#[allow(missing_docs)]
// Not documented by Linux!
@@ -572,7 +594,11 @@ sockopt_impl!(
libc::TCP_REPAIR,
u32
);
-#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "redox")))]
+#[cfg(not(any(
+ target_os = "openbsd",
+ target_os = "haiku",
+ target_os = "redox"
+)))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -596,6 +622,26 @@ sockopt_impl!(
libc::TCP_USER_TIMEOUT,
u32
);
+#[cfg(linux_android)]
+#[cfg(feature = "net")]
+sockopt_impl!(
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ /// Enables TCP Fast Open (RFC 7413) on a connecting socket. If a fast open
+ /// cookie is not available (first attempt to connect), `connect` syscall
+ /// will behave as usual, except for internally trying to solicit a cookie
+ /// from remote peer. When cookie is available, the next `connect` syscall
+ /// will immediately succeed without actually establishing TCP connection.
+ /// The connection establishment will be defered till the next `write` or
+ /// `sendmsg` syscalls on the socket, allowing TCP prtocol to establish
+ /// connection and send data in the same packets. Note: calling `read` right
+ /// after `connect` without `write` on the socket will cause the blocking
+ /// socket to be blocked forever.
+ TcpFastOpenConnect,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_FASTOPEN_CONNECT,
+ bool
+);
sockopt_impl!(
/// Sets or gets the maximum socket receive buffer in bytes.
RcvBuf,
@@ -612,7 +658,7 @@ sockopt_impl!(
libc::SO_SNDBUF,
usize
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can
/// perform the same task as `SO_RCVBUF`, but the `rmem_max limit` can be
@@ -623,7 +669,7 @@ sockopt_impl!(
libc::SO_RCVBUFFORCE,
usize
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can
/// perform the same task as `SO_SNDBUF`, but the `wmem_max` limit can be
@@ -652,7 +698,7 @@ sockopt_impl!(
libc::SO_ACCEPTCONN,
bool
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Bind this socket to a particular device like “eth0”.
BindToDevice,
@@ -661,7 +707,7 @@ sockopt_impl!(
libc::SO_BINDTODEVICE,
OsString<[u8; libc::IFNAMSIZ]>
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -673,7 +719,7 @@ sockopt_impl!(
libc::SO_ORIGINAL_DST,
libc::sockaddr_in
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
#[allow(missing_docs)]
// Not documented by Linux!
@@ -683,7 +729,7 @@ sockopt_impl!(
libc::IP6T_SO_ORIGINAL_DST,
libc::sockaddr_in6
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Specifies exact type of timestamping information collected by the kernel
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
@@ -693,7 +739,7 @@ sockopt_impl!(
libc::SO_TIMESTAMPING,
super::TimestampingFlag
);
-#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "redox")))]
+#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "hurd", target_os = "redox")))]
sockopt_impl!(
/// Enable or disable the receiving of the `SO_TIMESTAMP` control message.
ReceiveTimestamp,
@@ -702,7 +748,7 @@ sockopt_impl!(
libc::SO_TIMESTAMP,
bool
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Enable or disable the receiving of the `SO_TIMESTAMPNS` control message.
ReceiveTimestampns,
@@ -719,9 +765,9 @@ sockopt_impl!(
Both,
libc::SOL_SOCKET,
libc::SO_TS_CLOCK,
- i32
+ super::SocketTimestamp
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -806,7 +852,7 @@ sockopt_impl!(
libc::SO_MARK,
u32
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Enable or disable the receiving of the `SCM_CREDENTIALS` control
/// message.
@@ -828,13 +874,7 @@ sockopt_impl!(
libc::TCP_CONGESTION,
OsString<[u8; TCP_CA_NAME_MAX]>
);
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -846,15 +886,7 @@ sockopt_impl!(
libc::IP_PKTINFO,
bool
);
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", apple_targets, netbsdlike))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -866,13 +898,7 @@ sockopt_impl!(
libc::IPV6_RECVPKTINFO,
bool
);
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(bsd)]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -884,13 +910,7 @@ sockopt_impl!(
libc::IP_RECVIF,
bool
);
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(bsd)]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -902,7 +922,7 @@ sockopt_impl!(
libc::IP_RECVDSTADDR,
bool
);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -948,7 +968,7 @@ sockopt_impl!(
libc::SO_TXTIME,
libc::sock_txtime
);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "fuchsia"))]
sockopt_impl!(
/// Indicates that an unsigned 32-bit value ancillary message (cmsg) should
/// be attached to received skbs indicating the number of packets dropped by
@@ -969,7 +989,7 @@ sockopt_impl!(
libc::IPV6_V6ONLY,
bool
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Enable extended reliable error message passing.
Ipv4RecvErr,
@@ -978,7 +998,7 @@ sockopt_impl!(
libc::IP_RECVERR,
bool
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Control receiving of asynchronous error options.
Ipv6RecvErr,
@@ -987,7 +1007,7 @@ sockopt_impl!(
libc::IPV6_RECVERR,
bool
);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
sockopt_impl!(
/// Fetch the current system-estimated Path MTU.
IpMtu,
@@ -996,7 +1016,7 @@ sockopt_impl!(
libc::IP_MTU,
libc::c_int
);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
sockopt_impl!(
/// Set or retrieve the current time-to-live field that is used in every
/// packet sent from this socket.
@@ -1006,7 +1026,7 @@ sockopt_impl!(
libc::IP_TTL,
libc::c_int
);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
sockopt_impl!(
/// Set the unicast hop limit for the socket.
Ipv6Ttl,
@@ -1015,7 +1035,7 @@ sockopt_impl!(
libc::IPV6_UNICAST_HOPS,
libc::c_int
);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -1027,7 +1047,7 @@ sockopt_impl!(
libc::IPV6_ORIGDSTADDR,
bool
);
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
sockopt_impl!(
/// Set "don't fragment packet" flag on the IP packet.
IpDontFrag,
@@ -1036,12 +1056,7 @@ sockopt_impl!(
libc::IP_DONTFRAG,
bool
);
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
-))]
+#[cfg(any(linux_android, apple_targets))]
sockopt_impl!(
/// Set "don't fragment packet" flag on the IPv6 packet.
Ipv6DontFrag,
@@ -1053,13 +1068,13 @@ sockopt_impl!(
#[allow(missing_docs)]
// Not documented by Linux!
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[derive(Copy, Clone, Debug)]
pub struct AlgSetAeadAuthSize;
// ALG_SET_AEAD_AUTH_SIZE read the length from passed `option_len`
// See https://elixir.bootlin.com/linux/v4.4/source/crypto/af_alg.c#L222
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
impl SetSockOpt for AlgSetAeadAuthSize {
type Val = usize;
@@ -1079,18 +1094,18 @@ impl SetSockOpt for AlgSetAeadAuthSize {
#[allow(missing_docs)]
// Not documented by Linux!
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[derive(Clone, Debug)]
pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
impl<T> Default for AlgSetKey<T> {
fn default() -> Self {
AlgSetKey(Default::default())
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
impl<T> SetSockOpt for AlgSetKey<T>
where
T: AsRef<[u8]> + Clone,
@@ -1103,7 +1118,54 @@ where
fd.as_fd().as_raw_fd(),
libc::SOL_ALG,
libc::ALG_SET_KEY,
- val.as_ref().as_ptr() as *const _,
+ val.as_ref().as_ptr().cast(),
+ val.as_ref().len() as libc::socklen_t,
+ );
+ Errno::result(res).map(drop)
+ }
+ }
+}
+
+/// Set the Upper Layer Protocol (ULP) on the TCP socket.
+///
+/// For example, to enable the TLS ULP on a socket, the C function call would be:
+///
+/// ```c
+/// setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));
+/// ```
+///
+/// ... and the `nix` equivalent is:
+///
+/// ```ignore,rust
+/// setsockopt(sock, TcpUlp::default(), b"tls");
+/// ```
+///
+/// Note that the ULP name does not need a trailing NUL terminator (`\0`).
+#[cfg(linux_android)]
+#[derive(Clone, Debug)]
+pub struct TcpUlp<T>(::std::marker::PhantomData<T>);
+
+#[cfg(linux_android)]
+impl<T> Default for TcpUlp<T> {
+ fn default() -> Self {
+ TcpUlp(Default::default())
+ }
+}
+
+#[cfg(linux_android)]
+impl<T> SetSockOpt for TcpUlp<T>
+where
+ T: AsRef<[u8]> + Clone,
+{
+ type Val = T;
+
+ fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
+ unsafe {
+ let res = libc::setsockopt(
+ fd.as_fd().as_raw_fd(),
+ libc::SOL_TCP,
+ libc::TCP_ULP,
+ val.as_ref().as_ptr().cast(),
val.as_ref().len() as libc::socklen_t,
);
Errno::result(res).map(drop)
@@ -1111,6 +1173,113 @@ where
}
}
+/// Value used with the [`TcpTlsTx`] and [`TcpTlsRx`] socket options.
+#[cfg(target_os = "linux")]
+#[derive(Copy, Clone, Debug)]
+pub enum TlsCryptoInfo {
+ /// AES-128-GCM
+ Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128),
+
+ /// AES-256-GCM
+ Aes256Gcm(libc::tls12_crypto_info_aes_gcm_256),
+
+ /// CHACHA20-POLY1305
+ Chacha20Poly1305(libc::tls12_crypto_info_chacha20_poly1305),
+}
+
+/// Set the Kernel TLS write parameters on the TCP socket.
+///
+/// For example, the C function call would be:
+///
+/// ```c
+/// setsockopt(sock, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info));
+/// ```
+///
+/// ... and the `nix` equivalent is:
+///
+/// ```ignore,rust
+/// setsockopt(sock, TcpTlsTx, &crypto_info);
+/// ```
+#[cfg(target_os = "linux")]
+#[derive(Copy, Clone, Debug)]
+pub struct TcpTlsTx;
+
+#[cfg(target_os = "linux")]
+impl SetSockOpt for TcpTlsTx {
+ type Val = TlsCryptoInfo;
+
+ fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
+ let (ffi_ptr, ffi_len) = match val {
+ TlsCryptoInfo::Aes128Gcm(crypto_info) => {
+ (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
+ }
+ TlsCryptoInfo::Aes256Gcm(crypto_info) => {
+ (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
+ }
+ TlsCryptoInfo::Chacha20Poly1305(crypto_info) => {
+ (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
+ }
+ };
+ unsafe {
+ let res = libc::setsockopt(
+ fd.as_fd().as_raw_fd(),
+ libc::SOL_TLS,
+ libc::TLS_TX,
+ ffi_ptr,
+ ffi_len as libc::socklen_t,
+ );
+ Errno::result(res).map(drop)
+ }
+ }
+}
+
+/// Set the Kernel TLS read parameters on the TCP socket.
+///
+/// For example, the C function call would be:
+///
+/// ```c
+/// setsockopt(sock, SOL_TLS, TLS_RX, &crypto_info, sizeof(crypto_info));
+/// ```
+///
+/// ... and the `nix` equivalent is:
+///
+/// ```ignore,rust
+/// setsockopt(sock, TcpTlsRx, &crypto_info);
+/// ```
+#[cfg(target_os = "linux")]
+#[derive(Copy, Clone, Debug)]
+pub struct TcpTlsRx;
+
+#[cfg(target_os = "linux")]
+impl SetSockOpt for TcpTlsRx {
+ type Val = TlsCryptoInfo;
+
+ fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
+ let (ffi_ptr, ffi_len) = match val {
+ TlsCryptoInfo::Aes128Gcm(crypto_info) => {
+ (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
+ }
+ TlsCryptoInfo::Aes256Gcm(crypto_info) => {
+ (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
+ }
+ TlsCryptoInfo::Chacha20Poly1305(crypto_info) => {
+ (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
+ }
+ };
+ unsafe {
+ let res = libc::setsockopt(
+ fd.as_fd().as_raw_fd(),
+ libc::SOL_TLS,
+ libc::TLS_RX,
+ ffi_ptr,
+ ffi_len as libc::socklen_t,
+ );
+ Errno::result(res).map(drop)
+ }
+ }
+}
+
+
/*
*
* ===== Accessor helpers =====
@@ -1158,7 +1327,7 @@ impl<T> Get<T> for GetStruct<T> {
}
fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
+ self.val.as_mut_ptr().cast()
}
fn ffi_len(&mut self) -> *mut socklen_t {
@@ -1171,7 +1340,7 @@ impl<T> Get<T> for GetStruct<T> {
mem::size_of::<T>(),
"invalid getsockopt implementation"
);
- self.val.assume_init()
+ unsafe { self.val.assume_init() }
}
}
@@ -1209,7 +1378,7 @@ impl Get<bool> for GetBool {
}
fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
+ self.val.as_mut_ptr().cast()
}
fn ffi_len(&mut self) -> *mut socklen_t {
@@ -1222,7 +1391,7 @@ impl Get<bool> for GetBool {
mem::size_of::<c_int>(),
"invalid getsockopt implementation"
);
- self.val.assume_init() != 0
+ unsafe { self.val.assume_init() != 0 }
}
}
@@ -1243,7 +1412,7 @@ impl<'a> Set<'a, bool> for SetBool {
}
fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
+ mem::size_of_val(&self.val) as socklen_t
}
}
@@ -1262,7 +1431,7 @@ impl Get<u8> for GetU8 {
}
fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
+ self.val.as_mut_ptr().cast()
}
fn ffi_len(&mut self) -> *mut socklen_t {
@@ -1275,7 +1444,7 @@ impl Get<u8> for GetU8 {
mem::size_of::<u8>(),
"invalid getsockopt implementation"
);
- self.val.assume_init()
+ unsafe { self.val.assume_init() }
}
}
@@ -1294,7 +1463,7 @@ impl<'a> Set<'a, u8> for SetU8 {
}
fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
+ mem::size_of_val(&self.val) as socklen_t
}
}
@@ -1313,7 +1482,7 @@ impl Get<usize> for GetUsize {
}
fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
+ self.val.as_mut_ptr().cast()
}
fn ffi_len(&mut self) -> *mut socklen_t {
@@ -1326,7 +1495,7 @@ impl Get<usize> for GetUsize {
mem::size_of::<c_int>(),
"invalid getsockopt implementation"
);
- self.val.assume_init() as usize
+ unsafe { self.val.assume_init() as usize }
}
}
@@ -1345,7 +1514,7 @@ impl<'a> Set<'a, usize> for SetUsize {
}
fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
+ mem::size_of_val(&self.val) as socklen_t
}
}
@@ -1364,7 +1533,7 @@ impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
}
fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
+ self.val.as_mut_ptr().cast()
}
fn ffi_len(&mut self) -> *mut socklen_t {
@@ -1373,7 +1542,7 @@ impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
unsafe fn assume_init(self) -> OsString {
let len = self.len as usize;
- let mut v = self.val.assume_init();
+ let mut v = unsafe { self.val.assume_init() };
OsStr::from_bytes(&v.as_mut()[0..len]).to_owned()
}
}
@@ -1391,7 +1560,7 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> {
}
fn ffi_ptr(&self) -> *const c_void {
- self.val.as_bytes().as_ptr() as *const c_void
+ self.val.as_bytes().as_ptr().cast()
}
fn ffi_len(&self) -> socklen_t {
@@ -1399,72 +1568,3 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> {
}
}
-#[cfg(test)]
-mod test {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn can_get_peercred_on_unix_socket() {
- use super::super::*;
-
- let (a, b) = socketpair(
- AddressFamily::Unix,
- SockType::Stream,
- None,
- SockFlag::empty(),
- )
- .unwrap();
- let a_cred = getsockopt(&a, super::PeerCredentials).unwrap();
- let b_cred = getsockopt(&b, super::PeerCredentials).unwrap();
- assert_eq!(a_cred, b_cred);
- assert_ne!(a_cred.pid(), 0);
- }
-
- #[test]
- fn is_socket_type_unix() {
- use super::super::*;
-
- let (a, _b) = socketpair(
- AddressFamily::Unix,
- SockType::Stream,
- None,
- SockFlag::empty(),
- )
- .unwrap();
- let a_type = getsockopt(&a, super::SockType).unwrap();
- assert_eq!(a_type, SockType::Stream);
- }
-
- #[test]
- fn is_socket_type_dgram() {
- use super::super::*;
-
- let s = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- )
- .unwrap();
- let s_type = getsockopt(&s, super::SockType).unwrap();
- assert_eq!(s_type, SockType::Datagram);
- }
-
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- #[test]
- fn can_get_listen_on_tcp_socket() {
- use super::super::*;
-
- let s = socket(
- AddressFamily::Inet,
- SockType::Stream,
- SockFlag::empty(),
- None,
- )
- .unwrap();
- let s_listening = getsockopt(&s, super::AcceptConn).unwrap();
- assert!(!s_listening);
- listen(&s, 10).unwrap();
- let s_listening2 = getsockopt(&s, super::AcceptConn).unwrap();
- assert!(s_listening2);
- }
-}
diff --git a/third_party/rust/nix/src/sys/stat.rs b/third_party/rust/nix/src/sys/stat.rs
index 7e51c03a3f..c5854eec01 100644
--- a/third_party/rust/nix/src/sys/stat.rs
+++ b/third_party/rust/nix/src/sys/stat.rs
@@ -1,10 +1,6 @@
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
+#[cfg(any(apple_targets, target_os = "openbsd"))]
pub use libc::c_uint;
-#[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
+#[cfg(any(target_os = "netbsd", freebsdlike))]
pub use libc::c_ulong;
pub use libc::stat as FileStat;
pub use libc::{dev_t, mode_t};
@@ -43,7 +39,7 @@ libc_bitflags! {
S_IXUSR;
/// Read write and execute for group.
S_IRWXG;
- /// Read fr group.
+ /// Read for group.
S_IRGRP;
/// Write for group.
S_IWGRP;
@@ -65,26 +61,14 @@ libc_bitflags! {
}
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
+#[cfg(any(apple_targets, target_os = "openbsd"))]
pub type type_of_file_flag = c_uint;
-#[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
+#[cfg(any(freebsdlike, target_os = "netbsd"))]
pub type type_of_file_flag = c_ulong;
-#[cfg(any(
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "macos",
- target_os = "ios"
-))]
+#[cfg(bsd)]
libc_bitflags! {
/// File flags.
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub struct FileFlag: type_of_file_flag {
/// The file may only be appended to.
SF_APPEND;
@@ -101,7 +85,7 @@ libc_bitflags! {
#[cfg(any(target_os = "dragonfly"))]
SF_NOHISTORY;
/// The file may not be renamed or deleted.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
SF_NOUNLINK;
/// Mask of superuser changeable flags
SF_SETTABLE;
@@ -121,14 +105,13 @@ libc_bitflags! {
#[cfg(any(target_os = "dragonfly"))]
UF_CACHE;
/// File is compressed at the file system level.
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
UF_COMPRESSED;
/// The file may be hidden from directory listings at the application's
/// discretion.
#[cfg(any(
target_os = "freebsd",
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
))]
UF_HIDDEN;
/// The file may not be changed.
@@ -138,7 +121,7 @@ libc_bitflags! {
#[cfg(any(target_os = "dragonfly"))]
UF_NOHISTORY;
/// The file may not be renamed or deleted.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
UF_NOUNLINK;
/// The file is offline, or has the Windows and CIFS
/// `FILE_ATTRIBUTE_OFFLINE` attribute.
@@ -162,7 +145,7 @@ libc_bitflags! {
#[cfg(any(target_os = "freebsd"))]
UF_SYSTEM;
/// File renames and deletes are tracked.
- #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[cfg(apple_targets)]
UF_TRACKED;
#[cfg(any(target_os = "dragonfly"))]
UF_XLINK;
@@ -184,20 +167,15 @@ pub fn mknod<P: ?Sized + NixPath>(
}
/// Create a special or ordinary file, relative to a given directory.
-#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "redox",
- target_os = "haiku"
-)))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))]
pub fn mknodat<P: ?Sized + NixPath>(
- dirfd: RawFd,
+ dirfd: Option<RawFd>,
path: &P,
kind: SFlag,
perm: Mode,
dev: dev_t,
) -> Result<()> {
+ let dirfd = at_rawfd(dirfd);
let res = path.with_nix_path(|cstr| unsafe {
libc::mknodat(
dirfd,
@@ -211,19 +189,16 @@ pub fn mknodat<P: ?Sized + NixPath>(
}
#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub const fn major(dev: dev_t) -> u64 {
((dev >> 32) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)
}
#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub const fn minor(dev: dev_t) -> u64 {
((dev >> 12) & 0xffff_ff00) | ((dev) & 0x0000_00ff)
}
#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub const fn makedev(major: u64, minor: u64) -> dev_t {
((major & 0xffff_f000) << 32)
| ((major & 0x0000_0fff) << 8)
@@ -268,12 +243,12 @@ pub fn fstat(fd: RawFd) -> Result<FileStat> {
}
#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn fstatat<P: ?Sized + NixPath>(
- dirfd: RawFd,
+ dirfd: Option<RawFd>,
pathname: &P,
f: AtFlags,
) -> Result<FileStat> {
+ let dirfd = at_rawfd(dirfd);
let mut dst = mem::MaybeUninit::uninit();
let res = pathname.with_nix_path(|cstr| unsafe {
libc::fstatat(
@@ -324,7 +299,6 @@ pub enum FchmodatFlags {
///
/// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn fchmodat<P: ?Sized + NixPath>(
dirfd: Option<RawFd>,
path: &P,
@@ -383,12 +357,10 @@ pub fn utimes<P: ?Sized + NixPath>(
#[cfg(any(
target_os = "linux",
target_os = "haiku",
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn lutimes<P: ?Sized + NixPath>(
path: &P,
atime: &TimeVal,
@@ -404,6 +376,9 @@ pub fn lutimes<P: ?Sized + NixPath>(
/// Change the access and modification times of the file specified by a file descriptor.
///
+/// If you want to set the timestamp to now, use `TimeSpec::UTIME_NOW`. Use
+/// `TimeSpec::UTIME_OMIT` if you don't want to change it.
+///
/// # References
///
/// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
@@ -436,11 +411,13 @@ pub enum UtimensatFlags {
/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
/// former if the platforms you care about support it.
///
+/// If you want to set the timestamp to now, use `TimeSpec::UTIME_NOW`. Use
+/// `TimeSpec::UTIME_OMIT` if you don't want to change it.
+///
/// # References
///
/// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn utimensat<P: ?Sized + NixPath>(
dirfd: Option<RawFd>,
path: &P,
@@ -466,12 +443,12 @@ pub fn utimensat<P: ?Sized + NixPath>(
}
#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn mkdirat<P: ?Sized + NixPath>(
- fd: RawFd,
+ fd: Option<RawFd>,
path: &P,
mode: Mode,
) -> Result<()> {
+ let fd = at_rawfd(fd);
let res = path.with_nix_path(|cstr| unsafe {
libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t)
})?;
diff --git a/third_party/rust/nix/src/sys/statfs.rs b/third_party/rust/nix/src/sys/statfs.rs
index 5111df2e6e..b2315f4ceb 100644
--- a/third_party/rust/nix/src/sys/statfs.rs
+++ b/third_party/rust/nix/src/sys/statfs.rs
@@ -1,7 +1,7 @@
//! Get filesystem statistics, non-portably
//!
//! See [`statvfs`](crate::sys::statvfs) for a portable alternative.
-#[cfg(not(any(target_os = "linux", target_os = "android")))]
+#[cfg(not(linux_android))]
use std::ffi::CStr;
use std::fmt::{self, Debug};
use std::mem;
@@ -9,16 +9,7 @@ use std::os::unix::io::{AsFd, AsRawFd};
use cfg_if::cfg_if;
-#[cfg(all(
- feature = "mount",
- any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )
-))]
+#[cfg(all(feature = "mount", bsd))]
use crate::mount::MntFlags;
#[cfg(target_os = "linux")]
use crate::sys::statvfs::FsFlags;
@@ -26,15 +17,13 @@ use crate::{errno::Errno, NixPath, Result};
/// Identifies a mounted file system
#[cfg(target_os = "android")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub type fsid_t = libc::__fsid_t;
/// Identifies a mounted file system
#[cfg(not(target_os = "android"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub type fsid_t = libc::fsid_t;
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] {
+ if #[cfg(any(linux_android, target_os = "fuchsia"))] {
type type_of_statfs = libc::statfs64;
const LIBC_FSTATFS: unsafe extern fn
(fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
@@ -62,10 +51,12 @@ pub struct Statfs(type_of_statfs);
type fs_type_t = u32;
#[cfg(target_os = "android")]
type fs_type_t = libc::c_ulong;
-#[cfg(all(target_os = "linux", target_arch = "s390x"))]
+#[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
type fs_type_t = libc::c_uint;
#[cfg(all(target_os = "linux", target_env = "musl"))]
type fs_type_t = libc::c_ulong;
+#[cfg(all(target_os = "linux", target_env = "ohos"))]
+type fs_type_t = libc::c_ulong;
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
type fs_type_t = libc::c_int;
#[cfg(all(
@@ -73,6 +64,7 @@ type fs_type_t = libc::c_int;
not(any(
target_arch = "s390x",
target_env = "musl",
+ target_env = "ohos",
target_env = "uclibc"
))
))]
@@ -84,6 +76,7 @@ type fs_type_t = libc::__fsword_t;
target_os = "android",
all(target_os = "linux", target_arch = "s390x"),
all(target_os = "linux", target_env = "musl"),
+ all(target_os = "linux", target_env = "ohos"),
all(
target_os = "linux",
not(any(target_arch = "s390x", target_env = "musl"))
@@ -94,206 +87,203 @@ pub struct FsType(pub fs_type_t);
// These constants are defined without documentation in the Linux headers, so we
// can't very well document them here.
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const ADFS_SUPER_MAGIC: FsType =
FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const AFFS_SUPER_MAGIC: FsType =
FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const AFS_SUPER_MAGIC: FsType = FsType(libc::AFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const AUTOFS_SUPER_MAGIC: FsType =
FsType(libc::AUTOFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const BPF_FS_MAGIC: FsType = FsType(libc::BPF_FS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const BTRFS_SUPER_MAGIC: FsType =
FsType(libc::BTRFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const CGROUP2_SUPER_MAGIC: FsType =
FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const CGROUP_SUPER_MAGIC: FsType =
FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const CODA_SUPER_MAGIC: FsType =
FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const DEBUGFS_MAGIC: FsType = FsType(libc::DEBUGFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const DEVPTS_SUPER_MAGIC: FsType =
FsType(libc::DEVPTS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const ECRYPTFS_SUPER_MAGIC: FsType =
FsType(libc::ECRYPTFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const EXT2_SUPER_MAGIC: FsType =
FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const EXT3_SUPER_MAGIC: FsType =
FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const EXT4_SUPER_MAGIC: FsType =
FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const F2FS_SUPER_MAGIC: FsType =
FsType(libc::F2FS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const FUSE_SUPER_MAGIC: FsType =
FsType(libc::FUSE_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const FUTEXFS_SUPER_MAGIC: FsType =
FsType(libc::FUTEXFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const HOSTFS_SUPER_MAGIC: FsType =
FsType(libc::HOSTFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const HPFS_SUPER_MAGIC: FsType =
FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const ISOFS_SUPER_MAGIC: FsType =
FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const JFFS2_SUPER_MAGIC: FsType =
FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const MINIX2_SUPER_MAGIC2: FsType =
FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const MINIX2_SUPER_MAGIC: FsType =
FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const MINIX3_SUPER_MAGIC: FsType =
FsType(libc::MINIX3_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const MINIX_SUPER_MAGIC2: FsType =
FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const MINIX_SUPER_MAGIC: FsType =
FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const MSDOS_SUPER_MAGIC: FsType =
FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const NILFS_SUPER_MAGIC: FsType =
FsType(libc::NILFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const OCFS2_SUPER_MAGIC: FsType =
FsType(libc::OCFS2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const OPENPROM_SUPER_MAGIC: FsType =
FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const OVERLAYFS_SUPER_MAGIC: FsType =
FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const PROC_SUPER_MAGIC: FsType =
FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const QNX4_SUPER_MAGIC: FsType =
FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const QNX6_SUPER_MAGIC: FsType =
FsType(libc::QNX6_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const RDTGROUP_SUPER_MAGIC: FsType =
FsType(libc::RDTGROUP_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const REISERFS_SUPER_MAGIC: FsType =
FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const SECURITYFS_MAGIC: FsType =
FsType(libc::SECURITYFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const SELINUX_MAGIC: FsType = FsType(libc::SELINUX_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const SMACK_MAGIC: FsType = FsType(libc::SMACK_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const SYSFS_MAGIC: FsType = FsType(libc::SYSFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const TRACEFS_MAGIC: FsType = FsType(libc::TRACEFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const UDF_SUPER_MAGIC: FsType = FsType(libc::UDF_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const USBDEVICE_SUPER_MAGIC: FsType =
FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const XENFS_SUPER_MAGIC: FsType =
FsType(libc::XENFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[allow(missing_docs)]
pub const NSFS_MAGIC: FsType = FsType(libc::NSFS_MAGIC as fs_type_t);
-#[cfg(all(
- any(target_os = "linux", target_os = "android"),
- not(target_env = "musl")
-))]
+#[cfg(all(linux_android, not(target_env = "musl"), not(target_env = "ohos")))]
#[allow(missing_docs)]
pub const XFS_SUPER_MAGIC: FsType = FsType(libc::XFS_SUPER_MAGIC as fs_type_t);
@@ -302,39 +292,33 @@ impl Statfs {
#[cfg(not(any(
target_os = "openbsd",
target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos"
+ apple_targets,
)))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn filesystem_type(&self) -> FsType {
FsType(self.0.f_type)
}
/// Magic code defining system type
- #[cfg(not(any(target_os = "linux", target_os = "android")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(linux_android))]
pub fn filesystem_type_name(&self) -> &str {
let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
c_str.to_str().unwrap()
}
/// Optimal transfer block size
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
pub fn optimal_transfer_size(&self) -> i32 {
self.0.f_iosize
}
/// Optimal transfer block size
#[cfg(target_os = "openbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> u32 {
self.0.f_iosize
}
/// Optimal transfer block size
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
pub fn optimal_transfer_size(&self) -> u32 {
self.0.f_bsize
}
@@ -342,9 +326,9 @@ impl Statfs {
/// Optimal transfer block size
#[cfg(any(
target_os = "android",
- all(target_os = "linux", target_env = "musl")
+ all(target_os = "linux", target_env = "musl"),
+ all(target_os = "linux", target_env = "ohos")
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> libc::c_ulong {
self.0.f_bsize
}
@@ -355,46 +339,41 @@ impl Statfs {
not(any(
target_arch = "s390x",
target_env = "musl",
+ target_env = "ohos",
target_env = "uclibc"
))
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
self.0.f_bsize
}
/// Optimal transfer block size
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> libc::c_int {
self.0.f_bsize
}
/// Optimal transfer block size
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> libc::c_long {
self.0.f_iosize
}
/// Optimal transfer block size
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> u64 {
self.0.f_iosize
}
/// Size of a block
- #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(apple_targets, target_os = "openbsd"))]
pub fn block_size(&self) -> u32 {
self.0.f_bsize
}
/// Size of a block
// f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
pub fn block_size(&self) -> u32 {
self.0.f_bsize
}
@@ -402,7 +381,13 @@ impl Statfs {
/// Size of a block
// f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
#[cfg(all(target_os = "linux", target_env = "musl"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ pub fn block_size(&self) -> libc::c_ulong {
+ self.0.f_bsize
+ }
+
+ /// Size of a block
+ // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
+ #[cfg(all(target_os = "linux", target_env = "ohos"))]
pub fn block_size(&self) -> libc::c_ulong {
self.0.f_bsize
}
@@ -410,7 +395,6 @@ impl Statfs {
/// Size of a block
// f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> libc::c_int {
self.0.f_bsize
}
@@ -422,47 +406,34 @@ impl Statfs {
not(any(
target_arch = "s390x",
target_env = "musl",
+ target_env = "ohos",
target_env = "uclibc"
))
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> libc::__fsword_t {
self.0.f_bsize
}
/// Size of a block
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> u64 {
self.0.f_bsize
}
/// Size of a block
#[cfg(target_os = "android")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> libc::c_ulong {
self.0.f_bsize
}
/// Size of a block
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> libc::c_long {
self.0.f_bsize
}
/// Get the mount flags
- #[cfg(all(
- feature = "mount",
- any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(all(feature = "mount", bsd))]
#[allow(clippy::unnecessary_cast)] // Not unnecessary on all arches
pub fn flags(&self) -> MntFlags {
MntFlags::from_bits_truncate(self.0.f_flags as i32)
@@ -472,35 +443,30 @@ impl Statfs {
// The f_flags field exists on Android and Fuchsia too, but without man
// pages I can't tell if it can be cast to FsFlags.
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn flags(&self) -> FsFlags {
FsFlags::from_bits_truncate(self.0.f_flags as libc::c_ulong)
}
/// Maximum length of filenames
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> u32 {
self.0.f_namemax
}
/// Maximum length of filenames
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
pub fn maximum_name_length(&self) -> u32 {
self.0.f_namelen
}
/// Maximum length of filenames
#[cfg(all(target_os = "linux", target_env = "musl"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> libc::c_ulong {
self.0.f_namelen
}
/// Maximum length of filenames
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> libc::c_int {
self.0.f_namelen
}
@@ -511,173 +477,141 @@ impl Statfs {
not(any(
target_arch = "s390x",
target_env = "musl",
+ target_env = "ohos",
target_env = "uclibc"
))
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> libc::__fsword_t {
self.0.f_namelen
}
/// Maximum length of filenames
#[cfg(target_os = "android")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> libc::c_ulong {
self.0.f_namelen
}
/// Total data blocks in filesystem
#[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
+ apple_targets,
+ linux_android,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
- target_os = "linux",
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks(&self) -> u64 {
self.0.f_blocks
}
/// Total data blocks in filesystem
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks(&self) -> libc::c_long {
self.0.f_blocks
}
/// Total data blocks in filesystem
#[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks(&self) -> u32 {
self.0.f_blocks
}
/// Free blocks in filesystem
#[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
+ apple_targets,
+ linux_android,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
- target_os = "linux",
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_free(&self) -> u64 {
self.0.f_bfree
}
/// Free blocks in filesystem
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_free(&self) -> libc::c_long {
self.0.f_bfree
}
/// Free blocks in filesystem
#[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_free(&self) -> u32 {
self.0.f_bfree
}
/// Free blocks available to unprivileged user
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(apple_targets, linux_android, target_os = "fuchsia"))]
pub fn blocks_available(&self) -> u64 {
self.0.f_bavail
}
/// Free blocks available to unprivileged user
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_available(&self) -> libc::c_long {
self.0.f_bavail
}
/// Free blocks available to unprivileged user
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_available(&self) -> i64 {
self.0.f_bavail
}
/// Free blocks available to unprivileged user
#[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_available(&self) -> u32 {
self.0.f_bavail
}
/// Total file nodes in filesystem
#[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
+ apple_targets,
+ linux_android,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
- target_os = "linux",
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files(&self) -> u64 {
self.0.f_files
}
/// Total file nodes in filesystem
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files(&self) -> libc::c_long {
self.0.f_files
}
/// Total file nodes in filesystem
#[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files(&self) -> u32 {
self.0.f_files
}
/// Free file nodes in filesystem
#[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
+ apple_targets,
+ linux_android,
target_os = "fuchsia",
target_os = "openbsd",
- target_os = "linux",
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files_free(&self) -> u64 {
self.0.f_ffree
}
/// Free file nodes in filesystem
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files_free(&self) -> libc::c_long {
self.0.f_ffree
}
/// Free file nodes in filesystem
#[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files_free(&self) -> i64 {
self.0.f_ffree
}
/// Free file nodes in filesystem
#[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files_free(&self) -> u32 {
self.0.f_ffree
}
@@ -699,16 +633,7 @@ impl Debug for Statfs {
ds.field("files", &self.files());
ds.field("files_free", &self.files_free());
ds.field("filesystem_id", &self.filesystem_id());
- #[cfg(all(
- feature = "mount",
- any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )
- ))]
+ #[cfg(all(feature = "mount", bsd))]
ds.field("flags", &self.flags());
ds.finish()
}
@@ -747,107 +672,3 @@ pub fn fstatfs<Fd: AsFd>(fd: Fd) -> Result<Statfs> {
.map(|_| Statfs(stat.assume_init()))
}
}
-
-#[cfg(test)]
-mod test {
- use std::fs::File;
-
- use crate::sys::statfs::*;
- use crate::sys::statvfs::*;
- use std::path::Path;
-
- #[test]
- fn statfs_call() {
- check_statfs("/tmp");
- check_statfs("/dev");
- check_statfs("/run");
- check_statfs("/");
- }
-
- #[test]
- fn fstatfs_call() {
- check_fstatfs("/tmp");
- check_fstatfs("/dev");
- check_fstatfs("/run");
- check_fstatfs("/");
- }
-
- fn check_fstatfs(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes()).unwrap();
- let file = File::open(path).unwrap();
- let fs = fstatfs(&file).unwrap();
- assert_fs_equals(fs, vfs);
- }
-
- fn check_statfs(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes()).unwrap();
- let fs = statfs(path.as_bytes()).unwrap();
- assert_fs_equals(fs, vfs);
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
- assert_eq!(fs.files() as u64, vfs.files() as u64);
- assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
- assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
- }
-
- // This test is ignored because files_free/blocks_free can change after statvfs call and before
- // statfs call.
- #[test]
- #[ignore]
- fn statfs_call_strict() {
- check_statfs_strict("/tmp");
- check_statfs_strict("/dev");
- check_statfs_strict("/run");
- check_statfs_strict("/");
- }
-
- // This test is ignored because files_free/blocks_free can change after statvfs call and before
- // fstatfs call.
- #[test]
- #[ignore]
- fn fstatfs_call_strict() {
- check_fstatfs_strict("/tmp");
- check_fstatfs_strict("/dev");
- check_fstatfs_strict("/run");
- check_fstatfs_strict("/");
- }
-
- fn check_fstatfs_strict(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes());
- let file = File::open(path).unwrap();
- let fs = fstatfs(&file);
- assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
- }
-
- fn check_statfs_strict(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes());
- let fs = statfs(path.as_bytes());
- assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
- assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
- assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
- assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
- assert_eq!(fs.files() as u64, vfs.files() as u64);
- assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
- assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
- }
-}
diff --git a/third_party/rust/nix/src/sys/statvfs.rs b/third_party/rust/nix/src/sys/statvfs.rs
index 35424e5e27..db1abdd4fe 100644
--- a/third_party/rust/nix/src/sys/statvfs.rs
+++ b/third_party/rust/nix/src/sys/statvfs.rs
@@ -21,44 +21,34 @@ libc_bitflags!(
#[cfg(not(target_os = "haiku"))]
ST_NOSUID;
/// Do not interpret character or block-special devices
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ST_NODEV;
/// Do not allow execution of binaries on the filesystem
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ST_NOEXEC;
/// All IO should be done synchronously
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ST_SYNCHRONOUS;
/// Allow mandatory locks on the filesystem
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ST_MANDLOCK;
/// Write on file/directory/symlink
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
ST_WRITE;
/// Append-only file
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
ST_APPEND;
/// Immutable file
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
ST_IMMUTABLE;
/// Do not update access times on files
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ST_NOATIME;
/// Do not update access times on files
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ST_NODIRATIME;
/// Update access time relative to modify/change time
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"), not(target_env = "ohos"))))]
ST_RELATIME;
}
);
@@ -114,13 +104,18 @@ impl Statvfs {
}
/// Get the file system id
+ #[cfg(not(target_os = "hurd"))]
pub fn filesystem_id(&self) -> c_ulong {
self.0.f_fsid
}
+ /// Get the file system id
+ #[cfg(target_os = "hurd")]
+ pub fn filesystem_id(&self) -> u64 {
+ self.0.f_fsid
+ }
/// Get the mount flags
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn flags(&self) -> FsFlags {
FsFlags::from_bits_truncate(self.0.f_flag)
}
@@ -153,20 +148,3 @@ pub fn fstatvfs<Fd: AsFd>(fd: Fd) -> Result<Statvfs> {
.map(|_| Statvfs(stat.assume_init()))
}
}
-
-#[cfg(test)]
-mod test {
- use crate::sys::statvfs::*;
- use std::fs::File;
-
- #[test]
- fn statvfs_call() {
- statvfs(&b"/"[..]).unwrap();
- }
-
- #[test]
- fn fstatvfs_call() {
- let root = File::open("/").unwrap();
- fstatvfs(&root).unwrap();
- }
-}
diff --git a/third_party/rust/nix/src/sys/termios.rs b/third_party/rust/nix/src/sys/termios.rs
index ecaa3eaf8f..e006c2f1b0 100644
--- a/third_party/rust/nix/src/sys/termios.rs
+++ b/third_party/rust/nix/src/sys/termios.rs
@@ -85,28 +85,8 @@
//!
//! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust,ignore"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust"
-)]
+#![cfg_attr(bsd, doc = " ```rust,ignore")]
+#![cfg_attr(not(bsd), doc = " ```rust")]
//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -118,28 +98,8 @@
//!
//! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust,ignore"
-)]
+#![cfg_attr(bsd, doc = " ```rust")]
+#![cfg_attr(not(bsd), doc = " ```rust,ignore")]
//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -151,28 +111,8 @@
//!
//! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust,ignore"
-)]
+#![cfg_attr(bsd, doc = " ```rust")]
+#![cfg_attr(not(bsd), doc = " ```rust,ignore")]
//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -185,28 +125,8 @@
//! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
//! by specifying baud rates directly using `u32`s:
//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust,ignore"
-)]
+#![cfg_attr(bsd, doc = " ```rust")]
+#![cfg_attr(not(bsd), doc = " ```rust,ignore")]
//! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -246,7 +166,7 @@ pub struct Termios {
/// Control characters (see `termios.c_cc` documentation)
pub control_chars: [libc::cc_t; NCCS],
/// Line discipline (see `termios.c_line` documentation)
- #[cfg(any(target_os = "linux", target_os = "android",))]
+ #[cfg(linux_android)]
pub line_discipline: libc::cc_t,
/// Line discipline (see `termios.c_line` documentation)
#[cfg(target_os = "haiku")]
@@ -266,11 +186,7 @@ impl Termios {
termios.c_cflag = self.control_flags.bits();
termios.c_lflag = self.local_flags.bits();
termios.c_cc = self.control_chars;
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
+ #[cfg(any(linux_android, target_os = "haiku"))]
{
termios.c_line = self.line_discipline;
}
@@ -292,11 +208,7 @@ impl Termios {
termios.c_cflag = self.control_flags.bits();
termios.c_lflag = self.local_flags.bits();
termios.c_cc = self.control_chars;
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
+ #[cfg(any(linux_android, target_os = "haiku"))]
{
termios.c_line = self.line_discipline;
}
@@ -312,11 +224,7 @@ impl Termios {
self.control_flags = ControlFlags::from_bits_retain(termios.c_cflag);
self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag);
self.control_chars = termios.c_cc;
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
+ #[cfg(any(linux_android, target_os = "haiku"))]
{
self.line_discipline = termios.c_line;
}
@@ -332,11 +240,7 @@ impl From<libc::termios> for Termios {
control_flags: ControlFlags::from_bits_truncate(termios.c_cflag),
local_flags: LocalFlags::from_bits_truncate(termios.c_lflag),
control_chars: termios.c_cc,
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
+ #[cfg(any(linux_android, target_os = "haiku"))]
line_discipline: termios.c_line,
}
}
@@ -356,8 +260,13 @@ libc_enum! {
///
/// B0 is special and will disable the port.
#[cfg_attr(target_os = "haiku", repr(u8))]
- #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))]
- #[cfg_attr(all(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), not(target_os = "haiku")), repr(u32))]
+ #[cfg_attr(target_os = "hurd", repr(i32))]
+ #[cfg_attr(all(apple_targets, target_pointer_width = "64"), repr(u64))]
+ #[cfg_attr(all(
+ not(all(apple_targets, target_pointer_width = "64")),
+ not(target_os = "haiku"),
+ not(target_os = "hurd")
+ ), repr(u32))]
#[non_exhaustive]
pub enum BaudRate {
B0,
@@ -373,110 +282,62 @@ libc_enum! {
B1800,
B2400,
B4800,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
B7200,
B9600,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
B14400,
B19200,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
B28800,
B38400,
#[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
B57600,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
B76800,
#[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
B115200,
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(solarish)]
B153600,
#[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
B230400,
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(solarish)]
B307200,
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
+ solarish,
target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ target_os = "netbsd"))]
B460800,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
B500000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
B576000,
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
+ solarish,
target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ target_os = "netbsd"))]
B921600,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
B1000000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
B1152000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
B1500000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
B2000000,
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
B2500000,
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
B3000000,
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
B3500000,
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
B4000000,
}
impl TryFrom<libc::speed_t>
}
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(bsd)]
impl From<BaudRate> for u32 {
fn from(b: BaudRate) -> u32 {
b as u32
@@ -542,80 +403,57 @@ libc_enum! {
}
// TODO: Make this usable directly as a slice index.
-#[cfg(not(target_os = "haiku"))]
libc_enum! {
/// Indices into the `termios.c_cc` array for special characters.
#[repr(usize)]
#[non_exhaustive]
pub enum SpecialCharacterIndices {
- #[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(any(target_os = "aix", target_os = "haiku")))]
VDISCARD,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "aix",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd,
+ solarish,
+ target_os = "aix"))]
VDSUSP,
VEOF,
VEOL,
VEOL2,
VERASE,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(freebsdlike, solarish))]
VERASE2,
VINTR,
VKILL,
+ #[cfg(not(target_os = "haiku"))]
VLNEXT,
#[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
- target_os = "illumos", target_os = "solaris", target_os = "aix")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ solarish, target_os = "aix", target_os = "haiku")))]
VMIN,
VQUIT,
+ #[cfg(not(target_os = "haiku"))]
VREPRINT,
VSTART,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, solarish))]
VSTATUS,
VSTOP,
VSUSP,
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
VSWTC,
- #[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(solarish, target_os = "haiku"))]
VSWTCH,
#[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
- target_os = "illumos", target_os = "solaris", target_os = "aix")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ solarish, target_os = "aix", target_os = "haiku")))]
VTIME,
- #[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(not(any(target_os = "aix", target_os = "haiku")))]
VWERASE,
#[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
VCHECKPT,
}
}
#[cfg(any(
all(target_os = "linux", target_arch = "sparc64"),
- target_os = "illumos",
- target_os = "solaris",
+ solarish,
target_os = "aix",
+ target_os = "haiku",
))]
impl SpecialCharacterIndices {
pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
@@ -623,17 +461,7 @@ impl SpecialCharacterIndices {
}
pub use libc::NCCS;
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "aix",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(any(linux_android, target_os = "aix", bsd))]
pub use libc::_POSIX_VDISABLE;
libc_bitflags! {
@@ -651,13 +479,10 @@ libc_bitflags! {
IXON;
IXOFF;
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IXANY;
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IMAXBEL;
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, apple_targets))]
IUTF8;
}
}
@@ -666,209 +491,119 @@ libc_bitflags! {
/// Flags for configuring the output mode of a terminal
pub struct OutputFlags: tcflag_t {
OPOST;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "linux",
target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
OLCUC;
ONLCR;
OCRNL as tcflag_t;
ONOCR as tcflag_t;
ONLRET as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- OFILL as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
OFDEL as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
NL0 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
NL1 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
CR0 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
CR1 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
CR2 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
CR3 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "freebsd",
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
TAB0 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
TAB1 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
TAB2 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "freebsd",
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
TAB3 as tcflag_t;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
XTABS;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
BS0 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
BS1 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
VT0 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
VT1 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
FF0 as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
FF1 as tcflag_t;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
OXTABS;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
ONOEOT as tcflag_t;
// Bitmasks for use with OutputFlags to select specific settings
// These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
// is resolved.
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
CRDLY as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "freebsd",
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
TABDLY as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
BSDLY as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
VTDLY as tcflag_t;
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ apple_targets))]
FFDLY as tcflag_t;
}
}
@@ -876,13 +611,7 @@ libc_bitflags! {
libc_bitflags! {
/// Flags for setting the control mode of a terminal
pub struct ControlFlags: tcflag_t {
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
CIGNORE;
CS5;
CS6;
@@ -895,54 +624,30 @@ libc_bitflags! {
HUPCL;
CLOCAL;
#[cfg(not(any(target_os = "redox", target_os = "aix")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
CRTSCTS;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
CBAUD;
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "mips"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
CMSPAR;
#[cfg(any(target_os = "android",
all(target_os = "linux",
not(any(target_arch = "powerpc", target_arch = "powerpc64")))))]
CIBAUD;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
CBAUDEX;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
MDMBUF;
- #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(netbsdlike)]
CHWFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(freebsdlike, netbsdlike))]
CCTS_OFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(freebsdlike, netbsdlike))]
CRTS_IFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
CDTR_IFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
CDSR_OFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
CCAR_OFLOW;
// Bitmasks for use with ControlFlags to select specific settings
@@ -957,58 +662,35 @@ libc_bitflags! {
/// Flags for setting any local modes
pub struct LocalFlags: tcflag_t {
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
ECHOKE;
ECHOE;
ECHOK;
ECHO;
ECHONL;
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
ECHOPRT;
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
ECHOCTL;
ISIG;
ICANON;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
ALTWERASE;
IEXTEN;
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "aix")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
EXTPROC;
TOSTOP;
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
FLUSHO;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(bsd)]
NOKERNINFO;
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
PENDIN;
NOFLSH;
}
}
cfg_if! {
- if #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
+ if #[cfg(bsd)] {
/// Get input baud rate (see
/// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
///
@@ -1141,7 +823,6 @@ pub fn cfmakeraw(termios: &mut Termios) {
///
/// Note that this is a non-standard function, available on FreeBSD.
#[cfg(target_os = "freebsd")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn cfmakesane(termios: &mut Termios) {
let inner_termios = unsafe { termios.get_libc_termios_mut() };
unsafe {
@@ -1242,18 +923,3 @@ pub fn tcgetsid<Fd: AsFd>(fd: Fd) -> Result<Pid> {
Errno::result(res).map(Pid::from_raw)
}
}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use std::convert::TryFrom;
-
- #[test]
- fn try_from() {
- assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
- #[cfg(not(target_os = "haiku"))]
- BaudRate::try_from(999999999).expect_err("assertion failed");
- #[cfg(target_os = "haiku")]
- BaudRate::try_from(99).expect_err("assertion failed");
- }
-}
diff --git a/third_party/rust/nix/src/sys/time.rs b/third_party/rust/nix/src/sys/time.rs
index a0160e21ff..af436cabd5 100644
--- a/third_party/rust/nix/src/sys/time.rs
+++ b/third_party/rust/nix/src/sys/time.rs
@@ -2,7 +2,6 @@
// https://github.com/rust-lang/libc/issues/1848
pub use libc::{suseconds_t, time_t};
use libc::{timespec, timeval};
-use std::convert::From;
use std::time::Duration;
use std::{cmp, fmt, ops};
@@ -18,7 +17,7 @@ const fn zero_init_timespec() -> timespec {
all(
any(
target_os = "freebsd",
- target_os = "illumos",
+ solarish,
target_os = "linux",
target_os = "netbsd"
),
@@ -88,7 +87,7 @@ pub(crate) mod timer {
Interval(TimeSpec),
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
bitflags! {
/// Flags that are used for arming the timer.
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
@@ -97,12 +96,7 @@ pub(crate) mod timer {
const TFD_TIMER_CANCEL_ON_SET = libc::TFD_TIMER_CANCEL_ON_SET;
}
}
- #[cfg(any(
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "dragonfly",
- target_os = "illumos"
- ))]
+ #[cfg(any(freebsdlike, target_os = "netbsd", solarish))]
bitflags! {
/// Flags that are used for arming the timer.
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
@@ -334,6 +328,17 @@ impl TimeValLike for TimeSpec {
}
impl TimeSpec {
+ /// Leave the timestamp unchanged.
+ #[cfg(not(target_os = "redox"))]
+ // At the time of writing this PR, redox does not support this feature
+ pub const UTIME_OMIT: TimeSpec =
+ TimeSpec::new(0, libc::UTIME_OMIT as timespec_tv_nsec_t);
+ /// Update the timestamp to `Now`
+ // At the time of writing this PR, redox does not support this feature
+ #[cfg(not(target_os = "redox"))]
+ pub const UTIME_NOW: TimeSpec =
+ TimeSpec::new(0, libc::UTIME_NOW as timespec_tv_nsec_t);
+
/// Construct a new `TimeSpec` from its components
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
pub const fn new(seconds: time_t, nanoseconds: timespec_tv_nsec_t) -> Self {
@@ -712,101 +717,3 @@ fn mod_floor_64(this: i64, other: i64) -> i64 {
fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
(this / other, this % other)
}
-
-#[cfg(test)]
-mod test {
- use super::{TimeSpec, TimeVal, TimeValLike};
- use std::time::Duration;
-
- #[test]
- pub fn test_timespec() {
- assert_ne!(TimeSpec::seconds(1), TimeSpec::zero());
- assert_eq!(
- TimeSpec::seconds(1) + TimeSpec::seconds(2),
- TimeSpec::seconds(3)
- );
- assert_eq!(
- TimeSpec::minutes(3) + TimeSpec::seconds(2),
- TimeSpec::seconds(182)
- );
- }
-
- #[test]
- pub fn test_timespec_from() {
- let duration = Duration::new(123, 123_456_789);
- let timespec = TimeSpec::nanoseconds(123_123_456_789);
-
- assert_eq!(TimeSpec::from(duration), timespec);
- assert_eq!(Duration::from(timespec), duration);
- }
-
- #[test]
- pub fn test_timespec_neg() {
- let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
- let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123);
-
- assert_eq!(a, -b);
- }
-
- #[test]
- pub fn test_timespec_ord() {
- assert_eq!(TimeSpec::seconds(1), TimeSpec::nanoseconds(1_000_000_000));
- assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001));
- assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999));
- assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999));
- assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001));
- }
-
- #[test]
- pub fn test_timespec_fmt() {
- assert_eq!(TimeSpec::zero().to_string(), "0 seconds");
- assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds");
- assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds");
- assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds");
- assert_eq!(
- TimeSpec::nanoseconds(42).to_string(),
- "0.000000042 seconds"
- );
- assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds");
- }
-
- #[test]
- pub fn test_timeval() {
- assert_ne!(TimeVal::seconds(1), TimeVal::zero());
- assert_eq!(
- TimeVal::seconds(1) + TimeVal::seconds(2),
- TimeVal::seconds(3)
- );
- assert_eq!(
- TimeVal::minutes(3) + TimeVal::seconds(2),
- TimeVal::seconds(182)
- );
- }
-
- #[test]
- pub fn test_timeval_ord() {
- assert_eq!(TimeVal::seconds(1), TimeVal::microseconds(1_000_000));
- assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001));
- assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999));
- assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999));
- assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001));
- }
-
- #[test]
- pub fn test_timeval_neg() {
- let a = TimeVal::seconds(1) + TimeVal::microseconds(123);
- let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123);
-
- assert_eq!(a, -b);
- }
-
- #[test]
- pub fn test_timeval_fmt() {
- assert_eq!(TimeVal::zero().to_string(), "0 seconds");
- assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds");
- assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds");
- assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds");
- assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds");
- assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds");
- }
-}
diff --git a/third_party/rust/nix/src/sys/timerfd.rs b/third_party/rust/nix/src/sys/timerfd.rs
index c4337c9dfa..68b06d6322 100644
--- a/third_party/rust/nix/src/sys/timerfd.rs
+++ b/third_party/rust/nix/src/sys/timerfd.rs
@@ -53,7 +53,7 @@ impl AsFd for TimerFd {
impl FromRawFd for TimerFd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
TimerFd {
- fd: OwnedFd::from_raw_fd(fd),
+ fd: unsafe { OwnedFd::from_raw_fd(fd) },
}
}
}
diff --git a/third_party/rust/nix/src/sys/uio.rs b/third_party/rust/nix/src/sys/uio.rs
index eaf61edfd4..cdf380dd11 100644
--- a/third_party/rust/nix/src/sys/uio.rs
+++ b/third_party/rust/nix/src/sys/uio.rs
@@ -2,7 +2,7 @@
use crate::errno::Errno;
use crate::Result;
-use libc::{self, c_int, c_void, off_t, size_t};
+use libc::{self, c_int, off_t, size_t};
use std::io::{IoSlice, IoSliceMut};
use std::os::unix::io::{AsFd, AsRawFd};
@@ -18,7 +18,11 @@ pub fn writev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>]) -> Result<usize> {
//
// Because it is ABI compatible, a pointer cast here is valid
let res = unsafe {
- libc::writev(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
+ libc::writev(
+ fd.as_fd().as_raw_fd(),
+ iov.as_ptr().cast(),
+ iov.len() as c_int,
+ )
};
Errno::result(res).map(|r| r as usize)
@@ -33,7 +37,11 @@ pub fn writev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>]) -> Result<usize> {
pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
// SAFETY: same as in writev(), IoSliceMut is ABI-compatible with iovec
let res = unsafe {
- libc::readv(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
+ libc::readv(
+ fd.as_fd().as_raw_fd(),
+ iov.as_ptr().cast(),
+ iov.len() as c_int,
+ )
};
Errno::result(res).map(|r| r as usize)
@@ -45,9 +53,12 @@ pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
/// or an error occurs. The file offset is not changed.
///
/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
+#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris")))]
+pub fn pwritev<Fd: AsFd>(
+ fd: Fd,
+ iov: &[IoSlice<'_>],
+ offset: off_t,
+) -> Result<usize> {
#[cfg(target_env = "uclibc")]
let offset = offset as libc::off64_t; // uclibc doesn't use off_t
@@ -55,7 +66,7 @@ pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<u
let res = unsafe {
libc::pwritev(
fd.as_fd().as_raw_fd(),
- iov.as_ptr() as *const libc::iovec,
+ iov.as_ptr().cast(),
iov.len() as c_int,
offset,
)
@@ -71,8 +82,7 @@ pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<u
/// changed.
///
/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris")))]
// Clippy doesn't know that we need to pass iov mutably only because the
// mutation happens after converting iov to a pointer
#[allow(clippy::needless_pass_by_ref_mut)]
@@ -88,7 +98,7 @@ pub fn preadv<Fd: AsFd>(
let res = unsafe {
libc::preadv(
fd.as_fd().as_raw_fd(),
- iov.as_ptr() as *const libc::iovec,
+ iov.as_ptr().cast(),
iov.len() as c_int,
offset,
)
@@ -105,7 +115,7 @@ pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: off_t) -> Result<usize> {
let res = unsafe {
libc::pwrite(
fd.as_fd().as_raw_fd(),
- buf.as_ptr() as *const c_void,
+ buf.as_ptr().cast(),
buf.len() as size_t,
offset,
)
@@ -122,7 +132,7 @@ pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: off_t) -> Result<usize> {
let res = unsafe {
libc::pread(
fd.as_fd().as_raw_fd(),
- buf.as_mut_ptr() as *mut c_void,
+ buf.as_mut_ptr().cast(),
buf.len() as size_t,
offset,
)
@@ -139,8 +149,7 @@ pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: off_t) -> Result<usize> {
/// therefore not represented in Rust by an actual slice as `IoSlice` is. It
/// is used with [`process_vm_readv`](fn.process_vm_readv.html)
/// and [`process_vm_writev`](fn.process_vm_writev.html).
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
+#[cfg(linux_android)]
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct RemoteIoVec {
@@ -173,7 +182,7 @@ feature! {
/// [ptrace]: ../ptrace/index.html
/// [`IoSlice`]: https://doc.rust-lang.org/std/io/struct.IoSlice.html
/// [`RemoteIoVec`]: struct.RemoteIoVec.html
-#[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))]
+#[cfg(all(linux_android, not(target_env = "uclibc")))]
pub fn process_vm_writev(
pid: crate::unistd::Pid,
local_iov: &[IoSlice<'_>],
@@ -181,8 +190,8 @@ pub fn process_vm_writev(
{
let res = unsafe {
libc::process_vm_writev(pid.into(),
- local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
- remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
+ local_iov.as_ptr().cast(), local_iov.len() as libc::c_ulong,
+ remote_iov.as_ptr().cast(), remote_iov.len() as libc::c_ulong, 0)
};
Errno::result(res).map(|r| r as usize)
@@ -208,7 +217,7 @@ pub fn process_vm_writev(
/// [`ptrace`]: ../ptrace/index.html
/// [`IoSliceMut`]: https://doc.rust-lang.org/std/io/struct.IoSliceMut.html
/// [`RemoteIoVec`]: struct.RemoteIoVec.html
-#[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))]
+#[cfg(all(linux_android, not(target_env = "uclibc")))]
pub fn process_vm_readv(
pid: crate::unistd::Pid,
local_iov: &mut [IoSliceMut<'_>],
@@ -216,8 +225,8 @@ pub fn process_vm_readv(
{
let res = unsafe {
libc::process_vm_readv(pid.into(),
- local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
- remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
+ local_iov.as_ptr().cast(), local_iov.len() as libc::c_ulong,
+ remote_iov.as_ptr().cast(), remote_iov.len() as libc::c_ulong, 0)
};
Errno::result(res).map(|r| r as usize)
diff --git a/third_party/rust/nix/src/sys/utsname.rs b/third_party/rust/nix/src/sys/utsname.rs
index b48ed9f45e..cf4e6cc738 100644
--- a/third_party/rust/nix/src/sys/utsname.rs
+++ b/third_party/rust/nix/src/sys/utsname.rs
@@ -37,7 +37,7 @@ impl UtsName {
}
/// NIS or YP domain name of this machine.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
pub fn domainname(&self) -> &OsStr {
cast_and_trim(&self.0.domainname)
}
@@ -62,24 +62,3 @@ fn cast_and_trim(slice: &[c_char]) -> &OsStr {
OsStr::from_bytes(bytes)
}
-
-#[cfg(test)]
-mod test {
- #[cfg(target_os = "linux")]
- #[test]
- pub fn test_uname_linux() {
- assert_eq!(super::uname().unwrap().sysname(), "Linux");
- }
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- #[test]
- pub fn test_uname_darwin() {
- assert_eq!(super::uname().unwrap().sysname(), "Darwin");
- }
-
- #[cfg(target_os = "freebsd")]
- #[test]
- pub fn test_uname_freebsd() {
- assert_eq!(super::uname().unwrap().sysname(), "FreeBSD");
- }
-}
diff --git a/third_party/rust/nix/src/sys/wait.rs b/third_party/rust/nix/src/sys/wait.rs
index f7a63ffcd2..844e165c18 100644
--- a/third_party/rust/nix/src/sys/wait.rs
+++ b/third_party/rust/nix/src/sys/wait.rs
@@ -24,53 +24,41 @@ libc_bitflags!(
/// [`SIGSTOP`](crate::sys::signal::Signal::SIGSTOP) signal.
WUNTRACED;
/// Report the status of selected processes which have terminated.
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
+ apple_targets,
target_os = "freebsd",
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
target_os = "redox",
- target_os = "macos",
target_os = "netbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
WEXITED;
/// Report the status of selected processes that have continued from a
/// job control stop by receiving a
/// [`SIGCONT`](crate::sys::signal::Signal::SIGCONT) signal.
WCONTINUED;
/// An alias for WUNTRACED.
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
+ apple_targets,
target_os = "freebsd",
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
target_os = "redox",
- target_os = "macos",
target_os = "netbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
WSTOPPED;
/// Don't reap, just poll status.
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
+ apple_targets,
target_os = "freebsd",
target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
target_os = "redox",
- target_os = "macos",
target_os = "netbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
WNOWAIT;
/// Don't wait on children of other threads in this group
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "redox"))]
__WNOTHREAD;
/// Wait on all children, regardless of type
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "redox"))]
__WALL;
/// Wait for "clone" children only.
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "redox"))]
__WCLONE;
}
);
@@ -107,16 +95,14 @@ pub enum WaitStatus {
///
/// [`nix::sys::ptrace`]: ../ptrace/index.html
/// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
- #[cfg(any(target_os = "linux", target_os = "android"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
PtraceEvent(Pid, Signal, c_int),
/// The traced process was stopped by execution of a system call,
/// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for
/// more information.
///
/// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
- #[cfg(any(target_os = "linux", target_os = "android"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
PtraceSyscall(Pid),
/// The process was previously stopped but has resumed execution
/// after receiving a `SIGCONT` signal. This is only reported if
@@ -139,7 +125,7 @@ impl WaitStatus {
Some(p)
}
StillAlive => None,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
}
}
@@ -173,7 +159,7 @@ fn stop_signal(status: i32) -> Result<Signal> {
Signal::try_from(libc::WSTOPSIG(status))
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn syscall_stop(status: i32) -> bool {
// From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
// of delivering SIGTRAP | 0x80 as the signal number for syscall
@@ -182,7 +168,7 @@ fn syscall_stop(status: i32) -> bool {
libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn stop_additional(status: i32) -> c_int {
(status >> 16) as c_int
}
@@ -216,7 +202,7 @@ impl WaitStatus {
WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status))
} else if stopped(status) {
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
let status_additional = stop_additional(status);
Ok(if syscall_stop(status) {
@@ -259,7 +245,7 @@ impl WaitStatus {
all(target_os = "linux", not(target_env = "uclibc")),
))]
unsafe fn from_siginfo(siginfo: &libc::siginfo_t) -> Result<WaitStatus> {
- let si_pid = siginfo.si_pid();
+ let si_pid = unsafe { siginfo.si_pid() };
if si_pid == 0 {
return Ok(WaitStatus::StillAlive);
}
@@ -267,7 +253,7 @@ impl WaitStatus {
assert_eq!(siginfo.si_signo, libc::SIGCHLD);
let pid = Pid::from_raw(si_pid);
- let si_status = siginfo.si_status();
+ let si_status = unsafe { siginfo.si_status() };
let status = match siginfo.si_code {
libc::CLD_EXITED => WaitStatus::Exited(pid, si_status),
@@ -280,7 +266,7 @@ impl WaitStatus {
WaitStatus::Stopped(pid, Signal::try_from(si_status)?)
}
libc::CLD_CONTINUED => WaitStatus::Continued(pid),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
libc::CLD_TRAPPED => {
if si_status == libc::SIGTRAP | 0x80 {
WaitStatus::PtraceSyscall(pid)
@@ -354,7 +340,7 @@ pub enum Id<'fd> {
/// If the PID is zero, the caller's process group is used since Linux 5.4.
PGid(Pid),
/// Wait for the child referred to by the given PID file descriptor
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
PIDFd(BorrowedFd<'fd>),
/// A helper variant to resolve the unused parameter (`'fd`) problem on platforms
/// other than Linux and Android.
@@ -376,9 +362,11 @@ pub fn waitid(id: Id, flags: WaitPidFlag) -> Result<WaitStatus> {
Id::All => (libc::P_ALL, 0),
Id::Pid(pid) => (libc::P_PID, pid.as_raw() as libc::id_t),
Id::PGid(pid) => (libc::P_PGID, pid.as_raw() as libc::id_t),
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
Id::PIDFd(fd) => (libc::P_PIDFD, fd.as_raw_fd() as libc::id_t),
- Id::_Unreachable(_) => unreachable!("This variant could never be constructed"),
+ Id::_Unreachable(_) => {
+ unreachable!("This variant could never be constructed")
+ }
};
let siginfo = unsafe {
diff --git a/third_party/rust/nix/src/time.rs b/third_party/rust/nix/src/time.rs
index 2e03c46cf4..195df71211 100644
--- a/third_party/rust/nix/src/time.rs
+++ b/third_party/rust/nix/src/time.rs
@@ -1,11 +1,6 @@
+//! Sleep, query system clocks, and set system clock
use crate::sys::time::TimeSpec;
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
#[cfg(feature = "process")]
use crate::unistd::Pid;
use crate::{Errno, Result};
@@ -14,8 +9,7 @@ use std::mem::MaybeUninit;
/// Clock identifier
///
-/// Newtype pattern around `clockid_t` (which is just alias). It prevents bugs caused by
-/// accidentally passing wrong value.
+/// Newtype pattern around [`libc::clockid_t`].
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ClockId(clockid_t);
@@ -28,14 +22,7 @@ impl ClockId {
feature! {
#![feature = "process"]
/// Returns `ClockId` of a `pid` CPU-time clock
- #[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
pub fn pid_cpu_clock_id(pid: Pid) -> Result<Self> {
clock_getcpuclockid(pid)
}
@@ -43,7 +30,6 @@ impl ClockId {
/// Returns resolution of the clock id
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn res(self) -> Result<TimeSpec> {
clock_getres(self)
}
@@ -55,12 +41,12 @@ impl ClockId {
/// Sets time to `timespec` on the clock id
#[cfg(not(any(
- target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
target_os = "redox",
- target_os = "hermit",
+ target_os = "hermit"
)))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn set_time(self, timespec: TimeSpec) -> Result<()> {
clock_settime(self, timespec)
}
@@ -70,135 +56,103 @@ impl ClockId {
self.0
}
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))]
+ /// Starts at zero when the kernel boots and increments monotonically in SI seconds while the
+ /// machine is running.
pub const CLOCK_BOOTTIME: ClockId = ClockId(libc::CLOCK_BOOTTIME);
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Like [`CLOCK_BOOTTIME`](ClockId::CLOCK_BOOTTIME), but will wake the system if it is
+ /// suspended..
+ #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))]
pub const CLOCK_BOOTTIME_ALARM: ClockId =
ClockId(libc::CLOCK_BOOTTIME_ALARM);
+ /// Increments in SI seconds.
pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC);
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Like [`CLOCK_MONOTONIC`](ClockId::CLOCK_MONOTONIC), but optimized for execution time at the expense of accuracy.
+ #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))]
pub const CLOCK_MONOTONIC_COARSE: ClockId =
ClockId(libc::CLOCK_MONOTONIC_COARSE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Like [`CLOCK_MONOTONIC`](ClockId::CLOCK_MONOTONIC), but optimized for execution time at the expense of accuracy.
pub const CLOCK_MONOTONIC_FAST: ClockId =
ClockId(libc::CLOCK_MONOTONIC_FAST);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Like [`CLOCK_MONOTONIC`](ClockId::CLOCK_MONOTONIC), but optimized for accuracy at the expense of execution time.
pub const CLOCK_MONOTONIC_PRECISE: ClockId =
ClockId(libc::CLOCK_MONOTONIC_PRECISE);
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Similar to [`CLOCK_MONOTONIC`](ClockId::CLOCK_MONOTONIC), but provides access to a raw
+ /// hardware-based time that is not subject to NTP adjustments.
+ #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))]
pub const CLOCK_MONOTONIC_RAW: ClockId = ClockId(libc::CLOCK_MONOTONIC_RAW);
#[cfg(any(
- target_os = "android",
+ linux_android,
+ apple_targets,
+ freebsdlike,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly",
target_os = "redox",
- target_os = "linux"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Returns the execution time of the calling process.
pub const CLOCK_PROCESS_CPUTIME_ID: ClockId =
ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Increments when the CPU is running in user or kernel mode
pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF);
+ /// Increments as a wall clock should.
pub const CLOCK_REALTIME: ClockId = ClockId(libc::CLOCK_REALTIME);
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Like [`CLOCK_REALTIME`](ClockId::CLOCK_REALTIME), but not settable.
+ #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))]
pub const CLOCK_REALTIME_ALARM: ClockId =
ClockId(libc::CLOCK_REALTIME_ALARM);
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Like [`CLOCK_REALTIME`](ClockId::CLOCK_REALTIME), but optimized for execution time at the expense of accuracy.
+ #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))]
pub const CLOCK_REALTIME_COARSE: ClockId =
ClockId(libc::CLOCK_REALTIME_COARSE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Like [`CLOCK_REALTIME`](ClockId::CLOCK_REALTIME), but optimized for execution time at the expense of accuracy.
pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Like [`CLOCK_REALTIME`](ClockId::CLOCK_REALTIME), but optimized for accuracy at the expense of execution time.
pub const CLOCK_REALTIME_PRECISE: ClockId =
ClockId(libc::CLOCK_REALTIME_PRECISE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Returns the current second without performing a full time counter query, using an in-kernel
+ /// cached value of the current second.
pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND);
+ #[allow(missing_docs)] // Undocumented on Linux!
#[cfg(any(
target_os = "emscripten",
target_os = "fuchsia",
all(target_os = "linux", target_env = "musl")
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE);
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// International Atomic Time.
+ ///
+ /// A nonsettable system-wide clock derived from wall-clock time but ignoring leap seconds.
+ #[cfg(any(linux_android, target_os = "emscripten", target_os = "fuchsia"))]
pub const CLOCK_TAI: ClockId = ClockId(libc::CLOCK_TAI);
#[cfg(any(
- target_os = "android",
+ linux_android,
+ apple_targets,
+ freebsdlike,
target_os = "emscripten",
target_os = "fuchsia",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Returns the execution time of the calling thread.
pub const CLOCK_THREAD_CPUTIME_ID: ClockId =
ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Starts at zero when the kernel boots and increments monotonically in SI seconds while the
+ /// machine is running.
pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Like [`CLOCK_UPTIME`](ClockId::CLOCK_UPTIME), but optimized for execution time at the expense of accuracy.
pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Like [`CLOCK_UPTIME`](ClockId::CLOCK_UPTIME), but optimized for accuracy at the expense of execution time.
pub const CLOCK_UPTIME_PRECISE: ClockId =
ClockId(libc::CLOCK_UPTIME_PRECISE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
+ /// Increments only when the CPU is running in user mode on behalf of the calling process.
pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL);
}
@@ -223,7 +177,6 @@ impl std::fmt::Display for ClockId {
/// Get the resolution of the specified clock, (see
/// [clock_getres(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_getres.html)).
#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
let ret =
@@ -247,12 +200,12 @@ pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
/// Set the time of the specified clock, (see
/// [clock_settime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_settime.html)).
#[cfg(not(any(
- target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
target_os = "redox",
- target_os = "hermit",
+ target_os = "hermit"
)))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
let ret =
unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
@@ -261,13 +214,7 @@ pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
/// Get the clock id of the specified process id, (see
/// [clock_getcpuclockid(3)](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_getcpuclockid.html)).
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
#[cfg(feature = "process")]
#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
@@ -278,6 +225,61 @@ pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
let res = unsafe { clk_id.assume_init() };
Ok(ClockId::from(res))
} else {
- Err(Errno::from_i32(ret))
+ Err(Errno::from_raw(ret))
+ }
+}
+
+#[cfg(any(
+ linux_android,
+ solarish,
+ freebsdlike,
+ target_os = "netbsd",
+ target_os = "hurd",
+ target_os = "aix"
+))]
+libc_bitflags! {
+ /// Flags that are used for arming the timer.
+ pub struct ClockNanosleepFlags: libc::c_int {
+ /// Indicates that a requested time value should be treated as absolute instead of
+ /// relative.
+ TIMER_ABSTIME;
+ }
+}
+
+/// Suspend execution of this thread for the amount of time specified by `request`
+/// and measured against the clock speficied by `clock_id`.
+///
+/// If `flags` is [`TIMER_ABSTIME`](ClockNanosleepFlags::TIMER_ABSTIME), this function will suspend
+/// execution until the time value of clock_id reaches the absolute time specified by `request`. If
+/// a signal is caught by a signal-catching function, or a signal causes the process to terminate,
+/// this sleep is interrrupted.
+///
+/// see also [man 3 clock_nanosleep](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_nanosleep.html)
+#[cfg(any(
+ linux_android,
+ solarish,
+ freebsdlike,
+ target_os = "netbsd",
+ target_os = "hurd",
+ target_os = "aix"
+))]
+pub fn clock_nanosleep(
+ clock_id: ClockId,
+ flags: ClockNanosleepFlags,
+ request: &TimeSpec,
+) -> Result<TimeSpec> {
+ let mut remain = TimeSpec::new(0, 0);
+ let ret = unsafe {
+ libc::clock_nanosleep(
+ clock_id.as_raw(),
+ flags.bits(),
+ request.as_ref() as *const _,
+ remain.as_mut() as *mut _,
+ )
+ };
+ if ret == 0 {
+ Ok(remain)
+ } else {
+ Err(Errno::from_raw(ret))
}
}
diff --git a/third_party/rust/nix/src/unistd.rs b/third_party/rust/nix/src/unistd.rs
index bb9f1c1f67..4502766c5d 100644
--- a/third_party/rust/nix/src/unistd.rs
+++ b/third_party/rust/nix/src/unistd.rs
@@ -1,22 +1,29 @@
//! Safe wrappers around functions found in libc "unistd.h" header
-use crate::errno::{self, Errno};
+use crate::errno::Errno;
+
+#[cfg(any(
+ all(feature = "fs", not(target_os = "redox")),
+ all(feature = "process", linux_android)
+))]
+use crate::fcntl::at_rawfd;
#[cfg(not(target_os = "redox"))]
#[cfg(feature = "fs")]
-use crate::fcntl::{at_rawfd, AtFlags};
+use crate::fcntl::AtFlags;
+
#[cfg(feature = "fs")]
-use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag};
-#[cfg(all(
- feature = "fs",
- any(
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "macos",
- target_os = "ios"
- )
+#[cfg(any(
+ linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike,
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "hurd",
+ target_os = "redox",
))]
+use crate::fcntl::OFlag;
+#[cfg(all(feature = "fs", bsd))]
use crate::sys::stat::FileFlag;
#[cfg(feature = "fs")]
use crate::sys::stat::Mode;
@@ -24,43 +31,27 @@ use crate::{Error, NixPath, Result};
#[cfg(not(target_os = "redox"))]
use cfg_if::cfg_if;
use libc::{
- self, c_char, c_int, c_long, c_uint, c_void, gid_t, mode_t, off_t, pid_t,
- size_t, uid_t, PATH_MAX,
+ c_char, c_int, c_long, c_uint, gid_t, mode_t, off_t, pid_t, size_t, uid_t,
};
use std::convert::Infallible;
-use std::ffi::{CStr, OsString};
#[cfg(not(target_os = "redox"))]
-use std::ffi::{CString, OsStr};
-#[cfg(not(target_os = "redox"))]
-use std::os::unix::ffi::OsStrExt;
-use std::os::unix::ffi::OsStringExt;
-use std::os::unix::io::RawFd;
-use std::os::unix::io::{AsFd, AsRawFd};
+use std::ffi::CString;
+use std::ffi::{CStr, OsStr, OsString};
+use std::os::unix::ffi::{OsStrExt, OsStringExt};
+use std::os::unix::io::{AsFd, AsRawFd, OwnedFd, RawFd};
use std::path::PathBuf;
use std::{fmt, mem, ptr};
feature! {
#![feature = "fs"]
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
pub use self::pivot_root::*;
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "openbsd"
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "openbsd"))]
pub use self::setres::*;
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "openbsd"
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "openbsd"))]
pub use self::getres::*;
feature! {
@@ -225,7 +216,12 @@ impl fmt::Display for Pid {
/// you are now executing in the parent process or in the child.
#[derive(Clone, Copy, Debug)]
pub enum ForkResult {
- Parent { child: Pid },
+ /// This is the parent process of the fork.
+ Parent {
+ /// The PID of the fork's child process
+ child: Pid
+ },
+ /// This is the child process of the fork.
Child,
}
@@ -260,7 +256,7 @@ impl ForkResult {
/// }
/// Ok(ForkResult::Child) => {
/// // Unsafe to use `println!` (or `unwrap`) here. See Safety.
-/// write(libc::STDOUT_FILENO, "I'm a new child process\n".as_bytes()).ok();
+/// write(std::io::stdout(), "I'm a new child process\n".as_bytes()).ok();
/// unsafe { libc::_exit(0) };
/// }
/// Err(_) => println!("Fork failed"),
@@ -290,7 +286,7 @@ impl ForkResult {
#[inline]
pub unsafe fn fork() -> Result<ForkResult> {
use self::ForkResult::*;
- let res = libc::fork();
+ let res = unsafe { libc::fork() };
Errno::result(res).map(|res| match res {
0 => Child,
@@ -332,6 +328,9 @@ pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
let res = unsafe { libc::setpgid(pid.into(), pgid.into()) };
Errno::result(res).map(drop)
}
+/// Get process group
+///
+/// See Also [`getpgid`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgid.html)
#[inline]
pub fn getpgid(pid: Option<Pid>) -> Result<Pid> {
let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) };
@@ -366,8 +365,8 @@ feature! {
/// Get the group process id (GPID) of the foreground process group on the
/// terminal associated to file descriptor (FD).
#[inline]
-pub fn tcgetpgrp(fd: c_int) -> Result<Pid> {
- let res = unsafe { libc::tcgetpgrp(fd) };
+pub fn tcgetpgrp<F: AsFd>(fd: F) -> Result<Pid> {
+ let res = unsafe { libc::tcgetpgrp(fd.as_fd().as_raw_fd()) };
Errno::result(res).map(Pid)
}
/// Set the terminal foreground process group (see
@@ -376,8 +375,8 @@ pub fn tcgetpgrp(fd: c_int) -> Result<Pid> {
/// Get the group process id (PGID) to the foreground process group on the
/// terminal associated to file descriptor (FD).
#[inline]
-pub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> {
- let res = unsafe { libc::tcsetpgrp(fd, pgrp.into()) };
+pub fn tcsetpgrp<F: AsFd>(fd: F, pgrp: Pid) -> Result<()> {
+ let res = unsafe { libc::tcsetpgrp(fd.as_fd().as_raw_fd(), pgrp.into()) };
Errno::result(res).map(drop)
}
}
@@ -404,7 +403,7 @@ pub fn getpgrp() -> Pid {
///
/// No error handling is required as a thread id should always exist for any
/// process, even if threads are not being used.
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[inline]
pub fn gettid() -> Pid {
Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t })
@@ -444,30 +443,22 @@ pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
}
/// Create a new copy of the specified file descriptor using the specified fd
-/// and flags (see [dup(2)](https://man7.org/linux/man-pages/man2/dup.2.html)).
+/// and flags (see [`dup(2)`](https://man7.org/linux/man-pages/man2/dup.2.html)).
///
/// This function behaves similar to `dup2()` but allows for flags to be
/// specified.
+#[cfg(any(
+ netbsdlike,
+ solarish,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "hurd",
+ target_os = "linux"
+))]
pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
- dup3_polyfill(oldfd, newfd, flags)
-}
-
-#[inline]
-fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
- if oldfd == newfd {
- return Err(Errno::EINVAL);
- }
+ let res = unsafe { libc::dup3(oldfd, newfd, flags.bits()) };
- let fd = dup2(oldfd, newfd)?;
-
- if flags.contains(OFlag::O_CLOEXEC) {
- if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) {
- let _ = close(fd);
- return Err(e);
- }
- }
-
- Ok(fd)
+ Errno::result(res)
}
/// Change the current working directory of the calling process (see
@@ -583,8 +574,7 @@ pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
// mkfifoat is not implemented in OSX or android
#[inline]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "haiku",
target_os = "android",
target_os = "redox"
@@ -664,17 +654,17 @@ feature! {
/// ```
#[inline]
pub fn getcwd() -> Result<PathBuf> {
- let mut buf = Vec::with_capacity(512);
+ let mut buf = Vec::<u8>::with_capacity(512);
loop {
unsafe {
- let ptr = buf.as_mut_ptr() as *mut c_char;
+ let ptr = buf.as_mut_ptr().cast();
// The buffer must be large enough to store the absolute pathname plus
// a terminating null byte, or else null is returned.
// To safely handle this we start with a reasonable size (512 bytes)
// and double the buffer size upon every error
if !libc::getcwd(ptr, buf.capacity()).is_null() {
- let len = CStr::from_ptr(buf.as_ptr() as *const c_char)
+ let len = CStr::from_ptr(buf.as_ptr().cast())
.to_bytes()
.len();
buf.set_len(len);
@@ -688,8 +678,13 @@ pub fn getcwd() -> Result<PathBuf> {
}
}
+ #[cfg(not(target_os = "hurd"))]
+ const PATH_MAX: usize = libc::PATH_MAX as usize;
+ #[cfg(target_os = "hurd")]
+ const PATH_MAX: usize = 1024; // Hurd does not define a hard limit, so try a guess first
+
// Trigger the internal buffer resizing logic.
- reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?;
+ reserve_double_buffer_size(&mut buf, PATH_MAX)?;
}
}
}
@@ -749,11 +744,19 @@ pub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
Errno::result(res).map(drop)
}
-/// Flags for `fchownat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum FchownatFlags {
- FollowSymlink,
- NoFollowSymlink,
+// Just a wrapper around `AtFlags` so that we can help our users migrate.
+#[allow(missing_docs)]
+#[cfg(not(target_os = "redox"))]
+pub type FchownatFlags = AtFlags;
+#[allow(missing_docs)]
+#[cfg(not(target_os = "redox"))]
+impl FchownatFlags {
+ #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
+ #[allow(non_upper_case_globals)]
+ pub const FollowSymlink: FchownatFlags = FchownatFlags::empty();
+ #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
+ #[allow(non_upper_case_globals)]
+ pub const NoFollowSymlink: FchownatFlags = FchownatFlags::AT_SYMLINK_NOFOLLOW;
}
/// Change the ownership of the file at `path` to be owned by the specified
@@ -767,10 +770,10 @@ pub enum FchownatFlags {
/// with the file descriptor `dirfd` or the current working directory
/// if `dirfd` is `None`.
///
-/// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link,
+/// If `flag` is `AtFlags::AT_SYMLINK_NOFOLLOW` and `path` names a symbolic link,
/// then the mode of the symbolic link is changed.
///
-/// `fchownat(None, path, owner, group, FchownatFlags::NoFollowSymlink)` is identical to
+/// `fchownat(None, path, owner, group, AtFlags::AT_SYMLINK_NOFOLLOW)` is identical to
/// a call `libc::lchown(path, owner, group)`. That's why `lchown` is unimplemented in
/// the `nix` crate.
///
@@ -783,12 +786,8 @@ pub fn fchownat<P: ?Sized + NixPath>(
path: &P,
owner: Option<Uid>,
group: Option<Gid>,
- flag: FchownatFlags,
+ flag: AtFlags,
) -> Result<()> {
- let atflag = match flag {
- FchownatFlags::FollowSymlink => AtFlags::empty(),
- FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
let res = path.with_nix_path(|cstr| unsafe {
let (uid, gid) = chown_raw_ids(owner, group);
libc::fchownat(
@@ -796,7 +795,7 @@ pub fn fchownat<P: ?Sized + NixPath>(
cstr.as_ptr(),
uid,
gid,
- atflag.bits() as libc::c_int,
+ flag.bits()
)
})?;
@@ -883,7 +882,7 @@ pub fn execvp<S: AsRef<CStr>>(
/// This functions like a combination of `execvp(2)` and `execve(2)` to pass an
/// environment and have a search path. See these two for additional
/// information.
-#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))]
+#[cfg(any(target_os = "haiku", target_os = "hurd", target_os = "linux", target_os = "openbsd"))]
pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(
filename: &CStr,
args: &[SA],
@@ -909,12 +908,7 @@ pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(
///
/// This function is similar to `execve`, except that the program to be executed
/// is referenced as a file descriptor instead of a path.
-#[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "dragonfly",
- target_os = "freebsd"
-))]
+#[cfg(any(linux_android, freebsdlike, target_os = "hurd"))]
#[inline]
pub fn fexecve<SA: AsRef<CStr>, SE: AsRef<CStr>>(
fd: RawFd,
@@ -939,15 +933,16 @@ pub fn fexecve<SA: AsRef<CStr>, SE: AsRef<CStr>>(
///
/// This function is similar to `execve`, except that the program to be executed
/// is referenced as a file descriptor to the base directory plus a path.
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[inline]
pub fn execveat<SA: AsRef<CStr>, SE: AsRef<CStr>>(
- dirfd: RawFd,
+ dirfd: Option<RawFd>,
pathname: &CStr,
args: &[SA],
env: &[SE],
flags: super::fcntl::AtFlags,
) -> Result<Infallible> {
+ let dirfd = at_rawfd(dirfd);
let args_p = to_exec_array(args);
let env_p = to_exec_array(env);
@@ -991,14 +986,10 @@ pub fn execveat<SA: AsRef<CStr>, SE: AsRef<CStr>>(
/// * `noclose = false`: The process' stdin, stdout, and stderr will point to
/// `/dev/null` after daemonizing.
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
+ linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike
))]
pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
@@ -1020,19 +1011,16 @@ feature! {
pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
// Handle some differences in type of the len arg across platforms.
cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "aix",
- target_os = "solaris", ))] {
+ if #[cfg(any(freebsdlike,
+ solarish,
+ apple_targets,
+ target_os = "aix"))] {
type sethostname_len_t = c_int;
} else {
type sethostname_len_t = size_t;
}
}
- let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
+ let ptr = name.as_ref().as_bytes().as_ptr().cast();
let len = name.as_ref().len() as sethostname_len_t;
let res = unsafe { libc::sethostname(ptr, len) };
@@ -1056,14 +1044,14 @@ pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
pub fn gethostname() -> Result<OsString> {
// The capacity is the max length of a hostname plus the NUL terminator.
let mut buffer: Vec<u8> = Vec::with_capacity(256);
- let ptr = buffer.as_mut_ptr() as *mut c_char;
+ let ptr = buffer.as_mut_ptr().cast();
let len = buffer.capacity() as size_t;
let res = unsafe { libc::gethostname(ptr, len) };
Errno::result(res).map(|_| {
unsafe {
buffer.as_mut_ptr().wrapping_add(len - 1).write(0); // ensure always null-terminated
- let len = CStr::from_ptr(buffer.as_ptr() as *const c_char).len();
+ let len = CStr::from_ptr(buffer.as_ptr().cast()).len();
buffer.set_len(len);
}
OsString::from_vec(buffer)
@@ -1105,9 +1093,8 @@ pub fn close(fd: RawFd) -> Result<()> {
///
/// See also [read(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
- let res = unsafe {
- libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t)
- };
+ let res =
+ unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as size_t) };
Errno::result(res).map(|r| r as usize)
}
@@ -1115,9 +1102,13 @@ pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
/// Write to a raw file descriptor.
///
/// See also [write(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
-pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
+pub fn write<Fd: AsFd>(fd: Fd, buf: &[u8]) -> Result<usize> {
let res = unsafe {
- libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t)
+ libc::write(
+ fd.as_fd().as_raw_fd(),
+ buf.as_ptr().cast(),
+ buf.len() as size_t,
+ )
};
Errno::result(res).map(|r| r as usize)
@@ -1143,11 +1134,9 @@ pub enum Whence {
/// equal to offset that contains some data. If offset points to
/// some data, then the file offset is set to offset.
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
+ freebsdlike,
+ solarish,
target_os = "linux",
- target_os = "solaris"
))]
SeekData = libc::SEEK_DATA,
/// Specify an offset relative to the next hole in the file greater than
@@ -1156,11 +1145,9 @@ pub enum Whence {
/// then the file offset should be adjusted to the end of the file (i.e., there
/// is an implicit hole at the end of any file).
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
+ freebsdlike,
+ solarish,
target_os = "linux",
- target_os = "solaris"
))]
SeekHole = libc::SEEK_HOLE,
}
@@ -1174,7 +1161,11 @@ pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
Errno::result(res).map(|r| r as off_t)
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+/// Move the read/write file offset.
+///
+/// Unlike [`lseek`], it takes a 64-bit argument even on platforms where [`libc::off_t`] is
+/// 32 bits.
+#[cfg(linux_android)]
pub fn lseek64(
fd: RawFd,
offset: libc::off64_t,
@@ -1189,14 +1180,15 @@ pub fn lseek64(
/// Create an interprocess channel.
///
/// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
-pub fn pipe() -> std::result::Result<(RawFd, RawFd), Error> {
- let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
+pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error> {
+ let mut fds = mem::MaybeUninit::<[OwnedFd; 2]>::uninit();
- let res = unsafe { libc::pipe(fds.as_mut_ptr() as *mut c_int) };
+ let res = unsafe { libc::pipe(fds.as_mut_ptr().cast()) };
Error::result(res)?;
- unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
+ let [read, write] = unsafe { fds.assume_init() };
+ Ok((read, write))
}
feature! {
@@ -1219,26 +1211,24 @@ feature! {
///
/// See also [pipe(2)](https://man7.org/linux/man-pages/man2/pipe.2.html)
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
+ linux_android,
+ freebsdlike,
+ solarish,
target_os = "emscripten",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
+ target_os = "hurd",
target_os = "redox",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
+ netbsdlike,
))]
-pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
- let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
+pub fn pipe2(flags: OFlag) -> Result<(OwnedFd, OwnedFd)> {
+ let mut fds = mem::MaybeUninit::<[OwnedFd; 2]>::uninit();
let res =
- unsafe { libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits()) };
+ unsafe { libc::pipe2(fds.as_mut_ptr().cast(), flags.bits()) };
Errno::result(res)?;
- unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
+ let [read, write] = unsafe { fds.assume_init() };
+ Ok((read, write))
}
/// Truncate a file to a specified length
@@ -1261,6 +1251,7 @@ pub fn ftruncate<Fd: AsFd>(fd: Fd, len: off_t) -> Result<()> {
Errno::result(unsafe { libc::ftruncate(fd.as_fd().as_raw_fd(), len) }).map(drop)
}
+/// Determines if the file descriptor refers to a valid terminal type device.
pub fn isatty(fd: RawFd) -> Result<bool> {
unsafe {
// ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
@@ -1276,11 +1267,18 @@ pub fn isatty(fd: RawFd) -> Result<bool> {
}
}
-/// Flags for `linkat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum LinkatFlags {
- SymlinkFollow,
- NoSymlinkFollow,
+#[allow(missing_docs)]
+#[cfg(not(target_os = "redox"))]
+pub type LinkatFlags = AtFlags;
+#[allow(missing_docs)]
+#[cfg(not(target_os = "redox"))]
+impl LinkatFlags {
+ #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
+ #[allow(non_upper_case_globals)]
+ pub const SymlinkFollow: LinkatFlags = LinkatFlags::AT_SYMLINK_FOLLOW;
+ #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
+ #[allow(non_upper_case_globals)]
+ pub const NoSymlinkFollow: LinkatFlags = LinkatFlags::empty();
}
/// Link one file to another file
@@ -1288,7 +1286,7 @@ pub enum LinkatFlags {
/// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the
/// case of a relative `oldpath`, the path is interpreted relative to the directory associated
/// with file descriptor `olddirfd` instead of the current working directory and similiarly for
-/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and
+/// `newpath` and file descriptor `newdirfd`. In case `flag` is `AtFlags::AT_SYMLINK_FOLLOW` and
/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created.
/// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath`
/// and/or `newpath` is then interpreted relative to the current working directory of the calling
@@ -1302,13 +1300,8 @@ pub fn linkat<P: ?Sized + NixPath>(
oldpath: &P,
newdirfd: Option<RawFd>,
newpath: &P,
- flag: LinkatFlags,
+ flag: AtFlags,
) -> Result<()> {
- let atflag = match flag {
- LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW,
- LinkatFlags::NoSymlinkFollow => AtFlags::empty(),
- };
-
let res = oldpath.with_nix_path(|oldcstr| {
newpath.with_nix_path(|newcstr| unsafe {
libc::linkat(
@@ -1316,7 +1309,7 @@ pub fn linkat<P: ?Sized + NixPath>(
oldcstr.as_ptr(),
at_rawfd(newdirfd),
newcstr.as_ptr(),
- atflag.bits() as libc::c_int,
+ flag.bits(),
)
})
})??;
@@ -1335,7 +1328,9 @@ pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
/// Flags for `unlinkat` function.
#[derive(Clone, Copy, Debug)]
pub enum UnlinkatFlags {
+ /// Remove the directory entry as a directory, not a normal file
RemoveDir,
+ /// Remove the directory entry as a normal file, not a directory
NoRemoveDir,
}
@@ -1369,6 +1364,7 @@ pub fn unlinkat<P: ?Sized + NixPath>(
Errno::result(res).map(drop)
}
+/// Change a process's root directory
#[inline]
#[cfg(not(target_os = "fuchsia"))]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
@@ -1381,13 +1377,7 @@ pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
/// Commit filesystem caches to disk
///
/// See also [sync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(any(freebsdlike, linux_android, netbsdlike))]
pub fn sync() {
unsafe { libc::sync() };
}
@@ -1396,7 +1386,7 @@ pub fn sync() {
/// descriptor `fd` to disk
///
/// See also [syncfs(2)](https://man7.org/linux/man-pages/man2/sync.2.html)
-#[cfg(target_os = "linux")]
+#[cfg(linux_android)]
pub fn syncfs(fd: RawFd) -> Result<()> {
let res = unsafe { libc::syncfs(fd) };
@@ -1418,15 +1408,12 @@ pub fn fsync(fd: RawFd) -> Result<()> {
/// See also
/// [fdatasync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
+ linux_android,
+ solarish,
+ netbsdlike,
target_os = "freebsd",
+ target_os = "emscripten",
target_os = "fuchsia",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "illumos",
- target_os = "solaris"
))]
#[inline]
pub fn fdatasync(fd: RawFd) -> Result<()> {
@@ -1527,7 +1514,7 @@ feature! {
/// ID of the caller.
///
/// See also [setfsuid(2)](https://man7.org/linux/man-pages/man2/setfsuid.2.html)
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
pub fn setfsuid(uid: Uid) -> Uid {
let prev_fsuid = unsafe { libc::setfsuid(uid.into()) };
Uid::from_raw(prev_fsuid as uid_t)
@@ -1538,7 +1525,7 @@ pub fn setfsuid(uid: Uid) -> Uid {
/// ID of the caller.
///
/// See also [setfsgid(2)](https://man7.org/linux/man-pages/man2/setfsgid.2.html)
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
pub fn setfsgid(gid: Gid) -> Gid {
let prev_fsgid = unsafe { libc::setfsgid(gid.into()) };
Gid::from_raw(prev_fsgid as gid_t)
@@ -1555,14 +1542,14 @@ feature! {
/// **Note:** This function is not available for Apple platforms. On those
/// platforms, checking group membership should be achieved via communication
/// with the `opendirectoryd` service.
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+#[cfg(not(apple_targets))]
pub fn getgroups() -> Result<Vec<Gid>> {
// First get the maximum number of groups. The value returned
// shall always be greater than or equal to one and less than or
// equal to the value of {NGROUPS_MAX} + 1.
let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
Ok(Some(n)) => (n + 1) as usize,
- Ok(None) | Err(_) => <usize>::max_value(),
+ Ok(None) | Err(_) => usize::MAX,
};
// Next, get the number of groups so we can size our Vec
@@ -1588,7 +1575,7 @@ pub fn getgroups() -> Result<Vec<Gid>> {
let ngroups = unsafe {
libc::getgroups(
groups.capacity() as c_int,
- groups.as_mut_ptr() as *mut gid_t,
+ groups.as_mut_ptr().cast(),
)
};
@@ -1640,22 +1627,15 @@ pub fn getgroups() -> Result<Vec<Gid>> {
/// # try_main().unwrap();
/// ```
#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "redox",
target_os = "haiku"
)))]
pub fn setgroups(groups: &[Gid]) -> Result<()> {
cfg_if! {
- if #[cfg(any(target_os = "aix",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))] {
+ if #[cfg(any(bsd,
+ solarish,
+ target_os = "aix"))] {
type setgroups_ngroups_t = c_int;
} else {
type setgroups_ngroups_t = size_t;
@@ -1667,7 +1647,7 @@ pub fn setgroups(groups: &[Gid]) -> Result<()> {
let res = unsafe {
libc::setgroups(
groups.len() as setgroups_ngroups_t,
- groups.as_ptr() as *const gid_t,
+ groups.as_ptr().cast(),
)
};
@@ -1696,20 +1676,19 @@ pub fn setgroups(groups: &[Gid]) -> Result<()> {
/// will only ever return the complete list or else an error.
#[cfg(not(any(
target_os = "aix",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
+ solarish,
+ apple_targets,
target_os = "redox"
)))]
pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
Ok(Some(n)) => n as c_int,
- Ok(None) | Err(_) => <c_int>::max_value(),
+ Ok(None) | Err(_) => c_int::MAX,
};
use std::cmp::min;
let mut groups = Vec::<Gid>::with_capacity(min(ngroups_max, 8) as usize);
cfg_if! {
- if #[cfg(any(target_os = "ios", target_os = "macos"))] {
+ if #[cfg(apple_targets)] {
type getgrouplist_group_t = c_int;
} else {
type getgrouplist_group_t = gid_t;
@@ -1722,7 +1701,7 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
libc::getgrouplist(
user.as_ptr(),
gid as getgrouplist_group_t,
- groups.as_mut_ptr() as *mut getgrouplist_group_t,
+ groups.as_mut_ptr().cast(),
&mut ngroups,
)
};
@@ -1781,14 +1760,13 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
/// # try_main().unwrap();
/// ```
#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "redox",
target_os = "haiku"
)))]
pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
cfg_if! {
- if #[cfg(any(target_os = "ios", target_os = "macos"))] {
+ if #[cfg(apple_targets)] {
type initgroups_group_t = c_int;
} else {
type initgroups_group_t = gid_t;
@@ -1915,6 +1893,7 @@ pub fn sleep(seconds: c_uint) -> c_uint {
feature! {
#![feature = "acct"]
+/// Process accounting
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
pub mod acct {
use crate::errno::Errno;
@@ -1970,7 +1949,7 @@ feature! {
pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
let mut path =
template.with_nix_path(|path| path.to_bytes_with_nul().to_owned())?;
- let p = path.as_mut_ptr() as *mut _;
+ let p = path.as_mut_ptr().cast();
let fd = unsafe { libc::mkstemp(p) };
let last = path.pop(); // drop the trailing nul
debug_assert!(last == Some(b'\0'));
@@ -1983,6 +1962,38 @@ pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
feature! {
#![all(feature = "fs", feature = "feature")]
+/// Creates a directory which persists even after process termination
+///
+/// * `template`: a path whose rightmost characters contain some number of X, e.g. `/tmp/tmpdir_XXXXXX`
+/// * returns: filename
+///
+/// Err is returned either if no temporary filename could be created or the template had insufficient X
+///
+/// See also [mkstemp(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html)
+///
+/// ```
+/// use nix::unistd;
+///
+/// match unistd::mkdtemp("/tmp/tempdir_XXXXXX") {
+/// Ok(_path) => {
+/// // do something with directory
+/// }
+/// Err(e) => panic!("mkdtemp failed: {}", e)
+/// };
+/// ```
+pub fn mkdtemp<P: ?Sized + NixPath>(template: &P) -> Result<PathBuf> {
+ let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?;
+ let p = path.as_mut_ptr() as *mut _;
+ let p = unsafe { libc::mkdtemp(p) };
+ if p.is_null() {
+ return Err(Errno::last());
+ }
+ let last = path.pop(); // drop the trailing nul
+ debug_assert!(last == Some(b'\0'));
+ let pathname = OsString::from_vec(path);
+ Ok(PathBuf::from(pathname))
+}
+
/// Variable names for `pathconf`
///
/// Nix uses the same naming convention for these variables as the
@@ -2004,16 +2015,13 @@ feature! {
#[non_exhaustive]
pub enum PathconfVar {
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
+ freebsdlike,
+ netbsdlike,
target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
target_os = "redox"
))]
/// Minimum number of bits needed to represent, as a signed integer value,
/// the maximum size of a regular file allowed in the specified directory.
- #[cfg_attr(docsrs, doc(cfg(all())))]
FILESIZEBITS = libc::_PC_FILESIZEBITS,
/// Maximum number of links to a single file.
LINK_MAX = libc::_PC_LINK_MAX,
@@ -2035,86 +2043,62 @@ pub enum PathconfVar {
/// a pipe.
PIPE_BUF = libc::_PC_PIPE_BUF,
#[cfg(any(
- target_os = "android",
+ linux_android,
+ solarish,
+ netbsdlike,
target_os = "dragonfly",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
target_os = "redox",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Symbolic links can be created.
POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
+ linux_android,
+ freebsdlike,
target_os = "openbsd",
target_os = "redox"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Minimum number of bytes of storage actually allocated for any portion of
/// a file.
POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
+ freebsdlike,
+ linux_android,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Recommended increment for file transfer sizes between the
/// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
+ linux_android,
+ freebsdlike,
target_os = "openbsd",
target_os = "redox"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Maximum recommended file transfer size.
POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
+ linux_android,
+ freebsdlike,
target_os = "openbsd",
target_os = "redox"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Minimum recommended file transfer size.
POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
+ linux_android,
+ freebsdlike,
target_os = "openbsd",
target_os = "redox"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Recommended file transfer buffer alignment.
POSIX_REC_XFER_ALIGN = libc::_PC_REC_XFER_ALIGN,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
+ linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike,
target_os = "redox",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Maximum number of bytes in a symbolic link.
SYMLINK_MAX = libc::_PC_SYMLINK_MAX,
/// The use of `chown` and `fchown` is restricted to a process with
@@ -2128,50 +2112,36 @@ pub enum PathconfVar {
/// disable terminal special character handling.
_POSIX_VDISABLE = libc::_PC_VDISABLE,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
+ linux_android,
+ freebsdlike,
+ solarish,
target_os = "openbsd",
target_os = "redox",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Asynchronous input or output operations may be performed for the
/// associated file.
_POSIX_ASYNC_IO = libc::_PC_ASYNC_IO,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
+ linux_android,
+ freebsdlike,
+ solarish,
target_os = "openbsd",
target_os = "redox",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Prioritized input or output operations may be performed for the
/// associated file.
_POSIX_PRIO_IO = libc::_PC_PRIO_IO,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
+ linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike,
target_os = "redox",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Synchronized input or output operations may be performed for the
/// associated file.
_POSIX_SYNC_IO = libc::_PC_SYNC_IO,
#[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The resolution in nanoseconds for all file timestamps.
_POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION,
}
@@ -2192,13 +2162,13 @@ pub enum PathconfVar {
/// - `Ok(None)`: the variable has no limit (for limit variables) or is
/// unsupported (for option variables)
/// - `Err(x)`: an error occurred
-pub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result<Option<c_long>> {
+pub fn fpathconf<F: AsFd>(fd: F, var: PathconfVar) -> Result<Option<c_long>> {
let raw = unsafe {
Errno::clear();
- libc::fpathconf(fd, var as c_int)
+ libc::fpathconf(fd.as_fd().as_raw_fd(), var as c_int)
};
if raw == -1 {
- if errno::errno() == 0 {
+ if Errno::last_raw() == 0 {
Ok(None)
} else {
Err(Errno::last())
@@ -2238,7 +2208,7 @@ pub fn pathconf<P: ?Sized + NixPath>(
libc::pathconf(cstr.as_ptr(), var as c_int)
})?;
if raw == -1 {
- if errno::errno() == 0 {
+ if Errno::last_raw() == 0 {
Ok(None)
} else {
Err(Errno::last())
@@ -2275,23 +2245,17 @@ pub enum SysconfVar {
/// Maximum number of I/O operations in a single list I/O call supported by
/// the implementation.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
/// Maximum number of outstanding asynchronous I/O operations supported by
/// the implementation.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
AIO_MAX = libc::_SC_AIO_MAX,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The maximum amount by which a process can decrease its asynchronous I/O
/// priority level from its own scheduling priority.
AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX,
@@ -2299,68 +2263,47 @@ pub enum SysconfVar {
ARG_MAX = libc::_SC_ARG_MAX,
/// Maximum number of functions that may be registered with `atexit`.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
/// Maximum obase values allowed by the bc utility.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
/// Maximum number of elements permitted in an array by the bc utility.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
/// Maximum scale value allowed by the bc utility.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
/// Maximum length of a string constant accepted by the bc utility.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
/// Maximum number of simultaneous processes per real user ID.
CHILD_MAX = libc::_SC_CHILD_MAX,
- // The number of clock ticks per second.
+ /// The frequency of the statistics clock in ticks per second.
CLK_TCK = libc::_SC_CLK_TCK,
/// Maximum number of weights that can be assigned to an entry of the
/// LC_COLLATE order keyword in the locale definition file
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
/// Maximum number of timer expiration overruns.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
/// Maximum number of expressions that can be nested within parentheses by
/// the expr utility.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
EXPR_NEST_MAX = libc::_SC_EXPR_NEST_MAX,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, solarish, target_os = "linux"))]
/// Maximum length of a host name (not including the terminating null) as
/// returned from the `gethostname` function
HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX,
/// Maximum number of iovec structures that one process has available for
/// use with `readv` or `writev`.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
IOV_MAX = libc::_SC_IOV_MAX,
/// Unless otherwise noted, the maximum length, in bytes, of a utility's
/// input line (either standard input or another file), when the utility is
/// described as processing text files. The length includes room for the
/// trailing newline.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
LINE_MAX = libc::_SC_LINE_MAX,
/// Maximum length of a login name.
#[cfg(not(target_os = "haiku"))]
@@ -2369,308 +2312,176 @@ pub enum SysconfVar {
NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
/// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
/// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
/// The maximum number of open message queue descriptors a process may hold.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
/// The maximum number of message priorities supported by the implementation.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
/// A value one greater than the maximum value that the system may assign to
/// a newly-created file descriptor.
OPEN_MAX = libc::_SC_OPEN_MAX,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Advisory Information option.
_POSIX_ADVISORY_INFO = libc::_SC_ADVISORY_INFO,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, solarish, target_os = "linux"))]
/// The implementation supports barriers.
_POSIX_BARRIERS = libc::_SC_BARRIERS,
/// The implementation supports asynchronous input and output.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_ASYNCHRONOUS_IO = libc::_SC_ASYNCHRONOUS_IO,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, solarish, target_os = "linux"))]
/// The implementation supports clock selection.
_POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, solarish, target_os = "linux"))]
/// The implementation supports the Process CPU-Time Clocks option.
_POSIX_CPUTIME = libc::_SC_CPUTIME,
/// The implementation supports the File Synchronization option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_FSYNC = libc::_SC_FSYNC,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
+ solarish,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the IPv6 option.
_POSIX_IPV6 = libc::_SC_IPV6,
/// The implementation supports job control.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
/// The implementation supports memory mapped Files.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
/// The implementation supports the Process Memory Locking option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_MEMLOCK = libc::_SC_MEMLOCK,
/// The implementation supports the Range Memory Locking option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
/// The implementation supports memory protection.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
/// The implementation supports the Message Passing option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
/// The implementation supports the Monotonic Clock option.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_MONOTONIC_CLOCK = libc::_SC_MONOTONIC_CLOCK,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ solarish,
+ apple_targets,
target_os = "openbsd",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Prioritized Input and Output option.
_POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO,
/// The implementation supports the Process Scheduling option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_PRIORITY_SCHEDULING = libc::_SC_PRIORITY_SCHEDULING,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
+ freebsdlike,
+ solarish,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Raw Sockets option.
_POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
+ bsd,
+ solarish,
target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports read-write locks.
_POSIX_READER_WRITER_LOCKS = libc::_SC_READER_WRITER_LOCKS,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports realtime signals.
_POSIX_REALTIME_SIGNALS = libc::_SC_REALTIME_SIGNALS,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
+ bsd,
+ solarish,
target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Regular Expression Handling option.
_POSIX_REGEXP = libc::_SC_REGEXP,
/// Each process has a saved set-user-ID and a saved set-group-ID.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
/// The implementation supports semaphores.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
/// The implementation supports the Shared Memory Objects option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux",))]
/// The implementation supports the POSIX shell.
_POSIX_SHELL = libc::_SC_SHELL,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux",))]
/// The implementation supports the Spawn option.
_POSIX_SPAWN = libc::_SC_SPAWN,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux",))]
/// The implementation supports spin locks.
_POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Process Sporadic Server option.
_POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER,
+ /// The number of replenishment operations that can be simultaneously pending for a particular
+ /// sporadic server scheduler.
#[cfg(any(
- target_os = "ios",
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
/// The implementation supports the Synchronized Input and Output option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
/// The implementation supports the Thread Stack Address Attribute option.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
/// The implementation supports the Thread Stack Size Attribute option.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
#[cfg(any(
- target_os = "ios",
+ apple_targets,
target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
+ netbsdlike,
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Thread CPU-Time Clocks option.
_POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
/// The implementation supports the Non-Robust Mutex Priority Inheritance
/// option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
/// The implementation supports the Non-Robust Mutex Priority Protection option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
/// The implementation supports the Thread Execution Scheduling option.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation supports the Thread Process-Shared Synchronization
/// option.
_POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED,
@@ -2679,7 +2490,6 @@ pub enum SysconfVar {
target_os = "linux",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Robust Mutex Priority Inheritance option.
_POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT,
#[cfg(any(
@@ -2687,484 +2497,319 @@ pub enum SysconfVar {
target_os = "linux",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Robust Mutex Priority Protection option.
_POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
/// The implementation supports thread-safe functions.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Thread Sporadic Server option.
_POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
/// The implementation supports threads.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_THREADS = libc::_SC_THREADS,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports timeouts.
_POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
/// The implementation supports timers.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_TIMERS = libc::_SC_TIMERS,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Trace option.
_POSIX_TRACE = libc::_SC_TRACE,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Trace Event Filter option.
_POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER,
+ /// Maximum size of a trace event name in characters.
#[cfg(any(
- target_os = "ios",
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Trace Inherit option.
_POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Trace Log option.
_POSIX_TRACE_LOG = libc::_SC_TRACE_LOG,
+ /// The length in bytes of a trace generation version string or a trace stream name.
#[cfg(any(
- target_os = "ios",
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX,
+ /// Maximum number of times `posix_trace_create` may be called from the same or different
+ /// processes.
#[cfg(any(
- target_os = "ios",
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX,
+ /// Maximum number of user trace event type identifiers for a single process.
#[cfg(any(
- target_os = "ios",
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Typed Memory Objects option.
_POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS,
/// Integer value indicating version of this standard (C-language binding)
/// to which the implementation conforms. For implementations conforming to
/// POSIX.1-2008, the value shall be 200809L.
_POSIX_VERSION = libc::_SC_VERSION,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation provides a C-language compilation environment with
/// 32-bit `int`, `long`, `pointer`, and `off_t` types.
_POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation provides a C-language compilation environment with
/// 32-bit `int`, `long`, and pointer types and an `off_t` type using at
/// least 64 bits.
_POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation provides a C-language compilation environment with
/// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types.
_POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation provides a C-language compilation environment with an
/// `int` type using at least 32 bits and `long`, pointer, and `off_t` types
/// using at least 64 bits.
_POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
/// The implementation supports the C-Language Binding option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_C_BIND = libc::_SC_2_C_BIND,
/// The implementation supports the C-Language Development Utilities option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_C_DEV = libc::_SC_2_C_DEV,
/// The implementation supports the Terminal Characteristics option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
/// The implementation supports the FORTRAN Development Utilities option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
/// The implementation supports the FORTRAN Runtime Utilities option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
/// The implementation supports the creation of locales by the localedef
/// utility.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation supports the Batch Environment Services and Utilities
/// option.
_POSIX2_PBS = libc::_SC_2_PBS,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation supports the Batch Accounting option.
_POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation supports the Batch Checkpoint/Restart option.
_POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation supports the Locate Batch Job Request option.
_POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation supports the Batch Job Message Request option.
_POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(bsd, target_os = "linux"))]
/// The implementation supports the Track Batch Job Request option.
_POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
/// The implementation supports the Software Development Utilities option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
/// The implementation supports the User Portability Utilities option.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_UPE = libc::_SC_2_UPE,
/// Integer value indicating version of the Shell and Utilities volume of
/// POSIX.1 to which the implementation conforms.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_POSIX2_VERSION = libc::_SC_2_VERSION,
/// The size of a system page in bytes.
///
/// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
/// enum constants to have the same value, so nix omits `PAGESIZE`.
PAGE_SIZE = libc::_SC_PAGE_SIZE,
+ /// Maximum number of attempts made to destroy a thread's thread-specific data values on thread
+ /// exit.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
+ /// Maximum number of data keys that can be created by a process.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
+ /// Minimum size in bytes of thread stack storage.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
+ /// Maximum number of threads that can be created per process.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
+ /// The maximum number of repeated occurrences of a regular expression permitted when using
+ /// interval notation.
#[cfg(not(target_os = "haiku"))]
RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
+ /// Maximum number of realtime signals reserved for application use.
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
RTSIG_MAX = libc::_SC_RTSIG_MAX,
+ /// Maximum number of semaphores that a process may have.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
+ /// The maximum value a semaphore may have.
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX,
+ /// Maximum number of queued signals that a process may send and have pending at the
+ /// receiver(s) at any time.
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX,
+ /// The minimum maximum number of streams that a process may have open at any one time.
STREAM_MAX = libc::_SC_STREAM_MAX,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Maximum number of symbolic links that can be reliably traversed in the resolution of a
+ /// pathname in the absence of a loop.
+ #[cfg(any(bsd, target_os = "linux"))]
SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
+ /// Maximum number of timers per process supported.
#[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
TIMER_MAX = libc::_SC_TIMER_MAX,
+ /// Maximum length of terminal device name.
TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
+ /// The minimum maximum number of types supported for the name of a timezone.
TZNAME_MAX = libc::_SC_TZNAME_MAX,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the X/Open Encryption Option Group.
_XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the Issue 4, Version 2 Enhanced
/// Internationalization Option Group.
_XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// The implementation supports the XOpen Legacy Option group.
+ ///
+ /// See Also <https://pubs.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap02.html>
_XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the X/Open Realtime Option Group.
_XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the X/Open Realtime Threads Option Group.
_XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
/// The implementation supports the Issue 4, Version 2 Shared Memory Option
/// Group.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
_XOPEN_SHM = libc::_SC_XOPEN_SHM,
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
+ freebsdlike,
+ apple_targets,
target_os = "linux",
- target_os = "macos",
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the XSI STREAMS Option Group.
_XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// The implementation supports the XSI option
_XOPEN_UNIX = libc::_SC_XOPEN_UNIX,
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
+ linux_android,
+ freebsdlike,
+ apple_targets,
target_os = "openbsd"
))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
/// Integer value indicating version of the X/Open Portability Guide to
/// which the implementation conforms.
_XOPEN_VERSION = libc::_SC_XOPEN_VERSION,
/// The number of pages of physical memory. Note that it is possible for
/// the product of this value to overflow.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
_PHYS_PAGES = libc::_SC_PHYS_PAGES,
/// The number of currently available pages of physical memory.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
_AVPHYS_PAGES = libc::_SC_AVPHYS_PAGES,
/// The number of processors configured.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
_NPROCESSORS_CONF = libc::_SC_NPROCESSORS_CONF,
/// The number of processors currently online (available).
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
_NPROCESSORS_ONLN = libc::_SC_NPROCESSORS_ONLN,
}
@@ -3190,7 +2835,7 @@ pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
libc::sysconf(var as c_int)
};
if raw == -1 {
- if errno::errno() == 0 {
+ if Errno::last_raw() == 0 {
Ok(None)
} else {
Err(Errno::last())
@@ -3201,12 +2846,15 @@ pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[cfg(feature = "fs")]
mod pivot_root {
use crate::errno::Errno;
use crate::{NixPath, Result};
+ /// Change the root file system.
+ ///
+ /// See Also [`pivot_root`](https://man7.org/linux/man-pages/man2/pivot_root.2.html)
pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
new_root: &P1,
put_old: &P2,
@@ -3225,13 +2873,7 @@ mod pivot_root {
}
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "openbsd"
-))]
+#[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
mod setres {
feature! {
#![feature = "user"]
@@ -3276,13 +2918,7 @@ mod setres {
}
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "openbsd"
-))]
+#[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
mod getres {
feature! {
#![feature = "user"]
@@ -3294,16 +2930,22 @@ mod getres {
/// Real, effective and saved user IDs.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ResUid {
+ /// Real UID
pub real: Uid,
+ /// Effective UID
pub effective: Uid,
+ /// Saved UID
pub saved: Uid,
}
/// Real, effective and saved group IDs.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ResGid {
+ /// Real GID
pub real: Gid,
+ /// Effective GID
pub effective: Gid,
+ /// Saved GID
pub saved: Gid,
}
@@ -3318,9 +2960,9 @@ mod getres {
///
#[inline]
pub fn getresuid() -> Result<ResUid> {
- let mut ruid = libc::uid_t::max_value();
- let mut euid = libc::uid_t::max_value();
- let mut suid = libc::uid_t::max_value();
+ let mut ruid = libc::uid_t::MAX;
+ let mut euid = libc::uid_t::MAX;
+ let mut suid = libc::uid_t::MAX;
let res = unsafe { libc::getresuid(&mut ruid, &mut euid, &mut suid) };
Errno::result(res).map(|_| ResUid {
@@ -3341,9 +2983,9 @@ mod getres {
///
#[inline]
pub fn getresgid() -> Result<ResGid> {
- let mut rgid = libc::gid_t::max_value();
- let mut egid = libc::gid_t::max_value();
- let mut sgid = libc::gid_t::max_value();
+ let mut rgid = libc::gid_t::MAX;
+ let mut egid = libc::gid_t::MAX;
+ let mut sgid = libc::gid_t::MAX;
let res = unsafe { libc::getresgid(&mut rgid, &mut egid, &mut sgid) };
Errno::result(res).map(|_| ResGid {
@@ -3355,6 +2997,62 @@ mod getres {
}
}
+#[cfg(feature = "process")]
+#[cfg(target_os = "freebsd")]
+libc_bitflags! {
+ /// Flags for [`rfork`]
+ ///
+ /// subset of flags supported by FreeBSD 12.x and onwards
+ /// with a safe outcome, thus as `RFMEM` can possibly lead to undefined behavior,
+ /// it is not in the list. And `rfork_thread` is deprecated.
+ pub struct RforkFlags: libc::c_int {
+ /// creates a new process.
+ RFPROC;
+ /// the child process will detach from the parent.
+ /// however, no status will be emitted at child's exit.
+ RFNOWAIT;
+ /// the file descriptor's table will be copied
+ RFFDG;
+ /// a new file descriptor's table will be created
+ RFCFDG;
+ /// force sharing the sigacts structure between
+ /// the child and the parent.
+ RFSIGSHARE;
+ /// enables kernel thread support.
+ RFTHREAD;
+ /// sets a status to emit at child's exit.
+ RFTSIGZMB;
+ /// linux's behavior compatibility setting.
+ /// emits SIGUSR1 as opposed to SIGCHLD upon child's exit.
+ RFLINUXTHPN;
+ }
+}
+
+feature! {
+#![feature = "process"]
+#[cfg(target_os = "freebsd")]
+/// Like [`fork`], `rfork` can be used to have a tigher control about which
+/// resources child and parent process will be sharing, file descriptors,
+/// address spaces and child exit's behavior.
+///
+/// # Safety
+///
+/// The same restrictions apply as for [`fork`].
+///
+/// # See Also
+///
+/// * [rfork(2)](https://man.freebsd.org/cgi/man.cgi?query=rfork)
+pub unsafe fn rfork(flags: RforkFlags) -> Result<ForkResult> {
+ use ForkResult::*;
+ let res = unsafe { libc::rfork(flags.bits()) };
+
+ Errno::result(res).map(|res| match res {
+ 0 => Child,
+ res => Parent { child: Pid(res) },
+ })
+}
+}
+
#[cfg(feature = "fs")]
libc_bitflags! {
/// Options for access()
@@ -3419,9 +3117,8 @@ pub fn faccessat<P: ?Sized + NixPath>(
/// * [FreeBSD man page](https://www.freebsd.org/cgi/man.cgi?query=eaccess&sektion=2&n=1)
/// * [Linux man page](https://man7.org/linux/man-pages/man3/euidaccess.3.html)
#[cfg(any(
+ freebsdlike,
all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "freebsd",
- target_os = "dragonfly"
))]
pub fn eaccess<P: ?Sized + NixPath>(path: &P, mode: AccessFlags) -> Result<()> {
let res = path.with_nix_path(|cstr| unsafe {
@@ -3460,39 +3157,33 @@ pub struct User {
pub shell: PathBuf,
/// Login class
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub class: CString,
/// Last password change
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub change: libc::time_t,
/// Expiration time of account
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
pub expire: libc::time_t,
}
@@ -3539,34 +3230,31 @@ impl From<&libc::passwd> for User {
uid: Uid::from_raw(pw.pw_uid),
gid: Gid::from_raw(pw.pw_gid),
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
class: CString::new(CStr::from_ptr(pw.pw_class).to_bytes())
.unwrap(),
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
change: pw.pw_change,
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
expire: pw.pw_expire,
}
@@ -3602,40 +3290,37 @@ impl From<User> for libc::passwd {
pw_uid: u.uid.0,
pw_gid: u.gid.0,
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
pw_class: u.class.into_raw(),
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
pw_change: u.change,
#[cfg(not(any(
+ linux_android,
+ solarish,
target_os = "aix",
- target_os = "android",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "solaris"
+ target_os = "hurd",
)))]
pw_expire: u.expire,
- #[cfg(target_os = "illumos")]
+ #[cfg(solarish)]
pw_age: CString::new("").unwrap().into_raw(),
- #[cfg(target_os = "illumos")]
+ #[cfg(solarish)]
pw_comment: CString::new("").unwrap().into_raw(),
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+ #[cfg(freebsdlike)]
pw_fields: 0,
}
}
@@ -3680,7 +3365,7 @@ impl User {
} else {
// SAFETY: `f` guarantees that `pwd` is initialized if `res`
// is not null.
- let pwd = pwd.assume_init();
+ let pwd = unsafe { pwd.assume_init() };
return Ok(Some(User::from(&pwd)));
}
} else if Errno::last() == Errno::ERANGE {
@@ -3790,18 +3475,17 @@ impl Group {
let mut ret = Vec::new();
for i in 0.. {
- let u = mem.offset(i);
- if (*u).is_null() {
+ let u = unsafe { mem.offset(i).read_unaligned() };
+ if u.is_null() {
break;
} else {
- let s = CStr::from_ptr(*u).to_string_lossy().into_owned();
+ let s = unsafe {CStr::from_ptr(u).to_string_lossy().into_owned()};
ret.push(s);
}
}
ret
}
-
/// # Safety
///
/// If `f` writes to its `*mut *mut libc::group` parameter, then it must
@@ -3839,7 +3523,7 @@ impl Group {
} else {
// SAFETY: `f` guarantees that `grp` is initialized if `res`
// is not null.
- let grp = grp.assume_init();
+ let grp = unsafe { grp.assume_init() };
return Ok(Some(Group::from(&grp)));
}
} else if Errno::last() == Errno::ERANGE {
@@ -3913,19 +3597,22 @@ feature! {
/// Get the name of the terminal device that is open on file descriptor fd
/// (see [`ttyname(3)`](https://man7.org/linux/man-pages/man3/ttyname.3.html)).
#[cfg(not(target_os = "fuchsia"))]
-pub fn ttyname(fd: RawFd) -> Result<PathBuf> {
+pub fn ttyname<F: AsFd>(fd: F) -> Result<PathBuf> {
+ #[cfg(not(target_os = "hurd"))]
const PATH_MAX: usize = libc::PATH_MAX as usize;
+ #[cfg(target_os = "hurd")]
+ const PATH_MAX: usize = 1024; // Hurd does not define a hard limit, so try a guess first
let mut buf = vec![0_u8; PATH_MAX];
- let c_buf = buf.as_mut_ptr() as *mut libc::c_char;
+ let c_buf = buf.as_mut_ptr().cast();
- let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) };
+ let ret = unsafe { libc::ttyname_r(fd.as_fd().as_raw_fd(), c_buf, buf.len()) };
if ret != 0 {
- return Err(Errno::from_i32(ret));
+ return Err(Errno::from_raw(ret));
}
- let nul = buf.iter().position(|c| *c == b'\0').unwrap();
- buf.truncate(nul);
- Ok(OsString::from_vec(buf).into())
+ CStr::from_bytes_until_nul(&buf[..])
+ .map(|s| OsStr::from_bytes(s.to_bytes()).into())
+ .map_err(|_| Errno::EINVAL)
}
}
@@ -3935,19 +3622,12 @@ feature! {
/// Get the effective user ID and group ID associated with a Unix domain socket.
///
/// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid)
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "dragonfly",
-))]
-pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
+#[cfg(bsd)]
+pub fn getpeereid<F: AsFd>(fd: F) -> Result<(Uid, Gid)> {
let mut uid = 1;
let mut gid = 1;
- let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) };
+ let ret = unsafe { libc::getpeereid(fd.as_fd().as_raw_fd(), &mut uid, &mut gid) };
Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
}
@@ -3959,14 +3639,7 @@ feature! {
/// Set the file flags.
///
/// See also [chflags(2)](https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2)
-#[cfg(any(
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "macos",
- target_os = "ios"
-))]
+#[cfg(bsd)]
pub fn chflags<P: ?Sized + NixPath>(path: &P, flags: FileFlag) -> Result<()> {
let res = path.with_nix_path(|cstr| unsafe {
libc::chflags(cstr.as_ptr(), flags.bits())
diff --git a/third_party/rust/nix/test/common/mod.rs b/third_party/rust/nix/test/common/mod.rs
index bb056aab87..db4aed2598 100644
--- a/third_party/rust/nix/test/common/mod.rs
+++ b/third_party/rust/nix/test/common/mod.rs
@@ -2,18 +2,18 @@ use cfg_if::cfg_if;
#[macro_export]
macro_rules! skip {
- ($($reason: expr),+) => {
+ ($($reason: expr),+) => {{
use ::std::io::{self, Write};
let stderr = io::stderr();
let mut handle = stderr.lock();
writeln!(handle, $($reason),+).unwrap();
return;
- }
+ }}
}
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
#[macro_export] macro_rules! require_capability {
($name:expr, $capname:ident) => {
use ::caps::{Capability, CapSet, has_cap};
@@ -51,7 +51,7 @@ macro_rules! require_mount {
};
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[macro_export]
macro_rules! skip_if_cirrus {
($reason:expr) => {
@@ -87,7 +87,7 @@ macro_rules! skip_if_not_root {
}
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
#[macro_export] macro_rules! skip_if_seccomp {
($name:expr) => {
if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
diff --git a/third_party/rust/nix/test/sys/mod.rs b/third_party/rust/nix/test/sys/mod.rs
index 20312120a6..fb3f6be0e5 100644
--- a/third_party/rust/nix/test/sys/mod.rs
+++ b/third_party/rust/nix/test/sys/mod.rs
@@ -7,16 +7,16 @@ mod test_signal;
// cases on DragonFly.
#[cfg(any(
target_os = "freebsd",
- target_os = "ios",
+ apple_targets,
all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "macos",
target_os = "netbsd"
))]
mod test_aio;
#[cfg(not(any(
target_os = "redox",
target_os = "fuchsia",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "hurd"
)))]
mod test_ioctl;
#[cfg(not(target_os = "redox"))]
@@ -30,7 +30,7 @@ mod test_socket;
#[cfg(not(any(target_os = "redox")))]
mod test_sockopt;
mod test_stat;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_sysinfo;
#[cfg(not(any(
target_os = "redox",
@@ -41,20 +41,44 @@ mod test_termios;
mod test_uio;
mod test_wait;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_epoll;
#[cfg(target_os = "linux")]
+mod test_fanotify;
+#[cfg(target_os = "linux")]
mod test_inotify;
mod test_pthread;
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+
+#[cfg(any(linux_android, freebsdlike, netbsdlike, apple_targets))]
mod test_ptrace;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_timerfd;
+
+#[cfg(all(
+ any(
+ target_os = "freebsd",
+ solarish,
+ target_os = "linux",
+ target_os = "netbsd"
+ ),
+ feature = "time",
+ feature = "signal"
+))]
+mod test_timer;
+
+#[cfg(bsd)]
+mod test_event;
+mod test_statvfs;
+mod test_time;
+mod test_utsname;
+
+#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "openbsd"))]
+mod test_statfs;
+
+#[cfg(not(any(
+ target_os = "redox",
+ target_os = "fuchsia",
+ solarish,
+ target_os = "haiku"
+)))]
+mod test_resource;
diff --git a/third_party/rust/nix/test/sys/test_aio.rs b/third_party/rust/nix/test/sys/test_aio.rs
index 5035b5a08f..ba5ad02ec3 100644
--- a/third_party/rust/nix/test/sys/test_aio.rs
+++ b/third_party/rust/nix/test/sys/test_aio.rs
@@ -67,7 +67,7 @@ mod aio_fsync {
// Skip on Linux, because Linux's AIO implementation can't detect errors
// synchronously
#[test]
- #[cfg(any(target_os = "freebsd", target_os = "macos"))]
+ #[cfg(any(target_os = "freebsd", apple_targets))]
fn error() {
use std::mem;
@@ -157,7 +157,7 @@ mod aio_read {
// Skip on Linux, because Linux's AIO implementation can't detect errors
// synchronously
#[test]
- #[cfg(any(target_os = "freebsd", target_os = "macos"))]
+ #[cfg(any(target_os = "freebsd", apple_targets))]
fn error() {
const INITIAL: &[u8] = b"abcdef123456";
let mut rbuf = vec![0; 4];
@@ -411,7 +411,7 @@ mod aio_write {
// Skip on Linux, because Linux's AIO implementation can't detect errors
// synchronously
#[test]
- #[cfg(any(target_os = "freebsd", target_os = "macos"))]
+ #[cfg(any(target_os = "freebsd", apple_targets))]
fn error() {
let wbuf = "CDEF".to_string().into_bytes();
let mut aiow = Box::pin(AioWrite::new(
@@ -498,7 +498,9 @@ mod aio_writev {
any(
all(target_env = "musl", target_arch = "x86_64"),
target_arch = "mips",
- target_arch = "mips64"
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
),
ignore
)]
@@ -567,12 +569,6 @@ fn test_aio_cancel_all() {
}
#[test]
-// On Cirrus on Linux, this test fails due to a glibc bug.
-// https://github.com/nix-rust/nix/issues/1099
-#[cfg_attr(target_os = "linux", ignore)]
-// On Cirrus, aio_suspend is failing with EINVAL
-// https://github.com/nix-rust/nix/issues/1361
-#[cfg_attr(target_os = "macos", ignore)]
fn test_aio_suspend() {
const INITIAL: &[u8] = b"abcdef123456";
const WBUF: &[u8] = b"CDEFG";
@@ -622,3 +618,53 @@ fn test_aio_suspend() {
assert_eq!(wcb.as_mut().aio_return().unwrap(), WBUF.len());
assert_eq!(rcb.as_mut().aio_return().unwrap(), rlen);
}
+
+/// aio_suspend relies on casting Rust Aio* struct pointers to libc::aiocb
+/// pointers. This test ensures that such casts are valid.
+#[test]
+fn casting() {
+ let sev = SigevNotify::SigevNone;
+ let aiof = AioFsync::new(666, AioFsyncMode::O_SYNC, 0, sev);
+ assert_eq!(
+ aiof.as_ref() as *const libc::aiocb,
+ &aiof as *const AioFsync as *const libc::aiocb
+ );
+
+ let mut rbuf = [];
+ let aior = AioRead::new(666, 0, &mut rbuf, 0, sev);
+ assert_eq!(
+ aior.as_ref() as *const libc::aiocb,
+ &aior as *const AioRead as *const libc::aiocb
+ );
+
+ let wbuf = [];
+ let aiow = AioWrite::new(666, 0, &wbuf, 0, sev);
+ assert_eq!(
+ aiow.as_ref() as *const libc::aiocb,
+ &aiow as *const AioWrite as *const libc::aiocb
+ );
+}
+
+#[cfg(target_os = "freebsd")]
+#[test]
+fn casting_vectored() {
+ use std::io::{IoSlice, IoSliceMut};
+
+ let sev = SigevNotify::SigevNone;
+
+ let mut rbuf = [];
+ let mut rbufs = [IoSliceMut::new(&mut rbuf)];
+ let aiorv = AioReadv::new(666, 0, &mut rbufs[..], 0, sev);
+ assert_eq!(
+ aiorv.as_ref() as *const libc::aiocb,
+ &aiorv as *const AioReadv as *const libc::aiocb
+ );
+
+ let wbuf = [];
+ let wbufs = [IoSlice::new(&wbuf)];
+ let aiowv = AioWritev::new(666, 0, &wbufs, 0, sev);
+ assert_eq!(
+ aiowv.as_ref() as *const libc::aiocb,
+ &aiowv as *const AioWritev as *const libc::aiocb
+ );
+}
diff --git a/third_party/rust/nix/test/sys/test_aio_drop.rs b/third_party/rust/nix/test/sys/test_aio_drop.rs
index bbe6623fd7..54106dd168 100644
--- a/third_party/rust/nix/test/sys/test_aio_drop.rs
+++ b/third_party/rust/nix/test/sys/test_aio_drop.rs
@@ -8,8 +8,7 @@
not(target_env = "uclibc"),
any(
target_os = "linux",
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
)
diff --git a/third_party/rust/nix/test/sys/test_event.rs b/third_party/rust/nix/test/sys/test_event.rs
new file mode 100644
index 0000000000..a10b1e5d12
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_event.rs
@@ -0,0 +1,41 @@
+use libc::intptr_t;
+use nix::sys::event::{EventFilter, EventFlag, FilterFlag, KEvent};
+
+#[test]
+fn test_struct_kevent() {
+ use std::mem;
+
+ let udata: intptr_t = 12345;
+ let data: intptr_t = 0x1337;
+
+ let actual = KEvent::new(
+ 0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ data,
+ udata,
+ );
+ assert_eq!(0xdead_beef, actual.ident());
+ assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
+ assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
+ assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
+ assert_eq!(data, actual.data());
+ assert_eq!(udata, actual.udata());
+ assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
+}
+
+#[test]
+fn test_kevent_filter() {
+ let udata: intptr_t = 12345;
+
+ let actual = KEvent::new(
+ 0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ 0x1337,
+ udata,
+ );
+ assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
+}
diff --git a/third_party/rust/nix/test/sys/test_fanotify.rs b/third_party/rust/nix/test/sys/test_fanotify.rs
new file mode 100644
index 0000000000..20226c272a
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_fanotify.rs
@@ -0,0 +1,149 @@
+use crate::*;
+use nix::sys::fanotify::{
+ EventFFlags, Fanotify, FanotifyResponse, InitFlags, MarkFlags, MaskFlags,
+ Response,
+};
+use std::fs::{read_link, File, OpenOptions};
+use std::io::ErrorKind;
+use std::io::{Read, Write};
+use std::os::fd::AsRawFd;
+use std::thread;
+
+#[test]
+/// Run fanotify tests sequentially to avoid tmp files races
+pub fn test_fanotify() {
+ require_capability!("test_fanotify", CAP_SYS_ADMIN);
+
+ test_fanotify_notifications();
+ test_fanotify_responses();
+}
+
+fn test_fanotify_notifications() {
+ let group =
+ Fanotify::init(InitFlags::FAN_CLASS_NOTIF, EventFFlags::O_RDONLY)
+ .unwrap();
+ let tempdir = tempfile::tempdir().unwrap();
+ let tempfile = tempdir.path().join("test");
+ OpenOptions::new()
+ .write(true)
+ .create_new(true)
+ .open(&tempfile)
+ .unwrap();
+
+ group
+ .mark(
+ MarkFlags::FAN_MARK_ADD,
+ MaskFlags::FAN_OPEN | MaskFlags::FAN_MODIFY | MaskFlags::FAN_CLOSE,
+ None,
+ Some(&tempfile),
+ )
+ .unwrap();
+
+ // modify test file
+ {
+ let mut f = OpenOptions::new().write(true).open(&tempfile).unwrap();
+ f.write_all(b"hello").unwrap();
+ }
+
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(
+ event.mask(),
+ MaskFlags::FAN_OPEN
+ | MaskFlags::FAN_MODIFY
+ | MaskFlags::FAN_CLOSE_WRITE
+ );
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+
+ // read test file
+ {
+ let mut f = File::open(&tempfile).unwrap();
+ let mut s = String::new();
+ f.read_to_string(&mut s).unwrap();
+ }
+
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(
+ event.mask(),
+ MaskFlags::FAN_OPEN | MaskFlags::FAN_CLOSE_NOWRITE
+ );
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+}
+
+fn test_fanotify_responses() {
+ let group =
+ Fanotify::init(InitFlags::FAN_CLASS_CONTENT, EventFFlags::O_RDONLY)
+ .unwrap();
+ let tempdir = tempfile::tempdir().unwrap();
+ let tempfile = tempdir.path().join("test");
+ OpenOptions::new()
+ .write(true)
+ .create_new(true)
+ .open(&tempfile)
+ .unwrap();
+
+ group
+ .mark(
+ MarkFlags::FAN_MARK_ADD,
+ MaskFlags::FAN_OPEN_PERM,
+ None,
+ Some(&tempfile),
+ )
+ .unwrap();
+
+ let file_thread = thread::spawn({
+ let tempfile = tempfile.clone();
+
+ move || {
+ // first open, should fail
+ let Err(e) = File::open(&tempfile) else {
+ panic!("The first open should fail");
+ };
+ assert_eq!(e.kind(), ErrorKind::PermissionDenied);
+
+ // second open, should succeed
+ File::open(&tempfile).unwrap();
+ }
+ });
+
+ // Deny the first open try
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(event.mask(), MaskFlags::FAN_OPEN_PERM);
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+ group
+ .write_response(FanotifyResponse::new(*fd, Response::FAN_DENY))
+ .unwrap();
+
+ // Allow the second open try
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(event.mask(), MaskFlags::FAN_OPEN_PERM);
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+ group
+ .write_response(FanotifyResponse::new(*fd, Response::FAN_ALLOW))
+ .unwrap();
+
+ file_thread.join().unwrap();
+}
diff --git a/third_party/rust/nix/test/sys/test_ioctl.rs b/third_party/rust/nix/test/sys/test_ioctl.rs
index 40f60cfdbc..08843bf61c 100644
--- a/third_party/rust/nix/test/sys/test_ioctl.rs
+++ b/third_party/rust/nix/test/sys/test_ioctl.rs
@@ -28,7 +28,7 @@ ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
// TODO: Need a way to compute these constants at test time. Using precomputed
// values is fragile and needs to be maintained.
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
mod linux {
// The cast is not unnecessary on all platforms.
#[allow(clippy::unnecessary_cast)]
@@ -36,7 +36,9 @@ mod linux {
fn test_op_none() {
if cfg!(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64"
)) {
@@ -54,7 +56,9 @@ mod linux {
fn test_op_write() {
if cfg!(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64"
)) {
@@ -69,7 +73,11 @@ mod linux {
#[cfg(target_pointer_width = "64")]
#[test]
fn test_op_write_64() {
- if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) {
+ if cfg!(any(
+ target_arch = "mips64",
+ target_arch = "mips64r6",
+ target_arch = "powerpc64"
+ )) {
assert_eq!(
request_code_write!(b'z', 10, 1u64 << 32) as u32,
0x8000_7A0A
@@ -88,7 +96,9 @@ mod linux {
fn test_op_read() {
if cfg!(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64"
)) {
@@ -103,7 +113,11 @@ mod linux {
#[cfg(target_pointer_width = "64")]
#[test]
fn test_op_read_64() {
- if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) {
+ if cfg!(any(
+ target_arch = "mips64",
+ target_arch = "mips64r6",
+ target_arch = "powerpc64"
+ )) {
assert_eq!(
request_code_read!(b'z', 10, 1u64 << 32) as u32,
0x4000_7A0A
@@ -134,14 +148,7 @@ mod linux {
}
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(bsd)]
mod bsd {
#[test]
fn test_op_none() {
@@ -149,7 +156,7 @@ mod bsd {
assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
}
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+ #[cfg(freebsdlike)]
#[test]
fn test_op_write_int() {
assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
@@ -193,7 +200,7 @@ mod bsd {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod linux_ioctls {
use std::mem;
use std::os::unix::io::AsRawFd;
diff --git a/third_party/rust/nix/test/sys/test_mman.rs b/third_party/rust/nix/test/sys/test_mman.rs
index b4674e53fa..3689f642be 100644
--- a/third_party/rust/nix/test/sys/test_mman.rs
+++ b/third_party/rust/nix/test/sys/test_mman.rs
@@ -1,44 +1,44 @@
-use nix::sys::mman::{mmap, MapFlags, ProtFlags};
-use std::{num::NonZeroUsize, os::unix::io::BorrowedFd};
+#![allow(clippy::redundant_slicing)]
+
+use nix::sys::mman::{mmap_anonymous, MapFlags, ProtFlags};
+use std::num::NonZeroUsize;
#[test]
fn test_mmap_anonymous() {
unsafe {
- let ptr = mmap::<BorrowedFd>(
+ let mut ptr = mmap_anonymous(
None,
NonZeroUsize::new(1).unwrap(),
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS,
- None,
- 0,
+ MapFlags::MAP_PRIVATE,
)
- .unwrap() as *mut u8;
- assert_eq!(*ptr, 0x00u8);
- *ptr = 0xffu8;
- assert_eq!(*ptr, 0xffu8);
+ .unwrap()
+ .cast::<u8>();
+ assert_eq!(*ptr.as_ref(), 0x00u8);
+ *ptr.as_mut() = 0xffu8;
+ assert_eq!(*ptr.as_ref(), 0xffu8);
}
}
#[test]
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
fn test_mremap_grow() {
- use nix::libc::{c_void, size_t};
+ use nix::libc::size_t;
use nix::sys::mman::{mremap, MRemapFlags};
+ use std::ptr::NonNull;
const ONE_K: size_t = 1024;
let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
let slice: &mut [u8] = unsafe {
- let mem = mmap::<BorrowedFd>(
+ let mem = mmap_anonymous(
None,
one_k_non_zero,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
- None,
- 0,
+ MapFlags::MAP_PRIVATE,
)
.unwrap();
- std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
+ std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
};
assert_eq!(slice[ONE_K - 1], 0x00);
slice[ONE_K - 1] = 0xFF;
@@ -47,7 +47,7 @@ fn test_mremap_grow() {
let slice: &mut [u8] = unsafe {
#[cfg(target_os = "linux")]
let mem = mremap(
- slice.as_mut_ptr() as *mut c_void,
+ NonNull::from(&mut slice[..]).cast(),
ONE_K,
10 * ONE_K,
MRemapFlags::MREMAP_MAYMOVE,
@@ -56,14 +56,14 @@ fn test_mremap_grow() {
.unwrap();
#[cfg(target_os = "netbsd")]
let mem = mremap(
- slice.as_mut_ptr() as *mut c_void,
+ NonNull::from(&mut slice[..]).cast(),
ONE_K,
10 * ONE_K,
MRemapFlags::MAP_REMAPDUP,
None,
)
.unwrap();
- std::slice::from_raw_parts_mut(mem as *mut u8, 10 * ONE_K)
+ std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K)
};
// The first KB should still have the old data in it.
@@ -80,23 +80,22 @@ fn test_mremap_grow() {
// Segfaults for unknown reasons under QEMU for 32-bit targets
#[cfg_attr(all(target_pointer_width = "32", qemu), ignore)]
fn test_mremap_shrink() {
- use nix::libc::{c_void, size_t};
+ use nix::libc::size_t;
use nix::sys::mman::{mremap, MRemapFlags};
use std::num::NonZeroUsize;
+ use std::ptr::NonNull;
const ONE_K: size_t = 1024;
let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
let slice: &mut [u8] = unsafe {
- let mem = mmap::<BorrowedFd>(
+ let mem = mmap_anonymous(
None,
ten_one_k,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
- None,
- 0,
+ MapFlags::MAP_PRIVATE,
)
.unwrap();
- std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
+ std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
};
assert_eq!(slice[ONE_K - 1], 0x00);
slice[ONE_K - 1] = 0xFF;
@@ -104,7 +103,7 @@ fn test_mremap_shrink() {
let slice: &mut [u8] = unsafe {
let mem = mremap(
- slice.as_mut_ptr() as *mut c_void,
+ NonNull::from(&mut slice[..]).cast(),
ten_one_k.into(),
ONE_K,
MRemapFlags::empty(),
@@ -113,8 +112,8 @@ fn test_mremap_shrink() {
.unwrap();
// Since we didn't supply MREMAP_MAYMOVE, the address should be the
// same.
- assert_eq!(mem, slice.as_mut_ptr() as *mut c_void);
- std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
+ assert_eq!(mem.as_ptr(), NonNull::from(&mut slice[..]).cast().as_ptr());
+ std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
};
// The first KB should still be accessible and have the old data in it.
diff --git a/third_party/rust/nix/test/sys/test_ptrace.rs b/third_party/rust/nix/test/sys/test_ptrace.rs
index 530560fe17..246b35445d 100644
--- a/third_party/rust/nix/test/sys/test_ptrace.rs
+++ b/third_party/rust/nix/test/sys/test_ptrace.rs
@@ -6,11 +6,11 @@
use memoffset::offset_of;
use nix::errno::Errno;
use nix::sys::ptrace;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use nix::sys::ptrace::Options;
use nix::unistd::getpid;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use std::mem;
use crate::*;
@@ -28,7 +28,7 @@ fn test_ptrace() {
// Just make sure ptrace_setoptions can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_setoptions() {
require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE);
let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD)
@@ -38,7 +38,7 @@ fn test_ptrace_setoptions() {
// Just make sure ptrace_getevent can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_getevent() {
require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE);
let err = ptrace::getevent(getpid()).unwrap_err();
@@ -47,7 +47,7 @@ fn test_ptrace_getevent() {
// Just make sure ptrace_getsiginfo can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_getsiginfo() {
require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE);
if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) {
@@ -57,7 +57,7 @@ fn test_ptrace_getsiginfo() {
// Just make sure ptrace_setsiginfo can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_setsiginfo() {
require_capability!("test_ptrace_setsiginfo", CAP_SYS_PTRACE);
let siginfo = unsafe { mem::zeroed() };
diff --git a/third_party/rust/nix/test/sys/test_resource.rs b/third_party/rust/nix/test/sys/test_resource.rs
new file mode 100644
index 0000000000..8b12a9495b
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_resource.rs
@@ -0,0 +1,43 @@
+use nix::sys::resource::{getrlimit, setrlimit, Resource};
+use nix::sys::resource::{getrusage, UsageWho};
+
+/// Tests the RLIMIT_NOFILE functionality of getrlimit(), where the resource RLIMIT_NOFILE refers
+/// to the maximum file descriptor number that can be opened by the process (aka the maximum number
+/// of file descriptors that the process can open, since Linux 4.5).
+///
+/// We first fetch the existing file descriptor maximum values using getrlimit(), then edit the
+/// soft limit to make sure it has a new and distinct value to the hard limit. We then setrlimit()
+/// to put the new soft limit in effect, and then getrlimit() once more to ensure the limits have
+/// been updated.
+#[test]
+pub fn test_resource_limits_nofile() {
+ let (mut soft_limit, hard_limit) =
+ getrlimit(Resource::RLIMIT_NOFILE).unwrap();
+
+ soft_limit -= 1;
+ assert_ne!(soft_limit, hard_limit);
+ setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
+
+ let (new_soft_limit, _) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
+ assert_eq!(new_soft_limit, soft_limit);
+}
+
+#[test]
+pub fn test_self_cpu_time() {
+ // Make sure some CPU time is used.
+ let mut numbers: Vec<i32> = (1..1_000_000).collect();
+ numbers.iter_mut().for_each(|item| *item *= 2);
+
+ // FIXME: this is here to help ensure the compiler does not optimize the whole
+ // thing away. Replace the assert with test::black_box once stabilized.
+ assert_eq!(numbers[100..200].iter().sum::<i32>(), 30_100);
+
+ let usage = getrusage(UsageWho::RUSAGE_SELF)
+ .expect("Failed to call getrusage for SELF");
+ let rusage = usage.as_ref();
+
+ let user = usage.user_time();
+ assert!(user.tv_sec() > 0 || user.tv_usec() > 0);
+ assert_eq!(user.tv_sec(), rusage.ru_utime.tv_sec);
+ assert_eq!(user.tv_usec(), rusage.ru_utime.tv_usec);
+}
diff --git a/third_party/rust/nix/test/sys/test_select.rs b/third_party/rust/nix/test/sys/test_select.rs
index 79f75de3b4..e39a31923a 100644
--- a/third_party/rust/nix/test/sys/test_select.rs
+++ b/third_party/rust/nix/test/sys/test_select.rs
@@ -1,22 +1,20 @@
use nix::sys::select::*;
use nix::sys::signal::SigSet;
-use nix::sys::time::{TimeSpec, TimeValLike};
+use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
use nix::unistd::{pipe, write};
-use std::os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
+use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
#[test]
pub fn test_pselect() {
let _mtx = crate::SIGNAL_MTX.lock();
let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
+ write(&w1, b"hi!").unwrap();
let (r2, _w2) = pipe().unwrap();
- let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
let mut fd_set = FdSet::new();
- fd_set.insert(&r1);
- fd_set.insert(&r2);
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
let timeout = TimeSpec::seconds(10);
let sigmask = SigSet::empty();
@@ -24,21 +22,19 @@ pub fn test_pselect() {
1,
pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
);
- assert!(fd_set.contains(&r1));
- assert!(!fd_set.contains(&r2));
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
}
#[test]
pub fn test_pselect_nfds2() {
let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
+ write(&w1, b"hi!").unwrap();
let (r2, _w2) = pipe().unwrap();
- let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
let mut fd_set = FdSet::new();
- fd_set.insert(&r1);
- fd_set.insert(&r2);
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
let timeout = TimeSpec::seconds(10);
assert_eq!(
@@ -53,8 +49,8 @@ pub fn test_pselect_nfds2() {
)
.unwrap()
);
- assert!(fd_set.contains(&r1));
- assert!(!fd_set.contains(&r2));
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
}
macro_rules! generate_fdset_bad_fd_tests {
@@ -64,7 +60,7 @@ macro_rules! generate_fdset_bad_fd_tests {
#[should_panic]
fn $method() {
let bad_fd = unsafe{BorrowedFd::borrow_raw($fd)};
- FdSet::new().$method(&bad_fd);
+ FdSet::new().$method(bad_fd);
}
)*
}
@@ -72,7 +68,6 @@ macro_rules! generate_fdset_bad_fd_tests {
mod test_fdset_too_large_fd {
use super::*;
- use std::convert::TryInto;
generate_fdset_bad_fd_tests!(
FD_SETSIZE.try_into().unwrap(),
insert,
@@ -80,3 +75,219 @@ mod test_fdset_too_large_fd {
contains,
);
}
+
+#[test]
+fn fdset_insert() {
+ let mut fd_set = FdSet::new();
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+
+ let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
+ fd_set.insert(fd_seven);
+
+ assert!(fd_set.contains(fd_seven));
+}
+
+#[test]
+fn fdset_remove() {
+ let mut fd_set = FdSet::new();
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+
+ let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
+ fd_set.insert(fd_seven);
+ fd_set.remove(fd_seven);
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn fdset_clear() {
+ let mut fd_set = FdSet::new();
+ let fd_one = unsafe { BorrowedFd::borrow_raw(1) };
+ let fd_FD_SETSIZE_divided_by_two =
+ unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) };
+ let fd_FD_SETSIZE_minus_one =
+ unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) };
+ fd_set.insert(fd_one);
+ fd_set.insert(fd_FD_SETSIZE_divided_by_two);
+ fd_set.insert(fd_FD_SETSIZE_minus_one);
+
+ fd_set.clear();
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+}
+
+#[test]
+fn fdset_highest() {
+ let mut set = FdSet::new();
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ None
+ );
+ let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
+ let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
+ set.insert(fd_zero);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(0)
+ );
+ set.insert(fd_ninety);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(90)
+ );
+ set.remove(fd_zero);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(90)
+ );
+ set.remove(fd_ninety);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ None
+ );
+
+ let fd_four = unsafe { BorrowedFd::borrow_raw(4) };
+ let fd_five = unsafe { BorrowedFd::borrow_raw(5) };
+ let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
+ set.insert(fd_four);
+ set.insert(fd_five);
+ set.insert(fd_seven);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(7)
+ );
+}
+
+#[test]
+fn fdset_fds() {
+ let mut set = FdSet::new();
+ let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
+ let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
+ assert_eq!(
+ set.fds(None)
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![]
+ );
+ set.insert(fd_zero);
+ assert_eq!(
+ set.fds(None)
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0]
+ );
+ set.insert(fd_ninety);
+ assert_eq!(
+ set.fds(None)
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0, 90]
+ );
+
+ // highest limit
+ assert_eq!(
+ set.fds(Some(89))
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0]
+ );
+ assert_eq!(
+ set.fds(Some(90))
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0, 90]
+ );
+}
+
+#[test]
+fn test_select() {
+ let (r1, w1) = pipe().unwrap();
+ let (r2, _w2) = pipe().unwrap();
+
+ write(&w1, b"hi!").unwrap();
+ let mut fd_set = FdSet::new();
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
+
+ let mut timeout = TimeVal::seconds(10);
+ assert_eq!(
+ 1,
+ select(None, &mut fd_set, None, None, &mut timeout).unwrap()
+ );
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
+}
+
+#[test]
+fn test_select_nfds() {
+ let (r1, w1) = pipe().unwrap();
+ let (r2, _w2) = pipe().unwrap();
+
+ write(&w1, b"hi!").unwrap();
+ let mut fd_set = FdSet::new();
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
+
+ let mut timeout = TimeVal::seconds(10);
+ {
+ assert_eq!(
+ 1,
+ select(
+ Some(
+ fd_set
+ .highest()
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .unwrap()
+ + 1
+ ),
+ &mut fd_set,
+ None,
+ None,
+ &mut timeout
+ )
+ .unwrap()
+ );
+ }
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
+}
+
+#[test]
+fn test_select_nfds2() {
+ let (r1, w1) = pipe().unwrap();
+ write(&w1, b"hi!").unwrap();
+ let (r2, _w2) = pipe().unwrap();
+ let mut fd_set = FdSet::new();
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
+
+ let mut timeout = TimeVal::seconds(10);
+ assert_eq!(
+ 1,
+ select(
+ std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1,
+ &mut fd_set,
+ None,
+ None,
+ &mut timeout
+ )
+ .unwrap()
+ );
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
+}
diff --git a/third_party/rust/nix/test/sys/test_signal.rs b/third_party/rust/nix/test/sys/test_signal.rs
index ca25ff9ab0..bf607497be 100644
--- a/third_party/rust/nix/test/sys/test_signal.rs
+++ b/third_party/rust/nix/test/sys/test_signal.rs
@@ -1,9 +1,10 @@
-#[cfg(not(target_os = "redox"))]
use nix::errno::Errno;
use nix::sys::signal::*;
use nix::unistd::*;
-use std::convert::TryFrom;
+use std::hash::{Hash, Hasher};
use std::sync::atomic::{AtomicBool, Ordering};
+#[cfg(not(target_os = "redox"))]
+use std::thread;
#[test]
fn test_kill_none() {
@@ -124,7 +125,7 @@ fn test_signal() {
raise(Signal::SIGINT).unwrap();
assert!(SIGNALED.load(Ordering::Relaxed));
- #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
+ #[cfg(not(solarish))]
assert_eq!(
unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(),
handler
@@ -132,7 +133,7 @@ fn test_signal() {
// System V based OSes (e.g. illumos and Solaris) always resets the
// disposition to SIG_DFL prior to calling the signal handler
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ #[cfg(solarish)]
assert_eq!(
unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(),
SigHandler::SigDfl
@@ -141,3 +142,314 @@ fn test_signal() {
// Restore default signal handler
unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
}
+
+#[test]
+fn test_contains() {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ assert!(mask.contains(SIGUSR1));
+ assert!(!mask.contains(SIGUSR2));
+
+ let all = SigSet::all();
+ assert!(all.contains(SIGUSR1));
+ assert!(all.contains(SIGUSR2));
+}
+
+#[test]
+fn test_clear() {
+ let mut set = SigSet::all();
+ set.clear();
+ for signal in Signal::iterator() {
+ assert!(!set.contains(signal));
+ }
+}
+
+#[test]
+fn test_from_str_round_trips() {
+ for signal in Signal::iterator() {
+ assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
+ assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
+ }
+}
+
+#[test]
+fn test_from_str_invalid_value() {
+ let errval = Err(Errno::EINVAL);
+ assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
+ assert_eq!("kill".parse::<Signal>(), errval);
+ assert_eq!("9".parse::<Signal>(), errval);
+}
+
+#[test]
+fn test_extend() {
+ let mut one_signal = SigSet::empty();
+ one_signal.add(SIGUSR1);
+
+ let mut two_signals = SigSet::empty();
+ two_signals.add(SIGUSR2);
+ two_signals.extend(&one_signal);
+
+ assert!(two_signals.contains(SIGUSR1));
+ assert!(two_signals.contains(SIGUSR2));
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_set_mask() {
+ thread::spawn(|| {
+ let prev_mask = SigSet::thread_get_mask()
+ .expect("Failed to get existing signal mask!");
+
+ let mut test_mask = prev_mask;
+ test_mask.add(SIGUSR1);
+
+ test_mask.thread_set_mask().expect("assertion failed");
+ let new_mask =
+ SigSet::thread_get_mask().expect("Failed to get new mask!");
+
+ assert!(new_mask.contains(SIGUSR1));
+ assert!(!new_mask.contains(SIGUSR2));
+
+ prev_mask
+ .thread_set_mask()
+ .expect("Failed to revert signal mask!");
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_block() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ mask.thread_block().expect("assertion failed");
+
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_unblock() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ mask.thread_unblock().expect("assertion failed");
+
+ assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_swap() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+ mask.thread_block().unwrap();
+
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
+
+ let mut mask2 = SigSet::empty();
+ mask2.add(SIGUSR2);
+
+ let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap();
+
+ assert!(oldmask.contains(SIGUSR1));
+ assert!(!oldmask.contains(SIGUSR2));
+
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+fn test_from_and_into_iterator() {
+ let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
+ let signals = sigset.into_iter().collect::<Vec<Signal>>();
+ assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_sigaction() {
+ thread::spawn(|| {
+ extern "C" fn test_sigaction_handler(_: libc::c_int) {}
+ extern "C" fn test_sigaction_action(
+ _: libc::c_int,
+ _: *mut libc::siginfo_t,
+ _: *mut libc::c_void,
+ ) {
+ }
+
+ let handler_sig = SigHandler::Handler(test_sigaction_handler);
+
+ let flags =
+ SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO;
+
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ let action_sig = SigAction::new(handler_sig, flags, mask);
+
+ assert_eq!(
+ action_sig.flags(),
+ SaFlags::SA_ONSTACK | SaFlags::SA_RESTART
+ );
+ assert_eq!(action_sig.handler(), handler_sig);
+
+ mask = action_sig.mask();
+ assert!(mask.contains(SIGUSR1));
+ assert!(!mask.contains(SIGUSR2));
+
+ let handler_act = SigHandler::SigAction(test_sigaction_action);
+ let action_act = SigAction::new(handler_act, flags, mask);
+ assert_eq!(action_act.handler(), handler_act);
+
+ let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
+ assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
+
+ let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
+ assert_eq!(action_ign.handler(), SigHandler::SigIgn);
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_sigwait() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+ mask.add(SIGUSR2);
+ mask.thread_block().unwrap();
+
+ raise(SIGUSR1).unwrap();
+ assert_eq!(mask.wait().unwrap(), SIGUSR1);
+ })
+ .join()
+ .unwrap();
+}
+
+#[cfg(any(
+ bsd,
+ linux_android,
+ solarish,
+ target_os = "haiku",
+ target_os = "hurd",
+ target_os = "aix",
+ target_os = "fushsia"
+))]
+#[test]
+fn test_sigsuspend() {
+ // This test change signal handler
+ let _m = crate::SIGNAL_MTX.lock();
+ static SIGNAL_RECIEVED: AtomicBool = AtomicBool::new(false);
+ extern "C" fn test_sigsuspend_handler(_: libc::c_int) {
+ assert!(!SIGNAL_RECIEVED.swap(true, Ordering::SeqCst));
+ }
+ thread::spawn(|| {
+ const SIGNAL: Signal = Signal::SIGUSR1;
+
+ // Add signal mask to this thread
+ let mut signal_set = SigSet::empty();
+ signal_set.add(SIGNAL);
+ signal_set.thread_block().unwrap();
+
+ // Set signal handler and save old one.
+ let act = SigAction::new(
+ SigHandler::Handler(test_sigsuspend_handler),
+ SaFlags::empty(),
+ SigSet::empty(),
+ );
+ let old_act = unsafe { sigaction(SIGNAL, &act) }
+ .expect("expect to be able to set new action and get old action");
+
+ raise(SIGNAL).expect("expect be able to send signal");
+ // Now `SIGNAL` was sended but it is blocked.
+ let mut not_wait_set = SigSet::all();
+ not_wait_set.remove(SIGNAL);
+ // signal handler must run in SigSet::suspend()
+ assert!(!SIGNAL_RECIEVED.load(Ordering::SeqCst));
+ not_wait_set.suspend().unwrap();
+ assert!(SIGNAL_RECIEVED.load(Ordering::SeqCst));
+
+ // Restore the signal handler.
+ unsafe { sigaction(SIGNAL, &old_act) }
+ .expect("expect to be able to restore old action ");
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+fn test_from_sigset_t_unchecked() {
+ let src_set = SigSet::empty();
+ let set = unsafe { SigSet::from_sigset_t_unchecked(*src_set.as_ref()) };
+
+ for signal in Signal::iterator() {
+ assert!(!set.contains(signal));
+ }
+
+ let src_set = SigSet::all();
+ let set = unsafe { SigSet::from_sigset_t_unchecked(*src_set.as_ref()) };
+
+ for signal in Signal::iterator() {
+ assert!(set.contains(signal));
+ }
+}
+
+#[test]
+fn test_eq_empty() {
+ let set0 = SigSet::empty();
+ let set1 = SigSet::empty();
+ assert_eq!(set0, set1);
+}
+
+#[test]
+fn test_eq_all() {
+ let set0 = SigSet::all();
+ let set1 = SigSet::all();
+ assert_eq!(set0, set1);
+}
+
+#[test]
+fn test_hash_empty() {
+ use std::collections::hash_map::DefaultHasher;
+
+ let set0 = SigSet::empty();
+ let mut h0 = DefaultHasher::new();
+ set0.hash(&mut h0);
+
+ let set1 = SigSet::empty();
+ let mut h1 = DefaultHasher::new();
+ set1.hash(&mut h1);
+
+ assert_eq!(h0.finish(), h1.finish());
+}
+
+#[test]
+fn test_hash_all() {
+ use std::collections::hash_map::DefaultHasher;
+
+ let set0 = SigSet::all();
+ let mut h0 = DefaultHasher::new();
+ set0.hash(&mut h0);
+
+ let set1 = SigSet::all();
+ let mut h1 = DefaultHasher::new();
+ set1.hash(&mut h1);
+
+ assert_eq!(h0.finish(), h1.finish());
+}
diff --git a/third_party/rust/nix/test/sys/test_signalfd.rs b/third_party/rust/nix/test/sys/test_signalfd.rs
index 87153c9572..4e0971aba7 100644
--- a/third_party/rust/nix/test/sys/test_signalfd.rs
+++ b/third_party/rust/nix/test/sys/test_signalfd.rs
@@ -1,6 +1,40 @@
use std::convert::TryFrom;
#[test]
+fn create_signalfd() {
+ use nix::sys::{signal::SigSet, signalfd::SignalFd};
+
+ let mask = SigSet::empty();
+ SignalFd::new(&mask).unwrap();
+}
+
+#[test]
+fn create_signalfd_with_opts() {
+ use nix::sys::{
+ signal::SigSet,
+ signalfd::{SfdFlags, SignalFd},
+ };
+
+ let mask = SigSet::empty();
+ SignalFd::with_flags(&mask, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK)
+ .unwrap();
+}
+
+#[test]
+fn read_empty_signalfd() {
+ use nix::sys::{
+ signal::SigSet,
+ signalfd::{SfdFlags, SignalFd},
+ };
+
+ let mask = SigSet::empty();
+ let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
+
+ let res = fd.read_signal();
+ assert!(res.unwrap().is_none());
+}
+
+#[test]
fn test_signalfd() {
use nix::sys::signal::{self, raise, SigSet, Signal};
use nix::sys::signalfd::SignalFd;
@@ -25,3 +59,32 @@ fn test_signalfd() {
let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
assert_eq!(signo, signal::SIGUSR1);
}
+
+/// Update the signal mask of an already existing signalfd.
+#[test]
+fn test_signalfd_setmask() {
+ use nix::sys::signal::{self, raise, SigSet, Signal};
+ use nix::sys::signalfd::SignalFd;
+
+ // Grab the mutex for altering signals so we don't interfere with other tests.
+ let _m = crate::SIGNAL_MTX.lock();
+
+ // Block the SIGUSR1 signal from automatic processing for this thread
+ let mut mask = SigSet::empty();
+
+ let mut fd = SignalFd::new(&mask).unwrap();
+
+ mask.add(signal::SIGUSR1);
+ mask.thread_block().unwrap();
+ fd.set_mask(&mask).unwrap();
+
+ // Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill`
+ // because `kill` with `getpid` isn't correct during multi-threaded execution like during a
+ // cargo test session. Instead use `raise` which does the correct thing by default.
+ raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed");
+
+ // And now catch that same signal.
+ let res = fd.read_signal().unwrap().unwrap();
+ let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
+ assert_eq!(signo, signal::SIGUSR1);
+}
diff --git a/third_party/rust/nix/test/sys/test_socket.rs b/third_party/rust/nix/test/sys/test_socket.rs
index ed1686e87d..90b8a6f528 100644
--- a/third_party/rust/nix/test/sys/test_socket.rs
+++ b/third_party/rust/nix/test/sys/test_socket.rs
@@ -1,4 +1,4 @@
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
use crate::*;
use libc::c_char;
use nix::sys::socket::{getsockname, AddressFamily, UnixAddr};
@@ -21,7 +21,7 @@ pub fn test_timestamping() {
};
use std::io::{IoSlice, IoSliceMut};
- let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6797").unwrap();
let ssock = socket(
AddressFamily::Inet,
@@ -72,15 +72,134 @@ pub fn test_timestamping() {
assert!(std::time::Duration::from(diff).as_secs() < 60);
}
+#[cfg(target_os = "freebsd")]
+#[test]
+pub fn test_timestamping_realtime() {
+ use nix::sys::socket::{
+ recvmsg, sendmsg, setsockopt, socket, sockopt::ReceiveTimestamp,
+ sockopt::TsClock, ControlMessageOwned, MsgFlags, SockFlag, SockType,
+ SockaddrIn, SocketTimestamp,
+ };
+ use std::io::{IoSlice, IoSliceMut};
+
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6792").unwrap();
+
+ let ssock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .expect("send socket failed");
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ nix::sys::socket::bind(rsock.as_raw_fd(), &sock_addr).unwrap();
+
+ setsockopt(&rsock, ReceiveTimestamp, &true).unwrap();
+ setsockopt(&rsock, TsClock, &SocketTimestamp::SO_TS_REALTIME).unwrap();
+
+ let sbuf = [0u8; 2048];
+ let mut rbuf = [0u8; 2048];
+ let flags = MsgFlags::empty();
+ let iov1 = [IoSlice::new(&sbuf)];
+ let mut iov2 = [IoSliceMut::new(&mut rbuf)];
+
+ let mut cmsg = cmsg_space!(nix::sys::time::TimeVal);
+ sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
+ let recv =
+ recvmsg::<()>(rsock.as_raw_fd(), &mut iov2, Some(&mut cmsg), flags)
+ .unwrap();
+
+ let mut ts = None;
+ for c in recv.cmsgs() {
+ if let ControlMessageOwned::ScmRealtime(timeval) = c {
+ ts = Some(timeval);
+ }
+ }
+ let ts = ts.expect("ScmRealtime is present");
+ let sys_time =
+ ::nix::time::clock_gettime(::nix::time::ClockId::CLOCK_REALTIME)
+ .unwrap();
+ let diff = if ts > sys_time {
+ ts - sys_time
+ } else {
+ sys_time - ts
+ };
+ assert!(std::time::Duration::from(diff).as_secs() < 60);
+}
+
+#[cfg(target_os = "freebsd")]
+#[test]
+pub fn test_timestamping_monotonic() {
+ use nix::sys::socket::{
+ recvmsg, sendmsg, setsockopt, socket, sockopt::ReceiveTimestamp,
+ sockopt::TsClock, ControlMessageOwned, MsgFlags, SockFlag, SockType,
+ SockaddrIn, SocketTimestamp,
+ };
+ use std::io::{IoSlice, IoSliceMut};
+
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6803").unwrap();
+
+ let ssock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .expect("send socket failed");
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ nix::sys::socket::bind(rsock.as_raw_fd(), &sock_addr).unwrap();
+
+ setsockopt(&rsock, ReceiveTimestamp, &true).unwrap();
+ setsockopt(&rsock, TsClock, &SocketTimestamp::SO_TS_MONOTONIC).unwrap();
+
+ let sbuf = [0u8; 2048];
+ let mut rbuf = [0u8; 2048];
+ let flags = MsgFlags::empty();
+ let iov1 = [IoSlice::new(&sbuf)];
+ let mut iov2 = [IoSliceMut::new(&mut rbuf)];
+
+ let mut cmsg = cmsg_space!(nix::sys::time::TimeVal);
+ sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
+ let recv =
+ recvmsg::<()>(rsock.as_raw_fd(), &mut iov2, Some(&mut cmsg), flags)
+ .unwrap();
+
+ let mut ts = None;
+ for c in recv.cmsgs() {
+ if let ControlMessageOwned::ScmMonotonic(timeval) = c {
+ ts = Some(timeval);
+ }
+ }
+ let ts = ts.expect("ScmMonotonic is present");
+ let sys_time =
+ ::nix::time::clock_gettime(::nix::time::ClockId::CLOCK_MONOTONIC)
+ .unwrap();
+ let diff = sys_time - ts; // Monotonic clock sys_time must be greater
+ assert!(std::time::Duration::from(diff).as_secs() < 60);
+}
+
#[test]
pub fn test_path_to_sock_addr() {
let path = "/foo/bar";
let actual = Path::new(path);
let addr = UnixAddr::new(actual).unwrap();
- let expect: &[c_char] = unsafe {
- slice::from_raw_parts(path.as_ptr() as *const c_char, path.len())
- };
+ let expect: &[c_char] =
+ unsafe { slice::from_raw_parts(path.as_ptr().cast(), path.len()) };
assert_eq!(unsafe { &(*addr.as_ptr()).sun_path[..8] }, expect);
assert_eq!(addr.path(), Some(actual));
@@ -105,7 +224,7 @@ pub fn test_addr_equality_path() {
assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_abstract_sun_path_too_long() {
let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough");
@@ -113,7 +232,7 @@ pub fn test_abstract_sun_path_too_long() {
addr.expect_err("assertion failed");
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_addr_equality_abstract() {
let name = String::from("nix\0abstract\0test");
@@ -129,7 +248,7 @@ pub fn test_addr_equality_abstract() {
}
// Test getting/setting abstract addresses (without unix socket creation)
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_abstract_uds_addr() {
let empty = String::new();
@@ -151,7 +270,7 @@ pub fn test_abstract_uds_addr() {
}
// Test getting an unnamed address (without unix socket creation)
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_unnamed_uds_addr() {
use crate::nix::sys::socket::SockaddrLike;
@@ -200,7 +319,7 @@ pub fn test_socketpair() {
SockFlag::empty(),
)
.unwrap();
- write(fd1.as_raw_fd(), b"hello").unwrap();
+ write(&fd1, b"hello").unwrap();
let mut buf = [0; 5];
read(fd2.as_raw_fd(), &mut buf).unwrap();
@@ -315,7 +434,7 @@ mod recvfrom {
#[test]
pub fn udp() {
- let std_sa = SocketAddrV4::from_str("127.0.0.1:6789").unwrap();
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:6795").unwrap();
let sock_addr = SockaddrIn::from(std_sa);
let rsock = socket(
AddressFamily::Inet,
@@ -437,12 +556,7 @@ mod recvfrom {
}
}
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[test]
pub fn udp_sendmmsg() {
use std::io::IoSlice;
@@ -504,12 +618,7 @@ mod recvfrom {
assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap());
}
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[test]
pub fn udp_recvmmsg() {
use nix::sys::socket::{recvmmsg, MsgFlags};
@@ -565,7 +674,7 @@ mod recvfrom {
let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(
rsock.as_raw_fd(),
&mut data,
- msgs.iter(),
+ msgs.iter_mut(),
MsgFlags::empty(),
None,
)
@@ -585,12 +694,7 @@ mod recvfrom {
send_thread.join().unwrap();
}
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[test]
pub fn udp_recvmmsg_dontwait_short_read() {
use nix::sys::socket::{recvmmsg, MsgFlags};
@@ -653,7 +757,7 @@ mod recvfrom {
let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(
rsock.as_raw_fd(),
&mut data,
- msgs.iter(),
+ msgs.iter_mut(),
MsgFlags::MSG_DONTWAIT,
None,
)
@@ -674,10 +778,10 @@ mod recvfrom {
#[test]
pub fn udp_inet6() {
let addr = std::net::Ipv6Addr::from_str("::1").unwrap();
- let rport = 6789;
+ let rport = 6796;
let rstd_sa = SocketAddrV6::new(addr, rport, 0, 0);
let raddr = SockaddrIn6::from(rstd_sa);
- let sport = 6790;
+ let sport = 6798;
let sstd_sa = SocketAddrV6::new(addr, sport, 0, 0);
let saddr = SockaddrIn6::from(sstd_sa);
let rsock = socket(
@@ -757,7 +861,7 @@ pub fn test_scm_rights() {
{
let iov = [IoSlice::new(b"hello")];
- let fds = [r];
+ let fds = [r.as_raw_fd()];
let cmsg = ControlMessage::ScmRights(&fds);
assert_eq!(
sendmsg::<()>(
@@ -770,7 +874,6 @@ pub fn test_scm_rights() {
.unwrap(),
5
);
- close(r).unwrap();
}
{
@@ -803,16 +906,15 @@ pub fn test_scm_rights() {
let received_r = received_r.expect("Did not receive passed fd");
// Ensure that the received file descriptor works
- write(w.as_raw_fd(), b"world").unwrap();
+ write(&w, b"world").unwrap();
let mut buf = [0u8; 5];
read(received_r.as_raw_fd(), &mut buf).unwrap();
assert_eq!(&buf[..], b"world");
close(received_r).unwrap();
- close(w).unwrap();
}
// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_cipher() {
@@ -905,7 +1007,7 @@ pub fn test_af_alg_cipher() {
// Disable the test on emulated platforms due to not enabled support of AF_ALG
// in QEMU from rust cross
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_aead() {
@@ -1039,7 +1141,7 @@ pub fn test_af_alg_aead() {
// This would be a more interesting test if we could assume that the test host
// has more than one IP address (since we could select a different address to
// test from).
-#[cfg(any(target_os = "linux", target_os = "macos", target_os = "netbsd"))]
+#[cfg(any(target_os = "linux", apple_targets, target_os = "netbsd"))]
#[test]
pub fn test_sendmsg_ipv4packetinfo() {
use cfg_if::cfg_if;
@@ -1101,7 +1203,7 @@ pub fn test_sendmsg_ipv4packetinfo() {
// test from).
#[cfg(any(
target_os = "linux",
- target_os = "macos",
+ apple_targets,
target_os = "netbsd",
target_os = "freebsd"
))]
@@ -1158,12 +1260,7 @@ pub fn test_sendmsg_ipv6packetinfo() {
//
// Note that binding to 0.0.0.0 is *required* on FreeBSD; sendmsg
// returns EINVAL otherwise. (See FreeBSD's ip(4) man page.)
-#[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
-))]
+#[cfg(any(freebsdlike, netbsdlike))]
#[test]
pub fn test_sendmsg_ipv4sendsrcaddr() {
use nix::sys::socket::{
@@ -1302,7 +1399,7 @@ pub fn test_sendmsg_empty_cmsgs() {
)
.unwrap();
- for _ in msg.cmsgs() {
+ if msg.cmsgs().next().is_some() {
panic!("unexpected cmsg");
}
assert!(!msg
@@ -1312,19 +1409,14 @@ pub fn test_sendmsg_empty_cmsgs() {
}
}
-#[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "freebsd",
- target_os = "dragonfly",
-))]
+#[cfg(any(linux_android, freebsdlike))]
#[test]
fn test_scm_credentials() {
use nix::sys::socket::{
recvmsg, sendmsg, socketpair, AddressFamily, ControlMessage,
ControlMessageOwned, MsgFlags, SockFlag, SockType, UnixCredentials,
};
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
use nix::sys::socket::{setsockopt, sockopt::PassCred};
use nix::unistd::{getgid, getpid, getuid};
use std::io::{IoSlice, IoSliceMut};
@@ -1336,16 +1428,16 @@ fn test_scm_credentials() {
SockFlag::empty(),
)
.unwrap();
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
setsockopt(&recv, PassCred, &true).unwrap();
{
let iov = [IoSlice::new(b"hello")];
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
let cred = UnixCredentials::new();
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
let cmsg = ControlMessage::ScmCredentials(&cred);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
let cmsg = ControlMessage::ScmCreds;
assert_eq!(
sendmsg::<()>(
@@ -1376,9 +1468,9 @@ fn test_scm_credentials() {
for cmsg in msg.cmsgs() {
let cred = match cmsg {
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessageOwned::ScmCredentials(cred) => cred,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessageOwned::ScmCreds(cred) => cred,
other => panic!("unexpected cmsg {other:?}"),
};
@@ -1398,7 +1490,7 @@ fn test_scm_credentials() {
/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
/// `sendmsg` call.
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
#[cfg_attr(qemu, ignore)]
@@ -1410,7 +1502,7 @@ fn test_scm_credentials_and_rights() {
/// Ensure that passing a an oversized control message buffer to recvmsg
/// still works.
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
#[cfg_attr(qemu, ignore)]
@@ -1420,7 +1512,7 @@ fn test_too_large_cmsgspace() {
test_impl_scm_credentials_and_rights(space);
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
use libc::ucred;
use nix::sys::socket::sockopt::PassCred;
@@ -1451,7 +1543,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
gid: getgid().as_raw(),
}
.into();
- let fds = [r];
+ let fds = [r.as_raw_fd()];
let cmsgs = [
ControlMessage::ScmCredentials(&cred),
ControlMessage::ScmRights(&fds),
@@ -1467,7 +1559,6 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
.unwrap(),
5
);
- close(r).unwrap();
}
{
@@ -1510,18 +1601,19 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
let received_r = received_r.expect("Did not receive passed fd");
// Ensure that the received file descriptor works
- write(w.as_raw_fd(), b"world").unwrap();
+ write(&w, b"world").unwrap();
let mut buf = [0u8; 5];
read(received_r.as_raw_fd(), &mut buf).unwrap();
assert_eq!(&buf[..], b"world");
close(received_r).unwrap();
- close(w).unwrap();
}
// Test creating and using named unix domain sockets
#[test]
pub fn test_named_unixdomain() {
- use nix::sys::socket::{accept, bind, connect, listen, socket, UnixAddr};
+ use nix::sys::socket::{
+ accept, bind, connect, listen, socket, Backlog, UnixAddr,
+ };
use nix::sys::socket::{SockFlag, SockType};
use nix::unistd::{read, write};
use std::thread;
@@ -1537,7 +1629,7 @@ pub fn test_named_unixdomain() {
.expect("socket failed");
let sockaddr = UnixAddr::new(&sockname).unwrap();
bind(s1.as_raw_fd(), &sockaddr).expect("bind failed");
- listen(&s1, 10).expect("listen failed");
+ listen(&s1, Backlog::new(10).unwrap()).expect("listen failed");
let thr = thread::spawn(move || {
let s2 = socket(
@@ -1548,7 +1640,7 @@ pub fn test_named_unixdomain() {
)
.expect("socket failed");
connect(s2.as_raw_fd(), &sockaddr).expect("connect failed");
- write(s2.as_raw_fd(), b"hello").expect("write failed");
+ write(&s2, b"hello").expect("write failed");
});
let s3 = accept(s1.as_raw_fd()).expect("accept failed");
@@ -1560,8 +1652,16 @@ pub fn test_named_unixdomain() {
assert_eq!(&buf[..], b"hello");
}
+#[test]
+pub fn test_listen_wrongbacklog() {
+ use nix::sys::socket::Backlog;
+
+ assert!(Backlog::new(libc::SOMAXCONN + 1).is_err());
+ assert!(Backlog::new(-2).is_err());
+}
+
// Test using unnamed unix domain addresses
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_unnamed_unixdomain() {
use nix::sys::socket::{getsockname, socketpair};
@@ -1581,7 +1681,7 @@ pub fn test_unnamed_unixdomain() {
}
// Test creating and using unnamed unix domain addresses for autobinding sockets
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_unnamed_unixdomain_autobind() {
use nix::sys::socket::{bind, getsockname, socket};
@@ -1609,7 +1709,7 @@ pub fn test_unnamed_unixdomain_autobind() {
}
// Test creating and using named system control sockets
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(apple_targets)]
#[test]
pub fn test_syscontrol() {
use nix::errno::Errno;
@@ -1635,15 +1735,7 @@ pub fn test_syscontrol() {
// connect(fd.as_raw_fd(), &sockaddr).expect("connect failed");
}
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(any(bsd, linux_android))]
fn loopback_address(
family: AddressFamily,
) -> Option<nix::ifaddrs::InterfaceAddress> {
@@ -1670,20 +1762,16 @@ fn loopback_address(
})
}
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
// qemu doesn't seem to be emulating this correctly in these architectures
#[cfg_attr(
all(
qemu,
any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc64",
)
),
@@ -1765,20 +1853,16 @@ pub fn test_recv_ipv4pktinfo() {
}
}
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(bsd)]
// qemu doesn't seem to be emulating this correctly in these architectures
#[cfg_attr(
all(
qemu,
any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc64",
)
),
@@ -1883,7 +1967,7 @@ pub fn test_recvif() {
}
}
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_recvif_ipv4() {
@@ -1969,7 +2053,7 @@ pub fn test_recvif_ipv4() {
}
}
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_recvif_ipv6() {
@@ -2055,22 +2139,16 @@ pub fn test_recvif_ipv6() {
}
}
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", apple_targets, netbsdlike))]
// qemu doesn't seem to be emulating this correctly in these architectures
#[cfg_attr(
all(
qemu,
any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc64",
)
),
@@ -2152,7 +2230,7 @@ pub fn test_recv_ipv6pktinfo() {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_vsock() {
use nix::sys::socket::SockaddrLike;
@@ -2192,7 +2270,7 @@ pub fn test_vsock() {
assert_eq!(addr3.as_ref().svm_port, addr1.port());
}
-#[cfg(target_os = "macos")]
+#[cfg(apple_targets)]
#[test]
pub fn test_vsock() {
use nix::sys::socket::SockaddrLike;
@@ -2329,12 +2407,17 @@ fn test_recvmmsg_timestampns() {
// Receive the message
let mut buffer = vec![0u8; message.len()];
let cmsgspace = nix::cmsg_space!(TimeSpec);
- let iov = vec![[IoSliceMut::new(&mut buffer)]];
+ let mut iov = vec![[IoSliceMut::new(&mut buffer)]];
let mut data = MultiHeaders::preallocate(1, Some(cmsgspace));
- let r: Vec<RecvMsg<()>> =
- recvmmsg(in_socket.as_raw_fd(), &mut data, iov.iter(), flags, None)
- .unwrap()
- .collect();
+ let r: Vec<RecvMsg<()>> = recvmmsg(
+ in_socket.as_raw_fd(),
+ &mut data,
+ iov.iter_mut(),
+ flags,
+ None,
+ )
+ .unwrap()
+ .collect();
let rtime = match r[0].cmsgs().next() {
Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
Some(_) => panic!("Unexpected control message"),
@@ -2353,7 +2436,7 @@ fn test_recvmmsg_timestampns() {
// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
// of QEMU support is suspected.
#[cfg_attr(qemu, ignore)]
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "fuchsia"))]
#[test]
fn test_recvmsg_rxq_ovfl() {
use nix::sys::socket::sockopt::{RcvBuf, RxqOvfl};
@@ -2447,7 +2530,7 @@ fn test_recvmsg_rxq_ovfl() {
assert_eq!(drop_counter, 1);
}
-#[cfg(any(target_os = "linux", target_os = "android",))]
+#[cfg(linux_android)]
mod linux_errqueue {
use super::FromStr;
use nix::sys::socket::*;
@@ -2685,3 +2768,160 @@ pub fn test_txtime() {
recvmsg::<()>(rsock.as_raw_fd(), &mut iov2, None, MsgFlags::empty())
.unwrap();
}
+
+// cfg needed for capability check.
+#[cfg(linux_android)]
+#[test]
+fn test_icmp_protocol() {
+ use nix::sys::socket::{
+ sendto, socket, AddressFamily, MsgFlags, SockFlag, SockProtocol,
+ SockType, SockaddrIn,
+ };
+
+ require_capability!("test_icmp_protocol", CAP_NET_RAW);
+
+ let owned_fd = socket(
+ AddressFamily::Inet,
+ SockType::Raw,
+ SockFlag::empty(),
+ SockProtocol::Icmp,
+ )
+ .unwrap();
+
+ // Send a minimal ICMP packet with no payload.
+ let packet = [
+ 0x08, // Type
+ 0x00, // Code
+ 0x84, 0x85, // Checksum
+ 0x73, 0x8a, // ID
+ 0x00, 0x00, // Sequence Number
+ ];
+
+ let dest_addr = SockaddrIn::new(127, 0, 0, 1, 0);
+ sendto(owned_fd.as_raw_fd(), &packet, &dest_addr, MsgFlags::empty())
+ .unwrap();
+}
+
+// test contains both recvmmsg and timestaping which is linux only
+// there are existing tests for recvmmsg only in tests/
+#[cfg_attr(qemu, ignore)]
+#[cfg(target_os = "linux")]
+#[test]
+fn test_recvmm2() -> nix::Result<()> {
+ use nix::sys::{
+ socket::{
+ bind, recvmmsg, sendmsg, setsockopt, socket, sockopt::Timestamping,
+ AddressFamily, ControlMessageOwned, MsgFlags, MultiHeaders,
+ SockFlag, SockType, SockaddrIn, TimestampingFlag, Timestamps,
+ },
+ time::TimeSpec,
+ };
+ use std::io::{IoSlice, IoSliceMut};
+ use std::os::unix::io::AsRawFd;
+ use std::str::FromStr;
+
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
+
+ let ssock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )?;
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::SOCK_NONBLOCK,
+ None,
+ )?;
+
+ bind(rsock.as_raw_fd(), &sock_addr)?;
+
+ setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?;
+
+ let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
+
+ let mut recv_buf = vec![0; 1024];
+
+ let mut recv_iovs = Vec::new();
+ let mut pkt_iovs = Vec::new();
+
+ for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() {
+ pkt_iovs.push(IoSliceMut::new(chunk));
+ if ix % 2 == 1 {
+ recv_iovs.push(pkt_iovs);
+ pkt_iovs = Vec::new();
+ }
+ }
+ drop(pkt_iovs);
+
+ let flags = MsgFlags::empty();
+ let iov1 = [IoSlice::new(&sbuf)];
+
+ let cmsg = cmsg_space!(Timestamps);
+ sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
+
+ let mut data = MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
+
+ let t = TimeSpec::from_duration(std::time::Duration::from_secs(10));
+
+ let recv = recvmmsg(
+ rsock.as_raw_fd(),
+ &mut data,
+ recv_iovs.iter_mut(),
+ flags,
+ Some(t),
+ )?;
+
+ for rmsg in recv {
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ let mut saw_time = false;
+ let mut recvd = 0;
+ for cmsg in rmsg.cmsgs() {
+ if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
+ let ts = timestamps.system;
+
+ let sys_time = nix::time::clock_gettime(
+ nix::time::ClockId::CLOCK_REALTIME,
+ )?;
+ let diff = if ts > sys_time {
+ ts - sys_time
+ } else {
+ sys_time - ts
+ };
+ assert!(std::time::Duration::from(diff).as_secs() < 60);
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ {
+ saw_time = true;
+ }
+ }
+ }
+
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ assert!(saw_time);
+
+ for iov in rmsg.iovs() {
+ recvd += iov.len();
+ }
+ assert_eq!(recvd, 400);
+ }
+
+ Ok(())
+}
+
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn can_use_cmsg_space() {
+ let _ = cmsg_space!(u8);
+}
+
+#[cfg(not(any(linux_android, target_os = "redox", target_os = "haiku")))]
+#[test]
+fn can_open_routing_socket() {
+ use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType};
+
+ let _ =
+ socket(AddressFamily::Route, SockType::Raw, SockFlag::empty(), None)
+ .expect("Failed to open routing socket");
+}
diff --git a/third_party/rust/nix/test/sys/test_sockopt.rs b/third_party/rust/nix/test/sys/test_sockopt.rs
index 0e34917325..a99d4e39ed 100644
--- a/third_party/rust/nix/test/sys/test_sockopt.rs
+++ b/third_party/rust/nix/test/sys/test_sockopt.rs
@@ -1,14 +1,14 @@
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use crate::*;
use nix::sys::socket::{
getsockopt, setsockopt, socket, sockopt, AddressFamily, SockFlag,
SockProtocol, SockType,
};
use rand::{thread_rng, Rng};
-use std::os::unix::io::AsRawFd;
+use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not.
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd",))]
+#[cfg(freebsdlike)]
#[test]
pub fn test_local_peercred_seqpacket() {
use nix::{
@@ -29,12 +29,7 @@ pub fn test_local_peercred_seqpacket() {
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
-))]
+#[cfg(any(freebsdlike, apple_targets))]
#[test]
pub fn test_local_peercred_stream() {
use nix::{
@@ -55,7 +50,7 @@ pub fn test_local_peercred_stream() {
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
}
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
#[test]
pub fn test_local_peer_pid() {
use nix::sys::socket::socketpair;
@@ -108,15 +103,42 @@ fn test_so_buf() {
assert!(actual >= bufsize);
}
+#[cfg(target_os = "freebsd")]
+#[test]
+fn test_so_listen_q_limit() {
+ use nix::sys::socket::{bind, listen, Backlog, SockaddrIn};
+ use std::net::SocketAddrV4;
+ use std::str::FromStr;
+
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:4004").unwrap();
+ let sock_addr = SockaddrIn::from(std_sa);
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ bind(rsock.as_raw_fd(), &sock_addr).unwrap();
+ let pre_limit = getsockopt(&rsock, sockopt::ListenQLimit).unwrap();
+ assert_eq!(pre_limit, 0);
+ listen(&rsock, Backlog::new(42).unwrap()).unwrap();
+ let post_limit = getsockopt(&rsock, sockopt::ListenQLimit).unwrap();
+ assert_eq!(post_limit, 42);
+}
+
#[test]
fn test_so_tcp_maxseg() {
- use nix::sys::socket::{accept, bind, connect, listen, SockaddrIn};
+ use nix::sys::socket::{
+ accept, bind, connect, getsockname, listen, Backlog, SockaddrIn,
+ };
use nix::unistd::write;
use std::net::SocketAddrV4;
use std::str::FromStr;
- let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap();
- let sock_addr = SockaddrIn::from(std_sa);
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:0").unwrap();
+ let mut sock_addr = SockaddrIn::from(std_sa);
let rsock = socket(
AddressFamily::Inet,
@@ -126,13 +148,14 @@ fn test_so_tcp_maxseg() {
)
.unwrap();
bind(rsock.as_raw_fd(), &sock_addr).unwrap();
- listen(&rsock, 10).unwrap();
+ sock_addr = getsockname(rsock.as_raw_fd()).unwrap();
+ listen(&rsock, Backlog::new(10).unwrap()).unwrap();
let initial = getsockopt(&rsock, sockopt::TcpMaxSeg).unwrap();
// Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some
// platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger
// than 700
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
let segsize: u32 = 873;
assert!(initial < segsize);
setsockopt(&rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
@@ -151,12 +174,13 @@ fn test_so_tcp_maxseg() {
.unwrap();
connect(ssock.as_raw_fd(), &sock_addr).unwrap();
let rsess = accept(rsock.as_raw_fd()).unwrap();
- write(rsess, b"hello").unwrap();
+ let rsess = unsafe { OwnedFd::from_raw_fd(rsess) };
+ write(&rsess, b"hello").unwrap();
let actual = getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap();
// Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max
// TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary.
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
assert!((segsize - 100) <= actual);
assert!(actual <= segsize);
} else {
@@ -181,11 +205,10 @@ fn test_so_type() {
/// getsockopt(_, sockopt::SockType) should gracefully handle unknown socket
/// types. Regression test for https://github.com/nix-rust/nix/issues/1819
-#[cfg(any(target_os = "android", target_os = "linux",))]
+#[cfg(linux_android)]
#[test]
fn test_so_type_unknown() {
use nix::errno::Errno;
- use std::os::unix::io::{FromRawFd, OwnedFd};
require_capability!("test_so_type", CAP_NET_RAW);
let raw_fd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) };
@@ -229,7 +252,7 @@ fn test_tcp_congestion() {
}
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_bindtodevice() {
skip_if_not_root!("test_bindtodevice");
@@ -259,12 +282,7 @@ fn test_so_tcp_keepalive() {
setsockopt(&fd, sockopt::KeepAlive, &true).unwrap();
assert!(getsockopt(&fd, sockopt::KeepAlive).unwrap());
- #[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"
- ))]
+ #[cfg(any(linux_android, freebsdlike))]
{
let x = getsockopt(&fd, sockopt::TcpKeepIdle).unwrap();
setsockopt(&fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
@@ -281,14 +299,14 @@ fn test_so_tcp_keepalive() {
}
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[cfg_attr(qemu, ignore)]
fn test_get_mtu() {
use nix::sys::socket::{bind, connect, SockaddrIn};
use std::net::SocketAddrV4;
use std::str::FromStr;
- let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap();
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:0").unwrap();
let std_sb = SocketAddrV4::from_str("127.0.0.1:4002").unwrap();
let usock = socket(
@@ -308,7 +326,7 @@ fn test_get_mtu() {
}
#[test]
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
fn test_ttl_opts() {
let fd4 = socket(
AddressFamily::Inet,
@@ -331,7 +349,48 @@ fn test_ttl_opts() {
}
#[test]
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
+fn test_multicast_ttl_opts_ipv4() {
+ let fd4 = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd4, sockopt::IpMulticastTtl, &2)
+ .expect("setting ipmulticastttl on an inet socket should succeed");
+}
+
+#[test]
+#[cfg(linux_android)]
+fn test_multicast_ttl_opts_ipv6() {
+ let fd6 = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd6, sockopt::IpMulticastTtl, &2)
+ .expect("setting ipmulticastttl on an inet6 socket should succeed");
+}
+
+#[test]
+fn test_ipv6_multicast_hops() {
+ let fd6 = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd6, sockopt::Ipv6MulticastHops, &7)
+ .expect("setting ipv6multicasthops on an inet6 socket should succeed");
+}
+
+#[test]
+#[cfg(apple_targets)]
fn test_dontfrag_opts() {
let fd4 = socket(
AddressFamily::Inet,
@@ -361,12 +420,7 @@ fn test_dontfrag_opts() {
}
#[test]
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
-))]
+#[cfg(any(linux_android, apple_targets))]
// Disable the test under emulation because it fails in Cirrus-CI. Lack
// of QEMU support is suspected.
#[cfg_attr(qemu, ignore)]
@@ -446,3 +500,331 @@ fn test_ipv6_tclass() {
setsockopt(&fd, sockopt::Ipv6TClass, &class).unwrap();
assert_eq!(getsockopt(&fd, sockopt::Ipv6TClass).unwrap(), class);
}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_receive_timestamp() {
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+ assert!(getsockopt(&fd, sockopt::ReceiveTimestamp).unwrap());
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_realtime_micro() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(
+ &fd,
+ sockopt::TsClock,
+ &SocketTimestamp::SO_TS_REALTIME_MICRO,
+ )
+ .unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_REALTIME_MICRO
+ );
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_bintime() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(&fd, sockopt::TsClock, &SocketTimestamp::SO_TS_BINTIME).unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_BINTIME
+ );
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_realtime() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(&fd, sockopt::TsClock, &SocketTimestamp::SO_TS_REALTIME)
+ .unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_REALTIME
+ );
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_monotonic() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(&fd, sockopt::TsClock, &SocketTimestamp::SO_TS_MONOTONIC)
+ .unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_MONOTONIC
+ );
+}
+
+#[test]
+#[cfg(linux_android)]
+// Disable the test under emulation because it fails with ENOPROTOOPT in CI
+// on cross target. Lack of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
+fn test_ip_bind_address_no_port() {
+ let fd = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ setsockopt(&fd, sockopt::IpBindAddressNoPort, &true).expect(
+ "setting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ );
+ assert!(getsockopt(&fd, sockopt::IpBindAddressNoPort).expect(
+ "getting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ ));
+ setsockopt(&fd, sockopt::IpBindAddressNoPort, &false).expect(
+ "unsetting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ );
+ assert!(!getsockopt(&fd, sockopt::IpBindAddressNoPort).expect(
+ "getting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ ));
+}
+
+#[test]
+#[cfg(linux_android)]
+fn test_tcp_fast_open_connect() {
+ let fd = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ setsockopt(&fd, sockopt::TcpFastOpenConnect, &true).expect(
+ "setting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ );
+ assert!(getsockopt(&fd, sockopt::TcpFastOpenConnect).expect(
+ "getting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ ));
+ setsockopt(&fd, sockopt::TcpFastOpenConnect, &false).expect(
+ "unsetting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ );
+ assert!(!getsockopt(&fd, sockopt::TcpFastOpenConnect).expect(
+ "getting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ ));
+}
+
+#[cfg(linux_android)]
+#[test]
+fn can_get_peercred_on_unix_socket() {
+ use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType};
+
+ let (a, b) = socketpair(
+ AddressFamily::Unix,
+ SockType::Stream,
+ None,
+ SockFlag::empty(),
+ )
+ .unwrap();
+ let a_cred = getsockopt(&a, sockopt::PeerCredentials).unwrap();
+ let b_cred = getsockopt(&b, sockopt::PeerCredentials).unwrap();
+ assert_eq!(a_cred, b_cred);
+ assert_ne!(a_cred.pid(), 0);
+}
+
+#[test]
+fn is_socket_type_unix() {
+ use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType};
+
+ let (a, _b) = socketpair(
+ AddressFamily::Unix,
+ SockType::Stream,
+ None,
+ SockFlag::empty(),
+ )
+ .unwrap();
+ let a_type = getsockopt(&a, sockopt::SockType).unwrap();
+ assert_eq!(a_type, SockType::Stream);
+}
+
+#[test]
+fn is_socket_type_dgram() {
+ use nix::sys::socket::{
+ getsockopt, sockopt, AddressFamily, SockFlag, SockType,
+ };
+
+ let s = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ let s_type = getsockopt(&s, sockopt::SockType).unwrap();
+ assert_eq!(s_type, SockType::Datagram);
+}
+
+#[cfg(any(target_os = "freebsd", target_os = "linux"))]
+#[test]
+fn can_get_listen_on_tcp_socket() {
+ use nix::sys::socket::{
+ getsockopt, listen, socket, sockopt, AddressFamily, Backlog, SockFlag,
+ SockType,
+ };
+
+ let s = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ let s_listening = getsockopt(&s, sockopt::AcceptConn).unwrap();
+ assert!(!s_listening);
+ listen(&s, Backlog::new(10).unwrap()).unwrap();
+ let s_listening2 = getsockopt(&s, sockopt::AcceptConn).unwrap();
+ assert!(s_listening2);
+}
+
+#[cfg(target_os = "linux")]
+// Some architectures running under cross don't support `setsockopt(SOL_TCP, TCP_ULP)`
+// because the cross image is based on Ubuntu 16.04 which predates TCP ULP support
+// (it was added in kernel v4.13 released in 2017). For these architectures,
+// the `setsockopt(SOL_TCP, TCP_ULP, "tls", sizeof("tls"))` call succeeds
+// but the subsequent `setsockopt(SOL_TLS, TLS_TX, ...)` call fails with `ENOPROTOOPT`.
+// It's as if the first `setsockopt` call enabled some other option, not `TCP_ULP`.
+// For example, `strace` says:
+//
+// [pid 813] setsockopt(4, SOL_TCP, 0x1f /* TCP_??? */, [7564404], 4) = 0
+//
+// It's not clear why `setsockopt(SOL_TCP, TCP_ULP)` succeeds if the container image libc doesn't support it,
+// but in any case we can't run the test on such an architecture, so skip it.
+#[cfg_attr(qemu, ignore)]
+#[test]
+fn test_ktls() {
+ use nix::sys::socket::{
+ accept, bind, connect, getsockname, listen, Backlog, SockaddrIn,
+ };
+ use std::net::SocketAddrV4;
+ use std::str::FromStr;
+
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:0").unwrap();
+ let mut sock_addr = SockaddrIn::from(std_sa);
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ bind(rsock.as_raw_fd(), &sock_addr).unwrap();
+ sock_addr = getsockname(rsock.as_raw_fd()).unwrap();
+ listen(&rsock, Backlog::new(10).unwrap()).unwrap();
+
+ let ssock = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ connect(ssock.as_raw_fd(), &sock_addr).unwrap();
+
+ let _rsess = accept(rsock.as_raw_fd()).unwrap();
+
+ match setsockopt(&ssock, sockopt::TcpUlp::default(), b"tls") {
+ Ok(()) => (),
+
+ // TLS ULP is not enabled, so we can't test kTLS.
+ Err(nix::Error::ENOENT) => skip!("TLS ULP is not enabled"),
+
+ Err(err) => panic!("{err:?}"),
+ }
+
+ // In real life we would do a TLS handshake and extract the protocol version and secrets.
+ // For this test we just make some up.
+
+ let tx = sockopt::TlsCryptoInfo::Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128 {
+ info: libc::tls_crypto_info {
+ version: libc::TLS_1_2_VERSION,
+ cipher_type: libc::TLS_CIPHER_AES_GCM_128,
+ },
+ iv: *b"\x04\x05\x06\x07\x08\x09\x0a\x0b",
+ key: *b"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ salt: *b"\x00\x01\x02\x03",
+ rec_seq: *b"\x00\x00\x00\x00\x00\x00\x00\x00",
+ });
+ setsockopt(&ssock, sockopt::TcpTlsTx, &tx)
+ .expect("setting TLS_TX after enabling TLS ULP should succeed");
+
+ let rx = sockopt::TlsCryptoInfo::Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128 {
+ info: libc::tls_crypto_info {
+ version: libc::TLS_1_2_VERSION,
+ cipher_type: libc::TLS_CIPHER_AES_GCM_128,
+ },
+ iv: *b"\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb",
+ key: *b"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
+ salt: *b"\xf0\xf1\xf2\xf3",
+ rec_seq: *b"\x00\x00\x00\x00\x00\x00\x00\x00",
+ });
+ match setsockopt(&ssock, sockopt::TcpTlsRx, &rx) {
+ Ok(()) => (),
+ Err(nix::Error::ENOPROTOOPT) => {
+ // TLS_TX was added in v4.13 and TLS_RX in v4.17, so we appear to be between that range.
+ // It's good enough that TLS_TX worked, so let the test succeed.
+ }
+ Err(err) => panic!("{err:?}"),
+ }
+}
diff --git a/third_party/rust/nix/test/sys/test_statfs.rs b/third_party/rust/nix/test/sys/test_statfs.rs
new file mode 100644
index 0000000000..66b3f2ce96
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_statfs.rs
@@ -0,0 +1,99 @@
+use nix::sys::statfs::*;
+use nix::sys::statvfs::*;
+use std::fs::File;
+use std::path::Path;
+
+fn check_fstatfs(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes()).unwrap();
+ let file = File::open(path).unwrap();
+ let fs = fstatfs(&file).unwrap();
+ assert_fs_equals(fs, vfs);
+}
+
+fn check_statfs(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes()).unwrap();
+ let fs = statfs(path.as_bytes()).unwrap();
+ assert_fs_equals(fs, vfs);
+}
+
+fn check_fstatfs_strict(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes());
+ let file = File::open(path).unwrap();
+ let fs = fstatfs(&file);
+ assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
+}
+
+fn check_statfs_strict(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes());
+ let fs = statfs(path.as_bytes());
+ assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
+}
+
+// The cast is not unnecessary on all platforms.
+#[allow(clippy::unnecessary_cast)]
+fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
+ assert_eq!(fs.files() as u64, vfs.files() as u64);
+ assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
+ assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
+}
+
+#[test]
+fn statfs_call() {
+ check_statfs("/tmp");
+ check_statfs("/dev");
+ check_statfs("/run");
+ check_statfs("/");
+}
+
+#[test]
+fn fstatfs_call() {
+ check_fstatfs("/tmp");
+ check_fstatfs("/dev");
+ check_fstatfs("/run");
+ check_fstatfs("/");
+}
+
+// This test is ignored because files_free/blocks_free can change after statvfs call and before
+// statfs call.
+#[test]
+#[ignore]
+fn statfs_call_strict() {
+ check_statfs_strict("/tmp");
+ check_statfs_strict("/dev");
+ check_statfs_strict("/run");
+ check_statfs_strict("/");
+}
+
+// This test is ignored because files_free/blocks_free can change after statvfs call and before
+// fstatfs call.
+#[test]
+#[ignore]
+fn fstatfs_call_strict() {
+ check_fstatfs_strict("/tmp");
+ check_fstatfs_strict("/dev");
+ check_fstatfs_strict("/run");
+ check_fstatfs_strict("/");
+}
+
+// The cast is not unnecessary on all platforms.
+#[allow(clippy::unnecessary_cast)]
+fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
+ assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
+ assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
+ assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
+ assert_eq!(fs.files() as u64, vfs.files() as u64);
+ assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
+ assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
+}
diff --git a/third_party/rust/nix/test/sys/test_statvfs.rs b/third_party/rust/nix/test/sys/test_statvfs.rs
new file mode 100644
index 0000000000..5c80965253
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_statvfs.rs
@@ -0,0 +1,13 @@
+use nix::sys::statvfs::*;
+use std::fs::File;
+
+#[test]
+fn statvfs_call() {
+ statvfs(&b"/"[..]).unwrap();
+}
+
+#[test]
+fn fstatvfs_call() {
+ let root = File::open("/").unwrap();
+ fstatvfs(&root).unwrap();
+}
diff --git a/third_party/rust/nix/test/sys/test_termios.rs b/third_party/rust/nix/test/sys/test_termios.rs
index 83919378a7..35cc7ab739 100644
--- a/third_party/rust/nix/test/sys/test_termios.rs
+++ b/third_party/rust/nix/test/sys/test_termios.rs
@@ -4,17 +4,26 @@ use tempfile::tempfile;
use nix::errno::Errno;
use nix::fcntl;
use nix::pty::openpty;
-use nix::sys::termios::{self, tcgetattr, LocalFlags, OutputFlags};
+use nix::sys::termios::{self, tcgetattr, BaudRate, LocalFlags, OutputFlags};
use nix::unistd::{read, write};
/// Helper function analogous to `std::io::Write::write_all`, but for `Fd`s
fn write_all<Fd: AsFd>(f: Fd, buf: &[u8]) {
let mut len = 0;
while len < buf.len() {
- len += write(f.as_fd().as_raw_fd(), &buf[len..]).unwrap();
+ len += write(f.as_fd(), &buf[len..]).unwrap();
}
}
+#[test]
+fn test_baudrate_try_from() {
+ assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
+ #[cfg(not(target_os = "haiku"))]
+ BaudRate::try_from(999999999).expect_err("assertion failed");
+ #[cfg(target_os = "haiku")]
+ BaudRate::try_from(99).expect_err("assertion failed");
+}
+
// Test tcgetattr on a terminal
#[test]
fn test_tcgetattr_pty() {
diff --git a/third_party/rust/nix/test/sys/test_time.rs b/third_party/rust/nix/test/sys/test_time.rs
new file mode 100644
index 0000000000..0510225a92
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_time.rs
@@ -0,0 +1,91 @@
+use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
+use std::time::Duration;
+
+#[test]
+pub fn test_timespec() {
+ assert_ne!(TimeSpec::seconds(1), TimeSpec::zero());
+ assert_eq!(
+ TimeSpec::seconds(1) + TimeSpec::seconds(2),
+ TimeSpec::seconds(3)
+ );
+ assert_eq!(
+ TimeSpec::minutes(3) + TimeSpec::seconds(2),
+ TimeSpec::seconds(182)
+ );
+}
+
+#[test]
+pub fn test_timespec_from() {
+ let duration = Duration::new(123, 123_456_789);
+ let timespec = TimeSpec::nanoseconds(123_123_456_789);
+
+ assert_eq!(TimeSpec::from(duration), timespec);
+ assert_eq!(Duration::from(timespec), duration);
+}
+
+#[test]
+pub fn test_timespec_neg() {
+ let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
+ let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123);
+
+ assert_eq!(a, -b);
+}
+
+#[test]
+pub fn test_timespec_ord() {
+ assert_eq!(TimeSpec::seconds(1), TimeSpec::nanoseconds(1_000_000_000));
+ assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001));
+ assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999));
+ assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999));
+ assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001));
+}
+
+#[test]
+pub fn test_timespec_fmt() {
+ assert_eq!(TimeSpec::zero().to_string(), "0 seconds");
+ assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds");
+ assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds");
+ assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds");
+ assert_eq!(TimeSpec::nanoseconds(42).to_string(), "0.000000042 seconds");
+ assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds");
+}
+
+#[test]
+pub fn test_timeval() {
+ assert_ne!(TimeVal::seconds(1), TimeVal::zero());
+ assert_eq!(
+ TimeVal::seconds(1) + TimeVal::seconds(2),
+ TimeVal::seconds(3)
+ );
+ assert_eq!(
+ TimeVal::minutes(3) + TimeVal::seconds(2),
+ TimeVal::seconds(182)
+ );
+}
+
+#[test]
+pub fn test_timeval_ord() {
+ assert_eq!(TimeVal::seconds(1), TimeVal::microseconds(1_000_000));
+ assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001));
+ assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999));
+ assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999));
+ assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001));
+}
+
+#[test]
+pub fn test_timeval_neg() {
+ let a = TimeVal::seconds(1) + TimeVal::microseconds(123);
+ let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123);
+
+ assert_eq!(a, -b);
+}
+
+#[test]
+pub fn test_timeval_fmt() {
+ assert_eq!(TimeVal::zero().to_string(), "0 seconds");
+ assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds");
+ assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds");
+ assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds");
+ assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds");
+ assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds");
+}
diff --git a/third_party/rust/nix/test/test_timer.rs b/third_party/rust/nix/test/sys/test_timer.rs
index ffd146867b..ffd146867b 100644
--- a/third_party/rust/nix/test/test_timer.rs
+++ b/third_party/rust/nix/test/sys/test_timer.rs
diff --git a/third_party/rust/nix/test/sys/test_uio.rs b/third_party/rust/nix/test/sys/test_uio.rs
index fc09465f19..d035a7bb04 100644
--- a/third_party/rust/nix/test/sys/test_uio.rs
+++ b/third_party/rust/nix/test/sys/test_uio.rs
@@ -4,7 +4,7 @@ use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use std::fs::OpenOptions;
use std::io::IoSlice;
-use std::os::unix::io::{FromRawFd, OwnedFd};
+use std::os::unix::io::AsRawFd;
use std::{cmp, iter};
#[cfg(not(target_os = "redox"))]
@@ -44,22 +44,17 @@ fn test_writev() {
// FileDesc will close its filedesc (reader).
let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
- // Temporary workaround to cope with the existing RawFd pipe(2), should be
- // removed when pipe(2) becomes I/O-safe.
- let writer = unsafe { OwnedFd::from_raw_fd(writer) };
-
// Blocking io, should write all data.
let write_res = writev(&writer, &iovecs);
let written = write_res.expect("couldn't write");
// Check whether we written all data
assert_eq!(to_write.len(), written);
- let read_res = read(reader, &mut read_buf[..]);
+ let read_res = read(reader.as_raw_fd(), &mut read_buf[..]);
let read = read_res.expect("couldn't read");
// Check we have read as much as we written
assert_eq!(read, written);
// Check equality of written and read data
assert_eq!(&to_write, &read_buf);
- close(reader).expect("closed reader");
}
#[test]
@@ -92,10 +87,6 @@ fn test_readv() {
// Blocking io, should write all data.
write(writer, &to_write).expect("write failed");
- // Temporary workaround to cope with the existing RawFd pipe(2), should be
- // removed when pipe(2) becomes I/O-safe.
- let reader = unsafe { OwnedFd::from_raw_fd(reader) };
-
let read = readv(&reader, &mut iovecs[..]).expect("read failed");
// Check whether we've read all data
assert_eq!(to_write.len(), read);
@@ -108,7 +99,6 @@ fn test_readv() {
assert_eq!(read_buf.len(), to_write.len());
// Check equality of written and read data
assert_eq!(&read_buf, &to_write);
- close(writer).expect("couldn't close writer");
}
#[test]
@@ -150,7 +140,11 @@ fn test_pread() {
}
#[test]
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+#[cfg(not(any(
+ target_os = "redox",
+ target_os = "haiku",
+ target_os = "solaris"
+)))]
fn test_pwritev() {
use std::io::Read;
@@ -185,7 +179,11 @@ fn test_pwritev() {
}
#[test]
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+#[cfg(not(any(
+ target_os = "redox",
+ target_os = "haiku",
+ target_os = "solaris"
+)))]
fn test_preadv() {
use std::io::Write;
@@ -230,6 +228,7 @@ fn test_process_vm_readv() {
use nix::sys::signal::*;
use nix::sys::wait::*;
use nix::unistd::ForkResult::*;
+ use std::os::unix::io::AsRawFd;
require_capability!("test_process_vm_readv", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock();
@@ -241,10 +240,10 @@ fn test_process_vm_readv() {
let (r, w) = pipe().unwrap();
match unsafe { fork() }.expect("Error: Fork Failed") {
Parent { child } => {
- close(w).unwrap();
+ drop(w);
// wait for child
- read(r, &mut [0u8]).unwrap();
- close(r).unwrap();
+ read(r.as_raw_fd(), &mut [0u8]).unwrap();
+ drop(r);
let ptr = vector.as_ptr() as usize;
let remote_iov = RemoteIoVec { base: ptr, len: 5 };
@@ -263,12 +262,11 @@ fn test_process_vm_readv() {
assert_eq!(20u8, buf.iter().sum());
}
Child => {
- let _ = close(r);
+ drop(r);
for i in &mut vector {
*i += 1;
}
let _ = write(w, b"\0");
- let _ = close(w);
loop {
pause();
}
diff --git a/third_party/rust/nix/test/sys/test_utsname.rs b/third_party/rust/nix/test/sys/test_utsname.rs
new file mode 100644
index 0000000000..8f84ac074f
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_utsname.rs
@@ -0,0 +1,17 @@
+#[cfg(target_os = "linux")]
+#[test]
+pub fn test_uname_linux() {
+ assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "Linux");
+}
+
+#[cfg(apple_targets)]
+#[test]
+pub fn test_uname_darwin() {
+ assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "Darwin");
+}
+
+#[cfg(target_os = "freebsd")]
+#[test]
+pub fn test_uname_freebsd() {
+ assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "FreeBSD");
+}
diff --git a/third_party/rust/nix/test/sys/test_wait.rs b/third_party/rust/nix/test/sys/test_wait.rs
index d472f1ec19..365b0165f8 100644
--- a/third_party/rust/nix/test/sys/test_wait.rs
+++ b/third_party/rust/nix/test/sys/test_wait.rs
@@ -33,7 +33,12 @@ fn test_wait_signal() {
//target_os = "haiku",
all(target_os = "linux", not(target_env = "uclibc")),
))]
-#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+#[cfg(not(any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+)))]
fn test_waitid_signal() {
let _m = crate::FORK_MTX.lock();
@@ -76,7 +81,12 @@ fn test_wait_exit() {
target_os = "haiku",
all(target_os = "linux", not(target_env = "uclibc")),
))]
-#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+#[cfg(not(any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+)))]
fn test_waitid_exit() {
let _m = crate::FORK_MTX.lock();
@@ -140,7 +150,7 @@ fn test_waitid_pid() {
}
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
// FIXME: qemu-user doesn't implement ptrace on most arches
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod ptrace {
diff --git a/third_party/rust/nix/test/test.rs b/third_party/rust/nix/test/test.rs
index 7e73bb3056..c7231426c2 100644
--- a/third_party/rust/nix/test/test.rs
+++ b/third_party/rust/nix/test/test.rs
@@ -7,12 +7,14 @@ mod common;
mod sys;
#[cfg(not(target_os = "redox"))]
mod test_dir;
+mod test_errno;
mod test_fcntl;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_kmod;
+#[cfg(target_os = "linux")]
+mod test_mount;
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
+ freebsdlike,
target_os = "fushsia",
target_os = "linux",
target_os = "netbsd"
@@ -30,36 +32,16 @@ mod test_poll;
target_os = "haiku"
)))]
mod test_pty;
-mod test_resource;
#[cfg(any(
- target_os = "android",
+ linux_android,
target_os = "dragonfly",
all(target_os = "freebsd", fbsd14),
- target_os = "linux"
))]
mod test_sched;
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"
-))]
+#[cfg(any(linux_android, freebsdlike, apple_targets, solarish))]
mod test_sendfile;
mod test_stat;
mod test_time;
-#[cfg(all(
- any(
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd"
- ),
- feature = "time",
- feature = "signal"
-))]
-mod test_timer;
mod test_unistd;
use nix::unistd::{chdir, getcwd, read};
diff --git a/third_party/rust/nix/test/test_dir.rs b/third_party/rust/nix/test/test_dir.rs
index 2af4aa5c0a..24ecd6963e 100644
--- a/third_party/rust/nix/test/test_dir.rs
+++ b/third_party/rust/nix/test/test_dir.rs
@@ -6,10 +6,10 @@ use tempfile::tempdir;
#[cfg(test)]
fn flags() -> OFlag {
- #[cfg(target_os = "illumos")]
+ #[cfg(solarish)]
let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC;
- #[cfg(not(target_os = "illumos"))]
+ #[cfg(not(solarish))]
let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_DIRECTORY;
f
diff --git a/third_party/rust/nix/test/test_errno.rs b/third_party/rust/nix/test/test_errno.rs
new file mode 100644
index 0000000000..750fc924ff
--- /dev/null
+++ b/third_party/rust/nix/test/test_errno.rs
@@ -0,0 +1,16 @@
+use nix::errno::Errno;
+
+#[test]
+fn errno_set_and_read() {
+ Errno::ENFILE.set();
+ assert_eq!(Errno::last(), Errno::ENFILE);
+}
+
+#[test]
+fn errno_set_and_clear() {
+ Errno::ENFILE.set();
+ assert_eq!(Errno::last(), Errno::ENFILE);
+
+ Errno::clear();
+ assert_eq!(Errno::last(), Errno::from_raw(0));
+}
diff --git a/third_party/rust/nix/test/test_fcntl.rs b/third_party/rust/nix/test/test_fcntl.rs
index 5fef04ba9b..6572e8af8d 100644
--- a/third_party/rust/nix/test/test_fcntl.rs
+++ b/third_party/rust/nix/test/test_fcntl.rs
@@ -42,7 +42,7 @@ fn test_openat() {
open(tmp.path().parent().unwrap(), OFlag::empty(), Mode::empty())
.unwrap();
let fd = openat(
- dirfd,
+ Some(dirfd),
tmp.path().file_name().unwrap(),
OFlag::O_RDONLY,
Mode::empty(),
@@ -222,7 +222,7 @@ fn test_readlink() {
assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir);
assert_eq!(
- readlinkat(dirfd, "b").unwrap().to_str().unwrap(),
+ readlinkat(Some(dirfd), "b").unwrap().to_str().unwrap(),
expected_dir
);
}
@@ -234,10 +234,9 @@ fn test_readlink() {
/// The from_offset should be updated by the call to reflect
/// the 3 bytes read (6).
#[cfg(any(
- target_os = "linux",
+ linux_android,
// Not available until FreeBSD 13.0
all(target_os = "freebsd", fbsd14),
- target_os = "android"
))]
#[test]
// QEMU does not support copy_file_range. Skip under qemu
@@ -272,7 +271,7 @@ fn test_copy_file_range() {
assert_eq!(from_offset, 6);
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
mod linux_android {
use libc::loff_t;
use std::io::prelude::*;
@@ -280,7 +279,7 @@ mod linux_android {
use std::os::unix::prelude::*;
use nix::fcntl::*;
- use nix::unistd::{close, pipe, read, write};
+ use nix::unistd::{pipe, read, write};
use tempfile::tempfile;
#[cfg(target_os = "linux")]
@@ -299,7 +298,7 @@ mod linux_android {
let res = splice(
tmp.as_raw_fd(),
Some(&mut offset),
- wr,
+ wr.as_raw_fd(),
None,
2,
SpliceFFlags::empty(),
@@ -309,12 +308,9 @@ mod linux_android {
assert_eq!(2, res);
let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
+ assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"f1", &buf[0..2]);
assert_eq!(7, offset);
-
- close(rd).unwrap();
- close(wr).unwrap();
}
#[test]
@@ -323,24 +319,21 @@ mod linux_android {
let (rd2, wr2) = pipe().unwrap();
write(wr1, b"abc").unwrap();
- let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap();
+ let res =
+ tee(rd1.as_raw_fd(), wr2.as_raw_fd(), 2, SpliceFFlags::empty())
+ .unwrap();
assert_eq!(2, res);
let mut buf = [0u8; 1024];
// Check the tee'd bytes are at rd2.
- assert_eq!(2, read(rd2, &mut buf).unwrap());
+ assert_eq!(2, read(rd2.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"ab", &buf[0..2]);
// Check all the bytes are still at rd1.
- assert_eq!(3, read(rd1, &mut buf).unwrap());
+ assert_eq!(3, read(rd1.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"abc", &buf[0..3]);
-
- close(rd1).unwrap();
- close(wr1).unwrap();
- close(rd2).unwrap();
- close(wr2).unwrap();
}
#[test]
@@ -351,17 +344,15 @@ mod linux_android {
let buf2 = b"defghi";
let iovecs = [IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])];
- let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
+ let res = vmsplice(wr.as_raw_fd(), &iovecs[..], SpliceFFlags::empty())
+ .unwrap();
assert_eq!(6, res);
// Check the bytes can be read at rd.
let mut buf = [0u8; 32];
- assert_eq!(6, read(rd, &mut buf).unwrap());
+ assert_eq!(6, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"abcdef", &buf[0..6]);
-
- close(rd).unwrap();
- close(wr).unwrap();
}
#[cfg(target_os = "linux")]
@@ -481,8 +472,7 @@ mod linux_android {
}
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "wasi",
@@ -494,7 +484,7 @@ mod test_posix_fadvise {
use nix::errno::Errno;
use nix::fcntl::*;
use nix::unistd::pipe;
- use std::os::unix::io::{AsRawFd, RawFd};
+ use std::os::unix::io::AsRawFd;
use tempfile::NamedTempFile;
#[test]
@@ -509,7 +499,7 @@ mod test_posix_fadvise {
fn test_errno() {
let (rd, _wr) = pipe().unwrap();
let res = posix_fadvise(
- rd as RawFd,
+ rd.as_raw_fd(),
0,
100,
PosixFadviseAdvice::POSIX_FADV_WILLNEED,
@@ -519,23 +509,18 @@ mod test_posix_fadvise {
}
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "dragonfly",
+ linux_android,
+ freebsdlike,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "wasi",
- target_os = "freebsd"
))]
mod test_posix_fallocate {
use nix::errno::Errno;
use nix::fcntl::*;
use nix::unistd::pipe;
- use std::{
- io::Read,
- os::unix::io::{AsRawFd, RawFd},
- };
+ use std::{io::Read, os::unix::io::AsRawFd};
use tempfile::NamedTempFile;
#[test]
@@ -565,10 +550,133 @@ mod test_posix_fallocate {
#[test]
fn errno() {
let (rd, _wr) = pipe().unwrap();
- let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
+ let err = posix_fallocate(rd.as_raw_fd(), 0, 100).unwrap_err();
match err {
Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (),
errno => panic!("unexpected errno {errno}",),
}
}
}
+
+#[cfg(any(target_os = "dragonfly", target_os = "netbsd", apple_targets))]
+#[test]
+fn test_f_get_path() {
+ use nix::fcntl::*;
+ use std::{os::unix::io::AsRawFd, path::PathBuf};
+
+ let tmp = NamedTempFile::new().unwrap();
+ let fd = tmp.as_raw_fd();
+ let mut path = PathBuf::new();
+ let res =
+ fcntl(fd, FcntlArg::F_GETPATH(&mut path)).expect("get path failed");
+ assert_ne!(res, -1);
+ assert_eq!(
+ path.as_path().canonicalize().unwrap(),
+ tmp.path().canonicalize().unwrap()
+ );
+}
+
+#[cfg(apple_targets)]
+#[test]
+fn test_f_get_path_nofirmlink() {
+ use nix::fcntl::*;
+ use std::{os::unix::io::AsRawFd, path::PathBuf};
+
+ let tmp = NamedTempFile::new().unwrap();
+ let fd = tmp.as_raw_fd();
+ let mut path = PathBuf::new();
+ let res = fcntl(fd, FcntlArg::F_GETPATH_NOFIRMLINK(&mut path))
+ .expect("get path failed");
+ let mut tmpstr = String::from("/System/Volumes/Data");
+ tmpstr.push_str(
+ &tmp.path()
+ .canonicalize()
+ .unwrap()
+ .into_os_string()
+ .into_string()
+ .unwrap(),
+ );
+ assert_ne!(res, -1);
+ assert_eq!(
+ path.as_path()
+ .canonicalize()
+ .unwrap()
+ .into_os_string()
+ .into_string()
+ .unwrap(),
+ tmpstr
+ );
+}
+
+#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
+#[test]
+fn test_f_kinfo() {
+ use nix::fcntl::*;
+ use std::{os::unix::io::AsRawFd, path::PathBuf};
+
+ let tmp = NamedTempFile::new().unwrap();
+ // With TMPDIR set with UFS, the vnode name is not entered
+ // into the name cache thus path is always empty.
+ // Therefore, we reopen the tempfile a second time for the test
+ // to pass.
+ let tmp2 = File::open(tmp.path()).unwrap();
+ let fd = tmp2.as_raw_fd();
+ let mut path = PathBuf::new();
+ let res = fcntl(fd, FcntlArg::F_KINFO(&mut path)).expect("get path failed");
+ assert_ne!(res, -1);
+ assert_eq!(path, tmp.path());
+}
+
+/// Test `Flock` and associated functions.
+///
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+mod test_flock {
+ use nix::fcntl::*;
+ use tempfile::NamedTempFile;
+
+ /// Verify that `Flock::lock()` correctly obtains a lock, and subsequently unlocks upon drop.
+ #[test]
+ fn verify_lock_and_drop() {
+ // Get 2 `File` handles to same underlying file.
+ let file1 = NamedTempFile::new().unwrap();
+ let file2 = file1.reopen().unwrap();
+ let file1 = file1.into_file();
+
+ // Lock first handle
+ let lock1 = Flock::lock(file1, FlockArg::LockExclusive).unwrap();
+
+ // Attempt to lock second handle
+ let file2 = match Flock::lock(file2, FlockArg::LockExclusiveNonblock) {
+ Ok(_) => panic!("Expected second exclusive lock to fail."),
+ Err((f, _)) => f,
+ };
+
+ // Drop first lock
+ std::mem::drop(lock1);
+
+ // Attempt to lock second handle again (but successfully)
+ if Flock::lock(file2, FlockArg::LockExclusiveNonblock).is_err() {
+ panic!("Expected locking to be successful.");
+ }
+ }
+
+ /// Verify that `Flock::unlock()` correctly obtains unlocks.
+ #[test]
+ fn verify_unlock() {
+ // Get 2 `File` handles to same underlying file.
+ let file1 = NamedTempFile::new().unwrap();
+ let file2 = file1.reopen().unwrap();
+ let file1 = file1.into_file();
+
+ // Lock first handle
+ let lock1 = Flock::lock(file1, FlockArg::LockExclusive).unwrap();
+
+ // Unlock and retain file so any erroneous flocks also remain present.
+ let _file1 = lock1.unlock().unwrap();
+
+ // Attempt to lock second handle.
+ if Flock::lock(file2, FlockArg::LockExclusiveNonblock).is_err() {
+ panic!("Expected locking to be successful.");
+ }
+ }
+}
diff --git a/third_party/rust/nix/test/test_mount.rs b/third_party/rust/nix/test/test_mount.rs
index 5cf00408e8..a4f0903dba 100644
--- a/third_party/rust/nix/test/test_mount.rs
+++ b/third_party/rust/nix/test/test_mount.rs
@@ -1,267 +1,183 @@
-mod common;
-
-// Implementation note: to allow unprivileged users to run it, this test makes
-// use of user and mount namespaces. On systems that allow unprivileged user
-// namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run
-// without root.
-
-#[cfg(target_os = "linux")]
-mod test_mount {
- use std::fs::{self, File};
- use std::io::{self, Read, Write};
- use std::os::unix::fs::OpenOptionsExt;
- use std::os::unix::fs::PermissionsExt;
- use std::process::{self, Command};
-
- use libc::{EACCES, EROFS};
-
- use nix::errno::Errno;
- use nix::mount::{mount, umount, MsFlags};
- use nix::sched::{unshare, CloneFlags};
- use nix::sys::stat::{self, Mode};
- use nix::unistd::getuid;
-
- static SCRIPT_CONTENTS: &[u8] = b"#!/bin/sh
+use std::fs::{self, File};
+use std::io::{Read, Write};
+use std::os::unix::fs::OpenOptionsExt;
+use std::os::unix::fs::PermissionsExt;
+use std::process::Command;
+
+use libc::{EACCES, EROFS};
+
+use nix::mount::{mount, umount, MsFlags};
+use nix::sys::stat::{self, Mode};
+
+use crate::*;
+
+static SCRIPT_CONTENTS: &[u8] = b"#!/bin/sh
exit 23";
- const EXPECTED_STATUS: i32 = 23;
+const EXPECTED_STATUS: i32 = 23;
- const NONE: Option<&'static [u8]> = None;
- #[allow(clippy::bind_instead_of_map)] // False positive
- pub fn test_mount_tmpfs_without_flags_allows_rwx() {
- let tempdir = tempfile::tempdir().unwrap();
+const NONE: Option<&'static [u8]> = None;
- mount(
- NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::empty(),
- NONE,
- )
- .unwrap_or_else(|e| panic!("mount failed: {e}"));
+#[test]
+fn test_mount_tmpfs_without_flags_allows_rwx() {
+ require_capability!(
+ "test_mount_tmpfs_without_flags_allows_rwx",
+ CAP_SYS_ADMIN
+ );
+ let tempdir = tempfile::tempdir().unwrap();
+
+ mount(
+ NONE,
+ tempdir.path(),
+ Some(b"tmpfs".as_ref()),
+ MsFlags::empty(),
+ NONE,
+ )
+ .unwrap_or_else(|e| panic!("mount failed: {e}"));
+
+ let test_path = tempdir.path().join("test");
+
+ // Verify write.
+ fs::OpenOptions::new()
+ .create(true)
+ .write(true)
+ .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
+ .open(&test_path)
+ .and_then(|mut f| f.write(SCRIPT_CONTENTS))
+ .unwrap_or_else(|e| panic!("write failed: {e}"));
+
+ // Verify read.
+ let mut buf = Vec::new();
+ File::open(&test_path)
+ .and_then(|mut f| f.read_to_end(&mut buf))
+ .unwrap_or_else(|e| panic!("read failed: {e}"));
+ assert_eq!(buf, SCRIPT_CONTENTS);
+
+ // Verify execute.
+ assert_eq!(
+ EXPECTED_STATUS,
+ Command::new(&test_path)
+ .status()
+ .unwrap_or_else(|e| panic!("exec failed: {e}"))
+ .code()
+ .unwrap_or_else(|| panic!("child killed by signal"))
+ );
- let test_path = tempdir.path().join("test");
+ umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
+}
- // Verify write.
- fs::OpenOptions::new()
- .create(true)
- .write(true)
- .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
- .open(&test_path)
- .or_else(|e| {
- if Errno::from_i32(e.raw_os_error().unwrap())
- == Errno::EOVERFLOW
- {
- // Skip tests on certain Linux kernels which have a bug
- // regarding tmpfs in namespaces.
- // Ubuntu 14.04 and 16.04 are known to be affected; 16.10 is
- // not. There is no legitimate reason for open(2) to return
- // EOVERFLOW here.
- // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1659087
- let stderr = io::stderr();
- let mut handle = stderr.lock();
- writeln!(
- handle,
- "Buggy Linux kernel detected. Skipping test."
- )
- .unwrap();
- process::exit(0);
- } else {
- panic!("open failed: {e}");
- }
- })
- .and_then(|mut f| f.write(SCRIPT_CONTENTS))
- .unwrap_or_else(|e| panic!("write failed: {e}"));
+#[test]
+fn test_mount_rdonly_disallows_write() {
+ require_capability!("test_mount_rdonly_disallows_write", CAP_SYS_ADMIN);
+ let tempdir = tempfile::tempdir().unwrap();
+
+ mount(
+ NONE,
+ tempdir.path(),
+ Some(b"tmpfs".as_ref()),
+ MsFlags::MS_RDONLY,
+ NONE,
+ )
+ .unwrap_or_else(|e| panic!("mount failed: {e}"));
+
+ // EROFS: Read-only file system
+ assert_eq!(
+ EROFS,
+ File::create(tempdir.path().join("test"))
+ .unwrap_err()
+ .raw_os_error()
+ .unwrap()
+ );
- // Verify read.
- let mut buf = Vec::new();
- File::open(&test_path)
- .and_then(|mut f| f.read_to_end(&mut buf))
- .unwrap_or_else(|e| panic!("read failed: {e}"));
- assert_eq!(buf, SCRIPT_CONTENTS);
-
- // Verify execute.
- assert_eq!(
- EXPECTED_STATUS,
- Command::new(&test_path)
- .status()
- .unwrap_or_else(|e| panic!("exec failed: {e}"))
- .code()
- .unwrap_or_else(|| panic!("child killed by signal"))
- );
-
- umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
- }
+ umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
+}
- pub fn test_mount_rdonly_disallows_write() {
- let tempdir = tempfile::tempdir().unwrap();
+#[test]
+fn test_mount_noexec_disallows_exec() {
+ require_capability!("test_mount_noexec_disallows_exec", CAP_SYS_ADMIN);
+ let tempdir = tempfile::tempdir().unwrap();
+
+ mount(
+ NONE,
+ tempdir.path(),
+ Some(b"tmpfs".as_ref()),
+ MsFlags::MS_NOEXEC,
+ NONE,
+ )
+ .unwrap_or_else(|e| panic!("mount failed: {e}"));
+
+ let test_path = tempdir.path().join("test");
+
+ fs::OpenOptions::new()
+ .create(true)
+ .write(true)
+ .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
+ .open(&test_path)
+ .and_then(|mut f| f.write(SCRIPT_CONTENTS))
+ .unwrap_or_else(|e| panic!("write failed: {e}"));
+
+ // Verify that we cannot execute despite a+x permissions being set.
+ let mode = stat::Mode::from_bits_truncate(
+ fs::metadata(&test_path)
+ .map(|md| md.permissions().mode())
+ .unwrap_or_else(|e| panic!("metadata failed: {e}")),
+ );
- mount(
- NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::MS_RDONLY,
- NONE,
- )
- .unwrap_or_else(|e| panic!("mount failed: {e}"));
+ assert!(
+ mode.contains(Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IXOTH),
+ "{:?} did not have execute permissions",
+ &test_path
+ );
+
+ // EACCES: Permission denied
+ assert_eq!(
+ EACCES,
+ Command::new(&test_path)
+ .status()
+ .unwrap_err()
+ .raw_os_error()
+ .unwrap()
+ );
- // EROFS: Read-only file system
- assert_eq!(
- EROFS,
- File::create(tempdir.path().join("test"))
- .unwrap_err()
- .raw_os_error()
- .unwrap()
- );
+ umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
+}
- umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
- }
+#[test]
+fn test_mount_bind() {
+ require_capability!("test_mount_bind", CAP_SYS_ADMIN);
+ let tempdir = tempfile::tempdir().unwrap();
+ let file_name = "test";
- pub fn test_mount_noexec_disallows_exec() {
- let tempdir = tempfile::tempdir().unwrap();
+ {
+ let mount_point = tempfile::tempdir().unwrap();
mount(
+ Some(tempdir.path()),
+ mount_point.path(),
NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::MS_NOEXEC,
+ MsFlags::MS_BIND,
NONE,
)
.unwrap_or_else(|e| panic!("mount failed: {e}"));
- let test_path = tempdir.path().join("test");
-
fs::OpenOptions::new()
.create(true)
.write(true)
.mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
- .open(&test_path)
+ .open(mount_point.path().join(file_name))
.and_then(|mut f| f.write(SCRIPT_CONTENTS))
.unwrap_or_else(|e| panic!("write failed: {e}"));
- // Verify that we cannot execute despite a+x permissions being set.
- let mode = stat::Mode::from_bits_truncate(
- fs::metadata(&test_path)
- .map(|md| md.permissions().mode())
- .unwrap_or_else(|e| panic!("metadata failed: {e}")),
- );
-
- assert!(
- mode.contains(Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IXOTH),
- "{:?} did not have execute permissions",
- &test_path
- );
-
- // EACCES: Permission denied
- assert_eq!(
- EACCES,
- Command::new(&test_path)
- .status()
- .unwrap_err()
- .raw_os_error()
- .unwrap()
- );
-
- umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
+ umount(mount_point.path())
+ .unwrap_or_else(|e| panic!("umount failed: {e}"));
}
- pub fn test_mount_bind() {
- let tempdir = tempfile::tempdir().unwrap();
- let file_name = "test";
-
- {
- let mount_point = tempfile::tempdir().unwrap();
-
- mount(
- Some(tempdir.path()),
- mount_point.path(),
- NONE,
- MsFlags::MS_BIND,
- NONE,
- )
- .unwrap_or_else(|e| panic!("mount failed: {e}"));
-
- fs::OpenOptions::new()
- .create(true)
- .write(true)
- .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
- .open(mount_point.path().join(file_name))
- .and_then(|mut f| f.write(SCRIPT_CONTENTS))
- .unwrap_or_else(|e| panic!("write failed: {e}"));
-
- umount(mount_point.path())
- .unwrap_or_else(|e| panic!("umount failed: {e}"));
- }
-
- // Verify the file written in the mount shows up in source directory, even
- // after unmounting.
-
- let mut buf = Vec::new();
- File::open(tempdir.path().join(file_name))
- .and_then(|mut f| f.read_to_end(&mut buf))
- .unwrap_or_else(|e| panic!("read failed: {e}"));
- assert_eq!(buf, SCRIPT_CONTENTS);
- }
+ // Verify the file written in the mount shows up in source directory, even
+ // after unmounting.
- pub fn setup_namespaces() {
- // Hold on to the uid in the parent namespace.
- let uid = getuid();
-
- unshare(CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_NEWUSER).unwrap_or_else(|e| {
- let stderr = io::stderr();
- let mut handle = stderr.lock();
- writeln!(handle,
- "unshare failed: {e}. Are unprivileged user namespaces available?").unwrap();
- writeln!(handle, "mount is not being tested").unwrap();
- // Exit with success because not all systems support unprivileged user namespaces, and
- // that's not what we're testing for.
- process::exit(0);
- });
-
- // Map user as uid 1000.
- fs::OpenOptions::new()
- .write(true)
- .open("/proc/self/uid_map")
- .and_then(|mut f| f.write(format!("1000 {uid} 1\n").as_bytes()))
- .unwrap_or_else(|e| panic!("could not write uid map: {e}"));
- }
+ let mut buf = Vec::new();
+ File::open(tempdir.path().join(file_name))
+ .and_then(|mut f| f.read_to_end(&mut buf))
+ .unwrap_or_else(|e| panic!("read failed: {e}"));
+ assert_eq!(buf, SCRIPT_CONTENTS);
}
-
-// Test runner
-
-/// Mimic normal test output (hackishly).
-#[cfg(target_os = "linux")]
-macro_rules! run_tests {
- ( $($test_fn:ident),* ) => {{
- println!();
-
- $(
- print!("test test_mount::{} ... ", stringify!($test_fn));
- $test_fn();
- println!("ok");
- )*
-
- println!();
- }}
-}
-
-#[cfg(target_os = "linux")]
-fn main() {
- use test_mount::{
- setup_namespaces, test_mount_bind, test_mount_noexec_disallows_exec,
- test_mount_rdonly_disallows_write,
- test_mount_tmpfs_without_flags_allows_rwx,
- };
- skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1351");
- setup_namespaces();
-
- run_tests!(
- test_mount_tmpfs_without_flags_allows_rwx,
- test_mount_rdonly_disallows_write,
- test_mount_noexec_disallows_exec,
- test_mount_bind
- );
-}
-
-#[cfg(not(target_os = "linux"))]
-fn main() {}
diff --git a/third_party/rust/nix/test/test_mq.rs b/third_party/rust/nix/test/test_mq.rs
index 1fd8929c17..874a72b44d 100644
--- a/third_party/rust/nix/test/test_mq.rs
+++ b/third_party/rust/nix/test/test_mq.rs
@@ -112,7 +112,15 @@ fn test_mq_getattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg_attr(
- all(qemu, any(target_arch = "mips", target_arch = "mips64")),
+ all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+ )
+ ),
ignore
)]
fn test_mq_setattr() {
@@ -162,7 +170,15 @@ fn test_mq_setattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg_attr(
- all(qemu, any(target_arch = "mips", target_arch = "mips64")),
+ all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+ )
+ ),
ignore
)]
fn test_mq_set_nonblocking() {
diff --git a/third_party/rust/nix/test/test_net.rs b/third_party/rust/nix/test/test_net.rs
index c44655a4c9..faba8503fe 100644
--- a/third_party/rust/nix/test/test_net.rs
+++ b/third_party/rust/nix/test/test_net.rs
@@ -1,13 +1,9 @@
use nix::net::if_::*;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
const LOOPBACK: &[u8] = b"lo";
-#[cfg(not(any(
- target_os = "android",
- target_os = "linux",
- target_os = "haiku"
-)))]
+#[cfg(not(any(linux_android, target_os = "haiku")))]
const LOOPBACK: &[u8] = b"lo0";
#[cfg(target_os = "haiku")]
diff --git a/third_party/rust/nix/test/test_poll.rs b/third_party/rust/nix/test/test_poll.rs
index 045ccd3df1..fcb325494e 100644
--- a/third_party/rust/nix/test/test_poll.rs
+++ b/third_party/rust/nix/test/test_poll.rs
@@ -1,9 +1,9 @@
use nix::{
errno::Errno,
- poll::{poll, PollFd, PollFlags},
- unistd::{close, pipe, write},
+ poll::{poll, PollFd, PollFlags, PollTimeout},
+ unistd::{pipe, write},
};
-use std::os::unix::io::{BorrowedFd, FromRawFd, OwnedFd};
+use std::os::unix::io::{AsFd, BorrowedFd};
macro_rules! loop_while_eintr {
($poll_expr: expr) => {
@@ -20,32 +20,25 @@ macro_rules! loop_while_eintr {
#[test]
fn test_poll() {
let (r, w) = pipe().unwrap();
- let r = unsafe { OwnedFd::from_raw_fd(r) };
- let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
+ let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)];
// Poll an idle pipe. Should timeout
- let nfds = loop_while_eintr!(poll(&mut fds, 100));
+ let nfds = loop_while_eintr!(poll(&mut fds, PollTimeout::from(100u8)));
assert_eq!(nfds, 0);
assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- write(w, b".").unwrap();
+ write(&w, b".").unwrap();
// Poll a readable pipe. Should return an event.
- let nfds = poll(&mut fds, 100).unwrap();
+ let nfds = poll(&mut fds, PollTimeout::from(100u8)).unwrap();
assert_eq!(nfds, 1);
assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- close(w).unwrap();
}
// ppoll(2) is the same as poll except for how it handles timeouts and signals.
// Repeating the test for poll(2) should be sufficient to check that our
// bindings are correct.
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"
-))]
+#[cfg(any(linux_android, freebsdlike))]
#[test]
fn test_ppoll() {
use nix::poll::ppoll;
@@ -54,8 +47,7 @@ fn test_ppoll() {
let timeout = TimeSpec::milliseconds(1);
let (r, w) = pipe().unwrap();
- let r = unsafe { OwnedFd::from_raw_fd(r) };
- let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
+ let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)];
// Poll an idle pipe. Should timeout
let sigset = SigSet::empty();
@@ -63,19 +55,18 @@ fn test_ppoll() {
assert_eq!(nfds, 0);
assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- write(w, b".").unwrap();
+ write(&w, b".").unwrap();
// Poll a readable pipe. Should return an event.
let nfds = ppoll(&mut fds, Some(timeout), None).unwrap();
assert_eq!(nfds, 1);
assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- close(w).unwrap();
}
#[test]
fn test_pollfd_events() {
let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
- let mut pfd = PollFd::new(&fd_zero, PollFlags::POLLIN);
+ let mut pfd = PollFd::new(fd_zero.as_fd(), PollFlags::POLLIN);
assert_eq!(pfd.events(), PollFlags::POLLIN);
pfd.set_events(PollFlags::POLLOUT);
assert_eq!(pfd.events(), PollFlags::POLLOUT);
diff --git a/third_party/rust/nix/test/test_pty.rs b/third_party/rust/nix/test/test_pty.rs
index 4cc6620c3c..368ec129b0 100644
--- a/third_party/rust/nix/test/test_pty.rs
+++ b/third_party/rust/nix/test/test_pty.rs
@@ -1,9 +1,9 @@
use std::fs::File;
-use std::io::{Read, Write};
+use std::io::{stdout, Read, Write};
use std::os::unix::prelude::*;
use std::path::Path;
-use libc::{_exit, STDOUT_FILENO};
+use libc::_exit;
use nix::fcntl::{open, OFlag};
use nix::pty::*;
use nix::sys::stat;
@@ -12,7 +12,7 @@ use nix::unistd::{pause, write};
/// Test equivalence of `ptsname` and `ptsname_r`
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptsname_equivalence() {
let _m = crate::PTSNAME_MTX.lock();
@@ -29,7 +29,7 @@ fn test_ptsname_equivalence() {
/// Test data copying of `ptsname`
// TODO need to run in a subprocess, since ptsname is non-reentrant
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptsname_copy() {
let _m = crate::PTSNAME_MTX.lock();
@@ -47,7 +47,7 @@ fn test_ptsname_copy() {
/// Test data copying of `ptsname_r`
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptsname_r_copy() {
// Open a new PTTY master
let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
@@ -61,7 +61,7 @@ fn test_ptsname_r_copy() {
/// Test that `ptsname` returns different names for different devices
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptsname_unique() {
let _m = crate::PTSNAME_MTX.lock();
@@ -96,7 +96,7 @@ fn open_ptty_pair() -> (PtyMaster, File) {
open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty())
.unwrap();
- #[cfg(target_os = "illumos")]
+ #[cfg(solarish)]
// TODO: rewrite using ioctl!
#[allow(clippy::comparison_chain)]
{
@@ -185,7 +185,7 @@ fn test_openpty() {
// Writing to one should be readable on the other one
let string = "foofoofoo\n";
let mut buf = [0u8; 10];
- write(pty.master.as_raw_fd(), string.as_bytes()).unwrap();
+ write(&pty.master, string.as_bytes()).unwrap();
crate::read_exact(&pty.slave, &mut buf);
assert_eq!(&buf, string.as_bytes());
@@ -199,7 +199,7 @@ fn test_openpty() {
let string2 = "barbarbarbar\n";
let echoed_string2 = "barbarbarbar\r\n";
let mut buf = [0u8; 14];
- write(pty.slave.as_raw_fd(), string2.as_bytes()).unwrap();
+ write(&pty.slave, string2.as_bytes()).unwrap();
crate::read_exact(&pty.master, &mut buf);
assert_eq!(&buf, echoed_string2.as_bytes());
@@ -224,7 +224,7 @@ fn test_openpty_with_termios() {
// Writing to one should be readable on the other one
let string = "foofoofoo\n";
let mut buf = [0u8; 10];
- write(pty.master.as_raw_fd(), string.as_bytes()).unwrap();
+ write(&pty.master, string.as_bytes()).unwrap();
crate::read_exact(&pty.slave, &mut buf);
assert_eq!(&buf, string.as_bytes());
@@ -237,7 +237,7 @@ fn test_openpty_with_termios() {
let string2 = "barbarbarbar\n";
let echoed_string2 = "barbarbarbar\n";
let mut buf = [0u8; 13];
- write(pty.slave.as_raw_fd(), string2.as_bytes()).unwrap();
+ write(&pty.slave, string2.as_bytes()).unwrap();
crate::read_exact(&pty.master, &mut buf);
assert_eq!(&buf, echoed_string2.as_bytes());
@@ -258,7 +258,7 @@ fn test_forkpty() {
let pty = unsafe { forkpty(None, None).unwrap() };
match pty.fork_result {
Child => {
- write(STDOUT_FILENO, string.as_bytes()).unwrap();
+ write(stdout(), string.as_bytes()).unwrap();
pause(); // we need the child to stay alive until the parent calls read
unsafe {
_exit(0);
diff --git a/third_party/rust/nix/test/test_resource.rs b/third_party/rust/nix/test/test_resource.rs
deleted file mode 100644
index 2ab581ba29..0000000000
--- a/third_party/rust/nix/test/test_resource.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-#[cfg(not(any(
- target_os = "redox",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "haiku"
-)))]
-use nix::sys::resource::{getrlimit, setrlimit, Resource};
-
-/// Tests the RLIMIT_NOFILE functionality of getrlimit(), where the resource RLIMIT_NOFILE refers
-/// to the maximum file descriptor number that can be opened by the process (aka the maximum number
-/// of file descriptors that the process can open, since Linux 4.5).
-///
-/// We first fetch the existing file descriptor maximum values using getrlimit(), then edit the
-/// soft limit to make sure it has a new and distinct value to the hard limit. We then setrlimit()
-/// to put the new soft limit in effect, and then getrlimit() once more to ensure the limits have
-/// been updated.
-#[test]
-#[cfg(not(any(
- target_os = "redox",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "haiku"
-)))]
-pub fn test_resource_limits_nofile() {
- let (mut soft_limit, hard_limit) =
- getrlimit(Resource::RLIMIT_NOFILE).unwrap();
-
- soft_limit -= 1;
- assert_ne!(soft_limit, hard_limit);
- setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
-
- let (new_soft_limit, _) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
- assert_eq!(new_soft_limit, soft_limit);
-}
diff --git a/third_party/rust/nix/test/test_sendfile.rs b/third_party/rust/nix/test/test_sendfile.rs
index b85e030fd3..6333bf8662 100644
--- a/third_party/rust/nix/test/test_sendfile.rs
+++ b/third_party/rust/nix/test/test_sendfile.rs
@@ -1,21 +1,20 @@
use std::io::prelude::*;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use std::os::unix::io::{FromRawFd, OwnedFd};
use libc::off_t;
use nix::sys::sendfile::*;
use tempfile::tempfile;
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- use nix::unistd::{close, pipe, read};
- } else if #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos"))] {
+ if #[cfg(linux_android)] {
+ use nix::unistd::{pipe, read};
+ use std::os::unix::io::AsRawFd;
+ } else if #[cfg(any(freebsdlike, apple_targets, solarish))] {
use std::net::Shutdown;
use std::os::unix::net::UnixStream;
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
fn test_sendfile_linux() {
const CONTENTS: &[u8] = b"abcdef123456";
@@ -24,21 +23,14 @@ fn test_sendfile_linux() {
let (rd, wr) = pipe().unwrap();
let mut offset: off_t = 5;
- // The construct of this `OwnedFd` is a temporary workaround, when `pipe(2)`
- // becomes I/O-safe:
- // pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error>
- // then it is no longer needed.
- let wr = unsafe { OwnedFd::from_raw_fd(wr) };
let res = sendfile(&wr, &tmp, Some(&mut offset), 2).unwrap();
assert_eq!(2, res);
let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
+ assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"f1", &buf[0..2]);
assert_eq!(7, offset);
-
- close(rd).unwrap();
}
#[cfg(target_os = "linux")]
@@ -50,21 +42,14 @@ fn test_sendfile64_linux() {
let (rd, wr) = pipe().unwrap();
let mut offset: libc::off64_t = 5;
- // The construct of this `OwnedFd` is a temporary workaround, when `pipe(2)`
- // becomes I/O-safe:
- // pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error>
- // then it is no longer needed.
- let wr = unsafe { OwnedFd::from_raw_fd(wr) };
let res = sendfile64(&wr, &tmp, Some(&mut offset), 2).unwrap();
assert_eq!(2, res);
let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
+ assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"f1", &buf[0..2]);
assert_eq!(7, offset);
-
- close(rd).unwrap();
}
#[cfg(target_os = "freebsd")]
@@ -167,7 +152,7 @@ fn test_sendfile_dragonfly() {
assert_eq!(expected_string, read_string);
}
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
#[test]
fn test_sendfile_darwin() {
// Declare the content
@@ -215,3 +200,62 @@ fn test_sendfile_darwin() {
assert_eq!(bytes_written as usize, bytes_read);
assert_eq!(expected_string, read_string);
}
+
+#[cfg(solarish)]
+#[test]
+fn test_sendfilev() {
+ use std::os::fd::AsFd;
+ // Declare the content
+ let header_strings =
+ ["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
+ let body = "Xabcdef123456";
+ let body_offset = 1usize;
+ let trailer_strings = ["\n", "Served by Make Believe\n"];
+
+ // Write data to files
+ let mut header_data = tempfile().unwrap();
+ header_data
+ .write_all(header_strings.concat().as_bytes())
+ .unwrap();
+ let mut body_data = tempfile().unwrap();
+ body_data.write_all(body.as_bytes()).unwrap();
+ let mut trailer_data = tempfile().unwrap();
+ trailer_data
+ .write_all(trailer_strings.concat().as_bytes())
+ .unwrap();
+ let (mut rd, wr) = UnixStream::pair().unwrap();
+ let vec: &[SendfileVec] = &[
+ SendfileVec::new(
+ header_data.as_fd(),
+ 0,
+ header_strings.iter().map(|s| s.len()).sum(),
+ ),
+ SendfileVec::new(
+ body_data.as_fd(),
+ body_offset as off_t,
+ body.len() - body_offset,
+ ),
+ SendfileVec::new(
+ trailer_data.as_fd(),
+ 0,
+ trailer_strings.iter().map(|s| s.len()).sum(),
+ ),
+ ];
+
+ let (res, bytes_written) = sendfilev(&wr, vec);
+ assert!(res.is_ok());
+ wr.shutdown(Shutdown::Both).unwrap();
+
+ // Prepare the expected result
+ let expected_string = header_strings.concat()
+ + &body[body_offset..]
+ + &trailer_strings.concat();
+
+ // Verify the message that was sent
+ assert_eq!(bytes_written, expected_string.as_bytes().len());
+
+ let mut read_string = String::new();
+ let bytes_read = rd.read_to_string(&mut read_string).unwrap();
+ assert_eq!(bytes_written, bytes_read);
+ assert_eq!(expected_string, read_string);
+}
diff --git a/third_party/rust/nix/test/test_stat.rs b/third_party/rust/nix/test/test_stat.rs
index 55f15c0771..386f1084cc 100644
--- a/third_party/rust/nix/test/test_stat.rs
+++ b/third_party/rust/nix/test/test_stat.rs
@@ -21,8 +21,7 @@ use nix::errno::Errno;
use nix::fcntl;
#[cfg(any(
target_os = "linux",
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
@@ -117,7 +116,7 @@ fn test_fstatat() {
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty());
let result =
- stat::fstatat(dirfd.unwrap(), &filename, fcntl::AtFlags::empty());
+ stat::fstatat(Some(dirfd.unwrap()), &filename, fcntl::AtFlags::empty());
assert_stat_results(result);
}
@@ -235,8 +234,7 @@ fn test_utimes() {
#[test]
#[cfg(any(
target_os = "linux",
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
@@ -323,7 +321,7 @@ fn test_mkdirat_success_path() {
let dirfd =
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
.unwrap();
- mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed");
+ mkdirat(Some(dirfd), filename, Mode::S_IRWXU).expect("mkdirat failed");
assert!(Path::exists(&tempdir.path().join(filename)));
}
@@ -337,7 +335,7 @@ fn test_mkdirat_success_mode() {
let dirfd =
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
.unwrap();
- mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed");
+ mkdirat(Some(dirfd), filename, Mode::S_IRWXU).expect("mkdirat failed");
let permissions = fs::metadata(tempdir.path().join(filename))
.unwrap()
.permissions();
@@ -357,16 +355,14 @@ fn test_mkdirat_fail() {
stat::Mode::empty(),
)
.unwrap();
- let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
+ let result = mkdirat(Some(dirfd), filename, Mode::S_IRWXU).unwrap_err();
assert_eq!(result, Errno::ENOTDIR);
}
#[test]
#[cfg(not(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
+ freebsdlike,
+ apple_targets,
target_os = "haiku",
target_os = "redox"
)))]
@@ -384,11 +380,9 @@ fn test_mknod() {
#[test]
#[cfg(not(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
+ solarish,
+ freebsdlike,
+ apple_targets,
target_os = "haiku",
target_os = "redox"
)))]
@@ -402,7 +396,7 @@ fn test_mknodat() {
let target_dir =
Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap();
mknodat(
- target_dir.as_raw_fd(),
+ Some(target_dir.as_raw_fd()),
file_name,
SFlag::S_IFREG,
Mode::S_IRWXU,
@@ -410,7 +404,7 @@ fn test_mknodat() {
)
.unwrap();
let mode = fstatat(
- target_dir.as_raw_fd(),
+ Some(target_dir.as_raw_fd()),
file_name,
AtFlags::AT_SYMLINK_NOFOLLOW,
)
@@ -419,3 +413,75 @@ fn test_mknodat() {
assert_eq!(mode & libc::S_IFREG, libc::S_IFREG);
assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU);
}
+
+#[test]
+#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+fn test_futimens_unchanged() {
+ let tempdir = tempfile::tempdir().unwrap();
+ let fullpath = tempdir.path().join("file");
+ drop(File::create(&fullpath).unwrap());
+ let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty())
+ .unwrap();
+
+ let old_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let old_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+
+ futimens(fd, &TimeSpec::UTIME_OMIT, &TimeSpec::UTIME_OMIT).unwrap();
+
+ let new_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let new_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+ assert_eq!(old_atime, new_atime);
+ assert_eq!(old_mtime, new_mtime);
+}
+
+#[test]
+#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+fn test_utimensat_unchanged() {
+ let _dr = crate::DirRestore::new();
+ let tempdir = tempfile::tempdir().unwrap();
+ let filename = "foo.txt";
+ let fullpath = tempdir.path().join(filename);
+ drop(File::create(&fullpath).unwrap());
+ let dirfd =
+ fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
+ .unwrap();
+
+ let old_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let old_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+ utimensat(
+ Some(dirfd),
+ filename,
+ &TimeSpec::UTIME_OMIT,
+ &TimeSpec::UTIME_OMIT,
+ UtimensatFlags::NoFollowSymlink,
+ )
+ .unwrap();
+ let new_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let new_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+ assert_eq!(old_atime, new_atime);
+ assert_eq!(old_mtime, new_mtime);
+}
diff --git a/third_party/rust/nix/test/test_time.rs b/third_party/rust/nix/test/test_time.rs
index 5f76e61a2d..64c8161dbf 100644
--- a/third_party/rust/nix/test/test_time.rs
+++ b/third_party/rust/nix/test/test_time.rs
@@ -1,10 +1,4 @@
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
use nix::time::clock_getcpuclockid;
use nix::time::{clock_gettime, ClockId};
@@ -19,13 +13,7 @@ pub fn test_clock_gettime() {
clock_gettime(ClockId::CLOCK_REALTIME).expect("assertion failed");
}
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
#[test]
pub fn test_clock_getcpuclockid() {
let clock_id = clock_getcpuclockid(nix::unistd::Pid::this()).unwrap();
@@ -43,13 +31,7 @@ pub fn test_clock_id_now() {
ClockId::CLOCK_REALTIME.now().unwrap();
}
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
#[test]
pub fn test_clock_id_pid_cpu_clock_id() {
ClockId::pid_cpu_clock_id(nix::unistd::Pid::this())
@@ -57,3 +39,28 @@ pub fn test_clock_id_pid_cpu_clock_id() {
.unwrap()
.unwrap();
}
+
+#[cfg(any(
+ linux_android,
+ solarish,
+ freebsdlike,
+ target_os = "netbsd",
+ target_os = "hurd",
+ target_os = "aix"
+))]
+#[test]
+pub fn test_clock_nanosleep() {
+ use nix::{
+ sys::time::{TimeSpec, TimeValLike},
+ time::{clock_nanosleep, ClockNanosleepFlags},
+ };
+
+ let sleep_time = TimeSpec::microseconds(1);
+ let res = clock_nanosleep(
+ ClockId::CLOCK_MONOTONIC,
+ ClockNanosleepFlags::empty(),
+ &sleep_time,
+ );
+ let expected = TimeSpec::microseconds(0);
+ assert_eq!(res, Ok(expected));
+}
diff --git a/third_party/rust/nix/test/test_unistd.rs b/third_party/rust/nix/test/test_unistd.rs
index 10284e4127..aa2e5e56d7 100644
--- a/third_party/rust/nix/test/test_unistd.rs
+++ b/third_party/rust/nix/test/test_unistd.rs
@@ -67,6 +67,37 @@ fn test_fork_and_waitpid() {
}
#[test]
+#[cfg(target_os = "freebsd")]
+fn test_rfork_and_waitpid() {
+ let _m = crate::FORK_MTX.lock();
+
+ // Safe: Child only calls `_exit`, which is signal-safe
+ match unsafe { rfork(RforkFlags::RFPROC | RforkFlags::RFTHREAD) }
+ .expect("Error: Rfork Failed")
+ {
+ Child => unsafe { _exit(0) },
+ Parent { child } => {
+ // assert that child was created and pid > 0
+ let child_raw: ::libc::pid_t = child.into();
+ assert!(child_raw > 0);
+ let wait_status = waitpid(child, None);
+ match wait_status {
+ // assert that waitpid returned correct status and the pid is the one of the child
+ Ok(WaitStatus::Exited(pid_t, _)) => assert_eq!(pid_t, child),
+
+ // panic, must never happen
+ s @ Ok(_) => {
+ panic!("Child exited {s:?}, should never happen")
+ }
+
+ // panic, waitpid should never fail
+ Err(s) => panic!("Error: waitpid returned Err({s:?}"),
+ }
+ }
+ }
+}
+
+#[test]
fn test_wait() {
// Grab FORK_MTX so wait doesn't reap a different test's child process
let _m = crate::FORK_MTX.lock();
@@ -126,8 +157,7 @@ fn test_mkfifo_directory() {
#[test]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -147,8 +177,7 @@ fn test_mkfifoat_none() {
#[test]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -163,15 +192,15 @@ fn test_mkfifoat() {
mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap();
let stats =
- stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap();
+ stat::fstatat(Some(dirfd), mkfifoat_name, fcntl::AtFlags::empty())
+ .unwrap();
let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
assert_eq!(typ, SFlag::S_IFIFO);
}
#[test]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -186,8 +215,7 @@ fn test_mkfifoat_directory_none() {
#[test]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -197,7 +225,7 @@ fn test_mkfifoat_directory() {
let tempdir = tempdir().unwrap();
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
let mkfifoat_dir = "mkfifoat_dir";
- stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap();
+ stat::mkdirat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).unwrap();
mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR)
.expect_err("assertion failed");
@@ -220,7 +248,7 @@ fn test_getsid() {
assert_eq!(none_sid, pid_sid);
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
mod linux_android {
use nix::unistd::gettid;
@@ -234,8 +262,7 @@ mod linux_android {
#[test]
// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "redox",
target_os = "fuchsia",
target_os = "haiku"
@@ -263,12 +290,11 @@ fn test_setgroups() {
#[test]
// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "redox",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos"
+ solarish
)))]
fn test_initgroups() {
// Skip this test when not run as root as `initgroups()` and `setgroups()`
@@ -356,7 +382,7 @@ macro_rules! execve_test_factory (
match unsafe{fork()}.unwrap() {
Child => {
// Make `writer` be the stdout of the new process.
- dup2(writer, 1).unwrap();
+ dup2(writer.as_raw_fd(), 1).unwrap();
let r = syscall();
let _ = std::io::stderr()
.write_all(format!("{:?}", r).as_bytes());
@@ -370,7 +396,7 @@ macro_rules! execve_test_factory (
assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
// Read 1024 bytes.
let mut buf = [0u8; 1024];
- read(reader, &mut buf).unwrap();
+ read(reader.as_raw_fd(), &mut buf).unwrap();
// It should contain the things we printed using `/bin/sh`.
let string = String::from_utf8_lossy(&buf);
assert!(string.contains("nix!!!"));
@@ -404,46 +430,44 @@ cfg_if! {
if #[cfg(target_os = "android")] {
execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str());
execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
- } else if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"))] {
+ } else if #[cfg(any(freebsdlike, target_os = "linux", target_os = "hurd"))] {
// These tests frequently fail on musl, probably due to
// https://github.com/nix-rust/nix/issues/555
execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
- } else if #[cfg(any(target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))] {
+ } else if #[cfg(any(solarish, apple_targets, netbsdlike))] {
execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
// No fexecve() on ios, macos, NetBSD, OpenBSD.
}
}
-#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "haiku",
+ target_os = "hurd",
+ target_os = "linux",
+ target_os = "openbsd"
+))]
execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap());
cfg_if! {
if #[cfg(target_os = "android")] {
use nix::fcntl::AtFlags;
execve_test_factory!(test_execveat_empty, execveat,
- File::open("/system/bin/sh").unwrap().into_raw_fd(),
+ Some(File::open("/system/bin/sh").unwrap().into_raw_fd()),
"", AtFlags::AT_EMPTY_PATH);
execve_test_factory!(test_execveat_relative, execveat,
- File::open("/system/bin/").unwrap().into_raw_fd(),
+ Some(File::open("/system/bin/").unwrap().into_raw_fd()),
"./sh", AtFlags::empty());
execve_test_factory!(test_execveat_absolute, execveat,
- File::open("/").unwrap().into_raw_fd(),
+ Some(File::open("/").unwrap().into_raw_fd()),
"/system/bin/sh", AtFlags::empty());
} else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] {
use nix::fcntl::AtFlags;
- execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(),
+ execve_test_factory!(test_execveat_empty, execveat, Some(File::open("/bin/sh").unwrap().into_raw_fd()),
"", AtFlags::AT_EMPTY_PATH);
- execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap().into_raw_fd(),
+ execve_test_factory!(test_execveat_relative, execveat, Some(File::open("/bin/").unwrap().into_raw_fd()),
"./sh", AtFlags::empty());
- execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
+ execve_test_factory!(test_execveat_absolute, execveat, Some(File::open("/").unwrap().into_raw_fd()),
"/bin/sh", AtFlags::empty());
}
}
@@ -527,6 +551,8 @@ fn test_fchown() {
#[test]
#[cfg(not(target_os = "redox"))]
fn test_fchownat() {
+ use nix::fcntl::AtFlags;
+
let _dr = crate::DirRestore::new();
// Testing for anything other than our own UID/GID is hard.
let uid = Some(getuid());
@@ -540,14 +566,13 @@ fn test_fchownat() {
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
- fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink)
- .unwrap();
+ fchownat(Some(dirfd), "file", uid, gid, AtFlags::empty()).unwrap();
chdir(tempdir.path()).unwrap();
- fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
+ fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap();
fs::remove_file(&path).unwrap();
- fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err();
+ fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap_err();
}
#[test]
@@ -564,7 +589,7 @@ fn test_lseek() {
assert_eq!(b"f123456", &buf);
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[test]
fn test_lseek64() {
const CONTENTS: &[u8] = b"abcdef123456";
@@ -579,7 +604,7 @@ fn test_lseek64() {
}
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
macro_rules! require_acct{
() => {
require_capability!("test_acct", CAP_SYS_PACCT);
@@ -631,11 +656,12 @@ fn test_acct() {
acct::disable().unwrap();
}
+#[cfg_attr(target_os = "hurd", ignore)]
#[test]
fn test_fpathconf_limited() {
let f = tempfile().unwrap();
- // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
- let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX);
+ // PATH_MAX is limited on most platforms, so it makes a good test
+ let path_max = fpathconf(f, PathconfVar::PATH_MAX);
assert!(
path_max
.expect("fpathconf failed")
@@ -644,9 +670,10 @@ fn test_fpathconf_limited() {
);
}
+#[cfg_attr(target_os = "hurd", ignore)]
#[test]
fn test_pathconf_limited() {
- // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
+ // PATH_MAX is limited on most platforms, so it makes a good test
let path_max = pathconf("/", PathconfVar::PATH_MAX);
assert!(
path_max
@@ -656,9 +683,10 @@ fn test_pathconf_limited() {
);
}
+#[cfg_attr(target_os = "hurd", ignore)]
#[test]
fn test_sysconf_limited() {
- // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test
+ // OPEN_MAX is limited on most platforms, so it makes a good test
let open_max = sysconf(SysconfVar::OPEN_MAX);
assert!(
open_max
@@ -678,13 +706,7 @@ fn test_sysconf_unsupported() {
assert!(open_max.expect("sysconf failed").is_none())
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "openbsd"
-))]
+#[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
#[test]
fn test_getresuid() {
let resuids = getresuid().unwrap();
@@ -693,13 +715,7 @@ fn test_getresuid() {
assert_ne!(resuids.saved.as_raw(), libc::uid_t::MAX);
}
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "openbsd"
-))]
+#[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
#[test]
fn test_getresgid() {
let resgids = getresgid().unwrap();
@@ -714,12 +730,12 @@ fn test_getresgid() {
fn test_pipe() {
let (fd0, fd1) = pipe().unwrap();
let m0 = stat::SFlag::from_bits_truncate(
- stat::fstat(fd0).unwrap().st_mode as mode_t,
+ stat::fstat(fd0.as_raw_fd()).unwrap().st_mode as mode_t,
);
// S_IFIFO means it's a pipe
assert_eq!(m0, SFlag::S_IFIFO);
let m1 = stat::SFlag::from_bits_truncate(
- stat::fstat(fd1).unwrap().st_mode as mode_t,
+ stat::fstat(fd1.as_raw_fd()).unwrap().st_mode as mode_t,
);
assert_eq!(m1, SFlag::S_IFIFO);
}
@@ -727,25 +743,25 @@ fn test_pipe() {
// pipe2(2) is the same as pipe(2), except it allows setting some flags. Check
// that we can set a flag.
#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
+ linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike,
target_os = "emscripten",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
target_os = "redox",
- target_os = "solaris"
))]
#[test]
fn test_pipe2() {
use nix::fcntl::{fcntl, FcntlArg, FdFlag};
let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
- let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap());
+ let f0 = FdFlag::from_bits_truncate(
+ fcntl(fd0.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
+ );
assert!(f0.contains(FdFlag::FD_CLOEXEC));
- let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
+ let f1 = FdFlag::from_bits_truncate(
+ fcntl(fd1.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
+ );
assert!(f1.contains(FdFlag::FD_CLOEXEC));
}
@@ -881,6 +897,8 @@ fn test_symlinkat() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_file() {
+ use nix::fcntl::AtFlags;
+
let tempdir = tempdir().unwrap();
let oldfilename = "foo.txt";
let oldfilepath = tempdir.path().join(oldfilename);
@@ -902,7 +920,7 @@ fn test_linkat_file() {
oldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
@@ -911,6 +929,8 @@ fn test_linkat_file() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_olddirfd_none() {
+ use nix::fcntl::AtFlags;
+
let _dr = crate::DirRestore::new();
let tempdir_oldfile = tempdir().unwrap();
@@ -939,7 +959,7 @@ fn test_linkat_olddirfd_none() {
oldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
@@ -948,6 +968,8 @@ fn test_linkat_olddirfd_none() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_newdirfd_none() {
+ use nix::fcntl::AtFlags;
+
let _dr = crate::DirRestore::new();
let tempdir_oldfile = tempdir().unwrap();
@@ -976,20 +998,17 @@ fn test_linkat_newdirfd_none() {
oldfilename,
None,
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
}
#[test]
-#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "redox",
- target_os = "haiku"
-)))]
+#[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))]
fn test_linkat_no_follow_symlink() {
+ use nix::fcntl::AtFlags;
+
let _m = crate::CWD_LOCK.read();
let tempdir = tempdir().unwrap();
@@ -1019,7 +1038,7 @@ fn test_linkat_no_follow_symlink() {
symoldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::NoSymlinkFollow,
+ AtFlags::empty(),
)
.unwrap();
@@ -1033,6 +1052,8 @@ fn test_linkat_no_follow_symlink() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_follow_symlink() {
+ use nix::fcntl::AtFlags;
+
let _m = crate::CWD_LOCK.read();
let tempdir = tempdir().unwrap();
@@ -1062,7 +1083,7 @@ fn test_linkat_follow_symlink() {
symoldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
@@ -1070,8 +1091,8 @@ fn test_linkat_follow_symlink() {
// Check the file type of the new link
assert_eq!(
- (stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t)
- & SFlag::S_IFMT),
+ stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t)
+ & SFlag::S_IFMT,
SFlag::S_IFREG
);
@@ -1159,8 +1180,6 @@ fn test_access_file_exists() {
.expect("assertion failed");
}
-//Clippy false positive https://github.com/rust-lang/rust-clippy/issues/9111
-#[allow(clippy::needless_borrow)]
#[cfg(not(target_os = "redox"))]
#[test]
fn test_user_into_passwd() {
@@ -1177,7 +1196,7 @@ fn test_user_into_passwd() {
}
/// Tests setting the filesystem UID with `setfsuid`.
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[test]
fn test_setfsuid() {
use std::os::unix::fs::PermissionsExt;
@@ -1230,9 +1249,11 @@ fn test_ttyname() {
grantpt(&fd).expect("grantpt failed");
unlockpt(&fd).expect("unlockpt failed");
let sname = unsafe { ptsname(&fd) }.expect("ptsname failed");
- let fds = open(Path::new(&sname), OFlag::O_RDWR, stat::Mode::empty())
+ let fds = fs::OpenOptions::new()
+ .read(true)
+ .write(true)
+ .open(Path::new(&sname))
.expect("open failed");
- assert!(fds > 0);
let name = ttyname(fds).expect("ttyname failed");
assert!(name.starts_with("/dev"));
@@ -1242,35 +1263,17 @@ fn test_ttyname() {
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
fn test_ttyname_not_pty() {
let fd = File::open("/dev/zero").unwrap();
- assert!(fd.as_raw_fd() > 0);
- assert_eq!(ttyname(fd.as_raw_fd()), Err(Errno::ENOTTY));
+ assert_eq!(ttyname(fd), Err(Errno::ENOTTY));
}
#[test]
-#[cfg(not(any(
- target_os = "redox",
- target_os = "fuchsia",
- target_os = "haiku"
-)))]
-fn test_ttyname_invalid_fd() {
- assert_eq!(ttyname(-1), Err(Errno::EBADF));
-}
-
-#[test]
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "dragonfly",
-))]
+#[cfg(bsd)]
fn test_getpeereid() {
use std::os::unix::net::UnixStream;
let (sock_a, sock_b) = UnixStream::pair().unwrap();
- let (uid_a, gid_a) = getpeereid(sock_a.as_raw_fd()).unwrap();
- let (uid_b, gid_b) = getpeereid(sock_b.as_raw_fd()).unwrap();
+ let (uid_a, gid_a) = getpeereid(sock_a).unwrap();
+ let (uid_b, gid_b) = getpeereid(sock_b).unwrap();
let uid = geteuid();
let gid = getegid();
@@ -1282,20 +1285,6 @@ fn test_getpeereid() {
}
#[test]
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "dragonfly",
-))]
-fn test_getpeereid_invalid_fd() {
- // getpeereid is not POSIX, so error codes are inconsistent between different Unices.
- getpeereid(-1).expect_err("assertion failed");
-}
-
-#[test]
#[cfg(not(target_os = "redox"))]
fn test_faccessat_none_not_existing() {
use nix::fcntl::AtFlags;
@@ -1364,11 +1353,7 @@ fn test_faccessat_file_exists() {
}
#[test]
-#[cfg(any(
- all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
+#[cfg(any(all(target_os = "linux", not(target_env = "uclibc")), freebsdlike))]
fn test_eaccess_not_existing() {
let tempdir = tempdir().unwrap();
let dir = tempdir.path().join("does_not_exist.txt");
@@ -1379,11 +1364,7 @@ fn test_eaccess_not_existing() {
}
#[test]
-#[cfg(any(
- all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
+#[cfg(any(all(target_os = "linux", not(target_env = "uclibc")), freebsdlike))]
fn test_eaccess_file_exists() {
let tempdir = tempdir().unwrap();
let path = tempdir.path().join("does_exist.txt");
@@ -1391,3 +1372,14 @@ fn test_eaccess_file_exists() {
eaccess(&path, AccessFlags::R_OK | AccessFlags::W_OK)
.expect("assertion failed");
}
+
+#[test]
+#[cfg(bsd)]
+fn test_group_from() {
+ let group = Group::from_name("wheel").unwrap().unwrap();
+ assert!(group.name == "wheel");
+ let group_id = group.gid;
+ let group = Group::from_gid(group_id).unwrap().unwrap();
+ assert_eq!(group.gid, group_id);
+ assert_eq!(group.name, "wheel");
+}
diff --git a/third_party/rust/objc_exception/.cargo-checksum.json b/third_party/rust/objc_exception/.cargo-checksum.json
deleted file mode 100644
index ac8ccd308e..0000000000
--- a/third_party/rust/objc_exception/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"4c7727c5464280a94b263b3fbabd775838ce86794834b1adab9bfeefc8a2b731","build.rs":"6734724a6f3c46150f5a6a2adf07b9003ae6f1627fa0ee8fcafa28e9d4aafc15","extern/exception.m":"a6ee21d820126e98ee49ac34db1a6770cfd01f0fb0f71d03127e7eeff91a47c5","src/lib.rs":"24f3b04002dbf24397cc4fd2da7045d49c8b3a06101bab1918d007f7ae9b2207"},"package":"ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"} \ No newline at end of file
diff --git a/third_party/rust/objc_exception/Cargo.toml b/third_party/rust/objc_exception/Cargo.toml
deleted file mode 100644
index 7cdfacb7f7..0000000000
--- a/third_party/rust/objc_exception/Cargo.toml
+++ /dev/null
@@ -1,25 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "objc_exception"
-version = "0.1.2"
-authors = ["Steven Sheldon"]
-build = "build.rs"
-exclude = [".gitignore"]
-description = "Rust interface for Objective-C's throw and try/catch statements."
-documentation = "http://ssheldon.github.io/rust-objc/objc_exception/"
-keywords = ["objective-c", "osx", "ios"]
-license = "MIT"
-repository = "http://github.com/SSheldon/rust-objc-exception"
-[build-dependencies.cc]
-version = "1"
diff --git a/third_party/rust/objc_exception/build.rs b/third_party/rust/objc_exception/build.rs
deleted file mode 100644
index ba728b6e16..0000000000
--- a/third_party/rust/objc_exception/build.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-extern crate cc;
-
-fn main() {
- cc::Build::new()
- .file("extern/exception.m")
- .compile("libexception.a");
-}
diff --git a/third_party/rust/objc_exception/extern/exception.m b/third_party/rust/objc_exception/extern/exception.m
deleted file mode 100644
index 700439ecf7..0000000000
--- a/third_party/rust/objc_exception/extern/exception.m
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <objc/objc.h>
-#include <objc/NSObject.h>
-
-void RustObjCExceptionThrow(id exception) {
- @throw exception;
-}
-
-int RustObjCExceptionTryCatch(void (*try)(void *), void *context, id *error) {
- @try {
- try(context);
- if (error) {
- *error = nil;
- }
- return 0;
- } @catch (id exception) {
- if (error) {
- *error = [exception retain];
- }
- return 1;
- }
-}
diff --git a/third_party/rust/objc_exception/src/lib.rs b/third_party/rust/objc_exception/src/lib.rs
deleted file mode 100644
index d381f60c70..0000000000
--- a/third_party/rust/objc_exception/src/lib.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-//! Rust interface for Objective-C's `@throw` and `@try`/`@catch` statements.
-
-use std::mem;
-use std::os::raw::{c_int, c_void};
-use std::ptr;
-
-#[link(name = "objc", kind = "dylib")]
-extern { }
-
-extern {
- fn RustObjCExceptionThrow(exception: *mut c_void);
- fn RustObjCExceptionTryCatch(try: extern fn(*mut c_void),
- context: *mut c_void, error: *mut *mut c_void) -> c_int;
-}
-
-/// An opaque type representing any Objective-C object thrown as an exception.
-pub enum Exception { }
-
-/// Throws an Objective-C exception.
-/// The argument must be a pointer to an Objective-C object.
-///
-/// Unsafe because this unwinds from Objective-C.
-pub unsafe fn throw(exception: *mut Exception) -> ! {
- RustObjCExceptionThrow(exception as *mut _);
- unreachable!();
-}
-
-unsafe fn try_no_ret<F>(closure: F) -> Result<(), *mut Exception>
- where F: FnOnce() {
- extern fn try_objc_execute_closure<F>(closure: &mut Option<F>)
- where F: FnOnce() {
- // This is always passed Some, so it's safe to unwrap
- let closure = closure.take().unwrap();
- closure();
- }
-
- let f: extern fn(&mut Option<F>) = try_objc_execute_closure;
- let f: extern fn(*mut c_void) = mem::transmute(f);
- // Wrap the closure in an Option so it can be taken
- let mut closure = Some(closure);
- let context = &mut closure as *mut _ as *mut c_void;
-
- let mut exception = ptr::null_mut();
- let success = RustObjCExceptionTryCatch(f, context, &mut exception);
-
- if success == 0 {
- Ok(())
- } else {
- Err(exception as *mut _)
- }
-}
-
-/// Tries to execute the given closure and catches an Objective-C exception
-/// if one is thrown.
-///
-/// Returns a `Result` that is either `Ok` if the closure succeeded without an
-/// exception being thrown, or an `Err` with a pointer to an exception if one
-/// was thrown. The exception is retained and so must be released.
-///
-/// Unsafe because this encourages unwinding through the closure from
-/// Objective-C, which is not safe.
-pub unsafe fn try<F, R>(closure: F) -> Result<R, *mut Exception>
- where F: FnOnce() -> R {
- let mut value = None;
- let result = {
- let value_ref = &mut value;
- try_no_ret(move || {
- *value_ref = Some(closure());
- })
- };
- // If the try succeeded, this was set so it's safe to unwrap
- result.map(|_| value.unwrap())
-}
-
-#[cfg(test)]
-mod tests {
- use std::ptr;
- use super::{throw, try};
-
- #[test]
- fn test_try() {
- unsafe {
- let s = "Hello".to_string();
- let result = try(move || {
- if s.len() > 0 {
- throw(ptr::null_mut());
- }
- s.len()
- });
- assert!(result.unwrap_err() == ptr::null_mut());
-
- let mut s = "Hello".to_string();
- let result = try(move || {
- s.push_str(", World!");
- s
- });
- assert!(result.unwrap() == "Hello, World!");
- }
- }
-}
diff --git a/third_party/rust/owning_ref/.cargo-checksum.json b/third_party/rust/owning_ref/.cargo-checksum.json
deleted file mode 100644
index 274171be15..0000000000
--- a/third_party/rust/owning_ref/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"9a3880e4d5435ca03c0197c45d4ce6b6db6d3fb7eda855f297bafc2ec28af836","Cargo.toml":"91184e6b143ddf621fe7e6757fb28d8eb4c0e01f541fbd0dc440bf076ebfd20d","LICENSE":"90bc15ed094593083fd129fdd1a03607be80fe8839c5564616a5961ab7f7a194","README.md":"0dfea39ad1662ed0a61bb1453eafc207a53dfe577e7846c87d3a5161574fdb12","src/lib.rs":"2e423e210bf2e3ee5e4c426b9a3c9b7756fc434beff1ccf9afa48704e4ac993d"},"package":"6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"} \ No newline at end of file
diff --git a/third_party/rust/owning_ref/CHANGELOG.md b/third_party/rust/owning_ref/CHANGELOG.md
deleted file mode 100644
index a5d24e8c82..0000000000
--- a/third_party/rust/owning_ref/CHANGELOG.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Changelog
-
-## [0.4.1] - 2020-02-27
-### Added
-- `map_with_owner` (#51)
-
-### Changed
-- Use dyn for trait objects (#53)
diff --git a/third_party/rust/owning_ref/Cargo.toml b/third_party/rust/owning_ref/Cargo.toml
deleted file mode 100644
index 057fd5c1bb..0000000000
--- a/third_party/rust/owning_ref/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "owning_ref"
-version = "0.4.1"
-authors = ["Marvin Löbel <loebel.marvin@gmail.com>"]
-description = "A library for creating references that carry their owner with them."
-documentation = "http://kimundi.github.io/owning-ref-rs/owning_ref/index.html"
-readme = "README.md"
-keywords = ["reference", "sibling", "field", "owning"]
-license = "MIT"
-repository = "https://github.com/Kimundi/owning-ref-rs"
-[dependencies.stable_deref_trait]
-version = "1.0.0"
diff --git a/third_party/rust/owning_ref/LICENSE b/third_party/rust/owning_ref/LICENSE
deleted file mode 100644
index dff72d1e43..0000000000
--- a/third_party/rust/owning_ref/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Marvin Löbel
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/third_party/rust/owning_ref/README.md b/third_party/rust/owning_ref/README.md
deleted file mode 100644
index ad32ac24fd..0000000000
--- a/third_party/rust/owning_ref/README.md
+++ /dev/null
@@ -1,64 +0,0 @@
-[![Build Status](https://travis-ci.org/Kimundi/owning-ref-rs.svg)](https://travis-ci.org/Kimundi/owning-ref-rs)
-[![Crate](https://img.shields.io/crates/v/owning_ref.svg)](https://crates.io/crates/owning_ref)
-[![Docs](https://docs.rs/owning_ref/badge.svg)](https://docs.rs/owning_ref)
-
-owning-ref-rs
-==============
-
-A library for creating references that carry their owner with them.
-
-This can sometimes be useful because Rust borrowing rules normally prevent
-moving a type that has been borrowed from. For example, this kind of code gets rejected:
-
-```rust
-fn return_owned_and_referenced<'a>() -> (Vec<u8>, &'a [u8]) {
- let v = vec![1, 2, 3, 4];
- let s = &v[1..3];
- (v, s)
-}
-```
-
-This library enables this safe usage by keeping the owner and the reference
-bundled together in a wrapper type that ensure that lifetime constraint:
-
-```rust
-fn return_owned_and_referenced() -> OwningRef<Vec<u8>, [u8]> {
- let v = vec![1, 2, 3, 4];
- let or = OwningRef::new(v);
- let or = or.map(|v| &v[1..3]);
- or
-}
-```
-
-## Getting Started
-
-To get started, add the following to `Cargo.toml`.
-
-```toml
-owning_ref = "0.4.1"
-```
-
-...and see the [docs](http://kimundi.github.io/owning-ref-rs/owning_ref/index.html) for how to use it.
-
-
-## Example
-
-```rust
-extern crate owning_ref;
-use owning_ref::BoxRef;
-
-fn main() {
- // Create an array owned by a Box.
- let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>;
-
- // Transfer into a BoxRef.
- let arr: BoxRef<[i32]> = BoxRef::new(arr);
- assert_eq!(&*arr, &[1, 2, 3, 4]);
-
- // We can slice the array without losing ownership or changing type.
- let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]);
- assert_eq!(&*arr, &[2, 3]);
-
- // Also works for Arc, Rc, String and Vec!
-}
-```
diff --git a/third_party/rust/owning_ref/src/lib.rs b/third_party/rust/owning_ref/src/lib.rs
deleted file mode 100644
index fa2f15a220..0000000000
--- a/third_party/rust/owning_ref/src/lib.rs
+++ /dev/null
@@ -1,2016 +0,0 @@
-#![warn(missing_docs)]
-
-/*!
-# An owning reference.
-
-This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut`
-that enables it to bundle a reference together with the owner of the data it points to.
-This allows moving and dropping of a `OwningRef` without needing to recreate the reference.
-
-This can sometimes be useful because Rust borrowing rules normally prevent
-moving a type that has been moved from. For example, this kind of code gets rejected:
-
-```rust,ignore
-fn return_owned_and_referenced<'a>() -> (Vec<u8>, &'a [u8]) {
- let v = vec![1, 2, 3, 4];
- let s = &v[1..3];
- (v, s)
-}
-```
-
-Even though, from a memory-layout point of view, this can be entirely safe
-if the new location of the vector still lives longer than the lifetime `'a`
-of the reference because the backing allocation of the vector does not change.
-
-This library enables this safe usage by keeping the owner and the reference
-bundled together in a wrapper type that ensure that lifetime constraint:
-
-```rust
-# extern crate owning_ref;
-# use owning_ref::OwningRef;
-# fn main() {
-fn return_owned_and_referenced() -> OwningRef<Vec<u8>, [u8]> {
- let v = vec![1, 2, 3, 4];
- let or = OwningRef::new(v);
- let or = or.map(|v| &v[1..3]);
- or
-}
-# }
-```
-
-It works by requiring owner types to dereference to stable memory locations
-and preventing mutable access to root containers, which in practice requires heap allocation
-as provided by `Box<T>`, `Rc<T>`, etc.
-
-Also provided are typedefs for common owner type combinations,
-which allow for less verbose type signatures. For example, `BoxRef<T>` instead of `OwningRef<Box<T>, T>`.
-
-The crate also provides the more advanced `OwningHandle` type,
-which allows more freedom in bundling a dependent handle object
-along with the data it depends on, at the cost of some unsafe needed in the API.
-See the documentation around `OwningHandle` for more details.
-
-# Examples
-
-## Basics
-
-```
-extern crate owning_ref;
-use owning_ref::BoxRef;
-
-fn main() {
- // Create an array owned by a Box.
- let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>;
-
- // Transfer into a BoxRef.
- let arr: BoxRef<[i32]> = BoxRef::new(arr);
- assert_eq!(&*arr, &[1, 2, 3, 4]);
-
- // We can slice the array without losing ownership or changing type.
- let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]);
- assert_eq!(&*arr, &[2, 3]);
-
- // Also works for Arc, Rc, String and Vec!
-}
-```
-
-## Caching a reference to a struct field
-
-```
-extern crate owning_ref;
-use owning_ref::BoxRef;
-
-fn main() {
- struct Foo {
- tag: u32,
- x: u16,
- y: u16,
- z: u16,
- }
- let foo = Foo { tag: 1, x: 100, y: 200, z: 300 };
-
- let or = BoxRef::new(Box::new(foo)).map(|foo| {
- match foo.tag {
- 0 => &foo.x,
- 1 => &foo.y,
- 2 => &foo.z,
- _ => panic!(),
- }
- });
-
- assert_eq!(*or, 200);
-}
-```
-
-## Caching a reference to an entry in a vector
-
-```
-extern crate owning_ref;
-use owning_ref::VecRef;
-
-fn main() {
- let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]);
- assert_eq!(*v, 4);
-}
-```
-
-## Caching a subslice of a String
-
-```
-extern crate owning_ref;
-use owning_ref::StringRef;
-
-fn main() {
- let s = StringRef::new("hello world".to_owned())
- .map(|s| s.split(' ').nth(1).unwrap());
-
- assert_eq!(&*s, "world");
-}
-```
-
-## Reference counted slices that share ownership of the backing storage
-
-```
-extern crate owning_ref;
-use owning_ref::RcRef;
-use std::rc::Rc;
-
-fn main() {
- let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>);
- assert_eq!(&*rc, &[1, 2, 3, 4]);
-
- let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]);
- let rc_b = rc.clone().map(|s| &s[1..3]);
- let rc_c = rc.clone().map(|s| &s[2..4]);
- assert_eq!(&*rc_a, &[1, 2]);
- assert_eq!(&*rc_b, &[2, 3]);
- assert_eq!(&*rc_c, &[3, 4]);
-
- let rc_c_a = rc_c.clone().map(|s| &s[1]);
- assert_eq!(&*rc_c_a, &4);
-}
-```
-
-## Atomic reference counted slices that share ownership of the backing storage
-
-```
-extern crate owning_ref;
-use owning_ref::ArcRef;
-use std::sync::Arc;
-
-fn main() {
- use std::thread;
-
- fn par_sum(rc: ArcRef<[i32]>) -> i32 {
- if rc.len() == 0 {
- return 0;
- } else if rc.len() == 1 {
- return rc[0];
- }
- let mid = rc.len() / 2;
- let left = rc.clone().map(|s| &s[..mid]);
- let right = rc.map(|s| &s[mid..]);
-
- let left = thread::spawn(move || par_sum(left));
- let right = thread::spawn(move || par_sum(right));
-
- left.join().unwrap() + right.join().unwrap()
- }
-
- let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]);
- let rc: ArcRef<[i32]> = rc.into();
-
- assert_eq!(par_sum(rc), 10);
-}
-```
-
-## References into RAII locks
-
-```
-extern crate owning_ref;
-use owning_ref::RefRef;
-use std::cell::{RefCell, Ref};
-
-fn main() {
- let refcell = RefCell::new((1, 2, 3, 4));
- // Also works with Mutex and RwLock
-
- let refref = {
- let refref = RefRef::new(refcell.borrow()).map(|x| &x.3);
- assert_eq!(*refref, 4);
-
- // We move the RAII lock and the reference to one of
- // the subfields in the data it guards here:
- refref
- };
-
- assert_eq!(*refref, 4);
-
- drop(refref);
-
- assert_eq!(*refcell.borrow(), (1, 2, 3, 4));
-}
-```
-
-## Mutable reference
-
-When the owned container implements `DerefMut`, it is also possible to make
-a _mutable owning reference_. (E.g. with `Box`, `RefMut`, `MutexGuard`)
-
-```
-extern crate owning_ref;
-use owning_ref::RefMutRefMut;
-use std::cell::{RefCell, RefMut};
-
-fn main() {
- let refcell = RefCell::new((1, 2, 3, 4));
-
- let mut refmut_refmut = {
- let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3);
- assert_eq!(*refmut_refmut, 4);
- *refmut_refmut *= 2;
-
- refmut_refmut
- };
-
- assert_eq!(*refmut_refmut, 8);
- *refmut_refmut *= 2;
-
- drop(refmut_refmut);
-
- assert_eq!(*refcell.borrow(), (1, 2, 3, 16));
-}
-```
-*/
-
-extern crate stable_deref_trait;
-pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress};
-
-/// An owning reference.
-///
-/// This wraps an owner `O` and a reference `&T` pointing
-/// at something reachable from `O::Target` while keeping
-/// the ability to move `self` around.
-///
-/// The owner is usually a pointer that points at some base type.
-///
-/// For more details and examples, see the module and method docs.
-pub struct OwningRef<O, T: ?Sized> {
- owner: O,
- reference: *const T,
-}
-
-/// An mutable owning reference.
-///
-/// This wraps an owner `O` and a reference `&mut T` pointing
-/// at something reachable from `O::Target` while keeping
-/// the ability to move `self` around.
-///
-/// The owner is usually a pointer that points at some base type.
-///
-/// For more details and examples, see the module and method docs.
-pub struct OwningRefMut<O, T: ?Sized> {
- owner: O,
- reference: *mut T,
-}
-
-/// Helper trait for an erased concrete type an owner dereferences to.
-/// This is used in form of a trait object for keeping
-/// something around to (virtually) call the destructor.
-pub trait Erased {}
-impl<T> Erased for T {}
-
-/// Helper trait for erasing the concrete type of what an owner derferences to,
-/// for example `Box<T> -> Box<dyn Erased>`. This would be unneeded with
-/// higher kinded types support in the language.
-pub unsafe trait IntoErased<'a> {
- /// Owner with the dereference type substituted to `Erased`.
- type Erased;
- /// Perform the type erasure.
- fn into_erased(self) -> Self::Erased;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// OwningRef
-/////////////////////////////////////////////////////////////////////////////
-
-impl<O, T: ?Sized> OwningRef<O, T> {
- /// Creates a new owning reference from a owner
- /// initialized to the direct dereference of it.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRef;
- ///
- /// fn main() {
- /// let owning_ref = OwningRef::new(Box::new(42));
- /// assert_eq!(*owning_ref, 42);
- /// }
- /// ```
- pub fn new(o: O) -> Self
- where O: StableAddress,
- O: Deref<Target = T>,
- {
- OwningRef {
- reference: &*o,
- owner: o,
- }
- }
-
- /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait.
- /// Instead, the caller is responsible to make the same promises as implementing the trait.
- ///
- /// This is useful for cases where coherence rules prevents implementing the trait
- /// without adding a dependency to this crate in a third-party library.
- pub unsafe fn new_assert_stable_address(o: O) -> Self
- where O: Deref<Target = T>,
- {
- OwningRef {
- reference: &*o,
- owner: o,
- }
- }
-
- /// Converts `self` into a new owning reference that points at something reachable
- /// from the previous one.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRef;
- ///
- /// fn main() {
- /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
- ///
- /// // create a owning reference that points at the
- /// // third element of the array.
- /// let owning_ref = owning_ref.map(|array| &array[2]);
- /// assert_eq!(*owning_ref, 3);
- /// }
- /// ```
- pub fn map<F, U: ?Sized>(self, f: F) -> OwningRef<O, U>
- where O: StableAddress,
- F: FnOnce(&T) -> &U
- {
- OwningRef {
- reference: f(&self),
- owner: self.owner,
- }
- }
-
- /// Converts `self` into a new owning reference that points at something reachable
- /// from the previous one or from the owner itself.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U` or from the owner `O`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRef;
- ///
- /// fn main() {
- /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
- /// let owning_ref = owning_ref.map(|array| &array[2]);
- /// assert_eq!(*owning_ref, 3);
- ///
- /// // create a owning reference that points at the
- /// // second element of the array from the owning ref that was pointing to the third
- /// let owning_ref = owning_ref.map_with_owner(|array, _prev| &array[1]);
- /// assert_eq!(*owning_ref, 2);
- /// }
- /// ```
- pub fn map_with_owner<F, U: ?Sized>(self, f: F) -> OwningRef<O, U>
- where O: StableAddress,
- F: for<'a> FnOnce(&'a O, &'a T) -> &'a U
- {
- OwningRef {
- reference: f(&self.owner, &self),
- owner: self.owner,
- }
- }
-
- /// Tries to convert `self` into a new owning reference that points
- /// at something reachable from the previous one.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRef;
- ///
- /// fn main() {
- /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
- ///
- /// // create a owning reference that points at the
- /// // third element of the array.
- /// let owning_ref = owning_ref.try_map(|array| {
- /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) }
- /// });
- /// assert_eq!(*owning_ref.unwrap(), 3);
- /// }
- /// ```
- pub fn try_map<F, U: ?Sized, E>(self, f: F) -> Result<OwningRef<O, U>, E>
- where O: StableAddress,
- F: FnOnce(&T) -> Result<&U, E>
- {
- Ok(OwningRef {
- reference: f(&self)?,
- owner: self.owner,
- })
- }
-
- /// Tries to convert `self` into a new owning reference that points
- /// at something reachable from the previous one.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRef;
- ///
- /// fn main() {
- /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
- /// let owning_ref = owning_ref.map(|array| &array[2]);
- ///
- /// // create a owning reference that points at the
- /// // second element of the array from the owning ref that was pointing to the third
- /// let owning_ref = owning_ref.try_map_with_owner(|array, _prev| {
- /// if array[1] == 2 { Ok(&array[1]) } else { Err(()) }
- /// });
- /// assert_eq!(*owning_ref.unwrap(), 2);
- /// }
- /// ```
- pub fn try_map_with_owner<F, U: ?Sized, E>(self, f: F) -> Result<OwningRef<O, U>, E>
- where O: StableAddress,
- F: for<'a> FnOnce(&'a O, &'a T) -> Result<&'a U, E>
- {
- Ok(OwningRef {
- reference: f(&self.owner, &self)?,
- owner: self.owner,
- })
- }
-
- /// Converts `self` into a new owning reference with a different owner type.
- ///
- /// The new owner type needs to still contain the original owner in some way
- /// so that the reference into it remains valid. This function is marked unsafe
- /// because the user needs to manually uphold this guarantee.
- pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRef<P, T>
- where O: StableAddress,
- P: StableAddress,
- F: FnOnce(O) -> P
- {
- OwningRef {
- reference: self.reference,
- owner: f(self.owner),
- }
- }
-
- /// Converts `self` into a new owning reference where the owner is wrapped
- /// in an additional `Box<O>`.
- ///
- /// This can be used to safely erase the owner of any `OwningRef<O, T>`
- /// to a `OwningRef<Box<dyn Erased>, T>`.
- pub fn map_owner_box(self) -> OwningRef<Box<O>, T> {
- OwningRef {
- reference: self.reference,
- owner: Box::new(self.owner),
- }
- }
-
- /// Erases the concrete base type of the owner with a trait object.
- ///
- /// This allows mixing of owned references with different owner base types.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::{OwningRef, Erased};
- ///
- /// fn main() {
- /// // NB: Using the concrete types here for explicitnes.
- /// // For less verbose code type aliases like `BoxRef` are provided.
- ///
- /// let owning_ref_a: OwningRef<Box<[i32; 4]>, [i32; 4]>
- /// = OwningRef::new(Box::new([1, 2, 3, 4]));
- ///
- /// let owning_ref_b: OwningRef<Box<Vec<(i32, bool)>>, Vec<(i32, bool)>>
- /// = OwningRef::new(Box::new(vec![(0, false), (1, true)]));
- ///
- /// let owning_ref_a: OwningRef<Box<[i32; 4]>, i32>
- /// = owning_ref_a.map(|a| &a[0]);
- ///
- /// let owning_ref_b: OwningRef<Box<Vec<(i32, bool)>>, i32>
- /// = owning_ref_b.map(|a| &a[1].0);
- ///
- /// let owning_refs: [OwningRef<Box<dyn Erased>, i32>; 2]
- /// = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()];
- ///
- /// assert_eq!(*owning_refs[0], 1);
- /// assert_eq!(*owning_refs[1], 1);
- /// }
- /// ```
- pub fn erase_owner<'a>(self) -> OwningRef<O::Erased, T>
- where O: IntoErased<'a>,
- {
- OwningRef {
- reference: self.reference,
- owner: self.owner.into_erased(),
- }
- }
-
- // TODO: wrap_owner
-
- /// A reference to the underlying owner.
- pub fn as_owner(&self) -> &O {
- &self.owner
- }
-
- /// Discards the reference and retrieves the owner.
- pub fn into_owner(self) -> O {
- self.owner
- }
-}
-
-impl<O, T: ?Sized> OwningRefMut<O, T> {
- /// Creates a new owning reference from a owner
- /// initialized to the direct dereference of it.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRefMut;
- ///
- /// fn main() {
- /// let owning_ref_mut = OwningRefMut::new(Box::new(42));
- /// assert_eq!(*owning_ref_mut, 42);
- /// }
- /// ```
- pub fn new(mut o: O) -> Self
- where O: StableAddress,
- O: DerefMut<Target = T>,
- {
- OwningRefMut {
- reference: &mut *o,
- owner: o,
- }
- }
-
- /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait.
- /// Instead, the caller is responsible to make the same promises as implementing the trait.
- ///
- /// This is useful for cases where coherence rules prevents implementing the trait
- /// without adding a dependency to this crate in a third-party library.
- pub unsafe fn new_assert_stable_address(mut o: O) -> Self
- where O: DerefMut<Target = T>,
- {
- OwningRefMut {
- reference: &mut *o,
- owner: o,
- }
- }
-
- /// Converts `self` into a new _shared_ owning reference that points at
- /// something reachable from the previous one.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRefMut;
- ///
- /// fn main() {
- /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
- ///
- /// // create a owning reference that points at the
- /// // third element of the array.
- /// let owning_ref = owning_ref_mut.map(|array| &array[2]);
- /// assert_eq!(*owning_ref, 3);
- /// }
- /// ```
- pub fn map<F, U: ?Sized>(mut self, f: F) -> OwningRef<O, U>
- where O: StableAddress,
- F: FnOnce(&mut T) -> &U
- {
- OwningRef {
- reference: f(&mut self),
- owner: self.owner,
- }
- }
-
- /// Converts `self` into a new _mutable_ owning reference that points at
- /// something reachable from the previous one.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRefMut;
- ///
- /// fn main() {
- /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
- ///
- /// // create a owning reference that points at the
- /// // third element of the array.
- /// let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]);
- /// assert_eq!(*owning_ref_mut, 3);
- /// }
- /// ```
- pub fn map_mut<F, U: ?Sized>(mut self, f: F) -> OwningRefMut<O, U>
- where O: StableAddress,
- F: FnOnce(&mut T) -> &mut U
- {
- OwningRefMut {
- reference: f(&mut self),
- owner: self.owner,
- }
- }
-
- /// Tries to convert `self` into a new _shared_ owning reference that points
- /// at something reachable from the previous one.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRefMut;
- ///
- /// fn main() {
- /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
- ///
- /// // create a owning reference that points at the
- /// // third element of the array.
- /// let owning_ref = owning_ref_mut.try_map(|array| {
- /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) }
- /// });
- /// assert_eq!(*owning_ref.unwrap(), 3);
- /// }
- /// ```
- pub fn try_map<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRef<O, U>, E>
- where O: StableAddress,
- F: FnOnce(&mut T) -> Result<&U, E>
- {
- Ok(OwningRef {
- reference: f(&mut self)?,
- owner: self.owner,
- })
- }
-
- /// Tries to convert `self` into a new _mutable_ owning reference that points
- /// at something reachable from the previous one.
- ///
- /// This can be a reference to a field of `U`, something reachable from a field of
- /// `U`, or even something unrelated with a `'static` lifetime.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::OwningRefMut;
- ///
- /// fn main() {
- /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
- ///
- /// // create a owning reference that points at the
- /// // third element of the array.
- /// let owning_ref_mut = owning_ref_mut.try_map_mut(|array| {
- /// if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) }
- /// });
- /// assert_eq!(*owning_ref_mut.unwrap(), 3);
- /// }
- /// ```
- pub fn try_map_mut<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRefMut<O, U>, E>
- where O: StableAddress,
- F: FnOnce(&mut T) -> Result<&mut U, E>
- {
- Ok(OwningRefMut {
- reference: f(&mut self)?,
- owner: self.owner,
- })
- }
-
- /// Converts `self` into a new owning reference with a different owner type.
- ///
- /// The new owner type needs to still contain the original owner in some way
- /// so that the reference into it remains valid. This function is marked unsafe
- /// because the user needs to manually uphold this guarantee.
- pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRefMut<P, T>
- where O: StableAddress,
- P: StableAddress,
- F: FnOnce(O) -> P
- {
- OwningRefMut {
- reference: self.reference,
- owner: f(self.owner),
- }
- }
-
- /// Converts `self` into a new owning reference where the owner is wrapped
- /// in an additional `Box<O>`.
- ///
- /// This can be used to safely erase the owner of any `OwningRefMut<O, T>`
- /// to a `OwningRefMut<Box<dyn Erased>, T>`.
- pub fn map_owner_box(self) -> OwningRefMut<Box<O>, T> {
- OwningRefMut {
- reference: self.reference,
- owner: Box::new(self.owner),
- }
- }
-
- /// Erases the concrete base type of the owner with a trait object.
- ///
- /// This allows mixing of owned references with different owner base types.
- ///
- /// # Example
- /// ```
- /// extern crate owning_ref;
- /// use owning_ref::{OwningRefMut, Erased};
- ///
- /// fn main() {
- /// // NB: Using the concrete types here for explicitnes.
- /// // For less verbose code type aliases like `BoxRef` are provided.
- ///
- /// let owning_ref_mut_a: OwningRefMut<Box<[i32; 4]>, [i32; 4]>
- /// = OwningRefMut::new(Box::new([1, 2, 3, 4]));
- ///
- /// let owning_ref_mut_b: OwningRefMut<Box<Vec<(i32, bool)>>, Vec<(i32, bool)>>
- /// = OwningRefMut::new(Box::new(vec![(0, false), (1, true)]));
- ///
- /// let owning_ref_mut_a: OwningRefMut<Box<[i32; 4]>, i32>
- /// = owning_ref_mut_a.map_mut(|a| &mut a[0]);
- ///
- /// let owning_ref_mut_b: OwningRefMut<Box<Vec<(i32, bool)>>, i32>
- /// = owning_ref_mut_b.map_mut(|a| &mut a[1].0);
- ///
- /// let owning_refs_mut: [OwningRefMut<Box<dyn Erased>, i32>; 2]
- /// = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()];
- ///
- /// assert_eq!(*owning_refs_mut[0], 1);
- /// assert_eq!(*owning_refs_mut[1], 1);
- /// }
- /// ```
- pub fn erase_owner<'a>(self) -> OwningRefMut<O::Erased, T>
- where O: IntoErased<'a>,
- {
- OwningRefMut {
- reference: self.reference,
- owner: self.owner.into_erased(),
- }
- }
-
- // TODO: wrap_owner
-
- /// A reference to the underlying owner.
- pub fn as_owner(&self) -> &O {
- &self.owner
- }
-
- /// A mutable reference to the underlying owner.
- pub fn as_owner_mut(&mut self) -> &mut O {
- &mut self.owner
- }
-
- /// Discards the reference and retrieves the owner.
- pub fn into_owner(self) -> O {
- self.owner
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// OwningHandle
-/////////////////////////////////////////////////////////////////////////////
-
-use std::ops::{Deref, DerefMut};
-
-/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows
-/// consumers to pass around an owned object and a dependent reference,
-/// `OwningHandle` contains an owned object and a dependent _object_.
-///
-/// `OwningHandle` can encapsulate a `RefMut` along with its associated
-/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`.
-/// However, the API is completely generic and there are no restrictions on
-/// what types of owning and dependent objects may be used.
-///
-/// `OwningHandle` is created by passing an owner object (which dereferences
-/// to a stable address) along with a callback which receives a pointer to
-/// that stable location. The callback may then dereference the pointer and
-/// mint a dependent object, with the guarantee that the returned object will
-/// not outlive the referent of the pointer.
-///
-/// Since the callback needs to dereference a raw pointer, it requires `unsafe`
-/// code. To avoid forcing this unsafety on most callers, the `ToHandle` trait is
-/// implemented for common data structures. Types that implement `ToHandle` can
-/// be wrapped into an `OwningHandle` without passing a callback.
-pub struct OwningHandle<O, H>
- where O: StableAddress, H: Deref,
-{
- handle: H,
- _owner: O,
-}
-
-impl<O, H> Deref for OwningHandle<O, H>
- where O: StableAddress, H: Deref,
-{
- type Target = H::Target;
- fn deref(&self) -> &H::Target {
- self.handle.deref()
- }
-}
-
-unsafe impl<O, H> StableAddress for OwningHandle<O, H>
- where O: StableAddress, H: StableAddress,
-{}
-
-impl<O, H> DerefMut for OwningHandle<O, H>
- where O: StableAddress, H: DerefMut,
-{
- fn deref_mut(&mut self) -> &mut H::Target {
- self.handle.deref_mut()
- }
-}
-
-/// Trait to implement the conversion of owner to handle for common types.
-pub trait ToHandle {
- /// The type of handle to be encapsulated by the OwningHandle.
- type Handle: Deref;
-
- /// Given an appropriately-long-lived pointer to ourselves, create a
- /// handle to be encapsulated by the `OwningHandle`.
- unsafe fn to_handle(x: *const Self) -> Self::Handle;
-}
-
-/// Trait to implement the conversion of owner to mutable handle for common types.
-pub trait ToHandleMut {
- /// The type of handle to be encapsulated by the OwningHandle.
- type HandleMut: DerefMut;
-
- /// Given an appropriately-long-lived pointer to ourselves, create a
- /// mutable handle to be encapsulated by the `OwningHandle`.
- unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut;
-}
-
-impl<O, H> OwningHandle<O, H>
- where O: StableAddress, O::Target: ToHandle<Handle = H>, H: Deref,
-{
- /// Create a new `OwningHandle` for a type that implements `ToHandle`. For types
- /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts
- /// a callback to perform the conversion.
- pub fn new(o: O) -> Self {
- OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) })
- }
-}
-
-impl<O, H> OwningHandle<O, H>
- where O: StableAddress, O::Target: ToHandleMut<HandleMut = H>, H: DerefMut,
-{
- /// Create a new mutable `OwningHandle` for a type that implements `ToHandleMut`.
- pub fn new_mut(o: O) -> Self {
- OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) })
- }
-}
-
-impl<O, H> OwningHandle<O, H>
- where O: StableAddress, H: Deref,
-{
- /// Create a new OwningHandle. The provided callback will be invoked with
- /// a pointer to the object owned by `o`, and the returned value is stored
- /// as the object to which this `OwningHandle` will forward `Deref` and
- /// `DerefMut`.
- pub fn new_with_fn<F>(o: O, f: F) -> Self
- where F: FnOnce(*const O::Target) -> H
- {
- let h: H;
- {
- h = f(o.deref() as *const O::Target);
- }
-
- OwningHandle {
- handle: h,
- _owner: o,
- }
- }
-
- /// Create a new OwningHandle. The provided callback will be invoked with
- /// a pointer to the object owned by `o`, and the returned value is stored
- /// as the object to which this `OwningHandle` will forward `Deref` and
- /// `DerefMut`.
- pub fn try_new<F, E>(o: O, f: F) -> Result<Self, E>
- where F: FnOnce(*const O::Target) -> Result<H, E>
- {
- let h: H;
- {
- h = f(o.deref() as *const O::Target)?;
- }
-
- Ok(OwningHandle {
- handle: h,
- _owner: o,
- })
- }
-
- /// A getter for the underlying owner.
- pub fn as_owner(&self) -> &O {
- &self._owner
- }
-
- /// Discards the dependent object and returns the owner.
- pub fn into_owner(self) -> O {
- self._owner
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// std traits
-/////////////////////////////////////////////////////////////////////////////
-
-use std::convert::From;
-use std::fmt::{self, Debug};
-use std::marker::{Send, Sync};
-use std::cmp::{Eq, PartialEq, Ord, PartialOrd, Ordering};
-use std::hash::{Hash, Hasher};
-use std::borrow::Borrow;
-
-impl<O, T: ?Sized> Deref for OwningRef<O, T> {
- type Target = T;
-
- fn deref(&self) -> &T {
- unsafe {
- &*self.reference
- }
- }
-}
-
-impl<O, T: ?Sized> Deref for OwningRefMut<O, T> {
- type Target = T;
-
- fn deref(&self) -> &T {
- unsafe {
- &*self.reference
- }
- }
-}
-
-impl<O, T: ?Sized> DerefMut for OwningRefMut<O, T> {
- fn deref_mut(&mut self) -> &mut T {
- unsafe {
- &mut *self.reference
- }
- }
-}
-
-unsafe impl<O, T: ?Sized> StableAddress for OwningRef<O, T> {}
-
-unsafe impl<O, T: ?Sized> StableAddress for OwningRefMut<O, T> {}
-
-impl<O, T: ?Sized> AsRef<T> for OwningRef<O, T> {
- fn as_ref(&self) -> &T {
- &*self
- }
-}
-
-impl<O, T: ?Sized> AsRef<T> for OwningRefMut<O, T> {
- fn as_ref(&self) -> &T {
- &*self
- }
-}
-
-impl<O, T: ?Sized> AsMut<T> for OwningRefMut<O, T> {
- fn as_mut(&mut self) -> &mut T {
- &mut *self
- }
-}
-
-impl<O, T: ?Sized> Borrow<T> for OwningRef<O, T> {
- fn borrow(&self) -> &T {
- &*self
- }
-}
-
-impl<O, T: ?Sized> From<O> for OwningRef<O, T>
- where O: StableAddress,
- O: Deref<Target = T>,
-{
- fn from(owner: O) -> Self {
- OwningRef::new(owner)
- }
-}
-
-impl<O, T: ?Sized> From<O> for OwningRefMut<O, T>
- where O: StableAddress,
- O: DerefMut<Target = T>
-{
- fn from(owner: O) -> Self {
- OwningRefMut::new(owner)
- }
-}
-
-impl<O, T: ?Sized> From<OwningRefMut<O, T>> for OwningRef<O, T>
- where O: StableAddress,
- O: DerefMut<Target = T>
-{
- fn from(other: OwningRefMut<O, T>) -> Self {
- OwningRef {
- owner: other.owner,
- reference: other.reference,
- }
- }
-}
-
-// ^ FIXME: Is a Into impl for calling into_owner() possible as well?
-
-impl<O, T: ?Sized> Debug for OwningRef<O, T>
- where O: Debug,
- T: Debug,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(f,
- "OwningRef {{ owner: {:?}, reference: {:?} }}",
- self.as_owner(),
- &**self)
- }
-}
-
-impl<O, T: ?Sized> Debug for OwningRefMut<O, T>
- where O: Debug,
- T: Debug,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(f,
- "OwningRefMut {{ owner: {:?}, reference: {:?} }}",
- self.as_owner(),
- &**self)
- }
-}
-
-impl<O, T: ?Sized> Clone for OwningRef<O, T>
- where O: CloneStableAddress,
-{
- fn clone(&self) -> Self {
- OwningRef {
- owner: self.owner.clone(),
- reference: self.reference,
- }
- }
-}
-
-unsafe impl<O, T: ?Sized> CloneStableAddress for OwningRef<O, T>
- where O: CloneStableAddress {}
-
-unsafe impl<O, T: ?Sized> Send for OwningRef<O, T>
- where O: Send, for<'a> (&'a T): Send {}
-unsafe impl<O, T: ?Sized> Sync for OwningRef<O, T>
- where O: Sync, for<'a> (&'a T): Sync {}
-
-unsafe impl<O, T: ?Sized> Send for OwningRefMut<O, T>
- where O: Send, for<'a> (&'a mut T): Send {}
-unsafe impl<O, T: ?Sized> Sync for OwningRefMut<O, T>
- where O: Sync, for<'a> (&'a mut T): Sync {}
-
-impl Debug for dyn Erased {
- fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(f, "<dyn Erased>",)
- }
-}
-
-impl<O, T: ?Sized> PartialEq for OwningRef<O, T> where T: PartialEq {
- fn eq(&self, other: &Self) -> bool {
- (&*self as &T).eq(&*other as &T)
- }
-}
-
-impl<O, T: ?Sized> Eq for OwningRef<O, T> where T: Eq {}
-
-impl<O, T: ?Sized> PartialOrd for OwningRef<O, T> where T: PartialOrd {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- (&*self as &T).partial_cmp(&*other as &T)
- }
-}
-
-impl<O, T: ?Sized> Ord for OwningRef<O, T> where T: Ord {
- fn cmp(&self, other: &Self) -> Ordering {
- (&*self as &T).cmp(&*other as &T)
- }
-}
-
-impl<O, T: ?Sized> Hash for OwningRef<O, T> where T: Hash {
- fn hash<H: Hasher>(&self, state: &mut H) {
- (&*self as &T).hash(state);
- }
-}
-
-impl<O, T: ?Sized> PartialEq for OwningRefMut<O, T> where T: PartialEq {
- fn eq(&self, other: &Self) -> bool {
- (&*self as &T).eq(&*other as &T)
- }
-}
-
-impl<O, T: ?Sized> Eq for OwningRefMut<O, T> where T: Eq {}
-
-impl<O, T: ?Sized> PartialOrd for OwningRefMut<O, T> where T: PartialOrd {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- (&*self as &T).partial_cmp(&*other as &T)
- }
-}
-
-impl<O, T: ?Sized> Ord for OwningRefMut<O, T> where T: Ord {
- fn cmp(&self, other: &Self) -> Ordering {
- (&*self as &T).cmp(&*other as &T)
- }
-}
-
-impl<O, T: ?Sized> Hash for OwningRefMut<O, T> where T: Hash {
- fn hash<H: Hasher>(&self, state: &mut H) {
- (&*self as &T).hash(state);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// std types integration and convenience type defs
-/////////////////////////////////////////////////////////////////////////////
-
-use std::boxed::Box;
-use std::rc::Rc;
-use std::sync::Arc;
-use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard};
-use std::cell::{Ref, RefCell, RefMut};
-
-impl<T: 'static> ToHandle for RefCell<T> {
- type Handle = Ref<'static, T>;
- unsafe fn to_handle(x: *const Self) -> Self::Handle { (*x).borrow() }
-}
-
-impl<T: 'static> ToHandleMut for RefCell<T> {
- type HandleMut = RefMut<'static, T>;
- unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { (*x).borrow_mut() }
-}
-
-// NB: Implementing ToHandle{,Mut} for Mutex and RwLock requires a decision
-// about which handle creation to use (i.e. read() vs try_read()) as well as
-// what to do with error results.
-
-/// Typedef of a owning reference that uses a `Box` as the owner.
-pub type BoxRef<T, U = T> = OwningRef<Box<T>, U>;
-/// Typedef of a owning reference that uses a `Vec` as the owner.
-pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
-/// Typedef of a owning reference that uses a `String` as the owner.
-pub type StringRef = OwningRef<String, str>;
-
-/// Typedef of a owning reference that uses a `Rc` as the owner.
-pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
-/// Typedef of a owning reference that uses a `Arc` as the owner.
-pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;
-
-/// Typedef of a owning reference that uses a `Ref` as the owner.
-pub type RefRef<'a, T, U = T> = OwningRef<Ref<'a, T>, U>;
-/// Typedef of a owning reference that uses a `RefMut` as the owner.
-pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>;
-/// Typedef of a owning reference that uses a `MutexGuard` as the owner.
-pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;
-/// Typedef of a owning reference that uses a `RwLockReadGuard` as the owner.
-pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;
-/// Typedef of a owning reference that uses a `RwLockWriteGuard` as the owner.
-pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
-
-/// Typedef of a mutable owning reference that uses a `Box` as the owner.
-pub type BoxRefMut<T, U = T> = OwningRefMut<Box<T>, U>;
-/// Typedef of a mutable owning reference that uses a `Vec` as the owner.
-pub type VecRefMut<T, U = T> = OwningRefMut<Vec<T>, U>;
-/// Typedef of a mutable owning reference that uses a `String` as the owner.
-pub type StringRefMut = OwningRefMut<String, str>;
-
-/// Typedef of a mutable owning reference that uses a `RefMut` as the owner.
-pub type RefMutRefMut<'a, T, U = T> = OwningRefMut<RefMut<'a, T>, U>;
-/// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner.
-pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut<MutexGuard<'a, T>, U>;
-/// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner.
-pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRefMut<RwLockWriteGuard<'a, T>, U>;
-
-unsafe impl<'a, T: 'a> IntoErased<'a> for Box<T> {
- type Erased = Box<dyn Erased + 'a>;
- fn into_erased(self) -> Self::Erased {
- self
- }
-}
-unsafe impl<'a, T: 'a> IntoErased<'a> for Rc<T> {
- type Erased = Rc<dyn Erased + 'a>;
- fn into_erased(self) -> Self::Erased {
- self
- }
-}
-unsafe impl<'a, T: 'a> IntoErased<'a> for Arc<T> {
- type Erased = Arc<dyn Erased + 'a>;
- fn into_erased(self) -> Self::Erased {
- self
- }
-}
-
-/// Typedef of a owning reference that uses an erased `Box` as the owner.
-pub type ErasedBoxRef<U> = OwningRef<Box<dyn Erased>, U>;
-/// Typedef of a owning reference that uses an erased `Rc` as the owner.
-pub type ErasedRcRef<U> = OwningRef<Rc<dyn Erased>, U>;
-/// Typedef of a owning reference that uses an erased `Arc` as the owner.
-pub type ErasedArcRef<U> = OwningRef<Arc<dyn Erased>, U>;
-
-/// Typedef of a mutable owning reference that uses an erased `Box` as the owner.
-pub type ErasedBoxRefMut<U> = OwningRefMut<Box<dyn Erased>, U>;
-
-#[cfg(test)]
-mod tests {
- mod owning_ref {
- use super::super::OwningRef;
- use super::super::{RcRef, BoxRef, Erased, ErasedBoxRef};
- use std::cmp::{PartialEq, Ord, PartialOrd, Ordering};
- use std::hash::{Hash, Hasher};
- use std::collections::hash_map::DefaultHasher;
- use std::collections::HashMap;
- use std::rc::Rc;
-
- #[derive(Debug, PartialEq)]
- struct Example(u32, String, [u8; 3]);
- fn example() -> Example {
- Example(42, "hello world".to_string(), [1, 2, 3])
- }
-
- #[test]
- fn new_deref() {
- let or: OwningRef<Box<()>, ()> = OwningRef::new(Box::new(()));
- assert_eq!(&*or, &());
- }
-
- #[test]
- fn into() {
- let or: OwningRef<Box<()>, ()> = Box::new(()).into();
- assert_eq!(&*or, &());
- }
-
- #[test]
- fn map_offset_ref() {
- let or: BoxRef<Example> = Box::new(example()).into();
- let or: BoxRef<_, u32> = or.map(|x| &x.0);
- assert_eq!(&*or, &42);
-
- let or: BoxRef<Example> = Box::new(example()).into();
- let or: BoxRef<_, u8> = or.map(|x| &x.2[1]);
- assert_eq!(&*or, &2);
- }
-
- #[test]
- fn map_heap_ref() {
- let or: BoxRef<Example> = Box::new(example()).into();
- let or: BoxRef<_, str> = or.map(|x| &x.1[..5]);
- assert_eq!(&*or, "hello");
- }
-
- #[test]
- fn map_static_ref() {
- let or: BoxRef<()> = Box::new(()).into();
- let or: BoxRef<_, str> = or.map(|_| "hello");
- assert_eq!(&*or, "hello");
- }
-
- #[test]
- fn map_chained() {
- let or: BoxRef<String> = Box::new(example().1).into();
- let or: BoxRef<_, str> = or.map(|x| &x[1..5]);
- let or: BoxRef<_, str> = or.map(|x| &x[..2]);
- assert_eq!(&*or, "el");
- }
-
- #[test]
- fn map_chained_inference() {
- let or = BoxRef::new(Box::new(example().1))
- .map(|x| &x[..5])
- .map(|x| &x[1..3]);
- assert_eq!(&*or, "el");
- }
-
- #[test]
- fn as_owner() {
- let or: BoxRef<String> = Box::new(example().1).into();
- let or = or.map(|x| &x[..5]);
- assert_eq!(&*or, "hello");
- assert_eq!(&**or.as_owner(), "hello world");
- }
-
- #[test]
- fn into_owner() {
- let or: BoxRef<String> = Box::new(example().1).into();
- let or = or.map(|x| &x[..5]);
- assert_eq!(&*or, "hello");
- let s = *or.into_owner();
- assert_eq!(&s, "hello world");
- }
-
- #[test]
- fn fmt_debug() {
- let or: BoxRef<String> = Box::new(example().1).into();
- let or = or.map(|x| &x[..5]);
- let s = format!("{:?}", or);
- assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }");
- }
-
- #[test]
- fn erased_owner() {
- let o1: BoxRef<Example, str> = BoxRef::new(Box::new(example()))
- .map(|x| &x.1[..]);
-
- let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1))
- .map(|x| &x[..]);
-
- let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()];
- assert!(os.iter().all(|e| &e[..] == "hello world"));
- }
-
- #[test]
- fn non_static_erased_owner() {
- let foo = [413, 612];
- let bar = &foo;
-
- // FIXME: lifetime inference fails us, and we can't easily define a lifetime for a closure
- // (see https://github.com/rust-lang/rust/issues/22340)
- // So we use a function to identify the lifetimes instead.
- fn borrow<'a>(a: &'a &[i32; 2]) -> &'a i32 {
- &a[0]
- }
-
- let o: BoxRef<&[i32; 2]> = Box::new(bar).into();
- let o: BoxRef<&[i32; 2], i32> = o.map(borrow);
- let o: BoxRef<dyn Erased, i32> = o.erase_owner();
-
- assert_eq!(*o, 413);
- }
-
- #[test]
- fn raii_locks() {
- use super::super::{RefRef, RefMutRef};
- use std::cell::RefCell;
- use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef};
- use std::sync::{Mutex, RwLock};
-
- {
- let a = RefCell::new(1);
- let a = {
- let a = RefRef::new(a.borrow());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- {
- let a = RefCell::new(1);
- let a = {
- let a = RefMutRef::new(a.borrow_mut());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- {
- let a = Mutex::new(1);
- let a = {
- let a = MutexGuardRef::new(a.lock().unwrap());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- {
- let a = RwLock::new(1);
- let a = {
- let a = RwLockReadGuardRef::new(a.read().unwrap());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- {
- let a = RwLock::new(1);
- let a = {
- let a = RwLockWriteGuardRef::new(a.write().unwrap());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- }
-
- #[test]
- fn eq() {
- let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
- let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
- assert_eq!(or1.eq(&or2), true);
- }
-
- #[test]
- fn cmp() {
- let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
- let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice());
- assert_eq!(or1.cmp(&or2), Ordering::Less);
- }
-
- #[test]
- fn partial_cmp() {
- let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice());
- let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
- assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater));
- }
-
- #[test]
- fn hash() {
- let mut h1 = DefaultHasher::new();
- let mut h2 = DefaultHasher::new();
-
- let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
- let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
-
- or1.hash(&mut h1);
- or2.hash(&mut h2);
-
- assert_eq!(h1.finish(), h2.finish());
- }
-
- #[test]
- fn borrow() {
- let mut hash = HashMap::new();
- let key = RcRef::<String>::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]);
-
- hash.insert(key.clone().map(|s| &s[..3]), 42);
- hash.insert(key.clone().map(|s| &s[4..]), 23);
-
- assert_eq!(hash.get("foo"), Some(&42));
- assert_eq!(hash.get("bar"), Some(&23));
- }
-
- #[test]
- fn total_erase() {
- let a: OwningRef<Vec<u8>, [u8]>
- = OwningRef::new(vec![]).map(|x| &x[..]);
- let b: OwningRef<Box<[u8]>, [u8]>
- = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]);
-
- let c: OwningRef<Rc<Vec<u8>>, [u8]> = unsafe {a.map_owner(Rc::new)};
- let d: OwningRef<Rc<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Rc::new)};
-
- let e: OwningRef<Rc<dyn Erased>, [u8]> = c.erase_owner();
- let f: OwningRef<Rc<dyn Erased>, [u8]> = d.erase_owner();
-
- let _g = e.clone();
- let _h = f.clone();
- }
-
- #[test]
- fn total_erase_box() {
- let a: OwningRef<Vec<u8>, [u8]>
- = OwningRef::new(vec![]).map(|x| &x[..]);
- let b: OwningRef<Box<[u8]>, [u8]>
- = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]);
-
- let c: OwningRef<Box<Vec<u8>>, [u8]> = a.map_owner_box();
- let d: OwningRef<Box<Box<[u8]>>, [u8]> = b.map_owner_box();
-
- let _e: OwningRef<Box<dyn Erased>, [u8]> = c.erase_owner();
- let _f: OwningRef<Box<dyn Erased>, [u8]> = d.erase_owner();
- }
-
- #[test]
- fn try_map1() {
- use std::any::Any;
-
- let x = Box::new(123_i32);
- let y: Box<dyn Any> = x;
-
- OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).unwrap();
- }
-
- #[test]
- fn try_map2() {
- use std::any::Any;
-
- let x = Box::new(123_u32);
- let y: Box<dyn Any> = x;
-
- OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).unwrap_err();
- }
-
- #[test]
- fn map_with_owner() {
- let owning_ref: BoxRef<Example> = Box::new(example()).into();
- let owning_ref = owning_ref.map(|owner| &owner.1);
-
- owning_ref.map_with_owner(|owner, ref_field| {
- assert_eq!(owner.1, *ref_field);
- ref_field
- });
- }
-
- #[test]
- fn try_map_with_owner_ok() {
- let owning_ref: BoxRef<Example> = Box::new(example()).into();
- let owning_ref = owning_ref.map(|owner| &owner.1);
-
- owning_ref.try_map_with_owner(|owner, ref_field| {
- assert_eq!(owner.1, *ref_field);
- Ok(ref_field) as Result<_, ()>
- }).unwrap();
- }
-
- #[test]
- fn try_map_with_owner_err() {
- let owning_ref: BoxRef<Example> = Box::new(example()).into();
- let owning_ref = owning_ref.map(|owner| &owner.1);
-
- owning_ref.try_map_with_owner(|owner, ref_field| {
- assert_eq!(owner.1, *ref_field);
- Err(()) as Result<&(), _>
- }).unwrap_err();
- }
- }
-
- mod owning_handle {
- use super::super::OwningHandle;
- use super::super::RcRef;
- use std::rc::Rc;
- use std::cell::RefCell;
- use std::sync::Arc;
- use std::sync::RwLock;
-
- #[test]
- fn owning_handle() {
- use std::cell::RefCell;
- let cell = Rc::new(RefCell::new(2));
- let cell_ref = RcRef::new(cell);
- let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
- assert_eq!(*handle, 2);
- *handle = 3;
- assert_eq!(*handle, 3);
- }
-
- #[test]
- fn try_owning_handle_ok() {
- use std::cell::RefCell;
- let cell = Rc::new(RefCell::new(2));
- let cell_ref = RcRef::new(cell);
- let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| {
- Ok(unsafe {
- x.as_ref()
- }.unwrap().borrow_mut())
- }).unwrap();
- assert_eq!(*handle, 2);
- *handle = 3;
- assert_eq!(*handle, 3);
- }
-
- #[test]
- fn try_owning_handle_err() {
- use std::cell::RefCell;
- let cell = Rc::new(RefCell::new(2));
- let cell_ref = RcRef::new(cell);
- let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| {
- if false {
- return Ok(unsafe {
- x.as_ref()
- }.unwrap().borrow_mut())
- }
- Err(())
- });
- assert!(handle.is_err());
- }
-
- #[test]
- fn nested() {
- use std::cell::RefCell;
- use std::sync::{Arc, RwLock};
-
- let result = {
- let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
- let curr = RcRef::new(complex);
- let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
- let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap());
- assert_eq!(*curr, "someString");
- *curr = "someOtherString";
- curr
- };
- assert_eq!(*result, "someOtherString");
- }
-
- #[test]
- fn owning_handle_safe() {
- use std::cell::RefCell;
- let cell = Rc::new(RefCell::new(2));
- let cell_ref = RcRef::new(cell);
- let handle = OwningHandle::new(cell_ref);
- assert_eq!(*handle, 2);
- }
-
- #[test]
- fn owning_handle_mut_safe() {
- use std::cell::RefCell;
- let cell = Rc::new(RefCell::new(2));
- let cell_ref = RcRef::new(cell);
- let mut handle = OwningHandle::new_mut(cell_ref);
- assert_eq!(*handle, 2);
- *handle = 3;
- assert_eq!(*handle, 3);
- }
-
- #[test]
- fn owning_handle_safe_2() {
- let result = {
- let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
- let curr = RcRef::new(complex);
- let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
- let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap());
- assert_eq!(*curr, "someString");
- *curr = "someOtherString";
- curr
- };
- assert_eq!(*result, "someOtherString");
- }
- }
-
- mod owning_ref_mut {
- use super::super::{OwningRefMut, BoxRefMut, Erased, ErasedBoxRefMut};
- use super::super::BoxRef;
- use std::cmp::{PartialEq, Ord, PartialOrd, Ordering};
- use std::hash::{Hash, Hasher};
- use std::collections::hash_map::DefaultHasher;
- use std::collections::HashMap;
-
- #[derive(Debug, PartialEq)]
- struct Example(u32, String, [u8; 3]);
- fn example() -> Example {
- Example(42, "hello world".to_string(), [1, 2, 3])
- }
-
- #[test]
- fn new_deref() {
- let or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(()));
- assert_eq!(&*or, &());
- }
-
- #[test]
- fn new_deref_mut() {
- let mut or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(()));
- assert_eq!(&mut *or, &mut ());
- }
-
- #[test]
- fn mutate() {
- let mut or: OwningRefMut<Box<usize>, usize> = OwningRefMut::new(Box::new(0));
- assert_eq!(&*or, &0);
- *or = 1;
- assert_eq!(&*or, &1);
- }
-
- #[test]
- fn into() {
- let or: OwningRefMut<Box<()>, ()> = Box::new(()).into();
- assert_eq!(&*or, &());
- }
-
- #[test]
- fn map_offset_ref() {
- let or: BoxRefMut<Example> = Box::new(example()).into();
- let or: BoxRef<_, u32> = or.map(|x| &mut x.0);
- assert_eq!(&*or, &42);
-
- let or: BoxRefMut<Example> = Box::new(example()).into();
- let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]);
- assert_eq!(&*or, &2);
- }
-
- #[test]
- fn map_heap_ref() {
- let or: BoxRefMut<Example> = Box::new(example()).into();
- let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]);
- assert_eq!(&*or, "hello");
- }
-
- #[test]
- fn map_static_ref() {
- let or: BoxRefMut<()> = Box::new(()).into();
- let or: BoxRef<_, str> = or.map(|_| "hello");
- assert_eq!(&*or, "hello");
- }
-
- #[test]
- fn map_mut_offset_ref() {
- let or: BoxRefMut<Example> = Box::new(example()).into();
- let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0);
- assert_eq!(&*or, &42);
-
- let or: BoxRefMut<Example> = Box::new(example()).into();
- let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]);
- assert_eq!(&*or, &2);
- }
-
- #[test]
- fn map_mut_heap_ref() {
- let or: BoxRefMut<Example> = Box::new(example()).into();
- let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]);
- assert_eq!(&*or, "hello");
- }
-
- #[test]
- fn map_mut_static_ref() {
- static mut MUT_S: [u8; 5] = *b"hello";
-
- let mut_s: &'static mut [u8] = unsafe { &mut MUT_S };
-
- let or: BoxRefMut<()> = Box::new(()).into();
- let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s);
- assert_eq!(&*or, b"hello");
- }
-
- #[test]
- fn map_mut_chained() {
- let or: BoxRefMut<String> = Box::new(example().1).into();
- let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]);
- let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]);
- assert_eq!(&*or, "el");
- }
-
- #[test]
- fn map_chained_inference() {
- let or = BoxRefMut::new(Box::new(example().1))
- .map_mut(|x| &mut x[..5])
- .map_mut(|x| &mut x[1..3]);
- assert_eq!(&*or, "el");
- }
-
- #[test]
- fn try_map_mut() {
- let or: BoxRefMut<String> = Box::new(example().1).into();
- let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|x| Ok(&mut x[1..5]));
- assert_eq!(&*or.unwrap(), "ello");
-
- let or: BoxRefMut<String> = Box::new(example().1).into();
- let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|_| Err(()));
- assert!(or.is_err());
- }
-
- #[test]
- fn as_owner() {
- let or: BoxRefMut<String> = Box::new(example().1).into();
- let or = or.map_mut(|x| &mut x[..5]);
- assert_eq!(&*or, "hello");
- assert_eq!(&**or.as_owner(), "hello world");
- }
-
- #[test]
- fn into_owner() {
- let or: BoxRefMut<String> = Box::new(example().1).into();
- let or = or.map_mut(|x| &mut x[..5]);
- assert_eq!(&*or, "hello");
- let s = *or.into_owner();
- assert_eq!(&s, "hello world");
- }
-
- #[test]
- fn fmt_debug() {
- let or: BoxRefMut<String> = Box::new(example().1).into();
- let or = or.map_mut(|x| &mut x[..5]);
- let s = format!("{:?}", or);
- assert_eq!(&s,
- "OwningRefMut { owner: \"hello world\", reference: \"hello\" }");
- }
-
- #[test]
- fn erased_owner() {
- let o1: BoxRefMut<Example, str> = BoxRefMut::new(Box::new(example()))
- .map_mut(|x| &mut x.1[..]);
-
- let o2: BoxRefMut<String, str> = BoxRefMut::new(Box::new(example().1))
- .map_mut(|x| &mut x[..]);
-
- let os: Vec<ErasedBoxRefMut<str>> = vec![o1.erase_owner(), o2.erase_owner()];
- assert!(os.iter().all(|e| &e[..] == "hello world"));
- }
-
- #[test]
- fn non_static_erased_owner() {
- let mut foo = [413, 612];
- let bar = &mut foo;
-
- // FIXME: lifetime inference fails us, and we can't easily define a lifetime for a closure
- // (see https://github.com/rust-lang/rust/issues/22340)
- // So we use a function to identify the lifetimes instead.
- fn borrow<'a>(a: &'a mut &mut [i32; 2]) -> &'a mut i32 {
- &mut a[0]
- }
-
- let o: BoxRefMut<&mut [i32; 2]> = Box::new(bar).into();
- let o: BoxRefMut<&mut [i32; 2], i32> = o.map_mut(borrow);
- let o: BoxRefMut<dyn Erased, i32> = o.erase_owner();
-
- assert_eq!(*o, 413);
- }
-
- #[test]
- fn raii_locks() {
- use super::super::RefMutRefMut;
- use std::cell::RefCell;
- use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut};
- use std::sync::{Mutex, RwLock};
-
- {
- let a = RefCell::new(1);
- let a = {
- let a = RefMutRefMut::new(a.borrow_mut());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- {
- let a = Mutex::new(1);
- let a = {
- let a = MutexGuardRefMut::new(a.lock().unwrap());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- {
- let a = RwLock::new(1);
- let a = {
- let a = RwLockWriteGuardRefMut::new(a.write().unwrap());
- assert_eq!(*a, 1);
- a
- };
- assert_eq!(*a, 1);
- drop(a);
- }
- }
-
- #[test]
- fn eq() {
- let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
- let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
- assert_eq!(or1.eq(&or2), true);
- }
-
- #[test]
- fn cmp() {
- let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
- let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice());
- assert_eq!(or1.cmp(&or2), Ordering::Less);
- }
-
- #[test]
- fn partial_cmp() {
- let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice());
- let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
- assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater));
- }
-
- #[test]
- fn hash() {
- let mut h1 = DefaultHasher::new();
- let mut h2 = DefaultHasher::new();
-
- let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
- let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
-
- or1.hash(&mut h1);
- or2.hash(&mut h2);
-
- assert_eq!(h1.finish(), h2.finish());
- }
-
- #[test]
- fn borrow() {
- let mut hash = HashMap::new();
- let key1 = BoxRefMut::<String>::new(Box::new("foo".to_string())).map(|s| &s[..]);
- let key2 = BoxRefMut::<String>::new(Box::new("bar".to_string())).map(|s| &s[..]);
-
- hash.insert(key1, 42);
- hash.insert(key2, 23);
-
- assert_eq!(hash.get("foo"), Some(&42));
- assert_eq!(hash.get("bar"), Some(&23));
- }
-
- #[test]
- fn total_erase() {
- let a: OwningRefMut<Vec<u8>, [u8]>
- = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]);
- let b: OwningRefMut<Box<[u8]>, [u8]>
- = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]);
-
- let c: OwningRefMut<Box<Vec<u8>>, [u8]> = unsafe {a.map_owner(Box::new)};
- let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Box::new)};
-
- let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner();
- let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner();
- }
-
- #[test]
- fn total_erase_box() {
- let a: OwningRefMut<Vec<u8>, [u8]>
- = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]);
- let b: OwningRefMut<Box<[u8]>, [u8]>
- = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]);
-
- let c: OwningRefMut<Box<Vec<u8>>, [u8]> = a.map_owner_box();
- let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = b.map_owner_box();
-
- let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner();
- let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner();
- }
-
- #[test]
- fn try_map1() {
- use std::any::Any;
-
- let x = Box::new(123_i32);
- let y: Box<dyn Any> = x;
-
- OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).unwrap();
- }
-
- #[test]
- fn try_map2() {
- use std::any::Any;
-
- let x = Box::new(123_u32);
- let y: Box<dyn Any> = x;
-
- OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).unwrap_err();
- }
-
- #[test]
- fn try_map3() {
- use std::any::Any;
-
- let x = Box::new(123_i32);
- let y: Box<dyn Any> = x;
-
- OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).unwrap();
- }
-
- #[test]
- fn try_map4() {
- use std::any::Any;
-
- let x = Box::new(123_u32);
- let y: Box<dyn Any> = x;
-
- OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).unwrap_err();
- }
-
- #[test]
- fn into_owning_ref() {
- use super::super::BoxRef;
-
- let or: BoxRefMut<()> = Box::new(()).into();
- let or: BoxRef<()> = or.into();
- assert_eq!(&*or, &());
- }
-
- struct Foo {
- u: u32,
- }
- struct Bar {
- f: Foo,
- }
-
- #[test]
- fn ref_mut() {
- use std::cell::RefCell;
-
- let a = RefCell::new(Bar { f: Foo { u: 42 } });
- let mut b = OwningRefMut::new(a.borrow_mut());
- assert_eq!(b.f.u, 42);
- b.f.u = 43;
- let mut c = b.map_mut(|x| &mut x.f);
- assert_eq!(c.u, 43);
- c.u = 44;
- let mut d = c.map_mut(|x| &mut x.u);
- assert_eq!(*d, 44);
- *d = 45;
- assert_eq!(*d, 45);
- }
- }
-}
diff --git a/third_party/rust/packed_simd/.cargo-checksum.json b/third_party/rust/packed_simd/.cargo-checksum.json
deleted file mode 100644
index 0d75492f06..0000000000
--- a/third_party/rust/packed_simd/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"ae219b55eab1f8cd8c3497d7327ea0e5426dba23d2446f7981ca799ad80b6a52","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c4ac7027a9ab7d7858aa8957d7454dbfcdbb81e605b6a171f05310cc3cad3762","bors.toml":"dee881dc69b9b7834e4eba5d95c3ed5a416d4628815a167d6a22d4cb4fb064b8","build.rs":"019ed29c43989782d8eec3a961654cfc172d7a7898da4eca8f654700af7e1988","ci/all.sh":"2ae6b2445b4db83833e40b37efd0016c6b9879ee988b9b3ef94db5439a3e1606","ci/android-install-ndk.sh":"bdcf93ba9043ac1184e2c504a3d40c47c6c1601d882e0f0a27a8eb56fbabcb5f","ci/android-install-sdk.sh":"3490432022c5c8f5a115c084f7a9aca1626f96c0c87ffb62019228c4346b47e4","ci/android-sysimage.sh":"ebf4e5daa1f0fe1b2092b79f0f3f161c4c4275cb744e52352c4d81ab451e4c5a","ci/benchmark.sh":"b61d19ef6b90deba8fb79dee74c8b062d94844676293da346da87bb78a9a49a4","ci/deploy_and_run_on_ios_simulator.rs":"ec8ecf82d92072676aa47f0d1a3d021b60a7ae3531153ef12d2ff4541fc294dc","ci/docker/aarch64-linux-android/Dockerfile":"ace2e7d33c87bc0f6d3962a4a3408c04557646f7f51ab99cfbf574906796b016","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"da88c0d50f16dc08448c7fdf1fa5ed2cbe576acf9e7dd85b5b818621b2a8c702","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"bb5f8ae890707c128652290ffc544447643bf12037ddd73c6ad6989f848cb380","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"1afaefcbc05b740859acd4e067bc92439be6bcbe8f2e9678474fb434bcd398d9","ci/docker/armv7-linux-androideabi/Dockerfile":"370e55d3330a413a3ccf677b3afb3e0ef9018a5fab263faa97ae8ac017fc2286","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"8282ea707a94109beed47a57574755e2d58401735904a03f85fb64c578c53b4f","ci/docker/i586-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/i686-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/mips-unknown-linux-gnu/Dockerfile":"b2ebc25797612c4f8395fe9d407725156044955bfbcf442036b7f55b43a5f9da","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"b0c1692ac65bc56dd30494b1993d8e929c48cc9c4b92029b7c7592af6d4f9220","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"4e9249c179300138141d0b2b7401b11897f64aed69f541f078c1db4594df2827","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"3164c52b0dcbb01afa78292b15b5c43503ccf0491cf6eb801ec2bf22ae274e52","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"ae8274309928620a5dd232a46264e05399bb746288ebee3843a71c4162208cc3","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"ba5fbc4bf3bb91cd50b407248da31225681efc8f2be7618f4a0ab1219b389508","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"53f97f8b9b5aca7534b9bf9ea48f35175052cd2a560a107e01ad270731c032fc","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"89f5421cf06d817ae94092987e914472ef384ad2d1fff2735be3d8786ba11214","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"83eba19576486f9d10d7c037d669d72b31a65565a479f30b22aab36aaa2ff8dc","ci/docker/thumbv7neon-linux-androideabi/Dockerfile":"c2decd5591bd7a09378901bef629cd944acf052eb55e4f35b79eb9cb4d62246a","ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile":"51955a8bf3c4d440f47382af6f5426ebff94ab01a04da36175babda9a057740f","ci/docker/wasm32-unknown-unknown/Dockerfile":"b982b421c70db476900df5b60e19ef8815e6c7dae22687225002780cab7b0a76","ci/docker/x86_64-linux-android/Dockerfile":"a17ebdb186ce2dd6b62100b5a439e05a1ab9adab113e2508843e121aaea52992","ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile":"44b6203d9290bfdc53d81219f0937e1110847a23dd982ec8c4de388354f01536","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"7f4e3ca5fa288ea70edb4d1f75309708cd30b192e2e4444e61c4d5b3b58f89cf","ci/dox.sh":"434e9611c52e389312d2b03564adf09429f10cc76fe66a8644adb104903b87b7","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab7ad3b7a344833ee726aba6b647cf5952e56f0ad1ba420b13325","ci/lld-shim.rs":"3d7f71ec23a49e2b67f694a0168786f9a954dda15f5a138815d966643fd3fcc3","ci/max_line_width.sh":"0a1518bba4c9ecaa55694cb2e9930d0e19c265baabf73143f17f9cf285aaa5bb","ci/run-docker.sh":"92e036390ad9b0d16f109579df1b5ced2e72e9afea40c7d011400ebd3a2a90de","ci/run.sh":"9afabc961e0ee83b87201f3fd554c19e5b0c36f3a95d013595e276c9882dd0a4","ci/run_examples.sh":"d1a23c6c35374a0678ba5114b9b8fefd8be0a79e774872a8bf0898d1baca18d0","ci/runtest-android.rs":"145a8e9799a5223975061fe7e586ade5669ee4877a7d7a4cf6b4ab48e8e36c7c","ci/setup_benchmarks.sh":"fae3960023f6f3d1388cd2ad22fdbab4b075f1f29dd4292d7994a20783beb6cf","ci/test-runner-linux":"c8aa6025cff5306f4f31d0c61dc5f9d4dd5a1d189ab613ef8d4c367c694d9ccd","contributing.md":"2d2629310ad4d464c482bdbb5819f0d6ce223c576aeef2cdce6a1f6857085ea5","perf-guide/book.toml":"115a98284126c6b180178b44713314cc494f08a71662ee2ce15cf67f17a51064","perf-guide/src/SUMMARY.md":"3e03bffc991fdc2050f3d51842d72d9d21ea6abab56a3baf3b2d5973a78b89e1","perf-guide/src/ascii.css":"29afb08833b2fe2250f0412e1fa1161a2432a0820a14953c87124407417c741a","perf-guide/src/bound_checks.md":"5e4991ff58a183ef0cd9fdc1feb4cd12d083b44bdf87393bbb0927808ef3ce7d","perf-guide/src/float-math/approx.md":"8c09032fa2d795a0c5db1775826c850d28eb2627846d0965c60ee72de63735ad","perf-guide/src/float-math/fma.md":"311076ba4b741d604a82e74b83a8d7e8c318fcbd7f64c4392d1cf5af95c60243","perf-guide/src/float-math/fp.md":"04153e775ab6e4f0d7837bcc515230d327b04edfa34c84ce9c9e10ebaeef2be8","perf-guide/src/float-math/svml.md":"0798873b8eedaeda5fed62dc91645b57c20775a02d3cd74d8bd06958f1516506","perf-guide/src/introduction.md":"9f5a19e9e6751f25d2daad39891a0cc600974527ec4c8305843f9618910671bd","perf-guide/src/prof/linux.md":"447731eb5de7d69166728fdbc5ecb0c0c9db678ea493b45a592d67dd002184c0","perf-guide/src/prof/mca.md":"f56d54f3d20e7aa4d32052186e8237b03d65971eb5d112802b442570ff11d344","perf-guide/src/prof/profiling.md":"8a650c0fd6ede0964789bb6577557eeef1d8226a896788602ce61528e260e43c","perf-guide/src/target-feature/attribute.md":"615f88dca0a707b6c416fa605435dd6e1fb5361cc639429cbf68cd87624bd78b","perf-guide/src/target-feature/features.md":"17077760ff24c006b606dd21889c53d87228f4311f3ba3a574f9afdeacd86165","perf-guide/src/target-feature/inlining.md":"7ed1d7068d8173a00d84c16cfe5871cd68b9f04f8d0cca2d01ebc84957ebf2f6","perf-guide/src/target-feature/practice.md":"c4b371842e0086df178488fec97f20def8f0c62ee588bcd25fd948b9b1fa227e","perf-guide/src/target-feature/runtime.md":"835425f5ee597fb3e51d36e725a81ebee29f4561231d19563cd4da81dbb1cfcb","perf-guide/src/target-feature/rustflags.md":"01197acf6f0adec8db32b8591811f69cecb6555a2b05dc5d5ec27d0e3f7b065e","perf-guide/src/vert-hor-ops.md":"c6211c0ee91e60552ec592d89d9d957eedc21dee3cbd89e1ad6765ea06a27471","rust-toolchain":"58bea07cb6d97f9cfcd5c8f98b1feca0fb81cce5b0bf29a8e70ed2641956e9a6","rustfmt.toml":"d99a43f3f8ef9e425cf01c333fba9f0051f888f5d87ab4e8f63c2f7d0fe6620f","src/api.rs":"45508c6c0241519fc01a7f00c9105554c24c312c4e46900ef9c75139ea438305","src/api/bit_manip.rs":"27f3097fc0a11e3c4107049d9779e680dcd67407a066704008a6b9c4fd529e05","src/api/bitmask.rs":"058ebc38a2e0363f07a441d3e9a4775aaec57ccb170a0e5d5efa5dc4743ab07b","src/api/cast.rs":"03b94a3d316ac7b7be7068810044911e965e889a0ace7bae762749ca74a92747","src/api/cast/macros.rs":"b0a14d0c83ad2ebb7a275180f6d9e3f2bc312ba57a7d3d6c39fad4e0f20f9408","src/api/cast/v128.rs":"edd0994efac4379dff26e178423a52dbb3ffeb38b1fc97cae975d744c00b4fb6","src/api/cast/v16.rs":"96bd98c2d21b0663abe6c0ab33005b1fa693f3db7ee6795351391343863484da","src/api/cast/v256.rs":"8c31fe91f5e78ef737dfba6979cc1240210cb094a89d284fe459bf8a991ca24b","src/api/cast/v32.rs":"a99a79dd84d2a5e6adf9db98705675915bd03fd1287d489c7fe38e84d7e4a086","src/api/cast/v512.rs":"c0dd526f41ed7b8a71c3743d91267554ec0a0c75834ccc2e3ecb0ef3004af642","src/api/cast/v64.rs":"6572fdba2a1241a6cd666d3f0cce3306cd2cb7e5e236172e59d5d4351c8a88af","src/api/cmp.rs":"357c3a2a09c6d4611c32dd7fa95be2fae933d513e229026ec9b44451a77b884e","src/api/cmp/eq.rs":"60f70f355bae4cb5b17db53204cacc3890f70670611c17df638d4c04f7cc8075","src/api/cmp/ord.rs":"589f7234761c294fa5df8f525bc4acd5a47cdb602207d524a0d4e19804cd9695","src/api/cmp/partial_eq.rs":"902ccb8aa01fd5738b30ba0b712669c21d4801958907e03bad23432c7dba0198","src/api/cmp/partial_ord.rs":"9db0c37d7434cdfc62d8d66912e972fa3d8c115ab2af051a6f45e414bd3e4f1c","src/api/cmp/vertical.rs":"de3d62f38eba817299aa16f1e1939954c9a447e316509397465c2830852ba053","src/api/default.rs":"67bf21c134127d12a7028c8b88a57f0ceee8ccbd74976da8ca74eb9f16a174d5","src/api/fmt.rs":"67fb804bb86b6cd77cf8cd492b5733ce437071b66fe3297278b8a6552c325dda","src/api/fmt/binary.rs":"02b2b287f7404f8a983813cf70c87108c8da3835578b63ab303116885f609413","src/api/fmt/debug.rs":"56e1c3bdc092747344fffaafff9da7163ee7827857f6fb7cb1c9923eca4f6fa0","src/api/fmt/lower_hex.rs":"558fd592f7f485712fb051509cecc7174a21e6bf62e5ce64766e75afc97bb8e1","src/api/fmt/octal.rs":"3b2e70877a4f368c7704f8e254236c014c365c74d93371c1feb5f030e6c66422","src/api/fmt/upper_hex.rs":"2a442f666bc80e22d41f903f881238fe114dd49344c3ed69849250e853cafc5d","src/api/from.rs":"2e599d8329cb05eaf06224cc441355c4b7b51254fc19256619333be8c149d444","src/api/from/from_array.rs":"5d2cc700568376bf6ee1fe5e406da3bc2d488ff155644bf73d06a1349b73fc53","src/api/from/from_vector.rs":"9764371aa9e6005aace74dea14f59e5611a095b7cf42707940924749282c52f0","src/api/hash.rs":"5076ece87969592c876486f5b1ea8affbeaec379d1a14a30859e0aa5592019de","src/api/into_bits.rs":"8f8011627250e23e66b5c0ca641afb079d8232674bb1354140b536bdbea63e55","src/api/into_bits/arch_specific.rs":"e7445021f3908326bfee758835e5fc5ad56aa1baa77fc1c58abe4350c66c670a","src/api/into_bits/macros.rs":"bb4fe99be2af6a21d805efab44c8e4e61a7b2adb42a65504a0cf26d13efdadcd","src/api/into_bits/v128.rs":"145a44922b09a5ca5b62d88a461d327d399a997a15db4b11d7b17e554a9fa4c0","src/api/into_bits/v16.rs":"f4f4f61ba88aa51b158ec56ca3dce234349aea0daf2b3029a14ab5125d1e41e5","src/api/into_bits/v256.rs":"8cea9c5d9809f11323cb7cdc53b83df593fd17caf926251e412ae9777bed547f","src/api/into_bits/v32.rs":"905ba683d342fa32f4202b80bb46530807bd0a5b588f6c2e8c9f475223c47775","src/api/into_bits/v512.rs":"e25afa1fbf088a5d58e7d75d197b6cd4c56637ea28542ba18e46a451f29d04e7","src/api/into_bits/v64.rs":"d6238022ccff7b92e55b3f6017fc269acb6f36330a6d7e8fb389853a0f1b6478","src/api/math.rs":"8b2a2fc651917a850539f993aa0b9e5bf4da67b11685285b8de8cdca311719ec","src/api/math/float.rs":"969a75cdb3743c5ac7cde653d1a7f659ac65f2a5afb004c9928a7b34b79c3e39","src/api/math/float/abs.rs":"5b6b2701e2e11135b7ce58a05052ea8120e10e4702c95d046b9d21b827b26bf8","src/api/math/float/consts.rs":"6302c9261da4291d144d5bb53493cdd073498feb40955fb6860ea3c4d06c978a","src/api/math/float/cos.rs":"4c2dd7173728ef189314f1576c9486e03be21b7da98843b2f9011282a7979e31","src/api/math/float/exp.rs":"7c6d5f1e304f498a01cfa23b92380c815d7da0ad94eae3483783bc377d287eef","src/api/math/float/ln.rs":"54c7583f3df793b39ff57534fade27b41bb992439e5dc178252f5ca3190a3e54","src/api/math/float/mul_add.rs":"62cac77660d20159276d4c9ef066eb90c81cbddb808e8e157182c607625ad2eb","src/api/math/float/mul_adde.rs":"bae056ee9f3a70df39ec3c3b2f6437c65303888a7b843ef1a5bcf1f5aca0e602","src/api/math/float/powf.rs":"9ddb938984b36d39d82a82f862f80df8f7fb013f1d222d45698d41d88472f568","src/api/math/float/recpre.rs":"589225794ff1dbf31158dff660e6d4509ecc8befbb57c633900dea5ac0b840d6","src/api/math/float/rsqrte.rs":"a32abdcc318d7ccc8448231f54d75b884b7cbeb03a7d595713ab6243036f4dbf","src/api/math/float/sin.rs":"cbd3622b7df74f19691743001c8cf747a201f8977ad90542fee915f37dcd1e49","src/api/math/float/sqrt.rs":"0c66d5d63fb08e4d99c6b82a8828e41173aff1ac9fa1a2764a11fac217ccf2ac","src/api/math/float/sqrte.rs":"731e1c9f321b662accdd27dacb3aac2e8043b7aecb2f2161dde733bd9f025362","src/api/math/float/tanh.rs":"e57940434cc05981b086f0f3b92d32caceb38d67b90aebce5d3ed8e07c80538f","src/api/minimal.rs":"1f22bcc528555444e76de569ec0ae2029b9ae9d04805efeafa93369c8098036b","src/api/minimal/iuf.rs":"819cff26d3e196f807645bcc1d79eb27d9f175edb89910f2274d52a1e913cd11","src/api/minimal/mask.rs":"0cae10ae1fc65f5070e686c0c79bfba27b86b33d6c399367bd4848fb367dcec4","src/api/minimal/ptr.rs":"f74d7a4925d7209faebc26ea8315259cb2c08ec65789a70869e595649a9bc39a","src/api/ops.rs":"3e273b277a0f3019d42c3c59ca94a5afd4885d5ae6d2182e5089bbeec9de42ee","src/api/ops/scalar_arithmetic.rs":"d2d5ad897a59dd0787544f927e0e7ca4072c3e58b0f4a2324083312b0d5a21d7","src/api/ops/scalar_bitwise.rs":"482204e459ca6be79568e1c9f70adbe2d2151412ddf122fb2161be8ebb51c40c","src/api/ops/scalar_mask_bitwise.rs":"c250f52042e37b22d57256c80d4604104cfd2fbe2a2e127c676267270ca5d350","src/api/ops/scalar_shifts.rs":"c4773d435c3f9da4454327e6fbb2b5b41a1c0ebb1cca7372e69dc7a344a1b6e4","src/api/ops/vector_arithmetic.rs":"ddca15d09ddeef502c2ed66117a62300ca65d87e959e8b622d767bdf1c307910","src/api/ops/vector_bitwise.rs":"b3968f7005b649edcc22a54e2379b14d5ee19045f2e784029805781ae043b5ee","src/api/ops/vector_float_min_max.rs":"76bf8cb607e2c442923c1da1061a6b80d742d607408033c2a3761161114cf2a0","src/api/ops/vector_int_min_max.rs":"a378789c6ff9b32a51fbd0a97ffd36ed102cd1fe6a067d2b02017c1df342def6","src/api/ops/vector_mask_bitwise.rs":"5052d18517d765415d40327e6e8e55a312daaca0a5e2aec959bfa54b1675f9c8","src/api/ops/vector_neg.rs":"5c62f6b0221983cdbd23cd0a3af3672e6ba1255f0dfe8b19aae6fbd6503e231b","src/api/ops/vector_rotates.rs":"6c3f761d9d551f6365a8a95539ceace4b1a02e0b12d144f34ed68db94e88cff4","src/api/ops/vector_shifts.rs":"e510be14127c0ffd58a2573a39701da3557d66bedec09837ac8bbd44d579da00","src/api/ptr.rs":"8a793251bed6130dcfb2f1519ceaa18b751bbb15875928d0fb6deb5a5e07523a","src/api/ptr/gather_scatter.rs":"3d614f9d5b4ca201a9f7e46af4405e1d2c28ecee1620297c23b52e37b92cc0ea","src/api/reductions.rs":"ae5baca81352ecd44526d6c30c0a1feeda475ec73ddd3c3ec6b14e944e5448ee","src/api/reductions/bitwise.rs":"8bf910ae226188bd15fc7e125f058cd2566b6186fcd0cd8fd020f352c39ce139","src/api/reductions/float_arithmetic.rs":"47a5679896db2cbb56c31372fe42143da015b6beae7db5d2f3a0309ddf427ae1","src/api/reductions/integer_arithmetic.rs":"c2df3cf7493cca4174f2c65aea422a3d20d8a23af03f8d57cef72c19fee8f20d","src/api/reductions/mask.rs":"db83327a950e33a317f37fd33ca4e20c347fb415975ec024f3e23da8509425af","src/api/reductions/min_max.rs":"6af8c9aa45c69961b1b6fc205395f4767d4421869fb105fb3d563c5605fc13cd","src/api/select.rs":"6b07e7e8026df561f7307221a896f0fbb272536f41b9109040ac094c24c69331","src/api/shuffle.rs":"be7faff9b59654926df12897b2f98a4baa7d6acf2af1aaf93d388ba6e96f83ec","src/api/shuffle1_dyn.rs":"bfea5a91905b31444e9ef7ca6eddb7a9606b7e22d3f71bb842eb2795a0346620","src/api/slice.rs":"ee87484e8af329547b9a5d4f2a69e8bed6ea10bbd96270d706083843d4eea2ac","src/api/slice/from_slice.rs":"3735363000737104a8fc5f394ad8c31ec14e885952bd57647dd2a84001aee0a6","src/api/slice/write_to_slice.rs":"79d09c64d00724783c77c42e4583eeec97b18db94cf2ae146b564c3f85cfefd6","src/api/swap_bytes.rs":"05b4262eaade2f63e6cd3b780c19a03aecd2459d4cc4360051fc088887179a6e","src/codegen.rs":"db4f232fb9f5728db310b87dc8c4733be48afacab1053798c06106bef9a42b05","src/codegen/bit_manip.rs":"525ea6ff7ad1e043b6f6136992166f1803ed5563b7f6fc292c1c40257d20e264","src/codegen/llvm.rs":"12e748b4928c3be6cc12b4165c3041a3d0efccf6195338ecd3d88b8fdb0bbcc7","src/codegen/math.rs":"dfcf02ad34e2fdfe22c3f1cc2822001cc895e65031b4d06e585e5047839febb7","src/codegen/math/float.rs":"b2f31f479c5c70a6ff9ad33872c1e65506f72882b77a2e3f9e71c42e92af9355","src/codegen/math/float/abs.rs":"d5aaadcf540bdb9b4264dca6471a255fd7bf509e763bef0239c0144a68466fea","src/codegen/math/float/cos.rs":"17f28d2900c852dca221fa9c92a9cd5fe7fd2df8d427bbc60216c749b2be013d","src/codegen/math/float/cos_pi.rs":"dbaf9f443f9846a491d4ec52210a7b5835dd593b03366e3135b05c37d70f9d6c","src/codegen/math/float/exp.rs":"d300058a4bcc7ae7976f216f81902cd73a9e603ad63880dff3bbc866c27a9f37","src/codegen/math/float/ln.rs":"c851e211e43f8256093ba75b03ae0c307c9962ee66d94f09b4dd80068190cbdf","src/codegen/math/float/macros.rs":"fc9924869ed85e4795983af228cacf23158f4f35919adce16c920ad4a3f0a009","src/codegen/math/float/mul_add.rs":"041a5b69d5991d93ef795351b17560c10faf80b78fd26ad7df42a239b32cf9de","src/codegen/math/float/mul_adde.rs":"d71d5f0f3333b62a7439b823cb7adf5340ea1555ce820fb4a3f4cb922f73f5f5","src/codegen/math/float/powf.rs":"9742c3877f1a5509ca5c9492a40884b6579ba6dd11c26b7112e63f70666b395d","src/codegen/math/float/sin.rs":"0e9868d35531566509f3a01d85d5253045eb4afa8525d8407dcc1f5f33c56036","src/codegen/math/float/sin_cos_pi.rs":"8e6b6142d7dd240cdb36669722e82ab9810a2261e86e659f7d97a942ad8b1258","src/codegen/math/float/sin_pi.rs":"bb6d39db8f921e03a301fc5206ac1a61a97def8a2cb83b87ccf189f3fc48d548","src/codegen/math/float/sqrt.rs":"e6ebb0c5f428efad1f672b9a8fe4e58534dbf1ea5a8fe092ce5ce76b52fe89cb","src/codegen/math/float/sqrte.rs":"23acfaea38d0e081a6d9021c1094e813d0cfd12c58c1eca9662aade5e625d51c","src/codegen/math/float/tanh.rs":"816fd107f134920fb1a21cd792029d4b89306f6cf16d6f030cc1136823b033e7","src/codegen/pointer_sized_int.rs":"6ca13c214b6cf7e0929dbe18e96a16fc0bb7d8799608df29c4c8115490f99e01","src/codegen/reductions.rs":"8eb18ebac76985d2aa30262a2edd8cb004230b511a765d657525f677a585c12c","src/codegen/reductions/mask.rs":"e67f35a1f4d156a4894a2d6ea5a935b4d898cf70eefb2715f5c1cc165e776c11","src/codegen/reductions/mask/aarch64.rs":"84b101c17cad1ede4eb6d38cada0ac7da239dba8cea3badd3829b967e558431f","src/codegen/reductions/mask/arm.rs":"aaa07129bd078ae7e677cf8b8e67ec9f30536606a0c7ed1baaa18fd1793bb218","src/codegen/reductions/mask/fallback.rs":"3eb9319d2c7cf19216b607b8459612c4e027b643cf11b036937d36896bf76786","src/codegen/reductions/mask/fallback_impl.rs":"76547f396e55ef403327c77c314cf8db8c7a5c9b9819bfb925abeacf130249e5","src/codegen/reductions/mask/x86.rs":"36dcd8af4ab99730a078ed113d3955f74eb1a2876e2e6d9f224e0ff462c216d1","src/codegen/reductions/mask/x86/avx.rs":"3a40868b38c86e35aefb96d7578de6322efe89d8135e0366359b54ddd06f861a","src/codegen/reductions/mask/x86/avx2.rs":"677aed3f056285285daa3adff8bc65e739630b4424defa6d9665e160f027507e","src/codegen/reductions/mask/x86/sse.rs":"8522f6ed03f6c32dd577d4298df477c08aeaaa38563706f29096e1911ed731f2","src/codegen/reductions/mask/x86/sse2.rs":"54ec56e49b0c6841eccb719e4f310d65fe767c04136b2ec20bd8b9d7d9897b9e","src/codegen/shuffle.rs":"1ec2930f4e1acc43ac30b518af298d466a79e9e75734a51c380b7810efd1a27f","src/codegen/shuffle1_dyn.rs":"3f13ca1597378758d05106bf5ff3715eee531f3cb6d88f48b9182bd6c9386b51","src/codegen/swap_bytes.rs":"c67c86e91ca3fc77539e0efcea081a3c62548cccf503963ae408f2e86f4e6a21","src/codegen/v128.rs":"94226b31ec403d18d9d2fe06713f147c9c79e9b5f9105089088266313f843185","src/codegen/v16.rs":"ddec4ffb66b6f7aaffb9a1780c5ddba82557abd74f45073d335047e04cf74924","src/codegen/v256.rs":"6b63917f0444118d6b1595bff2045e59b97c4d24012bd575f69f1f0efc5a0241","src/codegen/v32.rs":"3477b3c5540aed86e61e2f5807dd31db947413cec9181c587d93ed6ec74f0eba","src/codegen/v512.rs":"5854f99d3aabc4cd42b28a20d9ce447756dc2ba024a409a69b6a8ae1f1842fc5","src/codegen/v64.rs":"e9e89caebfe63d10c0cbca61e4dfdba3b7e02ee0989170f80beed23237ddd950","src/codegen/vPtr.rs":"f0753b405cdc865bdf8e82c6505f299ea1f96136239ebbaf7f9ce93d310764b8","src/codegen/vSize.rs":"c89f5fdeb28ac4c8272ed1816fce03d9d95308cc32bb2533bd8b20cd5ac102ac","src/lib.rs":"05048c6a85ec65cf902d9dd8f757a3f76392b703a6794ea71f0d41500a89f78f","src/masks.rs":"70fc0abe4c2907ce2a491c574e1cfb9f3423385da2e1a923a48c9c13f8ba6ed8","src/sealed.rs":"ae7fdeaf5d84cd7710ed730ca72ca7eaba93df6cb0acb183e5c0a7327acf197f","src/testing.rs":"896669c08d8c801448a4d2fadc9d633eda0fbe879d229997e2a182e31278e469","src/testing/macros.rs":"403bbc5ecb7c786fe36156df302d0c07a8122408dbb15f7474d7682224ba1106","src/testing/utils.rs":"41912a92266dfe884647fc035e4242fd746100df8e839808ae0397af3759a3c8","src/v128.rs":"16cf9a8e7156b899ee9b9cd3f2dba9d13ec63289bea8c3ee9ae2e43ad9510288","src/v16.rs":"cb6465cf1e00bf530183af1819b9fe3d7eec978f8765d5e85d9b58a39a4b4045","src/v256.rs":"fe235017da18c7f3c361831c60e3173ad304d8ea1e95d64ebebc79da2d708511","src/v32.rs":"145d347855bac59b2de6508f9e594654e6c330423af9edc0e2ac8f4d1abdf45e","src/v512.rs":"f372f277f3e62eb5c945bb1c460333fdb17b6974fcc876633788ff53bded9599","src/v64.rs":"0b8079881b71575e3414be0b7f8f7eaba65281ba6732f2b2f61f73e95b6f48f7","src/vPtr.rs":"8b3e433d487180bb4304ff71245ecad90f0010f43e139a72027b672abe58facc","src/vSize.rs":"eda5aa020706cbf94d15bada41a0c2a35fc8f3f37cb7c2cd6f34d201399a495e","tests/endianness.rs":"5147f86d224c4c540b772033da2f994cad9bc9c035f38ec21e23bc4e55f8a759"},"package":"1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d"} \ No newline at end of file
diff --git a/third_party/rust/packed_simd/Cargo.toml b/third_party/rust/packed_simd/Cargo.toml
deleted file mode 100644
index 77fc096b05..0000000000
--- a/third_party/rust/packed_simd/Cargo.toml
+++ /dev/null
@@ -1,83 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2018"
-name = "packed_simd"
-version = "0.3.9"
-build = "build.rs"
-description = "Portable Packed SIMD vectors"
-homepage = "https://github.com/rust-lang/packed_simd"
-documentation = "https://docs.rs/crate/packed_simd/"
-readme = "README.md"
-keywords = [
- "simd",
- "vector",
- "portability",
-]
-categories = [
- "hardware-support",
- "concurrency",
- "no-std",
- "data-structures",
-]
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/packed_simd"
-
-[package.metadata.docs.rs]
-features = ["into_bits"]
-rustdoc-args = [
- "--cfg",
- "doc_cfg",
-]
-
-[dependencies.cfg-if]
-version = "1.0.0"
-
-[dependencies.core_arch]
-version = "0.1.5"
-optional = true
-
-[dependencies.num-traits]
-version = "0.2.14"
-features = ["libm"]
-default-features = false
-
-[dev-dependencies.arrayvec]
-version = "^0.5"
-default-features = false
-
-[dev-dependencies.paste]
-version = "^1"
-
-[features]
-default = []
-into_bits = []
-libcore_neon = []
-
-[target."cfg(target_arch = \"x86_64\")".dependencies.sleef-sys]
-version = "0.1.2"
-optional = true
-
-[target.wasm32-unknown-unknown.dev-dependencies.wasm-bindgen]
-version = "=0.2.87"
-
-[target.wasm32-unknown-unknown.dev-dependencies.wasm-bindgen-test]
-version = "=0.3.37"
-
-[badges.is-it-maintained-issue-resolution]
-repository = "rust-lang/packed_simd"
-
-[badges.is-it-maintained-open-issues]
-repository = "rust-lang/packed_simd"
-
-[badges.maintenance]
-status = "experimental"
diff --git a/third_party/rust/packed_simd/README.md b/third_party/rust/packed_simd/README.md
deleted file mode 100644
index 59db13fe4f..0000000000
--- a/third_party/rust/packed_simd/README.md
+++ /dev/null
@@ -1,144 +0,0 @@
-# `Simd<[T; N]>`
-
-## Implementation of [Rust RFC #2366: `std::simd`][rfc2366]
-
-[![Latest Version]][crates.io] [![docs]][master_docs]
-
-**WARNING**: this crate only supports the most recent nightly Rust toolchain
-and will be superseded by [`#![feature(portable_simd)]`](https://github.com/rust-lang/portable-simd).
-
-## Documentation
-
-* [API docs (`master` branch)][master_docs]
-* [Performance guide][perf_guide]
-* [API docs (`docs.rs`)][docs.rs]
-* [RFC2366 `std::simd`][rfc2366]: - contains motivation, design rationale,
- discussion, etc.
-
-## Examples
-
-Most of the examples come with both a scalar and a vectorized implementation.
-
-* [`aobench`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/aobench)
-* [`fannkuch_redux`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/fannkuch_redux)
-* [`matrix inverse`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/matrix_inverse)
-* [`mandelbrot`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/mandelbrot)
-* [`n-body`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/nbody)
-* [`options_pricing`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/options_pricing)
-* [`spectral_norm`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/spectral_norm)
-* [`triangle transform`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/triangle_xform)
-* [`stencil`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/stencil)
-* [`vector dot product`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/dot_product)
-
-## Cargo features
-
-* `into_bits` (default: disabled): enables `FromBits`/`IntoBits` trait
- implementations for the vector types. These allow reinterpreting the bits of a
- vector type as those of another vector type safely by just using the
- `.into_bits()` method.
-
-## Performance
-
-The following [ISPC] examples are also part of `packed_simd`'s
-[`examples/`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples/)
-directory, where `packed_simd`+[`rayon`][rayon] are used to emulate [ISPC]'s
-Single-Program-Multiple-Data (SPMD) programming model. The performance results
-on different hardware is shown in the `readme.md` of each example. The following
-table summarizes the performance ranges, where `+` means speed-up and `-`
-slowdown:
-
-* `aobench`: `[-1.02x, +1.53x]`,
-* `stencil`: `[+1.06x, +1.72x]`,
-* `mandelbrot`: `[-1.74x, +1.2x]`,
-* `options_pricing`:
- * `black_scholes`: `+1.0x`
- * `binomial_put`: `+1.4x`
-
- While SPMD is not the intended use case for `packed_simd`, it is possible to
- combine the library with [`rayon`][rayon] to poorly emulate [ISPC]'s SPMD programming
- model in Rust. Writing performant code is not as straightforward as with
- [ISPC], but with some care (e.g. see the [Performance Guide][perf_guide]) one
- can easily match and often out-perform [ISPC]'s "default performance".
-
-## Platform support
-
-The following table describes the supported platforms: `build` shows whether
-the library compiles without issues for a given target, while `run` shows
-whether the test suite passes for a given target.
-
-| **Linux** | **build** | **run** |
-|---------------------------------------|-----------|---------|
-| `i586-unknown-linux-gnu` | ✓ | ✗ |
-| `i686-unknown-linux-gnu` | ✓ | ✗ |
-| `x86_64-unknown-linux-gnu` | ✓ | ✓ |
-| `arm-unknown-linux-gnueabihf` | ✓ | ✓ |
-| `armv7-unknown-linux-gnueabi` | ✓ | ✓ |
-| `aarch64-unknown-linux-gnu` | ✓ | ✓ |
-| `powerpc-unknown-linux-gnu` | ✓ | ✗ |
-| `powerpc64-unknown-linux-gnu` | ✓ | ✗ |
-| `powerpc64le-unknown-linux-gnu` | ✓ | ✓ |
-| `s390x-unknown-linux-gnu` | ✓ | ✗ |
-| `sparc64-unknown-linux-gnu` | ✓ | ✗ |
-| `thumbv7neon-unknown-linux-gnueabihf` | ✓ | ✓ |
-| **MacOSX** | **build** | **run** |
-| `x86_64-apple-darwin` | ✓ | ✓ |
-| **Android** | **build** | **run** |
-| `x86_64-linux-android` | ✓ | ✓ |
-| `armv7-linux-androideabi` | ✓ | ✗ |
-| `aarch64-linux-android` | ✓ | ✗ |
-| `thumbv7neon-linux-androideabi` | ✓ | ✗ |
-| **iOS** | **build** | **run** |
-| `x86_64-apple-ios` | ✗ | ✗ |
-| `aarch64-apple-ios` | ✗ | ✗ |
-
-
-## Machine code verification
-
-The
-[`verify/`](https://github.com/rust-lang-nursery/packed_simd/tree/master/verify)
-crate tests disassembles the portable packed vector APIs at run-time and
-compares the generated machine code against the desired one to make sure that
-this crate remains efficient.
-
-## License
-
-This project is licensed under either of
-
-* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
- ([LICENSE-APACHE](LICENSE-APACHE))
-
-* [MIT License](http://opensource.org/licenses/MIT)
- ([LICENSE-MIT](LICENSE-MIT))
-
-at your option.
-
-## Contributing
-
-We welcome all people who want to contribute.
-Please see the [contributing instructions] for more information.
-
-Contributions in any form (issues, pull requests, etc.) to this project
-must adhere to Rust's [Code of Conduct].
-
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in `packed_simd` by you, as defined in the Apache-2.0 license, shall be
-dual licensed as above, without any additional terms or conditions.
-
-[travis]: https://travis-ci.com/rust-lang/packed_simd
-[Travis-CI Status]: https://travis-ci.com/rust-lang/packed_simd.svg?branch=master
-[appveyor]: https://ci.appveyor.com/project/gnzlbg/packed-simd
-[Appveyor Status]: https://ci.appveyor.com/api/projects/status/hd7v9dvr442hgdix?svg=true
-[Latest Version]: https://img.shields.io/crates/v/packed_simd.svg
-[crates.io]: https://crates.io/crates/packed_simd
-[docs]: https://docs.rs/packed_simd/badge.svg
-[docs.rs]: https://docs.rs/packed_simd
-[master_docs]: https://rust-lang-nursery.github.io/packed_simd/packed_simd/
-[perf_guide]: https://rust-lang-nursery.github.io/packed_simd/perf-guide/
-[rfc2366]: https://github.com/rust-lang/rfcs/pull/2366
-[ISPC]: https://ispc.github.io/
-[rayon]: https://crates.io/crates/rayon
-[boost_license]: https://www.boost.org/LICENSE_1_0.txt
-[SLEEF]: https://sleef.org/
-[sleef_sys]: https://crates.io/crates/sleef-sys
-[contributing instructions]: contributing.md
-[Code of Conduct]: https://www.rust-lang.org/en-US/conduct.html
diff --git a/third_party/rust/packed_simd/bors.toml b/third_party/rust/packed_simd/bors.toml
deleted file mode 100644
index 6d302dc85c..0000000000
--- a/third_party/rust/packed_simd/bors.toml
+++ /dev/null
@@ -1,3 +0,0 @@
-status = [
- "continuous-integration/travis-ci/push"
-] \ No newline at end of file
diff --git a/third_party/rust/packed_simd/build.rs b/third_party/rust/packed_simd/build.rs
deleted file mode 100644
index e87298a2de..0000000000
--- a/third_party/rust/packed_simd/build.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
- let target = std::env::var("TARGET").expect("TARGET environment variable not defined");
- if target.contains("neon") {
- println!("cargo:rustc-cfg=libcore_neon");
- }
-}
diff --git a/third_party/rust/packed_simd/ci/all.sh b/third_party/rust/packed_simd/ci/all.sh
deleted file mode 100755
index 55a1fa2efe..0000000000
--- a/third_party/rust/packed_simd/ci/all.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env bash
-#
-# Performs an operation on all targets
-
-set -ex
-
-: "${1?The all.sh script requires one argument.}"
-
-op=$1
-
-cargo_clean() {
- cargo clean
-}
-
-cargo_check_fmt() {
- cargo fmt --all -- --check
-}
-
-cargo_fmt() {
- cargo fmt --all
-}
-
-cargo_clippy() {
- cargo clippy --all -- -D clippy::perf
-}
-
-CMD="-1"
-
-case $op in
- clean*)
- CMD=cargo_clean
- ;;
- check_fmt*)
- CMD=cargo_check_fmt
- ;;
- fmt*)
- CMD=cargo_fmt
- ;;
- clippy)
- CMD=cargo_clippy
- ;;
- *)
- echo "Unknown operation: \"${op}\""
- exit 1
- ;;
-esac
-
-echo "Operation is: ${CMD}"
-
-# On src/
-$CMD
-
-# Check examples/
-for dir in examples/*/
-do
- dir=${dir%*/}
- (
- cd "${dir%*/}"
- $CMD
- )
-done
-
-(
- cd verify/verify
- $CMD
-)
-
-(
- cd micro_benchmarks
- $CMD
-)
diff --git a/third_party/rust/packed_simd/ci/android-install-ndk.sh b/third_party/rust/packed_simd/ci/android-install-ndk.sh
deleted file mode 100644
index 5370853937..0000000000
--- a/third_party/rust/packed_simd/ci/android-install-ndk.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env sh
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-ANDROID_NDK_URL=https://dl.google.com/android/repository
-ANDROID_NDK_ARCHIVE=android-ndk-r25b-linux.zip
-
-curl -fO "$ANDROID_NDK_URL/$ANDROID_NDK_ARCHIVE"
-unzip -q $ANDROID_NDK_ARCHIVE
-rm $ANDROID_NDK_ARCHIVE
-mv android-ndk-* ndk
-rm -rf android-ndk-*
diff --git a/third_party/rust/packed_simd/ci/android-install-sdk.sh b/third_party/rust/packed_simd/ci/android-install-sdk.sh
deleted file mode 100644
index 6b5ac09ab0..0000000000
--- a/third_party/rust/packed_simd/ci/android-install-sdk.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env sh
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-# Prep the SDK and emulator
-#
-# Note that the update process requires that we accept a bunch of licenses, and
-# we can't just pipe `yes` into it for some reason, so we take the same strategy
-# located in https://github.com/appunite/docker by just wrapping it in a script
-# which apparently magically accepts the licenses.
-
-mkdir sdk
-curl --retry 5 https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip -O
-unzip -d sdk sdk-tools-linux-3859397.zip
-
-case "$1" in
- arm | armv7)
- abi=armeabi-v7a
- ;;
-
- aarch64)
- abi=arm64-v8a
- ;;
-
- i686)
- abi=x86
- ;;
-
- x86_64)
- abi=x86_64
- ;;
-
- *)
- echo "invalid arch: $1"
- exit 1
- ;;
-esac;
-
-# --no_https avoids
- # javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
-yes | ./sdk/tools/bin/sdkmanager --licenses --no_https
-yes | ./sdk/tools/bin/sdkmanager --no_https \
- "emulator" \
- "platform-tools" \
- "platforms;android-24" \
- "system-images;android-24;default;$abi"
-
-echo "no" |
- ./sdk/tools/bin/avdmanager create avd \
- --name "${1}" \
- --package "system-images;android-24;default;$abi"
diff --git a/third_party/rust/packed_simd/ci/android-sysimage.sh b/third_party/rust/packed_simd/ci/android-sysimage.sh
deleted file mode 100644
index 9eabd7c8d9..0000000000
--- a/third_party/rust/packed_simd/ci/android-sysimage.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-URL=https://dl.google.com/android/repository/sys-img/android
-
-main() {
- local arch="${1}"
- local name="${2}"
- local dest=/system
- local td
- td="$(mktemp -d)"
-
- apt-get install --no-install-recommends e2tools
-
- pushd "${td}"
- curl --retry 5 -O "${URL}/${name}"
- unzip -q "${name}"
-
- local system
- system="$(find . -name system.img)"
- mkdir -p ${dest}/{bin,lib,lib64}
-
- # Extract android linker and libraries to /system
- # This allows android executables to be run directly (or with qemu)
- if [ "${arch}" = "x86_64" ] || [ "${arch}" = "arm64" ]; then
- e2cp -p "${system}:/bin/linker64" "${dest}/bin/"
- e2cp -p "${system}:/lib64/libdl.so" "${dest}/lib64/"
- e2cp -p "${system}:/lib64/libc.so" "${dest}/lib64/"
- e2cp -p "${system}:/lib64/libm.so" "${dest}/lib64/"
- else
- e2cp -p "${system}:/bin/linker" "${dest}/bin/"
- e2cp -p "${system}:/lib/libdl.so" "${dest}/lib/"
- e2cp -p "${system}:/lib/libc.so" "${dest}/lib/"
- e2cp -p "${system}:/lib/libm.so" "${dest}/lib/"
- fi
-
- # clean up
- apt-get purge --auto-remove -y e2tools
-
- popd
-
- rm -rf "${td}"
-}
-
-main "${@}"
diff --git a/third_party/rust/packed_simd/ci/benchmark.sh b/third_party/rust/packed_simd/ci/benchmark.sh
deleted file mode 100755
index 3635b9e371..0000000000
--- a/third_party/rust/packed_simd/ci/benchmark.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env bash
-#
-# Runs all benchmarks. Controlled by the following environment variables:
-#
-# FEATURES={} - cargo features to pass to all benchmarks (e.g. core_arch,sleef-sys,ispc)
-# NORUN={1} - only builds the benchmarks
-
-set -ex
-
-if [[ ${NORUN} != 1 ]]; then
- # Most benchmarks require hyperfine; require it upfront.
- hash hyperfine 2>/dev/null || { echo >&2 "hyperfine is not in PATH."; exit 1; }
-fi
-
-
-# If the ispc benchmark feature is enabled, ispc must be in the path of the
-# benchmarks.
-if echo "$FEATURES" | grep -q "ispc"; then
- hash ispc 2>/dev/null || { echo >&2 "ispc is not in PATH."; exit 1; }
-fi
-
-# An example with a benchmark.sh is a benchmark:
-for dir in examples/*/
-do
- dir=${dir%*/}
- cd ${dir%*/}
- if [ -f "benchmark.sh" ]; then
- ./benchmark.sh
- fi
- cd -
-done
-
diff --git a/third_party/rust/packed_simd/ci/deploy_and_run_on_ios_simulator.rs b/third_party/rust/packed_simd/ci/deploy_and_run_on_ios_simulator.rs
deleted file mode 100644
index c0fe52c356..0000000000
--- a/third_party/rust/packed_simd/ci/deploy_and_run_on_ios_simulator.rs
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This is a script to deploy and execute a binary on an iOS simulator.
-// The primary use of this is to be able to run unit tests on the simulator and
-// retrieve the results.
-//
-// To do this through Cargo instead, use Dinghy
-// (https://github.com/snipsco/dinghy): cargo dinghy install, then cargo dinghy
-// test.
-
-use std::env;
-use std::fs::{self, File};
-use std::io::Write;
-use std::path::Path;
-use std::process;
-use std::process::Command;
-
-macro_rules! t {
- ($e:expr) => (match $e {
- Ok(e) => e,
- Err(e) => panic!("{} failed with: {}", stringify!($e), e),
- })
-}
-
-// Step one: Wrap as an app
-fn package_as_simulator_app(crate_name: &str, test_binary_path: &Path) {
- println!("Packaging simulator app");
- drop(fs::remove_dir_all("ios_simulator_app"));
- t!(fs::create_dir("ios_simulator_app"));
- t!(fs::copy(test_binary_path,
- Path::new("ios_simulator_app").join(crate_name)));
-
- let mut f = t!(File::create("ios_simulator_app/Info.plist"));
- t!(f.write_all(format!(r#"
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE plist PUBLIC
- "-//Apple//DTD PLIST 1.0//EN"
- "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
- <plist version="1.0">
- <dict>
- <key>CFBundleExecutable</key>
- <string>{}</string>
- <key>CFBundleIdentifier</key>
- <string>com.rust.unittests</string>
- </dict>
- </plist>
- "#, crate_name).as_bytes()));
-}
-
-// Step two: Start the iOS simulator
-fn start_simulator() {
- println!("Looking for iOS simulator");
- let output = t!(Command::new("xcrun").arg("simctl").arg("list").output());
- assert!(output.status.success());
- let mut simulator_exists = false;
- let mut simulator_booted = false;
- let mut found_rust_sim = false;
- let stdout = t!(String::from_utf8(output.stdout));
- for line in stdout.lines() {
- if line.contains("rust_ios") {
- if found_rust_sim {
- panic!("Duplicate rust_ios simulators found. Please \
- double-check xcrun simctl list.");
- }
- simulator_exists = true;
- simulator_booted = line.contains("(Booted)");
- found_rust_sim = true;
- }
- }
-
- if simulator_exists == false {
- println!("Creating iOS simulator");
- Command::new("xcrun")
- .arg("simctl")
- .arg("create")
- .arg("rust_ios")
- .arg("com.apple.CoreSimulator.SimDeviceType.iPhone-SE")
- .arg("com.apple.CoreSimulator.SimRuntime.iOS-10-2")
- .check_status();
- } else if simulator_booted == true {
- println!("Shutting down already-booted simulator");
- Command::new("xcrun")
- .arg("simctl")
- .arg("shutdown")
- .arg("rust_ios")
- .check_status();
- }
-
- println!("Starting iOS simulator");
- // We can't uninstall the app (if present) as that will hang if the
- // simulator isn't completely booted; just erase the simulator instead.
- Command::new("xcrun").arg("simctl").arg("erase").arg("rust_ios").check_status();
- Command::new("xcrun").arg("simctl").arg("boot").arg("rust_ios").check_status();
-}
-
-// Step three: Install the app
-fn install_app_to_simulator() {
- println!("Installing app to simulator");
- Command::new("xcrun")
- .arg("simctl")
- .arg("install")
- .arg("booted")
- .arg("ios_simulator_app/")
- .check_status();
-}
-
-// Step four: Run the app
-fn run_app_on_simulator() {
- println!("Running app");
- let output = t!(Command::new("xcrun")
- .arg("simctl")
- .arg("launch")
- .arg("--console")
- .arg("booted")
- .arg("com.rust.unittests")
- .output());
-
- println!("stdout --\n{}\n", String::from_utf8_lossy(&output.stdout));
- println!("stderr --\n{}\n", String::from_utf8_lossy(&output.stderr));
-
- let stdout = String::from_utf8_lossy(&output.stdout);
- let failed = stdout.lines()
- .find(|l| l.contains("FAILED"))
- .map(|l| l.contains("FAILED"))
- .unwrap_or(false);
-
- let passed = stdout.lines()
- .find(|l| l.contains("test result: ok"))
- .map(|l| l.contains("test result: ok"))
- .unwrap_or(false);
-
- println!("Shutting down simulator");
- Command::new("xcrun")
- .arg("simctl")
- .arg("shutdown")
- .arg("rust_ios")
- .check_status();
- if !(passed && !failed) {
- panic!("tests didn't pass");
- }
-}
-
-trait CheckStatus {
- fn check_status(&mut self);
-}
-
-impl CheckStatus for Command {
- fn check_status(&mut self) {
- println!("\trunning: {:?}", self);
- assert!(t!(self.status()).success());
- }
-}
-
-fn main() {
- let args: Vec<String> = env::args().collect();
- if args.len() != 2 {
- println!("Usage: {} <executable>", args[0]);
- process::exit(-1);
- }
-
- let test_binary_path = Path::new(&args[1]);
- let crate_name = test_binary_path.file_name().unwrap();
-
- package_as_simulator_app(crate_name.to_str().unwrap(), test_binary_path);
- start_simulator();
- install_app_to_simulator();
- run_app_on_simulator();
-}
diff --git a/third_party/rust/packed_simd/ci/docker/aarch64-linux-android/Dockerfile b/third_party/rust/packed_simd/ci/docker/aarch64-linux-android/Dockerfile
deleted file mode 100644
index 27bde89c5a..0000000000
--- a/third_party/rust/packed_simd/ci/docker/aarch64-linux-android/Dockerfile
+++ /dev/null
@@ -1,47 +0,0 @@
-FROM ubuntu:16.04
-
-RUN dpkg --add-architecture i386 && \
- apt-get update && \
- apt-get install -y --no-install-recommends \
- file \
- make \
- curl \
- ca-certificates \
- python \
- unzip \
- expect \
- openjdk-9-jre \
- libstdc++6:i386 \
- libpulse0 \
- gcc \
- libc6-dev
-
-WORKDIR /android/
-COPY android* /android/
-
-ENV ANDROID_ARCH=aarch64
-ENV PATH=$PATH:/android/ndk-$ANDROID_ARCH/bin:/android/sdk/tools:/android/sdk/platform-tools
-
-RUN sh /android/android-install-ndk.sh $ANDROID_ARCH
-RUN sh /android/android-install-sdk.sh $ANDROID_ARCH
-RUN mv /root/.android /tmp
-RUN chmod 777 -R /tmp/.android
-RUN chmod 755 /android/sdk/tools/* /android/sdk/emulator/qemu/linux-x86_64/*
-
-ENV PATH=$PATH:/rust/bin \
- CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android-gcc \
- CARGO_TARGET_AARCH64_LINUX_ANDROID_RUNNER=/tmp/runtest \
- OBJDUMP=aarch64-linux-android-objdump \
- HOME=/tmp
-
-ADD runtest-android.rs /tmp/runtest.rs
-ENTRYPOINT [ \
- "bash", \
- "-c", \
- # set SHELL so android can detect a 64bits system, see
- # http://stackoverflow.com/a/41789144
- "SHELL=/bin/dash /android/sdk/emulator/emulator @aarch64 -no-window & \
- rustc /tmp/runtest.rs -o /tmp/runtest && \
- exec \"$@\"", \
- "--" \
-]
diff --git a/third_party/rust/packed_simd/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/aarch64-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 41ff4729ac..0000000000
--- a/third_party/rust/packed_simd/ci/docker/aarch64-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,14 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- ca-certificates \
- libc6-dev \
- gcc-aarch64-linux-gnu \
- libc6-dev-arm64-cross \
- qemu-user \
- make \
- file
-
-ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
- CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-aarch64 -L /usr/aarch64-linux-gnu" \
- OBJDUMP=aarch64-linux-gnu-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabi/Dockerfile b/third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabi/Dockerfile
deleted file mode 100644
index e1c591dd97..0000000000
--- a/third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabi/Dockerfile
+++ /dev/null
@@ -1,15 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- ca-certificates \
- libc6-dev \
- libc6-armel-cross \
- libc6-dev-armel-cross \
- binutils-arm-linux-gnueabi \
- gcc-arm-linux-gnueabi \
- qemu-user \
- make \
- file
-ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_LINKER=arm-linux-gnueabi-gcc \
- CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_RUNNER="qemu-arm -L /usr/arm-linux-gnueabi" \
- OBJDUMP=arm-linux-gnueabi-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile
deleted file mode 100644
index 757b79e7ec..0000000000
--- a/third_party/rust/packed_simd/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- ca-certificates \
- libc6-dev \
- gcc-arm-linux-gnueabihf \
- libc6-dev-armhf-cross \
- qemu-user \
- make \
- file
-ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
- CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \
- OBJDUMP=arm-linux-gnueabihf-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/armv7-linux-androideabi/Dockerfile b/third_party/rust/packed_simd/ci/docker/armv7-linux-androideabi/Dockerfile
deleted file mode 100644
index 995a9e30e6..0000000000
--- a/third_party/rust/packed_simd/ci/docker/armv7-linux-androideabi/Dockerfile
+++ /dev/null
@@ -1,47 +0,0 @@
-FROM ubuntu:16.04
-
-RUN dpkg --add-architecture i386 && \
- apt-get update && \
- apt-get install -y --no-install-recommends \
- file \
- make \
- curl \
- ca-certificates \
- python \
- unzip \
- expect \
- openjdk-9-jre \
- libstdc++6:i386 \
- libpulse0 \
- gcc \
- libc6-dev
-
-WORKDIR /android/
-COPY android* /android/
-
-ENV ANDROID_ARCH=arm
-ENV PATH=$PATH:/android/ndk-$ANDROID_ARCH/bin:/android/sdk/tools:/android/sdk/platform-tools
-
-RUN sh /android/android-install-ndk.sh $ANDROID_ARCH
-RUN sh /android/android-install-sdk.sh $ANDROID_ARCH
-RUN mv /root/.android /tmp
-RUN chmod 777 -R /tmp/.android
-RUN chmod 755 /android/sdk/tools/* /android/sdk/emulator/qemu/linux-x86_64/*
-
-ENV PATH=$PATH:/rust/bin \
- CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
- CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER=/tmp/runtest \
- OBJDUMP=arm-linux-androideabi-objdump \
- HOME=/tmp
-
-ADD runtest-android.rs /tmp/runtest.rs
-ENTRYPOINT [ \
- "bash", \
- "-c", \
- # set SHELL so android can detect a 64bits system, see
- # http://stackoverflow.com/a/41789144
- "SHELL=/bin/dash /android/sdk/emulator/emulator @arm -no-window & \
- rustc /tmp/runtest.rs -o /tmp/runtest && \
- exec \"$@\"", \
- "--" \
-]
diff --git a/third_party/rust/packed_simd/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/third_party/rust/packed_simd/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile
deleted file mode 100644
index 2539062933..0000000000
--- a/third_party/rust/packed_simd/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- ca-certificates \
- libc6-dev \
- gcc-arm-linux-gnueabihf \
- libc6-dev-armhf-cross \
- qemu-user \
- make \
- file
-ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
- CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \
- OBJDUMP=arm-linux-gnueabihf-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/i586-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/i586-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 01093698f6..0000000000
--- a/third_party/rust/packed_simd/ci/docker/i586-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc-multilib \
- libc6-dev \
- file \
- make \
- ca-certificates
diff --git a/third_party/rust/packed_simd/ci/docker/i686-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/i686-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 01093698f6..0000000000
--- a/third_party/rust/packed_simd/ci/docker/i686-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc-multilib \
- libc6-dev \
- file \
- make \
- ca-certificates
diff --git a/third_party/rust/packed_simd/ci/docker/mips-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/mips-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 3bd471e87d..0000000000
--- a/third_party/rust/packed_simd/ci/docker/mips-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu:18.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc libc6-dev qemu-user ca-certificates \
- gcc-mips-linux-gnu libc6-dev-mips-cross \
- qemu-system-mips \
- qemu-user \
- make \
- file
-
-ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER=mips-linux-gnu-gcc \
- CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER="qemu-mips -L /usr/mips-linux-gnu" \
- OBJDUMP=mips-linux-gnu-objdump \ No newline at end of file
diff --git a/third_party/rust/packed_simd/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/third_party/rust/packed_simd/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile
deleted file mode 100644
index f26f1f38eb..0000000000
--- a/third_party/rust/packed_simd/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile
+++ /dev/null
@@ -1,10 +0,0 @@
-FROM ubuntu:18.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc libc6-dev qemu-user ca-certificates \
- gcc-mips64-linux-gnuabi64 libc6-dev-mips64-cross \
- qemu-system-mips64 qemu-user
-
-ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_LINKER=mips64-linux-gnuabi64-gcc \
- CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_RUNNER="qemu-mips64 -L /usr/mips64-linux-gnuabi64" \
- OBJDUMP=mips64-linux-gnuabi64-objdump \ No newline at end of file
diff --git a/third_party/rust/packed_simd/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile b/third_party/rust/packed_simd/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile
deleted file mode 100644
index 7d9f0bd992..0000000000
--- a/third_party/rust/packed_simd/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile
+++ /dev/null
@@ -1,10 +0,0 @@
-FROM ubuntu:18.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc libc6-dev qemu-user ca-certificates \
- gcc-mips64el-linux-gnuabi64 libc6-dev-mips64el-cross \
- qemu-system-mips64el
-
-ENV CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_LINKER=mips64el-linux-gnuabi64-gcc \
- CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_RUNNER="qemu-mips64el -L /usr/mips64el-linux-gnuabi64" \
- OBJDUMP=mips64el-linux-gnuabi64-objdump \ No newline at end of file
diff --git a/third_party/rust/packed_simd/ci/docker/mipsel-unknown-linux-musl/Dockerfile b/third_party/rust/packed_simd/ci/docker/mipsel-unknown-linux-musl/Dockerfile
deleted file mode 100644
index 7488662ef2..0000000000
--- a/third_party/rust/packed_simd/ci/docker/mipsel-unknown-linux-musl/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-FROM ubuntu:18.10
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- ca-certificates \
- gcc \
- libc6-dev \
- make \
- qemu-user \
- qemu-system-mips \
- bzip2 \
- curl \
- file
-
-RUN mkdir /toolchain
-
-# Note that this originally came from:
-# https://downloads.openwrt.org/snapshots/trunk/malta/generic/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2
-RUN curl -L https://ci-mirrors.rust-lang.org/libc/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \
- tar xjf - -C /toolchain --strip-components=2
-
-ENV PATH=$PATH:/rust/bin:/toolchain/bin \
- CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
- CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER=mipsel-openwrt-linux-gcc \
- CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_RUNNER="qemu-mipsel -L /toolchain"
diff --git a/third_party/rust/packed_simd/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/powerpc-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 15ba58e60c..0000000000
--- a/third_party/rust/packed_simd/ci/docker/powerpc-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc libc6-dev qemu-user ca-certificates \
- gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \
- qemu-system-ppc \
- make \
- file
-
-ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER=powerpc-linux-gnu-gcc \
- CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER="qemu-ppc -cpu Vger -L /usr/powerpc-linux-gnu" \
- CC=powerpc-linux-gnu-gcc \
- OBJDUMP=powerpc-linux-gnu-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 21c296dc44..0000000000
--- a/third_party/rust/packed_simd/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,17 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- ca-certificates \
- libc6-dev \
- gcc-powerpc64-linux-gnu \
- libc6-dev-ppc64-cross \
- qemu-user \
- qemu-system-ppc \
- make \
- file
-
-ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER=powerpc64-linux-gnu-gcc \
- CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER="qemu-ppc64 -L /usr/powerpc64-linux-gnu" \
- CC=powerpc64-linux-gnu-gcc \
- OBJDUMP=powerpc64-linux-gnu-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 8034145fc0..0000000000
--- a/third_party/rust/packed_simd/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,11 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc libc6-dev qemu-user ca-certificates \
- gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \
- qemu-system-ppc file make
-
-ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER=powerpc64le-linux-gnu-gcc \
- CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER="qemu-ppc64le -L /usr/powerpc64le-linux-gnu" \
- CC=powerpc64le-linux-gnu-gcc \
- OBJDUMP=powerpc64le-linux-gnu-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/s390x-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/s390x-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index e785ca370c..0000000000
--- a/third_party/rust/packed_simd/ci/docker/s390x-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,20 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- ca-certificates \
- curl \
- cmake \
- gcc \
- libc6-dev \
- g++-s390x-linux-gnu \
- libc6-dev-s390x-cross \
- qemu-user \
- make \
- file
-
-ENV CARGO_TARGET_S390X_UNKNOWN_LINUX_GNU_LINKER=s390x-linux-gnu-gcc \
- CARGO_TARGET_S390X_UNKNOWN_LINUX_GNU_RUNNER="qemu-s390x -L /usr/s390x-linux-gnu" \
- CC_s390x_unknown_linux_gnu=s390x-linux-gnu-gcc \
- CXX_s390x_unknown_linux_gnu=s390x-linux-gnu-g++ \
- OBJDUMP=s390x-linux-gnu-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/sparc64-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/sparc64-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index c35f4d8f31..0000000000
--- a/third_party/rust/packed_simd/ci/docker/sparc64-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,18 +0,0 @@
-FROM debian:bookworm
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- curl ca-certificates \
- gcc libc6-dev \
- gcc-sparc64-linux-gnu libc6-dev-sparc64-cross \
- qemu-system-sparc64 openbios-sparc seabios ipxe-qemu \
- p7zip-full cpio
-
-COPY linux-sparc64.sh /
-RUN bash /linux-sparc64.sh
-
-COPY test-runner-linux /
-
-ENV CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER=sparc64-linux-gnu-gcc \
- CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_RUNNER="/test-runner-linux sparc64" \
- CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
- PATH=$PATH:/rust/bin
diff --git a/third_party/rust/packed_simd/ci/docker/thumbv7neon-linux-androideabi/Dockerfile b/third_party/rust/packed_simd/ci/docker/thumbv7neon-linux-androideabi/Dockerfile
deleted file mode 100644
index c1da77109c..0000000000
--- a/third_party/rust/packed_simd/ci/docker/thumbv7neon-linux-androideabi/Dockerfile
+++ /dev/null
@@ -1,47 +0,0 @@
-FROM ubuntu:16.04
-
-RUN dpkg --add-architecture i386 && \
- apt-get update && \
- apt-get install -y --no-install-recommends \
- file \
- make \
- curl \
- ca-certificates \
- python \
- unzip \
- expect \
- openjdk-9-jre \
- libstdc++6:i386 \
- libpulse0 \
- gcc \
- libc6-dev
-
-WORKDIR /android/
-COPY android* /android/
-
-ENV ANDROID_ARCH=arm
-ENV PATH=$PATH:/android/ndk-$ANDROID_ARCH/bin:/android/sdk/tools:/android/sdk/platform-tools
-
-RUN sh /android/android-install-ndk.sh $ANDROID_ARCH
-RUN sh /android/android-install-sdk.sh $ANDROID_ARCH
-RUN mv /root/.android /tmp
-RUN chmod 777 -R /tmp/.android
-RUN chmod 755 /android/sdk/tools/* /android/sdk/emulator/qemu/linux-x86_64/*
-
-ENV PATH=$PATH:/rust/bin \
- CARGO_TARGET_THUMBV7NEON_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
- CARGO_TARGET_THUMBV7NEON_LINUX_ANDROIDEABI_RUNNER=/tmp/runtest \
- OBJDUMP=arm-linux-androideabi-objdump \
- HOME=/tmp
-
-ADD runtest-android.rs /tmp/runtest.rs
-ENTRYPOINT [ \
- "bash", \
- "-c", \
- # set SHELL so android can detect a 64bits system, see
- # http://stackoverflow.com/a/41789144
- "SHELL=/bin/dash /android/sdk/emulator/emulator @arm -no-window & \
- rustc /tmp/runtest.rs -o /tmp/runtest && \
- exec \"$@\"", \
- "--" \
-]
diff --git a/third_party/rust/packed_simd/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile b/third_party/rust/packed_simd/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile
deleted file mode 100644
index 588d23c65a..0000000000
--- a/third_party/rust/packed_simd/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- ca-certificates \
- libc6-dev \
- gcc-arm-linux-gnueabihf \
- libc6-dev-armhf-cross \
- qemu-user \
- make \
- file
-ENV CARGO_TARGET_THUMBV7NEON_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
- CARGO_TARGET_THUMBV7NEON_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \
- OBJDUMP=arm-linux-gnueabihf-objdump
diff --git a/third_party/rust/packed_simd/ci/docker/wasm32-unknown-unknown/Dockerfile b/third_party/rust/packed_simd/ci/docker/wasm32-unknown-unknown/Dockerfile
deleted file mode 100644
index 51ee13e6c9..0000000000
--- a/third_party/rust/packed_simd/ci/docker/wasm32-unknown-unknown/Dockerfile
+++ /dev/null
@@ -1,39 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update -y && apt-get install -y --no-install-recommends \
- ca-certificates \
- clang \
- cmake \
- curl \
- git \
- libc6-dev \
- make \
- ninja-build \
- python-is-python3 \
- xz-utils
-
-# Install `wasm2wat`
-RUN git clone --recursive https://github.com/WebAssembly/wabt
-RUN make -C wabt -j$(nproc)
-ENV PATH=$PATH:/wabt/bin
-
-# Install `wasm-bindgen-test-runner`
-RUN curl -L https://github.com/rustwasm/wasm-bindgen/releases/download/0.2.87/wasm-bindgen-0.2.87-x86_64-unknown-linux-musl.tar.gz \
- | tar xzf -
-# Keep in sync with the version on Cargo.toml.
-ENV PATH=$PATH:/wasm-bindgen-0.2.87-x86_64-unknown-linux-musl
-ENV CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner
-
-# Install `node`
-RUN curl https://nodejs.org/dist/v14.16.0/node-v14.16.0-linux-x64.tar.xz | tar xJf -
-ENV PATH=$PATH:/node-v14.16.0-linux-x64/bin
-
-# We use a shim linker that removes `--strip-debug` when passed to LLD. While
-# this typically results in invalid debug information in release mode it doesn't
-# result in an invalid names section which is what we're interested in.
-COPY lld-shim.rs /
-ENV CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_LINKER=/tmp/lld-shim
-
-# Rustc isn't available until this container starts, so defer compilation of the
-# shim.
-ENTRYPOINT /rust/bin/rustc /lld-shim.rs -o /tmp/lld-shim && exec bash "$@"
diff --git a/third_party/rust/packed_simd/ci/docker/x86_64-linux-android/Dockerfile b/third_party/rust/packed_simd/ci/docker/x86_64-linux-android/Dockerfile
deleted file mode 100644
index 785936d347..0000000000
--- a/third_party/rust/packed_simd/ci/docker/x86_64-linux-android/Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-FROM ubuntu:20.04
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- ca-certificates \
- curl \
- gcc \
- libc-dev \
- python \
- unzip \
- file \
- make
-
-WORKDIR /android/
-ENV ANDROID_ARCH=x86_64
-COPY android-install-ndk.sh /android/
-RUN sh /android/android-install-ndk.sh
-
-ENV STDARCH_ASSERT_INSTR_LIMIT=30
-
-# We do not run x86_64-linux-android tests on an android emulator.
-# See ci/android-sysimage.sh for informations about how tests are run.
-COPY android-sysimage.sh /android/
-RUN bash /android/android-sysimage.sh x86_64 x86_64-24_r07.zip
-
-ENV PATH=$PATH:/rust/bin:/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin \
- CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android21-clang \
- CC_x86_64_linux_android=x86_64-linux-android21-clang \
- CXX_x86_64_linux_android=x86_64-linux-android21-clang++ \
- OBJDUMP=llvm-objdump \
- HOME=/tmp
diff --git a/third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile b/third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile
deleted file mode 100644
index a6bbe66539..0000000000
--- a/third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile
+++ /dev/null
@@ -1,16 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- libc6-dev \
- file \
- make \
- ca-certificates \
- wget \
- bzip2 \
- cmake \
- libclang-dev \
- clang
-
-RUN wget https://github.com/gnzlbg/intel_sde/raw/master/sde-external-8.16.0-2018-01-30-lin.tar.bz2
-RUN tar -xjf sde-external-8.16.0-2018-01-30-lin.tar.bz2
-ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="/sde-external-8.16.0-2018-01-30-lin/sde64 --"
diff --git a/third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index ce5bb88e62..0000000000
--- a/third_party/rust/packed_simd/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,10 +0,0 @@
-FROM ubuntu:18.04
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gcc \
- libc6-dev \
- file \
- make \
- ca-certificates \
- cmake \
- libclang-dev \
- clang
diff --git a/third_party/rust/packed_simd/ci/dox.sh b/third_party/rust/packed_simd/ci/dox.sh
deleted file mode 100755
index 560eaadcc8..0000000000
--- a/third_party/rust/packed_simd/ci/dox.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-set -ex
-
-rm -rf target/doc
-mkdir -p target/doc
-
-# Build API documentation
-cargo doc --features=into_bits
-
-# Build Performance Guide
-# FIXME: https://github.com/rust-lang-nursery/mdBook/issues/780
-# mdbook build perf-guide -d target/doc/perf-guide
-cd perf-guide
-mdbook build
-cd -
-cp -r perf-guide/book target/doc/perf-guide
-
-# If we're on travis, not a PR, and on the right branch, publish!
-if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then
- python3 -vV
- pip -vV
- python3.9 -vV
- pip install ghp_import --user
- ghp-import -n target/doc
- git push -qf https://${GH_PAGES}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
-fi
diff --git a/third_party/rust/packed_simd/ci/linux-s390x.sh b/third_party/rust/packed_simd/ci/linux-s390x.sh
deleted file mode 100644
index 972abeec56..0000000000
--- a/third_party/rust/packed_simd/ci/linux-s390x.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-set -ex
-
-mkdir -m 777 /qemu
-cd /qemu
-
-curl -LO https://github.com/qemu/qemu/raw/master/pc-bios/s390-ccw.img
-curl -LO http://ftp.debian.org/debian/dists/testing/main/installer-s390x/20170828/images/generic/kernel.debian
-curl -LO http://ftp.debian.org/debian/dists/testing/main/installer-s390x/20170828/images/generic/initrd.debian
-
-mv kernel.debian kernel
-mv initrd.debian initrd.gz
-
-mkdir init
-cd init
-gunzip -c ../initrd.gz | cpio -id
-rm ../initrd.gz
-cp /usr/s390x-linux-gnu/lib/libgcc_s.so.1 usr/lib/
-chmod a+w .
diff --git a/third_party/rust/packed_simd/ci/linux-sparc64.sh b/third_party/rust/packed_simd/ci/linux-sparc64.sh
deleted file mode 100644
index 4452b120e1..0000000000
--- a/third_party/rust/packed_simd/ci/linux-sparc64.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-set -ex
-
-mkdir -m 777 /qemu
-cd /qemu
-
-curl -LO https://cdimage.debian.org/cdimage/ports/9.0/sparc64/iso-cd/debian-9.0-sparc64-NETINST-1.iso
-7z e debian-9.0-sparc64-NETINST-1.iso boot/initrd.gz
-7z e debian-9.0-sparc64-NETINST-1.iso boot/sparc64
-mv sparc64 kernel
-rm debian-9.0-sparc64-NETINST-1.iso
-
-mkdir init
-cd init
-gunzip -c ../initrd.gz | cpio -id
-rm ../initrd.gz
-cp /usr/sparc64-linux-gnu/lib/libgcc_s.so.1 usr/lib/
-chmod a+w .
diff --git a/third_party/rust/packed_simd/ci/lld-shim.rs b/third_party/rust/packed_simd/ci/lld-shim.rs
deleted file mode 100644
index 10263869e8..0000000000
--- a/third_party/rust/packed_simd/ci/lld-shim.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-use std::os::unix::prelude::*;
-use std::process::Command;
-use std::env;
-
-fn main() {
- let args = env::args()
- .skip(1)
- .filter(|s| s != "--strip-debug")
- .collect::<Vec<_>>();
- panic!("failed to exec: {}", Command::new("rust-lld").args(&args).exec());
-}
diff --git a/third_party/rust/packed_simd/ci/max_line_width.sh b/third_party/rust/packed_simd/ci/max_line_width.sh
deleted file mode 100755
index f70639b6f8..0000000000
--- a/third_party/rust/packed_simd/ci/max_line_width.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env sh
-
-set -x
-
-export success=true
-
-find . -iname '*.rs' | while read -r file; do
- result=$(grep '.\{79\}' "${file}" | grep --invert 'http')
- if [ "${result}" = "" ]
- then
- :
- else
- echo "file \"${file}\": $result"
- exit 1
- fi
-done
-
diff --git a/third_party/rust/packed_simd/ci/run-docker.sh b/third_party/rust/packed_simd/ci/run-docker.sh
deleted file mode 100755
index abdd6852fc..0000000000
--- a/third_party/rust/packed_simd/ci/run-docker.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-# Small script to run tests for a target (or all targets) inside all the
-# respective docker images.
-
-set -ex
-
-run() {
- echo "Building docker container for TARGET=${TARGET} RUSTFLAGS=${RUSTFLAGS}"
- docker build -t packed_simd -f ci/docker/${TARGET}/Dockerfile ci/
- mkdir -p target
- target=$(echo "${TARGET}" | sed 's/-emulated//')
- echo "Running docker"
- docker run \
- --user `id -u`:`id -g` \
- --rm \
- --init \
- --volume $HOME/.cargo:/cargo \
- --env CARGO_HOME=/cargo \
- --volume `rustc --print sysroot`:/rust:ro \
- --env TARGET=$target \
- --env NORUN \
- --env NOVERIFY \
- --env RUSTFLAGS \
- --volume `pwd`:/checkout:ro \
- --volume `pwd`/target:/checkout/target \
- --workdir /checkout \
- --privileged \
- packed_simd \
- bash \
- -c 'PATH=$PATH:/rust/bin exec ci/run.sh'
-}
-
-if [ -z "${TARGET}" ]; then
- for d in `ls ci/docker/`; do
- run $d
- done
-else
- run ${TARGET}
-fi
diff --git a/third_party/rust/packed_simd/ci/run.sh b/third_party/rust/packed_simd/ci/run.sh
deleted file mode 100755
index b1b22ebd7c..0000000000
--- a/third_party/rust/packed_simd/ci/run.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-: ${TARGET?"The TARGET environment variable must be set."}
-
-# Tests are all super fast anyway, and they fault often enough on travis that
-# having only one thread increases debuggability to be worth it.
-#export RUST_TEST_THREADS=1
-#export RUST_BACKTRACE=full
-#export RUST_TEST_NOCAPTURE=1
-
-# Some appveyor builds run out-of-memory; this attempts to mitigate that:
-# https://github.com/rust-lang-nursery/packed_simd/issues/39
-# export RUSTFLAGS="${RUSTFLAGS} -C codegen-units=1"
-# export CARGO_BUILD_JOBS=1
-
-export CARGO_SUBCMD=test
-if [[ "${NORUN}" == "1" ]]; then
- export CARGO_SUBCMD=build
-fi
-
-if [[ ${TARGET} == "x86_64-apple-ios" ]] || [[ ${TARGET} == "i386-apple-ios" ]]; then
- export RUSTFLAGS="${RUSTFLAGS} -Clink-arg=-mios-simulator-version-min=7.0"
- rustc ./ci/deploy_and_run_on_ios_simulator.rs -o $HOME/runtest
- export CARGO_TARGET_X86_64_APPLE_IOS_RUNNER=$HOME/runtest
- export CARGO_TARGET_I386_APPLE_IOS_RUNNER=$HOME/runtest
-fi
-
-# The source directory is read-only. Need to copy internal crates to the target
-# directory for their Cargo.lock to be properly written.
-mkdir target || true
-
-rustc --version
-cargo --version
-echo "TARGET=${TARGET}"
-echo "HOST=${HOST}"
-echo "RUSTFLAGS=${RUSTFLAGS}"
-echo "NORUN=${NORUN}"
-echo "NOVERIFY=${NOVERIFY}"
-echo "CARGO_SUBCMD=${CARGO_SUBCMD}"
-echo "CARGO_BUILD_JOBS=${CARGO_BUILD_JOBS}"
-echo "CARGO_INCREMENTAL=${CARGO_INCREMENTAL}"
-echo "RUST_TEST_THREADS=${RUST_TEST_THREADS}"
-echo "RUST_BACKTRACE=${RUST_BACKTRACE}"
-echo "RUST_TEST_NOCAPTURE=${RUST_TEST_NOCAPTURE}"
-
-cargo_test() {
- cmd="cargo ${CARGO_SUBCMD} --verbose --target=${TARGET} ${@}"
- if [ "${NORUN}" != "1" ]
- then
- if [ "$TARGET" != "wasm32-unknown-unknown" ]
- then
- cmd="$cmd -- --quiet"
- fi
- fi
- mkdir target || true
- ${cmd} 2>&1 | tee > target/output
- if [[ ${PIPESTATUS[0]} != 0 ]]; then
- cat target/output
- return 1
- fi
-}
-
-cargo_test_impl() {
- ORIGINAL_RUSTFLAGS=${RUSTFLAGS}
- RUSTFLAGS="${ORIGINAL_RUSTFLAGS} --cfg test_v16 --cfg test_v32 --cfg test_v64" cargo_test ${@}
- RUSTFLAGS="${ORIGINAL_RUSTFLAGS} --cfg test_v128 --cfg test_v256" cargo_test ${@}
- RUSTFLAGS="${ORIGINAL_RUSTFLAGS} --cfg test_v512" cargo_test ${@}
- RUSTFLAGS=${ORIGINAL_RUSTFLAGS}
-}
-
-# Debug run:
-if [[ "${TARGET}" != "wasm32-unknown-unknown" ]]; then
- # Run wasm32-unknown-unknown in release mode only
- cargo_test_impl
-fi
-
-if [[ "${TARGET}" == "x86_64-unknown-linux-gnu" ]] || [[ "${TARGET}" == "x86_64-pc-windows-msvc" ]]; then
- # use sleef on linux and windows x86_64 builds
- # FIXME: Use `core_arch,sleef-sys` features once they works again
- cargo_test_impl --release --features=into_bits
-else
- # FIXME: Use `core_arch` feature once it works again
- cargo_test_impl --release --features=into_bits
-fi
-
-# Verify code generation
-if [[ "${NOVERIFY}" != "1" ]]; then
- cp -r verify/verify target/verify
- export STDSIMD_ASSERT_INSTR_LIMIT=30
- if [[ "${TARGET}" == "i586-unknown-linux-gnu" ]]; then
- export STDSIMD_ASSERT_INSTR_LIMIT=50
- fi
- cargo_test --release --manifest-path=target/verify/Cargo.toml
-fi
-
-# FIXME: Figure out which examples take too long to run and ignore or adjust those
-#. ci/run_examples.sh
diff --git a/third_party/rust/packed_simd/ci/run_examples.sh b/third_party/rust/packed_simd/ci/run_examples.sh
deleted file mode 100644
index 5b26b18afb..0000000000
--- a/third_party/rust/packed_simd/ci/run_examples.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-# Runs all examples.
-
-# FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/55
-# All examples fail to build for `armv7-apple-ios`.
-if [[ ${TARGET} == "armv7-apple-ios" ]]; then
- exit 0
-fi
-
-# FIXME: travis exceeds 50 minutes on these targets
-# Skipping the examples is an attempt at preventing travis from timing-out
-if [[ ${TARGET} == "arm-linux-androidabi" ]] || [[ ${TARGET} == "aarch64-linux-androidabi" ]] \
- || [[ ${TARGET} == "sparc64-unknown-linux-gnu" ]]; then
- exit 0
-fi
-
-if [[ ${TARGET} == "wasm32-unknown-unknown" ]]; then
- exit 0
-fi
-
-cp -r examples/aobench target/aobench
-cargo_test --manifest-path=target/aobench/Cargo.toml --release --no-default-features
-cargo_test --manifest-path=target/aobench/Cargo.toml --release --features=256bit
-
-cp -r examples/dot_product target/dot_product
-cargo_test --manifest-path=target/dot_product/Cargo.toml --release
-
-cp -r examples/fannkuch_redux target/fannkuch_redux
-cargo_test --manifest-path=target/fannkuch_redux/Cargo.toml --release
-
-# FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/56
-if [[ ${TARGET} != "i586-unknown-linux-gnu" ]]; then
- cp -r examples/mandelbrot target/mandelbrot
- cargo_test --manifest-path=target/mandelbrot/Cargo.toml --release
-fi
-
-cp -r examples/matrix_inverse target/matrix_inverse
-cargo_test --manifest-path=target/matrix_inverse/Cargo.toml --release
-
-cp -r examples/nbody target/nbody
-cargo_test --manifest-path=target/nbody/Cargo.toml --release
-
-cp -r examples/spectral_norm target/spectral_norm
-cargo_test --manifest-path=target/spectral_norm/Cargo.toml --release
-
-if [[ ${TARGET} != "i586-unknown-linux-gnu" ]]; then
- cp -r examples/stencil target/stencil
- cargo_test --manifest-path=target/stencil/Cargo.toml --release
-fi
-
-cp -r examples/triangle_xform target/triangle_xform
-cargo_test --manifest-path=target/triangle_xform/Cargo.toml --release
diff --git a/third_party/rust/packed_simd/ci/runtest-android.rs b/third_party/rust/packed_simd/ci/runtest-android.rs
deleted file mode 100644
index ed1cd80c83..0000000000
--- a/third_party/rust/packed_simd/ci/runtest-android.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use std::env;
-use std::process::Command;
-use std::path::{Path, PathBuf};
-
-fn main() {
- let args = env::args_os()
- .skip(1)
- .filter(|arg| arg != "--quiet")
- .collect::<Vec<_>>();
- assert_eq!(args.len(), 1);
- let test = PathBuf::from(&args[0]);
- let dst = Path::new("/data/local/tmp").join(test.file_name().unwrap());
-
- let status = Command::new("adb")
- .arg("wait-for-device")
- .status()
- .expect("failed to run: adb wait-for-device");
- assert!(status.success());
-
- let status = Command::new("adb")
- .arg("push")
- .arg(&test)
- .arg(&dst)
- .status()
- .expect("failed to run: adb pushr");
- assert!(status.success());
-
- let output = Command::new("adb")
- .arg("shell")
- .arg(&dst)
- .output()
- .expect("failed to run: adb shell");
- assert!(status.success());
-
- println!("status: {}\nstdout ---\n{}\nstderr ---\n{}",
- output.status,
- String::from_utf8_lossy(&output.stdout),
- String::from_utf8_lossy(&output.stderr));
-
- let stdout = String::from_utf8_lossy(&output.stdout);
- let mut lines = stdout.lines().filter(|l| l.starts_with("test result"));
- if !lines.all(|l| l.contains("test result: ok") && l.contains("0 failed")) {
- panic!("failed to find successful test run");
- }
-}
diff --git a/third_party/rust/packed_simd/ci/setup_benchmarks.sh b/third_party/rust/packed_simd/ci/setup_benchmarks.sh
deleted file mode 100755
index cd41a78513..0000000000
--- a/third_party/rust/packed_simd/ci/setup_benchmarks.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-# Get latest ISPC binary for the target and put it in the path
-git clone https://github.com/gnzlbg/ispc-binaries
-cp ispc-binaries/ispc-${TARGET} ispc
diff --git a/third_party/rust/packed_simd/ci/test-runner-linux b/third_party/rust/packed_simd/ci/test-runner-linux
deleted file mode 100755
index 0654f63bfd..0000000000
--- a/third_party/rust/packed_simd/ci/test-runner-linux
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-set -e
-
-arch=$1
-prog=$2
-
-cd /qemu/init
-cp -f $2 prog
-find . | cpio --create --format='newc' --quiet | gzip > ../initrd.gz
-cd ..
-
-timeout 30s qemu-system-$arch \
- -m 1024 \
- -nographic \
- -kernel kernel \
- -initrd initrd.gz \
- -append init=/prog > output || true
-
-# remove kernel messages
-tr -d '\r' < output | egrep -v '^\['
-
-# if the output contains a failure, return error
-! grep FAILED output > /dev/null
diff --git a/third_party/rust/packed_simd/contributing.md b/third_party/rust/packed_simd/contributing.md
deleted file mode 100644
index 79af8c199e..0000000000
--- a/third_party/rust/packed_simd/contributing.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Contributing to `packed_simd`
-
-Welcome! If you are reading this document, it means you are interested in contributing
-to the `packed_simd` crate.
-
-## Reporting issues
-
-All issues with this crate are tracked using GitHub's [Issue Tracker].
-
-You can use issues to bring bugs to the attention of the maintainers, to discuss
-certain problems encountered with the crate, or to request new features (although
-feature requests should be limited to things mentioned in the [RFC]).
-
-One thing to keep in mind is to always use the **latest** nightly toolchain when
-working on this crate. Due to the nature of this project, we use a lot of unstable
-features, meaning breakage happens often.
-
-[Issue Tracker]: https://github.com/rust-lang-nursery/packed_simd/issues
-[RFC]: https://github.com/rust-lang/rfcs/pull/2366
-
-### LLVM issues
-
-The Rust compiler relies on [LLVM](https://llvm.org/) for machine code generation,
-and quite a few LLVM bugs have been discovered during the development of this project.
-
-If you encounter issues with incorrect/suboptimal codegen, which you do not encounter
-when using the [SIMD vendor intrinsics](https://doc.rust-lang.org/nightly/std/arch/),
-it is likely the issue is with LLVM, or this crate's interaction with it.
-
-You should first open an issue **in this repo** to help us track the problem, and we
-will help determine what is the exact cause of the problem.
-If LLVM is indeed the cause, the issue will be reported upstream to the
-[LLVM bugtracker](https://bugs.llvm.org/).
-
-## Submitting Pull Requests
-
-New code is submitted to the crate using GitHub's [pull request] mechanism.
-You should first fork this repository, make your changes (preferably in a new
-branch), then use GitHub's web UI to create a new PR.
-
-[pull request]: https://help.github.com/articles/about-pull-requests/
-
-### Examples
-
-The `examples` directory contains code showcasing SIMD code written with this crate,
-usually in comparison to scalar or ISPC code. If you have a project / idea which
-uses SIMD, we'd love to add it to the examples list.
-
-Every example should include a small `README`, describing the example code's purpose.
-If your example could potentially work as a benchmark, then add a `benchmark.sh`
-script to allow running the example benchmark code in CI. See an existing example's
-[`benchmark.sh`](examples/aobench/benchmark.sh) for a sample.
-
-Don't forget to update the crate's top-level `README` with a link to your example.
-
-### Perf guide
-
-The objective of the [performance guide][perf-guide] is to be a comprehensive
-resource detailing the process of optimizing Rust code with SIMD support.
-
-If you believe a certain section could be reworded, or if you have any tips & tricks
-related to SIMD which you'd like to share, please open a PR.
-
-[mdBook] is used to manage the formatting of the guide as a book.
-
-[perf-guide]: https://rust-lang-nursery.github.io/packed_simd/perf-guide/
-[mdBook]: https://github.com/rust-lang-nursery/mdBook
diff --git a/third_party/rust/packed_simd/perf-guide/book.toml b/third_party/rust/packed_simd/perf-guide/book.toml
deleted file mode 100644
index 69ba3053ca..0000000000
--- a/third_party/rust/packed_simd/perf-guide/book.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[book]
-authors = ["Gonzalo Brito Gadeschi", "Gabriel Majeri"]
-multilingual = false
-src = "src"
-title = "Rust SIMD Performance Guide"
-description = "This book describes how to write performant SIMD code in Rust."
-
-[build]
-create-missing = false
-
-[output.html]
-additional-css = ["./src/ascii.css"]
diff --git a/third_party/rust/packed_simd/perf-guide/src/SUMMARY.md b/third_party/rust/packed_simd/perf-guide/src/SUMMARY.md
deleted file mode 100644
index 1e76898865..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/SUMMARY.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Summary
-
-[Introduction](./introduction.md)
-
-- [Floating-point Math](./float-math/fp.md)
- - [Short-vector Math Library](./float-math/svml.md)
- - [Approximate functions](./float-math/approx.md)
- - [Fused multiply-accumulate](./float-math/fma.md)
-
-- [Target features](./target-feature/features.md)
- - [Using `RUSTFLAGS`](./target-feature/rustflags.md)
- - [Using the `target_feature` attribute](./target-feature/attribute.md)
- - [Interaction with inlining](./target-feature/inlining.md)
- - [Detecting features at runtime](./target-feature/runtime.md)
-
-- [Bounds checking](./bound_checks.md)
-- [Vertical and horizontal operations](./vert-hor-ops.md)
-
-- [Performance profiling](./prof/profiling.md)
- - [Profiling on Linux](./prof/linux.md)
- - [Using machine code analyzers](./prof/mca.md)
diff --git a/third_party/rust/packed_simd/perf-guide/src/ascii.css b/third_party/rust/packed_simd/perf-guide/src/ascii.css
deleted file mode 100644
index 4c02651195..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/ascii.css
+++ /dev/null
@@ -1,4 +0,0 @@
-code {
- /* "Source Code Pro" breaks ASCII art */
- font-family: Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace;
-}
diff --git a/third_party/rust/packed_simd/perf-guide/src/bound_checks.md b/third_party/rust/packed_simd/perf-guide/src/bound_checks.md
deleted file mode 100644
index 2eeedb5ac8..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/bound_checks.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Bounds checking
-
-Reading and writing packed vectors to/from slices is checked by default.
-Independently of the configuration options used, the safe functions:
-
-* `Simd<[T; N]>::from_slice_aligned(& s[..])`
-* `Simd<[T; N]>::write_to_slice_aligned(&mut s[..])`
-
-always check that:
-
-* the slice is big enough to hold the vector
-* the slice is suitably aligned to perform an aligned load/store for a `Simd<[T;
- N]>` (this alignment is often much larger than that of `T`).
-
-There are `_unaligned` versions that use unaligned load and stores, as well as
-`unsafe` `_unchecked` that do not perform any checks iff `debug-assertions =
-false` / `debug = false`. That is, the `_unchecked` methods do still assert size
-and alignment in debug builds and could also do so in release builds depending
-on the configuration options.
-
-These assertions do often significantly impact performance and you should be
-aware of them.
diff --git a/third_party/rust/packed_simd/perf-guide/src/float-math/approx.md b/third_party/rust/packed_simd/perf-guide/src/float-math/approx.md
deleted file mode 100644
index 2237c67ec4..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/float-math/approx.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Approximate functions
-
-<!-- TODO:
-
-Explain that they exists, that they are often _much_ faster, how to use them,
-that people should check whether the error is good enough for their
-applications. Explain that this error is currently unstable and might change.
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/float-math/fma.md b/third_party/rust/packed_simd/perf-guide/src/float-math/fma.md
deleted file mode 100644
index 357748383d..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/float-math/fma.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Fused Multiply Add
-
-<!-- TODO:
-Explain that this is a compound operation, infinite precision, difference
-between `mul_add` and `mul_adde`, that LLVM cannot do this by itself, etc.
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/float-math/fp.md b/third_party/rust/packed_simd/perf-guide/src/float-math/fp.md
deleted file mode 100644
index 711fcc4fd5..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/float-math/fp.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Floating-point math
-
-This chapter contains information pertaining to working with floating-point numbers.
diff --git a/third_party/rust/packed_simd/perf-guide/src/float-math/svml.md b/third_party/rust/packed_simd/perf-guide/src/float-math/svml.md
deleted file mode 100644
index 266c2531cc..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/float-math/svml.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Short Vector Math Library
-
-<!-- TODO:
-Explain how is short-vector math performed by default (just scalarized libm calls).
-
-Explain how to enable `sleef`, etc.
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/introduction.md b/third_party/rust/packed_simd/perf-guide/src/introduction.md
deleted file mode 100644
index 7243e19c8a..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/introduction.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Introduction
-
-## What is SIMD
-
-<!-- TODO:
-describe what SIMD is, which algorithms can benefit from it,
-give usage examples
--->
-
-## History of SIMD in Rust
-
-<!-- TODO:
-discuss history of unstable std::simd,
-stabilization of std::arch, etc.
--->
-
-## Discover packed_simd
-
-<!-- TODO: describe scope of this project -->
-
-Writing fast and portable SIMD algorithms using `packed_simd` is, unfortunately,
-not trivial. There are many pitfals that one should be aware of, and some idioms
-that help avoid those pitfalls.
-
-This book attempts to document these best practices and provides practical examples
-on how to apply the tips to _your_ code.
diff --git a/third_party/rust/packed_simd/perf-guide/src/prof/linux.md b/third_party/rust/packed_simd/perf-guide/src/prof/linux.md
deleted file mode 100644
index 96c7d67bc4..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/prof/linux.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# Performance profiling on Linux
-
-## Using `perf`
-
-[perf](https://perf.wiki.kernel.org/) is the most powerful performance profiler
-for Linux, featuring support for various hardware Performance Monitoring Units,
-as well as integration with the kernel's performance events framework.
-
-We will only look at how can the `perf` command can be used to profile SIMD code.
-Full system profiling is outside of the scope of this book.
-
-### Recording
-
-The first step is to record a program's execution during an average workload.
-It helps if you can isolate the parts of your program which have performance
-issues, and set up a benchmark which can be easily (re)run.
-
-Build the benchmark binary in release mode, after having enabled debug info:
-
-```sh
-$ cargo build --release
-Finished release [optimized + debuginfo] target(s) in 0.02s
-```
-
-Then use the `perf record` subcommand:
-
-```sh
-$ perf record --call-graph=dwarf ./target/release/my-program
-[ perf record: Woken up 10 times to write data ]
-[ perf record: Captured and wrote 2,356 MB perf.data (292 samples) ]
-```
-
-Instead of using `--call-graph=dwarf`, which can become pretty slow, you can use
-`--call-graph=lbr` if you have a processor with support for Last Branch Record
-(i.e. Intel Haswell and newer).
-
-`perf` will, by default, record the count of CPU cycles it takes to execute
-various parts of your program. You can use the `-e` command line option
-to enable other performance events, such as `cache-misses`. Use `perf list`
-to get a list of all hardware counters supported by your CPU.
-
-### Viewing the report
-
-The next step is getting a bird's eye view of the program's execution.
-`perf` provides a `ncurses`-based interface which will get you started.
-
-Use `perf report` to open a visualization of your program's performance:
-
-```sh
-perf report --hierarchy -M intel
-```
-
-`--hierarchy` will display a tree-like structure of where your program spent
-most of its time. `-M intel` enables disassembly output with Intel syntax, which
-is subjectively more readable than the default AT&T syntax.
-
-Here is the output from profiling the `nbody` benchmark:
-
-```
-- 100,00% nbody
- - 94,18% nbody
- + 93,48% [.] nbody_lib::simd::advance
- + 0,70% [.] nbody_lib::run
- + 5,06% libc-2.28.so
-```
-
-If you move with the arrow keys to any node in the tree, you can the press `a`
-to have `perf` _annotate_ that node. This means it will:
-
-- disassemble the function
-
-- associate every instruction with the percentage of time which was spent executing it
-
-- interleaves the disassembly with the source code,
- assuming it found the debug symbols
- (you can use `s` to toggle this behaviour)
-
-`perf` will, by default, open the instruction which it identified as being the
-hottest spot in the function:
-
-```
-0,76 │ movapd xmm2,xmm0
-0,38 │ movhlps xmm2,xmm0
- │ addpd xmm2,xmm0
- │ unpcklpd xmm1,xmm2
-12,50 │ sqrtpd xmm0,xmm1
-1,52 │ mulpd xmm0,xmm1
-```
-
-In this case, `sqrtpd` will be highlighted in red, since that's the instruction
-which the CPU spends most of its time executing.
-
-## Using Valgrind
-
-Valgrind is a set of tools which initially helped C/C++ programmers find unsafe
-memory accesses in their code. Nowadays the project also has
-
-- a heap profiler called `massif`
-
-- a cache utilization profiler called `cachegrind`
-
-- a call-graph performance profiler called `callgrind`
-
-<!--
-TODO: explain valgrind's dynamic binary translation, warn about massive
-slowdown, talk about `kcachegrind` for a GUI
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/prof/mca.md b/third_party/rust/packed_simd/perf-guide/src/prof/mca.md
deleted file mode 100644
index 65ddf1a4eb..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/prof/mca.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# Machine code analysis tools
-
-## The microarchitecture of modern CPUs
-
-While you might have heard of Instruction Set Architectures, such as `x86` or
-`arm` or `mips`, the term _microarchitecture_ (also written here as _µ-arch_),
-refers to the internal details of an actual family of CPUs, such as Intel's
-_Haswell_ or AMD's _Jaguar_.
-
-Replacing scalar code with SIMD code will improve performance on all CPUs
-supporting the required vector extensions.
-However, due to microarchitectural differences, the actual speed-up at
-runtime might vary.
-
-**Example**: a simple example arises when optimizing for AMD K8 CPUs.
-The assembly generated for an empty function should look like this:
-
-```asm
-nop
-ret
-```
-
-The `nop` is used to align the `ret` instruction for better performance.
-However, the compiler will actually generated the following code:
-
-```asm
-repz ret
-```
-
-The `repz` instruction will repeat the following instruction until a certain
-condition. Of course, in this situation, the function will simply immediately
-return, and the `ret` instruction is still aligned.
-However, AMD K8's branch predictor performs better with the latter code.
-
-For those looking to absolutely maximize performance for a certain target µ-arch,
-you will have to read some CPU manuals, or ask the compiler to do it for you
-with `-C target-cpu`.
-
-### Summary of CPU internals
-
-Modern processors are able to execute instructions out-of-order for better performance,
-by utilizing tricks such as [branch prediction], [instruction pipelining],
-or [superscalar execution].
-
-[branch prediction]: https://en.wikipedia.org/wiki/Branch_predictor
-[instruction pipelining]: https://en.wikipedia.org/wiki/Instruction_pipelining
-[superscalar execution]: https://en.wikipedia.org/wiki/Superscalar_processor
-
-SIMD instructions are also subject to these optimizations, meaning it can get pretty
-difficult to determine where the slowdown happens.
-For example, if the profiler reports a store operation is slow, one of two things
-could be happening:
-
-- the store is limited by the CPU's memory bandwidth, which is actually an ideal
- scenario, all things considered;
-
-- memory bandwidth is nowhere near its peak, but the value to be stored is at the
- end of a long chain of operations, and this store is where the profiler
- encountered the pipeline stall;
-
-Since most profilers are simple tools which don't understand the subtleties of
-instruction scheduling, you
-
-## Analyzing the machine code
-
-Certain tools have knowledge of internal CPU microarchitecture, i.e. they know
-
-- how many physical [register files] a CPU actually has
-
-- what is the latency / throughtput of an instruction
-
-- what [µ-ops] are generated for a set of instructions
-
-and many other architectural details.
-
-[register files]: https://en.wikipedia.org/wiki/Register_file
-[µ-ops]: https://en.wikipedia.org/wiki/Micro-operation
-
-These tools are therefore able to provide accurate information as to why some
-instructions are inefficient, and where the bottleneck is.
-
-The disadvantage is that the output of these tools requires advanced knowledge
-of the target architecture to understand, i.e. they **cannot** point out what
-the cause of the issue is explicitly.
-
-## Intel's Architecture Code Analyzer (IACA)
-
-[IACA] is a free tool offered by Intel for analyzing the performance of various
-computational kernels.
-
-Being a proprietary, closed source tool, it _only_ supports Intel's µ-arches.
-
-[IACA]: https://software.intel.com/en-us/articles/intel-architecture-code-analyzer
-
-## llvm-mca
-
-<!--
-TODO: once LLVM 7 gets released, write a chapter on using llvm-mca
-with SIMD disassembly.
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/prof/profiling.md b/third_party/rust/packed_simd/perf-guide/src/prof/profiling.md
deleted file mode 100644
index 02ba78d2f2..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/prof/profiling.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Performance profiling
-
-While the rest of the book provides practical advice on how to improve the performance
-of SIMD code, this chapter is dedicated to [**performance profiling**][profiling].
-Profiling consists of recording a program's execution in order to identify program
-hotspots.
-
-**Important**: most profilers require debug information in order to accurately
-link the program hotspots back to the corresponding source code lines. Rust will
-disable debug info generation by default for optimized builds, but you can change
-that [in your `Cargo.toml`][cargo-ref].
-
-[profiling]: https://en.wikipedia.org/wiki/Profiling_(computer_programming)
-[cargo-ref]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-profile-sections
diff --git a/third_party/rust/packed_simd/perf-guide/src/target-feature/attribute.md b/third_party/rust/packed_simd/perf-guide/src/target-feature/attribute.md
deleted file mode 100644
index ee670fea5b..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/target-feature/attribute.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# The `target_feature` attribute
-
-<!-- TODO:
-Explain the `#[target_feature]` attribute
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/target-feature/features.md b/third_party/rust/packed_simd/perf-guide/src/target-feature/features.md
deleted file mode 100644
index b93030ca67..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/target-feature/features.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Enabling target features
-
-Not all processors of a certain architecture will have SIMD processing units,
-and using a SIMD instruction which is not supported will trigger undefined behavior.
-
-To allow building safe, portable programs, the Rust compiler will **not**, by default,
-generate any sort of vector instructions, unless it can statically determine
-they are supported. For example, on AMD64, SSE2 support is architecturally guaranteed.
-The `x86_64-apple-darwin` target enables up to SSSE3. The get a defintive list of
-which features are enabled by default on various platforms, refer to the target
-specifications [in the compiler's source code][targets].
-
-[targets]: https://github.com/rust-lang/rust/tree/master/src/librustc_target/spec
diff --git a/third_party/rust/packed_simd/perf-guide/src/target-feature/inlining.md b/third_party/rust/packed_simd/perf-guide/src/target-feature/inlining.md
deleted file mode 100644
index 86705102a7..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/target-feature/inlining.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Inlining
-
-<!-- TODO:
-Explain how the `#[target_feature]` attribute interacts with inlining
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/target-feature/practice.md b/third_party/rust/packed_simd/perf-guide/src/target-feature/practice.md
deleted file mode 100644
index 5b55c61c26..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/target-feature/practice.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Target features in practice
-
-Using `RUSTFLAGS` will allow the crate being compiled, as well as all its
-transitive dependencies to use certain target features.
-
-A tehnique used to avoid undefined behavior at runtime is to compile and
-ship multiple binaries, each compiled with a certain set of features.
-This might not be feasible in some cases, and can quickly get out of hand
-as more and more vector extensions are added to an architecture.
-
-Rust can be more flexible: you can build a single binary/library which automatically
-picks the best supported vector instructions depending on the host machine.
-The trick consists of monomorphizing parts of the code during building, and then
-using run-time feature detection to select the right code path when running.
-
-<!-- TODO
-Explain how to create efficient functions that dispatch to different
-implementations at run-time without issues (e.g. using `#[inline(always)]` for
-the impls, wrapping in `#[target_feature]`, and the wrapping those in a function
-that does run-time feature detection).
--->
-
-**NOTE** (x86 specific): because the AVX (256-bit) registers extend the existing
-SSE (128-bit) registers, mixing SSE and AVX instructions in a program can cause
-performance issues.
-
-The solution is to compile all code, even the code written with 128-bit vectors,
-with the AVX target feature enabled. This will cause the compiler to prefix the
-generated instructions with the [VEX] prefix.
-
-[VEX]: https://en.wikipedia.org/wiki/VEX_prefix
diff --git a/third_party/rust/packed_simd/perf-guide/src/target-feature/runtime.md b/third_party/rust/packed_simd/perf-guide/src/target-feature/runtime.md
deleted file mode 100644
index 47ddcc8660..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/target-feature/runtime.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Detecting host features at runtime
-
-<!-- TODO:
-Explain cost (how it works).
--->
diff --git a/third_party/rust/packed_simd/perf-guide/src/target-feature/rustflags.md b/third_party/rust/packed_simd/perf-guide/src/target-feature/rustflags.md
deleted file mode 100644
index f4c1d1304a..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/target-feature/rustflags.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# Using RUSTFLAGS
-
-One of the easiest ways to benefit from SIMD is to allow the compiler
-to generate code using certain vector instruction extensions.
-
-The environment variable `RUSTFLAGS` can be used to pass options for code
-generation to the Rust compiler. These flags will affect **all** compiled crates.
-
-There are two flags which can be used to enable specific vector extensions:
-
-## target-feature
-
-- Syntax: `-C target-feature=<features>`
-
-- Provides the compiler with a comma-separated set of instruction extensions
- to enable.
-
- **Example**: Use `-C target-feature=+sse3,+avx` to enable generating instructions
- for [Streaming SIMD Extensions 3](https://en.wikipedia.org/wiki/SSE3) and
- [Advanced Vector Extensions](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions).
-
-- To list target triples for all targets supported by Rust, use:
-
- ```sh
- rustc --print target-list
- ```
-
-- To list all support target features for a certain target triple, use:
-
- ```sh
- rustc --target=${TRIPLE} --print target-features
- ```
-
-- Note that all CPU features are independent, and will have to be enabled individually.
-
- **Example**: Setting `-C target-feature=+avx2` will _not_ enable `fma`, even though
- all CPUs which support AVX2 also support FMA. To enable both, one has to use
- `-C target-feature=+avx2,+fma`
-
-- Some features also depend on other features, which need to be enabled for the
- target instructions to be generated.
-
- **Example**: Unless `v7` is specified as the target CPU (see below), to enable
- NEON on ARM it is necessary to use `-C target-feature=+v7,+neon`.
-
-## target-cpu
-
-- Syntax: `-C target-cpu=<cpu>`
-
-- Sets the identifier of a CPU family / model for which to build and optimize the code.
-
- **Example**: `RUSTFLAGS='-C target-cpu=cortex-a75'`
-
-- To list all supported target CPUs for a certain target triple, use:
-
- ```sh
- rustc --target=${TRIPLE} --print target-cpus
- ```
-
- **Example**:
-
- ```sh
- rustc --target=i686-pc-windows-msvc --print target-cpus
- ```
-
-- The compiler will translate this into a list of target features. Therefore,
- individual feature checks (`#[cfg(target_feature = "...")]`) will still
- work properly.
-
-- It will cause the code generator to optimize the generated code for that
- specific CPU model.
-
-- Using `native` as the CPU model will cause Rust to generate and optimize code
- for the CPU running the compiler. It is useful when building programs which you
- plan to only use locally. This should never be used when the generated programs
- are meant to be run on other computers, such as when packaging for distribution
- or cross-compiling.
diff --git a/third_party/rust/packed_simd/perf-guide/src/vert-hor-ops.md b/third_party/rust/packed_simd/perf-guide/src/vert-hor-ops.md
deleted file mode 100644
index d0dd1be12a..0000000000
--- a/third_party/rust/packed_simd/perf-guide/src/vert-hor-ops.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# Vertical and horizontal operations
-
-In SIMD terminology, each vector has a certain "width" (number of lanes).
-A vector processor is able to perform two kinds of operations on a vector:
-
-- Vertical operations:
- operate on two vectors of the same width, result has same width
-
-**Example**: vertical addition of two `f32x4` vectors
-
- %0 == | 2 | -3.5 | 0 | 7 |
- + + + +
- %1 == | 4 | 1.5 | -1 | 0 |
- = = = =
- %0 + %1 == | 6 | -2 | -1 | 7 |
-
-- Horizontal operations:
- reduce the elements of two vectors in some way,
- the result's elements combine information from the two original ones
-
-**Example**: horizontal addition of two `u64x2` vectors
-
- %0 == | 1 | 3 |
- └─+───┘
- └───────┐
- │
- %1 == | 4 | -1 | │
- └─+──┘ │
- └───┐ │
- │ │
- ┌─────│───┘
- ▼ ▼
- %0 + %1 == | 4 | 3 |
-
-## Performance consideration of horizontal operations
-
-The result of vertical operations, like vector negation: `-a`, for a given lane,
-does not depend on the result of the operation for the other lanes. The result
-of horizontal operations, like the vector `sum` reduction: `a.sum()`, depends on
-the value of all vector lanes.
-
-In virtually all architectures vertical operations are fast, while horizontal
-operations are, by comparison, very slow.
-
-Consider the following two functions for computing the sum of all `f32` values
-in a slice:
-
-```rust
-fn fast_sum(x: &[f32]) -> f32 {
- assert!(x.len() % 4 == 0);
- let mut sum = f32x4::splat(0.); // [0., 0., 0., 0.]
- for i in (0..x.len()).step_by(4) {
- sum += f32x4::from_slice_unaligned(&x[i..]);
- }
- sum.sum()
-}
-
-fn slow_sum(x: &[f32]) -> f32 {
- assert!(x.len() % 4 == 0);
- let mut sum: f32 = 0.;
- for i in (0..x.len()).step_by(4) {
- sum += f32x4::from_slice_unaligned(&x[i..]).sum();
- }
- sum
-}
-```
-
-The inner loop over the slice is where the bulk of the work actually happens.
-There, the `fast_sum` function perform vertical operations into a vector, doing
-a single horizontal reduction at the end, while the `slow_sum` function performs
-horizontal vector operations inside of the loop.
-
-On all widely-used architectures, `fast_sum` is a large constant factor faster
-than `slow_sum`. You can run the [slice_sum]() example and see for yourself. On
-the particular machine tested there the algorithm using the horizontal vector
-addition is 2.7x slower than the one using vertical vector operations!
diff --git a/third_party/rust/packed_simd/rust-toolchain b/third_party/rust/packed_simd/rust-toolchain
deleted file mode 100644
index bf867e0ae5..0000000000
--- a/third_party/rust/packed_simd/rust-toolchain
+++ /dev/null
@@ -1 +0,0 @@
-nightly
diff --git a/third_party/rust/packed_simd/rustfmt.toml b/third_party/rust/packed_simd/rustfmt.toml
deleted file mode 100644
index 7316518b99..0000000000
--- a/third_party/rust/packed_simd/rustfmt.toml
+++ /dev/null
@@ -1,5 +0,0 @@
-max_width = 110
-use_small_heuristics = "Max"
-wrap_comments = true
-edition = "2018"
-error_on_line_overflow = true \ No newline at end of file
diff --git a/third_party/rust/packed_simd/src/api.rs b/third_party/rust/packed_simd/src/api.rs
deleted file mode 100644
index 262fc4ee69..0000000000
--- a/third_party/rust/packed_simd/src/api.rs
+++ /dev/null
@@ -1,309 +0,0 @@
-//! Implements the Simd<[T; N]> APIs
-
-#[macro_use]
-mod bitmask;
-pub(crate) mod cast;
-#[macro_use]
-mod cmp;
-#[macro_use]
-mod default;
-#[macro_use]
-mod fmt;
-#[macro_use]
-mod from;
-#[macro_use]
-mod hash;
-#[macro_use]
-mod math;
-#[macro_use]
-mod minimal;
-#[macro_use]
-mod ops;
-#[macro_use]
-mod ptr;
-#[macro_use]
-mod reductions;
-#[macro_use]
-mod select;
-#[macro_use]
-mod shuffle;
-#[macro_use]
-mod shuffle1_dyn;
-#[macro_use]
-mod slice;
-#[macro_use]
-mod swap_bytes;
-#[macro_use]
-mod bit_manip;
-
-#[cfg(feature = "into_bits")]
-pub(crate) mod into_bits;
-
-macro_rules! impl_i {
- ([$elem_ty:ident; $elem_n:expr]: $tuple_id:ident, $mask_ty:ident
- | $ielem_ty:ident, $ibitmask_ty:ident | $test_tt:tt | $($elem_ids:ident),*
- | From: $($from_vec_ty:ident),* | $(#[$doc:meta])*) => {
- impl_minimal_iuf!([$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- | $($elem_ids),* | $(#[$doc])*);
- impl_ops_vector_arithmetic!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_scalar_arithmetic!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (!(0 as $elem_ty), 0)
- );
- impl_ops_scalar_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (!(0 as $elem_ty), 0)
- );
- impl_ops_vector_shifts!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_scalar_shifts!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_rotates!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_neg!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_int_min_max!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt
- );
- impl_reduction_integer_arithmetic!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- );
- impl_reduction_min_max!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- );
- impl_reduction_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- | (|x|{ x as $elem_ty }) | (!(0 as $elem_ty), 0)
- );
- impl_fmt_debug!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_lower_hex!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_upper_hex!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_octal!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_binary!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_from_array!([$elem_ty; $elem_n]: $tuple_id | $test_tt | (1, 1));
- impl_from_vectors!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | $($from_vec_ty),*
- );
- impl_default!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_hash!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_slice_from_slice!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_slice_write_to_slice!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_swap_bytes!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_bit_manip!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_shuffle1_dyn!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_partial_eq!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (0, 1)
- );
- impl_cmp_eq!([$elem_ty; $elem_n]: $tuple_id | $test_tt | (0, 1));
- impl_cmp_vertical!(
- [$elem_ty; $elem_n]: $tuple_id, $mask_ty, false, (1, 0) | $test_tt
- );
- impl_cmp_partial_ord!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_ord!([$elem_ty; $elem_n]: $tuple_id | $test_tt | (0, 1));
- impl_bitmask!($tuple_id | $ibitmask_ty | (-1, 0) | $test_tt);
-
- test_select!($elem_ty, $mask_ty, $tuple_id, (1, 2) | $test_tt);
- test_cmp_partial_ord_int!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- test_shuffle1_dyn!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- }
-}
-
-macro_rules! impl_u {
- ([$elem_ty:ident; $elem_n:expr]: $tuple_id:ident, $mask_ty:ident
- | $ielem_ty:ident, $ibitmask_ty:ident | $test_tt:tt | $($elem_ids:ident),*
- | From: $($from_vec_ty:ident),* | $(#[$doc:meta])*) => {
- impl_minimal_iuf!([$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- | $($elem_ids),* | $(#[$doc])*);
- impl_ops_vector_arithmetic!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_scalar_arithmetic!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (!(0 as $elem_ty), 0)
- );
- impl_ops_scalar_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (!(0 as $elem_ty), 0)
- );
- impl_ops_vector_shifts!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_scalar_shifts!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_rotates!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_int_min_max!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt
- );
- impl_reduction_integer_arithmetic!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- );
- impl_reduction_min_max!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- );
- impl_reduction_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- | (|x|{ x as $elem_ty }) | (!(0 as $elem_ty), 0)
- );
- impl_fmt_debug!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_lower_hex!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_upper_hex!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_octal!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_binary!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_from_array!([$elem_ty; $elem_n]: $tuple_id | $test_tt | (1, 1));
- impl_from_vectors!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | $($from_vec_ty),*
- );
- impl_default!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_hash!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_slice_from_slice!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_slice_write_to_slice!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_swap_bytes!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_bit_manip!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_shuffle1_dyn!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_partial_eq!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (1, 0)
- );
- impl_cmp_eq!([$elem_ty; $elem_n]: $tuple_id | $test_tt | (0, 1));
- impl_cmp_vertical!(
- [$elem_ty; $elem_n]: $tuple_id, $mask_ty, false, (1, 0) | $test_tt
- );
- impl_cmp_partial_ord!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_ord!([$elem_ty; $elem_n]: $tuple_id | $test_tt | (0, 1));
- impl_bitmask!($tuple_id | $ibitmask_ty | ($ielem_ty::max_value(), 0) |
- $test_tt);
-
- test_select!($elem_ty, $mask_ty, $tuple_id, (1, 2) | $test_tt);
- test_cmp_partial_ord_int!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- test_shuffle1_dyn!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- }
-}
-
-macro_rules! impl_f {
- ([$elem_ty:ident; $elem_n:expr]: $tuple_id:ident, $mask_ty:ident
- | $ielem_ty:ident | $test_tt:tt | $($elem_ids:ident),*
- | From: $($from_vec_ty:ident),* | $(#[$doc:meta])*) => {
- impl_minimal_iuf!([$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- | $($elem_ids),* | $(#[$doc])*);
- impl_ops_vector_arithmetic!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_scalar_arithmetic!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_neg!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_ops_vector_float_min_max!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt
- );
- impl_reduction_float_arithmetic!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_reduction_min_max!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- );
- impl_fmt_debug!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_from_array!([$elem_ty; $elem_n]: $tuple_id | $test_tt | (1., 1.));
- impl_from_vectors!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | $($from_vec_ty),*
- );
- impl_default!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_partial_eq!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (1., 0.)
- );
- impl_slice_from_slice!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_slice_write_to_slice!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_shuffle1_dyn!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
-
- impl_float_consts!([$elem_ty; $elem_n]: $tuple_id);
- impl_float_category!([$elem_ty; $elem_n]: $tuple_id, $mask_ty);
-
- // floating-point math
- impl_math_float_abs!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_cos!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_exp!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_ln!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_mul_add!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_mul_adde!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_powf!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_recpre!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_rsqrte!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_sin!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_sqrt!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_sqrte!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_tanh!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_vertical!(
- [$elem_ty; $elem_n]: $tuple_id, $mask_ty, false, (1., 0.)
- | $test_tt
- );
-
- test_select!($elem_ty, $mask_ty, $tuple_id, (1., 2.) | $test_tt);
- test_reduction_float_min_max!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt
- );
- test_shuffle1_dyn!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- }
-}
-
-macro_rules! impl_m {
- ([$elem_ty:ident; $elem_n:expr]: $tuple_id:ident
- | $ielem_ty:ident, $ibitmask_ty:ident
- | $test_tt:tt | $($elem_ids:ident),* | From: $($from_vec_ty:ident),*
- | $(#[$doc:meta])*) => {
- impl_minimal_mask!(
- [$elem_ty; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- | $($elem_ids),* | $(#[$doc])*
- );
- impl_ops_vector_mask_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (true, false)
- );
- impl_ops_scalar_mask_bitwise!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (true, false)
- );
- impl_reduction_bitwise!(
- [bool; $elem_n]: $tuple_id | $ielem_ty | $test_tt
- | (|x|{ x != 0 }) | (true, false)
- );
- impl_reduction_mask!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_fmt_debug!([bool; $elem_n]: $tuple_id | $test_tt);
- impl_from_array!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt
- | (crate::$elem_ty::new(true), true)
- );
- impl_from_vectors!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | $($from_vec_ty),*
- );
- impl_default!([bool; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_partial_eq!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (true, false)
- );
- impl_cmp_eq!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (true, false)
- );
- impl_cmp_vertical!(
- [$elem_ty; $elem_n]: $tuple_id, $tuple_id, true, (true, false)
- | $test_tt
- );
- impl_select!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_partial_ord!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_cmp_ord!(
- [$elem_ty; $elem_n]: $tuple_id | $test_tt | (false, true)
- );
- impl_shuffle1_dyn!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_bitmask!($tuple_id | $ibitmask_ty | (true, false) | $test_tt);
-
- test_cmp_partial_ord_mask!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- test_shuffle1_dyn_mask!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- }
-}
-
-macro_rules! impl_const_p {
- ([$elem_ty:ty; $elem_n:expr]: $tuple_id:ident, $mask_ty:ident,
- $usize_ty:ident, $isize_ty:ident
- | $test_tt:tt | $($elem_ids:ident),*
- | From: $($from_vec_ty:ident),* | $(#[$doc:meta])*) => {
- impl_minimal_p!(
- [$elem_ty; $elem_n]: $tuple_id, $mask_ty, $usize_ty, $isize_ty
- | ref_ | $test_tt | $($elem_ids),*
- | (1 as $elem_ty, 0 as $elem_ty) | $(#[$doc])*
- );
- impl_ptr_read!([$elem_ty; $elem_n]: $tuple_id, $mask_ty | $test_tt);
- }
-}
-
-macro_rules! impl_mut_p {
- ([$elem_ty:ty; $elem_n:expr]: $tuple_id:ident, $mask_ty:ident,
- $usize_ty:ident, $isize_ty:ident
- | $test_tt:tt | $($elem_ids:ident),*
- | From: $($from_vec_ty:ident),* | $(#[$doc:meta])*) => {
- impl_minimal_p!(
- [$elem_ty; $elem_n]: $tuple_id, $mask_ty, $usize_ty, $isize_ty
- | ref_mut_ | $test_tt | $($elem_ids),*
- | (1 as $elem_ty, 0 as $elem_ty) | $(#[$doc])*
- );
- impl_ptr_read!([$elem_ty; $elem_n]: $tuple_id, $mask_ty | $test_tt);
- impl_ptr_write!([$elem_ty; $elem_n]: $tuple_id, $mask_ty | $test_tt);
- }
-}
diff --git a/third_party/rust/packed_simd/src/api/bit_manip.rs b/third_party/rust/packed_simd/src/api/bit_manip.rs
deleted file mode 100644
index c1e90bb0fb..0000000000
--- a/third_party/rust/packed_simd/src/api/bit_manip.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-//! Bit manipulations.
-
-macro_rules! impl_bit_manip {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Returns the number of ones in the binary representation of
- /// the lanes of `self`.
- #[inline]
- pub fn count_ones(self) -> Self {
- super::codegen::bit_manip::BitManip::ctpop(self)
- }
-
- /// Returns the number of zeros in the binary representation of
- /// the lanes of `self`.
- #[inline]
- pub fn count_zeros(self) -> Self {
- super::codegen::bit_manip::BitManip::ctpop(!self)
- }
-
- /// Returns the number of leading zeros in the binary
- /// representation of the lanes of `self`.
- #[inline]
- pub fn leading_zeros(self) -> Self {
- super::codegen::bit_manip::BitManip::ctlz(self)
- }
-
- /// Returns the number of trailing zeros in the binary
- /// representation of the lanes of `self`.
- #[inline]
- pub fn trailing_zeros(self) -> Self {
- super::codegen::bit_manip::BitManip::cttz(self)
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- #[allow(overflowing_literals)]
- pub mod [<$id _bit_manip>] {
- #![allow(const_item_mutation)]
- use super::*;
-
- const LANE_WIDTH: usize = mem::size_of::<$elem_ty>() * 8;
-
- macro_rules! test_func {
- ($x:expr, $func:ident) => {{
- let mut actual = $x;
- for i in 0..$id::lanes() {
- actual = actual.replace(
- i,
- $x.extract(i).$func() as $elem_ty
- );
- }
- let expected = $x.$func();
- assert_eq!(actual, expected);
- }};
- }
-
- const BYTES: [u8; 64] = [
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- ];
-
- fn load_bytes() -> $id {
- let elems: &mut [$elem_ty] = unsafe {
- slice::from_raw_parts_mut(
- BYTES.as_mut_ptr() as *mut $elem_ty,
- $id::lanes(),
- )
- };
- $id::from_slice_unaligned(elems)
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn count_ones() {
- test_func!($id::splat(0), count_ones);
- test_func!($id::splat(!0), count_ones);
- test_func!(load_bytes(), count_ones);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn count_zeros() {
- test_func!($id::splat(0), count_zeros);
- test_func!($id::splat(!0), count_zeros);
- test_func!(load_bytes(), count_zeros);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn leading_zeros() {
- test_func!($id::splat(0), leading_zeros);
- test_func!($id::splat(1), leading_zeros);
- // some implementations use `pshufb` which has unique
- // behavior when the 8th bit is set.
- test_func!($id::splat(0b1000_0010), leading_zeros);
- test_func!($id::splat(!0), leading_zeros);
- test_func!(
- $id::splat(1 << (LANE_WIDTH - 1)),
- leading_zeros
- );
- test_func!(load_bytes(), leading_zeros);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn trailing_zeros() {
- test_func!($id::splat(0), trailing_zeros);
- test_func!($id::splat(1), trailing_zeros);
- test_func!($id::splat(0b1000_0010), trailing_zeros);
- test_func!($id::splat(!0), trailing_zeros);
- test_func!(
- $id::splat(1 << (LANE_WIDTH - 1)),
- trailing_zeros
- );
- test_func!(load_bytes(), trailing_zeros);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/bitmask.rs b/third_party/rust/packed_simd/src/api/bitmask.rs
deleted file mode 100644
index 8f4868f328..0000000000
--- a/third_party/rust/packed_simd/src/api/bitmask.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-//! Bitmask API
-
-macro_rules! impl_bitmask {
- ($id:ident | $ibitmask_ty:ident | ($set:expr, $clear:expr)
- | $test_tt:tt) => {
- impl $id {
- /// Creates a bitmask with the MSB of each vector lane.
- ///
- /// If the vector has less than 8 lanes, the bits that do not
- /// correspond to any vector lanes are cleared.
- #[inline]
- pub fn bitmask(self) -> $ibitmask_ty {
- unsafe { codegen::llvm::simd_bitmask(self.0) }
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- #[cfg(not(
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/210
- target_endian = "big"
- ))]
- pub mod [<$id _bitmask>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn bitmask() {
- // clear all lanes
- let vec = $id::splat($clear as _);
- let bitmask: $ibitmask_ty = 0;
- assert_eq!(vec.bitmask(), bitmask);
-
- // set even lanes
- let mut vec = $id::splat($clear as _);
- for i in 0..$id::lanes() {
- if i % 2 == 0 {
- vec = vec.replace(i, $set as _);
- }
- }
- // create bitmask with even lanes set:
- let mut bitmask: $ibitmask_ty = 0;
- for i in 0..$id::lanes() {
- if i % 2 == 0 {
- bitmask |= 1 << i;
- }
- }
- assert_eq!(vec.bitmask(), bitmask);
-
-
- // set odd lanes
- let mut vec = $id::splat($clear as _);
- for i in 0..$id::lanes() {
- if i % 2 != 0 {
- vec = vec.replace(i, $set as _);
- }
- }
- // create bitmask with odd lanes set:
- let mut bitmask: $ibitmask_ty = 0;
- for i in 0..$id::lanes() {
- if i % 2 != 0 {
- bitmask |= 1 << i;
- }
- }
- assert_eq!(vec.bitmask(), bitmask);
-
- // set all lanes
- let vec = $id::splat($set as _);
- let mut bitmask: $ibitmask_ty = 0;
- for i in 0..$id::lanes() {
- bitmask |= 1 << i;
- }
- assert_eq!(vec.bitmask(), bitmask);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/cast.rs b/third_party/rust/packed_simd/src/api/cast.rs
deleted file mode 100644
index f1c32ca1a3..0000000000
--- a/third_party/rust/packed_simd/src/api/cast.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-//! Implementation of `FromCast` and `IntoCast`.
-#![allow(clippy::module_name_repetitions)]
-
-/// Numeric cast from `T` to `Self`.
-///
-/// > Note: This is a temporary workaround until the conversion traits
-/// specified > in [RFC2484] are implemented.
-///
-/// Numeric cast between vectors with the same number of lanes, such that:
-///
-/// * casting integer vectors whose lane types have the same size (e.g. `i32xN`
-/// -> `u32xN`) is a **no-op**,
-///
-/// * casting from a larger integer to a smaller integer (e.g. `u32xN` ->
-/// `u8xN`) will **truncate**,
-///
-/// * casting from a smaller integer to a larger integer (e.g. `u8xN` ->
-/// `u32xN`) will:
-/// * **zero-extend** if the source is unsigned, or
-/// * **sign-extend** if the source is signed,
-///
-/// * casting from a float to an integer will **round the float towards zero**,
-///
-/// * casting from an integer to float will produce the floating point
-/// representation of the integer, **rounding to nearest, ties to even**,
-///
-/// * casting from an `f32` to an `f64` is perfect and lossless,
-///
-/// * casting from an `f64` to an `f32` **rounds to nearest, ties to even**.
-///
-/// [RFC2484]: https://github.com/rust-lang/rfcs/pull/2484
-pub trait FromCast<T>: crate::marker::Sized {
- /// Numeric cast from `T` to `Self`.
- fn from_cast(_: T) -> Self;
-}
-
-/// Numeric cast from `Self` to `T`.
-///
-/// > Note: This is a temporary workaround until the conversion traits
-/// specified > in [RFC2484] are implemented.
-///
-/// Numeric cast between vectors with the same number of lanes, such that:
-///
-/// * casting integer vectors whose lane types have the same size (e.g. `i32xN`
-/// -> `u32xN`) is a **no-op**,
-///
-/// * casting from a larger integer to a smaller integer (e.g. `u32xN` ->
-/// `u8xN`) will **truncate**,
-///
-/// * casting from a smaller integer to a larger integer (e.g. `u8xN` ->
-/// `u32xN`) will:
-/// * **zero-extend** if the source is unsigned, or
-/// * **sign-extend** if the source is signed,
-///
-/// * casting from a float to an integer will **round the float towards zero**,
-///
-/// * casting from an integer to float will produce the floating point
-/// representation of the integer, **rounding to nearest, ties to even**,
-///
-/// * casting from an `f32` to an `f64` is perfect and lossless,
-///
-/// * casting from an `f64` to an `f32` **rounds to nearest, ties to even**.
-///
-/// [RFC2484]: https://github.com/rust-lang/rfcs/pull/2484
-pub trait Cast<T>: crate::marker::Sized {
- /// Numeric cast from `self` to `T`.
- fn cast(self) -> T;
-}
-
-/// `FromCast` implies `Cast`.
-impl<T, U> Cast<U> for T
-where
- U: FromCast<T>,
-{
- #[inline]
- fn cast(self) -> U {
- U::from_cast(self)
- }
-}
-
-/// `FromCast` and `Cast` are reflexive
-impl<T> FromCast<T> for T {
- #[inline]
- fn from_cast(t: Self) -> Self {
- t
- }
-}
-
-#[macro_use]
-mod macros;
-
-mod v16;
-pub use self::v16::*;
-
-mod v32;
-pub use self::v32::*;
-
-mod v64;
-pub use self::v64::*;
-
-mod v128;
-pub use self::v128::*;
-
-mod v256;
-pub use self::v256::*;
-
-mod v512;
-pub use self::v512::*;
diff --git a/third_party/rust/packed_simd/src/api/cast/macros.rs b/third_party/rust/packed_simd/src/api/cast/macros.rs
deleted file mode 100644
index 3bb29f0b80..0000000000
--- a/third_party/rust/packed_simd/src/api/cast/macros.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-//! Macros implementing `FromCast`
-
-macro_rules! impl_from_cast_ {
- ($id:ident[$test_tt:tt]: $from_ty:ident) => {
- impl crate::api::cast::FromCast<$from_ty> for $id {
- #[inline]
- fn from_cast(x: $from_ty) -> Self {
- use crate::llvm::simd_cast;
- debug_assert_eq!($from_ty::lanes(), $id::lanes());
- Simd(unsafe { simd_cast(x.0) })
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _from_cast_ $from_ty>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn test() {
- assert_eq!($id::lanes(), $from_ty::lanes());
- }
- }
- }
- }
- };
-}
-
-macro_rules! impl_from_cast {
- ($id:ident[$test_tt:tt]: $($from_ty:ident),*) => {
- $(
- impl_from_cast_!($id[$test_tt]: $from_ty);
- )*
- }
-}
-
-macro_rules! impl_from_cast_mask_ {
- ($id:ident[$test_tt:tt]: $from_ty:ident) => {
- impl crate::api::cast::FromCast<$from_ty> for $id {
- #[inline]
- fn from_cast(x: $from_ty) -> Self {
- debug_assert_eq!($from_ty::lanes(), $id::lanes());
- x.ne($from_ty::default())
- .select($id::splat(true), $id::splat(false))
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _from_cast_ $from_ty>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn test() {
- assert_eq!($id::lanes(), $from_ty::lanes());
-
- let x = $from_ty::default();
- let m: $id = x.cast();
- assert!(m.none());
- }
- }
- }
- }
- };
-}
-
-macro_rules! impl_from_cast_mask {
- ($id:ident[$test_tt:tt]: $($from_ty:ident),*) => {
- $(
- impl_from_cast_mask_!($id[$test_tt]: $from_ty);
- )*
- }
-}
-
-#[allow(unused)]
-macro_rules! impl_into_cast {
- ($id:ident[$test_tt:tt]: $($from_ty:ident),*) => {
- $(
- impl_from_cast_!($from_ty[$test_tt]: $id);
- )*
- }
-}
diff --git a/third_party/rust/packed_simd/src/api/cast/v128.rs b/third_party/rust/packed_simd/src/api/cast/v128.rs
deleted file mode 100644
index 2e10b97b77..0000000000
--- a/third_party/rust/packed_simd/src/api/cast/v128.rs
+++ /dev/null
@@ -1,302 +0,0 @@
-//! `FromCast` and `IntoCast` implementations for portable 128-bit wide vectors
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_from_cast!(i8x16[test_v128]: u8x16, m8x16, i16x16, u16x16, m16x16, i32x16, u32x16, f32x16, m32x16);
-impl_from_cast!(u8x16[test_v128]: i8x16, m8x16, i16x16, u16x16, m16x16, i32x16, u32x16, f32x16, m32x16);
-impl_from_cast_mask!(m8x16[test_v128]: i8x16, u8x16, i16x16, u16x16, m16x16, i32x16, u32x16, f32x16, m32x16);
-
-impl_from_cast!(
- i16x8[test_v128]: i8x8,
- u8x8,
- m8x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast!(
- u16x8[test_v128]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast_mask!(
- m16x8[test_v128]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-
-impl_from_cast!(
- i32x4[test_v128]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- u32x4[test_v128]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- f32x4[test_v128]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast_mask!(
- m32x4[test_v128]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-
-impl_from_cast!(
- i64x2[test_v128]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- u64x2[test_v128]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- f64x2[test_v128]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast_mask!(
- m64x2[test_v128]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-
-impl_from_cast!(
- isizex2[test_v128]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- usizex2[test_v128]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- msizex2
-);
-impl_from_cast_mask!(
- msizex2[test_v128]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2
-);
-
-// FIXME[test_v128]: 64-bit single element vectors into_cast impls
-impl_from_cast!(i128x1[test_v128]: u128x1, m128x1);
-impl_from_cast!(u128x1[test_v128]: i128x1, m128x1);
-impl_from_cast!(m128x1[test_v128]: i128x1, u128x1);
diff --git a/third_party/rust/packed_simd/src/api/cast/v16.rs b/third_party/rust/packed_simd/src/api/cast/v16.rs
deleted file mode 100644
index 896febacbb..0000000000
--- a/third_party/rust/packed_simd/src/api/cast/v16.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! `FromCast` and `IntoCast` implementations for portable 16-bit wide vectors
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_from_cast!(
- i8x2[test_v16]: u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- u8x2[test_v16]: i8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast_mask!(
- m8x2[test_v16]: i8x2,
- u8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
diff --git a/third_party/rust/packed_simd/src/api/cast/v256.rs b/third_party/rust/packed_simd/src/api/cast/v256.rs
deleted file mode 100644
index fe0c835e3c..0000000000
--- a/third_party/rust/packed_simd/src/api/cast/v256.rs
+++ /dev/null
@@ -1,298 +0,0 @@
-//! `FromCast` and `IntoCast` implementations for portable 256-bit wide vectors
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_from_cast!(i8x32[test_v256]: u8x32, m8x32, i16x32, u16x32, m16x32);
-impl_from_cast!(u8x32[test_v256]: i8x32, m8x32, i16x32, u16x32, m16x32);
-impl_from_cast_mask!(m8x32[test_v256]: i8x32, u8x32, i16x32, u16x32, m16x32);
-
-impl_from_cast!(i16x16[test_v256]: i8x16, u8x16, m8x16, u16x16, m16x16, i32x16, u32x16, f32x16, m32x16);
-impl_from_cast!(u16x16[test_v256]: i8x16, u8x16, m8x16, i16x16, m16x16, i32x16, u32x16, f32x16, m32x16);
-impl_from_cast_mask!(m16x16[test_v256]: i8x16, u8x16, m8x16, i16x16, u16x16, i32x16, u32x16, f32x16, m32x16);
-
-impl_from_cast!(
- i32x8[test_v256]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast!(
- u32x8[test_v256]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast!(
- f32x8[test_v256]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast_mask!(
- m32x8[test_v256]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-
-impl_from_cast!(
- i64x4[test_v256]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- u64x4[test_v256]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- f64x4[test_v256]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast_mask!(
- m64x4[test_v256]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-
-impl_from_cast!(
- i128x2[test_v256]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- u128x2[test_v256]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast_mask!(
- m128x2[test_v256]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- m64x2,
- f64x2,
- i128x2,
- u128x2,
- isizex2,
- usizex2,
- msizex2
-);
-
-impl_from_cast!(
- isizex4[test_v256]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- usizex4[test_v256]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- msizex4
-);
-impl_from_cast_mask!(
- msizex4[test_v256]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4
-);
diff --git a/third_party/rust/packed_simd/src/api/cast/v32.rs b/third_party/rust/packed_simd/src/api/cast/v32.rs
deleted file mode 100644
index 4ad1cbf74d..0000000000
--- a/third_party/rust/packed_simd/src/api/cast/v32.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-//! `FromCast` and `IntoCast` implementations for portable 32-bit wide vectors
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_from_cast!(
- i8x4[test_v32]: u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- u8x4[test_v32]: i8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast_mask!(
- m8x4[test_v32]: i8x4,
- u8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-
-impl_from_cast!(
- i16x2[test_v32]: i8x2,
- u8x2,
- m8x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- u16x2[test_v32]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast_mask!(
- m16x2[test_v32]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- i32x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
diff --git a/third_party/rust/packed_simd/src/api/cast/v512.rs b/third_party/rust/packed_simd/src/api/cast/v512.rs
deleted file mode 100644
index b64605045e..0000000000
--- a/third_party/rust/packed_simd/src/api/cast/v512.rs
+++ /dev/null
@@ -1,209 +0,0 @@
-//! `FromCast` and `IntoCast` implementations for portable 512-bit wide vectors
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_from_cast!(i8x64[test_v512]: u8x64, m8x64);
-impl_from_cast!(u8x64[test_v512]: i8x64, m8x64);
-impl_from_cast_mask!(m8x64[test_v512]: i8x64, u8x64);
-
-impl_from_cast!(i16x32[test_v512]: i8x32, u8x32, m8x32, u16x32, m16x32);
-impl_from_cast!(u16x32[test_v512]: i8x32, u8x32, m8x32, i16x32, m16x32);
-impl_from_cast_mask!(m16x32[test_v512]: i8x32, u8x32, m8x32, i16x32, u16x32);
-
-impl_from_cast!(i32x16[test_v512]: i8x16, u8x16, m8x16, i16x16, u16x16, m16x16, u32x16, f32x16, m32x16);
-impl_from_cast!(u32x16[test_v512]: i8x16, u8x16, m8x16, i16x16, u16x16, m16x16, i32x16, f32x16, m32x16);
-impl_from_cast!(f32x16[test_v512]: i8x16, u8x16, m8x16, i16x16, u16x16, m16x16, i32x16, u32x16, m32x16);
-impl_from_cast_mask!(m32x16[test_v512]: i8x16, u8x16, m8x16, i16x16, u16x16, m16x16, i32x16, u32x16, f32x16);
-
-impl_from_cast!(
- i64x8[test_v512]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast!(
- u64x8[test_v512]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast!(
- f64x8[test_v512]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast_mask!(
- m64x8[test_v512]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- isizex8,
- usizex8,
- msizex8
-);
-
-impl_from_cast!(
- i128x4[test_v512]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- u128x4[test_v512]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast_mask!(
- m128x4[test_v512]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- m64x4,
- f64x4,
- i128x4,
- u128x4,
- isizex4,
- usizex4,
- msizex4
-);
-
-impl_from_cast!(
- isizex8[test_v512]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- usizex8,
- msizex8
-);
-impl_from_cast!(
- usizex8[test_v512]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- msizex8
-);
-impl_from_cast_mask!(
- msizex8[test_v512]: i8x8,
- u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8
-);
diff --git a/third_party/rust/packed_simd/src/api/cast/v64.rs b/third_party/rust/packed_simd/src/api/cast/v64.rs
deleted file mode 100644
index b23d1a4917..0000000000
--- a/third_party/rust/packed_simd/src/api/cast/v64.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-//! `FromCast` and `IntoCast` implementations for portable 64-bit wide vectors
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_from_cast!(
- i8x8[test_v64]: u8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast!(
- u8x8[test_v64]: i8x8,
- m8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-impl_from_cast_mask!(
- m8x8[test_v64]: i8x8,
- u8x8,
- i16x8,
- u16x8,
- m16x8,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- isizex8,
- usizex8,
- msizex8
-);
-
-impl_from_cast!(
- i16x4[test_v64]: i8x4,
- u8x4,
- m8x4,
- u16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast!(
- u16x4[test_v64]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- m16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-impl_from_cast_mask!(
- m16x4[test_v64]: i8x4,
- u8x4,
- m8x4,
- i16x4,
- u16x4,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x4,
- u128x4,
- m128x4,
- isizex4,
- usizex4,
- msizex4
-);
-
-impl_from_cast!(
- i32x2[test_v64]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- u32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- u32x2[test_v64]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- f32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast!(
- f32x2[test_v64]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- m32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
-impl_from_cast_mask!(
- m32x2[test_v64]: i8x2,
- u8x2,
- m8x2,
- i16x2,
- u16x2,
- m16x2,
- i32x2,
- u32x2,
- f32x2,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x2,
- u128x2,
- m128x2,
- isizex2,
- usizex2,
- msizex2
-);
diff --git a/third_party/rust/packed_simd/src/api/cmp.rs b/third_party/rust/packed_simd/src/api/cmp.rs
deleted file mode 100644
index 6d5301dddd..0000000000
--- a/third_party/rust/packed_simd/src/api/cmp.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//! Implement cmp traits for vector types
-
-#[macro_use]
-mod partial_eq;
-
-#[macro_use]
-mod eq;
-
-#[macro_use]
-mod partial_ord;
-
-#[macro_use]
-mod ord;
-
-#[macro_use]
-mod vertical;
diff --git a/third_party/rust/packed_simd/src/api/cmp/eq.rs b/third_party/rust/packed_simd/src/api/cmp/eq.rs
deleted file mode 100644
index 3c55d0dce5..0000000000
--- a/third_party/rust/packed_simd/src/api/cmp/eq.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//! Implements `Eq` for vector types.
-
-macro_rules! impl_cmp_eq {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $test_tt:tt |
- ($true:expr, $false:expr)
- ) => {
- impl crate::cmp::Eq for $id {}
- impl crate::cmp::Eq for LexicographicallyOrdered<$id> {}
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_eq>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn eq() {
- fn foo<E: crate::cmp::Eq>(_: E) {}
- let a = $id::splat($false);
- foo(a);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/cmp/ord.rs b/third_party/rust/packed_simd/src/api/cmp/ord.rs
deleted file mode 100644
index e54ba3bfde..0000000000
--- a/third_party/rust/packed_simd/src/api/cmp/ord.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-//! Implements `Ord` for vector types.
-
-macro_rules! impl_cmp_ord {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $test_tt:tt |
- ($true:expr, $false:expr)
- ) => {
- impl $id {
- /// Returns a wrapper that implements `Ord`.
- #[inline]
- pub fn lex_ord(&self) -> LexicographicallyOrdered<$id> {
- LexicographicallyOrdered(*self)
- }
- }
-
- impl crate::cmp::Ord for LexicographicallyOrdered<$id> {
- #[inline]
- fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
- match self.partial_cmp(other) {
- Some(x) => x,
- None => unsafe { crate::hint::unreachable_unchecked() },
- }
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_ord>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn eq() {
- fn foo<E: crate::cmp::Ord>(_: E) {}
- let a = $id::splat($false);
- foo(a.partial_lex_ord());
- foo(a.lex_ord());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/cmp/partial_eq.rs b/third_party/rust/packed_simd/src/api/cmp/partial_eq.rs
deleted file mode 100644
index d69dd47425..0000000000
--- a/third_party/rust/packed_simd/src/api/cmp/partial_eq.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-//! Implements `PartialEq` for vector types.
-
-macro_rules! impl_cmp_partial_eq {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $test_tt:tt |
- ($true:expr, $false:expr)
- ) => {
- // FIXME: https://github.com/rust-lang-nursery/rust-clippy/issues/2892
- #[allow(clippy::partialeq_ne_impl)]
- impl crate::cmp::PartialEq<$id> for $id {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- $id::eq(*self, *other).all()
- }
- #[inline]
- fn ne(&self, other: &Self) -> bool {
- $id::ne(*self, *other).any()
- }
- }
-
- // FIXME: https://github.com/rust-lang-nursery/rust-clippy/issues/2892
- #[allow(clippy::partialeq_ne_impl)]
- impl crate::cmp::PartialEq<LexicographicallyOrdered<$id>> for LexicographicallyOrdered<$id> {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
- #[inline]
- fn ne(&self, other: &Self) -> bool {
- self.0 != other.0
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_PartialEq>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn partial_eq() {
- let a = $id::splat($false);
- let b = $id::splat($true);
-
- assert!(a != b);
- assert!(!(a == b));
- assert!(a == a);
- assert!(!(a != a));
-
- if $id::lanes() > 1 {
- let a = $id::splat($false).replace(0, $true);
- let b = $id::splat($true);
-
- assert!(a != b);
- assert!(!(a == b));
- assert!(a == a);
- assert!(!(a != a));
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/cmp/partial_ord.rs b/third_party/rust/packed_simd/src/api/cmp/partial_ord.rs
deleted file mode 100644
index 76ed9ebe4e..0000000000
--- a/third_party/rust/packed_simd/src/api/cmp/partial_ord.rs
+++ /dev/null
@@ -1,230 +0,0 @@
-//! Implements `PartialOrd` for vector types.
-//!
-//! This implements a lexicographical order.
-
-macro_rules! impl_cmp_partial_ord {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Returns a wrapper that implements `PartialOrd`.
- #[inline]
- pub fn partial_lex_ord(&self) -> LexicographicallyOrdered<$id> {
- LexicographicallyOrdered(*self)
- }
- }
-
- impl crate::cmp::PartialOrd<LexicographicallyOrdered<$id>> for LexicographicallyOrdered<$id> {
- #[inline]
- fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
- if PartialEq::eq(self, other) {
- Some(crate::cmp::Ordering::Equal)
- } else if PartialOrd::lt(self, other) {
- Some(crate::cmp::Ordering::Less)
- } else if PartialOrd::gt(self, other) {
- Some(crate::cmp::Ordering::Greater)
- } else {
- None
- }
- }
- #[inline]
- fn lt(&self, other: &Self) -> bool {
- let m_lt = self.0.lt(other.0);
- let m_eq = self.0.eq(other.0);
- for i in 0..$id::lanes() {
- if m_eq.extract(i) {
- continue;
- }
- return m_lt.extract(i);
- }
- false
- }
- #[inline]
- fn le(&self, other: &Self) -> bool {
- self.lt(other) | PartialEq::eq(self, other)
- }
- #[inline]
- fn ge(&self, other: &Self) -> bool {
- self.gt(other) | PartialEq::eq(self, other)
- }
- #[inline]
- fn gt(&self, other: &Self) -> bool {
- let m_gt = self.0.gt(other.0);
- let m_eq = self.0.eq(other.0);
- for i in 0..$id::lanes() {
- if m_eq.extract(i) {
- continue;
- }
- return m_gt.extract(i);
- }
- false
- }
- }
- };
-}
-
-macro_rules! test_cmp_partial_ord_int {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_PartialOrd>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn partial_lex_ord() {
- use crate::testing::utils::{test_cmp};
- // constant values
- let a = $id::splat(0);
- let b = $id::splat(1);
-
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
-
- // variable values: a = [0, 1, 2, 3]; b = [3, 2, 1, 0]
- let mut a = $id::splat(0);
- let mut b = $id::splat(0);
- for i in 0..$id::lanes() {
- a = a.replace(i, i as $elem_ty);
- b = b.replace(i, ($id::lanes() - i) as $elem_ty);
- }
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
-
- // variable values: a = [0, 1, 2, 3]; b = [0, 1, 2, 4]
- let mut b = a;
- b = b.replace(
- $id::lanes() - 1,
- a.extract($id::lanes() - 1) + 1 as $elem_ty
- );
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
-
- if $id::lanes() > 2 {
- // variable values a = [0, 1, 0, 0]; b = [0, 1, 2, 3]
- let b = a;
- let mut a = $id::splat(0);
- a = a.replace(1, 1 as $elem_ty);
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
-
- // variable values: a = [0, 1, 2, 3]; b = [0, 1, 3, 2]
- let mut b = a;
- b = b.replace(
- 2, a.extract($id::lanes() - 1) + 1 as $elem_ty
- );
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(crate::cmp::Ordering::Equal));
- }
- }
- }
- }
- }
- };
-}
-
-macro_rules! test_cmp_partial_ord_mask {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_PartialOrd>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn partial_lex_ord() {
- use crate::testing::utils::{test_cmp};
- use crate::cmp::Ordering;
-
- // constant values
- let a = $id::splat(false);
- let b = $id::splat(true);
-
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Equal));
-
- // variable values:
- // a = [false, false, false, false];
- // b = [false, false, false, true]
- let a = $id::splat(false);
- let mut b = $id::splat(false);
- b = b.replace($id::lanes() - 1, true);
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Equal));
-
- // variable values:
- // a = [true, true, true, false];
- // b = [true, true, true, true]
- let mut a = $id::splat(true);
- let b = $id::splat(true);
- a = a.replace($id::lanes() - 1, false);
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Equal));
-
- if $id::lanes() > 2 {
- // variable values
- // a = [false, true, false, false];
- // b = [false, true, true, true]
- let mut a = $id::splat(false);
- let mut b = $id::splat(true);
- a = a.replace(1, true);
- b = b.replace(0, false);
- test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Less));
- test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Greater));
- test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
- Some(Ordering::Equal));
- test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
- Some(Ordering::Equal));
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/cmp/vertical.rs b/third_party/rust/packed_simd/src/api/cmp/vertical.rs
deleted file mode 100644
index ea4a0d1a34..0000000000
--- a/third_party/rust/packed_simd/src/api/cmp/vertical.rs
+++ /dev/null
@@ -1,114 +0,0 @@
-//! Vertical (lane-wise) vector comparisons returning vector masks.
-
-macro_rules! impl_cmp_vertical {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident,
- $mask_ty:ident,
- $is_mask:expr,($true:expr, $false:expr) | $test_tt:tt
- ) => {
- impl $id {
- /// Lane-wise equality comparison.
- #[inline]
- pub fn eq(self, other: Self) -> $mask_ty {
- use crate::llvm::simd_eq;
- Simd(unsafe { simd_eq(self.0, other.0) })
- }
-
- /// Lane-wise inequality comparison.
- #[inline]
- pub fn ne(self, other: Self) -> $mask_ty {
- use crate::llvm::simd_ne;
- Simd(unsafe { simd_ne(self.0, other.0) })
- }
-
- /// Lane-wise less-than comparison.
- #[inline]
- pub fn lt(self, other: Self) -> $mask_ty {
- use crate::llvm::{simd_gt, simd_lt};
- if $is_mask {
- Simd(unsafe { simd_gt(self.0, other.0) })
- } else {
- Simd(unsafe { simd_lt(self.0, other.0) })
- }
- }
-
- /// Lane-wise less-than-or-equals comparison.
- #[inline]
- pub fn le(self, other: Self) -> $mask_ty {
- use crate::llvm::{simd_ge, simd_le};
- if $is_mask {
- Simd(unsafe { simd_ge(self.0, other.0) })
- } else {
- Simd(unsafe { simd_le(self.0, other.0) })
- }
- }
-
- /// Lane-wise greater-than comparison.
- #[inline]
- pub fn gt(self, other: Self) -> $mask_ty {
- use crate::llvm::{simd_gt, simd_lt};
- if $is_mask {
- Simd(unsafe { simd_lt(self.0, other.0) })
- } else {
- Simd(unsafe { simd_gt(self.0, other.0) })
- }
- }
-
- /// Lane-wise greater-than-or-equals comparison.
- #[inline]
- pub fn ge(self, other: Self) -> $mask_ty {
- use crate::llvm::{simd_ge, simd_le};
- if $is_mask {
- Simd(unsafe { simd_le(self.0, other.0) })
- } else {
- Simd(unsafe { simd_ge(self.0, other.0) })
- }
- }
- }
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_vertical>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn cmp() {
- let a = $id::splat($false);
- let b = $id::splat($true);
-
- let r = a.lt(b);
- let e = $mask_ty::splat(true);
- assert!(r == e);
- let r = a.le(b);
- assert!(r == e);
-
- let e = $mask_ty::splat(false);
- let r = a.gt(b);
- assert!(r == e);
- let r = a.ge(b);
- assert!(r == e);
- let r = a.eq(b);
- assert!(r == e);
-
- let mut a = a;
- let mut b = b;
- let mut e = e;
- for i in 0..$id::lanes() {
- if i % 2 == 0 {
- a = a.replace(i, $false);
- b = b.replace(i, $true);
- e = e.replace(i, true);
- } else {
- a = a.replace(i, $true);
- b = b.replace(i, $false);
- e = e.replace(i, false);
- }
- }
- let r = a.lt(b);
- assert!(r == e);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/default.rs b/third_party/rust/packed_simd/src/api/default.rs
deleted file mode 100644
index 7af55ea77a..0000000000
--- a/third_party/rust/packed_simd/src/api/default.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! Implements `Default` for vector types.
-
-macro_rules! impl_default {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl Default for $id {
- #[inline]
- fn default() -> Self {
- Self::splat($elem_ty::default())
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- pub mod [<$id _default>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn default() {
- let a = $id::default();
- for i in 0..$id::lanes() {
- assert_eq!(a.extract(i), $elem_ty::default());
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/fmt.rs b/third_party/rust/packed_simd/src/api/fmt.rs
deleted file mode 100644
index f3f55c4015..0000000000
--- a/third_party/rust/packed_simd/src/api/fmt.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//! Implements formatting APIs
-
-#[macro_use]
-mod debug;
-#[macro_use]
-mod lower_hex;
-#[macro_use]
-mod upper_hex;
-#[macro_use]
-mod octal;
-#[macro_use]
-mod binary;
diff --git a/third_party/rust/packed_simd/src/api/fmt/binary.rs b/third_party/rust/packed_simd/src/api/fmt/binary.rs
deleted file mode 100644
index 91c0825559..0000000000
--- a/third_party/rust/packed_simd/src/api/fmt/binary.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-//! Implement Octal formatting
-
-macro_rules! impl_fmt_binary {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::fmt::Binary for $id {
- #[allow(clippy::missing_inline_in_public_items)]
- fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
- write!(f, "{}(", stringify!($id))?;
- for i in 0..$elem_count {
- if i > 0 {
- write!(f, ", ")?;
- }
- self.extract(i).fmt(f)?;
- }
- write!(f, ")")
- }
- }
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _fmt_binary>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn binary() {
- use arrayvec::{ArrayString,ArrayVec};
- type TinyString = ArrayString<[u8; 512]>;
-
- use crate::fmt::Write;
- let v = $id::splat($elem_ty::default());
- let mut s = TinyString::new();
- write!(&mut s, "{:#b}", v).unwrap();
-
- let mut beg = TinyString::new();
- write!(&mut beg, "{}(", stringify!($id)).unwrap();
- assert!(s.starts_with(beg.as_str()));
- assert!(s.ends_with(")"));
- let s: ArrayVec<[TinyString; 64]>
- = s.replace(beg.as_str(), "")
- .replace(")", "").split(",")
- .map(|v| TinyString::from(v.trim()).unwrap())
- .collect();
- assert_eq!(s.len(), $id::lanes());
- for (index, ss) in s.into_iter().enumerate() {
- let mut e = TinyString::new();
- write!(&mut e, "{:#b}", v.extract(index)).unwrap();
- assert_eq!(ss, e);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/fmt/debug.rs b/third_party/rust/packed_simd/src/api/fmt/debug.rs
deleted file mode 100644
index 1e209b3bff..0000000000
--- a/third_party/rust/packed_simd/src/api/fmt/debug.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-//! Implement debug formatting
-
-macro_rules! impl_fmt_debug_tests {
- ([$elem_ty:ty; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _fmt_debug>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn debug() {
- use arrayvec::{ArrayString,ArrayVec};
- type TinyString = ArrayString<[u8; 512]>;
-
- use crate::fmt::Write;
- let v = $id::default();
- let mut s = TinyString::new();
- write!(&mut s, "{:?}", v).unwrap();
-
- let mut beg = TinyString::new();
- write!(&mut beg, "{}(", stringify!($id)).unwrap();
- assert!(s.starts_with(beg.as_str()));
- assert!(s.ends_with(")"));
- let s: ArrayVec<[TinyString; 64]>
- = s.replace(beg.as_str(), "")
- .replace(")", "").split(",")
- .map(|v| TinyString::from(v.trim()).unwrap())
- .collect();
- assert_eq!(s.len(), $id::lanes());
- for (index, ss) in s.into_iter().enumerate() {
- let mut e = TinyString::new();
- write!(&mut e, "{:?}", v.extract(index)).unwrap();
- assert_eq!(ss, e);
- }
- }
- }
- }
- }
- };
-}
-
-macro_rules! impl_fmt_debug {
- ([$elem_ty:ty; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::fmt::Debug for $id {
- #[allow(clippy::missing_inline_in_public_items)]
- fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
- write!(f, "{}(", stringify!($id))?;
- for i in 0..$elem_count {
- if i > 0 {
- write!(f, ", ")?;
- }
- self.extract(i).fmt(f)?;
- }
- write!(f, ")")
- }
- }
- impl_fmt_debug_tests!([$elem_ty; $elem_count]: $id | $test_tt);
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/fmt/lower_hex.rs b/third_party/rust/packed_simd/src/api/fmt/lower_hex.rs
deleted file mode 100644
index 8f11d3119b..0000000000
--- a/third_party/rust/packed_simd/src/api/fmt/lower_hex.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-//! Implement `LowerHex` formatting
-
-macro_rules! impl_fmt_lower_hex {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::fmt::LowerHex for $id {
- #[allow(clippy::missing_inline_in_public_items)]
- fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
- write!(f, "{}(", stringify!($id))?;
- for i in 0..$elem_count {
- if i > 0 {
- write!(f, ", ")?;
- }
- self.extract(i).fmt(f)?;
- }
- write!(f, ")")
- }
- }
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _fmt_lower_hex>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn lower_hex() {
- use arrayvec::{ArrayString,ArrayVec};
- type TinyString = ArrayString<[u8; 512]>;
-
- use crate::fmt::Write;
- let v = $id::splat($elem_ty::default());
- let mut s = TinyString::new();
- write!(&mut s, "{:#x}", v).unwrap();
-
- let mut beg = TinyString::new();
- write!(&mut beg, "{}(", stringify!($id)).unwrap();
- assert!(s.starts_with(beg.as_str()));
- assert!(s.ends_with(")"));
- let s: ArrayVec<[TinyString; 64]>
- = s.replace(beg.as_str(), "").replace(")", "")
- .split(",")
- .map(|v| TinyString::from(v.trim()).unwrap())
- .collect();
- assert_eq!(s.len(), $id::lanes());
- for (index, ss) in s.into_iter().enumerate() {
- let mut e = TinyString::new();
- write!(&mut e, "{:#x}", v.extract(index)).unwrap();
- assert_eq!(ss, e);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/fmt/octal.rs b/third_party/rust/packed_simd/src/api/fmt/octal.rs
deleted file mode 100644
index e708e094ce..0000000000
--- a/third_party/rust/packed_simd/src/api/fmt/octal.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-//! Implement Octal formatting
-
-macro_rules! impl_fmt_octal {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::fmt::Octal for $id {
- #[allow(clippy::missing_inline_in_public_items)]
- fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
- write!(f, "{}(", stringify!($id))?;
- for i in 0..$elem_count {
- if i > 0 {
- write!(f, ", ")?;
- }
- self.extract(i).fmt(f)?;
- }
- write!(f, ")")
- }
- }
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _fmt_octal>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn octal_hex() {
- use arrayvec::{ArrayString,ArrayVec};
- type TinyString = ArrayString<[u8; 512]>;
-
- use crate::fmt::Write;
- let v = $id::splat($elem_ty::default());
- let mut s = TinyString::new();
- write!(&mut s, "{:#o}", v).unwrap();
-
- let mut beg = TinyString::new();
- write!(&mut beg, "{}(", stringify!($id)).unwrap();
- assert!(s.starts_with(beg.as_str()));
- assert!(s.ends_with(")"));
- let s: ArrayVec<[TinyString; 64]>
- = s.replace(beg.as_str(), "").replace(")", "")
- .split(",")
- .map(|v| TinyString::from(v.trim()).unwrap())
- .collect();
- assert_eq!(s.len(), $id::lanes());
- for (index, ss) in s.into_iter().enumerate() {
- let mut e = TinyString::new();
- write!(&mut e, "{:#o}", v.extract(index)).unwrap();
- assert_eq!(ss, e);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/fmt/upper_hex.rs b/third_party/rust/packed_simd/src/api/fmt/upper_hex.rs
deleted file mode 100644
index 5ad455706b..0000000000
--- a/third_party/rust/packed_simd/src/api/fmt/upper_hex.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-//! Implement `UpperHex` formatting
-
-macro_rules! impl_fmt_upper_hex {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::fmt::UpperHex for $id {
- #[allow(clippy::missing_inline_in_public_items)]
- fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
- write!(f, "{}(", stringify!($id))?;
- for i in 0..$elem_count {
- if i > 0 {
- write!(f, ", ")?;
- }
- self.extract(i).fmt(f)?;
- }
- write!(f, ")")
- }
- }
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _fmt_upper_hex>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn upper_hex() {
- use arrayvec::{ArrayString,ArrayVec};
- type TinyString = ArrayString<[u8; 512]>;
-
- use crate::fmt::Write;
- let v = $id::splat($elem_ty::default());
- let mut s = TinyString::new();
- write!(&mut s, "{:#X}", v).unwrap();
-
- let mut beg = TinyString::new();
- write!(&mut beg, "{}(", stringify!($id)).unwrap();
- assert!(s.starts_with(beg.as_str()));
- assert!(s.ends_with(")"));
- let s: ArrayVec<[TinyString; 64]>
- = s.replace(beg.as_str(), "").replace(")", "")
- .split(",")
- .map(|v| TinyString::from(v.trim()).unwrap())
- .collect();
- assert_eq!(s.len(), $id::lanes());
- for (index, ss) in s.into_iter().enumerate() {
- let mut e = TinyString::new();
- write!(&mut e, "{:#X}", v.extract(index)).unwrap();
- assert_eq!(ss, e);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/from.rs b/third_party/rust/packed_simd/src/api/from.rs
deleted file mode 100644
index c30c4d6e21..0000000000
--- a/third_party/rust/packed_simd/src/api/from.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//! Implementations of the `From` and `Into` traits
-
-#[macro_use]
-mod from_array;
-
-#[macro_use]
-mod from_vector;
diff --git a/third_party/rust/packed_simd/src/api/from/from_array.rs b/third_party/rust/packed_simd/src/api/from/from_array.rs
deleted file mode 100644
index 5c7801ddaf..0000000000
--- a/third_party/rust/packed_simd/src/api/from/from_array.rs
+++ /dev/null
@@ -1,124 +0,0 @@
-//! Implements `From<[T; N]>` and `Into<[T; N]>` for vector types.
-
-macro_rules! impl_from_array {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt
- | ($non_default_array:expr, $non_default_vec:expr)) => {
- impl From<[$elem_ty; $elem_count]> for $id {
- #[inline]
- fn from(array: [$elem_ty; $elem_count]) -> Self {
- union U {
- array: [$elem_ty; $elem_count],
- vec: $id,
- }
- unsafe { U { array }.vec }
- }
- }
-
- impl From<$id> for [$elem_ty; $elem_count] {
- #[inline]
- fn from(vec: $id) -> Self {
- union U {
- array: [$elem_ty; $elem_count],
- vec: $id,
- }
- unsafe { U { vec }.array }
- }
- }
-
- // FIXME: `Into::into` is not inline, but due to
- // the blanket impl in `std`, which is not
- // marked `default`, we cannot override it here with
- // specialization.
- /*
- impl Into<[$elem_ty; $elem_count]> for $id {
- #[inline]
- fn into(self) -> [$elem_ty; $elem_count] {
- union U {
- array: [$elem_ty; $elem_count],
- vec: $id,
- }
- unsafe { U { vec: self }.array }
- }
- }
-
- impl Into<$id> for [$elem_ty; $elem_count] {
- #[inline]
- fn into(self) -> $id {
- union U {
- array: [$elem_ty; $elem_count],
- vec: $id,
- }
- unsafe { U { array: self }.vec }
- }
- }
- */
-
- test_if! {
- $test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- mod [<$id _from>] {
- use super::*;
- #[test]
- #[cfg_attr(miri, ignore)]
- fn array() {
- let vec: $id = Default::default();
-
- // FIXME: Workaround for arrays with more than 32
- // elements.
- //
- // Safe because we never take a reference to any
- // uninitialized element.
- union W {
- array: [$elem_ty; $elem_count],
- other: ()
- }
- let mut array = W { other: () };
- for i in 0..$elem_count {
- let default: $elem_ty = Default::default();
- // note: array.other is the active member and
- // initialized so we can take a reference to it:
- let p = unsafe {
- &mut array.other as *mut () as *mut $elem_ty
- };
- // note: default is a valid bit-pattern for
- // $elem_ty:
- unsafe {
- crate::ptr::write(p.wrapping_add(i), default)
- };
- }
- // note: the array variant of the union is properly
- // initialized:
- let mut array = unsafe {
- array.array
- };
-
- array[0] = $non_default_array;
- let vec = vec.replace(0, $non_default_vec);
-
- let vec_from_array = $id::from(array);
- assert_eq!(vec_from_array, vec);
- let array_from_vec
- = <[$elem_ty; $elem_count]>::from(vec);
- // FIXME: Workaround for arrays with more than 32
- // elements.
- for i in 0..$elem_count {
- assert_eq!(array_from_vec[i], array[i]);
- }
-
- let vec_from_into_array: $id = array.into();
- assert_eq!(vec_from_into_array, vec);
- let array_from_into_vec: [$elem_ty; $elem_count]
- = vec.into();
- // FIXME: Workaround for arrays with more than 32
- // elements.
- for i in 0..$elem_count {
- assert_eq!(array_from_into_vec[i], array[i]);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/from/from_vector.rs b/third_party/rust/packed_simd/src/api/from/from_vector.rs
deleted file mode 100644
index 55f70016d5..0000000000
--- a/third_party/rust/packed_simd/src/api/from/from_vector.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! Implements `From` and `Into` for vector types.
-
-macro_rules! impl_from_vector {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt
- | $source:ident) => {
- impl From<$source> for $id {
- #[inline]
- fn from(source: $source) -> Self {
- fn static_assert_same_number_of_lanes<T, U>()
- where
- T: crate::sealed::Simd,
- U: crate::sealed::Simd<LanesType = T::LanesType>,
- {
- }
- use crate::llvm::simd_cast;
- static_assert_same_number_of_lanes::<$id, $source>();
- Simd(unsafe { simd_cast(source.0) })
- }
- }
-
- // FIXME: `Into::into` is not inline, but due to the blanket impl in
- // `std`, which is not marked `default`, we cannot override it here
- // with specialization.
-
- /*
- impl Into<$id> for $source {
- #[inline]
- fn into(self) -> $id {
- unsafe { simd_cast(self) }
- }
- }
- */
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _from_ $source>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn from() {
- assert_eq!($id::lanes(), $source::lanes());
- let source: $source = Default::default();
- let vec: $id = Default::default();
-
- let e = $id::from(source);
- assert_eq!(e, vec);
-
- let e: $id = source.into();
- assert_eq!(e, vec);
- }
- }
- }
- }
- };
-}
-
-macro_rules! impl_from_vectors {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt
- | $($source:ident),*) => {
- $(
- impl_from_vector!(
- [$elem_ty; $elem_count]: $id | $test_tt | $source
- );
- )*
- }
-}
diff --git a/third_party/rust/packed_simd/src/api/hash.rs b/third_party/rust/packed_simd/src/api/hash.rs
deleted file mode 100644
index ee80eff939..0000000000
--- a/third_party/rust/packed_simd/src/api/hash.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-//! Implements `Hash` for vector types.
-
-macro_rules! impl_hash {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::hash::Hash for $id {
- #[inline]
- fn hash<H: crate::hash::Hasher>(&self, state: &mut H) {
- unsafe {
- union A {
- data: [$elem_ty; $id::lanes()],
- vec: $id,
- }
- A { vec: *self }.data.hash(state)
- }
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _hash>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn hash() {
- use crate::hash::{Hash, Hasher};
- #[allow(deprecated)]
- use crate::hash::{SipHasher13};
- type A = [$elem_ty; $id::lanes()];
- let a: A = [42 as $elem_ty; $id::lanes()];
- assert_eq!(
- crate::mem::size_of::<A>(),
- crate::mem::size_of::<$id>()
- );
- #[allow(deprecated)]
- let mut a_hash = SipHasher13::new();
- let mut v_hash = a_hash.clone();
- a.hash(&mut a_hash);
-
- // Integer within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- let v = $id::splat(42 as $elem_ty);
- v.hash(&mut v_hash);
- assert_eq!(a_hash.finish(), v_hash.finish());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/into_bits.rs b/third_party/rust/packed_simd/src/api/into_bits.rs
deleted file mode 100644
index 03fbe4bff7..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-//! Implementation of `FromBits` and `IntoBits`.
-
-/// Safe lossless bitwise conversion from `T` to `Self`.
-#[cfg_attr(doc_cfg, doc(cfg(feature = "into_bits")))]
-pub trait FromBits<T>: crate::marker::Sized {
- /// Safe lossless bitwise transmute from `T` to `Self`.
- fn from_bits(t: T) -> Self;
-}
-
-/// Safe lossless bitwise conversion from `Self` to `T`.
-#[cfg_attr(doc_cfg, doc(cfg(feature = "into_bits")))]
-pub trait IntoBits<T>: crate::marker::Sized {
- /// Safe lossless bitwise transmute from `self` to `T`.
- fn into_bits(self) -> T;
-}
-
-/// `FromBits` implies `IntoBits`.
-impl<T, U> IntoBits<U> for T
-where
- U: FromBits<T>,
-{
- #[inline]
- fn into_bits(self) -> U {
- debug_assert!(crate::mem::size_of::<Self>() == crate::mem::size_of::<U>());
- U::from_bits(self)
- }
-}
-
-/// `FromBits` and `IntoBits` are reflexive
-impl<T> FromBits<T> for T {
- #[inline]
- fn from_bits(t: Self) -> Self {
- t
- }
-}
-
-#[macro_use]
-mod macros;
-
-mod v16;
-pub use self::v16::*;
-
-mod v32;
-pub use self::v32::*;
-
-mod v64;
-pub use self::v64::*;
-
-mod v128;
-pub use self::v128::*;
-
-mod v256;
-pub use self::v256::*;
-
-mod v512;
-pub use self::v512::*;
-
-mod arch_specific;
-pub use self::arch_specific::*;
diff --git a/third_party/rust/packed_simd/src/api/into_bits/arch_specific.rs b/third_party/rust/packed_simd/src/api/into_bits/arch_specific.rs
deleted file mode 100644
index bfac915576..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/arch_specific.rs
+++ /dev/null
@@ -1,345 +0,0 @@
-//! `FromBits` and `IntoBits` between portable vector types and the
-//! architecture-specific vector types.
-#[rustfmt::skip]
-
-// FIXME: MIPS FromBits/IntoBits
-
-#[allow(unused)]
-use crate::*;
-
-/// This macro implements FromBits for the portable and the architecture
-/// specific vector types.
-///
-/// The "leaf" case is at the bottom, and the most generic case is at the top.
-/// The generic case is split into smaller cases recursively.
-macro_rules! impl_arch {
- ([$arch_head_i:ident[$arch_head_tt:tt]: $($arch_head_ty:ident),*],
- $([$arch_tail_i:ident[$arch_tail_tt:tt]: $($arch_tail_ty:ident),*]),* |
- from: $($from_ty:ident),* | into: $($into_ty:ident),* |
- test: $test_tt:tt) => {
- impl_arch!(
- [$arch_head_i[$arch_head_tt]: $($arch_head_ty),*] |
- from: $($from_ty),* |
- into: $($into_ty),* |
- test: $test_tt
- );
- impl_arch!(
- $([$arch_tail_i[$arch_tail_tt]: $($arch_tail_ty),*]),* |
- from: $($from_ty),* |
- into: $($into_ty),* |
- test: $test_tt
- );
- };
- ([$arch:ident[$arch_tt:tt]: $($arch_ty:ident),*] |
- from: $($from_ty:ident),* | into: $($into_ty:ident),* |
- test: $test_tt:tt) => {
- // note: if target is "arm", "+v7,+neon" must be enabled
- // and the std library must be recompiled with them
- #[cfg(any(
- not(target_arch = "arm"),
- all(target_feature = "v7", target_feature = "neon",
- any(feature = "core_arch", libcore_neon)))
- )]
- // note: if target is "powerpc", "altivec" must be enabled
- // and the std library must be recompiled with it
- #[cfg(any(
- not(target_arch = "powerpc"),
- all(target_feature = "altivec", feature = "core_arch"),
- ))]
- #[cfg(target_arch = $arch_tt)]
- use crate::arch::$arch::{
- $($arch_ty),*
- };
-
- #[cfg(any(
- not(target_arch = "arm"),
- all(target_feature = "v7", target_feature = "neon",
- any(feature = "core_arch", libcore_neon)))
- )]
- #[cfg(any(
- not(target_arch = "powerpc"),
- all(target_feature = "altivec", feature = "core_arch"),
- ))]
- #[cfg(target_arch = $arch_tt)]
- impl_arch!($($arch_ty),* | $($from_ty),* | $($into_ty),* |
- test: $test_tt);
- };
- ($arch_head:ident, $($arch_tail:ident),* | $($from_ty:ident),*
- | $($into_ty:ident),* | test: $test_tt:tt) => {
- impl_arch!($arch_head | $($from_ty),* | $($into_ty),* |
- test: $test_tt);
- impl_arch!($($arch_tail),* | $($from_ty),* | $($into_ty),* |
- test: $test_tt);
- };
- ($arch_head:ident | $($from_ty:ident),* | $($into_ty:ident),* |
- test: $test_tt:tt) => {
- impl_from_bits!($arch_head[$test_tt]: $($from_ty),*);
- impl_into_bits!($arch_head[$test_tt]: $($into_ty),*);
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Implementations for the 64-bit wide vector types:
-
-// FIXME: 64-bit single element types
-// FIXME: arm/aarch float16x4_t missing
-impl_arch!(
- [
- arm["arm"]: int8x8_t,
- uint8x8_t,
- poly8x8_t,
- int16x4_t,
- uint16x4_t,
- poly16x4_t,
- int32x2_t,
- uint32x2_t,
- float32x2_t,
- int64x1_t,
- uint64x1_t
- ],
- [
- aarch64["aarch64"]: int8x8_t,
- uint8x8_t,
- poly8x8_t,
- int16x4_t,
- uint16x4_t,
- poly16x4_t,
- int32x2_t,
- uint32x2_t,
- float32x2_t,
- int64x1_t,
- uint64x1_t,
- float64x1_t
- ] | from: i8x8,
- u8x8,
- m8x8,
- i16x4,
- u16x4,
- m16x4,
- i32x2,
- u32x2,
- f32x2,
- m32x2 | into: i8x8,
- u8x8,
- i16x4,
- u16x4,
- i32x2,
- u32x2,
- f32x2 | test: test_v64
-);
-
-////////////////////////////////////////////////////////////////////////////////
-// Implementations for the 128-bit wide vector types:
-
-// FIXME: arm/aarch float16x8_t missing
-// FIXME: ppc vector_pixel missing
-// FIXME: ppc64 vector_Float16 missing
-// FIXME: ppc64 vector_signed_long_long missing
-// FIXME: ppc64 vector_unsigned_long_long missing
-// FIXME: ppc64 vector_bool_long_long missing
-// FIXME: ppc64 vector_signed___int128 missing
-// FIXME: ppc64 vector_unsigned___int128 missing
-impl_arch!(
- [x86["x86"]: __m128, __m128i, __m128d],
- [x86_64["x86_64"]: __m128, __m128i, __m128d],
- [
- arm["arm"]: int8x16_t,
- uint8x16_t,
- poly8x16_t,
- int16x8_t,
- uint16x8_t,
- poly16x8_t,
- int32x4_t,
- uint32x4_t,
- float32x4_t,
- int64x2_t,
- uint64x2_t
- ],
- [
- aarch64["aarch64"]: int8x16_t,
- uint8x16_t,
- poly8x16_t,
- int16x8_t,
- uint16x8_t,
- poly16x8_t,
- int32x4_t,
- uint32x4_t,
- float32x4_t,
- int64x2_t,
- uint64x2_t,
- float64x2_t
- ],
- [
- powerpc["powerpc"]: vector_signed_char,
- vector_unsigned_char,
- vector_signed_short,
- vector_unsigned_short,
- vector_signed_int,
- vector_unsigned_int,
- vector_float
- ],
- [
- powerpc64["powerpc64"]: vector_signed_char,
- vector_unsigned_char,
- vector_signed_short,
- vector_unsigned_short,
- vector_signed_int,
- vector_unsigned_int,
- vector_float,
- vector_signed_long,
- vector_unsigned_long,
- vector_double
- ] | from: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1 | into: i8x16,
- u8x16,
- i16x8,
- u16x8,
- i32x4,
- u32x4,
- f32x4,
- i64x2,
- u64x2,
- f64x2,
- i128x1,
- u128x1 | test: test_v128
-);
-
-impl_arch!(
- [powerpc["powerpc"]: vector_bool_char],
- [powerpc64["powerpc64"]: vector_bool_char] | from: m8x16,
- m16x8,
- m32x4,
- m64x2,
- m128x1 | into: i8x16,
- u8x16,
- i16x8,
- u16x8,
- i32x4,
- u32x4,
- f32x4,
- i64x2,
- u64x2,
- f64x2,
- i128x1,
- u128x1,
- // Masks:
- m8x16 | test: test_v128
-);
-
-impl_arch!(
- [powerpc["powerpc"]: vector_bool_short],
- [powerpc64["powerpc64"]: vector_bool_short] | from: m16x8,
- m32x4,
- m64x2,
- m128x1 | into: i8x16,
- u8x16,
- i16x8,
- u16x8,
- i32x4,
- u32x4,
- f32x4,
- i64x2,
- u64x2,
- f64x2,
- i128x1,
- u128x1,
- // Masks:
- m8x16,
- m16x8 | test: test_v128
-);
-
-impl_arch!(
- [powerpc["powerpc"]: vector_bool_int],
- [powerpc64["powerpc64"]: vector_bool_int] | from: m32x4,
- m64x2,
- m128x1 | into: i8x16,
- u8x16,
- i16x8,
- u16x8,
- i32x4,
- u32x4,
- f32x4,
- i64x2,
- u64x2,
- f64x2,
- i128x1,
- u128x1,
- // Masks:
- m8x16,
- m16x8,
- m32x4 | test: test_v128
-);
-
-impl_arch!(
- [powerpc64["powerpc64"]: vector_bool_long] | from: m64x2,
- m128x1 | into: i8x16,
- u8x16,
- i16x8,
- u16x8,
- i32x4,
- u32x4,
- f32x4,
- i64x2,
- u64x2,
- f64x2,
- i128x1,
- u128x1,
- // Masks:
- m8x16,
- m16x8,
- m32x4,
- m64x2 | test: test_v128
-);
-
-////////////////////////////////////////////////////////////////////////////////
-// Implementations for the 256-bit wide vector types
-
-impl_arch!(
- [x86["x86"]: __m256, __m256i, __m256d],
- [x86_64["x86_64"]: __m256, __m256i, __m256d] | from: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2 | into: i8x32,
- u8x32,
- i16x16,
- u16x16,
- i32x8,
- u32x8,
- f32x8,
- i64x4,
- u64x4,
- f64x4,
- i128x2,
- u128x2 | test: test_v256
-);
-
-////////////////////////////////////////////////////////////////////////////////
-// FIXME: Implementations for the 512-bit wide vector types
diff --git a/third_party/rust/packed_simd/src/api/into_bits/macros.rs b/third_party/rust/packed_simd/src/api/into_bits/macros.rs
deleted file mode 100644
index 265ab34ae0..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/macros.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-//! Macros implementing `FromBits`
-
-macro_rules! impl_from_bits_ {
- ($id:ident[$test_tt:tt]: $from_ty:ident) => {
- impl crate::api::into_bits::FromBits<$from_ty> for $id {
- #[inline]
- fn from_bits(x: $from_ty) -> Self {
- unsafe { crate::mem::transmute(x) }
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _from_bits_ $from_ty>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn test() {
- use crate::{
- ptr::{read_unaligned},
- mem::{size_of, zeroed}
- };
- use crate::IntoBits;
- assert_eq!(size_of::<$id>(),
- size_of::<$from_ty>());
- // This is safe because we never create a reference to
- // uninitialized memory:
- let a: $from_ty = unsafe { zeroed() };
-
- let b_0: $id = crate::FromBits::from_bits(a);
- let b_1: $id = a.into_bits();
-
- // Check that these are byte-wise equal, that is,
- // that the bit patterns are identical:
- for i in 0..size_of::<$id>() {
- // This is safe because we only read initialized
- // memory in bounds. Also, taking a reference to
- // `b_i` is ok because the fields are initialized.
- unsafe {
- let b_0_v: u8 = read_unaligned(
- (&b_0 as *const $id as *const u8)
- .wrapping_add(i)
- );
- let b_1_v: u8 = read_unaligned(
- (&b_1 as *const $id as *const u8)
- .wrapping_add(i)
- );
- assert_eq!(b_0_v, b_1_v);
- }
- }
- }
- }
- }
- }
- };
-}
-
-macro_rules! impl_from_bits {
- ($id:ident[$test_tt:tt]: $($from_ty:ident),*) => {
- $(
- impl_from_bits_!($id[$test_tt]: $from_ty);
- )*
- }
-}
-
-#[allow(unused)]
-macro_rules! impl_into_bits {
- ($id:ident[$test_tt:tt]: $($from_ty:ident),*) => {
- $(
- impl_from_bits_!($from_ty[$test_tt]: $id);
- )*
- }
-}
diff --git a/third_party/rust/packed_simd/src/api/into_bits/v128.rs b/third_party/rust/packed_simd/src/api/into_bits/v128.rs
deleted file mode 100644
index 639c09c2c4..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/v128.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-//! `FromBits` and `IntoBits` implementations for portable 128-bit wide vectors
-#[rustfmt::skip]
-
-#[allow(unused)] // wasm_bindgen_test
-use crate::*;
-
-impl_from_bits!(
- i8x16[test_v128]: u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(
- u8x16[test_v128]: i8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(m8x16[test_v128]: m16x8, m32x4, m64x2, m128x1);
-
-impl_from_bits!(
- i16x8[test_v128]: i8x16,
- u8x16,
- m8x16,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(
- u16x8[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(m16x8[test_v128]: m32x4, m64x2, m128x1);
-
-impl_from_bits!(
- i32x4[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(
- u32x4[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(
- f32x4[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(m32x4[test_v128]: m64x2, m128x1);
-
-impl_from_bits!(
- i64x2[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(
- u64x2[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- f64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(
- f64x2[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- m64x2,
- i128x1,
- u128x1,
- m128x1
-);
-impl_from_bits!(m64x2[test_v128]: m128x1);
-
-impl_from_bits!(
- i128x1[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- u128x1,
- m128x1
-);
-impl_from_bits!(
- u128x1[test_v128]: i8x16,
- u8x16,
- m8x16,
- i16x8,
- u16x8,
- m16x8,
- i32x4,
- u32x4,
- f32x4,
- m32x4,
- i64x2,
- u64x2,
- f64x2,
- m64x2,
- i128x1,
- m128x1
-);
-// note: m128x1 cannot be constructed from all the other masks bit patterns in
-// here
diff --git a/third_party/rust/packed_simd/src/api/into_bits/v16.rs b/third_party/rust/packed_simd/src/api/into_bits/v16.rs
deleted file mode 100644
index e44d0e7f9a..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/v16.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//! `FromBits` and `IntoBits` implementations for portable 16-bit wide vectors
-#[rustfmt::skip]
-
-#[allow(unused)] // wasm_bindgen_test
-use crate::*;
-
-impl_from_bits!(i8x2[test_v16]: u8x2, m8x2);
-impl_from_bits!(u8x2[test_v16]: i8x2, m8x2);
-// note: m8x2 cannot be constructed from all i8x2 or u8x2 bit patterns
diff --git a/third_party/rust/packed_simd/src/api/into_bits/v256.rs b/third_party/rust/packed_simd/src/api/into_bits/v256.rs
deleted file mode 100644
index e432bbbc9f..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/v256.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-//! `FromBits` and `IntoBits` implementations for portable 256-bit wide vectors
-#[rustfmt::skip]
-
-#[allow(unused)] // wasm_bindgen_test
-use crate::*;
-
-impl_from_bits!(
- i8x32[test_v256]: u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(
- u8x32[test_v256]: i8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(m8x32[test_v256]: m16x16, m32x8, m64x4, m128x2);
-
-impl_from_bits!(
- i16x16[test_v256]: i8x32,
- u8x32,
- m8x32,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(
- u16x16[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(m16x16[test_v256]: m32x8, m64x4, m128x2);
-
-impl_from_bits!(
- i32x8[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(
- u32x8[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(
- f32x8[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(m32x8[test_v256]: m64x4, m128x2);
-
-impl_from_bits!(
- i64x4[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(
- u64x4[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- f64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(
- f64x4[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- m64x4,
- i128x2,
- u128x2,
- m128x2
-);
-impl_from_bits!(m64x4[test_v256]: m128x2);
-
-impl_from_bits!(
- i128x2[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- u128x2,
- m128x2
-);
-impl_from_bits!(
- u128x2[test_v256]: i8x32,
- u8x32,
- m8x32,
- i16x16,
- u16x16,
- m16x16,
- i32x8,
- u32x8,
- f32x8,
- m32x8,
- i64x4,
- u64x4,
- f64x4,
- m64x4,
- i128x2,
- m128x2
-);
-// note: m128x2 cannot be constructed from all the other masks bit patterns in
-// here
diff --git a/third_party/rust/packed_simd/src/api/into_bits/v32.rs b/third_party/rust/packed_simd/src/api/into_bits/v32.rs
deleted file mode 100644
index 5dba38a179..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/v32.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//! `FromBits` and `IntoBits` implementations for portable 32-bit wide vectors
-#[rustfmt::skip]
-
-#[allow(unused)] // wasm_bindgen_test
-use crate::*;
-
-impl_from_bits!(i8x4[test_v32]: u8x4, m8x4, i16x2, u16x2, m16x2);
-impl_from_bits!(u8x4[test_v32]: i8x4, m8x4, i16x2, u16x2, m16x2);
-impl_from_bits!(m8x4[test_v32]: m16x2);
-
-impl_from_bits!(i16x2[test_v32]: i8x4, u8x4, m8x4, u16x2, m16x2);
-impl_from_bits!(u16x2[test_v32]: i8x4, u8x4, m8x4, i16x2, m16x2);
-// note: m16x2 cannot be constructed from all m8x4 bit patterns
diff --git a/third_party/rust/packed_simd/src/api/into_bits/v512.rs b/third_party/rust/packed_simd/src/api/into_bits/v512.rs
deleted file mode 100644
index f6e9bb8bf7..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/v512.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-//! `FromBits` and `IntoBits` implementations for portable 512-bit wide vectors
-#[rustfmt::skip]
-
-#[allow(unused)] // wasm_bindgen_test
-use crate::*;
-
-impl_from_bits!(
- i8x64[test_v512]: u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(
- u8x64[test_v512]: i8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(m8x64[test_v512]: m16x32, m32x16, m64x8, m128x4);
-
-impl_from_bits!(
- i16x32[test_v512]: i8x64,
- u8x64,
- m8x64,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(
- u16x32[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(m16x32[test_v512]: m32x16, m64x8, m128x4);
-
-impl_from_bits!(
- i32x16[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(
- u32x16[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(
- f32x16[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(m32x16[test_v512]: m64x8, m128x4);
-
-impl_from_bits!(
- i64x8[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(
- u64x8[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- f64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(
- f64x8[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- m64x8,
- i128x4,
- u128x4,
- m128x4
-);
-impl_from_bits!(m64x8[test_v512]: m128x4);
-
-impl_from_bits!(
- i128x4[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- u128x4,
- m128x4
-);
-impl_from_bits!(
- u128x4[test_v512]: i8x64,
- u8x64,
- m8x64,
- i16x32,
- u16x32,
- m16x32,
- i32x16,
- u32x16,
- f32x16,
- m32x16,
- i64x8,
- u64x8,
- f64x8,
- m64x8,
- i128x4,
- m128x4
-);
-// note: m128x4 cannot be constructed from all the other masks bit patterns in
-// here
diff --git a/third_party/rust/packed_simd/src/api/into_bits/v64.rs b/third_party/rust/packed_simd/src/api/into_bits/v64.rs
deleted file mode 100644
index 5b065f1bd5..0000000000
--- a/third_party/rust/packed_simd/src/api/into_bits/v64.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! `FromBits` and `IntoBits` implementations for portable 64-bit wide vectors
-#[rustfmt::skip]
-
-#[allow(unused)] // wasm_bindgen_test
-use crate::*;
-
-impl_from_bits!(i8x8[test_v64]: u8x8, m8x8, i16x4, u16x4, m16x4, i32x2, u32x2, f32x2, m32x2);
-impl_from_bits!(u8x8[test_v64]: i8x8, m8x8, i16x4, u16x4, m16x4, i32x2, u32x2, f32x2, m32x2);
-impl_from_bits!(m8x8[test_v64]: m16x4, m32x2);
-
-impl_from_bits!(i16x4[test_v64]: i8x8, u8x8, m8x8, u16x4, m16x4, i32x2, u32x2, f32x2, m32x2);
-impl_from_bits!(u16x4[test_v64]: i8x8, u8x8, m8x8, i16x4, m16x4, i32x2, u32x2, f32x2, m32x2);
-impl_from_bits!(m16x4[test_v64]: m32x2);
-
-impl_from_bits!(i32x2[test_v64]: i8x8, u8x8, m8x8, i16x4, u16x4, m16x4, u32x2, f32x2, m32x2);
-impl_from_bits!(u32x2[test_v64]: i8x8, u8x8, m8x8, i16x4, u16x4, m16x4, i32x2, f32x2, m32x2);
-impl_from_bits!(f32x2[test_v64]: i8x8, u8x8, m8x8, i16x4, u16x4, m16x4, i32x2, u32x2, m32x2);
-// note: m32x2 cannot be constructed from all m16x4 or m8x8 bit patterns
diff --git a/third_party/rust/packed_simd/src/api/math.rs b/third_party/rust/packed_simd/src/api/math.rs
deleted file mode 100644
index e7a8d256ba..0000000000
--- a/third_party/rust/packed_simd/src/api/math.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//! Implements vertical math operations
-
-#[macro_use]
-mod float;
diff --git a/third_party/rust/packed_simd/src/api/math/float.rs b/third_party/rust/packed_simd/src/api/math/float.rs
deleted file mode 100644
index d5d2bee2eb..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-//! Implements vertical floating-point math operations.
-
-#[macro_use]
-mod abs;
-
-#[macro_use]
-mod consts;
-
-#[macro_use]
-mod cos;
-
-#[macro_use]
-mod exp;
-
-#[macro_use]
-mod powf;
-
-#[macro_use]
-mod ln;
-
-#[macro_use]
-mod mul_add;
-
-#[macro_use]
-mod mul_adde;
-
-#[macro_use]
-mod recpre;
-
-#[macro_use]
-mod rsqrte;
-
-#[macro_use]
-mod sin;
-
-#[macro_use]
-mod sqrt;
-
-#[macro_use]
-mod sqrte;
-
-#[macro_use]
-mod tanh;
-
-macro_rules! impl_float_category {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident, $mask_ty:ident) => {
- impl $id {
- #[inline]
- pub fn is_nan(self) -> $mask_ty {
- self.ne(self)
- }
-
- #[inline]
- pub fn is_infinite(self) -> $mask_ty {
- self.eq(Self::INFINITY) | self.eq(Self::NEG_INFINITY)
- }
-
- #[inline]
- pub fn is_finite(self) -> $mask_ty {
- !(self.is_nan() | self.is_infinite())
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/abs.rs b/third_party/rust/packed_simd/src/api/math/float/abs.rs
deleted file mode 100644
index 1865bdb68e..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/abs.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `abs`.
-
-macro_rules! impl_math_float_abs {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Absolute value.
- #[inline]
- pub fn abs(self) -> Self {
- use crate::codegen::math::float::abs::Abs;
- Abs::abs(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_abs>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn abs() {
- let o = $id::splat(1 as $elem_ty);
- assert_eq!(o, o.abs());
-
- let mo = $id::splat(-1 as $elem_ty);
- assert_eq!(o, mo.abs());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/consts.rs b/third_party/rust/packed_simd/src/api/math/float/consts.rs
deleted file mode 100644
index 7f41acbf1b..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/consts.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-macro_rules! impl_float_consts {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident) => {
- impl $id {
- /// Machine epsilon value.
- pub const EPSILON: $id = $id::splat(core::$elem_ty::EPSILON);
-
- /// Smallest finite value.
- pub const MIN: $id = $id::splat(core::$elem_ty::MIN);
-
- /// Smallest positive normal value.
- pub const MIN_POSITIVE: $id = $id::splat(core::$elem_ty::MIN_POSITIVE);
-
- /// Largest finite value.
- pub const MAX: $id = $id::splat(core::$elem_ty::MAX);
-
- /// Not a Number (NaN).
- pub const NAN: $id = $id::splat(core::$elem_ty::NAN);
-
- /// Infinity (∞).
- pub const INFINITY: $id = $id::splat(core::$elem_ty::INFINITY);
-
- /// Negative infinity (-∞).
- pub const NEG_INFINITY: $id = $id::splat(core::$elem_ty::NEG_INFINITY);
-
- /// Archimedes' constant (π)
- pub const PI: $id = $id::splat(core::$elem_ty::consts::PI);
-
- /// π/2
- pub const FRAC_PI_2: $id = $id::splat(core::$elem_ty::consts::FRAC_PI_2);
-
- /// π/3
- pub const FRAC_PI_3: $id = $id::splat(core::$elem_ty::consts::FRAC_PI_3);
-
- /// π/4
- pub const FRAC_PI_4: $id = $id::splat(core::$elem_ty::consts::FRAC_PI_4);
-
- /// π/6
- pub const FRAC_PI_6: $id = $id::splat(core::$elem_ty::consts::FRAC_PI_6);
-
- /// π/8
- pub const FRAC_PI_8: $id = $id::splat(core::$elem_ty::consts::FRAC_PI_8);
-
- /// 1/π
- pub const FRAC_1_PI: $id = $id::splat(core::$elem_ty::consts::FRAC_1_PI);
-
- /// 2/π
- pub const FRAC_2_PI: $id = $id::splat(core::$elem_ty::consts::FRAC_2_PI);
-
- /// 2/sqrt(π)
- pub const FRAC_2_SQRT_PI: $id = $id::splat(core::$elem_ty::consts::FRAC_2_SQRT_PI);
-
- /// sqrt(2)
- pub const SQRT_2: $id = $id::splat(core::$elem_ty::consts::SQRT_2);
-
- /// 1/sqrt(2)
- pub const FRAC_1_SQRT_2: $id = $id::splat(core::$elem_ty::consts::FRAC_1_SQRT_2);
-
- /// Euler's number (e)
- pub const E: $id = $id::splat(core::$elem_ty::consts::E);
-
- /// log<sub>2</sub>(e)
- pub const LOG2_E: $id = $id::splat(core::$elem_ty::consts::LOG2_E);
-
- /// log<sub>10</sub>(e)
- pub const LOG10_E: $id = $id::splat(core::$elem_ty::consts::LOG10_E);
-
- /// ln(2)
- pub const LN_2: $id = $id::splat(core::$elem_ty::consts::LN_2);
-
- /// ln(10)
- pub const LN_10: $id = $id::splat(core::$elem_ty::consts::LN_10);
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/cos.rs b/third_party/rust/packed_simd/src/api/math/float/cos.rs
deleted file mode 100644
index e5b8f46036..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/cos.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `cos`.
-
-macro_rules! impl_math_float_cos {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Cosine.
- #[inline]
- pub fn cos(self) -> Self {
- use crate::codegen::math::float::cos::Cos;
- Cos::cos(self)
- }
-
- /// Cosine of `self * PI`.
- #[inline]
- pub fn cos_pi(self) -> Self {
- use crate::codegen::math::float::cos_pi::CosPi;
- CosPi::cos_pi(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_cos>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn cos() {
- use crate::$elem_ty::consts::PI;
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let p = $id::splat(PI as $elem_ty);
- let ph = $id::splat(PI as $elem_ty / 2.);
- let z_r = $id::splat((PI as $elem_ty / 2.).cos());
- let o_r = $id::splat((PI as $elem_ty).cos());
-
- assert_eq!(o, z.cos());
- assert_eq!(z_r, ph.cos());
- assert_eq!(o_r, p.cos());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/exp.rs b/third_party/rust/packed_simd/src/api/math/float/exp.rs
deleted file mode 100644
index e3356d853a..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/exp.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `exp`.
-
-macro_rules! impl_math_float_exp {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Returns the exponential function of `self`: `e^(self)`.
- #[inline]
- pub fn exp(self) -> Self {
- use crate::codegen::math::float::exp::Exp;
- Exp::exp(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_exp>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn exp() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- assert_eq!(o, z.exp());
-
- let e = $id::splat(crate::f64::consts::E as $elem_ty);
- let tol = $id::splat(2.4e-4 as $elem_ty);
- assert!((e - o.exp()).abs().le(tol).all());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/ln.rs b/third_party/rust/packed_simd/src/api/math/float/ln.rs
deleted file mode 100644
index 5ceb9173ae..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/ln.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `ln`.
-
-macro_rules! impl_math_float_ln {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Returns the natural logarithm of `self`.
- #[inline]
- pub fn ln(self) -> Self {
- use crate::codegen::math::float::ln::Ln;
- Ln::ln(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_ln>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn ln() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- assert_eq!(z, o.ln());
-
- let e = $id::splat(crate::f64::consts::E as $elem_ty);
- let tol = $id::splat(2.4e-4 as $elem_ty);
- assert!((o - e.ln()).abs().le(tol).all());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/mul_add.rs b/third_party/rust/packed_simd/src/api/math/float/mul_add.rs
deleted file mode 100644
index 4b170ee2b7..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/mul_add.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `mul_add`.
-
-macro_rules! impl_math_float_mul_add {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Fused multiply add: `self * y + z`
- #[inline]
- pub fn mul_add(self, y: Self, z: Self) -> Self {
- use crate::codegen::math::float::mul_add::MulAdd;
- MulAdd::mul_add(self, y, z)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_mul_add>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn mul_add() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let t3 = $id::splat(3 as $elem_ty);
- let f = $id::splat(4 as $elem_ty);
-
- assert_eq!(z, z.mul_add(z, z));
- assert_eq!(o, o.mul_add(o, z));
- assert_eq!(o, o.mul_add(z, o));
- assert_eq!(o, z.mul_add(o, o));
-
- assert_eq!(t, o.mul_add(o, o));
- assert_eq!(t, o.mul_add(t, z));
- assert_eq!(t, t.mul_add(o, z));
-
- assert_eq!(f, t.mul_add(t, z));
- assert_eq!(f, t.mul_add(o, t));
- assert_eq!(t3, t.mul_add(o, o));
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/mul_adde.rs b/third_party/rust/packed_simd/src/api/math/float/mul_adde.rs
deleted file mode 100644
index c5b27110f2..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/mul_adde.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `mul_adde`.
-
-macro_rules! impl_math_float_mul_adde {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Fused multiply add estimate: ~= `self * y + z`
- ///
- /// While fused multiply-add (`fma`) has infinite precision,
- /// `mul_adde` has _at worst_ the same precision of a multiply followed by an add.
- /// This might be more efficient on architectures that do not have an `fma` instruction.
- #[inline]
- pub fn mul_adde(self, y: Self, z: Self) -> Self {
- use crate::codegen::math::float::mul_adde::MulAddE;
- MulAddE::mul_adde(self, y, z)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_mul_adde>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn mul_adde() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let t3 = $id::splat(3 as $elem_ty);
- let f = $id::splat(4 as $elem_ty);
-
- assert_eq!(z, z.mul_adde(z, z));
- assert_eq!(o, o.mul_adde(o, z));
- assert_eq!(o, o.mul_adde(z, o));
- assert_eq!(o, z.mul_adde(o, o));
-
- assert_eq!(t, o.mul_adde(o, o));
- assert_eq!(t, o.mul_adde(t, z));
- assert_eq!(t, t.mul_adde(o, z));
-
- assert_eq!(f, t.mul_adde(t, z));
- assert_eq!(f, t.mul_adde(o, t));
- assert_eq!(t3, t.mul_adde(o, o));
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/powf.rs b/third_party/rust/packed_simd/src/api/math/float/powf.rs
deleted file mode 100644
index 83dc9ff9c0..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/powf.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `powf`.
-
-macro_rules! impl_math_float_powf {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Raises `self` number to the floating point power of `x`.
- #[inline]
- pub fn powf(self, x: Self) -> Self {
- use crate::codegen::math::float::powf::Powf;
- Powf::powf(self, x)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_powf>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn powf() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- assert_eq!(o, o.powf(z));
- assert_eq!(o, t.powf(z));
- assert_eq!(o, o.powf(o));
- assert_eq!(t, t.powf(o));
-
- let f = $id::splat(4 as $elem_ty);
- assert_eq!(f, t.powf(t));
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/recpre.rs b/third_party/rust/packed_simd/src/api/math/float/recpre.rs
deleted file mode 100644
index 127f0b2ff6..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/recpre.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `recpre`.
-
-macro_rules! impl_math_float_recpre {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Reciprocal estimate: `~= 1. / self`.
- ///
- /// FIXME: The precision of the estimate is currently unspecified.
- #[inline]
- pub fn recpre(self) -> Self {
- $id::splat(1.) / self
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_recpre>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn recpre() {
- let tol = $id::splat(2.4e-4 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let error = (o - o.recpre()).abs();
- assert!(error.le(tol).all());
-
- let t = $id::splat(2 as $elem_ty);
- let e = 0.5;
- let error = (e - t.recpre()).abs();
- assert!(error.le(tol).all());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/rsqrte.rs b/third_party/rust/packed_simd/src/api/math/float/rsqrte.rs
deleted file mode 100644
index c77977f7b1..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/rsqrte.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `rsqrte`.
-
-macro_rules! impl_math_float_rsqrte {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Reciprocal square-root estimate: `~= 1. / self.sqrt()`.
- ///
- /// FIXME: The precision of the estimate is currently unspecified.
- #[inline]
- pub fn rsqrte(self) -> Self {
- unsafe {
- use crate::llvm::simd_fsqrt;
- $id::splat(1.) / Simd(simd_fsqrt(self.0))
- }
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_rsqrte>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn rsqrte() {
- use crate::$elem_ty::consts::SQRT_2;
- let tol = $id::splat(2.4e-4 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let error = (o - o.rsqrte()).abs();
- assert!(error.le(tol).all());
-
- let t = $id::splat(2 as $elem_ty);
- let e = 1. / SQRT_2;
- let error = (e - t.rsqrte()).abs();
- assert!(error.le(tol).all());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/sin.rs b/third_party/rust/packed_simd/src/api/math/float/sin.rs
deleted file mode 100644
index 49908319b1..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/sin.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `sin`.
-
-macro_rules! impl_math_float_sin {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Sine.
- #[inline]
- pub fn sin(self) -> Self {
- use crate::codegen::math::float::sin::Sin;
- Sin::sin(self)
- }
-
- /// Sine of `self * PI`.
- #[inline]
- pub fn sin_pi(self) -> Self {
- use crate::codegen::math::float::sin_pi::SinPi;
- SinPi::sin_pi(self)
- }
-
- /// Sine and cosine of `self * PI`.
- #[inline]
- pub fn sin_cos_pi(self) -> (Self, Self) {
- use crate::codegen::math::float::sin_cos_pi::SinCosPi;
- SinCosPi::sin_cos_pi(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_sin>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn sin() {
- use crate::$elem_ty::consts::PI;
- let z = $id::splat(0 as $elem_ty);
- let p = $id::splat(PI as $elem_ty);
- let ph = $id::splat(PI as $elem_ty / 2.);
- let o_r = $id::splat((PI as $elem_ty / 2.).sin());
- let z_r = $id::splat((PI as $elem_ty).sin());
-
- assert_eq!(z, z.sin());
- assert_eq!(o_r, ph.sin());
- assert_eq!(z_r, p.sin());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/sqrt.rs b/third_party/rust/packed_simd/src/api/math/float/sqrt.rs
deleted file mode 100644
index ae624122d0..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/sqrt.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `sqrt`.
-
-macro_rules! impl_math_float_sqrt {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- #[inline]
- pub fn sqrt(self) -> Self {
- use crate::codegen::math::float::sqrt::Sqrt;
- Sqrt::sqrt(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_sqrt>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn sqrt() {
- use crate::$elem_ty::consts::SQRT_2;
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- assert_eq!(z, z.sqrt());
- assert_eq!(o, o.sqrt());
-
- let t = $id::splat(2 as $elem_ty);
- let e = $id::splat(SQRT_2);
- assert_eq!(e, t.sqrt());
-
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/sqrte.rs b/third_party/rust/packed_simd/src/api/math/float/sqrte.rs
deleted file mode 100644
index f7ffad748d..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/sqrte.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `sqrte`.
-
-macro_rules! impl_math_float_sqrte {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Square-root estimate.
- ///
- /// FIXME: The precision of the estimate is currently unspecified.
- #[inline]
- pub fn sqrte(self) -> Self {
- use crate::codegen::math::float::sqrte::Sqrte;
- Sqrte::sqrte(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_sqrte>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn sqrte() {
- use crate::$elem_ty::consts::SQRT_2;
- let tol = $id::splat(2.4e-4 as $elem_ty);
-
- let z = $id::splat(0 as $elem_ty);
- let error = (z - z.sqrte()).abs();
- assert!(error.le(tol).all());
-
- let o = $id::splat(1 as $elem_ty);
- let error = (o - o.sqrte()).abs();
- assert!(error.le(tol).all());
-
- let t = $id::splat(2 as $elem_ty);
- let e = $id::splat(SQRT_2 as $elem_ty);
- let error = (e - t.sqrte()).abs();
-
- assert!(error.le(tol).all());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/math/float/tanh.rs b/third_party/rust/packed_simd/src/api/math/float/tanh.rs
deleted file mode 100644
index acfd93caaa..0000000000
--- a/third_party/rust/packed_simd/src/api/math/float/tanh.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `tanh`.
-
-macro_rules! impl_math_float_tanh {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Tanh.
- #[inline]
- pub fn tanh(self) -> Self {
- use crate::codegen::math::float::tanh::Tanh;
- Tanh::tanh(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_tanh>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn tanh() {
- let z = $id::splat(0 as $elem_ty);
-
- assert_eq!(z, z.tanh());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/minimal.rs b/third_party/rust/packed_simd/src/api/minimal.rs
deleted file mode 100644
index 840d9e3258..0000000000
--- a/third_party/rust/packed_simd/src/api/minimal.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#[macro_use]
-mod iuf;
-#[macro_use]
-mod mask;
-#[macro_use]
-mod ptr;
diff --git a/third_party/rust/packed_simd/src/api/minimal/iuf.rs b/third_party/rust/packed_simd/src/api/minimal/iuf.rs
deleted file mode 100644
index a155ac178a..0000000000
--- a/third_party/rust/packed_simd/src/api/minimal/iuf.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-//! Minimal API of signed integer, unsigned integer, and floating-point
-//! vectors.
-
-macro_rules! impl_minimal_iuf {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $ielem_ty:ident |
- $test_tt:tt | $($elem_name:ident),+ | $(#[$doc:meta])*) => {
-
- $(#[$doc])*
- pub type $id = Simd<[$elem_ty; $elem_count]>;
-
- impl sealed::Simd for $id {
- type Element = $elem_ty;
- const LANES: usize = $elem_count;
- type LanesType = [u32; $elem_count];
- }
-
- impl $id {
- /// Creates a new instance with each vector elements initialized
- /// with the provided values.
- #[inline]
- #[allow(clippy::too_many_arguments)]
- pub const fn new($($elem_name: $elem_ty),*) -> Self {
- Simd(codegen::$id($($elem_name as $ielem_ty),*))
- }
-
- /// Returns the number of vector lanes.
- #[inline]
- pub const fn lanes() -> usize {
- $elem_count
- }
-
- /// Constructs a new instance with each element initialized to
- /// `value`.
- #[inline]
- pub const fn splat(value: $elem_ty) -> Self {
- Simd(codegen::$id($({
- #[allow(non_camel_case_types, dead_code)]
- struct $elem_name;
- value as $ielem_ty
- }),*))
- }
-
- /// Extracts the value at `index`.
- ///
- /// # Panics
- ///
- /// If `index >= Self::lanes()`.
- #[inline]
- pub fn extract(self, index: usize) -> $elem_ty {
- assert!(index < $elem_count);
- unsafe { self.extract_unchecked(index) }
- }
-
- /// Extracts the value at `index`.
- ///
- /// # Safety
- ///
- /// If `index >= Self::lanes()` the behavior is undefined.
- #[inline]
- pub unsafe fn extract_unchecked(self, index: usize) -> $elem_ty {
- use crate::llvm::simd_extract;
- let e: $ielem_ty = simd_extract(self.0, index as u32);
- e as $elem_ty
- }
-
- /// Returns a new vector where the value at `index` is replaced by `new_value`.
- ///
- /// # Panics
- ///
- /// If `index >= Self::lanes()`.
- #[inline]
- #[must_use = "replace does not modify the original value - \
- it returns a new vector with the value at `index` \
- replaced by `new_value`d"
- ]
- pub fn replace(self, index: usize, new_value: $elem_ty) -> Self {
- assert!(index < $elem_count);
- unsafe { self.replace_unchecked(index, new_value) }
- }
-
- /// Returns a new vector where the value at `index` is replaced by `new_value`.
- ///
- /// # Safety
- ///
- /// If `index >= Self::lanes()` the behavior is undefined.
- #[inline]
- #[must_use = "replace_unchecked does not modify the original value - \
- it returns a new vector with the value at `index` \
- replaced by `new_value`d"
- ]
- pub unsafe fn replace_unchecked(
- self,
- index: usize,
- new_value: $elem_ty,
- ) -> Self {
- use crate::llvm::simd_insert;
- Simd(simd_insert(self.0, index as u32, new_value as $ielem_ty))
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- pub mod [<$id _minimal>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn minimal() {
- // lanes:
- assert_eq!($elem_count, $id::lanes());
-
- // splat and extract / extract_unchecked:
- const VAL: $elem_ty = 7 as $elem_ty;
- const VEC: $id = $id::splat(VAL);
- for i in 0..$id::lanes() {
- assert_eq!(VAL, VEC.extract(i));
- assert_eq!(
- VAL, unsafe { VEC.extract_unchecked(i) }
- );
- }
-
- // replace / replace_unchecked
- let new_vec = VEC.replace(0, 42 as $elem_ty);
- for i in 0..$id::lanes() {
- if i == 0 {
- assert_eq!(42 as $elem_ty, new_vec.extract(i));
- } else {
- assert_eq!(VAL, new_vec.extract(i));
- }
- }
- let new_vec = unsafe {
- VEC.replace_unchecked(0, 42 as $elem_ty)
- };
- for i in 0..$id::lanes() {
- if i == 0 {
- assert_eq!(42 as $elem_ty, new_vec.extract(i));
- } else {
- assert_eq!(VAL, new_vec.extract(i));
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn extract_panic_oob() {
- const VAL: $elem_ty = 7 as $elem_ty;
- const VEC: $id = $id::splat(VAL);
- let _ = VEC.extract($id::lanes());
- }
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn replace_panic_oob() {
- const VAL: $elem_ty = 7 as $elem_ty;
- const VEC: $id = $id::splat(VAL);
- let _ = VEC.replace($id::lanes(), 42 as $elem_ty);
- }
- }
- }
- }
- }
-}
diff --git a/third_party/rust/packed_simd/src/api/minimal/mask.rs b/third_party/rust/packed_simd/src/api/minimal/mask.rs
deleted file mode 100644
index a420060b42..0000000000
--- a/third_party/rust/packed_simd/src/api/minimal/mask.rs
+++ /dev/null
@@ -1,176 +0,0 @@
-//! Minimal API of mask vectors.
-
-macro_rules! impl_minimal_mask {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $ielem_ty:ident
- | $test_tt:tt | $($elem_name:ident),+ | $(#[$doc:meta])*) => {
- $(#[$doc])*
- pub type $id = Simd<[$elem_ty; $elem_count]>;
-
- impl sealed::Simd for $id {
- type Element = $elem_ty;
- const LANES: usize = $elem_count;
- type LanesType = [u32; $elem_count];
- }
-
- impl $id {
- /// Creates a new instance with each vector elements initialized
- /// with the provided values.
- #[inline]
- #[allow(clippy::too_many_arguments)]
- pub const fn new($($elem_name: bool),*) -> Self {
- Simd(codegen::$id($(Self::bool_to_internal($elem_name)),*))
- }
-
- /// Converts a boolean type into the type of the vector lanes.
- #[inline]
- #[allow(clippy::indexing_slicing)]
- const fn bool_to_internal(x: bool) -> $ielem_ty {
- [0 as $ielem_ty, !(0 as $ielem_ty)][x as usize]
- }
-
- /// Returns the number of vector lanes.
- #[inline]
- pub const fn lanes() -> usize {
- $elem_count
- }
-
- /// Constructs a new instance with each element initialized to
- /// `value`.
- #[inline]
- pub const fn splat(value: bool) -> Self {
- Simd(codegen::$id($({
- #[allow(non_camel_case_types, dead_code)]
- struct $elem_name;
- Self::bool_to_internal(value)
- }),*))
- }
-
- /// Extracts the value at `index`.
- ///
- /// # Panics
- ///
- /// If `index >= Self::lanes()`.
- #[inline]
- pub fn extract(self, index: usize) -> bool {
- assert!(index < $elem_count);
- unsafe { self.extract_unchecked(index) }
- }
-
- /// Extracts the value at `index`.
- ///
- /// # Safety
- ///
- /// If `index >= Self::lanes()` the behavior is undefined.
- #[inline]
- pub unsafe fn extract_unchecked(self, index: usize) -> bool {
- use crate::llvm::simd_extract;
- let x: $ielem_ty = simd_extract(self.0, index as u32);
- x != 0
- }
-
- /// Returns a new vector where the value at `index` is replaced by
- /// `new_value`.
- ///
- /// # Panics
- ///
- /// If `index >= Self::lanes()`.
- #[inline]
- #[must_use = "replace does not modify the original value - \
- it returns a new vector with the value at `index` \
- replaced by `new_value`d"
- ]
- pub fn replace(self, index: usize, new_value: bool) -> Self {
- assert!(index < $elem_count);
- unsafe { self.replace_unchecked(index, new_value) }
- }
-
- /// Returns a new vector where the value at `index` is replaced by
- /// `new_value`.
- ///
- /// # Safety
- ///
- /// If `index >= Self::lanes()` the behavior is undefined.
- #[inline]
- #[must_use = "replace_unchecked does not modify the original value - \
- it returns a new vector with the value at `index` \
- replaced by `new_value`d"
- ]
- pub unsafe fn replace_unchecked(
- self,
- index: usize,
- new_value: bool,
- ) -> Self {
- use crate::llvm::simd_insert;
- Simd(simd_insert(self.0, index as u32,
- Self::bool_to_internal(new_value)))
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _minimal>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn minimal() {
- // TODO: test new
-
- // lanes:
- assert_eq!($elem_count, $id::lanes());
-
- // splat and extract / extract_unchecked:
- let vec = $id::splat(true);
- for i in 0..$id::lanes() {
- assert_eq!(true, vec.extract(i));
- assert_eq!(true,
- unsafe { vec.extract_unchecked(i) }
- );
- }
-
- // replace / replace_unchecked
- let new_vec = vec.replace(0, false);
- for i in 0..$id::lanes() {
- if i == 0 {
- assert_eq!(false, new_vec.extract(i));
- } else {
- assert_eq!(true, new_vec.extract(i));
- }
- }
- let new_vec = unsafe {
- vec.replace_unchecked(0, false)
- };
- for i in 0..$id::lanes() {
- if i == 0 {
- assert_eq!(false, new_vec.extract(i));
- } else {
- assert_eq!(true, new_vec.extract(i));
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn extract_panic_oob() {
- let vec = $id::splat(false);
- let _ = vec.extract($id::lanes());
- }
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn replace_panic_oob() {
- let vec = $id::splat(false);
- let _ = vec.replace($id::lanes(), true);
- }
- }
- }
- }
- }
-}
diff --git a/third_party/rust/packed_simd/src/api/minimal/ptr.rs b/third_party/rust/packed_simd/src/api/minimal/ptr.rs
deleted file mode 100644
index d9e47c9ccb..0000000000
--- a/third_party/rust/packed_simd/src/api/minimal/ptr.rs
+++ /dev/null
@@ -1,1373 +0,0 @@
-//! Minimal API of pointer vectors.
-
-macro_rules! impl_minimal_p {
- ([$elem_ty:ty; $elem_count:expr]: $id:ident, $mask_ty:ident,
- $usize_ty:ident, $isize_ty:ident | $ref:ident | $test_tt:tt
- | $($elem_name:ident),+ | ($true:expr, $false:expr) |
- $(#[$doc:meta])*) => {
-
- $(#[$doc])*
- pub type $id<T> = Simd<[$elem_ty; $elem_count]>;
-
- impl<T> sealed::Simd for $id<T> {
- type Element = $elem_ty;
- const LANES: usize = $elem_count;
- type LanesType = [u32; $elem_count];
- }
-
- impl<T> $id<T> {
- /// Creates a new instance with each vector elements initialized
- /// with the provided values.
- #[inline]
- #[allow(clippy::too_many_arguments)]
- pub const fn new($($elem_name: $elem_ty),*) -> Self {
- Simd(codegen::$id($($elem_name),*))
- }
-
- /// Returns the number of vector lanes.
- #[inline]
- pub const fn lanes() -> usize {
- $elem_count
- }
-
- /// Constructs a new instance with each element initialized to
- /// `value`.
- #[inline]
- pub const fn splat(value: $elem_ty) -> Self {
- Simd(codegen::$id($({
- #[allow(non_camel_case_types, dead_code)]
- struct $elem_name;
- value
- }),*))
- }
-
- /// Constructs a new instance with each element initialized to
- /// `null`.
- #[inline]
- pub const fn null() -> Self {
- Self::splat(crate::ptr::null_mut() as $elem_ty)
- }
-
- /// Returns a mask that selects those lanes that contain `null`
- /// pointers.
- #[inline]
- pub fn is_null(self) -> $mask_ty {
- self.eq(Self::null())
- }
-
- /// Extracts the value at `index`.
- ///
- /// # Panics
- ///
- /// If `index >= Self::lanes()`.
- #[inline]
- pub fn extract(self, index: usize) -> $elem_ty {
- assert!(index < $elem_count);
- unsafe { self.extract_unchecked(index) }
- }
-
- /// Extracts the value at `index`.
- ///
- /// # Safety
- ///
- /// If `index >= Self::lanes()` the behavior is undefined.
- #[inline]
- pub unsafe fn extract_unchecked(self, index: usize) -> $elem_ty {
- use crate::llvm::simd_extract;
- simd_extract(self.0, index as u32)
- }
-
- /// Returns a new vector where the value at `index` is replaced by
- /// `new_value`.
- ///
- /// # Panics
- ///
- /// If `index >= Self::lanes()`.
- #[inline]
- #[must_use = "replace does not modify the original value - \
- it returns a new vector with the value at `index` \
- replaced by `new_value`d"
- ]
- #[allow(clippy::not_unsafe_ptr_arg_deref)]
- pub fn replace(self, index: usize, new_value: $elem_ty) -> Self {
- assert!(index < $elem_count);
- unsafe { self.replace_unchecked(index, new_value) }
- }
-
- /// Returns a new vector where the value at `index` is replaced by `new_value`.
- ///
- /// # Safety
- ///
- /// If `index >= Self::lanes()` the behavior is undefined.
- #[inline]
- #[must_use = "replace_unchecked does not modify the original value - \
- it returns a new vector with the value at `index` \
- replaced by `new_value`d"
- ]
- pub unsafe fn replace_unchecked(
- self,
- index: usize,
- new_value: $elem_ty,
- ) -> Self {
- use crate::llvm::simd_insert;
- Simd(simd_insert(self.0, index as u32, new_value))
- }
- }
-
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _minimal>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn minimal() {
- // lanes:
- assert_eq!($elem_count, $id::<i32>::lanes());
-
- // splat and extract / extract_unchecked:
- let VAL7: <$id<i32> as sealed::Simd>::Element
- = $ref!(7);
- let VAL42: <$id<i32> as sealed::Simd>::Element
- = $ref!(42);
- let VEC: $id<i32> = $id::splat(VAL7);
- for i in 0..$id::<i32>::lanes() {
- assert_eq!(VAL7, VEC.extract(i));
- assert_eq!(
- VAL7, unsafe { VEC.extract_unchecked(i) }
- );
- }
-
- // replace / replace_unchecked
- let new_vec = VEC.replace(0, VAL42);
- for i in 0..$id::<i32>::lanes() {
- if i == 0 {
- assert_eq!(VAL42, new_vec.extract(i));
- } else {
- assert_eq!(VAL7, new_vec.extract(i));
- }
- }
- let new_vec = unsafe {
- VEC.replace_unchecked(0, VAL42)
- };
- for i in 0..$id::<i32>::lanes() {
- if i == 0 {
- assert_eq!(VAL42, new_vec.extract(i));
- } else {
- assert_eq!(VAL7, new_vec.extract(i));
- }
- }
-
- let mut n = $id::<i32>::null();
- assert_eq!(
- n,
- $id::<i32>::splat(unsafe { crate::mem::zeroed() })
- );
- assert!(n.is_null().all());
- n = n.replace(
- 0, unsafe { crate::mem::transmute(1_isize) }
- );
- assert!(!n.is_null().all());
- if $id::<i32>::lanes() > 1 {
- assert!(n.is_null().any());
- } else {
- assert!(!n.is_null().any());
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn extract_panic_oob() {
- let VAL: <$id<i32> as sealed::Simd>::Element
- = $ref!(7);
- let VEC: $id<i32> = $id::splat(VAL);
- let _ = VEC.extract($id::<i32>::lanes());
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn replace_panic_oob() {
- let VAL: <$id<i32> as sealed::Simd>::Element
- = $ref!(7);
- let VAL42: <$id<i32> as sealed::Simd>::Element
- = $ref!(42);
- let VEC: $id<i32> = $id::splat(VAL);
- let _ = VEC.replace($id::<i32>::lanes(), VAL42);
- }
- }
- }
- }
-
- impl<T> crate::fmt::Debug for $id<T> {
- #[allow(clippy::missing_inline_in_public_items)]
- fn fmt(&self, f: &mut crate::fmt::Formatter<'_>)
- -> crate::fmt::Result {
- write!(
- f,
- "{}<{}>(",
- stringify!($id),
- crate::intrinsics::type_name::<T>()
- )?;
- for i in 0..$elem_count {
- if i > 0 {
- write!(f, ", ")?;
- }
- self.extract(i).fmt(f)?;
- }
- write!(f, ")")
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _fmt_debug>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn debug() {
- use arrayvec::{ArrayString,ArrayVec};
- type TinyString = ArrayString<[u8; 512]>;
-
- use crate::fmt::Write;
- let v = $id::<i32>::default();
- let mut s = TinyString::new();
- write!(&mut s, "{:?}", v).unwrap();
-
- let mut beg = TinyString::new();
- write!(&mut beg, "{}<i32>(", stringify!($id)).unwrap();
- assert!(
- s.starts_with(beg.as_str()),
- "s = {} (should start with = {})", s, beg
- );
- assert!(s.ends_with(")"));
- let s: ArrayVec<[TinyString; 64]>
- = s.replace(beg.as_str(), "")
- .replace(")", "").split(",")
- .map(|v| TinyString::from(v.trim()).unwrap())
- .collect();
- assert_eq!(s.len(), $id::<i32>::lanes());
- for (index, ss) in s.into_iter().enumerate() {
- let mut e = TinyString::new();
- write!(&mut e, "{:?}", v.extract(index)).unwrap();
- assert_eq!(ss, e);
- }
- }
- }
- }
- }
-
- impl<T> Default for $id<T> {
- #[inline]
- fn default() -> Self {
- // FIXME: ptrs do not implement default
- Self::null()
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _default>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn default() {
- let a = $id::<i32>::default();
- for i in 0..$id::<i32>::lanes() {
- assert_eq!(
- a.extract(i), unsafe { crate::mem::zeroed() }
- );
- }
- }
- }
- }
- }
-
- impl<T> $id<T> {
- /// Lane-wise equality comparison.
- #[inline]
- pub fn eq(self, other: Self) -> $mask_ty {
- unsafe {
- use crate::llvm::simd_eq;
- let a: $usize_ty = crate::mem::transmute(self);
- let b: $usize_ty = crate::mem::transmute(other);
- Simd(simd_eq(a.0, b.0))
- }
- }
-
- /// Lane-wise inequality comparison.
- #[inline]
- pub fn ne(self, other: Self) -> $mask_ty {
- unsafe {
- use crate::llvm::simd_ne;
- let a: $usize_ty = crate::mem::transmute(self);
- let b: $usize_ty = crate::mem::transmute(other);
- Simd(simd_ne(a.0, b.0))
- }
- }
-
- /// Lane-wise less-than comparison.
- #[inline]
- pub fn lt(self, other: Self) -> $mask_ty {
- unsafe {
- use crate::llvm::simd_lt;
- let a: $usize_ty = crate::mem::transmute(self);
- let b: $usize_ty = crate::mem::transmute(other);
- Simd(simd_lt(a.0, b.0))
- }
- }
-
- /// Lane-wise less-than-or-equals comparison.
- #[inline]
- pub fn le(self, other: Self) -> $mask_ty {
- unsafe {
- use crate::llvm::simd_le;
- let a: $usize_ty = crate::mem::transmute(self);
- let b: $usize_ty = crate::mem::transmute(other);
- Simd(simd_le(a.0, b.0))
- }
- }
-
- /// Lane-wise greater-than comparison.
- #[inline]
- pub fn gt(self, other: Self) -> $mask_ty {
- unsafe {
- use crate::llvm::simd_gt;
- let a: $usize_ty = crate::mem::transmute(self);
- let b: $usize_ty = crate::mem::transmute(other);
- Simd(simd_gt(a.0, b.0))
- }
- }
-
- /// Lane-wise greater-than-or-equals comparison.
- #[inline]
- pub fn ge(self, other: Self) -> $mask_ty {
- unsafe {
- use crate::llvm::simd_ge;
- let a: $usize_ty = crate::mem::transmute(self);
- let b: $usize_ty = crate::mem::transmute(other);
- Simd(simd_ge(a.0, b.0))
- }
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_vertical>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn cmp() {
- let a = $id::<i32>::null();
- let b = $id::<i32>::splat(unsafe {
- crate::mem::transmute(1_isize)
- });
-
- let r = a.lt(b);
- let e = $mask_ty::splat(true);
- assert!(r == e);
- let r = a.le(b);
- assert!(r == e);
-
- let e = $mask_ty::splat(false);
- let r = a.gt(b);
- assert!(r == e);
- let r = a.ge(b);
- assert!(r == e);
- let r = a.eq(b);
- assert!(r == e);
-
- let mut a = a;
- let mut b = b;
- let mut e = e;
- for i in 0..$id::<i32>::lanes() {
- if i % 2 == 0 {
- a = a.replace(
- i,
- unsafe { crate::mem::transmute(0_isize) }
- );
- b = b.replace(
- i,
- unsafe { crate::mem::transmute(1_isize) }
- );
- e = e.replace(i, true);
- } else {
- a = a.replace(
- i,
- unsafe { crate::mem::transmute(1_isize) }
- );
- b = b.replace(
- i,
- unsafe { crate::mem::transmute(0_isize) }
- );
- e = e.replace(i, false);
- }
- }
- let r = a.lt(b);
- assert!(r == e);
- }
- }
- }
- }
-
- #[allow(clippy::partialeq_ne_impl)]
- impl<T> crate::cmp::PartialEq<$id<T>> for $id<T> {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- $id::<T>::eq(*self, *other).all()
- }
- #[inline]
- fn ne(&self, other: &Self) -> bool {
- $id::<T>::ne(*self, *other).any()
- }
- }
-
- // FIXME: https://github.com/rust-lang-nursery/rust-clippy/issues/2892
- #[allow(clippy::partialeq_ne_impl)]
- impl<T> crate::cmp::PartialEq<LexicographicallyOrdered<$id<T>>>
- for LexicographicallyOrdered<$id<T>>
- {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
- #[inline]
- fn ne(&self, other: &Self) -> bool {
- self.0 != other.0
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_PartialEq>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn partial_eq() {
- let a = $id::<i32>::null();
- let b = $id::<i32>::splat(unsafe {
- crate::mem::transmute(1_isize)
- });
-
- assert!(a != b);
- assert!(!(a == b));
- assert!(a == a);
- assert!(!(a != a));
-
- if $id::<i32>::lanes() > 1 {
- let a = $id::<i32>::null().replace(0, unsafe {
- crate::mem::transmute(1_isize)
- });
- let b = $id::<i32>::splat(unsafe {
- crate::mem::transmute(1_isize)
- });
-
- assert!(a != b);
- assert!(!(a == b));
- assert!(a == a);
- assert!(!(a != a));
- }
- }
- }
- }
- }
-
- impl<T> crate::cmp::Eq for $id<T> {}
- impl<T> crate::cmp::Eq for LexicographicallyOrdered<$id<T>> {}
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _cmp_eq>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn eq() {
- fn foo<E: crate::cmp::Eq>(_: E) {}
- let a = $id::<i32>::null();
- foo(a);
- }
- }
- }
- }
-
- impl<T> From<[$elem_ty; $elem_count]> for $id<T> {
- #[inline]
- fn from(array: [$elem_ty; $elem_count]) -> Self {
- unsafe {
- // FIXME: unnecessary zeroing; better than UB.
- let mut u: Self = crate::mem::zeroed();
- crate::ptr::copy_nonoverlapping(
- &array as *const [$elem_ty; $elem_count] as *const u8,
- &mut u as *mut Self as *mut u8,
- crate::mem::size_of::<Self>()
- );
- u
- }
- }
- }
- impl<T> Into<[$elem_ty; $elem_count]> for $id<T> {
- #[inline]
- fn into(self) -> [$elem_ty; $elem_count] {
- unsafe {
- // FIXME: unnecessary zeroing; better than UB.
- let mut u: [$elem_ty; $elem_count] = crate::mem::zeroed();
- crate::ptr::copy_nonoverlapping(
- &self as *const $id<T> as *const u8,
- &mut u as *mut [$elem_ty; $elem_count] as *mut u8,
- crate::mem::size_of::<Self>()
- );
- u
- }
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _from>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn array() {
- let values = [1_i32; $elem_count];
-
- let mut vec: $id<i32> = Default::default();
- let mut array = [
- $id::<i32>::null().extract(0); $elem_count
- ];
-
- for i in 0..$elem_count {
- let ptr = &values[i] as *const i32 as *mut i32;
- vec = vec.replace(i, ptr);
- array[i] = ptr;
- }
-
- // FIXME: there is no impl of From<$id<T>> for [$elem_ty; N]
- // let a0 = From::from(vec);
- // assert_eq!(a0, array);
- #[allow(unused_assignments)]
- let mut a1 = array;
- a1 = vec.into();
- assert_eq!(a1, array);
-
- let v0: $id<i32> = From::from(array);
- assert_eq!(v0, vec);
- let v1: $id<i32> = array.into();
- assert_eq!(v1, vec);
- }
- }
- }
- }
-
- impl<T> $id<T> {
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned
- /// to an `align_of::<Self>()` boundary.
- #[inline]
- pub fn from_slice_aligned(slice: &[$elem_ty]) -> Self {
- unsafe {
- assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_ptr();
- assert!(
- target_ptr.align_offset(crate::mem::align_of::<Self>())
- == 0
- );
- Self::from_slice_aligned_unchecked(slice)
- }
- }
-
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()`.
- #[inline]
- pub fn from_slice_unaligned(slice: &[$elem_ty]) -> Self {
- unsafe {
- assert!(slice.len() >= $elem_count);
- Self::from_slice_unaligned_unchecked(slice)
- }
- }
-
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned
- /// to an `align_of::<Self>()` boundary, the behavior is undefined.
- #[inline]
- pub unsafe fn from_slice_aligned_unchecked(slice: &[$elem_ty])
- -> Self {
- #[allow(clippy::cast_ptr_alignment)]
- *(slice.as_ptr().cast())
- }
-
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` the behavior is undefined.
- #[inline]
- pub unsafe fn from_slice_unaligned_unchecked(
- slice: &[$elem_ty],
- ) -> Self {
- use crate::mem::size_of;
- let target_ptr = slice.as_ptr().cast();
- let mut x = Self::splat(crate::ptr::null_mut() as $elem_ty);
- let self_ptr = &mut x as *mut Self as *mut u8;
- crate::ptr::copy_nonoverlapping(
- target_ptr,
- self_ptr,
- size_of::<Self>(),
- );
- x
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _slice_from_slice>] {
- use super::*;
- use crate::iter::Iterator;
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn from_slice_unaligned() {
- let (null, non_null) = ptr_vals!($id<i32>);
-
- let mut unaligned = [
- non_null; $id::<i32>::lanes() + 1
- ];
- unaligned[0] = null;
- let vec = $id::<i32>::from_slice_unaligned(
- &unaligned[1..]
- );
- for (index, &b) in unaligned.iter().enumerate() {
- if index == 0 {
- assert_eq!(b, null);
- } else {
- assert_eq!(b, non_null);
- assert_eq!(b, vec.extract(index - 1));
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn from_slice_unaligned_fail() {
- let (_null, non_null) = ptr_vals!($id<i32>);
- let unaligned = [non_null; $id::<i32>::lanes() + 1];
- // the slice is not large enough => panic
- let _vec = $id::<i32>::from_slice_unaligned(
- &unaligned[2..]
- );
- }
-
- union A {
- data: [<$id<i32> as sealed::Simd>::Element;
- 2 * $id::<i32>::lanes()],
- _vec: $id<i32>,
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn from_slice_aligned() {
- let (null, non_null) = ptr_vals!($id<i32>);
- let mut aligned = A {
- data: [null; 2 * $id::<i32>::lanes()],
- };
- for i in
- $id::<i32>::lanes()..(2 * $id::<i32>::lanes()) {
- unsafe {
- aligned.data[i] = non_null;
- }
- }
-
- let vec = unsafe {
- $id::<i32>::from_slice_aligned(
- &aligned.data[$id::<i32>::lanes()..]
- )
- };
- for (index, &b) in unsafe {
- aligned.data.iter().enumerate()
- } {
- if index < $id::<i32>::lanes() {
- assert_eq!(b, null);
- } else {
- assert_eq!(b, non_null);
- assert_eq!(
- b, vec.extract(index - $id::<i32>::lanes())
- );
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn from_slice_aligned_fail_lanes() {
- let (_null, non_null) = ptr_vals!($id<i32>);
- let aligned = A {
- data: [non_null; 2 * $id::<i32>::lanes()],
- };
- // the slice is not large enough => panic
- let _vec = unsafe {
- $id::<i32>::from_slice_aligned(
- &aligned.data[2 * $id::<i32>::lanes()..]
- )
- };
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn from_slice_aligned_fail_align() {
- unsafe {
- let (null, _non_null) = ptr_vals!($id<i32>);
- let aligned = A {
- data: [null; 2 * $id::<i32>::lanes()],
- };
-
- // get a pointer to the front of data
- let ptr = aligned.data.as_ptr();
- // offset pointer by one element
- let ptr = ptr.wrapping_add(1);
-
- if ptr.align_offset(
- crate::mem::align_of::<$id<i32>>()
- ) == 0 {
- // the pointer is properly aligned, so
- // from_slice_aligned won't fail here (e.g. this
- // can happen for i128x1). So we panic to make
- // the "should_fail" test pass:
- panic!("ok");
- }
-
- // create a slice - this is safe, because the
- // elements of the slice exist, are properly
- // initialized, and properly aligned:
- let s = slice::from_raw_parts(
- ptr, $id::<i32>::lanes()
- );
- // this should always panic because the slice
- // alignment does not match the alignment
- // requirements for the vector type:
- let _vec = $id::<i32>::from_slice_aligned(s);
- }
- }
- }
- }
- }
-
- impl<T> $id<T> {
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not
- /// aligned to an `align_of::<Self>()` boundary.
- #[inline]
- pub fn write_to_slice_aligned(self, slice: &mut [$elem_ty]) {
- unsafe {
- assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_mut_ptr();
- assert!(
- target_ptr.align_offset(crate::mem::align_of::<Self>())
- == 0
- );
- self.write_to_slice_aligned_unchecked(slice);
- }
- }
-
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()`.
- #[inline]
- pub fn write_to_slice_unaligned(self, slice: &mut [$elem_ty]) {
- unsafe {
- assert!(slice.len() >= $elem_count);
- self.write_to_slice_unaligned_unchecked(slice);
- }
- }
-
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not
- /// aligned to an `align_of::<Self>()` boundary, the behavior is
- /// undefined.
- #[inline]
- pub unsafe fn write_to_slice_aligned_unchecked(
- self, slice: &mut [$elem_ty],
- ) {
- #[allow(clippy::cast_ptr_alignment)]
- *(slice.as_mut_ptr().cast()) = self;
- }
-
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` the behavior is undefined.
- #[inline]
- pub unsafe fn write_to_slice_unaligned_unchecked(
- self, slice: &mut [$elem_ty],
- ) {
- let target_ptr = slice.as_mut_ptr().cast();
- let self_ptr = &self as *const Self as *const u8;
- crate::ptr::copy_nonoverlapping(
- self_ptr,
- target_ptr,
- crate::mem::size_of::<Self>(),
- );
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _slice_write_to_slice>] {
- use super::*;
- use crate::iter::Iterator;
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn write_to_slice_unaligned() {
- let (null, non_null) = ptr_vals!($id<i32>);
- let mut unaligned = [null; $id::<i32>::lanes() + 1];
- let vec = $id::<i32>::splat(non_null);
- vec.write_to_slice_unaligned(&mut unaligned[1..]);
- for (index, &b) in unaligned.iter().enumerate() {
- if index == 0 {
- assert_eq!(b, null);
- } else {
- assert_eq!(b, non_null);
- assert_eq!(b, vec.extract(index - 1));
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn write_to_slice_unaligned_fail() {
- let (null, non_null) = ptr_vals!($id<i32>);
- let mut unaligned = [null; $id::<i32>::lanes() + 1];
- let vec = $id::<i32>::splat(non_null);
- // the slice is not large enough => panic
- vec.write_to_slice_unaligned(&mut unaligned[2..]);
- }
-
- union A {
- data: [<$id<i32> as sealed::Simd>::Element;
- 2 * $id::<i32>::lanes()],
- _vec: $id<i32>,
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn write_to_slice_aligned() {
- let (null, non_null) = ptr_vals!($id<i32>);
- let mut aligned = A {
- data: [null; 2 * $id::<i32>::lanes()],
- };
- let vec = $id::<i32>::splat(non_null);
- unsafe {
- vec.write_to_slice_aligned(
- &mut aligned.data[$id::<i32>::lanes()..]
- )
- };
- for (index, &b) in
- unsafe { aligned.data.iter().enumerate() } {
- if index < $id::<i32>::lanes() {
- assert_eq!(b, null);
- } else {
- assert_eq!(b, non_null);
- assert_eq!(
- b, vec.extract(index - $id::<i32>::lanes())
- );
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn write_to_slice_aligned_fail_lanes() {
- let (null, non_null) = ptr_vals!($id<i32>);
- let mut aligned = A {
- data: [null; 2 * $id::<i32>::lanes()],
- };
- let vec = $id::<i32>::splat(non_null);
- // the slice is not large enough => panic
- unsafe {
- vec.write_to_slice_aligned(
- &mut aligned.data[2 * $id::<i32>::lanes()..]
- )
- };
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn write_to_slice_aligned_fail_align() {
- let (null, non_null) = ptr_vals!($id<i32>);
- unsafe {
- let mut aligned = A {
- data: [null; 2 * $id::<i32>::lanes()],
- };
-
- // get a pointer to the front of data
- let ptr = aligned.data.as_mut_ptr();
- // offset pointer by one element
- let ptr = ptr.wrapping_add(1);
-
- if ptr.align_offset(
- crate::mem::align_of::<$id<i32>>()
- ) == 0 {
- // the pointer is properly aligned, so
- // write_to_slice_aligned won't fail here (e.g.
- // this can happen for i128x1). So we panic to
- // make the "should_fail" test pass:
- panic!("ok");
- }
-
- // create a slice - this is safe, because the
- // elements of the slice exist, are properly
- // initialized, and properly aligned:
- let s = slice::from_raw_parts_mut(
- ptr, $id::<i32>::lanes()
- );
- // this should always panic because the slice
- // alignment does not match the alignment
- // requirements for the vector type:
- let vec = $id::<i32>::splat(non_null);
- vec.write_to_slice_aligned(s);
- }
- }
- }
- }
- }
-
- impl<T> crate::hash::Hash for $id<T> {
- #[inline]
- fn hash<H: crate::hash::Hasher>(&self, state: &mut H) {
- let s: $usize_ty = unsafe { crate::mem::transmute(*self) };
- s.hash(state)
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _hash>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn hash() {
- use crate::hash::{Hash, Hasher};
- #[allow(deprecated)]
- use crate::hash::{SipHasher13};
-
- let values = [1_i32; $elem_count];
-
- let mut vec: $id<i32> = Default::default();
- let mut array = [
- $id::<i32>::null().extract(0);
- $elem_count
- ];
-
- for i in 0..$elem_count {
- let ptr = &values[i] as *const i32 as *mut i32;
- vec = vec.replace(i, ptr);
- array[i] = ptr;
- }
-
- #[allow(deprecated)]
- let mut a_hash = SipHasher13::new();
- let mut v_hash = a_hash.clone();
- array.hash(&mut a_hash);
- vec.hash(&mut v_hash);
- assert_eq!(a_hash.finish(), v_hash.finish());
- }
- }
- }
- }
-
- impl<T> $id<T> {
- /// Calculates the offset from a pointer.
- ///
- /// `count` is in units of `T`; e.g. a count of `3` represents a
- /// pointer offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is
- /// Undefined Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in
- /// bounds or one byte past the end of an allocated object.
- ///
- /// * The computed offset, in bytes, cannot overflow an `isize`.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around"
- /// the address space. That is, the infinite-precision sum, in bytes
- /// must fit in a `usize`.
- ///
- /// The compiler and standard library generally tries to ensure
- /// allocations never reach a size where an offset is a concern. For
- /// instance, `Vec` and `Box` ensure they never allocate more than
- /// `isize::MAX` bytes, so `vec.as_ptr().offset(vec.len() as isize)`
- /// is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an
- /// allocation. For instance, no known 64-bit platform can ever
- /// serve a request for 263 bytes due to page-table limitations or
- /// splitting the address space. However, some 32-bit and 16-bit
- /// platforms may successfully serve a request for more than
- /// `isize::MAX` bytes with things like Physical Address Extension.
- /// As such, memory acquired directly from allocators or memory
- /// mapped files may be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints
- /// are difficult to satisfy. The only advantage of this method is
- /// that it enables more aggressive compiler optimizations.
- #[inline]
- pub unsafe fn offset(self, count: $isize_ty) -> Self {
- // FIXME: should use LLVM's `add nsw nuw`
- self.wrapping_offset(count)
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- ///
- /// `count` is in units of `T`; e.g. a count of `3` represents a
- /// pointer offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires unsafe).
- ///
- /// Always use `.offset(count)` instead when possible, because
- /// offset allows the compiler to optimize better.
- #[inline]
- pub fn wrapping_offset(self, count: $isize_ty) -> Self {
- unsafe {
- let x: $isize_ty = crate::mem::transmute(self);
- // note: {+,*} currently performs a `wrapping_{add, mul}`
- crate::mem::transmute(
- x + (count * crate::mem::size_of::<T>() as isize)
- )
- }
- }
-
- /// Calculates the distance between two pointers.
- ///
- /// The returned value is in units of `T`: the distance in bytes is
- /// divided by `mem::size_of::<T>()`.
- ///
- /// This function is the inverse of offset.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is
- /// Undefined Behavior:
- ///
- /// * Both the starting and other pointer must be either in bounds
- /// or one byte past the end of the same allocated object.
- ///
- /// * The distance between the pointers, in bytes, cannot overflow
- /// an `isize`.
- ///
- /// * The distance between the pointers, in bytes, must be an exact
- /// multiple of the size of `T`.
- ///
- /// * The distance being in bounds cannot rely on "wrapping around"
- /// the address space.
- ///
- /// The compiler and standard library generally try to ensure
- /// allocations never reach a size where an offset is a concern. For
- /// instance, `Vec` and `Box` ensure they never allocate more than
- /// `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())`
- /// is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an
- /// allocation. For instance, no known 64-bit platform can ever
- /// serve a request for 263 bytes due to page-table limitations or
- /// splitting the address space. However, some 32-bit and 16-bit
- /// platforms may successfully serve a request for more than
- /// `isize::MAX` bytes with things like Physical Address Extension.
- /// As such, memory acquired directly from allocators or memory
- /// mapped files may be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset_from` instead if these constraints
- /// are difficult to satisfy. The only advantage of this method is
- /// that it enables more aggressive compiler optimizations.
- #[inline]
- pub unsafe fn offset_from(self, origin: Self) -> $isize_ty {
- // FIXME: should use LLVM's `sub nsw nuw`.
- self.wrapping_offset_from(origin)
- }
-
- /// Calculates the distance between two pointers.
- ///
- /// The returned value is in units of `T`: the distance in bytes is
- /// divided by `mem::size_of::<T>()`.
- ///
- /// If the address different between the two pointers is not a
- /// multiple of `mem::size_of::<T>()` then the result of the
- /// division is rounded towards zero.
- ///
- /// Though this method is safe for any two pointers, note that its
- /// result will be mostly useless if the two pointers aren't into
- /// the same allocated object, for example if they point to two
- /// different local variables.
- #[inline]
- pub fn wrapping_offset_from(self, origin: Self) -> $isize_ty {
- let x: $isize_ty = unsafe { crate::mem::transmute(self) };
- let y: $isize_ty = unsafe { crate::mem::transmute(origin) };
- // note: {-,/} currently perform wrapping_{sub, div}
- (y - x) / (crate::mem::size_of::<T>() as isize)
- }
-
- /// Calculates the offset from a pointer (convenience for
- /// `.offset(count as isize)`).
- ///
- /// `count` is in units of `T`; e.g. a count of 3 represents a
- /// pointer offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is
- /// Undefined Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in
- /// bounds or one byte past the end of an allocated object.
- ///
- /// * The computed offset, in bytes, cannot overflow an `isize`.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around"
- /// the address space. That is, the infinite-precision sum must fit
- /// in a `usize`.
- ///
- /// The compiler and standard library generally tries to ensure
- /// allocations never reach a size where an offset is a concern. For
- /// instance, `Vec` and `Box` ensure they never allocate more than
- /// `isize::MAX` bytes, so `vec.as_ptr().add(vec.len())` is always
- /// safe.
- ///
- /// Most platforms fundamentally can't even construct such an
- /// allocation. For instance, no known 64-bit platform can ever
- /// serve a request for 263 bytes due to page-table limitations or
- /// splitting the address space. However, some 32-bit and 16-bit
- /// platforms may successfully serve a request for more than
- /// `isize::MAX` bytes with things like Physical Address Extension.
- /// As such, memory acquired directly from allocators or memory
- /// mapped files may be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints
- /// are difficult to satisfy. The only advantage of this method is
- /// that it enables more aggressive compiler optimizations.
- #[inline]
- #[allow(clippy::should_implement_trait)]
- pub unsafe fn add(self, count: $usize_ty) -> Self {
- self.offset(count.cast())
- }
-
- /// Calculates the offset from a pointer (convenience for
- /// `.offset((count as isize).wrapping_neg())`).
- ///
- /// `count` is in units of T; e.g. a `count` of 3 represents a
- /// pointer offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is
- /// Undefined Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in
- /// bounds or one byte past the end of an allocated object.
- ///
- /// * The computed offset cannot exceed `isize::MAX` **bytes**.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around"
- /// the address space. That is, the infinite-precision sum must fit
- /// in a usize.
- ///
- /// The compiler and standard library generally tries to ensure
- /// allocations never reach a size where an offset is a concern. For
- /// instance, `Vec` and `Box` ensure they never allocate more than
- /// `isize::MAX` bytes, so
- /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an
- /// allocation. For instance, no known 64-bit platform can ever
- /// serve a request for 2<sup>63</sup> bytes due to page-table
- /// limitations or splitting the address space. However, some 32-bit
- /// and 16-bit platforms may successfully serve a request for more
- /// than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or
- /// memory mapped files *may* be too large to handle with this
- /// function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints
- /// are difficult to satisfy. The only advantage of this method is
- /// that it enables more aggressive compiler optimizations.
- #[inline]
- #[allow(clippy::should_implement_trait)]
- pub unsafe fn sub(self, count: $usize_ty) -> Self {
- let x: $isize_ty = count.cast();
- // note: - is currently wrapping_neg
- self.offset(-x)
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- /// (convenience for `.wrapping_offset(count as isize)`)
- ///
- /// `count` is in units of T; e.g. a `count` of 3 represents a
- /// pointer offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- ///
- /// Always use `.add(count)` instead when possible, because `add`
- /// allows the compiler to optimize better.
- #[inline]
- pub fn wrapping_add(self, count: $usize_ty) -> Self {
- self.wrapping_offset(count.cast())
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- /// (convenience for `.wrapping_offset((count as
- /// isize).wrapping_sub())`)
- ///
- /// `count` is in units of T; e.g. a `count` of 3 represents a
- /// pointer offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- ///
- /// Always use `.sub(count)` instead when possible, because `sub`
- /// allows the compiler to optimize better.
- #[inline]
- pub fn wrapping_sub(self, count: $usize_ty) -> Self {
- let x: $isize_ty = count.cast();
- self.wrapping_offset(-1 * x)
- }
- }
-
- impl<T> $id<T> {
- /// Shuffle vector elements according to `indices`.
- #[inline]
- pub fn shuffle1_dyn<I>(self, indices: I) -> Self
- where
- Self: codegen::shuffle1_dyn::Shuffle1Dyn<Indices = I>,
- {
- codegen::shuffle1_dyn::Shuffle1Dyn::shuffle1_dyn(self, indices)
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _shuffle1_dyn>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn shuffle1_dyn() {
- let (null, non_null) = ptr_vals!($id<i32>);
-
- // alternating = [non_null, null, non_null, null, ...]
- let mut alternating = $id::<i32>::splat(null);
- for i in 0..$id::<i32>::lanes() {
- if i % 2 == 0 {
- alternating = alternating.replace(i, non_null);
- }
- }
-
- type Indices = <$id<i32>
- as codegen::shuffle1_dyn::Shuffle1Dyn>::Indices;
- // even = [0, 0, 2, 2, 4, 4, ..]
- let even = {
- let mut v = Indices::splat(0);
- for i in 0..$id::<i32>::lanes() {
- if i % 2 == 0 {
- v = v.replace(i, (i as u8).into());
- } else {
- v = v.replace(i, (i as u8 - 1).into());
- }
- }
- v
- };
- // odd = [1, 1, 3, 3, 5, 5, ...]
- let odd = {
- let mut v = Indices::splat(0);
- for i in 0..$id::<i32>::lanes() {
- if i % 2 != 0 {
- v = v.replace(i, (i as u8).into());
- } else {
- v = v.replace(i, (i as u8 + 1).into());
- }
- }
- v
- };
-
- assert_eq!(
- alternating.shuffle1_dyn(even),
- $id::<i32>::splat(non_null)
- );
- if $id::<i32>::lanes() > 1 {
- assert_eq!(
- alternating.shuffle1_dyn(odd),
- $id::<i32>::splat(null)
- );
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops.rs b/third_party/rust/packed_simd/src/api/ops.rs
deleted file mode 100644
index f71c98795d..0000000000
--- a/third_party/rust/packed_simd/src/api/ops.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-//! Implementation of the `ops` traits
-#[macro_use]
-mod vector_mask_bitwise;
-#[macro_use]
-mod scalar_mask_bitwise;
-
-#[macro_use]
-mod vector_arithmetic;
-#[macro_use]
-mod scalar_arithmetic;
-
-#[macro_use]
-mod vector_bitwise;
-#[macro_use]
-mod scalar_bitwise;
-
-#[macro_use]
-mod vector_shifts;
-#[macro_use]
-mod scalar_shifts;
-
-#[macro_use]
-mod vector_rotates;
-
-#[macro_use]
-mod vector_neg;
-
-#[macro_use]
-mod vector_int_min_max;
-
-#[macro_use]
-mod vector_float_min_max;
diff --git a/third_party/rust/packed_simd/src/api/ops/scalar_arithmetic.rs b/third_party/rust/packed_simd/src/api/ops/scalar_arithmetic.rs
deleted file mode 100644
index da1a2037ea..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/scalar_arithmetic.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-//! Vertical (lane-wise) vector-scalar / scalar-vector arithmetic operations.
-
-macro_rules! impl_ops_scalar_arithmetic {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::ops::Add<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn add(self, other: $elem_ty) -> Self {
- self + $id::splat(other)
- }
- }
- impl crate::ops::Add<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn add(self, other: $id) -> $id {
- $id::splat(self) + other
- }
- }
-
- impl crate::ops::Sub<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn sub(self, other: $elem_ty) -> Self {
- self - $id::splat(other)
- }
- }
- impl crate::ops::Sub<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn sub(self, other: $id) -> $id {
- $id::splat(self) - other
- }
- }
-
- impl crate::ops::Mul<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn mul(self, other: $elem_ty) -> Self {
- self * $id::splat(other)
- }
- }
- impl crate::ops::Mul<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn mul(self, other: $id) -> $id {
- $id::splat(self) * other
- }
- }
-
- impl crate::ops::Div<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn div(self, other: $elem_ty) -> Self {
- self / $id::splat(other)
- }
- }
- impl crate::ops::Div<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn div(self, other: $id) -> $id {
- $id::splat(self) / other
- }
- }
-
- impl crate::ops::Rem<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn rem(self, other: $elem_ty) -> Self {
- self % $id::splat(other)
- }
- }
- impl crate::ops::Rem<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn rem(self, other: $id) -> $id {
- $id::splat(self) % other
- }
- }
-
- impl crate::ops::AddAssign<$elem_ty> for $id {
- #[inline]
- fn add_assign(&mut self, other: $elem_ty) {
- *self = *self + other;
- }
- }
-
- impl crate::ops::SubAssign<$elem_ty> for $id {
- #[inline]
- fn sub_assign(&mut self, other: $elem_ty) {
- *self = *self - other;
- }
- }
-
- impl crate::ops::MulAssign<$elem_ty> for $id {
- #[inline]
- fn mul_assign(&mut self, other: $elem_ty) {
- *self = *self * other;
- }
- }
-
- impl crate::ops::DivAssign<$elem_ty> for $id {
- #[inline]
- fn div_assign(&mut self, other: $elem_ty) {
- *self = *self / other;
- }
- }
-
- impl crate::ops::RemAssign<$elem_ty> for $id {
- #[inline]
- fn rem_assign(&mut self, other: $elem_ty) {
- *self = *self % other;
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_scalar_arith>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn ops_scalar_arithmetic() {
- let zi = 0 as $elem_ty;
- let oi = 1 as $elem_ty;
- let ti = 2 as $elem_ty;
- let fi = 4 as $elem_ty;
- let z = $id::splat(zi);
- let o = $id::splat(oi);
- let t = $id::splat(ti);
- let f = $id::splat(fi);
-
- // add
- assert_eq!(zi + z, z);
- assert_eq!(z + zi, z);
- assert_eq!(oi + z, o);
- assert_eq!(o + zi, o);
- assert_eq!(ti + z, t);
- assert_eq!(t + zi, t);
- assert_eq!(ti + t, f);
- assert_eq!(t + ti, f);
- // sub
- assert_eq!(zi - z, z);
- assert_eq!(z - zi, z);
- assert_eq!(oi - z, o);
- assert_eq!(o - zi, o);
- assert_eq!(ti - z, t);
- assert_eq!(t - zi, t);
- assert_eq!(fi - t, t);
- assert_eq!(f - ti, t);
- assert_eq!(f - o - o, t);
- assert_eq!(f - oi - oi, t);
- // mul
- assert_eq!(zi * z, z);
- assert_eq!(z * zi, z);
- assert_eq!(zi * o, z);
- assert_eq!(z * oi, z);
- assert_eq!(zi * t, z);
- assert_eq!(z * ti, z);
- assert_eq!(oi * t, t);
- assert_eq!(o * ti, t);
- assert_eq!(ti * t, f);
- assert_eq!(t * ti, f);
- // div
- assert_eq!(zi / o, z);
- assert_eq!(z / oi, z);
- assert_eq!(ti / o, t);
- assert_eq!(t / oi, t);
- assert_eq!(fi / o, f);
- assert_eq!(f / oi, f);
- assert_eq!(ti / t, o);
- assert_eq!(t / ti, o);
- assert_eq!(fi / t, t);
- assert_eq!(f / ti, t);
- // rem
- assert_eq!(oi % o, z);
- assert_eq!(o % oi, z);
- assert_eq!(fi % t, z);
- assert_eq!(f % ti, z);
-
- {
- let mut v = z;
- assert_eq!(v, z);
- v += oi; // add_assign
- assert_eq!(v, o);
- v -= oi; // sub_assign
- assert_eq!(v, z);
- v = t;
- v *= oi; // mul_assign
- assert_eq!(v, t);
- v *= ti;
- assert_eq!(v, f);
- v /= oi; // div_assign
- assert_eq!(v, f);
- v /= ti;
- assert_eq!(v, t);
- v %= ti; // rem_assign
- assert_eq!(v, z);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/scalar_bitwise.rs b/third_party/rust/packed_simd/src/api/ops/scalar_bitwise.rs
deleted file mode 100644
index 88216769ae..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/scalar_bitwise.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-//! Vertical (lane-wise) vector-scalar / scalar-vector bitwise operations.
-
-macro_rules! impl_ops_scalar_bitwise {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $test_tt:tt |
- ($true:expr, $false:expr)
- ) => {
- impl crate::ops::BitXor<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn bitxor(self, other: $elem_ty) -> Self {
- self ^ $id::splat(other)
- }
- }
- impl crate::ops::BitXor<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn bitxor(self, other: $id) -> $id {
- $id::splat(self) ^ other
- }
- }
-
- impl crate::ops::BitAnd<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn bitand(self, other: $elem_ty) -> Self {
- self & $id::splat(other)
- }
- }
- impl crate::ops::BitAnd<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn bitand(self, other: $id) -> $id {
- $id::splat(self) & other
- }
- }
-
- impl crate::ops::BitOr<$elem_ty> for $id {
- type Output = Self;
- #[inline]
- fn bitor(self, other: $elem_ty) -> Self {
- self | $id::splat(other)
- }
- }
- impl crate::ops::BitOr<$id> for $elem_ty {
- type Output = $id;
- #[inline]
- fn bitor(self, other: $id) -> $id {
- $id::splat(self) | other
- }
- }
-
- impl crate::ops::BitAndAssign<$elem_ty> for $id {
- #[inline]
- fn bitand_assign(&mut self, other: $elem_ty) {
- *self = *self & other;
- }
- }
- impl crate::ops::BitOrAssign<$elem_ty> for $id {
- #[inline]
- fn bitor_assign(&mut self, other: $elem_ty) {
- *self = *self | other;
- }
- }
- impl crate::ops::BitXorAssign<$elem_ty> for $id {
- #[inline]
- fn bitxor_assign(&mut self, other: $elem_ty) {
- *self = *self ^ other;
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_scalar_bitwise>] {
- use super::*;
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn ops_scalar_bitwise() {
- let zi = 0 as $elem_ty;
- let oi = 1 as $elem_ty;
- let ti = 2 as $elem_ty;
- let z = $id::splat(zi);
- let o = $id::splat(oi);
- let t = $id::splat(ti);
-
- // BitAnd:
- assert_eq!(oi & o, o);
- assert_eq!(o & oi, o);
- assert_eq!(oi & z, z);
- assert_eq!(o & zi, z);
- assert_eq!(zi & o, z);
- assert_eq!(z & oi, z);
- assert_eq!(zi & z, z);
- assert_eq!(z & zi, z);
-
- assert_eq!(ti & t, t);
- assert_eq!(t & ti, t);
- assert_eq!(ti & o, z);
- assert_eq!(t & oi, z);
- assert_eq!(oi & t, z);
- assert_eq!(o & ti, z);
-
- // BitOr:
- assert_eq!(oi | o, o);
- assert_eq!(o | oi, o);
- assert_eq!(oi | z, o);
- assert_eq!(o | zi, o);
- assert_eq!(zi | o, o);
- assert_eq!(z | oi, o);
- assert_eq!(zi | z, z);
- assert_eq!(z | zi, z);
-
- assert_eq!(ti | t, t);
- assert_eq!(t | ti, t);
- assert_eq!(zi | t, t);
- assert_eq!(z | ti, t);
- assert_eq!(ti | z, t);
- assert_eq!(t | zi, t);
-
- // BitXOR:
- assert_eq!(oi ^ o, z);
- assert_eq!(o ^ oi, z);
- assert_eq!(zi ^ z, z);
- assert_eq!(z ^ zi, z);
- assert_eq!(zi ^ o, o);
- assert_eq!(z ^ oi, o);
- assert_eq!(oi ^ z, o);
- assert_eq!(o ^ zi, o);
-
- assert_eq!(ti ^ t, z);
- assert_eq!(t ^ ti, z);
- assert_eq!(ti ^ z, t);
- assert_eq!(t ^ zi, t);
- assert_eq!(zi ^ t, t);
- assert_eq!(z ^ ti, t);
-
- {
- // AndAssign:
- let mut v = o;
- v &= ti;
- assert_eq!(v, z);
- }
- {
- // OrAssign:
- let mut v = z;
- v |= oi;
- assert_eq!(v, o);
- }
- {
- // XORAssign:
- let mut v = z;
- v ^= oi;
- assert_eq!(v, o);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/scalar_mask_bitwise.rs b/third_party/rust/packed_simd/src/api/ops/scalar_mask_bitwise.rs
deleted file mode 100644
index 523a85207b..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/scalar_mask_bitwise.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-//! Vertical (lane-wise) vector-vector bitwise operations.
-
-macro_rules! impl_ops_scalar_mask_bitwise {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $test_tt:tt |
- ($true:expr, $false:expr)
- ) => {
- impl crate::ops::BitXor<bool> for $id {
- type Output = Self;
- #[inline]
- fn bitxor(self, other: bool) -> Self {
- self ^ $id::splat(other)
- }
- }
- impl crate::ops::BitXor<$id> for bool {
- type Output = $id;
- #[inline]
- fn bitxor(self, other: $id) -> $id {
- $id::splat(self) ^ other
- }
- }
-
- impl crate::ops::BitAnd<bool> for $id {
- type Output = Self;
- #[inline]
- fn bitand(self, other: bool) -> Self {
- self & $id::splat(other)
- }
- }
- impl crate::ops::BitAnd<$id> for bool {
- type Output = $id;
- #[inline]
- fn bitand(self, other: $id) -> $id {
- $id::splat(self) & other
- }
- }
-
- impl crate::ops::BitOr<bool> for $id {
- type Output = Self;
- #[inline]
- fn bitor(self, other: bool) -> Self {
- self | $id::splat(other)
- }
- }
- impl crate::ops::BitOr<$id> for bool {
- type Output = $id;
- #[inline]
- fn bitor(self, other: $id) -> $id {
- $id::splat(self) | other
- }
- }
-
- impl crate::ops::BitAndAssign<bool> for $id {
- #[inline]
- fn bitand_assign(&mut self, other: bool) {
- *self = *self & other;
- }
- }
- impl crate::ops::BitOrAssign<bool> for $id {
- #[inline]
- fn bitor_assign(&mut self, other: bool) {
- *self = *self | other;
- }
- }
- impl crate::ops::BitXorAssign<bool> for $id {
- #[inline]
- fn bitxor_assign(&mut self, other: bool) {
- *self = *self ^ other;
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_scalar_mask_bitwise>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn ops_scalar_mask_bitwise() {
- let ti = true;
- let fi = false;
- let t = $id::splat(ti);
- let f = $id::splat(fi);
- assert!(t != f);
- assert!(!(t == f));
-
- // BitAnd:
- assert_eq!(ti & f, f);
- assert_eq!(t & fi, f);
- assert_eq!(fi & t, f);
- assert_eq!(f & ti, f);
- assert_eq!(ti & t, t);
- assert_eq!(t & ti, t);
- assert_eq!(fi & f, f);
- assert_eq!(f & fi, f);
-
- // BitOr:
- assert_eq!(ti | f, t);
- assert_eq!(t | fi, t);
- assert_eq!(fi | t, t);
- assert_eq!(f | ti, t);
- assert_eq!(ti | t, t);
- assert_eq!(t | ti, t);
- assert_eq!(fi | f, f);
- assert_eq!(f | fi, f);
-
- // BitXOR:
- assert_eq!(ti ^ f, t);
- assert_eq!(t ^ fi, t);
- assert_eq!(fi ^ t, t);
- assert_eq!(f ^ ti, t);
- assert_eq!(ti ^ t, f);
- assert_eq!(t ^ ti, f);
- assert_eq!(fi ^ f, f);
- assert_eq!(f ^ fi, f);
-
- {
- // AndAssign:
- let mut v = f;
- v &= ti;
- assert_eq!(v, f);
- }
- {
- // OrAssign:
- let mut v = f;
- v |= ti;
- assert_eq!(v, t);
- }
- {
- // XORAssign:
- let mut v = f;
- v ^= ti;
- assert_eq!(v, t);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/scalar_shifts.rs b/third_party/rust/packed_simd/src/api/ops/scalar_shifts.rs
deleted file mode 100644
index 4a7a096263..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/scalar_shifts.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-//! Vertical (lane-wise) vector-scalar shifts operations.
-
-macro_rules! impl_ops_scalar_shifts {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::ops::Shl<u32> for $id {
- type Output = Self;
- #[inline]
- fn shl(self, other: u32) -> Self {
- self << $id::splat(other as $elem_ty)
- }
- }
- impl crate::ops::Shr<u32> for $id {
- type Output = Self;
- #[inline]
- fn shr(self, other: u32) -> Self {
- self >> $id::splat(other as $elem_ty)
- }
- }
-
- impl crate::ops::ShlAssign<u32> for $id {
- #[inline]
- fn shl_assign(&mut self, other: u32) {
- *self = *self << other;
- }
- }
- impl crate::ops::ShrAssign<u32> for $id {
- #[inline]
- fn shr_assign(&mut self, other: u32) {
- *self = *self >> other;
- }
- }
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_scalar_shifts>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg_attr(any(target_arch = "s390x", target_arch = "sparc64"),
- allow(unreachable_code, unused_variables)
- )]
- #[cfg(not(target_arch = "aarch64"))]
- //~^ FIXME: https://github.com/rust-lang/packed_simd/issues/317
- fn ops_scalar_shifts() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let f = $id::splat(4 as $elem_ty);
-
- {
- let zi = 0 as u32;
- let oi = 1 as u32;
- let ti = 2 as u32;
- let maxi
- = (mem::size_of::<$elem_ty>() * 8 - 1) as u32;
-
- // shr
- assert_eq!(z >> zi, z);
- assert_eq!(z >> oi, z);
- assert_eq!(z >> ti, z);
- assert_eq!(z >> ti, z);
-
- #[cfg(any(target_arch = "s390x", target_arch = "sparc64"))] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/13
- return;
- }
-
- assert_eq!(o >> zi, o);
- assert_eq!(t >> zi, t);
- assert_eq!(f >> zi, f);
- assert_eq!(f >> maxi, z);
-
- assert_eq!(o >> oi, z);
- assert_eq!(t >> oi, o);
- assert_eq!(t >> ti, z);
- assert_eq!(f >> oi, t);
- assert_eq!(f >> ti, o);
- assert_eq!(f >> maxi, z);
-
- // shl
- assert_eq!(z << zi, z);
- assert_eq!(o << zi, o);
- assert_eq!(t << zi, t);
- assert_eq!(f << zi, f);
- assert_eq!(f << maxi, z);
-
- assert_eq!(o << oi, t);
- assert_eq!(o << ti, f);
- assert_eq!(t << oi, f);
-
- { // shr_assign
- let mut v = o;
- v >>= oi;
- assert_eq!(v, z);
- }
- { // shl_assign
- let mut v = o;
- v <<= oi;
- assert_eq!(v, t);
- }
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_arithmetic.rs b/third_party/rust/packed_simd/src/api/ops/vector_arithmetic.rs
deleted file mode 100644
index 7057f52d03..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_arithmetic.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-//! Vertical (lane-wise) vector-vector arithmetic operations.
-
-macro_rules! impl_ops_vector_arithmetic {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::ops::Add for $id {
- type Output = Self;
- #[inline]
- fn add(self, other: Self) -> Self {
- use crate::llvm::simd_add;
- unsafe { Simd(simd_add(self.0, other.0)) }
- }
- }
-
- impl crate::ops::Sub for $id {
- type Output = Self;
- #[inline]
- fn sub(self, other: Self) -> Self {
- use crate::llvm::simd_sub;
- unsafe { Simd(simd_sub(self.0, other.0)) }
- }
- }
-
- impl crate::ops::Mul for $id {
- type Output = Self;
- #[inline]
- fn mul(self, other: Self) -> Self {
- use crate::llvm::simd_mul;
- unsafe { Simd(simd_mul(self.0, other.0)) }
- }
- }
-
- impl crate::ops::Div for $id {
- type Output = Self;
- #[inline]
- fn div(self, other: Self) -> Self {
- use crate::llvm::simd_div;
- unsafe { Simd(simd_div(self.0, other.0)) }
- }
- }
-
- impl crate::ops::Rem for $id {
- type Output = Self;
- #[inline]
- fn rem(self, other: Self) -> Self {
- use crate::llvm::simd_rem;
- unsafe { Simd(simd_rem(self.0, other.0)) }
- }
- }
-
- impl crate::ops::AddAssign for $id {
- #[inline]
- fn add_assign(&mut self, other: Self) {
- *self = *self + other;
- }
- }
-
- impl crate::ops::SubAssign for $id {
- #[inline]
- fn sub_assign(&mut self, other: Self) {
- *self = *self - other;
- }
- }
-
- impl crate::ops::MulAssign for $id {
- #[inline]
- fn mul_assign(&mut self, other: Self) {
- *self = *self * other;
- }
- }
-
- impl crate::ops::DivAssign for $id {
- #[inline]
- fn div_assign(&mut self, other: Self) {
- *self = *self / other;
- }
- }
-
- impl crate::ops::RemAssign for $id {
- #[inline]
- fn rem_assign(&mut self, other: Self) {
- *self = *self % other;
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_vector_arith>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn ops_vector_arithmetic() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let f = $id::splat(4 as $elem_ty);
-
- // add
- assert_eq!(z + z, z);
- assert_eq!(o + z, o);
- assert_eq!(t + z, t);
- assert_eq!(t + t, f);
- // sub
- assert_eq!(z - z, z);
- assert_eq!(o - z, o);
- assert_eq!(t - z, t);
- assert_eq!(f - t, t);
- assert_eq!(f - o - o, t);
- // mul
- assert_eq!(z * z, z);
- assert_eq!(z * o, z);
- assert_eq!(z * t, z);
- assert_eq!(o * t, t);
- assert_eq!(t * t, f);
- // div
- assert_eq!(z / o, z);
- assert_eq!(t / o, t);
- assert_eq!(f / o, f);
- assert_eq!(t / t, o);
- assert_eq!(f / t, t);
- // rem
- assert_eq!(o % o, z);
- assert_eq!(f % t, z);
-
- {
- let mut v = z;
- assert_eq!(v, z);
- v += o; // add_assign
- assert_eq!(v, o);
- v -= o; // sub_assign
- assert_eq!(v, z);
- v = t;
- v *= o; // mul_assign
- assert_eq!(v, t);
- v *= t;
- assert_eq!(v, f);
- v /= o; // div_assign
- assert_eq!(v, f);
- v /= t;
- assert_eq!(v, t);
- v %= t; // rem_assign
- assert_eq!(v, z);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_bitwise.rs b/third_party/rust/packed_simd/src/api/ops/vector_bitwise.rs
deleted file mode 100644
index 7be9603fa2..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_bitwise.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-//! Vertical (lane-wise) vector-vector bitwise operations.
-
-macro_rules! impl_ops_vector_bitwise {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $test_tt:tt |
- ($true:expr, $false:expr)
- ) => {
- impl crate::ops::Not for $id {
- type Output = Self;
- #[inline]
- fn not(self) -> Self {
- Self::splat($true) ^ self
- }
- }
- impl crate::ops::BitXor for $id {
- type Output = Self;
- #[inline]
- fn bitxor(self, other: Self) -> Self {
- use crate::llvm::simd_xor;
- unsafe { Simd(simd_xor(self.0, other.0)) }
- }
- }
- impl crate::ops::BitAnd for $id {
- type Output = Self;
- #[inline]
- fn bitand(self, other: Self) -> Self {
- use crate::llvm::simd_and;
- unsafe { Simd(simd_and(self.0, other.0)) }
- }
- }
- impl crate::ops::BitOr for $id {
- type Output = Self;
- #[inline]
- fn bitor(self, other: Self) -> Self {
- use crate::llvm::simd_or;
- unsafe { Simd(simd_or(self.0, other.0)) }
- }
- }
- impl crate::ops::BitAndAssign for $id {
- #[inline]
- fn bitand_assign(&mut self, other: Self) {
- *self = *self & other;
- }
- }
- impl crate::ops::BitOrAssign for $id {
- #[inline]
- fn bitor_assign(&mut self, other: Self) {
- *self = *self | other;
- }
- }
- impl crate::ops::BitXorAssign for $id {
- #[inline]
- fn bitxor_assign(&mut self, other: Self) {
- *self = *self ^ other;
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_vector_bitwise>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn ops_vector_bitwise() {
-
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let m = $id::splat(!z.extract(0));
-
- // Not:
- assert_eq!(!z, m);
- assert_eq!(!m, z);
-
- // BitAnd:
- assert_eq!(o & o, o);
- assert_eq!(o & z, z);
- assert_eq!(z & o, z);
- assert_eq!(z & z, z);
-
- assert_eq!(t & t, t);
- assert_eq!(t & o, z);
- assert_eq!(o & t, z);
-
- // BitOr:
- assert_eq!(o | o, o);
- assert_eq!(o | z, o);
- assert_eq!(z | o, o);
- assert_eq!(z | z, z);
-
- assert_eq!(t | t, t);
- assert_eq!(z | t, t);
- assert_eq!(t | z, t);
-
- // BitXOR:
- assert_eq!(o ^ o, z);
- assert_eq!(z ^ z, z);
- assert_eq!(z ^ o, o);
- assert_eq!(o ^ z, o);
-
- assert_eq!(t ^ t, z);
- assert_eq!(t ^ z, t);
- assert_eq!(z ^ t, t);
-
- {
- // AndAssign:
- let mut v = o;
- v &= t;
- assert_eq!(v, z);
- }
- {
- // OrAssign:
- let mut v = z;
- v |= o;
- assert_eq!(v, o);
- }
- {
- // XORAssign:
- let mut v = z;
- v ^= o;
- assert_eq!(v, o);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_float_min_max.rs b/third_party/rust/packed_simd/src/api/ops/vector_float_min_max.rs
deleted file mode 100644
index 8310667b7a..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_float_min_max.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-//! Vertical (lane-wise) vector `min` and `max` for floating-point vectors.
-
-macro_rules! impl_ops_vector_float_min_max {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Minimum of two vectors.
- ///
- /// Returns a new vector containing the minimum value of each of
- /// the input vector lanes.
- #[inline]
- pub fn min(self, x: Self) -> Self {
- use crate::llvm::simd_fmin;
- unsafe { Simd(simd_fmin(self.0, x.0)) }
- }
-
- /// Maximum of two vectors.
- ///
- /// Returns a new vector containing the maximum value of each of
- /// the input vector lanes.
- #[inline]
- pub fn max(self, x: Self) -> Self {
- use crate::llvm::simd_fmax;
- unsafe { Simd(simd_fmax(self.0, x.0)) }
- }
- }
- test_if!{
- $test_tt:
- paste::item! {
- #[cfg(not(any(
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/223
- all(target_arch = "mips", target_endian = "big"),
- target_arch = "mips64",
- )))]
- pub mod [<$id _ops_vector_min_max>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn min_max() {
- let n = crate::$elem_ty::NAN;
- let o = $id::splat(1. as $elem_ty);
- let t = $id::splat(2. as $elem_ty);
-
- let mut m = o; // [1., 2., 1., 2., ...]
- let mut on = o;
- for i in 0..$id::lanes() {
- if i % 2 == 0 {
- m = m.replace(i, 2. as $elem_ty);
- on = on.replace(i, n);
- }
- }
-
- assert_eq!(o.min(t), o);
- assert_eq!(t.min(o), o);
- assert_eq!(m.min(o), o);
- assert_eq!(o.min(m), o);
- assert_eq!(m.min(t), m);
- assert_eq!(t.min(m), m);
-
- assert_eq!(o.max(t), t);
- assert_eq!(t.max(o), t);
- assert_eq!(m.max(o), m);
- assert_eq!(o.max(m), m);
- assert_eq!(m.max(t), t);
- assert_eq!(t.max(m), t);
-
- assert_eq!(on.min(o), o);
- assert_eq!(o.min(on), o);
- assert_eq!(on.max(o), o);
- assert_eq!(o.max(on), o);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_int_min_max.rs b/third_party/rust/packed_simd/src/api/ops/vector_int_min_max.rs
deleted file mode 100644
index 36ea98e6bf..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_int_min_max.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-//! Vertical (lane-wise) vector `min` and `max` for integer vectors.
-
-macro_rules! impl_ops_vector_int_min_max {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Minimum of two vectors.
- ///
- /// Returns a new vector containing the minimum value of each of
- /// the input vector lanes.
- #[inline]
- pub fn min(self, x: Self) -> Self {
- self.lt(x).select(self, x)
- }
-
- /// Maximum of two vectors.
- ///
- /// Returns a new vector containing the maximum value of each of
- /// the input vector lanes.
- #[inline]
- pub fn max(self, x: Self) -> Self {
- self.gt(x).select(self, x)
- }
- }
- test_if!{$test_tt:
- paste::item! {
- pub mod [<$id _ops_vector_min_max>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn min_max() {
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
-
- let mut m = o;
- for i in 0..$id::lanes() {
- if i % 2 == 0 {
- m = m.replace(i, 2 as $elem_ty);
- }
- }
- assert_eq!(o.min(t), o);
- assert_eq!(t.min(o), o);
- assert_eq!(m.min(o), o);
- assert_eq!(o.min(m), o);
- assert_eq!(m.min(t), m);
- assert_eq!(t.min(m), m);
-
- assert_eq!(o.max(t), t);
- assert_eq!(t.max(o), t);
- assert_eq!(m.max(o), m);
- assert_eq!(o.max(m), m);
- assert_eq!(m.max(t), t);
- assert_eq!(t.max(m), t);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_mask_bitwise.rs b/third_party/rust/packed_simd/src/api/ops/vector_mask_bitwise.rs
deleted file mode 100644
index 295fc1ca81..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_mask_bitwise.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-//! Vertical (lane-wise) vector-vector bitwise operations.
-
-macro_rules! impl_ops_vector_mask_bitwise {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $test_tt:tt |
- ($true:expr, $false:expr)
- ) => {
- impl crate::ops::Not for $id {
- type Output = Self;
- #[inline]
- fn not(self) -> Self {
- Self::splat($true) ^ self
- }
- }
- impl crate::ops::BitXor for $id {
- type Output = Self;
- #[inline]
- fn bitxor(self, other: Self) -> Self {
- use crate::llvm::simd_xor;
- unsafe { Simd(simd_xor(self.0, other.0)) }
- }
- }
- impl crate::ops::BitAnd for $id {
- type Output = Self;
- #[inline]
- fn bitand(self, other: Self) -> Self {
- use crate::llvm::simd_and;
- unsafe { Simd(simd_and(self.0, other.0)) }
- }
- }
- impl crate::ops::BitOr for $id {
- type Output = Self;
- #[inline]
- fn bitor(self, other: Self) -> Self {
- use crate::llvm::simd_or;
- unsafe { Simd(simd_or(self.0, other.0)) }
- }
- }
- impl crate::ops::BitAndAssign for $id {
- #[inline]
- fn bitand_assign(&mut self, other: Self) {
- *self = *self & other;
- }
- }
- impl crate::ops::BitOrAssign for $id {
- #[inline]
- fn bitor_assign(&mut self, other: Self) {
- *self = *self | other;
- }
- }
- impl crate::ops::BitXorAssign for $id {
- #[inline]
- fn bitxor_assign(&mut self, other: Self) {
- *self = *self ^ other;
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_vector_mask_bitwise>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn ops_vector_mask_bitwise() {
- let t = $id::splat(true);
- let f = $id::splat(false);
- assert!(t != f);
- assert!(!(t == f));
-
- // Not:
- assert_eq!(!t, f);
- assert_eq!(t, !f);
-
- // BitAnd:
- assert_eq!(t & f, f);
- assert_eq!(f & t, f);
- assert_eq!(t & t, t);
- assert_eq!(f & f, f);
-
- // BitOr:
- assert_eq!(t | f, t);
- assert_eq!(f | t, t);
- assert_eq!(t | t, t);
- assert_eq!(f | f, f);
-
- // BitXOR:
- assert_eq!(t ^ f, t);
- assert_eq!(f ^ t, t);
- assert_eq!(t ^ t, f);
- assert_eq!(f ^ f, f);
-
- {
- // AndAssign:
- let mut v = f;
- v &= t;
- assert_eq!(v, f);
- }
- {
- // OrAssign:
- let mut v = f;
- v |= t;
- assert_eq!(v, t);
- }
- {
- // XORAssign:
- let mut v = f;
- v ^= t;
- assert_eq!(v, t);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_neg.rs b/third_party/rust/packed_simd/src/api/ops/vector_neg.rs
deleted file mode 100644
index e2d91fd2fe..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_neg.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-//! Vertical (lane-wise) vector `Neg`.
-
-macro_rules! impl_ops_vector_neg {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::ops::Neg for $id {
- type Output = Self;
- #[inline]
- fn neg(self) -> Self {
- Self::splat(-1 as $elem_ty) * self
- }
- }
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_vector_neg>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn neg() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let f = $id::splat(4 as $elem_ty);
-
- let nz = $id::splat(-(0 as $elem_ty));
- let no = $id::splat(-(1 as $elem_ty));
- let nt = $id::splat(-(2 as $elem_ty));
- let nf = $id::splat(-(4 as $elem_ty));
-
- assert_eq!(-z, nz);
- assert_eq!(-o, no);
- assert_eq!(-t, nt);
- assert_eq!(-f, nf);
-
- assert_eq!(z, -nz);
- assert_eq!(o, -no);
- assert_eq!(t, -nt);
- assert_eq!(f, -nf);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_rotates.rs b/third_party/rust/packed_simd/src/api/ops/vector_rotates.rs
deleted file mode 100644
index 6c4bed72a2..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_rotates.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-//! Vertical (lane-wise) vector rotates operations.
-#![allow(unused)]
-
-macro_rules! impl_ops_vector_rotates {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Shifts the bits of each lane to the left by the specified
- /// amount in the corresponding lane of `n`, wrapping the
- /// truncated bits to the end of the resulting integer.
- ///
- /// Note: this is neither the same operation as `<<` nor equivalent
- /// to `slice::rotate_left`.
- #[inline]
- pub fn rotate_left(self, n: $id) -> $id {
- const LANE_WIDTH: $elem_ty =
- crate::mem::size_of::<$elem_ty>() as $elem_ty * 8;
- // Protect against undefined behavior for over-long bit shifts
- let n = n % LANE_WIDTH;
- (self << n) | (self >> ((LANE_WIDTH - n) % LANE_WIDTH))
- }
-
- /// Shifts the bits of each lane to the right by the specified
- /// amount in the corresponding lane of `n`, wrapping the
- /// truncated bits to the beginning of the resulting integer.
- ///
- /// Note: this is neither the same operation as `>>` nor equivalent
- /// to `slice::rotate_right`.
- #[inline]
- pub fn rotate_right(self, n: $id) -> $id {
- const LANE_WIDTH: $elem_ty =
- crate::mem::size_of::<$elem_ty>() as $elem_ty * 8;
- // Protect against undefined behavior for over-long bit shifts
- let n = n % LANE_WIDTH;
- (self >> n) | (self << ((LANE_WIDTH - n) % LANE_WIDTH))
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- // FIXME:
- // https://github.com/rust-lang-nursery/packed_simd/issues/75
- #[cfg(not(any(
- target_arch = "s390x",
- target_arch = "sparc64",
- )))]
- pub mod [<$id _ops_vector_rotate>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "aarch64"))]
- //~^ FIXME: https://github.com/rust-lang/packed_simd/issues/317
- fn rotate_ops() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let f = $id::splat(4 as $elem_ty);
-
- let max = $id::splat(
- (mem::size_of::<$elem_ty>() * 8 - 1) as $elem_ty);
-
- // rotate_right
- assert_eq!(z.rotate_right(z), z);
- assert_eq!(z.rotate_right(o), z);
- assert_eq!(z.rotate_right(t), z);
-
- assert_eq!(o.rotate_right(z), o);
- assert_eq!(t.rotate_right(z), t);
- assert_eq!(f.rotate_right(z), f);
- assert_eq!(f.rotate_right(max), f << 1);
-
- assert_eq!(o.rotate_right(o), o << max);
- assert_eq!(t.rotate_right(o), o);
- assert_eq!(t.rotate_right(t), o << max);
- assert_eq!(f.rotate_right(o), t);
- assert_eq!(f.rotate_right(t), o);
-
- // rotate_left
- assert_eq!(z.rotate_left(z), z);
- assert_eq!(o.rotate_left(z), o);
- assert_eq!(t.rotate_left(z), t);
- assert_eq!(f.rotate_left(z), f);
- assert_eq!(f.rotate_left(max), t);
-
- assert_eq!(o.rotate_left(o), t);
- assert_eq!(o.rotate_left(t), f);
- assert_eq!(t.rotate_left(o), f);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_shifts.rs b/third_party/rust/packed_simd/src/api/ops/vector_shifts.rs
deleted file mode 100644
index 8bb5ac2fc0..0000000000
--- a/third_party/rust/packed_simd/src/api/ops/vector_shifts.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-//! Vertical (lane-wise) vector-vector shifts operations.
-
-macro_rules! impl_ops_vector_shifts {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl crate::ops::Shl<$id> for $id {
- type Output = Self;
- #[inline]
- fn shl(self, other: Self) -> Self {
- use crate::llvm::simd_shl;
- unsafe { Simd(simd_shl(self.0, other.0)) }
- }
- }
- impl crate::ops::Shr<$id> for $id {
- type Output = Self;
- #[inline]
- fn shr(self, other: Self) -> Self {
- use crate::llvm::simd_shr;
- unsafe { Simd(simd_shr(self.0, other.0)) }
- }
- }
- impl crate::ops::ShlAssign<$id> for $id {
- #[inline]
- fn shl_assign(&mut self, other: Self) {
- *self = *self << other;
- }
- }
- impl crate::ops::ShrAssign<$id> for $id {
- #[inline]
- fn shr_assign(&mut self, other: Self) {
- *self = *self >> other;
- }
- }
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _ops_vector_shifts>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg_attr(any(target_arch = "s390x", target_arch = "sparc64"),
- allow(unreachable_code, unused_variables)
- )]
- #[cfg(not(target_arch = "aarch64"))]
- //~^ FIXME: https://github.com/rust-lang/packed_simd/issues/317
- fn ops_vector_shifts() {
- let z = $id::splat(0 as $elem_ty);
- let o = $id::splat(1 as $elem_ty);
- let t = $id::splat(2 as $elem_ty);
- let f = $id::splat(4 as $elem_ty);
-
- let max =$id::splat(
- (mem::size_of::<$elem_ty>() * 8 - 1) as $elem_ty
- );
-
- // shr
- assert_eq!(z >> z, z);
- assert_eq!(z >> o, z);
- assert_eq!(z >> t, z);
- assert_eq!(z >> t, z);
-
- #[cfg(any(target_arch = "s390x", target_arch = "sparc64"))] {
- // FIXME: rust produces bad codegen for shifts:
- // https://github.com/rust-lang-nursery/packed_simd/issues/13
- return;
- }
-
- assert_eq!(o >> z, o);
- assert_eq!(t >> z, t);
- assert_eq!(f >> z, f);
- assert_eq!(f >> max, z);
-
- assert_eq!(o >> o, z);
- assert_eq!(t >> o, o);
- assert_eq!(t >> t, z);
- assert_eq!(f >> o, t);
- assert_eq!(f >> t, o);
- assert_eq!(f >> max, z);
-
- // shl
- assert_eq!(z << z, z);
- assert_eq!(o << z, o);
- assert_eq!(t << z, t);
- assert_eq!(f << z, f);
- assert_eq!(f << max, z);
-
- assert_eq!(o << o, t);
- assert_eq!(o << t, f);
- assert_eq!(t << o, f);
-
- {
- // shr_assign
- let mut v = o;
- v >>= o;
- assert_eq!(v, z);
- }
- {
- // shl_assign
- let mut v = o;
- v <<= o;
- assert_eq!(v, t);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/ptr.rs b/third_party/rust/packed_simd/src/api/ptr.rs
deleted file mode 100644
index d2e523a49f..0000000000
--- a/third_party/rust/packed_simd/src/api/ptr.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//! Vector of pointers
-
-#[macro_use]
-mod gather_scatter;
diff --git a/third_party/rust/packed_simd/src/api/ptr/gather_scatter.rs b/third_party/rust/packed_simd/src/api/ptr/gather_scatter.rs
deleted file mode 100644
index 374482ac31..0000000000
--- a/third_party/rust/packed_simd/src/api/ptr/gather_scatter.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-//! Implements masked gather and scatters for vectors of pointers
-
-macro_rules! impl_ptr_read {
- ([$elem_ty:ty; $elem_count:expr]: $id:ident, $mask_ty:ident
- | $test_tt:tt) => {
- impl<T> $id<T>
- where
- [T; $elem_count]: sealed::SimdArray,
- {
- /// Reads selected vector elements from memory.
- ///
- /// Instantiates a new vector by reading the values from `self` for
- /// those lanes whose `mask` is `true`, and using the elements of
- /// `value` otherwise.
- ///
- /// No memory is accessed for those lanes of `self` whose `mask` is
- /// `false`.
- ///
- /// # Safety
- ///
- /// This method is unsafe because it dereferences raw pointers. The
- /// pointers must be aligned to `mem::align_of::<T>()`.
- #[inline]
- pub unsafe fn read<M>(
- self,
- mask: Simd<[M; $elem_count]>,
- value: Simd<[T; $elem_count]>,
- ) -> Simd<[T; $elem_count]>
- where
- M: sealed::Mask,
- [M; $elem_count]: sealed::SimdArray,
- {
- use crate::llvm::simd_gather;
- Simd(simd_gather(value.0, self.0, mask.0))
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- mod [<$id _read>] {
- use super::*;
- #[test]
- fn read() {
- let mut v = [0_i32; $elem_count];
- for i in 0..$elem_count {
- v[i] = i as i32;
- }
-
- let mut ptr = $id::<i32>::null();
-
- for i in 0..$elem_count {
- ptr = ptr.replace(i,
- &v[i] as *const i32 as *mut i32
- );
- }
-
- // all mask elements are true:
- let mask = $mask_ty::splat(true);
- let def = Simd::<[i32; $elem_count]>::splat(42_i32);
- let r: Simd<[i32; $elem_count]> = unsafe {
- ptr.read(mask, def)
- };
- assert_eq!(
- r,
- Simd::<[i32; $elem_count]>::from_slice_unaligned(
- &v
- )
- );
-
- let mut mask = mask;
- for i in 0..$elem_count {
- if i % 2 != 0 {
- mask = mask.replace(i, false);
- }
- }
-
- // even mask elements are true, odd ones are false:
- let r: Simd<[i32; $elem_count]> = unsafe {
- ptr.read(mask, def)
- };
- let mut e = v;
- for i in 0..$elem_count {
- if i % 2 != 0 {
- e[i] = 42;
- }
- }
- assert_eq!(
- r,
- Simd::<[i32; $elem_count]>::from_slice_unaligned(
- &e
- )
- );
-
- // all mask elements are false:
- let mask = $mask_ty::splat(false);
- let def = Simd::<[i32; $elem_count]>::splat(42_i32);
- let r: Simd<[i32; $elem_count]> = unsafe {
- ptr.read(mask, def) }
- ;
- assert_eq!(r, def);
- }
- }
- }
- }
- };
-}
-
-macro_rules! impl_ptr_write {
- ([$elem_ty:ty; $elem_count:expr]: $id:ident, $mask_ty:ident
- | $test_tt:tt) => {
- impl<T> $id<T>
- where
- [T; $elem_count]: sealed::SimdArray,
- {
- /// Writes selected vector elements to memory.
- ///
- /// Writes the lanes of `values` for which the mask is `true` to
- /// their corresponding memory addresses in `self`.
- ///
- /// No memory is accessed for those lanes of `self` whose `mask` is
- /// `false`.
- ///
- /// Overlapping memory addresses of `self` are written to in order
- /// from the lest-significant to the most-significant element.
- ///
- /// # Safety
- ///
- /// This method is unsafe because it dereferences raw pointers. The
- /// pointers must be aligned to `mem::align_of::<T>()`.
- #[inline]
- pub unsafe fn write<M>(self, mask: Simd<[M; $elem_count]>, value: Simd<[T; $elem_count]>)
- where
- M: sealed::Mask,
- [M; $elem_count]: sealed::SimdArray,
- {
- use crate::llvm::simd_scatter;
- simd_scatter(value.0, self.0, mask.0)
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- mod [<$id _write>] {
- use super::*;
- #[test]
- fn write() {
- // forty_two = [42, 42, 42, ...]
- let forty_two
- = Simd::<[i32; $elem_count]>::splat(42_i32);
-
- // This test will write to this array
- let mut arr = [0_i32; $elem_count];
- for i in 0..$elem_count {
- arr[i] = i as i32;
- }
- // arr = [0, 1, 2, ...]
-
- let mut ptr = $id::<i32>::null();
- for i in 0..$elem_count {
- ptr = ptr.replace(i, unsafe {
- arr.as_ptr().add(i) as *mut i32
- });
- }
- // ptr = [&arr[0], &arr[1], ...]
-
- // write `forty_two` to all elements of `v`
- {
- let backup = arr;
- unsafe {
- ptr.write($mask_ty::splat(true), forty_two)
- };
- assert_eq!(arr, [42_i32; $elem_count]);
- arr = backup; // arr = [0, 1, 2, ...]
- }
-
- // write 42 to even elements of arr:
- {
- // set odd elements of the mask to false
- let mut mask = $mask_ty::splat(true);
- for i in 0..$elem_count {
- if i % 2 != 0 {
- mask = mask.replace(i, false);
- }
- }
- // mask = [true, false, true, false, ...]
-
- // expected result r = [42, 1, 42, 3, 42, 5, ...]
- let mut r = arr;
- for i in 0..$elem_count {
- if i % 2 == 0 {
- r[i] = 42;
- }
- }
-
- let backup = arr;
- unsafe { ptr.write(mask, forty_two) };
- assert_eq!(arr, r);
- arr = backup; // arr = [0, 1, 2, 3, ...]
- }
-
- // write 42 to no elements of arr
- {
- let backup = arr;
- unsafe {
- ptr.write($mask_ty::splat(false), forty_two)
- };
- assert_eq!(arr, backup);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/reductions.rs b/third_party/rust/packed_simd/src/api/reductions.rs
deleted file mode 100644
index 54d2f0cc7f..0000000000
--- a/third_party/rust/packed_simd/src/api/reductions.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//! Reductions
-
-#[macro_use]
-mod float_arithmetic;
-#[macro_use]
-mod integer_arithmetic;
-#[macro_use]
-mod bitwise;
-#[macro_use]
-mod mask;
-#[macro_use]
-mod min_max;
diff --git a/third_party/rust/packed_simd/src/api/reductions/bitwise.rs b/third_party/rust/packed_simd/src/api/reductions/bitwise.rs
deleted file mode 100644
index 5bad4f474b..0000000000
--- a/third_party/rust/packed_simd/src/api/reductions/bitwise.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-//! Implements portable horizontal bitwise vector reductions.
-#![allow(unused)]
-
-macro_rules! impl_reduction_bitwise {
- (
- [$elem_ty:ident; $elem_count:expr]:
- $id:ident | $ielem_ty:ident | $test_tt:tt |
- ($convert:expr) |
- ($true:expr, $false:expr)
- ) => {
- impl $id {
- /// Lane-wise bitwise `and` of the vector elements.
- ///
- /// Note: if the vector has one lane, the first element of the
- /// vector is returned.
- #[inline]
- pub fn and(self) -> $elem_ty {
- #[cfg(not(target_arch = "aarch64"))]
- {
- use crate::llvm::simd_reduce_and;
- let r: $ielem_ty = unsafe { simd_reduce_and(self.0) };
- $convert(r)
- }
- #[cfg(target_arch = "aarch64")]
- {
- // FIXME: broken on aarch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- let mut x = self.extract(0) as $elem_ty;
- for i in 1..$id::lanes() {
- x &= self.extract(i) as $elem_ty;
- }
- x
- }
- }
-
- /// Lane-wise bitwise `or` of the vector elements.
- ///
- /// Note: if the vector has one lane, the first element of the
- /// vector is returned.
- #[inline]
- pub fn or(self) -> $elem_ty {
- #[cfg(not(target_arch = "aarch64"))]
- {
- use crate::llvm::simd_reduce_or;
- let r: $ielem_ty = unsafe { simd_reduce_or(self.0) };
- $convert(r)
- }
- #[cfg(target_arch = "aarch64")]
- {
- // FIXME: broken on aarch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- let mut x = self.extract(0) as $elem_ty;
- for i in 1..$id::lanes() {
- x |= self.extract(i) as $elem_ty;
- }
- x
- }
- }
-
- /// Lane-wise bitwise `xor` of the vector elements.
- ///
- /// Note: if the vector has one lane, the first element of the
- /// vector is returned.
- #[inline]
- pub fn xor(self) -> $elem_ty {
- #[cfg(not(target_arch = "aarch64"))]
- {
- use crate::llvm::simd_reduce_xor;
- let r: $ielem_ty = unsafe { simd_reduce_xor(self.0) };
- $convert(r)
- }
- #[cfg(target_arch = "aarch64")]
- {
- // FIXME: broken on aarch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- let mut x = self.extract(0) as $elem_ty;
- for i in 1..$id::lanes() {
- x ^= self.extract(i) as $elem_ty;
- }
- x
- }
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _reduction_bitwise>] {
- use super::*;
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn and() {
- let v = $id::splat($false);
- assert_eq!(v.and(), $false);
- let v = $id::splat($true);
- assert_eq!(v.and(), $true);
- let v = $id::splat($false);
- let v = v.replace(0, $true);
- if $id::lanes() > 1 {
- assert_eq!(v.and(), $false);
- } else {
- assert_eq!(v.and(), $true);
- }
- let v = $id::splat($true);
- let v = v.replace(0, $false);
- assert_eq!(v.and(), $false);
-
- }
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn or() {
- let v = $id::splat($false);
- assert_eq!(v.or(), $false);
- let v = $id::splat($true);
- assert_eq!(v.or(), $true);
- let v = $id::splat($false);
- let v = v.replace(0, $true);
- assert_eq!(v.or(), $true);
- let v = $id::splat($true);
- let v = v.replace(0, $false);
- if $id::lanes() > 1 {
- assert_eq!(v.or(), $true);
- } else {
- assert_eq!(v.or(), $false);
- }
- }
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn xor() {
- let v = $id::splat($false);
- assert_eq!(v.xor(), $false);
- let v = $id::splat($true);
- if $id::lanes() > 1 {
- assert_eq!(v.xor(), $false);
- } else {
- assert_eq!(v.xor(), $true);
- }
- let v = $id::splat($false);
- let v = v.replace(0, $true);
- assert_eq!(v.xor(), $true);
- let v = $id::splat($true);
- let v = v.replace(0, $false);
- if $id::lanes() > 1 {
- assert_eq!(v.xor(), $true);
- } else {
- assert_eq!(v.xor(), $false);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/reductions/float_arithmetic.rs b/third_party/rust/packed_simd/src/api/reductions/float_arithmetic.rs
deleted file mode 100644
index 9dc8783dbb..0000000000
--- a/third_party/rust/packed_simd/src/api/reductions/float_arithmetic.rs
+++ /dev/null
@@ -1,313 +0,0 @@
-//! Implements portable horizontal float vector arithmetic reductions.
-
-macro_rules! impl_reduction_float_arithmetic {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Horizontal sum of the vector elements.
- ///
- /// The intrinsic performs a tree-reduction of the vector elements.
- /// That is, for an 8 element vector:
- ///
- /// > ((x0 + x1) + (x2 + x3)) + ((x4 + x5) + (x6 + x7))
- ///
- /// If one of the vector element is `NaN` the reduction returns
- /// `NaN`. The resulting `NaN` is not required to be equal to any
- /// of the `NaN`s in the vector.
- #[inline]
- pub fn sum(self) -> $elem_ty {
- #[cfg(not(target_arch = "aarch64"))]
- {
- use crate::llvm::simd_reduce_add_ordered;
- unsafe { simd_reduce_add_ordered(self.0, 0 as $elem_ty) }
- }
- #[cfg(target_arch = "aarch64")]
- {
- // FIXME: broken on AArch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- let mut x = self.extract(0) as $elem_ty;
- for i in 1..$id::lanes() {
- x += self.extract(i) as $elem_ty;
- }
- x
- }
- }
-
- /// Horizontal product of the vector elements.
- ///
- /// The intrinsic performs a tree-reduction of the vector elements.
- /// That is, for an 8 element vector:
- ///
- /// > ((x0 * x1) * (x2 * x3)) * ((x4 * x5) * (x6 * x7))
- ///
- /// If one of the vector element is `NaN` the reduction returns
- /// `NaN`. The resulting `NaN` is not required to be equal to any
- /// of the `NaN`s in the vector.
- #[inline]
- pub fn product(self) -> $elem_ty {
- #[cfg(not(target_arch = "aarch64"))]
- {
- use crate::llvm::simd_reduce_mul_ordered;
- unsafe { simd_reduce_mul_ordered(self.0, 1 as $elem_ty) }
- }
- #[cfg(target_arch = "aarch64")]
- {
- // FIXME: broken on AArch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- let mut x = self.extract(0) as $elem_ty;
- for i in 1..$id::lanes() {
- x *= self.extract(i) as $elem_ty;
- }
- x
- }
- }
- }
-
- impl crate::iter::Sum for $id {
- #[inline]
- fn sum<I: Iterator<Item = $id>>(iter: I) -> $id {
- iter.fold($id::splat(0.), crate::ops::Add::add)
- }
- }
-
- impl crate::iter::Product for $id {
- #[inline]
- fn product<I: Iterator<Item = $id>>(iter: I) -> $id {
- iter.fold($id::splat(1.), crate::ops::Mul::mul)
- }
- }
-
- impl<'a> crate::iter::Sum<&'a $id> for $id {
- #[inline]
- fn sum<I: Iterator<Item = &'a $id>>(iter: I) -> $id {
- iter.fold($id::splat(0.), |a, b| crate::ops::Add::add(a, *b))
- }
- }
-
- impl<'a> crate::iter::Product<&'a $id> for $id {
- #[inline]
- fn product<I: Iterator<Item = &'a $id>>(iter: I) -> $id {
- iter.fold($id::splat(1.), |a, b| crate::ops::Mul::mul(a, *b))
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- pub mod [<$id _reduction_float_arith>] {
- use super::*;
- fn alternating(x: usize) -> $id {
- let mut v = $id::splat(1 as $elem_ty);
- for i in 0..$id::lanes() {
- if i % x == 0 {
- v = v.replace(i, 2 as $elem_ty);
- }
- }
- v
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn sum() {
- let v = $id::splat(0 as $elem_ty);
- assert_eq!(v.sum(), 0 as $elem_ty);
- let v = $id::splat(1 as $elem_ty);
- assert_eq!(v.sum(), $id::lanes() as $elem_ty);
- let v = alternating(2);
- assert_eq!(
- v.sum(),
- ($id::lanes() / 2 + $id::lanes()) as $elem_ty
- );
- }
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn product() {
- let v = $id::splat(0 as $elem_ty);
- assert_eq!(v.product(), 0 as $elem_ty);
- let v = $id::splat(1 as $elem_ty);
- assert_eq!(v.product(), 1 as $elem_ty);
- let f = match $id::lanes() {
- 64 => 16,
- 32 => 8,
- 16 => 4,
- _ => 2,
- };
- let v = alternating(f);
- assert_eq!(
- v.product(),
- (2_usize.pow(($id::lanes() / f) as u32)
- as $elem_ty)
- );
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[allow(unreachable_code)]
- fn sum_nan() {
- // FIXME: https://bugs.llvm.org/show_bug.cgi?id=36732
- // https://github.com/rust-lang-nursery/packed_simd/issues/6
- return;
-
- let n0 = crate::$elem_ty::NAN;
- let v0 = $id::splat(-3.0);
- for i in 0..$id::lanes() {
- let mut v = v0.replace(i, n0);
- // If the vector contains a NaN the result is NaN:
- assert!(
- v.sum().is_nan(),
- "nan at {} => {} | {:?}",
- i,
- v.sum(),
- v
- );
- for j in 0..i {
- v = v.replace(j, n0);
- assert!(v.sum().is_nan());
- }
- }
- let v = $id::splat(n0);
- assert!(v.sum().is_nan(), "all nans | {:?}", v);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[allow(unreachable_code)]
- fn product_nan() {
- // FIXME: https://bugs.llvm.org/show_bug.cgi?id=36732
- // https://github.com/rust-lang-nursery/packed_simd/issues/6
- return;
-
- let n0 = crate::$elem_ty::NAN;
- let v0 = $id::splat(-3.0);
- for i in 0..$id::lanes() {
- let mut v = v0.replace(i, n0);
- // If the vector contains a NaN the result is NaN:
- assert!(
- v.product().is_nan(),
- "nan at {} => {} | {:?}",
- i,
- v.product(),
- v
- );
- for j in 0..i {
- v = v.replace(j, n0);
- assert!(v.product().is_nan());
- }
- }
- let v = $id::splat(n0);
- assert!(v.product().is_nan(), "all nans | {:?}", v);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[allow(unused, dead_code)]
- fn sum_roundoff() {
- // Performs a tree-reduction
- fn tree_reduce_sum(a: &[$elem_ty]) -> $elem_ty {
- assert!(!a.is_empty());
- if a.len() == 1 {
- a[0]
- } else if a.len() == 2 {
- a[0] + a[1]
- } else {
- let mid = a.len() / 2;
- let (left, right) = a.split_at(mid);
- tree_reduce_sum(left) + tree_reduce_sum(right)
- }
- }
-
- let mut start = crate::$elem_ty::EPSILON;
- let mut scalar_reduction = 0. as $elem_ty;
-
- let mut v = $id::splat(0. as $elem_ty);
- for i in 0..$id::lanes() {
- let c = if i % 2 == 0 { 1e3 } else { -1. };
- start *= ::core::$elem_ty::consts::PI * c;
- scalar_reduction += start;
- v = v.replace(i, start);
- }
- let simd_reduction = v.sum();
-
- let mut a = [0. as $elem_ty; $id::lanes()];
- v.write_to_slice_unaligned(&mut a);
- let tree_reduction = tree_reduce_sum(&a);
-
- // tolerate 1 ULP difference:
- let red_bits = simd_reduction.to_bits();
- let tree_bits = tree_reduction.to_bits();
- assert!(
- if red_bits > tree_bits {
- red_bits - tree_bits
- } else {
- tree_bits - red_bits
- } < 2,
- "vector: {:?} | simd_reduction: {:?} | \
-tree_reduction: {} | scalar_reduction: {}",
- v,
- simd_reduction,
- tree_reduction,
- scalar_reduction
- );
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[allow(unused, dead_code)]
- fn product_roundoff() {
- use ::core::convert::TryInto;
- // Performs a tree-reduction
- fn tree_reduce_product(a: &[$elem_ty]) -> $elem_ty {
- assert!(!a.is_empty());
- if a.len() == 1 {
- a[0]
- } else if a.len() == 2 {
- a[0] * a[1]
- } else {
- let mid = a.len() / 2;
- let (left, right) = a.split_at(mid);
- tree_reduce_product(left)
- * tree_reduce_product(right)
- }
- }
-
- let mut start = crate::$elem_ty::EPSILON;
- let mut scalar_reduction = 1. as $elem_ty;
-
- let mut v = $id::splat(0. as $elem_ty);
- for i in 0..$id::lanes() {
- let c = if i % 2 == 0 { 1e3 } else { -1. };
- start *= ::core::$elem_ty::consts::PI * c;
- scalar_reduction *= start;
- v = v.replace(i, start);
- }
- let simd_reduction = v.product();
-
- let mut a = [0. as $elem_ty; $id::lanes()];
- v.write_to_slice_unaligned(&mut a);
- let tree_reduction = tree_reduce_product(&a);
-
- // FIXME: Too imprecise, even only for product(f32x8).
- // Figure out how to narrow this down.
- let ulp_limit = $id::lanes() / 2;
- let red_bits = simd_reduction.to_bits();
- let tree_bits = tree_reduction.to_bits();
- assert!(
- if red_bits > tree_bits {
- red_bits - tree_bits
- } else {
- tree_bits - red_bits
- } < ulp_limit.try_into().unwrap(),
- "vector: {:?} | simd_reduction: {:?} | \
-tree_reduction: {} | scalar_reduction: {}",
- v,
- simd_reduction,
- tree_reduction,
- scalar_reduction
- );
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/reductions/integer_arithmetic.rs b/third_party/rust/packed_simd/src/api/reductions/integer_arithmetic.rs
deleted file mode 100644
index e99e6cb5d7..0000000000
--- a/third_party/rust/packed_simd/src/api/reductions/integer_arithmetic.rs
+++ /dev/null
@@ -1,193 +0,0 @@
-//! Implements portable horizontal integer vector arithmetic reductions.
-
-macro_rules! impl_reduction_integer_arithmetic {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $ielem_ty:ident
- | $test_tt:tt) => {
- impl $id {
- /// Horizontal wrapping sum of the vector elements.
- ///
- /// The intrinsic performs a tree-reduction of the vector elements.
- /// That is, for an 8 element vector:
- ///
- /// > ((x0 + x1) + (x2 + x3)) + ((x4 + x5) + (x6 + x7))
- ///
- /// If an operation overflows it returns the mathematical result
- /// modulo `2^n` where `n` is the number of times it overflows.
- #[inline]
- pub fn wrapping_sum(self) -> $elem_ty {
- #[cfg(not(target_arch = "aarch64"))]
- {
- use crate::llvm::simd_reduce_add_ordered;
- let v: $ielem_ty = unsafe { simd_reduce_add_ordered(self.0, 0 as $ielem_ty) };
- v as $elem_ty
- }
- #[cfg(target_arch = "aarch64")]
- {
- // FIXME: broken on AArch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- let mut x = self.extract(0) as $elem_ty;
- for i in 1..$id::lanes() {
- x = x.wrapping_add(self.extract(i) as $elem_ty);
- }
- x
- }
- }
-
- /// Horizontal wrapping product of the vector elements.
- ///
- /// The intrinsic performs a tree-reduction of the vector elements.
- /// That is, for an 8 element vector:
- ///
- /// > ((x0 * x1) * (x2 * x3)) * ((x4 * x5) * (x6 * x7))
- ///
- /// If an operation overflows it returns the mathematical result
- /// modulo `2^n` where `n` is the number of times it overflows.
- #[inline]
- pub fn wrapping_product(self) -> $elem_ty {
- #[cfg(not(target_arch = "aarch64"))]
- {
- use crate::llvm::simd_reduce_mul_ordered;
- let v: $ielem_ty = unsafe { simd_reduce_mul_ordered(self.0, 1 as $ielem_ty) };
- v as $elem_ty
- }
- #[cfg(target_arch = "aarch64")]
- {
- // FIXME: broken on AArch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- let mut x = self.extract(0) as $elem_ty;
- for i in 1..$id::lanes() {
- x = x.wrapping_mul(self.extract(i) as $elem_ty);
- }
- x
- }
- }
- }
-
- impl crate::iter::Sum for $id {
- #[inline]
- fn sum<I: Iterator<Item = $id>>(iter: I) -> $id {
- iter.fold($id::splat(0), crate::ops::Add::add)
- }
- }
-
- impl crate::iter::Product for $id {
- #[inline]
- fn product<I: Iterator<Item = $id>>(iter: I) -> $id {
- iter.fold($id::splat(1), crate::ops::Mul::mul)
- }
- }
-
- impl<'a> crate::iter::Sum<&'a $id> for $id {
- #[inline]
- fn sum<I: Iterator<Item = &'a $id>>(iter: I) -> $id {
- iter.fold($id::splat(0), |a, b| crate::ops::Add::add(a, *b))
- }
- }
-
- impl<'a> crate::iter::Product<&'a $id> for $id {
- #[inline]
- fn product<I: Iterator<Item = &'a $id>>(iter: I) -> $id {
- iter.fold($id::splat(1), |a, b| crate::ops::Mul::mul(a, *b))
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _reduction_int_arith>] {
- use super::*;
-
- fn alternating(x: usize) -> $id {
- let mut v = $id::splat(1 as $elem_ty);
- for i in 0..$id::lanes() {
- if i % x == 0 {
- v = v.replace(i, 2 as $elem_ty);
- }
- }
- v
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn wrapping_sum() {
- let v = $id::splat(0 as $elem_ty);
- assert_eq!(v.wrapping_sum(), 0 as $elem_ty);
- let v = $id::splat(1 as $elem_ty);
- assert_eq!(v.wrapping_sum(), $id::lanes() as $elem_ty);
- let v = alternating(2);
- if $id::lanes() > 1 {
- assert_eq!(
- v.wrapping_sum(),
- ($id::lanes() / 2 + $id::lanes()) as $elem_ty
- );
- } else {
- assert_eq!(
- v.wrapping_sum(),
- 2 as $elem_ty
- );
- }
- }
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn wrapping_sum_overflow() {
- let start = $elem_ty::max_value()
- - ($id::lanes() as $elem_ty / 2);
-
- let v = $id::splat(start as $elem_ty);
- let vwrapping_sum = v.wrapping_sum();
-
- let mut wrapping_sum = start;
- for _ in 1..$id::lanes() {
- wrapping_sum = wrapping_sum.wrapping_add(start);
- }
- assert_eq!(wrapping_sum, vwrapping_sum, "v = {:?}", v);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn wrapping_product() {
- let v = $id::splat(0 as $elem_ty);
- assert_eq!(v.wrapping_product(), 0 as $elem_ty);
- let v = $id::splat(1 as $elem_ty);
- assert_eq!(v.wrapping_product(), 1 as $elem_ty);
- let f = match $id::lanes() {
- 64 => 16,
- 32 => 8,
- 16 => 4,
- _ => 2,
- };
- let v = alternating(f);
- if $id::lanes() > 1 {
- assert_eq!(
- v.wrapping_product(),
- (2_usize.pow(($id::lanes() / f) as u32)
- as $elem_ty)
- );
- } else {
- assert_eq!(
- v.wrapping_product(),
- 2 as $elem_ty
- );
- }
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn wrapping_product_overflow() {
- let start = $elem_ty::max_value()
- - ($id::lanes() as $elem_ty / 2);
-
- let v = $id::splat(start as $elem_ty);
- let vmul = v.wrapping_product();
-
- let mut mul = start;
- for _ in 1..$id::lanes() {
- mul = mul.wrapping_mul(start);
- }
- assert_eq!(mul, vmul, "v = {:?}", v);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/reductions/mask.rs b/third_party/rust/packed_simd/src/api/reductions/mask.rs
deleted file mode 100644
index 0dd6a84e7e..0000000000
--- a/third_party/rust/packed_simd/src/api/reductions/mask.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-//! Implements portable horizontal mask reductions.
-
-macro_rules! impl_reduction_mask {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Are `all` vector lanes `true`?
- #[inline]
- pub fn all(self) -> bool {
- unsafe { crate::codegen::reductions::mask::All::all(self) }
- }
- /// Is `any` vector lane `true`?
- #[inline]
- pub fn any(self) -> bool {
- unsafe { crate::codegen::reductions::mask::Any::any(self) }
- }
- /// Are `all` vector lanes `false`?
- #[inline]
- pub fn none(self) -> bool {
- !self.any()
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _reduction>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn all() {
- let a = $id::splat(true);
- assert!(a.all());
- let a = $id::splat(false);
- assert!(!a.all());
-
- if $id::lanes() > 1 {
- for i in 0..$id::lanes() {
- let mut a = $id::splat(true);
- a = a.replace(i, false);
- assert!(!a.all());
- let mut a = $id::splat(false);
- a = a.replace(i, true);
- assert!(!a.all());
- }
- }
- }
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn any() {
- let a = $id::splat(true);
- assert!(a.any());
- let a = $id::splat(false);
- assert!(!a.any());
-
- if $id::lanes() > 1 {
- for i in 0..$id::lanes() {
- let mut a = $id::splat(true);
- a = a.replace(i, false);
- assert!(a.any());
- let mut a = $id::splat(false);
- a = a.replace(i, true);
- assert!(a.any());
- }
- }
- }
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn none() {
- let a = $id::splat(true);
- assert!(!a.none());
- let a = $id::splat(false);
- assert!(a.none());
-
- if $id::lanes() > 1 {
- for i in 0..$id::lanes() {
- let mut a = $id::splat(true);
- a = a.replace(i, false);
- assert!(!a.none());
- let mut a = $id::splat(false);
- a = a.replace(i, true);
- assert!(!a.none());
- }
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/reductions/min_max.rs b/third_party/rust/packed_simd/src/api/reductions/min_max.rs
deleted file mode 100644
index a3ce13a451..0000000000
--- a/third_party/rust/packed_simd/src/api/reductions/min_max.rs
+++ /dev/null
@@ -1,360 +0,0 @@
-//! Implements portable horizontal vector min/max reductions.
-
-macro_rules! impl_reduction_min_max {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident
- | $ielem_ty:ident | $test_tt:tt) => {
- impl $id {
- /// Largest vector element value.
- #[inline]
- pub fn max_element(self) -> $elem_ty {
- #[cfg(not(any(
- target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "powerpc64",
- target_arch = "wasm32",
- )))]
- {
- use crate::llvm::simd_reduce_max;
- let v: $ielem_ty = unsafe { simd_reduce_max(self.0) };
- v as $elem_ty
- }
- #[cfg(any(
- target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "powerpc64",
- target_arch = "wasm32",
- ))]
- {
- // FIXME: broken on AArch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- // FIXME: broken on WASM32
- // https://github.com/rust-lang-nursery/packed_simd/issues/91
- let mut x = self.extract(0);
- for i in 1..$id::lanes() {
- x = x.max(self.extract(i));
- }
- x
- }
- }
-
- /// Smallest vector element value.
- #[inline]
- pub fn min_element(self) -> $elem_ty {
- #[cfg(not(any(
- target_arch = "aarch64",
- target_arch = "arm",
- all(target_arch = "x86", not(target_feature = "sse2")),
- target_arch = "powerpc64",
- target_arch = "wasm32",
- ),))]
- {
- use crate::llvm::simd_reduce_min;
- let v: $ielem_ty = unsafe { simd_reduce_min(self.0) };
- v as $elem_ty
- }
- #[cfg(any(
- target_arch = "aarch64",
- target_arch = "arm",
- all(target_arch = "x86", not(target_feature = "sse2")),
- target_arch = "powerpc64",
- target_arch = "wasm32",
- ))]
- {
- // FIXME: broken on AArch64
- // https://github.com/rust-lang-nursery/packed_simd/issues/15
- // FIXME: broken on i586-unknown-linux-gnu
- // https://github.com/rust-lang-nursery/packed_simd/issues/22
- // FIXME: broken on WASM32
- // https://github.com/rust-lang-nursery/packed_simd/issues/91
- let mut x = self.extract(0);
- for i in 1..$id::lanes() {
- x = x.min(self.extract(i));
- }
- x
- }
- }
- }
- test_if! {$test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- pub mod [<$id _reduction_min_max>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- pub fn max_element() {
- let v = $id::splat(0 as $elem_ty);
- assert_eq!(v.max_element(), 0 as $elem_ty);
- if $id::lanes() > 1 {
- let v = v.replace(1, 1 as $elem_ty);
- assert_eq!(v.max_element(), 1 as $elem_ty);
- }
- let v = v.replace(0, 2 as $elem_ty);
- assert_eq!(v.max_element(), 2 as $elem_ty);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- pub fn min_element() {
- let v = $id::splat(0 as $elem_ty);
- assert_eq!(v.min_element(), 0 as $elem_ty);
- if $id::lanes() > 1 {
- let v = v.replace(1, 1 as $elem_ty);
- assert_eq!(v.min_element(), 0 as $elem_ty);
- }
- let v = $id::splat(1 as $elem_ty);
- let v = v.replace(0, 2 as $elem_ty);
- if $id::lanes() > 1 {
- assert_eq!(v.min_element(), 1 as $elem_ty);
- } else {
- assert_eq!(v.min_element(), 2 as $elem_ty);
- }
- if $id::lanes() > 1 {
- let v = $id::splat(2 as $elem_ty);
- let v = v.replace(1, 1 as $elem_ty);
- assert_eq!(v.min_element(), 1 as $elem_ty);
- }
- }
- }
- }
- }
- };
-}
-
-macro_rules! test_reduction_float_min_max {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- test_if! {
- $test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- pub mod [<$id _reduction_min_max_nan>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn min_element_test() {
- let n = crate::$elem_ty::NAN;
-
- assert_eq!(n.min(-3.), -3.);
- assert_eq!((-3. as $elem_ty).min(n), -3.);
-
- let v0 = $id::splat(-3.);
-
- let target_with_broken_last_lane_nan = !cfg!(any(
- target_arch = "arm", target_arch = "aarch64",
- all(target_arch = "x86",
- not(target_feature = "sse2")
- ),
- target_arch = "powerpc64",
- target_arch = "wasm32",
- ));
-
- // The vector is initialized to `-3.`s: [-3, -3, -3, -3]
- for i in 0..$id::lanes() {
- // We replace the i-th element of the vector with
- // `NaN`: [-3, -3, -3, NaN]
- let mut v = v0.replace(i, n);
-
- // If the NaN is in the last place, the LLVM
- // implementation of these methods is broken on some
- // targets:
- if i == $id::lanes() - 1 &&
- target_with_broken_last_lane_nan {
- assert_eq!(v.min_element(), -3.,
- "[A]: nan at {} => {} | {:?}",
- i, v.min_element(), v);
-
- // If we replace all the elements in the vector
- // up-to the `i-th` lane with `NaN`s, the result
- // is still always `-3.` unless all elements of
- // the vector are `NaN`s:
- for j in 0..i {
- v = v.replace(j, n);
- if j == i-1 {
- assert!(v.min_element().is_nan(),
- "[B]: nan at {} => {} | {:?}",
- i, v.min_element(), v);
- } else {
- assert_eq!(v.min_element(), -3.,
- "[B]: nan at {} => {} | {:?}",
- i, v.min_element(), v);
- }
- }
-
- // We are done here, since we were in the last
- // lane which is the last iteration of the loop.
- break
- }
-
- // We are not in the last lane, and there is only
- // one `NaN` in the vector.
-
- // If the vector has one lane, the result is `NaN`:
- if $id::lanes() == 1 {
- assert!(v.min_element().is_nan(),
- "[C]: all nans | v={:?} | min={} | \
-is_nan: {}",
- v, v.min_element(),
- v.min_element().is_nan()
- );
-
- // And we are done, since the vector only has
- // one lane anyways.
- break;
- }
-
- // The vector has more than one lane, since there is
- // only one `NaN` in the vector, the result is
- // always `-3`.
- assert_eq!(v.min_element(), -3.,
- "[D]: nan at {} => {} | {:?}",
- i, v.min_element(), v);
-
- // If we replace all the elements in the vector
- // up-to the `i-th` lane with `NaN`s, the result is
- // still always `-3.` unless all elements of the
- // vector are `NaN`s:
- for j in 0..i {
- v = v.replace(j, n);
-
- if i == $id::lanes() - 1 && j == i - 1 {
- // All elements of the vector are `NaN`s,
- // therefore the result is NaN as well.
- //
- // Note: the #lanes of the vector is > 1, so
- // "i - 1" does not overflow.
- assert!(v.min_element().is_nan(),
- "[E]: all nans | v={:?} | min={} | \
-is_nan: {}",
- v, v.min_element(),
- v.min_element().is_nan());
- } else {
- // There are non-`NaN` elements in the
- // vector, therefore the result is `-3.`:
- assert_eq!(v.min_element(), -3.,
- "[F]: nan at {} => {} | {:?}",
- i, v.min_element(), v);
- }
- }
- }
-
- // If the vector contains all NaNs the result is NaN:
- assert!($id::splat(n).min_element().is_nan(),
- "all nans | v={:?} | min={} | is_nan: {}",
- $id::splat(n), $id::splat(n).min_element(),
- $id::splat(n).min_element().is_nan());
- }
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn max_element_test() {
- let n = crate::$elem_ty::NAN;
-
- assert_eq!(n.max(-3.), -3.);
- assert_eq!((-3. as $elem_ty).max(n), -3.);
-
- let v0 = $id::splat(-3.);
-
- let target_with_broken_last_lane_nan = !cfg!(any(
- target_arch = "arm", target_arch = "aarch64",
- target_arch = "powerpc64", target_arch = "wasm32",
- ));
-
- // The vector is initialized to `-3.`s: [-3, -3, -3, -3]
- for i in 0..$id::lanes() {
- // We replace the i-th element of the vector with
- // `NaN`: [-3, -3, -3, NaN]
- let mut v = v0.replace(i, n);
-
- // If the NaN is in the last place, the LLVM
- // implementation of these methods is broken on some
- // targets:
- if i == $id::lanes() - 1 &&
- target_with_broken_last_lane_nan {
- assert_eq!(v.max_element(), -3.,
- "[A]: nan at {} => {} | {:?}",
- i, v.max_element(), v);
-
- // If we replace all the elements in the vector
- // up-to the `i-th` lane with `NaN`s, the result
- // is still always `-3.` unless all elements of
- // the vector are `NaN`s:
- for j in 0..i {
- v = v.replace(j, n);
- if j == i-1 {
- assert!(v.min_element().is_nan(),
- "[B]: nan at {} => {} | {:?}",
- i, v.min_element(), v);
- } else {
- assert_eq!(v.max_element(), -3.,
- "[B]: nan at {} => {} | {:?}",
- i, v.max_element(), v);
- }
- }
-
- // We are done here, since we were in the last
- // lane which is the last iteration of the loop.
- break
- }
-
- // We are not in the last lane, and there is only
- // one `NaN` in the vector.
-
- // If the vector has one lane, the result is `NaN`:
- if $id::lanes() == 1 {
- assert!(v.max_element().is_nan(),
- "[C]: all nans | v={:?} | min={} | \
-is_nan: {}",
- v, v.max_element(),
- v.max_element().is_nan());
-
- // And we are done, since the vector only has
- // one lane anyways.
- break;
- }
-
- // The vector has more than one lane, since there is
- // only one `NaN` in the vector, the result is
- // always `-3`.
- assert_eq!(v.max_element(), -3.,
- "[D]: nan at {} => {} | {:?}",
- i, v.max_element(), v);
-
- // If we replace all the elements in the vector
- // up-to the `i-th` lane with `NaN`s, the result is
- // still always `-3.` unless all elements of the
- // vector are `NaN`s:
- for j in 0..i {
- v = v.replace(j, n);
-
- if i == $id::lanes() - 1 && j == i - 1 {
- // All elements of the vector are `NaN`s,
- // therefore the result is NaN as well.
- //
- // Note: the #lanes of the vector is > 1, so
- // "i - 1" does not overflow.
- assert!(v.max_element().is_nan(),
- "[E]: all nans | v={:?} | max={} | \
-is_nan: {}",
- v, v.max_element(),
- v.max_element().is_nan());
- } else {
- // There are non-`NaN` elements in the
- // vector, therefore the result is `-3.`:
- assert_eq!(v.max_element(), -3.,
- "[F]: nan at {} => {} | {:?}",
- i, v.max_element(), v);
- }
- }
- }
-
- // If the vector contains all NaNs the result is NaN:
- assert!($id::splat(n).max_element().is_nan(),
- "all nans | v={:?} | max={} | is_nan: {}",
- $id::splat(n), $id::splat(n).max_element(),
- $id::splat(n).max_element().is_nan());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/select.rs b/third_party/rust/packed_simd/src/api/select.rs
deleted file mode 100644
index daf6294721..0000000000
--- a/third_party/rust/packed_simd/src/api/select.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-//! Implements mask's `select`.
-
-/// Implements mask select method
-macro_rules! impl_select {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Selects elements of `a` and `b` using mask.
- ///
- /// The lanes of the result for which the mask is `true` contain
- /// the values of `a`. The remaining lanes contain the values of
- /// `b`.
- #[inline]
- pub fn select<T>(self, a: Simd<T>, b: Simd<T>) -> Simd<T>
- where
- T: sealed::SimdArray<NT = <[$elem_ty; $elem_count] as sealed::SimdArray>::NT>,
- {
- use crate::llvm::simd_select;
- Simd(unsafe { simd_select(self.0, a.0, b.0) })
- }
- }
-
- test_select!(bool, $id, $id, (false, true) | $test_tt);
- };
-}
-
-macro_rules! test_select {
- (
- $elem_ty:ident,
- $mask_ty:ident,
- $vec_ty:ident,($small:expr, $large:expr) |
- $test_tt:tt
- ) => {
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$vec_ty _select>] {
- use super::*;
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn select() {
- let o = $small as $elem_ty;
- let t = $large as $elem_ty;
-
- let a = $vec_ty::splat(o);
- let b = $vec_ty::splat(t);
- let m = a.lt(b);
- assert_eq!(m.select(a, b), a);
-
- let m = b.lt(a);
- assert_eq!(m.select(b, a), a);
-
- let mut c = a;
- let mut d = b;
- let mut m_e = $mask_ty::splat(false);
- for i in 0..$vec_ty::lanes() {
- if i % 2 == 0 {
- let c_tmp = c.extract(i);
- c = c.replace(i, d.extract(i));
- d = d.replace(i, c_tmp);
- } else {
- m_e = m_e.replace(i, true);
- }
- }
-
- let m = c.lt(d);
- assert_eq!(m_e, m);
- assert_eq!(m.select(c, d), a);
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/shuffle.rs b/third_party/rust/packed_simd/src/api/shuffle.rs
deleted file mode 100644
index 1c17bd766e..0000000000
--- a/third_party/rust/packed_simd/src/api/shuffle.rs
+++ /dev/null
@@ -1,184 +0,0 @@
-//! Implements portable vector shuffles with immediate indices.
-
-// FIXME: comprehensive tests
-// https://github.com/rust-lang-nursery/packed_simd/issues/20
-
-/// Shuffles vector elements.
-///
-/// This macro returns a new vector that contains a shuffle of the elements in
-/// one (`shuffle!(vec, [indices...])`) or two (`shuffle!(vec0, vec1,
-/// [indices...])`) input vectors.
-///
-/// The type of `vec0` and `vec1` must be equal, and the element type of the
-/// resulting vector is the element type of the input vector.
-///
-/// The number of `indices` must be a power-of-two in range `[0, 64)`, since
-/// currently, the largest vector supported by the library has 64 lanes. The
-/// length of the resulting vector equals the number of indices provided.
-///
-/// The indices must be in range `[0, M * N)` where `M` is the number of input
-/// vectors (`1` or `2`) and `N` is the number of lanes of the input vectors.
-/// The indices `i` in range `[0, N)` refer to the `i`-th element of `vec0`,
-/// while the indices in range `[N, 2*N)` refer to the `i - N`-th element of
-/// `vec1`.
-///
-/// # Examples
-///
-/// Shuffling elements of two vectors:
-///
-/// ```
-/// # use packed_simd::*;
-/// # fn main() {
-/// // Shuffle allows reordering the elements:
-/// let x = i32x4::new(1, 2, 3, 4);
-/// let y = i32x4::new(5, 6, 7, 8);
-/// let r = shuffle!(x, y, [4, 0, 5, 1]);
-/// assert_eq!(r, i32x4::new(5, 1, 6, 2));
-///
-/// // The resulting vector can als be smaller than the input:
-/// let r = shuffle!(x, y, [1, 6]);
-/// assert_eq!(r, i32x2::new(2, 7));
-///
-/// // Or larger:
-/// let r = shuffle!(x, y, [1, 3, 4, 2, 1, 7, 2, 2]);
-/// assert_eq!(r, i32x8::new(2, 4, 5, 3, 2, 8, 3, 3));
-/// // At most 2 * the number of lanes in the input vector.
-/// # }
-/// ```
-///
-/// Shuffling elements of one vector:
-///
-/// ```
-/// # use packed_simd::*;
-/// # fn main() {
-/// // Shuffle allows reordering the elements of a vector:
-/// let x = i32x4::new(1, 2, 3, 4);
-/// let r = shuffle!(x, [2, 1, 3, 0]);
-/// assert_eq!(r, i32x4::new(3, 2, 4, 1));
-///
-/// // The resulting vector can be smaller than the input:
-/// let r = shuffle!(x, [1, 3]);
-/// assert_eq!(r, i32x2::new(2, 4));
-///
-/// // Equal:
-/// let r = shuffle!(x, [1, 3, 2, 0]);
-/// assert_eq!(r, i32x4::new(2, 4, 3, 1));
-///
-/// // Or larger:
-/// let r = shuffle!(x, [1, 3, 2, 2, 1, 3, 2, 2]);
-/// assert_eq!(r, i32x8::new(2, 4, 3, 3, 2, 4, 3, 3));
-/// // At most 2 * the number of lanes in the input vector.
-/// # }
-/// ```
-#[macro_export]
-macro_rules! shuffle {
- ($vec0:expr, $vec1:expr, [$l0:expr, $l1:expr]) => {{
- #[allow(unused_unsafe)]
- unsafe {
- $crate::Simd($crate::__shuffle_vector2::<{[$l0, $l1]}, _, _>(
- $vec0.0,
- $vec1.0,
- ))
- }
- }};
- ($vec0:expr, $vec1:expr, [$l0:expr, $l1:expr, $l2:expr, $l3:expr]) => {{
- #[allow(unused_unsafe)]
- unsafe {
- $crate::Simd($crate::__shuffle_vector4::<{[$l0, $l1, $l2, $l3]}, _, _>(
- $vec0.0,
- $vec1.0,
- ))
- }
- }};
- ($vec0:expr, $vec1:expr,
- [$l0:expr, $l1:expr, $l2:expr, $l3:expr,
- $l4:expr, $l5:expr, $l6:expr, $l7:expr]) => {{
- #[allow(unused_unsafe)]
- unsafe {
- $crate::Simd($crate::__shuffle_vector8::<{[$l0, $l1, $l2, $l3, $l4, $l5, $l6, $l7]}, _, _>(
- $vec0.0,
- $vec1.0,
- ))
- }
- }};
- ($vec0:expr, $vec1:expr,
- [$l0:expr, $l1:expr, $l2:expr, $l3:expr,
- $l4:expr, $l5:expr, $l6:expr, $l7:expr,
- $l8:expr, $l9:expr, $l10:expr, $l11:expr,
- $l12:expr, $l13:expr, $l14:expr, $l15:expr]) => {{
- #[allow(unused_unsafe)]
- unsafe {
- $crate::Simd($crate::__shuffle_vector16::<{
- [
- $l0, $l1, $l2, $l3, $l4, $l5, $l6, $l7, $l8, $l9, $l10,
- $l11, $l12, $l13, $l14, $l15,
- ]
- }, _, _>(
- $vec0.0,
- $vec1.0,
- ))
- }
- }};
- ($vec0:expr, $vec1:expr,
- [$l0:expr, $l1:expr, $l2:expr, $l3:expr,
- $l4:expr, $l5:expr, $l6:expr, $l7:expr,
- $l8:expr, $l9:expr, $l10:expr, $l11:expr,
- $l12:expr, $l13:expr, $l14:expr, $l15:expr,
- $l16:expr, $l17:expr, $l18:expr, $l19:expr,
- $l20:expr, $l21:expr, $l22:expr, $l23:expr,
- $l24:expr, $l25:expr, $l26:expr, $l27:expr,
- $l28:expr, $l29:expr, $l30:expr, $l31:expr]) => {{
- #[allow(unused_unsafe)]
- unsafe {
- $crate::Simd($crate::__shuffle_vector32::<{
- [
- $l0, $l1, $l2, $l3, $l4, $l5, $l6, $l7, $l8, $l9, $l10,
- $l11, $l12, $l13, $l14, $l15, $l16, $l17, $l18, $l19,
- $l20, $l21, $l22, $l23, $l24, $l25, $l26, $l27, $l28,
- $l29, $l30, $l31,
- ]
- }, _, _>(
- $vec0.0,
- $vec1.0,
- ))
- }
- }};
- ($vec0:expr, $vec1:expr,
- [$l0:expr, $l1:expr, $l2:expr, $l3:expr,
- $l4:expr, $l5:expr, $l6:expr, $l7:expr,
- $l8:expr, $l9:expr, $l10:expr, $l11:expr,
- $l12:expr, $l13:expr, $l14:expr, $l15:expr,
- $l16:expr, $l17:expr, $l18:expr, $l19:expr,
- $l20:expr, $l21:expr, $l22:expr, $l23:expr,
- $l24:expr, $l25:expr, $l26:expr, $l27:expr,
- $l28:expr, $l29:expr, $l30:expr, $l31:expr,
- $l32:expr, $l33:expr, $l34:expr, $l35:expr,
- $l36:expr, $l37:expr, $l38:expr, $l39:expr,
- $l40:expr, $l41:expr, $l42:expr, $l43:expr,
- $l44:expr, $l45:expr, $l46:expr, $l47:expr,
- $l48:expr, $l49:expr, $l50:expr, $l51:expr,
- $l52:expr, $l53:expr, $l54:expr, $l55:expr,
- $l56:expr, $l57:expr, $l58:expr, $l59:expr,
- $l60:expr, $l61:expr, $l62:expr, $l63:expr]) => {{
- #[allow(unused_unsafe)]
- unsafe {
- $crate::Simd($crate::__shuffle_vector64::<{[
- $l0, $l1, $l2, $l3, $l4, $l5, $l6, $l7, $l8, $l9, $l10,
- $l11, $l12, $l13, $l14, $l15, $l16, $l17, $l18, $l19,
- $l20, $l21, $l22, $l23, $l24, $l25, $l26, $l27, $l28,
- $l29, $l30, $l31, $l32, $l33, $l34, $l35, $l36, $l37,
- $l38, $l39, $l40, $l41, $l42, $l43, $l44, $l45, $l46,
- $l47, $l48, $l49, $l50, $l51, $l52, $l53, $l54, $l55,
- $l56, $l57, $l58, $l59, $l60, $l61, $l62, $l63,
- ]}, _, _>(
- $vec0.0,
- $vec1.0,
- ))
- }
- }};
- ($vec:expr, [$($l:expr),*]) => {
- match $vec {
- v => shuffle!(v, v, [$($l),*])
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/shuffle1_dyn.rs b/third_party/rust/packed_simd/src/api/shuffle1_dyn.rs
deleted file mode 100644
index 64536be6cb..0000000000
--- a/third_party/rust/packed_simd/src/api/shuffle1_dyn.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-//! Shuffle vector elements according to a dynamic vector of indices.
-
-macro_rules! impl_shuffle1_dyn {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Shuffle vector elements according to `indices`.
- #[inline]
- pub fn shuffle1_dyn<I>(self, indices: I) -> Self
- where
- Self: codegen::shuffle1_dyn::Shuffle1Dyn<Indices = I>,
- {
- codegen::shuffle1_dyn::Shuffle1Dyn::shuffle1_dyn(self, indices)
- }
- }
- };
-}
-
-macro_rules! test_shuffle1_dyn {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _shuffle1_dyn>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn shuffle1_dyn() {
- let increasing = {
- let mut v = $id::splat(0 as $elem_ty);
- for i in 0..$id::lanes() {
- v = v.replace(i, i as $elem_ty);
- }
- v
- };
- let decreasing = {
- let mut v = $id::splat(0 as $elem_ty);
- for i in 0..$id::lanes() {
- v = v.replace(
- i,
- ($id::lanes() - 1 - i) as $elem_ty
- );
- }
- v
- };
-
- type Indices = <
- $id as codegen::shuffle1_dyn::Shuffle1Dyn
- >::Indices;
- let increasing_ids: Indices = increasing.cast();
- let decreasing_ids: Indices = decreasing.cast();
-
- assert_eq!(
- increasing.shuffle1_dyn(increasing_ids),
- increasing,
- "(i,i)=>i"
- );
- assert_eq!(
- decreasing.shuffle1_dyn(increasing_ids),
- decreasing,
- "(d,i)=>d"
- );
- assert_eq!(
- increasing.shuffle1_dyn(decreasing_ids),
- decreasing,
- "(i,d)=>d"
- );
- assert_eq!(
- decreasing.shuffle1_dyn(decreasing_ids),
- increasing,
- "(d,d)=>i"
- );
-
- for i in 0..$id::lanes() {
- let v_ids: Indices
- = $id::splat(i as $elem_ty).cast();
- assert_eq!(increasing.shuffle1_dyn(v_ids),
- $id::splat(increasing.extract(i))
- );
- assert_eq!(decreasing.shuffle1_dyn(v_ids),
- $id::splat(decreasing.extract(i))
- );
- assert_eq!(
- $id::splat(i as $elem_ty)
- .shuffle1_dyn(increasing_ids),
- $id::splat(i as $elem_ty)
- );
- assert_eq!(
- $id::splat(i as $elem_ty)
- .shuffle1_dyn(decreasing_ids),
- $id::splat(i as $elem_ty)
- );
- }
- }
- }
- }
- }
- };
-}
-
-macro_rules! test_shuffle1_dyn_mask {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _shuffle1_dyn>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn shuffle1_dyn() {
- // alternating = [true, false, true, false, ...]
- let mut alternating = $id::splat(false);
- for i in 0..$id::lanes() {
- if i % 2 == 0 {
- alternating = alternating.replace(i, true);
- }
- }
-
- type Indices = <
- $id as codegen::shuffle1_dyn::Shuffle1Dyn
- >::Indices;
- // even = [0, 0, 2, 2, 4, 4, ..]
- let even = {
- let mut v = Indices::splat(0);
- for i in 0..$id::lanes() {
- if i % 2 == 0 {
- v = v.replace(i, (i as u8).into());
- } else {
- v = v.replace(i, (i as u8 - 1).into());
- }
- }
- v
- };
- // odd = [1, 1, 3, 3, 5, 5, ...]
- let odd = {
- let mut v = Indices::splat(0);
- for i in 0..$id::lanes() {
- if i % 2 != 0 {
- v = v.replace(i, (i as u8).into());
- } else {
- v = v.replace(i, (i as u8 + 1).into());
- }
- }
- v
- };
-
- assert_eq!(
- alternating.shuffle1_dyn(even),
- $id::splat(true)
- );
- if $id::lanes() > 1 {
- assert_eq!(
- alternating.shuffle1_dyn(odd),
- $id::splat(false)
- );
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/slice.rs b/third_party/rust/packed_simd/src/api/slice.rs
deleted file mode 100644
index 526b848b5c..0000000000
--- a/third_party/rust/packed_simd/src/api/slice.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//! Slice from/to methods
-
-#[macro_use]
-mod from_slice;
-
-#[macro_use]
-mod write_to_slice;
diff --git a/third_party/rust/packed_simd/src/api/slice/from_slice.rs b/third_party/rust/packed_simd/src/api/slice/from_slice.rs
deleted file mode 100644
index cafd6f8213..0000000000
--- a/third_party/rust/packed_simd/src/api/slice/from_slice.rs
+++ /dev/null
@@ -1,202 +0,0 @@
-//! Implements methods to read a vector type from a slice.
-
-macro_rules! impl_slice_from_slice {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned
- /// to an `align_of::<Self>()` boundary.
- #[inline]
- pub fn from_slice_aligned(slice: &[$elem_ty]) -> Self {
- unsafe {
- assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_ptr();
- assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
- Self::from_slice_aligned_unchecked(slice)
- }
- }
-
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()`.
- #[inline]
- pub fn from_slice_unaligned(slice: &[$elem_ty]) -> Self {
- unsafe {
- assert!(slice.len() >= $elem_count);
- Self::from_slice_unaligned_unchecked(slice)
- }
- }
-
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned
- /// to an `align_of::<Self>()` boundary, the behavior is undefined.
- #[inline]
- pub unsafe fn from_slice_aligned_unchecked(slice: &[$elem_ty]) -> Self {
- debug_assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_ptr();
- debug_assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
-
- #[allow(clippy::cast_ptr_alignment)]
- *(target_ptr as *const Self)
- }
-
- /// Instantiates a new vector with the values of the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` the behavior is undefined.
- #[inline]
- pub unsafe fn from_slice_unaligned_unchecked(slice: &[$elem_ty]) -> Self {
- use crate::mem::size_of;
- debug_assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_ptr().cast();
- let mut x = Self::splat(0 as $elem_ty);
- let self_ptr = &mut x as *mut Self as *mut u8;
- crate::ptr::copy_nonoverlapping(target_ptr, self_ptr, size_of::<Self>());
- x
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- pub mod [<$id _slice_from_slice>] {
- use super::*;
- use crate::iter::Iterator;
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn from_slice_unaligned() {
- let mut unaligned = [42 as $elem_ty; $id::lanes() + 1];
- unaligned[0] = 0 as $elem_ty;
- let vec = $id::from_slice_unaligned(&unaligned[1..]);
- for (index, &b) in unaligned.iter().enumerate() {
- if index == 0 {
- assert_eq!(b, 0 as $elem_ty);
- } else {
- assert_eq!(b, 42 as $elem_ty);
- assert_eq!(b, vec.extract(index - 1));
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn from_slice_unaligned_fail() {
- let mut unaligned = [42 as $elem_ty; $id::lanes() + 1];
- unaligned[0] = 0 as $elem_ty;
- // the slice is not large enough => panic
- let _vec = $id::from_slice_unaligned(&unaligned[2..]);
- }
-
- union A {
- data: [$elem_ty; 2 * $id::lanes()],
- _vec: $id,
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn from_slice_aligned() {
- let mut aligned = A {
- data: [0 as $elem_ty; 2 * $id::lanes()],
- };
- for i in $id::lanes()..(2 * $id::lanes()) {
- unsafe {
- aligned.data[i] = 42 as $elem_ty;
- }
- }
-
- let vec = unsafe {
- $id::from_slice_aligned(
- &aligned.data[$id::lanes()..]
- )
- };
- for (index, &b) in
- unsafe { aligned.data.iter().enumerate() } {
- if index < $id::lanes() {
- assert_eq!(b, 0 as $elem_ty);
- } else {
- assert_eq!(b, 42 as $elem_ty);
- assert_eq!(
- b, vec.extract(index - $id::lanes())
- );
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn from_slice_aligned_fail_lanes() {
- let aligned = A {
- data: [0 as $elem_ty; 2 * $id::lanes()],
- };
- let _vec = unsafe {
- $id::from_slice_aligned(
- &aligned.data[2 * $id::lanes()..]
- )
- };
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn from_slice_aligned_fail_align() {
- unsafe {
- let aligned = A {
- data: [0 as $elem_ty; 2 * $id::lanes()],
- };
-
- // get a pointer to the front of data
- let ptr: *const $elem_ty = aligned.data.as_ptr()
- as *const $elem_ty;
- // offset pointer by one element
- let ptr = ptr.wrapping_add(1);
-
- if ptr.align_offset(
- crate::mem::align_of::<$id>()
- ) == 0 {
- // the pointer is properly aligned, so
- // from_slice_aligned won't fail here (e.g. this
- // can happen for i128x1). So we panic to make
- // the "should_fail" test pass:
- panic!("ok");
- }
-
- // create a slice - this is safe, because the
- // elements of the slice exist, are properly
- // initialized, and properly aligned:
- let s: &[$elem_ty] = slice::from_raw_parts(
- ptr, $id::lanes()
- );
- // this should always panic because the slice
- // alignment does not match the alignment
- // requirements for the vector type:
- let _vec = $id::from_slice_aligned(s);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/slice/write_to_slice.rs b/third_party/rust/packed_simd/src/api/slice/write_to_slice.rs
deleted file mode 100644
index 5abd4916e0..0000000000
--- a/third_party/rust/packed_simd/src/api/slice/write_to_slice.rs
+++ /dev/null
@@ -1,196 +0,0 @@
-//! Implements methods to write a vector type to a slice.
-
-macro_rules! impl_slice_write_to_slice {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not
- /// aligned to an `align_of::<Self>()` boundary.
- #[inline]
- pub fn write_to_slice_aligned(self, slice: &mut [$elem_ty]) {
- unsafe {
- assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_mut_ptr();
- assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
- self.write_to_slice_aligned_unchecked(slice);
- }
- }
-
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Panics
- ///
- /// If `slice.len() < Self::lanes()`.
- #[inline]
- pub fn write_to_slice_unaligned(self, slice: &mut [$elem_ty]) {
- unsafe {
- assert!(slice.len() >= $elem_count);
- self.write_to_slice_unaligned_unchecked(slice);
- }
- }
-
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` or `&slice[0]` is not
- /// aligned to an `align_of::<Self>()` boundary, the behavior is
- /// undefined.
- #[inline]
- pub unsafe fn write_to_slice_aligned_unchecked(self, slice: &mut [$elem_ty]) {
- debug_assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_mut_ptr();
- debug_assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
-
- #[allow(clippy::cast_ptr_alignment)]
- #[allow(clippy::cast_ptr_alignment)]
- #[allow(clippy::cast_ptr_alignment)]
- #[allow(clippy::cast_ptr_alignment)]
- *(target_ptr as *mut Self) = self;
- }
-
- /// Writes the values of the vector to the `slice`.
- ///
- /// # Safety
- ///
- /// If `slice.len() < Self::lanes()` the behavior is undefined.
- #[inline]
- pub unsafe fn write_to_slice_unaligned_unchecked(self, slice: &mut [$elem_ty]) {
- debug_assert!(slice.len() >= $elem_count);
- let target_ptr = slice.as_mut_ptr().cast();
- let self_ptr = &self as *const Self as *const u8;
- crate::ptr::copy_nonoverlapping(self_ptr, target_ptr, crate::mem::size_of::<Self>());
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- // Comparisons use integer casts within mantissa^1 range.
- #[allow(clippy::float_cmp)]
- pub mod [<$id _slice_write_to_slice>] {
- use super::*;
- use crate::iter::Iterator;
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn write_to_slice_unaligned() {
- let mut unaligned = [0 as $elem_ty; $id::lanes() + 1];
- let vec = $id::splat(42 as $elem_ty);
- vec.write_to_slice_unaligned(&mut unaligned[1..]);
- for (index, &b) in unaligned.iter().enumerate() {
- if index == 0 {
- assert_eq!(b, 0 as $elem_ty);
- } else {
- assert_eq!(b, 42 as $elem_ty);
- assert_eq!(b, vec.extract(index - 1));
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn write_to_slice_unaligned_fail() {
- let mut unaligned = [0 as $elem_ty; $id::lanes() + 1];
- let vec = $id::splat(42 as $elem_ty);
- vec.write_to_slice_unaligned(&mut unaligned[2..]);
- }
-
- union A {
- data: [$elem_ty; 2 * $id::lanes()],
- _vec: $id,
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)]
- #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn write_to_slice_aligned() {
- let mut aligned = A {
- data: [0 as $elem_ty; 2 * $id::lanes()],
- };
- let vec = $id::splat(42 as $elem_ty);
- unsafe {
- vec.write_to_slice_aligned(
- &mut aligned.data[$id::lanes()..]
- );
- for (idx, &b) in aligned.data.iter().enumerate() {
- if idx < $id::lanes() {
- assert_eq!(b, 0 as $elem_ty);
- } else {
- assert_eq!(b, 42 as $elem_ty);
- assert_eq!(
- b, vec.extract(idx - $id::lanes())
- );
- }
- }
- }
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn write_to_slice_aligned_fail_lanes() {
- let mut aligned = A {
- data: [0 as $elem_ty; 2 * $id::lanes()],
- };
- let vec = $id::splat(42 as $elem_ty);
- unsafe {
- vec.write_to_slice_aligned(
- &mut aligned.data[2 * $id::lanes()..]
- )
- };
- }
-
- // FIXME: wasm-bindgen-test does not support #[should_panic]
- // #[cfg_attr(not(target_arch = "wasm32"), test)]
- // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- #[cfg(not(target_arch = "wasm32"))]
- #[test]
- #[should_panic]
- fn write_to_slice_aligned_fail_align() {
- unsafe {
- let mut aligned = A {
- data: [0 as $elem_ty; 2 * $id::lanes()],
- };
-
- // get a pointer to the front of data
- let ptr: *mut $elem_ty
- = aligned.data.as_mut_ptr() as *mut $elem_ty;
- // offset pointer by one element
- let ptr = ptr.wrapping_add(1);
-
- if ptr.align_offset(crate::mem::align_of::<$id>())
- == 0 {
- // the pointer is properly aligned, so
- // write_to_slice_aligned won't fail here (e.g.
- // this can happen for i128x1). So we panic to
- // make the "should_fail" test pass:
- panic!("ok");
- }
-
- // create a slice - this is safe, because the
- // elements of the slice exist, are properly
- // initialized, and properly aligned:
- let s: &mut [$elem_ty]
- = slice::from_raw_parts_mut(ptr, $id::lanes());
- // this should always panic because the slice
- // alignment does not match the alignment
- // requirements for the vector type:
- let vec = $id::splat(42 as $elem_ty);
- vec.write_to_slice_aligned(s);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/api/swap_bytes.rs b/third_party/rust/packed_simd/src/api/swap_bytes.rs
deleted file mode 100644
index 4649ed679b..0000000000
--- a/third_party/rust/packed_simd/src/api/swap_bytes.rs
+++ /dev/null
@@ -1,192 +0,0 @@
-//! Horizontal swap bytes
-
-macro_rules! impl_swap_bytes {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Reverses the byte order of the vector.
- #[inline]
- pub fn swap_bytes(self) -> Self {
- super::codegen::swap_bytes::SwapBytes::swap_bytes(self)
- }
-
- /// Converts self to little endian from the target's endianness.
- ///
- /// On little endian this is a no-op. On big endian the bytes are
- /// swapped.
- #[inline]
- pub fn to_le(self) -> Self {
- #[cfg(target_endian = "little")]
- {
- self
- }
- #[cfg(not(target_endian = "little"))]
- {
- self.swap_bytes()
- }
- }
-
- /// Converts self to big endian from the target's endianness.
- ///
- /// On big endian this is a no-op. On little endian the bytes are
- /// swapped.
- #[inline]
- pub fn to_be(self) -> Self {
- #[cfg(target_endian = "big")]
- {
- self
- }
- #[cfg(not(target_endian = "big"))]
- {
- self.swap_bytes()
- }
- }
-
- /// Converts a vector from little endian to the target's endianness.
- ///
- /// On little endian this is a no-op. On big endian the bytes are
- /// swapped.
- #[inline]
- pub fn from_le(x: Self) -> Self {
- #[cfg(target_endian = "little")]
- {
- x
- }
- #[cfg(not(target_endian = "little"))]
- {
- x.swap_bytes()
- }
- }
-
- /// Converts a vector from big endian to the target's endianness.
- ///
- /// On big endian this is a no-op. On little endian the bytes are
- /// swapped.
- #[inline]
- pub fn from_be(x: Self) -> Self {
- #[cfg(target_endian = "big")]
- {
- x
- }
- #[cfg(not(target_endian = "big"))]
- {
- x.swap_bytes()
- }
- }
- }
-
- test_if! {
- $test_tt:
- paste::item! {
- pub mod [<$id _swap_bytes>] {
- use super::*;
-
- const BYTES: [u8; 64] = [
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- ];
-
- macro_rules! swap {
- ($func: ident) => {{
- // catch possible future >512 vectors
- assert!(mem::size_of::<$id>() <= 64);
-
- let mut actual = BYTES;
- let elems: &mut [$elem_ty] = unsafe {
- slice::from_raw_parts_mut(
- actual.as_mut_ptr() as *mut $elem_ty,
- $id::lanes(),
- )
- };
-
- let vec = $id::from_slice_unaligned(elems);
- $id::$func(vec).write_to_slice_unaligned(elems);
-
- actual
- }};
- }
-
- macro_rules! test_swap {
- ($func: ident) => {{
- let actual = swap!($func);
- let expected =
- BYTES.iter().rev()
- .skip(64 - crate::mem::size_of::<$id>());
- assert!(actual.iter().zip(expected)
- .all(|(x, y)| x == y));
- }};
- }
-
- macro_rules! test_no_swap {
- ($func: ident) => {{
- let actual = swap!($func);
- let expected = BYTES.iter()
- .take(mem::size_of::<$id>());
-
- assert!(actual.iter().zip(expected)
- .all(|(x, y)| x == y));
- }};
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn swap_bytes() {
- test_swap!(swap_bytes);
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn to_le() {
- #[cfg(target_endian = "little")]
- {
- test_no_swap!(to_le);
- }
- #[cfg(not(target_endian = "little"))]
- {
- test_swap!(to_le);
- }
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn to_be() {
- #[cfg(target_endian = "big")]
- {
- test_no_swap!(to_be);
- }
- #[cfg(not(target_endian = "big"))]
- {
- test_swap!(to_be);
- }
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn from_le() {
- #[cfg(target_endian = "little")]
- {
- test_no_swap!(from_le);
- }
- #[cfg(not(target_endian = "little"))]
- {
- test_swap!(from_le);
- }
- }
-
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn from_be() {
- #[cfg(target_endian = "big")]
- {
- test_no_swap!(from_be);
- }
- #[cfg(not(target_endian = "big"))]
- {
- test_swap!(from_be);
- }
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen.rs b/third_party/rust/packed_simd/src/codegen.rs
deleted file mode 100644
index 8a9e971486..0000000000
--- a/third_party/rust/packed_simd/src/codegen.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-//! Code-generation utilities
-
-pub(crate) mod bit_manip;
-pub(crate) mod llvm;
-pub(crate) mod math;
-pub(crate) mod reductions;
-pub(crate) mod shuffle;
-pub(crate) mod shuffle1_dyn;
-pub(crate) mod swap_bytes;
-
-macro_rules! impl_simd_array {
- ([$elem_ty:ident; $elem_count:expr]:
- $tuple_id:ident | $($elem_tys:ident),*) => {
- #[derive(Copy, Clone)]
- #[repr(simd)]
- pub struct $tuple_id($(pub(crate) $elem_tys),*);
- //^^^^^^^ leaked through SimdArray
-
- impl crate::sealed::Seal for [$elem_ty; $elem_count] {}
-
- impl crate::sealed::SimdArray for [$elem_ty; $elem_count] {
- type Tuple = $tuple_id;
- type T = $elem_ty;
- const N: usize = $elem_count;
- type NT = [u32; $elem_count];
- }
-
- impl crate::sealed::Seal for $tuple_id {}
- impl crate::sealed::Simd for $tuple_id {
- type Element = $elem_ty;
- const LANES: usize = $elem_count;
- type LanesType = [u32; $elem_count];
- }
-
- }
-}
-
-pub(crate) mod pointer_sized_int;
-
-pub(crate) mod v16;
-pub(crate) use self::v16::*;
-
-pub(crate) mod v32;
-pub(crate) use self::v32::*;
-
-pub(crate) mod v64;
-pub(crate) use self::v64::*;
-
-pub(crate) mod v128;
-pub(crate) use self::v128::*;
-
-pub(crate) mod v256;
-pub(crate) use self::v256::*;
-
-pub(crate) mod v512;
-pub(crate) use self::v512::*;
-
-pub(crate) mod vSize;
-pub(crate) use self::vSize::*;
-
-pub(crate) mod vPtr;
-pub(crate) use self::vPtr::*;
diff --git a/third_party/rust/packed_simd/src/codegen/bit_manip.rs b/third_party/rust/packed_simd/src/codegen/bit_manip.rs
deleted file mode 100644
index 32d8d717a0..0000000000
--- a/third_party/rust/packed_simd/src/codegen/bit_manip.rs
+++ /dev/null
@@ -1,347 +0,0 @@
-//! LLVM bit manipulation intrinsics.
-#[rustfmt::skip]
-
-pub(crate) use crate::*;
-
-#[allow(improper_ctypes, dead_code)]
-extern "C" {
- #[link_name = "llvm.ctlz.v2i8"]
- fn ctlz_u8x2(x: u8x2, is_zero_undef: bool) -> u8x2;
- #[link_name = "llvm.ctlz.v4i8"]
- fn ctlz_u8x4(x: u8x4, is_zero_undef: bool) -> u8x4;
- #[link_name = "llvm.ctlz.v8i8"]
- fn ctlz_u8x8(x: u8x8, is_zero_undef: bool) -> u8x8;
- #[link_name = "llvm.ctlz.v16i8"]
- fn ctlz_u8x16(x: u8x16, is_zero_undef: bool) -> u8x16;
- #[link_name = "llvm.ctlz.v32i8"]
- fn ctlz_u8x32(x: u8x32, is_zero_undef: bool) -> u8x32;
- #[link_name = "llvm.ctlz.v64i8"]
- fn ctlz_u8x64(x: u8x64, is_zero_undef: bool) -> u8x64;
-
- #[link_name = "llvm.ctlz.v2i16"]
- fn ctlz_u16x2(x: u16x2, is_zero_undef: bool) -> u16x2;
- #[link_name = "llvm.ctlz.v4i16"]
- fn ctlz_u16x4(x: u16x4, is_zero_undef: bool) -> u16x4;
- #[link_name = "llvm.ctlz.v8i16"]
- fn ctlz_u16x8(x: u16x8, is_zero_undef: bool) -> u16x8;
- #[link_name = "llvm.ctlz.v16i16"]
- fn ctlz_u16x16(x: u16x16, is_zero_undef: bool) -> u16x16;
- #[link_name = "llvm.ctlz.v32i16"]
- fn ctlz_u16x32(x: u16x32, is_zero_undef: bool) -> u16x32;
-
- #[link_name = "llvm.ctlz.v2i32"]
- fn ctlz_u32x2(x: u32x2, is_zero_undef: bool) -> u32x2;
- #[link_name = "llvm.ctlz.v4i32"]
- fn ctlz_u32x4(x: u32x4, is_zero_undef: bool) -> u32x4;
- #[link_name = "llvm.ctlz.v8i32"]
- fn ctlz_u32x8(x: u32x8, is_zero_undef: bool) -> u32x8;
- #[link_name = "llvm.ctlz.v16i32"]
- fn ctlz_u32x16(x: u32x16, is_zero_undef: bool) -> u32x16;
-
- #[link_name = "llvm.ctlz.v2i64"]
- fn ctlz_u64x2(x: u64x2, is_zero_undef: bool) -> u64x2;
- #[link_name = "llvm.ctlz.v4i64"]
- fn ctlz_u64x4(x: u64x4, is_zero_undef: bool) -> u64x4;
- #[link_name = "llvm.ctlz.v8i64"]
- fn ctlz_u64x8(x: u64x8, is_zero_undef: bool) -> u64x8;
-
- #[link_name = "llvm.ctlz.v1i128"]
- fn ctlz_u128x1(x: u128x1, is_zero_undef: bool) -> u128x1;
- #[link_name = "llvm.ctlz.v2i128"]
- fn ctlz_u128x2(x: u128x2, is_zero_undef: bool) -> u128x2;
- #[link_name = "llvm.ctlz.v4i128"]
- fn ctlz_u128x4(x: u128x4, is_zero_undef: bool) -> u128x4;
-
- #[link_name = "llvm.cttz.v2i8"]
- fn cttz_u8x2(x: u8x2, is_zero_undef: bool) -> u8x2;
- #[link_name = "llvm.cttz.v4i8"]
- fn cttz_u8x4(x: u8x4, is_zero_undef: bool) -> u8x4;
- #[link_name = "llvm.cttz.v8i8"]
- fn cttz_u8x8(x: u8x8, is_zero_undef: bool) -> u8x8;
- #[link_name = "llvm.cttz.v16i8"]
- fn cttz_u8x16(x: u8x16, is_zero_undef: bool) -> u8x16;
- #[link_name = "llvm.cttz.v32i8"]
- fn cttz_u8x32(x: u8x32, is_zero_undef: bool) -> u8x32;
- #[link_name = "llvm.cttz.v64i8"]
- fn cttz_u8x64(x: u8x64, is_zero_undef: bool) -> u8x64;
-
- #[link_name = "llvm.cttz.v2i16"]
- fn cttz_u16x2(x: u16x2, is_zero_undef: bool) -> u16x2;
- #[link_name = "llvm.cttz.v4i16"]
- fn cttz_u16x4(x: u16x4, is_zero_undef: bool) -> u16x4;
- #[link_name = "llvm.cttz.v8i16"]
- fn cttz_u16x8(x: u16x8, is_zero_undef: bool) -> u16x8;
- #[link_name = "llvm.cttz.v16i16"]
- fn cttz_u16x16(x: u16x16, is_zero_undef: bool) -> u16x16;
- #[link_name = "llvm.cttz.v32i16"]
- fn cttz_u16x32(x: u16x32, is_zero_undef: bool) -> u16x32;
-
- #[link_name = "llvm.cttz.v2i32"]
- fn cttz_u32x2(x: u32x2, is_zero_undef: bool) -> u32x2;
- #[link_name = "llvm.cttz.v4i32"]
- fn cttz_u32x4(x: u32x4, is_zero_undef: bool) -> u32x4;
- #[link_name = "llvm.cttz.v8i32"]
- fn cttz_u32x8(x: u32x8, is_zero_undef: bool) -> u32x8;
- #[link_name = "llvm.cttz.v16i32"]
- fn cttz_u32x16(x: u32x16, is_zero_undef: bool) -> u32x16;
-
- #[link_name = "llvm.cttz.v2i64"]
- fn cttz_u64x2(x: u64x2, is_zero_undef: bool) -> u64x2;
- #[link_name = "llvm.cttz.v4i64"]
- fn cttz_u64x4(x: u64x4, is_zero_undef: bool) -> u64x4;
- #[link_name = "llvm.cttz.v8i64"]
- fn cttz_u64x8(x: u64x8, is_zero_undef: bool) -> u64x8;
-
- #[link_name = "llvm.cttz.v1i128"]
- fn cttz_u128x1(x: u128x1, is_zero_undef: bool) -> u128x1;
- #[link_name = "llvm.cttz.v2i128"]
- fn cttz_u128x2(x: u128x2, is_zero_undef: bool) -> u128x2;
- #[link_name = "llvm.cttz.v4i128"]
- fn cttz_u128x4(x: u128x4, is_zero_undef: bool) -> u128x4;
-
- #[link_name = "llvm.ctpop.v2i8"]
- fn ctpop_u8x2(x: u8x2) -> u8x2;
- #[link_name = "llvm.ctpop.v4i8"]
- fn ctpop_u8x4(x: u8x4) -> u8x4;
- #[link_name = "llvm.ctpop.v8i8"]
- fn ctpop_u8x8(x: u8x8) -> u8x8;
- #[link_name = "llvm.ctpop.v16i8"]
- fn ctpop_u8x16(x: u8x16) -> u8x16;
- #[link_name = "llvm.ctpop.v32i8"]
- fn ctpop_u8x32(x: u8x32) -> u8x32;
- #[link_name = "llvm.ctpop.v64i8"]
- fn ctpop_u8x64(x: u8x64) -> u8x64;
-
- #[link_name = "llvm.ctpop.v2i16"]
- fn ctpop_u16x2(x: u16x2) -> u16x2;
- #[link_name = "llvm.ctpop.v4i16"]
- fn ctpop_u16x4(x: u16x4) -> u16x4;
- #[link_name = "llvm.ctpop.v8i16"]
- fn ctpop_u16x8(x: u16x8) -> u16x8;
- #[link_name = "llvm.ctpop.v16i16"]
- fn ctpop_u16x16(x: u16x16) -> u16x16;
- #[link_name = "llvm.ctpop.v32i16"]
- fn ctpop_u16x32(x: u16x32) -> u16x32;
-
- #[link_name = "llvm.ctpop.v2i32"]
- fn ctpop_u32x2(x: u32x2) -> u32x2;
- #[link_name = "llvm.ctpop.v4i32"]
- fn ctpop_u32x4(x: u32x4) -> u32x4;
- #[link_name = "llvm.ctpop.v8i32"]
- fn ctpop_u32x8(x: u32x8) -> u32x8;
- #[link_name = "llvm.ctpop.v16i32"]
- fn ctpop_u32x16(x: u32x16) -> u32x16;
-
- #[link_name = "llvm.ctpop.v2i64"]
- fn ctpop_u64x2(x: u64x2) -> u64x2;
- #[link_name = "llvm.ctpop.v4i64"]
- fn ctpop_u64x4(x: u64x4) -> u64x4;
- #[link_name = "llvm.ctpop.v8i64"]
- fn ctpop_u64x8(x: u64x8) -> u64x8;
-
- #[link_name = "llvm.ctpop.v1i128"]
- fn ctpop_u128x1(x: u128x1) -> u128x1;
- #[link_name = "llvm.ctpop.v2i128"]
- fn ctpop_u128x2(x: u128x2) -> u128x2;
- #[link_name = "llvm.ctpop.v4i128"]
- fn ctpop_u128x4(x: u128x4) -> u128x4;
-}
-
-pub(crate) trait BitManip {
- fn ctpop(self) -> Self;
- fn ctlz(self) -> Self;
- fn cttz(self) -> Self;
-}
-
-macro_rules! impl_bit_manip {
- (inner: $ty:ident, $scalar:ty, $uty:ident,
- $ctpop:ident, $ctlz:ident, $cttz:ident) => {
- // FIXME: several LLVM intrinsics break on s390x https://github.com/rust-lang-nursery/packed_simd/issues/192
- #[cfg(target_arch = "s390x")]
- impl_bit_manip! { scalar: $ty, $scalar }
- #[cfg(not(target_arch = "s390x"))]
- impl BitManip for $ty {
- #[inline]
- fn ctpop(self) -> Self {
- let y: $uty = self.cast();
- unsafe { $ctpop(y).cast() }
- }
-
- #[inline]
- fn ctlz(self) -> Self {
- let y: $uty = self.cast();
- // the ctxx intrinsics need compile-time constant
- // `is_zero_undef`
- unsafe { $ctlz(y, false).cast() }
- }
-
- #[inline]
- fn cttz(self) -> Self {
- let y: $uty = self.cast();
- unsafe { $cttz(y, false).cast() }
- }
- }
- };
- (sized_inner: $ty:ident, $scalar:ty, $uty:ident) => {
- #[cfg(target_arch = "s390x")]
- impl_bit_manip! { scalar: $ty, $scalar }
- #[cfg(not(target_arch = "s390x"))]
- impl BitManip for $ty {
- #[inline]
- fn ctpop(self) -> Self {
- let y: $uty = self.cast();
- $uty::ctpop(y).cast()
- }
-
- #[inline]
- fn ctlz(self) -> Self {
- let y: $uty = self.cast();
- $uty::ctlz(y).cast()
- }
-
- #[inline]
- fn cttz(self) -> Self {
- let y: $uty = self.cast();
- $uty::cttz(y).cast()
- }
- }
- };
- (scalar: $ty:ident, $scalar:ty) => {
- impl BitManip for $ty {
- #[inline]
- fn ctpop(self) -> Self {
- let mut ones = self;
- for i in 0..Self::lanes() {
- ones = ones.replace(i, self.extract(i).count_ones() as $scalar);
- }
- ones
- }
-
- #[inline]
- fn ctlz(self) -> Self {
- let mut lz = self;
- for i in 0..Self::lanes() {
- lz = lz.replace(i, self.extract(i).leading_zeros() as $scalar);
- }
- lz
- }
-
- #[inline]
- fn cttz(self) -> Self {
- let mut tz = self;
- for i in 0..Self::lanes() {
- tz = tz.replace(i, self.extract(i).trailing_zeros() as $scalar);
- }
- tz
- }
- }
- };
- ($uty:ident, $uscalar:ty, $ity:ident, $iscalar:ty,
- $ctpop:ident, $ctlz:ident, $cttz:ident) => {
- impl_bit_manip! { inner: $uty, $uscalar, $uty, $ctpop, $ctlz, $cttz }
- impl_bit_manip! { inner: $ity, $iscalar, $uty, $ctpop, $ctlz, $cttz }
- };
- (sized: $usize:ident, $uscalar:ty, $isize:ident,
- $iscalar:ty, $ty:ident) => {
- impl_bit_manip! { sized_inner: $usize, $uscalar, $ty }
- impl_bit_manip! { sized_inner: $isize, $iscalar, $ty }
- };
-}
-
-impl_bit_manip! { u8x2 , u8, i8x2, i8, ctpop_u8x2, ctlz_u8x2, cttz_u8x2 }
-impl_bit_manip! { u8x4 , u8, i8x4, i8, ctpop_u8x4, ctlz_u8x4, cttz_u8x4 }
-#[cfg(not(target_arch = "aarch64"))] // see below
-impl_bit_manip! { u8x8 , u8, i8x8, i8, ctpop_u8x8, ctlz_u8x8, cttz_u8x8 }
-impl_bit_manip! { u8x16 , u8, i8x16, i8, ctpop_u8x16, ctlz_u8x16, cttz_u8x16 }
-impl_bit_manip! { u8x32 , u8, i8x32, i8, ctpop_u8x32, ctlz_u8x32, cttz_u8x32 }
-impl_bit_manip! { u8x64 , u8, i8x64, i8, ctpop_u8x64, ctlz_u8x64, cttz_u8x64 }
-impl_bit_manip! { u16x2 , u16, i16x2, i16, ctpop_u16x2, ctlz_u16x2, cttz_u16x2 }
-impl_bit_manip! { u16x4 , u16, i16x4, i16, ctpop_u16x4, ctlz_u16x4, cttz_u16x4 }
-impl_bit_manip! { u16x8 , u16, i16x8, i16, ctpop_u16x8, ctlz_u16x8, cttz_u16x8 }
-impl_bit_manip! { u16x16 , u16, i16x16, i16, ctpop_u16x16, ctlz_u16x16, cttz_u16x16 }
-impl_bit_manip! { u16x32 , u16, i16x32, i16, ctpop_u16x32, ctlz_u16x32, cttz_u16x32 }
-impl_bit_manip! { u32x2 , u32, i32x2, i32, ctpop_u32x2, ctlz_u32x2, cttz_u32x2 }
-impl_bit_manip! { u32x4 , u32, i32x4, i32, ctpop_u32x4, ctlz_u32x4, cttz_u32x4 }
-impl_bit_manip! { u32x8 , u32, i32x8, i32, ctpop_u32x8, ctlz_u32x8, cttz_u32x8 }
-impl_bit_manip! { u32x16 , u32, i32x16, i32, ctpop_u32x16, ctlz_u32x16, cttz_u32x16 }
-impl_bit_manip! { u64x2 , u64, i64x2, i64, ctpop_u64x2, ctlz_u64x2, cttz_u64x2 }
-impl_bit_manip! { u64x4 , u64, i64x4, i64, ctpop_u64x4, ctlz_u64x4, cttz_u64x4 }
-impl_bit_manip! { u64x8 , u64, i64x8, i64, ctpop_u64x8, ctlz_u64x8, cttz_u64x8 }
-impl_bit_manip! { u128x1 , u128, i128x1, i128, ctpop_u128x1, ctlz_u128x1, cttz_u128x1 }
-impl_bit_manip! { u128x2 , u128, i128x2, i128, ctpop_u128x2, ctlz_u128x2, cttz_u128x2 }
-impl_bit_manip! { u128x4 , u128, i128x4, i128, ctpop_u128x4, ctlz_u128x4, cttz_u128x4 }
-
-#[cfg(target_arch = "aarch64")]
-impl BitManip for u8x8 {
- #[inline]
- fn ctpop(self) -> Self {
- let y: u8x8 = self.cast();
- unsafe { ctpop_u8x8(y).cast() }
- }
-
- #[inline]
- fn ctlz(self) -> Self {
- let y: u8x8 = self.cast();
- unsafe { ctlz_u8x8(y, false).cast() }
- }
-
- #[inline]
- fn cttz(self) -> Self {
- // FIXME: LLVM cttz.v8i8 broken on aarch64 https://github.com/rust-lang-nursery/packed_simd/issues/191
- // OPTIMIZE: adapt the algorithm used for v8i16/etc to Rust's aarch64
- // intrinsics
- let mut tz = self;
- for i in 0..Self::lanes() {
- tz = tz.replace(i, self.extract(i).trailing_zeros() as u8);
- }
- tz
- }
-}
-#[cfg(target_arch = "aarch64")]
-impl BitManip for i8x8 {
- #[inline]
- fn ctpop(self) -> Self {
- let y: u8x8 = self.cast();
- unsafe { ctpop_u8x8(y).cast() }
- }
-
- #[inline]
- fn ctlz(self) -> Self {
- let y: u8x8 = self.cast();
- unsafe { ctlz_u8x8(y, false).cast() }
- }
-
- #[inline]
- fn cttz(self) -> Self {
- // FIXME: LLVM cttz.v8i8 broken on aarch64 https://github.com/rust-lang-nursery/packed_simd/issues/191
- // OPTIMIZE: adapt the algorithm used for v8i16/etc to Rust's aarch64
- // intrinsics
- let mut tz = self;
- for i in 0..Self::lanes() {
- tz = tz.replace(i, self.extract(i).trailing_zeros() as i8);
- }
- tz
- }
-}
-
-cfg_if! {
- if #[cfg(target_pointer_width = "8")] {
- impl_bit_manip! { sized: usizex2, usize, isizex2, isize, u8x2 }
- impl_bit_manip! { sized: usizex4, usize, isizex4, isize, u8x4 }
- impl_bit_manip! { sized: usizex8, usize, isizex8, isize, u8x8 }
- } else if #[cfg(target_pointer_width = "16")] {
- impl_bit_manip! { sized: usizex2, usize, isizex2, isize, u16x2 }
- impl_bit_manip! { sized: usizex4, usize, isizex4, isize, u16x4 }
- impl_bit_manip! { sized: usizex8, usize, isizex8, isize, u16x8 }
- } else if #[cfg(target_pointer_width = "32")] {
- impl_bit_manip! { sized: usizex2, usize, isizex2, isize, u32x2 }
- impl_bit_manip! { sized: usizex4, usize, isizex4, isize, u32x4 }
- impl_bit_manip! { sized: usizex8, usize, isizex8, isize, u32x8 }
- } else if #[cfg(target_pointer_width = "64")] {
- impl_bit_manip! { sized: usizex2, usize, isizex2, isize, u64x2 }
- impl_bit_manip! { sized: usizex4, usize, isizex4, isize, u64x4 }
- impl_bit_manip! { sized: usizex8, usize, isizex8, isize, u64x8 }
- } else {
- compile_error!("unsupported target_pointer_width");
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/llvm.rs b/third_party/rust/packed_simd/src/codegen/llvm.rs
deleted file mode 100644
index bb482fac66..0000000000
--- a/third_party/rust/packed_simd/src/codegen/llvm.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-//! LLVM's platform intrinsics
-#![allow(dead_code)]
-
-use crate::sealed::Shuffle;
-#[allow(unused_imports)] // FIXME: spurious warning?
-use crate::sealed::Simd;
-
-extern "platform-intrinsic" {
- fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
-}
-
-#[allow(clippy::missing_safety_doc)]
-#[inline]
-pub unsafe fn __shuffle_vector2<const IDX: [u32; 2], T, U>(x: T, y: T) -> U
-where
- T: Simd,
- <T as Simd>::Element: Shuffle<[u32; 2], Output = U>,
-{
- simd_shuffle(x, y, IDX)
-}
-
-#[allow(clippy::missing_safety_doc)]
-#[inline]
-pub unsafe fn __shuffle_vector4<const IDX: [u32; 4], T, U>(x: T, y: T) -> U
-where
- T: Simd,
- <T as Simd>::Element: Shuffle<[u32; 4], Output = U>,
-{
- simd_shuffle(x, y, IDX)
-}
-
-#[allow(clippy::missing_safety_doc)]
-#[inline]
-pub unsafe fn __shuffle_vector8<const IDX: [u32; 8], T, U>(x: T, y: T) -> U
-where
- T: Simd,
- <T as Simd>::Element: Shuffle<[u32; 8], Output = U>,
-{
- simd_shuffle(x, y, IDX)
-}
-
-#[allow(clippy::missing_safety_doc)]
-#[inline]
-pub unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U
-where
- T: Simd,
- <T as Simd>::Element: Shuffle<[u32; 16], Output = U>,
-{
- simd_shuffle(x, y, IDX)
-}
-
-#[allow(clippy::missing_safety_doc)]
-#[inline]
-pub unsafe fn __shuffle_vector32<const IDX: [u32; 32], T, U>(x: T, y: T) -> U
-where
- T: Simd,
- <T as Simd>::Element: Shuffle<[u32; 32], Output = U>,
-{
- simd_shuffle(x, y, IDX)
-}
-
-#[allow(clippy::missing_safety_doc)]
-#[inline]
-pub unsafe fn __shuffle_vector64<const IDX: [u32; 64], T, U>(x: T, y: T) -> U
-where
- T: Simd,
- <T as Simd>::Element: Shuffle<[u32; 64], Output = U>,
-{
- simd_shuffle(x, y, IDX)
-}
-
-extern "platform-intrinsic" {
- pub(crate) fn simd_eq<T, U>(x: T, y: T) -> U;
- pub(crate) fn simd_ne<T, U>(x: T, y: T) -> U;
- pub(crate) fn simd_lt<T, U>(x: T, y: T) -> U;
- pub(crate) fn simd_le<T, U>(x: T, y: T) -> U;
- pub(crate) fn simd_gt<T, U>(x: T, y: T) -> U;
- pub(crate) fn simd_ge<T, U>(x: T, y: T) -> U;
-
- pub(crate) fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
- pub(crate) fn simd_extract<T, U>(x: T, idx: u32) -> U;
-
- pub(crate) fn simd_cast<T, U>(x: T) -> U;
-
- pub(crate) fn simd_add<T>(x: T, y: T) -> T;
- pub(crate) fn simd_sub<T>(x: T, y: T) -> T;
- pub(crate) fn simd_mul<T>(x: T, y: T) -> T;
- pub(crate) fn simd_div<T>(x: T, y: T) -> T;
- pub(crate) fn simd_rem<T>(x: T, y: T) -> T;
- pub(crate) fn simd_shl<T>(x: T, y: T) -> T;
- pub(crate) fn simd_shr<T>(x: T, y: T) -> T;
- pub(crate) fn simd_and<T>(x: T, y: T) -> T;
- pub(crate) fn simd_or<T>(x: T, y: T) -> T;
- pub(crate) fn simd_xor<T>(x: T, y: T) -> T;
-
- pub(crate) fn simd_reduce_add_unordered<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_add_ordered<T, U>(x: T, acc: U) -> U;
- pub(crate) fn simd_reduce_mul_ordered<T, U>(x: T, acc: U) -> U;
- pub(crate) fn simd_reduce_min<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_max<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_min_nanless<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_max_nanless<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_and<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_or<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_xor<T, U>(x: T) -> U;
- pub(crate) fn simd_reduce_all<T>(x: T) -> bool;
- pub(crate) fn simd_reduce_any<T>(x: T) -> bool;
-
- pub(crate) fn simd_select<M, T>(m: M, a: T, b: T) -> T;
-
- pub(crate) fn simd_fmin<T>(a: T, b: T) -> T;
- pub(crate) fn simd_fmax<T>(a: T, b: T) -> T;
-
- pub(crate) fn simd_fsqrt<T>(a: T) -> T;
- pub(crate) fn simd_fma<T>(a: T, b: T, c: T) -> T;
-
- pub(crate) fn simd_gather<T, P, M>(value: T, pointers: P, mask: M) -> T;
- pub(crate) fn simd_scatter<T, P, M>(value: T, pointers: P, mask: M);
-
- pub(crate) fn simd_bitmask<T, U>(value: T) -> U;
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math.rs b/third_party/rust/packed_simd/src/codegen/math.rs
deleted file mode 100644
index 9a0ea7a4e2..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//! Vertical math operations
-
-pub(crate) mod float;
diff --git a/third_party/rust/packed_simd/src/codegen/math/float.rs b/third_party/rust/packed_simd/src/codegen/math/float.rs
deleted file mode 100644
index 10d21831f1..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//! Vertical floating-point math operations.
-#![allow(clippy::useless_transmute)]
-
-#[macro_use]
-pub(crate) mod macros;
-pub(crate) mod abs;
-pub(crate) mod cos;
-pub(crate) mod cos_pi;
-pub(crate) mod exp;
-pub(crate) mod ln;
-pub(crate) mod mul_add;
-pub(crate) mod mul_adde;
-pub(crate) mod powf;
-pub(crate) mod sin;
-pub(crate) mod sin_cos_pi;
-pub(crate) mod sin_pi;
-pub(crate) mod sqrt;
-pub(crate) mod sqrte;
-pub(crate) mod tanh;
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/abs.rs b/third_party/rust/packed_simd/src/codegen/math/float/abs.rs
deleted file mode 100644
index 34aacc25be..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/abs.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-//! Vertical floating-point `fabs`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors fabs
-
-use crate::*;
-
-pub(crate) trait Abs {
- fn abs(self) -> Self;
-}
-
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.fabs.v2f32"]
- fn fabs_v2f32(x: f32x2) -> f32x2;
- #[link_name = "llvm.fabs.v4f32"]
- fn fabs_v4f32(x: f32x4) -> f32x4;
- #[link_name = "llvm.fabs.v8f32"]
- fn fabs_v8f32(x: f32x8) -> f32x8;
- #[link_name = "llvm.fabs.v16f32"]
- fn fabs_v16f32(x: f32x16) -> f32x16;
- /* FIXME 64-bit fabsgle elem vectors
- #[link_name = "llvm.fabs.v1f64"]
- fn fabs_v1f64(x: f64x1) -> f64x1;
- */
- #[link_name = "llvm.fabs.v2f64"]
- fn fabs_v2f64(x: f64x2) -> f64x2;
- #[link_name = "llvm.fabs.v4f64"]
- fn fabs_v4f64(x: f64x4) -> f64x4;
- #[link_name = "llvm.fabs.v8f64"]
- fn fabs_v8f64(x: f64x8) -> f64x8;
-
- #[link_name = "llvm.fabs.f32"]
- fn fabs_f32(x: f32) -> f32;
- #[link_name = "llvm.fabs.f64"]
- fn fabs_f64(x: f64) -> f64;
-}
-
-gen_unary_impl_table!(Abs, abs);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: fabs_f32);
- impl_unary!(f32x4[f32; 4]: fabs_f32);
- impl_unary!(f32x8[f32; 8]: fabs_f32);
- impl_unary!(f32x16[f32; 16]: fabs_f32);
-
- impl_unary!(f64x2[f64; 2]: fabs_f64);
- impl_unary!(f64x4[f64; 4]: fabs_f64);
- impl_unary!(f64x8[f64; 8]: fabs_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_fabsf4_avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_fabsf8_avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_fabsd4_avx2);
-
- impl_unary!(f32x4: Sleef_fabsf4_avx2128);
- impl_unary!(f32x8: Sleef_fabsf8_avx2);
- impl_unary!(f64x2: Sleef_fabsd2_avx2128);
- impl_unary!(f64x4: Sleef_fabsd4_avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_fabsf4_sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_fabsf8_avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_fabsd4_avx);
-
- impl_unary!(f32x4: Sleef_fabsf4_sse4);
- impl_unary!(f32x8: Sleef_fabsf8_avx);
- impl_unary!(f64x2: Sleef_fabsd2_sse4);
- impl_unary!(f64x4: Sleef_fabsd4_avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_fabsf4_sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_fabsf4_sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_fabsd2_sse4);
-
- impl_unary!(f32x4: Sleef_fabsf4_sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_fabsf4_sse4);
- impl_unary!(f64x2: Sleef_fabsd2_sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_fabsd2_sse4);
- } else {
- impl_unary!(f32x2[f32; 2]: fabs_f32);
- impl_unary!(f32x16: fabs_v16f32);
- impl_unary!(f64x8: fabs_v8f64);
-
- impl_unary!(f32x4: fabs_v4f32);
- impl_unary!(f32x8: fabs_v8f32);
- impl_unary!(f64x2: fabs_v2f64);
- impl_unary!(f64x4: fabs_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: fabs_f32);
- impl_unary!(f32x4: fabs_v4f32);
- impl_unary!(f32x8: fabs_v8f32);
- impl_unary!(f32x16: fabs_v16f32);
-
- impl_unary!(f64x2: fabs_v2f64);
- impl_unary!(f64x4: fabs_v4f64);
- impl_unary!(f64x8: fabs_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/cos.rs b/third_party/rust/packed_simd/src/codegen/math/float/cos.rs
deleted file mode 100644
index dec390cb74..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/cos.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-//! Vertical floating-point `cos`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vector cos
-
-use crate::*;
-
-pub(crate) trait Cos {
- fn cos(self) -> Self;
-}
-
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.cos.v2f32"]
- fn cos_v2f32(x: f32x2) -> f32x2;
- #[link_name = "llvm.cos.v4f32"]
- fn cos_v4f32(x: f32x4) -> f32x4;
- #[link_name = "llvm.cos.v8f32"]
- fn cos_v8f32(x: f32x8) -> f32x8;
- #[link_name = "llvm.cos.v16f32"]
- fn cos_v16f32(x: f32x16) -> f32x16;
- /* FIXME 64-bit cosgle elem vectors
- #[link_name = "llvm.cos.v1f64"]
- fn cos_v1f64(x: f64x1) -> f64x1;
- */
- #[link_name = "llvm.cos.v2f64"]
- fn cos_v2f64(x: f64x2) -> f64x2;
- #[link_name = "llvm.cos.v4f64"]
- fn cos_v4f64(x: f64x4) -> f64x4;
- #[link_name = "llvm.cos.v8f64"]
- fn cos_v8f64(x: f64x8) -> f64x8;
-
- #[link_name = "llvm.cos.f32"]
- fn cos_f32(x: f32) -> f32;
- #[link_name = "llvm.cos.f64"]
- fn cos_f64(x: f64) -> f64;
-}
-
-gen_unary_impl_table!(Cos, cos);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: cos_f32);
- impl_unary!(f32x4[f32; 4]: cos_f32);
- impl_unary!(f32x8[f32; 8]: cos_f32);
- impl_unary!(f32x16[f32; 16]: cos_f32);
-
- impl_unary!(f64x2[f64; 2]: cos_f64);
- impl_unary!(f64x4[f64; 4]: cos_f64);
- impl_unary!(f64x8[f64; 8]: cos_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_cosf4_u10avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_cosf8_u10avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_cosd4_u10avx2);
-
- impl_unary!(f32x4: Sleef_cosf4_u10avx2128);
- impl_unary!(f32x8: Sleef_cosf8_u10avx2);
- impl_unary!(f64x2: Sleef_cosd2_u10avx2128);
- impl_unary!(f64x4: Sleef_cosd4_u10avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_cosf4_u10sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_cosf8_u10avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_cosd4_u10avx);
-
- impl_unary!(f32x4: Sleef_cosf4_u10sse4);
- impl_unary!(f32x8: Sleef_cosf8_u10avx);
- impl_unary!(f64x2: Sleef_cosd2_u10sse4);
- impl_unary!(f64x4: Sleef_cosd4_u10avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_cosf4_u10sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_cosf4_u10sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_cosd2_u10sse4);
-
- impl_unary!(f32x4: Sleef_cosf4_u10sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_cosf4_u10sse4);
- impl_unary!(f64x2: Sleef_cosd2_u10sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_cosd2_u10sse4);
- } else {
- impl_unary!(f32x2[f32; 2]: cos_f32);
- impl_unary!(f32x16: cos_v16f32);
- impl_unary!(f64x8: cos_v8f64);
-
- impl_unary!(f32x4: cos_v4f32);
- impl_unary!(f32x8: cos_v8f32);
- impl_unary!(f64x2: cos_v2f64);
- impl_unary!(f64x4: cos_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: cos_f32);
- impl_unary!(f32x4: cos_v4f32);
- impl_unary!(f32x8: cos_v8f32);
- impl_unary!(f32x16: cos_v16f32);
-
- impl_unary!(f64x2: cos_v2f64);
- impl_unary!(f64x4: cos_v4f64);
- impl_unary!(f64x8: cos_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/cos_pi.rs b/third_party/rust/packed_simd/src/codegen/math/float/cos_pi.rs
deleted file mode 100644
index e283280ee4..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/cos_pi.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-//! Vertical floating-point `cos`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors cos_pi
-
-use crate::*;
-
-pub(crate) trait CosPi {
- fn cos_pi(self) -> Self;
-}
-
-gen_unary_impl_table!(CosPi, cos_pi);
-
-macro_rules! impl_def {
- ($vid:ident, $PI:path) => {
- impl CosPi for $vid {
- #[inline]
- fn cos_pi(self) -> Self {
- (self * Self::splat($PI)).cos()
- }
- }
- };
-}
-macro_rules! impl_def32 {
- ($vid:ident) => {
- impl_def!($vid, crate::f32::consts::PI);
- };
-}
-macro_rules! impl_def64 {
- ($vid:ident) => {
- impl_def!($vid, crate::f64::consts::PI);
- };
-}
-
-cfg_if! {
- if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_cospif4_u05avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_cospif8_u05avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_cospid4_u05avx2);
-
- impl_unary!(f32x4: Sleef_cospif4_u05avx2128);
- impl_unary!(f32x8: Sleef_cospif8_u05avx2);
- impl_unary!(f64x2: Sleef_cospid2_u05avx2128);
- impl_unary!(f64x4: Sleef_cospid4_u05avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_cospif4_u05sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_cospif8_u05avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_cospid4_u05avx);
-
- impl_unary!(f32x4: Sleef_cospif4_u05sse4);
- impl_unary!(f32x8: Sleef_cospif8_u05avx);
- impl_unary!(f64x2: Sleef_cospid2_u05sse4);
- impl_unary!(f64x4: Sleef_cospid4_u05avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_cospif4_u05sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_cospif4_u05sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_cospid2_u05sse4);
-
- impl_unary!(f32x4: Sleef_cospif4_u05sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_cospif4_u05sse4);
- impl_unary!(f64x2: Sleef_cospid2_u05sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_cospid2_u05sse4);
- } else {
- impl_def32!(f32x2);
- impl_def32!(f32x4);
- impl_def32!(f32x8);
- impl_def32!(f32x16);
-
- impl_def64!(f64x2);
- impl_def64!(f64x4);
- impl_def64!(f64x8);
- }
- }
- } else {
- impl_def32!(f32x2);
- impl_def32!(f32x4);
- impl_def32!(f32x8);
- impl_def32!(f32x16);
-
- impl_def64!(f64x2);
- impl_def64!(f64x4);
- impl_def64!(f64x8);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/exp.rs b/third_party/rust/packed_simd/src/codegen/math/float/exp.rs
deleted file mode 100644
index a7b20580e3..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/exp.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-//! Vertical floating-point `exp`
-#![allow(unused)]
-
-// FIXME 64-bit expgle elem vectors misexpg
-
-use crate::*;
-
-pub(crate) trait Exp {
- fn exp(self) -> Self;
-}
-
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.exp.v2f32"]
- fn exp_v2f32(x: f32x2) -> f32x2;
- #[link_name = "llvm.exp.v4f32"]
- fn exp_v4f32(x: f32x4) -> f32x4;
- #[link_name = "llvm.exp.v8f32"]
- fn exp_v8f32(x: f32x8) -> f32x8;
- #[link_name = "llvm.exp.v16f32"]
- fn exp_v16f32(x: f32x16) -> f32x16;
- /* FIXME 64-bit expgle elem vectors
- #[link_name = "llvm.exp.v1f64"]
- fn exp_v1f64(x: f64x1) -> f64x1;
- */
- #[link_name = "llvm.exp.v2f64"]
- fn exp_v2f64(x: f64x2) -> f64x2;
- #[link_name = "llvm.exp.v4f64"]
- fn exp_v4f64(x: f64x4) -> f64x4;
- #[link_name = "llvm.exp.v8f64"]
- fn exp_v8f64(x: f64x8) -> f64x8;
-
- #[link_name = "llvm.exp.f32"]
- fn exp_f32(x: f32) -> f32;
- #[link_name = "llvm.exp.f64"]
- fn exp_f64(x: f64) -> f64;
-}
-
-gen_unary_impl_table!(Exp, exp);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: exp_f32);
- impl_unary!(f32x4[f32; 4]: exp_f32);
- impl_unary!(f32x8[f32; 8]: exp_f32);
- impl_unary!(f32x16[f32; 16]: exp_f32);
-
- impl_unary!(f64x2[f64; 2]: exp_f64);
- impl_unary!(f64x4[f64; 4]: exp_f64);
- impl_unary!(f64x8[f64; 8]: exp_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_expf4_u10avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_expf8_u10avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_expd4_u10avx2);
-
- impl_unary!(f32x4: Sleef_expf4_u10avx2128);
- impl_unary!(f32x8: Sleef_expf8_u10avx2);
- impl_unary!(f64x2: Sleef_expd2_u10avx2128);
- impl_unary!(f64x4: Sleef_expd4_u10avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_expf4_u10sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_expf8_u10avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_expd4_u10avx);
-
- impl_unary!(f32x4: Sleef_expf4_u10sse4);
- impl_unary!(f32x8: Sleef_expf8_u10avx);
- impl_unary!(f64x2: Sleef_expd2_u10sse4);
- impl_unary!(f64x4: Sleef_expd4_u10avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_expf4_u10sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_expf4_u10sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_expd2_u10sse4);
-
- impl_unary!(f32x4: Sleef_expf4_u10sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_expf4_u10sse4);
- impl_unary!(f64x2: Sleef_expd2_u10sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_expd2_u10sse4);
- } else if #[cfg(target_feature = "sse2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_expf4_u10sse2);
- impl_unary!(f32x16[q => f32x4]: Sleef_expf4_u10sse2);
- impl_unary!(f64x8[q => f64x2]: Sleef_expd2_u10sse2);
-
- impl_unary!(f32x4: Sleef_expf4_u10sse2);
- impl_unary!(f32x8[h => f32x4]: Sleef_expf4_u10sse2);
- impl_unary!(f64x2: Sleef_expd2_u10sse2);
- impl_unary!(f64x4[h => f64x2]: Sleef_expd2_u10sse2);
- } else {
- impl_unary!(f32x2[f32; 2]: exp_f32);
- impl_unary!(f32x16: exp_v16f32);
- impl_unary!(f64x8: exp_v8f64);
-
- impl_unary!(f32x4: exp_v4f32);
- impl_unary!(f32x8: exp_v8f32);
- impl_unary!(f64x2: exp_v2f64);
- impl_unary!(f64x4: exp_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: exp_f32);
- impl_unary!(f32x4: exp_v4f32);
- impl_unary!(f32x8: exp_v8f32);
- impl_unary!(f32x16: exp_v16f32);
-
- impl_unary!(f64x2: exp_v2f64);
- impl_unary!(f64x4: exp_v4f64);
- impl_unary!(f64x8: exp_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/ln.rs b/third_party/rust/packed_simd/src/codegen/math/float/ln.rs
deleted file mode 100644
index a5e38cb40d..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/ln.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-//! Vertical floating-point `ln`
-#![allow(unused)]
-
-// FIXME 64-bit lngle elem vectors mislng
-
-use crate::*;
-
-pub(crate) trait Ln {
- fn ln(self) -> Self;
-}
-
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.log.v2f32"]
- fn ln_v2f32(x: f32x2) -> f32x2;
- #[link_name = "llvm.log.v4f32"]
- fn ln_v4f32(x: f32x4) -> f32x4;
- #[link_name = "llvm.log.v8f32"]
- fn ln_v8f32(x: f32x8) -> f32x8;
- #[link_name = "llvm.log.v16f32"]
- fn ln_v16f32(x: f32x16) -> f32x16;
- /* FIXME 64-bit lngle elem vectors
- #[link_name = "llvm.log.v1f64"]
- fn ln_v1f64(x: f64x1) -> f64x1;
- */
- #[link_name = "llvm.log.v2f64"]
- fn ln_v2f64(x: f64x2) -> f64x2;
- #[link_name = "llvm.log.v4f64"]
- fn ln_v4f64(x: f64x4) -> f64x4;
- #[link_name = "llvm.log.v8f64"]
- fn ln_v8f64(x: f64x8) -> f64x8;
-
- #[link_name = "llvm.log.f32"]
- fn ln_f32(x: f32) -> f32;
- #[link_name = "llvm.log.f64"]
- fn ln_f64(x: f64) -> f64;
-}
-
-gen_unary_impl_table!(Ln, ln);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: ln_f32);
- impl_unary!(f32x4[f32; 4]: ln_f32);
- impl_unary!(f32x8[f32; 8]: ln_f32);
- impl_unary!(f32x16[f32; 16]: ln_f32);
-
- impl_unary!(f64x2[f64; 2]: ln_f64);
- impl_unary!(f64x4[f64; 4]: ln_f64);
- impl_unary!(f64x8[f64; 8]: ln_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_logf4_u10avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_logf8_u10avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_logd4_u10avx2);
-
- impl_unary!(f32x4: Sleef_logf4_u10avx2128);
- impl_unary!(f32x8: Sleef_logf8_u10avx2);
- impl_unary!(f64x2: Sleef_logd2_u10avx2128);
- impl_unary!(f64x4: Sleef_logd4_u10avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_logf4_u10sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_logf8_u10avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_logd4_u10avx);
-
- impl_unary!(f32x4: Sleef_logf4_u10sse4);
- impl_unary!(f32x8: Sleef_logf8_u10avx);
- impl_unary!(f64x2: Sleef_logd2_u10sse4);
- impl_unary!(f64x4: Sleef_logd4_u10avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_logf4_u10sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_logf4_u10sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_logd2_u10sse4);
-
- impl_unary!(f32x4: Sleef_logf4_u10sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_logf4_u10sse4);
- impl_unary!(f64x2: Sleef_logd2_u10sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_logd2_u10sse4);
- } else if #[cfg(target_feature = "sse2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_logf4_u10sse2);
- impl_unary!(f32x16[q => f32x4]: Sleef_logf4_u10sse2);
- impl_unary!(f64x8[q => f64x2]: Sleef_logd2_u10sse2);
-
- impl_unary!(f32x4: Sleef_logf4_u10sse2);
- impl_unary!(f32x8[h => f32x4]: Sleef_logf4_u10sse2);
- impl_unary!(f64x2: Sleef_logd2_u10sse2);
- impl_unary!(f64x4[h => f64x2]: Sleef_logd2_u10sse2);
- } else {
- impl_unary!(f32x2[f32; 2]: ln_f32);
- impl_unary!(f32x16: ln_v16f32);
- impl_unary!(f64x8: ln_v8f64);
-
- impl_unary!(f32x4: ln_v4f32);
- impl_unary!(f32x8: ln_v8f32);
- impl_unary!(f64x2: ln_v2f64);
- impl_unary!(f64x4: ln_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: ln_f32);
- impl_unary!(f32x4: ln_v4f32);
- impl_unary!(f32x8: ln_v8f32);
- impl_unary!(f32x16: ln_v16f32);
-
- impl_unary!(f64x2: ln_v2f64);
- impl_unary!(f64x4: ln_v4f64);
- impl_unary!(f64x8: ln_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/macros.rs b/third_party/rust/packed_simd/src/codegen/math/float/macros.rs
deleted file mode 100644
index 8daee1afe2..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/macros.rs
+++ /dev/null
@@ -1,470 +0,0 @@
-//! Utility macros
-#![allow(unused)]
-
-macro_rules! impl_unary_ {
- // implementation mapping 1:1
- (vec | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self) -> Self {
- unsafe {
- use crate::mem::transmute;
- transmute($fun(transmute(self)))
- }
- }
- }
- };
- // implementation mapping 1:1 for when `$fun` is a generic function
- // like some of the fp math rustc intrinsics (e.g. `fn fun<T>(x: T) -> T`).
- (gen | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self) -> Self {
- unsafe {
- use crate::mem::transmute;
- transmute($fun(self.0))
- }
- }
- }
- };
- (scalar | $trait_id:ident, $trait_method:ident,
- $vec_id:ident, [$sid:ident; $scount:expr], $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self) -> Self {
- unsafe {
- union U {
- vec: $vec_id,
- scalars: [$sid; $scount],
- }
- let mut scalars = U { vec: self }.scalars;
- for i in &mut scalars {
- *i = $fun(*i);
- }
- U { scalars }.vec
- }
- }
- }
- };
- // implementation calling fun twice on each of the vector halves:
- (halves | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vech_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self) -> Self {
- unsafe {
- use crate::mem::transmute;
- union U {
- vec: $vec_id,
- halves: [$vech_id; 2],
- }
-
- let mut halves = U { vec: self }.halves;
-
- *halves.get_unchecked_mut(0) = transmute($fun(transmute(*halves.get_unchecked(0))));
- *halves.get_unchecked_mut(1) = transmute($fun(transmute(*halves.get_unchecked(1))));
-
- U { halves }.vec
- }
- }
- }
- };
- // implementation calling fun four times on each of the vector quarters:
- (quarter | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vecq_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self) -> Self {
- unsafe {
- use crate::mem::transmute;
- union U {
- vec: $vec_id,
- quarters: [$vecq_id; 4],
- }
-
- let mut quarters = U { vec: self }.quarters;
-
- *quarters.get_unchecked_mut(0) = transmute($fun(transmute(*quarters.get_unchecked(0))));
- *quarters.get_unchecked_mut(1) = transmute($fun(transmute(*quarters.get_unchecked(1))));
- *quarters.get_unchecked_mut(2) = transmute($fun(transmute(*quarters.get_unchecked(2))));
- *quarters.get_unchecked_mut(3) = transmute($fun(transmute(*quarters.get_unchecked(3))));
-
- U { quarters }.vec
- }
- }
- }
- };
- // implementation calling fun once on a vector twice as large:
- (twice | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vect_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self) -> Self {
- unsafe {
- use crate::mem::{transmute, uninitialized};
-
- union U {
- vec: [$vec_id; 2],
- twice: $vect_id,
- }
-
- let twice = U { vec: [self, uninitialized()] }.twice;
- let twice = transmute($fun(transmute(twice)));
-
- *(U { twice }.vec.get_unchecked(0))
- }
- }
- }
- };
-}
-
-macro_rules! gen_unary_impl_table {
- ($trait_id:ident, $trait_method:ident) => {
- macro_rules! impl_unary {
- ($vid:ident: $fun:ident) => {
- impl_unary_!(vec | $trait_id, $trait_method, $vid, $fun);
- };
- ($vid:ident[g]: $fun:ident) => {
- impl_unary_!(gen | $trait_id, $trait_method, $vid, $fun);
- };
- ($vid:ident[$sid:ident; $sc:expr]: $fun:ident) => {
- impl_unary_!(scalar | $trait_id, $trait_method, $vid, [$sid; $sc], $fun);
- };
- ($vid:ident[s]: $fun:ident) => {
- impl_unary_!(scalar | $trait_id, $trait_method, $vid, $fun);
- };
- ($vid:ident[h => $vid_h:ident]: $fun:ident) => {
- impl_unary_!(halves | $trait_id, $trait_method, $vid, $vid_h, $fun);
- };
- ($vid:ident[q => $vid_q:ident]: $fun:ident) => {
- impl_unary_!(quarter | $trait_id, $trait_method, $vid, $vid_q, $fun);
- };
- ($vid:ident[t => $vid_t:ident]: $fun:ident) => {
- impl_unary_!(twice | $trait_id, $trait_method, $vid, $vid_t, $fun);
- };
- }
- };
-}
-
-macro_rules! impl_tertiary_ {
- // implementation mapping 1:1
- (vec | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self, z: Self) -> Self {
- unsafe {
- use crate::mem::transmute;
- transmute($fun(transmute(self), transmute(y), transmute(z)))
- }
- }
- }
- };
- (scalar | $trait_id:ident, $trait_method:ident,
- $vec_id:ident, [$sid:ident; $scount:expr], $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self, z: Self) -> Self {
- unsafe {
- union U {
- vec: $vec_id,
- scalars: [$sid; $scount],
- }
- let mut x = U { vec: self }.scalars;
- let y = U { vec: y }.scalars;
- let z = U { vec: z }.scalars;
- for (x, (y, z)) in (&mut scalars).zip(&y).zip(&z) {
- *i = $fun(*i, *y, *z);
- }
- U { vec: x }.vec
- }
- }
- }
- };
- // implementation calling fun twice on each of the vector halves:
- (halves | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vech_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self, z: Self) -> Self {
- unsafe {
- use crate::mem::transmute;
- union U {
- vec: $vec_id,
- halves: [$vech_id; 2],
- }
-
- let mut x_halves = U { vec: self }.halves;
- let y_halves = U { vec: y }.halves;
- let z_halves = U { vec: z }.halves;
-
- *x_halves.get_unchecked_mut(0) = transmute($fun(
- transmute(*x_halves.get_unchecked(0)),
- transmute(*y_halves.get_unchecked(0)),
- transmute(*z_halves.get_unchecked(0)),
- ));
- *x_halves.get_unchecked_mut(1) = transmute($fun(
- transmute(*x_halves.get_unchecked(1)),
- transmute(*y_halves.get_unchecked(1)),
- transmute(*z_halves.get_unchecked(1)),
- ));
-
- U { halves: x_halves }.vec
- }
- }
- }
- };
- // implementation calling fun four times on each of the vector quarters:
- (quarter | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vecq_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self, z: Self) -> Self {
- unsafe {
- use crate::mem::transmute;
- union U {
- vec: $vec_id,
- quarters: [$vecq_id; 4],
- }
-
- let mut x_quarters = U { vec: self }.quarters;
- let y_quarters = U { vec: y }.quarters;
- let z_quarters = U { vec: z }.quarters;
-
- *x_quarters.get_unchecked_mut(0) = transmute($fun(
- transmute(*x_quarters.get_unchecked(0)),
- transmute(*y_quarters.get_unchecked(0)),
- transmute(*z_quarters.get_unchecked(0)),
- ));
-
- *x_quarters.get_unchecked_mut(1) = transmute($fun(
- transmute(*x_quarters.get_unchecked(1)),
- transmute(*y_quarters.get_unchecked(1)),
- transmute(*z_quarters.get_unchecked(1)),
- ));
-
- *x_quarters.get_unchecked_mut(2) = transmute($fun(
- transmute(*x_quarters.get_unchecked(2)),
- transmute(*y_quarters.get_unchecked(2)),
- transmute(*z_quarters.get_unchecked(2)),
- ));
-
- *x_quarters.get_unchecked_mut(3) = transmute($fun(
- transmute(*x_quarters.get_unchecked(3)),
- transmute(*y_quarters.get_unchecked(3)),
- transmute(*z_quarters.get_unchecked(3)),
- ));
-
- U { quarters: x_quarters }.vec
- }
- }
- }
- };
- // implementation calling fun once on a vector twice as large:
- (twice | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vect_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self, z: Self) -> Self {
- unsafe {
- use crate::mem::{transmute, uninitialized};
-
- union U {
- vec: [$vec_id; 2],
- twice: $vect_id,
- }
-
- let x_twice = U { vec: [self, uninitialized()] }.twice;
- let y_twice = U { vec: [y, uninitialized()] }.twice;
- let z_twice = U { vec: [z, uninitialized()] }.twice;
- let twice: $vect_id =
- transmute($fun(transmute(x_twice), transmute(y_twice), transmute(z_twice)));
-
- *(U { twice }.vec.get_unchecked(0))
- }
- }
- }
- };
-}
-
-macro_rules! gen_tertiary_impl_table {
- ($trait_id:ident, $trait_method:ident) => {
- macro_rules! impl_tertiary {
- ($vid:ident: $fun:ident) => {
- impl_tertiary_!(vec | $trait_id, $trait_method, $vid, $fun);
- };
- ($vid:ident[$sid:ident; $sc:expr]: $fun:ident) => {
- impl_tertiary_!(scalar | $trait_id, $trait_method, $vid, [$sid; $sc], $fun);
- };
- ($vid:ident[s]: $fun:ident) => {
- impl_tertiary_!(scalar | $trait_id, $trait_method, $vid, $fun);
- };
- ($vid:ident[h => $vid_h:ident]: $fun:ident) => {
- impl_tertiary_!(halves | $trait_id, $trait_method, $vid, $vid_h, $fun);
- };
- ($vid:ident[q => $vid_q:ident]: $fun:ident) => {
- impl_tertiary_!(quarter | $trait_id, $trait_method, $vid, $vid_q, $fun);
- };
- ($vid:ident[t => $vid_t:ident]: $fun:ident) => {
- impl_tertiary_!(twice | $trait_id, $trait_method, $vid, $vid_t, $fun);
- };
- }
- };
-}
-
-macro_rules! impl_binary_ {
- // implementation mapping 1:1
- (vec | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self) -> Self {
- unsafe {
- use crate::mem::transmute;
- transmute($fun(transmute(self), transmute(y)))
- }
- }
- }
- };
- (scalar | $trait_id:ident, $trait_method:ident,
- $vec_id:ident, [$sid:ident; $scount:expr], $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self) -> Self {
- unsafe {
- union U {
- vec: $vec_id,
- scalars: [$sid; $scount],
- }
- let mut x = U { vec: self }.scalars;
- let y = U { vec: y }.scalars;
- for (x, y) in x.iter_mut().zip(&y) {
- *x = $fun(*x, *y);
- }
- U { scalars: x }.vec
- }
- }
- }
- };
- // implementation calling fun twice on each of the vector halves:
- (halves | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vech_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self) -> Self {
- unsafe {
- use crate::mem::transmute;
- union U {
- vec: $vec_id,
- halves: [$vech_id; 2],
- }
-
- let mut x_halves = U { vec: self }.halves;
- let y_halves = U { vec: y }.halves;
-
- *x_halves.get_unchecked_mut(0) = transmute($fun(
- transmute(*x_halves.get_unchecked(0)),
- transmute(*y_halves.get_unchecked(0)),
- ));
- *x_halves.get_unchecked_mut(1) = transmute($fun(
- transmute(*x_halves.get_unchecked(1)),
- transmute(*y_halves.get_unchecked(1)),
- ));
-
- U { halves: x_halves }.vec
- }
- }
- }
- };
- // implementation calling fun four times on each of the vector quarters:
- (quarter | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vecq_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self) -> Self {
- unsafe {
- use crate::mem::transmute;
- union U {
- vec: $vec_id,
- quarters: [$vecq_id; 4],
- }
-
- let mut x_quarters = U { vec: self }.quarters;
- let y_quarters = U { vec: y }.quarters;
-
- *x_quarters.get_unchecked_mut(0) = transmute($fun(
- transmute(*x_quarters.get_unchecked(0)),
- transmute(*y_quarters.get_unchecked(0)),
- ));
-
- *x_quarters.get_unchecked_mut(1) = transmute($fun(
- transmute(*x_quarters.get_unchecked(1)),
- transmute(*y_quarters.get_unchecked(1)),
- ));
-
- *x_quarters.get_unchecked_mut(2) = transmute($fun(
- transmute(*x_quarters.get_unchecked(2)),
- transmute(*y_quarters.get_unchecked(2)),
- ));
-
- *x_quarters.get_unchecked_mut(3) = transmute($fun(
- transmute(*x_quarters.get_unchecked(3)),
- transmute(*y_quarters.get_unchecked(3)),
- ));
-
- U { quarters: x_quarters }.vec
- }
- }
- }
- };
- // implementation calling fun once on a vector twice as large:
- (twice | $trait_id:ident, $trait_method:ident, $vec_id:ident,
- $vect_id:ident, $fun:ident) => {
- impl $trait_id for $vec_id {
- #[inline]
- fn $trait_method(self, y: Self) -> Self {
- unsafe {
- use crate::mem::{transmute, uninitialized};
-
- union U {
- vec: [$vec_id; 2],
- twice: $vect_id,
- }
-
- let x_twice = U { vec: [self, uninitialized()] }.twice;
- let y_twice = U { vec: [y, uninitialized()] }.twice;
- let twice: $vect_id = transmute($fun(transmute(x_twice), transmute(y_twice)));
-
- *(U { twice }.vec.get_unchecked(0))
- }
- }
- }
- };
-}
-
-macro_rules! gen_binary_impl_table {
- ($trait_id:ident, $trait_method:ident) => {
- macro_rules! impl_binary {
- ($vid:ident: $fun:ident) => {
- impl_binary_!(vec | $trait_id, $trait_method, $vid, $fun);
- };
- ($vid:ident[$sid:ident; $sc:expr]: $fun:ident) => {
- impl_binary_!(scalar | $trait_id, $trait_method, $vid, [$sid; $sc], $fun);
- };
- ($vid:ident[s]: $fun:ident) => {
- impl_binary_!(scalar | $trait_id, $trait_method, $vid, $fun);
- };
- ($vid:ident[h => $vid_h:ident]: $fun:ident) => {
- impl_binary_!(halves | $trait_id, $trait_method, $vid, $vid_h, $fun);
- };
- ($vid:ident[q => $vid_q:ident]: $fun:ident) => {
- impl_binary_!(quarter | $trait_id, $trait_method, $vid, $vid_q, $fun);
- };
- ($vid:ident[t => $vid_t:ident]: $fun:ident) => {
- impl_binary_!(twice | $trait_id, $trait_method, $vid, $vid_t, $fun);
- };
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/mul_add.rs b/third_party/rust/packed_simd/src/codegen/math/float/mul_add.rs
deleted file mode 100644
index d37f30fa86..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/mul_add.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-//! Vertical floating-point `mul_add`
-#![allow(unused)]
-use crate::*;
-
-// FIXME: 64-bit 1 element mul_add
-
-pub(crate) trait MulAdd {
- fn mul_add(self, y: Self, z: Self) -> Self;
-}
-
-#[cfg(not(target_arch = "s390x"))]
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.fma.v2f32"]
- fn fma_v2f32(x: f32x2, y: f32x2, z: f32x2) -> f32x2;
- #[link_name = "llvm.fma.v4f32"]
- fn fma_v4f32(x: f32x4, y: f32x4, z: f32x4) -> f32x4;
- #[link_name = "llvm.fma.v8f32"]
- fn fma_v8f32(x: f32x8, y: f32x8, z: f32x8) -> f32x8;
- #[link_name = "llvm.fma.v16f32"]
- fn fma_v16f32(x: f32x16, y: f32x16, z: f32x16) -> f32x16;
- /* FIXME 64-bit single elem vectors
- #[link_name = "llvm.fma.v1f64"]
- fn fma_v1f64(x: f64x1, y: f64x1, z: f64x1) -> f64x1;
- */
- #[link_name = "llvm.fma.v2f64"]
- fn fma_v2f64(x: f64x2, y: f64x2, z: f64x2) -> f64x2;
- #[link_name = "llvm.fma.v4f64"]
- fn fma_v4f64(x: f64x4, y: f64x4, z: f64x4) -> f64x4;
- #[link_name = "llvm.fma.v8f64"]
- fn fma_v8f64(x: f64x8, y: f64x8, z: f64x8) -> f64x8;
-}
-
-gen_tertiary_impl_table!(MulAdd, mul_add);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- macro_rules! impl_broken {
- ($id:ident) => {
- impl MulAdd for $id {
- #[inline]
- fn mul_add(self, y: Self, z: Self) -> Self {
- self * y + z
- }
- }
- };
- }
-
- impl_broken!(f32x2);
- impl_broken!(f32x4);
- impl_broken!(f32x8);
- impl_broken!(f32x16);
-
- impl_broken!(f64x2);
- impl_broken!(f64x4);
- impl_broken!(f64x8);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_tertiary!(f32x2[t => f32x4]: Sleef_fmaf4_avx2128);
- impl_tertiary!(f32x16[h => f32x8]: Sleef_fmaf8_avx2);
- impl_tertiary!(f64x8[h => f64x4]: Sleef_fmad4_avx2);
-
- impl_tertiary!(f32x4: Sleef_fmaf4_avx2128);
- impl_tertiary!(f32x8: Sleef_fmaf8_avx2);
- impl_tertiary!(f64x2: Sleef_fmad2_avx2128);
- impl_tertiary!(f64x4: Sleef_fmad4_avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_tertiary!(f32x2[t => f32x4]: Sleef_fmaf4_sse4);
- impl_tertiary!(f32x16[h => f32x8]: Sleef_fmaf8_avx);
- impl_tertiary!(f64x8[h => f64x4]: Sleef_fmad4_avx);
-
- impl_tertiary!(f32x4: Sleef_fmaf4_sse4);
- impl_tertiary!(f32x8: Sleef_fmaf8_avx);
- impl_tertiary!(f64x2: Sleef_fmad2_sse4);
- impl_tertiary!(f64x4: Sleef_fmad4_avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_tertiary!(f32x2[t => f32x4]: Sleef_fmaf4_sse4);
- impl_tertiary!(f32x16[q => f32x4]: Sleef_fmaf4_sse4);
- impl_tertiary!(f64x8[q => f64x2]: Sleef_fmad2_sse4);
-
- impl_tertiary!(f32x4: Sleef_fmaf4_sse4);
- impl_tertiary!(f32x8[h => f32x4]: Sleef_fmaf4_sse4);
- impl_tertiary!(f64x2: Sleef_fmad2_sse4);
- impl_tertiary!(f64x4[h => f64x2]: Sleef_fmad2_sse4);
- } else {
- impl_tertiary!(f32x2: fma_v2f32);
- impl_tertiary!(f32x16: fma_v16f32);
- impl_tertiary!(f64x8: fma_v8f64);
-
- impl_tertiary!(f32x4: fma_v4f32);
- impl_tertiary!(f32x8: fma_v8f32);
- impl_tertiary!(f64x2: fma_v2f64);
- impl_tertiary!(f64x4: fma_v4f64);
- }
- }
- } else {
- impl_tertiary!(f32x2: fma_v2f32);
- impl_tertiary!(f32x4: fma_v4f32);
- impl_tertiary!(f32x8: fma_v8f32);
- impl_tertiary!(f32x16: fma_v16f32);
- // impl_tertiary!(f64x1: fma_v1f64); // FIXME 64-bit fmagle elem vectors
- impl_tertiary!(f64x2: fma_v2f64);
- impl_tertiary!(f64x4: fma_v4f64);
- impl_tertiary!(f64x8: fma_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/mul_adde.rs b/third_party/rust/packed_simd/src/codegen/math/float/mul_adde.rs
deleted file mode 100644
index c0baeacec2..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/mul_adde.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-//! Approximation for floating-point `mul_add`
-use crate::*;
-
-// FIXME: 64-bit 1 element mul_adde
-
-pub(crate) trait MulAddE {
- fn mul_adde(self, y: Self, z: Self) -> Self;
-}
-
-#[cfg(not(target_arch = "s390x"))]
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.fmuladd.v2f32"]
- fn fmuladd_v2f32(x: f32x2, y: f32x2, z: f32x2) -> f32x2;
- #[link_name = "llvm.fmuladd.v4f32"]
- fn fmuladd_v4f32(x: f32x4, y: f32x4, z: f32x4) -> f32x4;
- #[link_name = "llvm.fmuladd.v8f32"]
- fn fmuladd_v8f32(x: f32x8, y: f32x8, z: f32x8) -> f32x8;
- #[link_name = "llvm.fmuladd.v16f32"]
- fn fmuladd_v16f32(x: f32x16, y: f32x16, z: f32x16) -> f32x16;
- /* FIXME 64-bit single elem vectors
- #[link_name = "llvm.fmuladd.v1f64"]
- fn fmuladd_v1f64(x: f64x1, y: f64x1, z: f64x1) -> f64x1;
- */
- #[link_name = "llvm.fmuladd.v2f64"]
- fn fmuladd_v2f64(x: f64x2, y: f64x2, z: f64x2) -> f64x2;
- #[link_name = "llvm.fmuladd.v4f64"]
- fn fmuladd_v4f64(x: f64x4, y: f64x4, z: f64x4) -> f64x4;
- #[link_name = "llvm.fmuladd.v8f64"]
- fn fmuladd_v8f64(x: f64x8, y: f64x8, z: f64x8) -> f64x8;
-}
-
-macro_rules! impl_mul_adde {
- ($id:ident : $fn:ident) => {
- impl MulAddE for $id {
- #[inline]
- fn mul_adde(self, y: Self, z: Self) -> Self {
- #[cfg(not(target_arch = "s390x"))]
- {
- use crate::mem::transmute;
- unsafe { transmute($fn(transmute(self), transmute(y), transmute(z))) }
- }
- #[cfg(target_arch = "s390x")]
- {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- self * y + z
- }
- }
- }
- };
-}
-
-impl_mul_adde!(f32x2: fmuladd_v2f32);
-impl_mul_adde!(f32x4: fmuladd_v4f32);
-impl_mul_adde!(f32x8: fmuladd_v8f32);
-impl_mul_adde!(f32x16: fmuladd_v16f32);
-// impl_mul_adde!(f64x1: fma_v1f64); // FIXME 64-bit fmagle elem vectors
-impl_mul_adde!(f64x2: fmuladd_v2f64);
-impl_mul_adde!(f64x4: fmuladd_v4f64);
-impl_mul_adde!(f64x8: fmuladd_v8f64);
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/powf.rs b/third_party/rust/packed_simd/src/codegen/math/float/powf.rs
deleted file mode 100644
index 89ca52e96d..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/powf.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-//! Vertical floating-point `powf`
-#![allow(unused)]
-
-// FIXME 64-bit powfgle elem vectors mispowfg
-
-use crate::*;
-
-pub(crate) trait Powf {
- fn powf(self, x: Self) -> Self;
-}
-
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.pow.v2f32"]
- fn powf_v2f32(x: f32x2, y: f32x2) -> f32x2;
- #[link_name = "llvm.pow.v4f32"]
- fn powf_v4f32(x: f32x4, y: f32x4) -> f32x4;
- #[link_name = "llvm.pow.v8f32"]
- fn powf_v8f32(x: f32x8, y: f32x8) -> f32x8;
- #[link_name = "llvm.pow.v16f32"]
- fn powf_v16f32(x: f32x16, y: f32x16) -> f32x16;
- /* FIXME 64-bit powfgle elem vectors
- #[link_name = "llvm.pow.v1f64"]
- fn powf_v1f64(x: f64x1, y: f64x1) -> f64x1;
- */
- #[link_name = "llvm.pow.v2f64"]
- fn powf_v2f64(x: f64x2, y: f64x2) -> f64x2;
- #[link_name = "llvm.pow.v4f64"]
- fn powf_v4f64(x: f64x4, y: f64x4) -> f64x4;
- #[link_name = "llvm.pow.v8f64"]
- fn powf_v8f64(x: f64x8, y: f64x8) -> f64x8;
-
- #[link_name = "llvm.pow.f32"]
- fn powf_f32(x: f32, y: f32) -> f32;
- #[link_name = "llvm.pow.f64"]
- fn powf_f64(x: f64, y: f64) -> f64;
-}
-
-gen_binary_impl_table!(Powf, powf);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_binary!(f32x2[f32; 2]: powf_f32);
- impl_binary!(f32x4[f32; 4]: powf_f32);
- impl_binary!(f32x8[f32; 8]: powf_f32);
- impl_binary!(f32x16[f32; 16]: powf_f32);
-
- impl_binary!(f64x2[f64; 2]: powf_f64);
- impl_binary!(f64x4[f64; 4]: powf_f64);
- impl_binary!(f64x8[f64; 8]: powf_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_binary!(f32x2[t => f32x4]: Sleef_powf4_u10avx2128);
- impl_binary!(f32x16[h => f32x8]: Sleef_powf8_u10avx2);
- impl_binary!(f64x8[h => f64x4]: Sleef_powd4_u10avx2);
-
- impl_binary!(f32x4: Sleef_powf4_u10avx2128);
- impl_binary!(f32x8: Sleef_powf8_u10avx2);
- impl_binary!(f64x2: Sleef_powd2_u10avx2128);
- impl_binary!(f64x4: Sleef_powd4_u10avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_binary!(f32x2[t => f32x4]: Sleef_powf4_u10sse4);
- impl_binary!(f32x16[h => f32x8]: Sleef_powf8_u10avx);
- impl_binary!(f64x8[h => f64x4]: Sleef_powd4_u10avx);
-
- impl_binary!(f32x4: Sleef_powf4_u10sse4);
- impl_binary!(f32x8: Sleef_powf8_u10avx);
- impl_binary!(f64x2: Sleef_powd2_u10sse4);
- impl_binary!(f64x4: Sleef_powd4_u10avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_binary!(f32x2[t => f32x4]: Sleef_powf4_u10sse4);
- impl_binary!(f32x16[q => f32x4]: Sleef_powf4_u10sse4);
- impl_binary!(f64x8[q => f64x2]: Sleef_powd2_u10sse4);
-
- impl_binary!(f32x4: Sleef_powf4_u10sse4);
- impl_binary!(f32x8[h => f32x4]: Sleef_powf4_u10sse4);
- impl_binary!(f64x2: Sleef_powd2_u10sse4);
- impl_binary!(f64x4[h => f64x2]: Sleef_powd2_u10sse4);
- } else if #[cfg(target_feature = "sse2")] {
- impl_binary!(f32x2[t => f32x4]: Sleef_powf4_u10sse2);
- impl_binary!(f32x16[q => f32x4]: Sleef_powf4_u10sse2);
- impl_binary!(f64x8[q => f64x2]: Sleef_powd2_u10sse2);
-
- impl_binary!(f32x4: Sleef_powf4_u10sse2);
- impl_binary!(f32x8[h => f32x4]: Sleef_powf4_u10sse2);
- impl_binary!(f64x2: Sleef_powd2_u10sse2);
- impl_binary!(f64x4[h => f64x2]: Sleef_powd2_u10sse2);
- } else {
- impl_binary!(f32x2[f32; 2]: powf_f32);
- impl_binary!(f32x4: powf_v4f32);
- impl_binary!(f32x8: powf_v8f32);
- impl_binary!(f32x16: powf_v16f32);
-
- impl_binary!(f64x2: powf_v2f64);
- impl_binary!(f64x4: powf_v4f64);
- impl_binary!(f64x8: powf_v8f64);
- }
- }
- } else {
- impl_binary!(f32x2[f32; 2]: powf_f32);
- impl_binary!(f32x4: powf_v4f32);
- impl_binary!(f32x8: powf_v8f32);
- impl_binary!(f32x16: powf_v16f32);
-
- impl_binary!(f64x2: powf_v2f64);
- impl_binary!(f64x4: powf_v4f64);
- impl_binary!(f64x8: powf_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/sin.rs b/third_party/rust/packed_simd/src/codegen/math/float/sin.rs
deleted file mode 100644
index d881415909..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/sin.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-//! Vertical floating-point `sin`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors sin
-
-use crate::*;
-
-pub(crate) trait Sin {
- fn sin(self) -> Self;
-}
-
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.sin.v2f32"]
- fn sin_v2f32(x: f32x2) -> f32x2;
- #[link_name = "llvm.sin.v4f32"]
- fn sin_v4f32(x: f32x4) -> f32x4;
- #[link_name = "llvm.sin.v8f32"]
- fn sin_v8f32(x: f32x8) -> f32x8;
- #[link_name = "llvm.sin.v16f32"]
- fn sin_v16f32(x: f32x16) -> f32x16;
- /* FIXME 64-bit single elem vectors
- #[link_name = "llvm.sin.v1f64"]
- fn sin_v1f64(x: f64x1) -> f64x1;
- */
- #[link_name = "llvm.sin.v2f64"]
- fn sin_v2f64(x: f64x2) -> f64x2;
- #[link_name = "llvm.sin.v4f64"]
- fn sin_v4f64(x: f64x4) -> f64x4;
- #[link_name = "llvm.sin.v8f64"]
- fn sin_v8f64(x: f64x8) -> f64x8;
-
- #[link_name = "llvm.sin.f32"]
- fn sin_f32(x: f32) -> f32;
- #[link_name = "llvm.sin.f64"]
- fn sin_f64(x: f64) -> f64;
-}
-
-gen_unary_impl_table!(Sin, sin);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: sin_f32);
- impl_unary!(f32x4[f32; 4]: sin_f32);
- impl_unary!(f32x8[f32; 8]: sin_f32);
- impl_unary!(f32x16[f32; 16]: sin_f32);
-
- impl_unary!(f64x2[f64; 2]: sin_f64);
- impl_unary!(f64x4[f64; 4]: sin_f64);
- impl_unary!(f64x8[f64; 8]: sin_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sinf4_u10avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_sinf8_u10avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_sind4_u10avx2);
-
- impl_unary!(f32x4: Sleef_sinf4_u10avx2128);
- impl_unary!(f32x8: Sleef_sinf8_u10avx2);
- impl_unary!(f64x2: Sleef_sind2_u10avx2128);
- impl_unary!(f64x4: Sleef_sind4_u10avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sinf4_u10sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_sinf8_u10avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_sind4_u10avx);
-
- impl_unary!(f32x4: Sleef_sinf4_u10sse4);
- impl_unary!(f32x8: Sleef_sinf8_u10avx);
- impl_unary!(f64x2: Sleef_sind2_u10sse4);
- impl_unary!(f64x4: Sleef_sind4_u10avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sinf4_u10sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_sinf4_u10sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_sind2_u10sse4);
-
- impl_unary!(f32x4: Sleef_sinf4_u10sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_sinf4_u10sse4);
- impl_unary!(f64x2: Sleef_sind2_u10sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_sind2_u10sse4);
- } else {
- impl_unary!(f32x2[f32; 2]: sin_f32);
- impl_unary!(f32x16: sin_v16f32);
- impl_unary!(f64x8: sin_v8f64);
-
- impl_unary!(f32x4: sin_v4f32);
- impl_unary!(f32x8: sin_v8f32);
- impl_unary!(f64x2: sin_v2f64);
- impl_unary!(f64x4: sin_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: sin_f32);
- impl_unary!(f32x4: sin_v4f32);
- impl_unary!(f32x8: sin_v8f32);
- impl_unary!(f32x16: sin_v16f32);
-
- impl_unary!(f64x2: sin_v2f64);
- impl_unary!(f64x4: sin_v4f64);
- impl_unary!(f64x8: sin_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/sin_cos_pi.rs b/third_party/rust/packed_simd/src/codegen/math/float/sin_cos_pi.rs
deleted file mode 100644
index b283d11111..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/sin_cos_pi.rs
+++ /dev/null
@@ -1,188 +0,0 @@
-//! Vertical floating-point `sin_cos`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors sin_cos
-
-use crate::*;
-
-pub(crate) trait SinCosPi: Sized {
- type Output;
- fn sin_cos_pi(self) -> Self::Output;
-}
-
-macro_rules! impl_def {
- ($vid:ident, $PI:path) => {
- impl SinCosPi for $vid {
- type Output = (Self, Self);
- #[inline]
- fn sin_cos_pi(self) -> Self::Output {
- let v = self * Self::splat($PI);
- (v.sin(), v.cos())
- }
- }
- };
-}
-
-macro_rules! impl_def32 {
- ($vid:ident) => {
- impl_def!($vid, crate::f32::consts::PI);
- };
-}
-macro_rules! impl_def64 {
- ($vid:ident) => {
- impl_def!($vid, crate::f64::consts::PI);
- };
-}
-
-macro_rules! impl_unary_t {
- ($vid:ident: $fun:ident) => {
- impl SinCosPi for $vid {
- type Output = (Self, Self);
- fn sin_cos_pi(self) -> Self::Output {
- unsafe {
- use crate::mem::transmute;
- transmute($fun(transmute(self)))
- }
- }
- }
- };
- ($vid:ident[t => $vid_t:ident]: $fun:ident) => {
- impl SinCosPi for $vid {
- type Output = (Self, Self);
- fn sin_cos_pi(self) -> Self::Output {
- unsafe {
- use crate::mem::{transmute, uninitialized};
-
- union U {
- vec: [$vid; 2],
- twice: $vid_t,
- }
-
- let twice = U { vec: [self, uninitialized()] }.twice;
- let twice = transmute($fun(transmute(twice)));
-
- union R {
- twice: ($vid_t, $vid_t),
- vecs: ([$vid; 2], [$vid; 2]),
- }
- let r = R { twice }.vecs;
- (*r.0.get_unchecked(0), *r.0.get_unchecked(1))
- }
- }
- }
- };
- ($vid:ident[h => $vid_h:ident]: $fun:ident) => {
- impl SinCosPi for $vid {
- type Output = (Self, Self);
- fn sin_cos_pi(self) -> Self::Output {
- unsafe {
- use crate::mem::transmute;
-
- union U {
- vec: $vid,
- halves: [$vid_h; 2],
- }
-
- let halves = U { vec: self }.halves;
-
- let res_0: ($vid_h, $vid_h) = transmute($fun(transmute(*halves.get_unchecked(0))));
- let res_1: ($vid_h, $vid_h) = transmute($fun(transmute(*halves.get_unchecked(1))));
-
- union R {
- result: ($vid, $vid),
- halves: ([$vid_h; 2], [$vid_h; 2]),
- }
- R { halves: ([res_0.0, res_1.0], [res_0.1, res_1.1]) }.result
- }
- }
- }
- };
- ($vid:ident[q => $vid_q:ident]: $fun:ident) => {
- impl SinCosPi for $vid {
- type Output = (Self, Self);
- fn sin_cos_pi(self) -> Self::Output {
- unsafe {
- use crate::mem::transmute;
-
- union U {
- vec: $vid,
- quarters: [$vid_q; 4],
- }
-
- let quarters = U { vec: self }.quarters;
-
- let res_0: ($vid_q, $vid_q) = transmute($fun(transmute(*quarters.get_unchecked(0))));
- let res_1: ($vid_q, $vid_q) = transmute($fun(transmute(*quarters.get_unchecked(1))));
- let res_2: ($vid_q, $vid_q) = transmute($fun(transmute(*quarters.get_unchecked(2))));
- let res_3: ($vid_q, $vid_q) = transmute($fun(transmute(*quarters.get_unchecked(3))));
-
- union R {
- result: ($vid, $vid),
- quarters: ([$vid_q; 4], [$vid_q; 4]),
- }
- R {
- quarters: (
- [res_0.0, res_1.0, res_2.0, res_3.0],
- [res_0.1, res_1.1, res_2.1, res_3.1],
- ),
- }
- .result
- }
- }
- }
- };
-}
-
-cfg_if! {
- if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary_t!(f32x2[t => f32x4]: Sleef_sincospif4_u05avx2128);
- impl_unary_t!(f32x16[h => f32x8]: Sleef_sincospif8_u05avx2);
- impl_unary_t!(f64x8[h => f64x4]: Sleef_sincospid4_u05avx2);
-
- impl_unary_t!(f32x4: Sleef_sincospif4_u05avx2128);
- impl_unary_t!(f32x8: Sleef_sincospif8_u05avx2);
- impl_unary_t!(f64x2: Sleef_sincospid2_u05avx2128);
- impl_unary_t!(f64x4: Sleef_sincospid4_u05avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary_t!(f32x2[t => f32x4]: Sleef_sincospif4_u05sse4);
- impl_unary_t!(f32x16[h => f32x8]: Sleef_sincospif8_u05avx);
- impl_unary_t!(f64x8[h => f64x4]: Sleef_sincospid4_u05avx);
-
- impl_unary_t!(f32x4: Sleef_sincospif4_u05sse4);
- impl_unary_t!(f32x8: Sleef_sincospif8_u05avx);
- impl_unary_t!(f64x2: Sleef_sincospid2_u05sse4);
- impl_unary_t!(f64x4: Sleef_sincospid4_u05avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary_t!(f32x2[t => f32x4]: Sleef_sincospif4_u05sse4);
- impl_unary_t!(f32x16[q => f32x4]: Sleef_sincospif4_u05sse4);
- impl_unary_t!(f64x8[q => f64x2]: Sleef_sincospid2_u05sse4);
-
- impl_unary_t!(f32x4: Sleef_sincospif4_u05sse4);
- impl_unary_t!(f32x8[h => f32x4]: Sleef_sincospif4_u05sse4);
- impl_unary_t!(f64x2: Sleef_sincospid2_u05sse4);
- impl_unary_t!(f64x4[h => f64x2]: Sleef_sincospid2_u05sse4);
- } else {
- impl_def32!(f32x2);
- impl_def32!(f32x4);
- impl_def32!(f32x8);
- impl_def32!(f32x16);
-
- impl_def64!(f64x2);
- impl_def64!(f64x4);
- impl_def64!(f64x8);
- }
- }
- } else {
- impl_def32!(f32x2);
- impl_def32!(f32x4);
- impl_def32!(f32x8);
- impl_def32!(f32x16);
-
- impl_def64!(f64x2);
- impl_def64!(f64x4);
- impl_def64!(f64x8);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/sin_pi.rs b/third_party/rust/packed_simd/src/codegen/math/float/sin_pi.rs
deleted file mode 100644
index 0c8f6bb120..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/sin_pi.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-//! Vertical floating-point `sin_pi`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors sin_pi
-
-use crate::*;
-
-pub(crate) trait SinPi {
- fn sin_pi(self) -> Self;
-}
-
-gen_unary_impl_table!(SinPi, sin_pi);
-
-macro_rules! impl_def {
- ($vid:ident, $PI:path) => {
- impl SinPi for $vid {
- #[inline]
- fn sin_pi(self) -> Self {
- (self * Self::splat($PI)).sin()
- }
- }
- };
-}
-macro_rules! impl_def32 {
- ($vid:ident) => {
- impl_def!($vid, crate::f32::consts::PI);
- };
-}
-macro_rules! impl_def64 {
- ($vid:ident) => {
- impl_def!($vid, crate::f64::consts::PI);
- };
-}
-
-cfg_if! {
- if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sinpif4_u05avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_sinpif8_u05avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_sinpid4_u05avx2);
-
- impl_unary!(f32x4: Sleef_sinpif4_u05avx2128);
- impl_unary!(f32x8: Sleef_sinpif8_u05avx2);
- impl_unary!(f64x2: Sleef_sinpid2_u05avx2128);
- impl_unary!(f64x4: Sleef_sinpid4_u05avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sinpif4_u05sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_sinpif8_u05avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_sinpid4_u05avx);
-
- impl_unary!(f32x4: Sleef_sinpif4_u05sse4);
- impl_unary!(f32x8: Sleef_sinpif8_u05avx);
- impl_unary!(f64x2: Sleef_sinpid2_u05sse4);
- impl_unary!(f64x4: Sleef_sinpid4_u05avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sinpif4_u05sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_sinpif4_u05sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_sinpid2_u05sse4);
-
- impl_unary!(f32x4: Sleef_sinpif4_u05sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_sinpif4_u05sse4);
- impl_unary!(f64x2: Sleef_sinpid2_u05sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_sinpid2_u05sse4);
- } else {
- impl_def32!(f32x2);
- impl_def32!(f32x4);
- impl_def32!(f32x8);
- impl_def32!(f32x16);
-
- impl_def64!(f64x2);
- impl_def64!(f64x4);
- impl_def64!(f64x8);
- }
- }
- } else {
- impl_def32!(f32x2);
- impl_def32!(f32x4);
- impl_def32!(f32x8);
- impl_def32!(f32x16);
-
- impl_def64!(f64x2);
- impl_def64!(f64x4);
- impl_def64!(f64x8);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/sqrt.rs b/third_party/rust/packed_simd/src/codegen/math/float/sqrt.rs
deleted file mode 100644
index 67bb0a2a9c..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/sqrt.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-//! Vertical floating-point `sqrt`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors sqrt
-
-use crate::*;
-
-pub(crate) trait Sqrt {
- fn sqrt(self) -> Self;
-}
-
-#[allow(improper_ctypes)]
-extern "C" {
- #[link_name = "llvm.sqrt.v2f32"]
- fn sqrt_v2f32(x: f32x2) -> f32x2;
- #[link_name = "llvm.sqrt.v4f32"]
- fn sqrt_v4f32(x: f32x4) -> f32x4;
- #[link_name = "llvm.sqrt.v8f32"]
- fn sqrt_v8f32(x: f32x8) -> f32x8;
- #[link_name = "llvm.sqrt.v16f32"]
- fn sqrt_v16f32(x: f32x16) -> f32x16;
- /* FIXME 64-bit sqrtgle elem vectors
- #[link_name = "llvm.sqrt.v1f64"]
- fn sqrt_v1f64(x: f64x1) -> f64x1;
- */
- #[link_name = "llvm.sqrt.v2f64"]
- fn sqrt_v2f64(x: f64x2) -> f64x2;
- #[link_name = "llvm.sqrt.v4f64"]
- fn sqrt_v4f64(x: f64x4) -> f64x4;
- #[link_name = "llvm.sqrt.v8f64"]
- fn sqrt_v8f64(x: f64x8) -> f64x8;
-
- #[link_name = "llvm.sqrt.f32"]
- fn sqrt_f32(x: f32) -> f32;
- #[link_name = "llvm.sqrt.f64"]
- fn sqrt_f64(x: f64) -> f64;
-}
-
-gen_unary_impl_table!(Sqrt, sqrt);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: sqrt_f32);
- impl_unary!(f32x4[f32; 4]: sqrt_f32);
- impl_unary!(f32x8[f32; 8]: sqrt_f32);
- impl_unary!(f32x16[f32; 16]: sqrt_f32);
-
- impl_unary!(f64x2[f64; 2]: sqrt_f64);
- impl_unary!(f64x4[f64; 4]: sqrt_f64);
- impl_unary!(f64x8[f64; 8]: sqrt_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sqrtf4_avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_sqrtf8_avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_sqrtd4_avx2);
-
- impl_unary!(f32x4: Sleef_sqrtf4_avx2128);
- impl_unary!(f32x8: Sleef_sqrtf8_avx2);
- impl_unary!(f64x2: Sleef_sqrtd2_avx2128);
- impl_unary!(f64x4: Sleef_sqrtd4_avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sqrtf4_sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_sqrtf8_avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_sqrtd4_avx);
-
- impl_unary!(f32x4: Sleef_sqrtf4_sse4);
- impl_unary!(f32x8: Sleef_sqrtf8_avx);
- impl_unary!(f64x2: Sleef_sqrtd2_sse4);
- impl_unary!(f64x4: Sleef_sqrtd4_avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sqrtf4_sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_sqrtf4_sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_sqrtd2_sse4);
-
- impl_unary!(f32x4: Sleef_sqrtf4_sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_sqrtf4_sse4);
- impl_unary!(f64x2: Sleef_sqrtd2_sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_sqrtd2_sse4);
- } else {
- impl_unary!(f32x2[f32; 2]: sqrt_f32);
- impl_unary!(f32x16: sqrt_v16f32);
- impl_unary!(f64x8: sqrt_v8f64);
-
- impl_unary!(f32x4: sqrt_v4f32);
- impl_unary!(f32x8: sqrt_v8f32);
- impl_unary!(f64x2: sqrt_v2f64);
- impl_unary!(f64x4: sqrt_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: sqrt_f32);
- impl_unary!(f32x4: sqrt_v4f32);
- impl_unary!(f32x8: sqrt_v8f32);
- impl_unary!(f32x16: sqrt_v16f32);
-
- impl_unary!(f64x2: sqrt_v2f64);
- impl_unary!(f64x4: sqrt_v4f64);
- impl_unary!(f64x8: sqrt_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/sqrte.rs b/third_party/rust/packed_simd/src/codegen/math/float/sqrte.rs
deleted file mode 100644
index 58a1de1f40..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/sqrte.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! Vertical floating-point `sqrt`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors sqrte
-
-use crate::llvm::simd_fsqrt;
-use crate::*;
-
-pub(crate) trait Sqrte {
- fn sqrte(self) -> Self;
-}
-
-gen_unary_impl_table!(Sqrte, sqrte);
-
-cfg_if! {
- if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sqrtf4_u35avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_sqrtf8_u35avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_sqrtd4_u35avx2);
-
- impl_unary!(f32x4: Sleef_sqrtf4_u35avx2128);
- impl_unary!(f32x8: Sleef_sqrtf8_u35avx2);
- impl_unary!(f64x2: Sleef_sqrtd2_u35avx2128);
- impl_unary!(f64x4: Sleef_sqrtd4_u35avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sqrtf4_u35sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_sqrtf8_u35avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_sqrtd4_u35avx);
-
- impl_unary!(f32x4: Sleef_sqrtf4_u35sse4);
- impl_unary!(f32x8: Sleef_sqrtf8_u35avx);
- impl_unary!(f64x2: Sleef_sqrtd2_u35sse4);
- impl_unary!(f64x4: Sleef_sqrtd4_u35avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_sqrtf4_u35sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_sqrtf4_u35sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_sqrtd2_u35sse4);
-
- impl_unary!(f32x4: Sleef_sqrtf4_u35sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_sqrtf4_u35sse4);
- impl_unary!(f64x2: Sleef_sqrtd2_u35sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_sqrtd2_u35sse4);
- } else {
- impl_unary!(f32x2[g]: simd_fsqrt);
- impl_unary!(f32x16[g]: simd_fsqrt);
- impl_unary!(f64x8[g]: simd_fsqrt);
-
- impl_unary!(f32x4[g]: simd_fsqrt);
- impl_unary!(f32x8[g]: simd_fsqrt);
- impl_unary!(f64x2[g]: simd_fsqrt);
- impl_unary!(f64x4[g]: simd_fsqrt);
- }
- }
- } else {
- impl_unary!(f32x2[g]: simd_fsqrt);
- impl_unary!(f32x4[g]: simd_fsqrt);
- impl_unary!(f32x8[g]: simd_fsqrt);
- impl_unary!(f32x16[g]: simd_fsqrt);
-
- impl_unary!(f64x2[g]: simd_fsqrt);
- impl_unary!(f64x4[g]: simd_fsqrt);
- impl_unary!(f64x8[g]: simd_fsqrt);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/tanh.rs b/third_party/rust/packed_simd/src/codegen/math/float/tanh.rs
deleted file mode 100644
index 4243b0d886..0000000000
--- a/third_party/rust/packed_simd/src/codegen/math/float/tanh.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-//! Vertical floating-point `tanh`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors tanh
-
-#[cfg(not(feature = "std"))]
-use num_traits::Float;
-
-use crate::*;
-
-pub(crate) trait Tanh {
- fn tanh(self) -> Self;
-}
-
-macro_rules! define_tanh {
- ($name:ident, $basetype:ty, $simdtype:ty, $lanes:expr, $trait:path) => {
- fn $name(x: $simdtype) -> $simdtype {
- use core::intrinsics::transmute;
- let mut buf: [$basetype; $lanes] = unsafe { transmute(x) };
- for elem in &mut buf {
- *elem = <$basetype as $trait>::tanh(*elem);
- }
- unsafe { transmute(buf) }
- }
- };
-
- (f32 => $name:ident, $type:ty, $lanes:expr) => {
- define_tanh!($name, f32, $type, $lanes, Float);
- };
-
- (f64 => $name:ident, $type:ty, $lanes:expr) => {
- define_tanh!($name, f64, $type, $lanes, Float);
- };
-}
-
-// llvm does not seem to expose the hyperbolic versions of trigonometric
-// functions; we thus call the classical rust versions on all of them (which
-// stem from cmath).
-define_tanh!(f32 => tanh_v2f32, f32x2, 2);
-define_tanh!(f32 => tanh_v4f32, f32x4, 4);
-define_tanh!(f32 => tanh_v8f32, f32x8, 8);
-define_tanh!(f32 => tanh_v16f32, f32x16, 16);
-
-define_tanh!(f64 => tanh_v2f64, f64x2, 2);
-define_tanh!(f64 => tanh_v4f64, f64x4, 4);
-define_tanh!(f64 => tanh_v8f64, f64x8, 8);
-
-fn tanh_f32(x: f32) -> f32 {
- Float::tanh(x)
-}
-
-fn tanh_f64(x: f64) -> f64 {
- Float::tanh(x)
-}
-
-gen_unary_impl_table!(Tanh, tanh);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: tanh_f32);
- impl_unary!(f32x4[f32; 4]: tanh_f32);
- impl_unary!(f32x8[f32; 8]: tanh_f32);
- impl_unary!(f32x16[f32; 16]: tanh_f32);
-
- impl_unary!(f64x2[f64; 2]: tanh_f64);
- impl_unary!(f64x4[f64; 4]: tanh_f64);
- impl_unary!(f64x8[f64; 8]: tanh_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_tanhf8_u10avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_tanhd4_u10avx2);
-
- impl_unary!(f32x4: Sleef_tanhf4_u10avx2128);
- impl_unary!(f32x8: Sleef_tanhf8_u10avx2);
- impl_unary!(f64x2: Sleef_tanhd2_u10avx2128);
- impl_unary!(f64x4: Sleef_tanhd4_u10avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_tanhf8_u10avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_tanhd4_u10avx);
-
- impl_unary!(f32x4: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x8: Sleef_tanhf8_u10avx);
- impl_unary!(f64x2: Sleef_tanhd2_u10sse4);
- impl_unary!(f64x4: Sleef_tanhd4_u10avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_tanhd2_u10sse4);
-
- impl_unary!(f32x4: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f64x2: Sleef_tanhd2_u10sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_tanhd2_u10sse4);
- } else {
- impl_unary!(f32x2[f32; 2]: tanh_f32);
- impl_unary!(f32x16: tanh_v16f32);
- impl_unary!(f64x8: tanh_v8f64);
-
- impl_unary!(f32x4: tanh_v4f32);
- impl_unary!(f32x8: tanh_v8f32);
- impl_unary!(f64x2: tanh_v2f64);
- impl_unary!(f64x4: tanh_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: tanh_f32);
- impl_unary!(f32x4: tanh_v4f32);
- impl_unary!(f32x8: tanh_v8f32);
- impl_unary!(f32x16: tanh_v16f32);
-
- impl_unary!(f64x2: tanh_v2f64);
- impl_unary!(f64x4: tanh_v4f64);
- impl_unary!(f64x8: tanh_v8f64);
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/pointer_sized_int.rs b/third_party/rust/packed_simd/src/codegen/pointer_sized_int.rs
deleted file mode 100644
index 55cbc297aa..0000000000
--- a/third_party/rust/packed_simd/src/codegen/pointer_sized_int.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//! Provides `isize` and `usize`
-
-use cfg_if::cfg_if;
-
-cfg_if! {
- if #[cfg(target_pointer_width = "8")] {
- pub(crate) type isize_ = i8;
- pub(crate) type usize_ = u8;
- } else if #[cfg(target_pointer_width = "16")] {
- pub(crate) type isize_ = i16;
- pub(crate) type usize_ = u16;
- } else if #[cfg(target_pointer_width = "32")] {
- pub(crate) type isize_ = i32;
- pub(crate) type usize_ = u32;
-
- } else if #[cfg(target_pointer_width = "64")] {
- pub(crate) type isize_ = i64;
- pub(crate) type usize_ = u64;
- } else if #[cfg(target_pointer_width = "64")] {
- pub(crate) type isize_ = i64;
- pub(crate) type usize_ = u64;
- } else if #[cfg(target_pointer_width = "128")] {
- pub(crate) type isize_ = i128;
- pub(crate) type usize_ = u128;
- } else {
- compile_error!("unsupported target_pointer_width");
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions.rs b/third_party/rust/packed_simd/src/codegen/reductions.rs
deleted file mode 100644
index 302ca6d88f..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub(crate) mod mask;
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask.rs
deleted file mode 100644
index a78bcc5632..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-//! Code generation workaround for `all()` mask horizontal reduction.
-//!
-//! Works around [LLVM bug 36702].
-//!
-//! [LLVM bug 36702]: https://bugs.llvm.org/show_bug.cgi?id=36702
-#![allow(unused_macros)]
-
-use crate::*;
-
-pub(crate) trait All: crate::marker::Sized {
- unsafe fn all(self) -> bool;
-}
-
-pub(crate) trait Any: crate::marker::Sized {
- unsafe fn any(self) -> bool;
-}
-
-#[macro_use]
-mod fallback_impl;
-
-cfg_if! {
- if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
- #[macro_use]
- mod x86;
- } else if #[cfg(all(target_arch = "arm", target_feature = "v7",
- target_feature = "neon",
- any(feature = "core_arch", libcore_neon)))] {
- #[macro_use]
- mod arm;
- } else if #[cfg(all(target_arch = "aarch64", target_feature = "neon"))] {
- #[macro_use]
- mod aarch64;
- } else {
- #[macro_use]
- mod fallback;
- }
-}
-
-impl_mask_reductions!(m8x2);
-impl_mask_reductions!(m8x4);
-impl_mask_reductions!(m8x8);
-impl_mask_reductions!(m8x16);
-impl_mask_reductions!(m8x32);
-impl_mask_reductions!(m8x64);
-
-impl_mask_reductions!(m16x2);
-impl_mask_reductions!(m16x4);
-impl_mask_reductions!(m16x8);
-impl_mask_reductions!(m16x16);
-impl_mask_reductions!(m16x32);
-
-impl_mask_reductions!(m32x2);
-impl_mask_reductions!(m32x4);
-impl_mask_reductions!(m32x8);
-impl_mask_reductions!(m32x16);
-
-// FIXME: 64-bit single element vector
-// impl_mask_reductions!(m64x1);
-impl_mask_reductions!(m64x2);
-impl_mask_reductions!(m64x4);
-impl_mask_reductions!(m64x8);
-
-impl_mask_reductions!(m128x1);
-impl_mask_reductions!(m128x2);
-impl_mask_reductions!(m128x4);
-
-impl_mask_reductions!(msizex2);
-impl_mask_reductions!(msizex4);
-impl_mask_reductions!(msizex8);
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/aarch64.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/aarch64.rs
deleted file mode 100644
index b2db52c891..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/aarch64.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-//! Mask reductions implementation for `aarch64` targets
-
-/// 128-bit wide vectors
-macro_rules! aarch64_128_neon_impl {
- ($id:ident, $vmin:ident, $vmax:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "neon")]
- unsafe fn all(self) -> bool {
- use crate::arch::aarch64::$vmin;
- $vmin(crate::mem::transmute(self)) != 0
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "neon")]
- unsafe fn any(self) -> bool {
- use crate::arch::aarch64::$vmax;
- $vmax(crate::mem::transmute(self)) != 0
- }
- }
- };
-}
-
-/// 64-bit wide vectors
-macro_rules! aarch64_64_neon_impl {
- ($id:ident, $vec128:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "neon")]
- unsafe fn all(self) -> bool {
- // Duplicates the 64-bit vector into a 128-bit one and
- // calls all on that.
- union U {
- halves: ($id, $id),
- vec: $vec128,
- }
- U { halves: (self, self) }.vec.all()
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "neon")]
- unsafe fn any(self) -> bool {
- union U {
- halves: ($id, $id),
- vec: $vec128,
- }
- U { halves: (self, self) }.vec.any()
- }
- }
- };
-}
-
-/// Mask reduction implementation for `aarch64` targets
-macro_rules! impl_mask_reductions {
- // 64-bit wide masks
- (m8x8) => {
- aarch64_64_neon_impl!(m8x8, m8x16);
- };
- (m16x4) => {
- aarch64_64_neon_impl!(m16x4, m16x8);
- };
- (m32x2) => {
- aarch64_64_neon_impl!(m32x2, m32x4);
- };
- // 128-bit wide masks
- (m8x16) => {
- aarch64_128_neon_impl!(m8x16, vminvq_u8, vmaxvq_u8);
- };
- (m16x8) => {
- aarch64_128_neon_impl!(m16x8, vminvq_u16, vmaxvq_u16);
- };
- (m32x4) => {
- aarch64_128_neon_impl!(m32x4, vminvq_u32, vmaxvq_u32);
- };
- // Fallback to LLVM's default code-generation:
- ($id:ident) => {
- fallback_impl!($id);
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/arm.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/arm.rs
deleted file mode 100644
index 41c3cbc58a..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/arm.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-//! Mask reductions implementation for `arm` targets
-
-/// Implementation for ARM + v7 + NEON for 64-bit or 128-bit wide vectors with
-/// more than two elements.
-macro_rules! arm_128_v7_neon_impl {
- ($id:ident, $half:ident, $vpmin:ident, $vpmax:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "v7,neon")]
- unsafe fn all(self) -> bool {
- use crate::arch::arm::$vpmin;
- use crate::mem::transmute;
- union U {
- halves: ($half, $half),
- vec: $id,
- }
- let halves = U { vec: self }.halves;
- let h: $half = transmute($vpmin(transmute(halves.0), transmute(halves.1)));
- h.all()
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "v7,neon")]
- unsafe fn any(self) -> bool {
- use crate::arch::arm::$vpmax;
- use crate::mem::transmute;
- union U {
- halves: ($half, $half),
- vec: $id,
- }
- let halves = U { vec: self }.halves;
- let h: $half = transmute($vpmax(transmute(halves.0), transmute(halves.1)));
- h.any()
- }
- }
- };
-}
-
-/// Mask reduction implementation for `arm` targets
-macro_rules! impl_mask_reductions {
- // 128-bit wide masks
- (m8x16) => {
- arm_128_v7_neon_impl!(m8x16, m8x8, vpmin_u8, vpmax_u8);
- };
- (m16x8) => {
- arm_128_v7_neon_impl!(m16x8, m16x4, vpmin_u16, vpmax_u16);
- };
- (m32x4) => {
- arm_128_v7_neon_impl!(m32x4, m32x2, vpmin_u32, vpmax_u32);
- };
- // Fallback to LLVM's default code-generation:
- ($id:ident) => {
- fallback_impl!($id);
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/fallback.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/fallback.rs
deleted file mode 100644
index 4c377a6878..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/fallback.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//! Default mask reduction implementations.
-
-/// Default mask reduction implementation
-macro_rules! impl_mask_reductions {
- ($id:ident) => {
- fallback_impl!($id);
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/fallback_impl.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/fallback_impl.rs
deleted file mode 100644
index 0d246e2fda..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/fallback_impl.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-//! Default implementation of a mask reduction for any target.
-
-macro_rules! fallback_to_other_impl {
- ($id:ident, $other:ident) => {
- impl All for $id {
- #[inline]
- unsafe fn all(self) -> bool {
- let m: $other = crate::mem::transmute(self);
- m.all()
- }
- }
- impl Any for $id {
- #[inline]
- unsafe fn any(self) -> bool {
- let m: $other = crate::mem::transmute(self);
- m.any()
- }
- }
- };
-}
-
-/// Fallback implementation.
-macro_rules! fallback_impl {
- // 16-bit wide masks:
- (m8x2) => {
- impl All for m8x2 {
- #[inline]
- unsafe fn all(self) -> bool {
- let i: u16 = crate::mem::transmute(self);
- i == u16::max_value()
- }
- }
- impl Any for m8x2 {
- #[inline]
- unsafe fn any(self) -> bool {
- let i: u16 = crate::mem::transmute(self);
- i != 0
- }
- }
- };
- // 32-bit wide masks
- (m8x4) => {
- impl All for m8x4 {
- #[inline]
- unsafe fn all(self) -> bool {
- let i: u32 = crate::mem::transmute(self);
- i == u32::max_value()
- }
- }
- impl Any for m8x4 {
- #[inline]
- unsafe fn any(self) -> bool {
- let i: u32 = crate::mem::transmute(self);
- i != 0
- }
- }
- };
- (m16x2) => {
- fallback_to_other_impl!(m16x2, m8x4);
- };
- // 64-bit wide masks:
- (m8x8) => {
- impl All for m8x8 {
- #[inline]
- unsafe fn all(self) -> bool {
- let i: u64 = crate::mem::transmute(self);
- i == u64::max_value()
- }
- }
- impl Any for m8x8 {
- #[inline]
- unsafe fn any(self) -> bool {
- let i: u64 = crate::mem::transmute(self);
- i != 0
- }
- }
- };
- (m16x4) => {
- fallback_to_other_impl!(m16x4, m8x8);
- };
- (m32x2) => {
- fallback_to_other_impl!(m32x2, m16x4);
- };
- // FIXME: 64x1 maxk
- // 128-bit wide masks:
- (m8x16) => {
- impl All for m8x16 {
- #[inline]
- unsafe fn all(self) -> bool {
- let i: u128 = crate::mem::transmute(self);
- i == u128::max_value()
- }
- }
- impl Any for m8x16 {
- #[inline]
- unsafe fn any(self) -> bool {
- let i: u128 = crate::mem::transmute(self);
- i != 0
- }
- }
- };
- (m16x8) => {
- fallback_to_other_impl!(m16x8, m8x16);
- };
- (m32x4) => {
- fallback_to_other_impl!(m32x4, m16x8);
- };
- (m64x2) => {
- fallback_to_other_impl!(m64x2, m32x4);
- };
- (m128x1) => {
- fallback_to_other_impl!(m128x1, m64x2);
- };
- // 256-bit wide masks
- (m8x32) => {
- impl All for m8x32 {
- #[inline]
- unsafe fn all(self) -> bool {
- let i: [u128; 2] = crate::mem::transmute(self);
- let o: [u128; 2] = [u128::max_value(); 2];
- i == o
- }
- }
- impl Any for m8x32 {
- #[inline]
- unsafe fn any(self) -> bool {
- let i: [u128; 2] = crate::mem::transmute(self);
- let o: [u128; 2] = [0; 2];
- i != o
- }
- }
- };
- (m16x16) => {
- fallback_to_other_impl!(m16x16, m8x32);
- };
- (m32x8) => {
- fallback_to_other_impl!(m32x8, m16x16);
- };
- (m64x4) => {
- fallback_to_other_impl!(m64x4, m32x8);
- };
- (m128x2) => {
- fallback_to_other_impl!(m128x2, m64x4);
- };
- // 512-bit wide masks
- (m8x64) => {
- impl All for m8x64 {
- #[inline]
- unsafe fn all(self) -> bool {
- let i: [u128; 4] = crate::mem::transmute(self);
- let o: [u128; 4] = [u128::max_value(); 4];
- i == o
- }
- }
- impl Any for m8x64 {
- #[inline]
- unsafe fn any(self) -> bool {
- let i: [u128; 4] = crate::mem::transmute(self);
- let o: [u128; 4] = [0; 4];
- i != o
- }
- }
- };
- (m16x32) => {
- fallback_to_other_impl!(m16x32, m8x64);
- };
- (m32x16) => {
- fallback_to_other_impl!(m32x16, m16x32);
- };
- (m64x8) => {
- fallback_to_other_impl!(m64x8, m32x16);
- };
- (m128x4) => {
- fallback_to_other_impl!(m128x4, m64x8);
- };
- // Masks with pointer-sized elements64
- (msizex2) => {
- cfg_if! {
- if #[cfg(target_pointer_width = "64")] {
- fallback_to_other_impl!(msizex2, m64x2);
- } else if #[cfg(target_pointer_width = "32")] {
- fallback_to_other_impl!(msizex2, m32x2);
- } else {
- compile_error!("unsupported target_pointer_width");
- }
- }
- };
- (msizex4) => {
- cfg_if! {
- if #[cfg(target_pointer_width = "64")] {
- fallback_to_other_impl!(msizex4, m64x4);
- } else if #[cfg(target_pointer_width = "32")] {
- fallback_to_other_impl!(msizex4, m32x4);
- } else {
- compile_error!("unsupported target_pointer_width");
- }
- }
- };
- (msizex8) => {
- cfg_if! {
- if #[cfg(target_pointer_width = "64")] {
- fallback_to_other_impl!(msizex8, m64x8);
- } else if #[cfg(target_pointer_width = "32")] {
- fallback_to_other_impl!(msizex8, m32x8);
- } else {
- compile_error!("unsupported target_pointer_width");
- }
- }
- };
-}
-
-macro_rules! recurse_half {
- ($vid:ident, $vid_h:ident) => {
- impl All for $vid {
- #[inline]
- unsafe fn all(self) -> bool {
- union U {
- halves: ($vid_h, $vid_h),
- vec: $vid,
- }
- let halves = U { vec: self }.halves;
- halves.0.all() && halves.1.all()
- }
- }
- impl Any for $vid {
- #[inline]
- unsafe fn any(self) -> bool {
- union U {
- halves: ($vid_h, $vid_h),
- vec: $vid,
- }
- let halves = U { vec: self }.halves;
- halves.0.any() || halves.1.any()
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/x86.rs
deleted file mode 100644
index 4bf5098065..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-//! Mask reductions implementation for `x86` and `x86_64` targets
-
-#[cfg(target_feature = "sse")]
-#[macro_use]
-mod sse;
-
-#[cfg(target_feature = "sse2")]
-#[macro_use]
-mod sse2;
-
-#[cfg(target_feature = "avx")]
-#[macro_use]
-mod avx;
-
-#[cfg(target_feature = "avx2")]
-#[macro_use]
-mod avx2;
-
-/// x86 64-bit m8x8 implementation
-macro_rules! x86_m8x8_impl {
- ($id:ident) => {
- fallback_impl!($id);
- };
-}
-
-/// x86 128-bit m8x16 implementation
-macro_rules! x86_m8x16_impl {
- ($id:ident) => {
- cfg_if! {
- if #[cfg(target_feature = "sse2")] {
- x86_m8x16_sse2_impl!($id);
- } else {
- fallback_impl!($id);
- }
- }
- };
-}
-
-/// x86 128-bit m32x4 implementation
-macro_rules! x86_m32x4_impl {
- ($id:ident) => {
- cfg_if! {
- if #[cfg(target_feature = "sse")] {
- x86_m32x4_sse_impl!($id);
- } else {
- fallback_impl!($id);
- }
- }
- };
-}
-
-/// x86 128-bit m64x2 implementation
-macro_rules! x86_m64x2_impl {
- ($id:ident) => {
- cfg_if! {
- if #[cfg(target_feature = "sse2")] {
- x86_m64x2_sse2_impl!($id);
- } else if #[cfg(target_feature = "sse")] {
- x86_m32x4_sse_impl!($id);
- } else {
- fallback_impl!($id);
- }
- }
- };
-}
-
-/// x86 256-bit m8x32 implementation
-macro_rules! x86_m8x32_impl {
- ($id:ident, $half_id:ident) => {
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- x86_m8x32_avx2_impl!($id);
- } else if #[cfg(target_feature = "avx")] {
- x86_m8x32_avx_impl!($id);
- } else if #[cfg(target_feature = "sse2")] {
- recurse_half!($id, $half_id);
- } else {
- fallback_impl!($id);
- }
- }
- };
-}
-
-/// x86 256-bit m32x8 implementation
-macro_rules! x86_m32x8_impl {
- ($id:ident, $half_id:ident) => {
- cfg_if! {
- if #[cfg(target_feature = "avx")] {
- x86_m32x8_avx_impl!($id);
- } else if #[cfg(target_feature = "sse")] {
- recurse_half!($id, $half_id);
- } else {
- fallback_impl!($id);
- }
- }
- };
-}
-
-/// x86 256-bit m64x4 implementation
-macro_rules! x86_m64x4_impl {
- ($id:ident, $half_id:ident) => {
- cfg_if! {
- if #[cfg(target_feature = "avx")] {
- x86_m64x4_avx_impl!($id);
- } else if #[cfg(target_feature = "sse")] {
- recurse_half!($id, $half_id);
- } else {
- fallback_impl!($id);
- }
- }
- };
-}
-
-/// Fallback implementation.
-macro_rules! x86_intr_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- unsafe fn all(self) -> bool {
- use crate::llvm::simd_reduce_all;
- simd_reduce_all(self.0)
- }
- }
- impl Any for $id {
- #[inline]
- unsafe fn any(self) -> bool {
- use crate::llvm::simd_reduce_any;
- simd_reduce_any(self.0)
- }
- }
- };
-}
-
-/// Mask reduction implementation for `x86` and `x86_64` targets
-macro_rules! impl_mask_reductions {
- // 64-bit wide masks
- (m8x8) => {
- x86_m8x8_impl!(m8x8);
- };
- (m16x4) => {
- x86_m8x8_impl!(m16x4);
- };
- (m32x2) => {
- x86_m8x8_impl!(m32x2);
- };
- // 128-bit wide masks
- (m8x16) => {
- x86_m8x16_impl!(m8x16);
- };
- (m16x8) => {
- x86_m8x16_impl!(m16x8);
- };
- (m32x4) => {
- x86_m32x4_impl!(m32x4);
- };
- (m64x2) => {
- x86_m64x2_impl!(m64x2);
- };
- (m128x1) => {
- x86_intr_impl!(m128x1);
- };
- // 256-bit wide masks:
- (m8x32) => {
- x86_m8x32_impl!(m8x32, m8x16);
- };
- (m16x16) => {
- x86_m8x32_impl!(m16x16, m16x8);
- };
- (m32x8) => {
- x86_m32x8_impl!(m32x8, m32x4);
- };
- (m64x4) => {
- x86_m64x4_impl!(m64x4, m64x2);
- };
- (m128x2) => {
- x86_intr_impl!(m128x2);
- };
- (msizex2) => {
- cfg_if! {
- if #[cfg(target_pointer_width = "64")] {
- fallback_to_other_impl!(msizex2, m64x2);
- } else if #[cfg(target_pointer_width = "32")] {
- fallback_to_other_impl!(msizex2, m32x2);
- } else {
- compile_error!("unsupported target_pointer_width");
- }
- }
- };
- (msizex4) => {
- cfg_if! {
- if #[cfg(target_pointer_width = "64")] {
- fallback_to_other_impl!(msizex4, m64x4);
- } else if #[cfg(target_pointer_width = "32")] {
- fallback_to_other_impl!(msizex4, m32x4);
- } else {
- compile_error!("unsupported target_pointer_width");
- }
- }
- };
- (msizex8) => {
- cfg_if! {
- if #[cfg(target_pointer_width = "64")] {
- fallback_to_other_impl!(msizex8, m64x8);
- } else if #[cfg(target_pointer_width = "32")] {
- fallback_to_other_impl!(msizex8, m32x8);
- } else {
- compile_error!("unsupported target_pointer_width");
- }
- }
- };
-
- // Fallback to LLVM's default code-generation:
- ($id:ident) => {
- fallback_impl!($id);
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx.rs
deleted file mode 100644
index 61f352d228..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-//! Mask reductions implementation for `x86` and `x86_64` targets with `AVX`
-
-/// `x86`/`x86_64` 256-bit `AVX` implementation
-/// FIXME: it might be faster here to do two `_mm_movmask_epi8`
-#[cfg(target_feature = "avx")]
-macro_rules! x86_m8x32_avx_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "avx")]
- unsafe fn all(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_testc_si256;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_testc_si256;
- _mm256_testc_si256(crate::mem::transmute(self), crate::mem::transmute($id::splat(true))) != 0
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "avx")]
- unsafe fn any(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_testz_si256;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_testz_si256;
- _mm256_testz_si256(crate::mem::transmute(self), crate::mem::transmute(self)) == 0
- }
- }
- };
-}
-
-/// `x86`/`x86_64` 256-bit m32x8 `AVX` implementation
-macro_rules! x86_m32x8_avx_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn all(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_movemask_ps;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_movemask_ps;
- // _mm256_movemask_ps(a) creates a 8bit mask containing the
- // most significant bit of each lane of `a`. If all bits are
- // set, then all 8 lanes of the mask are true.
- _mm256_movemask_ps(crate::mem::transmute(self)) == 0b_1111_1111_i32
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn any(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_movemask_ps;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_movemask_ps;
-
- _mm256_movemask_ps(crate::mem::transmute(self)) != 0
- }
- }
- };
-}
-
-/// `x86`/`x86_64` 256-bit m64x4 `AVX` implementation
-macro_rules! x86_m64x4_avx_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn all(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_movemask_pd;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_movemask_pd;
- // _mm256_movemask_pd(a) creates a 4bit mask containing the
- // most significant bit of each lane of `a`. If all bits are
- // set, then all 4 lanes of the mask are true.
- _mm256_movemask_pd(crate::mem::transmute(self)) == 0b_1111_i32
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn any(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_movemask_pd;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_movemask_pd;
-
- _mm256_movemask_pd(crate::mem::transmute(self)) != 0
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx2.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx2.rs
deleted file mode 100644
index d37d023420..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/avx2.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-//! Mask reductions implementation for `x86` and `x86_64` targets with `AVX2`.
-#![allow(unused)]
-
-/// x86/x86_64 256-bit m8x32 AVX2 implementation
-macro_rules! x86_m8x32_avx2_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "sse2")]
- unsafe fn all(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_movemask_epi8;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_movemask_epi8;
- // _mm256_movemask_epi8(a) creates a 32bit mask containing the
- // most significant bit of each byte of `a`. If all
- // bits are set, then all 32 lanes of the mask are
- // true.
- _mm256_movemask_epi8(crate::mem::transmute(self)) == -1_i32
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "sse2")]
- unsafe fn any(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm256_movemask_epi8;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm256_movemask_epi8;
-
- _mm256_movemask_epi8(crate::mem::transmute(self)) != 0
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse.rs
deleted file mode 100644
index e0c9aee92b..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-//! Mask reductions implementation for `x86` and `x86_64` targets with `SSE`.
-#![allow(unused)]
-
-/// `x86`/`x86_64` 128-bit `m32x4` `SSE` implementation
-macro_rules! x86_m32x4_sse_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn all(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm_movemask_ps;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm_movemask_ps;
- // _mm_movemask_ps(a) creates a 4bit mask containing the
- // most significant bit of each lane of `a`. If all
- // bits are set, then all 4 lanes of the mask are
- // true.
- _mm_movemask_ps(crate::mem::transmute(self)) == 0b_1111_i32
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn any(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm_movemask_ps;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm_movemask_ps;
-
- _mm_movemask_ps(crate::mem::transmute(self)) != 0
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse2.rs b/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse2.rs
deleted file mode 100644
index bbb52fa47e..0000000000
--- a/third_party/rust/packed_simd/src/codegen/reductions/mask/x86/sse2.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! Mask reductions implementation for `x86` and `x86_64` targets with `SSE2`.
-#![allow(unused)]
-
-/// `x86`/`x86_64` 128-bit m64x2 `SSE2` implementation
-macro_rules! x86_m64x2_sse2_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn all(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm_movemask_pd;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm_movemask_pd;
- // _mm_movemask_pd(a) creates a 2bit mask containing the
- // most significant bit of each lane of `a`. If all
- // bits are set, then all 2 lanes of the mask are
- // true.
- _mm_movemask_pd(crate::mem::transmute(self)) == 0b_11_i32
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "sse")]
- unsafe fn any(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm_movemask_pd;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm_movemask_pd;
-
- _mm_movemask_pd(crate::mem::transmute(self)) != 0
- }
- }
- };
-}
-
-/// `x86`/`x86_64` 128-bit m8x16 `SSE2` implementation
-macro_rules! x86_m8x16_sse2_impl {
- ($id:ident) => {
- impl All for $id {
- #[inline]
- #[target_feature(enable = "sse2")]
- unsafe fn all(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm_movemask_epi8;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm_movemask_epi8;
- // _mm_movemask_epi8(a) creates a 16bit mask containing the
- // most significant bit of each byte of `a`. If all
- // bits are set, then all 16 lanes of the mask are
- // true.
- _mm_movemask_epi8(crate::mem::transmute(self)) == i32::from(u16::max_value())
- }
- }
- impl Any for $id {
- #[inline]
- #[target_feature(enable = "sse2")]
- unsafe fn any(self) -> bool {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm_movemask_epi8;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm_movemask_epi8;
-
- _mm_movemask_epi8(crate::mem::transmute(self)) != 0
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/shuffle.rs b/third_party/rust/packed_simd/src/codegen/shuffle.rs
deleted file mode 100644
index d3acd48f5b..0000000000
--- a/third_party/rust/packed_simd/src/codegen/shuffle.rs
+++ /dev/null
@@ -1,150 +0,0 @@
-//! Implementations of the `ShuffleResult` trait for the different numbers of
-//! lanes and vector element types.
-
-use crate::masks::*;
-use crate::sealed::{Seal, Shuffle};
-
-macro_rules! impl_shuffle {
- ($array:ty, $base:ty, $out:ty) => {
- impl Seal<$array> for $base {}
- impl Shuffle<$array> for $base {
- type Output = $out;
- }
- };
-}
-
-impl_shuffle! { [u32; 2], i8, crate::codegen::i8x2 }
-impl_shuffle! { [u32; 4], i8, crate::codegen::i8x4 }
-impl_shuffle! { [u32; 8], i8, crate::codegen::i8x8 }
-impl_shuffle! { [u32; 16], i8, crate::codegen::i8x16 }
-impl_shuffle! { [u32; 32], i8, crate::codegen::i8x32 }
-impl_shuffle! { [u32; 64], i8, crate::codegen::i8x64 }
-
-impl_shuffle! { [u32; 2], u8, crate::codegen::u8x2 }
-impl_shuffle! { [u32; 4], u8, crate::codegen::u8x4 }
-impl_shuffle! { [u32; 8], u8, crate::codegen::u8x8 }
-impl_shuffle! { [u32; 16], u8, crate::codegen::u8x16 }
-impl_shuffle! { [u32; 32], u8, crate::codegen::u8x32 }
-impl_shuffle! { [u32; 64], u8, crate::codegen::u8x64 }
-
-impl_shuffle! { [u32; 2], m8, crate::codegen::m8x2 }
-impl_shuffle! { [u32; 4], m8, crate::codegen::m8x4 }
-impl_shuffle! { [u32; 8], m8, crate::codegen::m8x8 }
-impl_shuffle! { [u32; 16], m8, crate::codegen::m8x16 }
-impl_shuffle! { [u32; 32], m8, crate::codegen::m8x32 }
-impl_shuffle! { [u32; 64], m8, crate::codegen::m8x64 }
-
-impl_shuffle! { [u32; 2], i16, crate::codegen::i16x2 }
-impl_shuffle! { [u32; 4], i16, crate::codegen::i16x4 }
-impl_shuffle! { [u32; 8], i16, crate::codegen::i16x8 }
-impl_shuffle! { [u32; 16], i16, crate::codegen::i16x16 }
-impl_shuffle! { [u32; 32], i16, crate::codegen::i16x32 }
-
-impl_shuffle! { [u32; 2], u16, crate::codegen::u16x2 }
-impl_shuffle! { [u32; 4], u16, crate::codegen::u16x4 }
-impl_shuffle! { [u32; 8], u16, crate::codegen::u16x8 }
-impl_shuffle! { [u32; 16], u16, crate::codegen::u16x16 }
-impl_shuffle! { [u32; 32], u16, crate::codegen::u16x32 }
-
-impl_shuffle! { [u32; 2], m16, crate::codegen::m16x2 }
-impl_shuffle! { [u32; 4], m16, crate::codegen::m16x4 }
-impl_shuffle! { [u32; 8], m16, crate::codegen::m16x8 }
-impl_shuffle! { [u32; 16], m16, crate::codegen::m16x16 }
-
-impl_shuffle! { [u32; 2], i32, crate::codegen::i32x2 }
-impl_shuffle! { [u32; 4], i32, crate::codegen::i32x4 }
-impl_shuffle! { [u32; 8], i32, crate::codegen::i32x8 }
-impl_shuffle! { [u32; 16], i32, crate::codegen::i32x16 }
-
-impl_shuffle! { [u32; 2], u32, crate::codegen::u32x2 }
-impl_shuffle! { [u32; 4], u32, crate::codegen::u32x4 }
-impl_shuffle! { [u32; 8], u32, crate::codegen::u32x8 }
-impl_shuffle! { [u32; 16], u32, crate::codegen::u32x16 }
-
-impl_shuffle! { [u32; 2], f32, crate::codegen::f32x2 }
-impl_shuffle! { [u32; 4], f32, crate::codegen::f32x4 }
-impl_shuffle! { [u32; 8], f32, crate::codegen::f32x8 }
-impl_shuffle! { [u32; 16], f32, crate::codegen::f32x16 }
-
-impl_shuffle! { [u32; 2], m32, crate::codegen::m32x2 }
-impl_shuffle! { [u32; 4], m32, crate::codegen::m32x4 }
-impl_shuffle! { [u32; 8], m32, crate::codegen::m32x8 }
-impl_shuffle! { [u32; 16], m32, crate::codegen::m32x16 }
-
-/* FIXME: 64-bit single element vector
-impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 }
-*/
-impl_shuffle! { [u32; 2], i64, crate::codegen::i64x2 }
-impl_shuffle! { [u32; 4], i64, crate::codegen::i64x4 }
-impl_shuffle! { [u32; 8], i64, crate::codegen::i64x8 }
-
-/* FIXME: 64-bit single element vector
-impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 }
-*/
-impl_shuffle! { [u32; 2], u64, crate::codegen::u64x2 }
-impl_shuffle! { [u32; 4], u64, crate::codegen::u64x4 }
-impl_shuffle! { [u32; 8], u64, crate::codegen::u64x8 }
-
-/* FIXME: 64-bit single element vector
-impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 }
-*/
-impl_shuffle! { [u32; 2], f64, crate::codegen::f64x2 }
-impl_shuffle! { [u32; 4], f64, crate::codegen::f64x4 }
-impl_shuffle! { [u32; 8], f64, crate::codegen::f64x8 }
-
-/* FIXME: 64-bit single element vector
-impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 }
-*/
-impl_shuffle! { [u32; 2], m64, crate::codegen::m64x2 }
-impl_shuffle! { [u32; 4], m64, crate::codegen::m64x4 }
-impl_shuffle! { [u32; 8], m64, crate::codegen::m64x8 }
-
-impl_shuffle! { [u32; 2], isize, crate::codegen::isizex2 }
-impl_shuffle! { [u32; 4], isize, crate::codegen::isizex4 }
-impl_shuffle! { [u32; 8], isize, crate::codegen::isizex8 }
-
-impl_shuffle! { [u32; 2], usize, crate::codegen::usizex2 }
-impl_shuffle! { [u32; 4], usize, crate::codegen::usizex4 }
-impl_shuffle! { [u32; 8], usize, crate::codegen::usizex8 }
-
-impl_shuffle! { [u32; 2], msize, crate::codegen::msizex2 }
-impl_shuffle! { [u32; 4], msize, crate::codegen::msizex4 }
-impl_shuffle! { [u32; 8], msize, crate::codegen::msizex8 }
-
-impl<T> Seal<[u32; 2]> for *const T {}
-impl<T> Shuffle<[u32; 2]> for *const T {
- type Output = crate::codegen::cptrx2<T>;
-}
-impl<T> Seal<[u32; 4]> for *const T {}
-impl<T> Shuffle<[u32; 4]> for *const T {
- type Output = crate::codegen::cptrx4<T>;
-}
-impl<T> Seal<[u32; 8]> for *const T {}
-impl<T> Shuffle<[u32; 8]> for *const T {
- type Output = crate::codegen::cptrx8<T>;
-}
-
-impl<T> Seal<[u32; 2]> for *mut T {}
-impl<T> Shuffle<[u32; 2]> for *mut T {
- type Output = crate::codegen::mptrx2<T>;
-}
-impl<T> Seal<[u32; 4]> for *mut T {}
-impl<T> Shuffle<[u32; 4]> for *mut T {
- type Output = crate::codegen::mptrx4<T>;
-}
-impl<T> Seal<[u32; 8]> for *mut T {}
-impl<T> Shuffle<[u32; 8]> for *mut T {
- type Output = crate::codegen::mptrx8<T>;
-}
-
-impl_shuffle! { [u32; 1], i128, crate::codegen::i128x1 }
-impl_shuffle! { [u32; 2], i128, crate::codegen::i128x2 }
-impl_shuffle! { [u32; 4], i128, crate::codegen::i128x4 }
-
-impl_shuffle! { [u32; 1], u128, crate::codegen::u128x1 }
-impl_shuffle! { [u32; 2], u128, crate::codegen::u128x2 }
-impl_shuffle! { [u32; 4], u128, crate::codegen::u128x4 }
-
-impl_shuffle! { [u32; 1], m128, crate::codegen::m128x1 }
-impl_shuffle! { [u32; 2], m128, crate::codegen::m128x2 }
-impl_shuffle! { [u32; 4], m128, crate::codegen::m128x4 }
diff --git a/third_party/rust/packed_simd/src/codegen/shuffle1_dyn.rs b/third_party/rust/packed_simd/src/codegen/shuffle1_dyn.rs
deleted file mode 100644
index 19d457a45b..0000000000
--- a/third_party/rust/packed_simd/src/codegen/shuffle1_dyn.rs
+++ /dev/null
@@ -1,408 +0,0 @@
-//! Shuffle vector lanes with run-time indices.
-
-use crate::*;
-
-pub trait Shuffle1Dyn {
- type Indices;
- fn shuffle1_dyn(self, _: Self::Indices) -> Self;
-}
-
-// Fallback implementation
-macro_rules! impl_fallback {
- ($id:ident) => {
- impl Shuffle1Dyn for $id {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- let mut result = Self::splat(0);
- for i in 0..$id::lanes() {
- result = result.replace(i, self.extract(indices.extract(i) as usize));
- }
- result
- }
- }
- };
-}
-
-macro_rules! impl_shuffle1_dyn {
- (u8x8) => {
- cfg_if! {
- if #[cfg(all(
- any(
- all(target_arch = "aarch64", target_feature = "neon"),
- all(target_arch = "doesnotexist", target_feature = "v7",
- target_feature = "neon")
- ),
- any(feature = "core_arch", libcore_neon)
- )
- )] {
- impl Shuffle1Dyn for u8x8 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- #[cfg(target_arch = "aarch64")]
- use crate::arch::aarch64::vtbl1_u8;
- #[cfg(target_arch = "doesnotexist")]
- use crate::arch::arm::vtbl1_u8;
-
- // This is safe because the binary is compiled with
- // neon enabled at compile-time and can therefore only
- // run on CPUs that have it enabled.
- unsafe {
- Simd(mem::transmute(
- vtbl1_u8(mem::transmute(self.0),
- crate::mem::transmute(indices.0))
- ))
- }
- }
- }
- } else {
- impl_fallback!(u8x8);
- }
- }
- };
- (u8x16) => {
- cfg_if! {
- if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
- target_feature = "ssse3"))] {
- impl Shuffle1Dyn for u8x16 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::_mm_shuffle_epi8;
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::_mm_shuffle_epi8;
- // This is safe because the binary is compiled with
- // ssse3 enabled at compile-time and can therefore only
- // run on CPUs that have it enabled.
- unsafe {
- Simd(mem::transmute(
- _mm_shuffle_epi8(mem::transmute(self.0),
- crate::mem::transmute(indices))
- ))
- }
- }
- }
- } else if #[cfg(all(target_arch = "aarch64", target_feature = "neon",
- any(feature = "core_arch", libcore_neon)))] {
- impl Shuffle1Dyn for u8x16 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- use crate::arch::aarch64::vqtbl1q_u8;
-
- // This is safe because the binary is compiled with
- // neon enabled at compile-time and can therefore only
- // run on CPUs that have it enabled.
- unsafe {
- Simd(mem::transmute(
- vqtbl1q_u8(mem::transmute(self.0),
- crate::mem::transmute(indices.0))
- ))
- }
- }
- }
- } else if #[cfg(all(target_arch = "doesnotexist", target_feature = "v7",
- target_feature = "neon",
- any(feature = "core_arch", libcore_neon)))] {
- impl Shuffle1Dyn for u8x16 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- use crate::arch::arm::vtbl2_u8;
-
- // This is safe because the binary is compiled with
- // neon enabled at compile-time and can therefore only
- // run on CPUs that have it enabled.
- unsafe {
- union U {
- j: u8x16,
- s: (u8x8, u8x8),
- }
-
- let (i0, i1) = U { j: y }.s;
-
- let r0 = vtbl2_u8(
- mem::transmute(x),
- crate::mem::transmute(i0)
- );
- let r1 = vtbl2_u8(
- mem::transmute(x),
- crate::mem::transmute(i1)
- );
-
- let r = U { s: (r0, r1) }.j;
-
- Simd(mem::transmute(r))
- }
- }
- }
- } else {
- impl_fallback!(u8x16);
- }
- }
- };
- (u16x8) => {
- impl Shuffle1Dyn for u16x8 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- let indices: u8x8 = (indices * 2).cast();
- let indices: u8x16 = shuffle!(indices, [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7]);
- let v = u8x16::new(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1);
- let indices = indices + v;
- unsafe {
- let s: u8x16 = crate::mem::transmute(self);
- crate::mem::transmute(s.shuffle1_dyn(indices))
- }
- }
- }
- };
- (u32x4) => {
- cfg_if! {
- if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
- target_feature = "avx"))] {
- impl Shuffle1Dyn for u32x4 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::{_mm_permutevar_ps};
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::{_mm_permutevar_ps};
-
- unsafe {
- crate::mem::transmute(
- _mm_permutevar_ps(
- crate::mem::transmute(self.0),
- crate::mem::transmute(indices.0)
- )
- )
- }
- }
- }
- } else {
- impl Shuffle1Dyn for u32x4 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- let indices: u8x4 = (indices * 4).cast();
- let indices: u8x16 = shuffle!(
- indices,
- [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
- );
- let v = u8x16::new(
- 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3
- );
- let indices = indices + v;
- unsafe {
- let s: u8x16 =crate::mem::transmute(self);
- crate::mem::transmute(s.shuffle1_dyn(indices))
- }
- }
- }
- }
- }
- };
- (u64x2) => {
- cfg_if! {
- if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
- target_feature = "avx"))] {
- impl Shuffle1Dyn for u64x2 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- #[cfg(target_arch = "x86")]
- use crate::arch::x86::{_mm_permutevar_pd};
- #[cfg(target_arch = "x86_64")]
- use crate::arch::x86_64::{_mm_permutevar_pd};
- // _mm_permutevar_pd uses the _second_ bit of each
- // element to perform the selection, that is: 0b00 => 0,
- // 0b10 => 1:
- let indices = indices << 1;
- unsafe {
- crate::mem::transmute(
- _mm_permutevar_pd(
- crate::mem::transmute(self),
- crate::mem::transmute(indices)
- )
- )
- }
- }
- }
- } else {
- impl Shuffle1Dyn for u64x2 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- let indices: u8x2 = (indices * 8).cast();
- let indices: u8x16 = shuffle!(
- indices,
- [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
- );
- let v = u8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7
- );
- let indices = indices + v;
- unsafe {
- let s: u8x16 =crate::mem::transmute(self);
- crate::mem::transmute(s.shuffle1_dyn(indices))
- }
- }
- }
- }
- }
- };
- (u128x1) => {
- impl Shuffle1Dyn for u128x1 {
- type Indices = Self;
- #[inline]
- fn shuffle1_dyn(self, _indices: Self::Indices) -> Self {
- self
- }
- }
- };
- ($id:ident) => {
- impl_fallback!($id);
- };
-}
-
-impl_shuffle1_dyn!(u8x2);
-impl_shuffle1_dyn!(u8x4);
-impl_shuffle1_dyn!(u8x8);
-impl_shuffle1_dyn!(u8x16);
-impl_shuffle1_dyn!(u8x32);
-impl_shuffle1_dyn!(u8x64);
-
-impl_shuffle1_dyn!(u16x2);
-impl_shuffle1_dyn!(u16x4);
-impl_shuffle1_dyn!(u16x8);
-impl_shuffle1_dyn!(u16x16);
-impl_shuffle1_dyn!(u16x32);
-
-impl_shuffle1_dyn!(u32x2);
-impl_shuffle1_dyn!(u32x4);
-impl_shuffle1_dyn!(u32x8);
-impl_shuffle1_dyn!(u32x16);
-
-impl_shuffle1_dyn!(u64x2);
-impl_shuffle1_dyn!(u64x4);
-impl_shuffle1_dyn!(u64x8);
-
-impl_shuffle1_dyn!(usizex2);
-impl_shuffle1_dyn!(usizex4);
-impl_shuffle1_dyn!(usizex8);
-
-impl_shuffle1_dyn!(u128x1);
-impl_shuffle1_dyn!(u128x2);
-impl_shuffle1_dyn!(u128x4);
-
-// Implementation for non-unsigned vector types
-macro_rules! impl_shuffle1_dyn_non_u {
- ($id:ident, $uid:ident) => {
- impl Shuffle1Dyn for $id {
- type Indices = $uid;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- unsafe {
- let u: $uid = crate::mem::transmute(self);
- crate::mem::transmute(u.shuffle1_dyn(indices))
- }
- }
- }
- };
-}
-
-impl_shuffle1_dyn_non_u!(i8x2, u8x2);
-impl_shuffle1_dyn_non_u!(i8x4, u8x4);
-impl_shuffle1_dyn_non_u!(i8x8, u8x8);
-impl_shuffle1_dyn_non_u!(i8x16, u8x16);
-impl_shuffle1_dyn_non_u!(i8x32, u8x32);
-impl_shuffle1_dyn_non_u!(i8x64, u8x64);
-
-impl_shuffle1_dyn_non_u!(i16x2, u16x2);
-impl_shuffle1_dyn_non_u!(i16x4, u16x4);
-impl_shuffle1_dyn_non_u!(i16x8, u16x8);
-impl_shuffle1_dyn_non_u!(i16x16, u16x16);
-impl_shuffle1_dyn_non_u!(i16x32, u16x32);
-
-impl_shuffle1_dyn_non_u!(i32x2, u32x2);
-impl_shuffle1_dyn_non_u!(i32x4, u32x4);
-impl_shuffle1_dyn_non_u!(i32x8, u32x8);
-impl_shuffle1_dyn_non_u!(i32x16, u32x16);
-
-impl_shuffle1_dyn_non_u!(i64x2, u64x2);
-impl_shuffle1_dyn_non_u!(i64x4, u64x4);
-impl_shuffle1_dyn_non_u!(i64x8, u64x8);
-
-impl_shuffle1_dyn_non_u!(isizex2, usizex2);
-impl_shuffle1_dyn_non_u!(isizex4, usizex4);
-impl_shuffle1_dyn_non_u!(isizex8, usizex8);
-
-impl_shuffle1_dyn_non_u!(i128x1, u128x1);
-impl_shuffle1_dyn_non_u!(i128x2, u128x2);
-impl_shuffle1_dyn_non_u!(i128x4, u128x4);
-
-impl_shuffle1_dyn_non_u!(m8x2, u8x2);
-impl_shuffle1_dyn_non_u!(m8x4, u8x4);
-impl_shuffle1_dyn_non_u!(m8x8, u8x8);
-impl_shuffle1_dyn_non_u!(m8x16, u8x16);
-impl_shuffle1_dyn_non_u!(m8x32, u8x32);
-impl_shuffle1_dyn_non_u!(m8x64, u8x64);
-
-impl_shuffle1_dyn_non_u!(m16x2, u16x2);
-impl_shuffle1_dyn_non_u!(m16x4, u16x4);
-impl_shuffle1_dyn_non_u!(m16x8, u16x8);
-impl_shuffle1_dyn_non_u!(m16x16, u16x16);
-impl_shuffle1_dyn_non_u!(m16x32, u16x32);
-
-impl_shuffle1_dyn_non_u!(m32x2, u32x2);
-impl_shuffle1_dyn_non_u!(m32x4, u32x4);
-impl_shuffle1_dyn_non_u!(m32x8, u32x8);
-impl_shuffle1_dyn_non_u!(m32x16, u32x16);
-
-impl_shuffle1_dyn_non_u!(m64x2, u64x2);
-impl_shuffle1_dyn_non_u!(m64x4, u64x4);
-impl_shuffle1_dyn_non_u!(m64x8, u64x8);
-
-impl_shuffle1_dyn_non_u!(msizex2, usizex2);
-impl_shuffle1_dyn_non_u!(msizex4, usizex4);
-impl_shuffle1_dyn_non_u!(msizex8, usizex8);
-
-impl_shuffle1_dyn_non_u!(m128x1, u128x1);
-impl_shuffle1_dyn_non_u!(m128x2, u128x2);
-impl_shuffle1_dyn_non_u!(m128x4, u128x4);
-
-impl_shuffle1_dyn_non_u!(f32x2, u32x2);
-impl_shuffle1_dyn_non_u!(f32x4, u32x4);
-impl_shuffle1_dyn_non_u!(f32x8, u32x8);
-impl_shuffle1_dyn_non_u!(f32x16, u32x16);
-
-impl_shuffle1_dyn_non_u!(f64x2, u64x2);
-impl_shuffle1_dyn_non_u!(f64x4, u64x4);
-impl_shuffle1_dyn_non_u!(f64x8, u64x8);
-
-// Implementation for non-unsigned vector types
-macro_rules! impl_shuffle1_dyn_ptr {
- ($id:ident, $uid:ident) => {
- impl<T> Shuffle1Dyn for $id<T> {
- type Indices = $uid;
- #[inline]
- fn shuffle1_dyn(self, indices: Self::Indices) -> Self {
- unsafe {
- let u: $uid = crate::mem::transmute(self);
- crate::mem::transmute(u.shuffle1_dyn(indices))
- }
- }
- }
- };
-}
-
-impl_shuffle1_dyn_ptr!(cptrx2, usizex2);
-impl_shuffle1_dyn_ptr!(cptrx4, usizex4);
-impl_shuffle1_dyn_ptr!(cptrx8, usizex8);
-
-impl_shuffle1_dyn_ptr!(mptrx2, usizex2);
-impl_shuffle1_dyn_ptr!(mptrx4, usizex4);
-impl_shuffle1_dyn_ptr!(mptrx8, usizex8);
diff --git a/third_party/rust/packed_simd/src/codegen/swap_bytes.rs b/third_party/rust/packed_simd/src/codegen/swap_bytes.rs
deleted file mode 100644
index 9cf34a3e04..0000000000
--- a/third_party/rust/packed_simd/src/codegen/swap_bytes.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-//! Horizontal swap bytes reductions.
-
-// FIXME: investigate using `llvm.bswap`
-// https://github.com/rust-lang-nursery/packed_simd/issues/19
-
-use crate::*;
-
-pub(crate) trait SwapBytes {
- fn swap_bytes(self) -> Self;
-}
-
-macro_rules! impl_swap_bytes {
- (v16: $($id:ident,)+) => {
- $(
- impl SwapBytes for $id {
- #[inline]
- fn swap_bytes(self) -> Self {
- shuffle!(self, [1, 0])
- }
- }
- )+
- };
- (v32: $($id:ident,)+) => {
- $(
- impl SwapBytes for $id {
- #[inline]
- #[allow(clippy::useless_transmute)]
- fn swap_bytes(self) -> Self {
- unsafe {
- let bytes: u8x4 = crate::mem::transmute(self);
- let result: u8x4 = shuffle!(bytes, [3, 2, 1, 0]);
- crate::mem::transmute(result)
- }
- }
- }
- )+
- };
- (v64: $($id:ident,)+) => {
- $(
- impl SwapBytes for $id {
- #[inline]
- #[allow(clippy::useless_transmute)]
- fn swap_bytes(self) -> Self {
- unsafe {
- let bytes: u8x8 = crate::mem::transmute(self);
- let result: u8x8 = shuffle!(
- bytes, [7, 6, 5, 4, 3, 2, 1, 0]
- );
- crate::mem::transmute(result)
- }
- }
- }
- )+
- };
- (v128: $($id:ident,)+) => {
- $(
- impl SwapBytes for $id {
- #[inline]
- #[allow(clippy::useless_transmute)]
- fn swap_bytes(self) -> Self {
- unsafe {
- let bytes: u8x16 = crate::mem::transmute(self);
- let result: u8x16 = shuffle!(bytes, [
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
- ]);
- crate::mem::transmute(result)
- }
- }
- }
- )+
- };
- (v256: $($id:ident,)+) => {
- $(
- impl SwapBytes for $id {
- #[inline]
- #[allow(clippy::useless_transmute)]
- fn swap_bytes(self) -> Self {
- unsafe {
- let bytes: u8x32 = crate::mem::transmute(self);
- let result: u8x32 = shuffle!(bytes, [
- 31, 30, 29, 28, 27, 26, 25, 24,
- 23, 22, 21, 20, 19, 18, 17, 16,
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
- ]);
- crate::mem::transmute(result)
- }
- }
- }
- )+
- };
- (v512: $($id:ident,)+) => {
- $(
- impl SwapBytes for $id {
- #[inline]
- #[allow(clippy::useless_transmute)]
- fn swap_bytes(self) -> Self {
- unsafe {
- let bytes: u8x64 = crate::mem::transmute(self);
- let result: u8x64 = shuffle!(bytes, [
- 63, 62, 61, 60, 59, 58, 57, 56,
- 55, 54, 53, 52, 51, 50, 49, 48,
- 47, 46, 45, 44, 43, 42, 41, 40,
- 39, 38, 37, 36, 35, 34, 33, 32,
- 31, 30, 29, 28, 27, 26, 25, 24,
- 23, 22, 21, 20, 19, 18, 17, 16,
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
- ]);
- crate::mem::transmute(result)
- }
- }
- }
- )+
- };
-}
-
-impl_swap_bytes!(v16: u8x2, i8x2,);
-impl_swap_bytes!(v32: u8x4, i8x4, u16x2, i16x2,);
-// FIXME: 64-bit single element vector
-impl_swap_bytes!(v64: u8x8, i8x8, u16x4, i16x4, u32x2, i32x2 /* u64x1, i64x1, */,);
-
-impl_swap_bytes!(v128: u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2, u128x1, i128x1,);
-impl_swap_bytes!(v256: u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4, u128x2, i128x2,);
-
-impl_swap_bytes!(v512: u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8, u128x4, i128x4,);
-
-cfg_if! {
- if #[cfg(target_pointer_width = "8")] {
- impl_swap_bytes!(v16: isizex2, usizex2,);
- impl_swap_bytes!(v32: isizex4, usizex4,);
- impl_swap_bytes!(v64: isizex8, usizex8,);
- } else if #[cfg(target_pointer_width = "16")] {
- impl_swap_bytes!(v32: isizex2, usizex2,);
- impl_swap_bytes!(v64: isizex4, usizex4,);
- impl_swap_bytes!(v128: isizex8, usizex8,);
- } else if #[cfg(target_pointer_width = "32")] {
- impl_swap_bytes!(v64: isizex2, usizex2,);
- impl_swap_bytes!(v128: isizex4, usizex4,);
- impl_swap_bytes!(v256: isizex8, usizex8,);
- } else if #[cfg(target_pointer_width = "64")] {
- impl_swap_bytes!(v128: isizex2, usizex2,);
- impl_swap_bytes!(v256: isizex4, usizex4,);
- impl_swap_bytes!(v512: isizex8, usizex8,);
- } else {
- compile_error!("unsupported target_pointer_width");
- }
-}
diff --git a/third_party/rust/packed_simd/src/codegen/v128.rs b/third_party/rust/packed_simd/src/codegen/v128.rs
deleted file mode 100644
index 9506424fad..0000000000
--- a/third_party/rust/packed_simd/src/codegen/v128.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-//! Internal 128-bit wide vector types
-
-use crate::masks::*;
-
-#[rustfmt::skip]
-impl_simd_array!(
- [i8; 16]: i8x16 |
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [u8; 16]: u8x16 |
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [m8; 16]: m8x16 |
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8
-);
-
-impl_simd_array!([i16; 8]: i16x8 | i16, i16, i16, i16, i16, i16, i16, i16);
-impl_simd_array!([u16; 8]: u16x8 | u16, u16, u16, u16, u16, u16, u16, u16);
-impl_simd_array!([m16; 8]: m16x8 | i16, i16, i16, i16, i16, i16, i16, i16);
-
-impl_simd_array!([i32; 4]: i32x4 | i32, i32, i32, i32);
-impl_simd_array!([u32; 4]: u32x4 | u32, u32, u32, u32);
-impl_simd_array!([f32; 4]: f32x4 | f32, f32, f32, f32);
-impl_simd_array!([m32; 4]: m32x4 | i32, i32, i32, i32);
-
-impl_simd_array!([i64; 2]: i64x2 | i64, i64);
-impl_simd_array!([u64; 2]: u64x2 | u64, u64);
-impl_simd_array!([f64; 2]: f64x2 | f64, f64);
-impl_simd_array!([m64; 2]: m64x2 | i64, i64);
-
-impl_simd_array!([i128; 1]: i128x1 | i128);
-impl_simd_array!([u128; 1]: u128x1 | u128);
-impl_simd_array!([m128; 1]: m128x1 | i128);
diff --git a/third_party/rust/packed_simd/src/codegen/v16.rs b/third_party/rust/packed_simd/src/codegen/v16.rs
deleted file mode 100644
index 4d55a6d899..0000000000
--- a/third_party/rust/packed_simd/src/codegen/v16.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//! Internal 16-bit wide vector types
-
-use crate::masks::*;
-
-impl_simd_array!([i8; 2]: i8x2 | i8, i8);
-impl_simd_array!([u8; 2]: u8x2 | u8, u8);
-impl_simd_array!([m8; 2]: m8x2 | i8, i8);
diff --git a/third_party/rust/packed_simd/src/codegen/v256.rs b/third_party/rust/packed_simd/src/codegen/v256.rs
deleted file mode 100644
index 5ca4759f0c..0000000000
--- a/third_party/rust/packed_simd/src/codegen/v256.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-//! Internal 256-bit wide vector types
-
-use crate::masks::*;
-
-#[rustfmt::skip]
-impl_simd_array!(
- [i8; 32]: i8x32 |
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [u8; 32]: u8x32 |
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [m8; 32]: m8x32 |
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [i16; 16]: i16x16 |
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [u16; 16]: u16x16 |
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [m16; 16]: m16x16 |
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16
-);
-
-impl_simd_array!([i32; 8]: i32x8 | i32, i32, i32, i32, i32, i32, i32, i32);
-impl_simd_array!([u32; 8]: u32x8 | u32, u32, u32, u32, u32, u32, u32, u32);
-impl_simd_array!([f32; 8]: f32x8 | f32, f32, f32, f32, f32, f32, f32, f32);
-impl_simd_array!([m32; 8]: m32x8 | i32, i32, i32, i32, i32, i32, i32, i32);
-
-impl_simd_array!([i64; 4]: i64x4 | i64, i64, i64, i64);
-impl_simd_array!([u64; 4]: u64x4 | u64, u64, u64, u64);
-impl_simd_array!([f64; 4]: f64x4 | f64, f64, f64, f64);
-impl_simd_array!([m64; 4]: m64x4 | i64, i64, i64, i64);
-
-impl_simd_array!([i128; 2]: i128x2 | i128, i128);
-impl_simd_array!([u128; 2]: u128x2 | u128, u128);
-impl_simd_array!([m128; 2]: m128x2 | i128, i128);
diff --git a/third_party/rust/packed_simd/src/codegen/v32.rs b/third_party/rust/packed_simd/src/codegen/v32.rs
deleted file mode 100644
index ae1dabd00c..0000000000
--- a/third_party/rust/packed_simd/src/codegen/v32.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//! Internal 32-bit wide vector types
-
-use crate::masks::*;
-
-impl_simd_array!([i8; 4]: i8x4 | i8, i8, i8, i8);
-impl_simd_array!([u8; 4]: u8x4 | u8, u8, u8, u8);
-impl_simd_array!([m8; 4]: m8x4 | i8, i8, i8, i8);
-
-impl_simd_array!([i16; 2]: i16x2 | i16, i16);
-impl_simd_array!([u16; 2]: u16x2 | u16, u16);
-impl_simd_array!([m16; 2]: m16x2 | i16, i16);
diff --git a/third_party/rust/packed_simd/src/codegen/v512.rs b/third_party/rust/packed_simd/src/codegen/v512.rs
deleted file mode 100644
index bf95110340..0000000000
--- a/third_party/rust/packed_simd/src/codegen/v512.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-//! Internal 512-bit wide vector types
-
-use crate::masks::*;
-
-#[rustfmt::skip]
-impl_simd_array!(
- [i8; 64]: i8x64 |
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
-
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [u8; 64]: u8x64 |
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
-
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8,
- u8, u8, u8, u8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [m8; 64]: m8x64 |
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
-
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8,
- i8, i8, i8, i8
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [i16; 32]: i16x32 |
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [u16; 32]: u16x32 |
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16,
- u16, u16, u16, u16
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [m16; 32]: m16x32 |
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16,
- i16, i16, i16, i16
-);
-
-#[rustfmt::skip]
-impl_simd_array!(
- [i32; 16]: i32x16 |
- i32, i32, i32, i32,
- i32, i32, i32, i32,
- i32, i32, i32, i32,
- i32, i32, i32, i32
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [u32; 16]: u32x16 |
- u32, u32, u32, u32,
- u32, u32, u32, u32,
- u32, u32, u32, u32,
- u32, u32, u32, u32
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [f32; 16]: f32x16 |
- f32, f32, f32, f32,
- f32, f32, f32, f32,
- f32, f32, f32, f32,
- f32, f32, f32, f32
-);
-#[rustfmt::skip]
-impl_simd_array!(
- [m32; 16]: m32x16 |
- i32, i32, i32, i32,
- i32, i32, i32, i32,
- i32, i32, i32, i32,
- i32, i32, i32, i32
-);
-
-impl_simd_array!([i64; 8]: i64x8 | i64, i64, i64, i64, i64, i64, i64, i64);
-impl_simd_array!([u64; 8]: u64x8 | u64, u64, u64, u64, u64, u64, u64, u64);
-impl_simd_array!([f64; 8]: f64x8 | f64, f64, f64, f64, f64, f64, f64, f64);
-impl_simd_array!([m64; 8]: m64x8 | i64, i64, i64, i64, i64, i64, i64, i64);
-
-impl_simd_array!([i128; 4]: i128x4 | i128, i128, i128, i128);
-impl_simd_array!([u128; 4]: u128x4 | u128, u128, u128, u128);
-impl_simd_array!([m128; 4]: m128x4 | i128, i128, i128, i128);
diff --git a/third_party/rust/packed_simd/src/codegen/v64.rs b/third_party/rust/packed_simd/src/codegen/v64.rs
deleted file mode 100644
index 3cfb67c1a0..0000000000
--- a/third_party/rust/packed_simd/src/codegen/v64.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//! Internal 64-bit wide vector types
-
-use crate::masks::*;
-
-impl_simd_array!([i8; 8]: i8x8 | i8, i8, i8, i8, i8, i8, i8, i8);
-impl_simd_array!([u8; 8]: u8x8 | u8, u8, u8, u8, u8, u8, u8, u8);
-impl_simd_array!([m8; 8]: m8x8 | i8, i8, i8, i8, i8, i8, i8, i8);
-
-impl_simd_array!([i16; 4]: i16x4 | i16, i16, i16, i16);
-impl_simd_array!([u16; 4]: u16x4 | u16, u16, u16, u16);
-impl_simd_array!([m16; 4]: m16x4 | i16, i16, i16, i16);
-
-impl_simd_array!([i32; 2]: i32x2 | i32, i32);
-impl_simd_array!([u32; 2]: u32x2 | u32, u32);
-impl_simd_array!([f32; 2]: f32x2 | f32, f32);
-impl_simd_array!([m32; 2]: m32x2 | i32, i32);
-
-impl_simd_array!([i64; 1]: i64x1 | i64);
-impl_simd_array!([u64; 1]: u64x1 | u64);
-impl_simd_array!([f64; 1]: f64x1 | f64);
-impl_simd_array!([m64; 1]: m64x1 | i64);
diff --git a/third_party/rust/packed_simd/src/codegen/vPtr.rs b/third_party/rust/packed_simd/src/codegen/vPtr.rs
deleted file mode 100644
index abd3aa8779..0000000000
--- a/third_party/rust/packed_simd/src/codegen/vPtr.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-//! Pointer vector types
-
-macro_rules! impl_simd_ptr {
- ([$ptr_ty:ty; $elem_count:expr]: $tuple_id:ident | $ty:ident
- | $($tys:ty),*) => {
- #[derive(Copy, Clone)]
- #[repr(simd)]
- pub struct $tuple_id<$ty>($(pub(crate) $tys),*);
- //^^^^^^^ leaked through SimdArray
-
- impl<$ty> crate::sealed::Seal for [$ptr_ty; $elem_count] {}
- impl<$ty> crate::sealed::SimdArray for [$ptr_ty; $elem_count] {
- type Tuple = $tuple_id<$ptr_ty>;
- type T = $ptr_ty;
- const N: usize = $elem_count;
- type NT = [u32; $elem_count];
- }
-
- impl<$ty> crate::sealed::Seal for $tuple_id<$ptr_ty> {}
- impl<$ty> crate::sealed::Simd for $tuple_id<$ptr_ty> {
- type Element = $ptr_ty;
- const LANES: usize = $elem_count;
- type LanesType = [u32; $elem_count];
- }
-
- }
-}
-
-impl_simd_ptr!([*const T; 2]: cptrx2 | T | T, T);
-impl_simd_ptr!([*const T; 4]: cptrx4 | T | T, T, T, T);
-impl_simd_ptr!([*const T; 8]: cptrx8 | T | T, T, T, T, T, T, T, T);
-
-impl_simd_ptr!([*mut T; 2]: mptrx2 | T | T, T);
-impl_simd_ptr!([*mut T; 4]: mptrx4 | T | T, T, T, T);
-impl_simd_ptr!([*mut T; 8]: mptrx8 | T | T, T, T, T, T, T, T, T);
diff --git a/third_party/rust/packed_simd/src/codegen/vSize.rs b/third_party/rust/packed_simd/src/codegen/vSize.rs
deleted file mode 100644
index d5db03991d..0000000000
--- a/third_party/rust/packed_simd/src/codegen/vSize.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//! Vector types with pointer-sized elements
-
-use crate::codegen::pointer_sized_int::{isize_, usize_};
-use crate::masks::*;
-
-impl_simd_array!([isize; 2]: isizex2 | isize_, isize_);
-impl_simd_array!([usize; 2]: usizex2 | usize_, usize_);
-impl_simd_array!([msize; 2]: msizex2 | isize_, isize_);
-
-impl_simd_array!([isize; 4]: isizex4 | isize_, isize_, isize_, isize_);
-impl_simd_array!([usize; 4]: usizex4 | usize_, usize_, usize_, usize_);
-impl_simd_array!([msize; 4]: msizex4 | isize_, isize_, isize_, isize_);
-
-impl_simd_array!([isize; 8]: isizex8 | isize_, isize_, isize_, isize_, isize_, isize_, isize_, isize_);
-impl_simd_array!([usize; 8]: usizex8 | usize_, usize_, usize_, usize_, usize_, usize_, usize_, usize_);
-impl_simd_array!([msize; 8]: msizex8 | isize_, isize_, isize_, isize_, isize_, isize_, isize_, isize_);
diff --git a/third_party/rust/packed_simd/src/lib.rs b/third_party/rust/packed_simd/src/lib.rs
deleted file mode 100644
index 867cc10e9e..0000000000
--- a/third_party/rust/packed_simd/src/lib.rs
+++ /dev/null
@@ -1,348 +0,0 @@
-//! # Portable packed SIMD vectors
-//!
-//! This crate is proposed for stabilization as `std::packed_simd` in [RFC2366:
-//! `std::simd`](https://github.com/rust-lang/rfcs/pull/2366) .
-//!
-//! The examples available in the
-//! [`examples/`](https://github.com/rust-lang-nursery/packed_simd/tree/master/examples)
-//! sub-directory of the crate showcase how to use the library in practice.
-//!
-//! ## Table of contents
-//!
-//! - [Introduction](#introduction)
-//! - [Vector types](#vector-types)
-//! - [Conditional operations](#conditional-operations)
-//! - [Conversions](#conversions)
-//! - [Hardware Features](#hardware-features)
-//! - [Performance guide](https://rust-lang-nursery.github.io/packed_simd/perf-guide/)
-//!
-//! ## Introduction
-//!
-//! This crate exports [`Simd<[T; N]>`][`Simd`]: a packed vector of `N`
-//! elements of type `T` as well as many type aliases for this type: for
-//! example, [`f32x4`], which is just an alias for `Simd<[f32; 4]>`.
-//!
-//! The operations on packed vectors are, by default, "vertical", that is, they
-//! are applied to each vector lane in isolation of the others:
-//!
-//! ```
-//! # use packed_simd::*;
-//! let a = i32x4::new(1, 2, 3, 4);
-//! let b = i32x4::new(5, 6, 7, 8);
-//! assert_eq!(a + b, i32x4::new(6, 8, 10, 12));
-//! ```
-//!
-//! Many "horizontal" operations are also provided:
-//!
-//! ```
-//! # use packed_simd::*;
-//! # let a = i32x4::new(1, 2, 3, 4);
-//! assert_eq!(a.wrapping_sum(), 10);
-//! ```
-//!
-//! In virtually all architectures vertical operations are fast, while
-//! horizontal operations are, by comparison, much slower. That is, the
-//! most portably-efficient way of performing a reduction over a slice
-//! is to collect the results into a vector using vertical operations,
-//! and performing a single horizontal operation at the end:
-//!
-//! ```
-//! # use packed_simd::*;
-//! fn reduce(x: &[i32]) -> i32 {
-//! assert_eq!(x.len() % 4, 0);
-//! let mut sum = i32x4::splat(0); // [0, 0, 0, 0]
-//! for i in (0..x.len()).step_by(4) {
-//! sum += i32x4::from_slice_unaligned(&x[i..]);
-//! }
-//! sum.wrapping_sum()
-//! }
-//!
-//! let x = [0, 1, 2, 3, 4, 5, 6, 7];
-//! assert_eq!(reduce(&x), 28);
-//! ```
-//!
-//! ## Vector types
-//!
-//! The vector type aliases are named according to the following scheme:
-//!
-//! > `{element_type}x{number_of_lanes} == Simd<[element_type;
-//! number_of_lanes]>`
-//!
-//! where the following element types are supported:
-//!
-//! * `i{element_width}`: signed integer
-//! * `u{element_width}`: unsigned integer
-//! * `f{element_width}`: float
-//! * `m{element_width}`: mask (see below)
-//! * `*{const,mut} T`: `const` and `mut` pointers
-//!
-//! ## Basic operations
-//!
-//! ```
-//! # use packed_simd::*;
-//! // Sets all elements to `0`:
-//! let a = i32x4::splat(0);
-//!
-//! // Reads a vector from a slice:
-//! let mut arr = [0, 0, 0, 1, 2, 3, 4, 5];
-//! let b = i32x4::from_slice_unaligned(&arr);
-//!
-//! // Reads the 4-th element of a vector:
-//! assert_eq!(b.extract(3), 1);
-//!
-//! // Returns a new vector where the 4-th element is replaced with `1`:
-//! let a = a.replace(3, 1);
-//! assert_eq!(a, b);
-//!
-//! // Writes a vector to a slice:
-//! let a = a.replace(2, 1);
-//! a.write_to_slice_unaligned(&mut arr[4..]);
-//! assert_eq!(arr, [0, 0, 0, 1, 0, 0, 1, 1]);
-//! ```
-//!
-//! ## Conditional operations
-//!
-//! One often needs to perform an operation on some lanes of the vector. Vector
-//! masks, like `m32x4`, allow selecting on which vector lanes an operation is
-//! to be performed:
-//!
-//! ```
-//! # use packed_simd::*;
-//! let a = i32x4::new(1, 1, 2, 2);
-//!
-//! // Add `1` to the first two lanes of the vector.
-//! let m = m16x4::new(true, true, false, false);
-//! let a = m.select(a + 1, a);
-//! assert_eq!(a, i32x4::splat(2));
-//! ```
-//!
-//! The elements of a vector mask are either `true` or `false`. Here `true`
-//! means that a lane is "selected", while `false` means that a lane is not
-//! selected.
-//!
-//! All vector masks implement a `mask.select(a: T, b: T) -> T` method that
-//! works on all vectors that have the same number of lanes as the mask. The
-//! resulting vector contains the elements of `a` for those lanes for which the
-//! mask is `true`, and the elements of `b` otherwise.
-//!
-//! The example constructs a mask with the first two lanes set to `true` and
-//! the last two lanes set to `false`. This selects the first two lanes of `a +
-//! 1` and the last two lanes of `a`, producing a vector where the first two
-//! lanes have been incremented by `1`.
-//!
-//! > note: mask `select` can be used on vector types that have the same number
-//! > of lanes as the mask. The example shows this by using [`m16x4`] instead
-//! > of [`m32x4`]. It is _typically_ more performant to use a mask element
-//! > width equal to the element width of the vectors being operated upon.
-//! > This is, however, not true for 512-bit wide vectors when targeting
-//! > AVX-512, where the most efficient masks use only 1-bit per element.
-//!
-//! All vertical comparison operations returns masks:
-//!
-//! ```
-//! # use packed_simd::*;
-//! let a = i32x4::new(1, 1, 3, 3);
-//! let b = i32x4::new(2, 2, 0, 0);
-//!
-//! // ge: >= (Greater Eequal; see also lt, le, gt, eq, ne).
-//! let m = a.ge(i32x4::splat(2));
-//!
-//! if m.any() {
-//! // all / any / none allow coherent control flow
-//! let d = m.select(a, b);
-//! assert_eq!(d, i32x4::new(2, 2, 3, 3));
-//! }
-//! ```
-//!
-//! ## Conversions
-//!
-//! * **lossless widening conversions**: [`From`]/[`Into`] are implemented for
-//! vectors with the same number of lanes when the conversion is value
-//! preserving (same as in `std`).
-//!
-//! * **safe bitwise conversions**: The cargo feature `into_bits` provides the
-//! `IntoBits/FromBits` traits (`x.into_bits()`). These perform safe bitwise
-//! `transmute`s when all bit patterns of the source type are valid bit
-//! patterns of the target type and are also implemented for the
-//! architecture-specific vector types of `std::arch`. For example, `let x:
-//! u8x8 = m8x8::splat(true).into_bits();` is provided because all `m8x8` bit
-//! patterns are valid `u8x8` bit patterns. However, the opposite is not
-//! true, not all `u8x8` bit patterns are valid `m8x8` bit-patterns, so this
-//! operation cannot be performed safely using `x.into_bits()`; one needs to
-//! use `unsafe { crate::mem::transmute(x) }` for that, making sure that the
-//! value in the `u8x8` is a valid bit-pattern of `m8x8`.
-//!
-//! * **numeric casts** (`as`): are performed using [`FromCast`]/[`Cast`]
-//! (`x.cast()`), just like `as`:
-//!
-//! * casting integer vectors whose lane types have the same size (e.g.
-//! `i32xN` -> `u32xN`) is a **no-op**,
-//!
-//! * casting from a larger integer to a smaller integer (e.g. `u32xN` ->
-//! `u8xN`) will **truncate**,
-//!
-//! * casting from a smaller integer to a larger integer (e.g. `u8xN` ->
-//! `u32xN`) will:
-//! * **zero-extend** if the source is unsigned, or
-//! * **sign-extend** if the source is signed,
-//!
-//! * casting from a float to an integer will **round the float towards
-//! zero**,
-//!
-//! * casting from an integer to float will produce the floating point
-//! representation of the integer, **rounding to nearest, ties to even**,
-//!
-//! * casting from an `f32` to an `f64` is perfect and lossless,
-//!
-//! * casting from an `f64` to an `f32` **rounds to nearest, ties to even**.
-//!
-//! Numeric casts are not very "precise": sometimes lossy, sometimes value
-//! preserving, etc.
-//!
-//! ## Hardware Features
-//!
-//! This crate can use different hardware features based on your configured
-//! `RUSTFLAGS`. For example, with no configured `RUSTFLAGS`, `u64x8` on
-//! x86_64 will use SSE2 operations like `PCMPEQD`. If you configure
-//! `RUSTFLAGS='-C target-feature=+avx2,+avx'` on supported x86_64 hardware
-//! the same `u64x8` may use wider AVX2 operations like `VPCMPEQQ`. It is
-//! important for performance and for hardware support requirements that
-//! you choose an appropriate set of `target-feature` and `target-cpu`
-//! options during builds. For more information, see the [Performance
-//! guide](https://rust-lang-nursery.github.io/packed_simd/perf-guide/)
-
-#![feature(
- adt_const_params,
- repr_simd,
- rustc_attrs,
- platform_intrinsics,
- stdsimd,
- arm_target_feature,
- link_llvm_intrinsics,
- core_intrinsics,
- stmt_expr_attributes,
- custom_inner_attributes,
-)]
-#![allow(non_camel_case_types, non_snake_case,
- // FIXME: these types are unsound in C FFI already
- // See https://github.com/rust-lang/rust/issues/53346
- improper_ctypes_definitions,
- incomplete_features,
- clippy::cast_possible_truncation,
- clippy::cast_lossless,
- clippy::cast_possible_wrap,
- clippy::cast_precision_loss,
- // TODO: manually add the `#[must_use]` attribute where appropriate
- clippy::must_use_candidate,
- // This lint is currently broken for generic code
- // See https://github.com/rust-lang/rust-clippy/issues/3410
- clippy::use_self,
- clippy::wrong_self_convention,
- clippy::from_over_into,
-)]
-#![cfg_attr(test, feature(hashmap_internals))]
-#![cfg_attr(doc_cfg, feature(doc_cfg))]
-#![deny(rust_2018_idioms, clippy::missing_inline_in_public_items)]
-#![no_std]
-
-use cfg_if::cfg_if;
-
-cfg_if! {
- if #[cfg(feature = "core_arch")] {
- #[allow(unused_imports)]
- use core_arch as arch;
- } else {
- #[allow(unused_imports)]
- use core::arch;
- }
-}
-
-#[cfg(all(target_arch = "wasm32", test))]
-use wasm_bindgen_test::*;
-
-#[allow(unused_imports)]
-use core::{
- /* arch (handled above), */ cmp, f32, f64, fmt, hash, hint, i128, i16, i32, i64, i8, intrinsics,
- isize, iter, marker, mem, ops, ptr, slice, u128, u16, u32, u64, u8, usize,
-};
-
-#[macro_use]
-mod testing;
-#[macro_use]
-mod api;
-mod codegen;
-mod sealed;
-
-pub use crate::sealed::{Mask, Shuffle, Simd as SimdVector, SimdArray};
-
-/// Packed SIMD vector type.
-///
-/// # Examples
-///
-/// ```
-/// # use packed_simd::Simd;
-/// let v = Simd::<[i32; 4]>::new(0, 1, 2, 3);
-/// assert_eq!(v.extract(2), 2);
-/// ```
-#[repr(transparent)]
-#[derive(Copy, Clone)]
-pub struct Simd<A: sealed::SimdArray>(
- // FIXME: this type should be private,
- // but it currently must be public for the
- // `shuffle!` macro to work: it needs to
- // access the internal `repr(simd)` type
- // to call the shuffle intrinsics.
- #[doc(hidden)] pub <A as sealed::SimdArray>::Tuple,
-);
-
-impl<A: sealed::SimdArray> sealed::Seal for Simd<A> {}
-
-/// Wrapper over `T` implementing a lexicoraphical order via the `PartialOrd`
-/// and/or `Ord` traits.
-#[repr(transparent)]
-#[derive(Copy, Clone, Debug)]
-#[allow(clippy::missing_inline_in_public_items)]
-pub struct LexicographicallyOrdered<T>(T);
-
-mod masks;
-pub use self::masks::*;
-
-mod v16;
-pub use self::v16::*;
-
-mod v32;
-pub use self::v32::*;
-
-mod v64;
-pub use self::v64::*;
-
-mod v128;
-pub use self::v128::*;
-
-mod v256;
-pub use self::v256::*;
-
-mod v512;
-pub use self::v512::*;
-
-mod vSize;
-pub use self::vSize::*;
-
-mod vPtr;
-pub use self::vPtr::*;
-
-pub use self::api::cast::*;
-
-#[cfg(feature = "into_bits")]
-pub use self::api::into_bits::*;
-
-// Re-export the shuffle intrinsics required by the `shuffle!` macro.
-#[doc(hidden)]
-pub use self::codegen::llvm::{
- __shuffle_vector16, __shuffle_vector2, __shuffle_vector32, __shuffle_vector4, __shuffle_vector64,
- __shuffle_vector8,
-};
-
-pub(crate) mod llvm {
- pub(crate) use crate::codegen::llvm::*;
-}
diff --git a/third_party/rust/packed_simd/src/masks.rs b/third_party/rust/packed_simd/src/masks.rs
deleted file mode 100644
index 04534eab2b..0000000000
--- a/third_party/rust/packed_simd/src/masks.rs
+++ /dev/null
@@ -1,126 +0,0 @@
-//! Mask types
-
-macro_rules! impl_mask_ty {
- ($id:ident : $elem_ty:ident | #[$doc:meta]) => {
- #[$doc]
- #[derive(Copy, Clone)]
- pub struct $id($elem_ty);
-
- impl crate::sealed::Seal for $id {}
- impl crate::sealed::Mask for $id {
- #[inline]
- fn test(&self) -> bool {
- $id::test(self)
- }
- }
-
- impl $id {
- /// Instantiate a mask with `value`
- #[inline]
- pub fn new(x: bool) -> Self {
- if x {
- $id(!0)
- } else {
- $id(0)
- }
- }
- /// Test if the mask is set
- #[inline]
- pub fn test(&self) -> bool {
- self.0 != 0
- }
- }
-
- impl Default for $id {
- #[inline]
- fn default() -> Self {
- $id(0)
- }
- }
-
- #[allow(clippy::partialeq_ne_impl)]
- impl PartialEq<$id> for $id {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
- #[inline]
- fn ne(&self, other: &Self) -> bool {
- self.0 != other.0
- }
- }
-
- impl Eq for $id {}
-
- impl PartialOrd<$id> for $id {
- #[inline]
- fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
- use crate::cmp::Ordering;
- if self == other {
- Some(Ordering::Equal)
- } else if self.0 > other.0 {
- // Note:
- // * false = 0_i
- // * true == !0_i == -1_i
- Some(Ordering::Less)
- } else {
- Some(Ordering::Greater)
- }
- }
-
- #[inline]
- fn lt(&self, other: &Self) -> bool {
- self.0 > other.0
- }
- #[inline]
- fn gt(&self, other: &Self) -> bool {
- self.0 < other.0
- }
- #[inline]
- fn le(&self, other: &Self) -> bool {
- self.0 >= other.0
- }
- #[inline]
- fn ge(&self, other: &Self) -> bool {
- self.0 <= other.0
- }
- }
-
- impl Ord for $id {
- #[inline]
- fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
- match self.partial_cmp(other) {
- Some(x) => x,
- None => unsafe { crate::hint::unreachable_unchecked() },
- }
- }
- }
-
- impl crate::hash::Hash for $id {
- #[inline]
- fn hash<H: crate::hash::Hasher>(&self, state: &mut H) {
- (self.0 != 0).hash(state);
- }
- }
-
- impl crate::fmt::Debug for $id {
- #[inline]
- fn fmt(&self, fmtter: &mut crate::fmt::Formatter<'_>) -> Result<(), crate::fmt::Error> {
- write!(fmtter, "{}({})", stringify!($id), self.0 != 0)
- }
- }
- };
-}
-
-impl_mask_ty!(m8: i8 | /// 8-bit wide mask.
-);
-impl_mask_ty!(m16: i16 | /// 16-bit wide mask.
-);
-impl_mask_ty!(m32: i32 | /// 32-bit wide mask.
-);
-impl_mask_ty!(m64: i64 | /// 64-bit wide mask.
-);
-impl_mask_ty!(m128: i128 | /// 128-bit wide mask.
-);
-impl_mask_ty!(msize: isize | /// isize-wide mask.
-);
diff --git a/third_party/rust/packed_simd/src/sealed.rs b/third_party/rust/packed_simd/src/sealed.rs
deleted file mode 100644
index 0ec20300fd..0000000000
--- a/third_party/rust/packed_simd/src/sealed.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-//! Sealed traits
-
-/// A sealed trait, this is logically private to the crate
-/// and will prevent implementations from outside the crate
-pub trait Seal<T = ()> {}
-
-/// Trait implemented by arrays that can be SIMD types.
-pub trait SimdArray: Seal {
- /// The type of the #[repr(simd)] type.
- type Tuple: Copy + Clone;
- /// The element type of the vector.
- type T;
- /// The number of elements in the array.
- const N: usize;
- /// The type: `[u32; Self::N]`.
- type NT;
-}
-
-/// This traits is used to constraint the arguments
-/// and result type of the portable shuffles.
-#[doc(hidden)]
-pub trait Shuffle<Lanes>: Seal<Lanes> {
- // Lanes is a `[u32; N]` where `N` is the number of vector lanes
-
- /// The result type of the shuffle.
- type Output;
-}
-
-/// This trait is implemented by all SIMD vector types.
-pub trait Simd: Seal {
- /// Element type of the SIMD vector
- type Element;
- /// The number of elements in the SIMD vector.
- const LANES: usize;
- /// The type: `[u32; Self::N]`.
- type LanesType;
-}
-
-/// This trait is implemented by all mask types
-pub trait Mask: Seal {
- fn test(&self) -> bool;
-}
diff --git a/third_party/rust/packed_simd/src/testing.rs b/third_party/rust/packed_simd/src/testing.rs
deleted file mode 100644
index 6320b28055..0000000000
--- a/third_party/rust/packed_simd/src/testing.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//! Testing macros and other utilities.
-
-#[macro_use]
-mod macros;
-
-#[cfg(test)]
-#[macro_use]
-pub(crate) mod utils;
diff --git a/third_party/rust/packed_simd/src/testing/macros.rs b/third_party/rust/packed_simd/src/testing/macros.rs
deleted file mode 100644
index 7bc4268b90..0000000000
--- a/third_party/rust/packed_simd/src/testing/macros.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//! Testing macros
-
-macro_rules! test_if {
- ($cfg_tt:tt: $it:item) => {
- #[cfg(any(
- // Test everything if:
- //
- // * tests are enabled,
- // * no features about exclusively testing
- // specific vector classes are enabled
- all(test, not(any(
- test_v16,
- test_v32,
- test_v64,
- test_v128,
- test_v256,
- test_v512,
- test_none, // disables all tests
- ))),
- // Test if:
- //
- // * tests are enabled
- // * a particular cfg token tree returns true
- all(test, $cfg_tt),
- ))]
- $it
- };
-}
-
-#[cfg(test)]
-#[allow(unused)]
-macro_rules! ref_ {
- ($anything:tt) => {
- &$anything
- };
-}
-
-#[cfg(test)]
-#[allow(unused)]
-macro_rules! ref_mut_ {
- ($anything:tt) => {
- &mut $anything
- };
-}
diff --git a/third_party/rust/packed_simd/src/testing/utils.rs b/third_party/rust/packed_simd/src/testing/utils.rs
deleted file mode 100644
index 7d8f395739..0000000000
--- a/third_party/rust/packed_simd/src/testing/utils.rs
+++ /dev/null
@@ -1,130 +0,0 @@
-//! Testing utilities
-
-#![allow(dead_code)]
-// FIXME: Or don't. But it's true this is a problematic comparison.
-#![allow(clippy::neg_cmp_op_on_partial_ord)]
-
-use crate::{cmp::PartialOrd, fmt::Debug, LexicographicallyOrdered};
-
-/// Tests PartialOrd for `a` and `b` where `a < b` is true.
-pub fn test_lt<T>(a: LexicographicallyOrdered<T>, b: LexicographicallyOrdered<T>)
-where
- LexicographicallyOrdered<T>: Debug + PartialOrd,
-{
- assert!(a < b, "{:?}, {:?}", a, b);
- assert!(b > a, "{:?}, {:?}", a, b);
-
- assert!(!(a == b), "{:?}, {:?}", a, b);
- assert_ne!(a, b, "{:?}, {:?}", a, b);
-
- assert!(a <= b, "{:?}, {:?}", a, b);
- assert!(b >= a, "{:?}, {:?}", a, b);
-
- // The elegance of the mathematical expression of irreflexivity is more
- // than clippy can handle.
- #[allow(clippy::eq_op)]
- {
- // Irreflexivity
- assert!(!(a < a), "{:?}, {:?}", a, b);
- assert!(!(b < b), "{:?}, {:?}", a, b);
- assert!(!(a > a), "{:?}, {:?}", a, b);
- assert!(!(b > b), "{:?}, {:?}", a, b);
-
- assert!(a <= a, "{:?}, {:?}", a, b);
- assert!(b <= b, "{:?}, {:?}", a, b);
- }
-}
-
-/// Tests PartialOrd for `a` and `b` where `a <= b` is true.
-pub fn test_le<T>(a: LexicographicallyOrdered<T>, b: LexicographicallyOrdered<T>)
-where
- LexicographicallyOrdered<T>: Debug + PartialOrd,
-{
- assert!(a <= b, "{:?}, {:?}", a, b);
- assert!(b >= a, "{:?}, {:?}", a, b);
-
- assert!(a <= b, "{:?}, {:?}", a, b);
- assert!(b >= a, "{:?}, {:?}", a, b);
-
- if a == b {
- assert!(!(a < b), "{:?}, {:?}", a, b);
- assert!(!(b > a), "{:?}, {:?}", a, b);
-
- assert!(!(a != b), "{:?}, {:?}", a, b);
- } else {
- assert_ne!(a, b, "{:?}, {:?}", a, b);
- test_lt(a, b);
- }
-}
-
-/// Test PartialOrd::partial_cmp for `a` and `b` returning `Ordering`
-pub fn test_cmp<T>(
- a: LexicographicallyOrdered<T>,
- b: LexicographicallyOrdered<T>,
- o: Option<crate::cmp::Ordering>,
-) where
- LexicographicallyOrdered<T>: PartialOrd + Debug,
- T: Debug + crate::sealed::Simd + Copy + Clone,
- <T as crate::sealed::Simd>::Element: Default + Copy + Clone + PartialOrd,
-{
- assert!(T::LANES <= 64, "array length in these two arrays needs updating");
- let mut arr_a: [T::Element; 64] = [Default::default(); 64];
- let mut arr_b: [T::Element; 64] = [Default::default(); 64];
-
- unsafe { crate::ptr::write_unaligned(arr_a.as_mut_ptr() as *mut LexicographicallyOrdered<T>, a) }
- unsafe { crate::ptr::write_unaligned(arr_b.as_mut_ptr() as *mut LexicographicallyOrdered<T>, b) }
- let expected = arr_a[0..T::LANES].partial_cmp(&arr_b[0..T::LANES]);
- let result = a.partial_cmp(&b);
- assert_eq!(expected, result, "{:?}, {:?}", a, b);
- assert_eq!(o, result, "{:?}, {:?}", a, b);
- match o {
- Some(crate::cmp::Ordering::Less) => {
- test_lt(a, b);
- test_le(a, b);
- }
- Some(crate::cmp::Ordering::Greater) => {
- test_lt(b, a);
- test_le(b, a);
- }
- Some(crate::cmp::Ordering::Equal) => {
- assert!(a == b, "{:?}, {:?}", a, b);
- assert!(!(a != b), "{:?}, {:?}", a, b);
- assert!(!(a < b), "{:?}, {:?}", a, b);
- assert!(!(b < a), "{:?}, {:?}", a, b);
- assert!(!(a > b), "{:?}, {:?}", a, b);
- assert!(!(b > a), "{:?}, {:?}", a, b);
-
- test_le(a, b);
- test_le(b, a);
- }
- None => {
- assert!(!(a == b), "{:?}, {:?}", a, b);
- assert!(!(a != b), "{:?}, {:?}", a, b);
- assert!(!(a < b), "{:?}, {:?}", a, b);
- assert!(!(a > b), "{:?}, {:?}", a, b);
- assert!(!(b < a), "{:?}, {:?}", a, b);
- assert!(!(b > a), "{:?}, {:?}", a, b);
- assert!(!(a <= b), "{:?}, {:?}", a, b);
- assert!(!(b <= a), "{:?}, {:?}", a, b);
- assert!(!(a >= b), "{:?}, {:?}", a, b);
- assert!(!(b >= a), "{:?}, {:?}", a, b);
- }
- }
-}
-
-// Returns a tuple containing two distinct pointer values of the same type as
-// the element type of the Simd vector `$id`.
-#[allow(unused)]
-macro_rules! ptr_vals {
- ($id:ty) => {
- // expands to an expression
- #[allow(unused_unsafe)]
- unsafe {
- // all bits cleared
- let clear: <$id as sealed::Simd>::Element = crate::mem::zeroed();
- // all bits set
- let set: <$id as sealed::Simd>::Element = crate::mem::transmute(-1_isize);
- (clear, set)
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/v128.rs b/third_party/rust/packed_simd/src/v128.rs
deleted file mode 100644
index 7949f6619a..0000000000
--- a/third_party/rust/packed_simd/src/v128.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-//! 128-bit wide vector types
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_i!([i8; 16]: i8x16, m8x16 | i8, u16 | test_v128 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: |
- /// A 128-bit vector with 16 `i8` lanes.
-);
-impl_u!([u8; 16]: u8x16, m8x16 | u8, u16 | test_v128 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: |
- /// A 128-bit vector with 16 `u8` lanes.
-);
-impl_m!([m8; 16]: m8x16 | i8, u16 | test_v128 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: m16x16 |
- /// A 128-bit vector mask with 16 `m8` lanes.
-);
-
-impl_i!([i16; 8]: i16x8, m16x8 | i16, u8 | test_v128 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: i8x8, u8x8 |
- /// A 128-bit vector with 8 `i16` lanes.
-);
-impl_u!([u16; 8]: u16x8, m16x8 | u16, u8 | test_v128 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: u8x8 |
- /// A 128-bit vector with 8 `u16` lanes.
-);
-impl_m!([m16; 8]: m16x8 | i16, u8 | test_v128 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: m8x8, m32x8 |
- /// A 128-bit vector mask with 8 `m16` lanes.
-);
-
-impl_i!([i32; 4]: i32x4, m32x4 | i32, u8 | test_v128 | x0, x1, x2, x3 |
- From: i8x4, u8x4, i16x4, u16x4 |
- /// A 128-bit vector with 4 `i32` lanes.
-);
-impl_u!([u32; 4]: u32x4, m32x4 | u32, u8 | test_v128 | x0, x1, x2, x3 |
- From: u8x4, u16x4 |
- /// A 128-bit vector with 4 `u32` lanes.
-);
-impl_f!([f32; 4]: f32x4, m32x4 | f32 | test_v128 | x0, x1, x2, x3 |
- From: i8x4, u8x4, i16x4, u16x4 |
- /// A 128-bit vector with 4 `f32` lanes.
-);
-impl_m!([m32; 4]: m32x4 | i32, u8 | test_v128 | x0, x1, x2, x3 |
- From: m8x4, m16x4, m64x4 |
- /// A 128-bit vector mask with 4 `m32` lanes.
-);
-
-impl_i!([i64; 2]: i64x2, m64x2 | i64, u8 | test_v128 | x0, x1 |
- From: i8x2, u8x2, i16x2, u16x2, i32x2, u32x2 |
- /// A 128-bit vector with 2 `i64` lanes.
-);
-impl_u!([u64; 2]: u64x2, m64x2 | u64, u8 | test_v128 | x0, x1 |
- From: u8x2, u16x2, u32x2 |
- /// A 128-bit vector with 2 `u64` lanes.
-);
-impl_f!([f64; 2]: f64x2, m64x2 | f64 | test_v128 | x0, x1 |
- From: i8x2, u8x2, i16x2, u16x2, i32x2, u32x2, f32x2 |
- /// A 128-bit vector with 2 `f64` lanes.
-);
-impl_m!([m64; 2]: m64x2 | i64, u8 | test_v128 | x0, x1 |
- From: m8x2, m16x2, m32x2, m128x2 |
- /// A 128-bit vector mask with 2 `m64` lanes.
-);
-
-impl_i!([i128; 1]: i128x1, m128x1 | i128, u8 | test_v128 | x0 |
- From: /*i8x1, u8x1, i16x1, u16x1, i32x1, u32x1, i64x1, u64x1 */ | // FIXME: unary small vector types
- /// A 128-bit vector with 1 `i128` lane.
-);
-impl_u!([u128; 1]: u128x1, m128x1 | u128, u8 | test_v128 | x0 |
- From: /*u8x1, u16x1, u32x1, u64x1 */ | // FIXME: unary small vector types
- /// A 128-bit vector with 1 `u128` lane.
-);
-impl_m!([m128; 1]: m128x1 | i128, u8 | test_v128 | x0 |
- From: /*m8x1, m16x1, m32x1, m64x1 */ | // FIXME: unary small vector types
- /// A 128-bit vector mask with 1 `m128` lane.
-);
diff --git a/third_party/rust/packed_simd/src/v16.rs b/third_party/rust/packed_simd/src/v16.rs
deleted file mode 100644
index 4ca5afb2a7..0000000000
--- a/third_party/rust/packed_simd/src/v16.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//! 16-bit wide vector types
-
-use crate::*;
-
-impl_i!([i8; 2]: i8x2, m8x2 | i8, u8 | test_v16 | x0, x1 |
- From: |
- /// A 16-bit vector with 2 `i8` lanes.
-);
-impl_u!([u8; 2]: u8x2, m8x2 | u8, u8 | test_v16 | x0, x1 |
- From: |
- /// A 16-bit vector with 2 `u8` lanes.
-);
-impl_m!([m8; 2]: m8x2 | i8, u8 | test_v16 | x0, x1 |
- From: m16x2, m32x2, m64x2, m128x2 |
- /// A 16-bit vector mask with 2 `m8` lanes.
-);
diff --git a/third_party/rust/packed_simd/src/v256.rs b/third_party/rust/packed_simd/src/v256.rs
deleted file mode 100644
index f0c3bc2813..0000000000
--- a/third_party/rust/packed_simd/src/v256.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-//! 256-bit wide vector types
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_i!([i8; 32]: i8x32, m8x32 | i8, u32 | test_v256 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31 |
- From: |
- /// A 256-bit vector with 32 `i8` lanes.
-);
-impl_u!([u8; 32]: u8x32, m8x32 | u8, u32 | test_v256 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31 |
- From: |
- /// A 256-bit vector with 32 `u8` lanes.
-);
-impl_m!([m8; 32]: m8x32 | i8, u32 | test_v256 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31 |
- From: |
- /// A 256-bit vector mask with 32 `m8` lanes.
-);
-
-impl_i!([i16; 16]: i16x16, m16x16 | i16, u16 | test_v256 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: i8x16, u8x16 |
- /// A 256-bit vector with 16 `i16` lanes.
-);
-impl_u!([u16; 16]: u16x16, m16x16 | u16, u16 | test_v256 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: u8x16 |
- /// A 256-bit vector with 16 `u16` lanes.
-);
-impl_m!([m16; 16]: m16x16 | i16, u16 | test_v256 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: m8x16 |
- /// A 256-bit vector mask with 16 `m16` lanes.
-);
-
-impl_i!([i32; 8]: i32x8, m32x8 | i32, u8 | test_v256 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: i8x8, u8x8, i16x8, u16x8 |
- /// A 256-bit vector with 8 `i32` lanes.
-);
-impl_u!([u32; 8]: u32x8, m32x8 | u32, u8 | test_v256 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: u8x8, u16x8 |
- /// A 256-bit vector with 8 `u32` lanes.
-);
-impl_f!([f32; 8]: f32x8, m32x8 | f32 | test_v256 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: i8x8, u8x8, i16x8, u16x8 |
- /// A 256-bit vector with 8 `f32` lanes.
-);
-impl_m!([m32; 8]: m32x8 | i32, u8 | test_v256 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: m8x8, m16x8 |
- /// A 256-bit vector mask with 8 `m32` lanes.
-);
-
-impl_i!([i64; 4]: i64x4, m64x4 | i64, u8 | test_v256 | x0, x1, x2, x3 |
- From: i8x4, u8x4, i16x4, u16x4, i32x4, u32x4 |
- /// A 256-bit vector with 4 `i64` lanes.
-);
-impl_u!([u64; 4]: u64x4, m64x4 | u64, u8 | test_v256 | x0, x1, x2, x3 |
- From: u8x4, u16x4, u32x4 |
- /// A 256-bit vector with 4 `u64` lanes.
-);
-impl_f!([f64; 4]: f64x4, m64x4 | f64 | test_v256 | x0, x1, x2, x3 |
- From: i8x4, u8x4, i16x4, u16x4, i32x4, u32x4, f32x4 |
- /// A 256-bit vector with 4 `f64` lanes.
-);
-impl_m!([m64; 4]: m64x4 | i64, u8 | test_v256 | x0, x1, x2, x3 |
- From: m8x4, m16x4, m32x4 |
- /// A 256-bit vector mask with 4 `m64` lanes.
-);
-
-impl_i!([i128; 2]: i128x2, m128x2 | i128, u8 | test_v256 | x0, x1 |
- From: i8x2, u8x2, i16x2, u16x2, i32x2, u32x2, i64x2, u64x2 |
- /// A 256-bit vector with 2 `i128` lanes.
-);
-impl_u!([u128; 2]: u128x2, m128x2 | u128, u8 | test_v256 | x0, x1 |
- From: u8x2, u16x2, u32x2, u64x2 |
- /// A 256-bit vector with 2 `u128` lanes.
-);
-impl_m!([m128; 2]: m128x2 | i128, u8 | test_v256 | x0, x1 |
- From: m8x2, m16x2, m32x2, m64x2 |
- /// A 256-bit vector mask with 2 `m128` lanes.
-);
diff --git a/third_party/rust/packed_simd/src/v32.rs b/third_party/rust/packed_simd/src/v32.rs
deleted file mode 100644
index 75a1838e5e..0000000000
--- a/third_party/rust/packed_simd/src/v32.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//! 32-bit wide vector types
-
-use crate::*;
-
-impl_i!([i8; 4]: i8x4, m8x4 | i8, u8 | test_v32 | x0, x1, x2, x3 |
- From: |
- /// A 32-bit vector with 4 `i8` lanes.
-);
-impl_u!([u8; 4]: u8x4, m8x4 | u8, u8 | test_v32 | x0, x1, x2, x3 |
- From: |
- /// A 32-bit vector with 4 `u8` lanes.
-);
-impl_m!([m8; 4]: m8x4 | i8, u8 | test_v32 | x0, x1, x2, x3 |
- From: m16x4, m32x4, m64x4 |
- /// A 32-bit vector mask with 4 `m8` lanes.
-);
-
-impl_i!([i16; 2]: i16x2, m16x2 | i16, u8 | test_v32 | x0, x1 |
- From: i8x2, u8x2 |
- /// A 32-bit vector with 2 `i16` lanes.
-);
-impl_u!([u16; 2]: u16x2, m16x2 | u16, u8 | test_v32 | x0, x1 |
- From: u8x2 |
- /// A 32-bit vector with 2 `u16` lanes.
-);
-impl_m!([m16; 2]: m16x2 | i16, u8 | test_v32 | x0, x1 |
- From: m8x2, m32x2, m64x2, m128x2 |
- /// A 32-bit vector mask with 2 `m16` lanes.
-);
diff --git a/third_party/rust/packed_simd/src/v512.rs b/third_party/rust/packed_simd/src/v512.rs
deleted file mode 100644
index 4c8c71338a..0000000000
--- a/third_party/rust/packed_simd/src/v512.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-//! 512-bit wide vector types
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_i!([i8; 64]: i8x64, m8x64 | i8, u64 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31,
- x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47,
- x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62, x63 |
- From: |
- /// A 512-bit vector with 64 `i8` lanes.
-);
-impl_u!([u8; 64]: u8x64, m8x64 | u8, u64 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31,
- x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47,
- x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62, x63 |
- From: |
- /// A 512-bit vector with 64 `u8` lanes.
-);
-impl_m!([m8; 64]: m8x64 | i8, u64 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31,
- x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47,
- x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62, x63 |
- From: |
- /// A 512-bit vector mask with 64 `m8` lanes.
-);
-
-impl_i!([i16; 32]: i16x32, m16x32 | i16, u32 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31 |
- From: i8x32, u8x32 |
- /// A 512-bit vector with 32 `i16` lanes.
-);
-impl_u!([u16; 32]: u16x32, m16x32 | u16, u32 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31 |
- From: u8x32 |
- /// A 512-bit vector with 32 `u16` lanes.
-);
-impl_m!([m16; 32]: m16x32 | i16, u32 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31 |
- From: m8x32 |
- /// A 512-bit vector mask with 32 `m16` lanes.
-);
-
-impl_i!([i32; 16]: i32x16, m32x16 | i32, u16 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: i8x16, u8x16, i16x16, u16x16 |
- /// A 512-bit vector with 16 `i32` lanes.
-);
-impl_u!([u32; 16]: u32x16, m32x16 | u32, u16 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: u8x16, u16x16 |
- /// A 512-bit vector with 16 `u32` lanes.
-);
-impl_f!([f32; 16]: f32x16, m32x16 | f32 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: i8x16, u8x16, i16x16, u16x16 |
- /// A 512-bit vector with 16 `f32` lanes.
-);
-impl_m!([m32; 16]: m32x16 | i32, u16 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 |
- From: m8x16, m16x16 |
- /// A 512-bit vector mask with 16 `m32` lanes.
-);
-
-impl_i!([i64; 8]: i64x8, m64x8 | i64, u8 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: i8x8, u8x8, i16x8, u16x8, i32x8, u32x8 |
- /// A 512-bit vector with 8 `i64` lanes.
-);
-impl_u!([u64; 8]: u64x8, m64x8 | u64, u8 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: u8x8, u16x8, u32x8 |
- /// A 512-bit vector with 8 `u64` lanes.
-);
-impl_f!([f64; 8]: f64x8, m64x8 | f64 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: i8x8, u8x8, i16x8, u16x8, i32x8, u32x8, f32x8 |
- /// A 512-bit vector with 8 `f64` lanes.
-);
-impl_m!([m64; 8]: m64x8 | i64, u8 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: m8x8, m16x8, m32x8 |
- /// A 512-bit vector mask with 8 `m64` lanes.
-);
-
-impl_i!([i128; 4]: i128x4, m128x4 | i128, u8 | test_v512 | x0, x1, x2, x3 |
- From: i8x4, u8x4, i16x4, u16x4, i32x4, u32x4, i64x4, u64x4 |
- /// A 512-bit vector with 4 `i128` lanes.
-);
-impl_u!([u128; 4]: u128x4, m128x4 | u128, u8 | test_v512 | x0, x1, x2, x3 |
- From: u8x4, u16x4, u32x4, u64x4 |
- /// A 512-bit vector with 4 `u128` lanes.
-);
-impl_m!([m128; 4]: m128x4 | i128, u8 | test_v512 | x0, x1, x2, x3 |
- From: m8x4, m16x4, m32x4, m64x4 |
- /// A 512-bit vector mask with 4 `m128` lanes.
-);
diff --git a/third_party/rust/packed_simd/src/v64.rs b/third_party/rust/packed_simd/src/v64.rs
deleted file mode 100644
index bf6b9de610..0000000000
--- a/third_party/rust/packed_simd/src/v64.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-//! 64-bit wide vector types
-#[rustfmt::skip]
-
-use super::*;
-
-impl_i!([i8; 8]: i8x8, m8x8 | i8, u8 | test_v64 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: |
- /// A 64-bit vector with 8 `i8` lanes.
-);
-impl_u!([u8; 8]: u8x8, m8x8 | u8, u8 | test_v64 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: |
- /// A 64-bit vector with 8 `u8` lanes.
-);
-impl_m!([m8; 8]: m8x8 | i8, u8 | test_v64 | x0, x1, x2, x3, x4, x5, x6, x7 |
- From: m16x8, m32x8 |
- /// A 64-bit vector mask with 8 `m8` lanes.
-);
-
-impl_i!([i16; 4]: i16x4, m16x4 | i16, u8 | test_v64 | x0, x1, x2, x3 |
- From: i8x4, u8x4 |
- /// A 64-bit vector with 4 `i16` lanes.
-);
-impl_u!([u16; 4]: u16x4, m16x4 | u16, u8 | test_v64 | x0, x1, x2, x3 |
- From: u8x4 |
- /// A 64-bit vector with 4 `u16` lanes.
-);
-impl_m!([m16; 4]: m16x4 | i16, u8 | test_v64 | x0, x1, x2, x3 |
- From: m8x4, m32x4, m64x4 |
- /// A 64-bit vector mask with 4 `m16` lanes.
-);
-
-impl_i!([i32; 2]: i32x2, m32x2 | i32, u8 | test_v64 | x0, x1 |
- From: i8x2, u8x2, i16x2, u16x2 |
- /// A 64-bit vector with 2 `i32` lanes.
-);
-impl_u!([u32; 2]: u32x2, m32x2 | u32, u8 | test_v64 | x0, x1 |
- From: u8x2, u16x2 |
- /// A 64-bit vector with 2 `u32` lanes.
-);
-impl_m!([m32; 2]: m32x2 | i32, u8 | test_v64 | x0, x1 |
- From: m8x2, m16x2, m64x2, m128x2 |
- /// A 64-bit vector mask with 2 `m32` lanes.
-);
-impl_f!([f32; 2]: f32x2, m32x2 | f32 | test_v64 | x0, x1 |
- From: i8x2, u8x2, i16x2, u16x2 |
- /// A 64-bit vector with 2 `f32` lanes.
-);
-
-/*
-impl_i!([i64; 1]: i64x1, m64x1 | i64, u8 | test_v64 | x0 |
- From: /*i8x1, u8x1, i16x1, u16x1, i32x1, u32x1*/ | // FIXME: primitive to vector conversion
- /// A 64-bit vector with 1 `i64` lanes.
-);
-impl_u!([u64; 1]: u64x1, m64x1 | u64, u8 | test_v64 | x0 |
- From: /*u8x1, u16x1, u32x1*/ | // FIXME: primitive to vector conversion
- /// A 64-bit vector with 1 `u64` lanes.
-);
-impl_m!([m64; 1]: m64x1 | i64, u8 | test_v64 | x0 |
- From: /*m8x1, m16x1, m32x1, */ m128x1 | // FIXME: unary small vector types
- /// A 64-bit vector mask with 1 `m64` lanes.
-);
-impl_f!([f64; 1]: f64x1, m64x1 | f64 | test_v64 | x0 |
- From: /*i8x1, u8x1, i16x1, u16x1, i32x1, u32x1, f32x1*/ | // FIXME: unary small vector types
- /// A 64-bit vector with 1 `f64` lanes.
-);
-*/
diff --git a/third_party/rust/packed_simd/src/vPtr.rs b/third_party/rust/packed_simd/src/vPtr.rs
deleted file mode 100644
index e34cb170eb..0000000000
--- a/third_party/rust/packed_simd/src/vPtr.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//! Vectors of pointers
-#[rustfmt::skip]
-
-use crate::*;
-
-impl_const_p!(
- [*const T; 2]: cptrx2, msizex2, usizex2, isizex2 | test_v128 | x0, x1 | From: |
- /// A vector with 2 `*const T` lanes
-);
-
-impl_mut_p!(
- [*mut T; 2]: mptrx2, msizex2, usizex2, isizex2 | test_v128 | x0, x1 | From: |
- /// A vector with 2 `*mut T` lanes
-);
-
-impl_const_p!(
- [*const T; 4]: cptrx4, msizex4, usizex4, isizex4 | test_v256 | x0, x1, x2, x3 | From: |
- /// A vector with 4 `*const T` lanes
-);
-
-impl_mut_p!(
- [*mut T; 4]: mptrx4, msizex4, usizex4, isizex4 | test_v256 | x0, x1, x2, x3 | From: |
- /// A vector with 4 `*mut T` lanes
-);
-
-impl_const_p!(
- [*const T; 8]: cptrx8, msizex8, usizex8, isizex8 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 | From: |
- /// A vector with 8 `*const T` lanes
-);
-
-impl_mut_p!(
- [*mut T; 8]: mptrx8, msizex8, usizex8, isizex8 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 | From: |
- /// A vector with 8 `*mut T` lanes
-);
diff --git a/third_party/rust/packed_simd/src/vSize.rs b/third_party/rust/packed_simd/src/vSize.rs
deleted file mode 100644
index b5d8910061..0000000000
--- a/third_party/rust/packed_simd/src/vSize.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-//! Vectors with pointer-sized elements
-
-use crate::codegen::pointer_sized_int::{isize_, usize_};
-use crate::*;
-
-impl_i!([isize; 2]: isizex2, msizex2 | isize_, u8 | test_v128 |
- x0, x1|
- From: |
- /// A vector with 2 `isize` lanes.
-);
-
-impl_u!([usize; 2]: usizex2, msizex2 | usize_, u8 | test_v128 |
- x0, x1|
- From: |
- /// A vector with 2 `usize` lanes.
-);
-impl_m!([msize; 2]: msizex2 | isize_, u8 | test_v128 |
- x0, x1 |
- From: |
- /// A vector mask with 2 `msize` lanes.
-);
-
-impl_i!([isize; 4]: isizex4, msizex4 | isize_, u8 | test_v256 |
- x0, x1, x2, x3 |
- From: |
- /// A vector with 4 `isize` lanes.
-);
-impl_u!([usize; 4]: usizex4, msizex4 | usize_, u8 | test_v256 |
- x0, x1, x2, x3|
- From: |
- /// A vector with 4 `usize` lanes.
-);
-impl_m!([msize; 4]: msizex4 | isize_, u8 | test_v256 |
- x0, x1, x2, x3 |
- From: |
- /// A vector mask with 4 `msize` lanes.
-);
-
-impl_i!([isize; 8]: isizex8, msizex8 | isize_, u8 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7 |
- From: |
- /// A vector with 8 `isize` lanes.
-);
-impl_u!([usize; 8]: usizex8, msizex8 | usize_, u8 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7 |
- From: |
- /// A vector with 8 `usize` lanes.
-);
-impl_m!([msize; 8]: msizex8 | isize_, u8 | test_v512 |
- x0, x1, x2, x3, x4, x5, x6, x7 |
- From: |
- /// A vector mask with 8 `msize` lanes.
-);
diff --git a/third_party/rust/packed_simd/tests/endianness.rs b/third_party/rust/packed_simd/tests/endianness.rs
deleted file mode 100644
index 17a7796b1b..0000000000
--- a/third_party/rust/packed_simd/tests/endianness.rs
+++ /dev/null
@@ -1,268 +0,0 @@
-#[cfg(target_arch = "wasm32")]
-use wasm_bindgen_test::*;
-
-use packed_simd::*;
-use std::{mem, slice};
-
-#[cfg_attr(not(target_arch = "wasm32"), test)]
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
-fn endian_indexing() {
- let v = i32x4::new(0, 1, 2, 3);
- assert_eq!(v.extract(0), 0);
- assert_eq!(v.extract(1), 1);
- assert_eq!(v.extract(2), 2);
- assert_eq!(v.extract(3), 3);
-}
-
-#[cfg_attr(not(target_arch = "wasm32"), test)]
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
-fn endian_bitcasts() {
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let t: i16x8 = unsafe { mem::transmute(x) };
- let e: i16x8 = if cfg!(target_endian = "little") {
- i16x8::new(256, 770, 1284, 1798, 2312, 2826, 3340, 3854)
- } else {
- i16x8::new(1, 515, 1029, 1543, 2057, 2571, 3085, 3599)
- };
- assert_eq!(t, e);
-}
-
-#[cfg_attr(not(target_arch = "wasm32"), test)]
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
-fn endian_casts() {
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let t: i16x16 = x.into(); // simd_cast
- #[rustfmt::skip]
- let e = i16x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- assert_eq!(t, e);
-}
-
-#[cfg_attr(not(target_arch = "wasm32"), test)]
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
-fn endian_load_and_stores() {
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let mut y: [i16; 8] = [0; 8];
- x.write_to_slice_unaligned(unsafe { slice::from_raw_parts_mut(&mut y as *mut _ as *mut i8, 16) });
-
- let e: [i16; 8] = if cfg!(target_endian = "little") {
- [256, 770, 1284, 1798, 2312, 2826, 3340, 3854]
- } else {
- [1, 515, 1029, 1543, 2057, 2571, 3085, 3599]
- };
- assert_eq!(y, e);
-
- let z = i8x16::from_slice_unaligned(unsafe { slice::from_raw_parts(&y as *const _ as *const i8, 16) });
- assert_eq!(z, x);
-}
-
-#[cfg_attr(not(target_arch = "wasm32"), test)]
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
-fn endian_array_union() {
- union A {
- data: [f32; 4],
- vec: f32x4,
- }
- let x: [f32; 4] = unsafe { A { vec: f32x4::new(0., 1., 2., 3.) }.data };
- // As all of these are integer values within the mantissa^1 range, it
- // would be very unusual for them to actually fail to compare.
- #[allow(clippy::float_cmp)]
- {
- assert_eq!(x[0], 0_f32);
- assert_eq!(x[1], 1_f32);
- assert_eq!(x[2], 2_f32);
- assert_eq!(x[3], 3_f32);
- }
- let y: f32x4 = unsafe { A { data: [3., 2., 1., 0.] }.vec };
- assert_eq!(y, f32x4::new(3., 2., 1., 0.));
-
- union B {
- data: [i8; 16],
- vec: i8x16,
- }
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let x: [i8; 16] = unsafe { B { vec: x }.data };
-
- for (i, v) in x.iter().enumerate() {
- assert_eq!(i as i8, *v);
- }
-
- #[rustfmt::skip]
- let y = [
- 15, 14, 13, 12, 11, 19, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
- ];
- #[rustfmt::skip]
- let e = i8x16::new(
- 15, 14, 13, 12, 11, 19, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
- );
- let z = unsafe { B { data: y }.vec };
- assert_eq!(z, e);
-
- union C {
- data: [i16; 8],
- vec: i8x16,
- }
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let x: [i16; 8] = unsafe { C { vec: x }.data };
-
- let e: [i16; 8] = if cfg!(target_endian = "little") {
- [256, 770, 1284, 1798, 2312, 2826, 3340, 3854]
- } else {
- [1, 515, 1029, 1543, 2057, 2571, 3085, 3599]
- };
- assert_eq!(x, e);
-}
-
-#[cfg_attr(not(target_arch = "wasm32"), test)]
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
-fn endian_tuple_access() {
- type F32x4T = (f32, f32, f32, f32);
- union A {
- data: F32x4T,
- vec: f32x4,
- }
- let x: F32x4T = unsafe { A { vec: f32x4::new(0., 1., 2., 3.) }.data };
- // As all of these are integer values within the mantissa^1 range, it
- // would be very unusual for them to actually fail to compare.
- #[allow(clippy::float_cmp)]
- {
- assert_eq!(x.0, 0_f32);
- assert_eq!(x.1, 1_f32);
- assert_eq!(x.2, 2_f32);
- assert_eq!(x.3, 3_f32);
- }
- let y: f32x4 = unsafe { A { data: (3., 2., 1., 0.) }.vec };
- assert_eq!(y, f32x4::new(3., 2., 1., 0.));
-
- #[rustfmt::skip]
- type I8x16T = (i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8);
- union B {
- data: I8x16T,
- vec: i8x16,
- }
-
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let x: I8x16T = unsafe { B { vec: x }.data };
-
- assert_eq!(x.0, 0);
- assert_eq!(x.1, 1);
- assert_eq!(x.2, 2);
- assert_eq!(x.3, 3);
- assert_eq!(x.4, 4);
- assert_eq!(x.5, 5);
- assert_eq!(x.6, 6);
- assert_eq!(x.7, 7);
- assert_eq!(x.8, 8);
- assert_eq!(x.9, 9);
- assert_eq!(x.10, 10);
- assert_eq!(x.11, 11);
- assert_eq!(x.12, 12);
- assert_eq!(x.13, 13);
- assert_eq!(x.14, 14);
- assert_eq!(x.15, 15);
-
- #[rustfmt::skip]
- let y = (
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
- );
- let z: i8x16 = unsafe { B { data: y }.vec };
- #[rustfmt::skip]
- let e = i8x16::new(
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
- );
- assert_eq!(e, z);
-
- #[rustfmt::skip]
- type I16x8T = (i16, i16, i16, i16, i16, i16, i16, i16);
- union C {
- data: I16x8T,
- vec: i8x16,
- }
-
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let x: I16x8T = unsafe { C { vec: x }.data };
-
- let e: [i16; 8] = if cfg!(target_endian = "little") {
- [256, 770, 1284, 1798, 2312, 2826, 3340, 3854]
- } else {
- [1, 515, 1029, 1543, 2057, 2571, 3085, 3599]
- };
- assert_eq!(x.0, e[0]);
- assert_eq!(x.1, e[1]);
- assert_eq!(x.2, e[2]);
- assert_eq!(x.3, e[3]);
- assert_eq!(x.4, e[4]);
- assert_eq!(x.5, e[5]);
- assert_eq!(x.6, e[6]);
- assert_eq!(x.7, e[7]);
-
- #[rustfmt::skip]
- #[repr(C)]
- #[derive(Copy ,Clone)]
- pub struct Tup(pub i8, pub i8, pub i16, pub i8, pub i8, pub i16,
- pub i8, pub i8, pub i16, pub i8, pub i8, pub i16);
-
- union D {
- data: Tup,
- vec: i8x16,
- }
-
- #[rustfmt::skip]
- let x = i8x16::new(
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- );
- let x: Tup = unsafe { D { vec: x }.data };
-
- let e: [i16; 12] = if cfg!(target_endian = "little") {
- [0, 1, 770, 4, 5, 1798, 8, 9, 2826, 12, 13, 3854]
- } else {
- [0, 1, 515, 4, 5, 1543, 8, 9, 2571, 12, 13, 3599]
- };
- assert_eq!(x.0 as i16, e[0]);
- assert_eq!(x.1 as i16, e[1]);
- assert_eq!(x.2 as i16, e[2]);
- assert_eq!(x.3 as i16, e[3]);
- assert_eq!(x.4 as i16, e[4]);
- assert_eq!(x.5 as i16, e[5]);
- assert_eq!(x.6 as i16, e[6]);
- assert_eq!(x.7 as i16, e[7]);
- assert_eq!(x.8 as i16, e[8]);
- assert_eq!(x.9 as i16, e[9]);
- assert_eq!(x.10 as i16, e[10]);
- assert_eq!(x.11 as i16, e[11]);
-}
diff --git a/third_party/rust/plist/Cargo.toml b/third_party/rust/plist/Cargo.toml
index 4829298f4f..f064e35f27 100644
--- a/third_party/rust/plist/Cargo.toml
+++ b/third_party/rust/plist/Cargo.toml
@@ -24,7 +24,7 @@ repository = "https://github.com/ebarnard/rust-plist/"
version = "0.13.0"
[dependencies.indexmap]
-version = "1.0.2"
+version = "2.1.0"
[dependencies.line-wrap]
version = "0.1.1"
diff --git a/third_party/rust/plist/src/lib.rs b/third_party/rust/plist/src/lib.rs
index 0ac048e30d..018bbe7d94 100644
--- a/third_party/rust/plist/src/lib.rs
+++ b/third_party/rust/plist/src/lib.rs
@@ -72,6 +72,8 @@
//! specify a tilde requirement e.g. `plist = "~1.0.3"` in you `Cargo.toml` so that the plist crate
//! is not automatically updated to version 1.1.
+#![allow(warnings)] // Third-party
+
pub mod dictionary;
#[cfg(feature = "enable_unstable_features_that_may_break_with_minor_version_bumps")]
diff --git a/third_party/rust/plist/src/stream/binary_writer.rs b/third_party/rust/plist/src/stream/binary_writer.rs
index 0e04dbe865..690e2092a2 100644
--- a/third_party/rust/plist/src/stream/binary_writer.rs
+++ b/third_party/rust/plist/src/stream/binary_writer.rs
@@ -577,7 +577,7 @@ fn is_even(value: usize) -> bool {
fn value_mut<'a>(
values: &'a mut IndexMap<Value<'static>, ValueState>,
value_index: usize,
-) -> (&'a mut Value<'static>, &'a mut ValueState) {
+) -> (&'a Value<'static>, &'a mut ValueState) {
values
.get_index_mut(value_index)
.expect("internal consistency error")
diff --git a/third_party/rust/prio/.cargo-checksum.json b/third_party/rust/prio/.cargo-checksum.json
index 2d8ae36c4a..858b46fcbc 100644
--- a/third_party/rust/prio/.cargo-checksum.json
+++ b/third_party/rust/prio/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9ae63800fb2fb7ad25b5206e1c6aedba07ebeadce625fa3d3c214391c754c434","LICENSE":"5f5a5db8d4baa0eea0ff2d32a5a86c7a899a3343f1496f4477f42e2d651cc6dc","README.md":"8b36e999c5b65c83fcc77d85e78e690438c08afbb8292640cfc7dbc5164dcfcd","benches/cycle_counts.rs":"40d2ce27e6df99b9d7f4913b39d29a7e60c8efa3718218d125f2691b559b0b77","benches/speed_tests.rs":"2ef52920b677cb0292adf3d5f6bf06f57e678b510550acc99e51b33e8a1bdb44","documentation/releases.md":"14cfe917c88b69d557badc683b887c734254810402c7e19c9a45d815637480a9","src/benchmarked.rs":"a1ca26229967c55ba0d000ed5a594ba42ba2a27af0b1f5e37168f00cb62ad562","src/codec.rs":"2f5763612d19659c7f3f806b94795276c032da7a8e0b41687b355e32b99929da","src/dp.rs":"683de654a0a4bfd51741fdb03f17a3e2a15d11633857623dae3a5df199cfccb6","src/dp/distributions.rs":"8cedb5d44aa8bed9635d8791ec0f05a42fabff95f63d59f50bf9c7764d0c68bd","src/fft.rs":"5900d31263cf16eec9d462eb75458c2582d4c502312d478f87652317ec9f1e9f","src/field.rs":"6e29dcad7ce386e6a0f549214a6a14335118e177e8a2a9d6b1eafbf1fb865ac1","src/field/field255.rs":"6472c11354a1a75d733436607739e69051d5ee15a3f2477bee22d3dd8c80b686","src/flp.rs":"e961b9000e1d332a98975bfbfead93f26af56333338f6102ae09c0a5cdb87987","src/flp/gadgets.rs":"ddf641b0c06348b2a74bd579f994ce8f3ba387f4fa5ec3ca5e3a1260237a1615","src/flp/types.rs":"cb57d1f71b73d19893bfc5e86077b8bdaf66f1cc62b6a49d78ac15737580f45d","src/flp/types/fixedpoint_l2.rs":"22c96b2d0f3bf57155a6acddeee9b6164c3521e99cd12f6b2dd5c206543765d6","src/flp/types/fixedpoint_l2/compatible_float.rs":"8bcfc8ccb1e3ef32fdabbbac40dd7ffb9af10ab9ed10d9cd8c02cd55faa8814f","src/fp.rs":"a70f2961bd9df6a6b9ad683924ed27e4d44fc67408681d7b68fba2c4594edba4","src/idpf.rs":"6a81395351d8beca8f38774f883af23e161067f32ea9f9c177a135b00b139b3c","src/lib.rs":"bb5a25d5d1b2b0f916acd66e27bbcd16022965110f46292edf512973191a9497","src/polynomial.rs":"8e91a56de1a9eaf7eb1f01857e1e1834f768525cadc3bbe02f4f4ff44deeaef8","src/prng.rs":"bcf0125f0fe82c17fca417f068d49c5e08e0e7159a2d5e8a156bb52702d070cc","src/topology/mod.rs":"09a6d07c598d7bb52164bb5f82ab5ceddba5a192454828a789516d621e85c557","src/topology/ping_pong.rs":"89b4b4968d2c3b322ba8ca72101bb026426f5c4f10efb4a7895cb0c4a1488d03","src/vdaf.rs":"fe507b7644288e4912ac3c561a77c390cb85005b889fdcb471392a5886683607","src/vdaf/dummy.rs":"386e7e163625a1c53a1a95dd47c14324c206872080dbe76e90ec5d93f90d39ae","src/vdaf/poplar1.rs":"78af3fe04ef038ec263073522b1c93e0e14a1ab08d6ef1136dd4aa46cb19f667","src/vdaf/prio2.rs":"97d425fcb0a8a15f600ee202e4da7be68ee04e329e8e9f4d50cecd7557213662","src/vdaf/prio2/client.rs":"90c529400c3be77461b02d5cd78c52e98626e83e149b677da711097c9b17e806","src/vdaf/prio2/server.rs":"a5ebc32d92849d2a565888e18c63eac36d2e854f2e51c98ebc04983837465235","src/vdaf/prio2/test_vector.rs":"507cb6d05e40270786eb2c123866a18f7ee586e7c022161bf8fd47cb472507a9","src/vdaf/prio3.rs":"0c60f16188604013bd894e9dddfc8263f65d9b882f7e6831d43c14e05b389af9","src/vdaf/prio3_test.rs":"e2c7e1fd6f20ea3c886a2bfb5a63262f41c9a419e0e419d0b808f585b55b730e","src/vdaf/test_vec/07/IdpfPoplar_0.json":"f4f23df90774d7ac74c0bd984e25db7c1a2c53705adf30a693f388922f2c5d38","src/vdaf/test_vec/07/Poplar1_0.json":"8a5a44e85c5c08bf54a656a8692cad962d08bf9ef49e69f04ca4646de3cc1a40","src/vdaf/test_vec/07/Poplar1_1.json":"1caff76c31ce637baca4adc62f63b4d0d887a860bba8f59ffdef5409f5a0988e","src/vdaf/test_vec/07/Poplar1_2.json":"439eb1ea543929b127c6f77b1109f2455f649a9a84b0335d3dd5177e75fe521f","src/vdaf/test_vec/07/Poplar1_3.json":"2864fe4000934fa4035dcb5914da804ddbd3e7e125c459efc5f400b41b5b6b55","src/vdaf/test_vec/07/Prio3Count_0.json":"33e41769b1e11376276dbfcc6670100673ea3ed887baaaf5c37c6f389167c26c","src/vdaf/test_vec/07/Prio3Count_1.json":"483f53318116847bd43d4b6040ef2f00436f643c05eae153144285e8a032990c","src/vdaf/test_vec/07/Prio3Histogram_0.json":"f71a736c57eb0811b34e2806dc7c6005b67fc62fffb0779a263f1030a09ec747","src/vdaf/test_vec/07/Prio3Histogram_1.json":"3d67c8547fe69baa6ba8d90c3fd307003f9ebe04984c39343dcd8e794a6bf5d8","src/vdaf/test_vec/07/Prio3SumVec_0.json":"9d0ff391d954073ccbb798d382ba8701131687410e6d754c3bce36e9c8f650df","src/vdaf/test_vec/07/Prio3SumVec_1.json":"83f1abe06fc76a9f628be112efc8168243ce4713b878fe7d6ffe2b5b17a87382","src/vdaf/test_vec/07/Prio3Sum_0.json":"732093776a144bf9a8e71ae3179ae0fd74e5db3787b31603dceeb6e557d9d814","src/vdaf/test_vec/07/Prio3Sum_1.json":"a4250943b8a33d4d19652bd8a7312059ea92e3f8b1d541439b64bff996bc1bf4","src/vdaf/test_vec/07/XofFixedKeyAes128.json":"ff40fc42eec15a483bd02e798ddab6c38d81a335f1fe5703290ced88d7ceae26","src/vdaf/test_vec/07/XofShake128.json":"e68b4769f4fb9be9a8d9d5bf823636ed97c6e1f68bcd794c7576ba8b42eeba9a","src/vdaf/test_vec/prio2/fieldpriov2.json":"7ba82fcf068dfd5b04fc7fd01ebe5626ea9740be9cd6aa631525f23b80bcd027","src/vdaf/xof.rs":"175a4b0077bf295aeee4f42c70b55684079f4ef8c1b580b90ac0af8914f05fc9","tests/discrete_gauss.rs":"ddae145ac52ff8cd2b2134266733fee6fd9378bfb68c943a28e5a0a314a1ceb7","tests/test_vectors/discrete_gauss_100.json":"0f056accac870bf79539c82492f7b1f30d69835fe780bb83e0a15b0f0b318bc3","tests/test_vectors/discrete_gauss_2.342.json":"2ce62090c800c786b02ad409c4de18a94858105cd4859d7f595fbdf7ab79e8e1","tests/test_vectors/discrete_gauss_3.json":"b088841eef4cba2b287f04d3707a7efd33c11a2d40a71c8d953e8231150dbe6e","tests/test_vectors/discrete_gauss_41293847.json":"5896a922e313ce15d1353f0bdbf1f55413cc6a8116531cfc1fd9f3f7000e9002","tests/test_vectors/discrete_gauss_9.json":"4ae1c1195d752b6db5b3be47e7e662c2070aac1146e5b9ce9398c0c93cec21d2","tests/test_vectors/discrete_gauss_9999999999999999999999.json":"d65ec163c7bcbd8091c748e659eba460a9c56b37bc7612fd4a96394e58480b23"},"package":"b3163d19b7d8bc08c7ab6b74510f5e048c0937509d14c28b8919d2baf8cb9387"} \ No newline at end of file
+{"files":{"Cargo.toml":"305efd4975370d0fa7b94ad850c0228d1db1d7baf271b15061ac7f2036e99381","LICENSE":"5f5a5db8d4baa0eea0ff2d32a5a86c7a899a3343f1496f4477f42e2d651cc6dc","README.md":"9a2b0c376b6f421300552b1ad52f87b346b4ab2b59b2c21fcd3ee4cf10445c3c","benches/cycle_counts.rs":"d3e9d26f6a43e73df488ae0ef3aec4b3088343bfae7603d68561a01418bf8fbf","benches/speed_tests.rs":"2080c3c5d80ffa1100dbd8981c48574cc5ecb9c4b959a2c1bd4a759314307c3e","documentation/field_parameters.sage":"8b0ec3dafebb8f6eeac606bef40dcaf3e521e8988944ade06ce89cbde780f101","documentation/releases.md":"14cfe917c88b69d557badc683b887c734254810402c7e19c9a45d815637480a9","src/benchmarked.rs":"a1ca26229967c55ba0d000ed5a594ba42ba2a27af0b1f5e37168f00cb62ad562","src/codec.rs":"0706823b71da46a6ba4f359f1253a283a5a5a126ebb0087e73ae42ee4c746f12","src/dp.rs":"5480fc055c60082898e3eee84ac0fa3737f2c4588dd07eed0c787b170a5acdea","src/dp/distributions.rs":"f1cf6694f78874cd5c2561a69c7cd40f85302007b095e56ed29a348a8b13840d","src/fft.rs":"36d8c7fe23c3f32bc555b00bd8bc9b48f4a081b9a93cb1c8908277981acbc067","src/field.rs":"3cd2aeaf81a9a9522bfcab0393aef81df72ed15af7562549dfd288c1eeb50584","src/field/field255.rs":"16e706e175322a1e1c5bfe2152afb03080e04963cd925eafbe72e4fb272734df","src/flp.rs":"129040b44306098298943fc44c6eaf19833b7bcd9dadeecce8787fcbb297b8f5","src/flp/gadgets.rs":"ddf641b0c06348b2a74bd579f994ce8f3ba387f4fa5ec3ca5e3a1260237a1615","src/flp/types.rs":"eb6ff64af7c58a71912909e9a783690d595bfaab39d50c4805afd2caf892efad","src/flp/types/fixedpoint_l2.rs":"5a42a04fdad9309816064b60d7a92aeb548f38c45dafa23ff83755cc5d73f55d","src/flp/types/fixedpoint_l2/compatible_float.rs":"8bcfc8ccb1e3ef32fdabbbac40dd7ffb9af10ab9ed10d9cd8c02cd55faa8814f","src/fp.rs":"a70f2961bd9df6a6b9ad683924ed27e4d44fc67408681d7b68fba2c4594edba4","src/idpf.rs":"ffb41ad4d56f817f5dc44379ef760f23c22883da518ff31fd6e4f411c898193b","src/lib.rs":"58101cbe431eb5160f7edce480515076749e101fd1231c82c7842e408807ce37","src/polynomial.rs":"de703703484219103dd617339a4b3130d74da5d2072b74ebbcbd7889cb82cd8f","src/prng.rs":"28d44b6588a0fb12c5b0b8021ca6d48385db8c7b525606412ec6e2e1e748e9c4","src/topology/mod.rs":"09a6d07c598d7bb52164bb5f82ab5ceddba5a192454828a789516d621e85c557","src/topology/ping_pong.rs":"c0d15d6af01e1e4e5639719ea668a0f25f9787cc2e35d8c59f6a19ef27780e5a","src/vdaf.rs":"b2ec4b02f89208714383722bad46e1a982843623a30f7b17905d57d7875bafb1","src/vdaf/dummy.rs":"143cb9b91db66397c8d577e61d1ac53b964c01c900f2e94573a680c1feb895f3","src/vdaf/poplar1.rs":"60f13b1b4b59ea16387675d274b43e9e39d712943642711a904f76f6be315087","src/vdaf/prio2.rs":"ad620cc08d4ff5eeb0e4ecdada80c2ec8929ffbb5d011dae64d21433da0a305b","src/vdaf/prio2/client.rs":"21b9a4acaccc0bddeba78d49c0f296f46a247bd3973873492418470bdb891e5f","src/vdaf/prio2/server.rs":"74771170162c7dae631042bdaf85f9b0371fa83fae2b0984ef8dea9cec49f499","src/vdaf/prio2/test_vector.rs":"9f56d12b79d7d3c0326329364787ee11d15d1a04f6c2e3bf0c25e35180b69411","src/vdaf/prio3.rs":"2970516f222eb911a8411ad7ffabe3dc6d9912d66f10f4999efab64fe842ab38","src/vdaf/prio3_test.rs":"83ad6f43e8d4da1995272a13848dd51f12a82b4b03821ff13d34b8e3d7535e98","src/vdaf/test_vec/08/IdpfPoplar_0.json":"f7cb4d44ac48c4062e4d62d5db9da7d456cc614a91400e90a4ba9796e2bc5db5","src/vdaf/test_vec/08/Poplar1_0.json":"510c406c7709e27a358680a7b42e0ed0950ac32a52d11ca34facc31e2d7026ad","src/vdaf/test_vec/08/Poplar1_1.json":"ff8172582d174befed35bb75d13ebec4b13f5c39eda8ffc771c43497a487809a","src/vdaf/test_vec/08/Poplar1_2.json":"24548c5a29219418f43e6d3cfd11980945a540e0b7a017f152b6d934c1132c78","src/vdaf/test_vec/08/Poplar1_3.json":"dec75bb53311d27428dd96382e1fe2ac66030ee124802f706035fadedd61b0c1","src/vdaf/test_vec/08/Prio3Count_0.json":"58c3aaedecb52147850804cb6033fb5e9636a386f4e1757891d65f4f1efee345","src/vdaf/test_vec/08/Prio3Count_1.json":"2f0f2688925d6789290a3ed9f46fa0815024f4be5ba3bbc46c1e73fb3b824f41","src/vdaf/test_vec/08/Prio3Histogram_0.json":"a14fd6dd9a9e7bfccda2066414db9e89d3fdc9a0531e28e674f70d7786369a7d","src/vdaf/test_vec/08/Prio3Histogram_1.json":"bef205f52aae80a5fef98a8e19b97bb43541c5140ed1dc1509a8a7c7f2cacfe5","src/vdaf/test_vec/08/Prio3SumVec_0.json":"ba07aa0d0435e9c1b4f4bd27ae2eb20d20e2f3c9c35bdeb3b7d0b91d1cdb7245","src/vdaf/test_vec/08/Prio3SumVec_1.json":"32864dc26cb90551bae952c51c65afc52ba9679a1d77c6f0a2b42d46cda7ae50","src/vdaf/test_vec/08/Prio3Sum_0.json":"2710a9e07af08bbc073f70afd18f9ca176f7a0b161dc4902b1db877431b89eb0","src/vdaf/test_vec/08/Prio3Sum_1.json":"1487295734b0381ddee13a8dc98b0b66d04ed0e96b496de7181614c06bdfc369","src/vdaf/test_vec/08/XofFixedKeyAes128.json":"a96370275c08778d7b95b2b3af2156a180a1319b4ff13aa62340fcc39609cd83","src/vdaf/test_vec/08/XofTurboShake128.json":"3444a04c7f0c6f8656847b7580be11dfeffb3f5ed650dc18581a683b662a7695","src/vdaf/test_vec/XofHmacSha256Aes128.json":"58816eaf9b9ec0a87a00f04c8998c40d6e3e5f2a3a678360da42e1b9819ee545","src/vdaf/test_vec/prio2/fieldpriov2.json":"7ba82fcf068dfd5b04fc7fd01ebe5626ea9740be9cd6aa631525f23b80bcd027","src/vdaf/xof.rs":"3ffec960474f73f4ce313dab4bde49d36d4b819e2410935b2d83ca9d8f2f0bd7","src/vidpf.rs":"58f013388a547d9c894be174f85fb9b964bbc866c1ee3206bbdeba960f601b74","tests/discrete_gauss.rs":"abada12c4b5d1f6c9380a6f07312d24eab5d4d189dae20b89d800a85618bd2bd","tests/test_vectors/discrete_gauss_100.json":"f0b33dda1cb19b44be90224af937be9a1af779bd730ae70db59967c843895010","tests/test_vectors/discrete_gauss_2.342.json":"3c3d9a1c69ed235d93b7a483d1386c54381deacb005103b5df3efaa00d583665","tests/test_vectors/discrete_gauss_3.json":"ee3d2208ae3af0a78b9366e72e7d747e36b357ac1ae60394d37defffd483c318","tests/test_vectors/discrete_gauss_41293847.json":"ba752876c5f685bef8c78a2ab9ba4e592e20e4053da856c0329f5283a14ef01d","tests/test_vectors/discrete_gauss_9.json":"2bd50a5ebb17e572bdf7072c352a23b64436d108f2570d95ae0373717c833279","tests/test_vectors/discrete_gauss_9999999999999999999999.json":"1c951ed0590e0beee87e8a007a4b91ec7045b2fa19b35d42b35dce4e7dd80995"},"package":"5cec5eb0d28eee4ea74be34b28ed4c625e88c54ff83c21b412a5ea7cc48624ae"} \ No newline at end of file
diff --git a/third_party/rust/prio/Cargo.toml b/third_party/rust/prio/Cargo.toml
index 6e7bcd7e6e..283a4555d1 100644
--- a/third_party/rust/prio/Cargo.toml
+++ b/third_party/rust/prio/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.64"
+rust-version = "1.71"
name = "prio"
-version = "0.15.3"
+version = "0.16.2"
authors = [
"Josh Aas <jaas@kflag.net>",
"Tim Geoghegan <timg@letsencrypt.org>",
@@ -54,7 +54,7 @@ name = "cycle_counts"
harness = false
[dependencies.aes]
-version = "0.8.3"
+version = "0.8.4"
optional = true
[dependencies.bitvec]
@@ -62,24 +62,29 @@ version = "1.0.1"
optional = true
[dependencies.byteorder]
-version = "1.4.3"
+version = "1.5.0"
[dependencies.ctr]
version = "0.9.2"
optional = true
[dependencies.fiat-crypto]
-version = "0.2.1"
+version = "0.2.6"
optional = true
[dependencies.fixed]
-version = "1.23"
+version = "1.26"
optional = true
[dependencies.getrandom]
-version = "0.2.10"
+version = "0.2.12"
features = ["std"]
+[dependencies.hex]
+version = "0.4.3"
+features = ["serde"]
+optional = true
+
[dependencies.hmac]
version = "0.12.1"
optional = true
@@ -93,11 +98,11 @@ features = [
optional = true
[dependencies.num-integer]
-version = "0.1.45"
+version = "0.1.46"
optional = true
[dependencies.num-iter]
-version = "0.1.43"
+version = "0.1.44"
optional = true
[dependencies.num-rational]
@@ -106,7 +111,7 @@ features = ["serde"]
optional = true
[dependencies.num-traits]
-version = "0.2.16"
+version = "0.2.18"
optional = true
[dependencies.rand]
@@ -117,15 +122,19 @@ optional = true
version = "0.6.4"
[dependencies.rayon]
-version = "1.8.0"
+version = "1.9.0"
optional = true
[dependencies.serde]
version = "1.0"
features = ["derive"]
+[dependencies.serde_json]
+version = "1.0"
+optional = true
+
[dependencies.sha2]
-version = "0.10.7"
+version = "0.10.8"
optional = true
[dependencies.sha3]
@@ -137,11 +146,15 @@ version = "2.5.0"
[dependencies.thiserror]
version = "1.0"
+[dependencies.zipf]
+version = "7.0.1"
+optional = true
+
[dev-dependencies.assert_matches]
version = "1.5.0"
[dev-dependencies.base64]
-version = "0.21.4"
+version = "0.22.0"
[dev-dependencies.cfg-if]
version = "1.0.0"
@@ -152,19 +165,12 @@ version = "0.5"
[dev-dependencies.fixed-macro]
version = "1.2.0"
-[dev-dependencies.hex]
-version = "0.4.3"
-features = ["serde"]
-
[dev-dependencies.hex-literal]
version = "0.4.1"
[dev-dependencies.iai]
version = "0.1"
-[dev-dependencies.itertools]
-version = "0.11.0"
-
[dev-dependencies.modinverse]
version = "0.1.0"
@@ -172,24 +178,20 @@ version = "0.1.0"
version = "0.4.4"
[dev-dependencies.once_cell]
-version = "1.18.0"
+version = "1.19.0"
[dev-dependencies.rand]
version = "0.8"
-[dev-dependencies.serde_json]
-version = "1.0"
-
[dev-dependencies.statrs]
version = "0.16.0"
-[dev-dependencies.zipf]
-version = "7.0.1"
-
[features]
crypto-dependencies = [
"aes",
"ctr",
+ "hmac",
+ "sha2",
]
default = ["crypto-dependencies"]
experimental = [
@@ -204,9 +206,9 @@ experimental = [
"rand",
]
multithreaded = ["rayon"]
-prio2 = [
- "crypto-dependencies",
- "hmac",
- "sha2",
+test-util = [
+ "hex",
+ "rand",
+ "serde_json",
+ "zipf",
]
-test-util = ["rand"]
diff --git a/third_party/rust/prio/README.md b/third_party/rust/prio/README.md
index b81a0150c2..b724eebfb1 100644
--- a/third_party/rust/prio/README.md
+++ b/third_party/rust/prio/README.md
@@ -1,8 +1,6 @@
# libprio-rs
-[![Build Status]][actions] [![Latest Version]][crates.io] [![Docs badge]][docs.rs]
+[![Latest Version]][crates.io] [![Docs badge]][docs.rs]
-[Build Status]: https://github.com/divviup/libprio-rs/workflows/ci-build/badge.svg
-[actions]: https://github.com/divviup/libprio-rs/actions?query=branch%3Amain
[Latest Version]: https://img.shields.io/crates/v/prio.svg
[crates.io]: https://crates.io/crates/prio
[Docs badge]: https://img.shields.io/badge/docs.rs-rustdoc-green
@@ -38,12 +36,13 @@ increases (e.g., 0.10 to 0.11).
| ----- | ---------- | ------------- | ------------- | --------------------- | ------ |
| 0.8 | `release/0.8` | [`draft-irtf-cfrg-vdaf-01`][vdaf-01] | [`draft-ietf-ppm-dap-01`][dap-01] | Yes | Unmaintained as of March 28, 2023 |
| 0.9 | `release/0.9` | [`draft-irtf-cfrg-vdaf-03`][vdaf-03] | [`draft-ietf-ppm-dap-02`][dap-02] and [`draft-ietf-ppm-dap-03`][dap-03] | Yes | Unmaintained as of September 22, 2022 |
-| 0.10 | `release/0.10` | [`draft-irtf-cfrg-vdaf-03`][vdaf-03] | [`draft-ietf-ppm-dap-02`][dap-02] and [`draft-ietf-ppm-dap-03`][dap-03] | Yes | Supported |
+| 0.10 | `release/0.10` | [`draft-irtf-cfrg-vdaf-03`][vdaf-03] | [`draft-ietf-ppm-dap-02`][dap-02] and [`draft-ietf-ppm-dap-03`][dap-03] | Yes | Unmaintained as of November 14, 2023 |
| 0.11 | `release/0.11` | [`draft-irtf-cfrg-vdaf-04`][vdaf-04] | N/A | Yes | Unmaintained |
| 0.12 | `release/0.12` | [`draft-irtf-cfrg-vdaf-05`][vdaf-05] | [`draft-ietf-ppm-dap-04`][dap-04] | Yes | Supported |
| 0.13 | `release/0.13` | [`draft-irtf-cfrg-vdaf-06`][vdaf-06] | [`draft-ietf-ppm-dap-05`][dap-05] | Yes | Unmaintained |
| 0.14 | `release/0.14` | [`draft-irtf-cfrg-vdaf-06`][vdaf-06] | [`draft-ietf-ppm-dap-05`][dap-05] | Yes | Unmaintained |
-| 0.15 | `main` | [`draft-irtf-cfrg-vdaf-07`][vdaf-07] | [`draft-ietf-ppm-dap-06`][dap-06] | Yes | Supported |
+| 0.15 | `release/0.15` | [`draft-irtf-cfrg-vdaf-07`][vdaf-07] | [`draft-ietf-ppm-dap-07`][dap-07] | Yes | Supported |
+| 0.16 | `main` | [`draft-irtf-cfrg-vdaf-08`][vdaf-08] | [`draft-ietf-ppm-dap-09`][dap-09] | Yes | Supported |
[vdaf-01]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/01/
[vdaf-03]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/03/
@@ -51,12 +50,14 @@ increases (e.g., 0.10 to 0.11).
[vdaf-05]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/05/
[vdaf-06]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/06/
[vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+[vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
[dap-01]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/01/
[dap-02]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/02/
[dap-03]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/03/
[dap-04]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/04/
[dap-05]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/05/
-[dap-06]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/06/
+[dap-07]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/07/
+[dap-09]: https://datatracker.ietf.org/doc/draft-ietf-ppm-dap/09/
[enpa]: https://www.abetterinternet.org/post/prio-services-for-covid-en/
[enpa-whitepaper]: https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf
[prio-server]: https://github.com/divviup/prio-server
@@ -68,9 +69,11 @@ increases (e.g., 0.10 to 0.11).
This crate defines the following feature flags:
-|Name|Default feature?|Description|
-|---|---|---|
-|`crypto-dependencies`|Yes|Enables dependencies on various RustCrypto crates, and uses them to implement `XofShake128` to support VDAFs.|
-|`experimental`|No|Certain experimental APIs are guarded by this feature. They may undergo breaking changes in future patch releases, as an exception to semantic versioning.|
-|`multithreaded`|No|Enables certain Prio3 VDAF implementations that use `rayon` for parallelization of gadget evaluations.|
-|`prio2`|No|Enables the Prio v2 API, and a VDAF based on the Prio2 system.|
+|Name|Default feature?|Description|Semver stable?|
+|---|---|---|---|
+|`crypto-dependencies`|Yes|Enables dependencies on various RustCrypto crates, and uses them to implement `XofTurboShake128` to support VDAFs.|✅|
+|`experimental`|No|Certain experimental APIs are guarded by this feature.|❌|
+|`multithreaded`|No|Enables certain Prio3 VDAF implementations that use `rayon` for parallelization of gadget evaluations.|✅|
+|`test-util`|No|Enables test utilities for VDAF users and VDAF implementers.|❌|
+
+Features that are not marked as "Semver stable" may undergo breaking changes in future patch releases, as an exception to semantic versioning.
diff --git a/third_party/rust/prio/benches/cycle_counts.rs b/third_party/rust/prio/benches/cycle_counts.rs
index 43a4ccdad0..5ab704cd44 100644
--- a/third_party/rust/prio/benches/cycle_counts.rs
+++ b/third_party/rust/prio/benches/cycle_counts.rs
@@ -5,15 +5,12 @@ use iai::black_box;
#[cfg(feature = "experimental")]
use prio::{
codec::{Decode, Encode, ParameterizedDecode},
- field::{Field255, FieldElement},
+ field::{Field255, FieldElement, FieldPrio2},
idpf::{Idpf, IdpfInput, IdpfPublicShare, RingBufferCache},
- vdaf::{poplar1::Poplar1IdpfValue, xof::Seed},
-};
-#[cfg(feature = "prio2")]
-use prio::{
- field::FieldPrio2,
vdaf::{
+ poplar1::Poplar1IdpfValue,
prio2::{Prio2, Prio2PrepareShare},
+ xof::Seed,
Aggregator, Share,
},
};
@@ -45,7 +42,7 @@ fn prng_4096() -> Vec<Field128> {
prng(4096)
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_client(size: usize) -> Vec<Share<FieldPrio2, 32>> {
let prio2 = Prio2::new(size).unwrap();
let input = vec![0u32; size];
@@ -53,22 +50,22 @@ fn prio2_client(size: usize) -> Vec<Share<FieldPrio2, 32>> {
prio2.shard(&black_box(input), &black_box(nonce)).unwrap().1
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_client_10() -> Vec<Share<FieldPrio2, 32>> {
prio2_client(10)
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_client_100() -> Vec<Share<FieldPrio2, 32>> {
prio2_client(100)
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_client_1000() -> Vec<Share<FieldPrio2, 32>> {
prio2_client(1000)
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_shard_and_prepare(size: usize) -> Prio2PrepareShare {
let prio2 = Prio2::new(size).unwrap();
let input = vec![0u32; size];
@@ -80,24 +77,24 @@ fn prio2_shard_and_prepare(size: usize) -> Prio2PrepareShare {
.1
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_shard_and_prepare_10() -> Prio2PrepareShare {
prio2_shard_and_prepare(10)
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_shard_and_prepare_100() -> Prio2PrepareShare {
prio2_shard_and_prepare(100)
}
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2_shard_and_prepare_1000() -> Prio2PrepareShare {
prio2_shard_and_prepare(1000)
}
fn prio3_client_count() -> Vec<Prio3InputShare<Field64, 16>> {
let prio3 = Prio3::new_count(2).unwrap();
- let measurement = 1;
+ let measurement = true;
let nonce = [0; 16];
prio3
.shard(&black_box(measurement), &black_box(nonce))
@@ -241,7 +238,7 @@ fn idpf_codec() {
.unwrap();
let bits = 4;
let public_share = IdpfPublicShare::<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>::get_decoded_with_param(&bits, &data).unwrap();
- let encoded = public_share.get_encoded();
+ let encoded = public_share.get_encoded().unwrap();
let _ = black_box(encoded.len());
}
@@ -261,34 +258,10 @@ macro_rules! main_base {
};
}
-#[cfg(feature = "prio2")]
-macro_rules! main_add_prio2 {
- ( $( $func_name:ident ),* $(,)* ) => {
- main_base!(
- prio2_client_10,
- prio2_client_100,
- prio2_client_1000,
- prio2_shard_and_prepare_10,
- prio2_shard_and_prepare_100,
- prio2_shard_and_prepare_1000,
- $( $func_name, )*
- );
- };
-}
-
-#[cfg(not(feature = "prio2"))]
-macro_rules! main_add_prio2 {
- ( $( $func_name:ident ),* $(,)* ) => {
- main_base!(
- $( $func_name, )*
- );
- };
-}
-
#[cfg(feature = "multithreaded")]
macro_rules! main_add_multithreaded {
( $( $func_name:ident ),* $(,)* ) => {
- main_add_prio2!(
+ main_base!(
prio3_client_count_vec_multithreaded_1000,
$( $func_name, )*
);
@@ -298,7 +271,7 @@ macro_rules! main_add_multithreaded {
#[cfg(not(feature = "multithreaded"))]
macro_rules! main_add_multithreaded {
( $( $func_name:ident ),* $(,)* ) => {
- main_add_prio2!(
+ main_base!(
$( $func_name, )*
);
};
@@ -308,6 +281,12 @@ macro_rules! main_add_multithreaded {
macro_rules! main_add_experimental {
( $( $func_name:ident ),* $(,)* ) => {
main_add_multithreaded!(
+ prio2_client_10,
+ prio2_client_100,
+ prio2_client_1000,
+ prio2_shard_and_prepare_10,
+ prio2_shard_and_prepare_100,
+ prio2_shard_and_prepare_1000,
idpf_codec,
idpf_poplar_gen_8,
idpf_poplar_gen_128,
diff --git a/third_party/rust/prio/benches/speed_tests.rs b/third_party/rust/prio/benches/speed_tests.rs
index 66458b1ada..d90085a74d 100644
--- a/third_party/rust/prio/benches/speed_tests.rs
+++ b/third_party/rust/prio/benches/speed_tests.rs
@@ -15,7 +15,9 @@ use num_rational::Ratio;
use num_traits::ToPrimitive;
#[cfg(feature = "experimental")]
use prio::dp::distributions::DiscreteGaussian;
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
+use prio::idpf::test_utils::generate_zipf_distributed_batch;
+#[cfg(feature = "experimental")]
use prio::vdaf::prio2::Prio2;
use prio::{
benchmarked::*,
@@ -35,8 +37,6 @@ use rand::prelude::*;
#[cfg(feature = "experimental")]
use std::iter;
use std::time::Duration;
-#[cfg(feature = "experimental")]
-use zipf::ZipfDistribution;
/// Seed for generation of random benchmark inputs.
///
@@ -116,7 +116,7 @@ fn poly_mul(c: &mut Criterion) {
}
/// Benchmark prio2.
-#[cfg(feature = "prio2")]
+#[cfg(feature = "experimental")]
fn prio2(c: &mut Criterion) {
let mut group = c.benchmark_group("prio2_shard");
for input_length in [10, 100, 1_000] {
@@ -164,14 +164,14 @@ fn prio3(c: &mut Criterion) {
c.bench_function("prio3count_shard", |b| {
let vdaf = Prio3::new_count(num_shares).unwrap();
- let measurement = black_box(1);
+ let measurement = black_box(true);
let nonce = black_box([0u8; 16]);
b.iter(|| vdaf.shard(&measurement, &nonce).unwrap());
});
c.bench_function("prio3count_prepare_init", |b| {
let vdaf = Prio3::new_count(num_shares).unwrap();
- let measurement = black_box(1);
+ let measurement = black_box(true);
let nonce = black_box([0u8; 16]);
let verify_key = black_box([0u8; 16]);
let (public_share, input_shares) = vdaf.shard(&measurement, &nonce).unwrap();
@@ -712,7 +712,7 @@ fn poplar1(c: &mut Criterion) {
for size in test_sizes.iter() {
group.throughput(Throughput::Bytes(*size as u64 / 8));
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
- let vdaf = Poplar1::new_shake128(size);
+ let vdaf = Poplar1::new_turboshake128(size);
let mut rng = StdRng::seed_from_u64(RNG_SEED);
let nonce = rng.gen::<[u8; 16]>();
@@ -736,7 +736,7 @@ fn poplar1(c: &mut Criterion) {
for size in test_sizes.iter() {
group.measurement_time(Duration::from_secs(30)); // slower benchmark
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
- let vdaf = Poplar1::new_shake128(size);
+ let vdaf = Poplar1::new_turboshake128(size);
let mut rng = StdRng::seed_from_u64(RNG_SEED);
b.iter_batched(
@@ -746,7 +746,7 @@ fn poplar1(c: &mut Criterion) {
// Parameters are chosen to match Chris Wood's experimental setup:
// https://github.com/chris-wood/heavy-hitter-comparison
- let (measurements, prefix_tree) = poplar1_generate_zipf_distributed_batch(
+ let (measurements, prefix_tree) = generate_zipf_distributed_batch(
&mut rng, // rng
size, // bits
10, // threshold
@@ -794,83 +794,54 @@ fn poplar1(c: &mut Criterion) {
group.finish();
}
-/// Generate a set of Poplar1 measurements with the given bit length `bits`. They are sampled
-/// according to the Zipf distribution with parameters `zipf_support` and `zipf_exponent`. Return
-/// the measurements, along with the prefix tree for the desired threshold.
-///
-/// The prefix tree consists of a sequence of candidate prefixes for each level. For a given level,
-/// the candidate prefixes are computed from the hit counts of the prefixes at the previous level:
-/// For any prefix `p` whose hit count is at least the desired threshold, add `p || 0` and `p || 1`
-/// to the list.
+/// Benchmark VIDPF performance.
#[cfg(feature = "experimental")]
-fn poplar1_generate_zipf_distributed_batch(
- rng: &mut impl Rng,
- bits: usize,
- threshold: usize,
- measurement_count: usize,
- zipf_support: usize,
- zipf_exponent: f64,
-) -> (Vec<IdpfInput>, Vec<Vec<IdpfInput>>) {
- // Generate random inputs.
- let mut inputs = Vec::with_capacity(zipf_support);
- for _ in 0..zipf_support {
- let bools: Vec<bool> = (0..bits).map(|_| rng.gen()).collect();
- inputs.push(IdpfInput::from_bools(&bools));
- }
+fn vidpf(c: &mut Criterion) {
+ use prio::vidpf::{Vidpf, VidpfInput, VidpfWeight};
- // Sample a number of inputs according to the Zipf distribution.
- let mut samples = Vec::with_capacity(measurement_count);
- let zipf = ZipfDistribution::new(zipf_support, zipf_exponent).unwrap();
- for _ in 0..measurement_count {
- samples.push(inputs[zipf.sample(rng) - 1].clone());
- }
+ let test_sizes = [8usize, 8 * 16, 8 * 256];
+ const NONCE_SIZE: usize = 16;
+ const NONCE: &[u8; NONCE_SIZE] = b"Test Nonce VIDPF";
- // Compute the prefix tree for the desired threshold.
- let mut prefix_tree = Vec::with_capacity(bits);
- prefix_tree.push(vec![
- IdpfInput::from_bools(&[false]),
- IdpfInput::from_bools(&[true]),
- ]);
-
- for level in 0..bits - 1 {
- // Compute the hit count of each prefix from the previous level.
- let mut hit_counts = vec![0; prefix_tree[level].len()];
- for (hit_count, prefix) in hit_counts.iter_mut().zip(prefix_tree[level].iter()) {
- for sample in samples.iter() {
- let mut is_prefix = true;
- for j in 0..prefix.len() {
- if prefix[j] != sample[j] {
- is_prefix = false;
- break;
- }
- }
- if is_prefix {
- *hit_count += 1;
- }
- }
- }
+ let mut group = c.benchmark_group("vidpf_gen");
+ for size in test_sizes.iter() {
+ group.throughput(Throughput::Bytes(*size as u64 / 8));
+ group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
+ let bits = iter::repeat_with(random).take(size).collect::<Vec<bool>>();
+ let input = VidpfInput::from_bools(&bits);
+ let weight = VidpfWeight::from(vec![Field255::one(), Field255::one()]);
- // Compute the next set of candidate prefixes.
- let mut next_prefixes = Vec::new();
- for (hit_count, prefix) in hit_counts.iter().zip(prefix_tree[level].iter()) {
- if *hit_count >= threshold {
- next_prefixes.push(prefix.clone_with_suffix(&[false]));
- next_prefixes.push(prefix.clone_with_suffix(&[true]));
- }
- }
- prefix_tree.push(next_prefixes);
+ let vidpf = Vidpf::<VidpfWeight<Field255>, NONCE_SIZE>::new(2);
+
+ b.iter(|| {
+ let _ = vidpf.gen(&input, &weight, NONCE).unwrap();
+ });
+ });
}
+ group.finish();
- (samples, prefix_tree)
+ let mut group = c.benchmark_group("vidpf_eval");
+ for size in test_sizes.iter() {
+ group.throughput(Throughput::Bytes(*size as u64 / 8));
+ group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
+ let bits = iter::repeat_with(random).take(size).collect::<Vec<bool>>();
+ let input = VidpfInput::from_bools(&bits);
+ let weight = VidpfWeight::from(vec![Field255::one(), Field255::one()]);
+ let vidpf = Vidpf::<VidpfWeight<Field255>, NONCE_SIZE>::new(2);
+
+ let (public, keys) = vidpf.gen(&input, &weight, NONCE).unwrap();
+
+ b.iter(|| {
+ let _ = vidpf.eval(&keys[0], &public, &input, NONCE).unwrap();
+ });
+ });
+ }
+ group.finish();
}
-#[cfg(all(feature = "prio2", feature = "experimental"))]
-criterion_group!(benches, poplar1, prio3, prio2, poly_mul, prng, idpf, dp_noise);
-#[cfg(all(not(feature = "prio2"), feature = "experimental"))]
-criterion_group!(benches, poplar1, prio3, poly_mul, prng, idpf, dp_noise);
-#[cfg(all(feature = "prio2", not(feature = "experimental")))]
-criterion_group!(benches, prio3, prio2, prng, poly_mul);
-#[cfg(all(not(feature = "prio2"), not(feature = "experimental")))]
+#[cfg(feature = "experimental")]
+criterion_group!(benches, poplar1, prio3, prio2, poly_mul, prng, idpf, dp_noise, vidpf);
+#[cfg(not(feature = "experimental"))]
criterion_group!(benches, prio3, prng, poly_mul);
criterion_main!(benches);
diff --git a/third_party/rust/prio/documentation/field_parameters.sage b/third_party/rust/prio/documentation/field_parameters.sage
new file mode 100755
index 0000000000..b83505baac
--- /dev/null
+++ b/third_party/rust/prio/documentation/field_parameters.sage
@@ -0,0 +1,117 @@
+#!/usr/bin/env sage
+
+# This file recomputes the values in src/fp.rs for each FFT-friendly finite
+# field.
+
+import pprint
+
+
+class Field:
+ # The name of the field.
+ name: str
+
+ # The prime modulus that defines the field.
+ modulus: Integer
+
+ # A generator element that generates a large subgroup with an order that's
+ # a power of two. This is _not_ in Montgomery representation.
+ generator_element: Integer
+
+ # The base 2 logarithm of the order of the FFT-friendly multiplicative
+ # subgroup. The generator element will be a 2^num_roots-th root of unity.
+ num_roots: Integer
+
+ def __init__(self, name, modulus, generator_element):
+ assert is_prime(modulus)
+ self.name = name
+ self.modulus = modulus
+ self.generator_element = generator_element
+
+ self.num_roots = None
+ for (prime, power) in factor(modulus - 1):
+ if prime == 2:
+ self.num_roots = power
+ break
+ else:
+ raise Exception(
+ "Multiplicative subgroup order is not a multiple of two"
+ )
+
+ def mu(self):
+ """
+ Computes mu, a constant used during multiplication. It is defined by
+ mu = (-p)^-1 mod r, where r is the modulus implicitly used in wrapping
+ machine word operations.
+ """
+ r = 2 ^ 64
+ return (-self.modulus).inverse_mod(r)
+
+ def r2(self):
+ """
+ Computes R^2 mod p. This constant is used when converting into
+ Montgomery representation. R is the machine word-friendly modulus
+ used in the Montgomery representation.
+ """
+ R = 2 ^ 128
+ return R ^ 2 % self.modulus
+
+ def to_montgomery(self, element):
+ """
+ Transforms an element into its Montgomery representation.
+ """
+ R = 2 ^ 128
+ return element * R % self.modulus
+
+ def bit_mask(self):
+ """
+ An integer with the same bit length as the prime modulus, but with all
+ bits set.
+ """
+ return 2 ^ (self.modulus.nbits()) - 1
+
+ def roots(self):
+ """
+ Returns a list of roots of unity, in Montgomery representation. The
+ value at index i is a 2^i-th root of unity. Note that the first array
+ element will thus be the Montgomery representation of one.
+ """
+ return [
+ self.to_montgomery(
+ pow(
+ self.generator_element,
+ 2 ^ (self.num_roots - i),
+ self.modulus,
+ )
+ )
+ for i in range(min(self.num_roots, 20) + 1)
+ ]
+
+
+FIELDS = [
+ Field(
+ "FieldPrio2",
+ 2 ^ 20 * 4095 + 1,
+ 3925978153,
+ ),
+ Field(
+ "Field64",
+ 2 ^ 32 * 4294967295 + 1,
+ pow(7, 4294967295, 2 ^ 32 * 4294967295 + 1),
+ ),
+ Field(
+ "Field128",
+ 2 ^ 66 * 4611686018427387897 + 1,
+ pow(7, 4611686018427387897, 2 ^ 66 * 4611686018427387897 + 1),
+ ),
+]
+for field in FIELDS:
+ print(field.name)
+ print(f"p: {field.modulus}")
+ print(f"mu: {field.mu()}")
+ print(f"r2: {field.r2()}")
+ print(f"g: {field.to_montgomery(field.generator_element)}")
+ print(f"num_roots: {field.num_roots}")
+ print(f"bit_mask: {field.bit_mask()}")
+ print("roots:")
+ pprint.pprint(field.roots())
+ print()
diff --git a/third_party/rust/prio/src/codec.rs b/third_party/rust/prio/src/codec.rs
index 71f4f8ce5f..98e6299abd 100644
--- a/third_party/rust/prio/src/codec.rs
+++ b/third_party/rust/prio/src/codec.rs
@@ -20,6 +20,7 @@ use std::{
/// An error that occurred during decoding.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum CodecError {
/// An I/O error.
#[error("I/O error")]
@@ -33,6 +34,10 @@ pub enum CodecError {
#[error("length prefix of encoded vector overflows buffer: {0}")]
LengthPrefixTooBig(usize),
+ /// The byte length of a vector exceeded the range of its length prefix.
+ #[error("vector length exceeded range of length prefix")]
+ LengthPrefixOverflow,
+
/// Custom errors from [`Decode`] implementations.
#[error("other error: {0}")]
Other(#[source] Box<dyn Error + 'static + Send + Sync>),
@@ -97,10 +102,10 @@ impl<D: Decode + ?Sized, T> ParameterizedDecode<T> for D {
/// Describes how to encode objects into a byte sequence.
pub trait Encode {
/// Append the encoded form of this object to the end of `bytes`, growing the vector as needed.
- fn encode(&self, bytes: &mut Vec<u8>);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError>;
/// Convenience method to encode a value into a new `Vec<u8>`.
- fn get_encoded(&self) -> Vec<u8> {
+ fn get_encoded(&self) -> Result<Vec<u8>, CodecError> {
self.get_encoded_with_param(&())
}
@@ -116,17 +121,21 @@ pub trait ParameterizedEncode<P> {
/// Append the encoded form of this object to the end of `bytes`, growing the vector as needed.
/// `encoding_parameter` provides details of the wire encoding, used to control how the value
/// is encoded.
- fn encode_with_param(&self, encoding_parameter: &P, bytes: &mut Vec<u8>);
+ fn encode_with_param(
+ &self,
+ encoding_parameter: &P,
+ bytes: &mut Vec<u8>,
+ ) -> Result<(), CodecError>;
/// Convenience method to encode a value into a new `Vec<u8>`.
- fn get_encoded_with_param(&self, encoding_parameter: &P) -> Vec<u8> {
+ fn get_encoded_with_param(&self, encoding_parameter: &P) -> Result<Vec<u8>, CodecError> {
let mut ret = if let Some(length) = self.encoded_len_with_param(encoding_parameter) {
Vec::with_capacity(length)
} else {
Vec::new()
};
- self.encode_with_param(encoding_parameter, &mut ret);
- ret
+ self.encode_with_param(encoding_parameter, &mut ret)?;
+ Ok(ret)
}
/// Returns an optional hint indicating how many bytes will be required to encode this value, or
@@ -139,7 +148,11 @@ pub trait ParameterizedEncode<P> {
/// Provide a blanket implementation so that any [`Encode`] can be used as a
/// `ParameterizedEncode<T>` for any `T`.
impl<E: Encode + ?Sized, T> ParameterizedEncode<T> for E {
- fn encode_with_param(&self, _encoding_parameter: &T, bytes: &mut Vec<u8>) {
+ fn encode_with_param(
+ &self,
+ _encoding_parameter: &T,
+ bytes: &mut Vec<u8>,
+ ) -> Result<(), CodecError> {
self.encode(bytes)
}
@@ -155,7 +168,9 @@ impl Decode for () {
}
impl Encode for () {
- fn encode(&self, _bytes: &mut Vec<u8>) {}
+ fn encode(&self, _bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ Ok(())
+ }
fn encoded_len(&self) -> Option<usize> {
Some(0)
@@ -171,8 +186,9 @@ impl Decode for u8 {
}
impl Encode for u8 {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
bytes.push(*self);
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -187,8 +203,9 @@ impl Decode for u16 {
}
impl Encode for u16 {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
bytes.extend_from_slice(&u16::to_be_bytes(*self));
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -208,9 +225,10 @@ impl Decode for U24 {
}
impl Encode for U24 {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
// Encode lower three bytes of the u32 as u24
bytes.extend_from_slice(&u32::to_be_bytes(self.0)[1..]);
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -225,8 +243,9 @@ impl Decode for u32 {
}
impl Encode for u32 {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
bytes.extend_from_slice(&u32::to_be_bytes(*self));
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -241,8 +260,9 @@ impl Decode for u64 {
}
impl Encode for u64 {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
bytes.extend_from_slice(&u64::to_be_bytes(*self));
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -257,18 +277,19 @@ pub fn encode_u8_items<P, E: ParameterizedEncode<P>>(
bytes: &mut Vec<u8>,
encoding_parameter: &P,
items: &[E],
-) {
+) -> Result<(), CodecError> {
// Reserve space to later write length
let len_offset = bytes.len();
bytes.push(0);
for item in items {
- item.encode_with_param(encoding_parameter, bytes);
+ item.encode_with_param(encoding_parameter, bytes)?;
}
- let len = bytes.len() - len_offset - 1;
- assert!(len <= usize::from(u8::MAX));
- bytes[len_offset] = len as u8;
+ let len =
+ u8::try_from(bytes.len() - len_offset - 1).map_err(|_| CodecError::LengthPrefixOverflow)?;
+ bytes[len_offset] = len;
+ Ok(())
}
/// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of
@@ -292,20 +313,19 @@ pub fn encode_u16_items<P, E: ParameterizedEncode<P>>(
bytes: &mut Vec<u8>,
encoding_parameter: &P,
items: &[E],
-) {
+) -> Result<(), CodecError> {
// Reserve space to later write length
let len_offset = bytes.len();
- 0u16.encode(bytes);
+ 0u16.encode(bytes)?;
for item in items {
- item.encode_with_param(encoding_parameter, bytes);
+ item.encode_with_param(encoding_parameter, bytes)?;
}
- let len = bytes.len() - len_offset - 2;
- assert!(len <= usize::from(u16::MAX));
- for (offset, byte) in u16::to_be_bytes(len as u16).iter().enumerate() {
- bytes[len_offset + offset] = *byte;
- }
+ let len = u16::try_from(bytes.len() - len_offset - 2)
+ .map_err(|_| CodecError::LengthPrefixOverflow)?;
+ bytes[len_offset..len_offset + 2].copy_from_slice(&len.to_be_bytes());
+ Ok(())
}
/// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of
@@ -330,20 +350,22 @@ pub fn encode_u24_items<P, E: ParameterizedEncode<P>>(
bytes: &mut Vec<u8>,
encoding_parameter: &P,
items: &[E],
-) {
+) -> Result<(), CodecError> {
// Reserve space to later write length
let len_offset = bytes.len();
- U24(0).encode(bytes);
+ U24(0).encode(bytes)?;
for item in items {
- item.encode_with_param(encoding_parameter, bytes);
+ item.encode_with_param(encoding_parameter, bytes)?;
}
- let len = bytes.len() - len_offset - 3;
- assert!(len <= 0xffffff);
- for (offset, byte) in u32::to_be_bytes(len as u32)[1..].iter().enumerate() {
- bytes[len_offset + offset] = *byte;
+ let len = u32::try_from(bytes.len() - len_offset - 3)
+ .map_err(|_| CodecError::LengthPrefixOverflow)?;
+ if len > 0xffffff {
+ return Err(CodecError::LengthPrefixOverflow);
}
+ bytes[len_offset..len_offset + 3].copy_from_slice(&len.to_be_bytes()[1..]);
+ Ok(())
}
/// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of
@@ -368,20 +390,19 @@ pub fn encode_u32_items<P, E: ParameterizedEncode<P>>(
bytes: &mut Vec<u8>,
encoding_parameter: &P,
items: &[E],
-) {
+) -> Result<(), CodecError> {
// Reserve space to later write length
let len_offset = bytes.len();
- 0u32.encode(bytes);
+ 0u32.encode(bytes)?;
for item in items {
- item.encode_with_param(encoding_parameter, bytes);
+ item.encode_with_param(encoding_parameter, bytes)?;
}
- let len = bytes.len() - len_offset - 4;
- let len: u32 = len.try_into().expect("Length too large");
- for (offset, byte) in len.to_be_bytes().iter().enumerate() {
- bytes[len_offset + offset] = *byte;
- }
+ let len = u32::try_from(bytes.len() - len_offset - 4)
+ .map_err(|_| CodecError::LengthPrefixOverflow)?;
+ bytes[len_offset..len_offset + 4].copy_from_slice(&len.to_be_bytes());
+ Ok(())
}
/// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of
@@ -432,6 +453,7 @@ fn decode_items<P, D: ParameterizedDecode<P>>(
#[cfg(test)]
mod tests {
+ use std::io::ErrorKind;
use super::*;
use assert_matches::assert_matches;
@@ -439,7 +461,7 @@ mod tests {
#[test]
fn encode_nothing() {
let mut bytes = vec![];
- ().encode(&mut bytes);
+ ().encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), 0);
}
@@ -448,7 +470,7 @@ mod tests {
let value = 100u8;
let mut bytes = vec![];
- value.encode(&mut bytes);
+ value.encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), 1);
let decoded = u8::decode(&mut Cursor::new(&bytes)).unwrap();
@@ -460,7 +482,7 @@ mod tests {
let value = 1000u16;
let mut bytes = vec![];
- value.encode(&mut bytes);
+ value.encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), 2);
// Check endianness of encoding
assert_eq!(bytes, vec![3, 232]);
@@ -474,7 +496,7 @@ mod tests {
let value = U24(1_000_000u32);
let mut bytes = vec![];
- value.encode(&mut bytes);
+ value.encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), 3);
// Check endianness of encoding
assert_eq!(bytes, vec![15, 66, 64]);
@@ -488,7 +510,7 @@ mod tests {
let value = 134_217_728u32;
let mut bytes = vec![];
- value.encode(&mut bytes);
+ value.encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), 4);
// Check endianness of encoding
assert_eq!(bytes, vec![8, 0, 0, 0]);
@@ -502,7 +524,7 @@ mod tests {
let value = 137_438_953_472u64;
let mut bytes = vec![];
- value.encode(&mut bytes);
+ value.encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), 8);
// Check endianness of encoding
assert_eq!(bytes, vec![0, 0, 0, 32, 0, 0, 0, 0]);
@@ -521,12 +543,12 @@ mod tests {
}
impl Encode for TestMessage {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.field_u8.encode(bytes);
- self.field_u16.encode(bytes);
- self.field_u24.encode(bytes);
- self.field_u32.encode(bytes);
- self.field_u64.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.field_u8.encode(bytes)?;
+ self.field_u16.encode(bytes)?;
+ self.field_u24.encode(bytes)?;
+ self.field_u32.encode(bytes)?;
+ self.field_u64.encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -584,7 +606,7 @@ mod tests {
};
let mut bytes = vec![];
- value.encode(&mut bytes);
+ value.encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), TestMessage::encoded_length());
assert_eq!(value.encoded_len().unwrap(), TestMessage::encoded_length());
@@ -622,7 +644,7 @@ mod tests {
fn roundtrip_variable_length_u8() {
let values = messages_vec();
let mut bytes = vec![];
- encode_u8_items(&mut bytes, &(), &values);
+ encode_u8_items(&mut bytes, &(), &values).unwrap();
assert_eq!(
bytes.len(),
@@ -640,7 +662,7 @@ mod tests {
fn roundtrip_variable_length_u16() {
let values = messages_vec();
let mut bytes = vec![];
- encode_u16_items(&mut bytes, &(), &values);
+ encode_u16_items(&mut bytes, &(), &values).unwrap();
assert_eq!(
bytes.len(),
@@ -661,7 +683,7 @@ mod tests {
fn roundtrip_variable_length_u24() {
let values = messages_vec();
let mut bytes = vec![];
- encode_u24_items(&mut bytes, &(), &values);
+ encode_u24_items(&mut bytes, &(), &values).unwrap();
assert_eq!(
bytes.len(),
@@ -682,7 +704,7 @@ mod tests {
fn roundtrip_variable_length_u32() {
let values = messages_vec();
let mut bytes = Vec::new();
- encode_u32_items(&mut bytes, &(), &values);
+ encode_u32_items(&mut bytes, &(), &values).unwrap();
assert_eq!(bytes.len(), 4 + 3 * TestMessage::encoded_length());
@@ -697,6 +719,21 @@ mod tests {
}
#[test]
+ fn decode_too_short() {
+ let values = messages_vec();
+ let mut bytes = Vec::new();
+ encode_u32_items(&mut bytes, &(), &values).unwrap();
+
+ let error =
+ decode_u32_items::<_, TestMessage>(&(), &mut Cursor::new(&bytes[..3])).unwrap_err();
+ assert_matches!(error, CodecError::Io(e) => assert_eq!(e.kind(), ErrorKind::UnexpectedEof));
+
+ let error =
+ decode_u32_items::<_, TestMessage>(&(), &mut Cursor::new(&bytes[..4])).unwrap_err();
+ assert_matches!(error, CodecError::LengthPrefixTooBig(_));
+ }
+
+ #[test]
fn decode_items_overflow() {
let encoded = vec![1u8];
@@ -724,11 +761,56 @@ mod tests {
#[test]
fn length_hint_correctness() {
- assert_eq!(().encoded_len().unwrap(), ().get_encoded().len());
- assert_eq!(0u8.encoded_len().unwrap(), 0u8.get_encoded().len());
- assert_eq!(0u16.encoded_len().unwrap(), 0u16.get_encoded().len());
- assert_eq!(U24(0).encoded_len().unwrap(), U24(0).get_encoded().len());
- assert_eq!(0u32.encoded_len().unwrap(), 0u32.get_encoded().len());
- assert_eq!(0u64.encoded_len().unwrap(), 0u64.get_encoded().len());
+ assert_eq!(().encoded_len().unwrap(), ().get_encoded().unwrap().len());
+ assert_eq!(0u8.encoded_len().unwrap(), 0u8.get_encoded().unwrap().len());
+ assert_eq!(
+ 0u16.encoded_len().unwrap(),
+ 0u16.get_encoded().unwrap().len()
+ );
+ assert_eq!(
+ U24(0).encoded_len().unwrap(),
+ U24(0).get_encoded().unwrap().len()
+ );
+ assert_eq!(
+ 0u32.encoded_len().unwrap(),
+ 0u32.get_encoded().unwrap().len()
+ );
+ assert_eq!(
+ 0u64.encoded_len().unwrap(),
+ 0u64.get_encoded().unwrap().len()
+ );
+ }
+
+ #[test]
+ fn get_decoded_leftover() {
+ let encoded_good = [1, 2, 3, 4];
+ assert_matches!(u32::get_decoded(&encoded_good).unwrap(), 0x01020304u32);
+
+ let encoded_bad = [1, 2, 3, 4, 5];
+ let error = u32::get_decoded(&encoded_bad).unwrap_err();
+ assert_matches!(error, CodecError::BytesLeftOver(1));
+ }
+
+ #[test]
+ fn encoded_len_backwards_compatibility() {
+ struct MyMessage;
+
+ impl Encode for MyMessage {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ bytes.extend_from_slice(b"Hello, world");
+ Ok(())
+ }
+ }
+
+ assert_eq!(MyMessage.encoded_len(), None);
+
+ assert_eq!(MyMessage.get_encoded().unwrap(), b"Hello, world");
+ }
+
+ #[test]
+ fn encode_length_prefix_overflow() {
+ let mut bytes = Vec::new();
+ let error = encode_u8_items(&mut bytes, &(), &[1u8; u8::MAX as usize + 1]).unwrap_err();
+ assert_matches!(error, CodecError::LengthPrefixOverflow);
}
}
diff --git a/third_party/rust/prio/src/dp.rs b/third_party/rust/prio/src/dp.rs
index 506676dbb9..6ed4f2afdf 100644
--- a/third_party/rust/prio/src/dp.rs
+++ b/third_party/rust/prio/src/dp.rs
@@ -20,6 +20,7 @@ use serde::{Deserialize, Serialize};
/// Errors propagated by methods in this module.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum DpError {
/// Tried to use an invalid float as privacy parameter.
#[error(
diff --git a/third_party/rust/prio/src/dp/distributions.rs b/third_party/rust/prio/src/dp/distributions.rs
index ba0270df9c..5fc42f96ec 100644
--- a/third_party/rust/prio/src/dp/distributions.rs
+++ b/third_party/rust/prio/src/dp/distributions.rs
@@ -292,7 +292,7 @@ mod tests {
use super::*;
use crate::dp::Rational;
- use crate::vdaf::xof::SeedStreamSha3;
+ use crate::vdaf::xof::SeedStreamTurboShake128;
use num_bigint::{BigUint, Sign, ToBigInt, ToBigUint};
use num_traits::{One, Signed, ToPrimitive};
@@ -306,15 +306,15 @@ mod tests {
DiscreteGaussian::new(Ratio::<BigUint>::from_integer(BigUint::from(5u8))).unwrap();
// check samples are consistent
- let mut rng = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]);
let samples: Vec<i8> = (0..10)
.map(|_| i8::try_from(sampler.sample(&mut rng)).unwrap())
.collect();
let samples1: Vec<i8> = (0..10)
.map(|_| i8::try_from(sampler.sample(&mut rng)).unwrap())
.collect();
- assert_eq!(samples, vec![-3, -11, -3, 5, 1, 5, 2, 2, 1, 18]);
- assert_eq!(samples1, vec![4, -4, -5, -2, 0, -5, -3, 1, 1, -2]);
+ assert_eq!(samples, vec![0, -3, -2, 3, 2, -1, -5, 4, -7, -5]);
+ assert_eq!(samples1, vec![2, 7, -8, -3, 1, -3, -3, 6, -3, -1]);
}
#[test]
@@ -325,7 +325,7 @@ mod tests {
// sample from a manually created distribution
let sampler1 =
DiscreteGaussian::new(Ratio::<BigUint>::from_integer(BigUint::from(4u8))).unwrap();
- let mut rng = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]);
let samples1: Vec<i8> = (0..10)
.map(|_| i8::try_from(sampler1.sample(&mut rng)).unwrap())
.collect();
@@ -337,7 +337,7 @@ mod tests {
let sampler2 = zcdp
.create_distribution(Ratio::<BigUint>::from_integer(1u8.into()))
.unwrap();
- let mut rng2 = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng2 = SeedStreamTurboShake128::from_seed([0u8; 16]);
let samples2: Vec<i8> = (0..10)
.map(|_| i8::try_from(sampler2.sample(&mut rng2)).unwrap())
.collect();
@@ -485,7 +485,7 @@ mod tests {
.unwrap();
// collect that number of samples
- let mut rng = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]);
let samples: Vec<BigInt> = (1..n_samples)
.map(|_| {
sample_discrete_gaussian(&Ratio::<BigUint>::from_integer(sigma.clone()), &mut rng)
@@ -519,7 +519,7 @@ mod tests {
#[test]
fn empirical_test_gauss() {
[100, 2000, 20000].iter().for_each(|p| {
- let mut rng = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]);
let sampler = || {
sample_discrete_gaussian(
&Ratio::<BigUint>::from_integer((*p).to_biguint().unwrap()),
@@ -541,7 +541,7 @@ mod tests {
#[test]
fn empirical_test_bernoulli_mean() {
[2u8, 5u8, 7u8, 9u8].iter().for_each(|p| {
- let mut rng = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]);
let sampler = || {
if sample_bernoulli(
&Ratio::<BigUint>::new(BigUint::one(), (*p).into()),
@@ -565,7 +565,7 @@ mod tests {
#[test]
fn empirical_test_geometric_mean() {
[2u8, 5u8, 7u8, 9u8].iter().for_each(|p| {
- let mut rng = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]);
let sampler = || {
sample_geometric_exp(
&Ratio::<BigUint>::new(BigUint::one(), (*p).into()),
@@ -588,7 +588,7 @@ mod tests {
#[test]
fn empirical_test_laplace_mean() {
[2u8, 5u8, 7u8, 9u8].iter().for_each(|p| {
- let mut rng = SeedStreamSha3::from_seed([0u8; 16]);
+ let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]);
let sampler = || {
sample_discrete_laplace(
&Ratio::<BigUint>::new(BigUint::one(), (*p).into()),
diff --git a/third_party/rust/prio/src/fft.rs b/third_party/rust/prio/src/fft.rs
index cac59a89ea..612013eb45 100644
--- a/third_party/rust/prio/src/fft.rs
+++ b/third_party/rust/prio/src/fft.rs
@@ -10,6 +10,7 @@ use std::convert::TryFrom;
/// An error returned by an FFT operation.
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
+#[non_exhaustive]
pub enum FftError {
/// The output is too small.
#[error("output slice is smaller than specified size")]
diff --git a/third_party/rust/prio/src/field.rs b/third_party/rust/prio/src/field.rs
index fb931de2d3..e6cd5c105d 100644
--- a/third_party/rust/prio/src/field.rs
+++ b/third_party/rust/prio/src/field.rs
@@ -7,7 +7,6 @@
//! [`FftFriendlyFieldElement`], and have an associated element called the "generator" that
//! generates a multiplicative subgroup of order `2^n` for some `n`.
-#[cfg(feature = "crypto-dependencies")]
use crate::prng::{Prng, PrngError};
use crate::{
codec::{CodecError, Decode, Encode},
@@ -25,8 +24,8 @@ use std::{
io::{Cursor, Read},
marker::PhantomData,
ops::{
- Add, AddAssign, BitAnd, ControlFlow, Div, DivAssign, Mul, MulAssign, Neg, Shl, Shr, Sub,
- SubAssign,
+ Add, AddAssign, BitAnd, ControlFlow, Div, DivAssign, Mul, MulAssign, Neg, Range, Shl, Shr,
+ Sub, SubAssign,
},
};
use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable, ConstantTimeEq};
@@ -39,6 +38,7 @@ pub use field255::Field255;
/// Possible errors from finite field operations.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum FieldError {
/// Input sizes do not match.
#[error("input sizes do not match")]
@@ -46,19 +46,24 @@ pub enum FieldError {
/// Returned when decoding a [`FieldElement`] from a too-short byte string.
#[error("short read from bytes")]
ShortRead,
- /// Returned when decoding a [`FieldElement`] from a byte string that encodes an integer greater
- /// than or equal to the field modulus.
- #[error("read from byte slice exceeds modulus")]
+ /// Returned when converting an integer to a [`FieldElement`] if the integer is greater than or
+ /// equal to the field modulus.
+ #[error("input value exceeds modulus")]
ModulusOverflow,
/// Error while performing I/O.
#[error("I/O error")]
Io(#[from] std::io::Error),
/// Error encoding or decoding a field.
#[error("Codec error")]
- Codec(#[from] CodecError),
+ #[deprecated]
+ Codec(CodecError),
/// Error converting to [`FieldElementWithInteger::Integer`].
#[error("Integer TryFrom error")]
IntegerTryFrom,
+ /// Returned when encoding an integer to "bitvector representation", or decoding from the same,
+ /// if the number of bits is larger than the bit length of the field's modulus.
+ #[error("bit vector length exceeds modulus bit length")]
+ BitVectorTooLong,
}
/// Objects with this trait represent an element of `GF(p)` for some prime `p`.
@@ -100,8 +105,8 @@ pub trait FieldElement:
fn inv(&self) -> Self;
/// Interprets the next [`Self::ENCODED_SIZE`] bytes from the input slice as an element of the
- /// field. The `m` most significant bits are cleared, where `m` is equal to the length of
- /// [`Self::Integer`] in bits minus the length of the modulus in bits.
+ /// field. Any of the most significant bits beyond the bit length of the modulus will be
+ /// cleared, in order to minimize the amount of rejection sampling needed.
///
/// # Errors
///
@@ -110,9 +115,9 @@ pub trait FieldElement:
///
/// # Warnings
///
- /// This function should only be used within [`prng::Prng`] to convert a random byte string into
- /// a field element. Use [`Self::decode`] to deserialize field elements. Use
- /// [`field::rand`] or [`prng::Prng`] to randomly generate field elements.
+ /// This function should only be used internally to convert a random byte string into
+ /// a field element. Use [`Decode::decode`] to deserialize field elements. Use
+ /// [`random_vector`] to randomly generate field elements.
#[doc(hidden)]
fn try_from_random(bytes: &[u8]) -> Result<Self, FieldError>;
@@ -129,9 +134,10 @@ pub trait FieldElement:
/// Ideally we would implement `From<&[F: FieldElement]> for Vec<u8>` or the corresponding
/// `Into`, but the orphan rule and the stdlib's blanket implementations of `Into` make this
/// impossible.
+ #[deprecated]
fn slice_into_byte_vec(values: &[Self]) -> Vec<u8> {
let mut vec = Vec::with_capacity(values.len() * Self::ENCODED_SIZE);
- encode_fieldvec(values, &mut vec);
+ encode_fieldvec(values, &mut vec).unwrap();
vec
}
@@ -149,18 +155,49 @@ pub trait FieldElement:
/// Ideally we would implement `From<&[u8]> for Vec<F: FieldElement>` or the corresponding
/// `Into`, but the orphan rule and the stdlib's blanket implementations of `Into` make this
/// impossible.
+ #[deprecated]
fn byte_slice_into_vec(bytes: &[u8]) -> Result<Vec<Self>, FieldError> {
if bytes.len() % Self::ENCODED_SIZE != 0 {
return Err(FieldError::ShortRead);
}
let mut vec = Vec::with_capacity(bytes.len() / Self::ENCODED_SIZE);
for chunk in bytes.chunks_exact(Self::ENCODED_SIZE) {
- vec.push(Self::get_decoded(chunk)?);
+ #[allow(deprecated)]
+ vec.push(Self::get_decoded(chunk).map_err(FieldError::Codec)?);
}
Ok(vec)
}
}
+/// An integer type that accompanies a finite field. Integers and field elements may be converted
+/// back and forth via the natural map between residue classes modulo 'p' and integers between 0
+/// and p - 1.
+pub trait Integer:
+ Debug
+ + Eq
+ + Ord
+ + BitAnd<Output = Self>
+ + Div<Output = Self>
+ + Shl<usize, Output = Self>
+ + Shr<usize, Output = Self>
+ + Add<Output = Self>
+ + Sub<Output = Self>
+ + TryFrom<usize, Error = Self::TryFromUsizeError>
+ + TryInto<u64, Error = Self::TryIntoU64Error>
+{
+ /// The error returned if converting `usize` to this integer type fails.
+ type TryFromUsizeError: std::error::Error;
+
+ /// The error returned if converting this integer type to a `u64` fails.
+ type TryIntoU64Error: std::error::Error;
+
+ /// Returns zero.
+ fn zero() -> Self;
+
+ /// Returns one.
+ fn one() -> Self;
+}
+
/// Extension trait for field elements that can be converted back and forth to an integer type.
///
/// The `Integer` associated type is an integer (primitive or otherwise) that supports various
@@ -168,104 +205,95 @@ pub trait FieldElement:
/// integer type. This trait also defines methods on field elements, `pow` and `modulus`, that make
/// use of the associated integer type.
pub trait FieldElementWithInteger: FieldElement + From<Self::Integer> {
- /// The error returned if converting `usize` to an `Integer` fails.
- type IntegerTryFromError: std::error::Error;
-
- /// The error returned if converting an `Integer` to a `u64` fails.
- type TryIntoU64Error: std::error::Error;
-
/// The integer representation of a field element.
- type Integer: Copy
- + Debug
- + Eq
- + Ord
- + BitAnd<Output = Self::Integer>
- + Div<Output = Self::Integer>
- + Shl<usize, Output = Self::Integer>
- + Shr<usize, Output = Self::Integer>
- + Add<Output = Self::Integer>
- + Sub<Output = Self::Integer>
- + From<Self>
- + TryFrom<usize, Error = Self::IntegerTryFromError>
- + TryInto<u64, Error = Self::TryIntoU64Error>;
+ type Integer: Integer + From<Self> + Copy;
/// Modular exponentation, i.e., `self^exp (mod p)`.
fn pow(&self, exp: Self::Integer) -> Self;
/// Returns the prime modulus `p`.
fn modulus() -> Self::Integer;
-}
-
-/// Methods common to all `FieldElementWithInteger` implementations that are private to the crate.
-pub(crate) trait FieldElementWithIntegerExt: FieldElementWithInteger {
- /// Encode `input` as bitvector of elements of `Self`. Output is written into the `output` slice.
- /// If `output.len()` is smaller than the number of bits required to respresent `input`,
- /// an error is returned.
- ///
- /// # Arguments
+ /// Encode the integer `input` as a sequence of bits in two's complement representation, least
+ /// significant bit first, and then map each bit to a field element.
///
- /// * `input` - The field element to encode
- /// * `output` - The slice to write the encoded bits into. Least signicant bit comes first
- fn fill_with_bitvector_representation(
- input: &Self::Integer,
- output: &mut [Self],
- ) -> Result<(), FieldError> {
- // Create a mutable copy of `input`. In each iteration of the following loop we take the
- // least significant bit, and shift input to the right by one bit.
- let mut i = *input;
-
- let one = Self::Integer::from(Self::one());
- for bit in output.iter_mut() {
- let w = Self::from(i & one);
- *bit = w;
- i = i >> 1;
+ /// Returns an error if `input` cannot be represented with `bits` many bits, or if `bits`
+ /// is larger than the bit width of the field's modulus.
+ fn encode_as_bitvector(
+ input: Self::Integer,
+ bits: usize,
+ ) -> Result<BitvectorRepresentationIter<Self>, FieldError> {
+ // Check if `bits` is too large for this field.
+ if !Self::valid_integer_bitlength(bits) {
+ return Err(FieldError::BitVectorTooLong);
}
- // If `i` is still not zero, this means that it cannot be encoded by `bits` bits.
- if i != Self::Integer::from(Self::zero()) {
+ // Check if the input value can be represented in the requested number of bits by shifting
+ // it. The above check on `bits` ensures this shift won't panic due to the shift width
+ // being too large.
+ if input >> bits != Self::Integer::zero() {
return Err(FieldError::InputSizeMismatch);
}
- Ok(())
+ Ok(BitvectorRepresentationIter {
+ inner: 0..bits,
+ input,
+ })
}
- /// Encode `input` as `bits`-bit vector of elements of `Self` if it's small enough
- /// to be represented with that many bits.
- ///
- /// # Arguments
+ /// Inverts the encoding done by [`Self::encode_as_bitvector`], and returns a single field
+ /// element.
///
- /// * `input` - The field element to encode
- /// * `bits` - The number of bits to use for the encoding
- fn encode_into_bitvector_representation(
- input: &Self::Integer,
- bits: usize,
- ) -> Result<Vec<Self>, FieldError> {
- let mut result = vec![Self::zero(); bits];
- Self::fill_with_bitvector_representation(input, &mut result)?;
- Ok(result)
- }
-
- /// Decode the bitvector-represented value `input` into a simple representation as a single
- /// field element.
+ /// This performs an inner product between the input vector of field elements and successive
+ /// powers of two (starting with 2^0 = 1). If the input came from [`Self::encode_as_bitvector`],
+ /// then the result will be equal to the originally encoded integer, projected into the field.
///
- /// # Errors
+ /// Note that this decoding operation is linear, so it can be applied to secret shares of an
+ /// encoded integer, and if the results are summed up, it will be equal to the encoded integer.
///
- /// This function errors if `2^input.len() - 1` does not fit into the field `Self`.
- fn decode_from_bitvector_representation(input: &[Self]) -> Result<Self, FieldError> {
- let fi_one = Self::Integer::from(Self::one());
-
+ /// Returns an error if the length of the input is larger than the bit width of the field's
+ /// modulus.
+ fn decode_bitvector(input: &[Self]) -> Result<Self, FieldError> {
if !Self::valid_integer_bitlength(input.len()) {
- return Err(FieldError::ModulusOverflow);
+ return Err(FieldError::BitVectorTooLong);
}
let mut decoded = Self::zero();
- for (l, bit) in input.iter().enumerate() {
- let w = fi_one << l;
- decoded += Self::from(w) * *bit;
+ let one = Self::one();
+ let two = one + one;
+ let mut power_of_two = one;
+ for value in input.iter() {
+ decoded += *value * power_of_two;
+ power_of_two *= two;
}
Ok(decoded)
}
+}
+
+/// This iterator returns a sequence of field elements that are equal to zero or one, representing
+/// some integer in two's complement form. See [`FieldElementWithInteger::encode_as_bitvector`].
+// Note that this is implemented with a separate struct, instead of using the map combinator,
+// because return_position_impl_trait_in_trait is not yet stable.
+#[derive(Debug, Clone)]
+pub struct BitvectorRepresentationIter<F: FieldElementWithInteger> {
+ inner: Range<usize>,
+ input: F::Integer,
+}
+
+impl<F> Iterator for BitvectorRepresentationIter<F>
+where
+ F: FieldElementWithInteger,
+{
+ type Item = F;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ let bit_offset = self.inner.next()?;
+ Some(F::from((self.input >> bit_offset) & F::Integer::one()))
+ }
+}
+/// Methods common to all `FieldElementWithInteger` implementations that are private to the crate.
+pub(crate) trait FieldElementWithIntegerExt: FieldElementWithInteger {
/// Interpret `i` as [`Self::Integer`] if it's representable in that type and smaller than the
/// field modulus.
fn valid_integer_try_from<N>(i: N) -> Result<Self::Integer, FieldError>
@@ -285,7 +313,7 @@ pub(crate) trait FieldElementWithIntegerExt: FieldElementWithInteger {
if bits >= 8 * Self::ENCODED_SIZE {
return false;
}
- if Self::modulus() >> bits != Self::Integer::from(Self::zero()) {
+ if Self::modulus() >> bits != Self::Integer::zero() {
return true;
}
false
@@ -382,7 +410,7 @@ macro_rules! make_field {
///
/// As an invariant, this integer representing the field element in the Montgomery domain
/// must be less than the field modulus, `p`.
- #[derive(Clone, Copy, PartialOrd, Ord, Default)]
+ #[derive(Clone, Copy, Default)]
pub struct $elem(u128);
impl $elem {
@@ -640,9 +668,10 @@ macro_rules! make_field {
}
impl Encode for $elem {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
let slice = <[u8; $elem::ENCODED_SIZE]>::from(*self);
bytes.extend_from_slice(&slice);
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -683,8 +712,6 @@ macro_rules! make_field {
impl FieldElementWithInteger for $elem {
type Integer = $int;
- type IntegerTryFromError = <Self::Integer as TryFrom<usize>>::Error;
- type TryIntoU64Error = <Self::Integer as TryInto<u64>>::Error;
fn pow(&self, exp: Self::Integer) -> Self {
// FieldParameters::pow() relies on mul(), and will always return a value less
@@ -717,6 +744,45 @@ macro_rules! make_field {
};
}
+impl Integer for u32 {
+ type TryFromUsizeError = <Self as TryFrom<usize>>::Error;
+ type TryIntoU64Error = <Self as TryInto<u64>>::Error;
+
+ fn zero() -> Self {
+ 0
+ }
+
+ fn one() -> Self {
+ 1
+ }
+}
+
+impl Integer for u64 {
+ type TryFromUsizeError = <Self as TryFrom<usize>>::Error;
+ type TryIntoU64Error = <Self as TryInto<u64>>::Error;
+
+ fn zero() -> Self {
+ 0
+ }
+
+ fn one() -> Self {
+ 1
+ }
+}
+
+impl Integer for u128 {
+ type TryFromUsizeError = <Self as TryFrom<usize>>::Error;
+ type TryIntoU64Error = <Self as TryInto<u64>>::Error;
+
+ fn zero() -> Self {
+ 0
+ }
+
+ fn one() -> Self {
+ 1
+ }
+}
+
make_field!(
/// Same as Field32, but encoded in little endian for compatibility with Prio v2.
FieldPrio2,
@@ -761,7 +827,7 @@ pub(crate) fn merge_vector<F: FieldElement>(
}
/// Outputs an additive secret sharing of the input.
-#[cfg(all(feature = "crypto-dependencies", test))]
+#[cfg(test)]
pub(crate) fn split_vector<F: FieldElement>(
inp: &[F],
num_shares: usize,
@@ -785,18 +851,20 @@ pub(crate) fn split_vector<F: FieldElement>(
}
/// Generate a vector of uniformly distributed random field elements.
-#[cfg(feature = "crypto-dependencies")]
-#[cfg_attr(docsrs, doc(cfg(feature = "crypto-dependencies")))]
pub fn random_vector<F: FieldElement>(len: usize) -> Result<Vec<F>, PrngError> {
Ok(Prng::new()?.take(len).collect())
}
/// `encode_fieldvec` serializes a type that is equivalent to a vector of field elements.
#[inline(always)]
-pub(crate) fn encode_fieldvec<F: FieldElement, T: AsRef<[F]>>(val: T, bytes: &mut Vec<u8>) {
+pub(crate) fn encode_fieldvec<F: FieldElement, T: AsRef<[F]>>(
+ val: T,
+ bytes: &mut Vec<u8>,
+) -> Result<(), CodecError> {
for elem in val.as_ref() {
- elem.encode(bytes);
+ elem.encode(bytes)?;
}
+ Ok(())
}
/// `decode_fieldvec` deserializes some number of field elements from a cursor, and advances the
@@ -822,16 +890,14 @@ pub(crate) fn decode_fieldvec<F: FieldElement>(
#[cfg(test)]
pub(crate) mod test_utils {
- use super::{FieldElement, FieldElementWithInteger};
+ use super::{FieldElement, FieldElementWithInteger, Integer};
use crate::{codec::CodecError, field::FieldError, prng::Prng};
use assert_matches::assert_matches;
use std::{
collections::hash_map::DefaultHasher,
- convert::{TryFrom, TryInto},
- fmt::Debug,
+ convert::TryFrom,
hash::{Hash, Hasher},
io::Cursor,
- ops::{Add, BitAnd, Div, Shl, Shr, Sub},
};
/// A test-only copy of `FieldElementWithInteger`.
@@ -842,42 +908,30 @@ pub(crate) mod test_utils {
/// requires the `Integer` associated type satisfy `Clone`, not `Copy`, so that it may be used
/// with arbitrary precision integer implementations.
pub(crate) trait TestFieldElementWithInteger:
- FieldElement + From<Self::Integer>
+ FieldElement + From<Self::TestInteger>
{
type IntegerTryFromError: std::error::Error;
type TryIntoU64Error: std::error::Error;
- type Integer: Clone
- + Debug
- + Eq
- + Ord
- + BitAnd<Output = Self::Integer>
- + Div<Output = Self::Integer>
- + Shl<usize, Output = Self::Integer>
- + Shr<usize, Output = Self::Integer>
- + Add<Output = Self::Integer>
- + Sub<Output = Self::Integer>
- + From<Self>
- + TryFrom<usize, Error = Self::IntegerTryFromError>
- + TryInto<u64, Error = Self::TryIntoU64Error>;
-
- fn pow(&self, exp: Self::Integer) -> Self;
-
- fn modulus() -> Self::Integer;
+ type TestInteger: Integer + From<Self> + Clone;
+
+ fn pow(&self, exp: Self::TestInteger) -> Self;
+
+ fn modulus() -> Self::TestInteger;
}
impl<F> TestFieldElementWithInteger for F
where
F: FieldElementWithInteger,
{
- type IntegerTryFromError = <F as FieldElementWithInteger>::IntegerTryFromError;
- type TryIntoU64Error = <F as FieldElementWithInteger>::TryIntoU64Error;
- type Integer = <F as FieldElementWithInteger>::Integer;
+ type IntegerTryFromError = <F::Integer as Integer>::TryFromUsizeError;
+ type TryIntoU64Error = <F::Integer as Integer>::TryIntoU64Error;
+ type TestInteger = F::Integer;
- fn pow(&self, exp: Self::Integer) -> Self {
+ fn pow(&self, exp: Self::TestInteger) -> Self {
<F as FieldElementWithInteger>::pow(self, exp)
}
- fn modulus() -> Self::Integer {
+ fn modulus() -> Self::TestInteger {
<F as FieldElementWithInteger>::modulus()
}
}
@@ -885,11 +939,11 @@ pub(crate) mod test_utils {
pub(crate) fn field_element_test_common<F: TestFieldElementWithInteger>() {
let mut prng: Prng<F, _> = Prng::new().unwrap();
let int_modulus = F::modulus();
- let int_one = F::Integer::try_from(1).unwrap();
+ let int_one = F::TestInteger::try_from(1).unwrap();
let zero = F::zero();
let one = F::one();
- let two = F::from(F::Integer::try_from(2).unwrap());
- let four = F::from(F::Integer::try_from(4).unwrap());
+ let two = F::from(F::TestInteger::try_from(2).unwrap());
+ let four = F::from(F::TestInteger::try_from(4).unwrap());
// add
assert_eq!(F::from(int_modulus.clone() - int_one.clone()) + one, zero);
@@ -943,10 +997,22 @@ pub(crate) mod test_utils {
assert_eq!(a, c);
// integer conversion
- assert_eq!(F::Integer::from(zero), F::Integer::try_from(0).unwrap());
- assert_eq!(F::Integer::from(one), F::Integer::try_from(1).unwrap());
- assert_eq!(F::Integer::from(two), F::Integer::try_from(2).unwrap());
- assert_eq!(F::Integer::from(four), F::Integer::try_from(4).unwrap());
+ assert_eq!(
+ F::TestInteger::from(zero),
+ F::TestInteger::try_from(0).unwrap()
+ );
+ assert_eq!(
+ F::TestInteger::from(one),
+ F::TestInteger::try_from(1).unwrap()
+ );
+ assert_eq!(
+ F::TestInteger::from(two),
+ F::TestInteger::try_from(2).unwrap()
+ );
+ assert_eq!(
+ F::TestInteger::from(four),
+ F::TestInteger::try_from(4).unwrap()
+ );
// serialization
let test_inputs = vec![
@@ -957,7 +1023,7 @@ pub(crate) mod test_utils {
];
for want in test_inputs.iter() {
let mut bytes = vec![];
- want.encode(&mut bytes);
+ want.encode(&mut bytes).unwrap();
assert_eq!(bytes.len(), F::ENCODED_SIZE);
assert_eq!(want.encoded_len().unwrap(), F::ENCODED_SIZE);
@@ -966,9 +1032,12 @@ pub(crate) mod test_utils {
assert_eq!(got, *want);
}
- let serialized_vec = F::slice_into_byte_vec(&test_inputs);
- let deserialized = F::byte_slice_into_vec(&serialized_vec).unwrap();
- assert_eq!(deserialized, test_inputs);
+ #[allow(deprecated)]
+ {
+ let serialized_vec = F::slice_into_byte_vec(&test_inputs);
+ let deserialized = F::byte_slice_into_vec(&serialized_vec).unwrap();
+ assert_eq!(deserialized, test_inputs);
+ }
let test_input = prng.get();
let json = serde_json::to_string(&test_input).unwrap();
@@ -981,13 +1050,16 @@ pub(crate) mod test_utils {
element.as_u64().unwrap();
}
- let err = F::byte_slice_into_vec(&[0]).unwrap_err();
- assert_matches!(err, FieldError::ShortRead);
+ #[allow(deprecated)]
+ {
+ let err = F::byte_slice_into_vec(&[0]).unwrap_err();
+ assert_matches!(err, FieldError::ShortRead);
- let err = F::byte_slice_into_vec(&vec![0xffu8; F::ENCODED_SIZE]).unwrap_err();
- assert_matches!(err, FieldError::Codec(CodecError::Other(err)) => {
- assert_matches!(err.downcast_ref::<FieldError>(), Some(FieldError::ModulusOverflow));
- });
+ let err = F::byte_slice_into_vec(&vec![0xffu8; F::ENCODED_SIZE]).unwrap_err();
+ assert_matches!(err, FieldError::Codec(CodecError::Other(err)) => {
+ assert_matches!(err.downcast_ref::<FieldError>(), Some(FieldError::ModulusOverflow));
+ });
+ }
let insufficient = vec![0u8; F::ENCODED_SIZE - 1];
let err = F::try_from(insufficient.as_ref()).unwrap_err();
@@ -1004,7 +1076,7 @@ pub(crate) mod test_utils {
// various products that should be equal have the same hash. Three is chosen as a generator
// here because it happens to generate fairly large subgroups of (Z/pZ)* for all four
// primes.
- let three = F::from(F::Integer::try_from(3).unwrap());
+ let three = F::from(F::TestInteger::try_from(3).unwrap());
let mut powers_of_three = Vec::with_capacity(500);
let mut power = one;
for _ in 0..500 {
@@ -1169,22 +1241,19 @@ mod tests {
fn test_encode_into_bitvector() {
let zero = Field128::zero();
let one = Field128::one();
- let zero_enc = Field128::encode_into_bitvector_representation(&0, 4).unwrap();
- let one_enc = Field128::encode_into_bitvector_representation(&1, 4).unwrap();
- let fifteen_enc = Field128::encode_into_bitvector_representation(&15, 4).unwrap();
+ let zero_enc = Field128::encode_as_bitvector(0, 4)
+ .unwrap()
+ .collect::<Vec<_>>();
+ let one_enc = Field128::encode_as_bitvector(1, 4)
+ .unwrap()
+ .collect::<Vec<_>>();
+ let fifteen_enc = Field128::encode_as_bitvector(15, 4)
+ .unwrap()
+ .collect::<Vec<_>>();
assert_eq!(zero_enc, [zero; 4]);
assert_eq!(one_enc, [one, zero, zero, zero]);
assert_eq!(fifteen_enc, [one; 4]);
- Field128::encode_into_bitvector_representation(&16, 4).unwrap_err();
- }
-
- #[test]
- fn test_fill_bitvector() {
- let zero = Field128::zero();
- let one = Field128::one();
- let mut output: Vec<Field128> = vec![zero; 6];
- Field128::fill_with_bitvector_representation(&9, &mut output[1..5]).unwrap();
- assert_eq!(output, [zero, one, zero, zero, one, zero]);
- Field128::fill_with_bitvector_representation(&16, &mut output[1..5]).unwrap_err();
+ Field128::encode_as_bitvector(16, 4).unwrap_err();
+ Field128::encode_as_bitvector(0, 129).unwrap_err();
}
}
diff --git a/third_party/rust/prio/src/field/field255.rs b/third_party/rust/prio/src/field/field255.rs
index fd06a6334a..15a53f8b09 100644
--- a/third_party/rust/prio/src/field/field255.rs
+++ b/third_party/rust/prio/src/field/field255.rs
@@ -271,8 +271,9 @@ impl<'de> Deserialize<'de> for Field255 {
}
impl Encode for Field255 {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
bytes.extend_from_slice(&<[u8; Self::ENCODED_SIZE]>::from(*self));
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -341,7 +342,7 @@ mod tests {
codec::Encode,
field::{
test_utils::{field_element_test_common, TestFieldElementWithInteger},
- FieldElement, FieldError,
+ FieldElement, FieldError, Integer,
},
};
use assert_matches::assert_matches;
@@ -375,16 +376,30 @@ mod tests {
}
}
+ impl Integer for BigUint {
+ type TryFromUsizeError = <Self as TryFrom<usize>>::Error;
+
+ type TryIntoU64Error = <Self as TryInto<u64>>::Error;
+
+ fn zero() -> Self {
+ Self::new(Vec::new())
+ }
+
+ fn one() -> Self {
+ Self::new(Vec::from([1]))
+ }
+ }
+
impl TestFieldElementWithInteger for Field255 {
- type Integer = BigUint;
- type IntegerTryFromError = <Self::Integer as TryFrom<usize>>::Error;
- type TryIntoU64Error = <Self::Integer as TryInto<u64>>::Error;
+ type TestInteger = BigUint;
+ type IntegerTryFromError = <Self::TestInteger as TryFrom<usize>>::Error;
+ type TryIntoU64Error = <Self::TestInteger as TryInto<u64>>::Error;
- fn pow(&self, _exp: Self::Integer) -> Self {
+ fn pow(&self, _exp: Self::TestInteger) -> Self {
unimplemented!("Field255::pow() is not implemented because it's not needed yet")
}
- fn modulus() -> Self::Integer {
+ fn modulus() -> Self::TestInteger {
MODULUS.clone()
}
}
@@ -415,7 +430,7 @@ mod tests {
#[test]
fn encode_endianness() {
let mut one_encoded = Vec::new();
- Field255::one().encode(&mut one_encoded);
+ Field255::one().encode(&mut one_encoded).unwrap();
assert_eq!(
one_encoded,
[
diff --git a/third_party/rust/prio/src/flp.rs b/third_party/rust/prio/src/flp.rs
index 1912ebab14..5fd956155a 100644
--- a/third_party/rust/prio/src/flp.rs
+++ b/third_party/rust/prio/src/flp.rs
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! Implementation of the generic Fully Linear Proof (FLP) system specified in
-//! [[draft-irtf-cfrg-vdaf-07]]. This is the main building block of [`Prio3`](crate::vdaf::prio3).
+//! [[draft-irtf-cfrg-vdaf-08]]. This is the main building block of [`Prio3`](crate::vdaf::prio3).
//!
//! The FLP is derived for any implementation of the [`Type`] trait. Such an implementation
//! specifies a validity circuit that defines the set of valid measurements, as well as the finite
@@ -24,7 +24,7 @@
//!
//! // The prover chooses a measurement.
//! let count = Count::new();
-//! let input: Vec<Field64> = count.encode_measurement(&0).unwrap();
+//! let input: Vec<Field64> = count.encode_measurement(&false).unwrap();
//!
//! // The prover and verifier agree on "joint randomness" used to generate and
//! // check the proof. The application needs to ensure that the prover
@@ -44,7 +44,7 @@
//! assert!(count.decide(&verifier).unwrap());
//! ```
//!
-//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
#[cfg(feature = "experimental")]
use crate::dp::DifferentialPrivacyStrategy;
@@ -61,6 +61,7 @@ pub mod types;
/// Errors propagated by methods in this module.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum FlpError {
/// Calling [`Type::prove`] returned an error.
#[error("prove error: {0}")]
@@ -110,20 +111,12 @@ pub enum FlpError {
/// An error happened during noising.
#[error("differential privacy error: {0}")]
DifferentialPrivacy(#[from] crate::dp::DpError),
-
- /// Unit test error.
- #[cfg(test)]
- #[error("test failed: {0}")]
- Test(String),
}
/// A type. Implementations of this trait specify how a particular kind of measurement is encoded
/// as a vector of field elements and how validity of the encoded measurement is determined.
/// Validity is determined via an arithmetic circuit evaluated over the encoded measurement.
pub trait Type: Sized + Eq + Clone + Debug {
- /// The Prio3 VDAF identifier corresponding to this type.
- const ID: u32;
-
/// The type of raw measurement to be encoded.
type Measurement: Clone + Debug;
@@ -178,7 +171,7 @@ pub trait Type: Sized + Eq + Clone + Debug {
/// use prio::field::{random_vector, FieldElement, Field64};
///
/// let count = Count::new();
- /// let input: Vec<Field64> = count.encode_measurement(&1).unwrap();
+ /// let input: Vec<Field64> = count.encode_measurement(&true).unwrap();
/// let joint_rand = random_vector(count.joint_rand_len()).unwrap();
/// let v = count.valid(&mut count.gadget(), &input, &joint_rand, 1).unwrap();
/// assert_eq!(v, Field64::zero());
@@ -552,6 +545,7 @@ pub trait Type: Sized + Eq + Clone + Debug {
/// A type which supports adding noise to aggregate shares for Server Differential Privacy.
#[cfg(feature = "experimental")]
+#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))]
pub trait TypeWithNoise<S>: Type
where
S: DifferentialPrivacyStrategy,
@@ -754,6 +748,227 @@ pub(crate) fn gadget_poly_len(gadget_degree: usize, wire_poly_len: usize) -> usi
gadget_degree * (wire_poly_len - 1) + 1
}
+/// Utilities for testing FLPs.
+#[cfg(feature = "test-util")]
+#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
+pub mod test_utils {
+ use super::*;
+ use crate::field::{random_vector, FieldElement, FieldElementWithInteger};
+
+ /// Various tests for an FLP.
+ #[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
+ pub struct FlpTest<'a, T: Type> {
+ /// The FLP.
+ pub flp: &'a T,
+
+ /// Optional test name.
+ pub name: Option<&'a str>,
+
+ /// The input to use for the tests.
+ pub input: &'a [T::Field],
+
+ /// If set, the expected result of truncating the input.
+ pub expected_output: Option<&'a [T::Field]>,
+
+ /// Whether the input is expected to be valid.
+ pub expect_valid: bool,
+ }
+
+ impl<T: Type> FlpTest<'_, T> {
+ /// Construct a test and run it. Expect the input to be valid and compare the truncated
+ /// output to the provided value.
+ pub fn expect_valid<const SHARES: usize>(
+ flp: &T,
+ input: &[T::Field],
+ expected_output: &[T::Field],
+ ) {
+ FlpTest {
+ flp,
+ name: None,
+ input,
+ expected_output: Some(expected_output),
+ expect_valid: true,
+ }
+ .run::<SHARES>()
+ }
+
+ /// Construct a test and run it. Expect the input to be invalid.
+ pub fn expect_invalid<const SHARES: usize>(flp: &T, input: &[T::Field]) {
+ FlpTest {
+ flp,
+ name: None,
+ input,
+ expect_valid: false,
+ expected_output: None,
+ }
+ .run::<SHARES>()
+ }
+
+ /// Construct a test and run it. Expect the input to be valid.
+ pub fn expect_valid_no_output<const SHARES: usize>(flp: &T, input: &[T::Field]) {
+ FlpTest {
+ flp,
+ name: None,
+ input,
+ expect_valid: true,
+ expected_output: None,
+ }
+ .run::<SHARES>()
+ }
+
+ /// Run the tests.
+ pub fn run<const SHARES: usize>(&self) {
+ let name = self.name.unwrap_or("unnamed test");
+
+ assert_eq!(
+ self.input.len(),
+ self.flp.input_len(),
+ "{name}: unexpected input length"
+ );
+
+ let mut gadgets = self.flp.gadget();
+ let joint_rand = random_vector(self.flp.joint_rand_len()).unwrap();
+ let prove_rand = random_vector(self.flp.prove_rand_len()).unwrap();
+ let query_rand = random_vector(self.flp.query_rand_len()).unwrap();
+ assert_eq!(
+ self.flp.query_rand_len(),
+ gadgets.len(),
+ "{name}: unexpected number of gadgets"
+ );
+ assert_eq!(
+ self.flp.joint_rand_len(),
+ joint_rand.len(),
+ "{name}: unexpected joint rand length"
+ );
+ assert_eq!(
+ self.flp.prove_rand_len(),
+ prove_rand.len(),
+ "{name}: unexpected prove rand length",
+ );
+ assert_eq!(
+ self.flp.query_rand_len(),
+ query_rand.len(),
+ "{name}: unexpected query rand length",
+ );
+
+ // Run the validity circuit.
+ let v = self
+ .flp
+ .valid(&mut gadgets, self.input, &joint_rand, 1)
+ .unwrap();
+ assert_eq!(
+ v == T::Field::zero(),
+ self.expect_valid,
+ "{name}: unexpected output of valid() returned {v}",
+ );
+
+ // Generate the proof.
+ let proof = self
+ .flp
+ .prove(self.input, &prove_rand, &joint_rand)
+ .unwrap();
+ assert_eq!(
+ proof.len(),
+ self.flp.proof_len(),
+ "{name}: unexpected proof length"
+ );
+
+ // Query the proof.
+ let verifier = self
+ .flp
+ .query(self.input, &proof, &query_rand, &joint_rand, 1)
+ .unwrap();
+ assert_eq!(
+ verifier.len(),
+ self.flp.verifier_len(),
+ "{name}: unexpected verifier length"
+ );
+
+ // Decide if the input is valid.
+ let res = self.flp.decide(&verifier).unwrap();
+ assert_eq!(res, self.expect_valid, "{name}: unexpected decision");
+
+ // Run distributed FLP.
+ let input_shares = split_vector::<_, SHARES>(self.input);
+ let proof_shares = split_vector::<_, SHARES>(&proof);
+ let verifier: Vec<T::Field> = (0..SHARES)
+ .map(|i| {
+ self.flp
+ .query(
+ &input_shares[i],
+ &proof_shares[i],
+ &query_rand,
+ &joint_rand,
+ SHARES,
+ )
+ .unwrap()
+ })
+ .reduce(|mut left, right| {
+ for (x, y) in left.iter_mut().zip(right.iter()) {
+ *x += *y;
+ }
+ left
+ })
+ .unwrap();
+
+ let res = self.flp.decide(&verifier).unwrap();
+ assert_eq!(
+ res, self.expect_valid,
+ "{name}: unexpected distributed decision"
+ );
+
+ // Try verifying various proof mutants.
+ for i in 0..std::cmp::min(proof.len(), 10) {
+ let mut mutated_proof = proof.clone();
+ mutated_proof[i] *= T::Field::from(
+ <T::Field as FieldElementWithInteger>::Integer::try_from(23).unwrap(),
+ );
+ let verifier = self
+ .flp
+ .query(self.input, &mutated_proof, &query_rand, &joint_rand, 1)
+ .unwrap();
+ assert!(
+ !self.flp.decide(&verifier).unwrap(),
+ "{name}: proof mutant {} deemed valid",
+ i
+ );
+ }
+
+ // Try truncating the input.
+ if let Some(ref expected_output) = self.expected_output {
+ let output = self.flp.truncate(self.input.to_vec()).unwrap();
+
+ assert_eq!(
+ output.len(),
+ self.flp.output_len(),
+ "{name}: unexpected output length of truncate()"
+ );
+
+ assert_eq!(
+ &output, expected_output,
+ "{name}: unexpected output of truncate()"
+ );
+ }
+ }
+ }
+
+ fn split_vector<F: FieldElement, const SHARES: usize>(inp: &[F]) -> [Vec<F>; SHARES] {
+ let mut outp = Vec::with_capacity(SHARES);
+ outp.push(inp.to_vec());
+
+ for _ in 1..SHARES {
+ let share: Vec<F> =
+ random_vector(inp.len()).expect("failed to generate a random vector");
+ for (x, y) in outp[0].iter_mut().zip(&share) {
+ *x -= *y;
+ }
+ outp.push(share);
+ }
+
+ outp.try_into().unwrap()
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -825,7 +1040,6 @@ mod tests {
}
impl<F: FftFriendlyFieldElement> Type for TestType<F> {
- const ID: u32 = 0xFFFF0000;
type Measurement = F::Integer;
type AggregateResult = F::Integer;
type Field = F;
@@ -960,7 +1174,6 @@ mod tests {
}
impl<F: FftFriendlyFieldElement> Type for Issue254Type<F> {
- const ID: u32 = 0xFFFF0000;
type Measurement = F::Integer;
type AggregateResult = F::Integer;
type Field = F;
diff --git a/third_party/rust/prio/src/flp/types.rs b/third_party/rust/prio/src/flp/types.rs
index 18c290355c..bca88a36cd 100644
--- a/third_party/rust/prio/src/flp/types.rs
+++ b/third_party/rust/prio/src/flp/types.rs
@@ -9,6 +9,7 @@ use crate::polynomial::poly_range_check;
use std::convert::TryInto;
use std::fmt::{self, Debug};
use std::marker::PhantomData;
+use subtle::Choice;
/// The counter data type. Each measurement is `0` or `1` and the aggregate result is the sum of the measurements (i.e., the total number of `1s`).
#[derive(Clone, PartialEq, Eq)]
pub struct Count<F> {
@@ -37,18 +38,16 @@ impl<F: FftFriendlyFieldElement> Default for Count<F> {
}
impl<F: FftFriendlyFieldElement> Type for Count<F> {
- const ID: u32 = 0x00000000;
- type Measurement = F::Integer;
+ type Measurement = bool;
type AggregateResult = F::Integer;
type Field = F;
- fn encode_measurement(&self, value: &F::Integer) -> Result<Vec<F>, FlpError> {
- let max = F::valid_integer_try_from(1)?;
- if *value > max {
- return Err(FlpError::Encode("Count value must be 0 or 1".to_string()));
- }
-
- Ok(vec![F::from(*value)])
+ fn encode_measurement(&self, value: &bool) -> Result<Vec<F>, FlpError> {
+ Ok(vec![F::conditional_select(
+ &F::zero(),
+ &F::one(),
+ Choice::from(u8::from(*value)),
+ )])
}
fn decode_result(&self, data: &[F], _num_measurements: usize) -> Result<F::Integer, FlpError> {
@@ -140,13 +139,12 @@ impl<F: FftFriendlyFieldElement> Sum<F> {
}
impl<F: FftFriendlyFieldElement> Type for Sum<F> {
- const ID: u32 = 0x00000001;
type Measurement = F::Integer;
type AggregateResult = F::Integer;
type Field = F;
fn encode_measurement(&self, summand: &F::Integer) -> Result<Vec<F>, FlpError> {
- let v = F::encode_into_bitvector_representation(summand, self.bits)?;
+ let v = F::encode_as_bitvector(*summand, self.bits)?.collect();
Ok(v)
}
@@ -174,7 +172,7 @@ impl<F: FftFriendlyFieldElement> Type for Sum<F> {
fn truncate(&self, input: Vec<F>) -> Result<Vec<F>, FlpError> {
self.truncate_call_check(&input)?;
- let res = F::decode_from_bitvector_representation(&input)?;
+ let res = F::decode_bitvector(&input)?;
Ok(vec![res])
}
@@ -239,13 +237,12 @@ impl<F: FftFriendlyFieldElement> Average<F> {
}
impl<F: FftFriendlyFieldElement> Type for Average<F> {
- const ID: u32 = 0xFFFF0000;
type Measurement = F::Integer;
type AggregateResult = f64;
type Field = F;
fn encode_measurement(&self, summand: &F::Integer) -> Result<Vec<F>, FlpError> {
- let v = F::encode_into_bitvector_representation(summand, self.bits)?;
+ let v = F::encode_as_bitvector(*summand, self.bits)?.collect();
Ok(v)
}
@@ -279,7 +276,7 @@ impl<F: FftFriendlyFieldElement> Type for Average<F> {
fn truncate(&self, input: Vec<F>) -> Result<Vec<F>, FlpError> {
self.truncate_call_check(&input)?;
- let res = F::decode_from_bitvector_representation(&input)?;
+ let res = F::decode_bitvector(&input)?;
Ok(vec![res])
}
@@ -380,7 +377,6 @@ where
F: FftFriendlyFieldElement,
S: ParallelSumGadget<F, Mul<F>> + Eq + 'static,
{
- const ID: u32 = 0x00000003;
type Measurement = usize;
type AggregateResult = Vec<F::Integer>;
type Field = F;
@@ -574,7 +570,6 @@ where
F: FftFriendlyFieldElement,
S: ParallelSumGadget<F, Mul<F>> + Eq + 'static,
{
- const ID: u32 = 0x00000002;
type Measurement = Vec<F::Integer>;
type AggregateResult = Vec<F::Integer>;
type Field = F;
@@ -588,18 +583,15 @@ where
)));
}
- let mut flattened = vec![F::zero(); self.flattened_len];
- for (summand, chunk) in measurement
- .iter()
- .zip(flattened.chunks_exact_mut(self.bits))
- {
+ let mut flattened = Vec::with_capacity(self.flattened_len);
+ for summand in measurement.iter() {
if summand > &self.max {
return Err(FlpError::Encode(format!(
"summand exceeds maximum of 2^{}-1",
self.bits
)));
}
- F::fill_with_bitvector_representation(summand, chunk)?;
+ flattened.extend(F::encode_as_bitvector(*summand, self.bits)?);
}
Ok(flattened)
@@ -642,7 +634,7 @@ where
self.truncate_call_check(&input)?;
let mut unflattened = Vec::with_capacity(self.len);
for chunk in input.chunks(self.bits) {
- unflattened.push(F::decode_from_bitvector_representation(chunk)?);
+ unflattened.push(F::decode_bitvector(chunk)?);
}
Ok(unflattened)
}
@@ -783,7 +775,7 @@ mod tests {
use crate::flp::gadgets::ParallelSum;
#[cfg(feature = "multithreaded")]
use crate::flp::gadgets::ParallelSumMultithreaded;
- use crate::flp::types::test_utils::{flp_validity_test, ValidityTestCase};
+ use crate::flp::test_utils::FlpTest;
use std::cmp;
#[test]
@@ -797,7 +789,7 @@ mod tests {
count
.decode_result(
&count
- .truncate(count.encode_measurement(&1).unwrap())
+ .truncate(count.encode_measurement(&true).unwrap())
.unwrap(),
1
)
@@ -806,39 +798,11 @@ mod tests {
);
// Test FLP on valid input.
- flp_validity_test(
- &count,
- &count.encode_measurement(&1).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![one]),
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
- &count,
- &count.encode_measurement(&0).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![zero]),
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest::expect_valid::<3>(&count, &count.encode_measurement(&true).unwrap(), &[one]);
+ FlpTest::expect_valid::<3>(&count, &count.encode_measurement(&false).unwrap(), &[zero]);
// Test FLP on invalid input.
- flp_validity_test(
- &count,
- &[TestField::from(1337)],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest::expect_invalid::<3>(&count, &[TestField::from(1337)]);
// Try running the validity circuit on an input that's too short.
count.valid(&mut count.gadget(), &[], &[], 1).unwrap_err();
@@ -865,72 +829,22 @@ mod tests {
);
// Test FLP on valid input.
- flp_validity_test(
+ FlpTest::expect_valid::<3>(
&sum,
&sum.encode_measurement(&1337).unwrap(),
- &ValidityTestCase {
- expect_valid: true,
- expected_output: Some(vec![TestField::from(1337)]),
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
- &Sum::new(0).unwrap(),
- &[],
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![zero]),
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
- &Sum::new(2).unwrap(),
- &[one, zero],
- &ValidityTestCase {
- expect_valid: true,
- expected_output: Some(vec![one]),
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
+ &[TestField::from(1337)],
+ );
+ FlpTest::expect_valid::<3>(&Sum::new(0).unwrap(), &[], &[zero]);
+ FlpTest::expect_valid::<3>(&Sum::new(2).unwrap(), &[one, zero], &[one]);
+ FlpTest::expect_valid::<3>(
&Sum::new(9).unwrap(),
&[one, zero, one, one, zero, one, one, one, zero],
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![TestField::from(237)]),
- num_shares: 3,
- },
- )
- .unwrap();
+ &[TestField::from(237)],
+ );
// Test FLP on invalid input.
- flp_validity_test(
- &Sum::new(3).unwrap(),
- &[one, nine, zero],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
- &Sum::new(5).unwrap(),
- &[zero, zero, zero, zero, nine],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest::expect_invalid::<3>(&Sum::new(3).unwrap(), &[one, nine, zero]);
+ FlpTest::expect_invalid::<3>(&Sum::new(5).unwrap(), &[zero, zero, zero, zero, nine]);
}
#[test]
@@ -1000,83 +914,29 @@ mod tests {
);
// Test valid inputs.
- flp_validity_test(
+ FlpTest::expect_valid::<3>(
&hist,
&hist.encode_measurement(&0).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![one, zero, zero]),
- num_shares: 3,
- },
- )
- .unwrap();
+ &[one, zero, zero],
+ );
- flp_validity_test(
+ FlpTest::expect_valid::<3>(
&hist,
&hist.encode_measurement(&1).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![zero, one, zero]),
- num_shares: 3,
- },
- )
- .unwrap();
+ &[zero, one, zero],
+ );
- flp_validity_test(
+ FlpTest::expect_valid::<3>(
&hist,
&hist.encode_measurement(&2).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![zero, zero, one]),
- num_shares: 3,
- },
- )
- .unwrap();
+ &[zero, zero, one],
+ );
// Test invalid inputs.
- flp_validity_test(
- &hist,
- &[zero, zero, nine],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
- &hist,
- &[zero, one, one],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
- &hist,
- &[one, one, one],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
-
- flp_validity_test(
- &hist,
- &[zero, zero, zero],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest::expect_invalid::<3>(&hist, &[zero, zero, nine]);
+ FlpTest::expect_invalid::<3>(&hist, &[zero, one, one]);
+ FlpTest::expect_invalid::<3>(&hist, &[one, one, one]);
+ FlpTest::expect_invalid::<3>(&hist, &[zero, zero, zero]);
}
#[test]
@@ -1104,72 +964,38 @@ mod tests {
for len in 1..10 {
let chunk_length = cmp::max((len as f64).sqrt() as usize, 1);
let sum_vec = f(1, len, chunk_length).unwrap();
- flp_validity_test(
+ FlpTest::expect_valid_no_output::<3>(
&sum_vec,
&sum_vec.encode_measurement(&vec![1; len]).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![one; len]),
- num_shares: 3,
- },
- )
- .unwrap();
+ );
}
let len = 100;
let sum_vec = f(1, len, 10).unwrap();
- flp_validity_test(
+ FlpTest::expect_valid::<3>(
&sum_vec,
&sum_vec.encode_measurement(&vec![1; len]).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![one; len]),
- num_shares: 3,
- },
- )
- .unwrap();
+ &vec![one; len],
+ );
let len = 23;
let sum_vec = f(4, len, 4).unwrap();
- flp_validity_test(
+ FlpTest::expect_valid::<3>(
&sum_vec,
&sum_vec.encode_measurement(&vec![9; len]).unwrap(),
- &ValidityTestCase::<TestField> {
- expect_valid: true,
- expected_output: Some(vec![nine; len]),
- num_shares: 3,
- },
- )
- .unwrap();
+ &vec![nine; len],
+ );
// Test on invalid inputs.
for len in 1..10 {
let chunk_length = cmp::max((len as f64).sqrt() as usize, 1);
let sum_vec = f(1, len, chunk_length).unwrap();
- flp_validity_test(
- &sum_vec,
- &vec![nine; len],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest::expect_invalid::<3>(&sum_vec, &vec![nine; len]);
}
let len = 23;
let sum_vec = f(2, len, 4).unwrap();
- flp_validity_test(
- &sum_vec,
- &vec![nine; 2 * len],
- &ValidityTestCase::<TestField> {
- expect_valid: false,
- expected_output: None,
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest::expect_invalid::<3>(&sum_vec, &vec![nine; 2 * len]);
// Round trip
let want = vec![1; len];
@@ -1232,184 +1058,6 @@ mod tests {
}
}
-#[cfg(test)]
-mod test_utils {
- use super::*;
- use crate::field::{random_vector, split_vector, FieldElement};
-
- pub(crate) struct ValidityTestCase<F> {
- pub(crate) expect_valid: bool,
- pub(crate) expected_output: Option<Vec<F>>,
- // Number of shares to split input and proofs into in `flp_test`.
- pub(crate) num_shares: usize,
- }
-
- pub(crate) fn flp_validity_test<T: Type>(
- typ: &T,
- input: &[T::Field],
- t: &ValidityTestCase<T::Field>,
- ) -> Result<(), FlpError> {
- let mut gadgets = typ.gadget();
-
- if input.len() != typ.input_len() {
- return Err(FlpError::Test(format!(
- "unexpected input length: got {}; want {}",
- input.len(),
- typ.input_len()
- )));
- }
-
- if typ.query_rand_len() != gadgets.len() {
- return Err(FlpError::Test(format!(
- "query rand length: got {}; want {}",
- typ.query_rand_len(),
- gadgets.len()
- )));
- }
-
- let joint_rand = random_vector(typ.joint_rand_len()).unwrap();
- let prove_rand = random_vector(typ.prove_rand_len()).unwrap();
- let query_rand = random_vector(typ.query_rand_len()).unwrap();
-
- // Run the validity circuit.
- let v = typ.valid(&mut gadgets, input, &joint_rand, 1)?;
- if v != T::Field::zero() && t.expect_valid {
- return Err(FlpError::Test(format!(
- "expected valid input: valid() returned {v}"
- )));
- }
- if v == T::Field::zero() && !t.expect_valid {
- return Err(FlpError::Test(format!(
- "expected invalid input: valid() returned {v}"
- )));
- }
-
- // Generate the proof.
- let proof = typ.prove(input, &prove_rand, &joint_rand)?;
- if proof.len() != typ.proof_len() {
- return Err(FlpError::Test(format!(
- "unexpected proof length: got {}; want {}",
- proof.len(),
- typ.proof_len()
- )));
- }
-
- // Query the proof.
- let verifier = typ.query(input, &proof, &query_rand, &joint_rand, 1)?;
- if verifier.len() != typ.verifier_len() {
- return Err(FlpError::Test(format!(
- "unexpected verifier length: got {}; want {}",
- verifier.len(),
- typ.verifier_len()
- )));
- }
-
- // Decide if the input is valid.
- let res = typ.decide(&verifier)?;
- if res != t.expect_valid {
- return Err(FlpError::Test(format!(
- "decision is {}; want {}",
- res, t.expect_valid,
- )));
- }
-
- // Run distributed FLP.
- let input_shares: Vec<Vec<T::Field>> = split_vector(input, t.num_shares)
- .unwrap()
- .into_iter()
- .collect();
-
- let proof_shares: Vec<Vec<T::Field>> = split_vector(&proof, t.num_shares)
- .unwrap()
- .into_iter()
- .collect();
-
- let verifier: Vec<T::Field> = (0..t.num_shares)
- .map(|i| {
- typ.query(
- &input_shares[i],
- &proof_shares[i],
- &query_rand,
- &joint_rand,
- t.num_shares,
- )
- .unwrap()
- })
- .reduce(|mut left, right| {
- for (x, y) in left.iter_mut().zip(right.iter()) {
- *x += *y;
- }
- left
- })
- .unwrap();
-
- let res = typ.decide(&verifier)?;
- if res != t.expect_valid {
- return Err(FlpError::Test(format!(
- "distributed decision is {}; want {}",
- res, t.expect_valid,
- )));
- }
-
- // Try verifying various proof mutants.
- for i in 0..proof.len() {
- let mut mutated_proof = proof.clone();
- mutated_proof[i] += T::Field::one();
- let verifier = typ.query(input, &mutated_proof, &query_rand, &joint_rand, 1)?;
- if typ.decide(&verifier)? {
- return Err(FlpError::Test(format!(
- "decision for proof mutant {} is {}; want {}",
- i, true, false,
- )));
- }
- }
-
- // Try verifying a proof that is too short.
- let mut mutated_proof = proof.clone();
- mutated_proof.truncate(gadgets[0].arity() - 1);
- if typ
- .query(input, &mutated_proof, &query_rand, &joint_rand, 1)
- .is_ok()
- {
- return Err(FlpError::Test(
- "query on short proof succeeded; want failure".to_string(),
- ));
- }
-
- // Try verifying a proof that is too long.
- let mut mutated_proof = proof;
- mutated_proof.extend_from_slice(&[T::Field::one(); 17]);
- if typ
- .query(input, &mutated_proof, &query_rand, &joint_rand, 1)
- .is_ok()
- {
- return Err(FlpError::Test(
- "query on long proof succeeded; want failure".to_string(),
- ));
- }
-
- if let Some(ref want) = t.expected_output {
- let got = typ.truncate(input.to_vec())?;
-
- if got.len() != typ.output_len() {
- return Err(FlpError::Test(format!(
- "unexpected output length: got {}; want {}",
- got.len(),
- typ.output_len()
- )));
- }
-
- if &got != want {
- return Err(FlpError::Test(format!(
- "unexpected output: got {got:?}; want {want:?}"
- )));
- }
- }
-
- Ok(())
- }
-}
-
#[cfg(feature = "experimental")]
#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))]
pub mod fixedpoint_l2;
diff --git a/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs b/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs
index b5aa2fd116..8766c035b8 100644
--- a/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs
+++ b/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs
@@ -172,15 +172,17 @@
pub mod compatible_float;
use crate::dp::{distributions::ZCdpDiscreteGaussian, DifferentialPrivacyStrategy, DpError};
-use crate::field::{Field128, FieldElement, FieldElementWithInteger, FieldElementWithIntegerExt};
+use crate::field::{
+ Field128, FieldElement, FieldElementWithInteger, FieldElementWithIntegerExt, Integer,
+};
use crate::flp::gadgets::{Mul, ParallelSumGadget, PolyEval};
use crate::flp::types::fixedpoint_l2::compatible_float::CompatibleFloat;
use crate::flp::types::parallel_sum_range_checks;
use crate::flp::{FlpError, Gadget, Type, TypeWithNoise};
-use crate::vdaf::xof::SeedStreamSha3;
+use crate::vdaf::xof::SeedStreamTurboShake128;
use fixed::traits::Fixed;
use num_bigint::{BigInt, BigUint, TryFromBigIntError};
-use num_integer::Integer;
+use num_integer::Integer as _;
use num_rational::Ratio;
use rand::{distributions::Distribution, Rng};
use rand_core::SeedableRng;
@@ -250,7 +252,7 @@ where
/// fixed point vector with `entries` entries.
pub fn new(entries: usize) -> Result<Self, FlpError> {
// (0) initialize constants
- let fi_one = u128::from(Field128::one());
+ let fi_one = <Field128 as FieldElementWithInteger>::Integer::one();
// (I) Check that the fixed type is compatible.
//
@@ -400,7 +402,6 @@ where
SPoly: ParallelSumGadget<Field128, PolyEval<Field128>> + Eq + Clone + 'static,
SMul: ParallelSumGadget<Field128, Mul<Field128>> + Eq + Clone + 'static,
{
- const ID: u32 = 0xFFFF0000;
type Measurement = Vec<T>;
type AggregateResult = Vec<f64>;
type Field = Field128;
@@ -419,12 +420,9 @@ where
// Encode the integer entries bitwise, and write them into the `encoded`
// vector.
let mut encoded: Vec<Field128> =
- vec![Field128::zero(); self.bits_per_entry * self.entries + self.bits_for_norm];
- for (l, entry) in integer_entries.clone().enumerate() {
- Field128::fill_with_bitvector_representation(
- &entry,
- &mut encoded[l * self.bits_per_entry..(l + 1) * self.bits_per_entry],
- )?;
+ Vec::with_capacity(self.bits_per_entry * self.entries + self.bits_for_norm);
+ for entry in integer_entries.clone() {
+ encoded.extend(Field128::encode_as_bitvector(entry, self.bits_per_entry)?);
}
// (II) Vector norm.
@@ -434,10 +432,7 @@ where
let norm_int = u128::from(norm);
// Write the norm into the `entries` vector.
- Field128::fill_with_bitvector_representation(
- &norm_int,
- &mut encoded[self.range_norm_begin..self.range_norm_end],
- )?;
+ encoded.extend(Field128::encode_as_bitvector(norm_int, self.bits_for_norm)?);
Ok(encoded)
}
@@ -535,7 +530,7 @@ where
// decode the bit-encoded entries into elements in the range [0,2^n):
let decoded_entries: Result<Vec<_>, _> = input[0..self.entries * self.bits_per_entry]
.chunks(self.bits_per_entry)
- .map(Field128::decode_from_bitvector_representation)
+ .map(Field128::decode_bitvector)
.collect();
// run parallel sum gadget on the decoded entries
@@ -544,7 +539,7 @@ where
// Chunks which are too short need to be extended with a share of the
// encoded zero value, that is: 1/num_shares * (2^(n-1))
- let fi_one = u128::from(Field128::one());
+ let fi_one = <Field128 as FieldElementWithInteger>::Integer::one();
let zero_enc = Field128::from(fi_one << (self.bits_per_entry - 1));
let zero_enc_share = zero_enc * num_shares_inverse;
@@ -567,7 +562,7 @@ where
// The submitted norm is also decoded from its bit-encoding, and
// compared with the computed norm.
let submitted_norm_enc = &input[self.range_norm_begin..self.range_norm_end];
- let submitted_norm = Field128::decode_from_bitvector_representation(submitted_norm_enc)?;
+ let submitted_norm = Field128::decode_bitvector(submitted_norm_enc)?;
let norm_check = computed_norm - submitted_norm;
@@ -586,7 +581,7 @@ where
let start = i_entry * self.bits_per_entry;
let end = (i_entry + 1) * self.bits_per_entry;
- let decoded = Field128::decode_from_bitvector_representation(&input[start..end])?;
+ let decoded = Field128::decode_bitvector(&input[start..end])?;
decoded_vector.push(decoded);
}
Ok(decoded_vector)
@@ -644,7 +639,11 @@ where
agg_result: &mut [Self::Field],
_num_measurements: usize,
) -> Result<(), FlpError> {
- self.add_noise(dp_strategy, agg_result, &mut SeedStreamSha3::from_entropy())
+ self.add_noise(
+ dp_strategy,
+ agg_result,
+ &mut SeedStreamTurboShake128::from_entropy(),
+ )
}
}
@@ -686,8 +685,8 @@ mod tests {
use crate::dp::{Rational, ZCdpBudget};
use crate::field::{random_vector, Field128, FieldElement};
use crate::flp::gadgets::ParallelSum;
- use crate::flp::types::test_utils::{flp_validity_test, ValidityTestCase};
- use crate::vdaf::xof::SeedStreamSha3;
+ use crate::flp::test_utils::FlpTest;
+ use crate::vdaf::xof::SeedStreamTurboShake128;
use fixed::types::extra::{U127, U14, U63};
use fixed::{FixedI128, FixedI16, FixedI64};
use fixed_macro::fixed;
@@ -768,15 +767,23 @@ mod tests {
let strategy = ZCdpDiscreteGaussian::from_budget(ZCdpBudget::new(
Rational::from_unsigned(100u8, 3u8).unwrap(),
));
- vsum.add_noise(&strategy, &mut v, &mut SeedStreamSha3::from_seed([0u8; 16]))
- .unwrap();
+ vsum.add_noise(
+ &strategy,
+ &mut v,
+ &mut SeedStreamTurboShake128::from_seed([0u8; 16]),
+ )
+ .unwrap();
assert_eq!(
vsum.decode_result(&v, 1).unwrap(),
match n {
// sensitivity depends on encoding so the noise differs
- 16 => vec![0.150604248046875, 0.139373779296875, -0.03759765625],
- 32 => vec![0.3051439793780446, 0.1226568529382348, 0.08595499861985445],
- 64 => vec![0.2896077990915178, 0.16115188007715098, 0.0788390114728425],
+ 16 => vec![0.288970947265625, 0.168853759765625, 0.085662841796875],
+ 32 => vec![0.257810294162482, 0.10634658299386501, 0.10149003705009818],
+ 64 => vec![
+ 0.37697368351762867,
+ -0.02388947667663828,
+ 0.19813152630930916
+ ],
_ => panic!("unsupported bitsize"),
}
);
@@ -785,52 +792,46 @@ mod tests {
let mut input: Vec<Field128> = vsum.encode_measurement(&fp_vec).unwrap();
assert_eq!(input[0], Field128::zero());
input[0] = one; // it was zero
- flp_validity_test(
- &vsum,
- &input,
- &ValidityTestCase::<Field128> {
- expect_valid: false,
- expected_output: Some(vec![
- Field128::from(enc_vec[0] + 1), // = enc(0.25) + 2^0
- Field128::from(enc_vec[1]),
- Field128::from(enc_vec[2]),
- ]),
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest {
+ name: None,
+ flp: &vsum,
+ input: &input,
+ expected_output: Some(&[
+ Field128::from(enc_vec[0] + 1), // = enc(0.25) + 2^0
+ Field128::from(enc_vec[1]),
+ Field128::from(enc_vec[2]),
+ ]),
+ expect_valid: false,
+ }
+ .run::<3>();
// encoding contains entries that are not zero or one
let mut input2: Vec<Field128> = vsum.encode_measurement(&fp_vec).unwrap();
input2[0] = one + one;
- flp_validity_test(
- &vsum,
- &input2,
- &ValidityTestCase::<Field128> {
- expect_valid: false,
- expected_output: Some(vec![
- Field128::from(enc_vec[0] + 2), // = enc(0.25) + 2*2^0
- Field128::from(enc_vec[1]),
- Field128::from(enc_vec[2]),
- ]),
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest {
+ name: None,
+ flp: &vsum,
+ input: &input2,
+ expected_output: Some(&[
+ Field128::from(enc_vec[0] + 2), // = enc(0.25) + 2*2^0
+ Field128::from(enc_vec[1]),
+ Field128::from(enc_vec[2]),
+ ]),
+ expect_valid: false,
+ }
+ .run::<3>();
// norm is too big
// 2^n - 1, the field element encoded by the all-1 vector
let one_enc = Field128::from(((2_u128) << (n - 1)) - 1);
- flp_validity_test(
- &vsum,
- &vec![one; 3 * n + 2 * n - 2], // all vector entries and the norm are all-1-vectors
- &ValidityTestCase::<Field128> {
- expect_valid: false,
- expected_output: Some(vec![one_enc; 3]),
- num_shares: 3,
- },
- )
- .unwrap();
+ FlpTest {
+ name: None,
+ flp: &vsum,
+ input: &vec![one; 3 * n + 2 * n - 2], // all vector entries and the norm are all-1-vectors
+ expected_output: Some(&[one_enc; 3]),
+ expect_valid: false,
+ }
+ .run::<3>();
// invalid submission length, should be 3n + (2*n - 2) for a
// 3-element n-bit vector. 3*n bits for 3 entries, (2*n-2) for norm.
diff --git a/third_party/rust/prio/src/idpf.rs b/third_party/rust/prio/src/idpf.rs
index 2bb73f2159..b3da128fa0 100644
--- a/third_party/rust/prio/src/idpf.rs
+++ b/third_party/rust/prio/src/idpf.rs
@@ -1,7 +1,7 @@
//! This module implements the incremental distributed point function (IDPF) described in
-//! [[draft-irtf-cfrg-vdaf-07]].
+//! [[draft-irtf-cfrg-vdaf-08]].
//!
-//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
use crate::{
codec::{CodecError, Decode, Encode, ParameterizedDecode},
@@ -24,12 +24,14 @@ use std::{
collections::{HashMap, VecDeque},
fmt::Debug,
io::{Cursor, Read},
+ iter::zip,
ops::{Add, AddAssign, ControlFlow, Index, Sub},
};
use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable, ConstantTimeEq};
/// IDPF-related errors.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum IdpfError {
/// Error from incompatible shares at different levels.
#[error("tried to merge shares from incompatible levels")]
@@ -107,6 +109,11 @@ impl IdpfInput {
index: self.index[..=level].to_owned().into(),
}
}
+
+ /// Return the bit at the specified level if the level is in bounds.
+ pub fn get(&self, level: usize) -> Option<bool> {
+ self.index.get(level).as_deref().copied()
+ }
}
impl From<BitVec<usize, Lsb0>> for IdpfInput {
@@ -146,7 +153,7 @@ pub trait IdpfValue:
+ Sub<Output = Self>
+ ConditionallyNegatable
+ Encode
- + Decode
+ + ParameterizedDecode<Self::ValueParameter>
+ Sized
{
/// Any run-time parameters needed to produce a value.
@@ -239,11 +246,13 @@ fn extend(seed: &[u8; 16], xof_fixed_key: &XofFixedKeyAes128Key) -> ([[u8; 16];
seed_stream.fill_bytes(&mut seeds[0]);
seed_stream.fill_bytes(&mut seeds[1]);
- let mut byte = [0u8];
- seed_stream.fill_bytes(&mut byte);
- let control_bits = [(byte[0] & 1).into(), ((byte[0] >> 1) & 1).into()];
+ // "Steal" the control bits from the seeds.
+ let control_bits_0 = seeds[0].as_ref()[0] & 1;
+ let control_bits_1 = seeds[1].as_ref()[0] & 1;
+ seeds[0].as_mut()[0] &= 0xfe;
+ seeds[1].as_mut()[0] &= 0xfe;
- (seeds, control_bits)
+ (seeds, [control_bits_0.into(), control_bits_1.into()])
}
fn convert<V>(
@@ -670,7 +679,7 @@ where
VI: Encode,
VL: Encode,
{
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
// Control bits need to be written within each byte in LSB-to-MSB order, and assigned into
// bytes in big-endian order. Thus, the first four levels will have their control bits
// encoded in the last byte, and the last levels will have their control bits encoded in the
@@ -691,11 +700,11 @@ where
bytes.append(&mut packed_control);
for correction_words in self.inner_correction_words.iter() {
- Seed(correction_words.seed).encode(bytes);
- correction_words.value.encode(bytes);
+ Seed(correction_words.seed).encode(bytes)?;
+ correction_words.value.encode(bytes)?;
}
- Seed(self.leaf_correction_word.seed).encode(bytes);
- self.leaf_correction_word.value.encode(bytes);
+ Seed(self.leaf_correction_word.seed).encode(bytes)?;
+ self.leaf_correction_word.value.encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -785,7 +794,7 @@ where
impl<V> Eq for IdpfCorrectionWord<V> where V: ConstantTimeEq {}
-fn xor_seeds(left: &[u8; 16], right: &[u8; 16]) -> [u8; 16] {
+pub(crate) fn xor_seeds(left: &[u8; 16], right: &[u8; 16]) -> [u8; 16] {
let mut seed = [0u8; 16];
for (a, (b, c)) in left.iter().zip(right.iter().zip(seed.iter_mut())) {
*c = a ^ b;
@@ -819,7 +828,7 @@ fn control_bit_to_seed_mask(control: Choice) -> [u8; 16] {
/// Take two seeds and a control bit, and return the first seed if the control bit is zero, or the
/// XOR of the two seeds if the control bit is one. This does not branch on the control bit.
-fn conditional_xor_seeds(
+pub(crate) fn conditional_xor_seeds(
normal_input: &[u8; 16],
switched_input: &[u8; 16],
control: Choice,
@@ -832,13 +841,18 @@ fn conditional_xor_seeds(
/// Returns one of two seeds, depending on the value of a selector bit. Does not branch on the
/// selector input or make selector-dependent memory accesses.
-fn conditional_select_seed(select: Choice, seeds: &[[u8; 16]; 2]) -> [u8; 16] {
+pub(crate) fn conditional_select_seed(select: Choice, seeds: &[[u8; 16]; 2]) -> [u8; 16] {
or_seeds(
&and_seeds(&control_bit_to_seed_mask(!select), &seeds[0]),
&and_seeds(&control_bit_to_seed_mask(select), &seeds[1]),
)
}
+/// Interchange the contents of seeds if the choice is 1, otherwise seeds remain unchanged.
+pub(crate) fn conditional_swap_seed(lhs: &mut [u8; 16], rhs: &mut [u8; 16], choice: Choice) {
+ zip(lhs, rhs).for_each(|(a, b)| u8::conditional_swap(a, b, choice));
+}
+
/// An interface that provides memoization of IDPF computations.
///
/// Each instance of a type implementing `IdpfCache` should only be used with one IDPF key and
@@ -947,11 +961,91 @@ impl IdpfCache for RingBufferCache {
}
}
+/// Utilities for testing IDPFs.
+#[cfg(feature = "test-util")]
+#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
+pub mod test_utils {
+ use super::*;
+
+ use rand::prelude::*;
+ use zipf::ZipfDistribution;
+
+ /// Generate a set of IDPF inputs with the given bit length `bits`. They are sampled according
+ /// to the Zipf distribution with parameters `zipf_support` and `zipf_exponent`. Return the
+ /// measurements, along with the prefixes traversed during the heavy hitters computation for
+ /// the given threshold.
+ ///
+ /// The prefix tree consists of a sequence of candidate prefixes for each level. For a given level,
+ /// the candidate prefixes are computed from the hit counts of the prefixes at the previous level:
+ /// For any prefix `p` whose hit count is at least the desired threshold, add `p || 0` and `p || 1`
+ /// to the list.
+ pub fn generate_zipf_distributed_batch(
+ rng: &mut impl Rng,
+ bits: usize,
+ threshold: usize,
+ measurement_count: usize,
+ zipf_support: usize,
+ zipf_exponent: f64,
+ ) -> (Vec<IdpfInput>, Vec<Vec<IdpfInput>>) {
+ // Generate random inputs.
+ let mut inputs = Vec::with_capacity(zipf_support);
+ for _ in 0..zipf_support {
+ let bools: Vec<bool> = (0..bits).map(|_| rng.gen()).collect();
+ inputs.push(IdpfInput::from_bools(&bools));
+ }
+
+ // Sample a number of inputs according to the Zipf distribution.
+ let mut samples = Vec::with_capacity(measurement_count);
+ let zipf = ZipfDistribution::new(zipf_support, zipf_exponent).unwrap();
+ for _ in 0..measurement_count {
+ samples.push(inputs[zipf.sample(rng) - 1].clone());
+ }
+
+ // Compute the prefix tree for the desired threshold.
+ let mut prefix_tree = Vec::with_capacity(bits);
+ prefix_tree.push(vec![
+ IdpfInput::from_bools(&[false]),
+ IdpfInput::from_bools(&[true]),
+ ]);
+
+ for level in 0..bits - 1 {
+ // Compute the hit count of each prefix from the previous level.
+ let mut hit_counts = vec![0; prefix_tree[level].len()];
+ for (hit_count, prefix) in hit_counts.iter_mut().zip(prefix_tree[level].iter()) {
+ for sample in samples.iter() {
+ let mut is_prefix = true;
+ for j in 0..prefix.len() {
+ if prefix[j] != sample[j] {
+ is_prefix = false;
+ break;
+ }
+ }
+ if is_prefix {
+ *hit_count += 1;
+ }
+ }
+ }
+
+ // Compute the next set of candidate prefixes.
+ let mut next_prefixes = Vec::with_capacity(prefix_tree.last().unwrap().len());
+ for (hit_count, prefix) in hit_counts.iter().zip(prefix_tree[level].iter()) {
+ if *hit_count >= threshold {
+ next_prefixes.push(prefix.clone_with_suffix(&[false]));
+ next_prefixes.push(prefix.clone_with_suffix(&[true]));
+ }
+ }
+ prefix_tree.push(next_prefixes);
+ }
+
+ (samples, prefix_tree)
+ }
+}
+
#[cfg(test)]
mod tests {
use std::{
collections::HashMap,
- convert::{TryFrom, TryInto},
+ convert::TryInto,
io::Cursor,
ops::{Add, AddAssign, Sub},
str::FromStr,
@@ -1568,16 +1662,16 @@ mod tests {
seed: [0xab; 16],
control_bits: [Choice::from(1), Choice::from(0)],
value: Poplar1IdpfValue::new([
- Field64::try_from(83261u64).unwrap(),
- Field64::try_from(125159u64).unwrap(),
+ Field64::from(83261u64),
+ Field64::from(125159u64),
]),
},
IdpfCorrectionWord{
seed: [0xcd;16],
control_bits: [Choice::from(0), Choice::from(1)],
value: Poplar1IdpfValue::new([
- Field64::try_from(17614120u64).unwrap(),
- Field64::try_from(20674u64).unwrap(),
+ Field64::from(17614120u64),
+ Field64::from(20674u64),
]),
},
]),
@@ -1605,7 +1699,7 @@ mod tests {
"f0debc9a78563412f0debc9a78563412f0debc9a78563412f0debc9a78563412", // field element correction word, continued
))
.unwrap();
- let encoded = public_share.get_encoded();
+ let encoded = public_share.get_encoded().unwrap();
let decoded = IdpfPublicShare::get_decoded_with_param(&3, &message).unwrap();
assert_eq!(public_share, decoded);
assert_eq!(message, encoded);
@@ -1692,7 +1786,7 @@ mod tests {
"0000000000000000000000000000000000000000000000000000000000000000",
))
.unwrap();
- let encoded = public_share.get_encoded();
+ let encoded = public_share.get_encoded().unwrap();
let decoded = IdpfPublicShare::get_decoded_with_param(&9, &message).unwrap();
assert_eq!(public_share, decoded);
assert_eq!(message, encoded);
@@ -1761,7 +1855,7 @@ mod tests {
0,
);
- assert_eq!(public_share.get_encoded(), serialized_public_share);
+ assert_eq!(public_share.get_encoded().unwrap(), serialized_public_share);
assert_eq!(
IdpfPublicShare::get_decoded_with_param(&idpf_bits, &serialized_public_share)
.unwrap(),
@@ -1821,7 +1915,7 @@ mod tests {
/// Load a test vector for Idpf key generation.
fn load_idpfpoplar_test_vector() -> IdpfTestVector {
let test_vec: serde_json::Value =
- serde_json::from_str(include_str!("vdaf/test_vec/07/IdpfPoplar_0.json")).unwrap();
+ serde_json::from_str(include_str!("vdaf/test_vec/08/IdpfPoplar_0.json")).unwrap();
let test_vec_obj = test_vec.as_object().unwrap();
let bits = test_vec_obj
@@ -1939,7 +2033,7 @@ mod tests {
public_share, expected_public_share,
"public share did not match\n{public_share:#x?}\n{expected_public_share:#x?}"
);
- let encoded_public_share = public_share.get_encoded();
+ let encoded_public_share = public_share.get_encoded().unwrap();
assert_eq!(encoded_public_share, test_vector.public_share);
}
@@ -1988,7 +2082,9 @@ mod tests {
}
impl Encode for MyUnit {
- fn encode(&self, _: &mut Vec<u8>) {}
+ fn encode(&self, _: &mut Vec<u8>) -> Result<(), CodecError> {
+ Ok(())
+ }
}
impl Decode for MyUnit {
@@ -2066,8 +2162,8 @@ mod tests {
}
impl Encode for MyVector {
- fn encode(&self, bytes: &mut Vec<u8>) {
- encode_u32_items(bytes, &(), &self.0);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ encode_u32_items(bytes, &(), &self.0)
}
}
diff --git a/third_party/rust/prio/src/lib.rs b/third_party/rust/prio/src/lib.rs
index c9d4e22c49..630e118646 100644
--- a/third_party/rust/prio/src/lib.rs
+++ b/third_party/rust/prio/src/lib.rs
@@ -17,6 +17,7 @@
pub mod benchmarked;
pub mod codec;
#[cfg(feature = "experimental")]
+#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))]
pub mod dp;
mod fft;
pub mod field;
@@ -32,3 +33,9 @@ mod polynomial;
mod prng;
pub mod topology;
pub mod vdaf;
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(feature = "crypto-dependencies", feature = "experimental")))
+)]
+pub mod vidpf;
diff --git a/third_party/rust/prio/src/polynomial.rs b/third_party/rust/prio/src/polynomial.rs
index 89d8a91404..272266f538 100644
--- a/third_party/rust/prio/src/polynomial.rs
+++ b/third_party/rust/prio/src/polynomial.rs
@@ -3,7 +3,7 @@
//! Functions for polynomial interpolation and evaluation
-#[cfg(feature = "prio2")]
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
use crate::fft::{discrete_fourier_transform, discrete_fourier_transform_inv_finish};
use crate::field::FftFriendlyFieldElement;
@@ -204,7 +204,7 @@ pub fn poly_mul<F: FftFriendlyFieldElement>(p: &[F], q: &[F]) -> Vec<F> {
out
}
-#[cfg(feature = "prio2")]
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
#[inline]
pub fn poly_interpret_eval<F: FftFriendlyFieldElement>(
points: &[F],
diff --git a/third_party/rust/prio/src/prng.rs b/third_party/rust/prio/src/prng.rs
index cb7d3a54c8..2c3f5b6640 100644
--- a/third_party/rust/prio/src/prng.rs
+++ b/third_party/rust/prio/src/prng.rs
@@ -6,10 +6,9 @@
//! NOTE: The public API for this module is a work in progress.
use crate::field::{FieldElement, FieldElementExt};
-#[cfg(feature = "crypto-dependencies")]
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
use crate::vdaf::xof::SeedStreamAes128;
-#[cfg(feature = "crypto-dependencies")]
-use getrandom::getrandom;
+use crate::vdaf::xof::{Seed, SeedStreamTurboShake128, Xof, XofTurboShake128};
use rand_core::RngCore;
use std::marker::PhantomData;
@@ -19,6 +18,7 @@ const BUFFER_SIZE_IN_ELEMENTS: usize = 32;
/// Errors propagated by methods in this module.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum PrngError {
/// Failure when calling getrandom().
#[error("getrandom: {0}")]
@@ -35,7 +35,7 @@ pub(crate) struct Prng<F, S> {
buffer_index: usize,
}
-#[cfg(feature = "crypto-dependencies")]
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
impl<F: FieldElement> Prng<F, SeedStreamAes128> {
/// Create a [`Prng`] from a seed for Prio 2. The first 16 bytes of the seed and the last 16
/// bytes of the seed are used, respectively, for the key and initialization vector for AES128
@@ -44,12 +44,17 @@ impl<F: FieldElement> Prng<F, SeedStreamAes128> {
let seed_stream = SeedStreamAes128::new(&seed[..16], &seed[16..]);
Self::from_seed_stream(seed_stream)
}
+}
+impl<F: FieldElement> Prng<F, SeedStreamTurboShake128> {
/// Create a [`Prng`] from a randomly generated seed.
pub(crate) fn new() -> Result<Self, PrngError> {
- let mut seed = [0; 32];
- getrandom(&mut seed)?;
- Ok(Self::from_prio2_seed(&seed))
+ let seed = Seed::generate()?;
+ Ok(Prng::from_seed_stream(XofTurboShake128::seed_stream(
+ &seed,
+ &[],
+ &[],
+ )))
}
}
@@ -125,18 +130,20 @@ where
#[cfg(test)]
mod tests {
use super::*;
+ #[cfg(feature = "experimental")]
+ use crate::field::{encode_fieldvec, Field128, FieldPrio2};
use crate::{
codec::Decode,
- field::{Field64, FieldPrio2},
- vdaf::xof::{Seed, SeedStreamSha3, Xof, XofShake128},
+ field::Field64,
+ vdaf::xof::{Seed, SeedStreamTurboShake128, Xof, XofTurboShake128},
};
- #[cfg(feature = "prio2")]
+ #[cfg(feature = "experimental")]
use base64::{engine::Engine, prelude::BASE64_STANDARD};
- #[cfg(feature = "prio2")]
+ #[cfg(feature = "experimental")]
use sha2::{Digest, Sha256};
- use std::convert::TryInto;
#[test]
+ #[cfg(feature = "experimental")]
fn secret_sharing_interop() {
let seed = [
0xcd, 0x85, 0x5b, 0xd4, 0x86, 0x48, 0xa4, 0xce, 0x52, 0x5c, 0x36, 0xee, 0x5a, 0x71,
@@ -158,21 +165,22 @@ mod tests {
}
/// takes a seed and hash as base64 encoded strings
- #[cfg(feature = "prio2")]
+ #[cfg(feature = "experimental")]
fn random_data_interop(seed_base64: &str, hash_base64: &str, len: usize) {
let seed = BASE64_STANDARD.decode(seed_base64).unwrap();
let random_data = extract_share_from_seed::<FieldPrio2>(len, &seed);
- let random_bytes = FieldPrio2::slice_into_byte_vec(&random_data);
+ let mut random_bytes = Vec::new();
+ encode_fieldvec(&random_data, &mut random_bytes).unwrap();
- let mut hasher = Sha256::new();
+ let mut hasher = <Sha256 as Digest>::new();
hasher.update(&random_bytes);
let digest = hasher.finalize();
assert_eq!(BASE64_STANDARD.encode(digest), hash_base64);
}
#[test]
- #[cfg(feature = "prio2")]
+ #[cfg(feature = "experimental")]
fn test_hash_interop() {
random_data_interop(
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
@@ -206,6 +214,7 @@ mod tests {
);
}
+ #[cfg(feature = "experimental")]
fn extract_share_from_seed<F: FieldElement>(length: usize, seed: &[u8]) -> Vec<F> {
assert_eq!(seed.len(), 32);
Prng::from_prio2_seed(seed.try_into().unwrap())
@@ -218,22 +227,22 @@ mod tests {
// These constants were found in a brute-force search, and they test that the XOF performs
// rejection sampling correctly when the raw output exceeds the prime modulus.
let seed = Seed::get_decoded(&[
- 0x29, 0xb2, 0x98, 0x64, 0xb4, 0xaa, 0x4e, 0x07, 0x2a, 0x44, 0x49, 0x24, 0xf6, 0x74,
- 0x0a, 0x3d,
+ 0xd5, 0x3f, 0xff, 0x5d, 0x88, 0x8c, 0x60, 0x4e, 0x9f, 0x24, 0x16, 0xe1, 0xa2, 0x0a,
+ 0x62, 0x34,
])
.unwrap();
- let expected = Field64::from(2035552711764301796);
+ let expected = Field64::from(3401316594827516850);
- let seed_stream = XofShake128::seed_stream(&seed, b"", b"");
+ let seed_stream = XofTurboShake128::seed_stream(&seed, b"", b"");
let mut prng = Prng::<Field64, _>::from_seed_stream(seed_stream);
- let actual = prng.nth(33236).unwrap();
+ let actual = prng.nth(662).unwrap();
assert_eq!(actual, expected);
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
{
- let mut seed_stream = XofShake128::seed_stream(&seed, b"", b"");
+ let mut seed_stream = XofTurboShake128::seed_stream(&seed, b"", b"");
let mut actual = <Field64 as FieldElement>::zero();
- for _ in 0..=33236 {
+ for _ in 0..=662 {
actual = <Field64 as crate::idpf::IdpfValue>::generate(&mut seed_stream, &());
}
assert_eq!(actual, expected);
@@ -246,12 +255,12 @@ mod tests {
fn left_over_buffer_back_fill() {
let seed = Seed::generate().unwrap();
- let mut prng: Prng<Field64, SeedStreamSha3> =
- Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b""));
+ let mut prng: Prng<Field64, SeedStreamTurboShake128> =
+ Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b""));
// Construct a `Prng` with a longer-than-usual buffer.
- let mut prng_weird_buffer_size: Prng<Field64, SeedStreamSha3> =
- Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b""));
+ let mut prng_weird_buffer_size: Prng<Field64, SeedStreamTurboShake128> =
+ Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b""));
let mut extra = [0; 7];
prng_weird_buffer_size.seed_stream.fill_bytes(&mut extra);
prng_weird_buffer_size.buffer.extend_from_slice(&extra);
@@ -265,13 +274,13 @@ mod tests {
#[cfg(feature = "experimental")]
#[test]
- fn into_new_field() {
+ fn into_different_field() {
let seed = Seed::generate().unwrap();
- let want: Prng<Field64, SeedStreamSha3> =
- Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b""));
+ let want: Prng<Field64, SeedStreamTurboShake128> =
+ Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b""));
let want_buffer = want.buffer.clone();
- let got: Prng<FieldPrio2, _> = want.into_new_field();
+ let got: Prng<Field128, _> = want.into_new_field();
assert_eq!(got.buffer_index, 0);
assert_eq!(got.buffer, want_buffer);
}
diff --git a/third_party/rust/prio/src/topology/ping_pong.rs b/third_party/rust/prio/src/topology/ping_pong.rs
index c55d4f638d..646f181865 100644
--- a/third_party/rust/prio/src/topology/ping_pong.rs
+++ b/third_party/rust/prio/src/topology/ping_pong.rs
@@ -4,7 +4,7 @@
//! two aggregators, designated "Leader" and "Helper". This topology is required for implementing
//! the [Distributed Aggregation Protocol][DAP].
//!
-//! [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
+//! [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
//! [DAP]: https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap
use crate::{
@@ -15,6 +15,7 @@ use std::fmt::Debug;
/// Errors emitted by this module.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum PingPongError {
/// Error running prepare_init
#[error("vdaf.prepare_init: {0}")]
@@ -28,12 +29,12 @@ pub enum PingPongError {
#[error("vdaf.prepare_next {0}")]
VdafPrepareNext(VdafError),
- /// Error decoding a prepare share
- #[error("decode prep share {0}")]
+ /// Error encoding or decoding a prepare share
+ #[error("encode/decode prep share {0}")]
CodecPrepShare(CodecError),
- /// Error decoding a prepare message
- #[error("decode prep message {0}")]
+ /// Error encoding or decoding a prepare message
+ #[error("encode/decode prep message {0}")]
CodecPrepMessage(CodecError),
/// Host is in an unexpected state
@@ -63,7 +64,7 @@ pub enum PingPongError {
/// variants are opaque byte buffers. This is because the ping-pong routines take responsibility for
/// decoding preparation shares and messages, which usually requires having the preparation state.
///
-/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
+/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
#[derive(Clone, PartialEq, Eq)]
pub enum PingPongMessage {
/// Corresponds to MessageType.initialize.
@@ -108,27 +109,28 @@ impl Debug for PingPongMessage {
}
impl Encode for PingPongMessage {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
// The encoding includes an implicit discriminator byte, called MessageType in the VDAF
// spec.
match self {
Self::Initialize { prep_share } => {
- 0u8.encode(bytes);
- encode_u32_items(bytes, &(), prep_share);
+ 0u8.encode(bytes)?;
+ encode_u32_items(bytes, &(), prep_share)?;
}
Self::Continue {
prep_msg,
prep_share,
} => {
- 1u8.encode(bytes);
- encode_u32_items(bytes, &(), prep_msg);
- encode_u32_items(bytes, &(), prep_share);
+ 1u8.encode(bytes)?;
+ encode_u32_items(bytes, &(), prep_msg)?;
+ encode_u32_items(bytes, &(), prep_share)?;
}
Self::Finish { prep_msg } => {
- 2u8.encode(bytes);
- encode_u32_items(bytes, &(), prep_msg);
+ 2u8.encode(bytes)?;
+ encode_u32_items(bytes, &(), prep_msg)?;
}
}
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -182,7 +184,7 @@ impl Decode for PingPongMessage {
/// preprocessed prepare message. Their encoding is much smaller than the `(State, Message)` tuple,
/// which can always be recomputed with [`Self::evaluate`].
///
-/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
+/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
#[derive(Clone, Debug, Eq)]
pub struct PingPongTransition<
const VERIFY_KEY_SIZE: usize,
@@ -212,26 +214,31 @@ impl<
),
PingPongError,
> {
- let prep_msg = self.current_prepare_message.get_encoded();
+ let prep_msg = self
+ .current_prepare_message
+ .get_encoded()
+ .map_err(PingPongError::CodecPrepMessage)?;
vdaf.prepare_next(
self.previous_prepare_state.clone(),
self.current_prepare_message.clone(),
)
- .map(|transition| match transition {
- PrepareTransition::Continue(prep_state, prep_share) => (
+ .map_err(PingPongError::VdafPrepareNext)
+ .and_then(|transition| match transition {
+ PrepareTransition::Continue(prep_state, prep_share) => Ok((
PingPongState::Continued(prep_state),
PingPongMessage::Continue {
prep_msg,
- prep_share: prep_share.get_encoded(),
+ prep_share: prep_share
+ .get_encoded()
+ .map_err(PingPongError::CodecPrepShare)?,
},
- ),
- PrepareTransition::Finish(output_share) => (
+ )),
+ PrepareTransition::Finish(output_share) => Ok((
PingPongState::Finished(output_share),
PingPongMessage::Finish { prep_msg },
- ),
+ )),
})
- .map_err(PingPongError::VdafPrepareNext)
}
}
@@ -253,9 +260,9 @@ where
A: Aggregator<VERIFY_KEY_SIZE, NONCE_SIZE>,
A::PrepareState: Encode,
{
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.previous_prepare_state.encode(bytes);
- self.current_prepare_message.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.previous_prepare_state.encode(bytes)?;
+ self.current_prepare_message.encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -293,7 +300,7 @@ where
/// code, and the `Rejected` state is represented as `std::result::Result::Err`, so this enum does
/// not include those variants.
///
-/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
+/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PingPongState<
const VERIFY_KEY_SIZE: usize,
@@ -331,7 +338,7 @@ pub enum PingPongContinuedValue<
/// Extension trait on [`crate::vdaf::Aggregator`] which adds the [VDAF Ping-Pong Topology][VDAF].
///
-/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
+/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>:
Aggregator<VERIFY_KEY_SIZE, NONCE_SIZE>
{
@@ -351,7 +358,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize
/// leader along with the next [`PingPongMessage`] received from the helper as input to
/// [`Self::leader_continued`] to advance to the next round.
///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
fn leader_initialized(
&self,
verify_key: &[u8; VERIFY_KEY_SIZE],
@@ -362,7 +369,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize
) -> Result<(Self::State, PingPongMessage), PingPongError>;
/// Initialize helper state using the helper's input share and the leader's first prepare share.
- /// Corresponds to `ping_pong_helper_init` in the forthcoming `draft-irtf-cfrg-vdaf-07`.
+ /// Corresponds to `ping_pong_helper_init` in [VDAF].
///
/// If successful, the returned [`PingPongTransition`] should be evaluated, yielding a
/// [`PingPongMessage`], which should be transmitted to the leader, and a [`PingPongState`].
@@ -378,6 +385,8 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize
/// # Errors
///
/// `inbound` must be `PingPongMessage::Initialize` or the function will fail.
+ ///
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
fn helper_initialized(
&self,
verify_key: &[u8; VERIFY_KEY_SIZE],
@@ -415,15 +424,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize
///
/// `inbound` must not be `PingPongMessage::Initialize` or the function will fail.
///
- /// # Notes
- ///
- /// The specification of this function in [VDAF] takes the aggregation parameter. This version
- /// does not, because [`crate::vdaf::Aggregator::prepare_preprocess`] does not take the
- /// aggregation parameter. This may change in the future if/when [#670][issue] is addressed.
- ///
- ///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
- /// [issue]: https://github.com/divviup/libprio-rs/issues/670
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
fn leader_continued(
&self,
leader_state: Self::State,
@@ -458,15 +459,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize
///
/// `inbound` must not be `PingPongMessage::Initialize` or the function will fail.
///
- /// # Notes
- ///
- /// The specification of this function in [VDAF] takes the aggregation parameter. This version
- /// does not, because [`crate::vdaf::Aggregator::prepare_preprocess`] does not take the
- /// aggregation parameter. This may change in the future if/when [#670][issue] is addressed.
- ///
- ///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8
- /// [issue]: https://github.com/divviup/libprio-rs/issues/670
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8
fn helper_continued(
&self,
helper_state: Self::State,
@@ -513,15 +506,17 @@ where
public_share,
input_share,
)
- .map(|(prep_state, prep_share)| {
- (
+ .map_err(PingPongError::VdafPrepareInit)
+ .and_then(|(prep_state, prep_share)| {
+ Ok((
PingPongState::Continued(prep_state),
PingPongMessage::Initialize {
- prep_share: prep_share.get_encoded(),
+ prep_share: prep_share
+ .get_encoded()
+ .map_err(PingPongError::CodecPrepShare)?,
},
- )
+ ))
})
- .map_err(PingPongError::VdafPrepareInit)
}
fn helper_initialized(
@@ -652,18 +647,14 @@ where
(PrepareTransition::Finish(output_share), None) => {
Ok(PingPongContinuedValue::FinishedNoMessage { output_share })
}
- (PrepareTransition::Continue(_, _), None) => {
- return Err(PingPongError::PeerMessageMismatch {
- found: inbound.variant(),
- expected: "continue",
- })
- }
- (PrepareTransition::Finish(_), Some(_)) => {
- return Err(PingPongError::PeerMessageMismatch {
- found: inbound.variant(),
- expected: "finish",
- })
- }
+ (PrepareTransition::Continue(_, _), None) => Err(PingPongError::PeerMessageMismatch {
+ found: inbound.variant(),
+ expected: "continue",
+ }),
+ (PrepareTransition::Finish(_), Some(_)) => Err(PingPongError::PeerMessageMismatch {
+ found: inbound.variant(),
+ expected: "finish",
+ }),
}
}
}
@@ -914,7 +905,7 @@ mod tests {
for (message, expected_hex) in messages {
let mut encoded_val = Vec::new();
- message.encode(&mut encoded_val);
+ message.encode(&mut encoded_val).unwrap();
let got_hex = hex::encode(&encoded_val);
assert_eq!(
&got_hex, expected_hex,
@@ -942,7 +933,7 @@ mod tests {
current_prepare_message: (),
};
- let encoded = transition.get_encoded();
+ let encoded = transition.get_encoded().unwrap();
let hex_encoded = hex::encode(&encoded);
assert_eq!(
diff --git a/third_party/rust/prio/src/vdaf.rs b/third_party/rust/prio/src/vdaf.rs
index 1a6c5f0315..e5f4e14c5a 100644
--- a/third_party/rust/prio/src/vdaf.rs
+++ b/third_party/rust/prio/src/vdaf.rs
@@ -1,14 +1,16 @@
// SPDX-License-Identifier: MPL-2.0
//! Verifiable Distributed Aggregation Functions (VDAFs) as described in
-//! [[draft-irtf-cfrg-vdaf-07]].
+//! [[draft-irtf-cfrg-vdaf-08]].
//!
-//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
#[cfg(feature = "experimental")]
use crate::dp::DifferentialPrivacyStrategy;
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
use crate::idpf::IdpfError;
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
+use crate::vidpf::VidpfError;
use crate::{
codec::{CodecError, Decode, Encode, ParameterizedDecode},
field::{encode_fieldvec, merge_vector, FieldElement, FieldError},
@@ -17,15 +19,16 @@ use crate::{
vdaf::xof::Seed,
};
use serde::{Deserialize, Serialize};
-use std::{fmt::Debug, io::Cursor};
+use std::{error::Error, fmt::Debug, io::Cursor};
use subtle::{Choice, ConstantTimeEq};
/// A component of the domain-separation tag, used to bind the VDAF operations to the document
/// version. This will be revised with each draft with breaking changes.
-pub(crate) const VERSION: u8 = 7;
+pub(crate) const VERSION: u8 = 8;
/// Errors emitted by this module.
#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
pub enum VdafError {
/// An error occurred.
#[error("vdaf error: {0}")]
@@ -55,6 +58,15 @@ pub enum VdafError {
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
#[error("idpf error: {0}")]
Idpf(#[from] IdpfError),
+
+ /// VIDPF error.
+ #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
+ #[error("vidpf error: {0}")]
+ Vidpf(#[from] VidpfError),
+
+ /// Errors from other VDAFs.
+ #[error(transparent)]
+ Other(Box<dyn Error + 'static + Send + Sync>),
}
/// An additive share of a vector of field elements.
@@ -67,18 +79,6 @@ pub enum Share<F, const SEED_SIZE: usize> {
Helper(Seed<SEED_SIZE>),
}
-impl<F: Clone, const SEED_SIZE: usize> Share<F, SEED_SIZE> {
- /// Truncate the Leader's share to the given length. If this is the Helper's share, then this
- /// method clones the input without modifying it.
- #[cfg(feature = "prio2")]
- pub(crate) fn truncated(&self, len: usize) -> Self {
- match self {
- Self::Leader(ref data) => Self::Leader(data[..len].to_vec()),
- Self::Helper(ref seed) => Self::Helper(seed.clone()),
- }
- }
-}
-
impl<F: ConstantTimeEq, const SEED_SIZE: usize> PartialEq for Share<F, SEED_SIZE> {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(other).into()
@@ -130,16 +130,15 @@ impl<F: FieldElement, const SEED_SIZE: usize> ParameterizedDecode<ShareDecodingP
}
impl<F: FieldElement, const SEED_SIZE: usize> Encode for Share<F, SEED_SIZE> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
match self {
Share::Leader(share_data) => {
for x in share_data {
- x.encode(bytes);
+ x.encode(bytes)?;
}
+ Ok(())
}
- Share::Helper(share_seed) => {
- share_seed.encode(bytes);
- }
+ Share::Helper(share_seed) => share_seed.encode(bytes),
}
}
@@ -158,9 +157,6 @@ impl<F: FieldElement, const SEED_SIZE: usize> Encode for Share<F, SEED_SIZE> {
/// and [`Collector`], which define the roles of the various parties involved in the execution of
/// the VDAF.
pub trait Vdaf: Clone + Debug {
- /// Algorithm identifier for this VDAF.
- const ID: u32;
-
/// The type of Client measurement to be aggregated.
type Measurement: Clone + Debug;
@@ -188,17 +184,20 @@ pub trait Vdaf: Clone + Debug {
+ for<'a> ParameterizedDecode<(&'a Self, &'a Self::AggregationParam)>
+ Encode;
+ /// Return the VDAF's algorithm ID.
+ fn algorithm_id(&self) -> u32;
+
/// The number of Aggregators. The Client generates as many input shares as there are
/// Aggregators.
fn num_aggregators(&self) -> usize;
/// Generate the domain separation tag for this VDAF. The output is used for domain separation
/// by the XOF.
- fn domain_separation_tag(usage: u16) -> [u8; 8] {
+ fn domain_separation_tag(&self, usage: u16) -> [u8; 8] {
let mut dst = [0_u8; 8];
dst[0] = VERSION;
dst[1] = 0; // algorithm class
- dst[2..6].copy_from_slice(&(Self::ID).to_be_bytes());
+ dst[2..6].copy_from_slice(&(self.algorithm_id()).to_be_bytes());
dst[6..8].copy_from_slice(&usage.to_be_bytes());
dst
}
@@ -211,7 +210,7 @@ pub trait Client<const NONCE_SIZE: usize>: Vdaf {
///
/// Implements `Vdaf::shard` from [VDAF].
///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.1
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.1
fn shard(
&self,
measurement: &Self::Measurement,
@@ -247,7 +246,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda
///
/// Implements `Vdaf.prep_init` from [VDAF].
///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2
fn prepare_init(
&self,
verify_key: &[u8; VERIFY_KEY_SIZE],
@@ -262,29 +261,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda
///
/// Implements `Vdaf.prep_shares_to_prep` from [VDAF].
///
- /// # Notes
- ///
- /// [`Self::prepare_shares_to_prepare_message`] is preferable since its name better matches the
- /// specification.
- ///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2
- #[deprecated(
- since = "0.15.0",
- note = "Use Vdaf::prepare_shares_to_prepare_message instead"
- )]
- fn prepare_preprocess<M: IntoIterator<Item = Self::PrepareShare>>(
- &self,
- agg_param: &Self::AggregationParam,
- inputs: M,
- ) -> Result<Self::PrepareMessage, VdafError> {
- self.prepare_shares_to_prepare_message(agg_param, inputs)
- }
-
- /// Preprocess a round of preparation shares into a single input to [`Self::prepare_next`].
- ///
- /// Implements `Vdaf.prep_shares_to_prep` from [VDAF].
- ///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2
fn prepare_shares_to_prepare_message<M: IntoIterator<Item = Self::PrepareShare>>(
&self,
agg_param: &Self::AggregationParam,
@@ -301,31 +278,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda
///
/// Implements `Vdaf.prep_next` from [VDAF].
///
- /// # Notes
- ///
- /// [`Self::prepare_next`] is preferable since its name better matches the specification.
- ///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2
- #[deprecated(since = "0.15.0", note = "Use Vdaf::prepare_next")]
- fn prepare_step(
- &self,
- state: Self::PrepareState,
- input: Self::PrepareMessage,
- ) -> Result<PrepareTransition<Self, VERIFY_KEY_SIZE, NONCE_SIZE>, VdafError> {
- self.prepare_next(state, input)
- }
-
- /// Compute the next state transition from the current state and the previous round of input
- /// messages. If this returns [`PrepareTransition::Continue`], then the returned
- /// [`Self::PrepareShare`] should be combined with the other Aggregators' `PrepareShare`s from
- /// this round and passed into another call to this method. This continues until this method
- /// returns [`PrepareTransition::Finish`], at which point the returned output share may be
- /// aggregated. If the method returns an error, the aggregator should consider its input share
- /// invalid and not attempt to process it any further.
- ///
- /// Implements `Vdaf.prep_next` from [VDAF].
- ///
- /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2
+ /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2
fn prepare_next(
&self,
state: Self::PrepareState,
@@ -342,6 +295,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda
/// Aggregator that implements differential privacy with Aggregator-side noise addition.
#[cfg(feature = "experimental")]
+#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))]
pub trait AggregatorWithNoise<
const VERIFY_KEY_SIZE: usize,
const NONCE_SIZE: usize,
@@ -428,7 +382,7 @@ impl<F> From<Vec<F>> for OutputShare<F> {
}
impl<F: FieldElement> Encode for OutputShare<F> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
encode_fieldvec(&self.0, bytes)
}
@@ -451,6 +405,12 @@ impl<F> Debug for OutputShare<F> {
pub struct AggregateShare<F>(Vec<F>);
+impl<F> From<Vec<F>> for AggregateShare<F> {
+ fn from(other: Vec<F>) -> Self {
+ Self(other)
+ }
+}
+
impl<F: ConstantTimeEq> PartialEq for AggregateShare<F> {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(other).into()
@@ -498,7 +458,7 @@ impl<F: FieldElement> AggregateShare<F> {
}
impl<F: FieldElement> Encode for AggregateShare<F> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
encode_fieldvec(&self.0, bytes)
}
@@ -507,151 +467,190 @@ impl<F: FieldElement> Encode for AggregateShare<F> {
}
}
-#[cfg(test)]
-pub(crate) fn run_vdaf<V, M, const SEED_SIZE: usize>(
- vdaf: &V,
- agg_param: &V::AggregationParam,
- measurements: M,
-) -> Result<V::AggregateResult, VdafError>
-where
- V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector,
- M: IntoIterator<Item = V::Measurement>,
-{
+/// Utilities for testing VDAFs.
+#[cfg(feature = "test-util")]
+#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
+pub mod test_utils {
+ use super::{Aggregatable, Aggregator, Client, Collector, PrepareTransition, VdafError};
+ use crate::codec::{Encode, ParameterizedDecode};
use rand::prelude::*;
- let mut rng = thread_rng();
- let mut verify_key = [0; SEED_SIZE];
- rng.fill(&mut verify_key[..]);
-
- let mut agg_shares: Vec<Option<V::AggregateShare>> = vec![None; vdaf.num_aggregators()];
- let mut num_measurements: usize = 0;
- for measurement in measurements.into_iter() {
- num_measurements += 1;
- let nonce = rng.gen();
- let (public_share, input_shares) = vdaf.shard(&measurement, &nonce)?;
- let out_shares = run_vdaf_prepare(
- vdaf,
- &verify_key,
- agg_param,
- &nonce,
- public_share,
- input_shares,
- )?;
- for (out_share, agg_share) in out_shares.into_iter().zip(agg_shares.iter_mut()) {
- // Check serialization of output shares
- let encoded_out_share = out_share.get_encoded();
- let round_trip_out_share =
- V::OutputShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_out_share)
- .unwrap();
- assert_eq!(round_trip_out_share.get_encoded(), encoded_out_share);
- let this_agg_share = V::AggregateShare::from(out_share);
- if let Some(ref mut inner) = agg_share {
- inner.merge(&this_agg_share)?;
- } else {
- *agg_share = Some(this_agg_share);
- }
+ /// Execute the VDAF end-to-end and return the aggregate result.
+ pub fn run_vdaf<V, M, const SEED_SIZE: usize>(
+ vdaf: &V,
+ agg_param: &V::AggregationParam,
+ measurements: M,
+ ) -> Result<V::AggregateResult, VdafError>
+ where
+ V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector,
+ M: IntoIterator<Item = V::Measurement>,
+ {
+ let mut sharded_measurements = Vec::new();
+ for measurement in measurements.into_iter() {
+ let nonce = random();
+ let (public_share, input_shares) = vdaf.shard(&measurement, &nonce)?;
+
+ sharded_measurements.push((public_share, nonce, input_shares));
}
- }
- for agg_share in agg_shares.iter() {
- // Check serialization of aggregate shares
- let encoded_agg_share = agg_share.as_ref().unwrap().get_encoded();
- let round_trip_agg_share =
- V::AggregateShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_agg_share)
- .unwrap();
- assert_eq!(round_trip_agg_share.get_encoded(), encoded_agg_share);
- }
+ run_vdaf_sharded(vdaf, agg_param, sharded_measurements)
+ }
+
+ /// Execute the VDAF on sharded measurements and return the aggregate result.
+ pub fn run_vdaf_sharded<V, M, I, const SEED_SIZE: usize>(
+ vdaf: &V,
+ agg_param: &V::AggregationParam,
+ sharded_measurements: M,
+ ) -> Result<V::AggregateResult, VdafError>
+ where
+ V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector,
+ M: IntoIterator<Item = (V::PublicShare, [u8; 16], I)>,
+ I: IntoIterator<Item = V::InputShare>,
+ {
+ let mut rng = thread_rng();
+ let mut verify_key = [0; SEED_SIZE];
+ rng.fill(&mut verify_key[..]);
+
+ let mut agg_shares: Vec<Option<V::AggregateShare>> = vec![None; vdaf.num_aggregators()];
+ let mut num_measurements: usize = 0;
+ for (public_share, nonce, input_shares) in sharded_measurements.into_iter() {
+ num_measurements += 1;
+ let out_shares = run_vdaf_prepare(
+ vdaf,
+ &verify_key,
+ agg_param,
+ &nonce,
+ public_share,
+ input_shares,
+ )?;
+ for (out_share, agg_share) in out_shares.into_iter().zip(agg_shares.iter_mut()) {
+ // Check serialization of output shares
+ let encoded_out_share = out_share.get_encoded().unwrap();
+ let round_trip_out_share =
+ V::OutputShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_out_share)
+ .unwrap();
+ assert_eq!(
+ round_trip_out_share.get_encoded().unwrap(),
+ encoded_out_share
+ );
- let res = vdaf.unshard(
- agg_param,
- agg_shares.into_iter().map(|option| option.unwrap()),
- num_measurements,
- )?;
- Ok(res)
-}
+ let this_agg_share = V::AggregateShare::from(out_share);
+ if let Some(ref mut inner) = agg_share {
+ inner.merge(&this_agg_share)?;
+ } else {
+ *agg_share = Some(this_agg_share);
+ }
+ }
+ }
-#[cfg(test)]
-pub(crate) fn run_vdaf_prepare<V, M, const SEED_SIZE: usize>(
- vdaf: &V,
- verify_key: &[u8; SEED_SIZE],
- agg_param: &V::AggregationParam,
- nonce: &[u8; 16],
- public_share: V::PublicShare,
- input_shares: M,
-) -> Result<Vec<V::OutputShare>, VdafError>
-where
- V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector,
- M: IntoIterator<Item = V::InputShare>,
-{
- let input_shares = input_shares
- .into_iter()
- .map(|input_share| input_share.get_encoded());
-
- let mut states = Vec::new();
- let mut outbound = Vec::new();
- for (agg_id, input_share) in input_shares.enumerate() {
- let (state, msg) = vdaf.prepare_init(
- verify_key,
- agg_id,
+ for agg_share in agg_shares.iter() {
+ // Check serialization of aggregate shares
+ let encoded_agg_share = agg_share.as_ref().unwrap().get_encoded().unwrap();
+ let round_trip_agg_share =
+ V::AggregateShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_agg_share)
+ .unwrap();
+ assert_eq!(
+ round_trip_agg_share.get_encoded().unwrap(),
+ encoded_agg_share
+ );
+ }
+
+ let res = vdaf.unshard(
agg_param,
- nonce,
- &public_share,
- &V::InputShare::get_decoded_with_param(&(vdaf, agg_id), &input_share)
- .expect("failed to decode input share"),
+ agg_shares.into_iter().map(|option| option.unwrap()),
+ num_measurements,
)?;
- states.push(state);
- outbound.push(msg.get_encoded());
- }
+ Ok(res)
+ }
+
+ /// Execute VDAF preparation for a single report and return the recovered output shares.
+ pub fn run_vdaf_prepare<V, M, const SEED_SIZE: usize>(
+ vdaf: &V,
+ verify_key: &[u8; SEED_SIZE],
+ agg_param: &V::AggregationParam,
+ nonce: &[u8; 16],
+ public_share: V::PublicShare,
+ input_shares: M,
+ ) -> Result<Vec<V::OutputShare>, VdafError>
+ where
+ V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector,
+ M: IntoIterator<Item = V::InputShare>,
+ {
+ let public_share =
+ V::PublicShare::get_decoded_with_param(vdaf, &public_share.get_encoded().unwrap())
+ .unwrap();
+ let input_shares = input_shares
+ .into_iter()
+ .map(|input_share| input_share.get_encoded().unwrap());
- let mut inbound = vdaf
- .prepare_shares_to_prepare_message(
- agg_param,
- outbound.iter().map(|encoded| {
- V::PrepareShare::get_decoded_with_param(&states[0], encoded)
- .expect("failed to decode prep share")
- }),
- )?
- .get_encoded();
-
- let mut out_shares = Vec::new();
- loop {
+ let mut states = Vec::new();
let mut outbound = Vec::new();
- for state in states.iter_mut() {
- match vdaf.prepare_next(
- state.clone(),
- V::PrepareMessage::get_decoded_with_param(state, &inbound)
- .expect("failed to decode prep message"),
- )? {
- PrepareTransition::Continue(new_state, msg) => {
- outbound.push(msg.get_encoded());
- *state = new_state
- }
- PrepareTransition::Finish(out_share) => {
- out_shares.push(out_share);
+ for (agg_id, input_share) in input_shares.enumerate() {
+ let (state, msg) = vdaf.prepare_init(
+ verify_key,
+ agg_id,
+ agg_param,
+ nonce,
+ &public_share,
+ &V::InputShare::get_decoded_with_param(&(vdaf, agg_id), &input_share)
+ .expect("failed to decode input share"),
+ )?;
+ states.push(state);
+ outbound.push(msg.get_encoded().unwrap());
+ }
+
+ let mut inbound = vdaf
+ .prepare_shares_to_prepare_message(
+ agg_param,
+ outbound.iter().map(|encoded| {
+ V::PrepareShare::get_decoded_with_param(&states[0], encoded)
+ .expect("failed to decode prep share")
+ }),
+ )?
+ .get_encoded()
+ .unwrap();
+
+ let mut out_shares = Vec::new();
+ loop {
+ let mut outbound = Vec::new();
+ for state in states.iter_mut() {
+ match vdaf.prepare_next(
+ state.clone(),
+ V::PrepareMessage::get_decoded_with_param(state, &inbound)
+ .expect("failed to decode prep message"),
+ )? {
+ PrepareTransition::Continue(new_state, msg) => {
+ outbound.push(msg.get_encoded().unwrap());
+ *state = new_state
+ }
+ PrepareTransition::Finish(out_share) => {
+ out_shares.push(out_share);
+ }
}
}
- }
- if outbound.len() == vdaf.num_aggregators() {
- // Another round is required before output shares are computed.
- inbound = vdaf
- .prepare_shares_to_prepare_message(
- agg_param,
- outbound.iter().map(|encoded| {
- V::PrepareShare::get_decoded_with_param(&states[0], encoded)
- .expect("failed to decode prep share")
- }),
- )?
- .get_encoded();
- } else if outbound.is_empty() {
- // Each Aggregator recovered an output share.
- break;
- } else {
- panic!("Aggregators did not finish the prepare phase at the same time");
+ if outbound.len() == vdaf.num_aggregators() {
+ // Another round is required before output shares are computed.
+ inbound = vdaf
+ .prepare_shares_to_prepare_message(
+ agg_param,
+ outbound.iter().map(|encoded| {
+ V::PrepareShare::get_decoded_with_param(&states[0], encoded)
+ .expect("failed to decode prep share")
+ }),
+ )?
+ .get_encoded()
+ .unwrap();
+ } else if outbound.is_empty() {
+ // Each Aggregator recovered an output share.
+ break;
+ } else {
+ panic!("Aggregators did not finish the prepare phase at the same time");
+ }
}
- }
- Ok(out_shares)
+ Ok(out_shares)
+ }
}
#[cfg(test)]
@@ -663,20 +662,17 @@ where
for<'a> T: ParameterizedDecode<(&'a V, &'a V::AggregationParam)>,
{
// Generate an arbitrary vector of field elements.
- let g = F::one() + F::one();
- let vec: Vec<F> = itertools::iterate(F::one(), |&v| g * v)
- .take(length)
- .collect();
+ let vec: Vec<F> = crate::field::random_vector(length).unwrap();
// Serialize the field element vector into a vector of bytes.
let mut bytes = Vec::with_capacity(vec.len() * F::ENCODED_SIZE);
- encode_fieldvec(&vec, &mut bytes);
+ encode_fieldvec(&vec, &mut bytes).unwrap();
// Deserialize the type of interest from those bytes.
let value = T::get_decoded_with_param(&(vdaf, agg_param), &bytes).unwrap();
// Round-trip the value back to a vector of bytes.
- let encoded = value.get_encoded();
+ let encoded = value.get_encoded().unwrap();
assert_eq!(encoded, bytes);
}
@@ -741,6 +737,7 @@ mod tests {
}
#[cfg(feature = "test-util")]
+#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
pub mod dummy;
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
#[cfg_attr(
@@ -748,10 +745,14 @@ pub mod dummy;
doc(cfg(all(feature = "crypto-dependencies", feature = "experimental")))
)]
pub mod poplar1;
-#[cfg(feature = "prio2")]
-#[cfg_attr(docsrs, doc(cfg(feature = "prio2")))]
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(feature = "crypto-dependencies", feature = "experimental")))
+)]
pub mod prio2;
pub mod prio3;
-#[cfg(test)]
-mod prio3_test;
+#[cfg(any(test, feature = "test-util"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
+pub mod prio3_test;
pub mod xof;
diff --git a/third_party/rust/prio/src/vdaf/dummy.rs b/third_party/rust/prio/src/vdaf/dummy.rs
index 507e7916bb..2bb0f96b8a 100644
--- a/third_party/rust/prio/src/vdaf/dummy.rs
+++ b/third_party/rust/prio/src/vdaf/dummy.rs
@@ -12,6 +12,9 @@ use crate::{
use rand::random;
use std::{fmt::Debug, io::Cursor, sync::Arc};
+/// The Dummy VDAF does summation modulus 256 so we can predict aggregation results.
+const MODULUS: u64 = u8::MAX as u64 + 1;
+
type ArcPrepInitFn =
Arc<dyn Fn(&AggregationParam) -> Result<(), VdafError> + 'static + Send + Sync>;
type ArcPrepStepFn = Arc<
@@ -49,7 +52,9 @@ impl Vdaf {
move |state| -> Result<PrepareTransition<Self, 0, 16>, VdafError> {
let new_round = state.current_round + 1;
if new_round == rounds {
- Ok(PrepareTransition::Finish(OutputShare(state.input_share)))
+ Ok(PrepareTransition::Finish(OutputShare(u64::from(
+ state.input_share,
+ ))))
} else {
Ok(PrepareTransition::Continue(
PrepareState {
@@ -76,7 +81,7 @@ impl Vdaf {
self
}
- /// Provide an alternate implementation of [`vdaf::Aggregator::prepare_step`].
+ /// Provide an alternate implementation of [`vdaf::Aggregator::prepare_next`].
pub fn with_prep_step_fn<
F: Fn(&PrepareState) -> Result<PrepareTransition<Self, 0, 16>, VdafError>,
>(
@@ -98,16 +103,18 @@ impl Default for Vdaf {
}
impl vdaf::Vdaf for Vdaf {
- const ID: u32 = 0xFFFF0000;
-
type Measurement = u8;
- type AggregateResult = u8;
+ type AggregateResult = u64;
type AggregationParam = AggregationParam;
type PublicShare = ();
type InputShare = InputShare;
type OutputShare = OutputShare;
type AggregateShare = AggregateShare;
+ fn algorithm_id(&self) -> u32 {
+ 0xFFFF0000
+ }
+
fn num_aggregators(&self) -> usize {
2
}
@@ -155,7 +162,7 @@ impl vdaf::Aggregator<0, 16> for Vdaf {
fn aggregate<M: IntoIterator<Item = Self::OutputShare>>(
&self,
- _: &Self::AggregationParam,
+ _aggregation_param: &Self::AggregationParam,
output_shares: M,
) -> Result<Self::AggregateShare, VdafError> {
let mut aggregate_share = AggregateShare(0);
@@ -184,12 +191,28 @@ impl vdaf::Client<16> for Vdaf {
}
}
+impl vdaf::Collector for Vdaf {
+ fn unshard<M: IntoIterator<Item = Self::AggregateShare>>(
+ &self,
+ aggregation_param: &Self::AggregationParam,
+ agg_shares: M,
+ _num_measurements: usize,
+ ) -> Result<Self::AggregateResult, VdafError> {
+ Ok(agg_shares
+ .into_iter()
+ .fold(0, |acc, share| (acc + share.0) % MODULUS)
+ // Sum in the aggregation parameter so that collections over the same measurements with
+ // varying parameters will yield predictable but distinct results.
+ + u64::from(aggregation_param.0))
+ }
+}
+
/// A dummy input share.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct InputShare(pub u8);
impl Encode for InputShare {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
self.0.encode(bytes)
}
@@ -209,7 +232,7 @@ impl Decode for InputShare {
pub struct AggregationParam(pub u8);
impl Encode for AggregationParam {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
self.0.encode(bytes)
}
@@ -226,17 +249,17 @@ impl Decode for AggregationParam {
/// Dummy output share.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct OutputShare(pub u8);
+pub struct OutputShare(pub u64);
impl Decode for OutputShare {
fn decode(bytes: &mut Cursor<&[u8]>) -> Result<Self, CodecError> {
- Ok(Self(u8::decode(bytes)?))
+ Ok(Self(u64::decode(bytes)?))
}
}
impl Encode for OutputShare {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.0.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.0.encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -252,9 +275,9 @@ pub struct PrepareState {
}
impl Encode for PrepareState {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.input_share.encode(bytes);
- self.current_round.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.input_share.encode(bytes)?;
+ self.current_round.encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -282,31 +305,30 @@ impl Aggregatable for AggregateShare {
type OutputShare = OutputShare;
fn merge(&mut self, other: &Self) -> Result<(), VdafError> {
- self.0 += other.0;
+ self.0 = (self.0 + other.0) % MODULUS;
Ok(())
}
fn accumulate(&mut self, out_share: &Self::OutputShare) -> Result<(), VdafError> {
- self.0 += u64::from(out_share.0);
+ self.0 = (self.0 + out_share.0) % MODULUS;
Ok(())
}
}
impl From<OutputShare> for AggregateShare {
fn from(out_share: OutputShare) -> Self {
- Self(u64::from(out_share.0))
+ Self(out_share.0)
}
}
impl Decode for AggregateShare {
fn decode(bytes: &mut Cursor<&[u8]>) -> Result<Self, CodecError> {
- let val = u64::decode(bytes)?;
- Ok(Self(val))
+ Ok(Self(u64::decode(bytes)?))
}
}
impl Encode for AggregateShare {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
self.0.encode(bytes)
}
@@ -314,3 +336,86 @@ impl Encode for AggregateShare {
self.0.encoded_len()
}
}
+
+/// Returns the aggregate result that the dummy VDAF would compute over the provided measurements,
+/// for the provided aggregation parameter.
+pub fn expected_aggregate_result<M>(aggregation_parameter: u8, measurements: M) -> u64
+where
+ M: IntoIterator<Item = u8>,
+{
+ (measurements.into_iter().map(u64::from).sum::<u64>()) % MODULUS
+ + u64::from(aggregation_parameter)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::vdaf::{test_utils::run_vdaf_sharded, Client};
+ use rand::prelude::*;
+
+ fn run_test(rounds: u32, aggregation_parameter: u8) {
+ let vdaf = Vdaf::new(rounds);
+ let mut verify_key = [0; 0];
+ thread_rng().fill(&mut verify_key[..]);
+ let measurements = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
+
+ let mut sharded_measurements = Vec::new();
+ for measurement in measurements {
+ let nonce = thread_rng().gen();
+ let (public_share, input_shares) = vdaf.shard(&measurement, &nonce).unwrap();
+
+ sharded_measurements.push((public_share, nonce, input_shares));
+ }
+
+ let result = run_vdaf_sharded(
+ &vdaf,
+ &AggregationParam(aggregation_parameter),
+ sharded_measurements.clone(),
+ )
+ .unwrap();
+ assert_eq!(
+ result,
+ expected_aggregate_result(aggregation_parameter, measurements)
+ );
+ }
+
+ #[test]
+ fn single_round_agg_param_10() {
+ run_test(1, 10)
+ }
+
+ #[test]
+ fn single_round_agg_param_20() {
+ run_test(1, 20)
+ }
+
+ #[test]
+ fn single_round_agg_param_32() {
+ run_test(1, 32)
+ }
+
+ #[test]
+ fn single_round_agg_param_u8_max() {
+ run_test(1, u8::MAX)
+ }
+
+ #[test]
+ fn two_round_agg_param_10() {
+ run_test(2, 10)
+ }
+
+ #[test]
+ fn two_round_agg_param_20() {
+ run_test(2, 20)
+ }
+
+ #[test]
+ fn two_round_agg_param_32() {
+ run_test(2, 32)
+ }
+
+ #[test]
+ fn two_round_agg_param_u8_max() {
+ run_test(2, u8::MAX)
+ }
+}
diff --git a/third_party/rust/prio/src/vdaf/poplar1.rs b/third_party/rust/prio/src/vdaf/poplar1.rs
index e8591f2049..514ed39069 100644
--- a/third_party/rust/prio/src/vdaf/poplar1.rs
+++ b/third_party/rust/prio/src/vdaf/poplar1.rs
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MPL-2.0
-//! Implementation of Poplar1 as specified in [[draft-irtf-cfrg-vdaf-07]].
+//! Implementation of Poplar1 as specified in [[draft-irtf-cfrg-vdaf-08]].
//!
-//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
use crate::{
codec::{CodecError, Decode, Encode, ParameterizedDecode},
@@ -10,7 +10,7 @@ use crate::{
idpf::{Idpf, IdpfInput, IdpfOutputShare, IdpfPublicShare, IdpfValue, RingBufferCache},
prng::Prng,
vdaf::{
- xof::{Seed, Xof, XofShake128},
+ xof::{Seed, Xof, XofTurboShake128},
Aggregatable, Aggregator, Client, Collector, PrepareTransition, Vdaf, VdafError,
},
};
@@ -34,9 +34,9 @@ const DST_VERIFY_RANDOMNESS: u16 = 4;
impl<P, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
/// Create an instance of [`Poplar1`]. The caller provides the bit length of each
- /// measurement (`BITS` as defined in the [[draft-irtf-cfrg-vdaf-07]]).
+ /// measurement (`BITS` as defined in [[draft-irtf-cfrg-vdaf-08]]).
///
- /// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+ /// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
pub fn new(bits: usize) -> Self {
Self {
bits,
@@ -45,12 +45,12 @@ impl<P, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
}
}
-impl Poplar1<XofShake128, 16> {
- /// Create an instance of [`Poplar1`] using [`XofShake128`]. The caller provides the bit length of
- /// each measurement (`BITS` as defined in the [[draft-irtf-cfrg-vdaf-07]]).
+impl Poplar1<XofTurboShake128, 16> {
+ /// Create an instance of [`Poplar1`] using [`XofTurboShake128`]. The caller provides the bit length of
+ /// each measurement (`BITS` as defined in [[draft-irtf-cfrg-vdaf-08]]).
///
- /// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
- pub fn new_shake128(bits: usize) -> Self {
+ /// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
+ pub fn new_turboshake128(bits: usize) -> Self {
Poplar1::new(bits)
}
}
@@ -65,6 +65,7 @@ pub struct Poplar1<P, const SEED_SIZE: usize> {
impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
/// Construct a `Prng` with the given seed and info-string suffix.
fn init_prng<I, B, F>(
+ &self,
seed: &[u8; SEED_SIZE],
usage: u16,
binder_chunks: I,
@@ -75,7 +76,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
P: Xof<SEED_SIZE>,
F: FieldElement,
{
- let mut xof = P::init(seed, &Self::domain_separation_tag(usage));
+ let mut xof = P::init(seed, &self.domain_separation_tag(usage));
for binder_chunk in binder_chunks.into_iter() {
xof.update(binder_chunk.as_ref());
}
@@ -156,15 +157,15 @@ impl<const SEED_SIZE: usize> ConstantTimeEq for Poplar1InputShare<SEED_SIZE> {
}
impl<const SEED_SIZE: usize> Encode for Poplar1InputShare<SEED_SIZE> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.idpf_key.encode(bytes);
- self.corr_seed.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.idpf_key.encode(bytes)?;
+ self.corr_seed.encode(bytes)?;
for corr in self.corr_inner.iter() {
- corr[0].encode(bytes);
- corr[1].encode(bytes);
+ corr[0].encode(bytes)?;
+ corr[1].encode(bytes)?;
}
- self.corr_leaf[0].encode(bytes);
- self.corr_leaf[1].encode(bytes);
+ self.corr_leaf[0].encode(bytes)?;
+ self.corr_leaf[1].encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -219,7 +220,7 @@ impl ConstantTimeEq for Poplar1PrepareState {
}
impl Encode for Poplar1PrepareState {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
self.0.encode(bytes)
}
@@ -268,15 +269,15 @@ impl ConstantTimeEq for PrepareStateVariant {
}
impl Encode for PrepareStateVariant {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
match self {
PrepareStateVariant::Inner(prep_state) => {
- 0u8.encode(bytes);
- prep_state.encode(bytes);
+ 0u8.encode(bytes)?;
+ prep_state.encode(bytes)
}
PrepareStateVariant::Leaf(prep_state) => {
- 1u8.encode(bytes);
- prep_state.encode(bytes);
+ 1u8.encode(bytes)?;
+ prep_state.encode(bytes)
}
}
}
@@ -342,16 +343,17 @@ impl<F> Debug for PrepareState<F> {
}
impl<F: FieldElement> Encode for PrepareState<F> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.sketch.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.sketch.encode(bytes)?;
// `expect` safety: output_share's length is the same as the number of prefixes; the number
// of prefixes is capped at 2^32-1.
u32::try_from(self.output_share.len())
.expect("Couldn't convert output_share length to u32")
- .encode(bytes);
+ .encode(bytes)?;
for elem in &self.output_share {
- elem.encode(bytes);
+ elem.encode(bytes)?;
}
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -430,14 +432,14 @@ impl<F: ConstantTimeEq> ConstantTimeEq for SketchState<F> {
}
impl<F: FieldElement> Encode for SketchState<F> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
match self {
SketchState::RoundOne {
A_share, B_share, ..
} => {
- 0u8.encode(bytes);
- A_share.encode(bytes);
- B_share.encode(bytes);
+ 0u8.encode(bytes)?;
+ A_share.encode(bytes)?;
+ B_share.encode(bytes)
}
SketchState::RoundTwo => 1u8.encode(bytes),
}
@@ -519,19 +521,19 @@ enum PrepareMessageVariant {
}
impl Encode for Poplar1PrepareMessage {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
match self.0 {
PrepareMessageVariant::SketchInner(vec) => {
- vec[0].encode(bytes);
- vec[1].encode(bytes);
- vec[2].encode(bytes);
+ vec[0].encode(bytes)?;
+ vec[1].encode(bytes)?;
+ vec[2].encode(bytes)
}
PrepareMessageVariant::SketchLeaf(vec) => {
- vec[0].encode(bytes);
- vec[1].encode(bytes);
- vec[2].encode(bytes);
+ vec[0].encode(bytes)?;
+ vec[1].encode(bytes)?;
+ vec[2].encode(bytes)
}
- PrepareMessageVariant::Done => (),
+ PrepareMessageVariant::Done => Ok(()),
}
}
@@ -614,17 +616,19 @@ impl ConstantTimeEq for Poplar1FieldVec {
}
impl Encode for Poplar1FieldVec {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
match self {
Self::Inner(ref data) => {
for elem in data {
- elem.encode(bytes);
+ elem.encode(bytes)?;
}
+ Ok(())
}
Self::Leaf(ref data) => {
for elem in data {
- elem.encode(bytes);
+ elem.encode(bytes)?;
}
+ Ok(())
}
}
}
@@ -769,11 +773,11 @@ impl Poplar1AggregationParam {
}
impl Encode for Poplar1AggregationParam {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
// Okay to unwrap because `try_from_prefixes()` checks this conversion succeeds.
let prefix_count = u32::try_from(self.prefixes.len()).unwrap();
- self.level.encode(bytes);
- prefix_count.encode(bytes);
+ self.level.encode(bytes)?;
+ prefix_count.encode(bytes)?;
// The encoding of the prefixes is defined by treating the IDPF indices as integers,
// shifting and ORing them together, and encoding the resulting arbitrary precision integer
@@ -799,6 +803,7 @@ impl Encode for Poplar1AggregationParam {
let mut packed = packed.into_vec();
packed.reverse();
bytes.append(&mut packed);
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -839,7 +844,6 @@ impl Decode for Poplar1AggregationParam {
}
impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Vdaf for Poplar1<P, SEED_SIZE> {
- const ID: u32 = 0x00001000;
type Measurement = IdpfInput;
type AggregateResult = Vec<u64>;
type AggregationParam = Poplar1AggregationParam;
@@ -848,6 +852,10 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Vdaf for Poplar1<P, SEED_SIZE> {
type OutputShare = Poplar1FieldVec;
type AggregateShare = Poplar1FieldVec;
+ fn algorithm_id(&self) -> u32 {
+ 0x00001000
+ }
+
fn num_aggregators(&self) -> usize {
2
}
@@ -870,7 +878,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
// Generate the authenticator for each inner level of the IDPF tree.
let mut prng =
- Self::init_prng::<_, _, Field64>(&poplar_random[2], DST_SHARD_RANDOMNESS, [&[]]);
+ self.init_prng::<_, _, Field64>(&poplar_random[2], DST_SHARD_RANDOMNESS, [nonce]);
let auth_inner: Vec<Field64> = (0..self.bits - 1).map(|_| prng.get()).collect();
// Generate the authenticator for the last level of the IDPF tree (i.e., the leaves).
@@ -900,12 +908,12 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
let corr_seed_0 = &poplar_random[0];
let corr_seed_1 = &poplar_random[1];
let mut prng = prng.into_new_field::<Field64>();
- let mut corr_prng_0 = Self::init_prng::<_, _, Field64>(
+ let mut corr_prng_0 = self.init_prng::<_, _, Field64>(
corr_seed_0,
DST_CORR_INNER,
[[0].as_slice(), nonce.as_slice()],
);
- let mut corr_prng_1 = Self::init_prng::<_, _, Field64>(
+ let mut corr_prng_1 = self.init_prng::<_, _, Field64>(
corr_seed_1,
DST_CORR_INNER,
[[1].as_slice(), nonce.as_slice()],
@@ -921,12 +929,12 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
// Generate the correlated randomness for the leaf nodes.
let mut prng = prng.into_new_field::<Field255>();
- let mut corr_prng_0 = Self::init_prng::<_, _, Field255>(
+ let mut corr_prng_0 = self.init_prng::<_, _, Field255>(
corr_seed_0,
DST_CORR_LEAF,
[[0].as_slice(), nonce.as_slice()],
);
- let mut corr_prng_1 = Self::init_prng::<_, _, Field255>(
+ let mut corr_prng_1 = self.init_prng::<_, _, Field255>(
corr_seed_1,
DST_CORR_LEAF,
[[1].as_slice(), nonce.as_slice()],
@@ -952,6 +960,60 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
],
))
}
+
+ /// Evaluate the IDPF at the given prefixes and compute the Aggregator's share of the sketch.
+ #[allow(clippy::too_many_arguments)]
+ fn eval_and_sketch<F>(
+ &self,
+ verify_key: &[u8; SEED_SIZE],
+ agg_id: usize,
+ nonce: &[u8; 16],
+ agg_param: &Poplar1AggregationParam,
+ public_share: &Poplar1PublicShare,
+ idpf_key: &Seed<16>,
+ corr_prng: &mut Prng<F, P::SeedStream>,
+ ) -> Result<(Vec<F>, Vec<F>), VdafError>
+ where
+ P: Xof<SEED_SIZE>,
+ F: FieldElement,
+ Poplar1IdpfValue<F>:
+ From<IdpfOutputShare<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>>,
+ {
+ let mut verify_prng = self.init_prng(
+ verify_key,
+ DST_VERIFY_RANDOMNESS,
+ [nonce.as_slice(), agg_param.level.to_be_bytes().as_slice()],
+ );
+
+ let mut out_share = Vec::with_capacity(agg_param.prefixes.len());
+ let mut sketch_share = vec![
+ corr_prng.get(), // a_share
+ corr_prng.get(), // b_share
+ corr_prng.get(), // c_share
+ ];
+
+ let mut idpf_eval_cache = RingBufferCache::new(agg_param.prefixes.len());
+ let idpf = Idpf::<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>::new((), ());
+ for prefix in agg_param.prefixes.iter() {
+ let share = Poplar1IdpfValue::<F>::from(idpf.eval(
+ agg_id,
+ public_share,
+ idpf_key,
+ prefix,
+ nonce,
+ &mut idpf_eval_cache,
+ )?);
+
+ let r = verify_prng.get();
+ let checked_data_share = share.0[0] * r;
+ sketch_share[0] += checked_data_share;
+ sketch_share[1] += checked_data_share * r;
+ sketch_share[2] += share.0[1] * r;
+ out_share.push(share.0[0]);
+ }
+
+ Ok((out_share, sketch_share))
+ }
}
impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Client<16> for Poplar1<P, SEED_SIZE> {
@@ -1000,7 +1062,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Aggregator<SEED_SIZE, 16>
};
if usize::from(agg_param.level) < self.bits - 1 {
- let mut corr_prng = Self::init_prng::<_, _, Field64>(
+ let mut corr_prng = self.init_prng::<_, _, Field64>(
input_share.corr_seed.as_ref(),
DST_CORR_INNER,
[[agg_id as u8].as_slice(), nonce.as_slice()],
@@ -1011,7 +1073,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Aggregator<SEED_SIZE, 16>
corr_prng.get();
}
- let (output_share, sketch_share) = eval_and_sketch::<P, Field64, SEED_SIZE>(
+ let (output_share, sketch_share) = self.eval_and_sketch::<Field64>(
verify_key,
agg_id,
nonce,
@@ -1033,13 +1095,13 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Aggregator<SEED_SIZE, 16>
Poplar1FieldVec::Inner(sketch_share),
))
} else {
- let corr_prng = Self::init_prng::<_, _, Field255>(
+ let corr_prng = self.init_prng::<_, _, Field255>(
input_share.corr_seed.as_ref(),
DST_CORR_LEAF,
[[agg_id as u8].as_slice(), nonce.as_slice()],
);
- let (output_share, sketch_share) = eval_and_sketch::<P, Field255, SEED_SIZE>(
+ let (output_share, sketch_share) = self.eval_and_sketch::<Field255>(
verify_key,
agg_id,
nonce,
@@ -1257,59 +1319,6 @@ fn compute_next_corr_shares<F: FieldElement + From<u64>, S: RngCore>(
(corr_0, corr_1)
}
-/// Evaluate the IDPF at the given prefixes and compute the Aggregator's share of the sketch.
-fn eval_and_sketch<P, F, const SEED_SIZE: usize>(
- verify_key: &[u8; SEED_SIZE],
- agg_id: usize,
- nonce: &[u8; 16],
- agg_param: &Poplar1AggregationParam,
- public_share: &Poplar1PublicShare,
- idpf_key: &Seed<16>,
- corr_prng: &mut Prng<F, P::SeedStream>,
-) -> Result<(Vec<F>, Vec<F>), VdafError>
-where
- P: Xof<SEED_SIZE>,
- F: FieldElement,
- Poplar1IdpfValue<F>:
- From<IdpfOutputShare<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>>,
-{
- // TODO(cjpatton) spec: Consider not encoding the prefixes here.
- let mut verify_prng = Poplar1::<P, SEED_SIZE>::init_prng(
- verify_key,
- DST_VERIFY_RANDOMNESS,
- [nonce.as_slice(), agg_param.level.to_be_bytes().as_slice()],
- );
-
- let mut out_share = Vec::with_capacity(agg_param.prefixes.len());
- let mut sketch_share = vec![
- corr_prng.get(), // a_share
- corr_prng.get(), // b_share
- corr_prng.get(), // c_share
- ];
-
- let mut idpf_eval_cache = RingBufferCache::new(agg_param.prefixes.len());
- let idpf = Idpf::<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>::new((), ());
- for prefix in agg_param.prefixes.iter() {
- let share = Poplar1IdpfValue::<F>::from(idpf.eval(
- agg_id,
- public_share,
- idpf_key,
- prefix,
- nonce,
- &mut idpf_eval_cache,
- )?);
-
- let r = verify_prng.get();
- let checked_data_share = share.0[0] * r;
- sketch_share[0] += checked_data_share;
- sketch_share[1] += checked_data_share * r;
- sketch_share[2] += share.0[1] * r;
- out_share.push(share.0[0]);
- }
-
- Ok((out_share, sketch_share))
-}
-
/// Compute the Aggregator's share of the sketch verifier. The shares should sum to zero.
#[allow(non_snake_case)]
fn finish_sketch<F: FieldElement>(
@@ -1447,9 +1456,9 @@ impl<F> Encode for Poplar1IdpfValue<F>
where
F: FieldElement,
{
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.0[0].encode(bytes);
- self.0[1].encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.0[0].encode(bytes)?;
+ self.0[1].encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -1491,7 +1500,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
- use crate::vdaf::{equality_comparison_test, run_vdaf_prepare};
+ use crate::vdaf::{equality_comparison_test, test_utils::run_vdaf_prepare};
use assert_matches::assert_matches;
use rand::prelude::*;
use serde::Deserialize;
@@ -1628,7 +1637,7 @@ mod tests {
#[test]
fn shard_prepare() {
let mut rng = thread_rng();
- let vdaf = Poplar1::new_shake128(64);
+ let vdaf = Poplar1::new_turboshake128(64);
let verify_key = rng.gen();
let input = IdpfInput::from_bytes(b"12341324");
let nonce = rng.gen();
@@ -1672,7 +1681,7 @@ mod tests {
fn heavy_hitters() {
let mut rng = thread_rng();
let verify_key = rng.gen();
- let vdaf = Poplar1::new_shake128(8);
+ let vdaf = Poplar1::new_turboshake128(8);
run_heavy_hitters(
&vdaf,
@@ -1699,7 +1708,7 @@ mod tests {
corr_leaf: [Field255::one(), <Field255 as FieldElement>::zero()],
};
assert_eq!(
- input_share.get_encoded().len(),
+ input_share.get_encoded().unwrap().len(),
input_share.encoded_len().unwrap()
);
@@ -1710,7 +1719,7 @@ mod tests {
Field64::one(),
]));
assert_eq!(
- prep_msg.get_encoded().len(),
+ prep_msg.get_encoded().unwrap().len(),
prep_msg.encoded_len().unwrap()
);
let prep_msg = Poplar1PrepareMessage(PrepareMessageVariant::SketchLeaf([
@@ -1719,24 +1728,24 @@ mod tests {
Field255::one(),
]));
assert_eq!(
- prep_msg.get_encoded().len(),
+ prep_msg.get_encoded().unwrap().len(),
prep_msg.encoded_len().unwrap()
);
let prep_msg = Poplar1PrepareMessage(PrepareMessageVariant::Done);
assert_eq!(
- prep_msg.get_encoded().len(),
+ prep_msg.get_encoded().unwrap().len(),
prep_msg.encoded_len().unwrap()
);
// Field vector variants.
let field_vec = Poplar1FieldVec::Inner(vec![Field64::one(); 23]);
assert_eq!(
- field_vec.get_encoded().len(),
+ field_vec.get_encoded().unwrap().len(),
field_vec.encoded_len().unwrap()
);
let field_vec = Poplar1FieldVec::Leaf(vec![Field255::one(); 23]);
assert_eq!(
- field_vec.get_encoded().len(),
+ field_vec.get_encoded().unwrap().len(),
field_vec.encoded_len().unwrap()
);
@@ -1747,7 +1756,7 @@ mod tests {
]))
.unwrap();
assert_eq!(
- agg_param.get_encoded().len(),
+ agg_param.get_encoded().unwrap().len(),
agg_param.encoded_len().unwrap()
);
let agg_param = Poplar1AggregationParam::try_from_prefixes(Vec::from([
@@ -1756,14 +1765,14 @@ mod tests {
]))
.unwrap();
assert_eq!(
- agg_param.get_encoded().len(),
+ agg_param.get_encoded().unwrap().len(),
agg_param.encoded_len().unwrap()
);
}
#[test]
fn round_trip_prepare_state() {
- let vdaf = Poplar1::new_shake128(1);
+ let vdaf = Poplar1::new_turboshake128(1);
for (agg_id, prep_state) in [
(
0,
@@ -1862,7 +1871,7 @@ mod tests {
})),
),
] {
- let encoded_prep_state = prep_state.get_encoded();
+ let encoded_prep_state = prep_state.get_encoded().unwrap();
assert_eq!(prep_state.encoded_len(), Some(encoded_prep_state.len()));
let decoded_prep_state =
Poplar1PrepareState::get_decoded_with_param(&(&vdaf, agg_id), &encoded_prep_state)
@@ -1947,7 +1956,7 @@ mod tests {
),
] {
let agg_param = Poplar1AggregationParam::try_from_prefixes(prefixes).unwrap();
- let encoded = agg_param.get_encoded();
+ let encoded = agg_param.get_encoded().unwrap();
assert_eq!(encoded, reference_encoding);
let decoded = Poplar1AggregationParam::get_decoded(reference_encoding).unwrap();
assert_eq!(decoded, agg_param);
@@ -2037,7 +2046,7 @@ mod tests {
}
// Shard measurement.
- let poplar = Poplar1::new_shake128(test_vector.bits);
+ let poplar = Poplar1::new_turboshake128(test_vector.bits);
let (public_share, input_shares) = poplar
.shard_with_random(&measurement, &nonce, &idpf_random, &poplar_random)
.unwrap();
@@ -2118,14 +2127,17 @@ mod tests {
Poplar1PublicShare::get_decoded_with_param(&poplar, prep.public_share.as_ref())
.unwrap()
);
- assert_eq!(&public_share.get_encoded(), prep.public_share.as_ref());
+ assert_eq!(
+ &public_share.get_encoded().unwrap(),
+ prep.public_share.as_ref()
+ );
assert_eq!(
input_shares[0],
Poplar1InputShare::get_decoded_with_param(&(&poplar, 0), prep.input_shares[0].as_ref())
.unwrap()
);
assert_eq!(
- &input_shares[0].get_encoded(),
+ &input_shares[0].get_encoded().unwrap(),
prep.input_shares[0].as_ref()
);
assert_eq!(
@@ -2134,7 +2146,7 @@ mod tests {
.unwrap()
);
assert_eq!(
- &input_shares[1].get_encoded(),
+ &input_shares[1].get_encoded().unwrap(),
prep.input_shares[1].as_ref()
);
assert_eq!(
@@ -2146,7 +2158,7 @@ mod tests {
.unwrap()
);
assert_eq!(
- &init_prep_share_0.get_encoded(),
+ &init_prep_share_0.get_encoded().unwrap(),
prep.prep_shares[0][0].as_ref()
);
assert_eq!(
@@ -2158,7 +2170,7 @@ mod tests {
.unwrap()
);
assert_eq!(
- &init_prep_share_1.get_encoded(),
+ &init_prep_share_1.get_encoded().unwrap(),
prep.prep_shares[0][1].as_ref()
);
assert_eq!(
@@ -2169,7 +2181,10 @@ mod tests {
)
.unwrap()
);
- assert_eq!(&r1_prep_msg.get_encoded(), prep.prep_messages[0].as_ref());
+ assert_eq!(
+ &r1_prep_msg.get_encoded().unwrap(),
+ prep.prep_messages[0].as_ref()
+ );
assert_eq!(
r1_prep_share_0,
@@ -2180,7 +2195,7 @@ mod tests {
.unwrap()
);
assert_eq!(
- &r1_prep_share_0.get_encoded(),
+ &r1_prep_share_0.get_encoded().unwrap(),
prep.prep_shares[1][0].as_ref()
);
assert_eq!(
@@ -2192,7 +2207,7 @@ mod tests {
.unwrap()
);
assert_eq!(
- &r1_prep_share_1.get_encoded(),
+ &r1_prep_share_1.get_encoded().unwrap(),
prep.prep_shares[1][1].as_ref()
);
assert_eq!(
@@ -2203,7 +2218,10 @@ mod tests {
)
.unwrap()
);
- assert_eq!(&r2_prep_msg.get_encoded(), prep.prep_messages[1].as_ref());
+ assert_eq!(
+ &r2_prep_msg.get_encoded().unwrap(),
+ prep.prep_messages[1].as_ref()
+ );
for (out_share, expected_out_share) in [
(out_share_0, &prep.out_shares[0]),
(out_share_1, &prep.out_shares[1]),
@@ -2212,13 +2230,13 @@ mod tests {
Poplar1FieldVec::Inner(vec) => {
assert_eq!(vec.len(), expected_out_share.len());
for (element, expected) in vec.iter().zip(expected_out_share.iter()) {
- assert_eq!(&element.get_encoded(), expected.as_ref());
+ assert_eq!(&element.get_encoded().unwrap(), expected.as_ref());
}
}
Poplar1FieldVec::Leaf(vec) => {
assert_eq!(vec.len(), expected_out_share.len());
for (element, expected) in vec.iter().zip(expected_out_share.iter()) {
- assert_eq!(&element.get_encoded(), expected.as_ref());
+ assert_eq!(&element.get_encoded().unwrap(), expected.as_ref());
}
}
};
@@ -2233,7 +2251,7 @@ mod tests {
);
assert_eq!(
- &agg_share_0.get_encoded(),
+ &agg_share_0.get_encoded().unwrap(),
test_vector.agg_shares[0].as_ref()
);
assert_eq!(
@@ -2245,7 +2263,7 @@ mod tests {
.unwrap()
);
assert_eq!(
- &agg_share_1.get_encoded(),
+ &agg_share_1.get_encoded().unwrap(),
test_vector.agg_shares[1].as_ref()
);
assert_eq!(agg_result, test_vector.agg_result);
@@ -2253,22 +2271,22 @@ mod tests {
#[test]
fn test_vec_poplar1_0() {
- check_test_vec(include_str!("test_vec/07/Poplar1_0.json"));
+ check_test_vec(include_str!("test_vec/08/Poplar1_0.json"));
}
#[test]
fn test_vec_poplar1_1() {
- check_test_vec(include_str!("test_vec/07/Poplar1_1.json"));
+ check_test_vec(include_str!("test_vec/08/Poplar1_1.json"));
}
#[test]
fn test_vec_poplar1_2() {
- check_test_vec(include_str!("test_vec/07/Poplar1_2.json"));
+ check_test_vec(include_str!("test_vec/08/Poplar1_2.json"));
}
#[test]
fn test_vec_poplar1_3() {
- check_test_vec(include_str!("test_vec/07/Poplar1_3.json"));
+ check_test_vec(include_str!("test_vec/08/Poplar1_3.json"));
}
#[test]
diff --git a/third_party/rust/prio/src/vdaf/prio2.rs b/third_party/rust/prio/src/vdaf/prio2.rs
index 4669c47d00..ba725d90d7 100644
--- a/third_party/rust/prio/src/vdaf/prio2.rs
+++ b/third_party/rust/prio/src/vdaf/prio2.rs
@@ -88,8 +88,13 @@ impl Prio2 {
)
.map_err(|e| VdafError::Uncategorized(e.to_string()))?;
+ let truncated_share = match input_share {
+ Share::Leader(data) => Share::Leader(data[..self.input_len].to_vec()),
+ Share::Helper(seed) => Share::Helper(seed.clone()),
+ };
+
Ok((
- Prio2PrepareState(input_share.truncated(self.input_len)),
+ Prio2PrepareState(truncated_share),
Prio2PrepareShare(verifier_share),
))
}
@@ -117,7 +122,6 @@ impl Prio2 {
}
impl Vdaf for Prio2 {
- const ID: u32 = 0xFFFF0000;
type Measurement = Vec<u32>;
type AggregateResult = Vec<u32>;
type AggregationParam = ();
@@ -126,6 +130,10 @@ impl Vdaf for Prio2 {
type OutputShare = OutputShare<FieldPrio2>;
type AggregateShare = AggregateShare<FieldPrio2>;
+ fn algorithm_id(&self) -> u32 {
+ 0xFFFF0000
+ }
+
fn num_aggregators(&self) -> usize {
// Prio2 can easily be extended to support more than two Aggregators.
2
@@ -184,8 +192,8 @@ impl ConstantTimeEq for Prio2PrepareState {
}
impl Encode for Prio2PrepareState {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.0.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.0.encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -213,10 +221,10 @@ impl<'a> ParameterizedDecode<(&'a Prio2, usize)> for Prio2PrepareState {
pub struct Prio2PrepareShare(v2_server::VerificationMessage<FieldPrio2>);
impl Encode for Prio2PrepareShare {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.0.f_r.encode(bytes);
- self.0.g_r.encode(bytes);
- self.0.h_r.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.0.f_r.encode(bytes)?;
+ self.0.g_r.encode(bytes)?;
+ self.0.h_r.encode(bytes)
}
fn encoded_len(&self) -> Option<usize> {
@@ -388,7 +396,7 @@ mod tests {
use super::*;
use crate::vdaf::{
equality_comparison_test, fieldvec_roundtrip_test, prio2::test_vector::Priov2TestVector,
- run_vdaf,
+ test_utils::run_vdaf,
};
use assert_matches::assert_matches;
use rand::prelude::*;
@@ -434,7 +442,7 @@ mod tests {
)
.unwrap();
- let encoded_prepare_state = prepare_state.get_encoded();
+ let encoded_prepare_state = prepare_state.get_encoded().unwrap();
let decoded_prepare_state = Prio2PrepareState::get_decoded_with_param(
&(&prio2, agg_id),
&encoded_prepare_state,
@@ -446,7 +454,7 @@ mod tests {
encoded_prepare_state.len()
);
- let encoded_prepare_share = prepare_share.get_encoded();
+ let encoded_prepare_share = prepare_share.get_encoded().unwrap();
let decoded_prepare_share =
Prio2PrepareShare::get_decoded_with_param(&prepare_state, &encoded_prepare_share)
.expect("failed to decode prepare share");
diff --git a/third_party/rust/prio/src/vdaf/prio2/client.rs b/third_party/rust/prio/src/vdaf/prio2/client.rs
index dbce39ee3f..9515601d8a 100644
--- a/third_party/rust/prio/src/vdaf/prio2/client.rs
+++ b/third_party/rust/prio/src/vdaf/prio2/client.rs
@@ -4,10 +4,14 @@
//! Primitives for the Prio2 client.
use crate::{
- field::{FftFriendlyFieldElement, FieldError},
+ codec::CodecError,
+ field::FftFriendlyFieldElement,
polynomial::{poly_fft, PolyAuxMemory},
prng::{Prng, PrngError},
- vdaf::{xof::SeedStreamAes128, VdafError},
+ vdaf::{
+ xof::{Seed, SeedStreamAes128},
+ VdafError,
+ },
};
use std::convert::TryFrom;
@@ -32,9 +36,9 @@ pub enum SerializeError {
/// Emitted by `unpack_proof[_mut]` if the serialized share+proof has the wrong length
#[error("serialized input has wrong length")]
UnpackInputSizeMismatch,
- /// Finite field operation error.
- #[error("finite field operation error")]
- Field(#[from] FieldError),
+ /// Codec error.
+ #[error(transparent)]
+ Codec(#[from] CodecError),
}
#[derive(Debug)]
@@ -63,7 +67,7 @@ impl<F: FftFriendlyFieldElement> ClientMemory<F> {
}
Ok(Self {
- prng: Prng::new()?,
+ prng: Prng::from_prio2_seed(Seed::<32>::generate()?.as_ref()),
points_f: vec![F::zero(); n],
points_g: vec![F::zero(); n],
evals_f: vec![F::zero(); 2 * n],
diff --git a/third_party/rust/prio/src/vdaf/prio2/server.rs b/third_party/rust/prio/src/vdaf/prio2/server.rs
index 11c161babf..9d2871c867 100644
--- a/third_party/rust/prio/src/vdaf/prio2/server.rs
+++ b/third_party/rust/prio/src/vdaf/prio2/server.rs
@@ -101,9 +101,13 @@ pub(crate) fn is_valid_share<F: FftFriendlyFieldElement>(
#[cfg(test)]
mod test_util {
use crate::{
+ codec::ParameterizedDecode,
field::{merge_vector, FftFriendlyFieldElement},
prng::Prng,
- vdaf::prio2::client::proof_length,
+ vdaf::{
+ prio2::client::{proof_length, SerializeError},
+ Share, ShareDecodingParameter,
+ },
};
use super::{generate_verification_message, is_valid_share, ServerError, VerificationMessage};
@@ -133,17 +137,17 @@ mod test_util {
/// Deserialize
fn deserialize_share(&self, share: &[u8]) -> Result<Vec<F>, ServerError> {
let len = proof_length(self.dimension);
- Ok(if self.is_first_server {
- F::byte_slice_into_vec(share)?
+ let decoding_parameter = if self.is_first_server {
+ ShareDecodingParameter::Leader(len)
} else {
- if share.len() != 32 {
- return Err(ServerError::ShareLength);
- }
-
- Prng::from_prio2_seed(&share.try_into().unwrap())
- .take(len)
- .collect()
- })
+ ShareDecodingParameter::Helper
+ };
+ let decoded_share = Share::get_decoded_with_param(&decoding_parameter, share)
+ .map_err(SerializeError::from)?;
+ match decoded_share {
+ Share::Leader(vec) => Ok(vec),
+ Share::Helper(seed) => Ok(Prng::from_prio2_seed(&seed.0).take(len).collect()),
+ }
}
/// Generate verification message from an encrypted share
@@ -194,14 +198,19 @@ mod test_util {
mod tests {
use super::*;
use crate::{
- codec::Encode,
+ codec::{Encode, ParameterizedDecode},
field::{FieldElement, FieldPrio2},
prng::Prng,
vdaf::{
- prio2::{client::unpack_proof_mut, server::test_util::Server, Prio2},
- Client,
+ prio2::{
+ client::{proof_length, unpack_proof_mut},
+ server::test_util::Server,
+ Prio2,
+ },
+ Client, Share, ShareDecodingParameter,
},
};
+ use assert_matches::assert_matches;
use rand::{random, Rng};
fn secret_share(share: &mut [FieldPrio2]) -> Vec<FieldPrio2> {
@@ -286,10 +295,13 @@ mod tests {
let vdaf = Prio2::new(dim).unwrap();
let (_, shares) = vdaf.shard(&data, &[0; 16]).unwrap();
- let share1_original = shares[0].get_encoded();
- let share2 = shares[1].get_encoded();
+ let share1_original = shares[0].get_encoded().unwrap();
+ let share2 = shares[1].get_encoded().unwrap();
- let mut share1_field = FieldPrio2::byte_slice_into_vec(&share1_original).unwrap();
+ let mut share1_field: Vec<FieldPrio2> = assert_matches!(
+ Share::get_decoded_with_param(&ShareDecodingParameter::<32>::Leader(proof_length(dim)), &share1_original),
+ Ok(Share::Leader(vec)) => vec
+ );
let unpacked_share1 = unpack_proof_mut(&mut share1_field, dim).unwrap();
let one = FieldPrio2::from(1);
@@ -304,7 +316,9 @@ mod tests {
};
// reserialize altered share1
- let share1_modified = FieldPrio2::slice_into_byte_vec(&share1_field);
+ let share1_modified = Share::<FieldPrio2, 32>::Leader(share1_field)
+ .get_encoded()
+ .unwrap();
let mut prng = Prng::from_prio2_seed(&random());
let eval_at = vdaf.choose_eval_at(&mut prng);
diff --git a/third_party/rust/prio/src/vdaf/prio2/test_vector.rs b/third_party/rust/prio/src/vdaf/prio2/test_vector.rs
index ae2b8b0f9d..114b437b55 100644
--- a/third_party/rust/prio/src/vdaf/prio2/test_vector.rs
+++ b/third_party/rust/prio/src/vdaf/prio2/test_vector.rs
@@ -48,9 +48,16 @@ mod base64 {
//! instead of an array of an array of integers when serializing to JSON.
//
// Thank you, Alice! https://users.rust-lang.org/t/serialize-a-vec-u8-to-json-as-base64/57781/2
- use crate::field::{FieldElement, FieldPrio2};
+ use crate::{
+ codec::ParameterizedDecode,
+ field::{encode_fieldvec, FieldElement, FieldPrio2},
+ vdaf::{Share, ShareDecodingParameter},
+ };
+ use assert_matches::assert_matches;
use base64::{engine::Engine, prelude::BASE64_STANDARD};
- use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
+ use serde::{
+ de::Error as _, ser::Error as _, Deserialize, Deserializer, Serialize, Serializer,
+ };
pub fn serialize_bytes<S: Serializer>(v: &[Vec<u8>], s: S) -> Result<S::Ok, S::Error> {
let base64_vec = v
@@ -63,21 +70,28 @@ mod base64 {
pub fn deserialize_bytes<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<Vec<u8>>, D::Error> {
<Vec<String>>::deserialize(d)?
.iter()
- .map(|s| BASE64_STANDARD.decode(s.as_bytes()).map_err(Error::custom))
+ .map(|s| {
+ BASE64_STANDARD
+ .decode(s.as_bytes())
+ .map_err(D::Error::custom)
+ })
.collect()
}
pub fn serialize_field<S: Serializer>(v: &[FieldPrio2], s: S) -> Result<S::Ok, S::Error> {
- String::serialize(
- &BASE64_STANDARD.encode(FieldPrio2::slice_into_byte_vec(v)),
- s,
- )
+ let mut bytes = Vec::new();
+ encode_fieldvec(v, &mut bytes).map_err(S::Error::custom)?;
+ String::serialize(&BASE64_STANDARD.encode(&bytes), s)
}
pub fn deserialize_field<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<FieldPrio2>, D::Error> {
let bytes = BASE64_STANDARD
.decode(String::deserialize(d)?.as_bytes())
- .map_err(Error::custom)?;
- FieldPrio2::byte_slice_into_vec(&bytes).map_err(Error::custom)
+ .map_err(D::Error::custom)?;
+ let decoding_parameter =
+ ShareDecodingParameter::<32>::Leader(bytes.len() / FieldPrio2::ENCODED_SIZE);
+ let share = Share::<FieldPrio2, 32>::get_decoded_with_param(&decoding_parameter, &bytes)
+ .map_err(D::Error::custom)?;
+ assert_matches!(share, Share::Leader(vec) => Ok(vec))
}
}
diff --git a/third_party/rust/prio/src/vdaf/prio3.rs b/third_party/rust/prio/src/vdaf/prio3.rs
index 4a7cdefb84..084f87f411 100644
--- a/third_party/rust/prio/src/vdaf/prio3.rs
+++ b/third_party/rust/prio/src/vdaf/prio3.rs
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
-//! Implementation of the Prio3 VDAF [[draft-irtf-cfrg-vdaf-07]].
+//! Implementation of the Prio3 VDAF [[draft-irtf-cfrg-vdaf-08]].
//!
//! **WARNING:** This code has not undergone significant security analysis. Use at your own risk.
//!
@@ -9,7 +9,7 @@
//! 2019 [[BBCG+19]], that lead to substantial improvements in terms of run time and communication
//! cost. The security of the construction was analyzed in [[DPRS23]].
//!
-//! Prio3 is a transformation of a Fully Linear Proof (FLP) system [[draft-irtf-cfrg-vdaf-07]] into
+//! Prio3 is a transformation of a Fully Linear Proof (FLP) system [[draft-irtf-cfrg-vdaf-08]] into
//! a VDAF. The base type, [`Prio3`], supports a wide variety of aggregation functions, some of
//! which are instantiated here:
//!
@@ -20,14 +20,14 @@
//!
//! Additional types can be constructed from [`Prio3`] as needed.
//!
-//! (*) denotes that the type is specified in [[draft-irtf-cfrg-vdaf-07]].
+//! (*) denotes that the type is specified in [[draft-irtf-cfrg-vdaf-08]].
//!
//! [BBCG+19]: https://ia.cr/2019/188
//! [CGB17]: https://crypto.stanford.edu/prio/
//! [DPRS23]: https://ia.cr/2023/130
-//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
-use super::xof::XofShake128;
+use super::xof::XofTurboShake128;
#[cfg(feature = "experimental")]
use super::AggregatorWithNoise;
use crate::codec::{CodecError, Decode, Encode, ParameterizedDecode};
@@ -72,19 +72,19 @@ const DST_JOINT_RAND_SEED: u16 = 6;
const DST_JOINT_RAND_PART: u16 = 7;
/// The count type. Each measurement is an integer in `[0,2)` and the aggregate result is the sum.
-pub type Prio3Count = Prio3<Count<Field64>, XofShake128, 16>;
+pub type Prio3Count = Prio3<Count<Field64>, XofTurboShake128, 16>;
impl Prio3Count {
/// Construct an instance of Prio3Count with the given number of aggregators.
pub fn new_count(num_aggregators: u8) -> Result<Self, VdafError> {
- Prio3::new(num_aggregators, Count::new())
+ Prio3::new(num_aggregators, 1, 0x00000000, Count::new())
}
}
/// The count-vector type. Each measurement is a vector of integers in `[0,2^bits)` and the
/// aggregate is the element-wise sum.
pub type Prio3SumVec =
- Prio3<SumVec<Field128, ParallelSum<Field128, Mul<Field128>>>, XofShake128, 16>;
+ Prio3<SumVec<Field128, ParallelSum<Field128, Mul<Field128>>>, XofTurboShake128, 16>;
impl Prio3SumVec {
/// Construct an instance of Prio3SumVec with the given number of aggregators. `bits` defines
@@ -96,7 +96,12 @@ impl Prio3SumVec {
len: usize,
chunk_length: usize,
) -> Result<Self, VdafError> {
- Prio3::new(num_aggregators, SumVec::new(bits, len, chunk_length)?)
+ Prio3::new(
+ num_aggregators,
+ 1,
+ 0x00000002,
+ SumVec::new(bits, len, chunk_length)?,
+ )
}
}
@@ -104,8 +109,11 @@ impl Prio3SumVec {
/// time. Note that the improvement is only noticeable for very large input lengths.
#[cfg(feature = "multithreaded")]
#[cfg_attr(docsrs, doc(cfg(feature = "multithreaded")))]
-pub type Prio3SumVecMultithreaded =
- Prio3<SumVec<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>, XofShake128, 16>;
+pub type Prio3SumVecMultithreaded = Prio3<
+ SumVec<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>,
+ XofTurboShake128,
+ 16,
+>;
#[cfg(feature = "multithreaded")]
impl Prio3SumVecMultithreaded {
@@ -118,13 +126,18 @@ impl Prio3SumVecMultithreaded {
len: usize,
chunk_length: usize,
) -> Result<Self, VdafError> {
- Prio3::new(num_aggregators, SumVec::new(bits, len, chunk_length)?)
+ Prio3::new(
+ num_aggregators,
+ 1,
+ 0x00000002,
+ SumVec::new(bits, len, chunk_length)?,
+ )
}
}
/// The sum type. Each measurement is an integer in `[0,2^bits)` for some `0 < bits < 64` and the
/// aggregate is the sum.
-pub type Prio3Sum = Prio3<Sum<Field128>, XofShake128, 16>;
+pub type Prio3Sum = Prio3<Sum<Field128>, XofTurboShake128, 16>;
impl Prio3Sum {
/// Construct an instance of Prio3Sum with the given number of aggregators and required bit
@@ -136,7 +149,7 @@ impl Prio3Sum {
)));
}
- Prio3::new(num_aggregators, Sum::new(bits)?)
+ Prio3::new(num_aggregators, 1, 0x00000001, Sum::new(bits)?)
}
}
@@ -160,7 +173,7 @@ pub type Prio3FixedPointBoundedL2VecSum<Fx> = Prio3<
ParallelSum<Field128, PolyEval<Field128>>,
ParallelSum<Field128, Mul<Field128>>,
>,
- XofShake128,
+ XofTurboShake128,
16,
>;
@@ -173,7 +186,12 @@ impl<Fx: Fixed + CompatibleFloat> Prio3FixedPointBoundedL2VecSum<Fx> {
entries: usize,
) -> Result<Self, VdafError> {
check_num_aggregators(num_aggregators)?;
- Prio3::new(num_aggregators, FixedPointBoundedL2VecSum::new(entries)?)
+ Prio3::new(
+ num_aggregators,
+ 1,
+ 0xFFFF0000,
+ FixedPointBoundedL2VecSum::new(entries)?,
+ )
}
}
@@ -191,7 +209,7 @@ pub type Prio3FixedPointBoundedL2VecSumMultithreaded<Fx> = Prio3<
ParallelSumMultithreaded<Field128, PolyEval<Field128>>,
ParallelSumMultithreaded<Field128, Mul<Field128>>,
>,
- XofShake128,
+ XofTurboShake128,
16,
>;
@@ -204,14 +222,19 @@ impl<Fx: Fixed + CompatibleFloat> Prio3FixedPointBoundedL2VecSumMultithreaded<Fx
entries: usize,
) -> Result<Self, VdafError> {
check_num_aggregators(num_aggregators)?;
- Prio3::new(num_aggregators, FixedPointBoundedL2VecSum::new(entries)?)
+ Prio3::new(
+ num_aggregators,
+ 1,
+ 0xFFFF0000,
+ FixedPointBoundedL2VecSum::new(entries)?,
+ )
}
}
/// The histogram type. Each measurement is an integer in `[0, length)` and the result is a
/// histogram counting the number of occurrences of each measurement.
pub type Prio3Histogram =
- Prio3<Histogram<Field128, ParallelSum<Field128, Mul<Field128>>>, XofShake128, 16>;
+ Prio3<Histogram<Field128, ParallelSum<Field128, Mul<Field128>>>, XofTurboShake128, 16>;
impl Prio3Histogram {
/// Constructs an instance of Prio3Histogram with the given number of aggregators,
@@ -221,7 +244,12 @@ impl Prio3Histogram {
length: usize,
chunk_length: usize,
) -> Result<Self, VdafError> {
- Prio3::new(num_aggregators, Histogram::new(length, chunk_length)?)
+ Prio3::new(
+ num_aggregators,
+ 1,
+ 0x00000003,
+ Histogram::new(length, chunk_length)?,
+ )
}
}
@@ -229,8 +257,11 @@ impl Prio3Histogram {
/// time. Note that this improvement is only noticeable for very large input lengths.
#[cfg(feature = "multithreaded")]
#[cfg_attr(docsrs, doc(cfg(feature = "multithreaded")))]
-pub type Prio3HistogramMultithreaded =
- Prio3<Histogram<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>, XofShake128, 16>;
+pub type Prio3HistogramMultithreaded = Prio3<
+ Histogram<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>,
+ XofTurboShake128,
+ 16,
+>;
#[cfg(feature = "multithreaded")]
impl Prio3HistogramMultithreaded {
@@ -241,13 +272,18 @@ impl Prio3HistogramMultithreaded {
length: usize,
chunk_length: usize,
) -> Result<Self, VdafError> {
- Prio3::new(num_aggregators, Histogram::new(length, chunk_length)?)
+ Prio3::new(
+ num_aggregators,
+ 1,
+ 0x00000003,
+ Histogram::new(length, chunk_length)?,
+ )
}
}
/// The average type. Each measurement is an integer in `[0,2^bits)` for some `0 < bits < 64` and
/// the aggregate is the arithmetic average.
-pub type Prio3Average = Prio3<Average<Field128>, XofShake128, 16>;
+pub type Prio3Average = Prio3<Average<Field128>, XofTurboShake128, 16>;
impl Prio3Average {
/// Construct an instance of Prio3Average with the given number of aggregators and required bit
@@ -263,6 +299,8 @@ impl Prio3Average {
Ok(Prio3 {
num_aggregators,
+ num_proofs: 1,
+ algorithm_id: 0xFFFF0000,
typ: Average::new(bits)?,
phantom: PhantomData,
})
@@ -277,7 +315,7 @@ impl Prio3Average {
/// - a [`Xof`] for deriving vectors of field elements from seeds.
///
/// New instances can be defined by aliasing the base type. For example, [`Prio3Count`] is an alias
-/// for `Prio3<Count<Field64>, XofShake128, 16>`.
+/// for `Prio3<Count<Field64>, XofTurboShake128, 16>`.
///
/// ```
/// use prio::vdaf::{
@@ -292,7 +330,7 @@ impl Prio3Average {
/// let mut out_shares = vec![vec![]; num_shares.into()];
/// let mut rng = thread_rng();
/// let verify_key = rng.gen();
-/// let measurements = [0, 1, 1, 1, 0];
+/// let measurements = [false, true, true, true, false];
/// for measurement in measurements {
/// // Shard
/// let nonce = rng.gen::<[u8; 16]>();
@@ -316,7 +354,7 @@ impl Prio3Average {
/// let prep_msg = vdaf.prepare_shares_to_prepare_message(&(), prep_shares).unwrap();
///
/// for (agg_id, state) in prep_states.into_iter().enumerate() {
-/// let out_share = match vdaf.prepare_step(state, prep_msg.clone()).unwrap() {
+/// let out_share = match vdaf.prepare_next(state, prep_msg.clone()).unwrap() {
/// PrepareTransition::Finish(out_share) => out_share,
/// _ => panic!("unexpected transition"),
/// };
@@ -339,6 +377,8 @@ where
P: Xof<SEED_SIZE>,
{
num_aggregators: u8,
+ num_proofs: u8,
+ algorithm_id: u32,
typ: T,
phantom: PhantomData<P>,
}
@@ -348,12 +388,25 @@ where
T: Type,
P: Xof<SEED_SIZE>,
{
- /// Construct an instance of this Prio3 VDAF with the given number of aggregators and the
- /// underlying type.
- pub fn new(num_aggregators: u8, typ: T) -> Result<Self, VdafError> {
+ /// Construct an instance of this Prio3 VDAF with the given number of aggregators, number of
+ /// proofs to generate and verify, the algorithm ID, and the underlying type.
+ pub fn new(
+ num_aggregators: u8,
+ num_proofs: u8,
+ algorithm_id: u32,
+ typ: T,
+ ) -> Result<Self, VdafError> {
check_num_aggregators(num_aggregators)?;
+ if num_proofs == 0 {
+ return Err(VdafError::Uncategorized(
+ "num_proofs must be at least 1".to_string(),
+ ));
+ }
+
Ok(Self {
num_aggregators,
+ num_proofs,
+ algorithm_id,
typ,
phantom: PhantomData,
})
@@ -369,19 +422,72 @@ where
self.typ.verifier_len()
}
+ #[inline]
+ fn num_proofs(&self) -> usize {
+ self.num_proofs.into()
+ }
+
+ fn derive_prove_rands(&self, prove_rand_seed: &Seed<SEED_SIZE>) -> Vec<T::Field> {
+ P::seed_stream(
+ prove_rand_seed,
+ &self.domain_separation_tag(DST_PROVE_RANDOMNESS),
+ &[self.num_proofs],
+ )
+ .into_field_vec(self.typ.prove_rand_len() * self.num_proofs())
+ }
+
fn derive_joint_rand_seed<'a>(
- parts: impl Iterator<Item = &'a Seed<SEED_SIZE>>,
+ &self,
+ joint_rand_parts: impl Iterator<Item = &'a Seed<SEED_SIZE>>,
) -> Seed<SEED_SIZE> {
let mut xof = P::init(
&[0; SEED_SIZE],
- &Self::domain_separation_tag(DST_JOINT_RAND_SEED),
+ &self.domain_separation_tag(DST_JOINT_RAND_SEED),
);
- for part in parts {
+ for part in joint_rand_parts {
xof.update(part.as_ref());
}
xof.into_seed()
}
+ fn derive_joint_rands<'a>(
+ &self,
+ joint_rand_parts: impl Iterator<Item = &'a Seed<SEED_SIZE>>,
+ ) -> (Seed<SEED_SIZE>, Vec<T::Field>) {
+ let joint_rand_seed = self.derive_joint_rand_seed(joint_rand_parts);
+ let joint_rands = P::seed_stream(
+ &joint_rand_seed,
+ &self.domain_separation_tag(DST_JOINT_RANDOMNESS),
+ &[self.num_proofs],
+ )
+ .into_field_vec(self.typ.joint_rand_len() * self.num_proofs());
+
+ (joint_rand_seed, joint_rands)
+ }
+
+ fn derive_helper_proofs_share(
+ &self,
+ proofs_share_seed: &Seed<SEED_SIZE>,
+ agg_id: u8,
+ ) -> Prng<T::Field, P::SeedStream> {
+ Prng::from_seed_stream(P::seed_stream(
+ proofs_share_seed,
+ &self.domain_separation_tag(DST_PROOF_SHARE),
+ &[self.num_proofs, agg_id],
+ ))
+ }
+
+ fn derive_query_rands(&self, verify_key: &[u8; SEED_SIZE], nonce: &[u8; 16]) -> Vec<T::Field> {
+ let mut xof = P::init(
+ verify_key,
+ &self.domain_separation_tag(DST_QUERY_RANDOMNESS),
+ );
+ xof.update(&[self.num_proofs]);
+ xof.update(nonce);
+ xof.into_seed_stream()
+ .into_field_vec(self.typ.query_rand_len() * self.num_proofs())
+ }
+
fn random_size(&self) -> usize {
if self.typ.joint_rand_len() == 0 {
// Two seeds per helper for measurement and proof shares, plus one seed for proving
@@ -438,42 +544,45 @@ where
let proof_share_seed = random_seeds.next().unwrap().try_into().unwrap();
let measurement_share_prng: Prng<T::Field, _> = Prng::from_seed_stream(P::seed_stream(
&Seed(measurement_share_seed),
- &Self::domain_separation_tag(DST_MEASUREMENT_SHARE),
+ &self.domain_separation_tag(DST_MEASUREMENT_SHARE),
&[agg_id],
));
- let joint_rand_blind =
- if let Some(helper_joint_rand_parts) = helper_joint_rand_parts.as_mut() {
- let joint_rand_blind = random_seeds.next().unwrap().try_into().unwrap();
- let mut joint_rand_part_xof = P::init(
- &joint_rand_blind,
- &Self::domain_separation_tag(DST_JOINT_RAND_PART),
- );
- joint_rand_part_xof.update(&[agg_id]); // Aggregator ID
- joint_rand_part_xof.update(nonce);
-
- let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE);
- for (x, y) in leader_measurement_share
- .iter_mut()
- .zip(measurement_share_prng)
- {
- *x -= y;
- y.encode(&mut encoding_buffer);
- joint_rand_part_xof.update(&encoding_buffer);
- encoding_buffer.clear();
- }
+ let joint_rand_blind = if let Some(helper_joint_rand_parts) =
+ helper_joint_rand_parts.as_mut()
+ {
+ let joint_rand_blind = random_seeds.next().unwrap().try_into().unwrap();
+ let mut joint_rand_part_xof = P::init(
+ &joint_rand_blind,
+ &self.domain_separation_tag(DST_JOINT_RAND_PART),
+ );
+ joint_rand_part_xof.update(&[agg_id]); // Aggregator ID
+ joint_rand_part_xof.update(nonce);
+
+ let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE);
+ for (x, y) in leader_measurement_share
+ .iter_mut()
+ .zip(measurement_share_prng)
+ {
+ *x -= y;
+ y.encode(&mut encoding_buffer).map_err(|_| {
+ VdafError::Uncategorized("failed to encode measurement share".to_string())
+ })?;
+ joint_rand_part_xof.update(&encoding_buffer);
+ encoding_buffer.clear();
+ }
- helper_joint_rand_parts.push(joint_rand_part_xof.into_seed());
+ helper_joint_rand_parts.push(joint_rand_part_xof.into_seed());
- Some(joint_rand_blind)
- } else {
- for (x, y) in leader_measurement_share
- .iter_mut()
- .zip(measurement_share_prng)
- {
- *x -= y;
- }
- None
- };
+ Some(joint_rand_blind)
+ } else {
+ for (x, y) in leader_measurement_share
+ .iter_mut()
+ .zip(measurement_share_prng)
+ {
+ *x -= y;
+ }
+ None
+ };
let helper =
HelperShare::from_seeds(measurement_share_seed, proof_share_seed, joint_rand_blind);
helper_shares.push(helper);
@@ -483,71 +592,75 @@ where
let public_share = Prio3PublicShare {
joint_rand_parts: helper_joint_rand_parts
.as_ref()
- .map(|helper_joint_rand_parts| {
- let leader_blind_bytes = random_seeds.next().unwrap().try_into().unwrap();
- let leader_blind = Seed::from_bytes(leader_blind_bytes);
-
- let mut joint_rand_part_xof = P::init(
- leader_blind.as_ref(),
- &Self::domain_separation_tag(DST_JOINT_RAND_PART),
- );
- joint_rand_part_xof.update(&[0]); // Aggregator ID
- joint_rand_part_xof.update(nonce);
- let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE);
- for x in leader_measurement_share.iter() {
- x.encode(&mut encoding_buffer);
- joint_rand_part_xof.update(&encoding_buffer);
- encoding_buffer.clear();
- }
- leader_blind_opt = Some(leader_blind);
-
- let leader_joint_rand_seed_part = joint_rand_part_xof.into_seed();
-
- let mut vec = Vec::with_capacity(self.num_aggregators());
- vec.push(leader_joint_rand_seed_part);
- vec.extend(helper_joint_rand_parts.iter().cloned());
- vec
- }),
+ .map(
+ |helper_joint_rand_parts| -> Result<Vec<Seed<SEED_SIZE>>, VdafError> {
+ let leader_blind_bytes = random_seeds.next().unwrap().try_into().unwrap();
+ let leader_blind = Seed::from_bytes(leader_blind_bytes);
+
+ let mut joint_rand_part_xof = P::init(
+ leader_blind.as_ref(),
+ &self.domain_separation_tag(DST_JOINT_RAND_PART),
+ );
+ joint_rand_part_xof.update(&[0]); // Aggregator ID
+ joint_rand_part_xof.update(nonce);
+ let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE);
+ for x in leader_measurement_share.iter() {
+ x.encode(&mut encoding_buffer).map_err(|_| {
+ VdafError::Uncategorized(
+ "failed to encode measurement share".to_string(),
+ )
+ })?;
+ joint_rand_part_xof.update(&encoding_buffer);
+ encoding_buffer.clear();
+ }
+ leader_blind_opt = Some(leader_blind);
+
+ let leader_joint_rand_seed_part = joint_rand_part_xof.into_seed();
+
+ let mut vec = Vec::with_capacity(self.num_aggregators());
+ vec.push(leader_joint_rand_seed_part);
+ vec.extend(helper_joint_rand_parts.iter().cloned());
+ Ok(vec)
+ },
+ )
+ .transpose()?,
};
// Compute the joint randomness.
- let joint_rand: Vec<T::Field> = public_share
+ let joint_rands = public_share
.joint_rand_parts
.as_ref()
- .map(|joint_rand_parts| {
- let joint_rand_seed = Self::derive_joint_rand_seed(joint_rand_parts.iter());
- P::seed_stream(
- &joint_rand_seed,
- &Self::domain_separation_tag(DST_JOINT_RANDOMNESS),
- &[],
- )
- .into_field_vec(self.typ.joint_rand_len())
- })
+ .map(|joint_rand_parts| self.derive_joint_rands(joint_rand_parts.iter()).1)
.unwrap_or_default();
- // Run the proof-generation algorithm.
- let prove_rand_seed = random_seeds.next().unwrap().try_into().unwrap();
- let prove_rand = P::seed_stream(
- &Seed::from_bytes(prove_rand_seed),
- &Self::domain_separation_tag(DST_PROVE_RANDOMNESS),
- &[],
- )
- .into_field_vec(self.typ.prove_rand_len());
- let mut leader_proof_share =
- self.typ
- .prove(&encoded_measurement, &prove_rand, &joint_rand)?;
+ // Generate the proofs.
+ let prove_rands = self.derive_prove_rands(&Seed::from_bytes(
+ random_seeds.next().unwrap().try_into().unwrap(),
+ ));
+ let mut leader_proofs_share = Vec::with_capacity(self.typ.proof_len() * self.num_proofs());
+ for p in 0..self.num_proofs() {
+ let prove_rand =
+ &prove_rands[p * self.typ.prove_rand_len()..(p + 1) * self.typ.prove_rand_len()];
+ let joint_rand =
+ &joint_rands[p * self.typ.joint_rand_len()..(p + 1) * self.typ.joint_rand_len()];
+
+ leader_proofs_share.append(&mut self.typ.prove(
+ &encoded_measurement,
+ prove_rand,
+ joint_rand,
+ )?);
+ }
// Generate the proof shares and distribute the joint randomness seed hints.
for (j, helper) in helper_shares.iter_mut().enumerate() {
- let proof_share_prng: Prng<T::Field, _> = Prng::from_seed_stream(P::seed_stream(
- &helper.proof_share,
- &Self::domain_separation_tag(DST_PROOF_SHARE),
- &[j as u8 + 1],
- ));
- for (x, y) in leader_proof_share
- .iter_mut()
- .zip(proof_share_prng)
- .take(self.typ.proof_len())
+ for (x, y) in
+ leader_proofs_share
+ .iter_mut()
+ .zip(self.derive_helper_proofs_share(
+ &helper.proofs_share,
+ u8::try_from(j).unwrap() + 1,
+ ))
+ .take(self.typ.proof_len() * self.num_proofs())
{
*x -= y;
}
@@ -557,14 +670,14 @@ where
let mut out = Vec::with_capacity(num_aggregators as usize);
out.push(Prio3InputShare {
measurement_share: Share::Leader(leader_measurement_share),
- proof_share: Share::Leader(leader_proof_share),
+ proofs_share: Share::Leader(leader_proofs_share),
joint_rand_blind: leader_blind_opt,
});
for helper in helper_shares.into_iter() {
out.push(Prio3InputShare {
measurement_share: Share::Helper(helper.measurement_share),
- proof_share: Share::Helper(helper.proof_share),
+ proofs_share: Share::Helper(helper.proofs_share),
joint_rand_blind: helper.joint_rand_blind,
});
}
@@ -585,7 +698,6 @@ where
T: Type,
P: Xof<SEED_SIZE>,
{
- const ID: u32 = T::ID;
type Measurement = T::Measurement;
type AggregateResult = T::AggregateResult;
type AggregationParam = ();
@@ -594,6 +706,10 @@ where
type OutputShare = OutputShare<T::Field>;
type AggregateShare = AggregateShare<T::Field>;
+ fn algorithm_id(&self) -> u32 {
+ self.algorithm_id
+ }
+
fn num_aggregators(&self) -> usize {
self.num_aggregators as usize
}
@@ -607,12 +723,13 @@ pub struct Prio3PublicShare<const SEED_SIZE: usize> {
}
impl<const SEED_SIZE: usize> Encode for Prio3PublicShare<SEED_SIZE> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
if let Some(joint_rand_parts) = self.joint_rand_parts.as_ref() {
for part in joint_rand_parts.iter() {
- part.encode(bytes);
+ part.encode(bytes)?;
}
}
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -675,7 +792,7 @@ pub struct Prio3InputShare<F, const SEED_SIZE: usize> {
measurement_share: Share<F, SEED_SIZE>,
/// The proof share.
- proof_share: Share<F, SEED_SIZE>,
+ proofs_share: Share<F, SEED_SIZE>,
/// Blinding seed used by the Aggregator to compute the joint randomness. This field is optional
/// because not every [`Type`] requires joint randomness.
@@ -697,28 +814,29 @@ impl<F: ConstantTimeEq, const SEED_SIZE: usize> ConstantTimeEq for Prio3InputSha
self.joint_rand_blind.as_ref(),
other.joint_rand_blind.as_ref(),
) & self.measurement_share.ct_eq(&other.measurement_share)
- & self.proof_share.ct_eq(&other.proof_share)
+ & self.proofs_share.ct_eq(&other.proofs_share)
}
}
impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> Encode for Prio3InputShare<F, SEED_SIZE> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
if matches!(
- (&self.measurement_share, &self.proof_share),
+ (&self.measurement_share, &self.proofs_share),
(Share::Leader(_), Share::Helper(_)) | (Share::Helper(_), Share::Leader(_))
) {
panic!("tried to encode input share with ambiguous encoding")
}
- self.measurement_share.encode(bytes);
- self.proof_share.encode(bytes);
+ self.measurement_share.encode(bytes)?;
+ self.proofs_share.encode(bytes)?;
if let Some(ref blind) = self.joint_rand_blind {
- blind.encode(bytes);
+ blind.encode(bytes)?;
}
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
- let mut len = self.measurement_share.encoded_len()? + self.proof_share.encoded_len()?;
+ let mut len = self.measurement_share.encoded_len()? + self.proofs_share.encoded_len()?;
if let Some(ref blind) = self.joint_rand_blind {
len += blind.encoded_len()?;
}
@@ -742,7 +860,7 @@ where
let (input_decoder, proof_decoder) = if agg_id == 0 {
(
ShareDecodingParameter::Leader(prio3.typ.input_len()),
- ShareDecodingParameter::Leader(prio3.typ.proof_len()),
+ ShareDecodingParameter::Leader(prio3.typ.proof_len() * prio3.num_proofs()),
)
} else {
(
@@ -752,7 +870,7 @@ where
};
let measurement_share = Share::decode_with_param(&input_decoder, bytes)?;
- let proof_share = Share::decode_with_param(&proof_decoder, bytes)?;
+ let proofs_share = Share::decode_with_param(&proof_decoder, bytes)?;
let joint_rand_blind = if prio3.typ.joint_rand_len() > 0 {
let blind = Seed::decode(bytes)?;
Some(blind)
@@ -762,7 +880,7 @@ where
Ok(Prio3InputShare {
measurement_share,
- proof_share,
+ proofs_share,
joint_rand_blind,
})
}
@@ -772,7 +890,7 @@ where
/// Message broadcast by each [`Aggregator`] in each round of the Preparation phase.
pub struct Prio3PrepareShare<F, const SEED_SIZE: usize> {
/// A share of the FLP verifier message. (See [`Type`].)
- verifier: Vec<F>,
+ verifiers: Vec<F>,
/// A part of the joint randomness seed.
joint_rand_part: Option<Seed<SEED_SIZE>>,
@@ -792,25 +910,26 @@ impl<F: ConstantTimeEq, const SEED_SIZE: usize> ConstantTimeEq for Prio3PrepareS
option_ct_eq(
self.joint_rand_part.as_ref(),
other.joint_rand_part.as_ref(),
- ) & self.verifier.ct_eq(&other.verifier)
+ ) & self.verifiers.ct_eq(&other.verifiers)
}
}
impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> Encode
for Prio3PrepareShare<F, SEED_SIZE>
{
- fn encode(&self, bytes: &mut Vec<u8>) {
- for x in &self.verifier {
- x.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ for x in &self.verifiers {
+ x.encode(bytes)?;
}
if let Some(ref seed) = self.joint_rand_part {
- seed.encode(bytes);
+ seed.encode(bytes)?;
}
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
// Each element of the verifier has the same size.
- let mut len = F::ENCODED_SIZE * self.verifier.len();
+ let mut len = F::ENCODED_SIZE * self.verifiers.len();
if let Some(ref seed) = self.joint_rand_part {
len += seed.encoded_len()?;
}
@@ -825,9 +944,9 @@ impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize>
decoding_parameter: &Prio3PrepareState<F, SEED_SIZE>,
bytes: &mut Cursor<&[u8]>,
) -> Result<Self, CodecError> {
- let mut verifier = Vec::with_capacity(decoding_parameter.verifier_len);
- for _ in 0..decoding_parameter.verifier_len {
- verifier.push(F::decode(bytes)?);
+ let mut verifiers = Vec::with_capacity(decoding_parameter.verifiers_len);
+ for _ in 0..decoding_parameter.verifiers_len {
+ verifiers.push(F::decode(bytes)?);
}
let joint_rand_part = if decoding_parameter.joint_rand_seed.is_some() {
@@ -837,7 +956,7 @@ impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize>
};
Ok(Prio3PrepareShare {
- verifier,
+ verifiers,
joint_rand_part,
})
}
@@ -869,10 +988,11 @@ impl<const SEED_SIZE: usize> ConstantTimeEq for Prio3PrepareMessage<SEED_SIZE> {
}
impl<const SEED_SIZE: usize> Encode for Prio3PrepareMessage<SEED_SIZE> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
if let Some(ref seed) = self.joint_rand_seed {
- seed.encode(bytes);
+ seed.encode(bytes)?;
}
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -924,7 +1044,7 @@ pub struct Prio3PrepareState<F, const SEED_SIZE: usize> {
measurement_share: Share<F, SEED_SIZE>,
joint_rand_seed: Option<Seed<SEED_SIZE>>,
agg_id: u8,
- verifier_len: usize,
+ verifiers_len: usize,
}
impl<F: ConstantTimeEq, const SEED_SIZE: usize> PartialEq for Prio3PrepareState<F, SEED_SIZE> {
@@ -939,7 +1059,7 @@ impl<F: ConstantTimeEq, const SEED_SIZE: usize> ConstantTimeEq for Prio3PrepareS
fn ct_eq(&self, other: &Self) -> Choice {
// We allow short-circuiting on the presence or absence of the joint_rand_seed, as well as
// the aggregator ID & verifier length parameters.
- if self.agg_id != other.agg_id || self.verifier_len != other.verifier_len {
+ if self.agg_id != other.agg_id || self.verifiers_len != other.verifiers_len {
return Choice::from(0);
}
@@ -962,7 +1082,7 @@ impl<F, const SEED_SIZE: usize> Debug for Prio3PrepareState<F, SEED_SIZE> {
},
)
.field("agg_id", &self.agg_id)
- .field("verifier_len", &self.verifier_len)
+ .field("verifiers_len", &self.verifiers_len)
.finish()
}
}
@@ -971,11 +1091,12 @@ impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> Encode
for Prio3PrepareState<F, SEED_SIZE>
{
/// Append the encoded form of this object to the end of `bytes`, growing the vector as needed.
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.measurement_share.encode(bytes);
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ self.measurement_share.encode(bytes)?;
if let Some(ref seed) = self.joint_rand_seed {
- seed.encode(bytes);
+ seed.encode(bytes)?;
}
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -1018,7 +1139,7 @@ where
measurement_share,
joint_rand_seed,
agg_id,
- verifier_len: prio3.typ.verifier_len(),
+ verifiers_len: prio3.typ.verifier_len() * prio3.num_proofs(),
})
}
}
@@ -1051,14 +1172,6 @@ where
VdafError,
> {
let agg_id = self.role_try_from(agg_id)?;
- let mut query_rand_xof = P::init(
- verify_key,
- &Self::domain_separation_tag(DST_QUERY_RANDOMNESS),
- );
- query_rand_xof.update(nonce);
- let query_rand = query_rand_xof
- .into_seed_stream()
- .into_field_vec(self.typ.query_rand_len());
// Create a reference to the (expanded) measurement share.
let expanded_measurement_share: Option<Vec<T::Field>> = match msg.measurement_share {
@@ -1066,7 +1179,7 @@ where
Share::Helper(ref seed) => Some(
P::seed_stream(
seed,
- &Self::domain_separation_tag(DST_MEASUREMENT_SHARE),
+ &self.domain_separation_tag(DST_MEASUREMENT_SHARE),
&[agg_id],
)
.into_field_vec(self.typ.input_len()),
@@ -1078,33 +1191,32 @@ where
};
// Create a reference to the (expanded) proof share.
- let expanded_proof_share: Option<Vec<T::Field>> = match msg.proof_share {
+ let expanded_proofs_share: Option<Vec<T::Field>> = match msg.proofs_share {
Share::Leader(_) => None,
- Share::Helper(ref seed) => Some(
- P::seed_stream(
- seed,
- &Self::domain_separation_tag(DST_PROOF_SHARE),
- &[agg_id],
- )
- .into_field_vec(self.typ.proof_len()),
+ Share::Helper(ref proof_shares_seed) => Some(
+ self.derive_helper_proofs_share(proof_shares_seed, agg_id)
+ .take(self.typ.proof_len() * self.num_proofs())
+ .collect(),
),
};
- let proof_share = match msg.proof_share {
+ let proofs_share = match msg.proofs_share {
Share::Leader(ref data) => data,
- Share::Helper(_) => expanded_proof_share.as_ref().unwrap(),
+ Share::Helper(_) => expanded_proofs_share.as_ref().unwrap(),
};
// Compute the joint randomness.
- let (joint_rand_seed, joint_rand_part, joint_rand) = if self.typ.joint_rand_len() > 0 {
+ let (joint_rand_seed, joint_rand_part, joint_rands) = if self.typ.joint_rand_len() > 0 {
let mut joint_rand_part_xof = P::init(
msg.joint_rand_blind.as_ref().unwrap().as_ref(),
- &Self::domain_separation_tag(DST_JOINT_RAND_PART),
+ &self.domain_separation_tag(DST_JOINT_RAND_PART),
);
joint_rand_part_xof.update(&[agg_id]);
joint_rand_part_xof.update(nonce);
let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE);
for x in measurement_share {
- x.encode(&mut encoding_buffer);
+ x.encode(&mut encoding_buffer).map_err(|_| {
+ VdafError::Uncategorized("failed to encode measurement share".to_string())
+ })?;
joint_rand_part_xof.update(&encoding_buffer);
encoding_buffer.clear();
}
@@ -1131,37 +1243,47 @@ where
.skip(agg_id as usize + 1),
);
- let joint_rand_seed = Self::derive_joint_rand_seed(corrected_joint_rand_parts);
+ let (joint_rand_seed, joint_rands) =
+ self.derive_joint_rands(corrected_joint_rand_parts);
- let joint_rand = P::seed_stream(
- &joint_rand_seed,
- &Self::domain_separation_tag(DST_JOINT_RANDOMNESS),
- &[],
+ (
+ Some(joint_rand_seed),
+ Some(own_joint_rand_part),
+ joint_rands,
)
- .into_field_vec(self.typ.joint_rand_len());
- (Some(joint_rand_seed), Some(own_joint_rand_part), joint_rand)
} else {
(None, None, Vec::new())
};
// Run the query-generation algorithm.
- let verifier_share = self.typ.query(
- measurement_share,
- proof_share,
- &query_rand,
- &joint_rand,
- self.num_aggregators as usize,
- )?;
+ let query_rands = self.derive_query_rands(verify_key, nonce);
+ let mut verifiers_share = Vec::with_capacity(self.typ.verifier_len() * self.num_proofs());
+ for p in 0..self.num_proofs() {
+ let query_rand =
+ &query_rands[p * self.typ.query_rand_len()..(p + 1) * self.typ.query_rand_len()];
+ let joint_rand =
+ &joint_rands[p * self.typ.joint_rand_len()..(p + 1) * self.typ.joint_rand_len()];
+ let proof_share =
+ &proofs_share[p * self.typ.proof_len()..(p + 1) * self.typ.proof_len()];
+
+ verifiers_share.append(&mut self.typ.query(
+ measurement_share,
+ proof_share,
+ query_rand,
+ joint_rand,
+ self.num_aggregators as usize,
+ )?);
+ }
Ok((
Prio3PrepareState {
measurement_share: msg.measurement_share.clone(),
joint_rand_seed,
agg_id,
- verifier_len: verifier_share.len(),
+ verifiers_len: verifiers_share.len(),
},
Prio3PrepareShare {
- verifier: verifier_share,
+ verifiers: verifiers_share,
joint_rand_part,
},
))
@@ -1174,17 +1296,17 @@ where
_: &Self::AggregationParam,
inputs: M,
) -> Result<Prio3PrepareMessage<SEED_SIZE>, VdafError> {
- let mut verifier = vec![T::Field::zero(); self.typ.verifier_len()];
+ let mut verifiers = vec![T::Field::zero(); self.typ.verifier_len() * self.num_proofs()];
let mut joint_rand_parts = Vec::with_capacity(self.num_aggregators());
let mut count = 0;
for share in inputs.into_iter() {
count += 1;
- if share.verifier.len() != verifier.len() {
+ if share.verifiers.len() != verifiers.len() {
return Err(VdafError::Uncategorized(format!(
"unexpected verifier share length: got {}; want {}",
- share.verifier.len(),
- verifier.len(),
+ share.verifiers.len(),
+ verifiers.len(),
)));
}
@@ -1193,7 +1315,7 @@ where
joint_rand_parts.push(joint_rand_seed_part);
}
- for (x, y) in verifier.iter_mut().zip(share.verifier) {
+ for (x, y) in verifiers.iter_mut().zip(share.verifiers) {
*x += y;
}
}
@@ -1205,19 +1327,17 @@ where
)));
}
- // Check the proof verifier.
- match self.typ.decide(&verifier) {
- Ok(true) => (),
- Ok(false) => {
+ // Check the proof verifiers.
+ for verifier in verifiers.chunks(self.typ.verifier_len()) {
+ if !self.typ.decide(verifier)? {
return Err(VdafError::Uncategorized(
"proof verifier check failed".into(),
- ))
+ ));
}
- Err(err) => return Err(VdafError::from(err)),
- };
+ }
let joint_rand_seed = if self.typ.joint_rand_len() > 0 {
- Some(Self::derive_joint_rand_seed(joint_rand_parts.iter()))
+ Some(self.derive_joint_rand_seed(joint_rand_parts.iter()))
} else {
None
};
@@ -1249,7 +1369,7 @@ where
let measurement_share = match step.measurement_share {
Share::Leader(data) => data,
Share::Helper(seed) => {
- let dst = Self::domain_separation_tag(DST_MEASUREMENT_SHARE);
+ let dst = self.domain_separation_tag(DST_MEASUREMENT_SHARE);
P::seed_stream(&seed, &dst, &[step.agg_id]).into_field_vec(self.typ.input_len())
}
};
@@ -1324,7 +1444,7 @@ where
#[derive(Clone)]
struct HelperShare<const SEED_SIZE: usize> {
measurement_share: Seed<SEED_SIZE>,
- proof_share: Seed<SEED_SIZE>,
+ proofs_share: Seed<SEED_SIZE>,
joint_rand_blind: Option<Seed<SEED_SIZE>>,
}
@@ -1336,7 +1456,7 @@ impl<const SEED_SIZE: usize> HelperShare<SEED_SIZE> {
) -> Self {
HelperShare {
measurement_share: Seed::from_bytes(measurement_share),
- proof_share: Seed::from_bytes(proof_share),
+ proofs_share: Seed::from_bytes(proof_share),
joint_rand_blind: joint_rand_blind.map(Seed::from_bytes),
}
}
@@ -1458,7 +1578,8 @@ mod tests {
#[cfg(feature = "experimental")]
use crate::flp::gadgets::ParallelSumGadget;
use crate::vdaf::{
- equality_comparison_test, fieldvec_roundtrip_test, run_vdaf, run_vdaf_prepare,
+ equality_comparison_test, fieldvec_roundtrip_test,
+ test_utils::{run_vdaf, run_vdaf_prepare},
};
use assert_matches::assert_matches;
#[cfg(feature = "experimental")]
@@ -1474,24 +1595,27 @@ mod tests {
fn test_prio3_count() {
let prio3 = Prio3::new_count(2).unwrap();
- assert_eq!(run_vdaf(&prio3, &(), [1, 0, 0, 1, 1]).unwrap(), 3);
+ assert_eq!(
+ run_vdaf(&prio3, &(), [true, false, false, true, true]).unwrap(),
+ 3
+ );
let mut nonce = [0; 16];
let mut verify_key = [0; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);
- let (public_share, input_shares) = prio3.shard(&0, &nonce).unwrap();
+ let (public_share, input_shares) = prio3.shard(&false, &nonce).unwrap();
run_vdaf_prepare(&prio3, &verify_key, &(), &nonce, public_share, input_shares).unwrap();
- let (public_share, input_shares) = prio3.shard(&1, &nonce).unwrap();
+ let (public_share, input_shares) = prio3.shard(&true, &nonce).unwrap();
run_vdaf_prepare(&prio3, &verify_key, &(), &nonce, public_share, input_shares).unwrap();
- test_serialization(&prio3, &1, &nonce).unwrap();
+ test_serialization(&prio3, &true, &nonce).unwrap();
let prio3_extra_helper = Prio3::new_count(3).unwrap();
assert_eq!(
- run_vdaf(&prio3_extra_helper, &(), [1, 0, 0, 1, 1]).unwrap(),
+ run_vdaf(&prio3_extra_helper, &(), [true, false, false, true, true]).unwrap(),
3,
);
}
@@ -1522,7 +1646,7 @@ mod tests {
assert_matches!(result, Err(VdafError::Uncategorized(_)));
let (public_share, mut input_shares) = prio3.shard(&1, &nonce).unwrap();
- assert_matches!(input_shares[0].proof_share, Share::Leader(ref mut data) => {
+ assert_matches!(input_shares[0].proofs_share, Share::Leader(ref mut data) => {
data[0] += Field128::one();
});
let result = run_vdaf_prepare(&prio3, &verify_key, &(), &nonce, public_share, input_shares);
@@ -1550,6 +1674,30 @@ mod tests {
}
#[test]
+ fn test_prio3_sum_vec_multiproof() {
+ let prio3 = Prio3::<
+ SumVec<Field128, ParallelSum<Field128, Mul<Field128>>>,
+ XofTurboShake128,
+ 16,
+ >::new(2, 2, 0xFFFF0000, SumVec::new(2, 20, 4).unwrap())
+ .unwrap();
+
+ assert_eq!(
+ run_vdaf(
+ &prio3,
+ &(),
+ [
+ vec![0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1],
+ vec![0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 1, 3, 0, 3, 0, 0, 0, 1, 0, 0],
+ vec![1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1],
+ ]
+ )
+ .unwrap(),
+ vec![1, 3, 1, 0, 3, 1, 0, 1, 2, 2, 3, 3, 1, 5, 1, 2, 1, 3, 0, 2],
+ );
+ }
+
+ #[test]
#[cfg(feature = "multithreaded")]
fn test_prio3_sum_vec_multithreaded() {
let prio3 = Prio3::new_sum_vec_multithreaded(2, 2, 20, 4).unwrap();
@@ -1598,7 +1746,7 @@ mod tests {
fn test_fixed_vec<Fx, PE, M, const SIZE: usize>(
fp_0: Fx,
- prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofShake128, 16>,
+ prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofTurboShake128, 16>,
) where
Fx: Fixed + CompatibleFloat + std::ops::Neg<Output = Fx>,
PE: Eq + ParallelSumGadget<Field128, PolyEval<Field128>> + Clone + 'static,
@@ -1690,7 +1838,7 @@ mod tests {
fp_4_inv: Fx,
fp_8_inv: Fx,
fp_16_inv: Fx,
- prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofShake128, 16>,
+ prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofTurboShake128, 16>,
) where
Fx: Fixed + CompatibleFloat + std::ops::Neg<Output = Fx>,
PE: Eq + ParallelSumGadget<Field128, PolyEval<Field128>> + Clone + 'static,
@@ -1752,7 +1900,7 @@ mod tests {
let (public_share, mut input_shares) = prio3
.shard(&vec![fp_4_inv, fp_8_inv, fp_16_inv], &nonce)
.unwrap();
- assert_matches!(input_shares[0].proof_share, Share::Leader(ref mut data) => {
+ assert_matches!(input_shares[0].proofs_share, Share::Leader(ref mut data) => {
data[0] += Field128::one();
});
let result =
@@ -1823,7 +1971,7 @@ mod tests {
}
if let (Share::Helper(left), Share::Helper(right)) =
- (&x.proof_share, &y.proof_share)
+ (&x.proofs_share, &y.proofs_share)
{
assert_ne!(left, right);
}
@@ -1847,7 +1995,7 @@ mod tests {
thread_rng().fill(&mut verify_key[..]);
let (public_share, input_shares) = prio3.shard(measurement, nonce)?;
- let encoded_public_share = public_share.get_encoded();
+ let encoded_public_share = public_share.get_encoded().unwrap();
let decoded_public_share =
Prio3PublicShare::get_decoded_with_param(prio3, &encoded_public_share)
.expect("failed to decode public share");
@@ -1858,7 +2006,7 @@ mod tests {
);
for (agg_id, input_share) in input_shares.iter().enumerate() {
- let encoded_input_share = input_share.get_encoded();
+ let encoded_input_share = input_share.get_encoded().unwrap();
let decoded_input_share =
Prio3InputShare::get_decoded_with_param(&(prio3, agg_id), &encoded_input_share)
.expect("failed to decode input share");
@@ -1875,7 +2023,7 @@ mod tests {
let (prepare_state, prepare_share) =
prio3.prepare_init(&verify_key, agg_id, &(), nonce, &public_share, input_share)?;
- let encoded_prepare_state = prepare_state.get_encoded();
+ let encoded_prepare_state = prepare_state.get_encoded().unwrap();
let decoded_prepare_state =
Prio3PrepareState::get_decoded_with_param(&(prio3, agg_id), &encoded_prepare_state)
.expect("failed to decode prepare state");
@@ -1885,7 +2033,7 @@ mod tests {
encoded_prepare_state.len()
);
- let encoded_prepare_share = prepare_share.get_encoded();
+ let encoded_prepare_share = prepare_share.get_encoded().unwrap();
let decoded_prepare_share =
Prio3PrepareShare::get_decoded_with_param(&prepare_state, &encoded_prepare_share)
.expect("failed to decode prepare share");
@@ -1903,7 +2051,7 @@ mod tests {
.prepare_shares_to_prepare_message(&(), prepare_shares)
.unwrap();
- let encoded_prepare_message = prepare_message.get_encoded();
+ let encoded_prepare_message = prepare_message.get_encoded().unwrap();
let decoded_prepare_message = Prio3PrepareMessage::get_decoded_with_param(
&last_prepare_state.unwrap(),
&encoded_prepare_message,
@@ -1967,31 +2115,31 @@ mod tests {
// Default.
Prio3InputShare {
measurement_share: Share::Leader(Vec::from([0])),
- proof_share: Share::Leader(Vec::from([1])),
+ proofs_share: Share::Leader(Vec::from([1])),
joint_rand_blind: Some(Seed([2])),
},
// Modified measurement share.
Prio3InputShare {
measurement_share: Share::Leader(Vec::from([100])),
- proof_share: Share::Leader(Vec::from([1])),
+ proofs_share: Share::Leader(Vec::from([1])),
joint_rand_blind: Some(Seed([2])),
},
// Modified proof share.
Prio3InputShare {
measurement_share: Share::Leader(Vec::from([0])),
- proof_share: Share::Leader(Vec::from([101])),
+ proofs_share: Share::Leader(Vec::from([101])),
joint_rand_blind: Some(Seed([2])),
},
// Modified joint_rand_blind.
Prio3InputShare {
measurement_share: Share::Leader(Vec::from([0])),
- proof_share: Share::Leader(Vec::from([1])),
+ proofs_share: Share::Leader(Vec::from([1])),
joint_rand_blind: Some(Seed([102])),
},
// Missing joint_rand_blind.
Prio3InputShare {
measurement_share: Share::Leader(Vec::from([0])),
- proof_share: Share::Leader(Vec::from([1])),
+ proofs_share: Share::Leader(Vec::from([1])),
joint_rand_blind: None,
},
])
@@ -2002,22 +2150,22 @@ mod tests {
equality_comparison_test(&[
// Default.
Prio3PrepareShare {
- verifier: Vec::from([0]),
+ verifiers: Vec::from([0]),
joint_rand_part: Some(Seed([1])),
},
// Modified verifier.
Prio3PrepareShare {
- verifier: Vec::from([100]),
+ verifiers: Vec::from([100]),
joint_rand_part: Some(Seed([1])),
},
// Modified joint_rand_part.
Prio3PrepareShare {
- verifier: Vec::from([0]),
+ verifiers: Vec::from([0]),
joint_rand_part: Some(Seed([101])),
},
// Missing joint_rand_part.
Prio3PrepareShare {
- verifier: Vec::from([0]),
+ verifiers: Vec::from([0]),
joint_rand_part: None,
},
])
@@ -2049,42 +2197,42 @@ mod tests {
measurement_share: Share::Leader(Vec::from([0])),
joint_rand_seed: Some(Seed([1])),
agg_id: 2,
- verifier_len: 3,
+ verifiers_len: 3,
},
// Modified measurement share.
Prio3PrepareState {
measurement_share: Share::Leader(Vec::from([100])),
joint_rand_seed: Some(Seed([1])),
agg_id: 2,
- verifier_len: 3,
+ verifiers_len: 3,
},
// Modified joint_rand_seed.
Prio3PrepareState {
measurement_share: Share::Leader(Vec::from([0])),
joint_rand_seed: Some(Seed([101])),
agg_id: 2,
- verifier_len: 3,
+ verifiers_len: 3,
},
// Missing joint_rand_seed.
Prio3PrepareState {
measurement_share: Share::Leader(Vec::from([0])),
joint_rand_seed: None,
agg_id: 2,
- verifier_len: 3,
+ verifiers_len: 3,
},
// Modified agg_id.
Prio3PrepareState {
measurement_share: Share::Leader(Vec::from([0])),
joint_rand_seed: Some(Seed([1])),
agg_id: 102,
- verifier_len: 3,
+ verifiers_len: 3,
},
// Modified verifier_len.
Prio3PrepareState {
measurement_share: Share::Leader(Vec::from([0])),
joint_rand_seed: Some(Seed([1])),
agg_id: 2,
- verifier_len: 103,
+ verifiers_len: 103,
},
])
}
diff --git a/third_party/rust/prio/src/vdaf/prio3_test.rs b/third_party/rust/prio/src/vdaf/prio3_test.rs
index 372a2c8560..9a3dfd85f4 100644
--- a/third_party/rust/prio/src/vdaf/prio3_test.rs
+++ b/third_party/rust/prio/src/vdaf/prio3_test.rs
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
+//! Tools for evaluating Prio3 test vectors.
+
use crate::{
codec::{Encode, ParameterizedDecode},
flp::Type,
@@ -58,19 +60,21 @@ macro_rules! err {
// TODO Generalize this method to work with any VDAF. To do so we would need to add
// `shard_with_random()` to traits. (There may be a less invasive alternative.)
-fn check_prep_test_vec<M, T, P, const SEED_SIZE: usize>(
+fn check_prep_test_vec<MS, MP, T, P, const SEED_SIZE: usize>(
prio3: &Prio3<T, P, SEED_SIZE>,
verify_key: &[u8; SEED_SIZE],
test_num: usize,
- t: &TPrio3Prep<M>,
+ t: &TPrio3Prep<MS>,
) -> Vec<OutputShare<T::Field>>
where
- T: Type<Measurement = M>,
+ MS: Clone,
+ MP: From<MS>,
+ T: Type<Measurement = MP>,
P: Xof<SEED_SIZE>,
{
let nonce = <[u8; 16]>::try_from(t.nonce.clone()).unwrap();
let (public_share, input_shares) = prio3
- .shard_with_random(&t.measurement, &nonce, &t.rand)
+ .shard_with_random(&t.measurement.clone().into(), &nonce, &t.rand)
.expect("failed to generate input shares");
assert_eq!(
@@ -86,7 +90,7 @@ where
"#{test_num}"
);
assert_eq!(
- input_shares[agg_id].get_encoded(),
+ input_shares[agg_id].get_encoded().unwrap(),
want.as_ref(),
"#{test_num}"
)
@@ -110,14 +114,18 @@ where
.unwrap_or_else(|e| err!(test_num, e, "decode test vector (prep share)")),
"#{test_num}"
);
- assert_eq!(prep_shares[i].get_encoded(), want.as_ref(), "#{test_num}");
+ assert_eq!(
+ prep_shares[i].get_encoded().unwrap(),
+ want.as_ref(),
+ "#{test_num}"
+ );
}
let inbound = prio3
.prepare_shares_to_prepare_message(&(), prep_shares)
.unwrap_or_else(|e| err!(test_num, e, "prep preprocess"));
assert_eq!(t.prep_messages.len(), 1);
- assert_eq!(inbound.get_encoded(), t.prep_messages[0].as_ref());
+ assert_eq!(inbound.get_encoded().unwrap(), t.prep_messages[0].as_ref());
let mut out_shares = Vec::new();
for state in states.iter_mut() {
@@ -130,7 +138,11 @@ where
}
for (got, want) in out_shares.iter().zip(t.out_shares.iter()) {
- let got: Vec<Vec<u8>> = got.as_ref().iter().map(|x| x.get_encoded()).collect();
+ let got: Vec<Vec<u8>> = got
+ .as_ref()
+ .iter()
+ .map(|x| x.get_encoded().unwrap())
+ .collect();
assert_eq!(got.len(), want.len());
for (got_elem, want_elem) in got.iter().zip(want.iter()) {
assert_eq!(got_elem.as_slice(), want_elem.as_ref());
@@ -141,12 +153,14 @@ where
}
#[must_use]
-fn check_aggregate_test_vec<M, T, P, const SEED_SIZE: usize>(
+fn check_aggregate_test_vec<MS, MP, T, P, const SEED_SIZE: usize>(
prio3: &Prio3<T, P, SEED_SIZE>,
- t: &TPrio3<M>,
+ t: &TPrio3<MS>,
) -> T::AggregateResult
where
- T: Type<Measurement = M>,
+ MS: Clone,
+ MP: From<MS>,
+ T: Type<Measurement = MP>,
P: Xof<SEED_SIZE>,
{
let verify_key = t.verify_key.as_ref().try_into().unwrap();
@@ -167,85 +181,113 @@ where
.collect::<Vec<_>>();
for (got, want) in aggregate_shares.iter().zip(t.agg_shares.iter()) {
- let got = got.get_encoded();
+ let got = got.get_encoded().unwrap();
assert_eq!(got.as_slice(), want.as_ref());
}
prio3.unshard(&(), aggregate_shares, 1).unwrap()
}
+/// Evaluate a Prio3 test vector. The instance of Prio3 is constructed from the `new_vdaf` callback,
+/// which takes in the VDAF parameters encoded by the test vectors and the number of shares.
+///
+/// This version allows customizing the deserialization of measurements, via an additional type
+/// parameter.
+#[cfg(feature = "test-util")]
+#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
+pub fn check_test_vec_custom_de<MS, MP, A, T, P, const SEED_SIZE: usize>(
+ test_vec_json_str: &str,
+ new_vdaf: impl Fn(&HashMap<String, serde_json::Value>, u8) -> Prio3<T, P, SEED_SIZE>,
+) where
+ MS: for<'de> Deserialize<'de> + Clone,
+ MP: From<MS>,
+ A: for<'de> Deserialize<'de> + Debug + Eq,
+ T: Type<Measurement = MP, AggregateResult = A>,
+ P: Xof<SEED_SIZE>,
+{
+ let t: TPrio3<MS> = serde_json::from_str(test_vec_json_str).unwrap();
+ let vdaf = new_vdaf(&t.other_params, t.shares);
+ let agg_result = check_aggregate_test_vec(&vdaf, &t);
+ assert_eq!(agg_result, serde_json::from_value(t.agg_result).unwrap());
+}
+
+/// Evaluate a Prio3 test vector. The instance of Prio3 is constructed from the `new_vdaf` callback,
+/// which takes in the VDAF parameters encoded by the test vectors and the number of shares.
+#[cfg(feature = "test-util")]
+#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
+pub fn check_test_vec<M, A, T, P, const SEED_SIZE: usize>(
+ test_vec_json_str: &str,
+ new_vdaf: impl Fn(&HashMap<String, serde_json::Value>, u8) -> Prio3<T, P, SEED_SIZE>,
+) where
+ M: for<'de> Deserialize<'de> + Clone,
+ A: for<'de> Deserialize<'de> + Debug + Eq,
+ T: Type<Measurement = M, AggregateResult = A>,
+ P: Xof<SEED_SIZE>,
+{
+ check_test_vec_custom_de::<M, M, _, _, _, SEED_SIZE>(test_vec_json_str, new_vdaf)
+}
+
+#[derive(Debug, Clone, Deserialize)]
+#[serde(transparent)]
+struct Prio3CountMeasurement(u8);
+
+impl From<Prio3CountMeasurement> for bool {
+ fn from(value: Prio3CountMeasurement) -> Self {
+ value.0 != 0
+ }
+}
+
#[test]
fn test_vec_prio3_count() {
for test_vector_str in [
- include_str!("test_vec/07/Prio3Count_0.json"),
- include_str!("test_vec/07/Prio3Count_1.json"),
+ include_str!("test_vec/08/Prio3Count_0.json"),
+ include_str!("test_vec/08/Prio3Count_1.json"),
] {
- let t: TPrio3<u64> = serde_json::from_str(test_vector_str).unwrap();
- let prio3 = Prio3::new_count(t.shares).unwrap();
-
- let aggregate_result = check_aggregate_test_vec(&prio3, &t);
- assert_eq!(aggregate_result, t.agg_result.as_u64().unwrap());
+ check_test_vec_custom_de::<Prio3CountMeasurement, _, _, _, _, 16>(
+ test_vector_str,
+ |_json_params, num_shares| Prio3::new_count(num_shares).unwrap(),
+ );
}
}
#[test]
fn test_vec_prio3_sum() {
for test_vector_str in [
- include_str!("test_vec/07/Prio3Sum_0.json"),
- include_str!("test_vec/07/Prio3Sum_1.json"),
+ include_str!("test_vec/08/Prio3Sum_0.json"),
+ include_str!("test_vec/08/Prio3Sum_1.json"),
] {
- let t: TPrio3<u128> = serde_json::from_str(test_vector_str).unwrap();
- let bits = t.other_params["bits"].as_u64().unwrap() as usize;
- let prio3 = Prio3::new_sum(t.shares, bits).unwrap();
-
- let aggregate_result = check_aggregate_test_vec(&prio3, &t);
- assert_eq!(aggregate_result, t.agg_result.as_u64().unwrap() as u128);
+ check_test_vec(test_vector_str, |json_params, num_shares| {
+ let bits = json_params["bits"].as_u64().unwrap() as usize;
+ Prio3::new_sum(num_shares, bits).unwrap()
+ });
}
}
#[test]
fn test_vec_prio3_sum_vec() {
for test_vector_str in [
- include_str!("test_vec/07/Prio3SumVec_0.json"),
- include_str!("test_vec/07/Prio3SumVec_1.json"),
+ include_str!("test_vec/08/Prio3SumVec_0.json"),
+ include_str!("test_vec/08/Prio3SumVec_1.json"),
] {
- let t: TPrio3<Vec<u128>> = serde_json::from_str(test_vector_str).unwrap();
- let bits = t.other_params["bits"].as_u64().unwrap() as usize;
- let length = t.other_params["length"].as_u64().unwrap() as usize;
- let chunk_length = t.other_params["chunk_length"].as_u64().unwrap() as usize;
- let prio3 = Prio3::new_sum_vec(t.shares, bits, length, chunk_length).unwrap();
-
- let aggregate_result = check_aggregate_test_vec(&prio3, &t);
- let expected_aggregate_result = t
- .agg_result
- .as_array()
- .unwrap()
- .iter()
- .map(|val| val.as_u64().unwrap() as u128)
- .collect::<Vec<u128>>();
- assert_eq!(aggregate_result, expected_aggregate_result);
+ check_test_vec(test_vector_str, |json_params, num_shares| {
+ let bits = json_params["bits"].as_u64().unwrap() as usize;
+ let length = json_params["length"].as_u64().unwrap() as usize;
+ let chunk_length = json_params["chunk_length"].as_u64().unwrap() as usize;
+ Prio3::new_sum_vec(num_shares, bits, length, chunk_length).unwrap()
+ });
}
}
#[test]
fn test_vec_prio3_histogram() {
for test_vector_str in [
- include_str!("test_vec/07/Prio3Histogram_0.json"),
- include_str!("test_vec/07/Prio3Histogram_1.json"),
+ include_str!("test_vec/08/Prio3Histogram_0.json"),
+ include_str!("test_vec/08/Prio3Histogram_1.json"),
] {
- let t: TPrio3<usize> = serde_json::from_str(test_vector_str).unwrap();
- let length = t.other_params["length"].as_u64().unwrap() as usize;
- let chunk_length = t.other_params["chunk_length"].as_u64().unwrap() as usize;
- let prio3 = Prio3::new_histogram(t.shares, length, chunk_length).unwrap();
-
- let aggregate_result = check_aggregate_test_vec(&prio3, &t);
- let expected_aggregate_result = t
- .agg_result
- .as_array()
- .unwrap()
- .iter()
- .map(|val| val.as_u64().unwrap() as u128)
- .collect::<Vec<u128>>();
- assert_eq!(aggregate_result, expected_aggregate_result);
+ check_test_vec(test_vector_str, |json_params, num_shares| {
+ let length = json_params["length"].as_u64().unwrap() as usize;
+ let chunk_length = json_params["chunk_length"].as_u64().unwrap() as usize;
+ Prio3::new_histogram(num_shares, length, chunk_length).unwrap()
+ });
}
}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/IdpfPoplar_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/IdpfPoplar_0.json
deleted file mode 100644
index 2ff7aa7ffd..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/IdpfPoplar_0.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "alpha": "0",
- "beta_inner": [
- [
- "0",
- "0"
- ],
- [
- "1",
- "1"
- ],
- [
- "2",
- "2"
- ],
- [
- "3",
- "3"
- ],
- [
- "4",
- "4"
- ],
- [
- "5",
- "5"
- ],
- [
- "6",
- "6"
- ],
- [
- "7",
- "7"
- ],
- [
- "8",
- "8"
- ]
- ],
- "beta_leaf": [
- "9",
- "9"
- ],
- "binder": "736f6d65206e6f6e6365",
- "bits": 10,
- "keys": [
- "000102030405060708090a0b0c0d0e0f",
- "101112131415161718191a1b1c1d1e1f"
- ],
- "public_share": "921909356f44964d29c537aeeaeba92e573e4298c88dcc35bd3ae6acb4367236226b1af3151d5814f308f04e208fde2110c72523338563bc1c5fb47d22b5c34ae102e1e82fa250c7e23b95e985f91d7d91887fa7fb301ec20a06b1d4408d9a594754dcd86ec00c91f40f17c1ff52ed99fcd59965fe243a6cec7e672fefc5e3a29e653d5dcca8917e8af2c4f19d122c6dd30a3e2a80fb809383ced9d24fcd86516025174f5183fddfc6d74dde3b78834391c785defc8e4fbff92214df4c8322ee433a8eaeed7369419e0d6037a536e081df333aaab9e8e4d207d846961f015d96d57e3b59e24927773d6e0d66108955c1da134baab4eacd363c8e452b8c3845d5fb5c0ff6c27d7423a73d32742ccc3c750a17cd1f6026dd98a2cf6d2bff2dd339017b25af23d6db00ae8975e3f7e6aaef4af71f3e8cd14eb5c4373db9c3a76fc04659b761e650a97cb873df894064ecb2043a4317ef237ffe8f130eb5c2ca2a132c16f14943cd7e462568c8544b82e29329eb2a"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_0.json
deleted file mode 100644
index 79fadca3df..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_0.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "agg_param": [
- 0,
- [
- 0,
- 1
- ]
- ],
- "agg_result": [
- 0,
- 1
- ],
- "agg_shares": [
- "70f1cb8dc03c9eea88d270d6211a8667",
- "910e34723ec361157a2d8f29dde57998"
- ],
- "bits": 4,
- "prep": [
- {
- "input_shares": [
- "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930",
- "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c"
- ],
- "measurement": 13,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "70f1cb8dc03c9eea",
- "88d270d6211a8667"
- ],
- [
- "910e34723ec36115",
- "7a2d8f29dde57998"
- ]
- ],
- "prep_messages": [
- "d4cd54eb29f676c2d10fab848e6e85ebd51804e3562cf23b",
- ""
- ],
- "prep_shares": [
- [
- "bd68d28c9fff9a30f84122278759025501b83270bf27b41d",
- "1765825e8af6db91d9cd885d07158396d460d17297043e1e"
- ],
- [
- "7c9659b7c681b4a4",
- "8569a648387e4b5b"
- ]
- ],
- "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_1.json
deleted file mode 100644
index a566fe8b4d..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_1.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{
- "agg_param": [
- 1,
- [
- 0,
- 1,
- 2,
- 3
- ]
- ],
- "agg_result": [
- 0,
- 0,
- 0,
- 1
- ],
- "agg_shares": [
- "d83fbcbf13566502f5849058b8b089e568a4e8aab8565425f69a56f809fc4527",
- "29c04340eba99afd0c7b6fa7464f761a995b175546a9abda0c65a907f503bad8"
- ],
- "bits": 4,
- "prep": [
- {
- "input_shares": [
- "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930",
- "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c"
- ],
- "measurement": 13,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "d83fbcbf13566502",
- "f5849058b8b089e5",
- "68a4e8aab8565425",
- "f69a56f809fc4527"
- ],
- [
- "29c04340eba99afd",
- "0c7b6fa7464f761a",
- "995b175546a9abda",
- "0c65a907f503bad8"
- ]
- ],
- "prep_messages": [
- "d45c0eabcc906acfb8239f3d0ef2b69a0f465979b04e355c",
- ""
- ],
- "prep_shares": [
- [
- "5d1b91841835491251436306076eaaa674d4b95b84b2a084",
- "77417d26b45b21bd68e03b3706840cf49c719f1d2b9c94d7"
- ],
- [
- "6e703a28b5960604",
- "938fc5d74969f9fb"
- ]
- ],
- "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_2.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_2.json
deleted file mode 100644
index 8141bc942e..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_2.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{
- "agg_param": [
- 2,
- [
- 0,
- 2,
- 4,
- 6
- ]
- ],
- "agg_result": [
- 0,
- 0,
- 0,
- 1
- ],
- "agg_shares": [
- "7ea47022f22f6be9bce8e0ee2eb522bcbc2d246c17704beed7043426b646fe26",
- "835b8fdd0cd0941645171f11d04add4345d2db93e78fb4112bfbcbd948b901d9"
- ],
- "bits": 4,
- "prep": [
- {
- "input_shares": [
- "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930",
- "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c"
- ],
- "measurement": 13,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "7ea47022f22f6be9",
- "bce8e0ee2eb522bc",
- "bc2d246c17704bee",
- "d7043426b646fe26"
- ],
- [
- "835b8fdd0cd09416",
- "45171f11d04add43",
- "45d2db93e78fb411",
- "2bfbcbd948b901d9"
- ]
- ],
- "prep_messages": [
- "6fb240ce8b8a2a8ce62112240f676105e0398515599f04b4",
- ""
- ],
- "prep_shares": [
- [
- "ca0f02c7c61655263bf76d954b8abd16eb6e5ce2b26911b2",
- "a5a23e07c573d565ac2aa48ec2dca3eef5ca2833a635f301"
- ],
- [
- "f5171a3cc9d49422",
- "0ce8e5c3352b6bdd"
- ]
- ],
- "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_3.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_3.json
deleted file mode 100644
index 1741ec0ebc..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_3.json
+++ /dev/null
@@ -1,76 +0,0 @@
-{
- "agg_param": [
- 3,
- [
- 1,
- 3,
- 5,
- 7,
- 9,
- 13,
- 15
- ]
- ],
- "agg_result": [
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0
- ],
- "agg_shares": [
- "ec2be80f01fd1ded599b1a18d6ef112c400f421cca2c080d4ccc5cdd09562b3e556c1aaabe9dd47e8bc25979394c7bb5c61fd1db34b8dfdcc3eff4a5304fb7706b5462025bb400e644f2e0752f38098702491691494a2b498176ef41c4e6a962f716473c53087a3e80db0b9acb50cb15081b5ea4b50c48093f67a8c75875422dfd64ab2fa71fa3f3b55ec708ba4086672aff514d0cffe6f1c07f117c22af9b2c67b2a0c7ec1366ce474721174edb8b9eb33faef5f9c9d0c956e4407a86473120cfa46e8c634c1bc66c63a2009911f82c8426a45013e637aaba0e471b03f0a67a",
- "01d417f0fe02e212a664e5e72910eed3bff0bde335d3f7f2b333a322f6a9d4419893e55541622b81743da686c6b3844a39e02e24cb4720233c100b5acfb0480f82ab9dfda44bff19bb0d1f8ad0c7f678fdb6e96eb6b5d4b67e8910be3b19561df6e8b8c3acf785c17f24f46534af34eaf7e4a15b4af3b7f6c0985738a78abd52f09a54d058e05c0c4aa138f745bf7998d500aeb2f300190e3f80ee83dd506453874d5f3813ec9931b8b8dee8b12474614cc0510a06362f36a91bbf8579b8ce5f1e5b91739cb3e439939c5dff66ee07d37bd95bafec19c85545f1b8e4fc0f5905"
- ],
- "bits": 4,
- "prep": [
- {
- "input_shares": [
- "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930",
- "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c"
- ],
- "measurement": 13,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "ec2be80f01fd1ded599b1a18d6ef112c400f421cca2c080d4ccc5cdd09562b3e",
- "556c1aaabe9dd47e8bc25979394c7bb5c61fd1db34b8dfdcc3eff4a5304fb770",
- "6b5462025bb400e644f2e0752f38098702491691494a2b498176ef41c4e6a962",
- "f716473c53087a3e80db0b9acb50cb15081b5ea4b50c48093f67a8c75875422d",
- "fd64ab2fa71fa3f3b55ec708ba4086672aff514d0cffe6f1c07f117c22af9b2c",
- "67b2a0c7ec1366ce474721174edb8b9eb33faef5f9c9d0c956e4407a86473120",
- "cfa46e8c634c1bc66c63a2009911f82c8426a45013e637aaba0e471b03f0a67a"
- ],
- [
- "01d417f0fe02e212a664e5e72910eed3bff0bde335d3f7f2b333a322f6a9d441",
- "9893e55541622b81743da686c6b3844a39e02e24cb4720233c100b5acfb0480f",
- "82ab9dfda44bff19bb0d1f8ad0c7f678fdb6e96eb6b5d4b67e8910be3b19561d",
- "f6e8b8c3acf785c17f24f46534af34eaf7e4a15b4af3b7f6c0985738a78abd52",
- "f09a54d058e05c0c4aa138f745bf7998d500aeb2f300190e3f80ee83dd506453",
- "874d5f3813ec9931b8b8dee8b12474614cc0510a06362f36a91bbf8579b8ce5f",
- "1e5b91739cb3e439939c5dff66ee07d37bd95bafec19c85545f1b8e4fc0f5905"
- ]
- ],
- "prep_messages": [
- "4a2b97cf17e54b126a86c6791c50d6507ee8b74b3d9903bcf3881121bc6e0975c4efb2d8b8a132b8a6caa4eb39ac2bbb5bdc351604fa9e78d1a6f5a5f615bb0c8819f485d8b24a4e48da47d3b7458a9cfde1e85c66453319a3f6d43dc40a0135",
- ""
- ],
- "prep_shares": [
- [
- "4e64e5ed76c69ef68d3e144918a719986e40ab82f34bd30298b0085a3265d16988b8f646731ef47cb2fb1598e4cb817747623f1cc70ee7843ce1a9d6e3cf5c456801c9a3ae0c7c7663349a3daaf8fb51d165085c751e5bdd4e800df9e1e0193e",
- "fcc6b1e1a01ead1bdc47b23004a9bcb80fa80cc9494d30b95bd808c78909380b2937bc9145833e3bf4ce8e5355e0a943147af6f93cebb7f394c54bcf12465e470d182be229a6ced7e4a5ad950d4d8e4a2c7ce000f126d83b5476c744e229e776"
- ],
- [
- "003c39f76240f6f9bcc6065a247b4432a651d5d72a35aff45928eec28c8a9d07",
- "edc3c6089dbf09064339f9a5db84bbcd59ae2a28d5ca500ba6d7113d73756278"
- ]
- ],
- "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_0.json
deleted file mode 100644
index c27ad93435..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_0.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "agg_param": null,
- "agg_result": 1,
- "agg_shares": [
- "afead111dacc0c7e",
- "53152eee2433f381"
- ],
- "prep": [
- {
- "input_shares": [
- "afead111dacc0c7ec08c411babd6e2404df512ddfa0a81736b7607f4ccb3f39e414fdb4bc89a63569702c92aed6a6a96",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
- ],
- "measurement": 1,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "afead111dacc0c7e"
- ],
- [
- "53152eee2433f381"
- ]
- ],
- "prep_messages": [
- ""
- ],
- "prep_shares": [
- [
- "123f23c117b7ed6099be9e6a31a42a9caa60882a3b4aa50303f8b588c9efe60b",
- "efc0dc3ee748129f2da661f47a625a57d64a5b62ab38647c34bb161c7576d721"
- ]
- ],
- "public_share": "",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_1.json
deleted file mode 100644
index 148fe6df58..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_1.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
- "agg_param": null,
- "agg_result": 1,
- "agg_shares": [
- "c5647e016eea69f6",
- "53152eee2433f381",
- "eb8553106be2a287"
- ],
- "prep": [
- {
- "input_shares": [
- "c5647e016eea69f6d10e90d05e2ad8b402b8580f394a719b371ae8f1a364b280d08ca7177946a1a0b9643e2469b0a2e9",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
- "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
- ],
- "measurement": 1,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "c5647e016eea69f6"
- ],
- [
- "53152eee2433f381"
- ],
- [
- "eb8553106be2a287"
- ]
- ],
- "prep_messages": [
- ""
- ],
- "prep_shares": [
- [
- "5c8d00fd24e449d375581d6adbeaf9cf4bdface6d368fd7b1562e5bf47b9fa68",
- "efc0dc3ee748129f2da661f47a625a57d64a5b62ab38647c34bb161c7576d721",
- "b7b122c4f1d2a38df764c623c266f02f7b5178c3d64735ec06037585d643f528"
- ]
- ],
- "public_share": "",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 3,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_0.json
deleted file mode 100644
index 099f786669..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_0.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "agg_param": null,
- "agg_result": [
- 0,
- 0,
- 1,
- 0
- ],
- "agg_shares": [
- "14be9c4ef7a6e12e963fdeac21cebdd4d36e13f4bc25306322e56303c62c90afd73f6b4aa9fdf33cb0afb55426d645ff8cd7e78cebf9d4f1087f6d4a033c8eae",
- "ed4163b108591ed14dc02153de31422b2e91ec0b43dacf9cc11a9cfc39d36f502bc094b556020cc333504aabd929ba007528187314062b0edb8092b5fcc37151"
- ],
- "chunk_length": 2,
- "length": 4,
- "prep": [
- {
- "input_shares": [
- "14be9c4ef7a6e12e963fdeac21cebdd4d36e13f4bc25306322e56303c62c90afd73f6b4aa9fdf33cb0afb55426d645ff8cd7e78cebf9d4f1087f6d4a033c8eaeec786d3b212d968c939de66318dbacafe73c1f5aa3e9078ba2f63ec5179e6b4694612c36f5d4d539d46dab1ac20e43963978d9dd36f19f31c83e58c903c2cd94215c68b15f5d6071e9e19fa973829dc71b536351b0db1072e77b7570e3e06c65fac248d21dd970f29640050e901d06775f05a897850cab5707ac25543ed6ce7061b9cd70c783e0483727236d0cbb05dafefd78ec4e6419efe93d6f82cdadbfd4e860661238040229f60205bbba983790303132333435363738393a3b3c3d3e3f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
- ],
- "measurement": 2,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "14be9c4ef7a6e12e963fdeac21cebdd4",
- "d36e13f4bc25306322e56303c62c90af",
- "d73f6b4aa9fdf33cb0afb55426d645ff",
- "8cd7e78cebf9d4f1087f6d4a033c8eae"
- ],
- [
- "ed4163b108591ed14dc02153de31422b",
- "2e91ec0b43dacf9cc11a9cfc39d36f50",
- "2bc094b556020cc333504aabd929ba00",
- "7528187314062b0edb8092b5fcc37151"
- ]
- ],
- "prep_messages": [
- "7556ccbddbd14d509ee89124d31d1feb"
- ],
- "prep_shares": [
- [
- "806b1f8537500ce0b4b501b0ae5ed8f82679ba11ad995d6f605b000e32c41afb6d0070287fe7b99b8304d264cba1e3c6f4456e1c06f3b9d3d4947b2041c86b020d26c74d7663817e6a91960489806931b304fcd3755b43b96c806d2bbeb0166bbec7c61c35f886f3f539890522388f43",
- "8194e07ac8aff31f2f4afe4f51a12707b692a56a1745315a1022b4eb257b2a8725c610416af7b0d1a296f409cdb3fbf4f4c0d488206d794254e4755fd124cdc9a67364ddc7865afe3554de5f52f1ac910f3f8e110cfbad4113861316dc73ec60de4f6c512adaa41de631eda8d6d8c189"
- ]
- ],
- "public_share": "bec7c61c35f886f3f539890522388f43de4f6c512adaa41de631eda8d6d8c189",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_1.json
deleted file mode 100644
index 0b9a9b4d5d..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_1.json
+++ /dev/null
@@ -1,89 +0,0 @@
-{
- "agg_param": null,
- "agg_result": [
- 0,
- 0,
- 1,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- ],
- "agg_shares": [
- "a6d2b4756e63a10bf5f650e258c73b0ccb20bace98e225dea29d625d527fdd4ded86beb9a0a0ac5c4216f5add7a297cece34b479a568a327f1e259839f813df97b34de254be5b9b9c8d9e56dbff50b7a6bf1e5967686755a1dc42e0ab170add8c88f8ca68f945e768a5007c775fd27cfecb4495e257a2f2f94ca48830aa16ec0decaeee645e295c5dc2ebe491aae1a7f17b2807fcb33ee08127db466067bf84ec613dac9c93adbe73dd262c1859b2865",
- "ed4163b108591ed14dc02153de31422b2e91ec0b43dacf9cc11a9cfc39d36f502bc094b556020cc333504aabd929ba007528187314062b0edb8092b5fcc3715126e16ce274ad58caaa14d22608269a4c41a256d3c9e847c0a6ac1a4fbaf6309e9ccbe74a9442ca956d843d6bd5adf9797a84557597d9cc81ddfa281ae5048d686bdb289ec2f3c96cdfa79b6974e6d15aec047748636d4358226283e11a78e045f59db2dda566162a56c85936ac0f4696",
- "6eebe7d888434023a1488dcac80682c8084e592524430a857f4701a673adb261eab8ac90085d47e06d99c0a64e33ae30bfa23313469131cafb9b13c763ba50b560eab4f73f6ded7b7011486b38e45939566cc395bf9042e5038fb6a6949821899ea48b0edc28d7f3cf2abbcdb454deb69cc6602c43ac034f563a8e62105a04d7b859e87af729a0cd2729a64c716b1326fe480838d15ece9eaf20c8b7de0c276b464e7358905e0eee4f654308ce549104"
- ],
- "chunk_length": 3,
- "length": 11,
- "prep": [
- {
- "input_shares": [
- "a6d2b4756e63a10bf5f650e258c73b0ccb20bace98e225dea29d625d527fdd4ded86beb9a0a0ac5c4216f5add7a297cece34b479a568a327f1e259839f813df97b34de254be5b9b9c8d9e56dbff50b7a6bf1e5967686755a1dc42e0ab170add8c88f8ca68f945e768a5007c775fd27cfecb4495e257a2f2f94ca48830aa16ec0decaeee645e295c5dc2ebe491aae1a7f17b2807fcb33ee08127db466067bf84ec613dac9c93adbe73dd262c1859b2865508d344dda6c4339e650c401324c31481780ef7e7dcc07120ac004c05ab75ee5d22e2d0eb229dcdd3755fab49a1c2916e17c8ed2d975cfe76d576569bf05233c07f94417fccaf73d1cc33e17dae74650badffdd639a9b9f9e89de4b9fd13e258b90fbb2b3817b607dc14e6e5327746ca20d1f1918bce9714b135ffe01eb4e6aefab92b0462f7e676e26007e8c2e5a66e16f32f7c8457a6dfba39d9082f640006d560b4d64e86e2e2358c84e03b857c980f51b1a78b53f7cb44343ed184d8dc87ebf8698609eeefae5d8882224ebd28b9531015badea8ae9fe01c7495cafecdc4f13389ea4eb0bbce0a5ab85aa6fc06aabd96d28c84ecf039bfeb4c350049485f8a4c706a109164ff4c640edaedd0ad50820b1d1ed7ab08fc69c48b39aff1eebc02ef1ea40bd70784bfa50511c3dd64b107f4297842280c3cff8d94be202a0e2cb0090f3adb2189f445fcf291f452f162606162636465666768696a6b6c6d6e6f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
- "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
- ],
- "measurement": 2,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "a6d2b4756e63a10bf5f650e258c73b0c",
- "cb20bace98e225dea29d625d527fdd4d",
- "ed86beb9a0a0ac5c4216f5add7a297ce",
- "ce34b479a568a327f1e259839f813df9",
- "7b34de254be5b9b9c8d9e56dbff50b7a",
- "6bf1e5967686755a1dc42e0ab170add8",
- "c88f8ca68f945e768a5007c775fd27cf",
- "ecb4495e257a2f2f94ca48830aa16ec0",
- "decaeee645e295c5dc2ebe491aae1a7f",
- "17b2807fcb33ee08127db466067bf84e",
- "c613dac9c93adbe73dd262c1859b2865"
- ],
- [
- "ed4163b108591ed14dc02153de31422b",
- "2e91ec0b43dacf9cc11a9cfc39d36f50",
- "2bc094b556020cc333504aabd929ba00",
- "7528187314062b0edb8092b5fcc37151",
- "26e16ce274ad58caaa14d22608269a4c",
- "41a256d3c9e847c0a6ac1a4fbaf6309e",
- "9ccbe74a9442ca956d843d6bd5adf979",
- "7a84557597d9cc81ddfa281ae5048d68",
- "6bdb289ec2f3c96cdfa79b6974e6d15a",
- "ec047748636d4358226283e11a78e045",
- "f59db2dda566162a56c85936ac0f4696"
- ],
- [
- "6eebe7d888434023a1488dcac80682c8",
- "084e592524430a857f4701a673adb261",
- "eab8ac90085d47e06d99c0a64e33ae30",
- "bfa23313469131cafb9b13c763ba50b5",
- "60eab4f73f6ded7b7011486b38e45939",
- "566cc395bf9042e5038fb6a694982189",
- "9ea48b0edc28d7f3cf2abbcdb454deb6",
- "9cc6602c43ac034f563a8e62105a04d7",
- "b859e87af729a0cd2729a64c716b1326",
- "fe480838d15ece9eaf20c8b7de0c276b",
- "464e7358905e0eee4f654308ce549104"
- ]
- ],
- "prep_messages": [
- "4b7dc5c1b2a08aec5dcfc13de800559b"
- ],
- "prep_shares": [
- [
- "e80c098526d9321dd0801f97a648722016fa117f10cb2b062fc5fb1e55705894007f838333ef348c6306e141369bd88d123c66d2faeb132e330a73882c38765d425847bd86e5f784b3348ee4840c5df103b49f04c4dcca4667abb956187da58c91c946d9d5fdf496d95428f8a625dddfc8b7bb469397ebd4b177f902896febdaac39a8d9ec0aa1a24132036c2430929c",
- "4f6d4137ddffd58b243b8f845a1684550b240ea3e91a68335f717b83056e9b45c5e62d7a24da54147fcb9260d023cb7f9c8d036f0100f5fea0ce22f49e3d7672bc83fd5c724f2684f3442e8c5291c41509151808d1da447cddc3fe11cf5cd8d7fe662cf035eff88b583f6b32499b332aa6dee37947ef482e15fcb3a7f04b20813162d162b9bf30eee4953b6fdabd10f1",
- "ca85b543fc26f756ef4351e4fea0098a73787eeab8b613029af310882b7e87d28fc5502fd76bd704626d9f0f662e531feaf1fa912cc209de6541401d8508a4788d92e549f58241334cfa29abc1fb80a28ae61d7a4060d9582e3e20f182e4519ab1bb9547c545aafc21416e779856c80cf3690155119111aebf3800757989229e4966453f7aa269163b272848de80227f"
- ]
- ],
- "public_share": "ac39a8d9ec0aa1a24132036c2430929c3162d162b9bf30eee4953b6fdabd10f14966453f7aa269163b272848de80227f",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
- }
- ],
- "shares": 3,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_0.json
deleted file mode 100644
index a7178fcfee..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_0.json
+++ /dev/null
@@ -1,194 +0,0 @@
-{
- "agg_param": null,
- "agg_result": [
- 256,
- 257,
- 258,
- 259,
- 260,
- 261,
- 262,
- 263,
- 264,
- 265
- ],
- "agg_shares": [
- "cdeb52d4615d1c718ef21a6560939efcb5024c89ea9b0f0018302087c0e978b5b5c84c8c4f217b14584cc3939963f56a2718c17af81d1f85129347fc73b2548262e047a67c3e0583eeef7c4a98a5da4ccdb558491081a00a8de5a46b8c2f299bc69162a7411b3ecf2b47670db337083dc50b8fc6d5c5d21da52fc7f538166b0e4564edd8fbb75bc8c4fdd0c02be2b6d11bc4a159297b72e2c635a9250feb2445",
- "3415ad2b9ea2e38e550de59a9f6c61034dfeb3761564f0ffcbcfdf783f16874a4e38b373b0de84eb8bb33c6c669c0a95dde83e8507e2e07ad16cb8038c4dab7da320b85983c1fa7cf50f83b5675a25b3394ba7b6ef7e5ff5561a5b9473d0d664416f9d58bee4c130b8b898f24cc8f7c243f570392a3a2de23ed0380ac7e994f1c49c12270448a4371f022f3fd41d492eef3c5ea6d6848d1d1dca56daf014dbba"
- ],
- "bits": 8,
- "chunk_length": 9,
- "length": 10,
- "prep": [
- {
- "input_shares": [
- "2451f59efba2edc493c9246ff1f0e0a7f8f6f22ee46e662c899e485d7ce288d6becdfee804a39618972fbaa595eeec25423e412cbe51d44a62747de627630302368ec3535a2545a2799e8a0b9a144c811158dda278865d834b34fbe77ad11dbb9fdcf0637c24e10d5ab36d03cdc5f6b95e400a0a81608d96c25733c376376de3927c3570e8ab671358a1686d0c44ac938368d5621cff66585454ef124daa5f18efd7e791a4bcb11caf74b378e2c4feff3e5bad16e7c3fab987eb4d4a0c675bb4f4e70e1373fb00a5dd30a1118355c20e2e4c3700be3d3c1cf25d3e4a729836ba564aa074f99be0d23d4cc0dc9f263c986988e0d16a3d28c262d34f220b1ed127cddea3e2a1bd075c653d4b6f1c3d35e25d2804e7960250dea42dc4a52c9545bedc182ee8391b4c6849366af8e15f30bd06872e5ed651ef7db0b0c442886de32eeeeacc5f2dfe87f9375b4774153fc9e442105b5f8e452e80874c84131400d4d588a1a5d94bac9e68dbf917ef6405b0bc13fa89daf46f84405aedb166ac93f6545256b1da6ac65e01d580bb26eef82c34b9d728fc0c96ff898ed46bd289abbec9917397552ebf6d1eb3f916f69ee9f80e9466512bff70af2d8f3a9ed599f24e33550a09304e1b4f51948e2d8cbf5a1bb14455b1786ae3af4670111bc3983293ad9ae029128efd86d0a05cb3f442b43f466cec5cc9c4989bf5a29eb5c2401bc8bba0d5b7487bc0bf010c968fe76e3a9924459dce6704528d56540081240ed0d2f301a8c9baca5c183b1b5c3a9c03dce5036926d06e1470c2e63d15fdc3a61056154fca9439c595098ff3794c7d7e62af5e3139b43e22a0f8864c254a069a083604762d77ea000177a7b908efe27f6e00db7ea25f573734af803044fb2dc333ed9ad589d7677e23614143fa6836d68ed311dcedf0ea031688b2cf8c5248f21be444f1c61b050a0ab7dca04992673afb737bd27526a72dda3b03dad4d3b0bb81f0887ee6f25ec4cf35d58ea5f085e97609cfb6a8e97d84fdf8755b8e81ff29614bf1b03bcd2b8d9ab06dc4d60785f83eb6ee4573859223214ecdad734d114e15e1971a8b82222910fd041a1123a4e792a9239f99252de3e3e8d5bb209e2c9bda506a79853c482546940364a8246392fb5e18e85847458445fe3a970b29db6d3d0e4a806cfec7c8538f24896d2d10669113f2b724161d2007ee75c0b651f4934046142b04b2015212997c609625bbeb81b9fa0249c167196557c08ae9ea2defcf7859eed4d35b2183c628cb82fe01255e558e7c8b13bded6ba43ed8b92f6ba7879b39932468260c5768ca0909aae899ad1252c5dbcd741d971f179bc36e88a0a10981f73202cb25db324da405fdd5ca5331431afe362c5f933b3c1216c3e19140cd27f7c2ef67898887856a46a518a3afec78ee0d9dce778289a38d2df906932c40019afadab12fe7d0695316e5a3c1e38aa630a44bc8cc01a5a8cae060b7de435e54963b9354182d64e340ec9dc3e37f8b2bbaaab23608b86827991df4367839f443c160c1eb77f41159f69592c3eb37c21a521afcd34036a13a145e9cb1039704b8e523359ea5c3a50f705118ea7d8b1063eb85bfcdc941e0235579e97856ee6f6bfe9c4d0d161b5662de26a2fbddc530ce918a98514903c63a3476d6ebe68e2503e6bf255691fbd8a006e9c77f5a4ad9e3e8d21a56bc4f7bc90d61ebb31eaa4dce48eb9a8069a584ae35266a4bc4af970860d2e9a0df7b87e8fc8b597e73a85d8eeb91def6057d7a77e8f859ee9ee07ef2fb2260660e59ee16458eafbd7bab979ed9bf72c1c27cadc9011f563aeed9a4b2f09ce5455857bcf3acbe0e1cf15537594469c777a885ad24ac5a8c894a8257c5212fb46184ad7f280bc25600129b25bf941460fcdd2e45a0216f1f2fec84d4792a15f877d15c649991ef998621a50a04251257ed6ccd803fdbc83ce4b5c4d7e8ee4487848768384e0b3970ec899dfb423560e755c4716deb3e188ca780cc7a97e8fb80076e9c44c6b7575725253ae4605844c3748bf90c14f17ee80a42fea450c05eb1f251eb09855f2ab368047d68cd7f4b8898d0113d52117375eed77707e7abff8554dc7da30cca674ac587198c0f165a47a5db79e9cc1c7bda9cdc36b94f14141a307850062f4d7208b8c612691699e3e3c16c3fc2dc6604e0fcb27acd6b5d326d2663a3f819589176c70423bc4d37d8c2a17e97468cf923a5388eb0d1de61358e9651a7e76b033d32d6c84e7ed5831a990b46e8228b6ef120643049645b82e100a7ed6ddd2ebfe2dcbd8b0e7ac1e5ee021d4279f164acc47875ade2c0acff5dbbf3a6eb0e8601632c926780be1660270420aa02c99fb39af1852b09904791e90cfa1f02aec0ab2de111524394819527819e52d495196ab3aff1e323dfec07af91e18b9a04e37552a23b13177bdcfc64ec7108e5e9b3679ccdf6b1e998e2bbcd5fbbbebf5ad8008e727cae6499cc06aa03809947e298683a4340f51d6eecad38d0a7a5437dd6e72bce6543b81fd3a438d71e232845cdb403f1011295f9aee5e33352b86e92343985884284c9646da13545f37b9d6da7d0cf902c19a5ca1f4f1818a2c2644807fcc54be35c29f96fb4fea5efdc88b270f1c5504bd8ba558834786020cc2f03ab5c56eaea38532b9faf6208f57d970b2e5ff92872713c9e0ad07b26e72dca6f9a9c02bad6c9db4d1d738f306292f14415d2856c2b073c5d8faf89e9713ceb375b6eefabc240bf6c6bf39cafb99993767dbaf5ee5f4b3f93e638e904fb55f443312c145b809fd203b5b3a16bd229b952e100bbfc0e49bbd05d54c3e5fa1a44fe55de16cfa52f3b169e0bfe95b1b8b6367f9309adfe3df079104fd720d46d772def3c0534d73615071fa22a79af875f796478d2f599dbb4c1ed303132333435363738393a3b3c3d3e3f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
- ],
- "measurement": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "9aa31b9c201fb42526a6b32120318aa9",
- "e8551983a3deafaafe0f608295f8d291",
- "3eed6ed96f607eb1be6e96868876fc78",
- "65b295d3525f0ad74886c2fe7b3b1cd6",
- "794a6d37d41457d6f04fd418888cf36e",
- "483cc86d052be058d0a1e12384ba0d89",
- "9c85cb376b5ebfeffb6c22af3bbd02bf",
- "9c0385979cecf00983ba97fc12b2235a",
- "c7cbf9f2533dc942eca94540b9a0e745",
- "0f418bc80d2926f6ec11e3615a4e0c17"
- ],
- [
- "675ce463dfe04bdabd594cdedfce7556",
- "1aaae67c5c215055e5ef9f7d6a072d6e",
- "c5129126909f814e2591697977890387",
- "9f4d6a2cada0f5289b793d0184c4e329",
- "8cb592c82beba829f3af2be777730c91",
- "bec33792fad41fa7135e1edc7b45f276",
- "6b7a34c894a14010e892dd50c442fd40",
- "6cfc7a6863130ff660456803ed4ddca5",
- "4234060dacc236bdf755babf465f18ba",
- "fbbe7437f2d6d909f7ed1c9ea5b1f3e8"
- ]
- ],
- "prep_messages": [
- "db085315822777376b4d0f962d8f06d9"
- ],
- "prep_shares": [
- [
- "e6a4fe7264f95c384446bd51db14f78e7f4133afed0604aeb3b87125fc076c7447d795723adfe93d85f9fe2993c52420e45694fd2ec164a54a7267ee5efc8cb40b6659ac81f2e850786218bcec469ec4f7bb28e875d75ee98d54d566186c61c35448a50cb11e195d886622861a78bbb74325b7972e7b4c47f0e2e10a15d7a33c3daecb2dfc507b1b6676c1e9bfc52a4873f408a5788e7b77ce6943e67f3f457280544d93b81b08e427f699ba54adcbb0ffab83366d9b336846c0c989f0bc25bdd14683f1a85e844b9dbac26daae84cc8d57ef6b0c340798ac5ade63150e8d7a9673b64d798a97cf2715f399fd371e342c1ad50e28431f54180ef63ad7dd21f3e5d8d67159cacfd56f5d99c39d53047c8d7bf11ad83a2e3e569e1393b12d87d01701fa71b50b51e092ca6b797bb97890efb6327f1c4e488663dca5f00675c2af7368a9ab95b3c4e9e1a8dd5430d336833",
- "1b5b018d9b06a3c79fb942ae24eb087131693625114418115cb3e54a45056eabd0f6e371501957e00796db78ea8f3388eb8345e938f5fbdd8b24c3a968276d7c457ff43ce93631942f823f5bb9c6d1335b8022e804072711cb8fa5fb3afb209e696c9cac47da44cdc3eb3874eb0d8c89692408b463df12bb2d6e8193d5829cce221e486a579b91cd10a0fb38fec7214a9008d574ba32615f6215aef827a2962a31df892814bd8b8f828d029f07f6acf490e7ecd3377f10b86ec2d5741ba37a3a9522b897e840e315a614a89d0bcf8296bdd45e330eaf3f34b3ce4e1dd41306eae92147fc6676eedff2cb239581f46750df341390e066dabb01ef6362694f923d5a65dbc5252a8da8702a979aca3e211af7124485c1c7dc68f6fb1bdfb9a4d0d993cece17c818d8fb1151f1ef1b32745f09c155f42259af588b424c1dafe8d0e90a3dfc6f55bb428773ce15071cb720fb"
- ]
- ],
- "public_share": "368a9ab95b3c4e9e1a8dd5430d3368330a3dfc6f55bb428773ce15071cb720fb",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- },
- {
- "input_shares": [
- "2551f59efba2edc493c9246ff1f0e0a7f8f6f22ee46e662c899e485d7ce288d6becdfee804a39618972fbaa595eeec25423e412cbe51d44a62747de627630302368ec3535a2545a2799e8a0b9a144c811158dda278865d834b34fbe77ad11dbb9fdcf0637c24e10d5ab36d03cdc5f6b95e400a0a81608d96c25733c376376de3927c3570e8ab671358a1686d0c44ac938368d5621cff66585454ef124daa5f18efd7e791a4bcb11caf74b378e2c4feff3e5bad16e7c3fab987eb4d4a0c675bb4f4e70e1373fb00a5dd30a1118355c20e2e4c3700be3d3c1cf25d3e4a729836ba564aa074f99be0d23d4cc0dc9f263c986988e0d16a3d28c262d34f220b1ed127cedea3e2a1bd075c653d4b6f1c3d35e25c2804e7960250dea42dc4a52c9545bedc182ee8391b4c6849366af8e15f30bd06872e5ed651ef7db0b0c442886de32eeeeacc5f2dfe87f9375b4774153fc9e442105b5f8e452e80874c84131400d4d588a1a5d94bac9e68dbf917ef6405b0bc13fa89daf46f84405aedb166ac93f6545256b1da6ac65e01d580bb26eef82c34b8d728fc0c96ff898ed46bd289abbec9917397552ebf6d1eb3f916f69ee9f80e9466512bff70af2d8f3a9ed599f24e33550a09304e1b4f51948e2d8cbf5a1bb14455b1786ae3af4670111bc3983293ad9ae029128efd86d0a05cb3f442b43f466cec5cc9c4989bf5a29eb5c2401bc8bba1d5b7487bc0bf010c968fe76e3a9924459dce6704528d56540081240ed0d2f300a8c9baca5c183b1b5c3a9c03dce5036926d06e1470c2e63d15fdc3a61056154fca9439c595098ff3794c7d7e62af5e3139b43e22a0f8864c254a069a083604762d77ea000177a7b908efe27f6e00db7ea25f573734af803044fb2dc333ed9ad589d7677e23614143fa6836d68ed311dcedf0ea031688b2cf8c5248f21be444f0c61b050a0ab7dca04992673afb737bd27526a72dda3b03dad4d3b0bb81f0887ee6f25ec4cf35d58ea5f085e97609cfb6a8e97d84fdf8755b8e81ff29614bf1b03bcd2b8d9ab06dc4d60785f83eb6ee4573859223214ecdad734d114e15e1971b8b82222910fd041a1123a4e792a9239e99252de3e3e8d5bb209e2c9bda506a78853c482546940364a8246392fb5e18e85847458445fe3a970b29db6d3d0e4a806cfec7c8538f24896d2d10669113f2b724161d2007ee75c0b651f4934046142b04b2015212997c609625bbeb81b9fa0249c167196557c08ae9ea2defcf7859eed4d35b2183c628cb82fe01255e558e7b8b13bded6ba43ed8b92f6ba7879b39922468260c5768ca0909aae899ad1252c5dbcd741d971f179bc36e88a0a10981f73202cb25db324da405fdd5ca5331431afe362c5f933b3c1216c3e19140cd27f7c2ef67898887856a46a518a3afec78ee0d9dce778289a38d2df906932c40019bfadab12fe7d0695316e5a3c1e38aa630a44bc8cc01a5a8cae060b7de435e54963b9354182d64e340ec9dc3e37f8b2bb9aab23608b86827991df4367839f443c160c1eb77f41159f69592c3eb37c21a521afcd34036a13a145e9cb1039704b8e523359ea5c3a50f705118ea7d8b1063eb85bfcdc941e0235579e97856ee6f6bfe9c4d0d161b5662de26a2fbddc530ce918a98514903c63a3476d6ebe68e2503e6bf255691fbd8a006e9c77f5a4ad9e3e7d21a56bc4f7bc90d61ebb31eaa4dce48eb9a8069a584ae35266a4bc4af970860d2e9a0df7b87e8fc8b597e73a85d8eeb91def6057d7a77e8f859ee9ee07ef2fb2260660e59ee16458eafbd7bab979ed9bf72c1c27cadc9011f563aeed9a4b2f09ce5455857bcf3acbe0e1cf15537594469c777a885ad24ac5a8c894a8257c5212fb46184ad7f280bc25600129b25bf941460fcdd2e45a0216f1f2fec84d4792a15f877d15c649991ef998621a50a04251257ed6ccd803fdbc83ce4b5c4d7e8ee4487848768384e0b3970ec899dfb423560e755c4716deb3e188ca780cc7a97e8fb80076e9c44c6b7575725253ae4605844c3748bf90c14f17ee80a42fea450c05eb1f251eb09855f2ab368047d68cd7f4b8898d0113d52117375eed77707e7abff8554dc7da30cca674ac587198c0f165a47a5db79e9cc1c7bda9cdc36b94f14141a307850062f4d7208b8c612691699e3e3c16c3fc2dc6604e0fcb27acd6b5d326d2663a3f819589176c70423bc4d42a21c0a30addfe4b4176740f9a418eca631cda9a8b94d20c7f9b834ed87751464dc5e5b446d920312003e4673b48c6c12b407af1ed90002507883f78d166f0b90bc14ed77d4aec6220cdd51948cdad29ab70513aadccd0e3c8c8108d3b0722602d9612aa6feb323a4ff3e8fe0e3d5701467491acdd3c71c34bc019047647779922216ccd61c47958461e3017adf446c4bd2ab7fbf70e41419679f6a9b3fa4c9aa5e9ef8469ace0d88bc35a3374f462573d2ba24b712359ef36e413006a9883bfa4fad43d89c7f1732725e3cad482d17a9499e1fb0f57d1ca93cafa7fd6d654a70cd7318bd7ace30e981217317105bcfe5e33352b86e92343985884284c9646d966beb8aca87d44e15dcce24aeb08312091cd98e6b52e2525409c58438f00131d33ce09fde0343f84db73369954f2d77a3a559189bc4dfd7e7c043b1364b36550595f624483c4eccccb1c4958a9284e43522dcc72ad9b01162d964605eab990dd1ddd25796f55991e1201f22526117662c0cad518f191effe5608b444b9e8973f5a11a8c154bc501bc47bb4fb5832d67f4c5ea5c221e64ff88ff5d5117aadac704a8b94beb036e87fc9a9462c355231b9bbe8a9122f12390073600f2d7f6262f1758eced79619900cad1910286c5bae553c6525c63c52ca97bf452957c5fc1a7d695dcb5ed0cf0004454c528d63960cd303132333435363738393a3b3c3d3e3f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
- ],
- "measurement": [
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1
- ],
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "9ba31b9c201fb42526a6b32120318aa9",
- "e8551983a3deafaafe0f608295f8d291",
- "3ded6ed96f607eb1be6e96868876fc78",
- "63b295d3525f0ad74886c2fe7b3b1cd6",
- "764a6d37d41457d6f04fd418888cf36e",
- "443cc86d052be058d0a1e12384ba0d89",
- "9785cb376b5ebfeffb6c22af3bbd02bf",
- "960385979cecf00983ba97fc12b2235a",
- "c0cbf9f2533dc942eca94540b9a0e745",
- "07418bc80d2926f6ec11e3615a4e0c17"
- ],
- [
- "675ce463dfe04bdabd594cdedfce7556",
- "1aaae67c5c215055e5ef9f7d6a072d6e",
- "c5129126909f814e2591697977890387",
- "9f4d6a2cada0f5289b793d0184c4e329",
- "8cb592c82beba829f3af2be777730c91",
- "bec33792fad41fa7135e1edc7b45f276",
- "6b7a34c894a14010e892dd50c442fd40",
- "6cfc7a6863130ff660456803ed4ddca5",
- "4234060dacc236bdf755babf465f18ba",
- "fbbe7437f2d6d909f7ed1c9ea5b1f3e8"
- ]
- ],
- "prep_messages": [
- "fdecd6d197e824492dd550fcdd0aa3c7"
- ],
- "prep_shares": [
- [
- "e6a4fe7264f95c384446bd51db14f78eec654b5beb7d60677c0b8385ca51a5bf896c79a069b04f339fdcb675885a26f533ec0d6e805beef6d7683a8ecdfa46cb87fdbc532efa5b1041347ed94f54fbca15041d013729d5eb78dcb1a1c293e0035448a50cb11e195d886622861a78bbb7bccc68d521fac002ece757cc5d82afb3b0f9f8766a1714047b50417a8e7f63eacf222c675bdf1d3e8362806ef5f9c16c446a1e5e06ce539aa300bc68c837c9207c5dbc7d85f896fb1be725e461ceacd303716a2cd8005e370a8ac1062d966b5c1499813d0dc63d697c4fd44dcfe81b3cfc37952de43649650c52ca9f2044fd3dfc42cd08bf0659e6a7facee2468ad1b07903a933ec3cbd06a5f81461e434449c32ef6678f3c8fd250c0b3318e80235144a96f07af2169dfddb503b38a2039f80f6bdfbbec6b3ad1025a43a90249221d20e627a73e2ed92bf1920574f42775675",
- "1b5b018d9b06a3c79fb942ae24eb0871aba638b677efec2418d7921020c44ff8d0f6e371501957e00796db78ea8f338813d41fd058418e6056a93bb2785cec1d457ff43ce93631942f823f5bb9c6d133fbfbf9d10fa7922dccd1e570b0246775696c9cac47da44cdc3eb3874eb0d8c89fcdfd722a57116825749c8972129304c221e486a579b91cd10a0fb38fec7214af0fe63f4a24e9e189e180a8aaed3b22931df892814bd8b8f828d029f07f6acf402eb7c22aea07b55e871ebdf6475ae509522b897e840e315a614a89d0bcf8296c0b0d5b745f277689643e3da46c09a1ce92147fc6676eedff2cb239581f46750fa1947870c81f9d565f51ed7e09d86dc5a65dbc5252a8da8702a979aca3e211ae9def20e5f2fa85d16e3ccb0a917510793cece17c818d8fb1151f1ef1b32745f09c155f42259af588b424c1dafe8d0e90a3dfc6f55bb428773ce15071cb720fb"
- ]
- ],
- "public_share": "0e627a73e2ed92bf1920574f427756750a3dfc6f55bb428773ce15071cb720fb",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- },
- {
- "input_shares": [
- "2551f59efba2edc493c9246ff1f0e0a7f9f6f22ee46e662c899e485d7ce288d6bfcdfee804a39618972fbaa595eeec25433e412cbe51d44a62747de627630302378ec3535a2545a2799e8a0b9a144c811258dda278865d834b34fbe77ad11dbba0dcf0637c24e10d5ab36d03cdc5f6b95f400a0a81608d96c25733c376376de3927c3570e8ab671358a1686d0c44ac938468d5621cff66585454ef124daa5f18f0d7e791a4bcb11caf74b378e2c4feff3f5bad16e7c3fab987eb4d4a0c675bb4f5e70e1373fb00a5dd30a1118355c20e2f4c3700be3d3c1cf25d3e4a729836ba574aa074f99be0d23d4cc0dc9f263c986a88e0d16a3d28c262d34f220b1ed127cedea3e2a1bd075c653d4b6f1c3d35e25d2804e7960250dea42dc4a52c9545bedd182ee8391b4c6849366af8e15f30bd07872e5ed651ef7db0b0c442886de32eefeacc5f2dfe87f9375b4774153fc9e443105b5f8e452e80874c84131400d4d589a1a5d94bac9e68dbf917ef6405b0bc14fa89daf46f84405aedb166ac93f6545256b1da6ac65e01d580bb26eef82c34b9d728fc0c96ff898ed46bd289abbec9927397552ebf6d1eb3f916f69ee9f80e9566512bff70af2d8f3a9ed599f24e33560a09304e1b4f51948e2d8cbf5a1bb14555b1786ae3af4670111bc3983293ad9be029128efd86d0a05cb3f442b43f466dec5cc9c4989bf5a29eb5c2401bc8bba1d5b7487bc0bf010c968fe76e3a9924469dce6704528d56540081240ed0d2f301a8c9baca5c183b1b5c3a9c03dce5036a26d06e1470c2e63d15fdc3a610561550ca9439c595098ff3794c7d7e62af5e3239b43e22a0f8864c254a069a083604772d77ea000177a7b908efe27f6e00db7fa25f573734af803044fb2dc333ed9ad589d7677e23614143fa6836d68ed311ddedf0ea031688b2cf8c5248f21be444f1c61b050a0ab7dca04992673afb737bd37526a72dda3b03dad4d3b0bb81f0887fe6f25ec4cf35d58ea5f085e97609cfb7a8e97d84fdf8755b8e81ff29614bf1b13bcd2b8d9ab06dc4d60785f83eb6ee4673859223214ecdad734d114e15e1971b8b82222910fd041a1123a4e792a9239f99252de3e3e8d5bb209e2c9bda506a79853c482546940364a8246392fb5e18e95847458445fe3a970b29db6d3d0e4a816cfec7c8538f24896d2d10669113f2b824161d2007ee75c0b651f4934046142c04b2015212997c609625bbeb81b9fa0349c167196557c08ae9ea2defcf7859eed4d35b2183c628cb82fe01255e558e7c8b13bded6ba43ed8b92f6ba7879b39932468260c5768ca0909aae899ad1252c6dbcd741d971f179bc36e88a0a10981f83202cb25db324da405fdd5ca5331431bfe362c5f933b3c1216c3e19140cd27f8c2ef67898887856a46a518a3afec78ef0d9dce778289a38d2df906932c40019bfadab12fe7d0695316e5a3c1e38aa631a44bc8cc01a5a8cae060b7de435e54973b9354182d64e340ec9dc3e37f8b2bbaaab23608b86827991df4367839f443c260c1eb77f41159f69592c3eb37c21a531afcd34036a13a145e9cb1039704b8e623359ea5c3a50f705118ea7d8b1063ec85bfcdc941e0235579e97856ee6f6bfe9c4d0d161b5662de26a2fbddc530ce928a98514903c63a3476d6ebe68e2503e7bf255691fbd8a006e9c77f5a4ad9e3e8d21a56bc4f7bc90d61ebb31eaa4dce49eb9a8069a584ae35266a4bc4af970861d2e9a0df7b87e8fc8b597e73a85d8eec91def6057d7a77e8f859ee9ee07ef2fc2260660e59ee16458eafbd7bab979ed9bf72c1c27cadc9011f563aeed9a4b2f09ce5455857bcf3acbe0e1cf15537594469c777a885ad24ac5a8c894a8257c5212fb46184ad7f280bc25600129b25bf941460fcdd2e45a0216f1f2fec84d4792a15f877d15c649991ef998621a50a04251257ed6ccd803fdbc83ce4b5c4d7e8ee4487848768384e0b3970ec899dfb423560e755c4716deb3e188ca780cc7a97e8fb80076e9c44c6b7575725253ae4605844c3748bf90c14f17ee80a42fea450c05eb1f251eb09855f2ab368047d68cd7f4b8898d0113d52117375eed77707e7abff8554dc7da30cca674ac587198c0f165a47a5db79e9cc1c7bda9cdc36b94f14141a307850062f4d7208b8c612691699e3e3c16c3fc2dc6604e0fcb27acd6b5d326d2663a3f819589176c70423bc4dc97f402ea5053f2aa068d42c371d327339bd8637472eb9be88e409688a53bff392a8891c96c7804998d761fcf34dbf8da8cb17567f75ab4be29ecb6c33c85bf572b645bb7b226e4b99ccc0d959e6d809ec45b70cefe5ada611ea14962c9788d3e15100872669baf3c07a424cc205db97c0e2f72880a40a48d3820f89a16c7ee9dbc44bea18d787e0b730093a7b1fe4f9fd3e50128c61f6d4179fde88b02629629bf9f56f15abe3860ad2c99eaee9eba2310ca898fee5103f7bcb11ec9f4154007cf7d2b51a173331576526665d9f90879a2122b2bdef3a2cff68e57b146ae6d99a4e247d0daa693ef0a07aadc1a4b25ce5e33352b86e92343985884284c9646d0f8ec766552f75092a8b613870386a8b77901f01cddd76b4761e74519b24b851a570b5de8ca954b2c7df0fb314b6fa550e8e49713a28358e399afb3b9199496b229bc55644ee8e4772f1e00dc53886ade4932acee5cfd079707bd1d204c58360f26434fb158b53c1c4a51b65703f123f8090fe42dc48dbd3469a7d4bf1958203adffe46dd39084b66c789517b4438ed9415946ca552d523fa6c71e3302c3552f140d62d41cf3580e5e8500674cbb7d9ddd849d1ddb1d48ef7fd92f363e5e5b6a95b0c67b37e7e5e6a4dec9d8d56e577562eecec955cb6f9925c81cc165634018ab142c519ddd54f358356cee2ba50840303132333435363738393a3b3c3d3e3f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
- ],
- "measurement": [
- 255,
- 255,
- 255,
- 255,
- 255,
- 255,
- 255,
- 255,
- 255,
- 255
- ],
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "99a41b9c201fb42526a6b32120318aa9",
- "e6561983a3deafaafe0f608295f8d291",
- "3bee6ed96f607eb1be6e96868876fc78",
- "61b395d3525f0ad74886c2fe7b3b1cd6",
- "744b6d37d41457d6f04fd418888cf36e",
- "423dc86d052be058d0a1e12384ba0d89",
- "9586cb376b5ebfeffb6c22af3bbd02bf",
- "940485979cecf00983ba97fc12b2235a",
- "beccf9f2533dc942eca94540b9a0e745",
- "05428bc80d2926f6ec11e3615a4e0c17"
- ],
- [
- "675ce463dfe04bdabd594cdedfce7556",
- "1aaae67c5c215055e5ef9f7d6a072d6e",
- "c5129126909f814e2591697977890387",
- "9f4d6a2cada0f5289b793d0184c4e329",
- "8cb592c82beba829f3af2be777730c91",
- "bec33792fad41fa7135e1edc7b45f276",
- "6b7a34c894a14010e892dd50c442fd40",
- "6cfc7a6863130ff660456803ed4ddca5",
- "4234060dacc236bdf755babf465f18ba",
- "fbbe7437f2d6d909f7ed1c9ea5b1f3e8"
- ]
- ],
- "prep_messages": [
- "190c0ef07d6f2cbd1bed12d71b5f118d"
- ],
- "prep_shares": [
- [
- "e6a4fe7264f95c384446bd51db14f78ef1ffdfc96013014baff7bd0684b8ff3360f6a2a23b1d7b71796b845eeb21e7d1682128dc8b87837803fec0e3bd6c548d5cc9c041a482cbfc38120743a2f1a0985053eaeccc339c56c2edf76451e22c9a1bca6ab2181850f44d904964d1f227a970e70b59328028ddafdb1649a8c4f1f7cbeb366e42f8603a7b627f7519f25617a33726ede06ab438714b4bd3cda025dc2bcab64974eb02b9e2a23bf0cab4e5ef1e87bb1a72767098c768a20e1090a712ed38c1e8803fd18181cc0069355b40f5f98ff3cbd2b31022df719d9c660e7d5bab239819730ad9165a38641379444093ba148996166ccf5e2826bddb7a7dc8eda4dd5928b12e1ea715538788804b5ce231dfc98ff45027ff8cb1f92007f2339621201a7dc483c83bb6df082105cb5f5d9eda1f847b3d43b4e16502062d5a4a158f651439d7666c683a6283d308c91b25",
- "1b5b018d9b06a3c79fb942ae24eb08714d70b996c916bc83063fda0f9ec82780d0f6e371501957e00796db78ea8f338874640cdcd2ca1496ea55d62aa3709498457ff43ce93631942f823f5bb9c6d133b1f04db02cc745245af6a31e4dfe912a696c9cac47da44cdc3eb3874eb0d8c89cc603d2ceec1678996fe311424b56e65221e486a579b91cd10a0fb38fec7214a46c9ce7f890afed4efa31fb5ca8766ae31df892814bd8b8f828d029f07f6acf47620063e9fa98ab947b376e068b9be689522b897e840e315a614a89d0bcf8296332affc2e6b52204d1d7994260e415c6e92147fc6676eedff2cb239581f4675066213f3b302497abbf10c1729131a0125a65dbc5252a8da8702a979aca3e211afb99a0edb76c92f2bd5941c6071db19d93cece17c818d8fb1151f1ef1b32745f09c155f42259af588b424c1dafe8d0e90a3dfc6f55bb428773ce15071cb720fb"
- ]
- ],
- "public_share": "8f651439d7666c683a6283d308c91b250a3dfc6f55bb428773ce15071cb720fb",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_1.json
deleted file mode 100644
index af95aac5a0..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_1.json
+++ /dev/null
@@ -1,146 +0,0 @@
-{
- "agg_param": null,
- "agg_result": [
- 45328,
- 76286,
- 26980
- ],
- "agg_shares": [
- "598a4207618eab7bd108c110106e84cd9498b18b79cace4b383274cef0ab280eae74b07f9a7f087a89a4f51f3adb97ed",
- "ea61abdf14b8477f6de1b47a18ac778ad0149cb235e666ccce92a9246a2858403e5903013ab179dcf6719d10fccdf589",
- "cfc412198ab90c0589158a74d7e503a89b7cb3c1504fcae7dc3ae20ca52b7fb17a9b4c7f2bcf7da947e96ccfc9567288"
- ],
- "bits": 16,
- "chunk_length": 7,
- "length": 3,
- "prep": [
- {
- "input_shares": [
- "db3fe5357f56f6cfe9a0a34ed08e231765b423d5670741c151f7bc28cb15c4c8678df838b6ef52d74c5bb5e8c8c607b2674c024da705b558163e3127ae09f4a5c061dc6129d71755ec77b5d5a2fc088541fa612bf1273d94718e0d28b654ea9524148bf910a5c6d55b596e323d4f55ab62b0851e0985987ea39cf500bfd4d5faed37f519120b574aead76d706e149c54b6e790f7c35553f830f67553ff3f08db0f5d8a2e157f9c1ef6eedcb845a19fffd3f9c6e705b035c95f3ebe51219a91c6ffff33c52b8fd7e90417636bb443c98c3e6933b1599c09151095fff99d7af43d327fcf2afdc50144e5b8f5b1ff1f8cc8d442613dc76dd48100dd4637b38fc5fa239333c6d1e2bec2132a3e3cf5fd11f7e823fbf275071a71535740ac64de88b83ba002bd4490de5c7540e454331d46ebb825725b964ecfcc5c3bb076bf57fd819c0bd788b4495da456594503c8f5b618c4713e957a7589b151ead3a27ae80153b0fbc219f5524eec22dc91aa56ed87a71d2b6e6b857ee03a700fb5af5b23513fb73023c2764f74b40f00e44e2e7acd463e7f38c783a898015b51863659502645e7d7fdf14abf76c605d42e523a540f40e816db420d599cea502baa131d6b61b8aed86a09b9f7587e107c6fc9043d72644153b54234146535e9ec25223d293f4a2a4481b5649a7625116aef735ecbbdd9e99076985e1c424e91c29ae231c01f2b12007c81a9b3c72a84522014f4cdcb949bb9850b62b1c9c5d35f0fc3dbf4f637ae85d3082ffd15890041a455a5dd38efca02eb415afcd2c93a2b6ab46c88847f380affbc3a9af4745718044c9f23978026af66871e610e1beee21360fc5ae4f05dd32689328216db3c512fddacefb2713187f4f5069170db246ae0cb13b3b88f8c832d11ae6b26fe6f0f89b9a9056c28ac6160134ab1af4be606a2ca7d1256cfc223c823ae4921ba11aab9e4f8104885b2d17ac7826ad06b0fd0e54397e67179755b29c6d724f3e9d9a6934619ef0bfee72cdcf0031672bb6e55be53d3ef0fccf7beba7dea636eff7fdecee99f60a0bc5d5cb11e24683ca8085cf218a3607c3f5a051c33717f39834435c5c542f42bd9c9d9103173cb11436e2a626e228415924037ee4a4078f0d9a5bd0fef1dc9415740c4b32f51d199d912907a103c7e25928acadfb4dc1e8d32c34b4f0100bfe95feb850e0d7b359aae9a332913d1f8eca0d1cd93dee2f4b75076536037ca2b6bec5003ae89e03db9813d0dd2165bf50a836ca492f05750a3b5fff4d089fc54fdf225aa112d72ab021b0cef1b8d31c852133fae501406668db0cb4c3589934bde5ec218876b0dc4087b61d706234635d5d9065787a21ed895fb7c05902a554f879dae44d0905292815c5ae2338be1faa9249c7a0530623084f3a7c8bdddf0cf0123597127f9416dcad20f71bb98bf0078d9d20d4ae09c46fc1882cae650f48bebfcc443dfd7963c9944f0ce0a9bda91fe8b8f307fb3da48e573224324c35e867599262fa281ee6bc537928747dd4a1370440bda92e28eb5ba088481e476f19e2a03a7c7619eb79e2184afff7bb585319fa6a58dbfb8862f5d193ccfe0e4aeb58c1633d9e983861d4976615b11514160e5d77ed9a3e2179893c65d9de03813d27aec3485d96098764ee1e7779d47850e6b96ba064b4b913da8390416afb16719a38b725d5b27db351049bdb322cfc93a905a108d07e49764eb5f3f66fe8f3aec7580606162636465666768696a6b6c6d6e6f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
- "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
- ],
- "measurement": [
- 10000,
- 32000,
- 9
- ],
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "7e6f6b02cb848e7e3c5840b05acfd699",
- "dda1902ed398efc35ebb269aa58e0d5a",
- "cd03902ade7fad281b8cfc5f1349ddf9"
- ],
- [
- "f9758e4a5c3d6d2a1b4b3c7e5d397d83",
- "9bb1de90bc4c2244e630e3b6780dc86a",
- "15735600bee57d499ed0890554ef5183"
- ],
- [
- "9b4106b3d83d0457705c83d147f7abe2",
- "89299140701aeef79e13f6aee1632a3b",
- "298919d5639ad48d0ea3799a98c7d082"
- ]
- ],
- "prep_messages": [
- "429a80b8b2f73ce00d066d0c0e540cfb"
- ],
- "prep_shares": [
- [
- "574ce7d79da173f0652f7d1e699d5fe756c90210a093e0c893b2b7510374465c35014cdcef24d6044e63ece20db245a982c5a00f16227c6530ade1e5fd4e925f8505da8add8b97fa3216790b11b46ad76bec9b6b3f0c1e9b8284f81f0c83bb690033a6c4a8e962d34b51e27aeaa33a0d41e852a78af96c6dfba1d36364996df4eaaacc993e5633528fb0d106753112ecbfe7fec74ea75d2d1b16267ee1b3d6145e746f19d0840be93d38baa3a5c7d42c6a05311092b4fe05e38aa9e24fb9c99a5aa4bc485752d049703409ccb6656150eeb34048030f19b5353df1e23b376b1c4be2925034d8b7a847690ca7f0c4f338c30b461d9e8c1a1de094fea67efdc4d3da6e96a43cd51241f828f01028e5b0e9",
- "21c1bcbdd38fa9e8d86272f8c66c2b16768d00a79945c6014bb55374174299e4e7967f80f8df630af6f5aac52647e36437d08d0aabfd406b0984557a1a69b28f3706033ed34cde0d6bfd39a81a0fca04117cd7ac37f06815b6dc1a356454d669b0e7871238066b280f7c09e0365214235dcd39dfdf6e46ad632d50101029ff490910f79b754d99088059cf1d5da8a791b1a51d8d96fe428bac8f547dc2e9632c4e00b3a6e95d36d03d83969de2989c120aa3c54040bc7f49f910df6c5e4003721a03a3f1d743c457d0cbadbc0bd25ca7f464f404a1f39f852872314ca44ea35a32c150fc25094cd2147739d1a1e03e8f6e636170867687f1c511dbb936fb521b6639ebc145f03b6d1751fcdf14c5108e",
- "89f25b6a8ecee226a56d10e9cff57402c3198e7629d8c4152d9319172f0df07727e57ad2e170a0a32cf748f9dc0fe45597d26743a7254aebceb106f0f172a5f2aecf563787471334096bb202a07696b7e0cf22d7dda51e1cf0fcc3d0d5d0a9f4c7ea8999a3f4edb4bd7d3ecb26f2137fe9d443f34248265c25a12290866130c9ccd2dd263bce8b78c14ddbc0c94ed85da0c401ac614c789711c0e2db27ad6ef59aabfdbb6bf174fff2358c4a8d6b7e6cd2a0d41883f3563506755a920aaa7695cf35ffecb0b195d01d1d86ee1a015df5de2f145b61ef3bc5fff1634d911a69540c03444dcb256fa982b24cf064dd6e4dffe71f8d5648cf336acd9485f9d70e24f2ad6b4aa14511e7b660c0866f73672a"
- ]
- ],
- "public_share": "da6e96a43cd51241f828f01028e5b0e96639ebc145f03b6d1751fcdf14c5108ef2ad6b4aa14511e7b660c0866f73672a",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
- },
- {
- "input_shares": [
- "db3fe5357f56f6cfe9a0a34ed08e231766b423d5670741c151f7bc28cb15c4c8688df838b6ef52d74c5bb5e8c8c607b2684c024da705b558163e3127ae09f4a5bf61dc6129d71755ec77b5d5a2fc088541fa612bf1273d94718e0d28b654ea9524148bf910a5c6d55b596e323d4f55ab63b0851e0985987ea39cf500bfd4d5faed37f519120b574aead76d706e149c54b6e790f7c35553f830f67553ff3f08db0e5d8a2e157f9c1ef6eedcb845a19fffd4f9c6e705b035c95f3ebe51219a91c6ffff33c52b8fd7e90417636bb443c98c3d6933b1599c09151095fff99d7af43d337fcf2afdc50144e5b8f5b1ff1f8cc8d442613dc76dd48100dd4637b38fc5fa249333c6d1e2bec2132a3e3cf5fd11f7e923fbf275071a71535740ac64de88b83ca002bd4490de5c7540e454331d46ebb925725b964ecfcc5c3bb076bf57fd819d0bd788b4495da456594503c8f5b618c4713e957a7589b151ead3a27ae80153b0fbc219f5524eec22dc91aa56ed87a71e2b6e6b857ee03a700fb5af5b23513fb63023c2764f74b40f00e44e2e7acd463e7f38c783a898015b51863659502645e7d7fdf14abf76c605d42e523a540f40e816db420d599cea502baa131d6b61b8add86a09b9f7587e107c6fc9043d72644053b54234146535e9ec25223d293f4a2a4481b5649a7625116aef735ecbbdd9e99076985e1c424e91c29ae231c01f2b12007c81a9b3c72a84522014f4cdcb949bb9850b62b1c9c5d35f0fc3dbf4f637af85d3082ffd15890041a455a5dd38efc902eb415afcd2c93a2b6ab46c88847f390affbc3a9af4745718044c9f23978027af66871e610e1beee21360fc5ae4f05ed32689328216db3c512fddacefb2713287f4f5069170db246ae0cb13b3b88f8d832d11ae6b26fe6f0f89b9a9056c28ad6160134ab1af4be606a2ca7d1256cfc223c823ae4921ba11aab9e4f8104885b3d17ac7826ad06b0fd0e54397e67179755b29c6d724f3e9d9a6934619ef0bfee72cdcf0031672bb6e55be53d3ef0fccf7beba7dea636eff7fdecee99f60a0bc5d5cb11e24683ca8085cf218a3607c3f5a051c33717f39834435c5c542f42bd9c9d9103173cb11436e2a626e228415924037ee4a4078f0d9a5bd0fef1dc9415740c4b32f51d199d912907a103c7e25928acadfb4dc1e8d32c34b4f0100bfe95feb850e0d7b359aae9a332913d1f8eca0d1cd93dee2f4b75076536037ca2b6bec5003ae89e03db9813d0dd2165bf50a836ca492f05750a3b5fff4d089fc54fdf225aa112d72ab021b0cef1b8d31c852133fae501406668db0cb4c3589934bde5ec218876b0dc4087b61d706234635d5d9065787a21ed895fb7c05902a554f879dae44d0905292815c5ae2338be1faa924d95673e4d904cc4215bfda1c9c0ca55fa38af6b696ef4f1a452d6870c1d82fa311cee716b00a11313a0ba7c4038e5e195b5e1d3502a44d9a9ab1636394821eaf157e6c77316f6e26b98ca81220752396890cce205581aead60bfcc3916a6c2d6d360c7e845e70c8c68e4acb5eb2877a9a7c7619eb79e2184afff7bb585319fa669b151040f5b15cab2d8c3a50379e9d9e8bf1ac6319bc32e489f64793f882d0e3e1906ac04d47eaec15c20c503d007d09d6a9b032d0f9a8b3d95447fcb1d4b7334b95d873a171f876dcc2a62a62af58e10802f88742027d3d27b9d72fea73dc84906d3dde03299dc3e033651406229da606162636465666768696a6b6c6d6e6f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
- "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
- ],
- "measurement": [
- 19342,
- 19615,
- 3061
- ],
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "fc936b02cb848e7e3c5840b05acfd699",
- "7c71902ed398efc35ebb269aa58e0d5a",
- "b90f902ade7fad281b8cfc5f1349ddf9"
- ],
- [
- "f9758e4a5c3d6d2a1b4b3c7e5d397d83",
- "9bb1de90bc4c2244e630e3b6780dc86a",
- "15735600bee57d499ed0890554ef5183"
- ],
- [
- "9b4106b3d83d0457705c83d147f7abe2",
- "89299140701aeef79e13f6aee1632a3b",
- "298919d5639ad48d0ea3799a98c7d082"
- ]
- ],
- "prep_messages": [
- "e129a25d4bb45ae8f5ff9d97d72f6d86"
- ],
- "prep_shares": [
- [
- "574ce7d79da173f0652f7d1e699d5fe7865e23ddbe20c3646ca1d41f8d0d123a831f3b90d5b917779d25ca7aafd5c903b4b996399d29d3af9fcb1c6549c36a639e45759c53b3bf6a1014fbdf7ea4d5d3726af036968d80aed52a7e48dc0a06ee66a6e34bf38ce1083cb56057cfbe98ae9138b635f2b64b60daf151ce214d33b99062b201463033142fc734e4c163fd8a5d2ea4503567c0a9739027883ab0b37ece24259b5ddcc88b3e272bbad93857a52a48abf5eb9fb135ccaf27fc0379f49f203cc0f5a4f14183ef3b935076893f0bc56dcd9b0ffbf8f711039bfd3fe894c0c007d8702db35ded99e2605fa3d9d4b70f6dfcdea9883c839e2a91aa358a38359e2d3cb20272a3ecb52e1edc17a48940",
- "21c1bcbdd38fa9e8d86272f8c66c2b167ab67945b007b46536ece1073c4ac681e7967f80f8df630af6f5aac52647e36454b87d9c2d6aa2d4c2186b47a6bef8153706033ed34cde0d6bfd39a81a0fca04618cc495486eccfbcba29099fb101871b0e7871238066b280f7c09e0365214230a741f21625c730fae5e37a7a3cbe0c00910f79b754d99088059cf1d5da8a7911221c38f8a6f79877dd34cb4fd2990744e00b3a6e95d36d03d83969de2989c12e44eb18d466e8954631aa1dbe84e78111a03a3f1d743c457d0cbadbc0bd25ca7de998de032e28d1a8ca88d584ad7a64032c150fc25094cd2147739d1a1e03e8f6e636170867687f1c511dbb936fb521b6639ebc145f03b6d1751fcdf14c5108e",
- "89f25b6a8ecee226a56d10e9cff57402a204a4e83b6b78a5aa32317f68443eac27e57ad2e170a0a32cf748f9dc0fe45524ab48c23361b4b327d498fd702f23b6aecf563787471334096bb202a07696b7eb8d79193777673f93547e14b15adb2ac7ea8999a3f4edb4bd7d3ecb26f2137f5e2881b52fd4d3ec538b978ebba54312ccd2dd263bce8b78c14ddbc0c94ed85d38fdf5fb7ee2eeb21ef066fdde8a94f89aabfdbb6bf174fff2358c4a8d6b7e6cdb080672d15b2ae06d6ca64387b56c00cf35ffecb0b195d01d1d86ee1a015df53e771738ec1faca3fcdfe4f033977dd50c03444dcb256fa982b24cf064dd6e4dffe71f8d5648cf336acd9485f9d70e24f2ad6b4aa14511e7b660c0866f73672a"
- ]
- ],
- "public_share": "9e2d3cb20272a3ecb52e1edc17a489406639ebc145f03b6d1751fcdf14c5108ef2ad6b4aa14511e7b660c0866f73672a",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
- },
- {
- "input_shares": [
- "db3fe5357f56f6cfe9a0a34ed08e231766b423d5670741c151f7bc28cb15c4c8678df838b6ef52d74c5bb5e8c8c607b2674c024da705b558163e3127ae09f4a5c061dc6129d71755ec77b5d5a2fc088542fa612bf1273d94718e0d28b654ea9525148bf910a5c6d55b596e323d4f55ab62b0851e0985987ea39cf500bfd4d5faec37f519120b574aead76d706e149c54b6e790f7c35553f830f67553ff3f08db0f5d8a2e157f9c1ef6eedcb845a19fffd4f9c6e705b035c95f3ebe51219a91c6000034c52b8fd7e90417636bb443c98c3e6933b1599c09151095fff99d7af43d327fcf2afdc50144e5b8f5b1ff1f8cc8d442613dc76dd48100dd4637b38fc5fa249333c6d1e2bec2132a3e3cf5fd11f7e923fbf275071a71535740ac64de88b83ca002bd4490de5c7540e454331d46ebb925725b964ecfcc5c3bb076bf57fd819d0bd788b4495da456594503c8f5b618c4713e957a7589b151ead3a27ae80153b1fbc219f5524eec22dc91aa56ed87a71d2b6e6b857ee03a700fb5af5b23513fb63023c2764f74b40f00e44e2e7acd463e7f38c783a898015b51863659502645e6d7fdf14abf76c605d42e523a540f40e716db420d599cea502baa131d6b61b8add86a09b9f7587e107c6fc9043d72644153b54234146535e9ec25223d293f4a2a4481b5649a7625116aef735ecbbdd9e99076985e1c424e91c29ae231c01f2b11007c81a9b3c72a84522014f4cdcb949cb9850b62b1c9c5d35f0fc3dbf4f637af85d3082ffd15890041a455a5dd38efc902eb415afcd2c93a2b6ab46c88847f380affbc3a9af4745718044c9f23978027af66871e610e1beee21360fc5ae4f05ed32689328216db3c512fddacefb2713187f4f5069170db246ae0cb13b3b88f8d832d11ae6b26fe6f0f89b9a9056c28ac6160134ab1af4be606a2ca7d1256cfc323c823ae4921ba11aab9e4f8104885b3d17ac7826ad06b0fd0e54397e67179765b29c6d724f3e9d9a6934619ef0bfee72cdcf0031672bb6e55be53d3ef0fccf8beba7dea636eff7fdecee99f60a0bc5d5cb11e24683ca8085cf218a3607c3f5a051c33717f39834435c5c542f42bd9c9d9103173cb11436e2a626e228415924037ee4a4078f0d9a5bd0fef1dc9415740c4b32f51d199d912907a103c7e25928acadfb4dc1e8d32c34b4f0100bfe95feb850e0d7b359aae9a332913d1f8eca0d1cd93dee2f4b75076536037ca2b6bec5003ae89e03db9813d0dd2165bf50a836ca492f05750a3b5fff4d089fc54fdf225aa112d72ab021b0cef1b8d31c852133fae501406668db0cb4c3589934bde5ec218876b0dc4087b61d706234635d5d9065787a21ed895fb7c05902a554f879dae44d0905292815c5ae2338be1faa924c67468654e6880c69828616e9d011132b27aa457c6dcbd554ec4374ec882357626d6f323bfadc3b23ac6d390e40f8f2008e462458194a1f9d63e0b977f4be907f34aecb0a12ad13b95bfc858c412abab064106faf149e9b25cb557c12a54e6ae957097b8b11f174094d134cc213bf98da7c7619eb79e2184afff7bb585319fa67b935c839af760464b6f3d5402847d07d9cf6c2502ae55f33e08959b38de273b2911fa9ef530cc2cc1a1f3f8224ed7c8efe455f3ad1e462c1d089d4be054801a56ecdd4dca5bbc7191990a1c028d6d79934bf7aed757eccdd68512ebe9f919f087f6020e75fa8e281316ae3a0a50a7f5606162636465666768696a6b6c6d6e6f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
- "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
- ],
- "measurement": [
- 15986,
- 24671,
- 23910
- ],
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "e0866b02cb848e7e3c5840b05acfd699",
- "3c85902ed398efc35ebb269aa58e0d5a",
- "2a61902ade7fad281b8cfc5f1349ddf9"
- ],
- [
- "f9758e4a5c3d6d2a1b4b3c7e5d397d83",
- "9bb1de90bc4c2244e630e3b6780dc86a",
- "15735600bee57d499ed0890554ef5183"
- ],
- [
- "9b4106b3d83d0457705c83d147f7abe2",
- "89299140701aeef79e13f6aee1632a3b",
- "298919d5639ad48d0ea3799a98c7d082"
- ]
- ],
- "prep_messages": [
- "62b225fa36c2cbc5896a40b1360f0ce0"
- ],
- "prep_shares": [
- [
- "574ce7d79da173f0652f7d1e699d5fe74186663960507c6ac01fafa7046bc88a5c4146feb2861bcb9f3ad8bb294028812c631ce293cde53b6fc09c6bdbcb839ede24393da7141c26a1a594ccdab1fba7ed2b2e38faf952343a2871b854699ff9533b4f88f9bc7e935cc62e3dea6efff7e2d396d8276281db4e789dc30d3fe01c397b64d685e87e7dccae1b7636b1a1486293f29e5c3433ee211e1f66ec5a7a0f1d79ed261735f53fdb51cbd51c1a6b057bf2845e34bfa091f0f8fd7565242c8b247064dfac759c1c646d085bca6ad0845b9cc2093fd49d493ebf2d48a90b99815f0bd165f56453c6b27dff04d3a161d9fc0bc4177e423791d4064faccfbbd3218c6815a24e38fb752efc839e59043cbb",
- "21c1bcbdd38fa9e8d86272f8c66c2b16ce028e4f460022aed5c3e47011081a9ce7967f80f8df630af6f5aac52647e36481e9f91e23071ea7d98af1e76a9dd5823706033ed34cde0d6bfd39a81a0fca048271f4696baf9fd2e8a37e7b5e1be75eb0e7871238066b280f7c09e036521423abafe75c716165e86a573bab2e46efda0910f79b754d99088059cf1d5da8a79146cedb83d4b00d96b9871a66d73147984e00b3a6e95d36d03d83969de2989c12e222e1015cad12a219308643f8e1c1511a03a3f1d743c457d0cbadbc0bd25ca7cb9908430d0604df4468ab54b36f81ef32c150fc25094cd2147739d1a1e03e8f6e636170867687f1c511dbb936fb521b6639ebc145f03b6d1751fcdf14c5108e",
- "89f25b6a8ecee226a56d10e9cff5740294125c8939f32731654a11d38906f94a27e57ad2e170a0a32cf748f9dc0fe45503b71c971d945163a09158bc06295e77aecf563787471334096bb202a07696b7f7c98da9fca5e00ff5ce6eb4b9d52274c7ea8999a3f4edb4bd7d3ecb26f2137fbd6dc71ed450947219eef408d88af7dbccd2dd263bce8b78c14ddbc0c94ed85db3255ece317e82a0f3b4a873e9b72b949aabfdbb6bf174fff2358c4a8d6b7e6c545473085c7c9b5c2aa9d290b01670ffcf35ffecb0b195d01d1d86ee1a015df56465c0991dd00dfda6948958c3ff38510c03444dcb256fa982b24cf064dd6e4dffe71f8d5648cf336acd9485f9d70e24f2ad6b4aa14511e7b660c0866f73672a"
- ]
- ],
- "public_share": "8c6815a24e38fb752efc839e59043cbb6639ebc145f03b6d1751fcdf14c5108ef2ad6b4aa14511e7b660c0866f73672a",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
- }
- ],
- "shares": 3,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_0.json
deleted file mode 100644
index 4dd3798668..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_0.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "agg_param": null,
- "agg_result": 100,
- "agg_shares": [
- "0467d4fd6a7ec85386c9f3ef0790dc10",
- "61992b02958137ac5d360c10f86f23ef"
- ],
- "bits": 8,
- "prep": [
- {
- "input_shares": [
- "1ac8a54e6804d575f85957d45c728487722ad069fc1ed413da970ea56ae482d81057f898a367319a14f402d072c24bb71aa13cf4f9cdcd731e779aaa4a5d561ff40e41797cf2d43308849ff9080f846c2e78e2736a1d3cdaa68f3ec890d633cc13f5bf96466d3f02f93612bc827ff53357d52ae00dd234b9758f2cbb7aa9682d06041da1507aa12446de554a945924f445d3715279ef00f4c55ae987cec4bb9f1316efdc8737b7f924d046a6b8ef222b0dc1205ce9b464076fa80d2dfe37af4d836d597ade7d51e18e9c95d13158942d249efd0a1a226759e4bc1d46d3a41bdb227703fe0a7554cf4769935bc99cd1f35b274ecec240816af4915c7abe3e16b7be5ab5e105f9ae7b2e683191c9400cf99ab0c687e4929f87e6e64f712ca02f07a1b29fcebdbfde7655797f9c1b6b3114420d8a19736ae614116782278b7a71f9ef6928ad44ce588644886523d6fbe0b7bbb47248edbaa0b5ce33f74a07005e2a6842eb2c05778e170112f6e6a5f206d7830aa122e29069dcb4a4c064e63c29b3c6e2b22dfb5ab344ca0f1be8e8ce36d26435413de2dc4f53e158ebb8478b4a98de014a688db9470106fd7e73a65c2e656b5a627b5584ca0594ba10cc39c5612bcef576625c37c5249ad5c04e42c66d6a9653c4ec47e2bcd860870bef64f812974654f17f77c08eaa395803d33bdf31db17d76dbb9d2407d7c4f9efbce274542ff6aa0dcf188803eb586108317db430ad517ce7cb0f56d225c835161eb348949ebe253bedc338c6b939ce837561f01d7f0304963eab2a28b38c36bb169a4ee0637635818bd5e4798a8319152a2678b0aa7b837cb0f24df6148ae2c84b78db8892f4415f90f3804e7a29cdcd32a0a8625fd20aca47ee0ef12ebd6138b3534a1b42303132333435363738393a3b3c3d3e3f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
- ],
- "measurement": 100,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "0467d4fd6a7ec85386c9f3ef0790dc10"
- ],
- [
- "61992b02958137ac5d360c10f86f23ef"
- ]
- ],
- "prep_messages": [
- "0fd2bb14ac123437f6520fdc4a817934"
- ],
- "prep_shares": [
- [
- "61428b8d7e326827ac832bc4074ad61652efcfdb8d95b6f06b83dd9f5d55ce9f142d1a1fd437eb8c84581ad15dcd9a57417942e63a1a46e6b0ffc8b6d6300f7d",
- "a0bd747281cd97d8377cd43bf8b529e9eb5e4b1153111bd6cd06aa3a5493a6da4470f696b9afff52ec10fc00040e4538470fdb8d3e05e188aba2b16e24c71b69"
- ]
- ],
- "public_share": "417942e63a1a46e6b0ffc8b6d6300f7d470fdb8d3e05e188aba2b16e24c71b69",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
- }
- ],
- "shares": 2,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_1.json
deleted file mode 100644
index 8e7163ae2a..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_1.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "agg_param": null,
- "agg_result": 100,
- "agg_shares": [
- "b3916e4086c52aa0439356b05082885a",
- "61992b02958137ac5d360c10f86f23ef",
- "52d565bde4b89db326369d3fb70d54b6"
- ],
- "bits": 8,
- "prep": [
- {
- "input_shares": [
- "ec863a16981eee70b71dc7d396a85ba412dcb4e86769d6db0c60f668456f5d6fbb844d9503580fb7b662bbb2ed7d92002e6ab4a2d31a6f611cbb5c48ca6df69811d536f74a3ff61eb29bd9b9f1b64c35eddd5c4ac97376057883a317f2989b545a682775f948f28f80f366f36b4eb90f931bca79e229eae377102295d9c46da2e239f74f045084747039c0a955726b4258bc0d14da7474bea6cd136eb5e55e9531e6a68703003a64943a5650b16674c82d9c4b526a7ed3d69f8f13ae83609cf056f3fed8d6593fdad7b367d2d248413072651073ea91b8162d42af168698f0f0928c8238b2df218e26d004d2bdb5f9f20d0a43c0286d08cfc26971f282992f82ff14d51cee3e0f3fc7411869c2176cabc6b1a68e33ff5eb217490de9f0d85cb84e9115bb7e208a190d25bf9cc138485892802a50b790ba6f45804de487a3353e54b5471adb5ab612d9ee6416649e136456215503637e0daab367149bc5cdf02a2dabc2790f84cadec1510263fe6aa27df5df395b7a241777a8ed28da27276b48f599dd895a005746cfd1f3c874e6f52407f4c417934d7091685c0b38b1d76b398ad263ec73f4f811aed38febf67a19a001a2c7ab8071f986939713cccd146c7a049c5129783359fcf86410765028fbfbbe62c2474a6b75de0ba49c037e07946deae971207f4f74b8b1d6a7b225eb0b66ed1f3878bc14d9d7a38b2162247b7ed9ac3df6fd2a98a3e4bf2855c8fb13f39487481fe03f5b5cb5123d11aaef180ff8ae69709322459a01a72e9304295ae5721d6eac6dae140677d0dd60f192f0475bacfd131d4ff3393238caa00fe0847c3a43c97a31f84f58b3c7487c5c0a09e85b39ed4b69fcdfa071da15216fd5f1fad125328e40689acce1a6cb113c2a16f599606162636465666768696a6b6c6d6e6f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
- "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
- ],
- "measurement": 100,
- "nonce": "000102030405060708090a0b0c0d0e0f",
- "out_shares": [
- [
- "b3916e4086c52aa0439356b05082885a"
- ],
- [
- "61992b02958137ac5d360c10f86f23ef"
- ],
- [
- "52d565bde4b89db326369d3fb70d54b6"
- ]
- ],
- "prep_messages": [
- "e385da3bc2246be76ff12a7093ecb45e"
- ],
- "prep_shares": [
- [
- "7b6a9ad01449ec86dc6736dced3ecd24b47ab2a3768908b10696d537f2b02c98cf3314686f94ac37c7d81b14fea51f784e037bbdd56b2ee8486757acad61db1e",
- "40a478cd7376c1e9ea339ddcf96ab1a7eb5e4b1153111bd6cd06aa3a5493a6da4470f696b9afff52ec10fc00040e4538470fdb8d3e05e188aba2b16e24c71b69",
- "46f1ec617740528f1c642c47185681331adc83aace0cc5ddd256cf295c93c64d207d424f5056a8d59748ba9e423c4cf5f560fb4c6505c9a773629e12f21ee230"
- ]
- ],
- "public_share": "4e037bbdd56b2ee8486757acad61db1e470fdb8d3e05e188aba2b16e24c71b69f560fb4c6505c9a773629e12f21ee230",
- "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
- }
- ],
- "shares": 3,
- "verify_key": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/XofFixedKeyAes128.json b/third_party/rust/prio/src/vdaf/test_vec/07/XofFixedKeyAes128.json
deleted file mode 100644
index ea76c50ff8..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/XofFixedKeyAes128.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "binder": "62696e64657220737472696e67",
- "derived_seed": "9cb53deb2feda2f9a7f34fde29a833f4",
- "dst": "646f6d61696e2073657061726174696f6e20746167",
- "expanded_vec_field128": "9cb53deb2feda2f9a7f34fde29a833f44ade288b2f55f2cd257e5f40595b5069543b40b740dfcf8ab5c863924f4510716b625f633a2f7e55a50b24a5fec9155dec199170f9ebe46768e9d120f7e8f62840441ef53dd5d2ba2d3fd39032e2da99498f4abf815b09c667cef08f0882fa945ba3335d2c7407de1b1650a5f4fe52884caf3ef1f5802eabb8f238c4d9d419bed904dcf79b22da49f68fb547c287a9cd4a38d58017eb2031a6bf1b4defb8905c3b777e9287f62a7fb0f97e4d8a26c4e5b909958bc73a6f7512b5b845488d98a7fcedf711ada6972f4c06818d3c3e7a070a88af60dc0323b59f304935fbbbd3792e590c9b6bce7459deba3599c7f30fe64a638219dde4bde4b1a51df8d85c2f36604c44f5f188148e3ba1dca3fd8073240ee577ef322df19a13d9ffa486a6833f4eb2838a58746707b8bf531cc86098f43809276b5f02914b26cb75938ca16eafa73397920a2f5e607af30e62ff60b83e15699d4d0265affe185b307ed330941a41b2b628e44d9a19412f7d9513cacd7b1fd740b7708e3bc764a0cf2146bca7c94d1901c43f509d7dcc9dfec54476789284e53f3760610a0ac5fce205e9b9aa0355c29702a5c9395bf1de8c974c800e1037a6bf5e0bd2af7d96b7f000ff6ab93299966b6832c493b600f2595a3db99353d2f8889019cd3ec5a73fa457f5442ed5edf349e78c9cf0cbf4f65aea03754c381c3efc206b7f17447cc51ac68eceacab9d92b13b0bc700c99a26ce2b6c3271f7639aa72dc27bbd54984907abb10ef1047ef352d378ddae48bf381804c89aa1847f5027537cf6af1b30aa44cead6495e98ca5b3205d39beb49d2db6752a4e57158e8c83464002b0b4a9838bc381c1dbdc3e9a584554fb76671a15f907c0b395a5",
- "length": 40,
- "seed": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/XofShake128.json b/third_party/rust/prio/src/vdaf/test_vec/07/XofShake128.json
deleted file mode 100644
index edafb1bd4d..0000000000
--- a/third_party/rust/prio/src/vdaf/test_vec/07/XofShake128.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "binder": "62696e64657220737472696e67",
- "derived_seed": "87c4d0dd654bf8eec8805c68b5eb0182",
- "dst": "646f6d61696e2073657061726174696f6e20746167",
- "expanded_vec_field128": "87c4d0dd654bf8eec8805c68b5eb0182b1b8ede598cfb8d8b234038fd0492eb14268bbb2ac15a55d463c8227c2d4fae8607631d13157c4935c5d2d56e4b1e2bdfe0f80b286d82e631704acee29ab6f7acaa316d3623cc3371297604caf57bc2eafe72056143971345901b9fb9f95b6a7384c6a88143124ff693ce9e453675f87a6b6338a1e1c9f72d19e32b51f60a1d7469de1fbe25407cc338d896b34c5fc437d2551297027eeefca9aaccdb78d655a6c220cbc2d76cc4a64b04806ae893c952996abb91f6ec32b6de27fe51be59514352d31af4967c0a85c5823ff73be7f15b9c0769321e4b69cb931a4e88f9da1fde1c5df9d84a7eadb41cf25681fc64a84a1c4accded794c1e6fec1fb26a286712425bfc29521273dcfc76cbab9b3c3c2b840ab6a4f9fd73ea434fc1c22a91943ed38fef0136f0f18f680c191978ab77c750d577c3526a327564da05cfc7bb9ef52c140d9e63b1f39761648772eaa61e2efb15890aed8340e6854b428f16dff5654c8a0852d46e817b49bbe91db3c46620adbd009a0d7d40843c1b6b7786833d3c1ae097b4fa35815dbcfca78e00a34f15936ed6d0f5bf50fc25adbecd3adfa55ba6bc7052f0662595cf7a933dfcc3d0ad5d825ec3bc191586a1c36a037d1c9e73c24777825d6afe59774abdb2918c2147a0436b17bafd967e07c46c3d6240c771f4fd4f9b3fff38b294508b8af5a1b71385f90f407620b7aa636fd2b55435b3688fc26ad3c23b2ad48158c4c475c07eb58569a8d1a906452b82d582397c4c69f5e79d3082d03b4dd85b5277a8b44c933d52d168caae8c602376f5487670a172d138364cb975c569c9c2d79506746090ea8102907c91b66764fd8740ca7bd3acb59173df29b5fa7542e51bce67b97c9ee2",
- "length": 40,
- "seed": "000102030405060708090a0b0c0d0e0f"
-}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/IdpfPoplar_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/IdpfPoplar_0.json
new file mode 100644
index 0000000000..68f3159234
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/IdpfPoplar_0.json
@@ -0,0 +1,52 @@
+{
+ "alpha": "0",
+ "beta_inner": [
+ [
+ "0",
+ "0"
+ ],
+ [
+ "1",
+ "1"
+ ],
+ [
+ "2",
+ "2"
+ ],
+ [
+ "3",
+ "3"
+ ],
+ [
+ "4",
+ "4"
+ ],
+ [
+ "5",
+ "5"
+ ],
+ [
+ "6",
+ "6"
+ ],
+ [
+ "7",
+ "7"
+ ],
+ [
+ "8",
+ "8"
+ ]
+ ],
+ "beta_leaf": [
+ "9",
+ "9"
+ ],
+ "binder": "736f6d65206e6f6e6365",
+ "bits": 10,
+ "keys": [
+ "000102030405060708090a0b0c0d0e0f",
+ "101112131415161718191a1b1c1d1e1f"
+ ],
+ "public_share": "18850fb4933f36be2d456c4e2477baf2c9a4a7204fb09ae3e3ff925ecfe07a297b07b1980635d1e1f512afbd6388c98f5bf076cc5fe746282e59b81e51bffd6699fac7ec2dab3e9dd2c60d896beb64131d73b8abd7b2f0b327e5d91b42c677468048180e55bd80946611101ff01cb82022f7aecbe1db443499a311b7b9ee114acc16ae30d73d77ab2995eef0d536c26753647394f24d0c7b6db95b0eda08056b919e862c373e9c7a1e17590e5d5f250e56249ad28f9c13a8b57dfd7dcd05d78d49640d0aa35173cb4a659ada59f57d0c408edf52cb16d8bfb5c5d56d0c28a1aa7d96054c848cfeb0eeb6576b7c8c5328dfe502bc5eef4f1c6f58abe9ad37b448995e2b584cdb5f3a94f056ca7b868ad8f593f07c73f88596398fb4f13c5a7393b8fb0d2c76076132f54484f5f18209f42e4fe98ba2b9b1d1d19c139dc4520ada547ddbb70baecf1bba61a7b3cbb4648a7235142e201a173038dac559940a55d29a68cc87298d722b6644fa445460ddb9938c64"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_0.json
new file mode 100644
index 0000000000..c4056a156a
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_0.json
@@ -0,0 +1,56 @@
+{
+ "agg_param": [
+ 0,
+ [
+ 0,
+ 1
+ ]
+ ],
+ "agg_result": [
+ 0,
+ 1
+ ],
+ "agg_shares": [
+ "42417a6b9fd228e050220f57293f7555",
+ "bfbe85945f2dd71fb2ddf0a8d5c08aaa"
+ ],
+ "bits": 4,
+ "prep": [
+ {
+ "input_shares": [
+ "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53",
+ "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721"
+ ],
+ "measurement": 13,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "42417a6b9fd228e0",
+ "50220f57293f7555"
+ ],
+ [
+ "bfbe85945f2dd71f",
+ "b2ddf0a8d5c08aaa"
+ ]
+ ],
+ "prep_messages": [
+ "f7c882b687b7bd461fb1f898356db5fa88833cdaa1e26a71",
+ ""
+ ],
+ "prep_shares": [
+ [
+ "029b574f4e07246cb5b90e90207a148abb7dfba2efb9a32a",
+ "f62d2b6738b099da6af7e90815f3a070cd054137b228c746"
+ ],
+ [
+ "264531e72e56a380",
+ "dbbace18d0a95c7f"
+ ]
+ ],
+ "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_1.json
new file mode 100644
index 0000000000..ea8bbfea10
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_1.json
@@ -0,0 +1,64 @@
+{
+ "agg_param": [
+ 1,
+ [
+ 0,
+ 1,
+ 2,
+ 3
+ ]
+ ],
+ "agg_result": [
+ 0,
+ 0,
+ 0,
+ 1
+ ],
+ "agg_shares": [
+ "f4265a0ff9c4f0d1f068b522d608c1a38cde98228531a78ccb74919ef72f5051",
+ "0dd9a5f0053b0f2e11974add28f73e5c752167dd79ce5873378b6e6107d0afae"
+ ],
+ "bits": 4,
+ "prep": [
+ {
+ "input_shares": [
+ "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53",
+ "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721"
+ ],
+ "measurement": 13,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "f4265a0ff9c4f0d1",
+ "f068b522d608c1a3",
+ "8cde98228531a78c",
+ "cb74919ef72f5051"
+ ],
+ [
+ "0dd9a5f0053b0f2e",
+ "11974add28f73e5c",
+ "752167dd79ce5873",
+ "378b6e6107d0afae"
+ ]
+ ],
+ "prep_messages": [
+ "d2ca8d38065df3047d92ebacf9c366b83ad81d98fb17356a",
+ ""
+ ],
+ "prep_shares": [
+ [
+ "4c00ed0607d7702352c8786bb90f360edd89e3c8507274b1",
+ "87caa031fe8582e12bca724140b430aa5e4e3acfa9a5c0b8"
+ ],
+ [
+ "1ed0621986d79f57",
+ "e32f9de6782860a8"
+ ]
+ ],
+ "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_2.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_2.json
new file mode 100644
index 0000000000..9b4fd0bc70
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_2.json
@@ -0,0 +1,64 @@
+{
+ "agg_param": [
+ 2,
+ [
+ 0,
+ 2,
+ 4,
+ 6
+ ]
+ ],
+ "agg_result": [
+ 0,
+ 0,
+ 0,
+ 1
+ ],
+ "agg_shares": [
+ "6bc200377c0ebf33de6ac488c1427b38bea3859050a09e19208319b3875c5099",
+ "963dffc882f140cc23953b773dbd84c7435c7a6fae5f61e6e27ce64c77a3af66"
+ ],
+ "bits": 4,
+ "prep": [
+ {
+ "input_shares": [
+ "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53",
+ "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721"
+ ],
+ "measurement": 13,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "6bc200377c0ebf33",
+ "de6ac488c1427b38",
+ "bea3859050a09e19",
+ "208319b3875c5099"
+ ],
+ [
+ "963dffc882f140cc",
+ "23953b773dbd84c7",
+ "435c7a6fae5f61e6",
+ "e27ce64c77a3af66"
+ ]
+ ],
+ "prep_messages": [
+ "453405bb632d670892ddc291c4d886ce098d206debd7e121",
+ ""
+ ],
+ "prep_shares": [
+ [
+ "bd7d6befff9982c88c631d4c593d754f4b817e23f0faf751",
+ "89b699cb6293e43f067aa5456b9b117fbf0ba249fadce9cf"
+ ],
+ [
+ "c36085ecec965e1f",
+ "3e9f7a131269a1e0"
+ ]
+ ],
+ "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_3.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_3.json
new file mode 100644
index 0000000000..f280aedebc
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_3.json
@@ -0,0 +1,76 @@
+{
+ "agg_param": [
+ 3,
+ [
+ 1,
+ 3,
+ 5,
+ 7,
+ 9,
+ 13,
+ 15
+ ]
+ ],
+ "agg_result": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0
+ ],
+ "agg_shares": [
+ "7e787b132dfe4dfcf9f8cab505a6133d30b7fd75f52a422d05ce25abe1b9cc5d3c4dce1f874d3e6bc4e9d9162ce3ae1e01da0581055c3d83de238e22b71bed1e8a69ed19cf9ccc49f2bb00c049d3153af4087218b63d6ae26ad30ca130641f50cb85fedfecf35fed0451625ebf2dac37281549b3cd8798fdd12d3eca3a68a17ec2c6f6086fca7b6dd59cd532e1b72bc95bedbfb4ce1dcc7cc873d989601e8a16ca1724e563a6c114b58e3bf58a65c621b00ebd22074223ec8e863c418a8ec83e0701d49174dab847df196325664790b6aba39c2d8ab74275b80ecc5d85c43c61",
+ "6f8784ecd201b2030607354afa59ecc2cf48028a0ad5bdd2fa31da541e463322b1b231e078b2c1943b1626e9d31c51e1fe25fa7efaa3c27c21dc71dd48e41261639612e6306333b60d44ff3fb62ceac50bf78de749c2951d952cf35ecf9be02f227a0120130ca012fbae9da140d253c8d7eab64c327867022ed2c135c5975e012b3909f7903584922a632acd1e48d436a412404b31e23383378c26769fe1756924e8db1a9c593eeb4a71c40a759a39de4ff142ddf8bddc137179c3be75713741e6fe2b6e8b2547b820e69cda99b86f49545c63d27548bd8a47f133a27a3bc31e"
+ ],
+ "bits": 4,
+ "prep": [
+ {
+ "input_shares": [
+ "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53",
+ "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721"
+ ],
+ "measurement": 13,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "7e787b132dfe4dfcf9f8cab505a6133d30b7fd75f52a422d05ce25abe1b9cc5d",
+ "3c4dce1f874d3e6bc4e9d9162ce3ae1e01da0581055c3d83de238e22b71bed1e",
+ "8a69ed19cf9ccc49f2bb00c049d3153af4087218b63d6ae26ad30ca130641f50",
+ "cb85fedfecf35fed0451625ebf2dac37281549b3cd8798fdd12d3eca3a68a17e",
+ "c2c6f6086fca7b6dd59cd532e1b72bc95bedbfb4ce1dcc7cc873d989601e8a16",
+ "ca1724e563a6c114b58e3bf58a65c621b00ebd22074223ec8e863c418a8ec83e",
+ "0701d49174dab847df196325664790b6aba39c2d8ab74275b80ecc5d85c43c61"
+ ],
+ [
+ "6f8784ecd201b2030607354afa59ecc2cf48028a0ad5bdd2fa31da541e463322",
+ "b1b231e078b2c1943b1626e9d31c51e1fe25fa7efaa3c27c21dc71dd48e41261",
+ "639612e6306333b60d44ff3fb62ceac50bf78de749c2951d952cf35ecf9be02f",
+ "227a0120130ca012fbae9da140d253c8d7eab64c327867022ed2c135c5975e01",
+ "2b3909f7903584922a632acd1e48d436a412404b31e23383378c26769fe17569",
+ "24e8db1a9c593eeb4a71c40a759a39de4ff142ddf8bddc137179c3be75713741",
+ "e6fe2b6e8b2547b820e69cda99b86f49545c63d27548bd8a47f133a27a3bc31e"
+ ]
+ ],
+ "prep_messages": [
+ "d6ce08ae0327f913210f5e0701c594bf1baa15a33f6933f9b73787f73464db6a6a10f3c7e7e76a1844367d0091f16a7f090e7ed1fcc6f2a456e9e12daec41b18e08c45f8b9c5d20b02e8fecd25cb7fc05e98a6c79a1ee08da284161b3bd94d53",
+ ""
+ ],
+ "prep_shares": [
+ [
+ "b289bbdd941be53774dbb8177fd40ee4614c325d64ca211dee7268c34fd93c7855030fd22ac1db9e4760d9cd03a090b976b2b9a9bcef2e9f9affeb5cd6afe05423b5b3db766c04dc072864e1dd8b0d0fabf8b8add732c7eeff4ae5ba5fe0fc13",
+ "11454dd06e0b14dcac33a5ef81f085dbb95de345db9e11dcc9c41e34e58a9e72020de4f5bc268f79fcd5a3328d51dac5925bc42740d7c305bce9f5d0d7143b43bdd7911c4359ce2ffabf9aec473f72b1b39fed19c3eb189fa2393160dbf8503f"
+ ],
+ [
+ "b4fe321bd55f5135b7ebfda820401ad7b7fba83b65e68b8ede4b0a566a9f5629",
+ "3901cde42aa0aeca48140257dfbfe528480457c49a19747121b4f5a99560a956"
+ ]
+ ],
+ "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_0.json
new file mode 100644
index 0000000000..c0336fa679
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_0.json
@@ -0,0 +1,39 @@
+{
+ "agg_param": null,
+ "agg_result": 1,
+ "agg_shares": [
+ "352c53cbc1f95eee",
+ "cdd3ac343d06a111"
+ ],
+ "prep": [
+ {
+ "input_shares": [
+ "352c53cbc1f95eee43253a8650e8ac18a5bd9c18b824886772947facdf1a413f1cf547cdb8c1ad4ed4c1294ccc856209",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
+ ],
+ "measurement": 1,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "352c53cbc1f95eee"
+ ],
+ [
+ "cdd3ac343d06a111"
+ ]
+ ],
+ "prep_messages": [
+ ""
+ ],
+ "prep_shares": [
+ [
+ "f6340e6030e5960b53ad59de202314363e6063ed75a89676e3b9635d397d650e",
+ "0bcbf19fce1a69f4b5de9ce10c9c671b9baa607f88bfa49de4367212193d9b3b"
+ ]
+ ],
+ "public_share": "",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_1.json
new file mode 100644
index 0000000000..6731f2a13b
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_1.json
@@ -0,0 +1,45 @@
+{
+ "agg_param": null,
+ "agg_result": 1,
+ "agg_shares": [
+ "4eeea47bcff955f0",
+ "cdd3ac343d06a111",
+ "e83dae4ff1ff08fe"
+ ],
+ "prep": [
+ {
+ "input_shares": [
+ "4eeea47bcff955f08194b8660a6bb007a346b42952b2298158c165d94c1c40979e10b54ae7092a5a14b325df003a6f9d",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
+ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
+ ],
+ "measurement": 1,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "4eeea47bcff955f0"
+ ],
+ [
+ "cdd3ac343d06a111"
+ ],
+ [
+ "e83dae4ff1ff08fe"
+ ]
+ ],
+ "prep_messages": [
+ ""
+ ],
+ "prep_shares": [
+ [
+ "817531f295522feac2551124114fdc827bfda7719fb1eb33b0b4e1c49761f62f",
+ "0bcbf19fce1a69f4b5de9ce10c9c671b9baa607f88bfa49de4367212193d9b3b",
+ "76bfdc6d999267219aa129cccf1e2459cf93ae20bf886d0d22fe0f5fcded28e6"
+ ]
+ ],
+ "public_share": "",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 3,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_0.json
new file mode 100644
index 0000000000..b39dc2838d
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_0.json
@@ -0,0 +1,52 @@
+{
+ "agg_param": null,
+ "agg_result": [
+ 0,
+ 0,
+ 1,
+ 0
+ ],
+ "agg_shares": [
+ "ac3ba28d7f5649e6b3932251da118acf6740508adaf7837c87cd0574c48a00ea2ba59154eff2921c69cdeb23276510d3758486d91898690c4ba0fd3e6e149956",
+ "55c45d7280a9b619306cddae25ee75309abfaf7525087c835c32fa8b3b75ff15d75a6eab100d6de37a3214dcd89aef2c8c7b7926e76796f3985f02c191eb66a9"
+ ],
+ "chunk_length": 2,
+ "length": 4,
+ "prep": [
+ {
+ "input_shares": [
+ "ac3ba28d7f5649e6b3932251da118acf6740508adaf7837c87cd0574c48a00ea2ba59154eff2921c69cdeb23276510d3758486d91898690c4ba0fd3e6e149956aaa0fbc70889fae40bf0b8873db6f2c2c26ef6772e0dd8d091e12a1dbe4388bbc88819a887c53a4afa8e3e35b0c00100af9000ad245790e71c322e5c252e25a25514ccc4ebeb9b9f47a98223b2d04d44f94a2cb4791ff9a056eca2a0c74ab11f08d41d917cdaa2858d372c08339c414559066eb7be61cf2b5bb36c7c598a97b19802fead02586c39b001c18b5ff36e66d9ab75d6e9c6c0c0eaae66b1014ba2645047801054acea9f87404cc2749584db303132333435363738393a3b3c3d3e3f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
+ ],
+ "measurement": 2,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "ac3ba28d7f5649e6b3932251da118acf",
+ "6740508adaf7837c87cd0574c48a00ea",
+ "2ba59154eff2921c69cdeb23276510d3",
+ "758486d91898690c4ba0fd3e6e149956"
+ ],
+ [
+ "55c45d7280a9b619306cddae25ee7530",
+ "9abfaf7525087c835c32fa8b3b75ff15",
+ "d75a6eab100d6de37a3214dcd89aef2c",
+ "8c7b7926e76796f3985f02c191eb66a9"
+ ]
+ ],
+ "prep_messages": [
+ "1acd91a20b79e95050d47db9bf4b1ed5"
+ ],
+ "prep_shares": [
+ [
+ "aaf0cada92114681d890231d05395ea51dcf30c4fa042de2f21b10d3126976a4565c5032534c5af98418b0bf0647dddada1e47da1c608f0d03070d5baf530d1e52b4ace95d26bdc41c0bf64068880a5bcbf5ab84954e1087ff8721b600477c48bc82ef4255afbf48216c910cd76ca594",
+ "570f35256deeb97e0b6fdce2fac6a15a8d4d3367a586ac831119c6edeefb5ab1d4a2ad70c499a97f61b3eb86717264b1a941e67b26a189ff84bc81c89edafd3187e190bacd40bfa5813ccbd77338c7eedb90e273a045b29382cdddc5571e35de1da4a26362199818038b8624ba1ea4a9"
+ ]
+ ],
+ "public_share": "bc82ef4255afbf48216c910cd76ca5941da4a26362199818038b8624ba1ea4a9",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_1.json
new file mode 100644
index 0000000000..512b2aca98
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_1.json
@@ -0,0 +1,89 @@
+{
+ "agg_param": null,
+ "agg_result": [
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "agg_shares": [
+ "6ef23fd4b5f5502e5c215848c3703c1ac06dbc83cebd2ebb78b8549c64cf10b6a709f226d0e6aadbaac7c1512dce7f44e0715547855fae84e0a1f1fe7612423940c18ce556a3754c64b46de79038603b2ffae8c57346b7a9385f34f084d8f62d8e145aab9b0f1c038ed9f7b94d82a6cc7d32743c367987da80859005285a4b2f41e62177eead51b17bae964e100bd7408688c19870104fddb90ed31a0065a92f870079891c2ccc659a2a2cf3cb424cc3",
+ "55c45d7280a9b619306cddae25ee75309abfaf7525087c835c32fa8b3b75ff15d75a6eab100d6de37a3214dcd89aef2c8c7b7926e76796f3985f02c191eb66a970fd5de8e08724782338a0d5e77d181f61a976f8712fccdde127760cb8056d105e3d2f6c325607ab4a9a3ce791283b3af006fd1a4aa66fbfb30ade0e81c5d226e5c8ad6b7e4bdd02db51d98a13f5cf81d7797d2adb9c59afef3378108eec9ad02f4bddb5208b11cdd02e159b36eddd76",
+ "3e4962b9c960f8b75772ca0817a14db5a7d293060c3a55c10e15b1d75fbbef33849b9f2d1f0ce840be052ad2f996908e951231929338bb876afe0b40f701571d51411532c8d4653b5c13f242874987a5715ca0411a8a7c78c9785503c3219cc116ae76e8319adc51ef8bcb5e20551ef994c68ea87fe00866af6f91eb56e0e1a9db50301d9306d14b8dff8f26dcff583da5fdc03cb45257731ebdb4d471aebbff4cb4a9c0c24822cd5ca6be71fdcfd5c5"
+ ],
+ "chunk_length": 3,
+ "length": 11,
+ "prep": [
+ {
+ "input_shares": [
+ "6ef23fd4b5f5502e5c215848c3703c1ac06dbc83cebd2ebb78b8549c64cf10b6a709f226d0e6aadbaac7c1512dce7f44e0715547855fae84e0a1f1fe7612423940c18ce556a3754c64b46de79038603b2ffae8c57346b7a9385f34f084d8f62d8e145aab9b0f1c038ed9f7b94d82a6cc7d32743c367987da80859005285a4b2f41e62177eead51b17bae964e100bd7408688c19870104fddb90ed31a0065a92f870079891c2ccc659a2a2cf3cb424cc31d60b4e3908aa656e527d0a66eaeaaf493bde0a7a86be4ed3145a5596fab04256c95611675891b234a939c91215ec467aa9a516cd6a9a7b8d1a4ddb91e8dbfbcc8d9a45d8792f9d56a68061809b7ef4963736c20e3cb8ce6a95e1bd84c7ae51ccb14192b3101ac85a5a3a62415fb516df685b9313b53f39bc6a74062a55435f9c35f50ffd660a6d7e0e9365128bf6d87e52358afe563bc1bdce119291c611597889d36caf3247f61821eb596b089dddaf32359b12e74260a24d816335a2bf1aa93dbd84dd31773f2795ee931187525a570589f31e66a0e0d8a92370c3458fb00b2afb3e3d98f142cf9606d47d28a75caa8b4ee730e1ff3faf0aed3a154887dceaa6dfad49582d4a560b0d6599e0cbab2b36f20b8ca497f6540ca17f69595c695c2c6e0e00956acca22c71fab529936c47ad8de0e09f39d41a3b0469edcbfea242b20cd6a4748d4075ffb9a755b297902606162636465666768696a6b6c6d6e6f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
+ ],
+ "measurement": 2,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "6ef23fd4b5f5502e5c215848c3703c1a",
+ "c06dbc83cebd2ebb78b8549c64cf10b6",
+ "a709f226d0e6aadbaac7c1512dce7f44",
+ "e0715547855fae84e0a1f1fe76124239",
+ "40c18ce556a3754c64b46de79038603b",
+ "2ffae8c57346b7a9385f34f084d8f62d",
+ "8e145aab9b0f1c038ed9f7b94d82a6cc",
+ "7d32743c367987da80859005285a4b2f",
+ "41e62177eead51b17bae964e100bd740",
+ "8688c19870104fddb90ed31a0065a92f",
+ "870079891c2ccc659a2a2cf3cb424cc3"
+ ],
+ [
+ "55c45d7280a9b619306cddae25ee7530",
+ "9abfaf7525087c835c32fa8b3b75ff15",
+ "d75a6eab100d6de37a3214dcd89aef2c",
+ "8c7b7926e76796f3985f02c191eb66a9",
+ "70fd5de8e08724782338a0d5e77d181f",
+ "61a976f8712fccdde127760cb8056d10",
+ "5e3d2f6c325607ab4a9a3ce791283b3a",
+ "f006fd1a4aa66fbfb30ade0e81c5d226",
+ "e5c8ad6b7e4bdd02db51d98a13f5cf81",
+ "d7797d2adb9c59afef3378108eec9ad0",
+ "2f4bddb5208b11cdd02e159b36eddd76"
+ ],
+ [
+ "3e4962b9c960f8b75772ca0817a14db5",
+ "a7d293060c3a55c10e15b1d75fbbef33",
+ "849b9f2d1f0ce840be052ad2f996908e",
+ "951231929338bb876afe0b40f701571d",
+ "51411532c8d4653b5c13f242874987a5",
+ "715ca0411a8a7c78c9785503c3219cc1",
+ "16ae76e8319adc51ef8bcb5e20551ef9",
+ "94c68ea87fe00866af6f91eb56e0e1a9",
+ "db50301d9306d14b8dff8f26dcff583d",
+ "a5fdc03cb45257731ebdb4d471aebbff",
+ "4cb4a9c0c24822cd5ca6be71fdcfd5c5"
+ ]
+ ],
+ "prep_messages": [
+ "1b2dc3cedc43f65731985f19081f490a"
+ ],
+ "prep_shares": [
+ [
+ "cd5978e237aafb0552d6f2614be379176c256bd1bb2d3fa71ec64fcf5e64b6baf5c530e6c828d5be1468539c16917e08f6cc5d754b81f6ea05ed0747377a2dbb5a731ed05a41704a11aea67a37c668810c7fbee6ef543f6a757ffa07f22a6fdc6c37173af38746dcd7ef1f2cb0f555d13b999f3ef6a282b6649c29878349c501711da5ad2a4ac3de6fccb15c803f918a",
+ "87cd13bcc0f7bb62542f40b8a480db80fca16e26264525b236a3664c792009277d9133d4ff0df494d18758677dbea683d9be082297301d1db87b6a345f74f07a3e268fd6e440eec02b3d4109b30d9c680c18d29df84586f30d30a2cf2419471d2b45845e9a4ba9f1c835ef577bcfa710e9d907592e678fa3a225e115cac914fde07e503edb901812725c6f25d7585fb2",
+ "add87361075e48973dfacce50f9caa67077de5a0a3d6e85b8b04772423132387fb2732f839d0de182c65e61553e08af6fa237248acc8e6cfad227ed43c8eed56bd3c1ae929a7c2bc1c5b47dfd2d57a56fd8f3a4f2187c7f94ae1dd203aa9e3bc20a53b7ada0b4f545e0c7a8370be163a582fb321c11446cb9f3b65dc2979f432236aba9b84dbe8182bce25a97ad12186"
+ ]
+ ],
+ "public_share": "711da5ad2a4ac3de6fccb15c803f918ae07e503edb901812725c6f25d7585fb2236aba9b84dbe8182bce25a97ad12186",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
+ }
+ ],
+ "shares": 3,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_0.json
new file mode 100644
index 0000000000..f18f47d506
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_0.json
@@ -0,0 +1,194 @@
+{
+ "agg_param": null,
+ "agg_result": [
+ 256,
+ 257,
+ 258,
+ 259,
+ 260,
+ 261,
+ 262,
+ 263,
+ 264,
+ 265
+ ],
+ "agg_shares": [
+ "b43a2f79240602a73fafe498f4596524e2d16ccd2a68978aa0fc3b08cb757afa0e634bcf86a6f9f6066716d8d6ff6fc5d8323c1f04aa8b08948ef2e9e7a7a10e3be55e452c536f004da7d3502d93f9ef835b59067c8de2bec68afff55e15d4923cdab73e57ea28b90b70d15dc110dac2ab8c34f509842b025606222ee32ce920b14cc3ccabdfc4f1f743b9ef3ca0c2b5bd715085b0d76c95daeecfad16278bb6",
+ "4dc6d086dbf9fd58a4501b670ba69adb202f9332d59768754303c4f7348a8505f59db43079590609dd98e9272900903a2ccec3e0fb5574f74f710d1618585ef1ca1ba1bad3ac90ff96582cafd26c061083a5a6f983721d411d75000aa1ea2b6dcb2648c1a815d746d88f2ea23eef253d5d74cb0af67bd4fd8df9ddd11cd316df58b43c3354203b0eecbb4610c35f3d4a4d8faf7a4f28936a09113052e9d87449"
+ ],
+ "bits": 8,
+ "chunk_length": 9,
+ "length": 10,
+ "prep": [
+ {
+ "input_shares": [
+ "43118698b73a59751812aa20a73ae412766ef3c4c7559adaf4f08d6d73fbe01849ac4f0da41a26f10b1709d08f56da39953a74ee5cca941b880a5857b143cdeb7065b4b8f6b13b474040cd9e5307fd42850c79e49dc4808a8bf2d976223522179142c2cce38fce9218a371029ac88597283e246464233e9d7cf7048bbe3d18d369dfb8d462dddbe94e33f7ebc07bf0cbe8ecf9e42a156f1fd2b6c434eb62813c0929e78c86cf9bcfad5d54287598c986364fcb6fbbfa0db79dc0f4c1dbaebed54201c88b9e1f93a7fcabc0137d2b6c8ec6f423d7aeeced8f7dbd4c64e7ed595b6e5d76034a16c5686a8982397ef1e882232a95e11e7377d5b758015b716472c4dfaa9021bf2f861e18507f7f8435b55a4a3c8f7357e245596c08975169be3fdf4f2bc8600e680b9013f52b67000959ce3a588caaabdedb7d6201210902695051d808571846039dc672be3d2a7d2d25137baf47f5b71d1d907c9db4d3c20045cb32bdcf9c0094bce467da04ed90e885c9e0765a41d98cc0cc454d1d97efe2255eed21c3b2297d9d0717f8d46d1a016ab89afabd89620aa6090d21ad7226d173f23cbdd31702582ca06b336d277c4f39903414ab2baddfa578bce3be8ba27d68651d720b8401a4ffc61c999f628cdc71c058767c63f23e8b933add17cd3e50ab8540c9ebf935b2912fa26d68e2cc9289e4f894b8d03a81b8d306cadabb209de35c980d4ceea42abc4a0581b6114c77e4cc66c01be07deb7bdb8db23df5d67398497b30ea78518ff759304b5269502f93848838ba2d3e1737aadbbcbd4cde25689fff7a738df9017a4f2986c8fe8b8ba6b6f87b4dd6ec84876ba076c31039cf59b695313060ca1dfdb288c8924ebcaddddf9d067f2be6033af80313292c03996a39281c78299d8549d12cd8427104783575ec604930ab55e288606fdeb863afbeb9df6a009694c055c34d68e19c19ef3fa851363493cdf197c201958449e57e327b15eb5e25d2d347374a85e4685b432a15f4f768fa0b180f6db9f0af65cbbcb0c137a2e12cbb0aadf81e78244e2b8855634a9d0014005d9c9209381943f019df54769b4452a47ce0f223ae52a4d28d725d97e40b37b250499508838bc8a7ccb133f7a02fbfc91fa1c27685786808ae4a45e08cf841c79f3a61b58ae87005dd4e43920089fc2bc23b8c6ac3aaf2081a14edf30a0299f3094410689ec026a8bf8ba2b1c470583987c30d5d8ca6e7ea605d0c7661dba95beef2f4b94f5306317ecfa60010d6b18c2aebb994a4559fad9f3538ef7eaaf35761f7640b807483793ed8ab3ae20672da387979a8171eb1425700e257a912e645a80739e5d494ba6d419dcd4fec13aa806fcfcc84480d7e0e676916aded6f1cf9d69f7e958dceae1edaa11b2569954b7689e647906cccbdcbc2897f139356d9c85168f08ed8990aefc891158a1b89d7c19d3c56ad2a91d3de46ada48ec6338d13efb16c4cb49acd981a044c335240ce7d1db84fde51058290cae528cc7dc5794daa652268d9e5d0fa639a8549c9fdcd3fd126f653f9b970d804fdd4f420e473a31410fe9a84fc43ae415d008ac86ca0881f737382196cd5b6dd4b8673cb515ef70c4624bea32c22a7b72c2f8e1c2fc693a4905215e10580aef647be4bd36baab91c2867bcec745bc5334ce8cda1a0d77f6bb5f1838c60904f8ba7aec00d2529e87c41702b774c6f11c632d35f477988847de39626fd7e83b07ca2de2d7dbd68d07617dc590e00684c79ff1d8ff484a31056b53b29cbe470c8bf99515d7ad2939120d3b9b9ebabfb29d0e7b77cc7bb5ab97fc44591ee036de0206b8331c99c75e8bcc50ac1cb75fec3fb640318010d3ddeaaf423d14d2d715e7cf81ee4d01ad0c0f09c66b2e0b396b93c2bc97b21a42cdafe748aa4b59c250e4639be7173f4cff260339d2797e402653a3bef19a0a17763395889c4269679f6bd0289a356eaf0f06b409d24d4c112ff8f60b9383669677635f20d8eeed5c38d9500e39dca878f578b4980f374ee556aa3458b551628ff9f110d11b7f2497195d9bf3c9557e6f3d11c05f52158aab8f6485cdecfa158e592453351f1866faed652e75b37562a4c696867a89ed8b55355c82c6b571918d3995cb6516f00742a7f0974f62ca846d1306422176a204627930693eaf08951f082629d0a5537aea1d8729693798896fb16830a7cc7b29737f29637308283d5577ee3ea54987f14e4b1b4a51a17f7426a1ea86b42db1410a05064dd773bb5dacdf49702f7cf3ee9695f82fe881ef34c52e8d46e1e415989a757ec94cdd07294a2290e19749606638ed7ab2138cb9f7769a75b169f02dded1bb93c70095ef01be80b96b0ec21588146c8a238abd2bc14a170c5a024fe683c809ff478def04de33f353111c054ff502e7fad8e768bde39cfe419373b0bd40f1ae943d61b6fb824ac689955567fb7526f05d4db0c32f0e7b76cadb917ce200edfda6065129e19fa38ba3855586913baee0bbbade97144bac9c4763c95278f90bcaaa42fbbbfac31fcba0b8291025dbfd1a3660a60cc97763672331ee7db22c0932f46dfc313e7bd60ee86b7e3b4c11b5daaf8cf3e35fcaa124ae0a05bd063ff4944364ee16326b6131422bf08803aa713c771377f5f47cc940f879b2a1763110c22867c7a704c970163b15f702757d87e6e24a4474865877352ecef45294ef3bb7ec9e45f8609da982a161f89a8a9c2a6cf56fc9e8a2d9396fccf4bdd7b8aaf370f4478cb45bd5773f2a5af3d6149b4e41e364cf87c771848716998b070fe95d1d74c9d77466eae8efe0d5a0435de53d50d562c611ed8a2145c752ea54b31101db21f2688fefac5a3df5fc8163f134e5bcfcfcb2106a642ae3e6bcbd15654f09546ccb8c48d84d3bc7d0a18900dba3d66cb02ec33303132333435363738393a3b3c3d3e3f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
+ ],
+ "measurement": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9
+ ],
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "3c1365280c0256e2bf8fa1dda6c8210c",
+ "4cf0ce9963cd8783355469ad43277e53",
+ "5ccbc3ef2ce2fdfc4422b2f29caa7aec",
+ "f565690aac38d90228da50a3a2e2355a",
+ "c1f6746cb91b25006fe29bc5b9dbfd4f",
+ "2f1e7357292ff6949783aafc745cf130",
+ "c39d92bfc7f862e84f259b7440b04896",
+ "932ebc51032cb90072570bba4b64f80a",
+ "966e96998e4aeca59e1693fabe8aeb91",
+ "9b25702c90f2ce3136faef39b2b783e7"
+ ],
+ [
+ "c5ec9ad7f3fda91d24705e225937def3",
+ "b60f31669c32787caeab9652bcd881ac",
+ "a7343c10d31d02039fdd4d0d63558513",
+ "0f9a96f553c726fdbb25af5c5d1dcaa5",
+ "44098b9346e4daff741d643a462402b0",
+ "d7e18ca8d6d0096b4c7c55038ba30ecf",
+ "44626d4038079d1794da648bbf4fb769",
+ "75d143aefcd346ff71a8f445b49b07f5",
+ "7391696671b5135a45e96c054175146e",
+ "6fda8fd36f0d31cead0510c64d487c18"
+ ]
+ ],
+ "prep_messages": [
+ "faa44093d924dc5a7a7964fd9c8ec82b"
+ ],
+ "prep_shares": [
+ [
+ "f9ab3aa30354eb87abdd838ca558b6cbf26345360ccb2dea7deffb9e075c54b422f03470466c54abee94d25dd57eff3a073bf64fcf5eb3d7334b815115b39e6b16ea9cd0bd90f550dd701f3bf288451f17d4c7a3adc44ef5ad49663dfa2e95250320cb7d3fa0323ddcddcdb0d628146f48f6b53badd73c5333fe30cefbca3badd9a688c628f9df7129d7283772dfa0cc630e06a2795703ee70e9a01f64d3a704df997b7b6de7335aedbab9b3a1932989f93e66bb51c72416fc7f1c54bdf6f15d04c07dd5c8c2d5abea0921c5047299cd82f633af0f04fbde479b82628f0e446e781cca6b0548eaa34d8d1e5279078afe906905aa91922bf69977a92b586541d02a80245334e5321901ea62181f121f7aaaaf89061b36b0f9eb5c9ca22ddb5d09bca32696a262178178745830d0c0dee8fcc9033f8f5c98e5f3eaa91fded998019c068644495dcc3fad1eb4b63821a23b",
+ "0854c55cfcab147838227c735aa7493430369af6251b129c24fca111dc13d34678b16bc625356621f29ea8e47b665ab509578cae546f46e04b013376fc8439d5cde2eb50a36d1303c487fd8456539db6e653b588217b6b273b7b3d79de062a76332662a738cb172c781306cffa8b46f9aceaaf6b663a749763c9db91c5ebb62dd0f94a3d036b82c41b49709fe6c3815e215adf1c2ae55fd9d90f8186c07c37af26d2e0803bbda031317b76cdbcc7b6817529c92ef23b00db2243ffd4767f7c8e9d39781324cef39ddf613e24e4a6351037d62b77ff946d119fb2da47fd757e16d34aa0c53bd7d6fb53472d84ca55f554638e2529702522faa8c177d51394a89bbd4cec850ee6ff565296aad4f2cd6b9f35ad7ff7b7b494b97248e3a894dce393259fa038f067fb28655b6e18edc9a032053e900a2e3d07f7ca52461922710f91f4ec2449a30929eb714d75d9db74f3a7"
+ ]
+ ],
+ "public_share": "9c068644495dcc3fad1eb4b63821a23bf4ec2449a30929eb714d75d9db74f3a7",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ },
+ {
+ "input_shares": [
+ "44118698b73a59751812aa20a73ae412766ef3c4c7559adaf4f08d6d73fbe01849ac4f0da41a26f10b1709d08f56da39953a74ee5cca941b880a5857b143cdeb7065b4b8f6b13b474040cd9e5307fd42850c79e49dc4808a8bf2d976223522179142c2cce38fce9218a371029ac88597283e246464233e9d7cf7048bbe3d18d369dfb8d462dddbe94e33f7ebc07bf0cbe8ecf9e42a156f1fd2b6c434eb62813c0929e78c86cf9bcfad5d54287598c986364fcb6fbbfa0db79dc0f4c1dbaebed54201c88b9e1f93a7fcabc0137d2b6c8ec6f423d7aeeced8f7dbd4c64e7ed595b6e5d76034a16c5686a8982397ef1e882232a95e11e7377d5b758015b716472c4e0aa9021bf2f861e18507f7f8435b55a493c8f7357e245596c08975169be3fdf4f2bc8600e680b9013f52b67000959ce3a588caaabdedb7d6201210902695051d808571846039dc672be3d2a7d2d25137baf47f5b71d1d907c9db4d3c20045cb32bdcf9c0094bce467da04ed90e885c9e0765a41d98cc0cc454d1d97efe2255eed21c3b2297d9d0717f8d46d1a016ab899fabd89620aa6090d21ad7226d173f23cbdd31702582ca06b336d277c4f39903414ab2baddfa578bce3be8ba27d68651d720b8401a4ffc61c999f628cdc71c058767c63f23e8b933add17cd3e50ab8540c9ebf935b2912fa26d68e2cc9289e4f894b8d03a81b8d306cadabb209de35c990d4ceea42abc4a0581b6114c77e4cc66c01be07deb7bdb8db23df5d67398497a30ea78518ff759304b5269502f93848838ba2d3e1737aadbbcbd4cde25689fff7a738df9017a4f2986c8fe8b8ba6b6f87b4dd6ec84876ba076c31039cf59b695313060ca1dfdb288c8924ebcaddddf9d067f2be6033af80313292c03996a39281c78299d8549d12cd8427104783575ec604930ab55e288606fdeb863afbeb9de6a009694c055c34d68e19c19ef3fa851363493cdf197c201958449e57e327b15eb5e25d2d347374a85e4685b432a15f4f768fa0b180f6db9f0af65cbbcb0c137a2e12cbb0aadf81e78244e2b8855634a9d0014005d9c9209381943f019df54779b4452a47ce0f223ae52a4d28d725d96e40b37b250499508838bc8a7ccb133f6a02fbfc91fa1c27685786808ae4a45e08cf841c79f3a61b58ae87005dd4e43920089fc2bc23b8c6ac3aaf2081a14edf30a0299f3094410689ec026a8bf8ba2b1c470583987c30d5d8ca6e7ea605d0c7661dba95beef2f4b94f5306317ecfa60010d6b18c2aebb994a4559fad9f3538ee7eaaf35761f7640b807483793ed8ab39e20672da387979a8171eb1425700e257a912e645a80739e5d494ba6d419dcd4fec13aa806fcfcc84480d7e0e676916aded6f1cf9d69f7e958dceae1edaa11b2569954b7689e647906cccbdcbc2897f139356d9c85168f08ed8990aefc891158b1b89d7c19d3c56ad2a91d3de46ada48ec6338d13efb16c4cb49acd981a044c335240ce7d1db84fde51058290cae528cb7dc5794daa652268d9e5d0fa639a8549c9fdcd3fd126f653f9b970d804fdd4f420e473a31410fe9a84fc43ae415d008ac86ca0881f737382196cd5b6dd4b8673cb515ef70c4624bea32c22a7b72c2f8e1c2fc693a4905215e10580aef647be4bd36baab91c2867bcec745bc5334ce8cda1a0d77f6bb5f1838c60904f8ba7aebf0d2529e87c41702b774c6f11c632d35f477988847de39626fd7e83b07ca2de2d7dbd68d07617dc590e00684c79ff1d8ff484a31056b53b29cbe470c8bf99515d7ad2939120d3b9b9ebabfb29d0e7b77cc7bb5ab97fc44591ee036de0206b8331c99c75e8bcc50ac1cb75fec3fb640318010d3ddeaaf423d14d2d715e7cf81ee4d01ad0c0f09c66b2e0b396b93c2bc97b21a42cdafe748aa4b59c250e4639be7173f4cff260339d2797e402653a3bef19a0a17763395889c4269679f6bd0289a356eaf0f06b409d24d4c112ff8f60b9383669677635f20d8eeed5c38d9500e39dca878f578b4980f374ee556aa3458b551628ff9f110d11b7f2497195d9bf3c9557e6f3d11c05f52158aab8f6485cdecfa158e592453351f1866faed652e75b37562a4c696867a89ed8b55355c82c6b571918d3995cb6516f00742a7f0974f62ca846d1306422176a204627930693eaf08951f082629d0a5537aea1d8729693798896fb16830a7cc7b29737f296373045c4b3272022ca8eba72c601043d08da35f439bc7d0100d6aeb7c2a7cb74a82c9abf8982362807bed855c50ebe0e571d2624f06387b4439e7580af40033dccb657fea66e721e9b2c20cdd3dba93c3261c4ec327a89ed4007b7393820f46a60ace5876392117b97b9a358a1286944bcf0e7cf4f471d46694dc37fc670aee1d4cd7fa002020f5c7ea0bc65d0ca4e42729107abeab7a2f7b86d9f663a73485f54c4870609a0789554bd2f623176f563b8d577965464bc1d7ecca70103d13c963f741f6981cb1d83a7eb09878d39d5ec7e007d390fd93c9dba87670e981d6e21069f72602526625fd88a5cafc400b01720fccc97763672331ee7db22c0932f46dfc351a6df904c48d8a976ce693f58706d7f16ffb3c0ea860cc818c14c42c925832c041c075fd291ba417723cb6e68e5deea5716298370a7c6aae23beb7276354591e9c084351aa1ddb79d9067319c93931e5018cc62705ac5dd58f1a8b7439bf4bcff7192ee243138bc26a9a2c42eb57859751a58f04f4f83b4b673254700571cdcb66a38b1187b425df9e234484fa168dd01ab675fb38b167ec06b6b7878311fcf2f20ca9aee115b9d683375ce1dc64f98d93136680c056af071501b2b50ea4b267cab3e117c157683ba9f7a10069efa0afab0ed9ec6444ddf16d5e834834fe2e0dbd0df92d6b6c19697673837bf51d697303132333435363738393a3b3c3d3e3f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
+ ],
+ "measurement": [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1
+ ],
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "3d1365280c0256e2bf8fa1dda6c8210c",
+ "4cf0ce9963cd8783355469ad43277e53",
+ "5bcbc3ef2ce2fdfc4422b2f29caa7aec",
+ "f365690aac38d90228da50a3a2e2355a",
+ "bef6746cb91b25006fe29bc5b9dbfd4f",
+ "2b1e7357292ff6949783aafc745cf130",
+ "be9d92bfc7f862e84f259b7440b04896",
+ "8d2ebc51032cb90072570bba4b64f80a",
+ "8f6e96998e4aeca59e1693fabe8aeb91",
+ "9325702c90f2ce3136faef39b2b783e7"
+ ],
+ [
+ "c5ec9ad7f3fda91d24705e225937def3",
+ "b60f31669c32787caeab9652bcd881ac",
+ "a7343c10d31d02039fdd4d0d63558513",
+ "0f9a96f553c726fdbb25af5c5d1dcaa5",
+ "44098b9346e4daff741d643a462402b0",
+ "d7e18ca8d6d0096b4c7c55038ba30ecf",
+ "44626d4038079d1794da648bbf4fb769",
+ "75d143aefcd346ff71a8f445b49b07f5",
+ "7391696671b5135a45e96c054175146e",
+ "6fda8fd36f0d31cead0510c64d487c18"
+ ]
+ ],
+ "prep_messages": [
+ "22b05b9abf6f7798c91fb089ec73d79c"
+ ],
+ "prep_shares": [
+ [
+ "f9ab3aa30354eb87abdd838ca558b6cba06d3c978291ea82c4c856026ce4a3cb3dec40f98bf1cf3db33e3a736043891abbb4629ed714cfb72b9a70be2083cc84c41c02e448c46154ed923d78db089e67c7bbe0ef236ecd77f99c8d5e5272f4aa0320cb7d3fa0323ddcddcdb0d628146f3a94850ce63a023fa1ec776f6082d00e5fef53097f1b9a562fe9c3c4b1d9b03a87131642b49c990eb174e205bf6d68af4248001090e9ee0c2c52614d1778ac60eaf3003e3714c6ef5c99442ad527fb434fea0dce4d6fe6cd3de25237bf75d34a3b619efbec942fe7f466c96521a9672a1b8773d0a3c0009b8020cc9719ddae7aee79d2a751e4405c17493fb96c28b9dfd90c135f76582ed5f72b0867cf2276d0aee16e5c44d6ac86eff63369b58b79fd5f34e68b4406f78664224591044c64f776d62683c1ad354cfd588c2168df20c6374a2b13433b05ee12db5fdd45070eac",
+ "0854c55cfcab147838227c735aa74934a0198736b579cfe4f87a1ab05d6cecc278b16bc625356621f29ea8e47b665ab59a91a8a0b72799489818a54757992f45cde2eb50a36d1303c487fd8456539db688dec5f51c76fdade09bf05bb59d8f82332662a738cb172c781306cffa8b46f986b9544adb196632fd3464f73faa14d8d0f94a3d036b82c41b49709fe6c3815ee39a9e9f46241986e33eb72c43757e3d26d2e0803bbda031317b76cdbcc7b681efe9a68224da578206e4518bbd64e9b69d39781324cef39ddf613e24e4a6351009ef3a1ca5f6d5b556077ed9c6e12b98d34aa0c53bd7d6fb53472d84ca55f554bff591feeca2f8c458b72bc0dd4a9dc4bd4cec850ee6ff565296aad4f2cd6b9fe2ca244753a83522e0d4496a1c66cdb8259fa038f067fb28655b6e18edc9a032053e900a2e3d07f7ca52461922710f91f4ec2449a30929eb714d75d9db74f3a7"
+ ]
+ ],
+ "public_share": "374a2b13433b05ee12db5fdd45070eacf4ec2449a30929eb714d75d9db74f3a7",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ },
+ {
+ "input_shares": [
+ "44118698b73a59751812aa20a73ae412776ef3c4c7559adaf4f08d6d73fbe0184aac4f0da41a26f10b1709d08f56da39963a74ee5cca941b880a5857b143cdeb7165b4b8f6b13b474040cd9e5307fd42860c79e49dc4808a8bf2d976223522179242c2cce38fce9218a371029ac88597293e246464233e9d7cf7048bbe3d18d369dfb8d462dddbe94e33f7ebc07bf0cbe9ecf9e42a156f1fd2b6c434eb62813c0a29e78c86cf9bcfad5d54287598c986374fcb6fbbfa0db79dc0f4c1dbaebed54301c88b9e1f93a7fcabc0137d2b6c8ec7f423d7aeeced8f7dbd4c64e7ed595b6f5d76034a16c5686a8982397ef1e882242a95e11e7377d5b758015b716472c4e0aa9021bf2f861e18507f7f8435b55a4a3c8f7357e245596c08975169be3fdf502bc8600e680b9013f52b67000959ce3b588caaabdedb7d6201210902695051d908571846039dc672be3d2a7d2d25137caf47f5b71d1d907c9db4d3c20045cb33bdcf9c0094bce467da04ed90e885c9e1765a41d98cc0cc454d1d97efe2255eed21c3b2297d9d0717f8d46d1a016ab89afabd89620aa6090d21ad7226d173f23dbdd31702582ca06b336d277c4f39903514ab2baddfa578bce3be8ba27d68651e720b8401a4ffc61c999f628cdc71c059767c63f23e8b933add17cd3e50ab8541c9ebf935b2912fa26d68e2cc9289e4f994b8d03a81b8d306cadabb209de35c990d4ceea42abc4a0581b6114c77e4cc67c01be07deb7bdb8db23df5d67398497b30ea78518ff759304b5269502f93848938ba2d3e1737aadbbcbd4cde25689f007b738df9017a4f2986c8fe8b8ba6b6f97b4dd6ec84876ba076c31039cf59b696313060ca1dfdb288c8924ebcaddddf9e067f2be6033af80313292c03996a39281c78299d8549d12cd8427104783575ed604930ab55e288606fdeb863afbeb9df6a009694c055c34d68e19c19ef3fa852363493cdf197c201958449e57e327b16eb5e25d2d347374a85e4685b432a15f5f768fa0b180f6db9f0af65cbbcb0c138a2e12cbb0aadf81e78244e2b8855634b9d0014005d9c9209381943f019df54779b4452a47ce0f223ae52a4d28d725d97e40b37b250499508838bc8a7ccb133f7a02fbfc91fa1c27685786808ae4a45e18cf841c79f3a61b58ae87005dd4e43930089fc2bc23b8c6ac3aaf2081a14edf40a0299f3094410689ec026a8bf8ba2b2c470583987c30d5d8ca6e7ea605d0c7761dba95beef2f4b94f5306317ecfa60010d6b18c2aebb994a4559fad9f3538ef7eaaf35761f7640b807483793ed8ab3ae20672da387979a8171eb1425700e258a912e645a80739e5d494ba6d419dcd50ec13aa806fcfcc84480d7e0e676916aeed6f1cf9d69f7e958dceae1edaa11b2669954b7689e647906cccbdcbc2897f149356d9c85168f08ed8990aefc891158b1b89d7c19d3c56ad2a91d3de46ada48fc6338d13efb16c4cb49acd981a044c345240ce7d1db84fde51058290cae528cc7dc5794daa652268d9e5d0fa639a854ac9fdcd3fd126f653f9b970d804fdd4f520e473a31410fe9a84fc43ae415d008bc86ca0881f737382196cd5b6dd4b8674cb515ef70c4624bea32c22a7b72c2f8e1c2fc693a4905215e10580aef647be4cd36baab91c2867bcec745bc5334ce8cea1a0d77f6bb5f1838c60904f8ba7aec00d2529e87c41702b774c6f11c632d360477988847de39626fd7e83b07ca2de2e7dbd68d07617dc590e00684c79ff1d90f484a31056b53b29cbe470c8bf99515e7ad2939120d3b9b9ebabfb29d0e7b77cc7bb5ab97fc44591ee036de0206b8331c99c75e8bcc50ac1cb75fec3fb640318010d3ddeaaf423d14d2d715e7cf81ee4d01ad0c0f09c66b2e0b396b93c2bc97b21a42cdafe748aa4b59c250e4639be7173f4cff260339d2797e402653a3bef19a0a17763395889c4269679f6bd0289a356eaf0f06b409d24d4c112ff8f60b9383669677635f20d8eeed5c38d9500e39dca878f578b4980f374ee556aa3458b551628ff9f110d11b7f2497195d9bf3c9557e6f3d11c05f52158aab8f6485cdecfa158e592453351f1866faed652e75b37562a4c696867a89ed8b55355c82c6b571918d3995cb6516f00742a7f0974f62ca846d1306422176a204627930693eaf08951f082629d0a5537aea1d8729693798896fb16830a7cc7b29737f29637303d4b2d335a15f1c48ed11d7948cae1b1efcb5af7c398f535e799f58a13109605cc3afae7e08683e40b1d015cfb8de1f5ca44d2eaa0fbfa549b4aa3933de82380b81ddd451d5e44a8f7f456355dfa125c002c8c5e7b2697e33dbd5cc1ac7ac8bbdfcb08ed49999a24a72685a31cdc25e0c9a27be6eb32af2d260f6d60427108a552cbe2a99ad070aec066c78bbf260e49e7ead7646ddd80d2fd067e7361e83e23aa3df8810cb4a44ee4b1205ecc8c548c064345134bb02e081a65ade1d3ec4523448d81153fa692e852e443120c8aba426dbc11bcef30ab6de561000c5be09b10524cedfab2395b99861a6f0c7e9c820dcc97763672331ee7db22c0932f46dfc3591f66851255b173a26f12c813e393a75c279385a4ef1668e0de195f818a9553d2a096f927333e1b445c8f212b665412b3f546fc56600ff4bc71f71f3c8aedc788a14e5e6f61343cc668e4d7e8d5b22314d9727e7e216f01d26d84168b8b8cad052eed93ec12355123dbbe497b1d0f6a92472c5181623dd46fe47e576cc7e804e23f58098d06504f11e23d87debccc25206b7ab2e8a54e197ecb27785fa834700ce9dab85af30a0cb4e385e6469db3e14a8545b97d72b9b4ffec701ab993457758873ec75af28a865542c437cf00bfc8092eebbb13b15cf9b481804696904c6ffae417be85dc3e8889fc8d2bf1cc7386303132333435363738393a3b3c3d3e3f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
+ ],
+ "measurement": [
+ 255,
+ 255,
+ 255,
+ 255,
+ 255,
+ 255,
+ 255,
+ 255,
+ 255,
+ 255
+ ],
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "3b1465280c0256e2bf8fa1dda6c8210c",
+ "4af1ce9963cd8783355469ad43277e53",
+ "59ccc3ef2ce2fdfc4422b2f29caa7aec",
+ "f166690aac38d90228da50a3a2e2355a",
+ "bcf7746cb91b25006fe29bc5b9dbfd4f",
+ "291f7357292ff6949783aafc745cf130",
+ "bc9e92bfc7f862e84f259b7440b04896",
+ "8b2fbc51032cb90072570bba4b64f80a",
+ "8d6f96998e4aeca59e1693fabe8aeb91",
+ "9126702c90f2ce3136faef39b2b783e7"
+ ],
+ [
+ "c5ec9ad7f3fda91d24705e225937def3",
+ "b60f31669c32787caeab9652bcd881ac",
+ "a7343c10d31d02039fdd4d0d63558513",
+ "0f9a96f553c726fdbb25af5c5d1dcaa5",
+ "44098b9346e4daff741d643a462402b0",
+ "d7e18ca8d6d0096b4c7c55038ba30ecf",
+ "44626d4038079d1794da648bbf4fb769",
+ "75d143aefcd346ff71a8f445b49b07f5",
+ "7391696671b5135a45e96c054175146e",
+ "6fda8fd36f0d31cead0510c64d487c18"
+ ]
+ ],
+ "prep_messages": [
+ "4b28ca5fab189f5689d02be161fe25af"
+ ],
+ "prep_shares": [
+ [
+ "f9ab3aa30354eb87abdd838ca558b6cb4cd1280dfc7d2f12bcb14c5a38a5fa1e4225a50845bc43cc7276668331627f53e6d1debec49fc79a6e0a2382b73e01d1af45275c3e553e9f0df2dce1fb8adf9b7cc9862e001ad0d0059d27c68b40e998a4233df802cb98ef8c94504a86e9b0e423e0661acc82059937329f34832d079f0184e04d6aafecf62dee814f748123de797d05203e140ccc9be383de282e7d377e0e3400af264e528f66cc39c14f6b590939d50e82fe5df4fa1e0aa96c27af32a5540a1ab456284c050fdf4fc7190c71acfc9d952d03d4af955b8df3f10fc64b48f1399d22792b7b18e64c7c09d986b27c4874ee16fff4ecde9d89391d3ca98a14f95ce098c05629305bb26e0db0955be0bafa82ff2a6b48283de372c395862a636d4a9bfdd06a15405a71a1d56a5a30afa2bde6fc55d8a3386fe4bd3c08985014376e4adc53e094949d34b36f1e8b16",
+ "0854c55cfcab147838227c735aa7493459da23320d129aafa331318931d85cdd78b16bc625356621f29ea8e47b665ab5d29caacc5ba36200516852c360c0a2d9cde2eb50a36d1303c487fd8456539db613567966c72ef1b9f8b8f2e93aebdc1c332662a738cb172c781306cffa8b46f908c1bfd01acb45c5c06c9ecb16265a3fd0f94a3d036b82c41b49709fe6c3815e1af0509da314c9297ca795e4487c9cc326d2e0803bbda031317b76cdbcc7b6819dd6910f3002a99c7075366ab035710a9d39781324cef39ddf613e24e4a635108fbc5c1b9dada07dd81a620426914410d34aa0c53bd7d6fb53472d84ca55f554883acb353f6718ee88b8e595fe5b9373bd4cec850ee6ff565296aad4f2cd6b9f2bdf8fd9fae82be3d2039778cad3aa16259fa038f067fb28655b6e18edc9a032053e900a2e3d07f7ca52461922710f91f4ec2449a30929eb714d75d9db74f3a7"
+ ]
+ ],
+ "public_share": "14376e4adc53e094949d34b36f1e8b16f4ec2449a30929eb714d75d9db74f3a7",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_1.json
new file mode 100644
index 0000000000..21fcfa001b
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_1.json
@@ -0,0 +1,146 @@
+{
+ "agg_param": null,
+ "agg_result": [
+ 45328,
+ 76286,
+ 26980
+ ],
+ "agg_shares": [
+ "447fb76d69adab4dc1990d2289325675e67772e564baab6396c6b45c58a1c5febe9c72ab66aab2aab4b588ff774cb480",
+ "47e6ff190ecf95c1c1941e2b03db246104c982f459555c7d30035b353f18e8985d9e4661cd30031dc481a1afdc0df13b",
+ "864b49788883bef060d1d3b273f2842916e90b2641f0f71e0136f06d684652684a2e47f3cb244a386bc8d550aba55a43"
+ ],
+ "bits": 16,
+ "chunk_length": 7,
+ "length": 3,
+ "prep": [
+ {
+ "input_shares": [
+ "5d82bd1f81516122465f8a60a3209afef5a5c181fdfd80d20d280edb0ae8ccc4953eff5c0efe473d411cf4f3b2e3fd320c83c6b8f2c626a42d25f89594365561966e130ecf8a778e42ce7cca37b919eb9304560ba6a60a5e5b523f5ad397b378edff4b21af66fba2f59db74e46ffdfa077bcea50472d6e771640a71fa31dd96446a2d8ce308904ea0d94760e7f8721d1531754521de6b338a20bdc8eda1d1acb6f3407a9f6f9d6cf9ccc3696c4d3226e89cf3207643a12d8c30332a8d364c97aaee81f4dc31ad62d49506e422e146492bd92a5cc933532fbfc1ee2e8e33116414358edd4baf633cdd80856f8132124171d9a2d989d3a9cf5d1d2b27baf94a5c523cf7ae624b8fe1c8ffc2229bbeecfc18e91c8683df7c579390d8b31ca87372cb5ebbe716d0edc0fe8f10c54835396a68cbacc670eee07dffa3203f8b202dc414ccb317950b35d8f4da3f0bafe8f4b0d09b5103494ed9cf9075bfd19c47f8bdee607eccea1987b4bf6ba603e29043ef636b1b327e57adf1b29b098d4eadfebb737a5ea3558794f02b97f3611034adf002518d85e769210bb2ed2e4b4390433c55d6140ffda97a5018ee007adf5125f079bebdb6eba6c35d0504d8b7a9cbbf0bd9d57bd5b563fdc052a492a7dad4a3c782b69b711ac2969758cffc3d9089a34716517c45fbb164a6bd15a001d454dfd444becef4c4a7fdbc1aaf3b7e0983b900222674a726db2b1b155190cec29c6afefe3841924dd7b212437fb10bffc8a17cea09a97ec2dfafe897e8ad4c5418946525e0908ac8790580a47a17a8089e7b78498f2a54375778e387b0985293431e2103f51600211e6e9a3f388e53d2df072d486d4c4838d8d8601fad2bd86d51ad3a58aebc0d8f6bac048d77968b26826cf545b44f7513667ac696564df8113529415a6e467d3a9f6bda8630717be753a45b5d688bbc4b95712f3bec044eb26db66f23861bf870cfb30347361e81a451f7f17642f6cbd902e92cc063b7cd4cdffbec78cb3f1957d650f89be7798894f6594ae1965964b5968c67003b247c0e83d3cef1ba2feef4c5c59d42a3efa8309f0ec4e9497b1c5a7c6b72f341d4ce5950bd12be5b6b22f32eade71f969f4ee1c0a864741fb2b5b1ad278c5f2f27000e4237b71cc664a87c50a7088b36bab5ad5a5494d599407fda9df6c538ad53563c222d3242b635116f5246b9dd6b7aba1f5abda8fd607ba18a3155c6e6c877ba0965f4005c8f475e5116bd7f899ba48ad299e5007401e49b85abf0ad681cbad302393975d682f6fb5a0795702ada0cf559198efff5ed8a16b12d1e866545db67d13ea5b7e59557776d458f5872d20ab0a3f6c74d61345bb6cd1f2dec5ee4a8d1c96d22a7b3c8ef21c1284d0785a56143100639cbfc12d1a6582b16b4bf804f6503665f275e5de6c60aac82324be975fedb2dd651c1173635fde95660cc844d347d10f8a24586a75597b1c39e828063364e13921665af885b721addc72a72d9a23bb6aa7aa3169804cf944d523d855c97a71d723b464e3976d1264bef3c266ff630ac23753eb79ad90eb5593ce456db34e977dbb19cfb58c52cbaf4826858368c3cbd8863abb5b2b95c36a447b8a4eef73e276d8bc61be6a420a12dd507bc72ef767bf49ddc9a7dcf61290b191ca4c1444e4863f1438e480a661f860c6868256aa7390e1a5033292afdcb6da8c464298c1cf5bc86bac0ad5ee5f72219e33a356a4cc3bdefd606162636465666768696a6b6c6d6e6f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
+ ],
+ "measurement": [
+ 10000,
+ 32000,
+ 9
+ ],
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "22c1e77978e4e319838804b62d66c7d1",
+ "4eecd0a1213e3921caece61ec83597ff",
+ "27112639228e3b8e913cd8ff27c4e62a"
+ ],
+ [
+ "18a2aa085a9adc958c310ab9abf3b675",
+ "0243d6a6c871c929a8ab73bcbfb2a2dd",
+ "75df6c20efbaab098480e08f49afa5be"
+ ],
+ [
+ "d8c36d7d2d813f50b845f19026a681b8",
+ "b24d59b71550fdb45567a5247817c622",
+ "6e0f6da6eeb61868ce4247708e8c7316"
+ ]
+ ],
+ "prep_messages": [
+ "065f5893e9afb58b358f78e7ed2cc07c"
+ ],
+ "prep_shares": [
+ [
+ "fedaa3d68353f75a2db6a1e49b2397a2bed007840b0f6ccc5ff3d89835264b58afa1771f5d2a277b65bbc2190fcac717b4f07c6d7ac4c692ad519e8a33e6d22479dfdaa6e2d3eb787ff4c9cc9deb4638b69a422203daec5a3a9b28f4eaddda1eef0000c41066465d05570989f605ad679d3d6906a8eba159f5af3995de50bdd1068ba7c0556bbd0724ada90ce58efc5b7c24f02cbc919cdb90bd915098f1f7b4bbc85c69e091f780fd70df4abb883070d02d2e06f76874cd4496526ce4aad58adf2b97e7cfed76951b532ebde9a3518e407992b67cbc6f3ccef64065bc5c214973167fea3f7baea5bf44bc32b85e37fb1f12524e4f720b7d10547ea1b558c569220ea8f5008a9be1e061606e347c3c49",
+ "cb8307fb467bb023448e58c74d159bf4ed77785c059b1bfe3c5b36ab3bb46cc6051853dd2151e2cc480d5164567c8c41df857ef182519ceaf1c704a25e6c948712d4839078fa72b1e64e8531f3e54c090d01fcc6023c8dc28300ceb5fd722c80211848dd2c787bd764b2099de3139df3e7472bf3c98fc31f1d3e09b8deaada8bb19f2941d9f4660018a051ede752680aa6d05e91c0c2feb5199be821f7eba9e3abe594acb8e9611a81294b8ed708fa93caa4f00ab2df5a298a09a7d71924a9ea0b98b57a0d21fda8ff765c0394041a9a2fce409f56e24f387aba5eec7bb507d18f623f5f376d80e762ee64ef3db152a4eaa42964a69f705f15eb77df0cf6f81589a8eaa4f01fe1b5aa656a0919ae5449",
+ "39a1542e3531588156bb055416c7cd68c32c28a3ac4eed2bb0f0460d41e3634bc0746eb13013792fcc318698a96b1343b152abb747abd3245a70d95eaf31f330e9e844395897d8d5f475d4644149864ca15c31da48dce96e593075a17d4deff6ae67d137adc6f38ec943c596b6fec177e66c119988225c82ac239141c8448add3f9b5c6e59d9736159ede439854b0532d9253f45dd09cb6b800fab1308b1f265978eab94b6bf4105729f7da8eddcee387a2a1eac1c64418e342368a3478fa335500371d0434c5e6511da60302f9947e84a52c49e6dc731f79ca0543441bff7a4cd909fe76206570074fca8dd8cc511ed104a88289bd3cd4d9e34a6c9a50a03649a431dd8df92d78dd6c0d478dd93c0cb"
+ ]
+ ],
+ "public_share": "220ea8f5008a9be1e061606e347c3c4989a8eaa4f01fe1b5aa656a0919ae54499a431dd8df92d78dd6c0d478dd93c0cb",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
+ },
+ {
+ "input_shares": [
+ "5d82bd1f81516122465f8a60a3209afef6a5c181fdfd80d20d280edb0ae8ccc4963eff5c0efe473d411cf4f3b2e3fd320d83c6b8f2c626a42d25f89594365561956e130ecf8a778e42ce7cca37b919eb9304560ba6a60a5e5b523f5ad397b378edff4b21af66fba2f59db74e46ffdfa078bcea50472d6e771640a71fa31dd96446a2d8ce308904ea0d94760e7f8721d1531754521de6b338a20bdc8eda1d1acb6e3407a9f6f9d6cf9ccc3696c4d3226e8acf3207643a12d8c30332a8d364c97aaee81f4dc31ad62d49506e422e146492bc92a5cc933532fbfc1ee2e8e33116414458edd4baf633cdd80856f8132124171d9a2d989d3a9cf5d1d2b27baf94a5c524cf7ae624b8fe1c8ffc2229bbeecfc18f91c8683df7c579390d8b31ca87372cb6ebbe716d0edc0fe8f10c54835396a68dbacc670eee07dffa3203f8b202dc414dcb317950b35d8f4da3f0bafe8f4b0d09b5103494ed9cf9075bfd19c47f8bdee607eccea1987b4bf6ba603e29043ef637b1b327e57adf1b29b098d4eadfebb736a5ea3558794f02b97f3611034adf002518d85e769210bb2ed2e4b4390433c55d6140ffda97a5018ee007adf5125f079bebdb6eba6c35d0504d8b7a9cbbf0bd9c57bd5b563fdc052a492a7dad4a3c782a69b711ac2969758cffc3d9089a34716517c45fbb164a6bd15a001d454dfd444becef4c4a7fdbc1aaf3b7e0983b900222674a726db2b1b155190cec29c6afefe3841924dd7b212437fb10bffc8a17cea19a97ec2dfafe897e8ad4c5418946525d0908ac8790580a47a17a8089e7b78499f2a54375778e387b0985293431e2104051600211e6e9a3f388e53d2df072d487d4c4838d8d8601fad2bd86d51ad3a58bebc0d8f6bac048d77968b26826cf545c44f7513667ac696564df8113529415a7e467d3a9f6bda8630717be753a45b5d688bbc4b95712f3bec044eb26db66f23961bf870cfb30347361e81a451f7f17642f6cbd902e92cc063b7cd4cdffbec78cb3f1957d650f89be7798894f6594ae1965964b5968c67003b247c0e83d3cef1ba2feef4c5c59d42a3efa8309f0ec4e9497b1c5a7c6b72f341d4ce5950bd12be5b6b22f32eade71f969f4ee1c0a864741fb2b5b1ad278c5f2f27000e4237b71cc664a87c50a7088b36bab5ad5a5494d599407fda9df6c538ad53563c222d3242b635116f5246b9dd6b7aba1f5abda8fd607ba18a3155c6e6c877ba0965f4005c8f475e5116bd7f899ba48ad299e5007401e49b85abf0ad681cbad302393975d682f6fb5a0795702ada0cf559198efff5ed8a16b12d1e866545db67d13ea5b7e59557776d458f5872d20ab0a3f6c74d61345bb6cd1f2dec5ee4a8d1c96d22a7b3c8ef21c1284d0785a56143100639cbfaddd5e94884c05ad97bdc1b9878082a47662898f549754812b390a2bb02ba487c6791eb083959499d8c22ec4b79caf467542aa89e22d69fa2bea599ce1923cb05efda49baa01b0405db15d8cbfe774cf38d520cde78b817177df5ddfdd1b7c5b164c1955aadd97a8ee58a53940041a8feb79ad90eb5593ce456db34e977dbb19e3054823c514afc4e5ca9c5a7abdf60b2ad80e66199c131e1dad4436e5289a51acb7aff16412afc36a49d37a813224bbadcfa7c6ab7e817fab68ed0be42d24ca34df61c2d8a38df8d0fe92416f131481fcc5f12eee6f2e3fa7b8035d631770c4faa15307c8f847e907b1b0ce96f9fbc1606162636465666768696a6b6c6d6e6f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
+ ],
+ "measurement": [
+ 19342,
+ 19615,
+ 3061
+ ],
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "a0e5e77978e4e319838804b62d66c7d1",
+ "edbbd0a1213e3921caece61ec83597ff",
+ "131d2639228e3b8e913cd8ff27c4e62a"
+ ],
+ [
+ "18a2aa085a9adc958c310ab9abf3b675",
+ "0243d6a6c871c929a8ab73bcbfb2a2dd",
+ "75df6c20efbaab098480e08f49afa5be"
+ ],
+ [
+ "d8c36d7d2d813f50b845f19026a681b8",
+ "b24d59b71550fdb45567a5247817c622",
+ "6e0f6da6eeb61868ce4247708e8c7316"
+ ]
+ ],
+ "prep_messages": [
+ "25034fec369564c831e89105a21ed2c7"
+ ],
+ "prep_shares": [
+ [
+ "fedaa3d68353f75a2db6a1e49b2397a29e8bb52fe68533a6e7518d7c431765b09d9fb09303205bd20b7bad45f8ee66e18d4ff77adffd7c0b1990ba9c1c18c0d83c70aab9194ab6e494736b7521bff256e44fb48a11052214545c4fc23b0424f8965526d4d9d8d65bb919f8e823db52d0cd97bbb67e45ed5ae83205b3c379c8b72f4220e4407e1f46c60ea678ed8d47742d82abe8cc8b00055cbeb2bf9c5cf03ee851b53b57812560f8c16902a3ca3e54d95174e928fcb415d903ba75e20b5c824ad2d32f70d2375df7fd78e3a9da48d881c81e5a3126d013776adc18fa8ffbfa1ad84cc857cabdf17c81c8f08d04e9dcf11e92808e461939e811b768e5fd98c3186d21176ab71c0fd31e38c5ce590cae",
+ "cb8307fb467bb023448e58c74d159bf447187a131bca6a8f66f613129c42c481051853dd2151e2cc480d5164567c8c4164b4ac35f70fe6b64517e65804ca767a12d4839078fa72b1e64e8531f3e54c09efe5a1f7aca60dd9e174711c82596e04211848dd2c787bd764b2099de3139df35aacfef634fc7a8fd7d4cb8f68a8c4eab19f2941d9f4660018a051ede752680abcbc6d60afb6984df051b2a1940016a2abe594acb8e9611a81294b8ed708fa932e03ad037523630eff76925e1a8076900b98b57a0d21fda8ff765c0394041a9ac56ec6717034855e757728c6617c78e28f623f5f376d80e762ee64ef3db152a4eaa42964a69f705f15eb77df0cf6f81589a8eaa4f01fe1b5aa656a0919ae5449",
+ "39a1542e3531588156bb055416c7cd6884463d0b107893ff1174455e3c438265c0746eb13013792fcc318698a96b1343f33bbecee2d08efabd7facd829d80dafe9e844395897d8d5f475d4644149864c3faef9fbd6b690a3750c76e3721c6667ae67d137adc6f38ec943c596b6fec17750073dadaecc860ca8ce32846d68208c3f9b5c6e59d9736159ede439854b05328ab3d8b398c8d0d7401a8718d9aad830978eab94b6bf4105729f7da8eddcee386ddf59f7d19da2437c7656a1f3d873c2500371d0434c5e6511da60302f9947e8c857cee7aa680bb0dd711dfda75fe0a0cd909fe76206570074fca8dd8cc511ed104a88289bd3cd4d9e34a6c9a50a03649a431dd8df92d78dd6c0d478dd93c0cb"
+ ]
+ ],
+ "public_share": "186d21176ab71c0fd31e38c5ce590cae89a8eaa4f01fe1b5aa656a0919ae54499a431dd8df92d78dd6c0d478dd93c0cb",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
+ },
+ {
+ "input_shares": [
+ "5d82bd1f81516122465f8a60a3209afef6a5c181fdfd80d20d280edb0ae8ccc4953eff5c0efe473d411cf4f3b2e3fd320c83c6b8f2c626a42d25f89594365561966e130ecf8a778e42ce7cca37b919eb9404560ba6a60a5e5b523f5ad397b378eeff4b21af66fba2f59db74e46ffdfa077bcea50472d6e771640a71fa31dd96445a2d8ce308904ea0d94760e7f8721d1531754521de6b338a20bdc8eda1d1acb6f3407a9f6f9d6cf9ccc3696c4d3226e8acf3207643a12d8c30332a8d364c97aafe81f4dc31ad62d49506e422e146492bd92a5cc933532fbfc1ee2e8e33116414358edd4baf633cdd80856f8132124171d9a2d989d3a9cf5d1d2b27baf94a5c524cf7ae624b8fe1c8ffc2229bbeecfc18f91c8683df7c579390d8b31ca87372cb6ebbe716d0edc0fe8f10c54835396a68dbacc670eee07dffa3203f8b202dc414dcb317950b35d8f4da3f0bafe8f4b0d09b5103494ed9cf9075bfd19c47f8bdee707eccea1987b4bf6ba603e29043ef636b1b327e57adf1b29b098d4eadfebb736a5ea3558794f02b97f3611034adf002518d85e769210bb2ed2e4b4390433c55c6140ffda97a5018ee007adf5125f079aebdb6eba6c35d0504d8b7a9cbbf0bd9c57bd5b563fdc052a492a7dad4a3c782b69b711ac2969758cffc3d9089a34716517c45fbb164a6bd15a001d454dfd444becef4c4a7fdbc1aaf3b7e0983b900221674a726db2b1b155190cec29c6afefe4841924dd7b212437fb10bffc8a17cea19a97ec2dfafe897e8ad4c5418946525d0908ac8790580a47a17a8089e7b78498f2a54375778e387b0985293431e2104051600211e6e9a3f388e53d2df072d487d4c4838d8d8601fad2bd86d51ad3a58aebc0d8f6bac048d77968b26826cf545c44f7513667ac696564df8113529415a6e467d3a9f6bda8630717be753a45b5d788bbc4b95712f3bec044eb26db66f23961bf870cfb30347361e81a451f7f17652f6cbd902e92cc063b7cd4cdffbec78cb3f1957d650f89be7798894f6594ae1a65964b5968c67003b247c0e83d3cef1ba2feef4c5c59d42a3efa8309f0ec4e9497b1c5a7c6b72f341d4ce5950bd12be5b6b22f32eade71f969f4ee1c0a864741fb2b5b1ad278c5f2f27000e4237b71cc664a87c50a7088b36bab5ad5a5494d599407fda9df6c538ad53563c222d3242b635116f5246b9dd6b7aba1f5abda8fd607ba18a3155c6e6c877ba0965f4005c8f475e5116bd7f899ba48ad299e5007401e49b85abf0ad681cbad302393975d682f6fb5a0795702ada0cf559198efff5ed8a16b12d1e866545db67d13ea5b7e59557776d458f5872d20ab0a3f6c74d61345bb6cd1f2dec5ee4a8d1c96d22a7b3c8ef21c1284d0785a56143100639cbfc3289478e516bd187dc85011217df3d9cc14a8f70c84bbd98d3a48ee1708913c3bd3c479700f0d9a01bc20a88c2c74202d08300dd1b74ec473f59b9f837fa6643b9a7627923e328512a0d1eaaef78c6fdb44f2789df4d6fea8cd33877405fbb744d075db8e2ea1c6363e0cb892ee5f90eb79ad90eb5593ce456db34e977dbb19ceba123f684af758e4bf0d03e1c085d6d425f0fd60afacc5baab06737d4cad9c375e0928789836c34150e196aca25fe1f4092243bdf49bb57f5dab084241ba1557429036f1660bb41b101fe37f03fce0595620833807d9b175ca2db5cc2df167cc1df780e3a73ecbbfcb4950440fb6c0606162636465666768696a6b6c6d6e6f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
+ ],
+ "measurement": [
+ 15986,
+ 24671,
+ 23910
+ ],
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "84d8e77978e4e319838804b62d66c7d1",
+ "adcfd0a1213e3921caece61ec83597ff",
+ "846e2639228e3b8e913cd8ff27c4e62a"
+ ],
+ [
+ "18a2aa085a9adc958c310ab9abf3b675",
+ "0243d6a6c871c929a8ab73bcbfb2a2dd",
+ "75df6c20efbaab098480e08f49afa5be"
+ ],
+ [
+ "d8c36d7d2d813f50b845f19026a681b8",
+ "b24d59b71550fdb45567a5247817c622",
+ "6e0f6da6eeb61868ce4247708e8c7316"
+ ]
+ ],
+ "prep_messages": [
+ "164bb9a531ed86890f679cfee8e40bd7"
+ ],
+ "prep_shares": [
+ [
+ "fedaa3d68353f75a2db6a1e49b2397a2d951596ce321ca830642b1c9a71f119b750393c6c754d535696c304ff488bcc6977ced640b7644d68067fa674f608e0a5751aaca2e39d7e4f47bec846689f311124c532053e2285de1dd28c7430d205d7bef7f1ff5f36d363f8ca7cf16b9d28d7fe79342273ee2629adb1396910910d4f1243c6e17898c5de5b4e50915995e0ec6b2c92fd59cf001c32018e569d540e26a5512100c73b1dfb9e76c4865fb4c8a98d2382c1bd1bbef9cb6f8fee190a7b2c18bb9c694e107ede1966ba61589e8a1ee07c034878188043745d1a13e9d328c35ab0af3a25ad52a2941d5c87ef54e798f310d45c2a44eb9b8b484c4cf2cb11289979db009d84867e096271383f95f17",
+ "cb8307fb467bb023448e58c74d159bf49f9b010f8d3342eccac47f456395810c051853dd2151e2cc480d5164567c8c41b406b0bc3e39acaada3e1565084d70c512d4839078fa72b1e64e8531f3e54c09965aa5eacbdfd1c87023b5c2c1751952211848dd2c787bd764b2099de3139df3696d74860c683106e0ba03981fd175ceb19f2941d9f4660018a051ede752680a2e4d31fc97379acf03c3454eb29d0433abe594acb8e9611a81294b8ed708fa932cd4dc5aeb67e4082571e2c1a9e2e9370b98b57a0d21fda8ff765c0394041a9abc294b2171b29cdda805a50345b159548f623f5f376d80e762ee64ef3db152a4eaa42964a69f705f15eb77df0cf6f81589a8eaa4f01fe1b5aa656a0919ae5449",
+ "39a1542e3531588156bb055416c7cd68bc76b21ba7b0f0ee6be53024718f5ae0c0746eb13013792fcc318698a96b13435bf89e78f7ee3fd7e39a1fdab2ea808be9e844395897d8d5f475d4644149864c3768148cc4a96a193de9ea7fad3ee418ae67d137adc6f38ec943c596b6fec177dc960939e2aa0560144c058bc34cabcb3f9b5c6e59d9736159ede439854b053235b3543dd1ff08e9184d44c28b2e98c8978eab94b6bf4105729f7da8eddcee388df030cba4cd2df0eccbf799ad07d72e500371d0434c5e6511da60302f9947e8a9a78a25434f4d85ce460e1dc1446ea7cd909fe76206570074fca8dd8cc511ed104a88289bd3cd4d9e34a6c9a50a03649a431dd8df92d78dd6c0d478dd93c0cb"
+ ]
+ ],
+ "public_share": "89979db009d84867e096271383f95f1789a8eaa4f01fe1b5aa656a0919ae54499a431dd8df92d78dd6c0d478dd93c0cb",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
+ }
+ ],
+ "shares": 3,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_0.json
new file mode 100644
index 0000000000..040e3f1741
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_0.json
@@ -0,0 +1,40 @@
+{
+ "agg_param": null,
+ "agg_result": 100,
+ "agg_shares": [
+ "f3d18d266d89cb425fd64a19a436e8bc",
+ "722e72d9927634bd8429b5e65bc91743"
+ ],
+ "bits": 8,
+ "prep": [
+ {
+ "input_shares": [
+ "6dc25550077a71c59f7020e3d0e7ac8da5809fa59c2a1c7da50f49f348a2dd8f46ac57b16cf3a153fb3aa17f19b651354b6e5e2666029f55a6e0d76f25269781bb4f7cf5e79ddd703d07a49094e878e48a68b2a4b901bceeb954375740d2385821e421c0d14a2246d80a4ef53b99eb6dac3738491e6a337c124d1bbdc0e1c752ee2e3b77c8f83cf734b152c7c93caab48127d1fcae79f5dc47d4e8f62463408f5c82435087d2a244e8b54a508f8474307003ff6d76327921cfc1b68e893f1eb8cbaf513ed61bbae3d3580c34c2dfae2ceb8a1120842f5db85c78c2f4225452a6f2b618972d56f013db62e73b92a8ec83107719d35a27f5cdc493d73a772c9f5c7bc67f4280e90dc1eadbe043546a8b5975976a00739136f5f4ab37b8d845f32db1c97a831b3a9d2d3bbec621146d5a5f8788d7e7a1958b2a9382c1d9f538b91d9582bab31f496c9ddc517ae206533a8b18e0b3854587379a3120970b0246aa13758de413cee5f99794170de0bbd7479bdf968c1db98d53b30bea4417d54c9cdcc5f5e71bd7367ad95aacfb02693f25bca1a5fd67cfb3ef6406607ecef3bbe052cab782eacce5d25f6589325d20a1d6f2d9beb14c3c89cb18d0042a5376907c057203feffcd8a36b24ecabc6fe4e0133ec68a1313b669c1771b91ffb86c284646ea5ad270c492b5d5d7a24b27655c2a715af2e797823fa97f87df42184add6f1cc26e9762159d43e9548a6a89da738a8a36159369e3aa7d3b2c25c8cf95b788bfd6293b9e66a42d3bde7b00a5822eb4f97347c91f9882d54a6279c22501ce4f3fa5ebca8fcbfd7baff84e687cb8d77b48e8b4026560d873e2b8c0529d02f3d4f1e5764e498cc9d22a5d64b50fb38edc42491e5f1571244bc6269a7fbbe64406b4303132333435363738393a3b3c3d3e3f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"
+ ],
+ "measurement": 100,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "f3d18d266d89cb425fd64a19a436e8bc"
+ ],
+ [
+ "722e72d9927634bd8429b5e65bc91743"
+ ]
+ ],
+ "prep_messages": [
+ "aac7d7306c0cdbbd7e23ef394322d54a"
+ ],
+ "prep_shares": [
+ [
+ "5e6f31522c0cb9b5107ad0c560b6ef9a69553124df856a84affd0a814674ea325a2f1c7fc62f1838a8d7aa8d4263ac0d86243c1f5c53992219ddfef99b94f76d",
+ "a390ceadd3f3464ad3852f3a9f49106571003e04a8d922570934a5812d4a8c45c1cf374cea16117767d4f4ee963acd756d42402e0f2b584af325b34eaa1615ad"
+ ]
+ ],
+ "public_share": "86243c1f5c53992219ddfef99b94f76d6d42402e0f2b584af325b34eaa1615ad",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
+ }
+ ],
+ "shares": 2,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_1.json
new file mode 100644
index 0000000000..8baf391f08
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_1.json
@@ -0,0 +1,46 @@
+{
+ "agg_param": null,
+ "agg_result": 100,
+ "agg_shares": [
+ "f91bcafa315d7cfa26564999203babdc",
+ "722e72d9927634bd8429b5e65bc91743",
+ "fbb5c32b3b2c4f481c80018083fb3ce0"
+ ],
+ "bits": 8,
+ "prep": [
+ {
+ "input_shares": [
+ "a48f16f9472cb825154a980720bd436b62db8329758026ed40deaa18e9bccea80cc0d2e40164379e7498b61a280fa86e7080b53acd1baf84604c5270ba2e161b069c2f1187bbead120b10d073d3326c5da5edeca2a2e0322253face85a769c92155d2859b86caac4f2b25d8779b2a99de3af195b2be8a4e5923d2a566833f86a683fdd68189962ea14ca940bcae99c612ca93caf3ec9bfa9ca2bdc0adeb80dba90992e4ea878bd39e321fe43f0cc073d9b5a8f9ff7f38b333e907e510a04499dc78059a620bc2d7201e3c7a4545cb5066add82690fd25269e66e1cf4334211b5578dc556c377753a501da19da81e839e6f3b7f56724ad9ee5e6dbc0a1cdcd3fc36601586eca9a50a620ed1c8941379369ae3a72b13c11c76cbd1f69d5d5acca56da4d8567007cbba3da384aa2d73e1bfba7ff77864c3b508d5a5b69b69a0bc6c092fc84d564e8f9726686e13f32239912a8a0bd92a8849d81f30560618db3bbd7f8b14a68e8a4bb2f61db7fa471573a4bee095db799ff19407b22fd77ecd55206e85f36dabec6323d8aaea77e328a07e3ccbcb3c893f6522fd0aa39f09b79dd9167cb9bccc326e2aaf51cc0e187c46766ccbe75321deb403d470795926b6879f0398a996aa5330734a5f3fed8b0e69e3a2c8a4efcd739fbedda27ae086f7144e655cdc89b07183818b56ce01dddf691d2a57f846c77d8601b203a2caf8a9bb3ec4f340d68702bf320df74e304d2db24de0dd26a6346ccc9a65c6c24e45a31636efb0919a87c8b14c08226807807acb467c29481b03e541c3ad3b2512b89c794687f4dae6b4c5f7fef5b5c348e61cca26629f015fc7babc7e0261b477843df830057f7c69248b4493b2e7a9f5503ba3eee569fc9911b35d0dd6111e8985a42273606162636465666768696a6b6c6d6e6f",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f",
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
+ ],
+ "measurement": 100,
+ "nonce": "000102030405060708090a0b0c0d0e0f",
+ "out_shares": [
+ [
+ "f91bcafa315d7cfa26564999203babdc"
+ ],
+ [
+ "722e72d9927634bd8429b5e65bc91743"
+ ],
+ [
+ "fbb5c32b3b2c4f481c80018083fb3ce0"
+ ]
+ ],
+ "prep_messages": [
+ "215cd3acf2c12d42b2897cb57fb420a6"
+ ],
+ "prep_shares": [
+ [
+ "8a17e1ae7baf0fcb35b9d89394f8f34e5e965d98db9ffbe0867029fbbdfd7195d7fda8b597d471f0046bd4508be2e2abbf23e0b165f191b5165f0350ae251442",
+ "6c98be496224df8772c21173ad6fa2b271003e04a8d922570934a5812d4a8c45c1cf374cea16117767d4f4ee963acd756d42402e0f2b584af325b34eaa1615ad",
+ "0c506007222c11ad1f8415f9bd9769fe526f9e6835c5e2ce8c44b01f27cc5060c4c159a86eb48e1571437659eb32b3e8800a1a73b5ae07e45e4cc67555122b2d"
+ ]
+ ],
+ "public_share": "bf23e0b165f191b5165f0350ae2514426d42402e0f2b584af325b34eaa1615ad800a1a73b5ae07e45e4cc67555122b2d",
+ "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
+ }
+ ],
+ "shares": 3,
+ "verify_key": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/XofFixedKeyAes128.json b/third_party/rust/prio/src/vdaf/test_vec/08/XofFixedKeyAes128.json
new file mode 100644
index 0000000000..6a34d6e32e
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/XofFixedKeyAes128.json
@@ -0,0 +1,8 @@
+{
+ "binder": "62696e64657220737472696e67",
+ "derived_seed": "3805276060157b7376b069305303669b",
+ "dst": "646f6d61696e2073657061726174696f6e20746167",
+ "expanded_vec_field128": "3805276060157b7376b069305303669b92beaaa4afa982314428494ba98f3595d49e76d1301b451d6fd79c9acbe9118717cfd0d4b9ef29806b4dce298a2d6aba17d7025e7964a2d7e24a263bd79d19edb11cd1db4bc07ce0ae1a9c6d1f59233e8d7065a66ce1b123ed773e4b370c9217c7032fc805f3a13f6fe2ef6f7961bf9d20fd22b8cd544cefe8e634d9245db7813ba43f630a123dfda73b6bbad8b11a916090a7d5ba8a4d20853f3f5c8222684050a53119e829313fa8de64f92553a44aa522fc90d9ec75f80547ec9637ce60e74afd51baa1d80b549444c5f0a6283ff494698ea6ffaea65964c4e0c2f9cf72a11310000261ddc85661f5068f505d34273295be9b8549b4c6278a80794929093a17cc017cf0b0e68e32e941708cfa58b9e598ac3d5d2ab4e9b33111c9c9fbc0a3682617d0ed1a0d15c9bfb9d5fd2889d1f56dd3a7f2e61ca59b0705d35f915349ffea0341816532bbdaa6dddba42bf27d1699d9e9ef580f3686ea42d687e54a87c3e6dab4f1ee5e1185faa6b809eb1a1e940692b3ba882684e8440b73e23088411000cf77ba69777b3bfa417050f0cef6cd0c9b6e7a47ab5c3da9a0e3de6ec323aed32f4cc3f51ac719e34f0bd9b0cc617e3034581a708f4a3bba587b4b4cb91529cfd47393893c3b5cd430d0456a245b0c45d4398fe423b67faa8682c764d92c514d7e34a89abc16353e71de7d49895527e632a6163d7362549a8e9ab12277460d30d7892e0a5993a4d3922738f07892764b0ceabf280779894ced52aa7fba94100c2ec0fa1973d2b11044e6844ddcdbd59f26e1b321d02c9189414cace4abece30878ca21d198f2e61b84e7cbebb6a0ad83e2abd5bf69d7f8eed193a8e141088a4b7d41fe23a939f678ba94a1d9c9c2",
+ "length": 40,
+ "seed": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/XofTurboShake128.json b/third_party/rust/prio/src/vdaf/test_vec/08/XofTurboShake128.json
new file mode 100644
index 0000000000..1e48d1f648
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/08/XofTurboShake128.json
@@ -0,0 +1,8 @@
+{
+ "binder": "62696e64657220737472696e67",
+ "derived_seed": "8bac064e720bb1c413040a3f41990075",
+ "dst": "646f6d61696e2073657061726174696f6e20746167",
+ "expanded_vec_field128": "8bac064e720bb1c413040a3f419900750ce08494b0f4f2d95171dcf44255ef94606fd5e6ffe3735329f5550e34fe61f0d4704239c107e4beb6623e20cb2e2659662aef8409fcc162a01d2333fc8d8ee7bc31c394c88edeb5904d25bf851d30246d9bf4221a5aec6ff4cb2580dde88dfa726e21b35da18f5b1839a257482ab292615b094b092444013874fce11cbd293fc81fd9a00d1befca7b1aefa2324ad2c84a8d678b02973bd539021e18861647474211e99ccfff5e47483985b25257f83665f44ed3fbce4f5a2b20e5c54239653141f7d5132b255936d33327789e13b145362059f67bd8d5b240dfd1e525d6ac5c0bb6a5b4a0b7b7318a5e22fc91763d2eb9dbd5fd3a3665127ffa63ac5be71a0b67a5ce5ee158d902a4e3a4c580e734ee40682e471373b958853eddee1de30dda6e6f4a3e3a297a79bd7f332ce89b8f0cd50589f03b95408405df362a41f58688e1fb818deaccf36eedbabc1762215102de02125dc79450d47dc04ba88cd507bdf1690ae6c1dbb44352c29687e3f60e0d3d9ed8758aa1495f4976477bda7e3cdbf37078f615dfde8330df46aebe393a665fa3f9b906498ef59ac5a0da50ebeb91c80ac0d8ba3d9bcb4e23f37e416dbe679d633834b8351085a321314d8b0276b24de1dc41091f9bdf765f2879ef0d624927a649bb693386b5a22af2ec5b67b8298abadf1e4ffa10a794ebb9924761d08ad75b595ef11118b33a8f5e649e0b8351600be077a164c806a7ee2aba58de06177ccd18e8822d35c2d6843378f254d64e5a1ee52d9c5b3f63ae262c3d6d5b63baf4e2faf436d51d6318ac9d05cf4fe3e203b2b047bdb1b4f4f8d5645a5d59ab506afc423f3a0ae5691e7f755dc5bff3b6b4f08c61614b62f63b03ce30d35a2c0d",
+ "length": 40,
+ "seed": "000102030405060708090a0b0c0d0e0f"
+}
diff --git a/third_party/rust/prio/src/vdaf/test_vec/XofHmacSha256Aes128.json b/third_party/rust/prio/src/vdaf/test_vec/XofHmacSha256Aes128.json
new file mode 100644
index 0000000000..510cc539e1
--- /dev/null
+++ b/third_party/rust/prio/src/vdaf/test_vec/XofHmacSha256Aes128.json
@@ -0,0 +1,8 @@
+{
+ "binder": "62696e64657220737472696e67",
+ "derived_seed": "e826c9564c620fb63357fbee88dc9bb3de2c41764adb44bea344024e1da124c6",
+ "dst": "646f6d61696e2073657061726174696f6e20746167",
+ "expanded_vec_field128": "e826c9564c620fb63357fbee88dc9bb3de2c41764adb44bea344024e1da124c6172f208e79762fed92c73cea422b312860008ee80e30f31d2d87840890604f39db37983f5c3483407333cecdb1b9ea550c26bc4f2d999fda91963054c6cb35a8ad8d28ee74a48e28aa475d67124e7c4417149955e506690d62e17f0730b7d4db8a9754f80603b7720205819d26bcfe4a4663d05c98c12705ea7dc333d5746d9c8ba697bb3d5be95d26ccb73052cb8fb19edfc35eaebaa22779436d3015512c9b536003d98b04a0f46feddbff762007c377c28a04039f72657650885bd40ed37acea63facd3c33d1ecb5048641053af5b4018b0c373d9ed7440da9fc6c76666c2eb8ed2943a64bbf6dae93ac91fcc26d7225c2ae42349161522fcce0b92d209411af8566b0adbaa36a8479737017efd2c359ea43924cdf432650dcd742e358af55ff6c321d0ebaae2abf5812d58b060cc147395e8137f99db58d2c425f2704da067df3a41c0443918375c177fa53545d8190d828c6045bbe5930e4762588ea14dc0a9db6cd903216ccae968ca0b11f0ac04e4dfc69a99986841dc99c851e314c7d4b10f4ef72e1244b543465fed076a7e9f50baca4ad7dccc73bfc55310f2ae6eaeaf7ee7a4d41fec76bff3b04e67d1f83e4da59f1fcb45877adfc3e4a2b1d5e3f136131ca2a02f34bdba1c5d2dafb2178674dc002d247662497b7f5818880cff308e5222e6df0bcdf6f68ebfaa8d0551530fa00ec29646441961e33b50872ada911591e16e3021baa5e7869756d3d812a63e3c7fa2c0ec2dc4cabe11c0256829b360ad9431536ab96efbe5a364cd1c323de8fbe405a2c87b9c58e5740bfb118af0ca1a23afb4a04e9cec3b9d1e57834cbc0fa17d5d7285f1f013df05e92a7343",
+ "length": 40,
+ "seed": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
+}
diff --git a/third_party/rust/prio/src/vdaf/xof.rs b/third_party/rust/prio/src/vdaf/xof.rs
index b38d176467..67881419df 100644
--- a/third_party/rust/prio/src/vdaf/xof.rs
+++ b/third_party/rust/prio/src/vdaf/xof.rs
@@ -1,8 +1,14 @@
// SPDX-License-Identifier: MPL-2.0
-//! Implementations of XOFs specified in [[draft-irtf-cfrg-vdaf-07]].
+//! Implementations of XOFs specified in [[draft-irtf-cfrg-vdaf-08]].
//!
-//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
+
+/// Value of the domain separation byte "D" used by XofTurboShake128 when invoking TurboSHAKE128.
+const XOF_TURBO_SHAKE_128_DOMAIN_SEPARATION: u8 = 1;
+/// Value of the domain separation byte "D" used by XofFixedKeyAes128 when invoking TurboSHAKE128.
+#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
+const XOF_FIXED_KEY_AES_128_DOMAIN_SEPARATION: u8 = 2;
use crate::{
field::FieldElement,
@@ -21,13 +27,17 @@ use aes::{
};
#[cfg(feature = "crypto-dependencies")]
use ctr::Ctr64BE;
+#[cfg(feature = "crypto-dependencies")]
+use hmac::{Hmac, Mac};
use rand_core::{
impls::{next_u32_via_fill, next_u64_via_fill},
RngCore, SeedableRng,
};
+#[cfg(feature = "crypto-dependencies")]
+use sha2::Sha256;
use sha3::{
digest::{ExtendableOutput, Update, XofReader},
- Shake128, Shake128Core, Shake128Reader,
+ TurboShake128, TurboShake128Core, TurboShake128Reader,
};
#[cfg(feature = "crypto-dependencies")]
use std::fmt::Formatter;
@@ -76,8 +86,9 @@ impl<const SEED_SIZE: usize> ConstantTimeEq for Seed<SEED_SIZE> {
}
impl<const SEED_SIZE: usize> Encode for Seed<SEED_SIZE> {
- fn encode(&self, bytes: &mut Vec<u8>) {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
bytes.extend_from_slice(&self.0[..]);
+ Ok(())
}
fn encoded_len(&self) -> Option<usize> {
@@ -105,9 +116,9 @@ impl<S: RngCore> IntoFieldVec for S {
}
}
-/// An extendable output function (XOF) with the interface specified in [[draft-irtf-cfrg-vdaf-07]].
+/// An extendable output function (XOF) with the interface specified in [[draft-irtf-cfrg-vdaf-08]].
///
-/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
pub trait Xof<const SEED_SIZE: usize>: Clone + Debug {
/// The type of stream produced by this XOF.
type SeedStream: RngCore + Sized;
@@ -145,7 +156,9 @@ pub struct SeedStreamAes128(Ctr64BE<Aes128>);
#[cfg(feature = "crypto-dependencies")]
impl SeedStreamAes128 {
- pub(crate) fn new(key: &[u8], iv: &[u8]) -> Self {
+ /// Construct an instance of the seed stream with the given AES key `key` and initialization
+ /// vector `iv`.
+ pub fn new(key: &[u8], iv: &[u8]) -> Self {
SeedStreamAes128(<Ctr64BE<Aes128> as KeyIvInit>::new(key.into(), iv.into()))
}
@@ -187,17 +200,19 @@ impl Debug for SeedStreamAes128 {
}
}
-/// The XOF based on SHA-3 as specified in [[draft-irtf-cfrg-vdaf-07]].
+/// The XOF based on TurboSHAKE128 as specified in [[draft-irtf-cfrg-vdaf-08]].
///
-/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
#[derive(Clone, Debug)]
-pub struct XofShake128(Shake128);
+pub struct XofTurboShake128(TurboShake128);
-impl Xof<16> for XofShake128 {
- type SeedStream = SeedStreamSha3;
+impl Xof<16> for XofTurboShake128 {
+ type SeedStream = SeedStreamTurboShake128;
fn init(seed_bytes: &[u8; 16], dst: &[u8]) -> Self {
- let mut xof = Self(Shake128::from_core(Shake128Core::default()));
+ let mut xof = Self(TurboShake128::from_core(TurboShake128Core::new(
+ XOF_TURBO_SHAKE_128_DOMAIN_SEPARATION,
+ )));
Update::update(
&mut xof.0,
&[dst.len().try_into().expect("dst must be at most 255 bytes")],
@@ -211,21 +226,21 @@ impl Xof<16> for XofShake128 {
Update::update(&mut self.0, data);
}
- fn into_seed_stream(self) -> SeedStreamSha3 {
- SeedStreamSha3::new(self.0.finalize_xof())
+ fn into_seed_stream(self) -> SeedStreamTurboShake128 {
+ SeedStreamTurboShake128::new(self.0.finalize_xof())
}
}
-/// The seed stream produced by SHAKE128.
-pub struct SeedStreamSha3(Shake128Reader);
+/// The seed stream produced by TurboSHAKE128.
+pub struct SeedStreamTurboShake128(TurboShake128Reader);
-impl SeedStreamSha3 {
- pub(crate) fn new(reader: Shake128Reader) -> Self {
+impl SeedStreamTurboShake128 {
+ pub(crate) fn new(reader: TurboShake128Reader) -> Self {
Self(reader)
}
}
-impl RngCore for SeedStreamSha3 {
+impl RngCore for SeedStreamTurboShake128 {
fn fill_bytes(&mut self, dest: &mut [u8]) {
XofReader::read(&mut self.0, dest);
}
@@ -244,13 +259,13 @@ impl RngCore for SeedStreamSha3 {
}
}
-/// A `rand`-compatible interface to construct XofShake128 seed streams, with the domain separation tag
-/// and binder string both fixed as the empty string.
-impl SeedableRng for SeedStreamSha3 {
+/// A `rand`-compatible interface to construct XofTurboShake128 seed streams, with the domain
+/// separation tag and binder string both fixed as the empty string.
+impl SeedableRng for SeedStreamTurboShake128 {
type Seed = [u8; 16];
fn from_seed(seed: Self::Seed) -> Self {
- XofShake128::init(&seed, b"").into_seed_stream()
+ XofTurboShake128::init(&seed, b"").into_seed_stream()
}
}
@@ -269,7 +284,9 @@ pub struct XofFixedKeyAes128Key {
impl XofFixedKeyAes128Key {
/// Derive the fixed key from the domain separation tag and binder string.
pub fn new(dst: &[u8], binder: &[u8]) -> Self {
- let mut fixed_key_deriver = Shake128::from_core(Shake128Core::default());
+ let mut fixed_key_deriver = TurboShake128::from_core(TurboShake128Core::new(
+ XOF_FIXED_KEY_AES_128_DOMAIN_SEPARATION,
+ ));
Update::update(
&mut fixed_key_deriver,
&[dst.len().try_into().expect("dst must be at most 255 bytes")],
@@ -293,15 +310,15 @@ impl XofFixedKeyAes128Key {
}
}
-/// XofFixedKeyAes128 as specified in [[draft-irtf-cfrg-vdaf-07]]. This XOF is NOT RECOMMENDED for
+/// XofFixedKeyAes128 as specified in [[draft-irtf-cfrg-vdaf-08]]. This XOF is NOT RECOMMENDED for
/// general use; see Section 9 ("Security Considerations") for details.
///
-/// This XOF combines SHA-3 and a fixed-key mode of operation for AES-128. The key is "fixed" in
-/// the sense that it is derived (using SHAKE128) from the domain separation tag and binder
-/// strings, and depending on the application, these strings can be hard-coded. The seed is used to
-/// construct each block of input passed to a hash function built from AES-128.
+/// This XOF combines TurboSHAKE128 and a fixed-key mode of operation for AES-128. The key is
+/// "fixed" in the sense that it is derived (using TurboSHAKE128) from the domain separation tag and
+/// binder strings, and depending on the application, these strings can be hard-coded. The seed is
+/// used to construct each block of input passed to a hash function built from AES-128.
///
-/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/
+/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/
#[derive(Clone, Debug)]
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
#[cfg_attr(
@@ -309,7 +326,7 @@ impl XofFixedKeyAes128Key {
doc(cfg(all(feature = "crypto-dependencies", feature = "experimental")))
)]
pub struct XofFixedKeyAes128 {
- fixed_key_deriver: Shake128,
+ fixed_key_deriver: TurboShake128,
base_block: Block,
}
@@ -318,7 +335,7 @@ impl Xof<16> for XofFixedKeyAes128 {
type SeedStream = SeedStreamFixedKeyAes128;
fn init(seed_bytes: &[u8; 16], dst: &[u8]) -> Self {
- let mut fixed_key_deriver = Shake128::from_core(Shake128Core::default());
+ let mut fixed_key_deriver = TurboShake128::from_core(TurboShake128Core::new(2u8));
Update::update(
&mut fixed_key_deriver,
&[dst.len().try_into().expect("dst must be at most 255 bytes")],
@@ -433,6 +450,37 @@ impl RngCore for SeedStreamFixedKeyAes128 {
}
}
+/// XOF based on HMAC-SHA256 and AES128. This XOF is not part of the VDAF spec.
+#[cfg(feature = "crypto-dependencies")]
+#[cfg_attr(docsrs, doc(cfg(feature = "crypto-dependencies")))]
+#[derive(Clone, Debug)]
+pub struct XofHmacSha256Aes128(Hmac<Sha256>);
+
+#[cfg(feature = "crypto-dependencies")]
+impl Xof<32> for XofHmacSha256Aes128 {
+ type SeedStream = SeedStreamAes128;
+
+ fn init(seed_bytes: &[u8; 32], dst: &[u8]) -> Self {
+ let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(seed_bytes).unwrap();
+ Mac::update(
+ &mut mac,
+ &[dst.len().try_into().expect("dst must be at most 255 bytes")],
+ );
+ Mac::update(&mut mac, dst);
+ Self(mac)
+ }
+
+ fn update(&mut self, data: &[u8]) {
+ Mac::update(&mut self.0, data);
+ }
+
+ fn into_seed_stream(self) -> SeedStreamAes128 {
+ let tag = Mac::finalize(self.0).into_bytes();
+ let (key, iv) = tag.split_at(16);
+ SeedStreamAes128::new(key, iv)
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -480,10 +528,34 @@ mod tests {
}
#[test]
- fn xof_shake128() {
+ fn xof_turboshake128() {
let t: XofTestVector =
- serde_json::from_str(include_str!("test_vec/07/XofShake128.json")).unwrap();
- let mut xof = XofShake128::init(&t.seed.try_into().unwrap(), &t.dst);
+ serde_json::from_str(include_str!("test_vec/08/XofTurboShake128.json")).unwrap();
+ let mut xof = XofTurboShake128::init(&t.seed.try_into().unwrap(), &t.dst);
+ xof.update(&t.binder);
+
+ assert_eq!(
+ xof.clone().into_seed(),
+ Seed(t.derived_seed.try_into().unwrap())
+ );
+
+ let mut bytes = Cursor::new(t.expanded_vec_field128.as_slice());
+ let mut want = Vec::with_capacity(t.length);
+ while (bytes.position() as usize) < t.expanded_vec_field128.len() {
+ want.push(Field128::decode(&mut bytes).unwrap())
+ }
+ let got: Vec<Field128> = xof.clone().into_seed_stream().into_field_vec(t.length);
+ assert_eq!(got, want);
+
+ test_xof::<XofTurboShake128, 16>();
+ }
+
+ #[test]
+ fn xof_hmac_sha256_aes128() {
+ let t: XofTestVector =
+ serde_json::from_str(include_str!("test_vec/XofHmacSha256Aes128.json")).unwrap();
+
+ let mut xof = XofHmacSha256Aes128::init(&t.seed.try_into().unwrap(), &t.dst);
xof.update(&t.binder);
assert_eq!(
@@ -499,14 +571,14 @@ mod tests {
let got: Vec<Field128> = xof.clone().into_seed_stream().into_field_vec(t.length);
assert_eq!(got, want);
- test_xof::<XofShake128, 16>();
+ test_xof::<XofHmacSha256Aes128, 32>();
}
#[cfg(feature = "experimental")]
#[test]
fn xof_fixed_key_aes128() {
let t: XofTestVector =
- serde_json::from_str(include_str!("test_vec/07/XofFixedKeyAes128.json")).unwrap();
+ serde_json::from_str(include_str!("test_vec/08/XofFixedKeyAes128.json")).unwrap();
let mut xof = XofFixedKeyAes128::init(&t.seed.try_into().unwrap(), &t.dst);
xof.update(&t.binder);
diff --git a/third_party/rust/prio/src/vidpf.rs b/third_party/rust/prio/src/vidpf.rs
new file mode 100644
index 0000000000..c8ba5db22c
--- /dev/null
+++ b/third_party/rust/prio/src/vidpf.rs
@@ -0,0 +1,827 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//! Verifiable Incremental Distributed Point Function (VIDPF).
+//!
+//! The VIDPF construction is specified in [[draft-mouris-cfrg-mastic]] and builds
+//! on techniques from [[MST23]] and [[CP22]] to lift an IDPF to a VIDPF.
+//!
+//! [CP22]: https://eprint.iacr.org/2021/580
+//! [MST23]: https://eprint.iacr.org/2023/080
+//! [draft-mouris-cfrg-mastic]: https://datatracker.ietf.org/doc/draft-mouris-cfrg-mastic/02/
+
+use core::{
+ iter::zip,
+ ops::{Add, AddAssign, BitXor, BitXorAssign, Index, Sub},
+};
+
+use bitvec::field::BitField;
+use rand_core::RngCore;
+use std::io::Cursor;
+use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable};
+
+use crate::{
+ codec::{CodecError, Encode, ParameterizedDecode},
+ field::FieldElement,
+ idpf::{
+ conditional_select_seed, conditional_swap_seed, conditional_xor_seeds, xor_seeds,
+ IdpfInput, IdpfValue,
+ },
+ vdaf::xof::{Seed, Xof, XofFixedKeyAes128, XofTurboShake128},
+};
+
+/// VIDPF-related errors.
+#[derive(Debug, thiserror::Error)]
+#[non_exhaustive]
+pub enum VidpfError {
+ /// Error when key's identifier are equal.
+ #[error("key's identifier should be different")]
+ SameKeyId,
+
+ /// Error when level does not fit in a 32-bit number.
+ #[error("level is not representable as a 32-bit integer")]
+ LevelTooBig,
+
+ /// Error during VIDPF evaluation: tried to access a level index out of bounds.
+ #[error("level index out of bounds")]
+ IndexLevel,
+
+ /// Error when weight's length mismatches the length in weight's parameter.
+ #[error("invalid weight length")]
+ InvalidWeightLength,
+
+ /// Failure when calling getrandom().
+ #[error("getrandom: {0}")]
+ GetRandom(#[from] getrandom::Error),
+}
+
+/// Represents the domain of an incremental point function.
+pub type VidpfInput = IdpfInput;
+
+/// Represents the codomain of an incremental point function.
+pub trait VidpfValue: IdpfValue + Clone {}
+
+/// A VIDPF instance.
+pub struct Vidpf<W: VidpfValue, const NONCE_SIZE: usize> {
+ /// Any parameters required to instantiate a weight value.
+ weight_parameter: W::ValueParameter,
+}
+
+impl<W: VidpfValue, const NONCE_SIZE: usize> Vidpf<W, NONCE_SIZE> {
+ /// Creates a VIDPF instance.
+ ///
+ /// # Arguments
+ ///
+ /// * `weight_parameter`, any parameters required to instantiate a weight value.
+ pub const fn new(weight_parameter: W::ValueParameter) -> Self {
+ Self { weight_parameter }
+ }
+
+ /// The [`Vidpf::gen`] method splits an incremental point function `F` into two private keys
+ /// used by the aggregation servers, and a common public share.
+ ///
+ /// The incremental point function is defined as `F`: [`VidpfInput`] --> [`VidpfValue`]
+ /// such that:
+ ///
+ /// ```txt
+ /// F(x) = weight, if x is a prefix of the input.
+ /// F(x) = 0, if x is not a prefix of the input.
+ /// ```
+ ///
+ /// # Arguments
+ ///
+ /// * `input`, determines the input of the function.
+ /// * `weight`, determines the input's weight of the function.
+ /// * `nonce`, used to cryptographically bind some information.
+ pub fn gen(
+ &self,
+ input: &VidpfInput,
+ weight: &W,
+ nonce: &[u8; NONCE_SIZE],
+ ) -> Result<(VidpfPublicShare<W>, [VidpfKey; 2]), VidpfError> {
+ let keys = [
+ VidpfKey::gen(VidpfServerId::S0)?,
+ VidpfKey::gen(VidpfServerId::S1)?,
+ ];
+ let public = self.gen_with_keys(&keys, input, weight, nonce)?;
+ Ok((public, keys))
+ }
+
+ /// [`Vidpf::gen_with_keys`] works as the [`Vidpf::gen`] method, except that two different
+ /// keys must be provided.
+ fn gen_with_keys(
+ &self,
+ keys: &[VidpfKey; 2],
+ input: &VidpfInput,
+ weight: &W,
+ nonce: &[u8; NONCE_SIZE],
+ ) -> Result<VidpfPublicShare<W>, VidpfError> {
+ if keys[0].id == keys[1].id {
+ return Err(VidpfError::SameKeyId);
+ }
+
+ let mut s_i = [keys[0].value, keys[1].value];
+ let mut t_i = [Choice::from(keys[0].id), Choice::from(keys[1].id)];
+
+ let n = input.len();
+ let mut cw = Vec::with_capacity(n);
+ let mut cs = Vec::with_capacity(n);
+
+ for level in 0..n {
+ let alpha_i = Choice::from(u8::from(input.get(level).ok_or(VidpfError::IndexLevel)?));
+
+ // If alpha_i == 0 then
+ // (same_seed, diff_seed) = (right_seed, left_seed)
+ // else
+ // (same_seed, diff_seed) = (left_seed, right_seed)
+ let seq_0 = Self::prg(&s_i[0], nonce);
+ let (same_seed_0, diff_seed_0) = &mut (seq_0.right_seed, seq_0.left_seed);
+ conditional_swap_seed(same_seed_0, diff_seed_0, alpha_i);
+
+ let seq_1 = Self::prg(&s_i[1], nonce);
+ let (same_seed_1, diff_seed_1) = &mut (seq_1.right_seed, seq_1.left_seed);
+ conditional_swap_seed(same_seed_1, diff_seed_1, alpha_i);
+
+ // If alpha_i == 0 then
+ // diff_control_bit = left_control_bit
+ // else
+ // diff_control_bit = right_control_bit
+ let diff_control_bit_0 = Choice::conditional_select(
+ &seq_0.left_control_bit,
+ &seq_0.right_control_bit,
+ alpha_i,
+ );
+ let diff_control_bit_1 = Choice::conditional_select(
+ &seq_1.left_control_bit,
+ &seq_1.right_control_bit,
+ alpha_i,
+ );
+
+ let s_cw = xor_seeds(same_seed_0, same_seed_1);
+ let t_cw_l =
+ seq_0.left_control_bit ^ seq_1.left_control_bit ^ alpha_i ^ Choice::from(1);
+ let t_cw_r = seq_0.right_control_bit ^ seq_1.right_control_bit ^ alpha_i;
+ let t_cw_diff = Choice::conditional_select(&t_cw_l, &t_cw_r, alpha_i);
+
+ let s_tilde_i_0 = conditional_xor_seeds(diff_seed_0, &s_cw, t_i[0]);
+ let s_tilde_i_1 = conditional_xor_seeds(diff_seed_1, &s_cw, t_i[1]);
+
+ t_i[0] = diff_control_bit_0 ^ (t_i[0] & t_cw_diff);
+ t_i[1] = diff_control_bit_1 ^ (t_i[1] & t_cw_diff);
+
+ let w_i_0;
+ let w_i_1;
+ (s_i[0], w_i_0) = self.convert(s_tilde_i_0, nonce);
+ (s_i[1], w_i_1) = self.convert(s_tilde_i_1, nonce);
+
+ let mut w_cw = w_i_1 - w_i_0 + weight.clone();
+ w_cw.conditional_negate(t_i[1]);
+
+ let cw_i = VidpfCorrectionWord {
+ seed: s_cw,
+ left_control_bit: t_cw_l,
+ right_control_bit: t_cw_r,
+ weight: w_cw,
+ };
+ cw.push(cw_i);
+
+ let pi_tilde_0 = Self::node_proof(input, level, &s_i[0])?;
+ let pi_tilde_1 = Self::node_proof(input, level, &s_i[1])?;
+ let cs_i = xor_proof(pi_tilde_0, &pi_tilde_1);
+ cs.push(cs_i);
+ }
+
+ Ok(VidpfPublicShare { cw, cs })
+ }
+
+ /// [`Vidpf::eval`] evaluates the entire `input` and produces a share of the
+ /// input's weight.
+ pub fn eval(
+ &self,
+ key: &VidpfKey,
+ public: &VidpfPublicShare<W>,
+ input: &VidpfInput,
+ nonce: &[u8; NONCE_SIZE],
+ ) -> Result<VidpfValueShare<W>, VidpfError> {
+ let mut state = VidpfEvalState::init_from_key(key);
+ let mut share = W::zero(&self.weight_parameter);
+
+ let n = input.len();
+ for level in 0..n {
+ (state, share) = self.eval_next(key.id, public, input, level, &state, nonce)?;
+ }
+
+ Ok(VidpfValueShare {
+ share,
+ proof: state.proof,
+ })
+ }
+
+ /// [`Vidpf::eval_next`] evaluates the `input` at the given level using the provided initial
+ /// state, and returns a new state and a share of the input's weight at that level.
+ fn eval_next(
+ &self,
+ id: VidpfServerId,
+ public: &VidpfPublicShare<W>,
+ input: &VidpfInput,
+ level: usize,
+ state: &VidpfEvalState,
+ nonce: &[u8; NONCE_SIZE],
+ ) -> Result<(VidpfEvalState, W), VidpfError> {
+ let cw = public.cw.get(level).ok_or(VidpfError::IndexLevel)?;
+
+ let seq_tilde = Self::prg(&state.seed, nonce);
+
+ let t_i = state.control_bit;
+ let sl = conditional_xor_seeds(&seq_tilde.left_seed, &cw.seed, t_i);
+ let sr = conditional_xor_seeds(&seq_tilde.right_seed, &cw.seed, t_i);
+ let tl = seq_tilde.left_control_bit ^ (t_i & cw.left_control_bit);
+ let tr = seq_tilde.right_control_bit ^ (t_i & cw.right_control_bit);
+
+ let x_i = Choice::from(u8::from(input.get(level).ok_or(VidpfError::IndexLevel)?));
+ let s_tilde_i = conditional_select_seed(x_i, &[sl, sr]);
+
+ let next_control_bit = Choice::conditional_select(&tl, &tr, x_i);
+ let (next_seed, w_i) = self.convert(s_tilde_i, nonce);
+
+ let zero = <W as IdpfValue>::zero(&self.weight_parameter);
+ let mut y = <W as IdpfValue>::conditional_select(&zero, &cw.weight, next_control_bit);
+ y += w_i;
+ y.conditional_negate(Choice::from(id));
+
+ let pi_i = &state.proof;
+ let cs_i = public.cs.get(level).ok_or(VidpfError::IndexLevel)?;
+ let pi_tilde = Self::node_proof(input, level, &next_seed)?;
+ let h2_input = xor_proof(
+ conditional_xor_proof(pi_tilde, cs_i, next_control_bit),
+ pi_i,
+ );
+ let next_proof = xor_proof(Self::node_proof_adjustment(h2_input), pi_i);
+
+ let next_state = VidpfEvalState {
+ seed: next_seed,
+ control_bit: next_control_bit,
+ proof: next_proof,
+ };
+
+ Ok((next_state, y))
+ }
+
+ fn prg(seed: &VidpfSeed, nonce: &[u8]) -> VidpfPrgOutput {
+ let mut rng = XofFixedKeyAes128::seed_stream(&Seed(*seed), VidpfDomainSepTag::PRG, nonce);
+
+ let mut left_seed = VidpfSeed::default();
+ let mut right_seed = VidpfSeed::default();
+ rng.fill_bytes(&mut left_seed);
+ rng.fill_bytes(&mut right_seed);
+ // Use the LSB of seeds as control bits, and clears the bit,
+ // i.e., seeds produced by `prg` always have their LSB = 0.
+ // This ensures `prg` costs two AES calls only.
+ let left_control_bit = Choice::from(left_seed[0] & 0x01);
+ let right_control_bit = Choice::from(right_seed[0] & 0x01);
+ left_seed[0] &= 0xFE;
+ right_seed[0] &= 0xFE;
+
+ VidpfPrgOutput {
+ left_seed,
+ left_control_bit,
+ right_seed,
+ right_control_bit,
+ }
+ }
+
+ fn convert(&self, seed: VidpfSeed, nonce: &[u8; NONCE_SIZE]) -> (VidpfSeed, W) {
+ let mut rng =
+ XofFixedKeyAes128::seed_stream(&Seed(seed), VidpfDomainSepTag::CONVERT, nonce);
+
+ let mut out_seed = VidpfSeed::default();
+ rng.fill_bytes(&mut out_seed);
+ let value = <W as IdpfValue>::generate(&mut rng, &self.weight_parameter);
+
+ (out_seed, value)
+ }
+
+ fn node_proof(
+ input: &VidpfInput,
+ level: usize,
+ seed: &VidpfSeed,
+ ) -> Result<VidpfProof, VidpfError> {
+ let mut shake = XofTurboShake128::init(seed, VidpfDomainSepTag::NODE_PROOF);
+ for chunk128 in input
+ .index(..=level)
+ .chunks(128)
+ .map(BitField::load_le::<u128>)
+ .map(u128::to_le_bytes)
+ {
+ shake.update(&chunk128);
+ }
+ shake.update(
+ &u16::try_from(level)
+ .map_err(|_e| VidpfError::LevelTooBig)?
+ .to_le_bytes(),
+ );
+ let mut rng = shake.into_seed_stream();
+
+ let mut proof = VidpfProof::default();
+ rng.fill_bytes(&mut proof);
+
+ Ok(proof)
+ }
+
+ fn node_proof_adjustment(mut proof: VidpfProof) -> VidpfProof {
+ let mut rng = XofTurboShake128::seed_stream(
+ &Seed(Default::default()),
+ VidpfDomainSepTag::NODE_PROOF_ADJUST,
+ &proof,
+ );
+ rng.fill_bytes(&mut proof);
+
+ proof
+ }
+}
+
+/// Contains the domain separation tags for invoking different oracles.
+struct VidpfDomainSepTag;
+impl VidpfDomainSepTag {
+ const PRG: &'static [u8] = b"Prg";
+ const CONVERT: &'static [u8] = b"Convert";
+ const NODE_PROOF: &'static [u8] = b"NodeProof";
+ const NODE_PROOF_ADJUST: &'static [u8] = b"NodeProofAdjust";
+}
+
+/// Private key of an aggregation server.
+pub struct VidpfKey {
+ id: VidpfServerId,
+ value: [u8; 16],
+}
+
+impl VidpfKey {
+ /// Generates a key at random.
+ ///
+ /// # Errors
+ /// Triggers an error if the random generator fails.
+ pub(crate) fn gen(id: VidpfServerId) -> Result<Self, VidpfError> {
+ let mut value = [0; 16];
+ getrandom::getrandom(&mut value)?;
+ Ok(Self { id, value })
+ }
+}
+
+/// Identifies the two aggregation servers.
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub(crate) enum VidpfServerId {
+ /// S0 is the first server.
+ S0,
+ /// S1 is the second server.
+ S1,
+}
+
+impl From<VidpfServerId> for Choice {
+ fn from(value: VidpfServerId) -> Self {
+ match value {
+ VidpfServerId::S0 => Self::from(0),
+ VidpfServerId::S1 => Self::from(1),
+ }
+ }
+}
+
+/// Adjusts values of shares during the VIDPF evaluation.
+#[derive(Debug)]
+struct VidpfCorrectionWord<W: VidpfValue> {
+ seed: VidpfSeed,
+ left_control_bit: Choice,
+ right_control_bit: Choice,
+ weight: W,
+}
+
+/// Common public information used by aggregation servers.
+#[derive(Debug)]
+pub struct VidpfPublicShare<W: VidpfValue> {
+ cw: Vec<VidpfCorrectionWord<W>>,
+ cs: Vec<VidpfProof>,
+}
+
+/// Contains the values produced during input evaluation at a given level.
+pub struct VidpfEvalState {
+ seed: VidpfSeed,
+ control_bit: Choice,
+ proof: VidpfProof,
+}
+
+impl VidpfEvalState {
+ fn init_from_key(key: &VidpfKey) -> Self {
+ Self {
+ seed: key.value,
+ control_bit: Choice::from(key.id),
+ proof: VidpfProof::default(),
+ }
+ }
+}
+
+/// Contains a share of the input's weight together with a proof for verification.
+pub struct VidpfValueShare<W: VidpfValue> {
+ /// Secret share of the input's weight.
+ pub share: W,
+ /// Proof used to verify the share.
+ pub proof: VidpfProof,
+}
+
+/// Proof size in bytes.
+const VIDPF_PROOF_SIZE: usize = 32;
+
+/// Allows to validate user input and shares after evaluation.
+type VidpfProof = [u8; VIDPF_PROOF_SIZE];
+
+fn xor_proof(mut lhs: VidpfProof, rhs: &VidpfProof) -> VidpfProof {
+ zip(&mut lhs, rhs).for_each(|(a, b)| a.bitxor_assign(b));
+ lhs
+}
+
+fn conditional_xor_proof(mut lhs: VidpfProof, rhs: &VidpfProof, choice: Choice) -> VidpfProof {
+ zip(&mut lhs, rhs).for_each(|(a, b)| a.conditional_assign(&a.bitxor(b), choice));
+ lhs
+}
+
+/// Feeds a pseudorandom generator during evaluation.
+type VidpfSeed = [u8; 16];
+
+/// Contains the seeds and control bits produced by [`Vidpf::prg`].
+struct VidpfPrgOutput {
+ left_seed: VidpfSeed,
+ left_control_bit: Choice,
+ right_seed: VidpfSeed,
+ right_control_bit: Choice,
+}
+
+/// Represents an array of field elements that implements the [`VidpfValue`] trait.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct VidpfWeight<F: FieldElement>(Vec<F>);
+
+impl<F: FieldElement> From<Vec<F>> for VidpfWeight<F> {
+ fn from(value: Vec<F>) -> Self {
+ Self(value)
+ }
+}
+
+impl<F: FieldElement> VidpfValue for VidpfWeight<F> {}
+
+impl<F: FieldElement> IdpfValue for VidpfWeight<F> {
+ /// The parameter determines the number of field elements in the vector.
+ type ValueParameter = usize;
+
+ fn generate<S: RngCore>(seed_stream: &mut S, length: &Self::ValueParameter) -> Self {
+ Self(
+ (0..*length)
+ .map(|_| <F as IdpfValue>::generate(seed_stream, &()))
+ .collect(),
+ )
+ }
+
+ fn zero(length: &Self::ValueParameter) -> Self {
+ Self((0..*length).map(|_| <F as IdpfValue>::zero(&())).collect())
+ }
+
+ /// Panics if weight lengths are different.
+ fn conditional_select(lhs: &Self, rhs: &Self, choice: Choice) -> Self {
+ assert_eq!(
+ lhs.0.len(),
+ rhs.0.len(),
+ "{}",
+ VidpfError::InvalidWeightLength
+ );
+
+ Self(
+ zip(&lhs.0, &rhs.0)
+ .map(|(a, b)| <F as IdpfValue>::conditional_select(a, b, choice))
+ .collect(),
+ )
+ }
+}
+
+impl<F: FieldElement> ConditionallyNegatable for VidpfWeight<F> {
+ fn conditional_negate(&mut self, choice: Choice) {
+ self.0.iter_mut().for_each(|a| a.conditional_negate(choice));
+ }
+}
+
+impl<F: FieldElement> Add for VidpfWeight<F> {
+ type Output = Self;
+
+ /// Panics if weight lengths are different.
+ fn add(self, rhs: Self) -> Self::Output {
+ assert_eq!(
+ self.0.len(),
+ rhs.0.len(),
+ "{}",
+ VidpfError::InvalidWeightLength
+ );
+
+ Self(zip(self.0, rhs.0).map(|(a, b)| a.add(b)).collect())
+ }
+}
+
+impl<F: FieldElement> AddAssign for VidpfWeight<F> {
+ /// Panics if weight lengths are different.
+ fn add_assign(&mut self, rhs: Self) {
+ assert_eq!(
+ self.0.len(),
+ rhs.0.len(),
+ "{}",
+ VidpfError::InvalidWeightLength
+ );
+
+ zip(&mut self.0, rhs.0).for_each(|(a, b)| a.add_assign(b));
+ }
+}
+
+impl<F: FieldElement> Sub for VidpfWeight<F> {
+ type Output = Self;
+
+ /// Panics if weight lengths are different.
+ fn sub(self, rhs: Self) -> Self::Output {
+ assert_eq!(
+ self.0.len(),
+ rhs.0.len(),
+ "{}",
+ VidpfError::InvalidWeightLength
+ );
+
+ Self(zip(self.0, rhs.0).map(|(a, b)| a.sub(b)).collect())
+ }
+}
+
+impl<F: FieldElement> Encode for VidpfWeight<F> {
+ fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
+ for e in &self.0 {
+ F::encode(e, bytes)?;
+ }
+ Ok(())
+ }
+
+ fn encoded_len(&self) -> Option<usize> {
+ Some(self.0.len() * F::ENCODED_SIZE)
+ }
+}
+
+impl<F: FieldElement> ParameterizedDecode<<Self as IdpfValue>::ValueParameter> for VidpfWeight<F> {
+ fn decode_with_param(
+ decoding_parameter: &<Self as IdpfValue>::ValueParameter,
+ bytes: &mut Cursor<&[u8]>,
+ ) -> Result<Self, CodecError> {
+ let mut v = Vec::with_capacity(*decoding_parameter);
+ for _ in 0..*decoding_parameter {
+ v.push(F::decode_with_param(&(), bytes)?);
+ }
+
+ Ok(Self(v))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::field::Field128;
+
+ use super::VidpfWeight;
+
+ type TestWeight = VidpfWeight<Field128>;
+ const TEST_WEIGHT_LEN: usize = 3;
+ const TEST_NONCE_SIZE: usize = 16;
+ const TEST_NONCE: &[u8; TEST_NONCE_SIZE] = b"Test Nonce VIDPF";
+
+ mod vidpf {
+ use crate::{
+ idpf::IdpfValue,
+ vidpf::{
+ Vidpf, VidpfError, VidpfEvalState, VidpfInput, VidpfKey, VidpfPublicShare,
+ VidpfServerId,
+ },
+ };
+
+ use super::{TestWeight, TEST_NONCE, TEST_NONCE_SIZE, TEST_WEIGHT_LEN};
+
+ fn vidpf_gen_setup(
+ input: &VidpfInput,
+ weight: &TestWeight,
+ ) -> (
+ Vidpf<TestWeight, TEST_NONCE_SIZE>,
+ VidpfPublicShare<TestWeight>,
+ [VidpfKey; 2],
+ [u8; TEST_NONCE_SIZE],
+ ) {
+ let vidpf = Vidpf::new(TEST_WEIGHT_LEN);
+ let (public, keys) = vidpf.gen(input, weight, TEST_NONCE).unwrap();
+ (vidpf, public, keys, *TEST_NONCE)
+ }
+
+ #[test]
+ fn gen_with_keys() {
+ let input = VidpfInput::from_bytes(&[0xFF]);
+ let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]);
+ let vidpf = Vidpf::new(TEST_WEIGHT_LEN);
+ let keys_with_same_id = [
+ VidpfKey::gen(VidpfServerId::S0).unwrap(),
+ VidpfKey::gen(VidpfServerId::S0).unwrap(),
+ ];
+
+ let err = vidpf
+ .gen_with_keys(&keys_with_same_id, &input, &weight, TEST_NONCE)
+ .unwrap_err();
+
+ assert_eq!(err.to_string(), VidpfError::SameKeyId.to_string());
+ }
+
+ #[test]
+ fn correctness_at_last_level() {
+ let input = VidpfInput::from_bytes(&[0xFF]);
+ let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]);
+ let (vidpf, public, [key_0, key_1], nonce) = vidpf_gen_setup(&input, &weight);
+
+ let value_share_0 = vidpf.eval(&key_0, &public, &input, &nonce).unwrap();
+ let value_share_1 = vidpf.eval(&key_1, &public, &input, &nonce).unwrap();
+
+ assert_eq!(
+ value_share_0.share + value_share_1.share,
+ weight,
+ "shares must add up to the expected weight",
+ );
+
+ assert_eq!(
+ value_share_0.proof, value_share_1.proof,
+ "proofs must be equal"
+ );
+
+ let bad_input = VidpfInput::from_bytes(&[0x00]);
+ let zero = TestWeight::zero(&TEST_WEIGHT_LEN);
+ let value_share_0 = vidpf.eval(&key_0, &public, &bad_input, &nonce).unwrap();
+ let value_share_1 = vidpf.eval(&key_1, &public, &bad_input, &nonce).unwrap();
+
+ assert_eq!(
+ value_share_0.share + value_share_1.share,
+ zero,
+ "shares must add up to zero",
+ );
+
+ assert_eq!(
+ value_share_0.proof, value_share_1.proof,
+ "proofs must be equal"
+ );
+ }
+
+ #[test]
+ fn correctness_at_each_level() {
+ let input = VidpfInput::from_bytes(&[0xFF]);
+ let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]);
+ let (vidpf, public, keys, nonce) = vidpf_gen_setup(&input, &weight);
+
+ assert_eval_at_each_level(&vidpf, &keys, &public, &input, &weight, &nonce);
+
+ let bad_input = VidpfInput::from_bytes(&[0x00]);
+ let zero = TestWeight::zero(&TEST_WEIGHT_LEN);
+
+ assert_eval_at_each_level(&vidpf, &keys, &public, &bad_input, &zero, &nonce);
+ }
+
+ fn assert_eval_at_each_level(
+ vidpf: &Vidpf<TestWeight, TEST_NONCE_SIZE>,
+ [key_0, key_1]: &[VidpfKey; 2],
+ public: &VidpfPublicShare<TestWeight>,
+ input: &VidpfInput,
+ weight: &TestWeight,
+ nonce: &[u8; TEST_NONCE_SIZE],
+ ) {
+ let mut state_0 = VidpfEvalState::init_from_key(key_0);
+ let mut state_1 = VidpfEvalState::init_from_key(key_1);
+
+ let n = input.len();
+ for level in 0..n {
+ let share_0;
+ let share_1;
+ (state_0, share_0) = vidpf
+ .eval_next(key_0.id, public, input, level, &state_0, nonce)
+ .unwrap();
+ (state_1, share_1) = vidpf
+ .eval_next(key_1.id, public, input, level, &state_1, nonce)
+ .unwrap();
+
+ assert_eq!(
+ share_0 + share_1,
+ *weight,
+ "shares must add up to the expected weight at the current level: {:?}",
+ level
+ );
+
+ assert_eq!(
+ state_0.proof, state_1.proof,
+ "proofs must be equal at the current level: {:?}",
+ level
+ );
+ }
+ }
+ }
+
+ mod weight {
+ use std::io::Cursor;
+ use subtle::{Choice, ConditionallyNegatable};
+
+ use crate::{
+ codec::{Encode, ParameterizedDecode},
+ idpf::IdpfValue,
+ vdaf::xof::{Seed, Xof, XofTurboShake128},
+ };
+
+ use super::{TestWeight, TEST_WEIGHT_LEN};
+
+ #[test]
+ fn roundtrip_codec() {
+ let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]);
+
+ let mut bytes = vec![];
+ weight.encode(&mut bytes).unwrap();
+
+ let expected_bytes = [
+ [vec![21], vec![0u8; 15]].concat(),
+ [vec![22], vec![0u8; 15]].concat(),
+ [vec![23], vec![0u8; 15]].concat(),
+ ]
+ .concat();
+
+ assert_eq!(weight.encoded_len().unwrap(), expected_bytes.len());
+ // Check endianness of encoding
+ assert_eq!(bytes, expected_bytes);
+
+ let decoded =
+ TestWeight::decode_with_param(&TEST_WEIGHT_LEN, &mut Cursor::new(&bytes)).unwrap();
+ assert_eq!(weight, decoded);
+ }
+
+ #[test]
+ fn add_sub() {
+ let [a, b] = compatible_weights();
+ let mut c = a.clone();
+ c += a.clone();
+
+ assert_eq!(
+ (a.clone() + b.clone()) + (a.clone() - b.clone()),
+ c,
+ "a: {:?} b:{:?}",
+ a,
+ b
+ );
+ }
+
+ #[test]
+ fn conditional_negate() {
+ let [a, _] = compatible_weights();
+ let mut c = a.clone();
+ c.conditional_negate(Choice::from(0));
+ let mut d = a.clone();
+ d.conditional_negate(Choice::from(1));
+ let zero = TestWeight::zero(&TEST_WEIGHT_LEN);
+
+ assert_eq!(c + d, zero, "a: {:?}", a);
+ }
+
+ #[test]
+ #[should_panic = "invalid weight length"]
+ fn add_panics() {
+ let [w0, w1] = incompatible_weights();
+ let _ = w0 + w1;
+ }
+
+ #[test]
+ #[should_panic = "invalid weight length"]
+ fn add_assign_panics() {
+ let [mut w0, w1] = incompatible_weights();
+ w0 += w1;
+ }
+
+ #[test]
+ #[should_panic = "invalid weight length"]
+ fn sub_panics() {
+ let [w0, w1] = incompatible_weights();
+ let _ = w0 - w1;
+ }
+
+ #[test]
+ #[should_panic = "invalid weight length"]
+ fn conditional_select_panics() {
+ let [w0, w1] = incompatible_weights();
+ TestWeight::conditional_select(&w0, &w1, Choice::from(0));
+ }
+
+ fn compatible_weights() -> [TestWeight; 2] {
+ let mut xof = XofTurboShake128::seed_stream(&Seed(Default::default()), &[], &[]);
+ [
+ TestWeight::generate(&mut xof, &TEST_WEIGHT_LEN),
+ TestWeight::generate(&mut xof, &TEST_WEIGHT_LEN),
+ ]
+ }
+
+ fn incompatible_weights() -> [TestWeight; 2] {
+ let mut xof = XofTurboShake128::seed_stream(&Seed(Default::default()), &[], &[]);
+ [
+ TestWeight::generate(&mut xof, &TEST_WEIGHT_LEN),
+ TestWeight::generate(&mut xof, &(2 * TEST_WEIGHT_LEN)),
+ ]
+ }
+ }
+}
diff --git a/third_party/rust/prio/tests/discrete_gauss.rs b/third_party/rust/prio/tests/discrete_gauss.rs
index 5b3ef4c5b3..d72138b64c 100644
--- a/third_party/rust/prio/tests/discrete_gauss.rs
+++ b/third_party/rust/prio/tests/discrete_gauss.rs
@@ -4,7 +4,7 @@ use num_bigint::{BigInt, BigUint};
use num_rational::Ratio;
use num_traits::FromPrimitive;
use prio::dp::distributions::DiscreteGaussian;
-use prio::vdaf::xof::SeedStreamSha3;
+use prio::vdaf::xof::SeedStreamTurboShake128;
use rand::distributions::Distribution;
use rand::SeedableRng;
use serde::Deserialize;
@@ -12,7 +12,7 @@ use serde::Deserialize;
/// A test vector of discrete Gaussian samples, produced by the python reference
/// implementation for [[CKS20]]. The script used to generate the test vector can
/// be found in this gist:
-/// https://gist.github.com/ooovi/529c00fc8a7eafd068cd076b78fc424e
+/// https://gist.github.com/divergentdave/94cab188e84a4764db6cdd1288e6ead3
/// The python reference implementation is here:
/// https://github.com/IBM/discrete-gaussian-differential-privacy
///
@@ -29,20 +29,15 @@ pub struct DiscreteGaussTestVector {
#[test]
fn discrete_gauss_reference() {
let test_vectors: Vec<DiscreteGaussTestVector> = vec![
- serde_json::from_str(include_str!(concat!("test_vectors/discrete_gauss_3.json"))).unwrap(),
- serde_json::from_str(include_str!(concat!("test_vectors/discrete_gauss_9.json"))).unwrap(),
- serde_json::from_str(include_str!(concat!(
- "test_vectors/discrete_gauss_100.json"
- )))
- .unwrap(),
- serde_json::from_str(include_str!(concat!(
- "test_vectors/discrete_gauss_41293847.json"
- )))
- .unwrap(),
- serde_json::from_str(include_str!(concat!(
+ serde_json::from_str(include_str!("test_vectors/discrete_gauss_3.json")).unwrap(),
+ serde_json::from_str(include_str!("test_vectors/discrete_gauss_9.json")).unwrap(),
+ serde_json::from_str(include_str!("test_vectors/discrete_gauss_100.json")).unwrap(),
+ serde_json::from_str(include_str!("test_vectors/discrete_gauss_41293847.json")).unwrap(),
+ serde_json::from_str(include_str!(
"test_vectors/discrete_gauss_9999999999999999999999.json"
- )))
+ ))
.unwrap(),
+ serde_json::from_str(include_str!("test_vectors/discrete_gauss_2.342.json")).unwrap(),
];
for test_vector in test_vectors {
@@ -53,7 +48,7 @@ fn discrete_gauss_reference() {
.unwrap();
// check samples are consistent
- let mut rng = SeedStreamSha3::from_seed(test_vector.seed);
+ let mut rng = SeedStreamTurboShake128::from_seed(test_vector.seed);
let samples: Vec<BigInt> = (0..test_vector.samples.len())
.map(|_| sampler.sample(&mut rng))
.collect();
diff --git a/third_party/rust/prio/tests/test_vectors/discrete_gauss_100.json b/third_party/rust/prio/tests/test_vectors/discrete_gauss_100.json
index fe8114c258..84425db753 100644
--- a/third_party/rust/prio/tests/test_vectors/discrete_gauss_100.json
+++ b/third_party/rust/prio/tests/test_vectors/discrete_gauss_100.json
@@ -1,54 +1,54 @@
{
"samples": [
- -74,
+ -54,
+ 61,
+ -113,
+ -98,
+ 21,
+ -91,
+ 72,
+ 112,
+ -29,
68,
- -15,
- 175,
- -120,
- -2,
- -73,
- 108,
- 40,
- 69,
- 81,
- -135,
- 247,
- 32,
- 107,
+ 84,
+ -27,
+ -109,
+ -20,
+ -24,
+ -69,
+ -168,
+ 199,
+ -122,
+ 59,
+ 35,
+ 282,
+ 113,
+ 4,
+ -91,
-61,
- 164,
- 22,
- 118,
- 37,
- -58,
- 147,
- 65,
- 53,
- 9,
- -96,
- -130,
- 100,
- 48,
+ -28,
+ 137,
+ 57,
+ 109,
+ 2,
+ 17,
+ -20,
+ 38,
+ -16,
+ 18,
+ -63,
+ 1,
+ -20,
-30,
- -2,
- -115,
- 56,
- 95,
- 119,
- 28,
- -101,
- 50,
- 39,
- 21,
- -6,
- -70,
- 131,
- 66,
- 81,
- -18,
- 94,
- 55,
- 20
+ -147,
+ -73,
+ -28,
+ -16,
+ -31,
+ 10,
+ -229,
+ -56,
+ -254
],
"seed": "000102030405060708090a0b0c0d0e0f",
"std_denom": 1,
diff --git a/third_party/rust/prio/tests/test_vectors/discrete_gauss_2.342.json b/third_party/rust/prio/tests/test_vectors/discrete_gauss_2.342.json
index 7d9508c44e..c70e3b06e1 100644
--- a/third_party/rust/prio/tests/test_vectors/discrete_gauss_2.342.json
+++ b/third_party/rust/prio/tests/test_vectors/discrete_gauss_2.342.json
@@ -1,54 +1,54 @@
{
"samples": [
-1,
- 4,
- 2,
- 0,
- 0,
- -2,
1,
- -5,
+ 6,
2,
+ -4,
-1,
- 0,
- 0,
- 0,
- 3,
- -6,
- 5,
+ -2,
2,
- 1,
- -1,
+ -2,
-3,
0,
- 2,
- -3,
-2,
+ -1,
+ 3,
2,
- -3,
- 1,
1,
2,
- -3,
- -1,
+ -7,
-1,
+ 0,
4,
- 2,
- -2,
1,
-1,
0,
- -3,
+ 1,
+ -2,
+ 0,
1,
2,
+ 0,
+ 6,
+ -2,
+ 2,
+ 0,
+ -2,
+ 2,
+ 6,
1,
+ 0,
+ -4,
+ -3,
+ -1,
-1,
- 3,
- 1,
2,
- -3,
+ 0,
+ 0,
-2,
- 0
+ 0,
+ 2
],
"seed": "000102030405060708090a0b0c0d0e0f",
"std_denom": 500,
diff --git a/third_party/rust/prio/tests/test_vectors/discrete_gauss_3.json b/third_party/rust/prio/tests/test_vectors/discrete_gauss_3.json
index d4a3486db0..363c136eb8 100644
--- a/third_party/rust/prio/tests/test_vectors/discrete_gauss_3.json
+++ b/third_party/rust/prio/tests/test_vectors/discrete_gauss_3.json
@@ -1,54 +1,54 @@
{
"samples": [
- 1,
+ -3,
-1,
-2,
1,
+ 7,
-1,
- 0,
- 1,
- -1,
- 0,
- 2,
- 3,
- 4,
- 1,
- 1,
-2,
- 4,
- 6,
+ 1,
-5,
+ 1,
-3,
- -1,
- 4,
- 0,
- 6,
- 2,
+ 3,
2,
- -4,
- -2,
-5,
+ -2,
+ 5,
+ -2,
+ 5,
+ -1,
-3,
2,
- 1,
- -3,
-2,
- 1,
+ -1,
-2,
- 1,
+ -2,
+ -1,
0,
- 3,
- -4,
- -4,
1,
- 3,
+ -1,
2,
- 1,
- 0,
+ -3,
+ 2,
+ -6,
+ -4,
+ -2,
+ -2,
+ -6,
-1,
- 1,
4,
- 1
+ -1,
+ 2,
+ -3,
+ 1,
+ -7,
+ -1,
+ 6,
+ 2,
+ -3,
+ 5
],
"seed": "000102030405060708090a0b0c0d0e0f",
"std_denom": 1,
diff --git a/third_party/rust/prio/tests/test_vectors/discrete_gauss_41293847.json b/third_party/rust/prio/tests/test_vectors/discrete_gauss_41293847.json
index 213e919c6c..247b2c2451 100644
--- a/third_party/rust/prio/tests/test_vectors/discrete_gauss_41293847.json
+++ b/third_party/rust/prio/tests/test_vectors/discrete_gauss_41293847.json
@@ -1,54 +1,54 @@
{
"samples": [
- -10157810,
- -7944688,
- 80361481,
- -2601121,
- -2098394,
- -61204295,
- 250399,
- 62702361,
- -35117486,
- 14804891,
- -5043613,
- 34131059,
- -34448923,
- -24176095,
- 106518772,
- 44056972,
- 15910928,
- 63338376,
- 12839729,
- 11701052,
- -54254959,
- -11306071,
- -6005727,
- 29738939,
- -30284246,
- -47672638,
- 11549070,
- -17580447,
- -2973754,
- -298465,
- -15349002,
- 56970396,
- 35612502,
- -78720214,
- -6082493,
- -2759887,
- -11374460,
- 177253,
- -35234082,
- 42256563,
- 44219644,
- 86984413,
- -43711428,
- -16031438,
- 42572889,
- 39464625,
- -14433332,
- -7735634,
- 4403776
+ -28705712,
+ 12839166,
+ 68574447,
+ 1993202,
+ 17416465,
+ 32526761,
+ 1212638,
+ -44876888,
+ 16502539,
+ -57954542,
+ -54567452,
+ -17421605,
+ 7569207,
+ 13482762,
+ -24573436,
+ 73067636,
+ -58069630,
+ -24924404,
+ 51409721,
+ -18659663,
+ -12752706,
+ 4308454,
+ -49095581,
+ -69009203,
+ -22975883,
+ 46983148,
+ 47341228,
+ -1860382,
+ 26901791,
+ -5079023,
+ -57635595,
+ -38560402,
+ 59065470,
+ 100046871,
+ -144954761,
+ -22089238,
+ -43816191,
+ -47986043,
+ 34106023,
+ 74194716,
+ -37681692,
+ 3946618,
+ 18344461,
+ -45770607,
+ -654004,
+ 31284526,
+ -50259979,
+ 28037461,
+ 2734567
],
"seed": "000102030405060708090a0b0c0d0e0f",
"std_denom": 1,
diff --git a/third_party/rust/prio/tests/test_vectors/discrete_gauss_9.json b/third_party/rust/prio/tests/test_vectors/discrete_gauss_9.json
index 408c7489a7..b5df20d182 100644
--- a/third_party/rust/prio/tests/test_vectors/discrete_gauss_9.json
+++ b/third_party/rust/prio/tests/test_vectors/discrete_gauss_9.json
@@ -1,54 +1,54 @@
{
"samples": [
- 2,
- 14,
- -12,
- 10,
- -13,
- 1,
- 6,
- -10,
+ -6,
+ 7,
+ -3,
+ -7,
+ -14,
+ 4,
+ 11,
+ -22,
-1,
+ 8,
+ -9,
+ 12,
+ -9,
+ 20,
+ -16,
+ -10,
+ -8,
+ -15,
+ 6,
+ -8,
+ 7,
+ 12,
+ 1,
4,
+ -3,
+ -7,
+ 20,
+ 2,
+ 13,
+ -4,
-5,
1,
- -20,
- 1,
- -14,
+ 2,
+ -2,
+ 4,
+ -6,
2,
-5,
- 10,
- 3,
- 9,
- 10,
- 12,
- -4,
- 12,
- -4,
- -13,
- 7,
- -10,
-6,
2,
- 6,
- 18,
- -7,
- -11,
- 20,
- 1,
- -4,
- 14,
- 11,
- 5,
- 6,
- -1,
2,
- 5,
- 3,
- -8,
- -1,
- 6,
- -8
+ -5,
+ -10,
+ -9,
+ -15,
+ -2,
+ -3,
+ 1,
+ -13
],
"seed": "000102030405060708090a0b0c0d0e0f",
"std_denom": 1,
diff --git a/third_party/rust/prio/tests/test_vectors/discrete_gauss_9999999999999999999999.json b/third_party/rust/prio/tests/test_vectors/discrete_gauss_9999999999999999999999.json
index 396f5a4cf0..1b43f758bd 100644
--- a/third_party/rust/prio/tests/test_vectors/discrete_gauss_9999999999999999999999.json
+++ b/third_party/rust/prio/tests/test_vectors/discrete_gauss_9999999999999999999999.json
@@ -1,54 +1,54 @@
{
"samples": [
- 7826646418794481373730,
- 4044429794334089153683,
- -13887062284591122240746,
- 4816851335312673293131,
- 1899078604295677453383,
- -7819872990828024151405,
- 1164017821807881486579,
- -25360379570365624087817,
- 5906637163630390455939,
- 3730592807287609262846,
- 1737147847266613603450,
- 18593764766679058926154,
- 22724295990478919946193,
- -4396717652132313983045,
- -7933138830987043774425,
- 12204708418993708917398,
- 10716232788607487693156,
- -7423575920998904747964,
- -274262846168968742506,
- -24595460253341309777726,
- 1880635641243101726137,
- 10823060437484007979521,
- -2525077352000184270857,
- -1421364839539048815904,
- -2648842672480402351562,
- -7783156811031000955203,
- -1831198454606609539077,
- 905920470298728568753,
- -8805882598094077859729,
- 2949974625887521817722,
- 13071000629486423981714,
- 1311702736683393895126,
- -14044034250430823347919,
- 1421736709768854180193,
- 14824744520414922652958,
- 10752031849750698732804,
- -522118577625103067952,
- 2006618532306506057615,
- -7573105805904097888275,
- -14482966128638641002042,
- -11408400475022385123481,
- -17555433966245180572099,
- -6120185353438187140929,
- -4778266138627264471521,
- -19325342657405318133711,
- 3725950229250476135126,
- -7977400544074383347686,
- 2738166449787592433931,
- -1321521809406566447071
+ -7678632936135800555201,
+ -9832864446958915374632,
+ 3796223649719723548306,
+ -10458306547534276720045,
+ -9593524715689396783652,
+ -2184509652523057908030,
+ -6469904065015921866985,
+ 8555843521262785582921,
+ -3275061234860213279391,
+ -1712551617443682313245,
+ -4176263950279049852314,
+ -1041488124720108532833,
+ 2422891656983904955539,
+ -5406575579403973625234,
+ 4031989610743156091985,
+ -15897376981820943559856,
+ -9495308497775799052592,
+ -10542231739931574778478,
+ -811195020079942319200,
+ -6168725392123782999911,
+ 3572639345203916100181,
+ 9572138148079890711898,
+ 12973597810318272581841,
+ -10417671747756128178069,
+ -4499306785200793424437,
+ 24392853538076877246695,
+ 490509578119404728479,
+ -3153758591414179213424,
+ -2953031165864251687043,
+ 7687220020362800379045,
+ -2894825604535601473288,
+ -2484898457763802405625,
+ 2506976850588238983075,
+ -317271622218426183645,
+ 3771644622097191550823,
+ 14048201376263257821999,
+ 1011626374739477364716,
+ -7985335097085684878144,
+ -9834946916794550716888,
+ -7808156770298839154888,
+ -10888303506419120919014,
+ 20441738459254393472434,
+ -1142146934147582936699,
+ -380992974206599694131,
+ 14719724965924743443097,
+ 2738534455216435603182,
+ 16889459715609520924993,
+ 8450917371339563018232,
+ 3461026365290831355984
],
"seed": "000102030405060708090a0b0c0d0e0f",
"std_denom": 1,
diff --git a/third_party/rust/qlog/.cargo-checksum.json b/third_party/rust/qlog/.cargo-checksum.json
index 4aae6bf3b8..e0db62dc79 100644
--- a/third_party/rust/qlog/.cargo-checksum.json
+++ b/third_party/rust/qlog/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"66c6d85a84c84711f3abddaafb163bc6025a8505701fea8b61bfa961851be757","README.md":"597691eb766c2cbd7a6591bda56d3e70e6836b62b6327fb73497523eabd5b53d","src/events/connectivity.rs":"116993412e200e375c97762980ffb638d2244197fd752b9569b5b20baf574308","src/events/h3.rs":"4799179c4d18403a3936a327c483d110bd058d42061f9cdd39601b3e91500c1b","src/events/mod.rs":"75f57b4717fa9777e19d61b99b6a79164f0e8bca9b4681c3ab11b204320c8c55","src/events/qpack.rs":"5c7267c45e3fb947cdfa946f9f9692d3e3e36a166f70124ba293dc27534267d0","src/events/quic.rs":"88b884f5788c671ffee79a3448f367c18f95ee30531262fcc14310d80e662f4a","src/events/security.rs":"e9852d7de16851b62c3e0a886a2c1a31d237e62574ef88428ef62dd179b0b008","src/lib.rs":"bbc190a6d0f484fd723f9df6c1b2a4596f826e0282ad40ee17a0822ea28a5626","src/reader.rs":"4e0069c24aca9cb99d75075c9b784fa02855ea449d2f1528bea944a4e02a9af5","src/streamer.rs":"4774c2abde1a5b0f4448aac06c62c7927208c12f338c46981f80c98703b54074"},"package":"9c0407438c69b3d99714a796a135cbfb2d60744e4747fb2b46a87acd1c1fcd0e"} \ No newline at end of file
+{"files":{"Cargo.toml":"f660fd1858ac7bc0cc6a0db2058a311328678b5d19e5f7a2eb1cdebe74155752","README.md":"597691eb766c2cbd7a6591bda56d3e70e6836b62b6327fb73497523eabd5b53d","src/events/connectivity.rs":"116993412e200e375c97762980ffb638d2244197fd752b9569b5b20baf574308","src/events/h3.rs":"4799179c4d18403a3936a327c483d110bd058d42061f9cdd39601b3e91500c1b","src/events/mod.rs":"2e9f00885face20abeb183c7421b11d402c13d841921ce9a8b0061b141e97353","src/events/qpack.rs":"5c7267c45e3fb947cdfa946f9f9692d3e3e36a166f70124ba293dc27534267d0","src/events/quic.rs":"aae0ff30e8cd27219dbb5bcb34d78d11c3f81bbdc099aabdd37b8f7206e3fb9c","src/events/security.rs":"e9852d7de16851b62c3e0a886a2c1a31d237e62574ef88428ef62dd179b0b008","src/lib.rs":"ef7121a53369c995e333a84c6ed0c14c91ca5825588a27a47ae5d92a44cb0b07","src/reader.rs":"4e0069c24aca9cb99d75075c9b784fa02855ea449d2f1528bea944a4e02a9af5","src/streamer.rs":"4774c2abde1a5b0f4448aac06c62c7927208c12f338c46981f80c98703b54074"},"package":"9b5f65b920fa913ce92267bb3c4ed3b9c2f81d05f8e1376c3bbc95455eedb7df"} \ No newline at end of file
diff --git a/third_party/rust/qlog/Cargo.toml b/third_party/rust/qlog/Cargo.toml
index 4a5eb1ff96..928951a973 100644
--- a/third_party/rust/qlog/Cargo.toml
+++ b/third_party/rust/qlog/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "qlog"
-version = "0.12.0"
+version = "0.13.0"
authors = ["Lucas Pardue <lucaspardue.24.7@gmail.com>"]
description = "qlog data model for QUIC and HTTP/3"
readme = "README.md"
diff --git a/third_party/rust/qlog/src/events/mod.rs b/third_party/rust/qlog/src/events/mod.rs
index ac18276fd0..dbd35183ef 100644
--- a/third_party/rust/qlog/src/events/mod.rs
+++ b/third_party/rust/qlog/src/events/mod.rs
@@ -203,6 +203,9 @@ impl From<EventType> for EventImportance {
ConnectivityEventType::ConnectionStarted,
) => EventImportance::Base,
EventType::ConnectivityEventType(
+ ConnectivityEventType::ConnectionClosed,
+ ) => EventImportance::Base,
+ EventType::ConnectivityEventType(
ConnectivityEventType::ConnectionIdUpdated,
) => EventImportance::Base,
EventType::ConnectivityEventType(
diff --git a/third_party/rust/qlog/src/events/quic.rs b/third_party/rust/qlog/src/events/quic.rs
index a7c1fa3225..e504125a1a 100644
--- a/third_party/rust/qlog/src/events/quic.rs
+++ b/third_party/rust/qlog/src/events/quic.rs
@@ -384,30 +384,43 @@ pub enum QuicFrameTypeName {
// ensure it goes out on the wire. This means that deserialization of frames
// also works automatically.
pub enum QuicFrame {
- Padding,
+ Padding {
+ length: Option<u32>,
+ payload_length: u32,
+ },
- Ping,
+ Ping {
+ length: Option<u32>,
+ payload_length: Option<u32>,
+ },
Ack {
ack_delay: Option<f32>,
acked_ranges: Option<AckedRanges>,
ect1: Option<u64>,
-
ect0: Option<u64>,
-
ce: Option<u64>,
+
+ length: Option<u32>,
+ payload_length: Option<u32>,
},
ResetStream {
stream_id: u64,
error_code: u64,
final_size: u64,
+
+ length: Option<u32>,
+ payload_length: Option<u32>,
},
StopSending {
stream_id: u64,
error_code: u64,
+
+ length: Option<u32>,
+ payload_length: Option<u32>,
},
Crypto {
diff --git a/third_party/rust/qlog/src/lib.rs b/third_party/rust/qlog/src/lib.rs
index 68ff278fcd..ed26570fe0 100644
--- a/third_party/rust/qlog/src/lib.rs
+++ b/third_party/rust/qlog/src/lib.rs
@@ -332,8 +332,14 @@
//! Some(&dcid),
//! );
//!
-//! let ping = qlog::events::quic::QuicFrame::Ping;
-//! let padding = qlog::events::quic::QuicFrame::Padding;
+//! let ping = qlog::events::quic::QuicFrame::Ping {
+//! length: None,
+//! payload_length: None,
+//! };
+//! let padding = qlog::events::quic::QuicFrame::Padding {
+//! length: None,
+//! payload_length: 1234,
+//! };
//!
//! let event_data =
//! qlog::events::EventData::PacketSent(qlog::events::quic::PacketSent {
@@ -790,7 +796,8 @@ mod tests {
},
"frames": [
{
- "frame_type": "padding"
+ "frame_type": "padding",
+ "payload_length": 1234
},
{
"frame_type": "ping"
@@ -808,14 +815,23 @@ mod tests {
let pkt_hdr = make_pkt_hdr(PacketType::Initial);
- let frames =
- vec![QuicFrame::Padding, QuicFrame::Ping, QuicFrame::Stream {
+ let frames = vec![
+ QuicFrame::Padding {
+ payload_length: 1234,
+ length: None,
+ },
+ QuicFrame::Ping {
+ payload_length: None,
+ length: None,
+ },
+ QuicFrame::Stream {
stream_id: 0,
offset: 0,
length: 100,
fin: Some(true),
raw: None,
- }];
+ },
+ ];
let ev_data = EventData::PacketSent(PacketSent {
header: pkt_hdr,
diff --git a/third_party/rust/relevancy/.cargo-checksum.json b/third_party/rust/relevancy/.cargo-checksum.json
index c8d8187c8d..bfa17d066a 100644
--- a/third_party/rust/relevancy/.cargo-checksum.json
+++ b/third_party/rust/relevancy/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"76d64a839128f51662d1c10728ceddbb6a9ebdfce803915874cd654117d1b14e","build.rs":"a562bfe527d21c4e8a1a44b892defa83cdff141ec5dd51ed6f3862330e50ddd7","src/bin/generate-test-data.rs":"7f1c9dc445418c7627f89d1f2aa8e550d0f85b3d1f05edb7c378ab9441714f1f","src/db.rs":"0b45180f3031759213a0421231b6f109ed4f5c88aca556df159ce2717416cfec","src/error.rs":"6831fc329044174a8451b8b008c0b96c47404c591eb42e880562e65da0adfd0f","src/interest.rs":"ce6298ef8f69fcb57c8e5797467cbe1c0212a0d94daf828b12845740ac14a166","src/lib.rs":"7a0f0ad0a43f371035d9c0b73d143cf1b387d4b8cfad0d0db79314b5b91fd43c","src/populate_interests.rs":"b8905b52f9fc80719c175253b758413f606b27660e660635094421eec8b24c8f","src/relevancy.udl":"a3fae5097f9e8b39bb6c74ed6789906748c46f22d377e3dcb73b08731908f5bc","src/schema.rs":"f782c712f10c4f1af2f9e1424d6b52f59a2bacfcc452a8feb763f36478f5dd5d","src/url_hash.rs":"5619a249d471e7b642d889bad09e93212559c8b947010d49492c1423da2b310e","test-data":"392fc950363c9953ea6ab144b81d84021c4af1e1177cc0adac4eda5688c8bc33"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"2b7bf33e20b6aa768dd18619845e9d5d22235d86f770e94b250ed0052662ce2d","build.rs":"a562bfe527d21c4e8a1a44b892defa83cdff141ec5dd51ed6f3862330e50ddd7","src/bin/generate-test-data.rs":"7f1c9dc445418c7627f89d1f2aa8e550d0f85b3d1f05edb7c378ab9441714f1f","src/db.rs":"7ca5688c42d44ad6e5320208257d131c5c744be47a1cfe3e1380147abf2aadc3","src/error.rs":"0fe48e211dffb2010f732672c38e1c79b1995df3e70b06398ed8ac43d326c1b1","src/ingest.rs":"d3f528c1d62b4b6af404bb14cb0d431f8d523911ada09e4e1db5836b6cf44e04","src/interest.rs":"adbaa1e0324c7bb32b023f105b45499390a1a83973d1a8c7d727a661a25cc259","src/lib.rs":"29ce35211c9d94d561d62d7e8ef57fc56cc90a9ba42b88b54c2f4c9236a8cd4d","src/relevancy.udl":"b551e7476f30dccdc74cbf2f38fc3b87a3a7d0ec5dfa6c2ea4417b18fbc7475c","src/rs.rs":"b98091d0adca809d8fef38eb5394f885e04d4d382b7c8abd7bd0fe53f64e7bd6","src/schema.rs":"f782c712f10c4f1af2f9e1424d6b52f59a2bacfcc452a8feb763f36478f5dd5d","src/url_hash.rs":"2e908316fb70923644d1990dbf470d69ce2f5e99b0c5c3d95ec691590be8ffa5","test-data":"1ef2cd092d59e7e126cd4a514af983d449ed9f9c98708702fd237464a76c2b5e"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/relevancy/Cargo.toml b/third_party/rust/relevancy/Cargo.toml
index eddd8fd25c..67c1716ab2 100644
--- a/third_party/rust/relevancy/Cargo.toml
+++ b/third_party/rust/relevancy/Cargo.toml
@@ -25,9 +25,12 @@ license = "MPL-2.0"
name = "generate-test-data"
[dependencies]
+anyhow = "1.0"
+base64 = "0.21.2"
log = "0.4"
md-5 = "0.10"
parking_lot = ">=0.11,<=0.12"
+serde_json = "1"
thiserror = "1.0"
uniffi = "0.27.1"
url = "2.5"
@@ -35,10 +38,20 @@ url = "2.5"
[dependencies.error-support]
path = "../support/error"
+[dependencies.interrupt-support]
+path = "../support/interrupt"
+
+[dependencies.remote_settings]
+path = "../remote_settings"
+
[dependencies.rusqlite]
version = "0.30.0"
features = ["bundled"]
+[dependencies.serde]
+version = "1"
+features = ["derive"]
+
[dependencies.sql-support]
path = "../support/sql"
diff --git a/third_party/rust/relevancy/src/db.rs b/third_party/rust/relevancy/src/db.rs
index 08684c45af..b2dc0b0c83 100644
--- a/third_party/rust/relevancy/src/db.rs
+++ b/third_party/rust/relevancy/src/db.rs
@@ -8,52 +8,66 @@ use crate::{
url_hash::{hash_url, UrlHash},
Interest, InterestVector, Result,
};
-use parking_lot::Mutex;
+use interrupt_support::SqlInterruptScope;
use rusqlite::{Connection, OpenFlags};
-use sql_support::{open_database::open_database_with_flags, ConnExt};
+use sql_support::{ConnExt, LazyDb};
use std::path::Path;
/// A thread-safe wrapper around an SQLite connection to the Relevancy database
pub struct RelevancyDb {
- pub conn: Mutex<Connection>,
+ reader: LazyDb<RelevancyConnectionInitializer>,
+ writer: LazyDb<RelevancyConnectionInitializer>,
}
impl RelevancyDb {
- pub fn open(path: impl AsRef<Path>) -> Result<Self> {
- let conn = open_database_with_flags(
- path,
- OpenFlags::SQLITE_OPEN_URI
- | OpenFlags::SQLITE_OPEN_NO_MUTEX
- | OpenFlags::SQLITE_OPEN_CREATE
- | OpenFlags::SQLITE_OPEN_READ_WRITE,
- &RelevancyConnectionInitializer,
- )?;
- Ok(Self {
- conn: Mutex::new(conn),
- })
+ pub fn new(path: impl AsRef<Path>) -> Self {
+ // Note: use `SQLITE_OPEN_READ_WRITE` for both read and write connections.
+ // Even if we're opening a read connection, we may need to do a write as part of the
+ // initialization process.
+ //
+ // The read-only nature of the connection is enforced by the fact that [RelevancyDb::read] uses a
+ // shared ref to the `RelevancyDao`.
+ let db_open_flags = OpenFlags::SQLITE_OPEN_URI
+ | OpenFlags::SQLITE_OPEN_NO_MUTEX
+ | OpenFlags::SQLITE_OPEN_CREATE
+ | OpenFlags::SQLITE_OPEN_READ_WRITE;
+ Self {
+ reader: LazyDb::new(path.as_ref(), db_open_flags, RelevancyConnectionInitializer),
+ writer: LazyDb::new(path.as_ref(), db_open_flags, RelevancyConnectionInitializer),
+ }
+ }
+
+ pub fn close(&self) {
+ self.reader.close(true);
+ self.writer.close(true);
+ }
+
+ pub fn interrupt(&self) {
+ self.reader.interrupt();
+ self.writer.interrupt();
}
#[cfg(test)]
- pub fn open_for_test() -> Self {
+ pub fn new_for_test() -> Self {
use std::sync::atomic::{AtomicU32, Ordering};
static COUNTER: AtomicU32 = AtomicU32::new(0);
let count = COUNTER.fetch_add(1, Ordering::Relaxed);
- Self::open(format!("file:test{count}.sqlite?mode=memory&cache=shared")).unwrap()
+ Self::new(format!("file:test{count}.sqlite?mode=memory&cache=shared"))
}
/// Accesses the Suggest database in a transaction for reading.
pub fn read<T>(&self, op: impl FnOnce(&RelevancyDao) -> Result<T>) -> Result<T> {
- let mut conn = self.conn.lock();
+ let (mut conn, scope) = self.reader.lock()?;
let tx = conn.transaction()?;
- let dao = RelevancyDao::new(&tx);
+ let dao = RelevancyDao::new(&tx, scope);
op(&dao)
}
/// Accesses the Suggest database in a transaction for reading and writing.
pub fn read_write<T>(&self, op: impl FnOnce(&mut RelevancyDao) -> Result<T>) -> Result<T> {
- let mut conn = self.conn.lock();
+ let (mut conn, scope) = self.writer.lock()?;
let tx = conn.transaction()?;
- let mut dao = RelevancyDao::new(&tx);
+ let mut dao = RelevancyDao::new(&tx, scope);
let result = op(&mut dao)?;
tx.commit()?;
Ok(result)
@@ -67,11 +81,17 @@ impl RelevancyDb {
/// reference (`&mut self`).
pub struct RelevancyDao<'a> {
pub conn: &'a Connection,
+ pub scope: SqlInterruptScope,
}
impl<'a> RelevancyDao<'a> {
- fn new(conn: &'a Connection) -> Self {
- Self { conn }
+ fn new(conn: &'a Connection, scope: SqlInterruptScope) -> Self {
+ Self { conn, scope }
+ }
+
+ /// Return Err(Interrupted) if we were interrupted
+ pub fn err_if_interrupted(&self) -> Result<()> {
+ Ok(self.scope.err_if_interrupted()?)
}
/// Associate a URL with an interest
@@ -98,7 +118,7 @@ impl<'a> RelevancyDao<'a> {
",
)?;
let interests = stmt.query_and_then((hash,), |row| -> Result<Interest> {
- Ok(row.get::<_, u32>(0)?.into())
+ row.get::<_, u32>(0)?.try_into()
})?;
let mut interest_vec = InterestVector::default();
diff --git a/third_party/rust/relevancy/src/error.rs b/third_party/rust/relevancy/src/error.rs
index 93ca7aabaa..1d42ff2c03 100644
--- a/third_party/rust/relevancy/src/error.rs
+++ b/third_party/rust/relevancy/src/error.rs
@@ -23,6 +23,21 @@ pub enum Error {
#[error("Error fetching interest data")]
FetchInterestDataError,
+
+ #[error("Interrupted")]
+ Interrupted(#[from] interrupt_support::Interrupted),
+
+ #[error("Invalid interest code: {0}")]
+ InvalidInterestCode(u32),
+
+ #[error("Remote Setting Error: {0}")]
+ RemoteSettingsError(#[from] remote_settings::RemoteSettingsError),
+
+ #[error("Serde Json Error: {0}")]
+ SerdeJsonError(#[from] serde_json::Error),
+
+ #[error("Base64 Decode Error: {0}")]
+ Base64DecodeError(String),
}
/// Result enum for the public API
diff --git a/third_party/rust/relevancy/src/ingest.rs b/third_party/rust/relevancy/src/ingest.rs
new file mode 100644
index 0000000000..dc01fbe019
--- /dev/null
+++ b/third_party/rust/relevancy/src/ingest.rs
@@ -0,0 +1,394 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use crate::db::RelevancyDao;
+use crate::rs::{
+ RelevancyAttachmentData, RelevancyRecord, RelevancyRemoteSettingsClient,
+ REMOTE_SETTINGS_COLLECTION,
+};
+use crate::url_hash::UrlHash;
+use crate::{Error, Interest, RelevancyDb, Result};
+use base64::{engine::general_purpose::STANDARD, Engine};
+use remote_settings::{Client, RemoteSettingsConfig, RemoteSettingsRecord, RemoteSettingsServer};
+
+// Number of rows to write when inserting interest data before checking for interruption
+const WRITE_CHUNK_SIZE: usize = 100;
+
+pub fn ensure_interest_data_populated(db: &RelevancyDb) -> Result<()> {
+ if !db.read(|dao| dao.need_to_load_url_interests())? {
+ return Ok(());
+ }
+
+ match fetch_interest_data() {
+ Ok(data) => {
+ db.read_write(move |dao| insert_interest_data(data, dao))?;
+ }
+ Err(e) => {
+ log::warn!("error fetching interest data: {e}");
+ return Err(Error::FetchInterestDataError);
+ }
+ }
+ Ok(())
+}
+
+fn fetch_interest_data() -> Result<Vec<(Interest, UrlHash)>> {
+ let rs = Client::new(RemoteSettingsConfig {
+ collection_name: REMOTE_SETTINGS_COLLECTION.to_string(),
+ server: Some(RemoteSettingsServer::Prod),
+ server_url: None,
+ bucket_name: None,
+ })?;
+ fetch_interest_data_inner(rs)
+}
+
+/// Fetch the interest data
+fn fetch_interest_data_inner(
+ rs: impl RelevancyRemoteSettingsClient,
+) -> Result<Vec<(Interest, UrlHash)>> {
+ let remote_settings_response = rs.get_records()?;
+ let mut result = vec![];
+
+ for record in remote_settings_response.records {
+ let attachment_data = match &record.attachment {
+ None => return Err(Error::FetchInterestDataError),
+ Some(a) => rs.get_attachment(&a.location)?,
+ };
+ let interest = get_interest(&record)?;
+ let urls = get_hash_urls(attachment_data)?;
+ result.extend(std::iter::repeat(interest).zip(urls));
+ }
+ Ok(result)
+}
+
+fn get_hash_urls(attachment_data: Vec<u8>) -> Result<Vec<UrlHash>> {
+ let mut hash_urls = vec![];
+
+ let parsed_attachment_data =
+ serde_json::from_slice::<Vec<RelevancyAttachmentData>>(&attachment_data)?;
+
+ for attachment_data in parsed_attachment_data {
+ let hash_url = STANDARD
+ .decode(attachment_data.domain)
+ .map_err(|_| Error::Base64DecodeError("Invalid base64 error".to_string()))?;
+ let url_hash = hash_url.try_into().map_err(|_| {
+ Error::Base64DecodeError("Base64 string has wrong number of bytes".to_string())
+ })?;
+ hash_urls.push(url_hash);
+ }
+ Ok(hash_urls)
+}
+
+/// Extract Interest from the record info
+fn get_interest(record: &RemoteSettingsRecord) -> Result<Interest> {
+ let record_fields: RelevancyRecord =
+ serde_json::from_value(serde_json::Value::Object(record.fields.clone()))?;
+ let custom_details = record_fields.record_custom_details;
+ let category_code = custom_details.category_to_domains.category_code;
+ Interest::try_from(category_code as u32)
+}
+
+/// Insert Interests into Db
+fn insert_interest_data(data: Vec<(Interest, UrlHash)>, dao: &mut RelevancyDao) -> Result<()> {
+ for chunk in data.chunks(WRITE_CHUNK_SIZE) {
+ dao.err_if_interrupted()?;
+ for (interest, hash_url) in chunk {
+ dao.add_url_interest(*hash_url, *interest)?;
+ }
+ }
+
+ Ok(())
+}
+
+#[cfg(test)]
+mod test {
+
+ use std::{cell::RefCell, collections::HashMap};
+
+ use anyhow::Context;
+ use remote_settings::RemoteSettingsResponse;
+ use serde_json::json;
+
+ use super::*;
+ use crate::{rs::RelevancyRemoteSettingsClient, url_hash::hash_url, InterestVector};
+
+ /// A snapshot containing fake Remote Settings records and attachments for
+ /// the store to ingest. We use snapshots to test the store's behavior in a
+ /// data-driven way.
+ struct Snapshot {
+ records: Vec<RemoteSettingsRecord>,
+ attachments: HashMap<&'static str, Vec<u8>>,
+ }
+
+ impl Snapshot {
+ /// Creates a snapshot from a JSON value that represents a collection of
+ /// Relevancy Remote Settings records.
+ ///
+ /// You can use the [`serde_json::json!`] macro to construct the JSON
+ /// value, then pass it to this function. It's easier to use the
+ /// `Snapshot::with_records(json!(...))` idiom than to construct the
+ /// records by hand.
+ fn with_records(value: serde_json::Value) -> anyhow::Result<Self> {
+ Ok(Self {
+ records: serde_json::from_value(value)
+ .context("Couldn't create snapshot with Remote Settings records")?,
+ attachments: HashMap::new(),
+ })
+ }
+
+ /// Adds a data attachment to the snapshot.
+ fn with_data(
+ mut self,
+ location: &'static str,
+ value: serde_json::Value,
+ ) -> anyhow::Result<Self> {
+ self.attachments.insert(
+ location,
+ serde_json::to_vec(&value).context("Couldn't add data attachment to snapshot")?,
+ );
+ Ok(self)
+ }
+ }
+
+ /// A fake Remote Settings client that returns records and attachments from
+ /// a snapshot.
+ struct SnapshotSettingsClient {
+ /// The current snapshot. You can modify it using
+ /// [`RefCell::borrow_mut()`] to simulate remote updates in tests.
+ snapshot: RefCell<Snapshot>,
+ }
+
+ impl SnapshotSettingsClient {
+ /// Creates a client with an initial snapshot.
+ fn with_snapshot(snapshot: Snapshot) -> Self {
+ Self {
+ snapshot: RefCell::new(snapshot),
+ }
+ }
+ }
+
+ impl RelevancyRemoteSettingsClient for SnapshotSettingsClient {
+ fn get_records(&self) -> Result<RemoteSettingsResponse> {
+ let records = self.snapshot.borrow().records.clone();
+ let last_modified = records
+ .iter()
+ .map(|record: &RemoteSettingsRecord| record.last_modified)
+ .max()
+ .unwrap_or(0);
+ Ok(RemoteSettingsResponse {
+ records,
+ last_modified,
+ })
+ }
+
+ fn get_attachment(&self, location: &str) -> Result<Vec<u8>> {
+ Ok(self
+ .snapshot
+ .borrow()
+ .attachments
+ .get(location)
+ .unwrap_or_else(|| unreachable!("Unexpected request for attachment `{}`", location))
+ .clone())
+ }
+ }
+
+ #[test]
+ fn test_interest_vectors() {
+ let db = RelevancyDb::new_for_test();
+ db.read_write(|dao| {
+ // Test that the interest data matches the values we started from in
+ // `bin/generate-test-data.rs`
+
+ dao.add_url_interest(hash_url("https://espn.com").unwrap(), Interest::Sports)?;
+ dao.add_url_interest(hash_url("https://dogs.com").unwrap(), Interest::Animals)?;
+ dao.add_url_interest(hash_url("https://cars.com").unwrap(), Interest::Autos)?;
+ dao.add_url_interest(
+ hash_url("https://www.vouge.com").unwrap(),
+ Interest::Fashion,
+ )?;
+ dao.add_url_interest(hash_url("https://slashdot.org").unwrap(), Interest::Tech)?;
+ dao.add_url_interest(hash_url("https://www.nascar.com").unwrap(), Interest::Autos)?;
+ dao.add_url_interest(
+ hash_url("https://www.nascar.com").unwrap(),
+ Interest::Sports,
+ )?;
+ dao.add_url_interest(
+ hash_url("https://unknown.url").unwrap(),
+ Interest::Inconclusive,
+ )?;
+
+ assert_eq!(
+ dao.get_url_interest_vector("https://espn.com/").unwrap(),
+ InterestVector {
+ sports: 1,
+ ..InterestVector::default()
+ }
+ );
+ assert_eq!(
+ dao.get_url_interest_vector("https://dogs.com/").unwrap(),
+ InterestVector {
+ animals: 1,
+ ..InterestVector::default()
+ }
+ );
+ assert_eq!(
+ dao.get_url_interest_vector("https://cars.com/").unwrap(),
+ InterestVector {
+ autos: 1,
+ ..InterestVector::default()
+ }
+ );
+ assert_eq!(
+ dao.get_url_interest_vector("https://www.vouge.com/")
+ .unwrap(),
+ InterestVector {
+ fashion: 1,
+ ..InterestVector::default()
+ }
+ );
+ assert_eq!(
+ dao.get_url_interest_vector("https://slashdot.org/")
+ .unwrap(),
+ InterestVector {
+ tech: 1,
+ ..InterestVector::default()
+ }
+ );
+ assert_eq!(
+ dao.get_url_interest_vector("https://www.nascar.com/")
+ .unwrap(),
+ InterestVector {
+ autos: 1,
+ sports: 1,
+ ..InterestVector::default()
+ }
+ );
+ assert_eq!(
+ dao.get_url_interest_vector("https://unknown.url/").unwrap(),
+ InterestVector {
+ inconclusive: 1,
+ ..InterestVector::default()
+ }
+ );
+ Ok(())
+ })
+ .unwrap();
+ }
+
+ #[test]
+ fn test_variations_on_the_url() {
+ let db = RelevancyDb::new_for_test();
+ db.read_write(|dao| {
+ dao.add_url_interest(hash_url("https://espn.com").unwrap(), Interest::Sports)?;
+ dao.add_url_interest(hash_url("https://nascar.com").unwrap(), Interest::Autos)?;
+ dao.add_url_interest(hash_url("https://nascar.com").unwrap(), Interest::Sports)?;
+
+ // Different paths/queries should work
+ assert_eq!(
+ dao.get_url_interest_vector("https://espn.com/foo/bar/?baz")
+ .unwrap(),
+ InterestVector {
+ sports: 1,
+ ..InterestVector::default()
+ }
+ );
+ // Different schemes should too
+ assert_eq!(
+ dao.get_url_interest_vector("http://espn.com/").unwrap(),
+ InterestVector {
+ sports: 1,
+ ..InterestVector::default()
+ }
+ );
+ // But changes to the domain shouldn't
+ assert_eq!(
+ dao.get_url_interest_vector("http://espn2.com/").unwrap(),
+ InterestVector::default()
+ );
+ // However, extra components past the 2nd one in the domain are ignored
+ assert_eq!(
+ dao.get_url_interest_vector("https://www.nascar.com/")
+ .unwrap(),
+ InterestVector {
+ autos: 1,
+ sports: 1,
+ ..InterestVector::default()
+ }
+ );
+ Ok(())
+ })
+ .unwrap();
+ }
+
+ #[test]
+ fn test_parse_records() -> anyhow::Result<()> {
+ let snapshot = Snapshot::with_records(json!([{
+ "id": "animals-0001",
+ "last_modified": 15,
+ "type": "category_to_domains",
+ "attachment": {
+ "filename": "data-1.json",
+ "mimetype": "application/json",
+ "location": "data-1.json",
+ "hash": "",
+ "size": 0
+ },
+ "record_custom_details": {
+ "category_to_domains": {
+ "category": "animals",
+ "category_code": 1,
+ "version": 1
+ }
+ }
+ }]))?
+ .with_data(
+ "data-1.json",
+ json!([
+ {"domain": "J2jtyjQtYQ/+/p//xhz43Q=="},
+ {"domain": "Zd4awCwGZLkat59nIWje3g=="}]),
+ )?;
+ let rs_client = SnapshotSettingsClient::with_snapshot(snapshot);
+ assert_eq!(
+ fetch_interest_data_inner(rs_client).unwrap(),
+ vec![
+ (Interest::Animals, hash_url("https://dogs.com").unwrap()),
+ (Interest::Animals, hash_url("https://cats.com").unwrap())
+ ]
+ );
+
+ Ok(())
+ }
+
+ #[test]
+ fn test_parse_records_with_bad_domain_strings() -> anyhow::Result<()> {
+ let snapshot = Snapshot::with_records(json!([{
+ "id": "animals-0001",
+ "last_modified": 15,
+ "type": "category_to_domains",
+ "attachment": {
+ "filename": "data-1.json",
+ "mimetype": "application/json",
+ "location": "data-1.json",
+ "hash": "",
+ "size": 0
+ },
+ "record_custom_details": {
+ "category_to_domains": {
+ "category": "animals",
+ "category_code": 1,
+ "version": 1
+ }
+ }
+ }]))?
+ .with_data(
+ "data-1.json",
+ json!([
+ {"domain": "badString"},
+ {"domain": "notBase64"}]),
+ )?;
+ let rs_client = SnapshotSettingsClient::with_snapshot(snapshot);
+ fetch_interest_data_inner(rs_client).expect_err("Invalid base64 error");
+
+ Ok(())
+ }
+}
diff --git a/third_party/rust/relevancy/src/interest.rs b/third_party/rust/relevancy/src/interest.rs
index 0573c743fc..797df11236 100644
--- a/third_party/rust/relevancy/src/interest.rs
+++ b/third_party/rust/relevancy/src/interest.rs
@@ -2,32 +2,37 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use crate::Error;
+
/// List of possible interests for a domain. Domains can have be associated with one or multiple
/// interests. `Inconclusive` is used for domains in the user's top sites that we can't classify
/// because there's no corresponding entry in the interest database.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u32)]
pub enum Interest {
- Animals,
- Arts,
- Autos,
- Business,
- Career,
- Education,
- Fashion,
- Finance,
- Food,
- Government,
- Health,
- Hobbies,
- Home,
- News,
- RealEstate,
- Society,
- Sports,
- Tech,
- Travel,
- Inconclusive,
+ // Note: if you change these codes, make sure to update the `TryFrom<u32>` implementation and
+ // the `test_interest_code_conversion` test.
+ Inconclusive = 0,
+ Animals = 1,
+ Arts = 2,
+ Autos = 3,
+ Business = 4,
+ Career = 5,
+ Education = 6,
+ Fashion = 7,
+ Finance = 8,
+ Food = 9,
+ Government = 10,
+ //Disable this per policy consultation
+ // Health = 11,
+ Hobbies = 12,
+ Home = 13,
+ News = 14,
+ RealEstate = 15,
+ Society = 16,
+ Sports = 17,
+ Tech = 18,
+ Travel = 19,
}
impl From<Interest> for u32 {
@@ -42,22 +47,44 @@ impl From<Interest> for usize {
}
}
-impl From<u32> for Interest {
- fn from(code: u32) -> Self {
- if code as usize > Self::COUNT {
- panic!("Invalid interest code: {code}")
+impl TryFrom<u32> for Interest {
+ // On error, return the invalid code back
+ type Error = Error;
+
+ fn try_from(code: u32) -> Result<Self, Self::Error> {
+ match code {
+ 0 => Ok(Self::Inconclusive),
+ 1 => Ok(Self::Animals),
+ 2 => Ok(Self::Arts),
+ 3 => Ok(Self::Autos),
+ 4 => Ok(Self::Business),
+ 5 => Ok(Self::Career),
+ 6 => Ok(Self::Education),
+ 7 => Ok(Self::Fashion),
+ 8 => Ok(Self::Finance),
+ 9 => Ok(Self::Food),
+ 10 => Ok(Self::Government),
+ //Disable this per policy consultation
+ // 11 => Ok(Self::Health),
+ 12 => Ok(Self::Hobbies),
+ 13 => Ok(Self::Home),
+ 14 => Ok(Self::News),
+ 15 => Ok(Self::RealEstate),
+ 16 => Ok(Self::Society),
+ 17 => Ok(Self::Sports),
+ 18 => Ok(Self::Tech),
+ 19 => Ok(Self::Travel),
+ n => Err(Error::InvalidInterestCode(n)),
}
- // Safety: This is safe since Interest has a u32 representation and we've done a bounds
- // check
- unsafe { std::mem::transmute(code) }
}
}
impl Interest {
- const COUNT: usize = 20;
+ const COUNT: usize = 19;
pub fn all() -> [Interest; Self::COUNT] {
[
+ Self::Inconclusive,
Self::Animals,
Self::Arts,
Self::Autos,
@@ -68,7 +95,7 @@ impl Interest {
Self::Finance,
Self::Food,
Self::Government,
- Self::Health,
+ // Self::Health,
Self::Hobbies,
Self::Home,
Self::News,
@@ -77,7 +104,6 @@ impl Interest {
Self::Sports,
Self::Tech,
Self::Travel,
- Self::Inconclusive,
]
}
}
@@ -88,6 +114,7 @@ impl Interest {
/// number of elements.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct InterestVector {
+ pub inconclusive: u32,
pub animals: u32,
pub arts: u32,
pub autos: u32,
@@ -98,7 +125,7 @@ pub struct InterestVector {
pub finance: u32,
pub food: u32,
pub government: u32,
- pub health: u32,
+ // pub health: u32,
pub hobbies: u32,
pub home: u32,
pub news: u32,
@@ -107,7 +134,34 @@ pub struct InterestVector {
pub sports: u32,
pub tech: u32,
pub travel: u32,
- pub inconclusive: u32,
+}
+
+impl std::ops::Add for InterestVector {
+ type Output = Self;
+
+ fn add(self, other: Self) -> Self {
+ Self {
+ inconclusive: self.inconclusive + other.inconclusive,
+ animals: self.animals + other.animals,
+ arts: self.arts + other.arts,
+ autos: self.autos + other.autos,
+ business: self.business + other.business,
+ career: self.career + other.career,
+ education: self.education + other.education,
+ fashion: self.fashion + other.fashion,
+ finance: self.finance + other.finance,
+ food: self.food + other.food,
+ government: self.government + other.government,
+ hobbies: self.hobbies + other.hobbies,
+ home: self.home + other.home,
+ news: self.news + other.news,
+ real_estate: self.real_estate + other.real_estate,
+ society: self.society + other.society,
+ sports: self.sports + other.sports,
+ tech: self.tech + other.tech,
+ travel: self.travel + other.travel,
+ }
+ }
}
impl std::ops::Index<Interest> for InterestVector {
@@ -115,6 +169,7 @@ impl std::ops::Index<Interest> for InterestVector {
fn index(&self, index: Interest) -> &u32 {
match index {
+ Interest::Inconclusive => &self.inconclusive,
Interest::Animals => &self.animals,
Interest::Arts => &self.arts,
Interest::Autos => &self.autos,
@@ -125,7 +180,7 @@ impl std::ops::Index<Interest> for InterestVector {
Interest::Finance => &self.finance,
Interest::Food => &self.food,
Interest::Government => &self.government,
- Interest::Health => &self.health,
+ // Interest::Health => &self.health,
Interest::Hobbies => &self.hobbies,
Interest::Home => &self.home,
Interest::News => &self.news,
@@ -134,7 +189,6 @@ impl std::ops::Index<Interest> for InterestVector {
Interest::Sports => &self.sports,
Interest::Tech => &self.tech,
Interest::Travel => &self.travel,
- Interest::Inconclusive => &self.inconclusive,
}
}
}
@@ -142,6 +196,7 @@ impl std::ops::Index<Interest> for InterestVector {
impl std::ops::IndexMut<Interest> for InterestVector {
fn index_mut(&mut self, index: Interest) -> &mut u32 {
match index {
+ Interest::Inconclusive => &mut self.inconclusive,
Interest::Animals => &mut self.animals,
Interest::Arts => &mut self.arts,
Interest::Autos => &mut self.autos,
@@ -152,7 +207,7 @@ impl std::ops::IndexMut<Interest> for InterestVector {
Interest::Finance => &mut self.finance,
Interest::Food => &mut self.food,
Interest::Government => &mut self.government,
- Interest::Health => &mut self.health,
+ // Interest::Health => &mut self.health,
Interest::Hobbies => &mut self.hobbies,
Interest::Home => &mut self.home,
Interest::News => &mut self.news,
@@ -161,7 +216,32 @@ impl std::ops::IndexMut<Interest> for InterestVector {
Interest::Sports => &mut self.sports,
Interest::Tech => &mut self.tech,
Interest::Travel => &mut self.travel,
- Interest::Inconclusive => &mut self.inconclusive,
}
}
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_interest_code_conversion() {
+ for interest in Interest::all() {
+ assert_eq!(Interest::try_from(u32::from(interest)).unwrap(), interest)
+ }
+ // try_from() for out of bounds codes should return an error
+ assert!(matches!(
+ Interest::try_from(20),
+ Err(Error::InvalidInterestCode(20))
+ ));
+ assert!(matches!(
+ Interest::try_from(100),
+ Err(Error::InvalidInterestCode(100))
+ ));
+ // Health is currently disabled, so it's code should return None for now
+ assert!(matches!(
+ Interest::try_from(11),
+ Err(Error::InvalidInterestCode(11))
+ ));
+ }
+}
diff --git a/third_party/rust/relevancy/src/lib.rs b/third_party/rust/relevancy/src/lib.rs
index 157a26277e..4bc774a261 100644
--- a/third_party/rust/relevancy/src/lib.rs
+++ b/third_party/rust/relevancy/src/lib.rs
@@ -11,8 +11,9 @@
mod db;
mod error;
+mod ingest;
mod interest;
-mod populate_interests;
+mod rs;
mod schema;
pub mod url_hash;
@@ -28,11 +29,18 @@ pub struct RelevancyStore {
/// Top-level API for the Relevancy component
impl RelevancyStore {
- #[handle_error(Error)]
- pub fn new(db_path: String) -> ApiResult<Self> {
- Ok(Self {
- db: RelevancyDb::open(db_path)?,
- })
+ pub fn new(db_path: String) -> Self {
+ Self {
+ db: RelevancyDb::new(db_path),
+ }
+ }
+
+ pub fn close(&self) {
+ self.db.close()
+ }
+
+ pub fn interrupt(&self) {
+ self.db.interrupt()
}
/// Ingest top URLs to build the user's interest vector.
@@ -47,9 +55,21 @@ impl RelevancyStore {
///
/// This method may execute for a long time and should only be called from a worker thread.
#[handle_error(Error)]
- pub fn ingest(&self, _top_urls_by_frecency: Vec<String>) -> ApiResult<()> {
- populate_interests::ensure_interest_data_populated(&self.db)?;
- todo!()
+ pub fn ingest(&self, top_urls_by_frecency: Vec<String>) -> ApiResult<InterestVector> {
+ ingest::ensure_interest_data_populated(&self.db)?;
+ self.classify(top_urls_by_frecency)
+ }
+
+ pub fn classify(&self, top_urls_by_frecency: Vec<String>) -> Result<InterestVector> {
+ // For experimentation purposes we are going to return an interest vector.
+ // Eventually we would want to store this data in the DB and incrementally update it.
+ let mut interest_vector = InterestVector::default();
+ for url in top_urls_by_frecency {
+ let interest_count = self.db.read(|dao| dao.get_url_interest_vector(&url))?;
+ interest_vector = interest_vector + interest_count;
+ }
+
+ Ok(interest_vector)
}
/// Calculate metrics for the validation phase
@@ -79,3 +99,45 @@ pub struct InterestMetrics {
}
uniffi::include_scaffolding!("relevancy");
+
+#[cfg(test)]
+mod test {
+ use crate::url_hash::hash_url;
+
+ use super::*;
+
+ #[test]
+ fn test_ingest() {
+ let top_urls = vec![
+ "https://food.com/".to_string(),
+ "https://hello.com".to_string(),
+ "https://pasta.com".to_string(),
+ "https://dog.com".to_string(),
+ ];
+ let relevancy_store =
+ RelevancyStore::new("file:test_store_data?mode=memory&cache=shared".to_owned());
+ relevancy_store
+ .db
+ .read_write(|dao| {
+ dao.add_url_interest(hash_url("https://food.com").unwrap(), Interest::Food)?;
+ dao.add_url_interest(
+ hash_url("https://hello.com").unwrap(),
+ Interest::Inconclusive,
+ )?;
+ dao.add_url_interest(hash_url("https://pasta.com").unwrap(), Interest::Food)?;
+ dao.add_url_interest(hash_url("https://dog.com").unwrap(), Interest::Animals)?;
+ Ok(())
+ })
+ .expect("Insert should succeed");
+
+ assert_eq!(
+ relevancy_store.ingest(top_urls).unwrap(),
+ InterestVector {
+ inconclusive: 1,
+ animals: 1,
+ food: 2,
+ ..InterestVector::default()
+ }
+ );
+ }
+}
diff --git a/third_party/rust/relevancy/src/populate_interests.rs b/third_party/rust/relevancy/src/populate_interests.rs
deleted file mode 100644
index e33b677dd6..0000000000
--- a/third_party/rust/relevancy/src/populate_interests.rs
+++ /dev/null
@@ -1,157 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use crate::{url_hash::UrlHash, Error, Interest, RelevancyDb, Result};
-use std::io::{Cursor, Read};
-
-pub fn ensure_interest_data_populated(db: &RelevancyDb) -> Result<()> {
- if !db.read(|dao| dao.need_to_load_url_interests())? {
- return Ok(());
- }
- let interest_data = match fetch_interest_data() {
- Ok(data) => data,
- Err(e) => {
- log::warn!("error fetching interest data: {e}");
- return Err(Error::FetchInterestDataError);
- }
- };
- db.read_write(move |dao| {
- for (url_hash, interest) in interest_data {
- dao.add_url_interest(url_hash, interest)?;
- }
- Ok(())
- })
-}
-
-/// Fetch the interest data
-fn fetch_interest_data() -> std::io::Result<Vec<(UrlHash, Interest)>> {
- // TODO: this hack should be replaced with something that fetches from remote settings
- let bytes = include_bytes!("../test-data");
- let mut reader = Cursor::new(&bytes);
- let mut data = vec![];
-
- // Loop over all possible interests
- for interest in Interest::all() {
- // read the count
- let mut buf = [0u8; 4];
- reader.read_exact(&mut buf)?;
- let count = u32::from_le_bytes(buf);
- for _ in 0..count {
- let mut url_hash: UrlHash = [0u8; 16];
- reader.read_exact(&mut url_hash)?;
- data.push((url_hash, interest));
- }
- }
- Ok(data)
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use crate::InterestVector;
-
- #[test]
- fn test_interest_vectors() {
- let db = RelevancyDb::open_for_test();
- ensure_interest_data_populated(&db).unwrap();
- db.read(|dao| {
- // Test that the interest data matches the values we started from in
- // `bin/generate-test-data.rs`
- assert_eq!(
- dao.get_url_interest_vector("https://espn.com/").unwrap(),
- InterestVector {
- sports: 1,
- ..InterestVector::default()
- }
- );
- assert_eq!(
- dao.get_url_interest_vector("https://dogs.com/").unwrap(),
- InterestVector {
- animals: 1,
- ..InterestVector::default()
- }
- );
- assert_eq!(
- dao.get_url_interest_vector("https://cars.com/").unwrap(),
- InterestVector {
- autos: 1,
- ..InterestVector::default()
- }
- );
- assert_eq!(
- dao.get_url_interest_vector("https://www.vouge.com/")
- .unwrap(),
- InterestVector {
- fashion: 1,
- ..InterestVector::default()
- }
- );
- assert_eq!(
- dao.get_url_interest_vector("https://slashdot.org/")
- .unwrap(),
- InterestVector {
- tech: 1,
- ..InterestVector::default()
- }
- );
- assert_eq!(
- dao.get_url_interest_vector("https://www.nascar.com/")
- .unwrap(),
- InterestVector {
- autos: 1,
- sports: 1,
- ..InterestVector::default()
- }
- );
- assert_eq!(
- dao.get_url_interest_vector("https://unknown.url/").unwrap(),
- InterestVector::default()
- );
- Ok(())
- })
- .unwrap();
- }
-
- #[test]
- fn test_variations_on_the_url() {
- let db = RelevancyDb::open_for_test();
- ensure_interest_data_populated(&db).unwrap();
- db.read(|dao| {
- // Different paths/queries should work
- assert_eq!(
- dao.get_url_interest_vector("https://espn.com/foo/bar/?baz")
- .unwrap(),
- InterestVector {
- sports: 1,
- ..InterestVector::default()
- }
- );
- // Different schemes should too
- assert_eq!(
- dao.get_url_interest_vector("http://espn.com/").unwrap(),
- InterestVector {
- sports: 1,
- ..InterestVector::default()
- }
- );
- // But changes to the domain shouldn't
- assert_eq!(
- dao.get_url_interest_vector("http://www.espn.com/").unwrap(),
- InterestVector::default()
- );
- // However, extra components past the 3rd one in the domain are ignored
- assert_eq!(
- dao.get_url_interest_vector("https://foo.www.nascar.com/")
- .unwrap(),
- InterestVector {
- autos: 1,
- sports: 1,
- ..InterestVector::default()
- }
- );
- Ok(())
- })
- .unwrap();
- }
-}
diff --git a/third_party/rust/relevancy/src/relevancy.udl b/third_party/rust/relevancy/src/relevancy.udl
index e07243ec28..ba9eb09969 100644
--- a/third_party/rust/relevancy/src/relevancy.udl
+++ b/third_party/rust/relevancy/src/relevancy.udl
@@ -8,12 +8,21 @@ interface RelevancyApiError {
// Top-level class for the Relevancy component
interface RelevancyStore {
// Construct a new RelevancyStore
- [Throws=RelevancyApiError]
+ //
+ // This is non-blocking since databases and other resources are lazily opened.
constructor(string dbpath);
+ // Close any open resources (for example databases)
+ //
+ // Calling `close` will interrupt any in-progress queries on other threads.
+ void close();
+
+ // Interrupt any current database queries
+ void interrupt();
+
// Ingest the top URLs by frequency to build up the user's interest vector
[Throws=RelevancyApiError]
- void ingest(sequence<string> top_urls);
+ InterestVector ingest(sequence<string> top_urls);
// Calculate metrics for the user's interest vector in order to measure how strongly we're
// identifying interests. See the `InterestMetrics` struct for details.
@@ -39,7 +48,7 @@ enum Interest {
"Finance",
"Food",
"Government",
- "Health",
+ // "Health",
"Hobbies",
"Home",
"News",
@@ -93,7 +102,7 @@ dictionary InterestVector {
u32 finance;
u32 food;
u32 government;
- u32 health;
+ // u32 health;
u32 hobbies;
u32 home;
u32 news;
diff --git a/third_party/rust/relevancy/src/rs.rs b/third_party/rust/relevancy/src/rs.rs
new file mode 100644
index 0000000000..bc8cc938e8
--- /dev/null
+++ b/third_party/rust/relevancy/src/rs.rs
@@ -0,0 +1,60 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+use crate::Result;
+use remote_settings::RemoteSettingsResponse;
+use serde::Deserialize;
+/// The Remote Settings collection name.
+pub(crate) const REMOTE_SETTINGS_COLLECTION: &str = "content-relevance";
+
+/// A trait for a client that downloads records from Remote Settings.
+///
+/// This trait lets tests use a mock client.
+pub(crate) trait RelevancyRemoteSettingsClient {
+ /// Fetches records from the Suggest Remote Settings collection.
+ fn get_records(&self) -> Result<RemoteSettingsResponse>;
+
+ /// Fetches a record's attachment from the Suggest Remote Settings
+ /// collection.
+ fn get_attachment(&self, location: &str) -> Result<Vec<u8>>;
+}
+
+impl RelevancyRemoteSettingsClient for remote_settings::Client {
+ fn get_records(&self) -> Result<RemoteSettingsResponse> {
+ Ok(remote_settings::Client::get_records(self)?)
+ }
+
+ fn get_attachment(&self, location: &str) -> Result<Vec<u8>> {
+ Ok(remote_settings::Client::get_attachment(self, location)?)
+ }
+}
+
+/// A record in the Relevancy Remote Settings collection.
+#[derive(Clone, Debug, Deserialize)]
+pub struct RelevancyRecord {
+ #[serde(rename = "type")]
+ pub record_type: String,
+ pub record_custom_details: RecordCustomDetails,
+}
+
+// Custom details related to category of the record.
+#[derive(Clone, Debug, Deserialize)]
+pub struct RecordCustomDetails {
+ pub category_to_domains: CategoryToDomains,
+}
+
+/// Category information related to the record.
+#[derive(Clone, Debug, Deserialize)]
+pub struct CategoryToDomains {
+ pub version: i32,
+ pub category: String,
+ pub category_code: i32,
+}
+
+/// A downloaded Remote Settings attachment that contains domain data.
+#[derive(Clone, Debug, Deserialize)]
+pub struct RelevancyAttachmentData {
+ pub domain: String,
+}
diff --git a/third_party/rust/relevancy/src/url_hash.rs b/third_party/rust/relevancy/src/url_hash.rs
index d31a45d06b..c010dcaf12 100644
--- a/third_party/rust/relevancy/src/url_hash.rs
+++ b/third_party/rust/relevancy/src/url_hash.rs
@@ -8,11 +8,10 @@ use url::{Host, Url};
pub type UrlHash = [u8; 16];
/// Given a URL, extract the part of it that we want to use to identify it.
-///
-/// We currently use the final 3 components of the URL domain.
-///
-/// TODO: decide if this should be 3 or 3 components.
pub fn url_hash_source(url: &str) -> Option<String> {
+ // We currently use the final 2 components of the URL domain.
+ const URL_COMPONENTS_TO_USE: usize = 2;
+
let url = Url::parse(url).ok()?;
let domain = match url.host() {
Some(Host::Domain(d)) => d,
@@ -20,7 +19,7 @@ pub fn url_hash_source(url: &str) -> Option<String> {
};
// This will store indexes of `.` chars as we search backwards.
let mut pos = domain.len();
- for _ in 0..3 {
+ for _ in 0..URL_COMPONENTS_TO_USE {
match domain[0..pos].rfind('.') {
Some(p) => pos = p,
// The domain has less than 3 dots, return it all
@@ -47,12 +46,12 @@ mod test {
fn test_url_hash_source() {
let table = [
("http://example.com/some-path", Some("example.com")),
- ("http://foo.example.com/some-path", Some("foo.example.com")),
+ ("http://foo.example.com/some-path", Some("example.com")),
(
"http://foo.bar.baz.example.com/some-path",
- Some("baz.example.com"),
+ Some("example.com"),
),
- ("http://foo.com.uk/some-path", Some("foo.com.uk")),
+ ("http://foo.com.uk/some-path", Some("com.uk")),
("http://amazon.com/some-path", Some("amazon.com")),
("http://192.168.0.1/some-path", None),
];
diff --git a/third_party/rust/relevancy/test-data b/third_party/rust/relevancy/test-data
index c645914143..46fd850189 100644
--- a/third_party/rust/relevancy/test-data
+++ b/third_party/rust/relevancy/test-data
Binary files differ
diff --git a/third_party/rust/remote_settings/.cargo-checksum.json b/third_party/rust/remote_settings/.cargo-checksum.json
index 619a9d13ca..96d0e51acd 100644
--- a/third_party/rust/remote_settings/.cargo-checksum.json
+++ b/third_party/rust/remote_settings/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"1029f571c66d33c4dfc5e9fc55287a780329ce183f5d2b672de79737155c4227","build.rs":"4326f03729cf8f1673e4228e6dc111de1ea4d8bcc06351f7ae563efb2613f866","src/client.rs":"7510ae0d5bcb9fbaa2c43c4773aa0fd518edc78fe0f396c0e1d6dd442446f429","src/config.rs":"7bb678addfae3b4ed5f2892d32263e5b33cc05e5a12a250f664150e78211f94a","src/error.rs":"192ca42af7c6b882f3129378c23b45dab8a0d2b179e23a8813a335ffd56b21dc","src/lib.rs":"416e99894e152f6cea7418ad2fabfd94bc3d907efd9f33fbd2a83fb99452b2df","src/remote_settings.udl":"2e71491ad3894d17e5bde0663d9490bfea6294d99cdbe9d67a36137faeedc593","uniffi.toml":"f8ec8dc593e0d501c2e9e40368ec93ec33b1edd8608e29495e0a54b63144e880"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"1029f571c66d33c4dfc5e9fc55287a780329ce183f5d2b672de79737155c4227","build.rs":"4326f03729cf8f1673e4228e6dc111de1ea4d8bcc06351f7ae563efb2613f866","src/client.rs":"666ef6536a81b107cdd6047b56ffb53a052c0a615b1fa827e630892c0e528a5d","src/config.rs":"52a209256acd8b1fada2b91e9d9f669df0ee6e9609baad7ec34a2111ed2a6541","src/error.rs":"b0cb36fb105d7ae8a2d8c2e5f98f410c106f1fd45c2e3e9bd8e865c0d2eb8726","src/lib.rs":"655559b1b0f09ad221ceba462ace73d9216a6551d70062126ffc8a085d8b89bb","src/remote_settings.udl":"1ffeb10385e4db63606cda79bb59e77170af1d2ca0028da8ab2c4d7622969734","uniffi.toml":"f8ec8dc593e0d501c2e9e40368ec93ec33b1edd8608e29495e0a54b63144e880"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/remote_settings/src/client.rs b/third_party/rust/remote_settings/src/client.rs
index 2cf26b7319..601b5c451a 100644
--- a/third_party/rust/remote_settings/src/client.rs
+++ b/third_party/rust/remote_settings/src/client.rs
@@ -4,7 +4,7 @@
use crate::config::RemoteSettingsConfig;
use crate::error::{RemoteSettingsError, Result};
-use crate::UniffiCustomTypeConverter;
+use crate::{RemoteSettingsServer, UniffiCustomTypeConverter};
use parking_lot::Mutex;
use serde::Deserialize;
use std::{
@@ -31,11 +31,17 @@ pub struct Client {
impl Client {
/// Create a new [Client] with properties matching config.
pub fn new(config: RemoteSettingsConfig) -> Result<Self> {
- let server_url = config
- .server_url
- .unwrap_or_else(|| String::from("https://firefox.settings.services.mozilla.com"));
+ let server = match (config.server, config.server_url) {
+ (Some(server), None) => server,
+ (None, Some(server_url)) => RemoteSettingsServer::Custom { url: server_url },
+ (None, None) => RemoteSettingsServer::Prod,
+ (Some(_), Some(_)) => Err(RemoteSettingsError::ConfigError(
+ "`RemoteSettingsConfig` takes either `server` or `server_url`, not both".into(),
+ ))?,
+ };
+
let bucket_name = config.bucket_name.unwrap_or_else(|| String::from("main"));
- let base_url = Url::parse(&server_url)?;
+ let base_url = server.url()?;
Ok(Self {
base_url,
@@ -519,6 +525,7 @@ mod test {
#[test]
fn test_defaults() {
let config = RemoteSettingsConfig {
+ server: None,
server_url: None,
bucket_name: None,
collection_name: String::from("the-collection"),
@@ -532,6 +539,33 @@ mod test {
}
#[test]
+ fn test_deprecated_server_url() {
+ let config = RemoteSettingsConfig {
+ server: None,
+ server_url: Some("https://example.com".into()),
+ bucket_name: None,
+ collection_name: String::from("the-collection"),
+ };
+ let client = Client::new(config).unwrap();
+ assert_eq!(Url::parse("https://example.com").unwrap(), client.base_url);
+ }
+
+ #[test]
+ fn test_invalid_config() {
+ let config = RemoteSettingsConfig {
+ server: Some(RemoteSettingsServer::Prod),
+ server_url: Some("https://example.com".into()),
+ bucket_name: None,
+ collection_name: String::from("the-collection"),
+ };
+ match Client::new(config) {
+ Ok(_) => panic!("Wanted config error; got client"),
+ Err(RemoteSettingsError::ConfigError(_)) => {}
+ Err(err) => panic!("Wanted config error; got {}", err),
+ }
+ }
+
+ #[test]
fn test_attachment_can_be_downloaded() {
viaduct_reqwest::use_reqwest_backend();
let server_info_m = mock("GET", "/")
@@ -552,7 +586,10 @@ mod test {
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
collection_name: String::from("the-collection"),
bucket_name: None,
};
@@ -588,7 +625,10 @@ mod test {
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
collection_name: String::from("the-collection"),
bucket_name: None,
};
@@ -617,7 +657,10 @@ mod test {
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
collection_name: String::from("the-collection"),
bucket_name: Some(String::from("the-bucket")),
};
@@ -644,7 +687,10 @@ mod test {
.with_header("Retry-After", "60")
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
collection_name: String::from("the-collection"),
bucket_name: Some(String::from("the-bucket")),
};
@@ -686,7 +732,10 @@ mod test {
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
collection_name: String::from("the-collection"),
bucket_name: Some(String::from("the-bucket")),
};
@@ -810,7 +859,10 @@ mod test {
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
collection_name: String::from("the-collection"),
bucket_name: Some(String::from("the-bucket")),
};
@@ -850,7 +902,10 @@ mod test {
.with_header("etag", "\"1000\"")
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
collection_name: String::from("the-collection"),
bucket_name: Some(String::from("the-bucket")),
};
@@ -953,7 +1008,10 @@ mod test {
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
bucket_name: Some(String::from("the-bucket")),
collection_name: String::from("the-collection"),
};
@@ -982,7 +1040,10 @@ mod test {
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
bucket_name: Some(String::from("the-bucket")),
collection_name: String::from("the-collection"),
};
diff --git a/third_party/rust/remote_settings/src/config.rs b/third_party/rust/remote_settings/src/config.rs
index 33fab1b500..d9051d06d0 100644
--- a/third_party/rust/remote_settings/src/config.rs
+++ b/third_party/rust/remote_settings/src/config.rs
@@ -3,19 +3,45 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! This module defines the custom configurations that consumers can set.
-//! Those configurations override default values and can be used to set a custom server url,
+//! Those configurations override default values and can be used to set a custom server,
//! collection name, and bucket name.
//! The purpose of the configuration parameters are to allow consumers an easy debugging option,
//! and the ability to be explicit about the server.
+use url::Url;
+
+use crate::Result;
+
/// Custom configuration for the client.
/// Currently includes the following:
-/// - `server_url`: The optional url for the settings server. If not specified, the standard server will be used.
+/// - `server`: The Remote Settings server to use. If not specified, defaults to the production server (`RemoteSettingsServer::Prod`).
+/// - `server_url`: An optional custom Remote Settings server URL. Deprecated; please use `server` instead.
/// - `bucket_name`: The optional name of the bucket containing the collection on the server. If not specified, the standard bucket will be used.
/// - `collection_name`: The name of the collection for the settings server.
#[derive(Debug, Clone)]
pub struct RemoteSettingsConfig {
+ pub server: Option<RemoteSettingsServer>,
pub server_url: Option<String>,
pub bucket_name: Option<String>,
pub collection_name: String,
}
+
+/// The Remote Settings server that the client should use.
+#[derive(Debug, Clone)]
+pub enum RemoteSettingsServer {
+ Prod,
+ Stage,
+ Dev,
+ Custom { url: String },
+}
+
+impl RemoteSettingsServer {
+ pub fn url(&self) -> Result<Url> {
+ Ok(match self {
+ Self::Prod => Url::parse("https://firefox.settings.services.mozilla.com").unwrap(),
+ Self::Stage => Url::parse("https://firefox.settings.services.allizom.org").unwrap(),
+ Self::Dev => Url::parse("https://remote-settings-dev.allizom.org").unwrap(),
+ Self::Custom { url } => Url::parse(url)?,
+ })
+ }
+}
diff --git a/third_party/rust/remote_settings/src/error.rs b/third_party/rust/remote_settings/src/error.rs
index 120681871b..32563800f0 100644
--- a/third_party/rust/remote_settings/src/error.rs
+++ b/third_party/rust/remote_settings/src/error.rs
@@ -22,6 +22,8 @@ pub enum RemoteSettingsError {
ResponseError(String),
#[error("This server doesn't support attachments")]
AttachmentsUnsupportedError,
+ #[error("Error configuring client: {0}")]
+ ConfigError(String),
}
pub type Result<T, E = RemoteSettingsError> = std::result::Result<T, E>;
diff --git a/third_party/rust/remote_settings/src/lib.rs b/third_party/rust/remote_settings/src/lib.rs
index 9aa6ecbf1a..9380a3fbc7 100644
--- a/third_party/rust/remote_settings/src/lib.rs
+++ b/third_party/rust/remote_settings/src/lib.rs
@@ -11,7 +11,7 @@ pub use client::{
RsJsonObject, SortOrder,
};
pub mod config;
-pub use config::RemoteSettingsConfig;
+pub use config::{RemoteSettingsConfig, RemoteSettingsServer};
uniffi::include_scaffolding!("remote_settings");
@@ -70,7 +70,10 @@ mod test {
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
bucket_name: Some(String::from("the-bucket")),
collection_name: String::from("the-collection"),
};
@@ -98,7 +101,10 @@ mod test {
.create();
let config = RemoteSettingsConfig {
- server_url: Some(mockito::server_url()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: mockito::server_url(),
+ }),
+ server_url: None,
bucket_name: Some(String::from("the-bucket")),
collection_name: String::from("the-collection"),
};
@@ -119,7 +125,10 @@ mod test {
fn test_download() {
viaduct_reqwest::use_reqwest_backend();
let config = RemoteSettingsConfig {
- server_url: Some("http://localhost:8888".to_string()),
+ server: Some(RemoteSettingsServer::Custom {
+ url: "http://localhost:8888".into(),
+ }),
+ server_url: None,
bucket_name: Some(String::from("the-bucket")),
collection_name: String::from("the-collection"),
};
diff --git a/third_party/rust/remote_settings/src/remote_settings.udl b/third_party/rust/remote_settings/src/remote_settings.udl
index d830b6778f..1da52b833e 100644
--- a/third_party/rust/remote_settings/src/remote_settings.udl
+++ b/third_party/rust/remote_settings/src/remote_settings.udl
@@ -7,10 +7,19 @@ typedef string RsJsonObject;
namespace remote_settings {};
+[Enum]
+interface RemoteSettingsServer {
+ Prod();
+ Stage();
+ Dev();
+ Custom(string url);
+};
+
dictionary RemoteSettingsConfig {
string collection_name;
string? bucket_name = null;
string? server_url = null;
+ RemoteSettingsServer? server = null;
};
dictionary RemoteSettingsResponse {
@@ -43,6 +52,7 @@ enum RemoteSettingsError {
"BackoffError",
"ResponseError",
"AttachmentsUnsupportedError",
+ "ConfigError",
};
interface RemoteSettings {
diff --git a/third_party/rust/serde/.cargo-checksum.json b/third_party/rust/serde/.cargo-checksum.json
index d55068bd63..65bca8af82 100644
--- a/third_party/rust/serde/.cargo-checksum.json
+++ b/third_party/rust/serde/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"f03b626efae73a6dd42f07d722dad2da3a4add51f4e653e30a6d696853bab209","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","build.rs":"f9ba30324b9ce085c903595fb55a5293f8c2348ff36bfe870521b935ae6d105c","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/de/format.rs":"c85071b016df643b161859682d21ce34fa0ebf2a3bdbeeea69859da48f5d934f","src/de/ignored_any.rs":"6480f2b2a83dc4764d01b2eec7309729eef2492eede2e5ee98d23a60b05198eb","src/de/impls.rs":"2857d734176a0b78a41c9358354b0b0b83c6b2d948590be072d98606a8cae9d6","src/de/mod.rs":"fc34da49f692803d2c2f131322d9b48ad8e4f39ed10b2b304d6193ab09d621fb","src/de/seed.rs":"045d890712a04eb33ffc5a021e5d948a63c89402b8ffeea749df2171b7484f8f","src/de/size_hint.rs":"fff83dc39d30e75e8e611991f9c5399188a1aad23a6462dbca2c8b62655cfedb","src/de/value.rs":"0fd511a288c20a1b768718f4baadf9c7d4146d276af6a71ba1d0f7679b28644a","src/integer128.rs":"29ef30b7d94507b34807090e68173767cdc7aff62edccd38affe69e75338dddc","src/lib.rs":"638b231a280519f1861ea5f1bfbe97e2394b2f7662a9701b8e57ed95093dd298","src/macros.rs":"e3486ef4a9a4ed1b27234aa1817ccb25ec0eb026ffc95e2c71c7b917f1f45629","src/private/de.rs":"6557a124fdaf61f9c7cd80163e40f4a453354e45b63a4eb55dafdfe0159f6881","src/private/doc.rs":"9ad740e9ea2eedf861b77116eda9a6fb74bc8553541cd17d1bc5791a3ef3271a","src/private/mod.rs":"b8f0c348621d91dd9da3db83d8877e70bc61ad0a2dc2d6fb57c6fc2c2cbafa26","src/private/ser.rs":"656613691bd8d40cb70a52d4ebe3ee96a993c8a1292d50822d9ca5bdad84426b","src/ser/fmt.rs":"77a5583e5c227ea1982b097ed6378af5c899d43761d71e33440262fd35944695","src/ser/impls.rs":"850619164b399c37cd373d24f5a2c83453f40b34bb978c5722d2c1ae226775b5","src/ser/impossible.rs":"e11b37689ec1395378d546fce74221ca9046d0761744301f12029102fd07e30e","src/ser/mod.rs":"a7fd082203d63cbe4f0fe86d9be16bf4f3b2444653dac6bb61d82e0f4f6b4214","src/std_error.rs":"25a07149e2e468747ffa5a58051c7f93d7b3c0fa0372f012a96c97ec8ab03b97"},"package":"3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"} \ No newline at end of file
+{"files":{"Cargo.toml":"fcf211f4e710da1375e944a42621a8cd3de8d683db3e464ab570652216015d87","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","build.rs":"56b4f43d4061c03fbdd4f6325f30439686b12679bace304223d30c03632a925e","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/de/format.rs":"c85071b016df643b161859682d21ce34fa0ebf2a3bdbeeea69859da48f5d934f","src/de/ignored_any.rs":"6480f2b2a83dc4764d01b2eec7309729eef2492eede2e5ee98d23a60b05198eb","src/de/impls.rs":"cd2781405d8f4568701a701e6b9946e5956eb201571118c8a49038928477779a","src/de/mod.rs":"2be26b699feb8cc0c7f573d58fc11bb92d0b7bd1063bf8fcbd0e71d60f53c99a","src/de/seed.rs":"045d890712a04eb33ffc5a021e5d948a63c89402b8ffeea749df2171b7484f8f","src/de/size_hint.rs":"fff83dc39d30e75e8e611991f9c5399188a1aad23a6462dbca2c8b62655cfedb","src/de/value.rs":"0fd511a288c20a1b768718f4baadf9c7d4146d276af6a71ba1d0f7679b28644a","src/integer128.rs":"29ef30b7d94507b34807090e68173767cdc7aff62edccd38affe69e75338dddc","src/lib.rs":"0e4c06f18a0f2e46d60f54f463e906bf1ba1330ef9820a12173fd28a91b9fcde","src/macros.rs":"e3486ef4a9a4ed1b27234aa1817ccb25ec0eb026ffc95e2c71c7b917f1f45629","src/private/de.rs":"9255ecf2d5c52f0f52b4e0dbf85bdd8c140bc2c1ac96086ee395589e0521aeb4","src/private/doc.rs":"b222decb40321190155209e1b8a5a52e3adfaa470047e379e664b71e0320655a","src/private/mod.rs":"b8f0c348621d91dd9da3db83d8877e70bc61ad0a2dc2d6fb57c6fc2c2cbafa26","src/private/ser.rs":"73577607e779e1b42713c51b9bc7136f99daccf473b4a641c99ceebe46708d47","src/ser/fmt.rs":"d1cfd9623605413e45a23ef778d97f0ac4da4adaed23739f1f9d7414b30e384b","src/ser/impls.rs":"0eebc159f7d3962c46c323e456afb679747ff57563e796c5fd92c64ed074ae70","src/ser/impossible.rs":"5c325da8e0370ab22abe1e15d8af1dc7a1707b127508f61e720cd7f0caa80593","src/ser/mod.rs":"a92d4ce0a6c68eb22a24a61574a5d2e9b0b463b284ff08e62298b8f7ae1a7464","src/std_error.rs":"25a07149e2e468747ffa5a58051c7f93d7b3c0fa0372f012a96c97ec8ab03b97"},"package":"9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"} \ No newline at end of file
diff --git a/third_party/rust/serde/Cargo.toml b/third_party/rust/serde/Cargo.toml
index 6ba68688ac..b6f335bafd 100644
--- a/third_party/rust/serde/Cargo.toml
+++ b/third_party/rust/serde/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "serde"
-version = "1.0.197"
+version = "1.0.198"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -74,4 +74,4 @@ std = []
unstable = []
[target."cfg(any())".dependencies.serde_derive]
-version = "=1.0.197"
+version = "=1.0.198"
diff --git a/third_party/rust/serde/build.rs b/third_party/rust/serde/build.rs
index fe5486a7a5..0074df63f4 100644
--- a/third_party/rust/serde/build.rs
+++ b/third_party/rust/serde/build.rs
@@ -64,6 +64,12 @@ fn main() {
if minor < 64 {
println!("cargo:rustc-cfg=no_core_cstr");
}
+
+ // Support for core::num::Saturating and std::num::Saturating stabilized in Rust 1.74
+ // https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html#stabilized-apis
+ if minor < 74 {
+ println!("cargo:rustc-cfg=no_core_num_saturating");
+ }
}
fn rustc_minor_version() -> Option<u32> {
diff --git a/third_party/rust/serde/src/de/impls.rs b/third_party/rust/serde/src/de/impls.rs
index 413c997afd..140878aec6 100644
--- a/third_party/rust/serde/src/de/impls.rs
+++ b/third_party/rust/serde/src/de/impls.rs
@@ -104,6 +104,28 @@ macro_rules! impl_deserialize_num {
deserializer.$deserialize(NonZeroVisitor)
}
}
+
+ #[cfg(not(no_core_num_saturating))]
+ impl<'de> Deserialize<'de> for Saturating<$primitive> {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct SaturatingVisitor;
+
+ impl<'de> Visitor<'de> for SaturatingVisitor {
+ type Value = Saturating<$primitive>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("integer with support for saturating semantics")
+ }
+
+ $($($method!(saturating $primitive $val : $visit);)*)*
+ }
+
+ deserializer.$deserialize(SaturatingVisitor)
+ }
+ }
};
($primitive:ident, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => {
@@ -154,6 +176,15 @@ macro_rules! num_self {
}
}
};
+
+ (saturating $primitive:ident $ty:ident : $visit:ident) => {
+ fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ Ok(Saturating(v))
+ }
+ };
}
macro_rules! num_as_self {
@@ -179,6 +210,15 @@ macro_rules! num_as_self {
}
}
};
+
+ (saturating $primitive:ident $ty:ident : $visit:ident) => {
+ fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ Ok(Saturating(v as $primitive))
+ }
+ };
}
macro_rules! num_as_copysign_self {
@@ -235,6 +275,21 @@ macro_rules! int_to_int {
Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
}
};
+
+ (saturating $primitive:ident $ty:ident : $visit:ident) => {
+ fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ if (v as i64) < $primitive::MIN as i64 {
+ Ok(Saturating($primitive::MIN))
+ } else if ($primitive::MAX as i64) < v as i64 {
+ Ok(Saturating($primitive::MAX))
+ } else {
+ Ok(Saturating(v as $primitive))
+ }
+ }
+ };
}
macro_rules! int_to_uint {
@@ -265,6 +320,21 @@ macro_rules! int_to_uint {
Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
}
};
+
+ (saturating $primitive:ident $ty:ident : $visit:ident) => {
+ fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ if v < 0 {
+ Ok(Saturating(0))
+ } else if ($primitive::MAX as u64) < v as u64 {
+ Ok(Saturating($primitive::MAX))
+ } else {
+ Ok(Saturating(v as $primitive))
+ }
+ }
+ };
}
macro_rules! uint_to_self {
@@ -295,6 +365,19 @@ macro_rules! uint_to_self {
Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self))
}
};
+
+ (saturating $primitive:ident $ty:ident : $visit:ident) => {
+ fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ if v as u64 <= $primitive::MAX as u64 {
+ Ok(Saturating(v as $primitive))
+ } else {
+ Ok(Saturating($primitive::MAX))
+ }
+ }
+ };
}
impl_deserialize_num! {
@@ -427,6 +510,21 @@ macro_rules! num_128 {
}
}
};
+
+ (saturating $primitive:ident $ty:ident : $visit:ident) => {
+ fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ if (v as i128) < $primitive::MIN as i128 {
+ Ok(Saturating($primitive::MIN))
+ } else if ($primitive::MAX as u128) < v as u128 {
+ Ok(Saturating($primitive::MAX))
+ } else {
+ Ok(Saturating(v as $primitive))
+ }
+ }
+ };
}
impl_deserialize_num! {
@@ -852,7 +950,10 @@ struct PhantomDataVisitor<T: ?Sized> {
marker: PhantomData<T>,
}
-impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
+impl<'de, T> Visitor<'de> for PhantomDataVisitor<T>
+where
+ T: ?Sized,
+{
type Value = PhantomData<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
@@ -868,7 +969,10 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
}
}
-impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
+impl<'de, T> Deserialize<'de> for PhantomData<T>
+where
+ T: ?Sized,
+{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
@@ -1877,9 +1981,9 @@ forwarded_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
-impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
+impl<'de, 'a, T> Deserialize<'de> for Cow<'a, T>
where
- T: ToOwned,
+ T: ?Sized + ToOwned,
T::Owned: Deserialize<'de>,
{
#[inline]
@@ -1902,7 +2006,7 @@ where
doc_cfg,
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
)]
-impl<'de, T: ?Sized> Deserialize<'de> for RcWeak<T>
+impl<'de, T> Deserialize<'de> for RcWeak<T>
where
T: Deserialize<'de>,
{
@@ -1924,7 +2028,7 @@ where
doc_cfg,
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
)]
-impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak<T>
+impl<'de, T> Deserialize<'de> for ArcWeak<T>
where
T: Deserialize<'de>,
{
@@ -1945,8 +2049,9 @@ macro_rules! box_forwarded_impl {
$t:ident
) => {
$(#[$attr])*
- impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
+ impl<'de, T> Deserialize<'de> for $t<T>
where
+ T: ?Sized,
Box<T>: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
diff --git a/third_party/rust/serde/src/de/mod.rs b/third_party/rust/serde/src/de/mod.rs
index 1924fe3d88..4c5a5f9b78 100644
--- a/third_party/rust/serde/src/de/mod.rs
+++ b/third_party/rust/serde/src/de/mod.rs
@@ -1735,9 +1735,9 @@ pub trait SeqAccess<'de> {
}
}
-impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A
+impl<'de, 'a, A> SeqAccess<'de> for &'a mut A
where
- A: SeqAccess<'de>,
+ A: ?Sized + SeqAccess<'de>,
{
type Error = A::Error;
@@ -1888,9 +1888,9 @@ pub trait MapAccess<'de> {
}
}
-impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A
+impl<'de, 'a, A> MapAccess<'de> for &'a mut A
where
- A: MapAccess<'de>,
+ A: ?Sized + MapAccess<'de>,
{
type Error = A::Error;
diff --git a/third_party/rust/serde/src/lib.rs b/third_party/rust/serde/src/lib.rs
index 5cf44c1c18..fefbf8fda2 100644
--- a/third_party/rust/serde/src/lib.rs
+++ b/third_party/rust/serde/src/lib.rs
@@ -95,7 +95,7 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/serde/1.0.197")]
+#![doc(html_root_url = "https://docs.rs/serde/1.0.198")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Show which crate feature enables conditionally compiled APIs in documentation.
@@ -274,6 +274,9 @@ mod lib {
pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
+
+ #[cfg(not(no_core_num_saturating))]
+ pub use self::core::num::Saturating;
}
// None of this crate's error handling needs the `From::from` error conversion
diff --git a/third_party/rust/serde/src/private/de.rs b/third_party/rust/serde/src/private/de.rs
index 883e6909c1..c402d2c66a 100644
--- a/third_party/rust/serde/src/private/de.rs
+++ b/third_party/rust/serde/src/private/de.rs
@@ -313,6 +313,8 @@ mod content {
}
}
+ /// Used to capture data in [`Content`] from other deserializers.
+ /// Cannot capture externally tagged enums, `i128` and `u128`.
struct ContentVisitor<'de> {
value: PhantomData<Content<'de>>,
}
@@ -528,6 +530,8 @@ mod content {
Content(Content<'de>),
}
+ /// Serves as a seed for deserializing a key of internally tagged enum.
+ /// Cannot capture externally tagged enums, `i128` and `u128`.
struct TagOrContentVisitor<'de> {
name: &'static str,
value: PhantomData<TagOrContent<'de>>,
@@ -814,6 +818,9 @@ mod content {
/// Used by generated code to deserialize an internally tagged enum.
///
+ /// Captures map or sequence from the original deserializer and searches
+ /// a tag in it (in case of sequence, tag is the first element of sequence).
+ ///
/// Not public API.
pub struct TaggedContentVisitor<T> {
tag_name: &'static str,
diff --git a/third_party/rust/serde/src/private/doc.rs b/third_party/rust/serde/src/private/doc.rs
index 1b18fe6b41..1f17c8db53 100644
--- a/third_party/rust/serde/src/private/doc.rs
+++ b/third_party/rust/serde/src/private/doc.rs
@@ -56,7 +56,10 @@ macro_rules! __serialize_unimplemented {
#[macro_export]
macro_rules! __serialize_unimplemented_method {
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
- fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error> {
+ fn $func $(<$t>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error>
+ where
+ $($t: ?Sized + $crate::Serialize,)*
+ {
unimplemented!()
}
};
diff --git a/third_party/rust/serde/src/private/ser.rs b/third_party/rust/serde/src/private/ser.rs
index 50bcb251e3..40cc6cbdb7 100644
--- a/third_party/rust/serde/src/private/ser.rs
+++ b/third_party/rust/serde/src/private/ser.rs
@@ -174,9 +174,9 @@ where
Err(self.bad_type(Unsupported::Optional))
}
- fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
+ fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
Err(self.bad_type(Unsupported::Optional))
}
@@ -205,18 +205,18 @@ where
map.end()
}
- fn serialize_newtype_struct<T: ?Sized>(
+ fn serialize_newtype_struct<T>(
self,
_: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
value.serialize(self)
}
- fn serialize_newtype_variant<T: ?Sized>(
+ fn serialize_newtype_variant<T>(
self,
_: &'static str,
_: u32,
@@ -224,7 +224,7 @@ where
inner_value: &T,
) -> Result<Self::Ok, Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
@@ -327,9 +327,9 @@ where
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
- fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
+ fn collect_str<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
- T: Display,
+ T: ?Sized + Display,
{
Err(self.bad_type(Unsupported::String))
}
@@ -364,9 +364,9 @@ mod content {
type Ok = M::Ok;
type Error = M::Error;
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), M::Error>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), M::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
@@ -404,13 +404,9 @@ mod content {
type Ok = M::Ok;
type Error = M::Error;
- fn serialize_field<T: ?Sized>(
- &mut self,
- key: &'static str,
- value: &T,
- ) -> Result<(), M::Error>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), M::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
@@ -635,9 +631,9 @@ mod content {
Ok(Content::None)
}
- fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Content, E>
+ fn serialize_some<T>(self, value: &T) -> Result<Content, E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
Ok(Content::Some(Box::new(tri!(value.serialize(self)))))
}
@@ -659,13 +655,9 @@ mod content {
Ok(Content::UnitVariant(name, variant_index, variant))
}
- fn serialize_newtype_struct<T: ?Sized>(
- self,
- name: &'static str,
- value: &T,
- ) -> Result<Content, E>
+ fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Content, E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
Ok(Content::NewtypeStruct(
name,
@@ -673,7 +665,7 @@ mod content {
))
}
- fn serialize_newtype_variant<T: ?Sized>(
+ fn serialize_newtype_variant<T>(
self,
name: &'static str,
variant_index: u32,
@@ -681,7 +673,7 @@ mod content {
value: &T,
) -> Result<Content, E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
Ok(Content::NewtypeVariant(
name,
@@ -782,9 +774,9 @@ mod content {
type Ok = Content;
type Error = E;
- fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
+ fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
@@ -808,9 +800,9 @@ mod content {
type Ok = Content;
type Error = E;
- fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
+ fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
@@ -835,9 +827,9 @@ mod content {
type Ok = Content;
type Error = E;
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
@@ -864,9 +856,9 @@ mod content {
type Ok = Content;
type Error = E;
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
@@ -896,18 +888,18 @@ mod content {
type Ok = Content;
type Error = E;
- fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), E>
+ fn serialize_key<T>(&mut self, key: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key);
Ok(())
}
- fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
+ fn serialize_value<T>(&mut self, value: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let key = self
.key
@@ -922,10 +914,10 @@ mod content {
Ok(Content::Map(self.entries))
}
- fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), E>
+ fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), E>
where
- K: Serialize,
- V: Serialize,
+ K: ?Sized + Serialize,
+ V: ?Sized + Serialize,
{
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
@@ -947,9 +939,9 @@ mod content {
type Ok = Content;
type Error = E;
- fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
@@ -976,9 +968,9 @@ mod content {
type Ok = Content;
type Error = E;
- fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
@@ -1088,9 +1080,9 @@ where
Ok(())
}
- fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+ fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
value.serialize(self)
}
@@ -1112,18 +1104,18 @@ where
Err(Self::bad_type(Unsupported::Enum))
}
- fn serialize_newtype_struct<T: ?Sized>(
+ fn serialize_newtype_struct<T>(
self,
_: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
value.serialize(self)
}
- fn serialize_newtype_variant<T: ?Sized>(
+ fn serialize_newtype_variant<T>(
self,
_: &'static str,
_: u32,
@@ -1131,7 +1123,7 @@ where
value: &T,
) -> Result<Self::Ok, Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
tri!(self.0.serialize_key(variant));
self.0.serialize_value(value)
@@ -1202,28 +1194,24 @@ where
type Ok = ();
type Error = M::Error;
- fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
+ fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
self.0.serialize_key(key)
}
- fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
self.0.serialize_value(value)
}
- fn serialize_entry<K: ?Sized, V: ?Sized>(
- &mut self,
- key: &K,
- value: &V,
- ) -> Result<(), Self::Error>
+ fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
where
- K: Serialize,
- V: Serialize,
+ K: ?Sized + Serialize,
+ V: ?Sized + Serialize,
{
self.0.serialize_entry(key, value)
}
@@ -1244,13 +1232,9 @@ where
type Ok = ();
type Error = M::Error;
- fn serialize_field<T: ?Sized>(
- &mut self,
- key: &'static str,
- value: &T,
- ) -> Result<(), Self::Error>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
self.0.serialize_entry(key, value)
}
@@ -1289,9 +1273,9 @@ where
type Ok = ();
type Error = M::Error;
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
@@ -1335,13 +1319,9 @@ where
type Ok = ();
type Error = M::Error;
- fn serialize_field<T: ?Sized>(
- &mut self,
- key: &'static str,
- value: &T,
- ) -> Result<(), Self::Error>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
diff --git a/third_party/rust/serde/src/ser/fmt.rs b/third_party/rust/serde/src/ser/fmt.rs
index 0650ab6f12..04684aded0 100644
--- a/third_party/rust/serde/src/ser/fmt.rs
+++ b/third_party/rust/serde/src/ser/fmt.rs
@@ -74,9 +74,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Display::fmt(variant, self)
}
- fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
+ fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> fmt::Result
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
Serialize::serialize(value, self)
}
@@ -89,9 +89,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Err(fmt::Error)
}
- fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
+ fn serialize_some<T>(self, _value: &T) -> fmt::Result
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
Err(fmt::Error)
}
@@ -100,7 +100,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Err(fmt::Error)
}
- fn serialize_newtype_variant<T: ?Sized>(
+ fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
@@ -108,7 +108,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
_value: &T,
) -> fmt::Result
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
Err(fmt::Error)
}
@@ -161,9 +161,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Err(fmt::Error)
}
- fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
+ fn collect_str<T>(self, value: &T) -> fmt::Result
where
- T: Display,
+ T: ?Sized + Display,
{
Display::fmt(value, self)
}
diff --git a/third_party/rust/serde/src/ser/impls.rs b/third_party/rust/serde/src/ser/impls.rs
index 8c70634af0..ffc4c70f90 100644
--- a/third_party/rust/serde/src/ser/impls.rs
+++ b/third_party/rust/serde/src/ser/impls.rs
@@ -114,7 +114,10 @@ where
////////////////////////////////////////////////////////////////////////////////
-impl<T: ?Sized> Serialize for PhantomData<T> {
+impl<T> Serialize for PhantomData<T>
+where
+ T: ?Sized,
+{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -504,17 +507,17 @@ macro_rules! deref_impl {
}
deref_impl! {
- <'a, T: ?Sized> Serialize for &'a T where T: Serialize
+ <'a, T> Serialize for &'a T where T: ?Sized + Serialize
}
deref_impl! {
- <'a, T: ?Sized> Serialize for &'a mut T where T: Serialize
+ <'a, T> Serialize for &'a mut T where T: ?Sized + Serialize
}
deref_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
- <T: ?Sized> Serialize for Box<T> where T: Serialize
+ <T> Serialize for Box<T> where T: ?Sized + Serialize
}
deref_impl! {
@@ -528,7 +531,7 @@ deref_impl! {
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
- <T: ?Sized> Serialize for Rc<T> where T: Serialize
+ <T> Serialize for Rc<T> where T: ?Sized + Serialize
}
deref_impl! {
@@ -542,13 +545,13 @@ deref_impl! {
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
- <T: ?Sized> Serialize for Arc<T> where T: Serialize
+ <T> Serialize for Arc<T> where T: ?Sized + Serialize
}
deref_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
- <'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned
+ <'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned
}
////////////////////////////////////////////////////////////////////////////////
@@ -561,9 +564,9 @@ deref_impl! {
doc_cfg,
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
)]
-impl<T: ?Sized> Serialize for RcWeak<T>
+impl<T> Serialize for RcWeak<T>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -581,9 +584,9 @@ where
doc_cfg,
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
)]
-impl<T: ?Sized> Serialize for ArcWeak<T>
+impl<T> Serialize for ArcWeak<T>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -641,9 +644,9 @@ where
}
}
-impl<T: ?Sized> Serialize for RefCell<T>
+impl<T> Serialize for RefCell<T>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -658,9 +661,9 @@ where
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
-impl<T: ?Sized> Serialize for Mutex<T>
+impl<T> Serialize for Mutex<T>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -675,9 +678,9 @@ where
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
-impl<T: ?Sized> Serialize for RwLock<T>
+impl<T> Serialize for RwLock<T>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -1023,6 +1026,20 @@ where
}
}
+#[cfg(not(no_core_num_saturating))]
+impl<T> Serialize for Saturating<T>
+where
+ T: Serialize,
+{
+ #[inline]
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ self.0.serialize(serializer)
+ }
+}
+
impl<T> Serialize for Reverse<T>
where
T: Serialize,
diff --git a/third_party/rust/serde/src/ser/impossible.rs b/third_party/rust/serde/src/ser/impossible.rs
index 479be94071..6432d5775a 100644
--- a/third_party/rust/serde/src/ser/impossible.rs
+++ b/third_party/rust/serde/src/ser/impossible.rs
@@ -72,9 +72,9 @@ where
type Ok = Ok;
type Error = Error;
- fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -92,9 +92,9 @@ where
type Ok = Ok;
type Error = Error;
- fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -112,9 +112,9 @@ where
type Ok = Ok;
type Error = Error;
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -132,9 +132,9 @@ where
type Ok = Ok;
type Error = Error;
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -152,17 +152,17 @@ where
type Ok = Ok;
type Error = Error;
- fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
+ fn serialize_key<T>(&mut self, key: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = key;
match self.void {}
}
- fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ fn serialize_value<T>(&mut self, value: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -180,9 +180,9 @@ where
type Ok = Ok;
type Error = Error;
- fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = key;
let _ = value;
@@ -201,9 +201,9 @@ where
type Ok = Ok;
type Error = Error;
- fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
- T: Serialize,
+ T: ?Sized + Serialize,
{
let _ = key;
let _ = value;
diff --git a/third_party/rust/serde/src/ser/mod.rs b/third_party/rust/serde/src/ser/mod.rs
index 75c45140e2..74b5e07691 100644
--- a/third_party/rust/serde/src/ser/mod.rs
+++ b/third_party/rust/serde/src/ser/mod.rs
@@ -796,9 +796,9 @@ pub trait Serializer: Sized {
/// ```
///
/// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some
- fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+ fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Serialize a `()` value.
///
@@ -891,13 +891,13 @@ pub trait Serializer: Sized {
/// }
/// }
/// ```
- fn serialize_newtype_struct<T: ?Sized>(
+ fn serialize_newtype_struct<T>(
self,
name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
///
@@ -925,7 +925,7 @@ pub trait Serializer: Sized {
/// }
/// }
/// ```
- fn serialize_newtype_variant<T: ?Sized>(
+ fn serialize_newtype_variant<T>(
self,
name: &'static str,
variant_index: u32,
@@ -933,7 +933,7 @@ pub trait Serializer: Sized {
value: &T,
) -> Result<Self::Ok, Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Begin to serialize a variably sized sequence. This call must be
/// followed by zero or more calls to `serialize_element`, then a call to
@@ -1170,7 +1170,8 @@ pub trait Serializer: Sized {
/// then a call to `end`.
///
/// The `name` is the name of the struct and the `len` is the number of
- /// data fields that will be serialized.
+ /// data fields that will be serialized. `len` does not include fields
+ /// which are skipped with [`SerializeStruct::skip_field`].
///
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
@@ -1207,6 +1208,8 @@ pub trait Serializer: Sized {
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
+ /// `len` does not include fields which are skipped with
+ /// [`SerializeStructVariant::skip_field`].
///
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
@@ -1346,9 +1349,9 @@ pub trait Serializer: Sized {
/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
/// [`serialize_str`]: #tymethod.serialize_str
#[cfg(any(feature = "std", feature = "alloc"))]
- fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+ fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
- T: Display,
+ T: ?Sized + Display,
{
self.serialize_str(&value.to_string())
}
@@ -1379,9 +1382,9 @@ pub trait Serializer: Sized {
/// }
/// ```
#[cfg(not(any(feature = "std", feature = "alloc")))]
- fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+ fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
- T: Display;
+ T: ?Sized + Display;
/// Determine whether `Serialize` implementations should serialize in
/// human-readable form.
@@ -1493,9 +1496,9 @@ pub trait SerializeSeq {
type Error: Error;
/// Serialize a sequence element.
- fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Finish serializing a sequence.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1593,9 +1596,9 @@ pub trait SerializeTuple {
type Error: Error;
/// Serialize a tuple element.
- fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Finish serializing a tuple.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1638,9 +1641,9 @@ pub trait SerializeTupleStruct {
type Error: Error;
/// Serialize a tuple struct field.
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Finish serializing a tuple struct.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1696,9 +1699,9 @@ pub trait SerializeTupleVariant {
type Error: Error;
/// Serialize a tuple variant field.
- fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Finish serializing a tuple variant.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1767,9 +1770,9 @@ pub trait SerializeMap {
/// `serialize_entry` instead as it may be implemented more efficiently in
/// some formats compared to a pair of calls to `serialize_key` and
/// `serialize_value`.
- fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
+ fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Serialize a map value.
///
@@ -1777,9 +1780,9 @@ pub trait SerializeMap {
///
/// Calling `serialize_value` before `serialize_key` is incorrect and is
/// allowed to panic or produce bogus results.
- fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Serialize a map entry consisting of a key and a value.
///
@@ -1798,14 +1801,10 @@ pub trait SerializeMap {
/// [`Serialize`]: ../trait.Serialize.html
/// [`serialize_key`]: #tymethod.serialize_key
/// [`serialize_value`]: #tymethod.serialize_value
- fn serialize_entry<K: ?Sized, V: ?Sized>(
- &mut self,
- key: &K,
- value: &V,
- ) -> Result<(), Self::Error>
+ fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
where
- K: Serialize,
- V: Serialize,
+ K: ?Sized + Serialize,
+ V: ?Sized + Serialize,
{
tri!(self.serialize_key(key));
self.serialize_value(value)
@@ -1856,15 +1855,13 @@ pub trait SerializeStruct {
type Error: Error;
/// Serialize a struct field.
- fn serialize_field<T: ?Sized>(
- &mut self,
- key: &'static str,
- value: &T,
- ) -> Result<(), Self::Error>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Indicate that a struct field has been skipped.
+ ///
+ /// The default implementation does nothing.
#[inline]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
let _ = key;
@@ -1922,15 +1919,13 @@ pub trait SerializeStructVariant {
type Error: Error;
/// Serialize a struct variant field.
- fn serialize_field<T: ?Sized>(
- &mut self,
- key: &'static str,
- value: &T,
- ) -> Result<(), Self::Error>
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
- T: Serialize;
+ T: ?Sized + Serialize;
/// Indicate that a struct variant field has been skipped.
+ ///
+ /// The default implementation does nothing.
#[inline]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
let _ = key;
diff --git a/third_party/rust/serde_derive/.cargo-checksum.json b/third_party/rust/serde_derive/.cargo-checksum.json
index 331652acd7..4795d909a2 100644
--- a/third_party/rust/serde_derive/.cargo-checksum.json
+++ b/third_party/rust/serde_derive/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"daf3d8f8efdf30d3575c7d1e1372ff7287891fb95625223e4a8a2f792c4474e1","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/bound.rs":"6c5c20785ac95af9480f8d0de35a7e844cc36a16012f6468db148acd03cb15c2","src/de.rs":"c221ab2b94a5d80dccff74a37f3448b3d695656552b452595dc289c73b12fb2b","src/dummy.rs":"9533dfee23f20d92ea75734c739022820c2787ded0d54f459feacdeb770ec912","src/fragment.rs":"6757cb4c3131d4300f093572efc273c4ab5a20e3e1efb54a311dcfa52d0bd6eb","src/internals/ast.rs":"7dc997e4090033bbd1d0bdd870e8bb87b096b7f66cfd02047f6b85ebdd569b12","src/internals/attr.rs":"6584c0a02de0d17993877303f3cc2c1bccf235257632220421f98082d82d387a","src/internals/case.rs":"10c8dda2b32d8c6c6b63cf09cdc63d02375af7e95ecefe8fecb34f93b65191bb","src/internals/check.rs":"d842eb9912fd29311060b67f3bc62c438eb7b5d86093355acb4de7eee02a0ef8","src/internals/ctxt.rs":"83a4e6fbe0e439d578478883594407e03f2f340541be479bdf0b04a202633a37","src/internals/mod.rs":"ed021ca635c18132a0e5c3d90f21b7f65def0a61e946421a30200b5b9ab6ad43","src/internals/receiver.rs":"fe8a480669511b5edcfe71f5dd290cf72ccec54c9016ec85f2ac59dce538077f","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"d619e88caa3c7a09b03014257f2b349ee922290062d9b97b4dd19d0e64532690","src/lib.rs":"7a6c2796244658f62d398ebc6819c4f3064dac4a1ad7c52b40359f9411f1c266","src/pretend.rs":"7facc10a5b805564dd95735ae11118ec17ca6adcc49a59764e7c920e27b9fc4a","src/ser.rs":"e3341471cea9d7e2fb4043e5d1746862beb9a4e25196170879eeac529d460920","src/this.rs":"87818dc80cbb521b51938a653d09daf10aafc220bb10425948de82ad670fcb85"},"package":"7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"} \ No newline at end of file
+{"files":{"Cargo.toml":"a8aac06a59f67cf1f468da3e234ae0cbb87089ad064bdfae4beb72932cd4210f","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/bound.rs":"6c5c20785ac95af9480f8d0de35a7e844cc36a16012f6468db148acd03cb15c2","src/de.rs":"c221ab2b94a5d80dccff74a37f3448b3d695656552b452595dc289c73b12fb2b","src/dummy.rs":"9533dfee23f20d92ea75734c739022820c2787ded0d54f459feacdeb770ec912","src/fragment.rs":"6757cb4c3131d4300f093572efc273c4ab5a20e3e1efb54a311dcfa52d0bd6eb","src/internals/ast.rs":"7dc997e4090033bbd1d0bdd870e8bb87b096b7f66cfd02047f6b85ebdd569b12","src/internals/attr.rs":"6584c0a02de0d17993877303f3cc2c1bccf235257632220421f98082d82d387a","src/internals/case.rs":"10c8dda2b32d8c6c6b63cf09cdc63d02375af7e95ecefe8fecb34f93b65191bb","src/internals/check.rs":"d842eb9912fd29311060b67f3bc62c438eb7b5d86093355acb4de7eee02a0ef8","src/internals/ctxt.rs":"83a4e6fbe0e439d578478883594407e03f2f340541be479bdf0b04a202633a37","src/internals/mod.rs":"ed021ca635c18132a0e5c3d90f21b7f65def0a61e946421a30200b5b9ab6ad43","src/internals/receiver.rs":"fe8a480669511b5edcfe71f5dd290cf72ccec54c9016ec85f2ac59dce538077f","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"d619e88caa3c7a09b03014257f2b349ee922290062d9b97b4dd19d0e64532690","src/lib.rs":"fd046746f651890097154a0a8cb5f90c050fda8da4e0bbdf1c8e4826d10794db","src/pretend.rs":"7facc10a5b805564dd95735ae11118ec17ca6adcc49a59764e7c920e27b9fc4a","src/ser.rs":"a5638fa1b42b2a0d23cc12649f9180d4132f4cb7cf9edace1a1caed483f609e9","src/this.rs":"87818dc80cbb521b51938a653d09daf10aafc220bb10425948de82ad670fcb85"},"package":"e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"} \ No newline at end of file
diff --git a/third_party/rust/serde_derive/Cargo.toml b/third_party/rust/serde_derive/Cargo.toml
index 33642ef04c..881bb3b7a5 100644
--- a/third_party/rust/serde_derive/Cargo.toml
+++ b/third_party/rust/serde_derive/Cargo.toml
@@ -10,9 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
+edition = "2015"
rust-version = "1.56"
name = "serde_derive"
-version = "1.0.197"
+version = "1.0.198"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
diff --git a/third_party/rust/serde_derive/src/lib.rs b/third_party/rust/serde_derive/src/lib.rs
index b91f17b1a9..70b16e9955 100644
--- a/third_party/rust/serde_derive/src/lib.rs
+++ b/third_party/rust/serde_derive/src/lib.rs
@@ -13,7 +13,7 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
-#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.197")]
+#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.198")]
// Ignored clippy lints
#![allow(
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
diff --git a/third_party/rust/serde_derive/src/ser.rs b/third_party/rust/serde_derive/src/ser.rs
index 3be51ee52d..7d89d22125 100644
--- a/third_party/rust/serde_derive/src/ser.rs
+++ b/third_party/rust/serde_derive/src/ser.rs
@@ -289,7 +289,7 @@ fn serialize_tuple_struct(
}
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
- assert!(fields.len() as u64 <= u64::from(u32::max_value()));
+ assert!(fields.len() as u64 <= u64::from(u32::MAX));
if cattrs.has_flatten() {
serialize_struct_as_map(params, fields, cattrs)
@@ -397,7 +397,7 @@ fn serialize_struct_as_map(
}
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
- assert!(variants.len() as u64 <= u64::from(u32::max_value()));
+ assert!(variants.len() as u64 <= u64::from(u32::MAX));
let self_var = &params.self_var;
diff --git a/third_party/rust/serde_json/.cargo-checksum.json b/third_party/rust/serde_json/.cargo-checksum.json
index 369b6fe170..1f61b06b5f 100644
--- a/third_party/rust/serde_json/.cargo-checksum.json
+++ b/third_party/rust/serde_json/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"f5270cafba66223a7b51ffc0d286075a17bb7cd88762fc80d333d3102629f4d8","Cargo.toml":"547ec897b43d41db797423629543e838ee4e08c6a4196a0756b5be0ef178adc1","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"1e5a86e6b5e79f92f9e7226d9a8ba16d4ec70567d153c9cacebcb582770378a1","build.rs":"0dd97b63a07aa2d4bbb4c7d0e73b521da130769da9f49f28a7b63332781eb3de","src/de.rs":"5dba95fc6a564917289bf1e404d59c74f95772f22ec92cb91d55053b65e93032","src/error.rs":"abb92a9bf62cb7f47141a733a9fd66ec8c369615d7e6f633d3536fd2a5ac74a2","src/features_check/error.rs":"d7359f864afbfe105a38abea9f563dc423036ebc4c956a5695a4beef144dc7ec","src/features_check/mod.rs":"2209f8d5c46b50c8a3b8dc22338dcaf0135d192e8b05d2f456cbe6a73104e958","src/io/core.rs":"9a4146802391fd202a36bebbf3b14b715ae09d8828cbe8e06a01214c470ebf5c","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"4fbeb1994049348d1fc388dd1a29e481f8abb8fe1e28bfebf50f3bbce5fa5fbe","src/lexical/bhcomp.rs":"b7c68d74c0055eb67ec2c1bcf27bbc28bef8f1bbc43db8eb94ba69892230add6","src/lexical/bignum.rs":"4230cde10dc8eae456a713cf90ec4e48dff4b1d0c542621ce7f00f39ade2645e","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"a265b9072194a62a67dfc4df3c86d4213097cf3f82280d025e0012a5a262fd9d","src/lexical/errors.rs":"6bc993febceb7dd96ac1c8c5c53b5f5a30297016c0f813ed8ff8d7938d01534d","src/lexical/exponent.rs":"387e945b97dc7ba48a7091c50d228a0dde3a1c4145703d4ab9c31191a91693b0","src/lexical/float.rs":"fe356213c92a049f4bef2f58bc0e3a26866ca06b8c1d74d0f961c5b883852cad","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"d533037c6141e6671102aee490c9cdeaba81e667ddca781b2b99db2c455e4a1a","src/lexical/large_powers64.rs":"745dd7c0cbe499eec027ef586248881011d9df20c7efab7929c1807b59886ba1","src/lexical/math.rs":"27e22b724cdf990cdacd0ccfc3749e6e2eb7529d43ebf6e95b1999560b9e199a","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"cf705c62612e31d704f43d94a633ea1243c6befad7ef5792e2e881a7fd21e809","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"697207248ba17b7f4965aedb11d276261ada5b06d9c6265d8fd6246664ff6e3c","src/lexical/shift.rs":"bc1ed053dd63d45ac9c35302f18de9f00d94027f28af4ab749c9248439de832a","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"f055ef570d978397cfae0d814ddbbf2372b8839ab4ffe8fc4c3308c9b2a332de","src/macros.rs":"c9f23156faec8d5216d72b6a97eebd768efb3f75870a6e2beed824308587b998","src/map.rs":"14fa16650b462ef138bebe1d18cb296b0e1ff404f12f2c212f72ed7c969b3a12","src/number.rs":"425f528c5ec2fcb4dd3c87a633d0b2cd505f7a305a40dffa1f022a643eda938b","src/raw.rs":"6d46836486b8d1c58f2aff563285400b1b0ec163eee34e7be78e0fa7a99aa0e8","src/read.rs":"49b4b1d067b6485cbded28fb961666ab5df82c36661af722dbae756efb6b2891","src/ser.rs":"566ae0b1860861ad70efd17fb0f6ae326e76d60453b6538c783a40d4ce616851","src/value/de.rs":"78f938d960e285f671f3b86ed173d598a815690a14512d6daa94dee43d3ce4cf","src/value/from.rs":"2dcfed837b040447a61eae50bd3938106b090f8a292206aea686022767006625","src/value/index.rs":"8a99d8d50f5674181ced22f6e81dc529eaecb01e543e30346e51fe42cb4b8a5f","src/value/mod.rs":"81c62fcb50e92b2f424e361328df5b02621756781bf80b8e26fd3d13473b57cd","src/value/partial_eq.rs":"95de799d57f7f4310b64a9488c0a7286dee76dba4329cb69a96298a887e58586","src/value/ser.rs":"5ea04bdf30c1c79baeab66b922908b47f1910b07d2f4ed0927a9a2c1ef3fbf60","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/debug.rs":"a8451217c1e127ad6e653ef11e0513525ee350e1e37dd575758a8ee9301b28fb","tests/lexical.rs":"383e06283e15e1db7c6b818da3c84a3afa0059f6e9fc994b069919d81346ab91","tests/lexical/algorithm.rs":"da378df9ee24bfa033968d5c94e91b58e52c39bf6c825dec51c3eb7250cc5874","tests/lexical/exponent.rs":"26ea92abc654a6a88a8281552bca2f76ea1fa4c17d66a1dd6defe14f7d89b666","tests/lexical/float.rs":"0440f2d85c993bcccd925096d7f4136bf624ffd66b3c7ee565d158390685eb11","tests/lexical/math.rs":"4874be2103be5fbe8b8015354414df271ffa00fd815546fc077f15fb4d7a5a37","tests/lexical/num.rs":"6e650c40de85ed72ac06b6bf1487ba161f3824e26d827df6cfdf2bbdb8d05a05","tests/lexical/parse.rs":"17c73e0a59d462716d974b8dd23a291eb6efdc3a933248874e5eab7e7209d67f","tests/lexical/rounding.rs":"6c56e39ba534616c1b2146e8efa6eb57aed322e683bf23183cd32a61fae6447e","tests/macros/mod.rs":"93aa1d54af20bc2c55b6ae8db73c1414cda2626eb9fa7bd57b9d613a3c6e6a19","tests/map.rs":"dcc5212242e4e93703c4335d54f5603b0211b33d6fb5ab410bb630cda6d46b09","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue520.rs":"d146be3472db902b48127d65fe83aa9f698143aca9074c83cd1a9d5dd28e3ec3","tests/regression/issue795.rs":"582e2e7c68113f05a4b1d2cb556a2df7cc77f2ce8164a32c5cc58ae68abb60ec","tests/regression/issue845.rs":"8bd64588fc344e119d0e9e5e7604236e7c168c574b0692033f15278e216a6b9c","tests/regression/issue953.rs":"b2cddc761f5ca6639900c173765a8a5868528a896924e5e925db2696469208f7","tests/stream.rs":"c7d91014538ecd8f495b196d40e999ab2745f2e69fa2ff9e52521605dc6ce856","tests/test.rs":"b9154ff63261cecd6f04443ce3580d285af16f77cdc2c87239408cb8e06009dc","tests/ui/missing_colon.rs":"d07e0c34d98eb43465f0a0310f2c0b5d5b0d26d243b352a1c6bbe6ad3b27eda9","tests/ui/missing_colon.stderr":"3732fd8f4e57b84efc07170cda5f9c5b2b17c707e23c1659222b5a46f652a8d8","tests/ui/missing_comma.rs":"b8a9662f99c3e6dd2b6417892c37640578ce91d3a8365bf10c1f686a3227aa87","tests/ui/missing_comma.stderr":"eae626cf93c97abd105066e624ca4e8cb096784413b9d2564cf9414a8492bc4d","tests/ui/missing_value.rs":"bca25d67127fb88e7c191c7b03af5a4ce8a9abb630f3d2e6a6c1e77e213dc9a4","tests/ui/missing_value.stderr":"b0df8add5cf74e5df30eedd3ca347e4862c04a01c54d802ff45392f2032065b1","tests/ui/not_found.rs":"d0a7adb309879ff65aee115b52cc33d36f4bad353cf97c4effc34a6128c2bee3","tests/ui/not_found.stderr":"359b751c0c21fab6d460daef4d5f73a265f7769c9b578f98ea3cb6cbf2387643","tests/ui/parse_expr.rs":"32e6d51f528db3d1ab0ed1e24765b865be393565c26f77413c5aa39d601ac563","tests/ui/parse_expr.stderr":"4fcd0a014fbce31c9266bab8527d6e6b6806a0e21d9e0275ce713137856073ce","tests/ui/parse_key.rs":"18829b2af320d5cf8a0a5cd3aaf84c7e92cc874651c30e45a3acafb76c2d8b93","tests/ui/parse_key.stderr":"fcb44e060b804a4762b7291e128c41d7010ffa8ab820b8828fd13fbe6d405ca6","tests/ui/unexpected_after_array_element.rs":"a343fc3104431720bdfcf330bcc3cfcd98c8dec3e951133b495242478b0b7eb3","tests/ui/unexpected_after_array_element.stderr":"8df615998fa3057bb9ed865981a35cdbb771625337048f0ad3fba7734e607adf","tests/ui/unexpected_after_map_entry.rs":"6e3bd2def435ca610e346bbc75cdbaf61963eb2ef1885bb5f76781ba1fac37ef","tests/ui/unexpected_after_map_entry.stderr":"b1985c89075ab48b2158bd1705ed766d37854b3d4620ab257cc8bc319d224f17","tests/ui/unexpected_colon.rs":"a313cff3fed4be4c33f1eda5d0c5c98147fb835a56d36470d9f367352c1d61ef","tests/ui/unexpected_colon.stderr":"b2288742fa6a4a7eb65d2ae899bcfed8795b57bd04958da227d60928a8df26c5","tests/ui/unexpected_comma.rs":"55a8b684bde1ce905837cce719fd457d8898b61cebc27e5b420d05cb6be97256","tests/ui/unexpected_comma.stderr":"4c103ca63ff15e2ca659242cc0eae0612bf050e7580da62f1cf50de8082aa7dc"},"package":"cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"} \ No newline at end of file
+{"files":{"CONTRIBUTING.md":"f5270cafba66223a7b51ffc0d286075a17bb7cd88762fc80d333d3102629f4d8","Cargo.toml":"f8b789a2b436af04913166cb07fcd87927fb4a89c84332f82fd58f84cc3a4e0b","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"f223b99630bae262eb2b88bb95d0f496db8f1ff4e94e43dbfc8d95d3a6c98d8f","build.rs":"9fa36e0b1bb7026b449a20986ae2f60b3046bcbcf3bf22b5c0e372eb892eaf57","src/de.rs":"c423a0534203713b89c3db544d7ea0988b4a913a0501d0d9cb170f6a66d23dd6","src/error.rs":"a9b5de0a82f95608b51b8e8875c7c49f94fb60b9f976fc6277aec0213926dec9","src/io/core.rs":"60ba28f67a9acaecf8964b611efba416b13f9f2bae4befc329fdf0e037293802","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"bd6106e5d8875c9ff1c1d57256b459a4f0992d14a0df1a5fffcd3d3cbdccee8c","src/lexical/bhcomp.rs":"b7c68d74c0055eb67ec2c1bcf27bbc28bef8f1bbc43db8eb94ba69892230add6","src/lexical/bignum.rs":"db688e8112389998d0f91906f6857e28f9b510a8b4065ad476c8e8be2f77becf","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"9502805adbc3da059131d1fac0a802e17065b36cd7472606b3af24e3241d5cb8","src/lexical/errors.rs":"3d9f6de6245533bcb101dfd718cfed61d59dc293f6768cedae28aa13ace164f5","src/lexical/exponent.rs":"51f19443008e8884b15c7d5d4b1f1cfbd5673a9d1da02f1af39fcf20e315f01f","src/lexical/float.rs":"fe356213c92a049f4bef2f58bc0e3a26866ca06b8c1d74d0f961c5b883852cad","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"c70b57a727960beec258758a4d4a1050f8eaf3b4e60027c663a2bfb0246e0153","src/lexical/large_powers64.rs":"e7af83ce3159b5fc4669fc5a231e767d8af21bacaece52a0a48951198965b197","src/lexical/math.rs":"240804aa030849495fa03a83a0ee8539d5a5c8639b825f2d69d27b7567b06fb3","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"dd9f4357b8d5bead413844d4015176d484e907e1a393cf7f583de5c5ccafb2e3","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"4762af3612880b17468ff2a1bb800c8e99f08330ae439699dd53d8dc5463ad13","src/lexical/shift.rs":"bc1ed053dd63d45ac9c35302f18de9f00d94027f28af4ab749c9248439de832a","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"161e03a3d34254716ed88d6d3b7c7536f646e674263ca71b5930b99c1c06a4ca","src/macros.rs":"516f69976f433bcc5e48c32b3e29c2e0ab7b549810827d7a9c59171cdf11c1e2","src/map.rs":"aeb07107ba949330e72f4d669d46b215990f83aa4055e06d1da69f2a32ddf642","src/number.rs":"537be73fe2f1f4c654a41e0b6461493ca7e3c20265163b3fb3405d047c163c1a","src/raw.rs":"74f5937706324c9325acc42597ff0a226faeaae38d270ab61ba6283e37616c86","src/read.rs":"7e5928c7f71cfa3848966ab6cc0e6596fd0a3e15cf9f2c59675bf920340ab79f","src/ser.rs":"ee5b6cb04c2ff7058b52cb5d0383218f484505ce0896e5c7fd5076bd9d90952e","src/value/de.rs":"890d88303ce0036a5efd1c57378dab7f8c45dabd798cece2248c2d9db52fa011","src/value/from.rs":"add9687e35db3962729d986c8aa54785cadeb07b8b7121cd4075e3a37ecc73a1","src/value/index.rs":"1a0d59629ae16d6553686de8d7152abd470153f67f9a1b69741e480ba491cd67","src/value/mod.rs":"c1b08509df5ae1ffb5c5e148ac29791923c92eb9957935683739a95bef0007e9","src/value/partial_eq.rs":"655fd0bf3ab1d6669444a55ab849f43bb333032de8ca8f1ee95e1068da43ee22","src/value/ser.rs":"d59f959448de1f4115ed62359e7444081741215e7005bcf97f7584b5e31e3b15","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/debug.rs":"a8451217c1e127ad6e653ef11e0513525ee350e1e37dd575758a8ee9301b28fb","tests/lexical.rs":"8ee6e617ef62a090de49ac2a930130a6913ab5316100781543c7788f89ef99c2","tests/lexical/algorithm.rs":"da378df9ee24bfa033968d5c94e91b58e52c39bf6c825dec51c3eb7250cc5874","tests/lexical/exponent.rs":"dc8fa8d05e561ff256f8b09385291768c7f45e5ad6cb878ef9194757aa014386","tests/lexical/float.rs":"0440f2d85c993bcccd925096d7f4136bf624ffd66b3c7ee565d158390685eb11","tests/lexical/math.rs":"4874be2103be5fbe8b8015354414df271ffa00fd815546fc077f15fb4d7a5a37","tests/lexical/num.rs":"6e650c40de85ed72ac06b6bf1487ba161f3824e26d827df6cfdf2bbdb8d05a05","tests/lexical/parse.rs":"a11f09bb003a3a024548008cf78bf76526ed71b00077d1989f45eb8cebc93b9c","tests/lexical/rounding.rs":"6c56e39ba534616c1b2146e8efa6eb57aed322e683bf23183cd32a61fae6447e","tests/macros/mod.rs":"93aa1d54af20bc2c55b6ae8db73c1414cda2626eb9fa7bd57b9d613a3c6e6a19","tests/map.rs":"89f604c5788bcb8dc82c82e252dc0da47257986e353c09d14e4ef3e58c455f2d","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue1004.rs":"38d7e3b6c515b881078ebd21ca8063d2ca105cd319695d29538f879e37f091b5","tests/regression/issue520.rs":"f95b362e45c57b431720c48eb47f7ddddf4078195d6859df523dc32950ce980a","tests/regression/issue795.rs":"37ff26744b1f950dd212565c6e3f276268882f7724cc589ac8b21ca8bd608413","tests/regression/issue845.rs":"10d2895cd1412cb6630f0a59db367f79ee672edb501151c7581e9921b5a84b92","tests/regression/issue953.rs":"b2cddc761f5ca6639900c173765a8a5868528a896924e5e925db2696469208f7","tests/stream.rs":"c7d91014538ecd8f495b196d40e999ab2745f2e69fa2ff9e52521605dc6ce856","tests/test.rs":"43cd75d02297758365ce6175a62843fa84fb60f4cdb3c9ed3cbfb752db6fcc68","tests/ui/missing_colon.rs":"d07e0c34d98eb43465f0a0310f2c0b5d5b0d26d243b352a1c6bbe6ad3b27eda9","tests/ui/missing_colon.stderr":"3732fd8f4e57b84efc07170cda5f9c5b2b17c707e23c1659222b5a46f652a8d8","tests/ui/missing_comma.rs":"b8a9662f99c3e6dd2b6417892c37640578ce91d3a8365bf10c1f686a3227aa87","tests/ui/missing_comma.stderr":"eae626cf93c97abd105066e624ca4e8cb096784413b9d2564cf9414a8492bc4d","tests/ui/missing_value.rs":"bca25d67127fb88e7c191c7b03af5a4ce8a9abb630f3d2e6a6c1e77e213dc9a4","tests/ui/missing_value.stderr":"b0df8add5cf74e5df30eedd3ca347e4862c04a01c54d802ff45392f2032065b1","tests/ui/not_found.rs":"d0a7adb309879ff65aee115b52cc33d36f4bad353cf97c4effc34a6128c2bee3","tests/ui/not_found.stderr":"359b751c0c21fab6d460daef4d5f73a265f7769c9b578f98ea3cb6cbf2387643","tests/ui/parse_expr.rs":"32e6d51f528db3d1ab0ed1e24765b865be393565c26f77413c5aa39d601ac563","tests/ui/parse_expr.stderr":"4fcd0a014fbce31c9266bab8527d6e6b6806a0e21d9e0275ce713137856073ce","tests/ui/parse_key.rs":"18829b2af320d5cf8a0a5cd3aaf84c7e92cc874651c30e45a3acafb76c2d8b93","tests/ui/parse_key.stderr":"20cf0d2898749f3c36780fc065f5049ee809e74cb6f0ef776f43f45e01596ee3","tests/ui/unexpected_after_array_element.rs":"a343fc3104431720bdfcf330bcc3cfcd98c8dec3e951133b495242478b0b7eb3","tests/ui/unexpected_after_array_element.stderr":"8df615998fa3057bb9ed865981a35cdbb771625337048f0ad3fba7734e607adf","tests/ui/unexpected_after_map_entry.rs":"6e3bd2def435ca610e346bbc75cdbaf61963eb2ef1885bb5f76781ba1fac37ef","tests/ui/unexpected_after_map_entry.stderr":"b1985c89075ab48b2158bd1705ed766d37854b3d4620ab257cc8bc319d224f17","tests/ui/unexpected_colon.rs":"a313cff3fed4be4c33f1eda5d0c5c98147fb835a56d36470d9f367352c1d61ef","tests/ui/unexpected_colon.stderr":"b2288742fa6a4a7eb65d2ae899bcfed8795b57bd04958da227d60928a8df26c5","tests/ui/unexpected_comma.rs":"55a8b684bde1ce905837cce719fd457d8898b61cebc27e5b420d05cb6be97256","tests/ui/unexpected_comma.stderr":"4c103ca63ff15e2ca659242cc0eae0612bf050e7580da62f1cf50de8082aa7dc"},"package":"3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"} \ No newline at end of file
diff --git a/third_party/rust/serde_json/Cargo.toml b/third_party/rust/serde_json/Cargo.toml
index cff28cd7b2..9941fdd86b 100644
--- a/third_party/rust/serde_json/Cargo.toml
+++ b/third_party/rust/serde_json/Cargo.toml
@@ -10,10 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
-rust-version = "1.36"
+edition = "2021"
+rust-version = "1.56"
name = "serde_json"
-version = "1.0.93"
+version = "1.0.116"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -36,14 +36,16 @@ repository = "https://github.com/serde-rs/json"
[package.metadata.docs.rs]
features = [
+ "preserve_order",
"raw_value",
"unbounded_depth",
]
-targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = [
"--cfg",
"docsrs",
+ "--generate-link-to-definition",
]
+targets = ["x86_64-unknown-linux-gnu"]
[package.metadata.playground]
features = ["raw_value"]
@@ -52,8 +54,7 @@ features = ["raw_value"]
doc-scrape-examples = false
[dependencies.indexmap]
-version = "1.5.2"
-features = ["std"]
+version = "2.2.1"
optional = true
[dependencies.itoa]
@@ -63,36 +64,36 @@ version = "1.0"
version = "1.0"
[dependencies.serde]
-version = "1.0.100"
+version = "1.0.194"
default-features = false
[dev-dependencies.automod]
-version = "1.0"
+version = "1.0.11"
[dev-dependencies.indoc]
-version = "2.0"
+version = "2.0.2"
[dev-dependencies.ref-cast]
-version = "1.0"
+version = "1.0.18"
[dev-dependencies.rustversion]
-version = "1.0"
+version = "1.0.13"
[dev-dependencies.serde]
-version = "1.0.100"
+version = "1.0.194"
features = ["derive"]
[dev-dependencies.serde_bytes]
-version = "0.11"
+version = "0.11.10"
[dev-dependencies.serde_derive]
-version = "1.0"
+version = "1.0.166"
[dev-dependencies.serde_stacker]
-version = "0.1"
+version = "0.1.8"
[dev-dependencies.trybuild]
-version = "1.0.49"
+version = "1.0.81"
features = ["diff"]
[features]
diff --git a/third_party/rust/serde_json/README.md b/third_party/rust/serde_json/README.md
index d704979247..be70b7b06d 100644
--- a/third_party/rust/serde_json/README.md
+++ b/third_party/rust/serde_json/README.md
@@ -76,7 +76,7 @@ enum Value {
A string of JSON data can be parsed into a `serde_json::Value` by the
[`serde_json::from_str`][from_str] function. There is also
-[`from_slice`][from_slice] for parsing from a byte slice &[u8] and
+[`from_slice`][from_slice] for parsing from a byte slice `&[u8]` and
[`from_reader`][from_reader] for parsing from any `io::Read` like a File or a
TCP stream.
diff --git a/third_party/rust/serde_json/build.rs b/third_party/rust/serde_json/build.rs
index 0e12602e46..dd09e62a3e 100644
--- a/third_party/rust/serde_json/build.rs
+++ b/third_party/rust/serde_json/build.rs
@@ -1,6 +1,4 @@
use std::env;
-use std::process::Command;
-use std::str::{self, FromStr};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
@@ -9,46 +7,11 @@ fn main() {
// src/lexical/math.rs for where this has an effect.
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
match target_arch.as_str() {
- "aarch64" | "mips64" | "powerpc64" | "x86_64" => {
+ "aarch64" | "mips64" | "powerpc64" | "x86_64" | "loongarch64" => {
println!("cargo:rustc-cfg=limb_width_64");
}
_ => {
println!("cargo:rustc-cfg=limb_width_32");
}
}
-
- let minor = match rustc_minor_version() {
- Some(minor) => minor,
- None => return,
- };
-
- // BTreeMap::get_key_value
- // https://blog.rust-lang.org/2019/12/19/Rust-1.40.0.html#additions-to-the-standard-library
- if minor < 40 {
- println!("cargo:rustc-cfg=no_btreemap_get_key_value");
- }
-
- // BTreeMap::remove_entry
- // https://blog.rust-lang.org/2020/07/16/Rust-1.45.0.html#library-changes
- if minor < 45 {
- println!("cargo:rustc-cfg=no_btreemap_remove_entry");
- }
-
- // BTreeMap::retain
- // https://blog.rust-lang.org/2021/06/17/Rust-1.53.0.html#stabilized-apis
- if minor < 53 {
- println!("cargo:rustc-cfg=no_btreemap_retain");
- }
-}
-
-fn rustc_minor_version() -> Option<u32> {
- let rustc = env::var_os("RUSTC")?;
- let output = Command::new(rustc).arg("--version").output().ok()?;
- let version = str::from_utf8(&output.stdout).ok()?;
- let mut pieces = version.split('.');
- if pieces.next() != Some("rustc 1") {
- return None;
- }
- let next = pieces.next()?;
- u32::from_str(next).ok()
}
diff --git a/third_party/rust/serde_json/src/de.rs b/third_party/rust/serde_json/src/de.rs
index 88d0f2624d..c7774f6873 100644
--- a/third_party/rust/serde_json/src/de.rs
+++ b/third_party/rust/serde_json/src/de.rs
@@ -22,6 +22,7 @@ use crate::number::NumberDeserializer;
pub use crate::read::{Read, SliceRead, StrRead};
#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub use crate::read::IoRead;
//////////////////////////////////////////////////////////////////////////////
@@ -209,7 +210,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.disable_recursion_limit = true;
}
- fn peek(&mut self) -> Result<Option<u8>> {
+ pub(crate) fn peek(&mut self) -> Result<Option<u8>> {
self.read.peek()
}
@@ -248,7 +249,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
fn parse_whitespace(&mut self) -> Result<Option<u8>> {
loop {
match tri!(self.peek()) {
- Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') => {
+ Some(b' ' | b'\n' | b'\t' | b'\r') => {
self.eat_char();
}
other => {
@@ -309,9 +310,9 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.fix_position(err)
}
- fn deserialize_number<V>(&mut self, visitor: V) -> Result<V::Value>
+ pub(crate) fn deserialize_number<'any, V>(&mut self, visitor: V) -> Result<V::Value>
where
- V: de::Visitor<'de>,
+ V: de::Visitor<'any>,
{
let peek = match tri!(self.parse_whitespace()) {
Some(b) => b,
@@ -335,6 +336,79 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
}
+ #[cfg(feature = "float_roundtrip")]
+ pub(crate) fn do_deserialize_f32<'any, V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'any>,
+ {
+ self.single_precision = true;
+ let val = self.deserialize_number(visitor);
+ self.single_precision = false;
+ val
+ }
+
+ pub(crate) fn do_deserialize_i128<'any, V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'any>,
+ {
+ let mut buf = String::new();
+
+ match tri!(self.parse_whitespace()) {
+ Some(b'-') => {
+ self.eat_char();
+ buf.push('-');
+ }
+ Some(_) => {}
+ None => {
+ return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+ }
+ };
+
+ tri!(self.scan_integer128(&mut buf));
+
+ let value = match buf.parse() {
+ Ok(int) => visitor.visit_i128(int),
+ Err(_) => {
+ return Err(self.error(ErrorCode::NumberOutOfRange));
+ }
+ };
+
+ match value {
+ Ok(value) => Ok(value),
+ Err(err) => Err(self.fix_position(err)),
+ }
+ }
+
+ pub(crate) fn do_deserialize_u128<'any, V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'any>,
+ {
+ match tri!(self.parse_whitespace()) {
+ Some(b'-') => {
+ return Err(self.peek_error(ErrorCode::NumberOutOfRange));
+ }
+ Some(_) => {}
+ None => {
+ return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+ }
+ }
+
+ let mut buf = String::new();
+ tri!(self.scan_integer128(&mut buf));
+
+ let value = match buf.parse() {
+ Ok(int) => visitor.visit_u128(int),
+ Err(_) => {
+ return Err(self.error(ErrorCode::NumberOutOfRange));
+ }
+ };
+
+ match value {
+ Ok(value) => Ok(value),
+ Err(err) => Err(self.fix_position(err)),
+ }
+ }
+
fn scan_integer128(&mut self, buf: &mut String) -> Result<()> {
match tri!(self.next_char_or_null()) {
b'0' => {
@@ -407,7 +481,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
// try to keep the number as a `u64` until we grow
// too large. At that point, switch to parsing the
// value as a `f64`.
- if overflow!(significand * 10 + digit, u64::max_value()) {
+ if overflow!(significand * 10 + digit, u64::MAX) {
return Ok(ParserNumber::F64(tri!(
self.parse_long_integer(positive, significand),
)));
@@ -459,7 +533,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) {
let digit = (c - b'0') as u64;
- if overflow!(significand * 10 + digit, u64::max_value()) {
+ if overflow!(significand * 10 + digit, u64::MAX) {
let exponent = exponent_before_decimal_point + exponent_after_decimal_point;
return self.parse_decimal_overflow(positive, significand, exponent);
}
@@ -523,7 +597,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.eat_char();
let digit = (c - b'0') as i32;
- if overflow!(exp * 10 + digit, i32::max_value()) {
+ if overflow!(exp * 10 + digit, i32::MAX) {
let zero_significand = significand == 0;
return self.parse_exponent_overflow(positive, zero_significand, positive_exp);
}
@@ -715,7 +789,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.eat_char();
let digit = (c - b'0') as i32;
- if overflow!(exp * 10 + digit, i32::max_value()) {
+ if overflow!(exp * 10 + digit, i32::MAX) {
let zero_significand = self.scratch.iter().all(|&digit| digit == b'0');
return self.parse_exponent_overflow(positive, zero_significand, positive_exp);
}
@@ -860,7 +934,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
if !positive {
buf.push('-');
}
- self.scan_integer(&mut buf)?;
+ tri!(self.scan_integer(&mut buf));
if positive {
if let Ok(unsigned) = buf.parse() {
return Ok(ParserNumber::U64(unsigned));
@@ -913,7 +987,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
fn scan_number(&mut self, buf: &mut String) -> Result<()> {
match tri!(self.peek_or_null()) {
b'.' => self.scan_decimal(buf),
- e @ b'e' | e @ b'E' => self.scan_exponent(e as char, buf),
+ e @ (b'e' | b'E') => self.scan_exponent(e as char, buf),
_ => Ok(()),
}
}
@@ -938,7 +1012,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
match tri!(self.peek_or_null()) {
- e @ b'e' | e @ b'E' => self.scan_exponent(e as char, buf),
+ e @ (b'e' | b'E') => self.scan_exponent(e as char, buf),
_ => Ok(()),
}
}
@@ -1059,7 +1133,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
tri!(self.read.ignore_str());
None
}
- frame @ b'[' | frame @ b'{' => {
+ frame @ (b'[' | b'{') => {
self.scratch.extend(enclosing.take());
self.eat_char();
Some(frame)
@@ -1204,9 +1278,9 @@ impl<'de, R: Read<'de>> Deserializer<R> {
where
V: de::Visitor<'de>,
{
- self.parse_whitespace()?;
+ tri!(self.parse_whitespace());
self.read.begin_raw_buffering();
- self.ignore_value()?;
+ tri!(self.ignore_value());
self.read.end_raw_buffering(visitor)
}
}
@@ -1258,11 +1332,15 @@ static POW10: [f64; 309] = [
macro_rules! deserialize_number {
($method:ident) => {
+ deserialize_number!($method, deserialize_number);
+ };
+
+ ($method:ident, $using:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
- self.deserialize_number(visitor)
+ self.$using(visitor)
}
};
}
@@ -1424,77 +1502,9 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
deserialize_number!(deserialize_f64);
#[cfg(feature = "float_roundtrip")]
- fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- self.single_precision = true;
- let val = self.deserialize_number(visitor);
- self.single_precision = false;
- val
- }
-
- fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- let mut buf = String::new();
-
- match tri!(self.parse_whitespace()) {
- Some(b'-') => {
- self.eat_char();
- buf.push('-');
- }
- Some(_) => {}
- None => {
- return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
- }
- };
-
- tri!(self.scan_integer128(&mut buf));
-
- let value = match buf.parse() {
- Ok(int) => visitor.visit_i128(int),
- Err(_) => {
- return Err(self.error(ErrorCode::NumberOutOfRange));
- }
- };
-
- match value {
- Ok(value) => Ok(value),
- Err(err) => Err(self.fix_position(err)),
- }
- }
-
- fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- match tri!(self.parse_whitespace()) {
- Some(b'-') => {
- return Err(self.peek_error(ErrorCode::NumberOutOfRange));
- }
- Some(_) => {}
- None => {
- return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
- }
- }
-
- let mut buf = String::new();
- tri!(self.scan_integer128(&mut buf));
-
- let value = match buf.parse() {
- Ok(int) => visitor.visit_u128(int),
- Err(_) => {
- return Err(self.error(ErrorCode::NumberOutOfRange));
- }
- };
-
- match value {
- Ok(value) => Ok(value),
- Err(err) => Err(self.fix_position(err)),
- }
- }
+ deserialize_number!(deserialize_f32, do_deserialize_f32);
+ deserialize_number!(deserialize_i128, do_deserialize_i128);
+ deserialize_number!(deserialize_u128, do_deserialize_u128);
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
@@ -2118,24 +2128,47 @@ struct MapKey<'a, R: 'a> {
de: &'a mut Deserializer<R>,
}
-macro_rules! deserialize_integer_key {
- ($method:ident => $visit:ident) => {
+macro_rules! deserialize_numeric_key {
+ ($method:ident) => {
+ fn $method<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.deserialize_number(visitor)
+ }
+ };
+
+ ($method:ident, $delegate:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
self.de.eat_char();
- self.de.scratch.clear();
- let string = tri!(self.de.read.parse_str(&mut self.de.scratch));
- match (string.parse(), string) {
- (Ok(integer), _) => visitor.$visit(integer),
- (Err(_), Reference::Borrowed(s)) => visitor.visit_borrowed_str(s),
- (Err(_), Reference::Copied(s)) => visitor.visit_str(s),
+
+ match tri!(self.de.peek()) {
+ Some(b'0'..=b'9' | b'-') => {}
+ _ => return Err(self.de.error(ErrorCode::ExpectedNumericKey)),
+ }
+
+ let value = tri!(self.de.$delegate(visitor));
+
+ match tri!(self.de.peek()) {
+ Some(b'"') => self.de.eat_char(),
+ _ => return Err(self.de.peek_error(ErrorCode::ExpectedDoubleQuote)),
}
+
+ Ok(value)
}
};
}
+impl<'de, 'a, R> MapKey<'a, R>
+where
+ R: Read<'de>,
+{
+ deserialize_numeric_key!(deserialize_number, deserialize_number);
+}
+
impl<'de, 'a, R> de::Deserializer<'de> for MapKey<'a, R>
where
R: Read<'de>,
@@ -2155,16 +2188,56 @@ where
}
}
- deserialize_integer_key!(deserialize_i8 => visit_i8);
- deserialize_integer_key!(deserialize_i16 => visit_i16);
- deserialize_integer_key!(deserialize_i32 => visit_i32);
- deserialize_integer_key!(deserialize_i64 => visit_i64);
- deserialize_integer_key!(deserialize_i128 => visit_i128);
- deserialize_integer_key!(deserialize_u8 => visit_u8);
- deserialize_integer_key!(deserialize_u16 => visit_u16);
- deserialize_integer_key!(deserialize_u32 => visit_u32);
- deserialize_integer_key!(deserialize_u64 => visit_u64);
- deserialize_integer_key!(deserialize_u128 => visit_u128);
+ deserialize_numeric_key!(deserialize_i8);
+ deserialize_numeric_key!(deserialize_i16);
+ deserialize_numeric_key!(deserialize_i32);
+ deserialize_numeric_key!(deserialize_i64);
+ deserialize_numeric_key!(deserialize_i128, deserialize_i128);
+ deserialize_numeric_key!(deserialize_u8);
+ deserialize_numeric_key!(deserialize_u16);
+ deserialize_numeric_key!(deserialize_u32);
+ deserialize_numeric_key!(deserialize_u64);
+ deserialize_numeric_key!(deserialize_u128, deserialize_u128);
+ #[cfg(not(feature = "float_roundtrip"))]
+ deserialize_numeric_key!(deserialize_f32);
+ #[cfg(feature = "float_roundtrip")]
+ deserialize_numeric_key!(deserialize_f32, deserialize_f32);
+ deserialize_numeric_key!(deserialize_f64);
+
+ fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.de.eat_char();
+
+ let peek = match tri!(self.de.next_char()) {
+ Some(b) => b,
+ None => {
+ return Err(self.de.peek_error(ErrorCode::EofWhileParsingValue));
+ }
+ };
+
+ let value = match peek {
+ b't' => {
+ tri!(self.de.parse_ident(b"rue\""));
+ visitor.visit_bool(true)
+ }
+ b'f' => {
+ tri!(self.de.parse_ident(b"alse\""));
+ visitor.visit_bool(false)
+ }
+ _ => {
+ self.de.scratch.clear();
+ let s = tri!(self.de.read.parse_str(&mut self.de.scratch));
+ Err(de::Error::invalid_type(Unexpected::Str(&s), &visitor))
+ }
+ };
+
+ match value {
+ Ok(value) => Ok(value),
+ Err(err) => Err(self.de.fix_position(err)),
+ }
+ }
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
@@ -2221,8 +2294,8 @@ where
}
forward_to_deserialize_any! {
- bool f32 f64 char str string unit unit_struct seq tuple tuple_struct map
- struct identifier ignored_any
+ char str string unit unit_struct seq tuple tuple_struct map struct
+ identifier ignored_any
}
}
@@ -2318,8 +2391,8 @@ where
fn peek_end_of_value(&mut self) -> Result<()> {
match tri!(self.de.peek()) {
- Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') | Some(b'"') | Some(b'[')
- | Some(b']') | Some(b'{') | Some(b'}') | Some(b',') | Some(b':') | None => Ok(()),
+ Some(b' ' | b'\n' | b'\t' | b'\r' | b'"' | b'[' | b']' | b'{' | b'}' | b',' | b':')
+ | None => Ok(()),
Some(_) => {
let position = self.de.read.peek_position();
Err(Error::syntax(
@@ -2369,7 +2442,7 @@ where
if self_delineated_value {
Ok(value)
} else {
- self.peek_end_of_value().map(|_| value)
+ self.peek_end_of_value().map(|()| value)
}
}
Err(e) => {
@@ -2408,9 +2481,9 @@ where
Ok(value)
}
-/// Deserialize an instance of type `T` from an IO stream of JSON.
+/// Deserialize an instance of type `T` from an I/O stream of JSON.
///
-/// The content of the IO stream is deserialized directly from the stream
+/// The content of the I/O stream is deserialized directly from the stream
/// without being buffered in memory by serde_json.
///
/// When reading from a source against which short reads are not efficient, such
diff --git a/third_party/rust/serde_json/src/error.rs b/third_party/rust/serde_json/src/error.rs
index 1875ef08b0..fbf9eb14e5 100644
--- a/third_party/rust/serde_json/src/error.rs
+++ b/third_party/rust/serde_json/src/error.rs
@@ -9,6 +9,8 @@ use core::str::FromStr;
use serde::{de, ser};
#[cfg(feature = "std")]
use std::error;
+#[cfg(feature = "std")]
+use std::io::ErrorKind;
/// This type represents all possible errors that can occur when serializing or
/// deserializing JSON data.
@@ -36,15 +38,16 @@ impl Error {
/// The first character in the input and any characters immediately
/// following a newline character are in column 1.
///
- /// Note that errors may occur in column 0, for example if a read from an IO
- /// stream fails immediately following a previously read newline character.
+ /// Note that errors may occur in column 0, for example if a read from an
+ /// I/O stream fails immediately following a previously read newline
+ /// character.
pub fn column(&self) -> usize {
self.err.column
}
/// Categorizes the cause of this error.
///
- /// - `Category::Io` - failure to read or write bytes on an IO stream
+ /// - `Category::Io` - failure to read or write bytes on an I/O stream
/// - `Category::Syntax` - input that is not syntactically valid JSON
/// - `Category::Data` - input data that is semantically incorrect
/// - `Category::Eof` - unexpected end of the input data
@@ -61,12 +64,15 @@ impl Error {
| ErrorCode::ExpectedObjectCommaOrEnd
| ErrorCode::ExpectedSomeIdent
| ErrorCode::ExpectedSomeValue
+ | ErrorCode::ExpectedDoubleQuote
| ErrorCode::InvalidEscape
| ErrorCode::InvalidNumber
| ErrorCode::NumberOutOfRange
| ErrorCode::InvalidUnicodeCodePoint
| ErrorCode::ControlCharacterWhileParsingString
| ErrorCode::KeyMustBeAString
+ | ErrorCode::ExpectedNumericKey
+ | ErrorCode::FloatKeyMustBeFinite
| ErrorCode::LoneLeadingSurrogateInHexEscape
| ErrorCode::TrailingComma
| ErrorCode::TrailingCharacters
@@ -76,7 +82,7 @@ impl Error {
}
/// Returns true if this error was caused by a failure to read or write
- /// bytes on an IO stream.
+ /// bytes on an I/O stream.
pub fn is_io(&self) -> bool {
self.classify() == Category::Io
}
@@ -104,12 +110,61 @@ impl Error {
pub fn is_eof(&self) -> bool {
self.classify() == Category::Eof
}
+
+ /// The kind reported by the underlying standard library I/O error, if this
+ /// error was caused by a failure to read or write bytes on an I/O stream.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use serde_json::Value;
+ /// use std::io::{self, ErrorKind, Read};
+ /// use std::process;
+ ///
+ /// struct ReaderThatWillTimeOut<'a>(&'a [u8]);
+ ///
+ /// impl<'a> Read for ReaderThatWillTimeOut<'a> {
+ /// fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ /// if self.0.is_empty() {
+ /// Err(io::Error::new(ErrorKind::TimedOut, "timed out"))
+ /// } else {
+ /// self.0.read(buf)
+ /// }
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let reader = ReaderThatWillTimeOut(br#" {"k": "#);
+ ///
+ /// let _: Value = match serde_json::from_reader(reader) {
+ /// Ok(value) => value,
+ /// Err(error) => {
+ /// if error.io_error_kind() == Some(ErrorKind::TimedOut) {
+ /// // Maybe this application needs to retry certain kinds of errors.
+ ///
+ /// # return;
+ /// } else {
+ /// eprintln!("error: {}", error);
+ /// process::exit(1);
+ /// }
+ /// }
+ /// };
+ /// }
+ /// ```
+ #[cfg(feature = "std")]
+ pub fn io_error_kind(&self) -> Option<ErrorKind> {
+ if let ErrorCode::Io(io_error) = &self.err.code {
+ Some(io_error.kind())
+ } else {
+ None
+ }
+ }
}
/// Categorizes the cause of a `serde_json::Error`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Category {
- /// The error was caused by a failure to read or write bytes on an IO
+ /// The error was caused by a failure to read or write bytes on an I/O
/// stream.
Io,
@@ -134,8 +189,8 @@ pub enum Category {
impl From<Error> for io::Error {
/// Convert a `serde_json::Error` into an `io::Error`.
///
- /// JSON syntax and data errors are turned into `InvalidData` IO errors.
- /// EOF errors are turned into `UnexpectedEof` IO errors.
+ /// JSON syntax and data errors are turned into `InvalidData` I/O errors.
+ /// EOF errors are turned into `UnexpectedEof` I/O errors.
///
/// ```
/// use std::io;
@@ -165,8 +220,8 @@ impl From<Error> for io::Error {
} else {
match j.classify() {
Category::Io => unreachable!(),
- Category::Syntax | Category::Data => io::Error::new(io::ErrorKind::InvalidData, j),
- Category::Eof => io::Error::new(io::ErrorKind::UnexpectedEof, j),
+ Category::Syntax | Category::Data => io::Error::new(ErrorKind::InvalidData, j),
+ Category::Eof => io::Error::new(ErrorKind::UnexpectedEof, j),
}
}
}
@@ -182,7 +237,7 @@ pub(crate) enum ErrorCode {
/// Catchall for syntax error messages
Message(Box<str>),
- /// Some IO error occurred while serializing or deserializing.
+ /// Some I/O error occurred while serializing or deserializing.
Io(io::Error),
/// EOF while parsing a list.
@@ -212,6 +267,9 @@ pub(crate) enum ErrorCode {
/// Expected this character to start a JSON value.
ExpectedSomeValue,
+ /// Expected this character to be a `"`.
+ ExpectedDoubleQuote,
+
/// Invalid hex escape code.
InvalidEscape,
@@ -230,6 +288,12 @@ pub(crate) enum ErrorCode {
/// Object key is not a string.
KeyMustBeAString,
+ /// Contents of key were supposed to be a number.
+ ExpectedNumericKey,
+
+ /// Object key is a non-finite float value.
+ FloatKeyMustBeFinite,
+
/// Lone leading surrogate in hex escape.
LoneLeadingSurrogateInHexEscape,
@@ -296,6 +360,7 @@ impl Display for ErrorCode {
ErrorCode::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"),
ErrorCode::ExpectedSomeIdent => f.write_str("expected ident"),
ErrorCode::ExpectedSomeValue => f.write_str("expected value"),
+ ErrorCode::ExpectedDoubleQuote => f.write_str("expected `\"`"),
ErrorCode::InvalidEscape => f.write_str("invalid escape"),
ErrorCode::InvalidNumber => f.write_str("invalid number"),
ErrorCode::NumberOutOfRange => f.write_str("number out of range"),
@@ -304,6 +369,12 @@ impl Display for ErrorCode {
f.write_str("control character (\\u0000-\\u001F) found while parsing a string")
}
ErrorCode::KeyMustBeAString => f.write_str("key must be a string"),
+ ErrorCode::ExpectedNumericKey => {
+ f.write_str("invalid value: expected key to be a number in quotes")
+ }
+ ErrorCode::FloatKeyMustBeFinite => {
+ f.write_str("float key must be finite (got NaN or +/-inf)")
+ }
ErrorCode::LoneLeadingSurrogateInHexEscape => {
f.write_str("lone leading surrogate in hex escape")
}
@@ -319,7 +390,7 @@ impl serde::de::StdError for Error {
#[cfg(feature = "std")]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match &self.err.code {
- ErrorCode::Io(err) => Some(err),
+ ErrorCode::Io(err) => err.source(),
_ => None,
}
}
@@ -367,11 +438,20 @@ impl de::Error for Error {
#[cold]
fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
- if let de::Unexpected::Unit = unexp {
- Error::custom(format_args!("invalid type: null, expected {}", exp))
- } else {
- Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
- }
+ Error::custom(format_args!(
+ "invalid type: {}, expected {}",
+ JsonUnexpected(unexp),
+ exp,
+ ))
+ }
+
+ #[cold]
+ fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
+ Error::custom(format_args!(
+ "invalid value: {}, expected {}",
+ JsonUnexpected(unexp),
+ exp,
+ ))
}
}
@@ -382,6 +462,22 @@ impl ser::Error for Error {
}
}
+struct JsonUnexpected<'a>(de::Unexpected<'a>);
+
+impl<'a> Display for JsonUnexpected<'a> {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {
+ de::Unexpected::Unit => formatter.write_str("null"),
+ de::Unexpected::Float(value) => write!(
+ formatter,
+ "floating point `{}`",
+ ryu::Buffer::new().format(value),
+ ),
+ unexp => Display::fmt(&unexp, formatter),
+ }
+ }
+}
+
// Parse our own error message that looks like "{} at line {} column {}" to work
// around erased-serde round-tripping the error through de::Error::custom.
fn make_error(mut msg: String) -> Error {
diff --git a/third_party/rust/serde_json/src/features_check/error.rs b/third_party/rust/serde_json/src/features_check/error.rs
deleted file mode 100644
index 22e58235c7..0000000000
--- a/third_party/rust/serde_json/src/features_check/error.rs
+++ /dev/null
@@ -1 +0,0 @@
-"serde_json requires that either `std` (default) or `alloc` feature is enabled"
diff --git a/third_party/rust/serde_json/src/features_check/mod.rs b/third_party/rust/serde_json/src/features_check/mod.rs
deleted file mode 100644
index d12032cef8..0000000000
--- a/third_party/rust/serde_json/src/features_check/mod.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//! Shows a user-friendly compiler error on incompatible selected features.
-
-#[allow(unused_macros)]
-macro_rules! hide_from_rustfmt {
- ($mod:item) => {
- $mod
- };
-}
-
-#[cfg(not(any(feature = "std", feature = "alloc")))]
-hide_from_rustfmt! {
- mod error;
-}
diff --git a/third_party/rust/serde_json/src/io/core.rs b/third_party/rust/serde_json/src/io/core.rs
index 465ab8b249..54c8ddfda4 100644
--- a/third_party/rust/serde_json/src/io/core.rs
+++ b/third_party/rust/serde_json/src/io/core.rs
@@ -9,7 +9,7 @@ pub enum ErrorKind {
Other,
}
-// IO errors can never occur in no-std mode. All our no-std IO implementations
+// I/O errors can never occur in no-std mode. All our no-std I/O implementations
// are infallible.
pub struct Error;
diff --git a/third_party/rust/serde_json/src/lexical/algorithm.rs b/third_party/rust/serde_json/src/lexical/algorithm.rs
index a2cbf18aff..eaa5e7ebc2 100644
--- a/third_party/rust/serde_json/src/lexical/algorithm.rs
+++ b/third_party/rust/serde_json/src/lexical/algorithm.rs
@@ -51,7 +51,10 @@ where
// Compute the product of the power, if it overflows,
// prematurely return early, otherwise, if we didn't overshoot,
// we can get an exact value.
- let value = mantissa.checked_mul(power)?;
+ let value = match mantissa.checked_mul(power) {
+ None => return None,
+ Some(value) => value,
+ };
if value >> mantissa_size != 0 {
None
} else {
diff --git a/third_party/rust/serde_json/src/lexical/bignum.rs b/third_party/rust/serde_json/src/lexical/bignum.rs
index f9551f534f..4fa7eed6dd 100644
--- a/third_party/rust/serde_json/src/lexical/bignum.rs
+++ b/third_party/rust/serde_json/src/lexical/bignum.rs
@@ -3,6 +3,7 @@
//! Big integer type definition.
use super::math::*;
+#[allow(unused_imports)]
use alloc::vec::Vec;
/// Storage for a big integer type.
diff --git a/third_party/rust/serde_json/src/lexical/digit.rs b/third_party/rust/serde_json/src/lexical/digit.rs
index 882aa9eef2..3d150a1afe 100644
--- a/third_party/rust/serde_json/src/lexical/digit.rs
+++ b/third_party/rust/serde_json/src/lexical/digit.rs
@@ -11,5 +11,8 @@ pub(crate) fn to_digit(c: u8) -> Option<u32> {
// Add digit to mantissa.
#[inline]
pub(crate) fn add_digit(value: u64, digit: u32) -> Option<u64> {
- value.checked_mul(10)?.checked_add(digit as u64)
+ match value.checked_mul(10) {
+ None => None,
+ Some(n) => n.checked_add(digit as u64),
+ }
}
diff --git a/third_party/rust/serde_json/src/lexical/errors.rs b/third_party/rust/serde_json/src/lexical/errors.rs
index cad4bd3d58..f4f41cdc5a 100644
--- a/third_party/rust/serde_json/src/lexical/errors.rs
+++ b/third_party/rust/serde_json/src/lexical/errors.rs
@@ -5,8 +5,7 @@
//! This estimates the error in a floating-point representation.
//!
//! This implementation is loosely based off the Golang implementation,
-//! found here:
-//! https://golang.org/src/strconv/atof.go
+//! found here: <https://golang.org/src/strconv/atof.go>
use super::float::*;
use super::num::*;
diff --git a/third_party/rust/serde_json/src/lexical/exponent.rs b/third_party/rust/serde_json/src/lexical/exponent.rs
index 6fc51977ed..5e27de893f 100644
--- a/third_party/rust/serde_json/src/lexical/exponent.rs
+++ b/third_party/rust/serde_json/src/lexical/exponent.rs
@@ -8,8 +8,8 @@
/// the mantissa we do not overflow for comically-long exponents.
#[inline]
fn into_i32(value: usize) -> i32 {
- if value > i32::max_value() as usize {
- i32::max_value()
+ if value > i32::MAX as usize {
+ i32::MAX
} else {
value as i32
}
diff --git a/third_party/rust/serde_json/src/lexical/large_powers32.rs b/third_party/rust/serde_json/src/lexical/large_powers32.rs
index 7991197262..eb8582f5f0 100644
--- a/third_party/rust/serde_json/src/lexical/large_powers32.rs
+++ b/third_party/rust/serde_json/src/lexical/large_powers32.rs
@@ -2,7 +2,7 @@
//! Precalculated large powers for 32-bit limbs.
-/// Large powers (&[u32]) for base5 operations.
+/// Large powers (`&[u32]`) for base5 operations.
const POW5_1: [u32; 1] = [5];
const POW5_2: [u32; 1] = [25];
const POW5_3: [u32; 1] = [625];
diff --git a/third_party/rust/serde_json/src/lexical/large_powers64.rs b/third_party/rust/serde_json/src/lexical/large_powers64.rs
index ee36561088..96554eac1c 100644
--- a/third_party/rust/serde_json/src/lexical/large_powers64.rs
+++ b/third_party/rust/serde_json/src/lexical/large_powers64.rs
@@ -2,7 +2,7 @@
//! Precalculated large powers for 64-bit limbs.
-/// Large powers (&[u64]) for base5 operations.
+/// Large powers (`&[u64]`) for base5 operations.
const POW5_1: [u64; 1] = [5];
const POW5_2: [u64; 1] = [25];
const POW5_3: [u64; 1] = [625];
diff --git a/third_party/rust/serde_json/src/lexical/math.rs b/third_party/rust/serde_json/src/lexical/math.rs
index 37cc1d24ad..d7122bffaf 100644
--- a/third_party/rust/serde_json/src/lexical/math.rs
+++ b/third_party/rust/serde_json/src/lexical/math.rs
@@ -336,7 +336,7 @@ mod small {
pub fn imul(x: &mut Vec<Limb>, y: Limb) {
// Multiply iteratively over all elements, adding the carry each time.
let mut carry: Limb = 0;
- for xi in x.iter_mut() {
+ for xi in &mut *x {
carry = scalar::imul(xi, y, carry);
}
@@ -482,7 +482,7 @@ mod small {
let rshift = bits - n;
let lshift = n;
let mut prev: Limb = 0;
- for xi in x.iter_mut() {
+ for xi in &mut *x {
let tmp = *xi;
*xi <<= lshift;
*xi |= prev >> rshift;
diff --git a/third_party/rust/serde_json/src/lexical/num.rs b/third_party/rust/serde_json/src/lexical/num.rs
index e47e003419..75eee01b81 100644
--- a/third_party/rust/serde_json/src/lexical/num.rs
+++ b/third_party/rust/serde_json/src/lexical/num.rs
@@ -223,7 +223,7 @@ pub trait Float: Number {
const NEGATIVE_INFINITY_BITS: Self::Unsigned;
/// Size of the significand (mantissa) without hidden bit.
const MANTISSA_SIZE: i32;
- /// Bias of the exponet
+ /// Bias of the exponent
const EXPONENT_BIAS: i32;
/// Exponent portion of a denormal float.
const DENORMAL_EXPONENT: i32;
@@ -248,7 +248,6 @@ pub trait Float: Number {
fn from_bits(u: Self::Unsigned) -> Self;
fn to_bits(self) -> Self::Unsigned;
fn is_sign_positive(self) -> bool;
- fn is_sign_negative(self) -> bool;
/// Returns true if the float is a denormal.
#[inline]
@@ -368,11 +367,6 @@ impl Float for f32 {
fn is_sign_positive(self) -> bool {
f32::is_sign_positive(self)
}
-
- #[inline]
- fn is_sign_negative(self) -> bool {
- f32::is_sign_negative(self)
- }
}
impl Float for f64 {
@@ -432,9 +426,4 @@ impl Float for f64 {
fn is_sign_positive(self) -> bool {
f64::is_sign_positive(self)
}
-
- #[inline]
- fn is_sign_negative(self) -> bool {
- f64::is_sign_negative(self)
- }
}
diff --git a/third_party/rust/serde_json/src/lexical/rounding.rs b/third_party/rust/serde_json/src/lexical/rounding.rs
index 6ec1292aa5..6344875227 100644
--- a/third_party/rust/serde_json/src/lexical/rounding.rs
+++ b/third_party/rust/serde_json/src/lexical/rounding.rs
@@ -25,7 +25,7 @@ pub(crate) fn lower_n_mask(n: u64) -> u64 {
debug_assert!(n <= bits, "lower_n_mask() overflow in shl.");
if n == bits {
- u64::max_value()
+ u64::MAX
} else {
(1 << n) - 1
}
diff --git a/third_party/rust/serde_json/src/lib.rs b/third_party/rust/serde_json/src/lib.rs
index 48d0fe2191..eabd169f53 100644
--- a/third_party/rust/serde_json/src/lib.rs
+++ b/third_party/rust/serde_json/src/lib.rs
@@ -55,10 +55,9 @@
//! ```
//!
//! A string of JSON data can be parsed into a `serde_json::Value` by the
-//! [`serde_json::from_str`][from_str] function. There is also
-//! [`from_slice`][from_slice] for parsing from a byte slice &[u8] and
-//! [`from_reader`][from_reader] for parsing from any `io::Read` like a File or
-//! a TCP stream.
+//! [`serde_json::from_str`][from_str] function. There is also [`from_slice`]
+//! for parsing from a byte slice `&[u8]` and [`from_reader`] for parsing from
+//! any `io::Read` like a File or a TCP stream.
//!
//! ```
//! use serde_json::{Result, Value};
@@ -300,7 +299,7 @@
//! [macro]: crate::json
//! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core
-#![doc(html_root_url = "https://docs.rs/serde_json/1.0.93")]
+#![doc(html_root_url = "https://docs.rs/serde_json/1.0.116")]
// Ignored clippy lints
#![allow(
clippy::collapsible_else_if,
@@ -315,18 +314,13 @@
clippy::match_single_binding,
clippy::needless_doctest_main,
clippy::needless_late_init,
- // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8366
- clippy::ptr_arg,
clippy::return_self_not_must_use,
clippy::transmute_ptr_to_ptr,
- clippy::unnecessary_wraps,
- // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
- clippy::unnested_or_patterns,
+ clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133
+ clippy::unnecessary_wraps
)]
// Ignored clippy_pedantic lints
#![allow(
- // buggy
- clippy::iter_not_returning_iterator, // https://github.com/rust-lang/rust-clippy/issues/8285
// Deserializer::from_str, into_iter
clippy::should_implement_trait,
// integer and float ser/de requires these sorts of casts
@@ -338,6 +332,7 @@
clippy::enum_glob_use,
clippy::if_not_else,
clippy::integer_division,
+ clippy::let_underscore_untyped,
clippy::map_err_ignore,
clippy::match_same_arms,
clippy::similar_names,
@@ -361,14 +356,25 @@
clippy::missing_errors_doc,
clippy::must_use_candidate,
)]
+// Restrictions
+#![deny(clippy::question_mark_used)]
#![allow(non_upper_case_globals)]
#![deny(missing_docs)]
-#![cfg_attr(not(feature = "std"), no_std)]
+#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
+#[cfg(not(any(feature = "std", feature = "alloc")))]
+compile_error! {
+ "serde_json requires that either `std` (default) or `alloc` feature is enabled"
+}
+
extern crate alloc;
#[cfg(feature = "std")]
+extern crate std;
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[doc(inline)]
pub use crate::de::from_reader;
#[doc(inline)]
@@ -378,6 +384,7 @@ pub use crate::error::{Error, Result};
#[doc(inline)]
pub use crate::ser::{to_string, to_string_pretty, to_vec, to_vec_pretty};
#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[doc(inline)]
pub use crate::ser::{to_writer, to_writer_pretty, Serializer};
#[doc(inline)]
@@ -407,8 +414,6 @@ pub mod ser;
mod ser;
pub mod value;
-mod features_check;
-
mod io;
#[cfg(feature = "std")]
mod iter;
diff --git a/third_party/rust/serde_json/src/macros.rs b/third_party/rust/serde_json/src/macros.rs
index 5287998b46..e8c6cd2ca4 100644
--- a/third_party/rust/serde_json/src/macros.rs
+++ b/third_party/rust/serde_json/src/macros.rs
@@ -10,7 +10,8 @@
/// "features": [
/// "serde",
/// "json"
-/// ]
+/// ],
+/// "homepage": null
/// }
/// });
/// ```
diff --git a/third_party/rust/serde_json/src/map.rs b/third_party/rust/serde_json/src/map.rs
index 3e8a3814c9..520cd6cf53 100644
--- a/third_party/rust/serde_json/src/map.rs
+++ b/third_party/rust/serde_json/src/map.rs
@@ -11,7 +11,7 @@ use alloc::string::String;
use core::borrow::Borrow;
use core::fmt::{self, Debug};
use core::hash::Hash;
-use core::iter::{FromIterator, FusedIterator};
+use core::iter::FusedIterator;
#[cfg(feature = "preserve_order")]
use core::mem;
use core::ops;
@@ -20,7 +20,7 @@ use serde::de;
#[cfg(not(feature = "preserve_order"))]
use alloc::collections::{btree_map, BTreeMap};
#[cfg(feature = "preserve_order")]
-use indexmap::{self, IndexMap};
+use indexmap::IndexMap;
/// Represents a JSON key/value type.
pub struct Map<K, V> {
@@ -106,7 +106,6 @@ impl Map<String, Value> {
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
#[inline]
- #[cfg(any(feature = "preserve_order", not(no_btreemap_get_key_value)))]
pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&String, &Value)>
where
String: Borrow<Q>,
@@ -131,6 +130,12 @@ impl Map<String, Value> {
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
+ ///
+ /// If serde_json's "preserve_order" is enabled, `.remove(key)` is
+ /// equivalent to [`.swap_remove(key)`][Self::swap_remove], replacing this
+ /// entry's position with the last element. If you need to preserve the
+ /// relative order of the keys in the map, use
+ /// [`.shift_remove(key)`][Self::shift_remove] instead.
#[inline]
pub fn remove<Q>(&mut self, key: &Q) -> Option<Value>
where
@@ -138,7 +143,7 @@ impl Map<String, Value> {
Q: ?Sized + Ord + Eq + Hash,
{
#[cfg(feature = "preserve_order")]
- return self.map.swap_remove(key);
+ return self.swap_remove(key);
#[cfg(not(feature = "preserve_order"))]
return self.map.remove(key);
}
@@ -148,49 +153,94 @@ impl Map<String, Value> {
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
+ ///
+ /// If serde_json's "preserve_order" is enabled, `.remove_entry(key)` is
+ /// equivalent to [`.swap_remove_entry(key)`][Self::swap_remove_entry],
+ /// replacing this entry's position with the last element. If you need to
+ /// preserve the relative order of the keys in the map, use
+ /// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead.
+ #[inline]
pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
where
String: Borrow<Q>,
Q: ?Sized + Ord + Eq + Hash,
{
- #[cfg(any(feature = "preserve_order", not(no_btreemap_remove_entry)))]
+ #[cfg(feature = "preserve_order")]
+ return self.swap_remove_entry(key);
+ #[cfg(not(feature = "preserve_order"))]
return self.map.remove_entry(key);
- #[cfg(all(
- not(feature = "preserve_order"),
- no_btreemap_remove_entry,
- not(no_btreemap_get_key_value),
- ))]
- {
- let (key, _value) = self.map.get_key_value(key)?;
- let key = key.clone();
- let value = self.map.remove::<String>(&key)?;
- Some((key, value))
- }
- #[cfg(all(
- not(feature = "preserve_order"),
- no_btreemap_remove_entry,
- no_btreemap_get_key_value,
- ))]
- {
- use core::ops::{Bound, RangeBounds};
-
- struct Key<'a, Q: ?Sized>(&'a Q);
-
- impl<'a, Q: ?Sized> RangeBounds<Q> for Key<'a, Q> {
- fn start_bound(&self) -> Bound<&Q> {
- Bound::Included(self.0)
- }
- fn end_bound(&self) -> Bound<&Q> {
- Bound::Included(self.0)
- }
- }
+ }
- let mut range = self.map.range(Key(key));
- let (key, _value) = range.next()?;
- let key = key.clone();
- let value = self.map.remove::<String>(&key)?;
- Some((key, value))
- }
+ /// Removes and returns the value corresponding to the key from the map.
+ ///
+ /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
+ /// last element of the map and popping it off. This perturbs the position
+ /// of what used to be the last element!
+ ///
+ /// [`Vec::swap_remove`]: std::vec::Vec::swap_remove
+ #[cfg(feature = "preserve_order")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
+ #[inline]
+ pub fn swap_remove<Q>(&mut self, key: &Q) -> Option<Value>
+ where
+ String: Borrow<Q>,
+ Q: ?Sized + Ord + Eq + Hash,
+ {
+ self.map.swap_remove(key)
+ }
+
+ /// Remove and return the key-value pair.
+ ///
+ /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
+ /// last element of the map and popping it off. This perturbs the position
+ /// of what used to be the last element!
+ ///
+ /// [`Vec::swap_remove`]: std::vec::Vec::swap_remove
+ #[cfg(feature = "preserve_order")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
+ #[inline]
+ pub fn swap_remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
+ where
+ String: Borrow<Q>,
+ Q: ?Sized + Ord + Eq + Hash,
+ {
+ self.map.swap_remove_entry(key)
+ }
+
+ /// Removes and returns the value corresponding to the key from the map.
+ ///
+ /// Like [`Vec::remove`], the entry is removed by shifting all of the
+ /// elements that follow it, preserving their relative order. This perturbs
+ /// the index of all of those elements!
+ ///
+ /// [`Vec::remove`]: std::vec::Vec::remove
+ #[cfg(feature = "preserve_order")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
+ #[inline]
+ pub fn shift_remove<Q>(&mut self, key: &Q) -> Option<Value>
+ where
+ String: Borrow<Q>,
+ Q: ?Sized + Ord + Eq + Hash,
+ {
+ self.map.shift_remove(key)
+ }
+
+ /// Remove and return the key-value pair.
+ ///
+ /// Like [`Vec::remove`], the entry is removed by shifting all of the
+ /// elements that follow it, preserving their relative order. This perturbs
+ /// the index of all of those elements!
+ ///
+ /// [`Vec::remove`]: std::vec::Vec::remove
+ #[cfg(feature = "preserve_order")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
+ #[inline]
+ pub fn shift_remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
+ where
+ String: Borrow<Q>,
+ Q: ?Sized + Ord + Eq + Hash,
+ {
+ self.map.shift_remove_entry(key)
}
/// Moves all elements from other into self, leaving other empty.
@@ -276,7 +326,6 @@ impl Map<String, Value> {
///
/// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)`
/// returns `false`.
- #[cfg(not(no_btreemap_retain))]
#[inline]
pub fn retain<F>(&mut self, f: F)
where
diff --git a/third_party/rust/serde_json/src/number.rs b/third_party/rust/serde_json/src/number.rs
index 21a76411cc..878a3dcb20 100644
--- a/third_party/rust/serde_json/src/number.rs
+++ b/third_party/rust/serde_json/src/number.rs
@@ -82,7 +82,7 @@ impl Number {
/// ```
/// # use serde_json::json;
/// #
- /// let big = i64::max_value() as u64 + 10;
+ /// let big = i64::MAX as u64 + 10;
/// let v = json!({ "a": 64, "b": big, "c": 256.0 });
///
/// assert!(v["a"].is_i64());
@@ -97,7 +97,7 @@ impl Number {
pub fn is_i64(&self) -> bool {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
- N::PosInt(v) => v <= i64::max_value() as u64,
+ N::PosInt(v) => v <= i64::MAX as u64,
N::NegInt(_) => true,
N::Float(_) => false,
}
@@ -177,7 +177,7 @@ impl Number {
/// ```
/// # use serde_json::json;
/// #
- /// let big = i64::max_value() as u64 + 10;
+ /// let big = i64::MAX as u64 + 10;
/// let v = json!({ "a": 64, "b": big, "c": 256.0 });
///
/// assert_eq!(v["a"].as_i64(), Some(64));
@@ -189,7 +189,7 @@ impl Number {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
N::PosInt(n) => {
- if n <= i64::max_value() as u64 {
+ if n <= i64::MAX as u64 {
Some(n as i64)
} else {
None
@@ -279,6 +279,62 @@ impl Number {
}
}
+ /// Returns the exact original JSON representation that this Number was
+ /// parsed from.
+ ///
+ /// For numbers constructed not via parsing, such as by `From<i32>`, returns
+ /// the JSON representation that serde\_json would serialize for this
+ /// number.
+ ///
+ /// ```
+ /// # use serde_json::Number;
+ /// for value in [
+ /// "7",
+ /// "12.34",
+ /// "34e-56789",
+ /// "0.0123456789000000012345678900000001234567890000123456789",
+ /// "343412345678910111213141516171819202122232425262728293034",
+ /// "-343412345678910111213141516171819202122232425262728293031",
+ /// ] {
+ /// let number: Number = serde_json::from_str(value).unwrap();
+ /// assert_eq!(number.as_str(), value);
+ /// }
+ /// ```
+ #[cfg(feature = "arbitrary_precision")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "arbitrary_precision")))]
+ pub fn as_str(&self) -> &str {
+ &self.n
+ }
+
+ pub(crate) fn as_f32(&self) -> Option<f32> {
+ #[cfg(not(feature = "arbitrary_precision"))]
+ match self.n {
+ N::PosInt(n) => Some(n as f32),
+ N::NegInt(n) => Some(n as f32),
+ N::Float(n) => Some(n as f32),
+ }
+ #[cfg(feature = "arbitrary_precision")]
+ self.n.parse::<f32>().ok().filter(|float| float.is_finite())
+ }
+
+ pub(crate) fn from_f32(f: f32) -> Option<Number> {
+ if f.is_finite() {
+ let n = {
+ #[cfg(not(feature = "arbitrary_precision"))]
+ {
+ N::Float(f as f64)
+ }
+ #[cfg(feature = "arbitrary_precision")]
+ {
+ ryu::Buffer::new().format_finite(f).to_owned()
+ }
+ };
+ Some(Number { n })
+ } else {
+ None
+ }
+ }
+
#[cfg(feature = "arbitrary_precision")]
/// Not public API. Only tests use this.
#[doc(hidden)]
@@ -332,8 +388,8 @@ impl Serialize for Number {
{
use serde::ser::SerializeStruct;
- let mut s = serializer.serialize_struct(TOKEN, 1)?;
- s.serialize_field(TOKEN, &self.n)?;
+ let mut s = tri!(serializer.serialize_struct(TOKEN, 1));
+ tri!(s.serialize_field(TOKEN, &self.n));
s.end()
}
}
@@ -377,11 +433,11 @@ impl<'de> Deserialize<'de> for Number {
where
V: de::MapAccess<'de>,
{
- let value = visitor.next_key::<NumberKey>()?;
+ let value = tri!(visitor.next_key::<NumberKey>());
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
- let v: NumberFromString = visitor.next_value()?;
+ let v: NumberFromString = tri!(visitor.next_value());
Ok(v.value)
}
}
@@ -420,7 +476,7 @@ impl<'de> de::Deserialize<'de> for NumberKey {
}
}
- deserializer.deserialize_identifier(FieldVisitor)?;
+ tri!(deserializer.deserialize_identifier(FieldVisitor));
Ok(NumberKey)
}
}
@@ -523,7 +579,7 @@ macro_rules! deserialize_number {
where
V: de::Visitor<'de>,
{
- visitor.$visit(self.n.parse().map_err(|_| invalid_number())?)
+ visitor.$visit(tri!(self.n.parse().map_err(|_| invalid_number())))
}
};
}
diff --git a/third_party/rust/serde_json/src/raw.rs b/third_party/rust/serde_json/src/raw.rs
index 6aa4ffcb61..22d14441ec 100644
--- a/third_party/rust/serde_json/src/raw.rs
+++ b/third_party/rust/serde_json/src/raw.rs
@@ -112,8 +112,8 @@ use serde::ser::{Serialize, SerializeStruct, Serializer};
/// raw_value: Box<RawValue>,
/// }
/// ```
-#[cfg_attr(not(doc), repr(transparent))]
#[cfg_attr(docsrs, doc(cfg(feature = "raw_value")))]
+#[repr(transparent)]
pub struct RawValue {
json: str,
}
@@ -177,11 +177,9 @@ impl RawValue {
/// - the input has no leading or trailing whitespace, and
/// - the input has capacity equal to its length.
pub fn from_string(json: String) -> Result<Box<Self>, Error> {
- {
- let borrowed = crate::from_str::<&Self>(&json)?;
- if borrowed.json.len() < json.len() {
- return Ok(borrowed.to_owned());
- }
+ let borrowed = tri!(crate::from_str::<&Self>(&json));
+ if borrowed.json.len() < json.len() {
+ return Ok(borrowed.to_owned());
}
Ok(Self::from_owned(json.into_boxed_str()))
}
@@ -287,7 +285,7 @@ pub fn to_raw_value<T>(value: &T) -> Result<Box<RawValue>, Error>
where
T: ?Sized + Serialize,
{
- let json_string = crate::to_string(value)?;
+ let json_string = tri!(crate::to_string(value));
Ok(RawValue::from_owned(json_string.into_boxed_str()))
}
@@ -298,8 +296,8 @@ impl Serialize for RawValue {
where
S: Serializer,
{
- let mut s = serializer.serialize_struct(TOKEN, 1)?;
- s.serialize_field(TOKEN, &self.json)?;
+ let mut s = tri!(serializer.serialize_struct(TOKEN, 1));
+ tri!(s.serialize_field(TOKEN, &self.json));
s.end()
}
}
@@ -322,7 +320,7 @@ impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
where
V: MapAccess<'de>,
{
- let value = visitor.next_key::<RawKey>()?;
+ let value = tri!(visitor.next_key::<RawKey>());
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
@@ -352,7 +350,7 @@ impl<'de> Deserialize<'de> for Box<RawValue> {
where
V: MapAccess<'de>,
{
- let value = visitor.next_key::<RawKey>()?;
+ let value = tri!(visitor.next_key::<RawKey>());
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
@@ -392,7 +390,7 @@ impl<'de> Deserialize<'de> for RawKey {
}
}
- deserializer.deserialize_identifier(FieldVisitor)?;
+ tri!(deserializer.deserialize_identifier(FieldVisitor));
Ok(RawKey)
}
}
@@ -529,3 +527,251 @@ impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
}
}
+
+impl<'de> IntoDeserializer<'de, Error> for &'de RawValue {
+ type Deserializer = &'de RawValue;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ self
+ }
+}
+
+impl<'de> Deserializer<'de> for &'de RawValue {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_any(visitor)
+ }
+
+ fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_bool(visitor)
+ }
+
+ fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_i8(visitor)
+ }
+
+ fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_i16(visitor)
+ }
+
+ fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_i32(visitor)
+ }
+
+ fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_i64(visitor)
+ }
+
+ fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_i128(visitor)
+ }
+
+ fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_u8(visitor)
+ }
+
+ fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_u16(visitor)
+ }
+
+ fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_u32(visitor)
+ }
+
+ fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_u64(visitor)
+ }
+
+ fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_u128(visitor)
+ }
+
+ fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_f32(visitor)
+ }
+
+ fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_f64(visitor)
+ }
+
+ fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_char(visitor)
+ }
+
+ fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_str(visitor)
+ }
+
+ fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_string(visitor)
+ }
+
+ fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_bytes(visitor)
+ }
+
+ fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_byte_buf(visitor)
+ }
+
+ fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_option(visitor)
+ }
+
+ fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_unit(visitor)
+ }
+
+ fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_unit_struct(name, visitor)
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ name: &'static str,
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_newtype_struct(name, visitor)
+ }
+
+ fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_seq(visitor)
+ }
+
+ fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_tuple(len, visitor)
+ }
+
+ fn deserialize_tuple_struct<V>(
+ self,
+ name: &'static str,
+ len: usize,
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_tuple_struct(name, len, visitor)
+ }
+
+ fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_map(visitor)
+ }
+
+ fn deserialize_struct<V>(
+ self,
+ name: &'static str,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_struct(name, fields, visitor)
+ }
+
+ fn deserialize_enum<V>(
+ self,
+ name: &'static str,
+ variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_enum(name, variants, visitor)
+ }
+
+ fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_identifier(visitor)
+ }
+
+ fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ crate::Deserializer::from_str(&self.json).deserialize_ignored_any(visitor)
+ }
+}
diff --git a/third_party/rust/serde_json/src/read.rs b/third_party/rust/serde_json/src/read.rs
index fc3a3ca748..a426911c7d 100644
--- a/third_party/rust/serde_json/src/read.rs
+++ b/third_party/rust/serde_json/src/read.rs
@@ -14,11 +14,13 @@ use crate::iter::LineColIterator;
use crate::raw::BorrowedRawDeserializer;
#[cfg(all(feature = "raw_value", feature = "std"))]
use crate::raw::OwnedRawDeserializer;
+#[cfg(all(feature = "raw_value", feature = "std"))]
+use alloc::string::String;
#[cfg(feature = "raw_value")]
use serde::de::Visitor;
/// Trait used by the deserializer for iterating over input. This is manually
-/// "specialized" for iterating over &[u8]. Once feature(specialization) is
+/// "specialized" for iterating over `&[u8]`. Once feature(specialization) is
/// stable we can use actual specialization.
///
/// This trait is sealed and cannot be implemented for types outside of
@@ -81,7 +83,7 @@ pub trait Read<'de>: private::Sealed {
#[doc(hidden)]
fn ignore_str(&mut self) -> Result<()>;
- /// Assumes the previous byte was a hex escape sequnce ('\u') in a string.
+ /// Assumes the previous byte was a hex escape sequence ('\u') in a string.
/// Parses next hexadecimal sequence.
#[doc(hidden)]
fn decode_hex_escape(&mut self) -> Result<u16>;
diff --git a/third_party/rust/serde_json/src/ser.rs b/third_party/rust/serde_json/src/ser.rs
index 80c2deb0c1..3742e0bef4 100644
--- a/third_party/rust/serde_json/src/ser.rs
+++ b/third_party/rust/serde_json/src/ser.rs
@@ -189,12 +189,9 @@ where
#[inline]
fn serialize_bytes(self, value: &[u8]) -> Result<()> {
- use serde::ser::SerializeSeq;
- let mut seq = tri!(self.serialize_seq(Some(value.len())));
- for byte in value {
- tri!(seq.serialize_element(byte));
- }
- seq.end()
+ self.formatter
+ .write_byte_array(&mut self.writer, value)
+ .map_err(Error::io)
}
#[inline]
@@ -439,17 +436,15 @@ where
.formatter
.begin_string(&mut self.writer)
.map_err(Error::io));
- {
- let mut adapter = Adapter {
- writer: &mut self.writer,
- formatter: &mut self.formatter,
- error: None,
- };
- match write!(adapter, "{}", value) {
- Ok(()) => debug_assert!(adapter.error.is_none()),
- Err(fmt::Error) => {
- return Err(Error::io(adapter.error.expect("there should be an error")));
- }
+ let mut adapter = Adapter {
+ writer: &mut self.writer,
+ formatter: &mut self.formatter,
+ error: None,
+ };
+ match write!(adapter, "{}", value) {
+ Ok(()) => debug_assert!(adapter.error.is_none()),
+ Err(fmt::Error) => {
+ return Err(Error::io(adapter.error.expect("there should be an error")));
}
}
self.formatter
@@ -789,6 +784,10 @@ fn key_must_be_a_string() -> Error {
Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)
}
+fn float_key_must_be_finite() -> Error {
+ Error::syntax(ErrorCode::FloatKeyMustBeFinite, 0, 0)
+}
+
impl<'a, W, F> ser::Serializer for MapKeySerializer<'a, W, F>
where
W: io::Write,
@@ -828,8 +827,21 @@ where
type SerializeStruct = Impossible<(), Error>;
type SerializeStructVariant = Impossible<(), Error>;
- fn serialize_bool(self, _value: bool) -> Result<()> {
- Err(key_must_be_a_string())
+ fn serialize_bool(self, value: bool) -> Result<()> {
+ tri!(self
+ .ser
+ .formatter
+ .begin_string(&mut self.ser.writer)
+ .map_err(Error::io));
+ tri!(self
+ .ser
+ .formatter
+ .write_bool(&mut self.ser.writer, value)
+ .map_err(Error::io));
+ self.ser
+ .formatter
+ .end_string(&mut self.ser.writer)
+ .map_err(Error::io)
}
fn serialize_i8(self, value: i8) -> Result<()> {
@@ -1002,12 +1014,46 @@ where
.map_err(Error::io)
}
- fn serialize_f32(self, _value: f32) -> Result<()> {
- Err(key_must_be_a_string())
+ fn serialize_f32(self, value: f32) -> Result<()> {
+ if !value.is_finite() {
+ return Err(float_key_must_be_finite());
+ }
+
+ tri!(self
+ .ser
+ .formatter
+ .begin_string(&mut self.ser.writer)
+ .map_err(Error::io));
+ tri!(self
+ .ser
+ .formatter
+ .write_f32(&mut self.ser.writer, value)
+ .map_err(Error::io));
+ self.ser
+ .formatter
+ .end_string(&mut self.ser.writer)
+ .map_err(Error::io)
}
- fn serialize_f64(self, _value: f64) -> Result<()> {
- Err(key_must_be_a_string())
+ fn serialize_f64(self, value: f64) -> Result<()> {
+ if !value.is_finite() {
+ return Err(float_key_must_be_finite());
+ }
+
+ tri!(self
+ .ser
+ .formatter
+ .begin_string(&mut self.ser.writer)
+ .map_err(Error::io));
+ tri!(self
+ .ser
+ .formatter
+ .write_f64(&mut self.ser.writer, value)
+ .map_err(Error::io));
+ self.ser
+ .formatter
+ .end_string(&mut self.ser.writer)
+ .map_err(Error::io)
}
fn serialize_char(self, value: char) -> Result<()> {
@@ -1043,11 +1089,11 @@ where
Err(key_must_be_a_string())
}
- fn serialize_some<T>(self, _value: &T) -> Result<()>
+ fn serialize_some<T>(self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
- Err(key_must_be_a_string())
+ value.serialize(self)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
@@ -1734,6 +1780,24 @@ pub trait Formatter {
writer.write_all(s)
}
+ /// Writes the representation of a byte array. Formatters can choose whether
+ /// to represent bytes as a JSON array of integers (the default), or some
+ /// JSON string encoding like hex or base64.
+ fn write_byte_array<W>(&mut self, writer: &mut W, value: &[u8]) -> io::Result<()>
+ where
+ W: ?Sized + io::Write,
+ {
+ tri!(self.begin_array(writer));
+ let mut first = true;
+ for byte in value {
+ tri!(self.begin_array_value(writer, first));
+ tri!(self.write_u8(writer, *byte));
+ tri!(self.end_array_value(writer));
+ first = false;
+ }
+ self.end_array(writer)
+ }
+
/// Called before every array. Writes a `[` to the specified
/// writer.
#[inline]
@@ -2062,7 +2126,9 @@ static ESCAPE: [u8; 256] = [
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
];
-/// Serialize the given data structure as JSON into the IO stream.
+/// Serialize the given data structure as JSON into the I/O stream.
+///
+/// Serialization guarantees it only feeds valid UTF-8 sequences to the writer.
///
/// # Errors
///
@@ -2079,9 +2145,11 @@ where
value.serialize(&mut ser)
}
-/// Serialize the given data structure as pretty-printed JSON into the IO
+/// Serialize the given data structure as pretty-printed JSON into the I/O
/// stream.
///
+/// Serialization guarantees it only feeds valid UTF-8 sequences to the writer.
+///
/// # Errors
///
/// Serialization can fail if `T`'s implementation of `Serialize` decides to
diff --git a/third_party/rust/serde_json/src/value/de.rs b/third_party/rust/serde_json/src/value/de.rs
index 9c266d08ae..936725635f 100644
--- a/third_party/rust/serde_json/src/value/de.rs
+++ b/third_party/rust/serde_json/src/value/de.rs
@@ -1,4 +1,4 @@
-use crate::error::Error;
+use crate::error::{Error, ErrorCode};
use crate::map::Map;
use crate::number::Number;
use crate::value::Value;
@@ -106,15 +106,15 @@ impl<'de> Deserialize<'de> for Value {
where
V: MapAccess<'de>,
{
- match visitor.next_key_seed(KeyClassifier)? {
+ match tri!(visitor.next_key_seed(KeyClassifier)) {
#[cfg(feature = "arbitrary_precision")]
Some(KeyClass::Number) => {
- let number: NumberFromString = visitor.next_value()?;
+ let number: NumberFromString = tri!(visitor.next_value());
Ok(Value::Number(number.value))
}
#[cfg(feature = "raw_value")]
Some(KeyClass::RawValue) => {
- let value = visitor.next_value_seed(crate::raw::BoxedFromString)?;
+ let value = tri!(visitor.next_value_seed(crate::raw::BoxedFromString));
crate::from_str(value.get()).map_err(de::Error::custom)
}
Some(KeyClass::Map(first_key)) => {
@@ -219,6 +219,8 @@ impl<'de> serde::Deserializer<'de> for Value {
Value::Number(n) => n.deserialize_any(visitor),
#[cfg(any(feature = "std", feature = "alloc"))]
Value::String(v) => visitor.visit_string(v),
+ #[cfg(not(any(feature = "std", feature = "alloc")))]
+ Value::String(_) => unreachable!(),
Value::Array(v) => visit_array(v, visitor),
Value::Object(v) => visit_object(v, visitor),
}
@@ -482,6 +484,14 @@ impl<'de> IntoDeserializer<'de, Error> for Value {
}
}
+impl<'de> IntoDeserializer<'de, Error> for &'de Value {
+ type Deserializer = Self;
+
+ fn into_deserializer(self) -> Self::Deserializer {
+ self
+ }
+}
+
struct VariantDeserializer {
value: Option<Value>,
}
@@ -1120,18 +1130,30 @@ struct MapKeyDeserializer<'de> {
key: Cow<'de, str>,
}
-macro_rules! deserialize_integer_key {
- ($method:ident => $visit:ident) => {
+macro_rules! deserialize_numeric_key {
+ ($method:ident) => {
+ deserialize_numeric_key!($method, deserialize_number);
+ };
+
+ ($method:ident, $using:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
- match (self.key.parse(), self.key) {
- (Ok(integer), _) => visitor.$visit(integer),
- (Err(_), Cow::Borrowed(s)) => visitor.visit_borrowed_str(s),
- #[cfg(any(feature = "std", feature = "alloc"))]
- (Err(_), Cow::Owned(s)) => visitor.visit_string(s),
+ let mut de = crate::Deserializer::from_str(&self.key);
+
+ match tri!(de.peek()) {
+ Some(b'0'..=b'9' | b'-') => {}
+ _ => return Err(Error::syntax(ErrorCode::ExpectedNumericKey, 0, 0)),
+ }
+
+ let number = tri!(de.$using(visitor));
+
+ if tri!(de.peek()).is_some() {
+ return Err(Error::syntax(ErrorCode::ExpectedNumericKey, 0, 0));
}
+
+ Ok(number)
}
};
}
@@ -1146,16 +1168,38 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
BorrowedCowStrDeserializer::new(self.key).deserialize_any(visitor)
}
- deserialize_integer_key!(deserialize_i8 => visit_i8);
- deserialize_integer_key!(deserialize_i16 => visit_i16);
- deserialize_integer_key!(deserialize_i32 => visit_i32);
- deserialize_integer_key!(deserialize_i64 => visit_i64);
- deserialize_integer_key!(deserialize_i128 => visit_i128);
- deserialize_integer_key!(deserialize_u8 => visit_u8);
- deserialize_integer_key!(deserialize_u16 => visit_u16);
- deserialize_integer_key!(deserialize_u32 => visit_u32);
- deserialize_integer_key!(deserialize_u64 => visit_u64);
- deserialize_integer_key!(deserialize_u128 => visit_u128);
+ deserialize_numeric_key!(deserialize_i8);
+ deserialize_numeric_key!(deserialize_i16);
+ deserialize_numeric_key!(deserialize_i32);
+ deserialize_numeric_key!(deserialize_i64);
+ deserialize_numeric_key!(deserialize_u8);
+ deserialize_numeric_key!(deserialize_u16);
+ deserialize_numeric_key!(deserialize_u32);
+ deserialize_numeric_key!(deserialize_u64);
+ #[cfg(not(feature = "float_roundtrip"))]
+ deserialize_numeric_key!(deserialize_f32);
+ deserialize_numeric_key!(deserialize_f64);
+
+ #[cfg(feature = "float_roundtrip")]
+ deserialize_numeric_key!(deserialize_f32, do_deserialize_f32);
+ deserialize_numeric_key!(deserialize_i128, do_deserialize_i128);
+ deserialize_numeric_key!(deserialize_u128, do_deserialize_u128);
+
+ fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: Visitor<'de>,
+ {
+ if self.key == "true" {
+ visitor.visit_bool(true)
+ } else if self.key == "false" {
+ visitor.visit_bool(false)
+ } else {
+ Err(serde::de::Error::invalid_type(
+ Unexpected::Str(&self.key),
+ &visitor,
+ ))
+ }
+ }
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -1193,8 +1237,8 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
}
forward_to_deserialize_any! {
- bool f32 f64 char str string bytes byte_buf unit unit_struct seq tuple
- tuple_struct map struct identifier ignored_any
+ char str string bytes byte_buf unit unit_struct seq tuple tuple_struct
+ map struct identifier ignored_any
}
}
@@ -1297,6 +1341,8 @@ impl<'de> de::Deserializer<'de> for BorrowedCowStrDeserializer<'de> {
Cow::Borrowed(string) => visitor.visit_borrowed_str(string),
#[cfg(any(feature = "std", feature = "alloc"))]
Cow::Owned(string) => visitor.visit_string(string),
+ #[cfg(not(any(feature = "std", feature = "alloc")))]
+ Cow::Owned(_) => unreachable!(),
}
}
@@ -1327,7 +1373,7 @@ impl<'de> de::EnumAccess<'de> for BorrowedCowStrDeserializer<'de> {
where
T: de::DeserializeSeed<'de>,
{
- let value = seed.deserialize(self)?;
+ let value = tri!(seed.deserialize(self));
Ok((value, UnitOnly))
}
}
diff --git a/third_party/rust/serde_json/src/value/from.rs b/third_party/rust/serde_json/src/value/from.rs
index c5a6a3960b..ed1e3338b0 100644
--- a/third_party/rust/serde_json/src/value/from.rs
+++ b/third_party/rust/serde_json/src/value/from.rs
@@ -4,7 +4,6 @@ use crate::number::Number;
use alloc::borrow::Cow;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
-use core::iter::FromIterator;
macro_rules! from_integer {
($($ty:ident)*) => {
@@ -29,7 +28,8 @@ from_integer! {
}
impl From<f32> for Value {
- /// Convert 32-bit floating point number to `Value`
+ /// Convert 32-bit floating point number to `Value::Number`, or
+ /// `Value::Null` if infinite or NaN.
///
/// # Examples
///
@@ -40,12 +40,13 @@ impl From<f32> for Value {
/// let x: Value = f.into();
/// ```
fn from(f: f32) -> Self {
- From::from(f as f64)
+ Number::from_f32(f).map_or(Value::Null, Value::Number)
}
}
impl From<f64> for Value {
- /// Convert 64-bit floating point number to `Value`
+ /// Convert 64-bit floating point number to `Value::Number`, or
+ /// `Value::Null` if infinite or NaN.
///
/// # Examples
///
@@ -61,7 +62,7 @@ impl From<f64> for Value {
}
impl From<bool> for Value {
- /// Convert boolean to `Value`
+ /// Convert boolean to `Value::Bool`.
///
/// # Examples
///
@@ -77,7 +78,7 @@ impl From<bool> for Value {
}
impl From<String> for Value {
- /// Convert `String` to `Value`
+ /// Convert `String` to `Value::String`.
///
/// # Examples
///
@@ -92,8 +93,8 @@ impl From<String> for Value {
}
}
-impl<'a> From<&'a str> for Value {
- /// Convert string slice to `Value`
+impl From<&str> for Value {
+ /// Convert string slice to `Value::String`.
///
/// # Examples
///
@@ -109,7 +110,7 @@ impl<'a> From<&'a str> for Value {
}
impl<'a> From<Cow<'a, str>> for Value {
- /// Convert copy-on-write string to `Value`
+ /// Convert copy-on-write string to `Value::String`.
///
/// # Examples
///
@@ -134,7 +135,7 @@ impl<'a> From<Cow<'a, str>> for Value {
}
impl From<Number> for Value {
- /// Convert `Number` to `Value`
+ /// Convert `Number` to `Value::Number`.
///
/// # Examples
///
@@ -150,7 +151,7 @@ impl From<Number> for Value {
}
impl From<Map<String, Value>> for Value {
- /// Convert map (with string keys) to `Value`
+ /// Convert map (with string keys) to `Value::Object`.
///
/// # Examples
///
@@ -167,7 +168,7 @@ impl From<Map<String, Value>> for Value {
}
impl<T: Into<Value>> From<Vec<T>> for Value {
- /// Convert a `Vec` to `Value`
+ /// Convert a `Vec` to `Value::Array`.
///
/// # Examples
///
@@ -182,8 +183,8 @@ impl<T: Into<Value>> From<Vec<T>> for Value {
}
}
-impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
- /// Convert a slice to `Value`
+impl<T: Clone + Into<Value>> From<&[T]> for Value {
+ /// Convert a slice to `Value::Array`.
///
/// # Examples
///
@@ -193,13 +194,13 @@ impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
/// let v: &[&str] = &["lorem", "ipsum", "dolor"];
/// let x: Value = v.into();
/// ```
- fn from(f: &'a [T]) -> Self {
+ fn from(f: &[T]) -> Self {
Value::Array(f.iter().cloned().map(Into::into).collect())
}
}
impl<T: Into<Value>> FromIterator<T> for Value {
- /// Convert an iteratable type to a `Value`
+ /// Create a `Value::Array` by collecting an iterator of array elements.
///
/// # Examples
///
@@ -229,7 +230,7 @@ impl<T: Into<Value>> FromIterator<T> for Value {
}
impl<K: Into<String>, V: Into<Value>> FromIterator<(K, V)> for Value {
- /// Convert an iteratable type to a `Value`
+ /// Create a `Value::Object` by collecting an iterator of key-value pairs.
///
/// # Examples
///
@@ -249,7 +250,7 @@ impl<K: Into<String>, V: Into<Value>> FromIterator<(K, V)> for Value {
}
impl From<()> for Value {
- /// Convert `()` to `Value`
+ /// Convert `()` to `Value::Null`.
///
/// # Examples
///
diff --git a/third_party/rust/serde_json/src/value/index.rs b/third_party/rust/serde_json/src/value/index.rs
index c74042b75a..891ca8ef73 100644
--- a/third_party/rust/serde_json/src/value/index.rs
+++ b/third_party/rust/serde_json/src/value/index.rs
@@ -116,7 +116,7 @@ impl Index for String {
}
}
-impl<'a, T> Index for &'a T
+impl<T> Index for &T
where
T: ?Sized + Index,
{
diff --git a/third_party/rust/serde_json/src/value/mod.rs b/third_party/rust/serde_json/src/value/mod.rs
index 470b6b24da..b3f51ea0db 100644
--- a/third_party/rust/serde_json/src/value/mod.rs
+++ b/third_party/rust/serde_json/src/value/mod.rs
@@ -106,6 +106,7 @@ pub use crate::map::Map;
pub use crate::number::Number;
#[cfg(feature = "raw_value")]
+#[cfg_attr(docsrs, doc(cfg(feature = "raw_value")))]
pub use crate::raw::{to_raw_value, RawValue};
/// Represents any valid JSON value.
@@ -182,11 +183,11 @@ impl Debug for Value {
Value::Number(number) => Debug::fmt(number, formatter),
Value::String(string) => write!(formatter, "String({:?})", string),
Value::Array(vec) => {
- formatter.write_str("Array ")?;
+ tri!(formatter.write_str("Array "));
Debug::fmt(vec, formatter)
}
Value::Object(map) => {
- formatter.write_str("Object ")?;
+ tri!(formatter.write_str("Object "));
Debug::fmt(map, formatter)
}
}
@@ -514,6 +515,28 @@ impl Value {
}
}
+ /// If the `Value` is a Number, returns the associated [`Number`]. Returns
+ /// None otherwise.
+ ///
+ /// ```
+ /// # use serde_json::{json, Number};
+ /// #
+ /// let v = json!({ "a": 1, "b": 2.2, "c": -3, "d": "4" });
+ ///
+ /// assert_eq!(v["a"].as_number(), Some(&Number::from(1u64)));
+ /// assert_eq!(v["b"].as_number(), Some(&Number::from_f64(2.2).unwrap()));
+ /// assert_eq!(v["c"].as_number(), Some(&Number::from(-3i64)));
+ ///
+ /// // The string `"4"` is not a number.
+ /// assert_eq!(v["d"].as_number(), None);
+ /// ```
+ pub fn as_number(&self) -> Option<&Number> {
+ match self {
+ Value::Number(number) => Some(number),
+ _ => None,
+ }
+ }
+
/// Returns true if the `Value` is an integer between `i64::MIN` and
/// `i64::MAX`.
///
@@ -889,7 +912,6 @@ mod ser;
/// ```
/// use serde::Serialize;
/// use serde_json::json;
-///
/// use std::error::Error;
///
/// #[derive(Serialize)]
@@ -898,7 +920,7 @@ mod ser;
/// location: String,
/// }
///
-/// fn compare_json_values() -> Result<(), Box<Error>> {
+/// fn compare_json_values() -> Result<(), Box<dyn Error>> {
/// let u = User {
/// fingerprint: "0xF9BA143B95FF6D82".to_owned(),
/// location: "Menlo Park, CA".to_owned(),
diff --git a/third_party/rust/serde_json/src/value/partial_eq.rs b/third_party/rust/serde_json/src/value/partial_eq.rs
index b4ef84c4f3..46c1dbc33b 100644
--- a/third_party/rust/serde_json/src/value/partial_eq.rs
+++ b/third_party/rust/serde_json/src/value/partial_eq.rs
@@ -9,6 +9,13 @@ fn eq_u64(value: &Value, other: u64) -> bool {
value.as_u64().map_or(false, |i| i == other)
}
+fn eq_f32(value: &Value, other: f32) -> bool {
+ match value {
+ Value::Number(n) => n.as_f32().map_or(false, |i| i == other),
+ _ => false,
+ }
+}
+
fn eq_f64(value: &Value, other: f64) -> bool {
value.as_f64().map_or(false, |i| i == other)
}
@@ -27,7 +34,7 @@ impl PartialEq<str> for Value {
}
}
-impl<'a> PartialEq<&'a str> for Value {
+impl PartialEq<&str> for Value {
fn eq(&self, other: &&str) -> bool {
eq_str(self, *other)
}
@@ -39,7 +46,7 @@ impl PartialEq<Value> for str {
}
}
-impl<'a> PartialEq<Value> for &'a str {
+impl PartialEq<Value> for &str {
fn eq(&self, other: &Value) -> bool {
eq_str(other, *self)
}
@@ -90,6 +97,7 @@ macro_rules! partialeq_numeric {
partialeq_numeric! {
eq_i64[i8 i16 i32 i64 isize]
eq_u64[u8 u16 u32 u64 usize]
- eq_f64[f32 f64]
+ eq_f32[f32]
+ eq_f64[f64]
eq_bool[bool]
}
diff --git a/third_party/rust/serde_json/src/value/ser.rs b/third_party/rust/serde_json/src/value/ser.rs
index a29814e92a..e869ae160f 100644
--- a/third_party/rust/serde_json/src/value/ser.rs
+++ b/third_party/rust/serde_json/src/value/ser.rs
@@ -1,12 +1,9 @@
use crate::error::{Error, ErrorCode, Result};
use crate::map::Map;
-use crate::number::Number;
use crate::value::{to_value, Value};
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
-#[cfg(not(feature = "arbitrary_precision"))]
-use core::convert::TryFrom;
use core::fmt::Display;
use core::result;
use serde::ser::{Impossible, Serialize};
@@ -32,6 +29,8 @@ impl Serialize for Value {
}
map.end()
}
+ #[cfg(not(any(feature = "std", feature = "alloc")))]
+ Value::Object(_) => unreachable!(),
}
}
}
@@ -149,13 +148,13 @@ impl serde::Serializer for Serializer {
}
#[inline]
- fn serialize_f32(self, value: f32) -> Result<Value> {
- self.serialize_f64(value as f64)
+ fn serialize_f32(self, float: f32) -> Result<Value> {
+ Ok(Value::from(float))
}
#[inline]
- fn serialize_f64(self, value: f64) -> Result<Value> {
- Ok(Number::from_f64(value).map_or(Value::Null, Value::Number))
+ fn serialize_f64(self, float: f64) -> Result<Value> {
+ Ok(Value::from(float))
}
#[inline]
@@ -452,6 +451,10 @@ fn key_must_be_a_string() -> Error {
Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)
}
+fn float_key_must_be_finite() -> Error {
+ Error::syntax(ErrorCode::FloatKeyMustBeFinite, 0, 0)
+}
+
impl serde::Serializer for MapKeySerializer {
type Ok = String;
type Error = Error;
@@ -482,8 +485,8 @@ impl serde::Serializer for MapKeySerializer {
value.serialize(self)
}
- fn serialize_bool(self, _value: bool) -> Result<String> {
- Err(key_must_be_a_string())
+ fn serialize_bool(self, value: bool) -> Result<String> {
+ Ok(value.to_string())
}
fn serialize_i8(self, value: i8) -> Result<String> {
@@ -518,12 +521,20 @@ impl serde::Serializer for MapKeySerializer {
Ok(value.to_string())
}
- fn serialize_f32(self, _value: f32) -> Result<String> {
- Err(key_must_be_a_string())
+ fn serialize_f32(self, value: f32) -> Result<String> {
+ if value.is_finite() {
+ Ok(ryu::Buffer::new().format_finite(value).to_owned())
+ } else {
+ Err(float_key_must_be_finite())
+ }
}
- fn serialize_f64(self, _value: f64) -> Result<String> {
- Err(key_must_be_a_string())
+ fn serialize_f64(self, value: f64) -> Result<String> {
+ if value.is_finite() {
+ Ok(ryu::Buffer::new().format_finite(value).to_owned())
+ } else {
+ Err(float_key_must_be_finite())
+ }
}
#[inline]
@@ -641,7 +652,7 @@ impl serde::ser::SerializeStruct for SerializeMap {
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { out_value } => {
if key == crate::number::TOKEN {
- *out_value = Some(value.serialize(NumberValueEmitter)?);
+ *out_value = Some(tri!(value.serialize(NumberValueEmitter)));
Ok(())
} else {
Err(invalid_number())
@@ -650,7 +661,7 @@ impl serde::ser::SerializeStruct for SerializeMap {
#[cfg(feature = "raw_value")]
SerializeMap::RawValue { out_value } => {
if key == crate::raw::TOKEN {
- *out_value = Some(value.serialize(RawValueEmitter)?);
+ *out_value = Some(tri!(value.serialize(RawValueEmitter)));
Ok(())
} else {
Err(invalid_raw_value())
diff --git a/third_party/rust/serde_json/tests/lexical.rs b/third_party/rust/serde_json/tests/lexical.rs
index 6e0f07b8c3..368c84478e 100644
--- a/third_party/rust/serde_json/tests/lexical.rs
+++ b/third_party/rust/serde_json/tests/lexical.rs
@@ -9,6 +9,7 @@
clippy::excessive_precision,
clippy::float_cmp,
clippy::if_not_else,
+ clippy::let_underscore_untyped,
clippy::module_name_repetitions,
clippy::needless_late_init,
clippy::shadow_unrelated,
@@ -25,11 +26,6 @@ extern crate alloc;
#[path = "../src/lexical/mod.rs"]
mod lexical;
-mod lib {
- pub use std::vec::Vec;
- pub use std::{cmp, iter, mem, ops};
-}
-
#[path = "lexical/algorithm.rs"]
mod algorithm;
diff --git a/third_party/rust/serde_json/tests/lexical/exponent.rs b/third_party/rust/serde_json/tests/lexical/exponent.rs
index f7a847be38..c109ff07df 100644
--- a/third_party/rust/serde_json/tests/lexical/exponent.rs
+++ b/third_party/rust/serde_json/tests/lexical/exponent.rs
@@ -17,38 +17,20 @@ fn scientific_exponent_test() {
assert_eq!(scientific_exponent(-10, 2, 20), -9);
// Underflow
- assert_eq!(
- scientific_exponent(i32::min_value(), 0, 0),
- i32::min_value()
- );
- assert_eq!(
- scientific_exponent(i32::min_value(), 0, 5),
- i32::min_value()
- );
+ assert_eq!(scientific_exponent(i32::MIN, 0, 0), i32::MIN);
+ assert_eq!(scientific_exponent(i32::MIN, 0, 5), i32::MIN);
// Overflow
- assert_eq!(
- scientific_exponent(i32::max_value(), 0, 0),
- i32::max_value() - 1
- );
- assert_eq!(
- scientific_exponent(i32::max_value(), 5, 0),
- i32::max_value()
- );
+ assert_eq!(scientific_exponent(i32::MAX, 0, 0), i32::MAX - 1);
+ assert_eq!(scientific_exponent(i32::MAX, 5, 0), i32::MAX);
}
#[test]
fn mantissa_exponent_test() {
assert_eq!(mantissa_exponent(10, 5, 0), 5);
assert_eq!(mantissa_exponent(0, 5, 0), -5);
- assert_eq!(
- mantissa_exponent(i32::max_value(), 5, 0),
- i32::max_value() - 5
- );
- assert_eq!(mantissa_exponent(i32::max_value(), 0, 5), i32::max_value());
- assert_eq!(mantissa_exponent(i32::min_value(), 5, 0), i32::min_value());
- assert_eq!(
- mantissa_exponent(i32::min_value(), 0, 5),
- i32::min_value() + 5
- );
+ assert_eq!(mantissa_exponent(i32::MAX, 5, 0), i32::MAX - 5);
+ assert_eq!(mantissa_exponent(i32::MAX, 0, 5), i32::MAX);
+ assert_eq!(mantissa_exponent(i32::MIN, 5, 0), i32::MIN);
+ assert_eq!(mantissa_exponent(i32::MIN, 0, 5), i32::MIN + 5);
}
diff --git a/third_party/rust/serde_json/tests/lexical/parse.rs b/third_party/rust/serde_json/tests/lexical/parse.rs
index 80ca25e772..03ec1a9a63 100644
--- a/third_party/rust/serde_json/tests/lexical/parse.rs
+++ b/third_party/rust/serde_json/tests/lexical/parse.rs
@@ -1,7 +1,7 @@
// Adapted from https://github.com/Alexhuszagh/rust-lexical.
use crate::lexical::num::Float;
-use crate::lexical::parse::{parse_concise_float, parse_truncated_float};
+use crate::lexical::{parse_concise_float, parse_truncated_float};
use core::f64;
use core::fmt::Debug;
diff --git a/third_party/rust/serde_json/tests/map.rs b/third_party/rust/serde_json/tests/map.rs
index ae01969561..538cd16ae0 100644
--- a/third_party/rust/serde_json/tests/map.rs
+++ b/third_party/rust/serde_json/tests/map.rs
@@ -35,7 +35,6 @@ fn test_append() {
assert!(val.is_empty());
}
-#[cfg(not(no_btreemap_retain))]
#[test]
fn test_retain() {
let mut v: Value = from_str(r#"{"b":null,"a":null,"c":null}"#).unwrap();
diff --git a/third_party/rust/serde_json/tests/regression/issue1004.rs b/third_party/rust/serde_json/tests/regression/issue1004.rs
new file mode 100644
index 0000000000..c09fb96108
--- /dev/null
+++ b/third_party/rust/serde_json/tests/regression/issue1004.rs
@@ -0,0 +1,12 @@
+#![cfg(feature = "arbitrary_precision")]
+
+#[test]
+fn test() {
+ let float = 5.55f32;
+ let value = serde_json::to_value(float).unwrap();
+ let json = serde_json::to_string(&value).unwrap();
+
+ // If the f32 were cast to f64 by Value before serialization, then this
+ // would incorrectly serialize as 5.550000190734863.
+ assert_eq!(json, "5.55");
+}
diff --git a/third_party/rust/serde_json/tests/regression/issue520.rs b/third_party/rust/serde_json/tests/regression/issue520.rs
index 9ed367731b..730ecc60a8 100644
--- a/third_party/rust/serde_json/tests/regression/issue520.rs
+++ b/third_party/rust/serde_json/tests/regression/issue520.rs
@@ -1,6 +1,6 @@
#![allow(clippy::float_cmp)]
-use serde_derive::{Serialize, Deserialize};
+use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "type", content = "data")]
diff --git a/third_party/rust/serde_json/tests/regression/issue795.rs b/third_party/rust/serde_json/tests/regression/issue795.rs
index bb82852c54..411e8af5d3 100644
--- a/third_party/rust/serde_json/tests/regression/issue795.rs
+++ b/third_party/rust/serde_json/tests/regression/issue795.rs
@@ -8,7 +8,10 @@ use std::fmt;
#[derive(Debug)]
pub enum Enum {
- Variant { x: u8 },
+ Variant {
+ #[allow(dead_code)]
+ x: u8,
+ },
}
impl<'de> Deserialize<'de> for Enum {
diff --git a/third_party/rust/serde_json/tests/regression/issue845.rs b/third_party/rust/serde_json/tests/regression/issue845.rs
index 56037ae669..7b6564dadb 100644
--- a/third_party/rust/serde_json/tests/regression/issue845.rs
+++ b/third_party/rust/serde_json/tests/regression/issue845.rs
@@ -1,7 +1,6 @@
#![allow(clippy::trait_duplication_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/8757
use serde::{Deserialize, Deserializer};
-use std::convert::TryFrom;
use std::fmt::{self, Display};
use std::marker::PhantomData;
use std::str::FromStr;
@@ -61,6 +60,7 @@ where
#[derive(Deserialize, Debug)]
pub struct Struct {
#[serde(deserialize_with = "deserialize_integer_or_string")]
+ #[allow(dead_code)]
pub i: i64,
}
diff --git a/third_party/rust/serde_json/tests/test.rs b/third_party/rust/serde_json/tests/test.rs
index f62a545e7f..7e6adad76f 100644
--- a/third_party/rust/serde_json/tests/test.rs
+++ b/third_party/rust/serde_json/tests/test.rs
@@ -5,7 +5,9 @@
clippy::derive_partial_eq_without_eq,
clippy::excessive_precision,
clippy::float_cmp,
+ clippy::incompatible_msrv, // https://github.com/rust-lang/rust-clippy/issues/12257
clippy::items_after_statements,
+ clippy::let_underscore_untyped,
clippy::shadow_unrelated,
clippy::too_many_lines,
clippy::unreadable_literal,
@@ -13,9 +15,6 @@
clippy::vec_init_then_push,
clippy::zero_sized_map_values
)]
-#![cfg_attr(feature = "trace-macros", feature(trace_macros))]
-#[cfg(feature = "trace-macros")]
-trace_macros!(true);
#[macro_use]
mod macros;
@@ -32,27 +31,25 @@ use serde_json::{
from_reader, from_slice, from_str, from_value, json, to_string, to_string_pretty, to_value,
to_vec, Deserializer, Number, Value,
};
-use std::collections::hash_map::DefaultHasher;
use std::collections::BTreeMap;
#[cfg(feature = "raw_value")]
use std::collections::HashMap;
use std::fmt::{self, Debug};
+use std::hash::BuildHasher;
+#[cfg(feature = "raw_value")]
use std::hash::{Hash, Hasher};
use std::io;
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::str::FromStr;
-use std::string::ToString;
use std::{f32, f64};
-use std::{i16, i32, i64, i8};
-use std::{u16, u32, u64, u8};
macro_rules! treemap {
() => {
BTreeMap::new()
};
- ($($k:expr => $v:expr),+) => {
+ ($($k:expr => $v:expr),+ $(,)?) => {
{
let mut m = BTreeMap::new();
$(
@@ -159,16 +156,28 @@ fn test_write_f64() {
#[test]
fn test_encode_nonfinite_float_yields_null() {
- let v = to_value(::std::f64::NAN).unwrap();
+ let v = to_value(f64::NAN.copysign(1.0)).unwrap();
+ assert!(v.is_null());
+
+ let v = to_value(f64::NAN.copysign(-1.0)).unwrap();
assert!(v.is_null());
- let v = to_value(::std::f64::INFINITY).unwrap();
+ let v = to_value(f64::INFINITY).unwrap();
assert!(v.is_null());
- let v = to_value(::std::f32::NAN).unwrap();
+ let v = to_value(-f64::INFINITY).unwrap();
assert!(v.is_null());
- let v = to_value(::std::f32::INFINITY).unwrap();
+ let v = to_value(f32::NAN.copysign(1.0)).unwrap();
+ assert!(v.is_null());
+
+ let v = to_value(f32::NAN.copysign(-1.0)).unwrap();
+ assert!(v.is_null());
+
+ let v = to_value(f32::INFINITY).unwrap();
+ assert!(v.is_null());
+
+ let v = to_value(-f32::INFINITY).unwrap();
assert!(v.is_null());
}
@@ -263,7 +272,7 @@ fn test_write_object() {
(
treemap!(
"a".to_string() => true,
- "b".to_string() => false
+ "b".to_string() => false,
),
"{\"a\":true,\"b\":false}",
),
@@ -274,7 +283,7 @@ fn test_write_object() {
treemap![
"a".to_string() => treemap![],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
"{\"a\":{},\"b\":{},\"c\":{}}",
),
@@ -283,10 +292,10 @@ fn test_write_object() {
"a".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
"{\"a\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"b\":{},\"c\":{}}",
),
@@ -296,9 +305,9 @@ fn test_write_object() {
"b".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
"{\"a\":{},\"b\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"c\":{}}",
),
@@ -309,8 +318,8 @@ fn test_write_object() {
"c".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
- ]
+ "c".to_string() => treemap![],
+ ],
],
"{\"a\":{},\"b\":{},\"c\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}}}",
),
@@ -323,7 +332,7 @@ fn test_write_object() {
treemap![
"a".to_string() => treemap![],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
pretty_str!({
"a": {},
@@ -336,10 +345,10 @@ fn test_write_object() {
"a".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
pretty_str!({
"a": {
@@ -363,9 +372,9 @@ fn test_write_object() {
"b".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
- "c".to_string() => treemap![]
+ "c".to_string() => treemap![],
],
pretty_str!({
"a": {},
@@ -390,8 +399,8 @@ fn test_write_object() {
"c".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![]
- ]
+ "c".to_string() => treemap![],
+ ],
],
pretty_str!({
"a": {},
@@ -422,7 +431,7 @@ fn test_write_object() {
(
treemap!(
"a".to_string() => true,
- "b".to_string() => false
+ "b".to_string() => false,
),
pretty_str!( {
"a": true,
@@ -1191,8 +1200,8 @@ fn test_parse_object() {
treemap!(
"a".to_string() => treemap!(
"b".to_string() => 3u64,
- "c".to_string() => 4
- )
+ "c".to_string() => 4,
+ ),
),
)]);
@@ -1368,7 +1377,7 @@ fn test_parse_enum() {
),
treemap!(
"a".to_string() => Animal::Dog,
- "b".to_string() => Animal::Frog("Henry".to_string(), vec![])
+ "b".to_string() => Animal::Frog("Henry".to_string(), vec![]),
),
)]);
}
@@ -1451,7 +1460,6 @@ fn test_serialize_seq_with_no_len() {
where
T: ser::Serialize,
{
- #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -1478,7 +1486,6 @@ fn test_serialize_seq_with_no_len() {
formatter.write_str("array")
}
- #[inline]
fn visit_unit<E>(self) -> Result<MyVec<T>, E>
where
E: de::Error,
@@ -1486,7 +1493,6 @@ fn test_serialize_seq_with_no_len() {
Ok(MyVec(Vec::new()))
}
- #[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<MyVec<T>, V::Error>
where
V: de::SeqAccess<'de>,
@@ -1537,7 +1543,6 @@ fn test_serialize_map_with_no_len() {
K: ser::Serialize + Ord,
V: ser::Serialize,
{
- #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -1565,7 +1570,6 @@ fn test_serialize_map_with_no_len() {
formatter.write_str("map")
}
- #[inline]
fn visit_unit<E>(self) -> Result<MyMap<K, V>, E>
where
E: de::Error,
@@ -1573,7 +1577,6 @@ fn test_serialize_map_with_no_len() {
Ok(MyMap(BTreeMap::new()))
}
- #[inline]
fn visit_map<Visitor>(self, mut visitor: Visitor) -> Result<MyMap<K, V>, Visitor::Error>
where
Visitor: de::MapAccess<'de>,
@@ -1660,22 +1663,11 @@ fn test_deserialize_from_stream() {
}
#[test]
-fn test_serialize_rejects_bool_keys() {
- let map = treemap!(
- true => 2,
- false => 4
- );
-
- let err = to_vec(&map).unwrap_err();
- assert_eq!(err.to_string(), "key must be a string");
-}
-
-#[test]
fn test_serialize_rejects_adt_keys() {
let map = treemap!(
Some("a") => 2,
Some("b") => 4,
- None => 6
+ None => 6,
);
let err = to_vec(&map).unwrap_err();
@@ -1889,23 +1881,41 @@ fn test_integer_key() {
// map with integer keys
let map = treemap!(
1 => 2,
- -1 => 6
+ -1 => 6,
);
let j = r#"{"-1":6,"1":2}"#;
test_encode_ok(&[(&map, j)]);
test_parse_ok(vec![(j, map)]);
- let j = r#"{"x":null}"#;
- test_parse_err::<BTreeMap<i32, ()>>(&[(
- j,
- "invalid type: string \"x\", expected i32 at line 1 column 4",
- )]);
+ test_parse_err::<BTreeMap<i32, ()>>(&[
+ (
+ r#"{"x":null}"#,
+ "invalid value: expected key to be a number in quotes at line 1 column 2",
+ ),
+ (
+ r#"{" 123":null}"#,
+ "invalid value: expected key to be a number in quotes at line 1 column 2",
+ ),
+ (r#"{"123 ":null}"#, "expected `\"` at line 1 column 6"),
+ ]);
+
+ let err = from_value::<BTreeMap<i32, ()>>(json!({" 123":null})).unwrap_err();
+ assert_eq!(
+ err.to_string(),
+ "invalid value: expected key to be a number in quotes",
+ );
+
+ let err = from_value::<BTreeMap<i32, ()>>(json!({"123 ":null})).unwrap_err();
+ assert_eq!(
+ err.to_string(),
+ "invalid value: expected key to be a number in quotes",
+ );
}
#[test]
fn test_integer128_key() {
let map = treemap! {
- 100000000000000000000000000000000000000u128 => ()
+ 100000000000000000000000000000000000000u128 => (),
};
let j = r#"{"100000000000000000000000000000000000000":null}"#;
assert_eq!(to_string(&map).unwrap(), j);
@@ -1913,24 +1923,107 @@ fn test_integer128_key() {
}
#[test]
-fn test_deny_float_key() {
- #[derive(Eq, PartialEq, Ord, PartialOrd)]
+fn test_float_key() {
+ #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone)]
struct Float;
impl Serialize for Float {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- serializer.serialize_f32(1.0)
+ serializer.serialize_f32(1.23)
+ }
+ }
+ impl<'de> Deserialize<'de> for Float {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ f32::deserialize(deserializer).map(|_| Float)
}
}
// map with float key
- let map = treemap!(Float => "x");
+ let map = treemap!(Float => "x".to_owned());
+ let j = r#"{"1.23":"x"}"#;
+
+ test_encode_ok(&[(&map, j)]);
+ test_parse_ok(vec![(j, map)]);
+
+ let j = r#"{"x": null}"#;
+ test_parse_err::<BTreeMap<Float, ()>>(&[(
+ j,
+ "invalid value: expected key to be a number in quotes at line 1 column 2",
+ )]);
+}
+
+#[test]
+fn test_deny_non_finite_f32_key() {
+ // We store float bits so that we can derive Ord, and other traits. In a
+ // real context the code might involve a crate like ordered-float.
+
+ #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone)]
+ struct F32Bits(u32);
+ impl Serialize for F32Bits {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.serialize_f32(f32::from_bits(self.0))
+ }
+ }
+
+ let map = treemap!(F32Bits(f32::INFINITY.to_bits()) => "x".to_owned());
+ assert!(serde_json::to_string(&map).is_err());
+ assert!(serde_json::to_value(map).is_err());
+
+ let map = treemap!(F32Bits(f32::NEG_INFINITY.to_bits()) => "x".to_owned());
+ assert!(serde_json::to_string(&map).is_err());
+ assert!(serde_json::to_value(map).is_err());
+
+ let map = treemap!(F32Bits(f32::NAN.to_bits()) => "x".to_owned());
+ assert!(serde_json::to_string(&map).is_err());
assert!(serde_json::to_value(map).is_err());
}
#[test]
+fn test_deny_non_finite_f64_key() {
+ // We store float bits so that we can derive Ord, and other traits. In a
+ // real context the code might involve a crate like ordered-float.
+
+ #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone)]
+ struct F64Bits(u64);
+ impl Serialize for F64Bits {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.serialize_f64(f64::from_bits(self.0))
+ }
+ }
+
+ let map = treemap!(F64Bits(f64::INFINITY.to_bits()) => "x".to_owned());
+ assert!(serde_json::to_string(&map).is_err());
+ assert!(serde_json::to_value(map).is_err());
+
+ let map = treemap!(F64Bits(f64::NEG_INFINITY.to_bits()) => "x".to_owned());
+ assert!(serde_json::to_string(&map).is_err());
+ assert!(serde_json::to_value(map).is_err());
+
+ let map = treemap!(F64Bits(f64::NAN.to_bits()) => "x".to_owned());
+ assert!(serde_json::to_string(&map).is_err());
+ assert!(serde_json::to_value(map).is_err());
+}
+
+#[test]
+fn test_boolean_key() {
+ let map = treemap!(false => 0, true => 1);
+ let j = r#"{"false":0,"true":1}"#;
+ test_encode_ok(&[(&map, j)]);
+ test_parse_ok(vec![(j, map)]);
+}
+
+#[test]
fn test_borrowed_key() {
let map: BTreeMap<&str, ()> = from_str("{\"borrowed\":null}").unwrap();
let expected = treemap! { "borrowed" => () };
@@ -1953,7 +2046,7 @@ fn test_effectively_string_keys() {
}
let map = treemap! {
Enum::One => 1,
- Enum::Two => 2
+ Enum::Two => 2,
};
let expected = r#"{"One":1,"Two":2}"#;
test_encode_ok(&[(&map, expected)]);
@@ -1963,7 +2056,7 @@ fn test_effectively_string_keys() {
struct Wrapper(String);
let map = treemap! {
Wrapper("zero".to_owned()) => 0,
- Wrapper("one".to_owned()) => 1
+ Wrapper("one".to_owned()) => 1,
};
let expected = r#"{"one":1,"zero":0}"#;
test_encode_ok(&[(&map, expected)]);
@@ -2145,8 +2238,8 @@ fn null_invalid_type() {
#[test]
fn test_integer128() {
- let signed = &[i128::min_value(), -1, 0, 1, i128::max_value()];
- let unsigned = &[0, 1, u128::max_value()];
+ let signed = &[i128::MIN, -1, 0, 1, i128::MAX];
+ let unsigned = &[0, 1, u128::MAX];
for integer128 in signed {
let expected = integer128.to_string();
@@ -2182,8 +2275,8 @@ fn test_integer128() {
#[test]
fn test_integer128_to_value() {
- let signed = &[i128::from(i64::min_value()), i128::from(u64::max_value())];
- let unsigned = &[0, u128::from(u64::max_value())];
+ let signed = &[i128::from(i64::MIN), i128::from(u64::MAX)];
+ let unsigned = &[0, u128::from(u64::MAX)];
for integer128 in signed {
let expected = integer128.to_string();
@@ -2196,7 +2289,7 @@ fn test_integer128_to_value() {
}
if !cfg!(feature = "arbitrary_precision") {
- let err = to_value(u128::from(u64::max_value()) + 1).unwrap_err();
+ let err = to_value(u128::from(u64::MAX) + 1).unwrap_err();
assert_eq!(err.to_string(), "number out of range");
}
}
@@ -2240,6 +2333,8 @@ fn test_raw_value_in_map_key() {
#[repr(transparent)]
struct RawMapKey(RawValue);
+ #[allow(unknown_lints)]
+ #[allow(non_local_definitions)] // false positive: https://github.com/rust-lang/rust/issues/121621
impl<'de> Deserialize<'de> for &'de RawMapKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@@ -2384,25 +2479,27 @@ fn test_value_into_deserializer() {
let mut map = BTreeMap::new();
map.insert("inner", json!({ "string": "Hello World" }));
+ let outer = Outer::deserialize(serde::de::value::MapDeserializer::new(
+ map.iter().map(|(k, v)| (*k, v)),
+ ))
+ .unwrap();
+ assert_eq!(outer.inner.string, "Hello World");
+
let outer = Outer::deserialize(map.into_deserializer()).unwrap();
assert_eq!(outer.inner.string, "Hello World");
}
#[test]
fn hash_positive_and_negative_zero() {
- fn hash(obj: impl Hash) -> u64 {
- let mut hasher = DefaultHasher::new();
- obj.hash(&mut hasher);
- hasher.finish()
- }
+ let rand = std::hash::RandomState::new();
let k1 = serde_json::from_str::<Number>("0.0").unwrap();
let k2 = serde_json::from_str::<Number>("-0.0").unwrap();
if cfg!(feature = "arbitrary_precision") {
assert_ne!(k1, k2);
- assert_ne!(hash(k1), hash(k2));
+ assert_ne!(rand.hash_one(k1), rand.hash_one(k2));
} else {
assert_eq!(k1, k2);
- assert_eq!(hash(k1), hash(k2));
+ assert_eq!(rand.hash_one(k1), rand.hash_one(k2));
}
}
diff --git a/third_party/rust/serde_json/tests/ui/parse_key.stderr b/third_party/rust/serde_json/tests/ui/parse_key.stderr
index f10c21800e..15662dc507 100644
--- a/third_party/rust/serde_json/tests/ui/parse_key.stderr
+++ b/third_party/rust/serde_json/tests/ui/parse_key.stderr
@@ -2,4 +2,4 @@ error[E0609]: no field `s` on type `&'static str`
--> tests/ui/parse_key.rs:4:16
|
4 | json!({ "".s : true });
- | ^
+ | ^ unknown field
diff --git a/third_party/rust/sfv/.cargo-checksum.json b/third_party/rust/sfv/.cargo-checksum.json
index b34463089b..38fd1a552e 100644
--- a/third_party/rust/sfv/.cargo-checksum.json
+++ b/third_party/rust/sfv/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"cf545d5d3384e757f96bffb58f35f1df6236a340e9aac13ae3398a8b9127fe30","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5318787a14e32720b1652f08a24408aaea67fdb5154ceda0f46a6069a0c5e5e3","README.md":"50a8b83ce705a34030957a3502c768674541220a5c2952a965f70c31faaed559","benches/bench.rs":"bbc60db4b542abb3738eba80f5c7c54ac39301ed5e48e2ae2a94cecfdb42e33f","src/lib.rs":"d6c579a4b35078c2f86d6515c957040eb54d9b7ecd65e74f90186d977986b358","src/parser.rs":"1c54f855a5bdd270b9b83b8cb95de670fdf14bce2154f683fba920b447adc94f","src/ref_serializer.rs":"8806ee50e2b2ae466a49788d7e972a47329c0e2c842d669673a152286e81c5d9","src/serializer.rs":"937541e0bdda7f3b043c55eb44ef2c431bdbf636498ce99af4ca47d773790178","src/test_parser.rs":"7a2728e7cbdcb1f3bb42e009045ec0dcfca241316a2aee4905925d4b1ce0bb3a","src/test_serializer.rs":"2419279c9a9a4f48952836d63f3822281c18691d86c146749a573c52a41d6ff0","src/utils.rs":"94c8f79f4747973819b9da2c1a9f6246bf3b5ea7450b376a98eb055f6acf8e73"},"package":"b4f1641177943b4e6faf7622463ae6dfe0f143eb88799e91e2e2e68ede568af5"} \ No newline at end of file
+{"files":{"Cargo.toml":"8ef5c3d39d05e807adfcb2b26639f0735b9c1c99c8373d09d32173786d1ec3ac","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5318787a14e32720b1652f08a24408aaea67fdb5154ceda0f46a6069a0c5e5e3","README.md":"50a8b83ce705a34030957a3502c768674541220a5c2952a965f70c31faaed559","benches/bench.rs":"bbc60db4b542abb3738eba80f5c7c54ac39301ed5e48e2ae2a94cecfdb42e33f","src/lib.rs":"d6c579a4b35078c2f86d6515c957040eb54d9b7ecd65e74f90186d977986b358","src/parser.rs":"1c54f855a5bdd270b9b83b8cb95de670fdf14bce2154f683fba920b447adc94f","src/ref_serializer.rs":"8806ee50e2b2ae466a49788d7e972a47329c0e2c842d669673a152286e81c5d9","src/serializer.rs":"937541e0bdda7f3b043c55eb44ef2c431bdbf636498ce99af4ca47d773790178","src/test_parser.rs":"7a2728e7cbdcb1f3bb42e009045ec0dcfca241316a2aee4905925d4b1ce0bb3a","src/test_serializer.rs":"2419279c9a9a4f48952836d63f3822281c18691d86c146749a573c52a41d6ff0","src/utils.rs":"94c8f79f4747973819b9da2c1a9f6246bf3b5ea7450b376a98eb055f6acf8e73"},"package":"f27daf6ed3fc7ffd5ea3ce9f684fe351c47e50f2fdbb6236e2bad0b440dbe408"} \ No newline at end of file
diff --git a/third_party/rust/sfv/Cargo.toml b/third_party/rust/sfv/Cargo.toml
index 1827d69d5d..8134440708 100644
--- a/third_party/rust/sfv/Cargo.toml
+++ b/third_party/rust/sfv/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "sfv"
-version = "0.9.3"
+version = "0.9.4"
authors = ["Tania Batieva <yalyna.ts@gmail.com>"]
exclude = [
"tests/**",
@@ -38,7 +38,7 @@ harness = false
version = "2.3.2"
[dependencies.indexmap]
-version = "1.8.0"
+version = "2"
[dependencies.rust_decimal]
version = "1.20.0"
diff --git a/third_party/rust/sql-support/.cargo-checksum.json b/third_party/rust/sql-support/.cargo-checksum.json
index 93cef6e94d..ecf062beaf 100644
--- a/third_party/rust/sql-support/.cargo-checksum.json
+++ b/third_party/rust/sql-support/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"812811e5a8e00abe3ec345cd8fd435e27fec7cb8f2e45a0e93e5becf564c46ad","src/conn_ext.rs":"e48e862e47c000c545dcc766fc1889498a8709bee00e240ed68d247b0fbef577","src/debug_tools.rs":"bece2bc3d35379b81ea2f942a0a3e909e0ab0553656505904745548eacaf402a","src/each_chunk.rs":"8aaba842e43b002fbc0fee95d14ce08faa7187b1979c765b2e270cd4802607a5","src/lib.rs":"af704ec04beb6c2c388d4566710e1167b18fb64acb248ccf37a67679daffddb6","src/maybe_cached.rs":"0b18425595055883a98807fbd62ff27a79c18af34e7cb3439f8c3438463ef2dd","src/open_database.rs":"ba290bfb39468e96f9b3ea865e0c13c2cc5a731ea8877a9feb6b1de4f7d666c4","src/repeat.rs":"b4c5ff5d083afba7f9f153f54aba2e6859b78b85c82d48dbd6bd58f67da9e6b9"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"2a0d414052d959098dcb3c22fce0eb008710ab594a6d0e5c58056b2dd497a359","src/conn_ext.rs":"e48e862e47c000c545dcc766fc1889498a8709bee00e240ed68d247b0fbef577","src/debug_tools.rs":"bece2bc3d35379b81ea2f942a0a3e909e0ab0553656505904745548eacaf402a","src/each_chunk.rs":"8aaba842e43b002fbc0fee95d14ce08faa7187b1979c765b2e270cd4802607a5","src/lazy.rs":"a96b4f4ec572538b49cdfa8fee981dcf5143a5f51163fb8a573d3ac128df70f9","src/lib.rs":"b2c120db4928c3e4abdd96405fd4c1016255699bdbc38c8cd60dbd3431fc0a12","src/maybe_cached.rs":"0b18425595055883a98807fbd62ff27a79c18af34e7cb3439f8c3438463ef2dd","src/open_database.rs":"dfc6f68354bf35ee1fc235986e5563e9f8c5cf7920dfe77a9a3d3ad4cfd3723f","src/repeat.rs":"b4c5ff5d083afba7f9f153f54aba2e6859b78b85c82d48dbd6bd58f67da9e6b9"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/sql-support/Cargo.toml b/third_party/rust/sql-support/Cargo.toml
index 0e6137ddbf..c09933b165 100644
--- a/third_party/rust/sql-support/Cargo.toml
+++ b/third_party/rust/sql-support/Cargo.toml
@@ -20,6 +20,7 @@ license = "MPL-2.0"
ffi-support = "0.4"
lazy_static = "1.4"
log = "0.4"
+parking_lot = ">=0.11,<=0.12"
tempfile = "3.1.0"
thiserror = "1.0"
diff --git a/third_party/rust/sql-support/src/lazy.rs b/third_party/rust/sql-support/src/lazy.rs
new file mode 100644
index 0000000000..b22d9c39e3
--- /dev/null
+++ b/third_party/rust/sql-support/src/lazy.rs
@@ -0,0 +1,151 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use crate::open_database::{open_database_with_flags, ConnectionInitializer, Error};
+use interrupt_support::{register_interrupt, SqlInterruptHandle, SqlInterruptScope};
+use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
+use rusqlite::{Connection, OpenFlags};
+use std::{
+ path::{Path, PathBuf},
+ sync::{Arc, Weak},
+};
+
+/// Lazily-loaded database with interruption support
+///
+/// In addition to the [Self::interrupt] method, LazyDb also calls
+/// [interrupt_support::register_interrupt] on any opened database. This means that if
+/// [interrupt_support::shutdown] is called it will interrupt this database if it's open and
+/// in-use.
+pub struct LazyDb<CI> {
+ path: PathBuf,
+ open_flags: OpenFlags,
+ connection_initializer: CI,
+ // Note: if you're going to lock both mutexes at once, make sure to lock the connection mutex
+ // first. Otherwise, you risk creating a deadlock where two threads each hold one of the locks
+ // and is waiting for the other.
+ connection: Mutex<Option<Connection>>,
+ // It's important to use a separate mutex for the interrupt handle, since the whole point is to
+ // interrupt while another thread holds the connection mutex. Since the only mutation is
+ // setting/unsetting the Arc, maybe this could be sped up by using something like
+ // `arc_swap::ArcSwap`, but that seems like overkill for our purposes. This mutex should rarely
+ // be contested and interrupt operations execute quickly.
+ interrupt_handle: Mutex<Option<Arc<SqlInterruptHandle>>>,
+}
+
+impl<CI: ConnectionInitializer> LazyDb<CI> {
+ /// Create a new LazyDb
+ ///
+ /// This does not open the connection and is non-blocking
+ pub fn new(path: &Path, open_flags: OpenFlags, connection_initializer: CI) -> Self {
+ Self {
+ path: path.to_owned(),
+ open_flags,
+ connection_initializer,
+ connection: Mutex::new(None),
+ interrupt_handle: Mutex::new(None),
+ }
+ }
+
+ /// Lock the database mutex and get a connection and interrupt scope.
+ ///
+ /// If the connection is closed, it will be opened.
+ ///
+ /// Calling `lock` again, or calling `close`, from the same thread while the mutex guard is
+ /// still alive will cause a deadlock.
+ pub fn lock(&self) -> Result<(MappedMutexGuard<'_, Connection>, SqlInterruptScope), Error> {
+ // Call get_conn first, then get_scope to ensure we acquire the locks in the correct order
+ let conn = self.get_conn()?;
+ let scope = self.get_scope(&conn)?;
+ Ok((conn, scope))
+ }
+
+ fn get_conn(&self) -> Result<MappedMutexGuard<'_, Connection>, Error> {
+ let mut guard = self.connection.lock();
+ // Open the database if it wasn't opened before. Do this outside of the MutexGuard::map call to simplify the error handling
+ if guard.is_none() {
+ *guard = Some(open_database_with_flags(
+ &self.path,
+ self.open_flags,
+ &self.connection_initializer,
+ )?);
+ };
+ // Use MutexGuard::map to get a Connection rather than Option<Connection>. The unwrap()
+ // call can't fail because of the previous code.
+ Ok(MutexGuard::map(guard, |conn_option| {
+ conn_option.as_mut().unwrap()
+ }))
+ }
+
+ fn get_scope(&self, conn: &Connection) -> Result<SqlInterruptScope, Error> {
+ let mut handle_guard = self.interrupt_handle.lock();
+ let result = match handle_guard.as_ref() {
+ Some(handle) => handle.begin_interrupt_scope(),
+ None => {
+ let handle = Arc::new(SqlInterruptHandle::new(conn));
+ register_interrupt(
+ Arc::downgrade(&handle) as Weak<dyn AsRef<SqlInterruptHandle> + Send + Sync>
+ );
+ handle_guard.insert(handle).begin_interrupt_scope()
+ }
+ };
+ // If we see an Interrupted error when beginning the scope, it means that we're in shutdown
+ // mode.
+ result.map_err(|_| Error::Shutdown)
+ }
+
+ /// Close the database if it's open
+ ///
+ /// Pass interrupt=true to interrupt any in-progress queries before closing the database.
+ ///
+ /// Do not call `close` if you already have a lock on the database in the current thread, as
+ /// this will cause a deadlock.
+ pub fn close(&self, interrupt: bool) {
+ let mut interrupt_handle = self.interrupt_handle.lock();
+ if let Some(handle) = interrupt_handle.as_ref() {
+ if interrupt {
+ handle.interrupt();
+ }
+ *interrupt_handle = None;
+ }
+ // Drop the interrupt handle lock to avoid holding both locks at once.
+ drop(interrupt_handle);
+ *self.connection.lock() = None;
+ }
+
+ /// Interrupt any in-progress queries
+ pub fn interrupt(&self) {
+ if let Some(handle) = self.interrupt_handle.lock().as_ref() {
+ handle.interrupt();
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::open_database::test_utils::TestConnectionInitializer;
+
+ fn open_test_db() -> LazyDb<TestConnectionInitializer> {
+ LazyDb::new(
+ Path::new(":memory:"),
+ OpenFlags::default(),
+ TestConnectionInitializer::new(),
+ )
+ }
+
+ #[test]
+ fn test_interrupt() {
+ let lazy_db = open_test_db();
+ let (_, scope) = lazy_db.lock().unwrap();
+ assert!(!scope.was_interrupted());
+ lazy_db.interrupt();
+ assert!(scope.was_interrupted());
+ }
+
+ #[test]
+ fn interrupt_before_db_is_opened_should_not_fail() {
+ let lazy_db = open_test_db();
+ lazy_db.interrupt();
+ }
+}
diff --git a/third_party/rust/sql-support/src/lib.rs b/third_party/rust/sql-support/src/lib.rs
index 2ece560b4d..5e8dfcea29 100644
--- a/third_party/rust/sql-support/src/lib.rs
+++ b/third_party/rust/sql-support/src/lib.rs
@@ -10,14 +10,16 @@
mod conn_ext;
pub mod debug_tools;
mod each_chunk;
+mod lazy;
mod maybe_cached;
pub mod open_database;
mod repeat;
-pub use crate::conn_ext::*;
-pub use crate::each_chunk::*;
-pub use crate::maybe_cached::*;
-pub use crate::repeat::*;
+pub use conn_ext::*;
+pub use each_chunk::*;
+pub use lazy::*;
+pub use maybe_cached::*;
+pub use repeat::*;
/// In PRAGMA foo='bar', `'bar'` must be a constant string (it cannot be a
/// bound parameter), so we need to escape manually. According to
diff --git a/third_party/rust/sql-support/src/open_database.rs b/third_party/rust/sql-support/src/open_database.rs
index d92a94a9ed..9096b796a3 100644
--- a/third_party/rust/sql-support/src/open_database.rs
+++ b/third_party/rust/sql-support/src/open_database.rs
@@ -46,6 +46,8 @@ pub enum Error {
SqlError(rusqlite::Error),
#[error("Failed to recover a corrupt database due to an error deleting the file: {0}")]
RecoveryError(std::io::Error),
+ #[error("In shutdown mode")]
+ Shutdown,
}
impl From<rusqlite::Error> for Error {
@@ -241,99 +243,28 @@ fn set_schema_version(conn: &Connection, version: u32) -> Result<()> {
// our other crates.
pub mod test_utils {
use super::*;
- use std::path::PathBuf;
+ use std::{cell::RefCell, collections::HashSet, path::PathBuf};
use tempfile::TempDir;
- // Database file that we can programatically run upgrades on
- //
- // We purposefully don't keep a connection to the database around to force upgrades to always
- // run against a newly opened DB, like they would in the real world. See #4106 for
- // details.
- pub struct MigratedDatabaseFile<CI: ConnectionInitializer> {
- // Keep around a TempDir to ensure the database file stays around until this struct is
- // dropped
- _tempdir: TempDir,
- pub connection_initializer: CI,
- pub path: PathBuf,
+ pub struct TestConnectionInitializer {
+ pub calls: RefCell<Vec<&'static str>>,
+ pub buggy_v3_upgrade: bool,
}
- impl<CI: ConnectionInitializer> MigratedDatabaseFile<CI> {
- pub fn new(connection_initializer: CI, init_sql: &str) -> Self {
- Self::new_with_flags(connection_initializer, init_sql, OpenFlags::default())
- }
-
- pub fn new_with_flags(
- connection_initializer: CI,
- init_sql: &str,
- open_flags: OpenFlags,
- ) -> Self {
- let tempdir = tempfile::tempdir().unwrap();
- let path = tempdir.path().join(Path::new("db.sql"));
- let conn = Connection::open_with_flags(&path, open_flags).unwrap();
- conn.execute_batch(init_sql).unwrap();
- Self {
- _tempdir: tempdir,
- connection_initializer,
- path,
- }
- }
-
- /// Attempt to run all upgrades up to a specific version.
- ///
- /// This will result in a panic if an upgrade fails to run.
- pub fn upgrade_to(&self, version: u32) {
- let mut conn = self.open();
- let tx = conn.transaction().unwrap();
- let mut current_version = get_schema_version(&tx).unwrap();
- while current_version < version {
- self.connection_initializer
- .upgrade_from(&tx, current_version)
- .unwrap();
- current_version += 1;
- }
- set_schema_version(&tx, current_version).unwrap();
- self.connection_initializer.finish(&tx).unwrap();
- tx.commit().unwrap();
- }
-
- /// Attempt to run all upgrades
- ///
- /// This will result in a panic if an upgrade fails to run.
- pub fn run_all_upgrades(&self) {
- let current_version = get_schema_version(&self.open()).unwrap();
- for version in current_version..CI::END_VERSION {
- self.upgrade_to(version + 1);
- }
- }
-
- pub fn open(&self) -> Connection {
- Connection::open(&self.path).unwrap()
+ impl Default for TestConnectionInitializer {
+ fn default() -> Self {
+ Self::new()
}
}
-}
-
-#[cfg(test)]
-mod test {
- use super::test_utils::MigratedDatabaseFile;
- use super::*;
- use std::cell::RefCell;
- use std::io::Write;
-
- struct TestConnectionInitializer {
- pub calls: RefCell<Vec<&'static str>>,
- pub buggy_v3_upgrade: bool,
- }
impl TestConnectionInitializer {
pub fn new() -> Self {
- let _ = env_logger::try_init();
Self {
calls: RefCell::new(Vec::new()),
buggy_v3_upgrade: false,
}
}
pub fn new_with_buggy_logic() -> Self {
- let _ = env_logger::try_init();
Self {
calls: RefCell::new(Vec::new()),
buggy_v3_upgrade: true,
@@ -427,6 +358,123 @@ mod test {
}
}
+ // Database file that we can programatically run upgrades on
+ //
+ // We purposefully don't keep a connection to the database around to force upgrades to always
+ // run against a newly opened DB, like they would in the real world. See #4106 for
+ // details.
+ pub struct MigratedDatabaseFile<CI: ConnectionInitializer> {
+ // Keep around a TempDir to ensure the database file stays around until this struct is
+ // dropped
+ _tempdir: TempDir,
+ pub connection_initializer: CI,
+ pub path: PathBuf,
+ }
+
+ impl<CI: ConnectionInitializer> MigratedDatabaseFile<CI> {
+ pub fn new(connection_initializer: CI, init_sql: &str) -> Self {
+ Self::new_with_flags(connection_initializer, init_sql, OpenFlags::default())
+ }
+
+ pub fn new_with_flags(
+ connection_initializer: CI,
+ init_sql: &str,
+ open_flags: OpenFlags,
+ ) -> Self {
+ let tempdir = tempfile::tempdir().unwrap();
+ let path = tempdir.path().join(Path::new("db.sql"));
+ let conn = Connection::open_with_flags(&path, open_flags).unwrap();
+ conn.execute_batch(init_sql).unwrap();
+ Self {
+ _tempdir: tempdir,
+ connection_initializer,
+ path,
+ }
+ }
+
+ /// Attempt to run all upgrades up to a specific version.
+ ///
+ /// This will result in a panic if an upgrade fails to run.
+ pub fn upgrade_to(&self, version: u32) {
+ let mut conn = self.open();
+ let tx = conn.transaction().unwrap();
+ let mut current_version = get_schema_version(&tx).unwrap();
+ while current_version < version {
+ self.connection_initializer
+ .upgrade_from(&tx, current_version)
+ .unwrap();
+ current_version += 1;
+ }
+ set_schema_version(&tx, current_version).unwrap();
+ self.connection_initializer.finish(&tx).unwrap();
+ tx.commit().unwrap();
+ }
+
+ /// Attempt to run all upgrades
+ ///
+ /// This will result in a panic if an upgrade fails to run.
+ pub fn run_all_upgrades(&self) {
+ let current_version = get_schema_version(&self.open()).unwrap();
+ for version in current_version..CI::END_VERSION {
+ self.upgrade_to(version + 1);
+ }
+ }
+
+ pub fn assert_schema_matches_new_database(&self) {
+ let db = self.open();
+ let new_db = open_memory_database(&self.connection_initializer).unwrap();
+ let table_names = get_table_names(&db);
+ let new_db_table_names = get_table_names(&new_db);
+ let extra_tables = Vec::from_iter(table_names.difference(&new_db_table_names));
+ if !extra_tables.is_empty() {
+ panic!("Extra tables not present in new database: {extra_tables:?}");
+ }
+ let new_db_extra_tables = Vec::from_iter(new_db_table_names.difference(&table_names));
+ if !new_db_extra_tables.is_empty() {
+ panic!("Extra tables only present in new database: {new_db_extra_tables:?}");
+ }
+
+ for table_name in table_names {
+ assert_eq!(
+ get_table_sql(&db, &table_name),
+ get_table_sql(&new_db, &table_name),
+ "sql differs for table: {table_name}",
+ );
+ }
+ }
+
+ pub fn open(&self) -> Connection {
+ Connection::open(&self.path).unwrap()
+ }
+ }
+
+ fn get_table_names(conn: &Connection) -> HashSet<String> {
+ conn.query_rows_and_then(
+ "SELECT name FROM sqlite_master WHERE type='table'",
+ (),
+ |row| row.get(0),
+ )
+ .unwrap()
+ .into_iter()
+ .collect()
+ }
+
+ fn get_table_sql(conn: &Connection, table_name: &str) -> String {
+ conn.query_row_and_then(
+ "SELECT sql FROM sqlite_master WHERE name = ? AND type='table'",
+ (&table_name,),
+ |row| row.get::<_, String>(0),
+ )
+ .unwrap()
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::test_utils::{MigratedDatabaseFile, TestConnectionInitializer};
+ use super::*;
+ use std::io::Write;
+
// A special schema used to test the upgrade that forces the database to be
// replaced.
static INIT_V1: &str = "
diff --git a/third_party/rust/suggest/.cargo-checksum.json b/third_party/rust/suggest/.cargo-checksum.json
index 120a503f29..8ead78a91c 100644
--- a/third_party/rust/suggest/.cargo-checksum.json
+++ b/third_party/rust/suggest/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"05e4d7f7b3649a3e3fa441c4af53a633d18f20bb04fd761ed33fc9d461fd0dee","README.md":"fb72d0028586cab1421b853ef529d7ce78ad7316818b7733a4f3488b0fba67f7","benches/benchmark_all.rs":"c2343c9197b6d9ccb0798d7701b1b0d2569d494dd31a975d21d7ec6f26e32879","build.rs":"78780c5cccfe22c3ff4198624b9e188559c437c3e6fa1c8bb66548eee6aa66bf","src/benchmarks/README.md":"ee6d50df2c31cfd80a5bc047011b518dcf57f1ef928a811bb770f1a09f41b3de","src/benchmarks/client.rs":"5d5db3f6e132654c06532feba15f98576122f6b9572ab5fa27b0c67d5b39ecb6","src/benchmarks/ingest.rs":"1ffdc403fb945ea0b58353df9773ba45ab0e9082d61dd5330ad49fad8cbb5d9f","src/benchmarks/mod.rs":"fe1898ba4d783213525da10d92858ee84cebfd22749bad7aeb461d338fe5504a","src/bin/debug_ingestion_sizes.rs":"ce6e810be7b3fc19e826d75b622b82cfab5a1a99397a6d0833c2c4eebff2d364","src/config.rs":"206ae9dc768c755649cb0c88a7b1fc3c926c715441784f61e9dc06a8a02fc568","src/db.rs":"734f5fd9f36f03c07a508a9a353872b81107f5fe09f27294ba27d7e1249e3988","src/error.rs":"f563210a6c050d98ec85e0f6d9401e7373bfb816e865e8edabbabb23d848ba13","src/keyword.rs":"988d0ab021c0df19cfd3c519df7d37f606bf984cd14d0efca4e5a7aff88344dd","src/lib.rs":"91ebbe0e1ffb99eefde204f81bc6bb199b4941976347baf1f132fd0ede20479c","src/pocket.rs":"1316668840ec9b4ea886223921dc9d3b5a1731d1a5206c0b1089f2a6c45c1b7b","src/provider.rs":"fe76f19a223f5cac056c7d48525087ca2c26bf0629b0e11b1f8dc98d165c8bb2","src/rs.rs":"e3eabde58c859ebe1154bf8da56ca134ace135934e3f280acc8186b4204399b3","src/schema.rs":"8b21006940e872658d722b52ba171280c96789eecf614b837d8cdbc9153ab576","src/store.rs":"413779074db3ce4589c31cd4fb0a050d44d1cbad1df3c94101d03e98efdf09cb","src/suggest.udl":"de50ea5c7ece0ae0ff4798979e0e12a5227b42bf024d48b6f585ea30a5133eb3","src/suggestion.rs":"f31227779d13d1b03a622e08a417ceba4afb161885a01c2bc87a6a652b5e8be5","src/yelp.rs":"9c0dc02a994cc05df524aa4ef337d10f575d1891259193b6419fed6fe279cb54","uniffi.toml":"f26317442ddb5b3281245bef6e60ffcb78bb95d29fe4a351a56dbb88d4ec8aab"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"05e4d7f7b3649a3e3fa441c4af53a633d18f20bb04fd761ed33fc9d461fd0dee","README.md":"fb72d0028586cab1421b853ef529d7ce78ad7316818b7733a4f3488b0fba67f7","benches/benchmark_all.rs":"c2343c9197b6d9ccb0798d7701b1b0d2569d494dd31a975d21d7ec6f26e32879","build.rs":"78780c5cccfe22c3ff4198624b9e188559c437c3e6fa1c8bb66548eee6aa66bf","src/benchmarks/README.md":"ee6d50df2c31cfd80a5bc047011b518dcf57f1ef928a811bb770f1a09f41b3de","src/benchmarks/client.rs":"4b2125031d740ca1ab468e76bbea777ac0bc4cc221b03b7bc2da773bed61dac5","src/benchmarks/ingest.rs":"1ffdc403fb945ea0b58353df9773ba45ab0e9082d61dd5330ad49fad8cbb5d9f","src/benchmarks/mod.rs":"fe1898ba4d783213525da10d92858ee84cebfd22749bad7aeb461d338fe5504a","src/bin/debug_ingestion_sizes.rs":"ce6e810be7b3fc19e826d75b622b82cfab5a1a99397a6d0833c2c4eebff2d364","src/config.rs":"206ae9dc768c755649cb0c88a7b1fc3c926c715441784f61e9dc06a8a02fc568","src/db.rs":"a4e18b9f45e0473ea64b5ecdf6d1d67e0519f9629d495c157b0bd1b47c3e2f4f","src/error.rs":"f563210a6c050d98ec85e0f6d9401e7373bfb816e865e8edabbabb23d848ba13","src/keyword.rs":"988d0ab021c0df19cfd3c519df7d37f606bf984cd14d0efca4e5a7aff88344dd","src/lib.rs":"18f988eb49626c6e186c8bc65a51b4a40d796f36d3de8905506f76c6e5e876cd","src/pocket.rs":"1316668840ec9b4ea886223921dc9d3b5a1731d1a5206c0b1089f2a6c45c1b7b","src/provider.rs":"fe76f19a223f5cac056c7d48525087ca2c26bf0629b0e11b1f8dc98d165c8bb2","src/rs.rs":"e3eabde58c859ebe1154bf8da56ca134ace135934e3f280acc8186b4204399b3","src/schema.rs":"88ff3ae6b652fa5a5cff4dc504d11a7fc33f1b2ee9716b970f646d9f9ca90ab7","src/store.rs":"aad193774eecec739a7debd1c9e4fd46df384e7a524203e5e5f0354b93f73c1c","src/suggest.udl":"bfa653aa88c954860a9728a597daad8f4a7db8c81bc156725bf801f7cddf8459","src/suggestion.rs":"f31227779d13d1b03a622e08a417ceba4afb161885a01c2bc87a6a652b5e8be5","src/yelp.rs":"9c0dc02a994cc05df524aa4ef337d10f575d1891259193b6419fed6fe279cb54","uniffi.toml":"f26317442ddb5b3281245bef6e60ffcb78bb95d29fe4a351a56dbb88d4ec8aab"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/suggest/src/benchmarks/client.rs b/third_party/rust/suggest/src/benchmarks/client.rs
index f5a21fd9cc..713bd7752b 100644
--- a/third_party/rust/suggest/src/benchmarks/client.rs
+++ b/third_party/rust/suggest/src/benchmarks/client.rs
@@ -22,6 +22,7 @@ impl RemoteSettingsWarmUpClient {
pub fn new() -> Self {
Self {
client: Client::new(RemoteSettingsConfig {
+ server: None,
server_url: None,
bucket_name: None,
collection_name: crate::rs::REMOTE_SETTINGS_COLLECTION.into(),
diff --git a/third_party/rust/suggest/src/db.rs b/third_party/rust/suggest/src/db.rs
index 0412c50d8f..6b6603ab71 100644
--- a/third_party/rust/suggest/src/db.rs
+++ b/third_party/rust/suggest/src/db.rs
@@ -188,6 +188,12 @@ impl<'a> SuggestDao<'a> {
//
// These methods implement CRUD operations
+ pub fn suggestions_table_empty(&self) -> Result<bool> {
+ Ok(self
+ .conn
+ .query_one::<bool>("SELECT NOT EXISTS (SELECT 1 FROM suggestions)")?)
+ }
+
/// Fetches suggestions that match the given query from the database.
pub fn fetch_suggestions(&self, query: &SuggestionQuery) -> Result<Vec<Suggestion>> {
let unique_providers = query.providers.iter().collect::<HashSet<_>>();
diff --git a/third_party/rust/suggest/src/lib.rs b/third_party/rust/suggest/src/lib.rs
index 15746614d0..93b456b8b4 100644
--- a/third_party/rust/suggest/src/lib.rs
+++ b/third_party/rust/suggest/src/lib.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-use remote_settings::RemoteSettingsConfig;
+use remote_settings::{RemoteSettingsConfig, RemoteSettingsServer};
#[cfg(feature = "benchmark_api")]
pub mod benchmarks;
mod config;
diff --git a/third_party/rust/suggest/src/schema.rs b/third_party/rust/suggest/src/schema.rs
index b304363de5..76a0deed39 100644
--- a/third_party/rust/suggest/src/schema.rs
+++ b/third_party/rust/suggest/src/schema.rs
@@ -15,118 +15,118 @@ use sql_support::open_database::{self, ConnectionInitializer};
/// [`SuggestConnectionInitializer::upgrade_from`].
/// a. If suggestions should be re-ingested after the migration, call `clear_database()` inside
/// the migration.
-pub const VERSION: u32 = 18;
+pub const VERSION: u32 = 19;
/// The current Suggest database schema.
pub const SQL: &str = "
- CREATE TABLE meta(
- key TEXT PRIMARY KEY,
- value NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE keywords(
- keyword TEXT NOT NULL,
- suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
- full_keyword_id INTEGER NULL REFERENCES full_keywords(id) ON DELETE SET NULL,
- rank INTEGER NOT NULL,
- PRIMARY KEY (keyword, suggestion_id)
- ) WITHOUT ROWID;
-
- -- full keywords are what we display to the user when a (partial) keyword matches
- -- The FK to suggestion_id makes it so full keywords get deleted when the parent suggestion is deleted.
- CREATE TABLE full_keywords(
- id INTEGER PRIMARY KEY,
- suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
- full_keyword TEXT NOT NULL
- );
-
- CREATE TABLE prefix_keywords(
- keyword_prefix TEXT NOT NULL,
- keyword_suffix TEXT NOT NULL DEFAULT '',
- confidence INTEGER NOT NULL DEFAULT 0,
- rank INTEGER NOT NULL,
- suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
- PRIMARY KEY (keyword_prefix, keyword_suffix, suggestion_id)
- ) WITHOUT ROWID;
-
- CREATE UNIQUE INDEX keywords_suggestion_id_rank ON keywords(suggestion_id, rank);
-
- CREATE TABLE suggestions(
- id INTEGER PRIMARY KEY,
- record_id TEXT NOT NULL,
- provider INTEGER NOT NULL,
- title TEXT NOT NULL,
- url TEXT NOT NULL,
- score REAL NOT NULL
- );
-
- CREATE TABLE amp_custom_details(
- suggestion_id INTEGER PRIMARY KEY,
- advertiser TEXT NOT NULL,
- block_id INTEGER NOT NULL,
- iab_category TEXT NOT NULL,
- impression_url TEXT NOT NULL,
- click_url TEXT NOT NULL,
- icon_id TEXT NOT NULL,
- FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
- );
-
- CREATE TABLE wikipedia_custom_details(
- suggestion_id INTEGER PRIMARY KEY REFERENCES suggestions(id) ON DELETE CASCADE,
- icon_id TEXT NOT NULL
- );
-
- CREATE TABLE amo_custom_details(
- suggestion_id INTEGER PRIMARY KEY,
- description TEXT NOT NULL,
- guid TEXT NOT NULL,
- icon_url TEXT NOT NULL,
- rating TEXT,
- number_of_ratings INTEGER NOT NULL,
- FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
- );
-
- CREATE INDEX suggestions_record_id ON suggestions(record_id);
-
- CREATE TABLE icons(
- id TEXT PRIMARY KEY,
- data BLOB NOT NULL,
- mimetype TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_subjects(
- keyword TEXT PRIMARY KEY,
- record_id TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_modifiers(
- type INTEGER NOT NULL,
- keyword TEXT NOT NULL,
- record_id TEXT NOT NULL,
- PRIMARY KEY (type, keyword)
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_location_signs(
- keyword TEXT PRIMARY KEY,
- need_location INTEGER NOT NULL,
- record_id TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_custom_details(
- icon_id TEXT PRIMARY KEY,
- score REAL NOT NULL,
- record_id TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE mdn_custom_details(
- suggestion_id INTEGER PRIMARY KEY,
- description TEXT NOT NULL,
- FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
- );
-
- CREATE TABLE dismissed_suggestions (
- url TEXT PRIMARY KEY
- ) WITHOUT ROWID;
+CREATE TABLE meta(
+ key TEXT PRIMARY KEY,
+ value NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE keywords(
+ keyword TEXT NOT NULL,
+ suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
+ full_keyword_id INTEGER NULL REFERENCES full_keywords(id) ON DELETE SET NULL,
+ rank INTEGER NOT NULL,
+ PRIMARY KEY (keyword, suggestion_id)
+) WITHOUT ROWID;
+
+-- full keywords are what we display to the user when a (partial) keyword matches
+-- The FK to suggestion_id makes it so full keywords get deleted when the parent suggestion is deleted.
+CREATE TABLE full_keywords(
+ id INTEGER PRIMARY KEY,
+ suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
+ full_keyword TEXT NOT NULL
+);
+
+CREATE TABLE prefix_keywords(
+ keyword_prefix TEXT NOT NULL,
+ keyword_suffix TEXT NOT NULL DEFAULT '',
+ confidence INTEGER NOT NULL DEFAULT 0,
+ rank INTEGER NOT NULL,
+ suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
+ PRIMARY KEY (keyword_prefix, keyword_suffix, suggestion_id)
+) WITHOUT ROWID;
+
+CREATE UNIQUE INDEX keywords_suggestion_id_rank ON keywords(suggestion_id, rank);
+
+CREATE TABLE suggestions(
+ id INTEGER PRIMARY KEY,
+ record_id TEXT NOT NULL,
+ provider INTEGER NOT NULL,
+ title TEXT NOT NULL,
+ url TEXT NOT NULL,
+ score REAL NOT NULL
+);
+
+CREATE TABLE amp_custom_details(
+ suggestion_id INTEGER PRIMARY KEY,
+ advertiser TEXT NOT NULL,
+ block_id INTEGER NOT NULL,
+ iab_category TEXT NOT NULL,
+ impression_url TEXT NOT NULL,
+ click_url TEXT NOT NULL,
+ icon_id TEXT NOT NULL,
+ FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
+);
+
+CREATE TABLE wikipedia_custom_details(
+ suggestion_id INTEGER PRIMARY KEY REFERENCES suggestions(id) ON DELETE CASCADE,
+ icon_id TEXT NOT NULL
+);
+
+CREATE TABLE amo_custom_details(
+ suggestion_id INTEGER PRIMARY KEY,
+ description TEXT NOT NULL,
+ guid TEXT NOT NULL,
+ icon_url TEXT NOT NULL,
+ rating TEXT,
+ number_of_ratings INTEGER NOT NULL,
+ FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
+);
+
+CREATE INDEX suggestions_record_id ON suggestions(record_id);
+
+CREATE TABLE icons(
+ id TEXT PRIMARY KEY,
+ data BLOB NOT NULL,
+ mimetype TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_subjects(
+ keyword TEXT PRIMARY KEY,
+ record_id TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_modifiers(
+ type INTEGER NOT NULL,
+ keyword TEXT NOT NULL,
+ record_id TEXT NOT NULL,
+ PRIMARY KEY (type, keyword)
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_location_signs(
+ keyword TEXT PRIMARY KEY,
+ need_location INTEGER NOT NULL,
+ record_id TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_custom_details(
+ icon_id TEXT PRIMARY KEY,
+ score REAL NOT NULL,
+ record_id TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE mdn_custom_details(
+ suggestion_id INTEGER PRIMARY KEY,
+ description TEXT NOT NULL,
+ FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
+);
+
+CREATE TABLE dismissed_suggestions (
+ url TEXT PRIMARY KEY
+) WITHOUT ROWID;
";
/// Initializes an SQLite connection to the Suggest database, performing
@@ -166,9 +166,9 @@ impl ConnectionInitializer for SuggestConnectionInitializer {
16 => {
tx.execute(
"
- CREATE TABLE dismissed_suggestions (
- url_hash INTEGER PRIMARY KEY
- ) WITHOUT ROWID;",
+CREATE TABLE dismissed_suggestions (
+ url_hash INTEGER PRIMARY KEY
+) WITHOUT ROWID;",
(),
)?;
Ok(())
@@ -176,14 +176,23 @@ impl ConnectionInitializer for SuggestConnectionInitializer {
17 => {
tx.execute(
"
- DROP TABLE dismissed_suggestions;
- CREATE TABLE dismissed_suggestions (
- url TEXT PRIMARY KEY
- ) WITHOUT ROWID;",
+DROP TABLE dismissed_suggestions;
+CREATE TABLE dismissed_suggestions (
+ url TEXT PRIMARY KEY
+) WITHOUT ROWID;",
(),
)?;
Ok(())
}
+ 18 => {
+ tx.execute_batch(
+ "
+CREATE TABLE IF NOT EXISTS dismissed_suggestions (
+ url TEXT PRIMARY KEY
+) WITHOUT ROWID;",
+ )?;
+ Ok(())
+ }
_ => Err(open_database::Error::IncompatibleVersion(version)),
}
}
@@ -212,112 +221,112 @@ mod test {
// Snapshot of the v16 schema. We use this to test that we can migrate from there to the
// current schema.
const V16_SCHEMA: &str = r#"
- CREATE TABLE meta(
- key TEXT PRIMARY KEY,
- value NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE keywords(
- keyword TEXT NOT NULL,
- suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
- full_keyword_id INTEGER NULL REFERENCES full_keywords(id) ON DELETE SET NULL,
- rank INTEGER NOT NULL,
- PRIMARY KEY (keyword, suggestion_id)
- ) WITHOUT ROWID;
-
- -- full keywords are what we display to the user when a (partial) keyword matches
- -- The FK to suggestion_id makes it so full keywords get deleted when the parent suggestion is deleted.
- CREATE TABLE full_keywords(
- id INTEGER PRIMARY KEY,
- suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
- full_keyword TEXT NOT NULL
- );
-
- CREATE TABLE prefix_keywords(
- keyword_prefix TEXT NOT NULL,
- keyword_suffix TEXT NOT NULL DEFAULT '',
- confidence INTEGER NOT NULL DEFAULT 0,
- rank INTEGER NOT NULL,
- suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
- PRIMARY KEY (keyword_prefix, keyword_suffix, suggestion_id)
- ) WITHOUT ROWID;
-
- CREATE UNIQUE INDEX keywords_suggestion_id_rank ON keywords(suggestion_id, rank);
-
- CREATE TABLE suggestions(
- id INTEGER PRIMARY KEY,
- record_id TEXT NOT NULL,
- provider INTEGER NOT NULL,
- title TEXT NOT NULL,
- url TEXT NOT NULL,
- score REAL NOT NULL
- );
-
- CREATE TABLE amp_custom_details(
- suggestion_id INTEGER PRIMARY KEY,
- advertiser TEXT NOT NULL,
- block_id INTEGER NOT NULL,
- iab_category TEXT NOT NULL,
- impression_url TEXT NOT NULL,
- click_url TEXT NOT NULL,
- icon_id TEXT NOT NULL,
- FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
- );
-
- CREATE TABLE wikipedia_custom_details(
- suggestion_id INTEGER PRIMARY KEY REFERENCES suggestions(id) ON DELETE CASCADE,
- icon_id TEXT NOT NULL
- );
-
- CREATE TABLE amo_custom_details(
- suggestion_id INTEGER PRIMARY KEY,
- description TEXT NOT NULL,
- guid TEXT NOT NULL,
- icon_url TEXT NOT NULL,
- rating TEXT,
- number_of_ratings INTEGER NOT NULL,
- FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
- );
-
- CREATE INDEX suggestions_record_id ON suggestions(record_id);
-
- CREATE TABLE icons(
- id TEXT PRIMARY KEY,
- data BLOB NOT NULL,
- mimetype TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_subjects(
- keyword TEXT PRIMARY KEY,
- record_id TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_modifiers(
- type INTEGER NOT NULL,
- keyword TEXT NOT NULL,
- record_id TEXT NOT NULL,
- PRIMARY KEY (type, keyword)
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_location_signs(
- keyword TEXT PRIMARY KEY,
- need_location INTEGER NOT NULL,
- record_id TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE yelp_custom_details(
- icon_id TEXT PRIMARY KEY,
- score REAL NOT NULL,
- record_id TEXT NOT NULL
- ) WITHOUT ROWID;
-
- CREATE TABLE mdn_custom_details(
- suggestion_id INTEGER PRIMARY KEY,
- description TEXT NOT NULL,
- FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
- );
-
- PRAGMA user_version=16;
+CREATE TABLE meta(
+ key TEXT PRIMARY KEY,
+ value NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE keywords(
+ keyword TEXT NOT NULL,
+ suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
+ full_keyword_id INTEGER NULL REFERENCES full_keywords(id) ON DELETE SET NULL,
+ rank INTEGER NOT NULL,
+ PRIMARY KEY (keyword, suggestion_id)
+) WITHOUT ROWID;
+
+-- full keywords are what we display to the user when a (partial) keyword matches
+-- The FK to suggestion_id makes it so full keywords get deleted when the parent suggestion is deleted.
+CREATE TABLE full_keywords(
+ id INTEGER PRIMARY KEY,
+ suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
+ full_keyword TEXT NOT NULL
+);
+
+CREATE TABLE prefix_keywords(
+ keyword_prefix TEXT NOT NULL,
+ keyword_suffix TEXT NOT NULL DEFAULT '',
+ confidence INTEGER NOT NULL DEFAULT 0,
+ rank INTEGER NOT NULL,
+ suggestion_id INTEGER NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
+ PRIMARY KEY (keyword_prefix, keyword_suffix, suggestion_id)
+) WITHOUT ROWID;
+
+CREATE UNIQUE INDEX keywords_suggestion_id_rank ON keywords(suggestion_id, rank);
+
+CREATE TABLE suggestions(
+ id INTEGER PRIMARY KEY,
+ record_id TEXT NOT NULL,
+ provider INTEGER NOT NULL,
+ title TEXT NOT NULL,
+ url TEXT NOT NULL,
+ score REAL NOT NULL
+);
+
+CREATE TABLE amp_custom_details(
+ suggestion_id INTEGER PRIMARY KEY,
+ advertiser TEXT NOT NULL,
+ block_id INTEGER NOT NULL,
+ iab_category TEXT NOT NULL,
+ impression_url TEXT NOT NULL,
+ click_url TEXT NOT NULL,
+ icon_id TEXT NOT NULL,
+ FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
+);
+
+CREATE TABLE wikipedia_custom_details(
+ suggestion_id INTEGER PRIMARY KEY REFERENCES suggestions(id) ON DELETE CASCADE,
+ icon_id TEXT NOT NULL
+);
+
+CREATE TABLE amo_custom_details(
+ suggestion_id INTEGER PRIMARY KEY,
+ description TEXT NOT NULL,
+ guid TEXT NOT NULL,
+ icon_url TEXT NOT NULL,
+ rating TEXT,
+ number_of_ratings INTEGER NOT NULL,
+ FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
+);
+
+CREATE INDEX suggestions_record_id ON suggestions(record_id);
+
+CREATE TABLE icons(
+ id TEXT PRIMARY KEY,
+ data BLOB NOT NULL,
+ mimetype TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_subjects(
+ keyword TEXT PRIMARY KEY,
+ record_id TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_modifiers(
+ type INTEGER NOT NULL,
+ keyword TEXT NOT NULL,
+ record_id TEXT NOT NULL,
+ PRIMARY KEY (type, keyword)
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_location_signs(
+ keyword TEXT PRIMARY KEY,
+ need_location INTEGER NOT NULL,
+ record_id TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE yelp_custom_details(
+ icon_id TEXT PRIMARY KEY,
+ score REAL NOT NULL,
+ record_id TEXT NOT NULL
+) WITHOUT ROWID;
+
+CREATE TABLE mdn_custom_details(
+ suggestion_id INTEGER PRIMARY KEY,
+ description TEXT NOT NULL,
+ FOREIGN KEY(suggestion_id) REFERENCES suggestions(id) ON DELETE CASCADE
+);
+
+PRAGMA user_version=16;
"#;
/// Test running all schema upgrades from V16, which was the first schema with a "real"
@@ -328,5 +337,6 @@ mod test {
fn test_all_upgrades() {
let db_file = MigratedDatabaseFile::new(SuggestConnectionInitializer, V16_SCHEMA);
db_file.run_all_upgrades();
+ db_file.assert_schema_matches_new_database();
}
}
diff --git a/third_party/rust/suggest/src/store.rs b/third_party/rust/suggest/src/store.rs
index c55cffc7f5..19886b22b8 100644
--- a/third_party/rust/suggest/src/store.rs
+++ b/third_party/rust/suggest/src/store.rs
@@ -13,7 +13,8 @@ use error_support::handle_error;
use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use remote_settings::{
- self, GetItemsOptions, RemoteSettingsConfig, RemoteSettingsRecord, SortOrder,
+ self, GetItemsOptions, RemoteSettingsConfig, RemoteSettingsRecord, RemoteSettingsServer,
+ SortOrder,
};
use rusqlite::{
types::{FromSql, ToSqlOutput},
@@ -50,6 +51,7 @@ pub struct SuggestStoreBuilder(Mutex<SuggestStoreBuilderInner>);
#[derive(Default)]
struct SuggestStoreBuilderInner {
data_path: Option<String>,
+ remote_settings_server: Option<RemoteSettingsServer>,
remote_settings_config: Option<RemoteSettingsConfig>,
}
@@ -79,6 +81,11 @@ impl SuggestStoreBuilder {
self
}
+ pub fn remote_settings_server(self: Arc<Self>, server: RemoteSettingsServer) -> Arc<Self> {
+ self.0.lock().remote_settings_server = Some(server);
+ self
+ }
+
#[handle_error(Error)]
pub fn build(&self) -> SuggestApiResult<Arc<SuggestStore>> {
let inner = self.0.lock();
@@ -86,14 +93,29 @@ impl SuggestStoreBuilder {
.data_path
.clone()
.ok_or_else(|| Error::SuggestStoreBuilder("data_path not specified".to_owned()))?;
- let settings_client =
- remote_settings::Client::new(inner.remote_settings_config.clone().unwrap_or_else(
- || RemoteSettingsConfig {
- server_url: None,
- bucket_name: None,
- collection_name: REMOTE_SETTINGS_COLLECTION.into(),
- },
- ))?;
+ let remote_settings_config = match (
+ inner.remote_settings_server.as_ref(),
+ inner.remote_settings_config.as_ref(),
+ ) {
+ (Some(server), None) => RemoteSettingsConfig {
+ server: Some(server.clone()),
+ server_url: None,
+ bucket_name: None,
+ collection_name: REMOTE_SETTINGS_COLLECTION.into(),
+ },
+ (None, Some(remote_settings_config)) => remote_settings_config.clone(),
+ (None, None) => RemoteSettingsConfig {
+ server: None,
+ server_url: None,
+ bucket_name: None,
+ collection_name: REMOTE_SETTINGS_COLLECTION.into(),
+ },
+ (Some(_), Some(_)) => Err(Error::SuggestStoreBuilder(
+ "can't specify both `remote_settings_server` and `remote_settings_config`"
+ .to_owned(),
+ ))?,
+ };
+ let settings_client = remote_settings::Client::new(remote_settings_config)?;
Ok(Arc::new(SuggestStore {
inner: SuggestStoreInner::new(data_path, settings_client),
}))
@@ -172,6 +194,7 @@ impl SuggestStore {
let settings_client = || -> Result<_> {
Ok(remote_settings::Client::new(
settings_config.unwrap_or_else(|| RemoteSettingsConfig {
+ server: None,
server_url: None,
bucket_name: None,
collection_name: REMOTE_SETTINGS_COLLECTION.into(),
@@ -252,6 +275,8 @@ pub struct SuggestIngestionConstraints {
/// soft limit, and the store might ingest more than requested.
pub max_suggestions: Option<u64>,
pub providers: Option<Vec<SuggestionProvider>>,
+ /// Only run ingestion if the table `suggestions` is empty
+ pub empty_only: bool,
}
/// The implementation of the store. This is generic over the Remote Settings
@@ -334,6 +359,10 @@ where
pub fn ingest(&self, constraints: SuggestIngestionConstraints) -> Result<()> {
let writer = &self.dbs()?.writer;
+ if constraints.empty_only && !writer.read(|dao| dao.suggestions_table_empty())? {
+ return Ok(());
+ }
+
if let Some(unparsable_records) =
writer.read(|dao| dao.get_meta::<UnparsableRecords>(UNPARSABLE_RECORDS_META_KEY))?
{
@@ -865,6 +894,12 @@ mod tests {
let store = unique_test_store(SnapshotSettingsClient::with_snapshot(snapshot));
+ // suggestions_table_empty returns true before the ingestion is complete
+ assert!(store
+ .dbs()?
+ .reader
+ .read(|dao| dao.suggestions_table_empty())?);
+
store.ingest(SuggestIngestionConstraints::default())?;
store.dbs()?.reader.read(|dao| {
@@ -904,6 +939,153 @@ mod tests {
Ok(())
})?;
+ // suggestions_table_empty returns false after the ingestion is complete
+ assert!(!store
+ .dbs()?
+ .reader
+ .read(|dao| dao.suggestions_table_empty())?);
+
+ Ok(())
+ }
+
+ /// Tests ingesting suggestions into an empty database.
+ #[test]
+ fn ingest_empty_only() -> anyhow::Result<()> {
+ before_each();
+
+ // This ingestion should run, since the DB is empty
+ let snapshot = Snapshot::with_records(json!([{
+ "id": "1234",
+ "type": "data",
+ "last_modified": 15,
+ "attachment": {
+ "filename": "data-1.json",
+ "mimetype": "application/json",
+ "location": "data-1.json",
+ "hash": "",
+ "size": 0,
+ },
+ }]))?
+ .with_data(
+ "data-1.json",
+ json!([{
+ "id": 0,
+ "advertiser": "Los Pollos Hermanos",
+ "iab_category": "8 - Food & Drink",
+ "keywords": ["lo", "los", "los p", "los pollos", "los pollos h", "los pollos hermanos"],
+ "title": "Los Pollos Hermanos - Albuquerque",
+ "url": "https://www.lph-nm.biz",
+ "icon": "5678",
+ "impression_url": "https://example.com/impression_url",
+ "click_url": "https://example.com/click_url",
+ "score": 0.3
+ }]),
+ )?;
+ let mut store = unique_test_store(SnapshotSettingsClient::with_snapshot(snapshot));
+ store.ingest(SuggestIngestionConstraints {
+ empty_only: true,
+ ..SuggestIngestionConstraints::default()
+ })?;
+
+ store.dbs()?.reader.read(|dao| {
+ expect![[r#"
+ [
+ Amp {
+ title: "Los Pollos Hermanos - Albuquerque",
+ url: "https://www.lph-nm.biz",
+ raw_url: "https://www.lph-nm.biz",
+ icon: None,
+ icon_mimetype: None,
+ full_keyword: "los",
+ block_id: 0,
+ advertiser: "Los Pollos Hermanos",
+ iab_category: "8 - Food & Drink",
+ impression_url: "https://example.com/impression_url",
+ click_url: "https://example.com/click_url",
+ raw_click_url: "https://example.com/click_url",
+ score: 0.3,
+ },
+ ]
+ "#]]
+ .assert_debug_eq(&dao.fetch_suggestions(&SuggestionQuery {
+ keyword: "lo".into(),
+ providers: vec![SuggestionProvider::Amp],
+ limit: None,
+ })?);
+
+ Ok(())
+ })?;
+
+ // ingestion should run with SuggestIngestionConstraints::empty_only = true, since the DB
+ // is empty
+ store.settings_client = SnapshotSettingsClient::with_snapshot(Snapshot::with_records(json!([{
+ "id": "1234",
+ "type": "data",
+ "last_modified": 15,
+ "attachment": {
+ "filename": "data-1.json",
+ "mimetype": "application/json",
+ "location": "data-1.json",
+ "hash": "",
+ "size": 0,
+ },
+ }, {
+ "id": "12345",
+ "type": "data",
+ "last_modified": 15,
+ "attachment": {
+ "filename": "data-2.json",
+ "mimetype": "application/json",
+ "location": "data-2.json",
+ "hash": "",
+ "size": 0,
+ },
+ }]))?
+ .with_data(
+ "data-1.json",
+ json!([{
+ "id": 0,
+ "advertiser": "Los Pollos Hermanos",
+ "iab_category": "8 - Food & Drink",
+ "keywords": ["lo", "los", "los p", "los pollos", "los pollos h", "los pollos hermanos"],
+ "title": "Los Pollos Hermanos - Albuquerque",
+ "url": "https://www.lph-nm.biz",
+ "icon": "5678",
+ "impression_url": "https://example.com/impression_url",
+ "click_url": "https://example.com/click_url",
+ "score": 0.3
+ }])
+ )?
+ .with_data("data-2.json", json!([{
+ "id": 1,
+ "advertiser": "Good Place Eats",
+ "iab_category": "8 - Food & Drink",
+ "keywords": ["la", "las", "lasa", "lasagna", "lasagna come out tomorrow"],
+ "title": "Lasagna Come Out Tomorrow",
+ "url": "https://www.lasagna.restaurant",
+ "icon": "2",
+ "impression_url": "https://example.com/impression_url",
+ "click_url": "https://example.com/click_url"
+ }]),
+ )?);
+ store.ingest(SuggestIngestionConstraints {
+ empty_only: true,
+ ..SuggestIngestionConstraints::default()
+ })?;
+
+ store.dbs()?.reader.read(|dao| {
+ expect![[r#"
+ []
+ "#]]
+ .assert_debug_eq(&dao.fetch_suggestions(&SuggestionQuery {
+ keyword: "la".into(),
+ providers: vec![SuggestionProvider::Amp],
+ limit: None,
+ })?);
+
+ Ok(())
+ })?;
+
Ok(())
}
@@ -2189,6 +2371,7 @@ mod tests {
store.ingest(SuggestIngestionConstraints {
max_suggestions: Some(max_suggestions),
providers: Some(vec![SuggestionProvider::Amp]),
+ ..SuggestIngestionConstraints::default()
})?;
let actual_limit = store
.settings_client
@@ -5021,10 +5204,10 @@ mod tests {
UnparsableRecords(
{
"clippy-2": UnparsableRecord {
- schema_version: 18,
+ schema_version: 19,
},
"fancy-new-suggestions-1": UnparsableRecord {
- schema_version: 18,
+ schema_version: 19,
},
},
),
@@ -5093,10 +5276,10 @@ mod tests {
UnparsableRecords(
{
"clippy-2": UnparsableRecord {
- schema_version: 18,
+ schema_version: 19,
},
"fancy-new-suggestions-1": UnparsableRecord {
- schema_version: 18,
+ schema_version: 19,
},
},
),
@@ -5178,6 +5361,7 @@ mod tests {
let constraints = SuggestIngestionConstraints {
max_suggestions: Some(100),
providers: Some(vec![SuggestionProvider::Amp, SuggestionProvider::Pocket]),
+ ..SuggestIngestionConstraints::default()
};
store.ingest(constraints)?;
@@ -5292,10 +5476,10 @@ mod tests {
UnparsableRecords(
{
"clippy-2": UnparsableRecord {
- schema_version: 18,
+ schema_version: 19,
},
"fancy-new-suggestions-1": UnparsableRecord {
- schema_version: 18,
+ schema_version: 19,
},
},
),
@@ -5381,7 +5565,7 @@ mod tests {
UnparsableRecords(
{
"invalid-attachment": UnparsableRecord {
- schema_version: 18,
+ schema_version: 19,
},
},
),
diff --git a/third_party/rust/suggest/src/suggest.udl b/third_party/rust/suggest/src/suggest.udl
index 4a4e3fe9a0..0c4781b951 100644
--- a/third_party/rust/suggest/src/suggest.udl
+++ b/third_party/rust/suggest/src/suggest.udl
@@ -6,6 +6,9 @@
[External="remote_settings"]
typedef extern RemoteSettingsConfig;
+[External="remote_settings"]
+typedef extern RemoteSettingsServer;
+
namespace suggest {
boolean raw_suggestion_url_matches([ByRef] string raw_url, [ByRef] string url);
@@ -103,6 +106,14 @@ dictionary SuggestionQuery {
dictionary SuggestIngestionConstraints {
u64? max_suggestions = null;
sequence<SuggestionProvider>? providers = null;
+ // Only ingest if the table `suggestions` is empty.
+ //
+ // This is indented to handle periodic updates. Consumers can schedule an ingest with
+ // `empty_only=true` on startup and a regular ingest with `empty_only=false` to run on a long periodic schedule (maybe
+ // once a day). This allows ingestion to normally be run at a slow, periodic rate. However, if
+ // there is a schema upgrade that causes the database to be thrown away, then the
+ // `empty_only=true` ingestion that runs on startup will repopulate it.
+ boolean empty_only = false;
};
dictionary SuggestGlobalConfig {
@@ -155,6 +166,10 @@ interface SuggestStoreBuilder {
SuggestStoreBuilder cache_path(string path);
[Self=ByArc]
+ SuggestStoreBuilder remote_settings_server(RemoteSettingsServer server);
+
+ // Deprecated: Use `remote_settings_server()` instead.
+ [Self=ByArc]
SuggestStoreBuilder remote_settings_config(RemoteSettingsConfig config);
[Throws=SuggestApiError]
diff --git a/third_party/rust/thiserror-impl/.cargo-checksum.json b/third_party/rust/thiserror-impl/.cargo-checksum.json
index 6adcf117c2..e4016f1165 100644
--- a/third_party/rust/thiserror-impl/.cargo-checksum.json
+++ b/third_party/rust/thiserror-impl/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"0a1dbd3bcb92455b7ed1d661e0c05958a64fd694a18357d3c61a8e1f2cffb9bd","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/ast.rs":"e2fbc32e91cd462757107c1f8ab2f888f08c865ac71270583f9e11b83e3c32ca","src/attr.rs":"7451fc0b0a06649e62679c7558e5aeb0e2019400c170cde54c23289ef44188f7","src/expand.rs":"9469753e0949556848183084e0f22521c6300d38ca0de196441446c50f350d3c","src/fmt.rs":"5d1cefc012403c2d4ff7ab2513c0ec559166df4271d5983a6463939b5ec8c3e1","src/generics.rs":"2076cde22271be355a8131a77add4b93f83ab0af4317cd2df5471fffa4f95c66","src/lib.rs":"5eea86c771e643328ad9bc3b881cce4bf9d50adae1b33e0d07645bdd9044003d","src/prop.rs":"5ba613e38430831259f20b258f33d57dcb783fbaeeb49e5faffa7b2a7be99e67","src/span.rs":"430460a4fa0d1fa9c627c1ddd575d2b101778fea84217591e1a93a5f6a2a0132","src/valid.rs":"ac95253944fd360d3578d0643a7baabb2cfa6bf9fbced7a6ce1f7b0529a3bb98"},"package":"a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"} \ No newline at end of file
+{"files":{"Cargo.toml":"27f9696d64a97df170dc620366a6b6b0b162917a686511e6b878586b04846226","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/ast.rs":"9b6cd6b1553483c99cd7e36aa422d37f4353c99b15da55534d28822f7fa7fd08","src/attr.rs":"99fca8c65a1907ee2f43f7ec28ce465bae22336c529bd7148738f9ce35375101","src/expand.rs":"2736a714372a4b81ac5438783dd2c0f656d624bec5cc4089af96ceecaeee011e","src/fmt.rs":"5d1cefc012403c2d4ff7ab2513c0ec559166df4271d5983a6463939b5ec8c3e1","src/generics.rs":"2076cde22271be355a8131a77add4b93f83ab0af4317cd2df5471fffa4f95c66","src/lib.rs":"5eea86c771e643328ad9bc3b881cce4bf9d50adae1b33e0d07645bdd9044003d","src/prop.rs":"5ba613e38430831259f20b258f33d57dcb783fbaeeb49e5faffa7b2a7be99e67","src/span.rs":"430460a4fa0d1fa9c627c1ddd575d2b101778fea84217591e1a93a5f6a2a0132","src/valid.rs":"ac95253944fd360d3578d0643a7baabb2cfa6bf9fbced7a6ce1f7b0529a3bb98"},"package":"d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"} \ No newline at end of file
diff --git a/third_party/rust/thiserror-impl/Cargo.toml b/third_party/rust/thiserror-impl/Cargo.toml
index 5445c126ec..757302d6af 100644
--- a/third_party/rust/thiserror-impl/Cargo.toml
+++ b/third_party/rust/thiserror-impl/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.56"
name = "thiserror-impl"
-version = "1.0.57"
+version = "1.0.59"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Implementation detail of the `thiserror` crate"
license = "MIT OR Apache-2.0"
diff --git a/third_party/rust/thiserror-impl/src/ast.rs b/third_party/rust/thiserror-impl/src/ast.rs
index 9e06928980..4739d58beb 100644
--- a/third_party/rust/thiserror-impl/src/ast.rs
+++ b/third_party/rust/thiserror-impl/src/ast.rs
@@ -82,7 +82,7 @@ impl<'a> Enum<'a> {
.map(|node| {
let mut variant = Variant::from_syn(node, &scope, span)?;
if let display @ None = &mut variant.attrs.display {
- *display = attrs.display.clone();
+ display.clone_from(&attrs.display);
}
if let Some(display) = &mut variant.attrs.display {
display.expand_shorthand(&variant.fields);
diff --git a/third_party/rust/thiserror-impl/src/attr.rs b/third_party/rust/thiserror-impl/src/attr.rs
index 269c69eca5..395edb1f5a 100644
--- a/third_party/rust/thiserror-impl/src/attr.rs
+++ b/third_party/rust/thiserror-impl/src/attr.rs
@@ -230,7 +230,18 @@ impl ToTokens for Display<'_> {
impl ToTokens for Trait {
fn to_tokens(&self, tokens: &mut TokenStream) {
- let trait_name = format_ident!("{}", format!("{:?}", self));
- tokens.extend(quote!(::core::fmt::#trait_name));
+ let trait_name = match self {
+ Trait::Debug => "Debug",
+ Trait::Display => "Display",
+ Trait::Octal => "Octal",
+ Trait::LowerHex => "LowerHex",
+ Trait::UpperHex => "UpperHex",
+ Trait::Pointer => "Pointer",
+ Trait::Binary => "Binary",
+ Trait::LowerExp => "LowerExp",
+ Trait::UpperExp => "UpperExp",
+ };
+ let ident = Ident::new(trait_name, Span::call_site());
+ tokens.extend(quote!(::core::fmt::#ident));
}
}
diff --git a/third_party/rust/thiserror-impl/src/expand.rs b/third_party/rust/thiserror-impl/src/expand.rs
index 1b44513a23..296b567bdc 100644
--- a/third_party/rust/thiserror-impl/src/expand.rs
+++ b/third_party/rust/thiserror-impl/src/expand.rs
@@ -155,7 +155,7 @@ fn impl_struct(input: Struct) -> TokenStream {
::core::fmt::Display::fmt(&self.#only_field, __formatter)
})
} else if let Some(display) = &input.attrs.display {
- display_implied_bounds = display.implied_bounds.clone();
+ display_implied_bounds.clone_from(&display.implied_bounds);
let use_as_display = use_as_display(display.has_bonus_display);
let pat = fields_pat(&input.fields);
Some(quote! {
@@ -399,7 +399,7 @@ fn impl_enum(input: Enum) -> TokenStream {
let mut display_implied_bounds = Set::new();
let display = match &variant.attrs.display {
Some(display) => {
- display_implied_bounds = display.implied_bounds.clone();
+ display_implied_bounds.clone_from(&display.implied_bounds);
display.to_token_stream()
}
None => {
diff --git a/third_party/rust/thiserror/.cargo-checksum.json b/third_party/rust/thiserror/.cargo-checksum.json
index efb4bd5017..f7e22ca1ee 100644
--- a/third_party/rust/thiserror/.cargo-checksum.json
+++ b/third_party/rust/thiserror/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"315a0379d474f762b74a40fb83f8a52b7efe0f5a352e7a7ab0b9d118f32f609e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"106c5a937767d49503e1fc5eae1b924f57f15decd8583720a3c652483e348a64","build.rs":"532f6ac494cdddfad3267067a46969a8052b02c1bd94567361f7103ab0dc8c28","build/probe.rs":"3245569a228727091f335db44c7c2f729729b2dfac9f46c1143eb179439f223d","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/aserror.rs":"cf3c98abb2b9e06afa3c4aba0df14938417c3e330315863437561cbb3573888b","src/display.rs":"0adeeeb524c6bee06de179d54e82a43dc12d2c5b7f69f6fd268ba4611ebf5233","src/lib.rs":"6903e561c2a83901061ed717061040a1d0ffb4296c2c52e19e617e1ca6c07211","src/provide.rs":"8007e22953bacfcc57bb7d12a03fbeb0acece5d2ec889cf55522a4e071d26df3","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_backtrace.rs":"a8f038490fb881463c0e8c36557617c47cf2d181f16c00525d4d139c7964fade","tests/test_deprecated.rs":"7b80a10f090a3982da017556d3d71398abcead59afd8278c7b9d9b1f7b66c7b3","tests/test_display.rs":"91a6bf704fd78a5565330f438f30ae4088aa8bc7ac5e1412401e440072408c03","tests/test_error.rs":"d06dca3c38f22d7ce4e27dadd6c0f78e5cefe3a2ebbc5fe44abc9ddd5ee1985f","tests/test_expr.rs":"d35b11040ebc547467f52571051854e3e094d52b8e229fa3d44700d5f40959a2","tests/test_from.rs":"36bd22be7b048cd187a19076aeac1456040f20a0b677b01c6003998b63439ea1","tests/test_generics.rs":"adc61f0d5fe8d53796848d44fb0373be5eab19a1eeb6a7172bc6f0dd7b91199c","tests/test_lints.rs":"c17d79d77edfcdd4b8f6dcdcd1c70ad065cfbc747e1a618ac6343315d0b59ea4","tests/test_option.rs":"ac30d929c019d6c54d1c1792b09e43c18dc0e4123b82051ff9e5db5e63c15e43","tests/test_path.rs":"ef5452c7e828a0179f5ace7e19f95b9762aa887caf10244adbfe36ded712c090","tests/test_source.rs":"f2f04f11bf8a709eddb1c68f113cda0c2be87e56800d6b9d991bedd545b4642f","tests/test_transparent.rs":"cd8d5be14d00d610a1782104bea6c013618501dab5c3625178ecfcf66e31f939","tests/ui/bad-field-attr.rs":"c5b567e3091969a01061843fb2d95c5e1aa3fa81edfeecdf416a84a6fba40aa8","tests/ui/bad-field-attr.stderr":"78f576d5ec66464a77f1cdf0f5bb7dcdf18f7f04f1165983a6239ec59d908ea3","tests/ui/concat-display.rs":"3995bd6b3bdd67df7bb16499775d89600c0dd20895633fe807396a64c117078d","tests/ui/concat-display.stderr":"256dfde61ee689ebe51588b135e2e030bdf95ba5adef1cb59f588c797bbdeef2","tests/ui/duplicate-enum-source.rs":"bfe28ce18042d446a76c7411aa233598211ce1157fdd3cb87bff3b3fa7c33131","tests/ui/duplicate-enum-source.stderr":"3d32fead420b27b4497be49080bc3b78f7f0ba339ead3de6c94e5dc20302c18f","tests/ui/duplicate-fmt.rs":"af53b66445bcce076a114376747f176b42c060a156563a41ccb638ae14c451fd","tests/ui/duplicate-fmt.stderr":"998bb121ce6f1595fd99529a7a1b06451b6bf476924337dce5524a83a7a5f1a1","tests/ui/duplicate-struct-source.rs":"f3d5f8e3d6fccfcdbb630db291353709583a920c6bf46f9f9de9966b67ea4c0f","tests/ui/duplicate-struct-source.stderr":"fb761d76668ac42357cf37b03c0abdbae5de0a828034990850291c9cb6ab766d","tests/ui/duplicate-transparent.rs":"41a9447e85f1a47027023442acde55c3d8610ec46d91b39bd43a42d7a004d747","tests/ui/duplicate-transparent.stderr":"4975abad43e973df158f18098d9bcb9dc39f8e75d3e733ed5d6620d1ee065c11","tests/ui/fallback-impl-with-display.rs":"141a8efbabe3fdac584bec8a61e6cceb58a34a70b825f6277037bf9d591150eb","tests/ui/fallback-impl-with-display.stderr":"1b3dad712b97598fbee70125471de1a8106eb161d42ce1f790ae07be8c8984ba","tests/ui/from-backtrace-backtrace.rs":"0caac64486c0eb9c076553c0502d468fbc477602a9a2595165a1dcd95524e5ff","tests/ui/from-backtrace-backtrace.stderr":"e24156ae0828878f3282341732b6e032eaa8cb4b4db366a6b5437ed0731d40a7","tests/ui/from-not-source.rs":"744a55aeffe11066830159ac023c33aaa5576e313b341fa24440ee13dfe3ac98","tests/ui/from-not-source.stderr":"525038e8b841707b927434cca4549168f73bd305faca17552a0d1fffa542ccc4","tests/ui/invalid-input-impl-anyway.rs":"6de91f71ddf038dffa3b9da33763a2ec3a5aa0047528e19ba998d5efe3aada5b","tests/ui/invalid-input-impl-anyway.stderr":"fa2725053cd87fc37f87546b377e6e5eed95c45e2a960863303b21a1935fdddb","tests/ui/lifetime.rs":"e72e0391695e47fcd07edbf3819f114e468e2097086ec687781c7c8d6b4b7da7","tests/ui/lifetime.stderr":"d889a23f71324afe95dafc5f9d15337fbdbc9977cb8924f0cafe3a3becf4ced7","tests/ui/missing-display.rs":"c1fd1bc0ec0fb103d7f7b128837f717d49485662839899d570b3c983f1332888","tests/ui/missing-display.stderr":"a8de0f1559da9320ee99ef334937d532d9e9f40a32ed7f8ce56fb465628bff96","tests/ui/missing-fmt.rs":"bc9e2830e54c2474ff6c27a766ed3dee88d29e40f93f30e8d64d63233866c17d","tests/ui/missing-fmt.stderr":"9a20ccee9b660fe31a5b3199307b48580bb8305cb9ce33d97d3fc767a0cfc614","tests/ui/no-display.rs":"962245372272d23e9833311c15e73221b3c7da822a2ff90189613af56ffb5c2e","tests/ui/no-display.stderr":"c145dbdd39e145b5c6f26f8504fbf1e33efa2eada37e09900b39dd62667f22d7","tests/ui/source-enum-not-error.rs":"3add5e7b4503d964bcae0848904822e1473c1d08c5a146c2df5347314ce1b8df","tests/ui/source-enum-not-error.stderr":"aeba0a8a0084833e470b6be2250370809f53c279ad603232af5302b9de9f8cce","tests/ui/source-enum-unnamed-field-not-error.rs":"a98989e908b84a8e6e6dceef02af7bdd1098a444d229950f67ed4f54d55c62e7","tests/ui/source-enum-unnamed-field-not-error.stderr":"4f3d90525dd462e67f633e83b26acec75d9af3626e40d28ded2c2438e0c73192","tests/ui/source-struct-not-error.rs":"09fb7713637242dca9192585a6daeb8d732dc1c1d0fa522b74f1c98618e6d949","tests/ui/source-struct-not-error.stderr":"b45eb66f078fec68d44feff1f8d6a676c341e9e9d9acb35daa58ec1ea20f9dae","tests/ui/source-struct-unnamed-field-not-error.rs":"eee605a9aafbb093666393e25cef4f7d7b8e90d518b9fadbdbed9685c66ccfcd","tests/ui/source-struct-unnamed-field-not-error.stderr":"10e408f71c1b61880b1d52739f222ec58a66be70a1df17e44c536fe0f9ffe2a6","tests/ui/transparent-display.rs":"b3c59583eb64b0b5a246444456d03cf52d51bcdc08885023600dbb44fd87e5f2","tests/ui/transparent-display.stderr":"16d538914e0d92026bde4b4bec75660217da9ecc6b621d12d2eb81d33ed1d1da","tests/ui/transparent-enum-many.rs":"2a40a764fb4683bff57973eec61507a6c00f7d4d7a32da6e7bd0190c2e445434","tests/ui/transparent-enum-many.stderr":"f1d78c1d6d8edbef153420db4fb9ca3dc6076fa043b5b1bc0cd291daa417a3ea","tests/ui/transparent-enum-not-error.rs":"f6315993e68bc71d6d4d39afa4d059695308ef785f92cc0d1df3e9ff55be2a9a","tests/ui/transparent-enum-not-error.stderr":"3a5fe056cd4566f402b03cb591394e0ba85bd74da53df3c8d50bda4a05c2e5ba","tests/ui/transparent-enum-source.rs":"18f606a98ac0a53f08dc56f5f923b9cbe75d25ed34479c777b48dac305d5968c","tests/ui/transparent-enum-source.stderr":"1b2e0ac53951034575d43ec0396c4e2b3cfb272db2aef8d6baa13a7e1632cc84","tests/ui/transparent-enum-unnamed-field-not-error.rs":"0c720567e9e0f87921055dfa9f607661725377633445e01a4b5048c7a7a50a85","tests/ui/transparent-enum-unnamed-field-not-error.stderr":"6d84e9a7f4e88daba12931a6c1508be60bb19125d06e44fa2fa205126d953bb1","tests/ui/transparent-struct-many.rs":"72c6b6c1a44c203d3bc68989b2f1ec092531ef75b745432824c3776c290326f6","tests/ui/transparent-struct-many.stderr":"7bd0536dbb54a0ce7d4a8e66ca7624a1b132d8a1d1e4fecca642ec77494ac01c","tests/ui/transparent-struct-not-error.rs":"fd814d3141c9182b1267b558d9daef8dd6e8b6462e1ad42b197f3a1c0703dce2","tests/ui/transparent-struct-not-error.stderr":"ac7634ea72096d8a5c1a91fd4f1b45ef870130a2698d9ae7c6530cec2f9799d5","tests/ui/transparent-struct-source.rs":"863fa691ed7d27e8767da58d9ee11fd40d6642274b36338ca1074c07964ea2b3","tests/ui/transparent-struct-source.stderr":"267dab65929e67d32347fb467a00b43af931f8205d727d7671938580217fc70e","tests/ui/transparent-struct-unnamed-field-not-error.rs":"fbff5874be44a5dcc347693d7929537256b187dfec467ed72c9968c095228d8d","tests/ui/transparent-struct-unnamed-field-not-error.stderr":"ea99d5422348c2588ad7374360e2a24649f040b9c5614c9308eff958f61960ec","tests/ui/unexpected-field-fmt.rs":"29fba7b4d81c642ec8e47cfe053aa515acf9080a86d65e685363a48993becfe3","tests/ui/unexpected-field-fmt.stderr":"20731c4a08af04bed3ff513903adadd690b6bc532b15604557e7f25575a8338f","tests/ui/unexpected-struct-source.rs":"c6cbe882d622635c216feb8290b1bd536ce0ec4feee16bc087667a21b3641d5c","tests/ui/unexpected-struct-source.stderr":"7c8227513478f6cc09e8a28be337c8a0e758a06ca5978d774c91bd43c4a54043","tests/ui/union.rs":"331adff27cebd8b95b03b6742cc8247331fda1f961e1590ed39c8d39f50cf1d8","tests/ui/union.stderr":"5f67ad29753d6fb14bc03aef7d4a1f660ee7796e469c037efbf8b13456934ad3"},"package":"1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"} \ No newline at end of file
+{"files":{"Cargo.toml":"7df807832514d69476a436a1466ed9cefde6d73f8fff7829718096c8bf6bb88e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"106c5a937767d49503e1fc5eae1b924f57f15decd8583720a3c652483e348a64","build.rs":"e93f4e6f8b7d24c9b119a85ea134067d2c2a7f78e082c1ab1e541c41225d5a36","build/probe.rs":"3245569a228727091f335db44c7c2f729729b2dfac9f46c1143eb179439f223d","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/aserror.rs":"cf3c98abb2b9e06afa3c4aba0df14938417c3e330315863437561cbb3573888b","src/display.rs":"0adeeeb524c6bee06de179d54e82a43dc12d2c5b7f69f6fd268ba4611ebf5233","src/lib.rs":"6a823f259101ba3c28fc8824afbe6ce66c1c4ffa7bea183172b25b891dfa1695","src/provide.rs":"8007e22953bacfcc57bb7d12a03fbeb0acece5d2ec889cf55522a4e071d26df3","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_backtrace.rs":"a8f038490fb881463c0e8c36557617c47cf2d181f16c00525d4d139c7964fade","tests/test_deprecated.rs":"7b80a10f090a3982da017556d3d71398abcead59afd8278c7b9d9b1f7b66c7b3","tests/test_display.rs":"91a6bf704fd78a5565330f438f30ae4088aa8bc7ac5e1412401e440072408c03","tests/test_error.rs":"d06dca3c38f22d7ce4e27dadd6c0f78e5cefe3a2ebbc5fe44abc9ddd5ee1985f","tests/test_expr.rs":"d35b11040ebc547467f52571051854e3e094d52b8e229fa3d44700d5f40959a2","tests/test_from.rs":"36bd22be7b048cd187a19076aeac1456040f20a0b677b01c6003998b63439ea1","tests/test_generics.rs":"adc61f0d5fe8d53796848d44fb0373be5eab19a1eeb6a7172bc6f0dd7b91199c","tests/test_lints.rs":"93d66ea5b6b91634ddf18a520b455f8bc65f3e9bbf90874e239f45ab15b0c125","tests/test_option.rs":"ac30d929c019d6c54d1c1792b09e43c18dc0e4123b82051ff9e5db5e63c15e43","tests/test_path.rs":"ef5452c7e828a0179f5ace7e19f95b9762aa887caf10244adbfe36ded712c090","tests/test_source.rs":"f2f04f11bf8a709eddb1c68f113cda0c2be87e56800d6b9d991bedd545b4642f","tests/test_transparent.rs":"cd8d5be14d00d610a1782104bea6c013618501dab5c3625178ecfcf66e31f939","tests/ui/bad-field-attr.rs":"c5b567e3091969a01061843fb2d95c5e1aa3fa81edfeecdf416a84a6fba40aa8","tests/ui/bad-field-attr.stderr":"78f576d5ec66464a77f1cdf0f5bb7dcdf18f7f04f1165983a6239ec59d908ea3","tests/ui/concat-display.rs":"3995bd6b3bdd67df7bb16499775d89600c0dd20895633fe807396a64c117078d","tests/ui/concat-display.stderr":"256dfde61ee689ebe51588b135e2e030bdf95ba5adef1cb59f588c797bbdeef2","tests/ui/duplicate-enum-source.rs":"bfe28ce18042d446a76c7411aa233598211ce1157fdd3cb87bff3b3fa7c33131","tests/ui/duplicate-enum-source.stderr":"3d32fead420b27b4497be49080bc3b78f7f0ba339ead3de6c94e5dc20302c18f","tests/ui/duplicate-fmt.rs":"af53b66445bcce076a114376747f176b42c060a156563a41ccb638ae14c451fd","tests/ui/duplicate-fmt.stderr":"998bb121ce6f1595fd99529a7a1b06451b6bf476924337dce5524a83a7a5f1a1","tests/ui/duplicate-struct-source.rs":"f3d5f8e3d6fccfcdbb630db291353709583a920c6bf46f9f9de9966b67ea4c0f","tests/ui/duplicate-struct-source.stderr":"fb761d76668ac42357cf37b03c0abdbae5de0a828034990850291c9cb6ab766d","tests/ui/duplicate-transparent.rs":"41a9447e85f1a47027023442acde55c3d8610ec46d91b39bd43a42d7a004d747","tests/ui/duplicate-transparent.stderr":"4975abad43e973df158f18098d9bcb9dc39f8e75d3e733ed5d6620d1ee065c11","tests/ui/fallback-impl-with-display.rs":"141a8efbabe3fdac584bec8a61e6cceb58a34a70b825f6277037bf9d591150eb","tests/ui/fallback-impl-with-display.stderr":"1b3dad712b97598fbee70125471de1a8106eb161d42ce1f790ae07be8c8984ba","tests/ui/from-backtrace-backtrace.rs":"0caac64486c0eb9c076553c0502d468fbc477602a9a2595165a1dcd95524e5ff","tests/ui/from-backtrace-backtrace.stderr":"e24156ae0828878f3282341732b6e032eaa8cb4b4db366a6b5437ed0731d40a7","tests/ui/from-not-source.rs":"744a55aeffe11066830159ac023c33aaa5576e313b341fa24440ee13dfe3ac98","tests/ui/from-not-source.stderr":"525038e8b841707b927434cca4549168f73bd305faca17552a0d1fffa542ccc4","tests/ui/invalid-input-impl-anyway.rs":"6de91f71ddf038dffa3b9da33763a2ec3a5aa0047528e19ba998d5efe3aada5b","tests/ui/invalid-input-impl-anyway.stderr":"fa2725053cd87fc37f87546b377e6e5eed95c45e2a960863303b21a1935fdddb","tests/ui/lifetime.rs":"e72e0391695e47fcd07edbf3819f114e468e2097086ec687781c7c8d6b4b7da7","tests/ui/lifetime.stderr":"d889a23f71324afe95dafc5f9d15337fbdbc9977cb8924f0cafe3a3becf4ced7","tests/ui/missing-display.rs":"c1fd1bc0ec0fb103d7f7b128837f717d49485662839899d570b3c983f1332888","tests/ui/missing-display.stderr":"a8de0f1559da9320ee99ef334937d532d9e9f40a32ed7f8ce56fb465628bff96","tests/ui/missing-fmt.rs":"bc9e2830e54c2474ff6c27a766ed3dee88d29e40f93f30e8d64d63233866c17d","tests/ui/missing-fmt.stderr":"9a20ccee9b660fe31a5b3199307b48580bb8305cb9ce33d97d3fc767a0cfc614","tests/ui/no-display.rs":"962245372272d23e9833311c15e73221b3c7da822a2ff90189613af56ffb5c2e","tests/ui/no-display.stderr":"c145dbdd39e145b5c6f26f8504fbf1e33efa2eada37e09900b39dd62667f22d7","tests/ui/source-enum-not-error.rs":"3add5e7b4503d964bcae0848904822e1473c1d08c5a146c2df5347314ce1b8df","tests/ui/source-enum-not-error.stderr":"aeba0a8a0084833e470b6be2250370809f53c279ad603232af5302b9de9f8cce","tests/ui/source-enum-unnamed-field-not-error.rs":"a98989e908b84a8e6e6dceef02af7bdd1098a444d229950f67ed4f54d55c62e7","tests/ui/source-enum-unnamed-field-not-error.stderr":"4f3d90525dd462e67f633e83b26acec75d9af3626e40d28ded2c2438e0c73192","tests/ui/source-struct-not-error.rs":"09fb7713637242dca9192585a6daeb8d732dc1c1d0fa522b74f1c98618e6d949","tests/ui/source-struct-not-error.stderr":"b45eb66f078fec68d44feff1f8d6a676c341e9e9d9acb35daa58ec1ea20f9dae","tests/ui/source-struct-unnamed-field-not-error.rs":"eee605a9aafbb093666393e25cef4f7d7b8e90d518b9fadbdbed9685c66ccfcd","tests/ui/source-struct-unnamed-field-not-error.stderr":"10e408f71c1b61880b1d52739f222ec58a66be70a1df17e44c536fe0f9ffe2a6","tests/ui/transparent-display.rs":"b3c59583eb64b0b5a246444456d03cf52d51bcdc08885023600dbb44fd87e5f2","tests/ui/transparent-display.stderr":"16d538914e0d92026bde4b4bec75660217da9ecc6b621d12d2eb81d33ed1d1da","tests/ui/transparent-enum-many.rs":"2a40a764fb4683bff57973eec61507a6c00f7d4d7a32da6e7bd0190c2e445434","tests/ui/transparent-enum-many.stderr":"f1d78c1d6d8edbef153420db4fb9ca3dc6076fa043b5b1bc0cd291daa417a3ea","tests/ui/transparent-enum-not-error.rs":"f6315993e68bc71d6d4d39afa4d059695308ef785f92cc0d1df3e9ff55be2a9a","tests/ui/transparent-enum-not-error.stderr":"3a5fe056cd4566f402b03cb591394e0ba85bd74da53df3c8d50bda4a05c2e5ba","tests/ui/transparent-enum-source.rs":"18f606a98ac0a53f08dc56f5f923b9cbe75d25ed34479c777b48dac305d5968c","tests/ui/transparent-enum-source.stderr":"1b2e0ac53951034575d43ec0396c4e2b3cfb272db2aef8d6baa13a7e1632cc84","tests/ui/transparent-enum-unnamed-field-not-error.rs":"0c720567e9e0f87921055dfa9f607661725377633445e01a4b5048c7a7a50a85","tests/ui/transparent-enum-unnamed-field-not-error.stderr":"6d84e9a7f4e88daba12931a6c1508be60bb19125d06e44fa2fa205126d953bb1","tests/ui/transparent-struct-many.rs":"72c6b6c1a44c203d3bc68989b2f1ec092531ef75b745432824c3776c290326f6","tests/ui/transparent-struct-many.stderr":"7bd0536dbb54a0ce7d4a8e66ca7624a1b132d8a1d1e4fecca642ec77494ac01c","tests/ui/transparent-struct-not-error.rs":"fd814d3141c9182b1267b558d9daef8dd6e8b6462e1ad42b197f3a1c0703dce2","tests/ui/transparent-struct-not-error.stderr":"ac7634ea72096d8a5c1a91fd4f1b45ef870130a2698d9ae7c6530cec2f9799d5","tests/ui/transparent-struct-source.rs":"863fa691ed7d27e8767da58d9ee11fd40d6642274b36338ca1074c07964ea2b3","tests/ui/transparent-struct-source.stderr":"267dab65929e67d32347fb467a00b43af931f8205d727d7671938580217fc70e","tests/ui/transparent-struct-unnamed-field-not-error.rs":"fbff5874be44a5dcc347693d7929537256b187dfec467ed72c9968c095228d8d","tests/ui/transparent-struct-unnamed-field-not-error.stderr":"ea99d5422348c2588ad7374360e2a24649f040b9c5614c9308eff958f61960ec","tests/ui/unexpected-field-fmt.rs":"29fba7b4d81c642ec8e47cfe053aa515acf9080a86d65e685363a48993becfe3","tests/ui/unexpected-field-fmt.stderr":"20731c4a08af04bed3ff513903adadd690b6bc532b15604557e7f25575a8338f","tests/ui/unexpected-struct-source.rs":"c6cbe882d622635c216feb8290b1bd536ce0ec4feee16bc087667a21b3641d5c","tests/ui/unexpected-struct-source.stderr":"7c8227513478f6cc09e8a28be337c8a0e758a06ca5978d774c91bd43c4a54043","tests/ui/union.rs":"331adff27cebd8b95b03b6742cc8247331fda1f961e1590ed39c8d39f50cf1d8","tests/ui/union.stderr":"5f67ad29753d6fb14bc03aef7d4a1f660ee7796e469c037efbf8b13456934ad3"},"package":"f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"} \ No newline at end of file
diff --git a/third_party/rust/thiserror/Cargo.toml b/third_party/rust/thiserror/Cargo.toml
index bb7315063c..b22f808e28 100644
--- a/third_party/rust/thiserror/Cargo.toml
+++ b/third_party/rust/thiserror/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.56"
name = "thiserror"
-version = "1.0.57"
+version = "1.0.59"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "derive(Error)"
documentation = "https://docs.rs/thiserror"
@@ -32,7 +32,7 @@ rustdoc-args = ["--generate-link-to-definition"]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies.thiserror-impl]
-version = "=1.0.57"
+version = "=1.0.59"
[dev-dependencies.anyhow]
version = "1.0.73"
diff --git a/third_party/rust/thiserror/build.rs b/third_party/rust/thiserror/build.rs
index 0b995d8ea0..ad42f256f5 100644
--- a/third_party/rust/thiserror/build.rs
+++ b/third_party/rust/thiserror/build.rs
@@ -1,5 +1,6 @@
use std::env;
use std::ffi::OsString;
+use std::iter;
use std::path::Path;
use std::process::{self, Command, Stdio};
@@ -66,15 +67,15 @@ fn compile_probe(rustc_bootstrap: bool) -> bool {
let out_dir = cargo_env_var("OUT_DIR");
let probefile = Path::new("build").join("probe.rs");
- // Make sure to pick up Cargo rustc configuration.
- let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER") {
- let mut cmd = Command::new(wrapper);
- // The wrapper's first argument is supposed to be the path to rustc.
- cmd.arg(rustc);
- cmd
- } else {
- Command::new(rustc)
- };
+ let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty());
+ let rustc_workspace_wrapper =
+ env::var_os("RUSTC_WORKSPACE_WRAPPER").filter(|wrapper| !wrapper.is_empty());
+ let mut rustc = rustc_wrapper
+ .into_iter()
+ .chain(rustc_workspace_wrapper)
+ .chain(iter::once(rustc));
+ let mut cmd = Command::new(rustc.next().unwrap());
+ cmd.args(rustc);
if !rustc_bootstrap {
cmd.env_remove("RUSTC_BOOTSTRAP");
@@ -84,6 +85,7 @@ fn compile_probe(rustc_bootstrap: bool) -> bool {
.arg("--edition=2018")
.arg("--crate-name=thiserror")
.arg("--crate-type=lib")
+ .arg("--cap-lints=allow")
.arg("--emit=dep-info,metadata")
.arg("--out-dir")
.arg(out_dir)
diff --git a/third_party/rust/thiserror/src/lib.rs b/third_party/rust/thiserror/src/lib.rs
index 717cdc6f19..5b07dca600 100644
--- a/third_party/rust/thiserror/src/lib.rs
+++ b/third_party/rust/thiserror/src/lib.rs
@@ -228,7 +228,7 @@
//!
//! [`anyhow`]: https://github.com/dtolnay/anyhow
-#![doc(html_root_url = "https://docs.rs/thiserror/1.0.57")]
+#![doc(html_root_url = "https://docs.rs/thiserror/1.0.59")]
#![allow(
clippy::module_name_repetitions,
clippy::needless_lifetimes,
diff --git a/third_party/rust/thiserror/tests/test_lints.rs b/third_party/rust/thiserror/tests/test_lints.rs
index 59699a4a3f..cafcbc0f36 100644
--- a/third_party/rust/thiserror/tests/test_lints.rs
+++ b/third_party/rust/thiserror/tests/test_lints.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::mixed_attributes_style)]
+
use thiserror::Error;
pub use std::error::Error;
diff --git a/third_party/rust/uniffi-example-arithmetic/.cargo-checksum.json b/third_party/rust/uniffi-example-arithmetic/.cargo-checksum.json
deleted file mode 100644
index 33a5447821..0000000000
--- a/third_party/rust/uniffi-example-arithmetic/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"359cffb76e0eac82aeec6a667f7670fa4b88346c2dd7c17febe71731fd6df58b","build.rs":"7d98b49c1d9c868c4199f0417eaa017ab459cdd536e9a29851d5f707941f9ead","src/arithmetic.udl":"8554c6907ece627645f6b896f71430e5412bf19b0ac6becf63eb9a69868d0f7a","src/lib.rs":"c454193443e92d49f997c760f4131192fb66bf213bbac1710c1ebde19e765e5d","tests/bindings/test_arithmetic.kts":"e0e9347755db4e18f70b1b74c2d5a4aa328373015090ed959b46d65c2a205d92","tests/bindings/test_arithmetic.py":"3e41d69e21e96a6830197c760f3b7bddd754edc0c5515b7bd33b79cccb10f941","tests/bindings/test_arithmetic.rb":"ea0fdce0a4c7b557b427db77521da05240cd6e87d60a128ac2307fab3bbbc76d","tests/bindings/test_arithmetic.swift":"455b87d95fc690af9c35f9e43676e9c855dedddd2fc1c9e1cbaa6a02835c2d4c","tests/test_generated_bindings.rs":"26b92d6b3e648f6fadd4182cbdba4f412b73da48a789785fd98cd486b29abf05","uniffi.toml":"a2d4f46fa51dc1be1e8bcdf67ec13223637fc1b6c6437455cf53c2dae065fb45"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/uniffi-example-arithmetic/Cargo.toml b/third_party/rust/uniffi-example-arithmetic/Cargo.toml
deleted file mode 100644
index 52f08bb9f6..0000000000
--- a/third_party/rust/uniffi-example-arithmetic/Cargo.toml
+++ /dev/null
@@ -1,42 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2021"
-name = "uniffi-example-arithmetic"
-version = "0.22.0"
-authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
-publish = false
-license = "MPL-2.0"
-
-[lib]
-name = "arithmetical"
-crate-type = [
- "lib",
- "cdylib",
-]
-
-[dependencies]
-thiserror = "1.0"
-
-[dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-
-[dev-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["bindgen-tests"]
-
-[build-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["build"]
diff --git a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.py b/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.py
deleted file mode 100644
index 0d4e666fbf..0000000000
--- a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from arithmetic import *
-
-try:
- add(18446744073709551615, 1)
- assert(not("Should have thrown a IntegerOverflow exception!"))
-except ArithmeticError.IntegerOverflow:
- # It's okay!
- pass
-
-assert add(2, 4) == 6
-assert add(4, 8) == 12
-
-try:
- sub(0, 1)
- assert(not("Should have thrown a IntegerOverflow exception!"))
-except ArithmeticError.IntegerOverflow:
- # It's okay!
- pass
-
-assert sub(4, 2) == 2
-assert sub(8, 4) == 4
-
-assert div(8, 4) == 2
-
-try:
- div(8, 0)
-except InternalError:
- # It's okay!
- pass
-else:
- assert(not("Should have panicked when dividing by zero"))
-
-assert equal(2, 2)
-assert equal(4, 4)
-
-assert not equal(2, 4)
-assert not equal(4, 8)
diff --git a/third_party/rust/uniffi-example-geometry/.cargo-checksum.json b/third_party/rust/uniffi-example-geometry/.cargo-checksum.json
deleted file mode 100644
index 52b8ef33db..0000000000
--- a/third_party/rust/uniffi-example-geometry/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"2d2c1ec66f7e2aaa4553b5338e68a7b64d68b84152547e1ccc4eeb019ca97103","build.rs":"fc5da645c8862e15f3b6879db179a1e5eec6161dc1cfbf95a4db9daf107a133f","src/geometry.udl":"7da7a6ec080c7117ec3c25206e23f9ed436e60b1a26fba34f991547680443550","src/lib.rs":"f9d004c97efb1a719368169f0aab181f27439eda3520c1afaca2420433226682","tests/bindings/test_geometry.kts":"e537185e3c699df1c0468525700e8a38f9a504b2a663c38442146b951e38e9a7","tests/bindings/test_geometry.py":"600e74ba0eba4e35d824c8f6d5bd5a2120a470017e8465c32d1e954a1939d323","tests/bindings/test_geometry.rb":"651de70af595f8b52ef030a03356939e8c1d0b40e44b4155b45d565d1d1dcbed","tests/bindings/test_geometry.swift":"a61fec6bfe16020809e20e4da372748c24366767138c5672a0bfff85c4b62d78","tests/test_generated_bindings.rs":"ff8fc093ccb6ee3ee2235c09276c7bb87234ad143667429cb721e46379577f3d"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/uniffi-example-geometry/Cargo.toml b/third_party/rust/uniffi-example-geometry/Cargo.toml
deleted file mode 100644
index b9c8a0beb6..0000000000
--- a/third_party/rust/uniffi-example-geometry/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2021"
-name = "uniffi-example-geometry"
-version = "0.22.0"
-authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
-publish = false
-license = "MPL-2.0"
-
-[lib]
-name = "uniffi_geometry"
-crate-type = [
- "lib",
- "cdylib",
-]
-
-[dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-
-[dev-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["bindgen-tests"]
-
-[build-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["build"]
diff --git a/third_party/rust/uniffi-example-rondpoint/.cargo-checksum.json b/third_party/rust/uniffi-example-rondpoint/.cargo-checksum.json
deleted file mode 100644
index 2f1f261a13..0000000000
--- a/third_party/rust/uniffi-example-rondpoint/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"c0706abf631a178bfbc2e53b0b714d4a7b73059c46e1326efa4f52d235dc05f5","build.rs":"ba88cce38ecd3321a7a93623755e3339e255360a7f946d3779ded804662c081a","src/lib.rs":"740d70ab5ca22eefcc291a56a9e4ed84e9669f4cfe3890e7d79bc56ae4b991a3","src/rondpoint.udl":"c903cb8c95b3ec1b103350857c3c3bc428bfd90c86a6c48089db9e0fc6e41eb5","tests/bindings/test_rondpoint.kts":"4aac8353278807f4add95c81f4c6c61187204b9767f882fd64872ed8ac1f6451","tests/bindings/test_rondpoint.py":"af25a56c35da9a934fb9f098c25f57329c53d461be378e4c5089b12a45efa28b","tests/bindings/test_rondpoint.rb":"d4b4523084534266ea7ef3161021b9903cb8d7a75cf4624c59055af9f02d22f9","tests/bindings/test_rondpoint.swift":"fa806e7e09c22ed44496658f6e0781765447bbdd250d7adf4b1152248ed70e69","tests/test_generated_bindings.rs":"5464f89e91c458f164b83a454c6df67a2953873e8a785a4720a2253d843f88e5"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/uniffi-example-rondpoint/Cargo.toml b/third_party/rust/uniffi-example-rondpoint/Cargo.toml
deleted file mode 100644
index 44d9628df4..0000000000
--- a/third_party/rust/uniffi-example-rondpoint/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2021"
-name = "uniffi-example-rondpoint"
-version = "0.22.0"
-authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
-publish = false
-license = "MPL-2.0"
-
-[lib]
-name = "uniffi_rondpoint"
-crate-type = [
- "lib",
- "cdylib",
-]
-
-[dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-
-[dev-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["bindgen-tests"]
-
-[build-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["build"]
diff --git a/third_party/rust/uniffi-example-sprites/.cargo-checksum.json b/third_party/rust/uniffi-example-sprites/.cargo-checksum.json
deleted file mode 100644
index 8a890fb65c..0000000000
--- a/third_party/rust/uniffi-example-sprites/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"94385b28fdc7e33b7019fada486124c027d29b3d2b11b57e8d488658386f7974","build.rs":"7e9d92d7c8fc17b359a29117b137ffc4d32f6c10b450d03e30a396339d8c9099","src/lib.rs":"d7984c0c10011b1bd939bce71dae7437ebb9090583b5d1b1cc133c2e5f60ab66","src/sprites.udl":"bfd35f04ba0549301189dfb8fc45b0f39bad00956c324f33be0e845fb7ff78aa","tests/bindings/test_sprites.kts":"06ed115325f37ce59ed6f33e2d651cd2aa352fddcc644580f62a6da6ca075844","tests/bindings/test_sprites.py":"f976f2be7ab8b88e8b84def760a849c0d98f4c7b481f054f92b566325d78d52d","tests/bindings/test_sprites.rb":"009d545bb7167b7218211430cfaeeb143cc30617eedcf3e51baafe752ad43241","tests/bindings/test_sprites.swift":"b2c0a6f4d5edfd7de7c2ba77b838865ffda153a6f364f273456175192d3e6e00","tests/test_generated_bindings.rs":"9a22d693c97fc6d90031cc60f61ece1d9279165ad6a92c9fe937448e126e8de6"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/uniffi-example-sprites/Cargo.toml b/third_party/rust/uniffi-example-sprites/Cargo.toml
deleted file mode 100644
index c6dc9d1f4b..0000000000
--- a/third_party/rust/uniffi-example-sprites/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2021"
-name = "uniffi-example-sprites"
-version = "0.22.0"
-authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
-publish = false
-license = "MPL-2.0"
-
-[lib]
-name = "uniffi_sprites"
-crate-type = [
- "lib",
- "cdylib",
-]
-
-[dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-
-[dev-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["bindgen-tests"]
-
-[build-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["build"]
diff --git a/third_party/rust/uniffi-example-todolist/.cargo-checksum.json b/third_party/rust/uniffi-example-todolist/.cargo-checksum.json
deleted file mode 100644
index 6b3a53fc5e..0000000000
--- a/third_party/rust/uniffi-example-todolist/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"9b182bf2d363240fe1f7b41c73da4bde96d87562812885e4f3175cb6b92ea56b","build.rs":"709d073560a66876d2b975f5145a2dc36e1e3420d79328c8b62666526cae5b2d","src/lib.rs":"ccf6851beb2a3e481541dd8a3c3e3d2fbd513a410eef820221942098212a8184","src/todolist.udl":"1f8a24049c2340b9184e95facfc191ecdcb91541729ae7f20b4625d67685f13c","tests/bindings/test_todolist.kts":"f3d29b48e0193563fc4f131d91ea697f758174dcdb80ea554f233949e575bf55","tests/bindings/test_todolist.py":"8ea1377fe336adaf4cade0fe073ae5825c3b38c63e46b7f4e92b87c0fe57c036","tests/bindings/test_todolist.rb":"e8840eb81477048718a56c5fa02c0fb2e28cf0a598a20c9393ba2262d6ffb89b","tests/bindings/test_todolist.swift":"d1911b85fe0c8c0b42e5421b5af5d7359c9a65bba477d23560eb4b0f52e80662","tests/test_generated_bindings.rs":"46ef1fbedaac0c4867812ef2632a641eab36ab0ee12f5757567dd037aeddcbd3"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/uniffi-example-todolist/Cargo.toml b/third_party/rust/uniffi-example-todolist/Cargo.toml
deleted file mode 100644
index cf4de491cd..0000000000
--- a/third_party/rust/uniffi-example-todolist/Cargo.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2021"
-name = "uniffi-example-todolist"
-version = "0.22.0"
-authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
-publish = false
-license = "MPL-2.0"
-
-[lib]
-name = "uniffi_todolist"
-crate-type = [
- "lib",
- "cdylib",
-]
-
-[dependencies]
-once_cell = "1.12"
-thiserror = "1.0"
-
-[dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-
-[dev-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["bindgen-tests"]
-
-[build-dependencies.uniffi]
-version = "0.27"
-path = "../../uniffi"
-features = ["build"]
diff --git a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.py b/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.py
deleted file mode 100644
index 7b676c83de..0000000000
--- a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from todolist import *
-
-todo = TodoList()
-
-entry = TodoEntry(text="Write bindings for strings in records")
-
-todo.add_item("Write python bindings")
-
-assert(todo.get_last() == "Write python bindings")
-
-todo.add_item("Write tests for bindings")
-
-assert(todo.get_last() == "Write tests for bindings")
-
-todo.add_entry(entry)
-
-assert(todo.get_last() == "Write bindings for strings in records")
-assert(todo.get_last_entry().text == "Write bindings for strings in records")
-
-todo.add_item("Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
-assert(todo.get_last() == "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
-
-entry2 = TodoEntry(text="Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
-todo.add_entry(entry2)
-assert(todo.get_last_entry().text == "Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
-
-todo2 = TodoList()
-assert(todo != todo2)
-assert(todo is not todo2)
-
-assert(get_default_list() is None)
-
-set_default_list(todo)
-assert(todo.get_items() == get_default_list().get_items())
-
-todo2.make_default()
-assert(todo2.get_items() == get_default_list().get_items())
-
-todo.add_item("Test liveness after being demoted from default")
-assert(todo.get_last() == "Test liveness after being demoted from default")
-
-todo2.add_item("Test shared state through local vs default reference")
-assert(get_default_list().get_last() == "Test shared state through local vs default reference")
-
diff --git a/third_party/rust/wasm-encoder/.cargo-checksum.json b/third_party/rust/wasm-encoder/.cargo-checksum.json
index b9591f5309..ca7d8944ba 100644
--- a/third_party/rust/wasm-encoder/.cargo-checksum.json
+++ b/third_party/rust/wasm-encoder/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"e0d334beb383d7a06a870e93a43cee25fb37c9c416b01e056a8c5589e9b5ae0c","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"ac016c4843a7e1a5737255b39418732783592222dc518020730edf9dd46a1c13","src/component.rs":"700351503077106eadf612f46079418e0b437ed0a6179dc16979768205b2ecbf","src/component/aliases.rs":"be5215154b872ed5664f3bfe2aa1391f36a2575aa9d53971ab61868a1c446e9d","src/component/builder.rs":"ea35c74cb0369181e9c0ce9729ff175d25f05bd63b48dcbbf703a53dfc113c7c","src/component/canonicals.rs":"a4f9c7a2b8ac3783d7337a5579cf71df2f33b315b354965980bd2c483d3aa141","src/component/components.rs":"07b8cae3a400e1955cc39d142569910b4fef2136021053d0ddbd6404d810aa52","src/component/exports.rs":"1af747401f153ccd5c5adfcab55dc4d75e241536cbbdc62624c3a07dd7620056","src/component/imports.rs":"a6cd7f914de7706a1a93a40fb8d0031b4b140786a347da636c70d093401079cd","src/component/instances.rs":"a76c5e7ba0ef73ae4bff5569d177198b7f3a9959dbe9f5c1b4bae7d1a9c839b1","src/component/modules.rs":"9e80907e72360fae4d8057b6b0e7a6b58edd7ba6aba6e63ba17346518e169617","src/component/names.rs":"ca2f46a6dbc872a9cdb297d58c958e16acaf8893318bfdba30e468841107d886","src/component/start.rs":"4055553d5c99c99abbc01bb8abb928ecb8b909d148b647a9977fbd444bb464a3","src/component/types.rs":"f44501e9b356e5588767323f1844e768221e00843a33354ff2597a76f32def46","src/core.rs":"a00656f82a623656c59a2d7230b40a5849a5083e117bc57061746f6e3022c7bb","src/core/code.rs":"23f96e90b57b1334b304bc66c9c39518d9d8baee1e2a7f5e3045f817019c62da","src/core/custom.rs":"4b9f07b701dc7b6990d92fb43016c28fb971411670bb6a48553b92b1c35eb9a3","src/core/data.rs":"c9d59eab2ab811bd950da52e6766c7df2367986c7a3a0d94d7aeb47d86f203ac","src/core/dump.rs":"8feaa532e3851186277ec1f4906e7fdc82c6399b211b8c928b16e293db1205b0","src/core/elements.rs":"2df1ad85f683b5cf3ce43c8cfef3f08f74a17cec9171537e3f24205dc067b4f7","src/core/exports.rs":"9e1eb3db0e0f73e00b66d82431257923feec8c052ac8b98717c8f36ffcc03537","src/core/functions.rs":"c18b9872ac0c21048a3ce32e5e44e8e702f97a57fa1b3a07bdd98c7f6c820f09","src/core/globals.rs":"0ed5f033489318d91e974090e8bf240720baa1ba621d0b5e0956dbd68e2165c1","src/core/imports.rs":"b4b096a6b1f449c4429efff605ca597549ea31873e18a9e6e55c616b4edc76db","src/core/linking.rs":"2f1053d9c2671e91a2b6e253dd38921bfc5f1b8a1a047b10c843033fe0f492de","src/core/memories.rs":"42e11ff5e8b2634bcd87810aef3fb9057c5d0b23c68ca9862a1e99aab5ecad72","src/core/names.rs":"2624a58835b27b17260fdbd20704856dce04e1826eb2b3b6196f8f1ffcf560ef","src/core/producers.rs":"f4916c1cf61e26170cd10fe350de7dad18005461c362909b9557c16c507517bc","src/core/start.rs":"a01d4a91bcd93048977ccafc6af160357297450395bf598351f5a3e6d322e0de","src/core/tables.rs":"c8286f5624ff429d42879932dedf45975513abfd98071a4084271860225af078","src/core/tags.rs":"66251072d5108dfde8177039cef95deac21606a361cddb04f37c08b8a8969db4","src/core/types.rs":"eb61f4f53a6c283ff6788c9724ffb728d2f525a62230bd13494a797ee23fbfef","src/lib.rs":"e61325ab8de1b4c404f4ee7665eef404fca2d23322a9c8f94efec8426edc166b","src/raw.rs":"a6a72cfe8f88ea6476eccee4acf362030ba2d2e5710215bc4f13cde7de6d71ae"},"package":"b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a"} \ No newline at end of file
+{"files":{"Cargo.toml":"dd8325b9b609ebb74c8fb1472fb2147bae3053bb7b481cf5375e4da172aa05c7","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"ac016c4843a7e1a5737255b39418732783592222dc518020730edf9dd46a1c13","src/component.rs":"700351503077106eadf612f46079418e0b437ed0a6179dc16979768205b2ecbf","src/component/aliases.rs":"be5215154b872ed5664f3bfe2aa1391f36a2575aa9d53971ab61868a1c446e9d","src/component/builder.rs":"ea35c74cb0369181e9c0ce9729ff175d25f05bd63b48dcbbf703a53dfc113c7c","src/component/canonicals.rs":"a4f9c7a2b8ac3783d7337a5579cf71df2f33b315b354965980bd2c483d3aa141","src/component/components.rs":"07b8cae3a400e1955cc39d142569910b4fef2136021053d0ddbd6404d810aa52","src/component/exports.rs":"1af747401f153ccd5c5adfcab55dc4d75e241536cbbdc62624c3a07dd7620056","src/component/imports.rs":"a6cd7f914de7706a1a93a40fb8d0031b4b140786a347da636c70d093401079cd","src/component/instances.rs":"a76c5e7ba0ef73ae4bff5569d177198b7f3a9959dbe9f5c1b4bae7d1a9c839b1","src/component/modules.rs":"9e80907e72360fae4d8057b6b0e7a6b58edd7ba6aba6e63ba17346518e169617","src/component/names.rs":"ca2f46a6dbc872a9cdb297d58c958e16acaf8893318bfdba30e468841107d886","src/component/start.rs":"4055553d5c99c99abbc01bb8abb928ecb8b909d148b647a9977fbd444bb464a3","src/component/types.rs":"069f0ee5fc4001c26a0db4bab32c8db268af68a11bf50a55f07c9365f2317e5f","src/core.rs":"a00656f82a623656c59a2d7230b40a5849a5083e117bc57061746f6e3022c7bb","src/core/code.rs":"49d8b8414f62d2851e7dc1bb5965037a12d2ef2a02bec8f96349779b352e7d9e","src/core/custom.rs":"4b9f07b701dc7b6990d92fb43016c28fb971411670bb6a48553b92b1c35eb9a3","src/core/data.rs":"f209e23710ab75600dd200af176e23940c88fac8a6ca31c3df67b97a911f2c55","src/core/dump.rs":"8feaa532e3851186277ec1f4906e7fdc82c6399b211b8c928b16e293db1205b0","src/core/elements.rs":"2df1ad85f683b5cf3ce43c8cfef3f08f74a17cec9171537e3f24205dc067b4f7","src/core/exports.rs":"9e1eb3db0e0f73e00b66d82431257923feec8c052ac8b98717c8f36ffcc03537","src/core/functions.rs":"c18b9872ac0c21048a3ce32e5e44e8e702f97a57fa1b3a07bdd98c7f6c820f09","src/core/globals.rs":"15408072945d2d96d16c1020ec1a029a348fbe22da26eb35d02d695527f675ba","src/core/imports.rs":"af26ca7dd09cb2b8ecfbe347378252f4d12b92e23818e23d72512591ceee671c","src/core/linking.rs":"2f1053d9c2671e91a2b6e253dd38921bfc5f1b8a1a047b10c843033fe0f492de","src/core/memories.rs":"9e437e878e61933bc731ef20994aefedb0ac4ac6b9464e36b38a8cdc26019dd8","src/core/names.rs":"2624a58835b27b17260fdbd20704856dce04e1826eb2b3b6196f8f1ffcf560ef","src/core/producers.rs":"f4916c1cf61e26170cd10fe350de7dad18005461c362909b9557c16c507517bc","src/core/start.rs":"a01d4a91bcd93048977ccafc6af160357297450395bf598351f5a3e6d322e0de","src/core/tables.rs":"c8286f5624ff429d42879932dedf45975513abfd98071a4084271860225af078","src/core/tags.rs":"66251072d5108dfde8177039cef95deac21606a361cddb04f37c08b8a8969db4","src/core/types.rs":"1f3f5b2bc09ea6f4a569ddfb7e343bf3fb450d8508b3bf338915dad98aad9582","src/lib.rs":"e61325ab8de1b4c404f4ee7665eef404fca2d23322a9c8f94efec8426edc166b","src/raw.rs":"a6a72cfe8f88ea6476eccee4acf362030ba2d2e5710215bc4f13cde7de6d71ae"},"package":"90e95b3563d164f33c1cfb0a7efbd5940c37710019be10cd09f800fdec8b0e5c"} \ No newline at end of file
diff --git a/third_party/rust/wasm-encoder/Cargo.toml b/third_party/rust/wasm-encoder/Cargo.toml
index aa4ce5bc7c..9fd28b544d 100644
--- a/third_party/rust/wasm-encoder/Cargo.toml
+++ b/third_party/rust/wasm-encoder/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "wasm-encoder"
-version = "0.201.0"
+version = "0.205.0"
authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
description = """
A low-level WebAssembly encoder.
@@ -27,7 +27,7 @@ repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wa
version = "0.2.4"
[dependencies.wasmparser]
-version = "0.201.0"
+version = "0.205.0"
optional = true
[dev-dependencies.anyhow]
diff --git a/third_party/rust/wasm-encoder/src/component/types.rs b/third_party/rust/wasm-encoder/src/component/types.rs
index 537e8c5a00..72e0034b6b 100644
--- a/third_party/rust/wasm-encoder/src/component/types.rs
+++ b/third_party/rust/wasm-encoder/src/component/types.rs
@@ -497,10 +497,10 @@ pub enum PrimitiveValType {
S64,
/// The type is an unsigned 64-bit integer.
U64,
- /// The type is a 32-bit floating point number.
- Float32,
- /// The type is a 64-bit floating point number.
- Float64,
+ /// The type is a 32-bit floating point number with only one NaN.
+ F32,
+ /// The type is a 64-bit floating point number with only one NaN.
+ F64,
/// The type is a Unicode character.
Char,
/// The type is a string.
@@ -519,8 +519,8 @@ impl Encode for PrimitiveValType {
Self::U32 => 0x79,
Self::S64 => 0x78,
Self::U64 => 0x77,
- Self::Float32 => 0x76,
- Self::Float64 => 0x75,
+ Self::F32 => 0x76,
+ Self::F64 => 0x75,
Self::Char => 0x74,
Self::String => 0x73,
});
@@ -540,8 +540,8 @@ impl From<wasmparser::PrimitiveValType> for PrimitiveValType {
wasmparser::PrimitiveValType::U32 => PrimitiveValType::U32,
wasmparser::PrimitiveValType::S64 => PrimitiveValType::S64,
wasmparser::PrimitiveValType::U64 => PrimitiveValType::U64,
- wasmparser::PrimitiveValType::Float32 => PrimitiveValType::Float32,
- wasmparser::PrimitiveValType::Float64 => PrimitiveValType::Float64,
+ wasmparser::PrimitiveValType::F32 => PrimitiveValType::F32,
+ wasmparser::PrimitiveValType::F64 => PrimitiveValType::F64,
wasmparser::PrimitiveValType::Char => PrimitiveValType::Char,
wasmparser::PrimitiveValType::String => PrimitiveValType::String,
}
diff --git a/third_party/rust/wasm-encoder/src/core/code.rs b/third_party/rust/wasm-encoder/src/core/code.rs
index 76bfd7afde..4b04b0b72b 100644
--- a/third_party/rust/wasm-encoder/src/core/code.rs
+++ b/third_party/rust/wasm-encoder/src/core/code.rs
@@ -274,6 +274,34 @@ impl Encode for MemArg {
}
}
+/// The memory ordering for atomic instructions.
+///
+/// For an in-depth explanation of memory orderings, see the C++ documentation
+/// for [`memory_order`] or the Rust documentation for [`atomic::Ordering`].
+///
+/// [`memory_order`]: https://en.cppreference.com/w/cpp/atomic/memory_order
+/// [`atomic::Ordering`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html
+#[derive(Clone, Copy, Debug)]
+pub enum Ordering {
+ /// For a load, it acquires; this orders all operations before the last
+ /// "releasing" store. For a store, it releases; this orders all operations
+ /// before it at the next "acquiring" load.
+ AcqRel,
+ /// Like `AcqRel` but all threads see all sequentially consistent operations
+ /// in the same order.
+ SeqCst,
+}
+
+impl Encode for Ordering {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let flag: u8 = match self {
+ Ordering::SeqCst => 0,
+ Ordering::AcqRel => 1,
+ };
+ sink.push(flag);
+ }
+}
+
/// Describe an unchecked SIMD lane index.
pub type Lane = u8;
@@ -980,6 +1008,16 @@ pub enum Instruction<'a> {
I64AtomicRmw8CmpxchgU(MemArg),
I64AtomicRmw16CmpxchgU(MemArg),
I64AtomicRmw32CmpxchgU(MemArg),
+
+ // More atomic instructions (the shared-everything-threads proposal)
+ GlobalAtomicGet {
+ ordering: Ordering,
+ global_index: u32,
+ },
+ GlobalAtomicSet {
+ ordering: Ordering,
+ global_index: u32,
+ },
}
impl Encode for Instruction<'_> {
@@ -2787,7 +2825,7 @@ impl Encode for Instruction<'_> {
0x113u32.encode(sink);
}
- // Atmoic instructions from the thread proposal
+ // Atomic instructions from the thread proposal
Instruction::MemoryAtomicNotify(memarg) => {
sink.push(0xFE);
sink.push(0x00);
@@ -3123,6 +3161,26 @@ impl Encode for Instruction<'_> {
sink.push(0x4E);
memarg.encode(sink);
}
+
+ // Atomic instructions from the shared-everything-threads proposal
+ Instruction::GlobalAtomicGet {
+ ordering,
+ global_index,
+ } => {
+ sink.push(0xFE);
+ sink.push(0x4F);
+ ordering.encode(sink);
+ global_index.encode(sink);
+ }
+ Instruction::GlobalAtomicSet {
+ ordering,
+ global_index,
+ } => {
+ sink.push(0xFE);
+ sink.push(0x50);
+ ordering.encode(sink);
+ global_index.encode(sink);
+ }
}
}
}
diff --git a/third_party/rust/wasm-encoder/src/core/data.rs b/third_party/rust/wasm-encoder/src/core/data.rs
index 6439b66e2e..6f408befe5 100644
--- a/third_party/rust/wasm-encoder/src/core/data.rs
+++ b/third_party/rust/wasm-encoder/src/core/data.rs
@@ -18,6 +18,7 @@ use crate::{encode_section, encoding_size, ConstExpr, Encode, Section, SectionId
/// maximum: None,
/// memory64: false,
/// shared: false,
+/// page_size_log2: None,
/// });
///
/// let mut data = DataSection::new();
diff --git a/third_party/rust/wasm-encoder/src/core/globals.rs b/third_party/rust/wasm-encoder/src/core/globals.rs
index 64fec982cd..291ca80472 100644
--- a/third_party/rust/wasm-encoder/src/core/globals.rs
+++ b/third_party/rust/wasm-encoder/src/core/globals.rs
@@ -14,6 +14,7 @@ use crate::{encode_section, ConstExpr, Encode, Section, SectionId, ValType};
/// GlobalType {
/// val_type: ValType::I32,
/// mutable: false,
+/// shared: false,
/// },
/// &ConstExpr::i32_const(42),
/// );
@@ -80,12 +81,21 @@ pub struct GlobalType {
pub val_type: ValType,
/// Whether this global is mutable or not.
pub mutable: bool,
+ /// Whether this global is shared or not.
+ pub shared: bool,
}
impl Encode for GlobalType {
fn encode(&self, sink: &mut Vec<u8>) {
self.val_type.encode(sink);
- sink.push(self.mutable as u8);
+ let mut flag = 0;
+ if self.mutable {
+ flag |= 0b01;
+ }
+ if self.shared {
+ flag |= 0b10;
+ }
+ sink.push(flag);
}
}
@@ -96,6 +106,7 @@ impl TryFrom<wasmparser::GlobalType> for GlobalType {
Ok(GlobalType {
val_type: global_ty.content_type.try_into()?,
mutable: global_ty.mutable,
+ shared: global_ty.shared,
})
}
}
diff --git a/third_party/rust/wasm-encoder/src/core/imports.rs b/third_party/rust/wasm-encoder/src/core/imports.rs
index 0030d640e6..d4db2e65c5 100644
--- a/third_party/rust/wasm-encoder/src/core/imports.rs
+++ b/third_party/rust/wasm-encoder/src/core/imports.rs
@@ -103,6 +103,7 @@ impl TryFrom<wasmparser::TypeRef> for EntityType {
/// maximum: None,
/// memory64: false,
/// shared: false,
+/// page_size_log2: None,
/// }
/// );
///
diff --git a/third_party/rust/wasm-encoder/src/core/memories.rs b/third_party/rust/wasm-encoder/src/core/memories.rs
index 892545eb98..d64ef01210 100644
--- a/third_party/rust/wasm-encoder/src/core/memories.rs
+++ b/third_party/rust/wasm-encoder/src/core/memories.rs
@@ -15,6 +15,7 @@ use crate::{encode_section, Encode, Section, SectionId};
/// maximum: None,
/// memory64: false,
/// shared: false,
+/// page_size_log2: None,
/// });
///
/// let mut module = Module::new();
@@ -75,26 +76,41 @@ pub struct MemoryType {
pub memory64: bool,
/// Whether or not this memory is shared.
pub shared: bool,
+ /// The log base 2 of a custom page size for this memory.
+ ///
+ /// The default page size for Wasm memories is 64KiB, i.e. 2<sup>16</sup> or
+ /// `65536`.
+ ///
+ /// After the introduction of [the custom-page-sizes
+ /// proposal](https://github.com/WebAssembly/custom-page-sizes), Wasm can
+ /// customize the page size. It must be a power of two that is less than or
+ /// equal to 64KiB. Attempting to encode an invalid page size may panic.
+ pub page_size_log2: Option<u32>,
}
impl Encode for MemoryType {
fn encode(&self, sink: &mut Vec<u8>) {
let mut flags = 0;
if self.maximum.is_some() {
- flags |= 0b001;
+ flags |= 0b0001;
}
if self.shared {
- flags |= 0b010;
+ flags |= 0b0010;
}
if self.memory64 {
- flags |= 0b100;
+ flags |= 0b0100;
+ }
+ if self.page_size_log2.is_some() {
+ flags |= 0b1000;
}
-
sink.push(flags);
self.minimum.encode(sink);
if let Some(max) = self.maximum {
max.encode(sink);
}
+ if let Some(p) = self.page_size_log2 {
+ p.encode(sink);
+ }
}
}
@@ -106,6 +122,7 @@ impl From<wasmparser::MemoryType> for MemoryType {
maximum: memory_ty.maximum,
memory64: memory_ty.memory64,
shared: memory_ty.shared,
+ page_size_log2: memory_ty.page_size_log2,
}
}
}
diff --git a/third_party/rust/wasm-encoder/src/core/types.rs b/third_party/rust/wasm-encoder/src/core/types.rs
index bfc54ae1e3..8b5f340bb6 100644
--- a/third_party/rust/wasm-encoder/src/core/types.rs
+++ b/third_party/rust/wasm-encoder/src/core/types.rs
@@ -450,9 +450,12 @@ pub enum HeapType {
/// The unboxed `i31` heap type.
I31,
- /// The abstract` exception` heap type.
+ /// The abstract `exception` heap type.
Exn,
+ /// The abstract `noexn` heap type.
+ NoExn,
+
/// A concrete Wasm-defined type at the given index.
Concrete(u32),
}
@@ -471,6 +474,7 @@ impl Encode for HeapType {
HeapType::Array => sink.push(0x6A),
HeapType::I31 => sink.push(0x6C),
HeapType::Exn => sink.push(0x69),
+ HeapType::NoExn => sink.push(0x74),
// Note that this is encoded as a signed type rather than unsigned
// as it's decoded as an s33
HeapType::Concrete(i) => i64::from(*i).encode(sink),
@@ -496,6 +500,7 @@ impl TryFrom<wasmparser::HeapType> for HeapType {
wasmparser::HeapType::Array => HeapType::Array,
wasmparser::HeapType::I31 => HeapType::I31,
wasmparser::HeapType::Exn => HeapType::Exn,
+ wasmparser::HeapType::NoExn => HeapType::NoExn,
})
}
}
@@ -645,6 +650,8 @@ impl Section for TypeSection {
#[cfg(test)]
mod tests {
+ use wasmparser::WasmFeatures;
+
use super::*;
use crate::Module;
@@ -661,10 +668,8 @@ mod tests {
module.section(&types);
let wasm_bytes = module.finish();
- let mut validator = wasmparser::Validator::new_with_features(wasmparser::WasmFeatures {
- gc: false,
- ..Default::default()
- });
+ let mut validator =
+ wasmparser::Validator::new_with_features(WasmFeatures::default() & !WasmFeatures::GC);
validator.validate_all(&wasm_bytes).expect(
"Encoding pre Wasm GC type should not accidentally use Wasm GC specific encoding",
diff --git a/third_party/rust/wasm-smith/.cargo-checksum.json b/third_party/rust/wasm-smith/.cargo-checksum.json
index d61edb195b..fd68c5102e 100644
--- a/third_party/rust/wasm-smith/.cargo-checksum.json
+++ b/third_party/rust/wasm-smith/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"b911aa53dc1f5c0cb04a77e15b43c31cee98893c7bcb98b6d73405aeca6b447c","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e7b2a96cf39834aa19aed7cad8658e33445cdec7c4957658ba39e3b82cc4254b","benches/corpus.rs":"2df29556be0799f0cb1f32c8d0ae5ba0c4b9815cf4d59a8b71744d926c0693a0","src/component.rs":"253cf8d8abf785e4b5a5c614561a85b032e7f7bdec366f83d9db0702f73d2122","src/component/encode.rs":"5985e3f412595e07372a0787ec3db6c3018840df2bcfc638ab8798fd74b22778","src/config.rs":"e75d93c0a6a5ba07ff3ec1164a9b58601fadc0a0899149e14a77e8f0ab4595e4","src/core.rs":"35d3854c8caa1f61494b2f8e2b5e150d67cf88582243feeeb198e2aa93247339","src/core/code_builder.rs":"a8b27f652c8ae4b964e05933df313016ab7ffc297ca76005faca3da2792e3afc","src/core/code_builder/no_traps.rs":"2f36c548a32a6a003e6bb22a8fe7c75517b9be00c5a299212836a7e2431a8693","src/core/encode.rs":"77e1395c78ecf1b688a3c515a58be6efe1aa58d450a20a50d69598c54f7162de","src/core/terminate.rs":"c7c5f5618d393e5d9e44ae5e9bbde4b81bfa1ca3d2111d1eea875e2490f0f64b","src/lib.rs":"d393ae9daba211ba68a48dbdee545e0570cb8298e4c62319b8c8a8b9355cd6e3","tests/available_imports.rs":"6d4c1b111f35fefce55b668474ac9ba25edf7fc3e3decb88696b644aec13d603","tests/common/mod.rs":"9d0712a0b3e30030934b04785fb8632576bdcc31921ee8f524e0b2c903dee28d","tests/component.rs":"44684e990e832590a0b348ce33fadf39ee55dec52fdfa9353570edcbf65325ee","tests/core.rs":"408a50da4438be4e5343b116aa80f5ce344ba9508fad413cc5c32cd0aa2164fb","tests/exports.rs":"dcac4e18f277cbdb821f4ad7eda0a900bd73924e0818cf1b408700c9b7bba789"},"package":"61ff53a54a853f174b0df74cdb1553f1451e7bcdc23b26b1379f664ee1913d1a"} \ No newline at end of file
+{"files":{"Cargo.toml":"4efe2ea2adda65b88d8ebcc59c881faaa54aa0a259f705d5a387c5e0c4a5a5d6","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e7b2a96cf39834aa19aed7cad8658e33445cdec7c4957658ba39e3b82cc4254b","benches/corpus.rs":"2df29556be0799f0cb1f32c8d0ae5ba0c4b9815cf4d59a8b71744d926c0693a0","src/component.rs":"7846fba1f588bb8cee539d4ae162c564332fd382abc54958ab72d31f5678e191","src/component/encode.rs":"5985e3f412595e07372a0787ec3db6c3018840df2bcfc638ab8798fd74b22778","src/config.rs":"207c1ed2535f11cfdc275b2388c03b2c9fe27b6f28d5c428c6c5cf6a81abe8af","src/core.rs":"b1ec6d747677dbf54ea1892e8b0928a68c641d6e56df4151cd8f9f9ae0f89a4f","src/core/code_builder.rs":"77d216064374edf0fcd273b2d6ddf3c4f90fd792be83f85c1e198bdea0138387","src/core/code_builder/no_traps.rs":"14dab911427934dd6394b36eea9761c8722c47611b3ebf9fde1d54bebd7c4e55","src/core/encode.rs":"77e1395c78ecf1b688a3c515a58be6efe1aa58d450a20a50d69598c54f7162de","src/core/terminate.rs":"e07fe450c1fee58726bace161c5747a6f01539e8b2937724064cc7370562555c","src/lib.rs":"21abe6dc08ab1fe40e6e9a063ee93c901318278c051a45f94519b8e4f402e2dc","tests/available_imports.rs":"6d4c1b111f35fefce55b668474ac9ba25edf7fc3e3decb88696b644aec13d603","tests/common/mod.rs":"815532619bf27593765c6238173644cdda33fbd0ba80e45fef165bbd9717934d","tests/component.rs":"bbde2e2d75680184724515a82babbe93b259e14c12c55c665d266967ede8b8f1","tests/core.rs":"4500bf8ec2a51c27a7cb01ef7c117c6e1acf12f1609579fd8761961c0d6c223a","tests/exports.rs":"518fea2a776cec51b059a31420908a73ddf7303aa143104afe32c52b09f88eda"},"package":"1218f393276f7a13f6c54467434633144b46c33ecbc3cbafdc938033f0315d1a"} \ No newline at end of file
diff --git a/third_party/rust/wasm-smith/Cargo.toml b/third_party/rust/wasm-smith/Cargo.toml
index 3847409e33..3221e77872 100644
--- a/third_party/rust/wasm-smith/Cargo.toml
+++ b/third_party/rust/wasm-smith/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "wasm-smith"
-version = "0.201.0"
+version = "0.205.0"
authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
exclude = ["/benches/corpus"]
description = "A WebAssembly test case generator"
@@ -61,14 +61,14 @@ version = "1.0.166"
optional = true
[dependencies.wasm-encoder]
-version = "0.201.0"
+version = "0.205.0"
[dependencies.wasmparser]
-version = "0.201.0"
+version = "0.205.0"
optional = true
[dependencies.wat]
-version = "1.201.0"
+version = "1.205.0"
optional = true
[dev-dependencies.criterion]
@@ -79,7 +79,7 @@ version = "0.8.4"
features = ["small_rng"]
[dev-dependencies.wasmparser]
-version = "0.201.0"
+version = "0.205.0"
[features]
_internal_cli = [
diff --git a/third_party/rust/wasm-smith/src/component.rs b/third_party/rust/wasm-smith/src/component.rs
index 7a85b2bf10..35bf93231b 100644
--- a/third_party/rust/wasm-smith/src/component.rs
+++ b/third_party/rust/wasm-smith/src/component.rs
@@ -952,6 +952,7 @@ impl ComponentBuilder {
Ok(crate::core::GlobalType {
val_type: self.arbitrary_core_valtype(u)?,
mutable: u.arbitrary()?,
+ shared: false,
})
}
@@ -1308,8 +1309,8 @@ impl ComponentBuilder {
6 => Ok(PrimitiveValType::U32),
7 => Ok(PrimitiveValType::S64),
8 => Ok(PrimitiveValType::U64),
- 9 => Ok(PrimitiveValType::Float32),
- 10 => Ok(PrimitiveValType::Float64),
+ 9 => Ok(PrimitiveValType::F32),
+ 10 => Ok(PrimitiveValType::F64),
11 => Ok(PrimitiveValType::Char),
12 => Ok(PrimitiveValType::String),
_ => unreachable!(),
@@ -1773,8 +1774,8 @@ fn canonical_abi_for(func_ty: &FuncType) -> Rc<crate::core::FuncType> {
| PrimitiveValType::S32
| PrimitiveValType::U32 => ValType::I32,
PrimitiveValType::S64 | PrimitiveValType::U64 => ValType::I64,
- PrimitiveValType::Float32 => ValType::F32,
- PrimitiveValType::Float64 => ValType::F64,
+ PrimitiveValType::F32 => ValType::F32,
+ PrimitiveValType::F64 => ValType::F64,
PrimitiveValType::String => {
unimplemented!("non-scalar types are not supported yet")
}
@@ -1819,8 +1820,8 @@ fn inverse_scalar_canonical_abi_for(
ComponentValType::Primitive(PrimitiveValType::U64),
])
.cloned(),
- ValType::F32 => Ok(ComponentValType::Primitive(PrimitiveValType::Float32)),
- ValType::F64 => Ok(ComponentValType::Primitive(PrimitiveValType::Float64)),
+ ValType::F32 => Ok(ComponentValType::Primitive(PrimitiveValType::F32)),
+ ValType::F64 => Ok(ComponentValType::Primitive(PrimitiveValType::F64)),
ValType::V128 | ValType::Ref(_) => {
unreachable!("not used in canonical ABI")
}
@@ -2055,8 +2056,8 @@ fn is_scalar(ty: &ComponentValType) -> bool {
| PrimitiveValType::U32
| PrimitiveValType::S64
| PrimitiveValType::U64
- | PrimitiveValType::Float32
- | PrimitiveValType::Float64
+ | PrimitiveValType::F32
+ | PrimitiveValType::F64
| PrimitiveValType::Char => true,
PrimitiveValType::String => false,
},
diff --git a/third_party/rust/wasm-smith/src/config.rs b/third_party/rust/wasm-smith/src/config.rs
index 43dbecceb8..57bd25be24 100644
--- a/third_party/rust/wasm-smith/src/config.rs
+++ b/third_party/rust/wasm-smith/src/config.rs
@@ -313,6 +313,12 @@ define_config! {
/// Defaults to `false`.
pub gc_enabled: bool = false,
+ /// Determines whether the custom-page-sizes proposal is enabled when
+ /// generating a Wasm module.
+ ///
+ /// Defaults to `false`.
+ pub custom_page_sizes_enabled: bool = false,
+
/// Returns whether we should generate custom sections or not. Defaults
/// to false.
pub generate_custom_sections: bool = false,
@@ -681,6 +687,7 @@ impl<'a> Arbitrary<'a> for Config {
},
table_max_size_required: u.arbitrary()?,
max_table_elements: u.int_in_range(0..=1_000_000)?,
+ disallow_traps: u.arbitrary()?,
// These fields, unlike the ones above, are less useful to set.
// They either make weird inputs or are for features not widely
@@ -712,9 +719,9 @@ impl<'a> Arbitrary<'a> for Config {
exports: None,
threads_enabled: false,
export_everything: false,
- disallow_traps: false,
tail_call_enabled: false,
gc_enabled: false,
+ custom_page_sizes_enabled: false,
generate_custom_sections: false,
allow_invalid_funcs: false,
})
diff --git a/third_party/rust/wasm-smith/src/core.rs b/third_party/rust/wasm-smith/src/core.rs
index 194d2101ae..db9bb2e546 100644
--- a/third_party/rust/wasm-smith/src/core.rs
+++ b/third_party/rust/wasm-smith/src/core.rs
@@ -146,6 +146,11 @@ pub struct Module {
/// What the maximum type index that can be referenced is.
max_type_limit: MaxTypeLimit,
+
+ /// Some known-interesting values, such as powers of two, values just before
+ /// or just after a memory size, etc...
+ interesting_values32: Vec<u32>,
+ interesting_values64: Vec<u64>,
}
impl<'a> Arbitrary<'a> for Module {
@@ -232,16 +237,13 @@ impl Module {
export_names: HashSet::new(),
const_expr_choices: Vec::new(),
max_type_limit: MaxTypeLimit::ModuleTypes,
+ interesting_values32: Vec::new(),
+ interesting_values64: Vec::new(),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub(crate) struct RecGroup {
- pub(crate) types: Vec<SubType>,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) struct SubType {
pub(crate) is_final: bool,
pub(crate) supertype: Option<u32>,
@@ -494,6 +496,8 @@ impl Module {
matches!(self.ty(b).composite_type, CompositeType::Func(_))
}
+ (HT::NoExn, HT::Exn) => true,
+
// Nothing else matches. (Avoid full wildcard matches so that
// adding/modifying variants is easier in the future.)
(HT::Concrete(_), _)
@@ -506,11 +510,9 @@ impl Module {
| (HT::Eq, _)
| (HT::Struct, _)
| (HT::Array, _)
- | (HT::I31, _) => false,
-
- // TODO: `exn` probably will be its own type hierarchy and will
- // probably get `noexn` as well.
- (HT::Exn, _) => false,
+ | (HT::I31, _)
+ | (HT::Exn, _)
+ | (HT::NoExn, _) => false,
}
}
@@ -779,7 +781,7 @@ impl Module {
HT::Extern => {
choices.push(HT::NoExtern);
}
- HT::Exn | HT::None | HT::NoExtern | HT::NoFunc => {}
+ HT::Exn | HT::NoExn | HT::None | HT::NoExtern | HT::NoFunc => {}
}
Ok(*u.choose(&choices)?)
}
@@ -858,6 +860,9 @@ impl Module {
choices.extend(self.func_types.iter().copied().map(HT::Concrete));
choices.push(HT::Func);
}
+ HT::NoExn => {
+ choices.push(HT::Exn);
+ }
HT::Concrete(mut idx) => {
match &self
.types
@@ -1422,6 +1427,7 @@ impl Module {
Ok(GlobalType {
val_type: self.arbitrary_valtype(u)?,
mutable: u.arbitrary()?,
+ shared: false,
})
}
@@ -1645,6 +1651,7 @@ impl Module {
wasmparser::HeapType::Array => HeapType::Array,
wasmparser::HeapType::I31 => HeapType::I31,
wasmparser::HeapType::Exn => HeapType::Exn,
+ wasmparser::HeapType::NoExn => HeapType::NoExn,
}
}
@@ -1754,6 +1761,7 @@ impl Module {
GlobalType {
val_type: convert_val_type(&global_type.content_type),
mutable: global_type.mutable,
+ shared: global_type.shared,
},
u,
)?,
@@ -2039,6 +2047,8 @@ impl Module {
}
fn arbitrary_code(&mut self, u: &mut Unstructured) -> Result<()> {
+ self.compute_interesting_values();
+
self.code.reserve(self.num_defined_funcs);
let mut allocs = CodeBuilderAllocations::new(self, self.config.exports.is_some());
for (_, ty) in self.funcs[self.funcs.len() - self.num_defined_funcs..].iter() {
@@ -2224,6 +2234,170 @@ impl Module {
}
})
}
+
+ fn compute_interesting_values(&mut self) {
+ debug_assert!(self.interesting_values32.is_empty());
+ debug_assert!(self.interesting_values64.is_empty());
+
+ let mut interesting_values32 = HashSet::new();
+ let mut interesting_values64 = HashSet::new();
+
+ let mut interesting = |val: u64| {
+ interesting_values32.insert(val as u32);
+ interesting_values64.insert(val);
+ };
+
+ // Zero is always interesting.
+ interesting(0);
+
+ // Max values are always interesting.
+ interesting(u8::MAX as _);
+ interesting(u16::MAX as _);
+ interesting(u32::MAX as _);
+ interesting(u64::MAX);
+
+ // Min values are always interesting.
+ interesting(i8::MIN as _);
+ interesting(i16::MIN as _);
+ interesting(i32::MIN as _);
+ interesting(i64::MIN as _);
+
+ for i in 0..64 {
+ // Powers of two.
+ interesting(1 << i);
+
+ // Inverted powers of two.
+ interesting(!(1 << i));
+
+ // Powers of two minus one, AKA high bits unset and low bits set.
+ interesting((1 << i) - 1);
+
+ // Negative powers of two, AKA high bits set and low bits unset.
+ interesting(((1_i64 << 63) >> i) as _);
+ }
+
+ // Some repeating bit patterns.
+ for pattern in [0b01010101, 0b00010001, 0b00010001, 0b00000001] {
+ for b in [pattern, !pattern] {
+ interesting(u64::from_ne_bytes([b, b, b, b, b, b, b, b]));
+ }
+ }
+
+ // Interesting float values.
+ let mut interesting_f64 = |x: f64| interesting(x.to_bits());
+ interesting_f64(0.0);
+ interesting_f64(-0.0);
+ interesting_f64(f64::INFINITY);
+ interesting_f64(f64::NEG_INFINITY);
+ interesting_f64(f64::EPSILON);
+ interesting_f64(-f64::EPSILON);
+ interesting_f64(f64::MIN);
+ interesting_f64(f64::MIN_POSITIVE);
+ interesting_f64(f64::MAX);
+ interesting_f64(f64::NAN);
+ let mut interesting_f32 = |x: f32| interesting(x.to_bits() as _);
+ interesting_f32(0.0);
+ interesting_f32(-0.0);
+ interesting_f32(f32::INFINITY);
+ interesting_f32(f32::NEG_INFINITY);
+ interesting_f32(f32::EPSILON);
+ interesting_f32(-f32::EPSILON);
+ interesting_f32(f32::MIN);
+ interesting_f32(f32::MIN_POSITIVE);
+ interesting_f32(f32::MAX);
+ interesting_f32(f32::NAN);
+
+ // Interesting values related to table bounds.
+ for t in self.tables.iter() {
+ interesting(t.minimum as _);
+ if let Some(x) = t.minimum.checked_add(1) {
+ interesting(x as _);
+ }
+
+ if let Some(x) = t.maximum {
+ interesting(x as _);
+ if let Some(y) = x.checked_add(1) {
+ interesting(y as _);
+ }
+ }
+ }
+
+ // Interesting values related to memory bounds.
+ for m in self.memories.iter() {
+ let min = m.minimum.saturating_mul(crate::page_size(m).into());
+ interesting(min);
+ for i in 0..5 {
+ if let Some(x) = min.checked_add(1 << i) {
+ interesting(x);
+ }
+ if let Some(x) = min.checked_sub(1 << i) {
+ interesting(x);
+ }
+ }
+
+ if let Some(max) = m.maximum {
+ let max = max.saturating_mul(crate::page_size(m).into());
+ interesting(max);
+ for i in 0..5 {
+ if let Some(x) = max.checked_add(1 << i) {
+ interesting(x);
+ }
+ if let Some(x) = max.checked_sub(1 << i) {
+ interesting(x);
+ }
+ }
+ }
+ }
+
+ self.interesting_values32.extend(interesting_values32);
+ self.interesting_values64.extend(interesting_values64);
+
+ // Sort for determinism.
+ self.interesting_values32.sort();
+ self.interesting_values64.sort();
+ }
+
+ fn arbitrary_const_instruction(
+ &self,
+ ty: ValType,
+ u: &mut Unstructured<'_>,
+ ) -> Result<Instruction> {
+ debug_assert!(self.interesting_values32.len() > 0);
+ debug_assert!(self.interesting_values64.len() > 0);
+ match ty {
+ ValType::I32 => Ok(Instruction::I32Const(if u.arbitrary()? {
+ *u.choose(&self.interesting_values32)? as i32
+ } else {
+ u.arbitrary()?
+ })),
+ ValType::I64 => Ok(Instruction::I64Const(if u.arbitrary()? {
+ *u.choose(&self.interesting_values64)? as i64
+ } else {
+ u.arbitrary()?
+ })),
+ ValType::F32 => Ok(Instruction::F32Const(if u.arbitrary()? {
+ f32::from_bits(*u.choose(&self.interesting_values32)?)
+ } else {
+ u.arbitrary()?
+ })),
+ ValType::F64 => Ok(Instruction::F64Const(if u.arbitrary()? {
+ f64::from_bits(*u.choose(&self.interesting_values64)?)
+ } else {
+ u.arbitrary()?
+ })),
+ ValType::V128 => Ok(Instruction::V128Const(if u.arbitrary()? {
+ let upper = (*u.choose(&self.interesting_values64)? as i128) << 64;
+ let lower = *u.choose(&self.interesting_values64)? as i128;
+ upper | lower
+ } else {
+ u.arbitrary()?
+ })),
+ ValType::Ref(ty) => {
+ assert!(ty.nullable);
+ Ok(Instruction::RefNull(ty.heap_type))
+ }
+ }
+ }
}
pub(crate) fn arbitrary_limits32(
@@ -2344,6 +2518,11 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
// We want to favor memories <= 1gb in size, allocate at most 16k pages,
// depending on the maximum number of memories.
let memory64 = config.memory64_enabled && u.arbitrary()?;
+ let page_size = if config.custom_page_sizes_enabled && u.arbitrary()? {
+ Some(1 << u.int_in_range(0..=16)?)
+ } else {
+ None
+ };
let max_inbounds = 16 * 1024 / u64::try_from(config.max_memories).unwrap();
let min_pages = if config.disallow_traps { Some(1) } else { None };
let max_pages = min_pages.unwrap_or(0).max(if memory64 {
@@ -2363,6 +2542,7 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
maximum,
memory64,
shared,
+ page_size_log2: page_size,
})
}
diff --git a/third_party/rust/wasm-smith/src/core/code_builder.rs b/third_party/rust/wasm-smith/src/core/code_builder.rs
index a55c5aafda..150572d930 100644
--- a/third_party/rust/wasm-smith/src/core/code_builder.rs
+++ b/third_party/rust/wasm-smith/src/core/code_builder.rs
@@ -870,6 +870,7 @@ impl CodeBuilderAllocations {
module.globals.push(GlobalType {
val_type: ty,
mutable: true,
+ shared: false,
});
module.defined_globals.push((global_idx, init));
@@ -1435,7 +1436,7 @@ impl CodeBuilder<'_> {
}
operands = &[];
}
- instructions.push(arbitrary_val(*expected, u));
+ instructions.push(module.arbitrary_const_instruction(*expected, u)?);
}
Ok(())
}
@@ -1544,20 +1545,6 @@ impl CodeBuilder<'_> {
}
}
-fn arbitrary_val(ty: ValType, u: &mut Unstructured<'_>) -> Instruction {
- match ty {
- ValType::I32 => Instruction::I32Const(u.arbitrary().unwrap_or(0)),
- ValType::I64 => Instruction::I64Const(u.arbitrary().unwrap_or(0)),
- ValType::F32 => Instruction::F32Const(u.arbitrary().unwrap_or(0.0)),
- ValType::F64 => Instruction::F64Const(u.arbitrary().unwrap_or(0.0)),
- ValType::V128 => Instruction::V128Const(u.arbitrary().unwrap_or(0)),
- ValType::Ref(ty) => {
- assert!(ty.nullable);
- Instruction::RefNull(ty.heap_type)
- }
- }
-}
-
#[inline]
fn unreachable_valid(module: &Module, _: &mut CodeBuilder) -> bool {
!module.config.disallow_traps
@@ -1617,13 +1604,24 @@ fn try_table(
let i = i as u32;
let label_types = ctrl.label_types();
+
+ // Empty labels are candidates for a `catch_all` since nothing is
+ // pushed in that case.
if label_types.is_empty() {
catch_options.push(Box::new(move |_, _| Ok(Catch::All { label: i })));
}
+
+ // Labels with just an `externref` are suitable for `catch_all_refs`,
+ // which first pushes nothing since there's no tag and then pushes
+ // the caught exception value.
if label_types == [ValType::EXNREF] {
catch_options.push(Box::new(move |_, _| Ok(Catch::AllRef { label: i })));
}
+ // If there is a tag which exactly matches the types of the label we're
+ // looking at then that tag can be used as part of a `catch` branch.
+ // That tag's parameters, which are the except values, are pushed
+ // for the label.
if builder.allocs.tags.contains_key(label_types) {
let label_types = label_types.to_vec();
catch_options.push(Box::new(move |u, builder| {
@@ -1634,15 +1632,20 @@ fn try_table(
}));
}
- let mut label_types_with_exnref = label_types.to_vec();
- label_types_with_exnref.push(ValType::EXNREF);
- if builder.allocs.tags.contains_key(&label_types_with_exnref) {
- catch_options.push(Box::new(move |u, builder| {
- Ok(Catch::OneRef {
- tag: *u.choose(&builder.allocs.tags[&label_types_with_exnref])?,
- label: i,
- })
- }));
+ // And finally the last type of catch label, `catch_ref`. If the label
+ // ends with `exnref`, then use everything except the last `exnref` to
+ // see if there's a matching tag. If so then `catch_ref` can be used
+ // with that tag when branching to this label.
+ if let Some((&ValType::EXNREF, rest)) = label_types.split_last() {
+ if builder.allocs.tags.contains_key(rest) {
+ let rest = rest.to_vec();
+ catch_options.push(Box::new(move |u, builder| {
+ Ok(Catch::OneRef {
+ tag: *u.choose(&builder.allocs.tags[&rest])?,
+ label: i,
+ })
+ }));
+ }
}
}
@@ -3403,49 +3406,45 @@ fn data_drop(
fn i32_const(
u: &mut Unstructured,
- _module: &Module,
+ module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
- let x = u.arbitrary()?;
builder.push_operands(&[ValType::I32]);
- instructions.push(Instruction::I32Const(x));
+ instructions.push(module.arbitrary_const_instruction(ValType::I32, u)?);
Ok(())
}
fn i64_const(
u: &mut Unstructured,
- _module: &Module,
+ module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
- let x = u.arbitrary()?;
builder.push_operands(&[ValType::I64]);
- instructions.push(Instruction::I64Const(x));
+ instructions.push(module.arbitrary_const_instruction(ValType::I64, u)?);
Ok(())
}
fn f32_const(
u: &mut Unstructured,
- _module: &Module,
+ module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
- let x = u.arbitrary()?;
builder.push_operands(&[ValType::F32]);
- instructions.push(Instruction::F32Const(x));
+ instructions.push(module.arbitrary_const_instruction(ValType::F32, u)?);
Ok(())
}
fn f64_const(
u: &mut Unstructured,
- _module: &Module,
+ module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
- let x = u.arbitrary()?;
builder.push_operands(&[ValType::F64]);
- instructions.push(Instruction::F64Const(x));
+ instructions.push(module.arbitrary_const_instruction(ValType::F64, u)?);
Ok(())
}
@@ -5204,10 +5203,12 @@ fn memory_offset(u: &mut Unstructured, module: &Module, memory_index: u32) -> Re
assert!(a + b + c != 0);
let memory_type = &module.memories[memory_index as usize];
- let min = memory_type.minimum.saturating_mul(65536);
+ let min = memory_type
+ .minimum
+ .saturating_mul(crate::page_size(memory_type).into());
let max = memory_type
.maximum
- .map(|max| max.saturating_mul(65536))
+ .map(|max| max.saturating_mul(crate::page_size(memory_type).into()))
.unwrap_or(u64::MAX);
let (min, max, true_max) = match (memory_type.memory64, module.config.disallow_traps) {
diff --git a/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs b/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs
index 4f8b31ca9f..5ced1fa391 100644
--- a/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs
+++ b/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs
@@ -37,7 +37,10 @@ pub(crate) fn load<'a>(
// []
insts.push(Instruction::MemorySize(memarg.memory_index));
// [mem_size_in_pages:address_type]
- insts.push(int_const_inst(address_type, 65_536));
+ insts.push(int_const_inst(
+ address_type,
+ crate::page_size(memory).into(),
+ ));
// [mem_size_in_pages:address_type wasm_page_size:address_type]
insts.push(int_mul_inst(address_type));
// [mem_size_in_bytes:address_type]
@@ -116,7 +119,10 @@ pub(crate) fn store<'a>(
// []
insts.push(Instruction::MemorySize(memarg.memory_index));
// [mem_size_in_pages:address_type]
- insts.push(int_const_inst(address_type, 65_536));
+ insts.push(int_const_inst(
+ address_type,
+ crate::page_size(memory).into(),
+ ));
// [mem_size_in_pages:address_type wasm_page_size:address_type]
insts.push(int_mul_inst(address_type));
// [mem_size_in_bytes:address_type]
diff --git a/third_party/rust/wasm-smith/src/core/terminate.rs b/third_party/rust/wasm-smith/src/core/terminate.rs
index 7983c35be6..33aff2639c 100644
--- a/third_party/rust/wasm-smith/src/core/terminate.rs
+++ b/third_party/rust/wasm-smith/src/core/terminate.rs
@@ -23,6 +23,7 @@ impl Module {
self.globals.push(GlobalType {
val_type: ValType::I32,
mutable: true,
+ shared: false,
});
self.defined_globals
.push((fuel_global, ConstExpr::i32_const(default_fuel as i32)));
diff --git a/third_party/rust/wasm-smith/src/lib.rs b/third_party/rust/wasm-smith/src/lib.rs
index b985791aae..59d4ddb640 100644
--- a/third_party/rust/wasm-smith/src/lib.rs
+++ b/third_party/rust/wasm-smith/src/lib.rs
@@ -63,10 +63,16 @@ use arbitrary::{Result, Unstructured};
pub use component::Component;
pub use config::{Config, MemoryOffsetChoices};
use std::{collections::HashSet, fmt::Write, str};
+use wasm_encoder::MemoryType;
#[cfg(feature = "_internal_cli")]
pub use config::InternalOptionalConfig;
+pub(crate) fn page_size(mem: &MemoryType) -> u32 {
+ const DEFAULT_WASM_PAGE_SIZE: u32 = 65_536;
+ mem.page_size_log2.unwrap_or(DEFAULT_WASM_PAGE_SIZE)
+}
+
/// Do something an arbitrary number of times.
///
/// The callback can return `false` to exit the loop early.
diff --git a/third_party/rust/wasm-smith/tests/common/mod.rs b/third_party/rust/wasm-smith/tests/common/mod.rs
index cc24eed278..8a238776d6 100644
--- a/third_party/rust/wasm-smith/tests/common/mod.rs
+++ b/third_party/rust/wasm-smith/tests/common/mod.rs
@@ -2,30 +2,34 @@ use wasm_smith::Config;
use wasmparser::{types::Types, Validator, WasmFeatures};
pub fn parser_features_from_config(config: &Config) -> WasmFeatures {
- WasmFeatures {
- mutable_global: true,
- saturating_float_to_int: config.saturating_float_to_int_enabled,
- sign_extension: config.sign_extension_ops_enabled,
- reference_types: config.reference_types_enabled,
- multi_value: config.multi_value_enabled,
- bulk_memory: config.bulk_memory_enabled,
- simd: config.simd_enabled,
- relaxed_simd: config.relaxed_simd_enabled,
- multi_memory: config.max_memories > 1,
- exceptions: config.exceptions_enabled,
- memory64: config.memory64_enabled,
- tail_call: config.tail_call_enabled,
- function_references: config.gc_enabled,
- gc: config.gc_enabled,
-
- threads: false,
- floats: true,
- extended_const: false,
- component_model: false,
- memory_control: false,
- component_model_values: false,
- component_model_nested_names: false,
- }
+ let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::FLOATS;
+ features.set(
+ WasmFeatures::SATURATING_FLOAT_TO_INT,
+ config.saturating_float_to_int_enabled,
+ );
+ features.set(
+ WasmFeatures::SIGN_EXTENSION,
+ config.sign_extension_ops_enabled,
+ );
+ features.set(
+ WasmFeatures::REFERENCE_TYPES,
+ config.reference_types_enabled,
+ );
+ features.set(WasmFeatures::MULTI_VALUE, config.multi_value_enabled);
+ features.set(WasmFeatures::BULK_MEMORY, config.bulk_memory_enabled);
+ features.set(WasmFeatures::SIMD, config.simd_enabled);
+ features.set(WasmFeatures::RELAXED_SIMD, config.relaxed_simd_enabled);
+ features.set(WasmFeatures::MULTI_MEMORY, config.max_memories > 1);
+ features.set(WasmFeatures::EXCEPTIONS, config.exceptions_enabled);
+ features.set(WasmFeatures::MEMORY64, config.memory64_enabled);
+ features.set(WasmFeatures::TAIL_CALL, config.tail_call_enabled);
+ features.set(WasmFeatures::FUNCTION_REFERENCES, config.gc_enabled);
+ features.set(WasmFeatures::GC, config.gc_enabled);
+ features.set(
+ WasmFeatures::CUSTOM_PAGE_SIZES,
+ config.custom_page_sizes_enabled,
+ );
+ features
}
pub fn validate(validator: &mut Validator, bytes: &[u8]) -> Types {
diff --git a/third_party/rust/wasm-smith/tests/component.rs b/third_party/rust/wasm-smith/tests/component.rs
index 7d5a40159c..89fdebffaa 100644
--- a/third_party/rust/wasm-smith/tests/component.rs
+++ b/third_party/rust/wasm-smith/tests/component.rs
@@ -18,11 +18,9 @@ fn smoke_test_component() {
ok_count += 1;
let component = component.to_bytes();
- let mut validator =
- wasmparser::Validator::new_with_features(wasmparser::WasmFeatures {
- component_model: true,
- ..Default::default()
- });
+ let mut validator = wasmparser::Validator::new_with_features(
+ wasmparser::WasmFeatures::default() | wasmparser::WasmFeatures::COMPONENT_MODEL,
+ );
if let Err(e) = validator.validate_all(&component) {
std::fs::write("component.wasm", &component).unwrap();
panic!(
diff --git a/third_party/rust/wasm-smith/tests/core.rs b/third_party/rust/wasm-smith/tests/core.rs
index 7286952dc6..9b18fcdeaf 100644
--- a/third_party/rust/wasm-smith/tests/core.rs
+++ b/third_party/rust/wasm-smith/tests/core.rs
@@ -3,6 +3,9 @@ use rand::{rngs::SmallRng, RngCore, SeedableRng};
use wasm_smith::{Config, Module};
use wasmparser::{Validator, WasmFeatures};
+mod common;
+use common::{parser_features_from_config, validate};
+
#[test]
fn smoke_test_module() {
let mut rng = SmallRng::seed_from_u64(0);
@@ -66,7 +69,7 @@ fn multi_value_disabled() {
if let Ok(module) = Module::new(cfg, &mut u) {
let wasm_bytes = module.to_bytes();
let mut features = wasm_features();
- features.multi_value = false;
+ features.remove(WasmFeatures::MULTI_VALUE);
let mut validator = Validator::new_with_features(features);
validate(&mut validator, &wasm_bytes);
}
@@ -140,53 +143,5 @@ fn smoke_test_wasm_gc() {
}
fn wasm_features() -> WasmFeatures {
- WasmFeatures {
- multi_memory: true,
- relaxed_simd: true,
- memory64: true,
- exceptions: true,
- tail_call: true,
- function_references: true,
- gc: true,
- ..WasmFeatures::default()
- }
-}
-
-fn parser_features_from_config(config: &Config) -> WasmFeatures {
- WasmFeatures {
- mutable_global: true,
- saturating_float_to_int: config.saturating_float_to_int_enabled,
- sign_extension: config.sign_extension_ops_enabled,
- reference_types: config.reference_types_enabled,
- multi_value: config.multi_value_enabled,
- bulk_memory: config.bulk_memory_enabled,
- simd: config.simd_enabled,
- relaxed_simd: config.relaxed_simd_enabled,
- multi_memory: config.max_memories > 1,
- exceptions: config.exceptions_enabled,
- memory64: config.memory64_enabled,
- tail_call: config.tail_call_enabled,
-
- threads: false,
- floats: true,
- extended_const: false,
- component_model: false,
- function_references: false,
- memory_control: false,
- gc: false,
- component_model_values: false,
- component_model_nested_names: false,
- }
-}
-
-fn validate(validator: &mut Validator, bytes: &[u8]) {
- let err = match validator.validate_all(bytes) {
- Ok(_) => return,
- Err(e) => e,
- };
- drop(std::fs::write("test.wasm", &bytes));
- if let Ok(text) = wasmprinter::print_bytes(bytes) {
- drop(std::fs::write("test.wat", &text));
- }
- panic!("wasm failed to validate: {}", err);
+ WasmFeatures::all()
}
diff --git a/third_party/rust/wasm-smith/tests/exports.rs b/third_party/rust/wasm-smith/tests/exports.rs
index ff1dac0cbe..6d3e4451a2 100644
--- a/third_party/rust/wasm-smith/tests/exports.rs
+++ b/third_party/rust/wasm-smith/tests/exports.rs
@@ -1,3 +1,5 @@
+#![cfg(feature = "wasmparser")]
+
use arbitrary::{Arbitrary, Unstructured};
use rand::{rngs::SmallRng, RngCore, SeedableRng};
use wasm_smith::{Config, Module};
@@ -18,9 +20,9 @@ enum ExportType {
fn smoke_test_single_export() {
let test = r#"
(module
- (func (export "foo") (param i32) (result i64)
- unreachable
- )
+ (func (export "foo") (param i32) (result i64)
+ unreachable
+ )
)
"#;
smoke_test_exports(test, 11)
@@ -30,15 +32,15 @@ fn smoke_test_single_export() {
fn smoke_test_multiple_exports() {
let test = r#"
(module
- (func (export "a") (param i32) (result i64)
- unreachable
- )
- (func (export "b")
- unreachable
- )
- (func (export "c")
- unreachable
- )
+ (func (export "a") (param i32) (result i64)
+ unreachable
+ )
+ (func (export "b")
+ unreachable
+ )
+ (func (export "c")
+ unreachable
+ )
)
"#;
smoke_test_exports(test, 12)
@@ -48,9 +50,9 @@ fn smoke_test_multiple_exports() {
fn smoke_test_exported_global() {
let test = r#"
(module
- (func (export "a") (param i32 i32 f32 f64) (result f32)
- unreachable
- )
+ (func (export "a") (param i32 i32 f32 f64) (result f32)
+ unreachable
+ )
(global (export "glob") f64 f64.const 0)
)
"#;
diff --git a/third_party/rust/wast/.cargo-checksum.json b/third_party/rust/wast/.cargo-checksum.json
index 3852650553..98ffcfa204 100644
--- a/third_party/rust/wast/.cargo-checksum.json
+++ b/third_party/rust/wast/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"53d3c5b19092b2144bdfe0d4cd843c2b42ce0fddfca703fd09fec319232468dc","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"5a0d2b894a3ac74ee2be74715a2f22c40a08520cb4ac59183f4e7356f34ac566","src/component.rs":"23a62f4f2774ccfaf60f68e9d9416e68ba203eea782ce0c39cf553ad293f1df4","src/component/alias.rs":"5ec26333e179dc3778dead489f1273815fe9c1c808ba6a7e60eff54072fad795","src/component/binary.rs":"02b07602dc755fd5cec95b6348dd919c75f368c16a81402072201cf911be5f0d","src/component/component.rs":"0c49ff1c1c4b8fe6d330eb41bce8ad176c7208c4178090b7325e9994e83c1f20","src/component/custom.rs":"f5b23c34b73a716a986fd999fc8d8c9e24c341e83292088fe83325cd82dab4f5","src/component/expand.rs":"71b2e23f50957b4a15d758df7f8651fdbaf5cf8f44fbfeb134b412318dbd8921","src/component/export.rs":"f51e824c839d8bb0884eca509622f376c8cce3335be324b2b25033af6216fd2a","src/component/func.rs":"4f69de6c38cc6fe77b638ed7d8000c8a170d7053a11a6585dcd5b4877a06804c","src/component/import.rs":"ffe6e4ab8f2cec68b1022c753135d675ab27ecd1315bd38517472ceaffd0610c","src/component/instance.rs":"e550a7ee9af092ae084dd41e2c0ae756b7dca8da4b91d672d90265a6a15dff83","src/component/item_ref.rs":"e9c426ccc0210dc0c37bb0448468f5f4d9e52656b72d4ff0f2dc65c89957fe60","src/component/module.rs":"d27a28199d1dea1c64294a514329a524432319288515b0a0e3091fa7d3a33f74","src/component/resolve.rs":"4bc58161f3e38499cf0d7fddcbaec875579e8c48e0f347f1c820db21b8aa2d86","src/component/types.rs":"c854a2df9613145c38720d41cda571d0d01408fc09789bd22740874628cbff99","src/component/wast.rs":"36f9440618be7755db0a2994e5ff14187392c25543cdde2069e4c69111a7f490","src/core.rs":"24b71d1ab2ad874c4e37b4dd709b6532989b60e6bc503194434f95029cc1cda7","src/core/binary.rs":"59462baaf8ccb7eb44a39721b71c3627c5ff2cf5e4f24c89a158c5372732f026","src/core/custom.rs":"edd6044b75d79ec873c28d803fb8dc9a53724f1bba474bcdef2bc77196e0a4d2","src/core/export.rs":"1322a120d9e1dd6f3aa1485ee0bbc4294961028ae8a7584a24170af5823b73b1","src/core/expr.rs":"c3b66daa6d2ad3f47d1d3c6a69bd1652d289e248ab3244e448f2fba7ea291b55","src/core/func.rs":"f87239645e45b7e40ecf7f8f2b707a7cfc0620cd2632cfdaca3cb155a06da732","src/core/global.rs":"dec0abecadd2fde9298acb729259deba1ef3c4733ae5afcb4fe8cd4a633f5349","src/core/import.rs":"602a13aed2fd5fa63e2562246586546199861df57f304c2906561ab77810cadd","src/core/memory.rs":"de66cc6d6a9238428ed39ea5dccfa5ff065b4f3ec96d6cfc8405cbb16742791d","src/core/module.rs":"2b608a3cfee4df1ceeefaa046863dc964172bd6f52f6678d96078091fae7657a","src/core/resolve/deinline_import_export.rs":"41226cb8c654e7ed5a22bdb774b3901c73bed52c23a4ed6f5d0302950e02c30b","src/core/resolve/mod.rs":"9b2680b00a1cafad2dbbfdac86aa1c135ea67203bbc4dee939302b27f4aff6d0","src/core/resolve/names.rs":"afa1df4d75555dd7235a117a3c7217d1ec774b062e3a7c98d7470447561c97af","src/core/resolve/types.rs":"ff34eed438539cd88ea6c2c51e49ed42eee0d8be566d40c799254bf08125cfa8","src/core/table.rs":"6b611622d7d4f83cbe8e1a82139937c0294996d5f8208ade0886d680d8ef0b5d","src/core/tag.rs":"8a3d4fcdb86dedd68cdaf25abd930ef52a461cf2a0e9393bb9cb6f425afaaf2e","src/core/types.rs":"608f59af8c41f83c0d6db41c03f187fd30d3f85a021540a5de522464b011d52a","src/core/wast.rs":"a7307f93fb20274f0c99952deeefb51c28d4afe017702ee75d96324285346442","src/encode.rs":"0b165176db54fb9136202c54180adabda843a88e5436b96c19be9d41623912a3","src/error.rs":"4526260299c7983696a49ffe30a80139beb0d081fa8f42decc5e3283b361b1cb","src/gensym.rs":"b5e02e34443085f01deb5b657e541be7dc5d6dc952304e434a0b08320ea6c185","src/lexer.rs":"bc65c4d71c6f16a55670585a31ee615c9fcfc40a4bfa165e020ed03a9a27930d","src/lib.rs":"3b1e7af5e618b9d3ac680e7f8e9b0114fedf502496fb0e62dc95d3dbc1633772","src/names.rs":"81d49fecbff3b2abbbc323595271f32d912f03cd55a5685b7216d7cead32c420","src/parser.rs":"fe6a3727c68c8075c38422de545eb189fd8f5747ca681f6704982ed5c8ea4476","src/token.rs":"d18c2f304ffbc017a3b0a7764daeb879a8c653c330cdb6b1eae431ae6c6dd14e","src/wast.rs":"af6e208c2a37028461a6ad9101967fbfa5c7fc343fe5eb6ecad54f948c74e15d","src/wat.rs":"6fd57cf40795fabe977bdae50913f0e75c3dad3a0c0ace95df2de4f92be8aaf5","tests/annotations.rs":"06294077550600f93a5a8c0d7e3ac38b47f00bb8933f9dc390ff31868e873afb","tests/comments.rs":"694e8a3467e9c837f723a43c729be0c6f6dfe3441ad9692759b1d55fd63055a2","tests/parse-fail.rs":"0f1d5dffd1e6145105571222096703c89c4f4a46e25c848faa730f731155ea1c","tests/parse-fail/bad-core-func-alias.wat":"b71372064c3fce9d4a616418605040fe5e1356030a709b798b4769d3619cbbfb","tests/parse-fail/bad-core-func-alias.wat.err":"bb63274c26d3a21209bad794767f48372834bdc10cfbebf568a0c65d52803c90","tests/parse-fail/bad-func-alias.wat":"237c07149e1e74afe3b991a1fee6acb63167c1ca8931341614c435000339b887","tests/parse-fail/bad-func-alias.wat.err":"4a4bfc691b06d20fdf71e1dbac04649a52c76787048415599978987d761308fa","tests/parse-fail/bad-index.wat":"d21489daeec3a35327dcc9e2ba2d0acdd05f4aeaff2272cca608fda4d2338497","tests/parse-fail/bad-index.wat.err":"dc11070de0c9160573006ea4e5fa3c4d28e71bc39b24b1938cf6ff3b03ea7154","tests/parse-fail/bad-name.wat":"e5ff5d410007779a0de6609ea4cc693f0e603d36a106b8f5098c1980dd9f8124","tests/parse-fail/bad-name.wat.err":"fb5638476c1b85d9d1919e3dbcb0f16f82d088a4a22d4a0c186d7b8ba6e1902b","tests/parse-fail/bad-name2.wat":"5a6a4d0c19e5f2e48d7cebf361aca9b9000b7ef0c652997b5bd0ffaadbd2ca8a","tests/parse-fail/bad-name2.wat.err":"129707cce45f1e3cfb3e2ca5c702182e16ca5eeb2dbb2edd0710b004a8e194a5","tests/parse-fail/bad-name3.wat":"c19133d738cc84e9174301f27d4050c216bda81c7e9918d03ac792b088f24a05","tests/parse-fail/bad-name3.wat.err":"84ea63d40a619a0782ec6e94fce63921188ab87b1c3875eacae0a371144ed83a","tests/parse-fail/block1.wat":"91e74b5c3b43be692e7a6ae74fbfa674c4b6197299eb61338c4eccf282b18f17","tests/parse-fail/block1.wat.err":"40a083ae496b41dee7002cc6a664c5db0c5e4d904ae03b815773a769c4493fca","tests/parse-fail/block2.wat":"a8c07b4c09d51f10a8ffdf19806586022552398701cd90eb6d09816d45df06e5","tests/parse-fail/block2.wat.err":"33c842ec5dd0f2fdd3a9ce8187dd98b45ceee48c12810802af809d05b9cd25e9","tests/parse-fail/block3.wat":"29739abfbabd7c55f00ddfbbb9ebd818b4a114ef2336d50514f0842f7e075905","tests/parse-fail/block3.wat.err":"fc667ae2e71a260f62a3c7393bc97272e7c0ff38b17594f4370847b8a5019060","tests/parse-fail/confusing-block-comment0.wat":"8f27c9d0d212bbb1862ea89ffd7cbeafde5dfd755d695c1ba696cd520aba1a1d","tests/parse-fail/confusing-block-comment0.wat.err":"b53cbaef7bcec3862c64e09c084b92cd61bd29b954125482b2d083db250cd9e2","tests/parse-fail/confusing-block-comment1.wat":"b1a0447c9a8eaab8938d15cd33bd4adbb8bb69c2d710209b604023991a4347cb","tests/parse-fail/confusing-block-comment1.wat.err":"2fc3b3e4f98416326e1e5ec034026301069b6a98fa24451bc7573e16b8cb3811","tests/parse-fail/confusing-block-comment2.wat":"e3f49c7a388fba81081beb25d87bbd7db0acce5dd8e3eaa04574905ed7ec420c","tests/parse-fail/confusing-block-comment2.wat.err":"2183231d6acd0b5a117f9aea747c3d5c12e758450a6cd74027bb954a3134cf19","tests/parse-fail/confusing-block-comment3.wat":"d83f89c582501eb8833e772b8462c8974984a2f7fbb80b1452dc399fac74e5ed","tests/parse-fail/confusing-block-comment3.wat.err":"8b2096a4833627905c63f49cdabe44be24336646578dcfbdc67e9bfb35cbc601","tests/parse-fail/confusing-block-comment4.wat":"b7c6c68844d918e9ef6dd5ab9c40c7de7b38f04f94fadad630eda4e596f3e0f8","tests/parse-fail/confusing-block-comment4.wat.err":"2f790cc511edfcd89a12c9207901be16039fc1a06a584d73095e77a52f861cd9","tests/parse-fail/confusing-block-comment5.wat":"a159808032638cc914fa80ac4354a68b0af4f435a09cbe3e2d577582e183eb0a","tests/parse-fail/confusing-block-comment5.wat.err":"6fe0d99894307442f83fe93beaa5da706e06c9bdaf8e39d7cbae4c4fffafcb94","tests/parse-fail/confusing-block-comment6.wat":"abe48bcba2587dca98bc80ddde4e813f94fbc8a3538704a0775ea85bca0f8466","tests/parse-fail/confusing-block-comment6.wat.err":"3c97b9bf1112bbb7335d7fe4be5befb6f91eea7bec7dd3e6b543792231003c56","tests/parse-fail/confusing-block-comment7.wat":"e125c416ea5fa0ac35a58295a83a6f345438e2d7ddc6a39bd76c8e89885b3f0e","tests/parse-fail/confusing-block-comment7.wat.err":"5c34528ff2019cd3f0b3df34fd42523c0b66120706321da2c88ec05793478d2e","tests/parse-fail/confusing-block-comment8.wat":"200cc4c0e5af21a25529d7a81633a03642cff807255d6cd72eb45cdccc605cec","tests/parse-fail/confusing-block-comment8.wat.err":"9b81237d150a784b71791eee88fb6264a8bd6412862660f7392945203809e517","tests/parse-fail/confusing-line-comment0.wat":"bcec4c5a1e52b3e392e07c6711c979aa8d7db8baaf2bcdf270ba16d1aa528d26","tests/parse-fail/confusing-line-comment0.wat.err":"41ec5a075dc6b73afe1aec6b3198c5c4ae3a1a900e1610115879058ce034d6f6","tests/parse-fail/confusing-line-comment1.wat":"a2afbcab00ec957dfd9e9bf21fa4238852247b27f0b054f4a00f6b172dddf853","tests/parse-fail/confusing-line-comment1.wat.err":"f19a645e6fb5cbd7a0dd2308732741edcf83dbae0ef62549972029856a9e7fc6","tests/parse-fail/confusing-line-comment2.wat":"7f2a68229d02aac56ec4dfccf139bf2d617a0e89430357b30444dc4239d8aa89","tests/parse-fail/confusing-line-comment2.wat.err":"08add3d33e10e1ab6b4f3ae431f5db61d6f6c0a2b7d6828482a1e51b3a2d3851","tests/parse-fail/confusing-line-comment3.wat":"61173ae54782f6de86685f9555ffb94bbe2cf20b234daf660abb69ba3326f1ff","tests/parse-fail/confusing-line-comment3.wat.err":"4a5333dc02efa3c1eeab9cafa7c707f78abe92defdb01a71d6fe20944e4785f0","tests/parse-fail/confusing-line-comment4.wat":"9ecbbbe82c750e6475af1bfb46fe7a06115e4446a437d19fc08ca3d002f2a1c9","tests/parse-fail/confusing-line-comment4.wat.err":"ddb8aee8006265253b09c313cf5eb5c2dc4da66f502b4f6d3e2e1de77b35aec9","tests/parse-fail/confusing-line-comment5.wat":"8a4c8d342111bc9d37c16dbdf67c52027e1a42632abc9f359b3e4f07a85748b5","tests/parse-fail/confusing-line-comment5.wat.err":"34e368719fc0eab2f1a43c9f8e6f1b31aa9be9f971085d72374e49bde39cbfe5","tests/parse-fail/confusing-line-comment6.wat":"15f0dcdec23736ce92db84b3a7cdfe8689c97f2a7d0b9b0bfb0dcd2675163ed1","tests/parse-fail/confusing-line-comment6.wat.err":"0570be2ede803f071925d249f3858d3a417b5a6d678c9da40fc851d788d12983","tests/parse-fail/confusing-line-comment7.wat":"c7ee59301a701dd52d56cad02df78b0ad3584460bc18efa42ee137fe0c35aef6","tests/parse-fail/confusing-line-comment7.wat.err":"feebbeee8c85d8b3b85cec89435ae18f3ade9f754ca180d747a41406b64ca07a","tests/parse-fail/confusing-line-comment8.wat":"17632a8142154624de88b3cf93516147ed3419d785200bcd7049499eca8e8f04","tests/parse-fail/confusing-line-comment8.wat.err":"9c209285f2295cd2bc999aa7a9534a654932493308ab1f102839ed15a4d04d17","tests/parse-fail/confusing-string0.wat":"497b679b32baddcd6a158f4cadd3d9a9dea3457bac2a8c2c3d4e09b7c2d80842","tests/parse-fail/confusing-string0.wat.err":"cb3d737f2319346675a038716694354cd3b272453daa8a96e32e9861a9277f7b","tests/parse-fail/confusing-string1.wat":"46654cbed1ea6aab5019aef3d20098a391e40dacafa1ad5e83bf4ec384109fce","tests/parse-fail/confusing-string1.wat.err":"de7e7da516dc6c244bd0e4f012577b69f0cacbcc10f727fadb4b50bb04e0e2b4","tests/parse-fail/confusing-string2.wat":"11938f217c14387c05312735130f00c91d9df2d3ff9df7f13395e0f2b81dad54","tests/parse-fail/confusing-string2.wat.err":"e7bd08b146a855d681fefaf9e0576a9c333a2d10044f8e268b916b22a54227c9","tests/parse-fail/confusing-string3.wat":"e0ca4903fcafb9a54a91cf99e5eac95d25c6d2eb67b076f88191ad396f839cb6","tests/parse-fail/confusing-string3.wat.err":"b88d5db9e445c798eb24f95b7661b9c0368934d27ee8208477cd1c99351b939a","tests/parse-fail/confusing-string4.wat":"3ee2aee7f77604d051519c6f1795634469c12e98ae347a98f0c8445eecf1ff3d","tests/parse-fail/confusing-string4.wat.err":"1edc65bb09d8d3eed6ff69e7d9a7a4b5941dc823fa3436fa375657510255f6f4","tests/parse-fail/confusing-string5.wat":"024e50943128840d53f17e31a9b9332ce4f0ee70a847a043015f435b1c3c6e76","tests/parse-fail/confusing-string5.wat.err":"a0f13ec40d596ea2d8b0c4292b0d28775a5116ab7e11d7de88b295d25428c661","tests/parse-fail/confusing-string6.wat":"79cf157e29319800d2652c5a7f3dc90e07ebe2145c9904a70fc12027cdee84b7","tests/parse-fail/confusing-string6.wat.err":"860555e7aa13e3de3639cc2a530d6a42b974b629c4659593e972cbb0f306abae","tests/parse-fail/confusing-string7.wat":"7d8e403766dfb4e569754160d31ed0f9a27f908ed6cff96be43ab3d37f5975d5","tests/parse-fail/confusing-string7.wat.err":"658b6a02ba6d769254485f35c20984e7135d914b4266929963d723f26a40be4a","tests/parse-fail/confusing-string8.wat":"5a9b222e578655d57ee6e9f19bc1ea8e29aa52d652975fac685213444ed6458f","tests/parse-fail/confusing-string8.wat.err":"9a4e1a510330c800a1df7966998ebc3cde931eda20b249e5360f5e9a905dce11","tests/parse-fail/inline1.wat":"4e9767d67207aace2ac5e6f63a30e7510e4aa245ba35420539509e2254470272","tests/parse-fail/inline1.wat.err":"0143017a9825e518baa6009bae2c8d63520051dedd3437705bbe36b038a57f41","tests/parse-fail/newline-in-string.wat":"5c01cf709544ade0a6cdfcc39a3836a3bc018b633dc42a6cd872b6defc763ea7","tests/parse-fail/newline-in-string.wat.err":"1504209cc37a78b2aee778f23eacf78606daf964cf7bff251f5700efcd27ffd7","tests/parse-fail/string1.wat":"620d46d585ce94b382b5fde628c1399f3e562014b7a44af46e92f7bd045ca86e","tests/parse-fail/string1.wat.err":"fc53f3a1c4a65d8f25e5af51dec7699f45cecba114ca9c7871781bc70f664320","tests/parse-fail/string10.wat":"f7409dd45e153a1b11cb23e38f4ed87da12bedde38f8f0ccfe91037b0a4d97bd","tests/parse-fail/string10.wat.err":"ce677db5e37e0ed81ca357ed6b5edb21d85c27303ee194855bea7a88457efb6a","tests/parse-fail/string11.wat":"f6e0400b8c6a2014efa1ac676c567e140d8f86b5f4d5129773e6d67af537b615","tests/parse-fail/string11.wat.err":"4c6a550d29eda38a4e1bf7a589596f11655dc779479d7b8d466cfc53f815a742","tests/parse-fail/string12.wat":"23e30070eef22271651cce096a801fc4f79f3c37343c88bb8d2fc99b32d3b8b9","tests/parse-fail/string12.wat.err":"b5ec59f2996b88b2ee157e22d1774dc3e36fc08ed5bfc621aea830d30f66f586","tests/parse-fail/string13.wat":"81a305b981159ee10e140749ea3220c9edaaff53605e63c21995de47382b5faf","tests/parse-fail/string13.wat.err":"959f26c6b54e0d367b51d11d1addd8a53b5b8ff3caf70ebdd46bbea8ccfa2418","tests/parse-fail/string14.wat":"c45c2cc9f7afbfbd4be8e513106d22f7e5e817091448576c6bdf0701b81d95dd","tests/parse-fail/string14.wat.err":"50b5bccba905ddbe275938edb7ed0b09a5ca53dcdad36a7ff736ce9bc8e7a338","tests/parse-fail/string15.wat":"b5e0d5ade40de53b2d767a132e28376bb8c7a6f6238c4d8c248ae717c41d7f1f","tests/parse-fail/string15.wat.err":"0e9fc502cc90f96d1f592a3f63369fd2a3574bc4a2345a70365dbb76804e870f","tests/parse-fail/string16.wat":"38c3688cee80a9d089d239aa06eb1d27c5364ad2bd270aca57d05997c20aa682","tests/parse-fail/string16.wat.err":"4274b3bbe4df4cf0373619b1fcd082d0c802990817d2aca26ed885168c80e489","tests/parse-fail/string2.wat":"1172964aed31537b8c466d1f045f3e756926e7b221f80b2aff4a9a6721ea0beb","tests/parse-fail/string2.wat.err":"4618d3b20a78a077337eb5d6cae14ac39d9853762f011fbd23cff8921618dbde","tests/parse-fail/string3.wat":"07e0fbcd6270c1db100917c151ee4ac3f935e4ee1b27bce3c453b22b4b74f4d6","tests/parse-fail/string3.wat.err":"08ffc6158a9e030b2e211d53bdb8aeacfd879815c7b284d6a83b030566e35928","tests/parse-fail/string4.wat":"c970da2051b0613bdd1de4664f10424e14f2ebabe604175d4fb9b763b37af577","tests/parse-fail/string4.wat.err":"406706594d305c560fabd66417ad4fc276939990b5e701bd9d13fc223d207219","tests/parse-fail/string5.wat":"386cf314bb05acdaaabdf4da1caf140167271a26bd08bf34c3a7427d4bc4431f","tests/parse-fail/string5.wat.err":"1e56b44a23a37b2b2ad05aa9dd7e1e18191b5cc22151f93bbcf9d618779a57bd","tests/parse-fail/string6.wat":"8f1fe2825ff96f2acee9130a7721f86fcc93c221baa9411bf1fb6f0870d38ccb","tests/parse-fail/string6.wat.err":"d55dfd84d94e893f167ae73b7a080aefb2bfb05cc8a1ec201c4d3066fb8549b4","tests/parse-fail/string7.wat":"b12f8c75313d7f834489d3c353422f90bc945b37139586446eda82e334a97cde","tests/parse-fail/string7.wat.err":"4cee0ca61992c249dd0faaf2529a073cf8deeb36111a3f69b43695e5682560a2","tests/parse-fail/string8.wat":"4c2e0e1f883bb4e8cba9313497ed792130e5848e62bde7716102788d7467be10","tests/parse-fail/string8.wat.err":"840c6def7c60dd7c2b7261549cab435ba78c9b3a937adf6d5d9595ff8af01c91","tests/parse-fail/string9.wat":"2b7670caed2b0688d535de6e4e416f35fa717cfbe096a6cc764a669085c8f52f","tests/parse-fail/string9.wat.err":"37b5a9c3af9631500f31f9e5e3efa821b8d96063c57d60fd01df6be6a5c323e1","tests/parse-fail/unbalanced.wat":"f664fbef53a0308f864ba496d38044eb90482636e32586512939d4930729f3fe","tests/parse-fail/unbalanced.wat.err":"aba579f7b836856e69afe05da8328aabe0643d94e369898e686aa7bb0b07e9c9","tests/recursive.rs":"ad8a2b07bf955121a7c9e326ed35f9b2bc56b440c8cc0bbde24d423a79945c1a"},"package":"1ef6e1ef34d7da3e2b374fd2b1a9c0227aff6cad596e1b24df9b58d0f6222faa"} \ No newline at end of file
+{"files":{"Cargo.toml":"3e223e7ed5faa9b3eaf4893e03596e1e40688df9dc2e0863fc3c44e443d88ef9","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"5a0d2b894a3ac74ee2be74715a2f22c40a08520cb4ac59183f4e7356f34ac566","src/component.rs":"23a62f4f2774ccfaf60f68e9d9416e68ba203eea782ce0c39cf553ad293f1df4","src/component/alias.rs":"5ec26333e179dc3778dead489f1273815fe9c1c808ba6a7e60eff54072fad795","src/component/binary.rs":"310940e2c455129c5e2a4219e64fca51121755818269306f943792216810c8b2","src/component/component.rs":"0c49ff1c1c4b8fe6d330eb41bce8ad176c7208c4178090b7325e9994e83c1f20","src/component/custom.rs":"f5b23c34b73a716a986fd999fc8d8c9e24c341e83292088fe83325cd82dab4f5","src/component/expand.rs":"71b2e23f50957b4a15d758df7f8651fdbaf5cf8f44fbfeb134b412318dbd8921","src/component/export.rs":"f51e824c839d8bb0884eca509622f376c8cce3335be324b2b25033af6216fd2a","src/component/func.rs":"4f69de6c38cc6fe77b638ed7d8000c8a170d7053a11a6585dcd5b4877a06804c","src/component/import.rs":"ffe6e4ab8f2cec68b1022c753135d675ab27ecd1315bd38517472ceaffd0610c","src/component/instance.rs":"e550a7ee9af092ae084dd41e2c0ae756b7dca8da4b91d672d90265a6a15dff83","src/component/item_ref.rs":"e9c426ccc0210dc0c37bb0448468f5f4d9e52656b72d4ff0f2dc65c89957fe60","src/component/module.rs":"d27a28199d1dea1c64294a514329a524432319288515b0a0e3091fa7d3a33f74","src/component/resolve.rs":"6454c289407e9e0c904c4e27af0cc5a40fbcd9a0d874ac5a64475b08264d2f39","src/component/types.rs":"65b2250f147f8b132e7d13ee809cf72d4fa5ed26a55f1a35f1ef665421b7e750","src/component/wast.rs":"aa39db0ea0acd38744dc3cbd35903c9b00b5de90a5bfc8b76e6b6a7581d7c4c0","src/core.rs":"24b71d1ab2ad874c4e37b4dd709b6532989b60e6bc503194434f95029cc1cda7","src/core/binary.rs":"2e7e1145273582d149398991a26c8252a9b6e325be8c277ab597b3be581fc795","src/core/custom.rs":"edd6044b75d79ec873c28d803fb8dc9a53724f1bba474bcdef2bc77196e0a4d2","src/core/export.rs":"1322a120d9e1dd6f3aa1485ee0bbc4294961028ae8a7584a24170af5823b73b1","src/core/expr.rs":"e521d86433d30b0669a160a913e0638e3bb78d8233fa570173b75e04b56abe26","src/core/func.rs":"f87239645e45b7e40ecf7f8f2b707a7cfc0620cd2632cfdaca3cb155a06da732","src/core/global.rs":"dec0abecadd2fde9298acb729259deba1ef3c4733ae5afcb4fe8cd4a633f5349","src/core/import.rs":"602a13aed2fd5fa63e2562246586546199861df57f304c2906561ab77810cadd","src/core/memory.rs":"be4b5067c4febb0e5718186e59ffee69305b01801f3133730a9933e2e7193bc1","src/core/module.rs":"2b608a3cfee4df1ceeefaa046863dc964172bd6f52f6678d96078091fae7657a","src/core/resolve/deinline_import_export.rs":"696b58d4b4267210e6453b7617c521b57f8c768970b740665c5b475575fc2160","src/core/resolve/mod.rs":"9b2680b00a1cafad2dbbfdac86aa1c135ea67203bbc4dee939302b27f4aff6d0","src/core/resolve/names.rs":"d869983d60e36b432a38edf60f53900f230cc5ab6248d3368ced229e69a259f0","src/core/resolve/types.rs":"6099b59c44aec7879996d6cdcb0d0ac2e25991a52291c5b15ab23b8d7e07cde9","src/core/table.rs":"6b611622d7d4f83cbe8e1a82139937c0294996d5f8208ade0886d680d8ef0b5d","src/core/tag.rs":"8a3d4fcdb86dedd68cdaf25abd930ef52a461cf2a0e9393bb9cb6f425afaaf2e","src/core/types.rs":"1d4afbeb9ed8a465d9c727e5bdc5be798216505fc4034d3fef64859808ff6e0a","src/core/wast.rs":"dda114d05e1b1fcf65a1ca6124786261cf0b885eb61ad10ab258f80ff6dd2c2e","src/encode.rs":"0b165176db54fb9136202c54180adabda843a88e5436b96c19be9d41623912a3","src/error.rs":"4526260299c7983696a49ffe30a80139beb0d081fa8f42decc5e3283b361b1cb","src/gensym.rs":"b5e02e34443085f01deb5b657e541be7dc5d6dc952304e434a0b08320ea6c185","src/lexer.rs":"bc65c4d71c6f16a55670585a31ee615c9fcfc40a4bfa165e020ed03a9a27930d","src/lib.rs":"bcf1814d97dca75bbd6f49123f5811472a3ca1e93788dfe23cb079804e9294d0","src/names.rs":"81d49fecbff3b2abbbc323595271f32d912f03cd55a5685b7216d7cead32c420","src/parser.rs":"fe6a3727c68c8075c38422de545eb189fd8f5747ca681f6704982ed5c8ea4476","src/token.rs":"292d0cc8871990ba7a757d49edcbe5a9c94c346131f10df2ce517789f25e7fd8","src/wast.rs":"692dc20c1912acd2ed1db7427d305a5c9eab31dfc8675f037ffc475b6db15d58","src/wat.rs":"2ff97b6af77da19b0a8e0dfd136f58dbfa8247896c476726d1c9f88a3630cac2","tests/annotations.rs":"06294077550600f93a5a8c0d7e3ac38b47f00bb8933f9dc390ff31868e873afb","tests/comments.rs":"694e8a3467e9c837f723a43c729be0c6f6dfe3441ad9692759b1d55fd63055a2","tests/parse-fail.rs":"162023ac21f74ea856ec5916f4925a762d769b425eaf721c223c54b3efec6a53","tests/parse-fail/bad-core-func-alias.wat":"b71372064c3fce9d4a616418605040fe5e1356030a709b798b4769d3619cbbfb","tests/parse-fail/bad-core-func-alias.wat.err":"bb63274c26d3a21209bad794767f48372834bdc10cfbebf568a0c65d52803c90","tests/parse-fail/bad-func-alias.wat":"237c07149e1e74afe3b991a1fee6acb63167c1ca8931341614c435000339b887","tests/parse-fail/bad-func-alias.wat.err":"4a4bfc691b06d20fdf71e1dbac04649a52c76787048415599978987d761308fa","tests/parse-fail/bad-index.wat":"d21489daeec3a35327dcc9e2ba2d0acdd05f4aeaff2272cca608fda4d2338497","tests/parse-fail/bad-index.wat.err":"dc11070de0c9160573006ea4e5fa3c4d28e71bc39b24b1938cf6ff3b03ea7154","tests/parse-fail/bad-name.wat":"e5ff5d410007779a0de6609ea4cc693f0e603d36a106b8f5098c1980dd9f8124","tests/parse-fail/bad-name.wat.err":"fb5638476c1b85d9d1919e3dbcb0f16f82d088a4a22d4a0c186d7b8ba6e1902b","tests/parse-fail/bad-name2.wat":"5a6a4d0c19e5f2e48d7cebf361aca9b9000b7ef0c652997b5bd0ffaadbd2ca8a","tests/parse-fail/bad-name2.wat.err":"129707cce45f1e3cfb3e2ca5c702182e16ca5eeb2dbb2edd0710b004a8e194a5","tests/parse-fail/bad-name3.wat":"c19133d738cc84e9174301f27d4050c216bda81c7e9918d03ac792b088f24a05","tests/parse-fail/bad-name3.wat.err":"84ea63d40a619a0782ec6e94fce63921188ab87b1c3875eacae0a371144ed83a","tests/parse-fail/block1.wat":"91e74b5c3b43be692e7a6ae74fbfa674c4b6197299eb61338c4eccf282b18f17","tests/parse-fail/block1.wat.err":"40a083ae496b41dee7002cc6a664c5db0c5e4d904ae03b815773a769c4493fca","tests/parse-fail/block2.wat":"a8c07b4c09d51f10a8ffdf19806586022552398701cd90eb6d09816d45df06e5","tests/parse-fail/block2.wat.err":"33c842ec5dd0f2fdd3a9ce8187dd98b45ceee48c12810802af809d05b9cd25e9","tests/parse-fail/block3.wat":"29739abfbabd7c55f00ddfbbb9ebd818b4a114ef2336d50514f0842f7e075905","tests/parse-fail/block3.wat.err":"fc667ae2e71a260f62a3c7393bc97272e7c0ff38b17594f4370847b8a5019060","tests/parse-fail/confusing-block-comment0.wat":"8f27c9d0d212bbb1862ea89ffd7cbeafde5dfd755d695c1ba696cd520aba1a1d","tests/parse-fail/confusing-block-comment0.wat.err":"b53cbaef7bcec3862c64e09c084b92cd61bd29b954125482b2d083db250cd9e2","tests/parse-fail/confusing-block-comment1.wat":"b1a0447c9a8eaab8938d15cd33bd4adbb8bb69c2d710209b604023991a4347cb","tests/parse-fail/confusing-block-comment1.wat.err":"2fc3b3e4f98416326e1e5ec034026301069b6a98fa24451bc7573e16b8cb3811","tests/parse-fail/confusing-block-comment2.wat":"e3f49c7a388fba81081beb25d87bbd7db0acce5dd8e3eaa04574905ed7ec420c","tests/parse-fail/confusing-block-comment2.wat.err":"2183231d6acd0b5a117f9aea747c3d5c12e758450a6cd74027bb954a3134cf19","tests/parse-fail/confusing-block-comment3.wat":"d83f89c582501eb8833e772b8462c8974984a2f7fbb80b1452dc399fac74e5ed","tests/parse-fail/confusing-block-comment3.wat.err":"8b2096a4833627905c63f49cdabe44be24336646578dcfbdc67e9bfb35cbc601","tests/parse-fail/confusing-block-comment4.wat":"b7c6c68844d918e9ef6dd5ab9c40c7de7b38f04f94fadad630eda4e596f3e0f8","tests/parse-fail/confusing-block-comment4.wat.err":"2f790cc511edfcd89a12c9207901be16039fc1a06a584d73095e77a52f861cd9","tests/parse-fail/confusing-block-comment5.wat":"a159808032638cc914fa80ac4354a68b0af4f435a09cbe3e2d577582e183eb0a","tests/parse-fail/confusing-block-comment5.wat.err":"6fe0d99894307442f83fe93beaa5da706e06c9bdaf8e39d7cbae4c4fffafcb94","tests/parse-fail/confusing-block-comment6.wat":"abe48bcba2587dca98bc80ddde4e813f94fbc8a3538704a0775ea85bca0f8466","tests/parse-fail/confusing-block-comment6.wat.err":"3c97b9bf1112bbb7335d7fe4be5befb6f91eea7bec7dd3e6b543792231003c56","tests/parse-fail/confusing-block-comment7.wat":"e125c416ea5fa0ac35a58295a83a6f345438e2d7ddc6a39bd76c8e89885b3f0e","tests/parse-fail/confusing-block-comment7.wat.err":"5c34528ff2019cd3f0b3df34fd42523c0b66120706321da2c88ec05793478d2e","tests/parse-fail/confusing-block-comment8.wat":"200cc4c0e5af21a25529d7a81633a03642cff807255d6cd72eb45cdccc605cec","tests/parse-fail/confusing-block-comment8.wat.err":"9b81237d150a784b71791eee88fb6264a8bd6412862660f7392945203809e517","tests/parse-fail/confusing-line-comment0.wat":"bcec4c5a1e52b3e392e07c6711c979aa8d7db8baaf2bcdf270ba16d1aa528d26","tests/parse-fail/confusing-line-comment0.wat.err":"41ec5a075dc6b73afe1aec6b3198c5c4ae3a1a900e1610115879058ce034d6f6","tests/parse-fail/confusing-line-comment1.wat":"a2afbcab00ec957dfd9e9bf21fa4238852247b27f0b054f4a00f6b172dddf853","tests/parse-fail/confusing-line-comment1.wat.err":"f19a645e6fb5cbd7a0dd2308732741edcf83dbae0ef62549972029856a9e7fc6","tests/parse-fail/confusing-line-comment2.wat":"7f2a68229d02aac56ec4dfccf139bf2d617a0e89430357b30444dc4239d8aa89","tests/parse-fail/confusing-line-comment2.wat.err":"08add3d33e10e1ab6b4f3ae431f5db61d6f6c0a2b7d6828482a1e51b3a2d3851","tests/parse-fail/confusing-line-comment3.wat":"61173ae54782f6de86685f9555ffb94bbe2cf20b234daf660abb69ba3326f1ff","tests/parse-fail/confusing-line-comment3.wat.err":"4a5333dc02efa3c1eeab9cafa7c707f78abe92defdb01a71d6fe20944e4785f0","tests/parse-fail/confusing-line-comment4.wat":"9ecbbbe82c750e6475af1bfb46fe7a06115e4446a437d19fc08ca3d002f2a1c9","tests/parse-fail/confusing-line-comment4.wat.err":"ddb8aee8006265253b09c313cf5eb5c2dc4da66f502b4f6d3e2e1de77b35aec9","tests/parse-fail/confusing-line-comment5.wat":"8a4c8d342111bc9d37c16dbdf67c52027e1a42632abc9f359b3e4f07a85748b5","tests/parse-fail/confusing-line-comment5.wat.err":"34e368719fc0eab2f1a43c9f8e6f1b31aa9be9f971085d72374e49bde39cbfe5","tests/parse-fail/confusing-line-comment6.wat":"15f0dcdec23736ce92db84b3a7cdfe8689c97f2a7d0b9b0bfb0dcd2675163ed1","tests/parse-fail/confusing-line-comment6.wat.err":"0570be2ede803f071925d249f3858d3a417b5a6d678c9da40fc851d788d12983","tests/parse-fail/confusing-line-comment7.wat":"c7ee59301a701dd52d56cad02df78b0ad3584460bc18efa42ee137fe0c35aef6","tests/parse-fail/confusing-line-comment7.wat.err":"feebbeee8c85d8b3b85cec89435ae18f3ade9f754ca180d747a41406b64ca07a","tests/parse-fail/confusing-line-comment8.wat":"17632a8142154624de88b3cf93516147ed3419d785200bcd7049499eca8e8f04","tests/parse-fail/confusing-line-comment8.wat.err":"9c209285f2295cd2bc999aa7a9534a654932493308ab1f102839ed15a4d04d17","tests/parse-fail/confusing-string0.wat":"497b679b32baddcd6a158f4cadd3d9a9dea3457bac2a8c2c3d4e09b7c2d80842","tests/parse-fail/confusing-string0.wat.err":"cb3d737f2319346675a038716694354cd3b272453daa8a96e32e9861a9277f7b","tests/parse-fail/confusing-string1.wat":"46654cbed1ea6aab5019aef3d20098a391e40dacafa1ad5e83bf4ec384109fce","tests/parse-fail/confusing-string1.wat.err":"de7e7da516dc6c244bd0e4f012577b69f0cacbcc10f727fadb4b50bb04e0e2b4","tests/parse-fail/confusing-string2.wat":"11938f217c14387c05312735130f00c91d9df2d3ff9df7f13395e0f2b81dad54","tests/parse-fail/confusing-string2.wat.err":"e7bd08b146a855d681fefaf9e0576a9c333a2d10044f8e268b916b22a54227c9","tests/parse-fail/confusing-string3.wat":"e0ca4903fcafb9a54a91cf99e5eac95d25c6d2eb67b076f88191ad396f839cb6","tests/parse-fail/confusing-string3.wat.err":"b88d5db9e445c798eb24f95b7661b9c0368934d27ee8208477cd1c99351b939a","tests/parse-fail/confusing-string4.wat":"3ee2aee7f77604d051519c6f1795634469c12e98ae347a98f0c8445eecf1ff3d","tests/parse-fail/confusing-string4.wat.err":"1edc65bb09d8d3eed6ff69e7d9a7a4b5941dc823fa3436fa375657510255f6f4","tests/parse-fail/confusing-string5.wat":"024e50943128840d53f17e31a9b9332ce4f0ee70a847a043015f435b1c3c6e76","tests/parse-fail/confusing-string5.wat.err":"a0f13ec40d596ea2d8b0c4292b0d28775a5116ab7e11d7de88b295d25428c661","tests/parse-fail/confusing-string6.wat":"79cf157e29319800d2652c5a7f3dc90e07ebe2145c9904a70fc12027cdee84b7","tests/parse-fail/confusing-string6.wat.err":"860555e7aa13e3de3639cc2a530d6a42b974b629c4659593e972cbb0f306abae","tests/parse-fail/confusing-string7.wat":"7d8e403766dfb4e569754160d31ed0f9a27f908ed6cff96be43ab3d37f5975d5","tests/parse-fail/confusing-string7.wat.err":"658b6a02ba6d769254485f35c20984e7135d914b4266929963d723f26a40be4a","tests/parse-fail/confusing-string8.wat":"5a9b222e578655d57ee6e9f19bc1ea8e29aa52d652975fac685213444ed6458f","tests/parse-fail/confusing-string8.wat.err":"9a4e1a510330c800a1df7966998ebc3cde931eda20b249e5360f5e9a905dce11","tests/parse-fail/inline1.wat":"4e9767d67207aace2ac5e6f63a30e7510e4aa245ba35420539509e2254470272","tests/parse-fail/inline1.wat.err":"0143017a9825e518baa6009bae2c8d63520051dedd3437705bbe36b038a57f41","tests/parse-fail/newline-in-string.wat":"5c01cf709544ade0a6cdfcc39a3836a3bc018b633dc42a6cd872b6defc763ea7","tests/parse-fail/newline-in-string.wat.err":"1504209cc37a78b2aee778f23eacf78606daf964cf7bff251f5700efcd27ffd7","tests/parse-fail/string1.wat":"620d46d585ce94b382b5fde628c1399f3e562014b7a44af46e92f7bd045ca86e","tests/parse-fail/string1.wat.err":"fc53f3a1c4a65d8f25e5af51dec7699f45cecba114ca9c7871781bc70f664320","tests/parse-fail/string10.wat":"f7409dd45e153a1b11cb23e38f4ed87da12bedde38f8f0ccfe91037b0a4d97bd","tests/parse-fail/string10.wat.err":"ce677db5e37e0ed81ca357ed6b5edb21d85c27303ee194855bea7a88457efb6a","tests/parse-fail/string11.wat":"f6e0400b8c6a2014efa1ac676c567e140d8f86b5f4d5129773e6d67af537b615","tests/parse-fail/string11.wat.err":"4c6a550d29eda38a4e1bf7a589596f11655dc779479d7b8d466cfc53f815a742","tests/parse-fail/string12.wat":"23e30070eef22271651cce096a801fc4f79f3c37343c88bb8d2fc99b32d3b8b9","tests/parse-fail/string12.wat.err":"b5ec59f2996b88b2ee157e22d1774dc3e36fc08ed5bfc621aea830d30f66f586","tests/parse-fail/string13.wat":"81a305b981159ee10e140749ea3220c9edaaff53605e63c21995de47382b5faf","tests/parse-fail/string13.wat.err":"959f26c6b54e0d367b51d11d1addd8a53b5b8ff3caf70ebdd46bbea8ccfa2418","tests/parse-fail/string14.wat":"c45c2cc9f7afbfbd4be8e513106d22f7e5e817091448576c6bdf0701b81d95dd","tests/parse-fail/string14.wat.err":"50b5bccba905ddbe275938edb7ed0b09a5ca53dcdad36a7ff736ce9bc8e7a338","tests/parse-fail/string15.wat":"b5e0d5ade40de53b2d767a132e28376bb8c7a6f6238c4d8c248ae717c41d7f1f","tests/parse-fail/string15.wat.err":"0e9fc502cc90f96d1f592a3f63369fd2a3574bc4a2345a70365dbb76804e870f","tests/parse-fail/string16.wat":"38c3688cee80a9d089d239aa06eb1d27c5364ad2bd270aca57d05997c20aa682","tests/parse-fail/string16.wat.err":"4274b3bbe4df4cf0373619b1fcd082d0c802990817d2aca26ed885168c80e489","tests/parse-fail/string2.wat":"1172964aed31537b8c466d1f045f3e756926e7b221f80b2aff4a9a6721ea0beb","tests/parse-fail/string2.wat.err":"4618d3b20a78a077337eb5d6cae14ac39d9853762f011fbd23cff8921618dbde","tests/parse-fail/string3.wat":"07e0fbcd6270c1db100917c151ee4ac3f935e4ee1b27bce3c453b22b4b74f4d6","tests/parse-fail/string3.wat.err":"08ffc6158a9e030b2e211d53bdb8aeacfd879815c7b284d6a83b030566e35928","tests/parse-fail/string4.wat":"c970da2051b0613bdd1de4664f10424e14f2ebabe604175d4fb9b763b37af577","tests/parse-fail/string4.wat.err":"406706594d305c560fabd66417ad4fc276939990b5e701bd9d13fc223d207219","tests/parse-fail/string5.wat":"386cf314bb05acdaaabdf4da1caf140167271a26bd08bf34c3a7427d4bc4431f","tests/parse-fail/string5.wat.err":"1e56b44a23a37b2b2ad05aa9dd7e1e18191b5cc22151f93bbcf9d618779a57bd","tests/parse-fail/string6.wat":"8f1fe2825ff96f2acee9130a7721f86fcc93c221baa9411bf1fb6f0870d38ccb","tests/parse-fail/string6.wat.err":"d55dfd84d94e893f167ae73b7a080aefb2bfb05cc8a1ec201c4d3066fb8549b4","tests/parse-fail/string7.wat":"b12f8c75313d7f834489d3c353422f90bc945b37139586446eda82e334a97cde","tests/parse-fail/string7.wat.err":"4cee0ca61992c249dd0faaf2529a073cf8deeb36111a3f69b43695e5682560a2","tests/parse-fail/string8.wat":"4c2e0e1f883bb4e8cba9313497ed792130e5848e62bde7716102788d7467be10","tests/parse-fail/string8.wat.err":"840c6def7c60dd7c2b7261549cab435ba78c9b3a937adf6d5d9595ff8af01c91","tests/parse-fail/string9.wat":"2b7670caed2b0688d535de6e4e416f35fa717cfbe096a6cc764a669085c8f52f","tests/parse-fail/string9.wat.err":"37b5a9c3af9631500f31f9e5e3efa821b8d96063c57d60fd01df6be6a5c323e1","tests/parse-fail/unbalanced.wat":"f664fbef53a0308f864ba496d38044eb90482636e32586512939d4930729f3fe","tests/parse-fail/unbalanced.wat.err":"aba579f7b836856e69afe05da8328aabe0643d94e369898e686aa7bb0b07e9c9","tests/recursive.rs":"ad8a2b07bf955121a7c9e326ed35f9b2bc56b440c8cc0bbde24d423a79945c1a"},"package":"441a6a195b3b5245e26d450bbcc91366c6b652382a22f63cbe3c73240e13b2bb"} \ No newline at end of file
diff --git a/third_party/rust/wast/Cargo.toml b/third_party/rust/wast/Cargo.toml
index 7f2d159a8b..8c07c94112 100644
--- a/third_party/rust/wast/Cargo.toml
+++ b/third_party/rust/wast/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "wast"
-version = "201.0.0"
+version = "205.0.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
description = """
Customizable Rust parsers for the WebAssembly Text formats WAT and WAST
@@ -40,13 +40,13 @@ version = "2.4.1"
version = "0.1.9"
[dependencies.wasm-encoder]
-version = "0.201.0"
+version = "0.205.0"
[dev-dependencies.anyhow]
version = "1.0.58"
-[dev-dependencies.rayon]
-version = "1.3"
+[dev-dependencies.libtest-mimic]
+version = "0.7.0"
[features]
default = ["wasm-module"]
diff --git a/third_party/rust/wast/src/component/binary.rs b/third_party/rust/wast/src/component/binary.rs
index a57cc0f912..a04343269f 100644
--- a/third_party/rust/wast/src/component/binary.rs
+++ b/third_party/rust/wast/src/component/binary.rs
@@ -597,7 +597,7 @@ impl From<core::HeapType<'_>> for wasm_encoder::HeapType {
match r {
core::HeapType::Func => Self::Func,
core::HeapType::Extern => Self::Extern,
- core::HeapType::Exn => {
+ core::HeapType::Exn | core::HeapType::NoExn => {
todo!("encoding of exceptions proposal types not yet implemented")
}
core::HeapType::Concrete(Index::Num(i, _)) => Self::Concrete(i),
@@ -640,11 +640,23 @@ impl From<core::TableType<'_>> for wasm_encoder::TableType {
impl From<core::MemoryType> for wasm_encoder::MemoryType {
fn from(ty: core::MemoryType) -> Self {
- let (minimum, maximum, memory64, shared) = match ty {
- core::MemoryType::B32 { limits, shared } => {
- (limits.min.into(), limits.max.map(Into::into), false, shared)
- }
- core::MemoryType::B64 { limits, shared } => (limits.min, limits.max, true, shared),
+ let (minimum, maximum, memory64, shared, page_size_log2) = match ty {
+ core::MemoryType::B32 {
+ limits,
+ shared,
+ page_size_log2,
+ } => (
+ limits.min.into(),
+ limits.max.map(Into::into),
+ false,
+ shared,
+ page_size_log2,
+ ),
+ core::MemoryType::B64 {
+ limits,
+ shared,
+ page_size_log2,
+ } => (limits.min, limits.max, true, shared, page_size_log2),
};
Self {
@@ -652,6 +664,7 @@ impl From<core::MemoryType> for wasm_encoder::MemoryType {
maximum,
memory64,
shared,
+ page_size_log2,
}
}
}
@@ -661,6 +674,7 @@ impl From<core::GlobalType<'_>> for wasm_encoder::GlobalType {
Self {
val_type: ty.ty.into(),
mutable: ty.mutable,
+ shared: ty.shared,
}
}
}
@@ -780,8 +794,8 @@ impl From<PrimitiveValType> for wasm_encoder::PrimitiveValType {
PrimitiveValType::U32 => Self::U32,
PrimitiveValType::S64 => Self::S64,
PrimitiveValType::U64 => Self::U64,
- PrimitiveValType::Float32 => Self::Float32,
- PrimitiveValType::Float64 => Self::Float64,
+ PrimitiveValType::F32 => Self::F32,
+ PrimitiveValType::F64 => Self::F64,
PrimitiveValType::Char => Self::Char,
PrimitiveValType::String => Self::String,
}
diff --git a/third_party/rust/wast/src/component/resolve.rs b/third_party/rust/wast/src/component/resolve.rs
index c0122ef73f..0f33df564a 100644
--- a/third_party/rust/wast/src/component/resolve.rs
+++ b/third_party/rust/wast/src/component/resolve.rs
@@ -531,7 +531,8 @@ impl<'a> Resolver<'a> {
| core::HeapType::Struct
| core::HeapType::None
| core::HeapType::NoFunc
- | core::HeapType::NoExtern => {}
+ | core::HeapType::NoExtern
+ | core::HeapType::NoExn => {}
core::HeapType::Concrete(id) => {
self.resolve_ns(id, Ns::Type)?;
}
diff --git a/third_party/rust/wast/src/component/types.rs b/third_party/rust/wast/src/component/types.rs
index 72eced02a8..dc8a91fd6b 100644
--- a/third_party/rust/wast/src/component/types.rs
+++ b/third_party/rust/wast/src/component/types.rs
@@ -230,8 +230,8 @@ pub enum PrimitiveValType {
U32,
S64,
U64,
- Float32,
- Float64,
+ F32,
+ F64,
Char,
String,
}
@@ -266,12 +266,18 @@ impl<'a> Parse<'a> for PrimitiveValType {
} else if l.peek::<kw::u64>()? {
parser.parse::<kw::u64>()?;
Ok(Self::U64)
+ } else if l.peek::<kw::f32>()? {
+ parser.parse::<kw::f32>()?;
+ Ok(Self::F32)
+ } else if l.peek::<kw::f64>()? {
+ parser.parse::<kw::f64>()?;
+ Ok(Self::F64)
} else if l.peek::<kw::float32>()? {
parser.parse::<kw::float32>()?;
- Ok(Self::Float32)
+ Ok(Self::F32)
} else if l.peek::<kw::float64>()? {
parser.parse::<kw::float64>()?;
- Ok(Self::Float64)
+ Ok(Self::F64)
} else if l.peek::<kw::char>()? {
parser.parse::<kw::char>()?;
Ok(Self::Char)
@@ -297,6 +303,8 @@ impl Peek for PrimitiveValType {
| Some(("u32", _))
| Some(("s64", _))
| Some(("u64", _))
+ | Some(("f32", _))
+ | Some(("f64", _))
| Some(("float32", _))
| Some(("float64", _))
| Some(("char", _))
diff --git a/third_party/rust/wast/src/component/wast.rs b/third_party/rust/wast/src/component/wast.rs
index 72d8bf15bc..28f1ce267c 100644
--- a/third_party/rust/wast/src/component/wast.rs
+++ b/third_party/rust/wast/src/component/wast.rs
@@ -1,6 +1,6 @@
use crate::kw;
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
-use crate::token::{Float32, Float64};
+use crate::token::{F32, F64};
/// Expression that can be used inside of `invoke` expressions for core wasm
/// functions.
@@ -16,8 +16,8 @@ pub enum WastVal<'a> {
S32(i32),
U64(u64),
S64(i64),
- Float32(Float32),
- Float64(Float64),
+ F32(F32),
+ F64(F64),
Char(char),
String(&'a str),
List(Vec<WastVal<'a>>),
@@ -53,8 +53,8 @@ static CASES: &[(&str, fn(Parser<'_>) -> Result<WastVal<'_>>)] = {
("s32.const", |p| Ok(S32(p.parse()?))),
("u64.const", |p| Ok(U64(p.parse()?))),
("s64.const", |p| Ok(S64(p.parse()?))),
- ("f32.const", |p| Ok(Float32(p.parse()?))),
- ("f64.const", |p| Ok(Float64(p.parse()?))),
+ ("f32.const", |p| Ok(F32(p.parse()?))),
+ ("f64.const", |p| Ok(F64(p.parse()?))),
("char.const", |p| {
let s = p.parse::<&str>()?;
let mut ch = s.chars();
diff --git a/third_party/rust/wast/src/core/binary.rs b/third_party/rust/wast/src/core/binary.rs
index da94da0241..769e120112 100644
--- a/third_party/rust/wast/src/core/binary.rs
+++ b/third_party/rust/wast/src/core/binary.rs
@@ -295,6 +295,7 @@ impl<'a> Encode for HeapType<'a> {
HeapType::I31 => e.push(0x6c),
HeapType::NoFunc => e.push(0x73),
HeapType::NoExtern => e.push(0x72),
+ HeapType::NoExn => e.push(0x74),
HeapType::None => e.push(0x71),
// Note that this is encoded as a signed leb128 so be sure to cast
// to an i64 first
@@ -349,6 +350,11 @@ impl<'a> Encode for RefType<'a> {
nullable: true,
heap: HeapType::NoExtern,
} => e.push(0x72),
+ // The 'nullexnref' binary abbreviation
+ RefType {
+ nullable: true,
+ heap: HeapType::NoExn,
+ } => e.push(0x74),
// The 'nullref' binary abbreviation
RefType {
nullable: true,
@@ -466,25 +472,45 @@ impl Encode for Limits {
impl Encode for MemoryType {
fn encode(&self, e: &mut Vec<u8>) {
match self {
- MemoryType::B32 { limits, shared } => {
+ MemoryType::B32 {
+ limits,
+ shared,
+ page_size_log2,
+ } => {
let flag_max = limits.max.is_some() as u8;
let flag_shared = *shared as u8;
- let flags = flag_max | (flag_shared << 1);
+ let flag_page_size = page_size_log2.is_some() as u8;
+ let flags = flag_max | (flag_shared << 1) | (flag_page_size << 3);
e.push(flags);
limits.min.encode(e);
if let Some(max) = limits.max {
max.encode(e);
}
+ if let Some(p) = page_size_log2 {
+ p.encode(e);
+ }
}
- MemoryType::B64 { limits, shared } => {
- let flag_max = limits.max.is_some() as u8;
- let flag_shared = *shared as u8;
- let flags = flag_max | (flag_shared << 1) | 0x04;
+ MemoryType::B64 {
+ limits,
+ shared,
+ page_size_log2,
+ } => {
+ let flag_max = limits.max.is_some();
+ let flag_shared = *shared;
+ let flag_mem64 = true;
+ let flag_page_size = page_size_log2.is_some();
+ let flags = ((flag_max as u8) << 0)
+ | ((flag_shared as u8) << 1)
+ | ((flag_mem64 as u8) << 2)
+ | ((flag_page_size as u8) << 3);
e.push(flags);
limits.min.encode(e);
if let Some(max) = limits.max {
max.encode(e);
}
+ if let Some(p) = page_size_log2 {
+ p.encode(e);
+ }
}
}
}
@@ -493,11 +519,14 @@ impl Encode for MemoryType {
impl<'a> Encode for GlobalType<'a> {
fn encode(&self, e: &mut Vec<u8>) {
self.ty.encode(e);
+ let mut flags = 0;
if self.mutable {
- e.push(0x01);
- } else {
- e.push(0x00);
+ flags |= 0b01;
+ }
+ if self.shared {
+ flags |= 0b10;
}
+ e.push(flags);
}
}
@@ -749,19 +778,6 @@ impl Encode for BlockType<'_> {
}
}
-impl Encode for FuncBindType<'_> {
- fn encode(&self, e: &mut Vec<u8>) {
- self.ty.encode(e);
- }
-}
-
-impl Encode for LetType<'_> {
- fn encode(&self, e: &mut Vec<u8>) {
- self.block.encode(e);
- self.locals.encode(e);
- }
-}
-
impl Encode for LaneArg {
fn encode(&self, e: &mut Vec<u8>) {
self.lane.encode(e);
@@ -784,6 +800,23 @@ impl Encode for MemArg<'_> {
}
}
+impl Encode for Ordering {
+ fn encode(&self, buf: &mut Vec<u8>) {
+ let flag: u8 = match self {
+ Ordering::SeqCst => 0,
+ Ordering::AcqRel => 1,
+ };
+ flag.encode(buf);
+ }
+}
+
+impl Encode for OrderedAccess<'_> {
+ fn encode(&self, buf: &mut Vec<u8>) {
+ self.ordering.encode(buf);
+ self.index.encode(buf);
+ }
+}
+
impl Encode for LoadOrStoreLane<'_> {
fn encode(&self, e: &mut Vec<u8>) {
self.memarg.encode(e);
@@ -845,13 +878,13 @@ impl Encode for BrTableIndices<'_> {
}
}
-impl Encode for Float32 {
+impl Encode for F32 {
fn encode(&self, e: &mut Vec<u8>) {
e.extend_from_slice(&self.bits.to_le_bytes());
}
}
-impl Encode for Float64 {
+impl Encode for F64 {
fn encode(&self, e: &mut Vec<u8>) {
e.extend_from_slice(&self.bits.to_le_bytes());
}
@@ -994,8 +1027,7 @@ fn find_names<'a>(
| Instruction::Block(block)
| Instruction::Loop(block)
| Instruction::Try(block)
- | Instruction::TryTable(TryTable { block, .. })
- | Instruction::Let(LetType { block, .. }) => {
+ | Instruction::TryTable(TryTable { block, .. }) => {
if let Some(name) = get_name(&block.label, &block.label_name) {
label_names.push((label_idx, name));
}
diff --git a/third_party/rust/wast/src/core/expr.rs b/third_party/rust/wast/src/core/expr.rs
index b45950b896..df0abb7cd0 100644
--- a/third_party/rust/wast/src/core/expr.rs
+++ b/third_party/rust/wast/src/core/expr.rs
@@ -184,7 +184,6 @@ impl<'a> ExpressionParser<'a> {
// seen
i @ Instruction::Block(_)
| i @ Instruction::Loop(_)
- | i @ Instruction::Let(_)
| i @ Instruction::TryTable(_) => {
self.instrs.push(i);
self.stack.push(Level::EndWith(Instruction::End(None)));
@@ -350,7 +349,7 @@ macro_rules! instructions {
}) => (
/// A listing of all WebAssembly instructions that can be in a module
/// that this crate currently parses.
- #[derive(Debug)]
+ #[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum Instruction<'a> {
$(
@@ -468,8 +467,6 @@ instructions! {
// function-references proposal
CallRef(Index<'a>) : [0x14] : "call_ref",
ReturnCallRef(Index<'a>) : [0x15] : "return_call_ref",
- FuncBind(FuncBindType<'a>) : [0x16] : "func.bind",
- Let(LetType<'a>) : [0x17] : "let",
Drop : [0x1a] : "drop",
Select(SelectTypes<'a>) : [] : "select",
@@ -574,8 +571,8 @@ instructions! {
I32Const(i32) : [0x41] : "i32.const",
I64Const(i64) : [0x42] : "i64.const",
- F32Const(Float32) : [0x43] : "f32.const",
- F64Const(Float64) : [0x44] : "f64.const",
+ F32Const(F32) : [0x43] : "f32.const",
+ F64Const(F64) : [0x44] : "f64.const",
I32Clz : [0x67] : "i32.clz",
I32Ctz : [0x68] : "i32.ctz",
@@ -803,6 +800,10 @@ instructions! {
I64AtomicRmw16CmpxchgU(MemArg<2>) : [0xfe, 0x4d] : "i64.atomic.rmw16.cmpxchg_u",
I64AtomicRmw32CmpxchgU(MemArg<4>) : [0xfe, 0x4e] : "i64.atomic.rmw32.cmpxchg_u",
+ // proposal: shared-everything-threads
+ GlobalAtomicGet(OrderedAccess<'a>) : [0xfe, 0x4f] : "global.atomic.get",
+ GlobalAtomicSet(OrderedAccess<'a>) : [0xfe, 0x50] : "global.atomic.set",
+
// proposal: simd
//
// https://webassembly.github.io/simd/core/binary/instructions.html
@@ -1123,7 +1124,7 @@ impl<'a> Instruction<'a> {
///
/// This is used to label blocks and also annotate what types are expected for
/// the block.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct BlockType<'a> {
pub label: Option<Id<'a>>,
@@ -1143,7 +1144,7 @@ impl<'a> Parse<'a> for BlockType<'a> {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct TryTable<'a> {
pub block: Box<BlockType<'a>>,
@@ -1187,7 +1188,7 @@ impl<'a> Parse<'a> for TryTable<'a> {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum TryTableCatchKind<'a> {
// Catch a tagged exception, do not capture an exnref.
@@ -1210,50 +1211,16 @@ impl<'a> TryTableCatchKind<'a> {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct TryTableCatch<'a> {
pub kind: TryTableCatchKind<'a>,
pub label: Index<'a>,
}
-/// Extra information associated with the func.bind instruction.
-#[derive(Debug)]
-#[allow(missing_docs)]
-pub struct FuncBindType<'a> {
- pub ty: TypeUse<'a, FunctionType<'a>>,
-}
-
-impl<'a> Parse<'a> for FuncBindType<'a> {
- fn parse(parser: Parser<'a>) -> Result<Self> {
- Ok(FuncBindType {
- ty: parser
- .parse::<TypeUse<'a, FunctionTypeNoNames<'a>>>()?
- .into(),
- })
- }
-}
-
-/// Extra information associated with the let instruction.
-#[derive(Debug)]
-#[allow(missing_docs)]
-pub struct LetType<'a> {
- pub block: Box<BlockType<'a>>,
- pub locals: Box<[Local<'a>]>,
-}
-
-impl<'a> Parse<'a> for LetType<'a> {
- fn parse(parser: Parser<'a>) -> Result<Self> {
- Ok(LetType {
- block: parser.parse()?,
- locals: Local::parse_remainder(parser)?.into(),
- })
- }
-}
-
/// Extra information associated with the `br_table` instruction.
#[allow(missing_docs)]
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct BrTableIndices<'a> {
pub labels: Vec<Index<'a>>,
pub default: Index<'a>,
@@ -1271,7 +1238,7 @@ impl<'a> Parse<'a> for BrTableIndices<'a> {
}
/// Payload for lane-related instructions. Unsigned with no + prefix.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct LaneArg {
/// The lane argument.
pub lane: u8,
@@ -1299,7 +1266,7 @@ impl<'a> Parse<'a> for LaneArg {
/// Payload for memory-related instructions indicating offset/alignment of
/// memory accesses.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemArg<'a> {
/// The alignment of this access.
///
@@ -1374,7 +1341,7 @@ impl<'a> MemArg<'a> {
}
/// Extra data associated with the `loadN_lane` and `storeN_lane` instructions.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct LoadOrStoreLane<'a> {
/// The memory argument for this instruction.
pub memarg: MemArg<'a>,
@@ -1428,7 +1395,7 @@ impl<'a> LoadOrStoreLane<'a> {
}
/// Extra data associated with the `call_indirect` instruction.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct CallIndirect<'a> {
/// The table that this call is going to be indexing.
pub table: Index<'a>,
@@ -1449,7 +1416,7 @@ impl<'a> Parse<'a> for CallIndirect<'a> {
}
/// Extra data associated with the `table.init` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct TableInit<'a> {
/// The index of the table we're copying into.
pub table: Index<'a>,
@@ -1471,7 +1438,7 @@ impl<'a> Parse<'a> for TableInit<'a> {
}
/// Extra data associated with the `table.copy` instruction.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct TableCopy<'a> {
/// The index of the destination table to copy into.
pub dst: Index<'a>,
@@ -1493,7 +1460,7 @@ impl<'a> Parse<'a> for TableCopy<'a> {
}
/// Extra data associated with unary table instructions.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct TableArg<'a> {
/// The index of the table argument.
pub dst: Index<'a>,
@@ -1511,7 +1478,7 @@ impl<'a> Parse<'a> for TableArg<'a> {
}
/// Extra data associated with unary memory instructions.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemoryArg<'a> {
/// The index of the memory space.
pub mem: Index<'a>,
@@ -1529,7 +1496,7 @@ impl<'a> Parse<'a> for MemoryArg<'a> {
}
/// Extra data associated with the `memory.init` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemoryInit<'a> {
/// The index of the data segment we're copying into memory.
pub data: Index<'a>,
@@ -1551,7 +1518,7 @@ impl<'a> Parse<'a> for MemoryInit<'a> {
}
/// Extra data associated with the `memory.copy` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemoryCopy<'a> {
/// The index of the memory we're copying from.
pub src: Index<'a>,
@@ -1573,7 +1540,7 @@ impl<'a> Parse<'a> for MemoryCopy<'a> {
}
/// Extra data associated with the `struct.get/set` instructions
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct StructAccess<'a> {
/// The index of the struct type we're accessing.
pub r#struct: Index<'a>,
@@ -1591,7 +1558,7 @@ impl<'a> Parse<'a> for StructAccess<'a> {
}
/// Extra data associated with the `array.fill` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayFill<'a> {
/// The index of the array type we're filling.
pub array: Index<'a>,
@@ -1606,7 +1573,7 @@ impl<'a> Parse<'a> for ArrayFill<'a> {
}
/// Extra data associated with the `array.copy` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayCopy<'a> {
/// The index of the array type we're copying to.
pub dest_array: Index<'a>,
@@ -1624,7 +1591,7 @@ impl<'a> Parse<'a> for ArrayCopy<'a> {
}
/// Extra data associated with the `array.init_[data/elem]` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayInit<'a> {
/// The index of the array type we're initializing.
pub array: Index<'a>,
@@ -1642,7 +1609,7 @@ impl<'a> Parse<'a> for ArrayInit<'a> {
}
/// Extra data associated with the `array.new_fixed` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayNewFixed<'a> {
/// The index of the array type we're accessing.
pub array: Index<'a>,
@@ -1660,7 +1627,7 @@ impl<'a> Parse<'a> for ArrayNewFixed<'a> {
}
/// Extra data associated with the `array.new_data` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayNewData<'a> {
/// The index of the array type we're accessing.
pub array: Index<'a>,
@@ -1678,7 +1645,7 @@ impl<'a> Parse<'a> for ArrayNewData<'a> {
}
/// Extra data associated with the `array.new_elem` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayNewElem<'a> {
/// The index of the array type we're accessing.
pub array: Index<'a>,
@@ -1696,7 +1663,7 @@ impl<'a> Parse<'a> for ArrayNewElem<'a> {
}
/// Extra data associated with the `ref.cast` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct RefCast<'a> {
/// The type to cast to.
pub r#type: RefType<'a>,
@@ -1711,7 +1678,7 @@ impl<'a> Parse<'a> for RefCast<'a> {
}
/// Extra data associated with the `ref.test` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct RefTest<'a> {
/// The type to test for.
pub r#type: RefType<'a>,
@@ -1726,7 +1693,7 @@ impl<'a> Parse<'a> for RefTest<'a> {
}
/// Extra data associated with the `br_on_cast` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct BrOnCast<'a> {
/// The label to branch to.
pub label: Index<'a>,
@@ -1747,7 +1714,7 @@ impl<'a> Parse<'a> for BrOnCast<'a> {
}
/// Extra data associated with the `br_on_cast_fail` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct BrOnCastFail<'a> {
/// The label to branch to.
pub label: Index<'a>,
@@ -1767,16 +1734,65 @@ impl<'a> Parse<'a> for BrOnCastFail<'a> {
}
}
+/// The memory ordering for atomic instructions.
+///
+/// For an in-depth explanation of memory orderings, see the C++ documentation
+/// for [`memory_order`] or the Rust documentation for [`atomic::Ordering`].
+///
+/// [`memory_order`]: https://en.cppreference.com/w/cpp/atomic/memory_order
+/// [`atomic::Ordering`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html
+#[derive(Clone, Debug)]
+pub enum Ordering {
+ /// Like `AcqRel` but all threads see all sequentially consistent operations
+ /// in the same order.
+ AcqRel,
+ /// For a load, it acquires; this orders all operations before the last
+ /// "releasing" store. For a store, it releases; this orders all operations
+ /// before it at the next "acquiring" load.
+ SeqCst,
+}
+
+impl<'a> Parse<'a> for Ordering {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ if parser.peek::<kw::seq_cst>()? {
+ parser.parse::<kw::seq_cst>()?;
+ Ok(Ordering::SeqCst)
+ } else if parser.peek::<kw::acq_rel>()? {
+ parser.parse::<kw::acq_rel>()?;
+ Ok(Ordering::AcqRel)
+ } else {
+ Err(parser.error("expected a memory ordering: `seq_cst` or `acq_rel`"))
+ }
+ }
+}
+
+/// Extra data associated with the `global.atomic.*` instructions.
+#[derive(Clone, Debug)]
+pub struct OrderedAccess<'a> {
+ /// The memory ordering for this atomic instruction.
+ pub ordering: Ordering,
+ /// The index of the global to access.
+ pub index: Index<'a>,
+}
+
+impl<'a> Parse<'a> for OrderedAccess<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ let ordering = parser.parse()?;
+ let index = parser.parse()?;
+ Ok(OrderedAccess { ordering, index })
+ }
+}
+
/// Different ways to specify a `v128.const` instruction
-#[derive(Debug)]
+#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum V128Const {
I8x16([i8; 16]),
I16x8([i16; 8]),
I32x4([i32; 4]),
I64x2([i64; 2]),
- F32x4([Float32; 4]),
- F64x2([Float64; 2]),
+ F32x4([F32; 4]),
+ F64x2([F64; 2]),
}
impl V128Const {
@@ -1934,7 +1950,7 @@ impl<'a> Parse<'a> for V128Const {
}
/// Lanes being shuffled in the `i8x16.shuffle` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct I8x16Shuffle {
#[allow(missing_docs)]
pub lanes: [u8; 16],
@@ -1966,7 +1982,7 @@ impl<'a> Parse<'a> for I8x16Shuffle {
}
/// Payload of the `select` instructions
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct SelectTypes<'a> {
#[allow(missing_docs)]
pub tys: Option<Vec<ValType<'a>>>,
diff --git a/third_party/rust/wast/src/core/memory.rs b/third_party/rust/wast/src/core/memory.rs
index eb1baa1a95..5f5f051109 100644
--- a/third_party/rust/wast/src/core/memory.rs
+++ b/third_party/rust/wast/src/core/memory.rs
@@ -59,7 +59,10 @@ impl<'a> Parse<'a> for Memory<'a> {
import,
ty: parser.parse()?,
}
- } else if l.peek::<LParen>()? || parser.peek2::<LParen>()? {
+ } else if l.peek::<LParen>()?
+ || ((parser.peek::<kw::i32>()? || parser.peek::<kw::i64>()?)
+ && parser.peek2::<LParen>()?)
+ {
let is_32 = if parser.parse::<Option<kw::i32>>()?.is_some() {
true
} else {
@@ -133,7 +136,7 @@ impl<'a> Parse<'a> for Data<'a> {
let id = parser.parse()?;
let name = parser.parse()?;
- let kind = if parser.peek::<&[u8]>()? {
+ let kind = if parser.peek::<&[u8]>()? || parser.peek::<RParen>()? {
DataKind::Passive
// ... and otherwise we must be attached to a particular memory as well
@@ -248,8 +251,8 @@ impl<'a> Parse<'a> for DataVal<'a> {
|| consume::<kw::i16, i16, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
|| consume::<kw::i32, i32, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
|| consume::<kw::i64, i64, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
- || consume::<kw::f32, Float32, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
- || consume::<kw::f64, Float64, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
+ || consume::<kw::f32, F32, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
+ || consume::<kw::f64, F64, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
|| consume::<kw::v128, V128Const, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
{
Ok(DataVal::Integral(result))
diff --git a/third_party/rust/wast/src/core/resolve/deinline_import_export.rs b/third_party/rust/wast/src/core/resolve/deinline_import_export.rs
index 98e680b58a..f2d12e9a52 100644
--- a/third_party/rust/wast/src/core/resolve/deinline_import_export.rs
+++ b/third_party/rust/wast/src/core/resolve/deinline_import_export.rs
@@ -50,7 +50,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
// field here instead, switching this to a `Normal` memory.
MemoryKind::Inline { is_32, ref data } => {
let len = data.iter().map(|l| l.len()).sum::<usize>() as u32;
- let pages = (len + page_size() - 1) / page_size();
+ let pages = (len + default_page_size() - 1) / default_page_size();
let kind = MemoryKind::Normal(if is_32 {
MemoryType::B32 {
limits: Limits {
@@ -58,6 +58,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
max: Some(pages),
},
shared: false,
+ page_size_log2: None,
}
} else {
MemoryType::B64 {
@@ -66,6 +67,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
max: Some(u64::from(pages)),
},
shared: false,
+ page_size_log2: None,
}
});
let data = match mem::replace(&mut m.kind, kind) {
@@ -212,7 +214,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
fields.push(item);
}
- fn page_size() -> u32 {
+ fn default_page_size() -> u32 {
1 << 16
}
}
diff --git a/third_party/rust/wast/src/core/resolve/names.rs b/third_party/rust/wast/src/core/resolve/names.rs
index 05894e9a1e..f17590bbd1 100644
--- a/third_party/rust/wast/src/core/resolve/names.rs
+++ b/third_party/rust/wast/src/core/resolve/names.rs
@@ -457,6 +457,10 @@ impl<'a, 'b> ExprResolver<'a, 'b> {
self.resolver.resolve(i, Ns::Global)?;
}
+ GlobalAtomicSet(i) | GlobalAtomicGet(i) => {
+ self.resolver.resolve(&mut i.index, Ns::Global)?;
+ }
+
LocalSet(i) | LocalGet(i) | LocalTee(i) => {
assert!(self.scopes.len() > 0);
// Resolve a local by iterating over scopes from most recent
@@ -490,30 +494,6 @@ impl<'a, 'b> ExprResolver<'a, 'b> {
self.resolver.resolve(i, Ns::Type)?;
}
- FuncBind(b) => {
- self.resolver.resolve_type_use(&mut b.ty)?;
- }
-
- Let(t) => {
- // Resolve (ref T) in locals
- for local in t.locals.iter_mut() {
- self.resolver.resolve_valtype(&mut local.ty)?;
- }
-
- // Register all locals defined in this let
- let mut scope = Namespace::default();
- for local in t.locals.iter() {
- scope.register(local.id, "local")?;
- }
- self.scopes.push(scope);
- self.blocks.push(ExprBlock {
- label: t.block.label,
- pushed_scope: true,
- });
-
- self.resolve_block_type(&mut t.block)?;
- }
-
Block(bt) | If(bt) | Loop(bt) | Try(bt) => {
self.blocks.push(ExprBlock {
label: bt.label,
diff --git a/third_party/rust/wast/src/core/resolve/types.rs b/third_party/rust/wast/src/core/resolve/types.rs
index bfb996b4b6..84b0e516e4 100644
--- a/third_party/rust/wast/src/core/resolve/types.rs
+++ b/third_party/rust/wast/src/core/resolve/types.rs
@@ -139,7 +139,6 @@ impl<'a> Expander<'a> {
Instruction::Block(bt)
| Instruction::If(bt)
| Instruction::Loop(bt)
- | Instruction::Let(LetType { block: bt, .. })
| Instruction::Try(bt)
| Instruction::TryTable(TryTable { block: bt, .. }) => {
// No expansion necessary, a type reference is already here.
@@ -174,9 +173,6 @@ impl<'a> Expander<'a> {
}
self.expand_type_use(&mut bt.ty);
}
- Instruction::FuncBind(b) => {
- self.expand_type_use(&mut b.ty);
- }
Instruction::CallIndirect(c) | Instruction::ReturnCallIndirect(c) => {
self.expand_type_use(&mut c.ty);
}
diff --git a/third_party/rust/wast/src/core/types.rs b/third_party/rust/wast/src/core/types.rs
index 179a62b9b8..160317c1c3 100644
--- a/third_party/rust/wast/src/core/types.rs
+++ b/third_party/rust/wast/src/core/types.rs
@@ -2,6 +2,7 @@ use crate::core::*;
use crate::kw;
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
use crate::token::{Id, Index, LParen, NameAnnotation, Span};
+use crate::Error;
use std::mem;
/// The value types for a wasm module.
@@ -86,6 +87,8 @@ pub enum HeapType<'a> {
NoExtern,
/// The bottom type of the anyref hierarchy. Part of the GC proposal.
None,
+ /// The bottom type of the exnref hierarchy. Part of the exceptions proposal.
+ NoExn,
/// A reference to a concrete function, struct, or array type defined by
/// Wasm: `ref T`. This is part of the function references and GC proposals.
Concrete(Index<'a>),
@@ -124,6 +127,9 @@ impl<'a> Parse<'a> for HeapType<'a> {
} else if l.peek::<kw::noextern>()? {
parser.parse::<kw::noextern>()?;
Ok(HeapType::NoExtern)
+ } else if l.peek::<kw::noexn>()? {
+ parser.parse::<kw::noexn>()?;
+ Ok(HeapType::NoExn)
} else if l.peek::<kw::none>()? {
parser.parse::<kw::none>()?;
Ok(HeapType::None)
@@ -147,6 +153,7 @@ impl<'a> Peek for HeapType<'a> {
|| kw::i31::peek(cursor)?
|| kw::nofunc::peek(cursor)?
|| kw::noextern::peek(cursor)?
+ || kw::noexn::peek(cursor)?
|| kw::none::peek(cursor)?
|| (LParen::peek(cursor)? && kw::r#type::peek2(cursor)?))
}
@@ -251,6 +258,14 @@ impl<'a> RefType<'a> {
heap: HeapType::None,
}
}
+
+ /// A `nullexnref` as an abbreviation for `(ref null noexn)`.
+ pub fn nullexnref() -> Self {
+ RefType {
+ nullable: true,
+ heap: HeapType::NoExn,
+ }
+ }
}
impl<'a> Parse<'a> for RefType<'a> {
@@ -286,6 +301,9 @@ impl<'a> Parse<'a> for RefType<'a> {
} else if l.peek::<kw::nullexternref>()? {
parser.parse::<kw::nullexternref>()?;
Ok(RefType::nullexternref())
+ } else if l.peek::<kw::nullexnref>()? {
+ parser.parse::<kw::nullexnref>()?;
+ Ok(RefType::nullexnref())
} else if l.peek::<kw::nullref>()? {
parser.parse::<kw::nullref>()?;
Ok(RefType::nullref())
@@ -327,6 +345,7 @@ impl<'a> Peek for RefType<'a> {
|| kw::i31ref::peek(cursor)?
|| kw::nullfuncref::peek(cursor)?
|| kw::nullexternref::peek(cursor)?
+ || kw::nullexnref::peek(cursor)?
|| kw::nullref::peek(cursor)?
|| (LParen::peek(cursor)? && kw::r#ref::peek2(cursor)?))
}
@@ -368,22 +387,35 @@ pub struct GlobalType<'a> {
pub ty: ValType<'a>,
/// Whether or not the global is mutable or not.
pub mutable: bool,
+ /// Whether or not the global is shared.
+ pub shared: bool,
}
impl<'a> Parse<'a> for GlobalType<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
- if parser.peek2::<kw::r#mut>()? {
+ if parser.peek2::<kw::shared>()? || parser.peek2::<kw::r#mut>()? {
parser.parens(|p| {
- p.parse::<kw::r#mut>()?;
+ let mut shared = false;
+ let mut mutable = false;
+ if p.peek::<kw::shared>()? {
+ p.parse::<kw::shared>()?;
+ shared = true;
+ }
+ if p.peek::<kw::r#mut>()? {
+ p.parse::<kw::r#mut>()?;
+ mutable = true;
+ }
Ok(GlobalType {
- ty: parser.parse()?,
- mutable: true,
+ ty: p.parse()?,
+ mutable,
+ shared,
})
})
} else {
Ok(GlobalType {
ty: parser.parse()?,
mutable: false,
+ shared: false,
})
}
}
@@ -458,6 +490,8 @@ pub enum MemoryType {
limits: Limits,
/// Whether or not this is a shared (atomic) memory type
shared: bool,
+ /// The custom page size for this memory, if any.
+ page_size_log2: Option<u32>,
},
/// A 64-bit memory
B64 {
@@ -465,21 +499,53 @@ pub enum MemoryType {
limits: Limits64,
/// Whether or not this is a shared (atomic) memory type
shared: bool,
+ /// The custom page size for this memory, if any.
+ page_size_log2: Option<u32>,
},
}
+fn page_size(parser: Parser<'_>) -> Result<Option<u32>> {
+ if parser.peek::<LParen>()? {
+ Ok(Some(parser.parens(|parser| {
+ parser.parse::<kw::pagesize>()?;
+ let span = parser.cur_span();
+ let size = parser.parse::<u32>()?;
+ if size.is_power_of_two() {
+ Ok(size.ilog2())
+ } else {
+ Err(Error::new(
+ span,
+ format!("invalid custom page size: {size}"),
+ ))
+ }
+ })?))
+ } else {
+ Ok(None)
+ }
+}
+
impl<'a> Parse<'a> for MemoryType {
fn parse(parser: Parser<'a>) -> Result<Self> {
if parser.peek::<kw::i64>()? {
parser.parse::<kw::i64>()?;
let limits = parser.parse()?;
let shared = parser.parse::<Option<kw::shared>>()?.is_some();
- Ok(MemoryType::B64 { limits, shared })
+ let page_size = page_size(parser)?;
+ Ok(MemoryType::B64 {
+ limits,
+ shared,
+ page_size_log2: page_size,
+ })
} else {
parser.parse::<Option<kw::i32>>()?;
let limits = parser.parse()?;
let shared = parser.parse::<Option<kw::shared>>()?.is_some();
- Ok(MemoryType::B32 { limits, shared })
+ let page_size = page_size(parser)?;
+ Ok(MemoryType::B32 {
+ limits,
+ shared,
+ page_size_log2: page_size,
+ })
}
}
}
diff --git a/third_party/rust/wast/src/core/wast.rs b/third_party/rust/wast/src/core/wast.rs
index 2d3b51b061..9dd9a92391 100644
--- a/third_party/rust/wast/src/core/wast.rs
+++ b/third_party/rust/wast/src/core/wast.rs
@@ -1,7 +1,7 @@
use crate::core::{HeapType, V128Const};
use crate::kw;
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
-use crate::token::{Float32, Float64, Index};
+use crate::token::{Index, F32, F64};
/// Expression that can be used inside of `invoke` expressions for core wasm
/// functions.
@@ -10,8 +10,8 @@ use crate::token::{Float32, Float64, Index};
pub enum WastArgCore<'a> {
I32(i32),
I64(i64),
- F32(Float32),
- F64(Float64),
+ F32(F32),
+ F64(F64),
V128(V128Const),
RefNull(HeapType<'a>),
RefExtern(u32),
@@ -67,8 +67,8 @@ impl Peek for WastArgCore<'_> {
pub enum WastRetCore<'a> {
I32(i32),
I64(i64),
- F32(NanPattern<Float32>),
- F64(NanPattern<Float64>),
+ F32(NanPattern<F32>),
+ F64(NanPattern<F64>),
V128(V128Pattern),
/// A null reference is expected, optionally with a specified type.
@@ -151,7 +151,7 @@ impl Peek for WastRetCore<'_> {
}
/// Either a NaN pattern (`nan:canonical`, `nan:arithmetic`) or a value of type `T`.
-#[derive(Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(missing_docs)]
pub enum NanPattern<T> {
CanonicalNan,
@@ -181,15 +181,15 @@ where
///
/// This implementation is necessary because only float types can include NaN patterns; otherwise
/// it is largely similar to the implementation of `V128Const`.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum V128Pattern {
I8x16([i8; 16]),
I16x8([i16; 8]),
I32x4([i32; 4]),
I64x2([i64; 2]),
- F32x4([NanPattern<Float32>; 4]),
- F64x2([NanPattern<Float64>; 2]),
+ F32x4([NanPattern<F32>; 4]),
+ F64x2([NanPattern<F64>; 2]),
}
impl<'a> Parse<'a> for V128Pattern {
diff --git a/third_party/rust/wast/src/lib.rs b/third_party/rust/wast/src/lib.rs
index bb16574177..4964e8df0f 100644
--- a/third_party/rust/wast/src/lib.rs
+++ b/third_party/rust/wast/src/lib.rs
@@ -447,14 +447,17 @@ pub mod kw {
custom_keyword!(nan_canonical = "nan:canonical");
custom_keyword!(nofunc);
custom_keyword!(noextern);
+ custom_keyword!(noexn);
custom_keyword!(none);
custom_keyword!(null);
custom_keyword!(nullfuncref);
custom_keyword!(nullexternref);
+ custom_keyword!(nullexnref);
custom_keyword!(nullref);
custom_keyword!(offset);
custom_keyword!(outer);
custom_keyword!(own);
+ custom_keyword!(pagesize);
custom_keyword!(param);
custom_keyword!(parent);
custom_keyword!(passive);
@@ -469,12 +472,14 @@ pub mod kw {
custom_keyword!(ref_null = "ref.null");
custom_keyword!(register);
custom_keyword!(rec);
+ custom_keyword!(acq_rel);
custom_keyword!(rep);
custom_keyword!(resource);
custom_keyword!(resource_new = "resource.new");
custom_keyword!(resource_drop = "resource.drop");
custom_keyword!(resource_rep = "resource.rep");
custom_keyword!(result);
+ custom_keyword!(seq_cst);
custom_keyword!(shared);
custom_keyword!(start);
custom_keyword!(sub);
diff --git a/third_party/rust/wast/src/token.rs b/third_party/rust/wast/src/token.rs
index 9dd15f97a8..b296341096 100644
--- a/third_party/rust/wast/src/token.rs
+++ b/third_party/rust/wast/src/token.rs
@@ -639,13 +639,13 @@ macro_rules! float {
}
float! {
- Float32 => {
+ F32 => {
bits: u32,
float: f32,
exponent_bits: 8,
name: strtof,
}
- Float64 => {
+ F64 => {
bits: u64,
float: f64,
exponent_bits: 11,
@@ -677,6 +677,22 @@ impl Peek for LParen {
}
}
+/// A convenience type to use with [`Parser::peek`](crate::parser::Parser::peek)
+/// to see if the next token is the end of an s-expression.
+pub struct RParen {
+ _priv: (),
+}
+
+impl Peek for RParen {
+ fn peek(cursor: Cursor<'_>) -> Result<bool> {
+ cursor.peek_rparen()
+ }
+
+ fn display() -> &'static str {
+ "right paren"
+ }
+}
+
#[cfg(test)]
mod tests {
#[test]
diff --git a/third_party/rust/wast/src/wast.rs b/third_party/rust/wast/src/wast.rs
index 5e18f517d0..418bc83fc7 100644
--- a/third_party/rust/wast/src/wast.rs
+++ b/third_party/rust/wast/src/wast.rs
@@ -113,8 +113,7 @@ impl WastDirective<'_> {
/// Returns the location in the source that this directive was defined at
pub fn span(&self) -> Span {
match self {
- WastDirective::Wat(QuoteWat::Wat(Wat::Module(m))) => m.span,
- WastDirective::Wat(QuoteWat::Wat(Wat::Component(c))) => c.span,
+ WastDirective::Wat(QuoteWat::Wat(w)) => w.span(),
WastDirective::Wat(QuoteWat::QuoteModule(span, _)) => *span,
WastDirective::Wat(QuoteWat::QuoteComponent(span, _)) => *span,
WastDirective::AssertMalformed { span, .. }
@@ -219,11 +218,23 @@ pub enum WastExecute<'a> {
Invoke(WastInvoke<'a>),
Wat(Wat<'a>),
Get {
+ span: Span,
module: Option<Id<'a>>,
global: &'a str,
},
}
+impl<'a> WastExecute<'a> {
+ /// Returns the first span for this execute statement.
+ pub fn span(&self) -> Span {
+ match self {
+ WastExecute::Invoke(i) => i.span,
+ WastExecute::Wat(i) => i.span(),
+ WastExecute::Get { span, .. } => *span,
+ }
+ }
+}
+
impl<'a> Parse<'a> for WastExecute<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut l = parser.lookahead1();
@@ -232,8 +243,9 @@ impl<'a> Parse<'a> for WastExecute<'a> {
} else if l.peek::<kw::module>()? || l.peek::<kw::component>()? {
Ok(WastExecute::Wat(parse_wat(parser)?))
} else if l.peek::<kw::get>()? {
- parser.parse::<kw::get>()?;
+ let span = parser.parse::<kw::get>()?.0;
Ok(WastExecute::Get {
+ span,
module: parser.parse()?,
global: parser.parse()?,
})
@@ -296,28 +308,47 @@ impl QuoteWat<'_> {
/// Encodes this module to bytes, either by encoding the module directly or
/// parsing the contents and then encoding it.
pub fn encode(&mut self) -> Result<Vec<u8>, Error> {
+ match self.to_test()? {
+ QuoteWatTest::Binary(bytes) => Ok(bytes),
+ QuoteWatTest::Text(text) => {
+ let text = std::str::from_utf8(&text).map_err(|_| {
+ let span = self.span();
+ Error::new(span, "malformed UTF-8 encoding".to_string())
+ })?;
+ let buf = ParseBuffer::new(&text)?;
+ let mut wat = parser::parse::<Wat<'_>>(&buf)?;
+ wat.encode()
+ }
+ }
+ }
+
+ /// Converts this to either a `QuoteWatTest::Binary` or
+ /// `QuoteWatTest::Text` depending on what it is internally.
+ pub fn to_test(&mut self) -> Result<QuoteWatTest, Error> {
let (source, prefix) = match self {
- QuoteWat::Wat(m) => return m.encode(),
+ QuoteWat::Wat(m) => return m.encode().map(QuoteWatTest::Binary),
QuoteWat::QuoteModule(_, source) => (source, None),
QuoteWat::QuoteComponent(_, source) => (source, Some("(component")),
};
- let mut ret = String::new();
- for (span, src) in source {
- match std::str::from_utf8(src) {
- Ok(s) => ret.push_str(s),
- Err(_) => {
- return Err(Error::new(*span, "malformed UTF-8 encoding".to_string()));
- }
- }
- ret.push(' ');
+ let mut ret = Vec::new();
+ for (_, src) in source {
+ ret.extend_from_slice(src);
+ ret.push(b' ');
}
if let Some(prefix) = prefix {
- ret.insert_str(0, prefix);
- ret.push(')');
+ ret.splice(0..0, prefix.as_bytes().iter().copied());
+ ret.push(b')');
+ }
+ Ok(QuoteWatTest::Text(ret))
+ }
+
+ /// Returns the defining span of this module.
+ pub fn span(&self) -> Span {
+ match self {
+ QuoteWat::Wat(w) => w.span(),
+ QuoteWat::QuoteModule(span, _) => *span,
+ QuoteWat::QuoteComponent(span, _) => *span,
}
- let buf = ParseBuffer::new(&ret)?;
- let mut wat = parser::parse::<Wat<'_>>(&buf)?;
- wat.encode()
}
}
@@ -345,6 +376,14 @@ impl<'a> Parse<'a> for QuoteWat<'a> {
}
}
+/// Returned from [`QuoteWat::to_test`].
+#[allow(missing_docs)]
+#[derive(Debug)]
+pub enum QuoteWatTest {
+ Binary(Vec<u8>),
+ Text(Vec<u8>),
+}
+
#[derive(Debug)]
#[allow(missing_docs)]
pub enum WastArg<'a> {
diff --git a/third_party/rust/wast/src/wat.rs b/third_party/rust/wast/src/wat.rs
index 6d9a233359..d4982264fa 100644
--- a/third_party/rust/wast/src/wat.rs
+++ b/third_party/rust/wast/src/wat.rs
@@ -32,6 +32,14 @@ impl Wat<'_> {
Wat::Component(c) => c.encode(),
}
}
+
+ /// Returns the defining span of this file.
+ pub fn span(&self) -> Span {
+ match self {
+ Wat::Module(m) => m.span,
+ Wat::Component(c) => c.span,
+ }
+ }
}
impl<'a> Parse<'a> for Wat<'a> {
diff --git a/third_party/rust/wast/tests/parse-fail.rs b/third_party/rust/wast/tests/parse-fail.rs
index 3ae1817a4a..a8d4f34456 100644
--- a/third_party/rust/wast/tests/parse-fail.rs
+++ b/third_party/rust/wast/tests/parse-fail.rs
@@ -4,46 +4,28 @@
//! Use `BLESS=1` in the environment to auto-update `*.err` files. Be sure to
//! look at the diff!
-use rayon::prelude::*;
+use libtest_mimic::{Arguments, Trial};
use std::env;
use std::path::{Path, PathBuf};
fn main() {
let mut tests = Vec::new();
find_tests("tests/parse-fail".as_ref(), &mut tests);
- let filter = std::env::args().nth(1);
-
let bless = env::var("BLESS").is_ok();
- let tests = tests
- .iter()
- .filter(|test| {
- if let Some(filter) = &filter {
- if let Some(s) = test.file_name().and_then(|s| s.to_str()) {
- if !s.contains(filter) {
- return false;
- }
- }
- }
- true
- })
- .collect::<Vec<_>>();
-
- println!("running {} tests\n", tests.len());
-
- let errors = tests
- .par_iter()
- .filter_map(|test| run_test(test, bless).err())
- .collect::<Vec<_>>();
- if !errors.is_empty() {
- for msg in errors.iter() {
- eprintln!("{}", msg);
- }
-
- panic!("{} tests failed", errors.len())
+ let mut trials = Vec::new();
+ for test in tests {
+ let trial = Trial::test(format!("{test:?}"), move || {
+ run_test(&test, bless).map_err(|e| format!("{e:?}").into())
+ });
+ trials.push(trial);
}
- println!("test result: ok. {} passed\n", tests.len());
+ let mut args = Arguments::from_args();
+ if cfg!(target_family = "wasm") && !cfg!(target_feature = "atomics") {
+ args.test_threads = Some(1);
+ }
+ libtest_mimic::run(&args, trials).exit();
}
fn run_test(test: &Path, bless: bool) -> anyhow::Result<()> {
diff --git a/third_party/rust/wgpu-core/.cargo-checksum.json b/third_party/rust/wgpu-core/.cargo-checksum.json
index f025f2ccaa..a4f8ad5e63 100644
--- a/third_party/rust/wgpu-core/.cargo-checksum.json
+++ b/third_party/rust/wgpu-core/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"3f5fa464854359b0150d4fe82cf5b0c17874dbb3c3c708b2a9cc24ebc1a61349","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","build.rs":"a99478d7f63fb41429e3834f4d0e5cd333f94ba1834c68295f929170e16987de","src/any_surface.rs":"1c032bc1894a222a47f0116b976f1543c1140c0534678502ee1172d4f77fc515","src/binding_model.rs":"bb4aefad17957e770a5f70f00bf5853dc13da1d9f836493c9aa9adbbe7bb8147","src/command/bind.rs":"a37f042484b65d9fdea4cdab3667381623ee9a8943a6d32683d410b92736d306","src/command/bundle.rs":"3435ea21daba6f5a26f9a4158b342d0b9a1839da39b82fa8c23d84ee144b9da0","src/command/clear.rs":"2eb9c323c3ae3644563cab1bb1d26e4a17a54f5a120698c7f09ef9f9e9077780","src/command/compute.rs":"1ad1d8b83774422bd73c7c67c153205e451fd71602b37f34162b59e5f7dbbc75","src/command/draw.rs":"15f9ad857504d8098279f9c789317feba321c9b6b8f0de20b8ba98f358c99d89","src/command/memory_init.rs":"71550dabbf7cc3c3ff6aa4ccd31af080bb5e1cb1e21422daea63fee30294476f","src/command/mod.rs":"1d347e1746194f7a07d1f75bd3a9d3cbe121fbaa479c25ba6b8c16e9d699e06b","src/command/query.rs":"43b78a163eb0eb5f1427b7a57b6d39a2748c25f880ba024c91e2f71e2a6a817d","src/command/render.rs":"875545efa83e56face9a857c5d8c814bc46f4b0538a152933265533176ad1e84","src/command/transfer.rs":"63042151145825c5cac6459a5a254a82142c86d299895f72bef2682f71de7ad1","src/conv.rs":"7e3ffe33b47a6fd3617aabf9f11cc68f1ccbee2c7343b8dbbcd0e8f3447e1ad8","src/device/any_device.rs":"65f47b58939b60f88f47861e65d5d45209492df8e73e7c1b60b3b459f510c09e","src/device/bgl.rs":"ec8bdd6e9b4cd50c25bed317275863d0c16bb6619f62ed85bf0464948010dfc1","src/device/global.rs":"6a08dcc25059f2194999c4f5e3a57a1a96b17031873b1a871095dc58115470fb","src/device/life.rs":"efba75c8632e0bd9c655dbff1f8ff027900f388b6eeb357a9c02ddad24474b23","src/device/mod.rs":"e578d03253a9af314e1e81168d45ea8cc0a8f56df79e440dc1ade945d75277ec","src/device/queue.rs":"4405a6b8ea29093239f1556e5352f7c777f4f6b783fd5dea458fde22556741ca","src/device/resource.rs":"65f84150c467aa50615a097d15f6b4dba3514b0adf2de1e9b9837e5084619a80","src/device/trace.rs":"9deb1b083165e07253b4928ac2f564aba06f9089c3aca1c0a1d438d87d981542","src/error.rs":"e3b6b7a69877437f4e46af7f0e8ca1db1822beae7c8448db41c2bae0f64b2bb4","src/global.rs":"0966475959706650fd036a18d51441a8e14c3ef10107db617f597614ca47e50a","src/hal_api.rs":"1cd9c3fe1c9d8c3a24e3e7f963a2ef26e056a2b26d529b840dbc969090aaf201","src/hash_utils.rs":"e8d484027c7ce81978e4679a5e20af9416ab7d2fa595f1ca95992b29d625b0ca","src/hub.rs":"352a1b75d4535f24b06d16134421db98f910e6e719f50f863a204df6768e3369","src/id.rs":"9f67dbef5d7a416eb740281ecf8a94673f624da16f21ec33c425c11d9ed01e90","src/identity.rs":"12b820eb4b8bd7b226e15eec97d0f100a695f6b9be7acd79ad2421f2d0fe1985","src/init_tracker/buffer.rs":"61eb9cfaa312135b7a937ff6a3117f531b5b7323fae6553a41d6de9bc106d7e0","src/init_tracker/mod.rs":"a0f64730cc025113b656b4690f9dcb0ec18b8770bc7ef24c7b4ad8bebae03d24","src/init_tracker/texture.rs":"030fd594bf9948fad391390d85c5e1fec7eaf67b6e812c60f2dd59bc4fda8fd5","src/instance.rs":"b6de2a371ef3b43d3217102fe87e423dd1eb12da86b65f54b902d9eaa38b6b9f","src/lib.rs":"4ad9979442cf88557fb3b9f8d3b26c7b929a710c60cabcd1f51788917c95aecb","src/pipeline.rs":"89d88de4b8b8e1dd2bc834d101a1bdf34816ebcaa616dc795f604e9183a21cd0","src/pool.rs":"778ea1c23fcfaaa5001606e686f712f606826039d60dd5a3cd26e7de91ac057a","src/present.rs":"f69580ee0baf181162f9dd82b159596c738558d8abb60db93047effbe1436b2f","src/registry.rs":"913e651dc585ff12fe7659443c38d635a2904881e56cb7159c5ca72d45ae5800","src/resource.rs":"59731bc9a207d87b07b6db9c897e20d64be27c144bb8eb8ab2505807163acfc4","src/snatch.rs":"5cf0e4e4611083e8256092696ecf0caa9e855dd680c18fc7dbb227d071aa2548","src/storage.rs":"f0c41461b8f9cdc862dbd3de04c8e720ee416c7c57310696f6f4fd22183fcc85","src/track/buffer.rs":"d1b4c85dfaf1bcc93013d7f51ba677f97c36245c9de224fb328595aa15109cf6","src/track/metadata.rs":"7016911136bc5b97053f54241b01d344f5d65c4337a292c8aa32bb142a26be0c","src/track/mod.rs":"5365c532a531d224a958bd8217769ef59d67d293b4f95972c10db71f6bff1a80","src/track/range.rs":"2a15794e79b0470d5ba6b3267173a42f34312878e1cb288f198d2854a7888e53","src/track/stateless.rs":"305e0a493fb1cd0a325274c0757e99c19f9d14deaa8ca11ada41c1399a4ae5c4","src/track/texture.rs":"da83403d5990021c5db78f1ffdf69198eadb99cc77a6bc481648337a5403295c","src/validation.rs":"026168ac4f23bc6a58a90c78fd3eb73485b3c1aad630ef43755604d1babade79"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"ef0dc61297a9dd672d3e0e71ced2973a97f0abdb705432816874867ec4dc873b","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","build.rs":"a99478d7f63fb41429e3834f4d0e5cd333f94ba1834c68295f929170e16987de","src/binding_model.rs":"f1279d3cd1f84eab37dc85658f32bb4b4f2687c9086f4b4f30e8a4b0d7c1a582","src/command/allocator.rs":"5ca1e40a735f7cb0531d3e5298767963a3c0ee9e264b44d3a356cd7ef16bcb52","src/command/bind.rs":"a37f042484b65d9fdea4cdab3667381623ee9a8943a6d32683d410b92736d306","src/command/bundle.rs":"1c7fceda77668ae5a055bf1d0184b78cc7362f7763d6b6a3c9d1687e4782f908","src/command/clear.rs":"1eb475a48e04a011be381720a420047a3d65fc85be3b9b55e6874c7fd14e40a8","src/command/compute.rs":"7a58ff8f492dc8926ab8cd580c7ae8bf8703df4472f093f4a027f4969f55b0f9","src/command/compute_command.rs":"b00623d80e9aa3bb78c1d8d24ccbc0cbd6f945ef3c9206b8fba5c3ce86753f5e","src/command/draw.rs":"15f9ad857504d8098279f9c789317feba321c9b6b8f0de20b8ba98f358c99d89","src/command/memory_init.rs":"71550dabbf7cc3c3ff6aa4ccd31af080bb5e1cb1e21422daea63fee30294476f","src/command/mod.rs":"947c0dc1e82301e5571579031f0b1b0627d1f6d9c8d3b5e510c37673ea661fc1","src/command/query.rs":"92b5aff8580631c51bc1ba72a45605e704c997684fc6a891640da945712db5ec","src/command/render.rs":"6d02d9a9f0c1e58a448cbd30e62e51dca5b8b61e576ece15655c343cc51e84b9","src/command/transfer.rs":"d0324465a5637e8346276a0427446377c21acbb285ff819091673ba5fc365a9c","src/conv.rs":"7e3ffe33b47a6fd3617aabf9f11cc68f1ccbee2c7343b8dbbcd0e8f3447e1ad8","src/device/any_device.rs":"8802f6d9d7fa9cd0b02c5ed57412a2ef01b9ad2b47182e18a914ce4ad5e24fde","src/device/bgl.rs":"f1c372cd632deacb9d0f0880846844c7cbe5f1ca88592ed35dbd59966958b33d","src/device/global.rs":"1881c6729b86423a4ab75db1ae0e3d6a8d34ab4600f3cd5e38bf8768d07b6905","src/device/life.rs":"a65cab56e0eb688d0776e719da785372a742d6a87bd3f3bef9042e9428453c3a","src/device/mod.rs":"aa16ac918714c844820142b4d321ac4e9a51ffef37501c6f5ca48e3817353d16","src/device/queue.rs":"33cc4bb3337d49810dc74bfc2eb8ad97a82023ad263d80700c769d0c0ad9bfe4","src/device/resource.rs":"b0a55d496ca59056854d5d41264f519992b342a4049d1b65a13220d8a76902a1","src/device/trace.rs":"9deb1b083165e07253b4928ac2f564aba06f9089c3aca1c0a1d438d87d981542","src/error.rs":"e3b6b7a69877437f4e46af7f0e8ca1db1822beae7c8448db41c2bae0f64b2bb4","src/global.rs":"fe1ddd4863d50568780bf04382a4fd0d3d8441dd7baff9dacf57e860811b87c9","src/hal_api.rs":"fb65bfab0334cb8b0bbe823b1da6d1e82cd4a312c60a332ce65df9fbc2f74482","src/hash_utils.rs":"e8d484027c7ce81978e4679a5e20af9416ab7d2fa595f1ca95992b29d625b0ca","src/hub.rs":"59aeb5c902fd6707f651994fc9e335a6e7fdd998faebd29c087171e226101405","src/id.rs":"23634dec36eb171cb95c672519e69705d466044dcea29028b58d2288de35f8db","src/identity.rs":"b27d4e06b1f6c25ca2f4ad276fdf8c09a5d71f890b06cbabef7ef62369cb4df6","src/init_tracker/buffer.rs":"61eb9cfaa312135b7a937ff6a3117f531b5b7323fae6553a41d6de9bc106d7e0","src/init_tracker/mod.rs":"a0f64730cc025113b656b4690f9dcb0ec18b8770bc7ef24c7b4ad8bebae03d24","src/init_tracker/texture.rs":"030fd594bf9948fad391390d85c5e1fec7eaf67b6e812c60f2dd59bc4fda8fd5","src/instance.rs":"d4c46ff5d0cc13b09c7b364d6445d30eaf7ea6f50ac9d49b0022b3a6e9377445","src/lib.rs":"77ec01c43b6f5daab174e0831bd98771a708cdfd42b0203f45490b6977ef2923","src/lock/mod.rs":"c7069f05341f1c63f478ed9176f4fbd1a6f633ea71f124c3b4d6c1b02d1febe8","src/lock/rank.rs":"acc3ef80c39297a440a53ec33e437be7fbb56a4bb09e326cfeb3d4bf76f60ac8","src/lock/ranked.rs":"94c2d929b54bc4ea68258bb4d58b692b61accc394dd48dbab5e69f1bdafaeb56","src/lock/vanilla.rs":"a6cd5cc3c1900271783ba146adf07e28424f6fecc5466d54624dbda237770fb4","src/pipeline.rs":"033335a759b801de7c606baf3f2ac8c706b1bbe27b209bcca73093569b604c0e","src/pool.rs":"7899e74874da17c83ec39a88b360de12f564ef4bee2bb1240c37becdaeb57a86","src/present.rs":"1147399ff3a62b69c944001639cd1cf19295e13cf0ddd3850b2736afdb0720b4","src/registry.rs":"1104d6972dad982c6cc6dfd25cbc52d0b8279d7989525d78ed49551434fa3cea","src/resource.rs":"ce469bbd6ae54efb989770b04079ee1a9c248b95f31ad5dae79603f87574878d","src/snatch.rs":"f9849b1050adba708c1b9be5a21ce806c83eef71c4f79b513768918f857fe814","src/storage.rs":"0c5a8a732e33ea565528b3a02e7a6c15178bc8dbc49a9cedcd76f8ebb1039b48","src/track/buffer.rs":"8571ebd57302ab9aba4aef4a310a02fe0848485f57ac3a7197393fbfbaddff2e","src/track/metadata.rs":"4b85341adc3b725e326dec0fe691f7e8e6c4e7c0a1ada1d86dd72a0a0b6397e6","src/track/mod.rs":"0056f0299fa71cc3acca9aa6becba15e0845b8e9000a11780d0b78da2ee01beb","src/track/range.rs":"2a15794e79b0470d5ba6b3267173a42f34312878e1cb288f198d2854a7888e53","src/track/stateless.rs":"b49192d248434570c024078cf204ad47f9030ed7a541324bad525881b78f75a4","src/track/texture.rs":"f962f97b582d4b528483f09df8662484159b6f5d19b376de53462d411421cee5","src/validation.rs":"1433e035d656afda97ee047b3247cb1a63844360174d575acf52cac868e27a3c"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/wgpu-core/Cargo.toml b/third_party/rust/wgpu-core/Cargo.toml
index aef86b3bbf..a4d1530917 100644
--- a/third_party/rust/wgpu-core/Cargo.toml
+++ b/third_party/rust/wgpu-core/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.74"
name = "wgpu-core"
-version = "0.19.0"
+version = "0.20.0"
authors = ["gfx-rs developers"]
description = "WebGPU core logic on wgpu-hal"
homepage = "https://wgpu.rs/"
@@ -40,7 +40,6 @@ targets = [
arrayvec = "0.7"
bit-vec = "0.6"
bitflags = "2"
-codespan-reporting = "0.11"
document-features = "0.2.8"
indexmap = "2"
log = "0.4"
@@ -55,15 +54,14 @@ version = "1.14"
optional = true
[dependencies.hal]
-version = "0.19.0"
+version = "0.20.0"
path = "../wgpu-hal"
default_features = false
package = "wgpu-hal"
[dependencies.naga]
-version = "0.19.0"
+version = "0.20.0"
path = "../naga"
-features = ["clone"]
[dependencies.profiling]
version = "1"
@@ -83,7 +81,7 @@ features = ["serde_derive"]
optional = true
[dependencies.wgt]
-version = "0.19.0"
+version = "0.20.0"
path = "../wgpu-types"
package = "wgpu-types"
diff --git a/third_party/rust/wgpu-core/src/any_surface.rs b/third_party/rust/wgpu-core/src/any_surface.rs
deleted file mode 100644
index 94edfc4433..0000000000
--- a/third_party/rust/wgpu-core/src/any_surface.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-use wgt::Backend;
-
-/// The `AnySurface` type: a `Arc` of a `A::Surface` for any backend `A`.
-use crate::hal_api::HalApi;
-
-use std::fmt;
-use std::mem::ManuallyDrop;
-use std::ptr::NonNull;
-
-struct AnySurfaceVtable {
- // We oppurtunistically store the backend here, since we now it will be used
- // with backend selection and it can be stored in static memory.
- backend: Backend,
- // Drop glue which knows how to drop the stored data.
- drop: unsafe fn(*mut ()),
-}
-
-/// An `A::Surface`, for any backend `A`.
-///
-/// Any `AnySurface` is just like an `A::Surface`, except that the `A` type
-/// parameter is erased. To access the `Surface`, you must downcast to a
-/// particular backend with the \[`downcast_ref`\] or \[`take`\] methods.
-pub struct AnySurface {
- data: NonNull<()>,
- vtable: &'static AnySurfaceVtable,
-}
-
-impl AnySurface {
- /// Construct an `AnySurface` that owns an `A::Surface`.
- pub fn new<A: HalApi>(surface: A::Surface) -> AnySurface {
- unsafe fn drop_glue<A: HalApi>(ptr: *mut ()) {
- unsafe {
- _ = Box::from_raw(ptr.cast::<A::Surface>());
- }
- }
-
- let data = NonNull::from(Box::leak(Box::new(surface)));
-
- AnySurface {
- data: data.cast(),
- vtable: &AnySurfaceVtable {
- backend: A::VARIANT,
- drop: drop_glue::<A>,
- },
- }
- }
-
- /// Get the backend this surface was created through.
- pub fn backend(&self) -> Backend {
- self.vtable.backend
- }
-
- /// If `self` refers to an `A::Surface`, returns a reference to it.
- pub fn downcast_ref<A: HalApi>(&self) -> Option<&A::Surface> {
- if A::VARIANT != self.vtable.backend {
- return None;
- }
-
- // SAFETY: We just checked the instance above implicitly by the backend
- // that it was statically constructed through.
- Some(unsafe { &*self.data.as_ptr().cast::<A::Surface>() })
- }
-
- /// If `self` is an `Arc<A::Surface>`, returns that.
- pub fn take<A: HalApi>(self) -> Option<A::Surface> {
- if A::VARIANT != self.vtable.backend {
- return None;
- }
-
- // Disable drop glue, since we're returning the owned surface. The
- // caller will be responsible for dropping it.
- let this = ManuallyDrop::new(self);
-
- // SAFETY: We just checked the instance above implicitly by the backend
- // that it was statically constructed through.
- Some(unsafe { *Box::from_raw(this.data.as_ptr().cast::<A::Surface>()) })
- }
-}
-
-impl Drop for AnySurface {
- fn drop(&mut self) {
- unsafe { (self.vtable.drop)(self.data.as_ptr()) }
- }
-}
-
-impl fmt::Debug for AnySurface {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "AnySurface<{}>", self.vtable.backend)
- }
-}
-
-#[cfg(send_sync)]
-unsafe impl Send for AnySurface {}
-#[cfg(send_sync)]
-unsafe impl Sync for AnySurface {}
diff --git a/third_party/rust/wgpu-core/src/binding_model.rs b/third_party/rust/wgpu-core/src/binding_model.rs
index 8689af2ac1..bea63b0ba4 100644
--- a/third_party/rust/wgpu-core/src/binding_model.rs
+++ b/third_party/rust/wgpu-core/src/binding_model.rs
@@ -462,8 +462,6 @@ pub struct BindGroupLayoutDescriptor<'a> {
pub entries: Cow<'a, [wgt::BindGroupLayoutEntry]>,
}
-pub type BindGroupLayouts<A> = crate::storage::Storage<BindGroupLayout<A>>;
-
/// Bind group layout.
#[derive(Debug)]
pub struct BindGroupLayout<A: HalApi> {
diff --git a/third_party/rust/wgpu-core/src/command/allocator.rs b/third_party/rust/wgpu-core/src/command/allocator.rs
new file mode 100644
index 0000000000..e17fd08d76
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/command/allocator.rs
@@ -0,0 +1,67 @@
+use crate::hal_api::HalApi;
+use crate::resource_log;
+use hal::Device as _;
+
+use crate::lock::{rank, Mutex};
+
+/// A pool of free [`wgpu_hal::CommandEncoder`]s, owned by a `Device`.
+///
+/// Each encoder in this list is in the "closed" state.
+///
+/// Since a raw [`CommandEncoder`][ce] is itself a pool for allocating
+/// raw [`CommandBuffer`][cb]s, this is a pool of pools.
+///
+/// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
+/// [ce]: hal::CommandEncoder
+/// [cb]: hal::Api::CommandBuffer
+pub(crate) struct CommandAllocator<A: HalApi> {
+ free_encoders: Mutex<Vec<A::CommandEncoder>>,
+}
+
+impl<A: HalApi> CommandAllocator<A> {
+ pub(crate) fn new() -> Self {
+ Self {
+ free_encoders: Mutex::new(rank::COMMAND_ALLOCATOR_FREE_ENCODERS, Vec::new()),
+ }
+ }
+
+ /// Return a fresh [`wgpu_hal::CommandEncoder`] in the "closed" state.
+ ///
+ /// If we have free encoders in the pool, take one of those. Otherwise,
+ /// create a new one on `device`.
+ ///
+ /// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
+ pub(crate) fn acquire_encoder(
+ &self,
+ device: &A::Device,
+ queue: &A::Queue,
+ ) -> Result<A::CommandEncoder, hal::DeviceError> {
+ let mut free_encoders = self.free_encoders.lock();
+ match free_encoders.pop() {
+ Some(encoder) => Ok(encoder),
+ None => unsafe {
+ let hal_desc = hal::CommandEncoderDescriptor { label: None, queue };
+ device.create_command_encoder(&hal_desc)
+ },
+ }
+ }
+
+ /// Add `encoder` back to the free pool.
+ pub(crate) fn release_encoder(&self, encoder: A::CommandEncoder) {
+ let mut free_encoders = self.free_encoders.lock();
+ free_encoders.push(encoder);
+ }
+
+ /// Free the pool of command encoders.
+ ///
+ /// This is only called when the `Device` is dropped.
+ pub(crate) fn dispose(&self, device: &A::Device) {
+ let mut free_encoders = self.free_encoders.lock();
+ resource_log!("CommandAllocator::dispose encoders {}", free_encoders.len());
+ for cmd_encoder in free_encoders.drain(..) {
+ unsafe {
+ device.destroy_command_encoder(cmd_encoder);
+ }
+ }
+ }
+}
diff --git a/third_party/rust/wgpu-core/src/command/bundle.rs b/third_party/rust/wgpu-core/src/command/bundle.rs
index 47beda8ec6..d9d821c533 100644
--- a/third_party/rust/wgpu-core/src/command/bundle.rs
+++ b/third_party/rust/wgpu-core/src/command/bundle.rs
@@ -73,7 +73,7 @@ index format changes.
[Gdcrbe]: crate::global::Global::device_create_render_bundle_encoder
[Grbef]: crate::global::Global::render_bundle_encoder_finish
-[wrpeb]: crate::command::render_ffi::wgpu_render_pass_execute_bundles
+[wrpeb]: crate::command::render::render_commands::wgpu_render_pass_execute_bundles
!*/
#![allow(clippy::reversed_empty_ranges)]
@@ -113,7 +113,7 @@ use hal::CommandEncoder as _;
use super::ArcRenderCommand;
-/// https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw
+/// <https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw>
fn validate_draw<A: HalApi>(
vertex: &[Option<VertexState<A>>],
step: &[VertexStep],
@@ -1548,15 +1548,14 @@ pub mod bundle_ffi {
offsets: *const DynamicOffset,
offset_length: usize,
) {
- let redundant = unsafe {
- bundle.current_bind_groups.set_and_check_redundant(
- bind_group_id,
- index,
- &mut bundle.base.dynamic_offsets,
- offsets,
- offset_length,
- )
- };
+ let offsets = unsafe { slice::from_raw_parts(offsets, offset_length) };
+
+ let redundant = bundle.current_bind_groups.set_and_check_redundant(
+ bind_group_id,
+ index,
+ &mut bundle.base.dynamic_offsets,
+ offsets,
+ );
if redundant {
return;
diff --git a/third_party/rust/wgpu-core/src/command/clear.rs b/third_party/rust/wgpu-core/src/command/clear.rs
index 72c923f82e..faff177928 100644
--- a/third_party/rust/wgpu-core/src/command/clear.rs
+++ b/third_party/rust/wgpu-core/src/command/clear.rs
@@ -104,6 +104,11 @@ impl Global {
let dst_buffer = buffer_guard
.get(dst)
.map_err(|_| ClearError::InvalidBuffer(dst))?;
+
+ if dst_buffer.device.as_info().id() != cmd_buf.device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
cmd_buf_data
.trackers
.buffers
@@ -200,6 +205,10 @@ impl Global {
.get(dst)
.map_err(|_| ClearError::InvalidTexture(dst))?;
+ if dst_texture.device.as_info().id() != cmd_buf.device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
// Check if subresource aspects are valid.
let clear_aspects =
hal::FormatAspects::new(dst_texture.desc.format, subresource_range.aspect);
diff --git a/third_party/rust/wgpu-core/src/command/compute.rs b/third_party/rust/wgpu-core/src/command/compute.rs
index b38324984c..4ee48f0086 100644
--- a/third_party/rust/wgpu-core/src/command/compute.rs
+++ b/third_party/rust/wgpu-core/src/command/compute.rs
@@ -1,3 +1,4 @@
+use crate::command::compute_command::{ArcComputeCommand, ComputeCommand};
use crate::device::DeviceError;
use crate::resource::Resource;
use crate::snatch::SnatchGuard;
@@ -20,7 +21,6 @@ use crate::{
hal_label, id,
id::DeviceId,
init_tracker::MemoryInitKind,
- pipeline,
resource::{self},
storage::Storage,
track::{Tracker, UsageConflict, UsageScope},
@@ -36,61 +36,9 @@ use serde::Serialize;
use thiserror::Error;
+use std::sync::Arc;
use std::{fmt, mem, str};
-#[doc(hidden)]
-#[derive(Clone, Copy, Debug)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-pub enum ComputeCommand {
- SetBindGroup {
- index: u32,
- num_dynamic_offsets: usize,
- bind_group_id: id::BindGroupId,
- },
- SetPipeline(id::ComputePipelineId),
-
- /// Set a range of push constants to values stored in [`BasePass::push_constant_data`].
- SetPushConstant {
- /// The byte offset within the push constant storage to write to. This
- /// must be a multiple of four.
- offset: u32,
-
- /// The number of bytes to write. This must be a multiple of four.
- size_bytes: u32,
-
- /// Index in [`BasePass::push_constant_data`] of the start of the data
- /// to be written.
- ///
- /// Note: this is not a byte offset like `offset`. Rather, it is the
- /// index of the first `u32` element in `push_constant_data` to read.
- values_offset: u32,
- },
-
- Dispatch([u32; 3]),
- DispatchIndirect {
- buffer_id: id::BufferId,
- offset: wgt::BufferAddress,
- },
- PushDebugGroup {
- color: u32,
- len: usize,
- },
- PopDebugGroup,
- InsertDebugMarker {
- color: u32,
- len: usize,
- },
- WriteTimestamp {
- query_set_id: id::QuerySetId,
- query_index: u32,
- },
- BeginPipelineStatisticsQuery {
- query_set_id: id::QuerySetId,
- query_index: u32,
- },
- EndPipelineStatisticsQuery,
-}
-
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ComputePass {
base: BasePass<ComputeCommand>,
@@ -184,7 +132,7 @@ pub enum ComputePassErrorInner {
#[error(transparent)]
Encoder(#[from] CommandEncoderError),
#[error("Bind group at index {0:?} is invalid")]
- InvalidBindGroup(usize),
+ InvalidBindGroup(u32),
#[error("Device {0:?} is invalid")]
InvalidDevice(DeviceId),
#[error("Bind group index {index} is greater than the device's requested `max_bind_group` limit {max}")]
@@ -249,7 +197,7 @@ impl PrettyError for ComputePassErrorInner {
pub struct ComputePassError {
pub scope: PassErrorScope,
#[source]
- inner: ComputePassErrorInner,
+ pub(super) inner: ComputePassErrorInner,
}
impl PrettyError for ComputePassError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
@@ -346,7 +294,8 @@ impl Global {
encoder_id: id::CommandEncoderId,
pass: &ComputePass,
) -> Result<(), ComputePassError> {
- self.command_encoder_run_compute_pass_impl::<A>(
+ // TODO: This should go directly to `command_encoder_run_compute_pass_impl` by means of storing `ArcComputeCommand` internally.
+ self.command_encoder_run_compute_pass_with_unresolved_commands::<A>(
encoder_id,
pass.base.as_ref(),
pass.timestamp_writes.as_ref(),
@@ -354,18 +303,41 @@ impl Global {
}
#[doc(hidden)]
- pub fn command_encoder_run_compute_pass_impl<A: HalApi>(
+ pub fn command_encoder_run_compute_pass_with_unresolved_commands<A: HalApi>(
&self,
encoder_id: id::CommandEncoderId,
base: BasePassRef<ComputeCommand>,
timestamp_writes: Option<&ComputePassTimestampWrites>,
) -> Result<(), ComputePassError> {
+ let resolved_commands =
+ ComputeCommand::resolve_compute_command_ids(A::hub(self), base.commands)?;
+
+ self.command_encoder_run_compute_pass_impl::<A>(
+ encoder_id,
+ BasePassRef {
+ label: base.label,
+ commands: &resolved_commands,
+ dynamic_offsets: base.dynamic_offsets,
+ string_data: base.string_data,
+ push_constant_data: base.push_constant_data,
+ },
+ timestamp_writes,
+ )
+ }
+
+ fn command_encoder_run_compute_pass_impl<A: HalApi>(
+ &self,
+ encoder_id: id::CommandEncoderId,
+ base: BasePassRef<ArcComputeCommand<A>>,
+ timestamp_writes: Option<&ComputePassTimestampWrites>,
+ ) -> Result<(), ComputePassError> {
profiling::scope!("CommandEncoder::run_compute_pass");
let pass_scope = PassErrorScope::Pass(encoder_id);
let hub = A::hub(self);
- let cmd_buf = CommandBuffer::get_encoder(hub, encoder_id).map_pass_err(pass_scope)?;
+ let cmd_buf: Arc<CommandBuffer<A>> =
+ CommandBuffer::get_encoder(hub, encoder_id).map_pass_err(pass_scope)?;
let device = &cmd_buf.device;
if !device.is_valid() {
return Err(ComputePassErrorInner::InvalidDevice(
@@ -380,7 +352,13 @@ impl Global {
#[cfg(feature = "trace")]
if let Some(ref mut list) = cmd_buf_data.commands {
list.push(crate::device::trace::Command::RunComputePass {
- base: BasePass::from_ref(base),
+ base: BasePass {
+ label: base.label.map(str::to_string),
+ commands: base.commands.iter().map(Into::into).collect(),
+ dynamic_offsets: base.dynamic_offsets.to_vec(),
+ string_data: base.string_data.to_vec(),
+ push_constant_data: base.push_constant_data.to_vec(),
+ },
timestamp_writes: timestamp_writes.cloned(),
});
}
@@ -400,9 +378,7 @@ impl Global {
let raw = encoder.open().map_pass_err(pass_scope)?;
let bind_group_guard = hub.bind_groups.read();
- let pipeline_guard = hub.compute_pipelines.read();
let query_set_guard = hub.query_sets.read();
- let buffer_guard = hub.buffers.read();
let mut state = State {
binder: Binder::new(),
@@ -480,19 +456,21 @@ impl Global {
// be inserted before texture reads.
let mut pending_discard_init_fixups = SurfacesInDiscardState::new();
+ // TODO: We should be draining the commands here, avoiding extra copies in the process.
+ // (A command encoder can't be executed twice!)
for command in base.commands {
- match *command {
- ComputeCommand::SetBindGroup {
+ match command {
+ ArcComputeCommand::SetBindGroup {
index,
num_dynamic_offsets,
- bind_group_id,
+ bind_group,
} => {
- let scope = PassErrorScope::SetBindGroup(bind_group_id);
+ let scope = PassErrorScope::SetBindGroup(bind_group.as_info().id());
let max_bind_groups = cmd_buf.limits.max_bind_groups;
- if index >= max_bind_groups {
+ if index >= &max_bind_groups {
return Err(ComputePassErrorInner::BindGroupIndexOutOfRange {
- index,
+ index: *index,
max: max_bind_groups,
})
.map_pass_err(scope);
@@ -505,13 +483,9 @@ impl Global {
);
dynamic_offset_count += num_dynamic_offsets;
- let bind_group = tracker
- .bind_groups
- .add_single(&*bind_group_guard, bind_group_id)
- .ok_or(ComputePassErrorInner::InvalidBindGroup(index as usize))
- .map_pass_err(scope)?;
+ let bind_group = tracker.bind_groups.insert_single(bind_group.clone());
bind_group
- .validate_dynamic_bindings(index, &temp_offsets, &cmd_buf.limits)
+ .validate_dynamic_bindings(*index, &temp_offsets, &cmd_buf.limits)
.map_pass_err(scope)?;
buffer_memory_init_actions.extend(
@@ -533,14 +507,14 @@ impl Global {
let entries =
state
.binder
- .assign_group(index as usize, bind_group, &temp_offsets);
+ .assign_group(*index as usize, bind_group, &temp_offsets);
if !entries.is_empty() && pipeline_layout.is_some() {
let pipeline_layout = pipeline_layout.as_ref().unwrap().raw();
for (i, e) in entries.iter().enumerate() {
if let Some(group) = e.group.as_ref() {
let raw_bg = group
.raw(&snatch_guard)
- .ok_or(ComputePassErrorInner::InvalidBindGroup(i))
+ .ok_or(ComputePassErrorInner::InvalidBindGroup(i as u32))
.map_pass_err(scope)?;
unsafe {
raw.set_bind_group(
@@ -554,16 +528,13 @@ impl Global {
}
}
}
- ComputeCommand::SetPipeline(pipeline_id) => {
+ ArcComputeCommand::SetPipeline(pipeline) => {
+ let pipeline_id = pipeline.as_info().id();
let scope = PassErrorScope::SetPipelineCompute(pipeline_id);
state.pipeline = Some(pipeline_id);
- let pipeline: &pipeline::ComputePipeline<A> = tracker
- .compute_pipelines
- .add_single(&*pipeline_guard, pipeline_id)
- .ok_or(ComputePassErrorInner::InvalidPipeline(pipeline_id))
- .map_pass_err(scope)?;
+ tracker.compute_pipelines.insert_single(pipeline.clone());
unsafe {
raw.set_compute_pipeline(pipeline.raw());
@@ -587,7 +558,7 @@ impl Global {
if let Some(group) = e.group.as_ref() {
let raw_bg = group
.raw(&snatch_guard)
- .ok_or(ComputePassErrorInner::InvalidBindGroup(i))
+ .ok_or(ComputePassErrorInner::InvalidBindGroup(i as u32))
.map_pass_err(scope)?;
unsafe {
raw.set_bind_group(
@@ -623,7 +594,7 @@ impl Global {
}
}
}
- ComputeCommand::SetPushConstant {
+ ArcComputeCommand::SetPushConstant {
offset,
size_bytes,
values_offset,
@@ -634,7 +605,7 @@ impl Global {
let values_end_offset =
(values_offset + size_bytes / wgt::PUSH_CONSTANT_ALIGNMENT) as usize;
let data_slice =
- &base.push_constant_data[(values_offset as usize)..values_end_offset];
+ &base.push_constant_data[(*values_offset as usize)..values_end_offset];
let pipeline_layout = state
.binder
@@ -649,7 +620,7 @@ impl Global {
pipeline_layout
.validate_push_constant_ranges(
wgt::ShaderStages::COMPUTE,
- offset,
+ *offset,
end_offset_bytes,
)
.map_pass_err(scope)?;
@@ -658,12 +629,12 @@ impl Global {
raw.set_push_constants(
pipeline_layout.raw(),
wgt::ShaderStages::COMPUTE,
- offset,
+ *offset,
data_slice,
);
}
}
- ComputeCommand::Dispatch(groups) => {
+ ArcComputeCommand::Dispatch(groups) => {
let scope = PassErrorScope::Dispatch {
indirect: false,
pipeline: state.pipeline,
@@ -688,7 +659,7 @@ impl Global {
{
return Err(ComputePassErrorInner::Dispatch(
DispatchError::InvalidGroupSize {
- current: groups,
+ current: *groups,
limit: groups_size_limit,
},
))
@@ -696,10 +667,11 @@ impl Global {
}
unsafe {
- raw.dispatch(groups);
+ raw.dispatch(*groups);
}
}
- ComputeCommand::DispatchIndirect { buffer_id, offset } => {
+ ArcComputeCommand::DispatchIndirect { buffer, offset } => {
+ let buffer_id = buffer.as_info().id();
let scope = PassErrorScope::Dispatch {
indirect: true,
pipeline: state.pipeline,
@@ -711,29 +683,25 @@ impl Global {
.require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION)
.map_pass_err(scope)?;
- let indirect_buffer = state
+ state
.scope
.buffers
- .merge_single(&*buffer_guard, buffer_id, hal::BufferUses::INDIRECT)
+ .insert_merge_single(buffer.clone(), hal::BufferUses::INDIRECT)
+ .map_pass_err(scope)?;
+ check_buffer_usage(buffer_id, buffer.usage, wgt::BufferUsages::INDIRECT)
.map_pass_err(scope)?;
- check_buffer_usage(
- buffer_id,
- indirect_buffer.usage,
- wgt::BufferUsages::INDIRECT,
- )
- .map_pass_err(scope)?;
let end_offset = offset + mem::size_of::<wgt::DispatchIndirectArgs>() as u64;
- if end_offset > indirect_buffer.size {
+ if end_offset > buffer.size {
return Err(ComputePassErrorInner::IndirectBufferOverrun {
- offset,
+ offset: *offset,
end_offset,
- buffer_size: indirect_buffer.size,
+ buffer_size: buffer.size,
})
.map_pass_err(scope);
}
- let buf_raw = indirect_buffer
+ let buf_raw = buffer
.raw
.get(&snatch_guard)
.ok_or(ComputePassErrorInner::InvalidIndirectBuffer(buffer_id))
@@ -742,9 +710,9 @@ impl Global {
let stride = 3 * 4; // 3 integers, x/y/z group size
buffer_memory_init_actions.extend(
- indirect_buffer.initialization_status.read().create_action(
- indirect_buffer,
- offset..(offset + stride),
+ buffer.initialization_status.read().create_action(
+ buffer,
+ *offset..(*offset + stride),
MemoryInitKind::NeedsInitializedMemory,
),
);
@@ -754,15 +722,15 @@ impl Global {
raw,
&mut intermediate_trackers,
&*bind_group_guard,
- Some(indirect_buffer.as_info().tracker_index()),
+ Some(buffer.as_info().tracker_index()),
&snatch_guard,
)
.map_pass_err(scope)?;
unsafe {
- raw.dispatch_indirect(buf_raw, offset);
+ raw.dispatch_indirect(buf_raw, *offset);
}
}
- ComputeCommand::PushDebugGroup { color: _, len } => {
+ ArcComputeCommand::PushDebugGroup { color: _, len } => {
state.debug_scope_depth += 1;
if !discard_hal_labels {
let label =
@@ -774,7 +742,7 @@ impl Global {
}
string_offset += len;
}
- ComputeCommand::PopDebugGroup => {
+ ArcComputeCommand::PopDebugGroup => {
let scope = PassErrorScope::PopDebugGroup;
if state.debug_scope_depth == 0 {
@@ -788,7 +756,7 @@ impl Global {
}
}
}
- ComputeCommand::InsertDebugMarker { color: _, len } => {
+ ArcComputeCommand::InsertDebugMarker { color: _, len } => {
if !discard_hal_labels {
let label =
str::from_utf8(&base.string_data[string_offset..string_offset + len])
@@ -797,49 +765,43 @@ impl Global {
}
string_offset += len;
}
- ComputeCommand::WriteTimestamp {
- query_set_id,
+ ArcComputeCommand::WriteTimestamp {
+ query_set,
query_index,
} => {
+ let query_set_id = query_set.as_info().id();
let scope = PassErrorScope::WriteTimestamp;
device
.require_features(wgt::Features::TIMESTAMP_QUERY_INSIDE_PASSES)
.map_pass_err(scope)?;
- let query_set: &resource::QuerySet<A> = tracker
- .query_sets
- .add_single(&*query_set_guard, query_set_id)
- .ok_or(ComputePassErrorInner::InvalidQuerySet(query_set_id))
- .map_pass_err(scope)?;
+ let query_set = tracker.query_sets.insert_single(query_set.clone());
query_set
- .validate_and_write_timestamp(raw, query_set_id, query_index, None)
+ .validate_and_write_timestamp(raw, query_set_id, *query_index, None)
.map_pass_err(scope)?;
}
- ComputeCommand::BeginPipelineStatisticsQuery {
- query_set_id,
+ ArcComputeCommand::BeginPipelineStatisticsQuery {
+ query_set,
query_index,
} => {
+ let query_set_id = query_set.as_info().id();
let scope = PassErrorScope::BeginPipelineStatisticsQuery;
- let query_set: &resource::QuerySet<A> = tracker
- .query_sets
- .add_single(&*query_set_guard, query_set_id)
- .ok_or(ComputePassErrorInner::InvalidQuerySet(query_set_id))
- .map_pass_err(scope)?;
+ let query_set = tracker.query_sets.insert_single(query_set.clone());
query_set
.validate_and_begin_pipeline_statistics_query(
raw,
query_set_id,
- query_index,
+ *query_index,
None,
&mut active_query,
)
.map_pass_err(scope)?;
}
- ComputeCommand::EndPipelineStatisticsQuery => {
+ ArcComputeCommand::EndPipelineStatisticsQuery => {
let scope = PassErrorScope::EndPipelineStatisticsQuery;
end_pipeline_statistics_query(raw, &*query_set_guard, &mut active_query)
@@ -883,33 +845,24 @@ impl Global {
}
}
-pub mod compute_ffi {
+pub mod compute_commands {
use super::{ComputeCommand, ComputePass};
- use crate::{id, RawString};
- use std::{convert::TryInto, ffi, slice};
+ use crate::id;
+ use std::convert::TryInto;
use wgt::{BufferAddress, DynamicOffset};
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given pointer is
- /// valid for `offset_length` elements.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_compute_pass_set_bind_group(
+ pub fn wgpu_compute_pass_set_bind_group(
pass: &mut ComputePass,
index: u32,
bind_group_id: id::BindGroupId,
- offsets: *const DynamicOffset,
- offset_length: usize,
+ offsets: &[DynamicOffset],
) {
- let redundant = unsafe {
- pass.current_bind_groups.set_and_check_redundant(
- bind_group_id,
- index,
- &mut pass.base.dynamic_offsets,
- offsets,
- offset_length,
- )
- };
+ let redundant = pass.current_bind_groups.set_and_check_redundant(
+ bind_group_id,
+ index,
+ &mut pass.base.dynamic_offsets,
+ offsets,
+ );
if redundant {
return;
@@ -917,13 +870,12 @@ pub mod compute_ffi {
pass.base.commands.push(ComputeCommand::SetBindGroup {
index,
- num_dynamic_offsets: offset_length,
+ num_dynamic_offsets: offsets.len(),
bind_group_id,
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_compute_pass_set_pipeline(
+ pub fn wgpu_compute_pass_set_pipeline(
pass: &mut ComputePass,
pipeline_id: id::ComputePipelineId,
) {
@@ -936,47 +888,34 @@ pub mod compute_ffi {
.push(ComputeCommand::SetPipeline(pipeline_id));
}
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given pointer is
- /// valid for `size_bytes` bytes.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_compute_pass_set_push_constant(
- pass: &mut ComputePass,
- offset: u32,
- size_bytes: u32,
- data: *const u8,
- ) {
+ pub fn wgpu_compute_pass_set_push_constant(pass: &mut ComputePass, offset: u32, data: &[u8]) {
assert_eq!(
offset & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
0,
"Push constant offset must be aligned to 4 bytes."
);
assert_eq!(
- size_bytes & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
+ data.len() as u32 & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
0,
"Push constant size must be aligned to 4 bytes."
);
- let data_slice = unsafe { slice::from_raw_parts(data, size_bytes as usize) };
let value_offset = pass.base.push_constant_data.len().try_into().expect(
"Ran out of push constant space. Don't set 4gb of push constants per ComputePass.",
);
pass.base.push_constant_data.extend(
- data_slice
- .chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
+ data.chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
.map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])),
);
pass.base.commands.push(ComputeCommand::SetPushConstant {
offset,
- size_bytes,
+ size_bytes: data.len() as u32,
values_offset: value_offset,
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_compute_pass_dispatch_workgroups(
+ pub fn wgpu_compute_pass_dispatch_workgroups(
pass: &mut ComputePass,
groups_x: u32,
groups_y: u32,
@@ -987,8 +926,7 @@ pub mod compute_ffi {
.push(ComputeCommand::Dispatch([groups_x, groups_y, groups_z]));
}
- #[no_mangle]
- pub extern "C" fn wgpu_compute_pass_dispatch_workgroups_indirect(
+ pub fn wgpu_compute_pass_dispatch_workgroups_indirect(
pass: &mut ComputePass,
buffer_id: id::BufferId,
offset: BufferAddress,
@@ -998,17 +936,8 @@ pub mod compute_ffi {
.push(ComputeCommand::DispatchIndirect { buffer_id, offset });
}
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given `label`
- /// is a valid null-terminated string.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_compute_pass_push_debug_group(
- pass: &mut ComputePass,
- label: RawString,
- color: u32,
- ) {
- let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pub fn wgpu_compute_pass_push_debug_group(pass: &mut ComputePass, label: &str, color: u32) {
+ let bytes = label.as_bytes();
pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(ComputeCommand::PushDebugGroup {
@@ -1017,22 +946,12 @@ pub mod compute_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_compute_pass_pop_debug_group(pass: &mut ComputePass) {
+ pub fn wgpu_compute_pass_pop_debug_group(pass: &mut ComputePass) {
pass.base.commands.push(ComputeCommand::PopDebugGroup);
}
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given `label`
- /// is a valid null-terminated string.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_compute_pass_insert_debug_marker(
- pass: &mut ComputePass,
- label: RawString,
- color: u32,
- ) {
- let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pub fn wgpu_compute_pass_insert_debug_marker(pass: &mut ComputePass, label: &str, color: u32) {
+ let bytes = label.as_bytes();
pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(ComputeCommand::InsertDebugMarker {
@@ -1041,8 +960,7 @@ pub mod compute_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_compute_pass_write_timestamp(
+ pub fn wgpu_compute_pass_write_timestamp(
pass: &mut ComputePass,
query_set_id: id::QuerySetId,
query_index: u32,
@@ -1053,8 +971,7 @@ pub mod compute_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_compute_pass_begin_pipeline_statistics_query(
+ pub fn wgpu_compute_pass_begin_pipeline_statistics_query(
pass: &mut ComputePass,
query_set_id: id::QuerySetId,
query_index: u32,
@@ -1067,8 +984,7 @@ pub mod compute_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_compute_pass_end_pipeline_statistics_query(pass: &mut ComputePass) {
+ pub fn wgpu_compute_pass_end_pipeline_statistics_query(pass: &mut ComputePass) {
pass.base
.commands
.push(ComputeCommand::EndPipelineStatisticsQuery);
diff --git a/third_party/rust/wgpu-core/src/command/compute_command.rs b/third_party/rust/wgpu-core/src/command/compute_command.rs
new file mode 100644
index 0000000000..49fdbbec24
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/command/compute_command.rs
@@ -0,0 +1,322 @@
+use std::sync::Arc;
+
+use crate::{
+ binding_model::BindGroup,
+ hal_api::HalApi,
+ id,
+ pipeline::ComputePipeline,
+ resource::{Buffer, QuerySet},
+};
+
+use super::{ComputePassError, ComputePassErrorInner, PassErrorScope};
+
+#[derive(Clone, Copy, Debug)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub enum ComputeCommand {
+ SetBindGroup {
+ index: u32,
+ num_dynamic_offsets: usize,
+ bind_group_id: id::BindGroupId,
+ },
+
+ SetPipeline(id::ComputePipelineId),
+
+ /// Set a range of push constants to values stored in `push_constant_data`.
+ SetPushConstant {
+ /// The byte offset within the push constant storage to write to. This
+ /// must be a multiple of four.
+ offset: u32,
+
+ /// The number of bytes to write. This must be a multiple of four.
+ size_bytes: u32,
+
+ /// Index in `push_constant_data` of the start of the data
+ /// to be written.
+ ///
+ /// Note: this is not a byte offset like `offset`. Rather, it is the
+ /// index of the first `u32` element in `push_constant_data` to read.
+ values_offset: u32,
+ },
+
+ Dispatch([u32; 3]),
+
+ DispatchIndirect {
+ buffer_id: id::BufferId,
+ offset: wgt::BufferAddress,
+ },
+
+ PushDebugGroup {
+ color: u32,
+ len: usize,
+ },
+
+ PopDebugGroup,
+
+ InsertDebugMarker {
+ color: u32,
+ len: usize,
+ },
+
+ WriteTimestamp {
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+ },
+
+ BeginPipelineStatisticsQuery {
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+ },
+
+ EndPipelineStatisticsQuery,
+}
+
+impl ComputeCommand {
+ /// Resolves all ids in a list of commands into the corresponding resource Arc.
+ ///
+ // TODO: Once resolving is done on-the-fly during recording, this function should be only needed with the replay feature:
+ // #[cfg(feature = "replay")]
+ pub fn resolve_compute_command_ids<A: HalApi>(
+ hub: &crate::hub::Hub<A>,
+ commands: &[ComputeCommand],
+ ) -> Result<Vec<ArcComputeCommand<A>>, ComputePassError> {
+ let buffers_guard = hub.buffers.read();
+ let bind_group_guard = hub.bind_groups.read();
+ let query_set_guard = hub.query_sets.read();
+ let pipelines_guard = hub.compute_pipelines.read();
+
+ let resolved_commands: Vec<ArcComputeCommand<A>> = commands
+ .iter()
+ .map(|c| -> Result<ArcComputeCommand<A>, ComputePassError> {
+ Ok(match *c {
+ ComputeCommand::SetBindGroup {
+ index,
+ num_dynamic_offsets,
+ bind_group_id,
+ } => ArcComputeCommand::SetBindGroup {
+ index,
+ num_dynamic_offsets,
+ bind_group: bind_group_guard.get_owned(bind_group_id).map_err(|_| {
+ ComputePassError {
+ scope: PassErrorScope::SetBindGroup(bind_group_id),
+ inner: ComputePassErrorInner::InvalidBindGroup(index),
+ }
+ })?,
+ },
+
+ ComputeCommand::SetPipeline(pipeline_id) => ArcComputeCommand::SetPipeline(
+ pipelines_guard
+ .get_owned(pipeline_id)
+ .map_err(|_| ComputePassError {
+ scope: PassErrorScope::SetPipelineCompute(pipeline_id),
+ inner: ComputePassErrorInner::InvalidPipeline(pipeline_id),
+ })?,
+ ),
+
+ ComputeCommand::SetPushConstant {
+ offset,
+ size_bytes,
+ values_offset,
+ } => ArcComputeCommand::SetPushConstant {
+ offset,
+ size_bytes,
+ values_offset,
+ },
+
+ ComputeCommand::Dispatch(dim) => ArcComputeCommand::Dispatch(dim),
+
+ ComputeCommand::DispatchIndirect { buffer_id, offset } => {
+ ArcComputeCommand::DispatchIndirect {
+ buffer: buffers_guard.get_owned(buffer_id).map_err(|_| {
+ ComputePassError {
+ scope: PassErrorScope::Dispatch {
+ indirect: true,
+ pipeline: None, // TODO: not used right now, but once we do the resolve during recording we can use this again.
+ },
+ inner: ComputePassErrorInner::InvalidBuffer(buffer_id),
+ }
+ })?,
+ offset,
+ }
+ }
+
+ ComputeCommand::PushDebugGroup { color, len } => {
+ ArcComputeCommand::PushDebugGroup { color, len }
+ }
+
+ ComputeCommand::PopDebugGroup => ArcComputeCommand::PopDebugGroup,
+
+ ComputeCommand::InsertDebugMarker { color, len } => {
+ ArcComputeCommand::InsertDebugMarker { color, len }
+ }
+
+ ComputeCommand::WriteTimestamp {
+ query_set_id,
+ query_index,
+ } => ArcComputeCommand::WriteTimestamp {
+ query_set: query_set_guard.get_owned(query_set_id).map_err(|_| {
+ ComputePassError {
+ scope: PassErrorScope::WriteTimestamp,
+ inner: ComputePassErrorInner::InvalidQuerySet(query_set_id),
+ }
+ })?,
+ query_index,
+ },
+
+ ComputeCommand::BeginPipelineStatisticsQuery {
+ query_set_id,
+ query_index,
+ } => ArcComputeCommand::BeginPipelineStatisticsQuery {
+ query_set: query_set_guard.get_owned(query_set_id).map_err(|_| {
+ ComputePassError {
+ scope: PassErrorScope::BeginPipelineStatisticsQuery,
+ inner: ComputePassErrorInner::InvalidQuerySet(query_set_id),
+ }
+ })?,
+ query_index,
+ },
+
+ ComputeCommand::EndPipelineStatisticsQuery => {
+ ArcComputeCommand::EndPipelineStatisticsQuery
+ }
+ })
+ })
+ .collect::<Result<Vec<_>, ComputePassError>>()?;
+ Ok(resolved_commands)
+ }
+}
+
+/// Equivalent to `ComputeCommand` but the Ids resolved into resource Arcs.
+#[derive(Clone, Debug)]
+pub enum ArcComputeCommand<A: HalApi> {
+ SetBindGroup {
+ index: u32,
+ num_dynamic_offsets: usize,
+ bind_group: Arc<BindGroup<A>>,
+ },
+
+ SetPipeline(Arc<ComputePipeline<A>>),
+
+ /// Set a range of push constants to values stored in `push_constant_data`.
+ SetPushConstant {
+ /// The byte offset within the push constant storage to write to. This
+ /// must be a multiple of four.
+ offset: u32,
+
+ /// The number of bytes to write. This must be a multiple of four.
+ size_bytes: u32,
+
+ /// Index in `push_constant_data` of the start of the data
+ /// to be written.
+ ///
+ /// Note: this is not a byte offset like `offset`. Rather, it is the
+ /// index of the first `u32` element in `push_constant_data` to read.
+ values_offset: u32,
+ },
+
+ Dispatch([u32; 3]),
+
+ DispatchIndirect {
+ buffer: Arc<Buffer<A>>,
+ offset: wgt::BufferAddress,
+ },
+
+ PushDebugGroup {
+ color: u32,
+ len: usize,
+ },
+
+ PopDebugGroup,
+
+ InsertDebugMarker {
+ color: u32,
+ len: usize,
+ },
+
+ WriteTimestamp {
+ query_set: Arc<QuerySet<A>>,
+ query_index: u32,
+ },
+
+ BeginPipelineStatisticsQuery {
+ query_set: Arc<QuerySet<A>>,
+ query_index: u32,
+ },
+
+ EndPipelineStatisticsQuery,
+}
+
+#[cfg(feature = "trace")]
+impl<A: HalApi> From<&ArcComputeCommand<A>> for ComputeCommand {
+ fn from(value: &ArcComputeCommand<A>) -> Self {
+ use crate::resource::Resource as _;
+
+ match value {
+ ArcComputeCommand::SetBindGroup {
+ index,
+ num_dynamic_offsets,
+ bind_group,
+ } => ComputeCommand::SetBindGroup {
+ index: *index,
+ num_dynamic_offsets: *num_dynamic_offsets,
+ bind_group_id: bind_group.as_info().id(),
+ },
+
+ ArcComputeCommand::SetPipeline(pipeline) => {
+ ComputeCommand::SetPipeline(pipeline.as_info().id())
+ }
+
+ ArcComputeCommand::SetPushConstant {
+ offset,
+ size_bytes,
+ values_offset,
+ } => ComputeCommand::SetPushConstant {
+ offset: *offset,
+ size_bytes: *size_bytes,
+ values_offset: *values_offset,
+ },
+
+ ArcComputeCommand::Dispatch(dim) => ComputeCommand::Dispatch(*dim),
+
+ ArcComputeCommand::DispatchIndirect { buffer, offset } => {
+ ComputeCommand::DispatchIndirect {
+ buffer_id: buffer.as_info().id(),
+ offset: *offset,
+ }
+ }
+
+ ArcComputeCommand::PushDebugGroup { color, len } => ComputeCommand::PushDebugGroup {
+ color: *color,
+ len: *len,
+ },
+
+ ArcComputeCommand::PopDebugGroup => ComputeCommand::PopDebugGroup,
+
+ ArcComputeCommand::InsertDebugMarker { color, len } => {
+ ComputeCommand::InsertDebugMarker {
+ color: *color,
+ len: *len,
+ }
+ }
+
+ ArcComputeCommand::WriteTimestamp {
+ query_set,
+ query_index,
+ } => ComputeCommand::WriteTimestamp {
+ query_set_id: query_set.as_info().id(),
+ query_index: *query_index,
+ },
+
+ ArcComputeCommand::BeginPipelineStatisticsQuery {
+ query_set,
+ query_index,
+ } => ComputeCommand::BeginPipelineStatisticsQuery {
+ query_set_id: query_set.as_info().id(),
+ query_index: *query_index,
+ },
+
+ ArcComputeCommand::EndPipelineStatisticsQuery => {
+ ComputeCommand::EndPipelineStatisticsQuery
+ }
+ }
+ }
+}
diff --git a/third_party/rust/wgpu-core/src/command/mod.rs b/third_party/rust/wgpu-core/src/command/mod.rs
index febed4fc97..d53f47bf42 100644
--- a/third_party/rust/wgpu-core/src/command/mod.rs
+++ b/third_party/rust/wgpu-core/src/command/mod.rs
@@ -1,20 +1,23 @@
+mod allocator;
mod bind;
mod bundle;
mod clear;
mod compute;
+mod compute_command;
mod draw;
mod memory_init;
mod query;
mod render;
mod transfer;
-use std::slice;
use std::sync::Arc;
pub(crate) use self::clear::clear_texture;
pub use self::{
- bundle::*, clear::ClearError, compute::*, draw::*, query::*, render::*, transfer::*,
+ bundle::*, clear::ClearError, compute::*, compute_command::ComputeCommand, draw::*, query::*,
+ render::*, transfer::*,
};
+pub(crate) use allocator::CommandAllocator;
use self::memory_init::CommandBufferTextureMemoryActions;
@@ -22,6 +25,7 @@ use crate::device::{Device, DeviceError};
use crate::error::{ErrorFormatter, PrettyError};
use crate::hub::Hub;
use crate::id::CommandBufferId;
+use crate::lock::{rank, Mutex};
use crate::snatch::SnatchGuard;
use crate::init_tracker::BufferInitTrackerAction;
@@ -30,7 +34,6 @@ use crate::track::{Tracker, UsageScope};
use crate::{api_log, global::Global, hal_api::HalApi, id, resource_log, Label};
use hal::CommandEncoder as _;
-use parking_lot::Mutex;
use thiserror::Error;
#[cfg(feature = "trace")]
@@ -38,23 +41,122 @@ use crate::device::trace::Command as TraceCommand;
const PUSH_CONSTANT_CLEAR_ARRAY: &[u32] = &[0_u32; 64];
+/// The current state of a [`CommandBuffer`].
#[derive(Debug)]
pub(crate) enum CommandEncoderStatus {
+ /// Ready to record commands. An encoder's initial state.
+ ///
+ /// Command building methods like [`command_encoder_clear_buffer`] and
+ /// [`command_encoder_run_compute_pass`] require the encoder to be in this
+ /// state.
+ ///
+ /// [`command_encoder_clear_buffer`]: Global::command_encoder_clear_buffer
+ /// [`command_encoder_run_compute_pass`]: Global::command_encoder_run_compute_pass
Recording,
+
+ /// Command recording is complete, and the buffer is ready for submission.
+ ///
+ /// [`Global::command_encoder_finish`] transitions a
+ /// `CommandBuffer` from the `Recording` state into this state.
+ ///
+ /// [`Global::queue_submit`] drops command buffers unless they are
+ /// in this state.
Finished,
+
+ /// An error occurred while recording a compute or render pass.
+ ///
+ /// When a `CommandEncoder` is left in this state, we have also
+ /// returned an error result from the function that encountered
+ /// the problem. Future attempts to use the encoder (that is,
+ /// calls to [`CommandBuffer::get_encoder`]) will also return
+ /// errors.
+ ///
+ /// Calling [`Global::command_encoder_finish`] in this state
+ /// discards the command buffer under construction.
Error,
}
+/// A raw [`CommandEncoder`][rce], and the raw [`CommandBuffer`][rcb]s built from it.
+///
+/// Each wgpu-core [`CommandBuffer`] owns an instance of this type, which is
+/// where the commands are actually stored.
+///
+/// This holds a `Vec` of raw [`CommandBuffer`][rcb]s, not just one. We are not
+/// always able to record commands in the order in which they must ultimately be
+/// submitted to the queue, but raw command buffers don't permit inserting new
+/// commands into the middle of a recorded stream. However, hal queue submission
+/// accepts a series of command buffers at once, so we can simply break the
+/// stream up into multiple buffers, and then reorder the buffers. See
+/// [`CommandEncoder::close_and_swap`] for a specific example of this.
+///
+/// Note that a [`CommandEncoderId`] actually refers to a [`CommandBuffer`].
+/// Methods that take a command encoder id actually look up the command buffer,
+/// and then use its encoder.
+///
+/// [rce]: hal::Api::CommandEncoder
+/// [rcb]: hal::Api::CommandBuffer
+/// [`CommandEncoderId`]: crate::id::CommandEncoderId
pub(crate) struct CommandEncoder<A: HalApi> {
+ /// The underlying `wgpu_hal` [`CommandEncoder`].
+ ///
+ /// Successfully executed command buffers' encoders are saved in a
+ /// [`CommandAllocator`] for recycling.
+ ///
+ /// [`CommandEncoder`]: hal::Api::CommandEncoder
+ /// [`CommandAllocator`]: crate::command::CommandAllocator
raw: A::CommandEncoder,
+
+ /// All the raw command buffers for our owning [`CommandBuffer`], in
+ /// submission order.
+ ///
+ /// These command buffers were all constructed with `raw`. The
+ /// [`wgpu_hal::CommandEncoder`] trait forbids these from outliving `raw`,
+ /// and requires that we provide all of these when we call
+ /// [`raw.reset_all()`][CE::ra], so the encoder and its buffers travel
+ /// together.
+ ///
+ /// [CE::ra]: hal::CommandEncoder::reset_all
+ /// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
list: Vec<A::CommandBuffer>,
+
+ /// True if `raw` is in the "recording" state.
+ ///
+ /// See the documentation for [`wgpu_hal::CommandEncoder`] for
+ /// details on the states `raw` can be in.
+ ///
+ /// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
is_open: bool,
+
label: Option<String>,
}
//TODO: handle errors better
impl<A: HalApi> CommandEncoder<A> {
- /// Closes the live encoder
+ /// Finish the current command buffer, if any, and place it
+ /// at the second-to-last position in our list.
+ ///
+ /// If we have opened this command encoder, finish its current
+ /// command buffer, and insert it just before the last element in
+ /// [`self.list`][l]. If this command buffer is closed, do nothing.
+ ///
+ /// On return, the underlying hal encoder is closed.
+ ///
+ /// What is this for?
+ ///
+ /// The `wgpu_hal` contract requires that each render or compute pass's
+ /// commands be preceded by calls to [`transition_buffers`] and
+ /// [`transition_textures`], to put the resources the pass operates on in
+ /// the appropriate state. Unfortunately, we don't know which transitions
+ /// are needed until we're done recording the pass itself. Rather than
+ /// iterating over the pass twice, we note the necessary transitions as we
+ /// record its commands, finish the raw command buffer for the actual pass,
+ /// record a new raw command buffer for the transitions, and jam that buffer
+ /// in just before the pass's. This is the function that jams in the
+ /// transitions' command buffer.
+ ///
+ /// [l]: CommandEncoder::list
+ /// [`transition_buffers`]: hal::CommandEncoder::transition_buffers
+ /// [`transition_textures`]: hal::CommandEncoder::transition_textures
fn close_and_swap(&mut self) -> Result<(), DeviceError> {
if self.is_open {
self.is_open = false;
@@ -65,6 +167,16 @@ impl<A: HalApi> CommandEncoder<A> {
Ok(())
}
+ /// Finish the current command buffer, if any, and add it to the
+ /// end of [`self.list`][l].
+ ///
+ /// If we have opened this command encoder, finish its current
+ /// command buffer, and push it onto the end of [`self.list`][l].
+ /// If this command buffer is closed, do nothing.
+ ///
+ /// On return, the underlying hal encoder is closed.
+ ///
+ /// [l]: CommandEncoder::list
fn close(&mut self) -> Result<(), DeviceError> {
if self.is_open {
self.is_open = false;
@@ -75,6 +187,9 @@ impl<A: HalApi> CommandEncoder<A> {
Ok(())
}
+ /// Discard the command buffer under construction, if any.
+ ///
+ /// The underlying hal encoder is closed, if it was recording.
pub(crate) fn discard(&mut self) {
if self.is_open {
self.is_open = false;
@@ -82,7 +197,10 @@ impl<A: HalApi> CommandEncoder<A> {
}
}
- fn open(&mut self) -> Result<&mut A::CommandEncoder, DeviceError> {
+ /// Begin recording a new command buffer, if we haven't already.
+ ///
+ /// The underlying hal encoder is put in the "recording" state.
+ pub(crate) fn open(&mut self) -> Result<&mut A::CommandEncoder, DeviceError> {
if !self.is_open {
self.is_open = true;
let label = self.label.as_deref();
@@ -92,6 +210,10 @@ impl<A: HalApi> CommandEncoder<A> {
Ok(&mut self.raw)
}
+ /// Begin recording a new command buffer for a render pass, with
+ /// its own label.
+ ///
+ /// The underlying hal encoder is put in the "recording" state.
fn open_pass(&mut self, label: Option<&str>) -> Result<(), DeviceError> {
self.is_open = true;
unsafe { self.raw.begin_encoding(label)? };
@@ -100,7 +222,7 @@ impl<A: HalApi> CommandEncoder<A> {
}
}
-pub struct BakedCommands<A: HalApi> {
+pub(crate) struct BakedCommands<A: HalApi> {
pub(crate) encoder: A::CommandEncoder,
pub(crate) list: Vec<A::CommandBuffer>,
pub(crate) trackers: Tracker<A>,
@@ -111,12 +233,29 @@ pub struct BakedCommands<A: HalApi> {
pub(crate) struct DestroyedBufferError(pub id::BufferId);
pub(crate) struct DestroyedTextureError(pub id::TextureId);
+/// The mutable state of a [`CommandBuffer`].
pub struct CommandBufferMutable<A: HalApi> {
+ /// The [`wgpu_hal::Api::CommandBuffer`]s we've built so far, and the encoder
+ /// they belong to.
+ ///
+ /// [`wgpu_hal::Api::CommandBuffer`]: hal::Api::CommandBuffer
pub(crate) encoder: CommandEncoder<A>,
+
+ /// The current state of this command buffer's encoder.
status: CommandEncoderStatus,
+
+ /// All the resources that the commands recorded so far have referred to.
pub(crate) trackers: Tracker<A>,
+
+ /// The regions of buffers and textures these commands will read and write.
+ ///
+ /// This is used to determine which portions of which
+ /// buffers/textures we actually need to initialize. If we're
+ /// definitely going to write to something before we read from it,
+ /// we don't need to clear its contents.
buffer_memory_init_actions: Vec<BufferInitTrackerAction<A>>,
texture_memory_actions: CommandBufferTextureMemoryActions<A>,
+
pub(crate) pending_query_resets: QueryResetMap<A>,
#[cfg(feature = "trace")]
pub(crate) commands: Option<Vec<TraceCommand>>,
@@ -133,11 +272,36 @@ impl<A: HalApi> CommandBufferMutable<A> {
}
}
+/// A buffer of commands to be submitted to the GPU for execution.
+///
+/// Whereas the WebGPU API uses two separate types for command buffers and
+/// encoders, this type is a fusion of the two:
+///
+/// - During command recording, this holds a [`CommandEncoder`] accepting this
+/// buffer's commands. In this state, the [`CommandBuffer`] type behaves like
+/// a WebGPU `GPUCommandEncoder`.
+///
+/// - Once command recording is finished by calling
+/// [`Global::command_encoder_finish`], no further recording is allowed. The
+/// internal [`CommandEncoder`] is retained solely as a storage pool for the
+/// raw command buffers. In this state, the value behaves like a WebGPU
+/// `GPUCommandBuffer`.
+///
+/// - Once a command buffer is submitted to the queue, it is removed from the id
+/// registry, and its contents are taken to construct a [`BakedCommands`],
+/// whose contents eventually become the property of the submission queue.
pub struct CommandBuffer<A: HalApi> {
pub(crate) device: Arc<Device<A>>,
limits: wgt::Limits,
support_clear_texture: bool,
pub(crate) info: ResourceInfo<CommandBuffer<A>>,
+
+ /// The mutable state of this command buffer.
+ ///
+ /// This `Option` is populated when the command buffer is first created.
+ /// When this is submitted, dropped, or destroyed, its contents are
+ /// extracted into a [`BakedCommands`] by
+ /// [`CommandBuffer::extract_baked_commands`].
pub(crate) data: Mutex<Option<CommandBufferMutable<A>>>,
}
@@ -176,25 +340,28 @@ impl<A: HalApi> CommandBuffer<A> {
.as_str(),
None,
),
- data: Mutex::new(Some(CommandBufferMutable {
- encoder: CommandEncoder {
- raw: encoder,
- is_open: false,
- list: Vec::new(),
- label,
- },
- status: CommandEncoderStatus::Recording,
- trackers: Tracker::new(),
- buffer_memory_init_actions: Default::default(),
- texture_memory_actions: Default::default(),
- pending_query_resets: QueryResetMap::new(),
- #[cfg(feature = "trace")]
- commands: if enable_tracing {
- Some(Vec::new())
- } else {
- None
- },
- })),
+ data: Mutex::new(
+ rank::COMMAND_BUFFER_DATA,
+ Some(CommandBufferMutable {
+ encoder: CommandEncoder {
+ raw: encoder,
+ is_open: false,
+ list: Vec::new(),
+ label,
+ },
+ status: CommandEncoderStatus::Recording,
+ trackers: Tracker::new(),
+ buffer_memory_init_actions: Default::default(),
+ texture_memory_actions: Default::default(),
+ pending_query_resets: QueryResetMap::new(),
+ #[cfg(feature = "trace")]
+ commands: if enable_tracing {
+ Some(Vec::new())
+ } else {
+ None
+ },
+ }),
+ ),
}
}
@@ -248,12 +415,18 @@ impl<A: HalApi> CommandBuffer<A> {
}
impl<A: HalApi> CommandBuffer<A> {
+ /// Return the [`CommandBuffer`] for `id`, for recording new commands.
+ ///
+ /// In `wgpu_core`, the [`CommandBuffer`] type serves both as encoder and
+ /// buffer, which is why this function takes an [`id::CommandEncoderId`] but
+ /// returns a [`CommandBuffer`]. The returned command buffer must be in the
+ /// "recording" state. Otherwise, an error is returned.
fn get_encoder(
hub: &Hub<A>,
id: id::CommandEncoderId,
) -> Result<Arc<Self>, CommandEncoderError> {
let storage = hub.command_buffers.read();
- match storage.get(id.transmute()) {
+ match storage.get(id.into_command_buffer_id()) {
Ok(cmd_buf) => match cmd_buf.data.lock().as_ref().unwrap().status {
CommandEncoderStatus::Recording => Ok(cmd_buf.clone()),
CommandEncoderStatus::Finished => Err(CommandEncoderError::NotRecording),
@@ -286,11 +459,9 @@ impl<A: HalApi> CommandBuffer<A> {
}
pub(crate) fn from_arc_into_baked(self: Arc<Self>) -> BakedCommands<A> {
- if let Some(mut command_buffer) = Arc::into_inner(self) {
- command_buffer.extract_baked_commands()
- } else {
- panic!("CommandBuffer cannot be destroyed because is still in use");
- }
+ let mut command_buffer = Arc::into_inner(self)
+ .expect("CommandBuffer cannot be destroyed because is still in use");
+ command_buffer.extract_baked_commands()
}
}
@@ -418,7 +589,7 @@ impl Global {
let hub = A::hub(self);
- let error = match hub.command_buffers.get(encoder_id.transmute()) {
+ let error = match hub.command_buffers.get(encoder_id.into_command_buffer_id()) {
Ok(cmd_buf) => {
let mut cmd_buf_data = cmd_buf.data.lock();
let cmd_buf_data = cmd_buf_data.as_mut().unwrap();
@@ -444,7 +615,7 @@ impl Global {
Err(_) => Some(CommandEncoderError::Invalid),
};
- (encoder_id.transmute(), error)
+ (encoder_id.into_command_buffer_id(), error)
}
pub fn command_encoder_push_debug_group<A: HalApi>(
@@ -599,16 +770,15 @@ impl BindGroupStateChange {
}
}
- unsafe fn set_and_check_redundant(
+ fn set_and_check_redundant(
&mut self,
bind_group_id: id::BindGroupId,
index: u32,
dynamic_offsets: &mut Vec<u32>,
- offsets: *const wgt::DynamicOffset,
- offset_length: usize,
+ offsets: &[wgt::DynamicOffset],
) -> bool {
// For now never deduplicate bind groups with dynamic offsets.
- if offset_length == 0 {
+ if offsets.is_empty() {
// If this get returns None, that means we're well over the limit,
// so let the call through to get a proper error
if let Some(current_bind_group) = self.last_states.get_mut(index as usize) {
@@ -624,8 +794,7 @@ impl BindGroupStateChange {
if let Some(current_bind_group) = self.last_states.get_mut(index as usize) {
current_bind_group.reset();
}
- dynamic_offsets
- .extend_from_slice(unsafe { slice::from_raw_parts(offsets, offset_length) });
+ dynamic_offsets.extend_from_slice(offsets);
}
false
}
@@ -700,7 +869,7 @@ impl PrettyError for PassErrorScope {
// This error is not in the error chain, only notes are needed
match *self {
Self::Pass(id) => {
- fmt.command_buffer_label(&id.transmute());
+ fmt.command_buffer_label(&id.into_command_buffer_id());
}
Self::SetBindGroup(id) => {
fmt.bind_group_label(&id);
diff --git a/third_party/rust/wgpu-core/src/command/query.rs b/third_party/rust/wgpu-core/src/command/query.rs
index 89cba6fbf3..fd3360cc00 100644
--- a/third_party/rust/wgpu-core/src/command/query.rs
+++ b/third_party/rust/wgpu-core/src/command/query.rs
@@ -9,7 +9,7 @@ use crate::{
hal_api::HalApi,
id::{self, Id},
init_tracker::MemoryInitKind,
- resource::QuerySet,
+ resource::{QuerySet, Resource},
storage::Storage,
Epoch, FastHashMap, Index,
};
@@ -429,11 +429,20 @@ impl Global {
.add_single(&*query_set_guard, query_set_id)
.ok_or(QueryError::InvalidQuerySet(query_set_id))?;
+ if query_set.device.as_info().id() != cmd_buf.device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
let (dst_buffer, dst_pending) = {
let buffer_guard = hub.buffers.read();
let dst_buffer = buffer_guard
.get(destination)
.map_err(|_| QueryError::InvalidBuffer(destination))?;
+
+ if dst_buffer.device.as_info().id() != cmd_buf.device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
tracker
.buffers
.set_single(dst_buffer, hal::BufferUses::COPY_DST)
diff --git a/third_party/rust/wgpu-core/src/command/render.rs b/third_party/rust/wgpu-core/src/command/render.rs
index 7e859e3cc8..87dc9aac16 100644
--- a/third_party/rust/wgpu-core/src/command/render.rs
+++ b/third_party/rust/wgpu-core/src/command/render.rs
@@ -1343,7 +1343,8 @@ impl Global {
let hub = A::hub(self);
- let cmd_buf = CommandBuffer::get_encoder(hub, encoder_id).map_pass_err(pass_scope)?;
+ let cmd_buf: Arc<CommandBuffer<A>> =
+ CommandBuffer::get_encoder(hub, encoder_id).map_pass_err(pass_scope)?;
let device = &cmd_buf.device;
let snatch_guard = device.snatchable_lock.read();
@@ -2409,7 +2410,10 @@ impl Global {
(trackers, pending_discard_init_fixups)
};
- let cmd_buf = hub.command_buffers.get(encoder_id.transmute()).unwrap();
+ let cmd_buf = hub
+ .command_buffers
+ .get(encoder_id.into_command_buffer_id())
+ .unwrap();
let mut cmd_buf_data = cmd_buf.data.lock();
let cmd_buf_data = cmd_buf_data.as_mut().unwrap();
@@ -2455,36 +2459,27 @@ impl Global {
}
}
-pub mod render_ffi {
+pub mod render_commands {
use super::{
super::{Rect, RenderCommand},
RenderPass,
};
- use crate::{id, RawString};
- use std::{convert::TryInto, ffi, num::NonZeroU32, slice};
+ use crate::id;
+ use std::{convert::TryInto, num::NonZeroU32};
use wgt::{BufferAddress, BufferSize, Color, DynamicOffset, IndexFormat};
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given pointer is
- /// valid for `offset_length` elements.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_render_pass_set_bind_group(
+ pub fn wgpu_render_pass_set_bind_group(
pass: &mut RenderPass,
index: u32,
bind_group_id: id::BindGroupId,
- offsets: *const DynamicOffset,
- offset_length: usize,
+ offsets: &[DynamicOffset],
) {
- let redundant = unsafe {
- pass.current_bind_groups.set_and_check_redundant(
- bind_group_id,
- index,
- &mut pass.base.dynamic_offsets,
- offsets,
- offset_length,
- )
- };
+ let redundant = pass.current_bind_groups.set_and_check_redundant(
+ bind_group_id,
+ index,
+ &mut pass.base.dynamic_offsets,
+ offsets,
+ );
if redundant {
return;
@@ -2492,16 +2487,12 @@ pub mod render_ffi {
pass.base.commands.push(RenderCommand::SetBindGroup {
index,
- num_dynamic_offsets: offset_length,
+ num_dynamic_offsets: offsets.len(),
bind_group_id,
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_set_pipeline(
- pass: &mut RenderPass,
- pipeline_id: id::RenderPipelineId,
- ) {
+ pub fn wgpu_render_pass_set_pipeline(pass: &mut RenderPass, pipeline_id: id::RenderPipelineId) {
if pass.current_pipeline.set_and_check_redundant(pipeline_id) {
return;
}
@@ -2511,8 +2502,7 @@ pub mod render_ffi {
.push(RenderCommand::SetPipeline(pipeline_id));
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_set_vertex_buffer(
+ pub fn wgpu_render_pass_set_vertex_buffer(
pass: &mut RenderPass,
slot: u32,
buffer_id: id::BufferId,
@@ -2527,8 +2517,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_set_index_buffer(
+ pub fn wgpu_render_pass_set_index_buffer(
pass: &mut RenderPass,
buffer: id::BufferId,
index_format: IndexFormat,
@@ -2538,22 +2527,19 @@ pub mod render_ffi {
pass.set_index_buffer(buffer, index_format, offset, size);
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_set_blend_constant(pass: &mut RenderPass, color: &Color) {
+ pub fn wgpu_render_pass_set_blend_constant(pass: &mut RenderPass, color: &Color) {
pass.base
.commands
.push(RenderCommand::SetBlendConstant(*color));
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_set_stencil_reference(pass: &mut RenderPass, value: u32) {
+ pub fn wgpu_render_pass_set_stencil_reference(pass: &mut RenderPass, value: u32) {
pass.base
.commands
.push(RenderCommand::SetStencilReference(value));
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_set_viewport(
+ pub fn wgpu_render_pass_set_viewport(
pass: &mut RenderPass,
x: f32,
y: f32,
@@ -2569,8 +2555,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_set_scissor_rect(
+ pub fn wgpu_render_pass_set_scissor_rect(
pass: &mut RenderPass,
x: u32,
y: u32,
@@ -2582,17 +2567,11 @@ pub mod render_ffi {
.push(RenderCommand::SetScissor(Rect { x, y, w, h }));
}
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given pointer is
- /// valid for `size_bytes` bytes.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_render_pass_set_push_constants(
+ pub fn wgpu_render_pass_set_push_constants(
pass: &mut RenderPass,
stages: wgt::ShaderStages,
offset: u32,
- size_bytes: u32,
- data: *const u8,
+ data: &[u8],
) {
assert_eq!(
offset & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
@@ -2600,31 +2579,28 @@ pub mod render_ffi {
"Push constant offset must be aligned to 4 bytes."
);
assert_eq!(
- size_bytes & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
+ data.len() as u32 & (wgt::PUSH_CONSTANT_ALIGNMENT - 1),
0,
"Push constant size must be aligned to 4 bytes."
);
- let data_slice = unsafe { slice::from_raw_parts(data, size_bytes as usize) };
let value_offset = pass.base.push_constant_data.len().try_into().expect(
"Ran out of push constant space. Don't set 4gb of push constants per RenderPass.",
);
pass.base.push_constant_data.extend(
- data_slice
- .chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
+ data.chunks_exact(wgt::PUSH_CONSTANT_ALIGNMENT as usize)
.map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])),
);
pass.base.commands.push(RenderCommand::SetPushConstant {
stages,
offset,
- size_bytes,
+ size_bytes: data.len() as u32,
values_offset: Some(value_offset),
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_draw(
+ pub fn wgpu_render_pass_draw(
pass: &mut RenderPass,
vertex_count: u32,
instance_count: u32,
@@ -2639,8 +2615,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_draw_indexed(
+ pub fn wgpu_render_pass_draw_indexed(
pass: &mut RenderPass,
index_count: u32,
instance_count: u32,
@@ -2657,8 +2632,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_draw_indirect(
+ pub fn wgpu_render_pass_draw_indirect(
pass: &mut RenderPass,
buffer_id: id::BufferId,
offset: BufferAddress,
@@ -2671,8 +2645,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_draw_indexed_indirect(
+ pub fn wgpu_render_pass_draw_indexed_indirect(
pass: &mut RenderPass,
buffer_id: id::BufferId,
offset: BufferAddress,
@@ -2685,8 +2658,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_multi_draw_indirect(
+ pub fn wgpu_render_pass_multi_draw_indirect(
pass: &mut RenderPass,
buffer_id: id::BufferId,
offset: BufferAddress,
@@ -2700,8 +2672,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_multi_draw_indexed_indirect(
+ pub fn wgpu_render_pass_multi_draw_indexed_indirect(
pass: &mut RenderPass,
buffer_id: id::BufferId,
offset: BufferAddress,
@@ -2715,8 +2686,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_multi_draw_indirect_count(
+ pub fn wgpu_render_pass_multi_draw_indirect_count(
pass: &mut RenderPass,
buffer_id: id::BufferId,
offset: BufferAddress,
@@ -2736,8 +2706,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_multi_draw_indexed_indirect_count(
+ pub fn wgpu_render_pass_multi_draw_indexed_indirect_count(
pass: &mut RenderPass,
buffer_id: id::BufferId,
offset: BufferAddress,
@@ -2757,17 +2726,8 @@ pub mod render_ffi {
});
}
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given `label`
- /// is a valid null-terminated string.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_render_pass_push_debug_group(
- pass: &mut RenderPass,
- label: RawString,
- color: u32,
- ) {
- let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pub fn wgpu_render_pass_push_debug_group(pass: &mut RenderPass, label: &str, color: u32) {
+ let bytes = label.as_bytes();
pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(RenderCommand::PushDebugGroup {
@@ -2776,22 +2736,12 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_pop_debug_group(pass: &mut RenderPass) {
+ pub fn wgpu_render_pass_pop_debug_group(pass: &mut RenderPass) {
pass.base.commands.push(RenderCommand::PopDebugGroup);
}
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given `label`
- /// is a valid null-terminated string.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_render_pass_insert_debug_marker(
- pass: &mut RenderPass,
- label: RawString,
- color: u32,
- ) {
- let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pub fn wgpu_render_pass_insert_debug_marker(pass: &mut RenderPass, label: &str, color: u32) {
+ let bytes = label.as_bytes();
pass.base.string_data.extend_from_slice(bytes);
pass.base.commands.push(RenderCommand::InsertDebugMarker {
@@ -2800,8 +2750,7 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_write_timestamp(
+ pub fn wgpu_render_pass_write_timestamp(
pass: &mut RenderPass,
query_set_id: id::QuerySetId,
query_index: u32,
@@ -2812,23 +2761,17 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_begin_occlusion_query(
- pass: &mut RenderPass,
- query_index: u32,
- ) {
+ pub fn wgpu_render_pass_begin_occlusion_query(pass: &mut RenderPass, query_index: u32) {
pass.base
.commands
.push(RenderCommand::BeginOcclusionQuery { query_index });
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_end_occlusion_query(pass: &mut RenderPass) {
+ pub fn wgpu_render_pass_end_occlusion_query(pass: &mut RenderPass) {
pass.base.commands.push(RenderCommand::EndOcclusionQuery);
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_begin_pipeline_statistics_query(
+ pub fn wgpu_render_pass_begin_pipeline_statistics_query(
pass: &mut RenderPass,
query_set_id: id::QuerySetId,
query_index: u32,
@@ -2841,26 +2784,17 @@ pub mod render_ffi {
});
}
- #[no_mangle]
- pub extern "C" fn wgpu_render_pass_end_pipeline_statistics_query(pass: &mut RenderPass) {
+ pub fn wgpu_render_pass_end_pipeline_statistics_query(pass: &mut RenderPass) {
pass.base
.commands
.push(RenderCommand::EndPipelineStatisticsQuery);
}
- /// # Safety
- ///
- /// This function is unsafe as there is no guarantee that the given pointer is
- /// valid for `render_bundle_ids_length` elements.
- #[no_mangle]
- pub unsafe extern "C" fn wgpu_render_pass_execute_bundles(
+ pub fn wgpu_render_pass_execute_bundles(
pass: &mut RenderPass,
- render_bundle_ids: *const id::RenderBundleId,
- render_bundle_ids_length: usize,
+ render_bundle_ids: &[id::RenderBundleId],
) {
- for &bundle_id in
- unsafe { slice::from_raw_parts(render_bundle_ids, render_bundle_ids_length) }
- {
+ for &bundle_id in render_bundle_ids {
pass.base
.commands
.push(RenderCommand::ExecuteBundle(bundle_id));
diff --git a/third_party/rust/wgpu-core/src/command/transfer.rs b/third_party/rust/wgpu-core/src/command/transfer.rs
index 8e98a4c9b9..84bc88e723 100644
--- a/third_party/rust/wgpu-core/src/command/transfer.rs
+++ b/third_party/rust/wgpu-core/src/command/transfer.rs
@@ -607,6 +607,11 @@ impl Global {
let src_buffer = buffer_guard
.get(source)
.map_err(|_| TransferError::InvalidBuffer(source))?;
+
+ if src_buffer.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
cmd_buf_data
.trackers
.buffers
@@ -628,6 +633,11 @@ impl Global {
let dst_buffer = buffer_guard
.get(destination)
.map_err(|_| TransferError::InvalidBuffer(destination))?;
+
+ if dst_buffer.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
cmd_buf_data
.trackers
.buffers
@@ -777,6 +787,10 @@ impl Global {
.get(destination.texture)
.map_err(|_| TransferError::InvalidTexture(destination.texture))?;
+ if dst_texture.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
let (hal_copy_size, array_layer_count) = validate_texture_copy_range(
destination,
&dst_texture.desc,
@@ -807,6 +821,11 @@ impl Global {
let src_buffer = buffer_guard
.get(source.buffer)
.map_err(|_| TransferError::InvalidBuffer(source.buffer))?;
+
+ if src_buffer.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
tracker
.buffers
.set_single(src_buffer, hal::BufferUses::COPY_SRC)
@@ -938,6 +957,10 @@ impl Global {
.get(source.texture)
.map_err(|_| TransferError::InvalidTexture(source.texture))?;
+ if src_texture.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
let (hal_copy_size, array_layer_count) =
validate_texture_copy_range(source, &src_texture.desc, CopySide::Source, copy_size)?;
@@ -989,6 +1012,11 @@ impl Global {
let dst_buffer = buffer_guard
.get(destination.buffer)
.map_err(|_| TransferError::InvalidBuffer(destination.buffer))?;
+
+ if dst_buffer.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
tracker
.buffers
.set_single(dst_buffer, hal::BufferUses::COPY_DST)
@@ -1117,6 +1145,13 @@ impl Global {
.get(destination.texture)
.map_err(|_| TransferError::InvalidTexture(source.texture))?;
+ if src_texture.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+ if dst_texture.device.as_info().id() != device.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
// src and dst texture format must be copy-compatible
// https://gpuweb.github.io/gpuweb/#copy-compatible
if src_texture.desc.format.remove_srgb_suffix()
diff --git a/third_party/rust/wgpu-core/src/device/any_device.rs b/third_party/rust/wgpu-core/src/device/any_device.rs
index 693155a753..9e459c1a94 100644
--- a/third_party/rust/wgpu-core/src/device/any_device.rs
+++ b/third_party/rust/wgpu-core/src/device/any_device.rs
@@ -34,7 +34,7 @@ impl AnyDevice {
unsafe fn drop_glue<A: HalApi>(ptr: *mut ()) {
// Drop the arc this instance is holding.
unsafe {
- _ = Arc::from_raw(ptr.cast::<A::Surface>());
+ _ = Arc::from_raw(ptr.cast::<A::Device>());
}
}
diff --git a/third_party/rust/wgpu-core/src/device/bgl.rs b/third_party/rust/wgpu-core/src/device/bgl.rs
index d606f049a3..911ac8a435 100644
--- a/third_party/rust/wgpu-core/src/device/bgl.rs
+++ b/third_party/rust/wgpu-core/src/device/bgl.rs
@@ -58,7 +58,7 @@ impl EntryMap {
assert!(self.sorted);
}
- /// Create a new [`BindGroupLayoutEntryMap`] from a slice of [`wgt::BindGroupLayoutEntry`]s.
+ /// Create a new [`EntryMap`] from a slice of [`wgt::BindGroupLayoutEntry`]s.
///
/// Errors if there are duplicate bindings or if any binding index is greater than
/// the device's limits.
diff --git a/third_party/rust/wgpu-core/src/device/global.rs b/third_party/rust/wgpu-core/src/device/global.rs
index 0c97e1b504..be524840b8 100644
--- a/third_party/rust/wgpu-core/src/device/global.rs
+++ b/third_party/rust/wgpu-core/src/device/global.rs
@@ -11,6 +11,7 @@ use crate::{
id::{self, AdapterId, DeviceId, QueueId, SurfaceId},
init_tracker::TextureInitTracker,
instance::{self, Adapter, Surface},
+ lock::{rank, RwLock},
pipeline, present,
resource::{self, BufferAccessResult},
resource::{BufferAccessError, BufferMapOperation, CreateBufferError, Resource},
@@ -20,7 +21,6 @@ use crate::{
use arrayvec::ArrayVec;
use hal::Device as _;
-use parking_lot::RwLock;
use wgt::{BufferAddress, TextureFormat};
@@ -257,7 +257,7 @@ impl Global {
hal::BufferUses::COPY_DST
};
- let (id, resource) = fid.assign(buffer);
+ let (id, resource) = fid.assign(Arc::new(buffer));
api_log!("Device::create_buffer({desc:?}) -> {id:?}");
device
@@ -572,7 +572,7 @@ impl Global {
Err(error) => break error,
};
- let (id, resource) = fid.assign(texture);
+ let (id, resource) = fid.assign(Arc::new(texture));
api_log!("Device::create_texture({desc:?}) -> {id:?}");
device
@@ -643,10 +643,12 @@ impl Global {
texture.hal_usage |= hal::TextureUses::COPY_DST;
}
- texture.initialization_status =
- RwLock::new(TextureInitTracker::new(desc.mip_level_count, 0));
+ texture.initialization_status = RwLock::new(
+ rank::TEXTURE_INITIALIZATION_STATUS,
+ TextureInitTracker::new(desc.mip_level_count, 0),
+ );
- let (id, resource) = fid.assign(texture);
+ let (id, resource) = fid.assign(Arc::new(texture));
api_log!("Device::create_texture({desc:?}) -> {id:?}");
device
@@ -699,7 +701,7 @@ impl Global {
let buffer = device.create_buffer_from_hal(hal_buffer, desc);
- let (id, buffer) = fid.assign(buffer);
+ let (id, buffer) = fid.assign(Arc::new(buffer));
api_log!("Device::create_buffer -> {id:?}");
device
@@ -818,7 +820,7 @@ impl Global {
Err(e) => break e,
};
- let (id, resource) = fid.assign(view);
+ let (id, resource) = fid.assign(Arc::new(view));
{
let mut views = texture.views.lock();
@@ -900,7 +902,7 @@ impl Global {
Err(e) => break e,
};
- let (id, resource) = fid.assign(sampler);
+ let (id, resource) = fid.assign(Arc::new(sampler));
api_log!("Device::create_sampler -> {id:?}");
device.trackers.lock().samplers.insert_single(resource);
@@ -982,7 +984,7 @@ impl Global {
let bgl =
device.create_bind_group_layout(&desc.label, entry_map, bgl::Origin::Pool)?;
- let (id_inner, arc) = fid.take().unwrap().assign(bgl);
+ let (id_inner, arc) = fid.take().unwrap().assign(Arc::new(bgl));
id = Some(id_inner);
Ok(arc)
@@ -1063,7 +1065,7 @@ impl Global {
Err(e) => break e,
};
- let (id, _) = fid.assign(layout);
+ let (id, _) = fid.assign(Arc::new(layout));
api_log!("Device::create_pipeline_layout -> {id:?}");
return (id, None);
};
@@ -1130,7 +1132,7 @@ impl Global {
Err(e) => break e,
};
- let (id, resource) = fid.assign(bind_group);
+ let (id, resource) = fid.assign(Arc::new(bind_group));
let weak_ref = Arc::downgrade(&resource);
for range in &resource.used_texture_ranges {
@@ -1170,6 +1172,20 @@ impl Global {
}
}
+ /// Create a shader module with the given `source`.
+ ///
+ /// <div class="warning">
+ // NOTE: Keep this in sync with `naga::front::wgsl::parse_str`!
+ // NOTE: Keep this in sync with `wgpu::Device::create_shader_module`!
+ ///
+ /// This function may consume a lot of stack space. Compiler-enforced limits for parsing
+ /// recursion exist; if shader compilation runs into them, it will return an error gracefully.
+ /// However, on some build profiles and platforms, the default stack size for a thread may be
+ /// exceeded before this limit is reached during parsing. Callers should ensure that there is
+ /// enough stack space for this, particularly if calls to this method are exposed to user
+ /// input.
+ ///
+ /// </div>
pub fn device_create_shader_module<A: HalApi>(
&self,
device_id: DeviceId,
@@ -1231,7 +1247,7 @@ impl Global {
Err(e) => break e,
};
- let (id, _) = fid.assign(shader);
+ let (id, _) = fid.assign(Arc::new(shader));
api_log!("Device::create_shader_module -> {id:?}");
return (id, None);
};
@@ -1288,7 +1304,7 @@ impl Global {
Ok(shader) => shader,
Err(e) => break e,
};
- let (id, _) = fid.assign(shader);
+ let (id, _) = fid.assign(Arc::new(shader));
api_log!("Device::create_shader_module_spirv -> {id:?}");
return (id, None);
};
@@ -1320,7 +1336,9 @@ impl Global {
profiling::scope!("Device::create_command_encoder");
let hub = A::hub(self);
- let fid = hub.command_buffers.prepare(id_in.map(|id| id.transmute()));
+ let fid = hub
+ .command_buffers
+ .prepare(id_in.map(|id| id.into_command_buffer_id()));
let error = loop {
let device = match hub.devices.get(device_id) {
@@ -1335,9 +1353,6 @@ impl Global {
};
let encoder = match device
.command_allocator
- .lock()
- .as_mut()
- .unwrap()
.acquire_encoder(device.raw(), queue.raw.as_ref().unwrap())
{
Ok(raw) => raw,
@@ -1353,13 +1368,13 @@ impl Global {
.map(|s| s.to_string()),
);
- let (id, _) = fid.assign(command_buffer);
+ let (id, _) = fid.assign(Arc::new(command_buffer));
api_log!("Device::create_command_encoder -> {id:?}");
- return (id.transmute(), None);
+ return (id.into_command_encoder_id(), None);
};
let id = fid.assign_error(desc.label.borrow_or_default());
- (id.transmute(), Some(error))
+ (id.into_command_encoder_id(), Some(error))
}
pub fn command_buffer_label<A: HalApi>(&self, id: id::CommandBufferId) -> String {
@@ -1374,7 +1389,7 @@ impl Global {
if let Some(cmd_buf) = hub
.command_buffers
- .unregister(command_encoder_id.transmute())
+ .unregister(command_encoder_id.into_command_buffer_id())
{
cmd_buf.data.lock().as_mut().unwrap().encoder.discard();
cmd_buf
@@ -1386,7 +1401,7 @@ impl Global {
pub fn command_buffer_drop<A: HalApi>(&self, command_buffer_id: id::CommandBufferId) {
profiling::scope!("CommandBuffer::drop");
api_log!("CommandBuffer::drop {command_buffer_id:?}");
- self.command_encoder_drop::<A>(command_buffer_id.transmute())
+ self.command_encoder_drop::<A>(command_buffer_id.into_command_encoder_id())
}
pub fn device_create_render_bundle_encoder(
@@ -1446,7 +1461,7 @@ impl Global {
Err(e) => break e,
};
- let (id, resource) = fid.assign(render_bundle);
+ let (id, resource) = fid.assign(Arc::new(render_bundle));
api_log!("RenderBundleEncoder::finish -> {id:?}");
device.trackers.lock().bundles.insert_single(resource);
return (id, None);
@@ -1509,7 +1524,7 @@ impl Global {
Err(err) => break err,
};
- let (id, resource) = fid.assign(query_set);
+ let (id, resource) = fid.assign(Arc::new(query_set));
api_log!("Device::create_query_set -> {id:?}");
device.trackers.lock().query_sets.insert_single(resource);
@@ -1587,7 +1602,7 @@ impl Global {
Err(e) => break e,
};
- let (id, resource) = fid.assign(pipeline);
+ let (id, resource) = fid.assign(Arc::new(pipeline));
api_log!("Device::create_render_pipeline -> {id:?}");
device
@@ -1720,7 +1735,7 @@ impl Global {
Err(e) => break e,
};
- let (id, resource) = fid.assign(pipeline);
+ let (id, resource) = fid.assign(Arc::new(pipeline));
api_log!("Device::create_compute_pipeline -> {id:?}");
device
@@ -1956,7 +1971,7 @@ impl Global {
};
let caps = unsafe {
- let suf = A::get_surface(surface);
+ let suf = A::surface_as_hal(surface);
let adapter = &device.adapter;
match adapter.raw.adapter.surface_capabilities(suf.unwrap()) {
Some(caps) => caps,
@@ -2018,7 +2033,6 @@ impl Global {
// Wait for all work to finish before configuring the surface.
let snatch_guard = device.snatchable_lock.read();
let fence = device.fence.read();
- let fence = fence.as_ref().unwrap();
match device.maintain(fence, wgt::Maintain::Wait, snatch_guard) {
Ok((closures, _)) => {
user_callbacks = closures;
@@ -2042,7 +2056,7 @@ impl Global {
// https://github.com/gfx-rs/wgpu/issues/4105
match unsafe {
- A::get_surface(surface)
+ A::surface_as_hal(surface)
.unwrap()
.configure(device.raw(), &hal_config)
} {
@@ -2107,7 +2121,7 @@ impl Global {
.map_err(|_| DeviceError::Invalid)?;
if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain {
- if submission_index.queue_id != device_id.transmute() {
+ if submission_index.queue_id != device_id.into_queue_id() {
return Err(WaitIdleError::WrongSubmissionIndex(
submission_index.queue_id,
device_id,
@@ -2131,7 +2145,6 @@ impl Global {
) -> Result<DevicePoll, WaitIdleError> {
let snatch_guard = device.snatchable_lock.read();
let fence = device.fence.read();
- let fence = fence.as_ref().unwrap();
let (closures, queue_empty) = device.maintain(fence, maintain, snatch_guard)?;
// Some deferred destroys are scheduled in maintain so run this right after
diff --git a/third_party/rust/wgpu-core/src/device/life.rs b/third_party/rust/wgpu-core/src/device/life.rs
index af345015df..0df580e6e6 100644
--- a/third_party/rust/wgpu-core/src/device/life.rs
+++ b/third_party/rust/wgpu-core/src/device/life.rs
@@ -7,6 +7,7 @@ use crate::{
},
hal_api::HalApi,
id,
+ lock::Mutex,
pipeline::{ComputePipeline, RenderPipeline},
resource::{
self, Buffer, DestroyedBuffer, DestroyedTexture, QuerySet, Resource, Sampler,
@@ -18,12 +19,10 @@ use crate::{
};
use smallvec::SmallVec;
-use parking_lot::Mutex;
use std::sync::Arc;
use thiserror::Error;
/// A struct that keeps lists of resources that are no longer needed by the user.
-#[derive(Default)]
pub(crate) struct ResourceMaps<A: HalApi> {
pub buffers: FastHashMap<TrackerIndex, Arc<Buffer<A>>>,
pub staging_buffers: FastHashMap<TrackerIndex, Arc<StagingBuffer<A>>>,
@@ -94,7 +93,7 @@ impl<A: HalApi> ResourceMaps<A> {
destroyed_textures.clear();
}
- pub(crate) fn extend(&mut self, mut other: Self) {
+ pub(crate) fn extend(&mut self, other: &mut Self) {
let ResourceMaps {
buffers,
staging_buffers,
@@ -128,7 +127,37 @@ impl<A: HalApi> ResourceMaps<A> {
}
}
-/// Resources used by a queue submission, and work to be done once it completes.
+/// A command submitted to the GPU for execution.
+///
+/// ## Keeping resources alive while the GPU is using them
+///
+/// [`wgpu_hal`] requires that, when a command is submitted to a queue, all the
+/// resources it uses must remain alive until it has finished executing.
+///
+/// The natural way to satisfy this would be for `ActiveSubmission` to hold
+/// strong references to all the resources used by its commands. However, that
+/// would entail dropping those strong references every time a queue submission
+/// finishes, adjusting the reference counts of all the resources it used. This
+/// is usually needless work: it's rare for the active submission queue to be
+/// the final reference to an object. Usually the user is still holding on to
+/// it.
+///
+/// To avoid this, an `ActiveSubmission` does not initially hold any strong
+/// references to its commands' resources. Instead, each resource tracks the
+/// most recent submission index at which it has been used in
+/// [`ResourceInfo::submission_index`]. When the user drops a resource, if the
+/// submission in which it was last used is still present in the device's queue,
+/// we add the resource to [`ActiveSubmission::last_resources`]. Finally, when
+/// this `ActiveSubmission` is dequeued and dropped in
+/// [`LifetimeTracker::triage_submissions`], we drop `last_resources` along with
+/// it. Thus, unless a resource is dropped by the user, it doesn't need to be
+/// touched at all when processing completed work.
+///
+/// However, it's not clear that this is effective. See [#5560].
+///
+/// [`wgpu_hal`]: hal
+/// [`ResourceInfo::submission_index`]: crate::resource::ResourceInfo
+/// [#5560]: https://github.com/gfx-rs/wgpu/issues/5560
struct ActiveSubmission<A: HalApi> {
/// The index of the submission we track.
///
@@ -150,6 +179,18 @@ struct ActiveSubmission<A: HalApi> {
/// Buffers to be mapped once this submission has completed.
mapped: Vec<Arc<Buffer<A>>>,
+ /// Command buffers used by this submission, and the encoder that owns them.
+ ///
+ /// [`wgpu_hal::Queue::submit`] requires the submitted command buffers to
+ /// remain alive until the submission has completed execution. Command
+ /// encoders double as allocation pools for command buffers, so holding them
+ /// here and cleaning them up in [`LifetimeTracker::triage_submissions`]
+ /// satisfies that requirement.
+ ///
+ /// Once this submission has completed, the command buffers are reset and
+ /// the command encoder is recycled.
+ ///
+ /// [`wgpu_hal::Queue::submit`]: hal::Queue::submit
encoders: Vec<EncoderInFlight<A>>,
/// List of queue "on_submitted_work_done" closures to be called once this
@@ -330,28 +371,25 @@ impl<A: HalApi> LifetimeTracker<A> {
///
/// Assume that all submissions up through `last_done` have completed.
///
- /// - Buffers used by those submissions are now ready to map, if
- /// requested. Add any buffers in the submission's [`mapped`] list to
- /// [`self.ready_to_map`], where [`LifetimeTracker::handle_mapping`] will find
- /// them.
+ /// - Buffers used by those submissions are now ready to map, if requested.
+ /// Add any buffers in the submission's [`mapped`] list to
+ /// [`self.ready_to_map`], where [`LifetimeTracker::handle_mapping`]
+ /// will find them.
///
/// - Resources whose final use was in those submissions are now ready to
- /// free. Add any resources in the submission's [`last_resources`] table
- /// to [`self.free_resources`], where [`LifetimeTracker::cleanup`] will find
- /// them.
+ /// free. Dropping the submission's [`last_resources`] table does so.
///
/// Return a list of [`SubmittedWorkDoneClosure`]s to run.
///
/// [`mapped`]: ActiveSubmission::mapped
/// [`self.ready_to_map`]: LifetimeTracker::ready_to_map
/// [`last_resources`]: ActiveSubmission::last_resources
- /// [`self.free_resources`]: LifetimeTracker::free_resources
/// [`SubmittedWorkDoneClosure`]: crate::device::queue::SubmittedWorkDoneClosure
#[must_use]
pub fn triage_submissions(
&mut self,
last_done: SubmissionIndex,
- command_allocator: &mut super::CommandAllocator<A>,
+ command_allocator: &crate::command::CommandAllocator<A>,
) -> SmallVec<[SubmittedWorkDoneClosure; 1]> {
profiling::scope!("triage_submissions");
@@ -558,6 +596,18 @@ impl<A: HalApi> LifetimeTracker<A> {
&mut trackers.textures,
|maps| &mut maps.textures,
);
+
+ // We may have been suspected because a texture view or bind group
+ // referring to us was dropped. Remove stale weak references, so that
+ // the backlink table doesn't grow without bound.
+ for texture in self.suspected_resources.textures.values() {
+ texture.views.lock().retain(|view| view.strong_count() > 0);
+ texture
+ .bind_groups
+ .lock()
+ .retain(|bg| bg.strong_count() > 0);
+ }
+
self
}
@@ -583,6 +633,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|maps| &mut maps.buffers,
);
+ // We may have been suspected because a bind group referring to us was
+ // dropped. Remove stale weak references, so that the backlink table
+ // doesn't grow without bound.
+ for buffer in self.suspected_resources.buffers.values() {
+ buffer.bind_groups.lock().retain(|bg| bg.strong_count() > 0);
+ }
+
self
}
@@ -693,13 +750,10 @@ impl<A: HalApi> LifetimeTracker<A> {
/// Identify resources to free, according to `trackers` and `self.suspected_resources`.
///
- /// Given `trackers`, the [`Tracker`] belonging to same [`Device`] as
- /// `self`, and `hub`, the [`Hub`] to which that `Device` belongs:
- ///
- /// Remove from `trackers` each resource mentioned in
- /// [`self.suspected_resources`]. If `trackers` held the final reference to
- /// that resource, add it to the appropriate free list, to be destroyed by
- /// the hal:
+ /// Remove from `trackers`, the [`Tracker`] belonging to same [`Device`] as
+ /// `self`, each resource mentioned in [`self.suspected_resources`]. If
+ /// `trackers` held the final reference to that resource, add it to the
+ /// appropriate free list, to be destroyed by the hal:
///
/// - Add resources used by queue submissions still in flight to the
/// [`last_resources`] table of the last such submission's entry in
@@ -799,29 +853,33 @@ impl<A: HalApi> LifetimeTracker<A> {
*buffer.map_state.lock() = resource::BufferMapState::Idle;
log::trace!("Buffer ready to map {tracker_index:?} is not tracked anymore");
} else {
- let mapping = match std::mem::replace(
+ // This _cannot_ be inlined into the match. If it is, the lock will be held
+ // open through the whole match, resulting in a deadlock when we try to re-lock
+ // the buffer back to active.
+ let mapping = std::mem::replace(
&mut *buffer.map_state.lock(),
resource::BufferMapState::Idle,
- ) {
+ );
+ let pending_mapping = match mapping {
resource::BufferMapState::Waiting(pending_mapping) => pending_mapping,
// Mapping cancelled
resource::BufferMapState::Idle => continue,
// Mapping queued at least twice by map -> unmap -> map
// and was already successfully mapped below
- active @ resource::BufferMapState::Active { .. } => {
- *buffer.map_state.lock() = active;
+ resource::BufferMapState::Active { .. } => {
+ *buffer.map_state.lock() = mapping;
continue;
}
_ => panic!("No pending mapping."),
};
- let status = if mapping.range.start != mapping.range.end {
+ let status = if pending_mapping.range.start != pending_mapping.range.end {
log::debug!("Buffer {tracker_index:?} map state -> Active");
- let host = mapping.op.host;
- let size = mapping.range.end - mapping.range.start;
+ let host = pending_mapping.op.host;
+ let size = pending_mapping.range.end - pending_mapping.range.start;
match super::map_buffer(
raw,
&buffer,
- mapping.range.start,
+ pending_mapping.range.start,
size,
host,
snatch_guard,
@@ -829,7 +887,8 @@ impl<A: HalApi> LifetimeTracker<A> {
Ok(ptr) => {
*buffer.map_state.lock() = resource::BufferMapState::Active {
ptr,
- range: mapping.range.start..mapping.range.start + size,
+ range: pending_mapping.range.start
+ ..pending_mapping.range.start + size,
host,
};
Ok(())
@@ -842,12 +901,12 @@ impl<A: HalApi> LifetimeTracker<A> {
} else {
*buffer.map_state.lock() = resource::BufferMapState::Active {
ptr: std::ptr::NonNull::dangling(),
- range: mapping.range,
- host: mapping.op.host,
+ range: pending_mapping.range,
+ host: pending_mapping.op.host,
};
Ok(())
};
- pending_callbacks.push((mapping.op, status));
+ pending_callbacks.push((pending_mapping.op, status));
}
}
pending_callbacks
diff --git a/third_party/rust/wgpu-core/src/device/mod.rs b/third_party/rust/wgpu-core/src/device/mod.rs
index e2ab6c2690..e9da11b7a8 100644
--- a/third_party/rust/wgpu-core/src/device/mod.rs
+++ b/third_party/rust/wgpu-core/src/device/mod.rs
@@ -4,7 +4,6 @@ use crate::{
hub::Hub,
id::{BindGroupLayoutId, PipelineLayoutId},
resource::{Buffer, BufferAccessError, BufferAccessResult, BufferMapOperation},
- resource_log,
snatch::SnatchGuard,
Label, DOWNLEVEL_ERROR_MESSAGE,
};
@@ -377,42 +376,6 @@ fn map_buffer<A: HalApi>(
Ok(mapping.ptr)
}
-pub(crate) struct CommandAllocator<A: HalApi> {
- free_encoders: Vec<A::CommandEncoder>,
-}
-
-impl<A: HalApi> CommandAllocator<A> {
- fn acquire_encoder(
- &mut self,
- device: &A::Device,
- queue: &A::Queue,
- ) -> Result<A::CommandEncoder, hal::DeviceError> {
- match self.free_encoders.pop() {
- Some(encoder) => Ok(encoder),
- None => unsafe {
- let hal_desc = hal::CommandEncoderDescriptor { label: None, queue };
- device.create_command_encoder(&hal_desc)
- },
- }
- }
-
- fn release_encoder(&mut self, encoder: A::CommandEncoder) {
- self.free_encoders.push(encoder);
- }
-
- fn dispose(self, device: &A::Device) {
- resource_log!(
- "CommandAllocator::dispose encoders {}",
- self.free_encoders.len()
- );
- for cmd_encoder in self.free_encoders {
- unsafe {
- device.destroy_command_encoder(cmd_encoder);
- }
- }
- }
-}
-
#[derive(Clone, Debug, Error)]
#[error("Device is invalid")]
pub struct InvalidDevice;
diff --git a/third_party/rust/wgpu-core/src/device/queue.rs b/third_party/rust/wgpu-core/src/device/queue.rs
index 3cb5f695a7..f0db961ffc 100644
--- a/third_party/rust/wgpu-core/src/device/queue.rs
+++ b/third_party/rust/wgpu-core/src/device/queue.rs
@@ -4,16 +4,17 @@ use crate::{
api_log,
command::{
extract_texture_selector, validate_linear_texture_data, validate_texture_copy_range,
- ClearError, CommandBuffer, CopySide, ImageCopyTexture, TransferError,
+ ClearError, CommandAllocator, CommandBuffer, CopySide, ImageCopyTexture, TransferError,
},
conv,
- device::{life::ResourceMaps, DeviceError, WaitIdleError},
+ device::{DeviceError, WaitIdleError},
get_lowest_common_denom,
global::Global,
hal_api::HalApi,
hal_label,
id::{self, DeviceId, QueueId},
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
+ lock::{rank, Mutex, RwLockWriteGuard},
resource::{
Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedTexture, Resource,
ResourceInfo, ResourceType, StagingBuffer, Texture, TextureInner,
@@ -22,7 +23,6 @@ use crate::{
};
use hal::{CommandEncoder as _, Device as _, Queue as _};
-use parking_lot::Mutex;
use smallvec::SmallVec;
use std::{
@@ -34,9 +34,9 @@ use thiserror::Error;
use super::Device;
pub struct Queue<A: HalApi> {
- pub device: Option<Arc<Device<A>>>,
- pub raw: Option<A::Queue>,
- pub info: ResourceInfo<Queue<A>>,
+ pub(crate) device: Option<Arc<Device<A>>>,
+ pub(crate) raw: Option<A::Queue>,
+ pub(crate) info: ResourceInfo<Queue<A>>,
}
impl<A: HalApi> Resource for Queue<A> {
@@ -152,13 +152,21 @@ pub enum TempResource<A: HalApi> {
Texture(Arc<Texture<A>>),
}
-/// A queue execution for a particular command encoder.
+/// A series of raw [`CommandBuffer`]s that have been submitted to a
+/// queue, and the [`wgpu_hal::CommandEncoder`] that built them.
+///
+/// [`CommandBuffer`]: hal::Api::CommandBuffer
+/// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
pub(crate) struct EncoderInFlight<A: HalApi> {
raw: A::CommandEncoder,
cmd_buffers: Vec<A::CommandBuffer>,
}
impl<A: HalApi> EncoderInFlight<A> {
+ /// Free all of our command buffers.
+ ///
+ /// Return the command encoder, fully reset and ready to be
+ /// reused.
pub(crate) unsafe fn land(mut self) -> A::CommandEncoder {
unsafe { self.raw.reset_all(self.cmd_buffers.into_iter()) };
self.raw
@@ -192,6 +200,8 @@ pub(crate) struct PendingWrites<A: HalApi> {
/// True if `command_encoder` is in the "recording" state, as
/// described in the docs for the [`wgpu_hal::CommandEncoder`]
/// trait.
+ ///
+ /// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
pub is_recording: bool,
pub temp_resources: Vec<TempResource<A>>,
@@ -253,7 +263,7 @@ impl<A: HalApi> PendingWrites<A> {
#[must_use]
fn post_submit(
&mut self,
- command_allocator: &mut super::CommandAllocator<A>,
+ command_allocator: &CommandAllocator<A>,
device: &A::Device,
queue: &A::Queue,
) -> Option<EncoderInFlight<A>> {
@@ -307,7 +317,7 @@ fn prepare_staging_buffer<A: HalApi>(
let mapping = unsafe { device.raw().map_buffer(&buffer, 0..size) }?;
let staging_buffer = StagingBuffer {
- raw: Mutex::new(Some(buffer)),
+ raw: Mutex::new(rank::STAGING_BUFFER_RAW, Some(buffer)),
device: device.clone(),
size,
info: ResourceInfo::new(
@@ -490,7 +500,7 @@ impl Global {
prepare_staging_buffer(device, buffer_size.get(), device.instance_flags)?;
let fid = hub.staging_buffers.prepare(id_in);
- let (id, _) = fid.assign(staging_buffer);
+ let (id, _) = fid.assign(Arc::new(staging_buffer));
resource_log!("Queue::create_staging_buffer {id:?}");
Ok((id, staging_buffer_ptr))
@@ -707,7 +717,7 @@ impl Global {
.get(destination.texture)
.map_err(|_| TransferError::InvalidTexture(destination.texture))?;
- if dst.device.as_info().id() != queue_id.transmute() {
+ if dst.device.as_info().id().into_queue_id() != queue_id {
return Err(DeviceError::WrongDevice.into());
}
@@ -1152,8 +1162,8 @@ impl Global {
let snatch_guard = device.snatchable_lock.read();
// Fence lock must be acquired after the snatch lock everywhere to avoid deadlocks.
- let mut fence = device.fence.write();
- let fence = fence.as_mut().unwrap();
+ let mut fence_guard = device.fence.write();
+ let fence = fence_guard.as_mut().unwrap();
let submit_index = device
.active_submission_index
.fetch_add(1, Ordering::Relaxed)
@@ -1173,11 +1183,6 @@ impl Global {
//TODO: if multiple command buffers are submitted, we can re-use the last
// native command buffer of the previous chain instead of always creating
// a temporary one, since the chains are not finished.
- let mut temp_suspected = device.temp_suspected.lock();
- {
- let mut suspected = temp_suspected.replace(ResourceMaps::new()).unwrap();
- suspected.clear();
- }
// finish all the command buffers first
for &cmb_id in command_buffer_ids {
@@ -1191,7 +1196,7 @@ impl Global {
Err(_) => continue,
};
- if cmdbuf.device.as_info().id() != queue_id.transmute() {
+ if cmdbuf.device.as_info().id().into_queue_id() != queue_id {
return Err(DeviceError::WrongDevice.into());
}
@@ -1210,13 +1215,10 @@ impl Global {
));
}
if !cmdbuf.is_finished() {
- if let Some(cmdbuf) = Arc::into_inner(cmdbuf) {
- device.destroy_command_buffer(cmdbuf);
- } else {
- panic!(
- "Command buffer cannot be destroyed because is still in use"
- );
- }
+ let cmdbuf = Arc::into_inner(cmdbuf).expect(
+ "Command buffer cannot be destroyed because is still in use",
+ );
+ device.destroy_command_buffer(cmdbuf);
continue;
}
@@ -1228,41 +1230,23 @@ impl Global {
// update submission IDs
for buffer in cmd_buf_trackers.buffers.used_resources() {
- let tracker_index = buffer.info.tracker_index();
- let raw_buf = match buffer.raw.get(&snatch_guard) {
- Some(raw) => raw,
- None => {
- return Err(QueueSubmitError::DestroyedBuffer(
- buffer.info.id(),
- ));
- }
- };
+ if buffer.raw.get(&snatch_guard).is_none() {
+ return Err(QueueSubmitError::DestroyedBuffer(
+ buffer.info.id(),
+ ));
+ }
buffer.info.use_at(submit_index);
- if buffer.is_unique() {
- if let BufferMapState::Active { .. } = *buffer.map_state.lock()
- {
- log::warn!("Dropped buffer has a pending mapping.");
- unsafe { device.raw().unmap_buffer(raw_buf) }
- .map_err(DeviceError::from)?;
- }
- temp_suspected
- .as_mut()
- .unwrap()
- .buffers
- .insert(tracker_index, buffer.clone());
- } else {
- match *buffer.map_state.lock() {
- BufferMapState::Idle => (),
- _ => {
- return Err(QueueSubmitError::BufferStillMapped(
- buffer.info.id(),
- ))
- }
+
+ match *buffer.map_state.lock() {
+ BufferMapState::Idle => (),
+ _ => {
+ return Err(QueueSubmitError::BufferStillMapped(
+ buffer.info.id(),
+ ))
}
}
}
for texture in cmd_buf_trackers.textures.used_resources() {
- let tracker_index = texture.info.tracker_index();
let should_extend = match texture.inner.get(&snatch_guard) {
None => {
return Err(QueueSubmitError::DestroyedTexture(
@@ -1279,13 +1263,6 @@ impl Global {
}
};
texture.info.use_at(submit_index);
- if texture.is_unique() {
- temp_suspected
- .as_mut()
- .unwrap()
- .textures
- .insert(tracker_index, texture.clone());
- }
if should_extend {
unsafe {
used_surface_textures
@@ -1296,12 +1273,6 @@ impl Global {
}
for texture_view in cmd_buf_trackers.views.used_resources() {
texture_view.info.use_at(submit_index);
- if texture_view.is_unique() {
- temp_suspected.as_mut().unwrap().texture_views.insert(
- texture_view.as_info().tracker_index(),
- texture_view.clone(),
- );
- }
}
{
for bg in cmd_buf_trackers.bind_groups.used_resources() {
@@ -1315,13 +1286,6 @@ impl Global {
for sampler in bg.used.samplers.used_resources() {
sampler.info.use_at(submit_index);
}
- if bg.is_unique() {
- temp_suspected
- .as_mut()
- .unwrap()
- .bind_groups
- .insert(bg.as_info().tracker_index(), bg.clone());
- }
}
}
// assert!(cmd_buf_trackers.samplers.is_empty());
@@ -1329,32 +1293,14 @@ impl Global {
cmd_buf_trackers.compute_pipelines.used_resources()
{
compute_pipeline.info.use_at(submit_index);
- if compute_pipeline.is_unique() {
- temp_suspected.as_mut().unwrap().compute_pipelines.insert(
- compute_pipeline.as_info().tracker_index(),
- compute_pipeline.clone(),
- );
- }
}
for render_pipeline in
cmd_buf_trackers.render_pipelines.used_resources()
{
render_pipeline.info.use_at(submit_index);
- if render_pipeline.is_unique() {
- temp_suspected.as_mut().unwrap().render_pipelines.insert(
- render_pipeline.as_info().tracker_index(),
- render_pipeline.clone(),
- );
- }
}
for query_set in cmd_buf_trackers.query_sets.used_resources() {
query_set.info.use_at(submit_index);
- if query_set.is_unique() {
- temp_suspected.as_mut().unwrap().query_sets.insert(
- query_set.as_info().tracker_index(),
- query_set.clone(),
- );
- }
}
for bundle in cmd_buf_trackers.bundles.used_resources() {
bundle.info.use_at(submit_index);
@@ -1369,13 +1315,6 @@ impl Global {
for query_set in bundle.used.query_sets.read().used_resources() {
query_set.info.use_at(submit_index);
}
- if bundle.is_unique() {
- temp_suspected
- .as_mut()
- .unwrap()
- .render_bundles
- .insert(bundle.as_info().tracker_index(), bundle.clone());
- }
}
}
let mut baked = cmdbuf.from_arc_into_baked();
@@ -1452,8 +1391,8 @@ impl Global {
}
}
- let mut pending_writes = device.pending_writes.lock();
- let pending_writes = pending_writes.as_mut().unwrap();
+ let mut pending_writes_guard = device.pending_writes.lock();
+ let pending_writes = pending_writes_guard.as_mut().unwrap();
{
used_surface_textures.set_size(hub.textures.read().len());
@@ -1528,7 +1467,7 @@ impl Global {
profiling::scope!("cleanup");
if let Some(pending_execution) = pending_writes.post_submit(
- device.command_allocator.lock().as_mut().unwrap(),
+ &device.command_allocator,
device.raw(),
queue.raw.as_ref().unwrap(),
) {
@@ -1543,18 +1482,22 @@ impl Global {
active_executions,
);
- // This will schedule destruction of all resources that are no longer needed
- // by the user but used in the command stream, among other things.
- let (closures, _) = match device.maintain(fence, wgt::Maintain::Poll, snatch_guard) {
- Ok(closures) => closures,
- Err(WaitIdleError::Device(err)) => return Err(QueueSubmitError::Queue(err)),
- Err(WaitIdleError::StuckGpu) => return Err(QueueSubmitError::StuckGpu),
- Err(WaitIdleError::WrongSubmissionIndex(..)) => unreachable!(),
- };
-
// pending_write_resources has been drained, so it's empty, but we
// want to retain its heap allocation.
pending_writes.temp_resources = pending_write_resources;
+ drop(pending_writes_guard);
+
+ // This will schedule destruction of all resources that are no longer needed
+ // by the user but used in the command stream, among other things.
+ let fence_guard = RwLockWriteGuard::downgrade(fence_guard);
+ let (closures, _) =
+ match device.maintain(fence_guard, wgt::Maintain::Poll, snatch_guard) {
+ Ok(closures) => closures,
+ Err(WaitIdleError::Device(err)) => return Err(QueueSubmitError::Queue(err)),
+ Err(WaitIdleError::StuckGpu) => return Err(QueueSubmitError::StuckGpu),
+ Err(WaitIdleError::WrongSubmissionIndex(..)) => unreachable!(),
+ };
+
device.lock_life().post_submit();
(submit_index, closures)
diff --git a/third_party/rust/wgpu-core/src/device/resource.rs b/third_party/rust/wgpu-core/src/device/resource.rs
index 4892aecb75..2541af7c70 100644
--- a/third_party/rust/wgpu-core/src/device/resource.rs
+++ b/third_party/rust/wgpu-core/src/device/resource.rs
@@ -7,18 +7,20 @@ use crate::{
bgl,
life::{LifetimeTracker, WaitIdleError},
queue::PendingWrites,
- AttachmentData, CommandAllocator, DeviceLostInvocation, MissingDownlevelFlags,
- MissingFeatures, RenderPassContext, CLEANUP_WAIT_MS,
+ AttachmentData, DeviceLostInvocation, MissingDownlevelFlags, MissingFeatures,
+ RenderPassContext, CLEANUP_WAIT_MS,
},
hal_api::HalApi,
hal_label,
hub::Hub,
+ id,
init_tracker::{
BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange,
TextureInitTracker, TextureInitTrackerAction,
},
instance::Adapter,
- pipeline,
+ lock::{rank, Mutex, MutexGuard, RwLock},
+ pipeline::{self},
pool::ResourcePool,
registry::Registry,
resource::{
@@ -41,7 +43,6 @@ use crate::{
use arrayvec::ArrayVec;
use hal::{CommandEncoder as _, Device as _};
use once_cell::sync::OnceCell;
-use parking_lot::{Mutex, MutexGuard, RwLock};
use smallvec::SmallVec;
use thiserror::Error;
@@ -97,7 +98,7 @@ pub struct Device<A: HalApi> {
pub(crate) zero_buffer: Option<A::Buffer>,
pub(crate) info: ResourceInfo<Device<A>>,
- pub(crate) command_allocator: Mutex<Option<CommandAllocator<A>>>,
+ pub(crate) command_allocator: command::CommandAllocator<A>,
//Note: The submission index here corresponds to the last submission that is done.
pub(crate) active_submission_index: AtomicU64, //SubmissionIndex,
// NOTE: if both are needed, the `snatchable_lock` must be consistently acquired before the
@@ -126,9 +127,6 @@ pub struct Device<A: HalApi> {
pub(crate) tracker_indices: TrackerIndexAllocators,
// Life tracker should be locked right after the device and before anything else.
life_tracker: Mutex<LifetimeTracker<A>>,
- /// Temporary storage for resource management functions. Cleared at the end
- /// of every call (unless an error occurs).
- pub(crate) temp_suspected: Mutex<Option<ResourceMaps<A>>>,
/// Pool of bind group layouts, allowing deduplication.
pub(crate) bgl_pool: ResourcePool<bgl::EntryMap, BindGroupLayout<A>>,
pub(crate) alignments: hal::Alignments,
@@ -141,6 +139,10 @@ pub struct Device<A: HalApi> {
#[cfg(feature = "trace")]
pub(crate) trace: Mutex<Option<trace::Trace>>,
pub(crate) usage_scopes: UsageScopePool<A>,
+
+ /// Temporary storage, cleared at the start of every call,
+ /// retained only to save allocations.
+ temp_suspected: Mutex<Option<ResourceMaps<A>>>,
}
pub(crate) enum DeferredDestroy<A: HalApi> {
@@ -165,7 +167,7 @@ impl<A: HalApi> Drop for Device<A> {
let raw = self.raw.take().unwrap();
let pending_writes = self.pending_writes.lock().take().unwrap();
pending_writes.dispose(&raw);
- self.command_allocator.lock().take().unwrap().dispose(&raw);
+ self.command_allocator.dispose(&raw);
unsafe {
raw.destroy_buffer(self.zero_buffer.take().unwrap());
raw.destroy_fence(self.fence.write().take().unwrap());
@@ -223,10 +225,8 @@ impl<A: HalApi> Device<A> {
let fence =
unsafe { raw_device.create_fence() }.map_err(|_| CreateDeviceError::OutOfMemory)?;
- let mut com_alloc = CommandAllocator {
- free_encoders: Vec::new(),
- };
- let pending_encoder = com_alloc
+ let command_allocator = command::CommandAllocator::new();
+ let pending_encoder = command_allocator
.acquire_encoder(&raw_device, raw_queue)
.map_err(|_| CreateDeviceError::OutOfMemory)?;
let mut pending_writes = queue::PendingWrites::<A>::new(pending_encoder);
@@ -271,38 +271,44 @@ impl<A: HalApi> Device<A> {
queue_to_drop: OnceCell::new(),
zero_buffer: Some(zero_buffer),
info: ResourceInfo::new("<device>", None),
- command_allocator: Mutex::new(Some(com_alloc)),
+ command_allocator,
active_submission_index: AtomicU64::new(0),
- fence: RwLock::new(Some(fence)),
- snatchable_lock: unsafe { SnatchLock::new() },
+ fence: RwLock::new(rank::DEVICE_FENCE, Some(fence)),
+ snatchable_lock: unsafe { SnatchLock::new(rank::DEVICE_SNATCHABLE_LOCK) },
valid: AtomicBool::new(true),
- trackers: Mutex::new(Tracker::new()),
+ trackers: Mutex::new(rank::DEVICE_TRACKERS, Tracker::new()),
tracker_indices: TrackerIndexAllocators::new(),
- life_tracker: Mutex::new(life::LifetimeTracker::new()),
- temp_suspected: Mutex::new(Some(life::ResourceMaps::new())),
+ life_tracker: Mutex::new(rank::DEVICE_LIFE_TRACKER, life::LifetimeTracker::new()),
+ temp_suspected: Mutex::new(
+ rank::DEVICE_TEMP_SUSPECTED,
+ Some(life::ResourceMaps::new()),
+ ),
bgl_pool: ResourcePool::new(),
#[cfg(feature = "trace")]
- trace: Mutex::new(trace_path.and_then(|path| match trace::Trace::new(path) {
- Ok(mut trace) => {
- trace.add(trace::Action::Init {
- desc: desc.clone(),
- backend: A::VARIANT,
- });
- Some(trace)
- }
- Err(e) => {
- log::error!("Unable to start a trace in '{path:?}': {e}");
- None
- }
- })),
+ trace: Mutex::new(
+ rank::DEVICE_TRACE,
+ trace_path.and_then(|path| match trace::Trace::new(path) {
+ Ok(mut trace) => {
+ trace.add(trace::Action::Init {
+ desc: desc.clone(),
+ backend: A::VARIANT,
+ });
+ Some(trace)
+ }
+ Err(e) => {
+ log::error!("Unable to start a trace in '{path:?}': {e}");
+ None
+ }
+ }),
+ ),
alignments,
limits: desc.required_limits.clone(),
features: desc.required_features,
downlevel,
instance_flags,
- pending_writes: Mutex::new(Some(pending_writes)),
- deferred_destroy: Mutex::new(Vec::new()),
- usage_scopes: Default::default(),
+ pending_writes: Mutex::new(rank::DEVICE_PENDING_WRITES, Some(pending_writes)),
+ deferred_destroy: Mutex::new(rank::DEVICE_DEFERRED_DESTROY, Vec::new()),
+ usage_scopes: Mutex::new(rank::DEVICE_USAGE_SCOPES, Default::default()),
})
}
@@ -379,7 +385,7 @@ impl<A: HalApi> Device<A> {
/// Check this device for completed commands.
///
- /// The `maintain` argument tells how the maintence function should behave, either
+ /// The `maintain` argument tells how the maintenance function should behave, either
/// blocking or just polling the current state of the gpu.
///
/// Return a pair `(closures, queue_empty)`, where:
@@ -392,11 +398,12 @@ impl<A: HalApi> Device<A> {
/// return it to our callers.)
pub(crate) fn maintain<'this>(
&'this self,
- fence: &A::Fence,
+ fence_guard: crate::lock::RwLockReadGuard<Option<A::Fence>>,
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
snatch_guard: SnatchGuard,
) -> Result<(UserClosures, bool), WaitIdleError> {
profiling::scope!("Device::maintain");
+ let fence = fence_guard.as_ref().unwrap();
let last_done_index = if maintain.is_wait() {
let index_to_wait_for = match maintain {
wgt::Maintain::WaitForSubmissionIndex(submission_index) => {
@@ -425,28 +432,12 @@ impl<A: HalApi> Device<A> {
};
let mut life_tracker = self.lock_life();
- let submission_closures = life_tracker.triage_submissions(
- last_done_index,
- self.command_allocator.lock().as_mut().unwrap(),
- );
-
- {
- // Normally, `temp_suspected` exists only to save heap
- // allocations: it's cleared at the start of the function
- // call, and cleared by the end. But `Global::queue_submit` is
- // fallible; if it exits early, it may leave some resources in
- // `temp_suspected`.
- let temp_suspected = self
- .temp_suspected
- .lock()
- .replace(ResourceMaps::new())
- .unwrap();
+ let submission_closures =
+ life_tracker.triage_submissions(last_done_index, &self.command_allocator);
- life_tracker.suspected_resources.extend(temp_suspected);
+ life_tracker.triage_suspected(&self.trackers);
- life_tracker.triage_suspected(&self.trackers);
- life_tracker.triage_mapped();
- }
+ life_tracker.triage_mapped();
let mapping_closures =
life_tracker.handle_mapping(self.raw(), &self.trackers, &snatch_guard);
@@ -478,6 +469,7 @@ impl<A: HalApi> Device<A> {
// Don't hold the locks while calling release_gpu_resources.
drop(life_tracker);
+ drop(fence_guard);
drop(snatch_guard);
if should_release_gpu_resource {
@@ -493,12 +485,14 @@ impl<A: HalApi> Device<A> {
}
pub(crate) fn untrack(&self, trackers: &Tracker<A>) {
+ // If we have a previously allocated `ResourceMap`, just use that.
let mut temp_suspected = self
.temp_suspected
.lock()
- .replace(ResourceMaps::new())
- .unwrap();
+ .take()
+ .unwrap_or_else(|| ResourceMaps::new());
temp_suspected.clear();
+
// As the tracker is cleared/dropped, we need to consider all the resources
// that it references for destruction in the next GC pass.
{
@@ -559,7 +553,11 @@ impl<A: HalApi> Device<A> {
}
}
}
- self.lock_life().suspected_resources.extend(temp_suspected);
+ self.lock_life()
+ .suspected_resources
+ .extend(&mut temp_suspected);
+ // Save this resource map for later reuse.
+ *self.temp_suspected.lock() = Some(temp_suspected);
}
pub(crate) fn create_buffer(
@@ -653,14 +651,17 @@ impl<A: HalApi> Device<A> {
device: self.clone(),
usage: desc.usage,
size: desc.size,
- initialization_status: RwLock::new(BufferInitTracker::new(aligned_size)),
- sync_mapped_writes: Mutex::new(None),
- map_state: Mutex::new(resource::BufferMapState::Idle),
+ initialization_status: RwLock::new(
+ rank::BUFFER_INITIALIZATION_STATUS,
+ BufferInitTracker::new(aligned_size),
+ ),
+ sync_mapped_writes: Mutex::new(rank::BUFFER_SYNC_MAPPED_WRITES, None),
+ map_state: Mutex::new(rank::BUFFER_MAP_STATE, resource::BufferMapState::Idle),
info: ResourceInfo::new(
desc.label.borrow_or_default(),
Some(self.tracker_indices.buffers.clone()),
),
- bind_groups: Mutex::new(Vec::new()),
+ bind_groups: Mutex::new(rank::BUFFER_BIND_GROUPS, Vec::new()),
})
}
@@ -680,10 +681,10 @@ impl<A: HalApi> Device<A> {
desc: desc.map_label(|_| ()),
hal_usage,
format_features,
- initialization_status: RwLock::new(TextureInitTracker::new(
- desc.mip_level_count,
- desc.array_layer_count(),
- )),
+ initialization_status: RwLock::new(
+ rank::TEXTURE_INITIALIZATION_STATUS,
+ TextureInitTracker::new(desc.mip_level_count, desc.array_layer_count()),
+ ),
full_range: TextureSelector {
mips: 0..desc.mip_level_count,
layers: 0..desc.array_layer_count(),
@@ -692,9 +693,9 @@ impl<A: HalApi> Device<A> {
desc.label.borrow_or_default(),
Some(self.tracker_indices.textures.clone()),
),
- clear_mode: RwLock::new(clear_mode),
- views: Mutex::new(Vec::new()),
- bind_groups: Mutex::new(Vec::new()),
+ clear_mode: RwLock::new(rank::TEXTURE_CLEAR_MODE, clear_mode),
+ views: Mutex::new(rank::TEXTURE_VIEWS, Vec::new()),
+ bind_groups: Mutex::new(rank::TEXTURE_BIND_GROUPS, Vec::new()),
}
}
@@ -710,14 +711,17 @@ impl<A: HalApi> Device<A> {
device: self.clone(),
usage: desc.usage,
size: desc.size,
- initialization_status: RwLock::new(BufferInitTracker::new(0)),
- sync_mapped_writes: Mutex::new(None),
- map_state: Mutex::new(resource::BufferMapState::Idle),
+ initialization_status: RwLock::new(
+ rank::BUFFER_INITIALIZATION_STATUS,
+ BufferInitTracker::new(0),
+ ),
+ sync_mapped_writes: Mutex::new(rank::BUFFER_SYNC_MAPPED_WRITES, None),
+ map_state: Mutex::new(rank::BUFFER_MAP_STATE, resource::BufferMapState::Idle),
info: ResourceInfo::new(
desc.label.borrow_or_default(),
Some(self.tracker_indices.buffers.clone()),
),
- bind_groups: Mutex::new(Vec::new()),
+ bind_groups: Mutex::new(rank::BUFFER_BIND_GROUPS, Vec::new()),
}
}
@@ -1421,7 +1425,7 @@ impl<A: HalApi> Device<A> {
pipeline::ShaderModuleSource::Wgsl(code) => {
profiling::scope!("naga::front::wgsl::parse_str");
let module = naga::front::wgsl::parse_str(&code).map_err(|inner| {
- pipeline::CreateShaderModuleError::Parsing(pipeline::ShaderError {
+ pipeline::CreateShaderModuleError::Parsing(naga::error::ShaderError {
source: code.to_string(),
label: desc.label.as_ref().map(|l| l.to_string()),
inner: Box::new(inner),
@@ -1434,7 +1438,7 @@ impl<A: HalApi> Device<A> {
let parser = naga::front::spv::Frontend::new(spv.iter().cloned(), &options);
profiling::scope!("naga::front::spv::Frontend");
let module = parser.parse().map_err(|inner| {
- pipeline::CreateShaderModuleError::ParsingSpirV(pipeline::ShaderError {
+ pipeline::CreateShaderModuleError::ParsingSpirV(naga::error::ShaderError {
source: String::new(),
label: desc.label.as_ref().map(|l| l.to_string()),
inner: Box::new(inner),
@@ -1447,7 +1451,7 @@ impl<A: HalApi> Device<A> {
let mut parser = naga::front::glsl::Frontend::default();
profiling::scope!("naga::front::glsl::Frontend.parse");
let module = parser.parse(&options, &code).map_err(|inner| {
- pipeline::CreateShaderModuleError::ParsingGlsl(pipeline::ShaderError {
+ pipeline::CreateShaderModuleError::ParsingGlsl(naga::error::ShaderError {
source: code.to_string(),
label: desc.label.as_ref().map(|l| l.to_string()),
inner: Box::new(inner),
@@ -1471,9 +1475,78 @@ impl<A: HalApi> Device<A> {
};
}
- use naga::valid::Capabilities as Caps;
profiling::scope!("naga::validate");
+ let debug_source =
+ if self.instance_flags.contains(wgt::InstanceFlags::DEBUG) && !source.is_empty() {
+ Some(hal::DebugSource {
+ file_name: Cow::Owned(
+ desc.label
+ .as_ref()
+ .map_or("shader".to_string(), |l| l.to_string()),
+ ),
+ source_code: Cow::Owned(source.clone()),
+ })
+ } else {
+ None
+ };
+
+ let info = self
+ .create_validator(naga::valid::ValidationFlags::all())
+ .validate(&module)
+ .map_err(|inner| {
+ pipeline::CreateShaderModuleError::Validation(naga::error::ShaderError {
+ source,
+ label: desc.label.as_ref().map(|l| l.to_string()),
+ inner: Box::new(inner),
+ })
+ })?;
+
+ let interface =
+ validation::Interface::new(&module, &info, self.limits.clone(), self.features);
+ let hal_shader = hal::ShaderInput::Naga(hal::NagaShader {
+ module,
+ info,
+ debug_source,
+ });
+ let hal_desc = hal::ShaderModuleDescriptor {
+ label: desc.label.to_hal(self.instance_flags),
+ runtime_checks: desc.shader_bound_checks.runtime_checks(),
+ };
+ let raw = match unsafe {
+ self.raw
+ .as_ref()
+ .unwrap()
+ .create_shader_module(&hal_desc, hal_shader)
+ } {
+ Ok(raw) => raw,
+ Err(error) => {
+ return Err(match error {
+ hal::ShaderError::Device(error) => {
+ pipeline::CreateShaderModuleError::Device(error.into())
+ }
+ hal::ShaderError::Compilation(ref msg) => {
+ log::error!("Shader error: {}", msg);
+ pipeline::CreateShaderModuleError::Generation
+ }
+ })
+ }
+ };
+
+ Ok(pipeline::ShaderModule {
+ raw: Some(raw),
+ device: self.clone(),
+ interface: Some(interface),
+ info: ResourceInfo::new(desc.label.borrow_or_default(), None),
+ label: desc.label.borrow_or_default().to_string(),
+ })
+ }
+ /// Create a validator with the given validation flags.
+ pub fn create_validator(
+ self: &Arc<Self>,
+ flags: naga::valid::ValidationFlags,
+ ) -> naga::valid::Validator {
+ use naga::valid::Capabilities as Caps;
let mut caps = Caps::empty();
caps.set(
Caps::PUSH_CONSTANT,
@@ -1541,69 +1614,36 @@ impl<A: HalApi> Device<A> {
.flags
.contains(wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES),
);
+ caps.set(
+ Caps::SUBGROUP,
+ self.features
+ .intersects(wgt::Features::SUBGROUP | wgt::Features::SUBGROUP_VERTEX),
+ );
+ caps.set(
+ Caps::SUBGROUP_BARRIER,
+ self.features.intersects(wgt::Features::SUBGROUP_BARRIER),
+ );
- let debug_source =
- if self.instance_flags.contains(wgt::InstanceFlags::DEBUG) && !source.is_empty() {
- Some(hal::DebugSource {
- file_name: Cow::Owned(
- desc.label
- .as_ref()
- .map_or("shader".to_string(), |l| l.to_string()),
- ),
- source_code: Cow::Owned(source.clone()),
- })
- } else {
- None
- };
-
- let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
- .validate(&module)
- .map_err(|inner| {
- pipeline::CreateShaderModuleError::Validation(pipeline::ShaderError {
- source,
- label: desc.label.as_ref().map(|l| l.to_string()),
- inner: Box::new(inner),
- })
- })?;
+ let mut subgroup_stages = naga::valid::ShaderStages::empty();
+ subgroup_stages.set(
+ naga::valid::ShaderStages::COMPUTE | naga::valid::ShaderStages::FRAGMENT,
+ self.features.contains(wgt::Features::SUBGROUP),
+ );
+ subgroup_stages.set(
+ naga::valid::ShaderStages::VERTEX,
+ self.features.contains(wgt::Features::SUBGROUP_VERTEX),
+ );
- let interface =
- validation::Interface::new(&module, &info, self.limits.clone(), self.features);
- let hal_shader = hal::ShaderInput::Naga(hal::NagaShader {
- module,
- info,
- debug_source,
- });
- let hal_desc = hal::ShaderModuleDescriptor {
- label: desc.label.to_hal(self.instance_flags),
- runtime_checks: desc.shader_bound_checks.runtime_checks(),
- };
- let raw = match unsafe {
- self.raw
- .as_ref()
- .unwrap()
- .create_shader_module(&hal_desc, hal_shader)
- } {
- Ok(raw) => raw,
- Err(error) => {
- return Err(match error {
- hal::ShaderError::Device(error) => {
- pipeline::CreateShaderModuleError::Device(error.into())
- }
- hal::ShaderError::Compilation(ref msg) => {
- log::error!("Shader error: {}", msg);
- pipeline::CreateShaderModuleError::Generation
- }
- })
- }
+ let subgroup_operations = if caps.contains(Caps::SUBGROUP) {
+ use naga::valid::SubgroupOperationSet as S;
+ S::BASIC | S::VOTE | S::ARITHMETIC | S::BALLOT | S::SHUFFLE | S::SHUFFLE_RELATIVE
+ } else {
+ naga::valid::SubgroupOperationSet::empty()
};
-
- Ok(pipeline::ShaderModule {
- raw: Some(raw),
- device: self.clone(),
- interface: Some(interface),
- info: ResourceInfo::new(desc.label.borrow_or_default(), None),
- label: desc.label.borrow_or_default().to_string(),
- })
+ let mut validator = naga::valid::Validator::new(flags, caps);
+ validator.subgroup_stages(subgroup_stages);
+ validator.subgroup_operations(subgroup_operations);
+ validator
}
#[allow(unused_unsafe)]
@@ -1913,6 +1953,7 @@ impl<A: HalApi> Device<A> {
used: &mut BindGroupStates<A>,
storage: &'a Storage<Buffer<A>>,
limits: &wgt::Limits,
+ device_id: id::Id<id::markers::Device>,
snatch_guard: &'a SnatchGuard<'a>,
) -> Result<hal::BufferBinding<'a, A>, binding_model::CreateBindGroupError> {
use crate::binding_model::CreateBindGroupError as Error;
@@ -1931,6 +1972,7 @@ impl<A: HalApi> Device<A> {
})
}
};
+
let (pub_usage, internal_use, range_limit) = match binding_ty {
wgt::BufferBindingType::Uniform => (
wgt::BufferUsages::UNIFORM,
@@ -1963,6 +2005,10 @@ impl<A: HalApi> Device<A> {
.add_single(storage, bb.buffer_id, internal_use)
.ok_or(Error::InvalidBuffer(bb.buffer_id))?;
+ if buffer.device.as_info().id() != device_id {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
check_buffer_usage(bb.buffer_id, buffer.usage, pub_usage)?;
let raw_buffer = buffer
.raw
@@ -2041,13 +2087,53 @@ impl<A: HalApi> Device<A> {
})
}
- pub(crate) fn create_texture_binding(
- view: &TextureView<A>,
- internal_use: hal::TextureUses,
- pub_usage: wgt::TextureUsages,
+ fn create_sampler_binding<'a>(
+ used: &BindGroupStates<A>,
+ storage: &'a Storage<Sampler<A>>,
+ id: id::Id<id::markers::Sampler>,
+ device_id: id::Id<id::markers::Device>,
+ ) -> Result<&'a Sampler<A>, binding_model::CreateBindGroupError> {
+ use crate::binding_model::CreateBindGroupError as Error;
+
+ let sampler = used
+ .samplers
+ .add_single(storage, id)
+ .ok_or(Error::InvalidSampler(id))?;
+
+ if sampler.device.as_info().id() != device_id {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
+ Ok(sampler)
+ }
+
+ pub(crate) fn create_texture_binding<'a>(
+ self: &Arc<Self>,
+ binding: u32,
+ decl: &wgt::BindGroupLayoutEntry,
+ storage: &'a Storage<TextureView<A>>,
+ id: id::Id<id::markers::TextureView>,
used: &mut BindGroupStates<A>,
used_texture_ranges: &mut Vec<TextureInitTrackerAction<A>>,
- ) -> Result<(), binding_model::CreateBindGroupError> {
+ snatch_guard: &'a SnatchGuard<'a>,
+ ) -> Result<hal::TextureBinding<'a, A>, binding_model::CreateBindGroupError> {
+ use crate::binding_model::CreateBindGroupError as Error;
+
+ let view = used
+ .views
+ .add_single(storage, id)
+ .ok_or(Error::InvalidTextureView(id))?;
+
+ if view.device.as_info().id() != self.as_info().id() {
+ return Err(DeviceError::WrongDevice.into());
+ }
+
+ let (pub_usage, internal_use) = self.texture_use_parameters(
+ binding,
+ decl,
+ view,
+ "SampledTexture, ReadonlyStorageTexture or WriteonlyStorageTexture",
+ )?;
let texture = &view.parent;
let texture_id = texture.as_info().id();
// Careful here: the texture may no longer have its own ref count,
@@ -2077,7 +2163,12 @@ impl<A: HalApi> Device<A> {
kind: MemoryInitKind::NeedsInitializedMemory,
});
- Ok(())
+ Ok(hal::TextureBinding {
+ view: view
+ .raw(snatch_guard)
+ .ok_or(Error::InvalidTextureView(id))?,
+ usage: internal_use,
+ })
}
// This function expects the provided bind group layout to be resolved
@@ -2139,6 +2230,7 @@ impl<A: HalApi> Device<A> {
&mut used,
&*buffer_guard,
&self.limits,
+ self.as_info().id(),
&snatch_guard,
)?;
@@ -2162,105 +2254,86 @@ impl<A: HalApi> Device<A> {
&mut used,
&*buffer_guard,
&self.limits,
+ self.as_info().id(),
&snatch_guard,
)?;
hal_buffers.push(bb);
}
(res_index, num_bindings)
}
- Br::Sampler(id) => {
- match decl.ty {
- wgt::BindingType::Sampler(ty) => {
- let sampler = used
- .samplers
- .add_single(&*sampler_guard, id)
- .ok_or(Error::InvalidSampler(id))?;
-
- if sampler.device.as_info().id() != self.as_info().id() {
- return Err(DeviceError::WrongDevice.into());
- }
-
- // Allowed sampler values for filtering and comparison
- let (allowed_filtering, allowed_comparison) = match ty {
- wgt::SamplerBindingType::Filtering => (None, false),
- wgt::SamplerBindingType::NonFiltering => (Some(false), false),
- wgt::SamplerBindingType::Comparison => (None, true),
- };
-
- if let Some(allowed_filtering) = allowed_filtering {
- if allowed_filtering != sampler.filtering {
- return Err(Error::WrongSamplerFiltering {
- binding,
- layout_flt: allowed_filtering,
- sampler_flt: sampler.filtering,
- });
- }
- }
+ Br::Sampler(id) => match decl.ty {
+ wgt::BindingType::Sampler(ty) => {
+ let sampler = Self::create_sampler_binding(
+ &used,
+ &sampler_guard,
+ id,
+ self.as_info().id(),
+ )?;
- if allowed_comparison != sampler.comparison {
- return Err(Error::WrongSamplerComparison {
+ let (allowed_filtering, allowed_comparison) = match ty {
+ wgt::SamplerBindingType::Filtering => (None, false),
+ wgt::SamplerBindingType::NonFiltering => (Some(false), false),
+ wgt::SamplerBindingType::Comparison => (None, true),
+ };
+ if let Some(allowed_filtering) = allowed_filtering {
+ if allowed_filtering != sampler.filtering {
+ return Err(Error::WrongSamplerFiltering {
binding,
- layout_cmp: allowed_comparison,
- sampler_cmp: sampler.comparison,
+ layout_flt: allowed_filtering,
+ sampler_flt: sampler.filtering,
});
}
-
- let res_index = hal_samplers.len();
- hal_samplers.push(sampler.raw());
- (res_index, 1)
}
- _ => {
- return Err(Error::WrongBindingType {
+ if allowed_comparison != sampler.comparison {
+ return Err(Error::WrongSamplerComparison {
binding,
- actual: decl.ty,
- expected: "Sampler",
- })
+ layout_cmp: allowed_comparison,
+ sampler_cmp: sampler.comparison,
+ });
}
+
+ let res_index = hal_samplers.len();
+ hal_samplers.push(sampler.raw());
+ (res_index, 1)
}
- }
+ _ => {
+ return Err(Error::WrongBindingType {
+ binding,
+ actual: decl.ty,
+ expected: "Sampler",
+ })
+ }
+ },
Br::SamplerArray(ref bindings_array) => {
let num_bindings = bindings_array.len();
Self::check_array_binding(self.features, decl.count, num_bindings)?;
let res_index = hal_samplers.len();
for &id in bindings_array.iter() {
- let sampler = used
- .samplers
- .add_single(&*sampler_guard, id)
- .ok_or(Error::InvalidSampler(id))?;
- if sampler.device.as_info().id() != self.as_info().id() {
- return Err(DeviceError::WrongDevice.into());
- }
+ let sampler = Self::create_sampler_binding(
+ &used,
+ &sampler_guard,
+ id,
+ self.as_info().id(),
+ )?;
+
hal_samplers.push(sampler.raw());
}
(res_index, num_bindings)
}
Br::TextureView(id) => {
- let view = used
- .views
- .add_single(&*texture_view_guard, id)
- .ok_or(Error::InvalidTextureView(id))?;
- let (pub_usage, internal_use) = self.texture_use_parameters(
+ let tb = self.create_texture_binding(
binding,
decl,
- view,
- "SampledTexture, ReadonlyStorageTexture or WriteonlyStorageTexture",
- )?;
- Self::create_texture_binding(
- view,
- internal_use,
- pub_usage,
+ &texture_view_guard,
+ id,
&mut used,
&mut used_texture_ranges,
+ &snatch_guard,
)?;
let res_index = hal_textures.len();
- hal_textures.push(hal::TextureBinding {
- view: view
- .raw(&snatch_guard)
- .ok_or(Error::InvalidTextureView(id))?,
- usage: internal_use,
- });
+ hal_textures.push(tb);
(res_index, 1)
}
Br::TextureViewArray(ref bindings_array) => {
@@ -2269,26 +2342,17 @@ impl<A: HalApi> Device<A> {
let res_index = hal_textures.len();
for &id in bindings_array.iter() {
- let view = used
- .views
- .add_single(&*texture_view_guard, id)
- .ok_or(Error::InvalidTextureView(id))?;
- let (pub_usage, internal_use) =
- self.texture_use_parameters(binding, decl, view,
- "SampledTextureArray, ReadonlyStorageTextureArray or WriteonlyStorageTextureArray")?;
- Self::create_texture_binding(
- view,
- internal_use,
- pub_usage,
+ let tb = self.create_texture_binding(
+ binding,
+ decl,
+ &texture_view_guard,
+ id,
&mut used,
&mut used_texture_ranges,
+ &snatch_guard,
)?;
- hal_textures.push(hal::TextureBinding {
- view: view
- .raw(&snatch_guard)
- .ok_or(Error::InvalidTextureView(id))?,
- usage: internal_use,
- });
+
+ hal_textures.push(tb);
}
(res_index, num_bindings)
@@ -2762,8 +2826,10 @@ impl<A: HalApi> Device<A> {
label: desc.label.to_hal(self.instance_flags),
layout: pipeline_layout.raw(),
stage: hal::ProgrammableStage {
- entry_point: final_entry_point_name.as_ref(),
module: shader_module.raw(),
+ entry_point: final_entry_point_name.as_ref(),
+ constants: desc.stage.constants.as_ref(),
+ zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
},
};
@@ -3178,6 +3244,8 @@ impl<A: HalApi> Device<A> {
hal::ProgrammableStage {
module: vertex_shader_module.raw(),
entry_point: &vertex_entry_point_name,
+ constants: stage_desc.constants.as_ref(),
+ zero_initialize_workgroup_memory: stage_desc.zero_initialize_workgroup_memory,
}
};
@@ -3237,6 +3305,10 @@ impl<A: HalApi> Device<A> {
Some(hal::ProgrammableStage {
module: shader_module.raw(),
entry_point: &fragment_entry_point_name,
+ constants: fragment_state.stage.constants.as_ref(),
+ zero_initialize_workgroup_memory: fragment_state
+ .stage
+ .zero_initialize_workgroup_memory,
})
}
None => None,
@@ -3482,10 +3554,9 @@ impl<A: HalApi> Device<A> {
.map_err(DeviceError::from)?
};
drop(guard);
- let closures = self.lock_life().triage_submissions(
- submission_index,
- self.command_allocator.lock().as_mut().unwrap(),
- );
+ let closures = self
+ .lock_life()
+ .triage_submissions(submission_index, &self.command_allocator);
assert!(
closures.is_empty(),
"wait_for_submit is not expected to work with closures"
@@ -3613,10 +3684,7 @@ impl<A: HalApi> Device<A> {
log::error!("failed to wait for the device: {error}");
}
let mut life_tracker = self.lock_life();
- let _ = life_tracker.triage_submissions(
- current_index,
- self.command_allocator.lock().as_mut().unwrap(),
- );
+ let _ = life_tracker.triage_submissions(current_index, &self.command_allocator);
if let Some(device_lost_closure) = life_tracker.device_lost_closure.take() {
// It's important to not hold the lock while calling the closure.
drop(life_tracker);
diff --git a/third_party/rust/wgpu-core/src/global.rs b/third_party/rust/wgpu-core/src/global.rs
index 9a8c43bf33..6f6756a88c 100644
--- a/third_party/rust/wgpu-core/src/global.rs
+++ b/third_party/rust/wgpu-core/src/global.rs
@@ -45,7 +45,7 @@ impl GlobalReport {
pub struct Global {
pub instance: Instance,
- pub surfaces: Registry<Surface>,
+ pub(crate) surfaces: Registry<Surface>,
pub(crate) hubs: Hubs,
}
@@ -155,11 +155,9 @@ impl Drop for Global {
// destroy surfaces
for element in surfaces_locked.map.drain(..) {
if let Element::Occupied(arc_surface, _) = element {
- if let Some(surface) = Arc::into_inner(arc_surface) {
- self.instance.destroy_surface(surface);
- } else {
- panic!("Surface cannot be destroyed because is still in use");
- }
+ let surface = Arc::into_inner(arc_surface)
+ .expect("Surface cannot be destroyed because is still in use");
+ self.instance.destroy_surface(surface);
}
}
}
diff --git a/third_party/rust/wgpu-core/src/hal_api.rs b/third_party/rust/wgpu-core/src/hal_api.rs
index 179024baed..f1a40b1cff 100644
--- a/third_party/rust/wgpu-core/src/hal_api.rs
+++ b/third_party/rust/wgpu-core/src/hal_api.rs
@@ -11,7 +11,7 @@ pub trait HalApi: hal::Api + 'static + WasmNotSendSync {
fn create_instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance;
fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance>;
fn hub(global: &Global) -> &Hub<Self>;
- fn get_surface(surface: &Surface) -> Option<&Self::Surface>;
+ fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface>;
}
impl HalApi for hal::api::Empty {
@@ -25,7 +25,7 @@ impl HalApi for hal::api::Empty {
fn hub(_: &Global) -> &Hub<Self> {
unimplemented!("called empty api")
}
- fn get_surface(_: &Surface) -> Option<&Self::Surface> {
+ fn surface_as_hal(_: &Surface) -> Option<&Self::Surface> {
unimplemented!("called empty api")
}
}
@@ -46,8 +46,8 @@ impl HalApi for hal::api::Vulkan {
fn hub(global: &Global) -> &Hub<Self> {
&global.hubs.vulkan
}
- fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
- surface.raw.downcast_ref::<Self>()
+ fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
+ surface.vulkan.as_ref()
}
}
@@ -67,8 +67,8 @@ impl HalApi for hal::api::Metal {
fn hub(global: &Global) -> &Hub<Self> {
&global.hubs.metal
}
- fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
- surface.raw.downcast_ref::<Self>()
+ fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
+ surface.metal.as_ref()
}
}
@@ -88,8 +88,8 @@ impl HalApi for hal::api::Dx12 {
fn hub(global: &Global) -> &Hub<Self> {
&global.hubs.dx12
}
- fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
- surface.raw.downcast_ref::<Self>()
+ fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
+ surface.dx12.as_ref()
}
}
@@ -110,7 +110,7 @@ impl HalApi for hal::api::Gles {
fn hub(global: &Global) -> &Hub<Self> {
&global.hubs.gl
}
- fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
- surface.raw.downcast_ref::<Self>()
+ fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
+ surface.gl.as_ref()
}
}
diff --git a/third_party/rust/wgpu-core/src/hub.rs b/third_party/rust/wgpu-core/src/hub.rs
index 0f4589c8b3..eb57411d98 100644
--- a/third_party/rust/wgpu-core/src/hub.rs
+++ b/third_party/rust/wgpu-core/src/hub.rs
@@ -169,23 +169,23 @@ impl HubReport {
///
/// [`A::hub(global)`]: HalApi::hub
pub struct Hub<A: HalApi> {
- pub adapters: Registry<Adapter<A>>,
- pub devices: Registry<Device<A>>,
- pub queues: Registry<Queue<A>>,
- pub pipeline_layouts: Registry<PipelineLayout<A>>,
- pub shader_modules: Registry<ShaderModule<A>>,
- pub bind_group_layouts: Registry<BindGroupLayout<A>>,
- pub bind_groups: Registry<BindGroup<A>>,
- pub command_buffers: Registry<CommandBuffer<A>>,
- pub render_bundles: Registry<RenderBundle<A>>,
- pub render_pipelines: Registry<RenderPipeline<A>>,
- pub compute_pipelines: Registry<ComputePipeline<A>>,
- pub query_sets: Registry<QuerySet<A>>,
- pub buffers: Registry<Buffer<A>>,
- pub staging_buffers: Registry<StagingBuffer<A>>,
- pub textures: Registry<Texture<A>>,
- pub texture_views: Registry<TextureView<A>>,
- pub samplers: Registry<Sampler<A>>,
+ pub(crate) adapters: Registry<Adapter<A>>,
+ pub(crate) devices: Registry<Device<A>>,
+ pub(crate) queues: Registry<Queue<A>>,
+ pub(crate) pipeline_layouts: Registry<PipelineLayout<A>>,
+ pub(crate) shader_modules: Registry<ShaderModule<A>>,
+ pub(crate) bind_group_layouts: Registry<BindGroupLayout<A>>,
+ pub(crate) bind_groups: Registry<BindGroup<A>>,
+ pub(crate) command_buffers: Registry<CommandBuffer<A>>,
+ pub(crate) render_bundles: Registry<RenderBundle<A>>,
+ pub(crate) render_pipelines: Registry<RenderPipeline<A>>,
+ pub(crate) compute_pipelines: Registry<ComputePipeline<A>>,
+ pub(crate) query_sets: Registry<QuerySet<A>>,
+ pub(crate) buffers: Registry<Buffer<A>>,
+ pub(crate) staging_buffers: Registry<StagingBuffer<A>>,
+ pub(crate) textures: Registry<Texture<A>>,
+ pub(crate) texture_views: Registry<TextureView<A>>,
+ pub(crate) samplers: Registry<Sampler<A>>,
}
impl<A: HalApi> Hub<A> {
@@ -241,7 +241,7 @@ impl<A: HalApi> Hub<A> {
if let Element::Occupied(ref surface, _epoch) = *element {
if let Some(ref mut present) = surface.presentation.lock().take() {
if let Some(device) = present.device.downcast_ref::<A>() {
- let suf = A::get_surface(surface);
+ let suf = A::surface_as_hal(surface);
unsafe {
suf.unwrap().unconfigure(device.raw());
//TODO: we could destroy the surface here
diff --git a/third_party/rust/wgpu-core/src/id.rs b/third_party/rust/wgpu-core/src/id.rs
index 72b74218d0..1fa89f2bf0 100644
--- a/third_party/rust/wgpu-core/src/id.rs
+++ b/third_party/rust/wgpu-core/src/id.rs
@@ -91,8 +91,7 @@ pub fn as_option_slice<T: Marker>(ids: &[Id<T>]) -> &[Option<Id<T>>] {
/// An identifier for a wgpu object.
///
-/// An `Id<T>` value identifies a value stored in a [`Global`]'s [`Hub`]'s [`Storage`].
-/// `Storage` implements [`Index`] and [`IndexMut`], accepting `Id` values as indices.
+/// An `Id<T>` value identifies a value stored in a [`Global`]'s [`Hub`].
///
/// ## Note on `Id` typing
///
@@ -112,10 +111,7 @@ pub fn as_option_slice<T: Marker>(ids: &[Id<T>]) -> &[Option<Id<T>>] {
/// [`Global`]: crate::global::Global
/// [`Hub`]: crate::hub::Hub
/// [`Hub<A>`]: crate::hub::Hub
-/// [`Storage`]: crate::storage::Storage
/// [`Texture<A>`]: crate::resource::Texture
-/// [`Index`]: std::ops::Index
-/// [`IndexMut`]: std::ops::IndexMut
/// [`Registry`]: crate::hub::Registry
/// [`Empty`]: hal::api::Empty
#[repr(transparent)]
@@ -182,15 +178,6 @@ where
self.0.backend()
}
- /// Transmute this identifier to one with a different marker trait.
- ///
- /// Legal use is governed through a sealed trait, however it's correctness
- /// depends on the current implementation of `wgpu-core`.
- #[inline]
- pub const fn transmute<U: self::transmute::Transmute<T>>(self) -> Id<U> {
- Id(self.0, PhantomData)
- }
-
#[inline]
pub fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self {
Id(RawId::zip(index, epoch, backend), PhantomData)
@@ -202,20 +189,6 @@ where
}
}
-pub(crate) mod transmute {
- // This trait is effectively sealed to prevent illegal transmutes.
- pub trait Transmute<U>: super::Marker {}
-
- // Self-transmute is always legal.
- impl<T> Transmute<T> for T where T: super::Marker {}
-
- // TODO: Remove these once queues have their own identifiers.
- impl Transmute<super::markers::Queue> for super::markers::Device {}
- impl Transmute<super::markers::Device> for super::markers::Queue {}
- impl Transmute<super::markers::CommandBuffer> for super::markers::CommandEncoder {}
- impl Transmute<super::markers::CommandEncoder> for super::markers::CommandBuffer {}
-}
-
impl<T> Copy for Id<T> where T: Marker {}
impl<T> Clone for Id<T>
@@ -349,6 +322,24 @@ ids! {
pub type QuerySetId QuerySet;
}
+impl CommandEncoderId {
+ pub fn into_command_buffer_id(self) -> CommandBufferId {
+ Id(self.0, PhantomData)
+ }
+}
+
+impl CommandBufferId {
+ pub fn into_command_encoder_id(self) -> CommandEncoderId {
+ Id(self.0, PhantomData)
+ }
+}
+
+impl DeviceId {
+ pub fn into_queue_id(self) -> QueueId {
+ Id(self.0, PhantomData)
+ }
+}
+
#[test]
fn test_id_backend() {
for &b in &[
diff --git a/third_party/rust/wgpu-core/src/identity.rs b/third_party/rust/wgpu-core/src/identity.rs
index d76d29341a..c89731f7af 100644
--- a/third_party/rust/wgpu-core/src/identity.rs
+++ b/third_party/rust/wgpu-core/src/identity.rs
@@ -1,8 +1,8 @@
-use parking_lot::Mutex;
use wgt::Backend;
use crate::{
id::{Id, Marker},
+ lock::{rank, Mutex},
Epoch, Index,
};
use std::{fmt::Debug, marker::PhantomData};
@@ -16,31 +16,26 @@ enum IdSource {
/// A simple structure to allocate [`Id`] identifiers.
///
-/// Calling [`alloc`] returns a fresh, never-before-seen id. Calling [`free`]
+/// Calling [`alloc`] returns a fresh, never-before-seen id. Calling [`release`]
/// marks an id as dead; it will never be returned again by `alloc`.
///
-/// Use `IdentityManager::default` to construct new instances.
+/// `IdentityValues` returns `Id`s whose index values are suitable for use as
+/// indices into a `Vec<T>` that holds those ids' referents:
///
-/// `IdentityManager` returns `Id`s whose index values are suitable for use as
-/// indices into a `Storage<T>` that holds those ids' referents:
+/// - Every live id has a distinct index value. Every live id's index
+/// selects a distinct element in the vector.
///
-/// - Every live id has a distinct index value. Each live id's index selects a
-/// distinct element in the vector.
-///
-/// - `IdentityManager` prefers low index numbers. If you size your vector to
+/// - `IdentityValues` prefers low index numbers. If you size your vector to
/// accommodate the indices produced here, the vector's length will reflect
/// the highwater mark of actual occupancy.
///
-/// - `IdentityManager` reuses the index values of freed ids before returning
+/// - `IdentityValues` reuses the index values of freed ids before returning
/// ids with new index values. Freed vector entries get reused.
///
-/// See the module-level documentation for an overview of how this
-/// fits together.
-///
/// [`Id`]: crate::id::Id
/// [`Backend`]: wgt::Backend;
-/// [`alloc`]: IdentityManager::alloc
-/// [`free`]: IdentityManager::free
+/// [`alloc`]: IdentityValues::alloc
+/// [`release`]: IdentityValues::release
#[derive(Debug)]
pub(super) struct IdentityValues {
free: Vec<(Index, Epoch)>,
@@ -122,12 +117,15 @@ impl<T: Marker> IdentityManager<T> {
impl<T: Marker> IdentityManager<T> {
pub fn new() -> Self {
Self {
- values: Mutex::new(IdentityValues {
- free: Vec::new(),
- next_index: 0,
- count: 0,
- id_source: IdSource::None,
- }),
+ values: Mutex::new(
+ rank::IDENTITY_MANAGER_VALUES,
+ IdentityValues {
+ free: Vec::new(),
+ next_index: 0,
+ count: 0,
+ id_source: IdSource::None,
+ },
+ ),
_phantom: PhantomData,
}
}
diff --git a/third_party/rust/wgpu-core/src/instance.rs b/third_party/rust/wgpu-core/src/instance.rs
index b909245fac..f0a3890c1e 100644
--- a/third_party/rust/wgpu-core/src/instance.rs
+++ b/third_party/rust/wgpu-core/src/instance.rs
@@ -1,19 +1,19 @@
+use std::collections::HashMap;
use std::sync::Arc;
use crate::{
- any_surface::AnySurface,
api_log,
device::{queue::Queue, resource::Device, DeviceDescriptor},
global::Global,
hal_api::HalApi,
id::markers,
id::{AdapterId, DeviceId, Id, Marker, QueueId, SurfaceId},
+ lock::{rank, Mutex},
present::Presentation,
resource::{Resource, ResourceInfo, ResourceType},
resource_log, LabelHelpers, DOWNLEVEL_WARNING_MESSAGE,
};
-use parking_lot::Mutex;
use wgt::{Backend, Backends, PowerPreference};
use hal::{Adapter as _, Instance as _, OpenDevice};
@@ -21,6 +21,7 @@ use thiserror::Error;
pub type RequestAdapterOptions = wgt::RequestAdapterOptions<SurfaceId>;
type HalInstance<A> = <A as hal::Api>::Instance;
+type HalSurface<A> = <A as hal::Api>::Surface;
#[derive(Clone, Debug, Error)]
#[error("Limit '{name}' value {requested} is better than allowed {allowed}")]
@@ -113,31 +114,36 @@ impl Instance {
}
pub(crate) fn destroy_surface(&self, surface: Surface) {
- fn destroy<A: HalApi>(instance: &Option<A::Instance>, surface: AnySurface) {
- unsafe {
- if let Some(suf) = surface.take::<A>() {
- instance.as_ref().unwrap().destroy_surface(suf);
+ fn destroy<A: HalApi>(instance: &Option<A::Instance>, mut surface: Option<HalSurface<A>>) {
+ if let Some(surface) = surface.take() {
+ unsafe {
+ instance.as_ref().unwrap().destroy_surface(surface);
}
}
}
- match surface.raw.backend() {
- #[cfg(vulkan)]
- Backend::Vulkan => destroy::<hal::api::Vulkan>(&self.vulkan, surface.raw),
- #[cfg(metal)]
- Backend::Metal => destroy::<hal::api::Metal>(&self.metal, surface.raw),
- #[cfg(dx12)]
- Backend::Dx12 => destroy::<hal::api::Dx12>(&self.dx12, surface.raw),
- #[cfg(gles)]
- Backend::Gl => destroy::<hal::api::Gles>(&self.gl, surface.raw),
- _ => unreachable!(),
- }
+ #[cfg(vulkan)]
+ destroy::<hal::api::Vulkan>(&self.vulkan, surface.vulkan);
+ #[cfg(metal)]
+ destroy::<hal::api::Metal>(&self.metal, surface.metal);
+ #[cfg(dx12)]
+ destroy::<hal::api::Dx12>(&self.dx12, surface.dx12);
+ #[cfg(gles)]
+ destroy::<hal::api::Gles>(&self.gl, surface.gl);
}
}
pub struct Surface {
pub(crate) presentation: Mutex<Option<Presentation>>,
pub(crate) info: ResourceInfo<Surface>,
- pub(crate) raw: AnySurface,
+
+ #[cfg(vulkan)]
+ pub vulkan: Option<HalSurface<hal::api::Vulkan>>,
+ #[cfg(metal)]
+ pub metal: Option<HalSurface<hal::api::Metal>>,
+ #[cfg(dx12)]
+ pub dx12: Option<HalSurface<hal::api::Dx12>>,
+ #[cfg(gles)]
+ pub gl: Option<HalSurface<hal::api::Gles>>,
}
impl Resource for Surface {
@@ -163,7 +169,7 @@ impl Surface {
&self,
adapter: &Adapter<A>,
) -> Result<hal::SurfaceCapabilities, GetSurfaceSupportError> {
- let suf = A::get_surface(self).ok_or(GetSurfaceSupportError::Unsupported)?;
+ let suf = A::surface_as_hal(self).ok_or(GetSurfaceSupportError::Unsupported)?;
profiling::scope!("surface_capabilities");
let caps = unsafe {
adapter
@@ -203,7 +209,7 @@ impl<A: HalApi> Adapter<A> {
}
pub fn is_surface_supported(&self, surface: &Surface) -> bool {
- let suf = A::get_surface(surface);
+ let suf = A::surface_as_hal(surface);
// If get_surface returns None, then the API does not advertise support for the surface.
//
@@ -461,13 +467,25 @@ pub enum RequestAdapterError {
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum CreateSurfaceError {
- #[error("No backend is available")]
- NoSupportedBackend,
- #[error(transparent)]
- InstanceError(#[from] hal::InstanceError),
+ #[error("The backend {0} was not enabled on the instance.")]
+ BackendNotEnabled(Backend),
+ #[error("Failed to create surface for any enabled backend: {0:?}")]
+ FailedToCreateSurfaceForAnyBackend(HashMap<Backend, hal::InstanceError>),
}
impl Global {
+ /// Creates a new surface targeting the given display/window handles.
+ ///
+ /// Internally attempts to create hal surfaces for all enabled backends.
+ ///
+ /// Fails only if creation for surfaces for all enabled backends fails in which case
+ /// the error for each enabled backend is listed.
+ /// Vice versa, if creation for any backend succeeds, success is returned.
+ /// Surface creation errors are logged to the debug log in any case.
+ ///
+ /// id_in:
+ /// - If `Some`, the id to assign to the surface. A new one will be generated otherwise.
+ ///
/// # Safety
///
/// - `display_handle` must be a valid object to create a surface upon.
@@ -483,50 +501,86 @@ impl Global {
profiling::scope!("Instance::create_surface");
fn init<A: HalApi>(
+ errors: &mut HashMap<Backend, hal::InstanceError>,
+ any_created: &mut bool,
+ backend: Backend,
inst: &Option<A::Instance>,
display_handle: raw_window_handle::RawDisplayHandle,
window_handle: raw_window_handle::RawWindowHandle,
- ) -> Option<Result<AnySurface, hal::InstanceError>> {
- inst.as_ref().map(|inst| unsafe {
- match inst.create_surface(display_handle, window_handle) {
- Ok(raw) => Ok(AnySurface::new::<A>(raw)),
- Err(e) => Err(e),
+ ) -> Option<HalSurface<A>> {
+ inst.as_ref().and_then(|inst| {
+ match unsafe { inst.create_surface(display_handle, window_handle) } {
+ Ok(raw) => {
+ *any_created = true;
+ Some(raw)
+ }
+ Err(err) => {
+ log::debug!(
+ "Instance::create_surface: failed to create surface for {:?}: {:?}",
+ backend,
+ err
+ );
+ errors.insert(backend, err);
+ None
+ }
}
})
}
- let mut hal_surface: Option<Result<AnySurface, hal::InstanceError>> = None;
-
- #[cfg(vulkan)]
- if hal_surface.is_none() {
- hal_surface =
- init::<hal::api::Vulkan>(&self.instance.vulkan, display_handle, window_handle);
- }
- #[cfg(metal)]
- if hal_surface.is_none() {
- hal_surface =
- init::<hal::api::Metal>(&self.instance.metal, display_handle, window_handle);
- }
- #[cfg(dx12)]
- if hal_surface.is_none() {
- hal_surface =
- init::<hal::api::Dx12>(&self.instance.dx12, display_handle, window_handle);
- }
- #[cfg(gles)]
- if hal_surface.is_none() {
- hal_surface = init::<hal::api::Gles>(&self.instance.gl, display_handle, window_handle);
- }
-
- let hal_surface = hal_surface.ok_or(CreateSurfaceError::NoSupportedBackend)??;
+ let mut errors = HashMap::default();
+ let mut any_created = false;
let surface = Surface {
- presentation: Mutex::new(None),
+ presentation: Mutex::new(rank::SURFACE_PRESENTATION, None),
info: ResourceInfo::new("<Surface>", None),
- raw: hal_surface,
+
+ #[cfg(vulkan)]
+ vulkan: init::<hal::api::Vulkan>(
+ &mut errors,
+ &mut any_created,
+ Backend::Vulkan,
+ &self.instance.vulkan,
+ display_handle,
+ window_handle,
+ ),
+ #[cfg(metal)]
+ metal: init::<hal::api::Metal>(
+ &mut errors,
+ &mut any_created,
+ Backend::Metal,
+ &self.instance.metal,
+ display_handle,
+ window_handle,
+ ),
+ #[cfg(dx12)]
+ dx12: init::<hal::api::Dx12>(
+ &mut errors,
+ &mut any_created,
+ Backend::Dx12,
+ &self.instance.dx12,
+ display_handle,
+ window_handle,
+ ),
+ #[cfg(gles)]
+ gl: init::<hal::api::Gles>(
+ &mut errors,
+ &mut any_created,
+ Backend::Gl,
+ &self.instance.gl,
+ display_handle,
+ window_handle,
+ ),
};
- let (id, _) = self.surfaces.prepare(id_in).assign(surface);
- Ok(id)
+ if any_created {
+ #[allow(clippy::arc_with_non_send_sync)]
+ let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
+ Ok(id)
+ } else {
+ Err(CreateSurfaceError::FailedToCreateSurfaceForAnyBackend(
+ errors,
+ ))
+ }
}
/// # Safety
@@ -537,29 +591,57 @@ impl Global {
&self,
layer: *mut std::ffi::c_void,
id_in: Option<SurfaceId>,
- ) -> SurfaceId {
+ ) -> Result<SurfaceId, CreateSurfaceError> {
profiling::scope!("Instance::create_surface_metal");
let surface = Surface {
- presentation: Mutex::new(None),
+ presentation: Mutex::new(rank::SURFACE_PRESENTATION, None),
info: ResourceInfo::new("<Surface>", None),
- raw: {
- let hal_surface = self
- .instance
- .metal
+ metal: Some(self.instance.metal.as_ref().map_or(
+ Err(CreateSurfaceError::BackendNotEnabled(Backend::Metal)),
+ |inst| {
+ // we don't want to link to metal-rs for this
+ #[allow(clippy::transmute_ptr_to_ref)]
+ Ok(inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) }))
+ },
+ )?),
+ #[cfg(dx12)]
+ dx12: None,
+ #[cfg(vulkan)]
+ vulkan: None,
+ #[cfg(gles)]
+ gl: None,
+ };
+
+ let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
+ Ok(id)
+ }
+
+ #[cfg(dx12)]
+ fn instance_create_surface_dx12(
+ &self,
+ id_in: Option<SurfaceId>,
+ create_surface_func: impl FnOnce(&HalInstance<hal::api::Dx12>) -> HalSurface<hal::api::Dx12>,
+ ) -> Result<SurfaceId, CreateSurfaceError> {
+ let surface = Surface {
+ presentation: Mutex::new(rank::SURFACE_PRESENTATION, None),
+ info: ResourceInfo::new("<Surface>", None),
+ dx12: Some(create_surface_func(
+ self.instance
+ .dx12
.as_ref()
- .map(|inst| {
- // we don't want to link to metal-rs for this
- #[allow(clippy::transmute_ptr_to_ref)]
- inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) })
- })
- .unwrap();
- AnySurface::new::<hal::api::Metal>(hal_surface)
- },
+ .ok_or(CreateSurfaceError::BackendNotEnabled(Backend::Dx12))?,
+ )),
+ #[cfg(metal)]
+ metal: None,
+ #[cfg(vulkan)]
+ vulkan: None,
+ #[cfg(gles)]
+ gl: None,
};
- let (id, _) = self.surfaces.prepare(id_in).assign(surface);
- id
+ let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
+ Ok(id)
}
#[cfg(dx12)]
@@ -570,25 +652,11 @@ impl Global {
&self,
visual: *mut std::ffi::c_void,
id_in: Option<SurfaceId>,
- ) -> SurfaceId {
+ ) -> Result<SurfaceId, CreateSurfaceError> {
profiling::scope!("Instance::instance_create_surface_from_visual");
-
- let surface = Surface {
- presentation: Mutex::new(None),
- info: ResourceInfo::new("<Surface>", None),
- raw: {
- let hal_surface = self
- .instance
- .dx12
- .as_ref()
- .map(|inst| unsafe { inst.create_surface_from_visual(visual as _) })
- .unwrap();
- AnySurface::new::<hal::api::Dx12>(hal_surface)
- },
- };
-
- let (id, _) = self.surfaces.prepare(id_in).assign(surface);
- id
+ self.instance_create_surface_dx12(id_in, |inst| unsafe {
+ inst.create_surface_from_visual(visual as _)
+ })
}
#[cfg(dx12)]
@@ -599,25 +667,11 @@ impl Global {
&self,
surface_handle: *mut std::ffi::c_void,
id_in: Option<SurfaceId>,
- ) -> SurfaceId {
+ ) -> Result<SurfaceId, CreateSurfaceError> {
profiling::scope!("Instance::instance_create_surface_from_surface_handle");
-
- let surface = Surface {
- presentation: Mutex::new(None),
- info: ResourceInfo::new("<Surface>", None),
- raw: {
- let hal_surface = self
- .instance
- .dx12
- .as_ref()
- .map(|inst| unsafe { inst.create_surface_from_surface_handle(surface_handle) })
- .unwrap();
- AnySurface::new::<hal::api::Dx12>(hal_surface)
- },
- };
-
- let (id, _) = self.surfaces.prepare(id_in).assign(surface);
- id
+ self.instance_create_surface_dx12(id_in, |inst| unsafe {
+ inst.create_surface_from_surface_handle(surface_handle)
+ })
}
#[cfg(dx12)]
@@ -628,27 +682,11 @@ impl Global {
&self,
swap_chain_panel: *mut std::ffi::c_void,
id_in: Option<SurfaceId>,
- ) -> SurfaceId {
+ ) -> Result<SurfaceId, CreateSurfaceError> {
profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel");
-
- let surface = Surface {
- presentation: Mutex::new(None),
- info: ResourceInfo::new("<Surface>", None),
- raw: {
- let hal_surface = self
- .instance
- .dx12
- .as_ref()
- .map(|inst| unsafe {
- inst.create_surface_from_swap_chain_panel(swap_chain_panel as _)
- })
- .unwrap();
- AnySurface::new::<hal::api::Dx12>(hal_surface)
- },
- };
-
- let (id, _) = self.surfaces.prepare(id_in).assign(surface);
- id
+ self.instance_create_surface_dx12(id_in, |inst| unsafe {
+ inst.create_surface_from_swap_chain_panel(swap_chain_panel as _)
+ })
}
pub fn surface_drop(&self, id: SurfaceId) {
@@ -656,32 +694,34 @@ impl Global {
api_log!("Surface::drop {id:?}");
- fn unconfigure<A: HalApi>(global: &Global, surface: &AnySurface, present: &Presentation) {
- let hub = HalApi::hub(global);
- if let Some(hal_surface) = surface.downcast_ref::<A>() {
+ fn unconfigure<A: HalApi>(
+ global: &Global,
+ surface: &Option<HalSurface<A>>,
+ present: &Presentation,
+ ) {
+ if let Some(surface) = surface {
+ let hub = HalApi::hub(global);
if let Some(device) = present.device.downcast_ref::<A>() {
- hub.surface_unconfigure(device, hal_surface);
+ hub.surface_unconfigure(device, surface);
}
}
}
let surface = self.surfaces.unregister(id);
- if let Some(surface) = Arc::into_inner(surface.unwrap()) {
- if let Some(present) = surface.presentation.lock().take() {
- #[cfg(vulkan)]
- unconfigure::<hal::api::Vulkan>(self, &surface.raw, &present);
- #[cfg(metal)]
- unconfigure::<hal::api::Metal>(self, &surface.raw, &present);
- #[cfg(dx12)]
- unconfigure::<hal::api::Dx12>(self, &surface.raw, &present);
- #[cfg(gles)]
- unconfigure::<hal::api::Gles>(self, &surface.raw, &present);
- }
+ let surface = Arc::into_inner(surface.unwrap())
+ .expect("Surface cannot be destroyed because is still in use");
- self.instance.destroy_surface(surface);
- } else {
- panic!("Surface cannot be destroyed because is still in use");
+ if let Some(present) = surface.presentation.lock().take() {
+ #[cfg(vulkan)]
+ unconfigure::<hal::api::Vulkan>(self, &surface.vulkan, &present);
+ #[cfg(metal)]
+ unconfigure::<hal::api::Metal>(self, &surface.metal, &present);
+ #[cfg(dx12)]
+ unconfigure::<hal::api::Dx12>(self, &surface.dx12, &present);
+ #[cfg(gles)]
+ unconfigure::<hal::api::Gles>(self, &surface.gl, &present);
}
+ self.instance.destroy_surface(surface);
}
fn enumerate<A: HalApi>(
@@ -707,7 +747,7 @@ impl Global {
for raw in hal_adapters {
let adapter = Adapter::new(raw);
log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info);
- let (id, _) = hub.adapters.prepare(id_backend).assign(adapter);
+ let (id, _) = hub.adapters.prepare(id_backend).assign(Arc::new(adapter));
list.push(id);
}
}
@@ -754,7 +794,10 @@ impl Global {
None => {
let adapter = Adapter::new(list.swap_remove(*selected));
log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info);
- let (id, _) = HalApi::hub(self).adapters.prepare(new_id).assign(adapter);
+ let (id, _) = HalApi::hub(self)
+ .adapters
+ .prepare(new_id)
+ .assign(Arc::new(adapter));
Some(id)
}
}
@@ -784,7 +827,7 @@ impl Global {
adapters.retain(|exposed| exposed.info.device_type == wgt::DeviceType::Cpu);
}
if let Some(surface) = compatible_surface {
- let surface = &A::get_surface(surface);
+ let surface = &A::surface_as_hal(surface);
adapters.retain(|exposed| unsafe {
// If the surface does not exist for this backend,
// then the surface is not supported.
@@ -937,13 +980,13 @@ impl Global {
let (id, _adapter): (_, Arc<Adapter<A>>) = match A::VARIANT {
#[cfg(vulkan)]
- Backend::Vulkan => fid.assign(Adapter::new(hal_adapter)),
+ Backend::Vulkan => fid.assign(Arc::new(Adapter::new(hal_adapter))),
#[cfg(metal)]
- Backend::Metal => fid.assign(Adapter::new(hal_adapter)),
+ Backend::Metal => fid.assign(Arc::new(Adapter::new(hal_adapter))),
#[cfg(dx12)]
- Backend::Dx12 => fid.assign(Adapter::new(hal_adapter)),
+ Backend::Dx12 => fid.assign(Arc::new(Adapter::new(hal_adapter))),
#[cfg(gles)]
- Backend::Gl => fid.assign(Adapter::new(hal_adapter)),
+ Backend::Gl => fid.assign(Arc::new(Adapter::new(hal_adapter))),
_ => unreachable!(),
};
resource_log!("Created Adapter {:?}", id);
@@ -1066,13 +1109,13 @@ impl Global {
Ok((device, queue)) => (device, queue),
Err(e) => break e,
};
- let (device_id, _) = device_fid.assign(device);
+ let (device_id, _) = device_fid.assign(Arc::new(device));
resource_log!("Created Device {:?}", device_id);
let device = hub.devices.get(device_id).unwrap();
queue.device = Some(device.clone());
- let (queue_id, queue) = queue_fid.assign(queue);
+ let (queue_id, queue) = queue_fid.assign(Arc::new(queue));
resource_log!("Created Queue {:?}", queue_id);
device.set_queue(queue);
@@ -1118,13 +1161,13 @@ impl Global {
Ok(device) => device,
Err(e) => break e,
};
- let (device_id, _) = devices_fid.assign(device);
+ let (device_id, _) = devices_fid.assign(Arc::new(device));
resource_log!("Created Device {:?}", device_id);
let device = hub.devices.get(device_id).unwrap();
queue.device = Some(device.clone());
- let (queue_id, queue) = queues_fid.assign(queue);
+ let (queue_id, queue) = queues_fid.assign(Arc::new(queue));
resource_log!("Created Queue {:?}", queue_id);
device.set_queue(queue);
diff --git a/third_party/rust/wgpu-core/src/lib.rs b/third_party/rust/wgpu-core/src/lib.rs
index 5454f0d682..032d85a4bc 100644
--- a/third_party/rust/wgpu-core/src/lib.rs
+++ b/third_party/rust/wgpu-core/src/lib.rs
@@ -39,6 +39,8 @@
unused_braces,
// It gets in the way a lot and does not prevent bugs in practice.
clippy::pattern_type_mismatch,
+ // `wgpu-core` isn't entirely user-facing, so it's useful to document internal items.
+ rustdoc::private_intra_doc_links
)]
#![warn(
trivial_casts,
@@ -48,7 +50,6 @@
unused_qualifications
)]
-pub mod any_surface;
pub mod binding_model;
pub mod command;
mod conv;
@@ -62,6 +63,7 @@ pub mod id;
pub mod identity;
mod init_tracker;
pub mod instance;
+mod lock;
pub mod pipeline;
mod pool;
pub mod present;
diff --git a/third_party/rust/wgpu-core/src/lock/mod.rs b/third_party/rust/wgpu-core/src/lock/mod.rs
new file mode 100644
index 0000000000..a6593a062d
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/lock/mod.rs
@@ -0,0 +1,41 @@
+//! Instrumented lock types.
+//!
+//! This module defines a set of instrumented wrappers for the lock
+//! types used in `wgpu-core` ([`Mutex`], [`RwLock`], and
+//! [`SnatchLock`]) that help us understand and validate `wgpu-core`
+//! synchronization.
+//!
+//! - The [`ranked`] module defines lock types that perform run-time
+//! checks to ensure that each thread acquires locks only in a
+//! specific order, to prevent deadlocks.
+//!
+//! - The [`vanilla`] module defines lock types that are
+//! uninstrumented, no-overhead wrappers around the standard lock
+//! types.
+//!
+//! (We plan to add more wrappers in the future.)
+//!
+//! If the `wgpu_validate_locks` config is set (for example, with
+//! `RUSTFLAGS='--cfg wgpu_validate_locks'`), `wgpu-core` uses the
+//! [`ranked`] module's locks. We hope to make this the default for
+//! debug builds soon.
+//!
+//! Otherwise, `wgpu-core` uses the [`vanilla`] module's locks.
+//!
+//! [`Mutex`]: parking_lot::Mutex
+//! [`RwLock`]: parking_lot::RwLock
+//! [`SnatchLock`]: crate::snatch::SnatchLock
+
+pub mod rank;
+
+#[cfg_attr(not(wgpu_validate_locks), allow(dead_code))]
+mod ranked;
+
+#[cfg_attr(wgpu_validate_locks, allow(dead_code))]
+mod vanilla;
+
+#[cfg(wgpu_validate_locks)]
+pub use ranked::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
+
+#[cfg(not(wgpu_validate_locks))]
+pub use vanilla::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
diff --git a/third_party/rust/wgpu-core/src/lock/rank.rs b/third_party/rust/wgpu-core/src/lock/rank.rs
new file mode 100644
index 0000000000..4387b8d138
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/lock/rank.rs
@@ -0,0 +1,170 @@
+//! Ranks for `wgpu-core` locks, restricting acquisition order.
+//!
+//! See [`LockRank`].
+
+/// The rank of a lock.
+///
+/// Each [`Mutex`], [`RwLock`], and [`SnatchLock`] in `wgpu-core` has been
+/// assigned a *rank*: a node in the DAG defined at the bottom of
+/// `wgpu-core/src/lock/rank.rs`. The rank of the most recently
+/// acquired lock you are still holding determines which locks you may
+/// attempt to acquire next.
+///
+/// When you create a lock in `wgpu-core`, you must specify its rank
+/// by passing in a [`LockRank`] value. This module declares a
+/// pre-defined set of ranks to cover everything in `wgpu-core`, named
+/// after the type in which they occur, and the name of the type's
+/// field that is a lock. For example, [`CommandBuffer::data`] is a
+/// `Mutex`, and its rank here is the constant
+/// [`COMMAND_BUFFER_DATA`].
+///
+/// [`Mutex`]: parking_lot::Mutex
+/// [`RwLock`]: parking_lot::RwLock
+/// [`SnatchLock`]: crate::snatch::SnatchLock
+/// [`CommandBuffer::data`]: crate::command::CommandBuffer::data
+#[derive(Debug, Copy, Clone)]
+pub struct LockRank {
+ /// The bit representing this lock.
+ ///
+ /// There should only be a single bit set in this value.
+ pub(super) bit: LockRankSet,
+
+ /// A bitmask of permitted successor ranks.
+ ///
+ /// If `rank` is the rank of the most recently acquired lock we
+ /// are still holding, then `rank.followers` is the mask of
+ /// locks we are allowed to acquire next.
+ ///
+ /// The `define_lock_ranks!` macro ensures that there are no
+ /// cycles in the graph of lock ranks and their followers.
+ pub(super) followers: LockRankSet,
+}
+
+/// Define a set of lock ranks, and each rank's permitted successors.
+macro_rules! define_lock_ranks {
+ {
+ $(
+ $( #[ $attr:meta ] )*
+ rank $name:ident $member:literal followed by { $( $follower:ident ),* $(,)? }
+ )*
+ } => {
+ // An enum that assigns a unique number to each rank.
+ #[allow(non_camel_case_types, clippy::upper_case_acronyms)]
+ enum LockRankNumber { $( $name, )* }
+
+ bitflags::bitflags! {
+ #[derive(Debug, Copy, Clone, Eq, PartialEq)]
+ /// A bitflags type representing a set of lock ranks.
+ pub struct LockRankSet: u64 {
+ $(
+ const $name = 1 << (LockRankNumber:: $name as u64);
+ )*
+ }
+ }
+
+ impl LockRankSet {
+ pub fn name(self) -> &'static str {
+ match self {
+ $(
+ LockRankSet:: $name => $member,
+ )*
+ _ => "<unrecognized LockRankSet bit>",
+ }
+ }
+ }
+
+ $(
+ // If there is any cycle in the ranking, the initializers
+ // for `followers` will be cyclic, and rustc will give us
+ // an error message explaining the cycle.
+ $( #[ $attr ] )*
+ pub const $name: LockRank = LockRank {
+ bit: LockRankSet:: $name,
+ followers: LockRankSet::empty() $( .union($follower.bit) )*,
+ };
+ )*
+ }
+}
+
+define_lock_ranks! {
+ rank DEVICE_TEMP_SUSPECTED "Device::temp_suspected" followed by {
+ SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
+ COMMAND_BUFFER_DATA,
+ DEVICE_TRACKERS,
+ }
+ rank COMMAND_BUFFER_DATA "CommandBuffer::data" followed by {
+ DEVICE_SNATCHABLE_LOCK,
+ DEVICE_USAGE_SCOPES,
+ SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
+ BUFFER_BIND_GROUP_STATE_BUFFERS,
+ TEXTURE_BIND_GROUP_STATE_TEXTURES,
+ BUFFER_MAP_STATE,
+ STATELESS_BIND_GROUP_STATE_RESOURCES,
+ }
+ rank DEVICE_SNATCHABLE_LOCK "Device::snatchable_lock" followed by {
+ SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
+ DEVICE_TRACE,
+ BUFFER_MAP_STATE,
+ BUFFER_BIND_GROUP_STATE_BUFFERS,
+ TEXTURE_BIND_GROUP_STATE_TEXTURES,
+ STATELESS_BIND_GROUP_STATE_RESOURCES,
+ // Uncomment this to see an interesting cycle.
+ // COMMAND_BUFFER_DATA,
+ }
+ rank BUFFER_MAP_STATE "Buffer::map_state" followed by {
+ DEVICE_PENDING_WRITES,
+ SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
+ DEVICE_TRACE,
+ }
+ rank DEVICE_PENDING_WRITES "Device::pending_writes" followed by {
+ COMMAND_ALLOCATOR_FREE_ENCODERS,
+ SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
+ DEVICE_LIFE_TRACKER,
+ }
+ rank DEVICE_LIFE_TRACKER "Device::life_tracker" followed by {
+ COMMAND_ALLOCATOR_FREE_ENCODERS,
+ // Uncomment this to see an interesting cycle.
+ // DEVICE_TEMP_SUSPECTED,
+ DEVICE_TRACE,
+ }
+ rank COMMAND_ALLOCATOR_FREE_ENCODERS "CommandAllocator::free_encoders" followed by {
+ SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
+ }
+
+ rank BUFFER_BIND_GROUPS "Buffer::bind_groups" followed by { }
+ rank BUFFER_BIND_GROUP_STATE_BUFFERS "BufferBindGroupState::buffers" followed by { }
+ rank BUFFER_INITIALIZATION_STATUS "Buffer::initialization_status" followed by { }
+ rank BUFFER_SYNC_MAPPED_WRITES "Buffer::sync_mapped_writes" followed by { }
+ rank DEVICE_DEFERRED_DESTROY "Device::deferred_destroy" followed by { }
+ rank DEVICE_FENCE "Device::fence" followed by { }
+ #[allow(dead_code)]
+ rank DEVICE_TRACE "Device::trace" followed by { }
+ rank DEVICE_TRACKERS "Device::trackers" followed by { }
+ rank DEVICE_USAGE_SCOPES "Device::usage_scopes" followed by { }
+ rank IDENTITY_MANAGER_VALUES "IdentityManager::values" followed by { }
+ rank REGISTRY_STORAGE "Registry::storage" followed by { }
+ rank RENDER_BUNDLE_SCOPE_BUFFERS "RenderBundleScope::buffers" followed by { }
+ rank RENDER_BUNDLE_SCOPE_TEXTURES "RenderBundleScope::textures" followed by { }
+ rank RENDER_BUNDLE_SCOPE_BIND_GROUPS "RenderBundleScope::bind_groups" followed by { }
+ rank RENDER_BUNDLE_SCOPE_RENDER_PIPELINES "RenderBundleScope::render_pipelines" followed by { }
+ rank RENDER_BUNDLE_SCOPE_QUERY_SETS "RenderBundleScope::query_sets" followed by { }
+ rank RESOURCE_POOL_INNER "ResourcePool::inner" followed by { }
+ rank SHARED_TRACKER_INDEX_ALLOCATOR_INNER "SharedTrackerIndexAllocator::inner" followed by { }
+ rank STAGING_BUFFER_RAW "StagingBuffer::raw" followed by { }
+ rank STATELESS_BIND_GROUP_STATE_RESOURCES "StatelessBindGroupState::resources" followed by { }
+ rank SURFACE_PRESENTATION "Surface::presentation" followed by { }
+ rank TEXTURE_BIND_GROUPS "Texture::bind_groups" followed by { }
+ rank TEXTURE_BIND_GROUP_STATE_TEXTURES "TextureBindGroupState::textures" followed by { }
+ rank TEXTURE_INITIALIZATION_STATUS "Texture::initialization_status" followed by { }
+ rank TEXTURE_CLEAR_MODE "Texture::clear_mode" followed by { }
+ rank TEXTURE_VIEWS "Texture::views" followed by { }
+
+ #[cfg(test)]
+ rank PAWN "pawn" followed by { ROOK, BISHOP }
+ #[cfg(test)]
+ rank ROOK "rook" followed by { KNIGHT }
+ #[cfg(test)]
+ rank KNIGHT "knight" followed by { }
+ #[cfg(test)]
+ rank BISHOP "bishop" followed by { }
+}
diff --git a/third_party/rust/wgpu-core/src/lock/ranked.rs b/third_party/rust/wgpu-core/src/lock/ranked.rs
new file mode 100644
index 0000000000..4237116c2c
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/lock/ranked.rs
@@ -0,0 +1,397 @@
+//! Lock types that enforce well-ranked lock acquisition order.
+//!
+//! This module's [`Mutex`] and [`RwLock` types are instrumented to check that
+//! `wgpu-core` acquires locks according to their rank, to prevent deadlocks. To
+//! use it, put `--cfg wgpu_validate_locks` in `RUSTFLAGS`.
+//!
+//! The [`LockRank`] constants in the [`lock::rank`] module describe edges in a
+//! directed graph of lock acquisitions: each lock's rank says, if this is the most
+//! recently acquired lock that you are still holding, then these are the locks you
+//! are allowed to acquire next.
+//!
+//! As long as this graph doesn't have cycles, any number of threads can acquire
+//! locks along paths through the graph without deadlock:
+//!
+//! - Assume that if a thread is holding a lock, then it will either release it,
+//! or block trying to acquire another one. No thread just sits on its locks
+//! forever for unrelated reasons. If it did, then that would be a source of
+//! deadlock "outside the system" that we can't do anything about.
+//!
+//! - This module asserts that threads acquire and release locks in a stack-like
+//! order: a lock is dropped only when it is the *most recently acquired* lock
+//! *still held* - call this the "youngest" lock. This stack-like ordering
+//! isn't a Rust requirement; Rust lets you drop guards in any order you like.
+//! This is a restriction we impose.
+//!
+//! - Consider the directed graph whose nodes are locks, and whose edges go from
+//! each lock to its permitted followers, the locks in its [`LockRank::followers`]
+//! set. The definition of the [`lock::rank`] module's [`LockRank`] constants
+//! ensures that this graph has no cycles, including trivial cycles from a node to
+//! itself.
+//!
+//! - This module then asserts that each thread attempts to acquire a lock only if
+//! it is among its youngest lock's permitted followers. Thus, as a thread
+//! acquires locks, it must be traversing a path through the graph along its
+//! edges.
+//!
+//! - Because there are no cycles in the graph, whenever one thread is blocked
+//! waiting to acquire a lock, that lock must be held by a different thread: if
+//! you were allowed to acquire a lock you already hold, that would be a cycle in
+//! the graph.
+//!
+//! - Furthermore, because the graph has no cycles, as we work our way from each
+//! thread to the thread it is blocked waiting for, we must eventually reach an
+//! end point: there must be some thread that is able to acquire its next lock, or
+//! that is about to release a lock.
+//!
+//! Thus, the system as a whole is always able to make progress: it is free of
+//! deadlocks.
+//!
+//! Note that this validation only monitors each thread's behavior in isolation:
+//! there's only thread-local state, nothing communicated between threads. So we
+//! don't detect deadlocks, per se, only the potential to cause deadlocks. This
+//! means that the validation is conservative, but more reproducible, since it's not
+//! dependent on any particular interleaving of execution.
+//!
+//! [`lock::rank`]: crate::lock::rank
+
+use super::rank::LockRank;
+use std::{cell::Cell, panic::Location};
+
+/// A `Mutex` instrumented for deadlock prevention.
+///
+/// This is just a wrapper around a [`parking_lot::Mutex`], along with
+/// its rank in the `wgpu_core` lock ordering.
+///
+/// For details, see [the module documentation][mod].
+///
+/// [mod]: crate::lock::ranked
+pub struct Mutex<T> {
+ inner: parking_lot::Mutex<T>,
+ rank: LockRank,
+}
+
+/// A guard produced by locking [`Mutex`].
+///
+/// This is just a wrapper around a [`parking_lot::MutexGuard`], along
+/// with the state needed to track lock acquisition.
+///
+/// For details, see [the module documentation][mod].
+///
+/// [mod]: crate::lock::ranked
+pub struct MutexGuard<'a, T> {
+ inner: parking_lot::MutexGuard<'a, T>,
+ saved: LockStateGuard,
+}
+
+thread_local! {
+ static LOCK_STATE: Cell<LockState> = const { Cell::new(LockState::INITIAL) };
+}
+
+/// Per-thread state for the deadlock checker.
+#[derive(Debug, Copy, Clone)]
+struct LockState {
+ /// The last lock we acquired, and where.
+ last_acquired: Option<(LockRank, &'static Location<'static>)>,
+
+ /// The number of locks currently held.
+ ///
+ /// This is used to enforce stack-like lock acquisition and release.
+ depth: u32,
+}
+
+impl LockState {
+ const INITIAL: LockState = LockState {
+ last_acquired: None,
+ depth: 0,
+ };
+}
+
+/// A container that restores a [`LockState`] when dropped.
+///
+/// This type serves two purposes:
+///
+/// - Operations like `RwLockWriteGuard::downgrade` would like to be able to
+/// destructure lock guards and reassemble their pieces into new guards, but
+/// if the guard type itself implements `Drop`, we can't destructure it
+/// without unsafe code or pointless `Option`s whose state is almost always
+/// statically known.
+///
+/// - We can just implement `Drop` for this type once, and then use it in lock
+/// guards, rather than implementing `Drop` separately for each guard type.
+struct LockStateGuard(LockState);
+
+impl Drop for LockStateGuard {
+ fn drop(&mut self) {
+ release(self.0)
+ }
+}
+
+/// Check and record the acquisition of a lock with `new_rank`.
+///
+/// Check that acquiring a lock with `new_rank` is permitted at this point, and
+/// update the per-thread state accordingly.
+///
+/// Return the `LockState` that must be restored when this thread is released.
+fn acquire(new_rank: LockRank, location: &'static Location<'static>) -> LockState {
+ let state = LOCK_STATE.get();
+ // Initially, it's fine to acquire any lock. So we only
+ // need to check when `last_acquired` is `Some`.
+ if let Some((ref last_rank, ref last_location)) = state.last_acquired {
+ assert!(
+ last_rank.followers.contains(new_rank.bit),
+ "Attempt to acquire nested mutexes in wrong order:\n\
+ last locked {:<35} at {}\n\
+ now locking {:<35} at {}\n\
+ Locking {} after locking {} is not permitted.",
+ last_rank.bit.name(),
+ last_location,
+ new_rank.bit.name(),
+ location,
+ new_rank.bit.name(),
+ last_rank.bit.name(),
+ );
+ }
+ LOCK_STATE.set(LockState {
+ last_acquired: Some((new_rank, location)),
+ depth: state.depth + 1,
+ });
+ state
+}
+
+/// Record the release of a lock whose saved state was `saved`.
+///
+/// Check that locks are being acquired in stacking order, and update the
+/// per-thread state accordingly.
+fn release(saved: LockState) {
+ let prior = LOCK_STATE.replace(saved);
+
+ // Although Rust allows mutex guards to be dropped in any
+ // order, this analysis requires that locks be acquired and
+ // released in stack order: the next lock to be released must be
+ // the most recently acquired lock still held.
+ assert_eq!(
+ prior.depth,
+ saved.depth + 1,
+ "Lock not released in stacking order"
+ );
+}
+
+impl<T> Mutex<T> {
+ pub fn new(rank: LockRank, value: T) -> Mutex<T> {
+ Mutex {
+ inner: parking_lot::Mutex::new(value),
+ rank,
+ }
+ }
+
+ #[track_caller]
+ pub fn lock(&self) -> MutexGuard<T> {
+ let saved = acquire(self.rank, Location::caller());
+ MutexGuard {
+ inner: self.inner.lock(),
+ saved: LockStateGuard(saved),
+ }
+ }
+}
+
+impl<'a, T> std::ops::Deref for MutexGuard<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ self.inner.deref()
+ }
+}
+
+impl<'a, T> std::ops::DerefMut for MutexGuard<'a, T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.inner.deref_mut()
+ }
+}
+
+impl<T: std::fmt::Debug> std::fmt::Debug for Mutex<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.inner.fmt(f)
+ }
+}
+
+/// An `RwLock` instrumented for deadlock prevention.
+///
+/// This is just a wrapper around a [`parking_lot::RwLock`], along with
+/// its rank in the `wgpu_core` lock ordering.
+///
+/// For details, see [the module documentation][mod].
+///
+/// [mod]: crate::lock::ranked
+pub struct RwLock<T> {
+ inner: parking_lot::RwLock<T>,
+ rank: LockRank,
+}
+
+/// A read guard produced by locking [`RwLock`] for reading.
+///
+/// This is just a wrapper around a [`parking_lot::RwLockReadGuard`], along with
+/// the state needed to track lock acquisition.
+///
+/// For details, see [the module documentation][mod].
+///
+/// [mod]: crate::lock::ranked
+pub struct RwLockReadGuard<'a, T> {
+ inner: parking_lot::RwLockReadGuard<'a, T>,
+ saved: LockStateGuard,
+}
+
+/// A write guard produced by locking [`RwLock`] for writing.
+///
+/// This is just a wrapper around a [`parking_lot::RwLockWriteGuard`], along
+/// with the state needed to track lock acquisition.
+///
+/// For details, see [the module documentation][mod].
+///
+/// [mod]: crate::lock::ranked
+pub struct RwLockWriteGuard<'a, T> {
+ inner: parking_lot::RwLockWriteGuard<'a, T>,
+ saved: LockStateGuard,
+}
+
+impl<T> RwLock<T> {
+ pub fn new(rank: LockRank, value: T) -> RwLock<T> {
+ RwLock {
+ inner: parking_lot::RwLock::new(value),
+ rank,
+ }
+ }
+
+ #[track_caller]
+ pub fn read(&self) -> RwLockReadGuard<T> {
+ let saved = acquire(self.rank, Location::caller());
+ RwLockReadGuard {
+ inner: self.inner.read(),
+ saved: LockStateGuard(saved),
+ }
+ }
+
+ #[track_caller]
+ pub fn write(&self) -> RwLockWriteGuard<T> {
+ let saved = acquire(self.rank, Location::caller());
+ RwLockWriteGuard {
+ inner: self.inner.write(),
+ saved: LockStateGuard(saved),
+ }
+ }
+}
+
+impl<'a, T> RwLockWriteGuard<'a, T> {
+ pub fn downgrade(this: Self) -> RwLockReadGuard<'a, T> {
+ RwLockReadGuard {
+ inner: parking_lot::RwLockWriteGuard::downgrade(this.inner),
+ saved: this.saved,
+ }
+ }
+}
+
+impl<T: std::fmt::Debug> std::fmt::Debug for RwLock<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.inner.fmt(f)
+ }
+}
+
+impl<'a, T> std::ops::Deref for RwLockReadGuard<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ self.inner.deref()
+ }
+}
+
+impl<'a, T> std::ops::Deref for RwLockWriteGuard<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ self.inner.deref()
+ }
+}
+
+impl<'a, T> std::ops::DerefMut for RwLockWriteGuard<'a, T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.inner.deref_mut()
+ }
+}
+
+/// Locks can be acquired in the order indicated by their ranks.
+#[test]
+fn permitted() {
+ use super::rank;
+
+ let lock1 = Mutex::new(rank::PAWN, ());
+ let lock2 = Mutex::new(rank::ROOK, ());
+
+ let _guard1 = lock1.lock();
+ let _guard2 = lock2.lock();
+}
+
+/// Locks can only be acquired in the order indicated by their ranks.
+#[test]
+#[should_panic(expected = "Locking pawn after locking rook")]
+fn forbidden_unrelated() {
+ use super::rank;
+
+ let lock1 = Mutex::new(rank::ROOK, ());
+ let lock2 = Mutex::new(rank::PAWN, ());
+
+ let _guard1 = lock1.lock();
+ let _guard2 = lock2.lock();
+}
+
+/// Lock acquisitions can't skip ranks.
+///
+/// These two locks *could* be acquired in this order, but only if other locks
+/// are acquired in between them. Skipping ranks isn't allowed.
+#[test]
+#[should_panic(expected = "Locking knight after locking pawn")]
+fn forbidden_skip() {
+ use super::rank;
+
+ let lock1 = Mutex::new(rank::PAWN, ());
+ let lock2 = Mutex::new(rank::KNIGHT, ());
+
+ let _guard1 = lock1.lock();
+ let _guard2 = lock2.lock();
+}
+
+/// Locks can be acquired and released in a stack-like order.
+#[test]
+fn stack_like() {
+ use super::rank;
+
+ let lock1 = Mutex::new(rank::PAWN, ());
+ let lock2 = Mutex::new(rank::ROOK, ());
+ let lock3 = Mutex::new(rank::BISHOP, ());
+
+ let guard1 = lock1.lock();
+ let guard2 = lock2.lock();
+ drop(guard2);
+
+ let guard3 = lock3.lock();
+ drop(guard3);
+ drop(guard1);
+}
+
+/// Locks can only be acquired and released in a stack-like order.
+#[test]
+#[should_panic(expected = "Lock not released in stacking order")]
+fn non_stack_like() {
+ use super::rank;
+
+ let lock1 = Mutex::new(rank::PAWN, ());
+ let lock2 = Mutex::new(rank::ROOK, ());
+
+ let guard1 = lock1.lock();
+ let guard2 = lock2.lock();
+
+ // Avoid a double panic from dropping this while unwinding due to the panic
+ // we're testing for.
+ std::mem::forget(guard2);
+
+ drop(guard1);
+}
diff --git a/third_party/rust/wgpu-core/src/lock/vanilla.rs b/third_party/rust/wgpu-core/src/lock/vanilla.rs
new file mode 100644
index 0000000000..9a35b6d9d8
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/lock/vanilla.rs
@@ -0,0 +1,121 @@
+//! Plain, uninstrumented wrappers around [`parking_lot`] lock types.
+//!
+//! These definitions are used when no particular lock instrumentation
+//! Cargo feature is selected.
+
+/// A plain wrapper around [`parking_lot::Mutex`].
+///
+/// This is just like [`parking_lot::Mutex`], except that our [`new`]
+/// method takes a rank, indicating where the new mutex should sit in
+/// `wgpu-core`'s lock ordering. The rank is ignored.
+///
+/// See the [`lock`] module documentation for other wrappers.
+///
+/// [`new`]: Mutex::new
+/// [`lock`]: crate::lock
+pub struct Mutex<T>(parking_lot::Mutex<T>);
+
+/// A guard produced by locking [`Mutex`].
+///
+/// This is just a wrapper around a [`parking_lot::MutexGuard`].
+pub struct MutexGuard<'a, T>(parking_lot::MutexGuard<'a, T>);
+
+impl<T> Mutex<T> {
+ pub fn new(_rank: super::rank::LockRank, value: T) -> Mutex<T> {
+ Mutex(parking_lot::Mutex::new(value))
+ }
+
+ pub fn lock(&self) -> MutexGuard<T> {
+ MutexGuard(self.0.lock())
+ }
+}
+
+impl<'a, T> std::ops::Deref for MutexGuard<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ self.0.deref()
+ }
+}
+
+impl<'a, T> std::ops::DerefMut for MutexGuard<'a, T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.0.deref_mut()
+ }
+}
+
+impl<T: std::fmt::Debug> std::fmt::Debug for Mutex<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+/// A plain wrapper around [`parking_lot::RwLock`].
+///
+/// This is just like [`parking_lot::RwLock`], except that our [`new`]
+/// method takes a rank, indicating where the new mutex should sit in
+/// `wgpu-core`'s lock ordering. The rank is ignored.
+///
+/// See the [`lock`] module documentation for other wrappers.
+///
+/// [`new`]: RwLock::new
+/// [`lock`]: crate::lock
+pub struct RwLock<T>(parking_lot::RwLock<T>);
+
+/// A read guard produced by locking [`RwLock`] as a reader.
+///
+/// This is just a wrapper around a [`parking_lot::RwLockReadGuard`].
+pub struct RwLockReadGuard<'a, T>(parking_lot::RwLockReadGuard<'a, T>);
+
+/// A write guard produced by locking [`RwLock`] as a writer.
+///
+/// This is just a wrapper around a [`parking_lot::RwLockWriteGuard`].
+pub struct RwLockWriteGuard<'a, T>(parking_lot::RwLockWriteGuard<'a, T>);
+
+impl<T> RwLock<T> {
+ pub fn new(_rank: super::rank::LockRank, value: T) -> RwLock<T> {
+ RwLock(parking_lot::RwLock::new(value))
+ }
+
+ pub fn read(&self) -> RwLockReadGuard<T> {
+ RwLockReadGuard(self.0.read())
+ }
+
+ pub fn write(&self) -> RwLockWriteGuard<T> {
+ RwLockWriteGuard(self.0.write())
+ }
+}
+
+impl<'a, T> RwLockWriteGuard<'a, T> {
+ pub fn downgrade(this: Self) -> RwLockReadGuard<'a, T> {
+ RwLockReadGuard(parking_lot::RwLockWriteGuard::downgrade(this.0))
+ }
+}
+
+impl<T: std::fmt::Debug> std::fmt::Debug for RwLock<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl<'a, T> std::ops::Deref for RwLockReadGuard<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ self.0.deref()
+ }
+}
+
+impl<'a, T> std::ops::Deref for RwLockWriteGuard<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ self.0.deref()
+ }
+}
+
+impl<'a, T> std::ops::DerefMut for RwLockWriteGuard<'a, T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.0.deref_mut()
+ }
+}
diff --git a/third_party/rust/wgpu-core/src/pipeline.rs b/third_party/rust/wgpu-core/src/pipeline.rs
index 4a7651b327..d70b118d7e 100644
--- a/third_party/rust/wgpu-core/src/pipeline.rs
+++ b/third_party/rust/wgpu-core/src/pipeline.rs
@@ -10,7 +10,8 @@ use crate::{
resource_log, validation, Label,
};
use arrayvec::ArrayVec;
-use std::{borrow::Cow, error::Error, fmt, marker::PhantomData, num::NonZeroU32, sync::Arc};
+use naga::error::ShaderError;
+use std::{borrow::Cow, marker::PhantomData, num::NonZeroU32, sync::Arc};
use thiserror::Error;
/// Information about buffer bindings, which
@@ -107,79 +108,8 @@ impl<A: HalApi> ShaderModule<A> {
}
}
-#[derive(Clone, Debug)]
-pub struct ShaderError<E> {
- pub source: String,
- pub label: Option<String>,
- pub inner: Box<E>,
-}
-#[cfg(feature = "wgsl")]
-impl fmt::Display for ShaderError<naga::front::wgsl::ParseError> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let label = self.label.as_deref().unwrap_or_default();
- let string = self.inner.emit_to_string(&self.source);
- write!(f, "\nShader '{label}' parsing {string}")
- }
-}
-#[cfg(feature = "glsl")]
-impl fmt::Display for ShaderError<naga::front::glsl::ParseError> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let label = self.label.as_deref().unwrap_or_default();
- let string = self.inner.emit_to_string(&self.source);
- write!(f, "\nShader '{label}' parsing {string}")
- }
-}
-#[cfg(feature = "spirv")]
-impl fmt::Display for ShaderError<naga::front::spv::Error> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let label = self.label.as_deref().unwrap_or_default();
- let string = self.inner.emit_to_string(&self.source);
- write!(f, "\nShader '{label}' parsing {string}")
- }
-}
-impl fmt::Display for ShaderError<naga::WithSpan<naga::valid::ValidationError>> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use codespan_reporting::{
- diagnostic::{Diagnostic, Label},
- files::SimpleFile,
- term,
- };
-
- let label = self.label.as_deref().unwrap_or_default();
- let files = SimpleFile::new(label, &self.source);
- let config = term::Config::default();
- let mut writer = term::termcolor::NoColor::new(Vec::new());
-
- let diagnostic = Diagnostic::error().with_labels(
- self.inner
- .spans()
- .map(|&(span, ref desc)| {
- Label::primary((), span.to_range().unwrap()).with_message(desc.to_owned())
- })
- .collect(),
- );
-
- term::emit(&mut writer, &config, &files, &diagnostic).expect("cannot write error");
-
- write!(
- f,
- "\nShader validation {}",
- String::from_utf8_lossy(&writer.into_inner())
- )
- }
-}
-impl<E> Error for ShaderError<E>
-where
- ShaderError<E>: fmt::Display,
- E: Error + 'static,
-{
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- Some(&self.inner)
- }
-}
-
//Note: `Clone` would require `WithSpan: Clone`.
-#[derive(Debug, Error)]
+#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum CreateShaderModuleError {
#[cfg(feature = "wgsl")]
@@ -187,7 +117,7 @@ pub enum CreateShaderModuleError {
Parsing(#[from] ShaderError<naga::front::wgsl::ParseError>),
#[cfg(feature = "glsl")]
#[error(transparent)]
- ParsingGlsl(#[from] ShaderError<naga::front::glsl::ParseError>),
+ ParsingGlsl(#[from] ShaderError<naga::front::glsl::ParseErrors>),
#[cfg(feature = "spirv")]
#[error(transparent)]
ParsingSpirV(#[from] ShaderError<naga::front::spv::Error>),
@@ -209,17 +139,6 @@ pub enum CreateShaderModuleError {
},
}
-impl CreateShaderModuleError {
- pub fn location(&self, source: &str) -> Option<naga::SourceLocation> {
- match *self {
- #[cfg(feature = "wgsl")]
- CreateShaderModuleError::Parsing(ref err) => err.inner.location(source),
- CreateShaderModuleError::Validation(ref err) => err.inner.location(source),
- _ => None,
- }
- }
-}
-
/// Describes a programmable pipeline stage.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@@ -233,6 +152,19 @@ pub struct ProgrammableStageDescriptor<'a> {
/// * If a single entry point associated with this stage must be in the shader, then proceed as
/// if `Some(…)` was specified with that entry point's name.
pub entry_point: Option<Cow<'a, str>>,
+ /// Specifies the values of pipeline-overridable constants in the shader module.
+ ///
+ /// If an `@id` attribute was specified on the declaration,
+ /// the key must be the pipeline constant ID as a decimal ASCII number; if not,
+ /// the key must be the constant's identifier name.
+ ///
+ /// The value may represent any of WGSL's concrete scalar types.
+ pub constants: Cow<'a, naga::back::PipelineConstants>,
+ /// Whether workgroup scoped memory will be initialized with zero values for this stage.
+ ///
+ /// This is required by the WebGPU spec, but may have overhead which can be avoided
+ /// for cross-platform applications
+ pub zero_initialize_workgroup_memory: bool,
}
/// Number of implicit bind groups derived at pipeline creation.
diff --git a/third_party/rust/wgpu-core/src/pool.rs b/third_party/rust/wgpu-core/src/pool.rs
index 47de6d5feb..7d17f3a7a3 100644
--- a/third_party/rust/wgpu-core/src/pool.rs
+++ b/third_party/rust/wgpu-core/src/pool.rs
@@ -5,8 +5,8 @@ use std::{
};
use once_cell::sync::OnceCell;
-use parking_lot::Mutex;
+use crate::lock::{rank, Mutex};
use crate::{PreHashedKey, PreHashedMap};
type SlotInner<V> = Weak<V>;
@@ -22,13 +22,15 @@ pub struct ResourcePool<K, V> {
impl<K: Clone + Eq + Hash, V> ResourcePool<K, V> {
pub fn new() -> Self {
Self {
- inner: Mutex::new(HashMap::default()),
+ inner: Mutex::new(rank::RESOURCE_POOL_INNER, HashMap::default()),
}
}
- /// Get a resource from the pool with the given entry map, or create a new one if it doesn't exist using the given constructor.
+ /// Get a resource from the pool with the given entry map, or create a new
+ /// one if it doesn't exist using the given constructor.
///
- /// Behaves such that only one resource will be created for each unique entry map at any one time.
+ /// Behaves such that only one resource will be created for each unique
+ /// entry map at any one time.
pub fn get_or_init<F, E>(&self, key: K, constructor: F) -> Result<Arc<V>, E>
where
F: FnOnce(K) -> Result<Arc<V>, E>,
@@ -96,6 +98,8 @@ impl<K: Clone + Eq + Hash, V> ResourcePool<K, V> {
/// Remove the given entry map from the pool.
///
/// Must *only* be called in the Drop impl of [`BindGroupLayout`].
+ ///
+ /// [`BindGroupLayout`]: crate::binding_model::BindGroupLayout
pub fn remove(&self, key: &K) {
let hashed_key = PreHashedKey::from_key(key);
diff --git a/third_party/rust/wgpu-core/src/present.rs b/third_party/rust/wgpu-core/src/present.rs
index cb4e17798f..053f7fdb24 100644
--- a/third_party/rust/wgpu-core/src/present.rs
+++ b/third_party/rust/wgpu-core/src/present.rs
@@ -9,7 +9,7 @@ When this texture is presented, we remove it from the device tracker as well as
extract it from the hub.
!*/
-use std::borrow::Borrow;
+use std::{borrow::Borrow, sync::Arc};
#[cfg(feature = "trace")]
use crate::device::trace::Action;
@@ -21,13 +21,13 @@ use crate::{
hal_api::HalApi,
hal_label, id,
init_tracker::TextureInitTracker,
+ lock::{rank, Mutex, RwLock},
resource::{self, ResourceInfo},
snatch::Snatchable,
track,
};
use hal::{Queue as _, Surface as _};
-use parking_lot::{Mutex, RwLock};
use thiserror::Error;
use wgt::SurfaceStatus as Status;
@@ -157,7 +157,7 @@ impl Global {
#[cfg(not(feature = "trace"))]
let _ = device;
- let suf = A::get_surface(surface.as_ref());
+ let suf = A::surface_as_hal(surface.as_ref());
let (texture_id, status) = match unsafe {
suf.unwrap()
.acquire_texture(Some(std::time::Duration::from_millis(
@@ -215,7 +215,10 @@ impl Global {
desc: texture_desc,
hal_usage,
format_features,
- initialization_status: RwLock::new(TextureInitTracker::new(1, 1)),
+ initialization_status: RwLock::new(
+ rank::TEXTURE_INITIALIZATION_STATUS,
+ TextureInitTracker::new(1, 1),
+ ),
full_range: track::TextureSelector {
layers: 0..1,
mips: 0..1,
@@ -224,14 +227,17 @@ impl Global {
"<Surface Texture>",
Some(device.tracker_indices.textures.clone()),
),
- clear_mode: RwLock::new(resource::TextureClearMode::Surface {
- clear_view: Some(clear_view),
- }),
- views: Mutex::new(Vec::new()),
- bind_groups: Mutex::new(Vec::new()),
+ clear_mode: RwLock::new(
+ rank::TEXTURE_CLEAR_MODE,
+ resource::TextureClearMode::Surface {
+ clear_view: Some(clear_view),
+ },
+ ),
+ views: Mutex::new(rank::TEXTURE_VIEWS, Vec::new()),
+ bind_groups: Mutex::new(rank::TEXTURE_BIND_GROUPS, Vec::new()),
};
- let (id, resource) = fid.assign(texture);
+ let (id, resource) = fid.assign(Arc::new(texture));
log::debug!("Created CURRENT Surface Texture {:?}", id);
{
@@ -324,7 +330,7 @@ impl Global {
.textures
.remove(texture.info.tracker_index());
let mut exclusive_snatch_guard = device.snatchable_lock.write();
- let suf = A::get_surface(&surface);
+ let suf = A::surface_as_hal(&surface);
let mut inner = texture.inner_mut(&mut exclusive_snatch_guard);
let inner = inner.as_mut().unwrap();
@@ -418,7 +424,7 @@ impl Global {
.lock()
.textures
.remove(texture.info.tracker_index());
- let suf = A::get_surface(&surface);
+ let suf = A::surface_as_hal(&surface);
let exclusive_snatch_guard = device.snatchable_lock.write();
match texture.inner.snatch(exclusive_snatch_guard).unwrap() {
resource::TextureInner::Surface { mut raw, parent_id } => {
diff --git a/third_party/rust/wgpu-core/src/registry.rs b/third_party/rust/wgpu-core/src/registry.rs
index 80394351af..f0f5674dae 100644
--- a/third_party/rust/wgpu-core/src/registry.rs
+++ b/third_party/rust/wgpu-core/src/registry.rs
@@ -1,11 +1,11 @@
use std::sync::Arc;
-use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use wgt::Backend;
use crate::{
id::Id,
identity::IdentityManager,
+ lock::{rank, RwLock, RwLockReadGuard, RwLockWriteGuard},
resource::Resource,
storage::{Element, InvalidId, Storage},
};
@@ -37,7 +37,8 @@ impl RegistryReport {
/// any other dependent resource
///
#[derive(Debug)]
-pub struct Registry<T: Resource> {
+pub(crate) struct Registry<T: Resource> {
+ // Must only contain an id which has either never been used or has been released from `storage`
identity: Arc<IdentityManager<T::Marker>>,
storage: RwLock<Storage<T>>,
backend: Backend,
@@ -47,7 +48,7 @@ impl<T: Resource> Registry<T> {
pub(crate) fn new(backend: Backend) -> Self {
Self {
identity: Arc::new(IdentityManager::new()),
- storage: RwLock::new(Storage::new()),
+ storage: RwLock::new(rank::REGISTRY_STORAGE, Storage::new()),
backend,
}
}
@@ -78,21 +79,26 @@ impl<T: Resource> FutureId<'_, T> {
Arc::new(value)
}
+ pub fn init_in_place(&self, mut value: Arc<T>) -> Arc<T> {
+ Arc::get_mut(&mut value)
+ .unwrap()
+ .as_info_mut()
+ .set_id(self.id);
+ value
+ }
+
/// Assign a new resource to this ID.
///
/// Registers it with the registry, and fills out the resource info.
- pub fn assign(self, value: T) -> (Id<T::Marker>, Arc<T>) {
+ pub fn assign(self, value: Arc<T>) -> (Id<T::Marker>, Arc<T>) {
let mut data = self.data.write();
- data.insert(self.id, self.init(value));
+ data.insert(self.id, self.init_in_place(value));
(self.id, data.get(self.id).unwrap().clone())
}
/// Assign an existing resource to a new ID.
///
/// Registers it with the registry.
- ///
- /// This _will_ leak the ID, and it will not be recycled again.
- /// See https://github.com/gfx-rs/wgpu/issues/4912.
pub fn assign_existing(self, value: &Arc<T>) -> Id<T::Marker> {
let mut data = self.data.write();
debug_assert!(!data.contains(self.id));
@@ -138,28 +144,35 @@ impl<T: Resource> Registry<T> {
pub(crate) fn write<'a>(&'a self) -> RwLockWriteGuard<'a, Storage<T>> {
self.storage.write()
}
- pub fn unregister_locked(&self, id: Id<T::Marker>, storage: &mut Storage<T>) -> Option<Arc<T>> {
+ pub(crate) fn unregister_locked(
+ &self,
+ id: Id<T::Marker>,
+ storage: &mut Storage<T>,
+ ) -> Option<Arc<T>> {
self.identity.free(id);
storage.remove(id)
}
- pub fn force_replace(&self, id: Id<T::Marker>, mut value: T) {
+ pub(crate) fn force_replace(&self, id: Id<T::Marker>, mut value: T) {
let mut storage = self.storage.write();
value.as_info_mut().set_id(id);
storage.force_replace(id, value)
}
- pub fn force_replace_with_error(&self, id: Id<T::Marker>, label: &str) {
+ pub(crate) fn force_replace_with_error(&self, id: Id<T::Marker>, label: &str) {
let mut storage = self.storage.write();
storage.remove(id);
storage.insert_error(id, label);
}
pub(crate) fn unregister(&self, id: Id<T::Marker>) -> Option<Arc<T>> {
- self.identity.free(id);
let value = self.storage.write().remove(id);
+ // This needs to happen *after* removing it from the storage, to maintain the
+ // invariant that `self.identity` only contains ids which are actually available
+ // See https://github.com/gfx-rs/wgpu/issues/5372
+ self.identity.free(id);
//Returning None is legal if it's an error ID
value
}
- pub fn label_for_resource(&self, id: Id<T::Marker>) -> String {
+ pub(crate) fn label_for_resource(&self, id: Id<T::Marker>) -> String {
let guard = self.storage.read();
let type_name = guard.kind();
@@ -197,3 +210,53 @@ impl<T: Resource> Registry<T> {
report
}
}
+
+#[cfg(test)]
+mod tests {
+ use std::sync::Arc;
+
+ use crate::{
+ id::Marker,
+ resource::{Resource, ResourceInfo, ResourceType},
+ };
+
+ use super::Registry;
+ struct TestData {
+ info: ResourceInfo<TestData>,
+ }
+ struct TestDataId;
+ impl Marker for TestDataId {}
+
+ impl Resource for TestData {
+ type Marker = TestDataId;
+
+ const TYPE: ResourceType = "Test data";
+
+ fn as_info(&self) -> &ResourceInfo<Self> {
+ &self.info
+ }
+
+ fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
+ &mut self.info
+ }
+ }
+
+ #[test]
+ fn simultaneous_registration() {
+ let registry = Registry::without_backend();
+ std::thread::scope(|s| {
+ for _ in 0..5 {
+ s.spawn(|| {
+ for _ in 0..1000 {
+ let value = Arc::new(TestData {
+ info: ResourceInfo::new("Test data", None),
+ });
+ let new_id = registry.prepare(None);
+ let (id, _) = new_id.assign(value);
+ registry.unregister(id);
+ }
+ });
+ }
+ })
+ }
+}
diff --git a/third_party/rust/wgpu-core/src/resource.rs b/third_party/rust/wgpu-core/src/resource.rs
index aca077caab..d3cd2968bf 100644
--- a/third_party/rust/wgpu-core/src/resource.rs
+++ b/third_party/rust/wgpu-core/src/resource.rs
@@ -8,8 +8,12 @@ use crate::{
},
global::Global,
hal_api::HalApi,
- id::{AdapterId, BufferId, DeviceId, Id, Marker, SurfaceId, TextureId},
+ id::{
+ AdapterId, BufferId, CommandEncoderId, DeviceId, Id, Marker, SurfaceId, TextureId,
+ TextureViewId,
+ },
init_tracker::{BufferInitTracker, TextureInitTracker},
+ lock::{Mutex, RwLock},
resource, resource_log,
snatch::{ExclusiveSnatchGuard, SnatchGuard, Snatchable},
track::{SharedTrackerIndexAllocator, TextureSelector, TrackerIndex},
@@ -18,7 +22,6 @@ use crate::{
};
use hal::CommandEncoder;
-use parking_lot::{Mutex, RwLock};
use smallvec::SmallVec;
use thiserror::Error;
use wgt::WasmNotSendSync;
@@ -55,7 +58,7 @@ use std::{
/// [`Device`]: crate::device::resource::Device
/// [`Buffer`]: crate::resource::Buffer
#[derive(Debug)]
-pub struct ResourceInfo<T: Resource> {
+pub(crate) struct ResourceInfo<T: Resource> {
id: Option<Id<T::Marker>>,
tracker_index: TrackerIndex,
tracker_indices: Option<Arc<SharedTrackerIndexAllocator>>,
@@ -141,7 +144,7 @@ impl<T: Resource> ResourceInfo<T> {
pub(crate) type ResourceType = &'static str;
-pub trait Resource: 'static + Sized + WasmNotSendSync {
+pub(crate) trait Resource: 'static + Sized + WasmNotSendSync {
type Marker: Marker;
const TYPE: ResourceType;
fn as_info(&self) -> &ResourceInfo<Self>;
@@ -370,10 +373,10 @@ pub type BufferAccessResult = Result<(), BufferAccessError>;
#[derive(Debug)]
pub(crate) struct BufferPendingMapping<A: HalApi> {
- pub range: Range<wgt::BufferAddress>,
- pub op: BufferMapOperation,
+ pub(crate) range: Range<wgt::BufferAddress>,
+ pub(crate) op: BufferMapOperation,
// hold the parent alive while the mapping is active
- pub _parent_buffer: Arc<Buffer<A>>,
+ pub(crate) _parent_buffer: Arc<Buffer<A>>,
}
pub type BufferDescriptor<'a> = wgt::BufferDescriptor<Label<'a>>;
@@ -734,7 +737,7 @@ pub(crate) enum TextureInner<A: HalApi> {
}
impl<A: HalApi> TextureInner<A> {
- pub fn raw(&self) -> Option<&A::Texture> {
+ pub(crate) fn raw(&self) -> Option<&A::Texture> {
match self {
Self::Native { raw } => Some(raw),
Self::Surface { raw: Some(tex), .. } => Some(tex.borrow()),
@@ -924,11 +927,11 @@ impl Global {
/// # Safety
///
/// - The raw texture handle must not be manually destroyed
- pub unsafe fn texture_as_hal<A: HalApi, F: FnOnce(Option<&A::Texture>)>(
+ pub unsafe fn texture_as_hal<A: HalApi, F: FnOnce(Option<&A::Texture>) -> R, R>(
&self,
id: TextureId,
hal_texture_callback: F,
- ) {
+ ) -> R {
profiling::scope!("Texture::as_hal");
let hub = A::hub(self);
@@ -937,7 +940,26 @@ impl Global {
let snatch_guard = texture.device.snatchable_lock.read();
let hal_texture = texture.raw(&snatch_guard);
- hal_texture_callback(hal_texture);
+ hal_texture_callback(hal_texture)
+ }
+
+ /// # Safety
+ ///
+ /// - The raw texture view handle must not be manually destroyed
+ pub unsafe fn texture_view_as_hal<A: HalApi, F: FnOnce(Option<&A::TextureView>) -> R, R>(
+ &self,
+ id: TextureViewId,
+ hal_texture_view_callback: F,
+ ) -> R {
+ profiling::scope!("TextureView::as_hal");
+
+ let hub = A::hub(self);
+ let texture_view_opt = { hub.texture_views.try_get(id).ok().flatten() };
+ let texture_view = texture_view_opt.as_ref().unwrap();
+ let snatch_guard = texture_view.device.snatchable_lock.read();
+ let hal_texture_view = texture_view.raw(&snatch_guard);
+
+ hal_texture_view_callback(hal_texture_view)
}
/// # Safety
@@ -1001,10 +1023,38 @@ impl Global {
profiling::scope!("Surface::as_hal");
let surface = self.surfaces.get(id).ok();
- let hal_surface = surface.as_ref().and_then(|surface| A::get_surface(surface));
+ let hal_surface = surface
+ .as_ref()
+ .and_then(|surface| A::surface_as_hal(surface));
hal_surface_callback(hal_surface)
}
+
+ /// # Safety
+ ///
+ /// - The raw command encoder handle must not be manually destroyed
+ pub unsafe fn command_encoder_as_hal_mut<
+ A: HalApi,
+ F: FnOnce(Option<&mut A::CommandEncoder>) -> R,
+ R,
+ >(
+ &self,
+ id: CommandEncoderId,
+ hal_command_encoder_callback: F,
+ ) -> R {
+ profiling::scope!("CommandEncoder::as_hal");
+
+ let hub = A::hub(self);
+ let cmd_buf = hub
+ .command_buffers
+ .get(id.into_command_buffer_id())
+ .unwrap();
+ let mut cmd_buf_data = cmd_buf.data.lock();
+ let cmd_buf_data = cmd_buf_data.as_mut().unwrap();
+ let cmd_buf_raw = cmd_buf_data.encoder.open().ok();
+
+ hal_command_encoder_callback(cmd_buf_raw)
+ }
}
/// A texture that has been marked as destroyed and is staged for actual deletion soon.
diff --git a/third_party/rust/wgpu-core/src/snatch.rs b/third_party/rust/wgpu-core/src/snatch.rs
index d5cd1a3d37..08a1eba11d 100644
--- a/third_party/rust/wgpu-core/src/snatch.rs
+++ b/third_party/rust/wgpu-core/src/snatch.rs
@@ -1,6 +1,6 @@
#![allow(unused)]
-use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
+use crate::lock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::{
backtrace::Backtrace,
cell::{Cell, RefCell, UnsafeCell},
@@ -8,6 +8,8 @@ use std::{
thread,
};
+use crate::lock::rank;
+
/// A guard that provides read access to snatchable data.
pub struct SnatchGuard<'a>(RwLockReadGuard<'a, ()>);
/// A guard that allows snatching the snatchable data.
@@ -64,8 +66,58 @@ impl<T> std::fmt::Debug for Snatchable<T> {
unsafe impl<T> Sync for Snatchable<T> {}
+struct LockTrace {
+ purpose: &'static str,
+ caller: &'static Location<'static>,
+ backtrace: Backtrace,
+}
+
+impl std::fmt::Display for LockTrace {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "a {} lock at {}\n{}",
+ self.purpose, self.caller, self.backtrace
+ )
+ }
+}
+
+#[cfg(debug_assertions)]
+impl LockTrace {
+ #[track_caller]
+ fn enter(purpose: &'static str) {
+ let new = LockTrace {
+ purpose,
+ caller: Location::caller(),
+ backtrace: Backtrace::capture(),
+ };
+
+ if let Some(prev) = SNATCH_LOCK_TRACE.take() {
+ let current = thread::current();
+ let name = current.name().unwrap_or("<unnamed>");
+ panic!(
+ "thread '{name}' attempted to acquire a snatch lock recursively.\n\
+ - Currently trying to acquire {new}\n\
+ - Previously acquired {prev}",
+ );
+ } else {
+ SNATCH_LOCK_TRACE.set(Some(new));
+ }
+ }
+
+ fn exit() {
+ SNATCH_LOCK_TRACE.take();
+ }
+}
+
+#[cfg(not(debug_assertions))]
+impl LockTrace {
+ fn enter(purpose: &'static str) {}
+ fn exit() {}
+}
+
thread_local! {
- static READ_LOCK_LOCATION: Cell<Option<(&'static Location<'static>, Backtrace)>> = const { Cell::new(None) };
+ static SNATCH_LOCK_TRACE: Cell<Option<LockTrace>> = const { Cell::new(None) };
}
/// A Device-global lock for all snatchable data.
@@ -78,31 +130,16 @@ impl SnatchLock {
/// right SnatchLock (the one associated to the same device). This method is unsafe
/// to force force sers to think twice about creating a SnatchLock. The only place this
/// method should be called is when creating the device.
- pub unsafe fn new() -> Self {
+ pub unsafe fn new(rank: rank::LockRank) -> Self {
SnatchLock {
- lock: RwLock::new(()),
+ lock: RwLock::new(rank, ()),
}
}
/// Request read access to snatchable resources.
#[track_caller]
pub fn read(&self) -> SnatchGuard {
- if cfg!(debug_assertions) {
- let caller = Location::caller();
- let backtrace = Backtrace::capture();
- if let Some((prev, bt)) = READ_LOCK_LOCATION.take() {
- let current = thread::current();
- let name = current.name().unwrap_or("<unnamed>");
- panic!(
- "thread '{name}' attempted to acquire a snatch read lock recursively.\n
- - {prev}\n{bt}\n
- - {caller}\n{backtrace}"
- );
- } else {
- READ_LOCK_LOCATION.set(Some((caller, backtrace)));
- }
- }
-
+ LockTrace::enter("read");
SnatchGuard(self.lock.read())
}
@@ -111,14 +148,21 @@ impl SnatchLock {
/// This should only be called when a resource needs to be snatched. This has
/// a high risk of causing lock contention if called concurrently with other
/// wgpu work.
+ #[track_caller]
pub fn write(&self) -> ExclusiveSnatchGuard {
+ LockTrace::enter("write");
ExclusiveSnatchGuard(self.lock.write())
}
}
impl Drop for SnatchGuard<'_> {
fn drop(&mut self) {
- #[cfg(debug_assertions)]
- READ_LOCK_LOCATION.take();
+ LockTrace::exit();
+ }
+}
+
+impl Drop for ExclusiveSnatchGuard<'_> {
+ fn drop(&mut self) {
+ LockTrace::exit();
}
}
diff --git a/third_party/rust/wgpu-core/src/storage.rs b/third_party/rust/wgpu-core/src/storage.rs
index 554ced8b7d..03874b8104 100644
--- a/third_party/rust/wgpu-core/src/storage.rs
+++ b/third_party/rust/wgpu-core/src/storage.rs
@@ -29,11 +29,14 @@ pub(crate) struct InvalidId;
/// A table of `T` values indexed by the id type `I`.
///
+/// `Storage` implements [`std::ops::Index`], accepting `Id` values as
+/// indices.
+///
/// The table is represented as a vector indexed by the ids' index
/// values, so you should use an id allocator like `IdentityManager`
/// that keeps the index values dense and close to zero.
#[derive(Debug)]
-pub struct Storage<T>
+pub(crate) struct Storage<T>
where
T: Resource,
{
diff --git a/third_party/rust/wgpu-core/src/track/buffer.rs b/third_party/rust/wgpu-core/src/track/buffer.rs
index 6cf1fdda6f..9a52a53253 100644
--- a/third_party/rust/wgpu-core/src/track/buffer.rs
+++ b/third_party/rust/wgpu-core/src/track/buffer.rs
@@ -11,6 +11,7 @@ use super::{PendingTransition, ResourceTracker, TrackerIndex};
use crate::{
hal_api::HalApi,
id::BufferId,
+ lock::{rank, Mutex},
resource::{Buffer, Resource},
snatch::SnatchGuard,
storage::Storage,
@@ -20,7 +21,6 @@ use crate::{
},
};
use hal::{BufferBarrier, BufferUses};
-use parking_lot::Mutex;
use wgt::{strict_assert, strict_assert_eq};
impl ResourceUses for BufferUses {
@@ -51,7 +51,7 @@ pub(crate) struct BufferBindGroupState<A: HalApi> {
impl<A: HalApi> BufferBindGroupState<A> {
pub fn new() -> Self {
Self {
- buffers: Mutex::new(Vec::new()),
+ buffers: Mutex::new(rank::BUFFER_BIND_GROUP_STATE_BUFFERS, Vec::new()),
_phantom: PhantomData,
}
@@ -245,6 +245,22 @@ impl<A: HalApi> BufferUsageScope<A> {
.get(id)
.map_err(|_| UsageConflict::BufferInvalid { id })?;
+ self.insert_merge_single(buffer.clone(), new_state)
+ .map(|_| buffer)
+ }
+
+ /// Merge a single state into the UsageScope, using an already resolved buffer.
+ ///
+ /// If the resulting state is invalid, returns a usage
+ /// conflict with the details of the invalid state.
+ ///
+ /// If the ID is higher than the length of internal vectors,
+ /// the vectors will be extended. A call to set_size is not needed.
+ pub fn insert_merge_single(
+ &mut self,
+ buffer: Arc<Buffer<A>>,
+ new_state: BufferUses,
+ ) -> Result<(), UsageConflict> {
let index = buffer.info.tracker_index().as_usize();
self.allow_index(index);
@@ -260,12 +276,12 @@ impl<A: HalApi> BufferUsageScope<A> {
index,
BufferStateProvider::Direct { state: new_state },
ResourceMetadataProvider::Direct {
- resource: Cow::Owned(buffer.clone()),
+ resource: Cow::Owned(buffer),
},
)?;
}
- Ok(buffer)
+ Ok(())
}
}
diff --git a/third_party/rust/wgpu-core/src/track/metadata.rs b/third_party/rust/wgpu-core/src/track/metadata.rs
index 3e71e0e084..d6e8d6f906 100644
--- a/third_party/rust/wgpu-core/src/track/metadata.rs
+++ b/third_party/rust/wgpu-core/src/track/metadata.rs
@@ -87,16 +87,18 @@ impl<T: Resource> ResourceMetadata<T> {
/// Add the resource with the given index, epoch, and reference count to the
/// set.
///
+ /// Returns a reference to the newly inserted resource.
+ /// (This allows avoiding a clone/reference count increase in many cases.)
+ ///
/// # Safety
///
/// The given `index` must be in bounds for this `ResourceMetadata`'s
/// existing tables. See `tracker_assert_in_bounds`.
#[inline(always)]
- pub(super) unsafe fn insert(&mut self, index: usize, resource: Arc<T>) {
+ pub(super) unsafe fn insert(&mut self, index: usize, resource: Arc<T>) -> &Arc<T> {
self.owned.set(index, true);
- unsafe {
- *self.resources.get_unchecked_mut(index) = Some(resource);
- }
+ let resource_dst = unsafe { self.resources.get_unchecked_mut(index) };
+ resource_dst.insert(resource)
}
/// Get the resource with the given index.
diff --git a/third_party/rust/wgpu-core/src/track/mod.rs b/third_party/rust/wgpu-core/src/track/mod.rs
index 374dfe7493..cc20b2a01c 100644
--- a/third_party/rust/wgpu-core/src/track/mod.rs
+++ b/third_party/rust/wgpu-core/src/track/mod.rs
@@ -102,10 +102,14 @@ mod stateless;
mod texture;
use crate::{
- binding_model, command, conv, hal_api::HalApi, id, pipeline, resource, snatch::SnatchGuard,
+ binding_model, command, conv,
+ hal_api::HalApi,
+ id,
+ lock::{rank, Mutex, RwLock},
+ pipeline, resource,
+ snatch::SnatchGuard,
};
-use parking_lot::{Mutex, RwLock};
use std::{fmt, ops, sync::Arc};
use thiserror::Error;
@@ -136,7 +140,8 @@ impl TrackerIndex {
/// of a certain type. This index is separate from the resource ID for various reasons:
/// - There can be multiple resource IDs pointing the the same resource.
/// - IDs of dead handles can be recycled while resources are internally held alive (and tracked).
-/// - The plan is to remove IDs in the long run (https://github.com/gfx-rs/wgpu/issues/5121).
+/// - The plan is to remove IDs in the long run
+/// ([#5121](https://github.com/gfx-rs/wgpu/issues/5121)).
/// In order to produce these tracker indices, there is a shared TrackerIndexAllocator
/// per resource type. Indices have the same lifetime as the internal resource they
/// are associated to (alloc happens when creating the resource and free is called when
@@ -190,7 +195,10 @@ pub(crate) struct SharedTrackerIndexAllocator {
impl SharedTrackerIndexAllocator {
pub fn new() -> Self {
SharedTrackerIndexAllocator {
- inner: Mutex::new(TrackerIndexAllocator::new()),
+ inner: Mutex::new(
+ rank::SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
+ TrackerIndexAllocator::new(),
+ ),
}
}
@@ -480,11 +488,26 @@ impl<A: HalApi> RenderBundleScope<A> {
/// Create the render bundle scope and pull the maximum IDs from the hubs.
pub fn new() -> Self {
Self {
- buffers: RwLock::new(BufferUsageScope::default()),
- textures: RwLock::new(TextureUsageScope::default()),
- bind_groups: RwLock::new(StatelessTracker::new()),
- render_pipelines: RwLock::new(StatelessTracker::new()),
- query_sets: RwLock::new(StatelessTracker::new()),
+ buffers: RwLock::new(
+ rank::RENDER_BUNDLE_SCOPE_BUFFERS,
+ BufferUsageScope::default(),
+ ),
+ textures: RwLock::new(
+ rank::RENDER_BUNDLE_SCOPE_TEXTURES,
+ TextureUsageScope::default(),
+ ),
+ bind_groups: RwLock::new(
+ rank::RENDER_BUNDLE_SCOPE_BIND_GROUPS,
+ StatelessTracker::new(),
+ ),
+ render_pipelines: RwLock::new(
+ rank::RENDER_BUNDLE_SCOPE_RENDER_PIPELINES,
+ StatelessTracker::new(),
+ ),
+ query_sets: RwLock::new(
+ rank::RENDER_BUNDLE_SCOPE_QUERY_SETS,
+ StatelessTracker::new(),
+ ),
}
}
@@ -639,8 +662,8 @@ impl<A: HalApi> Tracker<A> {
///
/// If a transition is needed to get the resources into the needed
/// state, those transitions are stored within the tracker. A
- /// subsequent call to [`BufferTracker::drain`] or
- /// [`TextureTracker::drain`] is needed to get those transitions.
+ /// subsequent call to [`BufferTracker::drain_transitions`] or
+ /// [`TextureTracker::drain_transitions`] is needed to get those transitions.
///
/// This is a really funky method used by Compute Passes to generate
/// barriers after a call to dispatch without needing to iterate
diff --git a/third_party/rust/wgpu-core/src/track/stateless.rs b/third_party/rust/wgpu-core/src/track/stateless.rs
index 00225f2305..25ffc027ee 100644
--- a/third_party/rust/wgpu-core/src/track/stateless.rs
+++ b/third_party/rust/wgpu-core/src/track/stateless.rs
@@ -6,9 +6,14 @@
use std::sync::Arc;
-use parking_lot::Mutex;
-
-use crate::{id::Id, resource::Resource, resource_log, storage::Storage, track::ResourceMetadata};
+use crate::{
+ id::Id,
+ lock::{rank, Mutex},
+ resource::Resource,
+ resource_log,
+ storage::Storage,
+ track::ResourceMetadata,
+};
use super::{ResourceTracker, TrackerIndex};
@@ -24,7 +29,7 @@ pub(crate) struct StatelessBindGroupSate<T: Resource> {
impl<T: Resource> StatelessBindGroupSate<T> {
pub fn new() -> Self {
Self {
- resources: Mutex::new(Vec::new()),
+ resources: Mutex::new(rank::STATELESS_BIND_GROUP_STATE_RESOURCES, Vec::new()),
}
}
@@ -153,16 +158,17 @@ impl<T: Resource> StatelessTracker<T> {
///
/// If the ID is higher than the length of internal vectors,
/// the vectors will be extended. A call to set_size is not needed.
- pub fn insert_single(&mut self, resource: Arc<T>) {
+ ///
+ /// Returns a reference to the newly inserted resource.
+ /// (This allows avoiding a clone/reference count increase in many cases.)
+ pub fn insert_single(&mut self, resource: Arc<T>) -> &Arc<T> {
let index = resource.as_info().tracker_index().as_usize();
self.allow_index(index);
self.tracker_assert_in_bounds(index);
- unsafe {
- self.metadata.insert(index, resource);
- }
+ unsafe { self.metadata.insert(index, resource) }
}
/// Adds the given resource to the tracker.
diff --git a/third_party/rust/wgpu-core/src/track/texture.rs b/third_party/rust/wgpu-core/src/track/texture.rs
index 3cf95ff38a..51ed72a18d 100644
--- a/third_party/rust/wgpu-core/src/track/texture.rs
+++ b/third_party/rust/wgpu-core/src/track/texture.rs
@@ -24,6 +24,7 @@ use super::{
};
use crate::{
hal_api::HalApi,
+ lock::{rank, Mutex},
resource::{Resource, Texture, TextureInner},
snatch::SnatchGuard,
track::{
@@ -36,7 +37,6 @@ use hal::TextureUses;
use arrayvec::ArrayVec;
use naga::FastHashMap;
-use parking_lot::Mutex;
use wgt::{strict_assert, strict_assert_eq};
use std::{borrow::Cow, iter, marker::PhantomData, ops::Range, sync::Arc, vec::Drain};
@@ -164,7 +164,7 @@ pub(crate) struct TextureBindGroupState<A: HalApi> {
impl<A: HalApi> TextureBindGroupState<A> {
pub fn new() -> Self {
Self {
- textures: Mutex::new(Vec::new()),
+ textures: Mutex::new(rank::TEXTURE_BIND_GROUP_STATE_TEXTURES, Vec::new()),
}
}
diff --git a/third_party/rust/wgpu-core/src/validation.rs b/third_party/rust/wgpu-core/src/validation.rs
index e4846c4000..d360ee9621 100644
--- a/third_party/rust/wgpu-core/src/validation.rs
+++ b/third_party/rust/wgpu-core/src/validation.rs
@@ -655,7 +655,8 @@ impl NumericType {
| Vf::Unorm16x4
| Vf::Snorm16x4
| Vf::Float16x4
- | Vf::Float32x4 => (NumericDimension::Vector(Vs::Quad), Scalar::F32),
+ | Vf::Float32x4
+ | Vf::Unorm10_10_10_2 => (NumericDimension::Vector(Vs::Quad), Scalar::F32),
Vf::Float64 => (NumericDimension::Scalar, Scalar::F64),
Vf::Float64x2 => (NumericDimension::Vector(Vs::Bi), Scalar::F64),
Vf::Float64x3 => (NumericDimension::Vector(Vs::Tri), Scalar::F64),
diff --git a/third_party/rust/wgpu-hal/.cargo-checksum.json b/third_party/rust/wgpu-hal/.cargo-checksum.json
index 2cba88cfdf..265725f165 100644
--- a/third_party/rust/wgpu-hal/.cargo-checksum.json
+++ b/third_party/rust/wgpu-hal/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"332863a1b354637fc62ff5729e7c2f5089fa65db05d330ec268a7aab04bb3d42","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"099ee611a911dc19330a61bffcde13663929a51b25ac528ee33ea796d695491e","build.rs":"c80bdc0152a00471eec6ed0dd0f7d55d0b975498a00ba05e94100c84ad639a49","examples/halmark/main.rs":"4604737f714943383c57feac2b8468ecf15e9e60c54a5303455e9953ec5c79fb","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"095113a1ba0851652a77aabfc8fa6ea7edcc2d09e91fd1e5009ead87d5998ea9","examples/ray-traced-triangle/main.rs":"955c2b8700c3b2daf14e9ef963ff499ed185b6f349dbc63caa422b2cf4942a1f","examples/ray-traced-triangle/shader.wgsl":"cc10caf92746724a71f6dd0dbc3a71e57b37c7d1d83278556805a535c0728a9d","src/auxil/dxgi/conv.rs":"760cd4eaa79b530368a30140b96bf73ac4fbdb4025eb95f0bed581638c8bb1cb","src/auxil/dxgi/exception.rs":"f0cfb5a0adcdc3b6db909601fee51ad51368f5da269bcd46e4dbea45a3bec4b1","src/auxil/dxgi/factory.rs":"5f861fbfe2f4cce08722a95283549b8f62b96f24a306d080d9f1730ae53501d8","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"79fe5aa17a2b21a7f06b1b604200c3c3e73fca31e8193aab80b5b15e7e9818a0","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"720ef2aae258733322a3274fd858f91effb8951dabaf7bbfd8a9a0be2d2dba97","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx12/adapter.rs":"2a90a4222702e50fabfc64339ac2aa667e1ee2d2bf801c3e2e59a91e261c7a04","src/dx12/command.rs":"e0675560784214a18e078062cbd0965c21a35c99eecf0e697d1badb9c692db35","src/dx12/conv.rs":"94d35f117ae003b07049f3a0bc6c45a0ffda9fb8053233d39c173cfb1b644403","src/dx12/descriptor.rs":"e06eb08bee4c805fa76b6ab791893b5b563ee60de9c8f8d8e0e21ab97ade5664","src/dx12/device.rs":"6a38dabd4db9d7ca79bfcfbeb3483320ad88f2db6e93a7210051bbf81acb1bbd","src/dx12/instance.rs":"030a86ac810d5ebf151328bbc06b9b5a89788721aa963cb4e0f3ff943b2c8633","src/dx12/mod.rs":"87e7012a113554c976abdbecd10b2fe6aab3ba695c88dc77d6beb3880d96ba54","src/dx12/shader_compilation.rs":"5087adb8576e2d7751619dfdf8b37c573bb4e494290c594077ca3208cce1e746","src/dx12/suballocation.rs":"6939fc36223a15cc070c744d0418f9ac6fa2829d794af17cdea7c61eb5f8d2c0","src/dx12/types.rs":"9573736baaa0ef607367c3b72144556d24faf677a26bb8df49a4372a1348e06b","src/dx12/view.rs":"792772e9c87840dcd045b7381a03162eb4a501492a95ca586e77e81aed621c67","src/empty.rs":"0849e0b7210d33145b3fb1368ed08b13fbc2144b1ccc0a1af913896e916bbe46","src/gles/adapter.rs":"22fe404177d4abb077f35a5be54295f81eacb021d448ad01aa96450ade8b089a","src/gles/command.rs":"788505168ae1af312781c86d31d5bc289fcc4e2b3cb047fb41deb62542db1a95","src/gles/conv.rs":"5d15d3a33032d32ff99bc338fba0689fa54c76d0714e335fe48523d841df386f","src/gles/device.rs":"e126042653b0651a12684504e19c05db3fe333bde3ac408063675eef6c27754a","src/gles/egl.rs":"72feefbcd399e686b5c210a67151ef040e45e123ad371539274d1d52b3dd162d","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"b8999f76ad45e07312b291457100f12699ba6a2635c1f1913b0648e9a9394015","src/gles/queue.rs":"7f62e9c1cb670f66ac8bb0d62cd531b9c11b2a29f8ed28736c40e21071fbe25d","src/gles/shaders/clear.frag":"9133ed8ed97d3641fbb6b5f5ea894a3554c629ccc1b80a5fc9221d7293aa1954","src/gles/shaders/clear.vert":"a543768725f4121ff2e9e1fb5b00644931e9d6f2f946c0ef01968afb5a135abd","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"000ed39eae4a6442ca16bdca68e1e61459e6815a5db8eeec53e0ee0f5f14ae66","src/gles/wgl.rs":"78bfe5bcdacfde8d8df0d6f3987048f8ad8a2c2c93df6d607cf5a16795d3bb8e","src/lib.rs":"b80b7d14f524f25875b1d7e7ee67cd6057bbe9944ea92b59d5d4d08d7b17580d","src/metal/adapter.rs":"e473a1857817030ee5c5358e8387daff66d1aca1f5133224cc844ea4b17d3e49","src/metal/command.rs":"61640f2cb7269f44487df2d911771fbe1f78484d44a5363a6ddfce7d77143b02","src/metal/conv.rs":"0bce6a8d0ccef16783475803d70d35e03ab7938c19374e22c9d253abe1f8b111","src/metal/device.rs":"1343ad60a423b81649a6eaad69de743a2247234a75ec48c0698973af67592e48","src/metal/mod.rs":"3e3f69ac864cb6a96c5b9df551a934bbc4bf08503430b9507561eef973daf57f","src/metal/surface.rs":"397dab6726eead96f0be9ecb6686874e691079da94c072921a6422e9b1284fb5","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"ac4525114d37d6ffa31f2c240b2bb9e1d97d19cd6d400598c2a1153d9144bd0f","src/vulkan/command.rs":"82060e8040eea27b717ec676525139a9c7238074ad5ce6902f5174ac5c7aa048","src/vulkan/conv.rs":"7e6266e3a0b7d0b8d5d51362a0386a84bc047350eeac663b6352a94d5e5c0a87","src/vulkan/device.rs":"24abe83a2cbe8fa3377d0fb8d64fcaac3a3e6b0521ec28143fa8b7dee0c1afee","src/vulkan/instance.rs":"60742c3c1feee63eca0953165dae57c86b0d58e496ad374743ff83ae50a4e8f1","src/vulkan/mod.rs":"dfd8e079b7b783de3dfdfbf2349d7283c1b9108242d1ffbb4e072376901c7bd1"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"8c0a58e1b89cd82b644379eaaa71825499293fe0667192812e1cf41ecec6fd42","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"b432248c4d5c85925ea2d741dc53069111619631a009994dbeaef980993d23a2","build.rs":"c80bdc0152a00471eec6ed0dd0f7d55d0b975498a00ba05e94100c84ad639a49","examples/halmark/main.rs":"c5debf7ff46b76fcdd4663c4cbd365d0015ac96c200488f6de34f914ba47d6e3","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"095113a1ba0851652a77aabfc8fa6ea7edcc2d09e91fd1e5009ead87d5998ea9","examples/ray-traced-triangle/main.rs":"5679fb4794966d9132b8d15471526f6adce58378bd319ae3f345494d2a216ddc","examples/ray-traced-triangle/shader.wgsl":"cc10caf92746724a71f6dd0dbc3a71e57b37c7d1d83278556805a535c0728a9d","src/auxil/dxgi/conv.rs":"134a1459339537a462448d5e1eb117931f450c6724bd9cb8388f39870c466eb3","src/auxil/dxgi/exception.rs":"f0cfb5a0adcdc3b6db909601fee51ad51368f5da269bcd46e4dbea45a3bec4b1","src/auxil/dxgi/factory.rs":"5f861fbfe2f4cce08722a95283549b8f62b96f24a306d080d9f1730ae53501d8","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"79fe5aa17a2b21a7f06b1b604200c3c3e73fca31e8193aab80b5b15e7e9818a0","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"720ef2aae258733322a3274fd858f91effb8951dabaf7bbfd8a9a0be2d2dba97","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx12/adapter.rs":"757fe846d1114bcd2343b8de405869377e1b3930e7e70a4908f07dc5284e0fca","src/dx12/command.rs":"e0675560784214a18e078062cbd0965c21a35c99eecf0e697d1badb9c692db35","src/dx12/conv.rs":"8efa0ecfaaef2d0aaca4a17a4ed293d4921b82383cbce90bec1b2fef41cb3462","src/dx12/descriptor.rs":"e06eb08bee4c805fa76b6ab791893b5b563ee60de9c8f8d8e0e21ab97ade5664","src/dx12/device.rs":"30e1d9ad16a077fdcb8091eed7fe90ba8c51edb905b2908dcdb3c85113cb88a3","src/dx12/instance.rs":"030a86ac810d5ebf151328bbc06b9b5a89788721aa963cb4e0f3ff943b2c8633","src/dx12/mod.rs":"edaf24893edbd5390460a618e8db9e5f767d319efaa834b11f0c2cd1373b41f4","src/dx12/shader_compilation.rs":"5087adb8576e2d7751619dfdf8b37c573bb4e494290c594077ca3208cce1e746","src/dx12/suballocation.rs":"6939fc36223a15cc070c744d0418f9ac6fa2829d794af17cdea7c61eb5f8d2c0","src/dx12/types.rs":"b5140522eea491b6943ee9da235cdbfbd611f830d2719fd8812dfdd494ed16e2","src/dx12/view.rs":"792772e9c87840dcd045b7381a03162eb4a501492a95ca586e77e81aed621c67","src/empty.rs":"0849e0b7210d33145b3fb1368ed08b13fbc2144b1ccc0a1af913896e916bbe46","src/gles/adapter.rs":"90f0402e2b62b9311d247f3eba2ff956ef38e3799ca08355721730fb9a25e6d3","src/gles/command.rs":"788505168ae1af312781c86d31d5bc289fcc4e2b3cb047fb41deb62542db1a95","src/gles/conv.rs":"2e99a39fbef7a5bb8f2a24779bf5387601ba336de4cac9ff2bdac5b93f48a1d7","src/gles/device.rs":"64a8f202f123a4f2238e295023803724cd3095f2932462cc087a2d2212f0df3d","src/gles/egl.rs":"fed5b9c74ada548f90afcf138985514eadf7cc87859b013a3fa33cc7f72fb201","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"a54401494e4279bd56867fc621bfe3a8252fe82409cdc1594e7b22ee09f68fc0","src/gles/queue.rs":"1d4ea44a8e2ce47f9266260f1f384f02f870473c0411b77c5bab6794ee8484f5","src/gles/shaders/clear.frag":"9133ed8ed97d3641fbb6b5f5ea894a3554c629ccc1b80a5fc9221d7293aa1954","src/gles/shaders/clear.vert":"a543768725f4121ff2e9e1fb5b00644931e9d6f2f946c0ef01968afb5a135abd","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"000ed39eae4a6442ca16bdca68e1e61459e6815a5db8eeec53e0ee0f5f14ae66","src/gles/wgl.rs":"59cd28ba85c6c3cbcbd82fd0e4225303a5f98e6a41b839400f9cce3a1b267af8","src/lib.rs":"88c8e93b1bea9eb31d2632f519c82e1c15b479e29b3700914a033efb59295634","src/metal/adapter.rs":"87636eaedbb18108c592aebf553ba3d84d052be567aa9306457b8cd9a2c6b0e7","src/metal/command.rs":"61640f2cb7269f44487df2d911771fbe1f78484d44a5363a6ddfce7d77143b02","src/metal/conv.rs":"a34a44e6affb594f3285f8d585b0fb33132aa7dc6a612f7c1aecaa400fe43265","src/metal/device.rs":"81ad3f5e4e5967cdb31a5e0f5e9404324b121408409b1422263bd9b0b793dd26","src/metal/mod.rs":"295223d5a06d9752d6911ec25ceb79c17dd93ced84c2c8a052957e6568e2e749","src/metal/surface.rs":"397dab6726eead96f0be9ecb6686874e691079da94c072921a6422e9b1284fb5","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"3c82f3294c330c9b3b3b554ea7ef8601459c4f4d28a34700690230e3572c1d44","src/vulkan/command.rs":"a79df7f455c4061ab404c319e6602e6c1a3567443b50c20ddba6150fbdcc8826","src/vulkan/conv.rs":"47b8d7822703a5bd2b8c80118ee6ac1cd0b985758e2f929317fe4c42ce9a9bd9","src/vulkan/device.rs":"fefa6ebebb2d578323f01420fecd85f36e584efdc8a88a0c89ffc66c9d5524f9","src/vulkan/instance.rs":"60742c3c1feee63eca0953165dae57c86b0d58e496ad374743ff83ae50a4e8f1","src/vulkan/mod.rs":"d1aefbd87a166bd2103b418f096ba777d9bc7d19eb2d1363dd2f351639fc732a"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/wgpu-hal/Cargo.toml b/third_party/rust/wgpu-hal/Cargo.toml
index f601949231..dc9fc7e827 100644
--- a/third_party/rust/wgpu-hal/Cargo.toml
+++ b/third_party/rust/wgpu-hal/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.74"
name = "wgpu-hal"
-version = "0.19.0"
+version = "0.20.0"
authors = ["gfx-rs developers"]
description = "WebGPU hardware abstraction layer"
homepage = "https://wgpu.rs/"
@@ -63,26 +63,25 @@ version = "0.13.1"
optional = true
[dependencies.naga]
-version = "0.19.0"
+version = "0.20.0"
path = "../naga"
-features = ["clone"]
[dependencies.profiling]
version = "1"
default-features = false
[dependencies.wgt]
-version = "0.19.0"
+version = "0.20.0"
path = "../wgpu-types"
package = "wgpu-types"
[dev-dependencies]
cfg-if = "1"
env_logger = "0.11"
-glam = "0.25.0"
+glam = "0.27.0"
[dev-dependencies.naga]
-version = "0.19.0"
+version = "0.20.0"
path = "../naga"
features = ["wgsl-in"]
@@ -156,13 +155,15 @@ features = [
[target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies]
core-graphics-types = "0.1"
-metal = "0.27.0"
objc = "0.2.5"
[target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies.block]
version = "0.1"
optional = true
+[target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies.metal]
+version = "0.28.0"
+
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.ash]
version = "0.37.3"
optional = true
@@ -172,7 +173,7 @@ version = "0.6"
optional = true
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.gpu-descriptor]
-version = "0.2"
+version = "0.3"
optional = true
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.khronos-egl]
@@ -223,7 +224,7 @@ version = "0.5"
optional = true
[target."cfg(windows)".dependencies.d3d12]
-version = "0.19.0"
+version = "0.20.0"
path = "../d3d12/"
features = ["libloading"]
optional = true
diff --git a/third_party/rust/wgpu-hal/README.md b/third_party/rust/wgpu-hal/README.md
index 588baa3cf5..bb5556b3d2 100644
--- a/third_party/rust/wgpu-hal/README.md
+++ b/third_party/rust/wgpu-hal/README.md
@@ -1,23 +1,120 @@
-*wgpu-hal* is an explicit low-level GPU abstraction powering *wgpu-core*.
-It's a spiritual successor to [gfx-hal](https://github.com/gfx-rs/gfx),
-but with reduced scope, and oriented towards WebGPU implementation goals.
+# `wgpu_hal`: a cross-platform unsafe graphics abstraction
-It has no overhead for validation or tracking, and the API translation overhead is kept to the bare minimum by the design of WebGPU.
-This API can be used for resource-demanding applications and engines.
+This crate defines a set of traits abstracting over modern graphics APIs,
+with implementations ("backends") for Vulkan, Metal, Direct3D, and GL.
-# Usage notes
+`wgpu_hal` is a spiritual successor to
+[gfx-hal](https://github.com/gfx-rs/gfx), but with reduced scope, and
+oriented towards WebGPU implementation goals. It has no overhead for
+validation or tracking, and the API translation overhead is kept to the bare
+minimum by the design of WebGPU. This API can be used for resource-demanding
+applications and engines.
-All of the API is `unsafe`. Documenting the exact safety requirements for the
-state and function arguments is desired, but will likely be incomplete while the library is in early development.
+The `wgpu_hal` crate's main design choices:
-The returned errors are only for cases that the user can't anticipate,
-such as running out-of-memory, or losing the device.
-For the counter-example, there is no error for mapping a buffer that's not mappable.
-As the buffer creator, the user should already know if they can map it.
+- Our traits are meant to be *portable*: proper use
+ should get equivalent results regardless of the backend.
-The API accepts iterators in order to avoid forcing the user to store data in particular containers. The implementation doesn't guarantee that any of the iterators are drained, unless stated otherwise by the function documentation.
-For this reason, we recommend that iterators don't do any mutating work.
+- Our traits' contracts are *unsafe*: implementations perform minimal
+ validation, if any, and incorrect use will often cause undefined behavior.
+ This allows us to minimize the overhead we impose over the underlying
+ graphics system. If you need safety, the [`wgpu-core`] crate provides a
+ safe API for driving `wgpu_hal`, implementing all necessary validation,
+ resource state tracking, and so on. (Note that `wgpu-core` is designed for
+ use via FFI; the [`wgpu`] crate provides more idiomatic Rust bindings for
+ `wgpu-core`.) Or, you can do your own validation.
-# Debugging
+- In the same vein, returned errors *only cover cases the user can't
+ anticipate*, like running out of memory or losing the device. Any errors
+ that the user could reasonably anticipate are their responsibility to
+ avoid. For example, `wgpu_hal` returns no error for mapping a buffer that's
+ not mappable: as the buffer creator, the user should already know if they
+ can map it.
+
+- We use *static dispatch*. The traits are not
+ generally object-safe. You must select a specific backend type
+ like [`vulkan::Api`] or [`metal::Api`], and then use that
+ according to the main traits, or call backend-specific methods.
+
+- We use *idiomatic Rust parameter passing*,
+ taking objects by reference, returning them by value, and so on,
+ unlike `wgpu-core`, which refers to objects by ID.
+
+- We map buffer contents *persistently*. This means that the buffer
+ can remain mapped on the CPU while the GPU reads or writes to it.
+ You must explicitly indicate when data might need to be
+ transferred between CPU and GPU, if `wgpu_hal` indicates that the
+ mapping is not coherent (that is, automatically synchronized
+ between the two devices).
+
+- You must record *explicit barriers* between different usages of a
+ resource. For example, if a buffer is written to by a compute
+ shader, and then used as and index buffer to a draw call, you
+ must use [`CommandEncoder::transition_buffers`] between those two
+ operations.
+
+- Pipeline layouts are *explicitly specified* when setting bind
+ group. Incompatible layouts disturb groups bound at higher indices.
+
+- The API *accepts collections as iterators*, to avoid forcing the user to
+ store data in particular containers. The implementation doesn't guarantee
+ that any of the iterators are drained, unless stated otherwise by the
+ function documentation. For this reason, we recommend that iterators don't
+ do any mutating work.
+
+Unfortunately, `wgpu_hal`'s safety requirements are not fully documented.
+Ideally, all trait methods would have doc comments setting out the
+requirements users must meet to ensure correct and portable behavior. If you
+are aware of a specific requirement that a backend imposes that is not
+ensured by the traits' documented rules, please file an issue. Or, if you are
+a capable technical writer, please file a pull request!
+
+[`wgpu-core`]: https://crates.io/crates/wgpu-core
+[`wgpu`]: https://crates.io/crates/wgpu
+[`vulkan::Api`]: vulkan/struct.Api.html
+[`metal::Api`]: metal/struct.Api.html
+
+## Primary backends
+
+The `wgpu_hal` crate has full-featured backends implemented on the following
+platform graphics APIs:
+
+- Vulkan, available on Linux, Android, and Windows, using the [`ash`] crate's
+ Vulkan bindings. It's also available on macOS, if you install [MoltenVK].
+
+- Metal on macOS, using the [`metal`] crate's bindings.
+
+- Direct3D 12 on Windows, using the [`d3d12`] crate's bindings.
+
+[`ash`]: https://crates.io/crates/ash
+[MoltenVK]: https://github.com/KhronosGroup/MoltenVK
+[`metal`]: https://crates.io/crates/metal
+[`d3d12`]: ahttps://crates.io/crates/d3d12
+
+## Secondary backends
+
+The `wgpu_hal` crate has a partial implementation based on the following
+platform graphics API:
+
+- The GL backend is available anywhere OpenGL, OpenGL ES, or WebGL are
+ available. See the [`gles`] module documentation for details.
+
+[`gles`]: gles/index.html
+
+You can see what capabilities an adapter is missing by checking the
+[`DownlevelCapabilities`][tdc] in [`ExposedAdapter::capabilities`], available
+from [`Instance::enumerate_adapters`].
+
+The API is generally designed to fit the primary backends better than the
+secondary backends, so the latter may impose more overhead.
+
+[tdc]: wgt::DownlevelCapabilities
+
+## Debugging
+
+Most of the information on the wiki [Debugging wgpu Applications][wiki-debug]
+page still applies to this API, with the exception of API tracing/replay
+functionality, which is only available in `wgpu-core`.
+
+[wiki-debug]: https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications
-Most of the information in https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications still applies to this API, with an exception of API tracing/replay functionality, which is only available in *wgpu-core*.
diff --git a/third_party/rust/wgpu-hal/examples/halmark/main.rs b/third_party/rust/wgpu-hal/examples/halmark/main.rs
index c238f299e7..aef6919c8f 100644
--- a/third_party/rust/wgpu-hal/examples/halmark/main.rs
+++ b/third_party/rust/wgpu-hal/examples/halmark/main.rs
@@ -245,17 +245,22 @@ impl<A: hal::Api> Example<A> {
.unwrap()
};
+ let constants = naga::back::PipelineConstants::default();
let pipeline_desc = hal::RenderPipelineDescriptor {
label: None,
layout: &pipeline_layout,
vertex_stage: hal::ProgrammableStage {
module: &shader,
entry_point: "vs_main",
+ constants: &constants,
+ zero_initialize_workgroup_memory: true,
},
vertex_buffers: &[],
fragment_stage: Some(hal::ProgrammableStage {
module: &shader,
entry_point: "fs_main",
+ constants: &constants,
+ zero_initialize_workgroup_memory: true,
}),
primitive: wgt::PrimitiveState {
topology: wgt::PrimitiveTopology::TriangleStrip,
@@ -840,6 +845,7 @@ fn main() {
}
}
ex.render();
+ window.request_redraw();
}
_ => {
example.as_mut().unwrap().update(event);
diff --git a/third_party/rust/wgpu-hal/examples/ray-traced-triangle/main.rs b/third_party/rust/wgpu-hal/examples/ray-traced-triangle/main.rs
index c05feae820..3985cd60af 100644
--- a/third_party/rust/wgpu-hal/examples/ray-traced-triangle/main.rs
+++ b/third_party/rust/wgpu-hal/examples/ray-traced-triangle/main.rs
@@ -371,6 +371,8 @@ impl<A: hal::Api> Example<A> {
stage: hal::ProgrammableStage {
module: &shader_module,
entry_point: "main",
+ constants: &Default::default(),
+ zero_initialize_workgroup_memory: true,
},
})
}
diff --git a/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs b/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs
index 6af4b77bb3..e5162362f7 100644
--- a/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs
+++ b/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs
@@ -261,6 +261,7 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT {
Vf::Uint32x4 => DXGI_FORMAT_R32G32B32A32_UINT,
Vf::Sint32x4 => DXGI_FORMAT_R32G32B32A32_SINT,
Vf::Float32x4 => DXGI_FORMAT_R32G32B32A32_FLOAT,
+ Vf::Unorm10_10_10_2 => DXGI_FORMAT_R10G10B10A2_UNORM,
Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(),
}
}
diff --git a/third_party/rust/wgpu-hal/src/dx12/adapter.rs b/third_party/rust/wgpu-hal/src/dx12/adapter.rs
index b417a88a6f..faf25cc852 100644
--- a/third_party/rust/wgpu-hal/src/dx12/adapter.rs
+++ b/third_party/rust/wgpu-hal/src/dx12/adapter.rs
@@ -115,18 +115,6 @@ impl super::Adapter {
)
});
- let mut shader_model_support: d3d12_ty::D3D12_FEATURE_DATA_SHADER_MODEL =
- d3d12_ty::D3D12_FEATURE_DATA_SHADER_MODEL {
- HighestShaderModel: d3d12_ty::D3D_SHADER_MODEL_6_0,
- };
- assert_eq!(0, unsafe {
- device.CheckFeatureSupport(
- d3d12_ty::D3D12_FEATURE_SHADER_MODEL,
- &mut shader_model_support as *mut _ as *mut _,
- mem::size_of::<d3d12_ty::D3D12_FEATURE_DATA_SHADER_MODEL>() as _,
- )
- });
-
let mut workarounds = super::Workarounds::default();
let info = wgt::AdapterInfo {
@@ -181,6 +169,53 @@ impl super::Adapter {
hr == 0 && features3.CastingFullyTypedFormatSupported != 0
};
+ let shader_model = if dxc_container.is_none() {
+ naga::back::hlsl::ShaderModel::V5_1
+ } else {
+ let mut versions = [
+ crate::dx12::types::D3D_SHADER_MODEL_6_7,
+ crate::dx12::types::D3D_SHADER_MODEL_6_6,
+ crate::dx12::types::D3D_SHADER_MODEL_6_5,
+ crate::dx12::types::D3D_SHADER_MODEL_6_4,
+ crate::dx12::types::D3D_SHADER_MODEL_6_3,
+ crate::dx12::types::D3D_SHADER_MODEL_6_2,
+ crate::dx12::types::D3D_SHADER_MODEL_6_1,
+ crate::dx12::types::D3D_SHADER_MODEL_6_0,
+ crate::dx12::types::D3D_SHADER_MODEL_5_1,
+ ]
+ .iter();
+ match loop {
+ if let Some(&sm) = versions.next() {
+ let mut sm = crate::dx12::types::D3D12_FEATURE_DATA_SHADER_MODEL {
+ HighestShaderModel: sm,
+ };
+ if 0 == unsafe {
+ device.CheckFeatureSupport(
+ 7, // D3D12_FEATURE_SHADER_MODEL
+ &mut sm as *mut _ as *mut _,
+ mem::size_of::<crate::dx12::types::D3D12_FEATURE_DATA_SHADER_MODEL>()
+ as _,
+ )
+ } {
+ break sm.HighestShaderModel;
+ }
+ } else {
+ break crate::dx12::types::D3D_SHADER_MODEL_5_1;
+ }
+ } {
+ crate::dx12::types::D3D_SHADER_MODEL_5_1 => naga::back::hlsl::ShaderModel::V5_1,
+ crate::dx12::types::D3D_SHADER_MODEL_6_0 => naga::back::hlsl::ShaderModel::V6_0,
+ crate::dx12::types::D3D_SHADER_MODEL_6_1 => naga::back::hlsl::ShaderModel::V6_1,
+ crate::dx12::types::D3D_SHADER_MODEL_6_2 => naga::back::hlsl::ShaderModel::V6_2,
+ crate::dx12::types::D3D_SHADER_MODEL_6_3 => naga::back::hlsl::ShaderModel::V6_3,
+ crate::dx12::types::D3D_SHADER_MODEL_6_4 => naga::back::hlsl::ShaderModel::V6_4,
+ crate::dx12::types::D3D_SHADER_MODEL_6_5 => naga::back::hlsl::ShaderModel::V6_5,
+ crate::dx12::types::D3D_SHADER_MODEL_6_6 => naga::back::hlsl::ShaderModel::V6_6,
+ crate::dx12::types::D3D_SHADER_MODEL_6_7 => naga::back::hlsl::ShaderModel::V6_7,
+ _ => unreachable!(),
+ }
+ };
+
let private_caps = super::PrivateCapabilities {
instance_flags,
heterogeneous_resource_heaps: options.ResourceHeapTier
@@ -196,6 +231,7 @@ impl super::Adapter {
casting_fully_typed_format_supported,
// See https://github.com/gfx-rs/wgpu/issues/3552
suballocation_supported: !info.name.contains("Iris(R) Xe"),
+ shader_model,
};
// Theoretically vram limited, but in practice 2^20 is the limit
@@ -273,7 +309,7 @@ impl super::Adapter {
wgt::Features::TEXTURE_BINDING_ARRAY
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
| wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
- shader_model_support.HighestShaderModel >= d3d12_ty::D3D_SHADER_MODEL_5_1,
+ shader_model >= naga::back::hlsl::ShaderModel::V5_1,
);
let bgra8unorm_storage_supported = {
@@ -295,21 +331,28 @@ impl super::Adapter {
bgra8unorm_storage_supported,
);
- // we must be using DXC because uint64_t was added with Shader Model 6
- // and FXC only supports up to 5.1
- let int64_shader_ops_supported = dxc_container.is_some() && {
- let mut features1: d3d12_ty::D3D12_FEATURE_DATA_D3D12_OPTIONS1 =
- unsafe { mem::zeroed() };
- let hr = unsafe {
- device.CheckFeatureSupport(
- d3d12_ty::D3D12_FEATURE_D3D12_OPTIONS1,
- &mut features1 as *mut _ as *mut _,
- mem::size_of::<d3d12_ty::D3D12_FEATURE_DATA_D3D12_OPTIONS1>() as _,
- )
- };
- hr == 0 && features1.Int64ShaderOps != 0
+ let mut features1: d3d12_ty::D3D12_FEATURE_DATA_D3D12_OPTIONS1 = unsafe { mem::zeroed() };
+ let hr = unsafe {
+ device.CheckFeatureSupport(
+ d3d12_ty::D3D12_FEATURE_D3D12_OPTIONS1,
+ &mut features1 as *mut _ as *mut _,
+ mem::size_of::<d3d12_ty::D3D12_FEATURE_DATA_D3D12_OPTIONS1>() as _,
+ )
};
- features.set(wgt::Features::SHADER_INT64, int64_shader_ops_supported);
+
+ features.set(
+ wgt::Features::SHADER_INT64,
+ shader_model >= naga::back::hlsl::ShaderModel::V6_0
+ && hr == 0
+ && features1.Int64ShaderOps != 0,
+ );
+
+ features.set(
+ wgt::Features::SUBGROUP,
+ shader_model >= naga::back::hlsl::ShaderModel::V6_0
+ && hr == 0
+ && features1.WaveOps != 0,
+ );
// float32-filterable should always be available on d3d12
features.set(wgt::Features::FLOAT32_FILTERABLE, true);
@@ -377,6 +420,8 @@ impl super::Adapter {
.min(crate::MAX_VERTEX_BUFFERS as u32),
max_vertex_attributes: d3d12_ty::D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT,
max_vertex_buffer_array_stride: d3d12_ty::D3D12_SO_BUFFER_MAX_STRIDE_IN_BYTES,
+ min_subgroup_size: 4, // Not using `features1.WaveLaneCountMin` as it is unreliable
+ max_subgroup_size: 128,
// The push constants are part of the root signature which
// has a limit of 64 DWORDS (256 bytes), but other resources
// also share the root signature:
diff --git a/third_party/rust/wgpu-hal/src/dx12/conv.rs b/third_party/rust/wgpu-hal/src/dx12/conv.rs
index 2b6c1d959e..b09ea76080 100644
--- a/third_party/rust/wgpu-hal/src/dx12/conv.rs
+++ b/third_party/rust/wgpu-hal/src/dx12/conv.rs
@@ -224,7 +224,7 @@ pub fn map_polygon_mode(mode: wgt::PolygonMode) -> d3d12_ty::D3D12_FILL_MODE {
}
/// D3D12 doesn't support passing factors ending in `_COLOR` for alpha blending
-/// (see https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc).
+/// (see <https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc>).
/// Therefore this function takes an additional `is_alpha` argument
/// which if set will return an equivalent `_ALPHA` factor.
fn map_blend_factor(factor: wgt::BlendFactor, is_alpha: bool) -> d3d12_ty::D3D12_BLEND {
diff --git a/third_party/rust/wgpu-hal/src/dx12/device.rs b/third_party/rust/wgpu-hal/src/dx12/device.rs
index 23bd409dc4..82075294ee 100644
--- a/third_party/rust/wgpu-hal/src/dx12/device.rs
+++ b/third_party/rust/wgpu-hal/src/dx12/device.rs
@@ -218,21 +218,39 @@ impl super::Device {
use naga::back::hlsl;
let stage_bit = crate::auxil::map_naga_stage(naga_stage);
- let module = &stage.module.naga.module;
+
+ let (module, info) = naga::back::pipeline_constants::process_overrides(
+ &stage.module.naga.module,
+ &stage.module.naga.info,
+ stage.constants,
+ )
+ .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("HLSL: {e:?}")))?;
+
+ let needs_temp_options = stage.zero_initialize_workgroup_memory
+ != layout.naga_options.zero_initialize_workgroup_memory;
+ let mut temp_options;
+ let naga_options = if needs_temp_options {
+ temp_options = layout.naga_options.clone();
+ temp_options.zero_initialize_workgroup_memory = stage.zero_initialize_workgroup_memory;
+ &temp_options
+ } else {
+ &layout.naga_options
+ };
+
//TODO: reuse the writer
let mut source = String::new();
- let mut writer = hlsl::Writer::new(&mut source, &layout.naga_options);
+ let mut writer = hlsl::Writer::new(&mut source, naga_options);
let reflection_info = {
profiling::scope!("naga::back::hlsl::write");
writer
- .write(module, &stage.module.naga.info)
+ .write(&module, &info)
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("HLSL: {e:?}")))?
};
let full_stage = format!(
"{}_{}\0",
naga_stage.to_hlsl_str(),
- layout.naga_options.shader_model.to_str()
+ naga_options.shader_model.to_str()
);
let ep_index = module
@@ -1062,12 +1080,7 @@ impl crate::Device for super::Device {
},
bind_group_infos,
naga_options: hlsl::Options {
- shader_model: match self.dxc_container {
- // DXC
- Some(_) => hlsl::ShaderModel::V6_0,
- // FXC doesn't support SM 6.0
- None => hlsl::ShaderModel::V5_1,
- },
+ shader_model: self.private_caps.shader_model,
binding_map,
fake_missing_bindings: false,
special_constants_binding,
diff --git a/third_party/rust/wgpu-hal/src/dx12/mod.rs b/third_party/rust/wgpu-hal/src/dx12/mod.rs
index 4f958943ca..9f021bc241 100644
--- a/third_party/rust/wgpu-hal/src/dx12/mod.rs
+++ b/third_party/rust/wgpu-hal/src/dx12/mod.rs
@@ -195,6 +195,7 @@ struct PrivateCapabilities {
heap_create_not_zeroed: bool,
casting_fully_typed_format_supported: bool,
suballocation_supported: bool,
+ shader_model: naga::back::hlsl::ShaderModel,
}
#[derive(Default)]
@@ -439,7 +440,7 @@ impl Texture {
}
}
- /// see https://learn.microsoft.com/en-us/windows/win32/direct3d12/subresources#plane-slice
+ /// see <https://learn.microsoft.com/en-us/windows/win32/direct3d12/subresources#plane-slice>
fn calc_subresource(&self, mip_level: u32, array_layer: u32, plane: u32) -> u32 {
mip_level + (array_layer + plane * self.array_layer_count()) * self.mip_level_count
}
diff --git a/third_party/rust/wgpu-hal/src/dx12/types.rs b/third_party/rust/wgpu-hal/src/dx12/types.rs
index b4ad38324a..17b608b840 100644
--- a/third_party/rust/wgpu-hal/src/dx12/types.rs
+++ b/third_party/rust/wgpu-hal/src/dx12/types.rs
@@ -41,3 +41,25 @@ winapi::STRUCT! {
BarycentricsSupported: winapi::shared::minwindef::BOOL,
}
}
+
+winapi::ENUM! {
+ enum D3D_SHADER_MODEL {
+ D3D_SHADER_MODEL_NONE = 0,
+ D3D_SHADER_MODEL_5_1 = 0x51,
+ D3D_SHADER_MODEL_6_0 = 0x60,
+ D3D_SHADER_MODEL_6_1 = 0x61,
+ D3D_SHADER_MODEL_6_2 = 0x62,
+ D3D_SHADER_MODEL_6_3 = 0x63,
+ D3D_SHADER_MODEL_6_4 = 0x64,
+ D3D_SHADER_MODEL_6_5 = 0x65,
+ D3D_SHADER_MODEL_6_6 = 0x66,
+ D3D_SHADER_MODEL_6_7 = 0x67,
+ D3D_HIGHEST_SHADER_MODEL = 0x67,
+ }
+}
+
+winapi::STRUCT! {
+ struct D3D12_FEATURE_DATA_SHADER_MODEL {
+ HighestShaderModel: D3D_SHADER_MODEL,
+ }
+}
diff --git a/third_party/rust/wgpu-hal/src/gles/adapter.rs b/third_party/rust/wgpu-hal/src/gles/adapter.rs
index b9d044337c..052c77006b 100644
--- a/third_party/rust/wgpu-hal/src/gles/adapter.rs
+++ b/third_party/rust/wgpu-hal/src/gles/adapter.rs
@@ -104,7 +104,7 @@ impl super::Adapter {
}
}
- fn make_info(vendor_orig: String, renderer_orig: String) -> wgt::AdapterInfo {
+ fn make_info(vendor_orig: String, renderer_orig: String, version: String) -> wgt::AdapterInfo {
let vendor = vendor_orig.to_lowercase();
let renderer = renderer_orig.to_lowercase();
@@ -179,13 +179,33 @@ impl super::Adapter {
0
};
+ let driver;
+ let driver_info;
+ if version.starts_with("WebGL ") || version.starts_with("OpenGL ") {
+ let es_sig = " ES";
+ match version.find(es_sig) {
+ Some(pos) => {
+ driver = version[..pos + es_sig.len()].to_owned();
+ driver_info = version[pos + es_sig.len() + 1..].to_owned();
+ }
+ None => {
+ let pos = version.find(' ').unwrap();
+ driver = version[..pos].to_owned();
+ driver_info = version[pos + 1..].to_owned();
+ }
+ }
+ } else {
+ driver = "OpenGL".to_owned();
+ driver_info = version;
+ }
+
wgt::AdapterInfo {
name: renderer_orig,
vendor: vendor_id,
device: 0,
device_type: inferred_device_type,
- driver: String::new(),
- driver_info: String::new(),
+ driver,
+ driver_info,
backend: wgt::Backend::Gl,
}
}
@@ -507,8 +527,7 @@ impl super::Adapter {
let has_etc = if cfg!(any(webgl, Emscripten)) {
extensions.contains("WEBGL_compressed_texture_etc")
} else {
- // This is a required part of GLES3, but not part of Desktop GL at all.
- es_ver.is_some()
+ es_ver.is_some() || extensions.contains("GL_ARB_ES3_compatibility")
};
features.set(wgt::Features::TEXTURE_COMPRESSION_ETC2, has_etc);
@@ -728,6 +747,8 @@ impl super::Adapter {
} else {
!0
},
+ min_subgroup_size: 0,
+ max_subgroup_size: 0,
max_push_constant_size: super::MAX_PUSH_CONSTANTS as u32 * 4,
min_uniform_buffer_offset_alignment,
min_storage_buffer_offset_alignment,
@@ -825,7 +846,7 @@ impl super::Adapter {
max_msaa_samples: max_samples,
}),
},
- info: Self::make_info(vendor, renderer),
+ info: Self::make_info(vendor, renderer, version),
features,
capabilities: crate::Capabilities {
limits,
diff --git a/third_party/rust/wgpu-hal/src/gles/conv.rs b/third_party/rust/wgpu-hal/src/gles/conv.rs
index bde69b8629..a6c924f162 100644
--- a/third_party/rust/wgpu-hal/src/gles/conv.rs
+++ b/third_party/rust/wgpu-hal/src/gles/conv.rs
@@ -212,6 +212,7 @@ pub(super) fn describe_vertex_format(vertex_format: wgt::VertexFormat) -> super:
Vf::Uint32x4 => (4, glow::UNSIGNED_INT, Vak::Integer),
Vf::Sint32x4 => (4, glow::INT, Vak::Integer),
Vf::Float32x4 => (4, glow::FLOAT, Vak::Float),
+ Vf::Unorm10_10_10_2 => (4, glow::UNSIGNED_INT_10_10_10_2, Vak::Float),
Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(),
};
diff --git a/third_party/rust/wgpu-hal/src/gles/device.rs b/third_party/rust/wgpu-hal/src/gles/device.rs
index 50c07f3ff0..a1e2736aa6 100644
--- a/third_party/rust/wgpu-hal/src/gles/device.rs
+++ b/third_party/rust/wgpu-hal/src/gles/device.rs
@@ -220,9 +220,17 @@ impl super::Device {
multiview: context.multiview,
};
- let shader = &stage.module.naga;
- let entry_point_index = shader
- .module
+ let (module, info) = naga::back::pipeline_constants::process_overrides(
+ &stage.module.naga.module,
+ &stage.module.naga.info,
+ stage.constants,
+ )
+ .map_err(|e| {
+ let msg = format!("{e}");
+ crate::PipelineError::Linkage(map_naga_stage(naga_stage), msg)
+ })?;
+
+ let entry_point_index = module
.entry_points
.iter()
.position(|ep| ep.name.as_str() == stage.entry_point)
@@ -247,11 +255,23 @@ impl super::Device {
};
let mut output = String::new();
+ let needs_temp_options = stage.zero_initialize_workgroup_memory
+ != context.layout.naga_options.zero_initialize_workgroup_memory;
+ let mut temp_options;
+ let naga_options = if needs_temp_options {
+ // We use a conditional here, as cloning the naga_options could be expensive
+ // That is, we want to avoid doing that unless we cannot avoid it
+ temp_options = context.layout.naga_options.clone();
+ temp_options.zero_initialize_workgroup_memory = stage.zero_initialize_workgroup_memory;
+ &temp_options
+ } else {
+ &context.layout.naga_options
+ };
let mut writer = glsl::Writer::new(
&mut output,
- &shader.module,
- &shader.info,
- &context.layout.naga_options,
+ &module,
+ &info,
+ naga_options,
&pipeline_options,
policies,
)
@@ -269,8 +289,8 @@ impl super::Device {
context.consume_reflection(
gl,
- &shader.module,
- shader.info.get_entry_point(entry_point_index),
+ &module,
+ info.get_entry_point(entry_point_index),
reflection_info,
naga_stage,
program,
@@ -297,6 +317,7 @@ impl super::Device {
naga_stage: naga_stage.to_owned(),
shader_id: stage.module.id,
entry_point: stage.entry_point.to_owned(),
+ zero_initialize_workgroup_memory: stage.zero_initialize_workgroup_memory,
});
}
let mut guard = self
diff --git a/third_party/rust/wgpu-hal/src/gles/egl.rs b/third_party/rust/wgpu-hal/src/gles/egl.rs
index b166f4f102..00ef70ba88 100644
--- a/third_party/rust/wgpu-hal/src/gles/egl.rs
+++ b/third_party/rust/wgpu-hal/src/gles/egl.rs
@@ -526,28 +526,51 @@ impl Inner {
}
let (config, supports_native_window) = choose_config(&egl, display, srgb_kind)?;
- egl.bind_api(khronos_egl::OPENGL_ES_API).unwrap();
+
+ let supports_opengl = if version >= (1, 4) {
+ let client_apis = egl
+ .query_string(Some(display), khronos_egl::CLIENT_APIS)
+ .unwrap()
+ .to_string_lossy();
+ client_apis
+ .split(' ')
+ .any(|client_api| client_api == "OpenGL")
+ } else {
+ false
+ };
+ egl.bind_api(if supports_opengl {
+ khronos_egl::OPENGL_API
+ } else {
+ khronos_egl::OPENGL_ES_API
+ })
+ .unwrap();
let needs_robustness = true;
let mut khr_context_flags = 0;
let supports_khr_context = display_extensions.contains("EGL_KHR_create_context");
- //TODO: make it so `Device` == EGL Context
- let mut context_attributes = vec![
- khronos_egl::CONTEXT_MAJOR_VERSION,
- 3, // Request GLES 3.0 or higher
- ];
-
- if force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
+ let mut context_attributes = vec![];
+ if supports_opengl {
+ context_attributes.push(khronos_egl::CONTEXT_MAJOR_VERSION);
+ context_attributes.push(3);
context_attributes.push(khronos_egl::CONTEXT_MINOR_VERSION);
- context_attributes.push(match force_gles_minor_version {
- wgt::Gles3MinorVersion::Version0 => 0,
- wgt::Gles3MinorVersion::Version1 => 1,
- wgt::Gles3MinorVersion::Version2 => 2,
- _ => unreachable!(),
- });
+ context_attributes.push(3);
+ if force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
+ log::warn!("Ignoring specified GLES minor version as OpenGL is used");
+ }
+ } else {
+ context_attributes.push(khronos_egl::CONTEXT_MAJOR_VERSION);
+ context_attributes.push(3); // Request GLES 3.0 or higher
+ if force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
+ context_attributes.push(khronos_egl::CONTEXT_MINOR_VERSION);
+ context_attributes.push(match force_gles_minor_version {
+ wgt::Gles3MinorVersion::Automatic => unreachable!(),
+ wgt::Gles3MinorVersion::Version0 => 0,
+ wgt::Gles3MinorVersion::Version1 => 1,
+ wgt::Gles3MinorVersion::Version2 => 2,
+ });
+ }
}
-
if flags.contains(wgt::InstanceFlags::DEBUG) {
if version >= (1, 5) {
log::debug!("\tEGL context: +debug");
@@ -577,8 +600,6 @@ impl Inner {
// because it's for desktop GL only, not GLES.
log::warn!("\tEGL context: -robust access");
}
-
- //TODO do we need `khronos_egl::CONTEXT_OPENGL_NOTIFICATION_STRATEGY_EXT`?
}
if khr_context_flags != 0 {
context_attributes.push(EGL_CONTEXT_FLAGS_KHR);
@@ -977,6 +998,7 @@ impl crate::Instance for Instance {
srgb_kind: inner.srgb_kind,
})
}
+
unsafe fn destroy_surface(&self, _surface: Surface) {}
unsafe fn enumerate_adapters(&self) -> Vec<crate::ExposedAdapter<super::Api>> {
@@ -993,6 +1015,12 @@ impl crate::Instance for Instance {
})
};
+ // In contrast to OpenGL ES, OpenGL requires explicitly enabling sRGB conversions,
+ // as otherwise the user has to do the sRGB conversion.
+ if !matches!(inner.srgb_kind, SrgbFrameBufferKind::None) {
+ unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) };
+ }
+
if self.flags.contains(wgt::InstanceFlags::DEBUG) && gl.supports_debug() {
log::debug!("Max label length: {}", unsafe {
gl.get_parameter_i32(glow::MAX_LABEL_LENGTH)
@@ -1106,6 +1134,13 @@ impl Surface {
unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) };
unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(sc.framebuffer)) };
+
+ if !matches!(self.srgb_kind, SrgbFrameBufferKind::None) {
+ // Disable sRGB conversions for `glBlitFramebuffer` as behavior does diverge between
+ // drivers and formats otherwise and we want to ensure no sRGB conversions happen.
+ unsafe { gl.disable(glow::FRAMEBUFFER_SRGB) };
+ }
+
// Note the Y-flipping here. GL's presentation is not flipped,
// but main rendering is. Therefore, we Y-flip the output positions
// in the shader, and also this blit.
@@ -1123,6 +1158,11 @@ impl Surface {
glow::NEAREST,
)
};
+
+ if !matches!(self.srgb_kind, SrgbFrameBufferKind::None) {
+ unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) };
+ }
+
unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) };
self.egl
diff --git a/third_party/rust/wgpu-hal/src/gles/mod.rs b/third_party/rust/wgpu-hal/src/gles/mod.rs
index 6f41f7c000..0fcb09be46 100644
--- a/third_party/rust/wgpu-hal/src/gles/mod.rs
+++ b/third_party/rust/wgpu-hal/src/gles/mod.rs
@@ -602,6 +602,7 @@ struct ProgramStage {
naga_stage: naga::ShaderStage,
shader_id: ShaderId,
entry_point: String,
+ zero_initialize_workgroup_memory: bool,
}
#[derive(PartialEq, Eq, Hash)]
diff --git a/third_party/rust/wgpu-hal/src/gles/queue.rs b/third_party/rust/wgpu-hal/src/gles/queue.rs
index 29dfb79d04..7c728d3978 100644
--- a/third_party/rust/wgpu-hal/src/gles/queue.rs
+++ b/third_party/rust/wgpu-hal/src/gles/queue.rs
@@ -213,12 +213,27 @@ impl super::Queue {
instance_count,
ref first_instance_location,
} => {
- match base_vertex {
- 0 => {
- unsafe {
- gl.uniform_1_u32(first_instance_location.as_ref(), first_instance)
- };
+ let supports_full_instancing = self
+ .shared
+ .private_caps
+ .contains(PrivateCapabilities::FULLY_FEATURED_INSTANCING);
+ if supports_full_instancing {
+ unsafe {
+ gl.draw_elements_instanced_base_vertex_base_instance(
+ topology,
+ index_count as i32,
+ index_type,
+ index_offset as i32,
+ instance_count as i32,
+ base_vertex,
+ first_instance,
+ )
+ }
+ } else {
+ unsafe { gl.uniform_1_u32(first_instance_location.as_ref(), first_instance) };
+
+ if base_vertex == 0 {
unsafe {
// Don't use `gl.draw_elements`/`gl.draw_elements_base_vertex` for `instance_count == 1`.
// Angle has a bug where it doesn't consider the instance divisor when `DYNAMIC_DRAW` is used in `gl.draw_elements`/`gl.draw_elements_base_vertex`.
@@ -231,41 +246,17 @@ impl super::Queue {
instance_count as i32,
)
}
- }
- _ => {
- let supports_full_instancing = self
- .shared
- .private_caps
- .contains(PrivateCapabilities::FULLY_FEATURED_INSTANCING);
-
- if supports_full_instancing {
- unsafe {
- gl.draw_elements_instanced_base_vertex_base_instance(
- topology,
- index_count as i32,
- index_type,
- index_offset as i32,
- instance_count as i32,
- base_vertex,
- first_instance,
- )
- }
- } else {
- unsafe {
- gl.uniform_1_u32(first_instance_location.as_ref(), first_instance)
- };
-
- // If we've gotten here, wgpu-core has already validated that this function exists via the DownlevelFlags::BASE_VERTEX feature.
- unsafe {
- gl.draw_elements_instanced_base_vertex(
- topology,
- index_count as _,
- index_type,
- index_offset as i32,
- instance_count as i32,
- base_vertex,
- )
- }
+ } else {
+ // If we've gotten here, wgpu-core has already validated that this function exists via the DownlevelFlags::BASE_VERTEX feature.
+ unsafe {
+ gl.draw_elements_instanced_base_vertex(
+ topology,
+ index_count as _,
+ index_type,
+ index_offset as i32,
+ instance_count as i32,
+ base_vertex,
+ )
}
}
}
diff --git a/third_party/rust/wgpu-hal/src/gles/wgl.rs b/third_party/rust/wgpu-hal/src/gles/wgl.rs
index 2564892969..aae70478b4 100644
--- a/third_party/rust/wgpu-hal/src/gles/wgl.rs
+++ b/third_party/rust/wgpu-hal/src/gles/wgl.rs
@@ -507,6 +507,8 @@ impl crate::Instance for Instance {
.supported_extensions()
.contains("GL_ARB_framebuffer_sRGB");
+ // In contrast to OpenGL ES, OpenGL requires explicitly enabling sRGB conversions,
+ // as otherwise the user has to do the sRGB conversion.
if srgb_capable {
unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) };
}
diff --git a/third_party/rust/wgpu-hal/src/lib.rs b/third_party/rust/wgpu-hal/src/lib.rs
index 79bd54e66e..d300ca30cc 100644
--- a/third_party/rust/wgpu-hal/src/lib.rs
+++ b/third_party/rust/wgpu-hal/src/lib.rs
@@ -1,17 +1,208 @@
-/*! This library describes the internal unsafe graphics abstraction API.
- * It follows WebGPU for the most part, re-using wgpu-types,
- * with the following deviations:
- * - Fully unsafe: zero overhead, zero validation.
- * - Compile-time backend selection via traits.
- * - Objects are passed by references and returned by value. No IDs.
- * - Mapping is persistent, with explicit synchronization.
- * - Resource transitions are explicit.
- * - All layouts are explicit. Binding model has compatibility.
+/*! A cross-platform unsafe graphics abstraction.
*
- * General design direction is to follow the majority by the following weights:
- * - wgpu-core: 1.5
- * - primary backends (Vulkan/Metal/DX12): 1.0 each
- * - secondary backend (GLES): 0.5
+ * This crate defines a set of traits abstracting over modern graphics APIs,
+ * with implementations ("backends") for Vulkan, Metal, Direct3D, and GL.
+ *
+ * `wgpu-hal` is a spiritual successor to
+ * [gfx-hal](https://github.com/gfx-rs/gfx), but with reduced scope, and
+ * oriented towards WebGPU implementation goals. It has no overhead for
+ * validation or tracking, and the API translation overhead is kept to the bare
+ * minimum by the design of WebGPU. This API can be used for resource-demanding
+ * applications and engines.
+ *
+ * The `wgpu-hal` crate's main design choices:
+ *
+ * - Our traits are meant to be *portable*: proper use
+ * should get equivalent results regardless of the backend.
+ *
+ * - Our traits' contracts are *unsafe*: implementations perform minimal
+ * validation, if any, and incorrect use will often cause undefined behavior.
+ * This allows us to minimize the overhead we impose over the underlying
+ * graphics system. If you need safety, the [`wgpu-core`] crate provides a
+ * safe API for driving `wgpu-hal`, implementing all necessary validation,
+ * resource state tracking, and so on. (Note that `wgpu-core` is designed for
+ * use via FFI; the [`wgpu`] crate provides more idiomatic Rust bindings for
+ * `wgpu-core`.) Or, you can do your own validation.
+ *
+ * - In the same vein, returned errors *only cover cases the user can't
+ * anticipate*, like running out of memory or losing the device. Any errors
+ * that the user could reasonably anticipate are their responsibility to
+ * avoid. For example, `wgpu-hal` returns no error for mapping a buffer that's
+ * not mappable: as the buffer creator, the user should already know if they
+ * can map it.
+ *
+ * - We use *static dispatch*. The traits are not
+ * generally object-safe. You must select a specific backend type
+ * like [`vulkan::Api`] or [`metal::Api`], and then use that
+ * according to the main traits, or call backend-specific methods.
+ *
+ * - We use *idiomatic Rust parameter passing*,
+ * taking objects by reference, returning them by value, and so on,
+ * unlike `wgpu-core`, which refers to objects by ID.
+ *
+ * - We map buffer contents *persistently*. This means that the buffer
+ * can remain mapped on the CPU while the GPU reads or writes to it.
+ * You must explicitly indicate when data might need to be
+ * transferred between CPU and GPU, if `wgpu-hal` indicates that the
+ * mapping is not coherent (that is, automatically synchronized
+ * between the two devices).
+ *
+ * - You must record *explicit barriers* between different usages of a
+ * resource. For example, if a buffer is written to by a compute
+ * shader, and then used as and index buffer to a draw call, you
+ * must use [`CommandEncoder::transition_buffers`] between those two
+ * operations.
+ *
+ * - Pipeline layouts are *explicitly specified* when setting bind
+ * group. Incompatible layouts disturb groups bound at higher indices.
+ *
+ * - The API *accepts collections as iterators*, to avoid forcing the user to
+ * store data in particular containers. The implementation doesn't guarantee
+ * that any of the iterators are drained, unless stated otherwise by the
+ * function documentation. For this reason, we recommend that iterators don't
+ * do any mutating work.
+ *
+ * Unfortunately, `wgpu-hal`'s safety requirements are not fully documented.
+ * Ideally, all trait methods would have doc comments setting out the
+ * requirements users must meet to ensure correct and portable behavior. If you
+ * are aware of a specific requirement that a backend imposes that is not
+ * ensured by the traits' documented rules, please file an issue. Or, if you are
+ * a capable technical writer, please file a pull request!
+ *
+ * [`wgpu-core`]: https://crates.io/crates/wgpu-core
+ * [`wgpu`]: https://crates.io/crates/wgpu
+ * [`vulkan::Api`]: vulkan/struct.Api.html
+ * [`metal::Api`]: metal/struct.Api.html
+ *
+ * ## Primary backends
+ *
+ * The `wgpu-hal` crate has full-featured backends implemented on the following
+ * platform graphics APIs:
+ *
+ * - Vulkan, available on Linux, Android, and Windows, using the [`ash`] crate's
+ * Vulkan bindings. It's also available on macOS, if you install [MoltenVK].
+ *
+ * - Metal on macOS, using the [`metal`] crate's bindings.
+ *
+ * - Direct3D 12 on Windows, using the [`d3d12`] crate's bindings.
+ *
+ * [`ash`]: https://crates.io/crates/ash
+ * [MoltenVK]: https://github.com/KhronosGroup/MoltenVK
+ * [`metal`]: https://crates.io/crates/metal
+ * [`d3d12`]: ahttps://crates.io/crates/d3d12
+ *
+ * ## Secondary backends
+ *
+ * The `wgpu-hal` crate has a partial implementation based on the following
+ * platform graphics API:
+ *
+ * - The GL backend is available anywhere OpenGL, OpenGL ES, or WebGL are
+ * available. See the [`gles`] module documentation for details.
+ *
+ * [`gles`]: gles/index.html
+ *
+ * You can see what capabilities an adapter is missing by checking the
+ * [`DownlevelCapabilities`][tdc] in [`ExposedAdapter::capabilities`], available
+ * from [`Instance::enumerate_adapters`].
+ *
+ * The API is generally designed to fit the primary backends better than the
+ * secondary backends, so the latter may impose more overhead.
+ *
+ * [tdc]: wgt::DownlevelCapabilities
+ *
+ * ## Traits
+ *
+ * The `wgpu-hal` crate defines a handful of traits that together
+ * represent a cross-platform abstraction for modern GPU APIs.
+ *
+ * - The [`Api`] trait represents a `wgpu-hal` backend. It has no methods of its
+ * own, only a collection of associated types.
+ *
+ * - [`Api::Instance`] implements the [`Instance`] trait. [`Instance::init`]
+ * creates an instance value, which you can use to enumerate the adapters
+ * available on the system. For example, [`vulkan::Api::Instance::init`][Ii]
+ * returns an instance that can enumerate the Vulkan physical devices on your
+ * system.
+ *
+ * - [`Api::Adapter`] implements the [`Adapter`] trait, representing a
+ * particular device from a particular backend. For example, a Vulkan instance
+ * might have a Lavapipe software adapter and a GPU-based adapter.
+ *
+ * - [`Api::Device`] implements the [`Device`] trait, representing an active
+ * link to a device. You get a device value by calling [`Adapter::open`], and
+ * then use it to create buffers, textures, shader modules, and so on.
+ *
+ * - [`Api::Queue`] implements the [`Queue`] trait, which you use to submit
+ * command buffers to a given device.
+ *
+ * - [`Api::CommandEncoder`] implements the [`CommandEncoder`] trait, which you
+ * use to build buffers of commands to submit to a queue. This has all the
+ * methods for drawing and running compute shaders, which is presumably what
+ * you're here for.
+ *
+ * - [`Api::Surface`] implements the [`Surface`] trait, which represents a
+ * swapchain for presenting images on the screen, via interaction with the
+ * system's window manager.
+ *
+ * The [`Api`] trait has various other associated types like [`Api::Buffer`] and
+ * [`Api::Texture`] that represent resources the rest of the interface can
+ * operate on, but these generally do not have their own traits.
+ *
+ * [Ii]: Instance::init
+ *
+ * ## Validation is the calling code's responsibility, not `wgpu-hal`'s
+ *
+ * As much as possible, `wgpu-hal` traits place the burden of validation,
+ * resource tracking, and state tracking on the caller, not on the trait
+ * implementations themselves. Anything which can reasonably be handled in
+ * backend-independent code should be. A `wgpu_hal` backend's sole obligation is
+ * to provide portable behavior, and report conditions that the calling code
+ * can't reasonably anticipate, like device loss or running out of memory.
+ *
+ * The `wgpu` crate collection is intended for use in security-sensitive
+ * applications, like web browsers, where the API is available to untrusted
+ * code. This means that `wgpu-core`'s validation is not simply a service to
+ * developers, to be provided opportunistically when the performance costs are
+ * acceptable and the necessary data is ready at hand. Rather, `wgpu-core`'s
+ * validation must be exhaustive, to ensure that even malicious content cannot
+ * provoke and exploit undefined behavior in the platform's graphics API.
+ *
+ * Because graphics APIs' requirements are complex, the only practical way for
+ * `wgpu` to provide exhaustive validation is to comprehensively track the
+ * lifetime and state of all the resources in the system. Implementing this
+ * separately for each backend is infeasible; effort would be better spent
+ * making the cross-platform validation in `wgpu-core` legible and trustworthy.
+ * Fortunately, the requirements are largely similar across the various
+ * platforms, so cross-platform validation is practical.
+ *
+ * Some backends have specific requirements that aren't practical to foist off
+ * on the `wgpu-hal` user. For example, properly managing macOS Objective-C or
+ * Microsoft COM reference counts is best handled by using appropriate pointer
+ * types within the backend.
+ *
+ * A desire for "defense in depth" may suggest performing additional validation
+ * in `wgpu-hal` when the opportunity arises, but this must be done with
+ * caution. Even experienced contributors infer the expectations their changes
+ * must meet by considering not just requirements made explicit in types, tests,
+ * assertions, and comments, but also those implicit in the surrounding code.
+ * When one sees validation or state-tracking code in `wgpu-hal`, it is tempting
+ * to conclude, "Oh, `wgpu-hal` checks for this, so `wgpu-core` needn't worry
+ * about it - that would be redundant!" The responsibility for exhaustive
+ * validation always rests with `wgpu-core`, regardless of what may or may not
+ * be checked in `wgpu-hal`.
+ *
+ * To this end, any "defense in depth" validation that does appear in `wgpu-hal`
+ * for requirements that `wgpu-core` should have enforced should report failure
+ * via the `unreachable!` macro, because problems detected at this stage always
+ * indicate a bug in `wgpu-core`.
+ *
+ * ## Debugging
+ *
+ * Most of the information on the wiki [Debugging wgpu Applications][wiki-debug]
+ * page still applies to this API, with the exception of API tracing/replay
+ * functionality, which is only available in `wgpu-core`.
+ *
+ * [wiki-debug]: https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications
*/
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
@@ -198,6 +389,15 @@ pub trait Api: Clone + fmt::Debug + Sized {
type Queue: Queue<A = Self>;
type CommandEncoder: CommandEncoder<A = Self>;
+
+ /// This API's command buffer type.
+ ///
+ /// The only thing you can do with `CommandBuffer`s is build them
+ /// with a [`CommandEncoder`] and then pass them to
+ /// [`Queue::submit`] for execution, or destroy them by passing
+ /// them to [`CommandEncoder::reset_all`].
+ ///
+ /// [`CommandEncoder`]: Api::CommandEncoder
type CommandBuffer: WasmNotSendSync + fmt::Debug;
type Buffer: fmt::Debug + WasmNotSendSync + 'static;
@@ -206,6 +406,24 @@ pub trait Api: Clone + fmt::Debug + Sized {
type TextureView: fmt::Debug + WasmNotSendSync;
type Sampler: fmt::Debug + WasmNotSendSync;
type QuerySet: fmt::Debug + WasmNotSendSync;
+
+ /// A value you can block on to wait for something to finish.
+ ///
+ /// A `Fence` holds a monotonically increasing [`FenceValue`]. You can call
+ /// [`Device::wait`] to block until a fence reaches or passes a value you
+ /// choose. [`Queue::submit`] can take a `Fence` and a [`FenceValue`] to
+ /// store in it when the submitted work is complete.
+ ///
+ /// Attempting to set a fence to a value less than its current value has no
+ /// effect.
+ ///
+ /// Waiting on a fence returns as soon as the fence reaches *or passes* the
+ /// requested value. This implies that, in order to reliably determine when
+ /// an operation has completed, operations must finish in order of
+ /// increasing fence values: if a higher-valued operation were to finish
+ /// before a lower-valued operation, then waiting for the fence to reach the
+ /// lower value could return before the lower-valued operation has actually
+ /// finished.
type Fence: fmt::Debug + WasmNotSendSync;
type BindGroupLayout: fmt::Debug + WasmNotSendSync;
@@ -405,7 +623,25 @@ pub trait Device: WasmNotSendSync {
&self,
fence: &<Self::A as Api>::Fence,
) -> Result<FenceValue, DeviceError>;
- /// Calling wait with a lower value than the current fence value will immediately return.
+
+ /// Wait for `fence` to reach `value`.
+ ///
+ /// Operations like [`Queue::submit`] can accept a [`Fence`] and a
+ /// [`FenceValue`] to store in it, so you can use this `wait` function
+ /// to wait for a given queue submission to finish execution.
+ ///
+ /// The `value` argument must be a value that some actual operation you have
+ /// already presented to the device is going to store in `fence`. You cannot
+ /// wait for values yet to be submitted. (This restriction accommodates
+ /// implementations like the `vulkan` backend's [`FencePool`] that must
+ /// allocate a distinct synchronization object for each fence value one is
+ /// able to wait for.)
+ ///
+ /// Calling `wait` with a lower [`FenceValue`] than `fence`'s current value
+ /// returns immediately.
+ ///
+ /// [`Fence`]: Api::Fence
+ /// [`FencePool`]: vulkan/enum.Fence.html#variant.FencePool
unsafe fn wait(
&self,
fence: &<Self::A as Api>::Fence,
@@ -437,14 +673,48 @@ pub trait Device: WasmNotSendSync {
pub trait Queue: WasmNotSendSync {
type A: Api;
- /// Submits the command buffers for execution on GPU.
+ /// Submit `command_buffers` for execution on GPU.
+ ///
+ /// If `signal_fence` is `Some(fence, value)`, update `fence` to `value`
+ /// when the operation is complete. See [`Fence`] for details.
+ ///
+ /// If two calls to `submit` on a single `Queue` occur in a particular order
+ /// (that is, they happen on the same thread, or on two threads that have
+ /// synchronized to establish an ordering), then the first submission's
+ /// commands all complete execution before any of the second submission's
+ /// commands begin. All results produced by one submission are visible to
+ /// the next.
+ ///
+ /// Within a submission, command buffers execute in the order in which they
+ /// appear in `command_buffers`. All results produced by one buffer are
+ /// visible to the next.
+ ///
+ /// If two calls to `submit` on a single `Queue` from different threads are
+ /// not synchronized to occur in a particular order, they must pass distinct
+ /// [`Fence`]s. As explained in the [`Fence`] documentation, waiting for
+ /// operations to complete is only trustworthy when operations finish in
+ /// order of increasing fence value, but submissions from different threads
+ /// cannot determine how to order the fence values if the submissions
+ /// themselves are unordered. If each thread uses a separate [`Fence`], this
+ /// problem does not arise.
///
/// Valid usage:
- /// - all of the command buffers were created from command pools
- /// that are associated with this queue.
- /// - all of the command buffers had `CommandBuffer::finish()` called.
- /// - all surface textures that the command buffers write to must be
- /// passed to the surface_textures argument.
+ ///
+ /// - All of the [`CommandBuffer`][cb]s were created from
+ /// [`CommandEncoder`][ce]s that are associated with this queue.
+ ///
+ /// - All of those [`CommandBuffer`][cb]s must remain alive until
+ /// the submitted commands have finished execution. (Since
+ /// command buffers must not outlive their encoders, this
+ /// implies that the encoders must remain alive as well.)
+ ///
+ /// - All of the [`SurfaceTexture`][st]s that the command buffers
+ /// write to appear in the `surface_textures` argument.
+ ///
+ /// [`Fence`]: Api::Fence
+ /// [cb]: Api::CommandBuffer
+ /// [ce]: Api::CommandEncoder
+ /// [st]: Api::SurfaceTexture
unsafe fn submit(
&self,
command_buffers: &[&<Self::A as Api>::CommandBuffer],
@@ -459,7 +729,12 @@ pub trait Queue: WasmNotSendSync {
unsafe fn get_timestamp_period(&self) -> f32;
}
-/// Encoder and allocation pool for `CommandBuffer`.
+/// Encoder and allocation pool for `CommandBuffer`s.
+///
+/// A `CommandEncoder` not only constructs `CommandBuffer`s but also
+/// acts as the allocation pool that owns the buffers' underlying
+/// storage. Thus, `CommandBuffer`s must not outlive the
+/// `CommandEncoder` that created them.
///
/// The life cycle of a `CommandBuffer` is as follows:
///
@@ -472,14 +747,17 @@ pub trait Queue: WasmNotSendSync {
///
/// - Call methods like `copy_buffer_to_buffer`, `begin_render_pass`,
/// etc. on a "recording" `CommandEncoder` to add commands to the
-/// list.
+/// list. (If an error occurs, you must call `discard_encoding`; see
+/// below.)
///
/// - Call `end_encoding` on a recording `CommandEncoder` to close the
/// encoder and construct a fresh `CommandBuffer` consisting of the
/// list of commands recorded up to that point.
///
/// - Call `discard_encoding` on a recording `CommandEncoder` to drop
-/// the commands recorded thus far and close the encoder.
+/// the commands recorded thus far and close the encoder. This is
+/// the only safe thing to do on a `CommandEncoder` if an error has
+/// occurred while recording commands.
///
/// - Call `reset_all` on a closed `CommandEncoder`, passing all the
/// live `CommandBuffers` built from it. All the `CommandBuffer`s
@@ -497,6 +775,10 @@ pub trait Queue: WasmNotSendSync {
/// built it.
///
/// - A `CommandEncoder` must not outlive its `Device`.
+///
+/// It is the user's responsibility to meet this requirements. This
+/// allows `CommandEncoder` implementations to keep their state
+/// tracking to a minimum.
pub trait CommandEncoder: WasmNotSendSync + fmt::Debug {
type A: Api;
@@ -509,13 +791,20 @@ pub trait CommandEncoder: WasmNotSendSync + fmt::Debug {
/// This `CommandEncoder` must be in the "closed" state.
unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
- /// Discard the command list under construction, if any.
+ /// Discard the command list under construction.
+ ///
+ /// If an error has occurred while recording commands, this
+ /// is the only safe thing to do with the encoder.
///
/// This puts this `CommandEncoder` in the "closed" state.
///
/// # Safety
///
/// This `CommandEncoder` must be in the "recording" state.
+ ///
+ /// Callers must not assume that implementations of this
+ /// function are idempotent, and thus should not call it
+ /// multiple times in a row.
unsafe fn discard_encoding(&mut self);
/// Return a fresh [`CommandBuffer`] holding the recorded commands.
@@ -1318,6 +1607,13 @@ pub struct ProgrammableStage<'a, A: Api> {
/// The name of the entry point in the compiled shader. There must be a function with this name
/// in the shader.
pub entry_point: &'a str,
+ /// Pipeline constants
+ pub constants: &'a naga::back::PipelineConstants,
+ /// Whether workgroup scoped memory will be initialized with zero values for this stage.
+ ///
+ /// This is required by the WebGPU spec, but may have overhead which can be avoided
+ /// for cross-platform applications
+ pub zero_initialize_workgroup_memory: bool,
}
// Rust gets confused about the impl requirements for `A`
@@ -1326,6 +1622,8 @@ impl<A: Api> Clone for ProgrammableStage<'_, A> {
Self {
module: self.module,
entry_point: self.entry_point,
+ constants: self.constants,
+ zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
}
}
}
diff --git a/third_party/rust/wgpu-hal/src/metal/adapter.rs b/third_party/rust/wgpu-hal/src/metal/adapter.rs
index 6211896838..cddba472bd 100644
--- a/third_party/rust/wgpu-hal/src/metal/adapter.rs
+++ b/third_party/rust/wgpu-hal/src/metal/adapter.rs
@@ -562,7 +562,11 @@ impl super::PrivateCapabilities {
Self {
family_check,
- msl_version: if os_is_xr || version.at_least((12, 0), (15, 0), os_is_mac) {
+ msl_version: if os_is_xr || version.at_least((14, 0), (17, 0), os_is_mac) {
+ MTLLanguageVersion::V3_1
+ } else if version.at_least((13, 0), (16, 0), os_is_mac) {
+ MTLLanguageVersion::V3_0
+ } else if version.at_least((12, 0), (15, 0), os_is_mac) {
MTLLanguageVersion::V2_4
} else if version.at_least((11, 0), (14, 0), os_is_mac) {
MTLLanguageVersion::V2_3
@@ -809,6 +813,14 @@ impl super::PrivateCapabilities {
None
},
timestamp_query_support,
+ supports_simd_scoped_operations: family_check
+ && (device.supports_family(MTLGPUFamily::Metal3)
+ || device.supports_family(MTLGPUFamily::Mac2)
+ || device.supports_family(MTLGPUFamily::Apple7)),
+ // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf#page=5
+ int64: family_check
+ && (device.supports_family(MTLGPUFamily::Apple3)
+ || device.supports_family(MTLGPUFamily::Metal3)),
}
}
@@ -882,7 +894,7 @@ impl super::PrivateCapabilities {
}
features.set(
F::SHADER_INT64,
- self.msl_version >= MTLLanguageVersion::V2_3,
+ self.int64 && self.msl_version >= MTLLanguageVersion::V2_3,
);
features.set(
@@ -894,6 +906,10 @@ impl super::PrivateCapabilities {
features.set(F::RG11B10UFLOAT_RENDERABLE, self.format_rg11b10_all);
features.set(F::SHADER_UNUSED_VERTEX_OUTPUT, true);
+ if self.supports_simd_scoped_operations {
+ features.insert(F::SUBGROUP | F::SUBGROUP_BARRIER);
+ }
+
features
}
@@ -948,6 +964,8 @@ impl super::PrivateCapabilities {
max_vertex_buffers: self.max_vertex_buffers,
max_vertex_attributes: 31,
max_vertex_buffer_array_stride: base.max_vertex_buffer_array_stride,
+ min_subgroup_size: 4,
+ max_subgroup_size: 64,
max_push_constant_size: 0x1000,
min_uniform_buffer_offset_alignment: self.buffer_alignment as u32,
min_storage_buffer_offset_alignment: self.buffer_alignment as u32,
diff --git a/third_party/rust/wgpu-hal/src/metal/conv.rs b/third_party/rust/wgpu-hal/src/metal/conv.rs
index 8f6439b50b..6ebabee1a6 100644
--- a/third_party/rust/wgpu-hal/src/metal/conv.rs
+++ b/third_party/rust/wgpu-hal/src/metal/conv.rs
@@ -222,6 +222,7 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> metal::MTLVertexFormat {
Vf::Uint32x4 => UInt4,
Vf::Sint32x4 => Int4,
Vf::Float32x4 => Float4,
+ Vf::Unorm10_10_10_2 => UInt1010102Normalized,
Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(),
}
}
diff --git a/third_party/rust/wgpu-hal/src/metal/device.rs b/third_party/rust/wgpu-hal/src/metal/device.rs
index 179429f5d7..2c8f5a2bfb 100644
--- a/third_party/rust/wgpu-hal/src/metal/device.rs
+++ b/third_party/rust/wgpu-hal/src/metal/device.rs
@@ -69,7 +69,13 @@ impl super::Device {
) -> Result<CompiledShader, crate::PipelineError> {
let stage_bit = map_naga_stage(naga_stage);
- let module = &stage.module.naga.module;
+ let (module, module_info) = naga::back::pipeline_constants::process_overrides(
+ &stage.module.naga.module,
+ &stage.module.naga.info,
+ stage.constants,
+ )
+ .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("MSL: {:?}", e)))?;
+
let ep_resources = &layout.per_stage_map[naga_stage];
let bounds_check_policy = if stage.module.runtime_checks {
@@ -88,6 +94,8 @@ impl super::Device {
metal::MTLLanguageVersion::V2_2 => (2, 2),
metal::MTLLanguageVersion::V2_3 => (2, 3),
metal::MTLLanguageVersion::V2_4 => (2, 4),
+ metal::MTLLanguageVersion::V3_0 => (3, 0),
+ metal::MTLLanguageVersion::V3_1 => (3, 1),
},
inline_samplers: Default::default(),
spirv_cross_compatibility: false,
@@ -104,7 +112,7 @@ impl super::Device {
// TODO: support bounds checks on binding arrays
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
},
- zero_initialize_workgroup_memory: true,
+ zero_initialize_workgroup_memory: stage.zero_initialize_workgroup_memory,
};
let pipeline_options = naga::back::msl::PipelineOptions {
@@ -114,13 +122,9 @@ impl super::Device {
},
};
- let (source, info) = naga::back::msl::write_string(
- module,
- &stage.module.naga.info,
- &options,
- &pipeline_options,
- )
- .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("MSL: {:?}", e)))?;
+ let (source, info) =
+ naga::back::msl::write_string(&module, &module_info, &options, &pipeline_options)
+ .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("MSL: {:?}", e)))?;
log::debug!(
"Naga generated shader for entry point '{}' and stage {:?}\n{}",
@@ -168,7 +172,7 @@ impl super::Device {
})?;
// collect sizes indices, immutable buffers, and work group memory sizes
- let ep_info = &stage.module.naga.info.get_entry_point(ep_index);
+ let ep_info = &module_info.get_entry_point(ep_index);
let mut wg_memory_sizes = Vec::new();
let mut sized_bindings = Vec::new();
let mut immutable_buffer_mask = 0;
diff --git a/third_party/rust/wgpu-hal/src/metal/mod.rs b/third_party/rust/wgpu-hal/src/metal/mod.rs
index 6aeafb0f86..7d547cfe3c 100644
--- a/third_party/rust/wgpu-hal/src/metal/mod.rs
+++ b/third_party/rust/wgpu-hal/src/metal/mod.rs
@@ -269,6 +269,8 @@ struct PrivateCapabilities {
supports_shader_primitive_index: bool,
has_unified_memory: Option<bool>,
timestamp_query_support: TimestampQuerySupport,
+ supports_simd_scoped_operations: bool,
+ int64: bool,
}
#[derive(Clone, Debug)]
@@ -649,7 +651,7 @@ struct BufferResource {
/// Buffers with the [`wgt::BufferBindingType::Storage`] binding type can
/// hold WGSL runtime-sized arrays. When one does, we must pass its size to
/// shader entry points to implement bounds checks and WGSL's `arrayLength`
- /// function. See [`device::CompiledShader::sized_bindings`] for details.
+ /// function. See `device::CompiledShader::sized_bindings` for details.
///
/// [`Storage`]: wgt::BufferBindingType::Storage
binding_size: Option<wgt::BufferSize>,
@@ -680,12 +682,12 @@ struct PipelineStageInfo {
/// The buffer argument table index at which we pass runtime-sized arrays' buffer sizes.
///
- /// See [`device::CompiledShader::sized_bindings`] for more details.
+ /// See `device::CompiledShader::sized_bindings` for more details.
sizes_slot: Option<naga::back::msl::Slot>,
/// Bindings of all WGSL `storage` globals that contain runtime-sized arrays.
///
- /// See [`device::CompiledShader::sized_bindings`] for more details.
+ /// See `device::CompiledShader::sized_bindings` for more details.
sized_bindings: Vec<naga::ResourceBinding>,
}
@@ -801,7 +803,7 @@ struct CommandState {
///
/// Specifically:
///
- /// - The keys are ['ResourceBinding`] values (that is, the WGSL `@group`
+ /// - The keys are [`ResourceBinding`] values (that is, the WGSL `@group`
/// and `@binding` attributes) for `var<storage>` global variables in the
/// current module that contain runtime-sized arrays.
///
@@ -813,7 +815,7 @@ struct CommandState {
/// of the buffers listed in [`stage_infos.S.sized_bindings`], which we must
/// pass to the entry point.
///
- /// See [`device::CompiledShader::sized_bindings`] for more details.
+ /// See `device::CompiledShader::sized_bindings` for more details.
///
/// [`ResourceBinding`]: naga::ResourceBinding
storage_buffer_length_map: rustc_hash::FxHashMap<naga::ResourceBinding, wgt::BufferSize>,
diff --git a/third_party/rust/wgpu-hal/src/vulkan/adapter.rs b/third_party/rust/wgpu-hal/src/vulkan/adapter.rs
index 2665463792..21219361f4 100644
--- a/third_party/rust/wgpu-hal/src/vulkan/adapter.rs
+++ b/third_party/rust/wgpu-hal/src/vulkan/adapter.rs
@@ -35,6 +35,8 @@ fn indexing_features() -> wgt::Features {
/// [`PhysicalDeviceFeatures::from_extensions_and_requested_features`]
/// constructs an value of this type indicating which Vulkan features to
/// enable, based on the `wgpu_types::Features` requested.
+///
+/// [`Instance::expose_adapter`]: super::Instance::expose_adapter
#[derive(Debug, Default)]
pub struct PhysicalDeviceFeatures {
/// Basic Vulkan 1.0 features.
@@ -86,6 +88,9 @@ pub struct PhysicalDeviceFeatures {
///
/// However, we do populate this when creating a device if
/// [`Features::RAY_TRACING_ACCELERATION_STRUCTURE`] is requested.
+ ///
+ /// [`Instance::expose_adapter`]: super::Instance::expose_adapter
+ /// [`Features::RAY_TRACING_ACCELERATION_STRUCTURE`]: wgt::Features::RAY_TRACING_ACCELERATION_STRUCTURE
buffer_device_address: Option<vk::PhysicalDeviceBufferDeviceAddressFeaturesKHR>,
/// Features provided by `VK_KHR_ray_query`,
@@ -95,12 +100,17 @@ pub struct PhysicalDeviceFeatures {
/// this from `vkGetPhysicalDeviceFeatures2`.
///
/// However, we do populate this when creating a device if ray tracing is requested.
+ ///
+ /// [`Instance::expose_adapter`]: super::Instance::expose_adapter
ray_query: Option<vk::PhysicalDeviceRayQueryFeaturesKHR>,
/// Features provided by `VK_KHR_zero_initialize_workgroup_memory`, promoted
/// to Vulkan 1.3.
zero_initialize_workgroup_memory:
Option<vk::PhysicalDeviceZeroInitializeWorkgroupMemoryFeatures>,
+
+ /// Features provided by `VK_EXT_subgroup_size_control`, promoted to Vulkan 1.3.
+ subgroup_size_control: Option<vk::PhysicalDeviceSubgroupSizeControlFeatures>,
}
// This is safe because the structs have `p_next: *mut c_void`, which we null out/never read.
@@ -148,6 +158,9 @@ impl PhysicalDeviceFeatures {
if let Some(ref mut feature) = self.ray_query {
info = info.push_next(feature);
}
+ if let Some(ref mut feature) = self.subgroup_size_control {
+ info = info.push_next(feature);
+ }
info
}
@@ -175,6 +188,7 @@ impl PhysicalDeviceFeatures {
/// [`Features`]: wgt::Features
/// [`DownlevelFlags`]: wgt::DownlevelFlags
/// [`PrivateCapabilities`]: super::PrivateCapabilities
+ /// [`add_to_device_create_builder`]: PhysicalDeviceFeatures::add_to_device_create_builder
/// [`DeviceCreateInfoBuilder`]: vk::DeviceCreateInfoBuilder
/// [`Adapter::required_device_extensions`]: super::Adapter::required_device_extensions
fn from_extensions_and_requested_features(
@@ -434,6 +448,17 @@ impl PhysicalDeviceFeatures {
} else {
None
},
+ subgroup_size_control: if device_api_version >= vk::API_VERSION_1_3
+ || enabled_extensions.contains(&vk::ExtSubgroupSizeControlFn::name())
+ {
+ Some(
+ vk::PhysicalDeviceSubgroupSizeControlFeatures::builder()
+ .subgroup_size_control(true)
+ .build(),
+ )
+ } else {
+ None
+ },
}
}
@@ -442,6 +467,9 @@ impl PhysicalDeviceFeatures {
/// Given `self`, together with the instance and physical device it was
/// built from, and a `caps` also built from those, determine which wgpu
/// features and downlevel flags the device can support.
+ ///
+ /// [`Features`]: wgt::Features
+ /// [`DownlevelFlags`]: wgt::DownlevelFlags
fn to_wgpu(
&self,
instance: &ash::Instance,
@@ -638,6 +666,34 @@ impl PhysicalDeviceFeatures {
);
}
+ if let Some(ref subgroup) = caps.subgroup {
+ if (caps.device_api_version >= vk::API_VERSION_1_3
+ || caps.supports_extension(vk::ExtSubgroupSizeControlFn::name()))
+ && subgroup.supported_operations.contains(
+ vk::SubgroupFeatureFlags::BASIC
+ | vk::SubgroupFeatureFlags::VOTE
+ | vk::SubgroupFeatureFlags::ARITHMETIC
+ | vk::SubgroupFeatureFlags::BALLOT
+ | vk::SubgroupFeatureFlags::SHUFFLE
+ | vk::SubgroupFeatureFlags::SHUFFLE_RELATIVE,
+ )
+ {
+ features.set(
+ F::SUBGROUP,
+ subgroup
+ .supported_stages
+ .contains(vk::ShaderStageFlags::COMPUTE | vk::ShaderStageFlags::FRAGMENT),
+ );
+ features.set(
+ F::SUBGROUP_VERTEX,
+ subgroup
+ .supported_stages
+ .contains(vk::ShaderStageFlags::VERTEX),
+ );
+ features.insert(F::SUBGROUP_BARRIER);
+ }
+ }
+
let supports_depth_format = |format| {
supports_format(
instance,
@@ -773,6 +829,13 @@ pub struct PhysicalDeviceProperties {
/// `VK_KHR_driver_properties` extension, promoted to Vulkan 1.2.
driver: Option<vk::PhysicalDeviceDriverPropertiesKHR>,
+ /// Additional `vk::PhysicalDevice` properties from Vulkan 1.1.
+ subgroup: Option<vk::PhysicalDeviceSubgroupProperties>,
+
+ /// Additional `vk::PhysicalDevice` properties from the
+ /// `VK_EXT_subgroup_size_control` extension, promoted to Vulkan 1.3.
+ subgroup_size_control: Option<vk::PhysicalDeviceSubgroupSizeControlProperties>,
+
/// The device API version.
///
/// Which is the version of Vulkan supported for device-level functionality.
@@ -888,6 +951,11 @@ impl PhysicalDeviceProperties {
if self.supports_extension(vk::ExtImageRobustnessFn::name()) {
extensions.push(vk::ExtImageRobustnessFn::name());
}
+
+ // Require `VK_EXT_subgroup_size_control` if the associated feature was requested
+ if requested_features.contains(wgt::Features::SUBGROUP) {
+ extensions.push(vk::ExtSubgroupSizeControlFn::name());
+ }
}
// Optional `VK_KHR_swapchain_mutable_format`
@@ -987,6 +1055,14 @@ impl PhysicalDeviceProperties {
.min(crate::MAX_VERTEX_BUFFERS as u32),
max_vertex_attributes: limits.max_vertex_input_attributes,
max_vertex_buffer_array_stride: limits.max_vertex_input_binding_stride,
+ min_subgroup_size: self
+ .subgroup_size_control
+ .map(|subgroup_size| subgroup_size.min_subgroup_size)
+ .unwrap_or(0),
+ max_subgroup_size: self
+ .subgroup_size_control
+ .map(|subgroup_size| subgroup_size.max_subgroup_size)
+ .unwrap_or(0),
max_push_constant_size: limits.max_push_constants_size,
min_uniform_buffer_offset_alignment: limits.min_uniform_buffer_offset_alignment as u32,
min_storage_buffer_offset_alignment: limits.min_storage_buffer_offset_alignment as u32,
@@ -1042,6 +1118,9 @@ impl super::InstanceShared {
let supports_driver_properties = capabilities.device_api_version
>= vk::API_VERSION_1_2
|| capabilities.supports_extension(vk::KhrDriverPropertiesFn::name());
+ let supports_subgroup_size_control = capabilities.device_api_version
+ >= vk::API_VERSION_1_3
+ || capabilities.supports_extension(vk::ExtSubgroupSizeControlFn::name());
let supports_acceleration_structure =
capabilities.supports_extension(vk::KhrAccelerationStructureFn::name());
@@ -1075,6 +1154,20 @@ impl super::InstanceShared {
builder = builder.push_next(next);
}
+ if capabilities.device_api_version >= vk::API_VERSION_1_1 {
+ let next = capabilities
+ .subgroup
+ .insert(vk::PhysicalDeviceSubgroupProperties::default());
+ builder = builder.push_next(next);
+ }
+
+ if supports_subgroup_size_control {
+ let next = capabilities
+ .subgroup_size_control
+ .insert(vk::PhysicalDeviceSubgroupSizeControlProperties::default());
+ builder = builder.push_next(next);
+ }
+
let mut properties2 = builder.build();
unsafe {
get_device_properties.get_physical_device_properties2(phd, &mut properties2);
@@ -1190,6 +1283,16 @@ impl super::InstanceShared {
builder = builder.push_next(next);
}
+ // `VK_EXT_subgroup_size_control` is promoted to 1.3
+ if capabilities.device_api_version >= vk::API_VERSION_1_3
+ || capabilities.supports_extension(vk::ExtSubgroupSizeControlFn::name())
+ {
+ let next = features
+ .subgroup_size_control
+ .insert(vk::PhysicalDeviceSubgroupSizeControlFeatures::default());
+ builder = builder.push_next(next);
+ }
+
let mut features2 = builder.build();
unsafe {
get_device_properties.get_physical_device_features2(phd, &mut features2);
@@ -1382,6 +1485,9 @@ impl super::Instance {
}),
image_format_list: phd_capabilities.device_api_version >= vk::API_VERSION_1_2
|| phd_capabilities.supports_extension(vk::KhrImageFormatListFn::name()),
+ subgroup_size_control: phd_features
+ .subgroup_size_control
+ .map_or(false, |ext| ext.subgroup_size_control == vk::TRUE),
};
let capabilities = crate::Capabilities {
limits: phd_capabilities.to_wgpu_limits(),
@@ -1581,6 +1687,15 @@ impl super::Adapter {
capabilities.push(spv::Capability::Geometry);
}
+ if features.intersects(wgt::Features::SUBGROUP | wgt::Features::SUBGROUP_VERTEX) {
+ capabilities.push(spv::Capability::GroupNonUniform);
+ capabilities.push(spv::Capability::GroupNonUniformVote);
+ capabilities.push(spv::Capability::GroupNonUniformArithmetic);
+ capabilities.push(spv::Capability::GroupNonUniformBallot);
+ capabilities.push(spv::Capability::GroupNonUniformShuffle);
+ capabilities.push(spv::Capability::GroupNonUniformShuffleRelative);
+ }
+
if features.intersects(
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
@@ -1616,7 +1731,13 @@ impl super::Adapter {
true, // could check `super::Workarounds::SEPARATE_ENTRY_POINTS`
);
spv::Options {
- lang_version: (1, 0),
+ lang_version: if features
+ .intersects(wgt::Features::SUBGROUP | wgt::Features::SUBGROUP_VERTEX)
+ {
+ (1, 3)
+ } else {
+ (1, 0)
+ },
flags,
capabilities: Some(capabilities.iter().cloned().collect()),
bounds_check_policies: naga::proc::BoundsCheckPolicies {
diff --git a/third_party/rust/wgpu-hal/src/vulkan/command.rs b/third_party/rust/wgpu-hal/src/vulkan/command.rs
index 43a2471954..ceb44dfbe6 100644
--- a/third_party/rust/wgpu-hal/src/vulkan/command.rs
+++ b/third_party/rust/wgpu-hal/src/vulkan/command.rs
@@ -104,6 +104,11 @@ impl crate::CommandEncoder for super::CommandEncoder {
}
unsafe fn discard_encoding(&mut self) {
+ // Safe use requires this is not called in the "closed" state, so the buffer
+ // shouldn't be null. Assert this to make sure we're not pushing null
+ // buffers to the discard pile.
+ assert_ne!(self.active, vk::CommandBuffer::null());
+
self.discarded.push(self.active);
self.active = vk::CommandBuffer::null();
}
diff --git a/third_party/rust/wgpu-hal/src/vulkan/conv.rs b/third_party/rust/wgpu-hal/src/vulkan/conv.rs
index 8202c93aa3..fe284f32a9 100644
--- a/third_party/rust/wgpu-hal/src/vulkan/conv.rs
+++ b/third_party/rust/wgpu-hal/src/vulkan/conv.rs
@@ -399,6 +399,7 @@ pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format {
Vf::Float64x2 => vk::Format::R64G64_SFLOAT,
Vf::Float64x3 => vk::Format::R64G64B64_SFLOAT,
Vf::Float64x4 => vk::Format::R64G64B64A64_SFLOAT,
+ Vf::Unorm10_10_10_2 => vk::Format::A2B10G10R10_UNORM_PACK32,
}
}
diff --git a/third_party/rust/wgpu-hal/src/vulkan/device.rs b/third_party/rust/wgpu-hal/src/vulkan/device.rs
index 70028cc700..ec392533a0 100644
--- a/third_party/rust/wgpu-hal/src/vulkan/device.rs
+++ b/third_party/rust/wgpu-hal/src/vulkan/device.rs
@@ -2,6 +2,7 @@ use super::conv;
use arrayvec::ArrayVec;
use ash::{extensions::khr, vk};
+use naga::back::spv::ZeroInitializeWorkgroupMemoryMode;
use parking_lot::Mutex;
use std::{
@@ -737,7 +738,8 @@ impl super::Device {
};
let needs_temp_options = !runtime_checks
|| !binding_map.is_empty()
- || naga_shader.debug_source.is_some();
+ || naga_shader.debug_source.is_some()
+ || !stage.zero_initialize_workgroup_memory;
let mut temp_options;
let options = if needs_temp_options {
temp_options = self.naga_options.clone();
@@ -760,27 +762,40 @@ impl super::Device {
file_name: debug.file_name.as_ref().as_ref(),
})
}
+ if !stage.zero_initialize_workgroup_memory {
+ temp_options.zero_initialize_workgroup_memory =
+ ZeroInitializeWorkgroupMemoryMode::None;
+ }
&temp_options
} else {
&self.naga_options
};
+
+ let (module, info) = naga::back::pipeline_constants::process_overrides(
+ &naga_shader.module,
+ &naga_shader.info,
+ stage.constants,
+ )
+ .map_err(|e| crate::PipelineError::Linkage(stage_flags, format!("{e}")))?;
+
let spv = {
profiling::scope!("naga::spv::write_vec");
- naga::back::spv::write_vec(
- &naga_shader.module,
- &naga_shader.info,
- options,
- Some(&pipeline_options),
- )
+ naga::back::spv::write_vec(&module, &info, options, Some(&pipeline_options))
}
.map_err(|e| crate::PipelineError::Linkage(stage_flags, format!("{e}")))?;
self.create_shader_module_impl(&spv)?
}
};
+ let mut flags = vk::PipelineShaderStageCreateFlags::empty();
+ if self.shared.private_caps.subgroup_size_control {
+ flags |= vk::PipelineShaderStageCreateFlags::ALLOW_VARYING_SUBGROUP_SIZE
+ }
+
let entry_point = CString::new(stage.entry_point).unwrap();
let create_info = vk::PipelineShaderStageCreateInfo::builder()
+ .flags(flags)
.stage(conv::map_shader_stage(stage_flags))
.module(vk_module)
.name(&entry_point)
@@ -1587,6 +1602,7 @@ impl crate::Device for super::Device {
.shared
.workarounds
.contains(super::Workarounds::SEPARATE_ENTRY_POINTS)
+ || !naga_shader.module.overrides.is_empty()
{
return Ok(super::ShaderModule::Intermediate {
naga_shader,
diff --git a/third_party/rust/wgpu-hal/src/vulkan/mod.rs b/third_party/rust/wgpu-hal/src/vulkan/mod.rs
index 0cd385045c..d1ea82772e 100644
--- a/third_party/rust/wgpu-hal/src/vulkan/mod.rs
+++ b/third_party/rust/wgpu-hal/src/vulkan/mod.rs
@@ -238,6 +238,7 @@ struct PrivateCapabilities {
robust_image_access2: bool,
zero_initialize_workgroup_memory: bool,
image_format_list: bool,
+ subgroup_size_control: bool,
}
bitflags::bitflags!(
@@ -413,6 +414,15 @@ pub struct TextureView {
attachment: FramebufferAttachment,
}
+impl TextureView {
+ /// # Safety
+ ///
+ /// - The image view handle must not be manually destroyed
+ pub unsafe fn raw_handle(&self) -> vk::ImageView {
+ self.raw
+ }
+}
+
#[derive(Debug)]
pub struct Sampler {
raw: vk::Sampler,
@@ -438,6 +448,7 @@ pub struct BindGroup {
set: gpu_descriptor::DescriptorSet<vk::DescriptorSet>,
}
+/// Miscellaneous allocation recycling pool for `CommandAllocator`.
#[derive(Default)]
struct Temp {
marker: Vec<u8>,
@@ -467,11 +478,31 @@ impl Temp {
pub struct CommandEncoder {
raw: vk::CommandPool,
device: Arc<DeviceShared>,
+
+ /// The current command buffer, if `self` is in the ["recording"]
+ /// state.
+ ///
+ /// ["recording"]: crate::CommandEncoder
+ ///
+ /// If non-`null`, the buffer is in the Vulkan "recording" state.
active: vk::CommandBuffer,
+
+ /// What kind of pass we are currently within: compute or render.
bind_point: vk::PipelineBindPoint,
+
+ /// Allocation recycling pool for this encoder.
temp: Temp,
+
+ /// A pool of available command buffers.
+ ///
+ /// These are all in the Vulkan "initial" state.
free: Vec<vk::CommandBuffer>,
+
+ /// A pool of discarded command buffers.
+ ///
+ /// These could be in any Vulkan state except "pending".
discarded: Vec<vk::CommandBuffer>,
+
/// If this is true, the active renderpass enabled a debug span,
/// and needs to be disabled on renderpass close.
rpass_debug_marker_active: bool,
@@ -481,6 +512,15 @@ pub struct CommandEncoder {
end_of_pass_timer_query: Option<(vk::QueryPool, u32)>,
}
+impl CommandEncoder {
+ /// # Safety
+ ///
+ /// - The command buffer handle must not be manually destroyed
+ pub unsafe fn raw_handle(&self) -> vk::CommandBuffer {
+ self.active
+ }
+}
+
impl fmt::Debug for CommandEncoder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CommandEncoder")
@@ -519,9 +559,47 @@ pub struct QuerySet {
raw: vk::QueryPool,
}
+/// The [`Api::Fence`] type for [`vulkan::Api`].
+///
+/// This is an `enum` because there are two possible implementations of
+/// `wgpu-hal` fences on Vulkan: Vulkan fences, which work on any version of
+/// Vulkan, and Vulkan timeline semaphores, which are easier and cheaper but
+/// require non-1.0 features.
+///
+/// [`Device::create_fence`] returns a [`TimelineSemaphore`] if
+/// [`VK_KHR_timeline_semaphore`] is available and enabled, and a [`FencePool`]
+/// otherwise.
+///
+/// [`Api::Fence`]: crate::Api::Fence
+/// [`vulkan::Api`]: Api
+/// [`Device::create_fence`]: crate::Device::create_fence
+/// [`TimelineSemaphore`]: Fence::TimelineSemaphore
+/// [`VK_KHR_timeline_semaphore`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VK_KHR_timeline_semaphore
+/// [`FencePool`]: Fence::FencePool
#[derive(Debug)]
pub enum Fence {
+ /// A Vulkan [timeline semaphore].
+ ///
+ /// These are simpler to use than Vulkan fences, since timeline semaphores
+ /// work exactly the way [`wpgu_hal::Api::Fence`] is specified to work.
+ ///
+ /// [timeline semaphore]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#synchronization-semaphores
+ /// [`wpgu_hal::Api::Fence`]: crate::Api::Fence
TimelineSemaphore(vk::Semaphore),
+
+ /// A collection of Vulkan [fence]s, each associated with a [`FenceValue`].
+ ///
+ /// The effective [`FenceValue`] of this variant is the greater of
+ /// `last_completed` and the maximum value associated with a signalled fence
+ /// in `active`.
+ ///
+ /// Fences are available in all versions of Vulkan, but since they only have
+ /// two states, "signaled" and "unsignaled", we need to use a separate fence
+ /// for each queue submission we might want to wait for, and remember which
+ /// [`FenceValue`] each one represents.
+ ///
+ /// [fence]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#synchronization-fences
+ /// [`FenceValue`]: crate::FenceValue
FencePool {
last_completed: crate::FenceValue,
/// The pending fence values have to be ascending.
@@ -531,21 +609,32 @@ pub enum Fence {
}
impl Fence {
+ /// Return the highest [`FenceValue`] among the signalled fences in `active`.
+ ///
+ /// As an optimization, assume that we already know that the fence has
+ /// reached `last_completed`, and don't bother checking fences whose values
+ /// are less than that: those fences remain in the `active` array only
+ /// because we haven't called `maintain` yet to clean them up.
+ ///
+ /// [`FenceValue`]: crate::FenceValue
fn check_active(
device: &ash::Device,
- mut max_value: crate::FenceValue,
+ mut last_completed: crate::FenceValue,
active: &[(crate::FenceValue, vk::Fence)],
) -> Result<crate::FenceValue, crate::DeviceError> {
for &(value, raw) in active.iter() {
unsafe {
- if value > max_value && device.get_fence_status(raw)? {
- max_value = value;
+ if value > last_completed && device.get_fence_status(raw)? {
+ last_completed = value;
}
}
}
- Ok(max_value)
+ Ok(last_completed)
}
+ /// Return the highest signalled [`FenceValue`] for `self`.
+ ///
+ /// [`FenceValue`]: crate::FenceValue
fn get_latest(
&self,
device: &ash::Device,
@@ -566,6 +655,18 @@ impl Fence {
}
}
+ /// Trim the internal state of this [`Fence`].
+ ///
+ /// This function has no externally visible effect, but you should call it
+ /// periodically to keep this fence's resource consumption under control.
+ ///
+ /// For fences using the [`FencePool`] implementation, this function
+ /// recycles fences that have been signaled. If you don't call this,
+ /// [`Queue::submit`] will just keep allocating a new Vulkan fence every
+ /// time it's called.
+ ///
+ /// [`FencePool`]: Fence::FencePool
+ /// [`Queue::submit`]: crate::Queue::submit
fn maintain(&mut self, device: &ash::Device) -> Result<(), crate::DeviceError> {
match *self {
Self::TimelineSemaphore(_) => {}
diff --git a/third_party/rust/wgpu-types/.cargo-checksum.json b/third_party/rust/wgpu-types/.cargo-checksum.json
index 928cdbab21..0f14282158 100644
--- a/third_party/rust/wgpu-types/.cargo-checksum.json
+++ b/third_party/rust/wgpu-types/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"0bcb9c2d557d01677740fea4690c79544898fe749880a72512dca33db171e590","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"b9fda00d1b61364cdd7e544aee731ce075ea8403349ed286711d39aa8d414c28","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"d8f88446d6c1740116442320eca91e06ce9a2f4713179195c1be44e8ab1fc42d","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"0e844b150863abdecee2a2cb44245330f22ab48d8ab14f15f06c13f96213bdf3","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/wgpu-types/Cargo.toml b/third_party/rust/wgpu-types/Cargo.toml
index c6f8b3002d..44bfa08b33 100644
--- a/third_party/rust/wgpu-types/Cargo.toml
+++ b/third_party/rust/wgpu-types/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.74"
name = "wgpu-types"
-version = "0.19.0"
+version = "0.20.0"
authors = ["gfx-rs developers"]
description = "WebGPU types"
homepage = "https://wgpu.rs/"
@@ -45,7 +45,7 @@ features = ["serde_derive"]
optional = true
[dev-dependencies]
-serde_json = "1.0.113"
+serde_json = "1.0.116"
[dev-dependencies.serde]
version = "1"
diff --git a/third_party/rust/wgpu-types/src/lib.rs b/third_party/rust/wgpu-types/src/lib.rs
index b36801e941..7049cd3a8d 100644
--- a/third_party/rust/wgpu-types/src/lib.rs
+++ b/third_party/rust/wgpu-types/src/lib.rs
@@ -890,6 +890,30 @@ bitflags::bitflags! {
///
/// This is a native only feature.
const SHADER_INT64 = 1 << 55;
+ /// Allows compute and fragment shaders to use the subgroup operation built-ins
+ ///
+ /// Supported Platforms:
+ /// - Vulkan
+ /// - DX12
+ /// - Metal
+ ///
+ /// This is a native only feature.
+ const SUBGROUP = 1 << 56;
+ /// Allows vertex shaders to use the subgroup operation built-ins
+ ///
+ /// Supported Platforms:
+ /// - Vulkan
+ ///
+ /// This is a native only feature.
+ const SUBGROUP_VERTEX = 1 << 57;
+ /// Allows shaders to use the subgroup barrier
+ ///
+ /// Supported Platforms:
+ /// - Vulkan
+ /// - Metal
+ ///
+ /// This is a native only feature.
+ const SUBGROUP_BARRIER = 1 << 58;
}
}
@@ -1119,7 +1143,7 @@ pub struct Limits {
/// pipeline output data, across all color attachments.
pub max_color_attachment_bytes_per_sample: u32,
/// Maximum number of bytes used for workgroup memory in a compute entry point. Defaults to
- /// 16352. Higher is "better".
+ /// 16384. Higher is "better".
pub max_compute_workgroup_storage_size: u32,
/// Maximum value of the product of the `workgroup_size` dimensions for a compute entry-point.
/// Defaults to 256. Higher is "better".
@@ -1136,6 +1160,11 @@ pub struct Limits {
/// The maximum value for each dimension of a `ComputePass::dispatch(x, y, z)` operation.
/// Defaults to 65535. Higher is "better".
pub max_compute_workgroups_per_dimension: u32,
+
+ /// Minimal number of invocations in a subgroup. Higher is "better".
+ pub min_subgroup_size: u32,
+ /// Maximal number of invocations in a subgroup. Lower is "better".
+ pub max_subgroup_size: u32,
/// Amount of storage available for push constants in bytes. Defaults to 0. Higher is "better".
/// Requesting more than 0 during device creation requires [`Features::PUSH_CONSTANTS`] to be enabled.
///
@@ -1146,7 +1175,6 @@ pub struct Limits {
/// - OpenGL doesn't natively support push constants, and are emulated with uniforms,
/// so this number is less useful but likely 256.
pub max_push_constant_size: u32,
-
/// Maximum number of live non-sampler bindings.
///
/// This limit only affects the d3d12 backend. Using a large number will allow the device
@@ -1156,6 +1184,14 @@ pub struct Limits {
impl Default for Limits {
fn default() -> Self {
+ Self::defaults()
+ }
+}
+
+impl Limits {
+ // Rust doesn't allow const in trait implementations, so we break this out
+ // to allow reusing these defaults in const contexts like `downlevel_defaults`
+ const fn defaults() -> Self {
Self {
max_texture_dimension_1d: 8192,
max_texture_dimension_2d: 8192,
@@ -1170,10 +1206,10 @@ impl Default for Limits {
max_storage_buffers_per_shader_stage: 8,
max_storage_textures_per_shader_stage: 4,
max_uniform_buffers_per_shader_stage: 12,
- max_uniform_buffer_binding_size: 64 << 10,
- max_storage_buffer_binding_size: 128 << 20,
+ max_uniform_buffer_binding_size: 64 << 10, // (64 KiB)
+ max_storage_buffer_binding_size: 128 << 20, // (128 MiB)
max_vertex_buffers: 8,
- max_buffer_size: 256 << 20,
+ max_buffer_size: 256 << 20, // (256 MiB)
max_vertex_attributes: 16,
max_vertex_buffer_array_stride: 2048,
min_uniform_buffer_offset_alignment: 256,
@@ -1187,13 +1223,13 @@ impl Default for Limits {
max_compute_workgroup_size_y: 256,
max_compute_workgroup_size_z: 64,
max_compute_workgroups_per_dimension: 65535,
+ min_subgroup_size: 0,
+ max_subgroup_size: 0,
max_push_constant_size: 0,
max_non_sampler_bindings: 1_000_000,
}
}
-}
-impl Limits {
/// These default limits are guaranteed to be compatible with GLES-3.1, and D3D11
///
/// Those limits are as follows (different from default are marked with *):
@@ -1218,13 +1254,15 @@ impl Limits {
/// max_vertex_buffers: 8,
/// max_vertex_attributes: 16,
/// max_vertex_buffer_array_stride: 2048,
+ /// min_subgroup_size: 0,
+ /// max_subgroup_size: 0,
/// max_push_constant_size: 0,
/// min_uniform_buffer_offset_alignment: 256,
/// min_storage_buffer_offset_alignment: 256,
/// max_inter_stage_shader_components: 60,
/// max_color_attachments: 8,
/// max_color_attachment_bytes_per_sample: 32,
- /// max_compute_workgroup_storage_size: 16352,
+ /// max_compute_workgroup_storage_size: 16352, // *
/// max_compute_invocations_per_workgroup: 256,
/// max_compute_workgroup_size_x: 256,
/// max_compute_workgroup_size_y: 256,
@@ -1239,35 +1277,11 @@ impl Limits {
max_texture_dimension_1d: 2048,
max_texture_dimension_2d: 2048,
max_texture_dimension_3d: 256,
- max_texture_array_layers: 256,
- max_bind_groups: 4,
- max_bindings_per_bind_group: 1000,
- max_dynamic_uniform_buffers_per_pipeline_layout: 8,
- max_dynamic_storage_buffers_per_pipeline_layout: 4,
- max_sampled_textures_per_shader_stage: 16,
- max_samplers_per_shader_stage: 16,
max_storage_buffers_per_shader_stage: 4,
- max_storage_textures_per_shader_stage: 4,
- max_uniform_buffers_per_shader_stage: 12,
- max_uniform_buffer_binding_size: 16 << 10,
- max_storage_buffer_binding_size: 128 << 20,
- max_vertex_buffers: 8,
- max_vertex_attributes: 16,
- max_vertex_buffer_array_stride: 2048,
- max_push_constant_size: 0,
- min_uniform_buffer_offset_alignment: 256,
- min_storage_buffer_offset_alignment: 256,
- max_inter_stage_shader_components: 60,
- max_color_attachments: 8,
- max_color_attachment_bytes_per_sample: 32,
+ max_uniform_buffer_binding_size: 16 << 10, // (16 KiB)
+ // see: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf#page=7
max_compute_workgroup_storage_size: 16352,
- max_compute_invocations_per_workgroup: 256,
- max_compute_workgroup_size_x: 256,
- max_compute_workgroup_size_y: 256,
- max_compute_workgroup_size_z: 64,
- max_compute_workgroups_per_dimension: 65535,
- max_buffer_size: 256 << 20,
- max_non_sampler_bindings: 1_000_000,
+ ..Self::defaults()
}
}
@@ -1296,6 +1310,8 @@ impl Limits {
/// max_vertex_buffers: 8,
/// max_vertex_attributes: 16,
/// max_vertex_buffer_array_stride: 255, // +
+ /// min_subgroup_size: 0,
+ /// max_subgroup_size: 0,
/// max_push_constant_size: 0,
/// min_uniform_buffer_offset_alignment: 256,
/// min_storage_buffer_offset_alignment: 256,
@@ -1326,6 +1342,8 @@ impl Limits {
max_compute_workgroup_size_y: 0,
max_compute_workgroup_size_z: 0,
max_compute_workgroups_per_dimension: 0,
+ min_subgroup_size: 0,
+ max_subgroup_size: 0,
// Value supported by Intel Celeron B830 on Windows (OpenGL 3.1)
max_inter_stage_shader_components: 31,
@@ -1418,6 +1436,10 @@ impl Limits {
compare!(max_vertex_buffers, Less);
compare!(max_vertex_attributes, Less);
compare!(max_vertex_buffer_array_stride, Less);
+ if self.min_subgroup_size > 0 && self.max_subgroup_size > 0 {
+ compare!(min_subgroup_size, Greater);
+ compare!(max_subgroup_size, Less);
+ }
compare!(max_push_constant_size, Less);
compare!(min_uniform_buffer_offset_alignment, Greater);
compare!(min_storage_buffer_offset_alignment, Greater);
@@ -4942,6 +4964,9 @@ pub enum VertexFormat {
Float64x3 = 32,
/// Four double-precision floats (f64). `vec4<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
Float64x4 = 33,
+ /// Three unsigned 10-bit integers and one 2-bit integer, packed into a 32-bit integer (u32). [0, 1024] converted to float [0, 1] `vec4<f32>` in shaders.
+ #[cfg_attr(feature = "serde", serde(rename = "unorm10-10-10-2"))]
+ Unorm10_10_10_2 = 34,
}
impl VertexFormat {
@@ -4960,7 +4985,8 @@ impl VertexFormat {
| Self::Float16x2
| Self::Float32
| Self::Uint32
- | Self::Sint32 => 4,
+ | Self::Sint32
+ | Self::Unorm10_10_10_2 => 4,
Self::Uint16x4
| Self::Sint16x4
| Self::Unorm16x4
@@ -7068,7 +7094,7 @@ pub struct InstanceDescriptor {
pub flags: InstanceFlags,
/// Which DX12 shader compiler to use.
pub dx12_shader_compiler: Dx12Compiler,
- /// Which OpenGL ES 3 minor version to request.
+ /// Which OpenGL ES 3 minor version to request. Will be ignored if OpenGL is available.
pub gles_minor_version: Gles3MinorVersion,
}
diff --git a/third_party/rust/zerocopy-derive/.cargo-checksum.json b/third_party/rust/zerocopy-derive/.cargo-checksum.json
new file mode 100644
index 0000000000..805ee6472f
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"b92b9f131058b37c8287d8cd35731a933f05bcd2b82d4ff4771bb8b9e7726d0d","LICENSE-APACHE":"9d185ac6703c4b0453974c0d85e9eee43e6941009296bb1f5eb0b54e2329e9f3","LICENSE-BSD":"83c1763356e822adde0a2cae748d938a73fdc263849ccff6b27776dff213bd32","LICENSE-MIT":"1a2f5c12ddc934d58956aa5dbdd3255fe55fd957633ab7d0d39e4f0daa73f7df","src/ext.rs":"d741f6132fca552676b132a38b6431362054aec0c86dcf1c281bca51d5decad2","src/lib.rs":"cb237ff473b4216c7b6e6beeb4789532eac31e776c9b6d39a06d408e2003bfd5","src/repr.rs":"780f547b9d51794ec35ea9359a2c55cd40cf1d84f6e1f4080034ff337df953c1","tests/enum_as_bytes.rs":"2e11daa46c6b922d748321e9a47c3b355e2a9e3b48af95a699c39186b7783711","tests/enum_from_zeroes.rs":"32ca3d0dc9085ef8eb9597b5e057ff0b3a0e92b6da44fac3326b2a124010ba4b","tests/enum_known_layout.rs":"7bc4979b3f9cadc4784afd821ea1c0670fe987a842627f9bb4406b248c5c6ce4","tests/enum_unaligned.rs":"0c42281098047c6a106c2eae2ee792b893b4f295e8147cf56eaf826888be5fbf","tests/hygiene.rs":"24f6fb3e4f1aa313753d3f16d9285105b836392f9d68de77ea436a9b24443102","tests/paths_and_modules.rs":"4218b6ac5d1aeb2d3b199af5f64eea45ab1117fc135e9d30588ff761e98b0f10","tests/priv_in_pub.rs":"57ff0106151dc34f2e14be90ca73c1c7e6791215683b28fc68abd2deed90fedb","tests/struct_as_bytes.rs":"334053105b4341376e11a895ceb534b1f0961100f7d04ece17745fbf7d58e0ca","tests/struct_from_bytes.rs":"90e4d0d7cd9b72f3338edff937f195614fca52b6d937cfbba5c2bc763ebc1e60","tests/struct_from_zeroes.rs":"52d6965cd7571926683e85b5b13e09a25144ad0615c7c73ac3a0abf99fa33cb8","tests/struct_known_layout.rs":"1d54c62a9f4682a1ae4174cee9c73c5f0986623f7bbb069c1bed78b82be36989","tests/struct_unaligned.rs":"a5d3377dda1ba884ec4b70ca043f599eccba3b2258de16c58a72c43633507e2e","tests/trybuild.rs":"0954299d2c50d06259a628fa828131e9f0e8953dfcc2cf0d52d6d9ff40c969d5","tests/ui-msrv/derive_transparent.rs":"9f15bf0bf22c8e47c3d645f99239462eae6a875bd469510ad41838d9ae4ed1f8","tests/ui-msrv/derive_transparent.stderr":"b8a66f15647fa8ef3ab5ab371710f36943b42af8f3d2d088509c05f029ad7b8d","tests/ui-msrv/enum.rs":"7eb4f7f912f91c9a040536882b398ac4f07153fd8dbcc49a30603c6eb8107899","tests/ui-msrv/enum.stderr":"321e41c161804d3918fd15214845862c5ca346581e88cf0260073e3c6203cc21","tests/ui-msrv/enum_from_bytes_u8_too_few.rs":"afbec6f24a4bfca472f2929abc5125d8f5b305a0a1b472a1215ad7739ed63100","tests/ui-msrv/enum_from_bytes_u8_too_few.stderr":"a5ab2757166ef9dfa51a09d3dbddd5e9e2b1a46bd3d4b8d175b33a90747878d7","tests/ui-msrv/late_compile_pass.rs":"244f7dcc9a821a400fe3c24323cf8ffe89aa28454527a85b492fc5afd5cae205","tests/ui-msrv/late_compile_pass.stderr":"a8598656086bfc855c7c69131e08b3ac0eac22c5a731346ab4fb5d06dc0dd8e6","tests/ui-msrv/mid_compile_pass.rs":"b80b01bfd383c537173f7d630ec2789a2af3e01bc6d53c807fdcf271b235d0c9","tests/ui-msrv/mid_compile_pass.stderr":"d2d8d441c7642ca266a4250e8b6a4a9aa693cfc2ec48f679600e392e7b6c6273","tests/ui-msrv/struct.rs":"882b8f0a84ac772aaec5a4f786a5216ad37a269a6d9f1f836f1b27cbe861743c","tests/ui-msrv/struct.stderr":"eb245197d856850ea4e9c6ec58fae60058dee5f7fb7ca68b113e4c9cd7826b34","tests/ui-msrv/union.rs":"0661431d493e5690653ba0ed076fba14ab03fff81471d572369269aa58bde5a0","tests/ui-msrv/union.stderr":"a75b425e50af3759dfe4d2bf832b4cb650ddbaf6b5c8853aa904be98685f1e53","tests/ui-nightly/derive_transparent.rs":"9f15bf0bf22c8e47c3d645f99239462eae6a875bd469510ad41838d9ae4ed1f8","tests/ui-nightly/derive_transparent.stderr":"8feb1939943dfa984b301d806844fe0d95ea4830690dd636643c80c81d827d46","tests/ui-nightly/enum.rs":"7eb4f7f912f91c9a040536882b398ac4f07153fd8dbcc49a30603c6eb8107899","tests/ui-nightly/enum.stderr":"9b4d965632beb995022209f0f4ca5d875725f33149916a963402b1901e1dbf14","tests/ui-nightly/enum_from_bytes_u8_too_few.rs":"afbec6f24a4bfca472f2929abc5125d8f5b305a0a1b472a1215ad7739ed63100","tests/ui-nightly/enum_from_bytes_u8_too_few.stderr":"28a493e1057279ea8e20df49ff0c02dfa132027a86bb6f5fe50e250c14e62572","tests/ui-nightly/late_compile_pass.rs":"244f7dcc9a821a400fe3c24323cf8ffe89aa28454527a85b492fc5afd5cae205","tests/ui-nightly/late_compile_pass.stderr":"f9615dc6b05b9b16a67fac482996a4eb147ff4c40e57083c74bdadd00545e3cf","tests/ui-nightly/mid_compile_pass.rs":"b80b01bfd383c537173f7d630ec2789a2af3e01bc6d53c807fdcf271b235d0c9","tests/ui-nightly/mid_compile_pass.stderr":"632c2bcbd13cef40d33acff4e03a92ba1ead5183f9b0876ab761d6c6e9da4276","tests/ui-nightly/struct.rs":"882b8f0a84ac772aaec5a4f786a5216ad37a269a6d9f1f836f1b27cbe861743c","tests/ui-nightly/struct.stderr":"34d084ac848de2880725d41e217c68d1c4cfc31f430195b65508f04dc547e9e5","tests/ui-nightly/union.rs":"0661431d493e5690653ba0ed076fba14ab03fff81471d572369269aa58bde5a0","tests/ui-nightly/union.stderr":"98209cdba5ae46d190d66ba9a6c882aff43b5c584cefc156c5fd24db177f377f","tests/ui-stable/derive_transparent.rs":"9f15bf0bf22c8e47c3d645f99239462eae6a875bd469510ad41838d9ae4ed1f8","tests/ui-stable/derive_transparent.stderr":"7563c87d050d46b7b02f175da358ff03415e729af09bfcef048744569068d7fb","tests/ui-stable/enum.rs":"7eb4f7f912f91c9a040536882b398ac4f07153fd8dbcc49a30603c6eb8107899","tests/ui-stable/enum.stderr":"3d2f2fa112f70f7c18e6aa3400ed5f28ff39b9241de4fdecf7e786bfe85ceadc","tests/ui-stable/enum_from_bytes_u8_too_few.rs":"afbec6f24a4bfca472f2929abc5125d8f5b305a0a1b472a1215ad7739ed63100","tests/ui-stable/enum_from_bytes_u8_too_few.stderr":"b3edb381f968f6f2ad9ab4810132df5962b0650460e07f77af818ababf124fe7","tests/ui-stable/late_compile_pass.rs":"244f7dcc9a821a400fe3c24323cf8ffe89aa28454527a85b492fc5afd5cae205","tests/ui-stable/late_compile_pass.stderr":"a22045df3f18250281809d487dc5782fc951431bd9728215bc9805e2e3e26407","tests/ui-stable/mid_compile_pass.rs":"b80b01bfd383c537173f7d630ec2789a2af3e01bc6d53c807fdcf271b235d0c9","tests/ui-stable/mid_compile_pass.stderr":"673d12c5c7105700a071f995f5644448694efe5733b54ac95dfa02ebe18b67f4","tests/ui-stable/struct.rs":"882b8f0a84ac772aaec5a4f786a5216ad37a269a6d9f1f836f1b27cbe861743c","tests/ui-stable/struct.stderr":"36360e6559d22de902331c48e9398955f4186195e2c1c4bfb587afb287538388","tests/ui-stable/union.rs":"0661431d493e5690653ba0ed076fba14ab03fff81471d572369269aa58bde5a0","tests/ui-stable/union.stderr":"0a2012e5f32634fc3beb033f07b66fc043737623f630f5f957864e72e9dd3ef6","tests/union_as_bytes.rs":"57e69981ed7bb8eebbb2ea2be160532074e32aa4cec6543e9e3af0f5e3767fd8","tests/union_from_bytes.rs":"7da559bbb70fb2dbbb7422ad3099d8c2504d5815bc1e87173ffa758b929382b2","tests/union_from_zeroes.rs":"448d21026955403e1f09c69e19c3542a454456aab1c13d32dad8c612b8cbc7f8","tests/union_known_layout.rs":"a94be098de0a2565d1cf3e9631b36c250ddae1c3490f18e9d8a7b6f70274ec00","tests/union_unaligned.rs":"c8a0458226645063805b9653c2148048e7b93b273b93e7959a969f15e167fa57","tests/util.rs":"8d0cfb435e4b154a3702511f3d10331d6b01bcd90f0d70d4a094778813e9e387"},"package":"9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"} \ No newline at end of file
diff --git a/third_party/rust/zerocopy-derive/Cargo.toml b/third_party/rust/zerocopy-derive/Cargo.toml
new file mode 100644
index 0000000000..827fe9f223
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/Cargo.toml
@@ -0,0 +1,44 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.60.0"
+name = "zerocopy-derive"
+version = "0.7.32"
+authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
+exclude = [
+ ".*",
+ "tests/enum_from_bytes.rs",
+ "tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled",
+]
+description = "Custom derive for traits from the zerocopy crate"
+license = "BSD-2-Clause OR Apache-2.0 OR MIT"
+repository = "https://github.com/google/zerocopy"
+
+[lib]
+proc-macro = true
+
+[dependencies.proc-macro2]
+version = "1.0.1"
+
+[dependencies.quote]
+version = "1.0.10"
+
+[dependencies.syn]
+version = "2.0.31"
+
+[dev-dependencies.static_assertions]
+version = "1.1"
+
+[dev-dependencies.trybuild]
+version = "=1.0.85"
+features = ["diff"]
diff --git a/third_party/rust/zerocopy-derive/LICENSE-APACHE b/third_party/rust/zerocopy-derive/LICENSE-APACHE
new file mode 100644
index 0000000000..2dc22c12fa
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/LICENSE-APACHE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2023 The Fuchsia Authors
+
+ 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
+
+ http://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.
+
diff --git a/third_party/rust/zerocopy-derive/LICENSE-BSD b/third_party/rust/zerocopy-derive/LICENSE-BSD
new file mode 100644
index 0000000000..7ed244f42d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/LICENSE-BSD
@@ -0,0 +1,24 @@
+Copyright 2019 The Fuchsia Authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/rust/zerocopy-derive/LICENSE-MIT b/third_party/rust/zerocopy-derive/LICENSE-MIT
new file mode 100644
index 0000000000..26e15216cd
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/LICENSE-MIT
@@ -0,0 +1,26 @@
+Copyright 2023 The Fuchsia Authors
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/third_party/rust/zerocopy-derive/src/ext.rs b/third_party/rust/zerocopy-derive/src/ext.rs
new file mode 100644
index 0000000000..87cf838f88
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/src/ext.rs
@@ -0,0 +1,53 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+use syn::{Data, DataEnum, DataStruct, DataUnion, Type};
+
+pub trait DataExt {
+ /// Extract the types of all fields. For enums, extract the types of fields
+ /// from each variant.
+ fn field_types(&self) -> Vec<&Type>;
+}
+
+impl DataExt for Data {
+ fn field_types(&self) -> Vec<&Type> {
+ match self {
+ Data::Struct(strc) => strc.field_types(),
+ Data::Enum(enm) => enm.field_types(),
+ Data::Union(un) => un.field_types(),
+ }
+ }
+}
+
+impl DataExt for DataStruct {
+ fn field_types(&self) -> Vec<&Type> {
+ self.fields.iter().map(|f| &f.ty).collect()
+ }
+}
+
+impl DataExt for DataEnum {
+ fn field_types(&self) -> Vec<&Type> {
+ self.variants.iter().flat_map(|var| &var.fields).map(|f| &f.ty).collect()
+ }
+}
+
+impl DataExt for DataUnion {
+ fn field_types(&self) -> Vec<&Type> {
+ self.fields.named.iter().map(|f| &f.ty).collect()
+ }
+}
+
+pub trait EnumExt {
+ fn is_c_like(&self) -> bool;
+}
+
+impl EnumExt for DataEnum {
+ fn is_c_like(&self) -> bool {
+ self.field_types().is_empty()
+ }
+}
diff --git a/third_party/rust/zerocopy-derive/src/lib.rs b/third_party/rust/zerocopy-derive/src/lib.rs
new file mode 100644
index 0000000000..9af8a28a06
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/src/lib.rs
@@ -0,0 +1,882 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+//! Derive macros for [zerocopy]'s traits.
+//!
+//! [zerocopy]: https://docs.rs/zerocopy
+
+// Sometimes we want to use lints which were added after our MSRV.
+// `unknown_lints` is `warn` by default and we deny warnings in CI, so without
+// this attribute, any unknown lint would cause a CI failure when testing with
+// our MSRV.
+#![allow(unknown_lints)]
+#![deny(renamed_and_removed_lints)]
+#![deny(clippy::all, clippy::missing_safety_doc, clippy::undocumented_unsafe_blocks)]
+#![deny(
+ rustdoc::bare_urls,
+ rustdoc::broken_intra_doc_links,
+ rustdoc::invalid_codeblock_attributes,
+ rustdoc::invalid_html_tags,
+ rustdoc::invalid_rust_codeblocks,
+ rustdoc::missing_crate_level_docs,
+ rustdoc::private_intra_doc_links
+)]
+#![recursion_limit = "128"]
+
+mod ext;
+mod repr;
+
+use {
+ proc_macro2::Span,
+ quote::quote,
+ syn::{
+ parse_quote, Data, DataEnum, DataStruct, DataUnion, DeriveInput, Error, Expr, ExprLit,
+ GenericParam, Ident, Lit,
+ },
+};
+
+use {crate::ext::*, crate::repr::*};
+
+// Unwraps a `Result<_, Vec<Error>>`, converting any `Err` value into a
+// `TokenStream` and returning it.
+macro_rules! try_or_print {
+ ($e:expr) => {
+ match $e {
+ Ok(x) => x,
+ Err(errors) => return print_all_errors(errors).into(),
+ }
+ };
+}
+
+// TODO(https://github.com/rust-lang/rust/issues/54140): Some errors could be
+// made better if we could add multiple lines of error output like this:
+//
+// error: unsupported representation
+// --> enum.rs:28:8
+// |
+// 28 | #[repr(transparent)]
+// |
+// help: required by the derive of FromBytes
+//
+// Instead, we have more verbose error messages like "unsupported representation
+// for deriving FromZeroes, FromBytes, AsBytes, or Unaligned on an enum"
+//
+// This will probably require Span::error
+// (https://doc.rust-lang.org/nightly/proc_macro/struct.Span.html#method.error),
+// which is currently unstable. Revisit this once it's stable.
+
+#[proc_macro_derive(KnownLayout)]
+pub fn derive_known_layout(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let ast = syn::parse_macro_input!(ts as DeriveInput);
+
+ let is_repr_c_struct = match &ast.data {
+ Data::Struct(..) => {
+ let reprs = try_or_print!(repr::reprs::<Repr>(&ast.attrs));
+ if reprs.iter().any(|(_meta, repr)| repr == &Repr::C) {
+ Some(reprs)
+ } else {
+ None
+ }
+ }
+ Data::Enum(..) | Data::Union(..) => None,
+ };
+
+ let fields = ast.data.field_types();
+
+ let (require_self_sized, extras) = if let (
+ Some(reprs),
+ Some((trailing_field, leading_fields)),
+ ) = (is_repr_c_struct, fields.split_last())
+ {
+ let repr_align = reprs
+ .iter()
+ .find_map(
+ |(_meta, repr)| {
+ if let Repr::Align(repr_align) = repr {
+ Some(repr_align)
+ } else {
+ None
+ }
+ },
+ )
+ .map(|repr_align| quote!(NonZeroUsize::new(#repr_align as usize)))
+ .unwrap_or(quote!(None));
+
+ let repr_packed = reprs
+ .iter()
+ .find_map(|(_meta, repr)| match repr {
+ Repr::Packed => Some(1),
+ Repr::PackedN(repr_packed) => Some(*repr_packed),
+ _ => None,
+ })
+ .map(|repr_packed| quote!(NonZeroUsize::new(#repr_packed as usize)))
+ .unwrap_or(quote!(None));
+
+ (
+ false,
+ quote!(
+ // SAFETY: `LAYOUT` accurately describes the layout of `Self`.
+ // The layout of `Self` is reflected using a sequence of
+ // invocations of `DstLayout::{new_zst,extend,pad_to_align}`.
+ // The documentation of these items vows that invocations in
+ // this manner will acurately describe a type, so long as:
+ //
+ // - that type is `repr(C)`,
+ // - its fields are enumerated in the order they appear,
+ // - the presence of `repr_align` and `repr_packed` are correctly accounted for.
+ //
+ // We respect all three of these preconditions here. This
+ // expansion is only used if `is_repr_c_struct`, we enumerate
+ // the fields in order, and we extract the values of `align(N)`
+ // and `packed(N)`.
+ const LAYOUT: ::zerocopy::DstLayout = {
+ use ::zerocopy::macro_util::core_reexport::num::NonZeroUsize;
+ use ::zerocopy::{DstLayout, KnownLayout};
+
+ let repr_align = #repr_align;
+ let repr_packed = #repr_packed;
+
+ DstLayout::new_zst(repr_align)
+ #(.extend(DstLayout::for_type::<#leading_fields>(), repr_packed))*
+ .extend(<#trailing_field as KnownLayout>::LAYOUT, repr_packed)
+ .pad_to_align()
+ };
+
+ // SAFETY:
+ // - The recursive call to `raw_from_ptr_len` preserves both address and provenance.
+ // - The `as` cast preserves both address and provenance.
+ // - `NonNull::new_unchecked` preserves both address and provenance.
+ #[inline(always)]
+ fn raw_from_ptr_len(
+ bytes: ::zerocopy::macro_util::core_reexport::ptr::NonNull<u8>,
+ elems: usize,
+ ) -> ::zerocopy::macro_util::core_reexport::ptr::NonNull<Self> {
+ use ::zerocopy::{KnownLayout};
+ let trailing = <#trailing_field as KnownLayout>::raw_from_ptr_len(bytes, elems);
+ let slf = trailing.as_ptr() as *mut Self;
+ // SAFETY: Constructed from `trailing`, which is non-null.
+ unsafe { ::zerocopy::macro_util::core_reexport::ptr::NonNull::new_unchecked(slf) }
+ }
+ ),
+ )
+ } else {
+ // For enums, unions, and non-`repr(C)` structs, we require that
+ // `Self` is sized, and as a result don't need to reason about the
+ // internals of the type.
+ (
+ true,
+ quote!(
+ // SAFETY: `LAYOUT` is guaranteed to accurately describe the
+ // layout of `Self`, because that is the documented safety
+ // contract of `DstLayout::for_type`.
+ const LAYOUT: ::zerocopy::DstLayout = ::zerocopy::DstLayout::for_type::<Self>();
+
+ // SAFETY: `.cast` preserves address and provenance.
+ //
+ // TODO(#429): Add documentation to `.cast` that promises that
+ // it preserves provenance.
+ #[inline(always)]
+ fn raw_from_ptr_len(
+ bytes: ::zerocopy::macro_util::core_reexport::ptr::NonNull<u8>,
+ _elems: usize,
+ ) -> ::zerocopy::macro_util::core_reexport::ptr::NonNull<Self> {
+ bytes.cast::<Self>()
+ }
+ ),
+ )
+ };
+
+ match &ast.data {
+ Data::Struct(strct) => {
+ let require_trait_bound_on_field_types = if require_self_sized {
+ RequireBoundedFields::No
+ } else {
+ RequireBoundedFields::Trailing
+ };
+
+ // A bound on the trailing field is required, since structs are
+ // unsized if their trailing field is unsized. Reflecting the layout
+ // of an usized trailing field requires that the field is
+ // `KnownLayout`.
+ impl_block(
+ &ast,
+ strct,
+ Trait::KnownLayout,
+ require_trait_bound_on_field_types,
+ require_self_sized,
+ None,
+ Some(extras),
+ )
+ }
+ Data::Enum(enm) => {
+ // A bound on the trailing field is not required, since enums cannot
+ // currently be unsized.
+ impl_block(
+ &ast,
+ enm,
+ Trait::KnownLayout,
+ RequireBoundedFields::No,
+ true,
+ None,
+ Some(extras),
+ )
+ }
+ Data::Union(unn) => {
+ // A bound on the trailing field is not required, since unions
+ // cannot currently be unsized.
+ impl_block(
+ &ast,
+ unn,
+ Trait::KnownLayout,
+ RequireBoundedFields::No,
+ true,
+ None,
+ Some(extras),
+ )
+ }
+ }
+ .into()
+}
+
+#[proc_macro_derive(FromZeroes)]
+pub fn derive_from_zeroes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let ast = syn::parse_macro_input!(ts as DeriveInput);
+ match &ast.data {
+ Data::Struct(strct) => derive_from_zeroes_struct(&ast, strct),
+ Data::Enum(enm) => derive_from_zeroes_enum(&ast, enm),
+ Data::Union(unn) => derive_from_zeroes_union(&ast, unn),
+ }
+ .into()
+}
+
+#[proc_macro_derive(FromBytes)]
+pub fn derive_from_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let ast = syn::parse_macro_input!(ts as DeriveInput);
+ match &ast.data {
+ Data::Struct(strct) => derive_from_bytes_struct(&ast, strct),
+ Data::Enum(enm) => derive_from_bytes_enum(&ast, enm),
+ Data::Union(unn) => derive_from_bytes_union(&ast, unn),
+ }
+ .into()
+}
+
+#[proc_macro_derive(AsBytes)]
+pub fn derive_as_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let ast = syn::parse_macro_input!(ts as DeriveInput);
+ match &ast.data {
+ Data::Struct(strct) => derive_as_bytes_struct(&ast, strct),
+ Data::Enum(enm) => derive_as_bytes_enum(&ast, enm),
+ Data::Union(unn) => derive_as_bytes_union(&ast, unn),
+ }
+ .into()
+}
+
+#[proc_macro_derive(Unaligned)]
+pub fn derive_unaligned(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let ast = syn::parse_macro_input!(ts as DeriveInput);
+ match &ast.data {
+ Data::Struct(strct) => derive_unaligned_struct(&ast, strct),
+ Data::Enum(enm) => derive_unaligned_enum(&ast, enm),
+ Data::Union(unn) => derive_unaligned_union(&ast, unn),
+ }
+ .into()
+}
+
+const STRUCT_UNION_ALLOWED_REPR_COMBINATIONS: &[&[StructRepr]] = &[
+ &[StructRepr::C],
+ &[StructRepr::Transparent],
+ &[StructRepr::Packed],
+ &[StructRepr::C, StructRepr::Packed],
+];
+
+// A struct is `FromZeroes` if:
+// - all fields are `FromZeroes`
+
+fn derive_from_zeroes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream {
+ impl_block(ast, strct, Trait::FromZeroes, RequireBoundedFields::Yes, false, None, None)
+}
+
+// An enum is `FromZeroes` if:
+// - all of its variants are fieldless
+// - one of the variants has a discriminant of `0`
+
+fn derive_from_zeroes_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::TokenStream {
+ if !enm.is_c_like() {
+ return Error::new_spanned(ast, "only C-like enums can implement FromZeroes")
+ .to_compile_error();
+ }
+
+ let has_explicit_zero_discriminant =
+ enm.variants.iter().filter_map(|v| v.discriminant.as_ref()).any(|(_, e)| {
+ if let Expr::Lit(ExprLit { lit: Lit::Int(i), .. }) = e {
+ i.base10_parse::<usize>().ok() == Some(0)
+ } else {
+ false
+ }
+ });
+ // If the first variant of an enum does not specify its discriminant, it is set to zero:
+ // https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
+ let has_implicit_zero_discriminant =
+ enm.variants.iter().next().map(|v| v.discriminant.is_none()) == Some(true);
+
+ if !has_explicit_zero_discriminant && !has_implicit_zero_discriminant {
+ return Error::new_spanned(
+ ast,
+ "FromZeroes only supported on enums with a variant that has a discriminant of `0`",
+ )
+ .to_compile_error();
+ }
+
+ impl_block(ast, enm, Trait::FromZeroes, RequireBoundedFields::Yes, false, None, None)
+}
+
+// Like structs, unions are `FromZeroes` if
+// - all fields are `FromZeroes`
+
+fn derive_from_zeroes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream {
+ impl_block(ast, unn, Trait::FromZeroes, RequireBoundedFields::Yes, false, None, None)
+}
+
+// A struct is `FromBytes` if:
+// - all fields are `FromBytes`
+
+fn derive_from_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream {
+ impl_block(ast, strct, Trait::FromBytes, RequireBoundedFields::Yes, false, None, None)
+}
+
+// An enum is `FromBytes` if:
+// - Every possible bit pattern must be valid, which means that every bit
+// pattern must correspond to a different enum variant. Thus, for an enum
+// whose layout takes up N bytes, there must be 2^N variants.
+// - Since we must know N, only representations which guarantee the layout's
+// size are allowed. These are `repr(uN)` and `repr(iN)` (`repr(C)` implies an
+// implementation-defined size). `usize` and `isize` technically guarantee the
+// layout's size, but would require us to know how large those are on the
+// target platform. This isn't terribly difficult - we could emit a const
+// expression that could call `core::mem::size_of` in order to determine the
+// size and check against the number of enum variants, but a) this would be
+// platform-specific and, b) even on Rust's smallest bit width platform (32),
+// this would require ~4 billion enum variants, which obviously isn't a thing.
+
+fn derive_from_bytes_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::TokenStream {
+ if !enm.is_c_like() {
+ return Error::new_spanned(ast, "only C-like enums can implement FromBytes")
+ .to_compile_error();
+ }
+
+ let reprs = try_or_print!(ENUM_FROM_BYTES_CFG.validate_reprs(ast));
+
+ let variants_required = match reprs.as_slice() {
+ [EnumRepr::U8] | [EnumRepr::I8] => 1usize << 8,
+ [EnumRepr::U16] | [EnumRepr::I16] => 1usize << 16,
+ // `validate_reprs` has already validated that it's one of the preceding
+ // patterns.
+ _ => unreachable!(),
+ };
+ if enm.variants.len() != variants_required {
+ return Error::new_spanned(
+ ast,
+ format!(
+ "FromBytes only supported on {} enum with {} variants",
+ reprs[0], variants_required
+ ),
+ )
+ .to_compile_error();
+ }
+
+ impl_block(ast, enm, Trait::FromBytes, RequireBoundedFields::Yes, false, None, None)
+}
+
+#[rustfmt::skip]
+const ENUM_FROM_BYTES_CFG: Config<EnumRepr> = {
+ use EnumRepr::*;
+ Config {
+ allowed_combinations_message: r#"FromBytes requires repr of "u8", "u16", "i8", or "i16""#,
+ derive_unaligned: false,
+ allowed_combinations: &[
+ &[U8],
+ &[U16],
+ &[I8],
+ &[I16],
+ ],
+ disallowed_but_legal_combinations: &[
+ &[C],
+ &[U32],
+ &[I32],
+ &[U64],
+ &[I64],
+ &[Usize],
+ &[Isize],
+ ],
+ }
+};
+
+// Like structs, unions are `FromBytes` if
+// - all fields are `FromBytes`
+
+fn derive_from_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream {
+ impl_block(ast, unn, Trait::FromBytes, RequireBoundedFields::Yes, false, None, None)
+}
+
+// A struct is `AsBytes` if:
+// - all fields are `AsBytes`
+// - `repr(C)` or `repr(transparent)` and
+// - no padding (size of struct equals sum of size of field types)
+// - `repr(packed)`
+
+fn derive_as_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream {
+ let reprs = try_or_print!(STRUCT_UNION_AS_BYTES_CFG.validate_reprs(ast));
+ let is_transparent = reprs.contains(&StructRepr::Transparent);
+ let is_packed = reprs.contains(&StructRepr::Packed);
+
+ // TODO(#10): Support type parameters for non-transparent, non-packed
+ // structs.
+ if !ast.generics.params.is_empty() && !is_transparent && !is_packed {
+ return Error::new(
+ Span::call_site(),
+ "unsupported on generic structs that are not repr(transparent) or repr(packed)",
+ )
+ .to_compile_error();
+ }
+
+ // We don't need a padding check if the struct is repr(transparent) or
+ // repr(packed).
+ // - repr(transparent): The layout and ABI of the whole struct is the same
+ // as its only non-ZST field (meaning there's no padding outside of that
+ // field) and we require that field to be `AsBytes` (meaning there's no
+ // padding in that field).
+ // - repr(packed): Any inter-field padding bytes are removed, meaning that
+ // any padding bytes would need to come from the fields, all of which
+ // we require to be `AsBytes` (meaning they don't have any padding).
+ let padding_check = if is_transparent || is_packed { None } else { Some(PaddingCheck::Struct) };
+ impl_block(ast, strct, Trait::AsBytes, RequireBoundedFields::Yes, false, padding_check, None)
+}
+
+const STRUCT_UNION_AS_BYTES_CFG: Config<StructRepr> = Config {
+ // Since `disallowed_but_legal_combinations` is empty, this message will
+ // never actually be emitted.
+ allowed_combinations_message: r#"AsBytes requires either a) repr "C" or "transparent" with all fields implementing AsBytes or, b) repr "packed""#,
+ derive_unaligned: false,
+ allowed_combinations: STRUCT_UNION_ALLOWED_REPR_COMBINATIONS,
+ disallowed_but_legal_combinations: &[],
+};
+
+// An enum is `AsBytes` if it is C-like and has a defined repr.
+
+fn derive_as_bytes_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::TokenStream {
+ if !enm.is_c_like() {
+ return Error::new_spanned(ast, "only C-like enums can implement AsBytes")
+ .to_compile_error();
+ }
+
+ // We don't care what the repr is; we only care that it is one of the
+ // allowed ones.
+ let _: Vec<repr::EnumRepr> = try_or_print!(ENUM_AS_BYTES_CFG.validate_reprs(ast));
+ impl_block(ast, enm, Trait::AsBytes, RequireBoundedFields::No, false, None, None)
+}
+
+#[rustfmt::skip]
+const ENUM_AS_BYTES_CFG: Config<EnumRepr> = {
+ use EnumRepr::*;
+ Config {
+ // Since `disallowed_but_legal_combinations` is empty, this message will
+ // never actually be emitted.
+ allowed_combinations_message: r#"AsBytes requires repr of "C", "u8", "u16", "u32", "u64", "usize", "i8", "i16", "i32", "i64", or "isize""#,
+ derive_unaligned: false,
+ allowed_combinations: &[
+ &[C],
+ &[U8],
+ &[U16],
+ &[I8],
+ &[I16],
+ &[U32],
+ &[I32],
+ &[U64],
+ &[I64],
+ &[Usize],
+ &[Isize],
+ ],
+ disallowed_but_legal_combinations: &[],
+ }
+};
+
+// A union is `AsBytes` if:
+// - all fields are `AsBytes`
+// - `repr(C)`, `repr(transparent)`, or `repr(packed)`
+// - no padding (size of union equals size of each field type)
+
+fn derive_as_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream {
+ // TODO(#10): Support type parameters.
+ if !ast.generics.params.is_empty() {
+ return Error::new(Span::call_site(), "unsupported on types with type parameters")
+ .to_compile_error();
+ }
+
+ try_or_print!(STRUCT_UNION_AS_BYTES_CFG.validate_reprs(ast));
+
+ impl_block(
+ ast,
+ unn,
+ Trait::AsBytes,
+ RequireBoundedFields::Yes,
+ false,
+ Some(PaddingCheck::Union),
+ None,
+ )
+}
+
+// A struct is `Unaligned` if:
+// - `repr(align)` is no more than 1 and either
+// - `repr(C)` or `repr(transparent)` and
+// - all fields `Unaligned`
+// - `repr(packed)`
+
+fn derive_unaligned_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream {
+ let reprs = try_or_print!(STRUCT_UNION_UNALIGNED_CFG.validate_reprs(ast));
+ let require_trait_bounds_on_field_types = (!reprs.contains(&StructRepr::Packed)).into();
+
+ impl_block(ast, strct, Trait::Unaligned, require_trait_bounds_on_field_types, false, None, None)
+}
+
+const STRUCT_UNION_UNALIGNED_CFG: Config<StructRepr> = Config {
+ // Since `disallowed_but_legal_combinations` is empty, this message will
+ // never actually be emitted.
+ allowed_combinations_message: r#"Unaligned requires either a) repr "C" or "transparent" with all fields implementing Unaligned or, b) repr "packed""#,
+ derive_unaligned: true,
+ allowed_combinations: STRUCT_UNION_ALLOWED_REPR_COMBINATIONS,
+ disallowed_but_legal_combinations: &[],
+};
+
+// An enum is `Unaligned` if:
+// - No `repr(align(N > 1))`
+// - `repr(u8)` or `repr(i8)`
+
+fn derive_unaligned_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::TokenStream {
+ if !enm.is_c_like() {
+ return Error::new_spanned(ast, "only C-like enums can implement Unaligned")
+ .to_compile_error();
+ }
+
+ // The only valid reprs are `u8` and `i8`, and optionally `align(1)`. We
+ // don't actually care what the reprs are so long as they satisfy that
+ // requirement.
+ let _: Vec<repr::EnumRepr> = try_or_print!(ENUM_UNALIGNED_CFG.validate_reprs(ast));
+
+ // C-like enums cannot currently have type parameters, so this value of true
+ // for `require_trait_bound_on_field_types` doesn't really do anything. But
+ // it's marginally more future-proof in case that restriction is lifted in
+ // the future.
+ impl_block(ast, enm, Trait::Unaligned, RequireBoundedFields::Yes, false, None, None)
+}
+
+#[rustfmt::skip]
+const ENUM_UNALIGNED_CFG: Config<EnumRepr> = {
+ use EnumRepr::*;
+ Config {
+ allowed_combinations_message:
+ r#"Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))"#,
+ derive_unaligned: true,
+ allowed_combinations: &[
+ &[U8],
+ &[I8],
+ ],
+ disallowed_but_legal_combinations: &[
+ &[C],
+ &[U16],
+ &[U32],
+ &[U64],
+ &[Usize],
+ &[I16],
+ &[I32],
+ &[I64],
+ &[Isize],
+ ],
+ }
+};
+
+// Like structs, a union is `Unaligned` if:
+// - `repr(align)` is no more than 1 and either
+// - `repr(C)` or `repr(transparent)` and
+// - all fields `Unaligned`
+// - `repr(packed)`
+
+fn derive_unaligned_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream {
+ let reprs = try_or_print!(STRUCT_UNION_UNALIGNED_CFG.validate_reprs(ast));
+ let require_trait_bound_on_field_types = (!reprs.contains(&StructRepr::Packed)).into();
+
+ impl_block(ast, unn, Trait::Unaligned, require_trait_bound_on_field_types, false, None, None)
+}
+
+// This enum describes what kind of padding check needs to be generated for the
+// associated impl.
+enum PaddingCheck {
+ // Check that the sum of the fields' sizes exactly equals the struct's size.
+ Struct,
+ // Check that the size of each field exactly equals the union's size.
+ Union,
+}
+
+impl PaddingCheck {
+ /// Returns the ident of the macro to call in order to validate that a type
+ /// passes the padding check encoded by `PaddingCheck`.
+ fn validator_macro_ident(&self) -> Ident {
+ let s = match self {
+ PaddingCheck::Struct => "struct_has_padding",
+ PaddingCheck::Union => "union_has_padding",
+ };
+
+ Ident::new(s, Span::call_site())
+ }
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum Trait {
+ KnownLayout,
+ FromZeroes,
+ FromBytes,
+ AsBytes,
+ Unaligned,
+}
+
+impl Trait {
+ fn ident(&self) -> Ident {
+ Ident::new(format!("{:?}", self).as_str(), Span::call_site())
+ }
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum RequireBoundedFields {
+ No,
+ Yes,
+ Trailing,
+}
+
+impl From<bool> for RequireBoundedFields {
+ fn from(do_require: bool) -> Self {
+ match do_require {
+ true => Self::Yes,
+ false => Self::No,
+ }
+ }
+}
+
+fn impl_block<D: DataExt>(
+ input: &DeriveInput,
+ data: &D,
+ trt: Trait,
+ require_trait_bound_on_field_types: RequireBoundedFields,
+ require_self_sized: bool,
+ padding_check: Option<PaddingCheck>,
+ extras: Option<proc_macro2::TokenStream>,
+) -> proc_macro2::TokenStream {
+ // In this documentation, we will refer to this hypothetical struct:
+ //
+ // #[derive(FromBytes)]
+ // struct Foo<T, I: Iterator>
+ // where
+ // T: Copy,
+ // I: Clone,
+ // I::Item: Clone,
+ // {
+ // a: u8,
+ // b: T,
+ // c: I::Item,
+ // }
+ //
+ // We extract the field types, which in this case are `u8`, `T`, and
+ // `I::Item`. We re-use the existing parameters and where clauses. If
+ // `require_trait_bound == true` (as it is for `FromBytes), we add where
+ // bounds for each field's type:
+ //
+ // impl<T, I: Iterator> FromBytes for Foo<T, I>
+ // where
+ // T: Copy,
+ // I: Clone,
+ // I::Item: Clone,
+ // T: FromBytes,
+ // I::Item: FromBytes,
+ // {
+ // }
+ //
+ // NOTE: It is standard practice to only emit bounds for the type parameters
+ // themselves, not for field types based on those parameters (e.g., `T` vs
+ // `T::Foo`). For a discussion of why this is standard practice, see
+ // https://github.com/rust-lang/rust/issues/26925.
+ //
+ // The reason we diverge from this standard is that doing it that way for us
+ // would be unsound. E.g., consider a type, `T` where `T: FromBytes` but
+ // `T::Foo: !FromBytes`. It would not be sound for us to accept a type with
+ // a `T::Foo` field as `FromBytes` simply because `T: FromBytes`.
+ //
+ // While there's no getting around this requirement for us, it does have the
+ // pretty serious downside that, when lifetimes are involved, the trait
+ // solver ties itself in knots:
+ //
+ // #[derive(Unaligned)]
+ // #[repr(C)]
+ // struct Dup<'a, 'b> {
+ // a: PhantomData<&'a u8>,
+ // b: PhantomData<&'b u8>,
+ // }
+ //
+ // error[E0283]: type annotations required: cannot resolve `core::marker::PhantomData<&'a u8>: zerocopy::Unaligned`
+ // --> src/main.rs:6:10
+ // |
+ // 6 | #[derive(Unaligned)]
+ // | ^^^^^^^^^
+ // |
+ // = note: required by `zerocopy::Unaligned`
+
+ let type_ident = &input.ident;
+ let trait_ident = trt.ident();
+ let field_types = data.field_types();
+
+ let bound_tt = |ty| parse_quote!(#ty: ::zerocopy::#trait_ident);
+ let field_type_bounds: Vec<_> = match (require_trait_bound_on_field_types, &field_types[..]) {
+ (RequireBoundedFields::Yes, _) => field_types.iter().map(bound_tt).collect(),
+ (RequireBoundedFields::No, _) | (RequireBoundedFields::Trailing, []) => vec![],
+ (RequireBoundedFields::Trailing, [.., last]) => vec![bound_tt(last)],
+ };
+
+ // Don't bother emitting a padding check if there are no fields.
+ #[allow(unstable_name_collisions)] // See `BoolExt` below
+ let padding_check_bound = padding_check.and_then(|check| (!field_types.is_empty()).then_some(check)).map(|check| {
+ let fields = field_types.iter();
+ let validator_macro = check.validator_macro_ident();
+ parse_quote!(
+ ::zerocopy::macro_util::HasPadding<#type_ident, {::zerocopy::#validator_macro!(#type_ident, #(#fields),*)}>:
+ ::zerocopy::macro_util::ShouldBe<false>
+ )
+ });
+
+ let self_sized_bound = if require_self_sized { Some(parse_quote!(Self: Sized)) } else { None };
+
+ let bounds = input
+ .generics
+ .where_clause
+ .as_ref()
+ .map(|where_clause| where_clause.predicates.iter())
+ .into_iter()
+ .flatten()
+ .chain(field_type_bounds.iter())
+ .chain(padding_check_bound.iter())
+ .chain(self_sized_bound.iter());
+
+ // The parameters with trait bounds, but without type defaults.
+ let params = input.generics.params.clone().into_iter().map(|mut param| {
+ match &mut param {
+ GenericParam::Type(ty) => ty.default = None,
+ GenericParam::Const(cnst) => cnst.default = None,
+ GenericParam::Lifetime(_) => {}
+ }
+ quote!(#param)
+ });
+
+ // The identifiers of the parameters without trait bounds or type defaults.
+ let param_idents = input.generics.params.iter().map(|param| match param {
+ GenericParam::Type(ty) => {
+ let ident = &ty.ident;
+ quote!(#ident)
+ }
+ GenericParam::Lifetime(l) => {
+ let ident = &l.lifetime;
+ quote!(#ident)
+ }
+ GenericParam::Const(cnst) => {
+ let ident = &cnst.ident;
+ quote!({#ident})
+ }
+ });
+
+ quote! {
+ // TODO(#553): Add a test that generates a warning when
+ // `#[allow(deprecated)]` isn't present.
+ #[allow(deprecated)]
+ unsafe impl < #(#params),* > ::zerocopy::#trait_ident for #type_ident < #(#param_idents),* >
+ where
+ #(#bounds,)*
+ {
+ fn only_derive_is_allowed_to_implement_this_trait() {}
+
+ #extras
+ }
+ }
+}
+
+fn print_all_errors(errors: Vec<Error>) -> proc_macro2::TokenStream {
+ errors.iter().map(Error::to_compile_error).collect()
+}
+
+// A polyfill for `Option::then_some`, which was added after our MSRV.
+//
+// TODO(#67): Remove this once our MSRV is >= 1.62.
+trait BoolExt {
+ fn then_some<T>(self, t: T) -> Option<T>;
+}
+
+impl BoolExt for bool {
+ fn then_some<T>(self, t: T) -> Option<T> {
+ if self {
+ Some(t)
+ } else {
+ None
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_config_repr_orderings() {
+ // Validate that the repr lists in the various configs are in the
+ // canonical order. If they aren't, then our algorithm to look up in
+ // those lists won't work.
+
+ // TODO(https://github.com/rust-lang/rust/issues/53485): Remove once
+ // `Vec::is_sorted` is stabilized.
+ fn is_sorted_and_deduped<T: Clone + Ord>(ts: &[T]) -> bool {
+ let mut sorted = ts.to_vec();
+ sorted.sort();
+ sorted.dedup();
+ ts == sorted.as_slice()
+ }
+
+ fn elements_are_sorted_and_deduped<T: Clone + Ord>(lists: &[&[T]]) -> bool {
+ lists.iter().all(|list| is_sorted_and_deduped(list))
+ }
+
+ fn config_is_sorted<T: KindRepr + Clone>(config: &Config<T>) -> bool {
+ elements_are_sorted_and_deduped(config.allowed_combinations)
+ && elements_are_sorted_and_deduped(config.disallowed_but_legal_combinations)
+ }
+
+ assert!(config_is_sorted(&STRUCT_UNION_UNALIGNED_CFG));
+ assert!(config_is_sorted(&ENUM_FROM_BYTES_CFG));
+ assert!(config_is_sorted(&ENUM_UNALIGNED_CFG));
+ }
+
+ #[test]
+ fn test_config_repr_no_overlap() {
+ // Validate that no set of reprs appears in both the
+ // `allowed_combinations` and `disallowed_but_legal_combinations` lists.
+
+ fn overlap<T: Eq>(a: &[T], b: &[T]) -> bool {
+ a.iter().any(|elem| b.contains(elem))
+ }
+
+ fn config_overlaps<T: KindRepr + Eq>(config: &Config<T>) -> bool {
+ overlap(config.allowed_combinations, config.disallowed_but_legal_combinations)
+ }
+
+ assert!(!config_overlaps(&STRUCT_UNION_UNALIGNED_CFG));
+ assert!(!config_overlaps(&ENUM_FROM_BYTES_CFG));
+ assert!(!config_overlaps(&ENUM_UNALIGNED_CFG));
+ }
+}
diff --git a/third_party/rust/zerocopy-derive/src/repr.rs b/third_party/rust/zerocopy-derive/src/repr.rs
new file mode 100644
index 0000000000..f4f2788685
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/src/repr.rs
@@ -0,0 +1,311 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+use core::fmt::{self, Display, Formatter};
+
+use {
+ proc_macro2::Span,
+ syn::punctuated::Punctuated,
+ syn::spanned::Spanned,
+ syn::token::Comma,
+ syn::{Attribute, DeriveInput, Error, LitInt, Meta},
+};
+
+pub struct Config<Repr: KindRepr> {
+ // A human-readable message describing what combinations of representations
+ // are allowed. This will be printed to the user if they use an invalid
+ // combination.
+ pub allowed_combinations_message: &'static str,
+ // Whether we're checking as part of `derive(Unaligned)`. If not, we can
+ // ignore `repr(align)`, which makes the code (and the list of valid repr
+ // combinations we have to enumerate) somewhat simpler. If we're checking
+ // for `Unaligned`, then in addition to checking against illegal
+ // combinations, we also check to see if there exists a `repr(align(N > 1))`
+ // attribute.
+ pub derive_unaligned: bool,
+ // Combinations which are valid for the trait.
+ pub allowed_combinations: &'static [&'static [Repr]],
+ // Combinations which are not valid for the trait, but are legal according
+ // to Rust. Any combination not in this or `allowed_combinations` is either
+ // illegal according to Rust or the behavior is unspecified. If the behavior
+ // is unspecified, it might become specified in the future, and that
+ // specification might not play nicely with our requirements. Thus, we
+ // reject combinations with unspecified behavior in addition to illegal
+ // combinations.
+ pub disallowed_but_legal_combinations: &'static [&'static [Repr]],
+}
+
+impl<R: KindRepr> Config<R> {
+ /// Validate that `input`'s representation attributes conform to the
+ /// requirements specified by this `Config`.
+ ///
+ /// `validate_reprs` extracts the `repr` attributes, validates that they
+ /// conform to the requirements of `self`, and returns them. Regardless of
+ /// whether `align` attributes are considered during validation, they are
+ /// stripped out of the returned value since no callers care about them.
+ pub fn validate_reprs(&self, input: &DeriveInput) -> Result<Vec<R>, Vec<Error>> {
+ let mut metas_reprs = reprs(&input.attrs)?;
+ metas_reprs.sort_by(|a: &(_, R), b| a.1.partial_cmp(&b.1).unwrap());
+
+ if self.derive_unaligned {
+ if let Some((meta, _)) =
+ metas_reprs.iter().find(|&repr: &&(_, R)| repr.1.is_align_gt_one())
+ {
+ return Err(vec![Error::new_spanned(
+ meta,
+ "cannot derive Unaligned with repr(align(N > 1))",
+ )]);
+ }
+ }
+
+ let mut metas = Vec::new();
+ let mut reprs = Vec::new();
+ metas_reprs.into_iter().filter(|(_, repr)| !repr.is_align()).for_each(|(meta, repr)| {
+ metas.push(meta);
+ reprs.push(repr)
+ });
+
+ if reprs.is_empty() {
+ // Use `Span::call_site` to report this error on the
+ // `#[derive(...)]` itself.
+ return Err(vec![Error::new(Span::call_site(), "must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout")]);
+ }
+
+ let initial_sp = metas[0].span();
+ let err_span = metas.iter().skip(1).try_fold(initial_sp, |sp, meta| sp.join(meta.span()));
+
+ if self.allowed_combinations.contains(&reprs.as_slice()) {
+ Ok(reprs)
+ } else if self.disallowed_but_legal_combinations.contains(&reprs.as_slice()) {
+ Err(vec![Error::new(
+ err_span.unwrap_or_else(|| input.span()),
+ self.allowed_combinations_message,
+ )])
+ } else {
+ Err(vec![Error::new(
+ err_span.unwrap_or_else(|| input.span()),
+ "conflicting representation hints",
+ )])
+ }
+ }
+}
+
+// The type of valid reprs for a particular kind (enum, struct, union).
+pub trait KindRepr: 'static + Sized + Ord {
+ fn is_align(&self) -> bool;
+ fn is_align_gt_one(&self) -> bool;
+ fn parse(meta: &Meta) -> syn::Result<Self>;
+}
+
+// Defines an enum for reprs which are valid for a given kind (structs, enums,
+// etc), and provide implementations of `KindRepr`, `Ord`, and `Display`, and
+// those traits' super-traits.
+macro_rules! define_kind_specific_repr {
+ ($type_name:expr, $repr_name:ident, [ $($repr_variant:ident),* ] , [ $($repr_variant_aligned:ident),* ]) => {
+ #[derive(Copy, Clone, Debug, Eq, PartialEq)]
+ pub enum $repr_name {
+ $($repr_variant,)*
+ $($repr_variant_aligned(u64),)*
+ }
+
+ impl KindRepr for $repr_name {
+ fn is_align(&self) -> bool {
+ match self {
+ $($repr_name::$repr_variant_aligned(_) => true,)*
+ _ => false,
+ }
+ }
+
+ fn is_align_gt_one(&self) -> bool {
+ match self {
+ // `packed(n)` only lowers alignment
+ $repr_name::Align(n) => n > &1,
+ _ => false,
+ }
+ }
+
+ fn parse(meta: &Meta) -> syn::Result<$repr_name> {
+ match Repr::from_meta(meta)? {
+ $(Repr::$repr_variant => Ok($repr_name::$repr_variant),)*
+ $(Repr::$repr_variant_aligned(u) => Ok($repr_name::$repr_variant_aligned(u)),)*
+ _ => Err(Error::new_spanned(meta, concat!("unsupported representation for deriving FromBytes, AsBytes, or Unaligned on ", $type_name)))
+ }
+ }
+ }
+
+ // Define a stable ordering so we can canonicalize lists of reprs. The
+ // ordering itself doesn't matter so long as it's stable.
+ impl PartialOrd for $repr_name {
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+ }
+
+ impl Ord for $repr_name {
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ format!("{:?}", self).cmp(&format!("{:?}", other))
+ }
+ }
+
+ impl core::fmt::Display for $repr_name {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ $($repr_name::$repr_variant => Repr::$repr_variant,)*
+ $($repr_name::$repr_variant_aligned(u) => Repr::$repr_variant_aligned(*u),)*
+ }.fmt(f)
+ }
+ }
+ }
+}
+
+define_kind_specific_repr!("a struct", StructRepr, [C, Transparent, Packed], [Align, PackedN]);
+define_kind_specific_repr!(
+ "an enum",
+ EnumRepr,
+ [C, U8, U16, U32, U64, Usize, I8, I16, I32, I64, Isize],
+ [Align]
+);
+
+// All representations known to Rust.
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub enum Repr {
+ U8,
+ U16,
+ U32,
+ U64,
+ Usize,
+ I8,
+ I16,
+ I32,
+ I64,
+ Isize,
+ C,
+ Transparent,
+ Packed,
+ PackedN(u64),
+ Align(u64),
+}
+
+impl Repr {
+ fn from_meta(meta: &Meta) -> Result<Repr, Error> {
+ let (path, list) = match meta {
+ Meta::Path(path) => (path, None),
+ Meta::List(list) => (&list.path, Some(list)),
+ _ => return Err(Error::new_spanned(meta, "unrecognized representation hint")),
+ };
+
+ let ident = path
+ .get_ident()
+ .ok_or_else(|| Error::new_spanned(meta, "unrecognized representation hint"))?;
+
+ Ok(match (ident.to_string().as_str(), list) {
+ ("u8", None) => Repr::U8,
+ ("u16", None) => Repr::U16,
+ ("u32", None) => Repr::U32,
+ ("u64", None) => Repr::U64,
+ ("usize", None) => Repr::Usize,
+ ("i8", None) => Repr::I8,
+ ("i16", None) => Repr::I16,
+ ("i32", None) => Repr::I32,
+ ("i64", None) => Repr::I64,
+ ("isize", None) => Repr::Isize,
+ ("C", None) => Repr::C,
+ ("transparent", None) => Repr::Transparent,
+ ("packed", None) => Repr::Packed,
+ ("packed", Some(list)) => {
+ Repr::PackedN(list.parse_args::<LitInt>()?.base10_parse::<u64>()?)
+ }
+ ("align", Some(list)) => {
+ Repr::Align(list.parse_args::<LitInt>()?.base10_parse::<u64>()?)
+ }
+ _ => return Err(Error::new_spanned(meta, "unrecognized representation hint")),
+ })
+ }
+}
+
+impl KindRepr for Repr {
+ fn is_align(&self) -> bool {
+ false
+ }
+
+ fn is_align_gt_one(&self) -> bool {
+ false
+ }
+
+ fn parse(meta: &Meta) -> syn::Result<Self> {
+ Self::from_meta(meta)
+ }
+}
+
+impl Display for Repr {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
+ if let Repr::Align(n) = self {
+ return write!(f, "repr(align({}))", n);
+ }
+ if let Repr::PackedN(n) = self {
+ return write!(f, "repr(packed({}))", n);
+ }
+ write!(
+ f,
+ "repr({})",
+ match self {
+ Repr::U8 => "u8",
+ Repr::U16 => "u16",
+ Repr::U32 => "u32",
+ Repr::U64 => "u64",
+ Repr::Usize => "usize",
+ Repr::I8 => "i8",
+ Repr::I16 => "i16",
+ Repr::I32 => "i32",
+ Repr::I64 => "i64",
+ Repr::Isize => "isize",
+ Repr::C => "C",
+ Repr::Transparent => "transparent",
+ Repr::Packed => "packed",
+ _ => unreachable!(),
+ }
+ )
+ }
+}
+
+pub(crate) fn reprs<R: KindRepr>(attrs: &[Attribute]) -> Result<Vec<(Meta, R)>, Vec<Error>> {
+ let mut reprs = Vec::new();
+ let mut errors = Vec::new();
+ for attr in attrs {
+ // Ignore documentation attributes.
+ if attr.path().is_ident("doc") {
+ continue;
+ }
+ if let Meta::List(ref meta_list) = attr.meta {
+ if meta_list.path.is_ident("repr") {
+ let parsed: Punctuated<Meta, Comma> =
+ match meta_list.parse_args_with(Punctuated::parse_terminated) {
+ Ok(parsed) => parsed,
+ Err(_) => {
+ errors.push(Error::new_spanned(
+ &meta_list.tokens,
+ "unrecognized representation hint",
+ ));
+ continue;
+ }
+ };
+ for meta in parsed {
+ match R::parse(&meta) {
+ Ok(repr) => reprs.push((meta, repr)),
+ Err(err) => errors.push(err),
+ }
+ }
+ }
+ }
+ }
+
+ if !errors.is_empty() {
+ return Err(errors);
+ }
+ Ok(reprs)
+}
diff --git a/third_party/rust/zerocopy-derive/tests/enum_as_bytes.rs b/third_party/rust/zerocopy-derive/tests/enum_as_bytes.rs
new file mode 100644
index 0000000000..e305bc4cea
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/enum_as_bytes.rs
@@ -0,0 +1,101 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+use {static_assertions::assert_impl_all, zerocopy::AsBytes};
+
+// An enum is `AsBytes` if if has a defined repr.
+
+#[derive(AsBytes)]
+#[repr(C)]
+enum C {
+ A,
+}
+
+assert_impl_all!(C: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(u8)]
+enum U8 {
+ A,
+}
+
+assert_impl_all!(U8: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(u16)]
+enum U16 {
+ A,
+}
+
+assert_impl_all!(U16: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(u32)]
+enum U32 {
+ A,
+}
+
+assert_impl_all!(U32: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(u64)]
+enum U64 {
+ A,
+}
+
+assert_impl_all!(U64: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(usize)]
+enum Usize {
+ A,
+}
+
+assert_impl_all!(Usize: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(i8)]
+enum I8 {
+ A,
+}
+
+assert_impl_all!(I8: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(i16)]
+enum I16 {
+ A,
+}
+
+assert_impl_all!(I16: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(i32)]
+enum I32 {
+ A,
+}
+
+assert_impl_all!(I32: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(i64)]
+enum I64 {
+ A,
+}
+
+assert_impl_all!(I64: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(isize)]
+enum Isize {
+ A,
+}
+
+assert_impl_all!(Isize: AsBytes);
diff --git a/third_party/rust/zerocopy-derive/tests/enum_from_zeroes.rs b/third_party/rust/zerocopy-derive/tests/enum_from_zeroes.rs
new file mode 100644
index 0000000000..c6bb675f52
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/enum_from_zeroes.rs
@@ -0,0 +1,35 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+mod util;
+
+use {static_assertions::assert_impl_all, zerocopy::FromZeroes};
+
+#[derive(FromZeroes)]
+enum Foo {
+ A,
+}
+
+assert_impl_all!(Foo: FromZeroes);
+
+#[derive(FromZeroes)]
+enum Bar {
+ A = 0,
+}
+
+assert_impl_all!(Bar: FromZeroes);
+
+#[derive(FromZeroes)]
+enum Baz {
+ A = 1,
+ B = 0,
+}
+
+assert_impl_all!(Baz: FromZeroes);
diff --git a/third_party/rust/zerocopy-derive/tests/enum_known_layout.rs b/third_party/rust/zerocopy-derive/tests/enum_known_layout.rs
new file mode 100644
index 0000000000..49a6765e53
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/enum_known_layout.rs
@@ -0,0 +1,46 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![allow(warnings)]
+
+mod util;
+
+use {core::marker::PhantomData, static_assertions::assert_impl_all, zerocopy::KnownLayout};
+
+#[derive(KnownLayout)]
+enum Foo {
+ A,
+}
+
+assert_impl_all!(Foo: KnownLayout);
+
+#[derive(KnownLayout)]
+enum Bar {
+ A = 0,
+}
+
+assert_impl_all!(Bar: KnownLayout);
+
+#[derive(KnownLayout)]
+enum Baz {
+ A = 1,
+ B = 0,
+}
+
+assert_impl_all!(Baz: KnownLayout);
+
+// Deriving `KnownLayout` should work if the enum has bounded parameters.
+
+#[derive(KnownLayout)]
+#[repr(C)]
+enum WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + KnownLayout>
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + KnownLayout,
+{
+ Variant([T; N], PhantomData<&'a &'b ()>),
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: KnownLayout);
diff --git a/third_party/rust/zerocopy-derive/tests/enum_unaligned.rs b/third_party/rust/zerocopy-derive/tests/enum_unaligned.rs
new file mode 100644
index 0000000000..152ce276b8
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/enum_unaligned.rs
@@ -0,0 +1,47 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+use {static_assertions::assert_impl_all, zerocopy::Unaligned};
+
+// An enum is `Unaligned` if:
+// - No `repr(align(N > 1))`
+// - `repr(u8)` or `repr(i8)`
+
+#[derive(Unaligned)]
+#[repr(u8)]
+enum Foo {
+ A,
+}
+
+assert_impl_all!(Foo: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(i8)]
+enum Bar {
+ A,
+}
+
+assert_impl_all!(Bar: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(u8, align(1))]
+enum Baz {
+ A,
+}
+
+assert_impl_all!(Baz: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(i8, align(1))]
+enum Blah {
+ B,
+}
+
+assert_impl_all!(Blah: Unaligned);
diff --git a/third_party/rust/zerocopy-derive/tests/hygiene.rs b/third_party/rust/zerocopy-derive/tests/hygiene.rs
new file mode 100644
index 0000000000..b7b838d6c3
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/hygiene.rs
@@ -0,0 +1,43 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+// Make sure that macro hygiene will ensure that when we reference "zerocopy",
+// that will work properly even if they've renamed the crate and have not
+// imported its traits.
+
+#![allow(warnings)]
+
+extern crate zerocopy as _zerocopy;
+
+#[macro_use]
+mod util;
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use static_assertions::assert_impl_all;
+
+#[derive(
+ _zerocopy::KnownLayout, _zerocopy::FromZeroes, _zerocopy::FromBytes, _zerocopy::Unaligned,
+)]
+#[repr(C)]
+struct TypeParams<'a, T, I: Iterator> {
+ a: T,
+ c: I::Item,
+ d: u8,
+ e: PhantomData<&'a [u8]>,
+ f: PhantomData<&'static str>,
+ g: PhantomData<String>,
+}
+
+assert_impl_all!(
+ TypeParams<'static, (), IntoIter<()>>:
+ _zerocopy::KnownLayout,
+ _zerocopy::FromZeroes,
+ _zerocopy::FromBytes,
+ _zerocopy::Unaligned
+);
diff --git a/third_party/rust/zerocopy-derive/tests/paths_and_modules.rs b/third_party/rust/zerocopy-derive/tests/paths_and_modules.rs
new file mode 100644
index 0000000000..a01983b097
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/paths_and_modules.rs
@@ -0,0 +1,38 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned};
+
+// Ensure that types that are use'd and types that are referenced by path work.
+
+mod foo {
+ use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned};
+
+ #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ #[repr(C)]
+ pub struct Foo {
+ foo: u8,
+ }
+
+ #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ #[repr(C)]
+ pub struct Bar {
+ bar: u8,
+ }
+}
+
+use foo::Foo;
+
+#[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+#[repr(C)]
+struct Baz {
+ foo: Foo,
+ bar: foo::Bar,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/priv_in_pub.rs b/third_party/rust/zerocopy-derive/tests/priv_in_pub.rs
new file mode 100644
index 0000000000..5f7d8749d3
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/priv_in_pub.rs
@@ -0,0 +1,24 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+use zerocopy::{AsBytes, FromBytes, FromZeroes, KnownLayout, Unaligned};
+
+// These derives do not result in E0446 as of Rust 1.59.0, because of
+// https://github.com/rust-lang/rust/pull/90586.
+//
+// This change eliminates one of the major downsides of emitting `where`
+// bounds for field types (i.e., the emission of E0446 for private field
+// types).
+
+#[derive(KnownLayout, AsBytes, FromZeroes, FromBytes, Unaligned)]
+#[repr(C)]
+pub struct Public(Private);
+
+#[derive(KnownLayout, AsBytes, FromZeroes, FromBytes, Unaligned)]
+#[repr(C)]
+struct Private(());
diff --git a/third_party/rust/zerocopy-derive/tests/struct_as_bytes.rs b/third_party/rust/zerocopy-derive/tests/struct_as_bytes.rs
new file mode 100644
index 0000000000..3c71bf07b5
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/struct_as_bytes.rs
@@ -0,0 +1,161 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+mod util;
+
+use std::{marker::PhantomData, mem::ManuallyDrop, option::IntoIter};
+
+use {static_assertions::assert_impl_all, zerocopy::AsBytes};
+
+use self::util::AU16;
+
+// A struct is `AsBytes` if:
+// - all fields are `AsBytes`
+// - `repr(C)` or `repr(transparent)` and
+// - no padding (size of struct equals sum of size of field types)
+// - `repr(packed)`
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct CZst;
+
+assert_impl_all!(CZst: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct C {
+ a: u8,
+ b: u8,
+ c: AU16,
+}
+
+assert_impl_all!(C: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(transparent)]
+struct Transparent {
+ a: u8,
+ b: CZst,
+}
+
+assert_impl_all!(Transparent: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(transparent)]
+struct TransparentGeneric<T: ?Sized> {
+ a: CZst,
+ b: T,
+}
+
+assert_impl_all!(TransparentGeneric<u64>: AsBytes);
+assert_impl_all!(TransparentGeneric<[u64]>: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C, packed)]
+struct CZstPacked;
+
+assert_impl_all!(CZstPacked: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C, packed)]
+struct CPacked {
+ a: u8,
+ // NOTE: The `u16` type is not guaranteed to have alignment 2, although it
+ // does on many platforms. However, to fix this would require a custom type
+ // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not
+ // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
+ // have no choice but to use `u16` here. Luckily, these tests run in CI on
+ // platforms on which `u16` has alignment 2, so this isn't that big of a
+ // deal.
+ b: u16,
+}
+
+assert_impl_all!(CPacked: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C, packed(2))]
+// The same caveats as for CPacked apply - we're assuming u64 is at least
+// 4-byte aligned by default. Without packed(2), this should fail, as there
+// would be padding between a/b assuming u64 is 4+ byte aligned.
+struct CPacked2 {
+ a: u16,
+ b: u64,
+}
+
+assert_impl_all!(CPacked2: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C, packed)]
+struct CPackedGeneric<T, U: ?Sized> {
+ t: T,
+ // Unsized types stored in `repr(packed)` structs must not be dropped
+ // because dropping them in-place might be unsound depending on the
+ // alignment of the outer struct. Sized types can be dropped by first being
+ // moved to an aligned stack variable, but this isn't possible with unsized
+ // types.
+ u: ManuallyDrop<U>,
+}
+
+assert_impl_all!(CPackedGeneric<u8, AU16>: AsBytes);
+assert_impl_all!(CPackedGeneric<u8, [AU16]>: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(packed)]
+struct Packed {
+ a: u8,
+ // NOTE: The `u16` type is not guaranteed to have alignment 2, although it
+ // does on many platforms. However, to fix this would require a custom type
+ // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not
+ // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
+ // have no choice but to use `u16` here. Luckily, these tests run in CI on
+ // platforms on which `u16` has alignment 2, so this isn't that big of a
+ // deal.
+ b: u16,
+}
+
+assert_impl_all!(Packed: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(packed)]
+struct PackedGeneric<T, U: ?Sized> {
+ t: T,
+ // Unsized types stored in `repr(packed)` structs must not be dropped
+ // because dropping them in-place might be unsound depending on the
+ // alignment of the outer struct. Sized types can be dropped by first being
+ // moved to an aligned stack variable, but this isn't possible with unsized
+ // types.
+ u: ManuallyDrop<U>,
+}
+
+assert_impl_all!(PackedGeneric<u8, AU16>: AsBytes);
+assert_impl_all!(PackedGeneric<u8, [AU16]>: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(transparent)]
+struct Unsized {
+ a: [u8],
+}
+
+assert_impl_all!(Unsized: AsBytes);
+
+// Deriving `AsBytes` should work if the struct has bounded parameters.
+
+#[derive(AsBytes)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + AsBytes>(
+ [T; N],
+ PhantomData<&'a &'b ()>,
+)
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + AsBytes;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: AsBytes);
diff --git a/third_party/rust/zerocopy-derive/tests/struct_from_bytes.rs b/third_party/rust/zerocopy-derive/tests/struct_from_bytes.rs
new file mode 100644
index 0000000000..98f03d1640
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/struct_from_bytes.rs
@@ -0,0 +1,79 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+mod util;
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {
+ static_assertions::assert_impl_all,
+ zerocopy::{FromBytes, FromZeroes},
+};
+
+use crate::util::AU16;
+
+// A struct is `FromBytes` if:
+// - all fields are `FromBytes`
+
+#[derive(FromZeroes, FromBytes)]
+struct Zst;
+
+assert_impl_all!(Zst: FromBytes);
+
+#[derive(FromZeroes, FromBytes)]
+struct One {
+ a: u8,
+}
+
+assert_impl_all!(One: FromBytes);
+
+#[derive(FromZeroes, FromBytes)]
+struct Two {
+ a: u8,
+ b: Zst,
+}
+
+assert_impl_all!(Two: FromBytes);
+
+#[derive(FromZeroes, FromBytes)]
+struct Unsized {
+ a: [u8],
+}
+
+assert_impl_all!(Unsized: FromBytes);
+
+#[derive(FromZeroes, FromBytes)]
+struct TypeParams<'a, T: ?Sized, I: Iterator> {
+ a: I::Item,
+ b: u8,
+ c: PhantomData<&'a [u8]>,
+ d: PhantomData<&'static str>,
+ e: PhantomData<String>,
+ f: T,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromBytes);
+assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: FromBytes);
+assert_impl_all!(TypeParams<'static, [AU16], IntoIter<()>>: FromBytes);
+
+// Deriving `FromBytes` should work if the struct has bounded parameters.
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromBytes>(
+ [T; N],
+ PhantomData<&'a &'b ()>,
+)
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + FromBytes;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromBytes);
diff --git a/third_party/rust/zerocopy-derive/tests/struct_from_zeroes.rs b/third_party/rust/zerocopy-derive/tests/struct_from_zeroes.rs
new file mode 100644
index 0000000000..75d824594b
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/struct_from_zeroes.rs
@@ -0,0 +1,77 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+#[macro_use]
+mod util;
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {static_assertions::assert_impl_all, zerocopy::FromZeroes};
+
+use crate::util::AU16;
+
+// A struct is `FromZeroes` if:
+// - all fields are `FromZeroes`
+
+#[derive(FromZeroes)]
+struct Zst;
+
+assert_impl_all!(Zst: FromZeroes);
+
+#[derive(FromZeroes)]
+struct One {
+ a: bool,
+}
+
+assert_impl_all!(One: FromZeroes);
+
+#[derive(FromZeroes)]
+struct Two {
+ a: bool,
+ b: Zst,
+}
+
+assert_impl_all!(Two: FromZeroes);
+
+#[derive(FromZeroes)]
+struct Unsized {
+ a: [u8],
+}
+
+assert_impl_all!(Unsized: FromZeroes);
+
+#[derive(FromZeroes)]
+struct TypeParams<'a, T: ?Sized, I: Iterator> {
+ a: I::Item,
+ b: u8,
+ c: PhantomData<&'a [u8]>,
+ d: PhantomData<&'static str>,
+ e: PhantomData<String>,
+ f: T,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes);
+assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: FromZeroes);
+assert_impl_all!(TypeParams<'static, [AU16], IntoIter<()>>: FromZeroes);
+
+// Deriving `FromZeroes` should work if the struct has bounded parameters.
+
+#[derive(FromZeroes)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromZeroes>(
+ [T; N],
+ PhantomData<&'a &'b ()>,
+)
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + FromZeroes;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromZeroes);
diff --git a/third_party/rust/zerocopy-derive/tests/struct_known_layout.rs b/third_party/rust/zerocopy-derive/tests/struct_known_layout.rs
new file mode 100644
index 0000000000..68d1284de9
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/struct_known_layout.rs
@@ -0,0 +1,65 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![allow(warnings)]
+
+#[macro_use]
+mod util;
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {
+ static_assertions::assert_impl_all,
+ zerocopy::{DstLayout, KnownLayout},
+};
+
+use crate::util::AU16;
+
+#[derive(KnownLayout)]
+struct Zst;
+
+assert_impl_all!(Zst: KnownLayout);
+
+#[derive(KnownLayout)]
+struct One {
+ a: bool,
+}
+
+assert_impl_all!(One: KnownLayout);
+
+#[derive(KnownLayout)]
+struct Two {
+ a: bool,
+ b: Zst,
+}
+
+assert_impl_all!(Two: KnownLayout);
+
+#[derive(KnownLayout)]
+struct TypeParams<'a, T, I: Iterator> {
+ a: I::Item,
+ b: u8,
+ c: PhantomData<&'a [u8]>,
+ d: PhantomData<&'static str>,
+ e: PhantomData<String>,
+ f: T,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: KnownLayout);
+assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: KnownLayout);
+
+// Deriving `KnownLayout` should work if the struct has bounded parameters.
+
+#[derive(KnownLayout)]
+#[repr(C)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + KnownLayout>(
+ [T; N],
+ PhantomData<&'a &'b ()>,
+)
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + KnownLayout;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: KnownLayout);
diff --git a/third_party/rust/zerocopy-derive/tests/struct_unaligned.rs b/third_party/rust/zerocopy-derive/tests/struct_unaligned.rs
new file mode 100644
index 0000000000..a7db4322a6
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/struct_unaligned.rs
@@ -0,0 +1,100 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+mod util;
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {static_assertions::assert_impl_all, zerocopy::Unaligned};
+
+use crate::util::AU16;
+
+// A struct is `Unaligned` if:
+// - `repr(align)` is no more than 1 and either
+// - `repr(C)` or `repr(transparent)` and
+// - all fields Unaligned
+// - `repr(packed)`
+
+#[derive(Unaligned)]
+#[repr(C)]
+struct Foo {
+ a: u8,
+}
+
+assert_impl_all!(Foo: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(transparent)]
+struct Bar {
+ a: u8,
+}
+
+assert_impl_all!(Bar: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(packed)]
+struct Baz {
+ // NOTE: The `u16` type is not guaranteed to have alignment 2, although it
+ // does on many platforms. However, to fix this would require a custom type
+ // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not
+ // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
+ // have no choice but to use `u16` here. Luckily, these tests run in CI on
+ // platforms on which `u16` has alignment 2, so this isn't that big of a
+ // deal.
+ a: u16,
+}
+
+assert_impl_all!(Baz: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(C, align(1))]
+struct FooAlign {
+ a: u8,
+}
+
+assert_impl_all!(FooAlign: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(transparent)]
+struct Unsized {
+ a: [u8],
+}
+
+assert_impl_all!(Unsized: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(C)]
+struct TypeParams<'a, T: ?Sized, I: Iterator> {
+ a: I::Item,
+ b: u8,
+ c: PhantomData<&'a [u8]>,
+ d: PhantomData<&'static str>,
+ e: PhantomData<String>,
+ f: T,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: Unaligned);
+assert_impl_all!(TypeParams<'static, u8, IntoIter<()>>: Unaligned);
+assert_impl_all!(TypeParams<'static, [u8], IntoIter<()>>: Unaligned);
+
+// Deriving `Unaligned` should work if the struct has bounded parameters.
+
+#[derive(Unaligned)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + Unaligned>(
+ [T; N],
+ PhantomData<&'a &'b ()>,
+)
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + Unaligned;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: Unaligned);
diff --git a/third_party/rust/zerocopy-derive/tests/trybuild.rs b/third_party/rust/zerocopy-derive/tests/trybuild.rs
new file mode 100644
index 0000000000..3ea1c3bfb8
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/trybuild.rs
@@ -0,0 +1,19 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[test]
+#[cfg_attr(miri, ignore)]
+fn ui() {
+ let version = testutil::ToolchainVersion::extract_from_pwd().unwrap();
+ // See the doc comment on this method for an explanation of what this does
+ // and why we store source files in different directories.
+ let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning();
+
+ let t = trybuild::TestCases::new();
+ t.compile_fail(format!("tests/{source_files_dirname}/*.rs"));
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.rs b/third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.rs
new file mode 100644
index 0000000000..2084d921bf
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.rs
@@ -0,0 +1,40 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use core::marker::PhantomData;
+
+use {
+ static_assertions::assert_impl_all,
+ zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned},
+};
+
+use self::util::NotZerocopy;
+
+fn main() {}
+
+// Test generic transparent structs
+
+#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+#[repr(transparent)]
+struct TransparentStruct<T> {
+ inner: T,
+ _phantom: PhantomData<()>,
+}
+
+// It should be legal to derive these traits on a transparent struct, but it
+// must also ensure the traits are only implemented when the inner type
+// implements them.
+assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr b/third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr
new file mode 100644
index 0000000000..3b228b1551
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr
@@ -0,0 +1,71 @@
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+ --> tests/ui-msrv/derive_transparent.rs:37:1
+ |
+37 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy`
+ |
+note: required because of the requirements on the impl of `FromZeroes` for `TransparentStruct<NotZerocopy>`
+ --> tests/ui-msrv/derive_transparent.rs:27:19
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^^
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-msrv/derive_transparent.rs:37:1
+ |
+37 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all`
+ = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-msrv/derive_transparent.rs:38:1
+ |
+38 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+note: required because of the requirements on the impl of `FromBytes` for `TransparentStruct<NotZerocopy>`
+ --> tests/ui-msrv/derive_transparent.rs:27:31
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-msrv/derive_transparent.rs:38:1
+ |
+38 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all`
+ = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied
+ --> tests/ui-msrv/derive_transparent.rs:39:1
+ |
+39 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy`
+ |
+note: required because of the requirements on the impl of `AsBytes` for `TransparentStruct<NotZerocopy>`
+ --> tests/ui-msrv/derive_transparent.rs:27:10
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-msrv/derive_transparent.rs:39:1
+ |
+39 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all`
+ = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied
+ --> tests/ui-msrv/derive_transparent.rs:40:1
+ |
+40 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy`
+ |
+note: required because of the requirements on the impl of `Unaligned` for `TransparentStruct<NotZerocopy>`
+ --> tests/ui-msrv/derive_transparent.rs:27:42
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-msrv/derive_transparent.rs:40:1
+ |
+40 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all`
+ = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/enum.rs b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum.rs
new file mode 100644
index 0000000000..31d5679d19
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum.rs
@@ -0,0 +1,194 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+//
+// Generic errors
+//
+
+#[derive(FromZeroes, FromBytes)]
+#[repr("foo")]
+enum Generic1 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(foo)]
+enum Generic2 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(transparent)]
+enum Generic3 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u8, u16)]
+enum Generic4 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+enum Generic5 {
+ A,
+}
+
+//
+// FromZeroes errors
+//
+
+#[derive(FromZeroes)]
+enum FromZeroes1 {
+ A(u8),
+}
+
+#[derive(FromZeroes)]
+enum FromZeroes2 {
+ A,
+ B(u8),
+}
+
+#[derive(FromZeroes)]
+enum FromZeroes3 {
+ A = 1,
+ B,
+}
+
+//
+// FromBytes errors
+//
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(C)]
+enum FromBytes1 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(usize)]
+enum FromBytes2 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(isize)]
+enum FromBytes3 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u32)]
+enum FromBytes4 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(i32)]
+enum FromBytes5 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u64)]
+enum FromBytes6 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(i64)]
+enum FromBytes7 {
+ A,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C)]
+enum Unaligned1 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u16)]
+enum Unaligned2 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i16)]
+enum Unaligned3 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u32)]
+enum Unaligned4 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i32)]
+enum Unaligned5 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u64)]
+enum Unaligned6 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i64)]
+enum Unaligned7 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(usize)]
+enum Unaligned8 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(isize)]
+enum Unaligned9 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u8, align(2))]
+enum Unaligned10 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i8, align(2))]
+enum Unaligned11 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+enum Unaligned12 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+enum Unaligned13 {
+ A,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/enum.stderr b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum.stderr
new file mode 100644
index 0000000000..39bde3f9e3
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum.stderr
@@ -0,0 +1,199 @@
+error: unrecognized representation hint
+ --> tests/ui-msrv/enum.rs:19:8
+ |
+19 | #[repr("foo")]
+ | ^^^^^
+
+error: unrecognized representation hint
+ --> tests/ui-msrv/enum.rs:25:8
+ |
+25 | #[repr(foo)]
+ | ^^^
+
+error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum
+ --> tests/ui-msrv/enum.rs:31:8
+ |
+31 | #[repr(transparent)]
+ | ^^^^^^^^^^^
+
+error: conflicting representation hints
+ --> tests/ui-msrv/enum.rs:37:1
+ |
+37 | #[repr(u8, u16)]
+ | ^
+
+error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
+ --> tests/ui-msrv/enum.rs:42:22
+ |
+42 | #[derive(FromZeroes, FromBytes)]
+ | ^^^^^^^^^
+ |
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: only C-like enums can implement FromZeroes
+ --> tests/ui-msrv/enum.rs:52:1
+ |
+52 | / enum FromZeroes1 {
+53 | | A(u8),
+54 | | }
+ | |_^
+
+error: only C-like enums can implement FromZeroes
+ --> tests/ui-msrv/enum.rs:57:1
+ |
+57 | / enum FromZeroes2 {
+58 | | A,
+59 | | B(u8),
+60 | | }
+ | |_^
+
+error: FromZeroes only supported on enums with a variant that has a discriminant of `0`
+ --> tests/ui-msrv/enum.rs:63:1
+ |
+63 | / enum FromZeroes3 {
+64 | | A = 1,
+65 | | B,
+66 | | }
+ | |_^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-msrv/enum.rs:73:8
+ |
+73 | #[repr(C)]
+ | ^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-msrv/enum.rs:79:8
+ |
+79 | #[repr(usize)]
+ | ^^^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-msrv/enum.rs:85:8
+ |
+85 | #[repr(isize)]
+ | ^^^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-msrv/enum.rs:91:8
+ |
+91 | #[repr(u32)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-msrv/enum.rs:97:8
+ |
+97 | #[repr(i32)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-msrv/enum.rs:103:8
+ |
+103 | #[repr(u64)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-msrv/enum.rs:109:8
+ |
+109 | #[repr(i64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:119:8
+ |
+119 | #[repr(C)]
+ | ^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:125:8
+ |
+125 | #[repr(u16)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:131:8
+ |
+131 | #[repr(i16)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:137:8
+ |
+137 | #[repr(u32)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:143:8
+ |
+143 | #[repr(i32)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:149:8
+ |
+149 | #[repr(u64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:155:8
+ |
+155 | #[repr(i64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:161:8
+ |
+161 | #[repr(usize)]
+ | ^^^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-msrv/enum.rs:167:8
+ |
+167 | #[repr(isize)]
+ | ^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/enum.rs:173:12
+ |
+173 | #[repr(u8, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/enum.rs:179:12
+ |
+179 | #[repr(i8, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/enum.rs:185:18
+ |
+185 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/enum.rs:191:8
+ |
+191 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0565]: meta item in `repr` must be an identifier
+ --> tests/ui-msrv/enum.rs:19:8
+ |
+19 | #[repr("foo")]
+ | ^^^^^
+
+error[E0552]: unrecognized representation hint
+ --> tests/ui-msrv/enum.rs:25:8
+ |
+25 | #[repr(foo)]
+ | ^^^
+
+error[E0566]: conflicting representation hints
+ --> tests/ui-msrv/enum.rs:37:8
+ |
+37 | #[repr(u8, u16)]
+ | ^^ ^^^
+ |
+ = note: `#[deny(conflicting_repr_hints)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs
new file mode 100644
index 0000000000..1b1bed31f3
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs
@@ -0,0 +1,272 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+#[derive(FromBytes)]
+#[repr(u8)]
+enum Foo {
+ Variant0,
+ Variant1,
+ Variant2,
+ Variant3,
+ Variant4,
+ Variant5,
+ Variant6,
+ Variant7,
+ Variant8,
+ Variant9,
+ Variant10,
+ Variant11,
+ Variant12,
+ Variant13,
+ Variant14,
+ Variant15,
+ Variant16,
+ Variant17,
+ Variant18,
+ Variant19,
+ Variant20,
+ Variant21,
+ Variant22,
+ Variant23,
+ Variant24,
+ Variant25,
+ Variant26,
+ Variant27,
+ Variant28,
+ Variant29,
+ Variant30,
+ Variant31,
+ Variant32,
+ Variant33,
+ Variant34,
+ Variant35,
+ Variant36,
+ Variant37,
+ Variant38,
+ Variant39,
+ Variant40,
+ Variant41,
+ Variant42,
+ Variant43,
+ Variant44,
+ Variant45,
+ Variant46,
+ Variant47,
+ Variant48,
+ Variant49,
+ Variant50,
+ Variant51,
+ Variant52,
+ Variant53,
+ Variant54,
+ Variant55,
+ Variant56,
+ Variant57,
+ Variant58,
+ Variant59,
+ Variant60,
+ Variant61,
+ Variant62,
+ Variant63,
+ Variant64,
+ Variant65,
+ Variant66,
+ Variant67,
+ Variant68,
+ Variant69,
+ Variant70,
+ Variant71,
+ Variant72,
+ Variant73,
+ Variant74,
+ Variant75,
+ Variant76,
+ Variant77,
+ Variant78,
+ Variant79,
+ Variant80,
+ Variant81,
+ Variant82,
+ Variant83,
+ Variant84,
+ Variant85,
+ Variant86,
+ Variant87,
+ Variant88,
+ Variant89,
+ Variant90,
+ Variant91,
+ Variant92,
+ Variant93,
+ Variant94,
+ Variant95,
+ Variant96,
+ Variant97,
+ Variant98,
+ Variant99,
+ Variant100,
+ Variant101,
+ Variant102,
+ Variant103,
+ Variant104,
+ Variant105,
+ Variant106,
+ Variant107,
+ Variant108,
+ Variant109,
+ Variant110,
+ Variant111,
+ Variant112,
+ Variant113,
+ Variant114,
+ Variant115,
+ Variant116,
+ Variant117,
+ Variant118,
+ Variant119,
+ Variant120,
+ Variant121,
+ Variant122,
+ Variant123,
+ Variant124,
+ Variant125,
+ Variant126,
+ Variant127,
+ Variant128,
+ Variant129,
+ Variant130,
+ Variant131,
+ Variant132,
+ Variant133,
+ Variant134,
+ Variant135,
+ Variant136,
+ Variant137,
+ Variant138,
+ Variant139,
+ Variant140,
+ Variant141,
+ Variant142,
+ Variant143,
+ Variant144,
+ Variant145,
+ Variant146,
+ Variant147,
+ Variant148,
+ Variant149,
+ Variant150,
+ Variant151,
+ Variant152,
+ Variant153,
+ Variant154,
+ Variant155,
+ Variant156,
+ Variant157,
+ Variant158,
+ Variant159,
+ Variant160,
+ Variant161,
+ Variant162,
+ Variant163,
+ Variant164,
+ Variant165,
+ Variant166,
+ Variant167,
+ Variant168,
+ Variant169,
+ Variant170,
+ Variant171,
+ Variant172,
+ Variant173,
+ Variant174,
+ Variant175,
+ Variant176,
+ Variant177,
+ Variant178,
+ Variant179,
+ Variant180,
+ Variant181,
+ Variant182,
+ Variant183,
+ Variant184,
+ Variant185,
+ Variant186,
+ Variant187,
+ Variant188,
+ Variant189,
+ Variant190,
+ Variant191,
+ Variant192,
+ Variant193,
+ Variant194,
+ Variant195,
+ Variant196,
+ Variant197,
+ Variant198,
+ Variant199,
+ Variant200,
+ Variant201,
+ Variant202,
+ Variant203,
+ Variant204,
+ Variant205,
+ Variant206,
+ Variant207,
+ Variant208,
+ Variant209,
+ Variant210,
+ Variant211,
+ Variant212,
+ Variant213,
+ Variant214,
+ Variant215,
+ Variant216,
+ Variant217,
+ Variant218,
+ Variant219,
+ Variant220,
+ Variant221,
+ Variant222,
+ Variant223,
+ Variant224,
+ Variant225,
+ Variant226,
+ Variant227,
+ Variant228,
+ Variant229,
+ Variant230,
+ Variant231,
+ Variant232,
+ Variant233,
+ Variant234,
+ Variant235,
+ Variant236,
+ Variant237,
+ Variant238,
+ Variant239,
+ Variant240,
+ Variant241,
+ Variant242,
+ Variant243,
+ Variant244,
+ Variant245,
+ Variant246,
+ Variant247,
+ Variant248,
+ Variant249,
+ Variant250,
+ Variant251,
+ Variant252,
+ Variant253,
+ Variant254,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr
new file mode 100644
index 0000000000..ff828dccba
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr
@@ -0,0 +1,11 @@
+error: FromBytes only supported on repr(u8) enum with 256 variants
+ --> tests/ui-msrv/enum_from_bytes_u8_too_few.rs:15:1
+ |
+15 | / #[repr(u8)]
+16 | | enum Foo {
+17 | | Variant0,
+18 | | Variant1,
+... |
+271 | | Variant254,
+272 | | }
+ | |_^
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs b/third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs
new file mode 100644
index 0000000000..cd65a6ed2c
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs
@@ -0,0 +1,75 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use self::util::{NotZerocopy, AU16};
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// FromZeroes errors
+//
+
+#[derive(FromZeroes)]
+struct FromZeroes1 {
+ value: NotZerocopy,
+}
+
+//
+// FromBytes errors
+//
+
+#[derive(FromBytes)]
+struct FromBytes1 {
+ value: NotZerocopy,
+}
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes1 {
+ value: NotZerocopy,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C)]
+struct Unaligned1 {
+ aligned: AU16,
+}
+
+// This specifically tests a bug we had in an old version of the code in which
+// the trait bound would only be enforced for the first field's type.
+#[derive(Unaligned)]
+#[repr(C)]
+struct Unaligned2 {
+ unaligned: u8,
+ aligned: AU16,
+}
+
+#[derive(Unaligned)]
+#[repr(transparent)]
+struct Unaligned3 {
+ aligned: AU16,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr b/third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr
new file mode 100644
index 0000000000..39dbcd1866
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr
@@ -0,0 +1,74 @@
+warning: unused import: `zerocopy::KnownLayout`
+ --> tests/ui-msrv/late_compile_pass.rs:16:5
+ |
+16 | use zerocopy::KnownLayout;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(unused_imports)]` on by default
+
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+ --> tests/ui-msrv/late_compile_pass.rs:28:10
+ |
+28 | #[derive(FromZeroes)]
+ | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-msrv/late_compile_pass.rs:37:10
+ |
+37 | #[derive(FromBytes)]
+ | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied
+ --> tests/ui-msrv/late_compile_pass.rs:37:10
+ |
+37 | #[derive(FromBytes)]
+ | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1`
+ |
+note: required by a bound in `FromBytes`
+ --> $WORKSPACE/src/lib.rs
+ |
+ | pub unsafe trait FromBytes: FromZeroes {
+ | ^^^^^^^^^^ required by this bound in `FromBytes`
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied
+ --> tests/ui-msrv/late_compile_pass.rs:46:10
+ |
+46 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-msrv/late_compile_pass.rs:56:10
+ |
+56 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-msrv/late_compile_pass.rs:64:10
+ |
+64 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-msrv/late_compile_pass.rs:71:10
+ |
+71 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs b/third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs
new file mode 100644
index 0000000000..e0c4bc578d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs
@@ -0,0 +1,61 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// KnownLayout errors
+//
+
+fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | Y | N | N | KL04 |
+#[derive(KnownLayout)]
+struct KL04<T: ?Sized>(u8, T);
+
+fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+ assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | Y | Y | N | KL06 |
+#[derive(KnownLayout)]
+struct KL06<T: ?Sized + KnownLayout>(u8, T);
+
+fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+ assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | Y | N | N | KL12 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL12<T: ?Sized>(u8, T);
+
+fn test_kl12<T: ?Sized>(kl: &KL12<T>) {
+ assert_kl(kl)
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | Y | N | Y | KL13 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL13<T>(u8, T);
+
+fn test_kl13<T>(t: T) -> impl KnownLayout {
+ KL13(0u8, t)
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr b/third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr
new file mode 100644
index 0000000000..5aa2cde0aa
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr
@@ -0,0 +1,104 @@
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+ --> tests/ui-msrv/mid_compile_pass.rs:59:26
+ |
+59 | fn test_kl13<T>(t: T) -> impl KnownLayout {
+ | ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T`
+ |
+note: required because of the requirements on the impl of `KnownLayout` for `KL13<T>`
+ --> tests/ui-msrv/mid_compile_pass.rs:55:10
+ |
+55 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+59 | fn test_kl13<T: zerocopy::KnownLayout>(t: T) -> impl KnownLayout {
+ | +++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui-msrv/mid_compile_pass.rs:31:15
+ |
+30 | fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+ | - this type parameter needs to be `std::marker::Sized`
+31 | assert_kl(kl);
+ | --------- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `KL04<T>`
+ --> tests/ui-msrv/mid_compile_pass.rs:28:8
+ |
+28 | struct KL04<T: ?Sized>(u8, T);
+ | ^^^^
+note: required because of the requirements on the impl of `KnownLayout` for `KL04<T>`
+ --> tests/ui-msrv/mid_compile_pass.rs:27:10
+ |
+27 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^
+note: required by a bound in `assert_kl`
+ --> tests/ui-msrv/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+30 - fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+30 + fn test_kl04<T>(kl: &KL04<T>) {
+ |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui-msrv/mid_compile_pass.rs:40:15
+ |
+39 | fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+ | - this type parameter needs to be `std::marker::Sized`
+40 | assert_kl(kl);
+ | --------- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `KL06<T>`
+ --> tests/ui-msrv/mid_compile_pass.rs:37:8
+ |
+37 | struct KL06<T: ?Sized + KnownLayout>(u8, T);
+ | ^^^^
+note: required because of the requirements on the impl of `KnownLayout` for `KL06<T>`
+ --> tests/ui-msrv/mid_compile_pass.rs:36:10
+ |
+36 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^
+note: required by a bound in `assert_kl`
+ --> tests/ui-msrv/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+39 - fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+39 + fn test_kl06<T: KnownLayout>(kl: &KL06<T>) {
+ |
+
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+ --> tests/ui-msrv/mid_compile_pass.rs:50:15
+ |
+50 | assert_kl(kl)
+ | --------- ^^ the trait `KnownLayout` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because of the requirements on the impl of `KnownLayout` for `KL12<T>`
+ --> tests/ui-msrv/mid_compile_pass.rs:45:10
+ |
+45 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^
+note: required by a bound in `assert_kl`
+ --> tests/ui-msrv/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+49 | fn test_kl12<T: ?Sized + zerocopy::KnownLayout>(kl: &KL12<T>) {
+ | +++++++++++++++++++++++
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/struct.rs b/third_party/rust/zerocopy-derive/tests/ui-msrv/struct.rs
new file mode 100644
index 0000000000..c76dc7f952
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/struct.rs
@@ -0,0 +1,99 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use zerocopy::KnownLayout;
+
+use self::util::AU16;
+
+fn main() {}
+
+//
+// KnownLayout errors
+//
+
+struct NotKnownLayout;
+
+struct NotKnownLayoutDst([u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | N | N | N | KL00 |
+#[derive(KnownLayout)]
+struct KL00(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | N | Y | N | KL02 |
+#[derive(KnownLayout)]
+struct KL02(u8, [u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | N | N | N | KL08 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL08(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | N | N | Y | KL09 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL09(NotKnownLayout, NotKnownLayout);
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes1<T>(T);
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes2 {
+ foo: u8,
+ bar: AU16,
+}
+
+#[derive(AsBytes)]
+#[repr(C, packed(2))]
+struct AsBytes3 {
+ foo: u8,
+ // We'd prefer to use AU64 here, but you can't use aligned types in
+ // packed structs.
+ bar: u64,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C, align(2))]
+struct Unaligned1;
+
+#[derive(Unaligned)]
+#[repr(transparent, align(2))]
+struct Unaligned2 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(packed, align(2))]
+struct Unaligned3;
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+struct Unaligned4;
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+struct Unaligned5;
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/struct.stderr b/third_party/rust/zerocopy-derive/tests/ui-msrv/struct.stderr
new file mode 100644
index 0000000000..f4a435d5f5
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/struct.stderr
@@ -0,0 +1,113 @@
+error: unsupported on generic structs that are not repr(transparent) or repr(packed)
+ --> tests/ui-msrv/struct.rs:55:10
+ |
+55 | #[derive(AsBytes)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/struct.rs:80:11
+ |
+80 | #[repr(C, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/struct.rs:84:21
+ |
+84 | #[repr(transparent, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/struct.rs:90:16
+ |
+90 | #[repr(packed, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/struct.rs:94:18
+ |
+94 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/struct.rs:98:8
+ |
+98 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0692]: transparent struct cannot have other repr hints
+ --> tests/ui-msrv/struct.rs:84:8
+ |
+84 | #[repr(transparent, align(2))]
+ | ^^^^^^^^^^^ ^^^^^^^^
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/struct.rs:31:10
+ |
+31 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `KL00`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL00`
+ --> tests/ui-msrv/struct.rs:32:8
+ |
+32 | struct KL00(u8, NotKnownLayoutDst);
+ | ^^^^
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/struct.rs:36:10
+ |
+36 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `KL02`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL02`
+ --> tests/ui-msrv/struct.rs:37:8
+ |
+37 | struct KL02(u8, [u8]);
+ | ^^^^
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayoutDst: KnownLayout` is not satisfied
+ --> tests/ui-msrv/struct.rs:41:10
+ |
+41 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayoutDst`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayout: KnownLayout` is not satisfied
+ --> tests/ui-msrv/struct.rs:47:10
+ |
+47 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayout`
+ |
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-msrv/struct.rs:59:10
+ |
+59 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
+ |
+ = help: the following implementations were found:
+ <HasPadding<T, VALUE> as ShouldBe<VALUE>>
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes3, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-msrv/struct.rs:66:10
+ |
+66 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes3, true>`
+ |
+ = help: the following implementations were found:
+ <HasPadding<T, VALUE> as ShouldBe<VALUE>>
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/union.rs b/third_party/rust/zerocopy-derive/tests/ui-msrv/union.rs
new file mode 100644
index 0000000000..8938e78478
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/union.rs
@@ -0,0 +1,73 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use self::util::AU16;
+use std::mem::ManuallyDrop;
+
+fn main() {}
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+union AsBytes1<T> {
+ foo: ManuallyDrop<T>,
+}
+
+#[derive(AsBytes)]
+#[repr(C)]
+union AsBytes2 {
+ foo: u8,
+ bar: [u8; 2],
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C, align(2))]
+union Unaligned1 {
+ foo: i16,
+ bar: AU16,
+}
+
+// Transparent unions are unstable; see issue #60405
+// <https://github.com/rust-lang/rust/issues/60405> for more information.
+
+// #[derive(Unaligned)]
+// #[repr(transparent, align(2))]
+// union Unaligned2 {
+// foo: u8,
+// }
+
+#[derive(Unaligned)]
+#[repr(packed, align(2))]
+union Unaligned3 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+struct Unaligned4 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+struct Unaligned5 {
+ foo: u8,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-msrv/union.stderr b/third_party/rust/zerocopy-derive/tests/ui-msrv/union.stderr
new file mode 100644
index 0000000000..3e13059211
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-msrv/union.stderr
@@ -0,0 +1,42 @@
+error: unsupported on types with type parameters
+ --> tests/ui-msrv/union.rs:24:10
+ |
+24 | #[derive(AsBytes)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/union.rs:42:11
+ |
+42 | #[repr(C, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/union.rs:58:16
+ |
+58 | #[repr(packed, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/union.rs:64:18
+ |
+64 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-msrv/union.rs:70:8
+ |
+70 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-msrv/union.rs:30:10
+ |
+30 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
+ |
+ = help: the following implementations were found:
+ <HasPadding<T, VALUE> as ShouldBe<VALUE>>
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.rs b/third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.rs
new file mode 100644
index 0000000000..2084d921bf
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.rs
@@ -0,0 +1,40 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use core::marker::PhantomData;
+
+use {
+ static_assertions::assert_impl_all,
+ zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned},
+};
+
+use self::util::NotZerocopy;
+
+fn main() {}
+
+// Test generic transparent structs
+
+#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+#[repr(transparent)]
+struct TransparentStruct<T> {
+ inner: T,
+ _phantom: PhantomData<()>,
+}
+
+// It should be legal to derive these traits on a transparent struct, but it
+// must also ensure the traits are only implemented when the inner type
+// implements them.
+assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr b/third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr
new file mode 100644
index 0000000000..f214877dfb
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr
@@ -0,0 +1,111 @@
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+ --> tests/ui-nightly/derive_transparent.rs:37:18
+ |
+37 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromZeroes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `FromZeroes`
+ --> tests/ui-nightly/derive_transparent.rs:27:19
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-nightly/derive_transparent.rs:37:1
+ |
+37 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-nightly/derive_transparent.rs:38:18
+ |
+38 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `FromBytes`
+ --> tests/ui-nightly/derive_transparent.rs:27:31
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-nightly/derive_transparent.rs:38:1
+ |
+38 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied
+ --> tests/ui-nightly/derive_transparent.rs:39:18
+ |
+39 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `AsBytes`
+ --> tests/ui-nightly/derive_transparent.rs:27:10
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-nightly/derive_transparent.rs:39:1
+ |
+39 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied
+ --> tests/ui-nightly/derive_transparent.rs:40:18
+ |
+40 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ TransparentStruct<T>
+ U16<O>
+ U32<O>
+ U64<O>
+ U128<O>
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `Unaligned`
+ --> tests/ui-nightly/derive_transparent.rs:27:42
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-nightly/derive_transparent.rs:40:1
+ |
+40 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/enum.rs b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum.rs
new file mode 100644
index 0000000000..31d5679d19
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum.rs
@@ -0,0 +1,194 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+//
+// Generic errors
+//
+
+#[derive(FromZeroes, FromBytes)]
+#[repr("foo")]
+enum Generic1 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(foo)]
+enum Generic2 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(transparent)]
+enum Generic3 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u8, u16)]
+enum Generic4 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+enum Generic5 {
+ A,
+}
+
+//
+// FromZeroes errors
+//
+
+#[derive(FromZeroes)]
+enum FromZeroes1 {
+ A(u8),
+}
+
+#[derive(FromZeroes)]
+enum FromZeroes2 {
+ A,
+ B(u8),
+}
+
+#[derive(FromZeroes)]
+enum FromZeroes3 {
+ A = 1,
+ B,
+}
+
+//
+// FromBytes errors
+//
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(C)]
+enum FromBytes1 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(usize)]
+enum FromBytes2 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(isize)]
+enum FromBytes3 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u32)]
+enum FromBytes4 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(i32)]
+enum FromBytes5 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u64)]
+enum FromBytes6 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(i64)]
+enum FromBytes7 {
+ A,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C)]
+enum Unaligned1 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u16)]
+enum Unaligned2 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i16)]
+enum Unaligned3 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u32)]
+enum Unaligned4 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i32)]
+enum Unaligned5 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u64)]
+enum Unaligned6 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i64)]
+enum Unaligned7 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(usize)]
+enum Unaligned8 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(isize)]
+enum Unaligned9 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u8, align(2))]
+enum Unaligned10 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i8, align(2))]
+enum Unaligned11 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+enum Unaligned12 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+enum Unaligned13 {
+ A,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/enum.stderr b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum.stderr
new file mode 100644
index 0000000000..a4d5edf35f
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum.stderr
@@ -0,0 +1,201 @@
+error: unrecognized representation hint
+ --> tests/ui-nightly/enum.rs:19:8
+ |
+19 | #[repr("foo")]
+ | ^^^^^
+
+error: unrecognized representation hint
+ --> tests/ui-nightly/enum.rs:25:8
+ |
+25 | #[repr(foo)]
+ | ^^^
+
+error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum
+ --> tests/ui-nightly/enum.rs:31:8
+ |
+31 | #[repr(transparent)]
+ | ^^^^^^^^^^^
+
+error: conflicting representation hints
+ --> tests/ui-nightly/enum.rs:37:8
+ |
+37 | #[repr(u8, u16)]
+ | ^^^^^^^
+
+error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
+ --> tests/ui-nightly/enum.rs:42:22
+ |
+42 | #[derive(FromZeroes, FromBytes)]
+ | ^^^^^^^^^
+ |
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: only C-like enums can implement FromZeroes
+ --> tests/ui-nightly/enum.rs:52:1
+ |
+52 | / enum FromZeroes1 {
+53 | | A(u8),
+54 | | }
+ | |_^
+
+error: only C-like enums can implement FromZeroes
+ --> tests/ui-nightly/enum.rs:57:1
+ |
+57 | / enum FromZeroes2 {
+58 | | A,
+59 | | B(u8),
+60 | | }
+ | |_^
+
+error: FromZeroes only supported on enums with a variant that has a discriminant of `0`
+ --> tests/ui-nightly/enum.rs:63:1
+ |
+63 | / enum FromZeroes3 {
+64 | | A = 1,
+65 | | B,
+66 | | }
+ | |_^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-nightly/enum.rs:73:8
+ |
+73 | #[repr(C)]
+ | ^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-nightly/enum.rs:79:8
+ |
+79 | #[repr(usize)]
+ | ^^^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-nightly/enum.rs:85:8
+ |
+85 | #[repr(isize)]
+ | ^^^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-nightly/enum.rs:91:8
+ |
+91 | #[repr(u32)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-nightly/enum.rs:97:8
+ |
+97 | #[repr(i32)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-nightly/enum.rs:103:8
+ |
+103 | #[repr(u64)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-nightly/enum.rs:109:8
+ |
+109 | #[repr(i64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:119:8
+ |
+119 | #[repr(C)]
+ | ^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:125:8
+ |
+125 | #[repr(u16)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:131:8
+ |
+131 | #[repr(i16)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:137:8
+ |
+137 | #[repr(u32)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:143:8
+ |
+143 | #[repr(i32)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:149:8
+ |
+149 | #[repr(u64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:155:8
+ |
+155 | #[repr(i64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:161:8
+ |
+161 | #[repr(usize)]
+ | ^^^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-nightly/enum.rs:167:8
+ |
+167 | #[repr(isize)]
+ | ^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/enum.rs:173:12
+ |
+173 | #[repr(u8, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/enum.rs:179:12
+ |
+179 | #[repr(i8, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/enum.rs:185:18
+ |
+185 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/enum.rs:191:8
+ |
+191 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0565]: meta item in `repr` must be an identifier
+ --> tests/ui-nightly/enum.rs:19:8
+ |
+19 | #[repr("foo")]
+ | ^^^^^
+
+error[E0552]: unrecognized representation hint
+ --> tests/ui-nightly/enum.rs:25:8
+ |
+25 | #[repr(foo)]
+ | ^^^
+ |
+ = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+
+error[E0566]: conflicting representation hints
+ --> tests/ui-nightly/enum.rs:37:8
+ |
+37 | #[repr(u8, u16)]
+ | ^^ ^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+ = note: `#[deny(conflicting_repr_hints)]` on by default
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs
new file mode 100644
index 0000000000..1b1bed31f3
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs
@@ -0,0 +1,272 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+#[derive(FromBytes)]
+#[repr(u8)]
+enum Foo {
+ Variant0,
+ Variant1,
+ Variant2,
+ Variant3,
+ Variant4,
+ Variant5,
+ Variant6,
+ Variant7,
+ Variant8,
+ Variant9,
+ Variant10,
+ Variant11,
+ Variant12,
+ Variant13,
+ Variant14,
+ Variant15,
+ Variant16,
+ Variant17,
+ Variant18,
+ Variant19,
+ Variant20,
+ Variant21,
+ Variant22,
+ Variant23,
+ Variant24,
+ Variant25,
+ Variant26,
+ Variant27,
+ Variant28,
+ Variant29,
+ Variant30,
+ Variant31,
+ Variant32,
+ Variant33,
+ Variant34,
+ Variant35,
+ Variant36,
+ Variant37,
+ Variant38,
+ Variant39,
+ Variant40,
+ Variant41,
+ Variant42,
+ Variant43,
+ Variant44,
+ Variant45,
+ Variant46,
+ Variant47,
+ Variant48,
+ Variant49,
+ Variant50,
+ Variant51,
+ Variant52,
+ Variant53,
+ Variant54,
+ Variant55,
+ Variant56,
+ Variant57,
+ Variant58,
+ Variant59,
+ Variant60,
+ Variant61,
+ Variant62,
+ Variant63,
+ Variant64,
+ Variant65,
+ Variant66,
+ Variant67,
+ Variant68,
+ Variant69,
+ Variant70,
+ Variant71,
+ Variant72,
+ Variant73,
+ Variant74,
+ Variant75,
+ Variant76,
+ Variant77,
+ Variant78,
+ Variant79,
+ Variant80,
+ Variant81,
+ Variant82,
+ Variant83,
+ Variant84,
+ Variant85,
+ Variant86,
+ Variant87,
+ Variant88,
+ Variant89,
+ Variant90,
+ Variant91,
+ Variant92,
+ Variant93,
+ Variant94,
+ Variant95,
+ Variant96,
+ Variant97,
+ Variant98,
+ Variant99,
+ Variant100,
+ Variant101,
+ Variant102,
+ Variant103,
+ Variant104,
+ Variant105,
+ Variant106,
+ Variant107,
+ Variant108,
+ Variant109,
+ Variant110,
+ Variant111,
+ Variant112,
+ Variant113,
+ Variant114,
+ Variant115,
+ Variant116,
+ Variant117,
+ Variant118,
+ Variant119,
+ Variant120,
+ Variant121,
+ Variant122,
+ Variant123,
+ Variant124,
+ Variant125,
+ Variant126,
+ Variant127,
+ Variant128,
+ Variant129,
+ Variant130,
+ Variant131,
+ Variant132,
+ Variant133,
+ Variant134,
+ Variant135,
+ Variant136,
+ Variant137,
+ Variant138,
+ Variant139,
+ Variant140,
+ Variant141,
+ Variant142,
+ Variant143,
+ Variant144,
+ Variant145,
+ Variant146,
+ Variant147,
+ Variant148,
+ Variant149,
+ Variant150,
+ Variant151,
+ Variant152,
+ Variant153,
+ Variant154,
+ Variant155,
+ Variant156,
+ Variant157,
+ Variant158,
+ Variant159,
+ Variant160,
+ Variant161,
+ Variant162,
+ Variant163,
+ Variant164,
+ Variant165,
+ Variant166,
+ Variant167,
+ Variant168,
+ Variant169,
+ Variant170,
+ Variant171,
+ Variant172,
+ Variant173,
+ Variant174,
+ Variant175,
+ Variant176,
+ Variant177,
+ Variant178,
+ Variant179,
+ Variant180,
+ Variant181,
+ Variant182,
+ Variant183,
+ Variant184,
+ Variant185,
+ Variant186,
+ Variant187,
+ Variant188,
+ Variant189,
+ Variant190,
+ Variant191,
+ Variant192,
+ Variant193,
+ Variant194,
+ Variant195,
+ Variant196,
+ Variant197,
+ Variant198,
+ Variant199,
+ Variant200,
+ Variant201,
+ Variant202,
+ Variant203,
+ Variant204,
+ Variant205,
+ Variant206,
+ Variant207,
+ Variant208,
+ Variant209,
+ Variant210,
+ Variant211,
+ Variant212,
+ Variant213,
+ Variant214,
+ Variant215,
+ Variant216,
+ Variant217,
+ Variant218,
+ Variant219,
+ Variant220,
+ Variant221,
+ Variant222,
+ Variant223,
+ Variant224,
+ Variant225,
+ Variant226,
+ Variant227,
+ Variant228,
+ Variant229,
+ Variant230,
+ Variant231,
+ Variant232,
+ Variant233,
+ Variant234,
+ Variant235,
+ Variant236,
+ Variant237,
+ Variant238,
+ Variant239,
+ Variant240,
+ Variant241,
+ Variant242,
+ Variant243,
+ Variant244,
+ Variant245,
+ Variant246,
+ Variant247,
+ Variant248,
+ Variant249,
+ Variant250,
+ Variant251,
+ Variant252,
+ Variant253,
+ Variant254,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr
new file mode 100644
index 0000000000..50cf0e7cb8
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr
@@ -0,0 +1,11 @@
+error: FromBytes only supported on repr(u8) enum with 256 variants
+ --> tests/ui-nightly/enum_from_bytes_u8_too_few.rs:15:1
+ |
+15 | / #[repr(u8)]
+16 | | enum Foo {
+17 | | Variant0,
+18 | | Variant1,
+... |
+271 | | Variant254,
+272 | | }
+ | |_^
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs b/third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs
new file mode 100644
index 0000000000..cd65a6ed2c
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs
@@ -0,0 +1,75 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use self::util::{NotZerocopy, AU16};
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// FromZeroes errors
+//
+
+#[derive(FromZeroes)]
+struct FromZeroes1 {
+ value: NotZerocopy,
+}
+
+//
+// FromBytes errors
+//
+
+#[derive(FromBytes)]
+struct FromBytes1 {
+ value: NotZerocopy,
+}
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes1 {
+ value: NotZerocopy,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C)]
+struct Unaligned1 {
+ aligned: AU16,
+}
+
+// This specifically tests a bug we had in an old version of the code in which
+// the trait bound would only be enforced for the first field's type.
+#[derive(Unaligned)]
+#[repr(C)]
+struct Unaligned2 {
+ unaligned: u8,
+ aligned: AU16,
+}
+
+#[derive(Unaligned)]
+#[repr(transparent)]
+struct Unaligned3 {
+ aligned: AU16,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr b/third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr
new file mode 100644
index 0000000000..3c45dc4e84
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr
@@ -0,0 +1,150 @@
+warning: unused import: `zerocopy::KnownLayout`
+ --> tests/ui-nightly/late_compile_pass.rs:16:5
+ |
+16 | use zerocopy::KnownLayout;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(unused_imports)]` on by default
+
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+ --> tests/ui-nightly/late_compile_pass.rs:28:10
+ |
+28 | #[derive(FromZeroes)]
+ | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromZeroes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-nightly/late_compile_pass.rs:37:10
+ |
+37 | #[derive(FromBytes)]
+ | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied
+ --> tests/ui-nightly/late_compile_pass.rs:37:10
+ |
+37 | #[derive(FromBytes)]
+ | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1`
+ |
+ = help: the following other types implement trait `FromZeroes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `FromBytes`
+ --> $WORKSPACE/src/lib.rs
+ |
+ | pub unsafe trait FromBytes: FromZeroes {
+ | ^^^^^^^^^^ required by this bound in `FromBytes`
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied
+ --> tests/ui-nightly/late_compile_pass.rs:46:10
+ |
+46 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-nightly/late_compile_pass.rs:56:10
+ |
+56 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ Unaligned1
+ Unaligned2
+ Unaligned3
+ U16<O>
+ U32<O>
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-nightly/late_compile_pass.rs:64:10
+ |
+64 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ Unaligned1
+ Unaligned2
+ Unaligned3
+ U16<O>
+ U32<O>
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-nightly/late_compile_pass.rs:71:10
+ |
+71 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ Unaligned1
+ Unaligned2
+ Unaligned3
+ U16<O>
+ U32<O>
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs b/third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs
new file mode 100644
index 0000000000..e0c4bc578d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs
@@ -0,0 +1,61 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// KnownLayout errors
+//
+
+fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | Y | N | N | KL04 |
+#[derive(KnownLayout)]
+struct KL04<T: ?Sized>(u8, T);
+
+fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+ assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | Y | Y | N | KL06 |
+#[derive(KnownLayout)]
+struct KL06<T: ?Sized + KnownLayout>(u8, T);
+
+fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+ assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | Y | N | N | KL12 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL12<T: ?Sized>(u8, T);
+
+fn test_kl12<T: ?Sized>(kl: &KL12<T>) {
+ assert_kl(kl)
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | Y | N | Y | KL13 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL13<T>(u8, T);
+
+fn test_kl13<T>(t: T) -> impl KnownLayout {
+ KL13(0u8, t)
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr b/third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr
new file mode 100644
index 0000000000..7fd758c8fe
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr
@@ -0,0 +1,104 @@
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+ --> tests/ui-nightly/mid_compile_pass.rs:59:26
+ |
+59 | fn test_kl13<T>(t: T) -> impl KnownLayout {
+ | ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T`
+ |
+note: required for `KL13<T>` to implement `KnownLayout`
+ --> tests/ui-nightly/mid_compile_pass.rs:55:10
+ |
+55 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+59 | fn test_kl13<T: zerocopy::KnownLayout>(t: T) -> impl KnownLayout {
+ | +++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui-nightly/mid_compile_pass.rs:31:15
+ |
+30 | fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+ | - this type parameter needs to be `Sized`
+31 | assert_kl(kl);
+ | --------- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `KL04<T>`
+ --> tests/ui-nightly/mid_compile_pass.rs:28:8
+ |
+28 | struct KL04<T: ?Sized>(u8, T);
+ | ^^^^
+note: required for `KL04<T>` to implement `KnownLayout`
+ --> tests/ui-nightly/mid_compile_pass.rs:27:10
+ |
+27 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+ --> tests/ui-nightly/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+30 - fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+30 + fn test_kl04<T>(kl: &KL04<T>) {
+ |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui-nightly/mid_compile_pass.rs:40:15
+ |
+39 | fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+ | - this type parameter needs to be `Sized`
+40 | assert_kl(kl);
+ | --------- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `KL06<T>`
+ --> tests/ui-nightly/mid_compile_pass.rs:37:8
+ |
+37 | struct KL06<T: ?Sized + KnownLayout>(u8, T);
+ | ^^^^
+note: required for `KL06<T>` to implement `KnownLayout`
+ --> tests/ui-nightly/mid_compile_pass.rs:36:10
+ |
+36 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+ --> tests/ui-nightly/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+39 - fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+39 + fn test_kl06<T: KnownLayout>(kl: &KL06<T>) {
+ |
+
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+ --> tests/ui-nightly/mid_compile_pass.rs:50:15
+ |
+50 | assert_kl(kl)
+ | --------- ^^ the trait `KnownLayout` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `KL12<T>` to implement `KnownLayout`
+ --> tests/ui-nightly/mid_compile_pass.rs:45:10
+ |
+45 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+ --> tests/ui-nightly/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+49 | fn test_kl12<T: ?Sized + zerocopy::KnownLayout>(kl: &KL12<T>) {
+ | +++++++++++++++++++++++
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/struct.rs b/third_party/rust/zerocopy-derive/tests/ui-nightly/struct.rs
new file mode 100644
index 0000000000..c76dc7f952
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/struct.rs
@@ -0,0 +1,99 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use zerocopy::KnownLayout;
+
+use self::util::AU16;
+
+fn main() {}
+
+//
+// KnownLayout errors
+//
+
+struct NotKnownLayout;
+
+struct NotKnownLayoutDst([u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | N | N | N | KL00 |
+#[derive(KnownLayout)]
+struct KL00(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | N | Y | N | KL02 |
+#[derive(KnownLayout)]
+struct KL02(u8, [u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | N | N | N | KL08 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL08(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | N | N | Y | KL09 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL09(NotKnownLayout, NotKnownLayout);
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes1<T>(T);
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes2 {
+ foo: u8,
+ bar: AU16,
+}
+
+#[derive(AsBytes)]
+#[repr(C, packed(2))]
+struct AsBytes3 {
+ foo: u8,
+ // We'd prefer to use AU64 here, but you can't use aligned types in
+ // packed structs.
+ bar: u64,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C, align(2))]
+struct Unaligned1;
+
+#[derive(Unaligned)]
+#[repr(transparent, align(2))]
+struct Unaligned2 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(packed, align(2))]
+struct Unaligned3;
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+struct Unaligned4;
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+struct Unaligned5;
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/struct.stderr b/third_party/rust/zerocopy-derive/tests/ui-nightly/struct.stderr
new file mode 100644
index 0000000000..c3abcbd182
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/struct.stderr
@@ -0,0 +1,143 @@
+error: unsupported on generic structs that are not repr(transparent) or repr(packed)
+ --> tests/ui-nightly/struct.rs:55:10
+ |
+55 | #[derive(AsBytes)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/struct.rs:80:11
+ |
+80 | #[repr(C, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/struct.rs:84:21
+ |
+84 | #[repr(transparent, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/struct.rs:90:16
+ |
+90 | #[repr(packed, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/struct.rs:94:18
+ |
+94 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/struct.rs:98:8
+ |
+98 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0692]: transparent struct cannot have other repr hints
+ --> tests/ui-nightly/struct.rs:84:8
+ |
+84 | #[repr(transparent, align(2))]
+ | ^^^^^^^^^^^ ^^^^^^^^
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/struct.rs:31:10
+ |
+31 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `KL00`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL00`
+ --> tests/ui-nightly/struct.rs:32:8
+ |
+32 | struct KL00(u8, NotKnownLayoutDst);
+ | ^^^^
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/struct.rs:36:10
+ |
+36 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `KL02`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL02`
+ --> tests/ui-nightly/struct.rs:37:8
+ |
+37 | struct KL02(u8, [u8]);
+ | ^^^^
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayoutDst: KnownLayout` is not satisfied
+ --> tests/ui-nightly/struct.rs:41:10
+ |
+41 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayoutDst`
+ |
+ = help: the following other types implement trait `KnownLayout`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayout: KnownLayout` is not satisfied
+ --> tests/ui-nightly/struct.rs:47:10
+ |
+47 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayout`
+ |
+ = help: the following other types implement trait `KnownLayout`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-nightly/struct.rs:59:10
+ |
+59 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
+ |
+ = help: the trait `ShouldBe<true>` is implemented for `HasPadding<AsBytes2, true>`
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes3, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-nightly/struct.rs:66:10
+ |
+66 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes3, true>`
+ |
+ = help: the trait `ShouldBe<true>` is implemented for `HasPadding<AsBytes3, true>`
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0587]: type has conflicting packed and align representation hints
+ --> tests/ui-nightly/struct.rs:91:1
+ |
+91 | struct Unaligned3;
+ | ^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/union.rs b/third_party/rust/zerocopy-derive/tests/ui-nightly/union.rs
new file mode 100644
index 0000000000..8938e78478
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/union.rs
@@ -0,0 +1,73 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use self::util::AU16;
+use std::mem::ManuallyDrop;
+
+fn main() {}
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+union AsBytes1<T> {
+ foo: ManuallyDrop<T>,
+}
+
+#[derive(AsBytes)]
+#[repr(C)]
+union AsBytes2 {
+ foo: u8,
+ bar: [u8; 2],
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C, align(2))]
+union Unaligned1 {
+ foo: i16,
+ bar: AU16,
+}
+
+// Transparent unions are unstable; see issue #60405
+// <https://github.com/rust-lang/rust/issues/60405> for more information.
+
+// #[derive(Unaligned)]
+// #[repr(transparent, align(2))]
+// union Unaligned2 {
+// foo: u8,
+// }
+
+#[derive(Unaligned)]
+#[repr(packed, align(2))]
+union Unaligned3 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+struct Unaligned4 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+struct Unaligned5 {
+ foo: u8,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-nightly/union.stderr b/third_party/rust/zerocopy-derive/tests/ui-nightly/union.stderr
new file mode 100644
index 0000000000..afc4e8c18d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-nightly/union.stderr
@@ -0,0 +1,48 @@
+error: unsupported on types with type parameters
+ --> tests/ui-nightly/union.rs:24:10
+ |
+24 | #[derive(AsBytes)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/union.rs:42:11
+ |
+42 | #[repr(C, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/union.rs:58:16
+ |
+58 | #[repr(packed, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/union.rs:64:18
+ |
+64 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-nightly/union.rs:70:8
+ |
+70 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-nightly/union.rs:30:10
+ |
+30 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
+ |
+ = help: the trait `ShouldBe<true>` is implemented for `HasPadding<AsBytes2, true>`
+ = help: see issue #48214
+ = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0587]: type has conflicting packed and align representation hints
+ --> tests/ui-nightly/union.rs:59:1
+ |
+59 | union Unaligned3 {
+ | ^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.rs b/third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.rs
new file mode 100644
index 0000000000..2084d921bf
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.rs
@@ -0,0 +1,40 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use core::marker::PhantomData;
+
+use {
+ static_assertions::assert_impl_all,
+ zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned},
+};
+
+use self::util::NotZerocopy;
+
+fn main() {}
+
+// Test generic transparent structs
+
+#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+#[repr(transparent)]
+struct TransparentStruct<T> {
+ inner: T,
+ _phantom: PhantomData<()>,
+}
+
+// It should be legal to derive these traits on a transparent struct, but it
+// must also ensure the traits are only implemented when the inner type
+// implements them.
+assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.stderr b/third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.stderr
new file mode 100644
index 0000000000..f24dd4866d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/derive_transparent.stderr
@@ -0,0 +1,111 @@
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+ --> tests/ui-stable/derive_transparent.rs:37:18
+ |
+37 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromZeroes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `FromZeroes`
+ --> tests/ui-stable/derive_transparent.rs:27:19
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-stable/derive_transparent.rs:37:1
+ |
+37 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-stable/derive_transparent.rs:38:18
+ |
+38 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `FromBytes`
+ --> tests/ui-stable/derive_transparent.rs:27:31
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-stable/derive_transparent.rs:38:1
+ |
+38 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied
+ --> tests/ui-stable/derive_transparent.rs:39:18
+ |
+39 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `AsBytes`
+ --> tests/ui-stable/derive_transparent.rs:27:10
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-stable/derive_transparent.rs:39:1
+ |
+39 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied
+ --> tests/ui-stable/derive_transparent.rs:40:18
+ |
+40 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ TransparentStruct<T>
+ U16<O>
+ U32<O>
+ U64<O>
+ U128<O>
+ and $N others
+note: required for `TransparentStruct<NotZerocopy>` to implement `Unaligned`
+ --> tests/ui-stable/derive_transparent.rs:27:42
+ |
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::{closure#0}::assert_impl_all`
+ --> tests/ui-stable/derive_transparent.rs:40:1
+ |
+40 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all`
+ = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/enum.rs b/third_party/rust/zerocopy-derive/tests/ui-stable/enum.rs
new file mode 100644
index 0000000000..31d5679d19
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/enum.rs
@@ -0,0 +1,194 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+//
+// Generic errors
+//
+
+#[derive(FromZeroes, FromBytes)]
+#[repr("foo")]
+enum Generic1 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(foo)]
+enum Generic2 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(transparent)]
+enum Generic3 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u8, u16)]
+enum Generic4 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+enum Generic5 {
+ A,
+}
+
+//
+// FromZeroes errors
+//
+
+#[derive(FromZeroes)]
+enum FromZeroes1 {
+ A(u8),
+}
+
+#[derive(FromZeroes)]
+enum FromZeroes2 {
+ A,
+ B(u8),
+}
+
+#[derive(FromZeroes)]
+enum FromZeroes3 {
+ A = 1,
+ B,
+}
+
+//
+// FromBytes errors
+//
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(C)]
+enum FromBytes1 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(usize)]
+enum FromBytes2 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(isize)]
+enum FromBytes3 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u32)]
+enum FromBytes4 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(i32)]
+enum FromBytes5 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(u64)]
+enum FromBytes6 {
+ A,
+}
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(i64)]
+enum FromBytes7 {
+ A,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C)]
+enum Unaligned1 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u16)]
+enum Unaligned2 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i16)]
+enum Unaligned3 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u32)]
+enum Unaligned4 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i32)]
+enum Unaligned5 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u64)]
+enum Unaligned6 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i64)]
+enum Unaligned7 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(usize)]
+enum Unaligned8 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(isize)]
+enum Unaligned9 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(u8, align(2))]
+enum Unaligned10 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(i8, align(2))]
+enum Unaligned11 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+enum Unaligned12 {
+ A,
+}
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+enum Unaligned13 {
+ A,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/enum.stderr b/third_party/rust/zerocopy-derive/tests/ui-stable/enum.stderr
new file mode 100644
index 0000000000..a47ce9c4ba
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/enum.stderr
@@ -0,0 +1,201 @@
+error: unrecognized representation hint
+ --> tests/ui-stable/enum.rs:19:8
+ |
+19 | #[repr("foo")]
+ | ^^^^^
+
+error: unrecognized representation hint
+ --> tests/ui-stable/enum.rs:25:8
+ |
+25 | #[repr(foo)]
+ | ^^^
+
+error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum
+ --> tests/ui-stable/enum.rs:31:8
+ |
+31 | #[repr(transparent)]
+ | ^^^^^^^^^^^
+
+error: conflicting representation hints
+ --> tests/ui-stable/enum.rs:37:1
+ |
+37 | #[repr(u8, u16)]
+ | ^
+
+error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
+ --> tests/ui-stable/enum.rs:42:22
+ |
+42 | #[derive(FromZeroes, FromBytes)]
+ | ^^^^^^^^^
+ |
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: only C-like enums can implement FromZeroes
+ --> tests/ui-stable/enum.rs:52:1
+ |
+52 | / enum FromZeroes1 {
+53 | | A(u8),
+54 | | }
+ | |_^
+
+error: only C-like enums can implement FromZeroes
+ --> tests/ui-stable/enum.rs:57:1
+ |
+57 | / enum FromZeroes2 {
+58 | | A,
+59 | | B(u8),
+60 | | }
+ | |_^
+
+error: FromZeroes only supported on enums with a variant that has a discriminant of `0`
+ --> tests/ui-stable/enum.rs:63:1
+ |
+63 | / enum FromZeroes3 {
+64 | | A = 1,
+65 | | B,
+66 | | }
+ | |_^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-stable/enum.rs:73:8
+ |
+73 | #[repr(C)]
+ | ^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-stable/enum.rs:79:8
+ |
+79 | #[repr(usize)]
+ | ^^^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-stable/enum.rs:85:8
+ |
+85 | #[repr(isize)]
+ | ^^^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-stable/enum.rs:91:8
+ |
+91 | #[repr(u32)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-stable/enum.rs:97:8
+ |
+97 | #[repr(i32)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-stable/enum.rs:103:8
+ |
+103 | #[repr(u64)]
+ | ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+ --> tests/ui-stable/enum.rs:109:8
+ |
+109 | #[repr(i64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:119:8
+ |
+119 | #[repr(C)]
+ | ^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:125:8
+ |
+125 | #[repr(u16)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:131:8
+ |
+131 | #[repr(i16)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:137:8
+ |
+137 | #[repr(u32)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:143:8
+ |
+143 | #[repr(i32)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:149:8
+ |
+149 | #[repr(u64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:155:8
+ |
+155 | #[repr(i64)]
+ | ^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:161:8
+ |
+161 | #[repr(usize)]
+ | ^^^^^
+
+error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
+ --> tests/ui-stable/enum.rs:167:8
+ |
+167 | #[repr(isize)]
+ | ^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/enum.rs:173:12
+ |
+173 | #[repr(u8, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/enum.rs:179:12
+ |
+179 | #[repr(i8, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/enum.rs:185:18
+ |
+185 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/enum.rs:191:8
+ |
+191 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0565]: meta item in `repr` must be an identifier
+ --> tests/ui-stable/enum.rs:19:8
+ |
+19 | #[repr("foo")]
+ | ^^^^^
+
+error[E0552]: unrecognized representation hint
+ --> tests/ui-stable/enum.rs:25:8
+ |
+25 | #[repr(foo)]
+ | ^^^
+ |
+ = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+
+error[E0566]: conflicting representation hints
+ --> tests/ui-stable/enum.rs:37:8
+ |
+37 | #[repr(u8, u16)]
+ | ^^ ^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+ = note: `#[deny(conflicting_repr_hints)]` on by default
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs b/third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs
new file mode 100644
index 0000000000..1b1bed31f3
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs
@@ -0,0 +1,272 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+#[derive(FromBytes)]
+#[repr(u8)]
+enum Foo {
+ Variant0,
+ Variant1,
+ Variant2,
+ Variant3,
+ Variant4,
+ Variant5,
+ Variant6,
+ Variant7,
+ Variant8,
+ Variant9,
+ Variant10,
+ Variant11,
+ Variant12,
+ Variant13,
+ Variant14,
+ Variant15,
+ Variant16,
+ Variant17,
+ Variant18,
+ Variant19,
+ Variant20,
+ Variant21,
+ Variant22,
+ Variant23,
+ Variant24,
+ Variant25,
+ Variant26,
+ Variant27,
+ Variant28,
+ Variant29,
+ Variant30,
+ Variant31,
+ Variant32,
+ Variant33,
+ Variant34,
+ Variant35,
+ Variant36,
+ Variant37,
+ Variant38,
+ Variant39,
+ Variant40,
+ Variant41,
+ Variant42,
+ Variant43,
+ Variant44,
+ Variant45,
+ Variant46,
+ Variant47,
+ Variant48,
+ Variant49,
+ Variant50,
+ Variant51,
+ Variant52,
+ Variant53,
+ Variant54,
+ Variant55,
+ Variant56,
+ Variant57,
+ Variant58,
+ Variant59,
+ Variant60,
+ Variant61,
+ Variant62,
+ Variant63,
+ Variant64,
+ Variant65,
+ Variant66,
+ Variant67,
+ Variant68,
+ Variant69,
+ Variant70,
+ Variant71,
+ Variant72,
+ Variant73,
+ Variant74,
+ Variant75,
+ Variant76,
+ Variant77,
+ Variant78,
+ Variant79,
+ Variant80,
+ Variant81,
+ Variant82,
+ Variant83,
+ Variant84,
+ Variant85,
+ Variant86,
+ Variant87,
+ Variant88,
+ Variant89,
+ Variant90,
+ Variant91,
+ Variant92,
+ Variant93,
+ Variant94,
+ Variant95,
+ Variant96,
+ Variant97,
+ Variant98,
+ Variant99,
+ Variant100,
+ Variant101,
+ Variant102,
+ Variant103,
+ Variant104,
+ Variant105,
+ Variant106,
+ Variant107,
+ Variant108,
+ Variant109,
+ Variant110,
+ Variant111,
+ Variant112,
+ Variant113,
+ Variant114,
+ Variant115,
+ Variant116,
+ Variant117,
+ Variant118,
+ Variant119,
+ Variant120,
+ Variant121,
+ Variant122,
+ Variant123,
+ Variant124,
+ Variant125,
+ Variant126,
+ Variant127,
+ Variant128,
+ Variant129,
+ Variant130,
+ Variant131,
+ Variant132,
+ Variant133,
+ Variant134,
+ Variant135,
+ Variant136,
+ Variant137,
+ Variant138,
+ Variant139,
+ Variant140,
+ Variant141,
+ Variant142,
+ Variant143,
+ Variant144,
+ Variant145,
+ Variant146,
+ Variant147,
+ Variant148,
+ Variant149,
+ Variant150,
+ Variant151,
+ Variant152,
+ Variant153,
+ Variant154,
+ Variant155,
+ Variant156,
+ Variant157,
+ Variant158,
+ Variant159,
+ Variant160,
+ Variant161,
+ Variant162,
+ Variant163,
+ Variant164,
+ Variant165,
+ Variant166,
+ Variant167,
+ Variant168,
+ Variant169,
+ Variant170,
+ Variant171,
+ Variant172,
+ Variant173,
+ Variant174,
+ Variant175,
+ Variant176,
+ Variant177,
+ Variant178,
+ Variant179,
+ Variant180,
+ Variant181,
+ Variant182,
+ Variant183,
+ Variant184,
+ Variant185,
+ Variant186,
+ Variant187,
+ Variant188,
+ Variant189,
+ Variant190,
+ Variant191,
+ Variant192,
+ Variant193,
+ Variant194,
+ Variant195,
+ Variant196,
+ Variant197,
+ Variant198,
+ Variant199,
+ Variant200,
+ Variant201,
+ Variant202,
+ Variant203,
+ Variant204,
+ Variant205,
+ Variant206,
+ Variant207,
+ Variant208,
+ Variant209,
+ Variant210,
+ Variant211,
+ Variant212,
+ Variant213,
+ Variant214,
+ Variant215,
+ Variant216,
+ Variant217,
+ Variant218,
+ Variant219,
+ Variant220,
+ Variant221,
+ Variant222,
+ Variant223,
+ Variant224,
+ Variant225,
+ Variant226,
+ Variant227,
+ Variant228,
+ Variant229,
+ Variant230,
+ Variant231,
+ Variant232,
+ Variant233,
+ Variant234,
+ Variant235,
+ Variant236,
+ Variant237,
+ Variant238,
+ Variant239,
+ Variant240,
+ Variant241,
+ Variant242,
+ Variant243,
+ Variant244,
+ Variant245,
+ Variant246,
+ Variant247,
+ Variant248,
+ Variant249,
+ Variant250,
+ Variant251,
+ Variant252,
+ Variant253,
+ Variant254,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr b/third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr
new file mode 100644
index 0000000000..5edbabc47d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr
@@ -0,0 +1,11 @@
+error: FromBytes only supported on repr(u8) enum with 256 variants
+ --> tests/ui-stable/enum_from_bytes_u8_too_few.rs:15:1
+ |
+15 | / #[repr(u8)]
+16 | | enum Foo {
+17 | | Variant0,
+18 | | Variant1,
+... |
+271 | | Variant254,
+272 | | }
+ | |_^
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.rs b/third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.rs
new file mode 100644
index 0000000000..cd65a6ed2c
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.rs
@@ -0,0 +1,75 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use self::util::{NotZerocopy, AU16};
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// FromZeroes errors
+//
+
+#[derive(FromZeroes)]
+struct FromZeroes1 {
+ value: NotZerocopy,
+}
+
+//
+// FromBytes errors
+//
+
+#[derive(FromBytes)]
+struct FromBytes1 {
+ value: NotZerocopy,
+}
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes1 {
+ value: NotZerocopy,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C)]
+struct Unaligned1 {
+ aligned: AU16,
+}
+
+// This specifically tests a bug we had in an old version of the code in which
+// the trait bound would only be enforced for the first field's type.
+#[derive(Unaligned)]
+#[repr(C)]
+struct Unaligned2 {
+ unaligned: u8,
+ aligned: AU16,
+}
+
+#[derive(Unaligned)]
+#[repr(transparent)]
+struct Unaligned3 {
+ aligned: AU16,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr b/third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr
new file mode 100644
index 0000000000..808054ab4d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr
@@ -0,0 +1,144 @@
+warning: unused import: `zerocopy::KnownLayout`
+ --> tests/ui-stable/late_compile_pass.rs:16:5
+ |
+16 | use zerocopy::KnownLayout;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(unused_imports)]` on by default
+
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+ --> tests/ui-stable/late_compile_pass.rs:28:10
+ |
+28 | #[derive(FromZeroes)]
+ | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromZeroes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-stable/late_compile_pass.rs:37:10
+ |
+37 | #[derive(FromBytes)]
+ | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied
+ --> tests/ui-stable/late_compile_pass.rs:37:10
+ |
+37 | #[derive(FromBytes)]
+ | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1`
+ |
+ = help: the following other types implement trait `FromZeroes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `FromBytes`
+ --> $WORKSPACE/src/lib.rs
+ |
+ | pub unsafe trait FromBytes: FromZeroes {
+ | ^^^^^^^^^^ required by this bound in `FromBytes`
+ = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied
+ --> tests/ui-stable/late_compile_pass.rs:46:10
+ |
+46 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-stable/late_compile_pass.rs:56:10
+ |
+56 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ Unaligned1
+ Unaligned2
+ Unaligned3
+ U16<O>
+ U32<O>
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-stable/late_compile_pass.rs:64:10
+ |
+64 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ Unaligned1
+ Unaligned2
+ Unaligned3
+ U16<O>
+ U32<O>
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
+ --> tests/ui-stable/late_compile_pass.rs:71:10
+ |
+71 | #[derive(Unaligned)]
+ | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
+ |
+ = help: the following other types implement trait `Unaligned`:
+ bool
+ i8
+ u8
+ Unaligned1
+ Unaligned2
+ Unaligned3
+ U16<O>
+ U32<O>
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs b/third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs
new file mode 100644
index 0000000000..e0c4bc578d
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs
@@ -0,0 +1,61 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// KnownLayout errors
+//
+
+fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | Y | N | N | KL04 |
+#[derive(KnownLayout)]
+struct KL04<T: ?Sized>(u8, T);
+
+fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+ assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | Y | Y | N | KL06 |
+#[derive(KnownLayout)]
+struct KL06<T: ?Sized + KnownLayout>(u8, T);
+
+fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+ assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | Y | N | N | KL12 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL12<T: ?Sized>(u8, T);
+
+fn test_kl12<T: ?Sized>(kl: &KL12<T>) {
+ assert_kl(kl)
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | Y | N | Y | KL13 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL13<T>(u8, T);
+
+fn test_kl13<T>(t: T) -> impl KnownLayout {
+ KL13(0u8, t)
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr b/third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr
new file mode 100644
index 0000000000..f39bcdb170
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr
@@ -0,0 +1,104 @@
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+ --> tests/ui-stable/mid_compile_pass.rs:59:26
+ |
+59 | fn test_kl13<T>(t: T) -> impl KnownLayout {
+ | ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T`
+ |
+note: required for `KL13<T>` to implement `KnownLayout`
+ --> tests/ui-stable/mid_compile_pass.rs:55:10
+ |
+55 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+59 | fn test_kl13<T: zerocopy::KnownLayout>(t: T) -> impl KnownLayout {
+ | +++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui-stable/mid_compile_pass.rs:31:15
+ |
+30 | fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+ | - this type parameter needs to be `Sized`
+31 | assert_kl(kl);
+ | --------- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `KL04<T>`
+ --> tests/ui-stable/mid_compile_pass.rs:28:8
+ |
+28 | struct KL04<T: ?Sized>(u8, T);
+ | ^^^^
+note: required for `KL04<T>` to implement `KnownLayout`
+ --> tests/ui-stable/mid_compile_pass.rs:27:10
+ |
+27 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+ --> tests/ui-stable/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+30 - fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+30 + fn test_kl04<T>(kl: &KL04<T>) {
+ |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui-stable/mid_compile_pass.rs:40:15
+ |
+39 | fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+ | - this type parameter needs to be `Sized`
+40 | assert_kl(kl);
+ | --------- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `KL06<T>`
+ --> tests/ui-stable/mid_compile_pass.rs:37:8
+ |
+37 | struct KL06<T: ?Sized + KnownLayout>(u8, T);
+ | ^^^^
+note: required for `KL06<T>` to implement `KnownLayout`
+ --> tests/ui-stable/mid_compile_pass.rs:36:10
+ |
+36 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+ --> tests/ui-stable/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+39 - fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+39 + fn test_kl06<T: KnownLayout>(kl: &KL06<T>) {
+ |
+
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+ --> tests/ui-stable/mid_compile_pass.rs:50:15
+ |
+50 | assert_kl(kl)
+ | --------- ^^ the trait `KnownLayout` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `KL12<T>` to implement `KnownLayout`
+ --> tests/ui-stable/mid_compile_pass.rs:45:10
+ |
+45 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+ --> tests/ui-stable/mid_compile_pass.rs:23:26
+ |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+ | ^^^^^^^^^^^ required by this bound in `assert_kl`
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+49 | fn test_kl12<T: ?Sized + zerocopy::KnownLayout>(kl: &KL12<T>) {
+ | +++++++++++++++++++++++
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/struct.rs b/third_party/rust/zerocopy-derive/tests/ui-stable/struct.rs
new file mode 100644
index 0000000000..c76dc7f952
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/struct.rs
@@ -0,0 +1,99 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use zerocopy::KnownLayout;
+
+use self::util::AU16;
+
+fn main() {}
+
+//
+// KnownLayout errors
+//
+
+struct NotKnownLayout;
+
+struct NotKnownLayoutDst([u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | N | N | N | KL00 |
+#[derive(KnownLayout)]
+struct KL00(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | N | N | Y | N | KL02 |
+#[derive(KnownLayout)]
+struct KL02(u8, [u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | N | N | N | KL08 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL08(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// | Y | N | N | Y | KL09 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL09(NotKnownLayout, NotKnownLayout);
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes1<T>(T);
+
+#[derive(AsBytes)]
+#[repr(C)]
+struct AsBytes2 {
+ foo: u8,
+ bar: AU16,
+}
+
+#[derive(AsBytes)]
+#[repr(C, packed(2))]
+struct AsBytes3 {
+ foo: u8,
+ // We'd prefer to use AU64 here, but you can't use aligned types in
+ // packed structs.
+ bar: u64,
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C, align(2))]
+struct Unaligned1;
+
+#[derive(Unaligned)]
+#[repr(transparent, align(2))]
+struct Unaligned2 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(packed, align(2))]
+struct Unaligned3;
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+struct Unaligned4;
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+struct Unaligned5;
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/struct.stderr b/third_party/rust/zerocopy-derive/tests/ui-stable/struct.stderr
new file mode 100644
index 0000000000..a93d7c45b0
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/struct.stderr
@@ -0,0 +1,131 @@
+error: unsupported on generic structs that are not repr(transparent) or repr(packed)
+ --> tests/ui-stable/struct.rs:55:10
+ |
+55 | #[derive(AsBytes)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/struct.rs:80:11
+ |
+80 | #[repr(C, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/struct.rs:84:21
+ |
+84 | #[repr(transparent, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/struct.rs:90:16
+ |
+90 | #[repr(packed, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/struct.rs:94:18
+ |
+94 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/struct.rs:98:8
+ |
+98 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0692]: transparent struct cannot have other repr hints
+ --> tests/ui-stable/struct.rs:84:8
+ |
+84 | #[repr(transparent, align(2))]
+ | ^^^^^^^^^^^ ^^^^^^^^
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/struct.rs:31:10
+ |
+31 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `KL00`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL00`
+ --> tests/ui-stable/struct.rs:32:8
+ |
+32 | struct KL00(u8, NotKnownLayoutDst);
+ | ^^^^
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/struct.rs:36:10
+ |
+36 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `KL02`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL02`
+ --> tests/ui-stable/struct.rs:37:8
+ |
+37 | struct KL02(u8, [u8]);
+ | ^^^^
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayoutDst: KnownLayout` is not satisfied
+ --> tests/ui-stable/struct.rs:41:10
+ |
+41 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayoutDst`
+ |
+ = help: the following other types implement trait `KnownLayout`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayout: KnownLayout` is not satisfied
+ --> tests/ui-stable/struct.rs:47:10
+ |
+47 | #[derive(KnownLayout)]
+ | ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayout`
+ |
+ = help: the following other types implement trait `KnownLayout`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+ = help: see issue #48214
+ = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-stable/struct.rs:59:10
+ |
+59 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
+ |
+ = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>`
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes3, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-stable/struct.rs:66:10
+ |
+66 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes3, true>`
+ |
+ = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>`
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/union.rs b/third_party/rust/zerocopy-derive/tests/ui-stable/union.rs
new file mode 100644
index 0000000000..8938e78478
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/union.rs
@@ -0,0 +1,73 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[macro_use]
+extern crate zerocopy;
+
+#[path = "../util.rs"]
+mod util;
+
+use self::util::AU16;
+use std::mem::ManuallyDrop;
+
+fn main() {}
+
+//
+// AsBytes errors
+//
+
+#[derive(AsBytes)]
+#[repr(C)]
+union AsBytes1<T> {
+ foo: ManuallyDrop<T>,
+}
+
+#[derive(AsBytes)]
+#[repr(C)]
+union AsBytes2 {
+ foo: u8,
+ bar: [u8; 2],
+}
+
+//
+// Unaligned errors
+//
+
+#[derive(Unaligned)]
+#[repr(C, align(2))]
+union Unaligned1 {
+ foo: i16,
+ bar: AU16,
+}
+
+// Transparent unions are unstable; see issue #60405
+// <https://github.com/rust-lang/rust/issues/60405> for more information.
+
+// #[derive(Unaligned)]
+// #[repr(transparent, align(2))]
+// union Unaligned2 {
+// foo: u8,
+// }
+
+#[derive(Unaligned)]
+#[repr(packed, align(2))]
+union Unaligned3 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(align(1), align(2))]
+struct Unaligned4 {
+ foo: u8,
+}
+
+#[derive(Unaligned)]
+#[repr(align(2), align(4))]
+struct Unaligned5 {
+ foo: u8,
+}
diff --git a/third_party/rust/zerocopy-derive/tests/ui-stable/union.stderr b/third_party/rust/zerocopy-derive/tests/ui-stable/union.stderr
new file mode 100644
index 0000000000..8d5cbbbd66
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/ui-stable/union.stderr
@@ -0,0 +1,41 @@
+error: unsupported on types with type parameters
+ --> tests/ui-stable/union.rs:24:10
+ |
+24 | #[derive(AsBytes)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/union.rs:42:11
+ |
+42 | #[repr(C, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/union.rs:58:16
+ |
+58 | #[repr(packed, align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/union.rs:64:18
+ |
+64 | #[repr(align(1), align(2))]
+ | ^^^^^^^^
+
+error: cannot derive Unaligned with repr(align(N > 1))
+ --> tests/ui-stable/union.rs:70:8
+ |
+70 | #[repr(align(2), align(4))]
+ | ^^^^^^^^
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+ --> tests/ui-stable/union.rs:30:10
+ |
+30 | #[derive(AsBytes)]
+ | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
+ |
+ = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>`
+ = help: see issue #48214
+ = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy-derive/tests/union_as_bytes.rs b/third_party/rust/zerocopy-derive/tests/union_as_bytes.rs
new file mode 100644
index 0000000000..84f51817f2
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/union_as_bytes.rs
@@ -0,0 +1,75 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {static_assertions::assert_impl_all, zerocopy::AsBytes};
+
+// A union is `AsBytes` if:
+// - all fields are `AsBytes`
+// - `repr(C)` or `repr(transparent)` and
+// - no padding (size of union equals size of each field type)
+// - `repr(packed)`
+
+#[derive(AsBytes, Clone, Copy)]
+#[repr(C)]
+union CZst {
+ a: (),
+}
+
+assert_impl_all!(CZst: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C)]
+union C {
+ a: u8,
+ b: u8,
+}
+
+assert_impl_all!(C: AsBytes);
+
+// Transparent unions are unstable; see issue #60405
+// <https://github.com/rust-lang/rust/issues/60405> for more information.
+
+// #[derive(AsBytes)]
+// #[repr(transparent)]
+// union Transparent {
+// a: u8,
+// b: CZst,
+// }
+
+// is_as_bytes!(Transparent);
+
+#[derive(AsBytes)]
+#[repr(C, packed)]
+union CZstPacked {
+ a: (),
+}
+
+assert_impl_all!(CZstPacked: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C, packed)]
+union CPacked {
+ a: u8,
+ b: i8,
+}
+
+assert_impl_all!(CPacked: AsBytes);
+
+#[derive(AsBytes)]
+#[repr(C, packed)]
+union CMultibytePacked {
+ a: i32,
+ b: u32,
+ c: f32,
+}
+
+assert_impl_all!(CMultibytePacked: AsBytes);
diff --git a/third_party/rust/zerocopy-derive/tests/union_from_bytes.rs b/third_party/rust/zerocopy-derive/tests/union_from_bytes.rs
new file mode 100644
index 0000000000..4635735ef1
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/union_from_bytes.rs
@@ -0,0 +1,72 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {
+ static_assertions::assert_impl_all,
+ zerocopy::{FromBytes, FromZeroes},
+};
+
+// A union is `FromBytes` if:
+// - all fields are `FromBytes`
+
+#[derive(Clone, Copy, FromZeroes, FromBytes)]
+union Zst {
+ a: (),
+}
+
+assert_impl_all!(Zst: FromBytes);
+
+#[derive(FromZeroes, FromBytes)]
+union One {
+ a: u8,
+}
+
+assert_impl_all!(One: FromBytes);
+
+#[derive(FromZeroes, FromBytes)]
+union Two {
+ a: u8,
+ b: Zst,
+}
+
+assert_impl_all!(Two: FromBytes);
+
+#[derive(FromZeroes, FromBytes)]
+union TypeParams<'a, T: Copy, I: Iterator>
+where
+ I::Item: Copy,
+{
+ a: T,
+ c: I::Item,
+ d: u8,
+ e: PhantomData<&'a [u8]>,
+ f: PhantomData<&'static str>,
+ g: PhantomData<String>,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromBytes);
+
+// Deriving `FromBytes` should work if the union has bounded parameters.
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(C)]
+union WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromBytes>
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + Copy + FromBytes,
+{
+ a: [T; N],
+ b: PhantomData<&'a &'b ()>,
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromBytes);
diff --git a/third_party/rust/zerocopy-derive/tests/union_from_zeroes.rs b/third_party/rust/zerocopy-derive/tests/union_from_zeroes.rs
new file mode 100644
index 0000000000..935fc1563b
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/union_from_zeroes.rs
@@ -0,0 +1,72 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+#[macro_use]
+mod util;
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {static_assertions::assert_impl_all, zerocopy::FromZeroes};
+
+// A union is `FromZeroes` if:
+// - all fields are `FromZeroes`
+
+#[derive(Clone, Copy, FromZeroes)]
+union Zst {
+ a: (),
+}
+
+assert_impl_all!(Zst: FromZeroes);
+
+#[derive(FromZeroes)]
+union One {
+ a: bool,
+}
+
+assert_impl_all!(One: FromZeroes);
+
+#[derive(FromZeroes)]
+union Two {
+ a: bool,
+ b: Zst,
+}
+
+assert_impl_all!(Two: FromZeroes);
+
+#[derive(FromZeroes)]
+union TypeParams<'a, T: Copy, I: Iterator>
+where
+ I::Item: Copy,
+{
+ a: T,
+ c: I::Item,
+ d: u8,
+ e: PhantomData<&'a [u8]>,
+ f: PhantomData<&'static str>,
+ g: PhantomData<String>,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes);
+
+// Deriving `FromZeroes` should work if the union has bounded parameters.
+
+#[derive(FromZeroes)]
+#[repr(C)]
+union WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromZeroes>
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + Copy + FromZeroes,
+{
+ a: [T; N],
+ b: PhantomData<&'a &'b ()>,
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromZeroes);
diff --git a/third_party/rust/zerocopy-derive/tests/union_known_layout.rs b/third_party/rust/zerocopy-derive/tests/union_known_layout.rs
new file mode 100644
index 0000000000..337ab4afef
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/union_known_layout.rs
@@ -0,0 +1,65 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![allow(warnings)]
+
+#[macro_use]
+mod util;
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {static_assertions::assert_impl_all, zerocopy::KnownLayout};
+
+#[derive(Clone, Copy, KnownLayout)]
+union Zst {
+ a: (),
+}
+
+assert_impl_all!(Zst: KnownLayout);
+
+#[derive(KnownLayout)]
+union One {
+ a: bool,
+}
+
+assert_impl_all!(One: KnownLayout);
+
+#[derive(KnownLayout)]
+union Two {
+ a: bool,
+ b: Zst,
+}
+
+assert_impl_all!(Two: KnownLayout);
+
+#[derive(KnownLayout)]
+union TypeParams<'a, T: Copy, I: Iterator>
+where
+ I::Item: Copy,
+{
+ a: T,
+ c: I::Item,
+ d: u8,
+ e: PhantomData<&'a [u8]>,
+ f: PhantomData<&'static str>,
+ g: PhantomData<String>,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: KnownLayout);
+
+// Deriving `KnownLayout` should work if the union has bounded parameters.
+
+#[derive(KnownLayout)]
+#[repr(C)]
+union WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + KnownLayout>
+where
+ 'a: 'b,
+ 'b: 'a,
+ T: 'a + 'b + Copy + KnownLayout,
+{
+ a: [T; N],
+ b: PhantomData<&'a &'b ()>,
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: KnownLayout);
diff --git a/third_party/rust/zerocopy-derive/tests/union_unaligned.rs b/third_party/rust/zerocopy-derive/tests/union_unaligned.rs
new file mode 100644
index 0000000000..5ba3ac76ac
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/union_unaligned.rs
@@ -0,0 +1,77 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#![allow(warnings)]
+
+use std::{marker::PhantomData, option::IntoIter};
+
+use {static_assertions::assert_impl_all, zerocopy::Unaligned};
+
+// A union is `Unaligned` if:
+// - `repr(align)` is no more than 1 and either
+// - `repr(C)` or `repr(transparent)` and
+// - all fields `Unaligned`
+// - `repr(packed)`
+
+#[derive(Unaligned)]
+#[repr(C)]
+union Foo {
+ a: u8,
+}
+
+assert_impl_all!(Foo: Unaligned);
+
+// Transparent unions are unstable; see issue #60405
+// <https://github.com/rust-lang/rust/issues/60405> for more information.
+
+// #[derive(Unaligned)]
+// #[repr(transparent)]
+// union Bar {
+// a: u8,
+// }
+
+// is_unaligned!(Bar);
+
+#[derive(Unaligned)]
+#[repr(packed)]
+union Baz {
+ // NOTE: The `u16` type is not guaranteed to have alignment 2, although it
+ // does on many platforms. However, to fix this would require a custom type
+ // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not
+ // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
+ // have no choice but to use `u16` here. Luckily, these tests run in CI on
+ // platforms on which `u16` has alignment 2, so this isn't that big of a
+ // deal.
+ a: u16,
+}
+
+assert_impl_all!(Baz: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(C, align(1))]
+union FooAlign {
+ a: u8,
+}
+
+assert_impl_all!(FooAlign: Unaligned);
+
+#[derive(Unaligned)]
+#[repr(C)]
+union TypeParams<'a, T: Copy, I: Iterator>
+where
+ I::Item: Copy,
+{
+ a: T,
+ c: I::Item,
+ d: u8,
+ e: PhantomData<&'a [u8]>,
+ f: PhantomData<&'static str>,
+ g: PhantomData<String>,
+}
+
+assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: Unaligned);
diff --git a/third_party/rust/zerocopy-derive/tests/util.rs b/third_party/rust/zerocopy-derive/tests/util.rs
new file mode 100644
index 0000000000..a8656fb20f
--- /dev/null
+++ b/third_party/rust/zerocopy-derive/tests/util.rs
@@ -0,0 +1,20 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+use zerocopy::{AsBytes, FromBytes, FromZeroes, KnownLayout};
+
+/// A type that doesn't implement any zerocopy traits.
+pub struct NotZerocopy<T = ()>(T);
+
+/// A `u16` with alignment 2.
+///
+/// Though `u16` has alignment 2 on some platforms, it's not guaranteed. By
+/// contrast, `AU16` is guaranteed to have alignment 2.
+#[derive(KnownLayout, FromZeroes, FromBytes, AsBytes, Copy, Clone)]
+#[repr(C, align(2))]
+pub struct AU16(u16);
diff --git a/third_party/rust/zerocopy/.cargo-checksum.json b/third_party/rust/zerocopy/.cargo-checksum.json
new file mode 100644
index 0000000000..9025e8f525
--- /dev/null
+++ b/third_party/rust/zerocopy/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CONTRIBUTING.md":"47968395d4bee21ffd1f4e665625ba6c89b841a71dc92d0cac432aafbcbfe027","Cargo.toml":"61ae2f6dcb97a4acc33f221b8110de9c171437ccf69902f172c6ef71934e1458","INTERNAL.md":"d6f3929776cd6b195d926dda36b7db287f92fa17ed8dabb0c9c12eb6f945bd61","LICENSE-APACHE":"9d185ac6703c4b0453974c0d85e9eee43e6941009296bb1f5eb0b54e2329e9f3","LICENSE-BSD":"83c1763356e822adde0a2cae748d938a73fdc263849ccff6b27776dff213bd32","LICENSE-MIT":"1a2f5c12ddc934d58956aa5dbdd3255fe55fd957633ab7d0d39e4f0daa73f7df","POLICIES.md":"c889920550fcd6aa0477ae1f9a1c6aa6f48bc0c5923b035d5ae8af4d3ce06b91","README.md":"a2a01b58f7344a1a03b314d545d221e1a22642071d2067ebefbeb0d1c63a27d0","cargo.sh":"ea53cc247d35243fbe161024890f7c2f855688b8fd26b7244df5ae999ba99bd2","clippy.toml":"df67a6131fff2fe52309e797d2dfad080fc8cbdfcb1baa7f14415b3e397c291c","generate-readme.sh":"0b86377c6ca87971154b8f461e71d72727ecb65e550d2f96729d8949e5264155","rustfmt.toml":"33a21d11175200d203fcdb803c61a24fc461661bf8a2de7c9189af7ecee123c2","src/byteorder.rs":"1fe45a93aefe6ecaa08217c7203ee94d93ae3fcd57113025cf789d26953f12e8","src/lib.rs":"2f21f18a4ca1d4be2d997f037158cb21a7421b2ba2cc52f3e4c5f9410197ed27","src/macro_util.rs":"23ac66f9e011a21c63c65bd2e8a4aadc90706f4d375239a5a0bbe309c588c8de","src/macros.rs":"6c6d794ad398131892c6541bb1a172b10144241057c0d79d1807cc97298beb42","src/post_monomorphization_compile_fail_tests.rs":"6f20b9ddb9d8c2573f2f0c18f58998b9207e588190586891f48b00570f7d4623","src/third_party/rust/LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","src/third_party/rust/LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/third_party/rust/README.fuchsia":"5dc26ec369c273eb99679b43c5de4c41c82797e8800c3926c4c76912e9596ecf","src/third_party/rust/layout.rs":"bf602961483f1ed0266602c00bc31345da38f4601954ed4a673f26d7ae8199b9","src/util.rs":"8bf8c2c12bba9596d38018f90da90a9aa310d9c1c677f318ecec40b1811885aa","src/wrappers.rs":"598520c9f56a1c6dff65f615cb386b95a02b131de72afd8b70dcdb2eabe993f1","testdata/include_value/data":"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589","tests/trybuild.rs":"8b77ed684725d2e99fd7806d8f361cd2495b388cc463be3ff2fae25bcbe34c56","tests/ui-msrv/include_value_not_from_bytes.rs":"ea2a419e0c7ce12b4febe6139523184cba2b2c54c879177e0c58a5f78f0ec340","tests/ui-msrv/include_value_not_from_bytes.stderr":"57d634cea8f0906b08e7eea056d09b02364f2a656623116c29fdc706b5393926","tests/ui-msrv/include_value_wrong_size.rs":"418e8c86ebf5a28ee50bd6ae00550f62a7a0ef3a7e7fda965b3d2337b64f2c66","tests/ui-msrv/include_value_wrong_size.stderr":"40bcc6c0172b530cda18bf60d35550e219254a71c0a1e4b16417b17db6d18829","tests/ui-msrv/invalid-impls/invalid-impls.rs":"474d843ad40f3936adcd3ff592d815d8169813962ab9d99a68348b4b91aef10e","tests/ui-msrv/invalid-impls/invalid-impls.stderr":"ddc7a15d675f91b8b838c5c1b8e0d3973d981b11ce956e0f50d4880f0ff0e408","tests/ui-msrv/max-align.rs":"ffcb6687c98e5629d01b17cbd0845ec195007cc39aa244b26a77d17688c8f13d","tests/ui-msrv/max-align.stderr":"38775aa2a8bc035eedbc57ab0081c865b804d9a7fc5200ec425210fdea6a69d1","tests/ui-msrv/transmute-dst-not-frombytes.rs":"e00251eae67cdf8267a4963f212857a2a51de640a6f856c4b8df2a953caad25a","tests/ui-msrv/transmute-dst-not-frombytes.stderr":"537111d0377c9a255bb9cd43fa12646a901f0b8cf6b1fb5842fb5f0d41ea86e8","tests/ui-msrv/transmute-mut-alignment-increase.rs":"ba83c9cf01acf11352f7ee5b54cd73a451394fd78b8ddeb0637931c87adfd6ae","tests/ui-msrv/transmute-mut-alignment-increase.stderr":"9e879881032ab5ba28f8cc6a240bf96150c4a7fb3e55b1de0c808dc5e0b1179d","tests/ui-msrv/transmute-mut-const.rs":"4227f4c0dda6d6128f41b209ecc2bf941c7659c8de84cc0e418862d279baa78f","tests/ui-msrv/transmute-mut-const.stderr":"3c8dcb20b8cffd73f3b330b0199c5912ff015b51fce6d3acf684e388abb70a9c","tests/ui-msrv/transmute-mut-dst-generic.rs":"aa015679b75dac0c37d5c43782b5e9522257f6ba34a10a89d0c1eba524a7af5c","tests/ui-msrv/transmute-mut-dst-generic.stderr":"d19ae09a138d21aa64da708da85fd09b9b98a70c76cf397f5cbe7866ccbddbed","tests/ui-msrv/transmute-mut-dst-not-a-reference.rs":"5d784ab588f081bfc304501f811a85ea2662f88fff8274ccbd53172ec255212c","tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr":"1cca08728f4b93b78757224420090f4ec0a2014043e9b1d86ffafe9fcc8f1faa","tests/ui-msrv/transmute-mut-dst-not-asbytes.rs":"b1f986b3433980d7572a80511ca5a758c91e0c761d01c50bc73ed025d45698a6","tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr":"fd4a28b880eebd3d4f4b1f0388a26b372b07fd8186979970e2ea881379bf007b","tests/ui-msrv/transmute-mut-dst-not-frombytes.rs":"a4353eeb67b4701908e694738c5c4ce965afe4432f14e00e740684352f5ddd30","tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr":"fd9e4c396c995be82b4bda2a28565f5d427d9733ae85f56cfb3922b1130fa06a","tests/ui-msrv/transmute-mut-dst-unsized.rs":"58c3423c07dd06ca98e61439f318ba5f3f7fc68ca9cb59371ebc482ad54709db","tests/ui-msrv/transmute-mut-dst-unsized.stderr":"b0c443b692859195ade80fb3650d51b4a01c2dd8b523322db84acfc3845b154d","tests/ui-msrv/transmute-mut-illegal-lifetime.rs":"ec18bf7b3d9bd2674b43d0e04fc0545227473d43b07e2bbccc19c2068df33673","tests/ui-msrv/transmute-mut-illegal-lifetime.stderr":"ff5965b190242ce05735d7c072c11565c5bd8609261c83dd06396ae8416dfbaa","tests/ui-msrv/transmute-mut-size-decrease.rs":"51aa423ec51a3c5579bbd7bac33adac8040629adc94eec3fb84825ef4f84f7bb","tests/ui-msrv/transmute-mut-size-decrease.stderr":"ae0c86cfbd85107ea908218c5389218a64a46ccf53a0bc553b9c17b48f475e0f","tests/ui-msrv/transmute-mut-size-increase.rs":"ecc34f87b2ec668338672be6bac82b4056ebe35d98fd5d9a210f43f7e866b8e1","tests/ui-msrv/transmute-mut-size-increase.stderr":"d8f4c9f85c59cf24f88e08b3e67796d1218a512e0082100bb63fe38a69186484","tests/ui-msrv/transmute-mut-src-dst-generic.rs":"613e00a353d1b359b57450bb408da585528f84b7eaf039a0c8d86bde1803395f","tests/ui-msrv/transmute-mut-src-dst-generic.stderr":"ec064415b76e341316de3886f3222ab826c2621ea641eb62285b1814369f48c2","tests/ui-msrv/transmute-mut-src-dst-not-references.rs":"0b73d42fbcecba3483e24d4e9296d24d551de18822b45120e225356c5ccefad8","tests/ui-msrv/transmute-mut-src-dst-not-references.stderr":"fc2740d55afdb07bdde457ac259f48ef5b3e13503968299e51791576328b207d","tests/ui-msrv/transmute-mut-src-dst-unsized.rs":"8ccf11a1990dbfd7ed7180c5e73e3a278f072f0a86eb2810f1b2c737ece76c57","tests/ui-msrv/transmute-mut-src-dst-unsized.stderr":"a47a39be560a9a80a31ebd6ee30178f2e375e9450c61a86effb3611f654e302c","tests/ui-msrv/transmute-mut-src-generic.rs":"2cfe526643436df07247cc2583e1d097b247411185952132433127a159527669","tests/ui-msrv/transmute-mut-src-generic.stderr":"a7588c104a34936839fdef78029fdc3929f08f6befac2a94ef5fce5364cd89ca","tests/ui-msrv/transmute-mut-src-immutable.rs":"606aba0c01726255c9be7e67a032ce854209c62dffec16d5dd2c8f484e19979a","tests/ui-msrv/transmute-mut-src-immutable.stderr":"6854b18881116cecf0c716eac01aac312bfe43a295a797c4ad01ac8b7ea7d81c","tests/ui-msrv/transmute-mut-src-not-a-reference.rs":"e627a60c6f6d1b398bdcfc9307dbc57b268cc784b4967d1afaceed7eebd5db47","tests/ui-msrv/transmute-mut-src-not-a-reference.stderr":"538af460b18f588b6075307de50ba1307f98189d2f2aea74346a77ad8b64710c","tests/ui-msrv/transmute-mut-src-not-asbytes.rs":"d0a6ddcfe31ac34ccc550090b80a67a010202bee12a39c230dd4374ef81a520c","tests/ui-msrv/transmute-mut-src-not-asbytes.stderr":"446ab2326cedeae89bd951561206dddcb546684629b12e46e3de1025caa7c894","tests/ui-msrv/transmute-mut-src-not-frombytes.rs":"5866e7d74baf3efb500338ba91a76f221e4a2479376e6921ec831fa284c9b3db","tests/ui-msrv/transmute-mut-src-not-frombytes.stderr":"659915278b39092444f82347fbd62d4bd0c12cecb1d5976159b3fd90c8b995f2","tests/ui-msrv/transmute-mut-src-unsized.rs":"6676d8f29f0a32418f86d4423c464f4e0fdb8fe9ee8aa87f86c5fcdf8bd5e197","tests/ui-msrv/transmute-mut-src-unsized.stderr":"7f9a60f0bafa5d59403e49f2a6b68a56fa2be6c2a62d785fe4cb51bc056159cc","tests/ui-msrv/transmute-ptr-to-usize.rs":"ea33dc39115509988d9abd6ac6536d88d82082417b21da9f9bc8cf8369c69618","tests/ui-msrv/transmute-ptr-to-usize.stderr":"e8713417a977f07158a58aec6690c3a79b49cf5edb9e66f6c1d218a1a55f47eb","tests/ui-msrv/transmute-ref-alignment-increase.rs":"a5028469f90ca572ec1c73131f9a8a0a1cbca47de0dcb9003ba98de378def783","tests/ui-msrv/transmute-ref-alignment-increase.stderr":"2c56277ab280ac4477ccd3ca4c48ac60e096a95579bfea58da81d9082d8ab499","tests/ui-msrv/transmute-ref-dst-generic.rs":"4a6b56491fd59646d1d1d8edbcc9d7de0dc69a9e6e4779f3cfd90e287f11557c","tests/ui-msrv/transmute-ref-dst-generic.stderr":"8f47f9eabb44e8d5c561359237e79d42a998b615b526666e16db325b9cea8a09","tests/ui-msrv/transmute-ref-dst-mutable.rs":"1c48caae9912f70dec5f5a99a0c880fe6a3022f11fd412438b8a1576803e5f73","tests/ui-msrv/transmute-ref-dst-mutable.stderr":"289e040b3e725546081dfd07640e499a5622915954f12c871708d3f46ff43d7a","tests/ui-msrv/transmute-ref-dst-not-a-reference.rs":"c4b8a6c1970e30390d0a301e2dbe718b9eeef743299f7e91cd12c582ec203af7","tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr":"b6c1f2aede85cce47f5ca379b9ae5a77c777e7c60de6590578c47432ebacae88","tests/ui-msrv/transmute-ref-dst-not-frombytes.rs":"42aab9630fbab93f400713a1730d6dd6a89f821b0fa4dd5347aabe5e78b13aff","tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr":"00b6c3472c0f84f4e32217c1c839c0eab1bf449abbc8bb8f60878ce62c360c8b","tests/ui-msrv/transmute-ref-dst-unsized.rs":"c374df8d00541fd34fff37e231e341501a427961f60d88ad3e3c375085cc060d","tests/ui-msrv/transmute-ref-dst-unsized.stderr":"73636b1d142730f1330753c3fa14c88a32a23bf1c0741503b99610a506a8f66b","tests/ui-msrv/transmute-ref-illegal-lifetime.rs":"6812bbf7ec851a8591464f10864dbd1f225e65ed5793b6f6375cbe8a9db50b14","tests/ui-msrv/transmute-ref-illegal-lifetime.stderr":"4f2a3e71cda94564f2343ca9ff23de3eca0d2ff465cedacab187151183813092","tests/ui-msrv/transmute-ref-size-decrease.rs":"939fb562e4678368e59fdafb3a597fd54a661fd09d9ecb23c6e626ff59b45384","tests/ui-msrv/transmute-ref-size-decrease.stderr":"686597597e9f87e717b702bf6b8b6a52d14c5612ec267d48a01b442ab14648e1","tests/ui-msrv/transmute-ref-size-increase.rs":"f66ab294f7618abfac5c503570137759afceb0dd26c8802bb1786b8873fe5670","tests/ui-msrv/transmute-ref-size-increase.stderr":"f1ad62609362a24b5cf47761e30e2cf0a35db82682e041faf251b2a1f822da7c","tests/ui-msrv/transmute-ref-src-dst-generic.rs":"96a6f6580307e6a397af8ca688a8a65144dff5240372203bd9f02bad6a41fd1e","tests/ui-msrv/transmute-ref-src-dst-generic.stderr":"ca3c1493cbab64b5af7c3c4ea88ca16f6bb2478865b0dbe9d4a28d3b11d5fad1","tests/ui-msrv/transmute-ref-src-dst-not-references.rs":"7311602a0153b260d819e9608e8e66ef5904919a2349a95187919d8211e48e23","tests/ui-msrv/transmute-ref-src-dst-not-references.stderr":"003bb1ccb5cf8322416e00e0fa5645f94d76aad875e60d281daae9625eb583a4","tests/ui-msrv/transmute-ref-src-dst-unsized.rs":"f83e0225e824b7526d7732ef5d759b32358e5db50c3c6a318d2b5dcc2eb3c707","tests/ui-msrv/transmute-ref-src-dst-unsized.stderr":"558be2a5b90f3b3a304d5ae94ed3f7cd369e1e0ad03991ff57500913232ea8de","tests/ui-msrv/transmute-ref-src-generic.rs":"ac1699aeca61c82aff5dac51d387a4ef7522faf2b2dfc56af398a2dc9d53745b","tests/ui-msrv/transmute-ref-src-generic.stderr":"2ba4f5f66b2a2eae90f2cb4b28bb92b066fcaf17412ca777e7d9823697d64736","tests/ui-msrv/transmute-ref-src-not-a-reference.rs":"a921f168fa6cb3c6a19894cecdb118bc3164275746672a916aa5194b92f2fb57","tests/ui-msrv/transmute-ref-src-not-a-reference.stderr":"5a8d829089820ec79d9cd8d9ffac7dbde430914fdad691d46edcd96414d5cad0","tests/ui-msrv/transmute-ref-src-not-asbytes.rs":"09aabae9e4634a5432bf7225240954d7b0592994c97a927e0469e27854588232","tests/ui-msrv/transmute-ref-src-not-asbytes.stderr":"bbd65ef7225a7a39f8c53362a1f137a6b294227b0d2b658fa8082742cda4a8bf","tests/ui-msrv/transmute-ref-src-unsized.rs":"d7797488f0ab5db89944ac7db25625c63aef72e6e4ed481d00a083449050b813","tests/ui-msrv/transmute-ref-src-unsized.stderr":"68537a0c14f72addd12d9e2a75f1a965e730a7ee8da04303402ecd69fe6de95e","tests/ui-msrv/transmute-size-decrease.rs":"c63dd10ddab58e282b033132d79fd21e80edb0c654f856679237977f62ced1ed","tests/ui-msrv/transmute-size-decrease.stderr":"978a9600a42a75fb33e46d10ac1485ef7c0a26054d15e52ec7e13023780d919e","tests/ui-msrv/transmute-size-increase.rs":"9413442e6e3c574bd7e36e8d4242000c1513624a4edc97567695a81b5851c491","tests/ui-msrv/transmute-size-increase.stderr":"168c9bb1045d125b069859d88132b7855a161e1353e1ff3d3f0bfcb70a831128","tests/ui-msrv/transmute-src-not-asbytes.rs":"8e2a76d99734c0502ba9daa8c7c2e34ca830ffd6024d3f7f29363d4263e89f74","tests/ui-msrv/transmute-src-not-asbytes.stderr":"e5913ff39e19e7f38b7aebe19f1930810c898d34fb7e7815c1404eff715f0414","tests/ui-nightly/include_value_not_from_bytes.rs":"ea2a419e0c7ce12b4febe6139523184cba2b2c54c879177e0c58a5f78f0ec340","tests/ui-nightly/include_value_not_from_bytes.stderr":"ca8e43f83feaf9210369fe37b2d31cacac7839e9bdd073aa6bcdc4bf11a88354","tests/ui-nightly/include_value_wrong_size.rs":"418e8c86ebf5a28ee50bd6ae00550f62a7a0ef3a7e7fda965b3d2337b64f2c66","tests/ui-nightly/include_value_wrong_size.stderr":"2b340b79ab4de286609aa5bf561c550ac3f30818df34bc659b54a58f4565501b","tests/ui-nightly/invalid-impls/invalid-impls.rs":"474d843ad40f3936adcd3ff592d815d8169813962ab9d99a68348b4b91aef10e","tests/ui-nightly/invalid-impls/invalid-impls.stderr":"0666e32657fa5f7292c62f34c0178c8dc442c53cf6f4d795894684b3e7b3e570","tests/ui-nightly/max-align.rs":"ffcb6687c98e5629d01b17cbd0845ec195007cc39aa244b26a77d17688c8f13d","tests/ui-nightly/max-align.stderr":"c346c1cbc54039a3fc7d8b69bce45d7306d16ca3b0092fcea478306171cf1318","tests/ui-nightly/transmute-dst-not-frombytes.rs":"e00251eae67cdf8267a4963f212857a2a51de640a6f856c4b8df2a953caad25a","tests/ui-nightly/transmute-dst-not-frombytes.stderr":"046d7e096f089ede594d360a36a9c1ab9f6e456576218fee3c9781169bf3adc4","tests/ui-nightly/transmute-mut-alignment-increase.rs":"ba83c9cf01acf11352f7ee5b54cd73a451394fd78b8ddeb0637931c87adfd6ae","tests/ui-nightly/transmute-mut-alignment-increase.stderr":"db521ff9c180434136b0e8421823435be8ed23c7ac85d9a83c479ad1b8153281","tests/ui-nightly/transmute-mut-const.rs":"4227f4c0dda6d6128f41b209ecc2bf941c7659c8de84cc0e418862d279baa78f","tests/ui-nightly/transmute-mut-const.stderr":"3d84712235a0e819e0286ddfccbf771cf3d4b03c944eb2794b75555499b3295f","tests/ui-nightly/transmute-mut-dst-generic.rs":"aa015679b75dac0c37d5c43782b5e9522257f6ba34a10a89d0c1eba524a7af5c","tests/ui-nightly/transmute-mut-dst-generic.stderr":"d012039fa54f3d7cc8ee7275637964e7d83f8067545260676326b571bca46617","tests/ui-nightly/transmute-mut-dst-not-a-reference.rs":"5d784ab588f081bfc304501f811a85ea2662f88fff8274ccbd53172ec255212c","tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr":"9d21ae45aff909bf6e6feca6c60fae8db1e4318935aede558bee1e243ede59f8","tests/ui-nightly/transmute-mut-dst-not-asbytes.rs":"b1f986b3433980d7572a80511ca5a758c91e0c761d01c50bc73ed025d45698a6","tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr":"5d77d9085413d8cea2572b574e882b7894898c2ec771059ff2b0e5f6acd11ca7","tests/ui-nightly/transmute-mut-dst-not-frombytes.rs":"a4353eeb67b4701908e694738c5c4ce965afe4432f14e00e740684352f5ddd30","tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr":"6d4f31f9698099bf52e45debdbaafd4ae85fb74c353d3d76c20fdb6414ea7a9b","tests/ui-nightly/transmute-mut-dst-unsized.rs":"58c3423c07dd06ca98e61439f318ba5f3f7fc68ca9cb59371ebc482ad54709db","tests/ui-nightly/transmute-mut-dst-unsized.stderr":"0df79b2009b5f8d237d81957b5fbaa04181de59306ba2fe77027081592f4c6d9","tests/ui-nightly/transmute-mut-illegal-lifetime.rs":"ec18bf7b3d9bd2674b43d0e04fc0545227473d43b07e2bbccc19c2068df33673","tests/ui-nightly/transmute-mut-illegal-lifetime.stderr":"b0379252732ca51314077fa20d3fb4bfcbee61f486229547c807ed0d7dede9c8","tests/ui-nightly/transmute-mut-size-decrease.rs":"51aa423ec51a3c5579bbd7bac33adac8040629adc94eec3fb84825ef4f84f7bb","tests/ui-nightly/transmute-mut-size-decrease.stderr":"9294c2562503924704673967f93afbfd4b1d84abbf76318636105acdc3f37a63","tests/ui-nightly/transmute-mut-size-increase.rs":"ecc34f87b2ec668338672be6bac82b4056ebe35d98fd5d9a210f43f7e866b8e1","tests/ui-nightly/transmute-mut-size-increase.stderr":"6858e39d6238843faa0ec4bf199f88d5013f1b50a811f5e882837f01eea00f93","tests/ui-nightly/transmute-mut-src-dst-generic.rs":"613e00a353d1b359b57450bb408da585528f84b7eaf039a0c8d86bde1803395f","tests/ui-nightly/transmute-mut-src-dst-generic.stderr":"f6a7bb45e58bf80a25a4e694e881f9c38f2a5d33817d9337d41a6d2c2aef93e8","tests/ui-nightly/transmute-mut-src-dst-not-references.rs":"0b73d42fbcecba3483e24d4e9296d24d551de18822b45120e225356c5ccefad8","tests/ui-nightly/transmute-mut-src-dst-not-references.stderr":"0e1e17242ec0b1e9052087b18ccdde9fa117e430a3675b624c49d36eb933ee88","tests/ui-nightly/transmute-mut-src-dst-unsized.rs":"8ccf11a1990dbfd7ed7180c5e73e3a278f072f0a86eb2810f1b2c737ece76c57","tests/ui-nightly/transmute-mut-src-dst-unsized.stderr":"608ed4e9d52c8c52773afea6565c42e30d8c6791c8a8d929235eb0bdcd9db1a6","tests/ui-nightly/transmute-mut-src-generic.rs":"2cfe526643436df07247cc2583e1d097b247411185952132433127a159527669","tests/ui-nightly/transmute-mut-src-generic.stderr":"3c54bad3b3ab88b5c046bfb6ef79e0162ec7228447a1ba8321d9da754d536f20","tests/ui-nightly/transmute-mut-src-immutable.rs":"606aba0c01726255c9be7e67a032ce854209c62dffec16d5dd2c8f484e19979a","tests/ui-nightly/transmute-mut-src-immutable.stderr":"d99fc596f5732e5a4b193028812e047ba0c748017a94fd55d4f7802849159359","tests/ui-nightly/transmute-mut-src-not-a-reference.rs":"e627a60c6f6d1b398bdcfc9307dbc57b268cc784b4967d1afaceed7eebd5db47","tests/ui-nightly/transmute-mut-src-not-a-reference.stderr":"3085a0120d3dcbc1d01d226e0b4235fe39da9a956444aabdedac9ec938aca609","tests/ui-nightly/transmute-mut-src-not-asbytes.rs":"d0a6ddcfe31ac34ccc550090b80a67a010202bee12a39c230dd4374ef81a520c","tests/ui-nightly/transmute-mut-src-not-asbytes.stderr":"7cd91c207adb2b3bc9d2f3f5eaa2409f6290c429eb393533676f9f7628420623","tests/ui-nightly/transmute-mut-src-not-frombytes.rs":"5866e7d74baf3efb500338ba91a76f221e4a2479376e6921ec831fa284c9b3db","tests/ui-nightly/transmute-mut-src-not-frombytes.stderr":"95f362f717bbed7501d9e328b6369a76a4b10c167e062272e64a1b8887669114","tests/ui-nightly/transmute-mut-src-unsized.rs":"6676d8f29f0a32418f86d4423c464f4e0fdb8fe9ee8aa87f86c5fcdf8bd5e197","tests/ui-nightly/transmute-mut-src-unsized.stderr":"9ac64e0b1c4afe6fe4bc20e63f7c22e89d596377212ac3c3ebf87ea12096818a","tests/ui-nightly/transmute-ptr-to-usize.rs":"ea33dc39115509988d9abd6ac6536d88d82082417b21da9f9bc8cf8369c69618","tests/ui-nightly/transmute-ptr-to-usize.stderr":"f05ba5ad01e235eed456686a1ee5b7a668495c38054155965846d2bd613bd7d8","tests/ui-nightly/transmute-ref-alignment-increase.rs":"a5028469f90ca572ec1c73131f9a8a0a1cbca47de0dcb9003ba98de378def783","tests/ui-nightly/transmute-ref-alignment-increase.stderr":"aef92964ba843b890ce6c6b0924726dd89e1b9d6513f2148c269fe8fa203adac","tests/ui-nightly/transmute-ref-dst-generic.rs":"4a6b56491fd59646d1d1d8edbcc9d7de0dc69a9e6e4779f3cfd90e287f11557c","tests/ui-nightly/transmute-ref-dst-generic.stderr":"06b9fcf8e0443f997c0ef5f8e2659afcb65f095b11162ea69488f89788b337a7","tests/ui-nightly/transmute-ref-dst-mutable.rs":"1c48caae9912f70dec5f5a99a0c880fe6a3022f11fd412438b8a1576803e5f73","tests/ui-nightly/transmute-ref-dst-mutable.stderr":"96d38ce9a807ad7b60a846a8f5558c447da0d6cbe9225a077df4997712424d9a","tests/ui-nightly/transmute-ref-dst-not-a-reference.rs":"c4b8a6c1970e30390d0a301e2dbe718b9eeef743299f7e91cd12c582ec203af7","tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr":"8ed2540877865fcdfca6e150465996a8f2872eb122ed5d647825e9181ae64754","tests/ui-nightly/transmute-ref-dst-not-frombytes.rs":"42aab9630fbab93f400713a1730d6dd6a89f821b0fa4dd5347aabe5e78b13aff","tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr":"ab474a92c39a0810796d51228db2340a4d52915ddbae72a77ac4962e8bf9604e","tests/ui-nightly/transmute-ref-dst-unsized.rs":"c374df8d00541fd34fff37e231e341501a427961f60d88ad3e3c375085cc060d","tests/ui-nightly/transmute-ref-dst-unsized.stderr":"fc2579bc6b9f6fff8b2092fff88d617c98e218ae1399b39dea80d9d71c6112f7","tests/ui-nightly/transmute-ref-illegal-lifetime.rs":"6812bbf7ec851a8591464f10864dbd1f225e65ed5793b6f6375cbe8a9db50b14","tests/ui-nightly/transmute-ref-illegal-lifetime.stderr":"cb98c1b304334e58fc61be1c4b7782e68ab92d90a44c9627326d94d14a44cc38","tests/ui-nightly/transmute-ref-size-decrease.rs":"939fb562e4678368e59fdafb3a597fd54a661fd09d9ecb23c6e626ff59b45384","tests/ui-nightly/transmute-ref-size-decrease.stderr":"14f6ea48e66c484e94f47c3af0983de06869a884cda19b2201548aadc2378758","tests/ui-nightly/transmute-ref-size-increase.rs":"f66ab294f7618abfac5c503570137759afceb0dd26c8802bb1786b8873fe5670","tests/ui-nightly/transmute-ref-size-increase.stderr":"d5777c69b0ee36b6dcaf7699abb3ea03e1a8bac17bb5a1d4059ae28ff5f4357f","tests/ui-nightly/transmute-ref-src-dst-generic.rs":"96a6f6580307e6a397af8ca688a8a65144dff5240372203bd9f02bad6a41fd1e","tests/ui-nightly/transmute-ref-src-dst-generic.stderr":"ebffb5c5318798ff84f1da69c3ba732b9af2ad3688ebd7b4b2770e2b201afccb","tests/ui-nightly/transmute-ref-src-dst-not-references.rs":"7311602a0153b260d819e9608e8e66ef5904919a2349a95187919d8211e48e23","tests/ui-nightly/transmute-ref-src-dst-not-references.stderr":"ca5b956d99998df493f7c72df6bd315b8cd6f1f9b113a45416b0088f1e368900","tests/ui-nightly/transmute-ref-src-dst-unsized.rs":"f83e0225e824b7526d7732ef5d759b32358e5db50c3c6a318d2b5dcc2eb3c707","tests/ui-nightly/transmute-ref-src-dst-unsized.stderr":"35f3ce0a3c11aa4ac6eb65a48089e0025e85fc016ae81566be57e4a1152dac2f","tests/ui-nightly/transmute-ref-src-generic.rs":"ac1699aeca61c82aff5dac51d387a4ef7522faf2b2dfc56af398a2dc9d53745b","tests/ui-nightly/transmute-ref-src-generic.stderr":"b53a09eca6226647cf53ee9bd0388e558def3bd1f8009b6ec74cc26e4db13d1c","tests/ui-nightly/transmute-ref-src-not-a-reference.rs":"a921f168fa6cb3c6a19894cecdb118bc3164275746672a916aa5194b92f2fb57","tests/ui-nightly/transmute-ref-src-not-a-reference.stderr":"f7b51be513a0603070e218bdd1ca2c47a94c58151ab5649f68877ea3d83268f4","tests/ui-nightly/transmute-ref-src-not-asbytes.rs":"09aabae9e4634a5432bf7225240954d7b0592994c97a927e0469e27854588232","tests/ui-nightly/transmute-ref-src-not-asbytes.stderr":"fdc888ef7f049c957bd000c321979f9b61008a1b1ba8dabf323e33676f7de030","tests/ui-nightly/transmute-ref-src-unsized.rs":"d7797488f0ab5db89944ac7db25625c63aef72e6e4ed481d00a083449050b813","tests/ui-nightly/transmute-ref-src-unsized.stderr":"7e874cb32d41946e2e49627fd64b6e0103d65c955a44ccf18edf184312edb68b","tests/ui-nightly/transmute-size-decrease.rs":"c63dd10ddab58e282b033132d79fd21e80edb0c654f856679237977f62ced1ed","tests/ui-nightly/transmute-size-decrease.stderr":"4e014a129866804cf91cc3ff7a8ad1044ae1e3a6aad3b6ff8839605ab1b1df77","tests/ui-nightly/transmute-size-increase.rs":"9413442e6e3c574bd7e36e8d4242000c1513624a4edc97567695a81b5851c491","tests/ui-nightly/transmute-size-increase.stderr":"c307d7a2ae3d18e016be5d77e720bcf7023d03b10bb3ff3190e4d934eb9fc6a7","tests/ui-nightly/transmute-src-not-asbytes.rs":"8e2a76d99734c0502ba9daa8c7c2e34ca830ffd6024d3f7f29363d4263e89f74","tests/ui-nightly/transmute-src-not-asbytes.stderr":"71938c61511f4746a919b7656dc6181e7f0367e9a97b3693563dc9b53302cb8c","tests/ui-stable/include_value_not_from_bytes.rs":"ea2a419e0c7ce12b4febe6139523184cba2b2c54c879177e0c58a5f78f0ec340","tests/ui-stable/include_value_not_from_bytes.stderr":"5aa78f38cdbd69c99a77cc68331fd0bd4bb0a07fd35e807b2aa35dd4c56e56ee","tests/ui-stable/include_value_wrong_size.rs":"418e8c86ebf5a28ee50bd6ae00550f62a7a0ef3a7e7fda965b3d2337b64f2c66","tests/ui-stable/include_value_wrong_size.stderr":"b4fdeefd36bb2343f4e6cfae39c821fcfefd0671ea59205ffeea48318ce4fac7","tests/ui-stable/invalid-impls/invalid-impls.rs":"474d843ad40f3936adcd3ff592d815d8169813962ab9d99a68348b4b91aef10e","tests/ui-stable/invalid-impls/invalid-impls.stderr":"8310e42b17407faecee6c53a357037485f496783d80d40f5faebbb4b6f8483e8","tests/ui-stable/max-align.rs":"ffcb6687c98e5629d01b17cbd0845ec195007cc39aa244b26a77d17688c8f13d","tests/ui-stable/max-align.stderr":"e33783407e633f7b45980d47192402dde119dd31feeda4bc68822926fcf29c07","tests/ui-stable/transmute-dst-not-frombytes.rs":"e00251eae67cdf8267a4963f212857a2a51de640a6f856c4b8df2a953caad25a","tests/ui-stable/transmute-dst-not-frombytes.stderr":"95f850609dfc88c2e47c6667601da35099a6588a939c8f9ea7f5bd3e2d03d20f","tests/ui-stable/transmute-mut-alignment-increase.rs":"ba83c9cf01acf11352f7ee5b54cd73a451394fd78b8ddeb0637931c87adfd6ae","tests/ui-stable/transmute-mut-alignment-increase.stderr":"92f1cda35d0c41a93f93152ad5c77fcd2c9ae17a7f2b4d54a311d434aa586400","tests/ui-stable/transmute-mut-const.rs":"4227f4c0dda6d6128f41b209ecc2bf941c7659c8de84cc0e418862d279baa78f","tests/ui-stable/transmute-mut-const.stderr":"d27b218da464aee431665618ffb4902e4d1a65e4153d25f05591538bf22cd623","tests/ui-stable/transmute-mut-dst-generic.rs":"aa015679b75dac0c37d5c43782b5e9522257f6ba34a10a89d0c1eba524a7af5c","tests/ui-stable/transmute-mut-dst-generic.stderr":"f2c60a1aae05ad780802b0290989c546abe35adcbcacf83a2264446a40ceb5dd","tests/ui-stable/transmute-mut-dst-not-a-reference.rs":"5d784ab588f081bfc304501f811a85ea2662f88fff8274ccbd53172ec255212c","tests/ui-stable/transmute-mut-dst-not-a-reference.stderr":"16a9cf4e0f90772d19c132f50dd0a85e60ecd929a6aa0820fbf568c7f6183d74","tests/ui-stable/transmute-mut-dst-not-asbytes.rs":"b1f986b3433980d7572a80511ca5a758c91e0c761d01c50bc73ed025d45698a6","tests/ui-stable/transmute-mut-dst-not-asbytes.stderr":"aa3615c19ef50b855a4c2feafa09d7af6e7603649df0337e29ca12d352306452","tests/ui-stable/transmute-mut-dst-not-frombytes.rs":"a4353eeb67b4701908e694738c5c4ce965afe4432f14e00e740684352f5ddd30","tests/ui-stable/transmute-mut-dst-not-frombytes.stderr":"5625f642d278fd6617472ba06aa8dda9a78899223ff3b04734060996d5dd67f2","tests/ui-stable/transmute-mut-dst-unsized.rs":"58c3423c07dd06ca98e61439f318ba5f3f7fc68ca9cb59371ebc482ad54709db","tests/ui-stable/transmute-mut-dst-unsized.stderr":"8cad3c8812e78b21667b6b885c3e4c5da025a154ea519f5539e9688802bb2ec4","tests/ui-stable/transmute-mut-illegal-lifetime.rs":"ec18bf7b3d9bd2674b43d0e04fc0545227473d43b07e2bbccc19c2068df33673","tests/ui-stable/transmute-mut-illegal-lifetime.stderr":"3a43e0be32ef3589fe3fa713d387bd3976bd8c75813f9641bbf7c539e10bed41","tests/ui-stable/transmute-mut-size-decrease.rs":"51aa423ec51a3c5579bbd7bac33adac8040629adc94eec3fb84825ef4f84f7bb","tests/ui-stable/transmute-mut-size-decrease.stderr":"b63870c4361917d4cd19fbaba433a9389b806135c9576ae8997c86f3b763fe3c","tests/ui-stable/transmute-mut-size-increase.rs":"ecc34f87b2ec668338672be6bac82b4056ebe35d98fd5d9a210f43f7e866b8e1","tests/ui-stable/transmute-mut-size-increase.stderr":"cb086ebcc60c4e17f8897c62c5b36b110b259c6e970825953798daf37144af47","tests/ui-stable/transmute-mut-src-dst-generic.rs":"613e00a353d1b359b57450bb408da585528f84b7eaf039a0c8d86bde1803395f","tests/ui-stable/transmute-mut-src-dst-generic.stderr":"ff7758361ba41d2bc3a49e9942e9f1f1b76d245f19a5391e45b9a066b8d0f6f4","tests/ui-stable/transmute-mut-src-dst-not-references.rs":"0b73d42fbcecba3483e24d4e9296d24d551de18822b45120e225356c5ccefad8","tests/ui-stable/transmute-mut-src-dst-not-references.stderr":"830581700736527e224bd923da3cd9c215e68556d2379c678174c08eff1501d6","tests/ui-stable/transmute-mut-src-dst-unsized.rs":"8ccf11a1990dbfd7ed7180c5e73e3a278f072f0a86eb2810f1b2c737ece76c57","tests/ui-stable/transmute-mut-src-dst-unsized.stderr":"b8a4632d0ba4229231cd30e8af07bb25dfc3cf1235ebbeb7a62e2ec71ebbef3a","tests/ui-stable/transmute-mut-src-generic.rs":"2cfe526643436df07247cc2583e1d097b247411185952132433127a159527669","tests/ui-stable/transmute-mut-src-generic.stderr":"de709f4435bf09ce98a6a9b19ac69560f85c43b665277ef60c9e62169e4a001f","tests/ui-stable/transmute-mut-src-immutable.rs":"606aba0c01726255c9be7e67a032ce854209c62dffec16d5dd2c8f484e19979a","tests/ui-stable/transmute-mut-src-immutable.stderr":"7c24d82d943695955b3ec1f0a53a349645fd3de1d549f3be989532e3774279bf","tests/ui-stable/transmute-mut-src-not-a-reference.rs":"e627a60c6f6d1b398bdcfc9307dbc57b268cc784b4967d1afaceed7eebd5db47","tests/ui-stable/transmute-mut-src-not-a-reference.stderr":"29b09aea59cfdb4b6535c5d33ec803539f28e53cce81938767ea0c22a1b1ce7d","tests/ui-stable/transmute-mut-src-not-asbytes.rs":"d0a6ddcfe31ac34ccc550090b80a67a010202bee12a39c230dd4374ef81a520c","tests/ui-stable/transmute-mut-src-not-asbytes.stderr":"51daf0724583595017b758d5881e10af3a07f07ce4b03754a909849561125509","tests/ui-stable/transmute-mut-src-not-frombytes.rs":"5866e7d74baf3efb500338ba91a76f221e4a2479376e6921ec831fa284c9b3db","tests/ui-stable/transmute-mut-src-not-frombytes.stderr":"83d60a22c5df81aef9a02033c5a4f097acc0338bde8b380dc053cc422333f8ba","tests/ui-stable/transmute-mut-src-unsized.rs":"6676d8f29f0a32418f86d4423c464f4e0fdb8fe9ee8aa87f86c5fcdf8bd5e197","tests/ui-stable/transmute-mut-src-unsized.stderr":"af53ab7b9b5edd17c9857459cbaf9636a2363196820fc998c4de81ede75ec441","tests/ui-stable/transmute-ptr-to-usize.rs":"ea33dc39115509988d9abd6ac6536d88d82082417b21da9f9bc8cf8369c69618","tests/ui-stable/transmute-ptr-to-usize.stderr":"cba0e2d85a961b56d8fc2566bc555082b52f762ac36b9745e319bb5d1e726514","tests/ui-stable/transmute-ref-alignment-increase.rs":"a5028469f90ca572ec1c73131f9a8a0a1cbca47de0dcb9003ba98de378def783","tests/ui-stable/transmute-ref-alignment-increase.stderr":"514c5254a0e84051cb34bd700c08163a98195730b87e67acda8907d401311b6c","tests/ui-stable/transmute-ref-dst-generic.rs":"4a6b56491fd59646d1d1d8edbcc9d7de0dc69a9e6e4779f3cfd90e287f11557c","tests/ui-stable/transmute-ref-dst-generic.stderr":"0fa2e50dd2f259260511ae3534334420e4384d542daa8532c7d3a625652c2ada","tests/ui-stable/transmute-ref-dst-mutable.rs":"1c48caae9912f70dec5f5a99a0c880fe6a3022f11fd412438b8a1576803e5f73","tests/ui-stable/transmute-ref-dst-mutable.stderr":"fc83b5283cb5319fd7a2b79f94ed0a49f16bce5b222f7e1cc5ce5a879f3de650","tests/ui-stable/transmute-ref-dst-not-a-reference.rs":"c4b8a6c1970e30390d0a301e2dbe718b9eeef743299f7e91cd12c582ec203af7","tests/ui-stable/transmute-ref-dst-not-a-reference.stderr":"e8a126f4832344b8a69591fcc25e22bbbb29f2078b809a47f8afa40ac1087a1f","tests/ui-stable/transmute-ref-dst-not-frombytes.rs":"42aab9630fbab93f400713a1730d6dd6a89f821b0fa4dd5347aabe5e78b13aff","tests/ui-stable/transmute-ref-dst-not-frombytes.stderr":"fb34ebeba63588a4f81763ea0363d4c5501b2dc1452bd5e8334c8fe009b420ae","tests/ui-stable/transmute-ref-dst-unsized.rs":"c374df8d00541fd34fff37e231e341501a427961f60d88ad3e3c375085cc060d","tests/ui-stable/transmute-ref-dst-unsized.stderr":"6024b682bfe79f7d972094f4f77bda7f8ed40f8949e14594a1d20f1fb8389c42","tests/ui-stable/transmute-ref-illegal-lifetime.rs":"6812bbf7ec851a8591464f10864dbd1f225e65ed5793b6f6375cbe8a9db50b14","tests/ui-stable/transmute-ref-illegal-lifetime.stderr":"45ab741d710dc5a01a21ab64f99927e7da5593328b2037b9bc82a87bc0969136","tests/ui-stable/transmute-ref-size-decrease.rs":"939fb562e4678368e59fdafb3a597fd54a661fd09d9ecb23c6e626ff59b45384","tests/ui-stable/transmute-ref-size-decrease.stderr":"fec5ab0e3d885bbb8e7ab82d6d58b9b4ee35a1802502fbc494bafa086d4132cf","tests/ui-stable/transmute-ref-size-increase.rs":"f66ab294f7618abfac5c503570137759afceb0dd26c8802bb1786b8873fe5670","tests/ui-stable/transmute-ref-size-increase.stderr":"720e2150c9ed538cf00d7525124ab0cee6ac53e91582470e09c140db783fc2be","tests/ui-stable/transmute-ref-src-dst-generic.rs":"96a6f6580307e6a397af8ca688a8a65144dff5240372203bd9f02bad6a41fd1e","tests/ui-stable/transmute-ref-src-dst-generic.stderr":"25f15e5316df34cd4a438548090c287228f86062f7e2ef59ea17fb727b868a19","tests/ui-stable/transmute-ref-src-dst-not-references.rs":"7311602a0153b260d819e9608e8e66ef5904919a2349a95187919d8211e48e23","tests/ui-stable/transmute-ref-src-dst-not-references.stderr":"2bff9f290ec40458939a1633f850853b3486220cfd40bc24c4e52635b7455742","tests/ui-stable/transmute-ref-src-dst-unsized.rs":"f83e0225e824b7526d7732ef5d759b32358e5db50c3c6a318d2b5dcc2eb3c707","tests/ui-stable/transmute-ref-src-dst-unsized.stderr":"80f9b39173dee338d3d7997d1283772b963e211dd6f14cfe37affc23520f7263","tests/ui-stable/transmute-ref-src-generic.rs":"ac1699aeca61c82aff5dac51d387a4ef7522faf2b2dfc56af398a2dc9d53745b","tests/ui-stable/transmute-ref-src-generic.stderr":"f3f8a7ee67ebec21169e1284c9eeaedcfa7b93c05f4e42c504cbd06508f34f9f","tests/ui-stable/transmute-ref-src-not-a-reference.rs":"a921f168fa6cb3c6a19894cecdb118bc3164275746672a916aa5194b92f2fb57","tests/ui-stable/transmute-ref-src-not-a-reference.stderr":"52efb101d85126138395fbed84c7cb911f86ea4457b991d91b2b6ec66521bcff","tests/ui-stable/transmute-ref-src-not-asbytes.rs":"09aabae9e4634a5432bf7225240954d7b0592994c97a927e0469e27854588232","tests/ui-stable/transmute-ref-src-not-asbytes.stderr":"543d5e4cced8f4d9f702a95d039579e121137ae2abfe2dad3da4692b8a43c1f0","tests/ui-stable/transmute-ref-src-unsized.rs":"d7797488f0ab5db89944ac7db25625c63aef72e6e4ed481d00a083449050b813","tests/ui-stable/transmute-ref-src-unsized.stderr":"228c5e4531cb5b8e33602dc58e9e0356a04de2946e17fbb206624f187ec86730","tests/ui-stable/transmute-size-decrease.rs":"c63dd10ddab58e282b033132d79fd21e80edb0c654f856679237977f62ced1ed","tests/ui-stable/transmute-size-decrease.stderr":"685acfb1b758f9854a5b36565f0b26cc1ef35322ee25387f05733187de1864d1","tests/ui-stable/transmute-size-increase.rs":"9413442e6e3c574bd7e36e8d4242000c1513624a4edc97567695a81b5851c491","tests/ui-stable/transmute-size-increase.stderr":"54cf03066a5d10ab7caa4741fe9d40df491a9a3fb81b6425a40bf04e21a6910e","tests/ui-stable/transmute-src-not-asbytes.rs":"8e2a76d99734c0502ba9daa8c7c2e34ca830ffd6024d3f7f29363d4263e89f74","tests/ui-stable/transmute-src-not-asbytes.stderr":"022dbcfa9950fe0576a26aecb6b8047740dd580f15491a754e9b95e16e1938da"},"package":"74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"} \ No newline at end of file
diff --git a/third_party/rust/zerocopy/CONTRIBUTING.md b/third_party/rust/zerocopy/CONTRIBUTING.md
new file mode 100644
index 0000000000..929e80996b
--- /dev/null
+++ b/third_party/rust/zerocopy/CONTRIBUTING.md
@@ -0,0 +1,215 @@
+<!-- Copyright 2022 The Fuchsia Authors
+
+Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+This file may not be copied, modified, or distributed except according to
+those terms. -->
+
+# How to Contribute
+
+We'd love to accept your patches and contributions to zerocopy. There are just a
+few small guidelines you need to follow.
+
+Once you've read the rest of this doc, check out our [good-first-issue
+label][good-first-issue] for some good issues you can use to get your toes wet!
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. 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. Head over to <https://cla.developers.google.com/> to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code Reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult [GitHub
+Help][about_pull_requests] for more information on using pull requests.
+
+## Code Guidelines
+
+### Philosophy
+
+This section is inspired by [Flutter's style guide][flutter_philosophy], which
+contains many general principles that you should apply to all your programming
+work. Read it. The below calls out specific aspects that we feel are
+particularly important.
+
+#### Dogfood Your Features
+
+In non-library code, it's often advised to only implement features you need.
+After all, it's hard to correctly design code without a concrete use case to
+guide its design. Since zerocopy is a library, this advice is not as applicable;
+we want our API surface to be featureful and complete even if not every feature
+or method has a known use case. However, the observation that unused code is
+hard to design still holds.
+
+Thus, when designing external-facing features, try to make use of them somehow.
+This could be by using them to implement other features, or it could be by
+writing prototype code which won't actually be checked in anywhere. If you're
+feeling ambitious, you could even add (and check in) a [Cargo
+example][cargo_example] that exercises the new feature.
+
+#### Go Down the Rabbit Hole
+
+You will occasionally encounter behavior that surprises you or seems wrong. It
+probably is! Invest the time to find the root cause - you will either learn
+something, or fix something, and both are worth your time. Do not work around
+behavior you don't understand.
+
+### Avoid Duplication
+
+Avoid duplicating code whenever possible. In cases where existing code is not
+exposed in a manner suitable to your needs, prefer to extract the necessary
+parts into a common dependency.
+
+### Comments
+
+When writing comments, take a moment to consider the future reader of your
+comment. Ensure that your comments are complete sentences with proper grammar
+and punctuation. Note that adding more comments or more verbose comments is not
+always better; for example, avoid comments that repeat the code they're anchored
+on.
+
+Documentation comments should be self-contained; in other words, do not assume
+that the reader is aware of documentation in adjacent files or on adjacent
+structures. Avoid documentation comments on types which describe _instances_ of
+the type; for example, `AddressSet is a set of client addresses.` is a comment
+that describes a field of type `AddressSet`, but the type may be used to hold
+any kind of `Address`, not just a client's.
+
+Phrase your comments to avoid references that might become stale; for example:
+do not mention a variable or type by name when possible (certain doc comments
+are necessary exceptions). Also avoid references to past or future versions of
+or past or future work surrounding the item being documented; explain things
+from first principles rather than making external references (including past
+revisions).
+
+When writing TODOs:
+
+1. Include an issue reference using the format `TODO(#123):`
+1. Phrase the text as an action that is to be taken; it should be possible for
+ another contributor to pick up the TODO without consulting any external
+ sources, including the referenced issue.
+
+### Tests
+
+Much of the code in zerocopy has the property that, if it is buggy, those bugs
+may not cause user code to fail. This makes it extra important to write thorough
+tests, but it also makes it harder to write those tests correctly. Here are some
+guidelines on how to test code in zerocopy:
+1. All code added to zerocopy must include tests that exercise it completely.
+1. Tests must be deterministic. Threaded or time-dependent code, random number
+ generators (RNGs), and communication with external processes are common
+ sources of nondeterminism. See [Write reproducible, deterministic
+ tests][determinism] for tips.
+1. Avoid [change detector tests][change_detector_tests]; tests that are
+ unnecessarily sensitive to changes, especially ones external to the code
+ under test, can hamper feature development and refactoring.
+1. Since we run tests in [Miri][miri], make sure that tests exist which exercise
+ any potential [undefined behavior][undefined_behavior] so that Miri can catch
+ it.
+1. If there's some user code that should be impossible to compile, add a
+ [trybuild test][trybuild] to ensure that it's properly rejected.
+
+### Source Control Best Practices
+
+Commits should be arranged for ease of reading; that is, incidental changes
+such as code movement or formatting changes should be committed separately from
+actual code changes.
+
+Commits should always be focused. For example, a commit could add a feature,
+fix a bug, or refactor code, but not a mixture.
+
+Commits should be thoughtfully sized; avoid overly large or complex commits
+which can be logically separated, but also avoid overly separated commits that
+require code reviews to load multiple commits into their mental working memory
+in order to properly understand how the various pieces fit together.
+
+#### Commit Messages
+
+Commit messages should be _concise_ but self-contained (avoid relying on issue
+references as explanations for changes) and written such that they are helpful
+to people reading in the future (include rationale and any necessary context).
+
+Avoid superfluous details or narrative.
+
+Commit messages should consist of a brief subject line and a separate
+explanatory paragraph in accordance with the following:
+
+1. [Separate subject from body with a blank line](https://chris.beams.io/posts/git-commit/#separate)
+1. [Limit the subject line to 50 characters](https://chris.beams.io/posts/git-commit/#limit-50)
+1. [Capitalize the subject line](https://chris.beams.io/posts/git-commit/#capitalize)
+1. [Do not end the subject line with a period](https://chris.beams.io/posts/git-commit/#end)
+1. [Use the imperative mood in the subject line](https://chris.beams.io/posts/git-commit/#imperative)
+1. [Wrap the body at 72 characters](https://chris.beams.io/posts/git-commit/#wrap-72)
+1. [Use the body to explain what and why vs. how](https://chris.beams.io/posts/git-commit/#why-not-how)
+
+If the code affects a particular subsystem, prefix the subject line with the
+name of that subsystem in square brackets, omitting any "zerocopy" prefix
+(that's implicit). For example, for a commit adding a feature to the
+zerocopy-derive crate:
+
+```text
+[derive] Support AsBytes on types with parameters
+```
+
+The body may be omitted if the subject is self-explanatory; e.g. when fixing a
+typo. The git book contains a [Commit Guidelines][commit_guidelines] section
+with much of the same advice, and the list above is part of a [blog
+post][beams_git_commit] by [Chris Beams][chris_beams].
+
+Commit messages should make use of issue integration. Including an issue
+reference like `#123` will cause the GitHub UI to link the text of that
+reference to the referenced issue, and will also make it so that the referenced
+issue back-links to the commit. Use "Closes", "Fixes", or "Resolves" on its own
+line to automatically close an issue when your commit is merged:
+
+```text
+Closes #123
+Fixes #123
+Resolves #123
+```
+
+When using issue integration, don't omit necessary context that may also be
+included in the relevant issue (see "Commit messages should be _concise_ but
+self-contained" above). Git history is more likely to be retained indefinitely
+than issue history (for example, if this repository is migrated away from GitHub
+at some point in the future).
+
+Commit messages should never contain references to any of:
+
+1. Relative moments in time
+1. Non-public URLs
+1. Individuals
+1. Hosted code reviews (such as on https://github.com/google/zerocopy/pulls)
+ + Refer to commits in this repository by their SHA-1 hash
+ + Refer to commits in other repositories by public web address (such as
+ https://github.com/google/zerocopy/commit/789b3deb)
+1. Other entities which may not make sense to arbitrary future readers
+
+## Community Guidelines
+
+This project follows [Google's Open Source Community
+Guidelines][google_open_source_guidelines].
+
+[about_pull_requests]: https://help.github.com/articles/about-pull-requests/
+[beams_git_commit]: https://chris.beams.io/posts/git-commit/
+[cargo_example]: http://xion.io/post/code/rust-examples.html
+[change_detector_tests]: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html
+[chris_beams]: https://chris.beams.io/
+[commit_guidelines]: https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines
+[determinism]: https://fuchsia.dev/fuchsia-src/contribute/testing/best-practices#write_reproducible_deterministic_tests
+[flutter_philosophy]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#philosophy
+[good-first-issue]: https://github.com/google/zerocopy/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
+[google_open_source_guidelines]: https://opensource.google/conduct/
+[magic_number]: https://en.wikipedia.org/wiki/Magic_number_(programming)
+[miri]: https://github.com/rust-lang/miri
+[trybuild]: https://crates.io/crates/trybuild
+[undefined_behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
diff --git a/third_party/rust/zerocopy/Cargo.toml b/third_party/rust/zerocopy/Cargo.toml
new file mode 100644
index 0000000000..36c00b78e4
--- /dev/null
+++ b/third_party/rust/zerocopy/Cargo.toml
@@ -0,0 +1,87 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.60.0"
+name = "zerocopy"
+version = "0.7.32"
+authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
+exclude = [".*"]
+description = "Utilities for zero-copy parsing and serialization"
+readme = "README.md"
+license = "BSD-2-Clause OR Apache-2.0 OR MIT"
+repository = "https://github.com/google/zerocopy"
+
+[package.metadata.ci]
+pinned-nightly = "nightly-2023-12-05"
+pinned-stable = "1.74.0"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = [
+ "--cfg",
+ "doc_cfg",
+ "--generate-link-to-definition",
+]
+
+[package.metadata.playground]
+features = ["__internal_use_only_features_that_work_on_stable"]
+
+[dependencies.byteorder]
+version = "1.3"
+optional = true
+default-features = false
+
+[dependencies.zerocopy-derive]
+version = "=0.7.32"
+optional = true
+
+[dev-dependencies.assert_matches]
+version = "1.5"
+
+[dev-dependencies.elain]
+version = "0.3.0"
+
+[dev-dependencies.itertools]
+version = "0.11"
+
+[dev-dependencies.rand]
+version = "0.8.5"
+features = ["small_rng"]
+
+[dev-dependencies.rustversion]
+version = "1.0"
+
+[dev-dependencies.static_assertions]
+version = "1.1"
+
+[dev-dependencies.trybuild]
+version = "=1.0.85"
+features = ["diff"]
+
+[dev-dependencies.zerocopy-derive]
+version = "=0.7.32"
+
+[features]
+__internal_use_only_features_that_work_on_stable = [
+ "alloc",
+ "derive",
+ "simd",
+]
+alloc = []
+default = ["byteorder"]
+derive = ["zerocopy-derive"]
+simd = []
+simd-nightly = ["simd"]
+
+[target."cfg(any())".dependencies.zerocopy-derive]
+version = "=0.7.32"
diff --git a/third_party/rust/zerocopy/INTERNAL.md b/third_party/rust/zerocopy/INTERNAL.md
new file mode 100644
index 0000000000..4e7f440732
--- /dev/null
+++ b/third_party/rust/zerocopy/INTERNAL.md
@@ -0,0 +1,44 @@
+<!-- Copyright 2022 The Fuchsia Authors
+
+Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+This file may not be copied, modified, or distributed except according to
+those terms. -->
+
+# Internal details
+
+This file documents various internal details of zerocopy and its infrastructure
+that consumers don't need to be concerned about. It focuses on details that
+affect multiple files, and allows each affected code location to reference this
+document rather than requiring us to repeat the same explanation in multiple
+locations.
+
+## CI and toolchain versions
+
+In CI (`.github/workflows/ci.yml`), we pin to specific versions or dates of the
+stable and nightly toolchains. The reason is twofold: First, our UI tests (see
+`tests/trybuild.rs` and `zerocopy-derive/tests/trybuild.rs`) depend on the
+format of rustc's error messages, and that format can change between toolchain
+versions (we also maintain multiple copies of our UI tests - one for each
+toolchain version pinned in CI - for this reason). Second, not all nightlies
+have a working Miri, so we need to pin to one that does (see
+https://rust-lang.github.io/rustup-components-history/).
+
+Updating the versions pinned in CI may cause the UI tests to break. In order to
+fix UI tests after a version update, run:
+
+```
+$ TRYBUILD=overwrite ./cargo.sh +all test
+```
+
+## Crate versions
+
+We ensure that the crate versions of zerocopy and zerocopy-derive are always the
+same in-tree, and that zerocopy depends upon zerocopy-derive using an exact
+version match to the current version in-tree. This has the result that, even
+when published on crates.io, both crates effectively constitute a single atomic
+version. So long as the code in zerocopy is compatible with the code in
+zerocopy-derive in the same Git commit, then publishing them both is fine. This
+frees us from the normal task of reasoning about compatibility with a range of
+semver-compatible versions of different crates.
diff --git a/third_party/rust/zerocopy/LICENSE-APACHE b/third_party/rust/zerocopy/LICENSE-APACHE
new file mode 100644
index 0000000000..2dc22c12fa
--- /dev/null
+++ b/third_party/rust/zerocopy/LICENSE-APACHE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2023 The Fuchsia Authors
+
+ 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
+
+ http://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.
+
diff --git a/third_party/rust/zerocopy/LICENSE-BSD b/third_party/rust/zerocopy/LICENSE-BSD
new file mode 100644
index 0000000000..7ed244f42d
--- /dev/null
+++ b/third_party/rust/zerocopy/LICENSE-BSD
@@ -0,0 +1,24 @@
+Copyright 2019 The Fuchsia Authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/rust/zerocopy/LICENSE-MIT b/third_party/rust/zerocopy/LICENSE-MIT
new file mode 100644
index 0000000000..26e15216cd
--- /dev/null
+++ b/third_party/rust/zerocopy/LICENSE-MIT
@@ -0,0 +1,26 @@
+Copyright 2023 The Fuchsia Authors
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/third_party/rust/zerocopy/POLICIES.md b/third_party/rust/zerocopy/POLICIES.md
new file mode 100644
index 0000000000..a9d9cc5ab2
--- /dev/null
+++ b/third_party/rust/zerocopy/POLICIES.md
@@ -0,0 +1,103 @@
+<!-- Copyright 2023 The Fuchsia Authors
+
+Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+This file may not be copied, modified, or distributed except according to
+those terms. -->
+
+# Zerocopy's Policies
+
+## Soundness
+
+Zerocopy is expressly designed for use in security-critical contexts. It is used
+in hardware security firmware, cryptographic implementations, hypervisors, and
+more. We understand that software in these contexts has a very high bar for
+correctness, and we take our responsibility to meet that bar very seriously.
+
+This section describes policies which are designed to ensure the correctness and
+soundness of our code and prevent regressions.
+
+### Forwards-compatibility
+
+Rust does not currently have a formal memory model. As such, while Rust provides
+guarantees about the semantics of some operations, the semantics of many
+operations is up in the air and subject to change.
+
+Zerocopy strives to ensure that our code - and code emitted by our custom
+derives - is sound under any version of Rust as early as our MSRV, and will
+continue to be sound under any future version of Rust. The policies in this
+section are designed to help ensure that we live up to this goal.
+
+### Safety comments
+
+Each non-test `unsafe` block must be annotated with a "safety comment" which
+provides a rationale for its soundness. In order to ensure that our soundness is
+forwards-compatible, safety comments must satisfy the following criteria:
+- Safety comments must constitute a (possibly informal) proof that all of Rust's
+ soundness rules are upheld.
+- Safety comments must only rely for their correctness on statements which
+ appear in the stable versions of the [Rust Reference] or standard library
+ documentation (ie, the docs for [core], [alloc], and [std]); arguments which
+ rely on text from the beta or nightly versions of these documents are not
+ considered complete.
+- All statements from the Reference or standard library documentation which are
+ relied upon for soundness must be quoted in the safety comment. This ensures
+ that there is no ambiguity as to what aspect of the text is being cited. This
+ is especially important in cases where the text of these documents changes in
+ the future. Such changes are of course required to be backwards-compatible,
+ but may change the manner in which a particular guarantee is explained.
+
+We use the [`clippy::undocumented_unsafe_blocks`] lint to ensure that `unsafe`
+blocks cannot be added without a safety comment. Note that there are a few
+outstanding uncommented `unsafe` blocks which are tracked in [#429]. Our goal is
+to reach 100% safety comment coverage and not regress once we've reached it.
+
+[Rust Reference]: https://doc.rust-lang.org/reference/
+[core]: https://doc.rust-lang.org/stable/core/
+[alloc]: https://doc.rust-lang.org/stable/alloc/
+[std]: https://doc.rust-lang.org/stable/std/
+[`clippy::undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#/undocumented_unsafe_blocks
+[#429]: https://github.com/google/zerocopy/issues/429
+
+#### Exceptions to our safety comment policy
+
+In rare circumstances, the soundness of an `unsafe` block may depend upon
+semantics which are widely agreed upon but not formally guaranteed. In order to
+avoid slowing down zerocopy's development to an unreasonable degree, a safety
+comment may violate our safety comment policy so long as all of the following
+hold:
+- The safety comment's correctness may rely on semantics which are not
+ guaranteed in official Rust documentation *so long as* a member of the Rust
+ team has articulated in an official communication (e.g. a comment on a Rust
+ GitHub repo) that Rust intends to guarantee particular semantics.
+- There exists an active effort to formalize the guarantee in Rust's official
+ documentation.
+
+### Target architecture support
+
+Zerocopy bases its soundness on guarantees made about the semantics of Rust
+which appear in the Rust Reference or standard library documentation; zerocopy
+is sound so long as these guarantees hold. There are known cases in which these
+guarantees do not hold on certain target architectures (see
+[rust-lang/unsafe-code-guidelines#461]); on such target architectures, zerocopy
+may be unsound. We consider it outside of zerocopy's scope to reason about these
+cases. Zerocopy makes no effort maintain soundness in cases where Rust's
+documented guarantees do not hold.
+
+[rust-lang/unsafe-code-guidelines#461]: https://github.com/rust-lang/unsafe-code-guidelines/issues/461
+
+## MSRV
+
+Our minimum supported Rust version (MSRV) is encoded in our `Cargo.toml` file.
+We consider an increase in MSRV to be a semver-breaking change, and will only
+increase our MSRV during semver-breaking version changes (e.g., 0.1 -> 0.2, 1.0
+-> 2.0, etc).
+
+## Yanking
+
+Whenever a bug or regression is identified, we will yank any affected versions
+which are part of the current version train. For example, if the most recent
+version is 0.10.20 and a bug is uncovered, we will release a fix in 0.10.21 and
+yank all 0.10.X versions which are affected. We *may* also yank versions in previous
+version trains on a case-by-case basis, but we don't guarantee it.
diff --git a/third_party/rust/zerocopy/README.md b/third_party/rust/zerocopy/README.md
new file mode 100644
index 0000000000..ec09c4569a
--- /dev/null
+++ b/third_party/rust/zerocopy/README.md
@@ -0,0 +1,154 @@
+<!-- Copyright 2022 The Fuchsia Authors
+
+Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+This file may not be copied, modified, or distributed except according to
+those terms.
+
+WARNING: DO NOT EDIT THIS FILE. It is generated automatically. Edits should be
+made in the doc comment on `src/lib.rs` or in `generate-readme.sh`.
+-->
+
+# zerocopy
+
+*<span style="font-size: 100%; color:grey;">Want to help improve zerocopy?
+Fill out our [user survey][user-survey]!</span>*
+
+***<span style="font-size: 140%">Fast, safe, <span
+style="color:red;">compile error</span>. Pick two.</span>***
+
+Zerocopy makes zero-cost memory manipulation effortless. We write `unsafe`
+so you don't have to.
+
+## Overview
+
+Zerocopy provides four core marker traits, each of which can be derived
+(e.g., `#[derive(FromZeroes)]`):
+- `FromZeroes` indicates that a sequence of zero bytes represents a valid
+ instance of a type
+- `FromBytes` indicates that a type may safely be converted from an
+ arbitrary byte sequence
+- `AsBytes` indicates that a type may safely be converted *to* a byte
+ sequence
+- `Unaligned` indicates that a type's alignment requirement is 1
+
+Types which implement a subset of these traits can then be converted to/from
+byte sequences with little to no runtime overhead.
+
+Zerocopy also provides byte-order aware integer types that support these
+conversions; see the `byteorder` module. These types are especially useful
+for network parsing.
+
+[user-survey]: https://docs.google.com/forms/d/e/1FAIpQLSdzBNTN9tzwsmtyZxRFNL02K36IWCdHWW2ZBckyQS2xiO3i8Q/viewform?usp=published_options
+
+## Cargo Features
+
+- **`alloc`**
+ By default, `zerocopy` is `no_std`. When the `alloc` feature is enabled,
+ the `alloc` crate is added as a dependency, and some allocation-related
+ functionality is added.
+
+- **`byteorder`** (enabled by default)
+ Adds the `byteorder` module and a dependency on the `byteorder` crate.
+ The `byteorder` module provides byte order-aware equivalents of the
+ multi-byte primitive numerical types. Unlike their primitive equivalents,
+ the types in this module have no alignment requirement and support byte
+ order conversions. This can be useful in handling file formats, network
+ packet layouts, etc which don't provide alignment guarantees and which may
+ use a byte order different from that of the execution platform.
+
+- **`derive`**
+ Provides derives for the core marker traits via the `zerocopy-derive`
+ crate. These derives are re-exported from `zerocopy`, so it is not
+ necessary to depend on `zerocopy-derive` directly.
+
+ However, you may experience better compile times if you instead directly
+ depend on both `zerocopy` and `zerocopy-derive` in your `Cargo.toml`,
+ since doing so will allow Rust to compile these crates in parallel. To do
+ so, do *not* enable the `derive` feature, and list both dependencies in
+ your `Cargo.toml` with the same leading non-zero version number; e.g:
+
+ ```toml
+ [dependencies]
+ zerocopy = "0.X"
+ zerocopy-derive = "0.X"
+ ```
+
+- **`simd`**
+ When the `simd` feature is enabled, `FromZeroes`, `FromBytes`, and
+ `AsBytes` impls are emitted for all stable SIMD types which exist on the
+ target platform. Note that the layout of SIMD types is not yet stabilized,
+ so these impls may be removed in the future if layout changes make them
+ invalid. For more information, see the Unsafe Code Guidelines Reference
+ page on the [layout of packed SIMD vectors][simd-layout].
+
+- **`simd-nightly`**
+ Enables the `simd` feature and adds support for SIMD types which are only
+ available on nightly. Since these types are unstable, support for any type
+ may be removed at any point in the future.
+
+[simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html
+
+## Security Ethos
+
+Zerocopy is expressly designed for use in security-critical contexts. We
+strive to ensure that that zerocopy code is sound under Rust's current
+memory model, and *any future memory model*. We ensure this by:
+- **...not 'guessing' about Rust's semantics.**
+ We annotate `unsafe` code with a precise rationale for its soundness that
+ cites a relevant section of Rust's official documentation. When Rust's
+ documented semantics are unclear, we work with the Rust Operational
+ Semantics Team to clarify Rust's documentation.
+- **...rigorously testing our implementation.**
+ We run tests using [Miri], ensuring that zerocopy is sound across a wide
+ array of supported target platforms of varying endianness and pointer
+ width, and across both current and experimental memory models of Rust.
+- **...formally proving the correctness of our implementation.**
+ We apply formal verification tools like [Kani][kani] to prove zerocopy's
+ correctness.
+
+For more information, see our full [soundness policy].
+
+[Miri]: https://github.com/rust-lang/miri
+[Kani]: https://github.com/model-checking/kani
+[soundness policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#soundness
+
+## Relationship to Project Safe Transmute
+
+[Project Safe Transmute] is an official initiative of the Rust Project to
+develop language-level support for safer transmutation. The Project consults
+with crates like zerocopy to identify aspects of safer transmutation that
+would benefit from compiler support, and has developed an [experimental,
+compiler-supported analysis][mcp-transmutability] which determines whether,
+for a given type, any value of that type may be soundly transmuted into
+another type. Once this functionality is sufficiently mature, zerocopy
+intends to replace its internal transmutability analysis (implemented by our
+custom derives) with the compiler-supported one. This change will likely be
+an implementation detail that is invisible to zerocopy's users.
+
+Project Safe Transmute will not replace the need for most of zerocopy's
+higher-level abstractions. The experimental compiler analysis is a tool for
+checking the soundness of `unsafe` code, not a tool to avoid writing
+`unsafe` code altogether. For the foreseeable future, crates like zerocopy
+will still be required in order to provide higher-level abstractions on top
+of the building block provided by Project Safe Transmute.
+
+[Project Safe Transmute]: https://rust-lang.github.io/rfcs/2835-project-safe-transmute.html
+[mcp-transmutability]: https://github.com/rust-lang/compiler-team/issues/411
+
+## MSRV
+
+See our [MSRV policy].
+
+[MSRV policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#msrv
+
+## Changelog
+
+Zerocopy uses [GitHub Releases].
+
+[GitHub Releases]: https://github.com/google/zerocopy/releases
+
+## Disclaimer
+
+Disclaimer: Zerocopy is not an officially supported Google product.
diff --git a/third_party/rust/zerocopy/cargo.sh b/third_party/rust/zerocopy/cargo.sh
new file mode 100755
index 0000000000..f72e898db6
--- /dev/null
+++ b/third_party/rust/zerocopy/cargo.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+#
+# Copyright 2023 The Fuchsia Authors
+#
+# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+# This file may not be copied, modified, or distributed except according to
+# those terms.
+
+# This script is a thin wrapper around Cargo that provides human-friendly
+# toolchain names which are automatically translated to the toolchain versions
+# we have pinned in CI.
+#
+# cargo.sh --version <toolchain-name> # looks up the version for the named toolchain
+# cargo.sh +<toolchain-name> [...] # runs cargo commands with the named toolchain
+# cargo.sh +all [...] # runs cargo commands with each toolchain
+#
+# The meta-toolchain "all" instructs this script to run the provided command
+# once for each toolchain (msrv, stable, nightly).
+#
+# A common task that is especially annoying to perform by hand is to update
+# trybuild's stderr files. Using this script:
+#
+# TRYBUILD=overwrite ./cargo.sh +all test --workspace
+
+set -eo pipefail
+
+function print-usage-and-exit {
+ echo "Usage:" >&2
+ echo " $0 --version <toolchain-name>" >&2
+ echo " $0 +<toolchain-name> [...]" >&2
+ echo " $0 +all [...]" >&2
+ exit 1
+}
+
+[[ $# -gt 0 ]] || print-usage-and-exit
+
+function pkg-meta {
+ # NOTE(#547): We set `CARGO_TARGET_DIR` here because `cargo metadata`
+ # sometimes causes the `cargo-metadata` crate to be rebuilt from source using
+ # the default toolchain. This has the effect of clobbering any existing build
+ # artifacts from whatever toolchain the user has specified (e.g., `+nightly`),
+ # causing the subsequent `cargo` invocation to rebuild unnecessarily. By
+ # specifying a separate build directory here, we ensure that this never
+ # clobbers the build artifacts used by the later `cargo` invocation.
+ CARGO_TARGET_DIR=target/cargo-sh cargo metadata --format-version 1 | jq -r ".packages[] | select(.name == \"zerocopy\").$1"
+}
+
+function lookup-version {
+ VERSION="$1"
+ case "$VERSION" in
+ msrv)
+ pkg-meta rust_version
+ ;;
+ stable)
+ pkg-meta 'metadata.ci."pinned-stable"'
+ ;;
+ nightly)
+ pkg-meta 'metadata.ci."pinned-nightly"'
+ ;;
+ *)
+ echo "Unrecognized toolchain name: '$VERSION' (options are 'msrv', 'stable', 'nightly')" >&2
+ return 1
+ ;;
+ esac
+}
+
+function get-rustflags {
+ [ "$1" == nightly ] && echo "--cfg __INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS"
+}
+
+function prompt {
+ PROMPT="$1"
+ YES="$2"
+ while true; do
+ read -p "$PROMPT " yn
+ case "$yn" in
+ [Yy]) $YES; return $?; ;;
+ [Nn]) return 1; ;;
+ *) break; ;;
+ esac
+ done
+}
+
+case "$1" in
+ # cargo.sh --version <toolchain-name>
+ --version)
+ [[ $# -eq 2 ]] || print-usage-and-exit
+ lookup-version "$2"
+ ;;
+ # cargo.sh +all [...]
+ +all)
+ echo "[cargo.sh] warning: running the same command for each toolchain (msrv, stable, nightly)" >&2
+ for toolchain in msrv stable nightly; do
+ echo "[cargo.sh] running with toolchain: $toolchain" >&2
+ $0 "+$toolchain" ${@:2}
+ done
+ exit 0
+ ;;
+ # cargo.sh +<toolchain-name> [...]
+ +*)
+ TOOLCHAIN="$(lookup-version ${1:1})"
+
+ cargo "+$TOOLCHAIN" version &>/dev/null && \
+ rustup "+$TOOLCHAIN" component list | grep '^rust-src (installed)$' >/dev/null || {
+ echo "[cargo.sh] missing either toolchain '$TOOLCHAIN' or component 'rust-src'" >&2
+ # If we're running in a GitHub action, then it's better to bail than to
+ # hang waiting for input we're never going to get.
+ [ -z ${GITHUB_RUN_ID+x} ] || exit 1
+ prompt "[cargo.sh] would you like to install toolchain '$TOOLCHAIN' and component 'rust-src' via 'rustup'?" \
+ "rustup toolchain install $TOOLCHAIN -c rust-src"
+ } || exit 1
+
+ RUSTFLAGS="$(get-rustflags ${1:1}) $RUSTFLAGS" cargo "+$TOOLCHAIN" ${@:2}
+ ;;
+ *)
+ print-usage-and-exit
+ ;;
+esac
diff --git a/third_party/rust/zerocopy/clippy.toml b/third_party/rust/zerocopy/clippy.toml
new file mode 100644
index 0000000000..9c1140643c
--- /dev/null
+++ b/third_party/rust/zerocopy/clippy.toml
@@ -0,0 +1,10 @@
+# Copyright 2023 The Fuchsia Authors
+#
+# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+# This file may not be copied, modified, or distributed except according to
+# those terms.
+
+accept-comment-above-statement = true
+accept-comment-above-attributes = true
diff --git a/third_party/rust/zerocopy/generate-readme.sh b/third_party/rust/zerocopy/generate-readme.sh
new file mode 100755
index 0000000000..be0dc929af
--- /dev/null
+++ b/third_party/rust/zerocopy/generate-readme.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# Copyright 2022 The Fuchsia Authors
+#
+# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+# This file may not be copied, modified, or distributed except according to
+# those terms.
+
+set -eo pipefail
+
+COPYRIGHT_HEADER=$(mktemp)
+BODY=$(mktemp)
+DISCLAIMER_FOOTER=$(mktemp)
+
+cat > $COPYRIGHT_HEADER <<'EOF'
+<!-- Copyright 2022 The Fuchsia Authors
+
+Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+This file may not be copied, modified, or distributed except according to
+those terms.
+
+WARNING: DO NOT EDIT THIS FILE. It is generated automatically. Edits should be
+made in the doc comment on `src/lib.rs` or in `generate-readme.sh`.
+-->
+
+EOF
+
+# This uses the `cargo readme` tool, which you can install via `cargo install
+# cargo-readme --version 3.2.0`.
+#
+# The `sed` command is used to strip code links like:
+#
+# /// Here is a link to [`Vec`].
+#
+# These links don't work in a Markdown file, and so we remove the `[` and `]`
+# characters to convert them to non-link code snippets.
+cargo readme --no-license | sed 's/\[\(`[^`]*`\)]/\1/g' > $BODY
+
+cat > $DISCLAIMER_FOOTER <<'EOF'
+
+## Disclaimer
+
+Disclaimer: Zerocopy is not an officially supported Google product.
+EOF
+
+cat $COPYRIGHT_HEADER $BODY $DISCLAIMER_FOOTER
diff --git a/third_party/rust/zerocopy/rustfmt.toml b/third_party/rust/zerocopy/rustfmt.toml
new file mode 100644
index 0000000000..c967afe9c5
--- /dev/null
+++ b/third_party/rust/zerocopy/rustfmt.toml
@@ -0,0 +1,19 @@
+# Copyright 2022 The Fuchsia Authors
+#
+# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+# This file may not be copied, modified, or distributed except according to
+# those terms.
+
+edition = "2021"
+
+# The "Default" setting has a heuristic which splits lines too aggresively.
+# We are willing to revisit this setting in future versions of rustfmt.
+# Bugs:
+# * https://github.com/rust-lang/rustfmt/issues/3119
+# * https://github.com/rust-lang/rustfmt/issues/3120
+use_small_heuristics = "Max"
+
+# Prevent carriage returns
+newline_style = "Unix"
diff --git a/third_party/rust/zerocopy/src/byteorder.rs b/third_party/rust/zerocopy/src/byteorder.rs
new file mode 100644
index 0000000000..2769410451
--- /dev/null
+++ b/third_party/rust/zerocopy/src/byteorder.rs
@@ -0,0 +1,1075 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+//! Byte order-aware numeric primitives.
+//!
+//! This module contains equivalents of the native multi-byte integer types with
+//! no alignment requirement and supporting byte order conversions.
+//!
+//! For each native multi-byte integer type - `u16`, `i16`, `u32`, etc - and
+//! floating point type - `f32` and `f64` - an equivalent type is defined by
+//! this module - [`U16`], [`I16`], [`U32`], [`F64`], etc. Unlike their native
+//! counterparts, these types have alignment 1, and take a type parameter
+//! specifying the byte order in which the bytes are stored in memory. Each type
+//! implements the [`FromBytes`], [`AsBytes`], and [`Unaligned`] traits.
+//!
+//! These two properties, taken together, make these types useful for defining
+//! data structures whose memory layout matches a wire format such as that of a
+//! network protocol or a file format. Such formats often have multi-byte values
+//! at offsets that do not respect the alignment requirements of the equivalent
+//! native types, and stored in a byte order not necessarily the same as that of
+//! the target platform.
+//!
+//! Type aliases are provided for common byte orders in the [`big_endian`],
+//! [`little_endian`], [`network_endian`], and [`native_endian`] submodules.
+//!
+//! # Example
+//!
+//! One use of these types is for representing network packet formats, such as
+//! UDP:
+//!
+//! ```rust,edition2021
+//! # #[cfg(feature = "derive")] { // This example uses derives, and won't compile without them
+//! use zerocopy::{AsBytes, ByteSlice, FromBytes, FromZeroes, Ref, Unaligned};
+//! use zerocopy::byteorder::network_endian::U16;
+//!
+//! #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+//! #[repr(C)]
+//! struct UdpHeader {
+//! src_port: U16,
+//! dst_port: U16,
+//! length: U16,
+//! checksum: U16,
+//! }
+//!
+//! struct UdpPacket<B: ByteSlice> {
+//! header: Ref<B, UdpHeader>,
+//! body: B,
+//! }
+//!
+//! impl<B: ByteSlice> UdpPacket<B> {
+//! fn parse(bytes: B) -> Option<UdpPacket<B>> {
+//! let (header, body) = Ref::new_from_prefix(bytes)?;
+//! Some(UdpPacket { header, body })
+//! }
+//!
+//! fn src_port(&self) -> u16 {
+//! self.header.src_port.get()
+//! }
+//!
+//! // more getters...
+//! }
+//! # }
+//! ```
+
+use core::{
+ convert::{TryFrom, TryInto},
+ fmt::{self, Binary, Debug, Display, Formatter, LowerHex, Octal, UpperHex},
+ marker::PhantomData,
+ num::TryFromIntError,
+};
+
+// We don't reexport `WriteBytesExt` or `ReadBytesExt` because those are only
+// available with the `std` feature enabled, and zerocopy is `no_std` by
+// default.
+pub use ::byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian, NetworkEndian, BE, LE};
+
+use super::*;
+
+macro_rules! impl_fmt_trait {
+ ($name:ident, $native:ident, $trait:ident) => {
+ impl<O: ByteOrder> $trait for $name<O> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ $trait::fmt(&self.get(), f)
+ }
+ }
+ };
+}
+
+macro_rules! impl_fmt_traits {
+ ($name:ident, $native:ident, "floating point number") => {
+ impl_fmt_trait!($name, $native, Display);
+ };
+ ($name:ident, $native:ident, "unsigned integer") => {
+ impl_fmt_traits!($name, $native, @all_types);
+ };
+ ($name:ident, $native:ident, "signed integer") => {
+ impl_fmt_traits!($name, $native, @all_types);
+ };
+ ($name:ident, $native:ident, @all_types) => {
+ impl_fmt_trait!($name, $native, Display);
+ impl_fmt_trait!($name, $native, Octal);
+ impl_fmt_trait!($name, $native, LowerHex);
+ impl_fmt_trait!($name, $native, UpperHex);
+ impl_fmt_trait!($name, $native, Binary);
+ };
+}
+
+macro_rules! impl_ops_traits {
+ ($name:ident, $native:ident, "floating point number") => {
+ impl_ops_traits!($name, $native, @all_types);
+ impl_ops_traits!($name, $native, @signed_integer_floating_point);
+ };
+ ($name:ident, $native:ident, "unsigned integer") => {
+ impl_ops_traits!($name, $native, @signed_unsigned_integer);
+ impl_ops_traits!($name, $native, @all_types);
+ };
+ ($name:ident, $native:ident, "signed integer") => {
+ impl_ops_traits!($name, $native, @signed_unsigned_integer);
+ impl_ops_traits!($name, $native, @signed_integer_floating_point);
+ impl_ops_traits!($name, $native, @all_types);
+ };
+ ($name:ident, $native:ident, @signed_unsigned_integer) => {
+ impl_ops_traits!(@without_byteorder_swap $name, $native, BitAnd, bitand, BitAndAssign, bitand_assign);
+ impl_ops_traits!(@without_byteorder_swap $name, $native, BitOr, bitor, BitOrAssign, bitor_assign);
+ impl_ops_traits!(@without_byteorder_swap $name, $native, BitXor, bitxor, BitXorAssign, bitxor_assign);
+ impl_ops_traits!(@with_byteorder_swap $name, $native, Shl, shl, ShlAssign, shl_assign);
+ impl_ops_traits!(@with_byteorder_swap $name, $native, Shr, shr, ShrAssign, shr_assign);
+
+ impl<O> core::ops::Not for $name<O> {
+ type Output = $name<O>;
+
+ #[inline(always)]
+ fn not(self) -> $name<O> {
+ let self_native = $native::from_ne_bytes(self.0);
+ $name((!self_native).to_ne_bytes(), PhantomData)
+ }
+ }
+ };
+ ($name:ident, $native:ident, @signed_integer_floating_point) => {
+ impl<O: ByteOrder> core::ops::Neg for $name<O> {
+ type Output = $name<O>;
+
+ #[inline(always)]
+ fn neg(self) -> $name<O> {
+ let self_native: $native = self.get();
+ #[allow(clippy::arithmetic_side_effects)]
+ $name::<O>::new(-self_native)
+ }
+ }
+ };
+ ($name:ident, $native:ident, @all_types) => {
+ impl_ops_traits!(@with_byteorder_swap $name, $native, Add, add, AddAssign, add_assign);
+ impl_ops_traits!(@with_byteorder_swap $name, $native, Div, div, DivAssign, div_assign);
+ impl_ops_traits!(@with_byteorder_swap $name, $native, Mul, mul, MulAssign, mul_assign);
+ impl_ops_traits!(@with_byteorder_swap $name, $native, Rem, rem, RemAssign, rem_assign);
+ impl_ops_traits!(@with_byteorder_swap $name, $native, Sub, sub, SubAssign, sub_assign);
+ };
+ (@with_byteorder_swap $name:ident, $native:ident, $trait:ident, $method:ident, $trait_assign:ident, $method_assign:ident) => {
+ impl<O: ByteOrder> core::ops::$trait for $name<O> {
+ type Output = $name<O>;
+
+ #[inline(always)]
+ fn $method(self, rhs: $name<O>) -> $name<O> {
+ let self_native: $native = self.get();
+ let rhs_native: $native = rhs.get();
+ let result_native = core::ops::$trait::$method(self_native, rhs_native);
+ $name::<O>::new(result_native)
+ }
+ }
+
+ impl<O: ByteOrder> core::ops::$trait_assign for $name<O> {
+ #[inline(always)]
+ fn $method_assign(&mut self, rhs: $name<O>) {
+ *self = core::ops::$trait::$method(*self, rhs);
+ }
+ }
+ };
+ // Implement traits in terms of the same trait on the native type, but
+ // without performing a byte order swap. This only works for bitwise
+ // operations like `&`, `|`, etc.
+ (@without_byteorder_swap $name:ident, $native:ident, $trait:ident, $method:ident, $trait_assign:ident, $method_assign:ident) => {
+ impl<O: ByteOrder> core::ops::$trait for $name<O> {
+ type Output = $name<O>;
+
+ #[inline(always)]
+ fn $method(self, rhs: $name<O>) -> $name<O> {
+ let self_native = $native::from_ne_bytes(self.0);
+ let rhs_native = $native::from_ne_bytes(rhs.0);
+ let result_native = core::ops::$trait::$method(self_native, rhs_native);
+ $name(result_native.to_ne_bytes(), PhantomData)
+ }
+ }
+
+ impl<O: ByteOrder> core::ops::$trait_assign for $name<O> {
+ #[inline(always)]
+ fn $method_assign(&mut self, rhs: $name<O>) {
+ *self = core::ops::$trait::$method(*self, rhs);
+ }
+ }
+ };
+}
+
+macro_rules! doc_comment {
+ ($x:expr, $($tt:tt)*) => {
+ #[doc = $x]
+ $($tt)*
+ };
+}
+
+macro_rules! define_max_value_constant {
+ ($name:ident, $bytes:expr, "unsigned integer") => {
+ /// The maximum value.
+ ///
+ /// This constant should be preferred to constructing a new value using
+ /// `new`, as `new` may perform an endianness swap depending on the
+ /// endianness `O` and the endianness of the platform.
+ pub const MAX_VALUE: $name<O> = $name([0xFFu8; $bytes], PhantomData);
+ };
+ // We don't provide maximum and minimum value constants for signed values
+ // and floats because there's no way to do it generically - it would require
+ // a different value depending on the value of the `ByteOrder` type
+ // parameter. Currently, one workaround would be to provide implementations
+ // for concrete implementations of that trait. In the long term, if we are
+ // ever able to make the `new` constructor a const fn, we could use that
+ // instead.
+ ($name:ident, $bytes:expr, "signed integer") => {};
+ ($name:ident, $bytes:expr, "floating point number") => {};
+}
+
+macro_rules! define_type {
+ ($article:ident,
+ $name:ident,
+ $native:ident,
+ $bits:expr,
+ $bytes:expr,
+ $read_method:ident,
+ $write_method:ident,
+ $number_kind:tt,
+ [$($larger_native:ty),*],
+ [$($larger_native_try:ty),*],
+ [$($larger_byteorder:ident),*],
+ [$($larger_byteorder_try:ident),*]) => {
+ doc_comment! {
+ concat!("A ", stringify!($bits), "-bit ", $number_kind,
+ " stored in a given byte order.
+
+`", stringify!($name), "` is like the native `", stringify!($native), "` type with
+two major differences: First, it has no alignment requirement (its alignment is 1).
+Second, the endianness of its memory layout is given by the type parameter `O`,
+which can be any type which implements [`ByteOrder`]. In particular, this refers
+to [`BigEndian`], [`LittleEndian`], [`NativeEndian`], and [`NetworkEndian`].
+
+", stringify!($article), " `", stringify!($name), "` can be constructed using
+the [`new`] method, and its contained value can be obtained as a native
+`",stringify!($native), "` using the [`get`] method, or updated in place with
+the [`set`] method. In all cases, if the endianness `O` is not the same as the
+endianness of the current platform, an endianness swap will be performed in
+order to uphold the invariants that a) the layout of `", stringify!($name), "`
+has endianness `O` and that, b) the layout of `", stringify!($native), "` has
+the platform's native endianness.
+
+`", stringify!($name), "` implements [`FromBytes`], [`AsBytes`], and [`Unaligned`],
+making it useful for parsing and serialization. See the module documentation for an
+example of how it can be used for parsing UDP packets.
+
+[`new`]: crate::byteorder::", stringify!($name), "::new
+[`get`]: crate::byteorder::", stringify!($name), "::get
+[`set`]: crate::byteorder::", stringify!($name), "::set
+[`FromBytes`]: crate::FromBytes
+[`AsBytes`]: crate::AsBytes
+[`Unaligned`]: crate::Unaligned"),
+ #[derive(Copy, Clone, Eq, PartialEq, Hash)]
+ #[cfg_attr(any(feature = "derive", test), derive(KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned))]
+ #[repr(transparent)]
+ pub struct $name<O>([u8; $bytes], PhantomData<O>);
+ }
+
+ #[cfg(not(any(feature = "derive", test)))]
+ impl_known_layout!(O => $name<O>);
+
+ safety_comment! {
+ /// SAFETY:
+ /// `$name<O>` is `repr(transparent)`, and so it has the same layout
+ /// as its only non-zero field, which is a `u8` array. `u8` arrays
+ /// are `FromZeroes`, `FromBytes`, `AsBytes`, and `Unaligned`.
+ impl_or_verify!(O => FromZeroes for $name<O>);
+ impl_or_verify!(O => FromBytes for $name<O>);
+ impl_or_verify!(O => AsBytes for $name<O>);
+ impl_or_verify!(O => Unaligned for $name<O>);
+ }
+
+ impl<O> Default for $name<O> {
+ #[inline(always)]
+ fn default() -> $name<O> {
+ $name::ZERO
+ }
+ }
+
+ impl<O> $name<O> {
+ /// The value zero.
+ ///
+ /// This constant should be preferred to constructing a new value
+ /// using `new`, as `new` may perform an endianness swap depending
+ /// on the endianness and platform.
+ pub const ZERO: $name<O> = $name([0u8; $bytes], PhantomData);
+
+ define_max_value_constant!($name, $bytes, $number_kind);
+
+ /// Constructs a new value from bytes which are already in the
+ /// endianness `O`.
+ #[inline(always)]
+ pub const fn from_bytes(bytes: [u8; $bytes]) -> $name<O> {
+ $name(bytes, PhantomData)
+ }
+ }
+
+ impl<O: ByteOrder> $name<O> {
+ // TODO(joshlf): Make these const fns if the `ByteOrder` methods
+ // ever become const fns.
+
+ /// Constructs a new value, possibly performing an endianness swap
+ /// to guarantee that the returned value has endianness `O`.
+ #[inline(always)]
+ pub fn new(n: $native) -> $name<O> {
+ let mut out = $name::default();
+ O::$write_method(&mut out.0[..], n);
+ out
+ }
+
+ /// Returns the value as a primitive type, possibly performing an
+ /// endianness swap to guarantee that the return value has the
+ /// endianness of the native platform.
+ #[inline(always)]
+ pub fn get(self) -> $native {
+ O::$read_method(&self.0[..])
+ }
+
+ /// Updates the value in place as a primitive type, possibly
+ /// performing an endianness swap to guarantee that the stored value
+ /// has the endianness `O`.
+ #[inline(always)]
+ pub fn set(&mut self, n: $native) {
+ O::$write_method(&mut self.0[..], n);
+ }
+ }
+
+ // The reasoning behind which traits to implement here is to only
+ // implement traits which won't cause inference issues. Notably,
+ // comparison traits like PartialEq and PartialOrd tend to cause
+ // inference issues.
+
+ impl<O: ByteOrder> From<$name<O>> for [u8; $bytes] {
+ #[inline(always)]
+ fn from(x: $name<O>) -> [u8; $bytes] {
+ x.0
+ }
+ }
+
+ impl<O: ByteOrder> From<[u8; $bytes]> for $name<O> {
+ #[inline(always)]
+ fn from(bytes: [u8; $bytes]) -> $name<O> {
+ $name(bytes, PhantomData)
+ }
+ }
+
+ impl<O: ByteOrder> From<$name<O>> for $native {
+ #[inline(always)]
+ fn from(x: $name<O>) -> $native {
+ x.get()
+ }
+ }
+
+ impl<O: ByteOrder> From<$native> for $name<O> {
+ #[inline(always)]
+ fn from(x: $native) -> $name<O> {
+ $name::new(x)
+ }
+ }
+
+ $(
+ impl<O: ByteOrder> From<$name<O>> for $larger_native {
+ #[inline(always)]
+ fn from(x: $name<O>) -> $larger_native {
+ x.get().into()
+ }
+ }
+ )*
+
+ $(
+ impl<O: ByteOrder> TryFrom<$larger_native_try> for $name<O> {
+ type Error = TryFromIntError;
+ #[inline(always)]
+ fn try_from(x: $larger_native_try) -> Result<$name<O>, TryFromIntError> {
+ $native::try_from(x).map($name::new)
+ }
+ }
+ )*
+
+ $(
+ impl<O: ByteOrder, P: ByteOrder> From<$name<O>> for $larger_byteorder<P> {
+ #[inline(always)]
+ fn from(x: $name<O>) -> $larger_byteorder<P> {
+ $larger_byteorder::new(x.get().into())
+ }
+ }
+ )*
+
+ $(
+ impl<O: ByteOrder, P: ByteOrder> TryFrom<$larger_byteorder_try<P>> for $name<O> {
+ type Error = TryFromIntError;
+ #[inline(always)]
+ fn try_from(x: $larger_byteorder_try<P>) -> Result<$name<O>, TryFromIntError> {
+ x.get().try_into().map($name::new)
+ }
+ }
+ )*
+
+ impl<O: ByteOrder> AsRef<[u8; $bytes]> for $name<O> {
+ #[inline(always)]
+ fn as_ref(&self) -> &[u8; $bytes] {
+ &self.0
+ }
+ }
+
+ impl<O: ByteOrder> AsMut<[u8; $bytes]> for $name<O> {
+ #[inline(always)]
+ fn as_mut(&mut self) -> &mut [u8; $bytes] {
+ &mut self.0
+ }
+ }
+
+ impl<O: ByteOrder> PartialEq<$name<O>> for [u8; $bytes] {
+ #[inline(always)]
+ fn eq(&self, other: &$name<O>) -> bool {
+ self.eq(&other.0)
+ }
+ }
+
+ impl<O: ByteOrder> PartialEq<[u8; $bytes]> for $name<O> {
+ #[inline(always)]
+ fn eq(&self, other: &[u8; $bytes]) -> bool {
+ self.0.eq(other)
+ }
+ }
+
+ impl_fmt_traits!($name, $native, $number_kind);
+ impl_ops_traits!($name, $native, $number_kind);
+
+ impl<O: ByteOrder> Debug for $name<O> {
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ // This results in a format like "U16(42)".
+ f.debug_tuple(stringify!($name)).field(&self.get()).finish()
+ }
+ }
+ };
+}
+
+define_type!(
+ A,
+ U16,
+ u16,
+ 16,
+ 2,
+ read_u16,
+ write_u16,
+ "unsigned integer",
+ [u32, u64, u128, usize],
+ [u32, u64, u128, usize],
+ [U32, U64, U128],
+ [U32, U64, U128]
+);
+define_type!(
+ A,
+ U32,
+ u32,
+ 32,
+ 4,
+ read_u32,
+ write_u32,
+ "unsigned integer",
+ [u64, u128],
+ [u64, u128],
+ [U64, U128],
+ [U64, U128]
+);
+define_type!(
+ A,
+ U64,
+ u64,
+ 64,
+ 8,
+ read_u64,
+ write_u64,
+ "unsigned integer",
+ [u128],
+ [u128],
+ [U128],
+ [U128]
+);
+define_type!(A, U128, u128, 128, 16, read_u128, write_u128, "unsigned integer", [], [], [], []);
+define_type!(
+ An,
+ I16,
+ i16,
+ 16,
+ 2,
+ read_i16,
+ write_i16,
+ "signed integer",
+ [i32, i64, i128, isize],
+ [i32, i64, i128, isize],
+ [I32, I64, I128],
+ [I32, I64, I128]
+);
+define_type!(
+ An,
+ I32,
+ i32,
+ 32,
+ 4,
+ read_i32,
+ write_i32,
+ "signed integer",
+ [i64, i128],
+ [i64, i128],
+ [I64, I128],
+ [I64, I128]
+);
+define_type!(
+ An,
+ I64,
+ i64,
+ 64,
+ 8,
+ read_i64,
+ write_i64,
+ "signed integer",
+ [i128],
+ [i128],
+ [I128],
+ [I128]
+);
+define_type!(An, I128, i128, 128, 16, read_i128, write_i128, "signed integer", [], [], [], []);
+define_type!(
+ An,
+ F32,
+ f32,
+ 32,
+ 4,
+ read_f32,
+ write_f32,
+ "floating point number",
+ [f64],
+ [],
+ [F64],
+ []
+);
+define_type!(An, F64, f64, 64, 8, read_f64, write_f64, "floating point number", [], [], [], []);
+
+macro_rules! module {
+ ($name:ident, $trait:ident, $endianness_str:expr) => {
+ /// Numeric primitives stored in
+ #[doc = $endianness_str]
+ /// byte order.
+ pub mod $name {
+ use byteorder::$trait;
+
+ module!(@ty U16, $trait, "16-bit unsigned integer", $endianness_str);
+ module!(@ty U32, $trait, "32-bit unsigned integer", $endianness_str);
+ module!(@ty U64, $trait, "64-bit unsigned integer", $endianness_str);
+ module!(@ty U128, $trait, "128-bit unsigned integer", $endianness_str);
+ module!(@ty I16, $trait, "16-bit signed integer", $endianness_str);
+ module!(@ty I32, $trait, "32-bit signed integer", $endianness_str);
+ module!(@ty I64, $trait, "64-bit signed integer", $endianness_str);
+ module!(@ty I128, $trait, "128-bit signed integer", $endianness_str);
+ module!(@ty F32, $trait, "32-bit floating point number", $endianness_str);
+ module!(@ty F64, $trait, "64-bit floating point number", $endianness_str);
+ }
+ };
+ (@ty $ty:ident, $trait:ident, $desc_str:expr, $endianness_str:expr) => {
+ /// A
+ #[doc = $desc_str]
+ /// stored in
+ #[doc = $endianness_str]
+ /// byte order.
+ pub type $ty = crate::byteorder::$ty<$trait>;
+ };
+}
+
+module!(big_endian, BigEndian, "big-endian");
+module!(little_endian, LittleEndian, "little-endian");
+module!(network_endian, NetworkEndian, "network-endian");
+module!(native_endian, NativeEndian, "native-endian");
+
+#[cfg(any(test, kani))]
+mod tests {
+ use ::byteorder::NativeEndian;
+
+ use {
+ super::*,
+ crate::{AsBytes, FromBytes, Unaligned},
+ };
+
+ #[cfg(not(kani))]
+ mod compatibility {
+ pub(super) use rand::{
+ distributions::{Distribution, Standard},
+ rngs::SmallRng,
+ Rng, SeedableRng,
+ };
+
+ pub(crate) trait Arbitrary {}
+
+ impl<T> Arbitrary for T {}
+ }
+
+ #[cfg(kani)]
+ mod compatibility {
+ pub(crate) use kani::Arbitrary;
+
+ pub(crate) struct SmallRng;
+
+ impl SmallRng {
+ pub(crate) fn seed_from_u64(_state: u64) -> Self {
+ Self
+ }
+ }
+
+ pub(crate) trait Rng {
+ fn sample<T, D: Distribution<T>>(&mut self, _distr: D) -> T
+ where
+ T: Arbitrary,
+ {
+ kani::any()
+ }
+ }
+
+ impl Rng for SmallRng {}
+
+ pub(crate) trait Distribution<T> {}
+ impl<T, U> Distribution<T> for U {}
+
+ pub(crate) struct Standard;
+ }
+
+ use compatibility::*;
+
+ // A native integer type (u16, i32, etc).
+ trait Native: Arbitrary + FromBytes + AsBytes + Copy + PartialEq + Debug {
+ const ZERO: Self;
+ const MAX_VALUE: Self;
+
+ type Distribution: Distribution<Self>;
+ const DIST: Self::Distribution;
+
+ fn rand<R: Rng>(rng: &mut R) -> Self {
+ rng.sample(Self::DIST)
+ }
+
+ #[cfg(kani)]
+ fn any() -> Self {
+ kani::any()
+ }
+
+ fn checked_add(self, rhs: Self) -> Option<Self>;
+ fn checked_div(self, rhs: Self) -> Option<Self>;
+ fn checked_mul(self, rhs: Self) -> Option<Self>;
+ fn checked_rem(self, rhs: Self) -> Option<Self>;
+ fn checked_sub(self, rhs: Self) -> Option<Self>;
+ fn checked_shl(self, rhs: Self) -> Option<Self>;
+ fn checked_shr(self, rhs: Self) -> Option<Self>;
+
+ fn is_nan(self) -> bool;
+
+ /// For `f32` and `f64`, NaN values are not considered equal to
+ /// themselves. This method is like `assert_eq!`, but it treats NaN
+ /// values as equal.
+ fn assert_eq_or_nan(self, other: Self) {
+ let slf = (!self.is_nan()).then(|| self);
+ let other = (!other.is_nan()).then(|| other);
+ assert_eq!(slf, other);
+ }
+ }
+
+ trait ByteArray:
+ FromBytes + AsBytes + Copy + AsRef<[u8]> + AsMut<[u8]> + Debug + Default + Eq
+ {
+ /// Invert the order of the bytes in the array.
+ fn invert(self) -> Self;
+ }
+
+ trait ByteOrderType: FromBytes + AsBytes + Unaligned + Copy + Eq + Debug {
+ type Native: Native;
+ type ByteArray: ByteArray;
+
+ const ZERO: Self;
+
+ fn new(native: Self::Native) -> Self;
+ fn get(self) -> Self::Native;
+ fn set(&mut self, native: Self::Native);
+ fn from_bytes(bytes: Self::ByteArray) -> Self;
+ fn into_bytes(self) -> Self::ByteArray;
+
+ /// For `f32` and `f64`, NaN values are not considered equal to
+ /// themselves. This method is like `assert_eq!`, but it treats NaN
+ /// values as equal.
+ fn assert_eq_or_nan(self, other: Self) {
+ let slf = (!self.get().is_nan()).then(|| self);
+ let other = (!other.get().is_nan()).then(|| other);
+ assert_eq!(slf, other);
+ }
+ }
+
+ trait ByteOrderTypeUnsigned: ByteOrderType {
+ const MAX_VALUE: Self;
+ }
+
+ macro_rules! impl_byte_array {
+ ($bytes:expr) => {
+ impl ByteArray for [u8; $bytes] {
+ fn invert(mut self) -> [u8; $bytes] {
+ self.reverse();
+ self
+ }
+ }
+ };
+ }
+
+ impl_byte_array!(2);
+ impl_byte_array!(4);
+ impl_byte_array!(8);
+ impl_byte_array!(16);
+
+ macro_rules! impl_byte_order_type_unsigned {
+ ($name:ident, unsigned) => {
+ impl<O: ByteOrder> ByteOrderTypeUnsigned for $name<O> {
+ const MAX_VALUE: $name<O> = $name::MAX_VALUE;
+ }
+ };
+ ($name:ident, signed) => {};
+ }
+
+ macro_rules! impl_traits {
+ ($name:ident, $native:ident, $bytes:expr, $sign:ident $(, @$float:ident)?) => {
+ impl Native for $native {
+ // For some types, `0 as $native` is required (for example, when
+ // `$native` is a floating-point type; `0` is an integer), but
+ // for other types, it's a trivial cast. In all cases, Clippy
+ // thinks it's dangerous.
+ #[allow(trivial_numeric_casts, clippy::as_conversions)]
+ const ZERO: $native = 0 as $native;
+ const MAX_VALUE: $native = $native::MAX;
+
+ type Distribution = Standard;
+ const DIST: Standard = Standard;
+
+ impl_traits!(@float_dependent_methods $(@$float)?);
+ }
+
+ impl<O: ByteOrder> ByteOrderType for $name<O> {
+ type Native = $native;
+ type ByteArray = [u8; $bytes];
+
+ const ZERO: $name<O> = $name::ZERO;
+
+ fn new(native: $native) -> $name<O> {
+ $name::new(native)
+ }
+
+ fn get(self) -> $native {
+ $name::get(self)
+ }
+
+ fn set(&mut self, native: $native) {
+ $name::set(self, native)
+ }
+
+ fn from_bytes(bytes: [u8; $bytes]) -> $name<O> {
+ $name::from(bytes)
+ }
+
+ fn into_bytes(self) -> [u8; $bytes] {
+ <[u8; $bytes]>::from(self)
+ }
+ }
+
+ impl_byte_order_type_unsigned!($name, $sign);
+ };
+ (@float_dependent_methods) => {
+ fn checked_add(self, rhs: Self) -> Option<Self> { self.checked_add(rhs) }
+ fn checked_div(self, rhs: Self) -> Option<Self> { self.checked_div(rhs) }
+ fn checked_mul(self, rhs: Self) -> Option<Self> { self.checked_mul(rhs) }
+ fn checked_rem(self, rhs: Self) -> Option<Self> { self.checked_rem(rhs) }
+ fn checked_sub(self, rhs: Self) -> Option<Self> { self.checked_sub(rhs) }
+ fn checked_shl(self, rhs: Self) -> Option<Self> { self.checked_shl(rhs.try_into().unwrap_or(u32::MAX)) }
+ fn checked_shr(self, rhs: Self) -> Option<Self> { self.checked_shr(rhs.try_into().unwrap_or(u32::MAX)) }
+ fn is_nan(self) -> bool { false }
+ };
+ (@float_dependent_methods @float) => {
+ fn checked_add(self, rhs: Self) -> Option<Self> { Some(self + rhs) }
+ fn checked_div(self, rhs: Self) -> Option<Self> { Some(self / rhs) }
+ fn checked_mul(self, rhs: Self) -> Option<Self> { Some(self * rhs) }
+ fn checked_rem(self, rhs: Self) -> Option<Self> { Some(self % rhs) }
+ fn checked_sub(self, rhs: Self) -> Option<Self> { Some(self - rhs) }
+ fn checked_shl(self, _rhs: Self) -> Option<Self> { unimplemented!() }
+ fn checked_shr(self, _rhs: Self) -> Option<Self> { unimplemented!() }
+ fn is_nan(self) -> bool { self.is_nan() }
+ };
+ }
+
+ impl_traits!(U16, u16, 2, unsigned);
+ impl_traits!(U32, u32, 4, unsigned);
+ impl_traits!(U64, u64, 8, unsigned);
+ impl_traits!(U128, u128, 16, unsigned);
+ impl_traits!(I16, i16, 2, signed);
+ impl_traits!(I32, i32, 4, signed);
+ impl_traits!(I64, i64, 8, signed);
+ impl_traits!(I128, i128, 16, signed);
+ impl_traits!(F32, f32, 4, signed, @float);
+ impl_traits!(F64, f64, 8, signed, @float);
+
+ macro_rules! call_for_unsigned_types {
+ ($fn:ident, $byteorder:ident) => {
+ $fn::<U16<$byteorder>>();
+ $fn::<U32<$byteorder>>();
+ $fn::<U64<$byteorder>>();
+ $fn::<U128<$byteorder>>();
+ };
+ }
+
+ macro_rules! call_for_signed_types {
+ ($fn:ident, $byteorder:ident) => {
+ $fn::<I16<$byteorder>>();
+ $fn::<I32<$byteorder>>();
+ $fn::<I64<$byteorder>>();
+ $fn::<I128<$byteorder>>();
+ };
+ }
+
+ macro_rules! call_for_float_types {
+ ($fn:ident, $byteorder:ident) => {
+ $fn::<F32<$byteorder>>();
+ $fn::<F64<$byteorder>>();
+ };
+ }
+
+ macro_rules! call_for_all_types {
+ ($fn:ident, $byteorder:ident) => {
+ call_for_unsigned_types!($fn, $byteorder);
+ call_for_signed_types!($fn, $byteorder);
+ call_for_float_types!($fn, $byteorder);
+ };
+ }
+
+ #[cfg(target_endian = "big")]
+ type NonNativeEndian = LittleEndian;
+ #[cfg(target_endian = "little")]
+ type NonNativeEndian = BigEndian;
+
+ // We use a `u64` seed so that we can use `SeedableRng::seed_from_u64`.
+ // `SmallRng`'s `SeedableRng::Seed` differs by platform, so if we wanted to
+ // call `SeedableRng::from_seed`, which takes a `Seed`, we would need
+ // conditional compilation by `target_pointer_width`.
+ const RNG_SEED: u64 = 0x7A03CAE2F32B5B8F;
+
+ const RAND_ITERS: usize = if cfg!(any(miri, kani)) {
+ // The tests below which use this constant used to take a very long time
+ // on Miri, which slows down local development and CI jobs. We're not
+ // using Miri to check for the correctness of our code, but rather its
+ // soundness, and at least in the context of these particular tests, a
+ // single loop iteration is just as good for surfacing UB as multiple
+ // iterations are.
+ //
+ // As of the writing of this comment, here's one set of measurements:
+ //
+ // $ # RAND_ITERS == 1
+ // $ cargo miri test -- -Z unstable-options --report-time endian
+ // test byteorder::tests::test_native_endian ... ok <0.049s>
+ // test byteorder::tests::test_non_native_endian ... ok <0.061s>
+ //
+ // $ # RAND_ITERS == 1024
+ // $ cargo miri test -- -Z unstable-options --report-time endian
+ // test byteorder::tests::test_native_endian ... ok <25.716s>
+ // test byteorder::tests::test_non_native_endian ... ok <38.127s>
+ 1
+ } else {
+ 1024
+ };
+
+ #[cfg_attr(test, test)]
+ #[cfg_attr(kani, kani::proof)]
+ fn test_zero() {
+ fn test_zero<T: ByteOrderType>() {
+ assert_eq!(T::ZERO.get(), T::Native::ZERO);
+ }
+
+ call_for_all_types!(test_zero, NativeEndian);
+ call_for_all_types!(test_zero, NonNativeEndian);
+ }
+
+ #[cfg_attr(test, test)]
+ #[cfg_attr(kani, kani::proof)]
+ fn test_max_value() {
+ fn test_max_value<T: ByteOrderTypeUnsigned>() {
+ assert_eq!(T::MAX_VALUE.get(), T::Native::MAX_VALUE);
+ }
+
+ call_for_unsigned_types!(test_max_value, NativeEndian);
+ call_for_unsigned_types!(test_max_value, NonNativeEndian);
+ }
+
+ #[cfg_attr(test, test)]
+ #[cfg_attr(kani, kani::proof)]
+ fn test_endian() {
+ fn test<T: ByteOrderType>(invert: bool) {
+ let mut r = SmallRng::seed_from_u64(RNG_SEED);
+ for _ in 0..RAND_ITERS {
+ let native = T::Native::rand(&mut r);
+ let mut bytes = T::ByteArray::default();
+ bytes.as_bytes_mut().copy_from_slice(native.as_bytes());
+ if invert {
+ bytes = bytes.invert();
+ }
+ let mut from_native = T::new(native);
+ let from_bytes = T::from_bytes(bytes);
+
+ from_native.assert_eq_or_nan(from_bytes);
+ from_native.get().assert_eq_or_nan(native);
+ from_bytes.get().assert_eq_or_nan(native);
+
+ assert_eq!(from_native.into_bytes(), bytes);
+ assert_eq!(from_bytes.into_bytes(), bytes);
+
+ let updated = T::Native::rand(&mut r);
+ from_native.set(updated);
+ from_native.get().assert_eq_or_nan(updated);
+ }
+ }
+
+ fn test_native<T: ByteOrderType>() {
+ test::<T>(false);
+ }
+
+ fn test_non_native<T: ByteOrderType>() {
+ test::<T>(true);
+ }
+
+ call_for_all_types!(test_native, NativeEndian);
+ call_for_all_types!(test_non_native, NonNativeEndian);
+ }
+
+ #[test]
+ fn test_ops_impls() {
+ // Test implementations of traits in `core::ops`. Some of these are
+ // fairly banal, but some are optimized to perform the operation without
+ // swapping byte order (namely, bit-wise operations which are identical
+ // regardless of byte order). These are important to test, and while
+ // we're testing those anyway, it's trivial to test all of the impls.
+
+ fn test<T, F, G, H>(op: F, op_native: G, op_native_checked: Option<H>)
+ where
+ T: ByteOrderType,
+ F: Fn(T, T) -> T,
+ G: Fn(T::Native, T::Native) -> T::Native,
+ H: Fn(T::Native, T::Native) -> Option<T::Native>,
+ {
+ let mut r = SmallRng::seed_from_u64(RNG_SEED);
+ for _ in 0..RAND_ITERS {
+ let n0 = T::Native::rand(&mut r);
+ let n1 = T::Native::rand(&mut r);
+ let t0 = T::new(n0);
+ let t1 = T::new(n1);
+
+ // If this operation would overflow/underflow, skip it rather
+ // than attempt to catch and recover from panics.
+ if matches!(&op_native_checked, Some(checked) if checked(n0, n1).is_none()) {
+ continue;
+ }
+
+ let n_res = op_native(n0, n1);
+ let t_res = op(t0, t1);
+
+ // For `f32` and `f64`, NaN values are not considered equal to
+ // themselves. We store `Option<f32>`/`Option<f64>` and store
+ // NaN as `None` so they can still be compared.
+ let n_res = (!T::Native::is_nan(n_res)).then(|| n_res);
+ let t_res = (!T::Native::is_nan(t_res.get())).then(|| t_res.get());
+ assert_eq!(n_res, t_res);
+ }
+ }
+
+ macro_rules! test {
+ (@binary $trait:ident, $method:ident $([$checked_method:ident])?, $($call_for_macros:ident),*) => {{
+ test!(
+ @inner $trait,
+ core::ops::$trait::$method,
+ core::ops::$trait::$method,
+ {
+ #[allow(unused_mut, unused_assignments)]
+ let mut op_native_checked = None::<fn(T::Native, T::Native) -> Option<T::Native>>;
+ $(
+ op_native_checked = Some(T::Native::$checked_method);
+ )?
+ op_native_checked
+ },
+ $($call_for_macros),*
+ );
+ }};
+ (@unary $trait:ident, $method:ident $([$checked_method:ident])?, $($call_for_macros:ident),*) => {{
+ test!(
+ @inner $trait,
+ |slf, _rhs| core::ops::$trait::$method(slf),
+ |slf, _rhs| core::ops::$trait::$method(slf),
+ {
+ #[allow(unused_mut, unused_assignments)]
+ let mut op_native_checked = None::<fn(T::Native, T::Native) -> Option<T::Native>>;
+ $(
+ op_native_checked = Some(|slf, _rhs| T::Native::$checked_method(slf));
+ )?
+ op_native_checked
+ },
+ $($call_for_macros),*
+ );
+ }};
+ (@inner $trait:ident, $op:expr, $op_native:expr, $op_native_checked:expr, $($call_for_macros:ident),*) => {{
+ fn t<T: ByteOrderType + core::ops::$trait<Output = T>>()
+ where
+ T::Native: core::ops::$trait<Output = T::Native>,
+ {
+ test::<T, _, _, _>(
+ $op,
+ $op_native,
+ $op_native_checked,
+ );
+ }
+
+ $(
+ $call_for_macros!(t, NativeEndian);
+ $call_for_macros!(t, NonNativeEndian);
+ )*
+ }};
+ }
+
+ test!(@binary Add, add[checked_add], call_for_all_types);
+ test!(@binary Div, div[checked_div], call_for_all_types);
+ test!(@binary Mul, mul[checked_mul], call_for_all_types);
+ test!(@binary Rem, rem[checked_rem], call_for_all_types);
+ test!(@binary Sub, sub[checked_sub], call_for_all_types);
+
+ test!(@binary BitAnd, bitand, call_for_unsigned_types, call_for_signed_types);
+ test!(@binary BitOr, bitor, call_for_unsigned_types, call_for_signed_types);
+ test!(@binary BitXor, bitxor, call_for_unsigned_types, call_for_signed_types);
+ test!(@binary Shl, shl[checked_shl], call_for_unsigned_types, call_for_signed_types);
+ test!(@binary Shr, shr[checked_shr], call_for_unsigned_types, call_for_signed_types);
+
+ test!(@unary Not, not, call_for_signed_types, call_for_unsigned_types);
+ test!(@unary Neg, neg, call_for_signed_types, call_for_float_types);
+ }
+
+ #[test]
+ fn test_debug_impl() {
+ // Ensure that Debug applies format options to the inner value.
+ let val = U16::<LE>::new(10);
+ assert_eq!(format!("{:?}", val), "U16(10)");
+ assert_eq!(format!("{:03?}", val), "U16(010)");
+ assert_eq!(format!("{:x?}", val), "U16(a)");
+ }
+}
diff --git a/third_party/rust/zerocopy/src/lib.rs b/third_party/rust/zerocopy/src/lib.rs
new file mode 100644
index 0000000000..1e826439ff
--- /dev/null
+++ b/third_party/rust/zerocopy/src/lib.rs
@@ -0,0 +1,8256 @@
+// Copyright 2018 The Fuchsia Authors
+//
+// Licensed under the 2-Clause BSD License <LICENSE-BSD or
+// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+// After updating the following doc comment, make sure to run the following
+// command to update `README.md` based on its contents:
+//
+// ./generate-readme.sh > README.md
+
+//! *<span style="font-size: 100%; color:grey;">Want to help improve zerocopy?
+//! Fill out our [user survey][user-survey]!</span>*
+//!
+//! ***<span style="font-size: 140%">Fast, safe, <span
+//! style="color:red;">compile error</span>. Pick two.</span>***
+//!
+//! Zerocopy makes zero-cost memory manipulation effortless. We write `unsafe`
+//! so you don't have to.
+//!
+//! # Overview
+//!
+//! Zerocopy provides four core marker traits, each of which can be derived
+//! (e.g., `#[derive(FromZeroes)]`):
+//! - [`FromZeroes`] indicates that a sequence of zero bytes represents a valid
+//! instance of a type
+//! - [`FromBytes`] indicates that a type may safely be converted from an
+//! arbitrary byte sequence
+//! - [`AsBytes`] indicates that a type may safely be converted *to* a byte
+//! sequence
+//! - [`Unaligned`] indicates that a type's alignment requirement is 1
+//!
+//! Types which implement a subset of these traits can then be converted to/from
+//! byte sequences with little to no runtime overhead.
+//!
+//! Zerocopy also provides byte-order aware integer types that support these
+//! conversions; see the [`byteorder`] module. These types are especially useful
+//! for network parsing.
+//!
+//! [user-survey]: https://docs.google.com/forms/d/e/1FAIpQLSdzBNTN9tzwsmtyZxRFNL02K36IWCdHWW2ZBckyQS2xiO3i8Q/viewform?usp=published_options
+//!
+//! # Cargo Features
+//!
+//! - **`alloc`**
+//! By default, `zerocopy` is `no_std`. When the `alloc` feature is enabled,
+//! the `alloc` crate is added as a dependency, and some allocation-related
+//! functionality is added.
+//!
+//! - **`byteorder`** (enabled by default)
+//! Adds the [`byteorder`] module and a dependency on the `byteorder` crate.
+//! The `byteorder` module provides byte order-aware equivalents of the
+//! multi-byte primitive numerical types. Unlike their primitive equivalents,
+//! the types in this module have no alignment requirement and support byte
+//! order conversions. This can be useful in handling file formats, network
+//! packet layouts, etc which don't provide alignment guarantees and which may
+//! use a byte order different from that of the execution platform.
+//!
+//! - **`derive`**
+//! Provides derives for the core marker traits via the `zerocopy-derive`
+//! crate. These derives are re-exported from `zerocopy`, so it is not
+//! necessary to depend on `zerocopy-derive` directly.
+//!
+//! However, you may experience better compile times if you instead directly
+//! depend on both `zerocopy` and `zerocopy-derive` in your `Cargo.toml`,
+//! since doing so will allow Rust to compile these crates in parallel. To do
+//! so, do *not* enable the `derive` feature, and list both dependencies in
+//! your `Cargo.toml` with the same leading non-zero version number; e.g:
+//!
+//! ```toml
+//! [dependencies]
+//! zerocopy = "0.X"
+//! zerocopy-derive = "0.X"
+//! ```
+//!
+//! - **`simd`**
+//! When the `simd` feature is enabled, `FromZeroes`, `FromBytes`, and
+//! `AsBytes` impls are emitted for all stable SIMD types which exist on the
+//! target platform. Note that the layout of SIMD types is not yet stabilized,
+//! so these impls may be removed in the future if layout changes make them
+//! invalid. For more information, see the Unsafe Code Guidelines Reference
+//! page on the [layout of packed SIMD vectors][simd-layout].
+//!
+//! - **`simd-nightly`**
+//! Enables the `simd` feature and adds support for SIMD types which are only
+//! available on nightly. Since these types are unstable, support for any type
+//! may be removed at any point in the future.
+//!
+//! [simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html
+//!
+//! # Security Ethos
+//!
+//! Zerocopy is expressly designed for use in security-critical contexts. We
+//! strive to ensure that that zerocopy code is sound under Rust's current
+//! memory model, and *any future memory model*. We ensure this by:
+//! - **...not 'guessing' about Rust's semantics.**
+//! We annotate `unsafe` code with a precise rationale for its soundness that
+//! cites a relevant section of Rust's official documentation. When Rust's
+//! documented semantics are unclear, we work with the Rust Operational
+//! Semantics Team to clarify Rust's documentation.
+//! - **...rigorously testing our implementation.**
+//! We run tests using [Miri], ensuring that zerocopy is sound across a wide
+//! array of supported target platforms of varying endianness and pointer
+//! width, and across both current and experimental memory models of Rust.
+//! - **...formally proving the correctness of our implementation.**
+//! We apply formal verification tools like [Kani][kani] to prove zerocopy's
+//! correctness.
+//!
+//! For more information, see our full [soundness policy].
+//!
+//! [Miri]: https://github.com/rust-lang/miri
+//! [Kani]: https://github.com/model-checking/kani
+//! [soundness policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#soundness
+//!
+//! # Relationship to Project Safe Transmute
+//!
+//! [Project Safe Transmute] is an official initiative of the Rust Project to
+//! develop language-level support for safer transmutation. The Project consults
+//! with crates like zerocopy to identify aspects of safer transmutation that
+//! would benefit from compiler support, and has developed an [experimental,
+//! compiler-supported analysis][mcp-transmutability] which determines whether,
+//! for a given type, any value of that type may be soundly transmuted into
+//! another type. Once this functionality is sufficiently mature, zerocopy
+//! intends to replace its internal transmutability analysis (implemented by our
+//! custom derives) with the compiler-supported one. This change will likely be
+//! an implementation detail that is invisible to zerocopy's users.
+//!
+//! Project Safe Transmute will not replace the need for most of zerocopy's
+//! higher-level abstractions. The experimental compiler analysis is a tool for
+//! checking the soundness of `unsafe` code, not a tool to avoid writing
+//! `unsafe` code altogether. For the foreseeable future, crates like zerocopy
+//! will still be required in order to provide higher-level abstractions on top
+//! of the building block provided by Project Safe Transmute.
+//!
+//! [Project Safe Transmute]: https://rust-lang.github.io/rfcs/2835-project-safe-transmute.html
+//! [mcp-transmutability]: https://github.com/rust-lang/compiler-team/issues/411
+//!
+//! # MSRV
+//!
+//! See our [MSRV policy].
+//!
+//! [MSRV policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#msrv
+//!
+//! # Changelog
+//!
+//! Zerocopy uses [GitHub Releases].
+//!
+//! [GitHub Releases]: https://github.com/google/zerocopy/releases
+
+// Sometimes we want to use lints which were added after our MSRV.
+// `unknown_lints` is `warn` by default and we deny warnings in CI, so without
+// this attribute, any unknown lint would cause a CI failure when testing with
+// our MSRV.
+#![allow(unknown_lints)]
+#![deny(renamed_and_removed_lints)]
+#![deny(
+ anonymous_parameters,
+ deprecated_in_future,
+ illegal_floating_point_literal_pattern,
+ late_bound_lifetime_arguments,
+ missing_copy_implementations,
+ missing_debug_implementations,
+ missing_docs,
+ path_statements,
+ patterns_in_fns_without_body,
+ rust_2018_idioms,
+ trivial_numeric_casts,
+ unreachable_pub,
+ unsafe_op_in_unsafe_fn,
+ unused_extern_crates,
+ unused_qualifications,
+ variant_size_differences
+)]
+#![cfg_attr(
+ __INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS,
+ deny(fuzzy_provenance_casts, lossy_provenance_casts)
+)]
+#![deny(
+ clippy::all,
+ clippy::alloc_instead_of_core,
+ clippy::arithmetic_side_effects,
+ clippy::as_underscore,
+ clippy::assertions_on_result_states,
+ clippy::as_conversions,
+ clippy::correctness,
+ clippy::dbg_macro,
+ clippy::decimal_literal_representation,
+ clippy::get_unwrap,
+ clippy::indexing_slicing,
+ clippy::missing_inline_in_public_items,
+ clippy::missing_safety_doc,
+ clippy::obfuscated_if_else,
+ clippy::perf,
+ clippy::print_stdout,
+ clippy::std_instead_of_core,
+ clippy::style,
+ clippy::suspicious,
+ clippy::todo,
+ clippy::undocumented_unsafe_blocks,
+ clippy::unimplemented,
+ clippy::unnested_or_patterns,
+ clippy::unwrap_used,
+ clippy::use_debug
+)]
+#![deny(
+ rustdoc::bare_urls,
+ rustdoc::broken_intra_doc_links,
+ rustdoc::invalid_codeblock_attributes,
+ rustdoc::invalid_html_tags,
+ rustdoc::invalid_rust_codeblocks,
+ rustdoc::missing_crate_level_docs,
+ rustdoc::private_intra_doc_links
+)]
+// In test code, it makes sense to weight more heavily towards concise, readable
+// code over correct or debuggable code.
+#![cfg_attr(any(test, kani), allow(
+ // In tests, you get line numbers and have access to source code, so panic
+ // messages are less important. You also often unwrap a lot, which would
+ // make expect'ing instead very verbose.
+ clippy::unwrap_used,
+ // In tests, there's no harm to "panic risks" - the worst that can happen is
+ // that your test will fail, and you'll fix it. By contrast, panic risks in
+ // production code introduce the possibly of code panicking unexpectedly "in
+ // the field".
+ clippy::arithmetic_side_effects,
+ clippy::indexing_slicing,
+))]
+#![cfg_attr(not(test), no_std)]
+#![cfg_attr(feature = "simd-nightly", feature(stdsimd))]
+#![cfg_attr(doc_cfg, feature(doc_cfg))]
+#![cfg_attr(
+ __INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS,
+ feature(layout_for_ptr, strict_provenance)
+)]
+
+// This is a hack to allow zerocopy-derive derives to work in this crate. They
+// assume that zerocopy is linked as an extern crate, so they access items from
+// it as `zerocopy::Xxx`. This makes that still work.
+#[cfg(any(feature = "derive", test))]
+extern crate self as zerocopy;
+
+#[macro_use]
+mod macros;
+
+#[cfg(feature = "byteorder")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "byteorder")))]
+pub mod byteorder;
+#[doc(hidden)]
+pub mod macro_util;
+mod post_monomorphization_compile_fail_tests;
+mod util;
+// TODO(#252): If we make this pub, come up with a better name.
+mod wrappers;
+
+#[cfg(feature = "byteorder")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "byteorder")))]
+pub use crate::byteorder::*;
+pub use crate::wrappers::*;
+
+#[cfg(any(feature = "derive", test))]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
+pub use zerocopy_derive::Unaligned;
+
+// `pub use` separately here so that we can mark it `#[doc(hidden)]`.
+//
+// TODO(#29): Remove this or add a doc comment.
+#[cfg(any(feature = "derive", test))]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
+#[doc(hidden)]
+pub use zerocopy_derive::KnownLayout;
+
+use core::{
+ cell::{self, RefMut},
+ cmp::Ordering,
+ fmt::{self, Debug, Display, Formatter},
+ hash::Hasher,
+ marker::PhantomData,
+ mem::{self, ManuallyDrop, MaybeUninit},
+ num::{
+ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
+ NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
+ },
+ ops::{Deref, DerefMut},
+ ptr::{self, NonNull},
+ slice,
+};
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+#[cfg(feature = "alloc")]
+use alloc::{boxed::Box, vec::Vec};
+
+#[cfg(any(feature = "alloc", kani))]
+use core::alloc::Layout;
+
+// Used by `TryFromBytes::is_bit_valid`.
+#[doc(hidden)]
+pub use crate::util::ptr::Ptr;
+
+// For each polyfill, as soon as the corresponding feature is stable, the
+// polyfill import will be unused because method/function resolution will prefer
+// the inherent method/function over a trait method/function. Thus, we suppress
+// the `unused_imports` warning.
+//
+// See the documentation on `util::polyfills` for more information.
+#[allow(unused_imports)]
+use crate::util::polyfills::NonNullExt as _;
+
+#[rustversion::nightly]
+#[cfg(all(test, not(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)))]
+const _: () = {
+ #[deprecated = "some tests may be skipped due to missing RUSTFLAGS=\"--cfg __INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS\""]
+ const _WARNING: () = ();
+ #[warn(deprecated)]
+ _WARNING
+};
+
+/// The target pointer width, counted in bits.
+const POINTER_WIDTH_BITS: usize = mem::size_of::<usize>() * 8;
+
+/// The layout of a type which might be dynamically-sized.
+///
+/// `DstLayout` describes the layout of sized types, slice types, and "slice
+/// DSTs" - ie, those that are known by the type system to have a trailing slice
+/// (as distinguished from `dyn Trait` types - such types *might* have a
+/// trailing slice type, but the type system isn't aware of it).
+///
+/// # Safety
+///
+/// Unlike [`core::alloc::Layout`], `DstLayout` is only used to describe full
+/// Rust types - ie, those that satisfy the layout requirements outlined by
+/// [the reference]. Callers may assume that an instance of `DstLayout`
+/// satisfies any conditions imposed on Rust types by the reference.
+///
+/// If `layout: DstLayout` describes a type, `T`, then it is guaranteed that:
+/// - `layout.align` is equal to `T`'s alignment
+/// - If `layout.size_info` is `SizeInfo::Sized { size }`, then `T: Sized` and
+/// `size_of::<T>() == size`
+/// - If `layout.size_info` is `SizeInfo::SliceDst(slice_layout)`, then
+/// - `T` is a slice DST
+/// - The `size` of an instance of `T` with `elems` trailing slice elements is
+/// equal to `slice_layout.offset + slice_layout.elem_size * elems` rounded up
+/// to the nearest multiple of `layout.align`. Any bytes in the range
+/// `[slice_layout.offset + slice_layout.elem_size * elems, size)` are padding
+/// and must not be assumed to be initialized.
+///
+/// [the reference]: https://doc.rust-lang.org/reference/type-layout.html
+#[doc(hidden)]
+#[allow(missing_debug_implementations, missing_copy_implementations)]
+#[cfg_attr(any(kani, test), derive(Copy, Clone, Debug, PartialEq, Eq))]
+pub struct DstLayout {
+ align: NonZeroUsize,
+ size_info: SizeInfo,
+}
+
+#[cfg_attr(any(kani, test), derive(Copy, Clone, Debug, PartialEq, Eq))]
+enum SizeInfo<E = usize> {
+ Sized { _size: usize },
+ SliceDst(TrailingSliceLayout<E>),
+}
+
+#[cfg_attr(any(kani, test), derive(Copy, Clone, Debug, PartialEq, Eq))]
+struct TrailingSliceLayout<E = usize> {
+ // The offset of the first byte of the trailing slice field. Note that this
+ // is NOT the same as the minimum size of the type. For example, consider
+ // the following type:
+ //
+ // struct Foo {
+ // a: u16,
+ // b: u8,
+ // c: [u8],
+ // }
+ //
+ // In `Foo`, `c` is at byte offset 3. When `c.len() == 0`, `c` is followed
+ // by a padding byte.
+ _offset: usize,
+ // The size of the element type of the trailing slice field.
+ _elem_size: E,
+}
+
+impl SizeInfo {
+ /// Attempts to create a `SizeInfo` from `Self` in which `elem_size` is a
+ /// `NonZeroUsize`. If `elem_size` is 0, returns `None`.
+ #[allow(unused)]
+ const fn try_to_nonzero_elem_size(&self) -> Option<SizeInfo<NonZeroUsize>> {
+ Some(match *self {
+ SizeInfo::Sized { _size } => SizeInfo::Sized { _size },
+ SizeInfo::SliceDst(TrailingSliceLayout { _offset, _elem_size }) => {
+ if let Some(_elem_size) = NonZeroUsize::new(_elem_size) {
+ SizeInfo::SliceDst(TrailingSliceLayout { _offset, _elem_size })
+ } else {
+ return None;
+ }
+ }
+ })
+ }
+}
+
+#[doc(hidden)]
+#[derive(Copy, Clone)]
+#[cfg_attr(test, derive(Debug))]
+#[allow(missing_debug_implementations)]
+pub enum _CastType {
+ _Prefix,
+ _Suffix,
+}
+
+impl DstLayout {
+ /// The minimum possible alignment of a type.
+ const MIN_ALIGN: NonZeroUsize = match NonZeroUsize::new(1) {
+ Some(min_align) => min_align,
+ None => unreachable!(),
+ };
+
+ /// The maximum theoretic possible alignment of a type.
+ ///
+ /// For compatibility with future Rust versions, this is defined as the
+ /// maximum power-of-two that fits into a `usize`. See also
+ /// [`DstLayout::CURRENT_MAX_ALIGN`].
+ const THEORETICAL_MAX_ALIGN: NonZeroUsize =
+ match NonZeroUsize::new(1 << (POINTER_WIDTH_BITS - 1)) {
+ Some(max_align) => max_align,
+ None => unreachable!(),
+ };
+
+ /// The current, documented max alignment of a type \[1\].
+ ///
+ /// \[1\] Per <https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers>:
+ ///
+ /// The alignment value must be a power of two from 1 up to
+ /// 2<sup>29</sup>.
+ #[cfg(not(kani))]
+ const CURRENT_MAX_ALIGN: NonZeroUsize = match NonZeroUsize::new(1 << 28) {
+ Some(max_align) => max_align,
+ None => unreachable!(),
+ };
+
+ /// Constructs a `DstLayout` for a zero-sized type with `repr_align`
+ /// alignment (or 1). If `repr_align` is provided, then it must be a power
+ /// of two.
+ ///
+ /// # Panics
+ ///
+ /// This function panics if the supplied `repr_align` is not a power of two.
+ ///
+ /// # Safety
+ ///
+ /// Unsafe code may assume that the contract of this function is satisfied.
+ #[doc(hidden)]
+ #[inline]
+ pub const fn new_zst(repr_align: Option<NonZeroUsize>) -> DstLayout {
+ let align = match repr_align {
+ Some(align) => align,
+ None => Self::MIN_ALIGN,
+ };
+
+ assert!(align.is_power_of_two());
+
+ DstLayout { align, size_info: SizeInfo::Sized { _size: 0 } }
+ }
+
+ /// Constructs a `DstLayout` which describes `T`.
+ ///
+ /// # Safety
+ ///
+ /// Unsafe code may assume that `DstLayout` is the correct layout for `T`.
+ #[doc(hidden)]
+ #[inline]
+ pub const fn for_type<T>() -> DstLayout {
+ // SAFETY: `align` is correct by construction. `T: Sized`, and so it is
+ // sound to initialize `size_info` to `SizeInfo::Sized { size }`; the
+ // `size` field is also correct by construction.
+ DstLayout {
+ align: match NonZeroUsize::new(mem::align_of::<T>()) {
+ Some(align) => align,
+ None => unreachable!(),
+ },
+ size_info: SizeInfo::Sized { _size: mem::size_of::<T>() },
+ }
+ }
+
+ /// Constructs a `DstLayout` which describes `[T]`.
+ ///
+ /// # Safety
+ ///
+ /// Unsafe code may assume that `DstLayout` is the correct layout for `[T]`.
+ const fn for_slice<T>() -> DstLayout {
+ // SAFETY: The alignment of a slice is equal to the alignment of its
+ // element type, and so `align` is initialized correctly.
+ //
+ // Since this is just a slice type, there is no offset between the
+ // beginning of the type and the beginning of the slice, so it is
+ // correct to set `offset: 0`. The `elem_size` is correct by
+ // construction. Since `[T]` is a (degenerate case of a) slice DST, it
+ // is correct to initialize `size_info` to `SizeInfo::SliceDst`.
+ DstLayout {
+ align: match NonZeroUsize::new(mem::align_of::<T>()) {
+ Some(align) => align,
+ None => unreachable!(),
+ },
+ size_info: SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: 0,
+ _elem_size: mem::size_of::<T>(),
+ }),
+ }
+ }
+
+ /// Like `Layout::extend`, this creates a layout that describes a record
+ /// whose layout consists of `self` followed by `next` that includes the
+ /// necessary inter-field padding, but not any trailing padding.
+ ///
+ /// In order to match the layout of a `#[repr(C)]` struct, this method
+ /// should be invoked for each field in declaration order. To add trailing
+ /// padding, call `DstLayout::pad_to_align` after extending the layout for
+ /// all fields. If `self` corresponds to a type marked with
+ /// `repr(packed(N))`, then `repr_packed` should be set to `Some(N)`,
+ /// otherwise `None`.
+ ///
+ /// This method cannot be used to match the layout of a record with the
+ /// default representation, as that representation is mostly unspecified.
+ ///
+ /// # Safety
+ ///
+ /// If a (potentially hypothetical) valid `repr(C)` Rust type begins with
+ /// fields whose layout are `self`, and those fields are immediately
+ /// followed by a field whose layout is `field`, then unsafe code may rely
+ /// on `self.extend(field, repr_packed)` producing a layout that correctly
+ /// encompasses those two components.
+ ///
+ /// We make no guarantees to the behavior of this method if these fragments
+ /// cannot appear in a valid Rust type (e.g., the concatenation of the
+ /// layouts would lead to a size larger than `isize::MAX`).
+ #[doc(hidden)]
+ #[inline]
+ pub const fn extend(self, field: DstLayout, repr_packed: Option<NonZeroUsize>) -> Self {
+ use util::{core_layout::padding_needed_for, max, min};
+
+ // If `repr_packed` is `None`, there are no alignment constraints, and
+ // the value can be defaulted to `THEORETICAL_MAX_ALIGN`.
+ let max_align = match repr_packed {
+ Some(max_align) => max_align,
+ None => Self::THEORETICAL_MAX_ALIGN,
+ };
+
+ assert!(max_align.is_power_of_two());
+
+ // We use Kani to prove that this method is robust to future increases
+ // in Rust's maximum allowed alignment. However, if such a change ever
+ // actually occurs, we'd like to be notified via assertion failures.
+ #[cfg(not(kani))]
+ {
+ debug_assert!(self.align.get() <= DstLayout::CURRENT_MAX_ALIGN.get());
+ debug_assert!(field.align.get() <= DstLayout::CURRENT_MAX_ALIGN.get());
+ if let Some(repr_packed) = repr_packed {
+ debug_assert!(repr_packed.get() <= DstLayout::CURRENT_MAX_ALIGN.get());
+ }
+ }
+
+ // The field's alignment is clamped by `repr_packed` (i.e., the
+ // `repr(packed(N))` attribute, if any) [1].
+ //
+ // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers:
+ //
+ // The alignments of each field, for the purpose of positioning
+ // fields, is the smaller of the specified alignment and the alignment
+ // of the field's type.
+ let field_align = min(field.align, max_align);
+
+ // The struct's alignment is the maximum of its previous alignment and
+ // `field_align`.
+ let align = max(self.align, field_align);
+
+ let size_info = match self.size_info {
+ // If the layout is already a DST, we panic; DSTs cannot be extended
+ // with additional fields.
+ SizeInfo::SliceDst(..) => panic!("Cannot extend a DST with additional fields."),
+
+ SizeInfo::Sized { _size: preceding_size } => {
+ // Compute the minimum amount of inter-field padding needed to
+ // satisfy the field's alignment, and offset of the trailing
+ // field. [1]
+ //
+ // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers:
+ //
+ // Inter-field padding is guaranteed to be the minimum
+ // required in order to satisfy each field's (possibly
+ // altered) alignment.
+ let padding = padding_needed_for(preceding_size, field_align);
+
+ // This will not panic (and is proven to not panic, with Kani)
+ // if the layout components can correspond to a leading layout
+ // fragment of a valid Rust type, but may panic otherwise (e.g.,
+ // combining or aligning the components would create a size
+ // exceeding `isize::MAX`).
+ let offset = match preceding_size.checked_add(padding) {
+ Some(offset) => offset,
+ None => panic!("Adding padding to `self`'s size overflows `usize`."),
+ };
+
+ match field.size_info {
+ SizeInfo::Sized { _size: field_size } => {
+ // If the trailing field is sized, the resulting layout
+ // will be sized. Its size will be the sum of the
+ // preceeding layout, the size of the new field, and the
+ // size of inter-field padding between the two.
+ //
+ // This will not panic (and is proven with Kani to not
+ // panic) if the layout components can correspond to a
+ // leading layout fragment of a valid Rust type, but may
+ // panic otherwise (e.g., combining or aligning the
+ // components would create a size exceeding
+ // `usize::MAX`).
+ let size = match offset.checked_add(field_size) {
+ Some(size) => size,
+ None => panic!("`field` cannot be appended without the total size overflowing `usize`"),
+ };
+ SizeInfo::Sized { _size: size }
+ }
+ SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: trailing_offset,
+ _elem_size,
+ }) => {
+ // If the trailing field is dynamically sized, so too
+ // will the resulting layout. The offset of the trailing
+ // slice component is the sum of the offset of the
+ // trailing field and the trailing slice offset within
+ // that field.
+ //
+ // This will not panic (and is proven with Kani to not
+ // panic) if the layout components can correspond to a
+ // leading layout fragment of a valid Rust type, but may
+ // panic otherwise (e.g., combining or aligning the
+ // components would create a size exceeding
+ // `usize::MAX`).
+ let offset = match offset.checked_add(trailing_offset) {
+ Some(offset) => offset,
+ None => panic!("`field` cannot be appended without the total size overflowing `usize`"),
+ };
+ SizeInfo::SliceDst(TrailingSliceLayout { _offset: offset, _elem_size })
+ }
+ }
+ }
+ };
+
+ DstLayout { align, size_info }
+ }
+
+ /// Like `Layout::pad_to_align`, this routine rounds the size of this layout
+ /// up to the nearest multiple of this type's alignment or `repr_packed`
+ /// (whichever is less). This method leaves DST layouts unchanged, since the
+ /// trailing padding of DSTs is computed at runtime.
+ ///
+ /// In order to match the layout of a `#[repr(C)]` struct, this method
+ /// should be invoked after the invocations of [`DstLayout::extend`]. If
+ /// `self` corresponds to a type marked with `repr(packed(N))`, then
+ /// `repr_packed` should be set to `Some(N)`, otherwise `None`.
+ ///
+ /// This method cannot be used to match the layout of a record with the
+ /// default representation, as that representation is mostly unspecified.
+ ///
+ /// # Safety
+ ///
+ /// If a (potentially hypothetical) valid `repr(C)` type begins with fields
+ /// whose layout are `self` followed only by zero or more bytes of trailing
+ /// padding (not included in `self`), then unsafe code may rely on
+ /// `self.pad_to_align(repr_packed)` producing a layout that correctly
+ /// encapsulates the layout of that type.
+ ///
+ /// We make no guarantees to the behavior of this method if `self` cannot
+ /// appear in a valid Rust type (e.g., because the addition of trailing
+ /// padding would lead to a size larger than `isize::MAX`).
+ #[doc(hidden)]
+ #[inline]
+ pub const fn pad_to_align(self) -> Self {
+ use util::core_layout::padding_needed_for;
+
+ let size_info = match self.size_info {
+ // For sized layouts, we add the minimum amount of trailing padding
+ // needed to satisfy alignment.
+ SizeInfo::Sized { _size: unpadded_size } => {
+ let padding = padding_needed_for(unpadded_size, self.align);
+ let size = match unpadded_size.checked_add(padding) {
+ Some(size) => size,
+ None => panic!("Adding padding caused size to overflow `usize`."),
+ };
+ SizeInfo::Sized { _size: size }
+ }
+ // For DST layouts, trailing padding depends on the length of the
+ // trailing DST and is computed at runtime. This does not alter the
+ // offset or element size of the layout, so we leave `size_info`
+ // unchanged.
+ size_info @ SizeInfo::SliceDst(_) => size_info,
+ };
+
+ DstLayout { align: self.align, size_info }
+ }
+
+ /// Validates that a cast is sound from a layout perspective.
+ ///
+ /// Validates that the size and alignment requirements of a type with the
+ /// layout described in `self` would not be violated by performing a
+ /// `cast_type` cast from a pointer with address `addr` which refers to a
+ /// memory region of size `bytes_len`.
+ ///
+ /// If the cast is valid, `validate_cast_and_convert_metadata` returns
+ /// `(elems, split_at)`. If `self` describes a dynamically-sized type, then
+ /// `elems` is the maximum number of trailing slice elements for which a
+ /// cast would be valid (for sized types, `elem` is meaningless and should
+ /// be ignored). `split_at` is the index at which to split the memory region
+ /// in order for the prefix (suffix) to contain the result of the cast, and
+ /// in order for the remaining suffix (prefix) to contain the leftover
+ /// bytes.
+ ///
+ /// There are three conditions under which a cast can fail:
+ /// - The smallest possible value for the type is larger than the provided
+ /// memory region
+ /// - A prefix cast is requested, and `addr` does not satisfy `self`'s
+ /// alignment requirement
+ /// - A suffix cast is requested, and `addr + bytes_len` does not satisfy
+ /// `self`'s alignment requirement (as a consequence, since all instances
+ /// of the type are a multiple of its alignment, no size for the type will
+ /// result in a starting address which is properly aligned)
+ ///
+ /// # Safety
+ ///
+ /// The caller may assume that this implementation is correct, and may rely
+ /// on that assumption for the soundness of their code. In particular, the
+ /// caller may assume that, if `validate_cast_and_convert_metadata` returns
+ /// `Some((elems, split_at))`, then:
+ /// - A pointer to the type (for dynamically sized types, this includes
+ /// `elems` as its pointer metadata) describes an object of size `size <=
+ /// bytes_len`
+ /// - If this is a prefix cast:
+ /// - `addr` satisfies `self`'s alignment
+ /// - `size == split_at`
+ /// - If this is a suffix cast:
+ /// - `split_at == bytes_len - size`
+ /// - `addr + split_at` satisfies `self`'s alignment
+ ///
+ /// Note that this method does *not* ensure that a pointer constructed from
+ /// its return values will be a valid pointer. In particular, this method
+ /// does not reason about `isize` overflow, which is a requirement of many
+ /// Rust pointer APIs, and may at some point be determined to be a validity
+ /// invariant of pointer types themselves. This should never be a problem so
+ /// long as the arguments to this method are derived from a known-valid
+ /// pointer (e.g., one derived from a safe Rust reference), but it is
+ /// nonetheless the caller's responsibility to justify that pointer
+ /// arithmetic will not overflow based on a safety argument *other than* the
+ /// mere fact that this method returned successfully.
+ ///
+ /// # Panics
+ ///
+ /// `validate_cast_and_convert_metadata` will panic if `self` describes a
+ /// DST whose trailing slice element is zero-sized.
+ ///
+ /// If `addr + bytes_len` overflows `usize`,
+ /// `validate_cast_and_convert_metadata` may panic, or it may return
+ /// incorrect results. No guarantees are made about when
+ /// `validate_cast_and_convert_metadata` will panic. The caller should not
+ /// rely on `validate_cast_and_convert_metadata` panicking in any particular
+ /// condition, even if `debug_assertions` are enabled.
+ #[allow(unused)]
+ const fn validate_cast_and_convert_metadata(
+ &self,
+ addr: usize,
+ bytes_len: usize,
+ cast_type: _CastType,
+ ) -> Option<(usize, usize)> {
+ // `debug_assert!`, but with `#[allow(clippy::arithmetic_side_effects)]`.
+ macro_rules! __debug_assert {
+ ($e:expr $(, $msg:expr)?) => {
+ debug_assert!({
+ #[allow(clippy::arithmetic_side_effects)]
+ let e = $e;
+ e
+ } $(, $msg)?);
+ };
+ }
+
+ // Note that, in practice, `self` is always a compile-time constant. We
+ // do this check earlier than needed to ensure that we always panic as a
+ // result of bugs in the program (such as calling this function on an
+ // invalid type) instead of allowing this panic to be hidden if the cast
+ // would have failed anyway for runtime reasons (such as a too-small
+ // memory region).
+ //
+ // TODO(#67): Once our MSRV is 1.65, use let-else:
+ // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#let-else-statements
+ let size_info = match self.size_info.try_to_nonzero_elem_size() {
+ Some(size_info) => size_info,
+ None => panic!("attempted to cast to slice type with zero-sized element"),
+ };
+
+ // Precondition
+ __debug_assert!(addr.checked_add(bytes_len).is_some(), "`addr` + `bytes_len` > usize::MAX");
+
+ // Alignment checks go in their own block to avoid introducing variables
+ // into the top-level scope.
+ {
+ // We check alignment for `addr` (for prefix casts) or `addr +
+ // bytes_len` (for suffix casts). For a prefix cast, the correctness
+ // of this check is trivial - `addr` is the address the object will
+ // live at.
+ //
+ // For a suffix cast, we know that all valid sizes for the type are
+ // a multiple of the alignment (and by safety precondition, we know
+ // `DstLayout` may only describe valid Rust types). Thus, a
+ // validly-sized instance which lives at a validly-aligned address
+ // must also end at a validly-aligned address. Thus, if the end
+ // address for a suffix cast (`addr + bytes_len`) is not aligned,
+ // then no valid start address will be aligned either.
+ let offset = match cast_type {
+ _CastType::_Prefix => 0,
+ _CastType::_Suffix => bytes_len,
+ };
+
+ // Addition is guaranteed not to overflow because `offset <=
+ // bytes_len`, and `addr + bytes_len <= usize::MAX` is a
+ // precondition of this method. Modulus is guaranteed not to divide
+ // by 0 because `align` is non-zero.
+ #[allow(clippy::arithmetic_side_effects)]
+ if (addr + offset) % self.align.get() != 0 {
+ return None;
+ }
+ }
+
+ let (elems, self_bytes) = match size_info {
+ SizeInfo::Sized { _size: size } => {
+ if size > bytes_len {
+ return None;
+ }
+ (0, size)
+ }
+ SizeInfo::SliceDst(TrailingSliceLayout { _offset: offset, _elem_size: elem_size }) => {
+ // Calculate the maximum number of bytes that could be consumed
+ // - any number of bytes larger than this will either not be a
+ // multiple of the alignment, or will be larger than
+ // `bytes_len`.
+ let max_total_bytes =
+ util::round_down_to_next_multiple_of_alignment(bytes_len, self.align);
+ // Calculate the maximum number of bytes that could be consumed
+ // by the trailing slice.
+ //
+ // TODO(#67): Once our MSRV is 1.65, use let-else:
+ // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#let-else-statements
+ let max_slice_and_padding_bytes = match max_total_bytes.checked_sub(offset) {
+ Some(max) => max,
+ // `bytes_len` too small even for 0 trailing slice elements.
+ None => return None,
+ };
+
+ // Calculate the number of elements that fit in
+ // `max_slice_and_padding_bytes`; any remaining bytes will be
+ // considered padding.
+ //
+ // Guaranteed not to divide by zero: `elem_size` is non-zero.
+ #[allow(clippy::arithmetic_side_effects)]
+ let elems = max_slice_and_padding_bytes / elem_size.get();
+ // Guaranteed not to overflow on multiplication: `usize::MAX >=
+ // max_slice_and_padding_bytes >= (max_slice_and_padding_bytes /
+ // elem_size) * elem_size`.
+ //
+ // Guaranteed not to overflow on addition:
+ // - max_slice_and_padding_bytes == max_total_bytes - offset
+ // - elems * elem_size <= max_slice_and_padding_bytes == max_total_bytes - offset
+ // - elems * elem_size + offset <= max_total_bytes <= usize::MAX
+ #[allow(clippy::arithmetic_side_effects)]
+ let without_padding = offset + elems * elem_size.get();
+ // `self_bytes` is equal to the offset bytes plus the bytes
+ // consumed by the trailing slice plus any padding bytes
+ // required to satisfy the alignment. Note that we have computed
+ // the maximum number of trailing slice elements that could fit
+ // in `self_bytes`, so any padding is guaranteed to be less than
+ // the size of an extra element.
+ //
+ // Guaranteed not to overflow:
+ // - By previous comment: without_padding == elems * elem_size +
+ // offset <= max_total_bytes
+ // - By construction, `max_total_bytes` is a multiple of
+ // `self.align`.
+ // - At most, adding padding needed to round `without_padding`
+ // up to the next multiple of the alignment will bring
+ // `self_bytes` up to `max_total_bytes`.
+ #[allow(clippy::arithmetic_side_effects)]
+ let self_bytes = without_padding
+ + util::core_layout::padding_needed_for(without_padding, self.align);
+ (elems, self_bytes)
+ }
+ };
+
+ __debug_assert!(self_bytes <= bytes_len);
+
+ let split_at = match cast_type {
+ _CastType::_Prefix => self_bytes,
+ // Guaranteed not to underflow:
+ // - In the `Sized` branch, only returns `size` if `size <=
+ // bytes_len`.
+ // - In the `SliceDst` branch, calculates `self_bytes <=
+ // max_toatl_bytes`, which is upper-bounded by `bytes_len`.
+ #[allow(clippy::arithmetic_side_effects)]
+ _CastType::_Suffix => bytes_len - self_bytes,
+ };
+
+ Some((elems, split_at))
+ }
+}
+
+/// A trait which carries information about a type's layout that is used by the
+/// internals of this crate.
+///
+/// This trait is not meant for consumption by code outside of this crate. While
+/// the normal semver stability guarantees apply with respect to which types
+/// implement this trait and which trait implementations are implied by this
+/// trait, no semver stability guarantees are made regarding its internals; they
+/// may change at any time, and code which makes use of them may break.
+///
+/// # Safety
+///
+/// This trait does not convey any safety guarantees to code outside this crate.
+#[doc(hidden)] // TODO: Remove this once KnownLayout is used by other APIs
+pub unsafe trait KnownLayout {
+ // The `Self: Sized` bound makes it so that `KnownLayout` can still be
+ // object safe. It's not currently object safe thanks to `const LAYOUT`, and
+ // it likely won't be in the future, but there's no reason not to be
+ // forwards-compatible with object safety.
+ #[doc(hidden)]
+ fn only_derive_is_allowed_to_implement_this_trait()
+ where
+ Self: Sized;
+
+ #[doc(hidden)]
+ const LAYOUT: DstLayout;
+
+ /// SAFETY: The returned pointer has the same address and provenance as
+ /// `bytes`. If `Self` is a DST, the returned pointer's referent has `elems`
+ /// elements in its trailing slice. If `Self` is sized, `elems` is ignored.
+ #[doc(hidden)]
+ fn raw_from_ptr_len(bytes: NonNull<u8>, elems: usize) -> NonNull<Self>;
+}
+
+// SAFETY: Delegates safety to `DstLayout::for_slice`.
+unsafe impl<T: KnownLayout> KnownLayout for [T] {
+ #[allow(clippy::missing_inline_in_public_items)]
+ fn only_derive_is_allowed_to_implement_this_trait()
+ where
+ Self: Sized,
+ {
+ }
+ const LAYOUT: DstLayout = DstLayout::for_slice::<T>();
+
+ // SAFETY: `.cast` preserves address and provenance. The returned pointer
+ // refers to an object with `elems` elements by construction.
+ #[inline(always)]
+ fn raw_from_ptr_len(data: NonNull<u8>, elems: usize) -> NonNull<Self> {
+ // TODO(#67): Remove this allow. See NonNullExt for more details.
+ #[allow(unstable_name_collisions)]
+ NonNull::slice_from_raw_parts(data.cast::<T>(), elems)
+ }
+}
+
+#[rustfmt::skip]
+impl_known_layout!(
+ (),
+ u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64,
+ bool, char,
+ NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
+ NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize
+);
+#[rustfmt::skip]
+impl_known_layout!(
+ T => Option<T>,
+ T: ?Sized => PhantomData<T>,
+ T => Wrapping<T>,
+ T => MaybeUninit<T>,
+ T: ?Sized => *const T,
+ T: ?Sized => *mut T,
+);
+impl_known_layout!(const N: usize, T => [T; N]);
+
+safety_comment! {
+ /// SAFETY:
+ /// `str` and `ManuallyDrop<[T]>` [1] have the same representations as
+ /// `[u8]` and `[T]` repsectively. `str` has different bit validity than
+ /// `[u8]`, but that doesn't affect the soundness of this impl.
+ ///
+ /// [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html:
+ ///
+ /// `ManuallyDrop<T>` is guaranteed to have the same layout and bit
+ /// validity as `T`
+ ///
+ /// TODO(#429):
+ /// - Add quotes from docs.
+ /// - Once [1] (added in
+ /// https://github.com/rust-lang/rust/pull/115522) is available on stable,
+ /// quote the stable docs instead of the nightly docs.
+ unsafe_impl_known_layout!(#[repr([u8])] str);
+ unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ManuallyDrop<T>);
+}
+
+/// Analyzes whether a type is [`FromZeroes`].
+///
+/// This derive analyzes, at compile time, whether the annotated type satisfies
+/// the [safety conditions] of `FromZeroes` and implements `FromZeroes` if it is
+/// sound to do so. This derive can be applied to structs, enums, and unions;
+/// e.g.:
+///
+/// ```
+/// # use zerocopy_derive::FromZeroes;
+/// #[derive(FromZeroes)]
+/// struct MyStruct {
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes)]
+/// #[repr(u8)]
+/// enum MyEnum {
+/// # Variant0,
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes)]
+/// union MyUnion {
+/// # variant: u8,
+/// # /*
+/// ...
+/// # */
+/// }
+/// ```
+///
+/// [safety conditions]: trait@FromZeroes#safety
+///
+/// # Analysis
+///
+/// *This section describes, roughly, the analysis performed by this derive to
+/// determine whether it is sound to implement `FromZeroes` for a given type.
+/// Unless you are modifying the implementation of this derive, or attempting to
+/// manually implement `FromZeroes` for a type yourself, you don't need to read
+/// this section.*
+///
+/// If a type has the following properties, then this derive can implement
+/// `FromZeroes` for that type:
+///
+/// - If the type is a struct, all of its fields must be `FromZeroes`.
+/// - If the type is an enum, it must be C-like (meaning that all variants have
+/// no fields) and it must have a variant with a discriminant of `0`. See [the
+/// reference] for a description of how discriminant values are chosen.
+/// - The type must not contain any [`UnsafeCell`]s (this is required in order
+/// for it to be sound to construct a `&[u8]` and a `&T` to the same region of
+/// memory). The type may contain references or pointers to `UnsafeCell`s so
+/// long as those values can themselves be initialized from zeroes
+/// (`FromZeroes` is not currently implemented for, e.g.,
+/// `Option<&UnsafeCell<_>>`, but it could be one day).
+///
+/// This analysis is subject to change. Unsafe code may *only* rely on the
+/// documented [safety conditions] of `FromZeroes`, and must *not* rely on the
+/// implementation details of this derive.
+///
+/// [the reference]: https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
+/// [`UnsafeCell`]: core::cell::UnsafeCell
+///
+/// ## Why isn't an explicit representation required for structs?
+///
+/// Neither this derive, nor the [safety conditions] of `FromZeroes`, requires
+/// that structs are marked with `#[repr(C)]`.
+///
+/// Per the [Rust reference](reference),
+///
+/// > The representation of a type can change the padding between fields, but
+/// does not change the layout of the fields themselves.
+///
+/// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations
+///
+/// Since the layout of structs only consists of padding bytes and field bytes,
+/// a struct is soundly `FromZeroes` if:
+/// 1. its padding is soundly `FromZeroes`, and
+/// 2. its fields are soundly `FromZeroes`.
+///
+/// The answer to the first question is always yes: padding bytes do not have
+/// any validity constraints. A [discussion] of this question in the Unsafe Code
+/// Guidelines Working Group concluded that it would be virtually unimaginable
+/// for future versions of rustc to add validity constraints to padding bytes.
+///
+/// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174
+///
+/// Whether a struct is soundly `FromZeroes` therefore solely depends on whether
+/// its fields are `FromZeroes`.
+// TODO(#146): Document why we don't require an enum to have an explicit `repr`
+// attribute.
+#[cfg(any(feature = "derive", test))]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
+pub use zerocopy_derive::FromZeroes;
+
+/// Types whose validity can be checked at runtime, allowing them to be
+/// conditionally converted from byte slices.
+///
+/// WARNING: Do not implement this trait yourself! Instead, use
+/// `#[derive(TryFromBytes)]`.
+///
+/// `TryFromBytes` types can safely be deserialized from an untrusted sequence
+/// of bytes by performing a runtime check that the byte sequence contains a
+/// valid instance of `Self`.
+///
+/// `TryFromBytes` is ignorant of byte order. For byte order-aware types, see
+/// the [`byteorder`] module.
+///
+/// # What is a "valid instance"?
+///
+/// In Rust, each type has *bit validity*, which refers to the set of bit
+/// patterns which may appear in an instance of that type. It is impossible for
+/// safe Rust code to produce values which violate bit validity (ie, values
+/// outside of the "valid" set of bit patterns). If `unsafe` code produces an
+/// invalid value, this is considered [undefined behavior].
+///
+/// Rust's bit validity rules are currently being decided, which means that some
+/// types have three classes of bit patterns: those which are definitely valid,
+/// and whose validity is documented in the language; those which may or may not
+/// be considered valid at some point in the future; and those which are
+/// definitely invalid.
+///
+/// Zerocopy takes a conservative approach, and only considers a bit pattern to
+/// be valid if its validity is a documenteed guarantee provided by the
+/// language.
+///
+/// For most use cases, Rust's current guarantees align with programmers'
+/// intuitions about what ought to be valid. As a result, zerocopy's
+/// conservatism should not affect most users. One notable exception is unions,
+/// whose bit validity is very up in the air; zerocopy does not permit
+/// implementing `TryFromBytes` for any union type.
+///
+/// If you are negatively affected by lack of support for a particular type,
+/// we encourage you to let us know by [filing an issue][github-repo].
+///
+/// # Safety
+///
+/// On its own, `T: TryFromBytes` does not make any guarantees about the layout
+/// or representation of `T`. It merely provides the ability to perform a
+/// validity check at runtime via methods like [`try_from_ref`].
+///
+/// Currently, it is not possible to stably implement `TryFromBytes` other than
+/// by using `#[derive(TryFromBytes)]`. While there are `#[doc(hidden)]` items
+/// on this trait that provide well-defined safety invariants, no stability
+/// guarantees are made with respect to these items. In particular, future
+/// releases of zerocopy may make backwards-breaking changes to these items,
+/// including changes that only affect soundness, which may cause code which
+/// uses those items to silently become unsound.
+///
+/// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
+/// [github-repo]: https://github.com/google/zerocopy
+/// [`try_from_ref`]: TryFromBytes::try_from_ref
+// TODO(#5): Update `try_from_ref` doc link once it exists
+#[doc(hidden)]
+pub unsafe trait TryFromBytes {
+ /// Does a given memory range contain a valid instance of `Self`?
+ ///
+ /// # Safety
+ ///
+ /// ## Preconditions
+ ///
+ /// The memory referenced by `candidate` may only be accessed via reads for
+ /// the duration of this method call. This prohibits writes through mutable
+ /// references and through [`UnsafeCell`]s. There may exist immutable
+ /// references to the same memory which contain `UnsafeCell`s so long as:
+ /// - Those `UnsafeCell`s exist at the same byte ranges as `UnsafeCell`s in
+ /// `Self`. This is a bidirectional property: `Self` may not contain
+ /// `UnsafeCell`s where other references to the same memory do not, and
+ /// vice-versa.
+ /// - Those `UnsafeCell`s are never used to perform mutation for the
+ /// duration of this method call.
+ ///
+ /// The memory referenced by `candidate` may not be referenced by any
+ /// mutable references even if these references are not used to perform
+ /// mutation.
+ ///
+ /// `candidate` is not required to refer to a valid `Self`. However, it must
+ /// satisfy the requirement that uninitialized bytes may only be present
+ /// where it is possible for them to be present in `Self`. This is a dynamic
+ /// property: if, at a particular byte offset, a valid enum discriminant is
+ /// set, the subsequent bytes may only have uninitialized bytes as
+ /// specificed by the corresponding enum.
+ ///
+ /// Formally, given `len = size_of_val_raw(candidate)`, at every byte
+ /// offset, `b`, in the range `[0, len)`:
+ /// - If, in all instances `s: Self` of length `len`, the byte at offset `b`
+ /// in `s` is initialized, then the byte at offset `b` within `*candidate`
+ /// must be initialized.
+ /// - Let `c` be the contents of the byte range `[0, b)` in `*candidate`.
+ /// Let `S` be the subset of valid instances of `Self` of length `len`
+ /// which contain `c` in the offset range `[0, b)`. If, for all instances
+ /// of `s: Self` in `S`, the byte at offset `b` in `s` is initialized,
+ /// then the byte at offset `b` in `*candidate` must be initialized.
+ ///
+ /// Pragmatically, this means that if `*candidate` is guaranteed to
+ /// contain an enum type at a particular offset, and the enum discriminant
+ /// stored in `*candidate` corresponds to a valid variant of that enum
+ /// type, then it is guaranteed that the appropriate bytes of `*candidate`
+ /// are initialized as defined by that variant's bit validity (although
+ /// note that the variant may contain another enum type, in which case the
+ /// same rules apply depending on the state of its discriminant, and so on
+ /// recursively).
+ ///
+ /// ## Postconditions
+ ///
+ /// Unsafe code may assume that, if `is_bit_valid(candidate)` returns true,
+ /// `*candidate` contains a valid `Self`.
+ ///
+ /// # Panics
+ ///
+ /// `is_bit_valid` may panic. Callers are responsible for ensuring that any
+ /// `unsafe` code remains sound even in the face of `is_bit_valid`
+ /// panicking. (We support user-defined validation routines; so long as
+ /// these routines are not required to be `unsafe`, there is no way to
+ /// ensure that these do not generate panics.)
+ ///
+ /// [`UnsafeCell`]: core::cell::UnsafeCell
+ #[doc(hidden)]
+ unsafe fn is_bit_valid(candidate: Ptr<'_, Self>) -> bool;
+
+ /// Attempts to interpret a byte slice as a `Self`.
+ ///
+ /// `try_from_ref` validates that `bytes` contains a valid `Self`, and that
+ /// it satisfies `Self`'s alignment requirement. If it does, then `bytes` is
+ /// reinterpreted as a `Self`.
+ ///
+ /// Note that Rust's bit validity rules are still being decided. As such,
+ /// there exist types whose bit validity is ambiguous. See the
+ /// `TryFromBytes` docs for a discussion of how these cases are handled.
+ // TODO(#251): In a future in which we distinguish between `FromBytes` and
+ // `RefFromBytes`, this requires `where Self: RefFromBytes` to disallow
+ // interior mutability.
+ #[inline]
+ #[doc(hidden)] // TODO(#5): Finalize name before remove this attribute.
+ fn try_from_ref(bytes: &[u8]) -> Option<&Self>
+ where
+ Self: KnownLayout,
+ {
+ let maybe_self = Ptr::from(bytes).try_cast_into_no_leftover::<Self>()?;
+
+ // SAFETY:
+ // - Since `bytes` is an immutable reference, we know that no mutable
+ // references exist to this memory region.
+ // - Since `[u8]` contains no `UnsafeCell`s, we know there are no
+ // `&UnsafeCell` references to this memory region.
+ // - Since we don't permit implementing `TryFromBytes` for types which
+ // contain `UnsafeCell`s, there are no `UnsafeCell`s in `Self`, and so
+ // the requirement that all references contain `UnsafeCell`s at the
+ // same offsets is trivially satisfied.
+ // - All bytes of `bytes` are initialized.
+ //
+ // This call may panic. If that happens, it doesn't cause any soundness
+ // issues, as we have not generated any invalid state which we need to
+ // fix before returning.
+ if unsafe { !Self::is_bit_valid(maybe_self) } {
+ return None;
+ }
+
+ // SAFETY:
+ // - Preconditions for `as_ref`:
+ // - `is_bit_valid` guarantees that `*maybe_self` contains a valid
+ // `Self`. Since `&[u8]` does not permit interior mutation, this
+ // cannot be invalidated after this method returns.
+ // - Since the argument and return types are immutable references,
+ // Rust will prevent the caller from producing any mutable
+ // references to the same memory region.
+ // - Since `Self` is not allowed to contain any `UnsafeCell`s and the
+ // same is true of `[u8]`, interior mutation is not possible. Thus,
+ // no mutation is possible. For the same reason, there is no
+ // mismatch between the two types in terms of which byte ranges are
+ // referenced as `UnsafeCell`s.
+ // - Since interior mutation isn't possible within `Self`, there's no
+ // way for the returned reference to be used to modify the byte range,
+ // and thus there's no way for the returned reference to be used to
+ // write an invalid `[u8]` which would be observable via the original
+ // `&[u8]`.
+ Some(unsafe { maybe_self.as_ref() })
+ }
+}
+
+/// Types for which a sequence of bytes all set to zero represents a valid
+/// instance of the type.
+///
+/// Any memory region of the appropriate length which is guaranteed to contain
+/// only zero bytes can be viewed as any `FromZeroes` type with no runtime
+/// overhead. This is useful whenever memory is known to be in a zeroed state,
+/// such memory returned from some allocation routines.
+///
+/// # Implementation
+///
+/// **Do not implement this trait yourself!** Instead, use
+/// [`#[derive(FromZeroes)]`][derive] (requires the `derive` Cargo feature);
+/// e.g.:
+///
+/// ```
+/// # use zerocopy_derive::FromZeroes;
+/// #[derive(FromZeroes)]
+/// struct MyStruct {
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes)]
+/// #[repr(u8)]
+/// enum MyEnum {
+/// # Variant0,
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes)]
+/// union MyUnion {
+/// # variant: u8,
+/// # /*
+/// ...
+/// # */
+/// }
+/// ```
+///
+/// This derive performs a sophisticated, compile-time safety analysis to
+/// determine whether a type is `FromZeroes`.
+///
+/// # Safety
+///
+/// *This section describes what is required in order for `T: FromZeroes`, and
+/// what unsafe code may assume of such types. If you don't plan on implementing
+/// `FromZeroes` manually, and you don't plan on writing unsafe code that
+/// operates on `FromZeroes` types, then you don't need to read this section.*
+///
+/// If `T: FromZeroes`, then unsafe code may assume that:
+/// - It is sound to treat any initialized sequence of zero bytes of length
+/// `size_of::<T>()` as a `T`.
+/// - Given `b: &[u8]` where `b.len() == size_of::<T>()`, `b` is aligned to
+/// `align_of::<T>()`, and `b` contains only zero bytes, it is sound to
+/// construct a `t: &T` at the same address as `b`, and it is sound for both
+/// `b` and `t` to be live at the same time.
+///
+/// If a type is marked as `FromZeroes` which violates this contract, it may
+/// cause undefined behavior.
+///
+/// `#[derive(FromZeroes)]` only permits [types which satisfy these
+/// requirements][derive-analysis].
+///
+#[cfg_attr(
+ feature = "derive",
+ doc = "[derive]: zerocopy_derive::FromZeroes",
+ doc = "[derive-analysis]: zerocopy_derive::FromZeroes#analysis"
+)]
+#[cfg_attr(
+ not(feature = "derive"),
+ doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeroes.html"),
+ doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeroes.html#analysis"),
+)]
+pub unsafe trait FromZeroes {
+ // The `Self: Sized` bound makes it so that `FromZeroes` is still object
+ // safe.
+ #[doc(hidden)]
+ fn only_derive_is_allowed_to_implement_this_trait()
+ where
+ Self: Sized;
+
+ /// Overwrites `self` with zeroes.
+ ///
+ /// Sets every byte in `self` to 0. While this is similar to doing `*self =
+ /// Self::new_zeroed()`, it differs in that `zero` does not semantically
+ /// drop the current value and replace it with a new one - it simply
+ /// modifies the bytes of the existing value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zerocopy::FromZeroes;
+ /// # use zerocopy_derive::*;
+ /// #
+ /// #[derive(FromZeroes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// let mut header = PacketHeader {
+ /// src_port: 100u16.to_be_bytes(),
+ /// dst_port: 200u16.to_be_bytes(),
+ /// length: 300u16.to_be_bytes(),
+ /// checksum: 400u16.to_be_bytes(),
+ /// };
+ ///
+ /// header.zero();
+ ///
+ /// assert_eq!(header.src_port, [0, 0]);
+ /// assert_eq!(header.dst_port, [0, 0]);
+ /// assert_eq!(header.length, [0, 0]);
+ /// assert_eq!(header.checksum, [0, 0]);
+ /// ```
+ #[inline(always)]
+ fn zero(&mut self) {
+ let slf: *mut Self = self;
+ let len = mem::size_of_val(self);
+ // SAFETY:
+ // - `self` is guaranteed by the type system to be valid for writes of
+ // size `size_of_val(self)`.
+ // - `u8`'s alignment is 1, and thus `self` is guaranteed to be aligned
+ // as required by `u8`.
+ // - Since `Self: FromZeroes`, the all-zeroes instance is a valid
+ // instance of `Self.`
+ //
+ // TODO(#429): Add references to docs and quotes.
+ unsafe { ptr::write_bytes(slf.cast::<u8>(), 0, len) };
+ }
+
+ /// Creates an instance of `Self` from zeroed bytes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zerocopy::FromZeroes;
+ /// # use zerocopy_derive::*;
+ /// #
+ /// #[derive(FromZeroes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// let header: PacketHeader = FromZeroes::new_zeroed();
+ ///
+ /// assert_eq!(header.src_port, [0, 0]);
+ /// assert_eq!(header.dst_port, [0, 0]);
+ /// assert_eq!(header.length, [0, 0]);
+ /// assert_eq!(header.checksum, [0, 0]);
+ /// ```
+ #[inline(always)]
+ fn new_zeroed() -> Self
+ where
+ Self: Sized,
+ {
+ // SAFETY: `FromZeroes` says that the all-zeroes bit pattern is legal.
+ unsafe { mem::zeroed() }
+ }
+
+ /// Creates a `Box<Self>` from zeroed bytes.
+ ///
+ /// This function is useful for allocating large values on the heap and
+ /// zero-initializing them, without ever creating a temporary instance of
+ /// `Self` on the stack. For example, `<[u8; 1048576]>::new_box_zeroed()`
+ /// will allocate `[u8; 1048576]` directly on the heap; it does not require
+ /// storing `[u8; 1048576]` in a temporary variable on the stack.
+ ///
+ /// On systems that use a heap implementation that supports allocating from
+ /// pre-zeroed memory, using `new_box_zeroed` (or related functions) may
+ /// have performance benefits.
+ ///
+ /// Note that `Box<Self>` can be converted to `Arc<Self>` and other
+ /// container types without reallocation.
+ ///
+ /// # Panics
+ ///
+ /// Panics if allocation of `size_of::<Self>()` bytes fails.
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
+ #[inline]
+ fn new_box_zeroed() -> Box<Self>
+ where
+ Self: Sized,
+ {
+ // If `T` is a ZST, then return a proper boxed instance of it. There is
+ // no allocation, but `Box` does require a correct dangling pointer.
+ let layout = Layout::new::<Self>();
+ if layout.size() == 0 {
+ return Box::new(Self::new_zeroed());
+ }
+
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ let ptr = unsafe { alloc::alloc::alloc_zeroed(layout).cast::<Self>() };
+ if ptr.is_null() {
+ alloc::alloc::handle_alloc_error(layout);
+ }
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ Box::from_raw(ptr)
+ }
+ }
+
+ /// Creates a `Box<[Self]>` (a boxed slice) from zeroed bytes.
+ ///
+ /// This function is useful for allocating large values of `[Self]` on the
+ /// heap and zero-initializing them, without ever creating a temporary
+ /// instance of `[Self; _]` on the stack. For example,
+ /// `u8::new_box_slice_zeroed(1048576)` will allocate the slice directly on
+ /// the heap; it does not require storing the slice on the stack.
+ ///
+ /// On systems that use a heap implementation that supports allocating from
+ /// pre-zeroed memory, using `new_box_slice_zeroed` may have performance
+ /// benefits.
+ ///
+ /// If `Self` is a zero-sized type, then this function will return a
+ /// `Box<[Self]>` that has the correct `len`. Such a box cannot contain any
+ /// actual information, but its `len()` property will report the correct
+ /// value.
+ ///
+ /// # Panics
+ ///
+ /// * Panics if `size_of::<Self>() * len` overflows.
+ /// * Panics if allocation of `size_of::<Self>() * len` bytes fails.
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
+ #[inline]
+ fn new_box_slice_zeroed(len: usize) -> Box<[Self]>
+ where
+ Self: Sized,
+ {
+ let size = mem::size_of::<Self>()
+ .checked_mul(len)
+ .expect("mem::size_of::<Self>() * len overflows `usize`");
+ let align = mem::align_of::<Self>();
+ // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a
+ // bug in which sufficiently-large allocations (those which, when
+ // rounded up to the alignment, overflow `isize`) are not rejected,
+ // which can cause undefined behavior. See #64 for details.
+ //
+ // TODO(#67): Once our MSRV is > 1.64.0, remove this assertion.
+ #[allow(clippy::as_conversions)]
+ let max_alloc = (isize::MAX as usize).saturating_sub(align);
+ assert!(size <= max_alloc);
+ // TODO(https://github.com/rust-lang/rust/issues/55724): Use
+ // `Layout::repeat` once it's stabilized.
+ let layout =
+ Layout::from_size_align(size, align).expect("total allocation size overflows `isize`");
+
+ let ptr = if layout.size() != 0 {
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ let ptr = unsafe { alloc::alloc::alloc_zeroed(layout).cast::<Self>() };
+ if ptr.is_null() {
+ alloc::alloc::handle_alloc_error(layout);
+ }
+ ptr
+ } else {
+ // `Box<[T]>` does not allocate when `T` is zero-sized or when `len`
+ // is zero, but it does require a non-null dangling pointer for its
+ // allocation.
+ NonNull::<Self>::dangling().as_ptr()
+ };
+
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ Box::from_raw(slice::from_raw_parts_mut(ptr, len))
+ }
+ }
+
+ /// Creates a `Vec<Self>` from zeroed bytes.
+ ///
+ /// This function is useful for allocating large values of `Vec`s and
+ /// zero-initializing them, without ever creating a temporary instance of
+ /// `[Self; _]` (or many temporary instances of `Self`) on the stack. For
+ /// example, `u8::new_vec_zeroed(1048576)` will allocate directly on the
+ /// heap; it does not require storing intermediate values on the stack.
+ ///
+ /// On systems that use a heap implementation that supports allocating from
+ /// pre-zeroed memory, using `new_vec_zeroed` may have performance benefits.
+ ///
+ /// If `Self` is a zero-sized type, then this function will return a
+ /// `Vec<Self>` that has the correct `len`. Such a `Vec` cannot contain any
+ /// actual information, but its `len()` property will report the correct
+ /// value.
+ ///
+ /// # Panics
+ ///
+ /// * Panics if `size_of::<Self>() * len` overflows.
+ /// * Panics if allocation of `size_of::<Self>() * len` bytes fails.
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "new_vec_zeroed")))]
+ #[inline(always)]
+ fn new_vec_zeroed(len: usize) -> Vec<Self>
+ where
+ Self: Sized,
+ {
+ Self::new_box_slice_zeroed(len).into()
+ }
+}
+
+/// Analyzes whether a type is [`FromBytes`].
+///
+/// This derive analyzes, at compile time, whether the annotated type satisfies
+/// the [safety conditions] of `FromBytes` and implements `FromBytes` if it is
+/// sound to do so. This derive can be applied to structs, enums, and unions;
+/// e.g.:
+///
+/// ```
+/// # use zerocopy_derive::{FromBytes, FromZeroes};
+/// #[derive(FromZeroes, FromBytes)]
+/// struct MyStruct {
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes, FromBytes)]
+/// #[repr(u8)]
+/// enum MyEnum {
+/// # V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E,
+/// # V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D,
+/// # V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C,
+/// # V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B,
+/// # V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A,
+/// # V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
+/// # V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68,
+/// # V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77,
+/// # V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86,
+/// # V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95,
+/// # V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4,
+/// # VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3,
+/// # VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2,
+/// # VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1,
+/// # VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0,
+/// # VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF,
+/// # VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE,
+/// # VFF,
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes, FromBytes)]
+/// union MyUnion {
+/// # variant: u8,
+/// # /*
+/// ...
+/// # */
+/// }
+/// ```
+///
+/// [safety conditions]: trait@FromBytes#safety
+///
+/// # Analysis
+///
+/// *This section describes, roughly, the analysis performed by this derive to
+/// determine whether it is sound to implement `FromBytes` for a given type.
+/// Unless you are modifying the implementation of this derive, or attempting to
+/// manually implement `FromBytes` for a type yourself, you don't need to read
+/// this section.*
+///
+/// If a type has the following properties, then this derive can implement
+/// `FromBytes` for that type:
+///
+/// - If the type is a struct, all of its fields must be `FromBytes`.
+/// - If the type is an enum:
+/// - It must be a C-like enum (meaning that all variants have no fields).
+/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
+/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
+/// - The maximum number of discriminants must be used (so that every possible
+/// bit pattern is a valid one). Be very careful when using the `C`,
+/// `usize`, or `isize` representations, as their size is
+/// platform-dependent.
+/// - The type must not contain any [`UnsafeCell`]s (this is required in order
+/// for it to be sound to construct a `&[u8]` and a `&T` to the same region of
+/// memory). The type may contain references or pointers to `UnsafeCell`s so
+/// long as those values can themselves be initialized from zeroes
+/// (`FromBytes` is not currently implemented for, e.g., `Option<*const
+/// UnsafeCell<_>>`, but it could be one day).
+///
+/// [`UnsafeCell`]: core::cell::UnsafeCell
+///
+/// This analysis is subject to change. Unsafe code may *only* rely on the
+/// documented [safety conditions] of `FromBytes`, and must *not* rely on the
+/// implementation details of this derive.
+///
+/// ## Why isn't an explicit representation required for structs?
+///
+/// Neither this derive, nor the [safety conditions] of `FromBytes`, requires
+/// that structs are marked with `#[repr(C)]`.
+///
+/// Per the [Rust reference](reference),
+///
+/// > The representation of a type can change the padding between fields, but
+/// does not change the layout of the fields themselves.
+///
+/// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations
+///
+/// Since the layout of structs only consists of padding bytes and field bytes,
+/// a struct is soundly `FromBytes` if:
+/// 1. its padding is soundly `FromBytes`, and
+/// 2. its fields are soundly `FromBytes`.
+///
+/// The answer to the first question is always yes: padding bytes do not have
+/// any validity constraints. A [discussion] of this question in the Unsafe Code
+/// Guidelines Working Group concluded that it would be virtually unimaginable
+/// for future versions of rustc to add validity constraints to padding bytes.
+///
+/// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174
+///
+/// Whether a struct is soundly `FromBytes` therefore solely depends on whether
+/// its fields are `FromBytes`.
+// TODO(#146): Document why we don't require an enum to have an explicit `repr`
+// attribute.
+#[cfg(any(feature = "derive", test))]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
+pub use zerocopy_derive::FromBytes;
+
+/// Types for which any bit pattern is valid.
+///
+/// Any memory region of the appropriate length which contains initialized bytes
+/// can be viewed as any `FromBytes` type with no runtime overhead. This is
+/// useful for efficiently parsing bytes as structured data.
+///
+/// # Implementation
+///
+/// **Do not implement this trait yourself!** Instead, use
+/// [`#[derive(FromBytes)]`][derive] (requires the `derive` Cargo feature);
+/// e.g.:
+///
+/// ```
+/// # use zerocopy_derive::{FromBytes, FromZeroes};
+/// #[derive(FromZeroes, FromBytes)]
+/// struct MyStruct {
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes, FromBytes)]
+/// #[repr(u8)]
+/// enum MyEnum {
+/// # V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E,
+/// # V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D,
+/// # V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C,
+/// # V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B,
+/// # V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A,
+/// # V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
+/// # V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68,
+/// # V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77,
+/// # V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86,
+/// # V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95,
+/// # V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4,
+/// # VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3,
+/// # VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2,
+/// # VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1,
+/// # VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0,
+/// # VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF,
+/// # VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE,
+/// # VFF,
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(FromZeroes, FromBytes)]
+/// union MyUnion {
+/// # variant: u8,
+/// # /*
+/// ...
+/// # */
+/// }
+/// ```
+///
+/// This derive performs a sophisticated, compile-time safety analysis to
+/// determine whether a type is `FromBytes`.
+///
+/// # Safety
+///
+/// *This section describes what is required in order for `T: FromBytes`, and
+/// what unsafe code may assume of such types. If you don't plan on implementing
+/// `FromBytes` manually, and you don't plan on writing unsafe code that
+/// operates on `FromBytes` types, then you don't need to read this section.*
+///
+/// If `T: FromBytes`, then unsafe code may assume that:
+/// - It is sound to treat any initialized sequence of bytes of length
+/// `size_of::<T>()` as a `T`.
+/// - Given `b: &[u8]` where `b.len() == size_of::<T>()`, `b` is aligned to
+/// `align_of::<T>()` it is sound to construct a `t: &T` at the same address
+/// as `b`, and it is sound for both `b` and `t` to be live at the same time.
+///
+/// If a type is marked as `FromBytes` which violates this contract, it may
+/// cause undefined behavior.
+///
+/// `#[derive(FromBytes)]` only permits [types which satisfy these
+/// requirements][derive-analysis].
+///
+#[cfg_attr(
+ feature = "derive",
+ doc = "[derive]: zerocopy_derive::FromBytes",
+ doc = "[derive-analysis]: zerocopy_derive::FromBytes#analysis"
+)]
+#[cfg_attr(
+ not(feature = "derive"),
+ doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html"),
+ doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html#analysis"),
+)]
+pub unsafe trait FromBytes: FromZeroes {
+ // The `Self: Sized` bound makes it so that `FromBytes` is still object
+ // safe.
+ #[doc(hidden)]
+ fn only_derive_is_allowed_to_implement_this_trait()
+ where
+ Self: Sized;
+
+ /// Interprets the given `bytes` as a `&Self` without copying.
+ ///
+ /// If `bytes.len() != size_of::<Self>()` or `bytes` is not aligned to
+ /// `align_of::<Self>()`, this returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// // These bytes encode a `PacketHeader`.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7].as_slice();
+ ///
+ /// let header = PacketHeader::ref_from(bytes).unwrap();
+ ///
+ /// assert_eq!(header.src_port, [0, 1]);
+ /// assert_eq!(header.dst_port, [2, 3]);
+ /// assert_eq!(header.length, [4, 5]);
+ /// assert_eq!(header.checksum, [6, 7]);
+ /// ```
+ #[inline]
+ fn ref_from(bytes: &[u8]) -> Option<&Self>
+ where
+ Self: Sized,
+ {
+ Ref::<&[u8], Self>::new(bytes).map(Ref::into_ref)
+ }
+
+ /// Interprets the prefix of the given `bytes` as a `&Self` without copying.
+ ///
+ /// `ref_from_prefix` returns a reference to the first `size_of::<Self>()`
+ /// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or `bytes` is not
+ /// aligned to `align_of::<Self>()`, this returns `None`.
+ ///
+ /// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then, use
+ /// [`Ref::into_ref`] to get a `&Self` with the same lifetime.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode a `PacketHeader`.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].as_slice();
+ ///
+ /// let header = PacketHeader::ref_from_prefix(bytes).unwrap();
+ ///
+ /// assert_eq!(header.src_port, [0, 1]);
+ /// assert_eq!(header.dst_port, [2, 3]);
+ /// assert_eq!(header.length, [4, 5]);
+ /// assert_eq!(header.checksum, [6, 7]);
+ /// ```
+ #[inline]
+ fn ref_from_prefix(bytes: &[u8]) -> Option<&Self>
+ where
+ Self: Sized,
+ {
+ Ref::<&[u8], Self>::new_from_prefix(bytes).map(|(r, _)| r.into_ref())
+ }
+
+ /// Interprets the suffix of the given `bytes` as a `&Self` without copying.
+ ///
+ /// `ref_from_suffix` returns a reference to the last `size_of::<Self>()`
+ /// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or the suffix of
+ /// `bytes` is not aligned to `align_of::<Self>()`, this returns `None`.
+ ///
+ /// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then, use
+ /// [`Ref::into_ref`] to get a `&Self` with the same lifetime.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketTrailer {
+ /// frame_check_sequence: [u8; 4],
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode a `PacketTrailer`.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].as_slice();
+ ///
+ /// let trailer = PacketTrailer::ref_from_suffix(bytes).unwrap();
+ ///
+ /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
+ /// ```
+ #[inline]
+ fn ref_from_suffix(bytes: &[u8]) -> Option<&Self>
+ where
+ Self: Sized,
+ {
+ Ref::<&[u8], Self>::new_from_suffix(bytes).map(|(_, r)| r.into_ref())
+ }
+
+ /// Interprets the given `bytes` as a `&mut Self` without copying.
+ ///
+ /// If `bytes.len() != size_of::<Self>()` or `bytes` is not aligned to
+ /// `align_of::<Self>()`, this returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(AsBytes, FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// // These bytes encode a `PacketHeader`.
+ /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
+ ///
+ /// let header = PacketHeader::mut_from(bytes).unwrap();
+ ///
+ /// assert_eq!(header.src_port, [0, 1]);
+ /// assert_eq!(header.dst_port, [2, 3]);
+ /// assert_eq!(header.length, [4, 5]);
+ /// assert_eq!(header.checksum, [6, 7]);
+ ///
+ /// header.checksum = [0, 0];
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0]);
+ /// ```
+ #[inline]
+ fn mut_from(bytes: &mut [u8]) -> Option<&mut Self>
+ where
+ Self: Sized + AsBytes,
+ {
+ Ref::<&mut [u8], Self>::new(bytes).map(Ref::into_mut)
+ }
+
+ /// Interprets the prefix of the given `bytes` as a `&mut Self` without
+ /// copying.
+ ///
+ /// `mut_from_prefix` returns a reference to the first `size_of::<Self>()`
+ /// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or `bytes` is not
+ /// aligned to `align_of::<Self>()`, this returns `None`.
+ ///
+ /// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then, use
+ /// [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(AsBytes, FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode a `PacketHeader`.
+ /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
+ ///
+ /// let header = PacketHeader::mut_from_prefix(bytes).unwrap();
+ ///
+ /// assert_eq!(header.src_port, [0, 1]);
+ /// assert_eq!(header.dst_port, [2, 3]);
+ /// assert_eq!(header.length, [4, 5]);
+ /// assert_eq!(header.checksum, [6, 7]);
+ ///
+ /// header.checksum = [0, 0];
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 8, 9]);
+ /// ```
+ #[inline]
+ fn mut_from_prefix(bytes: &mut [u8]) -> Option<&mut Self>
+ where
+ Self: Sized + AsBytes,
+ {
+ Ref::<&mut [u8], Self>::new_from_prefix(bytes).map(|(r, _)| r.into_mut())
+ }
+
+ /// Interprets the suffix of the given `bytes` as a `&mut Self` without copying.
+ ///
+ /// `mut_from_suffix` returns a reference to the last `size_of::<Self>()`
+ /// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or the suffix of
+ /// `bytes` is not aligned to `align_of::<Self>()`, this returns `None`.
+ ///
+ /// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then,
+ /// use [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(AsBytes, FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketTrailer {
+ /// frame_check_sequence: [u8; 4],
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode a `PacketTrailer`.
+ /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
+ ///
+ /// let trailer = PacketTrailer::mut_from_suffix(bytes).unwrap();
+ ///
+ /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
+ ///
+ /// trailer.frame_check_sequence = [0, 0, 0, 0];
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 0, 0]);
+ /// ```
+ #[inline]
+ fn mut_from_suffix(bytes: &mut [u8]) -> Option<&mut Self>
+ where
+ Self: Sized + AsBytes,
+ {
+ Ref::<&mut [u8], Self>::new_from_suffix(bytes).map(|(_, r)| r.into_mut())
+ }
+
+ /// Interprets the given `bytes` as a `&[Self]` without copying.
+ ///
+ /// If `bytes.len() % size_of::<Self>() != 0` or `bytes` is not aligned to
+ /// `align_of::<Self>()`, this returns `None`.
+ ///
+ /// If you need to convert a specific number of slice elements, see
+ /// [`slice_from_prefix`](FromBytes::slice_from_prefix) or
+ /// [`slice_from_suffix`](FromBytes::slice_from_suffix).
+ ///
+ /// # Panics
+ ///
+ /// If `Self` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// # #[derive(Debug, PartialEq, Eq)]
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct Pixel {
+ /// r: u8,
+ /// g: u8,
+ /// b: u8,
+ /// a: u8,
+ /// }
+ ///
+ /// // These bytes encode two `Pixel`s.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7].as_slice();
+ ///
+ /// let pixels = Pixel::slice_from(bytes).unwrap();
+ ///
+ /// assert_eq!(pixels, &[
+ /// Pixel { r: 0, g: 1, b: 2, a: 3 },
+ /// Pixel { r: 4, g: 5, b: 6, a: 7 },
+ /// ]);
+ /// ```
+ #[inline]
+ fn slice_from(bytes: &[u8]) -> Option<&[Self]>
+ where
+ Self: Sized,
+ {
+ Ref::<_, [Self]>::new_slice(bytes).map(|r| r.into_slice())
+ }
+
+ /// Interprets the prefix of the given `bytes` as a `&[Self]` with length
+ /// equal to `count` without copying.
+ ///
+ /// This method verifies that `bytes.len() >= size_of::<T>() * count`
+ /// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// first `size_of::<T>() * count` bytes from `bytes` to construct a
+ /// `&[Self]`, and returns the remaining bytes to the caller. It also
+ /// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
+ /// If any of the length, alignment, or overflow checks fail, it returns
+ /// `None`.
+ ///
+ /// # Panics
+ ///
+ /// If `T` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// # #[derive(Debug, PartialEq, Eq)]
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct Pixel {
+ /// r: u8,
+ /// g: u8,
+ /// b: u8,
+ /// a: u8,
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode two `Pixel`s.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].as_slice();
+ ///
+ /// let (pixels, rest) = Pixel::slice_from_prefix(bytes, 2).unwrap();
+ ///
+ /// assert_eq!(pixels, &[
+ /// Pixel { r: 0, g: 1, b: 2, a: 3 },
+ /// Pixel { r: 4, g: 5, b: 6, a: 7 },
+ /// ]);
+ ///
+ /// assert_eq!(rest, &[8, 9]);
+ /// ```
+ #[inline]
+ fn slice_from_prefix(bytes: &[u8], count: usize) -> Option<(&[Self], &[u8])>
+ where
+ Self: Sized,
+ {
+ Ref::<_, [Self]>::new_slice_from_prefix(bytes, count).map(|(r, b)| (r.into_slice(), b))
+ }
+
+ /// Interprets the suffix of the given `bytes` as a `&[Self]` with length
+ /// equal to `count` without copying.
+ ///
+ /// This method verifies that `bytes.len() >= size_of::<T>() * count`
+ /// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// last `size_of::<T>() * count` bytes from `bytes` to construct a
+ /// `&[Self]`, and returns the preceding bytes to the caller. It also
+ /// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
+ /// If any of the length, alignment, or overflow checks fail, it returns
+ /// `None`.
+ ///
+ /// # Panics
+ ///
+ /// If `T` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// # #[derive(Debug, PartialEq, Eq)]
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct Pixel {
+ /// r: u8,
+ /// g: u8,
+ /// b: u8,
+ /// a: u8,
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode two `Pixel`s.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].as_slice();
+ ///
+ /// let (rest, pixels) = Pixel::slice_from_suffix(bytes, 2).unwrap();
+ ///
+ /// assert_eq!(rest, &[0, 1]);
+ ///
+ /// assert_eq!(pixels, &[
+ /// Pixel { r: 2, g: 3, b: 4, a: 5 },
+ /// Pixel { r: 6, g: 7, b: 8, a: 9 },
+ /// ]);
+ /// ```
+ #[inline]
+ fn slice_from_suffix(bytes: &[u8], count: usize) -> Option<(&[u8], &[Self])>
+ where
+ Self: Sized,
+ {
+ Ref::<_, [Self]>::new_slice_from_suffix(bytes, count).map(|(b, r)| (b, r.into_slice()))
+ }
+
+ /// Interprets the given `bytes` as a `&mut [Self]` without copying.
+ ///
+ /// If `bytes.len() % size_of::<T>() != 0` or `bytes` is not aligned to
+ /// `align_of::<T>()`, this returns `None`.
+ ///
+ /// If you need to convert a specific number of slice elements, see
+ /// [`mut_slice_from_prefix`](FromBytes::mut_slice_from_prefix) or
+ /// [`mut_slice_from_suffix`](FromBytes::mut_slice_from_suffix).
+ ///
+ /// # Panics
+ ///
+ /// If `T` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// # #[derive(Debug, PartialEq, Eq)]
+ /// #[derive(AsBytes, FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct Pixel {
+ /// r: u8,
+ /// g: u8,
+ /// b: u8,
+ /// a: u8,
+ /// }
+ ///
+ /// // These bytes encode two `Pixel`s.
+ /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
+ ///
+ /// let pixels = Pixel::mut_slice_from(bytes).unwrap();
+ ///
+ /// assert_eq!(pixels, &[
+ /// Pixel { r: 0, g: 1, b: 2, a: 3 },
+ /// Pixel { r: 4, g: 5, b: 6, a: 7 },
+ /// ]);
+ ///
+ /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0]);
+ /// ```
+ #[inline]
+ fn mut_slice_from(bytes: &mut [u8]) -> Option<&mut [Self]>
+ where
+ Self: Sized + AsBytes,
+ {
+ Ref::<_, [Self]>::new_slice(bytes).map(|r| r.into_mut_slice())
+ }
+
+ /// Interprets the prefix of the given `bytes` as a `&mut [Self]` with length
+ /// equal to `count` without copying.
+ ///
+ /// This method verifies that `bytes.len() >= size_of::<T>() * count`
+ /// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// first `size_of::<T>() * count` bytes from `bytes` to construct a
+ /// `&[Self]`, and returns the remaining bytes to the caller. It also
+ /// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
+ /// If any of the length, alignment, or overflow checks fail, it returns
+ /// `None`.
+ ///
+ /// # Panics
+ ///
+ /// If `T` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// # #[derive(Debug, PartialEq, Eq)]
+ /// #[derive(AsBytes, FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct Pixel {
+ /// r: u8,
+ /// g: u8,
+ /// b: u8,
+ /// a: u8,
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode two `Pixel`s.
+ /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
+ ///
+ /// let (pixels, rest) = Pixel::mut_slice_from_prefix(bytes, 2).unwrap();
+ ///
+ /// assert_eq!(pixels, &[
+ /// Pixel { r: 0, g: 1, b: 2, a: 3 },
+ /// Pixel { r: 4, g: 5, b: 6, a: 7 },
+ /// ]);
+ ///
+ /// assert_eq!(rest, &[8, 9]);
+ ///
+ /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0, 8, 9]);
+ /// ```
+ #[inline]
+ fn mut_slice_from_prefix(bytes: &mut [u8], count: usize) -> Option<(&mut [Self], &mut [u8])>
+ where
+ Self: Sized + AsBytes,
+ {
+ Ref::<_, [Self]>::new_slice_from_prefix(bytes, count).map(|(r, b)| (r.into_mut_slice(), b))
+ }
+
+ /// Interprets the suffix of the given `bytes` as a `&mut [Self]` with length
+ /// equal to `count` without copying.
+ ///
+ /// This method verifies that `bytes.len() >= size_of::<T>() * count`
+ /// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// last `size_of::<T>() * count` bytes from `bytes` to construct a
+ /// `&[Self]`, and returns the preceding bytes to the caller. It also
+ /// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
+ /// If any of the length, alignment, or overflow checks fail, it returns
+ /// `None`.
+ ///
+ /// # Panics
+ ///
+ /// If `T` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// # #[derive(Debug, PartialEq, Eq)]
+ /// #[derive(AsBytes, FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct Pixel {
+ /// r: u8,
+ /// g: u8,
+ /// b: u8,
+ /// a: u8,
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode two `Pixel`s.
+ /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
+ ///
+ /// let (rest, pixels) = Pixel::mut_slice_from_suffix(bytes, 2).unwrap();
+ ///
+ /// assert_eq!(rest, &[0, 1]);
+ ///
+ /// assert_eq!(pixels, &[
+ /// Pixel { r: 2, g: 3, b: 4, a: 5 },
+ /// Pixel { r: 6, g: 7, b: 8, a: 9 },
+ /// ]);
+ ///
+ /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 0, 0]);
+ /// ```
+ #[inline]
+ fn mut_slice_from_suffix(bytes: &mut [u8], count: usize) -> Option<(&mut [u8], &mut [Self])>
+ where
+ Self: Sized + AsBytes,
+ {
+ Ref::<_, [Self]>::new_slice_from_suffix(bytes, count).map(|(b, r)| (b, r.into_mut_slice()))
+ }
+
+ /// Reads a copy of `Self` from `bytes`.
+ ///
+ /// If `bytes.len() != size_of::<Self>()`, `read_from` returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// // These bytes encode a `PacketHeader`.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7].as_slice();
+ ///
+ /// let header = PacketHeader::read_from(bytes).unwrap();
+ ///
+ /// assert_eq!(header.src_port, [0, 1]);
+ /// assert_eq!(header.dst_port, [2, 3]);
+ /// assert_eq!(header.length, [4, 5]);
+ /// assert_eq!(header.checksum, [6, 7]);
+ /// ```
+ #[inline]
+ fn read_from(bytes: &[u8]) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ Ref::<_, Unalign<Self>>::new_unaligned(bytes).map(|r| r.read().into_inner())
+ }
+
+ /// Reads a copy of `Self` from the prefix of `bytes`.
+ ///
+ /// `read_from_prefix` reads a `Self` from the first `size_of::<Self>()`
+ /// bytes of `bytes`. If `bytes.len() < size_of::<Self>()`, it returns
+ /// `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode a `PacketHeader`.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].as_slice();
+ ///
+ /// let header = PacketHeader::read_from_prefix(bytes).unwrap();
+ ///
+ /// assert_eq!(header.src_port, [0, 1]);
+ /// assert_eq!(header.dst_port, [2, 3]);
+ /// assert_eq!(header.length, [4, 5]);
+ /// assert_eq!(header.checksum, [6, 7]);
+ /// ```
+ #[inline]
+ fn read_from_prefix(bytes: &[u8]) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ Ref::<_, Unalign<Self>>::new_unaligned_from_prefix(bytes)
+ .map(|(r, _)| r.read().into_inner())
+ }
+
+ /// Reads a copy of `Self` from the suffix of `bytes`.
+ ///
+ /// `read_from_suffix` reads a `Self` from the last `size_of::<Self>()`
+ /// bytes of `bytes`. If `bytes.len() < size_of::<Self>()`, it returns
+ /// `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::FromBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketTrailer {
+ /// frame_check_sequence: [u8; 4],
+ /// }
+ ///
+ /// // These are more bytes than are needed to encode a `PacketTrailer`.
+ /// let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].as_slice();
+ ///
+ /// let trailer = PacketTrailer::read_from_suffix(bytes).unwrap();
+ ///
+ /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
+ /// ```
+ #[inline]
+ fn read_from_suffix(bytes: &[u8]) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ Ref::<_, Unalign<Self>>::new_unaligned_from_suffix(bytes)
+ .map(|(_, r)| r.read().into_inner())
+ }
+}
+
+/// Analyzes whether a type is [`AsBytes`].
+///
+/// This derive analyzes, at compile time, whether the annotated type satisfies
+/// the [safety conditions] of `AsBytes` and implements `AsBytes` if it is
+/// sound to do so. This derive can be applied to structs, enums, and unions;
+/// e.g.:
+///
+/// ```
+/// # use zerocopy_derive::{AsBytes};
+/// #[derive(AsBytes)]
+/// #[repr(C)]
+/// struct MyStruct {
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(AsBytes)]
+/// #[repr(u8)]
+/// enum MyEnum {
+/// # Variant,
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(AsBytes)]
+/// #[repr(C)]
+/// union MyUnion {
+/// # variant: u8,
+/// # /*
+/// ...
+/// # */
+/// }
+/// ```
+///
+/// [safety conditions]: trait@AsBytes#safety
+///
+/// # Error Messages
+///
+/// Due to the way that the custom derive for `AsBytes` is implemented, you may
+/// get an error like this:
+///
+/// ```text
+/// error[E0277]: the trait bound `HasPadding<Foo, true>: ShouldBe<false>` is not satisfied
+/// --> lib.rs:23:10
+/// |
+/// 1 | #[derive(AsBytes)]
+/// | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<Foo, true>`
+/// |
+/// = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>`
+/// ```
+///
+/// This error indicates that the type being annotated has padding bytes, which
+/// is illegal for `AsBytes` types. Consider reducing the alignment of some
+/// fields by using types in the [`byteorder`] module, adding explicit struct
+/// fields where those padding bytes would be, or using `#[repr(packed)]`. See
+/// the Rust Reference's page on [type layout] for more information
+/// about type layout and padding.
+///
+/// [type layout]: https://doc.rust-lang.org/reference/type-layout.html
+///
+/// # Analysis
+///
+/// *This section describes, roughly, the analysis performed by this derive to
+/// determine whether it is sound to implement `AsBytes` for a given type.
+/// Unless you are modifying the implementation of this derive, or attempting to
+/// manually implement `AsBytes` for a type yourself, you don't need to read
+/// this section.*
+///
+/// If a type has the following properties, then this derive can implement
+/// `AsBytes` for that type:
+///
+/// - If the type is a struct:
+/// - It must have a defined representation (`repr(C)`, `repr(transparent)`,
+/// or `repr(packed)`).
+/// - All of its fields must be `AsBytes`.
+/// - Its layout must have no padding. This is always true for
+/// `repr(transparent)` and `repr(packed)`. For `repr(C)`, see the layout
+/// algorithm described in the [Rust Reference].
+/// - If the type is an enum:
+/// - It must be a C-like enum (meaning that all variants have no fields).
+/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
+/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
+/// - The type must not contain any [`UnsafeCell`]s (this is required in order
+/// for it to be sound to construct a `&[u8]` and a `&T` to the same region of
+/// memory). The type may contain references or pointers to `UnsafeCell`s so
+/// long as those values can themselves be initialized from zeroes (`AsBytes`
+/// is not currently implemented for, e.g., `Option<&UnsafeCell<_>>`, but it
+/// could be one day).
+///
+/// [`UnsafeCell`]: core::cell::UnsafeCell
+///
+/// This analysis is subject to change. Unsafe code may *only* rely on the
+/// documented [safety conditions] of `FromBytes`, and must *not* rely on the
+/// implementation details of this derive.
+///
+/// [Rust Reference]: https://doc.rust-lang.org/reference/type-layout.html
+#[cfg(any(feature = "derive", test))]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
+pub use zerocopy_derive::AsBytes;
+
+/// Types that can be viewed as an immutable slice of initialized bytes.
+///
+/// Any `AsBytes` type can be viewed as a slice of initialized bytes of the same
+/// size. This is useful for efficiently serializing structured data as raw
+/// bytes.
+///
+/// # Implementation
+///
+/// **Do not implement this trait yourself!** Instead, use
+/// [`#[derive(AsBytes)]`][derive] (requires the `derive` Cargo feature); e.g.:
+///
+/// ```
+/// # use zerocopy_derive::AsBytes;
+/// #[derive(AsBytes)]
+/// #[repr(C)]
+/// struct MyStruct {
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(AsBytes)]
+/// #[repr(u8)]
+/// enum MyEnum {
+/// # Variant0,
+/// # /*
+/// ...
+/// # */
+/// }
+///
+/// #[derive(AsBytes)]
+/// #[repr(C)]
+/// union MyUnion {
+/// # variant: u8,
+/// # /*
+/// ...
+/// # */
+/// }
+/// ```
+///
+/// This derive performs a sophisticated, compile-time safety analysis to
+/// determine whether a type is `AsBytes`. See the [derive
+/// documentation][derive] for guidance on how to interpret error messages
+/// produced by the derive's analysis.
+///
+/// # Safety
+///
+/// *This section describes what is required in order for `T: AsBytes`, and
+/// what unsafe code may assume of such types. If you don't plan on implementing
+/// `AsBytes` manually, and you don't plan on writing unsafe code that
+/// operates on `AsBytes` types, then you don't need to read this section.*
+///
+/// If `T: AsBytes`, then unsafe code may assume that:
+/// - It is sound to treat any `t: T` as an immutable `[u8]` of length
+/// `size_of_val(t)`.
+/// - Given `t: &T`, it is sound to construct a `b: &[u8]` where `b.len() ==
+/// size_of_val(t)` at the same address as `t`, and it is sound for both `b`
+/// and `t` to be live at the same time.
+///
+/// If a type is marked as `AsBytes` which violates this contract, it may cause
+/// undefined behavior.
+///
+/// `#[derive(AsBytes)]` only permits [types which satisfy these
+/// requirements][derive-analysis].
+///
+#[cfg_attr(
+ feature = "derive",
+ doc = "[derive]: zerocopy_derive::AsBytes",
+ doc = "[derive-analysis]: zerocopy_derive::AsBytes#analysis"
+)]
+#[cfg_attr(
+ not(feature = "derive"),
+ doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.AsBytes.html"),
+ doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.AsBytes.html#analysis"),
+)]
+pub unsafe trait AsBytes {
+ // The `Self: Sized` bound makes it so that this function doesn't prevent
+ // `AsBytes` from being object safe. Note that other `AsBytes` methods
+ // prevent object safety, but those provide a benefit in exchange for object
+ // safety. If at some point we remove those methods, change their type
+ // signatures, or move them out of this trait so that `AsBytes` is object
+ // safe again, it's important that this function not prevent object safety.
+ #[doc(hidden)]
+ fn only_derive_is_allowed_to_implement_this_trait()
+ where
+ Self: Sized;
+
+ /// Gets the bytes of this value.
+ ///
+ /// `as_bytes` provides access to the bytes of this value as an immutable
+ /// byte slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::AsBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(AsBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// let header = PacketHeader {
+ /// src_port: [0, 1],
+ /// dst_port: [2, 3],
+ /// length: [4, 5],
+ /// checksum: [6, 7],
+ /// };
+ ///
+ /// let bytes = header.as_bytes();
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
+ /// ```
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ // Note that this method does not have a `Self: Sized` bound;
+ // `size_of_val` works for unsized values too.
+ let len = mem::size_of_val(self);
+ let slf: *const Self = self;
+
+ // SAFETY:
+ // - `slf.cast::<u8>()` is valid for reads for `len *
+ // mem::size_of::<u8>()` many bytes because...
+ // - `slf` is the same pointer as `self`, and `self` is a reference
+ // which points to an object whose size is `len`. Thus...
+ // - The entire region of `len` bytes starting at `slf` is contained
+ // within a single allocation.
+ // - `slf` is non-null.
+ // - `slf` is trivially aligned to `align_of::<u8>() == 1`.
+ // - `Self: AsBytes` ensures that all of the bytes of `slf` are
+ // initialized.
+ // - Since `slf` is derived from `self`, and `self` is an immutable
+ // reference, the only other references to this memory region that
+ // could exist are other immutable references, and those don't allow
+ // mutation. `AsBytes` prohibits types which contain `UnsafeCell`s,
+ // which are the only types for which this rule wouldn't be sufficient.
+ // - The total size of the resulting slice is no larger than
+ // `isize::MAX` because no allocation produced by safe code can be
+ // larger than `isize::MAX`.
+ //
+ // TODO(#429): Add references to docs and quotes.
+ unsafe { slice::from_raw_parts(slf.cast::<u8>(), len) }
+ }
+
+ /// Gets the bytes of this value mutably.
+ ///
+ /// `as_bytes_mut` provides access to the bytes of this value as a mutable
+ /// byte slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::AsBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// # #[derive(Eq, PartialEq, Debug)]
+ /// #[derive(AsBytes, FromZeroes, FromBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// let mut header = PacketHeader {
+ /// src_port: [0, 1],
+ /// dst_port: [2, 3],
+ /// length: [4, 5],
+ /// checksum: [6, 7],
+ /// };
+ ///
+ /// let bytes = header.as_bytes_mut();
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
+ ///
+ /// bytes.reverse();
+ ///
+ /// assert_eq!(header, PacketHeader {
+ /// src_port: [7, 6],
+ /// dst_port: [5, 4],
+ /// length: [3, 2],
+ /// checksum: [1, 0],
+ /// });
+ /// ```
+ #[inline(always)]
+ fn as_bytes_mut(&mut self) -> &mut [u8]
+ where
+ Self: FromBytes,
+ {
+ // Note that this method does not have a `Self: Sized` bound;
+ // `size_of_val` works for unsized values too.
+ let len = mem::size_of_val(self);
+ let slf: *mut Self = self;
+
+ // SAFETY:
+ // - `slf.cast::<u8>()` is valid for reads and writes for `len *
+ // mem::size_of::<u8>()` many bytes because...
+ // - `slf` is the same pointer as `self`, and `self` is a reference
+ // which points to an object whose size is `len`. Thus...
+ // - The entire region of `len` bytes starting at `slf` is contained
+ // within a single allocation.
+ // - `slf` is non-null.
+ // - `slf` is trivially aligned to `align_of::<u8>() == 1`.
+ // - `Self: AsBytes` ensures that all of the bytes of `slf` are
+ // initialized.
+ // - `Self: FromBytes` ensures that no write to this memory region
+ // could result in it containing an invalid `Self`.
+ // - Since `slf` is derived from `self`, and `self` is a mutable
+ // reference, no other references to this memory region can exist.
+ // - The total size of the resulting slice is no larger than
+ // `isize::MAX` because no allocation produced by safe code can be
+ // larger than `isize::MAX`.
+ //
+ // TODO(#429): Add references to docs and quotes.
+ unsafe { slice::from_raw_parts_mut(slf.cast::<u8>(), len) }
+ }
+
+ /// Writes a copy of `self` to `bytes`.
+ ///
+ /// If `bytes.len() != size_of_val(self)`, `write_to` returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::AsBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(AsBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// let header = PacketHeader {
+ /// src_port: [0, 1],
+ /// dst_port: [2, 3],
+ /// length: [4, 5],
+ /// checksum: [6, 7],
+ /// };
+ ///
+ /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0];
+ ///
+ /// header.write_to(&mut bytes[..]);
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
+ /// ```
+ ///
+ /// If too many or too few target bytes are provided, `write_to` returns
+ /// `None` and leaves the target bytes unmodified:
+ ///
+ /// ```
+ /// # use zerocopy::AsBytes;
+ /// # let header = u128::MAX;
+ /// let mut excessive_bytes = &mut [0u8; 128][..];
+ ///
+ /// let write_result = header.write_to(excessive_bytes);
+ ///
+ /// assert!(write_result.is_none());
+ /// assert_eq!(excessive_bytes, [0u8; 128]);
+ /// ```
+ #[inline]
+ fn write_to(&self, bytes: &mut [u8]) -> Option<()> {
+ if bytes.len() != mem::size_of_val(self) {
+ return None;
+ }
+
+ bytes.copy_from_slice(self.as_bytes());
+ Some(())
+ }
+
+ /// Writes a copy of `self` to the prefix of `bytes`.
+ ///
+ /// `write_to_prefix` writes `self` to the first `size_of_val(self)` bytes
+ /// of `bytes`. If `bytes.len() < size_of_val(self)`, it returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::AsBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(AsBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// let header = PacketHeader {
+ /// src_port: [0, 1],
+ /// dst_port: [2, 3],
+ /// length: [4, 5],
+ /// checksum: [6, 7],
+ /// };
+ ///
+ /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ ///
+ /// header.write_to_prefix(&mut bytes[..]);
+ ///
+ /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
+ /// ```
+ ///
+ /// If insufficient target bytes are provided, `write_to_prefix` returns
+ /// `None` and leaves the target bytes unmodified:
+ ///
+ /// ```
+ /// # use zerocopy::AsBytes;
+ /// # let header = u128::MAX;
+ /// let mut insufficent_bytes = &mut [0, 0][..];
+ ///
+ /// let write_result = header.write_to_suffix(insufficent_bytes);
+ ///
+ /// assert!(write_result.is_none());
+ /// assert_eq!(insufficent_bytes, [0, 0]);
+ /// ```
+ #[inline]
+ fn write_to_prefix(&self, bytes: &mut [u8]) -> Option<()> {
+ let size = mem::size_of_val(self);
+ bytes.get_mut(..size)?.copy_from_slice(self.as_bytes());
+ Some(())
+ }
+
+ /// Writes a copy of `self` to the suffix of `bytes`.
+ ///
+ /// `write_to_suffix` writes `self` to the last `size_of_val(self)` bytes of
+ /// `bytes`. If `bytes.len() < size_of_val(self)`, it returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerocopy::AsBytes;
+ /// # use zerocopy_derive::*;
+ ///
+ /// #[derive(AsBytes)]
+ /// #[repr(C)]
+ /// struct PacketHeader {
+ /// src_port: [u8; 2],
+ /// dst_port: [u8; 2],
+ /// length: [u8; 2],
+ /// checksum: [u8; 2],
+ /// }
+ ///
+ /// let header = PacketHeader {
+ /// src_port: [0, 1],
+ /// dst_port: [2, 3],
+ /// length: [4, 5],
+ /// checksum: [6, 7],
+ /// };
+ ///
+ /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ ///
+ /// header.write_to_suffix(&mut bytes[..]);
+ ///
+ /// assert_eq!(bytes, [0, 0, 0, 1, 2, 3, 4, 5, 6, 7]);
+ ///
+ /// let mut insufficent_bytes = &mut [0, 0][..];
+ ///
+ /// let write_result = header.write_to_suffix(insufficent_bytes);
+ ///
+ /// assert!(write_result.is_none());
+ /// assert_eq!(insufficent_bytes, [0, 0]);
+ /// ```
+ ///
+ /// If insufficient target bytes are provided, `write_to_suffix` returns
+ /// `None` and leaves the target bytes unmodified:
+ ///
+ /// ```
+ /// # use zerocopy::AsBytes;
+ /// # let header = u128::MAX;
+ /// let mut insufficent_bytes = &mut [0, 0][..];
+ ///
+ /// let write_result = header.write_to_suffix(insufficent_bytes);
+ ///
+ /// assert!(write_result.is_none());
+ /// assert_eq!(insufficent_bytes, [0, 0]);
+ /// ```
+ #[inline]
+ fn write_to_suffix(&self, bytes: &mut [u8]) -> Option<()> {
+ let start = bytes.len().checked_sub(mem::size_of_val(self))?;
+ bytes
+ .get_mut(start..)
+ .expect("`start` should be in-bounds of `bytes`")
+ .copy_from_slice(self.as_bytes());
+ Some(())
+ }
+}
+
+/// Types with no alignment requirement.
+///
+/// WARNING: Do not implement this trait yourself! Instead, use
+/// `#[derive(Unaligned)]` (requires the `derive` Cargo feature).
+///
+/// If `T: Unaligned`, then `align_of::<T>() == 1`.
+///
+/// # Safety
+///
+/// *This section describes what is required in order for `T: Unaligned`, and
+/// what unsafe code may assume of such types. `#[derive(Unaligned)]` only
+/// permits types which satisfy these requirements. If you don't plan on
+/// implementing `Unaligned` manually, and you don't plan on writing unsafe code
+/// that operates on `Unaligned` types, then you don't need to read this
+/// section.*
+///
+/// If `T: Unaligned`, then unsafe code may assume that it is sound to produce a
+/// reference to `T` at any memory location regardless of alignment. If a type
+/// is marked as `Unaligned` which violates this contract, it may cause
+/// undefined behavior.
+pub unsafe trait Unaligned {
+ // The `Self: Sized` bound makes it so that `Unaligned` is still object
+ // safe.
+ #[doc(hidden)]
+ fn only_derive_is_allowed_to_implement_this_trait()
+ where
+ Self: Sized;
+}
+
+safety_comment! {
+ /// SAFETY:
+ /// Per the reference [1], "the unit tuple (`()`) ... is guaranteed as a
+ /// zero-sized type to have a size of 0 and an alignment of 1."
+ /// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`: There
+ /// is only one possible sequence of 0 bytes, and `()` is inhabited.
+ /// - `AsBytes`: Since `()` has size 0, it contains no padding bytes.
+ /// - `Unaligned`: `()` has alignment 1.
+ ///
+ /// [1] https://doc.rust-lang.org/reference/type-layout.html#tuple-layout
+ unsafe_impl!((): TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_unaligned!(());
+}
+
+safety_comment! {
+ /// SAFETY:
+ /// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`: all bit
+ /// patterns are valid for numeric types [1]
+ /// - `AsBytes`: numeric types have no padding bytes [1]
+ /// - `Unaligned` (`u8` and `i8` only): The reference [2] specifies the size
+ /// of `u8` and `i8` as 1 byte. We also know that:
+ /// - Alignment is >= 1 [3]
+ /// - Size is an integer multiple of alignment [4]
+ /// - The only value >= 1 for which 1 is an integer multiple is 1
+ /// Therefore, the only possible alignment for `u8` and `i8` is 1.
+ ///
+ /// [1] Per https://doc.rust-lang.org/beta/reference/types/numeric.html#bit-validity:
+ ///
+ /// For every numeric type, `T`, the bit validity of `T` is equivalent to
+ /// the bit validity of `[u8; size_of::<T>()]`. An uninitialized byte is
+ /// not a valid `u8`.
+ ///
+ /// TODO(https://github.com/rust-lang/reference/pull/1392): Once this text
+ /// is available on the Stable docs, cite those instead.
+ ///
+ /// [2] https://doc.rust-lang.org/reference/type-layout.html#primitive-data-layout
+ ///
+ /// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
+ ///
+ /// Alignment is measured in bytes, and must be at least 1.
+ ///
+ /// [4] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
+ ///
+ /// The size of a value is always a multiple of its alignment.
+ ///
+ /// TODO(#278): Once we've updated the trait docs to refer to `u8`s rather
+ /// than bits or bytes, update this comment, especially the reference to
+ /// [1].
+ unsafe_impl!(u8: TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ unsafe_impl!(i8: TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_unaligned!(u8, i8);
+ unsafe_impl!(u16: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(i16: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(u32: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(i32: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(u64: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(i64: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(u128: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(i128: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(usize: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(isize: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(f32: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(f64: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+}
+
+safety_comment! {
+ /// SAFETY:
+ /// - `FromZeroes`: Valid since "[t]he value false has the bit pattern
+ /// 0x00" [1].
+ /// - `AsBytes`: Since "the boolean type has a size and alignment of 1 each"
+ /// and "The value false has the bit pattern 0x00 and the value true has
+ /// the bit pattern 0x01" [1]. Thus, the only byte of the bool is always
+ /// initialized.
+ /// - `Unaligned`: Per the reference [1], "[a]n object with the boolean type
+ /// has a size and alignment of 1 each."
+ ///
+ /// [1] https://doc.rust-lang.org/reference/types/boolean.html
+ unsafe_impl!(bool: FromZeroes, AsBytes, Unaligned);
+ assert_unaligned!(bool);
+ /// SAFETY:
+ /// - The safety requirements for `unsafe_impl!` with an `is_bit_valid`
+ /// closure:
+ /// - Given `t: *mut bool` and `let r = *mut u8`, `r` refers to an object
+ /// of the same size as that referred to by `t`. This is true because
+ /// `bool` and `u8` have the same size (1 byte) [1].
+ /// - Since the closure takes a `&u8` argument, given a `Ptr<'a, bool>`
+ /// which satisfies the preconditions of
+ /// `TryFromBytes::<bool>::is_bit_valid`, it must be guaranteed that the
+ /// memory referenced by that `Ptr` always contains a valid `u8`. Since
+ /// `bool`'s single byte is always initialized, `is_bit_valid`'s
+ /// precondition requires that the same is true of its argument. Since
+ /// `u8`'s only bit validity invariant is that its single byte must be
+ /// initialized, this memory is guaranteed to contain a valid `u8`.
+ /// - The alignment of `bool` is equal to the alignment of `u8`. [1] [2]
+ /// - The impl must only return `true` for its argument if the original
+ /// `Ptr<bool>` refers to a valid `bool`. We only return true if the
+ /// `u8` value is 0 or 1, and both of these are valid values for `bool`.
+ /// [3]
+ ///
+ /// [1] Per https://doc.rust-lang.org/reference/type-layout.html#primitive-data-layout:
+ ///
+ /// The size of most primitives is given in this table.
+ ///
+ /// | Type | `size_of::<Type>() ` |
+ /// |-----------|----------------------|
+ /// | `bool` | 1 |
+ /// | `u8`/`i8` | 1 |
+ ///
+ /// [2] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
+ ///
+ /// The size of a value is always a multiple of its alignment.
+ ///
+ /// [3] Per https://doc.rust-lang.org/reference/types/boolean.html:
+ ///
+ /// The value false has the bit pattern 0x00 and the value true has the
+ /// bit pattern 0x01.
+ unsafe_impl!(bool: TryFromBytes; |byte: &u8| *byte < 2);
+}
+safety_comment! {
+ /// SAFETY:
+ /// - `FromZeroes`: Per reference [1], "[a] value of type char is a Unicode
+ /// scalar value (i.e. a code point that is not a surrogate), represented
+ /// as a 32-bit unsigned word in the 0x0000 to 0xD7FF or 0xE000 to
+ /// 0x10FFFF range" which contains 0x0000.
+ /// - `AsBytes`: `char` is per reference [1] "represented as a 32-bit
+ /// unsigned word" (`u32`) which is `AsBytes`. Note that unlike `u32`, not
+ /// all bit patterns are valid for `char`.
+ ///
+ /// [1] https://doc.rust-lang.org/reference/types/textual.html
+ unsafe_impl!(char: FromZeroes, AsBytes);
+ /// SAFETY:
+ /// - The safety requirements for `unsafe_impl!` with an `is_bit_valid`
+ /// closure:
+ /// - Given `t: *mut char` and `let r = *mut u32`, `r` refers to an object
+ /// of the same size as that referred to by `t`. This is true because
+ /// `char` and `u32` have the same size [1].
+ /// - Since the closure takes a `&u32` argument, given a `Ptr<'a, char>`
+ /// which satisfies the preconditions of
+ /// `TryFromBytes::<char>::is_bit_valid`, it must be guaranteed that the
+ /// memory referenced by that `Ptr` always contains a valid `u32`. Since
+ /// `char`'s bytes are always initialized [2], `is_bit_valid`'s
+ /// precondition requires that the same is true of its argument. Since
+ /// `u32`'s only bit validity invariant is that its bytes must be
+ /// initialized, this memory is guaranteed to contain a valid `u32`.
+ /// - The alignment of `char` is equal to the alignment of `u32`. [1]
+ /// - The impl must only return `true` for its argument if the original
+ /// `Ptr<char>` refers to a valid `char`. `char::from_u32` guarantees
+ /// that it returns `None` if its input is not a valid `char`. [3]
+ ///
+ /// [1] Per https://doc.rust-lang.org/nightly/reference/types/textual.html#layout-and-bit-validity:
+ ///
+ /// `char` is guaranteed to have the same size and alignment as `u32` on
+ /// all platforms.
+ ///
+ /// [2] Per https://doc.rust-lang.org/core/primitive.char.html#method.from_u32:
+ ///
+ /// Every byte of a `char` is guaranteed to be initialized.
+ ///
+ /// [3] Per https://doc.rust-lang.org/core/primitive.char.html#method.from_u32:
+ ///
+ /// `from_u32()` will return `None` if the input is not a valid value for
+ /// a `char`.
+ unsafe_impl!(char: TryFromBytes; |candidate: &u32| char::from_u32(*candidate).is_some());
+}
+safety_comment! {
+ /// SAFETY:
+ /// - `FromZeroes`, `AsBytes`, `Unaligned`: Per the reference [1], `str`
+ /// has the same layout as `[u8]`, and `[u8]` is `FromZeroes`, `AsBytes`,
+ /// and `Unaligned`.
+ ///
+ /// Note that we don't `assert_unaligned!(str)` because `assert_unaligned!`
+ /// uses `align_of`, which only works for `Sized` types.
+ ///
+ /// TODO(#429): Add quotes from documentation.
+ ///
+ /// [1] https://doc.rust-lang.org/reference/type-layout.html#str-layout
+ unsafe_impl!(str: FromZeroes, AsBytes, Unaligned);
+ /// SAFETY:
+ /// - The safety requirements for `unsafe_impl!` with an `is_bit_valid`
+ /// closure:
+ /// - Given `t: *mut str` and `let r = *mut [u8]`, `r` refers to an object
+ /// of the same size as that referred to by `t`. This is true because
+ /// `str` and `[u8]` have the same representation. [1]
+ /// - Since the closure takes a `&[u8]` argument, given a `Ptr<'a, str>`
+ /// which satisfies the preconditions of
+ /// `TryFromBytes::<str>::is_bit_valid`, it must be guaranteed that the
+ /// memory referenced by that `Ptr` always contains a valid `[u8]`.
+ /// Since `str`'s bytes are always initialized [1], `is_bit_valid`'s
+ /// precondition requires that the same is true of its argument. Since
+ /// `[u8]`'s only bit validity invariant is that its bytes must be
+ /// initialized, this memory is guaranteed to contain a valid `[u8]`.
+ /// - The alignment of `str` is equal to the alignment of `[u8]`. [1]
+ /// - The impl must only return `true` for its argument if the original
+ /// `Ptr<str>` refers to a valid `str`. `str::from_utf8` guarantees that
+ /// it returns `Err` if its input is not a valid `str`. [2]
+ ///
+ /// [1] Per https://doc.rust-lang.org/reference/types/textual.html:
+ ///
+ /// A value of type `str` is represented the same was as `[u8]`.
+ ///
+ /// [2] Per https://doc.rust-lang.org/core/str/fn.from_utf8.html#errors:
+ ///
+ /// Returns `Err` if the slice is not UTF-8.
+ unsafe_impl!(str: TryFromBytes; |candidate: &[u8]| core::str::from_utf8(candidate).is_ok());
+}
+
+safety_comment! {
+ // `NonZeroXxx` is `AsBytes`, but not `FromZeroes` or `FromBytes`.
+ //
+ /// SAFETY:
+ /// - `AsBytes`: `NonZeroXxx` has the same layout as its associated
+ /// primitive. Since it is the same size, this guarantees it has no
+ /// padding - integers have no padding, and there's no room for padding
+ /// if it can represent all of the same values except 0.
+ /// - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that
+ /// `Option<NonZeroU8>` and `Option<NonZeroI8>` both have size 1. [1] [2]
+ /// This is worded in a way that makes it unclear whether it's meant as a
+ /// guarantee, but given the purpose of those types, it's virtually
+ /// unthinkable that that would ever change. `Option` cannot be smaller
+ /// than its contained type, which implies that, and `NonZeroX8` are of
+ /// size 1 or 0. `NonZeroX8` can represent multiple states, so they cannot
+ /// be 0 bytes, which means that they must be 1 byte. The only valid
+ /// alignment for a 1-byte type is 1.
+ ///
+ /// TODO(#429): Add quotes from documentation.
+ ///
+ /// [1] https://doc.rust-lang.org/stable/std/num/struct.NonZeroU8.html
+ /// [2] https://doc.rust-lang.org/stable/std/num/struct.NonZeroI8.html
+ /// TODO(https://github.com/rust-lang/rust/pull/104082): Cite documentation
+ /// that layout is the same as primitive layout.
+ unsafe_impl!(NonZeroU8: AsBytes, Unaligned);
+ unsafe_impl!(NonZeroI8: AsBytes, Unaligned);
+ assert_unaligned!(NonZeroU8, NonZeroI8);
+ unsafe_impl!(NonZeroU16: AsBytes);
+ unsafe_impl!(NonZeroI16: AsBytes);
+ unsafe_impl!(NonZeroU32: AsBytes);
+ unsafe_impl!(NonZeroI32: AsBytes);
+ unsafe_impl!(NonZeroU64: AsBytes);
+ unsafe_impl!(NonZeroI64: AsBytes);
+ unsafe_impl!(NonZeroU128: AsBytes);
+ unsafe_impl!(NonZeroI128: AsBytes);
+ unsafe_impl!(NonZeroUsize: AsBytes);
+ unsafe_impl!(NonZeroIsize: AsBytes);
+ /// SAFETY:
+ /// - The safety requirements for `unsafe_impl!` with an `is_bit_valid`
+ /// closure:
+ /// - Given `t: *mut NonZeroXxx` and `let r = *mut xxx`, `r` refers to an
+ /// object of the same size as that referred to by `t`. This is true
+ /// because `NonZeroXxx` and `xxx` have the same size. [1]
+ /// - Since the closure takes a `&xxx` argument, given a `Ptr<'a,
+ /// NonZeroXxx>` which satisfies the preconditions of
+ /// `TryFromBytes::<NonZeroXxx>::is_bit_valid`, it must be guaranteed
+ /// that the memory referenced by that `Ptr` always contains a valid
+ /// `xxx`. Since `NonZeroXxx`'s bytes are always initialized [1],
+ /// `is_bit_valid`'s precondition requires that the same is true of its
+ /// argument. Since `xxx`'s only bit validity invariant is that its
+ /// bytes must be initialized, this memory is guaranteed to contain a
+ /// valid `xxx`.
+ /// - The alignment of `NonZeroXxx` is equal to the alignment of `xxx`.
+ /// [1]
+ /// - The impl must only return `true` for its argument if the original
+ /// `Ptr<NonZeroXxx>` refers to a valid `NonZeroXxx`. The only `xxx`
+ /// which is not also a valid `NonZeroXxx` is 0. [1]
+ ///
+ /// [1] Per https://doc.rust-lang.org/core/num/struct.NonZeroU16.html:
+ ///
+ /// `NonZeroU16` is guaranteed to have the same layout and bit validity as
+ /// `u16` with the exception that `0` is not a valid instance.
+ unsafe_impl!(NonZeroU8: TryFromBytes; |n: &u8| *n != 0);
+ unsafe_impl!(NonZeroI8: TryFromBytes; |n: &i8| *n != 0);
+ unsafe_impl!(NonZeroU16: TryFromBytes; |n: &u16| *n != 0);
+ unsafe_impl!(NonZeroI16: TryFromBytes; |n: &i16| *n != 0);
+ unsafe_impl!(NonZeroU32: TryFromBytes; |n: &u32| *n != 0);
+ unsafe_impl!(NonZeroI32: TryFromBytes; |n: &i32| *n != 0);
+ unsafe_impl!(NonZeroU64: TryFromBytes; |n: &u64| *n != 0);
+ unsafe_impl!(NonZeroI64: TryFromBytes; |n: &i64| *n != 0);
+ unsafe_impl!(NonZeroU128: TryFromBytes; |n: &u128| *n != 0);
+ unsafe_impl!(NonZeroI128: TryFromBytes; |n: &i128| *n != 0);
+ unsafe_impl!(NonZeroUsize: TryFromBytes; |n: &usize| *n != 0);
+ unsafe_impl!(NonZeroIsize: TryFromBytes; |n: &isize| *n != 0);
+}
+safety_comment! {
+ /// SAFETY:
+ /// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`,
+ /// `AsBytes`: The Rust compiler reuses `0` value to represent `None`, so
+ /// `size_of::<Option<NonZeroXxx>>() == size_of::<xxx>()`; see
+ /// `NonZeroXxx` documentation.
+ /// - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that
+ /// `Option<NonZeroU8>` and `Option<NonZeroI8>` both have size 1. [1] [2]
+ /// This is worded in a way that makes it unclear whether it's meant as a
+ /// guarantee, but given the purpose of those types, it's virtually
+ /// unthinkable that that would ever change. The only valid alignment for
+ /// a 1-byte type is 1.
+ ///
+ /// TODO(#429): Add quotes from documentation.
+ ///
+ /// [1] https://doc.rust-lang.org/stable/std/num/struct.NonZeroU8.html
+ /// [2] https://doc.rust-lang.org/stable/std/num/struct.NonZeroI8.html
+ ///
+ /// TODO(https://github.com/rust-lang/rust/pull/104082): Cite documentation
+ /// for layout guarantees.
+ unsafe_impl!(Option<NonZeroU8>: TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ unsafe_impl!(Option<NonZeroI8>: TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_unaligned!(Option<NonZeroU8>, Option<NonZeroI8>);
+ unsafe_impl!(Option<NonZeroU16>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroI16>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroU32>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroI32>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroU64>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroI64>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroU128>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroI128>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroUsize>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+ unsafe_impl!(Option<NonZeroIsize>: TryFromBytes, FromZeroes, FromBytes, AsBytes);
+}
+
+safety_comment! {
+ /// SAFETY:
+ /// The following types can be transmuted from `[0u8; size_of::<T>()]`. [1]
+ /// None of them contain `UnsafeCell`s, and so they all soundly implement
+ /// `FromZeroes`.
+ ///
+ /// [1] Per
+ /// https://doc.rust-lang.org/nightly/core/option/index.html#representation:
+ ///
+ /// Rust guarantees to optimize the following types `T` such that
+ /// [`Option<T>`] has the same size and alignment as `T`. In some of these
+ /// cases, Rust further guarantees that `transmute::<_, Option<T>>([0u8;
+ /// size_of::<T>()])` is sound and produces `Option::<T>::None`. These
+ /// cases are identified by the second column:
+ ///
+ /// | `T` | `transmute::<_, Option<T>>([0u8; size_of::<T>()])` sound? |
+ /// |-----------------------|-----------------------------------------------------------|
+ /// | [`Box<U>`] | when `U: Sized` |
+ /// | `&U` | when `U: Sized` |
+ /// | `&mut U` | when `U: Sized` |
+ /// | [`ptr::NonNull<U>`] | when `U: Sized` |
+ /// | `fn`, `extern "C" fn` | always |
+ ///
+ /// TODO(#429), TODO(https://github.com/rust-lang/rust/pull/115333): Cite
+ /// the Stable docs once they're available.
+ #[cfg(feature = "alloc")]
+ unsafe_impl!(
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
+ T => FromZeroes for Option<Box<T>>
+ );
+ unsafe_impl!(T => FromZeroes for Option<&'_ T>);
+ unsafe_impl!(T => FromZeroes for Option<&'_ mut T>);
+ unsafe_impl!(T => FromZeroes for Option<NonNull<T>>);
+ unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeroes for opt_fn!(...));
+ unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeroes for opt_extern_c_fn!(...));
+}
+
+safety_comment! {
+ /// SAFETY:
+ /// Per reference [1]:
+ /// "For all T, the following are guaranteed:
+ /// size_of::<PhantomData<T>>() == 0
+ /// align_of::<PhantomData<T>>() == 1".
+ /// This gives:
+ /// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`: There
+ /// is only one possible sequence of 0 bytes, and `PhantomData` is
+ /// inhabited.
+ /// - `AsBytes`: Since `PhantomData` has size 0, it contains no padding
+ /// bytes.
+ /// - `Unaligned`: Per the preceding reference, `PhantomData` has alignment
+ /// 1.
+ ///
+ /// [1] https://doc.rust-lang.org/std/marker/struct.PhantomData.html#layout-1
+ unsafe_impl!(T: ?Sized => TryFromBytes for PhantomData<T>);
+ unsafe_impl!(T: ?Sized => FromZeroes for PhantomData<T>);
+ unsafe_impl!(T: ?Sized => FromBytes for PhantomData<T>);
+ unsafe_impl!(T: ?Sized => AsBytes for PhantomData<T>);
+ unsafe_impl!(T: ?Sized => Unaligned for PhantomData<T>);
+ assert_unaligned!(PhantomData<()>, PhantomData<u8>, PhantomData<u64>);
+}
+safety_comment! {
+ /// SAFETY:
+ /// `Wrapping<T>` is guaranteed by its docs [1] to have the same layout and
+ /// bit validity as `T`. Also, `Wrapping<T>` is `#[repr(transparent)]`, and
+ /// has a single field, which is `pub`. Per the reference [2], this means
+ /// that the `#[repr(transparent)]` attribute is "considered part of the
+ /// public ABI".
+ ///
+ /// - `TryFromBytes`: The safety requirements for `unsafe_impl!` with an
+ /// `is_bit_valid` closure:
+ /// - Given `t: *mut Wrapping<T>` and `let r = *mut T`, `r` refers to an
+ /// object of the same size as that referred to by `t`. This is true
+ /// because `Wrapping<T>` and `T` have the same layout
+ /// - The alignment of `Wrapping<T>` is equal to the alignment of `T`.
+ /// - The impl must only return `true` for its argument if the original
+ /// `Ptr<Wrapping<T>>` refers to a valid `Wrapping<T>`. Since
+ /// `Wrapping<T>` has the same bit validity as `T`, and since our impl
+ /// just calls `T::is_bit_valid`, our impl returns `true` exactly when
+ /// its argument contains a valid `Wrapping<T>`.
+ /// - `FromBytes`: Since `Wrapping<T>` has the same bit validity as `T`, if
+ /// `T: FromBytes`, then all initialized byte sequences are valid
+ /// instances of `Wrapping<T>`. Similarly, if `T: FromBytes`, then
+ /// `Wrapping<T>` doesn't contain any `UnsafeCell`s. Thus, `impl FromBytes
+ /// for Wrapping<T> where T: FromBytes` is a sound impl.
+ /// - `AsBytes`: Since `Wrapping<T>` has the same bit validity as `T`, if
+ /// `T: AsBytes`, then all valid instances of `Wrapping<T>` have all of
+ /// their bytes initialized. Similarly, if `T: AsBytes`, then
+ /// `Wrapping<T>` doesn't contain any `UnsafeCell`s. Thus, `impl AsBytes
+ /// for Wrapping<T> where T: AsBytes` is a valid impl.
+ /// - `Unaligned`: Since `Wrapping<T>` has the same layout as `T`,
+ /// `Wrapping<T>` has alignment 1 exactly when `T` does.
+ ///
+ /// [1] Per https://doc.rust-lang.org/core/num/struct.NonZeroU16.html:
+ ///
+ /// `NonZeroU16` is guaranteed to have the same layout and bit validity as
+ /// `u16` with the exception that `0` is not a valid instance.
+ ///
+ /// TODO(#429): Add quotes from documentation.
+ ///
+ /// [1] TODO(https://doc.rust-lang.org/nightly/core/num/struct.Wrapping.html#layout-1):
+ /// Reference this documentation once it's available on stable.
+ ///
+ /// [2] https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
+ unsafe_impl!(T: TryFromBytes => TryFromBytes for Wrapping<T>; |candidate: Ptr<T>| {
+ // SAFETY:
+ // - Since `T` and `Wrapping<T>` have the same layout and bit validity
+ // and contain the same fields, `T` contains `UnsafeCell`s exactly
+ // where `Wrapping<T>` does. Thus, all memory and `UnsafeCell`
+ // preconditions of `T::is_bit_valid` hold exactly when the same
+ // preconditions for `Wrapping<T>::is_bit_valid` hold.
+ // - By the same token, since `candidate` is guaranteed to have its
+ // bytes initialized where there are always initialized bytes in
+ // `Wrapping<T>`, the same is true for `T`.
+ unsafe { T::is_bit_valid(candidate) }
+ });
+ unsafe_impl!(T: FromZeroes => FromZeroes for Wrapping<T>);
+ unsafe_impl!(T: FromBytes => FromBytes for Wrapping<T>);
+ unsafe_impl!(T: AsBytes => AsBytes for Wrapping<T>);
+ unsafe_impl!(T: Unaligned => Unaligned for Wrapping<T>);
+ assert_unaligned!(Wrapping<()>, Wrapping<u8>);
+}
+safety_comment! {
+ // `MaybeUninit<T>` is `FromZeroes` and `FromBytes`, but never `AsBytes`
+ // since it may contain uninitialized bytes.
+ //
+ /// SAFETY:
+ /// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`:
+ /// `MaybeUninit<T>` has no restrictions on its contents. Unfortunately,
+ /// in addition to bit validity, `TryFromBytes`, `FromZeroes` and
+ /// `FromBytes` also require that implementers contain no `UnsafeCell`s.
+ /// Thus, we require `T: Trait` in order to ensure that `T` - and thus
+ /// `MaybeUninit<T>` - contains to `UnsafeCell`s. Thus, requiring that `T`
+ /// implement each of these traits is sufficient.
+ /// - `Unaligned`: "MaybeUninit<T> is guaranteed to have the same size,
+ /// alignment, and ABI as T" [1]
+ ///
+ /// [1] https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#layout-1
+ ///
+ /// TODO(https://github.com/google/zerocopy/issues/251): If we split
+ /// `FromBytes` and `RefFromBytes`, or if we introduce a separate
+ /// `NoCell`/`Freeze` trait, we can relax the trait bounds for `FromZeroes`
+ /// and `FromBytes`.
+ unsafe_impl!(T: TryFromBytes => TryFromBytes for MaybeUninit<T>);
+ unsafe_impl!(T: FromZeroes => FromZeroes for MaybeUninit<T>);
+ unsafe_impl!(T: FromBytes => FromBytes for MaybeUninit<T>);
+ unsafe_impl!(T: Unaligned => Unaligned for MaybeUninit<T>);
+ assert_unaligned!(MaybeUninit<()>, MaybeUninit<u8>);
+}
+safety_comment! {
+ /// SAFETY:
+ /// `ManuallyDrop` has the same layout and bit validity as `T` [1], and
+ /// accessing the inner value is safe (meaning that it's unsound to leave
+ /// the inner value uninitialized while exposing the `ManuallyDrop` to safe
+ /// code).
+ /// - `FromZeroes`, `FromBytes`: Since it has the same layout as `T`, any
+ /// valid `T` is a valid `ManuallyDrop<T>`. If `T: FromZeroes`, a sequence
+ /// of zero bytes is a valid `T`, and thus a valid `ManuallyDrop<T>`. If
+ /// `T: FromBytes`, any sequence of bytes is a valid `T`, and thus a valid
+ /// `ManuallyDrop<T>`.
+ /// - `AsBytes`: Since it has the same layout as `T`, and since it's unsound
+ /// to let safe code access a `ManuallyDrop` whose inner value is
+ /// uninitialized, safe code can only ever access a `ManuallyDrop` whose
+ /// contents are a valid `T`. Since `T: AsBytes`, this means that safe
+ /// code can only ever access a `ManuallyDrop` with all initialized bytes.
+ /// - `Unaligned`: `ManuallyDrop` has the same layout (and thus alignment)
+ /// as `T`, and `T: Unaligned` guarantees that that alignment is 1.
+ ///
+ /// `ManuallyDrop<T>` is guaranteed to have the same layout and bit
+ /// validity as `T`
+ ///
+ /// [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html:
+ ///
+ /// TODO(#429):
+ /// - Add quotes from docs.
+ /// - Once [1] (added in
+ /// https://github.com/rust-lang/rust/pull/115522) is available on stable,
+ /// quote the stable docs instead of the nightly docs.
+ unsafe_impl!(T: ?Sized + FromZeroes => FromZeroes for ManuallyDrop<T>);
+ unsafe_impl!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>);
+ unsafe_impl!(T: ?Sized + AsBytes => AsBytes for ManuallyDrop<T>);
+ unsafe_impl!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>);
+ assert_unaligned!(ManuallyDrop<()>, ManuallyDrop<u8>);
+}
+safety_comment! {
+ /// SAFETY:
+ /// Per the reference [1]:
+ ///
+ /// An array of `[T; N]` has a size of `size_of::<T>() * N` and the same
+ /// alignment of `T`. Arrays are laid out so that the zero-based `nth`
+ /// element of the array is offset from the start of the array by `n *
+ /// size_of::<T>()` bytes.
+ ///
+ /// ...
+ ///
+ /// Slices have the same layout as the section of the array they slice.
+ ///
+ /// In other words, the layout of a `[T]` or `[T; N]` is a sequence of `T`s
+ /// laid out back-to-back with no bytes in between. Therefore, `[T]` or `[T;
+ /// N]` are `TryFromBytes`, `FromZeroes`, `FromBytes`, and `AsBytes` if `T`
+ /// is (respectively). Furthermore, since an array/slice has "the same
+ /// alignment of `T`", `[T]` and `[T; N]` are `Unaligned` if `T` is.
+ ///
+ /// Note that we don't `assert_unaligned!` for slice types because
+ /// `assert_unaligned!` uses `align_of`, which only works for `Sized` types.
+ ///
+ /// [1] https://doc.rust-lang.org/reference/type-layout.html#array-layout
+ unsafe_impl!(const N: usize, T: FromZeroes => FromZeroes for [T; N]);
+ unsafe_impl!(const N: usize, T: FromBytes => FromBytes for [T; N]);
+ unsafe_impl!(const N: usize, T: AsBytes => AsBytes for [T; N]);
+ unsafe_impl!(const N: usize, T: Unaligned => Unaligned for [T; N]);
+ assert_unaligned!([(); 0], [(); 1], [u8; 0], [u8; 1]);
+ unsafe_impl!(T: TryFromBytes => TryFromBytes for [T]; |c: Ptr<[T]>| {
+ // SAFETY: Assuming the preconditions of `is_bit_valid` are satisfied,
+ // so too will the postcondition: that, if `is_bit_valid(candidate)`
+ // returns true, `*candidate` contains a valid `Self`. Per the reference
+ // [1]:
+ //
+ // An array of `[T; N]` has a size of `size_of::<T>() * N` and the
+ // same alignment of `T`. Arrays are laid out so that the zero-based
+ // `nth` element of the array is offset from the start of the array by
+ // `n * size_of::<T>()` bytes.
+ //
+ // ...
+ //
+ // Slices have the same layout as the section of the array they slice.
+ //
+ // In other words, the layout of a `[T] is a sequence of `T`s laid out
+ // back-to-back with no bytes in between. If all elements in `candidate`
+ // are `is_bit_valid`, so too is `candidate`.
+ //
+ // Note that any of the below calls may panic, but it would still be
+ // sound even if it did. `is_bit_valid` does not promise that it will
+ // not panic (in fact, it explicitly warns that it's a possibility), and
+ // we have not violated any safety invariants that we must fix before
+ // returning.
+ c.iter().all(|elem|
+ // SAFETY: We uphold the safety contract of `is_bit_valid(elem)`, by
+ // precondition on the surrounding call to `is_bit_valid`. The
+ // memory referenced by `elem` is contained entirely within `c`, and
+ // satisfies the preconditions satisfied by `c`. By axiom, we assume
+ // that `Iterator:all` does not invalidate these preconditions
+ // (e.g., by writing to `elem`.) Since `elem` is derived from `c`,
+ // it is only possible for uninitialized bytes to occur in `elem` at
+ // the same bytes they occur within `c`.
+ unsafe { <T as TryFromBytes>::is_bit_valid(elem) }
+ )
+ });
+ unsafe_impl!(T: FromZeroes => FromZeroes for [T]);
+ unsafe_impl!(T: FromBytes => FromBytes for [T]);
+ unsafe_impl!(T: AsBytes => AsBytes for [T]);
+ unsafe_impl!(T: Unaligned => Unaligned for [T]);
+}
+safety_comment! {
+ /// SAFETY:
+ /// - `FromZeroes`: For thin pointers (note that `T: Sized`), the zero
+ /// pointer is considered "null". [1] No operations which require
+ /// provenance are legal on null pointers, so this is not a footgun.
+ ///
+ /// NOTE(#170): Implementing `FromBytes` and `AsBytes` for raw pointers
+ /// would be sound, but carries provenance footguns. We want to support
+ /// `FromBytes` and `AsBytes` for raw pointers eventually, but we are
+ /// holding off until we can figure out how to address those footguns.
+ ///
+ /// [1] TODO(https://github.com/rust-lang/rust/pull/116988): Cite the
+ /// documentation once this PR lands.
+ unsafe_impl!(T => FromZeroes for *const T);
+ unsafe_impl!(T => FromZeroes for *mut T);
+}
+
+// SIMD support
+//
+// Per the Unsafe Code Guidelines Reference [1]:
+//
+// Packed SIMD vector types are `repr(simd)` homogeneous tuple-structs
+// containing `N` elements of type `T` where `N` is a power-of-two and the
+// size and alignment requirements of `T` are equal:
+//
+// ```rust
+// #[repr(simd)]
+// struct Vector<T, N>(T_0, ..., T_(N - 1));
+// ```
+//
+// ...
+//
+// The size of `Vector` is `N * size_of::<T>()` and its alignment is an
+// implementation-defined function of `T` and `N` greater than or equal to
+// `align_of::<T>()`.
+//
+// ...
+//
+// Vector elements are laid out in source field order, enabling random access
+// to vector elements by reinterpreting the vector as an array:
+//
+// ```rust
+// union U {
+// vec: Vector<T, N>,
+// arr: [T; N]
+// }
+//
+// assert_eq!(size_of::<Vector<T, N>>(), size_of::<[T; N]>());
+// assert!(align_of::<Vector<T, N>>() >= align_of::<[T; N]>());
+//
+// unsafe {
+// let u = U { vec: Vector<T, N>(t_0, ..., t_(N - 1)) };
+//
+// assert_eq!(u.vec.0, u.arr[0]);
+// // ...
+// assert_eq!(u.vec.(N - 1), u.arr[N - 1]);
+// }
+// ```
+//
+// Given this background, we can observe that:
+// - The size and bit pattern requirements of a SIMD type are equivalent to the
+// equivalent array type. Thus, for any SIMD type whose primitive `T` is
+// `TryFromBytes`, `FromZeroes`, `FromBytes`, or `AsBytes`, that SIMD type is
+// also `TryFromBytes`, `FromZeroes`, `FromBytes`, or `AsBytes` respectively.
+// - Since no upper bound is placed on the alignment, no SIMD type can be
+// guaranteed to be `Unaligned`.
+//
+// Also per [1]:
+//
+// This chapter represents the consensus from issue #38. The statements in
+// here are not (yet) "guaranteed" not to change until an RFC ratifies them.
+//
+// See issue #38 [2]. While this behavior is not technically guaranteed, the
+// likelihood that the behavior will change such that SIMD types are no longer
+// `TryFromBytes`, `FromZeroes`, `FromBytes`, or `AsBytes` is next to zero, as
+// that would defeat the entire purpose of SIMD types. Nonetheless, we put this
+// behavior behind the `simd` Cargo feature, which requires consumers to opt
+// into this stability hazard.
+//
+// [1] https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html
+// [2] https://github.com/rust-lang/unsafe-code-guidelines/issues/38
+#[cfg(feature = "simd")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "simd")))]
+mod simd {
+ /// Defines a module which implements `TryFromBytes`, `FromZeroes`,
+ /// `FromBytes`, and `AsBytes` for a set of types from a module in
+ /// `core::arch`.
+ ///
+ /// `$arch` is both the name of the defined module and the name of the
+ /// module in `core::arch`, and `$typ` is the list of items from that module
+ /// to implement `FromZeroes`, `FromBytes`, and `AsBytes` for.
+ #[allow(unused_macros)] // `allow(unused_macros)` is needed because some
+ // target/feature combinations don't emit any impls
+ // and thus don't use this macro.
+ macro_rules! simd_arch_mod {
+ (#[cfg $cfg:tt] $arch:ident, $mod:ident, $($typ:ident),*) => {
+ #[cfg $cfg]
+ #[cfg_attr(doc_cfg, doc(cfg $cfg))]
+ mod $mod {
+ use core::arch::$arch::{$($typ),*};
+
+ use crate::*;
+ impl_known_layout!($($typ),*);
+ safety_comment! {
+ /// SAFETY:
+ /// See comment on module definition for justification.
+ $( unsafe_impl!($typ: TryFromBytes, FromZeroes, FromBytes, AsBytes); )*
+ }
+ }
+ };
+ }
+
+ #[rustfmt::skip]
+ const _: () = {
+ simd_arch_mod!(
+ #[cfg(target_arch = "x86")]
+ x86, x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i
+ );
+ simd_arch_mod!(
+ #[cfg(all(feature = "simd-nightly", target_arch = "x86"))]
+ x86, x86_nightly, __m512bh, __m512, __m512d, __m512i
+ );
+ simd_arch_mod!(
+ #[cfg(target_arch = "x86_64")]
+ x86_64, x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i
+ );
+ simd_arch_mod!(
+ #[cfg(all(feature = "simd-nightly", target_arch = "x86_64"))]
+ x86_64, x86_64_nightly, __m512bh, __m512, __m512d, __m512i
+ );
+ simd_arch_mod!(
+ #[cfg(target_arch = "wasm32")]
+ wasm32, wasm32, v128
+ );
+ simd_arch_mod!(
+ #[cfg(all(feature = "simd-nightly", target_arch = "powerpc"))]
+ powerpc, powerpc, vector_bool_long, vector_double, vector_signed_long, vector_unsigned_long
+ );
+ simd_arch_mod!(
+ #[cfg(all(feature = "simd-nightly", target_arch = "powerpc64"))]
+ powerpc64, powerpc64, vector_bool_long, vector_double, vector_signed_long, vector_unsigned_long
+ );
+ simd_arch_mod!(
+ #[cfg(target_arch = "aarch64")]
+ aarch64, aarch64, float32x2_t, float32x4_t, float64x1_t, float64x2_t, int8x8_t, int8x8x2_t,
+ int8x8x3_t, int8x8x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int16x4_t,
+ int16x8_t, int32x2_t, int32x4_t, int64x1_t, int64x2_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t,
+ poly8x8x4_t, poly8x16_t, poly8x16x2_t, poly8x16x3_t, poly8x16x4_t, poly16x4_t, poly16x8_t,
+ poly64x1_t, poly64x2_t, uint8x8_t, uint8x8x2_t, uint8x8x3_t, uint8x8x4_t, uint8x16_t,
+ uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint16x4_t, uint16x8_t, uint32x2_t, uint32x4_t,
+ uint64x1_t, uint64x2_t
+ );
+ simd_arch_mod!(
+ #[cfg(all(feature = "simd-nightly", target_arch = "arm"))]
+ arm, arm, int8x4_t, uint8x4_t
+ );
+ };
+}
+
+/// Safely transmutes a value of one type to a value of another type of the same
+/// size.
+///
+/// The expression `$e` must have a concrete type, `T`, which implements
+/// `AsBytes`. The `transmute!` expression must also have a concrete type, `U`
+/// (`U` is inferred from the calling context), and `U` must implement
+/// `FromBytes`.
+///
+/// Note that the `T` produced by the expression `$e` will *not* be dropped.
+/// Semantically, its bits will be copied into a new value of type `U`, the
+/// original `T` will be forgotten, and the value of type `U` will be returned.
+///
+/// # Examples
+///
+/// ```
+/// # use zerocopy::transmute;
+/// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
+///
+/// let two_dimensional: [[u8; 4]; 2] = transmute!(one_dimensional);
+///
+/// assert_eq!(two_dimensional, [[0, 1, 2, 3], [4, 5, 6, 7]]);
+/// ```
+#[macro_export]
+macro_rules! transmute {
+ ($e:expr) => {{
+ // NOTE: This must be a macro (rather than a function with trait bounds)
+ // because there's no way, in a generic context, to enforce that two
+ // types have the same size. `core::mem::transmute` uses compiler magic
+ // to enforce this so long as the types are concrete.
+
+ let e = $e;
+ if false {
+ // This branch, though never taken, ensures that the type of `e` is
+ // `AsBytes` and that the type of this macro invocation expression
+ // is `FromBytes`.
+
+ struct AssertIsAsBytes<T: $crate::AsBytes>(T);
+ let _ = AssertIsAsBytes(e);
+
+ struct AssertIsFromBytes<U: $crate::FromBytes>(U);
+ #[allow(unused, unreachable_code)]
+ let u = AssertIsFromBytes(loop {});
+ u.0
+ } else {
+ // SAFETY: `core::mem::transmute` ensures that the type of `e` and
+ // the type of this macro invocation expression have the same size.
+ // We know this transmute is safe thanks to the `AsBytes` and
+ // `FromBytes` bounds enforced by the `false` branch.
+ //
+ // We use this reexport of `core::mem::transmute` because we know it
+ // will always be available for crates which are using the 2015
+ // edition of Rust. By contrast, if we were to use
+ // `std::mem::transmute`, this macro would not work for such crates
+ // in `no_std` contexts, and if we were to use
+ // `core::mem::transmute`, this macro would not work in `std`
+ // contexts in which `core` was not manually imported. This is not a
+ // problem for 2018 edition crates.
+ unsafe {
+ // Clippy: It's okay to transmute a type to itself.
+ #[allow(clippy::useless_transmute)]
+ $crate::macro_util::core_reexport::mem::transmute(e)
+ }
+ }
+ }}
+}
+
+/// Safely transmutes a mutable or immutable reference of one type to an
+/// immutable reference of another type of the same size.
+///
+/// The expression `$e` must have a concrete type, `&T` or `&mut T`, where `T:
+/// Sized + AsBytes`. The `transmute_ref!` expression must also have a concrete
+/// type, `&U` (`U` is inferred from the calling context), where `U: Sized +
+/// FromBytes`. It must be the case that `align_of::<T>() >= align_of::<U>()`.
+///
+/// The lifetime of the input type, `&T` or `&mut T`, must be the same as or
+/// outlive the lifetime of the output type, `&U`.
+///
+/// # Examples
+///
+/// ```
+/// # use zerocopy::transmute_ref;
+/// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
+///
+/// let two_dimensional: &[[u8; 4]; 2] = transmute_ref!(&one_dimensional);
+///
+/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
+/// ```
+///
+/// # Alignment increase error message
+///
+/// Because of limitations on macros, the error message generated when
+/// `transmute_ref!` is used to transmute from a type of lower alignment to a
+/// type of higher alignment is somewhat confusing. For example, the following
+/// code:
+///
+/// ```compile_fail
+/// const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]);
+/// ```
+///
+/// ...generates the following error:
+///
+/// ```text
+/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+/// --> src/lib.rs:1524:34
+/// |
+/// 5 | const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]);
+/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+/// |
+/// = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+/// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
+/// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+/// ```
+///
+/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
+/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
+/// align_of::<U>()`.
+#[macro_export]
+macro_rules! transmute_ref {
+ ($e:expr) => {{
+ // NOTE: This must be a macro (rather than a function with trait bounds)
+ // because there's no way, in a generic context, to enforce that two
+ // types have the same size or alignment.
+
+ // Ensure that the source type is a reference or a mutable reference
+ // (note that mutable references are implicitly reborrowed here).
+ let e: &_ = $e;
+
+ #[allow(unused, clippy::diverging_sub_expression)]
+ if false {
+ // This branch, though never taken, ensures that the type of `e` is
+ // `&T` where `T: 't + Sized + AsBytes`, that the type of this macro
+ // expression is `&U` where `U: 'u + Sized + FromBytes`, and that
+ // `'t` outlives `'u`.
+
+ struct AssertIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T);
+ let _ = AssertIsAsBytes(e);
+
+ struct AssertIsFromBytes<'a, U: ::core::marker::Sized + $crate::FromBytes>(&'a U);
+ #[allow(unused, unreachable_code)]
+ let u = AssertIsFromBytes(loop {});
+ u.0
+ } else if false {
+ // This branch, though never taken, ensures that `size_of::<T>() ==
+ // size_of::<U>()` and that that `align_of::<T>() >=
+ // align_of::<U>()`.
+
+ // `t` is inferred to have type `T` because it's assigned to `e` (of
+ // type `&T`) as `&t`.
+ let mut t = unreachable!();
+ e = &t;
+
+ // `u` is inferred to have type `U` because it's used as `&u` as the
+ // value returned from this branch.
+ let u;
+
+ $crate::assert_size_eq!(t, u);
+ $crate::assert_align_gt_eq!(t, u);
+
+ &u
+ } else {
+ // SAFETY: For source type `Src` and destination type `Dst`:
+ // - We know that `Src: AsBytes` and `Dst: FromBytes` thanks to the
+ // uses of `AssertIsAsBytes` and `AssertIsFromBytes` above.
+ // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to
+ // the use of `assert_size_eq!` above.
+ // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to
+ // the use of `assert_align_gt_eq!` above.
+ unsafe { $crate::macro_util::transmute_ref(e) }
+ }
+ }}
+}
+
+/// Safely transmutes a mutable reference of one type to an mutable reference of
+/// another type of the same size.
+///
+/// The expression `$e` must have a concrete type, `&mut T`, where `T: Sized +
+/// AsBytes`. The `transmute_mut!` expression must also have a concrete type,
+/// `&mut U` (`U` is inferred from the calling context), where `U: Sized +
+/// FromBytes`. It must be the case that `align_of::<T>() >= align_of::<U>()`.
+///
+/// The lifetime of the input type, `&mut T`, must be the same as or outlive the
+/// lifetime of the output type, `&mut U`.
+///
+/// # Examples
+///
+/// ```
+/// # use zerocopy::transmute_mut;
+/// let mut one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
+///
+/// let two_dimensional: &mut [[u8; 4]; 2] = transmute_mut!(&mut one_dimensional);
+///
+/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
+///
+/// two_dimensional.reverse();
+///
+/// assert_eq!(one_dimensional, [4, 5, 6, 7, 0, 1, 2, 3]);
+/// ```
+///
+/// # Alignment increase error message
+///
+/// Because of limitations on macros, the error message generated when
+/// `transmute_mut!` is used to transmute from a type of lower alignment to a
+/// type of higher alignment is somewhat confusing. For example, the following
+/// code:
+///
+/// ```compile_fail
+/// const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]);
+/// ```
+///
+/// ...generates the following error:
+///
+/// ```text
+/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+/// --> src/lib.rs:1524:34
+/// |
+/// 5 | const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]);
+/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+/// |
+/// = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+/// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
+/// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+/// ```
+///
+/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
+/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
+/// align_of::<U>()`.
+#[macro_export]
+macro_rules! transmute_mut {
+ ($e:expr) => {{
+ // NOTE: This must be a macro (rather than a function with trait bounds)
+ // because there's no way, in a generic context, to enforce that two
+ // types have the same size or alignment.
+
+ // Ensure that the source type is a mutable reference.
+ let e: &mut _ = $e;
+
+ #[allow(unused, clippy::diverging_sub_expression)]
+ if false {
+ // This branch, though never taken, ensures that the type of `e` is
+ // `&mut T` where `T: 't + Sized + FromBytes + AsBytes`, that the
+ // type of this macro expression is `&mut U` where `U: 'u + Sized +
+ // FromBytes + AsBytes`.
+
+ // We use immutable references here rather than mutable so that, if
+ // this macro is used in a const context (in which, as of this
+ // writing, mutable references are banned), the error message
+ // appears to originate in the user's code rather than in the
+ // internals of this macro.
+ struct AssertSrcIsFromBytes<'a, T: ::core::marker::Sized + $crate::FromBytes>(&'a T);
+ struct AssertSrcIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T);
+ struct AssertDstIsFromBytes<'a, T: ::core::marker::Sized + $crate::FromBytes>(&'a T);
+ struct AssertDstIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T);
+
+ if true {
+ let _ = AssertSrcIsFromBytes(&*e);
+ } else {
+ let _ = AssertSrcIsAsBytes(&*e);
+ }
+
+ if true {
+ #[allow(unused, unreachable_code)]
+ let u = AssertDstIsFromBytes(loop {});
+ &mut *u.0
+ } else {
+ #[allow(unused, unreachable_code)]
+ let u = AssertDstIsAsBytes(loop {});
+ &mut *u.0
+ }
+ } else if false {
+ // This branch, though never taken, ensures that `size_of::<T>() ==
+ // size_of::<U>()` and that that `align_of::<T>() >=
+ // align_of::<U>()`.
+
+ // `t` is inferred to have type `T` because it's assigned to `e` (of
+ // type `&mut T`) as `&mut t`.
+ let mut t = unreachable!();
+ e = &mut t;
+
+ // `u` is inferred to have type `U` because it's used as `&mut u` as
+ // the value returned from this branch.
+ let u;
+
+ $crate::assert_size_eq!(t, u);
+ $crate::assert_align_gt_eq!(t, u);
+
+ &mut u
+ } else {
+ // SAFETY: For source type `Src` and destination type `Dst`:
+ // - We know that `Src: FromBytes + AsBytes` and `Dst: FromBytes +
+ // AsBytes` thanks to the uses of `AssertSrcIsFromBytes`,
+ // `AssertSrcIsAsBytes`, `AssertDstIsFromBytes`, and
+ // `AssertDstIsAsBytes` above.
+ // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to
+ // the use of `assert_size_eq!` above.
+ // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to
+ // the use of `assert_align_gt_eq!` above.
+ unsafe { $crate::macro_util::transmute_mut(e) }
+ }
+ }}
+}
+
+/// Includes a file and safely transmutes it to a value of an arbitrary type.
+///
+/// The file will be included as a byte array, `[u8; N]`, which will be
+/// transmuted to another type, `T`. `T` is inferred from the calling context,
+/// and must implement [`FromBytes`].
+///
+/// The file is located relative to the current file (similarly to how modules
+/// are found). The provided path is interpreted in a platform-specific way at
+/// compile time. So, for instance, an invocation with a Windows path containing
+/// backslashes `\` would not compile correctly on Unix.
+///
+/// `include_value!` is ignorant of byte order. For byte order-aware types, see
+/// the [`byteorder`] module.
+///
+/// # Examples
+///
+/// Assume there are two files in the same directory with the following
+/// contents:
+///
+/// File `data` (no trailing newline):
+///
+/// ```text
+/// abcd
+/// ```
+///
+/// File `main.rs`:
+///
+/// ```rust
+/// use zerocopy::include_value;
+/// # macro_rules! include_value {
+/// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) };
+/// # }
+///
+/// fn main() {
+/// let as_u32: u32 = include_value!("data");
+/// assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
+/// let as_i32: i32 = include_value!("data");
+/// assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
+/// }
+/// ```
+#[doc(alias("include_bytes", "include_data", "include_type"))]
+#[macro_export]
+macro_rules! include_value {
+ ($file:expr $(,)?) => {
+ $crate::transmute!(*::core::include_bytes!($file))
+ };
+}
+
+/// A typed reference derived from a byte slice.
+///
+/// A `Ref<B, T>` is a reference to a `T` which is stored in a byte slice, `B`.
+/// Unlike a native reference (`&T` or `&mut T`), `Ref<B, T>` has the same
+/// mutability as the byte slice it was constructed from (`B`).
+///
+/// # Examples
+///
+/// `Ref` can be used to treat a sequence of bytes as a structured type, and to
+/// read and write the fields of that type as if the byte slice reference were
+/// simply a reference to that type.
+///
+/// ```rust
+/// # #[cfg(feature = "derive")] { // This example uses derives, and won't compile without them
+/// use zerocopy::{AsBytes, ByteSlice, ByteSliceMut, FromBytes, FromZeroes, Ref, Unaligned};
+///
+/// #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+/// #[repr(C)]
+/// struct UdpHeader {
+/// src_port: [u8; 2],
+/// dst_port: [u8; 2],
+/// length: [u8; 2],
+/// checksum: [u8; 2],
+/// }
+///
+/// struct UdpPacket<B> {
+/// header: Ref<B, UdpHeader>,
+/// body: B,
+/// }
+///
+/// impl<B: ByteSlice> UdpPacket<B> {
+/// pub fn parse(bytes: B) -> Option<UdpPacket<B>> {
+/// let (header, body) = Ref::new_unaligned_from_prefix(bytes)?;
+/// Some(UdpPacket { header, body })
+/// }
+///
+/// pub fn get_src_port(&self) -> [u8; 2] {
+/// self.header.src_port
+/// }
+/// }
+///
+/// impl<B: ByteSliceMut> UdpPacket<B> {
+/// pub fn set_src_port(&mut self, src_port: [u8; 2]) {
+/// self.header.src_port = src_port;
+/// }
+/// }
+/// # }
+/// ```
+pub struct Ref<B, T: ?Sized>(B, PhantomData<T>);
+
+/// Deprecated: prefer [`Ref`] instead.
+#[deprecated(since = "0.7.0", note = "LayoutVerified has been renamed to Ref")]
+#[doc(hidden)]
+pub type LayoutVerified<B, T> = Ref<B, T>;
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSlice,
+{
+ /// Constructs a new `Ref`.
+ ///
+ /// `new` verifies that `bytes.len() == size_of::<T>()` and that `bytes` is
+ /// aligned to `align_of::<T>()`, and constructs a new `Ref`. If either of
+ /// these checks fail, it returns `None`.
+ #[inline]
+ pub fn new(bytes: B) -> Option<Ref<B, T>> {
+ if bytes.len() != mem::size_of::<T>() || !util::aligned_to::<_, T>(bytes.deref()) {
+ return None;
+ }
+ Some(Ref(bytes, PhantomData))
+ }
+
+ /// Constructs a new `Ref` from the prefix of a byte slice.
+ ///
+ /// `new_from_prefix` verifies that `bytes.len() >= size_of::<T>()` and that
+ /// `bytes` is aligned to `align_of::<T>()`. It consumes the first
+ /// `size_of::<T>()` bytes from `bytes` to construct a `Ref`, and returns
+ /// the remaining bytes to the caller. If either the length or alignment
+ /// checks fail, it returns `None`.
+ #[inline]
+ pub fn new_from_prefix(bytes: B) -> Option<(Ref<B, T>, B)> {
+ if bytes.len() < mem::size_of::<T>() || !util::aligned_to::<_, T>(bytes.deref()) {
+ return None;
+ }
+ let (bytes, suffix) = bytes.split_at(mem::size_of::<T>());
+ Some((Ref(bytes, PhantomData), suffix))
+ }
+
+ /// Constructs a new `Ref` from the suffix of a byte slice.
+ ///
+ /// `new_from_suffix` verifies that `bytes.len() >= size_of::<T>()` and that
+ /// the last `size_of::<T>()` bytes of `bytes` are aligned to
+ /// `align_of::<T>()`. It consumes the last `size_of::<T>()` bytes from
+ /// `bytes` to construct a `Ref`, and returns the preceding bytes to the
+ /// caller. If either the length or alignment checks fail, it returns
+ /// `None`.
+ #[inline]
+ pub fn new_from_suffix(bytes: B) -> Option<(B, Ref<B, T>)> {
+ let bytes_len = bytes.len();
+ let split_at = bytes_len.checked_sub(mem::size_of::<T>())?;
+ let (prefix, bytes) = bytes.split_at(split_at);
+ if !util::aligned_to::<_, T>(bytes.deref()) {
+ return None;
+ }
+ Some((prefix, Ref(bytes, PhantomData)))
+ }
+}
+
+impl<B, T> Ref<B, [T]>
+where
+ B: ByteSlice,
+{
+ /// Constructs a new `Ref` of a slice type.
+ ///
+ /// `new_slice` verifies that `bytes.len()` is a multiple of
+ /// `size_of::<T>()` and that `bytes` is aligned to `align_of::<T>()`, and
+ /// constructs a new `Ref`. If either of these checks fail, it returns
+ /// `None`.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice` panics if `T` is a zero-sized type.
+ #[inline]
+ pub fn new_slice(bytes: B) -> Option<Ref<B, [T]>> {
+ let remainder = bytes
+ .len()
+ .checked_rem(mem::size_of::<T>())
+ .expect("Ref::new_slice called on a zero-sized type");
+ if remainder != 0 || !util::aligned_to::<_, T>(bytes.deref()) {
+ return None;
+ }
+ Some(Ref(bytes, PhantomData))
+ }
+
+ /// Constructs a new `Ref` of a slice type from the prefix of a byte slice.
+ ///
+ /// `new_slice_from_prefix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count` and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// first `size_of::<T>() * count` bytes from `bytes` to construct a `Ref`,
+ /// and returns the remaining bytes to the caller. It also ensures that
+ /// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
+ /// length, alignment, or overflow checks fail, it returns `None`.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_from_prefix` panics if `T` is a zero-sized type.
+ #[inline]
+ pub fn new_slice_from_prefix(bytes: B, count: usize) -> Option<(Ref<B, [T]>, B)> {
+ let expected_len = match mem::size_of::<T>().checked_mul(count) {
+ Some(len) => len,
+ None => return None,
+ };
+ if bytes.len() < expected_len {
+ return None;
+ }
+ let (prefix, bytes) = bytes.split_at(expected_len);
+ Self::new_slice(prefix).map(move |l| (l, bytes))
+ }
+
+ /// Constructs a new `Ref` of a slice type from the suffix of a byte slice.
+ ///
+ /// `new_slice_from_suffix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count` and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// last `size_of::<T>() * count` bytes from `bytes` to construct a `Ref`,
+ /// and returns the preceding bytes to the caller. It also ensures that
+ /// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
+ /// length, alignment, or overflow checks fail, it returns `None`.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_from_suffix` panics if `T` is a zero-sized type.
+ #[inline]
+ pub fn new_slice_from_suffix(bytes: B, count: usize) -> Option<(B, Ref<B, [T]>)> {
+ let expected_len = match mem::size_of::<T>().checked_mul(count) {
+ Some(len) => len,
+ None => return None,
+ };
+ let split_at = bytes.len().checked_sub(expected_len)?;
+ let (bytes, suffix) = bytes.split_at(split_at);
+ Self::new_slice(suffix).map(move |l| (bytes, l))
+ }
+}
+
+fn map_zeroed<B: ByteSliceMut, T: ?Sized>(opt: Option<Ref<B, T>>) -> Option<Ref<B, T>> {
+ match opt {
+ Some(mut r) => {
+ r.0.fill(0);
+ Some(r)
+ }
+ None => None,
+ }
+}
+
+fn map_prefix_tuple_zeroed<B: ByteSliceMut, T: ?Sized>(
+ opt: Option<(Ref<B, T>, B)>,
+) -> Option<(Ref<B, T>, B)> {
+ match opt {
+ Some((mut r, rest)) => {
+ r.0.fill(0);
+ Some((r, rest))
+ }
+ None => None,
+ }
+}
+
+fn map_suffix_tuple_zeroed<B: ByteSliceMut, T: ?Sized>(
+ opt: Option<(B, Ref<B, T>)>,
+) -> Option<(B, Ref<B, T>)> {
+ map_prefix_tuple_zeroed(opt.map(|(a, b)| (b, a))).map(|(a, b)| (b, a))
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSliceMut,
+{
+ /// Constructs a new `Ref` after zeroing the bytes.
+ ///
+ /// `new_zeroed` verifies that `bytes.len() == size_of::<T>()` and that
+ /// `bytes` is aligned to `align_of::<T>()`, and constructs a new `Ref`. If
+ /// either of these checks fail, it returns `None`.
+ ///
+ /// If the checks succeed, then `bytes` will be initialized to zero. This
+ /// can be useful when re-using buffers to ensure that sensitive data
+ /// previously stored in the buffer is not leaked.
+ #[inline(always)]
+ pub fn new_zeroed(bytes: B) -> Option<Ref<B, T>> {
+ map_zeroed(Self::new(bytes))
+ }
+
+ /// Constructs a new `Ref` from the prefix of a byte slice, zeroing the
+ /// prefix.
+ ///
+ /// `new_from_prefix_zeroed` verifies that `bytes.len() >= size_of::<T>()`
+ /// and that `bytes` is aligned to `align_of::<T>()`. It consumes the first
+ /// `size_of::<T>()` bytes from `bytes` to construct a `Ref`, and returns
+ /// the remaining bytes to the caller. If either the length or alignment
+ /// checks fail, it returns `None`.
+ ///
+ /// If the checks succeed, then the prefix which is consumed will be
+ /// initialized to zero. This can be useful when re-using buffers to ensure
+ /// that sensitive data previously stored in the buffer is not leaked.
+ #[inline(always)]
+ pub fn new_from_prefix_zeroed(bytes: B) -> Option<(Ref<B, T>, B)> {
+ map_prefix_tuple_zeroed(Self::new_from_prefix(bytes))
+ }
+
+ /// Constructs a new `Ref` from the suffix of a byte slice, zeroing the
+ /// suffix.
+ ///
+ /// `new_from_suffix_zeroed` verifies that `bytes.len() >= size_of::<T>()`
+ /// and that the last `size_of::<T>()` bytes of `bytes` are aligned to
+ /// `align_of::<T>()`. It consumes the last `size_of::<T>()` bytes from
+ /// `bytes` to construct a `Ref`, and returns the preceding bytes to the
+ /// caller. If either the length or alignment checks fail, it returns
+ /// `None`.
+ ///
+ /// If the checks succeed, then the suffix which is consumed will be
+ /// initialized to zero. This can be useful when re-using buffers to ensure
+ /// that sensitive data previously stored in the buffer is not leaked.
+ #[inline(always)]
+ pub fn new_from_suffix_zeroed(bytes: B) -> Option<(B, Ref<B, T>)> {
+ map_suffix_tuple_zeroed(Self::new_from_suffix(bytes))
+ }
+}
+
+impl<B, T> Ref<B, [T]>
+where
+ B: ByteSliceMut,
+{
+ /// Constructs a new `Ref` of a slice type after zeroing the bytes.
+ ///
+ /// `new_slice_zeroed` verifies that `bytes.len()` is a multiple of
+ /// `size_of::<T>()` and that `bytes` is aligned to `align_of::<T>()`, and
+ /// constructs a new `Ref`. If either of these checks fail, it returns
+ /// `None`.
+ ///
+ /// If the checks succeed, then `bytes` will be initialized to zero. This
+ /// can be useful when re-using buffers to ensure that sensitive data
+ /// previously stored in the buffer is not leaked.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice` panics if `T` is a zero-sized type.
+ #[inline(always)]
+ pub fn new_slice_zeroed(bytes: B) -> Option<Ref<B, [T]>> {
+ map_zeroed(Self::new_slice(bytes))
+ }
+
+ /// Constructs a new `Ref` of a slice type from the prefix of a byte slice,
+ /// after zeroing the bytes.
+ ///
+ /// `new_slice_from_prefix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count` and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// first `size_of::<T>() * count` bytes from `bytes` to construct a `Ref`,
+ /// and returns the remaining bytes to the caller. It also ensures that
+ /// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
+ /// length, alignment, or overflow checks fail, it returns `None`.
+ ///
+ /// If the checks succeed, then the suffix which is consumed will be
+ /// initialized to zero. This can be useful when re-using buffers to ensure
+ /// that sensitive data previously stored in the buffer is not leaked.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_from_prefix_zeroed` panics if `T` is a zero-sized type.
+ #[inline(always)]
+ pub fn new_slice_from_prefix_zeroed(bytes: B, count: usize) -> Option<(Ref<B, [T]>, B)> {
+ map_prefix_tuple_zeroed(Self::new_slice_from_prefix(bytes, count))
+ }
+
+ /// Constructs a new `Ref` of a slice type from the prefix of a byte slice,
+ /// after zeroing the bytes.
+ ///
+ /// `new_slice_from_suffix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count` and that `bytes` is aligned to `align_of::<T>()`. It consumes the
+ /// last `size_of::<T>() * count` bytes from `bytes` to construct a `Ref`,
+ /// and returns the preceding bytes to the caller. It also ensures that
+ /// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
+ /// length, alignment, or overflow checks fail, it returns `None`.
+ ///
+ /// If the checks succeed, then the consumed suffix will be initialized to
+ /// zero. This can be useful when re-using buffers to ensure that sensitive
+ /// data previously stored in the buffer is not leaked.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_from_suffix_zeroed` panics if `T` is a zero-sized type.
+ #[inline(always)]
+ pub fn new_slice_from_suffix_zeroed(bytes: B, count: usize) -> Option<(B, Ref<B, [T]>)> {
+ map_suffix_tuple_zeroed(Self::new_slice_from_suffix(bytes, count))
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSlice,
+ T: Unaligned,
+{
+ /// Constructs a new `Ref` for a type with no alignment requirement.
+ ///
+ /// `new_unaligned` verifies that `bytes.len() == size_of::<T>()` and
+ /// constructs a new `Ref`. If the check fails, it returns `None`.
+ #[inline(always)]
+ pub fn new_unaligned(bytes: B) -> Option<Ref<B, T>> {
+ Ref::new(bytes)
+ }
+
+ /// Constructs a new `Ref` from the prefix of a byte slice for a type with
+ /// no alignment requirement.
+ ///
+ /// `new_unaligned_from_prefix` verifies that `bytes.len() >=
+ /// size_of::<T>()`. It consumes the first `size_of::<T>()` bytes from
+ /// `bytes` to construct a `Ref`, and returns the remaining bytes to the
+ /// caller. If the length check fails, it returns `None`.
+ #[inline(always)]
+ pub fn new_unaligned_from_prefix(bytes: B) -> Option<(Ref<B, T>, B)> {
+ Ref::new_from_prefix(bytes)
+ }
+
+ /// Constructs a new `Ref` from the suffix of a byte slice for a type with
+ /// no alignment requirement.
+ ///
+ /// `new_unaligned_from_suffix` verifies that `bytes.len() >=
+ /// size_of::<T>()`. It consumes the last `size_of::<T>()` bytes from
+ /// `bytes` to construct a `Ref`, and returns the preceding bytes to the
+ /// caller. If the length check fails, it returns `None`.
+ #[inline(always)]
+ pub fn new_unaligned_from_suffix(bytes: B) -> Option<(B, Ref<B, T>)> {
+ Ref::new_from_suffix(bytes)
+ }
+}
+
+impl<B, T> Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: Unaligned,
+{
+ /// Constructs a new `Ref` of a slice type with no alignment requirement.
+ ///
+ /// `new_slice_unaligned` verifies that `bytes.len()` is a multiple of
+ /// `size_of::<T>()` and constructs a new `Ref`. If the check fails, it
+ /// returns `None`.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice` panics if `T` is a zero-sized type.
+ #[inline(always)]
+ pub fn new_slice_unaligned(bytes: B) -> Option<Ref<B, [T]>> {
+ Ref::new_slice(bytes)
+ }
+
+ /// Constructs a new `Ref` of a slice type with no alignment requirement
+ /// from the prefix of a byte slice.
+ ///
+ /// `new_slice_from_prefix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count`. It consumes the first `size_of::<T>() * count` bytes from
+ /// `bytes` to construct a `Ref`, and returns the remaining bytes to the
+ /// caller. It also ensures that `sizeof::<T>() * count` does not overflow a
+ /// `usize`. If either the length, or overflow checks fail, it returns
+ /// `None`.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_unaligned_from_prefix` panics if `T` is a zero-sized type.
+ #[inline(always)]
+ pub fn new_slice_unaligned_from_prefix(bytes: B, count: usize) -> Option<(Ref<B, [T]>, B)> {
+ Ref::new_slice_from_prefix(bytes, count)
+ }
+
+ /// Constructs a new `Ref` of a slice type with no alignment requirement
+ /// from the suffix of a byte slice.
+ ///
+ /// `new_slice_from_suffix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count`. It consumes the last `size_of::<T>() * count` bytes from `bytes`
+ /// to construct a `Ref`, and returns the remaining bytes to the caller. It
+ /// also ensures that `sizeof::<T>() * count` does not overflow a `usize`.
+ /// If either the length, or overflow checks fail, it returns `None`.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_unaligned_from_suffix` panics if `T` is a zero-sized type.
+ #[inline(always)]
+ pub fn new_slice_unaligned_from_suffix(bytes: B, count: usize) -> Option<(B, Ref<B, [T]>)> {
+ Ref::new_slice_from_suffix(bytes, count)
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSliceMut,
+ T: Unaligned,
+{
+ /// Constructs a new `Ref` for a type with no alignment requirement, zeroing
+ /// the bytes.
+ ///
+ /// `new_unaligned_zeroed` verifies that `bytes.len() == size_of::<T>()` and
+ /// constructs a new `Ref`. If the check fails, it returns `None`.
+ ///
+ /// If the check succeeds, then `bytes` will be initialized to zero. This
+ /// can be useful when re-using buffers to ensure that sensitive data
+ /// previously stored in the buffer is not leaked.
+ #[inline(always)]
+ pub fn new_unaligned_zeroed(bytes: B) -> Option<Ref<B, T>> {
+ map_zeroed(Self::new_unaligned(bytes))
+ }
+
+ /// Constructs a new `Ref` from the prefix of a byte slice for a type with
+ /// no alignment requirement, zeroing the prefix.
+ ///
+ /// `new_unaligned_from_prefix_zeroed` verifies that `bytes.len() >=
+ /// size_of::<T>()`. It consumes the first `size_of::<T>()` bytes from
+ /// `bytes` to construct a `Ref`, and returns the remaining bytes to the
+ /// caller. If the length check fails, it returns `None`.
+ ///
+ /// If the check succeeds, then the prefix which is consumed will be
+ /// initialized to zero. This can be useful when re-using buffers to ensure
+ /// that sensitive data previously stored in the buffer is not leaked.
+ #[inline(always)]
+ pub fn new_unaligned_from_prefix_zeroed(bytes: B) -> Option<(Ref<B, T>, B)> {
+ map_prefix_tuple_zeroed(Self::new_unaligned_from_prefix(bytes))
+ }
+
+ /// Constructs a new `Ref` from the suffix of a byte slice for a type with
+ /// no alignment requirement, zeroing the suffix.
+ ///
+ /// `new_unaligned_from_suffix_zeroed` verifies that `bytes.len() >=
+ /// size_of::<T>()`. It consumes the last `size_of::<T>()` bytes from
+ /// `bytes` to construct a `Ref`, and returns the preceding bytes to the
+ /// caller. If the length check fails, it returns `None`.
+ ///
+ /// If the check succeeds, then the suffix which is consumed will be
+ /// initialized to zero. This can be useful when re-using buffers to ensure
+ /// that sensitive data previously stored in the buffer is not leaked.
+ #[inline(always)]
+ pub fn new_unaligned_from_suffix_zeroed(bytes: B) -> Option<(B, Ref<B, T>)> {
+ map_suffix_tuple_zeroed(Self::new_unaligned_from_suffix(bytes))
+ }
+}
+
+impl<B, T> Ref<B, [T]>
+where
+ B: ByteSliceMut,
+ T: Unaligned,
+{
+ /// Constructs a new `Ref` for a slice type with no alignment requirement,
+ /// zeroing the bytes.
+ ///
+ /// `new_slice_unaligned_zeroed` verifies that `bytes.len()` is a multiple
+ /// of `size_of::<T>()` and constructs a new `Ref`. If the check fails, it
+ /// returns `None`.
+ ///
+ /// If the check succeeds, then `bytes` will be initialized to zero. This
+ /// can be useful when re-using buffers to ensure that sensitive data
+ /// previously stored in the buffer is not leaked.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice` panics if `T` is a zero-sized type.
+ #[inline(always)]
+ pub fn new_slice_unaligned_zeroed(bytes: B) -> Option<Ref<B, [T]>> {
+ map_zeroed(Self::new_slice_unaligned(bytes))
+ }
+
+ /// Constructs a new `Ref` of a slice type with no alignment requirement
+ /// from the prefix of a byte slice, after zeroing the bytes.
+ ///
+ /// `new_slice_from_prefix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count`. It consumes the first `size_of::<T>() * count` bytes from
+ /// `bytes` to construct a `Ref`, and returns the remaining bytes to the
+ /// caller. It also ensures that `sizeof::<T>() * count` does not overflow a
+ /// `usize`. If either the length, or overflow checks fail, it returns
+ /// `None`.
+ ///
+ /// If the checks succeed, then the prefix will be initialized to zero. This
+ /// can be useful when re-using buffers to ensure that sensitive data
+ /// previously stored in the buffer is not leaked.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_unaligned_from_prefix_zeroed` panics if `T` is a zero-sized
+ /// type.
+ #[inline(always)]
+ pub fn new_slice_unaligned_from_prefix_zeroed(
+ bytes: B,
+ count: usize,
+ ) -> Option<(Ref<B, [T]>, B)> {
+ map_prefix_tuple_zeroed(Self::new_slice_unaligned_from_prefix(bytes, count))
+ }
+
+ /// Constructs a new `Ref` of a slice type with no alignment requirement
+ /// from the suffix of a byte slice, after zeroing the bytes.
+ ///
+ /// `new_slice_from_suffix` verifies that `bytes.len() >= size_of::<T>() *
+ /// count`. It consumes the last `size_of::<T>() * count` bytes from `bytes`
+ /// to construct a `Ref`, and returns the remaining bytes to the caller. It
+ /// also ensures that `sizeof::<T>() * count` does not overflow a `usize`.
+ /// If either the length, or overflow checks fail, it returns `None`.
+ ///
+ /// If the checks succeed, then the suffix will be initialized to zero. This
+ /// can be useful when re-using buffers to ensure that sensitive data
+ /// previously stored in the buffer is not leaked.
+ ///
+ /// # Panics
+ ///
+ /// `new_slice_unaligned_from_suffix_zeroed` panics if `T` is a zero-sized
+ /// type.
+ #[inline(always)]
+ pub fn new_slice_unaligned_from_suffix_zeroed(
+ bytes: B,
+ count: usize,
+ ) -> Option<(B, Ref<B, [T]>)> {
+ map_suffix_tuple_zeroed(Self::new_slice_unaligned_from_suffix(bytes, count))
+ }
+}
+
+impl<'a, B, T> Ref<B, T>
+where
+ B: 'a + ByteSlice,
+ T: FromBytes,
+{
+ /// Converts this `Ref` into a reference.
+ ///
+ /// `into_ref` consumes the `Ref`, and returns a reference to `T`.
+ #[inline(always)]
+ pub fn into_ref(self) -> &'a T {
+ assert!(B::INTO_REF_INTO_MUT_ARE_SOUND);
+
+ // SAFETY: According to the safety preconditions on
+ // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
+ // ensures that, given `B: 'a`, it is sound to drop `self` and still
+ // access the underlying memory using reads for `'a`.
+ unsafe { self.deref_helper() }
+ }
+}
+
+impl<'a, B, T> Ref<B, T>
+where
+ B: 'a + ByteSliceMut,
+ T: FromBytes + AsBytes,
+{
+ /// Converts this `Ref` into a mutable reference.
+ ///
+ /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`.
+ #[inline(always)]
+ pub fn into_mut(mut self) -> &'a mut T {
+ assert!(B::INTO_REF_INTO_MUT_ARE_SOUND);
+
+ // SAFETY: According to the safety preconditions on
+ // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
+ // ensures that, given `B: 'a + ByteSliceMut`, it is sound to drop
+ // `self` and still access the underlying memory using both reads and
+ // writes for `'a`.
+ unsafe { self.deref_mut_helper() }
+ }
+}
+
+impl<'a, B, T> Ref<B, [T]>
+where
+ B: 'a + ByteSlice,
+ T: FromBytes,
+{
+ /// Converts this `Ref` into a slice reference.
+ ///
+ /// `into_slice` consumes the `Ref`, and returns a reference to `[T]`.
+ #[inline(always)]
+ pub fn into_slice(self) -> &'a [T] {
+ assert!(B::INTO_REF_INTO_MUT_ARE_SOUND);
+
+ // SAFETY: According to the safety preconditions on
+ // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
+ // ensures that, given `B: 'a`, it is sound to drop `self` and still
+ // access the underlying memory using reads for `'a`.
+ unsafe { self.deref_slice_helper() }
+ }
+}
+
+impl<'a, B, T> Ref<B, [T]>
+where
+ B: 'a + ByteSliceMut,
+ T: FromBytes + AsBytes,
+{
+ /// Converts this `Ref` into a mutable slice reference.
+ ///
+ /// `into_mut_slice` consumes the `Ref`, and returns a mutable reference to
+ /// `[T]`.
+ #[inline(always)]
+ pub fn into_mut_slice(mut self) -> &'a mut [T] {
+ assert!(B::INTO_REF_INTO_MUT_ARE_SOUND);
+
+ // SAFETY: According to the safety preconditions on
+ // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
+ // ensures that, given `B: 'a + ByteSliceMut`, it is sound to drop
+ // `self` and still access the underlying memory using both reads and
+ // writes for `'a`.
+ unsafe { self.deref_mut_slice_helper() }
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes,
+{
+ /// Creates an immutable reference to `T` with a specific lifetime.
+ ///
+ /// # Safety
+ ///
+ /// The type bounds on this method guarantee that it is safe to create an
+ /// immutable reference to `T` from `self`. However, since the lifetime `'a`
+ /// is not required to be shorter than the lifetime of the reference to
+ /// `self`, the caller must guarantee that the lifetime `'a` is valid for
+ /// this reference. In particular, the referent must exist for all of `'a`,
+ /// and no mutable references to the same memory may be constructed during
+ /// `'a`.
+ unsafe fn deref_helper<'a>(&self) -> &'a T {
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &*self.0.as_ptr().cast::<T>()
+ }
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSliceMut,
+ T: FromBytes + AsBytes,
+{
+ /// Creates a mutable reference to `T` with a specific lifetime.
+ ///
+ /// # Safety
+ ///
+ /// The type bounds on this method guarantee that it is safe to create a
+ /// mutable reference to `T` from `self`. However, since the lifetime `'a`
+ /// is not required to be shorter than the lifetime of the reference to
+ /// `self`, the caller must guarantee that the lifetime `'a` is valid for
+ /// this reference. In particular, the referent must exist for all of `'a`,
+ /// and no other references - mutable or immutable - to the same memory may
+ /// be constructed during `'a`.
+ unsafe fn deref_mut_helper<'a>(&mut self) -> &'a mut T {
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &mut *self.0.as_mut_ptr().cast::<T>()
+ }
+ }
+}
+
+impl<B, T> Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes,
+{
+ /// Creates an immutable reference to `[T]` with a specific lifetime.
+ ///
+ /// # Safety
+ ///
+ /// `deref_slice_helper` has the same safety requirements as `deref_helper`.
+ unsafe fn deref_slice_helper<'a>(&self) -> &'a [T] {
+ let len = self.0.len();
+ let elem_size = mem::size_of::<T>();
+ debug_assert_ne!(elem_size, 0);
+ // `Ref<_, [T]>` maintains the invariant that `size_of::<T>() > 0`.
+ // Thus, neither the mod nor division operations here can panic.
+ #[allow(clippy::arithmetic_side_effects)]
+ let elems = {
+ debug_assert_eq!(len % elem_size, 0);
+ len / elem_size
+ };
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ slice::from_raw_parts(self.0.as_ptr().cast::<T>(), elems)
+ }
+ }
+}
+
+impl<B, T> Ref<B, [T]>
+where
+ B: ByteSliceMut,
+ T: FromBytes + AsBytes,
+{
+ /// Creates a mutable reference to `[T]` with a specific lifetime.
+ ///
+ /// # Safety
+ ///
+ /// `deref_mut_slice_helper` has the same safety requirements as
+ /// `deref_mut_helper`.
+ unsafe fn deref_mut_slice_helper<'a>(&mut self) -> &'a mut [T] {
+ let len = self.0.len();
+ let elem_size = mem::size_of::<T>();
+ debug_assert_ne!(elem_size, 0);
+ // `Ref<_, [T]>` maintains the invariant that `size_of::<T>() > 0`.
+ // Thus, neither the mod nor division operations here can panic.
+ #[allow(clippy::arithmetic_side_effects)]
+ let elems = {
+ debug_assert_eq!(len % elem_size, 0);
+ len / elem_size
+ };
+ // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ slice::from_raw_parts_mut(self.0.as_mut_ptr().cast::<T>(), elems)
+ }
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSlice,
+ T: ?Sized,
+{
+ /// Gets the underlying bytes.
+ #[inline]
+ pub fn bytes(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSliceMut,
+ T: ?Sized,
+{
+ /// Gets the underlying bytes mutably.
+ #[inline]
+ pub fn bytes_mut(&mut self) -> &mut [u8] {
+ &mut self.0
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes,
+{
+ /// Reads a copy of `T`.
+ #[inline]
+ pub fn read(&self) -> T {
+ // SAFETY: Because of the invariants on `Ref`, we know that `self.0` is
+ // at least `size_of::<T>()` bytes long, and that it is at least as
+ // aligned as `align_of::<T>()`. Because `T: FromBytes`, it is sound to
+ // interpret these bytes as a `T`.
+ unsafe { ptr::read(self.0.as_ptr().cast::<T>()) }
+ }
+}
+
+impl<B, T> Ref<B, T>
+where
+ B: ByteSliceMut,
+ T: AsBytes,
+{
+ /// Writes the bytes of `t` and then forgets `t`.
+ #[inline]
+ pub fn write(&mut self, t: T) {
+ // SAFETY: Because of the invariants on `Ref`, we know that `self.0` is
+ // at least `size_of::<T>()` bytes long, and that it is at least as
+ // aligned as `align_of::<T>()`. Writing `t` to the buffer will allow
+ // all of the bytes of `t` to be accessed as a `[u8]`, but because `T:
+ // AsBytes`, we know this is sound.
+ unsafe { ptr::write(self.0.as_mut_ptr().cast::<T>(), t) }
+ }
+}
+
+impl<B, T> Deref for Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes,
+{
+ type Target = T;
+ #[inline]
+ fn deref(&self) -> &T {
+ // SAFETY: This is sound because the lifetime of `self` is the same as
+ // the lifetime of the return value, meaning that a) the returned
+ // reference cannot outlive `self` and, b) no mutable methods on `self`
+ // can be called during the lifetime of the returned reference. See the
+ // documentation on `deref_helper` for what invariants we are required
+ // to uphold.
+ unsafe { self.deref_helper() }
+ }
+}
+
+impl<B, T> DerefMut for Ref<B, T>
+where
+ B: ByteSliceMut,
+ T: FromBytes + AsBytes,
+{
+ #[inline]
+ fn deref_mut(&mut self) -> &mut T {
+ // SAFETY: This is sound because the lifetime of `self` is the same as
+ // the lifetime of the return value, meaning that a) the returned
+ // reference cannot outlive `self` and, b) no other methods on `self`
+ // can be called during the lifetime of the returned reference. See the
+ // documentation on `deref_mut_helper` for what invariants we are
+ // required to uphold.
+ unsafe { self.deref_mut_helper() }
+ }
+}
+
+impl<B, T> Deref for Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes,
+{
+ type Target = [T];
+ #[inline]
+ fn deref(&self) -> &[T] {
+ // SAFETY: This is sound because the lifetime of `self` is the same as
+ // the lifetime of the return value, meaning that a) the returned
+ // reference cannot outlive `self` and, b) no mutable methods on `self`
+ // can be called during the lifetime of the returned reference. See the
+ // documentation on `deref_slice_helper` for what invariants we are
+ // required to uphold.
+ unsafe { self.deref_slice_helper() }
+ }
+}
+
+impl<B, T> DerefMut for Ref<B, [T]>
+where
+ B: ByteSliceMut,
+ T: FromBytes + AsBytes,
+{
+ #[inline]
+ fn deref_mut(&mut self) -> &mut [T] {
+ // SAFETY: This is sound because the lifetime of `self` is the same as
+ // the lifetime of the return value, meaning that a) the returned
+ // reference cannot outlive `self` and, b) no other methods on `self`
+ // can be called during the lifetime of the returned reference. See the
+ // documentation on `deref_mut_slice_helper` for what invariants we are
+ // required to uphold.
+ unsafe { self.deref_mut_slice_helper() }
+ }
+}
+
+impl<T, B> Display for Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes + Display,
+{
+ #[inline]
+ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
+ let inner: &T = self;
+ inner.fmt(fmt)
+ }
+}
+
+impl<T, B> Display for Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes,
+ [T]: Display,
+{
+ #[inline]
+ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
+ let inner: &[T] = self;
+ inner.fmt(fmt)
+ }
+}
+
+impl<T, B> Debug for Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes + Debug,
+{
+ #[inline]
+ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
+ let inner: &T = self;
+ fmt.debug_tuple("Ref").field(&inner).finish()
+ }
+}
+
+impl<T, B> Debug for Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes + Debug,
+{
+ #[inline]
+ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
+ let inner: &[T] = self;
+ fmt.debug_tuple("Ref").field(&inner).finish()
+ }
+}
+
+impl<T, B> Eq for Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes + Eq,
+{
+}
+
+impl<T, B> Eq for Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes + Eq,
+{
+}
+
+impl<T, B> PartialEq for Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes + PartialEq,
+{
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.deref().eq(other.deref())
+ }
+}
+
+impl<T, B> PartialEq for Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes + PartialEq,
+{
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.deref().eq(other.deref())
+ }
+}
+
+impl<T, B> Ord for Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes + Ord,
+{
+ #[inline]
+ fn cmp(&self, other: &Self) -> Ordering {
+ let inner: &T = self;
+ let other_inner: &T = other;
+ inner.cmp(other_inner)
+ }
+}
+
+impl<T, B> Ord for Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes + Ord,
+{
+ #[inline]
+ fn cmp(&self, other: &Self) -> Ordering {
+ let inner: &[T] = self;
+ let other_inner: &[T] = other;
+ inner.cmp(other_inner)
+ }
+}
+
+impl<T, B> PartialOrd for Ref<B, T>
+where
+ B: ByteSlice,
+ T: FromBytes + PartialOrd,
+{
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ let inner: &T = self;
+ let other_inner: &T = other;
+ inner.partial_cmp(other_inner)
+ }
+}
+
+impl<T, B> PartialOrd for Ref<B, [T]>
+where
+ B: ByteSlice,
+ T: FromBytes + PartialOrd,
+{
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ let inner: &[T] = self;
+ let other_inner: &[T] = other;
+ inner.partial_cmp(other_inner)
+ }
+}
+
+mod sealed {
+ pub trait ByteSliceSealed {}
+}
+
+// ByteSlice and ByteSliceMut abstract over [u8] references (&[u8], &mut [u8],
+// Ref<[u8]>, RefMut<[u8]>, etc). We rely on various behaviors of these
+// references such as that a given reference will never changes its length
+// between calls to deref() or deref_mut(), and that split_at() works as
+// expected. If ByteSlice or ByteSliceMut were not sealed, consumers could
+// implement them in a way that violated these behaviors, and would break our
+// unsafe code. Thus, we seal them and implement it only for known-good
+// reference types. For the same reason, they're unsafe traits.
+
+#[allow(clippy::missing_safety_doc)] // TODO(fxbug.dev/99068)
+/// A mutable or immutable reference to a byte slice.
+///
+/// `ByteSlice` abstracts over the mutability of a byte slice reference, and is
+/// implemented for various special reference types such as `Ref<[u8]>` and
+/// `RefMut<[u8]>`.
+///
+/// Note that, while it would be technically possible, `ByteSlice` is not
+/// implemented for [`Vec<u8>`], as the only way to implement the [`split_at`]
+/// method would involve reallocation, and `split_at` must be a very cheap
+/// operation in order for the utilities in this crate to perform as designed.
+///
+/// [`split_at`]: crate::ByteSlice::split_at
+// It may seem overkill to go to this length to ensure that this doc link never
+// breaks. We do this because it simplifies CI - it means that generating docs
+// always succeeds, so we don't need special logic to only generate docs under
+// certain features.
+#[cfg_attr(feature = "alloc", doc = "[`Vec<u8>`]: alloc::vec::Vec")]
+#[cfg_attr(
+ not(feature = "alloc"),
+ doc = "[`Vec<u8>`]: https://doc.rust-lang.org/std/vec/struct.Vec.html"
+)]
+pub unsafe trait ByteSlice:
+ Deref<Target = [u8]> + Sized + self::sealed::ByteSliceSealed
+{
+ /// Are the [`Ref::into_ref`] and [`Ref::into_mut`] methods sound when used
+ /// with `Self`? If not, evaluating this constant must panic at compile
+ /// time.
+ ///
+ /// This exists to work around #716 on versions of zerocopy prior to 0.8.
+ ///
+ /// # Safety
+ ///
+ /// This may only be set to true if the following holds: Given the
+ /// following:
+ /// - `Self: 'a`
+ /// - `bytes: Self`
+ /// - `let ptr = bytes.as_ptr()`
+ ///
+ /// ...then:
+ /// - Using `ptr` to read the memory previously addressed by `bytes` is
+ /// sound for `'a` even after `bytes` has been dropped.
+ /// - If `Self: ByteSliceMut`, using `ptr` to write the memory previously
+ /// addressed by `bytes` is sound for `'a` even after `bytes` has been
+ /// dropped.
+ #[doc(hidden)]
+ const INTO_REF_INTO_MUT_ARE_SOUND: bool;
+
+ /// Gets a raw pointer to the first byte in the slice.
+ #[inline]
+ fn as_ptr(&self) -> *const u8 {
+ <[u8]>::as_ptr(self)
+ }
+
+ /// Splits the slice at the midpoint.
+ ///
+ /// `x.split_at(mid)` returns `x[..mid]` and `x[mid..]`.
+ ///
+ /// # Panics
+ ///
+ /// `x.split_at(mid)` panics if `mid > x.len()`.
+ fn split_at(self, mid: usize) -> (Self, Self);
+}
+
+#[allow(clippy::missing_safety_doc)] // TODO(fxbug.dev/99068)
+/// A mutable reference to a byte slice.
+///
+/// `ByteSliceMut` abstracts over various ways of storing a mutable reference to
+/// a byte slice, and is implemented for various special reference types such as
+/// `RefMut<[u8]>`.
+pub unsafe trait ByteSliceMut: ByteSlice + DerefMut {
+ /// Gets a mutable raw pointer to the first byte in the slice.
+ #[inline]
+ fn as_mut_ptr(&mut self) -> *mut u8 {
+ <[u8]>::as_mut_ptr(self)
+ }
+}
+
+impl<'a> sealed::ByteSliceSealed for &'a [u8] {}
+// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<'a> ByteSlice for &'a [u8] {
+ // SAFETY: If `&'b [u8]: 'a`, then the underlying memory is treated as
+ // borrowed immutably for `'a` even if the slice itself is dropped.
+ const INTO_REF_INTO_MUT_ARE_SOUND: bool = true;
+
+ #[inline]
+ fn split_at(self, mid: usize) -> (Self, Self) {
+ <[u8]>::split_at(self, mid)
+ }
+}
+
+impl<'a> sealed::ByteSliceSealed for &'a mut [u8] {}
+// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<'a> ByteSlice for &'a mut [u8] {
+ // SAFETY: If `&'b mut [u8]: 'a`, then the underlying memory is treated as
+ // borrowed mutably for `'a` even if the slice itself is dropped.
+ const INTO_REF_INTO_MUT_ARE_SOUND: bool = true;
+
+ #[inline]
+ fn split_at(self, mid: usize) -> (Self, Self) {
+ <[u8]>::split_at_mut(self, mid)
+ }
+}
+
+impl<'a> sealed::ByteSliceSealed for cell::Ref<'a, [u8]> {}
+// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<'a> ByteSlice for cell::Ref<'a, [u8]> {
+ const INTO_REF_INTO_MUT_ARE_SOUND: bool = if !cfg!(doc) {
+ panic!("Ref::into_ref and Ref::into_mut are unsound when used with core::cell::Ref; see https://github.com/google/zerocopy/issues/716")
+ } else {
+ // When compiling documentation, allow the evaluation of this constant
+ // to succeed. This doesn't represent a soundness hole - it just delays
+ // any error to runtime. The reason we need this is that, otherwise,
+ // `rustdoc` will fail when trying to document this item.
+ false
+ };
+
+ #[inline]
+ fn split_at(self, mid: usize) -> (Self, Self) {
+ cell::Ref::map_split(self, |slice| <[u8]>::split_at(slice, mid))
+ }
+}
+
+impl<'a> sealed::ByteSliceSealed for RefMut<'a, [u8]> {}
+// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<'a> ByteSlice for RefMut<'a, [u8]> {
+ const INTO_REF_INTO_MUT_ARE_SOUND: bool = if !cfg!(doc) {
+ panic!("Ref::into_ref and Ref::into_mut are unsound when used with core::cell::RefMut; see https://github.com/google/zerocopy/issues/716")
+ } else {
+ // When compiling documentation, allow the evaluation of this constant
+ // to succeed. This doesn't represent a soundness hole - it just delays
+ // any error to runtime. The reason we need this is that, otherwise,
+ // `rustdoc` will fail when trying to document this item.
+ false
+ };
+
+ #[inline]
+ fn split_at(self, mid: usize) -> (Self, Self) {
+ RefMut::map_split(self, |slice| <[u8]>::split_at_mut(slice, mid))
+ }
+}
+
+// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<'a> ByteSliceMut for &'a mut [u8] {}
+
+// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<'a> ByteSliceMut for RefMut<'a, [u8]> {}
+
+#[cfg(feature = "alloc")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
+mod alloc_support {
+ use alloc::vec::Vec;
+
+ use super::*;
+
+ /// Extends a `Vec<T>` by pushing `additional` new items onto the end of the
+ /// vector. The new items are initialized with zeroes.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `Vec::reserve(additional)` fails to reserve enough memory.
+ #[inline(always)]
+ pub fn extend_vec_zeroed<T: FromZeroes>(v: &mut Vec<T>, additional: usize) {
+ insert_vec_zeroed(v, v.len(), additional);
+ }
+
+ /// Inserts `additional` new items into `Vec<T>` at `position`.
+ /// The new items are initialized with zeroes.
+ ///
+ /// # Panics
+ ///
+ /// * Panics if `position > v.len()`.
+ /// * Panics if `Vec::reserve(additional)` fails to reserve enough memory.
+ #[inline]
+ pub fn insert_vec_zeroed<T: FromZeroes>(v: &mut Vec<T>, position: usize, additional: usize) {
+ assert!(position <= v.len());
+ v.reserve(additional);
+ // SAFETY: The `reserve` call guarantees that these cannot overflow:
+ // * `ptr.add(position)`
+ // * `position + additional`
+ // * `v.len() + additional`
+ //
+ // `v.len() - position` cannot overflow because we asserted that
+ // `position <= v.len()`.
+ unsafe {
+ // This is a potentially overlapping copy.
+ let ptr = v.as_mut_ptr();
+ #[allow(clippy::arithmetic_side_effects)]
+ ptr.add(position).copy_to(ptr.add(position + additional), v.len() - position);
+ ptr.add(position).write_bytes(0, additional);
+ #[allow(clippy::arithmetic_side_effects)]
+ v.set_len(v.len() + additional);
+ }
+ }
+
+ #[cfg(test)]
+ mod tests {
+ use core::convert::TryFrom as _;
+
+ use super::*;
+
+ #[test]
+ fn test_extend_vec_zeroed() {
+ // Test extending when there is an existing allocation.
+ let mut v = vec![100u64, 200, 300];
+ extend_vec_zeroed(&mut v, 3);
+ assert_eq!(v.len(), 6);
+ assert_eq!(&*v, &[100, 200, 300, 0, 0, 0]);
+ drop(v);
+
+ // Test extending when there is no existing allocation.
+ let mut v: Vec<u64> = Vec::new();
+ extend_vec_zeroed(&mut v, 3);
+ assert_eq!(v.len(), 3);
+ assert_eq!(&*v, &[0, 0, 0]);
+ drop(v);
+ }
+
+ #[test]
+ fn test_extend_vec_zeroed_zst() {
+ // Test extending when there is an existing (fake) allocation.
+ let mut v = vec![(), (), ()];
+ extend_vec_zeroed(&mut v, 3);
+ assert_eq!(v.len(), 6);
+ assert_eq!(&*v, &[(), (), (), (), (), ()]);
+ drop(v);
+
+ // Test extending when there is no existing (fake) allocation.
+ let mut v: Vec<()> = Vec::new();
+ extend_vec_zeroed(&mut v, 3);
+ assert_eq!(&*v, &[(), (), ()]);
+ drop(v);
+ }
+
+ #[test]
+ fn test_insert_vec_zeroed() {
+ // Insert at start (no existing allocation).
+ let mut v: Vec<u64> = Vec::new();
+ insert_vec_zeroed(&mut v, 0, 2);
+ assert_eq!(v.len(), 2);
+ assert_eq!(&*v, &[0, 0]);
+ drop(v);
+
+ // Insert at start.
+ let mut v = vec![100u64, 200, 300];
+ insert_vec_zeroed(&mut v, 0, 2);
+ assert_eq!(v.len(), 5);
+ assert_eq!(&*v, &[0, 0, 100, 200, 300]);
+ drop(v);
+
+ // Insert at middle.
+ let mut v = vec![100u64, 200, 300];
+ insert_vec_zeroed(&mut v, 1, 1);
+ assert_eq!(v.len(), 4);
+ assert_eq!(&*v, &[100, 0, 200, 300]);
+ drop(v);
+
+ // Insert at end.
+ let mut v = vec![100u64, 200, 300];
+ insert_vec_zeroed(&mut v, 3, 1);
+ assert_eq!(v.len(), 4);
+ assert_eq!(&*v, &[100, 200, 300, 0]);
+ drop(v);
+ }
+
+ #[test]
+ fn test_insert_vec_zeroed_zst() {
+ // Insert at start (no existing fake allocation).
+ let mut v: Vec<()> = Vec::new();
+ insert_vec_zeroed(&mut v, 0, 2);
+ assert_eq!(v.len(), 2);
+ assert_eq!(&*v, &[(), ()]);
+ drop(v);
+
+ // Insert at start.
+ let mut v = vec![(), (), ()];
+ insert_vec_zeroed(&mut v, 0, 2);
+ assert_eq!(v.len(), 5);
+ assert_eq!(&*v, &[(), (), (), (), ()]);
+ drop(v);
+
+ // Insert at middle.
+ let mut v = vec![(), (), ()];
+ insert_vec_zeroed(&mut v, 1, 1);
+ assert_eq!(v.len(), 4);
+ assert_eq!(&*v, &[(), (), (), ()]);
+ drop(v);
+
+ // Insert at end.
+ let mut v = vec![(), (), ()];
+ insert_vec_zeroed(&mut v, 3, 1);
+ assert_eq!(v.len(), 4);
+ assert_eq!(&*v, &[(), (), (), ()]);
+ drop(v);
+ }
+
+ #[test]
+ fn test_new_box_zeroed() {
+ assert_eq!(*u64::new_box_zeroed(), 0);
+ }
+
+ #[test]
+ fn test_new_box_zeroed_array() {
+ drop(<[u32; 0x1000]>::new_box_zeroed());
+ }
+
+ #[test]
+ fn test_new_box_zeroed_zst() {
+ // This test exists in order to exercise unsafe code, especially
+ // when running under Miri.
+ #[allow(clippy::unit_cmp)]
+ {
+ assert_eq!(*<()>::new_box_zeroed(), ());
+ }
+ }
+
+ #[test]
+ fn test_new_box_slice_zeroed() {
+ let mut s: Box<[u64]> = u64::new_box_slice_zeroed(3);
+ assert_eq!(s.len(), 3);
+ assert_eq!(&*s, &[0, 0, 0]);
+ s[1] = 3;
+ assert_eq!(&*s, &[0, 3, 0]);
+ }
+
+ #[test]
+ fn test_new_box_slice_zeroed_empty() {
+ let s: Box<[u64]> = u64::new_box_slice_zeroed(0);
+ assert_eq!(s.len(), 0);
+ }
+
+ #[test]
+ fn test_new_box_slice_zeroed_zst() {
+ let mut s: Box<[()]> = <()>::new_box_slice_zeroed(3);
+ assert_eq!(s.len(), 3);
+ assert!(s.get(10).is_none());
+ // This test exists in order to exercise unsafe code, especially
+ // when running under Miri.
+ #[allow(clippy::unit_cmp)]
+ {
+ assert_eq!(s[1], ());
+ }
+ s[2] = ();
+ }
+
+ #[test]
+ fn test_new_box_slice_zeroed_zst_empty() {
+ let s: Box<[()]> = <()>::new_box_slice_zeroed(0);
+ assert_eq!(s.len(), 0);
+ }
+
+ #[test]
+ #[should_panic(expected = "mem::size_of::<Self>() * len overflows `usize`")]
+ fn test_new_box_slice_zeroed_panics_mul_overflow() {
+ let _ = u16::new_box_slice_zeroed(usize::MAX);
+ }
+
+ #[test]
+ #[should_panic(expected = "assertion failed: size <= max_alloc")]
+ fn test_new_box_slice_zeroed_panics_isize_overflow() {
+ let max = usize::try_from(isize::MAX).unwrap();
+ let _ = u16::new_box_slice_zeroed((max / mem::size_of::<u16>()) + 1);
+ }
+ }
+}
+
+#[cfg(feature = "alloc")]
+#[doc(inline)]
+pub use alloc_support::*;
+
+#[cfg(test)]
+mod tests {
+ #![allow(clippy::unreadable_literal)]
+
+ use core::{cell::UnsafeCell, convert::TryInto as _, ops::Deref};
+
+ use static_assertions::assert_impl_all;
+
+ use super::*;
+ use crate::util::testutil::*;
+
+ // An unsized type.
+ //
+ // This is used to test the custom derives of our traits. The `[u8]` type
+ // gets a hand-rolled impl, so it doesn't exercise our custom derives.
+ #[derive(Debug, Eq, PartialEq, FromZeroes, FromBytes, AsBytes, Unaligned)]
+ #[repr(transparent)]
+ struct Unsized([u8]);
+
+ impl Unsized {
+ fn from_mut_slice(slc: &mut [u8]) -> &mut Unsized {
+ // SAFETY: This *probably* sound - since the layouts of `[u8]` and
+ // `Unsized` are the same, so are the layouts of `&mut [u8]` and
+ // `&mut Unsized`. [1] Even if it turns out that this isn't actually
+ // guaranteed by the language spec, we can just change this since
+ // it's in test code.
+ //
+ // [1] https://github.com/rust-lang/unsafe-code-guidelines/issues/375
+ unsafe { mem::transmute(slc) }
+ }
+ }
+
+ /// Tests of when a sized `DstLayout` is extended with a sized field.
+ #[allow(clippy::decimal_literal_representation)]
+ #[test]
+ fn test_dst_layout_extend_sized_with_sized() {
+ // This macro constructs a layout corresponding to a `u8` and extends it
+ // with a zero-sized trailing field of given alignment `n`. The macro
+ // tests that the resulting layout has both size and alignment `min(n,
+ // P)` for all valid values of `repr(packed(P))`.
+ macro_rules! test_align_is_size {
+ ($n:expr) => {
+ let base = DstLayout::for_type::<u8>();
+ let trailing_field = DstLayout::for_type::<elain::Align<$n>>();
+
+ let packs =
+ core::iter::once(None).chain((0..29).map(|p| NonZeroUsize::new(2usize.pow(p))));
+
+ for pack in packs {
+ let composite = base.extend(trailing_field, pack);
+ let max_align = pack.unwrap_or(DstLayout::CURRENT_MAX_ALIGN);
+ let align = $n.min(max_align.get());
+ assert_eq!(
+ composite,
+ DstLayout {
+ align: NonZeroUsize::new(align).unwrap(),
+ size_info: SizeInfo::Sized { _size: align }
+ }
+ )
+ }
+ };
+ }
+
+ test_align_is_size!(1);
+ test_align_is_size!(2);
+ test_align_is_size!(4);
+ test_align_is_size!(8);
+ test_align_is_size!(16);
+ test_align_is_size!(32);
+ test_align_is_size!(64);
+ test_align_is_size!(128);
+ test_align_is_size!(256);
+ test_align_is_size!(512);
+ test_align_is_size!(1024);
+ test_align_is_size!(2048);
+ test_align_is_size!(4096);
+ test_align_is_size!(8192);
+ test_align_is_size!(16384);
+ test_align_is_size!(32768);
+ test_align_is_size!(65536);
+ test_align_is_size!(131072);
+ test_align_is_size!(262144);
+ test_align_is_size!(524288);
+ test_align_is_size!(1048576);
+ test_align_is_size!(2097152);
+ test_align_is_size!(4194304);
+ test_align_is_size!(8388608);
+ test_align_is_size!(16777216);
+ test_align_is_size!(33554432);
+ test_align_is_size!(67108864);
+ test_align_is_size!(33554432);
+ test_align_is_size!(134217728);
+ test_align_is_size!(268435456);
+ }
+
+ /// Tests of when a sized `DstLayout` is extended with a DST field.
+ #[test]
+ fn test_dst_layout_extend_sized_with_dst() {
+ // Test that for all combinations of real-world alignments and
+ // `repr_packed` values, that the extension of a sized `DstLayout`` with
+ // a DST field correctly computes the trailing offset in the composite
+ // layout.
+
+ let aligns = (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap());
+ let packs = core::iter::once(None).chain(aligns.clone().map(Some));
+
+ for align in aligns {
+ for pack in packs.clone() {
+ let base = DstLayout::for_type::<u8>();
+ let elem_size = 42;
+ let trailing_field_offset = 11;
+
+ let trailing_field = DstLayout {
+ align,
+ size_info: SizeInfo::SliceDst(TrailingSliceLayout {
+ _elem_size: elem_size,
+ _offset: 11,
+ }),
+ };
+
+ let composite = base.extend(trailing_field, pack);
+
+ let max_align = pack.unwrap_or(DstLayout::CURRENT_MAX_ALIGN).get();
+
+ let align = align.get().min(max_align);
+
+ assert_eq!(
+ composite,
+ DstLayout {
+ align: NonZeroUsize::new(align).unwrap(),
+ size_info: SizeInfo::SliceDst(TrailingSliceLayout {
+ _elem_size: elem_size,
+ _offset: align + trailing_field_offset,
+ }),
+ }
+ )
+ }
+ }
+ }
+
+ /// Tests that calling `pad_to_align` on a sized `DstLayout` adds the
+ /// expected amount of trailing padding.
+ #[test]
+ fn test_dst_layout_pad_to_align_with_sized() {
+ // For all valid alignments `align`, construct a one-byte layout aligned
+ // to `align`, call `pad_to_align`, and assert that the size of the
+ // resulting layout is equal to `align`.
+ for align in (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()) {
+ let layout = DstLayout { align, size_info: SizeInfo::Sized { _size: 1 } };
+
+ assert_eq!(
+ layout.pad_to_align(),
+ DstLayout { align, size_info: SizeInfo::Sized { _size: align.get() } }
+ );
+ }
+
+ // Test explicitly-provided combinations of unpadded and padded
+ // counterparts.
+
+ macro_rules! test {
+ (unpadded { size: $unpadded_size:expr, align: $unpadded_align:expr }
+ => padded { size: $padded_size:expr, align: $padded_align:expr }) => {
+ let unpadded = DstLayout {
+ align: NonZeroUsize::new($unpadded_align).unwrap(),
+ size_info: SizeInfo::Sized { _size: $unpadded_size },
+ };
+ let padded = unpadded.pad_to_align();
+
+ assert_eq!(
+ padded,
+ DstLayout {
+ align: NonZeroUsize::new($padded_align).unwrap(),
+ size_info: SizeInfo::Sized { _size: $padded_size },
+ }
+ );
+ };
+ }
+
+ test!(unpadded { size: 0, align: 4 } => padded { size: 0, align: 4 });
+ test!(unpadded { size: 1, align: 4 } => padded { size: 4, align: 4 });
+ test!(unpadded { size: 2, align: 4 } => padded { size: 4, align: 4 });
+ test!(unpadded { size: 3, align: 4 } => padded { size: 4, align: 4 });
+ test!(unpadded { size: 4, align: 4 } => padded { size: 4, align: 4 });
+ test!(unpadded { size: 5, align: 4 } => padded { size: 8, align: 4 });
+ test!(unpadded { size: 6, align: 4 } => padded { size: 8, align: 4 });
+ test!(unpadded { size: 7, align: 4 } => padded { size: 8, align: 4 });
+ test!(unpadded { size: 8, align: 4 } => padded { size: 8, align: 4 });
+
+ let current_max_align = DstLayout::CURRENT_MAX_ALIGN.get();
+
+ test!(unpadded { size: 1, align: current_max_align }
+ => padded { size: current_max_align, align: current_max_align });
+
+ test!(unpadded { size: current_max_align + 1, align: current_max_align }
+ => padded { size: current_max_align * 2, align: current_max_align });
+ }
+
+ /// Tests that calling `pad_to_align` on a DST `DstLayout` is a no-op.
+ #[test]
+ fn test_dst_layout_pad_to_align_with_dst() {
+ for align in (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()) {
+ for offset in 0..10 {
+ for elem_size in 0..10 {
+ let layout = DstLayout {
+ align,
+ size_info: SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: offset,
+ _elem_size: elem_size,
+ }),
+ };
+ assert_eq!(layout.pad_to_align(), layout);
+ }
+ }
+ }
+ }
+
+ // This test takes a long time when running under Miri, so we skip it in
+ // that case. This is acceptable because this is a logic test that doesn't
+ // attempt to expose UB.
+ #[test]
+ #[cfg_attr(miri, ignore)]
+ fn testvalidate_cast_and_convert_metadata() {
+ impl From<usize> for SizeInfo {
+ fn from(_size: usize) -> SizeInfo {
+ SizeInfo::Sized { _size }
+ }
+ }
+
+ impl From<(usize, usize)> for SizeInfo {
+ fn from((_offset, _elem_size): (usize, usize)) -> SizeInfo {
+ SizeInfo::SliceDst(TrailingSliceLayout { _offset, _elem_size })
+ }
+ }
+
+ fn layout<S: Into<SizeInfo>>(s: S, align: usize) -> DstLayout {
+ DstLayout { size_info: s.into(), align: NonZeroUsize::new(align).unwrap() }
+ }
+
+ /// This macro accepts arguments in the form of:
+ ///
+ /// layout(_, _, _).validate(_, _, _), Ok(Some((_, _)))
+ /// | | | | | | | |
+ /// base_size ----+ | | | | | | |
+ /// align -----------+ | | | | | |
+ /// trailing_size ------+ | | | | |
+ /// addr ---------------------------+ | | | |
+ /// bytes_len -------------------------+ | | |
+ /// cast_type ----------------------------+ | |
+ /// elems ---------------------------------------------+ |
+ /// split_at ---------------------------------------------+
+ ///
+ /// `.validate` is shorthand for `.validate_cast_and_convert_metadata`
+ /// for brevity.
+ ///
+ /// Each argument can either be an iterator or a wildcard. Each
+ /// wildcarded variable is implicitly replaced by an iterator over a
+ /// representative sample of values for that variable. Each `test!`
+ /// invocation iterates over every combination of values provided by
+ /// each variable's iterator (ie, the cartesian product) and validates
+ /// that the results are expected.
+ ///
+ /// The final argument uses the same syntax, but it has a different
+ /// meaning:
+ /// - If it is `Ok(pat)`, then the pattern `pat` is supplied to
+ /// `assert_matches!` to validate the computed result for each
+ /// combination of input values.
+ /// - If it is `Err(msg)`, then `test!` validates that the call to
+ /// `validate_cast_and_convert_metadata` panics with the given panic
+ /// message.
+ ///
+ /// Note that the meta-variables that match these variables have the
+ /// `tt` type, and some valid expressions are not valid `tt`s (such as
+ /// `a..b`). In this case, wrap the expression in parentheses, and it
+ /// will become valid `tt`.
+ macro_rules! test {
+ ($(:$sizes:expr =>)?
+ layout($size:tt, $align:tt)
+ .validate($addr:tt, $bytes_len:tt, $cast_type:tt), $expect:pat $(,)?
+ ) => {
+ itertools::iproduct!(
+ test!(@generate_size $size),
+ test!(@generate_align $align),
+ test!(@generate_usize $addr),
+ test!(@generate_usize $bytes_len),
+ test!(@generate_cast_type $cast_type)
+ ).for_each(|(size_info, align, addr, bytes_len, cast_type)| {
+ // Temporarily disable the panic hook installed by the test
+ // harness. If we don't do this, all panic messages will be
+ // kept in an internal log. On its own, this isn't a
+ // problem, but if a non-caught panic ever happens (ie, in
+ // code later in this test not in this macro), all of the
+ // previously-buffered messages will be dumped, hiding the
+ // real culprit.
+ let previous_hook = std::panic::take_hook();
+ // I don't understand why, but this seems to be required in
+ // addition to the previous line.
+ std::panic::set_hook(Box::new(|_| {}));
+ let actual = std::panic::catch_unwind(|| {
+ layout(size_info, align).validate_cast_and_convert_metadata(addr, bytes_len, cast_type)
+ }).map_err(|d| {
+ *d.downcast::<&'static str>().expect("expected string panic message").as_ref()
+ });
+ std::panic::set_hook(previous_hook);
+
+ assert_matches::assert_matches!(
+ actual, $expect,
+ "layout({size_info:?}, {align}).validate_cast_and_convert_metadata({addr}, {bytes_len}, {cast_type:?})",
+ );
+ });
+ };
+ (@generate_usize _) => { 0..8 };
+ // Generate sizes for both Sized and !Sized types.
+ (@generate_size _) => {
+ test!(@generate_size (_)).chain(test!(@generate_size (_, _)))
+ };
+ // Generate sizes for both Sized and !Sized types by chaining
+ // specified iterators for each.
+ (@generate_size ($sized_sizes:tt | $unsized_sizes:tt)) => {
+ test!(@generate_size ($sized_sizes)).chain(test!(@generate_size $unsized_sizes))
+ };
+ // Generate sizes for Sized types.
+ (@generate_size (_)) => { test!(@generate_size (0..8)) };
+ (@generate_size ($sizes:expr)) => { $sizes.into_iter().map(Into::<SizeInfo>::into) };
+ // Generate sizes for !Sized types.
+ (@generate_size ($min_sizes:tt, $elem_sizes:tt)) => {
+ itertools::iproduct!(
+ test!(@generate_min_size $min_sizes),
+ test!(@generate_elem_size $elem_sizes)
+ ).map(Into::<SizeInfo>::into)
+ };
+ (@generate_fixed_size _) => { (0..8).into_iter().map(Into::<SizeInfo>::into) };
+ (@generate_min_size _) => { 0..8 };
+ (@generate_elem_size _) => { 1..8 };
+ (@generate_align _) => { [1, 2, 4, 8, 16] };
+ (@generate_opt_usize _) => { [None].into_iter().chain((0..8).map(Some).into_iter()) };
+ (@generate_cast_type _) => { [_CastType::_Prefix, _CastType::_Suffix] };
+ (@generate_cast_type $variant:ident) => { [_CastType::$variant] };
+ // Some expressions need to be wrapped in parentheses in order to be
+ // valid `tt`s (required by the top match pattern). See the comment
+ // below for more details. This arm removes these parentheses to
+ // avoid generating an `unused_parens` warning.
+ (@$_:ident ($vals:expr)) => { $vals };
+ (@$_:ident $vals:expr) => { $vals };
+ }
+
+ const EVENS: [usize; 8] = [0, 2, 4, 6, 8, 10, 12, 14];
+ const ODDS: [usize; 8] = [1, 3, 5, 7, 9, 11, 13, 15];
+
+ // base_size is too big for the memory region.
+ test!(layout(((1..8) | ((1..8), (1..8))), _).validate(_, [0], _), Ok(None));
+ test!(layout(((2..8) | ((2..8), (2..8))), _).validate(_, [1], _), Ok(None));
+
+ // addr is unaligned for prefix cast
+ test!(layout(_, [2]).validate(ODDS, _, _Prefix), Ok(None));
+ test!(layout(_, [2]).validate(ODDS, _, _Prefix), Ok(None));
+
+ // addr is aligned, but end of buffer is unaligned for suffix cast
+ test!(layout(_, [2]).validate(EVENS, ODDS, _Suffix), Ok(None));
+ test!(layout(_, [2]).validate(EVENS, ODDS, _Suffix), Ok(None));
+
+ // Unfortunately, these constants cannot easily be used in the
+ // implementation of `validate_cast_and_convert_metadata`, since
+ // `panic!` consumes a string literal, not an expression.
+ //
+ // It's important that these messages be in a separate module. If they
+ // were at the function's top level, we'd pass them to `test!` as, e.g.,
+ // `Err(TRAILING)`, which would run into a subtle Rust footgun - the
+ // `TRAILING` identifier would be treated as a pattern to match rather
+ // than a value to check for equality.
+ mod msgs {
+ pub(super) const TRAILING: &str =
+ "attempted to cast to slice type with zero-sized element";
+ pub(super) const OVERFLOW: &str = "`addr` + `bytes_len` > usize::MAX";
+ }
+
+ // casts with ZST trailing element types are unsupported
+ test!(layout((_, [0]), _).validate(_, _, _), Err(msgs::TRAILING),);
+
+ // addr + bytes_len must not overflow usize
+ test!(layout(_, _).validate([usize::MAX], (1..100), _), Err(msgs::OVERFLOW));
+ test!(layout(_, _).validate((1..100), [usize::MAX], _), Err(msgs::OVERFLOW));
+ test!(
+ layout(_, _).validate(
+ [usize::MAX / 2 + 1, usize::MAX],
+ [usize::MAX / 2 + 1, usize::MAX],
+ _
+ ),
+ Err(msgs::OVERFLOW)
+ );
+
+ // Validates that `validate_cast_and_convert_metadata` satisfies its own
+ // documented safety postconditions, and also a few other properties
+ // that aren't documented but we want to guarantee anyway.
+ fn validate_behavior(
+ (layout, addr, bytes_len, cast_type): (DstLayout, usize, usize, _CastType),
+ ) {
+ if let Some((elems, split_at)) =
+ layout.validate_cast_and_convert_metadata(addr, bytes_len, cast_type)
+ {
+ let (size_info, align) = (layout.size_info, layout.align);
+ let debug_str = format!(
+ "layout({size_info:?}, {align}).validate_cast_and_convert_metadata({addr}, {bytes_len}, {cast_type:?}) => ({elems}, {split_at})",
+ );
+
+ // If this is a sized type (no trailing slice), then `elems` is
+ // meaningless, but in practice we set it to 0. Callers are not
+ // allowed to rely on this, but a lot of math is nicer if
+ // they're able to, and some callers might accidentally do that.
+ let sized = matches!(layout.size_info, SizeInfo::Sized { .. });
+ assert!(!(sized && elems != 0), "{}", debug_str);
+
+ let resulting_size = match layout.size_info {
+ SizeInfo::Sized { _size } => _size,
+ SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: offset,
+ _elem_size: elem_size,
+ }) => {
+ let padded_size = |elems| {
+ let without_padding = offset + elems * elem_size;
+ without_padding
+ + util::core_layout::padding_needed_for(without_padding, align)
+ };
+
+ let resulting_size = padded_size(elems);
+ // Test that `validate_cast_and_convert_metadata`
+ // computed the largest possible value that fits in the
+ // given range.
+ assert!(padded_size(elems + 1) > bytes_len, "{}", debug_str);
+ resulting_size
+ }
+ };
+
+ // Test safety postconditions guaranteed by
+ // `validate_cast_and_convert_metadata`.
+ assert!(resulting_size <= bytes_len, "{}", debug_str);
+ match cast_type {
+ _CastType::_Prefix => {
+ assert_eq!(addr % align, 0, "{}", debug_str);
+ assert_eq!(resulting_size, split_at, "{}", debug_str);
+ }
+ _CastType::_Suffix => {
+ assert_eq!(split_at, bytes_len - resulting_size, "{}", debug_str);
+ assert_eq!((addr + split_at) % align, 0, "{}", debug_str);
+ }
+ }
+ } else {
+ let min_size = match layout.size_info {
+ SizeInfo::Sized { _size } => _size,
+ SizeInfo::SliceDst(TrailingSliceLayout { _offset, .. }) => {
+ _offset + util::core_layout::padding_needed_for(_offset, layout.align)
+ }
+ };
+
+ // If a cast is invalid, it is either because...
+ // 1. there are insufficent bytes at the given region for type:
+ let insufficient_bytes = bytes_len < min_size;
+ // 2. performing the cast would misalign type:
+ let base = match cast_type {
+ _CastType::_Prefix => 0,
+ _CastType::_Suffix => bytes_len,
+ };
+ let misaligned = (base + addr) % layout.align != 0;
+
+ assert!(insufficient_bytes || misaligned);
+ }
+ }
+
+ let sizes = 0..8;
+ let elem_sizes = 1..8;
+ let size_infos = sizes
+ .clone()
+ .map(Into::<SizeInfo>::into)
+ .chain(itertools::iproduct!(sizes, elem_sizes).map(Into::<SizeInfo>::into));
+ let layouts = itertools::iproduct!(size_infos, [1, 2, 4, 8, 16, 32])
+ .filter(|(size_info, align)| !matches!(size_info, SizeInfo::Sized { _size } if _size % align != 0))
+ .map(|(size_info, align)| layout(size_info, align));
+ itertools::iproduct!(layouts, 0..8, 0..8, [_CastType::_Prefix, _CastType::_Suffix])
+ .for_each(validate_behavior);
+ }
+
+ #[test]
+ #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+ fn test_validate_rust_layout() {
+ use core::ptr::NonNull;
+
+ // This test synthesizes pointers with various metadata and uses Rust's
+ // built-in APIs to confirm that Rust makes decisions about type layout
+ // which are consistent with what we believe is guaranteed by the
+ // language. If this test fails, it doesn't just mean our code is wrong
+ // - it means we're misunderstanding the language's guarantees.
+
+ #[derive(Debug)]
+ struct MacroArgs {
+ offset: usize,
+ align: NonZeroUsize,
+ elem_size: Option<usize>,
+ }
+
+ /// # Safety
+ ///
+ /// `test` promises to only call `addr_of_slice_field` on a `NonNull<T>`
+ /// which points to a valid `T`.
+ ///
+ /// `with_elems` must produce a pointer which points to a valid `T`.
+ fn test<T: ?Sized, W: Fn(usize) -> NonNull<T>>(
+ args: MacroArgs,
+ with_elems: W,
+ addr_of_slice_field: Option<fn(NonNull<T>) -> NonNull<u8>>,
+ ) {
+ let dst = args.elem_size.is_some();
+ let layout = {
+ let size_info = match args.elem_size {
+ Some(elem_size) => SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: args.offset,
+ _elem_size: elem_size,
+ }),
+ None => SizeInfo::Sized {
+ // Rust only supports types whose sizes are a multiple
+ // of their alignment. If the macro created a type like
+ // this:
+ //
+ // #[repr(C, align(2))]
+ // struct Foo([u8; 1]);
+ //
+ // ...then Rust will automatically round the type's size
+ // up to 2.
+ _size: args.offset
+ + util::core_layout::padding_needed_for(args.offset, args.align),
+ },
+ };
+ DstLayout { size_info, align: args.align }
+ };
+
+ for elems in 0..128 {
+ let ptr = with_elems(elems);
+
+ if let Some(addr_of_slice_field) = addr_of_slice_field {
+ let slc_field_ptr = addr_of_slice_field(ptr).as_ptr();
+ // SAFETY: Both `slc_field_ptr` and `ptr` are pointers to
+ // the same valid Rust object.
+ let offset: usize =
+ unsafe { slc_field_ptr.byte_offset_from(ptr.as_ptr()).try_into().unwrap() };
+ assert_eq!(offset, args.offset);
+ }
+
+ // SAFETY: `ptr` points to a valid `T`.
+ let (size, align) = unsafe {
+ (mem::size_of_val_raw(ptr.as_ptr()), mem::align_of_val_raw(ptr.as_ptr()))
+ };
+
+ // Avoid expensive allocation when running under Miri.
+ let assert_msg = if !cfg!(miri) {
+ format!("\n{args:?}\nsize:{size}, align:{align}")
+ } else {
+ String::new()
+ };
+
+ let without_padding =
+ args.offset + args.elem_size.map(|elem_size| elems * elem_size).unwrap_or(0);
+ assert!(size >= without_padding, "{}", assert_msg);
+ assert_eq!(align, args.align.get(), "{}", assert_msg);
+
+ // This encodes the most important part of the test: our
+ // understanding of how Rust determines the layout of repr(C)
+ // types. Sized repr(C) types are trivial, but DST types have
+ // some subtlety. Note that:
+ // - For sized types, `without_padding` is just the size of the
+ // type that we constructed for `Foo`. Since we may have
+ // requested a larger alignment, `Foo` may actually be larger
+ // than this, hence `padding_needed_for`.
+ // - For unsized types, `without_padding` is dynamically
+ // computed from the offset, the element size, and element
+ // count. We expect that the size of the object should be
+ // `offset + elem_size * elems` rounded up to the next
+ // alignment.
+ let expected_size = without_padding
+ + util::core_layout::padding_needed_for(without_padding, args.align);
+ assert_eq!(expected_size, size, "{}", assert_msg);
+
+ // For zero-sized element types,
+ // `validate_cast_and_convert_metadata` just panics, so we skip
+ // testing those types.
+ if args.elem_size.map(|elem_size| elem_size > 0).unwrap_or(true) {
+ let addr = ptr.addr().get();
+ let (got_elems, got_split_at) = layout
+ .validate_cast_and_convert_metadata(addr, size, _CastType::_Prefix)
+ .unwrap();
+ // Avoid expensive allocation when running under Miri.
+ let assert_msg = if !cfg!(miri) {
+ format!(
+ "{}\nvalidate_cast_and_convert_metadata({addr}, {size})",
+ assert_msg
+ )
+ } else {
+ String::new()
+ };
+ assert_eq!(got_split_at, size, "{}", assert_msg);
+ if dst {
+ assert!(got_elems >= elems, "{}", assert_msg);
+ if got_elems != elems {
+ // If `validate_cast_and_convert_metadata`
+ // returned more elements than `elems`, that
+ // means that `elems` is not the maximum number
+ // of elements that can fit in `size` - in other
+ // words, there is enough padding at the end of
+ // the value to fit at least one more element.
+ // If we use this metadata to synthesize a
+ // pointer, despite having a different element
+ // count, we still expect it to have the same
+ // size.
+ let got_ptr = with_elems(got_elems);
+ // SAFETY: `got_ptr` is a pointer to a valid `T`.
+ let size_of_got_ptr = unsafe { mem::size_of_val_raw(got_ptr.as_ptr()) };
+ assert_eq!(size_of_got_ptr, size, "{}", assert_msg);
+ }
+ } else {
+ // For sized casts, the returned element value is
+ // technically meaningless, and we don't guarantee any
+ // particular value. In practice, it's always zero.
+ assert_eq!(got_elems, 0, "{}", assert_msg)
+ }
+ }
+ }
+ }
+
+ macro_rules! validate_against_rust {
+ ($offset:literal, $align:literal $(, $elem_size:literal)?) => {{
+ #[repr(C, align($align))]
+ struct Foo([u8; $offset]$(, [[u8; $elem_size]])?);
+
+ let args = MacroArgs {
+ offset: $offset,
+ align: $align.try_into().unwrap(),
+ elem_size: {
+ #[allow(unused)]
+ let ret = None::<usize>;
+ $(let ret = Some($elem_size);)?
+ ret
+ }
+ };
+
+ #[repr(C, align($align))]
+ struct FooAlign;
+ // Create an aligned buffer to use in order to synthesize
+ // pointers to `Foo`. We don't ever load values from these
+ // pointers - we just do arithmetic on them - so having a "real"
+ // block of memory as opposed to a validly-aligned-but-dangling
+ // pointer is only necessary to make Miri happy since we run it
+ // with "strict provenance" checking enabled.
+ let aligned_buf = Align::<_, FooAlign>::new([0u8; 1024]);
+ let with_elems = |elems| {
+ let slc = NonNull::slice_from_raw_parts(NonNull::from(&aligned_buf.t), elems);
+ #[allow(clippy::as_conversions)]
+ NonNull::new(slc.as_ptr() as *mut Foo).unwrap()
+ };
+ let addr_of_slice_field = {
+ #[allow(unused)]
+ let f = None::<fn(NonNull<Foo>) -> NonNull<u8>>;
+ $(
+ // SAFETY: `test` promises to only call `f` with a `ptr`
+ // to a valid `Foo`.
+ let f: Option<fn(NonNull<Foo>) -> NonNull<u8>> = Some(|ptr: NonNull<Foo>| unsafe {
+ NonNull::new(ptr::addr_of_mut!((*ptr.as_ptr()).1)).unwrap().cast::<u8>()
+ });
+ let _ = $elem_size;
+ )?
+ f
+ };
+
+ test::<Foo, _>(args, with_elems, addr_of_slice_field);
+ }};
+ }
+
+ // Every permutation of:
+ // - offset in [0, 4]
+ // - align in [1, 16]
+ // - elem_size in [0, 4] (plus no elem_size)
+ validate_against_rust!(0, 1);
+ validate_against_rust!(0, 1, 0);
+ validate_against_rust!(0, 1, 1);
+ validate_against_rust!(0, 1, 2);
+ validate_against_rust!(0, 1, 3);
+ validate_against_rust!(0, 1, 4);
+ validate_against_rust!(0, 2);
+ validate_against_rust!(0, 2, 0);
+ validate_against_rust!(0, 2, 1);
+ validate_against_rust!(0, 2, 2);
+ validate_against_rust!(0, 2, 3);
+ validate_against_rust!(0, 2, 4);
+ validate_against_rust!(0, 4);
+ validate_against_rust!(0, 4, 0);
+ validate_against_rust!(0, 4, 1);
+ validate_against_rust!(0, 4, 2);
+ validate_against_rust!(0, 4, 3);
+ validate_against_rust!(0, 4, 4);
+ validate_against_rust!(0, 8);
+ validate_against_rust!(0, 8, 0);
+ validate_against_rust!(0, 8, 1);
+ validate_against_rust!(0, 8, 2);
+ validate_against_rust!(0, 8, 3);
+ validate_against_rust!(0, 8, 4);
+ validate_against_rust!(0, 16);
+ validate_against_rust!(0, 16, 0);
+ validate_against_rust!(0, 16, 1);
+ validate_against_rust!(0, 16, 2);
+ validate_against_rust!(0, 16, 3);
+ validate_against_rust!(0, 16, 4);
+ validate_against_rust!(1, 1);
+ validate_against_rust!(1, 1, 0);
+ validate_against_rust!(1, 1, 1);
+ validate_against_rust!(1, 1, 2);
+ validate_against_rust!(1, 1, 3);
+ validate_against_rust!(1, 1, 4);
+ validate_against_rust!(1, 2);
+ validate_against_rust!(1, 2, 0);
+ validate_against_rust!(1, 2, 1);
+ validate_against_rust!(1, 2, 2);
+ validate_against_rust!(1, 2, 3);
+ validate_against_rust!(1, 2, 4);
+ validate_against_rust!(1, 4);
+ validate_against_rust!(1, 4, 0);
+ validate_against_rust!(1, 4, 1);
+ validate_against_rust!(1, 4, 2);
+ validate_against_rust!(1, 4, 3);
+ validate_against_rust!(1, 4, 4);
+ validate_against_rust!(1, 8);
+ validate_against_rust!(1, 8, 0);
+ validate_against_rust!(1, 8, 1);
+ validate_against_rust!(1, 8, 2);
+ validate_against_rust!(1, 8, 3);
+ validate_against_rust!(1, 8, 4);
+ validate_against_rust!(1, 16);
+ validate_against_rust!(1, 16, 0);
+ validate_against_rust!(1, 16, 1);
+ validate_against_rust!(1, 16, 2);
+ validate_against_rust!(1, 16, 3);
+ validate_against_rust!(1, 16, 4);
+ validate_against_rust!(2, 1);
+ validate_against_rust!(2, 1, 0);
+ validate_against_rust!(2, 1, 1);
+ validate_against_rust!(2, 1, 2);
+ validate_against_rust!(2, 1, 3);
+ validate_against_rust!(2, 1, 4);
+ validate_against_rust!(2, 2);
+ validate_against_rust!(2, 2, 0);
+ validate_against_rust!(2, 2, 1);
+ validate_against_rust!(2, 2, 2);
+ validate_against_rust!(2, 2, 3);
+ validate_against_rust!(2, 2, 4);
+ validate_against_rust!(2, 4);
+ validate_against_rust!(2, 4, 0);
+ validate_against_rust!(2, 4, 1);
+ validate_against_rust!(2, 4, 2);
+ validate_against_rust!(2, 4, 3);
+ validate_against_rust!(2, 4, 4);
+ validate_against_rust!(2, 8);
+ validate_against_rust!(2, 8, 0);
+ validate_against_rust!(2, 8, 1);
+ validate_against_rust!(2, 8, 2);
+ validate_against_rust!(2, 8, 3);
+ validate_against_rust!(2, 8, 4);
+ validate_against_rust!(2, 16);
+ validate_against_rust!(2, 16, 0);
+ validate_against_rust!(2, 16, 1);
+ validate_against_rust!(2, 16, 2);
+ validate_against_rust!(2, 16, 3);
+ validate_against_rust!(2, 16, 4);
+ validate_against_rust!(3, 1);
+ validate_against_rust!(3, 1, 0);
+ validate_against_rust!(3, 1, 1);
+ validate_against_rust!(3, 1, 2);
+ validate_against_rust!(3, 1, 3);
+ validate_against_rust!(3, 1, 4);
+ validate_against_rust!(3, 2);
+ validate_against_rust!(3, 2, 0);
+ validate_against_rust!(3, 2, 1);
+ validate_against_rust!(3, 2, 2);
+ validate_against_rust!(3, 2, 3);
+ validate_against_rust!(3, 2, 4);
+ validate_against_rust!(3, 4);
+ validate_against_rust!(3, 4, 0);
+ validate_against_rust!(3, 4, 1);
+ validate_against_rust!(3, 4, 2);
+ validate_against_rust!(3, 4, 3);
+ validate_against_rust!(3, 4, 4);
+ validate_against_rust!(3, 8);
+ validate_against_rust!(3, 8, 0);
+ validate_against_rust!(3, 8, 1);
+ validate_against_rust!(3, 8, 2);
+ validate_against_rust!(3, 8, 3);
+ validate_against_rust!(3, 8, 4);
+ validate_against_rust!(3, 16);
+ validate_against_rust!(3, 16, 0);
+ validate_against_rust!(3, 16, 1);
+ validate_against_rust!(3, 16, 2);
+ validate_against_rust!(3, 16, 3);
+ validate_against_rust!(3, 16, 4);
+ validate_against_rust!(4, 1);
+ validate_against_rust!(4, 1, 0);
+ validate_against_rust!(4, 1, 1);
+ validate_against_rust!(4, 1, 2);
+ validate_against_rust!(4, 1, 3);
+ validate_against_rust!(4, 1, 4);
+ validate_against_rust!(4, 2);
+ validate_against_rust!(4, 2, 0);
+ validate_against_rust!(4, 2, 1);
+ validate_against_rust!(4, 2, 2);
+ validate_against_rust!(4, 2, 3);
+ validate_against_rust!(4, 2, 4);
+ validate_against_rust!(4, 4);
+ validate_against_rust!(4, 4, 0);
+ validate_against_rust!(4, 4, 1);
+ validate_against_rust!(4, 4, 2);
+ validate_against_rust!(4, 4, 3);
+ validate_against_rust!(4, 4, 4);
+ validate_against_rust!(4, 8);
+ validate_against_rust!(4, 8, 0);
+ validate_against_rust!(4, 8, 1);
+ validate_against_rust!(4, 8, 2);
+ validate_against_rust!(4, 8, 3);
+ validate_against_rust!(4, 8, 4);
+ validate_against_rust!(4, 16);
+ validate_against_rust!(4, 16, 0);
+ validate_against_rust!(4, 16, 1);
+ validate_against_rust!(4, 16, 2);
+ validate_against_rust!(4, 16, 3);
+ validate_against_rust!(4, 16, 4);
+ }
+
+ #[test]
+ fn test_known_layout() {
+ // Test that `$ty` and `ManuallyDrop<$ty>` have the expected layout.
+ // Test that `PhantomData<$ty>` has the same layout as `()` regardless
+ // of `$ty`.
+ macro_rules! test {
+ ($ty:ty, $expect:expr) => {
+ let expect = $expect;
+ assert_eq!(<$ty as KnownLayout>::LAYOUT, expect);
+ assert_eq!(<ManuallyDrop<$ty> as KnownLayout>::LAYOUT, expect);
+ assert_eq!(<PhantomData<$ty> as KnownLayout>::LAYOUT, <() as KnownLayout>::LAYOUT);
+ };
+ }
+
+ let layout = |offset, align, _trailing_slice_elem_size| DstLayout {
+ align: NonZeroUsize::new(align).unwrap(),
+ size_info: match _trailing_slice_elem_size {
+ None => SizeInfo::Sized { _size: offset },
+ Some(elem_size) => SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: offset,
+ _elem_size: elem_size,
+ }),
+ },
+ };
+
+ test!((), layout(0, 1, None));
+ test!(u8, layout(1, 1, None));
+ // Use `align_of` because `u64` alignment may be smaller than 8 on some
+ // platforms.
+ test!(u64, layout(8, mem::align_of::<u64>(), None));
+ test!(AU64, layout(8, 8, None));
+
+ test!(Option<&'static ()>, usize::LAYOUT);
+
+ test!([()], layout(0, 1, Some(0)));
+ test!([u8], layout(0, 1, Some(1)));
+ test!(str, layout(0, 1, Some(1)));
+ }
+
+ #[cfg(feature = "derive")]
+ #[test]
+ fn test_known_layout_derive() {
+ // In this and other files (`late_compile_pass.rs`,
+ // `mid_compile_pass.rs`, and `struct.rs`), we test success and failure
+ // modes of `derive(KnownLayout)` for the following combination of
+ // properties:
+ //
+ // +------------+--------------------------------------+-----------+
+ // | | trailing field properties | |
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // |------------+----------+----------------+----------+-----------|
+ // | N | N | N | N | KL00 |
+ // | N | N | N | Y | KL01 |
+ // | N | N | Y | N | KL02 |
+ // | N | N | Y | Y | KL03 |
+ // | N | Y | N | N | KL04 |
+ // | N | Y | N | Y | KL05 |
+ // | N | Y | Y | N | KL06 |
+ // | N | Y | Y | Y | KL07 |
+ // | Y | N | N | N | KL08 |
+ // | Y | N | N | Y | KL09 |
+ // | Y | N | Y | N | KL10 |
+ // | Y | N | Y | Y | KL11 |
+ // | Y | Y | N | N | KL12 |
+ // | Y | Y | N | Y | KL13 |
+ // | Y | Y | Y | N | KL14 |
+ // | Y | Y | Y | Y | KL15 |
+ // +------------+----------+----------------+----------+-----------+
+
+ struct NotKnownLayout<T = ()> {
+ _t: T,
+ }
+
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct AlignSize<const ALIGN: usize, const SIZE: usize>
+ where
+ elain::Align<ALIGN>: elain::Alignment,
+ {
+ _align: elain::Align<ALIGN>,
+ _size: [u8; SIZE],
+ }
+
+ type AU16 = AlignSize<2, 2>;
+ type AU32 = AlignSize<4, 4>;
+
+ fn _assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+
+ let sized_layout = |align, size| DstLayout {
+ align: NonZeroUsize::new(align).unwrap(),
+ size_info: SizeInfo::Sized { _size: size },
+ };
+
+ let unsized_layout = |align, elem_size, offset| DstLayout {
+ align: NonZeroUsize::new(align).unwrap(),
+ size_info: SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: offset,
+ _elem_size: elem_size,
+ }),
+ };
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | N | N | N | Y | KL01 |
+ #[derive(KnownLayout)]
+ struct KL01(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
+
+ let expected = DstLayout::for_type::<KL01>();
+
+ assert_eq!(<KL01 as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL01 as KnownLayout>::LAYOUT, sized_layout(4, 8));
+
+ // ...with `align(N)`:
+ #[derive(KnownLayout)]
+ #[repr(align(64))]
+ struct KL01Align(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
+
+ let expected = DstLayout::for_type::<KL01Align>();
+
+ assert_eq!(<KL01Align as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL01Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
+
+ // ...with `packed`:
+ #[derive(KnownLayout)]
+ #[repr(packed)]
+ struct KL01Packed(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
+
+ let expected = DstLayout::for_type::<KL01Packed>();
+
+ assert_eq!(<KL01Packed as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL01Packed as KnownLayout>::LAYOUT, sized_layout(1, 6));
+
+ // ...with `packed(N)`:
+ #[derive(KnownLayout)]
+ #[repr(packed(2))]
+ struct KL01PackedN(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
+
+ assert_impl_all!(KL01PackedN: KnownLayout);
+
+ let expected = DstLayout::for_type::<KL01PackedN>();
+
+ assert_eq!(<KL01PackedN as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL01PackedN as KnownLayout>::LAYOUT, sized_layout(2, 6));
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | N | N | Y | Y | KL03 |
+ #[derive(KnownLayout)]
+ struct KL03(NotKnownLayout, u8);
+
+ let expected = DstLayout::for_type::<KL03>();
+
+ assert_eq!(<KL03 as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL03 as KnownLayout>::LAYOUT, sized_layout(1, 1));
+
+ // ... with `align(N)`
+ #[derive(KnownLayout)]
+ #[repr(align(64))]
+ struct KL03Align(NotKnownLayout<AU32>, u8);
+
+ let expected = DstLayout::for_type::<KL03Align>();
+
+ assert_eq!(<KL03Align as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL03Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
+
+ // ... with `packed`:
+ #[derive(KnownLayout)]
+ #[repr(packed)]
+ struct KL03Packed(NotKnownLayout<AU32>, u8);
+
+ let expected = DstLayout::for_type::<KL03Packed>();
+
+ assert_eq!(<KL03Packed as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL03Packed as KnownLayout>::LAYOUT, sized_layout(1, 5));
+
+ // ... with `packed(N)`
+ #[derive(KnownLayout)]
+ #[repr(packed(2))]
+ struct KL03PackedN(NotKnownLayout<AU32>, u8);
+
+ assert_impl_all!(KL03PackedN: KnownLayout);
+
+ let expected = DstLayout::for_type::<KL03PackedN>();
+
+ assert_eq!(<KL03PackedN as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL03PackedN as KnownLayout>::LAYOUT, sized_layout(2, 6));
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | N | Y | N | Y | KL05 |
+ #[derive(KnownLayout)]
+ struct KL05<T>(u8, T);
+
+ fn _test_kl05<T>(t: T) -> impl KnownLayout {
+ KL05(0u8, t)
+ }
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | N | Y | Y | Y | KL07 |
+ #[derive(KnownLayout)]
+ struct KL07<T: KnownLayout>(u8, T);
+
+ fn _test_kl07<T: KnownLayout>(t: T) -> impl KnownLayout {
+ let _ = KL07(0u8, t);
+ }
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | Y | N | Y | N | KL10 |
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KL10(NotKnownLayout<AU32>, [u8]);
+
+ let expected = DstLayout::new_zst(None)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), None)
+ .extend(<[u8] as KnownLayout>::LAYOUT, None)
+ .pad_to_align();
+
+ assert_eq!(<KL10 as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL10 as KnownLayout>::LAYOUT, unsized_layout(4, 1, 4));
+
+ // ...with `align(N)`:
+ #[derive(KnownLayout)]
+ #[repr(C, align(64))]
+ struct KL10Align(NotKnownLayout<AU32>, [u8]);
+
+ let repr_align = NonZeroUsize::new(64);
+
+ let expected = DstLayout::new_zst(repr_align)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), None)
+ .extend(<[u8] as KnownLayout>::LAYOUT, None)
+ .pad_to_align();
+
+ assert_eq!(<KL10Align as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL10Align as KnownLayout>::LAYOUT, unsized_layout(64, 1, 4));
+
+ // ...with `packed`:
+ #[derive(KnownLayout)]
+ #[repr(C, packed)]
+ struct KL10Packed(NotKnownLayout<AU32>, [u8]);
+
+ let repr_packed = NonZeroUsize::new(1);
+
+ let expected = DstLayout::new_zst(None)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), repr_packed)
+ .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed)
+ .pad_to_align();
+
+ assert_eq!(<KL10Packed as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL10Packed as KnownLayout>::LAYOUT, unsized_layout(1, 1, 4));
+
+ // ...with `packed(N)`:
+ #[derive(KnownLayout)]
+ #[repr(C, packed(2))]
+ struct KL10PackedN(NotKnownLayout<AU32>, [u8]);
+
+ let repr_packed = NonZeroUsize::new(2);
+
+ let expected = DstLayout::new_zst(None)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), repr_packed)
+ .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed)
+ .pad_to_align();
+
+ assert_eq!(<KL10PackedN as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL10PackedN as KnownLayout>::LAYOUT, unsized_layout(2, 1, 4));
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | Y | N | Y | Y | KL11 |
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KL11(NotKnownLayout<AU64>, u8);
+
+ let expected = DstLayout::new_zst(None)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), None)
+ .extend(<u8 as KnownLayout>::LAYOUT, None)
+ .pad_to_align();
+
+ assert_eq!(<KL11 as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL11 as KnownLayout>::LAYOUT, sized_layout(8, 16));
+
+ // ...with `align(N)`:
+ #[derive(KnownLayout)]
+ #[repr(C, align(64))]
+ struct KL11Align(NotKnownLayout<AU64>, u8);
+
+ let repr_align = NonZeroUsize::new(64);
+
+ let expected = DstLayout::new_zst(repr_align)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), None)
+ .extend(<u8 as KnownLayout>::LAYOUT, None)
+ .pad_to_align();
+
+ assert_eq!(<KL11Align as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL11Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
+
+ // ...with `packed`:
+ #[derive(KnownLayout)]
+ #[repr(C, packed)]
+ struct KL11Packed(NotKnownLayout<AU64>, u8);
+
+ let repr_packed = NonZeroUsize::new(1);
+
+ let expected = DstLayout::new_zst(None)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), repr_packed)
+ .extend(<u8 as KnownLayout>::LAYOUT, repr_packed)
+ .pad_to_align();
+
+ assert_eq!(<KL11Packed as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL11Packed as KnownLayout>::LAYOUT, sized_layout(1, 9));
+
+ // ...with `packed(N)`:
+ #[derive(KnownLayout)]
+ #[repr(C, packed(2))]
+ struct KL11PackedN(NotKnownLayout<AU64>, u8);
+
+ let repr_packed = NonZeroUsize::new(2);
+
+ let expected = DstLayout::new_zst(None)
+ .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), repr_packed)
+ .extend(<u8 as KnownLayout>::LAYOUT, repr_packed)
+ .pad_to_align();
+
+ assert_eq!(<KL11PackedN as KnownLayout>::LAYOUT, expected);
+ assert_eq!(<KL11PackedN as KnownLayout>::LAYOUT, sized_layout(2, 10));
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | Y | Y | Y | N | KL14 |
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KL14<T: ?Sized + KnownLayout>(u8, T);
+
+ fn _test_kl14<T: ?Sized + KnownLayout>(kl: &KL14<T>) {
+ _assert_kl(kl)
+ }
+
+ // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+ // | Y | Y | Y | Y | KL15 |
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KL15<T: KnownLayout>(u8, T);
+
+ fn _test_kl15<T: KnownLayout>(t: T) -> impl KnownLayout {
+ let _ = KL15(0u8, t);
+ }
+
+ // Test a variety of combinations of field types:
+ // - ()
+ // - u8
+ // - AU16
+ // - [()]
+ // - [u8]
+ // - [AU16]
+
+ #[allow(clippy::upper_case_acronyms)]
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KLTU<T, U: ?Sized>(T, U);
+
+ assert_eq!(<KLTU<(), ()> as KnownLayout>::LAYOUT, sized_layout(1, 0));
+
+ assert_eq!(<KLTU<(), u8> as KnownLayout>::LAYOUT, sized_layout(1, 1));
+
+ assert_eq!(<KLTU<(), AU16> as KnownLayout>::LAYOUT, sized_layout(2, 2));
+
+ assert_eq!(<KLTU<(), [()]> as KnownLayout>::LAYOUT, unsized_layout(1, 0, 0));
+
+ assert_eq!(<KLTU<(), [u8]> as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0));
+
+ assert_eq!(<KLTU<(), [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 0));
+
+ assert_eq!(<KLTU<u8, ()> as KnownLayout>::LAYOUT, sized_layout(1, 1));
+
+ assert_eq!(<KLTU<u8, u8> as KnownLayout>::LAYOUT, sized_layout(1, 2));
+
+ assert_eq!(<KLTU<u8, AU16> as KnownLayout>::LAYOUT, sized_layout(2, 4));
+
+ assert_eq!(<KLTU<u8, [()]> as KnownLayout>::LAYOUT, unsized_layout(1, 0, 1));
+
+ assert_eq!(<KLTU<u8, [u8]> as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1));
+
+ assert_eq!(<KLTU<u8, [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2));
+
+ assert_eq!(<KLTU<AU16, ()> as KnownLayout>::LAYOUT, sized_layout(2, 2));
+
+ assert_eq!(<KLTU<AU16, u8> as KnownLayout>::LAYOUT, sized_layout(2, 4));
+
+ assert_eq!(<KLTU<AU16, AU16> as KnownLayout>::LAYOUT, sized_layout(2, 4));
+
+ assert_eq!(<KLTU<AU16, [()]> as KnownLayout>::LAYOUT, unsized_layout(2, 0, 2));
+
+ assert_eq!(<KLTU<AU16, [u8]> as KnownLayout>::LAYOUT, unsized_layout(2, 1, 2));
+
+ assert_eq!(<KLTU<AU16, [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2));
+
+ // Test a variety of field counts.
+
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KLF0;
+
+ assert_eq!(<KLF0 as KnownLayout>::LAYOUT, sized_layout(1, 0));
+
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KLF1([u8]);
+
+ assert_eq!(<KLF1 as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0));
+
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KLF2(NotKnownLayout<u8>, [u8]);
+
+ assert_eq!(<KLF2 as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1));
+
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KLF3(NotKnownLayout<u8>, NotKnownLayout<AU16>, [u8]);
+
+ assert_eq!(<KLF3 as KnownLayout>::LAYOUT, unsized_layout(2, 1, 4));
+
+ #[derive(KnownLayout)]
+ #[repr(C)]
+ struct KLF4(NotKnownLayout<u8>, NotKnownLayout<AU16>, NotKnownLayout<AU32>, [u8]);
+
+ assert_eq!(<KLF4 as KnownLayout>::LAYOUT, unsized_layout(4, 1, 8));
+ }
+
+ #[test]
+ fn test_object_safety() {
+ fn _takes_from_zeroes(_: &dyn FromZeroes) {}
+ fn _takes_from_bytes(_: &dyn FromBytes) {}
+ fn _takes_unaligned(_: &dyn Unaligned) {}
+ }
+
+ #[test]
+ fn test_from_zeroes_only() {
+ // Test types that implement `FromZeroes` but not `FromBytes`.
+
+ assert!(!bool::new_zeroed());
+ assert_eq!(char::new_zeroed(), '\0');
+
+ #[cfg(feature = "alloc")]
+ {
+ assert_eq!(bool::new_box_zeroed(), Box::new(false));
+ assert_eq!(char::new_box_zeroed(), Box::new('\0'));
+
+ assert_eq!(bool::new_box_slice_zeroed(3).as_ref(), [false, false, false]);
+ assert_eq!(char::new_box_slice_zeroed(3).as_ref(), ['\0', '\0', '\0']);
+
+ assert_eq!(bool::new_vec_zeroed(3).as_ref(), [false, false, false]);
+ assert_eq!(char::new_vec_zeroed(3).as_ref(), ['\0', '\0', '\0']);
+ }
+
+ let mut string = "hello".to_string();
+ let s: &mut str = string.as_mut();
+ assert_eq!(s, "hello");
+ s.zero();
+ assert_eq!(s, "\0\0\0\0\0");
+ }
+
+ #[test]
+ fn test_read_write() {
+ const VAL: u64 = 0x12345678;
+ #[cfg(target_endian = "big")]
+ const VAL_BYTES: [u8; 8] = VAL.to_be_bytes();
+ #[cfg(target_endian = "little")]
+ const VAL_BYTES: [u8; 8] = VAL.to_le_bytes();
+
+ // Test `FromBytes::{read_from, read_from_prefix, read_from_suffix}`.
+
+ assert_eq!(u64::read_from(&VAL_BYTES[..]), Some(VAL));
+ // The first 8 bytes are from `VAL_BYTES` and the second 8 bytes are all
+ // zeroes.
+ let bytes_with_prefix: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
+ assert_eq!(u64::read_from_prefix(&bytes_with_prefix[..]), Some(VAL));
+ assert_eq!(u64::read_from_suffix(&bytes_with_prefix[..]), Some(0));
+ // The first 8 bytes are all zeroes and the second 8 bytes are from
+ // `VAL_BYTES`
+ let bytes_with_suffix: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
+ assert_eq!(u64::read_from_prefix(&bytes_with_suffix[..]), Some(0));
+ assert_eq!(u64::read_from_suffix(&bytes_with_suffix[..]), Some(VAL));
+
+ // Test `AsBytes::{write_to, write_to_prefix, write_to_suffix}`.
+
+ let mut bytes = [0u8; 8];
+ assert_eq!(VAL.write_to(&mut bytes[..]), Some(()));
+ assert_eq!(bytes, VAL_BYTES);
+ let mut bytes = [0u8; 16];
+ assert_eq!(VAL.write_to_prefix(&mut bytes[..]), Some(()));
+ let want: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
+ assert_eq!(bytes, want);
+ let mut bytes = [0u8; 16];
+ assert_eq!(VAL.write_to_suffix(&mut bytes[..]), Some(()));
+ let want: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
+ assert_eq!(bytes, want);
+ }
+
+ #[test]
+ fn test_transmute() {
+ // Test that memory is transmuted as expected.
+ let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
+ let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
+ let x: [[u8; 2]; 4] = transmute!(array_of_u8s);
+ assert_eq!(x, array_of_arrays);
+ let x: [u8; 8] = transmute!(array_of_arrays);
+ assert_eq!(x, array_of_u8s);
+
+ // Test that the source expression's value is forgotten rather than
+ // dropped.
+ #[derive(AsBytes)]
+ #[repr(transparent)]
+ struct PanicOnDrop(());
+ impl Drop for PanicOnDrop {
+ fn drop(&mut self) {
+ panic!("PanicOnDrop::drop");
+ }
+ }
+ #[allow(clippy::let_unit_value)]
+ let _: () = transmute!(PanicOnDrop(()));
+
+ // Test that `transmute!` is legal in a const context.
+ const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
+ const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
+ const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S);
+ assert_eq!(X, ARRAY_OF_ARRAYS);
+ }
+
+ #[test]
+ fn test_transmute_ref() {
+ // Test that memory is transmuted as expected.
+ let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
+ let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
+ let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s);
+ assert_eq!(*x, array_of_arrays);
+ let x: &[u8; 8] = transmute_ref!(&array_of_arrays);
+ assert_eq!(*x, array_of_u8s);
+
+ // Test that `transmute_ref!` is legal in a const context.
+ const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
+ const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
+ #[allow(clippy::redundant_static_lifetimes)]
+ const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S);
+ assert_eq!(*X, ARRAY_OF_ARRAYS);
+
+ // Test that it's legal to transmute a reference while shrinking the
+ // lifetime (note that `X` has the lifetime `'static`).
+ let x: &[u8; 8] = transmute_ref!(X);
+ assert_eq!(*x, ARRAY_OF_U8S);
+
+ // Test that `transmute_ref!` supports decreasing alignment.
+ let u = AU64(0);
+ let array = [0, 0, 0, 0, 0, 0, 0, 0];
+ let x: &[u8; 8] = transmute_ref!(&u);
+ assert_eq!(*x, array);
+
+ // Test that a mutable reference can be turned into an immutable one.
+ let mut x = 0u8;
+ #[allow(clippy::useless_transmute)]
+ let y: &u8 = transmute_ref!(&mut x);
+ assert_eq!(*y, 0);
+ }
+
+ #[test]
+ fn test_transmute_mut() {
+ // Test that memory is transmuted as expected.
+ let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
+ let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
+ let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s);
+ assert_eq!(*x, array_of_arrays);
+ let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
+ assert_eq!(*x, array_of_u8s);
+
+ {
+ // Test that it's legal to transmute a reference while shrinking the
+ // lifetime.
+ let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
+ assert_eq!(*x, array_of_u8s);
+ }
+ // Test that `transmute_mut!` supports decreasing alignment.
+ let mut u = AU64(0);
+ let array = [0, 0, 0, 0, 0, 0, 0, 0];
+ let x: &[u8; 8] = transmute_mut!(&mut u);
+ assert_eq!(*x, array);
+
+ // Test that a mutable reference can be turned into an immutable one.
+ let mut x = 0u8;
+ #[allow(clippy::useless_transmute)]
+ let y: &u8 = transmute_mut!(&mut x);
+ assert_eq!(*y, 0);
+ }
+
+ #[test]
+ fn test_macros_evaluate_args_once() {
+ let mut ctr = 0;
+ let _: usize = transmute!({
+ ctr += 1;
+ 0usize
+ });
+ assert_eq!(ctr, 1);
+
+ let mut ctr = 0;
+ let _: &usize = transmute_ref!({
+ ctr += 1;
+ &0usize
+ });
+ assert_eq!(ctr, 1);
+ }
+
+ #[test]
+ fn test_include_value() {
+ const AS_U32: u32 = include_value!("../testdata/include_value/data");
+ assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
+ const AS_I32: i32 = include_value!("../testdata/include_value/data");
+ assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
+ }
+
+ #[test]
+ fn test_address() {
+ // Test that the `Deref` and `DerefMut` implementations return a
+ // reference which points to the right region of memory.
+
+ let buf = [0];
+ let r = Ref::<_, u8>::new(&buf[..]).unwrap();
+ let buf_ptr = buf.as_ptr();
+ let deref_ptr: *const u8 = r.deref();
+ assert_eq!(buf_ptr, deref_ptr);
+
+ let buf = [0];
+ let r = Ref::<_, [u8]>::new_slice(&buf[..]).unwrap();
+ let buf_ptr = buf.as_ptr();
+ let deref_ptr = r.deref().as_ptr();
+ assert_eq!(buf_ptr, deref_ptr);
+ }
+
+ // Verify that values written to a `Ref` are properly shared between the
+ // typed and untyped representations, that reads via `deref` and `read`
+ // behave the same, and that writes via `deref_mut` and `write` behave the
+ // same.
+ fn test_new_helper(mut r: Ref<&mut [u8], AU64>) {
+ // assert that the value starts at 0
+ assert_eq!(*r, AU64(0));
+ assert_eq!(r.read(), AU64(0));
+
+ // Assert that values written to the typed value are reflected in the
+ // byte slice.
+ const VAL1: AU64 = AU64(0xFF00FF00FF00FF00);
+ *r = VAL1;
+ assert_eq!(r.bytes(), &VAL1.to_bytes());
+ *r = AU64(0);
+ r.write(VAL1);
+ assert_eq!(r.bytes(), &VAL1.to_bytes());
+
+ // Assert that values written to the byte slice are reflected in the
+ // typed value.
+ const VAL2: AU64 = AU64(!VAL1.0); // different from `VAL1`
+ r.bytes_mut().copy_from_slice(&VAL2.to_bytes()[..]);
+ assert_eq!(*r, VAL2);
+ assert_eq!(r.read(), VAL2);
+ }
+
+ // Verify that values written to a `Ref` are properly shared between the
+ // typed and untyped representations; pass a value with `typed_len` `AU64`s
+ // backed by an array of `typed_len * 8` bytes.
+ fn test_new_helper_slice(mut r: Ref<&mut [u8], [AU64]>, typed_len: usize) {
+ // Assert that the value starts out zeroed.
+ assert_eq!(&*r, vec![AU64(0); typed_len].as_slice());
+
+ // Check the backing storage is the exact same slice.
+ let untyped_len = typed_len * 8;
+ assert_eq!(r.bytes().len(), untyped_len);
+ assert_eq!(r.bytes().as_ptr(), r.as_ptr().cast::<u8>());
+
+ // Assert that values written to the typed value are reflected in the
+ // byte slice.
+ const VAL1: AU64 = AU64(0xFF00FF00FF00FF00);
+ for typed in &mut *r {
+ *typed = VAL1;
+ }
+ assert_eq!(r.bytes(), VAL1.0.to_ne_bytes().repeat(typed_len).as_slice());
+
+ // Assert that values written to the byte slice are reflected in the
+ // typed value.
+ const VAL2: AU64 = AU64(!VAL1.0); // different from VAL1
+ r.bytes_mut().copy_from_slice(&VAL2.0.to_ne_bytes().repeat(typed_len));
+ assert!(r.iter().copied().all(|x| x == VAL2));
+ }
+
+ // Verify that values written to a `Ref` are properly shared between the
+ // typed and untyped representations, that reads via `deref` and `read`
+ // behave the same, and that writes via `deref_mut` and `write` behave the
+ // same.
+ fn test_new_helper_unaligned(mut r: Ref<&mut [u8], [u8; 8]>) {
+ // assert that the value starts at 0
+ assert_eq!(*r, [0; 8]);
+ assert_eq!(r.read(), [0; 8]);
+
+ // Assert that values written to the typed value are reflected in the
+ // byte slice.
+ const VAL1: [u8; 8] = [0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00];
+ *r = VAL1;
+ assert_eq!(r.bytes(), &VAL1);
+ *r = [0; 8];
+ r.write(VAL1);
+ assert_eq!(r.bytes(), &VAL1);
+
+ // Assert that values written to the byte slice are reflected in the
+ // typed value.
+ const VAL2: [u8; 8] = [0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF]; // different from VAL1
+ r.bytes_mut().copy_from_slice(&VAL2[..]);
+ assert_eq!(*r, VAL2);
+ assert_eq!(r.read(), VAL2);
+ }
+
+ // Verify that values written to a `Ref` are properly shared between the
+ // typed and untyped representations; pass a value with `len` `u8`s backed
+ // by an array of `len` bytes.
+ fn test_new_helper_slice_unaligned(mut r: Ref<&mut [u8], [u8]>, len: usize) {
+ // Assert that the value starts out zeroed.
+ assert_eq!(&*r, vec![0u8; len].as_slice());
+
+ // Check the backing storage is the exact same slice.
+ assert_eq!(r.bytes().len(), len);
+ assert_eq!(r.bytes().as_ptr(), r.as_ptr());
+
+ // Assert that values written to the typed value are reflected in the
+ // byte slice.
+ let mut expected_bytes = [0xFF, 0x00].iter().copied().cycle().take(len).collect::<Vec<_>>();
+ r.copy_from_slice(&expected_bytes);
+ assert_eq!(r.bytes(), expected_bytes.as_slice());
+
+ // Assert that values written to the byte slice are reflected in the
+ // typed value.
+ for byte in &mut expected_bytes {
+ *byte = !*byte; // different from `expected_len`
+ }
+ r.bytes_mut().copy_from_slice(&expected_bytes);
+ assert_eq!(&*r, expected_bytes.as_slice());
+ }
+
+ #[test]
+ fn test_new_aligned_sized() {
+ // Test that a properly-aligned, properly-sized buffer works for new,
+ // new_from_prefix, and new_from_suffix, and that new_from_prefix and
+ // new_from_suffix return empty slices. Test that a properly-aligned
+ // buffer whose length is a multiple of the element size works for
+ // new_slice. Test that xxx_zeroed behaves the same, and zeroes the
+ // memory.
+
+ // A buffer with an alignment of 8.
+ let mut buf = Align::<[u8; 8], AU64>::default();
+ // `buf.t` should be aligned to 8, so this should always succeed.
+ test_new_helper(Ref::<_, AU64>::new(&mut buf.t[..]).unwrap());
+ let ascending: [u8; 8] = (0..8).collect::<Vec<_>>().try_into().unwrap();
+ buf.t = ascending;
+ test_new_helper(Ref::<_, AU64>::new_zeroed(&mut buf.t[..]).unwrap());
+ {
+ // In a block so that `r` and `suffix` don't live too long.
+ buf.set_default();
+ let (r, suffix) = Ref::<_, AU64>::new_from_prefix(&mut buf.t[..]).unwrap();
+ assert!(suffix.is_empty());
+ test_new_helper(r);
+ }
+ {
+ buf.t = ascending;
+ let (r, suffix) = Ref::<_, AU64>::new_from_prefix_zeroed(&mut buf.t[..]).unwrap();
+ assert!(suffix.is_empty());
+ test_new_helper(r);
+ }
+ {
+ buf.set_default();
+ let (prefix, r) = Ref::<_, AU64>::new_from_suffix(&mut buf.t[..]).unwrap();
+ assert!(prefix.is_empty());
+ test_new_helper(r);
+ }
+ {
+ buf.t = ascending;
+ let (prefix, r) = Ref::<_, AU64>::new_from_suffix_zeroed(&mut buf.t[..]).unwrap();
+ assert!(prefix.is_empty());
+ test_new_helper(r);
+ }
+
+ // A buffer with alignment 8 and length 24. We choose this length very
+ // intentionally: if we instead used length 16, then the prefix and
+ // suffix lengths would be identical. In the past, we used length 16,
+ // which resulted in this test failing to discover the bug uncovered in
+ // #506.
+ let mut buf = Align::<[u8; 24], AU64>::default();
+ // `buf.t` should be aligned to 8 and have a length which is a multiple
+ // of `size_of::<AU64>()`, so this should always succeed.
+ test_new_helper_slice(Ref::<_, [AU64]>::new_slice(&mut buf.t[..]).unwrap(), 3);
+ let ascending: [u8; 24] = (0..24).collect::<Vec<_>>().try_into().unwrap();
+ // 16 ascending bytes followed by 8 zeros.
+ let mut ascending_prefix = ascending;
+ ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
+ // 8 zeros followed by 16 ascending bytes.
+ let mut ascending_suffix = ascending;
+ ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
+ test_new_helper_slice(Ref::<_, [AU64]>::new_slice_zeroed(&mut buf.t[..]).unwrap(), 3);
+
+ {
+ buf.t = ascending_suffix;
+ let (r, suffix) = Ref::<_, [AU64]>::new_slice_from_prefix(&mut buf.t[..], 1).unwrap();
+ assert_eq!(suffix, &ascending[8..]);
+ test_new_helper_slice(r, 1);
+ }
+ {
+ buf.t = ascending_suffix;
+ let (r, suffix) =
+ Ref::<_, [AU64]>::new_slice_from_prefix_zeroed(&mut buf.t[..], 1).unwrap();
+ assert_eq!(suffix, &ascending[8..]);
+ test_new_helper_slice(r, 1);
+ }
+ {
+ buf.t = ascending_prefix;
+ let (prefix, r) = Ref::<_, [AU64]>::new_slice_from_suffix(&mut buf.t[..], 1).unwrap();
+ assert_eq!(prefix, &ascending[..16]);
+ test_new_helper_slice(r, 1);
+ }
+ {
+ buf.t = ascending_prefix;
+ let (prefix, r) =
+ Ref::<_, [AU64]>::new_slice_from_suffix_zeroed(&mut buf.t[..], 1).unwrap();
+ assert_eq!(prefix, &ascending[..16]);
+ test_new_helper_slice(r, 1);
+ }
+ }
+
+ #[test]
+ fn test_new_unaligned_sized() {
+ // Test that an unaligned, properly-sized buffer works for
+ // `new_unaligned`, `new_unaligned_from_prefix`, and
+ // `new_unaligned_from_suffix`, and that `new_unaligned_from_prefix`
+ // `new_unaligned_from_suffix` return empty slices. Test that an
+ // unaligned buffer whose length is a multiple of the element size works
+ // for `new_slice`. Test that `xxx_zeroed` behaves the same, and zeroes
+ // the memory.
+
+ let mut buf = [0u8; 8];
+ test_new_helper_unaligned(Ref::<_, [u8; 8]>::new_unaligned(&mut buf[..]).unwrap());
+ buf = [0xFFu8; 8];
+ test_new_helper_unaligned(Ref::<_, [u8; 8]>::new_unaligned_zeroed(&mut buf[..]).unwrap());
+ {
+ // In a block so that `r` and `suffix` don't live too long.
+ buf = [0u8; 8];
+ let (r, suffix) = Ref::<_, [u8; 8]>::new_unaligned_from_prefix(&mut buf[..]).unwrap();
+ assert!(suffix.is_empty());
+ test_new_helper_unaligned(r);
+ }
+ {
+ buf = [0xFFu8; 8];
+ let (r, suffix) =
+ Ref::<_, [u8; 8]>::new_unaligned_from_prefix_zeroed(&mut buf[..]).unwrap();
+ assert!(suffix.is_empty());
+ test_new_helper_unaligned(r);
+ }
+ {
+ buf = [0u8; 8];
+ let (prefix, r) = Ref::<_, [u8; 8]>::new_unaligned_from_suffix(&mut buf[..]).unwrap();
+ assert!(prefix.is_empty());
+ test_new_helper_unaligned(r);
+ }
+ {
+ buf = [0xFFu8; 8];
+ let (prefix, r) =
+ Ref::<_, [u8; 8]>::new_unaligned_from_suffix_zeroed(&mut buf[..]).unwrap();
+ assert!(prefix.is_empty());
+ test_new_helper_unaligned(r);
+ }
+
+ let mut buf = [0u8; 16];
+ // `buf.t` should be aligned to 8 and have a length which is a multiple
+ // of `size_of::AU64>()`, so this should always succeed.
+ test_new_helper_slice_unaligned(
+ Ref::<_, [u8]>::new_slice_unaligned(&mut buf[..]).unwrap(),
+ 16,
+ );
+ buf = [0xFFu8; 16];
+ test_new_helper_slice_unaligned(
+ Ref::<_, [u8]>::new_slice_unaligned_zeroed(&mut buf[..]).unwrap(),
+ 16,
+ );
+
+ {
+ buf = [0u8; 16];
+ let (r, suffix) =
+ Ref::<_, [u8]>::new_slice_unaligned_from_prefix(&mut buf[..], 8).unwrap();
+ assert_eq!(suffix, [0; 8]);
+ test_new_helper_slice_unaligned(r, 8);
+ }
+ {
+ buf = [0xFFu8; 16];
+ let (r, suffix) =
+ Ref::<_, [u8]>::new_slice_unaligned_from_prefix_zeroed(&mut buf[..], 8).unwrap();
+ assert_eq!(suffix, [0xFF; 8]);
+ test_new_helper_slice_unaligned(r, 8);
+ }
+ {
+ buf = [0u8; 16];
+ let (prefix, r) =
+ Ref::<_, [u8]>::new_slice_unaligned_from_suffix(&mut buf[..], 8).unwrap();
+ assert_eq!(prefix, [0; 8]);
+ test_new_helper_slice_unaligned(r, 8);
+ }
+ {
+ buf = [0xFFu8; 16];
+ let (prefix, r) =
+ Ref::<_, [u8]>::new_slice_unaligned_from_suffix_zeroed(&mut buf[..], 8).unwrap();
+ assert_eq!(prefix, [0xFF; 8]);
+ test_new_helper_slice_unaligned(r, 8);
+ }
+ }
+
+ #[test]
+ fn test_new_oversized() {
+ // Test that a properly-aligned, overly-sized buffer works for
+ // `new_from_prefix` and `new_from_suffix`, and that they return the
+ // remainder and prefix of the slice respectively. Test that
+ // `xxx_zeroed` behaves the same, and zeroes the memory.
+
+ let mut buf = Align::<[u8; 16], AU64>::default();
+ {
+ // In a block so that `r` and `suffix` don't live too long. `buf.t`
+ // should be aligned to 8, so this should always succeed.
+ let (r, suffix) = Ref::<_, AU64>::new_from_prefix(&mut buf.t[..]).unwrap();
+ assert_eq!(suffix.len(), 8);
+ test_new_helper(r);
+ }
+ {
+ buf.t = [0xFFu8; 16];
+ // `buf.t` should be aligned to 8, so this should always succeed.
+ let (r, suffix) = Ref::<_, AU64>::new_from_prefix_zeroed(&mut buf.t[..]).unwrap();
+ // Assert that the suffix wasn't zeroed.
+ assert_eq!(suffix, &[0xFFu8; 8]);
+ test_new_helper(r);
+ }
+ {
+ buf.set_default();
+ // `buf.t` should be aligned to 8, so this should always succeed.
+ let (prefix, r) = Ref::<_, AU64>::new_from_suffix(&mut buf.t[..]).unwrap();
+ assert_eq!(prefix.len(), 8);
+ test_new_helper(r);
+ }
+ {
+ buf.t = [0xFFu8; 16];
+ // `buf.t` should be aligned to 8, so this should always succeed.
+ let (prefix, r) = Ref::<_, AU64>::new_from_suffix_zeroed(&mut buf.t[..]).unwrap();
+ // Assert that the prefix wasn't zeroed.
+ assert_eq!(prefix, &[0xFFu8; 8]);
+ test_new_helper(r);
+ }
+ }
+
+ #[test]
+ fn test_new_unaligned_oversized() {
+ // Test than an unaligned, overly-sized buffer works for
+ // `new_unaligned_from_prefix` and `new_unaligned_from_suffix`, and that
+ // they return the remainder and prefix of the slice respectively. Test
+ // that `xxx_zeroed` behaves the same, and zeroes the memory.
+
+ let mut buf = [0u8; 16];
+ {
+ // In a block so that `r` and `suffix` don't live too long.
+ let (r, suffix) = Ref::<_, [u8; 8]>::new_unaligned_from_prefix(&mut buf[..]).unwrap();
+ assert_eq!(suffix.len(), 8);
+ test_new_helper_unaligned(r);
+ }
+ {
+ buf = [0xFFu8; 16];
+ let (r, suffix) =
+ Ref::<_, [u8; 8]>::new_unaligned_from_prefix_zeroed(&mut buf[..]).unwrap();
+ // Assert that the suffix wasn't zeroed.
+ assert_eq!(suffix, &[0xFF; 8]);
+ test_new_helper_unaligned(r);
+ }
+ {
+ buf = [0u8; 16];
+ let (prefix, r) = Ref::<_, [u8; 8]>::new_unaligned_from_suffix(&mut buf[..]).unwrap();
+ assert_eq!(prefix.len(), 8);
+ test_new_helper_unaligned(r);
+ }
+ {
+ buf = [0xFFu8; 16];
+ let (prefix, r) =
+ Ref::<_, [u8; 8]>::new_unaligned_from_suffix_zeroed(&mut buf[..]).unwrap();
+ // Assert that the prefix wasn't zeroed.
+ assert_eq!(prefix, &[0xFF; 8]);
+ test_new_helper_unaligned(r);
+ }
+ }
+
+ #[test]
+ fn test_ref_from_mut_from() {
+ // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` success cases
+ // Exhaustive coverage for these methods is covered by the `Ref` tests above,
+ // which these helper methods defer to.
+
+ let mut buf =
+ Align::<[u8; 16], AU64>::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
+
+ assert_eq!(
+ AU64::ref_from(&buf.t[8..]).unwrap().0.to_ne_bytes(),
+ [8, 9, 10, 11, 12, 13, 14, 15]
+ );
+ let suffix = AU64::mut_from(&mut buf.t[8..]).unwrap();
+ suffix.0 = 0x0101010101010101;
+ // The `[u8:9]` is a non-half size of the full buffer, which would catch
+ // `from_prefix` having the same implementation as `from_suffix` (issues #506, #511).
+ assert_eq!(<[u8; 9]>::ref_from_suffix(&buf.t[..]).unwrap(), &[7u8, 1, 1, 1, 1, 1, 1, 1, 1]);
+ let suffix = AU64::mut_from_suffix(&mut buf.t[1..]).unwrap();
+ suffix.0 = 0x0202020202020202;
+ <[u8; 10]>::mut_from_suffix(&mut buf.t[..]).unwrap()[0] = 42;
+ assert_eq!(<[u8; 9]>::ref_from_prefix(&buf.t[..]).unwrap(), &[0, 1, 2, 3, 4, 5, 42, 7, 2]);
+ <[u8; 2]>::mut_from_prefix(&mut buf.t[..]).unwrap()[1] = 30;
+ assert_eq!(buf.t, [0, 30, 2, 3, 4, 5, 42, 7, 2, 2, 2, 2, 2, 2, 2, 2]);
+ }
+
+ #[test]
+ fn test_ref_from_mut_from_error() {
+ // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` error cases.
+
+ // Fail because the buffer is too large.
+ let mut buf = Align::<[u8; 16], AU64>::default();
+ // `buf.t` should be aligned to 8, so only the length check should fail.
+ assert!(AU64::ref_from(&buf.t[..]).is_none());
+ assert!(AU64::mut_from(&mut buf.t[..]).is_none());
+ assert!(<[u8; 8]>::ref_from(&buf.t[..]).is_none());
+ assert!(<[u8; 8]>::mut_from(&mut buf.t[..]).is_none());
+
+ // Fail because the buffer is too small.
+ let mut buf = Align::<[u8; 4], AU64>::default();
+ assert!(AU64::ref_from(&buf.t[..]).is_none());
+ assert!(AU64::mut_from(&mut buf.t[..]).is_none());
+ assert!(<[u8; 8]>::ref_from(&buf.t[..]).is_none());
+ assert!(<[u8; 8]>::mut_from(&mut buf.t[..]).is_none());
+ assert!(AU64::ref_from_prefix(&buf.t[..]).is_none());
+ assert!(AU64::mut_from_prefix(&mut buf.t[..]).is_none());
+ assert!(AU64::ref_from_suffix(&buf.t[..]).is_none());
+ assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_none());
+ assert!(<[u8; 8]>::ref_from_prefix(&buf.t[..]).is_none());
+ assert!(<[u8; 8]>::mut_from_prefix(&mut buf.t[..]).is_none());
+ assert!(<[u8; 8]>::ref_from_suffix(&buf.t[..]).is_none());
+ assert!(<[u8; 8]>::mut_from_suffix(&mut buf.t[..]).is_none());
+
+ // Fail because the alignment is insufficient.
+ let mut buf = Align::<[u8; 13], AU64>::default();
+ assert!(AU64::ref_from(&buf.t[1..]).is_none());
+ assert!(AU64::mut_from(&mut buf.t[1..]).is_none());
+ assert!(AU64::ref_from(&buf.t[1..]).is_none());
+ assert!(AU64::mut_from(&mut buf.t[1..]).is_none());
+ assert!(AU64::ref_from_prefix(&buf.t[1..]).is_none());
+ assert!(AU64::mut_from_prefix(&mut buf.t[1..]).is_none());
+ assert!(AU64::ref_from_suffix(&buf.t[..]).is_none());
+ assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_none());
+ }
+
+ #[test]
+ #[allow(clippy::cognitive_complexity)]
+ fn test_new_error() {
+ // Fail because the buffer is too large.
+
+ // A buffer with an alignment of 8.
+ let mut buf = Align::<[u8; 16], AU64>::default();
+ // `buf.t` should be aligned to 8, so only the length check should fail.
+ assert!(Ref::<_, AU64>::new(&buf.t[..]).is_none());
+ assert!(Ref::<_, AU64>::new_zeroed(&mut buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned(&buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned_zeroed(&mut buf.t[..]).is_none());
+
+ // Fail because the buffer is too small.
+
+ // A buffer with an alignment of 8.
+ let mut buf = Align::<[u8; 4], AU64>::default();
+ // `buf.t` should be aligned to 8, so only the length check should fail.
+ assert!(Ref::<_, AU64>::new(&buf.t[..]).is_none());
+ assert!(Ref::<_, AU64>::new_zeroed(&mut buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned(&buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned_zeroed(&mut buf.t[..]).is_none());
+ assert!(Ref::<_, AU64>::new_from_prefix(&buf.t[..]).is_none());
+ assert!(Ref::<_, AU64>::new_from_prefix_zeroed(&mut buf.t[..]).is_none());
+ assert!(Ref::<_, AU64>::new_from_suffix(&buf.t[..]).is_none());
+ assert!(Ref::<_, AU64>::new_from_suffix_zeroed(&mut buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned_from_prefix(&buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned_from_prefix_zeroed(&mut buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned_from_suffix(&buf.t[..]).is_none());
+ assert!(Ref::<_, [u8; 8]>::new_unaligned_from_suffix_zeroed(&mut buf.t[..]).is_none());
+
+ // Fail because the length is not a multiple of the element size.
+
+ let mut buf = Align::<[u8; 12], AU64>::default();
+ // `buf.t` has length 12, but element size is 8.
+ assert!(Ref::<_, [AU64]>::new_slice(&buf.t[..]).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_zeroed(&mut buf.t[..]).is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned(&buf.t[..]).is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_zeroed(&mut buf.t[..]).is_none());
+
+ // Fail because the buffer is too short.
+ let mut buf = Align::<[u8; 12], AU64>::default();
+ // `buf.t` has length 12, but the element size is 8 (and we're expecting
+ // two of them).
+ assert!(Ref::<_, [AU64]>::new_slice_from_prefix(&buf.t[..], 2).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_prefix_zeroed(&mut buf.t[..], 2).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_suffix(&buf.t[..], 2).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_suffix_zeroed(&mut buf.t[..], 2).is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_prefix(&buf.t[..], 2).is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_prefix_zeroed(&mut buf.t[..], 2)
+ .is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_suffix(&buf.t[..], 2).is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_suffix_zeroed(&mut buf.t[..], 2)
+ .is_none());
+
+ // Fail because the alignment is insufficient.
+
+ // A buffer with an alignment of 8. An odd buffer size is chosen so that
+ // the last byte of the buffer has odd alignment.
+ let mut buf = Align::<[u8; 13], AU64>::default();
+ // Slicing from 1, we get a buffer with size 12 (so the length check
+ // should succeed) but an alignment of only 1, which is insufficient.
+ assert!(Ref::<_, AU64>::new(&buf.t[1..]).is_none());
+ assert!(Ref::<_, AU64>::new_zeroed(&mut buf.t[1..]).is_none());
+ assert!(Ref::<_, AU64>::new_from_prefix(&buf.t[1..]).is_none());
+ assert!(Ref::<_, AU64>::new_from_prefix_zeroed(&mut buf.t[1..]).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice(&buf.t[1..]).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_zeroed(&mut buf.t[1..]).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_prefix(&buf.t[1..], 1).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_prefix_zeroed(&mut buf.t[1..], 1).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_suffix(&buf.t[1..], 1).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_suffix_zeroed(&mut buf.t[1..], 1).is_none());
+ // Slicing is unnecessary here because `new_from_suffix[_zeroed]` use
+ // the suffix of the slice, which has odd alignment.
+ assert!(Ref::<_, AU64>::new_from_suffix(&buf.t[..]).is_none());
+ assert!(Ref::<_, AU64>::new_from_suffix_zeroed(&mut buf.t[..]).is_none());
+
+ // Fail due to arithmetic overflow.
+
+ let mut buf = Align::<[u8; 16], AU64>::default();
+ let unreasonable_len = usize::MAX / mem::size_of::<AU64>() + 1;
+ assert!(Ref::<_, [AU64]>::new_slice_from_prefix(&buf.t[..], unreasonable_len).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_prefix_zeroed(&mut buf.t[..], unreasonable_len)
+ .is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_suffix(&buf.t[..], unreasonable_len).is_none());
+ assert!(Ref::<_, [AU64]>::new_slice_from_suffix_zeroed(&mut buf.t[..], unreasonable_len)
+ .is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_prefix(&buf.t[..], unreasonable_len)
+ .is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_prefix_zeroed(
+ &mut buf.t[..],
+ unreasonable_len
+ )
+ .is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_suffix(&buf.t[..], unreasonable_len)
+ .is_none());
+ assert!(Ref::<_, [[u8; 8]]>::new_slice_unaligned_from_suffix_zeroed(
+ &mut buf.t[..],
+ unreasonable_len
+ )
+ .is_none());
+ }
+
+ // Tests for ensuring that, if a ZST is passed into a slice-like function,
+ // we always panic. Since these tests need to be separate per-function, and
+ // they tend to take up a lot of space, we generate them using a macro in a
+ // submodule instead. The submodule ensures that we can just re-use the name
+ // of the function under test for the name of the test itself.
+ mod test_zst_panics {
+ macro_rules! zst_test {
+ ($name:ident($($tt:tt)*), $constructor_in_panic_msg:tt) => {
+ #[test]
+ #[should_panic = concat!("Ref::", $constructor_in_panic_msg, " called on a zero-sized type")]
+ fn $name() {
+ let mut buffer = [0u8];
+ let r = $crate::Ref::<_, [()]>::$name(&mut buffer[..], $($tt)*);
+ unreachable!("should have panicked, got {:?}", r);
+ }
+ }
+ }
+ zst_test!(new_slice(), "new_slice");
+ zst_test!(new_slice_zeroed(), "new_slice");
+ zst_test!(new_slice_from_prefix(1), "new_slice");
+ zst_test!(new_slice_from_prefix_zeroed(1), "new_slice");
+ zst_test!(new_slice_from_suffix(1), "new_slice");
+ zst_test!(new_slice_from_suffix_zeroed(1), "new_slice");
+ zst_test!(new_slice_unaligned(), "new_slice_unaligned");
+ zst_test!(new_slice_unaligned_zeroed(), "new_slice_unaligned");
+ zst_test!(new_slice_unaligned_from_prefix(1), "new_slice_unaligned");
+ zst_test!(new_slice_unaligned_from_prefix_zeroed(1), "new_slice_unaligned");
+ zst_test!(new_slice_unaligned_from_suffix(1), "new_slice_unaligned");
+ zst_test!(new_slice_unaligned_from_suffix_zeroed(1), "new_slice_unaligned");
+ }
+
+ #[test]
+ fn test_as_bytes_methods() {
+ /// Run a series of tests by calling `AsBytes` methods on `t`.
+ ///
+ /// `bytes` is the expected byte sequence returned from `t.as_bytes()`
+ /// before `t` has been modified. `post_mutation` is the expected
+ /// sequence returned from `t.as_bytes()` after `t.as_bytes_mut()[0]`
+ /// has had its bits flipped (by applying `^= 0xFF`).
+ ///
+ /// `N` is the size of `t` in bytes.
+ fn test<T: FromBytes + AsBytes + Debug + Eq + ?Sized, const N: usize>(
+ t: &mut T,
+ bytes: &[u8],
+ post_mutation: &T,
+ ) {
+ // Test that we can access the underlying bytes, and that we get the
+ // right bytes and the right number of bytes.
+ assert_eq!(t.as_bytes(), bytes);
+
+ // Test that changes to the underlying byte slices are reflected in
+ // the original object.
+ t.as_bytes_mut()[0] ^= 0xFF;
+ assert_eq!(t, post_mutation);
+ t.as_bytes_mut()[0] ^= 0xFF;
+
+ // `write_to` rejects slices that are too small or too large.
+ assert_eq!(t.write_to(&mut vec![0; N - 1][..]), None);
+ assert_eq!(t.write_to(&mut vec![0; N + 1][..]), None);
+
+ // `write_to` works as expected.
+ let mut bytes = [0; N];
+ assert_eq!(t.write_to(&mut bytes[..]), Some(()));
+ assert_eq!(bytes, t.as_bytes());
+
+ // `write_to_prefix` rejects slices that are too small.
+ assert_eq!(t.write_to_prefix(&mut vec![0; N - 1][..]), None);
+
+ // `write_to_prefix` works with exact-sized slices.
+ let mut bytes = [0; N];
+ assert_eq!(t.write_to_prefix(&mut bytes[..]), Some(()));
+ assert_eq!(bytes, t.as_bytes());
+
+ // `write_to_prefix` works with too-large slices, and any bytes past
+ // the prefix aren't modified.
+ let mut too_many_bytes = vec![0; N + 1];
+ too_many_bytes[N] = 123;
+ assert_eq!(t.write_to_prefix(&mut too_many_bytes[..]), Some(()));
+ assert_eq!(&too_many_bytes[..N], t.as_bytes());
+ assert_eq!(too_many_bytes[N], 123);
+
+ // `write_to_suffix` rejects slices that are too small.
+ assert_eq!(t.write_to_suffix(&mut vec![0; N - 1][..]), None);
+
+ // `write_to_suffix` works with exact-sized slices.
+ let mut bytes = [0; N];
+ assert_eq!(t.write_to_suffix(&mut bytes[..]), Some(()));
+ assert_eq!(bytes, t.as_bytes());
+
+ // `write_to_suffix` works with too-large slices, and any bytes
+ // before the suffix aren't modified.
+ let mut too_many_bytes = vec![0; N + 1];
+ too_many_bytes[0] = 123;
+ assert_eq!(t.write_to_suffix(&mut too_many_bytes[..]), Some(()));
+ assert_eq!(&too_many_bytes[1..], t.as_bytes());
+ assert_eq!(too_many_bytes[0], 123);
+ }
+
+ #[derive(Debug, Eq, PartialEq, FromZeroes, FromBytes, AsBytes)]
+ #[repr(C)]
+ struct Foo {
+ a: u32,
+ b: Wrapping<u32>,
+ c: Option<NonZeroU32>,
+ }
+
+ let expected_bytes: Vec<u8> = if cfg!(target_endian = "little") {
+ vec![1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]
+ } else {
+ vec![0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0]
+ };
+ let post_mutation_expected_a =
+ if cfg!(target_endian = "little") { 0x00_00_00_FE } else { 0xFF_00_00_01 };
+ test::<_, 12>(
+ &mut Foo { a: 1, b: Wrapping(2), c: None },
+ expected_bytes.as_bytes(),
+ &Foo { a: post_mutation_expected_a, b: Wrapping(2), c: None },
+ );
+ test::<_, 3>(
+ Unsized::from_mut_slice(&mut [1, 2, 3]),
+ &[1, 2, 3],
+ Unsized::from_mut_slice(&mut [0xFE, 2, 3]),
+ );
+ }
+
+ #[test]
+ fn test_array() {
+ #[derive(FromZeroes, FromBytes, AsBytes)]
+ #[repr(C)]
+ struct Foo {
+ a: [u16; 33],
+ }
+
+ let foo = Foo { a: [0xFFFF; 33] };
+ let expected = [0xFFu8; 66];
+ assert_eq!(foo.as_bytes(), &expected[..]);
+ }
+
+ #[test]
+ fn test_display_debug() {
+ let buf = Align::<[u8; 8], u64>::default();
+ let r = Ref::<_, u64>::new(&buf.t[..]).unwrap();
+ assert_eq!(format!("{}", r), "0");
+ assert_eq!(format!("{:?}", r), "Ref(0)");
+
+ let buf = Align::<[u8; 8], u64>::default();
+ let r = Ref::<_, [u64]>::new_slice(&buf.t[..]).unwrap();
+ assert_eq!(format!("{:?}", r), "Ref([0])");
+ }
+
+ #[test]
+ fn test_eq() {
+ let buf1 = 0_u64;
+ let r1 = Ref::<_, u64>::new(buf1.as_bytes()).unwrap();
+ let buf2 = 0_u64;
+ let r2 = Ref::<_, u64>::new(buf2.as_bytes()).unwrap();
+ assert_eq!(r1, r2);
+ }
+
+ #[test]
+ fn test_ne() {
+ let buf1 = 0_u64;
+ let r1 = Ref::<_, u64>::new(buf1.as_bytes()).unwrap();
+ let buf2 = 1_u64;
+ let r2 = Ref::<_, u64>::new(buf2.as_bytes()).unwrap();
+ assert_ne!(r1, r2);
+ }
+
+ #[test]
+ fn test_ord() {
+ let buf1 = 0_u64;
+ let r1 = Ref::<_, u64>::new(buf1.as_bytes()).unwrap();
+ let buf2 = 1_u64;
+ let r2 = Ref::<_, u64>::new(buf2.as_bytes()).unwrap();
+ assert!(r1 < r2);
+ }
+
+ #[test]
+ fn test_new_zeroed() {
+ assert!(!bool::new_zeroed());
+ assert_eq!(u64::new_zeroed(), 0);
+ // This test exists in order to exercise unsafe code, especially when
+ // running under Miri.
+ #[allow(clippy::unit_cmp)]
+ {
+ assert_eq!(<()>::new_zeroed(), ());
+ }
+ }
+
+ #[test]
+ fn test_transparent_packed_generic_struct() {
+ #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ #[repr(transparent)]
+ struct Foo<T> {
+ _t: T,
+ _phantom: PhantomData<()>,
+ }
+
+ assert_impl_all!(Foo<u32>: FromZeroes, FromBytes, AsBytes);
+ assert_impl_all!(Foo<u8>: Unaligned);
+
+ #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+ #[repr(packed)]
+ struct Bar<T, U> {
+ _t: T,
+ _u: U,
+ }
+
+ assert_impl_all!(Bar<u8, AU64>: FromZeroes, FromBytes, AsBytes, Unaligned);
+ }
+
+ #[test]
+ fn test_impls() {
+ use core::borrow::Borrow;
+
+ // A type that can supply test cases for testing
+ // `TryFromBytes::is_bit_valid`. All types passed to `assert_impls!`
+ // must implement this trait; that macro uses it to generate runtime
+ // tests for `TryFromBytes` impls.
+ //
+ // All `T: FromBytes` types are provided with a blanket impl. Other
+ // types must implement `TryFromBytesTestable` directly (ie using
+ // `impl_try_from_bytes_testable!`).
+ trait TryFromBytesTestable {
+ fn with_passing_test_cases<F: Fn(&Self)>(f: F);
+ fn with_failing_test_cases<F: Fn(&[u8])>(f: F);
+ }
+
+ impl<T: FromBytes> TryFromBytesTestable for T {
+ fn with_passing_test_cases<F: Fn(&Self)>(f: F) {
+ // Test with a zeroed value.
+ f(&Self::new_zeroed());
+
+ let ffs = {
+ let mut t = Self::new_zeroed();
+ let ptr: *mut T = &mut t;
+ // SAFETY: `T: FromBytes`
+ unsafe { ptr::write_bytes(ptr.cast::<u8>(), 0xFF, mem::size_of::<T>()) };
+ t
+ };
+
+ // Test with a value initialized with 0xFF.
+ f(&ffs);
+ }
+
+ fn with_failing_test_cases<F: Fn(&[u8])>(_f: F) {}
+ }
+
+ // Implements `TryFromBytesTestable`.
+ macro_rules! impl_try_from_bytes_testable {
+ // Base case for recursion (when the list of types has run out).
+ (=> @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => {};
+ // Implements for type(s) with no type parameters.
+ ($ty:ty $(,$tys:ty)* => @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => {
+ impl TryFromBytesTestable for $ty {
+ impl_try_from_bytes_testable!(
+ @methods @success $($success_case),*
+ $(, @failure $($failure_case),*)?
+ );
+ }
+ impl_try_from_bytes_testable!($($tys),* => @success $($success_case),* $(, @failure $($failure_case),*)?);
+ };
+ // Implements for multiple types with no type parameters.
+ ($($($ty:ty),* => @success $($success_case:expr), * $(, @failure $($failure_case:expr),*)?;)*) => {
+ $(
+ impl_try_from_bytes_testable!($($ty),* => @success $($success_case),* $(, @failure $($failure_case),*)*);
+ )*
+ };
+ // Implements only the methods; caller must invoke this from inside
+ // an impl block.
+ (@methods @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => {
+ fn with_passing_test_cases<F: Fn(&Self)>(_f: F) {
+ $(
+ _f($success_case.borrow());
+ )*
+ }
+
+ fn with_failing_test_cases<F: Fn(&[u8])>(_f: F) {
+ $($(
+ // `unused_qualifications` is spuriously triggered on
+ // `Option::<Self>::None`.
+ #[allow(unused_qualifications)]
+ let case = $failure_case.as_bytes();
+ _f(case.as_bytes());
+ )*)?
+ }
+ };
+ }
+
+ // Note that these impls are only for types which are not `FromBytes`.
+ // `FromBytes` types are covered by a preceding blanket impl.
+ impl_try_from_bytes_testable!(
+ bool => @success true, false,
+ @failure 2u8, 3u8, 0xFFu8;
+ char => @success '\u{0}', '\u{D7FF}', '\u{E000}', '\u{10FFFF}',
+ @failure 0xD800u32, 0xDFFFu32, 0x110000u32;
+ str => @success "", "hello", "❤️🧡💛💚💙💜",
+ @failure [0, 159, 146, 150];
+ [u8] => @success [], [0, 1, 2];
+ NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32,
+ NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128,
+ NonZeroUsize, NonZeroIsize
+ => @success Self::new(1).unwrap(),
+ // Doing this instead of `0` ensures that we always satisfy
+ // the size and alignment requirements of `Self` (whereas
+ // `0` may be any integer type with a different size or
+ // alignment than some `NonZeroXxx` types).
+ @failure Option::<Self>::None;
+ [bool]
+ => @success [true, false], [false, true],
+ @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8];
+ );
+
+ // Asserts that `$ty` implements any `$trait` and doesn't implement any
+ // `!$trait`. Note that all `$trait`s must come before any `!$trait`s.
+ //
+ // For `T: TryFromBytes`, uses `TryFromBytesTestable` to test success
+ // and failure cases for `TryFromBytes::is_bit_valid`.
+ macro_rules! assert_impls {
+ ($ty:ty: TryFromBytes) => {
+ <$ty as TryFromBytesTestable>::with_passing_test_cases(|val| {
+ let c = Ptr::from(val);
+ // SAFETY:
+ // - Since `val` is a normal reference, `c` is guranteed to
+ // be aligned, to point to a single allocation, and to
+ // have a size which doesn't overflow `isize`.
+ // - Since `val` is a valid `$ty`, `c`'s referent satisfies
+ // the bit validity constraints of `is_bit_valid`, which
+ // are a superset of the bit validity constraints of
+ // `$ty`.
+ let res = unsafe { <$ty as TryFromBytes>::is_bit_valid(c) };
+ assert!(res, "{}::is_bit_valid({:?}): got false, expected true", stringify!($ty), val);
+
+ // TODO(#5): In addition to testing `is_bit_valid`, test the
+ // methods built on top of it. This would both allow us to
+ // test their implementations and actually convert the bytes
+ // to `$ty`, giving Miri a chance to catch if this is
+ // unsound (ie, if our `is_bit_valid` impl is buggy).
+ //
+ // The following code was tried, but it doesn't work because
+ // a) some types are not `AsBytes` and, b) some types are
+ // not `Sized`.
+ //
+ // let r = <$ty as TryFromBytes>::try_from_ref(val.as_bytes()).unwrap();
+ // assert_eq!(r, &val);
+ // let r = <$ty as TryFromBytes>::try_from_mut(val.as_bytes_mut()).unwrap();
+ // assert_eq!(r, &mut val);
+ // let v = <$ty as TryFromBytes>::try_read_from(val.as_bytes()).unwrap();
+ // assert_eq!(v, val);
+ });
+ #[allow(clippy::as_conversions)]
+ <$ty as TryFromBytesTestable>::with_failing_test_cases(|c| {
+ let res = <$ty as TryFromBytes>::try_from_ref(c);
+ assert!(res.is_none(), "{}::is_bit_valid({:?}): got true, expected false", stringify!($ty), c);
+ });
+
+ #[allow(dead_code)]
+ const _: () = { static_assertions::assert_impl_all!($ty: TryFromBytes); };
+ };
+ ($ty:ty: $trait:ident) => {
+ #[allow(dead_code)]
+ const _: () = { static_assertions::assert_impl_all!($ty: $trait); };
+ };
+ ($ty:ty: !$trait:ident) => {
+ #[allow(dead_code)]
+ const _: () = { static_assertions::assert_not_impl_any!($ty: $trait); };
+ };
+ ($ty:ty: $($trait:ident),* $(,)? $(!$negative_trait:ident),*) => {
+ $(
+ assert_impls!($ty: $trait);
+ )*
+
+ $(
+ assert_impls!($ty: !$negative_trait);
+ )*
+ };
+ }
+
+ // NOTE: The negative impl assertions here are not necessarily
+ // prescriptive. They merely serve as change detectors to make sure
+ // we're aware of what trait impls are getting added with a given
+ // change. Of course, some impls would be invalid (e.g., `bool:
+ // FromBytes`), and so this change detection is very important.
+
+ assert_impls!((): KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!(u8: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!(i8: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!(u16: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(i16: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(u32: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(i32: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(u64: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(i64: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(u128: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(i128: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(usize: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(isize: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(f32: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(f64: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+
+ assert_impls!(bool: KnownLayout, TryFromBytes, FromZeroes, AsBytes, Unaligned, !FromBytes);
+ assert_impls!(char: KnownLayout, TryFromBytes, FromZeroes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(str: KnownLayout, TryFromBytes, FromZeroes, AsBytes, Unaligned, !FromBytes);
+
+ assert_impls!(NonZeroU8: KnownLayout, TryFromBytes, AsBytes, Unaligned, !FromZeroes, !FromBytes);
+ assert_impls!(NonZeroI8: KnownLayout, TryFromBytes, AsBytes, Unaligned, !FromZeroes, !FromBytes);
+ assert_impls!(NonZeroU16: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroI16: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroU32: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroI32: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroU64: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroI64: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroU128: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroI128: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroUsize: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+ assert_impls!(NonZeroIsize: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned);
+
+ assert_impls!(Option<NonZeroU8>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!(Option<NonZeroI8>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!(Option<NonZeroU16>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroI16>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroU32>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroI32>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroU64>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroI64>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroU128>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroI128>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroUsize>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+ assert_impls!(Option<NonZeroIsize>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned);
+
+ // Implements none of the ZC traits.
+ struct NotZerocopy;
+
+ #[rustfmt::skip]
+ type FnManyArgs = fn(
+ NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+ ) -> (NotZerocopy, NotZerocopy);
+
+ // Allowed, because we're not actually using this type for FFI.
+ #[allow(improper_ctypes_definitions)]
+ #[rustfmt::skip]
+ type ECFnManyArgs = extern "C" fn(
+ NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+ ) -> (NotZerocopy, NotZerocopy);
+
+ #[cfg(feature = "alloc")]
+ assert_impls!(Option<Box<UnsafeCell<NotZerocopy>>>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<Box<[UnsafeCell<NotZerocopy>]>>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<&'static UnsafeCell<NotZerocopy>>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<&'static [UnsafeCell<NotZerocopy>]>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<&'static mut UnsafeCell<NotZerocopy>>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<&'static mut [UnsafeCell<NotZerocopy>]>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<NonNull<UnsafeCell<NotZerocopy>>>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<NonNull<[UnsafeCell<NotZerocopy>]>>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<fn()>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<FnManyArgs>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<extern "C" fn()>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(Option<ECFnManyArgs>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+
+ assert_impls!(PhantomData<NotZerocopy>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!(PhantomData<[u8]>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+
+ assert_impls!(ManuallyDrop<u8>: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes);
+ assert_impls!(ManuallyDrop<[u8]>: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes);
+ assert_impls!(ManuallyDrop<NotZerocopy>: !TryFromBytes, !KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(ManuallyDrop<[NotZerocopy]>: !TryFromBytes, !KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+
+ assert_impls!(MaybeUninit<u8>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, Unaligned, !AsBytes);
+ assert_impls!(MaybeUninit<NotZerocopy>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+
+ assert_impls!(Wrapping<u8>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!(Wrapping<NotZerocopy>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+
+ assert_impls!(Unalign<u8>: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes);
+ assert_impls!(Unalign<NotZerocopy>: Unaligned, !KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes);
+
+ assert_impls!([u8]: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned);
+ assert_impls!([bool]: KnownLayout, TryFromBytes, FromZeroes, AsBytes, Unaligned, !FromBytes);
+ assert_impls!([NotZerocopy]: !KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!([u8; 0]: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes);
+ assert_impls!([NotZerocopy; 0]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!([u8; 1]: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes);
+ assert_impls!([NotZerocopy; 1]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+
+ assert_impls!(*const NotZerocopy: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(*mut NotZerocopy: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(*const [NotZerocopy]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(*mut [NotZerocopy]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(*const dyn Debug: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+ assert_impls!(*mut dyn Debug: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
+
+ #[cfg(feature = "simd")]
+ {
+ #[allow(unused_macros)]
+ macro_rules! test_simd_arch_mod {
+ ($arch:ident, $($typ:ident),*) => {
+ {
+ use core::arch::$arch::{$($typ),*};
+ use crate::*;
+ $( assert_impls!($typ: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); )*
+ }
+ };
+ }
+ #[cfg(target_arch = "x86")]
+ test_simd_arch_mod!(x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i);
+
+ #[cfg(all(feature = "simd-nightly", target_arch = "x86"))]
+ test_simd_arch_mod!(x86, __m512bh, __m512, __m512d, __m512i);
+
+ #[cfg(target_arch = "x86_64")]
+ test_simd_arch_mod!(x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i);
+
+ #[cfg(all(feature = "simd-nightly", target_arch = "x86_64"))]
+ test_simd_arch_mod!(x86_64, __m512bh, __m512, __m512d, __m512i);
+
+ #[cfg(target_arch = "wasm32")]
+ test_simd_arch_mod!(wasm32, v128);
+
+ #[cfg(all(feature = "simd-nightly", target_arch = "powerpc"))]
+ test_simd_arch_mod!(
+ powerpc,
+ vector_bool_long,
+ vector_double,
+ vector_signed_long,
+ vector_unsigned_long
+ );
+
+ #[cfg(all(feature = "simd-nightly", target_arch = "powerpc64"))]
+ test_simd_arch_mod!(
+ powerpc64,
+ vector_bool_long,
+ vector_double,
+ vector_signed_long,
+ vector_unsigned_long
+ );
+ #[cfg(target_arch = "aarch64")]
+ #[rustfmt::skip]
+ test_simd_arch_mod!(
+ aarch64, float32x2_t, float32x4_t, float64x1_t, float64x2_t, int8x8_t, int8x8x2_t,
+ int8x8x3_t, int8x8x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int16x4_t,
+ int16x8_t, int32x2_t, int32x4_t, int64x1_t, int64x2_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t,
+ poly8x8x4_t, poly8x16_t, poly8x16x2_t, poly8x16x3_t, poly8x16x4_t, poly16x4_t, poly16x8_t,
+ poly64x1_t, poly64x2_t, uint8x8_t, uint8x8x2_t, uint8x8x3_t, uint8x8x4_t, uint8x16_t,
+ uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint16x4_t, uint16x8_t, uint32x2_t, uint32x4_t,
+ uint64x1_t, uint64x2_t
+ );
+ #[cfg(all(feature = "simd-nightly", target_arch = "arm"))]
+ #[rustfmt::skip]
+ test_simd_arch_mod!(arm, int8x4_t, uint8x4_t);
+ }
+ }
+}
+
+#[cfg(kani)]
+mod proofs {
+ use super::*;
+
+ impl kani::Arbitrary for DstLayout {
+ fn any() -> Self {
+ let align: NonZeroUsize = kani::any();
+ let size_info: SizeInfo = kani::any();
+
+ kani::assume(align.is_power_of_two());
+ kani::assume(align < DstLayout::THEORETICAL_MAX_ALIGN);
+
+ // For testing purposes, we most care about instantiations of
+ // `DstLayout` that can correspond to actual Rust types. We use
+ // `Layout` to verify that our `DstLayout` satisfies the validity
+ // conditions of Rust layouts.
+ kani::assume(
+ match size_info {
+ SizeInfo::Sized { _size } => Layout::from_size_align(_size, align.get()),
+ SizeInfo::SliceDst(TrailingSliceLayout { _offset, _elem_size }) => {
+ // `SliceDst`` cannot encode an exact size, but we know
+ // it is at least `_offset` bytes.
+ Layout::from_size_align(_offset, align.get())
+ }
+ }
+ .is_ok(),
+ );
+
+ Self { align: align, size_info: size_info }
+ }
+ }
+
+ impl kani::Arbitrary for SizeInfo {
+ fn any() -> Self {
+ let is_sized: bool = kani::any();
+
+ match is_sized {
+ true => {
+ let size: usize = kani::any();
+
+ kani::assume(size <= isize::MAX as _);
+
+ SizeInfo::Sized { _size: size }
+ }
+ false => SizeInfo::SliceDst(kani::any()),
+ }
+ }
+ }
+
+ impl kani::Arbitrary for TrailingSliceLayout {
+ fn any() -> Self {
+ let elem_size: usize = kani::any();
+ let offset: usize = kani::any();
+
+ kani::assume(elem_size < isize::MAX as _);
+ kani::assume(offset < isize::MAX as _);
+
+ TrailingSliceLayout { _elem_size: elem_size, _offset: offset }
+ }
+ }
+
+ #[kani::proof]
+ fn prove_dst_layout_extend() {
+ use crate::util::{core_layout::padding_needed_for, max, min};
+
+ let base: DstLayout = kani::any();
+ let field: DstLayout = kani::any();
+ let packed: Option<NonZeroUsize> = kani::any();
+
+ if let Some(max_align) = packed {
+ kani::assume(max_align.is_power_of_two());
+ kani::assume(base.align <= max_align);
+ }
+
+ // The base can only be extended if it's sized.
+ kani::assume(matches!(base.size_info, SizeInfo::Sized { .. }));
+ let base_size = if let SizeInfo::Sized { _size: size } = base.size_info {
+ size
+ } else {
+ unreachable!();
+ };
+
+ // Under the above conditions, `DstLayout::extend` will not panic.
+ let composite = base.extend(field, packed);
+
+ // The field's alignment is clamped by `max_align` (i.e., the
+ // `packed` attribute, if any) [1].
+ //
+ // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers:
+ //
+ // The alignments of each field, for the purpose of positioning
+ // fields, is the smaller of the specified alignment and the
+ // alignment of the field's type.
+ let field_align = min(field.align, packed.unwrap_or(DstLayout::THEORETICAL_MAX_ALIGN));
+
+ // The struct's alignment is the maximum of its previous alignment and
+ // `field_align`.
+ assert_eq!(composite.align, max(base.align, field_align));
+
+ // Compute the minimum amount of inter-field padding needed to
+ // satisfy the field's alignment, and offset of the trailing field.
+ // [1]
+ //
+ // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers:
+ //
+ // Inter-field padding is guaranteed to be the minimum required in
+ // order to satisfy each field's (possibly altered) alignment.
+ let padding = padding_needed_for(base_size, field_align);
+ let offset = base_size + padding;
+
+ // For testing purposes, we'll also construct `alloc::Layout`
+ // stand-ins for `DstLayout`, and show that `extend` behaves
+ // comparably on both types.
+ let base_analog = Layout::from_size_align(base_size, base.align.get()).unwrap();
+
+ match field.size_info {
+ SizeInfo::Sized { _size: field_size } => {
+ if let SizeInfo::Sized { _size: composite_size } = composite.size_info {
+ // If the trailing field is sized, the resulting layout
+ // will be sized. Its size will be the sum of the
+ // preceeding layout, the size of the new field, and the
+ // size of inter-field padding between the two.
+ assert_eq!(composite_size, offset + field_size);
+
+ let field_analog =
+ Layout::from_size_align(field_size, field_align.get()).unwrap();
+
+ if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog)
+ {
+ assert_eq!(actual_offset, offset);
+ assert_eq!(actual_composite.size(), composite_size);
+ assert_eq!(actual_composite.align(), composite.align.get());
+ } else {
+ // An error here reflects that composite of `base`
+ // and `field` cannot correspond to a real Rust type
+ // fragment, because such a fragment would violate
+ // the basic invariants of a valid Rust layout. At
+ // the time of writing, `DstLayout` is a little more
+ // permissive than `Layout`, so we don't assert
+ // anything in this branch (e.g., unreachability).
+ }
+ } else {
+ panic!("The composite of two sized layouts must be sized.")
+ }
+ }
+ SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: field_offset,
+ _elem_size: field_elem_size,
+ }) => {
+ if let SizeInfo::SliceDst(TrailingSliceLayout {
+ _offset: composite_offset,
+ _elem_size: composite_elem_size,
+ }) = composite.size_info
+ {
+ // The offset of the trailing slice component is the sum
+ // of the offset of the trailing field and the trailing
+ // slice offset within that field.
+ assert_eq!(composite_offset, offset + field_offset);
+ // The elem size is unchanged.
+ assert_eq!(composite_elem_size, field_elem_size);
+
+ let field_analog =
+ Layout::from_size_align(field_offset, field_align.get()).unwrap();
+
+ if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog)
+ {
+ assert_eq!(actual_offset, offset);
+ assert_eq!(actual_composite.size(), composite_offset);
+ assert_eq!(actual_composite.align(), composite.align.get());
+ } else {
+ // An error here reflects that composite of `base`
+ // and `field` cannot correspond to a real Rust type
+ // fragment, because such a fragment would violate
+ // the basic invariants of a valid Rust layout. At
+ // the time of writing, `DstLayout` is a little more
+ // permissive than `Layout`, so we don't assert
+ // anything in this branch (e.g., unreachability).
+ }
+ } else {
+ panic!("The extension of a layout with a DST must result in a DST.")
+ }
+ }
+ }
+ }
+
+ #[kani::proof]
+ #[kani::should_panic]
+ fn prove_dst_layout_extend_dst_panics() {
+ let base: DstLayout = kani::any();
+ let field: DstLayout = kani::any();
+ let packed: Option<NonZeroUsize> = kani::any();
+
+ if let Some(max_align) = packed {
+ kani::assume(max_align.is_power_of_two());
+ kani::assume(base.align <= max_align);
+ }
+
+ kani::assume(matches!(base.size_info, SizeInfo::SliceDst(..)));
+
+ let _ = base.extend(field, packed);
+ }
+
+ #[kani::proof]
+ fn prove_dst_layout_pad_to_align() {
+ use crate::util::core_layout::padding_needed_for;
+
+ let layout: DstLayout = kani::any();
+
+ let padded: DstLayout = layout.pad_to_align();
+
+ // Calling `pad_to_align` does not alter the `DstLayout`'s alignment.
+ assert_eq!(padded.align, layout.align);
+
+ if let SizeInfo::Sized { _size: unpadded_size } = layout.size_info {
+ if let SizeInfo::Sized { _size: padded_size } = padded.size_info {
+ // If the layout is sized, it will remain sized after padding is
+ // added. Its sum will be its unpadded size and the size of the
+ // trailing padding needed to satisfy its alignment
+ // requirements.
+ let padding = padding_needed_for(unpadded_size, layout.align);
+ assert_eq!(padded_size, unpadded_size + padding);
+
+ // Prove that calling `DstLayout::pad_to_align` behaves
+ // identically to `Layout::pad_to_align`.
+ let layout_analog =
+ Layout::from_size_align(unpadded_size, layout.align.get()).unwrap();
+ let padded_analog = layout_analog.pad_to_align();
+ assert_eq!(padded_analog.align(), layout.align.get());
+ assert_eq!(padded_analog.size(), padded_size);
+ } else {
+ panic!("The padding of a sized layout must result in a sized layout.")
+ }
+ } else {
+ // If the layout is a DST, padding cannot be statically added.
+ assert_eq!(padded.size_info, layout.size_info);
+ }
+ }
+}
diff --git a/third_party/rust/zerocopy/src/macro_util.rs b/third_party/rust/zerocopy/src/macro_util.rs
new file mode 100644
index 0000000000..24fec4f015
--- /dev/null
+++ b/third_party/rust/zerocopy/src/macro_util.rs
@@ -0,0 +1,670 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+//! Utilities used by macros and by `zerocopy-derive`.
+//!
+//! These are defined here `zerocopy` rather than in code generated by macros or
+//! by `zerocopy-derive` so that they can be compiled once rather than
+//! recompiled for every invocation (e.g., if they were defined in generated
+//! code, then deriving `AsBytes` and `FromBytes` on three different types would
+//! result in the code in question being emitted and compiled six different
+//! times).
+
+#![allow(missing_debug_implementations)]
+
+use core::{marker::PhantomData, mem::ManuallyDrop};
+
+// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
+// `cfg` when `size_of_val_raw` is stabilized.
+#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+use core::ptr::{self, NonNull};
+
+/// A compile-time check that should be one particular value.
+pub trait ShouldBe<const VALUE: bool> {}
+
+/// A struct for checking whether `T` contains padding.
+pub struct HasPadding<T: ?Sized, const VALUE: bool>(PhantomData<T>);
+
+impl<T: ?Sized, const VALUE: bool> ShouldBe<VALUE> for HasPadding<T, VALUE> {}
+
+/// A type whose size is equal to `align_of::<T>()`.
+#[repr(C)]
+pub struct AlignOf<T> {
+ // This field ensures that:
+ // - The size is always at least 1 (the minimum possible alignment).
+ // - If the alignment is greater than 1, Rust has to round up to the next
+ // multiple of it in order to make sure that `Align`'s size is a multiple
+ // of that alignment. Without this field, its size could be 0, which is a
+ // valid multiple of any alignment.
+ _u: u8,
+ _a: [T; 0],
+}
+
+impl<T> AlignOf<T> {
+ #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ pub fn into_t(self) -> T {
+ unreachable!()
+ }
+}
+
+/// A type whose size is equal to `max(align_of::<T>(), align_of::<U>())`.
+#[repr(C)]
+pub union MaxAlignsOf<T, U> {
+ _t: ManuallyDrop<AlignOf<T>>,
+ _u: ManuallyDrop<AlignOf<U>>,
+}
+
+impl<T, U> MaxAlignsOf<T, U> {
+ #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ unreachable!()
+ }
+}
+
+const _64K: usize = 1 << 16;
+
+// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
+// `cfg` when `size_of_val_raw` is stabilized.
+#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+#[repr(C, align(65536))]
+struct Aligned64kAllocation([u8; _64K]);
+
+/// A pointer to an aligned allocation of size 2^16.
+///
+/// # Safety
+///
+/// `ALIGNED_64K_ALLOCATION` is guaranteed to point to the entirety of an
+/// allocation with size and alignment 2^16, and to have valid provenance.
+// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
+// `cfg` when `size_of_val_raw` is stabilized.
+#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+pub const ALIGNED_64K_ALLOCATION: NonNull<[u8]> = {
+ const REF: &Aligned64kAllocation = &Aligned64kAllocation([0; _64K]);
+ let ptr: *const Aligned64kAllocation = REF;
+ let ptr: *const [u8] = ptr::slice_from_raw_parts(ptr.cast(), _64K);
+ // SAFETY:
+ // - `ptr` is derived from a Rust reference, which is guaranteed to be
+ // non-null.
+ // - `ptr` is derived from an `&Aligned64kAllocation`, which has size and
+ // alignment `_64K` as promised. Its length is initialized to `_64K`,
+ // which means that it refers to the entire allocation.
+ // - `ptr` is derived from a Rust reference, which is guaranteed to have
+ // valid provenance.
+ //
+ // TODO(#429): Once `NonNull::new_unchecked` docs document that it preserves
+ // provenance, cite those docs.
+ // TODO: Replace this `as` with `ptr.cast_mut()` once our MSRV >= 1.65
+ #[allow(clippy::as_conversions)]
+ unsafe {
+ NonNull::new_unchecked(ptr as *mut _)
+ }
+};
+
+/// Computes the offset of the base of the field `$trailing_field_name` within
+/// the type `$ty`.
+///
+/// `trailing_field_offset!` produces code which is valid in a `const` context.
+// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
+// `cfg` when `size_of_val_raw` is stabilized.
+#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
+#[macro_export]
+macro_rules! trailing_field_offset {
+ ($ty:ty, $trailing_field_name:tt) => {{
+ let min_size = {
+ let zero_elems: *const [()] =
+ $crate::macro_util::core_reexport::ptr::slice_from_raw_parts(
+ $crate::macro_util::core_reexport::ptr::NonNull::<()>::dangling()
+ .as_ptr()
+ .cast_const(),
+ 0,
+ );
+ // SAFETY:
+ // - If `$ty` is `Sized`, `size_of_val_raw` is always safe to call.
+ // - Otherwise:
+ // - If `$ty` is not a slice DST, this pointer conversion will
+ // fail due to "mismatched vtable kinds", and compilation will
+ // fail.
+ // - If `$ty` is a slice DST, the safety requirement is that "the
+ // length of the slice tail must be an initialized integer, and
+ // the size of the entire value (dynamic tail length +
+ // statically sized prefix) must fit in isize." The length is
+ // initialized to 0 above, and Rust guarantees that no type's
+ // minimum size may overflow `isize`. [1]
+ //
+ // [1] TODO(#429),
+ // TODO(https://github.com/rust-lang/unsafe-code-guidelines/issues/465#issuecomment-1782206516):
+ // Citation for this?
+ unsafe {
+ #[allow(clippy::as_conversions)]
+ $crate::macro_util::core_reexport::mem::size_of_val_raw(zero_elems as *const $ty)
+ }
+ };
+
+ assert!(min_size <= _64K);
+
+ #[allow(clippy::as_conversions)]
+ let ptr = ALIGNED_64K_ALLOCATION.as_ptr() as *const $ty;
+
+ // SAFETY:
+ // - Thanks to the preceding `assert!`, we know that the value with zero
+ // elements fits in `_64K` bytes, and thus in the allocation addressed
+ // by `ALIGNED_64K_ALLOCATION`. The offset of the trailing field is
+ // guaranteed to be no larger than this size, so this field projection
+ // is guaranteed to remain in-bounds of its allocation.
+ // - Because the minimum size is no larger than `_64K` bytes, and
+ // because an object's size must always be a multiple of its alignment
+ // [1], we know that `$ty`'s alignment is no larger than `_64K`. The
+ // allocation addressed by `ALIGNED_64K_ALLOCATION` is guaranteed to
+ // be aligned to `_64K`, so `ptr` is guaranteed to satisfy `$ty`'s
+ // alignment.
+ //
+ // Note that, as of [2], this requirement is technically unnecessary
+ // for Rust versions >= 1.75.0, but no harm in guaranteeing it anyway
+ // until we bump our MSRV.
+ //
+ // [1] Per https://doc.rust-lang.org/reference/type-layout.html:
+ //
+ // The size of a value is always a multiple of its alignment.
+ //
+ // [2] https://github.com/rust-lang/reference/pull/1387
+ let field = unsafe {
+ $crate::macro_util::core_reexport::ptr::addr_of!((*ptr).$trailing_field_name)
+ };
+ // SAFETY:
+ // - Both `ptr` and `field` are derived from the same allocated object.
+ // - By the preceding safety comment, `field` is in bounds of that
+ // allocated object.
+ // - The distance, in bytes, between `ptr` and `field` is required to be
+ // a multiple of the size of `u8`, which is trivially true because
+ // `u8`'s size is 1.
+ // - The distance, in bytes, cannot overflow `isize`. This is guaranteed
+ // because no allocated object can have a size larger than can fit in
+ // `isize`. [1]
+ // - The distance being in-bounds cannot rely on wrapping around the
+ // address space. This is guaranteed because the same is guaranteed of
+ // allocated objects. [1]
+ //
+ // [1] TODO(#429), TODO(https://github.com/rust-lang/rust/pull/116675):
+ // Once these are guaranteed in the Reference, cite it.
+ let offset = unsafe { field.cast::<u8>().offset_from(ptr.cast::<u8>()) };
+ // Guaranteed not to be lossy: `field` comes after `ptr`, so the offset
+ // from `ptr` to `field` is guaranteed to be positive.
+ assert!(offset >= 0);
+ Some(
+ #[allow(clippy::as_conversions)]
+ {
+ offset as usize
+ },
+ )
+ }};
+}
+
+/// Computes alignment of `$ty: ?Sized`.
+///
+/// `align_of!` produces code which is valid in a `const` context.
+// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
+// `cfg` when `size_of_val_raw` is stabilized.
+#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
+#[macro_export]
+macro_rules! align_of {
+ ($ty:ty) => {{
+ // SAFETY: `OffsetOfTrailingIsAlignment` is `repr(C)`, and its layout is
+ // guaranteed [1] to begin with the single-byte layout for `_byte`,
+ // followed by the padding needed to align `_trailing`, then the layout
+ // for `_trailing`, and finally any trailing padding bytes needed to
+ // correctly-align the entire struct.
+ //
+ // This macro computes the alignment of `$ty` by counting the number of
+ // bytes preceeding `_trailing`. For instance, if the alignment of `$ty`
+ // is `1`, then no padding is required align `_trailing` and it will be
+ // located immediately after `_byte` at offset 1. If the alignment of
+ // `$ty` is 2, then a single padding byte is required before
+ // `_trailing`, and `_trailing` will be located at offset 2.
+
+ // This correspondence between offset and alignment holds for all valid
+ // Rust alignments, and we confirm this exhaustively (or, at least up to
+ // the maximum alignment supported by `trailing_field_offset!`) in
+ // `test_align_of_dst`.
+ //
+ // [1]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprc
+
+ #[repr(C)]
+ struct OffsetOfTrailingIsAlignment {
+ _byte: u8,
+ _trailing: $ty,
+ }
+
+ trailing_field_offset!(OffsetOfTrailingIsAlignment, _trailing)
+ }};
+}
+
+/// Does the struct type `$t` have padding?
+///
+/// `$ts` is the list of the type of every field in `$t`. `$t` must be a
+/// struct type, or else `struct_has_padding!`'s result may be meaningless.
+///
+/// Note that `struct_has_padding!`'s results are independent of `repr` since
+/// they only consider the size of the type and the sizes of the fields.
+/// Whatever the repr, the size of the type already takes into account any
+/// padding that the compiler has decided to add. Structs with well-defined
+/// representations (such as `repr(C)`) can use this macro to check for padding.
+/// Note that while this may yield some consistent value for some `repr(Rust)`
+/// structs, it is not guaranteed across platforms or compilations.
+#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
+#[macro_export]
+macro_rules! struct_has_padding {
+ ($t:ty, $($ts:ty),*) => {
+ core::mem::size_of::<$t>() > 0 $(+ core::mem::size_of::<$ts>())*
+ };
+}
+
+/// Does the union type `$t` have padding?
+///
+/// `$ts` is the list of the type of every field in `$t`. `$t` must be a
+/// union type, or else `union_has_padding!`'s result may be meaningless.
+///
+/// Note that `union_has_padding!`'s results are independent of `repr` since
+/// they only consider the size of the type and the sizes of the fields.
+/// Whatever the repr, the size of the type already takes into account any
+/// padding that the compiler has decided to add. Unions with well-defined
+/// representations (such as `repr(C)`) can use this macro to check for padding.
+/// Note that while this may yield some consistent value for some `repr(Rust)`
+/// unions, it is not guaranteed across platforms or compilations.
+#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
+#[macro_export]
+macro_rules! union_has_padding {
+ ($t:ty, $($ts:ty),*) => {
+ false $(|| core::mem::size_of::<$t>() != core::mem::size_of::<$ts>())*
+ };
+}
+
+/// Does `t` have alignment greater than or equal to `u`? If not, this macro
+/// produces a compile error. It must be invoked in a dead codepath. This is
+/// used in `transmute_ref!` and `transmute_mut!`.
+#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
+#[macro_export]
+macro_rules! assert_align_gt_eq {
+ ($t:ident, $u: ident) => {{
+ // The comments here should be read in the context of this macro's
+ // invocations in `transmute_ref!` and `transmute_mut!`.
+ if false {
+ // The type wildcard in this bound is inferred to be `T` because
+ // `align_of.into_t()` is assigned to `t` (which has type `T`).
+ let align_of: $crate::macro_util::AlignOf<_> = unreachable!();
+ $t = align_of.into_t();
+ // `max_aligns` is inferred to have type `MaxAlignsOf<T, U>` because
+ // of the inferred types of `t` and `u`.
+ let mut max_aligns = $crate::macro_util::MaxAlignsOf::new($t, $u);
+
+ // This transmute will only compile successfully if
+ // `align_of::<T>() == max(align_of::<T>(), align_of::<U>())` - in
+ // other words, if `align_of::<T>() >= align_of::<U>()`.
+ //
+ // SAFETY: This code is never run.
+ max_aligns = unsafe { $crate::macro_util::core_reexport::mem::transmute(align_of) };
+ } else {
+ loop {}
+ }
+ }};
+}
+
+/// Do `t` and `u` have the same size? If not, this macro produces a compile
+/// error. It must be invoked in a dead codepath. This is used in
+/// `transmute_ref!` and `transmute_mut!`.
+#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
+#[macro_export]
+macro_rules! assert_size_eq {
+ ($t:ident, $u: ident) => {{
+ // The comments here should be read in the context of this macro's
+ // invocations in `transmute_ref!` and `transmute_mut!`.
+ if false {
+ // SAFETY: This code is never run.
+ $u = unsafe {
+ // Clippy: It's okay to transmute a type to itself.
+ #[allow(clippy::useless_transmute)]
+ $crate::macro_util::core_reexport::mem::transmute($t)
+ };
+ } else {
+ loop {}
+ }
+ }};
+}
+
+/// Transmutes a reference of one type to a reference of another type.
+///
+/// # Safety
+///
+/// The caller must guarantee that:
+/// - `Src: AsBytes`
+/// - `Dst: FromBytes`
+/// - `size_of::<Src>() == size_of::<Dst>()`
+/// - `align_of::<Src>() >= align_of::<Dst>()`
+#[inline(always)]
+pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ src: &'src Src,
+) -> &'dst Dst {
+ let src: *const Src = src;
+ let dst = src.cast::<Dst>();
+ // SAFETY:
+ // - We know that it is sound to view the target type of the input reference
+ // (`Src`) as the target type of the output reference (`Dst`) because the
+ // caller has guaranteed that `Src: AsBytes`, `Dst: FromBytes`, and
+ // `size_of::<Src>() == size_of::<Dst>()`.
+ // - We know that there are no `UnsafeCell`s, and thus we don't have to
+ // worry about `UnsafeCell` overlap, because `Src: AsBytes` and `Dst:
+ // FromBytes` both forbid `UnsafeCell`s.
+ // - The caller has guaranteed that alignment is not increased.
+ // - We know that the returned lifetime will not outlive the input lifetime
+ // thanks to the lifetime bounds on this function.
+ unsafe { &*dst }
+}
+
+/// Transmutes a mutable reference of one type to a mutable reference of another
+/// type.
+///
+/// # Safety
+///
+/// The caller must guarantee that:
+/// - `Src: FromBytes + AsBytes`
+/// - `Dst: FromBytes + AsBytes`
+/// - `size_of::<Src>() == size_of::<Dst>()`
+/// - `align_of::<Src>() >= align_of::<Dst>()`
+#[inline(always)]
+pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ src: &'src mut Src,
+) -> &'dst mut Dst {
+ let src: *mut Src = src;
+ let dst = src.cast::<Dst>();
+ // SAFETY:
+ // - We know that it is sound to view the target type of the input reference
+ // (`Src`) as the target type of the output reference (`Dst`) and
+ // vice-versa because the caller has guaranteed that `Src: FromBytes +
+ // AsBytes`, `Dst: FromBytes + AsBytes`, and `size_of::<Src>() ==
+ // size_of::<Dst>()`.
+ // - We know that there are no `UnsafeCell`s, and thus we don't have to
+ // worry about `UnsafeCell` overlap, because `Src: FromBytes + AsBytes`
+ // and `Dst: FromBytes + AsBytes` forbid `UnsafeCell`s.
+ // - The caller has guaranteed that alignment is not increased.
+ // - We know that the returned lifetime will not outlive the input lifetime
+ // thanks to the lifetime bounds on this function.
+ unsafe { &mut *dst }
+}
+
+// NOTE: We can't change this to a `pub use core as core_reexport` until [1] is
+// fixed or we update to a semver-breaking version (as of this writing, 0.8.0)
+// on the `main` branch.
+//
+// [1] https://github.com/obi1kenobi/cargo-semver-checks/issues/573
+pub mod core_reexport {
+ pub use core::*;
+
+ pub mod mem {
+ pub use core::mem::*;
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use core::mem;
+
+ use super::*;
+ use crate::util::testutil::*;
+
+ #[test]
+ fn test_align_of() {
+ macro_rules! test {
+ ($ty:ty) => {
+ assert_eq!(mem::size_of::<AlignOf<$ty>>(), mem::align_of::<$ty>());
+ };
+ }
+
+ test!(());
+ test!(u8);
+ test!(AU64);
+ test!([AU64; 2]);
+ }
+
+ #[test]
+ fn test_max_aligns_of() {
+ macro_rules! test {
+ ($t:ty, $u:ty) => {
+ assert_eq!(
+ mem::size_of::<MaxAlignsOf<$t, $u>>(),
+ core::cmp::max(mem::align_of::<$t>(), mem::align_of::<$u>())
+ );
+ };
+ }
+
+ test!(u8, u8);
+ test!(u8, AU64);
+ test!(AU64, u8);
+ }
+
+ #[test]
+ fn test_typed_align_check() {
+ // Test that the type-based alignment check used in
+ // `assert_align_gt_eq!` behaves as expected.
+
+ macro_rules! assert_t_align_gteq_u_align {
+ ($t:ty, $u:ty, $gteq:expr) => {
+ assert_eq!(
+ mem::size_of::<MaxAlignsOf<$t, $u>>() == mem::size_of::<AlignOf<$t>>(),
+ $gteq
+ );
+ };
+ }
+
+ assert_t_align_gteq_u_align!(u8, u8, true);
+ assert_t_align_gteq_u_align!(AU64, AU64, true);
+ assert_t_align_gteq_u_align!(AU64, u8, true);
+ assert_t_align_gteq_u_align!(u8, AU64, false);
+ }
+
+ // TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove
+ // this `cfg` when `size_of_val_raw` is stabilized.
+ #[allow(clippy::decimal_literal_representation)]
+ #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+ #[test]
+ fn test_trailing_field_offset() {
+ assert_eq!(mem::align_of::<Aligned64kAllocation>(), _64K);
+
+ macro_rules! test {
+ (#[$cfg:meta] ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => {{
+ #[$cfg]
+ struct Test($($ts,)* $trailing_field_ty);
+ assert_eq!(test!(@offset $($ts),* ; $trailing_field_ty), $expect);
+ }};
+ (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => {
+ test!(#[$cfg] ($($ts),* ; $trailing_field_ty) => $expect);
+ test!($(#[$cfgs])* ($($ts),* ; $trailing_field_ty) => $expect);
+ };
+ (@offset ; $_trailing:ty) => { trailing_field_offset!(Test, 0) };
+ (@offset $_t:ty ; $_trailing:ty) => { trailing_field_offset!(Test, 1) };
+ }
+
+ test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; u8) => Some(0));
+ test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; [u8]) => Some(0));
+ test!(#[repr(C)] #[repr(packed)] (u8; u8) => Some(1));
+ test!(#[repr(C)] (; AU64) => Some(0));
+ test!(#[repr(C)] (; [AU64]) => Some(0));
+ test!(#[repr(C)] (u8; AU64) => Some(8));
+ test!(#[repr(C)] (u8; [AU64]) => Some(8));
+ test!(#[repr(C)] (; Nested<u8, AU64>) => Some(0));
+ test!(#[repr(C)] (; Nested<u8, [AU64]>) => Some(0));
+ test!(#[repr(C)] (u8; Nested<u8, AU64>) => Some(8));
+ test!(#[repr(C)] (u8; Nested<u8, [AU64]>) => Some(8));
+
+ // Test that `packed(N)` limits the offset of the trailing field.
+ test!(#[repr(C, packed( 1))] (u8; elain::Align< 2>) => Some( 1));
+ test!(#[repr(C, packed( 2))] (u8; elain::Align< 4>) => Some( 2));
+ test!(#[repr(C, packed( 4))] (u8; elain::Align< 8>) => Some( 4));
+ test!(#[repr(C, packed( 8))] (u8; elain::Align< 16>) => Some( 8));
+ test!(#[repr(C, packed( 16))] (u8; elain::Align< 32>) => Some( 16));
+ test!(#[repr(C, packed( 32))] (u8; elain::Align< 64>) => Some( 32));
+ test!(#[repr(C, packed( 64))] (u8; elain::Align< 128>) => Some( 64));
+ test!(#[repr(C, packed( 128))] (u8; elain::Align< 256>) => Some( 128));
+ test!(#[repr(C, packed( 256))] (u8; elain::Align< 512>) => Some( 256));
+ test!(#[repr(C, packed( 512))] (u8; elain::Align< 1024>) => Some( 512));
+ test!(#[repr(C, packed( 1024))] (u8; elain::Align< 2048>) => Some( 1024));
+ test!(#[repr(C, packed( 2048))] (u8; elain::Align< 4096>) => Some( 2048));
+ test!(#[repr(C, packed( 4096))] (u8; elain::Align< 8192>) => Some( 4096));
+ test!(#[repr(C, packed( 8192))] (u8; elain::Align< 16384>) => Some( 8192));
+ test!(#[repr(C, packed( 16384))] (u8; elain::Align< 32768>) => Some( 16384));
+ test!(#[repr(C, packed( 32768))] (u8; elain::Align< 65536>) => Some( 32768));
+ test!(#[repr(C, packed( 65536))] (u8; elain::Align< 131072>) => Some( 65536));
+ /* Alignments above 65536 are not yet supported.
+ test!(#[repr(C, packed( 131072))] (u8; elain::Align< 262144>) => Some( 131072));
+ test!(#[repr(C, packed( 262144))] (u8; elain::Align< 524288>) => Some( 262144));
+ test!(#[repr(C, packed( 524288))] (u8; elain::Align< 1048576>) => Some( 524288));
+ test!(#[repr(C, packed( 1048576))] (u8; elain::Align< 2097152>) => Some( 1048576));
+ test!(#[repr(C, packed( 2097152))] (u8; elain::Align< 4194304>) => Some( 2097152));
+ test!(#[repr(C, packed( 4194304))] (u8; elain::Align< 8388608>) => Some( 4194304));
+ test!(#[repr(C, packed( 8388608))] (u8; elain::Align< 16777216>) => Some( 8388608));
+ test!(#[repr(C, packed( 16777216))] (u8; elain::Align< 33554432>) => Some( 16777216));
+ test!(#[repr(C, packed( 33554432))] (u8; elain::Align< 67108864>) => Some( 33554432));
+ test!(#[repr(C, packed( 67108864))] (u8; elain::Align< 33554432>) => Some( 67108864));
+ test!(#[repr(C, packed( 33554432))] (u8; elain::Align<134217728>) => Some( 33554432));
+ test!(#[repr(C, packed(134217728))] (u8; elain::Align<268435456>) => Some(134217728));
+ test!(#[repr(C, packed(268435456))] (u8; elain::Align<268435456>) => Some(268435456));
+ */
+
+ // Test that `align(N)` does not limit the offset of the trailing field.
+ test!(#[repr(C, align( 1))] (u8; elain::Align< 2>) => Some( 2));
+ test!(#[repr(C, align( 2))] (u8; elain::Align< 4>) => Some( 4));
+ test!(#[repr(C, align( 4))] (u8; elain::Align< 8>) => Some( 8));
+ test!(#[repr(C, align( 8))] (u8; elain::Align< 16>) => Some( 16));
+ test!(#[repr(C, align( 16))] (u8; elain::Align< 32>) => Some( 32));
+ test!(#[repr(C, align( 32))] (u8; elain::Align< 64>) => Some( 64));
+ test!(#[repr(C, align( 64))] (u8; elain::Align< 128>) => Some( 128));
+ test!(#[repr(C, align( 128))] (u8; elain::Align< 256>) => Some( 256));
+ test!(#[repr(C, align( 256))] (u8; elain::Align< 512>) => Some( 512));
+ test!(#[repr(C, align( 512))] (u8; elain::Align< 1024>) => Some( 1024));
+ test!(#[repr(C, align( 1024))] (u8; elain::Align< 2048>) => Some( 2048));
+ test!(#[repr(C, align( 2048))] (u8; elain::Align< 4096>) => Some( 4096));
+ test!(#[repr(C, align( 4096))] (u8; elain::Align< 8192>) => Some( 8192));
+ test!(#[repr(C, align( 8192))] (u8; elain::Align< 16384>) => Some( 16384));
+ test!(#[repr(C, align( 16384))] (u8; elain::Align< 32768>) => Some( 32768));
+ test!(#[repr(C, align( 32768))] (u8; elain::Align< 65536>) => Some( 65536));
+ /* Alignments above 65536 are not yet supported.
+ test!(#[repr(C, align( 65536))] (u8; elain::Align< 131072>) => Some( 131072));
+ test!(#[repr(C, align( 131072))] (u8; elain::Align< 262144>) => Some( 262144));
+ test!(#[repr(C, align( 262144))] (u8; elain::Align< 524288>) => Some( 524288));
+ test!(#[repr(C, align( 524288))] (u8; elain::Align< 1048576>) => Some( 1048576));
+ test!(#[repr(C, align( 1048576))] (u8; elain::Align< 2097152>) => Some( 2097152));
+ test!(#[repr(C, align( 2097152))] (u8; elain::Align< 4194304>) => Some( 4194304));
+ test!(#[repr(C, align( 4194304))] (u8; elain::Align< 8388608>) => Some( 8388608));
+ test!(#[repr(C, align( 8388608))] (u8; elain::Align< 16777216>) => Some( 16777216));
+ test!(#[repr(C, align( 16777216))] (u8; elain::Align< 33554432>) => Some( 33554432));
+ test!(#[repr(C, align( 33554432))] (u8; elain::Align< 67108864>) => Some( 67108864));
+ test!(#[repr(C, align( 67108864))] (u8; elain::Align< 33554432>) => Some( 33554432));
+ test!(#[repr(C, align( 33554432))] (u8; elain::Align<134217728>) => Some(134217728));
+ test!(#[repr(C, align(134217728))] (u8; elain::Align<268435456>) => Some(268435456));
+ */
+ }
+
+ // TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove
+ // this `cfg` when `size_of_val_raw` is stabilized.
+ #[allow(clippy::decimal_literal_representation)]
+ #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+ #[test]
+ fn test_align_of_dst() {
+ // Test that `align_of!` correctly computes the alignment of DSTs.
+ assert_eq!(align_of!([elain::Align<1>]), Some(1));
+ assert_eq!(align_of!([elain::Align<2>]), Some(2));
+ assert_eq!(align_of!([elain::Align<4>]), Some(4));
+ assert_eq!(align_of!([elain::Align<8>]), Some(8));
+ assert_eq!(align_of!([elain::Align<16>]), Some(16));
+ assert_eq!(align_of!([elain::Align<32>]), Some(32));
+ assert_eq!(align_of!([elain::Align<64>]), Some(64));
+ assert_eq!(align_of!([elain::Align<128>]), Some(128));
+ assert_eq!(align_of!([elain::Align<256>]), Some(256));
+ assert_eq!(align_of!([elain::Align<512>]), Some(512));
+ assert_eq!(align_of!([elain::Align<1024>]), Some(1024));
+ assert_eq!(align_of!([elain::Align<2048>]), Some(2048));
+ assert_eq!(align_of!([elain::Align<4096>]), Some(4096));
+ assert_eq!(align_of!([elain::Align<8192>]), Some(8192));
+ assert_eq!(align_of!([elain::Align<16384>]), Some(16384));
+ assert_eq!(align_of!([elain::Align<32768>]), Some(32768));
+ assert_eq!(align_of!([elain::Align<65536>]), Some(65536));
+ /* Alignments above 65536 are not yet supported.
+ assert_eq!(align_of!([elain::Align<131072>]), Some(131072));
+ assert_eq!(align_of!([elain::Align<262144>]), Some(262144));
+ assert_eq!(align_of!([elain::Align<524288>]), Some(524288));
+ assert_eq!(align_of!([elain::Align<1048576>]), Some(1048576));
+ assert_eq!(align_of!([elain::Align<2097152>]), Some(2097152));
+ assert_eq!(align_of!([elain::Align<4194304>]), Some(4194304));
+ assert_eq!(align_of!([elain::Align<8388608>]), Some(8388608));
+ assert_eq!(align_of!([elain::Align<16777216>]), Some(16777216));
+ assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432));
+ assert_eq!(align_of!([elain::Align<67108864>]), Some(67108864));
+ assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432));
+ assert_eq!(align_of!([elain::Align<134217728>]), Some(134217728));
+ assert_eq!(align_of!([elain::Align<268435456>]), Some(268435456));
+ */
+ }
+
+ #[test]
+ fn test_struct_has_padding() {
+ // Test that, for each provided repr, `struct_has_padding!` reports the
+ // expected value.
+ macro_rules! test {
+ (#[$cfg:meta] ($($ts:ty),*) => $expect:expr) => {{
+ #[$cfg]
+ struct Test($($ts),*);
+ assert_eq!(struct_has_padding!(Test, $($ts),*), $expect);
+ }};
+ (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),*) => $expect:expr) => {
+ test!(#[$cfg] ($($ts),*) => $expect);
+ test!($(#[$cfgs])* ($($ts),*) => $expect);
+ };
+ }
+
+ test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] () => false);
+ test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8) => false);
+ test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8, ()) => false);
+ test!(#[repr(C)] #[repr(packed)] (u8, u8) => false);
+
+ test!(#[repr(C)] (u8, AU64) => true);
+ // Rust won't let you put `#[repr(packed)]` on a type which contains a
+ // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here.
+ // It's not ideal, but it definitely has align > 1 on /some/ of our CI
+ // targets, and this isn't a particularly complex macro we're testing
+ // anyway.
+ test!(#[repr(packed)] (u8, u64) => false);
+ }
+
+ #[test]
+ fn test_union_has_padding() {
+ // Test that, for each provided repr, `union_has_padding!` reports the
+ // expected value.
+ macro_rules! test {
+ (#[$cfg:meta] {$($fs:ident: $ts:ty),*} => $expect:expr) => {{
+ #[$cfg]
+ #[allow(unused)] // fields are never read
+ union Test{ $($fs: $ts),* }
+ assert_eq!(union_has_padding!(Test, $($ts),*), $expect);
+ }};
+ (#[$cfg:meta] $(#[$cfgs:meta])* {$($fs:ident: $ts:ty),*} => $expect:expr) => {
+ test!(#[$cfg] {$($fs: $ts),*} => $expect);
+ test!($(#[$cfgs])* {$($fs: $ts),*} => $expect);
+ };
+ }
+
+ test!(#[repr(C)] #[repr(packed)] {a: u8} => false);
+ test!(#[repr(C)] #[repr(packed)] {a: u8, b: u8} => false);
+
+ // Rust won't let you put `#[repr(packed)]` on a type which contains a
+ // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here.
+ // It's not ideal, but it definitely has align > 1 on /some/ of our CI
+ // targets, and this isn't a particularly complex macro we're testing
+ // anyway.
+ test!(#[repr(C)] #[repr(packed)] {a: u8, b: u64} => true);
+ }
+}
diff --git a/third_party/rust/zerocopy/src/macros.rs b/third_party/rust/zerocopy/src/macros.rs
new file mode 100644
index 0000000000..2da78af7df
--- /dev/null
+++ b/third_party/rust/zerocopy/src/macros.rs
@@ -0,0 +1,417 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+/// Documents multiple unsafe blocks with a single safety comment.
+///
+/// Invoked as:
+///
+/// ```rust,ignore
+/// safety_comment! {
+/// // Non-doc comments come first.
+/// /// SAFETY:
+/// /// Safety comment starts on its own line.
+/// macro_1!(args);
+/// macro_2! { args };
+/// /// SAFETY:
+/// /// Subsequent safety comments are allowed but not required.
+/// macro_3! { args };
+/// }
+/// ```
+///
+/// The macro invocations are emitted, each decorated with the following
+/// attribute: `#[allow(clippy::undocumented_unsafe_blocks)]`.
+macro_rules! safety_comment {
+ (#[doc = r" SAFETY:"] $($(#[$attr:meta])* $macro:ident!$args:tt;)*) => {
+ #[allow(clippy::undocumented_unsafe_blocks, unused_attributes)]
+ const _: () = { $($(#[$attr])* $macro!$args;)* };
+ }
+}
+
+/// Unsafely implements trait(s) for a type.
+///
+/// # Safety
+///
+/// The trait impl must be sound.
+///
+/// When implementing `TryFromBytes`:
+/// - If no `is_bit_valid` impl is provided, then it must be valid for
+/// `is_bit_valid` to unconditionally return `true`. In other words, it must
+/// be the case that any initialized sequence of bytes constitutes a valid
+/// instance of `$ty`.
+/// - If an `is_bit_valid` impl is provided, then:
+/// - Regardless of whether the provided closure takes a `Ptr<$repr>` or
+/// `&$repr` argument, it must be the case that, given `t: *mut $ty` and
+/// `let r = t as *mut $repr`, `r` refers to an object of equal or lesser
+/// size than the object referred to by `t`.
+/// - If the provided closure takes a `&$repr` argument, then given a `Ptr<'a,
+/// $ty>` which satisfies the preconditions of
+/// `TryFromBytes::<$ty>::is_bit_valid`, it must be guaranteed that the
+/// memory referenced by that `Ptr` always contains a valid `$repr`.
+/// - The alignment of `$repr` is less than or equal to the alignment of
+/// `$ty`.
+/// - The impl of `is_bit_valid` must only return `true` for its argument
+/// `Ptr<$repr>` if the original `Ptr<$ty>` refers to a valid `$ty`.
+macro_rules! unsafe_impl {
+ // Implement `$trait` for `$ty` with no bounds.
+ ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident: &$repr:ty| $is_bit_valid:expr)?) => {
+ $(#[$attr])*
+ unsafe impl $trait for $ty {
+ unsafe_impl!(@method $trait $(; |$candidate: &$repr| $is_bit_valid)?);
+ }
+ };
+ // Implement all `$traits` for `$ty` with no bounds.
+ ($ty:ty: $($traits:ident),*) => {
+ $( unsafe_impl!($ty: $traits); )*
+ };
+ // This arm is identical to the following one, except it contains a
+ // preceding `const`. If we attempt to handle these with a single arm, there
+ // is an inherent ambiguity between `const` (the keyword) and `const` (the
+ // ident match for `$tyvar:ident`).
+ //
+ // To explain how this works, consider the following invocation:
+ //
+ // unsafe_impl!(const N: usize, T: ?Sized + Copy => Clone for Foo<T>);
+ //
+ // In this invocation, here are the assignments to meta-variables:
+ //
+ // |---------------|------------|
+ // | Meta-variable | Assignment |
+ // |---------------|------------|
+ // | $constname | N |
+ // | $constty | usize |
+ // | $tyvar | T |
+ // | $optbound | Sized |
+ // | $bound | Copy |
+ // | $trait | Clone |
+ // | $ty | Foo<T> |
+ // |---------------|------------|
+ //
+ // The following arm has the same behavior with the exception of the lack of
+ // support for a leading `const` parameter.
+ (
+ $(#[$attr:meta])*
+ const $constname:ident : $constty:ident $(,)?
+ $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
+ => $trait:ident for $ty:ty $(; |$candidate:ident $(: &$ref_repr:ty)? $(: Ptr<$ptr_repr:ty>)?| $is_bit_valid:expr)?
+ ) => {
+ unsafe_impl!(
+ @inner
+ $(#[$attr])*
+ @const $constname: $constty,
+ $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
+ => $trait for $ty $(; |$candidate $(: &$ref_repr)? $(: Ptr<$ptr_repr>)?| $is_bit_valid)?
+ );
+ };
+ (
+ $(#[$attr:meta])*
+ $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
+ => $trait:ident for $ty:ty $(; |$candidate:ident $(: &$ref_repr:ty)? $(: Ptr<$ptr_repr:ty>)?| $is_bit_valid:expr)?
+ ) => {
+ unsafe_impl!(
+ @inner
+ $(#[$attr])*
+ $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
+ => $trait for $ty $(; |$candidate $(: &$ref_repr)? $(: Ptr<$ptr_repr>)?| $is_bit_valid)?
+ );
+ };
+ (
+ @inner
+ $(#[$attr:meta])*
+ $(@const $constname:ident : $constty:ident,)*
+ $($tyvar:ident $(: $(? $optbound:ident +)* + $($bound:ident +)* )?,)*
+ => $trait:ident for $ty:ty $(; |$candidate:ident $(: &$ref_repr:ty)? $(: Ptr<$ptr_repr:ty>)?| $is_bit_valid:expr)?
+ ) => {
+ $(#[$attr])*
+ unsafe impl<$(const $constname: $constty,)* $($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> $trait for $ty {
+ unsafe_impl!(@method $trait $(; |$candidate: $(&$ref_repr)? $(Ptr<$ptr_repr>)?| $is_bit_valid)?);
+ }
+ };
+
+ (@method TryFromBytes ; |$candidate:ident: &$repr:ty| $is_bit_valid:expr) => {
+ #[inline]
+ unsafe fn is_bit_valid(candidate: Ptr<'_, Self>) -> bool {
+ // SAFETY:
+ // - The argument to `cast_unsized` is `|p| p as *mut _` as required
+ // by that method's safety precondition.
+ // - The caller has promised that the cast results in an object of
+ // equal or lesser size.
+ // - The caller has promised that `$repr`'s alignment is less than
+ // or equal to `Self`'s alignment.
+ #[allow(clippy::as_conversions)]
+ let candidate = unsafe { candidate.cast_unsized::<$repr, _>(|p| p as *mut _) };
+ // SAFETY:
+ // - The caller has promised that the referenced memory region will
+ // contain a valid `$repr` for `'a`.
+ // - The memory may not be referenced by any mutable references.
+ // This is a precondition of `is_bit_valid`.
+ // - The memory may not be mutated even via `UnsafeCell`s. This is a
+ // precondition of `is_bit_valid`.
+ // - There must not exist any references to the same memory region
+ // which contain `UnsafeCell`s at byte ranges which are not
+ // identical to the byte ranges at which `T` contains
+ // `UnsafeCell`s. This is a precondition of `is_bit_valid`.
+ let $candidate: &$repr = unsafe { candidate.as_ref() };
+ $is_bit_valid
+ }
+ };
+ (@method TryFromBytes ; |$candidate:ident: Ptr<$repr:ty>| $is_bit_valid:expr) => {
+ #[inline]
+ unsafe fn is_bit_valid(candidate: Ptr<'_, Self>) -> bool {
+ // SAFETY:
+ // - The argument to `cast_unsized` is `|p| p as *mut _` as required
+ // by that method's safety precondition.
+ // - The caller has promised that the cast results in an object of
+ // equal or lesser size.
+ // - The caller has promised that `$repr`'s alignment is less than
+ // or equal to `Self`'s alignment.
+ #[allow(clippy::as_conversions)]
+ let $candidate = unsafe { candidate.cast_unsized::<$repr, _>(|p| p as *mut _) };
+ $is_bit_valid
+ }
+ };
+ (@method TryFromBytes) => { #[inline(always)] unsafe fn is_bit_valid(_: Ptr<'_, Self>) -> bool { true } };
+ (@method $trait:ident) => {
+ #[allow(clippy::missing_inline_in_public_items)]
+ fn only_derive_is_allowed_to_implement_this_trait() {}
+ };
+ (@method $trait:ident; |$_candidate:ident $(: &$_ref_repr:ty)? $(: NonNull<$_ptr_repr:ty>)?| $_is_bit_valid:expr) => {
+ compile_error!("Can't provide `is_bit_valid` impl for trait other than `TryFromBytes`");
+ };
+}
+
+/// Implements a trait for a type, bounding on each memeber of the power set of
+/// a set of type variables. This is useful for implementing traits for tuples
+/// or `fn` types.
+///
+/// The last argument is the name of a macro which will be called in every
+/// `impl` block, and is expected to expand to the name of the type for which to
+/// implement the trait.
+///
+/// For example, the invocation:
+/// ```ignore
+/// unsafe_impl_for_power_set!(A, B => Foo for type!(...))
+/// ```
+/// ...expands to:
+/// ```ignore
+/// unsafe impl Foo for type!() { ... }
+/// unsafe impl<B> Foo for type!(B) { ... }
+/// unsafe impl<A, B> Foo for type!(A, B) { ... }
+/// ```
+macro_rules! unsafe_impl_for_power_set {
+ ($first:ident $(, $rest:ident)* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)) => {
+ unsafe_impl_for_power_set!($($rest),* $(-> $ret)? => $trait for $macro!(...));
+ unsafe_impl_for_power_set!(@impl $first $(, $rest)* $(-> $ret)? => $trait for $macro!(...));
+ };
+ ($(-> $ret:ident)? => $trait:ident for $macro:ident!(...)) => {
+ unsafe_impl_for_power_set!(@impl $(-> $ret)? => $trait for $macro!(...));
+ };
+ (@impl $($vars:ident),* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)) => {
+ unsafe impl<$($vars,)* $($ret)?> $trait for $macro!($($vars),* $(-> $ret)?) {
+ #[allow(clippy::missing_inline_in_public_items)]
+ fn only_derive_is_allowed_to_implement_this_trait() {}
+ }
+ };
+}
+
+/// Expands to an `Option<extern "C" fn>` type with the given argument types and
+/// return type. Designed for use with `unsafe_impl_for_power_set`.
+macro_rules! opt_extern_c_fn {
+ ($($args:ident),* -> $ret:ident) => { Option<extern "C" fn($($args),*) -> $ret> };
+}
+
+/// Expands to a `Option<fn>` type with the given argument types and return
+/// type. Designed for use with `unsafe_impl_for_power_set`.
+macro_rules! opt_fn {
+ ($($args:ident),* -> $ret:ident) => { Option<fn($($args),*) -> $ret> };
+}
+
+/// Implements trait(s) for a type or verifies the given implementation by
+/// referencing an existing (derived) implementation.
+///
+/// This macro exists so that we can provide zerocopy-derive as an optional
+/// dependency and still get the benefit of using its derives to validate that
+/// our trait impls are sound.
+///
+/// When compiling without `--cfg 'feature = "derive"` and without `--cfg test`,
+/// `impl_or_verify!` emits the provided trait impl. When compiling with either
+/// of those cfgs, it is expected that the type in question is deriving the
+/// traits instead. In this case, `impl_or_verify!` emits code which validates
+/// that the given trait impl is at least as restrictive as the the impl emitted
+/// by the custom derive. This has the effect of confirming that the impl which
+/// is emitted when the `derive` feature is disabled is actually sound (on the
+/// assumption that the impl emitted by the custom derive is sound).
+///
+/// The caller is still required to provide a safety comment (e.g. using the
+/// `safety_comment!` macro) . The reason for this restriction is that, while
+/// `impl_or_verify!` can guarantee that the provided impl is sound when it is
+/// compiled with the appropriate cfgs, there is no way to guarantee that it is
+/// ever compiled with those cfgs. In particular, it would be possible to
+/// accidentally place an `impl_or_verify!` call in a context that is only ever
+/// compiled when the `derive` feature is disabled. If that were to happen,
+/// there would be nothing to prevent an unsound trait impl from being emitted.
+/// Requiring a safety comment reduces the likelihood of emitting an unsound
+/// impl in this case, and also provides useful documentation for readers of the
+/// code.
+///
+/// ## Example
+///
+/// ```rust,ignore
+/// // Note that these derives are gated by `feature = "derive"`
+/// #[cfg_attr(any(feature = "derive", test), derive(FromZeroes, FromBytes, AsBytes, Unaligned))]
+/// #[repr(transparent)]
+/// struct Wrapper<T>(T);
+///
+/// safety_comment! {
+/// /// SAFETY:
+/// /// `Wrapper<T>` is `repr(transparent)`, so it is sound to implement any
+/// /// zerocopy trait if `T` implements that trait.
+/// impl_or_verify!(T: FromZeroes => FromZeroes for Wrapper<T>);
+/// impl_or_verify!(T: FromBytes => FromBytes for Wrapper<T>);
+/// impl_or_verify!(T: AsBytes => AsBytes for Wrapper<T>);
+/// impl_or_verify!(T: Unaligned => Unaligned for Wrapper<T>);
+/// }
+/// ```
+macro_rules! impl_or_verify {
+ // The following two match arms follow the same pattern as their
+ // counterparts in `unsafe_impl!`; see the documentation on those arms for
+ // more details.
+ (
+ const $constname:ident : $constty:ident $(,)?
+ $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
+ => $trait:ident for $ty:ty
+ ) => {
+ impl_or_verify!(@impl { unsafe_impl!(
+ const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
+ ); });
+ impl_or_verify!(@verify $trait, {
+ impl<const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
+ });
+ };
+ (
+ $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
+ => $trait:ident for $ty:ty
+ ) => {
+ impl_or_verify!(@impl { unsafe_impl!(
+ $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
+ ); });
+ impl_or_verify!(@verify $trait, {
+ impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
+ });
+ };
+ (
+ $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
+ => $trait:ident for $ty:ty
+ ) => {
+ unsafe_impl!(
+ @inner
+ $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
+ => $trait for $ty
+ );
+ };
+ (@impl $impl_block:tt) => {
+ #[cfg(not(any(feature = "derive", test)))]
+ const _: () = { $impl_block };
+ };
+ (@verify $trait:ident, $impl_block:tt) => {
+ #[cfg(any(feature = "derive", test))]
+ const _: () = {
+ trait Subtrait: $trait {}
+ $impl_block
+ };
+ };
+}
+
+/// Implements `KnownLayout` for a sized type.
+macro_rules! impl_known_layout {
+ ($(const $constvar:ident : $constty:ty, $tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
+ $(impl_known_layout!(@inner const $constvar: $constty, $tyvar $(: ?$optbound)? => $ty);)*
+ };
+ ($($tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
+ $(impl_known_layout!(@inner , $tyvar $(: ?$optbound)? => $ty);)*
+ };
+ ($($ty:ty),*) => { $(impl_known_layout!(@inner , => $ty);)* };
+ (@inner $(const $constvar:ident : $constty:ty)? , $($tyvar:ident $(: ?$optbound:ident)?)? => $ty:ty) => {
+ const _: () = {
+ use core::ptr::NonNull;
+
+ // SAFETY: Delegates safety to `DstLayout::for_type`.
+ unsafe impl<$(const $constvar : $constty,)? $($tyvar $(: ?$optbound)?)?> KnownLayout for $ty {
+ #[allow(clippy::missing_inline_in_public_items)]
+ fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized {}
+
+ const LAYOUT: DstLayout = DstLayout::for_type::<$ty>();
+
+ // SAFETY: `.cast` preserves address and provenance.
+ //
+ // TODO(#429): Add documentation to `.cast` that promises that
+ // it preserves provenance.
+ #[inline(always)]
+ fn raw_from_ptr_len(bytes: NonNull<u8>, _elems: usize) -> NonNull<Self> {
+ bytes.cast::<Self>()
+ }
+ }
+ };
+ };
+}
+
+/// Implements `KnownLayout` for a type in terms of the implementation of
+/// another type with the same representation.
+///
+/// # Safety
+///
+/// - `$ty` and `$repr` must have the same:
+/// - Fixed prefix size
+/// - Alignment
+/// - (For DSTs) trailing slice element size
+/// - It must be valid to perform an `as` cast from `*mut $repr` to `*mut $ty`,
+/// and this operation must preserve referent size (ie, `size_of_val_raw`).
+macro_rules! unsafe_impl_known_layout {
+ ($($tyvar:ident: ?Sized + KnownLayout =>)? #[repr($repr:ty)] $ty:ty) => {
+ const _: () = {
+ use core::ptr::NonNull;
+
+ unsafe impl<$($tyvar: ?Sized + KnownLayout)?> KnownLayout for $ty {
+ #[allow(clippy::missing_inline_in_public_items)]
+ fn only_derive_is_allowed_to_implement_this_trait() {}
+
+ const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT;
+
+ // SAFETY: All operations preserve address and provenance.
+ // Caller has promised that the `as` cast preserves size.
+ //
+ // TODO(#429): Add documentation to `NonNull::new_unchecked`
+ // that it preserves provenance.
+ #[inline(always)]
+ #[allow(unused_qualifications)] // for `core::ptr::NonNull`
+ fn raw_from_ptr_len(bytes: NonNull<u8>, elems: usize) -> NonNull<Self> {
+ #[allow(clippy::as_conversions)]
+ let ptr = <$repr>::raw_from_ptr_len(bytes, elems).as_ptr() as *mut Self;
+ // SAFETY: `ptr` was converted from `bytes`, which is non-null.
+ unsafe { NonNull::new_unchecked(ptr) }
+ }
+ }
+ };
+ };
+}
+
+/// Uses `align_of` to confirm that a type or set of types have alignment 1.
+///
+/// Note that `align_of<T>` requires `T: Sized`, so this macro doesn't work for
+/// unsized types.
+macro_rules! assert_unaligned {
+ ($ty:ty) => {
+ // We only compile this assertion under `cfg(test)` to avoid taking an
+ // extra non-dev dependency (and making this crate more expensive to
+ // compile for our dependents).
+ #[cfg(test)]
+ static_assertions::const_assert_eq!(core::mem::align_of::<$ty>(), 1);
+ };
+ ($($ty:ty),*) => {
+ $(assert_unaligned!($ty);)*
+ };
+}
diff --git a/third_party/rust/zerocopy/src/post_monomorphization_compile_fail_tests.rs b/third_party/rust/zerocopy/src/post_monomorphization_compile_fail_tests.rs
new file mode 100644
index 0000000000..32505b6693
--- /dev/null
+++ b/third_party/rust/zerocopy/src/post_monomorphization_compile_fail_tests.rs
@@ -0,0 +1,118 @@
+// Copyright 2018 The Fuchsia Authors
+//
+// Licensed under the 2-Clause BSD License <LICENSE-BSD or
+// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+//! Code that should fail to compile during the post-monomorphization compiler
+//! pass.
+//!
+//! Due to [a limitation with the `trybuild` crate][trybuild-issue], we cannot
+//! use our UI testing framework to test compilation failures that are
+//! encountered after monomorphization has complated. This module has one item
+//! for each such test we would prefer to have as a UI test, with the code in
+//! question appearing as a rustdoc example which is marked with `compile_fail`.
+//! This has the effect of causing doctests to fail if any of these examples
+//! compile successfully.
+//!
+//! This is very much a hack and not a complete replacement for UI tests - most
+//! notably because this only provides a single "compile vs fail" bit of
+//! information, but does not allow us to depend upon the specific error that
+//! causes compilation to fail.
+//!
+//! [trybuild-issue]: https://github.com/dtolnay/trybuild/issues/241
+
+// Miri doesn't detect post-monimorphization failures as compile-time failures,
+// but instead as runtime failures.
+#![cfg(not(miri))]
+
+/// ```compile_fail
+/// use core::cell::{Ref, RefCell};
+///
+/// let refcell = RefCell::new([0u8, 1, 2, 3]);
+/// let core_ref = refcell.borrow();
+/// let core_ref = Ref::map(core_ref, |bytes| &bytes[..]);
+///
+/// // `zc_ref` now stores `core_ref` internally.
+/// let zc_ref = zerocopy::Ref::<_, u32>::new(core_ref).unwrap();
+///
+/// // This causes `core_ref` to get dropped and synthesizes a Rust
+/// // reference to the memory `core_ref` was pointing at.
+/// let rust_ref = zc_ref.into_ref();
+///
+/// // UB!!! This mutates `rust_ref`'s referent while it's alive.
+/// *refcell.borrow_mut() = [0, 0, 0, 0];
+///
+/// println!("{}", rust_ref);
+/// ```
+#[allow(unused)]
+const REFCELL_REF_INTO_REF: () = ();
+
+/// ```compile_fail
+/// use core::cell::{RefCell, RefMut};
+///
+/// let refcell = RefCell::new([0u8, 1, 2, 3]);
+/// let core_ref_mut = refcell.borrow_mut();
+/// let core_ref_mut = RefMut::map(core_ref_mut, |bytes| &mut bytes[..]);
+///
+/// // `zc_ref` now stores `core_ref_mut` internally.
+/// let zc_ref = zerocopy::Ref::<_, u32>::new(core_ref_mut).unwrap();
+///
+/// // This causes `core_ref_mut` to get dropped and synthesizes a Rust
+/// // reference to the memory `core_ref` was pointing at.
+/// let rust_ref_mut = zc_ref.into_mut();
+///
+/// // UB!!! This mutates `rust_ref_mut`'s referent while it's alive.
+/// *refcell.borrow_mut() = [0, 0, 0, 0];
+///
+/// println!("{}", rust_ref_mut);
+/// ```
+#[allow(unused)]
+const REFCELL_REFMUT_INTO_MUT: () = ();
+
+/// ```compile_fail
+/// use core::cell::{Ref, RefCell};
+///
+/// let refcell = RefCell::new([0u8, 1, 2, 3]);
+/// let core_ref = refcell.borrow();
+/// let core_ref = Ref::map(core_ref, |bytes| &bytes[..]);
+///
+/// // `zc_ref` now stores `core_ref` internally.
+/// let zc_ref = zerocopy::Ref::<_, [u16]>::new_slice(core_ref).unwrap();
+///
+/// // This causes `core_ref` to get dropped and synthesizes a Rust
+/// // reference to the memory `core_ref` was pointing at.
+/// let rust_ref = zc_ref.into_slice();
+///
+/// // UB!!! This mutates `rust_ref`'s referent while it's alive.
+/// *refcell.borrow_mut() = [0, 0, 0, 0];
+///
+/// println!("{:?}", rust_ref);
+/// ```
+#[allow(unused)]
+const REFCELL_REFMUT_INTO_SLICE: () = ();
+
+/// ```compile_fail
+/// use core::cell::{RefCell, RefMut};
+///
+/// let refcell = RefCell::new([0u8, 1, 2, 3]);
+/// let core_ref_mut = refcell.borrow_mut();
+/// let core_ref_mut = RefMut::map(core_ref_mut, |bytes| &mut bytes[..]);
+///
+/// // `zc_ref` now stores `core_ref_mut` internally.
+/// let zc_ref = zerocopy::Ref::<_, [u16]>::new_slice(core_ref_mut).unwrap();
+///
+/// // This causes `core_ref_mut` to get dropped and synthesizes a Rust
+/// // reference to the memory `core_ref` was pointing at.
+/// let rust_ref_mut = zc_ref.into_mut_slice();
+///
+/// // UB!!! This mutates `rust_ref_mut`'s referent while it's alive.
+/// *refcell.borrow_mut() = [0, 0, 0, 0];
+///
+/// println!("{:?}", rust_ref_mut);
+/// ```
+#[allow(unused)]
+const REFCELL_REFMUT_INTO_MUT_SLICE: () = ();
diff --git a/third_party/rust/zerocopy/src/third_party/rust/LICENSE-APACHE b/third_party/rust/zerocopy/src/third_party/rust/LICENSE-APACHE
new file mode 100644
index 0000000000..1b5ec8b78e
--- /dev/null
+++ b/third_party/rust/zerocopy/src/third_party/rust/LICENSE-APACHE
@@ -0,0 +1,176 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
diff --git a/third_party/rust/zerocopy/src/third_party/rust/LICENSE-MIT b/third_party/rust/zerocopy/src/third_party/rust/LICENSE-MIT
new file mode 100644
index 0000000000..31aa79387f
--- /dev/null
+++ b/third_party/rust/zerocopy/src/third_party/rust/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/zerocopy/src/third_party/rust/README.fuchsia b/third_party/rust/zerocopy/src/third_party/rust/README.fuchsia
new file mode 100644
index 0000000000..e0a23dd8e5
--- /dev/null
+++ b/third_party/rust/zerocopy/src/third_party/rust/README.fuchsia
@@ -0,0 +1,7 @@
+Name: rust
+License File: LICENSE-APACHE
+License File: LICENSE-MIT
+Description:
+
+See https://github.com/google/zerocopy/pull/492 for an explanation of why this
+file exists.
diff --git a/third_party/rust/zerocopy/src/third_party/rust/layout.rs b/third_party/rust/zerocopy/src/third_party/rust/layout.rs
new file mode 100644
index 0000000000..19ef7c6982
--- /dev/null
+++ b/third_party/rust/zerocopy/src/third_party/rust/layout.rs
@@ -0,0 +1,45 @@
+use core::num::NonZeroUsize;
+
+/// Returns the amount of padding we must insert after `len` bytes to ensure
+/// that the following address will satisfy `align` (measured in bytes).
+///
+/// e.g., if `len` is 9, then `padding_needed_for(len, 4)` returns 3, because
+/// that is the minimum number of bytes of padding required to get a 4-aligned
+/// address (assuming that the corresponding memory block starts at a 4-aligned
+/// address).
+///
+/// The return value of this function has no meaning if `align` is not a
+/// power-of-two.
+///
+/// # Panics
+///
+/// May panic if `align` is not a power of two.
+//
+// TODO(#419): Replace `len` with a witness type for region size.
+#[allow(unused)]
+#[inline(always)]
+pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize {
+ // Rounded up value is:
+ // len_rounded_up = (len + align - 1) & !(align - 1);
+ // and then we return the padding difference: `len_rounded_up - len`.
+ //
+ // We use modular arithmetic throughout:
+ //
+ // 1. align is guaranteed to be > 0, so align - 1 is always
+ // valid.
+ //
+ // 2. `len + align - 1` can overflow by at most `align - 1`,
+ // so the &-mask with `!(align - 1)` will ensure that in the
+ // case of overflow, `len_rounded_up` will itself be 0.
+ // Thus the returned padding, when added to `len`, yields 0,
+ // which trivially satisfies the alignment `align`.
+ //
+ // (Of course, attempts to allocate blocks of memory whose
+ // size and padding overflow in the above manner should cause
+ // the allocator to yield an error anyway.)
+
+ let align = align.get();
+ debug_assert!(align.is_power_of_two());
+ let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
+ len_rounded_up.wrapping_sub(len)
+}
diff --git a/third_party/rust/zerocopy/src/util.rs b/third_party/rust/zerocopy/src/util.rs
new file mode 100644
index 0000000000..b35cc079c1
--- /dev/null
+++ b/third_party/rust/zerocopy/src/util.rs
@@ -0,0 +1,808 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[path = "third_party/rust/layout.rs"]
+pub(crate) mod core_layout;
+
+use core::{mem, num::NonZeroUsize};
+
+pub(crate) mod ptr {
+ use core::{
+ fmt::{Debug, Formatter},
+ marker::PhantomData,
+ ptr::NonNull,
+ };
+
+ use crate::{util::AsAddress, KnownLayout, _CastType};
+
+ /// A raw pointer with more restrictions.
+ ///
+ /// `Ptr<T>` is similar to `NonNull<T>`, but it is more restrictive in the
+ /// following ways:
+ /// - It must derive from a valid allocation
+ /// - It must reference a byte range which is contained inside the
+ /// allocation from which it derives
+ /// - As a consequence, the byte range it references must have a size
+ /// which does not overflow `isize`
+ /// - It must satisfy `T`'s alignment requirement
+ ///
+ /// Thanks to these restrictions, it is easier to prove the soundness of
+ /// some operations using `Ptr`s.
+ ///
+ /// `Ptr<'a, T>` is [covariant] in `'a` and `T`.
+ ///
+ /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
+ pub struct Ptr<'a, T: 'a + ?Sized> {
+ // INVARIANTS:
+ // 1. `ptr` is derived from some valid Rust allocation, `A`
+ // 2. `ptr` has the same provenance as `A`
+ // 3. `ptr` addresses a byte range which is entirely contained in `A`
+ // 4. `ptr` addresses a byte range whose length fits in an `isize`
+ // 5. `ptr` addresses a byte range which does not wrap around the address
+ // space
+ // 6. `ptr` is validly-aligned for `T`
+ // 7. `A` is guaranteed to live for at least `'a`
+ // 8. `T: 'a`
+ ptr: NonNull<T>,
+ _lifetime: PhantomData<&'a ()>,
+ }
+
+ impl<'a, T: ?Sized> Copy for Ptr<'a, T> {}
+ impl<'a, T: ?Sized> Clone for Ptr<'a, T> {
+ #[inline]
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ impl<'a, T: ?Sized> Ptr<'a, T> {
+ /// Returns a shared reference to the value.
+ ///
+ /// # Safety
+ ///
+ /// For the duration of `'a`:
+ /// - The referenced memory must contain a validly-initialized `T` for
+ /// the duration of `'a`.
+ /// - The referenced memory must not also be referenced by any mutable
+ /// references.
+ /// - The referenced memory must not be mutated, even via an
+ /// [`UnsafeCell`].
+ /// - There must not exist any references to the same memory region
+ /// which contain `UnsafeCell`s at byte ranges which are not identical
+ /// to the byte ranges at which `T` contains `UnsafeCell`s.
+ ///
+ /// [`UnsafeCell`]: core::cell::UnsafeCell
+ // TODO(#429): The safety requirements are likely overly-restrictive.
+ // Notably, mutation via `UnsafeCell`s is probably fine. Once the rules
+ // are more clearly defined, we should relax the safety requirements.
+ // For an example of why this is subtle, see:
+ // https://github.com/rust-lang/unsafe-code-guidelines/issues/463#issuecomment-1736771593
+ #[allow(unused)]
+ pub(crate) unsafe fn as_ref(&self) -> &'a T {
+ // SAFETY:
+ // - By invariant, `self.ptr` is properly-aligned for `T`.
+ // - By invariant, `self.ptr` is "dereferenceable" in that it points
+ // to a single allocation.
+ // - By invariant, the allocation is live for `'a`.
+ // - The caller promises that no mutable references exist to this
+ // region during `'a`.
+ // - The caller promises that `UnsafeCell`s match exactly.
+ // - The caller promises that no mutation will happen during `'a`,
+ // even via `UnsafeCell`s.
+ // - The caller promises that the memory region contains a
+ // validly-intialized `T`.
+ unsafe { self.ptr.as_ref() }
+ }
+
+ /// Casts to a different (unsized) target type.
+ ///
+ /// # Safety
+ ///
+ /// The caller promises that
+ /// - `cast(p)` is implemented exactly as follows: `|p: *mut T| p as
+ /// *mut U`.
+ /// - The size of the object referenced by the resulting pointer is less
+ /// than or equal to the size of the object referenced by `self`.
+ /// - The alignment of `U` is less than or equal to the alignment of
+ /// `T`.
+ pub(crate) unsafe fn cast_unsized<U: 'a + ?Sized, F: FnOnce(*mut T) -> *mut U>(
+ self,
+ cast: F,
+ ) -> Ptr<'a, U> {
+ let ptr = cast(self.ptr.as_ptr());
+ // SAFETY: Caller promises that `cast` is just an `as` cast. We call
+ // `cast` on `self.ptr.as_ptr()`, which is non-null by construction.
+ let ptr = unsafe { NonNull::new_unchecked(ptr) };
+ // SAFETY:
+ // - By invariant, `self.ptr` is derived from some valid Rust
+ // allocation, and since `ptr` is just `self.ptr as *mut U`, so is
+ // `ptr`.
+ // - By invariant, `self.ptr` has the same provenance as `A`, and so
+ // the same is true of `ptr`.
+ // - By invariant, `self.ptr` addresses a byte range which is
+ // entirely contained in `A`, and so the same is true of `ptr`.
+ // - By invariant, `self.ptr` addresses a byte range whose length
+ // fits in an `isize`, and so the same is true of `ptr`.
+ // - By invariant, `self.ptr` addresses a byte range which does not
+ // wrap around the address space, and so the same is true of
+ // `ptr`.
+ // - By invariant, `self.ptr` is validly-aligned for `T`. Since
+ // `ptr` has the same address, and since the caller promises that
+ // the alignment of `U` is less than or equal to the alignment of
+ // `T`, `ptr` is validly-aligned for `U`.
+ // - By invariant, `A` is guaranteed to live for at least `'a`.
+ // - `U: 'a`
+ Ptr { ptr, _lifetime: PhantomData }
+ }
+ }
+
+ impl<'a> Ptr<'a, [u8]> {
+ /// Attempts to cast `self` to a `U` using the given cast type.
+ ///
+ /// Returns `None` if the resulting `U` would be invalidly-aligned or if
+ /// no `U` can fit in `self`. On success, returns a pointer to the
+ /// largest-possible `U` which fits in `self`.
+ ///
+ /// # Safety
+ ///
+ /// The caller may assume that this implementation is correct, and may
+ /// rely on that assumption for the soundness of their code. In
+ /// particular, the caller may assume that, if `try_cast_into` returns
+ /// `Some((ptr, split_at))`, then:
+ /// - If this is a prefix cast, `ptr` refers to the byte range `[0,
+ /// split_at)` in `self`.
+ /// - If this is a suffix cast, `ptr` refers to the byte range
+ /// `[split_at, self.len())` in `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `U` is a DST whose trailing slice element is zero-sized.
+ pub(crate) fn try_cast_into<U: 'a + ?Sized + KnownLayout>(
+ &self,
+ cast_type: _CastType,
+ ) -> Option<(Ptr<'a, U>, usize)> {
+ // PANICS: By invariant, the byte range addressed by `self.ptr` does
+ // not wrap around the address space. This implies that the sum of
+ // the address (represented as a `usize`) and length do not overflow
+ // `usize`, as required by `validate_cast_and_convert_metadata`.
+ // Thus, this call to `validate_cast_and_convert_metadata` won't
+ // panic.
+ let (elems, split_at) = U::LAYOUT.validate_cast_and_convert_metadata(
+ AsAddress::addr(self.ptr.as_ptr()),
+ self.len(),
+ cast_type,
+ )?;
+ let offset = match cast_type {
+ _CastType::_Prefix => 0,
+ _CastType::_Suffix => split_at,
+ };
+
+ let ptr = self.ptr.cast::<u8>().as_ptr();
+ // SAFETY: `offset` is either `0` or `split_at`.
+ // `validate_cast_and_convert_metadata` promises that `split_at` is
+ // in the range `[0, self.len()]`. Thus, in both cases, `offset` is
+ // in `[0, self.len()]`. Thus:
+ // - The resulting pointer is in or one byte past the end of the
+ // same byte range as `self.ptr`. Since, by invariant, `self.ptr`
+ // addresses a byte range entirely contained within a single
+ // allocation, the pointer resulting from this operation is within
+ // or one byte past the end of that same allocation.
+ // - By invariant, `self.len() <= isize::MAX`. Since `offset <=
+ // self.len()`, `offset <= isize::MAX`.
+ // - By invariant, `self.ptr` addresses a byte range which does not
+ // wrap around the address space. This means that the base pointer
+ // plus the `self.len()` does not overflow `usize`. Since `offset
+ // <= self.len()`, this addition does not overflow `usize`.
+ let base = unsafe { ptr.add(offset) };
+ // SAFETY: Since `add` is not allowed to wrap around, the preceding line
+ // produces a pointer whose address is greater than or equal to that of
+ // `ptr`. Since `ptr` is a `NonNull`, `base` is also non-null.
+ let base = unsafe { NonNull::new_unchecked(base) };
+ let ptr = U::raw_from_ptr_len(base, elems);
+ // SAFETY:
+ // - By invariant, `self.ptr` is derived from some valid Rust
+ // allocation, `A`, and has the same provenance as `A`. All
+ // operations performed on `self.ptr` and values derived from it
+ // in this method preserve provenance, so:
+ // - `ptr` is derived from a valid Rust allocation, `A`.
+ // - `ptr` has the same provenance as `A`.
+ // - `validate_cast_and_convert_metadata` promises that the object
+ // described by `elems` and `split_at` lives at a byte range which
+ // is a subset of the input byte range. Thus:
+ // - Since, by invariant, `self.ptr` addresses a byte range
+ // entirely contained in `A`, so does `ptr`.
+ // - Since, by invariant, `self.ptr` addresses a range whose
+ // length is not longer than `isize::MAX` bytes, so does `ptr`.
+ // - Since, by invariant, `self.ptr` addresses a range which does
+ // not wrap around the address space, so does `ptr`.
+ // - `validate_cast_and_convert_metadata` promises that the object
+ // described by `split_at` is validly-aligned for `U`.
+ // - By invariant on `self`, `A` is guaranteed to live for at least
+ // `'a`.
+ // - `U: 'a` by trait bound.
+ Some((Ptr { ptr, _lifetime: PhantomData }, split_at))
+ }
+
+ /// Attempts to cast `self` into a `U`, failing if all of the bytes of
+ /// `self` cannot be treated as a `U`.
+ ///
+ /// In particular, this method fails if `self` is not validly-aligned
+ /// for `U` or if `self`'s size is not a valid size for `U`.
+ ///
+ /// # Safety
+ ///
+ /// On success, the caller may assume that the returned pointer
+ /// references the same byte range as `self`.
+ #[allow(unused)]
+ #[inline(always)]
+ pub(crate) fn try_cast_into_no_leftover<U: 'a + ?Sized + KnownLayout>(
+ &self,
+ ) -> Option<Ptr<'a, U>> {
+ // TODO(#67): Remove this allow. See NonNulSlicelExt for more
+ // details.
+ #[allow(unstable_name_collisions)]
+ match self.try_cast_into(_CastType::_Prefix) {
+ Some((slf, split_at)) if split_at == self.len() => Some(slf),
+ Some(_) | None => None,
+ }
+ }
+ }
+
+ impl<'a, T> Ptr<'a, [T]> {
+ /// The number of slice elements referenced by `self`.
+ ///
+ /// # Safety
+ ///
+ /// Unsafe code my rely on `len` satisfying the above contract.
+ fn len(&self) -> usize {
+ #[allow(clippy::as_conversions)]
+ let slc = self.ptr.as_ptr() as *const [()];
+ // SAFETY:
+ // - `()` has alignment 1, so `slc` is trivially aligned.
+ // - `slc` was derived from a non-null pointer.
+ // - The size is 0 regardless of the length, so it is sound to
+ // materialize a reference regardless of location.
+ // - By invariant, `self.ptr` has valid provenance.
+ let slc = unsafe { &*slc };
+ // This is correct because the preceding `as` cast preserves the
+ // number of slice elements. Per
+ // https://doc.rust-lang.org/nightly/reference/expressions/operator-expr.html#slice-dst-pointer-to-pointer-cast:
+ //
+ // For slice types like `[T]` and `[U]`, the raw pointer types
+ // `*const [T]`, `*mut [T]`, `*const [U]`, and `*mut [U]` encode
+ // the number of elements in this slice. Casts between these raw
+ // pointer types preserve the number of elements. Note that, as a
+ // consequence, such casts do *not* necessarily preserve the size
+ // of the pointer's referent (e.g., casting `*const [u16]` to
+ // `*const [u8]` will result in a raw pointer which refers to an
+ // object of half the size of the original). The same holds for
+ // `str` and any compound type whose unsized tail is a slice type,
+ // such as struct `Foo(i32, [u8])` or `(u64, Foo)`.
+ //
+ // TODO(#429),
+ // TODO(https://github.com/rust-lang/reference/pull/1417): Once this
+ // text is available on the Stable docs, cite those instead of the
+ // Nightly docs.
+ slc.len()
+ }
+
+ pub(crate) fn iter(&self) -> impl Iterator<Item = Ptr<'a, T>> {
+ // TODO(#429): Once `NonNull::cast` documents that it preserves
+ // provenance, cite those docs.
+ let base = self.ptr.cast::<T>().as_ptr();
+ (0..self.len()).map(move |i| {
+ // TODO(https://github.com/rust-lang/rust/issues/74265): Use
+ // `NonNull::get_unchecked_mut`.
+
+ // SAFETY: If the following conditions are not satisfied
+ // `pointer::cast` may induce Undefined Behavior [1]:
+ // > 1. Both the starting and resulting pointer must be either
+ // > in bounds or one byte past the end of the same allocated
+ // > object.
+ // > 2. The computed offset, in bytes, cannot overflow an
+ // > `isize`.
+ // > 3. The offset being in bounds cannot rely on “wrapping
+ // > around” the address space. That is, the
+ // > infinite-precision sum must fit in a `usize`.
+ //
+ // [1] https://doc.rust-lang.org/std/primitive.pointer.html#method.add
+ //
+ // We satisfy all three of these conditions here:
+ // 1. `base` (by invariant on `self`) points to an allocated
+ // object. By contract, `self.len()` accurately reflects the
+ // number of elements in the slice. `i` is in bounds of
+ // `c.len()` by construction, and so the result of this
+ // addition cannot overflow past the end of the allocation
+ // referred to by `c`.
+ // 2. By invariant on `Ptr`, `self` addresses a byte range whose
+ // length fits in an `isize`. Since `elem` is contained in
+ // `self`, the computed offset of `elem` must fit within
+ // `isize.`
+ // 3. By invariant on `Ptr`, `self` addresses a byte range which
+ // does not wrap around the address space. Since `elem` is
+ // contained in `self`, the computed offset of `elem` must
+ // wrap around the address space.
+ //
+ // TODO(#429): Once `pointer::add` documents that it preserves
+ // provenance, cite those docs.
+ let elem = unsafe { base.add(i) };
+
+ // SAFETY:
+ // - `elem` must not be null. `base` is constructed from a
+ // `NonNull` pointer, and the addition that produces `elem`
+ // must not overflow or wrap around, so `elem >= base > 0`.
+ //
+ // TODO(#429): Once `NonNull::new_unchecked` documents that it
+ // preserves provenance, cite those docs.
+ let elem = unsafe { NonNull::new_unchecked(elem) };
+
+ // SAFETY: The safety invariants of `Ptr` (see definition) are
+ // satisfied:
+ // 1. `elem` is derived from a valid Rust allocation, because
+ // `self` is derived from a valid Rust allocation, by
+ // invariant on `Ptr`
+ // 2. `elem` has the same provenance as `self`, because it
+ // derived from `self` using a series of
+ // provenance-preserving operations
+ // 3. `elem` is entirely contained in the allocation of `self`
+ // (see above)
+ // 4. `elem` addresses a byte range whose length fits in an
+ // `isize` (see above)
+ // 5. `elem` addresses a byte range which does not wrap around
+ // the address space (see above)
+ // 6. `elem` is validly-aligned for `T`. `self`, which
+ // represents a `[T]` is validly aligned for `T`, and `elem`
+ // is an element within that `[T]`
+ // 7. The allocation of `elem` is guaranteed to live for at
+ // least `'a`, because `elem` is entirely contained in
+ // `self`, which lives for at least `'a` by invariant on
+ // `Ptr`.
+ // 8. `T: 'a`, because `elem` is an element within `[T]`, and
+ // `[T]: 'a` by invariant on `Ptr`
+ Ptr { ptr: elem, _lifetime: PhantomData }
+ })
+ }
+ }
+
+ impl<'a, T: 'a + ?Sized> From<&'a T> for Ptr<'a, T> {
+ #[inline(always)]
+ fn from(t: &'a T) -> Ptr<'a, T> {
+ // SAFETY: `t` points to a valid Rust allocation, `A`, by
+ // construction. Thus:
+ // - `ptr` is derived from `A`
+ // - Since we use `NonNull::from`, which preserves provenance, `ptr`
+ // has the same provenance as `A`
+ // - Since `NonNull::from` creates a pointer which addresses the
+ // same bytes as `t`, `ptr` addresses a byte range entirely
+ // contained in (in this case, identical to) `A`
+ // - Since `t: &T`, it addresses no more than `isize::MAX` bytes [1]
+ // - Since `t: &T`, it addresses a byte range which does not wrap
+ // around the address space [2]
+ // - Since it is constructed from a valid `&T`, `ptr` is
+ // validly-aligned for `T`
+ // - Since `t: &'a T`, the allocation `A` is guaranteed to live for
+ // at least `'a`
+ // - `T: 'a` by trait bound
+ //
+ // TODO(#429),
+ // TODO(https://github.com/rust-lang/rust/issues/116181): Once it's
+ // documented, reference the guarantee that `NonNull::from`
+ // preserves provenance.
+ //
+ // TODO(#429),
+ // TODO(https://github.com/rust-lang/unsafe-code-guidelines/issues/465):
+ // - [1] Where does the reference document that allocations fit in
+ // `isize`?
+ // - [2] Where does the reference document that allocations don't
+ // wrap around the address space?
+ Ptr { ptr: NonNull::from(t), _lifetime: PhantomData }
+ }
+ }
+
+ impl<'a, T: 'a + ?Sized> Debug for Ptr<'a, T> {
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
+ self.ptr.fmt(f)
+ }
+ }
+
+ #[cfg(test)]
+ mod tests {
+ use core::mem::{self, MaybeUninit};
+
+ use super::*;
+ use crate::{util::testutil::AU64, FromBytes};
+
+ #[test]
+ fn test_ptrtry_cast_into_soundness() {
+ // This test is designed so that if `Ptr::try_cast_into_xxx` are
+ // buggy, it will manifest as unsoundness that Miri can detect.
+
+ // - If `size_of::<T>() == 0`, `N == 4`
+ // - Else, `N == 4 * size_of::<T>()`
+ fn test<const N: usize, T: ?Sized + KnownLayout + FromBytes>() {
+ let mut bytes = [MaybeUninit::<u8>::uninit(); N];
+ let initialized = [MaybeUninit::new(0u8); N];
+ for start in 0..=bytes.len() {
+ for end in start..=bytes.len() {
+ // Set all bytes to uninitialized other than those in
+ // the range we're going to pass to `try_cast_from`.
+ // This allows Miri to detect out-of-bounds reads
+ // because they read uninitialized memory. Without this,
+ // some out-of-bounds reads would still be in-bounds of
+ // `bytes`, and so might spuriously be accepted.
+ bytes = [MaybeUninit::<u8>::uninit(); N];
+ let bytes = &mut bytes[start..end];
+ // Initialize only the byte range we're going to pass to
+ // `try_cast_from`.
+ bytes.copy_from_slice(&initialized[start..end]);
+
+ let bytes = {
+ let bytes: *const [MaybeUninit<u8>] = bytes;
+ #[allow(clippy::as_conversions)]
+ let bytes = bytes as *const [u8];
+ // SAFETY: We just initialized these bytes to valid
+ // `u8`s.
+ unsafe { &*bytes }
+ };
+
+ /// # Safety
+ ///
+ /// - `slf` must reference a byte range which is
+ /// entirely initialized.
+ /// - `slf` must reference a byte range which is only
+ /// referenced by shared references which do not
+ /// contain `UnsafeCell`s during its lifetime.
+ unsafe fn validate_and_get_len<T: ?Sized + KnownLayout + FromBytes>(
+ slf: Ptr<'_, T>,
+ ) -> usize {
+ // SAFETY:
+ // - Since all bytes in `slf` are initialized and
+ // `T: FromBytes`, `slf` contains a valid `T`.
+ // - The caller promises that the referenced memory
+ // is not also referenced by any mutable
+ // references.
+ // - The caller promises that the referenced memory
+ // is not also referenced as a type which contains
+ // `UnsafeCell`s.
+ let t = unsafe { slf.as_ref() };
+
+ let bytes = {
+ let len = mem::size_of_val(t);
+ let t: *const T = t;
+ // SAFETY:
+ // - We know `t`'s bytes are all initialized
+ // because we just read it from `slf`, which
+ // points to an initialized range of bytes. If
+ // there's a bug and this doesn't hold, then
+ // that's exactly what we're hoping Miri will
+ // catch!
+ // - Since `T: FromBytes`, `T` doesn't contain
+ // any `UnsafeCell`s, so it's okay for `t: T`
+ // and a `&[u8]` to the same memory to be
+ // alive concurrently.
+ unsafe { core::slice::from_raw_parts(t.cast::<u8>(), len) }
+ };
+
+ // This assertion ensures that `t`'s bytes are read
+ // and compared to another value, which in turn
+ // ensures that Miri gets a chance to notice if any
+ // of `t`'s bytes are uninitialized, which they
+ // shouldn't be (see the comment above).
+ assert_eq!(bytes, vec![0u8; bytes.len()]);
+
+ mem::size_of_val(t)
+ }
+
+ for cast_type in [_CastType::_Prefix, _CastType::_Suffix] {
+ if let Some((slf, split_at)) =
+ Ptr::from(bytes).try_cast_into::<T>(cast_type)
+ {
+ // SAFETY: All bytes in `bytes` have been
+ // initialized.
+ let len = unsafe { validate_and_get_len(slf) };
+ match cast_type {
+ _CastType::_Prefix => assert_eq!(split_at, len),
+ _CastType::_Suffix => assert_eq!(split_at, bytes.len() - len),
+ }
+ }
+ }
+
+ if let Some(slf) = Ptr::from(bytes).try_cast_into_no_leftover::<T>() {
+ // SAFETY: All bytes in `bytes` have been
+ // initialized.
+ let len = unsafe { validate_and_get_len(slf) };
+ assert_eq!(len, bytes.len());
+ }
+ }
+ }
+ }
+
+ macro_rules! test {
+ ($($ty:ty),*) => {
+ $({
+ const S: usize = core::mem::size_of::<$ty>();
+ const N: usize = if S == 0 { 4 } else { S * 4 };
+ test::<N, $ty>();
+ // We don't support casting into DSTs whose trailing slice
+ // element is a ZST.
+ if S > 0 {
+ test::<N, [$ty]>();
+ }
+ // TODO: Test with a slice DST once we have any that
+ // implement `KnownLayout + FromBytes`.
+ })*
+ };
+ }
+
+ test!(());
+ test!(u8, u16, u32, u64, u128, usize, AU64);
+ test!(i8, i16, i32, i64, i128, isize);
+ test!(f32, f64);
+ }
+ }
+}
+
+pub(crate) trait AsAddress {
+ fn addr(self) -> usize;
+}
+
+impl<'a, T: ?Sized> AsAddress for &'a T {
+ #[inline(always)]
+ fn addr(self) -> usize {
+ let ptr: *const T = self;
+ AsAddress::addr(ptr)
+ }
+}
+
+impl<'a, T: ?Sized> AsAddress for &'a mut T {
+ #[inline(always)]
+ fn addr(self) -> usize {
+ let ptr: *const T = self;
+ AsAddress::addr(ptr)
+ }
+}
+
+impl<T: ?Sized> AsAddress for *const T {
+ #[inline(always)]
+ fn addr(self) -> usize {
+ // TODO(#181), TODO(https://github.com/rust-lang/rust/issues/95228): Use
+ // `.addr()` instead of `as usize` once it's stable, and get rid of this
+ // `allow`. Currently, `as usize` is the only way to accomplish this.
+ #[allow(clippy::as_conversions)]
+ #[cfg_attr(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS, allow(lossy_provenance_casts))]
+ return self.cast::<()>() as usize;
+ }
+}
+
+impl<T: ?Sized> AsAddress for *mut T {
+ #[inline(always)]
+ fn addr(self) -> usize {
+ let ptr: *const T = self;
+ AsAddress::addr(ptr)
+ }
+}
+
+/// Is `t` aligned to `mem::align_of::<U>()`?
+#[inline(always)]
+pub(crate) fn aligned_to<T: AsAddress, U>(t: T) -> bool {
+ // `mem::align_of::<U>()` is guaranteed to return a non-zero value, which in
+ // turn guarantees that this mod operation will not panic.
+ #[allow(clippy::arithmetic_side_effects)]
+ let remainder = t.addr() % mem::align_of::<U>();
+ remainder == 0
+}
+
+/// Round `n` down to the largest value `m` such that `m <= n` and `m % align ==
+/// 0`.
+///
+/// # Panics
+///
+/// May panic if `align` is not a power of two. Even if it doesn't panic in this
+/// case, it will produce nonsense results.
+#[inline(always)]
+pub(crate) const fn round_down_to_next_multiple_of_alignment(
+ n: usize,
+ align: NonZeroUsize,
+) -> usize {
+ let align = align.get();
+ debug_assert!(align.is_power_of_two());
+
+ // Subtraction can't underflow because `align.get() >= 1`.
+ #[allow(clippy::arithmetic_side_effects)]
+ let mask = !(align - 1);
+ n & mask
+}
+
+pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
+ if a.get() < b.get() {
+ b
+ } else {
+ a
+ }
+}
+
+pub(crate) const fn min(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
+ if a.get() > b.get() {
+ b
+ } else {
+ a
+ }
+}
+
+/// Since we support multiple versions of Rust, there are often features which
+/// have been stabilized in the most recent stable release which do not yet
+/// exist (stably) on our MSRV. This module provides polyfills for those
+/// features so that we can write more "modern" code, and just remove the
+/// polyfill once our MSRV supports the corresponding feature. Without this,
+/// we'd have to write worse/more verbose code and leave TODO comments sprinkled
+/// throughout the codebase to update to the new pattern once it's stabilized.
+///
+/// Each trait is imported as `_` at the crate root; each polyfill should "just
+/// work" at usage sites.
+pub(crate) mod polyfills {
+ use core::ptr::{self, NonNull};
+
+ // A polyfill for `NonNull::slice_from_raw_parts` that we can use before our
+ // MSRV is 1.70, when that function was stabilized.
+ //
+ // TODO(#67): Once our MSRV is 1.70, remove this.
+ pub(crate) trait NonNullExt<T> {
+ fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]>;
+ }
+
+ impl<T> NonNullExt<T> for NonNull<T> {
+ #[inline(always)]
+ fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]> {
+ let ptr = ptr::slice_from_raw_parts_mut(data.as_ptr(), len);
+ // SAFETY: `ptr` is converted from `data`, which is non-null.
+ unsafe { NonNull::new_unchecked(ptr) }
+ }
+ }
+}
+
+#[cfg(test)]
+pub(crate) mod testutil {
+ use core::fmt::{self, Display, Formatter};
+
+ use crate::*;
+
+ /// A `T` which is aligned to at least `align_of::<A>()`.
+ #[derive(Default)]
+ pub(crate) struct Align<T, A> {
+ pub(crate) t: T,
+ _a: [A; 0],
+ }
+
+ impl<T: Default, A> Align<T, A> {
+ pub(crate) fn set_default(&mut self) {
+ self.t = T::default();
+ }
+ }
+
+ impl<T, A> Align<T, A> {
+ pub(crate) const fn new(t: T) -> Align<T, A> {
+ Align { t, _a: [] }
+ }
+ }
+
+ // A `u64` with alignment 8.
+ //
+ // Though `u64` has alignment 8 on some platforms, it's not guaranteed.
+ // By contrast, `AU64` is guaranteed to have alignment 8.
+ #[derive(
+ KnownLayout,
+ FromZeroes,
+ FromBytes,
+ AsBytes,
+ Eq,
+ PartialEq,
+ Ord,
+ PartialOrd,
+ Default,
+ Debug,
+ Copy,
+ Clone,
+ )]
+ #[repr(C, align(8))]
+ pub(crate) struct AU64(pub(crate) u64);
+
+ impl AU64 {
+ // Converts this `AU64` to bytes using this platform's endianness.
+ pub(crate) fn to_bytes(self) -> [u8; 8] {
+ crate::transmute!(self)
+ }
+ }
+
+ impl Display for AU64 {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+ }
+
+ #[derive(
+ FromZeroes, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone,
+ )]
+ #[repr(C)]
+ pub(crate) struct Nested<T, U: ?Sized> {
+ _t: T,
+ _u: U,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_round_down_to_next_multiple_of_alignment() {
+ fn alt_impl(n: usize, align: NonZeroUsize) -> usize {
+ let mul = n / align.get();
+ mul * align.get()
+ }
+
+ for align in [1, 2, 4, 8, 16] {
+ for n in 0..256 {
+ let align = NonZeroUsize::new(align).unwrap();
+ let want = alt_impl(n, align);
+ let got = round_down_to_next_multiple_of_alignment(n, align);
+ assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({n}, {align})");
+ }
+ }
+ }
+}
+
+#[cfg(kani)]
+mod proofs {
+ use super::*;
+
+ #[kani::proof]
+ fn prove_round_down_to_next_multiple_of_alignment() {
+ fn model_impl(n: usize, align: NonZeroUsize) -> usize {
+ assert!(align.get().is_power_of_two());
+ let mul = n / align.get();
+ mul * align.get()
+ }
+
+ let align: NonZeroUsize = kani::any();
+ kani::assume(align.get().is_power_of_two());
+ let n: usize = kani::any();
+
+ let expected = model_impl(n, align);
+ let actual = round_down_to_next_multiple_of_alignment(n, align);
+ assert_eq!(expected, actual, "round_down_to_next_multiple_of_alignment({n}, {align})");
+ }
+
+ // Restricted to nightly since we use the unstable `usize::next_multiple_of`
+ // in our model implementation.
+ #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
+ #[kani::proof]
+ fn prove_padding_needed_for() {
+ fn model_impl(len: usize, align: NonZeroUsize) -> usize {
+ let padded = len.next_multiple_of(align.get());
+ let padding = padded - len;
+ padding
+ }
+
+ let align: NonZeroUsize = kani::any();
+ kani::assume(align.get().is_power_of_two());
+ let len: usize = kani::any();
+ // Constrain `len` to valid Rust lengths, since our model implementation
+ // isn't robust to overflow.
+ kani::assume(len <= isize::MAX as usize);
+ kani::assume(align.get() < 1 << 29);
+
+ let expected = model_impl(len, align);
+ let actual = core_layout::padding_needed_for(len, align);
+ assert_eq!(expected, actual, "padding_needed_for({len}, {align})");
+
+ let padded_len = actual + len;
+ assert_eq!(padded_len % align, 0);
+ assert!(padded_len / align >= len / align);
+ }
+}
diff --git a/third_party/rust/zerocopy/src/wrappers.rs b/third_party/rust/zerocopy/src/wrappers.rs
new file mode 100644
index 0000000000..532d872978
--- /dev/null
+++ b/third_party/rust/zerocopy/src/wrappers.rs
@@ -0,0 +1,503 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+use core::{
+ cmp::Ordering,
+ fmt::{self, Debug, Display, Formatter},
+ hash::Hash,
+ mem::{self, ManuallyDrop},
+ ops::{Deref, DerefMut},
+ ptr,
+};
+
+use super::*;
+
+/// A type with no alignment requirement.
+///
+/// An `Unalign` wraps a `T`, removing any alignment requirement. `Unalign<T>`
+/// has the same size and bit validity as `T`, but not necessarily the same
+/// alignment [or ABI]. This is useful if a type with an alignment requirement
+/// needs to be read from a chunk of memory which provides no alignment
+/// guarantees.
+///
+/// Since `Unalign` has no alignment requirement, the inner `T` may not be
+/// properly aligned in memory. There are five ways to access the inner `T`:
+/// - by value, using [`get`] or [`into_inner`]
+/// - by reference inside of a callback, using [`update`]
+/// - fallibly by reference, using [`try_deref`] or [`try_deref_mut`]; these can
+/// fail if the `Unalign` does not satisfy `T`'s alignment requirement at
+/// runtime
+/// - unsafely by reference, using [`deref_unchecked`] or
+/// [`deref_mut_unchecked`]; it is the caller's responsibility to ensure that
+/// the `Unalign` satisfies `T`'s alignment requirement
+/// - (where `T: Unaligned`) infallibly by reference, using [`Deref::deref`] or
+/// [`DerefMut::deref_mut`]
+///
+/// [or ABI]: https://github.com/google/zerocopy/issues/164
+/// [`get`]: Unalign::get
+/// [`into_inner`]: Unalign::into_inner
+/// [`update`]: Unalign::update
+/// [`try_deref`]: Unalign::try_deref
+/// [`try_deref_mut`]: Unalign::try_deref_mut
+/// [`deref_unchecked`]: Unalign::deref_unchecked
+/// [`deref_mut_unchecked`]: Unalign::deref_mut_unchecked
+// NOTE: This type is sound to use with types that need to be dropped. The
+// reason is that the compiler-generated drop code automatically moves all
+// values to aligned memory slots before dropping them in-place. This is not
+// well-documented, but it's hinted at in places like [1] and [2]. However, this
+// also means that `T` must be `Sized`; unless something changes, we can never
+// support unsized `T`. [3]
+//
+// [1] https://github.com/rust-lang/rust/issues/54148#issuecomment-420529646
+// [2] https://github.com/google/zerocopy/pull/126#discussion_r1018512323
+// [3] https://github.com/google/zerocopy/issues/209
+#[allow(missing_debug_implementations)]
+#[derive(Default, Copy)]
+#[cfg_attr(
+ any(feature = "derive", test),
+ derive(KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned)
+)]
+#[repr(C, packed)]
+pub struct Unalign<T>(T);
+
+#[cfg(not(any(feature = "derive", test)))]
+impl_known_layout!(T => Unalign<T>);
+
+safety_comment! {
+ /// SAFETY:
+ /// - `Unalign<T>` is `repr(packed)`, so it is unaligned regardless of the
+ /// alignment of `T`, and so we don't require that `T: Unaligned`
+ /// - `Unalign<T>` has the same bit validity as `T`, and so it is
+ /// `FromZeroes`, `FromBytes`, or `AsBytes` exactly when `T` is as well.
+ impl_or_verify!(T => Unaligned for Unalign<T>);
+ impl_or_verify!(T: FromZeroes => FromZeroes for Unalign<T>);
+ impl_or_verify!(T: FromBytes => FromBytes for Unalign<T>);
+ impl_or_verify!(T: AsBytes => AsBytes for Unalign<T>);
+}
+
+// Note that `Unalign: Clone` only if `T: Copy`. Since the inner `T` may not be
+// aligned, there's no way to safely call `T::clone`, and so a `T: Clone` bound
+// is not sufficient to implement `Clone` for `Unalign`.
+impl<T: Copy> Clone for Unalign<T> {
+ #[inline(always)]
+ fn clone(&self) -> Unalign<T> {
+ *self
+ }
+}
+
+impl<T> Unalign<T> {
+ /// Constructs a new `Unalign`.
+ #[inline(always)]
+ pub const fn new(val: T) -> Unalign<T> {
+ Unalign(val)
+ }
+
+ /// Consumes `self`, returning the inner `T`.
+ #[inline(always)]
+ pub const fn into_inner(self) -> T {
+ // Use this instead of `mem::transmute` since the latter can't tell
+ // that `Unalign<T>` and `T` have the same size.
+ #[repr(C)]
+ union Transmute<T> {
+ u: ManuallyDrop<Unalign<T>>,
+ t: ManuallyDrop<T>,
+ }
+
+ // SAFETY: Since `Unalign` is `#[repr(C, packed)]`, it has the same
+ // layout as `T`. `ManuallyDrop<U>` is guaranteed to have the same
+ // layout as `U`, and so `ManuallyDrop<Unalign<T>>` has the same layout
+ // as `ManuallyDrop<T>`. Since `Transmute<T>` is `#[repr(C)]`, its `t`
+ // and `u` fields both start at the same offset (namely, 0) within the
+ // union.
+ //
+ // We do this instead of just destructuring in order to prevent
+ // `Unalign`'s `Drop::drop` from being run, since dropping is not
+ // supported in `const fn`s.
+ //
+ // TODO(https://github.com/rust-lang/rust/issues/73255): Destructure
+ // instead of using unsafe.
+ unsafe { ManuallyDrop::into_inner(Transmute { u: ManuallyDrop::new(self) }.t) }
+ }
+
+ /// Attempts to return a reference to the wrapped `T`, failing if `self` is
+ /// not properly aligned.
+ ///
+ /// If `self` does not satisfy `mem::align_of::<T>()`, then it is unsound to
+ /// return a reference to the wrapped `T`, and `try_deref` returns `None`.
+ ///
+ /// If `T: Unaligned`, then `Unalign<T>` implements [`Deref`], and callers
+ /// may prefer [`Deref::deref`], which is infallible.
+ #[inline(always)]
+ pub fn try_deref(&self) -> Option<&T> {
+ if !crate::util::aligned_to::<_, T>(self) {
+ return None;
+ }
+
+ // SAFETY: `deref_unchecked`'s safety requirement is that `self` is
+ // aligned to `align_of::<T>()`, which we just checked.
+ unsafe { Some(self.deref_unchecked()) }
+ }
+
+ /// Attempts to return a mutable reference to the wrapped `T`, failing if
+ /// `self` is not properly aligned.
+ ///
+ /// If `self` does not satisfy `mem::align_of::<T>()`, then it is unsound to
+ /// return a reference to the wrapped `T`, and `try_deref_mut` returns
+ /// `None`.
+ ///
+ /// If `T: Unaligned`, then `Unalign<T>` implements [`DerefMut`], and
+ /// callers may prefer [`DerefMut::deref_mut`], which is infallible.
+ #[inline(always)]
+ pub fn try_deref_mut(&mut self) -> Option<&mut T> {
+ if !crate::util::aligned_to::<_, T>(&*self) {
+ return None;
+ }
+
+ // SAFETY: `deref_mut_unchecked`'s safety requirement is that `self` is
+ // aligned to `align_of::<T>()`, which we just checked.
+ unsafe { Some(self.deref_mut_unchecked()) }
+ }
+
+ /// Returns a reference to the wrapped `T` without checking alignment.
+ ///
+ /// If `T: Unaligned`, then `Unalign<T>` implements[ `Deref`], and callers
+ /// may prefer [`Deref::deref`], which is safe.
+ ///
+ /// # Safety
+ ///
+ /// If `self` does not satisfy `mem::align_of::<T>()`, then
+ /// `self.deref_unchecked()` may cause undefined behavior.
+ #[inline(always)]
+ pub const unsafe fn deref_unchecked(&self) -> &T {
+ // SAFETY: `Unalign<T>` is `repr(transparent)`, so there is a valid `T`
+ // at the same memory location as `self`. It has no alignment guarantee,
+ // but the caller has promised that `self` is properly aligned, so we
+ // know that it is sound to create a reference to `T` at this memory
+ // location.
+ //
+ // We use `mem::transmute` instead of `&*self.get_ptr()` because
+ // dereferencing pointers is not stable in `const` on our current MSRV
+ // (1.56 as of this writing).
+ unsafe { mem::transmute(self) }
+ }
+
+ /// Returns a mutable reference to the wrapped `T` without checking
+ /// alignment.
+ ///
+ /// If `T: Unaligned`, then `Unalign<T>` implements[ `DerefMut`], and
+ /// callers may prefer [`DerefMut::deref_mut`], which is safe.
+ ///
+ /// # Safety
+ ///
+ /// If `self` does not satisfy `mem::align_of::<T>()`, then
+ /// `self.deref_mut_unchecked()` may cause undefined behavior.
+ #[inline(always)]
+ pub unsafe fn deref_mut_unchecked(&mut self) -> &mut T {
+ // SAFETY: `self.get_mut_ptr()` returns a raw pointer to a valid `T` at
+ // the same memory location as `self`. It has no alignment guarantee,
+ // but the caller has promised that `self` is properly aligned, so we
+ // know that the pointer itself is aligned, and thus that it is sound to
+ // create a reference to a `T` at this memory location.
+ unsafe { &mut *self.get_mut_ptr() }
+ }
+
+ /// Gets an unaligned raw pointer to the inner `T`.
+ ///
+ /// # Safety
+ ///
+ /// The returned raw pointer is not necessarily aligned to
+ /// `align_of::<T>()`. Most functions which operate on raw pointers require
+ /// those pointers to be aligned, so calling those functions with the result
+ /// of `get_ptr` will be undefined behavior if alignment is not guaranteed
+ /// using some out-of-band mechanism. In general, the only functions which
+ /// are safe to call with this pointer are those which are explicitly
+ /// documented as being sound to use with an unaligned pointer, such as
+ /// [`read_unaligned`].
+ ///
+ /// [`read_unaligned`]: core::ptr::read_unaligned
+ #[inline(always)]
+ pub const fn get_ptr(&self) -> *const T {
+ ptr::addr_of!(self.0)
+ }
+
+ /// Gets an unaligned mutable raw pointer to the inner `T`.
+ ///
+ /// # Safety
+ ///
+ /// The returned raw pointer is not necessarily aligned to
+ /// `align_of::<T>()`. Most functions which operate on raw pointers require
+ /// those pointers to be aligned, so calling those functions with the result
+ /// of `get_ptr` will be undefined behavior if alignment is not guaranteed
+ /// using some out-of-band mechanism. In general, the only functions which
+ /// are safe to call with this pointer are those which are explicitly
+ /// documented as being sound to use with an unaligned pointer, such as
+ /// [`read_unaligned`].
+ ///
+ /// [`read_unaligned`]: core::ptr::read_unaligned
+ // TODO(https://github.com/rust-lang/rust/issues/57349): Make this `const`.
+ #[inline(always)]
+ pub fn get_mut_ptr(&mut self) -> *mut T {
+ ptr::addr_of_mut!(self.0)
+ }
+
+ /// Sets the inner `T`, dropping the previous value.
+ // TODO(https://github.com/rust-lang/rust/issues/57349): Make this `const`.
+ #[inline(always)]
+ pub fn set(&mut self, t: T) {
+ *self = Unalign::new(t);
+ }
+
+ /// Updates the inner `T` by calling a function on it.
+ ///
+ /// If [`T: Unaligned`], then `Unalign<T>` implements [`DerefMut`], and that
+ /// impl should be preferred over this method when performing updates, as it
+ /// will usually be faster and more ergonomic.
+ ///
+ /// For large types, this method may be expensive, as it requires copying
+ /// `2 * size_of::<T>()` bytes. \[1\]
+ ///
+ /// \[1\] Since the inner `T` may not be aligned, it would not be sound to
+ /// invoke `f` on it directly. Instead, `update` moves it into a
+ /// properly-aligned location in the local stack frame, calls `f` on it, and
+ /// then moves it back to its original location in `self`.
+ ///
+ /// [`T: Unaligned`]: Unaligned
+ #[inline]
+ pub fn update<O, F: FnOnce(&mut T) -> O>(&mut self, f: F) -> O {
+ // On drop, this moves `copy` out of itself and uses `ptr::write` to
+ // overwrite `slf`.
+ struct WriteBackOnDrop<T> {
+ copy: ManuallyDrop<T>,
+ slf: *mut Unalign<T>,
+ }
+
+ impl<T> Drop for WriteBackOnDrop<T> {
+ fn drop(&mut self) {
+ // SAFETY: We never use `copy` again as required by
+ // `ManuallyDrop::take`.
+ let copy = unsafe { ManuallyDrop::take(&mut self.copy) };
+ // SAFETY: `slf` is the raw pointer value of `self`. We know it
+ // is valid for writes and properly aligned because `self` is a
+ // mutable reference, which guarantees both of these properties.
+ unsafe { ptr::write(self.slf, Unalign::new(copy)) };
+ }
+ }
+
+ // SAFETY: We know that `self` is valid for reads, properly aligned, and
+ // points to an initialized `Unalign<T>` because it is a mutable
+ // reference, which guarantees all of these properties.
+ //
+ // Since `T: !Copy`, it would be unsound in the general case to allow
+ // both the original `Unalign<T>` and the copy to be used by safe code.
+ // We guarantee that the copy is used to overwrite the original in the
+ // `Drop::drop` impl of `WriteBackOnDrop`. So long as this `drop` is
+ // called before any other safe code executes, soundness is upheld.
+ // While this method can terminate in two ways (by returning normally or
+ // by unwinding due to a panic in `f`), in both cases, `write_back` is
+ // dropped - and its `drop` called - before any other safe code can
+ // execute.
+ let copy = unsafe { ptr::read(self) }.into_inner();
+ let mut write_back = WriteBackOnDrop { copy: ManuallyDrop::new(copy), slf: self };
+
+ let ret = f(&mut write_back.copy);
+
+ drop(write_back);
+ ret
+ }
+}
+
+impl<T: Copy> Unalign<T> {
+ /// Gets a copy of the inner `T`.
+ // TODO(https://github.com/rust-lang/rust/issues/57349): Make this `const`.
+ #[inline(always)]
+ pub fn get(&self) -> T {
+ let Unalign(val) = *self;
+ val
+ }
+}
+
+impl<T: Unaligned> Deref for Unalign<T> {
+ type Target = T;
+
+ #[inline(always)]
+ fn deref(&self) -> &T {
+ // SAFETY: `deref_unchecked`'s safety requirement is that `self` is
+ // aligned to `align_of::<T>()`. `T: Unaligned` guarantees that
+ // `align_of::<T>() == 1`, and all pointers are one-aligned because all
+ // addresses are divisible by 1.
+ unsafe { self.deref_unchecked() }
+ }
+}
+
+impl<T: Unaligned> DerefMut for Unalign<T> {
+ #[inline(always)]
+ fn deref_mut(&mut self) -> &mut T {
+ // SAFETY: `deref_mut_unchecked`'s safety requirement is that `self` is
+ // aligned to `align_of::<T>()`. `T: Unaligned` guarantees that
+ // `align_of::<T>() == 1`, and all pointers are one-aligned because all
+ // addresses are divisible by 1.
+ unsafe { self.deref_mut_unchecked() }
+ }
+}
+
+impl<T: Unaligned + PartialOrd> PartialOrd<Unalign<T>> for Unalign<T> {
+ #[inline(always)]
+ fn partial_cmp(&self, other: &Unalign<T>) -> Option<Ordering> {
+ PartialOrd::partial_cmp(self.deref(), other.deref())
+ }
+}
+
+impl<T: Unaligned + Ord> Ord for Unalign<T> {
+ #[inline(always)]
+ fn cmp(&self, other: &Unalign<T>) -> Ordering {
+ Ord::cmp(self.deref(), other.deref())
+ }
+}
+
+impl<T: Unaligned + PartialEq> PartialEq<Unalign<T>> for Unalign<T> {
+ #[inline(always)]
+ fn eq(&self, other: &Unalign<T>) -> bool {
+ PartialEq::eq(self.deref(), other.deref())
+ }
+}
+
+impl<T: Unaligned + Eq> Eq for Unalign<T> {}
+
+impl<T: Unaligned + Hash> Hash for Unalign<T> {
+ #[inline(always)]
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.deref().hash(state);
+ }
+}
+
+impl<T: Unaligned + Debug> Debug for Unalign<T> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Debug::fmt(self.deref(), f)
+ }
+}
+
+impl<T: Unaligned + Display> Display for Unalign<T> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self.deref(), f)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use core::panic::AssertUnwindSafe;
+
+ use super::*;
+ use crate::util::testutil::*;
+
+ /// A `T` which is guaranteed not to satisfy `align_of::<A>()`.
+ ///
+ /// It must be the case that `align_of::<T>() < align_of::<A>()` in order
+ /// fot this type to work properly.
+ #[repr(C)]
+ struct ForceUnalign<T, A> {
+ // The outer struct is aligned to `A`, and, thanks to `repr(C)`, `t` is
+ // placed at the minimum offset that guarantees its alignment. If
+ // `align_of::<T>() < align_of::<A>()`, then that offset will be
+ // guaranteed *not* to satisfy `align_of::<A>()`.
+ _u: u8,
+ t: T,
+ _a: [A; 0],
+ }
+
+ impl<T, A> ForceUnalign<T, A> {
+ const fn new(t: T) -> ForceUnalign<T, A> {
+ ForceUnalign { _u: 0, t, _a: [] }
+ }
+ }
+
+ #[test]
+ fn test_unalign() {
+ // Test methods that don't depend on alignment.
+ let mut u = Unalign::new(AU64(123));
+ assert_eq!(u.get(), AU64(123));
+ assert_eq!(u.into_inner(), AU64(123));
+ assert_eq!(u.get_ptr(), <*const _>::cast::<AU64>(&u));
+ assert_eq!(u.get_mut_ptr(), <*mut _>::cast::<AU64>(&mut u));
+ u.set(AU64(321));
+ assert_eq!(u.get(), AU64(321));
+
+ // Test methods that depend on alignment (when alignment is satisfied).
+ let mut u: Align<_, AU64> = Align::new(Unalign::new(AU64(123)));
+ assert_eq!(u.t.try_deref(), Some(&AU64(123)));
+ assert_eq!(u.t.try_deref_mut(), Some(&mut AU64(123)));
+ // SAFETY: The `Align<_, AU64>` guarantees proper alignment.
+ assert_eq!(unsafe { u.t.deref_unchecked() }, &AU64(123));
+ // SAFETY: The `Align<_, AU64>` guarantees proper alignment.
+ assert_eq!(unsafe { u.t.deref_mut_unchecked() }, &mut AU64(123));
+ *u.t.try_deref_mut().unwrap() = AU64(321);
+ assert_eq!(u.t.get(), AU64(321));
+
+ // Test methods that depend on alignment (when alignment is not
+ // satisfied).
+ let mut u: ForceUnalign<_, AU64> = ForceUnalign::new(Unalign::new(AU64(123)));
+ assert_eq!(u.t.try_deref(), None);
+ assert_eq!(u.t.try_deref_mut(), None);
+
+ // Test methods that depend on `T: Unaligned`.
+ let mut u = Unalign::new(123u8);
+ assert_eq!(u.try_deref(), Some(&123));
+ assert_eq!(u.try_deref_mut(), Some(&mut 123));
+ assert_eq!(u.deref(), &123);
+ assert_eq!(u.deref_mut(), &mut 123);
+ *u = 21;
+ assert_eq!(u.get(), 21);
+
+ // Test that some `Unalign` functions and methods are `const`.
+ const _UNALIGN: Unalign<u64> = Unalign::new(0);
+ const _UNALIGN_PTR: *const u64 = _UNALIGN.get_ptr();
+ const _U64: u64 = _UNALIGN.into_inner();
+ // Make sure all code is considered "used".
+ //
+ // TODO(https://github.com/rust-lang/rust/issues/104084): Remove this
+ // attribute.
+ #[allow(dead_code)]
+ const _: () = {
+ let x: Align<_, AU64> = Align::new(Unalign::new(AU64(123)));
+ // Make sure that `deref_unchecked` is `const`.
+ //
+ // SAFETY: The `Align<_, AU64>` guarantees proper alignment.
+ let au64 = unsafe { x.t.deref_unchecked() };
+ match au64 {
+ AU64(123) => {}
+ _ => unreachable!(),
+ }
+ };
+ }
+
+ #[test]
+ fn test_unalign_update() {
+ let mut u = Unalign::new(AU64(123));
+ u.update(|a| a.0 += 1);
+ assert_eq!(u.get(), AU64(124));
+
+ // Test that, even if the callback panics, the original is still
+ // correctly overwritten. Use a `Box` so that Miri is more likely to
+ // catch any unsoundness (which would likely result in two `Box`es for
+ // the same heap object, which is the sort of thing that Miri would
+ // probably catch).
+ let mut u = Unalign::new(Box::new(AU64(123)));
+ let res = std::panic::catch_unwind(AssertUnwindSafe(|| {
+ u.update(|a| {
+ a.0 += 1;
+ panic!();
+ })
+ }));
+ assert!(res.is_err());
+ assert_eq!(u.into_inner(), Box::new(AU64(124)));
+ }
+}
diff --git a/third_party/rust/zerocopy/testdata/include_value/data b/third_party/rust/zerocopy/testdata/include_value/data
new file mode 100644
index 0000000000..85df50785d
--- /dev/null
+++ b/third_party/rust/zerocopy/testdata/include_value/data
@@ -0,0 +1 @@
+abcd \ No newline at end of file
diff --git a/third_party/rust/zerocopy/tests/trybuild.rs b/third_party/rust/zerocopy/tests/trybuild.rs
new file mode 100644
index 0000000000..24abc28622
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/trybuild.rs
@@ -0,0 +1,41 @@
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+use testutil::ToolchainVersion;
+
+#[test]
+#[cfg_attr(miri, ignore)]
+fn ui() {
+ let version = ToolchainVersion::extract_from_pwd().unwrap();
+ // See the doc comment on this method for an explanation of what this does
+ // and why we store source files in different directories.
+ let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning();
+
+ let t = trybuild::TestCases::new();
+ t.compile_fail(format!("tests/{source_files_dirname}/*.rs"));
+}
+
+// The file `invalid-impls.rs` directly includes `src/macros.rs` in order to
+// test the `impl_or_verify!` macro which is defined in that file. Specifically,
+// it tests the verification portion of that macro, which is enabled when
+// `cfg(any(feature = "derive", test))`. While `--cfg test` is of course passed
+// to the code in the file you're reading right now, `trybuild` does not pass
+// `--cfg test` when it invokes Cargo. As a result, this `trybuild` test only
+// tests the correct behavior when the "derive" feature is enabled.
+#[cfg(feature = "derive")]
+#[test]
+#[cfg_attr(miri, ignore)]
+fn ui_invalid_impls() {
+ let version = ToolchainVersion::extract_from_pwd().unwrap();
+ // See the doc comment on this method for an explanation of what this does
+ // and why we store source files in different directories.
+ let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning();
+
+ let t = trybuild::TestCases::new();
+ t.compile_fail(format!("tests/{source_files_dirname}/invalid-impls/*.rs"));
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs
new file mode 100644
index 0000000000..45b6138f47
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs
@@ -0,0 +1,12 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+// Should fail because `UnsafeCell<u32>: !FromBytes`.
+const NOT_FROM_BYTES: core::cell::UnsafeCell<u32> =
+ include_value!("../../testdata/include_value/data");
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr
new file mode 100644
index 0000000000..21f6443bbf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `UnsafeCell<u32>: FromBytes` is not satisfied
+ --> tests/ui-msrv/include_value_not_from_bytes.rs:12:5
+ |
+12 | include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `UnsafeCell<u32>`
+ |
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-msrv/include_value_not_from_bytes.rs:12:5
+ |
+12 | include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.rs b/third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.rs
new file mode 100644
index 0000000000..d87b30698b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.rs
@@ -0,0 +1,11 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+// Should fail because the file is 4 bytes long, not 8.
+const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data");
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr b/third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr
new file mode 100644
index 0000000000..30045849d7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/include_value_wrong_size.rs:11:25
+ |
+11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 4]` (32 bits)
+ = note: target type: `u64` (64 bits)
+ = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs b/third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs
new file mode 100644
index 0000000000..ea963907df
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs
@@ -0,0 +1,29 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+// Since some macros from `macros.rs` are unused.
+#![allow(unused)]
+
+extern crate zerocopy;
+extern crate zerocopy_derive;
+
+include!("../../../src/macros.rs");
+
+use zerocopy::*;
+use zerocopy_derive::*;
+
+fn main() {}
+
+#[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+#[repr(transparent)]
+struct Foo<T>(T);
+
+impl_or_verify!(T => FromZeroes for Foo<T>);
+impl_or_verify!(T => FromBytes for Foo<T>);
+impl_or_verify!(T => AsBytes for Foo<T>);
+impl_or_verify!(T => Unaligned for Foo<T>);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr b/third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr
new file mode 100644
index 0000000000..c1de466ece
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr
@@ -0,0 +1,127 @@
+error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
+ | ^^^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1
+ |
+26 | impl_or_verify!(T => FromZeroes for Foo<T>);
+ | ------------------------------------------- in this macro invocation
+ |
+note: required because of the requirements on the impl of `zerocopy::FromZeroes` for `Foo<T>`
+ --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:10
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^^
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `_::Subtrait`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1
+ |
+26 | impl_or_verify!(T => FromZeroes for Foo<T>);
+ | ------------------------------------------- in this macro invocation
+ = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+26 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo<T>);
+ | ++++++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
+ | ^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1
+ |
+27 | impl_or_verify!(T => FromBytes for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ |
+note: required because of the requirements on the impl of `zerocopy::FromBytes` for `Foo<T>`
+ --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:22
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `_::Subtrait`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1
+ |
+27 | impl_or_verify!(T => FromBytes for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+27 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo<T>);
+ | +++++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
+ | ^^^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `T`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1
+ |
+28 | impl_or_verify!(T => AsBytes for Foo<T>);
+ | ---------------------------------------- in this macro invocation
+ |
+note: required because of the requirements on the impl of `zerocopy::AsBytes` for `Foo<T>`
+ --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:33
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `_::Subtrait`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1
+ |
+28 | impl_or_verify!(T => AsBytes for Foo<T>);
+ | ---------------------------------------- in this macro invocation
+ = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+28 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo<T>);
+ | +++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
+ | ^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1
+ |
+29 | impl_or_verify!(T => Unaligned for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ |
+note: required because of the requirements on the impl of `zerocopy::Unaligned` for `Foo<T>`
+ --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:42
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-msrv/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `_::Subtrait`
+ |
+ ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1
+ |
+29 | impl_or_verify!(T => Unaligned for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo<T>);
+ | +++++++++++++++++++++
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/max-align.rs b/third_party/rust/zerocopy/tests/ui-msrv/max-align.rs
new file mode 100644
index 0000000000..53e3eb9b0a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/max-align.rs
@@ -0,0 +1,99 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[repr(C, align(1))]
+struct Align1;
+
+#[repr(C, align(2))]
+struct Align2;
+
+#[repr(C, align(4))]
+struct Align4;
+
+#[repr(C, align(8))]
+struct Align8;
+
+#[repr(C, align(16))]
+struct Align16;
+
+#[repr(C, align(32))]
+struct Align32;
+
+#[repr(C, align(64))]
+struct Align64;
+
+#[repr(C, align(128))]
+struct Align128;
+
+#[repr(C, align(256))]
+struct Align256;
+
+#[repr(C, align(512))]
+struct Align512;
+
+#[repr(C, align(1024))]
+struct Align1024;
+
+#[repr(C, align(2048))]
+struct Align2048;
+
+#[repr(C, align(4096))]
+struct Align4096;
+
+#[repr(C, align(8192))]
+struct Align8192;
+
+#[repr(C, align(16384))]
+struct Align16384;
+
+#[repr(C, align(32768))]
+struct Align32768;
+
+#[repr(C, align(65536))]
+struct Align65536;
+
+#[repr(C, align(131072))]
+struct Align131072;
+
+#[repr(C, align(262144))]
+struct Align262144;
+
+#[repr(C, align(524288))]
+struct Align524288;
+
+#[repr(C, align(1048576))]
+struct Align1048576;
+
+#[repr(C, align(2097152))]
+struct Align2097152;
+
+#[repr(C, align(4194304))]
+struct Align4194304;
+
+#[repr(C, align(8388608))]
+struct Align8388608;
+
+#[repr(C, align(16777216))]
+struct Align16777216;
+
+#[repr(C, align(33554432))]
+struct Align33554432;
+
+#[repr(C, align(67108864))]
+struct Align67108864;
+
+#[repr(C, align(134217728))]
+struct Align13421772;
+
+#[repr(C, align(268435456))]
+struct Align26843545;
+
+#[repr(C, align(1073741824))]
+struct Align1073741824;
+
+fn main() {}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/max-align.stderr b/third_party/rust/zerocopy/tests/ui-msrv/max-align.stderr
new file mode 100644
index 0000000000..6ab6e47e2b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/max-align.stderr
@@ -0,0 +1,5 @@
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+ --> tests/ui-msrv/max-align.rs:96:11
+ |
+96 | #[repr(C, align(1073741824))]
+ | ^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs
new file mode 100644
index 0000000000..c4caaff917
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..b4afbbd60c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-msrv/transmute-dst-not-frombytes.rs:18:41
+ |
+18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-msrv/transmute-dst-not-frombytes.rs:18:41
+ |
+18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.rs
new file mode 100644
index 0000000000..0928564dd5
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a type of smaller
+// alignment to one of larger alignment.
+const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.stderr
new file mode 100644
index 0000000000..033031c91b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-alignment-increase.stderr
@@ -0,0 +1,36 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:39
+ |
+19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+ = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0658]: mutable references are not allowed in constants
+ --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:54
+ |
+19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+
+error[E0015]: cannot call non-const fn `transmute_mut::<[u8; 2], AU16>` in constants
+ --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:39
+ |
+19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0716]: temporary value dropped while borrowed
+ --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:59
+ |
+19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
+ | --------------------^^^^^^^^-
+ | | |
+ | | creates a temporary which is freed while still in use
+ | temporary value is freed at the end of this statement
+ | using this value as a constant requires that borrow lasts for `'static`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.rs
new file mode 100644
index 0000000000..021b562f18
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.rs
@@ -0,0 +1,20 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+const ARRAY_OF_U8S: [u8; 2] = [0u8; 2];
+
+// `transmute_mut!` cannot, generally speaking, be used in const contexts.
+const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.stderr
new file mode 100644
index 0000000000..30bfe45412
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-const.stderr
@@ -0,0 +1,41 @@
+warning: taking a mutable reference to a `const` item
+ --> tests/ui-msrv/transmute-mut-const.rs:20:52
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(const_item_mutation)]` on by default
+ = note: each usage of a `const` item creates a new temporary
+ = note: the mutable reference will refer to this temporary, not the original `const` item
+note: `const` item defined here
+ --> tests/ui-msrv/transmute-mut-const.rs:17:1
+ |
+17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0658]: mutable references are not allowed in constants
+ --> tests/ui-msrv/transmute-mut-const.rs:20:52
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+
+error[E0015]: cannot call non-const fn `transmute_mut::<[u8; 2], [u8; 2]>` in constants
+ --> tests/ui-msrv/transmute-mut-const.rs:20:37
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0716]: temporary value dropped while borrowed
+ --> tests/ui-msrv/transmute-mut-const.rs:20:57
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | --------------------^^^^^^^^^^^^-
+ | | |
+ | | creates a temporary which is freed while still in use
+ | temporary value is freed at the end of this statement
+ | using this value as a constant requires that borrow lasts for `'static`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.rs
new file mode 100644
index 0000000000..7068f1026d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes>(u: &mut u8) -> &mut T {
+ // `transmute_mut!` requires the destination type to be concrete.
+ transmute_mut!(u)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.stderr
new file mode 100644
index 0000000000..f6b54ce1c2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-mut-dst-generic.rs:17:5
+ |
+17 | transmute_mut!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `T` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-mut-dst-generic.rs:17:5
+ |
+17 | transmute_mut!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<u8>` (8 bits)
+ = note: target type: `MaxAlignsOf<u8, T>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs
new file mode 100644
index 0000000000..33a9ecd955
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting into a non-reference
+// destination type.
+const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr
new file mode 100644
index 0000000000..8f0ea801ef
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.rs
new file mode 100644
index 0000000000..b72f12928c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the destination type implements `AsBytes`
+const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr
new file mode 100644
index 0000000000..7e2dd78b8f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `Dst: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-mut-dst-not-asbytes.rs:24:36
+ |
+24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Dst`
+ |
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-dst-not-asbytes.rs:24:36
+ |
+24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs
new file mode 100644
index 0000000000..102fcedc9a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..663e085a30
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
+ --> tests/ui-msrv/transmute-mut-dst-not-frombytes.rs:24:38
+ |
+24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst`
+ |
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-dst-not-frombytes.rs:24:38
+ |
+24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs
new file mode 100644
index 0000000000..693ccda56f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting into an unsized destination
+// type.
+const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr
new file mode 100644
index 0000000000..cb60a82a78
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr
@@ -0,0 +1,108 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<T, U>(e: T) -> U;
+ | ^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs
new file mode 100644
index 0000000000..c31765e4b9
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs
@@ -0,0 +1,15 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+fn main() {}
+
+fn increase_lifetime() {
+ let mut x = 0u64;
+ // It is illegal to increase the lifetime scope.
+ let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr
new file mode 100644
index 0000000000..5ff7145966
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr
@@ -0,0 +1,9 @@
+error[E0597]: `x` does not live long enough
+ --> tests/ui-msrv/transmute-mut-illegal-lifetime.rs:14:56
+ |
+14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x);
+ | ---------------- ^^^^^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `x` is borrowed for `'static`
+15 | }
+ | - `x` dropped here while still borrowed
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.rs
new file mode 100644
index 0000000000..c6eec3a9c2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// We require that the size of the destination type is not smaller than the size
+// of the source type.
+const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.stderr
new file mode 100644
index 0000000000..2bfc21898b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-decrease.stderr
@@ -0,0 +1,36 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:32
+ |
+17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 2]` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0658]: mutable references are not allowed in constants
+ --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:47
+ |
+17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+
+error[E0015]: cannot call non-const fn `transmute_mut::<[u8; 2], u8>` in constants
+ --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:32
+ |
+17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0716]: temporary value dropped while borrowed
+ --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:52
+ |
+17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
+ | --------------------^^^^^^^^-
+ | | |
+ | | creates a temporary which is freed while still in use
+ | temporary value is freed at the end of this statement
+ | using this value as a constant requires that borrow lasts for `'static`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.rs
new file mode 100644
index 0000000000..a4657c2838
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.stderr
new file mode 100644
index 0000000000..6e866a0d32
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-size-increase.stderr
@@ -0,0 +1,36 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-mut-size-increase.rs:17:37
+ |
+17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `[u8; 2]` (16 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0658]: mutable references are not allowed in constants
+ --> tests/ui-msrv/transmute-mut-size-increase.rs:17:52
+ |
+17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+
+error[E0015]: cannot call non-const fn `transmute_mut::<u8, [u8; 2]>` in constants
+ --> tests/ui-msrv/transmute-mut-size-increase.rs:17:37
+ |
+17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0716]: temporary value dropped while borrowed
+ --> tests/ui-msrv/transmute-mut-size-increase.rs:17:57
+ |
+17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
+ | --------------------^^^-
+ | | |
+ | | creates a temporary which is freed while still in use
+ | temporary value is freed at the end of this statement
+ | using this value as a constant requires that borrow lasts for `'static`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.rs
new file mode 100644
index 0000000000..aed7ded96f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes, U: AsBytes + FromBytes>(t: &mut T) -> &mut U {
+ // `transmute_mut!` requires the source and destination types to be
+ // concrete.
+ transmute_mut!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.stderr
new file mode 100644
index 0000000000..1162f21f9c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-mut-src-dst-generic.rs:18:5
+ |
+18 | transmute_mut!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `U` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-mut-src-dst-generic.rs:18:5
+ |
+18 | transmute_mut!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, U>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs
new file mode 100644
index 0000000000..98cc520889
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting between non-reference source
+// and destination types.
+const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr
new file mode 100644
index 0000000000..c500a93af7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-mut-src-dst-not-references.rs:17:59
+ |
+17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&mut _`, found `usize`
+ | | help: consider mutably borrowing here: `&mut 0usize`
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found type `usize`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.rs
new file mode 100644
index 0000000000..1bebcf2d68
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting between unsized source and
+// destination types.
+const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.stderr
new file mode 100644
index 0000000000..00201a6b68
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-dst-unsized.stderr
@@ -0,0 +1,237 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<T, U>(e: T) -> U;
+ | ^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.rs
new file mode 100644
index 0000000000..a3ef397876
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes>(t: &mut T) -> &mut u8 {
+ // `transmute_mut!` requires the source type to be concrete.
+ transmute_mut!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.stderr
new file mode 100644
index 0000000000..8a9296ca66
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-generic.stderr
@@ -0,0 +1,10 @@
+error[E0405]: cannot find trait `FromBytes` in this scope
+ --> tests/ui-msrv/transmute-mut-src-generic.rs:15:31
+ |
+15 | fn transmute_mut<T: AsBytes + FromBytes>(t: &mut T) -> &mut u8 {
+ | ^^^^^^^^^ not found in this scope
+ |
+help: consider importing this trait
+ |
+11 | use zerocopy::FromBytes;
+ |
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs
new file mode 100644
index 0000000000..08088d0db6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+fn ref_src_immutable() {
+ // `transmute_mut!` requires that its source type be a mutable reference.
+ let _: &mut u8 = transmute_mut!(&0u8);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr
new file mode 100644
index 0000000000..8262f169a2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-mut-src-immutable.rs:17:37
+ |
+17 | let _: &mut u8 = transmute_mut!(&0u8);
+ | ---------------^^^^-
+ | | |
+ | | types differ in mutability
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found reference `&u8`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs
new file mode 100644
index 0000000000..bf8bc32592
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a non-reference source
+// type.
+const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr
new file mode 100644
index 0000000000..3a6bdf78a6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-mut-src-not-a-reference.rs:17:53
+ |
+17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&mut _`, found `usize`
+ | | help: consider mutably borrowing here: `&mut 0usize`
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found type `usize`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.rs
new file mode 100644
index 0000000000..6a14f12fd0
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.stderr
new file mode 100644
index 0000000000..4056975829
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-asbytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `Src: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src`
+ |
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `Src: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src`
+ |
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs
new file mode 100644
index 0000000000..2ebe03601b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the source type implements `FromBytes`
+const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr
new file mode 100644
index 0000000000..b859c41cd2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `Src: FromBytes` is not satisfied
+ --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src`
+ |
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `Src: FromBytes` is not satisfied
+ --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src`
+ |
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs
new file mode 100644
index 0000000000..413dd68d89
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs
@@ -0,0 +1,16 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from an unsized source type.
+const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr
new file mode 100644
index 0000000000..6b18695e66
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr
@@ -0,0 +1,198 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<T, U>(e: T) -> U;
+ | ^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs
new file mode 100644
index 0000000000..5af8859332
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs
@@ -0,0 +1,20 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// It is unclear whether we can or should support this transmutation, especially
+// in a const context. This test ensures that even if such a transmutation
+// becomes valid due to the requisite implementations of `FromBytes` being
+// added, that we re-examine whether it should specifically be valid in a const
+// context.
+const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr
new file mode 100644
index 0000000000..06b1bbaf2d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr
@@ -0,0 +1,37 @@
+error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize`
+ |
+ = help: the following implementations were found:
+ <usize as AsBytes>
+ <f32 as AsBytes>
+ <f64 as AsBytes>
+ <i128 as AsBytes>
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize`
+ |
+ = help: the following implementations were found:
+ <usize as AsBytes>
+ <f32 as AsBytes>
+ <f64 as AsBytes>
+ <i128 as AsBytes>
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.rs
new file mode 100644
index 0000000000..bf1988c66b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a type of smaller
+// alignment to one of larger alignment.
+const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.stderr
new file mode 100644
index 0000000000..72864e144d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-alignment-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-alignment-increase.rs:19:35
+ |
+19 | const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+ = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.rs
new file mode 100644
index 0000000000..bf4a0f9adf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, FromBytes};
+
+fn main() {}
+
+fn transmute_ref<T: FromBytes>(u: &u8) -> &T {
+ // `transmute_ref!` requires the destination type to be concrete.
+ transmute_ref!(u)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.stderr
new file mode 100644
index 0000000000..ec7ec74894
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-dst-generic.rs:17:5
+ |
+17 | transmute_ref!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `T` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-dst-generic.rs:17:5
+ |
+17 | transmute_ref!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<u8>` (8 bits)
+ = note: target type: `MaxAlignsOf<u8, T>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs
new file mode 100644
index 0000000000..fa0e6e4c9b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+fn ref_dst_mutable() {
+ // `transmute_ref!` requires that its destination type be an immutable
+ // reference.
+ let _: &mut u8 = transmute_ref!(&0u8);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr
new file mode 100644
index 0000000000..5ccf2cd20d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs
new file mode 100644
index 0000000000..de55f9acdf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting into a non-reference
+// destination type.
+const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr
new file mode 100644
index 0000000000..9a61c4c7ce
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs
new file mode 100644
index 0000000000..d81f64d21b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..d317675446
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-msrv/transmute-ref-dst-not-frombytes.rs:18:42
+ |
+18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
+ |
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-msrv/transmute-ref-dst-not-frombytes.rs:18:42
+ |
+18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs
new file mode 100644
index 0000000000..625f1fac07
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting into an unsized destination
+// type.
+const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr
new file mode 100644
index 0000000000..78135de876
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr
@@ -0,0 +1,94 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<T, U>(e: T) -> U;
+ | ^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs
new file mode 100644
index 0000000000..8dd191e6f4
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs
@@ -0,0 +1,15 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+fn main() {}
+
+fn increase_lifetime() {
+ let x = 0u64;
+ // It is illegal to increase the lifetime scope.
+ let _: &'static u64 = zerocopy::transmute_ref!(&x);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr
new file mode 100644
index 0000000000..866ea56a66
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr
@@ -0,0 +1,9 @@
+error[E0597]: `x` does not live long enough
+ --> tests/ui-msrv/transmute-ref-illegal-lifetime.rs:14:52
+ |
+14 | let _: &'static u64 = zerocopy::transmute_ref!(&x);
+ | ------------ ^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `x` is borrowed for `'static`
+15 | }
+ | - `x` dropped here while still borrowed
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.rs
new file mode 100644
index 0000000000..1d66a54ef7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// Although this is not a soundness requirement, we currently require that the
+// size of the destination type is not smaller than the size of the source type.
+const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.stderr
new file mode 100644
index 0000000000..95669f9063
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-size-decrease.rs:17:28
+ |
+17 | const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 2]` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.rs
new file mode 100644
index 0000000000..cdca560b30
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.stderr
new file mode 100644
index 0000000000..10f0e1038c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-size-increase.rs:17:33
+ |
+17 | const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `[u8; 2]` (16 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.rs
new file mode 100644
index 0000000000..409d785b20
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_ref<T: AsBytes, U: FromBytes>(t: &T) -> &U {
+ // `transmute_ref!` requires the source and destination types to be
+ // concrete.
+ transmute_ref!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.stderr
new file mode 100644
index 0000000000..eb3268fa8f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-src-dst-generic.rs:18:5
+ |
+18 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `U` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-src-dst-generic.rs:18:5
+ |
+18 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, U>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs
new file mode 100644
index 0000000000..114e917b54
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting between non-reference source
+// and destination types.
+const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr
new file mode 100644
index 0000000000..2c5e23b6dd
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr
@@ -0,0 +1,42 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:54
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected reference, found `usize`
+ | | help: consider borrowing here: `&0usize`
+ | expected due to this
+ |
+ = note: expected reference `&_`
+ found type `usize`
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.rs
new file mode 100644
index 0000000000..6bfe7ffdfd
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting between unsized source and
+// destination types.
+const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.stderr
new file mode 100644
index 0000000000..adfd59792a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-dst-unsized.stderr
@@ -0,0 +1,195 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<T, U>(e: T) -> U;
+ | ^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.rs
new file mode 100644
index 0000000000..010281c32e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, AsBytes};
+
+fn main() {}
+
+fn transmute_ref<T: AsBytes>(t: &T) -> &u8 {
+ // `transmute_ref!` requires the source type to be concrete.
+ transmute_ref!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.stderr
new file mode 100644
index 0000000000..4cb3e51bc7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-src-generic.rs:17:5
+ |
+17 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-ref-src-generic.rs:17:5
+ |
+17 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, u8>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs
new file mode 100644
index 0000000000..90661b3e2c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a non-reference source
+// type.
+const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr
new file mode 100644
index 0000000000..0f4aeec9e2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> tests/ui-msrv/transmute-ref-src-not-a-reference.rs:17:49
+ |
+17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected reference, found `usize`
+ | | help: consider borrowing here: `&0usize`
+ | expected due to this
+ |
+ = note: expected reference `&_`
+ found type `usize`
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.rs
new file mode 100644
index 0000000000..6ab19f3c82
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.stderr
new file mode 100644
index 0000000000..6b80d4f494
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-not-asbytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs
new file mode 100644
index 0000000000..14e72b4ddc
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs
@@ -0,0 +1,16 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from an unsized source type.
+const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr
new file mode 100644
index 0000000000..43bac53595
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr
@@ -0,0 +1,170 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<T, U>(e: T) -> U;
+ | ^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
+ = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.rs
new file mode 100644
index 0000000000..1d56831f22
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// Although this is not a soundness requirement, we currently require that the
+// size of the destination type is not smaller than the size of the source type.
+const DECREASE_SIZE: u8 = transmute!(AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr
new file mode 100644
index 0000000000..ffa5688485
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-size-decrease.rs:19:27
+ |
+19 | const DECREASE_SIZE: u8 = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AU16` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.rs
new file mode 100644
index 0000000000..32f9363089
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: AU16 = transmute!(0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.stderr
new file mode 100644
index 0000000000..865d0caf9e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-msrv/transmute-size-increase.rs:19:29
+ |
+19 | const INCREASE_SIZE: AU16 = transmute!(0u8);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `AU16` (16 bits)
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.rs
new file mode 100644
index 0000000000..dd730216b6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
diff --git a/third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.stderr
new file mode 100644
index 0000000000..93eeda0c26
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-msrv/transmute-src-not-asbytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs
new file mode 100644
index 0000000000..45b6138f47
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs
@@ -0,0 +1,12 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+// Should fail because `UnsafeCell<u32>: !FromBytes`.
+const NOT_FROM_BYTES: core::cell::UnsafeCell<u32> =
+ include_value!("../../testdata/include_value/data");
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr
new file mode 100644
index 0000000000..d948a0db81
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `UnsafeCell<u32>: FromBytes` is not satisfied
+ --> tests/ui-nightly/include_value_not_from_bytes.rs:12:5
+ |
+12 | include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `UnsafeCell<u32>`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-nightly/include_value_not_from_bytes.rs:12:5
+ |
+12 | include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.rs b/third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.rs
new file mode 100644
index 0000000000..d87b30698b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.rs
@@ -0,0 +1,11 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+// Should fail because the file is 4 bytes long, not 8.
+const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data");
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr b/third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr
new file mode 100644
index 0000000000..f592ece1de
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/include_value_wrong_size.rs:11:25
+ |
+11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 4]` (32 bits)
+ = note: target type: `u64` (64 bits)
+ = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs b/third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs
new file mode 100644
index 0000000000..ea963907df
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs
@@ -0,0 +1,29 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+// Since some macros from `macros.rs` are unused.
+#![allow(unused)]
+
+extern crate zerocopy;
+extern crate zerocopy_derive;
+
+include!("../../../src/macros.rs");
+
+use zerocopy::*;
+use zerocopy_derive::*;
+
+fn main() {}
+
+#[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+#[repr(transparent)]
+struct Foo<T>(T);
+
+impl_or_verify!(T => FromZeroes for Foo<T>);
+impl_or_verify!(T => FromBytes for Foo<T>);
+impl_or_verify!(T => AsBytes for Foo<T>);
+impl_or_verify!(T => Unaligned for Foo<T>);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr b/third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr
new file mode 100644
index 0000000000..e5651d169e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr
@@ -0,0 +1,107 @@
+error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:26:37
+ |
+26 | impl_or_verify!(T => FromZeroes for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::FromZeroes`
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:10
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-nightly/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:26:1
+ |
+26 | impl_or_verify!(T => FromZeroes for Foo<T>);
+ | ------------------------------------------- in this macro invocation
+ = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+26 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo<T>);
+ | ++++++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:27:36
+ |
+27 | impl_or_verify!(T => FromBytes for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::FromBytes`
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:22
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-nightly/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:27:1
+ |
+27 | impl_or_verify!(T => FromBytes for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+27 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo<T>);
+ | +++++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:28:34
+ |
+28 | impl_or_verify!(T => AsBytes for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::AsBytes`
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:33
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-nightly/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:28:1
+ |
+28 | impl_or_verify!(T => AsBytes for Foo<T>);
+ | ---------------------------------------- in this macro invocation
+ = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+28 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo<T>);
+ | +++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:29:36
+ |
+29 | impl_or_verify!(T => Unaligned for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::Unaligned`
+ --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:42
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-nightly/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:29:1
+ |
+29 | impl_or_verify!(T => Unaligned for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo<T>);
+ | +++++++++++++++++++++
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/max-align.rs b/third_party/rust/zerocopy/tests/ui-nightly/max-align.rs
new file mode 100644
index 0000000000..53e3eb9b0a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/max-align.rs
@@ -0,0 +1,99 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[repr(C, align(1))]
+struct Align1;
+
+#[repr(C, align(2))]
+struct Align2;
+
+#[repr(C, align(4))]
+struct Align4;
+
+#[repr(C, align(8))]
+struct Align8;
+
+#[repr(C, align(16))]
+struct Align16;
+
+#[repr(C, align(32))]
+struct Align32;
+
+#[repr(C, align(64))]
+struct Align64;
+
+#[repr(C, align(128))]
+struct Align128;
+
+#[repr(C, align(256))]
+struct Align256;
+
+#[repr(C, align(512))]
+struct Align512;
+
+#[repr(C, align(1024))]
+struct Align1024;
+
+#[repr(C, align(2048))]
+struct Align2048;
+
+#[repr(C, align(4096))]
+struct Align4096;
+
+#[repr(C, align(8192))]
+struct Align8192;
+
+#[repr(C, align(16384))]
+struct Align16384;
+
+#[repr(C, align(32768))]
+struct Align32768;
+
+#[repr(C, align(65536))]
+struct Align65536;
+
+#[repr(C, align(131072))]
+struct Align131072;
+
+#[repr(C, align(262144))]
+struct Align262144;
+
+#[repr(C, align(524288))]
+struct Align524288;
+
+#[repr(C, align(1048576))]
+struct Align1048576;
+
+#[repr(C, align(2097152))]
+struct Align2097152;
+
+#[repr(C, align(4194304))]
+struct Align4194304;
+
+#[repr(C, align(8388608))]
+struct Align8388608;
+
+#[repr(C, align(16777216))]
+struct Align16777216;
+
+#[repr(C, align(33554432))]
+struct Align33554432;
+
+#[repr(C, align(67108864))]
+struct Align67108864;
+
+#[repr(C, align(134217728))]
+struct Align13421772;
+
+#[repr(C, align(268435456))]
+struct Align26843545;
+
+#[repr(C, align(1073741824))]
+struct Align1073741824;
+
+fn main() {}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/max-align.stderr b/third_party/rust/zerocopy/tests/ui-nightly/max-align.stderr
new file mode 100644
index 0000000000..0cadb9a99a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/max-align.stderr
@@ -0,0 +1,5 @@
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+ --> tests/ui-nightly/max-align.rs:96:11
+ |
+96 | #[repr(C, align(1073741824))]
+ | ^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs
new file mode 100644
index 0000000000..c4caaff917
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..a9f1f7becf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-nightly/transmute-dst-not-frombytes.rs:18:41
+ |
+18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `NotZerocopy`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-nightly/transmute-dst-not-frombytes.rs:18:41
+ |
+18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.rs
new file mode 100644
index 0000000000..0928564dd5
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a type of smaller
+// alignment to one of larger alignment.
+const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.stderr
new file mode 100644
index 0000000000..0666f8b526
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-alignment-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-mut-alignment-increase.rs:19:39
+ |
+19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+ = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.rs
new file mode 100644
index 0000000000..021b562f18
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.rs
@@ -0,0 +1,20 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+const ARRAY_OF_U8S: [u8; 2] = [0u8; 2];
+
+// `transmute_mut!` cannot, generally speaking, be used in const contexts.
+const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.stderr
new file mode 100644
index 0000000000..fa53ed09a9
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-const.stderr
@@ -0,0 +1,42 @@
+warning: taking a mutable reference to a `const` item
+ --> tests/ui-nightly/transmute-mut-const.rs:20:52
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: each usage of a `const` item creates a new temporary
+ = note: the mutable reference will refer to this temporary, not the original `const` item
+note: `const` item defined here
+ --> tests/ui-nightly/transmute-mut-const.rs:17:1
+ |
+17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `#[warn(const_item_mutation)]` on by default
+
+error[E0658]: mutable references are not allowed in constants
+ --> tests/ui-nightly/transmute-mut-const.rs:20:52
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0015]: cannot call non-const fn `transmute_mut::<'_, '_, [u8; 2], [u8; 2]>` in constants
+ --> tests/ui-nightly/transmute-mut-const.rs:20:37
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0716]: temporary value dropped while borrowed
+ --> tests/ui-nightly/transmute-mut-const.rs:20:57
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | --------------------^^^^^^^^^^^^-
+ | | |
+ | | creates a temporary value which is freed while still in use
+ | temporary value is freed at the end of this statement
+ | using this value as a constant requires that borrow lasts for `'static`
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.rs
new file mode 100644
index 0000000000..7068f1026d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes>(u: &mut u8) -> &mut T {
+ // `transmute_mut!` requires the destination type to be concrete.
+ transmute_mut!(u)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.stderr
new file mode 100644
index 0000000000..f278558cf8
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-mut-dst-generic.rs:17:5
+ |
+17 | transmute_mut!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `T` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-mut-dst-generic.rs:17:5
+ |
+17 | transmute_mut!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<u8>` (8 bits)
+ = note: target type: `MaxAlignsOf<u8, T>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs
new file mode 100644
index 0000000000..33a9ecd955
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting into a non-reference
+// destination type.
+const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr
new file mode 100644
index 0000000000..a84547bd03
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.rs
new file mode 100644
index 0000000000..b72f12928c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the destination type implements `AsBytes`
+const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr
new file mode 100644
index 0000000000..54c8e6023f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `Dst: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-mut-dst-not-asbytes.rs:24:36
+ |
+24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `Dst`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-dst-not-asbytes.rs:24:36
+ |
+24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs
new file mode 100644
index 0000000000..102fcedc9a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..ea2123bc0b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
+ --> tests/ui-nightly/transmute-mut-dst-not-frombytes.rs:24:38
+ |
+24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `Dst`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-dst-not-frombytes.rs:24:38
+ |
+24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs
new file mode 100644
index 0000000000..693ccda56f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting into an unsized destination
+// type.
+const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr
new file mode 100644
index 0000000000..a670e25013
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr
@@ -0,0 +1,86 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs
new file mode 100644
index 0000000000..c31765e4b9
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs
@@ -0,0 +1,15 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+fn main() {}
+
+fn increase_lifetime() {
+ let mut x = 0u64;
+ // It is illegal to increase the lifetime scope.
+ let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr
new file mode 100644
index 0000000000..b826fcc7a9
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr
@@ -0,0 +1,12 @@
+error[E0597]: `x` does not live long enough
+ --> tests/ui-nightly/transmute-mut-illegal-lifetime.rs:14:56
+ |
+12 | let mut x = 0u64;
+ | ----- binding `x` declared here
+13 | // It is illegal to increase the lifetime scope.
+14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x);
+ | ---------------- ^^^^^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `x` is borrowed for `'static`
+15 | }
+ | - `x` dropped here while still borrowed
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.rs
new file mode 100644
index 0000000000..c6eec3a9c2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// We require that the size of the destination type is not smaller than the size
+// of the source type.
+const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.stderr
new file mode 100644
index 0000000000..ac1e35cec7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-mut-size-decrease.rs:17:32
+ |
+17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 2]` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.rs
new file mode 100644
index 0000000000..a4657c2838
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.stderr
new file mode 100644
index 0000000000..d343bd65e6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-mut-size-increase.rs:17:37
+ |
+17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `[u8; 2]` (16 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.rs
new file mode 100644
index 0000000000..aed7ded96f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes, U: AsBytes + FromBytes>(t: &mut T) -> &mut U {
+ // `transmute_mut!` requires the source and destination types to be
+ // concrete.
+ transmute_mut!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.stderr
new file mode 100644
index 0000000000..e3f3a3fd79
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-mut-src-dst-generic.rs:18:5
+ |
+18 | transmute_mut!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `U` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-mut-src-dst-generic.rs:18:5
+ |
+18 | transmute_mut!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, U>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs
new file mode 100644
index 0000000000..98cc520889
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting between non-reference source
+// and destination types.
+const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr
new file mode 100644
index 0000000000..df3cf2dba0
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-mut-src-dst-not-references.rs:17:59
+ |
+17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&mut _`, found `usize`
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found type `usize`
+help: consider mutably borrowing here
+ |
+17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(&mut 0usize);
+ | ++++
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.rs
new file mode 100644
index 0000000000..1bebcf2d68
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting between unsized source and
+// destination types.
+const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.stderr
new file mode 100644
index 0000000000..0f41a420eb
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-dst-unsized.stderr
@@ -0,0 +1,231 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.rs
new file mode 100644
index 0000000000..a3ef397876
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes>(t: &mut T) -> &mut u8 {
+ // `transmute_mut!` requires the source type to be concrete.
+ transmute_mut!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.stderr
new file mode 100644
index 0000000000..c06d775072
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-generic.stderr
@@ -0,0 +1,10 @@
+error[E0405]: cannot find trait `FromBytes` in this scope
+ --> tests/ui-nightly/transmute-mut-src-generic.rs:15:31
+ |
+15 | fn transmute_mut<T: AsBytes + FromBytes>(t: &mut T) -> &mut u8 {
+ | ^^^^^^^^^ not found in this scope
+ |
+help: consider importing this trait
+ |
+11 + use zerocopy::FromBytes;
+ |
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs
new file mode 100644
index 0000000000..08088d0db6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+fn ref_src_immutable() {
+ // `transmute_mut!` requires that its source type be a mutable reference.
+ let _: &mut u8 = transmute_mut!(&0u8);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr
new file mode 100644
index 0000000000..7b7969d5d5
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-mut-src-immutable.rs:17:37
+ |
+17 | let _: &mut u8 = transmute_mut!(&0u8);
+ | ---------------^^^^-
+ | | |
+ | | types differ in mutability
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found reference `&u8`
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs
new file mode 100644
index 0000000000..bf8bc32592
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a non-reference source
+// type.
+const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr
new file mode 100644
index 0000000000..12b7674f0e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-mut-src-not-a-reference.rs:17:53
+ |
+17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&mut _`, found `usize`
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found type `usize`
+help: consider mutably borrowing here
+ |
+17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(&mut 0usize);
+ | ++++
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.rs
new file mode 100644
index 0000000000..6a14f12fd0
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.stderr
new file mode 100644
index 0000000000..b755d3c654
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-asbytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `Src: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `Src`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `Src: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs
new file mode 100644
index 0000000000..2ebe03601b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the source type implements `FromBytes`
+const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr
new file mode 100644
index 0000000000..5a9f0a7a7f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `Src: FromBytes` is not satisfied
+ --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `Src`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `Src: FromBytes` is not satisfied
+ --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src`
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs
new file mode 100644
index 0000000000..413dd68d89
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs
@@ -0,0 +1,16 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from an unsized source type.
+const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr
new file mode 100644
index 0000000000..99475adee0
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr
@@ -0,0 +1,158 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs
new file mode 100644
index 0000000000..5af8859332
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs
@@ -0,0 +1,20 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// It is unclear whether we can or should support this transmutation, especially
+// in a const context. This test ensures that even if such a transmutation
+// becomes valid due to the requisite implementations of `FromBytes` being
+// added, that we re-examine whether it should specifically be valid in a const
+// context.
+const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr
new file mode 100644
index 0000000000..2fcba2fb6f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr
@@ -0,0 +1,30 @@
+error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `*const usize`
+ | required by a bound introduced by this call
+ |
+ = help: the trait `AsBytes` is implemented for `usize`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize`
+ |
+ = help: the trait `AsBytes` is implemented for `usize`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.rs
new file mode 100644
index 0000000000..bf1988c66b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a type of smaller
+// alignment to one of larger alignment.
+const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.stderr
new file mode 100644
index 0000000000..1cef246bc3
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-alignment-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-alignment-increase.rs:19:35
+ |
+19 | const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+ = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.rs
new file mode 100644
index 0000000000..bf4a0f9adf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, FromBytes};
+
+fn main() {}
+
+fn transmute_ref<T: FromBytes>(u: &u8) -> &T {
+ // `transmute_ref!` requires the destination type to be concrete.
+ transmute_ref!(u)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.stderr
new file mode 100644
index 0000000000..4c94d501c2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-dst-generic.rs:17:5
+ |
+17 | transmute_ref!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `T` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-dst-generic.rs:17:5
+ |
+17 | transmute_ref!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<u8>` (8 bits)
+ = note: target type: `MaxAlignsOf<u8, T>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs
new file mode 100644
index 0000000000..fa0e6e4c9b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+fn ref_dst_mutable() {
+ // `transmute_ref!` requires that its destination type be an immutable
+ // reference.
+ let _: &mut u8 = transmute_ref!(&0u8);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr
new file mode 100644
index 0000000000..0cbdd176b8
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs
new file mode 100644
index 0000000000..de55f9acdf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting into a non-reference
+// destination type.
+const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr
new file mode 100644
index 0000000000..847d54732e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs
new file mode 100644
index 0000000000..d81f64d21b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..e4791d76b0
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:18:42
+ |
+18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `NotZerocopy`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:18:42
+ |
+18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs
new file mode 100644
index 0000000000..625f1fac07
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting into an unsized destination
+// type.
+const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr
new file mode 100644
index 0000000000..3d0f6d0300
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr
@@ -0,0 +1,69 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs
new file mode 100644
index 0000000000..8dd191e6f4
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs
@@ -0,0 +1,15 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+fn main() {}
+
+fn increase_lifetime() {
+ let x = 0u64;
+ // It is illegal to increase the lifetime scope.
+ let _: &'static u64 = zerocopy::transmute_ref!(&x);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr
new file mode 100644
index 0000000000..e16a557611
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr
@@ -0,0 +1,12 @@
+error[E0597]: `x` does not live long enough
+ --> tests/ui-nightly/transmute-ref-illegal-lifetime.rs:14:52
+ |
+12 | let x = 0u64;
+ | - binding `x` declared here
+13 | // It is illegal to increase the lifetime scope.
+14 | let _: &'static u64 = zerocopy::transmute_ref!(&x);
+ | ------------ ^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `x` is borrowed for `'static`
+15 | }
+ | - `x` dropped here while still borrowed
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.rs
new file mode 100644
index 0000000000..1d66a54ef7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// Although this is not a soundness requirement, we currently require that the
+// size of the destination type is not smaller than the size of the source type.
+const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.stderr
new file mode 100644
index 0000000000..793ecc54c0
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-size-decrease.rs:17:28
+ |
+17 | const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 2]` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.rs
new file mode 100644
index 0000000000..cdca560b30
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.stderr
new file mode 100644
index 0000000000..40c69f63c4
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-size-increase.rs:17:33
+ |
+17 | const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `[u8; 2]` (16 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.rs
new file mode 100644
index 0000000000..409d785b20
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_ref<T: AsBytes, U: FromBytes>(t: &T) -> &U {
+ // `transmute_ref!` requires the source and destination types to be
+ // concrete.
+ transmute_ref!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.stderr
new file mode 100644
index 0000000000..6a3a4fd95b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-src-dst-generic.rs:18:5
+ |
+18 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `U` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-src-dst-generic.rs:18:5
+ |
+18 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, U>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs
new file mode 100644
index 0000000000..114e917b54
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting between non-reference source
+// and destination types.
+const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr
new file mode 100644
index 0000000000..0f1f7fc7b3
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr
@@ -0,0 +1,45 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:54
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&_`, found `usize`
+ | expected due to this
+ |
+ = note: expected reference `&_`
+ found type `usize`
+help: consider borrowing here
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(&0usize);
+ | +
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.rs
new file mode 100644
index 0000000000..6bfe7ffdfd
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting between unsized source and
+// destination types.
+const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.stderr
new file mode 100644
index 0000000000..02e62bce0b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-dst-unsized.stderr
@@ -0,0 +1,183 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.rs
new file mode 100644
index 0000000000..010281c32e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, AsBytes};
+
+fn main() {}
+
+fn transmute_ref<T: AsBytes>(t: &T) -> &u8 {
+ // `transmute_ref!` requires the source type to be concrete.
+ transmute_ref!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.stderr
new file mode 100644
index 0000000000..a168f44bb4
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-src-generic.rs:17:5
+ |
+17 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-ref-src-generic.rs:17:5
+ |
+17 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, u8>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs
new file mode 100644
index 0000000000..90661b3e2c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a non-reference source
+// type.
+const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr
new file mode 100644
index 0000000000..be477c6c5e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> tests/ui-nightly/transmute-ref-src-not-a-reference.rs:17:49
+ |
+17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&_`, found `usize`
+ | expected due to this
+ |
+ = note: expected reference `&_`
+ found type `usize`
+help: consider borrowing here
+ |
+17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(&0usize);
+ | +
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.rs
new file mode 100644
index 0000000000..6ab19f3c82
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.stderr
new file mode 100644
index 0000000000..eb28ccf7c8
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-not-asbytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs
new file mode 100644
index 0000000000..14e72b4ddc
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs
@@ -0,0 +1,16 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from an unsized source type.
+const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr
new file mode 100644
index 0000000000..b280429b03
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr
@@ -0,0 +1,127 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.rs
new file mode 100644
index 0000000000..1d56831f22
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// Although this is not a soundness requirement, we currently require that the
+// size of the destination type is not smaller than the size of the source type.
+const DECREASE_SIZE: u8 = transmute!(AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr
new file mode 100644
index 0000000000..83742d7824
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-size-decrease.rs:19:27
+ |
+19 | const DECREASE_SIZE: u8 = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AU16` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.rs
new file mode 100644
index 0000000000..32f9363089
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: AU16 = transmute!(0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.stderr
new file mode 100644
index 0000000000..230bb17a77
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-nightly/transmute-size-increase.rs:19:29
+ |
+19 | const INCREASE_SIZE: AU16 = transmute!(0u8);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `AU16` (16 bits)
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.rs
new file mode 100644
index 0000000000..dd730216b6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
diff --git a/third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.stderr
new file mode 100644
index 0000000000..b36a820686
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-nightly/transmute-src-not-asbytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs b/third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs
new file mode 100644
index 0000000000..45b6138f47
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs
@@ -0,0 +1,12 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+// Should fail because `UnsafeCell<u32>: !FromBytes`.
+const NOT_FROM_BYTES: core::cell::UnsafeCell<u32> =
+ include_value!("../../testdata/include_value/data");
diff --git a/third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr
new file mode 100644
index 0000000000..7e9a035dc3
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `UnsafeCell<u32>: FromBytes` is not satisfied
+ --> tests/ui-stable/include_value_not_from_bytes.rs:12:5
+ |
+12 | include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `UnsafeCell<u32>`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-stable/include_value_not_from_bytes.rs:12:5
+ |
+12 | include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.rs b/third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.rs
new file mode 100644
index 0000000000..d87b30698b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.rs
@@ -0,0 +1,11 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#[macro_use]
+extern crate zerocopy;
+
+fn main() {}
+
+// Should fail because the file is 4 bytes long, not 8.
+const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data");
diff --git a/third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.stderr b/third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.stderr
new file mode 100644
index 0000000000..956d74c505
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/include_value_wrong_size.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/include_value_wrong_size.rs:11:25
+ |
+11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 4]` (32 bits)
+ = note: target type: `u64` (64 bits)
+ = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs b/third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs
new file mode 100644
index 0000000000..ea963907df
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs
@@ -0,0 +1,29 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+// Since some macros from `macros.rs` are unused.
+#![allow(unused)]
+
+extern crate zerocopy;
+extern crate zerocopy_derive;
+
+include!("../../../src/macros.rs");
+
+use zerocopy::*;
+use zerocopy_derive::*;
+
+fn main() {}
+
+#[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+#[repr(transparent)]
+struct Foo<T>(T);
+
+impl_or_verify!(T => FromZeroes for Foo<T>);
+impl_or_verify!(T => FromBytes for Foo<T>);
+impl_or_verify!(T => AsBytes for Foo<T>);
+impl_or_verify!(T => Unaligned for Foo<T>);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr b/third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr
new file mode 100644
index 0000000000..7737d67175
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr
@@ -0,0 +1,107 @@
+error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:26:37
+ |
+26 | impl_or_verify!(T => FromZeroes for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::FromZeroes`
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:10
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-stable/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-stable/invalid-impls/invalid-impls.rs:26:1
+ |
+26 | impl_or_verify!(T => FromZeroes for Foo<T>);
+ | ------------------------------------------- in this macro invocation
+ = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+26 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo<T>);
+ | ++++++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:27:36
+ |
+27 | impl_or_verify!(T => FromBytes for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::FromBytes`
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:22
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-stable/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-stable/invalid-impls/invalid-impls.rs:27:1
+ |
+27 | impl_or_verify!(T => FromBytes for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+27 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo<T>);
+ | +++++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:28:34
+ |
+28 | impl_or_verify!(T => AsBytes for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::AsBytes`
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:33
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-stable/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-stable/invalid-impls/invalid-impls.rs:28:1
+ |
+28 | impl_or_verify!(T => AsBytes for Foo<T>);
+ | ---------------------------------------- in this macro invocation
+ = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+28 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo<T>);
+ | +++++++++++++++++++
+
+error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:29:36
+ |
+29 | impl_or_verify!(T => Unaligned for Foo<T>);
+ | ^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `zerocopy::Unaligned`
+ --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:42
+ |
+22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
+ | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `_::Subtrait`
+ --> tests/ui-stable/invalid-impls/../../../src/macros.rs
+ |
+ | trait Subtrait: $trait {}
+ | ^^^^^^ required by this bound in `Subtrait`
+ |
+ ::: tests/ui-stable/invalid-impls/invalid-impls.rs:29:1
+ |
+29 | impl_or_verify!(T => Unaligned for Foo<T>);
+ | ------------------------------------------ in this macro invocation
+ = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo<T>);
+ | +++++++++++++++++++++
diff --git a/third_party/rust/zerocopy/tests/ui-stable/max-align.rs b/third_party/rust/zerocopy/tests/ui-stable/max-align.rs
new file mode 100644
index 0000000000..53e3eb9b0a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/max-align.rs
@@ -0,0 +1,99 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+#[repr(C, align(1))]
+struct Align1;
+
+#[repr(C, align(2))]
+struct Align2;
+
+#[repr(C, align(4))]
+struct Align4;
+
+#[repr(C, align(8))]
+struct Align8;
+
+#[repr(C, align(16))]
+struct Align16;
+
+#[repr(C, align(32))]
+struct Align32;
+
+#[repr(C, align(64))]
+struct Align64;
+
+#[repr(C, align(128))]
+struct Align128;
+
+#[repr(C, align(256))]
+struct Align256;
+
+#[repr(C, align(512))]
+struct Align512;
+
+#[repr(C, align(1024))]
+struct Align1024;
+
+#[repr(C, align(2048))]
+struct Align2048;
+
+#[repr(C, align(4096))]
+struct Align4096;
+
+#[repr(C, align(8192))]
+struct Align8192;
+
+#[repr(C, align(16384))]
+struct Align16384;
+
+#[repr(C, align(32768))]
+struct Align32768;
+
+#[repr(C, align(65536))]
+struct Align65536;
+
+#[repr(C, align(131072))]
+struct Align131072;
+
+#[repr(C, align(262144))]
+struct Align262144;
+
+#[repr(C, align(524288))]
+struct Align524288;
+
+#[repr(C, align(1048576))]
+struct Align1048576;
+
+#[repr(C, align(2097152))]
+struct Align2097152;
+
+#[repr(C, align(4194304))]
+struct Align4194304;
+
+#[repr(C, align(8388608))]
+struct Align8388608;
+
+#[repr(C, align(16777216))]
+struct Align16777216;
+
+#[repr(C, align(33554432))]
+struct Align33554432;
+
+#[repr(C, align(67108864))]
+struct Align67108864;
+
+#[repr(C, align(134217728))]
+struct Align13421772;
+
+#[repr(C, align(268435456))]
+struct Align26843545;
+
+#[repr(C, align(1073741824))]
+struct Align1073741824;
+
+fn main() {}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/max-align.stderr b/third_party/rust/zerocopy/tests/ui-stable/max-align.stderr
new file mode 100644
index 0000000000..ea472f2df7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/max-align.stderr
@@ -0,0 +1,5 @@
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+ --> tests/ui-stable/max-align.rs:96:11
+ |
+96 | #[repr(C, align(1073741824))]
+ | ^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs
new file mode 100644
index 0000000000..c4caaff917
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..b008bcdb10
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-stable/transmute-dst-not-frombytes.rs:18:41
+ |
+18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `NotZerocopy`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-stable/transmute-dst-not-frombytes.rs:18:41
+ |
+18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.rs
new file mode 100644
index 0000000000..0928564dd5
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a type of smaller
+// alignment to one of larger alignment.
+const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.stderr
new file mode 100644
index 0000000000..252fec9ef8
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-alignment-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-mut-alignment-increase.rs:19:39
+ |
+19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+ = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.rs
new file mode 100644
index 0000000000..021b562f18
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.rs
@@ -0,0 +1,20 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+const ARRAY_OF_U8S: [u8; 2] = [0u8; 2];
+
+// `transmute_mut!` cannot, generally speaking, be used in const contexts.
+const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.stderr
new file mode 100644
index 0000000000..a89ea67558
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-const.stderr
@@ -0,0 +1,41 @@
+warning: taking a mutable reference to a `const` item
+ --> tests/ui-stable/transmute-mut-const.rs:20:52
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: each usage of a `const` item creates a new temporary
+ = note: the mutable reference will refer to this temporary, not the original `const` item
+note: `const` item defined here
+ --> tests/ui-stable/transmute-mut-const.rs:17:1
+ |
+17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `#[warn(const_item_mutation)]` on by default
+
+error[E0658]: mutable references are not allowed in constants
+ --> tests/ui-stable/transmute-mut-const.rs:20:52
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+
+error[E0015]: cannot call non-const fn `transmute_mut::<'_, '_, [u8; 2], [u8; 2]>` in constants
+ --> tests/ui-stable/transmute-mut-const.rs:20:37
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0716]: temporary value dropped while borrowed
+ --> tests/ui-stable/transmute-mut-const.rs:20:57
+ |
+20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S);
+ | --------------------^^^^^^^^^^^^-
+ | | |
+ | | creates a temporary value which is freed while still in use
+ | temporary value is freed at the end of this statement
+ | using this value as a constant requires that borrow lasts for `'static`
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.rs
new file mode 100644
index 0000000000..7068f1026d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes>(u: &mut u8) -> &mut T {
+ // `transmute_mut!` requires the destination type to be concrete.
+ transmute_mut!(u)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.stderr
new file mode 100644
index 0000000000..0000eb0bab
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-mut-dst-generic.rs:17:5
+ |
+17 | transmute_mut!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `T` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-mut-dst-generic.rs:17:5
+ |
+17 | transmute_mut!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<u8>` (8 bits)
+ = note: target type: `MaxAlignsOf<u8, T>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs
new file mode 100644
index 0000000000..33a9ecd955
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting into a non-reference
+// destination type.
+const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr
new file mode 100644
index 0000000000..14ee444cc5
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
+ |
+ = note: expected type `usize`
+ found mutable reference `&mut _`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.rs
new file mode 100644
index 0000000000..b72f12928c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the destination type implements `AsBytes`
+const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.stderr
new file mode 100644
index 0000000000..f3cacca09d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-asbytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `Dst: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-mut-dst-not-asbytes.rs:24:36
+ |
+24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `Dst`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-stable/transmute-mut-dst-not-asbytes.rs:24:36
+ |
+24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs
new file mode 100644
index 0000000000..102fcedc9a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..39bb4fd96d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
+ --> tests/ui-stable/transmute-mut-dst-not-frombytes.rs:24:38
+ |
+24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `Dst`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-stable/transmute-mut-dst-not-frombytes.rs:24:38
+ |
+24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs
new file mode 100644
index 0000000000..693ccda56f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting into an unsized destination
+// type.
+const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr
new file mode 100644
index 0000000000..07727850cd
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr
@@ -0,0 +1,106 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32
+ |
+17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs
new file mode 100644
index 0000000000..c31765e4b9
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs
@@ -0,0 +1,15 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+fn main() {}
+
+fn increase_lifetime() {
+ let mut x = 0u64;
+ // It is illegal to increase the lifetime scope.
+ let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr
new file mode 100644
index 0000000000..7f128138f3
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr
@@ -0,0 +1,12 @@
+error[E0597]: `x` does not live long enough
+ --> tests/ui-stable/transmute-mut-illegal-lifetime.rs:14:56
+ |
+12 | let mut x = 0u64;
+ | ----- binding `x` declared here
+13 | // It is illegal to increase the lifetime scope.
+14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x);
+ | ---------------- ^^^^^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `x` is borrowed for `'static`
+15 | }
+ | - `x` dropped here while still borrowed
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.rs
new file mode 100644
index 0000000000..c6eec3a9c2
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// We require that the size of the destination type is not smaller than the size
+// of the source type.
+const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.stderr
new file mode 100644
index 0000000000..239991357d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-mut-size-decrease.rs:17:32
+ |
+17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 2]` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.rs
new file mode 100644
index 0000000000..a4657c2838
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.stderr
new file mode 100644
index 0000000000..1427c7b0e9
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-mut-size-increase.rs:17:37
+ |
+17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `[u8; 2]` (16 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.rs
new file mode 100644
index 0000000000..aed7ded96f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes, U: AsBytes + FromBytes>(t: &mut T) -> &mut U {
+ // `transmute_mut!` requires the source and destination types to be
+ // concrete.
+ transmute_mut!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.stderr
new file mode 100644
index 0000000000..ddb8bb6fe7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-mut-src-dst-generic.rs:18:5
+ |
+18 | transmute_mut!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `U` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-mut-src-dst-generic.rs:18:5
+ |
+18 | transmute_mut!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, U>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs
new file mode 100644
index 0000000000..98cc520889
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting between non-reference source
+// and destination types.
+const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr
new file mode 100644
index 0000000000..c0d9e0f0d3
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-mut-src-dst-not-references.rs:17:59
+ |
+17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&mut _`, found `usize`
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found type `usize`
+help: consider mutably borrowing here
+ |
+17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(&mut 0usize);
+ | ++++
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.rs
new file mode 100644
index 0000000000..1bebcf2d68
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting between unsized source and
+// destination types.
+const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr
new file mode 100644
index 0000000000..8cf76649eb
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr
@@ -0,0 +1,288 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsFromBytes`
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertDstIsAsBytes`
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36
+ |
+17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.rs
new file mode 100644
index 0000000000..a3ef397876
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_mut, AsBytes};
+
+fn main() {}
+
+fn transmute_mut<T: AsBytes + FromBytes>(t: &mut T) -> &mut u8 {
+ // `transmute_mut!` requires the source type to be concrete.
+ transmute_mut!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.stderr
new file mode 100644
index 0000000000..fc4809e418
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-generic.stderr
@@ -0,0 +1,10 @@
+error[E0405]: cannot find trait `FromBytes` in this scope
+ --> tests/ui-stable/transmute-mut-src-generic.rs:15:31
+ |
+15 | fn transmute_mut<T: AsBytes + FromBytes>(t: &mut T) -> &mut u8 {
+ | ^^^^^^^^^ not found in this scope
+ |
+help: consider importing this trait
+ |
+11 + use zerocopy::FromBytes;
+ |
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs
new file mode 100644
index 0000000000..08088d0db6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+fn ref_src_immutable() {
+ // `transmute_mut!` requires that its source type be a mutable reference.
+ let _: &mut u8 = transmute_mut!(&0u8);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr
new file mode 100644
index 0000000000..0115c791d3
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-mut-src-immutable.rs:17:37
+ |
+17 | let _: &mut u8 = transmute_mut!(&0u8);
+ | ---------------^^^^-
+ | | |
+ | | types differ in mutability
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found reference `&u8`
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs
new file mode 100644
index 0000000000..bf8bc32592
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from a non-reference source
+// type.
+const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr
new file mode 100644
index 0000000000..8c1d9b47ba
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-mut-src-not-a-reference.rs:17:53
+ |
+17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&mut _`, found `usize`
+ | expected due to this
+ |
+ = note: expected mutable reference `&mut _`
+ found type `usize`
+help: consider mutably borrowing here
+ |
+17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(&mut 0usize);
+ | ++++
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.rs
new file mode 100644
index 0000000000..6a14f12fd0
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.stderr
new file mode 100644
index 0000000000..9fc954654e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-asbytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `Src: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `Src`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `Src: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36
+ |
+24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs
new file mode 100644
index 0000000000..2ebe03601b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs
@@ -0,0 +1,24 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+#[derive(zerocopy::AsBytes)]
+#[repr(C)]
+struct Src;
+
+#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)]
+#[repr(C)]
+struct Dst;
+
+// `transmute_mut` requires that the source type implements `FromBytes`
+const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr
new file mode 100644
index 0000000000..cc4a19d724
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `Src: FromBytes` is not satisfied
+ --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `Src`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `Src: FromBytes` is not satisfied
+ --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src`
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38
+ |
+24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs
new file mode 100644
index 0000000000..413dd68d89
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs
@@ -0,0 +1,16 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_mut;
+
+fn main() {}
+
+// `transmute_mut!` does not support transmuting from an unsized source type.
+const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr
new file mode 100644
index 0000000000..7f6def929d
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr
@@ -0,0 +1,195 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsFromBytes`
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertSrcIsAsBytes`
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35
+ |
+16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_mut`
+ --> src/macro_util.rs
+ |
+ | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_mut`
+ = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs
new file mode 100644
index 0000000000..5af8859332
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs
@@ -0,0 +1,20 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// It is unclear whether we can or should support this transmutation, especially
+// in a const context. This test ensures that even if such a transmutation
+// becomes valid due to the requisite implementations of `FromBytes` being
+// added, that we re-examine whether it should specifically be valid in a const
+// context.
+const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr
new file mode 100644
index 0000000000..4f4d583dbe
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr
@@ -0,0 +1,30 @@
+error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `*const usize`
+ | required by a bound introduced by this call
+ |
+ = help: the trait `AsBytes` is implemented for `usize`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize`
+ |
+ = help: the trait `AsBytes` is implemented for `usize`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30
+ |
+20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.rs
new file mode 100644
index 0000000000..bf1988c66b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a type of smaller
+// alignment to one of larger alignment.
+const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.stderr
new file mode 100644
index 0000000000..a34c4065d1
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-alignment-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-alignment-increase.rs:19:35
+ |
+19 | const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<[u8; 2]>` (8 bits)
+ = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.rs
new file mode 100644
index 0000000000..bf4a0f9adf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, FromBytes};
+
+fn main() {}
+
+fn transmute_ref<T: FromBytes>(u: &u8) -> &T {
+ // `transmute_ref!` requires the destination type to be concrete.
+ transmute_ref!(u)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.stderr
new file mode 100644
index 0000000000..e30b9f67a6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-dst-generic.rs:17:5
+ |
+17 | transmute_ref!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `T` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-dst-generic.rs:17:5
+ |
+17 | transmute_ref!(u)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<u8>` (8 bits)
+ = note: target type: `MaxAlignsOf<u8, T>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs
new file mode 100644
index 0000000000..fa0e6e4c9b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+fn ref_dst_mutable() {
+ // `transmute_ref!` requires that its destination type be an immutable
+ // reference.
+ let _: &mut u8 = transmute_ref!(&0u8);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr
new file mode 100644
index 0000000000..c70f6ea618
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22
+ |
+18 | let _: &mut u8 = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut u8`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs
new file mode 100644
index 0000000000..de55f9acdf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting into a non-reference
+// destination type.
+const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr
new file mode 100644
index 0000000000..ab3f90c2fd
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36
+ |
+17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs
new file mode 100644
index 0000000000..d81f64d21b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref` requires that the destination type implements `FromBytes`
+const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr
new file mode 100644
index 0000000000..76d18c5e45
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
+ --> tests/ui-stable/transmute-ref-dst-not-frombytes.rs:18:42
+ |
+18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `FromBytes` is not implemented for `NotZerocopy`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `FromBytes`:
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ usize
+ u8
+ and $N others
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-stable/transmute-ref-dst-not-frombytes.rs:18:42
+ |
+18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs
new file mode 100644
index 0000000000..625f1fac07
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting into an unsized destination
+// type.
+const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr
new file mode 100644
index 0000000000..8a0c761466
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr
@@ -0,0 +1,89 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28
+ |
+17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs
new file mode 100644
index 0000000000..8dd191e6f4
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs
@@ -0,0 +1,15 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+fn main() {}
+
+fn increase_lifetime() {
+ let x = 0u64;
+ // It is illegal to increase the lifetime scope.
+ let _: &'static u64 = zerocopy::transmute_ref!(&x);
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr
new file mode 100644
index 0000000000..1ef34feb7f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr
@@ -0,0 +1,12 @@
+error[E0597]: `x` does not live long enough
+ --> tests/ui-stable/transmute-ref-illegal-lifetime.rs:14:52
+ |
+12 | let x = 0u64;
+ | - binding `x` declared here
+13 | // It is illegal to increase the lifetime scope.
+14 | let _: &'static u64 = zerocopy::transmute_ref!(&x);
+ | ------------ ^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `x` is borrowed for `'static`
+15 | }
+ | - `x` dropped here while still borrowed
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.rs
new file mode 100644
index 0000000000..1d66a54ef7
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// Although this is not a soundness requirement, we currently require that the
+// size of the destination type is not smaller than the size of the source type.
+const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.stderr
new file mode 100644
index 0000000000..f353b26ece
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-size-decrease.rs:17:28
+ |
+17 | const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `[u8; 2]` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.rs
new file mode 100644
index 0000000000..cdca560b30
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.stderr
new file mode 100644
index 0000000000..f51eb63f4b
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-size-increase.rs:17:33
+ |
+17 | const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `[u8; 2]` (16 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.rs
new file mode 100644
index 0000000000..409d785b20
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, AsBytes, FromBytes};
+
+fn main() {}
+
+fn transmute_ref<T: AsBytes, U: FromBytes>(t: &T) -> &U {
+ // `transmute_ref!` requires the source and destination types to be
+ // concrete.
+ transmute_ref!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.stderr
new file mode 100644
index 0000000000..0905dc6d5f
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-src-dst-generic.rs:18:5
+ |
+18 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `U` (this type does not have a fixed size)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-src-dst-generic.rs:18:5
+ |
+18 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, U>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs
new file mode 100644
index 0000000000..114e917b54
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting between non-reference source
+// and destination types.
+const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr
new file mode 100644
index 0000000000..8a80e991e6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr
@@ -0,0 +1,45 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:54
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&_`, found `usize`
+ | expected due to this
+ |
+ = note: expected reference `&_`
+ found type `usize`
+help: consider borrowing here
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(&0usize);
+ | +
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39
+ |
+17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
+ |
+ = note: expected type `usize`
+ found reference `&_`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.rs
new file mode 100644
index 0000000000..6bfe7ffdfd
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting between unsized source and
+// destination types.
+const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr
new file mode 100644
index 0000000000..ca62fcf7db
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr
@@ -0,0 +1,240 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsFromBytes`
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32
+ |
+17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.rs
new file mode 100644
index 0000000000..010281c32e
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::{transmute_ref, AsBytes};
+
+fn main() {}
+
+fn transmute_ref<T: AsBytes>(t: &T) -> &u8 {
+ // `transmute_ref!` requires the source type to be concrete.
+ transmute_ref!(t)
+}
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.stderr
new file mode 100644
index 0000000000..b6bbd1648a
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-generic.stderr
@@ -0,0 +1,19 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-src-generic.rs:17:5
+ |
+17 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `T` (this type does not have a fixed size)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-ref-src-generic.rs:17:5
+ |
+17 | transmute_ref!(t)
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AlignOf<T>` (size can vary because of T)
+ = note: target type: `MaxAlignsOf<T, u8>` (size can vary because of T)
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs
new file mode 100644
index 0000000000..90661b3e2c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs
@@ -0,0 +1,17 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from a non-reference source
+// type.
+const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr
new file mode 100644
index 0000000000..622c3db9ac
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> tests/ui-stable/transmute-ref-src-not-a-reference.rs:17:49
+ |
+17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize);
+ | ---------------^^^^^^-
+ | | |
+ | | expected `&_`, found `usize`
+ | expected due to this
+ |
+ = note: expected reference `&_`
+ found type `usize`
+help: consider borrowing here
+ |
+17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(&0usize);
+ | +
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.rs
new file mode 100644
index 0000000000..6ab19f3c82
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.stderr
new file mode 100644
index 0000000000..2ded6baa03
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-not-asbytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33
+ |
+18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs
new file mode 100644
index 0000000000..14e72b4ddc
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs
@@ -0,0 +1,16 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::transmute_ref;
+
+fn main() {}
+
+// `transmute_ref!` does not support transmuting from an unsized source type.
+const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr
new file mode 100644
index 0000000000..b194d67473
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr
@@ -0,0 +1,164 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute`
+ --> $RUST/core/src/intrinsics.rs
+ |
+ | pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ | ^^^ required by this bound in `transmute`
+ = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf::<T>::into_t`
+ --> src/macro_util.rs
+ |
+ | impl<T> AlignOf<T> {
+ | ^ required by this bound in `AlignOf::<T>::into_t`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn into_t(self) -> T {
+ | ------ required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: the left-hand-side of an assignment must have a statically known size
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf::<T, U>::new`
+ --> src/macro_util.rs
+ |
+ | impl<T, U> MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf::<T, U>::new`
+ | #[inline(never)] // Make `missing_inline_in_public_items` happy.
+ | pub fn new(_t: T, _u: U) -> MaxAlignsOf<T, U> {
+ | --- required by a bound in this associated function
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `MaxAlignsOf`
+ --> src/macro_util.rs
+ |
+ | pub union MaxAlignsOf<T, U> {
+ | ^ required by this bound in `MaxAlignsOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `AlignOf`
+ --> src/macro_util.rs
+ |
+ | pub struct AlignOf<T> {
+ | ^ required by this bound in `AlignOf`
+ = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31
+ |
+16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `transmute_ref`
+ --> src/macro_util.rs
+ |
+ | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
+ | ^^^ required by this bound in `transmute_ref`
+ = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.rs
new file mode 100644
index 0000000000..1d56831f22
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// Although this is not a soundness requirement, we currently require that the
+// size of the destination type is not smaller than the size of the source type.
+const DECREASE_SIZE: u8 = transmute!(AU16(0));
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.stderr
new file mode 100644
index 0000000000..0241662fdf
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-decrease.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-size-decrease.rs:19:27
+ |
+19 | const DECREASE_SIZE: u8 = transmute!(AU16(0));
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `AU16` (16 bits)
+ = note: target type: `u8` (8 bits)
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.rs
new file mode 100644
index 0000000000..32f9363089
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.rs
@@ -0,0 +1,19 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute!` does not support transmuting from a smaller type to a larger
+// one.
+const INCREASE_SIZE: AU16 = transmute!(0u8);
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.stderr
new file mode 100644
index 0000000000..87d82a208c
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-size-increase.stderr
@@ -0,0 +1,9 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> tests/ui-stable/transmute-size-increase.rs:19:29
+ |
+19 | const INCREASE_SIZE: AU16 = transmute!(0u8);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: source type: `u8` (8 bits)
+ = note: target type: `AU16` (16 bits)
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.rs b/third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.rs
new file mode 100644
index 0000000000..dd730216b6
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.rs
@@ -0,0 +1,18 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+include!("../../zerocopy-derive/tests/util.rs");
+
+extern crate zerocopy;
+
+use zerocopy::transmute;
+
+fn main() {}
+
+// `transmute` requires that the source type implements `AsBytes`
+const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
diff --git a/third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.stderr b/third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.stderr
new file mode 100644
index 0000000000..f2e834eb57
--- /dev/null
+++ b/third_party/rust/zerocopy/tests/ui-stable/transmute-src-not-asbytes.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotZerocopy<AU16>: AsBytes` is not satisfied
+ --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy<AU16>`
+ |
+ = help: the following other types implement trait `AsBytes`:
+ bool
+ char
+ isize
+ i8
+ i16
+ i32
+ i64
+ i128
+ and $N others
+note: required by a bound in `AssertIsAsBytes`
+ --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32
+ |
+18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0)));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes`
+ = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp b/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp
index 7bcc4da241..a7b8e2f90d 100644
--- a/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp
+++ b/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp
@@ -2064,7 +2064,7 @@ namespace xsimd
inline T reduce(Op op, batch<T, A> const& self, std::integral_constant<unsigned, Lvl>) noexcept
{
using index_type = as_unsigned_integer_t<T>;
- batch<T, A> split = swizzle(self, make_batch_constant<batch<index_type, A>, split_high<index_type, Lvl / 2>>());
+ batch<T, A> split = swizzle(self, make_batch_constant<index_type, A, split_high<index_type, Lvl / 2>>());
return reduce(op, op(split, self), std::integral_constant<unsigned, Lvl / 2>());
}
}
diff --git a/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_memory.hpp b/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_memory.hpp
index e9e9065832..f92f6b48b4 100644
--- a/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_memory.hpp
+++ b/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_memory.hpp
@@ -21,10 +21,10 @@
namespace xsimd
{
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant;
- template <class batch_type, bool... Values>
+ template <typename T, class A, bool... Values>
struct batch_bool_constant;
namespace kernel
@@ -180,7 +180,7 @@ namespace xsimd
}
};
batch<T, A> tmp(val);
- return select(make_batch_bool_constant<batch<T, A>, index_mask>(), self, tmp);
+ return select(make_batch_bool_constant<T, A, index_mask>(), self, tmp);
}
// get
@@ -295,7 +295,7 @@ namespace xsimd
}
};
- return swizzle(self, make_batch_constant<batch<as_unsigned_integer_t<T>, A>, rotate_generator>(), A {});
+ return swizzle(self, make_batch_constant<as_unsigned_integer_t<T>, A, rotate_generator>(), A {});
}
template <size_t N, class A, class T>
@@ -316,7 +316,7 @@ namespace xsimd
}
};
- return swizzle(self, make_batch_constant<batch<as_unsigned_integer_t<T>, A>, rotate_generator>(), A {});
+ return swizzle(self, make_batch_constant<as_unsigned_integer_t<T>, A, rotate_generator>(), A {});
}
template <size_t N, class A, class T>
@@ -412,6 +412,12 @@ namespace xsimd
return true;
}
+ template <typename ITy>
+ constexpr bool is_zip_lo(size_t, ITy)
+ {
+ return false;
+ }
+
template <typename ITy0, typename ITy1, typename... ITys>
constexpr bool is_zip_lo(size_t bsize, ITy0 index0, ITy1 index1, ITys... indices)
{
@@ -423,6 +429,12 @@ namespace xsimd
return true;
}
+ template <typename ITy>
+ constexpr bool is_zip_hi(size_t, ITy)
+ {
+ return false;
+ }
+
template <typename ITy0, typename ITy1, typename... ITys>
constexpr bool is_zip_hi(size_t bsize, ITy0 index0, ITy1 index1, ITys... indices)
{
@@ -443,19 +455,19 @@ namespace xsimd
}
template <class A, typename T, typename ITy, ITy... Indices>
- inline batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<batch<ITy, A>, Indices...>, requires_arch<generic>) noexcept
+ inline batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<ITy, A, Indices...>, requires_arch<generic>) noexcept
{
constexpr size_t bsize = sizeof...(Indices);
// Detect common patterns
XSIMD_IF_CONSTEXPR(detail::is_swizzle_fst(bsize, Indices...))
{
- return swizzle(x, batch_constant<batch<ITy, A>, ((Indices >= bsize) ? 0 /* never happens */ : Indices)...>());
+ return swizzle(x, batch_constant<ITy, A, ((Indices >= bsize) ? 0 /* never happens */ : Indices)...>());
}
XSIMD_IF_CONSTEXPR(detail::is_swizzle_snd(bsize, Indices...))
{
- return swizzle(y, batch_constant<batch<ITy, A>, ((Indices >= bsize) ? (Indices - bsize) : 0 /* never happens */)...>());
+ return swizzle(y, batch_constant<ITy, A, ((Indices >= bsize) ? (Indices - bsize) : 0 /* never happens */)...>());
}
XSIMD_IF_CONSTEXPR(detail::is_zip_lo(bsize, Indices...))
@@ -470,7 +482,7 @@ namespace xsimd
XSIMD_IF_CONSTEXPR(detail::is_select(bsize, Indices...))
{
- return select(batch_bool_constant<batch<T, A>, (Indices < bsize)...>(), x, y);
+ return select(batch_bool_constant<T, A, (Indices < bsize)...>(), x, y);
}
#if defined(__has_builtin)
@@ -491,9 +503,9 @@ namespace xsimd
#else
// Use a generic_pattern. It is suboptimal but clang optimizes this
// pretty well.
- batch<T, A> x_lane = swizzle(x, batch_constant<batch<ITy, A>, ((Indices >= bsize) ? (Indices - bsize) : Indices)...>());
- batch<T, A> y_lane = swizzle(y, batch_constant<batch<ITy, A>, ((Indices >= bsize) ? (Indices - bsize) : Indices)...>());
- batch_bool_constant<batch<T, A>, (Indices < bsize)...> select_x_lane;
+ batch<T, A> x_lane = swizzle(x, batch_constant<ITy, A, ((Indices >= bsize) ? (Indices - bsize) : Indices)...>());
+ batch<T, A> y_lane = swizzle(y, batch_constant<ITy, A, ((Indices >= bsize) ? (Indices - bsize) : Indices)...>());
+ batch_bool_constant<T, A, (Indices < bsize)...> select_x_lane;
return select(select_x_lane, x_lane, y_lane);
#endif
}
@@ -530,7 +542,7 @@ namespace xsimd
// swizzle
template <class A, class T, class ITy, ITy... Vs>
- inline batch<std::complex<T>, A> swizzle(batch<std::complex<T>, A> const& self, batch_constant<batch<ITy, A>, Vs...> mask, requires_arch<generic>) noexcept
+ inline batch<std::complex<T>, A> swizzle(batch<std::complex<T>, A> const& self, batch_constant<ITy, A, Vs...> mask, requires_arch<generic>) noexcept
{
return { swizzle(self.real(), mask), swizzle(self.imag(), mask) };
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_avx.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_avx.hpp
index 5ec1e02d48..66bcb45022 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_avx.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_avx.hpp
@@ -1161,22 +1161,22 @@ namespace xsimd
return detail::merge_sse(res_low, res_hi);
}
template <class A, class T, bool... Values, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<avx>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<avx>) noexcept
{
return select(batch_bool<T, A> { Values... }, true_br, false_br, avx2 {});
}
template <class A, bool... Values>
- inline batch<float, A> select(batch_bool_constant<batch<float, A>, Values...> const&, batch<float, A> const& true_br, batch<float, A> const& false_br, requires_arch<avx>) noexcept
+ inline batch<float, A> select(batch_bool_constant<float, A, Values...> const&, batch<float, A> const& true_br, batch<float, A> const& false_br, requires_arch<avx>) noexcept
{
- constexpr auto mask = batch_bool_constant<batch<float, A>, Values...>::mask();
+ constexpr auto mask = batch_bool_constant<float, A, Values...>::mask();
return _mm256_blend_ps(false_br, true_br, mask);
}
template <class A, bool... Values>
- inline batch<double, A> select(batch_bool_constant<batch<double, A>, Values...> const&, batch<double, A> const& true_br, batch<double, A> const& false_br, requires_arch<avx>) noexcept
+ inline batch<double, A> select(batch_bool_constant<double, A, Values...> const&, batch<double, A> const& true_br, batch<double, A> const& false_br, requires_arch<avx>) noexcept
{
- constexpr auto mask = batch_bool_constant<batch<double, A>, Values...>::mask();
+ constexpr auto mask = batch_bool_constant<double, A, Values...>::mask();
return _mm256_blend_pd(false_br, true_br, mask);
}
@@ -1238,7 +1238,7 @@ namespace xsimd
// shuffle
template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3, ITy I4, ITy I5, ITy I6, ITy I7>
- inline batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<batch<ITy, A>, I0, I1, I2, I3, I4, I5, I6, I7> mask, requires_arch<avx>) noexcept
+ inline batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<ITy, A, I0, I1, I2, I3, I4, I5, I6, I7> mask, requires_arch<avx>) noexcept
{
constexpr uint32_t smask = detail::mod_shuffle(I0, I1, I2, I3);
// shuffle within lane
@@ -1253,7 +1253,7 @@ namespace xsimd
}
template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3>
- inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<batch<ITy, A>, I0, I1, I2, I3> mask, requires_arch<avx>) noexcept
+ inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<ITy, A, I0, I1, I2, I3> mask, requires_arch<avx>) noexcept
{
constexpr uint32_t smask = (I0 & 0x1) | ((I1 & 0x1) << 1) | ((I2 & 0x1) << 2) | ((I3 & 0x1) << 3);
// shuffle within lane
@@ -1504,7 +1504,7 @@ namespace xsimd
// swizzle (constant mask)
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3, uint32_t V4, uint32_t V5, uint32_t V6, uint32_t V7>
- inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<avx>) noexcept
+ inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<avx>) noexcept
{
// duplicate low and high part of input
__m256 hi = _mm256_castps128_ps256(_mm256_extractf128_ps(self, 1));
@@ -1514,14 +1514,14 @@ namespace xsimd
__m256 low_low = _mm256_insertf128_ps(self, _mm256_castps256_ps128(low), 1);
// normalize mask
- batch_constant<batch<uint32_t, A>, (V0 % 4), (V1 % 4), (V2 % 4), (V3 % 4), (V4 % 4), (V5 % 4), (V6 % 4), (V7 % 4)> half_mask;
+ batch_constant<uint32_t, A, (V0 % 4), (V1 % 4), (V2 % 4), (V3 % 4), (V4 % 4), (V5 % 4), (V6 % 4), (V7 % 4)> half_mask;
// permute within each lane
- __m256 r0 = _mm256_permutevar_ps(low_low, (batch<uint32_t, A>)half_mask);
- __m256 r1 = _mm256_permutevar_ps(hi_hi, (batch<uint32_t, A>)half_mask);
+ __m256 r0 = _mm256_permutevar_ps(low_low, half_mask.as_batch());
+ __m256 r1 = _mm256_permutevar_ps(hi_hi, half_mask.as_batch());
// mask to choose the right lane
- batch_bool_constant<batch<uint32_t, A>, (V0 >= 4), (V1 >= 4), (V2 >= 4), (V3 >= 4), (V4 >= 4), (V5 >= 4), (V6 >= 4), (V7 >= 4)> blend_mask;
+ batch_bool_constant<uint32_t, A, (V0 >= 4), (V1 >= 4), (V2 >= 4), (V3 >= 4), (V4 >= 4), (V5 >= 4), (V6 >= 4), (V7 >= 4)> blend_mask;
// blend the two permutes
constexpr auto mask = blend_mask.mask();
@@ -1529,7 +1529,7 @@ namespace xsimd
}
template <class A, uint64_t V0, uint64_t V1, uint64_t V2, uint64_t V3>
- inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1, V2, V3>, requires_arch<avx>) noexcept
+ inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<uint64_t, A, V0, V1, V2, V3>, requires_arch<avx>) noexcept
{
// duplicate low and high part of input
__m256d hi = _mm256_castpd128_pd256(_mm256_extractf128_pd(self, 1));
@@ -1539,14 +1539,14 @@ namespace xsimd
__m256d low_low = _mm256_insertf128_pd(self, _mm256_castpd256_pd128(low), 1);
// normalize mask
- batch_constant<batch<uint64_t, A>, (V0 % 2) * -1, (V1 % 2) * -1, (V2 % 2) * -1, (V3 % 2) * -1> half_mask;
+ batch_constant<uint64_t, A, (V0 % 2) * -1, (V1 % 2) * -1, (V2 % 2) * -1, (V3 % 2) * -1> half_mask;
// permute within each lane
- __m256d r0 = _mm256_permutevar_pd(low_low, (batch<uint64_t, A>)half_mask);
- __m256d r1 = _mm256_permutevar_pd(hi_hi, (batch<uint64_t, A>)half_mask);
+ __m256d r0 = _mm256_permutevar_pd(low_low, half_mask.as_batch());
+ __m256d r1 = _mm256_permutevar_pd(hi_hi, half_mask.as_batch());
// mask to choose the right lane
- batch_bool_constant<batch<uint64_t, A>, (V0 >= 2), (V1 >= 2), (V2 >= 2), (V3 >= 2)> blend_mask;
+ batch_bool_constant<uint64_t, A, (V0 >= 2), (V1 >= 2), (V2 >= 2), (V3 >= 2)> blend_mask;
// blend the two permutes
constexpr auto mask = blend_mask.mask();
@@ -1564,7 +1564,7 @@ namespace xsimd
uint32_t V7,
detail::enable_sized_integral_t<T, 4> = 0>
inline batch<T, A> swizzle(batch<T, A> const& self,
- batch_constant<batch<uint32_t, A>,
+ batch_constant<uint32_t, A,
V0,
V1,
V2,
@@ -1588,7 +1588,7 @@ namespace xsimd
detail::enable_sized_integral_t<T, 8> = 0>
inline batch<T, A>
swizzle(batch<T, A> const& self,
- batch_constant<batch<uint64_t, A>, V0, V1, V2, V3> const& mask,
+ batch_constant<uint64_t, A, V0, V1, V2, V3> const& mask,
requires_arch<avx>) noexcept
{
return bitwise_cast<T>(
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_avx2.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_avx2.hpp
index a4881778e0..c052e0f269 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_avx2.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_avx2.hpp
@@ -729,9 +729,9 @@ namespace xsimd
}
}
template <class A, class T, bool... Values, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<avx2>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<avx2>) noexcept
{
- constexpr int mask = batch_bool_constant<batch<T, A>, Values...>::mask();
+ constexpr int mask = batch_bool_constant<T, A, Values...>::mask();
// FIXME: for some reason mask here is not considered as an immediate,
// but it's okay for _mm256_blend_epi32
// case 2: return _mm256_blend_epi16(false_br, true_br, mask);
@@ -912,36 +912,36 @@ namespace xsimd
// swizzle (constant mask)
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3, uint32_t V4, uint32_t V5, uint32_t V6, uint32_t V7>
- inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<avx2>) noexcept
+ inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<avx2>) noexcept
{
- return _mm256_permutevar8x32_ps(self, (batch<uint32_t, A>)mask);
+ return _mm256_permutevar8x32_ps(self, mask.as_batch());
}
template <class A, uint64_t V0, uint64_t V1, uint64_t V2, uint64_t V3>
- inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1, V2, V3>, requires_arch<avx2>) noexcept
+ inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<uint64_t, A, V0, V1, V2, V3>, requires_arch<avx2>) noexcept
{
constexpr auto mask = detail::shuffle(V0, V1, V2, V3);
return _mm256_permute4x64_pd(self, mask);
}
template <class A, uint64_t V0, uint64_t V1, uint64_t V2, uint64_t V3>
- inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1, V2, V3>, requires_arch<avx2>) noexcept
+ inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<uint64_t, A, V0, V1, V2, V3>, requires_arch<avx2>) noexcept
{
constexpr auto mask = detail::shuffle(V0, V1, V2, V3);
return _mm256_permute4x64_epi64(self, mask);
}
template <class A, uint64_t V0, uint64_t V1, uint64_t V2, uint64_t V3>
- inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1, V2, V3> mask, requires_arch<avx2>) noexcept
+ inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<uint64_t, A, V0, V1, V2, V3> mask, requires_arch<avx2>) noexcept
{
return bitwise_cast<int64_t>(swizzle(bitwise_cast<uint64_t>(self), mask, avx2 {}));
}
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3, uint32_t V4, uint32_t V5, uint32_t V6, uint32_t V7>
- inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<avx2>) noexcept
+ inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<avx2>) noexcept
{
- return _mm256_permutevar8x32_epi32(self, (batch<uint32_t, A>)mask);
+ return _mm256_permutevar8x32_epi32(self, mask.as_batch());
}
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3, uint32_t V4, uint32_t V5, uint32_t V6, uint32_t V7>
- inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<avx2>) noexcept
+ inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<avx2>) noexcept
{
return bitwise_cast<int32_t>(swizzle(bitwise_cast<uint32_t>(self), mask, avx2 {}));
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_avx512bw.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_avx512bw.hpp
index 95fbcbd461..db72b73ca5 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_avx512bw.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_avx512bw.hpp
@@ -617,27 +617,27 @@ namespace xsimd
// swizzle (static version)
template <class A, uint16_t... Vs>
- inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<batch<uint16_t, A>, Vs...> mask, requires_arch<avx512bw>) noexcept
+ inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<uint16_t, A, Vs...> mask, requires_arch<avx512bw>) noexcept
{
- return swizzle(self, (batch<uint16_t, A>)mask, avx512bw {});
+ return swizzle(self, mask.as_batch(), avx512bw {});
}
template <class A, uint16_t... Vs>
- inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<batch<uint16_t, A>, Vs...> mask, requires_arch<avx512bw>) noexcept
+ inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<uint16_t, A, Vs...> mask, requires_arch<avx512bw>) noexcept
{
- return swizzle(self, (batch<uint16_t, A>)mask, avx512bw {});
+ return swizzle(self, mask.as_batch(), avx512bw {});
}
template <class A, uint8_t... Vs>
- inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<batch<uint8_t, A>, Vs...> mask, requires_arch<avx512bw>) noexcept
+ inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<uint8_t, A, Vs...> mask, requires_arch<avx512bw>) noexcept
{
- return swizzle(self, (batch<uint8_t, A>)mask, avx512bw {});
+ return swizzle(self, mask.as_batch(), avx512bw {});
}
template <class A, uint8_t... Vs>
- inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<batch<uint8_t, A>, Vs...> mask, requires_arch<avx512bw>) noexcept
+ inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<uint8_t, A, Vs...> mask, requires_arch<avx512bw>) noexcept
{
- return swizzle(self, (batch<uint8_t, A>)mask, avx512bw {});
+ return swizzle(self, mask.as_batch(), avx512bw {});
}
// zip_hi
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_avx512f.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_avx512f.hpp
index 7ee4610135..d94c681015 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_avx512f.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_avx512f.hpp
@@ -1422,8 +1422,8 @@ namespace xsimd
template <class A, class T, class _ = typename std::enable_if<(sizeof(T) == 1), void>::type>
inline T reduce_max(batch<T, A> const& self, requires_arch<avx512f>) noexcept
{
- constexpr batch_constant<batch<uint64_t, A>, 5, 6, 7, 8, 0, 0, 0, 0> mask;
- batch<T, A> step = _mm512_permutexvar_epi64((batch<uint64_t, A>)mask, self);
+ constexpr batch_constant<uint64_t, A, 5, 6, 7, 8, 0, 0, 0, 0> mask;
+ batch<T, A> step = _mm512_permutexvar_epi64(mask.as_batch(), self);
batch<T, A> acc = max(self, step);
__m256i low = _mm512_castsi512_si256(acc);
return reduce_max(batch<T, avx2>(low));
@@ -1433,8 +1433,8 @@ namespace xsimd
template <class A, class T, class _ = typename std::enable_if<(sizeof(T) == 1), void>::type>
inline T reduce_min(batch<T, A> const& self, requires_arch<avx512f>) noexcept
{
- constexpr batch_constant<batch<uint64_t, A>, 5, 6, 7, 8, 0, 0, 0, 0> mask;
- batch<T, A> step = _mm512_permutexvar_epi64((batch<uint64_t, A>)mask, self);
+ constexpr batch_constant<uint64_t, A, 5, 6, 7, 8, 0, 0, 0, 0> mask;
+ batch<T, A> step = _mm512_permutexvar_epi64(mask.as_batch(), self);
batch<T, A> acc = min(self, step);
__m256i low = _mm512_castsi512_si256(acc);
return reduce_min(batch<T, avx2>(low));
@@ -1571,7 +1571,7 @@ namespace xsimd
}
template <class A, class T, bool... Values, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<avx512f>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<avx512f>) noexcept
{
return select(batch_bool<T, A> { Values... }, true_br, false_br, avx512f {});
}
@@ -1709,7 +1709,7 @@ namespace xsimd
// shuffle
template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3, ITy I4, ITy I5, ITy I6, ITy I7, ITy I8, ITy I9, ITy I10, ITy I11, ITy I12, ITy I13, ITy I14, ITy I15>
inline batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y,
- batch_constant<batch<ITy, A>, I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15> mask,
+ batch_constant<ITy, A, I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15> mask,
requires_arch<avx512f>) noexcept
{
constexpr uint32_t smask = (I0 & 0x3) | ((I1 & 0x3) << 2) | ((I2 & 0x3) << 4) | ((I3 & 0x3) << 6);
@@ -1726,7 +1726,7 @@ namespace xsimd
}
template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3, ITy I4, ITy I5, ITy I6, ITy I7>
- inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<batch<ITy, A>, I0, I1, I2, I3, I4, I5, I6, I7> mask, requires_arch<avx512f>) noexcept
+ inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<ITy, A, I0, I1, I2, I3, I4, I5, I6, I7> mask, requires_arch<avx512f>) noexcept
{
constexpr uint32_t smask = (I0 & 0x1) | ((I1 & 0x1) << 1) | ((I2 & 0x1) << 2) | ((I3 & 0x1) << 3) | ((I4 & 0x1) << 4) | ((I5 & 0x1) << 5) | ((I6 & 0x1) << 6) | ((I7 & 0x1) << 7);
// shuffle within lane
@@ -1917,39 +1917,39 @@ namespace xsimd
// swizzle (constant version)
template <class A, uint32_t... Vs>
- inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<batch<uint32_t, A>, Vs...> mask, requires_arch<avx512f>) noexcept
+ inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<uint32_t, A, Vs...> mask, requires_arch<avx512f>) noexcept
{
- return swizzle(self, (batch<uint32_t, A>)mask, avx512f {});
+ return swizzle(self, mask.as_batch(), avx512f {});
}
template <class A, uint64_t... Vs>
- inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<batch<uint64_t, A>, Vs...> mask, requires_arch<avx512f>) noexcept
+ inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<uint64_t, A, Vs...> mask, requires_arch<avx512f>) noexcept
{
- return swizzle(self, (batch<uint64_t, A>)mask, avx512f {});
+ return swizzle(self, mask.as_batch(), avx512f {});
}
template <class A, uint64_t... Vs>
- inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<batch<uint64_t, A>, Vs...> mask, requires_arch<avx512f>) noexcept
+ inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<uint64_t, A, Vs...> mask, requires_arch<avx512f>) noexcept
{
- return swizzle(self, (batch<uint64_t, A>)mask, avx512f {});
+ return swizzle(self, mask.as_batch(), avx512f {});
}
template <class A, uint64_t... Vs>
- inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<batch<uint64_t, A>, Vs...> mask, requires_arch<avx512f>) noexcept
+ inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<uint64_t, A, Vs...> mask, requires_arch<avx512f>) noexcept
{
- return swizzle(self, (batch<uint64_t, A>)mask, avx512f {});
+ return swizzle(self, mask.as_batch(), avx512f {});
}
template <class A, uint32_t... Vs>
- inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<batch<uint32_t, A>, Vs...> mask, requires_arch<avx512f>) noexcept
+ inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<uint32_t, A, Vs...> mask, requires_arch<avx512f>) noexcept
{
- return swizzle(self, (batch<uint32_t, A>)mask, avx512f {});
+ return swizzle(self, mask.as_batch(), avx512f {});
}
template <class A, uint32_t... Vs>
- inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<batch<uint32_t, A>, Vs...> mask, requires_arch<avx512f>) noexcept
+ inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<uint32_t, A, Vs...> mask, requires_arch<avx512f>) noexcept
{
- return swizzle(self, (batch<uint32_t, A>)mask, avx512f {});
+ return swizzle(self, mask.as_batch(), avx512f {});
}
namespace detail
@@ -1973,14 +1973,14 @@ namespace xsimd
uint16_t I24, uint16_t I25, uint16_t I26, uint16_t I27, uint16_t I28, uint16_t I29, uint16_t I30, uint16_t I31>
struct fold_batch_constant
{
- using type = batch_constant<batch<uint32_t, A>, I0 / 2, I2 / 2, I4 / 2, I6 / 2, I8 / 2, I10 / 2, I12 / 2, I14 / 2,
+ using type = batch_constant<uint32_t, A, I0 / 2, I2 / 2, I4 / 2, I6 / 2, I8 / 2, I10 / 2, I12 / 2, I14 / 2,
I16 / 2, I18 / 2, I20 / 2, I22 / 2, I24 / 2, I26 / 2, I28 / 2, I30 / 2>;
};
}
template <class A, uint16_t... Idx, class _ = typename std::enable_if<detail::is_pair_of_contiguous_indices<uint16_t, A, Idx...>::value, void>::type>
- inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<batch<uint16_t, A>, Idx...>, requires_arch<avx512f>) noexcept
+ inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<uint16_t, A, Idx...>, requires_arch<avx512f>) noexcept
{
constexpr typename detail::fold_batch_constant<A, Idx...>::type mask32;
return _mm512_permutexvar_epi32(static_cast<batch<uint32_t, A>>(mask32), self);
@@ -1988,13 +1988,13 @@ namespace xsimd
template <class A>
inline batch<uint16_t, A>
- swizzle(batch<uint16_t, A> const& self, batch_constant<batch<uint16_t, A>, (uint16_t)1, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1>, requires_arch<avx512f>) noexcept
+ swizzle(batch<uint16_t, A> const& self, batch_constant<uint16_t, A, (uint16_t)1, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1, (uint16_t)0, (uint16_t)1>, requires_arch<avx512f>) noexcept
{
// FIXME: this sequence is very inefficient, but it's here to catch
// a pattern generated by detail::reduce from xsimd_generic_math.hpp.
// The whole pattern is actually decently folded by GCC and Clang,
// so bare with it.
- constexpr batch_constant<batch<uint32_t, A>, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0> mask32;
+ constexpr batch_constant<uint32_t, A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0> mask32;
auto tmp = _mm512_permutexvar_epi32(static_cast<batch<uint32_t, A>>(mask32), self);
alignas(A::alignment()) uint16_t buffer[32];
@@ -2005,7 +2005,7 @@ namespace xsimd
template <class A, uint16_t... Vs>
inline batch<int16_t, A>
- swizzle(batch<int16_t, A> const& self, batch_constant<batch<uint16_t, A>, Vs...> mask, requires_arch<avx512f>) noexcept
+ swizzle(batch<int16_t, A> const& self, batch_constant<uint16_t, A, Vs...> mask, requires_arch<avx512f>) noexcept
{
return bitwise_cast<int16_t>(swizzle(bitwise_cast<uint16_t>(self), mask, avx512f {}));
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_emulated.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_emulated.hpp
new file mode 100644
index 0000000000..ac3dd4fef3
--- /dev/null
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_emulated.hpp
@@ -0,0 +1,757 @@
+/***************************************************************************
+ * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
+ * Martin Renou *
+ * Copyright (c) QuantStack *
+ * Copyright (c) Serge Guelton *
+ * *
+ * Distributed under the terms of the BSD 3-Clause License. *
+ * *
+ * The full license is in the file LICENSE, distributed with this software. *
+ ****************************************************************************/
+
+#ifndef XSIMD_EMULATED_HPP
+#define XSIMD_EMULATED_HPP
+
+#include <complex>
+#include <limits>
+#include <numeric>
+#include <type_traits>
+
+#include "../arch/xsimd_scalar.hpp"
+
+#include "../types/xsimd_emulated_register.hpp"
+#include "../types/xsimd_utils.hpp"
+
+namespace xsimd
+{
+ template <typename T, class A, bool... Values>
+ struct batch_bool_constant;
+
+ template <class T_out, class T_in, class A>
+ inline batch<T_out, A> bitwise_cast(batch<T_in, A> const& x) noexcept;
+
+ template <typename T, class A, T... Values>
+ struct batch_constant;
+
+ namespace kernel
+ {
+ using namespace types;
+
+ // fwd
+ template <class A, class T, size_t I>
+ inline batch<T, A> insert(batch<T, A> const& self, T val, index<I>, requires_arch<generic>) noexcept;
+ template <class A, typename T, typename ITy, ITy... Indices>
+ inline batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<ITy, A, Indices...>, requires_arch<generic>) noexcept;
+
+ namespace detail
+ {
+ template <size_t I, class F, class... Bs>
+ auto emulated_apply(F func, Bs const&... bs) -> decltype(func(bs.data[I]...))
+ {
+ return func(bs.data[I]...);
+ }
+
+ template <class F, class B, class... Bs, size_t... Is>
+ auto emulated_apply(F func, ::xsimd::detail::index_sequence<Is...>, B const& b, Bs const&... bs) -> std::array<decltype(func(b.data[0], bs.data[0]...)), B::size>
+ {
+ return { emulated_apply<Is>(func, b, bs...)... };
+ }
+
+ template <class B, class F, class... Bs>
+ auto emulated_apply(F func, B const& b, Bs const&... bs) -> std::array<decltype(func(b.data[0], bs.data[0]...)), B::size>
+ {
+ return emulated_apply(func, ::xsimd::detail::make_index_sequence<B::size>(), b, bs...);
+ }
+ }
+
+ // abs
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> abs(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v)
+ { return xsimd::abs(v); },
+ self);
+ }
+
+ // add
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> add(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::add(v0, v1); },
+ self, other);
+ }
+
+ // all
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline bool all(batch_bool<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return std::all_of(self.data.begin(), self.data.end(), [](T v)
+ { return bool(v); });
+ }
+
+ // any
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline bool any(batch_bool<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return std::any_of(self.data.begin(), self.data.end(), [](T v)
+ { return bool(v); });
+ }
+
+ // batch_bool_cast
+ template <class A, class T_out, class T_in, size_t N = 8 * sizeof(T_in) * batch<T_in, A>::size>
+ inline batch_bool<T_out, A> batch_bool_cast(batch_bool<T_in, A> const& self, batch_bool<T_out, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ return { self.data };
+ }
+
+ // bitwise_and
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> bitwise_and(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::bitwise_and(v0, v1); },
+ self, other);
+ }
+
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> bitwise_and(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v0, bool v1)
+ { return xsimd::bitwise_and(v0, v1); },
+ self, other);
+ }
+
+ // bitwise_andnot
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> bitwise_andnot(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::bitwise_andnot(v0, v1); },
+ self, other);
+ }
+
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> bitwise_andnot(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v0, bool v1)
+ { return xsimd::bitwise_andnot(v0, v1); },
+ self, other);
+ }
+
+ // bitwise_lshift
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> bitwise_lshift(batch<T, A> const& self, int32_t other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([other](T v)
+ { return xsimd::bitwise_lshift(v, other); },
+ self);
+ }
+
+ // bitwise_not
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> bitwise_not(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v)
+ { return xsimd::bitwise_not(v); },
+ self);
+ }
+
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> bitwise_not(batch_bool<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v)
+ { return xsimd::bitwise_not(v); },
+ self);
+ }
+
+ // bitwise_or
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> bitwise_or(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::bitwise_or(v0, v1); },
+ self, other);
+ }
+
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> bitwise_or(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v0, bool v1)
+ { return xsimd::bitwise_or(v0, v1); },
+ self, other);
+ }
+
+ // bitwise_rshift
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> bitwise_rshift(batch<T, A> const& self, int32_t other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([other](T v)
+ { return xsimd::bitwise_rshift(v, other); },
+ self);
+ }
+
+ // bitwise_xor
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> bitwise_xor(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::bitwise_xor(v0, v1); },
+ self, other);
+ }
+
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> bitwise_xor(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v0, bool v1)
+ { return xsimd::bitwise_xor(v0, v1); },
+ self, other);
+ }
+
+ // bitwise_cast
+ template <class A, class T_in, class T_out, size_t N = 8 * sizeof(T_in) * batch<T_in, A>::size>
+ inline batch<T_out, A> bitwise_cast(batch<T_in, A> const& self, batch<T_out, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T_out, A>::size;
+ std::array<T_out, size> result;
+ char* raw_data = reinterpret_cast<char*>(result.data());
+ const char* raw_input = reinterpret_cast<const char*>(self.data.data());
+ memcpy(raw_data, raw_input, size * sizeof(T_out));
+ return result;
+ }
+
+ // broadcast
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ batch<T, A> inline broadcast(T val, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> r;
+ std::fill(r.begin(), r.end(), val);
+ return r;
+ }
+
+ // store_complex
+ namespace detail
+ {
+ // complex_low
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> complex_low(batch<std::complex<T>, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> result;
+ for (size_t i = 0; i < size / 2; ++i)
+ {
+ result[2 * i] = self.real().data[i];
+ result[1 + 2 * i] = self.imag().data[i];
+ }
+ return result;
+ }
+ // complex_high
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> complex_high(batch<std::complex<T>, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> result;
+ for (size_t i = 0; i < size / 2; ++i)
+ {
+ result[2 * i] = self.real().data[i + size / 2];
+ result[1 + 2 * i] = self.imag().data[i + size / 2];
+ }
+ return result;
+ }
+ }
+
+ // decr_if
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> decr_if(batch<T, A> const& self, batch_bool<T, A> const& mask, requires_arch<emulated<N>>) noexcept
+ {
+ return self - batch<T, A>(mask.data);
+ }
+
+ // div
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> div(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::div(v0, v1); },
+ self, other);
+ }
+
+ // fast_cast
+ namespace detail
+ {
+ template <class A, size_t N = 8 * sizeof(float) * batch<float, A>::size>
+ inline batch<float, A> fast_cast(batch<int32_t, A> const& self, batch<float, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](int32_t v)
+ { return float(v); },
+ self);
+ }
+
+ template <class A, size_t N = 8 * sizeof(float) * batch<float, A>::size>
+ inline batch<float, A> fast_cast(batch<uint32_t, A> const& self, batch<float, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](uint32_t v)
+ { return float(v); },
+ self);
+ }
+
+ template <class A, size_t N = 8 * sizeof(double) * batch<double, A>::size>
+ inline batch<double, A> fast_cast(batch<int64_t, A> const& self, batch<double, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](int64_t v)
+ { return double(v); },
+ self);
+ }
+
+ template <class A, size_t N = 8 * sizeof(double) * batch<double, A>::size>
+ inline batch<double, A> fast_cast(batch<uint64_t, A> const& self, batch<double, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](uint64_t v)
+ { return double(v); },
+ self);
+ }
+
+ template <class A, size_t N = 8 * sizeof(int32_t) * batch<int32_t, A>::size>
+ inline batch<int32_t, A> fast_cast(batch<float, A> const& self, batch<int32_t, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](float v)
+ { return int32_t(v); },
+ self);
+ }
+
+ template <class A, size_t N = 8 * sizeof(double) * batch<double, A>::size>
+ inline batch<int64_t, A> fast_cast(batch<double, A> const& self, batch<int64_t, A> const&, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](double v)
+ { return int64_t(v); },
+ self);
+ }
+ }
+
+ // eq
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, emulated<N>> eq(batch<T, emulated<N>> const& self, batch<T, emulated<N>> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::eq(v0, v1); },
+ self, other);
+ }
+
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch_bool<T, A>::size>
+ inline batch_bool<T, emulated<N>> eq(batch_bool<T, emulated<N>> const& self, batch_bool<T, emulated<N>> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v0, bool v1)
+ { return xsimd::eq(v0, v1); },
+ self, other);
+ }
+
+ // from_bool
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> from_bool(batch_bool<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v)
+ { return T(v); },
+ self);
+ }
+
+ // from_mask
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> from_mask(batch_bool<T, A> const&, uint64_t mask, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<bool, size> vmask;
+ for (size_t i = 0; i < size; ++i)
+ vmask[i] = (mask >> i) & 1u;
+ return vmask;
+ }
+
+ // ge
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, emulated<N>> ge(batch<T, emulated<N>> const& self, batch<T, emulated<N>> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::ge(v0, v1); },
+ self, other);
+ }
+
+ // gt
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, emulated<N>> gt(batch<T, emulated<N>> const& self, batch<T, emulated<N>> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::gt(v0, v1); },
+ self, other);
+ }
+
+ // haddp
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> haddp(batch<T, A> const* row, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> r;
+ for (size_t i = 0; i < size; ++i)
+ r[i] = std::accumulate(row[i].data.begin() + 1, row[i].data.end(), row[i].data.front());
+ return r;
+ }
+
+ // incr_if
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> incr_if(batch<T, A> const& self, batch_bool<T, A> const& mask, requires_arch<emulated<N>>) noexcept
+ {
+ return self + batch<T, A>(mask.data);
+ }
+
+ // insert
+ template <class A, class T, size_t I, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> insert(batch<T, A> const& self, T val, index<I>, requires_arch<emulated<N>>) noexcept
+ {
+ batch<T, A> other = self;
+ other.data[I] = val;
+ return other;
+ }
+
+ // isnan
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size, class = typename std::enable_if<std::is_floating_point<T>::value, void>::type>
+ inline batch_bool<T, A> isnan(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v)
+ { return xsimd::isnan(v); },
+ self);
+ }
+
+ // load_aligned
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> load_aligned(T const* mem, convert<T>, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> res;
+ std::copy(mem, mem + size, res.begin());
+ return res;
+ }
+
+ // load_unaligned
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> load_unaligned(T const* mem, convert<T>, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> res;
+ std::copy(mem, mem + size, res.begin());
+ return res;
+ }
+
+ // load_complex
+ namespace detail
+ {
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<std::complex<T>, A> load_complex(batch<T, A> const& hi, batch<T, A> const& lo, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> real, imag;
+ for (size_t i = 0; i < size / 2; ++i)
+ {
+ real[i] = hi.data[2 * i];
+ imag[i] = hi.data[1 + 2 * i];
+ }
+ for (size_t i = 0; i < size / 2; ++i)
+ {
+ real[size / 2 + i] = lo.data[2 * i];
+ imag[size / 2 + i] = lo.data[1 + 2 * i];
+ }
+ return { real, imag };
+ }
+ }
+
+ // le
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, emulated<N>> le(batch<T, emulated<N>> const& self, batch<T, emulated<N>> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::le(v0, v1); },
+ self, other);
+ }
+
+ // lt
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, emulated<N>> lt(batch<T, emulated<N>> const& self, batch<T, emulated<N>> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::lt(v0, v1); },
+ self, other);
+ }
+
+ // mask
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline uint64_t mask(batch_bool<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ uint64_t res = 0;
+ for (size_t i = 0; i < size; ++i)
+ res |= (self.data[i] ? 1u : 0u) << i;
+ return res;
+ }
+
+ // max
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> max(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::max(v0, v1); },
+ self, other);
+ }
+
+ // min
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> min(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::min(v0, v1); },
+ self, other);
+ }
+
+ // mul
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> mul(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::mul(v0, v1); },
+ self, other);
+ }
+
+ // nearbyint_as_int
+ template <class A, typename T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<as_integer_t<T>, A> nearbyint_as_int(batch<T, A> const& self,
+ requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v)
+ { return xsimd::nearbyint_as_int(v); },
+ self);
+ }
+
+ // neg
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> neg(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v)
+ { return xsimd::neg(v); },
+ self);
+ }
+
+ // neq
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> neq(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::neq(v0, v1); },
+ self, other);
+ }
+
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch_bool<T, A> neq(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool v0, bool v1)
+ { return xsimd::neq(v0, v1); },
+ self, other);
+ }
+
+ // reduce_add
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline T reduce_add(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> buffer;
+ self.store_unaligned(buffer.data());
+ return std::accumulate(buffer.begin() + 1, buffer.end(), *buffer.begin());
+ }
+
+ // reduce_max
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline T reduce_max(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return std::accumulate(self.data.begin() + 1, self.data.end(), *self.data.begin(), [](T const& x, T const& y)
+ { return xsimd::max(x, y); });
+ }
+
+ // reduce_min
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline T reduce_min(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return std::accumulate(self.data.begin() + 1, self.data.end(), *self.data.begin(), [](T const& x, T const& y)
+ { return xsimd::min(x, y); });
+ }
+
+ // rsqrt
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> rsqrt(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v)
+ { return xsimd::rsqrt(v); },
+ self);
+ }
+
+ // select
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> select(batch_bool<T, A> const& cond, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](bool c, T t, T f)
+ { return xsimd::select(c, t, f); },
+ cond, true_br, false_br);
+ }
+
+ template <class A, class T, bool... Values>
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const& cond, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<emulated<8 * sizeof(T) * batch<T, A>::size>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ static_assert(sizeof...(Values) == size, "consistent init");
+ return select((batch_bool<T, A>)cond, true_br, false_br, emulated<8 * sizeof(T) * size> {});
+ }
+
+ // shuffle
+ template <class A, typename T, class ITy, ITy... Is>
+ inline batch<T, A> shuffle(batch<T, A> const& x, batch<float, A> const& y, batch_constant<ITy, A, Is...> mask, requires_arch<emulated<batch<T, A>::size>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ batch<ITy, A> bmask = mask;
+ std::array<T, size> res;
+ for (size_t i = 0; i < size; ++i)
+ res[i] = bmask.data[i] < size ? x.data[bmask.data[i]] : y.data[bmask.data[i] - size];
+ return res;
+ }
+
+ // sqrt
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> sqrt(batch<T, A> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v)
+ { return xsimd::sqrt(v); },
+ self);
+ }
+
+ // slide_left
+ template <size_t M, class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> slide_left(batch<T, A> const& x, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> result;
+ char* raw_data = reinterpret_cast<char*>(result.data());
+ memset(raw_data, 0, M);
+ memcpy(raw_data + M, reinterpret_cast<const char*>(x.data.data()), sizeof(T) * result.size() - M);
+ return result;
+ }
+
+ // slide_right
+ template <size_t M, class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> slide_right(batch<T, A> const& x, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ std::array<T, size> result;
+ char* raw_data = reinterpret_cast<char*>(result.data());
+ memcpy(raw_data, reinterpret_cast<const char*>(x.data.data()) + M, sizeof(T) * result.size() - M);
+ memset(raw_data + sizeof(T) * result.size() - M, 0, M);
+ return result;
+ }
+
+ // sadd
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> sadd(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::sadd(v0, v1); },
+ self, other);
+ }
+
+ // set
+ template <class A, class T, size_t N, class... Values>
+ inline batch<T, emulated<N>> set(batch<T, emulated<N>> const&, requires_arch<emulated<N>>, Values... values) noexcept
+ {
+ static_assert(sizeof...(Values) == batch<T, emulated<N>>::size, "consistent init");
+ return { typename batch<T, emulated<N>>::register_type { static_cast<T>(values)... } };
+ }
+
+ template <class A, class T, size_t N, class... Values>
+ inline batch_bool<T, emulated<N>> set(batch_bool<T, emulated<N>> const&, requires_arch<emulated<N>>, Values... values) noexcept
+ {
+ static_assert(sizeof...(Values) == batch<T, emulated<N>>::size, "consistent init");
+ return { std::array<bool, sizeof...(Values)> { static_cast<bool>(values)... } };
+ }
+
+ // ssub
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> ssub(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::ssub(v0, v1); },
+ self, other);
+ }
+
+ // store_aligned
+ template <class A, class T, size_t N>
+ inline void store_aligned(T* mem, batch<T, emulated<N>> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ std::copy(self.data.begin(), self.data.end(), mem);
+ }
+
+ // store_unaligned
+ template <class A, class T, size_t N>
+ inline void store_unaligned(T* mem, batch<T, emulated<N>> const& self, requires_arch<emulated<N>>) noexcept
+ {
+ std::copy(self.data.begin(), self.data.end(), mem);
+ }
+
+ // sub
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> sub(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ return detail::emulated_apply([](T v0, T v1)
+ { return xsimd::sub(v0, v1); },
+ self, other);
+ }
+
+ // swizzle
+
+ template <class A, typename T, class ITy, ITy... Is>
+ inline batch<T, A> swizzle(batch<T, A> const& self, batch_constant<ITy, A, Is...> mask, requires_arch<emulated<8 * sizeof(T) * batch<T, A>::size>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ batch<ITy, A> bmask = mask;
+ std::array<T, size> res;
+ for (size_t i = 0; i < size; ++i)
+ res[i] = self.data[bmask.data[i]];
+ return res;
+ }
+
+ // zip_hi
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> zip_hi(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ // Note: irregular behavior for odd numbers.
+ std::array<T, size> res;
+ if (size % 2)
+ {
+ for (size_t i = 0; i < size; ++i)
+ res[i] = (i % 2 ? self : other).data[size / 2 + i / 2];
+ }
+ else
+ {
+ for (size_t i = 0; i < size; ++i)
+ res[i] = (i % 2 ? other : self).data[size / 2 + i / 2];
+ }
+ return res;
+ }
+
+ // zip_lo
+ template <class A, class T, size_t N = 8 * sizeof(T) * batch<T, A>::size>
+ inline batch<T, A> zip_lo(batch<T, A> const& self, batch<T, A> const& other, requires_arch<emulated<N>>) noexcept
+ {
+ constexpr size_t size = batch<T, A>::size;
+ // Note: irregular behavior for odd numbers.
+ std::array<T, size> res;
+ for (size_t i = 0; i < size; ++i)
+ res[i] = (i % 2 ? other : self).data[i / 2];
+ return res;
+ }
+ }
+}
+
+#endif
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_isa.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_isa.hpp
index dcd2df3fa9..5b714b2991 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_isa.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_isa.hpp
@@ -16,6 +16,10 @@
#include "./xsimd_generic_fwd.hpp"
+#if XSIMD_WITH_EMULATED
+#include "./xsimd_emulated.hpp"
+#endif
+
#if XSIMD_WITH_SSE2
#include "./xsimd_sse2.hpp"
#endif
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_neon.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_neon.hpp
index 3510eb21d9..b0edae8633 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_neon.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_neon.hpp
@@ -146,7 +146,7 @@ inline float32x4_t vreinterpretq_f32_f32(float32x4_t arg) noexcept { return arg;
namespace xsimd
{
- template <class batch_type, bool... Values>
+ template <typename T, class A, bool... Values>
struct batch_bool_constant;
namespace kernel
@@ -1743,7 +1743,7 @@ namespace xsimd
}
template <class A, class T, bool... b, detail::enable_neon_type_t<T> = 0>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, b...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<neon>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, b...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<neon>) noexcept
{
return select(batch_bool<T, A> { b... }, true_br, false_br, neon {});
}
@@ -2717,7 +2717,7 @@ namespace xsimd
}
}
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant;
namespace kernel
@@ -2728,7 +2728,7 @@ namespace xsimd
template <class A, class T, class I, I... idx>
inline batch<T, A> swizzle(batch<T, A> const& self,
- batch_constant<batch<I, A>, idx...>,
+ batch_constant<I, A, idx...>,
requires_arch<neon>) noexcept
{
static_assert(batch<T, A>::size == sizeof...(idx), "valid swizzle indices");
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_neon64.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_neon64.hpp
index 77538d1c2d..2469b14f37 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_neon64.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_neon64.hpp
@@ -21,7 +21,7 @@
namespace xsimd
{
- template <class batch_type, bool... Values>
+ template <typename T, class A, bool... Values>
struct batch_bool_constant;
namespace kernel
@@ -942,7 +942,7 @@ namespace xsimd
}
template <class A, bool... b>
- inline batch<double, A> select(batch_bool_constant<batch<double, A>, b...> const&,
+ inline batch<double, A> select(batch_bool_constant<double, A, b...> const&,
batch<double, A> const& true_br,
batch<double, A> const& false_br,
requires_arch<neon64>) noexcept
@@ -1243,7 +1243,7 @@ namespace xsimd
}
}
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant;
namespace kernel
@@ -1354,42 +1354,40 @@ namespace xsimd
template <class CB1, class CB2, class IS>
struct index_burst_impl;
- template <class B1, class B2, typename B2::value_type... V,
- typename B2::value_type... incr>
- struct index_burst_impl<batch_constant<B1>, batch_constant<B2, V...>,
- integer_sequence<typename B2::value_type, incr...>>
+ template <typename T1, class A, typename T2, T2... V,
+ T2... incr>
+ struct index_burst_impl<batch_constant<T1, A>, batch_constant<T2, A, V...>,
+ integer_sequence<T2, incr...>>
{
- using type = batch_constant<B2, V...>;
+ using type = batch_constant<T2, A, V...>;
};
- template <class B1, typename B1::value_type V0, typename B1::value_type... V1,
- class B2, typename B2::value_type... V2,
- typename B2::value_type... incr>
- struct index_burst_impl<batch_constant<B1, V0, V1...>, batch_constant<B2, V2...>,
- integer_sequence<typename B2::value_type, incr...>>
+ template <typename T1, class A, T1 V0, T1... V1,
+ typename T2, T2... V2, T2... incr>
+ struct index_burst_impl<batch_constant<T1, A, V0, V1...>, batch_constant<T2, A, V2...>,
+ integer_sequence<T2, incr...>>
{
- using value_type = typename B2::value_type;
- using next_input = batch_constant<B1, V1...>;
- using next_output = batch_constant<B2, V2..., (V0 + incr)...>;
- using type = typename index_burst_impl<next_input, next_output, integer_sequence<value_type, incr...>>::type;
+ using next_input = batch_constant<T1, A, V1...>;
+ using next_output = batch_constant<T2, A, V2..., (V0 + incr)...>;
+ using type = typename index_burst_impl<next_input, next_output, integer_sequence<T2, incr...>>::type;
};
template <class B, class T>
struct index_burst;
- template <class B, typename B::value_type... V, class T>
- struct index_burst<batch_constant<B, V...>, T>
+ template <typename Tp, class A, Tp... V, typename T>
+ struct index_burst<batch_constant<Tp, A, V...>, T>
{
- static constexpr size_t mul = sizeof(typename B::value_type) / sizeof(T);
- using input = batch_constant<B, (mul * V)...>;
- using output = batch_constant<batch<T, typename B::arch_type>>;
+ static constexpr size_t mul = sizeof(Tp) / sizeof(T);
+ using input = batch_constant<Tp, A, (mul * V)...>;
+ using output = batch_constant<T, A>;
using type = typename index_burst_impl<input, output, make_integer_sequence<T, mul>>::type;
};
- template <class B, class T>
+ template <class B, typename T>
using index_burst_t = typename index_burst<B, T>::type;
- template <class T, class B>
+ template <typename T, class B>
inline index_burst_t<B, T> burst_index(B)
{
return index_burst_t<B, T>();
@@ -1399,7 +1397,7 @@ namespace xsimd
template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self,
- batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> idx,
+ batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> idx,
requires_arch<neon64>) noexcept
{
return vqtbl1q_u8(self, batch<uint8_t, A>(idx));
@@ -1408,7 +1406,7 @@ namespace xsimd
template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self,
- batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> idx,
+ batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> idx,
requires_arch<neon64>) noexcept
{
return vqtbl1q_s8(self, batch<uint8_t, A>(idx));
@@ -1416,7 +1414,7 @@ namespace xsimd
template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self,
- batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> idx,
+ batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<uint8_t, A>;
@@ -1425,7 +1423,7 @@ namespace xsimd
template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self,
- batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> idx,
+ batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<int8_t, A>;
@@ -1434,7 +1432,7 @@ namespace xsimd
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self,
- batch_constant<batch<uint32_t, A>, V0, V1, V2, V3> idx,
+ batch_constant<uint32_t, A, V0, V1, V2, V3> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<uint8_t, A>;
@@ -1443,7 +1441,7 @@ namespace xsimd
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self,
- batch_constant<batch<uint32_t, A>, V0, V1, V2, V3> idx,
+ batch_constant<uint32_t, A, V0, V1, V2, V3> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<int8_t, A>;
@@ -1452,7 +1450,7 @@ namespace xsimd
template <class A, uint64_t V0, uint64_t V1>
inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self,
- batch_constant<batch<uint64_t, A>, V0, V1> idx,
+ batch_constant<uint64_t, A, V0, V1> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<uint8_t, A>;
@@ -1461,7 +1459,7 @@ namespace xsimd
template <class A, uint64_t V0, uint64_t V1>
inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self,
- batch_constant<batch<uint64_t, A>, V0, V1> idx,
+ batch_constant<uint64_t, A, V0, V1> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<int8_t, A>;
@@ -1470,7 +1468,7 @@ namespace xsimd
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
inline batch<float, A> swizzle(batch<float, A> const& self,
- batch_constant<batch<uint32_t, A>, V0, V1, V2, V3> idx,
+ batch_constant<uint32_t, A, V0, V1, V2, V3> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<uint8_t, A>;
@@ -1479,7 +1477,7 @@ namespace xsimd
template <class A, uint64_t V0, uint64_t V1>
inline batch<double, A> swizzle(batch<double, A> const& self,
- batch_constant<batch<uint64_t, A>, V0, V1> idx,
+ batch_constant<uint64_t, A, V0, V1> idx,
requires_arch<neon64>) noexcept
{
using batch_type = batch<uint8_t, A>;
@@ -1488,7 +1486,7 @@ namespace xsimd
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
inline batch<std::complex<float>, A> swizzle(batch<std::complex<float>, A> const& self,
- batch_constant<batch<uint32_t, A>, V0, V1, V2, V3> idx,
+ batch_constant<uint32_t, A, V0, V1, V2, V3> idx,
requires_arch<neon64>) noexcept
{
return batch<std::complex<float>>(swizzle(self.real(), idx, A()), swizzle(self.imag(), idx, A()));
@@ -1496,7 +1494,7 @@ namespace xsimd
template <class A, uint64_t V0, uint64_t V1>
inline batch<std::complex<double>, A> swizzle(batch<std::complex<double>, A> const& self,
- batch_constant<batch<uint64_t, A>, V0, V1> idx,
+ batch_constant<uint64_t, A, V0, V1> idx,
requires_arch<neon64>) noexcept
{
return batch<std::complex<double>>(swizzle(self.real(), idx, A()), swizzle(self.imag(), idx, A()));
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_rvv.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_rvv.hpp
index 98d1de9ce3..2b8cebe5c9 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_rvv.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_rvv.hpp
@@ -284,7 +284,7 @@
namespace xsimd
{
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant;
namespace kernel
@@ -1150,7 +1150,7 @@ namespace xsimd
// swizzle
template <class A, class T, class I, I... idx>
- inline batch<T, A> swizzle(batch<T, A> const& arg, batch_constant<batch<I, A>, idx...>, requires_arch<rvv>) noexcept
+ inline batch<T, A> swizzle(batch<T, A> const& arg, batch_constant<I, A, idx...>, requires_arch<rvv>) noexcept
{
static_assert(batch<T, A>::size == sizeof...(idx), "invalid swizzle indices");
const batch<I, A> indices { idx... };
@@ -1159,11 +1159,11 @@ namespace xsimd
template <class A, class T, class I, I... idx>
inline batch<std::complex<T>, A> swizzle(batch<std::complex<T>, A> const& self,
- batch_constant<batch<I, A>, idx...>,
+ batch_constant<I, A, idx...>,
requires_arch<rvv>) noexcept
{
- const auto real = swizzle(self.real(), batch_constant<batch<I, A>, idx...> {}, rvv {});
- const auto imag = swizzle(self.imag(), batch_constant<batch<I, A>, idx...> {}, rvv {});
+ const auto real = swizzle(self.real(), batch_constant<I, A, idx...> {}, rvv {});
+ const auto imag = swizzle(self.imag(), batch_constant<I, A, idx...> {}, rvv {});
return batch<std::complex<T>>(real, imag);
}
@@ -1188,7 +1188,7 @@ namespace xsimd
}
template <class A, class T, bool... b>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, b...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<rvv>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, b...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<rvv>) noexcept
{
return select(batch_bool<T, A> { b... }, true_br, false_br, rvv {});
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_scalar.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_scalar.hpp
index 1cde15ffe1..38b9f841df 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_scalar.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_scalar.hpp
@@ -86,6 +86,57 @@ namespace xsimd
using std::tgamma;
using std::trunc;
+ inline signed char abs(signed char v)
+ {
+ return v < 0 ? -v : v;
+ }
+
+ namespace detail
+ {
+ // Use templated type here to prevent automatic instantiation that may
+ // ends up in a warning
+ template <typename char_type>
+ inline char abs(char_type v, std::true_type)
+ {
+ return v;
+ }
+ template <typename char_type>
+ inline char abs(char_type v, std::false_type)
+ {
+ return v < 0 ? -v : v;
+ }
+ }
+
+ inline char abs(char v)
+ {
+ return detail::abs(v, std::is_unsigned<char>::type {});
+ }
+
+ inline short abs(short v)
+ {
+ return v < 0 ? -v : v;
+ }
+ inline unsigned char abs(unsigned char v)
+ {
+ return v;
+ }
+ inline unsigned short abs(unsigned short v)
+ {
+ return v;
+ }
+ inline unsigned int abs(unsigned int v)
+ {
+ return v;
+ }
+ inline unsigned long abs(unsigned long v)
+ {
+ return v;
+ }
+ inline unsigned long long abs(unsigned long long v)
+ {
+ return v;
+ }
+
#ifndef _WIN32
using std::isfinite;
using std::isinf;
@@ -137,7 +188,7 @@ namespace xsimd
#endif
template <class T, class Tp>
- inline auto add(T const& x, Tp const& y) noexcept -> decltype(x + y)
+ inline typename std::common_type<T, Tp>::type add(T const& x, Tp const& y) noexcept
{
return x + y;
}
@@ -209,52 +260,32 @@ namespace xsimd
return x & y;
}
- inline float bitwise_and(float x, float y) noexcept
- {
- uint32_t ix, iy;
- std::memcpy((void*)&ix, (void*)&x, sizeof(float));
- std::memcpy((void*)&iy, (void*)&y, sizeof(float));
- uint32_t ir = bitwise_and(ix, iy);
- float r;
- std::memcpy((void*)&r, (void*)&ir, sizeof(float));
- return r;
- }
-
- inline double bitwise_and(double x, double y) noexcept
+ template <class T_out, class T_in>
+ inline T_out bitwise_cast(T_in x) noexcept
{
- uint64_t ix, iy;
- std::memcpy((void*)&ix, (void*)&x, sizeof(double));
- std::memcpy((void*)&iy, (void*)&y, sizeof(double));
- uint64_t ir = bitwise_and(ix, iy);
- double r;
- std::memcpy((void*)&r, (void*)&ir, sizeof(double));
+ static_assert(sizeof(T_in) == sizeof(T_out), "bitwise_cast between types of the same size");
+ T_out r;
+ std::memcpy((void*)&r, (void*)&x, sizeof(T_in));
return r;
}
- template <class T>
- inline typename std::enable_if<std::is_integral<T>::value, T>::type
- bitwise_andnot(T x, T y) noexcept
- {
- return x & ~y;
- }
-
- inline float bitwise_andnot(float x, float y) noexcept
+ inline float bitwise_and(float x, float y) noexcept
{
uint32_t ix, iy;
std::memcpy((void*)&ix, (void*)&x, sizeof(float));
std::memcpy((void*)&iy, (void*)&y, sizeof(float));
- uint32_t ir = bitwise_andnot(ix, iy);
+ uint32_t ir = bitwise_and(ix, iy);
float r;
std::memcpy((void*)&r, (void*)&ir, sizeof(float));
return r;
}
- inline double bitwise_andnot(double x, double y) noexcept
+ inline double bitwise_and(double x, double y) noexcept
{
uint64_t ix, iy;
std::memcpy((void*)&ix, (void*)&x, sizeof(double));
std::memcpy((void*)&iy, (void*)&y, sizeof(double));
- uint64_t ir = bitwise_andnot(ix, iy);
+ uint64_t ir = bitwise_and(ix, iy);
double r;
std::memcpy((void*)&r, (void*)&ir, sizeof(double));
return r;
@@ -281,6 +312,11 @@ namespace xsimd
return ~x;
}
+ inline bool bitwise_not(bool x) noexcept
+ {
+ return !x;
+ }
+
inline float bitwise_not(float x) noexcept
{
uint32_t ix;
@@ -302,6 +338,12 @@ namespace xsimd
}
template <class T>
+ inline typename std::enable_if<std::is_scalar<T>::value, T>::type bitwise_andnot(T x, T y) noexcept
+ {
+ return bitwise_and(x, bitwise_not(y));
+ }
+
+ template <class T>
inline typename std::enable_if<std::is_integral<T>::value, T>::type
bitwise_or(T x, T y) noexcept
{
@@ -360,7 +402,7 @@ namespace xsimd
}
template <class T, class Tp>
- inline auto div(T const& x, Tp const& y) noexcept -> decltype(x / y)
+ inline typename std::common_type<T, Tp>::type div(T const& x, Tp const& y) noexcept
{
return x / y;
}
@@ -372,13 +414,13 @@ namespace xsimd
}
template <class T, class Tp>
- inline auto mul(T const& x, Tp const& y) noexcept -> decltype(x * y)
+ inline typename std::common_type<T, Tp>::type mul(T const& x, Tp const& y) noexcept
{
return x * y;
}
template <class T>
- inline auto neg(T const& x) noexcept -> decltype(-x)
+ inline T neg(T const& x) noexcept
{
return -x;
}
@@ -776,9 +818,9 @@ namespace xsimd
}
template <class T, class = typename std::enable_if<std::is_scalar<T>::value>::type>
- inline bool bitofsign(T const& x) noexcept
+ inline T bitofsign(T const& x) noexcept
{
- return x < T(0);
+ return T(x < T(0));
}
template <class T>
@@ -842,7 +884,7 @@ namespace xsimd
}
template <class T, class Tp>
- inline auto sub(T const& x, Tp const& y) noexcept -> decltype(x - y)
+ inline typename std::common_type<T, Tp>::type sub(T const& x, Tp const& y) noexcept
{
return x - y;
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_sse2.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_sse2.hpp
index d39cc201f9..d733a8c362 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_sse2.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_sse2.hpp
@@ -20,13 +20,13 @@
namespace xsimd
{
- template <class batch_type, bool... Values>
+ template <typename T, class A, bool... Values>
struct batch_bool_constant;
template <class T_out, class T_in, class A>
inline batch<T_out, A> bitwise_cast(batch<T_in, A> const& x) noexcept;
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant;
namespace kernel
@@ -59,7 +59,7 @@ namespace xsimd
template <class A, class T, size_t I>
inline batch<T, A> insert(batch<T, A> const& self, T val, index<I>, requires_arch<generic>) noexcept;
template <class A, typename T, typename ITy, ITy... Indices>
- inline batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<batch<ITy, A>, Indices...>, requires_arch<generic>) noexcept;
+ inline batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<ITy, A, Indices...>, requires_arch<generic>) noexcept;
template <class A, class T>
inline batch<T, A> avg(batch<T, A> const&, batch<T, A> const&, requires_arch<generic>) noexcept;
template <class A, class T>
@@ -1216,6 +1216,43 @@ namespace xsimd
return _mm_cvtss_f32(tmp1);
}
+ template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
+ inline T reduce_add(batch<T, A> const& self, requires_arch<sse2>) noexcept
+ {
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
+ {
+ __m128i tmp1 = _mm_shuffle_epi32(self, 0x0E);
+ __m128i tmp2 = _mm_add_epi32(self, tmp1);
+ __m128i tmp3 = _mm_shuffle_epi32(tmp2, 0x01);
+ __m128i tmp4 = _mm_add_epi32(tmp2, tmp3);
+ return _mm_cvtsi128_si32(tmp4);
+ }
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
+ {
+ __m128i tmp1 = _mm_shuffle_epi32(self, 0x0E);
+ __m128i tmp2 = _mm_add_epi64(self, tmp1);
+#if defined(__x86_64__)
+ return _mm_cvtsi128_si64(tmp2);
+#else
+ __m128i m;
+ _mm_storel_epi64(&m, tmp2);
+ int64_t i;
+ std::memcpy(&i, &m, sizeof(i));
+ return i;
+#endif
+ }
+ else
+ {
+ return hadd(self, generic {});
+ }
+ }
+
+ template <class A>
+ inline double reduce_add(batch<double, A> const& self, requires_arch<sse2>) noexcept
+ {
+ return _mm_cvtsd_f64(_mm_add_sd(self, _mm_unpackhi_pd(self, self)));
+ }
+
// reduce_max
template <class A, class T, class _ = typename std::enable_if<(sizeof(T) <= 2), void>::type>
inline T reduce_max(batch<T, A> const& self, requires_arch<sse2>) noexcept
@@ -1260,42 +1297,6 @@ namespace xsimd
return acc3.get(0);
}
- template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
- inline T reduce_add(batch<T, A> const& self, requires_arch<sse2>) noexcept
- {
- XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
- {
- __m128i tmp1 = _mm_shuffle_epi32(self, 0x0E);
- __m128i tmp2 = _mm_add_epi32(self, tmp1);
- __m128i tmp3 = _mm_shuffle_epi32(tmp2, 0x01);
- __m128i tmp4 = _mm_add_epi32(tmp2, tmp3);
- return _mm_cvtsi128_si32(tmp4);
- }
- else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
- {
- __m128i tmp1 = _mm_shuffle_epi32(self, 0x0E);
- __m128i tmp2 = _mm_add_epi64(self, tmp1);
-#if defined(__x86_64__)
- return _mm_cvtsi128_si64(tmp2);
-#else
- __m128i m;
- _mm_storel_epi64(&m, tmp2);
- int64_t i;
- std::memcpy(&i, &m, sizeof(i));
- return i;
-#endif
- }
- else
- {
- return hadd(self, generic {});
- }
- }
- template <class A>
- inline double reduce_add(batch<double, A> const& self, requires_arch<sse2>) noexcept
- {
- return _mm_cvtsd_f64(_mm_add_sd(self, _mm_unpackhi_pd(self, self)));
- }
-
// rsqrt
template <class A>
inline batch<float, A> rsqrt(batch<float, A> const& val, requires_arch<sse2>) noexcept
@@ -1321,7 +1322,7 @@ namespace xsimd
return _mm_or_si128(_mm_and_si128(cond, true_br), _mm_andnot_si128(cond, false_br));
}
template <class A, class T, bool... Values, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<sse2>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<sse2>) noexcept
{
return select(batch_bool<T, A> { Values... }, true_br, false_br, sse2 {});
}
@@ -1333,7 +1334,7 @@ namespace xsimd
// shuffle
template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3>
- inline batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<batch<ITy, A>, I0, I1, I2, I3> mask, requires_arch<sse2>) noexcept
+ inline batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<ITy, A, I0, I1, I2, I3> mask, requires_arch<sse2>) noexcept
{
constexpr uint32_t smask = detail::mod_shuffle(I0, I1, I2, I3);
// shuffle within lane
@@ -1347,7 +1348,7 @@ namespace xsimd
}
template <class A, class ITy, ITy I0, ITy I1>
- inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<batch<ITy, A>, I0, I1> mask, requires_arch<sse2>) noexcept
+ inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<ITy, A, I0, I1> mask, requires_arch<sse2>) noexcept
{
constexpr uint32_t smask = detail::mod_shuffle(I0, I1);
// shuffle within lane
@@ -1600,41 +1601,41 @@ namespace xsimd
// swizzle
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
- inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3>, requires_arch<sse2>) noexcept
+ inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<sse2>) noexcept
{
constexpr uint32_t index = detail::shuffle(V0, V1, V2, V3);
return _mm_shuffle_ps(self, self, index);
}
template <class A, uint64_t V0, uint64_t V1>
- inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1>, requires_arch<sse2>) noexcept
+ inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<sse2>) noexcept
{
constexpr uint32_t index = detail::shuffle(V0, V1);
return _mm_shuffle_pd(self, self, index);
}
template <class A, uint64_t V0, uint64_t V1>
- inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1>, requires_arch<sse2>) noexcept
+ inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<sse2>) noexcept
{
constexpr uint32_t index = detail::shuffle(2 * V0, 2 * V0 + 1, 2 * V1, 2 * V1 + 1);
return _mm_shuffle_epi32(self, index);
}
template <class A, uint64_t V0, uint64_t V1>
- inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1> mask, requires_arch<sse2>) noexcept
+ inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<uint64_t, A, V0, V1> mask, requires_arch<sse2>) noexcept
{
return bitwise_cast<int64_t>(swizzle(bitwise_cast<uint64_t>(self), mask, sse2 {}));
}
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
- inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3>, requires_arch<sse2>) noexcept
+ inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<sse2>) noexcept
{
constexpr uint32_t index = detail::shuffle(V0, V1, V2, V3);
return _mm_shuffle_epi32(self, index);
}
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
- inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3> mask, requires_arch<sse2>) noexcept
+ inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3> mask, requires_arch<sse2>) noexcept
{
return bitwise_cast<int32_t>(swizzle(bitwise_cast<uint32_t>(self), mask, sse2 {}));
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_sse4_1.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_sse4_1.hpp
index 165a191e42..18cfe38cef 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_sse4_1.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_sse4_1.hpp
@@ -284,9 +284,9 @@ namespace xsimd
}
template <class A, class T, bool... Values, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<sse4_1>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<sse4_1>) noexcept
{
- constexpr int mask = batch_bool_constant<batch<T, A>, Values...>::mask();
+ constexpr int mask = batch_bool_constant<T, A, Values...>::mask();
XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
{
return _mm_blend_epi16(false_br, true_br, mask);
@@ -304,19 +304,19 @@ namespace xsimd
}
else
{
- return select(batch_bool_constant<batch<T, A>, Values...>(), true_br, false_br, ssse3 {});
+ return select(batch_bool_constant<T, A, Values...>(), true_br, false_br, ssse3 {});
}
}
template <class A, bool... Values>
- inline batch<float, A> select(batch_bool_constant<batch<float, A>, Values...> const&, batch<float, A> const& true_br, batch<float, A> const& false_br, requires_arch<sse4_1>) noexcept
+ inline batch<float, A> select(batch_bool_constant<float, A, Values...> const&, batch<float, A> const& true_br, batch<float, A> const& false_br, requires_arch<sse4_1>) noexcept
{
- constexpr int mask = batch_bool_constant<batch<float, A>, Values...>::mask();
+ constexpr int mask = batch_bool_constant<float, A, Values...>::mask();
return _mm_blend_ps(false_br, true_br, mask);
}
template <class A, bool... Values>
- inline batch<double, A> select(batch_bool_constant<batch<double, A>, Values...> const&, batch<double, A> const& true_br, batch<double, A> const& false_br, requires_arch<sse4_1>) noexcept
+ inline batch<double, A> select(batch_bool_constant<double, A, Values...> const&, batch<double, A> const& true_br, batch<double, A> const& false_br, requires_arch<sse4_1>) noexcept
{
- constexpr int mask = batch_bool_constant<batch<double, A>, Values...>::mask();
+ constexpr int mask = batch_bool_constant<double, A, Values...>::mask();
return _mm_blend_pd(false_br, true_br, mask);
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_ssse3.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_ssse3.hpp
index b6ea119213..d4c0b171cb 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_ssse3.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_ssse3.hpp
@@ -140,32 +140,32 @@ namespace xsimd
// swizzle (constant mask)
template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
- inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<ssse3>) noexcept
+ inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<ssse3>) noexcept
{
- constexpr batch_constant<batch<uint8_t, A>, 2 * V0, 2 * V0 + 1, 2 * V1, 2 * V1 + 1, 2 * V2, 2 * V2 + 1, 2 * V3, 2 * V3 + 1,
+ constexpr batch_constant<uint8_t, A, 2 * V0, 2 * V0 + 1, 2 * V1, 2 * V1 + 1, 2 * V2, 2 * V2 + 1, 2 * V3, 2 * V3 + 1,
2 * V4, 2 * V4 + 1, 2 * V5, 2 * V5 + 1, 2 * V6, 2 * V6 + 1, 2 * V7, 2 * V7 + 1>
mask8;
- return _mm_shuffle_epi8(self, (batch<uint8_t, A>)mask8);
+ return _mm_shuffle_epi8(self, mask8.as_batch());
}
template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
- inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<ssse3>) noexcept
+ inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<ssse3>) noexcept
{
return bitwise_cast<int16_t>(swizzle(bitwise_cast<uint16_t>(self), mask, ssse3 {}));
}
template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
- inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
+ inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
{
- return swizzle(self, (batch<uint8_t, A>)mask, ssse3 {});
+ return swizzle(self, mask.as_batch(), ssse3 {});
}
template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
- inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
+ inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
{
- return swizzle(self, (batch<uint8_t, A>)mask, ssse3 {});
+ return swizzle(self, mask.as_batch(), ssse3 {});
}
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_sve.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_sve.hpp
index 3177c97b28..553f026cc3 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_sve.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_sve.hpp
@@ -20,7 +20,7 @@
namespace xsimd
{
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant;
namespace kernel
@@ -739,19 +739,19 @@ namespace xsimd
// swizzle (static)
template <class A, class T, class I, I... idx>
- inline batch<T, A> swizzle(batch<T, A> const& arg, batch_constant<batch<I, A>, idx...> indices, requires_arch<sve>) noexcept
+ inline batch<T, A> swizzle(batch<T, A> const& arg, batch_constant<I, A, idx...> indices, requires_arch<sve>) noexcept
{
static_assert(batch<T, A>::size == sizeof...(idx), "invalid swizzle indices");
- return swizzle(arg, (batch<I, A>)indices, sve {});
+ return swizzle(arg, indices.as_batch(), sve {});
}
template <class A, class T, class I, I... idx>
inline batch<std::complex<T>, A> swizzle(batch<std::complex<T>, A> const& arg,
- batch_constant<batch<I, A>, idx...> indices,
+ batch_constant<I, A, idx...> indices,
requires_arch<sve>) noexcept
{
static_assert(batch<std::complex<T>, A>::size == sizeof...(idx), "invalid swizzle indices");
- return swizzle(arg, (batch<I, A>)indices, sve {});
+ return swizzle(arg, indices.as_batch(), sve {});
}
/*************
@@ -811,7 +811,7 @@ namespace xsimd
}
template <class A, class T, bool... b>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, b...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<sve>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, b...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<sve>) noexcept
{
return select(batch_bool<T, A> { b... }, true_br, false_br, sve {});
}
diff --git a/third_party/xsimd/include/xsimd/arch/xsimd_wasm.hpp b/third_party/xsimd/include/xsimd/arch/xsimd_wasm.hpp
index ab9acdc8c3..050b1a08fc 100644
--- a/third_party/xsimd/include/xsimd/arch/xsimd_wasm.hpp
+++ b/third_party/xsimd/include/xsimd/arch/xsimd_wasm.hpp
@@ -19,13 +19,13 @@
namespace xsimd
{
- template <class batch_type, bool... Values>
+ template <typename T, class A, bool... Values>
struct batch_bool_constant;
template <class T_out, class T_in, class A>
inline batch<T_out, A> bitwise_cast(batch<T_in, A> const& x) noexcept;
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant;
namespace kernel
@@ -36,7 +36,7 @@ namespace xsimd
template <class A, class T, size_t I>
inline batch<T, A> insert(batch<T, A> const& self, T val, index<I>, requires_arch<generic>) noexcept;
template <class A, typename T, typename ITy, ITy... Indices>
- inline batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<batch<ITy, A>, Indices...>, requires_arch<generic>) noexcept;
+ inline batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<ITy, A, Indices...>, requires_arch<generic>) noexcept;
template <class A, class T>
inline batch<T, A> avg(batch<T, A> const&, batch<T, A> const&, requires_arch<generic>) noexcept;
@@ -1275,7 +1275,7 @@ namespace xsimd
return wasm_v128_or(wasm_v128_and(cond, true_br), wasm_v128_andnot(false_br, cond));
}
template <class A, class T, bool... Values, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<wasm>) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<wasm>) noexcept
{
return select(batch_bool<T, A> { Values... }, true_br, false_br, wasm {});
}
@@ -1287,13 +1287,13 @@ namespace xsimd
// shuffle
template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3>
- inline batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<batch<ITy, A>, I0, I1, I2, I3>, requires_arch<wasm>) noexcept
+ inline batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<ITy, A, I0, I1, I2, I3>, requires_arch<wasm>) noexcept
{
return wasm_i32x4_shuffle(x, y, I0, I1, I2, I3);
}
template <class A, class ITy, ITy I0, ITy I1>
- inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<batch<ITy, A>, I0, I1>, requires_arch<wasm>) noexcept
+ inline batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<ITy, A, I0, I1>, requires_arch<wasm>) noexcept
{
return wasm_i64x2_shuffle(x, y, I0, I1);
}
@@ -1515,63 +1515,63 @@ namespace xsimd
// swizzle
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
- inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3>, requires_arch<wasm>) noexcept
+ inline batch<float, A> swizzle(batch<float, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<wasm>) noexcept
{
return wasm_i32x4_shuffle(self, self, V0, V1, V2, V3);
}
template <class A, uint64_t V0, uint64_t V1>
- inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1>, requires_arch<wasm>) noexcept
+ inline batch<double, A> swizzle(batch<double, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<wasm>) noexcept
{
return wasm_i64x2_shuffle(self, self, V0, V1);
}
template <class A, uint64_t V0, uint64_t V1>
- inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1>, requires_arch<wasm>) noexcept
+ inline batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<wasm>) noexcept
{
return wasm_i64x2_shuffle(self, self, V0, V1);
}
template <class A, uint64_t V0, uint64_t V1>
- inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<batch<uint64_t, A>, V0, V1> mask, requires_arch<wasm>) noexcept
+ inline batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<uint64_t, A, V0, V1> mask, requires_arch<wasm>) noexcept
{
return bitwise_cast<int64_t>(swizzle(bitwise_cast<uint64_t>(self), mask, wasm {}));
}
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
- inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3>, requires_arch<wasm>) noexcept
+ inline batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<wasm>) noexcept
{
return wasm_i32x4_shuffle(self, self, V0, V1, V2, V3);
}
template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
- inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<batch<uint32_t, A>, V0, V1, V2, V3> mask, requires_arch<wasm>) noexcept
+ inline batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3> mask, requires_arch<wasm>) noexcept
{
return bitwise_cast<int32_t>(swizzle(bitwise_cast<uint32_t>(self), mask, wasm {}));
}
template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
- inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<wasm>) noexcept
+ inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<wasm>) noexcept
{
return wasm_i16x8_shuffle(self, self, V0, V1, V2, V3, V4, V5, V6, V7);
}
template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
- inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<wasm>) noexcept
+ inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<wasm>) noexcept
{
return bitwise_cast<int16_t>(swizzle(bitwise_cast<uint16_t>(self), mask, wasm {}));
}
template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
- inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15>, requires_arch<wasm>) noexcept
+ inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15>, requires_arch<wasm>) noexcept
{
return wasm_i8x16_shuffle(self, self, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15);
}
template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
- inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<wasm>) noexcept
+ inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<wasm>) noexcept
{
return bitwise_cast<int8_t>(swizzle(bitwise_cast<uint8_t>(self), mask, wasm {}));
}
diff --git a/third_party/xsimd/include/xsimd/types/xsimd_all_registers.hpp b/third_party/xsimd/include/xsimd/types/xsimd_all_registers.hpp
index 6537157bc6..6d024a1677 100644
--- a/third_party/xsimd/include/xsimd/types/xsimd_all_registers.hpp
+++ b/third_party/xsimd/include/xsimd/types/xsimd_all_registers.hpp
@@ -46,3 +46,7 @@
#include "xsimd_rvv_register.hpp"
#include "xsimd_wasm_register.hpp"
+
+#if XSIMD_WITH_EMULATED
+#include "xsimd_emulated_register.hpp"
+#endif
diff --git a/third_party/xsimd/include/xsimd/types/xsimd_api.hpp b/third_party/xsimd/include/xsimd/types/xsimd_api.hpp
index 751e31d33a..138c9642d0 100644
--- a/third_party/xsimd/include/xsimd/types/xsimd_api.hpp
+++ b/third_party/xsimd/include/xsimd/types/xsimd_api.hpp
@@ -2031,7 +2031,7 @@ namespace xsimd
* @return the result of the selection.
*/
template <class T, class A, bool... Values>
- inline batch<T, A> select(batch_bool_constant<batch<T, A>, Values...> const& cond, batch<T, A> const& true_br, batch<T, A> const& false_br) noexcept
+ inline batch<T, A> select(batch_bool_constant<T, A, Values...> const& cond, batch<T, A> const& true_br, batch<T, A> const& false_br) noexcept
{
detail::static_check_supported_config<T, A>();
return kernel::select<A>(cond, true_br, false_br, A {});
@@ -2047,7 +2047,7 @@ namespace xsimd
* element of \c x and \c y. Each element of the mask index the vector that
* would be formed by the concatenation of \c x and \c y. For instance
* \code{.cpp}
- * batch_constant<batch<uint32_t, sse2>, 0, 4, 3, 7>
+ * batch_constant<uint32_t, sse2, 0, 4, 3, 7>
* \endcode
* Picks \c x[0], \c y[0], \c x[3], \c y[3]
*
@@ -2055,7 +2055,7 @@ namespace xsimd
*/
template <class T, class A, class Vt, Vt... Values>
inline typename std::enable_if<std::is_arithmetic<T>::value, batch<T, A>>::type
- shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<batch<Vt, A>, Values...> mask) noexcept
+ shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<Vt, A, Values...> mask) noexcept
{
static_assert(sizeof(T) == sizeof(Vt), "consistent mask");
detail::static_check_supported_config<T, A>();
@@ -2210,19 +2210,22 @@ namespace xsimd
template <class To, class A = default_arch, class From>
inline void store_as(To* dst, batch<From, A> const& src, aligned_mode) noexcept
{
- kernel::store_aligned(dst, src, A {});
+ detail::static_check_supported_config<From, A>();
+ kernel::store_aligned<A>(dst, src, A {});
}
template <class A = default_arch, class From>
inline void store_as(bool* dst, batch_bool<From, A> const& src, aligned_mode) noexcept
{
- kernel::store(src, dst, A {});
+ detail::static_check_supported_config<From, A>();
+ kernel::store<A>(src, dst, A {});
}
template <class To, class A = default_arch, class From>
inline void store_as(std::complex<To>* dst, batch<std::complex<From>, A> const& src, aligned_mode) noexcept
{
- kernel::store_complex_aligned(dst, src, A {});
+ detail::static_check_supported_config<std::complex<From>, A>();
+ kernel::store_complex_aligned<A>(dst, src, A {});
}
#ifdef XSIMD_ENABLE_XTL_COMPLEX
@@ -2244,25 +2247,29 @@ namespace xsimd
template <class To, class A = default_arch, class From>
inline void store_as(To* dst, batch<From, A> const& src, unaligned_mode) noexcept
{
- kernel::store_unaligned(dst, src, A {});
+ detail::static_check_supported_config<From, A>();
+ kernel::store_unaligned<A>(dst, src, A {});
}
template <class A = default_arch, class From>
inline void store_as(bool* dst, batch_bool<From, A> const& src, unaligned_mode) noexcept
{
- kernel::store(src, dst, A {});
+ detail::static_check_supported_config<From, A>();
+ kernel::store<A>(src, dst, A {});
}
template <class To, class A = default_arch, class From>
inline void store_as(std::complex<To>* dst, batch<std::complex<From>, A> const& src, unaligned_mode) noexcept
{
- kernel::store_complex_unaligned(dst, src, A {});
+ detail::static_check_supported_config<std::complex<From>, A>();
+ kernel::store_complex_unaligned<A>(dst, src, A {});
}
#ifdef XSIMD_ENABLE_XTL_COMPLEX
template <class To, class A = default_arch, class From, bool i3ec>
inline void store_as(xtl::xcomplex<To, To, i3ec>* dst, batch<std::complex<From>, A> const& src, unaligned_mode) noexcept
{
+ detail::static_check_supported_config<std::complex<From>, A>();
store_as(reinterpret_cast<std::complex<To>*>(dst), src, unaligned_mode());
}
#endif
@@ -2350,14 +2357,14 @@ namespace xsimd
*/
template <class T, class A, class Vt, Vt... Values>
inline typename std::enable_if<std::is_arithmetic<T>::value, batch<T, A>>::type
- swizzle(batch<T, A> const& x, batch_constant<batch<Vt, A>, Values...> mask) noexcept
+ swizzle(batch<T, A> const& x, batch_constant<Vt, A, Values...> mask) noexcept
{
static_assert(sizeof(T) == sizeof(Vt), "consistent mask");
detail::static_check_supported_config<T, A>();
return kernel::swizzle<A>(x, mask, A {});
}
template <class T, class A, class Vt, Vt... Values>
- inline batch<std::complex<T>, A> swizzle(batch<std::complex<T>, A> const& x, batch_constant<batch<Vt, A>, Values...> mask) noexcept
+ inline batch<std::complex<T>, A> swizzle(batch<std::complex<T>, A> const& x, batch_constant<Vt, A, Values...> mask) noexcept
{
static_assert(sizeof(T) == sizeof(Vt), "consistent mask");
detail::static_check_supported_config<T, A>();
diff --git a/third_party/xsimd/include/xsimd/types/xsimd_batch_constant.hpp b/third_party/xsimd/include/xsimd/types/xsimd_batch_constant.hpp
index 0de9c8ad42..cb28220441 100644
--- a/third_party/xsimd/include/xsimd/types/xsimd_batch_constant.hpp
+++ b/third_party/xsimd/include/xsimd/types/xsimd_batch_constant.hpp
@@ -25,17 +25,24 @@ namespace xsimd
* @tparam batch_type the type of the associated batch values.
* @tparam Values boolean constant represented by this batch
**/
- template <class batch_type, bool... Values>
+ template <typename T, class A, bool... Values>
struct batch_bool_constant
{
-
- public:
+ using batch_type = batch_bool<T, A>;
static constexpr std::size_t size = sizeof...(Values);
- using arch_type = typename batch_type::arch_type;
using value_type = bool;
static_assert(sizeof...(Values) == batch_type::size, "consistent batch size");
- constexpr operator batch_bool<typename batch_type::value_type, arch_type>() const noexcept { return { Values... }; }
+ public:
+ /**
+ * @brief Generate a batch of @p batch_type from this @p batch_bool_constant
+ */
+ constexpr batch_type as_batch_bool() const noexcept { return { Values... }; }
+
+ /**
+ * @brief Generate a batch of @p batch_type from this @p batch_bool_constant
+ */
+ constexpr operator batch_type() const noexcept { return as_batch_bool(); }
constexpr bool get(size_t i) const noexcept
{
@@ -70,14 +77,14 @@ namespace xsimd
};
template <class F, class SelfPack, class OtherPack, size_t... Indices>
- static constexpr batch_bool_constant<batch_type, F()(std::tuple_element<Indices, SelfPack>::type::value, std::tuple_element<Indices, OtherPack>::type::value)...>
+ static constexpr batch_bool_constant<T, A, F()(std::tuple_element<Indices, SelfPack>::type::value, std::tuple_element<Indices, OtherPack>::type::value)...>
apply(detail::index_sequence<Indices...>)
{
return {};
}
template <class F, bool... OtherValues>
- static constexpr auto apply(batch_bool_constant<batch_type, Values...>, batch_bool_constant<batch_type, OtherValues...>)
+ static constexpr auto apply(batch_bool_constant<T, A, Values...>, batch_bool_constant<T, A, OtherValues...>)
-> decltype(apply<F, std::tuple<std::integral_constant<bool, Values>...>, std::tuple<std::integral_constant<bool, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>()))
{
static_assert(sizeof...(Values) == sizeof...(OtherValues), "compatible constant batches");
@@ -85,12 +92,12 @@ namespace xsimd
}
public:
-#define MAKE_BINARY_OP(OP, NAME) \
- template <bool... OtherValues> \
- constexpr auto operator OP(batch_bool_constant<batch_type, OtherValues...> other) const \
- -> decltype(apply<NAME>(*this, other)) \
- { \
- return apply<NAME>(*this, other); \
+#define MAKE_BINARY_OP(OP, NAME) \
+ template <bool... OtherValues> \
+ constexpr auto operator OP(batch_bool_constant<T, A, OtherValues...> other) const \
+ -> decltype(apply<NAME>(*this, other)) \
+ { \
+ return apply<NAME>(*this, other); \
}
MAKE_BINARY_OP(|, logical_or)
@@ -101,12 +108,12 @@ namespace xsimd
#undef MAKE_BINARY_OP
- constexpr batch_bool_constant<batch_type, !Values...> operator!() const
+ constexpr batch_bool_constant<T, A, !Values...> operator!() const
{
return {};
}
- constexpr batch_bool_constant<batch_type, !Values...> operator~() const
+ constexpr batch_bool_constant<T, A, !Values...> operator~() const
{
return {};
}
@@ -120,88 +127,93 @@ namespace xsimd
* @tparam batch_type the type of the associated batch values.
* @tparam Values constants represented by this batch
**/
- template <class batch_type, typename batch_type::value_type... Values>
+ template <typename T, class A, T... Values>
struct batch_constant
{
static constexpr std::size_t size = sizeof...(Values);
- using arch_type = typename batch_type::arch_type;
+ using batch_type = batch<T, A>;
using value_type = typename batch_type::value_type;
static_assert(sizeof...(Values) == batch_type::size, "consistent batch size");
/**
* @brief Generate a batch of @p batch_type from this @p batch_constant
*/
- inline operator batch_type() const noexcept { return { Values... }; }
+ inline batch_type as_batch() const noexcept { return { Values... }; }
+
+ /**
+ * @brief Generate a batch of @p batch_type from this @p batch_constant
+ */
+ inline operator batch_type() const noexcept { return as_batch(); }
/**
* @brief Get the @p i th element of this @p batch_constant
*/
- constexpr value_type get(size_t i) const noexcept
+ constexpr T get(size_t i) const noexcept
{
- return get(i, std::array<value_type, size> { Values... });
+ return get(i, std::array<T, size> { Values... });
}
private:
- constexpr value_type get(size_t i, std::array<value_type, size> const& values) const noexcept
+ constexpr T get(size_t i, std::array<T, size> const& values) const noexcept
{
return values[i];
}
struct arithmetic_add
{
- constexpr value_type operator()(value_type x, value_type y) const { return x + y; }
+ constexpr T operator()(T x, T y) const { return x + y; }
};
struct arithmetic_sub
{
- constexpr value_type operator()(value_type x, value_type y) const { return x - y; }
+ constexpr T operator()(T x, T y) const { return x - y; }
};
struct arithmetic_mul
{
- constexpr value_type operator()(value_type x, value_type y) const { return x * y; }
+ constexpr T operator()(T x, T y) const { return x * y; }
};
struct arithmetic_div
{
- constexpr value_type operator()(value_type x, value_type y) const { return x / y; }
+ constexpr T operator()(T x, T y) const { return x / y; }
};
struct arithmetic_mod
{
- constexpr value_type operator()(value_type x, value_type y) const { return x % y; }
+ constexpr T operator()(T x, T y) const { return x % y; }
};
struct binary_and
{
- constexpr value_type operator()(value_type x, value_type y) const { return x & y; }
+ constexpr T operator()(T x, T y) const { return x & y; }
};
struct binary_or
{
- constexpr value_type operator()(value_type x, value_type y) const { return x | y; }
+ constexpr T operator()(T x, T y) const { return x | y; }
};
struct binary_xor
{
- constexpr value_type operator()(value_type x, value_type y) const { return x ^ y; }
+ constexpr T operator()(T x, T y) const { return x ^ y; }
};
template <class F, class SelfPack, class OtherPack, size_t... Indices>
- static constexpr batch_constant<batch_type, F()(std::tuple_element<Indices, SelfPack>::type::value, std::tuple_element<Indices, OtherPack>::type::value)...>
+ static constexpr batch_constant<T, A, F()(std::tuple_element<Indices, SelfPack>::type::value, std::tuple_element<Indices, OtherPack>::type::value)...>
apply(detail::index_sequence<Indices...>)
{
return {};
}
- template <class F, value_type... OtherValues>
- static constexpr auto apply(batch_constant<batch_type, Values...>, batch_constant<batch_type, OtherValues...>)
- -> decltype(apply<F, std::tuple<std::integral_constant<value_type, Values>...>, std::tuple<std::integral_constant<value_type, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>()))
+ template <class F, T... OtherValues>
+ static constexpr auto apply(batch_constant<T, A, Values...>, batch_constant<T, A, OtherValues...>)
+ -> decltype(apply<F, std::tuple<std::integral_constant<T, Values>...>, std::tuple<std::integral_constant<T, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>()))
{
static_assert(sizeof...(Values) == sizeof...(OtherValues), "compatible constant batches");
- return apply<F, std::tuple<std::integral_constant<value_type, Values>...>, std::tuple<std::integral_constant<value_type, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>());
+ return apply<F, std::tuple<std::integral_constant<T, Values>...>, std::tuple<std::integral_constant<T, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>());
}
public:
-#define MAKE_BINARY_OP(OP, NAME) \
- template <value_type... OtherValues> \
- constexpr auto operator OP(batch_constant<batch_type, OtherValues...> other) const \
- -> decltype(apply<NAME>(*this, other)) \
- { \
- return apply<NAME>(*this, other); \
+#define MAKE_BINARY_OP(OP, NAME) \
+ template <T... OtherValues> \
+ constexpr auto operator OP(batch_constant<T, A, OtherValues...> other) const \
+ -> decltype(apply<NAME>(*this, other)) \
+ { \
+ return apply<NAME>(*this, other); \
}
MAKE_BINARY_OP(+, arithmetic_add)
@@ -215,17 +227,17 @@ namespace xsimd
#undef MAKE_BINARY_OP
- constexpr batch_constant<batch_type, (value_type)-Values...> operator-() const
+ constexpr batch_constant<T, A, (T)-Values...> operator-() const
{
return {};
}
- constexpr batch_constant<batch_type, (value_type) + Values...> operator+() const
+ constexpr batch_constant<T, A, (T) + Values...> operator+() const
{
return {};
}
- constexpr batch_constant<batch_type, (value_type)~Values...> operator~() const
+ constexpr batch_constant<T, A, (T)~Values...> operator~() const
{
return {};
}
@@ -233,15 +245,15 @@ namespace xsimd
namespace detail
{
- template <class batch_type, class G, std::size_t... Is>
+ template <typename T, class A, class G, std::size_t... Is>
inline constexpr auto make_batch_constant(detail::index_sequence<Is...>) noexcept
- -> batch_constant<batch_type, (typename batch_type::value_type)G::get(Is, sizeof...(Is))...>
+ -> batch_constant<T, A, (T)G::get(Is, sizeof...(Is))...>
{
return {};
}
- template <class batch_type, class G, std::size_t... Is>
+ template <typename T, class A, class G, std::size_t... Is>
inline constexpr auto make_batch_bool_constant(detail::index_sequence<Is...>) noexcept
- -> batch_bool_constant<batch_type, G::get(Is, sizeof...(Is))...>
+ -> batch_bool_constant<T, A, G::get(Is, sizeof...(Is))...>
{
return {};
}
@@ -268,19 +280,19 @@ namespace xsimd
* };
* @endcode
*/
- template <class batch_type, class G>
- inline constexpr auto make_batch_constant() noexcept -> decltype(detail::make_batch_constant<batch_type, G>(detail::make_index_sequence<batch_type::size>()))
+ template <typename T, class A, class G>
+ inline constexpr auto make_batch_constant() noexcept -> decltype(detail::make_batch_constant<T, A, G>(detail::make_index_sequence<batch<T, A>::size>()))
{
- return detail::make_batch_constant<batch_type, G>(detail::make_index_sequence<batch_type::size>());
+ return detail::make_batch_constant<T, A, G>(detail::make_index_sequence<batch<T, A>::size>());
}
- template <class batch_type, class G>
+ template <typename T, class A, class G>
inline constexpr auto make_batch_bool_constant() noexcept
- -> decltype(detail::make_batch_bool_constant<batch_type, G>(
- detail::make_index_sequence<batch_type::size>()))
+ -> decltype(detail::make_batch_bool_constant<T, A, G>(
+ detail::make_index_sequence<batch<T, A>::size>()))
{
- return detail::make_batch_bool_constant<batch_type, G>(
- detail::make_index_sequence<batch_type::size>());
+ return detail::make_batch_bool_constant<T, A, G>(
+ detail::make_index_sequence<batch<T, A>::size>());
}
} // namespace xsimd
diff --git a/third_party/xsimd/include/xsimd/types/xsimd_emulated_register.hpp b/third_party/xsimd/include/xsimd/types/xsimd_emulated_register.hpp
new file mode 100644
index 0000000000..b05d718143
--- /dev/null
+++ b/third_party/xsimd/include/xsimd/types/xsimd_emulated_register.hpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
+ * Martin Renou *
+ * Copyright (c) QuantStack *
+ * Copyright (c) Serge Guelton *
+ * *
+ * Distributed under the terms of the BSD 3-Clause License. *
+ * *
+ * The full license is in the file LICENSE, distributed with this software. *
+ ****************************************************************************/
+
+#ifndef XSIMD_EMULATED_REGISTER_HPP
+#define XSIMD_EMULATED_REGISTER_HPP
+
+#include "./xsimd_generic_arch.hpp"
+#include "./xsimd_register.hpp"
+
+namespace xsimd
+{
+ /**
+ * @ingroup architectures
+ *
+ * emulated instructions
+ */
+ template <size_t N>
+ struct emulated : generic
+ {
+ static constexpr bool supported() noexcept { return true; }
+ static constexpr bool available() noexcept { return true; }
+ static constexpr bool requires_alignment() noexcept { return false; }
+ static constexpr std::size_t alignment() noexcept { return 8; }
+ static constexpr char const* name() noexcept { return "emulated"; }
+ };
+
+ namespace types
+ {
+ template <size_t N>
+ struct simd_emulated_bool_register
+ {
+ using register_type = std::array<bool, N>;
+ register_type data;
+ simd_emulated_bool_register() = default;
+ simd_emulated_bool_register(register_type r) { data = r; }
+ operator register_type() const noexcept { return data; }
+ };
+ template <typename T, size_t N>
+ struct get_bool_simd_register<T, emulated<N>>
+ {
+ using type = simd_emulated_bool_register<N / (8 * sizeof(T))>;
+ };
+
+ template <typename T, size_t N>
+ struct simd_register<T, emulated<N>>
+ {
+ static_assert(N % (8 * sizeof(T)) == 0, "bit width must be a multiple of scalar width");
+ using register_type = std::array<T, N / (8 * sizeof(T))>;
+ register_type data;
+ inline operator register_type() const noexcept
+ {
+ return data;
+ }
+ };
+ template <typename T, size_t N>
+ struct has_simd_register<T, emulated<N>> : std::is_scalar<T>
+ {
+ };
+ template <typename T, size_t N>
+ struct has_simd_register<std::complex<T>, emulated<N>> : std::true_type
+ {
+ };
+#ifdef XSIMD_ENABLE_XTL_COMPLEX
+ template <typename T, bool i3ec, size_t N>
+ struct has_simd_register<xtl::complex<T, T, i3ec>, emulated<N>> : std::true_type
+ {
+ };
+#endif
+ }
+}
+
+#endif
diff --git a/third_party/xsimd/moz.yaml b/third_party/xsimd/moz.yaml
index 6385b68fa5..b88c749f67 100644
--- a/third_party/xsimd/moz.yaml
+++ b/third_party/xsimd/moz.yaml
@@ -10,8 +10,8 @@ origin:
url: https://github.com/QuantStack/xsimd
- release: 7080469620c2145fbedf4ef8950406066e1ca2d6 (2024-03-17T21:35:00Z).
- revision: 7080469620c2145fbedf4ef8950406066e1ca2d6
+ release: be9dcb5df413a893fb6646fa950eeb4aeac70ffc (2024-04-20T09:35:04Z).
+ revision: be9dcb5df413a893fb6646fa950eeb4aeac70ffc
license: BSD-3-Clause
diff --git a/third_party/zstd/moz.build b/third_party/zstd/moz.build
index 6bcc264981..3f38ca8feb 100644
--- a/third_party/zstd/moz.build
+++ b/third_party/zstd/moz.build
@@ -44,7 +44,6 @@ UNIFIED_SOURCES += [
#]
CFLAGS += [
- '-Wall',
'-Wextra',
'-Wcast-qual',
'-Wcast-align',
diff --git a/third_party/rust/uniffi-example-arithmetic/build.rs b/toolkit/components/uniffi-fixtures/arithmetic/build.rs
index 303ac22d8d..303ac22d8d 100644
--- a/third_party/rust/uniffi-example-arithmetic/build.rs
+++ b/toolkit/components/uniffi-fixtures/arithmetic/build.rs
diff --git a/third_party/rust/uniffi-example-arithmetic/src/arithmetic.udl b/toolkit/components/uniffi-fixtures/arithmetic/src/arithmetic.udl
index 117df4834a..117df4834a 100644
--- a/third_party/rust/uniffi-example-arithmetic/src/arithmetic.udl
+++ b/toolkit/components/uniffi-fixtures/arithmetic/src/arithmetic.udl
diff --git a/third_party/rust/uniffi-example-arithmetic/src/lib.rs b/toolkit/components/uniffi-fixtures/arithmetic/src/lib.rs
index 92ab8c072b..92ab8c072b 100644
--- a/third_party/rust/uniffi-example-arithmetic/src/lib.rs
+++ b/toolkit/components/uniffi-fixtures/arithmetic/src/lib.rs
diff --git a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.kts b/toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.kts
index ef11850ae2..ef11850ae2 100644
--- a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.kts
+++ b/toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.kts
diff --git a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.rb b/toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.rb
index 6669eb279f..6669eb279f 100644
--- a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.rb
+++ b/toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.rb
diff --git a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.swift b/toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.swift
index a8e34680e4..a8e34680e4 100644
--- a/third_party/rust/uniffi-example-arithmetic/tests/bindings/test_arithmetic.swift
+++ b/toolkit/components/uniffi-fixtures/arithmetic/tests/bindings/test_arithmetic.swift
diff --git a/third_party/rust/uniffi-example-arithmetic/tests/test_generated_bindings.rs b/toolkit/components/uniffi-fixtures/arithmetic/tests/test_generated_bindings.rs
index 168e6e1d4c..168e6e1d4c 100644
--- a/third_party/rust/uniffi-example-arithmetic/tests/test_generated_bindings.rs
+++ b/toolkit/components/uniffi-fixtures/arithmetic/tests/test_generated_bindings.rs
diff --git a/third_party/rust/uniffi-example-arithmetic/uniffi.toml b/toolkit/components/uniffi-fixtures/arithmetic/uniffi.toml
index 883231dcaa..883231dcaa 100644
--- a/third_party/rust/uniffi-example-arithmetic/uniffi.toml
+++ b/toolkit/components/uniffi-fixtures/arithmetic/uniffi.toml
diff --git a/third_party/rust/uniffi-example-geometry/build.rs b/toolkit/components/uniffi-fixtures/geometry/build.rs
index 2dd1c96bc3..2dd1c96bc3 100644
--- a/third_party/rust/uniffi-example-geometry/build.rs
+++ b/toolkit/components/uniffi-fixtures/geometry/build.rs
diff --git a/third_party/rust/uniffi-example-geometry/src/geometry.udl b/toolkit/components/uniffi-fixtures/geometry/src/geometry.udl
index af60d429bf..af60d429bf 100644
--- a/third_party/rust/uniffi-example-geometry/src/geometry.udl
+++ b/toolkit/components/uniffi-fixtures/geometry/src/geometry.udl
diff --git a/third_party/rust/uniffi-example-geometry/src/lib.rs b/toolkit/components/uniffi-fixtures/geometry/src/lib.rs
index d710b150bb..d710b150bb 100644
--- a/third_party/rust/uniffi-example-geometry/src/lib.rs
+++ b/toolkit/components/uniffi-fixtures/geometry/src/lib.rs
diff --git a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.kts b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.kts
index 77bb9932ec..77bb9932ec 100644
--- a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.kts
+++ b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.kts
diff --git a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.py b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.py
index fd6772be24..bfb6560626 100644
--- a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.py
+++ b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.py
@@ -1,4 +1,4 @@
-from geometry import *
+from geometry import Line, Point, gradient, intersection
ln1 = Line(start=Point(coord_x=0, coord_y=0), end=Point(coord_x=1, coord_y=2))
ln2 = Line(start=Point(coord_x=1, coord_y=1), end=Point(coord_x=2, coord_y=2))
diff --git a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.rb b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.rb
index 90fdff684e..90fdff684e 100644
--- a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.rb
+++ b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.rb
diff --git a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.swift b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.swift
index 58bd65607f..58bd65607f 100644
--- a/third_party/rust/uniffi-example-geometry/tests/bindings/test_geometry.swift
+++ b/toolkit/components/uniffi-fixtures/geometry/tests/bindings/test_geometry.swift
diff --git a/third_party/rust/uniffi-example-geometry/tests/test_generated_bindings.rs b/toolkit/components/uniffi-fixtures/geometry/tests/test_generated_bindings.rs
index 4638d847c8..4638d847c8 100644
--- a/third_party/rust/uniffi-example-geometry/tests/test_generated_bindings.rs
+++ b/toolkit/components/uniffi-fixtures/geometry/tests/test_generated_bindings.rs
diff --git a/third_party/rust/uniffi-example-rondpoint/build.rs b/toolkit/components/uniffi-fixtures/rondpoint/build.rs
index f830879d09..f830879d09 100644
--- a/third_party/rust/uniffi-example-rondpoint/build.rs
+++ b/toolkit/components/uniffi-fixtures/rondpoint/build.rs
diff --git a/third_party/rust/uniffi-example-rondpoint/src/lib.rs b/toolkit/components/uniffi-fixtures/rondpoint/src/lib.rs
index 3f2233ddaa..3f2233ddaa 100644
--- a/third_party/rust/uniffi-example-rondpoint/src/lib.rs
+++ b/toolkit/components/uniffi-fixtures/rondpoint/src/lib.rs
diff --git a/third_party/rust/uniffi-example-rondpoint/src/rondpoint.udl b/toolkit/components/uniffi-fixtures/rondpoint/src/rondpoint.udl
index 7c8261d74e..7c8261d74e 100644
--- a/third_party/rust/uniffi-example-rondpoint/src/rondpoint.udl
+++ b/toolkit/components/uniffi-fixtures/rondpoint/src/rondpoint.udl
diff --git a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.kts b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.kts
index cc5ddf2a86..cc5ddf2a86 100644
--- a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.kts
+++ b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.kts
diff --git a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.py b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.py
index 0b47c0fa5a..df3e3fab18 100644
--- a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.py
+++ b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.py
@@ -1,18 +1,37 @@
-import sys
import ctypes
-from rondpoint import *
+import sys
-dico = Dictionnaire(un=Enumeration.DEUX, deux=True, petit_nombre=0, gros_nombre=123456789)
+from rondpoint import (
+ Dictionnaire,
+ Enumeration,
+ EnumerationAvecDonnees,
+ Retourneur,
+ Stringifier,
+ copie_carte,
+ copie_dictionnaire,
+ copie_enumeration,
+ copie_enumerations,
+ switcheroo,
+)
+
+dico = Dictionnaire(
+ un=Enumeration.DEUX, deux=True, petit_nombre=0, gros_nombre=123456789
+)
copyDico = copie_dictionnaire(dico)
assert dico == copyDico
assert copie_enumeration(Enumeration.DEUX) == Enumeration.DEUX
-assert copie_enumerations([Enumeration.UN, Enumeration.DEUX]) == [Enumeration.UN, Enumeration.DEUX]
-assert copie_carte({
- "0": EnumerationAvecDonnees.ZERO(),
- "1": EnumerationAvecDonnees.UN(1),
- "2": EnumerationAvecDonnees.DEUX(2, "deux"),
-}) == {
+assert copie_enumerations([Enumeration.UN, Enumeration.DEUX]) == [
+ Enumeration.UN,
+ Enumeration.DEUX,
+]
+assert copie_carte(
+ {
+ "0": EnumerationAvecDonnees.ZERO(),
+ "1": EnumerationAvecDonnees.UN(1),
+ "2": EnumerationAvecDonnees.DEUX(2, "deux"),
+ }
+) == {
"0": EnumerationAvecDonnees.ZERO(),
"1": EnumerationAvecDonnees.UN(1),
"2": EnumerationAvecDonnees.DEUX(2, "deux"),
@@ -30,11 +49,13 @@ assert EnumerationAvecDonnees.UN(1) != EnumerationAvecDonnees.UN(2)
# lowering from rust and lifting into python.
rt = Retourneur()
+
def affirmAllerRetour(vals, identique):
for v in vals:
id_v = identique(v)
assert id_v == v, f"Round-trip failure: {v} => {id_v}"
+
MIN_I8 = -1 * 2**7
MAX_I8 = 2**7 - 1
MIN_I16 = -1 * 2**15
@@ -65,21 +86,29 @@ affirmAllerRetour([0x00000000, 0x12345678, 0xFFFFFFFF], rt.identique_u32)
# Longs
affirmAllerRetour([MIN_I64, -1, 0, 1, MAX_I64], rt.identique_i64)
-affirmAllerRetour([0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], rt.identique_u64)
+affirmAllerRetour(
+ [0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], rt.identique_u64
+)
# Floats
affirmAllerRetour([0.0, 0.5, 0.25, 1.0, F32_ONE_THIRD], rt.identique_float)
# Doubles
affirmAllerRetour(
- [0.0, 0.5, 0.25, 1.0, 1.0 / 3, sys.float_info.max, sys.float_info.min],
- rt.identique_double
+ [0.0, 0.5, 0.25, 1.0, 1.0 / 3, sys.float_info.max, sys.float_info.min],
+ rt.identique_double,
)
# Strings
affirmAllerRetour(
- ["", "abc", "été", "ښي لاس ته لوستلو لوستل", "😻emoji 👨‍👧‍👦multi-emoji, 🇨🇭a flag, a canal, panama"],
- rt.identique_string
+ [
+ "",
+ "abc",
+ "été",
+ "ښي لاس ته لوستلو لوستل",
+ "😻emoji 👨‍👧‍👦multi-emoji, 🇨🇭a flag, a canal, panama",
+ ],
+ rt.identique_string,
)
# Test one way across the FFI.
@@ -97,11 +126,13 @@ affirmAllerRetour(
# together, we've shown the correctness of the return leg.
st = Stringifier()
+
def affirmEnchaine(vals, toString, rustyStringify=lambda v: str(v).lower()):
for v in vals:
str_v = toString(v)
assert rustyStringify(v) == str_v, f"String compare error {v} => {str_v}"
+
# Test the efficacy of the string transport from rust. If this fails, but everything else
# works, then things are very weird.
wellKnown = st.well_known_string("python")
@@ -124,7 +155,10 @@ affirmEnchaine([0x00000000, 0x12345678, 0xFFFFFFFF], st.to_string_u32)
# Longs
affirmEnchaine([MIN_I64, -1, 0, 1, MAX_I64], st.to_string_i64)
-affirmEnchaine([0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], st.to_string_u64)
+affirmEnchaine(
+ [0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], st.to_string_u64
+)
+
# Floats
def rustyFloatToStr(v):
@@ -134,13 +168,16 @@ def rustyFloatToStr(v):
return str(int(v))
return str(v)
+
affirmEnchaine([0.0, 0.5, 0.25, 1.0], st.to_string_float, rustyFloatToStr)
-assert st.to_string_float(F32_ONE_THIRD) == "0.33333334" # annoyingly different string repr
+assert (
+ st.to_string_float(F32_ONE_THIRD) == "0.33333334"
+) # annoyingly different string repr
# Doubles
# TODO: float_info.max/float_info.min don't stringify-roundtrip properly yet, TBD.
affirmEnchaine(
- [0.0, 0.5, 0.25, 1.0, 1.0 / 3],
- st.to_string_double,
- rustyFloatToStr,
+ [0.0, 0.5, 0.25, 1.0, 1.0 / 3],
+ st.to_string_double,
+ rustyFloatToStr,
)
diff --git a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.rb b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.rb
index faa4062019..faa4062019 100644
--- a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.rb
+++ b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.rb
diff --git a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.swift b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift
index d9f47058ed..d9f47058ed 100644
--- a/third_party/rust/uniffi-example-rondpoint/tests/bindings/test_rondpoint.swift
+++ b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift
diff --git a/third_party/rust/uniffi-example-rondpoint/tests/test_generated_bindings.rs b/toolkit/components/uniffi-fixtures/rondpoint/tests/test_generated_bindings.rs
index d337374334..d337374334 100644
--- a/third_party/rust/uniffi-example-rondpoint/tests/test_generated_bindings.rs
+++ b/toolkit/components/uniffi-fixtures/rondpoint/tests/test_generated_bindings.rs
diff --git a/third_party/rust/uniffi-example-sprites/build.rs b/toolkit/components/uniffi-fixtures/sprites/build.rs
index 26ac3085b8..26ac3085b8 100644
--- a/third_party/rust/uniffi-example-sprites/build.rs
+++ b/toolkit/components/uniffi-fixtures/sprites/build.rs
diff --git a/third_party/rust/uniffi-example-sprites/src/lib.rs b/toolkit/components/uniffi-fixtures/sprites/src/lib.rs
index d3cc11e408..d3cc11e408 100644
--- a/third_party/rust/uniffi-example-sprites/src/lib.rs
+++ b/toolkit/components/uniffi-fixtures/sprites/src/lib.rs
diff --git a/third_party/rust/uniffi-example-sprites/src/sprites.udl b/toolkit/components/uniffi-fixtures/sprites/src/sprites.udl
index 6781c6cee5..6781c6cee5 100644
--- a/third_party/rust/uniffi-example-sprites/src/sprites.udl
+++ b/toolkit/components/uniffi-fixtures/sprites/src/sprites.udl
diff --git a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.kts b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.kts
index 42451f28dd..42451f28dd 100644
--- a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.kts
+++ b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.kts
diff --git a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.py b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.py
index d04742e076..1e91997001 100644
--- a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.py
+++ b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.py
@@ -1,4 +1,4 @@
-from sprites import *
+from sprites import Point, Sprite, Vector
sempty = Sprite(None)
assert sempty.get_position() == Point(x=0, y=0)
@@ -14,4 +14,3 @@ assert s.get_position() == Point(x=-3, y=4)
srel = Sprite.new_relative_to(Point(x=0, y=1), Vector(dx=1, dy=1.5))
assert srel.get_position() == Point(x=1, y=2.5)
-
diff --git a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.rb b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.rb
index fa73043979..fa73043979 100644
--- a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.rb
+++ b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.rb
diff --git a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.swift b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.swift
index d5428ac679..d5428ac679 100644
--- a/third_party/rust/uniffi-example-sprites/tests/bindings/test_sprites.swift
+++ b/toolkit/components/uniffi-fixtures/sprites/tests/bindings/test_sprites.swift
diff --git a/third_party/rust/uniffi-example-sprites/tests/test_generated_bindings.rs b/toolkit/components/uniffi-fixtures/sprites/tests/test_generated_bindings.rs
index 00dd779d68..00dd779d68 100644
--- a/third_party/rust/uniffi-example-sprites/tests/test_generated_bindings.rs
+++ b/toolkit/components/uniffi-fixtures/sprites/tests/test_generated_bindings.rs
diff --git a/third_party/rust/uniffi-example-todolist/build.rs b/toolkit/components/uniffi-fixtures/todolist/build.rs
index 2dd2f68b75..2dd2f68b75 100644
--- a/third_party/rust/uniffi-example-todolist/build.rs
+++ b/toolkit/components/uniffi-fixtures/todolist/build.rs
diff --git a/third_party/rust/uniffi-example-todolist/src/lib.rs b/toolkit/components/uniffi-fixtures/todolist/src/lib.rs
index 11cdc63aee..11cdc63aee 100644
--- a/third_party/rust/uniffi-example-todolist/src/lib.rs
+++ b/toolkit/components/uniffi-fixtures/todolist/src/lib.rs
diff --git a/third_party/rust/uniffi-example-todolist/src/todolist.udl b/toolkit/components/uniffi-fixtures/todolist/src/todolist.udl
index 5c923314cd..5c923314cd 100644
--- a/third_party/rust/uniffi-example-todolist/src/todolist.udl
+++ b/toolkit/components/uniffi-fixtures/todolist/src/todolist.udl
diff --git a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.kts b/toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.kts
index bb2b292224..bb2b292224 100644
--- a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.kts
+++ b/toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.kts
diff --git a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.rb b/toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.rb
index fc1a823f52..fc1a823f52 100644
--- a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.rb
+++ b/toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.rb
diff --git a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.swift b/toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.swift
index 6ce72cadb2..6ce72cadb2 100644
--- a/third_party/rust/uniffi-example-todolist/tests/bindings/test_todolist.swift
+++ b/toolkit/components/uniffi-fixtures/todolist/tests/bindings/test_todolist.swift
diff --git a/third_party/rust/uniffi-example-todolist/tests/test_generated_bindings.rs b/toolkit/components/uniffi-fixtures/todolist/tests/test_generated_bindings.rs
index cefdbfe1dc..cefdbfe1dc 100644
--- a/third_party/rust/uniffi-example-todolist/tests/test_generated_bindings.rs
+++ b/toolkit/components/uniffi-fixtures/todolist/tests/test_generated_bindings.rs